Index: /branches/new-random/.cvsignore
===================================================================
--- /branches/new-random/.cvsignore	(revision 13309)
+++ /branches/new-random/.cvsignore	(revision 13309)
@@ -0,0 +1,10 @@
+*\.?fsl
+*CL*
+*cl*
+*boot*
+*fsl
+.gdb*
+*.image
+README*
+*~.*
+*.app
Index: /branches/new-random/bin/.cvsignore
===================================================================
--- /branches/new-random/bin/.cvsignore	(revision 13309)
+++ /branches/new-random/bin/.cvsignore	(revision 13309)
@@ -0,0 +1,3 @@
+*fsl
+
+
Index: /branches/new-random/cocoa-ide/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/.cvsignore	(revision 13309)
@@ -0,0 +1,3 @@
+*~.*
+*fsl
+
Index: /branches/new-random/cocoa-ide/Info.plist-proto
===================================================================
--- /branches/new-random/cocoa-ide/Info.plist-proto	(revision 13309)
+++ /branches/new-random/cocoa-ide/Info.plist-proto	(revision 13309)
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeExtensions</key>
+			<array>
+				<string>lisp</string>
+			</array>
+			<key>CFBundleTypeIconFile</key>
+			<string>openmcl-icon.icns</string>
+			<key>CFBundleTypeName</key>
+			<string>Lisp source code</string>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>LSIsAppleDefaultForType</key>
+			<true/>
+			<key>NSDocumentClass</key>
+			<string>HemlockEditorDocument</string>
+		</dict>
+		<dict>
+			<key>CFBundleTypeIconFile</key>
+			<string>openmcl-icon.icns</string>
+			<key>CFBundleTypeName</key>
+			<string>Listener</string>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>NSDocumentClass</key>
+			<string>HemlockListenerDocument</string>
+		</dict>
+		<dict>
+			<key>CFBundleTypeExtensions</key>
+			<array>
+				<string>txt</string>
+				<string>text</string>
+				<string>*</string>
+			</array>
+			<key>CFBundleTypeName</key>
+			<string>NSStringPboardType</string>
+			<key>CFBundleTypeOSTypes</key>
+			<array>
+				<string>****</string>
+			</array>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>NSDocumentClass</key>
+			<string>HemlockEditorDocument</string>
+		</dict>
+		<dict>
+			<key>CFBundleTypeName</key>
+			<string>html</string>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>NSDocumentClass</key>
+			<string>DisplayDocument</string>
+		</dict>
+	</array>
+	<key>CFBundleExecutable</key>
+	<string>OPENMCL-KERNEL</string>
+	<key>CFBundleHelpBookFolder</key>
+	<string>Help</string>
+	<key>CFBundleHelpBookName</key>
+	<string>OpenMCL Help</string>
+	<key>CFBundleIconFile</key>
+	<string>openmcl-icon.icns</string>
+	<key>CFBundleIdentifier</key>
+	<string>OPENMCL-IDENTIFIER</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>OPENMCL-NAME</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>OMCL</string>
+	<key>CFBundleVersion</key>
+	<string>OPENMCL-VERSION</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>LispApplication</string>
+	<key>UTExportedTypeDeclarations</key>
+	<array>
+		<dict>
+			<key>UTTypeConformsTo</key>
+			<array>
+				<string>public.source-code</string>
+			</array>
+			<key>UTTypeDescription</key>
+			<string>Lisp source file</string>
+			<key>UTTypeIdentifier</key>
+			<string>org.lisp.lisp-source</string>
+			<key>UTTypeReferenceURL</key>
+			<string></string>
+			<key>UTTypeTagSpecification</key>
+			<dict>
+				<key>public.filename-extension</key>
+				<array>
+					<string>lisp</string>
+					<string>lsp</string>
+					<string>cl</string>
+				</array>
+			</dict>
+		</dict>
+	</array>
+	<key>NSAppleScriptEnabled</key>
+	<string>YES</string>
+	<key>CFBundleURLTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleURLSchemes</key>
+			<array>
+				<string>ccl</string>
+			</array>
+		</dict>
+	</array>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/README
===================================================================
--- /branches/new-random/cocoa-ide/README	(revision 13309)
+++ /branches/new-random/cocoa-ide/README	(revision 13309)
@@ -0,0 +1,80 @@
+November 20, 2007
+
+This directory contains sources and other resources needed to build
+a Cocoa-based IDE for Clozure CL on OSX.
+
+The IDE uses the ObjC bridge (in ccl/objc-bridge/) to communicate
+with the ObjC runtime.
+
+The "./ide-contents" directory contains nib files, icons and other
+resources used by the IDE.  These are copied to the application bundle
+by the build process.
+
+The "./hemlock" directory contains a hacked up version of Portable
+Hemlock (forked from the main Portable Hemlock tree some years ago.)
+Hemlock is public domain Emacs-like editor that comes with CMUCL;
+Portable Hemlock is an attempt to "free Hemlock from its CMUCL prison"
+(e.g., remove dependencies on CMUCL).  Hemlock (and Portable Hemlock)
+were designed to use CLX for display and event processing; the version
+distributed here uses the Cocoa text system for that functionality.
+Much of the initial work on Portable Hemlock was done by Gilbert Baumann.
+
+To run the IDE from within a ccl command-line session (a shell, Emacs shell
+buffer, under SLIME or ILisp or ...), do:
+
+? (require "COCOA")
+
+The first time this is run, it'll compile the sources, generating lots
+of compiler warnings.  You'll also see messages noting that various
+new ObjC-callable methods are being defined.  When the loading process
+completes, it creates a temporary application bundle in "ccl:temp
+bundle.app" and activates it.  You should see a new menubar, a
+listener window, and a Clozure CL icon in the Dock. The non-GUI
+listener process from which the REQUIRE was issued will remain active;
+you may see warning/diagnostic/error messages from the IDE directed to
+the standard output/error streams associated with that listener.
+(Under SLIME, these messages might appear in the *inferior lisp*
+buffer.)
+
+It's also possible to save the loaded IDE in a populated bundle,
+effectively making it a double-clickable application.  To do this, you
+can do:
+
+? (require "COCOA-APPLICATION")
+
+which will create an application bundle in "ccl:Clozure CL.app"
+and save an executable lisp image inside it. Double-clicking on
+that bundle in the Finder will launch the IDE; any diagnostic
+messages/warnings/etc. will be written to the system log, which
+can be examined with the Console application.
+
+The IDE depends on functionality introduced in OSX 10.4 (Tiger).
+
+
+
+*Note: CCL directory and IDE Preferences
+
+Normally, the IDE assumes it is located at the top level of the "CCL"
+directory.  It uses the CCL directory to enable Meta-. to find the
+system source files and require'd modules, among other things.  If you
+want to move the IDE somewhere else, e.g. to put it in the
+Applications folder, but still want to be able to Meta-. and require
+stuff from the CCL directory, you can set the "CCL Directory" entry in
+the "Paths" pane of the Preferences dialog to the absolute path of the
+directory containing the system sources.
+
+The values of changed application preferences are stored in
+"~/Library/Preferences/com.clozure.Clozure CL.plist"; if you have
+an old version of this file, it might be desirable to delete it
+before invoking the IDE for the first time.
+
+
+*Note: Interface files
+
+The standalone IDE bundle contains a copy of the FFI/ObjC interface
+definition databases (i.e. the .cdb files) for its target platform in
+Clozure CL.app/Contents/Resources/xxx-headers.  If you create
+additional databases that you want the IDE to access, you can just
+copy them into the bundle.  Conversely, if you'd rather use the
+interface definitions in the CCL directory, just delete the ones in
+the bundle.
Index: /branches/new-random/cocoa-ide/altconsole/AltConsoleDocument.h
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/AltConsoleDocument.h	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/AltConsoleDocument.h	(revision 13309)
@@ -0,0 +1,37 @@
+/*
+   Copyright (C) 2003 Clozure Associates
+   This file is part of OpenMCL.  
+
+   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with OpenMCL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with OpenMCL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   OpenMCL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+
+  $Log: AltConsoleDocument.h,v $
+  Revision 1.2  2003/11/17 07:30:39  gb
+  update copyright/license
+
+  Revision 1.1.1.1  2003/11/17 07:14:42  gb
+  initial checkin
+
+*/
+
+#import <Cocoa/Cocoa.h>
+
+@interface AltConsoleDocument : NSDocument
+{
+  NSFileHandle *in, *out, *err;
+  NSTextView *textView;
+  unsigned outpos;
+  NSDictionary *local_typing_attributes, *system_output_attributes;
+  NSTextField *indicator;
+  NSTimer *watchdog;
+  Boolean peerDied;
+}
+@end
Index: /branches/new-random/cocoa-ide/altconsole/AltConsoleDocument.m
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/AltConsoleDocument.m	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/AltConsoleDocument.m	(revision 13309)
@@ -0,0 +1,240 @@
+/*
+   Copyright (C) 2003 Clozure Associates
+   This file is part of OpenMCL.  
+
+   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with OpenMCL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with OpenMCL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   OpenMCL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+
+  $Log: AltConsoleDocument.m,v $
+  Revision 1.2  2003/11/17 07:30:39  gb
+  update copyright/license
+
+  Revision 1.1.1.1  2003/11/17 07:14:42  gb
+  initial checkin
+
+*/
+
+#import "AltConsoleDocument.h"
+#import "AltConsoleDocumentController.h"
+#include <sys/signal.h>
+
+@implementation AltConsoleDocument
+- (id)init {
+    self = [super init];
+    if (self) {
+      NSMutableDictionary *dict;
+
+      peerDied = NO;
+      in = [[[NSFileHandle alloc] initWithFileDescriptor: 0] retain];
+      out =[[[NSFileHandle alloc] initWithFileDescriptor: 1] retain];
+      err =[[[NSFileHandle alloc] initWithFileDescriptor: 2] retain];
+      dict = [[NSMutableDictionary alloc] initWithCapacity: 3];
+      [dict setObject: [NSFont fontWithName: @"Courier" size:12.0] forKey: @"NSFont"];
+      [dict setObject: [NSParagraphStyle defaultParagraphStyle] forKey: @"NSParagraphStyle"];
+      system_output_attributes = dict;
+      dict = [dict mutableCopy];
+      [dict setObject: [NSFont fontWithName: @"Courier-Bold" size:12.0]
+	    forKey: @"NSFont"];
+      [dict setObject: [NSColor blackColor] forKey: @"NSColor"];
+      local_typing_attributes = dict;
+      outpos = 0;
+    }
+    return self;
+}
+
+- (NSString *)windowNibName {
+    return @"AltConsole";
+}
+
+- (void) peerDied:(NSNotification *)notification {
+  peerDied = YES;
+  [indicator setStringValue:@"Disconnected"];
+  [textView setEditable: NO];
+  if (watchdog) {
+    [watchdog invalidate];
+    watchdog = nil;
+  }
+   [[NSApplication sharedApplication] terminate:nil];
+}
+
+- (void) gotData:(NSNotification *)notification {
+  NSData *data = [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem];
+  if ([data length] != 0) {
+    NSTextStorage *buffer_text = [textView textStorage];
+    NSString *s = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
+    NSAttributedString *str = [[NSAttributedString alloc] initWithString: s attributes: system_output_attributes];
+    int textlen;
+    
+    [buffer_text beginEditing];
+    [buffer_text appendAttributedString: str];
+    [buffer_text endEditing];
+    textlen = [buffer_text length];
+    [textView scrollRangeToVisible: NSMakeRange(textlen, 0)];
+    [str release];
+    [in readInBackgroundAndNotify];
+    [self updateChangeCount: NSChangeDone];
+    outpos = textlen;
+  }
+}
+
+
+- (void) watchPeer: (id) theTimer {
+  pid_t peer = getppid();
+
+  if (kill(peer, 0) < 0) {
+    [[NSNotificationCenter defaultCenter]
+      postNotificationName: @"peerDied" object: nil];
+  }
+}
+
+
+- (void)windowControllerDidLoadNib:(NSWindowController *) aController {
+    [super windowControllerDidLoadNib:aController];
+
+    NSWindow *w = [aController window];
+    NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"altconsole"];
+
+    [toolbar setDelegate:self];
+    [w setToolbar:toolbar];
+    [toolbar release];
+
+    [[NSNotificationCenter defaultCenter]
+     addObserver: self
+     selector: @selector(gotData:)
+     name: NSFileHandleReadCompletionNotification
+     object: in];
+    [[NSNotificationCenter defaultCenter]
+     addObserver: self
+     selector: @selector(peerDied:)
+     name: @"peerDied"
+     object: nil];
+    [in readInBackgroundAndNotify];
+    [textView setDelegate: self];
+    [textView setContinuousSpellCheckingEnabled: NO];
+    [self setFileURL: [NSURL fileURLWithPath: [[AltConsoleDocumentController sharedDocumentController] herald]]];
+    [[AltConsoleDocumentController sharedDocumentController]
+      add_console_document];
+    watchdog = [NSTimer scheduledTimerWithTimeInterval: 1.0
+			target: self
+			selector: @selector(watchPeer:)
+			userInfo: nil
+			repeats: YES];
+    [NSApp activateIgnoringOtherApps: YES];
+}
+
+- (NSData *)dataRepresentationOfType:(NSString *)aType {
+  [[textView string] 
+    dataUsingEncoding: NSASCIIStringEncoding
+    allowLossyConversion: YES];
+}
+
+- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType {
+    return YES;
+}
+
+- (BOOL)textView: tv shouldChangeTextInRange: (NSRange)r replacementString: s {
+  if (peerDied) {
+    return NO;
+  }
+  if (r.location < outpos) {
+    return NO;
+  }
+  [tv setTypingAttributes: local_typing_attributes];
+  return YES;
+}
+
+- (BOOL)textView: tv doCommandBySelector: (SEL) aselector {
+  if (! [self respondsToSelector: aselector]) {
+    return NO;
+  }
+  [self performSelector: aselector withObject: tv];
+  return YES;
+}
+
+- (void) sendString: (NSString *)s {
+  [out writeData: [s dataUsingEncoding: NSASCIIStringEncoding allowLossyConversion: YES]];
+}
+
+- (void) insertNewline:(NSTextView *)tv {
+  if (peerDied) {
+    [tv insertNewline: self];
+  } else {
+    NSTextStorage *textbuf = [tv textStorage];
+    int textlen = [textbuf length];
+    NSString *textstring = [textbuf string];
+    NSRange r = [tv selectedRange];
+    int curpos = r.location, curlen = r.length;
+    
+    if (curpos >= outpos) {
+      curpos += curlen;
+      [tv setSelectedRange: NSMakeRange(curpos, 0)];
+      [tv insertNewline: self];
+      curpos++;
+      textlen++;
+      if (curpos == textlen) {
+	[self sendString: [textstring substringWithRange: NSMakeRange(outpos, textlen-outpos)]];
+	outpos = textlen;
+      }
+    } else if (curlen > 0) {
+      [tv setSelectedRange: NSMakeRange(textlen,0)];
+      [tv insertText: [textstring substringWithRange: r]];
+      [tv scrollRangeToVisible: NSMakeRange([textbuf length],0)];
+    }
+  }
+}
+
+- (void) close {
+  [[NSNotificationCenter defaultCenter] removeObserver: self];
+  [[AltConsoleDocumentController sharedDocumentController]
+    remove_console_document];
+  if (watchdog) {
+    [watchdog invalidate];
+    watchdog = nil;
+  }
+  [super close];
+}
+  
+
+- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
+{
+  [NSArray arrayWithObject:@"clear display"];
+}
+
+- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
+{
+  [NSArray arrayWithObject:@"clear display"];
+}
+
+- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
+{
+  NSToolbarItem *item = [[[NSToolbarItem alloc]
+			   initWithItemIdentifier:itemIdentifier] autorelease];
+
+  if ([itemIdentifier isEqualToString:@"clear display"]) {
+    [item setLabel:@"Clear Display"];
+    [item setImage:[NSImage imageNamed:@"Clear"]];
+    [item setTarget:self];
+    [item setAction:@selector(clearDisplay:)];
+  } else {
+    item = nil;
+  }
+  return item;
+}
+
+- (void)clearDisplay:(id)sender
+{
+  NSTextStorage *storage = [textView textStorage];
+
+  [storage deleteCharactersInRange:NSMakeRange(0, [storage length])];
+  outpos = 0;
+}
+
+@end
Index: /branches/new-random/cocoa-ide/altconsole/AltConsoleDocumentController.h
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/AltConsoleDocumentController.h	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/AltConsoleDocumentController.h	(revision 13309)
@@ -0,0 +1,39 @@
+/*
+   Copyright (C) 2003 Clozure Associates
+   This file is part of OpenMCL.  
+
+   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with OpenMCL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with OpenMCL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   OpenMCL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+
+  $Log: AltConsoleDocumentController.h,v $
+  Revision 1.2  2003/11/17 07:30:39  gb
+  update copyright/license
+
+  Revision 1.1.1.1  2003/11/17 07:14:42  gb
+  initial checkin
+
+*/
+
+
+#import <Cocoa/Cocoa.h>
+
+@interface AltConsoleDocumentController : NSDocumentController {
+  unsigned console_documents;
+  pid_t peer_pid;
+  NSString *peer_name;
+  NSString *peer_herald;
+}
+
+- (NSString *)herald;
+
+- (void) add_console_document;
+- (void) remove_console_document;
+@end
Index: /branches/new-random/cocoa-ide/altconsole/AltConsoleDocumentController.m
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/AltConsoleDocumentController.m	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/AltConsoleDocumentController.m	(revision 13309)
@@ -0,0 +1,72 @@
+/*
+   Copyright (C) 2003 Clozure Associates
+   This file is part of OpenMCL.  
+
+   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with OpenMCL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with OpenMCL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   OpenMCL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+
+  $Log: AltConsoleDocumentController.m,v $
+  Revision 1.2  2003/11/17 07:30:39  gb
+  update copyright/license
+
+  Revision 1.1.1.1  2003/11/17 07:14:42  gb
+  initial checkin
+
+*/
+
+#import "AltConsoleDocumentController.h"
+#include <Carbon/Carbon.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+@implementation AltConsoleDocumentController
+
+- (id) init {
+  self = [super init];
+  if (self) {
+    ProcessSerialNumber psn;
+
+    console_documents = 0;
+    peer_pid = getppid();
+    peer_name = @"Unknown";
+    if (GetProcessForPID(peer_pid, &psn) == 0) {
+      CFStringRef name;
+      if (CopyProcessName(&psn, &name) == 0) {
+        peer_name = [[NSString stringWithString: (NSString *)name] retain];
+      }
+    }
+    peer_herald = [[[NSString stringWithFormat: @"~/%@-%d",peer_name, peer_pid]stringByExpandingTildeInPath] retain];
+  }
+  return self;
+}
+    
+-(BOOL)validateMenuItem:(NSMenuItem *)item {
+ if ([item action] == @selector(newDocument:)) {
+    return (console_documents == 0);
+  }
+  return [super validateMenuItem:item];
+}
+
+- (NSString *)herald {
+  return peer_herald;
+}
+
+- (void) add_console_document {
+  console_documents++;
+}
+
+- (void) remove_console_document {
+  if (console_documents) {
+    --console_documents;
+  }
+}
+
+@end
Index: /branches/new-random/cocoa-ide/altconsole/Info.plist
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/Info.plist	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/Info.plist	(revision 13309)
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeExtensions</key>
+			<array>
+				<string>log</string>
+			</array>
+			<key>CFBundleTypeIconFile</key>
+			<string></string>
+			<key>CFBundleTypeName</key>
+			<string>AltConsoleDocumentType</string>
+			<key>CFBundleTypeOSTypes</key>
+			<array>
+				<string>TEXT</string>
+			</array>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>NSDocumentClass</key>
+			<string>AltConsoleDocument</string>
+		</dict>
+	</array>
+	<key>CFBundleExecutable</key>
+	<string>AltConsole</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+        <key>CFBundleIdentifier</key>
+	<string>com.clozure.AltConsole</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>0.1</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/altconsole/Makefile
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/Makefile	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/Makefile	(revision 13309)
@@ -0,0 +1,35 @@
+#
+# $Log: Makefile,v $
+# Revision 1.1.1.1  2003/11/17 07:14:42  gb
+# initial checkin
+#
+#
+
+
+APPBASE=.
+OBJECTS=main.o AltConsoleDocument.o AltConsoleDocumentController.o
+RESOURCES=resource/MainMenu.nib resource/AltConsole.nib resource/Credits.rtf resource/InfoPlist.strings resource/Clear.tiff
+CC=gcc-4.0
+
+CFLAGS=-g -O -mmacosx-version-min=10.4 -m32 -Wno-protocol
+
+AltConsole: $(OBJECTS)
+	$(CC) $(CFLAGS) -o $@ $(OBJECTS) -framework Cocoa
+
+$(APPBASE)/AltConsole.app: AltConsole $(RESOURCES) Info.plist
+	mkdir -p $(APPBASE)
+	rm -rf $(APPBASE)/AltConsole.app
+	mkdir -p $(APPBASE)/AltConsole.app/Contents/Resources/English.lproj
+	cp -r -p $(RESOURCES) $(APPBASE)/AltConsole.app/Contents/Resources/English.lproj
+	mkdir -p $(APPBASE)/AltConsole.app/Contents/MacOS
+	cp -p AltConsole $(APPBASE)/AltConsole.app/Contents/MacOS
+	cp -p Info.plist $(APPBASE)/AltConsole.app/Contents/
+	touch $(APPBASE)/AltConsole.app
+
+install: $(APPBASE)/AltConsole.app
+
+clean:
+	rm -f AltConsole $(OBJECTS) *~ #*
+
+remove: clean
+	rm -rf $(APPBASE)/AltConsole.app
Index: /branches/new-random/cocoa-ide/altconsole/main.m
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/main.m	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/main.m	(revision 13309)
@@ -0,0 +1,99 @@
+/*
+   Copyright (C) 2003 Clozure Associates
+   This file is part of OpenMCL.  
+
+   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with OpenMCL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with OpenMCL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   OpenMCL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+
+  $Log: main.m,v $
+  Revision 1.3  2008/11/22 04:11:00  gb
+  I -think- that we want to test the result of a call to not_detached(),
+  not test the address of that function.
+
+  Revision 1.2  2003/11/17 07:30:39  gb
+  update copyright/license
+
+*/
+
+#import <Cocoa/Cocoa.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+
+BOOL
+not_detached() {
+  struct stat dev_null_stat, fd_0_stat;
+
+  if ((fstat(0, &fd_0_stat) == 0) &&
+      (stat("/dev/null", &dev_null_stat) == 0) &&
+      (dev_null_stat.st_ino != fd_0_stat.st_ino)) {
+    return YES;
+  }
+  return NO;
+}
+
+int
+select_ignoring_eintr(int n, fd_set *in, fd_set *out, fd_set *err, struct timeval *tv) {
+  int result;
+  
+  do {
+    result = select(n, in, out, err, tv);
+    if (result >= 0) {
+      return result;
+    }
+    if (errno != EINTR) {
+      return result;
+    }
+  } while (1);
+  return result;
+}
+
+int main(int argc, const char *argv[]) {
+  if (not_detached()) {
+    int flags = fcntl(0, F_GETFL);
+    fd_set in, err;
+    
+    /*
+      It's apparently necessary to put the file descriptor into
+      non-blocking mode, to keep the FIONREAD from indicating that
+      data is available when we're actually at EOF.
+    */
+    fcntl(0, F_SETFL, flags | O_NONBLOCK);
+    FD_ZERO(&in); 
+    FD_ZERO(&err);
+    FD_SET(0,&in);
+    FD_SET(0,&err);
+    
+    /*
+      GDB may cause the select() syscall to be interrupted if it
+      attaches to us while we're blocked in select, so select until we
+      win or get an error other than EINTR.
+    */
+    if (select_ignoring_eintr(1, &in, NULL, &err, NULL) == 1) {
+      int nbytes;
+      
+      if ((ioctl(0, FIONREAD, &nbytes)  == 0) && (nbytes > 0)) {
+	/* 
+	   If we have incoming data, restore fd 0 to its previous
+	   blocking state and start the Cocoa application.
+	*/
+        fcntl(0, F_SETFL, flags);
+        return NSApplicationMain(argc, argv);
+      }
+    }
+    fcntl(0, F_SETFL, flags);
+  }
+  return -1;
+}
Index: /branches/new-random/cocoa-ide/altconsole/resource/AltConsole.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/resource/AltConsole.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/resource/AltConsole.nib/classes.nib	(revision 13309)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>CLASS</key>
+			<string>AltConsoleDocument</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>indicator</key>
+				<string>id</string>
+				<key>textView</key>
+				<string>id</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSDocument</string>
+		</dict>
+		<dict>
+			<key>CLASS</key>
+			<string>FirstResponder</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/altconsole/resource/AltConsole.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/resource/AltConsole.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/resource/AltConsole.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>43</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9J61</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/altconsole/resource/InfoPlist.strings
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/resource/InfoPlist.strings	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/resource/InfoPlist.strings	(revision 13309)
@@ -0,0 +1,5 @@
+/* Localized versions of Info.plist keys */
+
+CFBundleShortVersionString = "0.1";
+CFBundleGetInfoString = "altconsole version 0.1, Copyright 2003 Clozure Associates.";
+NSHumanReadableCopyright = "Copyright 2003 Clozure Associates.";
Index: /branches/new-random/cocoa-ide/altconsole/resource/MainMenu.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/resource/MainMenu.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/resource/MainMenu.nib/classes.nib	(revision 13309)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>CLASS</key>
+			<string>FirstResponder</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+		<dict>
+			<key>CLASS</key>
+			<string>AltConsoleDocumentController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSDocumentController</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/altconsole/resource/MainMenu.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/resource/MainMenu.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/resource/MainMenu.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>29</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9J61</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/altconsole/version.plist
===================================================================
--- /branches/new-random/cocoa-ide/altconsole/version.plist	(revision 13309)
+++ /branches/new-random/cocoa-ide/altconsole/version.plist	(revision 13309)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildVersion</key>
+	<string>17</string>
+	<key>CFBundleShortVersionString</key>
+	<string>0.1</string>
+	<key>CFBundleVersion</key>
+	<string>0.1</string>
+	<key>ProjectName</key>
+	<string>NibPBTemplates</string>
+	<key>SourceVersion</key>
+	<string>1150000</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/app-delegate.lisp
===================================================================
--- /branches/new-random/cocoa-ide/app-delegate.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/app-delegate.lisp	(revision 13309)
@@ -0,0 +1,251 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+(defclass lisp-application-delegate (ns:ns-object)
+    ()
+  (:metaclass ns:+ns-object))
+
+;;; This method is a good place to:
+;;;  * register value transformer names
+;;;  * register default user defaults
+(objc:defmethod (#/initialize :void) ((self +lisp-application-delegate))
+  (#/setValueTransformer:forName: ns:ns-value-transformer
+				  (make-instance 'font-to-name-transformer)
+				  #@"FontToName")
+
+  (let* ((domain (#/standardUserDefaults ns:ns-user-defaults))
+	 (initial-values (cocoa-defaults-initial-values))
+	 (dict (#/mutableCopy initial-values)))
+    (declare (special *standalone-cocoa-ide*))
+    #+cocotron
+    (#/setObject:forKey:
+     dict
+     (#/dictionaryWithObjectsAndKeys:
+      ns:ns-dictionary
+      #@"Control" #@"LeftControl"
+      #@"Alt" #@"LeftAlt"
+      #@"Command" #@"RightControl"
+      #@"Alt" #@"RightAlt"
+      +null-ptr+)
+     #@"NSModifierFlagMapping")
+    (#/registerDefaults: domain dict)
+    (#/release dict)
+    (update-cocoa-defaults)
+    (when *standalone-cocoa-ide*
+      (init-ccl-directory-for-ide))))
+
+(defun init-ccl-directory-for-ide ()
+  (let* ((bundle-path (#/bundlePath (#/mainBundle ns:ns-bundle)))
+         (parent (#/stringByDeletingLastPathComponent bundle-path))
+         (path (ccl::ensure-directory-pathname
+                (lisp-string-from-nsstring parent))))
+    (ccl::replace-base-translation "ccl:" path)))
+
+
+(defvar *ccl-ide-init-file* "home:ccl-ide-init")
+
+;;; Errors that occur while this file is loading will enter a break
+;;; loop, with *DEBUG-IO* connected to the terminal/Emacs, to AltConsole,
+;;; or to /dev/null and syslog.
+(defun load-ide-init-file ()
+  (with-simple-restart (continue "Skip loading IDE init file.")
+    (load *ccl-ide-init-file* :if-does-not-exist nil :verbose nil)))
+
+(objc:defmethod (#/applicationWillFinishLaunching: :void)
+    ((self lisp-application-delegate) notification)
+  (declare (ignore notification))
+  (initialize-user-interface)
+  (load-ide-init-file))
+
+(objc:defmethod (#/applicationWillTerminate: :void)
+		((self lisp-application-delegate) notification)
+  (declare (ignore notification))
+  ;; UI has decided to quit; terminate other lisp threads.
+  (ccl::prepare-to-quit))
+
+(defloadvar *preferences-window-controller* nil)
+
+(objc:defmethod (#/showPreferences: :void) ((self lisp-application-delegate)
+					    sender)
+  (declare (ignore sender))
+  (when (null *preferences-window-controller*)
+    (setf *preferences-window-controller*
+	  (make-instance 'preferences-window-controller)))
+  (#/showWindow: *preferences-window-controller* self))
+
+(defloadvar *processes-window-controller* nil)
+
+(objc:defmethod (#/showProcessesWindow: :void) ((self lisp-application-delegate)
+						sender)
+  (declare (ignore sender))
+  (when (null *processes-window-controller*)
+    (setf *processes-window-controller*
+	  (make-instance 'processes-window-controller)))
+  (#/showWindow: *processes-window-controller* self))
+
+(defloadvar *apropos-window-controller* nil)
+
+(objc:defmethod (#/showAproposWindow: :void) ((self lisp-application-delegate)
+						sender)
+  (declare (ignore sender))
+  (when (null *apropos-window-controller*)
+    (setf *apropos-window-controller*
+	  (make-instance 'apropos-window-controller)))
+  (#/showWindow: *apropos-window-controller* self))
+
+(defloadvar *xapropos-window-controller* nil)
+
+(objc:defmethod (#/showXaproposWindow: :void) ((self lisp-application-delegate)
+						sender)
+  (declare (ignore sender))
+  (when (null *xapropos-window-controller*)
+    (setf *xapropos-window-controller*
+	  (make-instance 'xapropos-window-controller)))
+  (#/showWindow: *xapropos-window-controller* self))
+
+(objc:defmethod (#/showNewInspector: :void) ((self lisp-application-delegate)
+                                             sender)
+  (declare (ignore sender))
+  (#/showWindow: (make-instance 'inspector::xinspector-window-controller
+                   :inspector (inspector::make-inspector *package*)) self))
+
+(objc:defmethod (#/showSearchFiles: :void) ((self lisp-application-delegate)
+                                            sender)
+  ;;If command key is pressed, always make a new window
+  ;;otherwise bring frontmost search files window to the front
+  (declare (ignore sender))
+  (let ((w nil))
+    (if (or (current-event-command-key-p)
+            (null (setf w (first-window-with-controller-type 'search-files-window-controller))))
+      (let* ((wc (make-instance 'search-files-window-controller)))
+        (#/showWindow: wc self))
+      (#/makeKeyAndOrderFront: w self))))
+
+(objc:defmethod (#/newListener: :void) ((self lisp-application-delegate)
+                                        sender)
+  (declare (ignore sender))
+  (#/openUntitledDocumentOfType:display:
+   (#/sharedDocumentController ns:ns-document-controller) #@"Listener" t))
+
+(objc:defmethod (#/showListener: :void) ((self lisp-application-delegate)
+                                        sender)
+  (declare (ignore sender))
+  (let* ((all-windows (#/orderedWindows *NSApp*))
+	 (key-window (#/keyWindow *NSApp*))
+	 (listener-windows ())
+	 (top-listener nil))
+    (dotimes (i (#/count all-windows))
+      (let* ((w (#/objectAtIndex: all-windows i))
+	     (wc (#/windowController w)))
+	(when (eql (#/class wc) hemlock-listener-window-controller)
+	  (push w listener-windows))))
+    (setq listener-windows (nreverse listener-windows))
+    (setq top-listener (car listener-windows))
+    (cond 
+     ((null listener-windows)
+      (#/newListener: self +null-ptr+))
+     ((eql key-window top-listener)
+      ;; The current window is a listener.  If there is more than
+      ;; one listener, bring the rear-most forward.
+      (let* ((w (car (last listener-windows))))
+	(if (eql top-listener w)
+	  (#_NSBeep)
+	  (#/makeKeyAndOrderFront: w +null-ptr+))))
+     (t
+      (#/makeKeyAndOrderFront: top-listener +null-ptr+)))))
+
+(objc:defmethod (#/ensureListener: :void) ((self lisp-application-delegate)
+					   sender)
+  (declare (ignore sender))
+  (let ((top-listener-document (#/topListener hemlock-listener-document)))
+    (when (eql top-listener-document +null-ptr+)
+      (let* ((dc (#/sharedDocumentController ns:ns-document-controller))
+	     (wc nil))
+	(setq top-listener-document
+	      (#/makeUntitledDocumentOfType:error: dc #@"Listener" +null-ptr+))
+	(#/addDocument: dc top-listener-document)
+	(#/makeWindowControllers top-listener-document)
+	(setq wc (#/lastObject (#/windowControllers top-listener-document)))
+	(#/orderFront: (#/window wc) +null-ptr+)))))
+
+(defvar *cocoa-application-finished-launching* (make-semaphore)
+  "Semaphore that's signaled when the application's finished launching ...")
+
+(objc:defmethod (#/applicationDidFinishLaunching: :void)
+    ((self lisp-application-delegate) notification)
+  (declare (ignore notification))
+  (signal-semaphore *cocoa-application-finished-launching*))
+
+(objc:defmethod (#/applicationShouldOpenUntitledFile: #>BOOL)
+    ((self lisp-application-delegate) app)
+  (declare (ignore app))
+  t)
+
+(objc:defmethod (#/applicationOpenUntitledFile: :<BOOL>)
+    ((self lisp-application-delegate) app)
+  (when (zerop *cocoa-listener-count*)
+    (#/newListener: self app)
+    t))
+
+(objc:defmethod (#/loadFile: :void) ((self lisp-application-delegate) sender)
+  (declare (ignore sender))
+  (let ((filename (cocoa-choose-file-dialog
+		   :button-string "Load"
+		   :file-types (list (pathname-type *.lisp-pathname*)
+				     (pathname-type *.fasl-pathname*)))))
+    (when filename
+      (#/ensureListener: self nil)
+      (let* ((doc (#/topListener hemlock-listener-document))
+	     (process (hemlock-document-process doc)))
+	(process-interrupt process #'(lambda ()
+				       (load filename)
+				       (fresh-line)))))))
+
+(objc:defmethod (#/compileFile: :void) ((self lisp-application-delegate) sender)
+  (declare (ignore sender))
+  (let ((filename (cocoa-choose-file-dialog
+		   :button-string "Compile"
+		   :file-types (list (pathname-type *.lisp-pathname*)))))
+    (when filename
+      (#/ensureListener: self nil)
+      (let* ((doc (#/topListener hemlock-listener-document))
+	     (process (hemlock-document-process doc)))
+	(process-interrupt process #'(lambda ()
+				       (compile-file filename)
+				       (fresh-line)))))))
+
+(objc:defmethod (#/exitBreak: :void) ((self lisp-application-delegate) sender)
+  (let* ((top-listener (#/topListener hemlock-listener-document)))
+    (unless (%null-ptr-p top-listener)
+      (#/exitBreak: top-listener sender))))
+
+(objc:defmethod (#/continue: :void) ((self lisp-application-delegate) sender)
+  (let* ((top-listener (#/topListener hemlock-listener-document)))
+    (unless (%null-ptr-p top-listener)
+      (#/continue: top-listener sender))))
+
+(objc:defmethod (#/restarts: :void) ((self lisp-application-delegate) sender)
+  (let* ((top-listener (#/topListener hemlock-listener-document)))
+    (unless (%null-ptr-p top-listener)
+      (#/restarts: top-listener sender))))
+
+(objc:defmethod (#/backtrace: :void) ((self lisp-application-delegate) sender)
+  (let* ((top-listener (#/topListener hemlock-listener-document)))
+    (unless (%null-ptr-p top-listener)
+      (#/backtrace: top-listener sender))))
+
+(objc:defmethod (#/validateMenuItem: #>BOOL) ((self lisp-application-delegate) item)
+  (let* ((action (#/action item)))
+    (cond ((or (eql action (@selector "exitBreak:"))
+               (eql action (@selector "continue:"))
+               (eql action (@selector "restarts:"))
+               (eql action (@selector "backtrace:")))
+           (let* ((top-listener (#/topListener hemlock-listener-document)))
+             (unless (%null-ptr-p top-listener)      
+               (#/validateMenuItem: top-listener item))))
+          (t t))))
+
+
Index: /branches/new-random/cocoa-ide/apropos-window.lisp
===================================================================
--- /branches/new-random/cocoa-ide/apropos-window.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/apropos-window.lisp	(revision 13309)
@@ -0,0 +1,231 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+(defclass package-combo-box (ns:ns-combo-box)
+  ((packages :initform nil))
+  (:metaclass ns:+ns-object))
+
+;;; This is a premature optimization.  Instead of calling LIST-ALL-PACKAGES
+;;; so frequently, just get a fresh copy when the user clicks in the
+;;; combo box.
+(objc:defmethod (#/becomeFirstResponder :<BOOL>) ((self package-combo-box))
+  (with-slots (packages) self
+    (setf packages (coerce (list-all-packages) 'vector))
+    (setf packages (sort packages #'string-lessp :key #'package-name)))
+  (call-next-method))
+
+(defclass apropos-window-controller (ns:ns-window-controller)
+  ((apropos-array :foreign-type :id :initform +null-ptr+
+		  :reader apropos-array
+		  :documentation "Bound to NSArrayController in nib file")
+   (array-controller :foreign-type :id :accessor array-controller)
+   (combo-box :foreign-type :id :accessor combo-box)
+   (table-view :foreign-type :id :accessor table-view)
+   (text-view :foreign-type :id :accessor text-view)
+   (external-symbols-checkbox :foreign-type :id
+			      :accessor external-symbols-checkbox)
+   (shows-external-symbols :initform nil)
+   (symbol-list :initform nil)
+   (package :initform nil)
+   (input :initform nil)
+   (previous-input :initform nil :accessor previous-input
+		   :documentation "Last string entered"))
+  (:metaclass ns:+ns-object))
+
+(defmethod (setf apropos-array) (value (self apropos-window-controller))
+  (with-slots (apropos-array) self
+    (unless (eql value apropos-array)
+      (#/release apropos-array)
+      (setf apropos-array (#/retain value)))))
+
+;;; Diasable automatic KVO notifications, since having our class swizzled
+;;; out from underneath us confuses CLOS.  (Leopard doesn't hose us,
+;;; and we can use automatic KVO notifications there.)
+(objc:defmethod (#/automaticallyNotifiesObserversForKey: :<BOOL>) ((self +apropos-window-controller)
+                                                                  key)
+  (declare (ignore key))
+  nil)
+
+(objc:defmethod (#/awakeFromNib :void) ((self apropos-window-controller))
+  (with-slots (table-view text-view) self
+    (#/setString: text-view #@"")
+    (#/setDelegate: table-view self)
+    (#/setDoubleAction: table-view (@selector #/definitionForSelectedSymbol:))))
+
+(objc:defmethod #/init ((self apropos-window-controller))
+  (prog1
+      (#/initWithWindowNibName: self #@"apropos")
+    (#/setShouldCascadeWindows: self nil)
+    (#/setWindowFrameAutosaveName: self #@"apropos panel")
+    (setf (apropos-array self) (#/array ns:ns-mutable-array))))
+
+(objc:defmethod (#/dealloc :void) ((self apropos-window-controller))
+  (#/release (slot-value self 'apropos-array))
+  (call-next-method))
+
+(objc:defmethod (#/toggleShowsExternalSymbols: :void)
+    ((self apropos-window-controller) sender)
+  (declare (ignore sender))
+  (with-slots (shows-external-symbols) self
+    (setf shows-external-symbols (not shows-external-symbols))
+    (update-symbol-list self)
+    (update-apropos-array self)))
+
+(objc:defmethod (#/setPackage: :void) ((self apropos-window-controller)
+				       sender)
+  (with-slots (combo-box package) self
+    (assert (eql sender combo-box))
+    (with-slots (packages) sender
+      (let ((index (#/indexOfSelectedItem sender)))
+	(if (minusp index)
+	  (setf package nil)		;search all packages
+	  (setf package (svref packages index))))))
+  (update-symbol-list self)
+  (update-apropos-array self))
+
+(defmethod update-symbol-list ((self apropos-window-controller))
+  (with-slots (input package shows-external-symbols symbol-list) self
+    (when (plusp (length input))
+      (setf symbol-list nil)
+      (if package
+	(if shows-external-symbols
+	  (do-external-symbols (sym package)
+	    (when (ccl::%apropos-substring-p input (symbol-name sym))
+	      (push sym symbol-list)))
+	  (do-symbols (sym package)
+	    (when (ccl::%apropos-substring-p input (symbol-name sym))
+	      (push sym symbol-list))))
+	(if shows-external-symbols
+	  (dolist (p (list-all-packages))
+	    (do-external-symbols (sym p)
+	      (when (ccl::%apropos-substring-p input (symbol-name sym))
+		(push sym symbol-list))))
+	  (do-all-symbols (sym)
+	    (when (ccl::%apropos-substring-p input (symbol-name sym))
+	      (push sym symbol-list)))))
+      (setf symbol-list (sort symbol-list #'string-lessp)))))
+
+(defmethod update-apropos-array ((self apropos-window-controller))
+  (with-slots (input apropos-array symbol-list package) self
+    (when (plusp (length input))
+      (let ((new-array (#/array ns:ns-mutable-array))
+	    (*package* (or package (find-package "COMMON-LISP-USER")))
+	    (n 0))
+	(dolist (s symbol-list)
+	  (#/addObject: new-array (#/dictionaryWithObjectsAndKeys:
+				   ns:ns-dictionary
+				   (#/autorelease
+				    (%make-nsstring
+				     (prin1-to-string s)))
+				   #@"symbol"
+				   (#/numberWithInt: ns:ns-number n)
+				   #@"index"
+				   (#/autorelease
+				    (%make-nsstring
+				     (inspector::symbol-type-line s)))
+				   #@"kind"
+				   +null-ptr+))
+	  (incf n))
+	(#/willChangeValueForKey: self #@"aproposArray")
+	(setf apropos-array new-array)
+	(#/didChangeValueForKey: self #@"aproposArray")))))
+
+(objc:defmethod (#/apropos: :void) ((self apropos-window-controller) sender)
+  (let* ((input (lisp-string-from-nsstring (#/stringValue sender))))
+    (when (and (plusp (length input))
+	       (not (string-equal input (previous-input self))))
+      (setf (slot-value self 'input) input)
+      (setf (previous-input self) input)
+      (update-symbol-list self)
+      (update-apropos-array self))))
+
+(objc:defmethod (#/inspectSelectedSymbol: :void) ((self apropos-window-controller) sender)
+  (declare (ignorable sender))
+  (let* ((row (#/clickedRow (table-view self))))
+    (unless (minusp row)
+      (with-slots (array-controller symbol-list) self
+	(let* ((number (#/valueForKeyPath: array-controller #@"selection.index"))
+	       (i (#/intValue number))
+	       (sym (elt symbol-list i)))
+	  (inspect sym))))))
+
+(objc:defmethod (#/definitionForSelectedSymbol: :void) ((self apropos-window-controller) sender)
+  (declare (ignorable sender))
+  (let* ((row (#/clickedRow (table-view self))))
+    (unless (minusp row)
+      (with-slots (array-controller symbol-list) self
+	(let* ((number (#/valueForKeyPath: array-controller #@"selection.index"))
+	       (i (#/intValue number))
+	       (sym (elt symbol-list i)))
+	  (hemlock::edit-definition sym))))))
+
+;;; Data source methods for package combo box
+
+(objc:defmethod (#/numberOfItemsInComboBox: :<NSI>nteger) ((self apropos-window-controller)
+						   combo-box)
+  (declare (ignore combo-box))
+  (length (list-all-packages)))
+
+(objc:defmethod #/comboBox:objectValueForItemAtIndex: ((self apropos-window-controller)
+						       combo-box
+						       (index :<NSI>nteger))
+  (with-slots (packages) combo-box
+    (let* ((pkg-name (package-name (svref packages index))))
+      (if pkg-name
+	(#/autorelease (%make-nsstring pkg-name))
+	+null-ptr+))))
+
+(objc:defmethod #/comboBox:completedString: ((self apropos-window-controller)
+					     combo-box
+					     partial-string)
+  (flet ((string-prefix-p (s1 s2)
+	   "Is s1 a prefix of s2?"
+	   (string-equal s1 s2 :end2 (min (length s1) (length s2)))))
+    (with-slots (packages) combo-box
+      (let* ((s (lisp-string-from-nsstring partial-string)))
+	(dotimes (i (length packages) +null-ptr+)
+	  (let ((name (package-name (svref packages i))))
+	    (when (string-prefix-p s name)
+	      (return (#/autorelease (%make-nsstring name))))))))))
+
+(objc:defmethod (#/comboBox:indexOfItemWithStringValue: :<NSUI>nteger)
+    ((self apropos-window-controller)
+     combo-box
+     string)
+  (with-slots (packages) combo-box
+    (let* ((s (lisp-string-from-nsstring string)))
+      (or (position s packages :test #'(lambda (str pkg)
+					 (string-equal str (package-name pkg))))
+	  #$NSNotFound))))
+
+
+;;; Table view delegate methods
+
+(objc:defmethod (#/tableViewSelectionDidChange: :void) ((self apropos-window-controller)
+							notification)
+  (with-slots (array-controller symbol-list text-view) self
+    (let* ((tv (#/object notification))
+	   (row (#/selectedRow tv)))
+      (unless (minusp row)
+	(let* ((number (#/valueForKeyPath:
+			array-controller #@"selection.index"))
+	       (i (#/intValue number))
+	       (sym (elt symbol-list i))
+	       (info (make-array '(0) :element-type 'base-char
+				 :fill-pointer 0 :adjustable t)))
+	  (with-output-to-string (s info)
+	    (dolist (doctype '(compiler-macro function method-combination
+			       setf structure t type variable))
+	      (let ((docstring (documentation sym doctype)))
+		(when docstring
+		  (format s "~&~a" docstring))
+		(when (eq doctype 'function)
+		  (format s "~&arglist: ~s" (arglist sym))))))
+	  (if (plusp (length info))
+	    (#/setString: text-view (#/autorelease (%make-nsstring info)))
+	    (#/setString: text-view #@"")))))))
+
+
Index: /branches/new-random/cocoa-ide/build-application.lisp
===================================================================
--- /branches/new-random/cocoa-ide/build-application.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/build-application.lisp	(revision 13309)
@@ -0,0 +1,99 @@
+;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: cl-user -*-
+;;;; ***********************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          build-application.lisp
+;;;; Version:       0.9
+;;;; Project:       Cocoa application builder
+;;;; Purpose:       the in-process application builder
+;;;;
+;;;; ***********************************************************************
+
+(require "BUILDER-UTILITIES")
+
+(in-package :ccl)
+
+
+;;; TODO: 
+;;;  1. make a way to specify a user-defined app delegate in build-application
+;;;  2. review function names. consider renaming BUILD-APPLICATION to
+;;;     SAVE-APPLICATION-BUNDLE, to better distinguish the in-process
+;;;     save-to-a-bundle function from the out-of-process batch version
+
+;;; BUILD-APPLICATION
+;;; ------------------------------------------------------------------------
+;;; Builds an application bundle and saves an executable lisp image
+;;; into it. Populates the bundle directory with the files needed to
+;;; run the lisp image when the bundle is double-clicked.
+
+(defun build-application (&key
+                          (name $default-application-bundle-name)
+                          (type-string $default-application-type-string)
+                          (creator-string $default-application-creator-string)
+                          (directory (current-directory))
+                          (copy-ide-resources t) ; whether to copy the IDE's resources
+                          (info-plist nil) ; optional user-defined info-plist
+                          (nibfiles nil) ; a list of user-specified nibfiles
+                                        ; to be copied into the app bundle
+                          (main-nib-name) ; the name of the nib that is to be loaded
+                                        ; as the app's main. this name gets written
+                                        ; into the Info.plist on the "NSMainNibFile" key
+                          (application-class 'gui::cocoa-application)
+                          (private-frameworks nil)
+                          (toplevel-function nil)
+                          (altconsole t))
+
+  (let* ((info-plist (or info-plist ; if the user supplied one then we use it
+                         (if copy-ide-resources 
+                             ;; otherwise: if copying resources use ide's
+                             (get-ide-bundle-info-plist)
+                             ;; else, create a new one
+                             (make-info-dict))))
+         (ide-bundle-path (get-ide-bundle-path))
+         ;; create the bundle directory
+         (app-bundle (make-application-bundle :name name :project-path directory))
+         (executable-dir (bundle-executable-path app-bundle))
+         (image-path (namestring (path executable-dir (bundle-executable-name name)))))
+    ;; maybe copy IDE resources to the bundle
+    (when copy-ide-resources
+      (recursive-copy-directory (path ide-bundle-path "Contents" "Resources/")
+                                (path app-bundle  "Contents" "Resources/")
+                                :test #'not-vc-control-file
+                                :if-exists :overwrite))
+    ;; write Info.plist
+    (write-info-plist info-plist (path app-bundle "Contents" "Info.plist")
+                      name type-string creator-string :main-nib-name main-nib-name)
+    ;; write Pkginfo
+    (write-pkginfo (path app-bundle "Contents" "PkgInfo") type-string creator-string)
+    ;; copy any user nibfiles into the bundle
+    (when nibfiles
+      (let ((nib-paths (mapcar #'pathname nibfiles)))
+        (assert (and (every #'probe-file nib-paths))
+                (nibfiles)
+                "The nibfiles parameter must be a list of valid pathnames to existing files or directories")
+        (dolist (n nib-paths)
+          (let ((dest (path app-bundle  "Contents" "Resources" "English.lproj/")))
+            (copy-nibfile n dest :if-exists :overwrite)))))
+    ;; copy any private frameworks into the bundle
+    (copy-private-frameworks private-frameworks app-bundle)
+    ;; install the AltConsole application if requested
+    (when altconsole
+      (install-altconsole app-bundle))
+    ;; save the application image into the bundle
+    (save-application image-path
+                      :application-class application-class
+                      :toplevel-function toplevel-function
+                      :prepend-kernel t
+                      #+windows-target #+windows-target
+                      :application-type :gui)))
+
+
+
+#|
+(require :build-application)
+(load "/usr/local/ccl/trunk/source/cocoa-ide/builder-utilities.lisp")
+(load "/usr/local/ccl/trunk/source/cocoa-ide/build-application.lisp")
+(ccl::build-application :name "Foo"
+                        :directory "/Users/mikel/Desktop"
+                        :copy-ide-resources t)
+|#
Index: /branches/new-random/cocoa-ide/builder-utilities.lisp
===================================================================
--- /branches/new-random/cocoa-ide/builder-utilities.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/builder-utilities.lisp	(revision 13309)
@@ -0,0 +1,396 @@
+;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: cl-user -*-
+;;;; ***********************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          builder-utilities.lisp
+;;;; Version:       0.9
+;;;; Project:       bosco - Cocoa application builder
+;;;; Purpose:       utilities used by both batch and interactive builders
+;;;;
+;;;; ***********************************************************************
+
+(in-package :ccl)
+
+;;; ABOUT
+;;; ------------------------------------------------------------------------
+;;; Builder-utilities contains several functions used by OpenMCL
+;;; application-building tools for building and copying bundles,
+;;; resource directories, and magic files used by OSX applications.
+
+(defun %temp-nsstring (s) (#/autorelease (%make-nsstring s)))
+
+;;; Info Defaults
+;;; Some useful values for use when creating application bundles
+
+(defparameter $default-application-bundle-name "MyApplication")
+(defparameter $default-application-type-string "APPL")
+(defparameter $default-application-creator-string "OMCL")
+(defparameter $default-application-version-number "1.0")
+
+;;; defaults related to Info.plist files
+(defparameter $cfbundle-development-region-key #@"CFBundleDevelopmentRegion")
+(defparameter $default-info-plist-development-region "English")
+
+(defparameter $cfbundle-executable-key #@"CFBundleExecutable")
+(defparameter $default-info-plist-executable $default-application-bundle-name)
+
+(defparameter $cfbundle-getinfo-string-key #@"CFBundleGetInfoString")
+(defparameter $default-info-plist-getInfo-string "\"1.0 Copyright © 2008\"")
+
+(defparameter $cfbundle-help-book-folder-key #@"CFBundleHelpBookFolder")
+(defparameter $default-info-plist-help-book-folder "MyApplicationHelp")
+
+(defparameter $cfbundle-help-book-name-key #@"CFBundleHelpBookName")
+(defparameter $default-info-plist-help-book-name "\"MyApplication Help\"")
+
+(defparameter $cfbundle-icon-file-key #@"CFBundleIconFile")
+(defparameter $default-info-plist-icon-file "\"MyApplication.icns\"")
+
+(defparameter $cfbundle-bundle-identifier-key #@"CFBundleIdentifier")
+(defparameter $default-info-plist-bundle-identifier "\"com.clozure.apps.myapplication\"")
+
+(defparameter $cfbundle-dictionary-version-key #@"CFBundleInfoDictionaryVersion")
+(defparameter $default-info-dictionary-version "\"6.0\"")
+
+(defparameter $cfbundle-bundle-name-key #@"CFBundleName")
+(defparameter $default-info-plist-bundle-name "MyApplication")
+
+(defparameter $cfbundle-bundle-package-type-key #@"CFBundlePackageType")
+(defparameter $default-info-plist-bundle-package-type "APPL")
+
+(defparameter $cfbundle-short-version-string-key #@"CFBundleShortVersionString")
+(defparameter $default-info-plist-short-version-string "\"1.0\"")
+
+(defparameter $cfbundle-bundle-signature-key #@"CFBundleSignature")
+(defparameter $default-info-plist-bundle-signature "OMCL")
+
+(defparameter $cfbundle-version-key #@"CFBundleVersion")
+(defparameter $default-info-plist-version "\"1.0\"")
+
+(defparameter $ls-has-localized-display-name-key #@"LSHasLocalizedDisplayName")
+(defparameter $default-info-plist-has-localized-display-name "0")
+
+(defparameter $ls-minimum-system-version-key #@"LSMinimumSystemVersion")
+(defparameter $default-info-plist-minimum-system-version "\"10.5\"")
+
+(defparameter $ns-main-nib-file-key #@"NSMainNibFile")
+(defparameter $default-info-plist-main-nib-file "MainMenu")
+
+(defparameter $ns-principal-class-key #@"NSPrincipalClass")
+(defparameter $default-info-plist-principal-class "LispApplication")
+
+;;; keys for document-types dicts
+(defparameter $cfbundle-type-extensions-key #@"CFBundleTypeExtensions")
+(defparameter $cfbundle-type-icon-file-key #@"CFBundleTypeIconFile")
+(defparameter $cfbundle-type-mime-types-key #@"CFBundleTypeMIMETypes")
+(defparameter $cfbundle-type-name-key #@"CFBundleTypeName")
+(defparameter $cfbundle-type-ostypes-key #@"CFBundleTypeOSTypes")
+(defparameter $cfbundle-type-role-key #@"CFBundleTypeRole")
+(defparameter $ls-item-content-types-key #@"LSItemContentTypes")
+(defparameter $ls-type-is-package-key #@"LSTypeIsPackage")
+(defparameter $ns-document-class-key #@"NSDocumentClass")
+(defparameter $ns-exportable-as-key #@"NSExportableAs")
+
+;;; NOT-VC-CONTROL-FILE (path)
+;;; ------------------------------------------------------------------------
+;;; Returns T if the specified file (or directory) is not part of a version
+;;; control system's control data
+
+(defun not-vc-control-file (path)
+  (let ((vc-directories '(".svn" "CVS"))
+        (vc-files '("svn-commit.tmp" "svn-commit.tmp~"
+                    "svn-prop.tmp" "svn-prop.tmp~"
+                    ".cvsignore")))
+    (not (or (member (car (last (pathname-directory path))) vc-directories :test #'equalp)
+             (member (file-namestring path) vc-files :test #'equalp)))))
+
+;;; COPY-NIBFILE (srcnib dest-directory &key (if-exists :overwrite))
+;;; ------------------------------------------------------------------------
+;;; Copies a nibfile (which may in fact be a directory) to the
+;;; destination path (which may already exist, and may need to
+;;; be overwritten
+
+(defun copy-nibfile (srcnib dest-directory &key (if-exists :overwrite))
+  (setq if-exists (require-type if-exists '(member :overwrite :error)))
+  (let* ((basename (basename srcnib))
+         (dest (path dest-directory basename)))
+    (if (probe-file dest)
+        (case if-exists
+          (:overwrite (progn
+                        (if (directoryp dest)
+                            (recursive-delete-directory dest)
+                            (delete-file dest))))
+          (:error (error "The nibfile '~A' already exists" dest))))
+    (if (directoryp srcnib)
+        (recursive-copy-directory srcnib dest :test #'not-vc-control-file)
+        (copy-file srcnib dest))))
+
+;;; BASENAME path
+;;; ------------------------------------------------------------------------
+;;; returns the final component of a pathname--that is, the
+;;; filename (with type extension) if it names a file, or the
+;;; last directory name if it names a directory
+
+(defun basename (path)
+  ;; first probe to see whether the path exists.  if it does, then
+  ;; PROBE-FILE returns a canonical pathname for it which, among other
+  ;; things, ensures the pathame represents a directory if it's really
+  ;; a directory, and a file if it's really a file
+  (let* ((path (or (probe-file path)
+                   path))
+         (dir (pathname-directory path))
+         (name (pathname-name path))
+         (type (pathname-type path)))
+    (if name
+        (if type
+            (make-pathname :name name :type type)
+            (make-pathname :name name))
+        ;; it's possible to have a pathname with a type but no name
+        ;; e.g. "/Users/foo/.emacs"
+        (if type
+            (make-pathname :type type)
+            (make-pathname :directory (first (last dir)))))))
+
+;;; PATH (&rest components)
+;;; ------------------------------------------------------------------------
+;;; returns a pathname. The input COMPONENTS are treated as 
+;;; directory names, each contained in the one to the left, except
+;;; for the last. The last is treated as a directory if it ends
+;;; with a path separator, and a file if it doesn't
+(defun path (&rest components)
+  (if (null components)
+      (pathname "")
+      (if (null (cdr components))
+          (pathname (car components))
+          (merge-pathnames (apply #'path (cdr components))
+                           (ensure-directory-pathname (car components))))))
+
+
+;;; WRITE-PKGINFO path package-type bundle-signature
+;;; ------------------------------------------------------------------------
+;;; Writes a PkgInfo file of the sort used by Cocoa applications
+;;; to identify their package types and signatures. Writes
+;;; PACKAGE-TYPE and BUNDLE-SIGNATURE to the file at PATH,
+;;; clobbering it if it already exists.
+(defun write-pkginfo (path package-type bundle-signature)
+  (with-open-file (out path
+                       :direction :output
+                       :if-does-not-exist :create
+                       :if-exists :supersede)
+    (format out "~A~A" package-type bundle-signature)))
+
+;;; MAKE-INFO-DICT
+;;; ------------------------------------------------------------------------
+;;; returns a newly-created NSDictionary with contents
+;;; specified by the input parameters
+(defun make-info-dict (&key
+                       (development-region $default-info-plist-development-region)
+                       (executable $default-info-plist-executable)
+                       (getinfo-string $default-info-plist-getinfo-string)
+                       (help-book-folder $default-info-plist-help-book-folder)
+                       (help-book-name $default-info-plist-help-book-name)
+                       (icon-file $default-info-plist-icon-file)
+                       (bundle-identifier $default-info-plist-bundle-identifier)
+                       (dictionary-version $default-info-dictionary-version)
+                       (bundle-name $default-info-plist-bundle-name)
+                       (bundle-package-type $default-info-plist-bundle-package-type)
+                       (short-version-string $default-info-plist-short-version-string)
+                       (bundle-signature $default-info-plist-bundle-signature)
+                       (version $default-info-plist-version)
+                       (has-localized-display-name $default-info-plist-has-localized-display-name)
+                       (minimum-system-version $default-info-plist-minimum-system-version)
+                       (main-nib-file $default-info-plist-main-nib-file)
+                       (principal-class $default-info-plist-principal-class))
+  (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
+                                   (%temp-nsstring development-region) $cfbundle-development-region-key
+                                   (%temp-nsstring executable) $cfbundle-executable-key
+                                   (%temp-nsstring getinfo-string) $cfbundle-getinfo-string-key
+                                   (%temp-nsstring help-book-folder) $cfbundle-help-book-folder-key
+                                   (%temp-nsstring help-book-name) $cfbundle-help-book-name-key
+                                   (%temp-nsstring icon-file) $cfbundle-icon-file-key
+                                   (%temp-nsstring bundle-identifier) $cfbundle-bundle-identifier-key
+                                   (%temp-nsstring dictionary-version) $cfbundle-dictionary-version-key
+                                   (%temp-nsstring bundle-name) $cfbundle-bundle-name-key
+                                   (%temp-nsstring bundle-package-type) $cfbundle-bundle-package-type-key
+                                   (%temp-nsstring short-version-string) $cfbundle-short-version-string-key
+                                   (%temp-nsstring bundle-signature) $cfbundle-bundle-signature-key
+                                   (%temp-nsstring version) $cfbundle-version-key
+                                   (%temp-nsstring has-localized-display-name) $ls-has-localized-display-name-key
+                                   (%temp-nsstring minimum-system-version) $ls-minimum-system-version-key
+                                   (%temp-nsstring main-nib-file) $ns-main-nib-file-key
+                                   (%temp-nsstring principal-class) $ns-principal-class-key
+                                   +null-ptr+))
+
+(defun make-doctype-dict (&key
+                          (extensions nil)
+                          (icon-file "Icons.icns")
+                          (mime-types nil)
+                          (type-name nil)
+                          (ostypes nil)
+                          (role nil)
+                          (ls-item-content-types nil)
+                          (bundlep nil)
+                          (document-class nil)
+                          (exportable-as nil))
+  ;; certain values are required
+  (assert (or ls-item-content-types extensions mime-types ostypes)
+          ()
+          "You must supply a list of strings as the value for one of the keywords :ls-item-content-types, :extensions, :mime-types, or :ostypes")
+  (assert type-name () "You must supply a string as a value for the keyword :type-name")
+  (assert role () 
+          "You must supply one of the strings \"Editor\", \"Viewer\", \"Shell\", or \"None\" as a value for the keyword :role")
+  (assert document-class ()
+          "You must supply the name of an NSDocument subclass (as a string) as the value of the keyword :document-class")
+  )
+
+;;; READ-INFO-PLIST info-path
+;;; ------------------------------------------------------------------------
+;;; returns a newly-created NSDictionary with the contents
+;;; of the plist file at INFO-PATH 
+(defun read-info-plist (info-path)
+  (let* ((info-path (pathname info-path)) ; make sure it's a pathname to start
+         (verified-path (probe-file info-path)))
+    (assert (and verified-path
+                 (string-equal (pathname-type verified-path) "plist"))
+            (info-path)
+            "The input path for READ-INFO-PLIST must be the name of a valid 'plist' file.")
+    (let* ((info-path-str (%temp-nsstring (namestring info-path))))
+      (#/dictionaryWithContentsOfFile: ns:ns-mutable-dictionary 
+                                       info-path-str))))
+
+;;; WRITE-INFO-PLIST info-plist path name package-type bundle-signature 
+;;; ------------------------------------------------------------------------
+;;; sets the name, package-type, and bundle-signature of the
+;;; info-plist from the inputs; writes the changed dictionary to a new
+;;; Info.plist file at PATH.
+
+(defun write-info-plist (info-dict out-path name package-type bundle-signature
+                         &key main-nib-name)
+  ;; change the fields needed, write the results to PATH
+  (assert (or (null main-nib-name)
+              (stringp main-nib-name))
+          (main-nib-name)
+          "The main-nib-name must be a string or NIL, not ~S" main-nib-name)
+  (with-autorelease-pool
+    (let* ((bundle-name-str (%make-nsstring name))
+           (type-str (%make-nsstring package-type))
+           (sig-str (%make-nsstring bundle-signature))
+           (app-name-str (%make-nsstring (bundle-executable-name name)))
+           (app-plist-path-str (%make-nsstring (namestring out-path))))
+      (#/setValue:forKey: info-dict bundle-name-str $cfbundle-bundle-name-key)
+      (#/setValue:forKey: info-dict app-name-str $cfbundle-executable-key)
+      (#/setValue:forKey: info-dict type-str $cfbundle-bundle-package-type-key)
+      (#/setValue:forKey: info-dict sig-str $cfbundle-bundle-signature-key)
+      (when main-nib-name
+        (#/setValue:forKey: info-dict 
+                            (%make-nsstring main-nib-name)
+                            $ns-main-nib-file-key))
+      (#/writeToFile:atomically: info-dict app-plist-path-str #$YES))))
+
+;;; GET-IDE-BUNDLE-PATH
+;;; ------------------------------------------------------------------------
+;;; Returns the llisp pathname of the running IDE bundle
+
+(defun get-ide-bundle-path ()
+  (let* ((ide-bundle (#/mainBundle ns:ns-bundle))
+         (ide-bundle-path-nsstring (#/bundlePath ide-bundle)))
+    (pathname 
+     (ensure-directory-pathname 
+      (lisp-string-from-nsstring ide-bundle-path-nsstring)))))
+
+;;; GET-IDE-BUNDLE-INFO-PLIST
+;;; ------------------------------------------------------------------------
+;;; Returns an NSDictionary instance created by reading the Info.plist
+;;; file from the running IDE's application bundle
+
+(defun get-ide-bundle-info-plist ()
+  (let* ((ide-bundle (#/mainBundle ns:ns-bundle))
+         (ide-bundle-path-nsstring (#/bundlePath ide-bundle))
+         (ide-bundle-path (ensure-directory-pathname 
+                           (lisp-string-from-nsstring ide-bundle-path-nsstring)))
+         (ide-plist-path-str (namestring (path ide-bundle-path 
+                                               "Contents" "Info.plist"))))
+    (read-info-plist ide-plist-path-str)))
+
+;;; BUNNDLE-EXECUTABLE-PATH app-path
+;;; ------------------------------------------------------------------------
+;;; Returns the pathname of the executable directory given the pathname of
+;;; an application bundle
+(defun bundle-executable-path (app-path)
+  (path app-path "Contents" 
+        #-windows-target (ensure-directory-pathname "MacOS")
+        #+windows-target (ensure-directory-pathname "Windows")))
+
+;;; BUNNDLE-EXECUTABLE-NAME name
+;;; ------------------------------------------------------------------------
+;;; Returns the name of the executable file for an application bundle
+(defun bundle-executable-name (name)
+  #-windows-target name
+  #+windows-target (concatenate 'string name ".exe"))
+
+;;; MAKE-APPLICATION-BUNDLE name package-type bundle-signature project-path
+;;; ------------------------------------------------------------------------
+;;; Build the directory structure of a Cocoa application bundle and
+;;; populate it with the required PkgInfo and Info.plist files.
+(defun make-application-bundle (&key 
+                                (name $default-application-bundle-name)
+                                (project-path (current-directory)))
+  (let* ((app-bundle (path project-path 
+                           (ensure-directory-pathname (concatenate 'string name ".app"))))
+         (contents-dir (path app-bundle (ensure-directory-pathname "Contents")))
+         (executable-dir (bundle-executable-path app-bundle))
+         (rsrc-dir (path contents-dir  "Resources" 
+                         (ensure-directory-pathname "English.lproj"))))
+    (ensure-directories-exist executable-dir)
+    (ensure-directories-exist rsrc-dir)
+    app-bundle))
+
+;;; BUNDLE-FRAMEWORKS-PATH app-path
+;;; ------------------------------------------------------------------------
+;;; Returns the pathname of the frameworks directory given the pathname of
+;;; an application bundle
+(defun bundle-frameworks-path (app-path)
+  (path app-path "Contents"
+        #-windows-target (ensure-directory-pathname "Frameworks")
+        #+windows-target (ensure-directory-pathname "Windows")))
+
+;;; FIND-FRAMEWORK-EXECUTABLE framework-path
+;;; ------------------------------------------------------------------------
+;;; Returns the pathname of the framework's executable file given the
+;;; pathname of a framework
+(defun find-framework-executable (framework-path)
+  (let* ((raw-framework-name (car (last (pathname-directory framework-path))))
+         (framework-name (subseq raw-framework-name 0 (- (length raw-framework-name)
+                                                         #.(length ".framework"))))
+         (executable-wildcard (path framework-path
+                                    (concatenate 'string framework-name "*.dll")))
+         (executables (directory executable-wildcard)))
+    (when executables
+      (truename (first executables)))))
+
+;;; COPY-PRIVATE-FRAMEWORKS private-frameworks app-path
+;;; ------------------------------------------------------------------------
+;;; Copy any private frameworks into the bundle taking into account the
+;;; different directory structures used by Cocoa and Cocotron (Windows).
+(defun copy-private-frameworks (private-frameworks app-path)
+  (let ((private-frameworks #+windows-target (append *cocoa-application-frameworks*
+                                                     private-frameworks)
+                            #-windows-target private-frameworks)
+        (frameworks-dir (bundle-frameworks-path app-path)))
+    #+windows-target
+    (dolist (lib *cocoa-application-libraries*)
+      (copy-file lib frameworks-dir :preserve-attributes t :if-exists :supersede))
+    (when private-frameworks
+      (flet ((subdir (framework target)
+               (ensure-directory-pathname
+                (make-pathname :name (car (last (pathname-directory framework)))
+                               :defaults target))))
+        (dolist (framework private-frameworks)
+          (recursive-copy-directory framework (subdir framework frameworks-dir)
+                                    :test #'not-vc-control-file
+                                    :if-exists :overwrite)
+          #+windows-target
+          (let ((executable (find-framework-executable framework)))
+            (when executable
+              (copy-file executable frameworks-dir 
+                         :preserve-attributes t :if-exists :supersede))))))))
Index: /branches/new-random/cocoa-ide/cocoa-application.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-application.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-application.lisp	(revision 13309)
@@ -0,0 +1,45 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2002-2003 Clozure Associates
+;;;   This file is part of OpenMCL.  
+;;;
+;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with OpenMCL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")			; for now.
+
+#+windows-target
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (pushnew :cocotron *features*))
+
+
+(defvar *cocoa-application-path*
+  (let* ((bits (nth-value 1 (host-platform))))
+    (format nil "ccl:Clozure CL~a.app;" bits)))
+(defvar *cocoa-application-copy-headers-p* nil)
+(defvar *cocoa-application-install-altconsole* t)
+(defvar *cocoa-application-bundle-suffix*
+  (multiple-value-bind (os bits cpu) (host-platform)
+    (declare (ignore os))
+    (format nil "Clozure CL-~a~a" (string-downcase cpu) bits)))
+(defvar *cocoa-application-frameworks* #+cocotron '("ccl:cocotron;Foundation.framework;" "ccl:cocotron;AppKit.framework;") #-cocotron nil)
+(defvar *cocoa-application-libraries* #+cocotron '("ccl:cocotron;Foundation'.1'.0'.dll" "ccl:cocotron;AppKit'.1'.0'.dll") #-cocotron nil)
+        
+(defvar *cocoa-ide-force-compile* nil)
+(load "ccl:cocoa-ide;defsystem.lisp")
+(load-ide *cocoa-ide-force-compile*)
+
+;;; If things go wrong, you might see some debugging information via
+;;; the OSX console (/Applications/Utilities/Console.app.)  Standard
+;;; and error output for the initial lisp process will be directed
+;;; there.
+(build-ide *cocoa-application-path*)
Index: /branches/new-random/cocoa-ide/cocoa-backtrace.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-backtrace.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-backtrace.lisp	(revision 13309)
@@ -0,0 +1,405 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+(defclass stack-descriptor ()
+  ((context :initarg :context :reader stack-descriptor-context)
+   (filter :initform nil :initarg :filter :reader stack-descriptor-filter)
+   (interruptable-p :initform t :accessor stack-descriptor-interruptable-p)
+   (segment-size :initform 50 :reader stack-descriptor-segment-size)
+   (frame-count :initform -1 :reader stack-descriptor-frame-count)
+   (frame-cache :initform (make-hash-table) :reader stack-descriptor-frame-cache)))
+
+(defun make-stack-descriptor (context &rest keys)
+  (apply #'make-instance 'stack-descriptor
+         ;; For some reason backtrace context is an anonymous vector
+         :context (require-type context 'simple-vector)
+         keys))
+
+(defmethod initialize-instance :after ((sd stack-descriptor) &key &allow-other-keys)
+  (with-slots (frame-count) sd
+    (setf frame-count (count-stack-descriptor-frames sd))))
+
+(defmethod stack-descriptor-refresh ((sd stack-descriptor))
+  (clrhash (stack-descriptor-frame-cache sd)))
+
+(defmethod stack-descriptor-origin ((sd stack-descriptor))
+  (ccl::bt.youngest (stack-descriptor-context sd)))
+
+(defmethod stack-descriptor-process ((sd stack-descriptor))
+  (ccl::tcr->process (ccl::bt.tcr (stack-descriptor-context sd))))
+
+(defmethod stack-descriptor-condition ((sd stack-descriptor))
+  (ccl::bt.break-condition (stack-descriptor-context sd)))
+
+(defmethod map-stack-frames (sd function &optional start end)
+  (ccl:map-call-frames function
+                       :origin (stack-descriptor-origin sd)
+                       :process (stack-descriptor-process sd)
+                       :test (stack-descriptor-filter sd)
+                       :start-frame-number (or start 0)
+                       :count (- (or end most-positive-fixnum)
+                                 (or start 0))))
+
+(defmethod count-stack-descriptor-frames ((sd stack-descriptor))
+  (let ((count 0))
+    (map-stack-frames sd (lambda (fp context)
+                           (declare (ignore fp context))
+                           (incf count)))
+    count))
+
+;; Function must be side-effect free, it may be restarted or aborted.
+(defun collect-stack-frames (sd function &optional start end)
+  (let ((process (stack-descriptor-process sd)))
+    ;; In general, it's best to run backtrace printing in the error process, since
+    ;; printing often depends on the dynamic state (e.g. bound vars) at the point of
+    ;; error.  However, if the erring process is wedged in some way, getting at it
+    ;; from outside may be better than nothing.
+    (if (or (not (stack-descriptor-interruptable-p sd))
+            (eq process *current-process*))
+      (let* ((results nil)
+	     (*print-level* *backtrace-print-level*)
+	     (*print-length* *backtrace-print-length*)
+	     (*print-circle* (null *print-level*)))
+        (map-stack-frames sd (lambda (fp context)
+                               (push (funcall function fp context) results))
+                          start end)
+        (nreverse results))
+      (let ((s (make-semaphore))
+            (res :none))
+        (process-interrupt process
+                           (lambda ()
+                             (ignore-errors (setq res (collect-stack-frames sd function start end)))
+                             (signal-semaphore s)))
+        (timed-wait-on-semaphore s 2) ;; give it 2 seconds before going to plan B...
+        (if (eq res :none)
+          (progn
+            (setf (stack-descriptor-interruptable-p sd) nil)
+            (collect-stack-frames sd function start end))
+          res)))))
+
+(defclass frame-descriptor ()
+  ((data :initarg :data :reader frame-descriptor-data)
+   (label :initarg :label :reader frame-descriptor-label)
+   (values :initarg :values :reader frame-descriptor-values)))
+
+(defun make-frame-descriptor (fp context)
+  (let* ((args (ccl:frame-supplied-arguments fp context))
+         (vars (ccl:frame-named-variables fp context))
+         (lfun (ccl:frame-function fp context)))
+    (make-instance 'frame-descriptor
+      :data (cons fp context)
+      :label (if lfun
+               (with-output-to-string (stream)
+                 (format stream "(~S" (or (ccl:function-name lfun) lfun))
+                 (if (eq args (ccl::%unbound-marker))
+                   (format stream " #<Unknown Arguments>")
+                   (loop for arg in args
+                     do (if (eq arg (ccl::%unbound-marker))
+                          (format stream " #<Unavailable>")
+                          (format stream " ~:['~;~]~s" (ccl::self-evaluating-p arg) arg))))
+                 (format stream ")"))
+               ":kernel")
+      :values (if lfun
+                (map 'vector
+                     (lambda (var.val)
+                       (destructuring-bind (var . val) var.val
+                         (let ((label (format nil "~:[~s~;~a~]: ~s"
+                                              (stringp var) var val)))
+                           (cons label var.val))))
+                     (cons `("Function" . ,lfun)
+                           (and (not (eq vars (ccl::%unbound-marker))) vars)))
+                ))))
+
+(defmethod stack-descriptor-frame ((sd stack-descriptor) index)
+  (let ((cache (stack-descriptor-frame-cache sd)))
+    (or (gethash index cache)
+        ;; get a bunch at once.
+        (let* ((segment-size (stack-descriptor-segment-size sd))
+               (start (- index (rem index segment-size)))
+               (end (+ start segment-size))
+               (frames (collect-stack-frames sd #'make-frame-descriptor start end)))
+          (loop for n upfrom start as frame in frames do (setf (gethash n cache) frame))
+          (gethash index cache)))))
+
+(defun frame-descriptor-function (frame)
+  (destructuring-bind (fp . context) (frame-descriptor-data frame)
+    (ccl:frame-function fp context)))
+
+;; Don't bother making first-class frame value descriptors = frame + index
+
+(defun frame-descriptor-value-count (frame)
+  (length (frame-descriptor-values frame)))
+
+(defun frame-descriptor-value-label (frame index)
+  (car (svref (frame-descriptor-values frame) index)))
+
+(defun frame-descriptor-value (frame index)
+  (destructuring-bind (var . val)
+                      (cdr (svref (frame-descriptor-values frame) index))
+    (values val var)))
+
+(defun backtrace-frame-default-action (frame &optional index)
+  (if index
+    (inspect (frame-descriptor-value frame index))
+    (multiple-value-bind (lfun pc) (frame-descriptor-function frame)
+      (when lfun
+        (let ((source (or (and pc (ccl:find-source-note-at-pc lfun pc))
+                          (ccl:function-source-note lfun))))
+          (if (source-note-p source)
+            (hemlock-ext:execute-in-file-view
+             (ccl:source-note-filename source)
+             (lambda  ()
+               (hemlock::move-to-source-note source)))
+            (hemlock::edit-definition lfun)))))))
+
+;; Cocoa layer
+
+;; General utils, should be moved elsewhere
+(defclass abstract-ns-lisp-string (ns:ns-string)
+    ()
+  (:metaclass ns:+ns-object))
+
+(defgeneric ns-lisp-string-string (abstract-ns-lisp-string))
+
+(objc:defmethod (#/length :<NSUI>nteger) ((self abstract-ns-lisp-string))
+    (length (ns-lisp-string-string self)))
+
+(objc:defmethod (#/characterAtIndex: :unichar) ((self abstract-ns-lisp-string) (index :<NSUI>nteger))
+  (char-code (char (ns-lisp-string-string self) index)))
+
+(defclass ns-lisp-string (abstract-ns-lisp-string)
+  ((lisp-string :initarg :string :reader ns-lisp-string-string))
+  (:metaclass ns:+ns-object))
+
+(defclass frame-label (abstract-ns-lisp-string)
+    ((frame-number  :foreign-type :int :accessor frame-label-number)
+     (controller :foreign-type :id :reader frame-label-controller))
+  (:metaclass ns:+ns-object))
+
+(defmethod frame-label-descriptor ((self frame-label))
+  (stack-descriptor-frame
+    (backtrace-controller-stack-descriptor (frame-label-controller self))
+    (frame-label-number self)))
+  
+(defmethod ns-lisp-string-string ((self frame-label))
+  (frame-descriptor-label (frame-label-descriptor self)))
+
+(objc:defmethod #/initWithFrameNumber:controller: ((self frame-label) (frame-number :int) controller)
+  (let* ((obj (#/init self)))
+    (unless (%null-ptr-p obj)
+      (setf (slot-value obj 'frame-number) frame-number
+            (slot-value obj 'controller) controller))
+    obj))
+
+
+(defclass item-label (abstract-ns-lisp-string)
+    ((frame-label :foreign-type :id :accessor item-label-label)
+     (index :foreign-type :int :accessor item-label-index))
+  (:metaclass ns:+ns-object))
+
+(defmethod ns-lisp-string-string ((self item-label))
+  (frame-descriptor-value-label (frame-label-descriptor (item-label-label self))
+                                (item-label-index self)))
+
+(objc:defmethod #/initWithFrameLabel:index: ((self item-label) the-frame-label (index :int))
+  (let* ((obj (#/init self)))
+    (unless (%null-ptr-p obj)
+      (setf (slot-value obj 'frame-label) the-frame-label
+            (slot-value obj 'index) index))
+    obj))
+
+(defclass backtrace-window-controller (ns:ns-window-controller)
+    ((context :initarg :context :reader backtrace-controller-context)
+     (stack-descriptor :initform nil :reader backtrace-controller-stack-descriptor)
+     (outline-view :foreign-type :id :reader backtrace-controller-outline-view))
+  (:metaclass ns:+ns-object))
+
+(defmethod backtrace-controller-process ((self backtrace-window-controller))
+  (let ((context (backtrace-controller-context self)))
+    (and context (ccl::tcr->process (ccl::bt.tcr context)))))
+
+(defmethod backtrace-controller-break-level ((self backtrace-window-controller))
+  (let ((context (backtrace-controller-context self)))
+    (and context (ccl::bt.break-level context))))
+
+(objc:defmethod #/windowNibName ((self backtrace-window-controller))
+  #@"backtrace")
+
+(objc:defmethod (#/close :void) ((self backtrace-window-controller))
+  (setf (slot-value self 'context) nil)
+  (call-next-method))
+
+(defmethod our-frame-label-p ((self backtrace-window-controller) thing)
+  (and (typep thing 'frame-label)
+       (eql self (frame-label-controller thing))))
+
+(def-cocoa-default *backtrace-font-name* :string #+darwin-target "Monaco"
+                   #-darwin-target "Courier" "Name of font used in backtrace views")
+(def-cocoa-default *backtrace-font-size* :float 9.0f0 "Size of font used in backtrace views")
+
+
+(objc:defmethod (#/windowDidLoad :void) ((self backtrace-window-controller))
+  (let* ((outline (slot-value self 'outline-view))
+         (font (default-font :name *backtrace-font-name* :size *backtrace-font-size*)))
+    (unless (%null-ptr-p outline)
+      (#/setTarget: outline self)
+      #-cocotron ; crashes
+      (#/setRowHeight: outline  (size-of-char-in-font font))
+      (#/setDoubleAction: outline (@selector #/backtraceDoubleClick:))
+      (#/setShouldCascadeWindows: self nil)
+      (let* ((columns (#/tableColumns outline)))
+        (dotimes (i (#/count columns))
+          (let* ((column (#/objectAtIndex:  columns i))
+                 (data-cell (#/dataCell column)))
+            (#/setEditable: data-cell nil)
+            (#/setFont: data-cell font)
+            (when (eql i 0)
+              (let* ((header-cell (#/headerCell column))
+                     (sd (backtrace-controller-stack-descriptor self))
+                     (break-condition (stack-descriptor-condition sd))
+                     (break-condition-string
+                      (let* ((*print-level* 5)
+                             (*print-length* 5)
+                             (*print-circle* t))
+                        (format nil "~a: ~a"
+                                (class-name (class-of break-condition))
+                                break-condition))))
+                (#/setFont: header-cell (default-font :name "Courier" :size 10 :attributes '(:bold)))
+                (#/setStringValue: header-cell (%make-nsstring break-condition-string))))))))
+    (let* ((window (#/window  self)))
+      (unless (%null-ptr-p window)
+        (let* ((process (backtrace-controller-process self))
+               (listener-window (if (typep process 'cocoa-listener-process)
+                                  (cocoa-listener-process-window process))))
+          (when listener-window
+            (let* ((listener-frame (#/frame listener-window))
+                   (backtrace-width (ns:ns-rect-width (#/frame window)))
+                   (new-x (- (+ (ns:ns-rect-x listener-frame)
+                                (/ (ns:ns-rect-width listener-frame) 2))
+                             (/ backtrace-width 2))))
+              (ns:with-ns-point (p new-x (+ (ns:ns-rect-y listener-frame) (ns:ns-rect-height listener-frame)))
+                (#/setFrameOrigin: window p))))
+          (#/setTitle:  window (%make-nsstring
+                                (format nil "Backtrace for ~a(~d), break level ~d"
+                                        (process-name process)
+                                        (process-serial-number process)
+                                        (backtrace-controller-break-level self)))))))))
+
+(objc:defmethod (#/continue: :void) ((self backtrace-window-controller) sender)
+  (declare (ignore sender))
+  (let ((process (backtrace-controller-process self)))
+    (when process (process-interrupt process #'continue))))
+
+(objc:defmethod (#/exitBreak: :void) ((self backtrace-window-controller) sender)
+  (declare (ignore sender))
+  (let ((process (backtrace-controller-process self)))
+    (when process (process-interrupt process #'abort-break))))
+
+(objc:defmethod (#/restarts: :void) ((self backtrace-window-controller) sender)
+  (let* ((context (backtrace-controller-context self)))
+    (when context
+      (#/showWindow: (restarts-controller-for-context context) sender))))
+
+(objc:defmethod (#/backtraceDoubleClick: :void)
+    ((self backtrace-window-controller) sender)
+  (let* ((row (#/clickedRow sender)))
+    (if (>= row 0)
+      (let* ((item (#/itemAtRow: sender row)))
+        (cond ((typep item 'frame-label)
+               (let ((frame (frame-label-descriptor item)))
+                 (backtrace-frame-default-action frame)))
+              ((typep item 'item-label)
+               (let* ((frame (frame-label-descriptor (item-label-label item)))
+                      (index (item-label-index item)))
+                 (backtrace-frame-default-action frame index))))))))
+
+(objc:defmethod (#/outlineView:isItemExpandable: :<BOOL>)
+    ((self backtrace-window-controller) view item)
+  (declare (ignore view))
+  (or (%null-ptr-p item)
+      (and (our-frame-label-p self item)
+           (> (frame-descriptor-value-count (frame-label-descriptor item)) 0))))
+
+(objc:defmethod (#/outlineView:numberOfChildrenOfItem: :<NSI>nteger)
+    ((self backtrace-window-controller) view item)
+    (declare (ignore view))
+    (let* ((sd (backtrace-controller-stack-descriptor self)))
+      (cond ((%null-ptr-p item)
+             (stack-descriptor-frame-count sd))
+            ((our-frame-label-p self item)
+             (let ((frame (stack-descriptor-frame sd (frame-label-number item))))
+               (frame-descriptor-value-count frame)))
+            (t -1))))
+
+(objc:defmethod #/outlineView:child:ofItem:
+    ((self backtrace-window-controller) view (index :<NSI>nteger) item)
+  (declare (ignore view))
+  (cond ((%null-ptr-p item)
+         (make-instance 'frame-label
+           :with-frame-number index
+           :controller self))
+        ((our-frame-label-p self item)
+         (make-instance 'item-label
+           :with-frame-label item
+           :index index))
+        (t (break) (%make-nsstring "Huh?"))))
+
+(objc:defmethod #/outlineView:objectValueForTableColumn:byItem:
+    ((self backtrace-window-controller) view column item)
+  (declare (ignore view column))
+  (if (%null-ptr-p item)
+    #@"Open this"
+    (%setf-macptr (%null-ptr) item)))
+
+(defmethod initialize-instance :after ((self backtrace-window-controller)
+                                       &key &allow-other-keys)
+  (setf (slot-value self 'stack-descriptor)
+        (make-stack-descriptor (backtrace-controller-context self))))
+
+(defun backtrace-controller-for-context (context)
+  (let ((bt (ccl::bt.dialog context)))
+    (when bt
+      (stack-descriptor-refresh (backtrace-controller-stack-descriptor bt)))
+    (or bt
+        (setf (ccl::bt.dialog context)
+              (make-instance 'backtrace-window-controller
+                :with-window-nib-name #@"backtrace"
+                :context context)))))
+
+#+debug
+(objc:defmethod (#/willLoad :void) ((self backtrace-window-controller))
+  (#_NSLog #@"will load %@" :address  (#/windowNibName self)))
+
+;; Called when current process is about to enter a breakloop
+(defmethod ui-object-enter-backtrace-context ((app ns:ns-application)
+                                              context)
+  (let* ((proc *current-process*))
+    (when (typep proc 'cocoa-listener-process)
+      (push context (cocoa-listener-process-backtrace-contexts proc)))))
+
+(defmethod ui-object-exit-backtrace-context ((app ns:ns-application)
+                                              context)
+  (let* ((proc *current-process*))
+    (when (typep proc 'cocoa-listener-process)
+      (when (eq context (car (cocoa-listener-process-backtrace-contexts proc)))
+        (setf (cocoa-listener-process-backtrace-contexts proc)
+              (cdr (cocoa-listener-process-backtrace-contexts proc)))
+        (let* ((btwindow (prog1 (ccl::bt.dialog context)
+                           (setf (ccl::bt.dialog context) nil)))
+               (restartswindow
+                (prog1 (car (ccl::bt.restarts context))
+                           (setf (ccl::bt.restarts context) nil))))
+          (when btwindow
+            (#/performSelectorOnMainThread:withObject:waitUntilDone: btwindow (@selector #/close)  +null-ptr+ t))
+          (when restartswindow
+            (#/performSelectorOnMainThread:withObject:waitUntilDone: restartswindow (@selector #/close)  +null-ptr+ t)))))))
+
+  
+
+
+
+
+
Index: /branches/new-random/cocoa-ide/cocoa-defaults.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-defaults.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-defaults.lisp	(revision 13309)
@@ -0,0 +1,145 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2004 Clozure Associates
+;;;   This file is part of OpenMCL.  
+;;;
+;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with OpenMCL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "GUI")
+
+(defstruct cocoa-default
+  symbol                                ; a lisp special variable
+  string                                ; an NSConstantString
+  type                                  ; a keyword
+  value                                 ; the "standard" initial value
+  doc                                   ; a doc string
+  change-hook                           ; an optional hook function
+  )
+
+(let* ((cocoa-defaults ()))
+  (defun %get-cocoa-default (name)
+    (find name cocoa-defaults :key #'cocoa-default-symbol))
+  (defun %put-cocoa-default (default)
+    (push default cocoa-defaults))
+  (defun cocoa-defaults () cocoa-defaults)
+  (defun %remove-cocoa-default (name)
+    (setq cocoa-defaults
+          (delete name cocoa-defaults :key #'cocoa-default-symbol)))
+  (defun %clear-cocoa-defaults () (setq cocoa-defaults nil)))
+
+(defun set-cocoa-default (name string type value doc &optional change-hook)
+  (check-type name symbol)
+  (check-type string ccl::objc-constant-string)
+  (check-type type keyword)
+  (check-type doc (or null string))
+  (%remove-cocoa-default name)
+  (%put-cocoa-default (make-cocoa-default :symbol name
+                                          :string string
+                                          :type type
+                                          :value value
+                                          :doc doc
+                                          :change-hook change-hook))
+  (if (eq type :color)
+    (apply #'color-values-to-nscolor value)
+    value))
+
+;;; Names which contain #\* confuse Cocoa Bindings.
+(defun objc-default-key (name)
+  (ccl::ns-constant-string (ccl::lisp-to-objc-message (list (make-symbol (remove #\* (string name)))))))
+  
+
+(defun %define-cocoa-default (name type value doc &optional change-hook)
+  (proclaim `(special ,name))
+  ;; Make the variable "GLOBAL": its value can be changed, but it can't
+  ;; have a per-thread binding.
+  (ccl::%symbol-bits name (logior (ash 1 ccl::$sym_vbit_global)
+				  (the fixnum (ccl::%symbol-bits name))))
+  (record-source-file name 'variable)
+  (setf (documentation name 'variable) doc)
+  (set name (set-cocoa-default name (objc-default-key name) type value doc change-hook))
+  name)
+  
+  
+
+(defmacro def-cocoa-default (name type value  doc &optional change-hook &environment env)
+  `(progn
+     (eval-when (:compile-toplevel)
+       (ccl::note-variable-info ',name :global ,env))
+    (declaim (special ,name))
+    (defloadvar ,name nil)
+    (%define-cocoa-default ',name  ',type ,value ',doc ,change-hook)))
+
+    
+(defun update-cocoa-defaults ()
+  (update-cocoa-defaults-list
+   (#/standardUserDefaults ns:ns-user-defaults)
+   (cocoa-defaults)))
+
+(defun update-cocoa-defaults-list (domain defaults)
+  (dolist (d defaults)
+    (let* ((name (cocoa-default-symbol d))
+           (type (cocoa-default-type d)) 
+           (key (ccl::objc-constant-string-nsstringptr (cocoa-default-string d))))
+      (let* ((hook (cocoa-default-change-hook d))
+             (old-value (symbol-value name)))
+        (case type
+          (:int
+           (set name (#/integerForKey: domain key)))
+          (:float
+           (set name (#/floatForKey: domain key)))
+          (:bool
+           (set name (#/boolForKey: domain key)))
+          (:string
+           (let* ((nsstring (#/stringForKey: domain key)))
+             (unless (%null-ptr-p nsstring)
+               (set name (lisp-string-from-nsstring nsstring)))))
+          ((:color :font)
+           #+cocotron
+           (let* ((value (cocoa-default-value d)))
+             (set name
+                  (ecase type
+                    (:color (apply #'color-values-to-nscolor value))
+                    (:font (funcall value)))))
+           #-cocotron
+           (let* ((data (#/dataForKey: domain key)))
+             (unless (%null-ptr-p data)
+               (set name (#/retain (#/unarchiveObjectWithData: ns:ns-unarchiver data)))))))
+        (when hook (funcall hook old-value (symbol-value name)))))))
+
+
+
+;;; Return an NSDictionary describing the "default" values of the defaults.
+(defun cocoa-defaults-initial-values ()
+  (let* ((defaults (cocoa-defaults))
+         (dict (make-instance 'ns:ns-mutable-dictionary
+                              :with-capacity (length defaults))))
+    (dolist (d defaults dict)
+      (let* ((value (cocoa-default-value d)))
+        (#/setObject:forKey: dict
+                             (case (cocoa-default-type d)                               
+                               (:color #-cocotron
+                                       (#/archivedDataWithRootObject:
+                                        ns:ns-archiver
+                                        (apply #'color-values-to-nscolor value))
+                                       #+cocotron
+                                       (apply #'color-values-to-nscolor value)
+                                       )
+			       (:font #-cocotron
+                                      (#/archivedDataWithRootObject:
+                                       ns:ns-archiver
+                                       (funcall value))
+                                      #+cocotron
+                                      (funcall value))
+                               (:bool (if value #@"YES" #@"NO"))
+                               (t
+                                (%make-nsstring (format nil "~a" (cocoa-default-value d)))))
+                             (ccl::objc-constant-string-nsstringptr (cocoa-default-string d)))))))
Index: /branches/new-random/cocoa-ide/cocoa-doc.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-doc.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-doc.lisp	(revision 13309)
@@ -0,0 +1,172 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+(def-cocoa-default *hyperspec-url-string* :string "http://www.lispworks.com/documentation/HyperSpec/" "HTTP URL for HyperSpec lookup")
+
+(defloadvar *hyperspec-root-url* nil)
+(defloadvar *hyperspec-map-sym-hash* nil)
+(defloadvar *hyperspec-map-sym-url* nil)
+
+(def-cocoa-default *hyperspec-lookup-enabled* :bool nil "enables hyperspec lookup"
+                   (lambda (old new)
+                     (unless (eq new old)
+                       (if new
+                         (setup-hyperspec-root-url)
+                         (progn
+                           (when *hyperspec-root-url*
+                             (#/release *hyperspec-root-url*))
+                           (setq *hyperspec-root-url* nil)
+                           (when *hyperspec-map-sym-url*
+                             (#/release *hyperspec-map-sym-url*))
+                           (setq *hyperspec-root-url* nil)
+                           (setq *hyperspec-map-sym-hash* nil))))))
+
+
+(defclass display-document (ns:ns-document)
+    ((text-view :foreign-type :id))
+  (:metaclass ns:+ns-object))
+
+(defclass url-delegate (ns:ns-object)
+    ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/textView:clickedOnLink:atIndex: :<BOOL>)
+    ((self url-delegate)
+     textview
+     link
+     (index :<NSUI>nteger))
+  (declare (ignorable link))
+  (let* ((attribute (#/attribute:atIndex:effectiveRange:
+                     (#/textStorage textview)
+                     #&NSLinkAttributeName
+                     index
+                     +null-ptr+)))
+    (if (typep attribute 'ns:ns-url)
+      (rlet ((dictp :id +null-ptr+))
+        (let* ((data (make-instance 'ns:ns-data :with-contents-of-url attribute))
+               (string (unless (%null-ptr-p data)
+                         (make-instance 'ns:ns-attributed-string 
+                                        :with-html data
+                                        :base-url attribute
+                                        :document-attributes dictp)))
+               (textstorage (#/textStorage textview))
+               (dict (pref dictp :id))
+               (title
+                #-cocotron
+                 (unless (%null-ptr-p dict)
+                        (#/valueForKey: dict #&NSTitleDocumentAttribute))))
+          (when title 
+            (#/setTitle: (#/window textview) title))
+          (when string
+            (#/beginEditing textstorage)
+            (#/replaceCharactersInRange:withAttributedString:
+             textstorage
+             (ns:make-ns-range 0 (#/length textstorage))
+             string)
+            (#/setSelectedRange: textview (ns:make-ns-range 0 0))
+            (#/endEditing textstorage)
+            (#/scrollRangeToVisible: textview (ns:make-ns-range 0 0)))))))
+  #$YES)
+
+(objc:defmethod (#/textView:shouldChangeTextInRange:replacementString: :<BOOL>)
+    ((self url-delegate)
+     textview
+     (range :<NSR>ange)
+     string)
+  (declare (ignorable textview range string))
+  nil)
+
+
+
+
+
+(objc:defmethod #/windowNibName ((self display-document))
+  #@"displaydoc")
+
+(objc:defmethod (#/windowControllerDidLoadNib: :void)
+    ((self display-document) controller)
+  (with-slots (text-view) self
+    (unless (%null-ptr-p text-view)
+      (#/setEditable: text-view t)
+      (#/setDelegate: text-view (make-instance 'url-delegate))))
+  (call-next-method controller))
+
+
+(defun hyperspec-root-url ()
+  (or *hyperspec-root-url*
+      (setq *hyperspec-root-url* (setup-hyperspec-root-url))))
+
+(defun setup-hyperspec-root-url ()
+  (make-instance 'ns:ns-url
+                 :with-string
+                 (%make-nsstring *hyperspec-url-string*)))
+
+(defun hyperspec-map-hash (document)
+  (or *hyperspec-map-sym-hash*
+      (rlet ((perror :id  +null-ptr+))
+        (let* ((map-url (make-instance 'ns:ns-url :with-string #@"Data/Map_Sym.txt" :relative-to-url (hyperspec-root-url)))
+               (data (make-instance 'ns:ns-data
+                                    :with-contents-of-url map-url
+                                    :options 0
+                                    :error perror)))
+          (let* ((err (pref perror :id)))
+            (unless (%null-ptr-p err)
+              (#/presentError: document err)
+              (return-from hyperspec-map-hash nil)))
+          (with-input-from-string (s (%str-from-ptr (#/bytes data) (#/length data)))
+            (let* ((hash (make-hash-table :test #'eq))
+                   (*package* (find-package "CL"))
+                   (eof (cons nil nil)))
+              (declare (dynamic-extent eof))
+              (loop
+                (let* ((sym (read s nil eof))
+                       (url (read-line s nil eof)))
+                  (when (eq sym eof)
+                    (return 
+                      (setq *hyperspec-map-sym-url* map-url
+                            *hyperspec-map-sym-hash* hash)))
+                  (setf (gethash sym hash) url)))))))))
+
+(defun lookup-hyperspec-symbol (symbol doc)
+  (let* ((relative-url (gethash symbol (hyperspec-map-hash doc))))
+    (when relative-url
+      (let* ((url (#/absoluteURL
+                   (make-instance 'ns:ns-url
+                                  :with-string (%make-nsstring relative-url)
+                                  :relative-to-url *hyperspec-map-sym-url*))))
+        (rlet ((pdocattrs :id +null-ptr+)
+               (perror :id  +null-ptr+))
+          (let* ((data (make-instance 'ns:ns-data
+                                      :with-contents-of-url url
+                                      :options 0
+                                      :error perror)))
+            (if (not (%null-ptr-p (pref perror :id)))
+              (progn
+                (#/presentError: doc (pref perror :id)))
+              (let* ((string (make-instance 'ns:ns-attributed-string
+                                            :with-html data
+                                            :base-url url
+                                            :document-attributes pdocattrs))
+                     (docattrs (pref pdocattrs :id))
+                     (title #+cocotron +null-ptr+
+                            #-cocotron
+                            (if (%null-ptr-p docattrs)
+                              +null-ptr+
+                              (#/objectForKey: docattrs #&NSTitleDocumentAttribute))))
+                (if (%null-ptr-p title)
+                  (setq title (%make-nsstring (string symbol))))
+                (#/newDisplayDocumentWithTitle:content:
+                 (#/sharedDocumentController ns:ns-document-controller)
+                 title
+                 string)))))))))
+                              
+
+
+                   
+                   
+                   
+                   
+                
Index: /branches/new-random/cocoa-ide/cocoa-editor.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-editor.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-editor.lisp	(revision 13309)
@@ -0,0 +1,3385 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+;;; In the double-float case, this is probably way too small.
+;;; Traditionally, it's (approximately) the point at which
+;;; a single-float stops being able to accurately represent
+;;; integral values.
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defconstant large-number-for-text (cgfloat 1.0f7)))
+
+(def-cocoa-default *editor-font* :font #'(lambda ()
+					   (#/fontWithName:size:
+					    ns:ns-font
+                                            #+darwin-target
+					    #@"Monaco"
+                                            #-darwin-target
+                                            #@"Courier"
+                                            10.0))
+		   "Default font for editor windows")
+
+(def-cocoa-default *editor-rows* :int 24 "Initial height of editor windows, in characters")
+(def-cocoa-default *editor-columns* :int 80 "Initial width of editor windows, in characters")
+
+(def-cocoa-default *editor-background-color* :color '(1.0 1.0 1.0 1.0) "Editor background color")
+(def-cocoa-default *wrap-lines-to-window* :bool nil
+		   "Soft wrap lines to window width")
+
+(def-cocoa-default *use-screen-fonts* :bool t "Use bitmap screen fonts when available")
+
+(def-cocoa-default *option-is-meta* :bool t "Use option key as meta?")
+
+(defgeneric hemlock-view (ns-object))
+
+(defmethod hemlock-view ((unknown t))
+  nil)
+
+(defgeneric hemlock-buffer (ns-object))
+
+(defmethod hemlock-buffer ((unknown t))
+  (let ((view (hemlock-view unknown)))
+    (when view (hi::hemlock-view-buffer view))))
+
+(defmacro nsstring-encoding-to-nsinteger (n)
+  (ccl::target-word-size-case
+   (32 `(ccl::u32->s32 ,n))
+   (64 n)))
+
+(defmacro nsinteger-to-nsstring-encoding (n)
+  (ccl::target-word-size-case
+   (32 `(ccl::s32->u32 ,n))
+   (64 n)))
+
+;;; Create a paragraph style, mostly so that we can set tabs reasonably.
+(defun rme-create-paragraph-style (font line-break-mode)
+  (let* ((p (make-instance 'ns:ns-mutable-paragraph-style))
+	 (charwidth (fround (nth-value 1 (size-of-char-in-font font)))))
+    (#/setLineBreakMode: p
+                         (ecase line-break-mode
+                           (:char #$NSLineBreakByCharWrapping)
+                           (:word #$NSLineBreakByWordWrapping)
+                           ;; This doesn't seem to work too well.
+                           ((nil) #$NSLineBreakByClipping)))
+    ;; Clear existing tab stops.
+    (#/setTabStops: p (#/array ns:ns-array))
+    ;; And set the "default tab interval".
+    (#/setDefaultTabInterval: p (* *tab-width* charwidth))
+    p))
+
+(defun rme-create-text-attributes (&key (font *editor-font*)
+				   (line-break-mode :char)
+				   (color nil)
+				   (obliqueness nil)
+				   (stroke-width nil))
+  (let* ((dict (make-instance 'ns:ns-mutable-dictionary :with-capacity 5)))
+    (#/setObject:forKey: dict (rme-create-paragraph-style font line-break-mode)
+			 #&NSParagraphStyleAttributeName)
+    (#/setObject:forKey: dict font #&NSFontAttributeName)
+    (when color
+      (#/setObject:forKey: dict color #&NSForegroundColorAttributeName))
+    (when stroke-width
+      (#/setObject:forKey: dict (#/numberWithFloat: ns:ns-number stroke-width)
+			   #&NSStrokeWidthAttributeName))
+    (when obliqueness
+      (#/setObject:forKey: dict (#/numberWithFloat: ns:ns-number obliqueness)
+			   #&NSObliquenessAttributeName))
+    dict))
+
+(defun rme-make-editor-style-map ()
+  (let* ((font *editor-font*)
+	 (fm (#/sharedFontManager ns:ns-font-manager))
+	 (bold-font (#/convertFont:toHaveTrait: fm font #$NSBoldFontMask))
+	 (oblique-font (#/convertFont:toHaveTrait: fm font #$NSItalicFontMask))
+	 (bold-oblique-font (#/convertFont:toHaveTrait:
+			     fm font (logior #$NSItalicFontMask
+					     #$NSBoldFontMask)))
+	 (colors (vector (#/blackColor ns:ns-color)))
+	 (fonts (vector font bold-font oblique-font bold-oblique-font))
+	 (styles (make-instance 'ns:ns-mutable-array)))
+    (dotimes (c (length colors))
+      (dotimes (i 4)
+	(let* ((mask (logand i 3))
+	       (f (svref fonts mask)))
+	  (#/addObject: styles 
+			(rme-create-text-attributes :font f
+						    :color (svref colors c)
+						    :obliqueness
+						    (if (logbitp 1 i)
+						      (when (eql f font)
+							0.15f0))
+						    :stroke-width
+						    (if (logbitp 0 i)
+						      (when (eql f font)
+							-10.0f0)))))))
+    styles))
+
+(defun make-editor-style-map ()
+  (rme-make-editor-style-map))
+
+#+nil
+(defun make-editor-style-map ()
+  (let* ((font-name *default-font-name*)
+	 (font-size *default-font-size*)
+         (font (default-font :name font-name :size font-size))
+         (bold-font (let* ((f (default-font :name font-name :size font-size :attributes '(:bold))))
+                      (unless (eql f font) f)))
+         (oblique-font (let* ((f (default-font :name font-name :size font-size :attributes '(:italic))))
+                      (unless (eql f font) f)))
+         (bold-oblique-font (let* ((f (default-font :name font-name :size font-size :attributes '(:bold :italic))))
+                      (unless (eql f font) f)))
+	 (color-class (find-class 'ns:ns-color))
+	 (colors (vector (#/blackColor color-class)))
+	 (styles (make-instance 'ns:ns-mutable-array
+                                :with-capacity (the fixnum (* 4 (length colors)))))
+         (bold-stroke-width -10.0f0)
+         (fonts (vector font (or bold-font font) (or oblique-font font) (or bold-oblique-font font)))
+         (real-fonts (vector font bold-font oblique-font bold-oblique-font))
+	 (s 0))
+    (declare (dynamic-extent fonts real-fonts colors))
+    (dotimes (c (length colors))
+      (dotimes (i 4)
+        (let* ((mask (logand i 3)))
+          (#/addObject: styles
+                        (create-text-attributes :font (svref fonts mask)
+                                                :color (svref colors c)
+                                                :obliqueness
+                                                (if (logbitp 1 i)
+                                                  (unless (svref real-fonts mask)
+                                                    0.15f0))
+                                                :stroke-width
+                                                (if (logbitp 0 i)
+                                                  (unless (svref real-fonts mask)
+                                                    bold-stroke-width)))))
+	(incf s)))
+    (#/retain styles)))
+
+(defun make-hemlock-buffer (&rest args)
+  (let* ((buf (apply #'hi::make-buffer args)))
+    (assert buf)
+    buf))
+
+;;; Define some key event modifiers and keysym codes
+
+(hi:define-modifier-bit #$NSShiftKeyMask "Shift")
+(hi:define-modifier-bit #$NSControlKeyMask "Control")
+(hi:define-modifier-bit #$NSAlternateKeyMask "Meta")
+(hi:define-modifier-bit #$NSAlphaShiftKeyMask "Lock")
+
+(hi:define-keysym-code :F1 #$NSF1FunctionKey)
+(hi:define-keysym-code :F2 #$NSF2FunctionKey)
+(hi:define-keysym-code :F3 #$NSF3FunctionKey)
+(hi:define-keysym-code :F4 #$NSF4FunctionKey)
+(hi:define-keysym-code :F5 #$NSF5FunctionKey)
+(hi:define-keysym-code :F6 #$NSF6FunctionKey)
+(hi:define-keysym-code :F7 #$NSF7FunctionKey)
+(hi:define-keysym-code :F8 #$NSF8FunctionKey)
+(hi:define-keysym-code :F9 #$NSF9FunctionKey)
+(hi:define-keysym-code :F10 #$NSF10FunctionKey)
+(hi:define-keysym-code :F11 #$NSF11FunctionKey)
+(hi:define-keysym-code :F12 #$NSF12FunctionKey)
+(hi:define-keysym-code :F13 #$NSF13FunctionKey)
+(hi:define-keysym-code :F14 #$NSF14FunctionKey)
+(hi:define-keysym-code :F15 #$NSF15FunctionKey)
+(hi:define-keysym-code :F16 #$NSF16FunctionKey)
+(hi:define-keysym-code :F17 #$NSF17FunctionKey)
+(hi:define-keysym-code :F18 #$NSF18FunctionKey)
+(hi:define-keysym-code :F19 #$NSF19FunctionKey)
+(hi:define-keysym-code :F20 #$NSF20FunctionKey)
+(hi:define-keysym-code :F21 #$NSF21FunctionKey)
+(hi:define-keysym-code :F22 #$NSF22FunctionKey)
+(hi:define-keysym-code :F23 #$NSF23FunctionKey)
+(hi:define-keysym-code :F24 #$NSF24FunctionKey)
+(hi:define-keysym-code :F25 #$NSF25FunctionKey)
+(hi:define-keysym-code :F26 #$NSF26FunctionKey)
+(hi:define-keysym-code :F27 #$NSF27FunctionKey)
+(hi:define-keysym-code :F28 #$NSF28FunctionKey)
+(hi:define-keysym-code :F29 #$NSF29FunctionKey)
+(hi:define-keysym-code :F30 #$NSF30FunctionKey)
+(hi:define-keysym-code :F31 #$NSF31FunctionKey)
+(hi:define-keysym-code :F32 #$NSF32FunctionKey)
+(hi:define-keysym-code :F33 #$NSF33FunctionKey)
+(hi:define-keysym-code :F34 #$NSF34FunctionKey)
+(hi:define-keysym-code :F35 #$NSF35FunctionKey)
+
+;;; Upper right key bank.
+;;;
+(hi:define-keysym-code :Printscreen #$NSPrintScreenFunctionKey)
+;; Couldn't type scroll lock.
+(hi:define-keysym-code :Pause #$NSPauseFunctionKey)
+
+;;; Middle right key bank.
+;;;
+(hi:define-keysym-code :Insert #$NSInsertFunctionKey)
+(hi:define-keysym-code :Del #$NSDeleteFunctionKey)
+(hi:define-keysym-code :Home #$NSHomeFunctionKey)
+(hi:define-keysym-code :Pageup #$NSPageUpFunctionKey)
+(hi:define-keysym-code :End #$NSEndFunctionKey)
+(hi:define-keysym-code :Pagedown #$NSPageDownFunctionKey)
+
+;;; Arrows.
+;;;
+(hi:define-keysym-code :Leftarrow #$NSLeftArrowFunctionKey)
+(hi:define-keysym-code :Uparrow #$NSUpArrowFunctionKey)
+(hi:define-keysym-code :Downarrow #$NSDownArrowFunctionKey)
+(hi:define-keysym-code :Rightarrow #$NSRightArrowFunctionKey)
+
+;;;
+
+;(hi:define-keysym-code :linefeed 65290)
+
+
+
+
+
+
+;;; We want to display a Hemlock buffer in a "pane" (an on-screen
+;;; view) which in turn is presented in a "frame" (a Cocoa window).  A
+;;; 1:1 mapping between frames and panes seems to fit best into
+;;; Cocoa's document architecture, but we should try to keep the
+;;; concepts separate (in case we come up with better UI paradigms.)
+;;; Each pane has a modeline (which describes attributes of the
+;;; underlying document); each frame has an echo area (which serves
+;;; to display some commands' output and to provide multi-character
+;;; input.)
+
+
+;;; I'd pretty much concluded that it wouldn't be possible to get the
+;;; Cocoa text system (whose storage model is based on NSString
+;;; NSMutableAttributedString, NSTextStorage, etc.) to get along with
+;;; Hemlock, and (since the whole point of using Hemlock was to be
+;;; able to treat an editor buffer as a rich lisp data structure) it
+;;; seemed like it'd be necessary to toss the higher-level Cocoa text
+;;; system and implement our own scrolling, redisplay, selection
+;;; ... code.
+;;;
+;;; Mikel Evins pointed out that NSString and friends were
+;;; abstract classes and that there was therefore no reason (in
+;;; theory) not to implement a thin wrapper around a Hemlock buffer
+;;; that made it act like an NSString.  As long as the text system can
+;;; ask a few questions about the NSString (its length and the
+;;; character and attributes at a given location), it's willing to
+;;; display the string in a scrolling, mouse-selectable NSTextView;
+;;; as long as Hemlock tells the text system when and how the contents
+;;; of the abstract string changes, Cocoa will handle the redisplay
+;;; details.
+;;;
+
+
+
+;;; Hemlock-buffer-string objects:
+
+(defclass hemlock-buffer-string (ns:ns-string)
+    ((cache :initform nil :initarg :cache :accessor hemlock-buffer-string-cache))
+  (:metaclass ns:+ns-object))
+
+(defmethod hemlock-buffer ((self hemlock-buffer-string))
+  (let ((cache (hemlock-buffer-string-cache self)))
+    (when cache
+      (hemlock-buffer cache))))
+
+;;; Cocoa wants to treat the buffer as a linear array of characters;
+;;; Hemlock wants to treat it as a doubly-linked list of lines, so
+;;; we often have to map between an absolute position in the buffer
+;;; and a relative position on a line.  We can certainly do that
+;;; by counting the characters in preceding lines every time that we're
+;;; asked, but we're often asked to map a sequence of nearby positions
+;;; and wind up repeating a lot of work.  Caching the results of that
+;;; work seems to speed things up a bit in many cases; this data structure
+;;; is used in that process.  (It's also the only way to get to the
+;;; actual underlying Lisp buffer from inside the network of text-system
+;;; objects.)
+
+(defstruct buffer-cache 
+  buffer				; the hemlock buffer
+  buflen				; length of buffer, if known
+  workline				; cache for character-at-index
+  workline-offset			; cached offset of workline
+  workline-length			; length of cached workline
+  workline-start-font-index		; current font index at start of workline
+  )
+
+(defmethod hemlock-buffer ((self buffer-cache))
+  (buffer-cache-buffer self))
+
+;;; Initialize (or reinitialize) a buffer cache, so that it points
+;;; to the buffer's first line (which is the only line whose
+;;; absolute position will never change).  Code which modifies the
+;;; buffer generally has to call this, since any cached information
+;;; might be invalidated by the modification.
+
+(defun reset-buffer-cache (d &optional (buffer (buffer-cache-buffer d)
+						buffer-p))
+  (when buffer-p (setf (buffer-cache-buffer d) buffer))
+  (let* ((hi::*current-buffer* buffer)
+         (workline (hi::mark-line
+		    (hi::buffer-start-mark buffer))))
+    (setf (buffer-cache-buflen d) (hemlock-buffer-length buffer)
+	  (buffer-cache-workline-offset d) 0
+	  (buffer-cache-workline d) workline
+	  (buffer-cache-workline-length d) (hi::line-length workline)
+	  (buffer-cache-workline-start-font-index d) 0)
+    d))
+
+
+(defun adjust-buffer-cache-for-insertion (display pos n)
+  (if (buffer-cache-workline display)
+    (let* ((hi::*current-buffer* (buffer-cache-buffer display)))
+      (if (> (buffer-cache-workline-offset display) pos)
+        (incf (buffer-cache-workline-offset display) n)
+        (when (>= (+ (buffer-cache-workline-offset display)
+                     (buffer-cache-workline-length display))
+                  pos)
+          (setf (buffer-cache-workline-length display)
+                (hi::line-length (buffer-cache-workline display)))))
+      (incf (buffer-cache-buflen display) n))
+    (reset-buffer-cache display)))
+
+          
+           
+
+;;; Update the cache so that it's describing the current absolute
+;;; position.
+
+(defun update-line-cache-for-index (cache index)
+  (let* ((buffer (buffer-cache-buffer cache))
+         (hi::*current-buffer* buffer)
+         (line (or
+		(buffer-cache-workline cache)
+		(progn
+		  (reset-buffer-cache cache)
+		  (buffer-cache-workline cache))))
+	 (pos (buffer-cache-workline-offset cache))
+	 (len (buffer-cache-workline-length cache))
+	 (moved nil))
+    (loop
+      (when (and (>= index pos)
+		   (< index (1+ (+ pos len))))
+	  (let* ((idx (- index pos)))
+	    (when moved
+	      (setf (buffer-cache-workline cache) line
+		    (buffer-cache-workline-offset cache) pos
+		    (buffer-cache-workline-length cache) len))
+	    (return (values line idx))))
+      (setq moved t)
+      (if (< index pos)
+	(setq line (hi::line-previous line)
+	      len (hi::line-length line)
+	      pos (1- (- pos len)))
+	(setq line (hi::line-next line)
+	      pos (1+ (+ pos len))
+	      len (hi::line-length line))))))
+
+;;; Ask Hemlock to count the characters in the buffer.
+(defun hemlock-buffer-length (buffer)
+  (let* ((hi::*current-buffer* buffer))
+    (hemlock::count-characters (hemlock::buffer-region buffer))))
+
+;;; Find the line containing (or immediately preceding) index, which is
+;;; assumed to be less than the buffer's length.  Return the character
+;;; in that line or the trailing #\newline, as appropriate.
+(defun hemlock-char-at-index (cache index)
+  (let* ((hi::*current-buffer* (buffer-cache-buffer cache)))
+    (multiple-value-bind (line idx) (update-line-cache-for-index cache index)
+      (let* ((len (hemlock::line-length line)))
+        (if (< idx len)
+          (hemlock::line-character line idx)
+          #\newline)))))
+
+;;; Given an absolute position, move the specified mark to the appropriate
+;;; offset on the appropriate line.
+(defun move-hemlock-mark-to-absolute-position (mark cache abspos)
+  ;; TODO: figure out if updating the cache matters, and if not, use hi:move-to-absolute-position.
+  (let* ((hi::*current-buffer* (buffer-cache-buffer cache)))
+    (hi::move-to-absolute-position mark abspos)
+    #+old
+    (multiple-value-bind (line idx) (update-line-cache-for-index cache abspos)
+      #+debug
+      (#_NSLog #@"Moving point from current pos %d to absolute position %d"
+               :int (hi:mark-absolute-position mark)
+               :int abspos)
+      (hemlock::move-to-position mark idx line)
+      #+debug
+      (#_NSLog #@"Moved mark to %d" :int (hi:mark-absolute-position mark)))))
+
+;;; Return the length of the abstract string, i.e., the number of
+;;; characters in the buffer (including implicit newlines.)
+(objc:defmethod (#/length :<NSUI>nteger) ((self hemlock-buffer-string))
+  (let* ((cache (hemlock-buffer-string-cache self)))
+    (or (buffer-cache-buflen cache)
+        (setf (buffer-cache-buflen cache)
+              (let* ((buffer (buffer-cache-buffer cache)))
+		(hemlock-buffer-length buffer))))))
+
+
+
+;;; Return the character at the specified index (as a :unichar.)
+
+(objc:defmethod (#/characterAtIndex: :unichar)
+    ((self hemlock-buffer-string) (index :<NSUI>nteger))
+  #+debug
+  (#_NSLog #@"Character at index: %d" :<NSUI>nteger index)
+  (char-code (hemlock-char-at-index (hemlock-buffer-string-cache self) index)))
+
+(objc:defmethod (#/getCharacters:range: :void)
+    ((self hemlock-buffer-string)
+     (buffer (:* :unichar))
+     (r :<NSR>ange))
+  (let* ((cache (hemlock-buffer-string-cache self))
+         (index (ns:ns-range-location r))
+         (length (ns:ns-range-length r))
+         (hi::*current-buffer* (buffer-cache-buffer cache)))
+    #+debug
+    (#_NSLog #@"get characters: %d/%d"
+             :<NSUI>nteger index
+             :<NSUI>nteger length)
+    (multiple-value-bind (line idx) (update-line-cache-for-index cache index)
+      (let* ((len (hemlock::line-length line)))
+        (do* ((i 0 (1+ i)))
+             ((= i length))
+          (cond ((< idx len)
+                 (setf (paref buffer (:* :unichar) i)
+                       (char-code (hemlock::line-character line idx)))
+                 (incf idx))
+                (t
+                 (setf (paref buffer (:* :unichar) i)
+                       (char-code #\Newline)
+                       line (hi::line-next line)
+                       len (if line (hi::line-length line) 0)
+                       idx 0))))))))
+
+
+(objc:defmethod (#/getLineStart:end:contentsEnd:forRange: :void)
+    ((self hemlock-buffer-string)
+     (startptr (:* :<NSUI>nteger))
+     (endptr (:* :<NSUI>nteger))
+     (contents-endptr (:* :<NSUI>nteger))
+     (r :<NSR>ange))
+  (let* ((cache (hemlock-buffer-string-cache self))
+         (index (pref r :<NSR>ange.location))
+         (length (pref r :<NSR>ange.length))
+	 (hi::*current-buffer* (buffer-cache-buffer cache)))
+    #+debug
+    (#_NSLog #@"get line start: %d/%d"
+             :unsigned index
+             :unsigned length)
+    (update-line-cache-for-index cache index)
+    (unless (%null-ptr-p startptr)
+      ;; Index of the first character in the line which contains
+      ;; the start of the range.
+      (setf (pref startptr :<NSUI>nteger)
+            (buffer-cache-workline-offset cache)))
+    (unless (%null-ptr-p endptr)
+      ;; Index of the newline which terminates the line which
+      ;; contains the start of the range.
+      (setf (pref endptr :<NSUI>nteger)
+            (+ (buffer-cache-workline-offset cache)
+               (buffer-cache-workline-length cache))))
+    (unless (%null-ptr-p contents-endptr)
+      ;; Index of the newline which terminates the line which
+      ;; contains the start of the range.
+      (unless (zerop length)
+        (update-line-cache-for-index cache (+ index length)))
+      (setf (pref contents-endptr :<NSUI>nteger)
+            (1+ (+ (buffer-cache-workline-offset cache)
+                   (buffer-cache-workline-length cache)))))))
+
+;;; For debugging, mostly: make the printed representation of the string
+;;; referenence the named Hemlock buffer.
+(objc:defmethod #/description ((self hemlock-buffer-string))
+  (let* ((cache (hemlock-buffer-string-cache self))
+	 (b (buffer-cache-buffer cache)))
+    (with-cstrs ((s (format nil "~a" b)))
+      (#/stringWithFormat: ns:ns-string #@"<%s for %s>" (#_object_getClassName self) s))))
+
+
+
+
+;;; hemlock-text-storage objects
+(defclass hemlock-text-storage (ns:ns-text-storage)
+    ((string :foreign-type :id)
+     (hemlock-string :foreign-type :id)
+     (edit-count :foreign-type :int)
+     (mirror :foreign-type :id)
+     (styles :foreign-type :id)
+     (selection-set-by-search :foreign-type :<BOOL>))
+  (:metaclass ns:+ns-object))
+(declaim (special hemlock-text-storage))
+
+(defmethod hemlock-buffer ((self hemlock-text-storage))
+  (let ((string (slot-value self 'hemlock-string)))
+    (unless (%null-ptr-p string)
+      (hemlock-buffer string))))
+
+;;; This is only here so that calls to it can be logged for debugging.
+#+debug
+(objc:defmethod (#/lineBreakBeforeIndex:withinRange: :<NSUI>nteger)
+    ((self hemlock-text-storage)
+     (index :<NSUI>nteger)
+     (r :<NSR>ange))
+  (#_NSLog #@"Line break before index: %d within range: %@"
+           :unsigned index
+           :id (#_NSStringFromRange r))
+  (call-next-method index r))
+
+
+
+
+;;; Return true iff we're inside a "beginEditing/endEditing" pair
+(objc:defmethod (#/editingInProgress :<BOOL>) ((self hemlock-text-storage))
+  ;; This is meaningless outside the event thread, since you can't tell what
+  ;; other edit-count changes have already been queued up for execution on
+  ;; the event thread before it gets to whatever you might queue up next.
+  (assume-cocoa-thread)
+  (> (slot-value self 'edit-count) 0))
+
+(defmethod assume-not-editing ((ts hemlock-text-storage))
+  #+debug NIL (assert (eql (slot-value ts 'edit-count) 0)))
+
+(defun textstorage-note-insertion-at-position (self pos n)
+  (ns:with-ns-range (r pos 0)
+    (#/edited:range:changeInLength: self #$NSTextStorageEditedCharacters r n)
+    (setf (ns:ns-range-length r) n)
+    (#/edited:range:changeInLength: self #$NSTextStorageEditedAttributes r 0)))
+
+
+
+;;; This runs on the main thread; it synchronizes the "real" NSMutableAttributedString
+;;; with the hemlock string and informs the textstorage of the insertion.
+(objc:defmethod (#/noteHemlockInsertionAtPosition:length: :void) ((self hemlock-text-storage)
+                                                                  (pos :<NSI>nteger)
+                                                                  (n :<NSI>nteger)
+                                                                  (extra :<NSI>nteger))
+  (declare (ignorable extra))
+  (assume-cocoa-thread)
+  (let* ((mirror (#/mirror self))
+	 (hemlock-string (#/hemlockString self))
+         (display (hemlock-buffer-string-cache hemlock-string))
+         (buffer (buffer-cache-buffer display))
+         (hi::*current-buffer* buffer)
+         (attributes (buffer-active-font-attributes buffer))
+         (document (#/document self))
+	 (undo-mgr (and document (#/undoManager document))))
+    #+debug 
+    (#_NSLog #@"insert: pos = %ld, n = %ld" :long pos :long n)
+    ;; We need to update the hemlock string mirror here so that #/substringWithRange:
+    ;; will work on the hemlock buffer string.
+    (adjust-buffer-cache-for-insertion display pos n)
+    (update-line-cache-for-index display pos)
+    (let* ((replacestring (#/substringWithRange: hemlock-string (ns:make-ns-range pos n))))
+      (ns:with-ns-range (replacerange pos 0)
+        (#/replaceCharactersInRange:withString:
+         mirror replacerange replacestring))
+      (when (and undo-mgr (not (#/isUndoing undo-mgr)))
+        (#/replaceCharactersAtPosition:length:withString:
+	 (#/prepareWithInvocationTarget: undo-mgr self)
+	 pos n #@"")))
+    (#/setAttributes:range: mirror attributes (ns:make-ns-range pos n))
+    (textstorage-note-insertion-at-position self pos n)))
+
+(objc:defmethod (#/noteHemlockDeletionAtPosition:length: :void) ((self hemlock-text-storage)
+                                                                 (pos :<NSI>nteger)
+                                                                 (n :<NSI>nteger)
+                                                                 (extra :<NSI>nteger))
+  (declare (ignorable extra))
+  #+debug
+  (#_NSLog #@"delete: pos = %ld, n = %ld" :long pos :long n)
+  (ns:with-ns-range (range pos n)
+    (let* ((mirror (#/mirror self))
+	   (deleted-string (#/substringWithRange: (#/string mirror) range))
+	   (document (#/document self))
+	   (undo-mgr (and document (#/undoManager document)))
+	   (display (hemlock-buffer-string-cache (#/hemlockString self))))
+      ;; It seems to be necessary to call #/edited:range:changeInLength: before
+      ;; deleting from the mirror attributed string.  It's not clear whether this
+      ;; is also true of insertions and modifications.
+      (#/edited:range:changeInLength: self (logior #$NSTextStorageEditedCharacters
+						   #$NSTextStorageEditedAttributes)
+				      range (- n))
+      (#/deleteCharactersInRange: mirror range)
+      (when (and undo-mgr (not (#/isUndoing undo-mgr)))
+        (#/replaceCharactersAtPosition:length:withString:
+	 (#/prepareWithInvocationTarget: undo-mgr self)
+	 pos 0 deleted-string))
+      (reset-buffer-cache display)
+      (update-line-cache-for-index display pos))))
+
+(objc:defmethod (#/noteHemlockModificationAtPosition:length: :void) ((self hemlock-text-storage)
+                                                                     (pos :<NSI>nteger)
+                                                                     (n :<NSI>nteger)
+                                                                     (extra :<NSI>nteger))
+  (declare (ignorable extra))
+  #+debug
+  (#_NSLog #@"modify: pos = %ld, n = %ld" :long pos :long n)
+  (ns:with-ns-range (range pos n)
+    (let* ((hemlock-string (#/hemlockString self))
+	   (mirror (#/mirror self))
+	   (deleted-string (#/substringWithRange: (#/string mirror) range))
+	   (document (#/document self))
+	   (undo-mgr (and document (#/undoManager document))))
+      (#/replaceCharactersInRange:withString:
+       mirror range (#/substringWithRange: hemlock-string range))
+      (#/edited:range:changeInLength: self (logior #$NSTextStorageEditedCharacters
+                                                   #$NSTextStorageEditedAttributes) range 0)
+      (when (and undo-mgr (not (#/isUndoing undo-mgr)))
+        (#/replaceCharactersAtPosition:length:withString:
+	 (#/prepareWithInvocationTarget: undo-mgr self)
+	 pos n deleted-string)))))
+
+(objc:defmethod (#/noteHemlockAttrChangeAtPosition:length: :void) ((self hemlock-text-storage)
+                                                                   (pos :<NSI>nteger)
+                                                                   (n :<NSI>nteger)
+                                                                   (fontnum :<NSI>nteger))
+  (ns:with-ns-range (range pos n)
+    (#/setAttributes:range: (#/mirror self) (#/objectAtIndex: (#/styles self) fontnum) range)
+    (#/edited:range:changeInLength: self #$NSTextStorageEditedAttributes range 0)))
+
+
+(defloadvar *buffer-change-invocation*
+    (with-autorelease-pool
+        (#/retain
+                   (#/invocationWithMethodSignature: ns:ns-invocation
+                                                     (#/instanceMethodSignatureForSelector:
+                                                      hemlock-text-storage
+                                            (@selector #/noteHemlockInsertionAtPosition:length:))))))
+
+(defstatic *buffer-change-invocation-lock* (make-lock))
+
+         
+         
+(objc:defmethod (#/beginEditing :void) ((self hemlock-text-storage))
+  (assume-cocoa-thread)
+  (with-slots (edit-count) self
+    #+debug
+    (#_NSLog #@"begin-editing")
+    (incf edit-count)
+    #+debug
+    (#_NSLog #@"after beginEditing on %@ edit-count now = %d" :id self :int edit-count)
+    (call-next-method)))
+
+(objc:defmethod (#/endEditing :void) ((self hemlock-text-storage))
+  (assume-cocoa-thread)
+  (with-slots (edit-count) self
+    #+debug
+    (#_NSLog #@"end-editing")
+    (call-next-method)
+    (assert (> edit-count 0))
+    (decf edit-count)
+    #+debug
+    (#_NSLog #@"after endEditing on %@, edit-count now = %d" :id self :int edit-count)))
+
+
+
+  
+
+;;; Access the string.  It'd be nice if this was a generic function;
+;;; we could have just made a reader method in the class definition.
+
+
+
+(objc:defmethod #/string ((self hemlock-text-storage))
+  (slot-value self 'string))
+
+(objc:defmethod #/mirror ((self hemlock-text-storage))
+  (slot-value self 'mirror))
+
+(objc:defmethod #/hemlockString ((self hemlock-text-storage))
+  (slot-value self 'hemlock-string))
+
+(objc:defmethod #/styles ((self hemlock-text-storage))
+  (slot-value self 'styles))
+
+(objc:defmethod #/document ((self hemlock-text-storage))
+  (or
+   (let* ((string (#/hemlockString self)))
+     (unless (%null-ptr-p string)
+       (let* ((cache (hemlock-buffer-string-cache string)))
+         (when cache
+           (let* ((buffer (buffer-cache-buffer cache)))
+             (when buffer
+               (hi::buffer-document buffer)))))))
+   +null-ptr+))
+
+
+#-cocotron
+(objc:defmethod #/initWithString: ((self hemlock-text-storage) s)
+  (setq s (%inc-ptr s 0))
+  (let* ((newself (#/init self))
+         (styles (make-editor-style-map))
+         (mirror (make-instance ns:ns-mutable-attributed-string
+                                   :with-string s
+                                   :attributes (#/objectAtIndex: styles 0))))
+    (declare (type hemlock-text-storage newself))
+    (setf (slot-value newself 'styles) styles)
+    (setf (slot-value newself 'hemlock-string) s)
+    (setf (slot-value newself 'mirror) mirror)
+    (setf (slot-value newself 'string) (#/retain (#/string mirror)))
+    newself))
+
+#+cocotron
+(objc:defmethod #/initWithString: ((self hemlock-text-storage) s)
+  (setq s (%inc-ptr s 0))
+  (let* ((styles (make-editor-style-map))
+         (mirror (make-instance ns:ns-mutable-attributed-string
+                                   :with-string s
+                                   :attributes (#/objectAtIndex: styles 0)))
+         (string (#/retain (#/string mirror)))
+         (newself (call-next-method string)))
+    (declare (type hemlock-text-storage newself))
+    (setf (slot-value newself 'styles) styles)
+    (setf (slot-value newself 'hemlock-string) s)
+    (setf (slot-value newself 'mirror) mirror)
+    (setf (slot-value newself 'string) string)
+    newself))
+
+;;; Should generally only be called after open/revert.
+(objc:defmethod (#/updateMirror :void) ((self hemlock-text-storage))
+  (with-slots (hemlock-string mirror styles) self
+    (#/replaceCharactersInRange:withString: mirror (ns:make-ns-range 0 (#/length mirror)) hemlock-string)
+    (#/setAttributes:range: mirror (#/objectAtIndex: styles 0) (ns:make-ns-range 0 (#/length mirror)))))
+
+;;; This is the only thing that's actually called to create a
+;;; hemlock-text-storage object.  (It also creates the underlying
+;;; hemlock-buffer-string.)
+(defun make-textstorage-for-hemlock-buffer (buffer)
+  (make-instance 'hemlock-text-storage
+                 :with-string
+                 (make-instance
+                  'hemlock-buffer-string
+                  :cache
+                  (reset-buffer-cache
+                   (make-buffer-cache)
+                   buffer))))
+
+(objc:defmethod #/attributesAtIndex:effectiveRange:
+    ((self hemlock-text-storage) (index :<NSUI>nteger) (rangeptr (* :<NSR>ange)))
+  #+debug
+  (#_NSLog #@"Attributes at index: %lu storage %@" :<NSUI>nteger index :id self)
+  (with-slots (mirror styles) self
+    (when (>= index (#/length mirror))
+      (#_NSLog #@"Bounds error - Attributes at index: %lu  edit-count: %d mirror: %@ layout: %@" :<NSUI>nteger index ::unsigned (slot-value self 'edit-count) :id mirror :id (#/objectAtIndex: (#/layoutManagers self) 0))
+      (ccl::dbg))
+    (let* ((attrs (#/attributesAtIndex:effectiveRange: mirror index rangeptr)))
+      (when (eql 0 (#/count attrs))
+        (#_NSLog #@"No attributes ?")
+        (ns:with-ns-range (r)
+          (#/attributesAtIndex:longestEffectiveRange:inRange:
+           mirror index r (ns:make-ns-range 0 (#/length mirror)))
+          (setq attrs (#/objectAtIndex: styles 0))
+          (#/setAttributes:range: mirror attrs r)))
+      attrs)))
+
+(objc:defmethod (#/replaceCharactersAtPosition:length:withString: :void)
+    ((self hemlock-text-storage) (pos <NSUI>nteger) (len <NSUI>nteger) string)
+  (let* ((document (#/document self))
+	 (undo-mgr (and document (#/undoManager document))))
+    (when (and undo-mgr (not (#/isRedoing undo-mgr)))
+      (let ((replaced-string (#/substringWithRange: (#/hemlockString self) (ns:make-ns-range pos len))))
+	(#/replaceCharactersAtPosition:length:withString:
+	 (#/prepareWithInvocationTarget: undo-mgr self)
+	 pos (#/length string) replaced-string)))
+    (ns:with-ns-range (r pos len)
+      (#/beginEditing self)
+      (unwind-protect
+           (#/replaceCharactersInRange:withString: self r string)
+        (#/endEditing self)))))
+
+;; In theory (though not yet in practice) we allow for a buffer to be shown in multiple
+;; windows, and any change to a buffer through one window has to be reflected in all of
+;; them.  Once hemlock really supports multiple views of a buffer, it will have some
+;; mechanims to ensure that.
+;; In Cocoa, we get some messages for the buffer (i.e. the document or the textstorage)
+;; with no reference to a view.  There used to be code here that tried to do special-
+;; case stuff for all views on the buffer, but that's not necessary, because as long
+;; as hemlock doesn't support it, there will only be one view, and as soon as hemlock
+;; does support it, will take care of updating all other views.  So all we need is to
+;; get our hands on one of the views and do whatever it is through it.
+(defun front-view-for-buffer (buffer)
+  (loop
+     with win-arr =  (#/orderedWindows *NSApp*)
+     for i from 0 below (#/count win-arr) as w = (#/objectAtIndex: win-arr i)
+     thereis (and (eq (hemlock-buffer w) buffer) (hemlock-view w))))
+
+
+;;; Modify the hemlock buffer; don't change attributes.
+(objc:defmethod (#/replaceCharactersInRange:withString: :void)
+    ((self hemlock-text-storage) (r :<NSR>ange) string)
+  (let* ((buffer (hemlock-buffer self))
+         (hi::*current-buffer* buffer)
+         (position (pref r :<NSR>ange.location))
+	 (length (pref r :<NSR>ange.length))
+	 (lisp-string (if (> (#/length string) 0) (lisp-string-from-nsstring string)))
+         (view (front-view-for-buffer buffer))
+         (edit-count (slot-value self 'edit-count)))
+    ;; #!#@#@* find panel neglects to call #/beginEditing / #/endEditing.
+    (when (eql 0 edit-count)
+      (#/beginEditing self))
+    (unwind-protect
+         (hi::with-mark ((m (hi::buffer-point buffer)))
+           (hi::move-to-absolute-position m position)
+           (when (> length 0)
+             (hi::delete-characters m length))
+           (when lisp-string
+             (hi::insert-string m lisp-string)))
+      (when (eql 0 edit-count)
+        (#/endEditing self)))
+    (when view
+      (setf (hi::hemlock-view-quote-next-p view) nil))))
+
+(objc:defmethod (#/setAttributes:range: :void) ((self hemlock-text-storage)
+                                                attributes
+                                                (r :<NSR>ange))
+  #+debug
+  (#_NSLog #@"Set attributes: %@ at %d/%d" :id attributes :int (pref r :<NSR>ange.location) :int (pref r :<NSR>ange.length))
+  (with-slots (mirror) self
+    (#/setAttributes:range: mirror attributes r)
+      #+debug
+      (#_NSLog #@"Assigned attributes = %@" :id (#/attributesAtIndex:effectiveRange: mirror (pref r :<NSR>ange.location) +null-ptr+))))
+
+(defun for-each-textview-using-storage (textstorage f)
+  (let* ((layouts (#/layoutManagers textstorage)))
+    (unless (%null-ptr-p layouts)
+      (dotimes (i (#/count layouts))
+	(let* ((layout (#/objectAtIndex: layouts i))
+	       (containers (#/textContainers layout)))
+	  (unless (%null-ptr-p containers)
+	    (dotimes (j (#/count containers))
+	      (let* ((container (#/objectAtIndex: containers j))
+		     (tv (#/textView container)))
+		(funcall f tv)))))))))
+
+;;; Again, it's helpful to see the buffer name when debugging.
+(objc:defmethod #/description ((self hemlock-text-storage))
+  (#/stringWithFormat: ns:ns-string #@"%s : string %@" (#_object_getClassName self) (slot-value self 'hemlock-string)))
+
+(defun close-hemlock-textstorage (ts)
+  (declare (type hemlock-text-storage ts))
+  (when (slot-exists-p ts 'styles)
+    (with-slots (styles) ts
+      (#/release styles)
+      (setq styles +null-ptr+)))
+  (let* ((hemlock-string (slot-value ts 'hemlock-string)))
+    (setf (slot-value ts 'hemlock-string) +null-ptr+)
+    
+    (unless (%null-ptr-p hemlock-string)
+      (let* ((cache (hemlock-buffer-string-cache hemlock-string))
+             (buffer (if cache (buffer-cache-buffer cache))))
+        (when buffer
+          (setf (buffer-cache-buffer cache) nil
+                (slot-value hemlock-string 'cache) nil
+                (hi::buffer-document buffer) nil)
+          (when (eq buffer hi::*current-buffer*)
+	    (setf hi::*current-buffer* nil))
+	  (hi::delete-buffer buffer))))))
+
+
+
+;;; Mostly experimental, so that we can see what happens when a 
+;;; real typesetter is used.
+#-cocotron
+(progn
+(defclass hemlock-ats-typesetter (ns:ns-ats-typesetter)
+    ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:nextGlyphIndex: :void)
+    ((self hemlock-ats-typesetter)
+     layout-manager
+     (start-index :<NSUI>nteger)
+     (max-lines :<NSUI>nteger)
+     (next-index (:* :<NSUI>nteger)))
+  (#_NSLog #@"layoutGlyphs: start = %d, maxlines = %d" :int start-index :int max-lines)
+  (call-next-method layout-manager start-index max-lines next-index))
+)
+
+
+;;; An abstract superclass of the main and echo-area text views.
+(defclass hemlock-textstorage-text-view (ns::ns-text-view)
+    ((paren-highlight-left-pos :foreign-type #>NSUInteger :accessor text-view-paren-highlight-left-pos)
+     (paren-highlight-right-pos :foreign-type #>NSUInteger :accessor text-view-paren-highlight-right-pos)
+     (paren-highlight-color-attribute :foreign-type :id :accessor text-view-paren-highlight-color)
+     (paren-highlight-enabled :foreign-type #>BOOL :accessor text-view-paren-highlight-enabled)
+     (peer :foreign-type :id))
+  (:metaclass ns:+ns-object))
+(declaim (special hemlock-textstorage-text-view))
+
+#| causes more problems than it solves.
+   removed until a better implementation manifests itself --me
+(objc:defmethod (#/performDragOperation: #>BOOL)
+    ((self hemlock-textstorage-text-view)
+     (sender :id))
+  (let* ((pboard (#/draggingPasteboard sender))
+         (pbTypes (#/arrayWithObjects: ns:ns-array #&NSFilenamesPboardType
+                                       +null-ptr+))
+         (available-type (#/availableTypeFromArray: pboard pbTypes)))
+    (if (%null-ptr-p available-type)
+        (progn (log-debug "No data available of type NSFilenamesPboardType")
+               (call-next-method sender))
+        (let* ((plist (#/propertyListForType: pboard #&NSFilenamesPboardType)))
+          (cond
+            ;; we found NSFilenamesPboardType and it's an array of pathnames
+            ((#/isKindOfClass: plist ns:ns-array)
+             (with-autorelease-pool
+               (let* ((strings-for-dropped-objects 
+                       (mapcar (lambda (d) 
+                                 (if (#/isKindOfClass: d ns:ns-string)
+                                     (ccl::lisp-string-from-nsstring d)
+                                     (#/description d)))
+                               (list-from-ns-array plist)))
+                      (canonical-dropped-paths 
+                       (mapcar (lambda (s) 
+                                 (if (and (probe-file s)
+                                          (directoryp s))
+                                     (ccl::ensure-directory-pathname s)
+                                     s))
+                               strings-for-dropped-objects))
+                      (dropstr (if (= (length canonical-dropped-paths) 1)
+                                   (with-output-to-string (out)
+                                     (format out "~S~%" (first canonical-dropped-paths)))
+                                   nil)))
+                 ;; TODO: insert them in the window
+                 (if dropstr
+                     (let* ((hview (hemlock-view self))
+                            (buf (hi:hemlock-view-buffer hview))
+                            (point (hi::buffer-point buf))
+                            (hi::*current-buffer* buf))
+                       (hi::insert-string point dropstr)
+                       #$YES)
+                     #$NO))))
+            ;; we found NSFilenamesPboardType, but didn't get an array of pathnames; huh???
+            (t (log-debug "hemlock-textstorage-text-view received an unrecognized data type in a drag operation: '~S'"
+                          (#/description plist))
+               (call-next-method sender)))))))
+|#
+
+(defmethod hemlock-view ((self hemlock-textstorage-text-view))
+  (let ((frame (#/window self)))
+    (unless (%null-ptr-p frame)
+      (hemlock-view frame))))
+
+(defmethod activate-hemlock-view ((self hemlock-textstorage-text-view))
+  (assume-cocoa-thread)
+  (let* ((the-hemlock-frame (#/window self)))
+    #+debug (log-debug "Activating ~s" self)
+    (with-slots ((echo peer)) self
+      (deactivate-hemlock-view echo))
+    (#/setEditable: self t)
+    (#/makeFirstResponder: the-hemlock-frame self)))
+
+(defmethod deactivate-hemlock-view ((self hemlock-textstorage-text-view))
+  (assume-cocoa-thread)
+  #+debug (log-debug "deactivating ~s" self)
+  (assume-not-editing self)
+  (#/setSelectable: self nil)
+  (disable-paren-highlight self))
+
+
+
+      
+
+(defmethod eventqueue-abort-pending-p ((self hemlock-textstorage-text-view))
+  ;; Return true if cmd-. is in the queue.  Not sure what to do about c-g:
+  ;; would have to distinguish c-g from c-q c-g or c-q c-q c-g etc.... Maybe
+  ;; c-g will need to be synchronous meaning just end current command,
+  ;; while cmd-. is the real abort.
+  #|
+   (let* ((now (#/dateWithTimeIntervalSinceNow: ns:ns-date 0.0d0)))
+    (loop (let* ((event (#/nextEventMatchingMask:untilDate:inMode:dequeue:
+			 target (logior #$whatever) now #&NSDefaultRunLoopMode t)))
+	    (when (%null-ptr-p event) (return)))))
+  "target" can either be an NSWindow or the global shared application object;
+  |#
+  nil)
+
+(defvar *buffer-being-edited* nil)
+
+#-darwin-target
+(objc:defmethod (#/hasMarkedText #>BOOL) ((self hemlock-textstorage-text-view))
+  nil)
+
+(objc:defmethod (#/keyDown: :void) ((self hemlock-textstorage-text-view) event)
+  #+debug (#_NSLog #@"Key down event in %@  = %@" :id self :address event)
+  (let* ((view (hemlock-view self))
+	 ;; quote-p means handle characters natively
+	 (quote-p (and view (hi::hemlock-view-quote-next-p view))))
+    #+debug (log-debug "~&quote-p ~s event ~s" quote-p event)
+    (cond ((or (null view) (#/hasMarkedText self) (eq quote-p :native))
+	   (when (and quote-p (not (eq quote-p :native)))	;; see ticket:461
+	     (setf (hi::hemlock-view-quote-next-p view) nil))
+	   (call-next-method event))
+	  ((not (eventqueue-abort-pending-p self))
+	   (let ((hemlock-key (nsevent-to-key-event event quote-p)))
+	     (if (and hemlock-key
+                      (not (hi:native-key-event-p hemlock-key)))
+               (progn
+                 (#/setHiddenUntilMouseMoves: ns:ns-cursor t)
+                 (hi::handle-hemlock-event view hemlock-key))
+	       (call-next-method event)))))))
+
+(defmethod hi::handle-hemlock-event :around ((view hi:hemlock-view) event)
+  (declare (ignore event))
+  (with-autorelease-pool
+   (call-next-method)))
+
+(defconstant +shift-event-mask+ (hi:key-event-modifier-mask "Shift"))
+
+;;; Translate a keyDown NSEvent to a Hemlock key-event.
+(defun nsevent-to-key-event (event quote-p)
+  (let* ((modifiers (#/modifierFlags event)))
+    (unless (logtest #$NSCommandKeyMask modifiers)
+      (let* ((native-chars (#/characters event))
+	     (native-len (if (%null-ptr-p native-chars)
+			   0
+			   (#/length native-chars)))
+	     (native-c (and (eql 1 native-len)
+			    (#/characterAtIndex: native-chars 0)))
+	     (option-p (logtest #$NSAlternateKeyMask modifiers)))
+	;; If a standalone dead key (e.g. ^'` on a French keyboard,) was pressed,
+	;; reverse the meaning of quote-p, i.e. use the system meaning if NOT quoted.
+	;; (I have no idea what makes standalone dead keys somehow different from
+	;; non-standalone dead keys).
+	(when (and (not option-p) (eql 0 native-len))
+	  (setq quote-p (not quote-p)))
+	(let ((c (if (or quote-p
+			 (and option-p
+			      (or (not *option-is-meta*)
+                                  #-cocotron
+				  (and native-c
+				       (ccl::valid-char-code-p native-c)
+				       (standard-char-p (code-char (the ccl::valid-char-code native-c)))))
+			      (setq quote-p t)))
+		   native-c
+		   (let ((chars (#/charactersIgnoringModifiers event)))
+		     (and (not (%null-ptr-p chars))
+			  (eql 1 (#/length chars))
+			  (#/characterAtIndex: chars 0))))))
+	  (when c
+	    (let ((bits 0)
+		  (useful-modifiers (logandc2 modifiers
+					      (logior
+					       ;;#$NSShiftKeyMask
+					       #$NSAlphaShiftKeyMask))))
+	      (unless quote-p
+		(dolist (map hi:*modifier-translations*)
+		  (when (logtest useful-modifiers (car map))
+		    (setq bits (logior bits
+				       (hi:key-event-modifier-mask (cdr map)))))))
+	      (let* ((char (code-char c)))
+		(when (and char (alpha-char-p char))
+		  (setq bits (logandc2 bits +shift-event-mask+)))
+		(when (logtest #$NSAlphaShiftKeyMask modifiers)
+		  (setf c (char-code (char-upcase char)))))
+	      (hi:make-key-event c bits))))))))
+
+;; For now, this is only used to abort i-search.  All actual mouse handling is done
+;; by Cocoa.   In the future might want to allow users to extend via hemlock, e.g.
+;; to implement mouse-copy.
+;; Also -- shouldn't this happen on mouse up?
+(objc:defmethod (#/mouseDown: :void) ((self hemlock-textstorage-text-view) event)
+  ;; If no modifier keys are pressed, send hemlock a no-op.
+  ;; (Or almost a no-op - this does an update-hemlock-selection as a side-effect)
+  (unless (logtest #$NSDeviceIndependentModifierFlagsMask (#/modifierFlags event))
+    (let* ((view (hemlock-view self)))
+      (when view
+	(unless (eventqueue-abort-pending-p self)
+	  (hi::handle-hemlock-event view #k"leftdown")))))
+  (call-next-method event))
+
+(defmethod assume-not-editing ((tv hemlock-textstorage-text-view))
+  (assume-not-editing (#/textStorage tv)))
+
+(objc:defmethod (#/changeColor: :void) ((self hemlock-textstorage-text-view)
+                                        sender)
+  (declare (ignorable sender))
+  #+debug (#_NSLog #@"Change color to = %@" :id (#/color sender)))
+
+(def-cocoa-default *layout-text-in-background* :bool t "When true, do text layout when idle.")
+
+(objc:defmethod (#/layoutManager:didCompleteLayoutForTextContainer:atEnd: :void)
+    ((self hemlock-textstorage-text-view) layout cont (flag :<BOOL>))
+  (declare (ignorable cont flag))
+  #+debug (#_NSLog #@"layout complete: container = %@, atend = %d" :id cont :int (if flag 1 0))
+  (unless *layout-text-in-background*
+    (#/setDelegate: layout +null-ptr+)
+    (#/setBackgroundLayoutEnabled: layout nil)))
+
+(defloadvar *paren-highlight-background-color* ())
+
+(defun paren-highlight-background-color ()
+  (or *paren-highlight-background-color*
+      (setq *paren-highlight-background-color*
+            (#/retain (#/colorWithCalibratedRed:green:blue:alpha:
+                       ns:ns-color
+                       .3
+                       .875
+                       .8125
+                       1.0)))))
+                                                        
+
+
+(defmethod remove-paren-highlight ((self hemlock-textstorage-text-view))
+  #-cocotron
+  (let* ((left (text-view-paren-highlight-left-pos self))
+         (right (text-view-paren-highlight-right-pos self)))
+    (ns:with-ns-range  (char-range left 1)
+      (let* ((layout (#/layoutManager self)))
+        (#/removeTemporaryAttribute:forCharacterRange: 
+         layout #&NSBackgroundColorAttributeName 
+         char-range)
+        (setf (pref char-range #>NSRange.location) right)
+        (#/removeTemporaryAttribute:forCharacterRange: 
+         layout #&NSBackgroundColorAttributeName 
+         char-range)))))
+
+(defmethod disable-paren-highlight ((self hemlock-textstorage-text-view))
+  (when (eql (text-view-paren-highlight-enabled self) #$YES)
+    (setf (text-view-paren-highlight-enabled self) #$NO)
+    (remove-paren-highlight self)))
+
+
+(defmethod compute-temporary-attributes ((self hemlock-textstorage-text-view))
+  #-cocotron
+  (let* ((container (#/textContainer self))
+         ;; If there's a containing scroll view, use its contentview         
+         ;; Otherwise, just use the current view.
+         (scrollview (#/enclosingScrollView self))
+         (contentview (if (%null-ptr-p scrollview) self (#/contentView scrollview)))
+         (rect (#/bounds contentview))
+         (layout (#/layoutManager container))
+         (glyph-range (#/glyphRangeForBoundingRect:inTextContainer:
+                       layout rect container))
+         (char-range (#/characterRangeForGlyphRange:actualGlyphRange:
+                      layout glyph-range +null-ptr+))
+         (start (ns:ns-range-location char-range))
+         (length (ns:ns-range-length char-range)))
+    (when (> length 0)
+      ;; Remove all temporary attributes from the character range
+      (#/removeTemporaryAttribute:forCharacterRange:
+       layout #&NSForegroundColorAttributeName char-range)
+      (#/removeTemporaryAttribute:forCharacterRange:
+       layout #&NSBackgroundColorAttributeName char-range)
+      (let* ((ts (#/textStorage self))
+             (cache (hemlock-buffer-string-cache (slot-value ts 'hemlock-string)))
+             (hi::*current-buffer* (buffer-cache-buffer cache)))
+        (multiple-value-bind (start-line start-offset)
+                             (update-line-cache-for-index cache start)
+          (let* ((end-line (update-line-cache-for-index cache (+ start length))))
+            (set-temporary-character-attributes
+             layout
+             (- start start-offset)
+             start-line
+             (hi::line-next end-line))))))
+    (when (eql #$YES (text-view-paren-highlight-enabled self))
+      (let* ((background #&NSBackgroundColorAttributeName)
+             (paren-highlight-left (text-view-paren-highlight-left-pos self))
+             (paren-highlight-right (text-view-paren-highlight-right-pos self))
+             (paren-highlight-color (text-view-paren-highlight-color self))
+	     (attrs (#/dictionaryWithObject:forKey: ns:ns-dictionary
+						    paren-highlight-color
+						    background)))
+        (#/addTemporaryAttributes:forCharacterRange:
+         layout attrs (ns:make-ns-range paren-highlight-left 1))
+        (#/addTemporaryAttributes:forCharacterRange:
+         layout attrs (ns:make-ns-range paren-highlight-right 1))))))
+
+(defmethod update-paren-highlight ((self hemlock-textstorage-text-view))
+  (disable-paren-highlight self)
+  (let* ((buffer (hemlock-buffer self)))
+    (when (and buffer (string= (hi::buffer-major-mode buffer) "Lisp"))
+      (let* ((hi::*current-buffer* buffer)
+             (point (hi::buffer-point buffer)))
+        #+debug (#_NSLog #@"Syntax check for paren-highlighting")
+        (update-buffer-package (hi::buffer-document buffer) buffer)
+        (cond ((eql (hi::next-character point) #\()
+               (hemlock::pre-command-parse-check point)
+               (when (hemlock::valid-spot point t)
+                 (hi::with-mark ((temp point))
+                   (when (hemlock::list-offset temp 1)
+                     #+debug (#_NSLog #@"enable paren-highlight, forward")
+                     (setf (text-view-paren-highlight-right-pos self)
+                           (1- (hi:mark-absolute-position temp))
+                           (text-view-paren-highlight-left-pos self)
+                           (hi::mark-absolute-position point)
+                           (text-view-paren-highlight-enabled self) #$YES)))))
+              ((eql (hi::previous-character point) #\))
+               (hemlock::pre-command-parse-check point)
+               (when (hemlock::valid-spot point nil)
+                 (hi::with-mark ((temp point))
+                   (when (hemlock::list-offset temp -1)
+                     #+debug (#_NSLog #@"enable paren-highlight, backward")
+                     (setf (text-view-paren-highlight-left-pos self)
+                           (hi:mark-absolute-position temp)
+                           (text-view-paren-highlight-right-pos self)
+                           (1- (hi:mark-absolute-position point))
+                           (text-view-paren-highlight-enabled self) #$YES))))))
+        (compute-temporary-attributes self)))))
+
+
+
+;;; Set and display the selection at pos, whose length is len and whose
+;;; affinity is affinity.  This should never be called from any Cocoa
+;;; event handler; it should not call anything that'll try to set the
+;;; underlying buffer's point and/or mark
+
+(objc:defmethod (#/updateSelection:length:affinity: :void)
+    ((self hemlock-textstorage-text-view)
+     (pos :int)
+     (length :int)
+     (affinity :<NSS>election<A>ffinity))
+  (assume-cocoa-thread)
+  (when (eql length 0)
+    (update-paren-highlight self))
+  (let* ((buffer (hemlock-buffer self)))
+    (setf (hi::buffer-selection-set-by-command buffer) (> length 0)))
+  (rlet ((range :ns-range :location pos :length length))
+    (ccl::%call-next-objc-method self
+				 hemlock-textstorage-text-view
+				 (@selector #/setSelectedRange:affinity:stillSelecting:)
+				 '(:void :<NSR>ange :<NSS>election<A>ffinity :<BOOL>)
+				 range
+				 affinity
+				 nil)
+    (assume-not-editing self)
+    (when (> length 0)
+      (let* ((ts (#/textStorage self)))
+	(with-slots (selection-set-by-search) ts
+	  (when (prog1 (eql #$YES selection-set-by-search)
+		  (setq selection-set-by-search #$NO))
+	    (highlight-search-selection self pos length)))))
+    ))
+
+(defloadvar *can-use-show-find-indicator-for-range*
+    (#/instancesRespondToSelector: ns:ns-text-view (@selector "showFindIndicatorForRange:")))
+
+;;; Add transient highlighting to a selection established via a search
+;;; primitive, if the OS supports it.
+(defun highlight-search-selection (tv pos length)
+  (when *can-use-show-find-indicator-for-range*
+    (ns:with-ns-range (r pos length)
+      (objc-message-send tv "showFindIndicatorForRange:" :<NSR>ange r :void))))
+  
+;;; A specialized NSTextView. The NSTextView is part of the "pane"
+;;; object that displays buffers.
+(defclass hemlock-text-view (hemlock-textstorage-text-view)
+    ((pane :foreign-type :id :accessor text-view-pane)
+     (char-width :foreign-type :<CGF>loat :accessor text-view-char-width)
+     (line-height :foreign-type :<CGF>loat :accessor text-view-line-height))
+  (:metaclass ns:+ns-object))
+(declaim (special hemlock-text-view))
+
+
+(defloadvar *lisp-string-color* (#/blueColor ns:ns-color))
+(defloadvar *lisp-comment-color* (#/brownColor ns:ns-color))
+
+;;; LAYOUT is an NSLayoutManager in which we'll set temporary character
+;;; attrubutes before redisplay.
+;;; POS is the absolute character position of the start of START-LINE.
+;;; END-LINE is either EQ to START-LNE (in the degenerate case) or
+;;; follows it in the buffer; it may be NIL and is the exclusive
+;;; end of a range of lines
+;;; HI::*CURRENT-BUFFER* is bound to the buffer containing START-LINE
+;;; and END-LINE
+(defun set-temporary-character-attributes (layout pos start-line end-line)
+  (ns:with-ns-range (range)
+    (let* ((color-attribute #&NSForegroundColorAttributeName)
+           (string-color  *lisp-string-color* )
+           (comment-color *lisp-comment-color*))
+      (hi::with-mark ((m (hi::buffer-start-mark hi::*current-buffer*)))
+        (hi::line-start m start-line)
+        (hi::pre-command-parse-check m))
+      (do ((p pos (+ p (1+ (hi::line-length line))))
+           (line start-line (hi::line-next line)))
+          ((eq line end-line))
+        (let* ((parse-info (getf (hi::line-plist line) 'hemlock::lisp-info))
+               (last-end 0))
+          (when parse-info
+            (dolist (r (hemlock::lisp-info-ranges-to-ignore parse-info))
+              (destructuring-bind (istart . iend) r
+                (let* ((attr (if (= istart 0)
+                               (hemlock::lisp-info-begins-quoted parse-info)
+                               (if (< last-end istart)
+                                 (hi:character-attribute :lisp-syntax
+                                                         (hi::line-character line (1- istart)))
+                                 :comment)))
+                       (type (case attr
+                               ((:char-quote :symbol-quote) nil)
+                               (:string-quote :string)
+                               (t :comment)))
+                       (start (+ p istart))
+                       (len (- iend istart)))
+                  (when type
+                    (when (eq type :string)
+                      (decf start)
+                      (incf len 2))
+                    (setf (ns:ns-range-location range) start
+                          (ns:ns-range-length range) len)
+                    (let ((attrs (#/dictionaryWithObject:forKey:
+                                  ns:ns-dictionary
+                                  (if (eq type :string) string-color comment-color)
+                                  color-attribute)))
+                      (#/addTemporaryAttributes:forCharacterRange:
+                       layout attrs range)))
+                  (setq last-end iend))))))))))
+
+#+no
+(objc:defmethod (#/drawRect: :void) ((self hemlock-text-view) (rect :<NSR>ect))
+  ;; Um, don't forget to actually draw the view..
+  (call-next-method  rect))
+
+
+(defmethod hemlock-view ((self hemlock-text-view))
+  (let ((pane (text-view-pane self)))
+    (when pane (hemlock-view pane))))
+
+
+
+(objc:defmethod (#/evalSelection: :void) ((self hemlock-text-view) sender)
+  (declare (ignore sender))
+  ;; TODO: this should just invoke editor-evaluate-region-command instead of reinventing the wheel.
+  (let* ((buffer (hemlock-buffer self))
+         (package-name (hi::variable-value 'hemlock::current-package :buffer buffer))
+         (pathname (hi::buffer-pathname buffer))
+         ;; Cocotron issue 380: NSTextView doesn't implement #/selectedRanges and
+         ;;  #/setSelectedRanges: methods.
+         #-cocotron (ranges (#/selectedRanges self))
+         #+cocotron (ranges (#/arrayWithObject: ns:ns-array 
+                                                (#/valueWithRange: ns:ns-value
+                                                                   (#/selectedRange self))))
+         (text (#/string self)))
+    (dotimes (i (#/count ranges))
+      (let* ((r (#/rangeValue (#/objectAtIndex: ranges i)))
+             (s (#/substringWithRange: text r))
+             (o (ns:ns-range-location r)))
+        (setq s (lisp-string-from-nsstring s))
+        (ui-object-eval-selection *NSApp* (list package-name pathname s o))))))
+
+(objc:defmethod (#/evalAll: :void) ((self hemlock-text-view) sender)
+  (declare (ignore sender))
+  (let* ((buffer (hemlock-buffer self))
+         (package-name (hi::variable-value 'hemlock::default-package :buffer buffer))
+         (pathname (hi::buffer-pathname buffer))
+         (s (lisp-string-from-nsstring (#/string self))))
+    (ui-object-eval-selection *NSApp* (list package-name pathname s))))
+
+(objc:defmethod (#/loadBuffer: :void) ((self hemlock-text-view) sender)
+  (declare (ignore sender))
+  (let* ((buffer (hemlock-buffer self))
+         (package-name (hi::variable-value 'hemlock::default-package :buffer buffer))
+         (pathname (hi::buffer-pathname buffer)))
+    (ui-object-load-buffer *NSApp* (list package-name pathname))))
+
+(objc:defmethod (#/compileBuffer: :void) ((self hemlock-text-view) sender)
+  (declare (ignore sender))
+  (let* ((buffer (hemlock-buffer self))
+         (package-name (hi::variable-value 'hemlock::default-package :buffer buffer))
+         (pathname (hi::buffer-pathname buffer)))
+    (ui-object-compile-buffer *NSApp* (list package-name pathname))))
+
+(objc:defmethod (#/compileAndLoadBuffer: :void) ((self hemlock-text-view) sender)
+  (declare (ignore sender))
+  (let* ((buffer (hemlock-buffer self))
+         (package-name (hi::variable-value 'hemlock::default-package :buffer buffer))
+         (pathname (hi::buffer-pathname buffer)))
+    (ui-object-compile-and-load-buffer *NSApp* (list package-name pathname))))
+
+(defloadvar *text-view-context-menu* ())
+
+(defun text-view-context-menu ()
+  (or *text-view-context-menu*
+      (setq *text-view-context-menu*
+            (#/retain
+             (let* ((menu (make-instance 'ns:ns-menu :with-title #@"Menu")))
+               (#/addItemWithTitle:action:keyEquivalent:
+                menu #@"Cut" (@selector #/cut:) #@"")
+               (#/addItemWithTitle:action:keyEquivalent:
+                menu #@"Copy" (@selector #/copy:) #@"")
+               (#/addItemWithTitle:action:keyEquivalent:
+                menu #@"Paste" (@selector #/paste:) #@"")
+               ;; Separator
+               (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+               (#/addItemWithTitle:action:keyEquivalent:
+                menu #@"Background Color ..." (@selector #/changeBackgroundColor:) #@"")
+               (#/addItemWithTitle:action:keyEquivalent:
+                menu #@"Text Color ..." (@selector #/changeTextColor:) #@"")
+
+               menu)))))
+
+
+
+
+
+(objc:defmethod (#/changeBackgroundColor: :void)
+    ((self hemlock-text-view) sender)
+  (let* ((colorpanel (#/sharedColorPanel ns:ns-color-panel))
+         (color (#/backgroundColor self)))
+    (#/close colorpanel)
+    (#/setAction: colorpanel (@selector #/updateBackgroundColor:))
+    (#/setColor: colorpanel color)
+    (#/setTarget: colorpanel self)
+    (#/setContinuous: colorpanel nil)
+    (#/orderFrontColorPanel: *NSApp* sender)))
+
+
+
+(objc:defmethod (#/updateBackgroundColor: :void)
+    ((self hemlock-text-view) sender)
+  (when (#/isVisible sender)
+    (let* ((color (#/color sender)))
+      (unless (typep self 'echo-area-view)
+        (let* ((window (#/window self))
+               (echo-view (unless (%null-ptr-p window)
+                            (slot-value window 'echo-area-view))))
+          (when echo-view (#/setBackgroundColor: echo-view color))))
+      #+debug (#_NSLog #@"Updating backgroundColor to %@, sender = %@" :id color :id sender)
+      (#/setBackgroundColor: self color))))
+
+(objc:defmethod (#/changeTextColor: :void)
+    ((self hemlock-text-view) sender)
+  (let* ((colorpanel (#/sharedColorPanel ns:ns-color-panel))
+         (textstorage (#/textStorage self))
+         (color (#/objectForKey:
+                 (#/objectAtIndex: (slot-value textstorage 'styles) 0)
+                 #&NSForegroundColorAttributeName)))
+    (#/close colorpanel)
+    (#/setAction: colorpanel (@selector #/updateTextColor:))
+    (#/setColor: colorpanel color)
+    (#/setTarget: colorpanel self)
+    (#/setContinuous: colorpanel nil)
+    (#/orderFrontColorPanel: *NSApp* sender)))
+
+
+
+
+
+
+   
+(objc:defmethod (#/updateTextColor: :void)
+    ((self hemlock-textstorage-text-view) sender)
+  (unwind-protect
+      (progn
+	(#/setUsesFontPanel: self t)
+	(ccl::%call-next-objc-method
+	 self
+	 hemlock-textstorage-text-view
+         (@selector #/changeColor:)
+         '(:void :id)
+         sender))
+    (#/setUsesFontPanel: self nil))
+  (#/setNeedsDisplay: self t))
+   
+(objc:defmethod (#/updateTextColor: :void)
+    ((self hemlock-text-view) sender)
+  (let* ((textstorage (#/textStorage self))
+         (styles (slot-value textstorage 'styles))
+         (newcolor (#/color sender)))
+    (dotimes (i 4)
+      (let* ((dict (#/objectAtIndex: styles i)))
+        (#/setValue:forKey: dict newcolor #&NSForegroundColorAttributeName)))
+    (call-next-method sender)))
+
+
+
+(defmethod text-view-string-cache ((self hemlock-textstorage-text-view))
+  (hemlock-buffer-string-cache (#/hemlockString (#/textStorage self))))
+
+#-cocotron                             ; for now, small struct return FFI issue
+
+(objc:defmethod (#/selectionRangeForProposedRange:granularity: :ns-range)
+    ((self hemlock-textstorage-text-view)
+     (proposed :ns-range)
+     (g :<NSS>election<G>ranularity))
+  #+debug
+  (#_NSLog #@"Granularity = %d" :int g)
+  (objc:returning-foreign-struct (r)
+     (block HANDLED
+       (let* ((index (ns:ns-range-location proposed))  
+              (length (ns:ns-range-length proposed))
+              (textstorage (#/textStorage self)))
+         (when (and (eql 0 length)      ; not extending existing selection
+                    (or (not (eql g #$NSSelectByCharacter))
+                        (and (eql index (#/length textstorage))
+                             (let* ((event (#/currentEvent (#/window self))))
+                               (and (eql (#/type event) #$NSLeftMouseDown)
+                                    (> (#/clickCount event) 1))))))
+           (let* ((cache (hemlock-buffer-string-cache (#/hemlockString textstorage)))
+                  (buffer (buffer-cache-buffer cache))
+                  (hi::*current-buffer* buffer)
+                  (point (hi::buffer-point buffer))
+                  (atom-mode (or (eql g #$NSSelectByParagraph)
+                                 (and (eql index (#/length textstorage))
+                                      (let* ((event (#/currentEvent (#/window self))))
+                                        (and (eql (#/type event) #$NSLeftMouseDown)
+                                             (> (#/clickCount event) 2)))))))
+             (hi::with-mark ((mark point))
+               (move-hemlock-mark-to-absolute-position mark cache index)
+	       (let ((region (selection-for-click mark atom-mode)))
+		 (when region
+		   ;; Act as if we started the selection at the other end, so the heuristic
+		   ;; in #/selectionRangeForProposedRange does the right thing.  ref bug #565.
+		   (cond ((hi::mark= (hi::region-start region) mark)
+			  (hi::move-mark point (hi::region-end region)))
+			 ((hi::mark= (hi::region-end region) mark)
+			  (hi::move-mark point (hi::region-start region))))
+		   (let ((start (hi::mark-absolute-position (hi::region-start region)))
+			 (end (hi::mark-absolute-position (hi::region-end region))))
+		     (assert (<= start end))
+		     (ns:init-ns-range r start (- end start)))
+		   #+debug
+		   (#_NSLog #@"range = %@, proposed = %@, granularity = %d"
+			    :address (#_NSStringFromRange r)
+			    :address (#_NSStringFromRange proposed)
+			    :<NSS>election<G>ranularity g)
+		   (return-from HANDLED r)))))))
+       (prog1
+           (call-next-method proposed g)
+         #+debug
+         (#_NSLog #@"range = %@, proposed = %@, granularity = %d"
+                  :address (#_NSStringFromRange r)
+                  :address (#_NSStringFromRange proposed)
+                  :<NSS>election<G>ranularity g)))))
+
+;; Return nil to use the default Cocoa selection, which will be word for double-click, line for triple.
+(defun selection-for-click (mark paragraph-mode-p)
+  (unless paragraph-mode-p
+    ;; Select a word if near one
+    (hi::with-mark ((fwd mark)
+		    (bwd mark))
+      (or (hi::find-attribute fwd :word-delimiter)
+	  (hi::buffer-end fwd))
+      (or (hi::reverse-find-attribute bwd :word-delimiter)
+	  (hi::buffer-start bwd))
+      (unless (hi::mark= bwd fwd)
+	(return-from selection-for-click (hi::region bwd fwd)))))
+  (when (string= (hi::buffer-major-mode (hi::mark-buffer mark)) "Lisp") ;; gag
+    (hemlock::pre-command-parse-check mark)
+    (hemlock::form-region-at-mark mark)))
+
+(defun append-output (view string)
+  (assume-cocoa-thread)
+  ;; Arrange to do the append in command context
+  (when view
+    (hi::handle-hemlock-event view #'(lambda ()
+				       (hemlock::append-buffer-output (hi::hemlock-view-buffer view) string)))))
+
+
+;;; Update the underlying buffer's point (and "active region", if appropriate.
+;;; This is called in response to a mouse click or other event; it shouldn't
+;;; be called from the Hemlock side of things.
+
+(objc:defmethod (#/setSelectedRange:affinity:stillSelecting: :void)
+    ((self hemlock-text-view)
+     (r :<NSR>ange)
+     (affinity :<NSS>election<A>ffinity)
+     (still-selecting :<BOOL>))
+  #+debug
+  (#_NSLog #@"Set selected range called: range = %@, affinity = %d, still-selecting = %d"
+           :address (#_NSStringFromRange r)
+           :<NSS>election<A>ffinity affinity
+           :<BOOL> (if still-selecting #$YES #$NO))
+  #+debug
+  (#_NSLog #@"text view string = %@, textstorage string = %@"
+           :id (#/string self)
+           :id (#/string (#/textStorage self)))
+  (unless (#/editingInProgress (#/textStorage self))
+    (let* ((d (hemlock-buffer-string-cache (#/hemlockString (#/textStorage self))))
+           (buffer (buffer-cache-buffer d))
+	   (hi::*current-buffer* buffer)
+           (point (hi::buffer-point buffer))
+           (location (pref r :<NSR>ange.location))
+           (len (pref r :<NSR>ange.length)))
+      (setf (hi::buffer-selection-set-by-command buffer) nil)
+      (cond ((eql len 0)
+             #+debug
+             (#_NSLog #@"Moving point to absolute position %d" :int location)
+             (setf (hi::buffer-region-active buffer) nil)
+             (move-hemlock-mark-to-absolute-position point d location)
+             (update-paren-highlight self))
+            (t
+             ;; We don't get much information about which end of the
+             ;; selection the mark's at and which end point is at, so
+             ;; we have to sort of guess.  In every case I've ever seen,
+             ;; selection via the mouse generates a sequence of calls to
+             ;; this method whose parameters look like:
+             ;; a: range: {n0,0} still-selecting: false  [ rarely repeats ]
+             ;; b: range: {n0,0) still-selecting: true   [ rarely repeats ]
+             ;; c: range: {n1,m} still-selecting: true   [ often repeats ]
+             ;; d: range: {n1,m} still-selecting: false  [ rarely repeats ]
+             ;;
+             ;; (Sadly, "affinity" doesn't tell us anything interesting.)
+             ;; We've handled a and b in the clause above; after handling
+             ;; b, point references buffer position n0 and the
+             ;; region is inactive.
+             ;; Let's ignore c, and wait until the selection's stabilized.
+             ;; Make a new mark, a copy of point (position n0).
+             ;; At step d (here), we should have either
+             ;; d1) n1=n0.  Mark stays at n0, point moves to n0+m.
+             ;; d2) n1+m=n0.  Mark stays at n0, point moves to n0-m.
+             ;; If neither d1 nor d2 apply, arbitrarily assume forward
+             ;; selection: mark at n1, point at n1+m.
+             ;; In all cases, activate Hemlock selection.
+             (unless still-selecting
+                (let* ((pointpos (hi:mark-absolute-position point))
+                       (selection-end (+ location len))
+                       (mark (hi::copy-mark point :right-inserting)))
+                   (cond ((eql pointpos location)
+                          (move-hemlock-mark-to-absolute-position point
+                                                                  d
+                                                                  selection-end))
+                         ((eql pointpos selection-end)
+                          (move-hemlock-mark-to-absolute-position point
+                                                                  d
+                                                                  location))
+                         (t
+                          (move-hemlock-mark-to-absolute-position mark
+                                                                  d
+                                                                  location)
+                          (move-hemlock-mark-to-absolute-position point
+                                                                  d
+                                                                  selection-end)))
+                   (hemlock::%buffer-push-buffer-mark buffer mark t)))))))
+  (call-next-method r affinity still-selecting))
+
+
+
+
+;;; Modeline-view
+
+(defclass modeline-view (ns:ns-view)
+    ((pane :foreign-type :id :accessor modeline-view-pane)
+     (text-attributes :foreign-type :id :accessor modeline-text-attributes))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod #/initWithFrame: ((self modeline-view) (frame :<NSR>ect))
+  (call-next-method frame)
+  (let* ((size (#/smallSystemFontSize ns:ns-font))
+	 (font (#/systemFontOfSize: ns:ns-font size))
+	 (dict (#/dictionaryWithObject:forKey: ns:ns-dictionary font #&NSFontAttributeName)))
+    (setf (modeline-text-attributes self) (#/retain dict)))
+  self)
+
+;;; Find the underlying buffer.
+(defun buffer-for-modeline-view (mv)
+  (let* ((pane (modeline-view-pane mv)))
+    (unless (%null-ptr-p pane)
+      (let* ((tv (text-pane-text-view pane)))
+        (unless (%null-ptr-p tv)
+	  (hemlock-buffer tv))))))
+
+;;; Draw a string in the modeline view.  The font and other attributes
+;;; are initialized lazily; apparently, calling the Font Manager too
+;;; early in the loading sequence confuses some Carbon libraries that're
+;;; used in the event dispatch mechanism,
+(defun draw-modeline-string (the-modeline-view)
+  (with-slots (text-attributes) the-modeline-view
+    (let* ((buffer (buffer-for-modeline-view the-modeline-view)))
+      (when buffer
+	(let* ((string
+                (apply #'concatenate 'string
+                       (mapcar
+                        #'(lambda (field)
+                            (or (ignore-errors 
+                                  (funcall (hi::modeline-field-function field) buffer))
+                                ""))
+                        (hi::buffer-modeline-fields buffer)))))
+	  (#/drawAtPoint:withAttributes: (#/autorelease (%make-nsstring string))
+                                         (ns:make-ns-point 5 1)
+                                         text-attributes))))))
+
+(objc:defmethod (#/drawRect: :void) ((self modeline-view) (rect :<NSR>ect))
+  (declare (ignorable rect))
+  (let* ((bounds (#/bounds self))
+	 (context (#/currentContext ns:ns-graphics-context)))
+    (#/saveGraphicsState context)
+    (#/set (#/colorWithCalibratedWhite:alpha: ns:ns-color 0.9 1.0))
+    (#_NSRectFill bounds)
+    (#/set (#/colorWithCalibratedWhite:alpha: ns:ns-color 0.3333 1.0))
+    ;; Draw borders on top and bottom.
+    (ns:with-ns-rect (r 0 0.5 (ns:ns-rect-width bounds) 0.5)
+      (#_NSRectFill r))
+    (ns:with-ns-rect (r 0 (- (ns:ns-rect-height bounds) 0.5)
+			(ns:ns-rect-width bounds) (- (ns:ns-rect-height bounds) 0.5))
+      (#_NSRectFill r))
+    (draw-modeline-string self)
+    (#/restoreGraphicsState context)))
+
+;;; Hook things up so that the modeline is updated whenever certain buffer
+;;; attributes change.
+(hi::%init-mode-redisplay)
+
+
+
+;;; A clip view subclass, which exists mostly so that we can track origin changes.
+(defclass text-pane-clip-view (ns:ns-clip-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/scrollToPoint: :void) ((self text-pane-clip-view)
+                                           (origin #>NSPoint))
+  (unless (#/inLiveResize self)
+    (call-next-method origin)
+    (compute-temporary-attributes (#/documentView self))))
+
+;;; Text-pane
+
+;;; The text pane is just an NSBox that (a) provides a draggable border
+;;; around (b) encapsulates the text view and the mode line.
+
+(defclass text-pane (ns:ns-box)
+    ((hemlock-view :initform nil :reader text-pane-hemlock-view)
+     (text-view :foreign-type :id :accessor text-pane-text-view)
+     (mode-line :foreign-type :id :accessor text-pane-mode-line)
+     (scroll-view :foreign-type :id :accessor text-pane-scroll-view))
+  (:metaclass ns:+ns-object))
+
+(defmethod hemlock-view ((self text-pane))
+  (text-pane-hemlock-view self))
+
+;;; This method gets invoked on the text pane, which is its containing
+;;; window's delegate object.
+(objc:defmethod (#/windowDidResignKey: :void)
+    ((self text-pane) notification)
+  (declare (ignorable notification))
+  ;; When the window loses focus, we should remove or change transient
+  ;; highlighting (like matching-paren highlighting).  Maybe make this
+  ;; more general ...
+  ;; Currently, this only removes temporary attributes from matching
+  ;; parens; other kinds of syntax highlighting stays visible when
+  ;; the containing window loses keyboard focus
+  (let* ((tv (text-pane-text-view self)))
+    (remove-paren-highlight tv)
+    (remove-paren-highlight (slot-value tv 'peer))))
+
+;;; Likewise, reactivate transient highlighting when the window gets
+;;; focus.
+(objc:defmethod (#/windowDidBecomeKey: :void)
+    ((self text-pane) notification)
+  (declare (ignorable notification))
+  (let* ((tv (text-pane-text-view self)))
+    (compute-temporary-attributes tv)
+    (compute-temporary-attributes (slot-value tv 'peer))))
+  
+
+;;; Mark the buffer's modeline as needing display.  This is called whenever
+;;; "interesting" attributes of a buffer are changed.
+(defun hemlock-ext:invalidate-modeline (buffer)
+  (let* ((doc (hi::buffer-document buffer)))
+    (when doc
+      (document-invalidate-modeline doc))))
+
+(def-cocoa-default *text-pane-margin-width* :float 0.0f0 "width of indented margin around text pane")
+(def-cocoa-default *text-pane-margin-height* :float 0.0f0 "height of indented margin around text pane")
+
+
+(objc:defmethod #/initWithFrame: ((self text-pane) (frame :<NSR>ect))
+  (let* ((pane (call-next-method frame)))
+    (unless (%null-ptr-p pane)
+      (#/setAutoresizingMask: pane (logior
+                                    #$NSViewWidthSizable
+                                    #$NSViewHeightSizable))
+      (#/setBoxType: pane #$NSBoxPrimary)
+      (#/setBorderType: pane #$NSNoBorder)
+      (#/setContentViewMargins: pane (ns:make-ns-size *text-pane-margin-width*  *text-pane-margin-height*))
+      (#/setTitlePosition: pane #$NSNoTitle))
+    pane))
+
+(objc:defmethod #/defaultMenu ((class +hemlock-text-view))
+  (text-view-context-menu))
+
+;;; If we don't override this, NSTextView will start adding Google/
+;;; Spotlight search options and dictionary lookup when a selection
+;;; is active.
+(objc:defmethod #/menuForEvent: ((self hemlock-text-view) event)
+  (declare (ignore event))
+  (#/menu self))
+
+(defun make-scrolling-text-view-for-textstorage (textstorage x y width height tracks-width color style)
+  (let* ((scrollview (#/autorelease
+                      (make-instance
+                       'ns:ns-scroll-view
+                       :with-frame (ns:make-ns-rect x y width height)))))
+    (#/setBorderType: scrollview #$NSNoBorder)
+    (#/setHasVerticalScroller: scrollview t)
+    (#/setHasHorizontalScroller: scrollview t)
+    (#/setRulersVisible: scrollview nil)
+    (#/setAutoresizingMask: scrollview (logior
+                                        #$NSViewWidthSizable
+                                        #$NSViewHeightSizable))
+    (#/setAutoresizesSubviews: (#/contentView scrollview) t)
+    (let* ((layout (make-instance 'ns:ns-layout-manager)))
+      #+suffer
+      (#/setTypesetter: layout (make-instance 'hemlock-ats-typesetter))
+      (#/addLayoutManager: textstorage layout)
+      (#/setUsesScreenFonts: layout *use-screen-fonts*)
+      (#/release layout)
+      (let* ((contentsize (#/contentSize scrollview)))
+        (ns:with-ns-size (containersize large-number-for-text large-number-for-text)
+          (ns:with-ns-rect (tv-frame 0 0 (ns:ns-size-width contentsize) (ns:ns-size-height contentsize))
+            (ns:init-ns-size containersize large-number-for-text large-number-for-text)
+            (ns:init-ns-rect tv-frame 0 0 (ns:ns-size-width contentsize) (ns:ns-size-height contentsize))
+            (let* ((container (#/autorelease (make-instance
+                                              'ns:ns-text-container
+                                              :with-container-size containersize))))
+              (#/addTextContainer: layout  container)
+              (let* ((tv (#/autorelease (make-instance 'hemlock-text-view
+                                                       :with-frame tv-frame
+                                                       :text-container container))))
+                (setf (text-view-paren-highlight-color tv) (paren-highlight-background-color))
+                (#/setDelegate: layout tv)
+                (#/setMinSize: tv (ns:make-ns-size 0 (ns:ns-size-height contentsize)))
+                (#/setMaxSize: tv (ns:make-ns-size large-number-for-text large-number-for-text))
+                (#/setRichText: tv nil)
+                (#/setAutoresizingMask: tv #$NSViewWidthSizable)
+                (#/setBackgroundColor: tv color)
+		(when (slot-exists-p textstorage 'styles)
+		  (#/setTypingAttributes: tv (#/objectAtIndex:
+					      (#/styles textstorage) style)))
+                #-cocotron
+                (#/setSmartInsertDeleteEnabled: tv nil)
+                (#/setAllowsUndo: tv nil) ; don't want NSTextView undo
+                #-cocotron
+                (#/setUsesFindPanel: tv t)
+                #-cocotron
+                (#/setUsesFontPanel: tv nil)
+                (#/setMenu: tv (text-view-context-menu))
+
+		;;  The container tracking and the text view sizability along a
+		;;  particular axis must always be different, or else things can
+		;;  get really confused (possibly causing an infinite loop).
+
+		(if (or tracks-width *wrap-lines-to-window*)
+		  (progn
+		    (#/setWidthTracksTextView: container t)
+		    (#/setHeightTracksTextView: container nil)
+		    (#/setHorizontallyResizable: tv nil)
+		    (#/setVerticallyResizable: tv t))
+		  (progn
+		    (#/setWidthTracksTextView: container nil)
+		    (#/setHeightTracksTextView: container nil)
+		    (#/setHorizontallyResizable: tv t)
+		    (#/setVerticallyResizable: tv t)))
+                (#/setContentView: scrollview (make-instance 'text-pane-clip-view))
+                (#/setDocumentView: scrollview tv)	      
+                (values tv scrollview)))))))))
+
+(defun make-scrolling-textview-for-pane (pane textstorage track-width color style)
+  (let* ((contentrect (#/frame (#/contentView pane)) ))
+    (multiple-value-bind (tv scrollview)
+	(make-scrolling-text-view-for-textstorage
+	 textstorage
+         (ns:ns-rect-x contentrect)
+         (ns:ns-rect-y contentrect)
+         (ns:ns-rect-width contentrect)
+         (ns:ns-rect-height contentrect)
+	 track-width
+         color
+         style)
+      (#/addSubview: pane scrollview)
+      (let* ((r (#/frame scrollview)))
+        (decf (ns:ns-rect-height r) 15)
+        (incf (ns:ns-rect-y r) 15)
+        (#/setFrame: scrollview r))
+      #-cocotron
+      (#/setAutohidesScrollers: scrollview t)
+      (setf (slot-value pane 'scroll-view) scrollview
+            (slot-value pane 'text-view) tv
+            (slot-value tv 'pane) pane
+            #|(slot-value scrollview 'pane) pane|#)
+      ;;(let* ((modeline  (scroll-view-modeline scrollview)))
+      (let* ((modeline  (make-instance 'modeline-view
+                          :with-frame (ns:make-ns-rect 0 0 (ns:ns-rect-width contentrect)
+                                                       15))))
+        (#/setAutoresizingMask: modeline #$NSViewWidthSizable)
+        (#/addSubview: pane modeline)
+        (#/release modeline)
+        (setf (slot-value pane 'mode-line) modeline
+              (slot-value modeline 'pane) pane))
+      tv)))
+
+(defmethod hemlock-ext:change-active-pane ((view hi:hemlock-view) new-pane)
+  #+debug (log-debug "change active pane to ~s" new-pane)
+  (let* ((pane (hi::hemlock-view-pane view))
+	 (text-view (text-pane-text-view pane))
+	 (tv (ecase new-pane
+	       (:echo (slot-value text-view 'peer))
+	       (:text text-view))))
+    (activate-hemlock-view tv)))
+
+(defclass echo-area-view (hemlock-textstorage-text-view)
+    ()
+  (:metaclass ns:+ns-object))
+(declaim (special echo-area-view))
+
+(defmethod compute-temporary-attributes ((self echo-area-view))
+)
+
+(defmethod update-paren-highlight ((self echo-area-view))
+)
+
+(defmethod hemlock-view ((self echo-area-view))
+  (let ((text-view (slot-value self 'peer)))
+    (when text-view
+      (hemlock-view text-view))))
+
+;;; The "document" for an echo-area isn't a real NSDocument.
+(defclass echo-area-document (ns:ns-object)
+    ((textstorage :foreign-type :id))
+  (:metaclass ns:+ns-object))
+
+(defmethod hemlock-buffer ((self echo-area-document))
+  (let ((ts (slot-value self 'textstorage)))
+    (unless (%null-ptr-p ts)
+      (hemlock-buffer ts))))
+
+(objc:defmethod #/undoManager ((self echo-area-document))
+  +null-ptr+) ;For now, undo is not supported for echo-areas
+
+(defmethod update-buffer-package ((doc echo-area-document) buffer)
+  (declare (ignore buffer)))
+
+(defmethod document-invalidate-modeline ((self echo-area-document))
+  nil)
+
+(objc:defmethod (#/close :void) ((self echo-area-document))
+  (let* ((ts (slot-value self 'textstorage)))
+    (unless (%null-ptr-p ts)
+      (setf (slot-value self 'textstorage) (%null-ptr))
+      (close-hemlock-textstorage ts))))
+
+(objc:defmethod (#/updateChangeCount: :void) ((self echo-area-document) (change :<NSD>ocument<C>hange<T>ype))
+  (declare (ignore change)))
+
+(defun make-echo-area (the-hemlock-frame x y width height main-buffer color)
+  (let* ((box (make-instance 'ns:ns-view :with-frame (ns:make-ns-rect x y width height))))
+    (#/setAutoresizingMask: box #$NSViewWidthSizable)
+    (let* ((box-frame (#/bounds box))
+           (containersize (ns:make-ns-size large-number-for-text (ns:ns-rect-height box-frame)))
+           (clipview (make-instance 'ns:ns-clip-view
+                                    :with-frame box-frame)))
+      (#/setAutoresizingMask: clipview (logior #$NSViewWidthSizable
+                                               #$NSViewHeightSizable))
+      (#/setBackgroundColor: clipview color)
+      (#/addSubview: box clipview)
+      (#/setAutoresizesSubviews: box t)
+      (#/release clipview)
+      (let* ((buffer (hi::make-echo-buffer))
+             (textstorage
+              (progn
+		;; What's the reason for sharing this?  Is it just the lock?
+                (setf (hi::buffer-gap-context buffer) (hi::ensure-buffer-gap-context main-buffer))
+                (make-textstorage-for-hemlock-buffer buffer)))
+             (doc (make-instance 'echo-area-document))
+             (layout (make-instance 'ns:ns-layout-manager))
+             (container (#/autorelease
+                         (make-instance 'ns:ns-text-container
+                                        :with-container-size
+                                        containersize))))
+        (#/addLayoutManager: textstorage layout)
+	(#/setUsesScreenFonts: layout *use-screen-fonts*)
+        (#/addTextContainer: layout container)
+        (#/release layout)
+        (let* ((echo (make-instance 'echo-area-view
+                                    :with-frame box-frame
+                                    :text-container container)))
+          (#/setMinSize: echo (pref box-frame :<NSR>ect.size))
+          (#/setMaxSize: echo (ns:make-ns-size large-number-for-text large-number-for-text))
+          (#/setRichText: echo nil)
+          #-cocotron
+          (#/setUsesFontPanel: echo nil)
+          (#/setHorizontallyResizable: echo t)
+          (#/setVerticallyResizable: echo nil)
+          (#/setAutoresizingMask: echo #$NSViewNotSizable)
+          (#/setBackgroundColor: echo color)
+          (#/setWidthTracksTextView: container nil)
+          (#/setHeightTracksTextView: container nil)
+          (#/setMenu: echo +null-ptr+)
+          (setf (hemlock-frame-echo-area-buffer the-hemlock-frame) buffer
+                (slot-value doc 'textstorage) textstorage
+                (hi::buffer-document buffer) doc)
+          (#/setDocumentView: clipview echo)
+          (#/setAutoresizesSubviews: clipview nil)
+          (#/sizeToFit echo)
+          (values echo box))))))
+		    
+(defun make-echo-area-for-window (w main-buffer color)
+  (let* ((content-view (#/contentView w))
+	 (bounds (#/bounds content-view))
+         (height (+ 1 (size-of-char-in-font *editor-font*))))
+    (multiple-value-bind (echo-area box)
+			 (make-echo-area w
+					 0.0f0
+					 0.0f0
+					 (- (ns:ns-rect-width bounds) 16.0f0)
+                                         height
+					 main-buffer
+					 color)
+      (#/addSubview: content-view box)
+      echo-area)))
+               
+(defclass hemlock-frame (ns:ns-window)
+    ((echo-area-view :foreign-type :id)
+     (pane :foreign-type :id)
+     (echo-area-buffer :initform nil :accessor hemlock-frame-echo-area-buffer)
+     (echo-area-stream :initform nil :accessor hemlock-frame-echo-area-stream))
+  (:metaclass ns:+ns-object))
+(declaim (special hemlock-frame))
+
+;;; If a window's document's edited status changes, update the modeline.
+(objc:defmethod (#/setDocumentEdited: :void) ((w hemlock-frame)
+                                              (edited #>BOOL))
+  (let* ((was-edited (#/isDocumentEdited w)))
+    (unless (eq was-edited edited)
+      (#/setNeedsDisplay: (text-pane-mode-line (slot-value w 'pane)) t)))
+  (call-next-method edited))
+
+
+(objc:defmethod (#/miniaturize: :void) ((w hemlock-frame) sender)
+  (let* ((event (#/currentEvent w))
+         (flags (#/modifierFlags event)))
+    (if (logtest #$NSControlKeyMask flags)
+      (progn
+        (#/orderOut: w nil)
+        (#/changeWindowsItem:title:filename: *nsapp* w (#/title w) nil))
+      (call-next-method sender))))
+
+(defmethod hemlock-view ((frame hemlock-frame))
+  (let ((pane (slot-value frame 'pane)))
+    (when (and pane (not (%null-ptr-p pane)))
+      (hemlock-view pane))))
+
+(objc:defmethod (#/runErrorSheet: :void) ((self hemlock-frame) message)
+  #+debug (#_NSLog #@"runErrorSheet: signal = %@" :id signal)
+  (#_NSBeginAlertSheet #@"Error in Hemlock command processing" ;title
+                       (if (logbitp 0 (random 2))
+                         #@"Not OK, but what can you do?"
+                         #@"The sky is falling. FRED never did this!")
+                       +null-ptr+
+                       +null-ptr+
+                       self
+                       self
+                       +null-ptr+
+                       +null-ptr+
+                       +null-ptr+
+                       message))
+
+(defun report-condition-in-hemlock-frame (condition frame)
+  (assume-cocoa-thread)
+  (let ((message (nsstring-for-lisp-condition condition)))
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     frame
+     (@selector #/runErrorSheet:)
+     message
+     t)))
+
+(defmethod hemlock-ext:report-hemlock-error ((view hi:hemlock-view) condition debug-p)
+  (when debug-p (maybe-log-callback-error condition))
+  (let ((pane (hi::hemlock-view-pane view)))
+    (when (and pane (not (%null-ptr-p pane)))
+      (report-condition-in-hemlock-frame condition (#/window pane)))))
+
+(defun window-menubar-height ()
+  #+cocotron (objc:objc-message-send (ccl::@class "NSMainMenuView") "menuHeight" #>CGFloat)
+  #-cocotron 0.0f0)
+
+(defun new-hemlock-document-window (class)
+  (let* ((w (new-cocoa-window :class class
+                              :activate nil))
+         (echo-area-height (+ 1 (size-of-char-in-font *editor-font*))))
+      (values w (add-pane-to-window w :reserve-below echo-area-height))))
+
+
+
+(defun add-pane-to-window (w &key (reserve-above 0.0f0) (reserve-below 0.0f0))
+  (let* ((window-content-view (#/contentView w))
+	 (window-frame (#/frame window-content-view)))
+    (ns:with-ns-rect (pane-rect  0 reserve-below (ns:ns-rect-width window-frame) (- (ns:ns-rect-height window-frame) (+ reserve-above reserve-below)))
+       (let* ((pane (make-instance 'text-pane :with-frame pane-rect)))
+	 (#/addSubview: window-content-view pane)
+         (#/setDelegate: w pane)
+         ;; Cocotron doesn't set the new window's initialFirstResponder which means
+         ;; that the user must click in the window before they can edit.  So, do it here.
+         ;; Remove this when Cocotron issue #374 is fixed
+         ;;  (http://code.google.com/p/cocotron/issues/detail?id=374)
+         #+cocotron (#/setInitialFirstResponder: w pane)
+	 pane))))
+
+(defun textpane-for-textstorage (class ts ncols nrows container-tracks-text-view-width color style)
+  (let* ((pane (nth-value
+                1
+                (new-hemlock-document-window class))))
+    (make-scrolling-textview-for-pane pane ts container-tracks-text-view-width color style)
+    (multiple-value-bind (height width)
+        (size-of-char-in-font (default-font))
+      (size-text-pane pane height width nrows ncols))
+    pane))
+
+
+
+
+(defun hemlock-buffer-from-nsstring (nsstring name &rest modes)
+  (let* ((buffer (make-hemlock-buffer name :modes modes)))
+    (nsstring-to-buffer nsstring buffer)))
+
+(defun %nsstring-to-hemlock-string (nsstring)
+  "returns line-termination of string"
+  (let* ((string (lisp-string-from-nsstring nsstring))
+         (lfpos (position #\linefeed string))
+         (crpos (position #\return string))
+         (line-termination (if crpos
+                             (if (eql lfpos (1+ crpos))
+                               :crlf
+                               :cr)
+			     :lf))
+	 (hemlock-string (case line-termination
+			   (:crlf (remove #\return string))
+			   (:cr (nsubstitute #\linefeed #\return string))
+			   (t string))))
+    (values hemlock-string line-termination)))
+
+;: TODO: I think this is jumping through hoops because it want to be invokable outside the main
+;; cocoa thread.
+(defun nsstring-to-buffer (nsstring buffer)
+  (let* ((document (hi::buffer-document buffer))
+	 (hi::*current-buffer* buffer)
+         (region (hi::buffer-region buffer)))
+    (multiple-value-bind (hemlock-string line-termination)
+			 (%nsstring-to-hemlock-string nsstring)
+      (setf (hi::buffer-line-termination buffer) line-termination)
+
+      (setf (hi::buffer-document buffer) nil) ;; What's this about??
+      (unwind-protect
+	  (let ((point (hi::buffer-point buffer)))
+	    (hi::delete-region region)
+	    (hi::insert-string point hemlock-string)
+	    (setf (hi::buffer-modified buffer) nil)
+	    (hi::buffer-start point)
+	    ;; TODO: why would this be needed? insert-string should take care of any internal bookkeeping.
+	    (hi::renumber-region region)
+	    buffer)
+	(setf (hi::buffer-document buffer) document)))))
+
+
+(setq hi::*beep-function* #'(lambda (stream)
+			      (declare (ignore stream))
+			      (#_NSBeep)))
+
+
+;;; This function must run in the main event thread.
+(defun %hemlock-frame-for-textstorage (class ts ncols nrows container-tracks-text-view-width color style)
+  (assume-cocoa-thread)
+  (let* ((pane (textpane-for-textstorage class ts ncols nrows container-tracks-text-view-width color style))
+         (buffer (hemlock-buffer ts))
+         (frame (#/window pane))
+         (echo-area (make-echo-area-for-window frame buffer color))
+	 (echo-buffer (hemlock-buffer (#/textStorage echo-area)))
+         (tv (text-pane-text-view pane)))
+    #+GZ (assert echo-buffer)
+    (with-slots (peer) tv
+      (setq peer echo-area))
+    (with-slots (peer) echo-area
+      (setq peer tv))
+    (setf (slot-value frame 'echo-area-view) echo-area
+          (slot-value frame 'pane) pane)
+    (setf (slot-value pane 'hemlock-view)
+	  (make-instance 'hi:hemlock-view
+	    :buffer buffer
+	    :pane pane
+	    :echo-area-buffer echo-buffer))
+    (activate-hemlock-view tv)
+   frame))
+
+(defun hemlock-ext:invoke-modifying-buffer-storage (buffer thunk)
+  (assume-cocoa-thread)
+  (when buffer ;; nil means just get rid of any prior buffer
+    (setq buffer (require-type buffer 'hi::buffer)))
+  (let ((old *buffer-being-edited*))
+    (if (eq buffer old)
+      (funcall thunk)
+      (unwind-protect
+	  (progn
+	    (buffer-document-end-editing old)
+	    (buffer-document-begin-editing buffer)
+	    (funcall thunk))
+	(buffer-document-end-editing buffer)
+	(buffer-document-begin-editing old)))))
+
+(defun buffer-document-end-editing (buffer)
+  (when buffer
+    (let* ((document (hi::buffer-document (require-type buffer 'hi::buffer))))
+      (when document
+	(setq *buffer-being-edited* nil)
+	(let ((ts (slot-value document 'textstorage)))
+	  (#/endEditing ts)
+	  (update-hemlock-selection ts))))))
+
+(defun buffer-document-begin-editing (buffer)
+  (when buffer
+    (let* ((document (hi::buffer-document buffer)))
+      (when document
+	(setq *buffer-being-edited* buffer)
+	(#/beginEditing (slot-value document 'textstorage))))))
+
+(defun document-edit-level (document)
+  (assume-cocoa-thread) ;; see comment in #/editingInProgress
+  (slot-value (slot-value document 'textstorage) 'edit-count))
+
+(defun buffer-edit-level (buffer)
+  (if buffer
+    (let* ((document (hi::buffer-document buffer)))
+      (if document
+        (document-edit-level document)
+        0))
+    0))
+
+(defun hemlock-ext:invoke-allowing-buffer-display (buffer thunk)
+  ;; Call THUNK with the buffer's edit-level at 0, then restore the buffer's edit level.
+  (let* ((level (buffer-edit-level buffer)))
+    (dotimes (i level) (buffer-document-end-editing buffer))
+    (unwind-protect
+        (funcall thunk)
+      (dotimes (i level) (buffer-document-begin-editing buffer)))))
+
+
+(defun buffer-document-modified (buffer)
+  (let* ((doc (hi::buffer-document buffer)))
+    (if doc
+      (#/isDocumentEdited doc))))
+
+(defun perform-edit-change-notification (textstorage selector pos n &optional (extra 0))
+  (with-lock-grabbed (*buffer-change-invocation-lock*)
+    (let* ((invocation *buffer-change-invocation*))
+      (rlet ((ppos :<NSI>nteger pos)
+             (pn :<NSI>nteger n)
+             (pextra :<NSI>nteger extra))
+        (#/setTarget: invocation textstorage)
+        (#/setSelector: invocation selector)
+        (#/setArgument:atIndex: invocation ppos 2)
+        (#/setArgument:atIndex: invocation pn 3)
+        (#/setArgument:atIndex: invocation pextra 4))
+      (#/performSelectorOnMainThread:withObject:waitUntilDone:
+       invocation
+       (@selector #/invoke)
+       +null-ptr+
+       t))))
+
+
+
+
+(defun hemlock-ext:buffer-note-font-change (buffer region font)
+  (when (hi::bufferp buffer)
+    (let* ((document (hi::buffer-document buffer))
+	   (textstorage (if document (slot-value document 'textstorage)))
+           (pos (hi:mark-absolute-position (hi::region-start region)))
+           (n (- (hi:mark-absolute-position (hi::region-end region)) pos)))
+      (perform-edit-change-notification textstorage
+                                        (@selector #/noteHemlockAttrChangeAtPosition:length:)
+                                        pos
+                                        n
+                                        font))))
+
+(defun buffer-active-font-attributes (buffer)
+  (let* ((style 0)
+         (region (hi::buffer-active-font-region buffer))
+         (textstorage (slot-value (hi::buffer-document buffer) 'textstorage))
+         (styles (#/styles textstorage)))
+    (when region
+      (let* ((start (hi::region-end region)))
+        (setq style (hi::font-mark-font start))))
+    (#/objectAtIndex: styles style)))
+      
+;; Note that inserted a string of length n at mark.  Assumes this is called after
+;; buffer marks were updated.
+(defun hemlock-ext:buffer-note-insertion (buffer mark n)
+  (when (hi::bufferp buffer)
+    (let* ((document (hi::buffer-document buffer))
+	   (textstorage (if document (slot-value document 'textstorage))))
+      (when textstorage
+        (let* ((pos (hi:mark-absolute-position mark)))
+          (when (eq (hi::mark-%kind mark) :left-inserting)
+	    ;; Make up for the fact that the mark moved forward with the insertion.
+	    ;; For :right-inserting and :temporary marks, they should be left back.
+            (decf pos n))
+          (perform-edit-change-notification textstorage
+                                            (@selector #/noteHemlockInsertionAtPosition:length:)
+                                            pos
+                                            n))))))
+
+(defun hemlock-ext:buffer-note-modification (buffer mark n)
+  (when (hi::bufferp buffer)
+    (let* ((document (hi::buffer-document buffer))
+	   (textstorage (if document (slot-value document 'textstorage))))
+      (when textstorage
+            (perform-edit-change-notification textstorage
+                                              (@selector #/noteHemlockModificationAtPosition:length:)
+                                              (hi:mark-absolute-position mark)
+                                              n)))))
+  
+
+(defun hemlock-ext:buffer-note-deletion (buffer mark n)
+  (when (hi::bufferp buffer)
+    (let* ((document (hi::buffer-document buffer))
+	   (textstorage (if document (slot-value document 'textstorage))))
+      (when textstorage
+        (let* ((pos (hi:mark-absolute-position mark)))
+          (perform-edit-change-notification textstorage
+                                            (@selector #/noteHemlockDeletionAtPosition:length:)
+                                            pos
+                                            (abs n)))))))
+
+
+
+(defun hemlock-ext:note-buffer-saved (buffer)
+  (assume-cocoa-thread)
+  (let* ((document (hi::buffer-document buffer)))
+    (when document
+      ;; Hmm... I guess this is always done by the act of saving.
+      nil)))
+
+(defun hemlock-ext:note-buffer-unsaved (buffer)
+  (assume-cocoa-thread)
+  (let* ((document (hi::buffer-document buffer)))
+    (when document
+      (#/updateChangeCount: document #$NSChangeCleared))))
+
+
+(defun size-of-char-in-font (f)
+  (let* ((sf (#/screenFont f))
+         (screen-p *use-screen-fonts*))
+    (if (%null-ptr-p sf) (setq sf f screen-p nil))
+    (let* ((layout (#/autorelease (#/init (#/alloc ns:ns-layout-manager)))))
+      (#/setUsesScreenFonts: layout screen-p)
+      (values (fround (#/defaultLineHeightForFont: layout sf))
+              (fround (ns:ns-size-width (#/advancementForGlyph: sf (char-code #\space))))))))
+         
+
+
+(defun size-text-pane (pane line-height char-width nrows ncols)
+  (let* ((tv (text-pane-text-view pane))
+         (height (fceiling (* nrows line-height)))
+	 (width (fceiling (* ncols char-width)))
+	 (scrollview (text-pane-scroll-view pane))
+	 (window (#/window scrollview))
+         (has-horizontal-scroller (#/hasHorizontalScroller scrollview))
+         (has-vertical-scroller (#/hasVerticalScroller scrollview)))
+    (ns:with-ns-size (tv-size
+                      (+ width (* 2 (#/lineFragmentPadding (#/textContainer tv))))
+                      height)
+      (when has-vertical-scroller 
+	(#/setVerticalLineScroll: scrollview line-height)
+	(#/setVerticalPageScroll: scrollview (cgfloat 0.0) #|line-height|#))
+      (when has-horizontal-scroller
+	(#/setHorizontalLineScroll: scrollview char-width)
+	(#/setHorizontalPageScroll: scrollview (cgfloat 0.0) #|char-width|#))
+      (let* ((sv-size (#/frameSizeForContentSize:hasHorizontalScroller:hasVerticalScroller:borderType: ns:ns-scroll-view tv-size has-horizontal-scroller has-vertical-scroller (#/borderType scrollview)))
+             (pane-frame (#/frame pane))
+             (margins (#/contentViewMargins pane)))
+        (incf (ns:ns-size-height sv-size)
+              (+ (ns:ns-rect-y pane-frame)
+                 (* 2 (ns:ns-size-height  margins))))
+        (incf (ns:ns-size-width sv-size)
+              (ns:ns-size-width margins))
+        (#/setContentSize: window sv-size)
+        (setf (slot-value tv 'char-width) char-width
+              (slot-value tv 'line-height) line-height)
+        (#/setResizeIncrements: window
+                                (ns:make-ns-size char-width line-height))))))
+				    
+  
+(defclass hemlock-editor-window-controller (ns:ns-window-controller)
+  ()
+  (:metaclass ns:+ns-object))
+
+;;; This is borrowed from emacs.  The first click on the zoom button will
+;;; zoom vertically.  The second will zoom completely.  The third will
+;;; return to the original size.
+(objc:defmethod (#/windowWillUseStandardFrame:defaultFrame: #>NSRect)
+                ((wc hemlock-editor-window-controller) sender (default-frame #>NSRect))
+  (let* ((r (#/frame sender)))
+    (if (= (ns:ns-rect-height r) (ns:ns-rect-height default-frame))
+      (setf r default-frame)
+      (setf (ns:ns-rect-height r) (ns:ns-rect-height default-frame)
+            (ns:ns-rect-y r) (ns:ns-rect-y default-frame)))
+    r))
+
+(objc:defmethod (#/windowWillClose: :void) ((wc hemlock-editor-window-controller)
+                                            notification)
+  (declare (ignore notification))
+  ;; The echo area "document" should probably be a slot in the document
+  ;; object, and released when the document object is.
+  (let* ((w (#/window wc))
+         (buf (hemlock-frame-echo-area-buffer w))
+         (echo-doc (if buf (hi::buffer-document buf))))
+    (when echo-doc
+      (setf (hemlock-frame-echo-area-buffer w) nil)
+      (#/close echo-doc))
+    (#/setFrameAutosaveName: w #@"")
+    (#/autorelease w)))
+
+(defmethod hemlock-view ((self hemlock-editor-window-controller))
+  (let ((frame (#/window self)))
+    (unless (%null-ptr-p frame)
+      (hemlock-view frame))))
+
+;;; Map *default-file-character-encoding* to an :<NSS>tring<E>ncoding
+(defun get-default-encoding ()
+  #-cocotron                            ;need IANA conversion stuff
+  (let* ((file-encoding *default-file-character-encoding*))
+    (when (and (typep file-encoding 'keyword)
+               (lookup-character-encoding file-encoding))
+      (let* ((string (string file-encoding))
+             (len (length string)))
+        (with-cstrs ((cstr string))
+          (with-nsstr (nsstr cstr len)
+            (let* ((cf (#_CFStringConvertIANACharSetNameToEncoding nsstr)))
+              (if (= cf #$kCFStringEncodingInvalidId)
+                (setq cf (#_CFStringGetSystemEncoding)))
+              (let* ((ns (#_CFStringConvertEncodingToNSStringEncoding cf)))
+                (if (= ns #$kCFStringEncodingInvalidId)
+                  (#/defaultCStringEncoding ns:ns-string)
+                  ns)))))))))
+
+(defclass hemlock-document-controller (ns:ns-document-controller)
+    ((last-encoding :foreign-type :<NSS>tring<E>ncoding))
+  (:metaclass ns:+ns-object))
+(declaim (special hemlock-document-controller))
+
+(objc:defmethod #/init ((self hemlock-document-controller))
+  (prog1
+      (call-next-method)
+    (setf (slot-value self 'last-encoding) 0)))
+
+
+;;; The HemlockEditorDocument class.
+
+
+(defclass hemlock-editor-document (ns:ns-document)
+    ((textstorage :foreign-type :id)
+     (encoding :foreign-type :<NSS>tring<E>ncoding))
+  (:metaclass ns:+ns-object))
+
+(defmethod hemlock-buffer ((self hemlock-editor-document))
+  (let ((ts (slot-value self 'textstorage)))
+    (unless (%null-ptr-p ts)
+      (hemlock-buffer ts))))
+
+(defmethod assume-not-editing ((doc hemlock-editor-document))
+  (assume-not-editing (slot-value doc 'textstorage)))
+
+(defmethod document-invalidate-modeline ((self hemlock-editor-document))
+  (for-each-textview-using-storage
+   (slot-value self 'textstorage)
+   #'(lambda (tv)
+       (let* ((pane (text-view-pane tv)))
+	 (unless (%null-ptr-p pane)
+	   (#/setNeedsDisplay: (text-pane-mode-line pane) t))))))
+
+(defmethod update-buffer-package ((doc hemlock-editor-document) buffer)
+  (let* ((name (or (hemlock::package-at-mark (hi::buffer-point buffer))
+                   (hi::variable-value 'hemlock::default-package :buffer buffer))))
+    (when name
+      (let* ((pkg (find-package name)))
+        (if pkg
+          (setq name (shortest-package-name pkg))))
+      (let* ((curname (hi::variable-value 'hemlock::current-package :buffer buffer)))
+        (if (or (null curname)
+                (not (string= curname name)))
+          (setf (hi::variable-value 'hemlock::current-package :buffer buffer) name))))))
+
+(defun hemlock-ext:note-selection-set-by-search (buffer)
+  (let* ((doc (hi::buffer-document buffer)))
+    (when doc
+      (with-slots (textstorage) doc
+	(when textstorage
+	  (with-slots (selection-set-by-search) textstorage
+	    (setq selection-set-by-search #$YES)))))))
+
+(objc:defmethod (#/validateMenuItem: :<BOOL>)
+    ((self hemlock-text-view) item)
+  (let* ((action (#/action item)))
+    #+debug (#_NSLog #@"action = %s" :address action)
+    (cond ((eql action (@selector #/hyperSpecLookUp:))
+           ;; For now, demand a selection.
+           (and *hyperspec-lookup-enabled*
+		(hyperspec-root-url)
+                (not (eql 0 (ns:ns-range-length (#/selectedRange self))))))
+          ((eql action (@selector #/cut:))
+           (let* ((selection (#/selectedRange self)))
+             (and (> (ns:ns-range-length selection))
+                  (#/shouldChangeTextInRange:replacementString: self selection #@""))))
+          ((eql action (@selector #/evalSelection:))
+           (not (eql 0 (ns:ns-range-length (#/selectedRange self)))))
+          ((eql action (@selector #/evalAll:))
+           (let* ((doc (#/document (#/windowController (#/window self)))))
+             (and (not (%null-ptr-p doc))
+                  (eq (type-of doc) 'hemlock-editor-document))))
+          ;; if this hemlock-text-view is in an editor windowm and its buffer has
+          ;; an associated pathname, then activate the Load Buffer item
+          ((or (eql action (@selector #/loadBuffer:))
+               (eql action (@selector #/compileBuffer:))
+               (eql action (@selector #/compileAndLoadBuffer:))) 
+           (let* ((buffer (hemlock-buffer self))
+                  (pathname (hi::buffer-pathname buffer)))
+             (not (null pathname))))
+	  (t (call-next-method item)))))
+
+(defmethod user-input-style ((doc hemlock-editor-document))
+  0)
+
+(defvar *encoding-name-hash* (make-hash-table))
+
+(defmethod document-encoding-name ((doc hemlock-editor-document))
+  (with-slots (encoding) doc
+    (if (eql encoding 0)
+      "Automatic"
+      (or (gethash encoding *encoding-name-hash*)
+          (setf (gethash encoding *encoding-name-hash*)
+                (lisp-string-from-nsstring (nsstring-for-nsstring-encoding encoding)))))))
+
+(defun hemlock-ext:buffer-encoding-name (buffer)
+  (let ((doc (hi::buffer-document buffer)))
+    (and doc (document-encoding-name doc))))
+
+;; TODO: make each buffer have a slot, and this is just the default value.
+(defmethod textview-background-color ((doc hemlock-editor-document))
+  *editor-background-color*)
+
+
+(objc:defmethod (#/setTextStorage: :void) ((self hemlock-editor-document) ts)
+  (let* ((doc (%inc-ptr self 0))        ; workaround for stack-consed self
+         (string (#/hemlockString ts))
+         (buffer (hemlock-buffer string)))
+    (unless (%null-ptr-p doc)
+      (setf (slot-value doc 'textstorage) ts
+            (hi::buffer-document buffer) doc))))
+
+;; This runs on the main thread.
+(objc:defmethod (#/revertToSavedFromFile:ofType: :<BOOL>)
+    ((self hemlock-editor-document) filename filetype)
+  (declare (ignore filetype))
+  (assume-cocoa-thread)
+  #+debug
+  (#_NSLog #@"revert to saved from file %@ of type %@"
+           :id filename :id filetype)
+  (let* ((encoding (slot-value self 'encoding))
+         (nsstring (make-instance ns:ns-string
+                                  :with-contents-of-file filename
+                                  :encoding encoding
+                                  :error +null-ptr+))
+         (buffer (hemlock-buffer self))
+         (old-length (hemlock-buffer-length buffer))
+	 (hi::*current-buffer* buffer)
+         (textstorage (slot-value self 'textstorage))
+         (point (hi::buffer-point buffer))
+         (pointpos (hi:mark-absolute-position point)))
+    (hemlock-ext:invoke-modifying-buffer-storage
+     buffer
+     #'(lambda ()
+         (#/edited:range:changeInLength:
+          textstorage #$NSTextStorageEditedCharacters (ns:make-ns-range 0 old-length) (- old-length))
+         (nsstring-to-buffer nsstring buffer)
+         (let* ((newlen (hemlock-buffer-length buffer)))
+           (#/edited:range:changeInLength: textstorage  #$NSTextStorageEditedAttributes (ns:make-ns-range 0 0) newlen)
+           (#/edited:range:changeInLength: textstorage #$NSTextStorageEditedCharacters (ns:make-ns-range 0 newlen) 0)
+           (let* ((ts-string (#/hemlockString textstorage))
+                  (display (hemlock-buffer-string-cache ts-string)))
+             (reset-buffer-cache display) 
+             (update-line-cache-for-index display 0)
+             (move-hemlock-mark-to-absolute-position point
+                                                     display
+                                                     (min newlen pointpos))))
+         (#/updateMirror textstorage)
+         (setf (hi::buffer-modified buffer) nil)
+         (hi::note-modeline-change buffer)))
+    t))
+
+
+(defvar *last-document-created* nil)
+
+(objc:defmethod #/init ((self hemlock-editor-document))
+  (let* ((doc (call-next-method)))
+    (unless  (%null-ptr-p doc)
+      (#/setTextStorage: doc (make-textstorage-for-hemlock-buffer
+                              (make-hemlock-buffer
+                               (lisp-string-from-nsstring
+                                (#/displayName doc))
+                               :modes '("Lisp" "Editor")))))
+    (with-slots (encoding) doc
+      (setq encoding (or (get-default-encoding) #$NSISOLatin1StringEncoding)))
+    (setq *last-document-created* doc)
+    doc))
+
+  
+(defun make-buffer-for-document (ns-document pathname)
+  (let* ((buffer-name (hi::pathname-to-buffer-name pathname))
+	 (buffer (make-hemlock-buffer buffer-name)))
+    (setf (slot-value ns-document 'textstorage)
+	  (make-textstorage-for-hemlock-buffer buffer))
+    (setf (hi::buffer-pathname buffer) pathname)
+    buffer))
+
+(objc:defmethod (#/readFromURL:ofType:error: :<BOOL>)
+    ((self hemlock-editor-document) url type (perror (:* :id)))
+  (declare (ignorable type))
+  (with-callback-context "readFromURL"
+    (rlet ((pused-encoding :<NSS>tring<E>ncoding 0))
+      (let* ((pathname
+              (lisp-string-from-nsstring
+               (if (#/isFileURL url)
+                 (#/path url)
+                 (#/absoluteString url))))
+             (buffer (or (hemlock-buffer self)
+                         (make-buffer-for-document self pathname)))
+             (selected-encoding (slot-value (#/sharedDocumentController (find-class 'hemlock-document-controller)) 'last-encoding))
+             (string
+              (if (zerop selected-encoding)
+                (#/stringWithContentsOfURL:usedEncoding:error:
+                 ns:ns-string
+                 url
+                 pused-encoding
+                 perror)
+                +null-ptr+)))
+        
+        (if (%null-ptr-p string)
+          (progn
+            (if (zerop selected-encoding)
+              (setq selected-encoding (or (get-default-encoding) #$NSISOLatin1StringEncoding)))
+            (setq string (#/stringWithContentsOfURL:encoding:error:
+                          ns:ns-string
+                          url
+                          selected-encoding
+                          perror)))
+          (setq selected-encoding (pref pused-encoding :<NSS>tring<E>ncoding)))
+        (unless (%null-ptr-p string)
+          (with-slots (encoding) self (setq encoding selected-encoding))
+
+          ;; ** TODO: Argh.  How about we just let hemlock insert it.
+          (let* ((textstorage (slot-value self 'textstorage))
+                 (display (hemlock-buffer-string-cache (#/hemlockString textstorage)))
+                 (hi::*current-buffer* buffer))
+            (hemlock-ext:invoke-modifying-buffer-storage
+             buffer
+             #'(lambda ()
+                 (nsstring-to-buffer string buffer)
+                 (reset-buffer-cache display) 
+                 (#/updateMirror textstorage)
+                 (update-line-cache-for-index display 0)
+                 (textstorage-note-insertion-at-position
+                  textstorage
+                  0
+                  (hemlock-buffer-length buffer))
+                 (hi::note-modeline-change buffer)
+                 (setf (hi::buffer-modified buffer) nil))))
+          t)))))
+
+
+
+
+(def-cocoa-default *editor-keep-backup-files* :bool t "maintain backup files")
+
+(objc:defmethod (#/keepBackupFile :<BOOL>) ((self hemlock-editor-document))
+  ;;; Don't use the NSDocument backup file scheme.
+  nil)
+
+(objc:defmethod (#/writeSafelyToURL:ofType:forSaveOperation:error: :<BOOL>)
+    ((self hemlock-editor-document)
+     absolute-url
+     type
+     (save-operation :<NSS>ave<O>peration<T>ype)
+     (error (:* :id)))
+  (when (and *editor-keep-backup-files*
+             (eql save-operation #$NSSaveOperation))
+    (write-hemlock-backup-file (#/fileURL self)))
+  (call-next-method absolute-url type save-operation error))
+
+(defun write-hemlock-backup-file (url)
+  (unless (%null-ptr-p url)
+    (when (#/isFileURL url)
+      (let* ((path (#/path url)))
+        (unless (%null-ptr-p path)
+          (let* ((newpath (#/stringByAppendingString: path #@"~"))
+                 (fm (#/defaultManager ns:ns-file-manager)))
+            ;; There are all kinds of ways for this to lose.
+            ;; In order for the copy to succeed, the destination can't exist.
+            ;; (It might exist, but be a directory, or there could be
+            ;; permission problems ...)
+            (#/removeFileAtPath:handler: fm newpath +null-ptr+)
+            (#/copyPath:toPath:handler: fm path newpath +null-ptr+)))))))
+
+             
+
+
+
+(defun hemlock-ext:all-hemlock-views ()
+  "List of all hemlock views, in z-order, frontmost first"
+  (loop for win in (windows)
+    as buf = (and (typep win 'hemlock-frame) (hemlock-view win))
+    when buf collect buf))
+
+(defmethod document-panes ((document hemlock-editor-document))
+  (let* ((ts (slot-value document 'textstorage))
+	 (panes ()))
+    (for-each-textview-using-storage
+     ts
+     #'(lambda (tv)
+	 (let* ((pane (text-view-pane tv)))
+	   (unless (%null-ptr-p pane)
+	     (push pane panes)))))
+    panes))
+
+(objc:defmethod (#/noteEncodingChange: :void) ((self hemlock-editor-document)
+                                               popup)
+  (with-slots (encoding) self
+    (setq encoding (nsinteger-to-nsstring-encoding (#/selectedTag popup)))
+    (hi::note-modeline-change (hemlock-buffer self))))
+
+#-cocotron
+(objc:defmethod (#/prepareSavePanel: :<BOOL>) ((self hemlock-editor-document)
+                                               panel)
+  (with-slots (encoding) self
+    (let* ((popup (build-encodings-popup (#/sharedDocumentController hemlock-document-controller) encoding)))
+      (#/setAction: popup (@selector #/noteEncodingChange:))
+      (#/setTarget: popup self)
+      (#/setAccessoryView: panel popup)))
+  (#/setExtensionHidden: panel nil)
+  (#/setCanSelectHiddenExtension: panel nil)
+  (#/setAllowedFileTypes: panel +null-ptr+)
+  (call-next-method panel))
+
+
+(defloadvar *ns-cr-string* (%make-nsstring (string #\return)))
+(defloadvar *ns-lf-string* (%make-nsstring (string #\linefeed)))
+(defloadvar *ns-crlf-string* (with-autorelease-pool (#/retain (#/stringByAppendingString: *ns-cr-string* *ns-lf-string*))))
+
+(objc:defmethod (#/writeToURL:ofType:error: :<BOOL>)
+    ((self hemlock-editor-document) url type (error (:* :id)))
+  (declare (ignore type))
+  (with-slots (encoding textstorage) self
+    (let* ((string (#/string textstorage))
+           (buffer (hemlock-buffer self)))
+      (case (when buffer (hi::buffer-line-termination buffer))
+        (:crlf (unless (typep string 'ns:ns-mutable-string)
+		 (setq string (make-instance 'ns:ns-mutable-string :with string string))
+		 (#/replaceOccurrencesOfString:withString:options:range:
+		  string *ns-lf-string* *ns-crlf-string* #$NSLiteralSearch (ns:make-ns-range 0 (#/length string)))))
+        (:cr (setq string (if (typep string 'ns:ns-mutable-string)
+			    string
+			    (make-instance 'ns:ns-mutable-string :with string string)))
+	     (#/replaceOccurrencesOfString:withString:options:range:
+	      string *ns-lf-string* *ns-cr-string* #$NSLiteralSearch (ns:make-ns-range 0 (#/length string)))))
+      (when (#/writeToURL:atomically:encoding:error:
+             string url t encoding error)
+        (when buffer
+          (setf (hi::buffer-modified buffer) nil))
+        t))))
+
+;;; Cocotron's NSDocument uses the deprecated as of 10.4 methods to implement the NSSavePanel
+#+cocotron
+(objc:defmethod (#/writeToFile:ofType: :<BOOL>)
+    ((self hemlock-editor-document) path type)
+  (rlet ((perror :id +null-ptr+))
+    (#/writeToURL:ofType:error: self (#/fileURLWithPath: ns:ns-url path) type perror)))
+
+
+;;; Shadow the setFileURL: method, so that we can keep the buffer
+;;; name and pathname in synch with the document.
+(objc:defmethod (#/setFileURL: :void) ((self hemlock-editor-document)
+                                        url)
+  (call-next-method url)
+  (let* ((path nil)
+         (controllers (#/windowControllers self)))
+    (dotimes (i (#/count controllers))
+      (let* ((controller (#/objectAtIndex: controllers i))
+             (window (#/window controller)))
+        (#/setFrameAutosaveName: window (or path (setq path (#/path url)))))))
+  (let* ((buffer (hemlock-buffer self)))
+    (when buffer
+      (let* ((new-pathname (lisp-string-from-nsstring (#/path url))))
+	(setf (hi::buffer-name buffer) (hi::pathname-to-buffer-name new-pathname))
+	(setf (hi::buffer-pathname buffer) new-pathname)))))
+
+
+(def-cocoa-default *initial-editor-x-pos* :float 20.0f0 "X position of upper-left corner of initial editor")
+
+(def-cocoa-default *initial-editor-y-pos* :float 10.0f0 "Y position of upper-left corner of initial editor")
+
+(defloadvar *editor-cascade-point* nil)
+
+(defloadvar *next-editor-x-pos* nil) ; set after defaults initialized
+(defloadvar *next-editor-y-pos* nil)
+
+(defun x-pos-for-window (window x)
+  (let* ((frame (#/frame window))
+         (screen (#/screen window)))
+    (if (%null-ptr-p screen) (setq screen (#/mainScreen ns:ns-screen)))
+    (let* ((screen-rect (#/visibleFrame screen)))
+      (if (>= x 0)
+        (+ x (ns:ns-rect-x screen-rect))
+        (- (+ (ns:ns-rect-width screen-rect) x) (ns:ns-rect-width frame))))))
+
+(defun y-pos-for-window (window y)
+  (let* ((frame (#/frame window))
+         (screen (#/screen window)))
+    (if (%null-ptr-p screen) (setq screen (#/mainScreen ns:ns-screen)))
+    (let* ((screen-rect (#/visibleFrame screen)))
+      (if (>= y 0)
+        (+ y (ns:ns-rect-y screen-rect) (ns:ns-rect-height frame))
+        (+ (ns:ns-rect-height screen-rect) y)))))
+
+(objc:defmethod (#/makeWindowControllers :void) ((self hemlock-editor-document))
+  #+debug
+  (#_NSLog #@"Make window controllers")
+    (let* ((textstorage  (slot-value self 'textstorage))
+           (window (%hemlock-frame-for-textstorage
+                    hemlock-frame
+                    textstorage
+                    *editor-columns*
+                    *editor-rows*
+                    nil
+                    (textview-background-color self)
+                    (user-input-style self)))
+           (controller (make-instance
+                           'hemlock-editor-window-controller
+                         :with-window window))
+           (url (#/fileURL self))
+           (path (unless (%null-ptr-p url) (#/path url))))
+      ;;(#/setDelegate: window self)
+      (#/setDelegate: window controller)
+      (#/setDelegate: (text-pane-text-view (slot-value window 'pane)) self)
+      (#/addWindowController: self controller)
+      (#/release controller)
+      (#/setShouldCascadeWindows: controller nil)
+      (when path
+        (unless (#/setFrameAutosaveName: window path)
+          (setq path nil)))
+      (unless (and path
+                   (#/setFrameUsingName: window path))
+        ;; Cascade windows from the top left corner of the topmost editor window.
+        ;; If there's no editor window, use the default position.
+        (flet ((editor-window-p (w)
+                 (and (not (eql w window))
+                      (eql (#/class (#/windowController w))
+                           (find-class 'hemlock-editor-window-controller)))))
+          (let* ((editors (remove-if-not #'editor-window-p (windows)))
+                 (top-editor (car editors)))
+            (if top-editor
+              (ns:with-ns-point (zp 0 0)
+                (setq *editor-cascade-point* (#/cascadeTopLeftFromPoint:
+                                              top-editor zp)))
+              (let* ((screen-frame (#/visibleFrame (#/screen window)))
+                     (pt (ns:make-ns-point *initial-editor-x-pos*
+                                           (- (ns:ns-rect-height screen-frame)
+                                              *initial-editor-y-pos*))))
+                (setq *editor-cascade-point* pt)))))
+        (#/cascadeTopLeftFromPoint: window *editor-cascade-point*))
+      (let ((view (hemlock-view window)))
+        (hi::handle-hemlock-event view #'(lambda ()
+                                           (hi::process-file-options))))
+      (#/synchronizeWindowTitleWithDocumentName controller)))
+
+
+(objc:defmethod (#/close :void) ((self hemlock-editor-document))
+  #+debug
+  (#_NSLog #@"Document close: %@" :id self)
+  (let* ((textstorage (slot-value self 'textstorage)))
+    (unless (%null-ptr-p textstorage)
+      (setf (slot-value self 'textstorage) (%null-ptr))
+      #+huh?
+      (for-each-textview-using-storage
+       textstorage
+       #'(lambda (tv)
+           (let* ((layout (#/layoutManager tv)))
+             (#/setBackgroundLayoutEnabled: layout nil))))
+      (close-hemlock-textstorage textstorage)))
+  (call-next-method))
+
+(objc:defmethod (#/dealloc :void) ((self hemlock-editor-document))
+  (let* ((textstorage (slot-value self 'textstorage)))
+    (unless (%null-ptr-p textstorage)
+      (setf (slot-value self 'textstorage) (%null-ptr))
+      (close-hemlock-textstorage textstorage)))
+  (call-next-method))
+
+
+
+(defmethod view-screen-lines ((view hi:hemlock-view))
+    (let* ((pane (hi::hemlock-view-pane view)))
+      (floor (ns:ns-size-height (#/contentSize (text-pane-scroll-view pane)))
+             (text-view-line-height (text-pane-text-view pane)))))
+
+;; Beware this doesn't seem to take horizontal scrolling into account.
+(defun visible-charpos-range (tv)
+  (let* ((rect (#/visibleRect tv))
+         (container-origin (#/textContainerOrigin tv))
+         (layout (#/layoutManager tv)))
+    ;; Convert from view coordinates to container coordinates
+    (decf (pref rect :<NSR>ect.origin.x) (pref container-origin :<NSP>oint.x))
+    (decf (pref rect :<NSR>ect.origin.y) (pref container-origin :<NSP>oint.y))
+    (let* ((glyph-range (#/glyphRangeForBoundingRect:inTextContainer:
+                         layout rect (#/textContainer tv)))
+           (char-range (#/characterRangeForGlyphRange:actualGlyphRange:
+                        layout glyph-range +null-ptr+)))
+      (values (pref char-range :<NSR>ange.location)
+              (pref char-range :<NSR>ange.length)))))
+
+(defun charpos-xy (tv charpos)
+  (let* ((layout (#/layoutManager tv))
+         (glyph-range (#/glyphRangeForCharacterRange:actualCharacterRange:
+                       layout
+                       (ns:make-ns-range charpos 0)
+                       +null-ptr+))
+         (rect (#/boundingRectForGlyphRange:inTextContainer:
+                layout
+                glyph-range
+                (#/textContainer tv)))
+         (container-origin (#/textContainerOrigin tv)))
+    (values (+ (pref rect :<NSR>ect.origin.x) (pref container-origin :<NSP>oint.x))
+            (+ (pref rect :<NSR>ect.origin.y) (pref container-origin :<NSP>oint.y)))))
+
+;;(nth-value 1 (charpos-xy tv (visible-charpos-range tv))) - this is smaller as it
+;; only includes lines fully scrolled off...
+(defun text-view-vscroll (tv)
+  ;; Return the number of pixels scrolled off the top of the view.
+  (let* ((scroll-view (text-pane-scroll-view (text-view-pane tv)))
+         (clip-view (#/contentView scroll-view))
+         (bounds (#/bounds clip-view)))
+    (ns:ns-rect-y bounds)))
+
+(defun set-text-view-vscroll (tv vscroll)
+  (let* ((scroll-view (text-pane-scroll-view (text-view-pane tv)))
+         (clip-view (#/contentView scroll-view))
+         (bounds (#/bounds clip-view)))
+    (decf vscroll (mod vscroll (text-view-line-height tv))) ;; show whole line
+    (ns:with-ns-point (new-origin (ns:ns-rect-x bounds) vscroll)
+      (#/scrollToPoint: clip-view (#/constrainScrollPoint: clip-view new-origin))
+      (#/reflectScrolledClipView: scroll-view clip-view))))
+
+(defun scroll-by-lines (tv nlines)
+  "Change the vertical origin of the containing scrollview's clipview"
+  (set-text-view-vscroll tv (+ (text-view-vscroll tv)
+                               (* nlines (text-view-line-height tv)))))
+
+;; TODO: should be a hemlock variable..
+(defvar *next-screen-context-lines* 2)
+
+(defmethod hemlock-ext:scroll-view ((view hi:hemlock-view) how &optional where)
+  (assume-cocoa-thread)
+  (let* ((tv (text-pane-text-view (hi::hemlock-view-pane view)))
+         (may-change-selection t))
+    (when (eq how :line)
+      (setq where (require-type where '(integer 0)))
+      (let* ((line-y (nth-value 1 (charpos-xy tv where)))
+             (top-y (text-view-vscroll tv))
+             (nlines (floor (- line-y top-y) (text-view-line-height tv))))
+        (setq how :lines-down where nlines)))
+    (ecase how
+      (:center-selection
+       (#/centerSelectionInVisibleArea: tv +null-ptr+))
+      ((:page-up :view-page-up)
+       (when (eq how :view-page-up)
+         (setq may-change-selection nil))
+       (require-type where 'null)
+       ;; TODO: next-screen-context-lines
+       (scroll-by-lines tv (- *next-screen-context-lines* (view-screen-lines view))))
+      ((:page-down :view-page-down)
+       (when (eq how :view-page-down)
+         (setq may-change-selection nil))
+       (require-type where 'null)
+       (scroll-by-lines tv (- (view-screen-lines view) *next-screen-context-lines*)))
+      (:lines-up
+       (scroll-by-lines tv (- (require-type where 'integer))))
+      (:lines-down
+       (scroll-by-lines tv (require-type where 'integer))))
+    ;; If point is not on screen, move it.
+    (when may-change-selection
+      (let* ((point (hi::current-point))
+             (point-pos (hi::mark-absolute-position point)))
+        (multiple-value-bind (win-pos win-len) (visible-charpos-range tv)
+          (unless (and (<= win-pos point-pos) (< point-pos (+ win-pos win-len)))
+            (let* ((point (hi::current-point-collapsing-selection))
+                   (cache (hemlock-buffer-string-cache (#/hemlockString (#/textStorage tv)))))
+              (move-hemlock-mark-to-absolute-position point cache win-pos)
+              (update-hemlock-selection (#/textStorage tv)))))))))
+
+(defun iana-charset-name-of-nsstringencoding (ns)
+  #+cocotron (declare (ignore ns))
+  #+cocotron +null-ptr+
+  #-cocotron
+  (#_CFStringConvertEncodingToIANACharSetName
+   (#_CFStringConvertNSStringEncodingToEncoding ns)))
+    
+(defun nsstring-for-nsstring-encoding (ns)
+  (let* ((iana (iana-charset-name-of-nsstringencoding ns)))
+    (if (%null-ptr-p iana)
+      (#/stringWithFormat: ns:ns-string #@"{%@}"
+                           (#/localizedNameOfStringEncoding: ns:ns-string ns))
+      iana)))
+
+;;; Return T if the specified #>NSStringEncoding names something that
+;;; CCL supports.  (Could also have a set of other encoding names that
+;;; the user is interested in, maintained by preferences.
+
+(defun supported-string-encoding-p (ns-string-encoding)
+  #-cocotron
+  (let* ((cfname (#_CFStringConvertEncodingToIANACharSetName
+                  (#_CFStringConvertNSStringEncodingToEncoding ns-string-encoding)))
+         (name (unless (%null-ptr-p cfname)
+                 (nstring-upcase (ccl::lisp-string-from-nsstring cfname))))
+         (keyword (when (and name (find-symbol name "KEYWORD"))
+                    (intern name "KEYWORD"))))
+    (or (and keyword (not (null (lookup-character-encoding keyword))))
+        ;; look in other table maintained by preferences
+        )))
+    
+         
+
+
+  
+;;; Return a list of :<NSS>tring<E>ncodings, sorted by the
+;;; (localized) name of each encoding.
+(defun supported-nsstring-encodings ()
+  (ccl::collect ((ids))
+    (let* ((ns-ids (#/availableStringEncodings ns:ns-string)))
+      (unless (%null-ptr-p ns-ids)
+        (do* ((i 0 (1+ i)))
+             ()
+          (let* ((id (paref ns-ids (:* :<NSS>tring<E>ncoding) i)))
+            (if (zerop id)
+              (return (sort (ids)
+                            #'(lambda (x y)
+                                (= #$NSOrderedAscending
+                                   (#/localizedCompare:
+                                    (nsstring-for-nsstring-encoding x)
+                                    (nsstring-for-nsstring-encoding y))))))
+              (when (supported-string-encoding-p id)              
+                (ids id)))))))))
+
+
+
+
+
+;;; TexEdit.app has support for allowing the encoding list in this
+;;; popup to be customized (e.g., to suppress encodings that the
+;;; user isn't interested in.)
+(defmethod build-encodings-popup ((self hemlock-document-controller)
+                                  &optional (preferred-encoding (get-default-encoding)))
+  (let* ((id-list (supported-nsstring-encodings))
+         (popup (make-instance 'ns:ns-pop-up-button)))
+    ;;; Add a fake "Automatic" item with tag 0.
+    (#/addItemWithTitle: popup #@"Automatic")
+    (#/setTag: (#/itemAtIndex: popup 0) 0)
+    (dolist (id id-list)
+      (#/addItemWithTitle: popup (nsstring-for-nsstring-encoding id))
+      (#/setTag: (#/lastItem popup) (nsstring-encoding-to-nsinteger id)))
+    (when preferred-encoding
+      (#/selectItemWithTag: popup (nsstring-encoding-to-nsinteger preferred-encoding)))
+    (#/sizeToFit popup)
+    popup))
+
+
+(objc:defmethod (#/runModalOpenPanel:forTypes: :<NSI>nteger)
+    ((self hemlock-document-controller) panel types)
+  (let* (#-cocotron (popup (build-encodings-popup self #|preferred|#)))
+    #-cocotron (#/setAccessoryView: panel popup)
+    (let* ((result (call-next-method panel types)))
+      (when (= result #$NSOKButton)
+        #-cocotron
+        (with-slots (last-encoding) self
+          (setq last-encoding
+                (nsinteger-to-nsstring-encoding (#/tag (#/selectedItem popup))))))
+      result)))
+  
+(defun hemlock-ext:open-hemlock-buffer (&key (pathname :prompt))
+  (assert (eq pathname :prompt)) ;; TODO: should handle pathname
+  (#/performSelectorOnMainThread:withObject:waitUntilDone:
+   (#/sharedDocumentController hemlock-document-controller)
+   (@selector #/openDocument:) +null-ptr+ t))
+  
+(defun hemlock-ext:save-hemlock-buffer (buffer &key pathname copy)
+  (let ((doc (hi::buffer-document buffer)))
+    (cond (copy
+           (assert (eq pathname :prompt)) ;; TODO: should handle pathname
+           (save-hemlock-document-as doc))
+          ((null pathname)
+           (save-hemlock-document doc))
+          (t
+           (assert (eq pathname :prompt)) ;; TODO: should handle pathname
+           (save-hemlock-document-to doc)))))
+
+(defmethod save-hemlock-document ((self hemlock-editor-document))
+  (#/performSelectorOnMainThread:withObject:waitUntilDone:
+   self (@selector #/saveDocument:) +null-ptr+ t))
+
+(defmethod save-hemlock-document-as ((self hemlock-editor-document))
+  (#/performSelectorOnMainThread:withObject:waitUntilDone:
+   self (@selector #/saveDocumentAs:) +null-ptr+ t))
+
+(defmethod save-hemlock-document-to ((self hemlock-editor-document))
+  (#/performSelectorOnMainThread:withObject:waitUntilDone:
+   self (@selector #/saveDocumentTo:) +null-ptr+ t))
+
+
+(defun maybe-fixup-application-menu ()
+  ;; If the CFBundleName isn't #@"Clozure CL", then set the
+  ;; title of any menu item on the application menu that ends
+  ;; in #@"Clozure CL" to the CFBundleName.
+  (let* ((bundle (#/mainBundle ns:ns-bundle))
+         (dict (#/infoDictionary bundle))
+         (cfbundlename (#/objectForKey: dict #@"CFBundleName"))
+         (targetname #@"Clozure CL"))
+    (unless (#/isEqualToString: cfbundlename targetname)
+      (let* ((appmenu (#/submenu (#/itemAtIndex: (#/mainMenu *nsapp*)  0)))
+             (numitems (#/numberOfItems appmenu)))
+        (dotimes (i numitems)
+          (let* ((item (#/itemAtIndex: appmenu i))
+                 (title (#/title item)))
+            (unless (%null-ptr-p title)
+              (when (#/hasSuffix: title targetname)
+                (let ((new-title (#/mutableCopy title)))
+                  (ns:with-ns-range (r 0 (#/length new-title))
+                    (#/replaceOccurrencesOfString:withString:options:range:
+                     new-title targetname cfbundlename #$NSLiteralSearch r))
+                  (#/setTitle: item new-title)
+                  (#/release new-title))))))))))
+
+(defun initialize-user-interface ()
+  ;; The first created instance of an NSDocumentController (or
+  ;; subclass thereof) becomes the shared document controller.  So it
+  ;; may look like we're dropping this instance on the floor, but
+  ;; we're really not.
+  (maybe-fixup-application-menu)
+  (make-instance 'hemlock-document-controller)
+  ;(#/sharedPanel lisp-preferences-panel)
+  (make-editor-style-map))
+
+;;; This needs to run on the main thread.  Sets the cocoa selection from the
+;;; hemlock selection.
+(defmethod update-hemlock-selection ((self hemlock-text-storage))
+  (assume-cocoa-thread)
+  (let ((buffer (hemlock-buffer self)))
+    (multiple-value-bind (start end) (hi:buffer-selection-range buffer)
+      #+debug
+      (#_NSLog #@"update Hemlock selection: charpos = %d, abspos = %d"
+               :int (hi::mark-charpos (hi::buffer-point buffer)) :int start)
+      (for-each-textview-using-storage
+       self
+       #'(lambda (tv)
+           (#/updateSelection:length:affinity: tv
+                                               start
+                                               (- end start)
+                                               (if (eql start 0)
+                                                 #$NSSelectionAffinityUpstream
+                                                 #$NSSelectionAffinityDownstream)))))))
+
+;; This should be invoked by any command that modifies the buffer, so it can show the
+;; user what happened...  This ensures the Cocoa selection is made visible, so it
+;; assumes the Cocoa selection has already been synchronized with the hemlock one.
+(defmethod hemlock-ext:ensure-selection-visible ((view hi:hemlock-view))
+  (let ((tv (text-pane-text-view (hi::hemlock-view-pane view))))
+    (#/scrollRangeToVisible: tv (#/selectedRange tv))))
+
+(defloadvar *general-pasteboard* nil)
+
+(defun general-pasteboard ()
+  (or *general-pasteboard*
+      (setq *general-pasteboard*
+            (#/retain (#/generalPasteboard ns:ns-pasteboard)))))
+
+(defloadvar *string-pasteboard-types* ())
+
+(defun string-pasteboard-types ()
+  (or *string-pasteboard-types*
+      (setq *string-pasteboard-types*
+            (#/retain (#/arrayWithObject: ns:ns-array #&NSStringPboardType)))))
+
+
+(objc:defmethod (#/stringToPasteBoard:  :void)
+    ((self lisp-application) string)
+  (let* ((pb (general-pasteboard)))
+    (#/declareTypes:owner: pb (string-pasteboard-types) nil)
+    (#/setString:forType: pb string #&NSStringPboardType)))
+    
+(defun hemlock-ext:string-to-clipboard (string)
+  (when (> (length string) 0)
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     *nsapp* (@selector #/stringToPasteBoard:) (%make-nsstring string) t)))
+
+;;; The default #/paste method seems to want to set the font to
+;;; something ... inappropriate.  If we can figure out why it
+;;; does that and persuade it not to, we wouldn't have to do
+;;; this here.
+;;; (It's likely to also be the case that Carbon applications
+;;; terminate lines with #\Return when writing to the clipboard;
+;;; we may need to continue to override this method in order to
+;;; fix that.)
+(objc:defmethod (#/paste: :void) ((self hemlock-textstorage-text-view) sender)
+  (declare (ignorable sender))
+  #+debug (#_NSLog #@"Paste: sender = %@" :id sender)
+  (let* ((pb (general-pasteboard))
+         (string (progn (#/types pb) (#/stringForType: pb #&NSStringPboardType))))
+    #+debug (log-debug "   string = ~s" string)
+    (unless (%null-ptr-p string)
+      (unless (zerop (ns:ns-range-length (#/rangeOfString: string *ns-cr-string*)))
+        (setq string (make-instance 'ns:ns-mutable-string :with-string string))
+        (#/replaceOccurrencesOfString:withString:options:range:
+                string *ns-cr-string* *ns-lf-string* #$NSLiteralSearch (ns:make-ns-range 0 (#/length string))))
+      (let* ((textstorage (#/textStorage self)))
+        (unless (#/shouldChangeTextInRange:replacementString: self (#/selectedRange self) string)
+          (#/setSelectedRange: self (ns:make-ns-range (#/length textstorage) 0)))
+	(let* ((selectedrange (#/selectedRange self)))
+          ;; We really should bracket the call to
+          ;; #/repaceCharactersInRange:withString: here with calls
+          ;; to #/beginEditing and #/endEditing, but our implementation
+          ;; of #/replaceCharactersInRange:withString: calls code that
+          ;; asserts that editing isn't in progress.  Once that's
+          ;; fixed, this should be fixed as well.
+          (#/beginEditing textstorage)
+	  (#/replaceCharactersInRange:withString: textstorage selectedrange string)
+          (#/endEditing textstorage)
+          (update-hemlock-selection textstorage) )))))
+
+
+(objc:defmethod (#/hyperSpecLookUp: :void)
+    ((self hemlock-text-view) sender)
+  (declare (ignore sender))
+  (let* ((range (#/selectedRange self)))
+    (unless (eql 0 (ns:ns-range-length range))
+      (let* ((string (nstring-upcase (lisp-string-from-nsstring (#/substringWithRange: (#/string (#/textStorage self)) range)))))
+        (multiple-value-bind (symbol win) (find-symbol string "CL")
+          (when win
+            (lookup-hyperspec-symbol symbol self)))))))
+
+
+;; This is called by stuff that makes a window programmatically, e.g. m-. or grep.
+;; But the Open and New menus invoke the cocoa fns below directly. So just changing
+;; things here will not change how the menus create views.  Instead,f make changes to
+;; the subfunctions invoked by the below, e.g. #/readFromURL or #/makeWindowControllers.
+(defun find-or-make-hemlock-view (&optional pathname)
+  (assume-cocoa-thread)
+  (rlet ((perror :id +null-ptr+))
+    (let* ((doc (if pathname
+                  (#/openDocumentWithContentsOfURL:display:error:
+                   (#/sharedDocumentController ns:ns-document-controller)
+                   (pathname-to-url pathname)
+                   #$YES
+                   perror)
+                  (let ((*last-document-created* nil))
+                    (#/newDocument: 
+                     (#/sharedDocumentController hemlock-document-controller)
+                     +null-ptr+)
+                    *last-document-created*))))
+      #+debug (log-debug "created ~s" doc)
+      (when (%null-ptr-p doc)
+        (error "Couldn't open ~s: ~a" pathname
+               (let ((error (pref perror :id)))
+                 (if (%null-ptr-p error)
+                   "unknown error encountered"
+                   (lisp-string-from-nsstring (#/localizedDescription error))))))
+      (front-view-for-buffer (hemlock-buffer doc)))))
+
+(defun hemlock-ext:execute-in-file-view (pathname thunk)
+  (execute-in-gui #'(lambda ()
+                      (assume-cocoa-thread)
+                      (let ((view (find-or-make-hemlock-view pathname)))
+                        (hi::handle-hemlock-event view thunk)))))
+
+(defun hemlock-ext:open-sequence-dialog (&key title sequence action (printer #'prin1))
+  (make-instance 'sequence-window-controller
+    :title title
+    :sequence sequence
+    :result-callback action
+    :display printer))
+
+(objc:defmethod (#/documentClassForType: :<C>lass) ((self hemlock-document-controller)
+						    type)
+  (if (#/isEqualToString: type #@"html")
+      display-document
+      (call-next-method type)))
+      
+
+(objc:defmethod #/newDisplayDocumentWithTitle:content:
+		((self hemlock-document-controller)
+		 title
+		 string)
+  (assume-cocoa-thread)
+  (let* ((doc (#/makeUntitledDocumentOfType:error: self #@"html" +null-ptr+)))
+    (unless (%null-ptr-p doc)
+      (#/addDocument: self doc)
+      (#/makeWindowControllers doc)
+      (let* ((window (#/window (#/objectAtIndex: (#/windowControllers doc) 0))))
+	(#/setTitle: window title)
+	(let* ((tv (slot-value doc 'text-view))
+	       (lm (#/layoutManager tv))
+	       (ts (#/textStorage lm)))
+	  (#/beginEditing ts)
+	  (#/replaceCharactersInRange:withAttributedString:
+	   ts
+	   (ns:make-ns-range 0 (#/length ts))
+	   string)
+	  (#/endEditing ts))
+	(#/makeKeyAndOrderFront: window self)))
+    doc))
+
+(defun hemlock-ext:revert-hemlock-buffer (buffer)
+  (let* ((doc (hi::buffer-document buffer)))
+    (when doc
+      (#/performSelectorOnMainThread:withObject:waitUntilDone:
+       doc
+       (@selector #/revertDocumentToSaved:)
+       +null-ptr+
+       t))))
+
+(defun hemlock-ext:raise-buffer-view (buffer &optional action)
+  "Bring a window containing buffer to front and then execute action in
+   the window.  Returns before operation completes."
+  ;; Queue for after this event, so don't screw up current context.
+  (queue-for-gui #'(lambda ()
+                     (let ((doc (hi::buffer-document buffer)))
+                       (unless (and doc (not (%null-ptr-p doc)))
+                         (hi:editor-error "Deleted buffer: ~s" buffer))
+                       (#/showWindows doc)
+                       (when action
+                         (hi::handle-hemlock-event (front-view-for-buffer buffer) action))))))
+
+;;; Enable CL:ED
+(defun cocoa-edit (&optional arg)
+  (cond ((or (null arg)
+             (typep arg 'string)
+             (typep arg 'pathname))
+         (when arg
+           (unless (probe-file arg)
+             (let ((lpath (merge-pathnames arg *.lisp-pathname*)))
+               (when (probe-file lpath) (setq arg lpath)))))
+         (execute-in-gui #'(lambda () (find-or-make-hemlock-view arg))))
+        ((ccl::valid-function-name-p arg)
+         (hemlock::edit-definition arg)
+         nil)
+        (t (report-bad-arg arg '(or null string pathname (satisfies ccl::valid-function-name-p))))))
+
+(setq ccl::*resident-editor-hook* 'cocoa-edit)
+
+#-cocotron
+(defclass url-handler-command (ns:ns-script-command)
+  ()
+  (:documentation
+   "Handles AppleEvents that send us URLs to open. Both logical pathnames
+    ('ccl:lib;foo.lisp') and symbols (ccl::*current-process*) can be parsed as a URL
+    with a scheme of 'ccl'. So, we accept those as URLs, and handle them appropriately.")
+  (:metaclass ns:+ns-script-command))
+
+#-cocotron
+(objc:defmethod #/performDefaultImplementation ((self url-handler-command))
+  (let* ((string (ccl::lisp-string-from-nsstring (#/directParameter self)))
+         (symbol (let ((*read-eval* nil))
+                   (handler-case (read-from-string string)
+                     (error () nil)))))
+    (if symbol
+      (hemlock::edit-definition symbol)
+      (execute-in-gui #'(lambda ()
+                          (find-or-make-hemlock-view
+                           (if (probe-file string)
+                             string
+                             (let ((lpath (merge-pathnames string *.lisp-pathname*)))
+                               (when (probe-file lpath)
+                                 lpath))))))))
+  +null-ptr+)
Index: /branches/new-random/cocoa-ide/cocoa-grep.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-grep.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-grep.lisp	(revision 13309)
@@ -0,0 +1,132 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+(defvar *grep-program* "grep")
+
+(defun cocoa-edit-grep-line (file line-num)
+  (assume-cocoa-thread)
+  (let ((view (find-or-make-hemlock-view file)))
+    (hi::handle-hemlock-event view #'(lambda ()
+                                       (edit-grep-line-in-buffer line-num)))))
+
+(defun edit-grep-line-in-buffer (line-num)
+  (let ((point (hi::current-point-collapsing-selection)))
+    (hi::buffer-start point)
+    (unless (hi::line-offset point line-num)
+      (hi::buffer-end point))))
+
+(defun parse-grep-line (line)
+  (let* ((pos1 (position #\: line))
+	 (pos2 (and pos1 (position #\: line :start (1+ pos1))))
+	 (num (and pos2 (ignore-errors
+			 (parse-integer line :start (1+ pos1) :end pos2
+					:junk-allowed nil))))
+	 (file (and num (subseq line 0 pos1))))
+    (when file
+      (values file (1- num)))))
+  
+(defun request-edit-grep-line (line)
+  (multiple-value-bind (file line-num) (parse-grep-line line)
+    (when file
+      (execute-in-gui #'(lambda ()
+                          (cocoa-edit-grep-line file line-num))))))
+
+(defun grep-comment-line-p (line)
+  (multiple-value-bind (file line-num) (parse-grep-line line)
+    #+gz (when (member "archive" (pathname-directory file) :test #'equalp)
+	   (return-from grep-comment-line-p t))
+    (with-open-file (stream file)
+      (loop while (> line-num 0)
+	for ch = (read-char stream nil nil)
+	when (null ch) do (return nil)
+	do (when (member ch '(#\Return #\Linefeed))
+	     (decf line-num)
+	     (when (and (eql ch #\Return)
+			(eql (peek-char nil stream nil nil) #\Linefeed))
+	       (read-char stream))))
+      (when (eql line-num 0)
+	(loop as ch = (read-char stream nil nil)
+	  while (and ch (whitespacep ch) (not (member ch '(#\Return #\Linefeed))))
+	  finally (return (eql ch #\;)))))))
+
+(defun grep-remove-comment-lines (lines)
+  (remove-if #'grep-comment-line-p lines))
+
+(defun split-grep-lines (output)
+  (loop with end = (length output)
+    for start = 0 then (1+ pos)
+    as pos = (or (position #\Newline output :start start :end end) end)
+    when (< start pos) collect (subseq output start pos)
+    while (< pos end)))
+
+(defvar *grep-ignore-case* t)
+(defvar *grep-include-pattern* "*.lisp")
+(defvar *grep-exclude-pattern* "*.lisp~")
+
+(defun grep (pattern directory &key (ignore-case *grep-ignore-case*)
+		                    (include *grep-include-pattern*)
+				    (exclude *grep-exclude-pattern*))
+  (with-output-to-string (stream)
+    (let* ((proc (run-program *grep-program*
+			      (nconc (and include (list "--include" include))
+				     (and exclude (list "--exclude" exclude))
+				     (and ignore-case (list "--ignore-case"))
+				     (list "--recursive"
+					   "--with-filename"
+					   "--line-number"
+                                           "--no-messages"
+					   "-e" pattern
+					   (ccl::native-untranslated-namestring directory)))
+			      :input nil
+			      :output stream)))
+      (multiple-value-bind (status exit-code) (external-process-status proc)
+	(let ((output (get-output-stream-string stream)))
+	  (if (and (eq :exited status) (or (= exit-code 0) (= exit-code 2)))
+	      (let ((lines (split-grep-lines output)))
+		(unless (hi:value hemlock::grep-search-comments)
+		  (setq lines (grep-remove-comment-lines lines)))
+		(make-instance 'sequence-window-controller
+			       :sequence lines
+			       :result-callback #'request-edit-grep-line
+			       :display #'princ
+			       :title (format nil "~a in ~a" pattern directory)))
+            (if (and (eql status :exited)
+                     (eql exit-code 1))
+              (hi:editor-error "Pattern ~s not found" pattern)
+	      (hi:editor-error "Error in grep status ~s code ~s: ~a" status exit-code output))))))))
+
+
+(hi:defhvar "Grep Directory"
+  "The directory searched by \"Grep\".  NIL means to use the directory of the buffer."
+  :value nil)
+
+(hi:defhvar "Grep Search Comments"
+  "If true (the default) grep will find results anywhere.  NIL means to ignore results
+   within comments.  For now only recognizes as comments lines which start with semi-colon."
+  :value t)
+
+(hi:defcommand "Grep" (p)
+  "Prompts for a pattern and invokes grep, searching recursively through .lisp
+   files in \"Grep Directory\".
+   With an argument, prompts for a directory to search, and sets \"Grep Directory\"
+   for the next time."
+  ""
+  (let* ((default (make-pathname :name :unspecific
+				 :type :unspecific
+				 :defaults (or (hi:value hemlock::grep-directory)
+					       (hi:buffer-pathname hi::*current-buffer*)
+					       "ccl:")))
+	 (directory (if p
+			(setf (hi:value hemlock::grep-directory)
+			      (hi:prompt-for-file :must-exist t
+						  :default default
+						  :default-string (namestring default)
+						  :prompt "Directory: "))
+			default))
+	 (pattern (hi:prompt-for-string
+		   :prompt "Pattern: "
+		   :help "Pattern to search for")))
+    (grep pattern directory)))
Index: /branches/new-random/cocoa-ide/cocoa-listener.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-listener.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-listener.lisp	(revision 13309)
@@ -0,0 +1,713 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+(def-cocoa-default *listener-input-font* :font #'(lambda ()
+						   (#/fontWithName:size:
+						    ns:ns-font
+                                                    #+darwin-target
+						    #@"Monaco"
+                                                    #-darwin-target
+                                                    #@"Courier"
+                                                    10.0))
+		   "Default font for listener input")
+(def-cocoa-default *listener-output-font* :font #'(lambda ()
+						    (#/fontWithName:size:
+						     ns:ns-font
+                                                     #+darwin-target
+						     #@"Monaco"
+                                                     #-darwin-target
+                                                     #@"Courier"
+                                                     10.0))
+		   "Default font for listener output")
+
+(def-cocoa-default *listener-rows* :int 16 "Initial height of listener windows, in characters")
+(def-cocoa-default *listener-columns* :int 80 "Initial height of listener windows, in characters")
+
+(def-cocoa-default hi::*listener-output-style* :int 1 "Text style index for listener output")
+
+(def-cocoa-default hi::*listener-input-style* :int 0 "Text style index for listener output")
+
+(def-cocoa-default *listener-background-color* :color '(1.0 1.0 1.0 1.0) "Listener default background color")
+
+(def-cocoa-default *read-only-listener* :bool t "Do not allow editing old listener output")
+
+(defun hemlock-ext:read-only-listener-p ()
+  *read-only-listener*)
+
+
+(defclass cocoa-listener-input-stream (fundamental-character-input-stream)
+  ((queue :initform ())
+   (queue-lock :initform (make-lock))
+   (read-lock :initform (make-lock))
+   (queue-semaphore :initform (make-semaphore)) ;; total queue count
+   (text-semaphore :initform (make-semaphore))  ;; text-only queue count
+   (cur-string :initform nil)
+   (cur-string-pos :initform 0)
+   (cur-env :initform nil)
+   (cur-sstream :initform nil)
+   (cur-offset :initform nil)
+   (source-map :initform nil)
+   (reading-line :initform nil :accessor hi:input-stream-reading-line)))
+
+(defmethod interactive-stream-p ((stream cocoa-listener-input-stream))
+  t)
+
+
+
+
+(defmethod dequeue-listener-char ((stream cocoa-listener-input-stream) wait-p)
+  (with-slots (queue queue-lock read-lock queue-semaphore text-semaphore cur-string cur-string-pos) stream
+    (with-lock-grabbed (read-lock)
+      (or (with-lock-grabbed (queue-lock)
+            (when (< cur-string-pos (length cur-string))
+              (prog1 (aref cur-string cur-string-pos) (incf cur-string-pos))))
+          (loop
+            (unless (if wait-p
+                      (wait-on-semaphore text-semaphore nil "Listener Input")
+                      (timed-wait-on-semaphore text-semaphore 0))
+              (return nil))
+            (assert (timed-wait-on-semaphore queue-semaphore 0) () "queue/text mismatch!")
+            (with-lock-grabbed (queue-lock)
+              (let* ((s (find-if #'stringp queue)))
+                (assert s () "queue/semaphore mismatch!")
+                (setq queue (delq s queue 1))
+                (when (< 0 (length s))
+                  (setf cur-string s cur-string-pos 1)
+                  (return (aref s 0))))))))))
+
+(defmethod ccl::read-toplevel-form ((stream cocoa-listener-input-stream) &key eof-value)
+  (with-slots (queue queue-lock read-lock queue-semaphore text-semaphore cur-string cur-string-pos cur-sstream
+               cur-env source-map cur-offset)
+    stream
+    (with-lock-grabbed (read-lock)
+      (loop
+        (when cur-sstream
+          #+debug (log-debug "About to recursively read from sstring in env: ~s" cur-env)
+          (let* ((env cur-env)
+                 (form (progv (car env) (cdr env)
+                         (ccl::read-toplevel-form cur-sstream
+                                                  :eof-value eof-value
+                                                  :file-name *loading-file-source-file*
+                                                  :start-offset cur-offset
+                                                  :map source-map)))
+                 (last-form-in-selection (not (listen cur-sstream))))
+            #+debug (log-debug " --> ~s" form)
+            (when last-form-in-selection
+              (setf cur-sstream nil cur-env nil))
+            (return (values form env (or last-form-in-selection ccl::*verbose-eval-selection*)))))
+        (when (with-lock-grabbed (queue-lock)
+                (loop
+                  unless (< cur-string-pos (length cur-string)) return nil
+                  unless (whitespacep (aref cur-string cur-string-pos)) return t
+                  do (incf cur-string-pos)))
+          (return (values (call-next-method) nil t)))
+        (wait-on-semaphore queue-semaphore nil "Toplevel Read")
+        (let ((val (with-lock-grabbed (queue-lock) (pop queue))))
+          (cond ((stringp val)
+                 (assert (timed-wait-on-semaphore text-semaphore 0) () "text/queue mismatch!")
+                 (setq cur-string val cur-string-pos 0))
+                (t
+                 (destructuring-bind (string package-name pathname offset) val
+                   ;; This env is used both for read and eval.  *nx-source-note-map* is for the latter.
+                   (let ((env (cons '(*loading-file-source-file* *loading-toplevel-location* ccl::*nx-source-note-map*)
+                                    (list pathname nil source-map))))
+                     (when package-name
+                       (push '*package* (car env))
+                       (push (ccl::pkg-arg package-name) (cdr env)))
+                     (if source-map
+                       (clrhash source-map)
+                       (setf source-map (make-hash-table :test 'eq :shared nil)))
+                     (setf cur-sstream (make-string-input-stream string) cur-env env cur-offset offset))))))))))
+
+(defmethod enqueue-toplevel-form ((stream cocoa-listener-input-stream) string &key package-name pathname offset)
+  (with-slots (queue-lock queue queue-semaphore) stream
+    (with-lock-grabbed (queue-lock)
+      (setq queue (nconc queue (list (list string package-name pathname offset))))
+      (signal-semaphore queue-semaphore))))
+
+(defmethod enqueue-listener-input ((stream cocoa-listener-input-stream) string)
+  (with-slots (queue-lock queue queue-semaphore text-semaphore) stream
+    (with-lock-grabbed (queue-lock)
+      (setq queue (nconc queue (list string)))
+      (signal-semaphore queue-semaphore)
+      (signal-semaphore text-semaphore))))
+
+(defmethod stream-read-char-no-hang ((stream cocoa-listener-input-stream))
+  (dequeue-listener-char stream nil))
+
+(defmethod stream-read-char ((stream cocoa-listener-input-stream))
+  (dequeue-listener-char stream t))
+
+(defmethod stream-unread-char ((stream cocoa-listener-input-stream) char)
+  ;; Can't guarantee the right order of reads/unreads, just make sure not to
+  ;; introduce any internal inconsistencies (and dtrt for the non-conflict case).
+  (with-slots (queue queue-lock queue-semaphore text-semaphore cur-string cur-string-pos) stream
+    (with-lock-grabbed (queue-lock)
+      (cond ((>= cur-string-pos (length cur-string))
+             (push (string char) queue)
+             (signal-semaphore queue-semaphore)
+             (signal-semaphore text-semaphore))
+            ((< 0 cur-string-pos)
+             (decf cur-string-pos)
+             (setf (aref cur-string cur-string-pos) char))
+            (t (setf cur-string (concatenate 'string (string char) cur-string)))))))
+
+(defmethod ccl::stream-eof-transient-p ((stream cocoa-listener-input-stream))
+  t)
+
+(defmethod stream-clear-input ((stream cocoa-listener-input-stream))
+  (with-slots (queue-lock cur-string cur-string-pos cur-sstream cur-env) stream
+    (with-lock-grabbed (queue-lock)
+      (setf (hi::input-stream-reading-line stream) nil)
+      (setf cur-string nil cur-string-pos 0 cur-sstream nil cur-env nil))))
+
+(defmethod stream-read-line ((stream cocoa-listener-input-stream))
+  (let* ((old-reading-line (hi:input-stream-reading-line stream)))
+    (unwind-protect
+         (progn
+           (setf (hi::input-stream-reading-line stream) t)
+           (call-next-method))
+      (setf (hi:input-stream-reading-line stream) old-reading-line))))
+
+(defparameter $listener-flush-limit 4095)
+
+(defclass cocoa-listener-output-stream (fundamental-character-output-stream)
+  ((lock :initform (make-lock))
+   (hemlock-view :initarg :hemlock-view)
+   (data :initform (make-array (1+ $listener-flush-limit)
+                               :adjustable t :fill-pointer 0
+                               :element-type 'character))
+   (limit :initform $listener-flush-limit)))
+
+(defmethod stream-element-type ((stream cocoa-listener-output-stream))
+  (with-slots (data) stream
+    (array-element-type data)))
+
+(defmethod ccl:stream-write-char ((stream cocoa-listener-output-stream) char)
+  (with-slots (data lock limit) stream
+    (when (with-lock-grabbed (lock)
+	    (>= (vector-push-extend char data) limit))
+      (stream-force-output stream))))
+
+;; This isn't really thread safe, but it's not too bad...  I'll take a chance - trying
+;; to get it to execute in the gui thread is too deadlock-prone.
+(defmethod hemlock-listener-output-mark-column ((view hi::hemlock-view))
+  (let* ((output-region (hi::variable-value 'hemlock::current-output-font-region
+					    :buffer (hi::hemlock-view-buffer view))))
+    (hi::mark-charpos (hi::region-end output-region))))
+
+;; TODO: doesn't do the right thing for embedded tabs (in buffer or data)
+(defmethod ccl:stream-line-column ((stream cocoa-listener-output-stream))
+  (with-slots (hemlock-view data lock) stream
+    (with-lock-grabbed (lock)
+      (let* ((n (length data))
+             (pos (position #\Newline data :from-end t)))
+        (if (null pos)
+          (+ (hemlock-listener-output-mark-column hemlock-view) n)
+          (- n pos 1))))))
+
+(defmethod ccl:stream-fresh-line  ((stream cocoa-listener-output-stream))
+  (with-slots (hemlock-view data lock limit) stream
+    (when (with-lock-grabbed (lock)
+            (let ((n (length data)))
+              (unless (if (= n 0)
+                        (= (hemlock-listener-output-mark-column hemlock-view) 0)
+                        (eq (aref data (1- n)) #\Newline))
+                (>= (vector-push-extend #\Newline data) limit))))
+      (stream-force-output stream))))
+
+(defmethod ccl::stream-finish-output ((stream cocoa-listener-output-stream))
+  (stream-force-output stream))
+
+(defmethod ccl:stream-force-output ((stream cocoa-listener-output-stream))
+  (if (typep *current-process* 'appkit-process)
+    (with-slots (hemlock-view data lock) stream
+      (with-lock-grabbed (lock)
+        (when (> (fill-pointer data) 0)
+          (append-output hemlock-view data)
+          (setf (fill-pointer data) 0))))
+    (with-slots (data) stream
+      (when (> (fill-pointer data) 0)
+        (queue-for-gui #'(lambda () (stream-force-output stream)))))))
+
+(defmethod ccl:stream-clear-output ((stream cocoa-listener-output-stream))
+  (with-slots (data lock) stream
+    (with-lock-grabbed (lock)
+      (setf (fill-pointer data) 0))))
+
+(defmethod ccl:stream-line-length ((stream cocoa-listener-output-stream))
+  ;; TODO: ** compute length from window size **
+  80)
+
+
+(defloadvar *cocoa-listener-count* 0)
+
+(defclass cocoa-listener-process (process)
+    ((input-stream :reader cocoa-listener-process-input-stream)
+     (output-stream :reader cocoa-listener-process-output-stream)
+     (backtrace-contexts :initform nil
+                         :accessor cocoa-listener-process-backtrace-contexts)
+     (window :reader cocoa-listener-process-window)))
+  
+(defloadvar *first-listener* t)
+
+(defun new-cocoa-listener-process (procname window)
+  (declare (special *standalone-cocoa-ide*))
+  (let* ((input-stream (make-instance 'cocoa-listener-input-stream))
+         (output-stream (make-instance 'cocoa-listener-output-stream
+                          :hemlock-view (hemlock-view window)))
+         
+         (proc
+          (ccl::make-mcl-listener-process 
+           procname
+           input-stream
+           output-stream
+           ;; cleanup function
+           #'(lambda ()
+               (mapcar #'(lambda (buf)
+                           (when (eq (buffer-process buf) *current-process*)
+                             (let ((doc (hi::buffer-document buf)))
+                               (when doc
+                                 (setf (hemlock-document-process doc) nil) ;; so #/close doesn't kill it.
+                                 (#/performSelectorOnMainThread:withObject:waitUntilDone:
+                                  doc
+                                  (@selector #/close)
+                                  +null-ptr+
+                                  nil)))))
+                       hi:*buffer-list*))
+           :initial-function
+           #'(lambda ()
+               (setq ccl::*listener-autorelease-pool* (create-autorelease-pool))
+               (when (and *standalone-cocoa-ide*
+                        (prog1 *first-listener* (setq *first-listener* nil)))
+                 (ccl::startup-ccl (ccl::application-init-file ccl::*application*))
+                 (ui-object-note-package *nsapp* *package*))
+               (ccl::listener-function))
+           :echoing nil
+           :class 'cocoa-listener-process)))
+    (setf (slot-value proc 'input-stream) input-stream)
+    (setf (slot-value proc 'output-stream) output-stream)
+    (setf (slot-value proc 'window) window)
+    proc))
+  
+(defclass hemlock-listener-frame (hemlock-frame)
+    ()
+  (:metaclass ns:+ns-object))
+(declaim (special hemlock-listener-frame))
+
+(objc:defmethod (#/setDocumentEdited: :void) ((w hemlock-listener-frame)
+                                              (edited #>BOOL))
+  (declare (ignorable edited)))
+
+
+(defclass hemlock-listener-window-controller (hemlock-editor-window-controller)
+    ()
+  (:metaclass ns:+ns-object)
+  )
+(declaim (special hemlock-listener-window-controller))
+
+;;; Listener documents are never (or always) ediited.  Don't cause their
+;;; close boxes to be highlighted.
+(objc:defmethod (#/setDocumentEdited: :void)
+    ((self hemlock-listener-window-controller) (edited :<BOOL>))
+  (declare (ignorable edited)))
+
+
+
+(objc:defmethod #/windowTitleForDocumentDisplayName: ((self hemlock-listener-window-controller) name)
+  (let* ((doc (#/document self)))
+    (if (or (%null-ptr-p doc)
+            (not (%null-ptr-p (#/fileURL doc))))
+      (call-next-method name)
+      (let* ((buffer (hemlock-buffer doc))
+             (bufname (if buffer (hi::buffer-name buffer))))
+        (if bufname
+          (%make-nsstring bufname)
+          (call-next-method name))))))
+
+
+;;; The HemlockListenerDocument class.
+
+
+(defclass hemlock-listener-document (hemlock-editor-document)
+  ((process :reader %hemlock-document-process :writer (setf hemlock-document-process)))
+  (:metaclass ns:+ns-object))
+(declaim (special hemlock-listener-document))
+
+(defgeneric hemlock-document-process (doc)
+  (:method ((unknown t)) nil)
+  (:method ((doc hemlock-listener-document)) (%hemlock-document-process doc)))
+
+;; Nowadays this is nil except for listeners.
+(defun buffer-process (buffer)
+  (hemlock-document-process (hi::buffer-document buffer)))
+
+(defmethod update-buffer-package ((doc hemlock-listener-document) buffer)
+  (declare (ignore buffer)))
+
+(defmethod document-encoding-name ((doc hemlock-listener-document))
+  "UTF-8")
+
+(defmethod user-input-style ((doc hemlock-listener-document))
+  hi::*listener-input-style*)
+  
+(defmethod textview-background-color ((doc hemlock-listener-document))
+  *listener-background-color*)
+
+;; For use with the :process-info listener modeline field
+(defmethod hemlock-ext:buffer-process-description (buffer)
+  (let ((proc (buffer-process buffer)))
+    (when proc
+      (format nil "~a(~d) [~a]"
+              (ccl:process-name proc)
+              (ccl::process-serial-number proc)
+              ;; TODO: this doesn't really work as a modeline item, because the modeline
+              ;; doesn't get notified when it changes.
+              (ccl:process-whostate proc)))))
+
+(objc:defmethod #/topListener ((self +hemlock-listener-document))
+  (let* ((all-documents (#/orderedDocuments *NSApp*)))
+    (dotimes (i (#/count all-documents) +null-ptr+)
+      (let* ((doc (#/objectAtIndex: all-documents i)))
+	(when (eql (#/class doc) self)
+	  (return doc))))))
+
+(defun symbol-value-in-top-listener-process (symbol)
+  (let* ((process (hemlock-document-process (#/topListener hemlock-listener-document))))
+     (if process
+       (ignore-errors (symbol-value-in-process symbol process))
+       (values nil t))))
+  
+(defun hemlock-ext:top-listener-output-stream ()
+  (let* ((process (hemlock-document-process (#/topListener hemlock-listener-document))))
+    (when process
+      (setq process (require-type process 'cocoa-listener-process))
+      (cocoa-listener-process-output-stream process))))
+
+(defun hemlock-ext:top-listener-input-stream ()
+  (let* ((process (hemlock-document-process (#/topListener hemlock-listener-document))))
+    (when process
+      (setq process (require-type process 'cocoa-listener-process))
+      (cocoa-listener-process-input-stream process))))
+
+
+
+(objc:defmethod (#/isDocumentEdited :<BOOL>) ((self hemlock-listener-document))
+  nil)
+
+
+
+(objc:defmethod #/init ((self hemlock-listener-document))
+  (let* ((doc (call-next-method)))
+    (unless (%null-ptr-p doc)
+      (let* ((listener-name (if (eql 1 (incf *cocoa-listener-count*))
+                              "Listener"
+                              (format nil
+                                      "Listener-~d" *cocoa-listener-count*)))
+	     (buffer (hemlock-buffer doc)))
+	(setf (hi::buffer-pathname buffer) nil
+	      (hi::buffer-minor-mode buffer "Listener") t
+	      (hi::buffer-name buffer) listener-name)
+        (hi::set-buffer-modeline-fields buffer hemlock::*listener-modeline-fields*)))
+    doc))
+
+(def-cocoa-default *initial-listener-x-pos* :float -100.0f0 "X position of upper-left corner of initial listener")
+
+(def-cocoa-default *initial-listener-y-pos* :float 100.0f0 "Y position of upper-left corner of initial listener")
+
+(defloadvar *next-listener-x-pos* nil) ; set after defaults initialized
+(defloadvar *next-listener-y-pos* nil) ; likewise
+
+(objc:defmethod (#/close :void) ((self hemlock-listener-document))
+  (if (zerop (decf *cocoa-listener-count*))
+    (setq *next-listener-x-pos* nil
+          *next-listener-y-pos* nil))
+  (let* ((p (shiftf (hemlock-document-process self) nil)))
+    (when p
+      (process-kill p)))
+  (call-next-method))
+
+
+
+(objc:defmethod (#/makeWindowControllers :void) ((self hemlock-listener-document))
+  (let* ((textstorage (slot-value self 'textstorage))
+         (window (%hemlock-frame-for-textstorage
+                  hemlock-listener-frame
+                  textstorage
+                  *listener-columns*
+                  *listener-rows*
+                  t
+                  (textview-background-color self)
+                  (user-input-style self)))
+	 (listener-styles (#/arrayWithObjects: ns:ns-mutable-array
+					       (rme-create-text-attributes
+						:font *listener-input-font*)
+					       (rme-create-text-attributes
+						:font *listener-output-font*)
+					       +null-ptr+))
+	 (controller (make-instance
+		      'hemlock-listener-window-controller
+		      :with-window window))
+	 (listener-name (hi::buffer-name (hemlock-buffer self)))
+         (path (#/windowTitleForDocumentDisplayName: controller (#/displayName self ))))
+    (when (slot-exists-p textstorage 'styles)
+      (with-slots (styles) textstorage
+	;; We probably should be more disciplined about
+	;; Cocoa memory management.  Having retain/release in
+	;; random places all over the code is going to get
+	;; unwieldy.
+	(#/release styles)
+	(setf styles (#/retain listener-styles))))
+    ;; Disabling background layout on listeners is an attempt to work
+    ;; around a bug.  The bug's probably gone ...
+    #-cocotron                          ;no concept of background layout
+    (let* ((layout-managers (#/layoutManagers textstorage)))
+      (dotimes (i (#/count layout-managers))
+        (let* ((layout (#/objectAtIndex: layout-managers i)))
+          (#/setBackgroundLayoutEnabled: layout nil))))
+    (#/setDelegate: window controller)
+    (#/setDelegate: (text-pane-text-view (slot-value window 'pane)) self)
+    (#/setShouldCascadeWindows: controller nil)
+    (#/addWindowController: self controller)
+    (#/release controller)
+    (setf (hemlock-document-process self)
+          (new-cocoa-listener-process listener-name window))
+    (when path
+      (unless (#/setFrameAutosaveName: window path)
+        (setq path nil)))
+    (unless (and path
+                 (when (#/setFrameUsingName: window path)
+                   (let* ((frame (#/frame window)))
+                     (ns:with-ns-point (current-point
+                                        (ns:ns-rect-x frame)
+                                        (+ (ns:ns-rect-y frame)
+                                           (ns:ns-rect-height frame)))
+                        (let* ((next-point (#/cascadeTopLeftFromPoint:
+                                            window
+                                            current-point)))
+                     (setq *next-listener-x-pos*
+                           (ns:ns-point-x next-point)
+                           *next-listener-y-pos*
+                           (ns:ns-point-y next-point)))))
+                   t))
+      (ns:with-ns-point (current-point
+                         (or *next-listener-x-pos*
+                             (x-pos-for-window window *initial-listener-x-pos*))
+                         (or *next-listener-y-pos*
+                             (y-pos-for-window window *initial-listener-y-pos*)))
+        (let* ((new-point (#/cascadeTopLeftFromPoint: window current-point)))
+          (setf *next-listener-x-pos* (ns:ns-point-x new-point)
+                *next-listener-y-pos* (ns:ns-point-y new-point)))))
+    (#/synchronizeWindowTitleWithDocumentName controller)
+    controller))
+
+(objc:defmethod (#/textView:shouldChangeTextInRange:replacementString: :<BOOL>)
+    ((self hemlock-listener-document)
+     tv
+     (range :<NSR>ange)
+     string)
+  (declare (ignore tv string))
+  (let* ((range-start (ns:ns-range-location range))
+         (range-end (+ range-start (ns:ns-range-length range)))
+         (buffer (hemlock-buffer self))
+         (protected-region (hi::buffer-protected-region buffer)))
+    (if protected-region
+      (let* ((prot-start (hi:mark-absolute-position (hi::region-start protected-region)))
+             (prot-end (hi:mark-absolute-position (hi::region-end protected-region))))
+        (not (or (and (>= range-start prot-start)
+                      (< range-start prot-end))
+                 (and (>= range-end prot-start)
+                      (< range-end prot-end)))))
+      t)))
+    
+    
+;;; Action methods
+(objc:defmethod (#/interrupt: :void) ((self hemlock-listener-document) sender)
+  (declare (ignore sender))
+  (let* ((process (hemlock-document-process self)))
+    (when process
+      (ccl::force-break-in-listener process))))
+
+
+
+(objc:defmethod (#/exitBreak: :void) ((self hemlock-listener-document) sender)
+  (declare (ignore sender))
+  (let* ((process (hemlock-document-process self)))
+    #+debug (log-debug  "~&exitBreak process ~s" process)
+    (when process
+      (process-interrupt process #'abort-break))))
+
+(defmethod listener-backtrace-context ((proc cocoa-listener-process))
+  (car (cocoa-listener-process-backtrace-contexts proc)))
+
+(objc:defmethod (#/backtrace: :void) ((self hemlock-listener-document) sender)
+  (let* ((process (hemlock-document-process self)))
+    (when process
+      (let* ((context (listener-backtrace-context process)))
+        (when context
+          (#/makeKeyAndOrderFront: (#/windowForSheet self) nil)
+          (#/showWindow: (backtrace-controller-for-context context) sender))))))
+
+(defun restarts-controller-for-context (context)
+  (or (car (ccl::bt.restarts context))
+      (setf (car (ccl::bt.restarts context))
+            (let* ((tcr (ccl::bt.tcr context))
+                   (tsp-range (inspector::make-tsp-stack-range tcr context))
+                   (vsp-range (inspector::make-vsp-stack-range tcr context))
+                   (csp-range (inspector::make-csp-stack-range tcr context))
+                   (process (ccl::tcr->process tcr)))
+              (make-instance 'sequence-window-controller
+                             :sequence (cdr (ccl::bt.restarts context))
+                             :result-callback #'(lambda (r)
+                                                  (process-interrupt
+                                                   process
+                                                   #'invoke-restart-interactively
+                                                   r))
+                             :display #'(lambda (item stream)
+                                          (let* ((ccl::*aux-vsp-ranges* vsp-range)
+                                                 (ccl::*aux-tsp-ranges* tsp-range)
+                                                 (ccl::*aux-csp-ranges* csp-range))
+                                          (princ item stream)))
+                             :title (format nil "Restarts for ~a(~d), break level ~d"
+                                            (process-name process)
+                                            (process-serial-number process)
+                                            (ccl::bt.break-level context)))))))
+                            
+(objc:defmethod (#/restarts: :void) ((self hemlock-listener-document) sender)
+  (let* ((process (hemlock-document-process self)))
+    (when process
+      (let* ((context (listener-backtrace-context process)))
+        (when context
+          (#/showWindow: (restarts-controller-for-context context) sender))))))
+
+(objc:defmethod (#/continue: :void) ((self hemlock-listener-document) sender)
+  (declare (ignore sender))
+  (let* ((process (hemlock-document-process self)))
+    (when process
+      (let* ((context (listener-backtrace-context process)))
+        (when context
+          (process-interrupt process #'invoke-restart-interactively 'continue))))))
+
+
+
+
+
+
+;;; Menu item action validation.  It'd be nice if we could distribute this a
+;;; bit better, so that this method didn't have to change whenever a new
+;;; action was implemented in this class.  For now, we have to do so.
+
+(defmethod document-validate-menu-item ((doc hemlock-listener-document) item)
+  ;; Return two values: the first is true if the second is definitive.
+  ;; So far, all actions demand that there be an underlying process, so
+  ;; check for that first.
+  (let* ((process (hemlock-document-process doc)))
+    (if process
+      (let* ((action (#/action item)))
+        (cond
+          ((or (eql action (@selector #/revertDocumentToSaved:))
+	       (eql action (@selector #/saveDocument:))
+	       (eql action (@selector #/saveDocumentAs:)))
+           (values t nil))
+          ((eql action (@selector #/interrupt:)) (values t t))
+          ((eql action (@selector #/continue:))
+           (let* ((context (listener-backtrace-context process)))
+             (values
+              t
+              (and context
+                   (find 'continue (cdr (ccl::bt.restarts context))
+                         :key #'restart-name)))))
+          ((or (eql action (@selector #/backtrace:))
+               (eql action (@selector #/exitBreak:))
+               (eql action (@selector #/restarts:)))
+           (values t
+                   (not (null (listener-backtrace-context process)))))))
+      (values nil nil))))
+
+(objc:defmethod (#/validateMenuItem: :<BOOL>)
+    ((self hemlock-listener-document) item)
+  (multiple-value-bind (have-opinion opinion)
+      (document-validate-menu-item self item)
+    (if have-opinion
+      opinion
+      (call-next-method item))))
+
+(defun shortest-package-name (package)
+  (let* ((name (package-name package))
+         (len (length name)))
+    (dolist (nick (package-nicknames package) name)
+      (let* ((nicklen (length nick)))
+        (if (< nicklen len)
+          (setq name nick len nicklen))))))
+
+(defmethod ui-object-note-package ((app ns:ns-application) package)
+  (let ((proc *current-process*)
+        (name (shortest-package-name package)))
+    (execute-in-gui #'(lambda ()
+                        (dolist (buf hi::*buffer-list*)
+                          (when (eq proc (buffer-process buf))
+                            (setf (hi::variable-value 'hemlock::current-package :buffer buf) name)))))))
+
+
+(defmethod eval-in-listener-process ((process cocoa-listener-process)
+                                     string &key path package offset)
+  (enqueue-toplevel-form (cocoa-listener-process-input-stream process) string
+                         :package-name package :pathname path :offset offset))
+
+;;; This is basically used to provide INPUT to the listener process, by
+;;; writing to an fd which is connected to that process's standard
+;;; input.
+(defun hemlock-ext:send-string-to-listener (listener-buffer string)
+  (let* ((process (buffer-process listener-buffer)))
+    (unless process
+      (error "No listener process found for ~s" listener-buffer))
+    (enqueue-listener-input (cocoa-listener-process-input-stream process) string)))
+
+(defmethod ui-object-choose-listener-for-selection ((app ns:ns-application)
+						    selection)
+  (declare (ignore selection))
+  (#/performSelectorOnMainThread:withObject:waitUntilDone:
+   (#/delegate *NSApp*)
+   (@selector #/ensureListener:)
+   +null-ptr+
+   #$YES)
+  (hemlock-document-process (#/topListener hemlock-listener-document)))
+
+(defmethod ui-object-eval-selection ((app ns:ns-application)
+				     selection)
+  (let* ((target-listener (ui-object-choose-listener-for-selection
+			   app selection)))
+    (when target-listener
+      (destructuring-bind (package path string &optional offset) selection
+        (eval-in-listener-process target-listener string :package package :path path :offset offset)))))
+
+(defmethod ui-object-load-buffer ((app ns:ns-application) selection)
+  (let* ((target-listener (ui-object-choose-listener-for-selection app nil)))
+    (when target-listener
+      (destructuring-bind (package path) selection
+        (let ((string (format nil "(load ~S)" path)))
+          (eval-in-listener-process target-listener string :package package))))))
+
+(defmethod ui-object-compile-buffer ((app ns:ns-application) selection)
+  (let* ((target-listener (ui-object-choose-listener-for-selection app nil)))
+    (when target-listener
+      (destructuring-bind (package path) selection
+        (let ((string (format nil "(compile-file ~S)" path)))
+          (eval-in-listener-process target-listener string :package package))))))
+
+(defmethod ui-object-compile-and-load-buffer ((app ns:ns-application) selection)
+  (let* ((target-listener (ui-object-choose-listener-for-selection app nil)))
+    (when target-listener
+      (destructuring-bind (package path) selection
+        (let ((string (format nil "(progn (compile-file ~S)(load ~S))" 
+                              path
+                              (make-pathname :directory (pathname-directory path)
+                                             :name (pathname-name path)
+                                             :type (pathname-type path)))))
+          (eval-in-listener-process target-listener string :package package))))))
+
+       
+ 
Index: /branches/new-random/cocoa-ide/cocoa-prefs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-prefs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-prefs.lisp	(revision 13309)
@@ -0,0 +1,168 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2004 Clozure Associates
+;;;   This file is part of OpenMCL.  
+;;;
+;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with OpenMCL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "GUI")
+
+(defloadvar *lisp-preferences-panel* nil)
+
+(defclass lisp-preferences-panel (ns:ns-panel)
+    ()
+  (:metaclass ns:+ns-object))
+
+(defclass font-name-transformer (ns:ns-value-transformer)
+    ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod #/transformedNameClass ((self +font-name-transformer))
+  ns:ns-string)
+
+
+(objc:defmethod (#/allowsReverseTransformation :<BOOL>)
+    ((self +font-name-transformer))
+  nil)
+
+(objc:defmethod #/transformValue ((self font-name-transformer) value)
+  ;; Is there any better way of doing this that doesn't involve
+  ;; making a font ?
+  (#/displayName (make-instance ns:ns-font
+                                :with-name value
+                                :size (cgfloat 12.0))))
+
+
+
+(defclass lisp-preferences-window-controller (ns:ns-window-controller)
+    ()
+  (:metaclass ns:+ns-object))
+(declaim (special lisp-preferences-window-controller))
+
+(objc:defmethod (#/fontPanelForDefaultFont: :void)
+    ((self lisp-preferences-window-controller) sender)
+  (let* ((fm (#/sharedFontManager ns:ns-font-manager)))
+    (#/setSelectedFont:isMultiple: fm (default-font) nil)
+    (#/setEnabled: fm t)
+    (#/setTarget: fm self)
+    (#/setAction: fm (@selector #/changeDefaultFont:)))
+  (#/orderFrontFontPanel: *NSApp* sender))
+
+
+(objc:defmethod (#/fontPanelForModelineFont: :void)
+		((self lisp-preferences-window-controller) sender)
+  (declare (special *modeline-font-name* *modeline-font-size*))
+  (let* ((fm (#/sharedFontManager ns:ns-font-manager)))
+    (#/setSelectedFont:isMultiple: fm (default-font
+					  :name *modeline-font-name*
+					:size *modeline-font-size*)
+				   nil)
+    (#/setTarget: fm self)
+    (#/setAction: fm (@selector #/changeModelineFont:)))
+  (#/orderFrontFontPanel: *NSApp* sender))
+
+
+(objc:defmethod (#/changeDefaultFont: :void) ((self lisp-preferences-window-controller) sender)
+  (let* ((f (#/convertFont: sender (default-font))))
+    (when (is-fixed-pitch-font f)
+      (let* ((values (#/values (#/sharedUserDefaultsController ns:ns-user-defaults-controller))))
+        (#/setValue:forKey: values (#/fontName f) #@"defaultFontName")
+        (#/setValue:forKey: values (#/stringWithFormat: ns:ns-string #@"%u" (round (#/pointSize f))) #@"defaultFontSize")))))
+
+(objc:defmethod (#/changeModelineFont: :void) ((self lisp-preferences-window-controller) sender)
+  (declare (special *modeline-font-name* *modeline-font-size*))
+  (let* ((f (#/convertFont: sender (default-font
+					  :name *modeline-font-name*
+					:size *modeline-font-size*))))
+    (when (is-fixed-pitch-font f)
+      (let* ((values (#/values (#/sharedUserDefaultsController ns:ns-user-defaults-controller))))
+        (#/setValue:forKey: values (#/fontName f) #@"modelineFontName")
+        (#/setValue:forKey: values (#/stringWithFormat: ns:ns-string #@"%u" (round (#/pointSize f))) #@"modelineFontSize")))))
+
+
+(objc:defmethod (#/changeColor: :void) ((self lisp-preferences-panel)
+                                        sender)
+  (declare (ignore sender)))
+
+
+(objc:defmethod (#/selectHyperspecFileURL: :void)
+    ((self lisp-preferences-window-controller)
+     sender)
+  (declare (ignore sender))
+  (let* ((panel (make-instance 'ns:ns-open-panel))
+         (values (#/values (#/sharedUserDefaultsController ns:ns-user-defaults-controller))))
+    (#/setAllowsMultipleSelection: panel nil)
+    (#/setCanChooseDirectories: panel t)
+    (#/setCanChooseFiles: panel nil)
+    (when (eql
+           (#/runModalForDirectory:file:types:
+            panel
+            (#/valueForKey: values #@"hyperspecFileURLString")
+            +null-ptr+
+            +null-ptr+)
+           #$NSOKButton)
+      (let* ((filename (#/objectAtIndex: (#/filenames panel) 0)))
+        (#/setValue:forKey: values filename #@"hyperspecFileURLString")))))
+
+(objc:defmethod #/sharedPanel ((self +lisp-preferences-panel))
+  (cond (*lisp-preferences-panel*)
+        (t
+         (let* ((domain (#/standardUserDefaults ns:ns-user-defaults))
+                (initial-values (cocoa-defaults-initial-values)))
+           (#/registerDefaults: domain initial-values)
+           (update-cocoa-defaults)
+           (#/setValueTransformer:forName:
+            ns:ns-value-transformer
+            (make-instance 'font-name-transformer)
+            #@"FontNameTransformer")
+           (let* ((sdc (#/sharedUserDefaultsController ns:ns-user-defaults-controller)))
+             (#/setAppliesImmediately: sdc nil)
+             (#/setInitialValues: sdc initial-values)
+             (let* ((controller (make-instance lisp-preferences-window-controller
+                                             :with-window-nib-name #@"preferences"))
+		    (window (#/window controller)))
+               (unless (%null-ptr-p window)
+                 (#/setFloatingPanel: window t)
+                 (#/addObserver:selector:name:object:
+                  (#/defaultCenter ns:ns-notification-center)
+                  controller
+                  (@selector #/defaultsChanged:)
+                  #&NSUserDefaultsDidChangeNotification
+                  (#/standardUserDefaults ns:ns-user-defaults))
+                 (setq *lisp-preferences-panel* window))))))))
+
+  
+(objc:defmethod #/init ((self lisp-preferences-panel))
+  (let* ((class (class-of self)))
+    (#/dealloc self)
+    (#/sharedPanel class)))
+
+
+(objc:defmethod (#/makeKeyAndOrderFront: :void)
+    ((self lisp-preferences-panel) sender)
+  (let* ((color-panel (#/sharedColorPanel ns:ns-color-panel)))
+    (#/close color-panel)
+    (#/setAction: color-panel +null-ptr+)
+    (#/setShowsAlpha: color-panel t))
+  (call-next-method sender))
+
+(objc:defmethod (#/show :void) ((self lisp-preferences-panel))
+  (#/makeKeyAndOrderFront: self +null-ptr+))
+
+(objc:defmethod (#/defaultsChanged: :void)
+    ((self lisp-preferences-window-controller)
+     notification)
+  (declare (ignore notification))
+  (update-cocoa-defaults))
+  
+
+
Index: /branches/new-random/cocoa-ide/cocoa-typeout.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-typeout.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-typeout.lisp	(revision 13309)
@@ -0,0 +1,194 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+;;
+;; a typeout window is just an ns-window containing a scroll-view
+;; which contains a text-view. The text is read only.
+;;
+;; the window is implicitly bound to a stream, and text written to
+;; the stream is written into the text-view object. The stream is 
+;; available via the function (gui::typeout-stream)
+;;
+
+;; @class typeout-view
+;;
+(defclass typeout-view (ns:ns-view)
+  ((scroll-view :foreign-type :id :reader typeout-view-scroll-view)
+   (text-view :foreign-type :id :reader typeout-view-text-view))
+  (:metaclass ns:+ns-object))
+(declaim (special typeout-view))
+
+(defclass typeout-text-view (ns:ns-text-view)
+    ()
+  (:metaclass ns:+ns-object))
+(declaim (special typeout-text-view))
+
+(objc:defmethod (#/clearAll: :void) ((self typeout-text-view))
+  (#/selectAll: self +null-ptr+)
+  (#/delete: self +null-ptr+))
+
+(objc:defmethod (#/insertString: :void) ((self typeout-text-view) text)
+  (#/setEditable: self t)
+  (#/insertText: self text)
+  (#/setEditable: self nil))
+
+
+(objc:defmethod #/initWithFrame: ((self typeout-view) (frame :<NSR>ect))
+  (declare (special *default-font-name* *default-font-size*))
+  (call-next-method frame)
+  (let* ((scrollview (make-instance 'ns:ns-scroll-view
+                                    :with-frame frame))
+	 (scroll-content (#/contentView scrollview))) 
+    (#/setBorderType: scrollview #$NSBezelBorder)
+    (#/setHasVerticalScroller: scrollview t)
+    (#/setHasHorizontalScroller: scrollview t)
+    (#/setRulersVisible: scrollview nil)
+    (#/setAutoresizingMask: scrollview (logior #$NSViewWidthSizable #$NSViewHeightSizable))
+    (#/setAutoresizesSubviews: scroll-content t)
+    (#/addSubview: self scrollview)
+    (setf (slot-value self 'scroll-view) scrollview)
+    (let* ((contentsize (#/contentSize scrollview)))
+      (ns:with-ns-rect (text-frame 0 0 (ns:ns-size-width contentsize) (ns:ns-size-height contentsize))
+        (let* ((text-view (make-instance 'typeout-text-view
+                                         :with-frame text-frame)))
+          (#/setEditable: text-view nil)
+          (#/setHorizontallyResizable: text-view t)
+          (#/setAutoresizingMask: text-view #$NSViewWidthSizable)
+          (#/setTypingAttributes: text-view (create-text-attributes 
+				  :font (default-font :name *default-font-name* :size *default-font-size*)
+				  :line-break-mode :char))
+          (#/setDocumentView: scrollview text-view)
+          (ns:with-ns-size (container-size 1.0f7 1.0f7)
+          (let* ((layout (#/layoutManager text-view))
+                 (container (make-instance 'ns:ns-text-container
+                                           :with-container-size container-size)))
+            (#/setWidthTracksTextView: container t)
+            (#/setHeightTracksTextView: container nil)
+            (#/addTextContainer: layout container)))
+        
+          (setf (slot-value self 'text-view) text-view)))))
+  self)
+
+;;
+;; @class typeout-panel
+;;
+(defloadvar *typeout-window* nil)
+
+(defclass typeout-window (ns:ns-window)
+    ((typeout-view :foreign-type :id :accessor typeout-window-typeout-view))
+  (:metaclass ns:+ns-object))
+(declaim (special typeout-window))
+
+(defloadvar *typeout-windows* ())
+(defstatic *typeout-windows-lock* (make-lock))
+
+(defun get-typeout-window (title)
+  (with-lock-grabbed (*typeout-windows-lock*)
+    (when *typeout-windows*
+      (let* ((w (pop *typeout-windows*)))
+        (set-window-title w title)
+        w))))
+
+(objc:defmethod #/typeoutWindowWithTitle: ((self +typeout-window) title)
+  (let* ((panel (new-cocoa-window :class self
+                                  :title title
+                                  :width 600
+                                  :activate nil)))
+    (#/setReleasedWhenClosed: panel nil)
+    (let* ((view (make-instance 'typeout-view :with-frame (#/bounds (#/contentView panel)))))
+      (#/setAutoresizingMask: view (logior
+                                    #$NSViewWidthSizable
+                                    #$NSViewHeightSizable))
+      (#/setContentView: panel view)
+      (#/setNeedsDisplay: view t)
+      (setf (slot-value panel 'typeout-view) view)
+      panel)))
+
+(objc:defmethod #/sharedPanel ((self +typeout-window))
+   (cond (*typeout-window*)
+	 (t
+          (setq *typeout-window* (#/typeoutWindowWithTitle: self "Typeout")))))
+
+
+
+(objc:defmethod (#/close :void) ((self typeout-window))
+  (call-next-method)
+  (unless (eql self *typeout-window*)
+    (with-lock-grabbed (*typeout-windows-lock*)
+      (push (%inc-ptr self 0) *typeout-windows*))))
+
+
+
+(objc:defmethod (#/show :void) ((self typeout-window))
+  (#/makeKeyAndOrderFront: self +null-ptr+))
+
+
+(defclass typeout-stream (fundamental-character-output-stream)
+  ((string-stream :initform (make-string-output-stream))
+   (window :initform (#/sharedPanel typeout-window) :initarg :window)))
+
+(defun prepare-typeout-stream (stream)
+  (declare (ignorable stream))
+  (with-slots (window) stream
+    (#/show window)))
+
+
+
+;;;
+;;;  TYPEOUT-STREAM methods
+;;;
+
+(defmethod stream-write-char ((stream typeout-stream) char)
+  (prepare-typeout-stream stream)
+  (write-char char (slot-value stream 'string-stream)))
+
+(defmethod stream-write-string ((stream typeout-stream) string &optional (start 0) end)
+  (prepare-typeout-stream stream)
+  (write-string (if (and (eql start 0) (or (null end) (eql end (length string))))
+		    string 
+		    (subseq string start end))
+		(slot-value stream 'string-stream)))
+
+  
+(defmethod stream-fresh-line ((stream typeout-stream))
+  (prepare-typeout-stream stream)
+  (fresh-line (slot-value stream 'string-stream)))
+
+(defmethod stream-line-column ((stream typeout-stream))
+  (stream-line-column (slot-value stream 'string-stream)))
+
+(defmethod stream-clear-output ((stream typeout-stream))
+  (prepare-typeout-stream stream)
+  (let* ((window (slot-value stream 'window))
+         (the-typeout-view (typeout-window-typeout-view window))
+         (text-view (slot-value the-typeout-view 'text-view))
+         (string-stream (slot-value stream 'string-stream)))
+    (get-output-stream-string string-stream)
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     text-view
+     (@selector #/clearAll:)
+     +null-ptr+
+     t)))
+
+(defmethod stream-force-output ((stream typeout-stream))
+  (let* ((window (slot-value stream 'window))
+         (the-typeout-view (typeout-window-typeout-view window))
+         (text-view (slot-value the-typeout-view 'text-view)))
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     text-view
+     (@selector #/insertString:)
+     (%make-nsstring (get-output-stream-string (slot-value stream 'string-stream))) 
+     t)))
+  
+
+(defloadvar *typeout-stream* nil)
+
+(defun typeout-stream (&optional title)
+  (if (null title)
+    (or *typeout-stream*
+        (setq *typeout-stream* (make-instance 'typeout-stream)))
+    (make-instance 'typeout-stream :window (#/typeoutWindowWithTitle: typeout-window (%make-nsstring (format nil "~a" title))))))
+
Index: /branches/new-random/cocoa-ide/cocoa-utils.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-utils.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-utils.lisp	(revision 13309)
@@ -0,0 +1,412 @@
+; -*- Mode: Lisp; Package: GUI -*-
+
+(in-package "GUI")
+
+(defmethod list-from-ns-array (thing) (error "~S is not an instance of NS:NS-ARRAY" thing))
+(defmethod list-from-ns-array ((nsa ns:ns-array))
+  (let ((result (list))
+        (c (#/count nsa)))
+    (dotimes (i c) (setf result (push (#/objectAtIndex: nsa i) result)))
+    (reverse result)))
+
+(defclass key-select-table-view (ns:ns-table-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/keyDown: :void) ((self key-select-table-view) event)
+  (let* ((code (#/keyCode event)))
+    (if (and (>= (#/selectedRow self) 0)
+             (= code 36)) ; return key
+      (#/sendAction:to:from: *NSApp* (#/doubleAction self) (#/target self) self)
+      (call-next-method event))))
+
+(defclass sequence-window-controller (ns:ns-window-controller)
+    ((table-view :foreign-type :id :reader sequence-window-controller-table-view)
+     (sequence :initform nil :initarg :sequence :type sequence :reader sequence-window-controller-sequence)
+     (result-callback :initarg :result-callback)
+     (display :initform #'(lambda (item stream) (prin1 item stream)) :initarg :display)
+     (title :initform "Sequence dialog" :initarg :title))
+  (:metaclass ns:+ns-object))
+
+
+(objc:defmethod #/init ((self sequence-window-controller))
+  (call-next-method)
+  (let* ((w (new-cocoa-window :activate nil))
+         (contentview (#/contentView w))
+         (contentframe (#/frame contentview))
+         (scrollview (make-instance 'ns:ns-scroll-view :with-frame contentframe)))
+    (#/setWindow: self w)
+    (#/setDelegate: w self)
+    (#/setWindowController: w self)
+    (#/setHasVerticalScroller: scrollview t)
+    (#/setHasHorizontalScroller: scrollview t)
+    (#/setAutohidesScrollers: scrollview t)
+    (#/setRulersVisible: scrollview nil)
+    (#/setAutoresizingMask: scrollview (logior
+                                        #$NSViewWidthSizable
+                                        #$NSViewHeightSizable))
+    (#/setAutoresizesSubviews: (#/contentView scrollview) t)
+    (let* ((table-view (make-instance 'key-select-table-view)))
+      (#/setDocumentView: scrollview table-view)
+      (#/release table-view)
+      #-cocotron
+      (#/setColumnAutoresizingStyle: table-view #$NSTableViewUniformColumnAutoresizingStyle)
+      (setf (slot-value self 'table-view) table-view)
+      (let* ((column (make-instance 'ns:ns-table-column :with-identifier #@"")))
+        (#/setEditable: column nil)
+        #-cocotron
+	(#/setResizingMask: column #$NSTableColumnAutoresizingMask)
+        (#/addTableColumn: table-view column)
+	(#/release column))
+      (#/setAutoresizingMask: table-view (logior
+                                          #$NSViewWidthSizable
+                                          #$NSViewHeightSizable))
+      (#/sizeToFit table-view)
+      (#/setDataSource: table-view self)
+      (#/setTarget: table-view self)
+      (#/setHeaderView: table-view +null-ptr+)
+      (#/setUsesAlternatingRowBackgroundColors: table-view t)
+      (#/setDoubleAction: table-view (@selector #/sequenceDoubleClick:))
+      (#/addSubview: contentview scrollview)
+      (#/release scrollview)
+      self)))
+
+(objc:defmethod (#/dealloc :void) ((self sequence-window-controller))
+  (call-next-method))
+
+(objc:defmethod (#/windowWillClose: :void) ((self sequence-window-controller)
+					    notification)
+  (declare (ignore notification))
+  (#/setDataSource: (slot-value self 'table-view) +null-ptr+)
+  (#/autorelease self))
+
+(objc:defmethod (#/sequenceDoubleClick: :void)
+    ((self sequence-window-controller) sender)
+  (let* ((n (#/selectedRow sender)))
+    (when (>= n 0)
+      (with-slots (sequence result-callback) self
+        (funcall result-callback (elt sequence n))))))
+
+(objc:defmethod (#/numberOfRowsInTableView: :<NSI>nteger)
+    ((self sequence-window-controller) view)
+  (declare (ignore view))
+  (length (slot-value self 'sequence)))
+
+
+(objc:defmethod #/tableView:objectValueForTableColumn:row:
+    ((self sequence-window-controller) view column (row :<NSI>nteger))
+  (declare (ignore column view))
+  (with-slots (display sequence) self
+    (#/autorelease
+     (%make-nsstring (with-output-to-string (s)
+		       (funcall display (elt sequence row) s))))))
+
+(defmethod initialize-instance :after ((self sequence-window-controller) &key &allow-other-keys)
+  (let* ((window (#/window self)))
+    (with-slots (title) self
+      (when title (#/setTitle: window (%make-nsstring title))))
+    (#/reloadData (sequence-window-controller-table-view self))
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     self
+     (@selector #/showWindow:)
+     +null-ptr+
+     nil)))
+
+;;; Looks like a "util" to me ...
+(defun pathname-to-url (pathname)
+  (make-instance 'ns:ns-url
+                 :file-url-with-path
+                 (%make-nsstring (native-translated-namestring pathname))))
+
+(defun cgfloat (number)
+  (float number ccl::+cgfloat-zero+))
+
+(defun color-values-to-nscolor (red green blue &optional alpha)
+  (#/retain (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color
+                                                       (cgfloat red)
+                                                       (cgfloat green)
+                                                       (cgfloat blue)
+                                                       (cgfloat (or alpha 1.0)))))
+
+(defun map-windows (fn)
+  (let ((win-arr (#/orderedWindows *NSApp*)))
+    (dotimes (i (#/count win-arr))
+      (funcall fn (#/objectAtIndex: win-arr i)))))
+
+(defun windows ()
+  (let* ((ret nil))
+    (map-windows #'(lambda (w) (push w ret)))
+    (nreverse ret)))
+
+(defun first-window-satisfying-predicate (pred)
+  (block foo
+    (map-windows #'(lambda (w) (when (funcall pred w)
+                                 (return-from foo w))))))  
+
+(defun first-window-with-controller-type (controller-type)
+  (first-window-satisfying-predicate #'(lambda (w) (typep (#/windowController w) controller-type))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+
+(defvar *log-callback-errors* :backtrace)
+
+(defun maybe-log-callback-error (condition)
+  (when *log-callback-errors*
+    ;; Put these in separate ignore-errors, so at least some of it can get thru
+    (let ((emsg (ignore-errors (princ-to-string condition))))
+      (ignore-errors (clear-output *debug-io*))
+      (ignore-errors (format *debug-io* "~&Lisp error: ~s" (or emsg condition)))
+      (when (eq *log-callback-errors* :backtrace)
+        (let* ((err (nth-value 1 (ignore-errors (ccl:print-call-history :detailed-p t)))))
+          (when err
+            (ignore-errors (format *debug-io* "~&Error printing call history - "))
+            (ignore-errors (print err *debug-io*))
+            (ignore-errors (princ err *debug-io*))
+            (ignore-errors (force-output *debug-io*))))))))
+
+(defmacro with-callback-context (description &body body)
+  (let ((saved-debug-io (gensym)))
+    `(ccl::with-standard-abort-handling ,(format nil "Abort ~a" description)
+       (let ((,saved-debug-io *debug-io*))
+         (handler-bind ((error #'(lambda (condition)
+                                   (let ((*debug-io* ,saved-debug-io))
+                                     (maybe-log-callback-error condition)
+                                     (abort)))))
+           ,@body)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; utilities for executing in the cocoa event thread
+
+(defstatic *cocoa-thread-arg-id-map* (make-id-map))
+
+;; This is for debugging, it's preserved across queue-for-gui and bound
+;; so it can be seen in backtraces.
+(defvar *invoking-event-context* "unknown")
+(defvar *invoking-event-process* nil)
+
+(defun register-cocoa-thread-function (thunk result-handler context)
+  (assign-id-map-id *cocoa-thread-arg-id-map* (list* thunk
+						     result-handler
+						     (or context *invoking-event-context*)
+						     *current-process*)))
+
+(objc:defmethod (#/invokeLispFunction: :void) ((self ns:ns-application) id)
+  (invoke-lisp-function self id))
+
+(defmethod invoke-lisp-function ((self ns:ns-application) id)
+  (destructuring-bind (thunk result-handler context . invoking-process)
+		      (id-map-free-object *cocoa-thread-arg-id-map* (if (numberp id) id (#/longValue id)))
+    (handle-invoking-lisp-function thunk result-handler context invoking-process)))
+
+(defun execute-in-gui (thunk &key context)
+  "Execute thunk in the main cocoa thread, return whatever values it returns"
+  (if (typep *current-process* 'appkit-process)
+    (handle-invoking-lisp-function thunk nil context)
+    (if (or (not *nsapp*) (not (#/isRunning *nsapp*)))
+      (error "cocoa thread not available")
+      (with-autorelease-pool 
+          (let* ((return-values nil)
+                 (result-handler #'(lambda (&rest values) (setq return-values values)))
+                 (arg (make-instance 'ns:ns-number
+                                     :with-long (register-cocoa-thread-function thunk result-handler context))))
+            (#/performSelectorOnMainThread:withObject:waitUntilDone:
+             *nsapp*
+             (@selector #/invokeLispFunction:)
+             arg
+             t)
+            (apply #'values return-values))))))
+
+
+(defconstant $lisp-function-event-subtype 17)
+
+(defclass lisp-application (ns:ns-application)
+    ((termp :foreign-type :<BOOL>)
+     (console :foreign-type :id :accessor console))
+  (:metaclass ns:+ns-object))
+
+(defmethod current-event-modifier-p (modifier-mask)
+  (let* ((event (#/currentEvent *nsapp*))
+         (modifiers (#/modifierFlags event)))
+    (logtest modifier-mask modifiers)))
+
+(defun current-event-command-key-p ()
+  (current-event-modifier-p #$NSCommandKeyMask))
+
+;;; I'm not sure if there's another way to recognize events whose
+;;; type is #$NSApplicationDefined.
+(objc:defmethod (#/sendEvent: :void) ((self lisp-application) e)
+  (declare (dynamic-extent self e))
+  (if (and (eql (#/type e) #$NSApplicationDefined)
+	   (eql (#/subtype e) $lisp-function-event-subtype))
+    (invoke-lisp-function self (#/data1 e))
+    (call-next-method e)))
+
+;; This queues an event rather than just doing performSelectorOnMainThread, so that the
+;; action is deferred until the event thread is idle.
+(defun queue-for-gui (thunk &key result-handler context at-start)
+  "Queue thunk for execution in main cocoa thread and return immediately."
+  (execute-in-gui
+   #'(lambda () 
+       (let* ((e (#/otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:
+		  ns:ns-event
+		  #$NSApplicationDefined
+		  (ns:make-ns-point 0 0)
+		  0
+		  0.0d0
+		  0
+		  +null-ptr+
+		  $lisp-function-event-subtype
+		  (register-cocoa-thread-function thunk result-handler context)
+		  0)))
+	 ;(#/retain e)
+	 (#/postEvent:atStart: *nsapp* e (not (null at-start)))))))
+
+(defun handle-invoking-lisp-function (thunk result-handler context &optional (invoking-process *current-process*))
+  ;; TODO: the point is to execute result-handler in the original process, but this will do for now.
+  (let* ((*invoking-event-process* invoking-process)
+	 (*invoking-event-context* context))
+    (if result-handler
+      (multiple-value-call result-handler (funcall thunk))
+      (funcall thunk))))
+
+(defun choose-directory-dialog ()
+  (execute-in-gui #'(lambda ()
+                      (let ((op (#/openPanel ns:ns-open-panel)))
+                        (#/setAllowsMultipleSelection: op nil)
+                        (#/setCanChooseDirectories: op t)
+                        (#/setCanChooseFiles: op nil)
+                        (when (eql (#/runModalForTypes: op +null-ptr+) #$NSOKButton)
+                          ;; #/stringByStandardizingPath seems to strip trailing slashes
+                         (let* ((path (#/retain (#/stringByAppendingString:
+                                        (#/stringByStandardizingPath
+                                         (#/objectAtIndex: (#/filenames op) 0))
+                                        #@"/"))))
+                            path))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; debugging
+
+(defun double-%-in (string)
+  ;; Replace any % characters in string with %%, to keep them from
+  ;; being treated as printf directives.
+  (let* ((%pos (position #\% string)))
+    (if %pos
+      (concatenate 'string (subseq string 0 %pos) "%%" (double-%-in (subseq string (1+ %pos))))
+      string)))
+
+(defun log-debug (format-string &rest args)
+  (let ((string (apply #'format nil format-string args)))
+    (#_NSLog (ccl::%make-nsstring (double-%-in string)))))
+
+(pushnew '(log-debug . 0) ccl::*format-arg-functions* :test #'equal)
+
+(defun nslog-condition (c &optional (msg "Error in event loop: "))
+  (let* ((rep (format nil "~a" c)))
+    (with-cstrs ((str rep)
+                 (msg-str msg))
+      (with-nsstr (nsstr str (length rep))
+        (with-nsstr (nsmsg msg-str (length msg))
+         (#_NSLog #@"%@: %@" :address nsmsg :address nsstr))))))
+
+(defun nsstring-for-lisp-condition (cond)
+  (%make-nsstring (double-%-in (or (ignore-errors (princ-to-string cond))
+                                   "#<error printing error message>"))))
+
+
+
+(defun assume-cocoa-thread ()
+  (assert (eq *current-process* ccl::*initial-process*)))
+
+(defmethod assume-not-editing ((whatever t)))
+
+;;; -----------------------------------------------------------------
+;;; utility to display a Cocoa alert window
+;;; -----------------------------------------------------------------
+;;; TODO: Currently this form gives no indication which button was clicked. Probably it should do so.
+(defun alert-window (&key 
+                     (title "Alert")
+                     (message "Something happened.")
+                     (default-button "Okay")
+                     alternate-button
+                     other-button)
+  (let ((nstitle (%make-nsstring title))
+        (nsmessage (%make-nsstring message))
+        (ns-default-button (%make-nsstring default-button))
+        (ns-alternate-button (or (and alternate-button (%make-nsstring alternate-button))
+                                 +null-ptr+))
+        (ns-other-button (or (and other-button (%make-nsstring other-button))
+                             +null-ptr+)))
+    (#_NSRunAlertPanel nstitle nsmessage ns-default-button ns-alternate-button ns-other-button)
+    (#/release nstitle)
+    (#/release nsmessage)
+    (#/release ns-default-button)
+    (unless (eql ns-alternate-button +null-ptr+)
+      (#/release ns-alternate-button))
+    (unless (eql ns-other-button +null-ptr+)
+      (#/release ns-other-button))))
+
+;;; -----------------------------------------------------------------
+;;; utility to display a Cocoa progress window
+;;; -----------------------------------------------------------------
+
+(defparameter *progress-window-controller* nil)
+
+(defclass progress-window-controller (ns:ns-window-controller)
+    ((progress-window :foreign-type :id :reader progress-window)
+     (message-field :foreign-type :id :reader progress-window-message-field)
+     (progress-bar :foreign-type :id :reader progress-window-progress-bar))
+  (:metaclass ns:+ns-object))
+
+(defun get-progress-window ()
+  (unless *progress-window-controller*
+    (setf *progress-window-controller* 
+          (make-instance 'progress-window-controller))
+    (#/initWithWindowNibName: *progress-window-controller* #@"ProgressWindow"))
+  (unless (#/isWindowLoaded *progress-window-controller*)
+    (#/loadWindow *progress-window-controller*))
+  (let ((window (progress-window *progress-window-controller*)))
+    (if (or (null window)
+            (%null-ptr-p window))
+        nil
+        window)))
+
+(defmacro with-modal-progress-dialog (title message &body body)
+  `(let* ((nstitle (%make-nsstring ,title))
+          (nsmessage (%make-nsstring ,message))
+          (window (get-progress-window))
+          (progress-bar (progress-window-progress-bar *progress-window-controller*))
+          (message-field (progress-window-message-field *progress-window-controller*)))
+     (unwind-protect 
+          (if window
+              (progn
+                (#/setTitle: window nstitle)
+                (#/setIndeterminate: progress-bar #$YES)
+                (#/setUsesThreadedAnimation: progress-bar #$YES)
+                (#/setStringValue: message-field nsmessage)
+                (#/makeKeyAndOrderFront: window +null-ptr+)
+                (let ((modal-session (#/beginModalSessionForWindow: ccl::*nsapp* window)))
+                  (#/startAnimation: progress-bar +null-ptr+)
+                  (let ((result (progn ,@body)))
+                    (#/stopAnimation: progress-bar +null-ptr+)
+                    (#/orderOut: window +null-ptr+)
+                    (#/endModalSession: ccl::*nsapp* modal-session)
+                    result)))
+              (progn
+                (alert-window :title "Failure"
+                            :message "Unable to load the modal progress window")
+                nil))
+       (#/release nstitle)
+       (#/release nsmessage))))
+
+(defun post-tiger-p ()
+  #+cocotron t
+  #-cocotron 
+  (rlet ((p :int))
+    (#_Gestalt #$gestaltSystemVersion p)
+    (>= (%get-long p) #x1050)))
+
+
Index: /branches/new-random/cocoa-ide/cocoa-window.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa-window.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa-window.lisp	(revision 13309)
@@ -0,0 +1,388 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2002-2007 Clozure Associates
+;;;   This file is part of OpenMCL.  
+;;;
+;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with OpenMCL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "GUI")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (def-cocoa-default *default-font-name* :string "Courier" "Name of font to use in editor windows")
+  (def-cocoa-default *default-font-size* :float 12.0f0 "Size of font to use in editor windows, as a positive SINGLE-FLOAT")
+  (def-cocoa-default *tab-width* :int 8 "Width of editor tab stops, in characters"))
+
+(defun init-cocoa-application ()
+  (with-autorelease-pool
+      (#/standardUserDefaults ns:ns-user-defaults)
+      (let* ((bundle (open-main-bundle))
+	     (dict (#/infoDictionary  bundle))
+	     (classname (#/objectForKey: dict #@"NSPrincipalClass"))
+	     (mainnibname (#/objectForKey: dict  #@"NSMainNibFile"))
+	     (progname (#/objectForKey: dict #@"CFBundleName")))
+	(if (%null-ptr-p classname)
+	  (error "problems loading bundle: can't determine class name"))
+	(if (%null-ptr-p mainnibname)
+	  (error "problems loading bundle: can't determine main nib name"))
+	(unless (%null-ptr-p progname)
+          (#/setProcessName: (#/processInfo ns:ns-process-info) progname))
+	(let* ((appclass (#_NSClassFromString classname))
+	       (app (#/sharedApplication appclass)))
+          (#/loadNibNamed:owner: ns:ns-bundle mainnibname  app)
+	  app))))
+
+
+
+#+apple-objc
+(defun trace-dps-events (flag)
+  (external-call "__DPSSetEventsTraced"
+		 :unsigned-byte (if flag #$YES #$NO)
+		 :void))
+
+(defclass appkit-process (process)
+    ((have-interactive-terminal-io :initform t)))
+
+(defmethod event-loop-can-have-interactive-terminal-io ((process appkit-process))
+  #+windows-target t
+  #-windows-target (slot-value process 'have-interactive-terminal-io))
+
+;;; Interrupt the AppKit event process, by enqueing an event (if the
+;;; application event loop seems to be running.)  It's possible that
+;;; the event loop will stop after the calling thread checks; in that
+;;; case, the application's probably already in the process of
+;;; exiting, and isn't that different from the case where asynchronous
+;;; interrupts are used.
+(defmethod process-interrupt ((process appkit-process) function &rest args)
+  (if (eq process *current-process*)
+    (apply function args)
+    (if (and *NSApp* (#/isRunning *NSApp*))
+      (queue-for-gui #'(lambda () (apply function args)) :at-start t)
+      #+not-yet
+      (let* ((invoked nil)
+             (f (lambda ()
+                  (unless invoked
+                    (setq invoked t)
+                    (apply function args)))))
+        (queue-for-gui f :at-start t)
+        (call-next-method process f))
+      (call-next-method))))
+
+(defparameter *debug-in-event-process* t)
+
+(defparameter *event-process-reported-conditions* () "Things that we've already complained about on this event cycle.")
+
+(defmethod ccl::process-debug-condition ((process appkit-process) condition frame-pointer)
+  "Better than nothing.  Not much better."
+  (when *debug-in-event-process*
+    (let* ((c (if (typep condition 'ccl::ns-lisp-exception)
+                (ccl::ns-lisp-exception-condition condition)
+                condition)))
+      (unless (or (not (typep c 'error)) (member c *event-process-reported-conditions*))
+        (push c *event-process-reported-conditions*)
+        (cond ((slot-value process 'have-interactive-terminal-io)
+               (ccl::application-error ccl::*application* c frame-pointer))
+              (t
+               (catch 'need-a-catch-frame-for-backtrace
+                 (let* ((*debug-in-event-process* nil)
+                        (context
+                         (ccl::new-backtrace-info nil
+                                                  frame-pointer
+                                                  (if ccl::*backtrace-contexts*
+                                                      (or (ccl::child-frame
+                                                           (ccl::bt.youngest
+                                                            (car ccl::*backtrace-contexts*))
+                                                           nil)
+                                                          (ccl::last-frame-ptr))
+                                                      (ccl::last-frame-ptr))
+                                                  (ccl::%current-tcr)
+                                                  condition
+                                                  (ccl::%current-frame-ptr)
+                                                  #+ppc-target ccl::*fake-stack-frames*
+                                                  #+x86-target (ccl::%current-frame-ptr)
+                                                  (ccl::db-link)
+                                                  (1+ ccl::*break-level*)))
+                        (ccl::*backtrace-contexts* (cons context ccl::*backtrace-contexts*)))  
+                   (format t "~%~%*** Error in event process: ~a~%~%" condition)
+                   (print-call-history :context context :detailed-p t :count 20
+                                       :origin frame-pointer)
+                   (format t "~%~%~%")
+                   (force-output t)
+                   ))))))))
+
+
+
+(defloadvar *default-ns-application-proxy-class-name*
+    "LispApplicationDelegate")
+
+
+(defun enable-foreground ()
+  #+apple-objc
+  (rlet ((psn :<P>rocess<S>erial<N>umber))
+    (#_GetCurrentProcess psn)
+    (#_TransformProcessType psn #$kProcessTransformToForegroundApplication)
+    (eql 0 (#_SetFrontProcess psn))))
+
+#+nil
+(objc:defmethod (#/showPreferences: :void) ((self lisp-application) sender)
+  (declare (ignore sender))
+  (#/show (#/sharedPanel lisp-preferences-panel)))
+
+(objc:defmethod (#/toggleConsole: :void) ((self lisp-application) sender)
+  (let* ((console (console self)))
+    (unless (%null-ptr-p console)
+      (mark-console-output-available console nil)
+      (if (setf (console-window-hidden-by-user console) (#/isVisible console))
+        (#/orderOut: console sender)
+        (#/orderFront: console sender)))))
+
+(objc:defmethod (#/validateMenuItem: :<BOOL>) ((self lisp-application)
+                                               item)
+  (let* ((action (#/action item)))
+    (cond ((eql action (@selector #/toggleConsole:))
+           (let* ((console (console self)))
+             (unless (%null-ptr-p console)
+               (if (#/isVisible console)
+                 (#/setTitle: item #@"Hide System Console")
+                 (#/setTitle: item #@"Show System Console"))
+               t)))
+          (t #+cocotron t #-cocotron (call-next-method item)))))
+
+(defmethod ccl::process-exit-application ((process appkit-process) thunk)
+  (when (eq process ccl::*initial-process*)
+    (%set-toplevel thunk)
+    (#/terminate: *NSApp* +null-ptr+)))
+
+(defun run-event-loop ()
+  (%set-toplevel nil)
+  (change-class *cocoa-event-process* 'appkit-process)
+  (event-loop))
+
+(defun stop-event-loop ()
+  (#/stop: *nsapp* +null-ptr+))
+
+(defun event-loop (&optional end-test)
+  (let* ((app *NSApp*)
+         (thread ccl::*current-process*))
+    (loop
+      (if (event-loop-can-have-interactive-terminal-io thread)
+        (with-simple-restart (abort "Process the next event")
+          (#/run app))
+        (let* ((ccl::*break-on-errors* nil))
+          (handler-case (let* ((*event-process-reported-conditions* nil))
+                          (if end-test
+                            (#/run app)
+                            #|(#/runMode:beforeDate: (#/currentRunLoop ns:ns-run-loop)
+                                                     #&NSDefaultRunLoopMode
+                                                     (#/distantFuture ns:ns-date))|#
+                            (#/run app)))
+            (error (c) (nslog-condition c)))))
+      #+debug (log-debug "~&runMode exited, end-test: ~s isRunning ~s quitting: ~s" end-test (#/isRunning app) ccl::*quitting*)
+      (when (or (and end-test (funcall end-test))
+		(and ccl::*quitting* (not (#/isRunning app))))
+	(return)))))
+
+(defun start-cocoa-application (&key
+				(application-proxy-class-name
+				 *default-ns-application-proxy-class-name*))
+  
+  (flet ((cocoa-startup ()
+	   ;; Start up a thread to run periodic tasks.
+	   (process-run-function "housekeeping" #'ccl::housekeeping-loop)
+           (with-autorelease-pool
+             (enable-foreground)
+             (or *NSApp* (setq *NSApp* (init-cocoa-application)))
+             #-cocotron
+             (let* ((icon (#/imageNamed: ns:ns-image #@"NSApplicationIcon")))
+               (unless (%null-ptr-p icon)
+                 (#/setApplicationIconImage: *NSApp* icon)))
+             (setf (ccl::application-ui-object *application*) *NSApp*)
+             (when application-proxy-class-name
+               (let* ((classptr (ccl::%objc-class-classptr
+                                 (ccl::load-objc-class-descriptor application-proxy-class-name)))
+                      (instance (#/init (#/alloc classptr))))
+
+                 (#/setDelegate: *NSApp* instance))))
+           (run-event-loop)))
+    (process-interrupt *cocoa-event-process* #'(lambda ()
+						 (%set-toplevel 
+						  #'cocoa-startup)
+						 (toplevel)))))
+
+(defparameter *font-attribute-names*
+  '((:bold . #.#$NSBoldFontMask)
+    (:italic . #.#$NSItalicFontMask)
+    (:small-caps . #.#$NSSmallCapsFontMask)))
+
+
+;;; The NSFont method #/isFixedPitch has returned random answers
+;;; in many cases for the last few OSX releases.  Try to return
+;;; a reasonable answer, by checking to see if the width of the
+;;; advancement for the #\i glyph matches that of the advancement
+;;; of the #\m glyph.
+
+#-cocotron
+(defun is-fixed-pitch-font (font)
+  (= (ns:ns-size-width (#/advancementForGlyph: font (#/glyphWithName: font #@"i")))
+     (ns:ns-size-width (#/advancementForGlyph: font (#/glyphWithName: font #@"m")))))
+
+#+cocotron
+(defun is-fixed-pitch-font (font)
+  (#/isFixedPitch font))
+
+;;; Try to find the specified font.  If it doesn't exist (or isn't
+;;; fixed-pitch), try to find a fixed-pitch font of the indicated size.
+(defun default-font (&key (name *default-font-name*)
+			  (size *default-font-size*)
+			  (attributes ()))
+				
+  (setq size (cgfloat size))
+  (with-cstrs ((name name))
+    (with-autorelease-pool
+	(rletz ((matrix (:array :<CGF>loat 6)))
+	  (setf (paref matrix (:* :<CGF>loat) 0) size
+                (paref matrix (:* :<CGF>loat) 3) size)
+          (let* ((fontname (#/stringWithCString: ns:ns-string name))
+		 (font (#/fontWithName:matrix: ns:ns-font fontname matrix))
+		 
+		 (implemented-attributes ()))
+	    (if (or (%null-ptr-p font)
+		    (and 
+		     (not (is-fixed-pitch-font font))))
+	      (setq font (#/userFixedPitchFontOfSize: ns:ns-font size)))
+	    (when attributes
+	      (dolist (attr-name attributes)
+		(let* ((pair (assoc attr-name *font-attribute-names*))
+		       (newfont))
+		  (when pair
+		    (setq newfont
+                          (#/convertFont:toHaveTrait:
+                           (#/sharedFontManager ns:ns-font-manager) font (cdr pair)))
+		    (unless (eql font newfont)
+		      (setq font newfont)
+		      (push attr-name implemented-attributes))))))
+	    (values (#/retain font) implemented-attributes))))))
+
+
+;;; Create a paragraph style, mostly so that we can set tabs reasonably.
+(defun create-paragraph-style (font line-break-mode)
+  (let* ((p (make-instance 'ns:ns-mutable-paragraph-style))
+	 (charwidth (fround (nth-value 1 (size-of-char-in-font font)))))
+    (#/setLineBreakMode: p
+                         (ecase line-break-mode
+                           (:char #$NSLineBreakByCharWrapping)
+                           (:word #$NSLineBreakByWordWrapping)
+                           ;; This doesn't seem to work too well.
+                           ((nil) #$NSLineBreakByClipping)))
+    ;; Clear existing tab stops.
+    (#/setTabStops: p (#/array ns:ns-array))
+    ;; And set the "default tab interval".
+    (#/setDefaultTabInterval: p (cgfloat (* *tab-width* charwidth)))
+    p))
+    
+(defun create-text-attributes (&key (font (default-font))
+				    (line-break-mode :char)
+				    (color nil)
+                                    (obliqueness nil)
+                                    (stroke-width nil))
+  (let* ((dict (make-instance 'ns:ns-mutable-dictionary :with-capacity 5)))
+    (#/setObject:forKey: dict (create-paragraph-style font line-break-mode)
+			 #&NSParagraphStyleAttributeName)
+    (#/setObject:forKey: dict font #&NSFontAttributeName)
+    (when color
+      (#/setObject:forKey: dict color #&NSForegroundColorAttributeName))
+    (when stroke-width
+      (#/setObject:forKey: dict (#/numberWithFloat: ns:ns-number stroke-width)
+			   #&NSStrokeWidthAttributeName))
+    (when obliqueness
+      (#/setObject:forKey: dict (#/numberWithFloat: ns:ns-number obliqueness)
+			   #&NSObliquenessAttributeName))
+    dict))
+
+
+(defun get-cocoa-window-flag (w flagname)
+  (case flagname
+    (:accepts-mouse-moved-events
+     (#/acceptsMouseMovedEvents w))
+    (:cursor-rects-enabled
+     (#/areCursorRectsEnabled w))
+    (:auto-display
+     (#/isAutodisplay w))))
+
+
+
+(defun (setf get-cocoa-window-flag) (value w flagname)
+  (case flagname
+    (:accepts-mouse-moved-events
+     (#/setAcceptsMouseMovedEvents: w value))
+    (:auto-display
+     (#/setAutodisplay: w value))))
+
+
+
+(defun activate-window (w)
+  ;; Make w the "key" and frontmost window.  Make it visible, if need be.
+  (#/makeKeyAndOrderFront: w nil))
+
+(defun set-window-title (window title)
+  (#/setTitle: window (if title
+                        (if (typep title 'ns:ns-string)
+                          title
+                          (%make-nsstring title))
+                        #@"") ))
+
+(defun new-cocoa-window (&key
+                         (class (find-class 'ns:ns-window))
+                         (title nil)
+                         (x 200.0)
+                         (y 200.0)
+                         (height 200.0)
+                         (width 500.0)
+                         (closable t)
+                         (iconifyable t)
+                         (metal nil)
+                         (expandable t)
+                         (backing :buffered)
+                         (defer t)
+                         (accepts-mouse-moved-events nil)
+                         (auto-display t)
+                         (activate t))
+  (ns:with-ns-rect (frame x y width height)
+    (let* ((stylemask
+            (logior #$NSTitledWindowMask
+                    (if closable #$NSClosableWindowMask 0)
+                    (if iconifyable #$NSMiniaturizableWindowMask 0)
+                    (if expandable #$NSResizableWindowMask 0)
+		    (if metal #$NSTexturedBackgroundWindowMask 0)))
+           (backing-type
+            (ecase backing
+              ((t :retained) #$NSBackingStoreRetained)
+              ((nil :nonretained) #$NSBackingStoreNonretained)
+              (:buffered #$NSBackingStoreBuffered)))
+           (w (make-instance
+	       class
+	       :with-content-rect frame
+	       :style-mask stylemask
+	       :backing backing-type
+	       :defer defer)))
+      (setf (get-cocoa-window-flag w :accepts-mouse-moved-events)
+            accepts-mouse-moved-events
+            (get-cocoa-window-flag w :auto-display)
+            auto-display)
+      (#/setBackgroundColor: w (#/whiteColor ns:ns-color))
+      (when activate (activate-window w))
+      (when title (set-window-title w title))
+      w)))
+
+
+
+
Index: /branches/new-random/cocoa-ide/cocoa.lisp
===================================================================
--- /branches/new-random/cocoa-ide/cocoa.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/cocoa.lisp	(revision 13309)
@@ -0,0 +1,22 @@
+(in-package "CCL")
+
+#+windows-target
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (pushnew :cocotron *features*))
+
+(defvar *cocoa-application-path* #+gz "ccl:GZ temp bundle.app;" #-gz
+        (let* ((bits (nth-value 1 (host-platform))))
+          (format nil "ccl:temp bundle~a.app;"
+                  bits)))
+(defvar *cocoa-application-copy-headers-p* nil)
+(defvar *cocoa-application-install-altconsole* nil)
+(defvar *cocoa-application-bundle-suffix*
+  (multiple-value-bind (os bits cpu) (host-platform)
+    (declare (ignore os))
+    (format nil "temp bundle-~a~a" (string-downcase cpu) bits)))
+(defvar *cocoa-ide-force-compile* nil)
+(defvar *cocoa-application-frameworks* #+cocotron '("ccl:cocotron;Foundation.framework;" "ccl:cocotron;AppKit.framework;") #-cocotron nil)
+(defvar *cocoa-application-libraries* #+cocotron '("ccl:cocotron;Foundation'.1'.0'.dll" "ccl:cocotron;AppKit'.1'.0'.dll") #-cocotron nil)
+
+(load "ccl:cocoa-ide;defsystem.lisp")
+(load-ide *cocoa-ide-force-compile*)
Index: /branches/new-random/cocoa-ide/compile-hemlock.lisp
===================================================================
--- /branches/new-random/cocoa-ide/compile-hemlock.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/compile-hemlock.lisp	(revision 13309)
@@ -0,0 +1,105 @@
+(in-package "CCL")
+
+(defparameter *hemlock-src-dir-pathname* "ccl:cocoa-ide;hemlock;src;")
+
+(defparameter *hemlock-binary-dir-pathname* "ccl:cocoa-ide;hemlock;bin;openmcl;")
+
+(defparameter *hemlock-binary-file-extension*
+  (pathname-type (compile-file-pathname "foo.lisp")))
+
+(defun hemlock-source-pathname (name)
+  (make-pathname :name name
+                 :type "lisp"
+                 :defaults *hemlock-src-dir-pathname*))
+
+(defun hemlock-binary-pathname (name)
+  (make-pathname :name name
+                 :type *hemlock-binary-file-extension*
+                 :defaults *hemlock-binary-dir-pathname*))
+
+(defun compile-and-load-hemlock-file (name &optional force)
+  (let* ((source-pathname (hemlock-source-pathname name))
+	 (binary-pathname (hemlock-binary-pathname name)))
+    (when (or force
+	      (not (probe-file binary-pathname))
+	      (> (file-write-date source-pathname)
+		 (file-write-date binary-pathname)))
+      (compile-file source-pathname :output-file binary-pathname :verbose t))
+    (load binary-pathname :verbose t)))
+
+
+(defparameter *hemlock-files*
+  '("package"
+
+    "hemlock-ext"                     
+	       
+    "decls"                             ;early declarations of functions and stuff
+	       
+    "struct"
+    "charmacs"
+    "key-event" 
+    "keysym-defs"
+    "cocoa-hemlock"
+    "rompsite"
+
+    "macros"
+
+    "views"
+    "line"
+    "ring"
+    "vars"
+    "interp"
+    "syntax"
+    "htext1"
+    "buffer"  
+    "charprops"
+    "htext2"
+    "htext3"
+    "htext4"
+    "files"
+    "search1"
+    "search2"
+    "table"
+    "modeline"
+    "pop-up-stream"
+    "font"
+    "streams"
+    "main"
+    "echo"
+    "echocoms"
+    "command"
+    "indent"
+    ;; moved     "comments"
+    "morecoms"
+    "undo"
+    "killcoms"
+    "searchcoms"
+    "isearchcoms"
+    "filecoms"
+    "doccoms"
+    "fill"
+    "text"
+    "lispmode"
+    "listener"
+    "comments"
+    "icom"
+    "defsyn"
+    "edit-defs"
+    "register"
+    "completion"
+    "symbol-completion"
+    "bindings"
+    ))
+
+(defun compile-hemlock (&optional force)
+  (with-compilation-unit ()
+    (dolist (name *hemlock-files*)
+      (compile-and-load-hemlock-file name force)))
+  (fasl-concatenate "ccl:cocoa-ide;hemlock"
+                    (mapcar #'hemlock-binary-pathname *hemlock-files*)
+                    :if-exists :supersede)
+  (provide "HEMLOCK")
+  )
+
+
+(provide "COMPILE-HEMLOCK")
Index: /branches/new-random/cocoa-ide/console-window.lisp
===================================================================
--- /branches/new-random/cocoa-ide/console-window.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/console-window.lisp	(revision 13309)
@@ -0,0 +1,180 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2008 Clozure Associates
+
+(in-package "GUI")
+
+
+(defclass console-window (typeout-window)
+  ((syslog-in :foreign-type :id :accessor syslog-in)
+   (syslog-out :foreign-type :id :accessor syslog-out)
+   (nextra :foreign-type :int)
+   (translatebuf :foreign-type :address)
+   (bufsize :foreign-type :int)
+   (hidden-by-user :initform t :accessor console-window-hidden-by-user))
+  (:metaclass ns:+ns-object))
+
+(defconstant $system-console-menu-item-tag 1)
+
+
+;;; Insert/append a string to the console-window's text view,
+;;; activating the window if necessary.
+
+(objc:defmethod (#/insertString: :void) ((self console-window) string)
+  (with-slots ((tv typeout-view)) self
+    (if (console-window-hidden-by-user self)
+      (mark-console-output-available self t)
+      (#/makeKeyAndOrderFront: self +null-ptr+))
+    (#/insertString: (typeout-view-text-view tv) string)))
+
+(defmethod mark-console-output-available ((self console-window) available-p)
+  #+cocotron (declare (ignore available-p))
+  #-cocotron
+  (let* ((menu (#/windowsMenu *nsapp*))
+         (menu-ref (ccl::external-call "__NSGetCarbonMenu" :address menu :address))
+         (index (#/indexOfItemWithTag: menu $system-console-menu-item-tag)))
+    (when (< index 0)
+      (setq index (#/indexOfItemWithTitle: menu #@"Show System Console")))
+    (when (> index 0)
+      (ccl::external-call "_SetItemMark" :id menu-ref :integer (1+ index)
+                          :integer (if available-p #$diamondMark 0)))))
+
+;;; Process a chunkful of data
+(objc:defmethod (#/processData: :void) ((self console-window) data)
+  (with-slots (syslog-in syslog-out nextra translatebuf bufsize) self
+    (let* ((encoding (load-time-value (get-character-encoding :utf-8)))
+	   (data-length (#/length data))
+           (n nextra)
+           (cursize bufsize)
+           (need (+ n data-length))
+           (xlate translatebuf))
+      (#/writeData: syslog-out data)
+      (when (> need cursize)
+        (let* ((new (#_malloc need)))
+          (dotimes (i n) (setf (%get-unsigned-byte new i)
+                               (%get-unsigned-byte xlate i)))
+          (#_free xlate)
+          (setq xlate new translatebuf new bufsize need)))
+      #+debug (#_NSLog #@"got %d bytes of data" :int data-length)
+      (with-macptrs ((target (%inc-ptr xlate n)))
+        (#/getBytes:range: data target (ns:make-ns-range 0 data-length)))
+      (let* ((total (+ n data-length))
+             (noctets-used (nth-value 1
+                                      (funcall (ccl::character-encoding-length-of-memory-encoding-function encoding)
+                                               xlate
+                                               total
+                                               0)))
+             (string (make-instance ns:ns-string
+                                    :with-bytes xlate
+                                    :length noctets-used
+                                    :encoding #$NSUTF8StringEncoding)))
+         (unless (zerop (setq n (- total noctets-used)))
+              ;; By definition, the number of untranslated octets
+              ;; can't be more than 3.
+              (dotimes (i n)
+                (setf (%get-unsigned-byte xlate i)
+                      (%get-unsigned-byte xlate (+ noctets-used i)))))
+            (setq nextra n)
+            (#/insertString: self string)))))
+
+;;; We want to be able to capture and display process-level
+;;; output to file descriptors 1 and 2, including messages
+;;; logged via #_NSLog/#_CFLog and variants.  Logging messages
+;;; may only be echoed to fd 2 if that fd is open to a file
+;;; (rather than to a socket/pty/pipe/...).  Unless/until
+;;; the the file has data written to it, reading from
+;;; it will return EOF, and waiting via mechanisms like
+;;; #_poll/#_select/#/readInBackgroundAndNotify will indicate
+;;; that the file can be read without blocking.  True, but
+;;; we'd rather not see it as being constantly at EOF ...
+;;; So, we have a timer-driven method wake up every second
+;;; or so, and see if there's actually any unread data
+;;; to process.
+
+(objc:defmethod (#/checkForData: :void) ((self console-window) timer)
+  (declare (ignorable timer))
+  (let* ((in (syslog-in self)))
+    (loop
+      (let* ((data (#/availableData in))
+             (n (#/length data)))
+        (declare (fixnum n))
+        (if (zerop n)
+          (return)
+          (#/processData: self data))))))
+
+;;; Open file descriptor to a temporary file.  The write-fd will be
+;;; open for reading and writing and the file will have mode #o600
+;;; (readable/ writable by owner, not accessible to others.)  Unlink
+;;; the file as soon as it's opened, to help avoid exposing its contents
+;;; (and to ensure that the file gets deleted when the application
+;;; quits.)
+#-windows-target
+(defun open-logging-fds ()
+  (with-cstrs ((template "/tmp/logfileXXXXXX"))
+    (let* ((write-fd (#_mkstemp template)))
+      (when (>= write-fd 0)
+        (let* ((read-fd (#_open template #$O_RDONLY)))
+          (#_unlink template)
+          (values write-fd read-fd))))))
+
+
+
+(objc:defmethod #/redirectStandardOutput ((self console-window))
+  (with-slots (syslog-out syslog-in) self
+    (multiple-value-bind (write-fd read-fd) (open-logging-fds)
+      (when write-fd
+        (setq syslog-out
+              (make-instance 'ns:ns-file-handle :with-file-descriptor (#_dup 1)
+                             :close-on-dealloc t))
+        (let* ((log-fh (make-instance 'ns:ns-file-handle
+                                      :with-file-descriptor read-fd
+                                      :close-on-dealloc t)))
+          (setq syslog-in log-fh)
+          (let* ((bufsize #$BUFSIZ)
+                 (buffer (#_malloc bufsize)))
+            (setf (slot-value self 'translatebuf) buffer
+                  (slot-value self 'bufsize) bufsize
+                  (slot-value self 'nextra) 0))
+          (#_dup2 write-fd 1)
+          (#_dup2 write-fd 2)
+          (#/scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
+           ns:ns-timer
+           1.0d0
+           self
+           (@selector #/checkForData:)
+           +null-ptr+
+           t)))))
+  self)
+
+(objc:defmethod #/init ((self console-window))
+  (#/release self)
+  #+windows-target +null-ptr+
+  #-windows-target
+  (flet ((path-inode (path)
+           (nth-value 4 (ccl::%stat path)))
+         (fd-inode (fd)
+           (nth-value 4 (ccl::%fstat fd))))
+    (cond ((and nil
+                (eql (fd-inode 0) (path-inode "/dev/null"))
+                (eql (fd-inode 1) (fd-inode 2))
+                (rlet ((pflags :long))
+                  (#_fcntl 2 #$F_GETFL :address pflags)
+                  (let* ((accmode (logand #$O_ACCMODE (pref flags :long))))
+                    (or (eql #$O_RDONLY accmode)
+                        (eql #$O_RDWR accmode)))))
+           (let* ((win (#/typeoutWindowWithTitle: (find-class 'console-window) #@"Console")))
+
+
+             (#/redirectStandardOutput win)
+             (let* ((tv (typeout-view-text-view (typeout-window-typeout-view win))))
+               (#/setTypingAttributes: tv
+                                       (create-text-attributes
+                                        :font (default-font
+                                                  :name #+darwin-target "Monaco"
+                                                  #-darwin-target "Courier"
+                                                :size 10)
+                                        :color (#/redColor ns:ns-color))))
+             (#/setFrameOrigin: win (ns:make-ns-point 20 20))
+             win))
+          (t +null-ptr+))))
+
Index: /branches/new-random/cocoa-ide/defsystem.lisp
===================================================================
--- /branches/new-random/cocoa-ide/defsystem.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/defsystem.lisp	(revision 13309)
@@ -0,0 +1,122 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+;;;
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (use-interface-dir :cocoa))
+
+;; These are used to communicate with ide-bundle, which must be loaded before objc-support.
+;; They are defvar'ed so the caller can set them before loading us.
+(defvar *cocoa-application-path* nil)
+(defvar *cocoa-application-copy-headers-p* nil)
+(require "IDE-BUNDLE")
+
+(require "OBJC-SUPPORT")
+
+(defpackage "GUI"
+  (:use :common-lisp :ccl)
+  (:import-from
+   "CCL"
+   ;; symbols defined here
+   *cocoa-application-path*
+   *cocoa-application-copy-headers-p*
+   load-ide
+   build-ide
+   ;; Misc symbols that perhaps should be exported from CCL but currently aren't.
+   report-bad-arg
+   native-translated-namestring
+   make-id-map
+   assign-id-map-id
+   id-map-free-object
+   process-thread
+   process-serial-number
+   ensure-directory-pathname
+   recursive-copy-directory
+   application
+   ;; Symbols that perhaps should be exported by ObjC support but aren't
+   @selector
+   *nsapp*
+   with-nsstr
+   %make-nsstring
+   lisp-string-from-nsstring
+   with-autorelease-pool
+   ns-height
+   ns-width
+   *cocoa-event-process*
+   create-autorelease-pool
+   release-autorelease-pool
+   release-canonical-nsobject
+   objc-message-send
+   open-main-bundle
+   )
+  (:export
+   "ABSTRACT-NS-LISP-STRING"
+   "NS-LISP-STRING"
+   "NS-LISP-STRING-STRING"
+
+   "EXECUTE-IN-GUI"
+   ))
+
+(defparameter *ide-files*
+  '(;"ide-bundle" - loaded by hand above
+    "cocoa-utils"
+    "cocoa-defaults"
+    "cocoa-prefs"
+    "cocoa-typeout"
+    "console-window"
+    "cocoa-window"
+    "cocoa-doc"
+    "compile-hemlock"
+    "hemlock"  ;; treated specially below, compile-hemlock must come before.
+    "cocoa-editor"
+    "cocoa-listener"
+    "cocoa-grep"
+    "cocoa-backtrace"
+    "inspector"
+    "project"
+    "preferences"
+    "processes-window"
+    "apropos-window"
+    "xapropos"
+    "file-dialogs"
+    "app-delegate"
+    "ide-self-update"
+    "search-files"
+    "start"
+    ))
+
+(defparameter *leopard-only-ide-files*
+  '("xinspector"
+    ))
+
+(defun load-ide (&optional force-compile)
+  (declare (special *hemlock-files*)) ;; kludge
+  (let ((src-dir "ccl:cocoa-ide;")
+	(bin-dir "ccl:cocoa-ide;fasls;"))
+    (ensure-directories-exist bin-dir)
+    ;; kludge to limit experimental files to Leopard
+    #+darwin-target
+    (rlet ((p :int))
+      (#_Gestalt #$gestaltSystemVersion p)
+      (when (>= (%get-long p) #x1050)
+        (setq *ide-files* (append *ide-files* *leopard-only-ide-files*))))
+    (with-compilation-unit ()
+      (dolist (name *ide-files*)
+	(let* ((source (make-pathname :name name :type (pathname-type *.lisp-pathname*)
+				      :defaults src-dir))
+	       (fasl (make-pathname :name name :type (pathname-type *.fasl-pathname*)
+				    :defaults bin-dir))
+	       (sources (cons source
+			      (and (equalp name "hemlock")
+				   ;; This is defined in compile-hemlock, which is loaded first
+				   (mapcar #'hemlock-source-pathname *hemlock-files*)))))
+	  (if (needs-compile-p fasl sources force-compile)
+	    (progn
+	      ;; Once compile something, keep compiling, in case macros changed.
+	      (setq force-compile t)
+	      (compile-file source :output-file fasl :verbose t :load t))
+	    (load fasl :verbose t)))))
+    (provide "COCOA")))
Index: /branches/new-random/cocoa-ide/file-dialogs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/file-dialogs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/file-dialogs.lisp	(revision 13309)
@@ -0,0 +1,112 @@
+(in-package "GUI")
+
+;;;; MCL-ish file dialogs
+
+(defun %cocoa-choose-file-dialog (directory file-types file button-string)
+  (assume-cocoa-thread)
+  (let* ((open-panel (#/openPanel ns:ns-open-panel))
+         (types-array +null-ptr+))
+    ;; Maybe support multiple file selection later.
+    (#/setAllowsMultipleSelection: open-panel #$NO)
+    (when directory
+      (setq directory (#/autorelease (%make-nsstring directory))))
+    (when file
+      (setq file (#/autorelease (%make-nsstring file))))
+    (when file-types
+      (setq types-array (make-instance 'ns:ns-mutable-array))
+      (dolist (type file-types)
+        (let ((s (%make-nsstring type)))
+          (#/addObject: types-array s)
+          (#/release s)))
+      (#/autorelease types-array))
+    (when button-string
+      #-cocotron (#/setPrompt: open-panel (#/autorelease (%make-nsstring button-string))))
+    (let ((result (#/runModalForDirectory:file:types: open-panel directory
+						      file types-array)))
+      (cond ((= result #$NSOKButton)
+	     (lisp-string-from-nsstring (#/filename open-panel)))
+	    ((= result #$NSCancelButton)
+	     nil)
+	    (t
+	     (error "couldn't run the open panel: error code ~d" result))))))
+        
+(defun cocoa-choose-file-dialog (&key directory file-types file button-string)
+  (when directory
+    (setq directory (directory-namestring directory)))
+  (when file-types
+    (unless (and (listp file-types)
+		 (every #'stringp file-types))
+      (error "~s is not a list of strings." file-types)))
+  (when file
+    (setq file (file-namestring file)))
+  (check-type button-string (or null string))
+  (execute-in-gui #'(lambda () (%cocoa-choose-file-dialog directory file-types file button-string))))
+
+(defun %cocoa-choose-new-file-dialog (directory file-types file)
+  (assume-cocoa-thread)
+  (let* ((save-panel (#/savePanel ns:ns-save-panel))
+         (types-array +null-ptr+))
+    #-cocotron (#/setCanSelectHiddenExtension: save-panel t)
+    (when directory
+      (setq directory (#/autorelease (%make-nsstring directory))))
+    (when file
+      (setq file (#/autorelease (%make-nsstring file))))
+    (when file-types
+      (setq types-array (make-instance 'ns:ns-mutable-array))
+      (dolist (type file-types)
+        (let ((s (%make-nsstring type)))
+          (#/addObject: types-array s)
+          (#/release s)))
+      (#/autorelease types-array))
+    #-cocotron (#/setAllowedFileTypes: save-panel types-array)
+    (let ((result (#/runModalForDirectory:file: save-panel directory file)))
+      (cond ((= result #$NSOKButton)
+	     (lisp-string-from-nsstring (#/filename save-panel)))
+	    ((= result #$NSCancelButton)
+	     nil)
+	    (t
+	     (error "couldn't run the save panel: error code ~d" result))))))
+
+(defun cocoa-choose-new-file-dialog (&key directory file-types file)
+  (when directory
+    (setq directory (directory-namestring directory)))
+  (when file
+    (setq file (file-namestring file)))
+  (when file-types
+    (unless (and (listp file-types)
+		 (every #'stringp file-types))
+      (error "~s is not a list of strings." file-types)))
+  (execute-in-gui #'(lambda () (%cocoa-choose-new-file-dialog directory file-types file))))
+
+(defun cocoa-choose-file-dialog-hook-function (must-exist prompt file-types)
+  (declare (ignore prompt))
+  (if must-exist
+    (cocoa-choose-file-dialog :file-types file-types)
+    (cocoa-choose-new-file-dialog :file-types file-types)))
+
+(setq ccl::*choose-file-dialog-hook* 'cocoa-choose-file-dialog-hook-function)
+
+(defun %cocoa-choose-directory-dialog (directory)
+  (assume-cocoa-thread)
+  (let ((open-panel (#/openPanel ns:ns-open-panel)))
+    (#/setCanChooseFiles: open-panel #$NO)
+    (#/setCanChooseDirectories: open-panel #$YES)
+    (#/setAllowsMultipleSelection: open-panel #$NO)
+    (#/setTitle: open-panel #@"Choose Directory")
+    #-cocotron (#/setPrompt: open-panel #@"Choose")
+    (when directory
+      (setq directory (#/autorelease (%make-nsstring directory))))
+    (let  ((result (#/runModalForDirectory:file:types: open-panel directory
+						       nil nil)))
+      (cond ((= result #$NSOKButton)
+	     (make-pathname :directory (lisp-string-from-nsstring
+					(#/directory open-panel))))
+	    ((= result #$NSCancelButton)
+	     nil)
+	    (t
+	     (error "couldn't run the open panel: error code ~d" result))))))
+
+(defun cocoa-choose-directory-dialog (&key directory)
+  (when directory
+    (setq directory (directory-namestring directory)))
+  (execute-in-gui #'(lambda () (%cocoa-choose-directory-dialog directory))))
Index: /branches/new-random/cocoa-ide/hemlock-text.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock-text.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock-text.lisp	(revision 13309)
@@ -0,0 +1,516 @@
+(in-package "GUI")
+
+;;; NSMutableString subclass that uses a Hemlock buffer for
+;;; character storage.
+
+(defclass xhemlock-buffer-string (ns:ns-mutable-string)
+  ((cache :initform (reset-buffer-cache
+		     (make-buffer-cache :buffer (make-untitled-buffer)))
+	  :initarg :cache :accessor hemlock-buffer-string-cache))
+  (:metaclass ns:+ns-object))
+
+(defmethod hemlock-buffer ((self xhemlock-buffer-string))
+  (with-slots (cache) self
+    (when cache
+      (buffer-cache-buffer cache))))
+
+(defvar *untitled-buffer-counter* 0)
+
+(defun next-untitled-buffer-counter ()
+  (ccl::atomic-incf *untitled-buffer-counter*))
+
+(defun make-untitled-buffer ()
+  (loop
+    (let* ((name (format nil "untitled-~d" (next-untitled-buffer-counter)))
+           (buffer (hi:make-buffer name)))
+      (when buffer
+        (return buffer)))))
+
+(objc:defmethod (#/dealloc :void) ((self xhemlock-buffer-string))
+  (let ((buffer (hemlock-buffer self)))
+    (when buffer
+      (when (eq buffer hi::*current-buffer*)
+	(setf hi::*current-buffer* nil))
+      (setf (hi::buffer-document buffer) nil)
+      ;; It makes sense to me to delete the buffer here, but
+      ;; the existing code does it in response to closing a document.
+      ;;(hi::delete-buffer buffer)
+      (setf (slot-value self 'cache) nil)
+      (call-next-method))))
+
+;;; NSMutableString primitive method
+
+(objc:defmethod (#/replaceCharactersInRange:withString: :void)
+                ((self xhemlock-buffer-string) (range #>NSRange) string)
+  (let* ((buffer (hemlock-buffer self))
+	 (cache (hemlock-buffer-string-cache self))
+         (hi::*current-buffer* buffer)
+         (position (pref range #>NSRange.location))
+	 (length (pref range #>NSRange.length))
+	 (lisp-string (if (> (#/length string) 0) (lisp-string-from-nsstring string))))
+    (hi:with-mark ((m (hi:buffer-point buffer)))
+      (move-hemlock-mark-to-absolute-position m cache position)
+      (when (> length 0)
+        (hi:delete-characters m length))
+      (when lisp-string
+        (hi:insert-string m lisp-string)))))
+
+;;; NSString primitive methods
+
+(objc:defmethod (#/length #>NSUInteger) ((self xhemlock-buffer-string))
+  (let* ((cache (hemlock-buffer-string-cache self)))
+    (or (buffer-cache-buflen cache)
+        (setf (buffer-cache-buflen cache)
+              (let* ((buffer (buffer-cache-buffer cache)))
+		(hemlock-buffer-length buffer))))))
+
+#+slow
+(objc:defmethod (#/length #>NSUInteger) ((self xhemlock-buffer-string))
+  (let* ((buffer (hemlock-buffer self))
+	 (hi::*current-buffer* buffer))
+    (hi:count-characters (hi:buffer-region buffer))))
+
+(objc:defmethod (#/characterAtIndex: :unichar) ((self xhemlock-buffer-string)
+						(index #>NSUInteger))
+  (char-code (hemlock-char-at-index (hemlock-buffer-string-cache self) index)))
+
+#+slow
+(objc:defmethod (#/characterAtIndex: :unichar) ((self xhemlock-buffer-string) (index #>NSUInteger))
+  (let* ((buffer (hemlock-buffer self))
+         (hi::*current-buffer* buffer)
+         (start (hi:buffer-start-mark buffer)))
+    (hi:with-mark ((m start))
+      (if (hi:character-offset m index)
+	;; If the lisp character can't be represented as a 16-bit UTF-16
+	;; code point (i.e., the character needs to be encoded with a surrogate
+	;; pair), just punt and return the replacement character.  This is
+	;; clearly not good for Gilgamesh (presumably a cuneiform user), among
+	;; others. If we keep using the Cocoa text system, we'll have to hair
+	;; things up to deal with this at some point.
+	(let* ((char (or (hi:next-character m)
+			 (error "index ~d out of range" index)))
+	       (code (char-code char)))
+	  (if (< code #x10000)
+	    code
+	    #\Replacement_Character))))))
+
+(objc:defmethod (#/getCharacters:range: :void) ((self xhemlock-buffer-string)
+						(buffer (:* :unichar))
+						(r :<NSR>ange))
+  (let* ((cache (hemlock-buffer-string-cache self))
+         (index (ns:ns-range-location r))
+         (length (ns:ns-range-length r))
+         (hi::*current-buffer* (buffer-cache-buffer cache)))
+    #+debug
+    (#_NSLog #@"get characters: %d/%d"
+             :<NSUI>nteger index
+             :<NSUI>nteger length)
+    (multiple-value-bind (line idx) (update-line-cache-for-index cache index)
+      (let* ((len (hemlock::line-length line)))
+        (do* ((i 0 (1+ i)))
+             ((= i length))
+          (cond ((< idx len)
+                 (setf (paref buffer (:* :unichar) i)
+                       (char-code (hemlock::line-character line idx)))
+                 (incf idx))
+                (t
+                 (setf (paref buffer (:* :unichar) i)
+                       (char-code #\Newline)
+                       line (hi::line-next line)
+                       len (if line (hi::line-length line) 0)
+                       idx 0))))))))
+
+
+
+;;; This is bound to T when we edit text using the methods of
+;;; NSTextStorage.  These keeps the Hemlock text primitives from
+;;; calling edited:range:changeInLength: on their own.
+(defvar *suppress-edit-notifications* nil)
+
+;;; NSTextStorage subclass that uses a HemlockBufferString for
+;;; text storage, and for character attributes, too.
+
+(defclass xhemlock-text-storage (ns:ns-text-storage)
+  ((hemlock-string :foreign-type :id :reader hemlock-string)
+   (edit-count :foreign-type :int)
+   (selection-set-by-search :foreign-type #>BOOL))
+  (:metaclass ns:+ns-object))
+
+(defmethod (setf hemlock-string) (new (self xhemlock-text-storage))
+  (with-slots (hemlock-string) self
+    (unless (eql hemlock-string new)
+      (#/release hemlock-string)
+      (setf hemlock-string (#/retain new)))))
+
+(objc:defmethod (#/dealloc :void) ((self xhemlock-text-storage))
+  (setf (hemlock-string self) +null-ptr+)
+  (call-next-method))
+
+(objc:defmethod #/hemlockString ((self xhemlock-text-storage))
+  (slot-value self 'hemlock-string))
+
+(objc:defmethod (#/updateMirror :void) ((self xhemlock-text-storage))
+  ;; don't need to do anything
+  )
+
+(defmethod hemlock-buffer ((self xhemlock-text-storage))
+  (let ((string (hemlock-string self)))
+    (unless (%null-ptr-p string)
+      (hemlock-buffer string))))
+
+(objc:defmethod #/initWithString: ((self xhemlock-text-storage) string)
+  (setq string (%inc-ptr string 0)) ;avoid stack-consed macptr?
+  (ccl::%call-next-objc-method self (find-class 'xhemlock-text-storage)
+                               (@selector #/init) '(:id))
+  (setf (slot-value self 'hemlock-string) (#/retain string))
+  self)
+
+(objc:defmethod #/init ((self xhemlock-text-storage))
+  (#/initWithString: self (make-instance 'xhemlock-buffer-string)))
+
+(objc:defmethod #/string ((self xhemlock-text-storage))
+  (hemlock-string self))
+
+(objc:defmethod (#/replaceCharactersInRange:withString: :void)
+                ((self xhemlock-text-storage) (range #>NSRange) string)
+  (let* ((orig-len (#/length self))
+	 (contents (hemlock-string self))
+	 (*suppress-edit-notifications* t))
+    (#/replaceCharactersInRange:withString: contents range string)
+    (#/edited:range:changeInLength: self #$NSTextStorageEditedCharacters
+                                    range (- (#/length self) orig-len))))
+
+(objc:defmethod (#/setAttributes:range: :void) ((self xhemlock-text-storage)
+                                                (attributes :id)
+                                                (range #>NSRange))
+  (let* ((string (hemlock-string self))
+	 (cache (hemlock-buffer-string-cache (hemlock-string self)))
+	 (buffer (hemlock-buffer string))
+         (hi::*current-buffer* buffer)
+	 (*suppress-edit-notifications* t))
+    (hi:with-mark ((start (hi:buffer-point buffer))
+                   (end (hi:buffer-point buffer)))
+      (move-hemlock-mark-to-absolute-position start cache
+					      (ns:ns-range-location range))
+      (move-hemlock-mark-to-absolute-position end cache
+					      (+ (ns:ns-range-location range)
+						 (ns:ns-range-length range)))
+      (hi::set-region-charprops (hi:region start end) (dict-to-charprops attributes))))
+  (#/edited:range:changeInLength: self #$NSTextStorageEditedAttributes
+                                  range 0))
+
+;;; This appears to be called at every blink of the insertion point.
+(objc:defmethod #/attributesAtIndex:effectiveRange: ((self xhemlock-text-storage)
+                                                     (location #>NSUInteger)
+                                                     (rangeptr (* #>NSRange)))
+  (let* ((buffer (hemlock-buffer (hemlock-string self)))
+         (hi::*current-buffer* buffer))
+    (hi:with-mark ((m (hi:buffer-point buffer)))
+      (move-hemlock-mark-to-absolute-position m
+					      (hemlock-buffer-string-cache
+					       (hemlock-string self))
+					      location)
+      (multiple-value-bind (plist start end)
+                           (hi::line-charprops-for-position (hi:mark-line m) (hi:mark-charpos m))
+        (unless (%null-ptr-p rangeptr)
+	  (let ((origin (hi::get-line-origin (hi:mark-line m))))
+	    (incf start origin)
+	    (incf end origin)
+	    (setf (pref rangeptr #>NSRange.location) start
+		  (pref rangeptr #>NSRange.length) (- end start))))
+	;; This conses up a brand-new NSDictionary every time.
+	;; Some sort of caching may be profitable here (or not...)
+        (charprops-to-dict plist)))))
+
+;;; Return true iff we're inside a "beginEditing/endEditing" pair
+(objc:defmethod (#/editingInProgress :<BOOL>) ((self xhemlock-text-storage))
+  ;; This is meaningless outside the event thread, since you can't tell what
+  ;; other edit-count changes have already been queued up for execution on
+  ;; the event thread before it gets to whatever you might queue up next.
+  (assume-cocoa-thread)
+  (> (slot-value self 'edit-count) 0))
+
+(objc:defmethod (#/beginEditing :void) ((self xhemlock-text-storage))
+  (assume-cocoa-thread)
+  (with-slots (edit-count) self
+    #+debug
+    (#_NSLog #@"begin-editing")
+    (incf edit-count)
+    #+debug
+    (#_NSLog #@"after beginEditing on %@ edit-count now = %d" :id self :int edit-count)
+    (call-next-method)))
+
+(objc:defmethod (#/endEditing :void) ((self xhemlock-text-storage))
+  (assume-cocoa-thread)
+  (with-slots (edit-count) self
+    #+debug
+    (#_NSLog #@"end-editing")
+    (call-next-method)
+    (assert (> edit-count 0))
+    (decf edit-count)
+    #+debug
+    (#_NSLog #@"after endEditing on %@, edit-count now = %d" :id self :int edit-count)))
+
+(objc:defmethod (#/noteHemlockInsertionAtPosition:length: :void)
+    ((self xhemlock-text-storage) (pos :<NSI>nteger) (n :<NSI>nteger)
+     (extra :<NSI>nteger))
+  (declare (ignore extra))
+  (let* ((buffer (hemlock-buffer self))
+	 (document (hi::buffer-document buffer))
+	 (undo-mgr (and document (#/undoManager document))))
+    (when (and undo-mgr (not (#/isUndoing undo-mgr)))
+      (#/replaceCharactersInRange:withString:
+       (#/prepareWithInvocationTarget: undo-mgr self)
+       (ns:make-ns-range pos n) #@"")))
+  (let ((cache (hemlock-buffer-string-cache (hemlock-string self))))
+    (adjust-buffer-cache-for-insertion cache pos n)
+    (update-line-cache-for-index cache pos))
+  (unless *suppress-edit-notifications*
+    (textstorage-note-insertion-at-position self pos n)))
+
+(objc:defmethod (#/noteHemlockDeletionAtPosition:length: :void)
+    ((self xhemlock-text-storage) (pos :<NSI>nteger) (n :<NSI>nteger)
+     (extra :<NSI>nteger))
+  (declare (ignorable extra))
+  (let ((cache (hemlock-buffer-string-cache (hemlock-string self))))
+    (reset-buffer-cache cache)
+    (update-line-cache-for-index cache pos))
+  (unless *suppress-edit-notifications*
+    (ns:with-ns-range (range pos n)
+      (#/edited:range:changeInLength: self
+				      (logior #$NSTextStorageEditedCharacters
+					      #$NSTextStorageEditedAttributes)
+				      range (- n)))))
+
+(objc:defmethod (#/noteHemlockModificationAtPosition:length: :void)
+    ((self xhemlock-text-storage) (pos :<NSI>nteger) (n :<NSI>nteger)
+     (extra :<NSI>nteger))
+  (declare (ignorable extra))
+  (unless *suppress-edit-notifications*
+    (ns:with-ns-range (range pos n)
+      (#/edited:range:changeInLength: self 
+				      (logior #$NSTextStorageEditedCharacters
+					      #$NSTextStorageEditedAttributes)
+				      range 0))))
+
+(objc:defmethod (#/noteHemlockAttrChangeAtPosition:length: :void)
+    ((self xhemlock-text-storage) (pos :<NSI>nteger) (n :<NSI>nteger)
+     (fontnum :<NSI>nteger))
+  (declare (ignore fontnum))
+  (unless *suppress-edit-notifications*
+    (ns:with-ns-range (range pos n)
+      (#/edited:range:changeInLength: self #$NSTextStorageEditedAttributes
+				      range 0))))
+
+(defmethod assume-not-editing ((ts xhemlock-text-storage))
+  #+debug NIL (assert (eql (slot-value ts 'edit-count) 0)))
+
+(defmethod update-hemlock-selection ((self xhemlock-text-storage))
+  (assume-cocoa-thread)
+  (let ((buffer (hemlock-buffer self)))
+    (multiple-value-bind (start end) (hi:buffer-selection-range buffer)
+      #+debug
+      (#_NSLog #@"update Hemlock selection: charpos = %d, abspos = %d"
+               :int (hi::mark-charpos (hi::buffer-point buffer)) :int start)
+      (for-each-textview-using-storage
+       self
+       #'(lambda (tv)
+           (#/updateSelection:length:affinity: tv
+                                               start
+                                               (- end start)
+                                               (if (eql start 0)
+                                                 #$NSSelectionAffinityUpstream
+                                                 #$NSSelectionAffinityDownstream)))))))
+
+
+
+;;; Tabs are going to be a problem.
+(defloadvar *default-paragraph-style*
+    (let* ((style (#/mutableCopy (#/defaultParagraphStyle ns:ns-paragraph-style)))
+           (charwidth (nth-value 1 (size-of-char-in-font *editor-font*))))
+      (#/setLineBreakMode: style #$NSLineBreakByCharWrapping)
+      (#/setTabStops: style (#/array ns:ns-array))
+      (#/setDefaultTabInterval: style (* *tab-width* charwidth))
+      style))
+
+(defun ns-color-to-charprop (color)
+  (let ((color (#/colorUsingColorSpaceName: color #&NSCalibratedRGBColorSpace)))
+    (rlet ((r #>CGFloat)
+           (g #>CGFloat)
+           (b #>CGFloat)
+           (a #>CGFloat))
+      (#/getRed:green:blue:alpha: color r g b a)
+      (flet ((scale (f)
+               (floor (* 255 f))))
+        (let* ((rr (scale (pref r #>CGFloat)))
+               (gg (scale (pref g #>CGFloat)))
+               (bb (scale (pref b #>CGFloat))))
+          (format nil "#~2,'0x~2,'0x~2,'0x" rr gg bb))))))
+
+(defvar *charprop-colors* (make-hash-table :test #'equalp))
+
+(defun ns-color-from-charprop (color-string)
+  (or (gethash color-string *charprop-colors*)
+      (when (and (= (length color-string) 7)
+		 (char= (char color-string 0) #\#))
+	(let* ((rr (ignore-errors (parse-integer color-string :start 1 :end 3 :radix 16)))
+	       (gg (ignore-errors (parse-integer color-string :start 3 :end 5 :radix 16)))
+	       (bb (ignore-errors (parse-integer color-string :start 5 :end 7 :radix 16)))
+	       (aa (cgfloat 1)))
+	  (when (and rr gg bb)
+	    (setq rr (cgfloat (/ rr 255.0))
+		  gg (cgfloat (/ gg 255.0))
+		  bb (cgfloat (/ bb 255.0)))
+	    (setf (gethash color-string *charprop-colors*)
+		  (#/retain (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color
+									rr gg bb aa))))))))
+(defun dict-to-charprops (dict)
+  (let ((enumerator (#/keyEnumerator dict))
+        (plist nil))
+    (loop
+      (let ((key (#/nextObject enumerator)))
+        (when (%null-ptr-p key)
+          (return plist))
+        (let ((value (#/objectForKey: dict key))
+              (keyword (car (rassoc key hi::*cocoa-attributes* :test #'ns-string-equal))))
+          (case keyword
+            (:ns-font
+             (let* ((font value)
+                    (descriptor (#/fontDescriptor font))
+                    (traits-mask (#/symbolicTraits descriptor))
+                    (name (lisp-string-from-nsstring (#/familyName font)))
+                    (size (cgfloat (#/pointSize font))))
+               (setq plist (nconc plist (list :font-name name :font-size size)))
+               (when (logtest traits-mask #$NSFontItalicTrait)
+                 (setq plist (nconc plist (list :font-slant :italic))))
+               (when (logtest traits-mask #$NSFontBoldTrait)
+                 (setq plist (nconc plist (list :font-weight :bold))))
+               (if (logtest traits-mask #$NSFontExpandedTrait)
+                 (setq plist (nconc plist (list :font-width :exapnded)))
+                 (if (logtest traits-mask #$NSFontCondensedTrait)
+                   (setq plist (nconc plist (list :font-width :condensed)))))))
+            (:ns-paragraph-style )
+            (:ns-foreground-color
+             (let* ((color value)
+                    (color-string (ns-color-to-charprop color)))
+               (setq plist (nconc plist (list :font-color color-string)))))
+            (:ns-underline-style
+             (let* ((style (#/intValue value))
+                    (underline-keyword (cond ((= style #$NSUnderlineStyleSingle)
+                                              :single)
+                                             ((= style #$NSUnderlineStyleDouble)
+                                              :double)
+                                             ((= style #$NSUnderlineStyleThick)
+                                              :thick))))
+               (when underline-keyword
+                 (setq plist (nconc plist (list :font-underline underline-keyword))))))
+            (:ns-superscript )
+            (:ns-background-color 
+             (let* ((color value)
+                    (color-string (ns-color-to-charprop color)))
+               (setq plist (nconc plist (list :background-color color-string)))))
+            (:ns-attachment (format t "~s" keyword))
+            (:ns-ligature (format t "~s" keyword))
+            (:ns-baseline-offset (format t "~s" keyword))
+            (:ns-kern (format t "~s" keyword))
+            (:ns-link (format t "~s" keyword))
+            (:ns-stroke-width (format t "~s" keyword))
+            (:ns-stroke-color (format t "~s" keyword))
+            (:ns-underline-color (format t "~s" keyword))
+            (:ns-strikethrough-style (format t "~s" keyword))
+            (:ns-strikethrough-color (format t "~s" keyword))
+            (:ns-shadow (format t "~s" keyword))
+            (:ns-obliqueness (format t "~s" keyword))
+            (:ns-expansion (format t "~s" keyword))
+            (:ns-cursor (format t "~s" keyword))
+            (:ns-tool-tip (format t "~s" keyword))
+            (:ns-character-shap (format t "~s" keyword))
+            (:ns-glyph-info (format t "~s" keyword))))))))
+
+(defun charprops-to-dict (plist)
+  (when (null plist)
+    (return-from charprops-to-dict
+                 (#/dictionaryWithObjectsAndKeys: ns:ns-dictionary
+						  *default-paragraph-style*
+						  #&NSParagraphStyleAttributeName
+						  *editor-font*
+						  #&NSFontAttributeName
+						  +null-ptr+)))
+  (let* ((dict (#/dictionaryWithCapacity: ns:ns-mutable-dictionary 8))
+         (default-font *editor-font*)	;what about listeners?
+         (fm (#/sharedFontManager ns:ns-font-manager))
+         (font +null-ptr+)
+         (font-name nil))
+    (#/setObject:forKey: dict *default-paragraph-style*
+                         #&NSParagraphStyleAttributeName)
+    (setq font-name (getf plist :font-name))
+    (when font-name
+      (case font-name
+        (:document-font (setq font (#/userFontOfSize: ns:ns-font 0.0)))
+        (:fixed-font (setq font (#/userFixedPitchFontOfSize: ns:ns-font 0.0)))
+        (:system-font (setq font (#/systemFontOfSize: ns:ns-font 0.0)))
+        (t (setq font (#/fontWithName:size: ns:ns-font
+                                            (#/autorelease (%make-nsstring font-name))
+                                            0.0)))))
+    (when (%null-ptr-p font)
+      (setq font default-font))
+    (loop for (k v) on plist by #'cddr
+      do (case k
+           (:font-size
+	    (setq v (float v ns:+cgfloat-zero+))
+	    (setq font (#/convertFont:toSize: fm font v)))
+           (:font-weight
+	    (cond
+	      ((eq v :bold)
+	       (setq font (#/convertFont:toHaveTrait: fm font #$NSBoldFontMask)))
+	      ((eq v :plain)
+	       (setq font (#/convertFont:toHaveTrait: fm font #$NSUnboldFontMask)))))
+           (:font-width
+	    (cond
+	      ((eq v :condensed)
+	       (setq font (#/convertFont:toHaveTrait: fm font #$NSCondensedFontMask)))
+	      ((eq v :expanded)
+	       (setq font (#/convertFont:toHaveTrait: fm font #$NSExpandedFontMask)))))
+           (:font-slant
+	    (cond ((eq v :italic)
+		   (setq font (#/convertFont:toHaveTrait: fm font #$NSItalicFontMask)))
+		  ((eq v :roman)
+		   (setq font (#/convertFont:toHaveTrait: fm font #$NSUnitalicFontMask)))))
+           (:font-underline
+	    (let (n)
+	      (case v
+		(:single
+		 (setq n (#/numberWithInt: ns:ns-number #$NSUnderlineStyleSingle)))
+		(:double
+		 (setq n (#/numberWithInt: ns:ns-number #$NSUnderlineStyleDouble)))
+		(:thick
+		 (setq n (#/numberWithInt: ns:ns-number #$NSUnderlineStyleThick))))
+	      (when n
+		(#/setObject:forKey: dict n #&NSUnderlineStyleAttributeName))))
+           (:font-color
+	    (let ((color (ns-color-from-charprop v)))
+	      (when color
+		(#/setObject:forKey: dict color #&NSForegroundColorAttributeName))))
+           (:background-color
+	    (let ((color (ns-color-from-charprop v)))
+	      (when color
+		(#/setObject:forKey: dict color #&NSBackgroundColorAttributeName))))))
+    (unless (%null-ptr-p font)
+      (#/setObject:forKey: dict font #&NSFontAttributeName))
+    dict))
+
+(defclass xhemlock-text-view (ns:ns-text-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+;;; replaces version in cocoa-editor.lisp
+
+(defun make-textstorage-for-hemlock-buffer (buffer)
+  (make-instance 'xhemlock-text-storage
+                 :with-string
+                 (make-instance
+                  'xhemlock-buffer-string
+                  :cache
+                  (reset-buffer-cache
+                   (make-buffer-cache)
+                   buffer))))
Index: /branches/new-random/cocoa-ide/hemlock.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock.lisp	(revision 13309)
@@ -0,0 +1,9 @@
+;;;-*- Mode: LISP; Package: CCL -*-
+
+(in-package "CCL")
+
+(require "COMPILE-HEMLOCK")
+
+(format t "~&;;; Compiling Hemlock ...")
+
+(compile-hemlock t)
Index: /branches/new-random/cocoa-ide/hemlock/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/INSTALL
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/INSTALL	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/INSTALL	(revision 13309)
@@ -0,0 +1,16 @@
+                          INSTALLATION NOTES
+
+Phemlock comes with a mk:defsystem style .system file. So when you are
+lucky you just can fire up your Lisp and say
+
+    (oos :hemlock :load)
+
+    (hemlock)
+
+This was tested with:
+
+ - CMUCL
+ - ACL
+ - CLISP using MIT CLX
+
+
Index: /branches/new-random/cocoa-ide/hemlock/README
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/README	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/README	(revision 13309)
@@ -0,0 +1,98 @@
+                               Phemlock
+                         The Portable Hemlock
+
+Please see:
+
+    http://www.stud.uni-karlsruhe.de/~unk6/hemlock/
+
+This is an attempt to free Hemlock from its CMUCL prison. In the long
+run I want to be able to run Hemlock on any system which supports ANSI
+Common Lisp and CLIM. 
+
+The source code of Hemlock showed unportability (or better its age) in
+the following areas:
+
+ - Buffers sometimes also serve as streams. As Hemlock was written
+   there was no universal de-facto standard interface for user defined
+   streams and the source code defined CMUCL streams. These days we
+   have Gray streams.
+
+ - File I/O was tied to both CMUCL and Unix and probably slow
+   machines. The file i/o functions directly called unix-read and
+   unix-write and beam data direcly to and fro system areas. I changed
+   that using standard CL functions doing i/o on a line-by-line basis
+   now.
+
+ - The TTY interface is inherently unportable. Currently it is
+   disabled altogether. I think we could reclaim some useful code from
+   Hemlock's TTY interface and morph it into a CLIM TTY port. And
+   since my screen cannot even display a text console interface, this
+   has very low priority on my list, though other people might want to
+   have it.
+
+ - The X11 interface uses the SERVE-EVENT facility of CMUCL, which
+   naturally is only available there. I provided a thin portability
+   layer to provide the same API using just the standard CLX
+   interface.
+
+This already summaries pretty well the current state of Phemlock. You
+can edit files using the X11 interface on an ANSI CL which provides
+for CLX.
+
+
+FUTURE
+
+The next steps I have in mind are:
+
+ - Port the missing files except the TTY interface.
+
+ - Hemlock has the idea that characters are 8-bit wide. We need to
+   teach it otherwise as we have Unicode strings now. This involves
+   syntax tables and probably searching.
+
+ - I want a CLIM Hemlock.
+
+   How exactly to do this is still not decided. I see two
+   possibilities:
+
+   . Hemlock already provides for a kind of device interface. We can
+     implement a new device which is just a CLIM device.
+
+   . Or we rip this device abstraction layer and state that CLIM
+     itself is the device layer. (Making the bet that we'll have a TTY
+     CLIM in the future).
+
+After that is done, we can talk about extending Phemlock in various
+ways like syntax highlighting, color, new modes, ...
+
+
+RANDOM NOTES
+
+. Hemlock has this feature of so called buffered lines; from the
+  documentation in line.lisp:
+
+    ;; A buffered line:
+    ;;    The line hasn't been touched since it was read from a file, and the
+    ;;    actual contents are in some system I/O area.  This is indicated by
+    ;;    the Line-Buffered-P slot being true.  In buffered lines on the RT,
+    ;;    the %Chars slot contains the system-area-pointer to the beginning
+    ;;    of the characters.
+
+  This sounds like a good idea actually. Though it seems that the CMUCL
+  implementation does this by using sap pointers and beams some data
+  back and fro to actual strings.
+
+  However, I am not very fond of random low-level byte-bashing hacks and
+  so the READ-FILE and WRITE-FILE functions are now just reading and
+  writing on a line by line basis which makes them clean an portable.
+
+  So the current state in Phemlock is: line-buffered-p is always nil. 
+
+. It uses EXT:COMPLETE-FILE which is defined in cmucl:filesys.lisp.
+  We'll need a portable definition.
+
+
+-- 
+Gilbert Baumann <unk6@stud.uni-karlsruhe.de>
+2003-02-06
+$Id$
Index: /branches/new-random/cocoa-ide/hemlock/TODO
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/TODO	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/TODO	(revision 13309)
@@ -0,0 +1,21 @@
+TODO
+
+Feel free to stick your own notes into it, be sure to append a
+signature.
+
+- we need to get rid of hemlock11.cursor and hemlock11.mask
+  --GB 2003-03-26
+
+- Provide the classes fundamental-character-{input|output}-stream for SCL
+
+- Write a style guide.
+  . signed comments
+  . no 80-characters-per-line limitations
+  . no #+/#- in the main code body
+  . no :: in the main code body
+  . no changes to bindings in bindings.lisp
+    unless one updates the manual too.
+
+- Import the scribe parser and work on the html converter
+
+$Id$
Index: /branches/new-random/cocoa-ide/hemlock/bin/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/bin/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/bin/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/bin/openmcl/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/bin/openmcl/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/bin/openmcl/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*fsl
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/doc/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/doc/cim/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/cim/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/cim/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/doc/cim/aux-sys.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/cim/aux-sys.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/cim/aux-sys.mss	(revision 13309)
@@ -0,0 +1,694 @@
+@comment{-*- Dictionary: /usr/lisp/scribe/hem/hem; Mode: spell; Package: Hemlock; Log: /usr/lisp/scribe/hem/hem-docs.log -*-}
+@chapter (Auxiliary Systems)
+This chapter describes utilities that some implementations of @hemlock may
+leave unprovided or unsupported.
+
+
+@section[Key-events]
+@index(I/O)
+@index[keyboard input]
+@index[input, keyboard]
+@index[mouse input]
+@index[input, mouse]
+@label[key-events]
+
+These routines are defined in the @f["EXTENSIONS"] package since other projects
+have often used @hemlock's input translations for interfacing to CLX.
+
+
+@subsection[Introduction]
+
+The canonical representation of editor input is a key-event structure.  Users
+can bind commands to keys (see section @ref[key-bindings]), which are non-zero
+length sequences of key-events.  A key-event consists of an identifying token
+known as a @i[keysym] and a field of bits representing modifiers.  Users define
+keysyms, integers between 0 and 65535 inclusively, by supplying names that
+reflect the legends on their keyboard's keys.  Users define modifier names
+similarly, but the system chooses the bit and mask for recognizing the
+modifier.  You can use keysym and modifier names to textually specify
+key-events and Hemlock keys in a @f[#k] syntax.  The following are some
+examples:
+@begin[programexample]
+   #k"C-u"
+   #k"Control-u"
+   #k"c-m-z"
+   #k"control-x meta-d"
+   #k"a"
+   #k"A"
+   #k"Linefeed"
+@end[programexample]
+This is convenient for use within code and in init files containing
+@f[bind-key] calls.
+
+The @f[#k] syntax is delimited by double quotes, but the system parses the
+contents rather than reading it as a Common Lisp string.  Within the double
+quotes, spaces separate multiple key-events.  A single key-event optionally
+starts with modifier names terminated by hyphens.  Modifier names are
+alphabetic sequences of characters which the system uses case-insensitively.
+Following modifiers is a keysym name, which is case-insensitive if it consists
+of multiple characters, but if the name consists of only a single character,
+then it is case-sensitive.
+
+You can escape special characters @dash hyphen, double quote, open angle
+bracket, close angle bracket, and space @dash with a backslash, and you can
+specify a backslash by using two contiguously.  You can use angle brackets to
+enclose a keysym name with many special characters in it.  Between angle
+brackets appearing in a keysym name position, there are only two special
+characters, the closing angle bracket and backslash.
+
+
+
+@subsection[Interface]
+
+All of the following routines and variables are exported from the "EXTENSIONS"
+("EXT") package.
+
+
+@defun[fun {define-keysym}, args {@i[keysym] @i[preferred-name] @rest @i[other-names]}]
+This function establishes a mapping from @i[preferred-name] to @i[keysym] for
+purposes of @f[#k] syntax.  @i[Other-names] also map to @i[keysym], but the
+system uses @i[preferred-name] when printing key-events.  The names are
+case-insensitive simple-strings; however, if the string contains a single
+character, then it is used case-sensitively.  Redefining a keysym or re-using
+names has undefined effects.
+
+You can use this to define unused keysyms, but primarily this defines keysyms
+defined in the @i[X Window System Protocol, MIT X Consortium Standard, X
+Version 11, Release 4].  @f[translate-key-event] uses this knowledge to
+determine what keysyms are modifier keysyms and what keysym stand for
+alphabetic key-events.
+@enddefun
+
+
+@defun[fun {define-mouse-keysym}, args {@i[button] @i[keysym] @i[name] @i[shifted-bit] @i[event-key]}]
+This function defines @i[keysym] named @i[name] for key-events representing the
+X @i[button] cross the X @i[event-key] (@kwd[button-press] or
+@kwd[button-release]).  @i[Shifted-bit] is a defined modifier name that
+@f[translate-mouse-key-event] sets in the key-event it returns whenever the X
+shift bit is set in an incoming event.
+
+Note, by default, there are distinct keysyms for each button distinguishing
+whether the user pressed or released the button.
+
+@i[Keysym] should be an one unspecified in @i[X Window System Protocol, MIT X
+Consortium Standard, X Version 11, Release 4].
+@enddefun
+
+
+@defun[fun {name-keysym}, args {@i[name]}]
+This function returns the keysym named @i[name].  If @i[name] is unknown, this
+returns @nil.
+@enddefun
+
+@defun[fun {keysym-names}, args {@i[keysym]}]
+This function returns the list of all names for @i[keysym].  If @i[keysym] is
+undefined, this returns @nil.
+@enddefun
+
+@defun[fun {keysym-preferred-name}, args {@i[keysym]}]
+This returns the preferred name for @i[keysym], how it is typically printed.
+If @i[keysym] is undefined, this returns @nil.
+@enddefun
+
+@defun[fun {define-key-event-modifier}, args {@i[long-name] @i[short-name]}]
+This establishes @i[long-name] and @i[short-name] as modifier names for
+purposes of specifying key-events in @f[#k] syntax.  The names are
+case-insensitive simple-strings.  If either name is already defined, this
+signals an error.
+
+The system defines the following default modifiers (first the long name,
+then the short name):
+@begin[Itemize]
+@f["Hyper"], @f["H"]
+
+@f["Super"], @f["S"]
+
+@f["Meta"], @f["M"]
+
+@f["Control"], @f["C"]
+
+@f["Shift"], @f["Shift"]
+
+@f["Lock"], @f["Lock"]
+@end[Itemize]
+@enddefun
+
+
+@defvar[var {all-modifier-names}]
+This variable holds all the defined modifier names.
+@enddefvar
+
+
+@defun[fun {define-clx-modifier}, args {@i[clx-mask] @i[modifier-name]}]
+This function establishes a mapping from @i[clx-mask] to a defined key-event
+@i[modifier-name].  @f[translate-key-event] and @f[translate-mouse-key-event]
+can only return key-events with bits defined by this routine.
+
+The system defines the following default mappings between CLX modifiers and
+key-event modifiers:
+@begin[Itemize]
+@f[(xlib:make-state-mask :mod-1)    -->  "Meta"]
+
+@f[(xlib:make-state-mask :control)  -->  "Control"]
+
+@f[(xlib:make-state-mask :lock)     -->  "Lock"]
+
+@f[(xlib:make-state-mask :shift)    -->  "Shift"]
+@end[Itemize]
+@enddefun
+
+
+@defun[fun {make-key-event-bits}, args {@rest @i[modifier-names]}]
+This function returns bits suitable for @f[make-key-event] from the supplied
+@i[modifier-names].  If any name is undefined, this signals an error.
+@enddefun
+
+@defun[fun {key-event-modifier-mask}, args {@i[modifier-name]}]
+This function returns a mask for @i[modifier-name].  This mask is suitable for
+use with @f[key-event-bits].  If @i[modifier-name] is undefined, this signals
+an error.
+@enddefun
+
+@defun[fun {key-event-bits-modifiers}, args {@i[bits]}]
+This returns a list of key-event modifier names, one for each modifier
+set in @i[bits].
+@enddefun
+
+
+@defun[fun {translate-key-event}, args {@i[display] @i[scan-code] @i[bits]}]
+This function translates the X @i[scan-code] and X @i[bits] to a key-event.
+First this maps @i[scan-code] to an X keysym using @f[xlib:keycode->keysym]
+looking at @i[bits] and supplying index as @f[1] if the X shift bit is on,
+@f[0] otherwise.
+
+If the resulting keysym is undefined, and it is not a modifier keysym,
+then this signals an error.  If the keysym is a modifier key, then this
+returns @nil.
+
+If these conditions are satisfied
+@begin[Itemize]
+The keysym is defined.
+
+The X shift bit is off.
+
+The X lock bit is on.
+
+The X keysym represents a lowercase letter.
+@end[Itemize]
+then this maps the @i[scan-code] again supplying index as @f[1] this time,
+treating the X lock bit as a caps-lock bit.  If this results in an undefined
+keysym, this signals an error.  Otherwise, this makes a key-event with the
+keysym and bits formed by mapping the X bits to key-event bits.
+
+Otherwise, this makes a key-event with the keysym and bits formed by
+mapping the X bits to key-event bits.
+@enddefun
+
+
+@defun[fun {translate-mouse-key-event}, args {@i[scan-code] @i[bits] @i[event-key]}]
+This function translates the X button code, @i[scan-code], and modifier bits,
+@i[bits], for the X @i[event-key] into a key-event.  See
+@f[define-mouse-keysym].
+@enddefun
+
+@defun[fun {make-key-event}, args {@i[object] @i[bits]}]
+This function returns a key-event described by @i[object] with @i[bits].
+@i[Object] is one of keysym, string, or key-event.  When @i[object] is a
+key-event, this uses @f[key-event-keysym].  You can form @i[bits] with
+@f[make-key-event-bits] or @f[key-event-modifier-mask].
+@enddefun
+
+@defun[fun {key-event-p}, args {@i[object]}]
+This function returns whether @i[object] is a key-event.
+@enddefun
+
+@defun[fun {key-event-bits}, args {@i[key-event]}]
+This function returns the bits field of a @i[key-event].
+@enddefun
+
+@defun[fun {key-event-keysym}, args {@i[key-event]}]
+This function returns the keysym field of a @i[key-event].
+@enddefun
+
+@defun[fun {char-key-event}, args {@i[character]}]
+This function returns the key-event associated with @i[character].  You can
+associate a key-event with a character by @f[setf]'ing this form.
+@enddefun
+
+@defun[fun {key-event-char}, args {@i[key-event]}]
+This function returns the character associated with @i[key-event].  You can
+associate a character with a key-event by @f[setf]'ing this form.  The system
+defaultly translates key-events in some implementation dependent way for text
+insertion; for example, under an ASCII system, the key-event @f[#k"C-h"], as
+well as @f[#k"backspace"] would map to the Common Lisp character that causes a
+backspace.
+@enddefun
+
+@defun[fun {key-event-bit-p}, args {@i[key-event] @i[bit-name]}]
+This function returns whether @i[key-event] has the bit set named by
+@i[bit-name].  This signals an error if @i[bit-name] is undefined.
+@enddefun
+
+@defmac[fun {do-alpha-key-events}, args
+{(@i[var] @i[kind] @optional @i[result]) @mstar<@i[form]>}]
+ This macro evaluates each @i[form] with @i[var] bound to a key-event
+representing an alphabetic character.  @i[Kind] is one of @kwd[lower],
+@kwd[upper], or @kwd[both], and this binds @i[var] to each key-event in order
+as specified in @i[X Window System Protocol, MIT X Consortium Standard, X
+Version 11, Release 4].  When @kwd[both] is specified, this processes lowercase
+letters first.
+@enddefmac
+
+@defun[fun {print-pretty-key}, args {@i[key] @optional @i[stream] @i[long-names-p]}]
+This prints @i[key], a key-event or vector of key-events, in a user-expected
+fashion to @i[stream].  @i[Long-names-p] indicates whether modifiers should
+print with their long or short name.  @i[Stream] defaults to
+@var[standard-output].
+@enddefun
+
+@defun[fun {print-pretty-key-event}, args {@i[key-event] @optional @i[stream] @i[long-names-p]}]
+This prints @i[key-event] to @i[stream] in a user-expected fashion.
+@i[Long-names-p] indicates whether modifier names should appear using the long
+name or short name.  @i[Stream] defaults to @var[standard-output].
+@enddefun
+
+
+
+@section (CLX Interface)
+
+@subsection (Graphics Window Hooks)
+This section describes a few hooks used by Hemlock's internals to handle
+graphics windows that manifest Hemlock windows.  Some heavy users of Hemlock as
+a tool have needed these in the past, but typically functions that replace the
+default values of these hooks must be written in the "@f[HEMLOCK-INTERNALS]"
+package.  All of these symbols are internal to this package.
+
+If you need this level of control for your application, consult the current
+implementation for code fragments that will be useful in correctly writing your
+own window hook functions.
+
+@defvar[var {create-window-hook}]
+This holds a function that @Hemlock calls when @f[make-window] executes under
+CLX.  @Hemlock passes the CLX display and the following arguments from
+@f[make-window]: starting mark, ask-user, x, y, width, height, and modelinep.
+The function returns a CLX window or nil indicating one could not be made.
+@enddefvar
+
+@defvar[var {delete-window-hook}]
+This holds a function that @hemlock calls when @f[delete-window] executes under
+CLX.  @hemlock passes the CLX window and the @hemlock window to this function.
+@enddefvar
+
+@defvar[var {random-typeout-hook}]
+This holds a function that @hemlock calls when random typeout occurs under CLX.
+@hemlock passes it a @hemlock device, a pre-existing CLX window or @nil, and
+the number of pixels needed to display the number of lines requested in the
+@f[with-pop-up-display] form.  It should return a window, and if a new window
+is created, then a CLX gcontext must be the second value.
+@enddefvar
+
+@defvar[var {create-initial-windows-hook}]
+This holds a function that @hemlock calls when it initializes the screen
+manager and makes the first windows, typically windows for the @hid[Main] and
+@hid[Echo Area] buffers.  @hemlock passes the function a @hemlock device.
+@enddefvar
+
+
+@subsection (Entering and Leaving Windows)
+
+@defhvar[var "Enter Window Hook"]
+When the mouse enters an editor window, @hemlock invokes the functions in this
+hook.  These functions take a @Hemlock window as an argument.
+@enddefhvar
+
+@defhvar[var "Exit Window Hook"]
+When the mouse exits an editor window, @hemlock invokes the functions in this
+hook.  These functions take a @Hemlock window as an argument.
+@enddefhvar
+
+
+@subsection (How to Lose Up-Events)
+Often the only useful activity user's design for the mouse is to click on
+something.  @Hemlock sees a character representing the down event, but what do
+you do with the up event character that you know must follow?  Having the
+command eat it would be tasteless, and would inhibit later customizations that
+make use of it, possibly adding on to the down click command's functionality.
+Bind the corresponding up character to the command described here.
+
+@defcom[com "Do Nothing"]
+This does nothing as many times as you tell it.
+@enddefcom
+
+
+@section (Slave Lisps)
+@index (Slave lisp interface functions)
+Some implementations of @hemlock feature the ability to manage multiple slave
+Lisps, each connected to one editor Lisp.  The routines discussed here spawn
+slaves, send evaluation and compilation requests, return the current server,
+etc.  This is very powerful because without it you can lose your editing state
+when code you are developing causes a fatal error in Lisp.
+
+The routines described in this section are best suited for creating editor
+commands that interact with slave Lisps, but in the past users implemented
+several independent Lisps as nodes communicating via these functions.  There is
+a better level on which to write such code that avoids the extra effort these
+routines take for the editor's sake.  See the @i[CMU Common Lisp User's Manual]
+for the @f[remote] and @f[wire] packages.
+
+
+@subsection (The Current Slave)
+There is a slave-information structure that these return which is suitable for
+passing to the routines described in the following subsections.
+
+@defun[fun {create-slave}, args {@optional @i[name]}]
+This creates a slave that tries to connect to the editor.  When the slave
+connects to the editor, this returns a slave-information structure, and the
+interactive buffer is the buffer named @i[name].  This generates a name if
+@i[name] is @nil.  In case the slave never connects, this will eventually
+timeout and signal an editor-error.
+@enddefun
+
+@defun[fun {get-current-eval-server}, args {@optional @i[errorp]}]
+@defhvar1[var {Current Eval Server}]
+This returns the server-information for the @hid[Current Eval Server] after
+making sure it is valid.  Of course, a slave Lisp can die at anytime.  If this
+variable is @nil, and @i[errorp] is non-@nil, then this signals an
+editor-error; otherwise, it tries to make a new slave.  If there is no current
+eval server, then this tries to make a new slave, prompting the user based on a
+few variables (see the @i[Hemlock User's Manual]).
+@enddefun
+
+@defun[fun {get-current-compile-server}]
+@defhvar1[var {Current Compile Server}]
+This returns the server-information for the @hid[Current Compile Server] after
+making sure it is valid.  This may return nil.  Since multiple slaves may
+exist, it is convenient to use one for developing code and one for compiling
+files.  The compilation commands that use slave Lisps prefer to use the current
+compile server but will fall back on the current eval server when necessary.
+Typically, users only have separate compile servers when the slave Lisp can
+live on a separate workstation to save cycles on the editor machine, and the
+@hemlock commands only use this for compiling files.
+@enddefun
+
+
+@subsection (Asynchronous Operation Queuing)
+The routines in this section queue requests with an eval server.  Requests are
+always satisfied in order, but these do not wait for notification that the
+operation actually happened.  Because of this, the user can continue editing
+while his evaluation or compilation occurs.  Note, these usually execute in the
+slave immediately, but if the interactive buffer connected to the slave is
+waiting for a form to return a value, the operation requested must wait until
+the slave is free again.
+
+@defun[fun {string-eval}, args {@i[string]}, keys {[server][package][context]}]
+@defun1[fun {region-eval}, args {@i[region]}, keys {[server][package][context]}]
+@defun1[fun {region-compile}, args {@i[region]}, keys {[server][package]}]
+@f[string-eval] queues the evaluation of the form read from @i[string] on eval
+server @i[server].  @i[Server] defaults to the result of
+@f[get-current-server], and @i[string] is a simple-string.  The evaluation
+occurs with @var[package] bound in the slave to the package named by
+@i[package], which defaults to @hid[Current Package] or the empty string; the
+empty string indicates that the slave should evaluate the form in its current
+package.  The slave reads the form in @i[string] within this context as well.
+@i[Context] is a string to use when reporting start and end notifications in
+the @hid[Echo Area] buffer; it defaults to the concatenation of @f["evaluation
+of "] and @i[string].
+
+@f[region-eval] is the same as @f[string-eval], but @i[context] defaults
+differently.  If the user leaves this unsupplied, then it becomes a string
+involving part of the first line of region.
+
+@f[region-compile] is the same as the above.  @i[Server] defaults the same; it
+does not default to @f[get-current-compile-server] since this compiles the
+region into the slave Lisp's environment, to affect what you are currently
+working on.
+@enddefun
+
+@defun[fun {file-compile}, args {@i[file]},
+			   keys {[output-file][error-file][load][server]},
+			   morekeys {[package]}]
+@defhvar1[var {Remote Compile File}, val {nil}]
+This compiles @i[file] in a slave Lisp.  When @i[output-file] is @true (the
+default), this uses a temporary output file that is publicly writable in case
+the client is on another machine, which allows for file systems that do not
+permit remote write access.  This renames the temporary file to the appropriate
+binary name or deletes it after compilation.  Setting @hid[Remote Compile File]
+to @nil, inhibits this.  If @i[output-file] is non-@nil and not @true, then it
+is the name of the binary file to write.  The compilation occurs with
+@var[package] bound in the slave to the package named by @i[package], which
+defaults to @hid[Current Package] or the empty string; the empty string
+indicates that the slave should evaluate the form in its current package.
+@i[Error-file] is the file in which to record compiler output, and a @nil value
+inhibits this file's creation.  @i[Load] indicates whether to load the
+resulting binary file, defaults to @nil.  @i[Server] defaults to
+@f[get-current-compile-server], but if this returns nil, then @i[server]
+defaults to @f[get-current-server].
+@enddefun
+
+@subsection (Synchronous Operation Queuing)
+The routines in this section queue requests with an eval server and wait for
+confirmation that the evaluation actually occurred.  Because of this, the user
+cannot continue editing while the slave executes the request.  Note, these
+usually execute in the slave immediately, but if the interactive buffer
+connected to the slave is waiting for a form to return a value, the operation
+requested must wait until the slave is free again.
+
+@defun[fun {eval-form-in-server},
+       args {@i[server-info] @i[string] @optional @i[package]}]
+ This function queues the evaluation of a form in the server associated with
+@i[server-info] and waits for the results.  The server @f[read]'s the form from
+@i[string] with @var[package] bound to the package named by @i[package].  This
+returns the results from the slave Lisp in a list of string values.  You can
+@f[read] from the strings or simply display them depending on the @f[print]'ing
+of the evaluation results.
+
+@i[Package] defaults to @hid[Current Package].  If this is @nil, the server
+uses the value of @var[package] in the server.
+
+While the slave executes the form, it binds @var[terminal-io] to a stream that
+signals errors when read from and dumps output to a bit-bucket.  This prevents
+the editor and slave from dead locking by waiting for each other to reply.
+@enddefun
+
+@defun[fun {eval-form-in-server-1},
+       args {@i[server-info] @i[string] @optional @i[package]}]
+ This function calls @f[eval-form-in-server] and @f[read]'s the result in the
+first string it returns.  This result must be @f[read]'able in the editor's
+Lisp.
+@enddefun
+
+
+@section (Spelling)
+@index (Spelling checking)
+@hemlock supports spelling checking and correcting commands based on the ITS
+Ispell dictionary.  These commands use the following routines which include
+adding and deleting entries, reading the Ispell dictionary in a compiled binary
+format, reading user dictionary files in a text format, and checking and
+correcting possible spellings.
+
+@defun[fun {maybe-read-spell-dictionary}, package {spell}]
+This reads the default binary Ispell dictionary.  Users must call this before
+the following routines will work.
+@enddefun
+
+@defun[fun {spell-read-dictionary}, package {spell}, args {@i[filename]}]
+This adds entries to the dictionary from the lines in the file @i[filename].
+Dictionary files contain line oriented records like the following:
+@begin[programexample]
+entry1/flag1/flag2
+entry2
+entry3/flag1
+@end[programexample]
+The flags are the Ispell flags indicating which endings are appropriate for the
+given entry root, but these are unnecessary for user dictionary files.  You can
+consult Ispell documentation if you want to know more about them.
+@enddefun
+
+@defun[fun {spell-add-entry}, package {spell},
+       args {@i[line] @optional @i[word-end]}]
+This takes a line from a dictionary file, and adds the entry described by
+@i[line] to the dictionary.  @i[Word-end] defaults to the position of the first
+slash character or the length of the line.  @i[Line] is destructively modified.
+@enddefun
+
+@defun[fun {spell-remove-entry}, package {spell}, args {@i[entry]}]
+This removes entry, a simple-string, from the dictionary, so it will be an
+unknown word.  This destructively modifies @i[entry].  If it is a root word,
+then all words derived with @i[entry] and its flags will also be deleted.  If
+@i[entry] is a word derived from some root word, then the root and any words
+derived from it remain known words.
+@enddefun
+
+@defun[fun {correct-spelling}, package {spell}, args {@i[word]}]
+This checks the spelling of @i[word] and outputs the results.  If this finds
+@i[word] is correctly spelled due to some appropriate suffix on a root, it
+generates output indicating this.  If this finds @i[word] as a root entry, it
+simply outputs that it found @i[word].  If this cannot find @i[word] at all,
+then it outputs possibly correct close spellings.  This writes to
+@var[standard-output], and it calls @f[maybe-read-spell-dictionary] before
+attempting any lookups.
+@enddefun
+
+@defun[fun {spell-try-word}, package {spell}, args {@i[word] @i[word-len]}]
+@defcon1[var {max-entry-length}, val {31}]
+This returns an index into the dictionary if it finds @i[word] or an
+appropriate root.  @i[Word-len] must be inclusively in the range 2 through
+@f[max-entry-length], and it is the length of @i[word].  @i[Word] must be
+uppercase.  This returns a second value indicating whether it found @i[word]
+due to a suffix flag, @nil if @i[word] is a root entry.
+@enddefun
+
+@defun[fun {spell-root-word}, package {spell}, args {@i[index]}]
+This returns a copy of the root word at dictionary entry @i[index].  This index
+is the same as returned by @f[spell-try-word].
+@enddefun
+
+@defun[fun {spell-collect-close-words}, package {spell}, args {@i[word]}]
+This returns a list of words correctly spelled that are @i[close] to @i[word].
+@i[Word] must be uppercase, and its length must be inclusively in the range 2
+through @f[max-entry-length].  Close words are determined by the Ispell rules:
+@begin[enumerate]
+Two adjacent letters can be transposed to form a correct spelling.
+
+One letter can be changed to form a correct spelling.
+
+One letter can be added to form a correct spelling.
+
+One letter can be removed to form a correct spelling.
+@end[enumerate]
+@enddefun
+
+@defun[fun {spell-root-flags}, package {spell}, args {@i[index]}]
+This returns a list of suffix flags as capital letters that apply to the
+dictionary root entry at @i[index].  This index is the same as returned by
+@f[spell-try-word].
+@enddefun
+
+
+@section (File Utilities)
+Some implementations of @hemlock provide extensive directory editing commands,
+@hid[Dired], including a single wildcard feature.  An asterisk denotes a
+wildcard.
+
+@defun[fun {copy-file}, package {dired},
+       args {@i[spec1] @i[spec2]}, keys {[update][clobber][directory]}]
+ This function copies @i[spec1] to @i[spec2].  It accepts a single wildcard in
+the filename portion of the specification, and it accepts directories.  This
+copies files maintaining the source's write date.
+
+If @i[spec1] and @i[spec2] are both directories, this recursively copies the
+files and subdirectory structure of @i[spec1]; if @i[spec2] is in the
+subdirectory structure of @i[spec1], the recursion will not descend into it.
+Use @f["/spec1/*"] to copy only the files from @i[spec1] to directory
+@i[spec2].
+
+If @i[spec2] is a directory, and @i[spec1] is a file, then this copies
+@i[spec1] into @i[spec2] with the same @f[pathname-name].
+
+When @kwd[update] is non-@nil, then the copying process only copies files if the
+source is newer than the destination.
+
+When @kwd[update] and @kwd[clobber] are @nil, and the destination exists, the
+copying process stops and asks the user whether the destination should be
+overwritten.
+
+When the user supplies @kwd[directory], it is a list of pathnames, directories
+excluded, and @i[spec1] is a pattern containing one wildcard.  This then copies
+each of the pathnames whose @f[pathname-name] matches the pattern.  @i[Spec2]
+is either a directory or a pathname whose @f[pathname-name] contains a
+wildcard.
+@enddefun
+
+@defun[fun {rename-file}, package {dired},
+       args {@i[spec1] @i[spec2]}, keys {[clobber][directory]}]
+ This function renames @i[spec1] to @i[spec2].  It accepts a single wildcard in
+the filename portion of the specification, and @i[spec2] may be a directory
+with the destination specification resulting in the merging of @i[spec2] with
+@i[spec1].  If @kwd[clobber] is @nil, and @i[spec2] exists, then this asks the
+user to confirm the renaming.  When renaming a directory, end the specification
+without the trailing slash.
+
+When the user supplies @kwd[directory], it is a list of pathnames, directories
+excluded, and @i[spec1] is a pattern containing one wildcard.  This then copies
+each of the pathnames whose @f[pathname-name] matches the pattern.  @i[Spec2]
+is either a directory or a pathname whose @f[pathname-name] contains a
+wildcard.
+@enddefun
+
+@defun[fun {delete-file}, package {dired},
+       args {@i[spec]}, keys {[recursive][clobber]}]
+ This function deletes @i[spec].  It accepts a single wildcard in the filename
+portion of the specification, and it asks for confirmation on each file if
+@kwd[clobber] is @nil.  If @kwd[recursive] is non-@nil, then @i[spec] may be a
+directory to recursively delete the entirety of the directory and its
+subdirectory structure.  An empty directory may be specified without
+@kwd[recursive] being non-@nil.  Specify directories with the trailing
+slash.
+@enddefun
+
+@defun[fun {find-file}, package {dired},
+       args {@i[name] @optional @i[directory] @i[find-all]}]
+ This function finds the file with @f[file-namestring] @i[name], recursively
+looking in @i[directory].  If @i[find-all] is non-@nil (defaults to @nil), then
+this continues searching even after finding a first occurrence of file.
+@i[Name] may contain a single wildcard, which causes @i[find-all] to default to
+@true instead of @nil.
+@enddefun
+
+@defun[fun {make-directory}, package {dired}, args {@i[name]}]
+This function creates the directory with @i[name].  If it already exists, this
+signals an error.
+@enddefun
+
+@defun[fun {pathnames-from-pattern}, package {dired},
+       args {@i[pattern] @i[files]}]
+This function returns a list of pathnames from the list @i[files] whose
+@f[file-namestring]'s match @i[pattern].  @i[Pattern] must be a non-empty
+string and contain only one asterisk.  @i[Files] contains no directories.
+@enddefun
+
+@defvar[var {update-default}, package {dired}]
+@defvar1[var {clobber-default}, package {dired}]
+@defvar1[var {recursive-default}, package {dired}]
+These are the default values for the keyword arguments above with corresponding
+names.  These default to @nil, @true, and @nil respectively.
+@enddefvar
+
+@defvar[var {report-function}, package {dired}]
+@defvar1[var {error-function}, package {dired}]
+@defvar1[var {yesp-function}, package {dired}]
+These are the function the above routines call to report progress, signal
+errors, and prompt for @i[yes] or @i[no].  These all take format strings and
+arguments.
+@enddefvar
+
+
+@defun[fun {merge-relative-pathnames}, args {@i[pathname] @i[default-directory]}]
+This function merges @i[pathname] with @i[default-directory].  If @i[pathname]
+is not absolute, this assumes it is relative to @i[default-directory].  The
+result is always a directory pathname.
+@enddefun
+
+@defun[fun {directoryp}, args {@i[pathname]}]
+This function returns whether @i[pathname] names a directory: it has no name
+and no type fields.
+@enddefun
+
+
+@section (Beeping)
+
+@defun[fun {hemlock-beep}]
+@Hemlock binds @f[system:*beep-function*] to this function to beep the device.
+It is different for different devices.
+@enddefun
+
+@defhvar[var "Bell Style", val {:border-flash}]
+@defhvar1[var "Beep Border Width", val {20}]
+@hid[Bell Style] determines what @var[hemlock-beep] does in @hemlock under CLX.
+Acceptable values are @kwd[border-flash], @kwd[feep],
+@kwd[border-flash-and-feep], @kwd[flash], @kwd[flash-and-feep], and @nil (do
+nothing).
+
+@hid[Beep Border Width] is the width in pixels of the border flashed by border
+flash beep styles.
+@enddefhvar
Index: /branches/new-random/cocoa-ide/hemlock/doc/cim/cim.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/cim/cim.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/cim/cim.mss	(revision 13309)
@@ -0,0 +1,4039 @@
+@make[Manual] @comment{-*- Dictionary: /afs/cs/project/clisp/docs/hem/hem; Mode: spell; Package: Hemlock; Log: /usr/lisp/scribe/hem/hem-docs.log -*-}
+@Device[postscript]
+@style(FontFamily = TimesRoman)
+@Style(Spacing = 1.2 lines)
+@Style(StringMax = 5000)
+@style(Hyphenation = On)
+@style(Date="March 1952")
+@use(database "/afs/cs/project/clisp/docs/database/")
+@Style [DoubleSided]
+@Libraryfile[ArpaCredit]
+@Libraryfile[Hem]
+@Libraryfile[Spice]
+@Libraryfile[Uttir]
+
+@String(ReportTitle "Hemlock Command Implementor's Manual")
+
+@comment<
+@begin[TitlePage]
+@begin[TitleBox]
+>
+@blankspace(1.3inches)
+@heading[Hemlock Command Implementor's Manual]
+
+@center[
+@b<Bill Chiles>
+@b<Rob MacLachlan>
+
+@b<@value[date]>
+
+@b<CMU-CS-89-134-R1>
+]
+@comment<@end[TitleBox]>
+@blankspace(2lines)
+@begin[Center]
+School of Computer Science
+Carnegie Mellon University
+Pittsburgh, PA 15213
+@end[Center]
+
+@blankspace(2lines)
+@begin[Center]
+This is a revised version of Technical Report CMU-CS-87-159.
+@end[Center]
+@heading[Abstract]
+@begin(Text, indent 0)
+This document describes how to write commands for the @Hemlock text editor, as
+of version M3.2.  @Hemlock is a customizable, extensible text editor whose
+initial command set closely resembles that of ITS/TOPS-20 @Emacs.  @Hemlock is
+written in the CMU Common Lisp and has been ported to other implementations.
+@end(Text)
+
+@blankspace(0.5in)
+@begin[ResearchCredit]
+@arpacredit[Contract=Basic87-90]
+@end[ResearchCredit]
+@comment<@end[TitlePage]>
+
+
+@commandstring(dash = "@Y[M]")
+
+
+@Tabclear
+
+@chapter(Introduction)
+
+ @hemlock is a text editor which follows in the tradition of editors
+such as EMACS and the Lisp Machine editor ZWEI.  In its basic form,
+@hemlock has almost the same command set as EMACS, and similar
+features such as multiple buffers and windows, extended commands,
+and built in documentation.
+
+Both user extensions and the original commands are written in Lisp,
+therefore a command implementor will have a working knowledge of this
+language.  Users not familiar with Lisp need not despair however.  Many
+users of Multics EMACS, another text editor written in Lisp, came to learn
+Lisp simply for the purpose of writing their own editor extensions, and
+found, to their surprise, that it was really pretty easy to write simple
+commands.
+
+This document describes the Common Lisp functions, macros and data structures
+that are used to implement new commands.  The basic editor consists of a set of
+Lisp utility functions for manipulating buffers and the other data structures
+of the editor as well as handling the display.  All user level commands are
+written in terms of these functions.  To find out how to define commands see
+chapter @ref[commands].
+
+@chapter(Representation of Text)
+@index (Lines)
+@section(Lines)
+In @hemlock all text is in some @i[line].  Text is broken into lines wherever
+it contains a newline character; newline characters are never stored, but are
+assumed to exist between every pair of lines.  The implicit newline character
+is treated as a single character by the text primitives.
+
+@defun[fun {linep}, args {@i[line]}]
+This function returns @true if @i[line] is a @f[line] object, otherwise @nil.
+@enddefun
+
+@defun[fun {line-string}, args {@i[line]}]
+Given a @i(line), this function returns as a simple string the characters in
+the line.  This is @f[setf]'able to set the @f[line-string] to any string that
+does not contain newline characters.  It is an error to destructively modify
+the result of @f[line-string] or to destructively modify any string after the
+@f[line-string] of some line has been set to that string.
+@enddefun
+
+@defun[fun {line-previous}, args {@i[line]}]
+@defun1[fun {line-next}, args {@i[line]}]
+Given a @i(line), @f[line-previous] returns the previous line or @nil if there
+is no previous line.  Similarly, @f[line-next] returns the line following
+@i[line] or @nil.
+@enddefun
+
+@defun[fun {line-buffer}, args {@i[line]}]
+This function returns the buffer which contains this @i(line).  Since a
+line may not be associated with any buffer, in which case @f[line-buffer]
+returns @nil.
+@enddefun
+
+@defun[fun {line-length}, args {@i[line]}]
+This function returns the number of characters in the @i(line).  This excludes
+the newline character at the end.
+@enddefun
+
+@defun[fun {line-character}, args {@i[line] @i[index]}]
+This function returns the character at position @i[index] within @i[line].  It
+is an error for @i[index] to be greater than the length of the line or less
+than zero.  If @i[index] is equal to the length of the line, this returns a
+@f[#\newline] character.
+@enddefun
+
+@defun[fun {line-plist}, args {@i[line]}]
+This function returns the property-list for @i[line].  @f[setf], @f[getf],
+@f[putf] and @f[remf] can be used to change properties.  This is typically used
+in conjunction with @f[line-signature] to cache information about the line's
+contents.
+@enddefun
+
+@defun[fun {line-signature}, args {@i[line]}]
+This function returns an object that serves as a signature for a @i[line]'s
+contents.  It is guaranteed that any modification of text on the line will
+result in the signature changing so that it is not @f[eql] to any previous
+value.  The signature may change even when the text remains unmodified, but
+this does not happen often.
+@enddefun
+
+
+@section(Marks)
+@label[marks]
+@index (Marks)
+A mark indicates a specific position within the text represented by a line and
+a character position within that line.  Although a mark is sometimes loosely
+referred to as pointing to some character, it in fact points between
+characters.  If the @f[charpos] is zero, the previous character is the newline
+character separating the previous line from the mark's @f[line].  If the
+charpos is equal to the number of characters in the line, the next character is
+the newline character separating the current line from the next.  If the mark's
+line has no previous line, a mark with @f[charpos] of zero has no previous
+character; if the mark's line has no next line, a mark with @f[charpos] equal
+to the length of the line has no next character.
+
+This section discusses the very basic operations involving marks, but a lot of
+@hemlock programming is built on altering some text at a mark.  For more
+extended uses of marks see chapter @ref[doing-stuff].
+
+
+@subsection(Kinds of Marks)
+@index (Permanent marks)
+@index (Temporary marks)
+A mark may have one of two lifetimes: @i[temporary] or @i[permanent].
+Permanent marks remain valid after arbitrary operations on the text; temporary
+marks do not.  Temporary marks are used because less bookkeeping overhead is
+involved in their creation and use.  If a temporary mark is used after the text
+it points to has been modified results will be unpredictable.  Permanent marks
+continue to point between the same two characters regardless of insertions and
+deletions made before or after them.
+
+There are two different kinds of permanent marks which differ only in their
+behavior when text is inserted @i(at the position of the mark); text is
+inserted to the left of a @i[left-inserting] mark and to the right of
+@i[right-inserting] mark.
+
+
+@subsection(Mark Functions)
+@defun[fun {markp}, args {@i[mark]}]
+This function returns @true if @i[mark] is a @f[mark] object, otherwise @nil.
+@enddefun
+
+@defun[fun {mark-line}, args {@i[mark]}]
+This function returns the line to which @i(mark) points.
+@enddefun
+
+@defun[fun {mark-charpos}, args {@i[mark]}]
+This function returns the character position of the character after @i(mark).
+If @i[mark]'s line has no next line, this returns the length of the line as
+usual; however, there is actually is no character after the mark.
+@enddefun
+
+@defun[fun {mark-kind}, args {@i[mark]}]
+This function returns one of @kwd[right-inserting], @kwd[left-inserting] or
+@kwd[temporary] depending on the mark's kind.  A corresponding @f[setf] form
+changes the mark's kind.
+@enddefun
+
+@defun[fun {previous-character}, args {@i[mark]}]
+@defun1[fun {next-character}, args {@i[mark]}]
+This function returns the character immediately before (after) the position of
+the @i[mark], or @nil if there is no previous (next) character.  These
+characters may be set with @f[setf] when they exist; the @f[setf] methods for
+these forms signal errors when there is no previous or next character.
+@enddefun
+
+
+@subsection(Making Marks)
+@defun[fun {mark}, args {@i[line] @i[charpos] @optional @i[kind]}]
+This function returns a mark object that points to the @i(charpos)'th character
+of the @i(line).  @i(Kind) is the kind of mark to create, one of
+@kwd[temporary], @kwd[left-inserting], or @kwd[right-inserting].  The default
+is @kwd[temporary].
+@enddefun
+
+@defun[fun {copy-mark}, args {@i[mark] @optional @i[kind]}]
+This function returns a new mark pointing to the same position and of the same
+kind, or of kind @i[kind] if it is supplied.
+@enddefun
+
+@defun[fun {delete-mark}, args {@i[mark]}]
+This function deletes @i(mark).  Delete any permanent marks when you are
+finished using it.
+@enddefun
+
+@Defmac[Fun {with-mark}, Args 
+        {(@Mstar<(@i[mark] @i[pos] @mopt[@i(kind)])>) @Mstar<@i[form]>}]
+ This macro binds to each variable @i[mark] a mark of kind @i[kind], which
+defaults to @kwd[temporary], pointing to the same position as the mark @i[pos].
+On exit from the scope the mark is deleted.  The value of the last @i[form] is
+the value returned.
+@enddefmac
+
+
+@subsection(Moving Marks)
+@index(Moving marks)
+These functions destructively modify marks to point to new positions.  Other
+sections of this document describe mark moving routines specific to higher
+level text forms than characters and lines, such as words, sentences,
+paragraphs, Lisp forms, etc.
+
+@defun[fun {move-to-position}, args {@i[mark] @i[charpos] @optional @i[line]}]
+This function changes the @i(mark) to point to the given character position on
+the line @i(line).  @i(Line) defaults to @i[mark]'s line.
+@enddefun
+
+@defun[fun {move-mark}, args {@i[mark] @i[new-position]}]
+This function moves @i[mark] to the same position as the mark @i[new-position]
+and returns it.
+@enddefun
+
+@defun[fun {line-start}, args {@i[mark] @optional @i[line]}]
+@defun1[fun {line-end}, args {@i[mark] @optional @i[line]}]
+This function changes @i[mark] to point to the beginning or the end of @i(line)
+and returns it.  @i[Line] defaults to @i[mark]'s line.
+@enddefun
+
+@defun[fun {buffer-start}, args {@i[mark] @optional @i[buffer]}]
+@defun1[fun {buffer-end}, args {@i[mark] @optional @i[buffer]}]
+These functions change @i[mark] to point to the beginning or end of @i[buffer],
+which defaults to the buffer @i[mark] currently points into.  If @i[buffer] is
+unsupplied, then it is an error for @i[mark] to be disassociated from any
+buffer.
+@enddefun
+
+@defun[fun {mark-before}, args {@i[mark]}]
+@defun1[fun {mark-after}, args {@i[mark]}]
+These functions change @i[mark] to point one character before or after the
+current position.  If there is no character before/after the current position,
+then they return @nil and leave @i[mark] unmodified.
+@enddefun
+
+@defun[fun {character-offset}, args {@i[mark] @i[n]}]
+This function changes @i[mark] to point @i[n] characters after (@i[n] before if
+@i[n] is negative) the current position.  If there are less than @i[n]
+characters after (before) the @i[mark], then this returns @nil and @i[mark] is
+unmodified.
+@enddefun
+
+@defun[fun {line-offset}, args {@i[mark] @i[n] @optional @i[charpos]}]
+This function changes @i[mark] to point @i[n] lines after (@i[n] before if
+@i[n] is negative) the current position.  The character position of the
+resulting mark is
+@lisp
+(min (line-length @i(resulting-line)) (mark-charpos @i(mark)))
+@endlisp
+if @i[charpos] is unspecified, or
+@lisp
+(min (line-length @i(resulting-line)) @i(charpos))
+@endlisp
+if it is.  As with @funref(character-offset), if there are not @i[n] lines then
+@nil is returned and @i[mark] is not modified.
+@enddefun
+
+
+@section(Regions)
+@index (Regions)
+A region is simply a pair of marks: a starting mark and an ending mark.
+The text in a region consists of the characters following the starting
+mark and preceding the ending mark (keep in mind that a mark points between
+characters on a line, not at them).
+
+By modifying the starting or ending mark in a region it is possible to
+produce regions with a start and end which are out of order or even in
+different buffers.  The use of such regions is undefined and may
+result in arbitrarily bad behavior.
+
+
+@subsection(Region Functions)
+@defun[fun {region}, args {@i[start] @i[end]}]
+This function returns a region constructed from the marks @i[start] and
+@i[end].  It is an error for the marks to point to non-contiguous lines or for
+@i(start) to come after @i(end).
+@enddefun
+
+@defun[fun {regionp}, args {@i[region]}]
+This function returns @true if @i[region] is a @f[region] object, otherwise
+@nil.
+@enddefun
+
+@defun[fun {make-empty-region}]
+This function returns a region with start and end marks pointing to the start
+of one empty line.  The start mark is a @kwd[right-inserting] mark, and the end
+is a @kwd[left-inserting] mark.
+@enddefun
+
+@defun[fun {copy-region}, args {@i[region]}]
+This function returns a region containing a copy of the text in the specified
+@i[region].  The resulting region is completely disjoint from @i[region] with
+respect to data references @dash marks, lines, text, etc.
+@enddefun
+
+@defun[fun {region-to-string}, args {@i[region]}]
+@defun1[fun {string-to-region}, args {@i[string]}]
+These functions coerce regions to Lisp strings and vice versa.  Within the
+string, lines are delimited by newline characters.
+@enddefun
+
+@defun[fun {line-to-region}, args {@i[line]}]
+This function returns a region containing all the characters on @i[line].  The
+first mark is @kwd[right-inserting] and the last is @kwd[left-inserting].
+@enddefun
+
+@defun[fun {region-start}, args {@i[region]}]
+@defun1[fun {region-end}, args {@i[region]}]
+This function returns the start or end mark of @i(region).
+@enddefun
+
+@defun[fun {region-bounds}, args {@i[region]}]
+This function returns as multiple-values the starting and ending marks of
+@i[region].
+@enddefun
+
+@defun[fun {set-region-bounds}, args {@i[region] @i[start] @i[end]}]
+This function sets the start and end of region to @i[start] and @i[end].  It is
+an error for @i[start] to be after or in a different buffer from @i[end].
+@enddefun
+
+@index(Counting lines and characters)
+@defun[fun {count-lines}, args {@i[region]}]
+This function returns the number of lines in the @i(region), first and last
+lines inclusive.  A newline is associated with the line it follows, thus a
+region containing some number of non-newline characters followed by one newline
+is one line, but if a newline were added at the beginning, it would be two
+lines.
+@enddefun
+
+@defun[fun {count-characters}, args {@i[region]}]
+This function returns the number of characters in a given @i(region).  This
+counts line breaks as one character.
+@enddefun
+
+@defun[fun {check-region-query-size}, args {@i[region]}]
+@defhvar1[var {Region Query Size}, val {30}]
+@f[check-region-query-size] counts the lines in @i[region], and if their number
+exceeds the @hid[Region Query Size] threshold, it prompts the user for
+confirmation.  This should be used in commands that perform destructive
+operations and are not undoable.  If the user responds negatively, then this
+signals an editor-error, aborting whatever command was in progress.
+@enddefun
+
+
+
+@chapter(Buffers)
+@index (Buffers)
+@label[buffers]
+A buffer is an environment within @hemlock consisting of:
+@begin(enumerate)
+A name.
+
+A piece of text.
+
+A current focus of attention, the point.
+
+An associated file (optional).
+
+A write protect flag.
+
+Some variables (page @pageref[variables]).
+
+Some key bindings (page @pageref[key-bindings]).
+
+Some collection of modes (page @pageref[modes]).
+
+Some windows in which it is displayed (page @pageref[windows]).
+
+A list of modeline fields (optional).
+@end(enumerate)
+
+
+@section (The Current Buffer)
+@index (Current buffer)
+@defun[fun {current-buffer}]
+@defhvar1[var {Set Buffer Hook}]
+@defhvar1[var {After Set Buffer Hook}]
+@f[current-buffer] returns the current buffer object.  Usually this is the
+buffer that @funref[current-window] is displaying.  This value may be changed
+with @f[setf], and the @f[setf] method invokes @hid[Set Buffer Hook] before the
+change occurs with the new value.  After the change occurs, the method invokes
+@hid[After Set Buffer Hook] with the old value.
+@enddefun
+
+@defun[fun {current-point}]
+This function returns the @f[buffer-point] of the current buffer.
+This is such a common idiom in commands that it is defined despite
+its trivial implementation.
+@enddefun
+
+@defun[fun {current-mark}]
+@defun1[fun {pop-buffer-mark}]
+@defun1[fun {push-buffer-mark}, args {@i[mark] @optional @i[activate-region]}]
+@index(Buffer mark stack)
+@index(Mark stack)
+@label(mark-stack)
+@f[current-mark] returns the top of the current buffer's mark stack.  There
+always is at least one mark at the beginning of the buffer's region, and all
+marks returned are right-inserting.
+
+@f[pop-buffer-mark] pops the current buffer's mark stack, returning the mark.
+If the stack becomes empty, this pushes a new mark on the stack pointing to the
+buffer's start.  This always deactivates the current region (see section
+@ref[active-regions]).
+
+@f[push-buffer-mark] pushes @i[mark] into the current buffer's mark stack,
+ensuring that the mark is right-inserting.  If @i[mark] does not point into the
+current buffer, this signals an error.  Optionally, the current region is made
+active, but this never deactivates the current region (see section
+@ref[active-regions]).  @i[Mark] is returned.
+@enddefun
+
+@defvar[var {buffer-list}]
+This variable holds a list of all the buffer objects made with @f[make-buffer].
+@enddefvar
+
+@defvar[var {buffer-names}]
+This variable holds a @f[string-table] (page @pageref(string-tables)) of all the
+names of the buffers in @var[buffer-list].  The values of the entries are the
+corresponding buffer objects.
+@enddefvar
+
+@defvar[var {buffer-history}]
+This is a list of buffer objects ordered from those most recently selected to
+those selected farthest in the past.  When someone makes a buffer, an element
+of @hid[Make Buffer Hook] adds this buffer to the end of this list.  When
+someone deletes a buffer, an element of @hid[Delete Buffer Hook] removes the
+buffer from this list.  Each buffer occurs in this list exactly once, but it
+never contains the @var[echo-area-buffer].
+@enddefvar
+
+@defun[fun {change-to-buffer}, args {@i[buffer]}]
+This switches to @i[buffer] in the @f[current-window] maintaining
+@f[buffer-history].
+@enddefun
+
+@defun[fun {previous-buffer}]
+This returns the first buffer from @var[buffer-history] that is not the
+@f[current-buffer].  If none can be found, then this returns @nil.
+@enddefun
+
+
+@section(Buffer Functions)
+@defun[fun {make-buffer}, args {@i[name]}, keys {[modes][modeline-fields][delete-hook]}]
+@defhvar1[var {Make Buffer Hook}]
+@defhvar1[var {Default Modeline Fields}]
+@f[make-buffer] creates and returns a buffer with the given @i(name).  If a
+buffer named @i[name] already exists, @nil is returned.  @i[Modes] is a list of
+modes which should be in effect in the buffer, major mode first, followed by
+any minor modes.  If this is omitted then the buffer is created with the list
+of modes contained in @hvarref[Default Modes].  @i[Modeline-fields] is a list
+of modeline-field objects (see section @ref[modelines]) which may be @nil.
+@f[delete-hook] is a list of delete hooks specific to this buffer, and
+@f[delete-buffer] invokes these along with @hid[Delete Buffer Hook].
+
+Buffers created with @f[make-buffer] are entered into the list
+@var[buffer-list], and their names are inserted into the
+string-table @var[buffer-names].  When a buffer is created the hook
+@hid[Make Buffer Hook] is invoked with the new buffer.
+@enddefun
+
+@defun[fun {bufferp}, args {@i[buffer]}]
+Returns @true if @i[buffer] is a @f[buffer] object, otherwise @nil.
+@enddefun
+
+@defun[fun {buffer-name}, args {@i[buffer]}]
+@defhvar1[var {Buffer Name Hook}]
+@f[buffer-name] returns the name, which is a string, of the given @i(buffer).
+The corresponding @f[setf] method invokes @hid[Buffer Name Hook] with
+@i[buffer] and the new name and then sets the buffer's name.  When the user
+supplies a name for which a buffer already exists, the @f[setf] method signals
+an error.
+@enddefun
+
+@defun[fun {buffer-region}, args {@i[buffer]}]
+Returns the @i[buffer]'s region.  This can be set with @f[setf].  Note, this
+returns the region that contains all the text in a buffer, not the
+@funref[current-region].
+@enddefun
+
+@defun[fun {buffer-pathname}, args {@i[buffer]}]
+@defhvar1[var {Buffer Pathname Hook}]
+@f[buffer-pathname] returns the pathname of the file associated with
+the given @i(buffer), or nil if it has no associated file.  This is
+the truename of the file as of the most recent time it was read or
+written.  There is a @f[setf] form to change the pathname.  When the
+pathname is changed the hook @hid[Buffer Pathname Hook] is invoked
+with the buffer and new value.
+@enddefun
+
+@defun[fun {buffer-write-date}, args {@i[buffer]}]
+Returns the write date for the file associated with the buffer in universal
+time format.  When this the @f[buffer-pathname] is set, use @f[setf] to set
+this to the corresponding write date, or to @nil if the date is unknown or
+there is no file.
+@enddefun
+
+@defun[fun {buffer-point}, args {@i[buffer]}]
+Returns the mark which is the current location within @i[buffer].  To
+move the point, use @f[move-mark] or @funref[move-to-position] rather
+than setting @f[buffer-point] with @f[setf].
+@enddefun
+
+@defun[fun {buffer-mark}, args {@i[buffer]}]
+@index(Buffer mark stack)
+@index(Mark stack)
+This function returns the top of @i[buffer]'s mark stack.  There always
+is at least one mark at the beginning of @i[buffer]'s region, and all marks
+returned are right-inserting.
+@enddefun
+
+@defun[fun {buffer-start-mark}, args {@i[buffer]}]
+@defun1[fun {buffer-end-mark}, args {@i[buffer]}]
+These functions return the start and end marks of @i[buffer]'s region:
+@Begin[ProgramExample]
+(buffer-start-mark buffer)  <==>
+  (region-start (buffer-region buffer))
+and
+(buffer-end-mark buffer)  <==>
+  (region-end (buffer-region buffer))
+@End[ProgramExample]
+@enddefun
+
+@defun[fun {buffer-writable}, args {@i[buffer]}]
+@defhvar1[var "Buffer Writable Hook"]
+This function returns @true if you can modify the @i(buffer), @nil if you
+cannot.  If a buffer is not writable, then any attempt to alter text in the
+buffer results in an error.  There is a @f[setf] method to change this value.
+
+The @f[setf] method invokes the functions in @hid[Buffer Writable Hook] on the
+buffer and new value before storing the new value.
+@enddefun
+
+@defun[fun {buffer-modified}, args {@i[buffer]}]
+@defhvar1[var "Buffer Modified Hook"]
+@f[buffer-modified] returns @true if the @i[buffer] has been modified, @nil if
+it hasn't.  This attribute is set whenever a text-altering operation is
+performed on a buffer.  There is a @f[setf] method to change this value.
+
+The @f[setf] method invokes the functions in @hid[Buffer Modified Hook] with
+the buffer whenever the value of the modified flag changes.
+@enddefun
+
+@defmac[fun {with-writable-buffer}, args {(@i[buffer]) @rest @i[forms]}]
+This macro executes @i[forms] with @i[buffer]'s writable status set.  After
+@i[forms] execute, this resets the @i[buffer]'s writable and modified status.
+@enddefmac
+
+@defun[fun {buffer-signature}, args {@i[buffer]}]
+This function returns an arbitrary number which reflects the buffer's current
+@i[signature].  The result is @f[eql] to a previous result if and only if the
+buffer has not been modified between the calls.
+@enddefun
+
+@defun[fun {buffer-variables}, args {@i[buffer]}]
+This function returns a string-table (page @pageref[string-tables]) containing
+the names of the buffer's local variables.  See chapter @ref[variables].
+@enddefun
+
+@defun[fun {buffer-modes}, args {@i[buffer]}]
+This function returns the list of the names of the modes active in @i[buffer].
+The major mode is first, followed by any minor modes.  See chapter @ref[modes].
+@enddefun
+
+@defun[fun {buffer-windows}, args {@i[buffer]}]
+This function returns the list of all the windows in which the buffer may be
+displayed.  This list may include windows which are not currently visible.  See
+page @pageref[windows] for a discussion of windows.
+@enddefun
+
+@defun[fun {buffer-delete-hook}, args {@i[buffer]}]
+This function returns the list of buffer specific functions @f[delete-buffer]
+invokes when deleting a buffer.  This is @f[setf]'able.
+@enddefun
+
+@defun[fun {delete-buffer}, args {@i[buffer]}]
+@defhvar1[var {Delete Buffer Hook}]
+@f[delete-buffer] removes @i[buffer] from @varref[buffer-list] and its name
+from @varref[buffer-names].  Before @i[buffer] is deleted, this invokes the
+functions on @i[buffer] returned by @f[buffer-delete-hook] and those found in
+@hid[Delete Buffer Hook].  If @i[buffer] is the @f[current-buffer], or if it is
+displayed in any windows, then this function signals an error.
+@enddefun
+
+@defun[fun {delete-buffer-if-possible}, args {@i[buffer]}]
+This uses @f[delete-buffer] to delete @i[buffer] if at all possible.  If
+@i[buffer] is the @f[current-buffer], then this sets the @f[current-buffer] to
+the first distinct buffer in @f[buffer-history].  If @i[buffer] is displayed in
+any windows, then this makes each window display the same distinct buffer.
+@enddefun
+
+
+@section(Modelines)
+@index(Modelines)
+@label(modelines)
+
+A Buffer may specify a modeline, a line of text which is displayed across the
+bottom of a window to indicate status information.  Modelines are described as
+a list of @f[modeline-field] objects which have individual update functions and
+are optionally fixed-width.  These have an @f[eql] name for convenience in
+referencing and updating, but the name must be unique for all created
+modeline-field objects.  When creating a modeline-field with a specified width,
+the result of the update function is either truncated or padded on the right to
+meet the constraint.  All modeline-field functions must return simple strings
+with standard characters, and these take a buffer and a window as arguments.
+Modeline-field objects are typically shared amongst, or aliased by, different
+buffers' modeline fields lists.  These lists are unique allowing fields to
+behave the same wherever they occur, but different buffers may display these
+fields in different arrangements.
+
+Whenever one of the following changes occurs, all of a buffer's modeline fields
+are updated:
+@Begin[Itemize]
+A buffer's major mode is set.
+
+One of a buffer's minor modes is turned on or off.
+
+A buffer is renamed.
+
+A buffer's pathname changes.
+
+A buffer's modified status changes.
+
+A window's buffer is changed.
+@End[Itemize]
+
+The policy is that whenever one of these changes occurs, it is guaranteed that
+the modeline will be updated before the next trip through redisplay.
+Furthermore, since the system cannot know what modeline-field objects the
+user has added whose update functions rely on these values, or how he has
+changed @hid[Default Modeline Fields], we must update all the fields.  When any
+but the last occurs, the modeline-field update function is invoked once for
+each window into the buffer.  When a window's buffer changes, each
+modeline-field update function is invoked once; other windows' modeline
+fields should not be affected due to a given window's buffer changing.
+
+The user should note that modelines can be updated at any time, so update
+functions should be careful to avoid needless delays (for example, waiting for
+a local area network to determine information).
+
+@defun[fun {make-modeline-field}, keys {[name][width][function]}]
+@defun1[fun {modeline-field-p}, args @i(modeline-field)]
+@defun1[fun {modeline-field-name}, args @i(modeline-field)]
+@f[make-modeline-field] returns a modeline-field object with @i[name],
+@i[width], and @i[function].  @i[Width] defaults to @nil meaning that the field
+is variable width; otherwise, the programmer must supply this as a positive
+integer.  @i[Function] must take a buffer and window as arguments and return a
+@f[simple-string] containing only standard characters.  If @i[name] already
+names a modeline-field object, then this signals an error.
+
+@f[modeline-field-name] returns the name field of a modeline-field object.  If
+this is set with @f[setf], and the new name already names a modeline-field,
+then the @f[setf] method signals an error.
+
+@f[modeline-field-p] returns @true or @nil, depending on whether its argument
+is a @f[modeline-field] object.
+@enddefun
+
+@defun[fun {modeline-field}, args {@i[name]}]
+This returns the modeline-field object named @i[name].  If none exists, this
+returns nil.
+@enddefun
+
+@defun[fun {modeline-field-function}, args {@i[modeline-field]}]
+Returns the function called when updating the @i[modeline-field].  When this is
+set with @f[setf], the @f[setf] method updates @i[modeline-field] for all
+windows on all buffers that contain the given field, so the next trip through
+redisplay will reflect the change.  All modeline-field functions must return
+simple strings with standard characters, and they take a buffer and a window
+as arguments.
+@enddefun
+
+@defun[fun {modeline-field-width}, args {@i[modeline-field]}]
+Returns the width to which @i[modeline-field] is constrained, or @nil
+indicating that it is variable width.  When this is set with @f[setf], the
+@f[setf] method updates all modeline-fields for all windows on all buffers that
+contain the given field, so the next trip through redisplay will reflect the
+change.  All the fields for any such modeline display must be updated, which is
+not the case when setting a modeline-field's function.
+@enddefun
+
+@defun[fun {buffer-modeline-fields}, args {@i[buffer]}]
+Returns a copy of the list of @i[buffer]'s modeline-field objects.  This list
+can be destructively modified without affecting display of @i[buffer]'s
+modeline, but modifying any particular field's components (for example, width
+or function) causes the changes to be reflected the next trip through redisplay
+in every modeline display that uses the modified modeline-field.  When this is
+set with @f[setf], @f[update-modeline-fields] is called for each window into
+@i[buffer].
+@enddefun
+
+@defun[fun {buffer-modeline-field-p}, args {@i[buffer] @i[field]}]
+If @i[field], a modeline-field or the name of one, is in buffer's list of
+modeline-field objects, it is returned; otherwise, this returns nil.
+@enddefun
+
+@defun[fun {update-modeline-fields}, args {@i[buffer] @i[window]}]
+This invokes each modeline-field object's function from @i[buffer]'s list,
+passing @i[buffer] and @i[window].  The results are collected regarding each
+modeline-field object's width as appropriate, and the window is marked so
+the next trip through redisplay will reflect the changes.  If window does not
+display modelines, then no computation occurs.
+@enddefun
+
+@defun[fun {update-modeline-field}, args {@i[buffer] @i[window] @i[field-or-name]}]
+This invokes the modeline-field object's function for @i[field-or-name], which
+is a modeline-field object or the name of one for @i[buffer].  This passes
+@i[buffer] and @i[window] to the update function.  The result is applied to the
+@i[window]'s modeline display using the modeline-field object's width, and the
+window is marked so the next trip through redisplay will reflect the changes.
+If the window does not display modelines, then no computation occurs.  If
+@i[field-or-name] is not found in @i[buffer]'s list of modeline-field objects,
+then this signals an error.  See @f[buffer-modeline-field-p] above.
+@enddefun
+
+
+
+@chapter(Altering and Searching Text)
+@label[doing-stuff]
+
+@section(Altering Text)
+@index(Altering text)
+@index(Inserting)
+@index(Deleting)
+A note on marks and text alteration: @kwd[temporary] marks are invalid
+after any change has been made to the text the mark points to; it is an
+error to use a temporary mark after such a change has been made.  If
+text is deleted which has permanent marks pointing into it then they
+are left pointing to the position where the text was.
+
+@defun[fun {insert-character}, args {@i[mark] @i[character]}]
+@defun1[fun {insert-string}, args {@i[mark] @i[string]}]
+@defun1[fun {insert-region}, args {@i[mark] @i[region]}]
+Inserts @i[character], @i[string] or @i[region] at @i[mark].
+@f[insert-character] signals an error if @i[character] is not
+@f[string-char-p].  If @i[string] or @i[region] is empty, and @i[mark] is in
+some buffer, then @hemlock leaves @f[buffer-modified] of @i[mark]'s buffer
+unaffected.
+@enddefun
+
+@defun[fun {ninsert-region}, args {@i[mark] @i[region]}]
+Like @f[insert-region], inserts the @i[region] at the @i[mark]'s position,
+destroying the source region.  This must be used with caution, since if anyone
+else can refer to the source region bad things will happen.  In particular, one
+should make sure the region is not linked into any existing buffer.  If
+@i[region] is empty, and @i[mark] is in some buffer, then @hemlock leaves
+@f[buffer-modified] of @i[mark]'s buffer unaffected.
+@enddefun
+
+@defun[fun {delete-characters}, args {@i[mark] @i[n]}]
+This deletes @i[n] characters after the @i[mark] (or -@i[n] before if @i[n] is
+negative).  If @i[n] characters after (or -@i[n] before) the @i[mark] do not
+exist, then this returns @nil; otherwise, it returns @true.  If @i[n] is zero,
+and @i[mark] is in some buffer, then @hemlock leaves @f[buffer-modified] of
+@i[mark]'s buffer unaffected.
+@enddefun
+
+@defun[fun {delete-region}, args {@i[region]}]
+This deletes @i[region].  This is faster than @f[delete-and-save-region]
+(below) because no lines are copied.  If @i[region] is empty and contained in
+some buffer's @f[buffer-region], then @hemlock leaves @f[buffer-modified] of
+the buffer unaffected.
+@enddefun
+
+@defun[fun {delete-and-save-region}, args {@i[region]}]
+This deletes @i[region] and returns a region containing the original
+@i[region]'s text.  If @i[region] is empty and contained in some buffer's
+@f[buffer-region], then @hemlock leaves @f[buffer-modified] of the buffer
+unaffected.  In this case, this returns a distinct empty region.
+@enddefun
+
+@defun[fun {filter-region}, args {@i[function] @i[region]}]
+Destructively modifies @i[region] by replacing the text
+of each line with the result of the application of @i[function] to a
+string containing that text.  @i[Function] must obey the following
+restrictions:
+@begin[enumerate]
+The argument may not be destructively modified.
+
+The return value may not contain newline characters.
+
+The return value may not be destructively modified after it is
+returned from @i[function].
+@end[enumerate]
+The strings are passed in order, and are always simple strings.
+
+Using this function, a region could be uppercased by doing:
+@lisp
+(filter-region #'string-upcase region)
+@endlisp
+@enddefun
+
+
+@section(Text Predicates)
+@defun[fun {start-line-p}, args {@i[mark]}]
+Returns @true if the @i(mark) points before the first character in a line,
+@nil otherwise.
+@enddefun
+
+@defun[fun {end-line-p}, args {@i[mark]}]
+Returns @true if the @i(mark) points after the last character in a line and
+before the newline, @nil otherwise.
+@enddefun
+
+@defun[fun {empty-line-p}, args {@i[mark]}]
+Return @true of the line which @i[mark] points to contains no characters.
+@enddefun
+
+@defun[fun {blank-line-p}, args {@i[line]}]
+Returns @true if @i[line] contains only characters with a
+@hid[Whitespace] attribute of 1.  See chapter @ref[character-attributes] for
+discussion of character attributes.
+@enddefun
+
+@defun[fun {blank-before-p}, args {@i[mark]}]
+@defun1[fun {blank-after-p}, args {@i[mark]}]
+These functions test if all the characters preceding or following
+@i[mark] on the line it is on have a @hid[Whitespace] attribute of @f[1].
+@enddefun
+
+@defun[fun {same-line-p}, args {@i[mark1] @i[mark2]}]
+Returns @true if @i(mark1) and @i(mark2) point to the same line, or @nil
+otherwise;  That is,
+@example[(same-line-p a b) <==> (eq (mark-line a) (mark-line b))]
+@enddefun
+
+@defun[fun {mark<}, funlabel {mark-LSS}, args {@i[mark1] @i[mark2]}]
+@defun1[fun {mark<=}, funlabel {mark-LEQ}, args {@i[mark1] @i[mark2]}]
+@defun1[fun {mark=}, funlabel {mark-EQL}, args {@i[mark1] @i[mark2]}]
+@defun1[fun {mark/=}, funlabel {mark-NEQ}, args {@i[mark1] @i[mark2]}]
+@defun1[fun {mark>=}, funlabel {mark-GEQ}, args {@i[mark1] @i[mark2]}]
+@defun1[fun {mark>}, funlabel {mark-GTR}, args {@i[mark1] @i[mark2]}]
+These predicates test the relative ordering of two marks in a piece of
+text, that is a mark is @f[mark>] another if it points to a position
+after it.  If the marks point into different, non-connected pieces of
+text, such as different buffers, then it is an error to test their
+ordering; for such marks @f[mark=] is always false and @f[mark/=] is
+always true.
+@enddefun
+
+@defun[fun {line<}, funlabel {line-LSS}, args {@i[line1] @i[line2]}]
+@defun1[fun {line<=}, funlabel {line-LEQ}, args {@i[line1] @i[line2]}]
+@defun1[fun {line>=}, funlabel {line-GEQ}, args {@i[line1] @i[line2]}]
+@defun1[fun {line>}, funlabel {line-GTR}, args {@i[line1] @i[line2]}]
+These predicates test the ordering of @i[line1] and @i[line2].  If the
+lines are in unconnected pieces of text it is an error to test their
+ordering.
+@enddefun
+
+@defun[fun {lines-related}, args {@i[line1] @i[line2]}]
+This function returns @true if @i[line1] and @i[line2] are in the same
+piece of text, or @nil otherwise.
+@enddefun
+
+@defun[fun {first-line-p}, args {@i[mark]}]
+@defun1[fun {last-line-p}, args {@i[mark]}]
+@f[first-line-p] returns @true if there is no line before the line
+@i[mark] is on, and @nil otherwise.  @i[Last-line-p] similarly tests
+tests whether there is no line after @i[mark].
+@enddefun
+
+
+@section(Kill Ring)
+@index(Kill ring)
+@label(kill-ring)
+
+@defvar[var {kill-ring}]
+This is a ring (see section @ref[rings]) of regions deleted from buffers.
+Some commands save affected regions on the kill ring before performing
+modifications.  You should consider making the command undoable (see section
+@ref[undo]), but this is a simple way of achieving a less satisfactory means
+for the user to recover.
+@enddefvar
+
+@defun[fun {kill-region}, args {@i[region] @i[current-type]}]
+This kills @i[region] saving it in @var[kill-ring].  @i[Current-type] is either
+@kwd[kill-forward] or @kwd[kill-backward].  When the @funref[last-command-type]
+is one of these, this adds @i[region] to the beginning or end, respectively, of
+the top of @var[kill-ring].  The result of calling this is undoable using the
+command @hid[Undo] (see the @i[Hemlock User's Manual]).  This sets
+@f[last-command-type] to @i[current-type], and it interacts with
+@f[kill-characters].
+@enddefun
+
+@defun[fun {kill-characters}, args {@i[mark] @i[count]}]
+@defhvar1[var {Character Deletion Threshold}, val {5}]
+@f[kill-characters] kills @i[count] characters after @i[mark] if @i[count] is
+positive, otherwise before @i[mark] if @i[count] is negative.  When @i[count]
+is greater than or equal to @hid[Character Deletion Threshold], the killed
+characters are saved on @var[kill-ring].  This may be called multiple times
+contiguously (that is, without @funref[last-command-type] being set) to
+accumulate an effective count for purposes of comparison with the threshold.
+
+This sets @f[last-command-type], and it interacts with @f[kill-region].  When
+this adds a new region to @var[kill-ring], it sets @f[last-command-type] to
+@kwd[kill-forward] (if @i[count] is positive) or @kwd[kill-backward] (if
+@i[count] is negative).  When @f[last-command-type] is @kwd[kill-forward] or
+@kwd[kill-backward], this adds the killed characters to the beginning (if
+@i[count] is negative) or the end (if @i[count] is positive) of the top of
+@var[kill-ring], and it sets @f[last-command-type] as if it added a new region
+to @var[kill-ring].  When the kill ring is unaffected, this sets
+@f[last-command-type] to @kwd[char-kill-forward] or @kwd[char-kill-backward]
+depending on whether @i[count] is positive or negative, respectively.
+
+This returns mark if it deletes characters.  If there are not @i[count]
+characters in the appropriate direction, this returns nil.
+@enddefun
+
+
+@section(Active Regions)
+@index(Active regions)
+@label(active-regions)
+
+Every buffer has a mark stack (page @pageref[mark-stack]) and a mark known as
+the point where most text altering nominally occurs.  Between the top of the
+mark stack, the @f[current-mark], and the @f[current-buffer]'s point, the
+@f[current-point], is what is known as the @f[current-region].  Certain
+commands signal errors when the user tries to operate on the @f[current-region]
+without its having been activated.  If the user turns off this feature, then
+the @f[current-region] is effectively always active.
+
+When writing a command that marks a region of text, the programmer should make
+sure to activate the region.  This typically occurs naturally from the
+primitives that you use to mark regions, but sometimes you must explicitly
+activate the region.  These commands should be written this way, so they do not
+require the user to separately mark an area and then activate it.  Commands
+that modify regions do not have to worry about deactivating the region since
+modifying a buffer automatically deactivates the region.  Commands that insert
+text often activate the region ephemerally; that is, the region is active for
+the immediately following command, allowing the user wants to delete the region
+inserted, fill it, or whatever.
+
+Once a marking command makes the region active, it remains active until:
+@begin[itemize]
+a command uses the region,
+
+a command modifies the buffer,
+
+a command changes the current window or buffer,
+
+a command signals an editor-error,
+
+or the user types @binding[C-g].
+@end[itemize]
+
+@defhvar[var "Active Regions Enabled", val {t}]
+When this variable is non-@nil, some primitives signal an editor-error if
+the region is not active.  This may be set to @nil for more traditional @emacs
+region semantics.
+@enddefhvar
+
+@defvar[var {ephemerally-active-command-types}]
+This is a list of command types (see section @ref[command-types]), and its
+initial value is the list of @kwd[ephemerally-active] and @kwd[unkill].  When
+the previous command's type is one of these, the @f[current-region] is active
+for the currently executing command only, regardless of whether it does
+something to deactivate the region.  However, the current command may activate
+the region for future commands.  @kwd[ephemerally-active] is a default command
+type that may be used to ephemerally activate the region, and @kwd[unkill] is
+the type used by two commands, @hid[Un-kill] and @hid[Rotate Kill Ring] (what
+users typically think of as @binding[C-y] and @binding[M-y]).
+@enddefvar
+
+@defun[fun {activate-region}]
+This makes the @f[current-region] active.
+@enddefun
+
+@defun[fun {deactivate-region}]
+After invoking this the @f[current-region] is no longer active.
+@enddefun
+
+@defun[fun {region-active-p}]
+Returns whether the @f[current-region] is active, including ephemerally.  This
+ignores @hid[Active Regions Enabled].
+@enddefun
+
+@defun[fun {check-region-active}]
+This signals an editor-error when active regions are enabled, and the
+@f[current-region] is not active.
+@enddefun
+
+@defun[fun {current-region},
+       args {@optional @i[error-if-not-active] @i[deactivate-region]}]
+This returns a region formed with @f[current-mark] and @f[current-point],
+optionally signaling an editor-error if the current region is not active.
+@i[Error-if-not-active] defaults to @true.  Each call returns a distinct region
+object.  Depending on @i[deactivate-region] (defaults to @true), fetching the
+current region deactivates it.  @hemlock primitives are free to modify text
+regardless of whether the region is active, so a command that checks for this
+can deactivate the region whenever it is convenient.
+@enddefun
+
+
+@section(Searching and Replacing)
+@index(Searching)
+@index(Replacing)
+
+Before using any of these functions to do a character search, look at character
+attributes (page @pageref[character-attributes]).  They provide a facility
+similar to the syntax table in real EMACS.  Syntax tables are a powerful,
+general, and efficient mechanism for assigning meanings to characters in
+various modes.
+
+@defcon[var {search-char-code-limit}]
+An exclusive upper limit for the char-code of characters given to the searching
+functions.  The result of searches for characters with a char-code greater than
+or equal to this limit is ill-defined, but it is @i[not] an error to do such
+searches.
+@enddefcon
+
+@defun[fun {new-search-pattern},
+args {@i[kind] @i[direction] @i[pattern] @optional @i[result-search-pattern]}] 
+
+Returns a @i[search-pattern] object which can be given to the @f[find-pattern]
+and @f[replace-pattern] functions.  A search-pattern is a specification of a
+particular sort of search to do.  @i[direction] is either @kwd[forward] or
+@kwd[backward], indicating the direction to search in.  @i[kind] specifies the
+kind of search pattern to make, and @i[pattern] is a thing which specifies what
+to search for.
+
+The interpretation of @i[pattern] depends on the @i[kind] of pattern being
+made.  Currently defined kinds of search pattern are:
+@begin(description)
+@kwd[string-insensitive]@\Does a case-insensitive string search,
+@i[pattern] being the string to search for.
+
+@kwd[string-sensitive]@\Does a case-sensitive string search for
+@i[pattern].
+
+@kwd[character]@\Finds an occurrence of the character @i[pattern].
+This is case sensitive.
+
+@kwd[not-character]@\Find a character which is not the character
+@i[pattern].
+
+@kwd[test]@\Finds a character which satisfies the function @i[pattern].
+This function may not be applied an any particular fashion, so it
+should depend only on what its argument is, and should have no
+side-effects.
+
+@kwd[test-not]@\Similar to as @kwd[test], except it finds a character that
+fails the test.
+
+@kwd[any]@\Finds a character that is in the string @i[pattern].
+
+@kwd[not-any]@\Finds a character that is not in the string @i[pattern].
+@end(description)
+
+@i[result-search-pattern], if supplied, is a search-pattern to
+destructively modify to produce the new pattern.  Where reasonable
+this should be supplied, since some kinds of search patterns may
+involve large data structures.
+@enddefun
+
+@defun[fun {search-pattern-p}, args {@i[search-pattern]}]
+Returns @true if @i[search-pattern] is a @f[search-pattern] object, otherwise
+@nil.
+@enddefun
+
+@defun[fun {get-search-pattern}, args {@i[string] @i[direction]}]
+@defvar1[var {last-search-pattern}]
+@defvar1[var {last-search-string}]
+@f[get-search-pattern] interfaces to a default search string and pattern that
+search and replacing commands can use.  These commands then share a default
+when prompting for what to search or replace, and save on consing a search
+pattern each time they execute.  This uses @hid[Default Search Kind] (see the
+@i[Hemlock User's Manual]) when updating the pattern object.  This returns the
+pattern, so you probably don't need to refer to @var[last-search-pattern], but
+@var[last-search-string] is useful when prompting.
+@enddefun
+
+@defun[fun {find-pattern}, args {@i[mark] @i[search-pattern]}]
+Find the next match of @i[search-pattern] starting at @i[mark].  If a
+match is found then @i[mark] is altered to point before the matched text
+and the number of characters matched is returned.  If no match is
+found then @nil is returned and @i[mark] is not modified.
+@enddefun
+
+@defun[fun {replace-pattern}, args
+        {@i[mark] @i[search-pattern] @i[replacement] @optional @i[n]}]
+Replace @i[n] matches of @i[search-pattern] with the string
+@i[replacement] starting at @i[mark].  If @i[n] is @nil (the default)
+then replace all matches.  A mark pointing before the last replacement
+done is returned.
+@enddefun
+
+
+
+@Chapter(The Current Environment)
+@label(current-environment)
+@index(Current environment)
+
+@section(Different Scopes)
+    In @hemlock the values of @i[variables] (page @pageref[variables]),
+@i[key-bindings] (page @pageref(key-bindings)) and
+@i[character-attributes] (page @pageref[character-attributes]) may
+depend on the @funref(current-buffer) and the modes
+active in it.  There are three possible scopes for
+@hemlock values:
+@begin(description)
+@i[buffer local]@\The value is present only if the buffer it is local
+to is the @f[current-buffer].
+
+@i[mode local]@\The value is present only when the mode it is local to
+is active in the @f[current-buffer].
+
+@i[global]@\The value is always present unless shadowed by a buffer or
+mode local value.
+@end(description)
+
+
+@section(Shadowing)
+    It is possible for there to be a conflict between different values
+for the same thing in different scopes.  For example, there be might a
+global binding for a given variable and also a local binding in the
+current buffer.  Whenever there is a conflict shadowing occurs,
+permitting only one of the values to be visible in the current
+environment.
+
+    The process of resolving such a conflict can be described as a
+search down a list of places where the value might be defined, returning
+the first value found.  The order for the search is as follows:
+@begin(enumerate)
+Local values in the current buffer.
+
+Mode local values in the minor modes of the current buffer, in order
+from the highest precedence mode to the lowest precedence mode.  The
+order of minor modes with equal precedences is undefined.
+
+Mode local values in the current buffer's major mode.
+
+Global values.
+@end(enumerate)
+
+
+
+@chapter(Hemlock Variables)
+@index (Hemlock variables)
+@label(variables)
+@hemlock implements a system of variables separate from normal Lisp variables
+for the following reasons:
+@begin(enumerate)
+@hemlock has different scoping rules which are useful in an editor.  @hemlock
+variables can be local to a @i(buffer) (page @pageref[buffers]) or a @i(mode)
+(page @pageref[modes]).
+
+@hemlock variables have @i(hooks) (page @pageref[hooks]), lists of functions
+called when someone sets the variable.  See @f[variable-value] for the
+arguments @hemlock passes to these hook functions.
+
+There is a database of variable names and documentation which makes it easier
+to find out what variables exist and what their values mean.
+@end(enumerate)
+
+
+@section(Variable Names)
+To the user, a variable name is a case insensitive string.  This
+string is referred to as the @i[string name] of the variable.  A
+string name is conventionally composed of words separated by spaces.
+
+In Lisp code a variable name is a symbol.  The name of this symbol is
+created by replacing any spaces in the string name with hyphens.  This
+symbol name is always interned in the @hemlock package and referring
+to a symbol with the same name in the wrong package is an error.
+
+@defvar[var {global-variable-names}]
+This variable holds a string-table of the names of all the global @hemlock
+variables.  The value of each entry is the symbol name of the variable.
+@enddefvar
+
+@defun[fun {current-variable-tables}]
+This function returns a list of variable tables currently established,
+globally, in the @f[current-buffer], and by the modes of the
+@f[current-buffer].  This list is suitable for use with
+@f[prompt-for-variable].
+@enddefun
+
+
+@section(Variable Functions)
+In the following descriptions @i[name] is the symbol name of the variable.
+
+@defun[fun {defhvar}, args {@i[string-name] @i[documentation]},
+	keys {[mode][buffer][hooks][value]}]
+ This function defines a @hemlock variable.  Functions that take a variable
+name signal an error when the variable is undefined.
+@begin(description)
+@i[string-name]@\The string name of the variable to define.
+
+@i[documentation]@\The documentation string for the variable.
+
+@multiple{
+@kwd[mode],
+@kwd[buffer]}@\
+ If @i[buffer] is supplied, the variable is local to that buffer.  If @i[mode]
+is supplied, it is local to that mode.  If neither is supplied, it is global.
+
+@kwd[value]@\
+ This is the initial value for the variable, which defaults to @nil.
+
+@kwd[hooks]@\
+ This is the initial list of functions to call when someone sets the variable's
+value.  These functions execute before @hemlock establishes the new value.  See
+@f[variable-value] for the arguments passed to the hook functions.
+@end(description)
+If a variable with the same name already exists in the same place, then
+@f[defhvar] sets its hooks and value from @i[hooks] and @i[value] if the user
+supplies these keywords.
+@enddefun
+
+@defun[fun {variable-value}, args {@i[name] @optional @i[kind] @i[where]}]
+This function returns the value of a @hemlock variable in some place.
+The following values for @i[kind] are defined:
+@begin[description]
+@kwd[current]@\
+ Return the value present in the current environment, taking into consideration
+any mode or buffer local variables.  This is the default.
+
+@kwd[global]@\
+ Return the global value.
+
+@kwd[mode]@\
+ Return the value in the mode named @i[where].
+
+@kwd[buffer]@\
+ Return the value in the buffer @i[where].
+@end[description]
+When set with @f[setf], @hemlock sets the value of the specified variable and
+invokes the functions in its hook list with @i[name], @i[kind], @i[where], and
+the new value.
+@enddefun
+
+@defun[fun {variable-documentation}, args
+	{@i[name] @optional @i[kind] @i[where]}] 
+@defun1[fun {variable-hooks}, args
+        {@i[name] @optional @i[kind] @i[where]}]
+@defun1[fun {variable-name}, args
+	{@i[name] @optional @i[kind] @i[where]}]
+These function return the documentation, hooks and string name of a
+@hemlock variable.  The @i[kind] and @i[where] arguments are the same
+as for @f[variable-value].  The documentation and hook list may be set
+using @f[setf].
+@enddefun
+
+@defun[fun {string-to-variable}, args {@i[string]}]
+This function converts a string into the corresponding variable symbol
+name.  @i[String] need not be the name of an actual @hemlock variable.
+@enddefun
+
+@defmac[fun {value}, args {@i[name]}] 
+@defmac1[fun {setv}, args {@i[name] @i[new-value]}]
+These macros get and set the current value of the @hemlock variable
+@i[name].  @i[Name] is not evaluated.  There is a @f[setf] form for
+@f[value].
+@enddefmac
+
+@Defmac[Fun {hlet}, Args {(@Mstar<(@i[var] @i[value])>) @Mstar<@i[form]>}]
+This macro is very similar to @f[let] in effect; within its scope each
+of the @hemlock variables @i[var] have the respective @i[value]s, but
+after the scope is exited by any means the binding is removed.  This
+does not cause any hooks to be invoked.  The value of the last
+@i[form] is returned.
+@enddefmac
+
+@defun[fun {hemlock-bound-p}, args {@i[name] @optional @i[kind] @i[where]}]
+Returns @true if @i[name] is defined as a @hemlock variable in the
+place specified by @i[kind] and @i[where], or @nil otherwise.
+@enddefun
+
+@defun[fun {delete-variable}, args {@i(name) @optional @i[kind] @i[where]}]
+@defhvar1[var {Delete Variable Hook}]
+@f[delete-variable] makes the @hemlock variable @i[name] no longer
+defined in the specified place.  @i[Kind] and @i[where] have the same
+meanings as they do for @f[variable-value], except that @kwd[current]
+is not available, and the default for @i[kind] is @kwd[global]
+
+An error will be signaled if no such variable exists.  The hook,
+@hid[Delete Variable Hook] is invoked with the same arguments before the
+variable is deleted.
+@enddefun
+
+
+@section(Hooks)
+@index(Hooks)
+@label[hooks]
+@hemlock actions such as setting variables, changing buffers, changing windows,
+turning modes on and off, etc., often have hooks associated with them.  A hook
+is a list of functions called before the system performs the action.  The
+manual describes the object specific hooks with the rest of the operations
+defined on these objects.
+
+Often hooks are stored in @hemlock variables, @hid[Delete Buffer Hook] and
+@hid[Set Window Hook] for example.  This leads to a minor point of confusion
+because these variables have hooks that the system executes when someone
+changes their values.  These hook functions @hemlock invokes when someone sets
+a variable are an example of a hook stored in an object instead of a @hemlock
+variable.  These are all hooks for editor activity, but @hemlock keeps them in
+different kinds of locations.  This is why some of the routines in this section
+have a special interpretation of the hook @i[place] argument.
+
+@defmac[fun {add-hook}, args {@i[place] @i[hook-fun]}]
+@defmac1[fun {remove-hook}, args {@i[place] @i[hook-fun]}]
+These macros add or remove a hook function in some @i[place].  If @i[hook-fun]
+already exists in @i[place], this call has no effect.  If @i[place] is a
+symbol, then it is a @hemlock variable; otherwise, it is a generalized variable
+or storage location.  Here are two examples:
+@Begin[ProgramExample]
+(add-hook delete-buffer-hook 'remove-buffer-from-menu)
+
+(add-hook (variable-hooks 'check-mail-interval)
+          'reschedule-mail-check)
+@End[ProgramExample]
+@enddefmac
+
+@defmac[fun {invoke-hook}, args {@i[place] @rest @i[args]}]
+This macro calls all the functions in @i[place].  If @i[place] is a symbol,
+then it is a @hemlock variable; otherwise, it is a generalized variable.
+@enddefun
+
+
+
+@chapter(Commands)
+@index (Commands)
+@label[commands]
+
+
+@section(Introduction)
+The way that the user tells @hemlock to do something is by invoking a
+@i(command).  Commands have three attributes:
+@begin(description)
+@i[name]@\A command's name provides a way to refer to it.  Command
+names are usually capitalized words separated by spaces, such as 
+@hid[Forward Word].
+
+@i[documentation]@\The documentation for a command is used by
+on-line help facilities.
+
+@i[function]@\A command is implemented by a Lisp function, which is callable
+from Lisp.
+@end(description)
+
+@defvar[var {command-names}]
+Holds a string-table (page @pageref[string-tables]) associating
+command names to command objects.  Whenever a new command is defined
+it is entered in this table.
+@enddefvar
+
+
+@subsection(Defining Commands)
+
+@defmac[fun {defcommand}, args 
+{@^@mgroup<@i[command-name] @MOR (@i[command-name] @i[function-name])> @i[lambda-list]
+@\@i[command-doc] @i[function-doc] @mstar<@i[form]>}]
+
+Defines a command named @i[name].  @f[defcommand] creates a function to
+implement the command from the @i[lambda-list] and @i[form]'s supplied.  The
+@i[lambda-list] must specify one required argument, see section
+@ref[invoking-commands-as-functions], which by convention is typically named
+@f[p].  If the caller does not specify @i[function-name], @f[defcommand]
+creates the command name by replacing all spaces with hyphens and appending
+"@f[-command]".  @i[Function-doc] becomes the documentation for the function
+and should primarily describe issues involved in calling the command as a
+function, such as what any additional arguments are.  @i[Command-doc] becomes
+the command documentation for the command.  @enddefmac
+
+@defun[fun {make-command}, args 
+	{@i[name] @i[documentation] @i[function]}] 
+Defines a new command named @i[name], with command documentation
+@I[documentation] and function @i[function].  The command in entered
+in the string-table @varref[command-names], with the command object as
+its value.  Normally command implementors will use the @f[defcommand]
+macro, but this permits access to the command definition mechanism at
+a lower level, which is occasionally useful.
+@enddefun
+
+@defun[fun {commandp}, args {@i[command]}]
+Returns @true if @i[command] is a @f[command] object, otherwise @nil.
+@enddefun
+
+@defun[fun {command-documentation}, args {@i[command]}]
+@defun1[fun {command-function}, args {@i[command]}]
+@defun1[fun {command-name}, args {@i[command]}]
+Returns the documentation, function, or name for @i[command].  These
+may be set with @f[setf].
+@enddefun
+
+
+@subsection(Command Documentation)
+@i[Command documentation] is a description of what the command does
+when it is invoked as an extended command or from a key.  Command
+documentation may be either a string or a function.  If the
+documentation is a string then the first line should briefly summarize
+the command, with remaining lines filling the details.  Example:
+@lisp
+(defcommand "Forward Character" (p)
+  "Move the point forward one character.
+   With prefix argument move that many characters, with negative
+   argument go backwards."
+  "Move the point of the current buffer forward p characters."
+   . . .)
+@endlisp
+
+Command documentation may also be a function of one argument.  The
+function is called with either @kwd[short] or @kwd[full], indicating
+that the function should return a short documentation string or do
+something to document the command fully.
+
+
+@section(The Command Interpreter)
+@index[Interpreter, command]
+@index[Invocation, command]
+@index[Command interpreter]
+
+The @i[command interpreter] is a function which reads key-events (see section
+@ref[key-events-intro]) from the keyboard and dispatches to different commands
+on the basis of what the user types.  When the command interpreter executes a
+command, we say it @i[invokes] the command.  The command interpreter also
+provides facilities for communication between commands contiguously running
+commands, such as a last command type register.  It also takes care of
+resetting communication mechanisms, clearing the echo area, displaying partial
+keys typed slowly by the user, etc.
+
+@defvar[var {invoke-hook}]
+This variable contains a function the command interpreter calls when it wants
+to invoke a command.  The function receives the command and the prefix argument
+as arguments.  The initial value is a function which simply funcalls the
+@f[command-function] of the command with the supplied prefix argument.  This is
+useful for implementing keyboard macros and similar things.
+@enddefhvar
+
+@defhvar[var "Command Abort Hook"]
+The command interpreter invokes the function in this variable whenever someone
+aborts a command (for example, if someone called @f[editor-error]).
+@enddefhvar
+
+When @hemlock initially starts the command interpreter is in control, but
+commands may read from the keyboard themselves and assign whatever
+interpretation they will to the key-events read.  Commands may call the command
+interpreter recursively using the function @funref[recursive-edit].
+
+
+@subsection(Editor Input)
+@label[key-events-intro]
+@index[key-events]
+
+The canonical representation of editor input is a key-event structure.  Users
+can bind commands to keys (see section @ref[key-bindings]), which are non-zero
+length sequences of key-events.  A key-event consists of an identifying token
+known as a @i[keysym] and a field of bits representing modifiers.  Users define
+keysyms, integers between 0 and 65535 inclusively, by supplying names that
+reflect the legends on their keyboard's keys.  Users define modifier names
+similarly, but the system chooses the bit and mask for recognizing the
+modifier.  You can use keysym and modifier names to textually specify
+key-events and Hemlock keys in a @f[#k] syntax.  The following are some
+examples:
+@begin[programexample]
+   #k"C-u"
+   #k"Control-u"
+   #k"c-m-z"
+   #k"control-x meta-d"
+   #k"a"
+   #k"A"
+   #k"Linefeed"
+@end[programexample]
+This is convenient for use within code and in init files containing
+@f[bind-key] calls.
+
+The @f[#k] syntax is delimited by double quotes, but the system parses the
+contents rather than reading it as a Common Lisp string.  Within the double
+quotes, spaces separate multiple key-events.  A single key-event optionally
+starts with modifier names terminated by hyphens.  Modifier names are
+alphabetic sequences of characters which the system uses case-insensitively.
+Following modifiers is a keysym name, which is case-insensitive if it consists
+of multiple characters, but if the name consists of only a single character,
+then it is case-sensitive.
+
+You can escape special characters @dash hyphen, double quote, open angle
+bracket, close angle bracket, and space @dash with a backslash, and you can
+specify a backslash by using two contiguously.  You can use angle brackets to
+enclose a keysym name with many special characters in it.  Between angle
+brackets appearing in a keysym name position, there are only two special
+characters, the closing angle bracket and backslash.
+
+For more information on key-events see section @ref[key-events].
+
+
+
+@subsection(Binding Commands to Keys)
+@label[Key-Bindings]
+@Index[Key Bindings]
+
+The command interpreter determines which command to invoke on the basis of
+@i[key bindings].  A key binding is an association between a command and a
+sequence of key-events (see section @ref[key-events-intro].  A sequence of
+key-events is called a @i[key] and is represented by a single key-event or a
+sequence (list or vector) of key-events.
+
+Since key bindings may be local to a mode or buffer, the current environment
+(page @pageref[current-environment]) determines the set of key bindings in
+effect at any given time.  When the command interpreter tries to find the
+binding for a key, it first checks if there is a local binding in the
+@w[@funref[current-buffer]], then if there is a binding in each of the minor
+modes and the major mode for the current buffer @w[(page @pageref[modes])], and
+finally checks to see if there is a global binding.  If no binding is found,
+then the command interpreter beeps or flashes the screen to indicate this.
+
+@defun[fun {bind-key}, args
+        {@i(name) @i(key) @optional @i[kind] @i[where]}]
+ This function associates command @i[name] and @i[key] in some environment.
+@i[Key] is either a key-event or a sequence of key-events.  There are three
+possible values of @i[kind]:
+@begin(description)
+@kwd[global]@\
+ The default, make a global key binding.
+
+@kwd[mode]@\
+ Make a mode specific key binding in the mode whose name is @i[where].
+
+@kwd[buffer]@\
+ Make a binding which is local to buffer @i[where].
+@end(description)
+
+This processes @i[key] for key translations before establishing the binding.
+See section @ref[key-trans].
+
+If the key is some prefix of a key binding which already exists in the
+specified place, then the new one will override the old one, effectively
+deleting it.
+
+@f[ext:do-alpha-key-events] is useful for setting up bindings in certain new
+modes.
+@enddefun
+
+@defun[fun {command-bindings}, args {@i[command]}]
+This function returns a list of the places where @i[command] is bound.  A place
+is specified as a list of the key (always a vector), the kind of binding, and
+where (either the mode or buffer to which the binding is local, or @nil if it
+is a global).
+@enddefun
+
+@defun[fun {delete-key-binding}, args {@i[key] @optional @i[kind] @i[where]}]
+This function removes the binding of @i[key] in some place.  @i[Key] is either
+a key-event or a sequence of key-events.  @i[kind] is the kind of binding to
+delete, one of @kwd[global] (the default), @kwd[mode] or @kwd[buffer].  If
+@i[kind] is @kwd[mode], @i[where] is the mode name, and if @i[kind] is
+@kwd[buffer], then @i[where] is the buffer.
+
+This function signals an error if @i[key] is unbound.
+
+This processes @i[key] for key translations before deleting the binding.  See
+section @ref[key-trans].
+@enddefun
+
+@defun[fun {get-command}, args {@i[key] @optional @i[kind] @i[where]}]
+This function returns the command bound to @i[key], returning @nil if it is
+unbound.  @i[Key] is either a key-event or a sequence of key-events.  If
+@i[key] is an initial subsequence of some keys, then this returns the keyword
+@kwd[prefix].  There are four cases of @i[kind]:
+@begin(description)
+@kwd[current]@\
+ Return the current binding of @i[key] using the current buffer's search list.
+If there are any transparent key bindings for @i[key], then they are returned
+in a list as a second value.
+
+@kwd[global]@\
+ Return the global binding of @i[key].  This is the default.
+
+@kwd[mode]@\
+ Return the binding of @i[key] in the mode named @i[where].
+
+@kwd[buffer]@\
+ Return the binding of @i[key] local to the buffer @i[where].
+@end(description)
+
+This processes @i[key] for key translations before looking for any binding.
+See section @ref[key-trans].
+@enddefun
+
+@defun[fun {map-bindings}, Args {@i[function] @i[kind] @optional @i[where]}]
+This function maps over the key bindings in some place.  For each binding, this
+passes @i[function] the key and the command bound to it.  @i[Kind] and
+@i[where] are the same as in @f[bind-key].  The key is not guaranteed to remain
+valid after a given iteration.
+@enddefmac
+
+
+@subsection[Key Translation]
+@index[bit-prefix keys]
+@index[key translation]
+@index[translating keys]
+@label[key-trans]
+Key translation is a process that the command interpreter applies to keys
+before doing anything else.  There are two kinds of key translations:
+substitution and bit-prefix.  In either case, the command interpreter
+translates a key when a specified key-event sequence appears in a key.
+
+In a substitution translation, the system replaces the matched subsequence with
+another key-event sequence.  Key translation is not recursively applied to the
+substituted key-events.
+
+In a bit-prefix translation, the system removes the matched subsequence and
+effectively sets the specified bits in the next key-event in the key.
+
+While translating a key, if the system encounters an incomplete final
+subsequence of key-events, it aborts the translation process.  This happens
+when those last key-events form a prefix of some translation.  It also happens
+when they translate to a bit-prefix, but there is no following key-event to
+which the system can apply the indicated modifier.  If there is a binding for
+this partially untranslated key, then the command interpreter will invoke that
+command; otherwise, it will wait for the user to type more key-events.
+
+@defun[fun {key-translation}, args {@i[key]}]
+This form is @f[setf]'able and allows users to register key translations that
+the command interpreter will use as users type key-events.
+
+This function returns the key translation for @i[key], returning @nil if there
+is none.  @i[Key] is either a key-event or a sequence of key-events.  If
+@i[key] is a prefix of a translation, then this returns @kwd[prefix].
+
+A key translation is either a key or modifier specification.  The bits
+translations have a list form: @w<@f[(:bits {]@i[bit-name]@f[}*)]>.
+
+Whenever @i[key] appears as a subsequence of a key argument to the binding
+manipulation functions, that portion will be replaced with the translation.
+@enddefun
+
+
+
+@subsection[Transparent Key Bindings]
+@label[transparent-key-bindings]
+@index[Transparent key bindings]
+
+Key bindings local to a mode may be @i[transparent].  A transparent key
+binding does not shadow less local key bindings, but rather indicates that
+the bound command should be invoked before the first normal key binding.
+Transparent key bindings are primarily useful for implementing minor modes
+such as auto fill and word abbreviation.  There may be several transparent
+key bindings for a given key, in which case all of the commands bound are
+invoked in the order they were found.  If there no normal key binding for a
+key typed, then the command interpreter acts as though the key is unbound
+even if there are transparent key bindings.
+
+The @kwd[transparent-p] argument to @funref[defmode] determines whether the
+key bindings in a mode are transparent or not.
+
+
+@subsection (Interactive)
+@index (Keyboard macro vs. interactive)
+@index (Interactive vs. keyboard macro)
+@Hemlock supports keyboard macros.  A user may enter a mode where the editor
+records his actions, and when the user exits this mode, the command @hid[Last
+Keyboard Macro] plays back the actions.  Some commands behave differently when
+invoked as part of the definition of a keyboard macro.  For example, when used
+in a keyboard macro, a command that @f[message]'s useless user confirmation
+will slow down the repeated invocations of @hid[Last Keyboard Macro] because
+the command will pause on each execution to make sure the user sees the
+message.  This can be eliminated with the use of @f[interactive].  As another
+example, some commands conditionally signal an editor-error versus simply
+beeping the device depending on whether it executes on behalf of the user or a
+keyboard macro.
+
+@defun[fun {interactive}]
+This returns @true when the user invoked the command directly.
+@enddefun
+
+
+@section(Command Types)
+@index(Command types)
+@label(command-types)
+In many editors the behavior of a command depends on the kind of command
+invoked before it.  @hemlock provides a mechanism to support this known as
+@i(command type).
+
+@defun[fun {last-command-type}]
+This returns the command type of the last command invoked.  If this is set with
+@f[setf], the supplied value becomes the value of @f[last-command-type] until
+the next command completes.  If the previous command did not set
+@f[last-command-type], then its value is @nil.  Normally a command type is a
+keyword.  The command type is not cleared after a command is invoked due to a
+transparent key binding.
+@enddefun
+
+
+@section(Command Arguments)
+@label[invoking-commands-as-functions]
+There are three ways in which a command may be invoked: It may be bound to a
+key which has been typed, it may be invoked as an extended command, or it may
+be called as a Lisp function.  Ideally commands should be written in such a way
+that they will behave sensibly no matter which way they are invoked.  The
+functions which implement commands must obey certain conventions about argument
+passing if the command is to function properly.
+
+
+@subsection(The Prefix Argument)
+@index(Prefix arguments)
+Whenever a command is invoked it is passed as its first argument what
+is known as the @i[prefix argument].  The prefix argument is always
+either an integer or @nil.  When a command uses this value it is
+usually as a repeat count, or some conceptually similar function.
+
+@defun[fun {prefix-argument}]
+This function returns the current value of the prefix argument.  When
+set with @f[setf], the new value becomes the prefix argument for the
+next command.
+@enddefun
+
+If the prefix argument is not set by the previous command then the
+prefix argument for a command is @nil.  The prefix argument is not cleared
+after a command is invoked due to a transparent key binding.
+
+
+@subsection(Lisp Arguments)
+It is often desirable to call commands from Lisp code, in which case
+arguments which would otherwise be prompted for are passed as optional
+arguments following the prefix argument.  A command should prompt for
+any arguments not supplied.
+
+
+@section(Recursive Edits)
+@index(Recursive edits)
+@defmac[fun {use-buffer}, args {@i[buffer] @mstar<@i[form]>}]
+The effect of this is similar to setting the current-buffer to @i[buffer]
+during the evaluation of @i[forms].  There are restrictions placed on what the
+code can expect about its environment.  In particular, the value of any global
+binding of a @hemlock variable which is also a mode local variable of some mode
+is ill-defined; if the variable has a global binding it will be bound, but the
+value may not be the global value.  It is also impossible to nest
+@f[use-buffer]'s in different buffers.  The reason for using @f[use-buffer] is
+that it may be significantly faster than changing @f[current-buffer] to
+@i[buffer] and back.
+@enddefmac
+
+@defun[fun {recursive-edit}, args {@optional @i[handle-abort]}]
+@defhvar1[var {Enter Recursive Edit Hook}]
+@index[aborting]
+@f[recursive-edit] invokes the command interpreter.  The command interpreter
+will read from the keyboard and invoke commands until it is terminated with
+either @f[exit-recursive-edit] or @f[abort-recursive-edit].
+
+Normally, an editor-error or @bf[C-g] aborts the command in progress and
+returns control to the top-level command loop.  If @f[recursive-edit] is used
+with @i[handle-abort] true, then @f[editor-error] or @bf[C-g] will only abort
+back to the recursive command loop.
+
+Before the command interpreter is entered the hook
+@hid[Enter Recursive Edit Hook] is invoked.
+@enddefun
+
+@defun[fun {in-recursive-edit}]
+This returns whether the calling point is dynamically within a recursive edit
+context.
+@enddefun
+
+@defun[fun {exit-recursive-edit}, args {@optional @i[values-list]}]
+@defhvar1[var {Exit Recursive Edit Hook}]
+@f[exit-recursive-edit] exits a recursive edit returning as multiple values
+each element of @i[values-list], which defaults to @nil.  This invokes
+@hid[Exit Recursive Edit Hook] after exiting the command interpreter.  If no
+recursive edit is in progress, then this signals an error.
+@enddefun
+
+@defun[fun {abort-recursive-edit}, args {@rest @i[args]}]
+@defhvar1[var {Abort Recursive Edit Hook}]
+@f[abort-recursive-edit] terminates a recursive edit by applying
+@funref[editor-error] to @i[args] after exiting the command interpreter.  This
+invokes @hid[Abort Recursive Edit Hook] with @i[args] before aborting the
+recursive edit .  If no recursive edit is in progress, then this signals an
+error.
+@enddefun
+
+
+
+@Chapter(Modes)
+@label[modes]
+@index (Modes)
+A mode is a collection of @hemlock values which may be present in the current
+environment @w<(page @pageref(current-environment))> depending on the editing
+task at hand.  Examples of typical modes are @hid[Lisp], for editing Lisp code,
+and @hid[Echo Area], for prompting in the echo area.
+
+
+@section(Mode Hooks)
+  When a mode is added to or removed from a buffer, its @i[mode hook]
+is invoked.  The hook functions take two arguments, the buffer
+involved and @true if the mode is being added or @nil if it is being
+removed. 
+
+Mode hooks are typically used to make a mode do something additional to
+what it usually does.  One might, for example, make a text mode hook
+that turned on auto-fill mode when you entered.
+
+
+@section(Major and Minor Modes)
+There are two kinds of modes, @i[major] modes and @i[minor] modes.  A buffer
+always has exactly one major mode, but it may have any number of minor modes.
+Major modes may have mode character attributes while minor modes may not.
+
+A major mode is usually used to change the environment in some major way, such
+as to install special commands for editing some language.  Minor modes
+generally change some small attribute of the environment, such as whether lines
+are automatically broken when they get too long.  A minor mode should work
+regardless of what major mode and minor modes are in effect.
+
+@defhvar[var {Default Modes}, val {("Fundamental" "Save")}]
+This variable contains a list of mode names which are instantiated in a
+buffer when no other information is available.
+@enddefhvar
+
+@defvar[var {mode-names}]
+Holds a string-table of the names of all the modes.
+@enddefvar
+
+@defcom[com "Illegal"]
+This is a useful command to bind in modes that wish to shadow global bindings
+by making them effectively illegal.  Also, although less likely, minor modes
+may shadow major mode bindings with this.  This command calls @f[editor-error].
+@enddefcom
+
+
+@section(Mode Functions)
+
+@defun[fun {defmode}, args {@i[name]},
+        keys {[setup-function][cleanup-function][major-p]},
+        morekeys {[precedence][transparent-p][documentation]}]
+This function defines a new mode named @i[name], and enters it in
+@varref[mode-names].  If @i[major-p] is supplied and is not @nil
+then the mode is a major mode; otherwise it is a minor mode.
+
+@i[Setup-function] and @i[cleanup-function] are functions which are
+invoked with the buffer affected, after the mode is turned on, and
+before it is turned off, respectively.  These functions typically are
+used to make buffer-local key or variable bindings and to remove them
+when the mode is turned off.
+
+@i[Precedence] is only meaningful for a minor mode.  The precedence of a
+minor mode determines the order in which it in a buffer's list of modes.
+When searching for values in the current environment, minor modes are
+searched in order, so the precedence of a minor mode determines which value
+is found when there are several definitions.
+
+@i[Transparent-p] determines whether key bindings local to the defined mode
+are transparent.  Transparent key bindings are invoked in addition to the
+first normal key binding found rather than shadowing less local key bindings.
+
+@i[Documentation] is some introductory text about the mode.  Commands such as
+@hid[Describe Mode] use this.
+@enddefun
+
+@defun[fun {mode-documentation}, args {@i[name]}]
+This function returns the documentation for the mode named @i[name].
+@enddefun
+
+@defun[fun {buffer-major-mode}, args {@i[buffer]}]
+@defhvar1[var {Buffer Major Mode Hook}]
+@f[buffer-major-mode] returns the name of @i[buffer]'s major mode.
+The major mode may be changed with @f[setf]; then
+ @hid[Buffer Major Mode Hook] is invoked with
+@i[buffer] and the new mode.
+@enddefun
+
+@defun[fun {buffer-minor-mode}, args {@i[buffer] @i[name]}]
+@defhvar1[var {Buffer Minor Mode Hook}]
+@f[buffer-minor-mode] returns @true if the minor mode @i[name] is active
+in @i[buffer], @nil otherwise.  A minor mode may be turned on or off
+by using @f[setf]; then @hid[Buffer Minor Mode Hook] is
+invoked with @i[buffer], @i[name] and the new value.
+@enddefun
+
+@defun[fun {mode-variables}, args {@i[name]}]
+Returns the string-table of mode local variables.
+@enddefun
+
+@defun[fun {mode-major-p}, args {@i[name]}]
+Returns @true if @i[name] is the name of a major mode, or @nil if
+it is the name of a minor mode.  It is an error for @i[name] not to be
+the name of a mode.
+@enddefun
+
+
+
+@chapter(Character Attributes)
+@label(character-attributes)
+@index(Character attributes)
+@index(Syntax tables)
+
+@section(Introduction)
+Character attributes provide a global database of information about characters.
+This facility is similar to, but more general than, the @i[syntax tables] of
+other editors such as @f[EMACS].  For example, you should use character
+attributes for commands that need information regarding whether a character is
+@i[whitespace] or not.  Use character attributes for these reasons:
+@begin(enumerate)
+If this information is all in one place, then it is easy the change the
+behavior of the editor by changing the syntax table, much easier than it would
+be if character constants were wired into commands.
+
+This centralization of information avoids needless duplication of effort.
+
+The syntax table primitives are probably faster than anything that can be
+written above the primitive level.
+@end(enumerate)
+
+Note that an essential part of the character attribute scheme is that
+@i[character attributes are global and are there for the user to change.]
+Information about characters which is internal to some set of commands (and
+which the user should not know about) should not be maintained as a character
+attribute.  For such uses various character searching abilities are provided by
+the function @funref[find-pattern].
+
+@defcon[var {syntax-char-code-limit}]
+The exclusive upper bound on character codes which are significant in
+the character attribute functions.  Font and bits are always ignored.
+@enddefcon
+
+
+@section(Character Attribute Names)
+
+As for @hemlock variables, character attributes have a user visible
+string name, but are referred to in Lisp code as a symbol.  The string
+name, which is typically composed of capitalized words separated by
+spaces, is translated into a keyword by replacing all spaces with
+hyphens and interning this string in the keyword package.  The
+attribute named @hid[Ada Syntax] would thus become @kwd[ada-syntax].
+
+@defvar[var {character-attribute-names}]
+Whenever a character attribute is defined, its name is entered in
+this string table (page @pageref[string-tables]), with the
+corresponding keyword as the value.
+@enddefvar
+
+
+@section(Character Attribute Functions)
+
+@defun[fun {defattribute}, args 
+	{@i[name] @i[documentation] @optional @i[type] @i[initial-value]}]
+ This function defines a new character attribute with @i[name], a
+simple-string.  Character attribute operations take attribute arguments as a
+keyword whose name is @i[name] uppercased with spaces replaced by hyphens.
+
+@i[Documentation] describes the uses of the character attribute.
+
+@i[Type], which defaults to @w<@f[(mod 2)]>, specifies what type the values of
+the character attribute are.  Values of a character attribute may be of any
+type which may be specified to @f[make-array].  @i[Initial-value] (default
+@f[0]) is the value which all characters will initially have for this
+attribute.
+@enddefun
+
+@defun[fun {character-attribute-name}, args {@i[attribute]}]
+@defun1[fun {character-attribute-documentation}, args {@i[attribute]}]
+These functions return the name or documentation for @i[attribute].
+@enddefun
+
+@defun[fun {character-attribute}, args	{@i[attribute] @i[character]}]
+@defhvar1[var {Character Attribute Hook}]
+@f[character-attribute] returns the value of @i[attribute] for @i[character].
+This signals an error if @i[attribute] is undefined.
+
+@f[setf] will set a character's attributes.  This @f[setf] method invokes the
+functions in @hid[Character Attribute Hook] on the attribute and character
+before it makes the change.
+
+If @i[character] is @nil, then the value of the attribute for the beginning or
+end of the buffer can be accessed or set.  The buffer beginning and end thus
+become a sort of fictitious character, which simplifies the use of character
+attributes in many cases.
+@enddefun
+
+@defun[fun {character-attribute-p}, args {@i[symbol]}]
+This function returns @true if @i[symbol] is the name of a character attribute,
+@nil otherwise.
+@enddefun
+
+@defun[fun {shadow-attribute}, args 
+{@i[attribute] @i[character] @i[value] @i[mode]}]
+@defhvar1[var {Shadow Attribute Hook}]
+This function establishes @i[value] as the value of @i[character]'s
+@i[attribute] attribute when in the mode @i[mode].  @i[Mode] must be the name
+of a major mode.  @hid[Shadow Attribute Hook] is invoked with the same
+arguments when this function is called.  If the value for an attribute is set
+while the value is shadowed, then only the shadowed value is affected, not the
+global one.
+@enddefun
+
+@defun[fun {unshadow-attribute}, args {@i[attribute] @i[character] @i[mode]}]
+@defhvar1[var {Unshadow Attribute Hook}]
+Make the value of @i[attribute] for @i[character] no longer be shadowed in
+@i[mode].  @hid[Unshadow Attribute Hook] is invoked with the same arguments
+when this function is called.
+@enddefun
+
+@defun[fun {find-attribute},
+	args {@i[mark] @i[attribute] @optional @i[test]}]
+@defun1[fun {reverse-find-attribute},
+	args {@i[mark] @i[attribute] @optional @i[test]}]
+ These functions find the next (or previous) character with some value for the
+character attribute @i[attribute] starting at @i[mark].  They pass @i[Test] one
+argument, the value of @i[attribute] for the character tested.  If the test
+succeeds, then these routines modify @i[mark] to point before (after for
+@f[reverse-find-attribute]) the character which satisfied the test.  If no
+characters satisfy the test, then these return @nil, and @i[mark] remains
+unmodified.  @i[Test] defaults to @f[not zerop].  There is no guarantee that
+the test is applied in any particular fashion, so it should have no side
+effects and depend only on its argument.
+@enddefun
+
+
+@section(Character Attribute Hooks)
+
+It is often useful to use the character attribute mechanism as an abstract
+interface to other information about characters which in fact is stored
+elsewhere.  For example, some implementation of @hemlock might decide to define
+a @hid[Print Representation] attribute which controls how a character is
+displayed on the screen.
+
+To make this easy to do, each attribute has a list of hook functions
+which are invoked with the attribute, character and new value whenever
+the current value changes for any reason.
+
+@defun[fun {character-attribute-hooks}, args {@i[attribute]}]
+Return the current hook list for @i[attribute].  This may be set with
+@f[setf].  The @f[add-hook] and @macref[remove-hook] macros should
+be used to manipulate these lists.
+@enddefun
+
+
+@section (System Defined Character Attributes)
+@label(sys-def-chars)
+These are predefined in @hemlock:
+@begin[description]
+@hid[Whitespace]@\
+A value of @f[1] indicates the character is whitespace.
+
+@hid[Word Delimiter]@\
+A value of @f[1] indicates the character separates words (see section
+@ref[text-functions]).
+
+@hid[Digit]@\
+A value of @f[1] indicates the character is a base ten digit.  This may be
+shadowed in modes or buffers to mean something else.
+
+@hid[Space]@\
+This is like @hid[Whitespace], but it should not include @binding[Newline].
+@hemlock uses this primarily for handling indentation on a line.
+
+@hid[Sentence Terminator]@\
+A value of @f[1] indicates these characters terminate sentences (see section
+@ref[text-functions]).
+
+@hid[Sentence Closing Char]@\
+A value of @f[1] indicates these delimiting characters, such as @binding["]
+or @binding[)], may follow a @hid[Sentence Terminator] (see section
+@ref[text-functions]).
+
+@hid[Paragraph Delimiter]@\
+A value of @f[1] indicates these characters delimit paragraphs when they begin
+a line (see section @ref[text-functions]).
+
+@hid[Page Delimiter]@\
+A value of @f[1] indicates this character separates logical pages (see section
+@ref[logical-pages]) when it begins a line.
+
+@hid[Scribe Syntax]@\
+This uses the following symbol values:
+@begin[multiple]
+@begin[description]
+@nil@\These characters have no interesting properties.
+
+@kwd[escape]@\This is @binding[@@] for the Scribe formatting language.
+
+@kwd[open-paren]@\These characters begin delimited text.
+
+@kwd[close-paren]@\These characters end delimited text.
+
+@kwd[space]@\These characters can terminate the name of a formatting command.
+
+@kwd[newline]@\These characters can terminate the name of a formatting command.
+@end[description]
+@end[multiple]
+
+
+@hid[Lisp Syntax]@\
+This uses symbol values from the following:
+@begin[multiple]
+@begin[description]
+@nil@\These characters have no interesting properties.
+
+@kwd[space]@\These characters act like whitespace and should not include
+@binding[Newline].
+
+@kwd[newline]@\This is the @binding[Newline] character.
+
+@kwd[open-paren]@\This is @binding[(] character.
+
+@kwd[close-paren]@\This is @binding[)] character.
+
+@kwd[prefix]@\This is a character that is a part of any form it precedes @dash
+for example, the single quote, @binding['].
+
+@kwd[string-quote]@\This is the character that quotes a string literal,
+@binding["].@comment["]
+
+@kwd[char-quote]@\This is the character that escapes a single character,
+@binding[\].
+
+@kwd[comment]@\This is the character that makes a comment with the rest of the
+line, @binding[;].
+
+@kwd[constituent]@\These characters are constitute symbol names.
+@end[description]
+@end[multiple]
+
+@end[description]
+
+
+
+@chapter (Controlling the Display)
+@section (Windows)
+@tag[windows]
+@index(Windows)
+@index(modelines)
+
+A window is a mechanism for displaying part of a buffer on some physical
+device.  A window is a way to view a buffer but is not synonymous with one; a
+buffer may be viewed in any number of windows.  A window may have a
+@i[modeline] which is a line of text displayed across the bottom of a window to
+indicate status information, typically related to the buffer displayed.
+
+
+@section (The Current Window)
+@index (Current window)
+@defun[fun {current-window}, args {}]
+@defhvar1[var {Set Window Hook}]
+@f[current-window] returns the window in which the cursor is currently
+displayed.  The cursor always tracks the buffer-point of the corresponding
+buffer.  If the point is moved to a position which would be off the screen the
+recentering process is invoked.  Recentering shifts the starting point of the
+window so that the point is once again displayed.  The current window may be
+changed with @f[setf].  Before the current window is changed, the hook @hid[Set
+Window Hook] is invoked with the new value.
+@enddefun
+
+@defvar[var {window-list}]
+Holds a list of all the window objects made with @funref[make-window].
+@enddefvar
+
+
+@section(Window Functions)
+
+@defun[fun {make-window}, args {@i[mark]},
+	keys {[modelinep][window][ask-user]},
+	morekeys {[x][y][width][height]},
+	morekeys {[proportion]}]
+@defhvar1[var {Default Window Width}]
+@defhvar1[var {Default Window Height}]
+@defhvar1[var {Make Window Hook}]
+
+@comment[NOTE, we purposefully do not document the font-family or device
+	 arguments since we don't officially support fonts or devices.]
+
+@f[make-window] returns a window displaying text starting at @i[mark], which
+must point into a buffer.  If it could not make a window on the device, it
+returns nil.  The default action is to make the new window a proportion of the
+@f[current-window]'s height to make room for the new window.
+
+@i[Modelinep] specifies whether the window should display buffer modelines.
+
+@i[Window] is a device dependent window to be used with the Hemlock window.
+The device may not support this argument.  @i[Window] becomes the parent window
+for a new group of windows that behave in a stack orientation as windows do on
+the terminal.
+
+If @i[ask-user] is non-@nil, @hemlock prompts the user for the missing
+dimensions (@i[x], @i[y], @i[width], and @i[height]) to make a new group of
+windows, as with the @i[window] argument.  The device may not support this
+argument.  Non-null values other than @f[t] may have device dependent meanings.
+@i[X] and @i[y] are in pixel units, but @i[width] and @i[height] are characters
+units.  @hid[Default Window Width] and @hid[Default Window Height] are the
+default values for the @i[width] and @i[height] arguments.
+
+@i[Proportion] determines what proportion of the @f[current-window]'s height
+the new window will use.  The @f[current-window] retains whatever space left
+after accommodating the new one.  The default is to split the window in half.
+
+This invokes @hid[Make Window Hook] with the new window.
+@enddefun
+
+@defun[fun {windowp}, args {@i[window]}]
+This function returns @true if @i[window] is a @f[window] object, otherwise
+@nil.
+@enddefun
+
+@defun[fun {delete-window}, args {@i[window]}]
+@defhvar1[var {Delete Window Hook}]
+@f[delete-window] makes @i[window] go away, first invoking @hid[Delete Window
+Hook] with @i[window].
+@enddefun
+
+@defun[fun {window-buffer}, args {@i[window]}]
+@defhvar1[var {Window Buffer Hook}]
+@f[window-buffer] returns the buffer from which the window displays
+text.  This may be changed with @f[setf], in which case the hook
+@hid[Window Buffer Hook] is invoked beforehand with the window and the
+new buffer.
+@enddefun
+
+@defun[fun {window-display-start}, args {@i[window]}]
+@defun1[fun {window-display-end}, args {@i[window]}] 
+@f[window-display-start] returns the mark that points before the first
+character displayed in @i[window].  Note that if @i[window] is the current
+window, then moving the start may not prove much, since recentering may move it
+back to approximately where it was originally.
+
+@f[window-display-end] is similar, but points after the last character
+displayed.  Moving the end is meaningless, since redisplay always moves it to
+after the last character.
+@enddefun
+
+@defun[fun {window-display-recentering}, args {@i[window]}]
+This function returns whether redisplay will ensure the buffer's point of
+@i[window]'s buffer is visible after redisplay.  This is @f[setf]'able, and
+changing @i[window]'s buffer sets this to @nil via @hid[Window Buffer Hook].
+@enddefun
+
+@defun[fun {window-point}, args {@i[window]}]
+This function returns as a mark the position in the buffer where the cursor is
+displayed.  This may be set with @f[setf].  If @i[window] is the current
+window, then setting the point will have little effect; it is forced to track
+the buffer point.  When the window is not current, the window point is the
+position that the buffer point will be moved to when the window becomes
+current.
+@enddefun
+
+@defun[fun {center-window}, args {@i[window] @i[mark]}]
+This function attempts to adjust window's display start so the that @i[mark] is
+vertically centered within the window.
+@enddefun
+
+@defun[fun {scroll-window}, args {@i[window] @i[n]}]
+This function scrolls the window down @i[n] display lines; if @i[n] is negative
+scroll up.  Leave the cursor at the same text position unless we scroll it off
+the screen, in which case the cursor is moved to the end of the window closest
+to its old position.
+@enddefun
+
+@defun[fun {displayed-p}, args {@i[mark] @i[window]}]
+Returns @true if either the character before or the character after @i[mark]
+is being displayed in @i[window], or @nil otherwise.  
+@enddefun
+
+@defun[fun {window-height}, args {@i[window]}]
+@defun1[fun {window-width}, args {@i[window]}]
+Height or width of the area of the window used for displaying the
+buffer, in character positions.  These values may be changed with
+@f[setf], but the setting attempt may fail, in which case nothing is done.
+@enddefun
+
+@defun[fun {next-window}, args {@i[window]}]
+@defun1[fun {previous-window}, args {@i[window]}]
+Return the next or previous window of @i[window].  The exact meaning of next
+and previous depends on the device displaying the window.  It should be
+possible to cycle through all the windows displayed on a device using either
+next or previous (implying that these functions wrap around.)
+@enddefun
+
+
+@section(Cursor Positions)
+@index(Cursor positions)
+A cursor position is an absolute position within a window's coordinate
+system.  The origin is in the upper-left-hand corner and the unit
+is character positions.
+
+@defun[fun {mark-to-cursorpos}, args {@i[mark] @i[window]}]
+Returns as multiple values the @f[X] and @f[Y] position on which
+@i[mark] is being displayed in @i[window], or @nil if it is not within the
+bounds displayed.
+@enddefun
+
+@defun[fun {cursorpos-to-mark}, args {@i[X] @i[Y] @i[window]}]
+Returns as a mark the text position which corresponds to the given
+(@i[X], @i[Y]) position within window, or @nil if that
+position does not correspond to any text within @i[window].
+@enddefun
+
+@defun[fun {last-key-event-cursorpos}]
+Interprets mouse input.  It returns as multiple values the (@i[X], @i[Y])
+position and the window where the pointing device was the last time some key
+event happened.  If the information is unavailable, this returns @nil.
+@enddefun
+
+@defun[fun {mark-column}, args {@i[mark]}]
+This function returns the @i[X] position at which @i[mark] would be displayed,
+supposing its line was displayed on an infinitely wide screen.  This takes into
+consideration strange characters such as tabs.
+@enddefun
+
+@defun[fun {move-to-column}, args {@i[mark] @i[column] @optional @i[line]}]
+This function is analogous to @funref[move-to-position], except that
+it moves @i[mark] to the position on @i[line] which corresponds to the
+specified @i[column].  @i[Line] defaults to the line that @i[mark] is
+currently on.  If the line would not reach to the specified column,
+then @nil is returned and @i[mark] is not modified.  Note that since a
+character may be displayed on more than one column on the screen,
+several different values of @i[column] may cause @i[mark] to be moved
+to the same position.
+@enddefun
+
+@defun[fun {show-mark}, args {@i[mark] @i[window] @i[time]}]
+This function highlights the position of @i[mark] within @i[window] for
+@i[time] seconds, possibly by moving the cursor there.  The wait may be aborted
+if there is pending input.  If @i[mark] is positioned outside the text
+displayed by @i[window], then this returns @nil, otherwise @true.
+@enddefun
+
+
+@section(Redisplay)
+Redisplay translates changes in the internal representation of text into
+changes on the screen.  Ideally this process finds the minimal transformation
+to make the screen correspond to the text in order to maximize the speed of
+redisplay.
+
+@defun[fun {redisplay}]
+@defhvar1[var "Redisplay Hook"]
+@f[redisplay] executes the redisplay process, and @hemlock typically invokes
+this whenever it looks for input.  The redisplay process frequently checks for
+input, and if it detects any, it aborts.  The return value is interpreted as
+follows:
+@begin[description]
+@false@\No update was needed.
+
+@true@\Update was needed, and completed successfully.
+
+@kwd[editor-input]@\Update is needed, but was aborted due to pending input.
+@end[description]
+
+This function invokes the functions in @hid[Redisplay Hook] on the current
+window after computing screen transformations but before executing them.  After
+invoking the hook, this recomputes the redisplay and then executes it on the
+current window.
+
+For the current window and any window with @f[window-display-recentering] set,
+@f[redisplay] ensures the buffer's point for the window's buffer is visible
+after redisplay.
+@enddefun
+
+@defun[fun {redisplay-all}]
+This causes all editor windows to be completely redisplayed.  For the current
+window and any window with @f[window-display-recentering] set, this ensures the
+buffer's point for the window's buffer is visible after redisplay.  The return
+values are the same as for redisplay, except that @false is never returned.
+@enddefun
+
+@defun[fun {editor-finish-output}, args {@i[window]}]
+This makes sure the editor is synchronized with respect to redisplay output to
+@i[window].  This may do nothing on some devices.
+@enddefun
+
+
+
+@chapter(Logical Key-Events)
+@label[logical-key-events]
+@index[Logical key-events]
+
+
+@section[Introduction]
+Some primitives such as @funref[prompt-for-key] and commands such as EMACS
+query replace read key-events directly from the keyboard instead of using the
+command interpreter.  To encourage consistency between these commands and to
+make them portable and easy to customize, there is a mechanism for defining
+@i[logical key-events].
+
+A logical key-event is a keyword which stands for some set of key-events.  The
+system globally interprets these key-events as indicators a particular action.
+For example, the @kwd[help] logical key-event represents the set of key-events
+that request help in a given @hemlock implementation.  This mapping is a
+many-to-many mapping, not one-to-one, so a given logical key-event may have
+multiple corresponding actual key-events.  Also, any key-event may represent
+different logical key-events.
+
+
+@section[Logical Key-Event Functions]
+
+@defvar[var {logical-key-event-names}]
+This variable holds a string-table mapping all logical key-event names to the
+keyword identifying the logical key-event.
+@enddefvar
+
+@defun[fun {define-logical-key-event}, args {@i[string-name] @i[documentation]}]
+ This function defines a new logical key-event with name @i[string-name], a
+simple-string.  Logical key-event operations take logical key-events arguments
+as a keyword whose name is @i[string-name] uppercased with spaces replaced by
+hyphens.
+
+@i[Documentation] describes the action indicated by the logical key-event.
+@enddefun
+
+@defun[fun {logical-key-event-key-events}, args {@i[keyword]}]
+This function returns the list of key-events representing the logical key-event
+@i[keyword].
+@enddefun
+
+@defun[fun {logical-key-event-name}, args {@i[keyword]}]
+@defun1[fun {logical-key-event-documentation}, args {@i[keyword]}]
+These functions return the string name and documentation given to
+@f[define-logical-key-event] for logical key-event @i[keyword].
+@enddefun
+
+@defun[fun {logical-key-event-p}, args {@i[key-event] @i[keyword]}]
+This function returns @f[t] if @i[key-event] is the logical key-event
+@i[keyword].  This is @f[setf]'able establishing or disestablishing key-events
+as particular logical key-events.  It is a error for @i[keyword] to be an
+undefined logical key-event.
+@enddefun
+
+
+@section[System Defined Logical Key-Events]
+There are many default logical key-events, some of which are used by functions
+documented in this manual.  If a command wants to read a single key-event
+command that fits one of these descriptions then the key-event read should be
+compared to the corresponding logical key-event instead of explicitly
+mentioning the particular key-event in the code.  In many cases you can use the
+@macref[command-case] macro.  It makes logical key-events easy to use and takes
+care of prompting and displaying help messages.
+
+@begin[description]
+@kwd[yes]@\
+ Indicates the prompter should take the action under consideration.
+
+@kwd[no]@\
+ Indicates the prompter should NOT take the action under consideration.
+
+@kwd[do-all]@\
+ Indicates the prompter should repeat the action under consideration as many
+times as possible.
+
+@kwd[do-once]@\
+ Indicates the prompter should execute the action under consideration once and
+then exit.
+
+@kwd[exit]@\
+ Indicates the prompter should terminate its activity in a normal fashion.
+
+@kwd[abort]@\
+ Indicates the prompter should terminate its activity without performing any
+closing actions of convenience, for example.
+
+@kwd[keep]@\
+ Indicates the prompter should preserve something.
+
+@kwd[help]@\
+ Indicates the prompter should display some help information.
+
+@kwd[confirm]@\
+ Indicates the prompter should take any input provided or use the default if
+the user entered nothing.
+
+@kwd[quote]@\
+ Indicates the prompter should take the following key-event as itself without
+any sort of command interpretation.
+
+@kwd[recursive-edit]@\
+ Indicates the prompter should enter a recursive edit in the current context.
+
+@kwd[cancel]@\
+ Indicates the prompter should cancel the effect of a previous key-event input.
+
+@kwd[forward-search]@\
+ Indicates the prompter should search forward in the current context.
+
+@kwd[backward-search]@\
+ Indicates the prompter should search backward in the current context.
+@end[description]
+
+@blankspace(1 line)
+Define a new logical key-event whenever:
+@begin[enumerate]
+The key-event concerned represents a general class of actions, and
+several commands may want to take a similar action of this type.
+
+The exact key-event a command implementor chooses may generate violent taste
+disputes among users, and then the users can trivially change the command in
+their init files.
+
+You are using @f[command-case] which prevents implementors from specifying
+non-standard characters for dispatching in otherwise possibly portable code, 
+and you can define and set the logical key-event in a site dependent file where
+you can mention implementation dependent characters.
+@end[enumerate]
+
+
+
+@chapter(The Echo Area)
+
+@hemlock provides a number of facilities for displaying information and
+prompting the user for it.  Most of these work through a small window displayed
+at the bottom of the screen.  This is called the echo area and is supported by
+a buffer and a window.  This buffer's modeline (see section @ref[modelines]) is
+referred to as the status line, which, unlike other buffers' modelines, is used
+to show general status about the editor, Lisp, or world.
+
+@defhvar[var {Default Status Line Fields}]
+This is the initial list of modeline-field objects stored in the echo area
+buffer.
+@enddefhvar
+
+@defhvar[var "Echo Area Height", val {3}]
+This variable determines the initial height in lines of the echo area window. 
+@enddefhvar
+
+
+@section(Echo Area Functions)
+It is considered poor taste to perform text operations on the echo area buffer
+to display messages; the @f[message] function should be used instead.  A
+command must use this function or set @funref[buffer-modified] for the
+@hid[Echo Area] buffer to @nil to cause @hemlock to leave text in the echo area
+after the command's execution.
+
+@defun[fun {clear-echo-area}]
+Clears the echo area.
+@enddefun
+
+@defun[fun {message}, args {@i[control-string] @rest @i[format-arguments]}]
+@defun1[fun {loud-message}, args {@i[control-string] @rest @i[format-arguments]}]
+@defhvar1[var {Message Pause}, val {0.5}]
+Displays a message in the echo area.  The message is always displayed on a
+fresh line.  @f[message] pauses for @hid[Message Pause] seconds before
+returning to assure that messages are not displayed too briefly to be seen.
+Because of this, @f[message] is the best way to display text in the echo area.
+
+@f[loud-message] is like @f[message], but it first clears the echo area and
+beeps.
+@enddefun
+
+@defvar[var {echo-area-window}]
+@defvar1[var {echo-area-buffer}]
+@f[echo-area-buffer] contains the buffer object for the echo area, which is
+named @hid[Echo Area].  This buffer is usually in @hid[Echo Area] mode.
+@f[echo-area-window] contains a window displaying @f[echo-area-buffer].  Its
+modeline is the status line, see the beginning of this chapter.
+@enddefvar
+
+@defvar[var {echo-area-stream}]
+@index (Echo area)
+This is a buffered @hemlock output stream
+(@pageref[make-hemlock-output-stream-fun]) which inserts text written to it at
+the point of the echo area buffer.  Since this stream is buffered a
+@f[force-output] must be done when output is complete to assure that it is
+displayed.
+@enddefvar
+
+
+@section(Prompting Functions)
+@index(Prompting functions)
+Most of the prompting functions accept the following keyword arguments:
+@begin(description)
+@kwd[must-exist] @\If @kwd[must-exist] has a non-@nil value then the
+user is prompted until a valid response is obtained.  If
+@kwd[must-exist] is @nil then return as a string whatever is input.
+The default is @true.
+
+@kwd[default] @\If null input is given when the user is prompted 
+then this value is returned.  If no default is given then
+some input must be given before anything interesting will happen.
+
+@kwd[default-string] @\If a @kwd[default] is given then this is a
+string to be printed to indicate what the default is.  The default is
+some representation of the value for @kwd[default], for example for a
+buffer it is the name of the buffer.
+
+@kwd[prompt] @\This is the prompt string to display.
+
+@kwd[help] @\@multiple{
+This is similar to @kwd[prompt], except that it is displayed when
+the help command is typed during input.  @comment{If there is some known number
+of options as in keyword parses, then they may be displayed, depending
+on the setting of @hvarref[Help Show Options].}
+
+This may also be a function.  When called with no arguments, it should either
+return a string which is the help text or perform some action to help the user,
+returning @Nil.}
+@end(description)
+
+@defun[fun {prompt-for-buffer}, keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}] 
+Prompts with completion for a buffer name and returns the corresponding buffer.
+If @i[must-exist] is @nil, then it returns the input string if it is not a
+buffer name.  This refuses to accept the empty string as input when
+@kwd[default] and @kwd[default-string] are @nil.  @kwd[default-string] may be
+used to supply a default buffer name when @kwd[default] is @nil, but when
+@kwd[must-exist] is non-@nil, it must name an already existing buffer.
+@enddefun
+
+@defmac[fun {command-case}, Args {(@mstar<@i[key] @i[value]>) @Mstar<(@Mgroup"(@MSTAR'@i[tag]') @MOR @i[tag]" @i[help] @MSTAR'@i[form]')>}] 
+ This macro is analogous to the Common Lisp @f[case] macro.  Commands such as
+@hid[Query Replace] use this to get a key-event, translate it to a character,
+and then to dispatch on the character to some case.  In addition to character
+dispatching, this supports logical key-events @w<(page
+@pageref[logical-key-events])> by using the input key-event directly without
+translating it to a character.  Since the description of this macro is rather
+complex, first consider the following example:
+@lisp
+(defcommand "Save All Buffers" (p)
+  "Give the User a chance to save each modified buffer."
+  "Give the User a chance to save each modified buffer."
+  (dolist (b *buffer-list*)
+    (select-buffer-command () b)
+    (when (buffer-modified b)
+      (command-case (:prompt "Save this buffer: [Y] "
+		     :help "Save buffer, or do something else:")
+	((:yes :confirm)
+	 "Save this buffer and go on to the next."
+	 (save-file-command () b))
+	(:no "Skip saving this buffer, and go on to the next.")
+	(:recursive-edit
+	 "Go into a recursive edit in this buffer."
+	 (do-recursive-edit) (reprompt))
+	((:exit #\p) "Punt this silly loop."
+	 (return nil))))))
+@endlisp
+
+@f[command-case] prompts for a key-event and then executes the code in the
+first branch with a logical key-event or a character (called @i[tags]) matching
+the input.  Each character must be a standard-character, one that satisfies the
+Common Lisp @f[standard-char-p] predicate, and the dispatching mechanism
+compares the input key-event to any character tags by mapping the key-event to
+a character with @f[ext:key-event-char].  If the tag is a logical key-event,
+then the search for an appropriate case compares the key-event read with the
+tag using @f[logical-key-event-p].
+
+All uses of @f[command-case] have two default cases, @kwd[help] and
+@kwd[abort].  You can override these easily by specifying your own branches
+that include these logical key-event tags.  The @kwd[help] branch displays in a
+pop-up window the a description of the valid responses using the variously
+specified help strings.  The @kwd[abort] branch signals an editor-error.
+
+The @i[key]/@i[value] arguments control the prompting.  The following are valid
+values:
+@begin[description]
+@kwd[help]@\
+ The default @kwd[help] case displays this string in a pop-up window.  In
+addition it formats a description of the valid input including each case's
+@i[help] string.
+
+@kwd[prompt]@\
+ This is the prompt used when reading the key-event.
+
+@kwd[change-window]@\
+ If this is non-nil (the default), then the echo area window becomes the
+current window while the prompting mechanism reads a key-event.  Sometimes it
+is desirable to maintain the current window since it may be easier for users to
+answer the question if they can see where the current point is.
+
+@kwd[bind]@\
+ This specifies a variable to which the prompting mechanism binds the input
+key-event.  Any case may reference this variable.  If you wish to know what
+character corresponds to the key-event, use @f[ext:key-event-char].
+@end(description)
+
+Instead of specifying a tag or list of tags, you may use @true.  This becomes
+the default branch, and its forms execute if no other branch is taken,
+including the default @kwd[help] and @kwd[abort] cases.  This option has no
+@i[help] string, and the default @kwd[help] case does not describe the default
+branch.  Every @f[command-case] has a default branch; if none is specified, the
+macro includes one that @f[system:beep]'s and @f[reprompt]'s (see below).
+
+Within the body of @f[command-case], there is a defined @f[reprompt] macro.
+It causes the prompting mechanism and dispatching mechanism to immediately
+repeat without further execution in the current branch.
+@enddefmac
+
+
+@defun[fun {prompt-for-key-event}, keys {[prompt][change-window]}]
+This function prompts for a key-event returning immediately when the user types
+the next key-event.  @macref[command-case] is more useful for most purposes.
+When appropriate, use logical key-events @w<(page
+@pageref[logical-key-events])>.
+@enddefun
+
+@defun[fun {prompt-for-key}, keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}]
+ This function prompts for a @i[key], a vector of key-events, suitable for
+passing to any of the functions that manipulate key bindings @w<(page
+@pageref[key-bindings])>.  If @i[must-exist] is true, then the key must be
+bound in the current environment, and the command currently bound is returned
+as the second value.
+@enddefun
+
+@defun[fun {prompt-for-file}, keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}]
+ This function prompts for an acceptable filename in some system dependent
+fashion.  "Acceptable" means that it is a legal filename, and it exists if
+@i[must-exist] is non-@nil.  @f[prompt-for-file] returns a Common Lisp
+pathname.
+
+If the file exists as entered, then this returns it, otherwise it is merged
+with @i[default] as by @f[merge-pathnames].
+@enddefun
+
+@defun[fun {prompt-for-integer}, keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}] 
+ This function prompts for a possibly signed integer.  If @i[must-exist] is
+@nil, then @f[prompt-for-integer] returns the input as a string if it is not a
+valid integer.
+@enddefun
+
+@defun[fun {prompt-for-keyword}, args {@i[string-tables]},
+	keys {[prompt][help][must-exist]},
+	morekeys {[default][default-string]}]
+ This function prompts for a keyword with completion, using the string tables
+in the list @i[string-tables].  If @I[must-exist] is non-@nil, then the result
+must be an unambiguous prefix of a string in one of the @i[string-tables], and
+the returns the complete string even if only a prefix of the full string was
+typed.  In addition, this returns the value of the corresponding entry in the
+string table as the second value.
+
+If @i[must-exist] is @nil, then this function returns the string exactly as
+entered.  The difference between @f[prompt-for-keyword] with @i[must-exist]
+@nil, and @f[prompt-for-string], is the user may complete the input using the
+@hid<Complete Parse> and @hid<Complete Field> commands.
+@enddefun
+
+@defun[fun {prompt-for-expression},
+	keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}]
+ This function reads a Lisp expression.  If @i[must-exist] is @nil, and a read
+error occurs, then this returns the string typed.
+@enddefun
+
+@defun[fun {prompt-for-string}, keys 
+{[prompt][help][default][default-string]}]
+ This function prompts for a string; this cannot fail.
+@enddefun
+
+@defun[fun {prompt-for-variable}, keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}]
+ This function prompts for a variable name.  If @i[must-exist] is non-@nil,
+then the string must be a variable @i[defined in the current environment], in
+which case the symbol name of the variable found is returned as the second
+value.
+@enddefun
+
+@defun[fun {prompt-for-y-or-n}, keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}]
+ This prompts for @binding[y], @binding[Y], @binding[n], or @binding[N],
+returning @true or @nil without waiting for confirmation.  When the user types
+a confirmation key, this returns @i[default] if it is supplied.  If
+@i[must-exist] is @nil, this returns whatever key-event the user first types;
+however, if the user types one of the above key-events, this returns @true or
+@nil.  This is analogous to the Common Lisp function @f[y-or-n-p].
+@enddefun
+
+@defun[fun {prompt-for-yes-or-no}, keys {[prompt][help][must-exist][default]},
+	morekeys {[default-string]}]
+ This function is to @f[prompt-for-y-or-n] as @f[yes-or-no-p] is to
+@f[y-or-n-p].  "Yes" or "No" must be typed out in full and
+confirmation must be given.
+@enddefun
+
+
+@section(Control of Parsing Behavior)
+
+@defhvar[var {Beep On Ambiguity}, val {@true}]
+If this variable is true, then an attempt to complete a parse which is
+ambiguous will result in a "beep".
+@enddefhvar
+
+
+@begin(comment)
+@hemlock provides for limited control of parsing routine behaviour The
+character attribute @hid[Parse Field Separator] is a boolean attribute, a value
+of @f[1] indicating that the character is a field separator recognized by the
+@hid<Complete Field> command.
+@end(comment)
+
+@begin(comment)
+@defhvar[var {Help Show Options}]
+During a keyword or similar parse, typing the help command may cause a
+list of options to be displayed.  If displaying the help would take up
+more lines than the value of this variable then confirmation will be
+asked for before they will be displayed.
+@enddefhvar
+@end(comment)
+
+
+
+@section(Defining New Prompting Functions)
+Prompting functions are implemented as a recursive edit in the
+@hid[Echo Area] buffer.  Completion, help, and other parsing features
+are implemented by commands which are bound in @hid[Echo Area Mode].
+
+A prompting function passes information down into the recursive edit
+by binding a collection of special variables.
+
+@defvar[var {parse-verification-function}]
+The system binds this to a function that @comref[Confirm Parse] calls.  It does
+most of the work when parsing prompted input.  @comref[Confirm Parse] passes
+one argument, which is the string that was in @var<parse-input-region> when the
+user invokes the command.  The function should return a list of values which
+are to be the result of the recursive edit, or @nil indicating that the parse
+failed.  In order to return zero values, a non-@nil second value may be
+returned along with a @nil first value.
+@enddefvar
+
+@defvar[var {parse-string-tables}]
+This is the list of @f[string-table]s, if any, that pertain to this parse.
+@enddefvar
+
+@defvar[var {parse-value-must-exist}]
+This is bound to the value of the @kwd[must-exist] argument, and is
+referred to by the verification function, and possibly some of the
+commands.
+@enddefvar
+
+@defvar[var {parse-default}]
+When prompting the user, this is bound to a string representing the default
+object, the value supplied as the @kwd[default] argument.  @hid<Confirm Parse>
+supplies this to the parse verification function when the
+@var<parse-input-region> is empty.
+@enddefvar
+
+@defvar[var {parse-default-string}]
+When prompting the user, if @var[parse-default] is @nil, @hemlock displays this
+string as a representation of the default object; for example, when prompting
+for a buffer, this variable would be bound to the buffer name.
+@enddefvar
+
+@defvar[var {parse-type}]
+The kind of parse in progress, one of @kwd[file], @kwd[keyword] or
+@kwd[string].  This tells the completion commands how to do completion, with
+@kwd[string] disabling completion.
+@enddefvar
+
+@defvar[var {parse-prompt}]
+The prompt being used for the current parse.
+@enddefvar
+
+@defvar[var {parse-help}]
+The help string or function being used for the current parse.
+@enddefvar
+
+@defvar[var {parse-starting-mark}]
+This variable holds a mark in the @varref[echo-area-buffer] which
+is the position at which the parse began.
+@enddefvar
+
+@defvar[var {parse-input-region}]
+This variable holds a region with @var[parse-starting-mark] as its
+start and the end of the echo-area buffer as its end.  When
+@hid[Confirm Parse] is called, the text in this region is the text
+that will be parsed.
+@enddefvar
+
+
+@section(Some Echo Area Commands)
+
+These are some of the @hid[Echo Area] commands that coordinate with the
+prompting routines.  @Hemlock binds other commands specific to the @hid[Echo
+Area], but they are uninteresting to mention here, such as deleting to the
+beginning of the line or deleting backwards a word.
+
+@defcom[com {Help On Parse},
+	stuff (bound to @bf[Home, C-_] in @hid[Echo Area] mode)]
+Display the help text for the parse currently in progress.
+@enddefcom
+
+@defcom[com {Complete Keyword},
+	stuff (bound to @bf[Escape] in @hid[Echo Area] mode)] 
+This attempts to complete the current region as a keyword in
+@var[string-tables].  It signals an editor-error if the input is ambiguous
+or incorrect.
+@enddefcom
+
+@defcom[com {Complete Field},
+	stuff (bound to @bf[Space] in @hid[Echo Area] mode)]
+Similar to @hid[Complete Keyword], but only attempts to complete up to and
+including the first character in the keyword with a non-zero
+@kwd[parse-field-separator] attribute.  If
+there is no field separator then attempt to complete the entire keyword.
+If it is not a keyword parse then just self-insert.
+@enddefcom
+
+@defcom[com {Confirm Parse},
+	stuff (bound to @bf[Return] in @hid[Echo Area] mode)]
+If @var[string-tables] is non-@nil find the string in the region in
+them.  Call @var[parse-verification-function] with the current input.
+If it returns a non-@nil value then that is returned as the value of
+the parse.  A parse may return a @nil value if the verification
+function returns a non-@nil second value.
+@enddefcom
+
+
+
+@chapter (Files)
+@index (Files)
+This chapter discusses ways to read and write files at various levels @dash at
+marks, into regions, and into buffers.  This also treats automatic mechanisms
+that affect the state of buffers in which files are read.
+
+@section (File Options and Type Hooks)
+@index (File options)
+@index (Type hooks)
+@index (File type hooks)
+The user specifies file options with a special syntax on the first line of a
+file.  If the first line contains the string "@f[-*-]", then @hemlock
+interprets the text between the first such occurrence and the second, which
+must be contained in one line , as a list of @w{"@f<@i[option]: @i[value]>"}
+pairs separated by semicolons.  The following is a typical example:
+@begin[programexample]
+;;; -*- Mode: Lisp, Editor; Package: Hemlock -*-
+@end[programexample]
+See the @i[Hemlock User's Manual] for more details and predefined options.
+
+File type hooks are executed when @hemlock reads a file into a buffer based on
+the type of the pathname.  When the user specifies a @hid[Mode] file option
+that turns on a major mode, @hemlock ignores type hooks.  This mechanism is
+mostly used as a simple means for turning on some appropriate default major
+mode.
+
+@defmac[fun {define-file-option}, args
+{@i[name] (@i[buffer] @i[value]) @mstar<@i[declaration]> @mstar<@i[form]>}]
+This defines a new file option with the string name @i[name].  @i[Buffer] and
+@i[value] specify variable names for the buffer and the option value string,
+and @i[form]'s are evaluated with these bound.
+@enddefmac
+
+@defmac[fun {define-file-type-hook}, args 
+{@i[type-list] (@i[buffer] @i[type]) @mstar<@i[declaration]> @mstar<@i[form]>}]
+
+This defines some code that @f[process-file-options] (below) executes when the
+file options fail to set a major mode.  This associates each type, a
+@f[simple-string], in @i[type-list] with a routine that binds @i[buffer] to the
+buffer the file is in and @i[type] to the type of the pathname.
+@enddefmac
+
+@defun[fun {process-file-options}, args {@i[buffer] @optional @i[pathname]}]
+This checks for file options in buffer and invokes handlers if there are any.
+@i[Pathname] defaults to @i[buffer]'s pathname but may be @nil.  If there is no
+@hid[Mode] file option that specifies a major mode, and @i[pathname] has a
+type, then this tries to invoke the appropriate file type hook.
+@f[read-buffer-file] calls this.
+@enddefun
+
+
+@section (Pathnames and Buffers)
+There is no good way to uniquely identify buffer names and pathnames.  However,
+@hemlock has one way of mapping pathnames to buffer names that should be used
+for consistency among customizations and primitives.  Independent of this,
+@hemlock provides a means for consistently generating prompting defaults when
+asking the user for pathnames.
+
+@defun[fun {pathname-to-buffer-name}, args {@i[pathname]}]
+This function returns a string of the form "@f[file-namestring]
+@f[directory-namestring]".
+@enddefun
+
+@defhvar[var "Pathname Defaults", val {(pathname "gazonk.del")}]
+@defhvar1[var "Last Resort Pathname Defaults Function"]
+@defhvar1[var "Last Resort Pathname Defaults", val {(pathname "gazonk")}]
+These variables control the computation of default pathnames when needed for
+promting the user.  @hid[Pathname Defaults] is a @i[sticky] default.
+See the @i[Hemlock User's Manual] for more details.
+@enddefhvar
+
+@defun[fun {buffer-default-pathname}, args {@i[buffer]}]
+This returns @hid[Buffer Pathname] if it is bound.  If it is not bound, and
+@i[buffer]'s name is composed solely of alphnumeric characters, then return a
+pathname formed from @i[buffer]'s name.  If @i[buffer]'s name has other
+characters in it, then return the value of @hid[Last Resort Pathname Defaults
+Function] called on @i[buffer].
+@enddefun
+
+@section (File Groups)
+@index (File groups)
+File groups provide a simple way of collecting the files that compose a system
+and naming that collection.  @Hemlock supports commands for searching,
+replacing, and compiling groups.
+
+@defvar[var {active-file-group}]
+This is the list of files that constitute the currently selected file group.
+If this is @nil, then there is no current group.
+@enddefvar
+
+@defmac[fun {do-active-group}, args {@mstar<@i[form]>}]
+@defhvar1[var "Group Find File", val {nil}]
+@defhvar1[var "Group Save File Confirm", val {t}]
+@f[do-active-group] iterates over @var[active-file-group] executing the forms
+once for each file.  While the forms are executing, the file is in the current
+buffer, and the point is at the beginning.  If there is no active group, this
+signals an editor-error.
+
+This reads each file into its own buffer using @f[find-file-buffer].  Since
+unwanted buffers may consume large amounts of memory, @hid[Group Find File]
+controls whether to delete the buffer after executing the forms.  When the
+variable is false, this deletes the buffer if it did not previously exist;
+however, regardless of this variable, if the user leaves the buffer modified,
+the buffer persists after the forms have completed.  Whenever this processes a
+buffer that already existed, it saves the location of the buffer's point before
+and restores it afterwards.  
+
+After processing a buffer, if it is modified, @f[do-active-group] tries to save
+it.  If @hid[Group Save File Confirm] is non-@nil, it asks for confirmation.
+@enddefmac
+
+
+@section (File Reading and Writing)
+Common Lisp pathnames are used by the file primitives.  For probing, checking
+write dates, and so forth, all of the Common Lisp file functions are available.
+
+@defun[fun {read-file}, args {@i[pathname] @i[mark]}]
+This inserts the file named by @i[pathname] at @i[mark].
+@enddefun
+
+@defun[fun {write-file}, args {@i[region] @i[pathname]},
+	keys {[keep-backup][access][append]}]
+@defhvar1[var {Keep Backup Files}, val {@nil}]
+This function writes the contents of @i[region] to the file named by
+@i[pathname].  This writes @i[region] using a stream as if it were opened with
+@kwd[if-exists] supplied as @kwd[rename-and-delete].
+
+When @i[keep-backup], which defaults to the value of @hid[Keep Backup Files],
+is non-@nil, this opens the stream as if @kwd[if-exists] were @kwd[rename].  If
+@i[append] is non-@nil, this writes the file as if it were opened with
+@kwd[if-exists] supplied as @kwd[append].
+
+This signals an error if both @i[append] and @i[keep-backup] are supplied as
+non-@nil.
+
+@i[Access] is an implementation dependent value that is suitable for setting
+@i[pathname]'s access or protection bits.
+@enddefun
+
+
+@defun[fun {write-buffer-file}, args {@i[buffer] @i[pathname]}]
+@defhvar1[var {Write File Hook}]
+@defhvar1[var {Add Newline at EOF on Writing File}, val {@kwd[ask-user]}]
+@f[write-buffer-file] writes @i[buffer] to the file named by @i[pathname]
+including the following:
+@begin[itemize]
+It assumes pathname is somehow related to @i[buffer]'s pathname: if the
+@i[buffer]'s write date is not the same as @i[pathname]'s, then this prompts
+the user for confirmation before overwriting the file.
+
+It consults @hid[Add Newline at EOF on Writing File] (see @i[Hemlock User's
+Manual] for possible values) and interacts with the user if necessary.
+
+It sets @hid[Pathname Defaults], and after using @f[write-file], marks
+@i[buffer] unmodified.
+
+It updates @i[Buffer]'s pathname and write date.
+
+It renames the buffer according to the new pathname if possible.
+
+It invokes @hid[Write File Hook].
+@end[itemize]
+
+@hid[Write File Hook] is a list of functions that take the newly written buffer
+as an argument.
+@enddefun
+
+
+@defun[fun {read-buffer-file}, args {@i[pathname] @i[buffer]}]
+@defhvar1[var {Read File Hook}]
+@f[read-buffer-file] deletes @i[buffer]'s region and uses @f[read-file] to read
+@i[pathname] into it, including the following:
+@begin[itemize]
+It sets @i[buffer]'s write date to the file's write date if the file exists;
+otherwise, it @f[message]'s that this is a new file and sets @i[buffer]'s write
+date to @nil.
+
+It moves @i[buffer]'s point to the beginning.
+
+It sets @i[buffer]'s unmodified status.
+
+It sets @i[buffer]'s pathname to the result of probing @i[pathname] if the file
+exists; otherwise, this function sets @i[buffer]'s pathname to the result of
+merging @i[pathname] with @f[default-directory].
+
+It sets @hid[Pathname Defaults] to the result of the previous item.
+
+It processes the file options.
+
+It invokes @hid[Read File Hook].
+@end[itemize]
+
+@hid[Read File Hook] is a list functions that take two arguments @dash the
+buffer read into and whether the file existed, @true if so.
+@enddefun
+
+
+@defun[fun {find-file-buffer}, args {@i[pathname]}]
+This returns a buffer assoicated with the @i[pathname], reading the file into a
+new buffer if necessary.  This returns a second value indicating whether a new
+buffer was created, @true if so.  If the file has already been read, this
+checks to see if the file has been modified on disk since it was read, giving
+the user various recovery options.  This is the basis of the @hid[Find File]
+command.
+@enddefun
+
+
+
+@chapter (Hemlock's Lisp Environment)
+
+@index (Lisp environment)
+This chapter is sort of a catch all for any functions and variables
+which concern @hemlock's interaction with the outside world.
+
+@section(Entering and Leaving the Editor)
+
+@defun[fun {ed}, args {@optional @i[x]}]
+@defhvar1[var "Entry Hook"]
+@f[ed] enters the editor.  It is basically as specified in Common Lisp.  If
+@i[x] is supplied and is a symbol, the definition of @i[x] is put into a
+buffer, and that buffer is selected.  If @i[x] is a pathname, the file
+specified by @i[x] is visited in a new buffer.  If @i[x] is not supplied or
+@nil, the editor is entered in the same state as when last exited.
+	
+The @hid[Entry Hook] is invoked each time the editor is entered.
+@enddefhvar
+
+@defun[fun {exit-hemlock}, args {@optional @i[value]}]
+@defhvar1[var {Exit Hook}]
+@f[exit-hemlock] leaves @hemlock and return to Lisp; @i[value] is the
+value to return, which defaults to @true.  The hook 
+@hvarref[Exit Hook] is invoked before this is done.
+@enddefun
+
+@defun[fun {pause-hemlock}]
+@f[pause-hemlock] suspends the editor process and returns control to the shell.
+When the process is resumed, it will still be running @hemlock.
+@enddefun
+
+
+@section(Keyboard Input)
+@index(I/O)
+@index[keyboard input]
+@index[input, keyboard]
+
+Keyboard input interacts with a number of other parts of the editor.  Since the
+command loop works by reading from the keyboard, keyboard input is the initial
+cause of everything that happens.  Also, @hemlock redisplays in the low-level
+input loop when there is no available input from the user.
+
+
+@defvar[var {editor-input}]
+@defvar1[var {real-editor-input}]
+@defhvar1[var "Input Hook"]
+@defhvar1[var "Abort Hook"]
+@index[aborting]
+@var[editor-input] is an object on which @hemlock's I/O routines operate.  You
+can get input, clear input, return input, and listen for input.  Input appears
+as key-events.
+
+@var[real-editor-input] holds the initial value of @var[editor-input].  This is
+useful for reading from the user when @var[editor-input] is rebound (such as
+within a keyboard macro.)
+
+@Hemlock invokes the functions in @hid[Input Hook] each time someone reads a
+key-event from @var[real-editor-input].  These take no arguments.
+@enddefvar
+
+@defun[fun {get-key-event}, args {@i[editor-input] @optional @i[ignore-abort-attempts-p]}]
+This function returns a key-event as soon as it is available on
+@i[editor-input].  @i[Editor-input] is either @var[editor-input] or
+@var[real-editor-input].  @i[Ignore-abort-attempts-p] indicates whether
+@binding[C-g] and @binding[C-G] throw to the editor's top-level command loop;
+when this is non-nil, this function returns those key-events when the user
+types them.  Otherwise, it aborts the editor's current state, returning to the
+command loop.
+
+When the user aborts, @Hemlock invokes the functions in @hid[Abort Hook].
+These functions take no arguments.  When aborting, @Hemlock ignores the
+@hid[Input Hook].
+@enddefun
+
+
+@defun[fun {unget-key-event}, args {@i[key-event] @i[editor-input]}]
+This function returns @i[key-event] to @i[editor-input], so the next invocation
+of @f[get-key-event] will return @i[key-event].  If @i[key-event] is
+@f[#k"C-g"] or @f[#k"C-G"], then whether @f[get-key-event] returns it depends
+on that function's second argument.  @i[Editor-input] is either
+@var[editor-input] or @var[real-editor-input].
+@enddefun
+
+@defun[fun {clear-editor-input}, args {@i[editor-input]}]
+This function flushes any pending input on @i[editor-input].  @i[Editor-input]
+is either @var[editor-input] or @var[real-editor-input].
+@enddefun
+
+@defun[fun {listen-editor-input}, args {@i[editor-input]}]
+This function returns whether there is any input available on @i[editor-input].
+@i[Editor-input] is either @var[editor-input] or @var[real-editor-input].
+@enddefun
+
+@defun[fun {editor-sleep}, args {@i[time]}]
+Return either after @i[time] seconds have elapsed or when input is available on
+@var[editor-input].
+@enddefun
+
+@defvar[var {key-event-history}]
+This is a @hemlock ring buffer (see page @pageref[rings]) that holds the last
+60 key-events read from the keyboard.
+@enddefvar
+
+@defvar[var {last-key-event-typed}]
+Commands use this variable to realize the last key-event the user typed to
+invoke the commands.  Before @hemlock ever reads any input, the value is @nil.
+This variable usually holds the last key-event read from the keyboard, but it
+is also maintained within keyboard macros allowing commands to behave the same
+on each repetition as they did in the recording invocation.
+@enddefvar
+
+@defvar[var {input-transcript}]
+If this is non-@nil then it should be an adjustable vector with a fill-pointer.
+When it is non-@nil, @hemlock pushes all input read onto this vector.
+@enddefvar
+
+
+
+@section(Hemlock Streams)
+It is possible to create streams which output to or get input from a buffer.
+This mechanism is quite powerful and permits easy interfacing of @hemlock to
+Lisp.
+
+@defun[fun {make-hemlock-output-stream}, args 
+	{@i[mark] @optional @i[buffered]}]
+@defun1[fun {hemlock-output-stream-p}, args {@i[object]}]
+@f[make-hemlock-output-stream] returns a stream that inserts at the permanent
+mark @i[mark] all output directed to it.  @i[Buffered] controls whether the
+stream is buffered or not, and its valid values are the following keywords:
+@begin[description]
+@kwd[none]@\No buffering is done.  This is the default.
+
+@kwd[line]@\The buffer is flushed whenever a newline is written or
+when it is explicitly done with @f[force-output].
+
+@kwd[full]@\The screen is only brought up to date when it is
+explicitly done with @f[force-output]
+@end[description]
+
+@f[hemlock-output-stream-p] returns @true if @i[object] is a
+@f[hemlock-output-stream] object.
+@enddefun
+
+@defun[fun {make-hemlock-region-stream}, args {@i[region]}]
+@defun1[fun {hemlock-region-stream-p}, args {@i[object]}]
+@f[make-hemlock-region-stream] returns a stream from which the text in
+@i[region] can be read.  @f[hemlock-region-stream-p] returns @true if
+@i[object] is a @f[hemlock-region-stream] object.
+@enddefun
+
+@defmac[fun {with-input-from-region}, args
+{(@i[var] @i[region]) @mstar<@i[declaration]> @mstar<@i[form]>}]
+While evaluating @i[form]s, binds @i[var] to a stream which returns input
+from @i[region].
+@enddefmac
+
+@defmac[fun {with-output-to-mark}, args
+{(@i[var] @i[mark] @mopt<@i"buffered">) @mstar<@i[declaration]> @mstar<@i[form]>}]
+ During the evaluation of the @i[form]s, binds @i[var] to a stream which
+inserts output at the permanent @i[mark].  @i[Buffered] has the same meaning as
+for @f[make-hemlock-output-stream].
+@enddefmac
+
+@defmac[fun {with-pop-up-display}, args {(@i[var] @key @i[height name]) @mstar<@i[declaration]> @mstar<@i[form]>}]
+@defvar1[var {random-typeout-buffers}]
+ This macro executes @i[forms] in a context with @i[var] bound to a stream.
+@Hemlock collects output to this stream and tries to pop up a display of the
+appropriate height containing all the output.  When @i[height] is supplied,
+@Hemlock creates the pop-up display immediately, forcing output on line breaks.
+The system saves the output in a buffer named @i[name], which defaults to
+@hid[Random Typeout].  When the window is the incorrect height, the display
+mechanism will scroll the window with more-style prompting.  This is useful
+for displaying information of temporary interest.
+
+When a buffer with name @i[name] already exists and was not previously created
+by @f[with-pop-up-display], @Hemlock signals an error.
+
+@var[random-typeout-buffers] is an association list mapping random typeout
+buffers to the streams that operate on the buffers.
+@enddefmac
+
+
+@section (Interface to the Error System)
+The error system interface is minimal.  There is a simple editor-error
+condition which is a subtype of error and a convenient means for signaling
+them.  @Hemlock also provides a standard handler for error conditions while in
+the editor.
+
+@defun[fun {editor-error-format-string}, args {@i[condition]}]
+@defun1[fun {editor-error-format-arguments}, args {@i[condition]}]
+Handlers for editor-error conditions can access the condition object with
+these.
+@enddefun
+
+@defun[fun {editor-error}, args {@rest @i[args]}]
+This function is called to signal minor errors within Hemlock; these are errors
+that a normal user could encounter in the course of editing such as a search
+failing or an attempt to delete past the end of the buffer.  This function
+@f[signal]'s an editor-error condition formed from @i[args], which are @nil or
+a @f[format] string possibly followed by @f[format] arguments.  @Hemlock
+invokes commands in a dynamic context with an editor-error condition handler
+bound.  This default handler beeps or flashes (or both) the display.  If the
+condition passed to the handler has a non-@nil string slot, the handler also
+invokes @f[message] on it.  The command in progress is always aborted, and this
+function never returns.
+@enddefun
+
+@defmac[fun {handle-lisp-errors}, args {@mstar<@i[form]>}]
+Within the body of this macro any Lisp errors that occur are handled in some
+fashion more gracefully than simply dumping the user in the debugger.  This
+macro should be wrapped around code which may get an error due to some action
+of the user @dash for example, evaluating code fragments on the behalf of and
+supplied by the user.  Using this in a command allows the established handler
+to shadow the default editor-error handler, so commands should take care to
+signal user errors (calls to @f[editor-errors]) outside of this context.
+@enddefmac
+
+
+@section (Definition Editing)
+@index (Definition editing)
+@hemlock provides commands for finding the definition of a function, macro, or
+command and placing the user at the definition in a buffer.  This, of course,
+is implementation dependent, and if an implementation does not associate a
+source file with a routine, or if @hemlock cannot get at the information, then
+these commands do not work.  If the Lisp system does not store an absolute
+pathname, independent of the machine on which the maintainer built the system,
+then users need a way of translating a source pathname to one that will be able
+to locate the source.
+
+@defun[fun {add-definition-dir-translation}, args {@i[dir1] @i[dir2]}]
+This maps directory pathname @i[dir1] to @i[dir2].  Successive invocations
+using the same @i[dir1] push into a translation list.  When @hemlock seeks a
+definition source file, and it has a translation, then it tries the
+translations in order.  This is useful if your sources are on various machines,
+some of which may be down.  When @hemlock tries to find a translation, it first
+looks for translations of longer directory pathnames, finding more specific
+translations before shorter, more general ones.
+@enddefun
+
+@defun[fun {delete-definition-dir-translation}, args {@i[dir]}]
+This deletes the mapping of @i[dir] to all directories to which it has been
+mapped.
+@enddefun
+
+
+@section (Event Scheduling)
+@index (Event scheduling)
+@index (Scheduling events)
+The mechanism described in this chapter is only operative when the Lisp process
+is actually running inside of @hemlock, within the @f[ed] function.  The
+designers intended its use to be associated with the editor, such as with
+auto-saving files, reminding the user, etc.
+
+@defun[fun {schedule-event}, args {@i[time] @i[function] @optional @i[repeat]}]
+This causes @hemlock to call @i[function] after @i[time] seconds have passed,
+optionally repeating every @i[time] seconds.  @i[Repeat] defaults to @true.
+This is a rough mechanism since commands can take an arbitrary amount of time
+to run; @hemlock invokes @i[function] at the first possible moment after
+@i[time] has elapsed.  @i[Function] takes the time in seconds that has elapsed
+since the last time it was called (or since it was scheduled for the first
+invocation).
+@enddefun
+
+@defun[fun {remove-scheduled-event}, args {@i[function]}]
+This removes @i[function] from the scheduling queue.  @i[Function] does not
+have to be in the queue.
+@enddefun
+
+
+@section (Miscellaneous)
+
+@defun[fun {in-lisp}, args {@mstar<@i[form]>}]
+@index[Evaluating Lisp code]
+This evaluates @i[form]'s inside @f[handle-lisp-errors].  It also binds
+@var[package] to the package named by @hid[Current Package] if it is non-@nil.
+Use this when evaluating Lisp code on behalf of the user.
+@enddefun
+
+@defmac[fun {do-alpha-chars}, args {(@i[var] @i[kind] [@i[result]]) @mstar<@i[form]>}]
+This iterates over alphabetic characters in Common Lisp binding @i[var] to each
+character in order as specified under character relations in @i[Common Lisp the
+Language].  @i[Kind] is one of @kwd[lower], @kwd[upper], or @kwd[both].  When
+the user supplies @kwd[both], lowercase characters are processed first.
+@enddefmac
+
+
+
+@chapter (High-Level Text Primitives)
+This chapter discusses primitives that operate on higher level text forms than
+characters and words.  For English text, there are functions that know about
+sentence and paragraph structures, and for Lisp sources, there are functions
+that understand this language.  This chapter also describes mechanisms for
+organizing file sections into @i[logical pages] and for formatting text forms.
+
+
+@section (Indenting Text)
+@index (Indenting)
+@label(indenting)
+
+@defhvar[var "Indent Function", val {tab-to-tab-stop}]
+The value of this variable determines how indentation is done, and it is a
+function which is passed a mark as its argument.  The function should indent
+the line that the mark points to.  The function may move the mark around on
+the line.  The mark will be @f[:left-inserting].  The default simply inserts a
+@binding[tab] character at the mark.  A function for @hid[Lisp] mode probably
+moves the mark to the beginning of the line, deletes horizontal whitespace, and
+computes some appropriate indentation for Lisp code.
+@enddefhvar
+
+@defhvar[var "Indent with Tabs", val {indent-using-tabs}]
+@defhvar1[var "Spaces per Tab", val {8}]
+@hid[Indent with Tabs] holds a function that takes a mark and a number of
+spaces.  The function will insert a maximum number of tabs and a minimum number
+of spaces at mark to move the specified number of columns.  The default
+definition uses @hid[Spaces per Tab] to determine the size of a tab.  @i[Note,]
+@hid[Spaces per Tab] @i[is not used everywhere in @hemlock yet, so changing
+this variable could have unexpected results.]
+@enddefhvar
+
+@defun[fun {indent-region}, args {@i[region]}]
+@defun1[fun {indent-region-for-commands}, args {@i[region]}]
+@f[indent-region] invokes the value of @hid[Indent Function] on every line of
+region.  @f[indent-region-for-commands] uses @f[indent-region] but first saves
+the region for the @hid[Undo] command.
+@enddefun
+
+@defun[fun {delete-horizontal-space}, args {@i[mark]}]
+This deletes all characters with a @hid[Space] attribute (see section
+@ref[sys-def-chars]) of @f[1].
+@enddefun
+
+
+@section (Lisp Text Buffers)
+@index (Lisp text functions)
+@hemlock bases its Lisp primitives on parsing a block of the buffer and
+annotating lines as to what kind of Lisp syntax occurs on the line or what kind
+of form a mark might be in (for example, string, comment, list, etc.).  These
+do not work well if the block of parsed forms is exceeded when moving marks
+around these forms, but the block that gets parsed is somewhat programmable.
+
+There is also a notion of a @i[top level form] which this documentation often
+uses synonymously with @i[defun], meaning a Lisp form occurring in a source
+file delimited by parentheses with the opening parenthesis at the beginning of
+some line.  The names of the functions include this inconsistency.
+
+@defun[fun {pre-command-parse-check}, args {@i[mark] @i[for-sure]}]
+@defhvar1[var {Parse Start Function}, val {start-of-parse-block}]
+@defhvar1[var {Parse End Function}, val {end-of-parse-block}]
+@defhvar1[var {Minimum Lines Parsed}, val {50}]
+@defhvar1[var {Maximum Lines Parsed}, val {500}]
+@defhvar1[var {Defun Parse Goal}, val {2}]
+@f[pre-command-parse-check] calls @hid[Parse Start Function] and @hid[Parse End
+Function] on @i[mark] to get two marks.  It then parses all the lines between
+the marks including the complete lines they point into.  When @i[for-sure] is
+non-@nil, this parses the area regardless of any cached information about the
+lines.  Every command that uses the following routines calls this before doing
+so.
+
+The default values of the start and end variables use @hid[Minimum Lines
+Parsed], @hid[Maximum Lines Parsed], and @hid[Defun Parse Goal] to determine
+how big a region to parse.  These two functions always include at least the
+minimum number of lines before and after the mark passed to them.  They try to
+include @hid[Defun Parse Goal] number of top level forms before and after the
+mark passed them, but these functions never return marks that include more than
+the maximum number of lines before or after the mark passed to them.
+@enddefun
+
+@defun[fun {form-offset}, args {@i[mark] @i[count]}]
+This tries to move @i[mark] @i[count] forms forward if positive or -@i[count]
+forms backwards if negative.  @i[Mark] is always moved.  If there were enough
+forms in the appropriate direction, this returns @i[mark], otherwise nil.
+@enddefun
+
+@defun[fun {top-level-offset}, args {@i[mark] @i[count]}]
+This tries to move @i[mark] @i[count] top level forms forward if positive or
+-@i[count] top level forms backwards if negative.  If there were enough top
+level forms in the appropriate direction, this returns @i[mark], otherwise nil.
+@i[Mark] is moved only if this is successful.
+@enddefun
+
+@defun[fun {mark-top-level-form}, args {@i[mark1] @i[mark2]}]
+This moves @i[mark1] and @i[mark2] to the beginning and end, respectively, of
+the current or next top level form.  @i[Mark1] is used as a reference to start
+looking.  The marks may be altered even if unsuccessful.  If successful, return
+@i[mark2], else nil.  @i[Mark2] is left at the beginning of the line following
+the top level form if possible, but if the last line has text after the closing
+parenthesis, this leaves the mark immediately after the form.
+@enddefun
+
+@defun[fun {defun-region}, args {@i[mark]}]
+This returns a region around the current or next defun with respect to
+@i[mark].  @i[Mark] is not used to form the region.  If there is no appropriate
+top level form, this signals an editor-error.  This calls
+@f[pre-command-parse-check] first.
+@enddefun
+
+@defun[fun {inside-defun-p}, args {@i[mark]}]
+@defun1[fun {start-defun-p}, args {@i[mark]}]
+These return, respectively, whether @i[mark] is inside a top level form or at
+the beginning of a line immediately before a character whose @hid[Lisp Syntax]
+(see section @ref[sys-def-chars]) value is @kwd[opening-paren].
+@enddefun
+
+@defun[fun {forward-up-list}, args {@i[mark]}]
+@defun1[fun {backward-up-list}, args {@i[mark]}]
+Respectively, these move @i[mark] immediately past a character whose @hid[Lisp
+Syntax] (see section @ref[sys-def-chars]) value is @kwd[closing-paren] or
+immediately before a character whose @hid[Lisp Syntax] value is
+@kwd[opening-paren].
+@enddefun
+
+@defun[fun {valid-spot}, args {@i[mark] @i[forwardp]}]
+This returns @true or @nil depending on whether the character indicated by
+@i[mark] is a valid spot.  When @i[forwardp] is set, use the character after
+mark and vice versa.  Valid spots exclude commented text, inside strings, and
+character quoting.
+@enddefun
+
+@defun[fun {defindent}, args {@i[name] @i[count]}]
+This defines the function with @i[name] to have @i[count] special arguments.
+@f[indent-for-lisp], the value of @hid[Indent Function] (see section
+@ref[indenting]) in @hid[Lisp] mode, uses this to specially indent these
+arguments.  For example, @f[do] has two, @f[with-open-file] has one, etc.
+There are many of these defined by the system including definitions for special
+@hemlock forms.  @i[Name] is a simple-string, case insensitive and purely
+textual (that is, not read by the Lisp reader); therefore, @f["with-a-mumble"]
+is distinct from @f["mumble:with-a-mumble"].
+@enddefun
+
+
+@section (English Text Buffers)
+@index (English text functions)
+@label(text-functions)
+This section describes some routines that understand basic English language
+forms.
+
+@defun[fun {word-offset}, args {@i[mark] @i[count]}]
+This moves @i[mark] @i[count] words forward (if positive) or backwards (if
+negative).  If @i[mark] is in the middle of a word, that counts as one.  If
+there were @i[count] (-@i[count] if negative) words in the appropriate
+direction, this returns @i[mark], otherwise nil.  This always moves @i[mark].
+A word lies between two characters whose @hid[Word Delimiter] attribute value
+is @f[1] (see section @ref[sys-def-chars]).
+@enddefun
+
+@defun[fun {sentence-offset}, args {@i[mark] @i[count]}]
+This moves @i[mark] @i[count] sentences forward (if positive) or backwards (if
+negative).  If @i[mark] is in the middle of a sentence, that counts as one.  If
+there were @i[count] (-@i[count] if negative) sentences in the appropriate
+direction, this returns @i[mark], otherwise nil.  This always moves @i[mark].
+
+A sentence ends with a character whose @hid[Sentence Terminator] attribute is
+@f[1] followed by two spaces, a newline, or the end of the buffer.  The
+terminating character is optionally followed by any number of characters whose
+@hid[Sentence Closing Char] attribute is @f[1].  A sentence begins after a
+previous sentence ends, at the beginning of a paragraph, or at the beginning of
+the buffer.
+@enddefun
+
+@defun[fun {paragraph-offset}, args {@i[mark] @i[count] @optional @i[prefix]}]
+@defhvar1[var {Paragraph Delimiter Function}, var {default-para-delim-function}]
+This moves @i[mark] @i[count] paragraphs forward (if positive) or backwards (if
+negative).  If @i[mark] is in the middle of a paragraph, that counts as one.
+If there were @i[count] (-@i[count] if negative) paragraphs in the appropriate
+direction, this returns @i[mark], otherwise nil.  This only moves @i[mark] if
+there were enough paragraphs.
+
+@hid[Paragraph Delimiter Function] holds a function that takes a mark,
+typically at the beginning of a line, and returns whether or not the current
+line should break the paragraph.  @f[default-para-delim-function] returns @true
+if the next character, the first on the line, has a @hid[Paragraph Delimiter]
+attribute value of @f[1].  This is typically a space, for an indented
+paragraph, or a newline, for a block style.  Some modes require a more
+complicated determinant; for example, @hid[Scribe] modes adds some characters
+to the set and special cases certain formatting commands.
+
+@i[Prefix] defaults to @hid[Fill Prefix] (see section @ref[filling]), and the
+right prefix is necessary to correctly skip paragraphs.  If @i[prefix] is
+non-@nil, and a line begins with @i[prefix], then the scanning process skips
+the prefix before invoking the @hid[Paragraph Delimiter Function].
+Note, when scanning for paragraph bounds, and @i[prefix] is non-@nil, lines are
+potentially part of the paragraph regardless of whether they contain the prefix;
+only the result of invoking the delimiter function matters.
+
+The programmer should be aware of an idiom for finding the end of the current
+paragraph.  Assume @f[paragraphp] is the result of moving @f[mark] one
+paragraph, then the following correctly determines whether there actually is a
+current paragraph:
+@begin[programexample]
+(or paragraphp
+    (and (last-line-p mark)
+         (end-line-p mark)
+	 (not (blank-line-p (mark-line mark)))))
+@end[programexample]
+In this example @f[mark] is at the end of the last paragraph in the buffer, and
+there is no last newline character in the buffer.  @f[paragraph-offset] would
+have returned @nil since it could not skip any paragraphs since @f[mark] was at
+the end of the current and last paragraph.  However, you still have found a
+current paragraph on which to operate.  @f[mark-paragraph] understands this
+problem.
+@enddefun
+
+@defun[fun {mark-paragraph}, args {@f[mark1] @f[mark2]}]
+This marks the next or current paragraph, setting @i[mark1] to the beginning
+and @i[mark2] to the end.  This uses @hid[Fill Prefix] (see section
+@ref[filling]).  @i[Mark1] is always on the first line of the paragraph,
+regardless of whether the previous line is blank.  @i[Mark2] is typically at
+the beginning of the line after the line the paragraph ends on, this returns
+@i[mark2] on success.  If this cannot find a paragraph, then the marks are left
+unmoved, and @nil is returned.
+@enddefun
+
+
+@section (Logical Pages)
+@index (Logical pages)
+@index (Page functions)
+@label(logical-pages)
+Logical pages are a way of dividing a file into coarse divisions.  This is
+analogous to dividing a paper into sections, and @hemlock provides primitives
+for moving between the pages of a file and listing a directory of the page
+titles.  Pages are separated by @hid[Page Delimiter] characters (see section
+@ref[sys-def-chars]) that appear at the beginning of a line.
+
+@defun[fun {goto-page}, args {@i[mark] @i[n]}]
+This moves @i[mark] to the absolute page numbered @i[n].  If there are less
+than @i[n] pages, it signals an editor-error.  If it returns, it returns
+@i[mark].  @hemlock numbers pages starting with one for the page delimited by
+the beginning of the buffer and the first @hid[Page Delimiter] (or the end of
+the buffer).
+@enddefun
+
+@defun[fun {page-offset}, args {@i[mark] @i[n]}]
+This moves mark forward @i[n] (-@i[n] backwards, if @i[n] is negative)
+@hid[Page Delimiter] characters that are in the zero'th line position.  If a
+@hid[Page Delimiter] is the immediately next character after mark (or before
+mark, if @i[n] is negative), then skip it before starting.  This always moves
+@i[mark], and if there were enough pages to move over, it returns @i[mark];
+otherwise, it returns @nil.
+@enddefun
+
+@defun[fun {page-directory}, args {@i[buffer]}]
+This returns a list of each first non-blank line in @i[buffer] that follows a
+@hid[Page Delimiter] character that is in the zero'th line position.  This
+includes the first line of the @i[buffer] as the first page title.  If a page
+is empty, then its title is the empty string.
+@enddefun
+
+@defun[fun {display-page-directory}, args {@i[stream] @i[directory]}]
+This writes the list of strings, @i[directory], to @i[stream], enumerating them
+in a field three wide.  The number and string are separated by two spaces, and
+the first line contains headings for the page numbers and title strings.
+@enddefun
+
+
+@section (Filling)
+@index (filling)
+@label(filling)
+Filling is an operation on text that breaks long lines at word boundaries
+before a given column and merges shorter lines together in an attempt to make
+each line roughly the specified length.  This is different from justification
+which tries to add whitespace in awkward places to make each line exactly the
+same length.  @Hemlock's filling optionally inserts a specified string at the
+beginning of each line.  Also, it eliminates extra whitespace between lines and
+words, but it knows two spaces follow sentences (see section
+@ref[text-functions]).
+
+@defhvar[var "Fill Column", val {75}]
+@defhvar1[var "Fill Prefix", val {nil}]
+These variables hold the default values of the prefix and column arguments to
+@hemlock's filling primitives.  If @hid[Fill Prefix] is @nil, then there is no
+fill prefix.
+@enddefhvar
+
+@defun[fun {fill-region}, args {@i[region] @optional @i[prefix] @i[column]}]
+This deletes any blank lines in region and fills it according to prefix and
+column.  @i[Prefix] and @i[column] default to @hid[Fill Prefix] and @hid[Fill
+Column].
+@enddefun
+
+@defun[fun {fill-region-by-paragraphs},
+	args {@i[region] @optional @i[prefix] @i[column]}]
+This finds paragraphs (see section @ref[text-functions]) within region and
+fills them with @f[fill-region].  This ignores blank lines between paragraphs.
+@i[Prefix] and @i[column] default to @hid[Fill Prefix] and @hid[Fill Column].
+@enddefun
+
+
+
+@chapter (Utilities)
+@index (Utilities)
+This chapter describes a number of utilities for manipulating some types of
+objects @hemlock uses to record information.  String-tables are used to store
+names of variables, commands, modes, and buffers.  Ring lists can be used to
+provide a kill ring, recent command history, or other user-visible features.
+
+
+@section(String-table Functions)
+@index (String-tables)
+@label(string-tables)
+
+String tables are similar to Common Lisp hash tables in that they associate a
+value with an object.  There are a few useful differences: in a string table
+the key is always a case insensitive string, and primitives are provided to
+facilitate keyword completion and recognition.  Any type of string may be added
+to a string table, but the string table functions always return
+@f[simple-string]'s.
+
+A string entry in one of these tables may be thought of as being separated into
+fields or keywords.  The interface provides keyword completion and recognition
+which is primarily used to implement some @hid[Echo Area] commands.  These
+routines perform a prefix match on a field-by-field basis allowing the
+ambiguous specification of earlier fields while going on to enter later fields.
+While string tables may use any @f[string-char] as a separator, the use of
+characters other than @binding[space] may make the @hid[Echo Area] commands
+fail or work unexpectedly.
+
+@defun[fun {make-string-table}, keys {[separator][initial-contents]}]
+This function creates an empty string table that uses @i[separator] as the
+character, which must be a @f[string-char], that distinguishes fields.
+@i[Initial-contents] specifies an initial set of strings and their values in
+the form of a dotted @f[a-list], for example:
+@Begin[ProgramExample]
+'(("Global" . t) ("Mode" . t) ("Buffer" . t))
+@End[ProgramExample]
+@enddefun
+
+@defun[fun {string-table-p}, args {@i[string-table]}]
+This function returns @true if @i[string-table] is a @f[string-table] object,
+otherwise @nil.
+@enddefun
+
+@defun[fun {string-table-separator}, args {@i[string-table]}]
+This function returns the separator character given to @f[make-string-table].
+@enddefun
+
+@defun[fun {delete-string}, args {@i[string] @i[table]}]
+@defun1[fun {clrstring}, args {@i[table]}]
+@f[delete-string] removes any entry for @i[string] from the @f[string-table]
+@i[table], returning @true if there was an entry.  @f[clrstring] removes all
+entries from @i[table].
+@enddefun
+
+@defun[fun {getstring}, args {@i[string] @i[table]}]
+This function returns as multiple values, first the value corresponding to the
+string if it is found and @nil if it isn't, and second @true if it is found and
+@nil if it isn't.
+
+This may be set with @f[setf] to add a new entry or to store a new value for a
+string.  It is an error to try to insert a string with more than one
+field separator character occurring contiguously.
+@enddefun
+
+@defun[fun {complete-string}, args {@i[string] @i[tables]}]
+This function completes @i[string] as far as possible over the list of
+@i[tables], returning five values.  It is an error for @i[tables] to have
+different separator characters.  The five return values are as follows:
+@begin[itemize]
+The maximal completion of the string or @nil if there is none.
+
+An indication of the usefulness of the returned string:
+@begin[description]
+@kwd[none]@\
+There is no completion of @i[string].
+
+@kwd[complete]@\
+The completion is a valid entry, but other valid completions exist too.  This
+occurs when the supplied string is an entry as well as initial substring of
+another entry.
+
+@kwd[unique]@\
+The completion is a valid entry and unique.
+
+@kwd[ambiguous]@\
+The completion is invalid; @f[get-string] would return @nil and @nil if given
+the returned string.
+@end[description]
+
+The value of the string when the completion is @kwd[unique] or @kwd[complete],
+otherwise @nil.
+
+An index, or nil, into the completion returned, indicating where the addition
+of a single field to @i[string] ends.  The command @hid[Complete Field] uses
+this when the completion contains the addition to @i[string] of more than one
+field.
+
+An index to the separator following the first ambiguous field when the
+completion is @kwd[ambiguous] or @kwd[complete], otherwise @nil.
+@end[itemize]
+@enddefun
+
+@defun[fun {find-ambiguous}, args {@i[string] @i[table]}]
+@defun1[fun {find-containing}, args {@i[string] @i[table]}]
+@f[find-ambiguous] returns a list in alphabetical order of all the
+strings in @i[table] matching @i[string].  This considers an entry as matching
+if each field in @i[string], taken in order, is an initial substring of the
+entry's fields; entry may have fields remaining.
+ 
+@f[find-containing] is similar, but it ignores the order of the fields in
+@i[string], returning all strings in @i[table] matching any permutation of the
+fields in @i[string].
+@enddefun
+
+@defmac[fun {do-strings}, args {(@i[string-var] @i[value-var] @i[table] @MOPT<@i[result]>) @mstar<@i[declaration]> @mstar<@i[tag] @MOR @i[statement]>}]
+This macro iterates over the strings in @i[table] in alphabetical order.  On
+each iteration, it binds @i[string-var] to an entry's string and @i[value-var]
+to an entry's value.
+@enddefmac
+
+
+@section (Ring Functions)
+@index (Rings)
+@label[rings]
+There are various purposes in an editor for which a ring of values can be used,
+so @hemlock provides a general ring buffer type.  It is used for maintaining a
+ring of killed regions (see section @ref[kill-ring]), a ring of marks (see
+section @ref[mark-stack]), or a ring of command strings which various modes and
+commands maintain as a history mechanism.
+
+@defun[fun {make-ring}, args {@i[length] @optional @i[delete-function]}]
+Makes an empty ring object capable of holding up to @i[length] Lisp objects.
+@i[Delete-function] is a function that each object is passed to before it falls
+off the end.  @i[Length] must be greater than zero.
+@enddefun
+
+@defun[fun {ringp}, args {@i[ring]}]
+Returns @true if @i[ring] is a @f[ring] object, otherwise @nil.
+@enddefun
+
+@defun[fun {ring-length}, args {@i[ring]}]
+Returns as multiple-values the number of elements which @i[ring]
+currently holds and the maximum number of elements which it may hold.
+@enddefun
+
+@defun[fun {ring-ref}, args {@i[ring] @i[index]}]
+Returns the @i[index]'th item in the @i[ring], where zero is the index
+of the most recently pushed.  This may be set with @f[setf].
+@enddefun
+
+@defun[fun {ring-push}, args {@i[object] @i[ring]}]
+Pushes @i[object] into @i[ring], possibly causing the oldest item to
+go away.
+@enddefun
+
+@defun[fun {ring-pop}, args {@i[ring]}]
+Removes the most recently pushed object from @i[ring] and returns it.
+If the ring contains no elements then an error is signalled.
+@enddefun
+
+@defun[fun {rotate-ring}, args {@i[ring] @i[offset]}]
+With a positive @i[offset], rotates @i[ring] forward that many times.
+In a forward rotation the index of each element is reduced by one,
+except the one which initially had a zero index, which is made the
+last element.  A negative offset rotates the ring the other way.
+@enddefun
+
+
+@section (Undoing commands)
+@index (Undo functions)
+@label(undo)
+
+@defun[fun {save-for-undo}, args {@i[name] @i[method] @optional @i[cleanup] @i[method-undo] @i[buffer]}]
+This saves information to undo a command.  @i[Name] is a string to display when
+prompting the user for confirmation when he invokes the @hid[Undo] command (for
+example, @f["kill"] or @f["Fill Paragraph"]).  @i[Method] is the function to
+invoke to undo the effect of the command.  @i[Method-undo] is a function that
+undoes the undo function, or effectively re-establishes the state immediately
+after invoking the command.  If there is any existing undo information, this
+invokes the @i[cleanup] function; typically @i[method] closes over or uses
+permanent marks into a buffer, and the @i[cleanup] function should delete such
+references.  @i[Buffer] defaults to the @f[current-buffer], and the @hid[Undo]
+command only invokes undo methods when they were saved for the buffer that is
+current when the user invokes @hid[Undo].
+@enddefun
+
+@defun[fun {make-region-undo}, args {@i[kind] @i[name] @i[region] @optional @i[mark-or-region]}]
+This handles three common cases that commands fall into when setting up undo
+methods, including cleanup and method-undo functions (see @f[save-for-undo]).
+These cases are indicated by the @i[kind] argument:
+@begin[description]
+@kwd[twiddle]@\
+Use this kind when a command modifies a region, and the undo information
+indicates how to swap between two regions @dash the one before any modification
+occurs and the resulting region.  @i[Region] is the resulting region, and it
+has permanent marks into the buffer.  @i[Mark-or-region] is a region without
+marks into the buffer (for example, the result of @f[copy-region]).  As a
+result of calling this, a first invocation of @hid[Undo] deletes @i[region],
+saving it, and inserts @i[mark-or-region] where @i[region] used to be.  The
+undo method sets up for a second invocation of @hid[Undo] that will undo the
+effect of the undo; that is, after two calls, the buffer is exactly as it was
+after invoking the command.  This activity is repeatable any number of times.
+This establishes a cleanup method that deletes the two permanent marks into the
+buffer used to locate the modified region.
+
+@kwd[insert]@\
+Use this kind when a command has deleted a region, and the undo information
+indicates how to re-insert the region.  @i[Region] is the deleted and saved
+region, and it does not contain marks into any buffer.  @i[Mark-or-region] is a
+permanent mark into the buffer where the undo method should insert @i[region].
+As a result of calling this, a first invocation of @hid[Undo] inserts
+@i[region] at @i[mark-or-region] and forms a region around the inserted text
+with permanent marks into the buffer.  This allows a second invocation of
+@hid[Undo] to undo the effect of the undo; that is, after two calls, the buffer
+is exactly as it was after invoking the command.  This activity is repeatable
+any number of times.  This establishes a cleanup method that deletes either the
+permanent mark into the buffer or the two permanent marks of the region,
+depending on how many times the user used @hid[Undo].
+
+@kwd[delete]@\
+Use this kind when a command has inserted a block of text, and the undo
+information indicates how to delete the region.  @i[Region] has permanent marks
+into the buffer and surrounds the inserted text.  Leave @i[Mark-or-region]
+unspecified.  As a result of calling this, a first invocation of @hid[Undo]
+deletes @i[region], saving it, and establishes a permanent mark into the buffer
+to remember where the @i[region] was.  This allows a second invocation of
+@hid[Undo] to undo the effect of the undo; that is, after two calls, the buffer
+is exactly as it was after invoking the command.  This activity is repeatable
+any number of times.  This establishes a cleanup method that deletes either the
+permanent mark into the buffer or the two permanent marks of the region,
+depending on how many times the user used @hid[Undo].
+@end[description]
+
+@blankspace(1 line)
+@i[Name] in all cases is an appropriate string indicating what the command did.
+This is used by @hid[Undo] when prompting the user for confirmation before
+calling the undo method.  The string used by @hid[Undo] alternates between this
+argument and something to indicate that the user is undoing an undo.
+@enddefun
+
+
+
+@chapter (Miscellaneous)
+This chapter is somewhat of a catch-all for comments and features that don't
+fit well anywhere else.
+
+
+@section (Generic Pointer Up)
+@hid[Generic Pointer Up] is a @hemlock command bound to mouse up-clicks.  It
+invokes a function supplied with the interface described in this section.  This
+command allows different commands to be bound to the same down-click in various
+modes with one command bound to the corresponding up-click.
+
+@defun[fun {supply-generic-pointer-up-function}, args {@i[function]}]
+@index[Generic Pointer Up]
+This function supplies a function that @hid[Generic Pointer Up] invokes the
+next time it executes.
+@enddefun
+
+
+@section (Using View Mode)
+@hid[View] mode supports scrolling through files automatically terminating the
+buffer at end-of-file as well as commands for quitting the mode and popping
+back to the buffer that spawned the @hid[View] mode buffer.  Modes such as
+@hid[Dired] and @hid[Lisp-Lib] use this to view files and description of
+library entries.
+
+Modes that want similar commands should use @f[view-file-command] to view a
+file and get a handle on the view buffer.  To allow the @hid[View Return] and
+@hid[View Quit] commands to return to the originating buffer, you must set the
+variable @hid[View Return Function] in the viewing buffer to a function that
+knows how to do this.  Furthermore, since you now have a reference to the
+originating buffer, you must add a buffer local delete hook to it that will
+clear the view return function's reference.  This needs to happen for two
+reasons in case the user deletes the originating buffer:
+@Begin[Enumerate]
+You don't want the return function to go to a non-existing, invalid buffer.
+
+Since the viewing buffer still exists, its @hid[View Return Function] buffer
+local variable still exists.  This means the function still references the
+deleted originating buffer, and garbage collection cannot reclaim the memory
+locked down by the deleted buffer.
+@End[Enumerate]
+
+The following is a piece of code that could implement part of @hid[Dired View
+File] that uses two closures to accomplish that described above:
+@Begin[ProgramExample]
+(let* ((dired-buf (current-buffer))
+       (buffer (view-file-command nil pathname)))
+  (push #'(lambda (buffer)
+	    (declare (ignore buffer))
+	    (setf dired-buf nil))
+	(buffer-delete-hook dired-buf))
+  (setf (variable-value 'view-return-function :buffer buffer)
+	#'(lambda ()
+	    (if dired-buf
+		(change-to-buffer dired-buf)
+		(dired-from-buffer-pathname-command nil)))))
+@End[ProgramExample]
+
+The @hid[Dired] buffer's delete hook clears the return function's reference to
+the @hid[Dired] buffer.  The return function tests the variable to see if it
+still holds a buffer when the function executes.
+
+
+
+@comment[@chapter (Auxiliary Systems)]
+@include(aux-sys)
Index: /branches/new-random/cocoa-ide/hemlock/doc/misc/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/misc/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/misc/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/doc/misc/compilation.order
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/misc/compilation.order	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/misc/compilation.order	(revision 13309)
@@ -0,0 +1,250 @@
+; Definitions of structures intended for use within the HEMLOCK-INTERNALS
+; package.
+Struct
+; Definitions of structures intended for use within the HEMLOCK package.
+Struct-ed
+; Code specific to CMU Common Lisp on the IBM RT/PC under Mach.
+rompsite
+; Implementation dependant character hacking macros.
+Charmacs
+; This is implementation dependent code for canonical input event
+; representation.  It also provides a interface for converting X11 codes
+; and bits to an input event.
+Key-event
+Keysym-defs
+; Implementation independent code to support input to Hemlock, based on
+; keytran.lisp and keytrandefs.lisp.
+Input
+; Random macros needed in the compiler.
+Macros
+; Implementation dependant line structure definition.
+Line
+
+; Ring-Buffer data-type primitives.
+Ring
+; String-Table primitives.
+Table
+ 
+; Text manipulation primitives.
+Htext1
+Htext2
+Htext3
+Htext4
+
+; Searching and replacing primitives.
+Search1 ;String searches.
+Search2 ;Character searches, uses %sp-[reverse-]find-character-with-attribute.
+
+; Stuff that depends on the current line-image building scheme, and
+; thus %SP-Find-Character-With-Attribute.
+; Build line images.
+Linimage
+; Cursor-positioning and recentering stuff.
+Cursor
+
+; Uses %SP-Find-Character-With-Attribute, but is independent of line-image
+; stuff.
+; Syntax table primitives.
+Syntax
+
+; Window image building stuff.
+Winimage
+
+; Implementation dependent redisplay code for running under X.
+Hunk-Draw
+
+; Implementation independent interface to Unix style termcap files.
+Termcap
+
+; Implementation independent redisplay entry points.
+Display
+
+; Implementation dependent redisplay.
+Bit-display ;for bitmap displays under X.
+
+; Implementation dependent redisplay code for running with a terminal.
+Tty-disp-rt
+
+; Implementation independent redisplay code for running with a terminal.
+Tty-display
+
+; Implementation dependent code for random typeout/pop-up displays on the
+; bitmap and tty.
+pop-up-stream
+
+; Implementation independent screen management.
+Screen
+
+; Implementation dependent screen management.
+Bit-screen ;for bitmap display under X.
+
+; Implementation independent screen management code for running with a terminal.
+Tty-screen
+
+; Implementation independent code for Hemlock window primitives and
+; some other redisplay stuff.
+Window
+
+; Implementation independent interface to fonts.
+Font
+
+; The command interpreter.
+Interp
+
+; Hemlock variable access functions.
+Vars
+
+; Buffer and mode manipulation functions
+Buffer
+
+; Implementation dependent file primitives.
+Files
+
+; Implemention dependent stream primitives.
+Streams
+
+; echo-area prompting functions.
+Echo
+
+; Random top-level user functions and implementation independant initilization
+; stuff.
+Main
+
+; Echo-Area commands.
+EchoComs
+
+; Some character attribute definitions.
+Defsyn
+
+; Basic commands
+Command
+MoreComs
+
+; Stuff for undoing stuff.
+Undo
+
+; Killing and un-killing commands.  Mark ring primitives and commands.
+KillComs
+
+; Searching and replacing commands.
+SearchComs
+
+; File and buffer manipulating commands.
+Filecoms
+
+; Indentation commands
+Indent
+
+; Commands for lisp mode.
+Lispmode
+
+; Comment-hacking commands.
+Comments
+
+; Auto Fill Mode and filling commands.
+Fill
+
+; Text primitives and commands (paragraphs, sentences, etc.)
+Text
+
+; Documentation commands.
+Doccoms
+
+; Commands for buffer comparison and stuff.
+Srccom
+
+; Commands for manipulating groups of files.
+Group
+
+; Implementation dependent spell code.
+Spell-RT
+; Spelling correction interface implementation.
+Spell-Corr
+; Spell interface to incrementally add to the dictionary.
+Spell-Aug
+; Nearly implementation independent code to build binary dictionary.
+Spell-Build
+; User interface commands.
+Spellcoms
+
+; Word abbreviation commands.
+Abbrev
+
+; Overwrite mode, for making text pictures and stuff.
+Overwrite
+
+; Gosling Emacs bindings and twiddle chars command.  Lots of other
+;differences.
+gosmacs
+
+; a typescript server in Hemlock.  Client Lisp's *terminal-io* streams are
+; set to typescript streams which send message requests to typescript servers
+; for input and output, so this is how client Lisps can do full I/O inside
+; a Hemlock buffer.
+Ts-buf
+Ts-stream
+
+; commands for interacting with client Lisp environments and REP loops.
+eval-server
+Lispeval
+
+; commands for evaling and running a REP loop in a buffer.
+Lispbuf
+
+; Keyboard macros and stuff.
+Kbdmac
+
+; Hackish thing to italicize comments.
+Icom
+
+; Stuff to check buffer integrity.
+Integrity
+
+; Scribe Mode
+Scribe
+
+; Definition editing/function definition finding
+Edit-Defs
+
+; auto-save mode.
+auto-save
+
+; register code.  stuff for stashing marks and regions in "registers".
+register
+
+; commands pertinent only to the X windowing system.
+xcoms
+
+; implements Unix specific commands for Hemlock.
+unixcoms
+
+; mail interface to MH.
+mh
+
+; highlighting parens and active regions.
+highlight
+
+; directory editing; implementation dependent.
+dired
+diredcoms
+
+; buffer hacking mode.
+bufed
+
+; lisp library browser mode; implementation dependent.
+lisp-lib
+
+; completion mode to save key strokes for long Lisp identifiers.
+completion
+
+; "Process" mode, primarily implements Unix shells in Hemlock buffers.
+shell
+
+; stuff for talking to slave Lisps to do debugging.
+debug
+
+; site dependent NNTP interface for reading Netnews.
+netnews
+
+; File that sets up all the default key bindings; implementation dependant.
+Bindings
Index: /branches/new-random/cocoa-ide/hemlock/doc/misc/hemlock.log
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/misc/hemlock.log	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/misc/hemlock.log	(revision 13309)
@@ -0,0 +1,4514 @@
+.../systems-work/hemlock/mh.lisp, 18-Oct-90 13:41:38, Edit by Chiles.
+  MAYBE-DELETE-EXTRA-DRAFT-WINDOW modified to correctly delete another window
+  if one exists when a draft is a split window draft.  This had to be modified
+  to handle separate, unstacked windows correctly.
+
+.../systems-work/hemlock/bindings.lisp, 06-Sep-90 16:59:32, Edit by Chiles.
+  We failed to avoid binding "Auto Check Word Spelling" to #k"'" when we added
+  the new key-event stuff.  Actually, Blaine did.
+
+.../systems-work/hemlock/bindings.lisp, 24-Aug-90 14:04:34, Edit by Chiles.
+  Bound C-M-s (typically "Shell") to "Illegal" in the echo area.
+
+.../systems-work/hemlock/bit-screen.lisp, 06-Aug-90 13:48:10, Edit by Chiles.
+  I modified CREATE-WINDOW-FROM-CURRENT to correctly determin if there is
+  enough room to split the current window to make the new window.
+
+.../systems-work/hemlock/bit-screen.lisp, 06-Aug-90 12:59:40, Edit by Chiles.
+  Made SET-WINDOW-HOOK-RAISE-FUN frob the windows group X window, instead of
+  the child X window.
+
+.../systems-work/hemlock/hunk-draw.lisp, 05-Aug-90 12:57:21, Edit by Chiles.
+  Fixed DROP-CURSOR to beat on the parent borders instead of the non-existent
+  child borders.
+
+.../systems-work/hemlock/bit-screen.lisp, 05-Aug-90 11:58:46, Edit by Chiles.
+  Removed exports for MAKE-WINDOW, DELETE-WINDOW, NEXT-WINDOW, and
+  PREVIOUS-WINDOW since they're in screen.lisp.
+
+  Modified HUNK-RECONFIGURED to realize it object arg is either a hunk (for a
+  child changing) or a window-group (for a group/parent window changing).
+
+  Modified HUNK-MOUSE-ENTERED and HUNK-MOUSE-LEFT to frob the group window's
+  border instead of the child's border.
+
+  Totally redefined *create-window-hook* and *delete-window-hook*.  This
+  affected most of the arrangement of creation and deletion functionality.
+
+  Made the random-typeout window made from keeping a pop-up display, adhere to
+  the minimum resizing parameters Hemlock windows like to try to keep users
+  from screwing themselves.
+
+  Made MAYBE-MAKE-X-WINDOW-AND-PARENT set window manager hints for supplied
+  parents as if Hemlock had made the parent window.
+
+  Made code correctly handle font-family parameters instead of dropping into
+  lower-level code that incorrectly assumed *default-font-family*.
+
+  Consolidated some code, notably MODIFY-PARENT-PROPERTIES.
+
+
+.../systems-work/hemlock/xcoms.lisp, 01-Aug-90 14:00:43, Edit by Chiles.
+  Blew away "Stack Window".
+
+.../systems-work/hemlock/input.lisp, 01-Aug-90 13:49:27, Edit by Chiles.
+  Blaine modified MAYBE-KEEP-RANDOM-TYPEOUT-WINDOW in accordance with the new
+  bitmap window group stuff.
+
+.../systems-work/hemlock/filecoms.lisp, 01-Aug-90 11:23:07, Edit by Chiles.
+  Blaine modified "Delete Window" and "Delete Next Window" in accordance with
+  the new bitmap window group stuff.  They now test the length of *window-list*
+  to determine if they can delete the window instead of using next and previous
+  window commands and primitives and testing against the CURRENT-WINDOW.
+
+.../systems-work/hemlock/screen.lisp, 01-Aug-90 10:15:53, Edit by Chiles.
+  Blaine modified DELETE-WINDOW to test for *window-list* having length two or
+  less, signalling an error if so.  This allows the bitmap window deletion
+  method to delete the current window by changing to another group.  The
+  "Delete Window" command cannot tell there are other windows, and it already
+  tries to make the previous window the current one before calling the
+  DELETE-WINDOW primitive.  With the new bitmap window groups, this doesn't
+  work.  We still have a problem if a programmer calls DELETE-WINDOW on the
+  current window which will break Hemlock.
+
+.../systems-work/hemlock/rompsite.lisp, 01-Aug-90 09:33:02, Edit by Chiles.
+  Blaine modified the X events masks and the raising and lowering of Hemlock
+  windows upon entering and leaving in accordance with the new bitmap window
+  groups.
+
+.../systems-work/hemlock/struct.lisp, 01-Aug-90 09:07:25, Edit by Chiles.
+  Blaine added window-group structure and the window-group slot to
+  bitmap-hunks for the new bitmap window groups.
+
+.../systems-work/hemlock/keysym-defs.lisp, 04-Jul-90 12:14:09, Edit by Chiles.
+  Added a few key-event to character translations at the end of the file to
+  make quoting characters work better when running under X.
+
+/usr2/mbb/lisp/work/diredcoms.lisp, 02-Jul-90 10:12:28, Edit by Mbb.
+  Fixed a bug in "Dired" where it was incorrectly assuming that the current
+  buffer was a DIRED buffer.
+
+.../systems-work/hemlock/searchcoms.lisp, 27-Jun-90 18:27:38, Edit by Chiles.
+.../systems-work/hemlock/kbdmac.lisp, 27-Jun-90 18:19:09, Edit by Chiles.
+  Fixed "Keyboard Macro Query" to realize the :bind arg to COMMAND-CASE is a
+  key-event, not a charcter.
+
+.../systems-work/hemlock/macros.lisp, 27-Jun-90 18:04:12, Edit by Chiles.
+  Fixed COMMAND-CASE to bind key-events, not characters.  It also doesn't make
+  N calls to mapping functions everytime someone was to map one way or the
+  other.  It also no longer makes erroneous assumptions about characters and
+  key-events having a one-to-one mapping.
+
+.../systems-work/hemlock/key-event.lisp, 27-Jun-90 17:34:57, Edit by Chiles.
+  Fixed bugs in character/key-event mapping that allowed bogus typed objects to
+  fall through as if they mapped to meaningful values.
+
+.../systems-work/hemlock/interp.lisp, 26-Jun-90 09:54:52, Edit by Chiles.
+  Fixed some documentation.
+
+  Fixed a bug in KEY-TRANSLATION.  Someone changed a type-spec from '(or
+  simple-vector null) to '(simple-vector null).
+
+  Fixed a bug in TRANSLATE-KEY.  It returned the wrong thing and by accident
+  didn't go into an infinite loop if there were any key translations to
+  multiple key-event keys.
+
+
+.../systems-work/hemlock/echo.lisp, 25-Jun-90 11:44:05, Edit by Chiles.
+  Fixed default prompt of PROMPT-FOR-KEY-EVENT to be "Key-event: ", not
+  "Character: ".
+
+.../systems-work/hemlock/interp.lisp, 24-Jun-90 12:28:02, Edit by Chiles.
+  Removed silly KEYIFY definition, and I put Blaine's name on the file since he
+  modified half of the contents to get the new key tables stuff to work.
+
+.../systems-work/hemlock/input.lisp, 21-Jun-90 19:52:01, Edit by Chiles.
+  Added doc strings to public routines.  Documented some code.  Moved some
+  silly things around.
+
+.../systems-work/hemlock/srccom.lisp, 21-Jun-90 18:53:46, Edit by Chiles.
+.../systems-work/hemlock/spellcoms.lisp, 21-Jun-90 18:52:56, Edit by Chiles.
+.../systems-work/hemlock/macros.lisp, 21-Jun-90 18:51:19, Edit by Chiles.
+.../systems-work/hemlock/filecoms.lisp, 21-Jun-90 18:49:14, Edit by Chiles.
+.../systems-work/hemlock/doccoms.lisp, 21-Jun-90 18:45:55, Edit by Chiles.
+  Made COMMAND-CASE specify lowercase letters.
+
+.../systems-work/hemlock/key-event.lisp, 20-Jun-90 23:11:18, Edit by Chiles.
+  Fixed a bug in TRANSLATE-KEY-EVENT.
+
+.../systems-work/hemlock/bindings.lisp, 20-Jun-90 23:03:22, Edit by Chiles.
+  Bound #k"H-t" to "Illegal" in the echo area.  This is normally bound to a
+  command that makes the current window display the most recently used
+  random-typeout buffer.
+
+.../systems-work/hemlock/macros.lisp, 20-Jun-90 20:45:07, Edit by Chiles.
+  Fixed an extra paren bug that prevented successful compilation.  That's what
+  I get for Blaine's failure to use "Extract Form".
+
+.../systems-work/hemlock/lispmode.lisp, 20-Jun-90 20:47:57, Edit by Chiles.
+  Added "Extract Form", a more useful and intuitive and consistent command to
+  use instead of "Extract List" which is archaic, confusing, erroneously bound
+  by default, and bound to old Lisp ideals that lists are something to focus
+  on.
+
+.../hemlock/ts-buf.lisp, 20-Jun-90 17:40:51, Edit by Wlott.
+  Made typescript commands more robust in light of the possibility of being
+  executed while in a buffer other than the slave buffer.
+
+.../systems-work/hemlock/key-event.lisp, 20-Jun-90 17:00:33, Edit by Chiles.
+  Totally rewrote mouse translation code.  Fixed multiple bugs MAKE-KEY-EVENT.
+
+.../systems-work/hemlock/macros.lisp, 20-Jun-90 13:55:48, Edit by Chiles.
+  Removed :character argument to COMMAND-CASE.  Stopped case-folding and
+  eliminated variables used for that.
+
+.../systems-work/hemlock/fill.lisp, 16-Jun-90 14:07:48, Edit by Chiles.
+  Fixed "Auto Fill Linefeed" and "Auto Fill Return" to use #k syntax instead of
+  characters for keys.
+
+.../systems-work/hemlock/key-event.lisp, 16-Jun-90 13:59:23, Edit by Chiles.
+  Added missing exports.
+
+  Fixed a couple bugs with DEFINE-KEY-EVENT-MODIFIER.  It was using EQL to
+  compare strings.  Stuck an UNWIND-PROTECT in there to keep things consistent.
+  Added restart for already defined modifiers allowing the user to go on
+  blowing it off; this helps reloading the file.
+
+
+.../systems-work/hemlock/echo.lisp, 16-Jun-90 11:11:17, Edit by Chiles.
+  Fixed two GET-KEY-EVENT calls to ignore abort attempts in PROMPT-FOR-KEY
+  and PROMPT-FOR-KEY-EVENT.
+
+.../systems-work/hemlock/keysym-defs.lisp, 15-Jun-90 18:17:38, Edit by Chiles.
+  This file used to be called keytrandefs.lisp.
+
+.../systems-work/hemlock/key-event.lisp, 15-Jun-90 18:34:10, Edit by Chiles.
+  This file used to be called keytran.lisp.  It now implements key-events in
+  the "EXTENSIONS" package.
+
+.../systems-work/hemlock/bit-screen.lisp, 14-Jun-90 14:28:58, Edit by Chiles.
+  Replaced calls to EXT:TRANSLATE-CHARACTER and EXT:TRANSLATE-MOUSE-CHARACTER
+  with EXT:TRANSLATE-KEY-EVENT and EXT:TRANSLATE-MOUSE-KEY-EVENT.
+
+.../systems-work/hemlock/shell.lisp, 15-Jun-90 16:27:42, Edit by Chiles.
+  Picked up Blaine's new shell hacks and documented them.  Added "Current
+  Shell" and "Ask about Old Shells" variables.  Changed "Shell" to be more like
+  "Select Slave" and wrote "Shell Command Line in Buffer".
+
+/usr2/mbb/lisp/work/doccoms.lisp, 14-Jun-90 21:19:46, Edit by Mbb.
+  Made a quoted list of #k mouse-keys be a call to LIST on the mouse-keys
+  instead so they would get evaluated.
+
+/usr2/mbb/lisp/work/input.lisp, 12-Jun-90 21:00:12, Edit by Mbb.
+  input.lisp is a new file.  It contains code to implement input to
+  hemlock.  Similar code previously resided in rompsite.lisp
+
+/usr2/mbb/lisp/work/icom.lisp, 12-Jun-90 16:15:00, Edit by Mbb.
+/usr2/mbb/lisp/work/gosmacs.lisp, 12-Jun-90 16:15:00, Edit by Mbb.
+  Changed BIND-KEY calls to use #k format instead of characters.
+
+.../systems-work/hemlock/filecoms.lisp, 13-Jun-90 15:17:06, Edit by Chiles.
+  Wrote "Go to One Window" which makes a default initial window and deletes all
+  other windows.  This is useful with losing window managers like twm, and it
+  is useful in case you ever resize or move the main Hemlock window which
+  happens by accident to some people.
+
+/usr2/mbb/lisp/work/keytran.lisp, 13-Jun-90 14:01:58, Edit by Mbb.
+  Changed all the BIND-KEY forms in this file to use #k format.
+
+/usr2/mbb/lisp/work/files.lisp, 12-Jun-90 10:26:58, Edit by Mbb.
+  Inserted the form (proclaim '(special vm_page_size)) so the compiler
+  wouldn't whine about vm_page_size not being declared or bound. 
+
+/usr2/mbb/lisp/work/buffer.lisp, 11-Jun-90 11:58:39, Edit by Mbb.
+  Modified DEFMODE -- The default mode-bindings slot is now a hash-table
+  whereas it used to be a key-table.  Did the same for buffer-bindings in
+  MAKE-BUFFER.
+
+/usr2/mbb/lisp/work/keytrandefs.lisp, 11-Jun-90 13:17:59, Edit by Mbb.
+  Made all calls to "EXTENSIONS" use an ext: prefix.
+
+/usr2/mbb/lisp/work/scribe.lisp, 08-Jun-90 17:33:31, Edit by Mbb.
+/usr2/mbb/lisp/work/register.lisp, 08-Jun-90 17:29:23, Edit by Mbb.
+/usr2/mbb/lisp/work/interp.lisp, 08-Jun-90 17:27:44, Edit by Mbb.
+  Changed all calls to PRINT-PRETTY-CHARACTER to calls to
+  PRINT-PRETTY-KEY-EVENT. 
+
+/usr2/mbb/lisp/work/kbdmac.lisp, 08-Jun-90 17:25:50, Edit by Mbb.
+  Made all calls to SUB-PRINT-KEY be calls to PRINT-PRETTY-KEY.
+
+/usr2/mbb/lisp/work/doccoms.lisp, 08-Jun-90 17:15:46, Edit by Mbb.
+  Removed SUB-PRINT-KEY in favor of PRINT-PRETTY-KEY.
+
+/usr2/mbb/lisp/work/searchcoms.lisp, 08-Jun-90 14:38:55, Edit by Mbb.
+/usr2/mbb/lisp/work/overwrite.lisp, 08-Jun-90 14:38:38, Edit by Mbb.
+/usr2/mbb/lisp/work/morecoms.lisp, 08-Jun-90 14:37:43, Edit by Mbb.
+/usr2/mbb/lisp/work/completion.lisp, 08-Jun-90 14:37:10, Edit by Mbb.
+/usr2/mbb/lisp/work/command.lisp, 08-Jun-90 14:36:12, Edit by Mbb.
+  Changed all calls to TEXT-CHARACTER to calls to KEY-EVENT-CHAR.
+
+/usr2/mbb/lisp/work/rompsite.lisp, 08-Jun-90 12:15:17, Edit by Mbb.
+/usr2/mbb/lisp/work/termcap.lisp, 08-Jun-90 12:15:17, Edit by Mbb.
+  Commented out CL-TERMCAP-CHAR as it is no longer needed.  
+  GET-TERMCAP-STRING-CHAR does the conversion to a character now.
+
+/usr2/mbb/lisp/work/doccoms.lisp, 08-Jun-90 11:08:09, Edit by Mbb.
+  Removed from GET-MOUSE-COMMANDS a call to MAKE-CHAR in favor of
+  MAKE-KEY-EVENT and also fixed a list to use the new #k"foo" format.
+
+/usr2/mbb/lisp/work/bindings.lisp, 08-Jun-90 10:44:49, Edit by Mbb.
+  Chnaged all bindings to #k"foo" format.
+
+/usr2/mbb/lisp/work/charmacs.lisp, 07-Jun-90 14:44:36, Edit by Mbb.
+  Removed the declaration of the constant all-bit-names, as bit names are
+  no longer supported in Common Lisp.
+
+/usr2/mbb/lisp/work/charmacs.lisp, 07-Jun-90 14:41:23, Edit by Mbb.
+  Changed ALPHA-CHAR-LOOP and DO-ALPHA-CHARS to ALPHA-KEY-EVENTS-LOOP and
+  DO-ALPHA-KEY-EVENTS respectively.
+
+/usr2/mbb/lisp/work/tty-display.lisp, 06-Jun-90 10:38:07, Edit by Mbb.
+/usr2/mbb/lisp/work/searchcoms.lisp, 06-Jun-90 10:36:39, Edit by Mbb.
+/usr2/mbb/lisp/work/searchcoms.lisp, 06-Jun-90 10:21:58, Edit by Mbb.
+/usr2/mbb/lisp/work/rompsite.lisp, 06-Jun-90 10:09:11, Edit by Mbb.
+/usr2/mbb/lisp/work/morecoms.lisp, 06-Jun-90 10:16:52, Edit by Mbb.
+/usr2/mbb/lisp/work/mh.lisp, 06-Jun-90 10:14:12, Edit by Mbb.
+/usr2/mbb/lisp/work/doccoms.lisp, 06-Jun-90 10:04:45, Edit by Mbb.
+/usr2/mbb/lisp/work/macros.lisp, 05-Jun-90 15:11:03, Edit by Mbb.
+/usr2/mbb/lisp/work/kbdmac.lisp, 05-Jun-90 15:08:37, Edit by Mbb.
+/usr2/mbb/lisp/work/interp.lisp, 05-Jun-90 11:02:59, Edit by Mbb.
+/usr2/mbb/lisp/work/echo.lisp, 05-Jun-90 10:58:55, Edit by Mbb.
+/usr2/mbb/lisp/work/doccoms.lisp, 05-Jun-90 15:05:40, Edit by Mbb.
+/usr2/mbb/lisp/work/command.lisp, 05-Jun-90 15:02:21, Edit by Mbb.
+  Fixed all references to *editor-input*.
+
+/usr2/mbb/lisp/work/main.lisp, 06-Jun-90 10:07:41, Edit by Mbb.
+  *editor-input* used to be exported from this file, event though it is
+  also exported in input.lisp.  Removed export from main.lisp.
+
+/usr2/mbb/lisp/work/rompsite.lisp, 05-Jun-90 14:31:55, Edit by Mbb.
+  Changed reference to *character-history* in SITE-INIT to
+  *key-event-history*.
+
+/usr2/mbb/lisp/work/mh.lisp, 05-Jun-90 14:30:28, Edit by Mbb.
+  Changed a reference to *character-history* to *key-event-history*.
+
+/usr2/mbb/lisp/work/main.lisp, 05-Jun-90 14:27:23, Edit by Mbb.
+  Removed export of *character-history* from this file in favor of putting
+  it in input.lisp and changing the name to *key-event-history*.
+
+/usr2/mbb/lisp/work/doccoms.lisp, 05-Jun-90 14:19:41, Edit by Mbb.
+  Made "What Lossage" command reference *key-event-history* instead of
+  *character-history*.
+
+/usr2/mbb/lisp/work/streams.lisp, 05-Jun-90 14:10:43, Edit by Mbb.
+  Made KBDMAC-GET use *last-key-event-typed* instead of
+  *last-character-typed*.  Also changed stream definition of kbdmac-stream
+  to coincide with the new editor-input like streams.
+
+/usr2/mbb/lisp/work/spellcoms.lisp, 05-Jun-90 14:08:57, Edit by Mbb.
+  Made SUB-CORRECT-LAST-MISSPELLED-WORD work with *last-key-event-typed*.
+
+/usr2/mbb/lisp/work/scribe.lisp, 05-Jun-90 14:07:23, Edit by Mbb.
+  Fixed "Scribe Insert bracket" to work with *last-key-event-typed*.
+
+/usr2/mbb/lisp/work/rompsite.lisp, 05-Jun-90 13:59:46, Edit by Mbb.
+  Removed all Input queue management and Random Typeout input routines and
+  put them in a input.lisp, a new hemlock file.
+
+/usr2/mbb/lisp/work/rompsite.lisp, 05-Jun-90 13:45:23, Edit by Mbb.
+  Changed DEFVAR of *last-character-typed* to *last-key-event-typed*.  Also
+  fixed setting of *last-character-typed* in DQ-EVENT.  For some reason,
+  *last-character-typed* was exported from both main.lisp and
+  rompsite.lisp.  This remains under the new name.
+
+/usr2/mbb/lisp/work/overwrite.lisp, 05-Jun-90 13:43:23, Edit by Mbb.
+  Made "Self Overwrite" use *last-key-event-typed* instead of
+  *last-character-typed*.
+
+/usr2/mbb/lisp/work/morecoms.lisp, 05-Jun-90 13:41:58, Edit by Mbb.
+  Made "Self Insert Caps Lock" deal with *last-key-event-typed* instead of
+  *last-character-typed*.
+
+/usr2/mbb/lisp/work/main.lisp, 05-Jun-90 13:40:48, Edit by Mbb.
+  Changed export of *last-character-typed* to *last-key-event-typed*.
+
+/usr2/mbb/lisp/work/kbdmac.lisp, 05-Jun-90 13:37:38, Edit by Mbb.
+  Made DEFAULT-KBDMAC-TRANSFORM and SELF-INSERT-KBDMAC-TRANSFORM use
+  *last-key-event-typed* instead of *last-character-typed*.
+
+/usr2/mbb/lisp/work/echocoms.lisp, 05-Jun-90 13:34:52, Edit by Mbb.
+  Made "Complete Field" work with *last-key-event-typed*.
+/usr2/mbb/lisp/work/completion.lisp, 05-Jun-90 13:28:07, Edit by Mbb.
+  Made "Completion Self Insert" deal with *last-key-event-typed* instead of
+  *last-character-typed*.
+
+/usr2/mbb/lisp/work/command.lisp, 05-Jun-90 13:24:55, Edit by Mbb.
+  Changed UNIVERSAL-ARGUMENT-LOOP to deal with *last-key-event-typed*
+  instead of *last-character-typed*.  Also made "Self Insert" do the same.
+
+/usr2/mbb/lisp/work/spellcoms.lisp, 05-Jun-90 12:58:02, Edit by Mbb.
+  Changed calls to PROMPT-FOR-CHARACTER to calls to PROMPT-FOR-KEY-EVENT.
+  Since what we wanted was the number of the correction choice, simply wrap
+  a call to KEY-EVENT-CHAR around the PROMPT-FOR-KEY-EVENT.
+
+/usr2/mbb/lisp/work/scribe.lisp, 05-Jun-90 11:59:46, Edit by Mbb.
+  Made ADD-SCRIBE-DIRECTIVE and INSERT-SCRIBE-DIRECTIVE use PROMPT-FOR-KEY
+  instead of PROMPT-FOR-CHARACTER.  They used to HASH on the result of
+  PROMPT-FOR-CHARACTER, so key-events will work just as well.
+
+/usr2/mbb/lisp/work/scribe.lisp, 05-Jun-90 11:59:46, Edit by Mbb.
+  Changed all top-level ADD-SCRIBE-DIRECTIVE-COMMAND calls to use #k syntax
+  when binding dispatches.
+
+/usr2/mbb/lisp/work/struct.lisp, 05-Jun-90 11:08:20, Edit by Mbb.
+  Changed DEFSETF for %SET-LOGICAL-CHAR= to %SET-LOGICAL-KEY-EVENT-P in
+  order to maintain consistency.
+
+/usr2/mbb/lisp/work/macros.lisp, 05-Jun-90 09:23:41, Edit by Mbb.
+  Fixed COMMAND-CASE to bind key-events instead of characters.
+
+/usr2/mbb/lisp/work/register.lisp, 05-Jun-90 09:31:41, Edit by Mbb.
+  Made PROMPT-FOR-REGISTER return a key-event instead of a character.  The
+  rest of the code code just hashes on what PROMPT-FOR-REGISTER returns, so
+  since key-events are unique, nothing else had to be changed.
+
+/usr2/mbb/lisp/work/keytrandefs.lisp, 04-Jun-90 13:16:13, Edit by Mbb.
+  Completely changed this file to conform to new key syntax.
+
+/usr2/mbb/lisp/work/charmacs.lisp, 04-Jun-90 13:10:55, Edit by Mbb.
+  Removed all pushes into lisp::char-name-alist.
+
+.../systems-work/hemlock/completion.lisp, 29-May-90 13:54:48, Edit by Chiles.
+  Changed test in DO-COMPLETION to explicitly test for uppercase characters.
+  Testing for lowercase characters caused ID's to be uppercased when they began
+  with non-alphabetic characters (such as digit-chars).
+
+.../systems-work/hemlock/bindings.lisp, 21-May-90 10:22:28, Edit by Chiles.
+.../systems-work/hemlock/morecoms.lisp, 21-May-90 10:19:13, Edit by Chiles.
+  Added "CAPS-LOCK" mode, "Caps Lock Mode" and "Caps Lock Self Insert".
+
+  Added bindings for lowercase letters.
+
+
+.../systems-work/hemlock/bindings.lisp, 21-May-90 10:14:10, Edit by Chiles.
+.../systems-work/hemlock/diredcoms.lisp, 21-May-90 10:03:16, Edit by Chiles.
+  Wrote "Dired Up Directory" and added binding to #\^ in "Dired" mode.
+
+.../systems-work/hemlock/diredcoms.lisp, 08-May-90 15:38:28, Edit by Chiles.
+  Fixed :help string in file prompt for "Delete File".
+
+.../hemlock/ts-stream.lisp, 26-Apr-90 17:14:10, Edit by Wlott.
+  Make %ts-stream-listen try calling server before finally saying that
+  there is no more input available.
+
+.../hemlock/files.lisp, 26-Apr-90 18:43:29, Edit by Wlott.
+  Fixed a bug in write-file in which the first line was being extended with
+  garbage if it didn't start at the first character.
+
+.../systems-work/hemlock/lispeval.lisp, 16-Apr-90 14:03:10, Edit by Chiles.
+  Modified OPERATION-STARTED, OPERATION-COMPLETED, and "List Operations" to
+  preserve the case of context strings when MESSAGE'ing.  I added "The"'s to
+  sentences which previously capitalized the first word of the context and
+  lowered the remaining parts of the string.  I added periods to sentences in
+  all these routines.  I stopped operation listing from forcing the entire
+  string to lowercase.  The user should get his context as he supplied it.
+  Many users complained about file names reporting as incorrect due to the old
+  state of the code.
+
+.../systems-work/hemlock/lispbuf.lisp, 16-Apr-90 13:41:05, Edit by Chiles.
+  Fixed doc string for "Current Package" in "package" file option handler.
+
+/usr2/ch/lisp/lispeval.lisp, 15-Apr-90 19:14:38, Edit by Christopher Hoover.
+  Sometimes the defined "Current Package" does not exist in the slave, and
+  sometimes "Current Package" is defined as nil.  "Describe Function Call"
+  points out which reason led to using the default package in the slave.
+
+.../systems-work/hemlock/shell.lisp, 24-Mar-90 11:58:10, Edit by Chiles.
+  New file.
+
+.../systems-work/hemlock/bindings.lisp, 24-Mar-90 11:57:31, Edit by Chiles.
+  Added bindings for new "Process" mode.
+
+.../systems-work/hemlock/main.lisp, 22-Mar-90 16:03:27, Edit by Blaine.
+  Added new hook "Buffer Writable Hook".
+
+.../systems-work/hemlock/buffer.lisp, 22-Mar-90 15:45:51, Edit by Blaine.
+  Write BUFFER-WRITABLE and %SET-BUFFER-WRITABLE.
+
+.../systems-work/hemlock/struct.lisp, 22-Mar-90 15:40:31, Edit by Blaine.
+  Renamed the writable slot to %writable.  Added DEFSETF for BUFFER-WRITABLE.
+
+.../systems-work/hemlock/completion.lisp, 22-Mar-90 14:51:00, Edit by Chiles.
+  Picked up Blaine's "Save Completions", "Read Completions", and "Parse Buffer
+  for Completions".
+
+  I added documentation to "Completion" mode and made the parameter
+  completion-bucket-size-limit be a Hemlock variable "Completion Bucket Size".
+
+
+.../systems-work/hemlock/buffer.lisp, 19-Mar-90 16:45:01, Edit by Chiles.
+  Made the BUFFER-MODIFIED SETF'er return the value stored.
+
+.../systems-work/hemlock/table.lisp, 12-Mar-90 12:43:13, Edit by Chiles.
+  Made BI-SVPOSITION stop calling IDENTITY on every element.  There already was
+  a test for the key argument being nil, but the author allowed the argument to
+  default to IDENTITY.  Also, it is never called without a key argument anyway
+  -- gratuitous generality maladjusted.
+
+.../systems-work/hemlock/mh.lisp, 09-Mar-90 09:03:28, Edit by Chiles.
+  Fixed bug in REMAIL-MESSAGE resulting from recent changes to the environment
+  code that made my MH env vars become capitalized when they should have been
+  lowercase.
+
+.../systems-work/hemlock/lispeval.lisp, 27-Feb-90 15:03:31, Edit by Chiles.
+  Modified EVAL-FORM-IN-SERVER to optionally take a package name.  It uses the
+  value of "Current Package" as a default, which it previously always supplied.
+  EVAL-FORM-IN-SERVER-1 accordingly takes a package argument now.  "Describe
+  Function Call" now first asks the server if the value of "Current Package"
+  names a package, and if it does not, then this command describes the function
+  call by reading the name into *package* in the slave.  This reasonably
+  handles the problem of describing a function call with a buffer package that
+  does not exist in the slave.
+
+.../systems-work/hemlock/screen.lisp, 27-Feb-90 13:18:16, Edit by Mbb.
+  Made pop-up displays better count lines when fully buffered.
+
+.../systems-work/hemlock/lispeval.lisp, 22-Feb-90 11:20:03, Edit by Chiles.
+  Picked up Williams change to "Lisp Operations", and I documented his peculiar
+  queue implementation.
+
+.../systems-work/hemlock/srccom.lisp, 21-Feb-90 13:52:45, Edit by Chiles.
+  Added "Source Compare Ignore Indentation" and wrote a macro to generate the
+  line comparison routines that *srccom-line-=* holds.
+
+.../systems-work/hemlock/searchcoms.lisp, 15-Feb-90 10:17:40, Edit by Chiles.
+  Fixed a bug in undo'ing replacements.  IF two were immediately adjacent, the
+  second would not be undone.
+
+.../systems-work/hemlock/command.lisp, 14-Feb-90 14:15:38, Edit by Chiles.
+  Fixed "Forward Character".
+
+.../systems-work/hemlock/eval-server.lisp, 10-Feb-90 12:07:29, Edit by Chiles.
+  Made editor MESSAGE what slave is GC'ing when dumping GC messages behind the
+  prompt.  Also, moved the global frobbing into the two routines that setup and
+  cleanup stream variables.
+
+.../systems-work/hemlock/mh.lisp, 09-Feb-90 17:02:43, Edit by Chiles.
+  Finally fixed bug in PICK-MESSAGES that allowed MH pick to screw us.  MH pick
+  would output "0" when no messages matched a specification, so PICK-MESSAGES
+  now tests the result of calling MH to invoke "pick".  It returns nil whenever
+  MH returns other than t for correct completion.
+
+.../systems-work/hemlock/termcap.lisp, 08-Feb-90 20:07:01, Edit by Chiles.
+  The new fd-streams, which correctly implement unreading characters, pointed
+  out that this code relied on multiply unreading characters.  It no longer
+  does.
+
+.../systems-work/hemlock/lisp-lib.lisp, 07-Feb-90 15:50:50, Edit by Chiles.
+  Modified MERGE-PATHNAMES calls that used strings with dots to merge in types.
+  This no longer works with the new NAMESTRING/PARSE-NAMESTRING stuff.
+
+.../systems-work/hemlock/command.lisp, 07-Feb-90 13:52:10, Edit by Chiles.
+  "Next Line" was opening newlines in the middle of the buffer's last line of
+  text when the buffer wasn't newline terminated.
+
+/usr2/mbb/lisp/work/macros.lisp, 07-Feb-90 12:22:54, Edit by Mbb.
+  Changed how WITH-POP-UP-DISPLAY determines whether to cleanup.  It 
+  shouldn't have been cleaning up unless something had really happened, but
+  it was.
+
+.../systems-work/hemlock/files.lisp, 31-Jan-90 11:58:15, Edit by Chiles.
+  Modifed all occurrances of "fdstream" to "fd-stream" to be consistent with
+  new interface.
+
+.../systems-work/hemlock/mh.lisp, 26-Jan-90 12:41:47, Edit by Chiles.
+  Fixed bug leaving a file open every time I called MH-PROFILE-COMPONENT, and
+  closed the process in MH.
+
+.../systems-work/hemlock/command.lisp, 24-Jan-90 11:06:13, Edit by Chiles.
+  Changed "Next Line", "Previous Line", "Next Word", "Previous Word",
+  "Forward Character", "Backward Character", "Delete Next Character", and
+  "Delete Previous Character" to work with correctly negative arguments.
+
+.../systems-work/hemlock/macros.lisp, 24-Jan-90 10:40:00, Edit by Chiles.
+  Modified WITH-POP-UP-DISPLAY to have a doc string other than "Do Some Shit."
+
+.../systems-work/hemlock/lispbuf.lisp, 22-Jan-90 15:17:49, Edit by Chiles.
+  Modified code around *prompt* to adhere to new semantics of its values.
+
+.../hemlock/mh.lisp, 19-Jan-90 21:00:28, Edit by Wlott.
+  Changed to use new RUN-PROGRAM return values.
+
+.../systems-work/hemlock/eval-server.lisp, 19-Jan-90 12:07:06, Edit by Chiles.
+  Modified DO-OPERATION and the thing that aborts operations to handshake on
+  whether we were in the debugger when we aborted.  If we were, output a
+  message trying to inform the user that the output in his typescript can be
+  ignored; he is no longer really in the debugger.
+
+.../systems-work/hemlock/lispeval.lisp, 18-Jan-90 23:21:55, Edit by Chiles.
+  Fixed "Abort Operations" to really abort the operations (one more time).
+
+.../systems-work/hemlock/eval-server.lisp, 18-Jan-90 16:45:24, Edit by Chiles.
+  Made the -slave switch handler setup *gc-notify-before* and *gc-notify-after*
+  to do gratuitous output to the editor.
+
+.../systems-work/hemlock/ts-stream.lisp, 18-Jan-90 16:08:00, Edit by Chiles.
+  Fixed a bug in WAIT-FOR-TYPESCRIPT-INPUT that incorrectly reported input when
+  the function was re-entered by handling an event in SERVE-EVENT.
+
+.../systems-work/hemlock/ts-buf.lisp, 18-Jan-90 12:14:40, Edit by Chiles.
+  Modified TS-BUFFER-OUTPUT-STRING to take a gratuitous-p optional indicating
+  output should go behind the prompt.
+
+.../systems-work/hemlock/morecoms.lisp, 17-Jan-90 21:21:53, Edit by Chiles.
+  Modified DO-RECURSIVE-EDIT to update the modeline field before possibly
+  signalling an error in the cleanup forms of the UNWIND-PROTECT.
+
+.../systems-work/hemlock/ts-buf.lisp, 17-Jan-90 15:25:18, Edit by Chiles.
+  Removed weird disappearing prompt stuff.  Added stuff to help users unwedge
+  themselves when they get behind the prompt.
+
+.../systems-work/hemlock/streams.lisp, 16-Jan-90 13:42:19, Edit by William.
+  Made Hemlock output streams make sure the mark is :left-inserting, but only
+  when actually doing the output.
+
+.../systems-work/hemlock/morecoms.lisp, 15-Jan-90 09:07:31, Edit by Chiles.
+  Modified "Count Lines" and "Count Words" to report lines counted as being in
+  the active region or after the point.
+
+.../systems-work/hemlock/eval-server.lisp, 15-Jan-90 13:09:19, Edit by Wlott.
+  Changed occurances of SYSTEM:SERVER to SYSTEM:SERVE-EVENT.
+
+  Added tweeking of *standard-output* and friends in addition to
+  *terminal-io* when connecting to a slave.
+
+
+.../systems-work/hemlock/lispeval.lisp, 15-Jan-90 14:13:56, Edit by Wlott.
+  Made FILE-COMPILE pay attention to "Remote Compile File". (I must have been
+  brain-dead the first time through that code...)
+
+.../systems-work/hemlock/files.lisp, 15-Jan-90 15:21:36, Edit by Wlott.
+  Changed write-file to be faster.
+
+.../systems-work/hemlock/srccom.lisp, 13-Jan-90 14:42:07, Edit by Chiles.
+  Made "Merge Buffers" have an (A)lign window with start of difference display
+  option in the command loop.  I often had to use recursive edit to be able to
+  position the window to see the difference that was otherwise not visible due
+  to normal scrolling and redisplay centering the mark.
+
+.../systems-work/hemlock/srccom.lisp, 13-Jan-90 14:00:25, Edit by Chiles.
+  Fixed "Compare Buffers" and "Merge Buffers" to test for a nil result when
+  calling LINE-OFFSET.  When buffers weren't terminated with newlines, the old
+  code would infinitely loop.
+
+.../systems-work/hemlock/lispmode.lisp, 12-Jan-90 18:29:20, Edit by Chiles.
+  Modified SCAN-DIRECTION-VALID to check for the ignore region falling off the
+  end of the line which caused %FORM-OFFSET to infinitely loop.
+
+.../systems-work/hemlock/ts-stream.lisp, 12-Jan-90 12:47:37, Edit by Wlott.
+  Changed occurances of SYSTEM:SERVER to SYSTEM:SERVE-EVENT.
+
+.../systems-work/hemlock/tty-disp-rt.lisp, 11-Jan-90 19:31:46, Edit by Wlott.
+  Changed to work with fdstreams.
+
+.../systems-work/hemlock/rompsite.lisp, 11-Jan-90 16:42:02, Edit by Wlott.
+  Changed occurances of SYSTEM:SERVER to SYSTEM:SERVE-EVENT.
+
+.../systems-work/hemlock/tty-screen.lisp, 09-Jan-90 14:27:17, Edit by Chiles.
+  When we make a random typeout window, we no longer say the screen image is
+  trashed.  Some uses of pop up displays do output and then prompt inside the
+  form, and this prompting was causing the main window to be redisplayed since
+  we said the screen image was trashed.  This drew over our pop up display.
+
+.../systems-work/hemlock/indent.lisp, 08-Jan-90 10:20:48, Edit by Mbb.
+  Made "Center Line" use the active region.
+
+.../systems-work/hemlock/bit-screen.lisp, 05-Jan-90 17:07:23, Edit by Mbb.
+  REVERSE-VIDEO-HOOK-FUN was calling the wrong function.
+
+.../systems-work/hemlock/eval-server.lisp, 01-Dec-89 17:58:53, Edit by Chiles.
+  Fixed a bug in SERVER-DIED that prevented it from deleting variables
+  referencing dead server-infos.
+
+.../systems-work/hemlock/ts-buf.lisp, 01-Dec-89 17:06:22, Edit by Chiles.
+  Modified and documented TYPESCRIPTIFY-BUFFER to make a local "Current Eval
+  Server" variable.
+
+.../systems-work/hemlock/eval-server.lisp, 01-Dec-89 16:29:25, Edit by Chiles.
+  GET-CURRENT-EVAL-SERVER cleaned up.  "Select Slave" rewritten to no longer
+  set current eval server.
+
+.../systems-work/hemlock/eval-server.lisp, 22-Nov-89 15:51:42, Edit by Mbb.
+  Just someone forgetting the result argument to THROW.  The old defmacro
+  compiler stuff didn't catch this, so it used to pass (and amazingly, work).
+
+.../systems-work/hemlock/morecoms.lisp, 22-Nov-89 15:31:29, Edit by Mbb.
+  Somehow, the old "Count Lines" worked.  How, I don't know.  It had an IF
+  without a THEN clause, which is required by ClTM.  The new DEFMACRO stuff
+  caught it.
+
+.../systems-work/hemlock/mh.lisp, 27-Oct-89 11:49:25, Edit by Chiles.
+  After recently eliminating recursive folder support, "List Folders" continued
+  to claim it would list all folders recursively.  Removed useless code and
+  bogus doc string.
+
+.../systems-work/hemlock/diredcoms.lisp, 25-Oct-89 16:15:29, Edit by Chiles.
+  Picked up Blaine's changes to make "Dired" and "Dired with Pattern" do dot
+  files with an argument.  This propagates to subdirectories.
+
+.../systems-work/hemlock/lisp-lib.lisp, 25-Oct-89 15:59:19, Edit by Chiles.
+  Made browser look in new library location.
+
+.../systems-work/hemlock/lispeval.lisp, 29-Sep-89 15:52:50, Edit by Chiles.
+  Fixed a bug in "Abort Operations" and documented how it works.
+
+.../systems-work/hemlock/mh.lisp, 28-Sep-89 15:37:39, Edit by Chiles.
+  Modified "Headers Delete Message" to be prepared to deal with a list of
+  message ID's when in a message buffer.
+
+.../systems-work/hemlock/eval-server.lisp, 22-Sep-89 11:28:02, Edit by Chiles.
+  Made SERVER-COMPILE-TEXT do a TERPRI on error-output since the background
+  buffer was incredibly hard to read when compiling single defuns.
+
+.../systems-work/hemlock/rompsite.lisp, 20-Sep-89 00:39:06, Edit by Chiles.
+  Installed WITHOUT-HEMLOCK from code:lispinit.lisp.  This had to be part of
+  Hemlock, as it should have been, so expansions of it during compilation of
+  Hemlock would no longer cause hardwired references to bogus "OLD-HI" symbols.
+
+.../systems-work/hemlock/doccoms.lisp, 19-Sep-89 20:15:26, Edit by Chiles.
+.../clisp-1/systems-work/hemlock/echo.lisp, 19-Sep-89 20:06:56, Edit by Chiles.
+  Replaced ~C FORMAT directives with ~:C to adhere to new standard.
+
+/usr2/ch/lisp/echocoms.lisp, 11-Sep-89 21:21:46, Edit by Christopher Hoover.
+  Made "Complete Field" and "Complete Keyword" do the same thing for
+  parse types of :file.
+
+/usr1/lisp/hemlock/searchcoms.lisp, 18-Sep-89 12:56:33, Edit by Chiles.
+  When we fixed QUERY-REPLACE-LOOP to use a permanent marker for the end mark,
+  we destroyed the current region effect when the current mark was before the
+  current point.  I fixed this to be a permanent mark that is a copy of the end
+  mark of the region within which we replace things.
+
+/usr1/lisp/hemlock/mh.lisp, 15-Sep-89 11:30:56, Edit by Chiles.
+  Blew away "-recurse" from CHECK-FOLDER-NAME-TABLE.
+
+/usr1/lisp/hemlock/macros.lisp, 14-Sep-89 12:18:47, Edit by Chiles.
+  Fixed bug in DO-STRINGS introduced with the new string table stuff a few
+  months ago.  It spliced the result form after a DOTIMES instead inside it, so
+  RETURN's inside the DO-STRING's returned the result form instead of the
+  returned values.
+
+/usr/lisp/hemlock/ts-stream.lisp, 13-Sep-89 19:07:27, Edit by Wlott.
+  Fixed bug in %TS-STREAM-SOUT that caused the character position to become
+  confused.
+
+/usr1/lisp/hemlock/lispeval.lisp, 08-Sep-89 11:59:16, Edit by Chiles.
+  Changed "Forget Compiler ..." to "Flush ...".
+
+/usr1/lisp/hemlock/diredcoms.lisp, 03-Sep-89 17:39:07, Edit by Chiles.
+  Stopped DIRED-DOWN-LINE from moving the mark to the beginning of the line.
+
+/usr1/lisp/hemlock/macros.lisp, 01-Sep-89 10:50:03, Edit by Chiles.
+  Proclaimed *buffer-names* special.
+
+/usr1/lisp/hemlock/rompsite.lisp, 27-Aug-89 12:26:44, Edit by Chiles.
+  Removed BUILD-HEMLOCK.  Created load-hem.lisp.
+
+/usr1/lisp/nhem/rompsite.lisp, 25-Aug-89 11:17:01, Edit by Chiles.
+  Added LOAD's for new TCP/eval server files.
+
+  Removed old eval server stuff.
+
+
+/usr1/lisp/nhem/eval-server.lisp, 25-Aug-89 11:16:29, Edit by Chiles.
+  This is a new file.
+
+/usr1/lisp/nhem/ts-stream.lisp, 25-Aug-89 09:56:46, Edit by Chiles.
+  This is a new file.
+
+/usr1/lisp/nhem/ts.lisp, 24-Aug-89 16:35:30, Edit by Chiles.
+  Basically a new file for interfacing to the new typescript streams.
+
+/usr1/lisp/nhem/lispeval.lisp, 24-Aug-89 16:16:25, Edit by Chiles.
+  This is effectively a new file for use with TCP eval servers.
+
+/usr1/lisp/nhem/lispbuf.lisp, 24-Aug-89 16:07:34, Edit by Chiles.
+  Added "Editor" mode to this file.
+
+/usr1/lisp/nhem/edit-defs.lisp, 24-Aug-89 15:57:28, Edit by Chiles.
+  Updated definition fetching code to use DO-EVAL-FORM instead of
+  EVAL_FORM-IN-CLIENT.
+
+/usr1/lisp/nhem/echo.lisp, 24-Aug-89 15:54:00, Edit by Chiles.
+  Moved LOUD-MESSAGE here from lispeval.lisp and exported it.
+
+/usr1/lisp/nhem/bindings.lisp, 24-Aug-89 15:51:31, Edit by Chiles.
+  Commented out binding for "Abort Typescript Input".
+
+  Added bindings for "Next Compiler Error" and "Previous Compiler Error".
+
+  Changed some names "Process Control ..." to "Typescript Slave ...".
+
+
+/usr1/lisp/hemlock/struct.lisp, 16-Aug-89 15:09:14, Edit by Chiles.
+  Removed
+     (:print-function ...)
+  forms for structures that included another structure and explicitly
+  specified the included functions print fucntion.  It is now in the standard
+  and our system that these should automatically be inherited.
+
+/usr1/lisp/nhem/bit-screen.lisp, 28-Jul-89 14:42:20, Edit by Chiles.
+  Blaine fixed his fix to the "Reverse Video" hook for the new pop-up displays.
+
+/usr1/lisp/nhem/morecoms.lisp, 28-Jul-89 13:45:33, Edit by Chiles.
+  Restored old definition of "Capitalize Word" and made it loop until it finds
+  the first alphabetic character in the word instead of assuming the first
+  character is capitalizable.
+
+/usr1/lisp/nhem/filecoms.lisp, 27-Jul-89 10:09:56, Edit by Chiles.
+  Blaine made "Log Change" check that the initial buffer still exists before
+  going to it.
+
+/usr1/lisp/nhem/command.lisp, 26-Jul-89 17:49:32, Edit by Chiles.
+  Rewrote "Universal Argument", "Argument Digit", "Negative Argument".  This
+  fixes the bug M-- M-1 M-2 yielding -8 instead of -12.  Now "Universal
+  Argument" strips bits off every character it reads, and it no longer goes
+  through the command loop on repeated C-U input.  The other two commands
+  basically setup to jump into "Universal Argument".  This means to things:
+     1] You no longer can type minus signs after every C-u.
+     2] When typing digits, you cannot invoke any commands bound to
+        a first digit with modifier bits.  This should be no big deal.
+
+/usr1/lisp/hemlock/syntax.lisp, 14-Jul-89 15:26:51, Edit by Chiles.
+/usr1/lisp/hemlock/buffer.lisp, 14-Jul-89 15:17:25, Edit by Chiles.
+/usr1/lisp/hemlock/vars.lisp, 14-Jul-89 14:31:34, Edit by Chiles.
+/usr1/lisp/hemlock/main.lisp, 14-Jul-89 14:33:27, Edit by Chiles.
+  Moved *global-variable-names* back to main.lisp from vars.lisp since vars is
+  loaded before table.lisp which defines MAKE-STRING-TABLE.
+
+  Moved *buffer-names* and *mode-names* back to main.lisp for above reason.
+
+  *command-names* from interp.
+
+  *character-attribute-names from syntax.
+
+
+/usr1/lisp/nhem/font.lisp, 11-Jul-89 15:49:59, Edit by Chiles.
+  Modified NEW-FONT-MARK to terminate a loop correctly and to stop calling
+  DIS-LINE-LINE on nil.
+
+/../victoria/usr2/lisp/hemlock/bit-screen.lisp, 09-Jul-89 15:51:46, Edit by Mbb.
+  Made REVERSE-VIDEO-HOOK-FUN do the right thing for random typeout
+  windows.  I, uhhhh.., kind of missed this.
+
+  Removed an extraneaous variable binding that was causing a "Bound but not
+  referenced error."
+
+
+/usr1/lisp/nhem/completion.lisp, 07-Jul-89 13:00:47, Edit by Chiles.
+  #\' is no longer a completion-wordchar in "Lisp" mode.  Just an oversight.
+
+/usr/lisp/hemlock/rompsite.lisp, 07-Jul-89 16:18:51, Edit by Mbb.
+  Replaced call to INVOKE-HOOK with DOLIST since this is compiled before
+  macros.lisp, analogous to using VARIABLE-VALUE instead of VALUE.
+
+/usr/lisp/hemlock/htext1.lisp, 07-Jul-89 16:06:08, Edit by Mbb.
+/usr/lisp/hemlock/htext4.lisp, 07-Jul-89 16:06:08, Edit by Mbb.
+  Frobbed MOVE-SOME-MARKS in htext1.lisp to allow declarations within the
+  body.  Added declarations using this macro in htext4.  Also gratuitously
+  changed the indentation in htext4 of MOVE-SOME-MARKS (To screw file
+  comparison.)
+
+/usr/lisp/hemlock/tty-screen.lisp, 07-Jul-89 14:29:53, Edit by Mbb.
+  Renamed MAKE-DEVICE to MAKE-TTY-DEVICE.
+
+/usr/lisp/hemlock/struct.lisp, 07-Jul-89 14:19:16, Edit by Mbb.
+/usr/lisp/hemlock/bit-display.lisp, 07-Jul-89 14:15:42, Edit by Mbb.
+/usr/lisp/hemlock/tty-display.lisp, 07-Jul-89 14:20:47, Edit by Mbb.
+  Moved device and hunk stuff into struct.lisp.
+
+/usr/lisp/hemlock/echo.lisp, 07-Jul-89 11:19:23, Edit by Mbb.
+  Made PROMPTING-MERGE-PATHNAMES work.  It used to choke if
+  pathname-defaults was NIL.
+
+  Moved definition of hemlock-eof from main.lisp to echo.lisp, where it
+  belongs.
+
+
+/usr/lisp/hemlock/rompsite.lisp, 06-Jul-89 16:20:13, Edit by Mbb.
+  Moved constant definition of font-map-size from font.lisp to
+  rompsite.lisp because SETUP-FONT-FAMILY assumed that it was a special.
+
+/usr/lisp/hemlock/rompsite.lisp, 06-Jul-89 13:21:21, Edit by Mbb.
+  Moved definitions of *editor-input*, *last-character-typed*, and
+  *character-history* from main.lisp to rompsite.lisp, where they belong,
+  and exported them.
+
+/usr/lisp/hemlock/window.lisp, 06-Jul-89 13:16:55, Edit by Mbb.
+  Moved definitions of *current-window* and *window-list* from main.lisp to
+  window.lisp, exporting *window-list*.
+
+/usr/lisp/hemlock/interp.lisp, 06-Jul-89 13:09:29, Edit by Mbb.
+  Moved definitions of *command-names*, *prefix-argument-supplied*, and
+  *prefix-argument* from main.lisp to interp.lisp, exporting *command-names*.
+
+/usr/lisp/hemlock/buffer.lisp, 06-Jul-89 12:59:36, Edit by Mbb.
+  Moved definitions of *buffer-names*, *buffer-list*, *current-buffer*, and
+  *mode-names* from main.lisp to buffer.lisp, exporting all but
+  *current-buffer*.
+
+/usr/lisp/hemlock/vars.lisp, 06-Jul-89 12:09:46, Edit by Mbb.
+  Moved definition of *global-variable-names* from main.lisp to vars.lisp,
+  where it belongs, and exported it.
+
+/usr/lisp/hemlock/syntax.lisp, 06-Jul-89 11:57:48, Edit by Mbb.
+  Moved *last-character-attibute-requested*, *character-attribute-names*,
+  *value-of-last-character-attribute-requested*, and *character-attributes*
+  from main.lisp to syntax.lisp, exporting *character-attribute-names*.
+
+  Proclaimed the following variables special:
+  (*mode-names* *current-buffer* *last-character-attribute-requested*
+   *value-of-last-character-attribute-requested*).
+
+
+/usr/lisp/hemlock/struct.lisp, 06-Jul-89 11:48:59, Edit by Mbb.
+  Removed definitions of now-tick and TICK and put them in htext1.lisp,
+  exporting now-tick.
+
+/usr/lisp/hemlock/killcoms.lisp, 06-Jul-89 09:40:29, Edit by Mbb.
+  Proclaimed the following variable special:  *delete-char-region*.  
+
+/usr/lisp/hemlock/echocoms.lisp, 06-Jul-89 09:33:57, Edit by Mbb.
+  Proclaimed the following variable special:  *kill-ring*.
+
+/usr/lisp/hemlock/window.lisp, 05-Jul-89 16:39:31, Edit by Mbb.
+  Proclaimed the following variable special:  *buffer-list*.
+
+/usr/lisp/hemlock/tty-screen.lisp, 05-Jul-89 16:37:06, Edit by Mbb.
+  Proclaimed the following variable special:  *parse-starting-mark*.
+
+/usr/lisp/hemlock/screen.lisp, 05-Jul-89 16:30:31, Edit by Mbb.
+  Proclaimed the following variable special:  *echo-area-buffer*.  
+
+/usr/lisp/hemlock/display.lisp, 05-Jul-89 16:28:18, Edit by Mbb.
+  Proclaimed the following variable special:  *window-list*.  
+
+  Moved device and hunk structure definitions to struct.lisp.
+
+
+/usr/lisp/hemlock/hunk-draw.lisp, 05-Jul-89 16:24:18, Edit by Mbb.
+  Proclaimed the following variables special:
+  (*default-border-pixmap* *highlight-border-pixmap*).  
+
+/usr/lisp/hemlock/cursor.lisp, 05-Jul-89 16:15:50, Edit by Mbb.
+  Proclaimed the following variable special:  the-sentinel.  
+
+/usr/lisp/hemlock/linimage.lisp, 05-Jul-89 16:12:41, Edit by Mbb.
+  Proclaimed the following variable special:  *character-attributes*.  
+
+/usr/lisp/hemlock/macros.lisp, 05-Jul-89 16:10:00, Edit by Mbb.
+  Proclaimed the following variable special:  *echo-area-stream*.
+
+/usr/lisp/hemlock/rompsite.lisp, 05-Jul-89 16:02:53, Edit by Mbb.
+  Proclaimed the following variables special:
+  (FONT-MAP-SIZE *DEFAULT-FONT-FAMILY* *CURRENT-WINDOW* *INPUT-TRANSCRIPT*
+   *FOREGROUND-BACKGROUND-XOR* *ECHO-AREA-WINDOW* *BUFFER-NAMES*
+   HEMLOCK::*CREATED-SLAVE-CONNECTED* *CHARACTER-HISTORY*
+   *SCREEN-IMAGE-TRASHED*).
+
+/usr/lisp/hemlock/struct-ed.lisp, 05-Jul-89 15:42:36, Edit by Mbb.
+/usr/lisp/hemlock/lispeval.lisp, 05-Jul-89 15:42:36, Edit by Mbb.
+  Created this file for structures that are only used in the HEMLOCK
+  package.  Moved SERVER-INFO structure from lispeval.lisp to this file.
+
+/usr/lisp/hemlock/rompsite.lisp, 05-Jul-89 15:34:21, Edit by Mbb.
+  Moved the package initialization stuff from rompsite.lisp to ctw.lisp, as
+  this is where it should be.
+
+/usr2/lisp/hemlock/pop-up-stream.lisp, 05-Jul-89 14:07:55, Edit by Mbb.
+/usr2/lisp/hemlock/struct.lisp, 05-Jul-89 14:07:55, Edit by Mbb.
+  Moved the POP-UP-STREAM structure to struct.lisp.
+
+/usr1/mbb/lisp/work/screen.lisp, 03-Jul-89 17:05:58, Edit by Mbb.
+  Made RANDOM-TYPEOUT-CLEANUP clean up the modeline field instead of doing
+  it in both the tty and bitmap cleanup methods.
+
+/usr1/mbb/lisp/work/pop-up-stream.lisp, 03-Jul-89 15:53:13, Edit by Mbb.
+  Made misc methods for line-buffered and full-buffered streams distinct.
+  FORCE-OUTPUT and FINISH-OUTPUT are now no-ops for full-buffered streams.
+
+/usr1/mbb/lisp/work/macros.lisp, 03-Jul-89 15:43:19, Edit by Mbb.
+  Made GET-RANDOM-TYPEOUT-INFO assign distinct misc methods to
+  full-buffered and line-buffered random-typeout streams.
+
+/usr1/lisp/nhem/window.lisp, 02-Jul-89 15:54:40, Edit by Chiles.
+  Added "Maximum Modeline Pathname Length" which defaults to nil.  Wrote
+  BUFFER-PATHNAME-ML-FIELD-FUN.
+
+/usr1/lisp/nhem/morecoms.lisp, 02-Jul-89 16:09:45, Edit by Chiles.
+  Made "Defhvar" propagate any existing hooks as well.
+
+/usr1/lisp/nhem/vars.lisp, 02-Jul-89 15:04:33, Edit by Chiles.
+/usr1/lisp/nhem/syntax.lisp, 02-Jul-89 15:02:25, Edit by Chiles.
+/usr1/lisp/nhem/main.lisp, 02-Jul-89 14:55:14, Edit by Chiles.
+/usr1/lisp/nhem/display.lisp, 02-Jul-89 14:43:59, Edit by Chiles.
+/usr1/lisp/nhem/buffer.lisp, 02-Jul-89 14:38:55, Edit by Chiles.
+  Replaced occurrences of DOLIST used to invoke hook functions with the new
+  INVOKE-HOOK.
+
+/usr1/lisp/nhem/window.lisp, 02-Jul-89 15:06:35, Edit by Chiles.
+/usr1/lisp/nhem/vars.lisp, 02-Jul-89 15:04:33, Edit by Chiles.
+/usr1/lisp/nhem/syntax.lisp, 02-Jul-89 15:02:25, Edit by Chiles.
+/usr1/lisp/nhem/searchcoms.lisp, 02-Jul-89 14:59:43, Edit by Chiles.
+/usr1/lisp/nhem/screen.lisp, 02-Jul-89 14:58:52, Edit by Chiles.
+/usr1/lisp/nhem/rompsite.lisp, 02-Jul-89 14:57:44, Edit by Chiles.
+/usr1/lisp/nhem/mh.lisp, 02-Jul-89 14:56:23, Edit by Chiles.
+/usr1/lisp/nhem/main.lisp, 02-Jul-89 14:55:14, Edit by Chiles.
+/usr1/lisp/nhem/interp.lisp, 02-Jul-89 14:52:04, Edit by Chiles.
+/usr1/lisp/nhem/htext1.lisp, 02-Jul-89 14:49:28, Edit by Chiles.
+/usr1/lisp/nhem/filecoms.lisp, 02-Jul-89 14:41:23, Edit by Chiles.
+/usr1/lisp/nhem/buffer.lisp, 02-Jul-89 14:36:54, Edit by Chiles.
+/usr1/lisp/nhem/bit-screen.lisp, 02-Jul-89 14:33:21, Edit by Chiles.
+  Replaced occurrences of
+     "invoke-hook* '"
+  with
+     "invoke-hook ".
+
+  Replaced occurrences of
+     "invoke-hook '"
+  with
+     "invoke-hook ".
+
+
+/usr1/lisp/nhem/vars.lisp, 02-Jul-89 14:30:55, Edit by Chiles.
+  Deleted function definition for INVOKE-HOOK.
+
+/usr1/lisp/nhem/macros.lisp, 02-Jul-89 13:45:37, Edit by Chiles.
+  Wrote macro INVOKE-HOOK that replaces INVOKE-HOOK* and is exported.
+
+/usr1/lisp/nhem/bit-screen.lisp, 29-Jun-89 11:26:19, Edit by Chiles.
+  Fixed INIT-BITMAP-DEVICE to drop any pending events on the floor, so
+  accidental input while not in Hemlock is ignored.
+
+/usr1/lisp/nhem/lispeval.lisp, 29-Jun-89 10:54:17, Edit by Chiles.
+  Made default value for "Remote Compile File" be nil.
+
+/usr1/lisp/nhem/window.lisp, 29-Jun-89 10:43:26, Edit by Chiles.
+  Moved the :modifiedp modeline-field to be between the modes and buffer name.
+  Modified the :modifiedp and :buffer-pathname update functions accordingly.
+
+/usr1/lisp/nhem/macros.lisp, 29-Jun-89 10:12:25, Edit by Chiles.
+  Fixed GET-RANDOM-TYPEOUT-INFO: it now supplies "Fundamental" only for the
+  random typeout buffer's modes, and the delete hook is now a compiled function
+  instead of interpreted.
+
+/usr1/lisp/nhem/pop-up-stream.lisp, 28-Jun-89 16:41:56, Edit by Chiles.
+  Fixed a bug in RANDOM-TYPEOUT-MISC that called redisplay on the pop-up window
+  when it didn't exist.  When the stream is full-buffered, and no previous
+  random typeout has occurred for a given buffer, the window slot in the stream
+  is nil.  This should be fixed better than I have done.
+
+/usr1/lisp/nhem/lispmode.lisp, 28-Jun-89 16:38:40, Edit by Chiles.
+  Added DEFINDENT for WITH-POP-UP-DISPLAY.
+
+/usr1/mbb/lisp/work/bit-screen.lisp, 22-Jun-89 20:11:59, Edit by Mbb.
+  The device dependant random-typeout-cleanup methods were fixing up the
+  modeline, but this is device independant, so I moved it to screen.lisp.
+
+/usr1/mbb/lisp/work/screen.lisp, 22-Jun-89 19:58:08, Edit by Mbb.
+  RANDOM-TYPEOUT-CLEANUP now sets the Random Typeout buffer's modeline
+  field to :normal.  Before it lost on a Keep character in a more.
+
+/usr1/mbb/lisp/work/pop-up-stream.lisp, 22-Jun-89 19:48:12, Edit by Mbb.
+  Fixed NO-TEXT-PAST-BOTTOM-P to work.  It previously choked when there
+  were no newlines in the buffer.
+
+/usr1/mbb/lisp/work/rompsite.lisp, 22-Jun-89 19:45:54, Edit by Mbb.
+  Made END-RANDOM-TYPEOUT do a more-prompt, in case the user didn't give us
+  a newline on his last line of output.  This was previously a bug.
+
+/usr1/mbb/lisp/work/morecoms.lisp, 22-Jun-89 16:21:43, Edit by Mbb.
+  Made "Capitalize Word" consistent with "Uppercase Word" and "Lowercase
+  Word".  Someone failed to see how easy this was.
+
+/usr1/mbb/lisp/work/diredcoms.lisp, 22-Jun-89 13:15:07, Edit by Mbb.
+/usr1/mbb/lisp/work/rompsite.lisp, 22-Jun-89 13:18:00, Edit by Mbb.
+  Moved DIRECTORYP from diredcoms.lisp to rompsite.lisp.  This is a
+  generally useful function.
+
+/usr1/lisp/nhem/searchcoms.lisp, 22-Jun-89 16:29:05, Edit by Chiles.
+  Fixed a bug in the termination test of the replacement loop.  It used to use
+  a temporary mark to hold onto the end of the region which lost with multiple
+  replacements on the last line with the end of the region at the end of the
+  line.
+
+/usr1/lisp/nhem/bufed.lisp, 22-Jun-89 16:26:59, Edit by Chiles.
+  Made DELETE-BUFED-BUFFERS a buffer local hook for the bufed buffer.
+
+/usr1/mbb/lisp/work/filecoms.lisp, 22-Jun-89 10:43:51, Edit by Mbb.
+  PATHNAME-TO-BUFFER-NAME now returns a string in the form of
+  <file-namestring pathname> <directory-namestring> pathname.
+
+  Deleted *name/type-separator-character*.
+
+
+/usr1/mbb/lisp/work/echocoms.lisp, 21-Jun-89 17:05:36, Edit by Mbb.
+  "Complete Keyword" now only merges with the directory of the default, as
+  opposed to the whole thing.  This makes completion look more like the new
+  confirmation.
+
+/usr1/mbb/lisp/work/morecoms.lisp, 21-Jun-89 21:45:05, Edit by Mbb.
+  Made "List Buffers" tabulate it's output.  It looks better that way.
+
+/usr1/mbb/lisp/work/echo.lisp, 21-Jun-89 15:50:43, Edit by Mbb.
+  Made FILE-VERIFICATION-FUNCTION allow merging of relative pathnames and
+  nearly honest-to-goodness UNIX pathnames.  Eliminated all file-name and
+  file-type merging, only merging with default directory.  However, if the user
+  only inputs a directory spec, then he could only mean to pick up the
+  file-namestring from the defaults.
+
+/usr1/mbb/lisp/work/mh.lisp, 21-Jun-89 11:36:24, Edit by Mbb.
+/usr1/mbb/lisp/work/rompsite.lisp, 21-Jun-89 11:41:52, Edit by Mbb.
+  I moved MERGE-RELATIVE-PATHNAMES from mh.lisp to rompsite.lisp and
+  exported it for its general usefulness.
+
+/usr1/lisp/hemlock/bindings.lisp, 21-Jun-89 13:44:07, Edit by Chiles.
+  Added bindings for "Completion" mode.
+
+/usr1/lisp/nhem/mh.lisp, 19-Jun-89 18:58:03, Edit by Chiles.
+  Modified MH once again to supply nil and nil for the group and account
+  information to RFS-AUTHENTICATE.
+
+/usr1/lisp/nhem/bindings.lisp, 19-Jun-89 16:28:48, Edit by Chiles.
+  Changed binding of "Select Random Typeout Buffer".
+
+/usr1/lisp/nhem/morecoms.lisp, 19-Jun-89 16:26:21, Edit by Chiles.
+  "List Buffers" no longer shows random typeout buffers.
+
+/usr1/mbb/lisp/work/pop-up-stream.lisp, 19-Jun-89 14:02:04, Edit by Mbb.
+  Made line-buffered-moreing work.  A last minute fix before I it went into
+  the last core broke this.
+
+/usr1/mbb/lisp/work/pop-up-stream.lisp, 18-Jun-89 13:26:12, Edit by Mbb.
+  Added :charpos feature to the RANDOM-TYPEOUT-MISC method because format
+  uses it to implement tabbing.
+
+/usr1/mbb/lisp/work/lispbuf.lisp, 18-Jun-89 12:19:52, Edit by Mbb.
+  Made "Editor Describe Function Call" not supply a height to
+  WITH-POP-UP-DISPLAY.
+
+/usr1/mbb/lisp/work/spellcoms.lisp, 16-Jun-89 17:47:30, Edit by Mbb.
+  Added a height specification to the WITH-POP-UP-DISPLAY call in
+  GET-WORD-CORRECTION so the stream would be line-buffered, and thus visible.
+
+/usr1/mbb/lisp/work/macros.lisp, 16-Jun-89 17:27:38, Edit by Mbb.
+/usr1/mbb/lisp/work/pop-up-stream.lisp, 16-Jun-89 17:27:08, Edit by Mbb.
+  Added FORCE-OUTPUT and FINISH-OUTPUT functionality to Random Typeout
+  Streams.
+
+/usr1/mbb/lisp/work/morecoms.lisp, 16-Jun-89 17:24:15, Edit by Mbb.
+  Made "Point to here" issue the traditional "I'm afraid I can't let you do
+  that Dave." message when the usere tries to make the special Random
+  Typeout window current.
+
+/usr1/lisp/hemlock/diredcoms.lisp, 16-Jun-89 01:20:44, Edit by Chiles.
+  Fixed "Copy File" and "Rename File" to no longer think they run in dired
+  buffers.
+
+/usr1/lisp/hemlock/bindings.lisp, 16-Jun-89 01:07:54, Edit by Chiles.
+  Added binding for "Select Random Typeout Buffer".
+
+/usr1/lisp/hemlock/bindings.lisp, 15-Jun-89 16:59:15, Edit by Chiles.
+  Defined #\K to be a :keep logical character.
+
+/usr1/lisp/hemlock/echo.lisp, 15-Jun-89 16:43:16, Edit by Chiles.
+  Added definition for "Keep" logical character.
+
+/usr1/lisp/nhem/mh.lisp, 15-Jun-89 13:14:00, Edit by Chiles.
+  Modified INCORPORATE-NEW-MAIL to better detect mistyped passwords with new MH
+  error messages.
+
+/usr/lisp/hemlock/lisp-lib.lisp, 12-Jun-89 14:55:16, Edit by Mbb.
+  Made "Lisp Library Help" consistent with "Bufed" and other modes that now
+  use the mode-description mechanism.
+
+/usr/lisp/hemlock/window.lisp, 07-Jun-89 16:56:02, Edit by Mbb.
+  Fixed a bug in WINDOW-FOR-HUNK that prevented anyone from making a window
+  1 character high.
+
+/usr/lisp/hemlock/pop-up-stream.lisp, 07-Jun-89 19:10:17, Edit by Mbb.
+  This file replaces tty-stream.lisp and bit-stream.lisp and does essentially
+  the same thing, but in a completely different way.
+
+/usr/lisp/hemlock/display.lisp, 07-Jun-89 18:32:56, Edit by Mbb.
+  Added two slots to the device structure: random-typeout-full-more and
+  random-typeout-line-more.  These are called from the random typeout
+  stream output methods to give users a neat scrolling effect on a bitmap, and
+  on the tty they just clear the window and draw some more lines from the top.
+
+/usr/lisp/hemlock/display.lisp, 07-Jun-89 18:32:56, Edit by Mbb.
+  Made %PRINT-DEVICE-HUNK not choke when the hunk has no associated window.
+
+/usr/lisp/hemlock/mh.lisp, 07-Jun-89 18:30:05, Edit by Mbb.
+  Made the NEW-MAIL-BUF-DELETE-HOOK ignore buffer so the compiler doesn't
+  warn that it was "bound but not referenced".
+
+/usr/lisp/hemlock/bit-screen.lisp, 07-Jun-89 14:52:45, Edit by Mbb.
+  Made BITMAP-RANDOM-TYPEOUT-SETUP create a psuedo-window to display a random
+  typeout buffer.  Also made BITMAP-RANDOM-TYPEOUT-CLEANUP do the right
+  thing.  Two functions were added to deal with the pseudo-window:
+  MAKE-TTY-RANDOM-TYPEOUT-WINDOW and CHANGE-TTY-RANDOM-TYPEOUT-WINDOW.
+
+/usr/lisp/hemlock/tty-screen.lisp, 07-Jun-89 14:26:48, Edit by Mbb.
+  Made TTY-RANDOM-TYPEOUT-SETUP create a psuedo-window to display a random
+  typeout-buffer.  Also made TTY-RANDOM-TYPEOUT-CLEANUP do the right thing.
+  Two functions were added to deal with the psuedo-window :
+  MAKE-BITMAP-RANDOM-TYPEOUT-WINDOW and CHANGE-BITMAP-RANDOM-TYPEOUT-WINDOW.
+
+/usr/lisp/hemlock/screen.lisp, 07-Jun-89 15:07:50, Edit by Mbb.
+  Modified PREPARE-FOR-RANDOM-TYPEOUT and RANDOM-TYPEOUT-CLEANUP to
+  implement the new mechanism.  Also added the modeline field definitions
+  for random typeout buffers.
+
+/usr1/lisp/nhem/keytran.lisp, 05-Jun-89 12:53:12, Edit by Chiles.
+  Fixed a bugt in DEFINE-KEYSYM that alwyas ignores shifted characters.
+
+/usr1/lisp/nhem/rompsite.lisp, 02-Jun-89 11:54:20, Edit by Chiles.
+  Made FUN-DEFINED-FROM-PATHNAME not string-downcase the file.
+
+/usr/lisp/hemlock/spellcoms.lisp, 31-May-89 20:46:54, Edit by Mbb.
+/usr/lisp/hemlock/searchcoms.lisp, 31-May-89 20:44:59, Edit by Mbb.
+/usr/lisp/hemlock/scribe.lisp, 31-May-89 20:44:14, Edit by Mbb.
+/usr/lisp/hemlock/register.lisp, 31-May-89 20:42:46, Edit by Mbb.
+/usr/lisp/hemlock/morecoms.lisp, 31-May-89 20:41:30, Edit by Mbb.
+/usr/lisp/hemlock/mh.lisp, 07-Jun-89 18:30:05, Edit by Mbb.
+/usr/lisp/hemlock/lispeval.lisp, 31-May-89 20:36:12, Edit by Mbb.
+/usr/lisp/hemlock/lispbuf.lisp, 31-May-89 20:30:34, Edit by Mbb.
+/usr/lisp/hemlock/lisp-lib.lisp, 12-Jun-89 14:55:16, Edit by Mbb.
+/usr/lisp/hemlock/filecoms.lisp, 31-May-89 20:21:59, Edit by Mbb.
+/usr/lisp/hemlock/echocoms.lisp, 31-May-89 20:19:14, Edit by Mbb.
+/usr/lisp/hemlock/echo.lisp, 05-Jun-89 15:58:14, Edit by Mbb.
+/usr/lisp/hemlock/doccoms.lisp, 31-May-89 20:13:38, Edit by Mbb.
+/usr/lisp/hemlock/abbrev.lisp, 31-May-89 19:55:20, Edit by Mbb.
+  Changed occurences of WITH-RANDOM-TYPEOUT to WITH-POP-UP-DISPLAY.
+
+/usr1/lisp/nhem/bit-screen.lisp, 31-May-89 21:41:02, Edit by Chiles.
+  The following functions were modified to accomodate using the extra space at
+  the bottom of a window when there is no thumb bar:
+     WRITE-N-EXPOSED-REGIONS
+     WRITE-ONE-EXPOSED-REGION
+     HUNK-PROCESS-INPUT
+     MAYBE-PROMPT-USER-FOR-WINDOW
+     BITMAP-RANDOM-TYPEOUT-SETUP   *** Merge with Blaine.
+     DEFAULT-CREATE-WINDOW-HOOK
+     DEFAULT-CREATE-INITIAL-WINDOWS-HOOK
+     BITMAP-MAKE-WINDOW
+     SET-HUNK-SIZE
+
+/usr/lisp/hemlock/macros.lisp, 31-May-89 19:29:21, Edit by Mbb.
+  Defined the macro WITH-POP-UP-DISPLAY that replaces WITH-RANDOM-TYPEOUT.
+  The new machanism stuffs output into a real hemlock buffer and a pseudo
+  window so users can get to it if they need to.
+
+/usr/lisp/hemlock/rompsite.lisp, 31-May-89 15:35:11, Edit by Mbb.
+  Rewrote WAIT-FOR-MORE and END-RANDOM-TYPEOUT, and added
+  MAYBE-KEEP-RANDOM-TYPEOUT-WINDOW, that will finish output and keep the
+  random typeout window if we're on a bitmap-device.
+
+  Added random-typeout-xevents-mask constant.
+
+
+/usr1/lisp/nhem/hunk-draw.lisp, 31-May-89 14:19:46, Edit by Chiles.
+  Introduced hunk-thumb-bar-bottom-border, 10, and set hunk-bottom-border to 3.
+  Modified hunk-draw-bottom-border accordingly.
+
+/usr1/lisp/nhem/bit-screen.lisp, 31-May-89 10:00:56, Edit by Chiles.
+  Modified HUNK-PROCESS-INPUT to use extra bits below bottom line and above
+  thumb bar as part of the bottom line.  This should eliminate problems with
+  mouse scrolling and point-to-here functionality which otherwise would beep
+  causing the user to move the mouse up a tiny bit.
+
+/usr1/lisp/nhem/lispbuf.lisp, 26-May-89 14:21:11, Edit by Chiles.
+  Made "Select Eval Buffer" supply a buffer local delete hook that sets the
+  special to nil, so Hemlock doesn't hold onto that memory.
+
+/usr1/lisp/nhem/buffer.lisp, 26-May-89 14:18:50, Edit by Chiles.
+  Modified MAKE-BUFFER to check the type of the :delete-hook arg.
+
+/usr1/ch/lisp/complete/table.lisp, 17-Apr-89 18:41:11, Edit by Hoover.
+  Exported STRING-TABLE-SEPARATOR.
+
+  Fixed a bug in FIND-LONGEST-COMPLETION which made COMPLETE-STRING
+  think some :COMPLETE completions were :UNIQUE.
+
+
+/usr1/lisp/nhem/mh.lisp, 19-May-89 17:36:03, Edit by Chiles.
+/usr1/lisp/nhem/dired.lisp, 19-May-89 17:34:35, Edit by Chiles.
+  Replaced all %SES-NAMESTRING uses with NAMESTRING.
+
+/usr1/lisp/nhem/unixcoms.lisp, 17-May-89 11:53:05, Edit by Chiles.
+  Made SCRIBE-FILE move the buffer's point to the end of the buffer.  This
+  still does not do everything you want:
+     Queue multiple scribe requests.
+     Leave a stream around all the time that gets cleaned up when the
+        buffer is deleted, so it can have a disjoint mark from the buffer's
+        point.  The stream is made whenever the buffer is made.
+
+/usr1/lisp/nhem/diredcoms.lisp, 15-May-89 17:04:50, Edit by Chiles and MBB.
+  Added "Dired Information" variable and structure instead of N buffer local
+  variables.  Fixed a couple bugs.  Modified "Dired" to correctly handle
+  file-namestring patterns ... prompts separately with argument.  Must prompt
+  separately because cannot know user's intent and must canonicalize names for
+  uniqueness when looking up dired buffers.
+
+/usr1/lisp/nhem/xcoms.lisp, 12-May-89 11:35:24, Edit by Chiles.
+  Fixed bug in "Stack Window", paren mismatched.
+
+/usr1/lisp/nhem/struct.lisp, 11-May-89 13:41:38, Edit by Chiles.
+  Modified font-mark printing to use double quotes instead of ``''.
+
+/usr1/lisp/nhem/interp.lisp, 11-May-89 13:40:05, Edit by Chiles.
+  Modified command printing to use double quotes instead of ``''.
+
+/usr1/lisp/nhem/htext2.lisp, 11-May-89 13:37:22, Edit by Chiles.
+  Modified line, mark, region, and buffer print functions to use double quotes
+  instead of Scribe ligatures, ``''.  Fixed a bug in mark printing that wrote
+  its last string to *standard-output* instead of the given stream.
+
+/usr1/lisp/hemlock/mh.lisp, 05-May-89 17:01:39, Edit by DBM.
+  Wrote "Message Help", "Headers Help", and "Draft Help".
+
+/usr1/lisp/hemlock/bindings.lisp, 05-May-89 17:03:56, Edit by Chiles.
+  Added bindings for "Message Help", "Headers Help", and "Draft Help".
+
+/usr1/lisp/nhem/dired.lisp, 02-May-89 14:20:43, Edit by Chiles.
+  Fixed a bug in RENAME-FILE not handling a pattern and directory spec
+  combination correctly.
+
+/usr1/lisp/nhem/mh.lisp, 26-Apr-89 14:48:45, Edit by Chiles.
+  Modified doc strings to work better with "Describe Mode".
+
+/usr1/lisp/nhem/echo.lisp, 25-Apr-89 15:21:21, Edit by Chiles.
+  Modified PROMPT-FOR-VAR to call CURRENT-VARIABLE-TABLES.  Modified
+  PROMPT-FOR-FILE to look for the typein in the default directory before
+  merging with the defaults and taking that potentially non-existent file.
+  Re-order a bunch of stuff and cleaned up page titles.
+
+/usr1/lisp/nhem/bindings.lisp, 25-Apr-89 13:18:42, Edit by Chiles.
+  Removed binding (bind-key "Do Nothing" #\super-leftup :mode "Bufed").
+
+/usr1/lisp/nhem/bindings.lisp, 24-Apr-89 15:44:17, Edit by Chiles.
+  Added "View" mode bindings similar to "Message" mode bindings.
+
+/usr1/lisp/nhem/morecoms.lisp, 24-Apr-89 14:46:36, Edit by Chiles.
+  Modified "Generic Pointer Up" and "Point to Here".
+
+/usr1/lisp/nhem/bufed.lisp, 24-Apr-89 14:41:51, Edit by Chiles.
+  Modified "Bufed Goto and Quit".
+
+/usr1/lisp/nhem/interp.lisp, 24-Apr-89 14:09:41, Edit by Chiles.
+  Modified BIND-KEY to provide a restart before signalling an non-existent
+  command error.
+
+/usr1/lisp/nhem/searchcoms.lisp, 20-Apr-89 18:35:53, Edit by Chiles.
+  Rewrote QUERY-REPLACE-FUNCTION, modifying REPLACE-THAT-CASE and creating
+  QUERY-REPLACE-LOOP, to clean things up.  Fixed bug in return values that
+  broke "Group Query Replace".
+
+/usr1/lisp/nhem/spellcoms.lisp, 19-Apr-89 14:40:36, Edit by Chiles.
+  Modified CORRECT-BUFFER-WORD-END to return values other than nil when end and
+  start were only one character apart.
+
+/usr1/lisp/hemlock/diredcoms.lisp, 18-Apr-89 14:23:38, Edit by Chiles.
+  Modified ARRAY-ELEMENT-FROM-MARK to no longer move the mark argument
+  since it can correctly count the number of lines in the region anyway.
+
+/usr1/lisp/nhem/diredcoms.lisp, 18-Apr-89 11:11:21, Edit by Chiles.
+  Rewrote "View Return" and "View Quit" since they didn't interact correctly.
+
+/usr1/lisp/nhem/xcoms.lisp, 17-Apr-89 15:48:58, Edit by Chiles.
+  Fixed bug in "Stack Window".  It now signals an editor-error unless the
+  device is a hi::bitmap-device.  This command probably should be deleted since
+  it is somewhat silly and written only for one person.
+
+/usr1/lisp/nhem/filecoms.lisp, 12-Apr-89 15:19:52, Edit by Chiles.
+  Made "Revert File" keep buffer's pathname when reverting to checkpoint file.
+
+/usr1/lisp/nhem/bindings.lisp, 12-Apr-89 14:48:52, Edit by Chiles.
+  Added binding for "Select Scribe Warnings".
+
+  Deleted bindings of "Goto Dired Buffer" and "Goto Dired Buffer Quitting".
+  Added "View" mode bindings for "View Return" and "View Quit".
+
+
+/usr1/lisp/nhem/struct.lisp, 12-Apr-89 14:14:12, Edit by Chiles.
+  Exported and provided a doc string for BUFFER-DELETE-HOOK.
+
+/usr1/mbb/lisp/nhem/searchcoms.lisp, 11-Apr-89 13:44:13, Edit by Blaine.
+  Made "Query Replace" and "Replace String" echo how many occurrences are
+  replaced.
+
+/usr1/mbb/lisp/nhem/searchcoms.lisp, 11-Apr-89 13:44:13, Edit by Blaine.
+  Made the doc-strings for "List Matching Lines", "Delete Matcing Lines",
+  "Delete Non-matching Lines", "Count Occurrences", "Replace String", and
+  "Query Replace" indicate that they are sensitive to the active-region.
+
+/usr1/mbb/lisp/nhem/scribe.lisp, 10-Apr-89 22:30:25, Edit by Blaine.
+  Wrote the "Select Scribe Warnings", which goes to the buffer named "Scribe
+  Warnings" if it exists.
+
+/usr1/mbb/lisp/nhem/lisp-lib.lisp, 10-Apr-89 21:39:51, Edit by Blaine.
+  Made "Describe Library Entry" and "Desribe Pointer Library Entry" put the
+  user in view mode instead of normal editing mode.  Also added the command
+  ARRAY-ELEMENT-FROM-POINTER-Y-POS which returns an array element whose index
+  is determined by the y position, in lines, of the pointer.
+
+/usr1/mbb/lisp/nhem/bufed.lisp, 10-Apr-89 21:29:20, Edit by Blaine.
+  Fixed a few bugs in Bufed.  Made "Bufed Undelete" replace #\D with #\space.
+  Made "Bufed Goto and Quit" use the pointer location instead of the
+  current-point.  Also made bufed not move the current-point.
+
+/usr1/mbb/lisp/nhem/diredcoms.lisp, 11-Apr-89 13:22:44, Edit by Blaine.
+  Fixed bug in UPDATE-DIRED-BUFFER.  I was setting "Dired Buffer Files" inside
+  of a dotimes when it should have been outside.
+
+  Deleted commands "Goto Dired Buffer" and "Goto Dired Buffer Quitting" in lieu
+  of "View REturn" and "View Quit".
+
+  Wrote "Dired from Buffer Pathname".
+
+
+/usr1/lisp/nhem/mh.lisp, 10-Apr-89 10:20:42, Edit by Chiles.
+  Modified SUB-WRITE-MH-SEQUENCE to bind *print-base* to 10 when writing
+  message ID's.
+
+/usr1/ch/lisp/spell/spell-build.lisp, 08-Apr-89 16:55:52, Edit by Hoover.
+  Increased max-entry-count-estimate to 15600 in order to build the new
+  dictionary.  Updated filenames in comments and added a line specifying
+  compilation dependencies.
+
+  Picked up the latest ispell dictionary and merged in local favorites.
+  This dictionary is available via anonymous ftp from celray.cs.yale.edu
+  (128.36.0.25) and locally as /../m/usr/misc/.ispell/src/dict.191.
+
+/usr1/lisp/nhem/lispmode.lisp, 07-Apr-89 16:25:51, Edit by Chiles.
+  Added DEFINDENT for WITH-WRITABLE-BUFFER.
+
+/usr1/lisp/nhem/diredcoms.lisp, 07-Apr-89 16:22:05, Edit by Chiles.
+  Modifed INITIALIZE-DIRED-BUFFER and "Dired" to beep and blow off the dired
+  when no entries satisfy the spec.
+
+/usr1/lisp/nhem/echocoms.lisp, 07-Apr-89 10:49:09, Edit by Chiles.
+  Added "ps" to "Ignore File Types".
+
+/usr1/lisp/nhem/mh.lisp, 04-Apr-89 00:16:54, Edit by Chiles.
+  Wrote GET-STORABLE-MSG-BUF-NAME and used it inside SHOW-HEADERS-MESSAGE and
+  SHOW-MESSAGE-OFFSET-MSG-BUF.
+
+  Removed variable "Deliver Message Deleting Buffers".  I modified
+  DELIVER-DRAFT-BUFFER-MESSAGE to ignore it.  This now also always deletes the
+  draft buffer, regardless of whether this variable is re-installed.  Now the
+  message buffer is always deleted unless it is kept.  "Delete Draft and
+  Buffer" now also always deletes the message buffer unless it is kept.  IF the
+  variable is re-installed this deletion will be guarded by it as well.
+
+
+/usr1/lisp/nhem/bindings.lisp, 03-Apr-89 12:21:51, Edit by Chiles.
+  Changed binding of "Define Keyboard Macro Key" to C-x M-(.
+
+/usr1/lisp/nhem/bindings.lisp, 02-Apr-89 16:44:54, Edit by Chiles.
+  Fixed mail bindings that got switched up or something, "Next Message", "Next
+  Undeleted Message", "Previous Message", "Previous Undeleted Message".
+
+/usr1/lisp/nhem/bindings.lisp, 01-Apr-89 16:38:10, Edit by Chiles.
+  Bound "Bufed" to C-x C-M-b, and changed some c-'s to control-'s.
+
+/usr1/lisp/nhem/morecoms.lisp, 31-Mar-89 18:24:30, Edit by Chiles.
+  Wrote "Generic Pointer Up" to replace "Push Mark/Point to Here" and added
+  ADD-GENERIC-POINTER-UP-FUNCTION.  Modified "Point to Here" in accordance.
+
+/usr1/lisp/nhem/bufed.lisp, 31-Mar-89 18:34:40, Edit by Chiles.
+  Fixed "Bufed Goto and Quit".  Modified "Bufed" to move point to the beginning
+  of the buffer.
+
+/usr1/lisp/nhem/bindings.lisp, 31-Mar-89 18:27:02, Edit by Chiles.
+  Changed bindings of "Push Mark/Point to Here" to "Generic Pointer Up".
+
+/usr1/lisp/nhem/mh.lisp, 31-Mar-89 13:40:46, Edit by Chiles.
+  Fixed a bug in SETUP-REMAIL-DRAFT-BUFFER recently introduced by tweaking
+  cleanup hooks.  THis now makes a dummy "Draft Information" variable.
+
+/usr1/lisp/nhem/macros.lisp, 29-Mar-89 22:19:57, Edit by Chiles.
+  Changed error handler to take r and R for restarts instead of P.
+
+/usr1/lisp/nhem/dired.lisp, 29-Mar-89 21:41:04, Edit by Chiles.
+  Renamed MAKEDIR to MAKE-DIRECTORY.
+
+/usr1/lisp/nhem/diredcoms.lisp, 29-Mar-89 17:04:51, Edit by Chiles.
+  Modified some doc strings and rewrote "Dired Help" to use "Describe Mode".
+
+/usr1/lisp/nhem/bufed.lisp, 29-Mar-89 16:53:06, Edit by Chiles.
+  Fixed some documentation and rewrote "Bufed Help" to use "Describe Mode".
+
+/usr1/lisp/nhem/bindings.lisp, 29-Mar-89 16:45:08, Edit by Chiles.
+  Added binding for "Bufed Help".
+
+/usr1/lisp/nhem/bufed.lisp, 29-Mar-89 16:36:53, Edit by Chiles.
+  Added documentation to mode "Bufed".
+
+/usr1/lisp/nhem/doccoms.lisp, 29-Mar-89 15:52:11, Edit by Chiles.
+  Wrote "Describe Mode" and hooked it into "Help".
+
+/usr1/lisp/nhem/buffer.lisp, 29-Mar-89 11:24:19, Edit by Chiles.
+  Wrote MODE-DOCUMENTATION and exported it.
+
+/usr1/lisp/nhem/filecoms.lisp, 28-Mar-89 17:24:47, Edit by Chiles.
+  Removed "Rename File" and "Delete File".
+
+/usr1/lisp/nhem/dired.lisp, 28-Mar-89 16:42:27, Edit by Chiles.
+  Removed "[Yes]" from DELETE-FILE-2
+
+/usr1/lisp/nhem/diredcoms.lisp, 28-Mar-89 16:03:16, Edit by Chiles.
+  Moved "Delete File" here and made it consistent with the new "Copy File" and
+  "Rename File" in that it calls out to the dired package.
+
+/usr1/lisp/hemlock/bindings.lisp, 28-Mar-89 11:32:03, Edit by DBM.
+  Names for a couple of bindings were incorrect and have been
+  fixed.
+
+/usr1/lisp/nhem/diredcoms.lisp, 28-Mar-89 11:19:50, Edit by Chiles.
+  Modified "View File" to name buffers better.
+
+/usr1/lisp/nhem/bindings.lisp, 27-Mar-89 13:01:14, Edit by Chiles.
+  Forgot a copy and rename dired bindings.
+
+/usr1/lisp/nhem/mh.lisp, 27-Mar-89 11:46:28, Edit by Chiles.
+  Fixed :delete-hook arg that was not a list.
+
+/usr1/lisp/nhem/lispeval.lisp, 25-Mar-89 09:44:46, Edit by Chiles.
+  Wrote "Editor Server Name".
+
+/usr1/lisp/nhem/rompsite.lisp, 25-Mar-89 09:37:57, Edit by Chiles.
+  Modified INIT-EDITOR-SERVER to include process ID in editor server name for
+  same user, same machine, multiple instance protection.
+
+/usr1/lisp/nhem/lispbuf.lisp, 24-Mar-89 23:19:56, Edit by Chiles.
+/usr1/lisp/nhem/lispbuf.lisp, 24-Mar-89 23:12:48, Edit by Chiles.
+  "Reenter Interactive Input" must copy the region when it is active since
+  moving the point changed the input region.  There also was a bug that it
+  checked for the value of buffer-input-mark, but this has no global binding.
+  It now checks for a binding instead of a non-nil value.
+
+/usr1/lisp/nhem/spellcoms.lisp, 24-Mar-89 21:44:36, Edit by Chiles.
+  Made CORRECT-BUFFER-SPELLING and SPELL-PREVIOUS-WORD always ignore trailing
+  apostrophe s's on words.
+
+/usr1/lisp/nhem/bindings.lisp, 23-Mar-89 20:51:16, Edit by Chiles.
+  Added Bufed bindings.
+
+/usr1/lisp/nhem/bufed.lisp, 23-Mar-89 20:52:48, Edit by Chiles.
+  New file.
+
+/usr1/lisp/nhem/ts.lisp, 22-Mar-89 17:04:44, Edit by Chiles.
+/usr1/lisp/nhem/srccom.lisp, 22-Mar-89 17:04:02, Edit by Chiles.
+/usr1/lisp/nhem/spellcoms.lisp, 22-Mar-89 17:03:17, Edit by Chiles.
+/usr1/lisp/nhem/register.lisp, 22-Mar-89 17:00:37, Edit by Chiles.
+/usr1/lisp/nhem/morecoms.lisp, 22-Mar-89 16:59:49, Edit by Chiles.
+/usr1/lisp/nhem/mh.lisp, 22-Mar-89 16:59:08, Edit by Chiles.
+/usr1/lisp/nhem/lispeval.lisp, 22-Mar-89 16:58:16, Edit by Chiles.
+/usr1/lisp/nhem/lisp-lib.lisp, 22-Mar-89 16:57:31, Edit by Chiles.
+/usr1/lisp/nhem/killcoms.lisp, 22-Mar-89 15:27:23, Edit by Chiles.
+/usr1/lisp/nhem/htext2.lisp, 22-Mar-89 15:24:23, Edit by Chiles.
+/usr1/lisp/nhem/hi-integrity.lisp, 22-Mar-89 15:23:12, Edit by Chiles.
+/usr1/lisp/nhem/filecoms.lisp, 22-Mar-89 15:22:19, Edit by Chiles.
+/usr1/lisp/nhem/edit-defs.lisp, 22-Mar-89 15:21:01, Edit by Chiles.
+/usr1/lisp/nhem/echocoms.lisp, 22-Mar-89 14:59:18, Edit by Chiles.
+/usr1/lisp/nhem/echo.lisp, 22-Mar-89 14:57:55, Edit by Chiles.
+/usr1/lisp/nhem/diredcoms.lisp, 22-Mar-89 14:13:31, Edit by Chiles.
+/usr1/lisp/nhem/cursor.lisp, 22-Mar-89 14:11:46, Edit by Chiles.
+/usr1/lisp/nhem/command.lisp, 22-Mar-89 14:09:36, Edit by Chiles.
+/usr1/lisp/nhem/bit-screen.lisp, 22-Mar-89 14:08:27, Edit by Chiles.
+  Replaced idioms with BUFFER-START-MARK and BUFFER-END-MARK.
+
+/usr1/lisp/nhem/buffer.lisp, 22-Mar-89 14:05:29, Edit by Chiles.
+  Wrote BUFFER-START-MARK and BUFFER-END-MARK.
+
+/usr1/lisp/nhem/lisp-lib.lisp, 21-Mar-89 14:32:14, Edit by Chiles.
+  Modified all Lisp Library commands to signal an editor-error when not in a
+  library buffer.
+
+/usr1/lisp/nhem/morecoms.lisp, 21-Mar-89 14:22:02, Edit by Mbb.
+  Made "Count Occurrences" use the active region when it exists, otherwise
+  point to end of buffer.  "Count Lines Region" became "Count Lines", and
+  "Count Words Region" became "Count Words".  These two use the active region
+  now too.
+
+/usr1/lisp/nhem/searchcoms.lisp, 21-Mar-89 14:19:17, Edit by Mbb.
+  Made QUERY-REPLACE-FUNCTION use the active region if it exists, otherwise
+  point to end of buffer.  Also, "List Matching Lines", "Delete Matching
+  Lines", and "Delete Non-Matching Lines" handle the active region similarly.
+
+/usr1/lisp/nhem/spellcoms.lisp, 20-Mar-89 15:17:19, Edit by Chiles.
+  Made CORRECT-BUFFER-SPELLING and SPELL-PREVIOUS-WORD ignore apostrophes
+  following words.
+
+/usr1/lisp/nhem/mh.lisp, 17-Mar-89 11:16:13, Edit by Chiles.
+  Replaced MODIFYING-MAIL-BUF with WITH-WRITABLE-BUFFER.
+
+/usr1/lisp/nhem/buffer.lisp, 17-Mar-89 11:07:41, Edit by Chiles.
+  Wrote WITH-WRITABLE-BUFFER.
+
+/usr1/lisp/nhem/window.lisp, 16-Mar-89 11:13:41, Edit by Chiles.
+  Made MAKE-MODELINE-FIELD have a restart that clobbers the existing defintion
+  of a modeline field name.
+
+/usr1/lisp/nhem/display.lisp, 14-Mar-89 23:19:27, Edit by Chiles.
+  Made REDISPLAY-WINDOWS-FROM-MARK invoke *things-to-do-once*.  Some commands
+  were making buffers, using line buffered output streams
+  (WITH-OUTPUT-TO-MARK), and when redisplaying from the mark.  This didn't
+  allow the chance for the buffer's modeline info object's start fields to get
+  initialized via UPDATE-MODELINE-FIELDS.
+
+/usr1/ch/lisp/complete/table.lisp, 14-Mar-89 19:46:09, Edit by Hoover.
+  Fixed a bogus declaration in COMPUTE-FIELD-POS.
+
+/usr1/lisp/nhem/echo.lisp, 14-Mar-89 14:07:56, Edit by Chiles.
+  Wrote BUFFER-VERIFICATION-FUNCTION which now moves the point around for
+  ambiguous shit.
+
+/usr1/lisp/nhem/echocoms.lisp, 14-Mar-89 13:22:31, Edit by Chiles.
+  Made "Complete Keyword" move the point in the echo area to the first
+  ambiguous field for :keyword completion (when the prefix is ambiguous of
+  course).
+
+/usr1/lisp/nhem/filecoms.lisp, 14-Mar-89 11:04:49, Edit by Chiles.
+  Modified PROCESS-FILE-OPTIONS to LOUD-MESSAGE and abort file options on
+  parsing errors.  It still goes on to try to set a major mode.
+
+/usr1/lisp/nhem/table.lisp, 13-Mar-89 13:17:32, Edit by Chiles.
+  Eliminated optional argument to COMPLETE-STRING.  Entered code for signalling
+  an error if the tables did not contain the same separator character, but
+  commented it out.
+
+/usr1/lisp/nhem/bindings.lisp, 09-Mar-89 16:19:19, Edit by Chiles.
+  Added more page titles.  Voided some character translations and made up for
+  the few commands that needed to be duplicated.
+
+/usr1/lisp/nhem/window.lisp, 07-Mar-89 16:37:18, Edit by Chiles.
+  Added print function for modeline field info objects.
+
+/usr1/lisp/nhem/edit-defs.lisp, 07-Mar-89 10:59:30, Edit by Chiles.
+  Made GO-TO-DEFINITION use name-len instead of calculating it again.
+
+/usr1/lisp/nhem/mh.lisp, 06-Mar-89 21:37:11, Edit by Chiles.
+  Now make new mail buffer with delete-hook NEW-MAIL-BUF-DELETE-HOOK.  Delete
+  old CLEANUP-NEW-MAIL-BUF-DELETION.
+
+  Made CLEANUP-HEADERS-BUFFER, CLEANUP-MESSAGE-BUFFER, and CLEANUP-DRAFT-BUFFER
+  no longer check for their appropriate information structure.  Made
+  MAYBE-MAKE-MH-BUFFER set buffer local deletion hooks for these functions.
+
+
+/usr1/lisp/nhem/buffer.lisp, 06-Mar-89 21:25:54, Edit by Chiles.
+  MAKE-BUFFER now takes a :delete-hook argument, and DELETE-BUFFER now invokes
+  these functions.
+
+/usr1/lisp/nhem/struct.lisp, 06-Mar-89 21:19:05, Edit by Chiles.
+  Made buffer structure have a local delete hooks list.
+
+/usr1/lisp/nhem/highlight.lisp, 06-Mar-89 17:54:46, Edit by Chiles.
+  Made HIGHLIGHT-ACTIVE-REGION no longer do anything on the tty.
+
+/usr1/lisp/nhem/filecoms.lisp, 03-Mar-89 18:02:19, Edit by Chiles.
+  Fixed some recently lost functionality in "Create Buffer".
+
+/usr1/lisp/nhem/dired.lisp, 01-Mar-89 11:07:46, Edit by Chiles.
+  Modified ARRAY-ELEMENT-FROM-MARK to take an error message.
+
+/usr1/lisp/nhem/dired.lisp, 27-Feb-89 15:03:49, Edit by Chiles.
+  DELETE-FILE-AUX no longer outputs deleted file names on standard output.
+
+/usr1/lisp/nhem/kbdmac.lisp, 23-Feb-89 10:36:37, Edit by Chiles.
+  Changed "Define Keyboard Macro Key" message.
+
+/usr1/lisp/hemlock/rompsite.lisp, 07-Mar-89 17:33:05, Edit by DBM.
+  Modified the Hemlock GC notify functions to conform with the new
+  format for the messages.
+
+/usr1/lisp/nhem/dired.lisp, 27-Feb-89 15:03:49, Edit by Chiles.
+  DELETE-FILE-AUX no longer outputs deleted file names on standard output.
+
+/usr1/lisp/nhem/kbdmac.lisp, 23-Feb-89 10:36:37, Edit by Chiles.
+  Changed "Define Keyboard Macro Key" message.
+
+/usr1/lisp/nhem/complete/bindings.lisp, 22-Feb-89 14:31:11, Edit by Chiles.
+  Added new keyboard macro bindings.
+
+/usr1/lisp/nhem/complete/kbdmac.lisp, 22-Feb-89 14:22:01, Edit by Chiles.
+  Added new command "Define Keyboard Macro Key".
+
+/usr1/lisp/nhem/complete/scribe.lisp, 21-Feb-89 12:52:19, Edit by Chiles.
+/usr1/lisp/nhem/complete/morecoms.lisp, 21-Feb-89 12:50:45, Edit by Chiles.
+/usr1/lisp/nhem/complete/doccoms.lisp, 21-Feb-89 12:46:15, Edit by Chiles.
+/usr1/lisp/nhem/complete/abbrev.lisp, 21-Feb-89 12:42:26, Edit by Chiles.
+  Modified MAKE-STRING-TABLE call.
+
+/usr1/lisp/nhem/complete/echo.lisp, 21-Feb-89 12:37:06, Edit by Chiles.
+  Modified for new string tables.
+
+/usr1/lisp/nhem/complete/echocoms.lisp, 21-Feb-89 11:50:59, Edit by Chiles.
+  Modified stuff for new string tables.
+
+/usr1/lisp/nhem/complete/struct.lisp, 21-Feb-89 11:43:26, Edit by Chiles.
+  Added new setf method for string tables.
+
+/usr1/lisp/nhem/complete/complete.lisp, 21-Feb-89 11:46:04, Edit by Chiles.
+  New file.
+
+/usr1/lisp/nhem/complete/macros.lisp, 21-Feb-89 11:45:10, Edit by Chiles.
+  Added new DO-STRINGS.
+
+/usr1/lisp/hemlock/dired.lisp, 22-Feb-89 16:36:49, Edit by DBM.
+  Fixed "Dired Help" string.
+
+/usr1/lisp/hemlock/mh.lisp, 21-Feb-89 14:25:42, Edit by Chiles.
+  Added delete-buffer-hook to set *new-mail-buffer* to nil.
+
+/usr1/lisp/nhem/rompsite.lisp, 20-Feb-89 16:54:11, Edit by Chiles.
+  Added load for hem:lisp-lib.fasl.
+
+/usr1/lisp/nhem/lisp-lib.lisp, 20-Feb-89 16:51:19, Edit by Chiles.
+  This is a new file.
+
+/usr1/lisp/nhem/bindings.lisp, 20-Feb-89 16:50:13, Edit by Chiles.
+  Added "Lisp-Lib" bindings.
+
+/usr1/lisp/nhem/dired.lisp, 15-Feb-89 15:20:25, Edit by Chiles.
+  This is a new file.
+
+/usr1/lisp/nhem/bindings.lisp, 15-Feb-89 15:20:03, Edit by Chiles.
+  Added Dired bindings.
+
+/usr1/lisp/nhem/rompsite.lisp, 14-Feb-89 18:04:46, Edit by Chiles.
+  Added load for dired.fasl.
+
+/usr1/lisp/nhem/srccom.lisp, 14-Feb-89 16:16:11, Edit by Chiles.
+  Fixed some silly coding.
+
+/usr1/lisp/nhem/rompsite.lisp, 14-Feb-89 16:06:28, Edit by Chiles.
+  Removed tty MESSAGE of GC info.
+
+/usr1/lisp/nhem/scribe.lisp, 14-Feb-89 11:08:53, Edit by Chiles.
+  Made "Insert Scribe Directive" use the active region for environments.
+
+/usr1/lisp/nhem/group.lisp, 13-Feb-89 16:19:57, Edit by Chiles.
+  Put back routine I accidently deleted.
+
+/usr1/lisp/nhem/struct.lisp, 10-Feb-89 16:45:23, Edit by Chiles.
+  Deleted export of COPY-MODELINE-FIELD.
+
+/usr1/ch/lisp/rompsite.lisp, 02-Feb-89 16:49:42, Edit by Christopher Hoover.
+  Changed font path support to use EXT:CAREFULLY-ADD-FONT-PATHS.  Made
+  Hemlock look first on the local machine and then in AFS for fonts.
+
+/usr1/lisp/nhem/searchcoms.lisp, 31-Jan-89 11:00:10, Edit by Chiles.
+  Installed "String Search Ignore Case" and removed "Default Search Kind".
+
+/usr1/lisp/nhem/rompsite.lisp, 30-Jan-89 15:17:12, Edit by Chiles.
+  Changed underline font variable values and set up to really use X11 font
+  paths.
+
+/usr1/lisp/nhem/bindings.lisp, 27-Jan-89 13:31:13, Edit by Chiles.
+  Removed "Typescript" mode local binding of "Process Control invoke EXT:ABORT"
+  to #\hyper-a.
+
+/usr1/lisp/nhem/macros.lisp, 20-Jan-89 16:11:18, Edit by Chiles.
+  Fixed bug in LISP-ERROR-ERROR-HANDLER that allowed logical characters in
+  COMMAND-CASE to throw us into the debugger with a recursive error.
+
+/usr1/lisp/nhem/doccoms.lisp, 16-Jan-89 19:04:03, Edit by Chiles.
+  Fixed doc string for "Help" p.
+
+/usr1/lisp/nhem/macros.lisp, 11-Jan-89 23:03:10, Edit by Chiles.
+  Deleted export of IGNORE-EDITOR-ERRORS which no longer exists.
+
+/usr1/lisp/nhem/htext1.lisp, 11-Jan-89 22:54:14, Edit by Chiles.
+  Exported LINE> and LINES-RELATED.
+
+/usr1/lisp/nhem/window.lisp, 11-Jan-89 22:45:22, Edit by Chiles.
+  Removed some bogus exports dirtying the system with "nonexistent" symbols.
+
+/usr1/lisp/nhem/filecoms.lisp, 11-Jan-89 13:37:41, Edit by Chiles.
+  Fixed bug in READ-BUFFER-FILE invoking hook on wrong pathname (not probed
+  one).
+
+/usr1/lisp/nhem/filecoms.lisp, 10-Jan-89 18:03:38, Edit by Chiles.
+  Fixed bug in PATHNAME-TO-BUFFER-NAME.
+
+/usr1/lisp/nhem/lispeval.lisp, 05-Jan-89 17:21:54, Edit by Chiles.
+  Made "Describe Symbol" use MARK-SYMBOL
+
+/usr1/lisp/nhem/lispbuf.lisp, 05-Jan-89 17:20:12, Edit by Chiles.
+  Wrote MARK-SYMBOL and made "Editor Describe Symbol" use it.
+
+/usr1/lisp/nhem/scribe.lisp, 05-Jan-89 15:55:23, Edit by Chiles.
+  Made INSERT-SCRIBE-DIRECTIVE use the next word if the mark is immediately
+  before it, instead of the previous word.  Cleaned up the code some and
+  documented it (oh no!).
+
+/usr1/lisp/nhem/spellcoms.lisp, 05-Jan-89 15:32:32, Edit by Chiles.
+  Made SPELL-PREVIOUS-WORD return the next word when the mark is immediately
+  before the next word, such that the cursor is displayed within that word.
+  Renamed "Correct Word Spelling" to "Check Word Spelling" and "Check Word
+  Spelling" to "Auto Check Word Spelling".
+
+/usr1/lisp/nhem/rompsite.lisp, 03-Jan-89 11:37:50, Edit by Chiles.
+  Made INVOKE-SCHEDULED-EVENTS bind *time-queue* to nil around invoking event
+  function.
+
+/usr1/lisp/nhem/hunk-draw.lisp, 02-Jan-89 15:53:58, Edit by Chiles.
+  Fixed problem with underline font leaving dots at the end of lines.  I was
+  copying the pixmap onto the screen one pixel short of the appropriate length.
+
+/usr1/lisp/nhem/lispeval.lisp, 23-Dec-88 15:13:07, Edit by Chiles.
+  Rewrote "Compile Defun", "Evaluate Defun", and "Re-evaluate Defvar" to
+  use DEFUN-REGION.
+
+/usr1/lisp/nhem/lispbuf.lisp, 23-Dec-88 15:04:46, Edit by Chiles.
+  Wrote DEFUN-REGION and rewrote "Editor Compile Defun", "Editor Evaluate
+  Defun", and "Editor Re-evaluate Defvar" to use it.
+
+/usr1/lisp/nhem/lispmode.lisp, 22-Dec-88 23:43:33, Edit by Chiles.
+  Wrote MARK-TOP-LEVEL-FORM.  Rewrote "Mark Defun" and "End of Defun" to use
+  it.  Added doc strings to START-DEFUN-P and INSIDE-DEFUN-P.
+
+/usr1/lisp/nhem/keytran.lisp, 22-Dec-88 17:39:21, Edit by Chiles.
+  Fixed a bug in TRANSLATE-MOUSE-CHARACTER that would have tried to set the
+  :lock bit for a character which our system doesn't support.
+
+/usr1/lisp/nhem/mh.lisp, 21-Dec-88 14:26:09, Edit by Chiles.
+  Replaced occurrences of FILL-REGION-COMMAND-AUX with
+  FILL-REGION-BY-PARAGRAHPS.
+
+/usr1/lisp/nhem/fill.lisp, 21-Dec-88 13:59:36, Edit by Chiles.
+  Renamed FILL-REGION-COMMAND-AUX to FILL-REGION-BY-PARAGRAHPS.  Made some
+  arguments optional.
+
+/usr1/lisp/nhem/morecoms.lisp, 20-Dec-88 17:31:29, Edit by Chiles.
+  Modified PAGE-DIRECTORY to clean it up and made it pull control-l's off the
+  line strings if it occurred as the first characters.
+
+/usr1/lisp/nhem/window.lisp, 19-Dec-88 13:52:23, Edit by Chiles.
+  Modified WINDOW-CHANGED to update the modeline's dis-line length.
+
+/usr1/lisp/nhem/unixcoms.lisp, 17-Dec-88 10:53:54, Edit by Chiles.
+/usr1/lisp/nhem/mh.lisp, 17-Dec-88 10:53:13, Edit by Chiles.
+/usr1/lisp/nhem/lispeval.lisp, 17-Dec-88 10:52:09, Edit by Chiles.
+/usr1/lisp/nhem/lispbuf.lisp, 17-Dec-88 10:51:08, Edit by Chiles.
+  Changed instances of WRITE-DA-FILE to WRITE-BUFFER-FILE.
+
+/usr1/lisp/nhem/killcoms.lisp, 14-Dec-88 23:32:02, Edit by Chiles.
+  Fixed a bug in the KILL-REGION/KILL-CHARACTER interaction code -- needed to
+  set the *delete-char-region* to nil when the previous command type was a
+  region kill.
+
+/usr1/lisp/nhem/echo.lisp, 14-Dec-88 22:40:43, Edit by Chiles.
+  Modified PROMPT-FOR-BUFFER to disallow input of the empty string when no
+  default is offered.  This now permits defaults to be specified with
+  :default-string even when :default is nil, but when :must-exist is non-nil,
+  :default-string must name an existing buffer.
+
+/usr1/lisp/nhem/filecoms.lisp, 14-Dec-88 22:13:17, Edit by Chiles.
+  Rewrote "Create Buffer".  It now offers a default of "Buffer n".
+
+  Added doc strings for BUFFER-DEFAULT-PATHNAME and PATHNAME-TO-BUFFER-NAME.
+  Changed what PATHNAME-TO-BUFFER-NAME does.  When there is a type but no name,
+  it inserts *name/type-separator-character* before the type.
+
+  Renamed WRITE-DA-FILE to WRITE-BUFFER-FILE, and READ-DA-FILE to
+  READ-BUFFER-FILE.  Modified FIND-FILE-BUFFER and "Visit File".  Hope they're
+  right.
+
+  "Process File Options" no longer complains about a missing pathname.
+  PROCESS-FILE-OPTIONS is willing to handle a buffer without an associated
+  pathname.
+
+
+/usr1/lisp/nhem/echo.lisp, 14-Dec-88 22:05:31, Edit by Chiles.
+  PROMPT-FOR-BUFFER does not allow the empty string to be supplied anymore.
+
+/usr1/lisp/nhem/srccom.lisp, 14-Dec-88 21:56:53, Edit by Chiles.
+  Made the prompt for a destination buffer offer a sticky-default,
+  "Source Compare Default Destination".
+
+/usr1/lisp/nhem/mh.lisp, 14-Dec-88 13:19:01, Edit by Chiles.
+  Updated modeline stuff to use MODELINE-FIELD.
+
+/usr1/lisp/nhem/main.lisp, 13-Dec-88 13:52:20, Edit by Chiles.
+  Modified MAKE-MODELINE-FIELD calls.
+
+/usr1/lisp/nhem/morecoms.lisp, 13-Dec-88 13:50:07, Edit by Chiles.
+  Updated DO-RECURSIVE-EDIT to use MODELINE-FIELD.
+
+/usr1/lisp/nhem/struct.lisp, 13-Dec-88 12:47:22, Edit by Chiles.
+  Renamed modeline-field-name to %name.  Defined setf'er.
+
+/usr1/lisp/nhem/window.lisp, 13-Dec-88 13:40:45, Edit by Chiles.
+  Modified modeline stuff to make names first class.  Renamed some modelien
+  field objects.  Wrote MODELINE-FIELD, MODELINE-FIELD-NAME, and a setf'er.
+
+/usr1/lisp/nhem/bit-screen.lisp, 13-Dec-88 11:41:32, Edit by Chiles.
+  Uncommented hook additions for WINDOW-BUFFER and BUFFER-NAME icon naming.
+
+/usr1/lisp/nhem/rompsite.lisp, 13-Dec-88 11:42:28, Edit by Chiles.
+  Updated window icon naming for X11.  Someone wanted it.
+
+/usr1/lisp/nhem/killcoms.lisp, 12-Dec-88 12:30:23, Edit by Chiles.
+  Made PUSH-BUFFER-MARK signal a Lisp error.
+
+/usr1/lisp/nhem/rompsite.lisp, 10-Dec-88 20:50:06, Edit by Chiles.
+  Added doc strings for TEXT-CHARACTER and PRINT-PRETTY-CHARACTER.
+
+/usr1/lisp/nhem/auto-save.lisp, 10-Dec-88 14:26:52, Edit by Chiles.
+  Added some documentation and removed some bogus "interface" claims as per
+  Rob's understanding of what "interface" means in a function's comments.
+
+/usr1/lisp/nhem/macros.lisp, 08-Dec-88 13:49:04, Edit by Chiles.
+  Modified doc string for EDITOR-ERROR.  It also now signals an error if the
+  editor-error condition goes unhandled.
+
+/usr1/lisp/nhem/interp.lisp, 08-Dec-88 13:37:02, Edit by Chiles.
+  Established editor-error condition handler around command invocation.
+  Editor-error's were being handled by the "internal:" error handler
+  established in ED since these conditions are a subtype of error.
+
+/usr1/lisp/nhem/filecoms.lisp, 06-Dec-88 14:29:26, Edit by Chiles.
+  Wrote DELETE-BUFFER-IF-POSSIBLE.  Added doc string for CHANGE-TO-BUFFER.
+
+/usr1/lisp/nhem/buffer.lisp, 06-Dec-88 13:51:58, Edit by Chiles.
+  Modified page title and doc string for DELETE-BUFFER.
+
+/usr1/lisp/nhem/mh.lisp, 06-Dec-88 13:45:19, Edit by Chiles.
+  Moved DELETE-MH-BUFFER and replaced calls with DELETE-BUFFER-IF-POSSIBLE.
+
+/usr1/lisp/nhem/xcoms.lisp, 30-Nov-88 17:36:43, Edit by Chiles.
+  Here it is -- "Stack Window".
+
+/usr1/lisp/nhem/filecoms.lisp, 30-Nov-88 17:36:19, Edit by Chiles.
+  Moved "Stack Window".
+
+/usr1/lisp/nhem/fill.lisp, 29-Nov-88 11:59:51, Edit by Chiles.
+  Changed occurrences of %MARK-PARAGRAPH to MARK-PARAGRAPH.
+
+/usr1/lisp/nhem/text.lisp, 29-Nov-88 11:58:01, Edit by Chiles.
+  Changed %MARK-PARAGRAPH to MARK-PARAGRAPH.
+
+/usr1/lisp/hemlock/mh.lisp, 28-Nov-88 16:21:44, Edit by DBM.
+  Modified CLEANUP-HEADERS-REFERENCE to set the message/draft-hdrs-mark to
+  nil.  This is necessary if someone deletes the headers buffer before the
+  message buffer.
+
+/usr1/lisp/nhem/macros.lisp, 27-Nov-88 15:59:21, Edit by Chiles.
+  Rewrote EDITOR-ERROR.  Created an editor-error condition with accesses
+  EDITOR-ERROR-FORMAT-STRING and EDITOR-ERROR-FORMAT-ARGUMENTS.
+
+/usr1/lisp/nhem/main.lisp, 26-Nov-88 14:56:25, Edit by Chiles.
+  Deleted bogus export of *current-package*.
+
+/usr1/lisp/nhem/text.lisp, 26-Nov-88 12:28:30, Edit by Chiles.
+  Replaced occurrence of %KILL-REGION with KILL-REGION.
+
+/usr1/lisp/nhem/lispmode.lisp, 26-Nov-88 12:27:12, Edit by Chiles.
+  Replaced occurrence of %KILL-REGION with KILL-REGION.
+
+/usr1/lisp/nhem/lispbuf.lisp, 26-Nov-88 12:26:07, Edit by Chiles.
+  Replaced occurrence of %KILL-REGION with KILL-REGION.
+
+/usr1/lisp/nhem/echocoms.lisp, 26-Nov-88 12:25:25, Edit by Chiles.
+  Replaced occurrence of %KILL-REGION with KILL-REGION.
+
+/usr1/lisp/nhem/morecoms.lisp, 25-Nov-88 20:55:18, Edit by Chiles.
+  Modified "Delete Previous Character Expanding Tabs" to call KILL-CHARACTERS.
+
+/usr1/lisp/nhem/command.lisp, 25-Nov-88 21:27:07, Edit by Chiles.
+  Modified "Delete Next Character" and "Delete Previous Character" to call
+  KILL-CHARACTERS.
+
+/usr1/lisp/nhem/killcoms.lisp, 25-Nov-88 21:58:39, Edit by Chiles.
+  Wrote KILL-CHARACTERS and modified KILL-REGION (used to be %KILL-REGION).
+
+/usr1/lisp/nhem/icom.lisp, 25-Nov-88 16:04:48, Edit by Chiles.
+  Removed italicize comments file option.  Changed package spec to string.
+
+/usr1/lisp/nhem/mh.lisp, 22-Nov-88 16:06:53, Edit by Chiles.
+  Made SHOW-PROMPTED-MESSAGE normalize message ID strings.
+
+/usr1/lisp/nhem/bit-screen.lisp, 21-Nov-88 16:22:30, Edit by Chiles.
+  DEFAULT-DELETE-WINDOW-HOOK-NEXT-MERGE now sets the next hunk trashed since we
+  are somehow getting exposure events out of order with configure
+  notifications.  We should be able to remove this when facilities fixes the
+  new software it just released.
+
+/usr1/lisp/nhem/lispeval.lisp, 18-Nov-88 13:54:01, Edit by Chiles.
+  Made CREATE-SLAVE correctly get the name of the slave that just connected.
+
+/usr1/lisp/nhem/rompsite.lisp, 18-Nov-88 13:52:21, Edit by Chiles.
+  Made EDITOR_CONNECT-HANDLER set the name of the editor that just connected.
+
+/usr1/lisp/nhem/hunk-draw.lisp, 17-Nov-88 09:08:04, Edit by Chiles.
+  Made HUNK-REPLACE-LINE-ON-PIXMAP set gcontext :exposures nil.  Fixed the
+  macro it uses to no longer require binding gcontext each time around the
+  loop.
+
+/usr1/lisp/nhem/mh.lisp, 15-Nov-88 21:25:50, Edit by Chiles.
+  Added page of code for message buffer modeline fields.  Wrote
+  MARK-TO-NOTE-REPLIED-MSG.  Created "Default Message Modeline Fields".
+  Modified DELETE-MESSAGE and UNDELETE-MESSAGE.  Modified MAYBE-MAKE-MH-BUFFER.
+  Modified "Deliver Message" and wrote DELIVER-DRAFT-BUFFER-MESSAGE.
+
+/usr1/lisp/nhem/struct.lisp, 16-Nov-88 13:25:17, Edit by Chiles.
+  Export MODELINE-FIELD-NAME instead ML-FIELD-NAME.
+
+/usr1/lisp/nhem/rompsite.lisp, 16-Nov-88 13:32:48, Edit by Chiles.
+  Wrote EDITOR-DESCRIBE-FUNCTION.
+
+/usr1/lisp/nhem/lispbuf.lisp, 16-Nov-88 13:39:41, Edit by Chiles.
+  Wrote FUNCTION-TO-DESCRIBE and modified "Editor Describe Function Call".
+
+/usr1/lisp/nhem/lispeval.lisp, 16-Nov-88 13:50:14, Edit by Chiles.
+  Made DESCRIBE-FUNCTION-CALL-AUX use EDITOR-DESCRIBE-FUNCTION and
+  FUNCTION-TO-DESCRIBE.
+
+/usr1/lisp/nhem/mh.lisp, 15-Nov-88 20:46:02, Edit by Chiles.
+  Added message buffer modeline stuff.  Modified MAYBE-MAKE-MH-BUFFER for the
+  creation of the message buffer.  Modified DELETE-MESSAGE
+
+  Maybe D shouldn't be fixed width?
+
+/usr1/lisp/nhem/window.lisp, 15-Nov-88 13:34:41, Edit by Chiles.
+  Modified %SET-MODELINE-FIELD-WIDTH to not allow zero width fields.  Modified
+  MAKE-MODELINE-FIELD to check constraints too.
+
+  Fixed a bug in the :buffer-name modeline-field.
+
+
+/usr1/lisp/nhem/rompsite.lisp, 15-Nov-88 12:30:32, Edit by Chiles.
+  Replaced "nmmonitor" with "nm_active".
+
+/usr1/lisp/nhem/display.lisp, 15-Nov-88 12:40:25, Edit by Chiles.
+  Fixed REDISPLAY-WINDOWS-FOR-MARK to force output and so on.
+
+/usr1/lisp/hemlock/buffer.lisp, 14-Nov-88 15:14:34, Edit by DBM.
+  Made SETUP-INITIAL-BUFFER supply :modeline-fields nil.  This gets set
+  when the editor fires up.
+
+/usr1/lisp/nhem/tty-display.lisp, 10-Nov-88 16:23:04, Edit by Chiles.
+  Modified occurrences of WINDOW-MODELINE-STRING to be WINDOW-MODELINE-BUFFER.
+  Made dumb redisplay method set the window's dis-line flags to unaltered.
+
+/usr1/lisp/nhem/bit-display.lisp, 10-Nov-88 16:20:40, Edit by Chiles.
+  Modified occurrences of WINDOW-MODELINE-STRING to be WINDOW-MODELINE-BUFFER.
+
+/usr1/lisp/nhem/main.lisp, 10-Nov-88 16:07:07, Edit by Chiles.
+  Added "Default Status Line Fields" along with DEFVAR's and PROCLAIM's for
+  recursive edit and completion mode fields.
+
+  Modified "Default Modeline Fields".
+
+/usr1/lisp/nhem/bit-screen.lisp, 10-Nov-88 13:11:49, Edit by Chiles.
+  Modified BITMAP-MAKE-WINDOW to take modelinep.  Modified
+  DEFAULT-CREATE-INITIAL-WINDOWS-ECHO to supply :modelinep t to MAKE-WINDOW.
+  Modified SET-HUNK-SIZE to determine if the window displays modelines by
+  checking WINDOW-MODELINE-BUFFER.
+
+/usr1/lisp/nhem/screen.lisp, 10-Nov-88 13:02:34, Edit by Chiles.
+  MAKE-WINDOW now takes a :modelinep argument.
+
+  Added sets for echo and main BUFFER-MODELINE-FIELDS.
+
+/usr1/lisp/nhem/mh.lisp, 09-Nov-88 11:43:45, Edit by Chiles.
+  Modified a few MAKE-BUFFER calls.  The modeline fields for mail buffer should
+  be redesigned when this stuff goes into the core.
+
+/usr1/lisp/nhem/lispeval.lisp, 09-Nov-88 11:38:19, Edit by Chiles.
+  Modified MAKE-BUFFER call.  Made "Set Buffer Package" do over buffer's
+  windows calling UPDATE-MODELINE-FIELD on :package.
+
+/usr1/lisp/nhem/echo.lisp, 09-Nov-88 11:31:34, Edit by Chiles.
+  Modified MAKE-BUFFER call.
+
+/usr1/lisp/nhem/tty-screen.lisp, 09-Nov-88 11:02:14, Edit by Chiles.
+  Made main-lines be one less for status line.  Made echo :text-position be one
+  less for status line.  Modified calls to SETUP-MODELINE-IMAGE.
+
+  Made TTY-MAKE-WINDOW refer to modelinep argument and modified its
+  SETUP-MODELINE-IMAGE call.
+
+/usr1/lisp/nhem/struct.lisp, 08-Nov-88 21:52:14, Edit by Chiles.
+  Added modeline-fields slot to buffer structure.
+
+  Deleted window structure slots: main-pane, text-pane, modeline-pane,
+  font-map, modeline-line, and modeline-width.  Added modeline-buffer and
+  modeline-buffer-len slots.
+
+  Added DEFSETF for BUFFER-MODELINE-FIELDS.
+
+  Added modeline-field and modeline-field-info structures.
+
+
+/usr1/lisp/nhem/buffer.lisp, 05-Nov-88 17:30:52, Edit by Chiles.
+  Added page titles.
+
+  Modified MAKE-BUFFER to initialize the %modeline-fields slot with a list of
+  ml-field-info objects.  Now it takes keyword arguments.  Modified call in
+  SETUP-INITIAL-BUFFER.
+
+  Wrote BUFFER-MODELINE-FIELDS, %SET-BUFFER-MODELINE-FIELDS, and
+  SUB-SET-BUFFER-MODELINE-FIELDS, BUFFER-MODELINE-FIELD-P.
+
+/usr1/lisp/nhem/bit-display.lisp, 27-Oct-88 21:09:46, Edit by Chiles.
+  Removed calls to UPDATE-MODELINE-IMAGE.
+
+/usr1/lisp/nhem/winimage.lisp, 27-Oct-88 20:51:21, Edit by Chiles.
+  Deleted UPDATE-MODELINE-IMAGE.
+
+/usr1/lisp/nhem/display.lisp, 30-Oct-88 19:47:04, Edit by Chiles.
+  Stopped REDISPLAY-WINDOW and REDISPLAY-WINDOW-ALL from forcing output and
+  calling the after methods.  This was causing INTERNAL-REDISPLAY to queue
+  input events for the editor that weren't seen before going into SYSTEM:SERVER
+  with a non-zero timeout.  This means SYSTEM:SERVER had to timeout, or another
+  character had to be entered, before the unseen one was revealed.
+
+/usr1/lisp/nhem/display.lisp, 27-Oct-88 15:10:58, Edit by Chiles.
+  Wrote INTERNAL-REDISPLAY and made REDISPLAY-LOOP optionally splice in calling
+  the device's after-redisplay function.
+
+/usr1/lisp/nhem/rompsite.lisp, 27-Oct-88 15:12:02, Edit by Chiles.
+  Replaced calls to REDISPLAY with INTERNAL-REDISPLAY.
+
+/usr1/lisp/nhem/morecoms.lisp, 26-Oct-88 15:50:43, Edit by Chiles.
+  Wrote "Goto Absolute Line".
+
+/usr1/lisp/nhem/hunk-draw.lisp, 26-Oct-88 15:32:22, Edit by Chiles.
+  Made HUNK-REPLACE-LINE dispatch on *hack-hunk-replace-line*.
+
+/usr1/lisp/nhem/display.lisp, 26-Oct-88 15:15:47, Edit by Chiles.
+  Added an after-redisplay slot to the basic display structure.  Made
+  REDISPLAY-LOOP, REDISPLAY-WINDOWS-FROM-MARK, REDISPLAY-WINDOW, and
+  REDISPLAY-WINDOW-ALL use this.
+
+/usr1/lisp/nhem/bit-screen.lisp, 26-Oct-88 15:03:05, Edit by Chiles.
+  MAKE-DEFAULT-BITMAP-DEVICE now sets the :after-redisplay slot.
+  REVERSE-VIDEO-HOOK-FUN now sets *hack-hunk-replace-line*.
+
+/usr1/lisp/hemlock/macros.lisp, 25-Oct-88 15:14:49, Edit by DBM.
+  Fixed the restart case in lisp-error-error-handler.
+
+/usr1/lisp/nhem/hunk-draw.lisp, 23-Oct-88 18:12:12, Edit by Chiles.
+  Fixed pixmap creation to be root depth instead of 1, so color stuff works.
+  When inverting areas, now use boole-xor instead of boole-c2 and a foreground
+  that is the xor of the foreground and background.  This makes color inversion
+  work.  If A is the foreground, and B is the background, then A xor B is AxB.
+  This value has the property that A xor AxB is B, and B xor AxB is A, thus
+  inverting in color the region.
+
+/usr1/lisp/nhem/bit-screen.lisp, 23-Oct-88 16:26:43, Edit by Chiles.
+  Modified BITMAP-MAKE-WINDOW to make the gcontext after we definitely have a
+  window.  Made sure that where I destroy an xwindow, that I free the gcontext
+  for that hunk.  Added a DEFVAR for *foreground-background-xor*, which is
+  initialized in INIT-BITMAP-SCREEN-MANAGER.  This function also has corrected
+  calls to GET-HEMLOCK-GREY-PIXMAP and GET-HEMLOCK-CURSOR.  Made
+  REVERSE-VIDEO-HOOK-FUN deal with rthunk correctly for new strategy, and it
+  calls GET-HEMLOCK-CURSOR now.
+
+/usr1/lisp/nhem/rompsite.lisp, 23-Oct-88 14:17:19, Edit by Chiles.
+  Modified FLASH-WINDOW-BORDER and FLASH-WINDOW to use an xor function and a
+  pixel value that is the xor of foreground and background.  This allows
+  inversion in a color window, that is for any pixel values including 1 and 0.
+  Changed the cursor fetching code to no longer save the pixmaps hot spots.
+  These are now generated each time you fetch a new Hemlock cursor, and this
+  code now uses distinct graphics contexts for each pixmap (cursor and mask) to
+  accomodate the color monitor.  This also seemed more correct in general.  The
+  grey pixmap generation has been changed to not use XLIB:PUT-RAW-IMAGE since
+  this required Hemlock to know every server/monitor's preferences for raw
+  data.  Fixed pixmap creation to be the root depth instead of 1 when not
+  making cursors.
+
+/usr1/lisp/nhem/hunk-draw.lisp, 22-Oct-88 20:06:02, Edit by Chiles.
+  Made HUNK-REPLACE-LINE-PIXMAP call XLIB:CREATE-PIXMAP with a depth of
+  XLIB:SCREEN-ROOT-DEPTH instead of 1.
+
+/usr1/lisp/nhem/buffer.lisp, 22-Oct-88 16:09:32, Edit by Chiles.
+  Modified %SET-BUFFER-NAME to do the right thing if the name supplied was
+  already in use but for the buffer being affected.  This allows the buffer to
+  be renamed to the same name, but with different casing for display effect.
+
+/usr1/lisp/nhem/filecoms.lisp, 22-Oct-88 16:37:45, Edit by Chiles.
+  Modified "Rename Buffer" to allow users to rename a buffer to the same
+  name,but with different casing for visual effect.
+
+/usr1/lisp/nhem/lispeval.lisp, 21-Oct-88 18:40:11, Edit by Chiles.
+  Made CREATE-SLAVE not mess with the value of "Current Eval Server".  It now
+  uses a special *create-slave-wait* that is set by the connect handler.
+
+/usr1/lisp/nhem/rompsite.lisp, 21-Oct-88 18:08:42, Edit by Chiles.
+  Made EDITOR_CONNECT-HANDLER only affect the :global value of "Current Eval
+  Server".  It also not sets ed::*create-slave-wait* to nil.
+
+/usr1/lisp/nhem/window.lisp, 21-Oct-88 02:26:40, Edit by Chiles.
+  Modified %SET-WINDOW-BUFFER to move the window's display start and ends to
+  the new display-start slot buffers have.
+
+/usr1/lisp/nhem/buffer.lisp, 21-Oct-88 02:25:07, Edit by Chiles.
+  Added initialization for :display-start slot of new buffer.
+
+/usr1/lisp/nhem/struct.lisp, 21-Oct-88 02:23:11, Edit by Chiles.
+  Added display-start slot to the buffer structure.
+
+/usr1/lisp/nhem/lispeval.lisp, 20-Oct-88 22:13:53, Edit by Chiles.
+  MAYBE-QUEUE-OPERATION-REQUEST now informs the user whether the operation is
+  queued to be sent or being sent.
+
+/usr1/lisp/nhem/killcoms.lisp, 17-Oct-88 13:34:26, Edit by Chiles.
+  Made "Set/Pop Mark" only MESSAGE when interactive.
+
+/usr1/lisp/nhem/filecoms.lisp, 17-Oct-88 12:16:08, Edit by Chiles.
+  Installed new "Save All Files" that tells how many files it saved.
+
+/usr1/lisp/nhem/mh.lisp, 14-Oct-88 13:56:45, Edit by Chiles.
+  Made EXPUNGE-MESSAGES-FIX-UNSEEN-HEADERS always set the name back in case the
+  user used "Pick Headers".  Broke off part of it to form
+  MAYBE-GET-NEW-MAIL-MSG-HDRS which is now also called in PICK-MESSAGE-HEADERS.
+  Made "Incorporate and Read New Mail" set the unseen mail buffer's name when
+  it already existed just in case someone used "Pick Headers".
+  PICK-MESSAGE-HEADERS now checks for the new mail buffer, and when the pick
+  expression is empty, it uses MAYBE-GET-NEW-MAIL-MSG-HDRS.
+
+/usr1/lisp/nhem/mh.lisp, 13-Oct-88 11:31:13, Edit by Chiles.
+  PROMPT-FOR-FOLDER was not giving must-exist to PROMPT-FOR-KEYWORD.  It was
+  always passing nil.
+
+/usr1/lisp/nhem/bit-screen.lisp, 12-Oct-88 15:09:10, Edit by Chiles.
+  Reinstalled the better window deletion next merger code.  Commented out the
+  hack in case we run into another asinine window manager.
+
+/usr1/lisp/nhem/lispbuf.lisp, 10-Oct-88 14:03:41, Edit by Chiles.
+  Modified commands that redirected *standard-output* for compiler warnings to
+  now redirect *error-output* to adhere to new compiler
+
+/usr1/lisp/nhem/lispbuf.lisp, 09-Oct-88 16:54:18, Edit by Chiles.
+  Made "Package" file option not choke when it couldn't stringify the thing.
+
+/usr1/lisp/nhem/bindings.lisp, 05-Oct-88 20:24:21, Edit by Chiles.
+  Eliminated bogus BIND-KEY in "Eval" mode for "Confirm Eval Input".
+
+/usr1/lisp/nhem/morecoms.lisp, 04-Oct-88 20:13:34, Edit by Chiles.
+  Made "Uppercase Region" and "Lowercase Region" insist on the region being
+  active.  Made TWIDDLE-REGION, which implements above, take a region instead
+  of two marks.
+
+/usr1/lisp/nhem/htext4.lisp, 04-Oct-88 19:57:55, Edit by Chiles.
+  Modified FILTER-REGION doc string.  Added page titles.
+
+/usr1/lisp/hemlock/bit-display.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/keytrandefs.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/tty-screen.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/bit-screen.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/font.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/window.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/bit-stream.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/hunk-draw.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/main.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/xcoms.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/charmacs.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/rompsite.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/keytran.lisp, 03-October-88, Edit by Chiles.
+/usr1/lisp/hemlock/screen.lisp, 03-October-88, Edit by Chiles.
+  Modified to support X11 using CLX.
+
+/usr1/lisp/nhem/scribe.lisp, 30-Sep-88 14:45:41, Edit by Chiles.
+  Broke up long FORMAT string into several lines of code.  Fixed bug in
+  DIRECTIVE-HELP.
+
+/usr1/lisp/nhem/filecoms.lisp, 27-Sep-88 11:48:10, Edit by Chiles.
+  Added a "Make Buffer Hook" to add all new buffers to the history.  Added some
+  doc and a page title.
+
+/usr1/lisp/nhem/bindings.lisp, 22-Sep-88 22:46:30, Edit by Chiles.
+  Added binding for "Insert Scribe Directive".  Deleted lots of other "Scribe"
+  bindings.
+
+/usr1/lisp/nhem/scribe.lisp, 21-Sep-88 22:48:46, Edit by Chiles.
+  Added new code to dispatch on a character and either insert a Scribe command
+  or environment, instead of having 30 similar commands.  Deleted the following
+  commands entirely:
+     "Scribe Appendix"
+     "Scribe AppendixSection"
+     "Scribe Chapter"
+     "Scribe Heading"
+     "Scribe MajorHeading"
+     "Scribe Paragraph"
+     "Scribe PrefaceSection"
+     "Scribe Section"
+     "Scribe SubHeading"
+     "Scribe SubSection"
+     "Scribe UnNumbered"
+     "Scribe Verbatim"
+     "Scribe Verse"
+  Introduced "List Scribe Paragraph Delimiters".
+  Cleaned up code.
+  Got the stuff working.
+
+/usr1/lisp/nhem/lispmode.lisp, 15-Sep-88 14:31:53, Edit by Chiles.
+  Modified LISP-INDENT-REGION to do it undoably.  It takes an optional argument
+  for the undo text.  "Indent Form" supplies its name when calling this.
+  Documented INDENT-FOR-LISP.  Modified some page boundaries.
+
+/usr1/lisp/nhem/bindings.lisp, 07-Sep-88 16:44:35, Edit by Chiles.
+  Changed "Eval Input" bindings to "Confirm Eval Input".
+
+/usr1/lisp/nhem/lispbuf.lisp, 07-Sep-88 16:43:34, Edit by Chiles.
+  Renamed "Eval Input" to "Confirm Eval Input".
+
+/usr1/lisp/nhem/mh.lisp, 07-Sep-88 13:08:04, Edit by Chiles.
+  Modified DELETE-AND-EXPUNGE-TEMP-DRAFTS one more time.  Now it makes use of
+  MH's :errorp arguement to squelch errors.
+
+/usr1/lisp/hemlock/lispeval.lisp, 30-Aug-88 11:32:53, Edit by DBM.
+  Changed references to slave-utility-name to slave-utility and
+  slave-arguments to slave-utility-switches.
+
+/usr1/lisp/nhem/ts.lisp, 19-Aug-88 21:47:12, Edit by Chiles.
+  Fixed "Unwedge Interactive Input String" according to mail I sent.
+
+/usr1/lisp/nhem/bindings.lisp, 15-Aug-88 12:30:05, Edit by Chiles.
+  Added binding for "Scribe Buffer File".
+
+/usr1/lisp/nhem/lispeval.lisp, 15-Aug-88 11:11:10, Edit by Chiles.
+  Renamed "Slave Utility Name" to "Slave Utility" and
+          "Slave Arguments" to "Slave Utility Switches".
+
+/usr1/lisp/nhem/unixcoms.lisp, 15-Aug-88 11:09:48, Edit by Chiles.
+  Renamed "Print Utility Options" to "Print Utility Switches".  Added Scribe
+  stuff.
+
+/usr1/lisp/nhem/mh.lisp, 09-Aug-88 23:16:09, Edit by Chiles.
+  Made "Expunge Messages" and "Quit Headers" doc strings mention "Temporary
+  Draft Folder".  Modified DELETE-AND-EXPUNGE-TEMPORARY-DRAFTS to do a
+  directory to realize if there were really any messages to blow away.
+
+/usr1/lisp/nhem/doccoms.lisp, 09-Aug-88 22:57:13, Edit by Chiles.
+  Modified "Apropos" to use CURRENT-VARIABLE-TABLES, and cleaned up this moby
+  growing command.
+
+/usr1/lisp/nhem/echo.lisp, 09-Aug-88 22:26:46, Edit by Chiles.
+  Wrote CURRENT-VARIABLE-TABLES, and exported it.  Modified PROMPT-FOR-VARIABLE
+  to use it.
+
+/usr1/lisp/nhem/mh.lisp, 07-Aug-88 04:03:13, Edit by Chiles.
+  "Remail Message".
+
+/usr1/lisp/nhem/filecoms.lisp, 04-Aug-88 22:20:23, Edit by Chiles.
+  Made "Insert File" and "Insert Buffer" push a buffer mark before inserting.
+
+/usr1/lisp/nhem/lispbuf.lisp, 04-Aug-88 21:31:10, Edit by Chiles.
+  Fixed default binding and doc string of "Unwedge Interactive Input Confirm".
+
+/usr1/lisp/nhem/mh.lisp, 30-Jul-88 22:09:59, Edit by Chiles.
+  Fixed a bug with "Reply to Message Prefix Action".  Made "Reply to M in O
+  Window", when invoked in the headers buffer, put the message in the "current"
+  window.
+
+/usr1/lisp/nhem/highlight.lisp, 26-Jul-88 17:26:32, Edit by Chiles.
+  Did away with HIGHLIGHT-ACTIVE-REGION-P.  Replaced calls with
+  REGION-ACTIVE-P.  Made MAYBE-HIGHLIGHT-OPEN-PARENS check the value of
+  "Highlight Active Region" and REGION-ACTIVE-P instead of just the latter.
+
+/usr1/lisp/nhem/killcoms.lisp, 26-Jul-88 17:21:36, Edit by Chiles.
+  Made REGION-ACTIVE-P check for the last command type being a member of
+  *ephemerally-active-command-types*.  Modified "Kill Region" and "Save Region"
+  to call CURRENT-REGION normally.
+
+/usr1/lisp/nhem/lispbuf.lisp, 19-Jul-88 22:35:22, Edit by Chiles.
+  Fixed bug in "Eval Input".
+
+/usr1/lisp/hemlock/linimage.lisp, 27-Jul-88 11:09:17, Edit by DBM.
+/usr1/lisp/hemlock/line.lisp, 27-Jul-88 10:56:33, Edit by DBM.
+  Removed some old Perq cruft.  
+
+/usr1/lisp/nhem/lispbuf.lisp, 19-Jul-88 22:35:22, Edit by Chiles.
+  Fixed bug in "Eval Input".
+
+/usr1/lisp/nhem/filecoms.lisp, 11-Jul-88 12:55:48, Edit by Chiles.
+  Fixed bug in "Visit File" telling the user that the file is already in some
+  buffer.
+
+/usr1/lisp/nhem/doccoms.lisp, 06-Jul-88 23:14:13, Edit by Chiles.
+  Added "Describe Pointer" command and frobbed "Help".
+
+/usr1/lisp/nhem/bindings.lisp, 05-Jul-88 16:34:31, Edit by Chiles.
+  Added bindings for new commands in Commands.Lisp.
+
+  Added initial value for *describe-pointer-keylist*.
+
+/usr1/lisp/nhem/command.lisp, 05-Jul-88 16:36:40, Edit by Chiles.
+  Added "Mark to Beginning of Buffer" "Mark to End of Buffer".
+
+/usr1/lisp/nhem/ts.lisp, 04-Jul-88 15:46:46, Edit by Chiles.
+  Broke "Process Control" up into separate commands.
+
+/usr1/lisp/nhem/filecoms.lisp, 01-Jul-88 23:40:00, Edit by Chiles.
+  made "Visit File" MESSAGE when another buffer also contains the pathname.
+
+/usr1/lisp/nhem/mh.lisp, 29-Jun-88 23:33:40, Edit by Chiles.
+  Wrote "Delete Message and Down Line".
+
+  Made "Deliver Message" say "Delivering draft ...".
+
+  Deleted GET-MESSAGE-HEADERS-SEQ.  Made SET-MESSAGE-HEADERS-IDS optionally
+  return an MH sequence.  These were identical but for this difference.
+
+  Made "Refile Message" and "Delete Message" maintain consistency.
+
+  Made SHOW-MESSAGE-OFFSET-MARK return nil when it couldn't place the mark
+  instead of signalling an error.  Wrote SHOW-MESSAGE-OFFSET-MSG-BUG, and
+  renamed SHOW-MESSAGE-OFFSET-HEADERS to SHOW-MESSAGE-OFFSET-HDRS-BUF.  In a
+  message buffer, we move back to the headers buffer and delete the message
+  buffer.
+
+  Added "Reply to Message Prefix Action" which controls prefix argument actions
+  in "Reply to Message".
+  
+  Removed "Automatic Current Message" feature.
+  Removed DEFHVAR just after "Headers Information".
+  Removed when...show from:
+     "Message Headers"
+     "Pick Headers"
+     INSERT-NEW-MAIL-MESSAGE-HEADERS
+  Modified REVAMP-HEADERS-BUFFER and CLEANUP-HEADERS-BUFFER to always take care
+  of the main message buffer.
+
+
+/usr1/lisp/nhem/bindings.lisp, 27-Jun-88 13:45:22, Edit by Chiles.
+  Added bindings for macroexpansion and reenter input stuff.
+
+  Added new bindings for "Process Control" break up.
+
+
+/usr1/lisp/nhem/lispbuf.lisp, 27-Jun-88 13:34:56, Edit by Chiles.
+  Added "Editor Macroexpand Expression".
+
+  Added "Reenter Interactive Input".
+
+
+/usr1/lisp/nhem/lispeval.lisp, 27-Jun-88 13:33:11, Edit by Chiles.
+  Added "Macroexpand Expression".
+
+/usr1/lisp/nhem/bindings.lisp, 26-Jun-88 20:02:02, Edit by Chiles.
+  Uncommented binding for "Delete Message and Down Line".
+
+/usr1/lisp/nhem/bindings.lisp, 24-Jun-88 16:11:37, Edit by Chiles.
+  Fixed C-c bindings messed up by making C-c a hyper prefix.  Made all c-, m-,
+  and s- bindings be spelled out for consistency.
+
+/usr1/lisp/nhem/mh.lisp, 16-Jun-88 15:02:40, Edit by Chiles.
+  Made "Delete Draft and Buffer" cleanup after split window drafts.
+
+/usr1/lisp/nhem/spellcoms.lisp, 16-Jun-88 12:54:08, Edit by Chiles.
+  Made corrections based on previous corrections undoable and changed message
+  to say "corrected" instead of "replaced".
+
+/usr1/lisp/nhem/mh.lisp, 15-Jun-88 20:04:23, Edit by Chiles.
+  Added MESSAGE's to INCORPORATE-NEW-MAIL.
+
+/usr1/lisp/nhem/lispeval.lisp, 13-Jun-88 19:28:48, Edit by Chiles.
+  Made #\c for "Edit Compiler Errors" center the window around the current
+  error.
+
+/usr1/lisp/nhem/mh.lisp, 10-Jun-88 16:16:58, Edit by Chiles.
+  Fixed a bug in "Headers Refile Message".  It wasn't supplying
+  *refile-default-destination* to PROMPT-FOR-FOLDER when in a message buffer.
+
+/usr1/lisp/nhem/mh.lisp, 10-Jun-88 13:21:55, Edit by Chiles.
+  Made CLEANUP-HEADERS-REFERENCE, when the info is TYPEP 'draft-info, set the
+  replied-to folder and msg to nil.
+
+/usr1/lisp/nhem/lispbuf.lisp, 09-Jun-88 20:17:30, Edit by Chiles.
+  Fixed bug in warning message for "List Compile Group".
+
+/usr1/ch/lisp/files.lisp, 06-Jun-88 23:44:01, Edit by Christopher Hoover.
+   Fixed a bug which caused WRITE-FILE to sometimes lose when given an
+   "access" value.
+
+/usr1/ch/lisp/unixcoms.lisp, 03-Jun-88 15:54:46, Edit by Christopher Hoover.
+  Wrote the command "Unix Filter Region".
+
+/usr1/ch/lisp/auto-save.lisp, 16-May-88 02:31:07, Edit by Christopher Hoover.
+  Fixed the code so that "Auto Save Checkpoint Frequency" is always
+  truncated to an integer to keep (very) bad things from happening.
+
+/usr1/lisp/nhem/spellcoms.lisp, 01-Jun-88 10:46:45, Edit by Chiles.
+  Made "Check Word Spelling" show close words regardless of "Correct Unique
+  Spelling Immediately".
+
+/usr1/lisp/nhem/bindings.lisp, 31-May-88 15:25:23, Edit by Chiles.
+  Bound all alpha chars to "Illegal" in "Headers" and "Message" modes.
+
+/usr1/lisp/nhem/mh.lisp, 25-May-88 11:42:13, Edit by Chiles.
+  Created "Temporary Draft Folder" variable, wrote
+  DELETE-AND-EXPUNGE-TEMP-DRAFTS, and modified "Quit Headers"and "Expunge
+  Messages".
+
+/usr1/lisp/nhem/edit-defs.lisp, 25-May-88 11:09:51, Edit by Chiles.
+  Made "Edit Definition" and "Goto Definition" (which has a new name) use
+  editor Lisp if there is no currently valid slave.
+
+/usr1/lisp/nhem/lispeval.lisp, 25-May-88 02:39:37, Edit by Chiles.
+  Made "Describe Function Call" and "Describe Symbol" use the editor Lisp when
+  the current eval server doesn't exist is invalid.
+
+/usr1/lisp/nhem/mh.lisp, 24-May-88 14:57:36, Edit by Chiles.
+  Changed PROMPT-FOR-MESSAGE to take keyword args adding prompt.  Changed all
+  the call sites.  Made "Message Headers", "Delete Message", "Undelete
+  Message", and "Refile Message" supply particular prompt messages.
+
+  Changed "Quit Headers Confirm" to "Expunge Messages Confirm".
+
+/usr1/lisp/nhem/mh.lisp, 19-May-88 12:14:27, Edit by Chiles.
+  Wrote BREAKUP-MESSAGE-SPEC and added the variable, "Unseen Headers Message
+  Spec".  This affected "Incorporate and Show New Mail" and "Expunge Message".
+
+/usr1/lisp/nhem/mh.lisp, 15-May-88 15:40:24, Edit by Chiles.
+  Made MH-PROFILE-COMPONENT take an optional error-on-open argument, so when
+  this is used for sequence files, and the sequence file is not there or
+  readable, then the command can continue ... assuming the sequence file
+  operation is insignificant if the file cannot be opened.  Made
+  MH-SEQUENCE-LIST use this argument.
+
+  Made MARK-ONE-MESSAGE not write the file on :delete unless the message was
+  really in the sequence before deletion.
+
+/usr1/lisp/nhem/lispmode.lisp, 12-May-88 15:11:15, Edit by Chiles.
+  Added mailer and xlib DEFINDENT forms.
+
+/usr1/lisp/nhem/mh.lisp, 12-May-88 10:45:02, Edit by Chiles.
+  Fixed documentation for "Reply to Message in Other Window".
+
+/usr1/lisp/nhem/mh.lisp, 11-May-88 14:03:29, Edit by Chiles.
+  Wrote "Edit Message Buffer".  Made a bunch of (subseq folder 1) calls be
+  calls to STRIP-FOLDER-NAME for consistency.
+
+/usr1/lisp/nhem/mh.lisp, 11-May-88 10:33:23, Edit by Chiles.
+  Made "Insert Message Region" know about split-window drafts.
+
+/usr1/lisp/hemlock/edit-defs.lisp, 10-May-88 17:11:28, Edit by Chiles.
+  Made "Edit Command Definition" on an argument prompt for a key instead of
+  prompting for a command name.
+
+/usr1/lisp/nhem/mh.lisp, 10-May-88 12:37:40, Edit by Chiles.
+  Made DELETE-HEADERS-LINE-REFERENCES delete message buffers if they are
+  not associated with a draft buffer.  If they are, then it cleans up the
+  reference.
+
+  Wrote "Reply to Message in Other Window" which splits the current window
+  when replying to a message.  Made "Insert Message Buffer" try to delete a
+  window if the draft is a split-window draft.  Made "Deliver Message"
+  delete a window if there are a couple lieing around and the draft is a
+  split-window draft.
+
+/usr1/lisp/nhem/command.lisp, 10-May-88 11:19:21, Edit by Chiles.
+  Added doc strings to "Exit Hemlock" and "Pause Hemlock".
+
+/usr1/lisp/nhem/files.lisp, 09-May-88 16:57:39, Edit by Chiles.
+  Made WRITE-FILE take keywords keep-backup (previously optional) and access.
+  When access is supplied non-nil, it is used as Unix modes with
+  MACH:UNIX-CHMOD.
+
+/usr1/lisp/nhem/doccoms.lisp, 10-May-88 08:27:39, Edit by Chiles.
+  Made "Describe Command" show bindings.  Fixed bindings printing.
+
+/usr1/lisp/nhem/auto-save.lisp, 09-May-88 17:28:05, Edit by Chiles.
+  Made WRITE-CHECKPOINT-FILE call WRITE-FILE the new correct way supplying
+  :access #o600 for read/write by owner only.
+
+/usr1/lisp/nhem/spellcoms.lisp, 09-May-88 10:09:13, Edit by Chiles.
+  Made "Set Buffer Spelling Dictionary" hash on the namestring of the true name
+  instead of what was given.  Made it also add the write hook instead of the
+  "Dictionary" file option.  Stopped modifying "Write File Hook" buffer
+  specifically, using ADD-HOOK now.  Made "Dictionary" file option LOUD-MESSAGE
+  if it couldn't find the dictionary file, blowing the whole thing off.
+  Changed "Message Buffer Insertion Prefix" to four spaces.
+
+/usr1/lisp/nhem/mh.lisp, 09-May-88 09:34:43, Edit by Chiles.
+  Fixed a bug in SETUP-HEADERS-MESSAGE-DRAFT that associated the draft with the
+  headers buffer which caused CLEANUP-DRAFT-BUFFER to try to delete a nil
+  headers mark into the headers buffer.
+
+/usr1/lisp/nhem/mh.lisp, 06-May-88 10:06:23, Edit by Chiles.
+  Renamed SETUP-MSG-BUF-REPLY-DRAFT to SETUP-MESSAGE-BUFFER-DRAFT, modifying it
+  to take a message buffer, message info, and a type.  The type is one of
+  :reply, :compose, or :forward.  It does the right thing.
+
+/usr1/lisp/nhem/tty-display.lisp, 05-May-88 17:26:08, Edit by Chiles.
+  Rewrote CM-OUTPUT-COORDINATE to not use TRUNCATE on floats or LOG.  Changed
+  it from a macro to a function too.  Now it builds the characters in a buffer,
+  using DEVICE-WRITE-STRING to send the chars out.
+
+/usr1/lisp/nhem/mh.lisp, 03-May-88 14:41:30, Edit by Chiles.
+  New Hemlock file.  Ta dah!
+
+/usr1/lisp/nhem/bindings.lisp, 03-May-88 14:55:46, Edit by Chiles.
+  Added new mailer bindings.
+
+/usr1/lisp/nhem/display.lisp, 18-Apr-88 14:30:41, Edit by Chiles.
+  Added DEFVAR for *screen-image-trashed* which was lost due to old bitmap code
+  tossing.
+
+/usr1/lisp/nhem/window.lisp, 19-Apr-88 12:01:26, Edit by Chiles.
+  Inserted code from Owindow.Lisp (previously thrown away due to old bitmap
+  code tossing) that was still necessary for tty redisplay.
+
+/usr1/lisp/nhem/rompsite.lisp, 18-Apr-88 11:02:05, Edit by Chiles.
+  Made HEMLOCK-WINDOW test *hemlock-window-mngt* for being non-nil.
+
+  Removed OBITMAP-SHOW-MARK.
+
+  Removed loading old bitmap files from BUILD-HEMLOCK.
+
+/usr1/lisp/nhem/rompsite.lisp, 06-Apr-88 12:44:22, Edit by Chiles.
+  Made the editer server name default to "[<machine-name>:<user-name>]Editor".
+
+/usr1/lisp/nhem/display.lisp, 04-Apr-88 09:47:08, Edit by Chiles.
+  Removed some references to old bitmap redisplay in comments.
+
+/usr1/lisp/nhem/filecoms.lisp, 04-Apr-88 09:09:45, Edit by Chiles.
+  Changed the default of "Keep Backup Files" and the doc string.
+
+/usr1/lisp/hemlock/obit-display.lisp, 01-Apr-88 16:27:00, Edit by Chiles
+/usr1/lisp/hemlock/obit-screen.lisp, 01-Apr-88 16:27:00, Edit by Chiles
+/usr1/lisp/hemlock/ofont.lisp, 01-Apr-88 16:27:00, Edit by Chiles
+/usr1/lisp/hemlock/owindow.lisp, 01-Apr-88 16:27:00, Edit by Chiles
+/usr1/lisp/hemlock/pane-stream.lisp, 01-Apr-88 16:27:00, Edit by Chiles
+/usr1/lisp/hemlock/pane.lisp, 01-Apr-88 16:27:00, Edit by Chiles
+/usr1/lisp/hemlock/keyboard_codes.lisp, 01-Apr-88 16:27:00, Edit by Chiles
+  These files have been removed from the sources.
+
+/usr1/lisp/nhem/screen.lisp, 01-Apr-88 16:25:47, Edit by Chiles.
+  Made %INIT-SCREEN-MANAGER not regard CONSOLEP.
+
+/usr1/lisp/nhem/rompsite.lisp, 01-Apr-88 16:04:09, Edit by Chiles.
+  Rewrote (that is, mostly blew away a lot of code) GET-EDITOR-TTY-INPUT.  Blew
+  away TRANSLATE-CHAR definition.
+
+  Blew away all console character translation variables.
+
+  Cleaned out console specific code in SETUP-INPUT and RESET-INPUT.
+
+  Blew away use of *editor-console-input*.
+
+  Blew away CONSOLEP.
+
+
+/usr1/lisp/nhem/morecoms.lisp, 30-Mar-88 14:19:12, Edit by Chiles.
+  Removed unnecessary (null b) check in "List Buffers".
+
+/usr1/lisp/nhem/undo.lisp, 25-Mar-88 14:33:23, Edit by Chiles.
+  Massively documented this stuff.
+
+/usr0/ram/group.lisp, 21-Mar-88 13:58:49, Edit by Ram.
+  Changed Do-Active-Group to save and restore the Buffer-Point around the code
+  that hacks on the buffer.  This means that group commands no longer trash the
+  point (which usually left you at the beginning of the buffer).
+
+/usr1/ch/lisp/echocoms.lisp, 21-Mar-88 13:33:57, Edit by Christopher Hoover.
+  Frobbed "Ignore File Types" -- deleted unknowns and added a few common
+  binary formats.
+
+/usr1/ch/lisp/auto-save.lisp, 16-Mar-88 16:54:00, Edit by Christopher Hoover.
+  Made the call to write-region in Auto Save supply NIL as the optional
+  argument for keeping backup files so that the luser does not end up
+  with .CKP.BAK files.
+
+/usr1/ch/lisp/files.lisp, 16-Mar-88 15:59:18, Edit by Christopher Hoover.
+  Made write-region take an optional argument which tells it whether or
+  not to do ":if-exist :rename" or ":if-exist :rename-and-delete".
+  If the argument is not supplied, it looks at the hvar "Keep Backup
+  Files".
+
+/usr1/ch/lisp/filecoms.lisp, 16-Mar-88 15:20:00, Edit by Christopher Hoover.
+  Added the hvar "Keep Backup Files".  This variable controls whether
+  write region deletes .BAK files.
+
+/usr1/ch/lisp/filecoms.lisp, 14-Mar-88 22:14:47, Edit by Christopher Hoover.
+  Removed "c" and "h" from the file type hook which invokes Pascal mode
+  since Pascal mode is worse than Fundamental mode for editing C code.
+  Someday, there will be a real electric C mode.
+
+/usr1/lisp/nhem/rompsite.lisp, 15-Mar-88 21:00:11, Edit by Chiles.
+  Wrote RE-INIT-EDITOR-SERVER to be the port death handler instead of
+  INIT-EDITOR-SERVER.
+
+/usr1/lisp/nhem/morecoms.lisp, 15-Mar-88 16:25:44, Edit by Chiles.
+  Installed Naeem's mods to "Delete Previous Character Expanding Tabs" that
+  saves on the kill ring after some threshold.
+
+/usr1/lisp/nhem/command.lisp, 15-Mar-88 16:24:09, Edit by Chiles.
+  Installed Naeem's mods to "Delete Previous Character" and "Delete Next
+  Character" that saves on the kill ring after some threshold.
+
+/usr1/ch/lisp/echocoms.lisp, 14-Mar-88 21:50:47, Edit by Christopher Hoover
+  Deleted the hvar "Help Show Options" since it is not used anywhere.
+  Added a real doc string for the hvar "Beep on Ambiguity".
+
+  Fixed Complete Keyword for files to use the new whizzy complete-file.
+  Added the hvar "Ignore File Types" to control which file types to
+  ignore.
+
+/usr1/lisp/nhem/morecoms.lisp, 10-Mar-88 20:59:36, Edit by Chiles.
+  Installed "Defhvar" command.
+
+/usr1/lisp/nhem/filecoms.lisp, 10-Mar-88 15:48:57, Edit by Chiles.
+  Modified PROCESS-FILE-OPTIONS to invoke the file type hook when no major mode
+  had been seen, even though some mode option had been specified.  Modified the
+  "Mode" file option handler to return whether it had seen a major mode.
+
+/usr1/lisp/nhem/bit-screen.lisp, 08-Mar-88 14:57:10, Edit by Chiles.
+  Made REVERSE-VIDEO-HOOK-FUN make sure there is an X window for the random
+  typeout stream before trying to set its background.
+
+/usr1/lisp/nhem/fill.lisp, 06-Mar-88 21:28:51, Edit by Chiles.
+  Made %FILLING-SET-NEXT-LINE not call INDENT-NEW-COMMENT-LINE-COMMAND when
+  there is a fill prefix.
+
+/usr1/lisp/nhem/bit-display.lisp, 06-Mar-88 14:15:17, Edit by Chiles.
+  Fixed redisplay bug concerning excessive counting of lines to clear.
+  Otherwise case now stops counting cleared lines and packages off one clear
+  operations if we are currently counting.
+
+/usr1/lisp/nhem/font.lisp, 06-Mar-88 12:46:24, Edit by Chiles.
+  Made *default-font-family* have a default value so MAKE-WINDOW and things
+  trying to look at it under tty redisplay don't choke.
+
+/usr1/lisp/nhem/main.lisp, 02-Mar-88 22:03:26, Edit by Chiles.
+  Changed EXPORT of after-initializations to AFTER-EDITOR-INITIALIZATIONS which
+  is really what the macro is called.
+
+/usr1/lisp/nhem/font.lisp, 02-Mar-88 19:53:10, Edit by Chiles.
+  Rearranged some functions.  Added doc strings for exported stuff.  Deleted
+  hardwired structures.  Moved two parameters to Rompsite.Lisp.  Added logical
+  pages.
+
+/usr1/lisp/nhem/lispbuf.lisp, 02-Mar-88 14:12:30, Edit by Chiles.
+  Made SETUP-EVAL-MODE make a local binding of "Current Package" to nil.
+
+/usr1/lisp/nhem/lispeval.lisp, 02-Mar-88 13:42:49, Edit by Chiles.
+  Modified "Set Buffer Package" to set *package* when in the eval buffer.
+
+/usr1/lisp/nhem/bit-screen.lisp, 01-Mar-88 16:00:24, Edit by Chiles.
+  Made HUNK-MOUSE-ENTERED invoke the "Enter Window Hook" and made
+  HUNK-MOUSE-LEFT invoke the "Exit Window Hook".  Fixed REVERSE-VIDEO-HOOK-FUN
+  to change the background pixmap for a window, so you don't get a flash of
+  white before Hemlock paints black when the window is exposed.
+
+/usr1/lisp/nhem/filecoms.lisp, 24-Feb-88 12:26:07, Edit by Chiles.
+  Changed "Last Resort Pathname Defaults" and "Last Resort Pathname Defaults
+  Function".
+
+/usr1/lisp/nhem/rompsite.lisp, 01-Mar-88 15:29:32, Edit by Chiles.
+  Made SITE-INIT define "Enter Window Hook" and "Exit Window Hook".  Wrote
+  ENTER-WINDOW-AUTORAISE as example hook for losers into autoraising.
+
+  Put in DEFHVAR in SITE-INIT for "Default Font".  Modified INIT-RAW-IO,
+  SETUP-FONT-FAMILY, and OPEN-FONT in conjunction with supporting this new
+  variable.
+
+/usr1/chiles/work/temp-hem/rompsite.lisp, 22-Feb-88 21:07:14, Edit by Chiles.
+  Changed GET-HEMLOCK-CURSOR to not use ".mask" as a pathname, but to use
+  MAKE-PATHNAME :type "mask" ... instead.
+
+/usr1/chiles/work/temp-hem/lispeval.lisp, 22-Feb-88 21:01:49, Edit by Chiles.
+  Changed CLEANUP-COMPILE-NOTIFICATION to not use ".fasl" as a pathname, but to
+  use MAKE-PATHNAME :type "fasl" ... instead.
+
+/usr1/lisp/nhem/filecoms.lisp, 22-Feb-88 17:15:35, Edit by Chiles.
+  Introduced "Last Resort Pathname Defaults" and "Last Resort Pathname Defaults
+  Function" and modified BUFFER-DEFAULT-PATHNAME.
+
+/usr1/lisp/nhem/spellcoms.lisp, 22-Feb-88 16:50:33, Edit by Chiles.
+  Made "Check Word Spelling" output digits with possible correct spellings.
+  Made "Correct Last Misspelled Word" take 0-9 in the command loop as the
+  numbered word to use as a correct spelling.
+
+/usr1/lisp/nhem/morecoms.lisp, 22-Feb-88 13:13:54, Edit by Chiles.
+  Frobbed control flow in "Goto Page" and made it drop a mark when searching
+  page titles a first time.
+
+/usr1/lisp/nhem/auto-save.lisp, 18-Feb-88 17:25:10, Edit by Chiles.
+  Made "Save" mode turn off automatically in "Typescript" and "Eval" modes.
+
+/usr1/lisp/nhem/main.lisp, 18-Feb-88 17:11:12, Edit by Chiles.
+  Put "Save" mode in "Default Modes".
+
+/usr1/lisp/nhem/indent.lisp, 16-Feb-88 14:41:34, Edit by Chiles.
+  Fixed bug "Indent" being called with a zero argument.
+
+/usr1/lisp/nhem/searchcoms.lisp, 16-Feb-88 14:14:32, Edit by Chiles.
+  Made THE four searching commands only drop a mark if the region is not
+  active.  Also, make i-search ^G invoke the abort-hook.  Made incremental
+  searching commands set the last command type to nil since each letter typed
+  does not go through the command loop, and ephemerally active regions were
+  staying highlighted throughout the search.
+
+/usr1/lisp/nhem/lispmode.lisp, 14-Feb-88 20:34:03, Edit by Chiles.
+  Added DEFINDENT's for some CLOS stuff.  Added one for "frob" for Rob and me.
+  Added a few for system calls.
+
+/usr1/lisp/nhem/lispeval.lisp, 11-Feb-88 13:58:31, Edit by Chiles.
+  Made FILE-COMPILE look at a new variable "Remote File Compile".
+
+/usr1/lisp/nhem/lispeval.lisp, 10-Feb-88 20:08:04, Edit by Chiles.
+  Made OLDER-OR-NON-EXISTENT-FASL-P's second argument optional.
+
+/usr1/lisp/nhem/lispbuf.lisp, 10-Feb-88 20:11:14, Edit by Chiles.
+  Made "List Compile Group" use OLDER-OR-NON-EXISTENT-FASL-P.
+
+/usr1/lisp/nhem/highlight.lisp, 10-Feb-88 19:52:50, Edit by Chiles.
+  Modified HIGHLIGHT-ACTIVE-REGION to not do anything when the window is the
+  echo area window.
+
+/usr1/lisp/nhem/killcoms.lisp, 10-Feb-88 15:55:19, Edit by Chiles.
+  Augmented the active region flag with an active region buffer variable to
+  circumvent echo area interactions.
+
+/usr1/lisp/nhem/main.lisp, 10-Feb-88 15:46:29, Edit by Chiles.
+  Made SAVE-ALL-BUFFERS optionally list unmodified buffers.
+
+/usr1/lisp/nhem/highlight.lisp, 08-Feb-88 13:49:37, Edit by Chiles.
+  Implemented highlighting active regions.  Renamed a bunch of open paren
+  highlighting stuff, and frobbed it to interact with region highlighting.
+
+/usr1/lisp/nhem/killcoms.lisp, 08-Feb-88 13:30:20, Edit by Chiles.
+  Made CURRENT-REGION take another option to not deactivate the region.
+
+/usr1/lisp/nhem/rompsite.lisp, 06-Feb-88 16:23:45, Edit by Chiles.
+  Fixed bug in PRETTY-PRINT-CHARACTER that was created by INSERT-CHARACTER
+  checking the type of its arguments.
+
+/usr1/lisp/nhem/lispmode.lisp, 06-Feb-88 16:17:20, Edit by Chiles.
+  Fixed Scan-Direction-Valid to return NIL when it hits the end of the buffer.
+
+/usr1/lisp/nhem/killcoms.lisp, 06-Feb-88 10:11:35, Edit by Chiles.
+  Made "Exchange Point and Mark" no longer activate the region.
+
+/usr1/lisp/nhem/fill.lisp, 06-Feb-88 09:53:14, Edit by Chiles.
+  Made "Fill Paragraph" and "Fill Region" use p as the column if supplied.
+
+/usr1/lisp/nhem/rompsite.lisp, 04-Feb-88 15:33:11, Edit by Chiles.
+  Fixed the font stuff in initialization to not call TRUENAME on the font
+  names.  This was wrong.  Fixed the font stuff to be aware of a font not
+  opening, signalling an error if it is the default font and warning if it was
+  the highlighting font.
+
+/usr1/lisp/nhem/htext3.lisp, 04-Feb-88 16:02:41, Edit by Chiles.
+  Made INSERT-CHARACTER check the type of its argument.
+
+/usr1/lisp/nhem/searchcoms.lisp, 04-Feb-88 15:46:24, Edit by Chiles.
+  Fixed bug in i-search that allowed non-text characters to be searched for.
+  Also in the C-q case, nil was trying to be inserted into a buffer which
+  crashed Lisp.
+
+/usr1/lisp/nhem/command.lisp, 04-Feb-88 14:21:10, Edit by Chiles.
+  Provided error message for TEXT-CHARACTER nil result in "Self Insert" and
+  "Quoted Insert"
+
+/usr1/lisp/nhem/overwrite.lisp, 04-Feb-88 14:17:32, Edit by Chiles.
+  Protected use of TEXT-CHARACTER, testing for nil result.
+
+/usr1/lisp/nhem/lispeval.lisp, 03-Feb-88 11:57:33, Edit by Chiles.
+/usr1/lisp/nhem/lispbuf.lisp, 03-Feb-88 11:57:33, Edit by Chiles.
+  Modified "Compile Buffer File", "Editor Compile Buffer File", "Compile
+  Group", and "Editor Compile Group".  Deleted MAYBE-COMPILE-FILE and
+  MAYBE-COMPILE-EDITOR-FILE.  Wrote OLDER-OR-NON-EXISTENT-FASL-P.
+
+/usr1/lisp/nhem/icom.lisp, 01-Feb-88 16:21:37, Edit by Chiles.
+  Merged Scott's hack to the comment hack to keep highlighted parens clean.
+
+/usr1/lisp/nhem/obit-screen.lisp, 01-Feb-88 16:08:35, Edit by Chiles.
+  Modified OBITMAP-MAKE-WINDOW and OBITMAP-DELETE-WINDOW to invalidate the
+  currently selected hunk.
+
+/usr1/lisp/nhem/tty-screen.lisp, 01-Feb-88 15:56:53, Edit by Chiles.
+  Modified TTY-MAKE-WINDOW and TTY-DELETE-WINDOW to invalidate the currently
+  selected hunk.
+
+/usr1/lisp/nhem/spellcoms.lisp, 01-Feb-88 08:28:09, Edit by Chiles.
+  Fixed MAYBE-READ-DEFAULT-USER-SPELLING-DICTIONARY.
+
+/usr1/lisp/nhem/bindings.lisp, 28-Jan-88 20:46:09, Edit by Chiles.
+  Deleted binding for "Compile Buffer File" in "Editor" mode.
+
+/usr1/lisp/nhem/interp.lisp, 28-Jan-88 11:18:47, Edit by Chiles.
+  Fixed problem with clearing prefix characters from the echo area when a bad
+  sequence is typed.
+
+/usr0/ram/lispmode.lisp, 27-Jan-88 17:21:48, Edit by Ram.
+  Wrote Find-Ignore-Region and used it to implement Valid-Spot and the new
+  Scan-Direction-Valid macro, which efficiently scans for a valid character
+  having the specified properties of its attribute.  Used Scan-Direction-Valid
+  to substantially rewrite %Form-Offset.  It now correctly handles character
+  literals (and as a side-effect, symbols with slashed characters).  Also
+  changed form offset to skip over prefix characters when moving backward over
+  a list.  Users will probably notice this, and hopefully like it.
+
+/usr0/ram/highlight.lisp, 27-Jan-88 17:15:35, Edit by Ram.
+  Changed Form-Offset to List-Offset in Maybe-Highlight-Open-Parens.  Now that
+  backward form offset on lists include prefix characters, Form-Offset is no
+  longer correct.  Directly doing List-Offset is slightly more efficient
+  anyway.
+
+/usr1/lisp/nhem/highlight.lisp, 27-Jan-88 15:29:50, Edit by Chiles.
+  Turned "Highlight Open Parens" off by default.
+
+/usr1/lisp/nhem/lispmode.lisp, 27-Jan-88 15:32:12, Edit by Chiles.
+  Turned "Paren Pause Period" and "Highlight Open Parens" on in "Lisp" mode.
+  Set "Paren Pause Period" to 0.5 by default.
+
+/usr1/lisp/nhem/tty-screen.lisp, 27-Jan-88 15:32:57, Edit by Chiles.
+  Made INIT-TTY-SCREEN-MANAGER make "Paren Pause Period" and "Highlight Open
+  Parens" be off in "Lisp" mode for tty's since we don't have highlighting
+  fonts for tty's.
+
+/usr1/lisp/hemlock/highlight.lisp, 25-Jan-88 16:19:49, Edit by DBM.
+  Chanded default for "Highlight Open Parens" to T.
+
+/usr1/lisp/nhem/newer/rompsite.lisp, 25-Jan-88 11:30:43, Edit by Chiles.
+  Made SLEEP-FOR-TIME deal with noting a read wait (dropping and lifting the
+  cursor).
+
+/usr1/lisp/nhem/main.lisp, 25-Jan-88 11:11:10, Edit by Chiles.
+  Entered DEFHVAR for "Key Echo Delay".
+
+/usr1/lisp/nhem/newer/interp.lisp, 25-Jan-88 11:06:01, Edit by Chiles.
+  Frobbed %COMMAND-LOOP to try to echo keys after some typing delay.
+
+/usr1/lisp/nhem/newer/lispeval.lisp, 24-Jan-88 19:43:50, Edit by Chiles.
+  Made DELETE-SERVER look for all bindings of "Current Eval Server", setting
+  them to nil if they referenced the argument info object.  Also made it delete
+  the "Server Information" variable in the slave buffer if there was one.
+
+/usr1/lisp/nhem/newer/rompsite.lisp, 24-Jan-88 19:10:52, Edit by Chiles.
+  Modified EDITOR_CONNECT-HANDLER to define "Server Information" in the slave
+  buffer.
+
+/usr1/lisp/nhem/newer/command.lisp, 24-Jan-88 15:33:09, Edit by Chiles.
+  Installed Shareef's "Refresh Screen" that knows about arguments.
+
+/usr1/lisp/nhem/newer/lispmode.lisp, 24-Jan-88 15:27:06, Edit by Chiles.
+  Fixed bug in "Lisp Insert )" to make it echo the closing paren if it is not
+  DISPLAYED-P regardless of "Paren Pause Period".
+
+/usr1/lisp/nhem/highlight.lisp, 23-Jan-88 15:43:59, Edit by Chiles.
+  New file.
+
+/usr1/lisp/nhem/scribe.lisp, 23-Jan-88 15:42:11, Edit by Chiles.
+  Modified SCRIBE-INSERT-PAREN to know about "Paren Pause Period" possibly
+  being nil.
+
+/usr1/lisp/nhem/lispmode.lisp, 23-Jan-88 15:40:57, Edit by Chiles.
+  Modified "Lisp Insert )" to know about "Paren Pause Period" possibly being
+  nil.
+
+/usr1/lisp/nhem/morecoms.lisp, 23-Jan-88 15:36:22, Edit by Chiles.
+  Fixed "Mark Page" when point is at buffer-end.
+
+/usr1/lisp/nhem/srccom.lisp, 23-Jan-88 15:26:40, Edit by Chiles.
+  Put "Buffer Changes" from my init file into the core.
+
+/usr1/lisp/nhem/filecoms.lisp, 23-Jan-88 15:21:36, Edit by Chiles.
+  Modified "Revert File" to be more aware of whether it was backing up to the
+  checkpoint file or the saved file.
+
+/usr1/lisp/nhem/display.lisp, 23-Jan-88 14:01:50, Edit by Chiles.
+  Changed REDISPLAY-LOOP and REDISPLAY-WINDOWS-FROM-MARK to do the current
+  window first if it is going to get done, so the redisplay-hook effects could
+  be seen in other windows into the same buffer.
+
+/usr1/lisp/nhem/edit-defs.lisp, 23-Jan-88 14:47:28, Edit by Chiles.
+  Modified DEFINITION-EDITING-INFO to correspond to the new
+  FUN-DEFINED-FROM-PATHNAME ability to deal with encapsulations.
+
+/usr1/lisp/nhem/rompsite.lisp, 23-Jan-88 14:36:33, Edit by Chiles.
+  Modified FUN-DEFINED-FROM-PATHNAME, now deals with encapsulations.
+
+/usr1/lisp/nhem/indent.lisp, 23-Jan-88 13:42:43, Edit by Chiles.
+  Added Shareef's "Center Line" command.
+
+/usr1/lisp/nhem/files.lisp, 23-Jan-88 12:42:10, Edit by Chiles.
+  Made WRITE-FILE supply :if-exists :rename-and-delete.
+
+/usr1/lisp/nhem/lispeval.lisp, 23-Jan-88 12:28:13, Edit by Chiles.
+  Made "Compile File" signal an error when buffer has no associated pathname.
+
+/usr1/ch/lisp/filecoms.lisp, 22-Jan-88 11:48:49, Edit by Christopher Hoover
+  Fixed write-region to call (current-region) before prompting for filename.
+  This makes it work better with active regions.
+
+/usr1/chiles/work/modeline/window.lisp, 19-Jan-88 09:58:24, Edit by Chiles.
+  Modified DEFAULT-MODELINE-FUNCTION-FUNCTION and wrote
+  UPDATE-BUFFER-MODELINES, which is exported.
+
+/usr1/chiles/work/modeline/main.lisp, 19-Jan-88 10:10:27, Edit by Chiles.
+  Changed the value of "Default Modeline String".
+
+/usr1/chiles/work/modeline/lispmode.lisp, 19-Jan-88 10:05:31, Edit by Chiles.
+  Wrote SETUP-LISP-MODE to make a "Current Package" if there wasn't one already.
+
+/usr1/chiles/work/modeline/lispeval.lisp, 19-Jan-88 09:49:29, Edit by Chiles.
+  Made "Set Buffer Package" use PROMPT-FOR-EXPRESSION, using STRING on the
+  result.  It also now calls UPDATE-BUFFER-MODELINES.  When in a slave's
+  interactive buffer's, do NOT set "Current Package", but change *package* in
+  the slave.  Modified sites of (value current-package) to supply "" instead of
+  the editor's *package*.
+
+/usr1/lisp/nhem/lispbuf.lisp, 18-Jan-88 12:50:34, Edit by Chiles.
+  Modified "package" file option to do a STRING of a READ-FROM-STRING.
+
+/usr1/lisp/nhem/ts.lisp, 17-Jan-88 20:53:13, Edit by Chiles.
+  Made MAKE-TYPESCRIPT use "Interactive History Length" when setting up
+  "Interactive History".
+
+/usr1/lisp/nhem/lispbuf.lisp, 17-Jan-88 20:51:25, Edit by Chiles.
+  Moved some stuff around.  Created "Interactive History Length" used to setup
+  "Interactive History" when "Eval" mode is turned on.
+
+/usr1/lisp/nhem/spellcoms.lisp, 16-Jan-88 16:58:31, Edit by Chiles.
+  Introduced "Default User Spelling Dictionary".  When set, this is loaded upon
+  entering "Spell" mode and when "Set Buffer Spelling Dictionary" (or
+  "dictionary" file option) runs.  Also, "Save Incremental Spelling Insertions"
+  doesn't prompt for a file if this is set.
+
+  Made SAVE-DICTIONARY-ON-WRITE make sure 'spell-information is bound in the
+  buffer.
+
+/usr1/ch/lisp/auto-save.lisp, 12-Jan-88 16:28:56, Edit by Christopher Hoover
+  Wrapped a condition-case around the write-file in Auto Save.  This will cause
+  Auto Save to graceful handle write failures.
+
+/usr1/lisp/nhem/spellcoms.lisp, 06-Jan-88 22:14:14, Edit by Chiles.
+  Made incremental insertions dictionary specific with a global default for
+  upward compatability.
+    Commands with new names:
+      "Append to Spelling Dictionary" --> "Save Incremental Spelling Insertions"
+      "Augment Spelling Dictionary" --> "Read Spelling Dictionary"
+    New commands:
+      "Set Buffer Spelling Dictionary"
+      "Remove Word from Spelling Dictionary"
+      "List Incremental Spelling Insertions"
+  AND there is a "dictionary" file option that read a dictionary if necessary,
+  makes it the buffer's dictionary, and causes the incremental insertions for
+  this dictionary to be written when the buffer is.
+
+  Added "Spelling Un-Correct Prompt for Insert" that makes "Undo Last Spelling
+  Correction" prompt before inserting word into dictionary.
+
+/usr1/lisp/nhem/doccoms.lisp, 22-Dec-87 15:42:26, Edit by Chiles.
+  Changed #\S help to #\V, "Describe and show Variable".  Rewrote some code to
+  do this and added the command "Describe and show Variable".
+
+/usr1/lisp/nhem/spell-augment.lisp, 17-Dec-87 21:05:37, Edit by Chiles.
+  Added SPELL-ROOT-FLAGS, which returns a list of the letter flags a root entry
+  has, and SPELL-REMOVE-ENTRY, which removes an entry by clearing a flag if
+  appropriate or setting the dictionary element to -1.
+
+/usr1/lisp/nhem/spell-correct.lisp, 17-Dec-87 20:34:09, Edit by Chiles.
+  Made TRY-WORD-ENDINGS return the flag mask when a flag was used instead of
+  just t.  Modified lookup hashing to know about deleted elements.
+
+/usr1/lisp/nhem/echo.lisp, 16-Dec-87 21:25:58, Edit by Chiles.
+  MAYBE-WAIT should really do a SLEEP instead of EDITOR-SLEEP to make sure
+  nothing happens while the user is trying to see the message.
+
+/usr1/lisp/nhem/active/text.lisp, 14-Dec-87 01:25:42, Edit by Chiles.
+  Made "Mark Paragraph" and "Mark Sentence" use PUSH-BUFFER-MARK, so it will
+  activate the region.
+
+/usr1/lisp/nhem/active/lispmode.lisp, 14-Dec-87 01:25:03, Edit by Chiles.
+  Made "Mark Defun" and "Mark Form" use PUSH-BUFFER-MARK, so it will activate
+  the region.
+
+/usr1/lisp/nhem/active/morecoms.lisp, 13-Dec-87 20:45:48, Edit by Chiles.
+  Modified "Insert Page Directory" to insert the listing at the curren point if
+  invoked with an argument.
+
+/usr1/lisp/nhem/active/lispeval.lisp, 12-Dec-87 13:15:04, Edit by Chiles.
+  Defined "Slave Utility Name" and "Slave Arguments" and made CREATE-SLAVE use
+  these to spawn Lisps.
+
+/usr1/lisp/nhem/active/main.lisp, 11-Dec-87 07:24:44, Edit by Chiles.
+  Defined and invoked "Reset Hook".
+
+/usr1/lisp/nhem/active/xcommand.lisp, 11-Dec-87 05:37:26, Edit by Chiles.
+  Made "Region to Cut Buffer" use CURRENT-REGION, insisting it be active.
+
+/usr1/lisp/nhem/active/lispbuf.lisp, 11-Dec-87 05:16:46, Edit by Chiles.
+  Made commands use CURRENT-REGION, insisting it be active.  Changed the
+  semantics of "Editor Compile Defun" "Editor Evaluate Defun".
+
+/usr1/lisp/nhem/active/indent.lisp, 11-Dec-87 03:49:08, Edit by Chiles.
+  Made "Indent Region" and "Indent Rigidly" use CURRENT-REGION, insisting it be
+  active.
+
+/usr1/lisp/nhem/active/fill.lisp, 11-Dec-87 03:16:15, Edit by Chiles.
+  Made "Fill Region" use CURRENT-REGION, insisting it be active.
+
+/usr1/lisp/nhem/active/filecoms.lisp, 11-Dec-87 03:12:25, Edit by Chiles.
+  Made "Write Region" use CURRENT-REGION, insisting it be active.
+
+/usr1/lisp/nhem/active/abbrev.lisp, 11-Dec-87 03:05:12, Edit by Chiles.
+  Modified commands to use CURRENT-REGION, not insisting it be active.
+
+/usr1/lisp/nhem/active/morecoms.lisp, 11-Dec-87 02:40:31, Edit by Chiles.
+  Changed calls to PUSH-BUFFER-MARK that shouldn't activate the region.  Made
+  "Count Lines Region" and "Count Words Region" use CURRENT-REGION, not
+  insisting it be active (for now).  "Insert Page Directory" sets the command
+  type to :ephemerally-active, so "Kill Region" can kill the inserted text.
+
+/usr1/lisp/nhem/active/lispeval.lisp, 11-Dec-87 01:52:20, Edit by Chiles.
+  Made "Edit Compiler Errors" not activate the region when it calls
+  PUSH-BUFFER-MARK.  Made commands use CURRENT-REGION, insisting it be active.
+  Changed the semantics of "Compile Defun" and "Evaluate Defun".  Fixed bug in
+  FILE-COMPILE-TEMP-FILE.
+
+/usr1/lisp/nhem/active/edit-defs.lisp, 11-Dec-87 01:32:31, Edit by Chiles.
+  Made GO-TO-DEFINITION not activate the region when it calls
+  PUSH-BUFFER-MARK.
+
+/usr1/lisp/nhem/active/command.lisp, 11-Dec-87 01:25:22, Edit by Chiles.
+  Made "Beginning of Buffer" and "End of Buffer" not activate the region when
+  they call PUSH-BUFFER-MARK.
+
+/usr1/lisp/nhem/active/register.lisp, 11-Dec-87 01:01:22, Edit by Chiles.
+  Fixed bug in cleanup for deleted buffers -- should free register when its a
+  mark since you cannot list it.  Made "Get Register" set LAST-COMMAND-TYPE to
+  :ephemerally-active, so "Kill Region" can kill the inserted text.
+
+/usr1/lisp/nhem/active/bindings.lisp, 10-Dec-87 23:41:40, Edit by Chiles.
+  Added bindings for "Activate Region", "Pop and Goto Mark", and "Pop Mark".
+  Bound "Verbose Directory" to ^X^D and destroyed translation for ^D, so I
+  duplicated bindings for "Delete Next Character" and "Scribe Display".
+
+/usr1/lisp/nhem/macros.lisp, 10-Dec-87 16:49:39, Edit by Chiles.
+  Made ADD-HOOK	use PUSHNEW.
+
+/usr1/lisp/nhem/register.lisp, 10-Dec-87 00:08:00, Edit by Chiles.
+  New Register hacking code.
+
+/usr1/lisp/nhem/bindings.lisp, 09-Dec-87 13:55:22, Edit by Chiles.
+  Made bindings for "Transpose Regions" and "Directory".
+  Added default bindings for register stuff.
+
+/usr1/lisp/nhem/morecoms.lisp, 09-Dec-87 13:36:55, Edit by Chiles.
+  Added "Transpose Regions".
+
+/usr1/lisp/nhem/doccoms.lisp, 09-Dec-87 13:20:28, Edit by Chiles.
+  Wrote "Show Variable".
+
+/usr1/lisp/nhem/echo.lisp, 09-Dec-87 13:04:50, Edit by Chiles.
+  Modified PROMPT-FOR-VARIABLE and wrote VARIABLE-VERIFICATION-FUNCTION to
+  notice when a variable completion lost due to multiple entries of the same
+  variable.
+
+/usr1/lisp/nhem/spellcoms.lisp, 09-Dec-87 01:05:57, Edit by Chiles.
+  Made "Append to Spelling Dictionary" take an optional file argument.
+
+/usr1/lisp/nhem/edit-defs.lisp, 08-Dec-87 18:18:44, Edit by Chiles.
+  Merged with lost sources to get back the preference translation functionality
+  where one directory can be mapped to an ordered list of translations.
+
+/usr1/lisp/nhem/lispeval.lisp, 08-Dec-87 22:54:12, Edit by Chiles.
+  Modifed eval-notification structure, EVAL-OPERATION_COMPLETE, REGION-EVAL,
+  and FILE-COMPILE-TEMP-FILE.  Wrote PATHNAME-FOR-REMOTE-ACCESS and STRING-EVAL
+  and the command "Load File".
+
+/usr1/lisp/nhem/lispbuf.lisp, 08-Dec-87 19:48:43, Edit by Chiles.
+  Renamed "Load File" to be "Editor Load File".
+
+/usr1/lisp/nhem/main.lisp, 05-Dec-87 18:14:19, Edit by Chiles.
+  Defined "Redisplay Hook".
+
+/usr1/lisp/nhem/display.lisp, 05-Dec-87 15:37:53, Edit by Chiles.
+  Put a redisplay hook into REDISPLAY-WINDOW-RECENTERING.
+
+/usr1/lisp/nhem/rompsite.lisp, 04-Dec-87 21:10:14, Edit by Chiles.
+  Made SITE-WRAPPER-MACRO bind *standard-input* to a stream that disallows
+  reads.  This is to keep people from losing in "Eval" mode.
+
+/usr1/lisp/nhem/filecoms.lisp, 04-Dec-87 15:00:50, Edit by Chiles.
+  Made "Visit File" set buffer-writable, so the buffer's region could be
+  deleted when the buffer was read only.
+
+/usr1/lisp/nhem/edit-defs.lisp, 04-Dec-87 14:54:21, Edit by Chiles.
+  Created "Editor Definition Info" variable to control where "Edit
+  Definition" and "Go to Definition" get their defined from information,
+  the editor Lisp or the slave Lisp.
+
+/usr1/lisp/nhem/lispbuf.lisp, 04-Dec-87 13:52:46, Edit by Chiles.
+  Made "Editor Definition Info" t in "Eval" mode.
+
+/usr1/lisp/nhem/lispeval.lisp, 04-Dec-87 13:53:20, Edit by Chiles.
+  Made "Editor Definition Info" t in "Editor" mode.
+
+/usr1/lisp/hemlock/lispeval.lisp, 02-Dec-87 13:23:27, Edit by DBM.
+  Mofified for new name server.
+
+/usr1/lisp/hemlock/rompsite.lisp, 02-Dec-87 13:22:10, Edit by DBM.
+  Modified for new name server.
+
+/usr1/lisp/nhem/bit-screen.lisp, 29-Nov-87 22:55:03, Edit by Chiles.
+  Made BITMAP-DELETE-WINDOW call REMOVE-XWINDOW-OBJECT on the X window
+  instead of the Hemlock window.
+
+/usr1/lisp/nhem/auto-save.lisp, 23-Nov-87 15:59:36, Edit by Chiles.
+  Picked up Chris' latest version.  Tweaked a defvar into a defhvar.
+  Changed its reference and made "Save" mode be turned off when nil or an
+  empty pathname is returned.
+
+/usr1/lisp/nhem/lispeval.lisp, 23-Nov-87 14:33:19, Edit by Chiles.
+  Fixed logic error in GET-CURRENT-SERVER.
+
+/usr1/lisp/nhem/lispeval.lisp, 20-Nov-87 14:17:52, Edit by Chiles.
+  Wrote CALL-EVAL_FORM that makes sure the server isn't busy, binds and
+  error handler, and binds a server death handler.  EVAL_FORM-IN-CLIENT and
+  "Re-Evaluate Defvar" use this.
+
+/usr1/lisp/nhem/rompsite.lisp, 20-Nov-87 13:22:23, Edit by Chiles.
+  Made GET-HEMLOCK-CURSOR do a TRUENAME on the cursor bitmap file variable.
+
+/usr1/lisp/nhem/searchcoms.lisp, 20-Nov-87 11:56:35, Edit by Chiles.
+  "Delete Matching Lines" modified and new "Delete Non-Matching Lines" by
+  Chris. 
+
+/usr1/lisp/nhem/killcoms.lisp, 20-Nov-87 11:58:26, Edit by Chiles.
+  "Delete Blank Lines" added by Chris.
+
+/usr1/lisp/nhem/bindings.lisp, 20-Nov-87 12:06:58, Edit by Chiles.
+  Added binding for "Delete Blank Lines".
+
+/usr1/lisp/nhem/morecoms.lisp, 20-Nov-87 12:10:21, Edit by Chiles.
+  Added Chris' "Count Words Region".
+
+/usr1/lisp/nhem/bit-screen.lisp, 19-Nov-87 00:02:04, Edit by Chiles.
+  Fixed problem with flushing random typeout with the mouse over the
+  typeout window.  Apparently when X buries a window, you do not get an
+  exit event, but Hemlock was getting an entered event and causing the
+  cursor to get out of sync.
+
+/usr1/lisp/nhem/lispeval.lisp, 18-Nov-87 22:39:54, Edit by Chiles.
+  Rewrote CHECK-SERVER-INFO, SUB-CHECK-SERVER-INFO, and GET-CURRENT-SERVER.
+  Added MAYBE-CREATE-SLAVE in the process.  Now when the current eval
+  server dies, the next Lisp interaction command does not signal an error
+  but tries to get a valid slave for the user.
+
+/usr1/lisp/nhem/rompsite.lisp, 18-Nov-87 01:07:02, Edit by Chiles.
+  Wrote EDITOR-INPUT-METHOD-MACRO to replace the bodies of EDITOR-TTY-IN
+  and EDITOR-WINDOW-IN.  Added to the macro a test for re-entering a
+  Hemlock input method, signalling an error if this happens.  Added a
+  binding of an error condition handler that exits Hemlock and goes into
+  the debugger.
+
+/usr1/lisp/hemlock/bit-screen.lisp, 17-Nov-87 17:03:15, Edit by Chiles.
+  Made enter and exit window event handlers call CURSOR-INVERT-CENTER when
+  the cursor is dropped.
+
+/usr1/lisp/nhem/lispeval.lisp, 17-Nov-87 15:40:42, Edit by Chiles.
+  Made CREATE-SLAVE not call INIT-EDITOR-SERVER since we presumably catch
+  nameserver crashes now.
+
+/usr1/lisp/nhem/lispbuf.lisp, 15-Nov-87 20:30:20, Edit by Chiles.
+  Made "Compile File" do an update compilation.
+
+/usr1/lisp/nhem/lispeval.lisp, 15-Nov-87 20:11:12, Edit by Chiles.
+  Made "Compile File" do an update compilation.
+
+/usr1/lisp/nhem/main.lisp, 15-Nov-87 18:20:19, Edit by Chiles.
+  Fixed doc string of ED to escape some "'s.
+
+/usr1/lisp/nhem/morecoms.lisp, 15-Nov-87 17:27:12, Edit by Chiles.
+  Made "Exit Recursive Edit" and "Abort Recursive Edit" call
+  IN-RECURSIVE-EDIT, signalling an error when nil.
+
+/usr1/lisp/nhem/buffer.lisp, 15-Nov-87 16:48:01, Edit by Chiles.
+  Made EXIT-RECURSIVE-EDIT and ABORT-RECURSIVE-EDIT signal an error when
+  not in a recursive edit.  Wrote IN-RECURSIVE-EDIT.
+
+/usr1/lisp/nhem/lispbuf.lisp, 15-Nov-87 13:45:32, Edit by Chiles.
+  Made "Load File" supply (or load default buffer pathname default) for
+  :default to PROMPT-FOR-FILE.
+
+/usr1/lisp/nhem/, 15-Nov-87 13:24:00, Edit by Chiles.
+  Renamed Integrity.Lisp to Hi-Integrity.Lisp.  Created Ed-Integrity.Lisp
+  that currently includes tty redisplay testing code.  Modified Ctw.Lisp to
+  conform with these two changes.
+
+/usr1/lisp/nhem/tty-display.lisp, 15-Nov-87 12:35:09, Edit by Chiles.
+  Generally added major gobs of documentation.
+  Modified:
+     COMPUTE-TTY-CHANGES
+        Introduced cum-inserts.
+        Changed computation of line deletions location.
+        Changed where deletions are done for the modeline due to excessive
+           insertion above it.
+     DO-SEMI-DUMB-LINE-WRITES
+        Commented out a somewhat bogus optimization that was causing
+           TTY-SMART-WINDOW-REDISPLAY to lose when "Scroll Redraw Ration"
+           kicked in.
+     DELETE-SI-LINES
+     INSERT-SI-LINES
+        Changed variable names.
+
+/usr1/lisp/nhem/filecoms.lisp, 14-Nov-87 13:38:42, Edit by Chiles.
+  Made "Write Region" use BUFFER-PATHNAME-DEFAULTS.
+
+/usr1/lisp/nhem/lispeval.lisp, 11-Nov-87 21:54:53, Edit by Chiles.
+  Modified "Edit Compiler Errors" to not switch to errors buffer unless it
+  has too.  This fixes spurious redisplay when there are no errors to edit.
+
+/usr1/lisp/nhem/main.lisp, 10-Nov-87 19:19:13, Edit by Chiles.
+  Removed DEFHVAR's for "Timer Hook" and "Timer Hook Interval".
+
+/usr1/lisp/nhem/rompsite.lisp, 10-Nov-87 19:15:25, Edit by Chiles.
+  Added page title "Time queue".  This is used in editor input stream in
+  methods in conjunction with user interfaces SCHEDULE-EVENT and
+  REMOVE-SCHEDULED-EVENT to all the user to have functions invoked
+  periodically.
+
+/usr1/lisp/nhem/main.lisp, 09-Nov-87 21:23:37, Edit by Chiles.
+  Added AFTER-EDITOR-INITIALIZATIONS macro.  Made ED funcall stuff on
+  *after-editor-initializations-funs* put there by the macro.
+
+/usr1/lisp/nhem/filecoms.lisp, 06-Nov-87 00:59:21, Edit by Chiles.
+  Modified WRITE-DA-FILE and READ-DA-FILE to invoke the "Write File Hook"
+  and "Read File Hook" hooks.  eh!
+
+/usr2/lisp/nhem/lispeval.lisp, 26-Oct-87 11:36:35, Edit by Chiles.
+  Put back in feature of restoring previous buffer in "Edit Compiler
+  Errors" that was lost somehow.
+
+/usr2/lisp/nhem/filecoms.lisp, 25-Oct-87 17:13:04, Edit by Chiles.
+  ROB: Split two subfunctions off of "Find File".  FIND-FILE-BUFFER does
+  all the work, returning the buffer and a flag indicating whether it
+  created a buffer.  Fixed some :prompt values.
+
+/usr2/lisp/nhem/edit-defs.lisp, 25-Oct-87 16:42:00, Edit by Chiles.
+  Fixed bug in GET-DEFINITION-PATTERN for type :command.
+
+/usr0/ram/group.lisp, 04-Oct-87 15:10:49, Edit by Ram.
+  Changed Group-Read-File to use Find-File-Buffer instead of Find-File-Command,
+  eliminating the need for gruesome hacks to tell whether a buffer was created.
+  This also has the beneficial side-effect of making it easy for group commands
+  to leave to buffer history intact.  Changed Do-Active-Group to restore the
+  buffer that was current at the time the command was done.
+
+/usr1/lisp/hemlock/hunk-draw.lisp, 23-Oct-87 15:45:14, Edit by Chiles.
+  Wrote CURSOR-INVERT-CENTER to hollow out the center of the cursor.  THis
+  is used when Hemlock is not the listener to corresspond with Xterm
+  behaviour.  Modified DROP-CURSOR and LIFT-CURSOR to use this new fun too
+  when Hemlock is not the listener, so we don't get little black squares or
+  empty boxes when we should.
+
+/usr2/lisp/nhem/filecoms.lisp, 23-Oct-87 15:36:25, Edit by Chiles.
+  Inserted Chris Hoover's "Revert File" and "Mode" file option definitions.
+
+/usr2/lisp/nhem/hunk-draw.lisp, 23-Oct-87 15:24:36, Edit by Chiles.
+  Fixed documentation for DRAW-HUNK-BOTTOM-BORDER and HUNK-REPLACE-MODELINE,
+  stating dependencies on BITMAP-HUNK-MODELINE-POS not returning nil.
+
+/usr2/lisp/nhem/bit-screen.lisp, 23-Oct-87 15:16:40, Edit by Chiles.
+  Fixed a usage of BITMAP-HUNK-MODELINE-POS that was assuming it was never
+  nil.
+
+/usr1/lisp/hemlock/lispeval.lisp, 23-Oct-87 12:10:09, Edit by DBM.
+  File-compile, Region-eval, and region-compile were passing a
+  structure as a port to the servers.
+
+/usr2/lisp/nhem/bindings.lisp, 23-Oct-87 11:58:45, Edit by Chiles.
+  Killed bindings for c-m-c and c-m-\c in "Echo Area".
+
+/usr2/lisp/nhem/bit-screen.lisp, 22-Oct-87 15:43:08, Edit by Chiles.
+  Fixed BITMAP-MAKE-WINDOW to set the thumb-bar-p slot to (and
+  modeline-string (value thumb-bar-meter)) instead of just the Hvar's
+  value.  Windows without modelines were get a nil not number error.
+
+/usr2/lisp/nhem/lispbuf.lisp, 16-Oct-87 14:04:38, Edit by Chiles.
+  Made DESCRIBE-SYMBOL-AUX slightly better with respect to (quote <symbol>)
+  (function <symbol>).
+
+/usr2/lisp/nhem/lispeval.lisp, 15-Oct-87 22:22:13, Edit by Chiles.
+  Made DESCRIBE-SYMBOL-AUX slightly better with respect to (quote <symbol>)
+  (function <symbol>).
+
+/usr2/lisp/nhem/edit-defs.lisp, 15-Oct-87 21:02:29, Edit by Chiles.
+  Added a hack to catch command definitions when looking for the name of a
+  function, and the last sever letters of the function name are "COMMAND".
+
+/usr2/lisp/nhem/bit-screen.lisp, 15-Oct-87 16:33:54, Edit by Chiles.
+  Made HUNK-EXPOSED-OR-CHANGED take a width and height argument since the X
+  exposedwindow handler is supposed to now and eliminated the call to
+  FULL-WINDOW-STATE.
+
+/usr1/lisp/hemlock/rompsite.lisp, 12-Oct-87 16:56:14, Edit by DBM.
+  Added auto-save.fasl to list of files loaded.
+
+/usr1/lisp/hemlock/auto-save.lisp, 12-Oct-87 16:49:34, Edit by DBM.
+  Added to the hemlock sources.
+
+/usr2/lisp/nhem/lispeval.lisp, 06-Oct-87 00:18:25, Edit by Chiles.
+  Modified "Edit Compiler Errors" to save a pointer to the previous buffer
+  when moving to the background buffer, and to use this before EDITOR-ERROR
+  calls to restore the user's position.
+
+/usr2/lisp/nhem/edit-defs.lisp, 01-Oct-87 14:06:00, Edit by Chiles.
+  Rewrote translation stuff and GO-TO-DEFINITION to handle a list of
+  translations for a given match.  This allows me to first look on
+  vancouver, then wb1, then lisp-rt1, then fred, etc. for sources depending
+  on which machines are down.
+
+/usr2/lisp/nhem/filecoms.lisp, 01-Oct-87 12:20:46, Edit by Chiles.
+  Modified "Save All Files" to show the file it is going to write when
+  prompting, and when the buffer name is not derived from the pathname, it
+  shows both.
+
+/usr2/lisp/nhem/bit-screen.lisp, 30-Sep-87 22:39:37, Edit by Chiles.
+  Rewrote BITMAP-DELETE-WINDOW to not lose when a window is made and then
+  deleted right away.  Created DELETING-WINDOW-DROP-EVENT that drops
+  pending events for a window that is about to be deleted.  Also, made
+  BITMAP-DELETE-WINDOW lift the cursor when the window being deleted
+  displayed the cursor.
+
+/usr2/lisp/nhem/ts.lisp, 30-Sep-87 21:57:18, Edit by Chiles.
+  Made PROCESS_OPERATION_CONTROL-HANDLER test for *in-top-level-catcher*
+  before throwing to top level.
+
+/usr2/lisp/nhem/tty-display.lisp, 29-Sep-87 15:40:22, Edit by Chiles.
+  Modified TTY-SMART-CLEAR-TO-EOW and TTY-DUMB-WINDOW-REDISPLAY to clear
+  screen image lines properly ... had some off-by-one problems.
+
+/usr2/lisp/nhem/lispbuf.lisp, 28-Sep-87 12:59:25, Edit by Chiles.
+  Made "Editor Compile Defun" and "Editor Compile Region" call
+  COMPILE-FROM-STREAM with :defined-from-pathname supplied as the buffer's
+  pathname. 
+
+/usr2/lisp/nhem/rompsite.lisp, 28-Sep-87 11:21:07, Edit by Chiles.
+  Made FUN-DEFINED-FROM-PATHNAME test for "/..", clipping it and the
+  machine name if it is present in the defining file name.
+
+/usr2/lisp/nhem/lispeval.lisp, 25-Sep-87 11:42:25, Edit by Chiles.
+  Modified "Set Eval Buffer" to set the global eval server always.
+  Modified "Set Compile Server" to set the global compile server always.
+  Rewrote or added support routines SELECT-CURRENT-SERVER,
+  SELECT-GLOBAL-SERVER, SELECT-CURRENT-COMPILE-SERVER,
+  SELECT-GLOBAL-COMPILE-SERVER, GET-CURRENT-SERVER, CHECK-SERVER-INFO.
+  Modified "Select Background" to try for the current compile server's
+  background with a prefix argument.  Modified "Edit Compiler Errors" to
+  look for a compile server before using the current eval server.  Added
+  commands "Current Eval Server" and "Current Compile Server".  Introduced
+  "Prompt for Current Server", so CHECK-SERVER-INFO does not prompt for
+  creating a new slave but prompts for an already known server instead.
+
+/usr2/lisp/nhem/morecoms.lisp, 24-Sep-87 23:12:42, Edit by Chiles.
+  Modified "List Buffers" to show both buffer name and pathname when the
+  are different and both exist.
+
+/usr2/lisp/nhem/hunk-draw.lisp, 25-Sep-87 09:48:17, Edit by Chiles.
+  Made HUNK-DRAW-BOTTOM-BORDER enhance the 80'th notch it draws.
+
+/usr2/lisp/nhem/defsyn.lisp, 24-Sep-87 23:32:57, Edit by Chiles.
+  Made #\formfeed no longer is a whitespace character.
+
+/usr2/lisp/nhem/bindings.lisp, 24-Sep-87 23:28:26, Edit by Chiles.
+  Did some "Argument Digit" binding.
+
+/usr2/lisp/nhem/lispmode.lisp, 24-Sep-87 23:24:29, Edit by Chiles.
+  "Minimum Lines Parsed" and "Maximum Lines Parsed" now default to 50 and
+  500.
+
+/usr2/lisp/nhem/searchcoms.lisp, 24-Sep-87 23:22:41, Edit by Chiles.
+  Made "Count Occurrences" use echo area for result instead of random
+  typeout.
+
+/usr2/lisp/nhem/filecoms.lisp, 24-Sep-87 22:16:48, Edit by Chiles.
+  Made default for "Save All Files Confirm" be t.
+
+/usr2/lisp/nhem/bindings.lisp, 24-Sep-87 22:11:20, Edit by Chiles.
+  Made binding for "Select Background", C-M-C.
+
+/usr2/lisp/nhem/lispbuf.lisp, 24-Sep-87 22:02:32, Edit by Chiles.
+  Changed "Lisp Describe" to "Editor Describe".
+
+/usr2/lisp/nhem/doccoms.lisp, 24-Sep-87 21:56:40, Edit by Chiles.
+  Replaced instance of LISP-DESCRIBE-COMMAND with EDITOR-DESCRIBE-COMMAND.
+
+/usr2/lisp/nhem/lispbuf.lisp, 24-Sep-87 21:48:36, Edit by Chiles.
+  Removed "Eval Mode" command.
+
+/usr2/lisp/nhem/lispeval.lisp, 24-Sep-87 00:21:19, Edit by Chiles.
+  Fixed "Set Buffer Package" to not try to access nil when there isn't a
+  current eval server.  Also, made it test for the server being valid
+  before trying to use it.
+
+/usr2/lisp/nhem/lispeval.lisp, 23-Sep-87 22:49:32, Edit by Chiles.
+  Modified GET-CURRENT-SERVER and CREATE-SERVER to use
+  MAYBE-GET-SLAVE-NAME.
+
+/usr2/lisp/nhem/rompsite.lisp, 23-Sep-87 22:27:38, Edit by Chiles.
+  Modified EDITOR_CONNECT-handler to handler name argument differently.
+  Added definition of "Thumb Bar Meter" to SITE-INIT.
+
+/usr2/lisp/nhem/bit-screen.lisp, 23-Sep-87 15:03:12, Edit by Chiles.
+  Made HUNK-EXPOSED-REGION and HUNK-RESET call HUNK-DRAW-BOTTOM-BORDER.
+
+/usr2/lisp/nhem/hunk-draw.lisp, 23-Sep-87 14:56:44, Edit by Chiles.
+  Renamed HUNK-DRAW-TOP-BORDER to HUNK-DRAW-BOTTOM-BORDER and made it do it
+  to the bottom.  Made hunk-bottom-border be 10 instead of 3.
+
+/usr2/lisp/nhem/bindings.lisp, 21-Sep-87 17:13:39, Edit by Chiles.
+  Made "Compile File" be the default binding for "Editor" mode.
+
+/usr2/lisp/nhem/rompsite.lisp, 21-Sep-87 12:55:58, Edit by Chiles.
+  Modified EDITOR-WINDOW-IN to not use VARIABLE-VALUE four times in a loop.
+  Likewise for EDITOR-TTY-IN.
+
+/usr2/lisp/nhem/edit-defs.lisp, 20-Sep-87 23:57:08, Edit by Chiles.
+  Rewrote GET-DEFINTION-FILE and wrote MAYBE-TRANSLATE-DEFINITION-FILE to
+  have definition directory translation done in the editor instead of the
+  client.
+
+/usr2/lisp/nhem/bindings.lisp, 15-Sep-87 16:44:28, Edit by Chiles.
+  Made prefix key translation for #\control-^ to be :control.
+
+/usr2/lisp/nhem/lispeval.lisp, 14-Sep-87 22:09:42, Edit by chiles.
+  Modified "Set Buffer Package" to use new TL:SET_PACKAGE interface.
+
+/usr2/lisp/nhem/htext4.lisp, 14-Sep-87 17:27:44, Edit by chiles.
+  Modified DELETE-CHARACTERS to do nothing and return t when n = 0.
+  Modified DELETE-REGION to do nothing when the region is empty.
+  Modified DELETE-AND-SAVE-REGION to just return an empty region when its
+  argument is empty.
+
+/usr2/lisp/nhem/htext3.lisp, 14-Sep-87 17:12:52, Edit by chiles.
+  Modified INSERT-STRING to not modify buffer when the string is empty.
+  INSERT-CHARACTER always modifies the buffer.
+  INSERT-REGION wins on empty regions because of INSERT-STRING.
+
+/usr2/lisp/nhem/display.lisp, 14-Sep-87 17:14:52, Edit by chiles.
+  Added some documentation to REDISPLAY-WINDOW-RECENTERING.  Modified
+  MAYBE-UPDATE-WINDOW-IMAGE to return to or nil based on whether it updated
+  the window image.
+
+/usr2/lisp/nhem/cursor.lisp, 14-Sep-87 16:59:56, Edit by chiles.
+  Modified MAYBE-RECENTER-WINDOW to return t or nil based on whether it
+  recentered.
+
+/usr2/lisp/nhem/filecoms.lisp, 13-Sep-87 18:37:15, Edit by Chiles.
+  Made "Log Entry Template" capitalize file author.
+
+/usr2/lisp/nhem/lispeval.lisp, 13-Sep-87 17:59:15, Edit by Chiles.
+  Modified server-info structure, removing the ll-buffer slot in favor of a
+  slave-ts slot.  Modified CREATE-SLAVE to pass the -slave switch the name
+  of the editor server in case two people are on the same machine (in which
+  case they must use -edit differently), and instead of using EDITOR-SLEEP,
+  it now uses SERVER (it was returning immediately on input with
+  EDITOR-SLEEP).  Modified REGION-EVAL, REGION-COMPILE, and FILE-COMPILE to
+  pass the slave-ts slot of the server-info structure of the notification,
+  so terminal-io will happen in the interactive buffer for the server
+  instead of the background buffer.
+
+/usr2/lisp/nhem/main.lisp, 13-Sep-87 14:32:47, Edit by Chiles.
+  Added DEFHVAR's for "Input Hook", "Timer Hook", and "Timer Hook
+  Interval".  Added code in ED to handle Hemlock specific init files.
+
+/usr2/lisp/nhem/ts.lisp, 13-Sep-87 15:34:09, Edit by Chiles.
+  Modified READ-OR-HANG to message about input waits that occur while a
+  buffer is not visible.  Introduced variable "Input Wait Alarm".
+
+/usr2/lisp/nhem/rompsite.lisp, 13-Sep-87 14:41:27, Edit by Chiles.
+  Made editor input stream methods deal with "Input Hook", "Timer Hook",
+  and "Timer Hook Interval".  Modified EDITOR_CONNECT-HANDLER to correspond
+  with new server-info structure.
+
+/usr1/lisp/hemlock/rompsite.lisp, 10-Sep-87 14:38:14, Edit by DBM.
+  Now that Lisp no longer diddles the interrupt characters, the bare
+  console has to be modified so that it doesn't send one of the standard
+  control characters as part of the encoding for control characters.
+
+/usr0/ram/htext1.lisp, 10-Sep-87 13:29:50, Edit by Ram
+  Added a without-interrupts in Close-Line and some warnings about exclusion
+  elsewhere. 
+
+/usr2/lisp/nhem/lispbuf.lisp, 09-Sep-87 22:09:00, Edit by Chiles.
+  Wrote "Select Eval Buffer" command.
+
+/usr2/lisp/nhem/lispeval.lisp, 09-Sep-87 21:47:46, Edit by Chiles.
+  Rewrote the local queuing of :unsent notifications.  This involved
+  deleting all the old stuff and changing KILL-NOTIFICATION and
+  MAYBE-QUEUE-OPERATION-REQUEST.
+
+/usr2/lisp/nhem/filecoms.lisp, 09-Sep-87 18:17:34, Edit by Chiles.
+  Changed "Log Entry Template".
+
+/usr2/lisp/nhem/rompsite.lisp, 09-Sep-87 18:06:39, Edit by Chiles.
+  Made MORE-READ-CHAR call REDISPLAY while looping on SERVER.
+
+/usr2/lisp/nhem/tty-display-rt.lisp, 09-Sep-87 16:00:26, Edit by Chiles.
+  Modified INIT-TTY-DEVICE and EXIT-TTY-DEVICE to not assume that
+  system:*file-input-handlers* had an association for Unix stdin (0).
+
+/usr2/lisp/nhem/lispbuf.lisp, 08-Sep-87 14:04:00, Edit by Chiles.
+  Replaced appropriate occurrences of "top-level" and "top level" with
+  "eval".
+
+/usr2/lisp/nhem/lispeval.lisp, 07-Sep-87 20:56:39, Edit by Chiles.
+  Replaced occurrences of "lisp listener" with "slave lisp" or "lisp
+  interaction".  Renamed things to to with "anonymous client lisp" to
+  "slave".
+
+/usr2/lisp/nhem/tty-display-rt.lisp, 06-Sep-87 18:47:02, Edit by Chiles.
+  Added some documentation to the exit method.
+
+/usr2/lisp/nhem/filecoms.lisp, 03-Sep-87 16:12:28, Edit by Chiles.
+  Made "Directory" list Unix dot files if the prefix is supplied and made
+  the random typeout window have the right number of lines for each
+  listing.  Made a "Verbose Directory" command like "Directory" but based
+  on the new :verbose argument to PRINT-DIRECTORY.
+
+/usr2/lisp/nhem/rompsite.lisp, 06-Sep-87 18:07:40, Edit by Chiles.
+  Fixed INIT-RAW-IO again to not push into system:*file-input-handlers*.
+  Modified EDITOR_CONNECT-HANDLER to make "Slave Lisp <n>" buffer names
+  instead of "Lisp Listener <n>" buffer names.
+
+/usr2/lisp/nhem/tty-display.lisp, 06-Sep-87 16:54:18, Edit by Chiles.
+  Fixed TTY-SMART-CLEAR-TO-EOW boundary condition -- when clearing last
+  line of window to eow, needed >= test instead of = test.
+
+/usr2/lisp/nhem/bindings.lisp, 05-Sep-87 15:52:11, Edit by Chiles.
+  Deleted binding of "Exit Hemlock" to C-c since it is later used for
+  "Process Control".  Changed binding of "Select Lisp Listener" to be a
+  binding for "Select Slave Lisp".  Replaced occurrences of "top-level"
+  with "eval".
+
+/usr2/lisp/nhem/morecoms.lisp, 05-Sep-87 14:08:32, Edit by Chiles.
+  Made "List Buffers" print pathnames with the FILE-NAMESTRING first
+  followed by two spaces and the DIRECTORY-NAMESTRING.
+
+/usr2/lisp/nhem/hunk-draw.lisp, 01-Sep-87 15:02:57, Edit by Chiles.
+  Made CURSOR-INVERT do an X:XFLUSH.
+
+/usr2/lisp/nhem/bindings.lisp, 01-Sep-87 15:00:47, Edit by Chiles.
+  Fixed merge lossage from re-integration with sources.
+
+/usr2/lisp/nhem/bindings.lisp, 28-Aug-87 17:05:12, Edit by Chiles.
+  Fixed some bindings for "Editor" mode and put them on the right page.
+
+/usr2/lisp/nhem/lispeval.lisp, 28-Aug-87 19:05:14, Edit by Chiles.
+  Fixed bug in CREATE-ANONYMOUS-CLIENT-LISP and "Select Lisp Listener".
+  Made "Set Eval Server" really define a buffer local variable when a
+  prefix was supplied.
+
+/usr1/ram/charmacs.lisp, 25-Aug-87 19:59:00, Edit by Ram
+  Flushed Alt and Oops character names.  Added Escape as a name to shadow
+  the initial Altmode name.  Added Enter and Action as alternate names for
+  Return and Linefeed.
+
+/usr1/ram/keytran.lisp, 25-Aug-87 19:44:24, Edit by Ram
+  Changed delete to translate to delete rather than oops.  Made all random
+  named keys translate to a super character when shifted.  Made keypad keys
+  always translate to super characters.
+
+/usr1/ram/bindings.lisp, 25-Aug-87 19:15:10, Edit by Ram
+  Frobbed bindings to allow rational documentation.  Case-Insensitivize now
+  translates to lowercase.  Use of Insert as an Escape standin had been
+  flushed.  Insert is now used for X cut buffer operations.  Bindings to Oops
+  have been flushed.  Interactive input kill/abort is now M-i/C-M-i.  Flushed
+  redundant extra bindings of mouse commands to super-clicks (except for S-left
+  being the same as middle).  Made S-Left and S-Right be illegal in the echo
+  area.  Made illegal upclicks do nothing so that you don't get annoying double
+  errors.  Made C-_ be a :Help character.  Flushed M-_ binding for Help and
+  Help on Parse.  Made redundant bindings to backspace and return for C-h and
+  C-m so that TTYs can win.  (Scribe mode is still wedged pending intallation
+  of the new Scribe insertion command.)  Use Delete character name instead of
+  Rubout.
+
+/usr2/lisp/nnhem/searchcoms.lisp, 24-Aug-87 09:17:00, Edit by Chiles
+  Added Chris Hoover's "List Matching Lines", "Delete Matching Lines", and
+  "Count Occurrences".  Redid page breaks.
+
+/usr2/lisp/nnhem/lispeval.lisp, 23-Aug-87 18:53:42, Edit by Chiles
+  Rewrote "Select Lisp Listener" and wrote CREATE-ANONYMOUS-CLIENT-LISP to
+  be used in the command and GET-CURRENT-SERVER.
+
+/usr2/lisp/nnhem/tty-screen.lisp, 23-Aug-87 10:15:58, Edit by Chiles
+  TTY-RANDOM-TYPEOUT-CLEANUP now calls REDISPLAY-WINDOW-ALL instead of
+  funcall'ing DEVICE-DUMB-REDISPLAY directly.
+
+/usr2/lisp/nnhem/font.lisp, 22-Aug-87 14:10:06, Edit by Chiles
+  SETF methods for changing a window's font set the hunk's trashed slot to
+  :font-change instead of t.
+
+/usr2/lisp/nnhem/window.lisp, 21-Aug-87 19:59:19, Edit by Chiles
+  Replaced numeric constants with symbolic ones.  WINDOW-CHANGED no longer
+  redisplays, but it does update the window image (recentering if current
+  window).
+
+/usr2/lisp/nhem/pane.lisp, 19-Aug-87 22:34:12, Edit by Chiles
+  Wrote OFROB-CURSOR to be the note-read-wait method for old bitmap
+  displays.  Rewrote PANE-SHOW-CURSOR.  Titled pages.  Documented cursor
+  stuff.
+
+/usr2/lisp/nhem/obit-screen.lisp, 19-Aug-87 22:28:24, Edit by Chiles
+  Added an initialization for the note-read-wait slot of the default old
+  bitmap device to #'ofrob-cursor.  OBITMAP-RANDOM-TYPEOUT-CLEANUP now
+  calls REDISPLAY-WINDOW-ALL instead of ODUMB-WINDOW-REDISPLAY.
+
+/usr2/lisp/nhem/hunk-draw.lisp, 19-Aug-87 18:53:14, Edit by Chiles
+  Rewrote HUNK-SHOW-CURSOR.  Added FROB-CURSOR.  Tweaked DROP-CURSOR and
+  LIFT-CURSOR.
+
+/usr2/lisp/nhem/bit-screen.lisp, 19-Aug-87 18:49:23, Edit by Chiles
+  Initialized note-read-wait slot of default bitmap device to #'frob-cursor
+  which is new in Hunk-Draw.Lisp.  Modified SET-WINDOW-HOOK-RAISE-FUN.  Put
+  DEFHVAR in SITE-INIT.  Removed all references to BITMAP-HUNK-LOCK.
+  Additionally modified HUNK-RESET, HUNK-EXPOSED-OR-CHANGED, and
+  HUNK-CHANGED.  HUNK-EXPOSED-OR-CHANGED now calls REDISPLAY-WINDOW-ALL
+  instead of DUMB-WINDOW-REDISPLAY.
+
+/usr2/lisp/nhem/display.lisp, 19-Aug-87 18:46:16, Edit by Chiles
+  Added device structure slot note-read-wait which is a function that
+  somehow notes on the display that input is expected.  This will simply be
+  dropping the cursor for now on the RT.  Rewrote REDISPLAY-LOOP to take a
+  window variable to bind and two forms for general window redisplay and
+  current window redisplay.  Added REDISPLAY-WINDOW, REDISPLAY-WINDOW-ALL,
+  MAYBE-UPDATE-WINDOW-IMAGE, and REDISPLAY-WINDOW-RECENTERING.  Modified
+  REDISPLAY-WINDOWS-FROM-MARK to use REDISPLAY-WINDOW-RECENTERING (which is
+  also used by REDISPLAY).
+
+/usr2/lisp/nhem/bit-display.lisp, 19-Aug-87 14:44:03, Edit by Chiles
+  Reorganized pages some: put smart redisplay structure definitions on the
+  smart window redisplay page, and retitle/titled other pages.  Did away
+  with most macros, making them functions and moving their definitions
+  below their uses.  Modified some call sites and argument passing of what
+  were macros and now are functions.  Removed code from
+  SMART-WINDOW-REDISPLAY and DUMB-WINDOW-REDISPLAY that is now encorporated
+  into the REDISPLAY and REDISPLAY-ALL loops.  Removed references and sets
+  to BITMAP-HUNK-LOCK.
+
+/usr2/lisp/nhem/obit-display.lisp, 19-Aug-87 14:44:14, Edit by Chiles
+  Moved definition of *current-font* from Bit-Display.Lisp to the only file
+  using it, this one.  Removed recenterp argument from
+  OSMART-WINDOW-REDISPLAY and ODUMB-WINDOW-REDISPLAY.  Also removed window
+  image building code from these functions since it is now taken care of
+  higher up in the redisplay calls.
+
+/usr2/lisp/nhem/tty-display-rt.lisp, 19-Aug-87 12:26:13, Edit by Chiles
+  Modified INIT-TTY-DEVICE and EXIT-TTY-DEVICE to destructively modify
+  system:*file-input-handlers*.  Now the standard input file descriptor
+  used for terminal streams is associated with an editor input handler
+  instead of the editor having its own file descriptor.
+
+/usr2/lisp/nhem/rompsite.lisp, 18-Aug-87 15:29:01, Edit by Chiles
+  Modified INIT-RAW-IO to not open the tty device.  Now, it simply assumes
+  Unix standard input.  Modified TTY-BEEP to not write to the editor's file
+  descriptor which is Unix standard input but to write to 1 (Unix standard
+  output).  Put DEFHVAR for "Set Window Autoraise" in SITE-INIT.  Modified
+  SHOW-MARK to call REDISPLAY-WINDOW instead of calling the smart redisplay
+  method out of the device.  Made editor connect handler store lisp
+  listener buffer in server-info slot.
+
+/usr2/lisp/nhem/tty-display.lisp, 18-Aug-87 15:13:41, Edit by Chiles
+  Moved INIT-TTY-DEVICE and EXIT-TTY-DEVICE to Tty-Display-Rt.Lisp.
+  Deleted code from TTY-SMART-WINDOW-REDISPLAY and
+  TTY-SEMI-DUMB-WINDOW-REDISPLAY that was folded into the REDISPLAY and
+  REDISPLAY-ALL loops.  Likewise for TTY-DUMB-WINDOW-REDISPLAY.  Also
+  deleted recenterp arguments from all these functions.
+
+/usr2/lisp/nhem/rompsite.lisp, 18-Aug-87 14:13:43, Edit by Chiles
+  Made EDITOR-TTY-IN and EDITOR-WINDOW-IN drop and lift the cursor at most
+  once, not each time SERVER is called.
+
+/usr2/lisp/nhem/vars.lisp, 18-Aug-87 13:29:37, Edit by Chiles
+  Fixed error form for GET-MODE-OBJECT to say the argument is not a defined
+  mode instead of saying NIL isn't.
+
+/usr2/lisp/nhem/buffer.lisp, 18-Aug-87 13:28:01, Edit by Chiles
+  Fixed MODE-MAJOR-P to return MODE-OBJECT-MAJOR-P instead of
+  MODE-OBJECT-NAME.
+
+/usr2/lisp/nhem/morecoms.lisp, 11-Aug-87 12:03:46, Edit by Chiles
+  JR fixed "List Buffers" to print the pathname of the buffer unless there
+  was not one or the buffer names was not derived from it.  Otherwise,
+  print the buffer name.
+
+/usr2/lisp/nhem/bindings.lisp, 30-Jul-87 15:26:08, Edit by Chiles
+  Added binding for C-M-\L to "Illegal" in "Echo Area" mode.
+
+/usr2/lisp/nhem/line.lisp, 29-Jul-87 15:28:41, Edit by Chiles
+  Rob documented the line defstruct, eliminating the chars slot in favor of
+  always having the %chars slot.  Added a macro for LINE-%CHARS instead of
+  symbol-function and symbol-plist hackery.
+
+/usr2/lisp/nhem/struct.lisp, 29-Jul-87 15:31:55, Edit by Chiles
+  Fixed documentation on COMMANDP.
+
+/usr2/lisp/nhem/echo.lisp, 28-Jul-87 16:26:44, Edit by Chiles
+  Merged some code from the Perq to fix up current buffer and window when
+  trying to confirm a non-existent parse.
+
+/usr2/lisp/nhem/bit-screen.lisp, 26-Jul-87 20:13:05, Edit by Chiles
+  Made SET-WINDOW-HOOK-RAISE-FUN look at the value of "Set Window Autoraise".
+
+/usr2/lisp/nhem/rompsite.lisp, 26-Jul-87 19:59:31, Edit by Chiles
+  Made EDITOR-SLEEP loop around SERVER using its timeout functionality
+  instead of busy looping.
+
+/usr2/lisp/nhem/lispeval.lisp, 26-Jul-87 20:04:08, Edit by Chiles
+  Made loop waiting for anonymous client lisp use EDITOR-SLEEP which loops
+  around SERVER.  Before, the client Lisp could never connect since SERVER
+  was never being called.
+
+  Wrote "Select Lisp Listener" command.
+
+/usr2/lisp/nhem/tty-display.lisp, 26-Jul-87 18:56:41, Edit by Chiles
+  Fixed display bug involving lines that are both new and changed (seen
+  often in the echo area for some reason).
+
+/usr2/lisp/nhem/filecoms.lisp, 25-Jul-87 19:37:16, Edit by Chiles
+  Fixed "Select Previous Buffer" to not call "Circulate Buffer" since it
+  doesn't exist.
+
+/usr2/lisp/nhem/macros.lisp, 25-Jul-87 18:30:59, Edit by Chiles
+  Made LISP-ERROR-ERROR-HANDLER have an E command that reports the
+  condition it was called on in a pop-up window.
+
+/usr2/lisp/nhem/lispeval.lisp, 25-Jul-87 19:28:23, Edit by Chiles
+  Made FILE-COMPILE use a temporary output file for compiler output when
+  its ouput-file argument is not t.  This temporary file is publicly
+  writeable in case the eval server is running on another machine.
+
+/usr2/lisp/nhem/edit-defs.lisp, 25-Jul-87 19:25:32, Edit by Chiles
+  Made "Go to Definition" and "Edit Definition" use the client Lisp to
+  determine where something is defined.  Had to restructure the code
+  significantly, but it can be put back to non-eval-server functionality
+  easily and cleanly.
+
+/usr2/lisp/nhem/bindings.lisp, 23-Jul-87 11:07:22, Edit by Chiles
+  Added bindings for "Process Control", "Editor Evaluate Expression", and
+  "Select Lisp Listener".
+
+Rompsite.Lisp, while doing eval-server, Edit by Chiles
+  Tty streams now loop over SERVER for input, so the eval-server stuff can
+  be used on terminals.  There are a couple new functions for connection to
+  editor servers.
+
+Lispeval.Lisp, while doing eval-server, Edit by Chiles
+  This is a new file replacing a lot of commands in Lispbuf.Lisp with
+  similar commands that use the eval server interface.  New in this file
+  from the Perq implementation is function description.
+
+Ts.Lisp, while doing eval-server, Edit by Chiles
+  This is a new file that implements the server side of the typescript
+  protocol.
+
+Morecoms.Lisp, while doing eval-server, Edit by Chiles
+  Made "Do Nothing", typically bound to up mouse clicks, propagate the last
+  command type (as if nothing happened).  This was needed to make
+  super-rightup keep the command type of super-rightdown ("Insert Kill Buffer").
+
+Keytran.Lisp, while doing eval-server, Edit by Chiles
+  Made shift-mouseclicks send super-mouseclick.
+
+Bindings.Lisp, while doing eval-server, Edit by Chiles
+  Addeds lots of new bindings and changed a few with respect to the
+  eval-server stuff going in.
+
+Bit-Screen.Lisp, while doing eval-server, Edit by Chiles
+  Fixed initial windows hook to keep echo area border visible on the screen
+  by hacking in another -2 pixels.  This might be because X has by default
+  moves windows down from the top, so the top borders will show.
+
+/usr1/ram/lispmode.lisp, 01-Jul-87 12:04:59, Edit by Ram
+  Fixed Quest-For-Balancing-Paren to use the net-open and net-close information
+  correctly.  It's silly to go to the trouble of computing this information,
+  and then (incorrectly) compute a paren balance by subtracting the two.
+
+/usr2/lisp/nhem/streams.lisp, 19-Jun-87 18:02:55, Edit by Chiles
+  Merged in some fixes from old Perq version.
+
+/usr2/lisp/nhem/lispbuf.lisp, 19-Jun-87 17:54:25, Edit by Chiles
+  Changed the following command names to be prefixed by "Editor ":
+     "Editor Evaluate Defun"
+     "Editor Re-evaluate Defvar"
+     "Editor Evaluate Expression"
+     "Editor Compile Defun"
+     "Editor Compile Region"
+     "Editor Evaluate Region"
+     "Editor Evaluate Buffer"
+     "Editor Compile File"
+     "Editor Compile Group"
+     "Editor Describe Function Call"
+     "Editor Describe Symbol".
+  Removed old reference to KILL-TOP-LEVEL-INPUT-COMMAND in "Top-Level Eval".
+
+/usr2/lisp/nhem/killcoms.lisp, 19-Jun-87 17:39:34, Edit by Chiles
+  Wrote BUFFER-MARK which is to CURRENT-MARK as BUFFER-POINT is to
+  CURRENT-POINT.
+
+/usr2/lisp/nhem/filecoms.lisp, 16-Jun-87 23:25:52, Edit by Chiles
+  Removed the definition of the "Package" file option, placing a new
+  version in Lispbuf.Lisp.
+
+/usr2/lisp/nhem/srccom.lisp, 18-Jun-87 10:23:01, Edit by Chiles
+  Made "Compare Buffers" and "Merge Buffers" only handle the current region
+  in each buffer when the prefix argument is supplied.
+
+/usr2/lisp/nhem/bindings.lisp, 16-Jun-87 14:09:20, Edit by Chiles
+  Added bindings for super-<mouseclick> characters.  Added binding for
+  "Exit Hemlock".  Added binding for "Circulate Buffer".
+
+/usr2/lisp/nhem/morecoms.lisp, 15-Jun-87 22:18:26, Edit by Chiles
+  Made "Do Nothing" set the last command type to its current value.
+  Added "Insert Kill Buffer".
+
+/usr2/lisp/nhem/echocoms.lisp, 15-Jun-87 13:47:15, Edit by Chiles
+  Made "Help on Parse" check for *parse-help* being nil.
+
+/usr2/lisp/nhem/bit-screen.lisp, 08-Jun-87 12:20:39, Edit by Chiles
+  Modified DEFAULT-CREATE-INITIAL-WINDOWS-HOOK to added in a couple more
+  border widths, so the echo area's bottom border is visible.
+
+*************************
+
+/usr1/lisp/hemlock/rompsite.lisp, 03-Jun-87 10:09:24, Edit by DBM.
+  All references to the accint package have been changed to Mach.
+
+/usr1/lisp/hemlock/obit-screen.lisp, 03-Jun-87 10:05:34, Edit by DBM.
+  All references to the accint package have been changed to Mach.
+
+/usr2/lisp/nhem/tty-display.lisp, 01-Jun-87 21:25:15, Edit by Chiles
+  Modified TTY-SMART-WINDOW-REDISPLAY to punt insert/delete line
+  optimizations in favor of redrawing every altered line when "Scroll
+  Redraw Ratio" is exceeded.
+
+/usr2/lisp/nhem/command.lisp, 01-Jun-87 21:12:21, Edit by Chiles
+  "Scroll Redraw Ratio" is a new Hemlock variable that controls the
+  abortion of insert/delete line optimization in terminal redisplay in
+  favor of redrawing all altered lines.  This is used in Tty-Display.Lisp.
+
+/usr2/lisp/nhem/tty-display.lisp, 27-May-87 14:38:50, Edit by Chiles
+  Wrote TTY-SMART-CLEAR-TO-EOW to use the internal screen image instead of
+  TTY-SEMI-DUMB-WINDOW-REDISPLAY and TTY-SMART-WINDOW-REDISPLAY using the
+  clear-to-eow method that clears every line disregarding internal
+  information.
+
+/usr2/lisp/nhem/rompsite.lisp, 26-May-87 16:14:27, Edit by Chiles
+  Modified EDITOR-TTY-IN to detect lowercase control g's.
+
+/usr2/lisp/nhem/bit-screen.lisp, 25-May-87 17:40:30, Edit by Chiles
+  Modified arguments to X window event handlers as per the changes in
+  X.Lisp.
+
+/usr1/ram/spellcoms.lisp, 22-May-87 04:02:19, Edit by Ram
+  Fixed Fix-Word to bump the mark in the all uppercase case even when the word
+  is already in the hashtable.
+
+/usr1/ram/echo.lisp, 14-May-87 13:07:07, Edit by Ram
+  Changed Message to use displayed-p on the buffer end to tell whether the echo
+  area needs to be cleared rather than just counting the lines.  This works
+  much better in the presence of wrapped lines.
+
+/usr1/ram/cursor.lisp, 14-May-87 13:02:09, Edit by Ram
+  Changed renamed Display-P to %Displayed-P, and wrote Displayed-P which does
+  an update-window-iamge before calling %Displayed-P.
+
+/usr2/lisp/xhem/xcommand.lisp, 12-May-87 16:00:16, Edit by Chiles
+  This is a new file of X specific commands.  Currently it only contains
+  "Insert Cut Buffer" and "Region to Cut Buffer".
+
+/usr2/lisp/xhem/keyboard_codes.lisp, 12-May-87 15:55:42, Edit by Chiles
+  Modified some translations to work better with the new key bindings.
+
+/usr2/lisp/xhem/lispbuf.lisp, 12-May-87 14:43:15, Edit by Chiles
+  Added "List Compile File" and "Re-evaluate Defvar".
+
+/usr2/lisp/xhem/command.lisp, 12-May-87 14:07:11, Edit by Chiles
+  Modified "Self Insert" and "Quoted Insert" to handler new TEXT-CHARACTER
+  in Rompsite.Lisp.
+
+/usr2/lisp/xhem/morecoms.lisp, 12-May-87 14:01:29, Edit by Chiles
+  Made "List Buffers" on a prefix argument list only modified buffers.
+
+/usr2/lisp/xhem/main.lisp, 12-May-87 12:55:51, Edit by Chiles
+  Stopped ED from calling REDISPLAY-ALL when the editor has been entered
+  already and moved this into the device init methods that require this.
+
+/usr2/lisp/xhem/lispmode.lisp, 12-May-87 12:53:32, Edit by Chiles
+  Blasted a couple bogus type declarations on some DEFSTRUCT slots.
+  Inserted a few lines to LISP-INDENTATION from my init file.
+
+/usr2/lisp/xhem/indent.lisp, 12-May-87 12:48:29, Edit by Chiles
+  Replaced a couple SCAN-CHAR and REV-SCAN-CHAR uses with FIND-ATTRIBUTE
+  and REVERSE-FIND-ATTRIBUTE, so compilation in a Lisp without Hemlock
+  wouldn't lose.
+
+/usr2/lisp/xhem/filecoms.lisp, 12-May-87 12:42:08, Edit by Chiles
+  Renamed "New Window" to "Split Window", and made "New Window" prompt the
+  user for a window.
+
+/usr2/lisp/xhem/charmacs.lisp, 12-May-87 12:24:05, Edit by Chiles
+  Modified character name a-list.  Rob Flushed addition of the command-bits
+  feature and added the all-bit-names constant. 
+
+/usr2/lisp/xhem/window.lisp, 12-May-87 11:47:35, Edit by Chiles
+  This contains the stuff we still need from Owindow.Lisp and some new
+  stuff brought over from the Perq.
+
+/usr2/lisp/xhem/tty-screen.lisp, 12-May-87 11:43:55, Edit by Chiles
+  Modified to fit the new device independent structure, adding beep and
+  finish-output methods.  Creating and Deleting window methods now set
+  *screen-image-trashed since not all devices need this.  Random typeout
+  methods got an extra argument that we ignore.
+
+/usr2/lisp/xhem/struct.lisp, 12-May-87 11:37:25, Edit by Chiles
+  Modified window, dis-line, and font structures.  When the old bitmap
+  stuff goes away, so will a few slots of windows.  Also, some old setf
+  stuff for old font information will go away.
+
+/usr2/lisp/xhem/screen.lisp, 12-May-87 11:34:06, Edit by Chiles
+  Modified to be once-again device independent with respect to the addition
+  of Hemlock running under X windows.  MAKE-WINDOW and DELETE-WINDOW no
+  longer set *screen-image-trashed* since this isn't necessary for all
+  devices.
+
+/usr2/lisp/xhem/rompsite.lisp, 12-May-87 00:56:01, Edit by Chiles
+  SITE-INIT is all new and defines some Hemlock variables for controlling
+  some of the X activity.  INIT-RAW-IO is much bigger now for initializing
+  stuff when we are running under X.  *editor-windowed-input* is set to t
+  when we are running under X, and WINDOWED-MONITOR-P returns the value of
+  this variable for use is other files.  
+
+  BEEP was moved to Code:Machio.Lisp, and there's a couple different
+  beeping methods in here now that get called as a result of
+  *beep-function* being bound by SITE-WRAPPER-MACRO.  HEMLOCK-WINDOW calls
+  *hemlock-window-mngt* when *current-window* is bound, which happens going
+  in and out of Hemlock.
+
+  The X scan code translation mechanism lives here, but the initialization
+  is in Keytran.Lisp.  Terminal translation now downcases control
+  characters to interact more smoothly with the new Hemlock key translation
+  and binding scheme.
+
+  There are now different types of editor input streams that all a head and
+  tail pointer into an input queue of events.  One is used for terminals
+  and flat bitmap screens, and the other uses SERVER for windowed input
+  under X.  TEXT-CHARACTER is new and now more correct.
+
+  There is a page of X support: getting a Hemlock cursor, setting up a grey
+  pixmap for border frobbing, cut buffer manipulation, and naming windows.
+
+/usr2/lisp/xhem/owindow.lisp, 12-May-87 00:52:54, Edit by Chiles
+  This file used to be Window.Lisp.  It now contains only the old bitmap
+  related code for setting up a windows image.
+
+/usr2/lisp/xhem/ofont.lisp, 12-May-87 00:51:35, Edit by Chiles
+  This file used to be Font.Lisp.  It now contains only the few things
+  necessary for old bitmap font interfacing.
+
+/usr2/lisp/xhem/obit-screen.lisp, 12-May-87 00:43:50, Edit by Chiles
+  This file used to be Screen-Bit.Lisp.  Shared stuff has been moved to
+  the new file by the old name.  Window creation and deletion methods now
+  set *screen-image-trashed* since this is not meaningful across all
+  devices.
+
+/usr2/lisp/xhem/obit-display.lisp, 12-May-87 00:40:35, Edit by Chiles
+  This file used to be Bit-Display.Lisp.  Shared stuff has been moved to
+  the new file by the old name.
+
+/usr2/lisp/xhem/macros.lisp, 12-May-87 00:35:30, Edit by Chiles
+  WITH-RANDOM-TYPEOUT has been modified to handle new termination
+  functionality involved with running Hemlock under X.
+  LISP-ERROR-ERROR-HANDLER no longer calls REDISPLAY after returning from a
+  BREAK.  This is the responsibility of the device's init method if it is
+  necessary.
+
+/usr2/lisp/xhem/keytran.lisp, 12-May-87 00:30:18, Edit by Chiles
+  This is a new file.  It contains the initialization of the keyboard
+  translations for Hemlock running under X.  These were too numerous to
+  leave in Rompsite since there is no hack for generating the translations.
+
+/usr2/lisp/xhem/hunk-draw.lisp, 12-May-87 00:28:02, Edit by Chiles
+  This is a new file, a kin to Pane.Lisp.  It contains screen painting
+  routines for Hemlock running under X windows.  This includes cursor and
+  border manipulation.
+
+/usr2/lisp/xhem/font.lisp, 12-May-87 00:12:10, Edit by Chiles
+  This is a new file, replacing the currently named Ofont.Lisp.  It
+  contains the pseudo-independent Hemlock font information implementation.
+  This includes stuff particular for running Hemlock under X windows and
+  stuff that is used by the other bitmap redisplay/screen manager code.
+
+/usr2/lisp/xhem/display.lisp, 12-May-87 00:09:23, Edit by Chiles
+  The device structure has been modified to handle new methods, such as
+  beeping and finishing output.  The device-clear method is now optional.
+  The entry points into redisplay have been modified to encorporate the
+  needs of Hemlock running under X windows.
+
+/usr2/lisp/xhem/bit-screen.lisp, 11-May-87 23:16:26, Edit by Chiles
+  This is a new file, replacing the currently named Obit-Screen.Lisp.  It
+  contains the event handlers for selected events on Hemlock windows, the
+  screen management methods for Hemlock running under X windows, the random
+  typeout methods, and screen manager initialization.
+
+/usr2/lisp/xhem/bit-hunk-stream.lisp, 11-May-87 22:43:36, Edit by Chiles
+  This is a new file.  It contains the bitmap-hunk-output-stream structure
+  definition and the associated methods.  This is used for random typeout.
+
+/usr2/lisp/xhem/bit-display.lisp, 11-May-87 22:38:47, Edit by Chiles
+  This is a new file, replacing the currently named Obit-Display.Lisp.  It
+  contains the bitmap-hunk structure and the X related redisplay methods.d 
+
+/usr1/ram/cursor.lisp, 08-May-87 05:02:09, Edit by Ram
+  Totally rewrote dis-line-offset-guess, making it dramatically simpler and
+  more correct by making it do only what is needed for the scrolling functions,
+  rather than attempting to make it preserve position within the line.
+
+/../chiles/usr/lisp/hemlock/bindings.lisp, 29-Apr-87 23:33:27, Edit by Ram
+  Massively revised bindings now that we have key-translations and a real meta
+  key.  C-Z and Escape are now handled as bit-prefix characters, so all
+  explicit bindings containing these have been flushed.  Key translations are
+  used to make things case-insensitive, so duplicate bindings for different
+  case have been flushed.
+
+  All the C-<punctuation>/Escape <punctuation> bindings pairs have been
+  replaced with M-<punctuation>.  This is the main user-interface change.  Also
+  the commands previously bound to C-Z M-<char> have been rebound to C-M-<CHAR>
+  (i.e. control meta shift).  This is necessary since C-Z M-<char> is just
+  C-M-<char> due to the bit prefix mechanism.  We selectively flush the
+  uppercasing translation for the control meta chars used in this way.
+
+  In a more rt-specific change, uses of Help have been replaced with Home.
+
+/usr/ram/interp.lisp, 30-Apr-87 00:36:04, Edit by Ram
+  New Key-Translation mechanism replaces key links.  A key translation
+  specifies a substitution that is done one key arguments to the bindings
+  functions.  When the translated-from key appears as a subsequence of the key
+  to be translated, that subsequence is replaced with the translation.  There
+  is also a mechanism for defining bit-prefix characters.
+
+  The key-table code has been changed a fair amount.  Key-tables are now
+  structures.  The conditionalization off of the commands-bits feature has been
+  flushed.  Keys are no longer internally assumed to be simple-vectors so that
+  we can use vectors with fill-pointers as internal buffers.
+
+  Also put in a few doc strings and made crunch-key allow any seqence and check
+  that the components are characters.  The type check was in the PERQ version
+  but got lost.
+
+/usr/ram/spellcoms.slisp, 12-Apr-87 10:57:44, Edit by Ram
+  Fixed Spell-Replace-Word not to consider words beginning with #\' to be
+  capitalized.
+
+/../wb1/usr/chiles/nhem/lispmode.slisp, 04-Apr-87 22:44:36, Edit by Chiles
+  Modified "Transpose Forms" such that
+     (form1)       ;comment
+     (form2)
+  became
+     (form2)       ;comment
+     (form1)
+  instead of
+     ;comment
+     (form2)       (form1)
+
+/../wb1/usr/chiles/nhem/tty-display.slisp, 26-Mar-87 18:51:40, Edit by Chiles
+  Fixed bug in TTY-SEMI-DUMB-WINDOW-REDISPLAY and
+  TTY-SMART-WINDOW-REDISPLAY that came up when writing the modeline.  Put
+  in an UNWIND-PROTECT around TTY-SMART-LINE-REDISPLAY since it can throw
+  out of redisplay leaving the terminal in standout mode.
+
+/../wb1/usr/chiles/nhem/htext1.slisp, 26-Mar-87 18:10:15, Edit by Chiles
+  Modified MODIFYING-BUFFER to invoke new "Buffer Modified Hook" when the
+  buffer went from unmodified to modified.
+
+/../wb1/usr/chiles/nhem/main.slisp, 26-Mar-87 17:49:12, Edit by Chiles
+  Added definition for "Buffer Modified Hook" and changed definition for
+  "Default Modeline String".
+
+/../wb1/usr/chiles/nhem/window.slisp, 26-Mar-87 17:37:32, Edit by Chiles
+  Made %INIT-REDISPLAY add QUEUE-BUFFER-CHANGES to new "Buffer Modified Hook".
+  Made DEFAULT-MODELINE-FUNCTION-FUNCTION return one more value, whether
+  the buffer is modified.
+
+/../wb1/usr/chiles/nhem/buffer.slisp, 26-Mar-87 18:14:08, Edit by Chiles
+  Made %SET-BUFFER-MODIFIED to invoke new "Buffer Modified Hook" on sense.
+
+/usr1/ram/group.slisp, 20-Mar-87 14:10:56, Edit by Ram
+  Changed the "Group Search" commands to feel more like the "Query Replace"
+  commands.  :Yes now exits instead of skipping, skipping is moved to :No and
+  skipping the rest of the file is move to :Do-All.
+
+/usr/ram/searchcoms.slisp, 19-Mar-87 00:04:09, Edit by Ram
+  Changed query-replace-function to set up the search pattern itself.  Also
+  made it error if the count is specified and negative, rather than trying to
+  do replacement backwards and getting it wrong.  Also restore the search
+  pattern after a recursive edit.
+
+/usr/ram/group.slisp, 19-Mar-87 00:31:13, Edit by Ram
+  Fixed up a bunch of things.  Indirect filespecs are parsed normally; it is no
+  longer assumed that the rest of the line is the name of the file.  The
+  default file name is no longer capitalized.  Temporary search buffers are no
+  longer renamed to "Group Search", making exiting from searches more
+  well-defined.  "Group Search" restores the search pattern after a recursive
+  edit.
+
+/usr/lisp/nhem/lispmode.slisp, 12-Mar-87 16:05:30, Edit by Chiles
+  Rewrote TOP-LEVEL-OFFSET to be correct and to not move the mark unless it
+  could really do the offset.  Modified INSIDE-DEFUN-P to not return t when
+  point is between a top level form and the beginning of the buffer.  Added
+  START-DEFUN-P to be used in heavily modified versions of "End of Defun"
+  and "Mark Defun" commands.
+
+/../wb1/usr/chiles/nhem/lispmode.slisp, 03-Mar-87 17:33:05, Edit by Chiles
+  Fixed LISP-INDENTATION to do a "generic" indent instead of simply
+  returning 0.  This fixes doc strings.
+
+/../wb1/usr/chiles/nhem/indent.slisp, 27-Feb-87 14:18:59, Edit by Chiles
+  Fixed "Indent" command to only affect argument number of lines (instead
+  of one too many) when the prefix argument is supplied.  Rewrote
+  INDENT-REGION-FOR-COMMANDS to be much simpler, fixing a couple
+  irritatingly buggy special cases.
+
+/../wb1/usr/chiles/nhem/fill.slisp, 27-Feb-87 12:18:50, Edit by Chiles
+  Fixed "Fill Paragrah" command's undoability.  When a prefix was added to
+  the first line, it was ignored by the undo region do to a :left-inserting
+  mark.
+
+/usr1/ram/text.slisp, 23-Feb-87 11:00:53, Edit by Ram
+  The "Paragraph Delimiter Function" variable is now used to determine whether
+  a line is a paragraph break.  This is used by Scribe mode.
+
+/usr1/ram/spellcoms.slisp, 23-Feb-87 10:52:18, Edit by Ram
+  "Spell Correct Unique Spelling Immediately" (on by default) causes an unknown
+  word with only one correction to be corrected immediately in auto-spell mode,
+  rather than requiring "Correct Last Misspelled Word" to be done.
+
+  The "Undo Last Spelling Correction" command undoes the last incremental
+  spelling correction and places the word in the dictionary.
+
+  "Spell Ignore Uppercase" (off by default) causes all-uppercase unknown words
+  to be ignored.
+
+/usr1/ram/defsyn.slisp, 23-Feb-87 10:50:01, Edit by Ram
+  Changed definition of "Lisp Syntax" attribute for new Lisp mode primitives.
+
+/usr1/ram/lispbuf.slisp, 23-Feb-87 10:48:54, Edit by Ram
+  Changed to use new Lisp mode primitives. 
+
+/usr1/ram/htext1.slisp, 23-Feb-87 10:19:19, Edit by Ram
+  Deleted old line-plist support.  The user directly accesses the Plist slot
+  now that he is responsible for keeping treack of when it changes. 
+
+/usr1/ram/line.slisp, 23-Feb-87 10:17:30, Edit by Ram
+  Merged in code to implement the documented line-plist/line-signature
+  semantics.  This code somehow never got merged in from the PERQ version.
+
+/usr1/ram/scribe.slisp, 20-Feb-87 16:25:07, Edit by Ram
+  A real Scribe mode.  Has general bracket balancing, and knows about paragraph
+  boundaries.  Also various commands for inserting Scribe directives bound to
+  C-H mumble.
+
+/usr1/ram/bindings.slisp, 20-Feb-87 14:22:45, Edit by Ram
+  New bindings for "Undo Last Spelling Correction" and Scribe mode commands.
+
+/usr1/ram/lispmode.slisp, 18-Feb-87 11:42:22, Edit by Ram
+  New Lisp mode primitives, courtesy of Ivan (Crash and burn like an unblanced
+  paren Vazquez.  These primitives know about Lisp commenting and quotation
+  conventions, and ignoring meaningless parens and quotes.  This is done by
+  pre-parsing the lines in the buffer, annotating them with information about
+  the quoted areas on the line.  Forward-Form and Backward-Form are gone,
+  replaced by Form-Offset.  Similarly, Forward-List and Backward-List are
+  replaced by List-Offset.
+
+  All users of these Lisp parsing primitives must call Pre-Command-Parse-Check
+  or equivalent to ensure that the buffer is properly annotated.  This function
+  calls the values of "Parse Start Function" and "Parse End Function" to
+  determine the area of the buffer to parse.  The default parse start and end
+  functions use "Minimum Lines Parsed", "Maximum Lines Parsed" and
+  "Defun Parse Goal" to determine how much stuff to parse.
+
+  I also reimplemented Lisp indentation.  Other than general cleanup, use of
+  newly avilable syntax information, and bug fixes, the major changes are:
+   -- Unless there is a reason otherwise, indentation for a form will be copied
+      from the previous form.
+   -- If no special args appear on the same line with the form name, then the
+      special args are indented four spaces.  This is useful with
+      Unwind-Protect and Multiple-Value-Bind.
+   -- DEFxxx is now uniformly treated as a two-arg special form, rather than
+      being bizzarely special-cased.  "Indent Defanything" controls this
+      behavior.
+   -- Lines in the middle of a quoted string are not indented, rather than
+      being indented as though they were lines of code.  This eliminates
+      spurious whitespace in multi-line strings.
+
+/usr/lisp/hemlock/termcap.slisp, 17-Feb-87 12:04:32, Edit by Chiles
+  Made GET-TERMCAP handle TERMCAP environment variable.
+
+/usr/lisp/hemlock/rompsite.slisp, 17-Feb-87 11:48:16, Edit by Chiles
+  Modified SITE-WRAPPER-MACRO to call init/exit methods out of the device.
+  EDITOR-LISTEN now loops a parameter number of times which can be set when
+  using a slow line to make sure the editor listens for input before
+  wasting redisplay effort.
+
+/usr/lisp/hemlock/tty-display.slisp, 16-Feb-87 17:05:01, Edit by Chiles
+  Added "semi dumb" terminal redisplay.  This is used for terminals without
+  add line and delete line.  Made INIT-TTY-DEVICE (renamed) and
+  EXIT-TTY-DEVICE (renamed) call standard init/exit function from
+  Rompsite.Slisp.
+
+/usr/lisp/hemlock/macros.slisp, 14-Feb-87 01:33:08, Edit by Chiles
+  Made LISP-ERROR-ERROR-HANDLER call init/exit methods out of the device
+  when going in and out of Hemlock.
+
+/usr/lisp/hemlock/bit-screen.slisp, 14-Feb-87 01:08:15, Edit by Chiles
+  Added INIT-BITMAP-DEVICE and EXIT-BITMAP-DEVICE.  Now whenever the editor
+  is exited or entered there is a method to be called in the device
+  structure.
+
+/usr/lisp/hemlock/main.slisp, 14-Feb-87 00:27:47, Edit by Chiles
+  Made ED reflect new SITE-WRAPPER-MACRO in Rompsite.Slisp.
+
+/usr/lisp/hemlock/tty-screen.slisp, 14-Feb-87 00:13:44, Edit by Chiles
+  Modified MAKE-DEVICE to reflect new "semi dumb" redisplay ability.
+
+/usr/lisp/hemlock/rompsite.slisp, 12-Feb-87 13:02:40, Edit by DBM.
+  A bug in get-editor-input was causing Hemlock to drop characters.
+  There used to be a (setq *events* before the (rplacd (last *events*...
+
+/usr/lisp/hemlock/rompsite.slisp, 10-Feb-87 15:58:23, Edit by DBM.
+  Modified all the unix package specifiers to be mach.
+
+/usr/lisp/hemlock/tty-display-rt.slisp, 10-Feb-87 15:54:04, Edit by DBM.
+  Modified all the unix package specifiers to be mach.
+
+/usr/lisp/hemlock/spell-rt.slisp, 10-Feb-87 15:52:41, Edit by DBM.
+  Modified all the unix package specifiers to be mach.
+
+/usr/lisp/hemlock/macros.slisp, 10-Feb-87 15:51:58, Edit by DBM.
+  Modified all the unix package specifiers to be mach.
+
+/usr/lisp/hemlock/files.slisp, 10-Feb-87 15:49:03, Edit by DBM.
+  Modified all the unix package specifiers to be mach.
+
+/usr/lisp/hemlock/rompsite.slisp, 14-Jan-87 14:20:03, Edit by DBM.
+  Wrapped a catch of redisplay-catcher around the redisplay form
+  in show-mark -- otherwise sometimes a bad throw would happen.
+
+/usr/lisp/hemlock/rompsite.slisp, 14-Jan-87 14:05:30, Edit by DBM.
+  Export pause-hemlock, so that the command works.
+
+/usr/lisp/hemlock/tty-hunk-stream.slisp, 14-Jan-87 11:58:52, Edit by Chiles
+  Fixed scrolling for random typeout -- forgot to local variable to line 0
+  TTY-HUNK-STREAM-NEWLINE.
+
+/usr/lisp/hemlock/bit-screen.slisp, 13-Jan-87 16:45:31, Edit by DBM.
+  Modified bitmap-make-window so that it creates a bitmap-hunk
+  instead of device-hunk to describe the device.  Also added the
+  arguments :device, :text-pane, and :modeline-pane to the call.
+
+/usr/lisp/hemlock/macros.slisp, 12-Jan-87 12:56:43, Edit by DBM.
+  Changed device-random-output-stream to device-random-typeout-stream.
+
+/usr/lisp/hemlock/tty-screen.slisp, 11-Jan-87 17:03:35, Edit by Chiles
+  This is a new file.  It contains terminal screen management
+  initialization, device methods for window operations, and device methods
+  for random typeout.
+
+/usr/lisp/hemlock/tty-hunk-stream.slisp, 11-Jan-87 16:58:52, Edit by Chiles
+  This is a new file.  It contains stream-hunk and tty-hunk-stream
+  structure definitions and stream operations.  This is used for random
+  typeout.
+
+/usr/lisp/hemlock/tty-display.slisp, 10-Jan-87 15:35:09, Edit by Chiles
+  This is a new file.  It contains terminal device structures, hunk
+  structures, and other structures needed for terminal redisplay methods.
+
+/usr/lisp/hemlock/tty-display-rt.slisp, 31-Dec-86 01:12:12, Edit by Chiles
+  This is a new file.  It contains RT specific, terminal redisplay code.
+
+/usr/lisp/hemlock/termcap.slisp, 11-Jan-87 16:36:33, Edit by Chiles
+  This is a new file.  It contains code for building a representation of
+  terminal capabilities from Unix termcap files.
+
+/usr/lisp/hemlock/screen.slisp, 11-Jan-87 16:30:31, Edit by Chiles
+  This is a new file.  The previous contents are now in Bit-Screen.Slisp --
+  see log entry below.  This file contains new %INIT-SCREEN-MANAGER,
+  PREPARE-FOR-RANDOM-TYPEOUT, and RANDOM-TYPEOUT-CLEANUP functions, and it
+  contains new window operations that dispatch off the device structure --
+  MAKE-WINDOW, NEXT-WINDOW, PREVIOUS-WINDOW, and DELETE-WINDOW.
+
+/usr/lisp/hemlock/rompsite.slisp, 11-Jan-87 16:06:26, Edit by Chiles
+  Organized file into logical partitions with page markers.  Added
+  *editor-console-input* to be used in GET-EDITOR-INPUT, which should go
+  away when we are on a window system -- maybe a device method for
+  translating input characters or even getting them.  Modified INIT-RAW-IO
+  to set *editor-console-input*.  Modified SITE-WRAPPER-MACRO, so it does
+  not signal an error if it cannot find a bitmap device.  Added terminal
+  character translation tables and TTY-TRANSLATE-CHAR.  Added
+  SLEEP-FOR-TIME to be used in input stuff and SHOW-MARK.  Rewrote
+  SHOW-MARK code to dispatch off of device.  Added functions CONSOLEP and
+  GET-TERMINAL-NAME for use in Screen.Slisp.  Modified BUILD-HEMLOCK to be
+  consistent with new files.
+
+/usr/lisp/hemlock/main.slisp, 11-Jan-87 16:00:36, Edit by Chiles
+  Modified ED to call any device init or exit function going in or out of
+  ED.
+
+/usr/lisp/hemlock/display.slisp, 11-Jan-87 14:35:16, Edit by Chiles
+  This is a new file.  The previous contents are now in Bit-Display.Slisp --
+  see log entry below.  This file contains device structure definitions for
+  redisplay methods and device-hunk structure definitions for claiming
+  areas of the screens.  It contains the entry points into redisplay.
+
+/usr/lisp/hemlock/bit-screen.slisp, 11-Jan-87 15:03:07, Edit by Chiles
+  Created from old Screen.Slisp.  Removed functions MAKE-WINDOW,
+  NEXT-WINDOW, PREVIOUS-WINDOW, DELETE-WINDOW, PREPARE-FOR-RANDOM-TYPEOUT,
+  and RANDOM-TYPEOUT-CLEANUP putting them in the new Screen.Slisp.  Added
+  bitmap device funs, bitmap-hunk structure definition, new initialization
+  function for bitmap screen management, new bitmap window operation
+  methods (make, delete, next, previous), and new random typeout setup and
+  cleanup for bitmaps.  Deleted screen-hunk structure definition.
+
+/usr/lisp/hemlock/bit-display.slisp, 11-Jan-87 14:50:38, Edit by Chiles
+  Created file from old Display.Slisp.  Removed functions REDISPLAY,
+  REDISPLAY-ALL, and REDISPLAY-WINDOWS-FROM-MARK putting them in the new
+  Display.Slisp.
+
+/usr/lisp/hemlock/window.slisp, 28-Dec-86 21:46:17, Edit by Chiles
+  Modified %REDISPLAY-INIT to initialize the device before calling
+  REDISPLAY-ALL.
+
+/usr/lisp/hemlock/macros.slisp, 18-Dec-86 17:14:25, Edit by Chiles
+  Rewrote WITH-RANDOM-TYPEOUT to grab the random typeout stream from the
+  device structure gotten from the current window.
+
+/usr/slisp/hemlock/macros.slisp, 22-Oct-86 22:11:22, Edit by Chiles
+  Error-error handler calls BREAK on the condition instead of the string
+  "Hemlock Debug".
+
+/usr/slisp/hemlock/rompsite.slisp, 22-Oct-86 22:01:22, Edit by Chiles
+  Setup for spell files.
+
+/usr/slisp/hemlock/spell-build.slisp, 22-Oct-86 17:48:02, Edit by Chiles
+/usr/slisp/hemlock/spellcoms.slisp, 22-Oct-86 17:47:04, Edit by Chiles
+/usr/slisp/hemlock/spell-augment.slisp, 22-Oct-86 17:46:21, Edit by Chiles
+/usr/slisp/hemlock/spell-correct.slisp, 22-Oct-86 17:45:29, Edit by Chiles
+  The spelling correction stuff has been rewritten substantially.  This is
+  the RT implementation.  These files should be implementation independent,
+  modulo their use of Spell-Rt.Slisp.  
+
+/usr/slisp/hemlock/spell-rt.slisp, 22-Oct-86 17:38:27, Edit by Chiles
+  Created this file to contain implementation dependent spelling code.
+
+/usr/slisp/hemlock/bindings.slisp, 22-Oct-86 17:35:48, Edit by Chiles
+  Used the new DO-ALPHA-CHARS macro from Charmacs.Slisp to do key linking.
+  Also, uncommented the spelling bindings.
+
+/usr/slisp/hemlock/edit-defs.slisp, 11-Oct-16 16:56:45, Edit by Chiles
+  Created this file to contain the stuff just removed from Lispmode.Slisp.
+
+/usr/slisp/hemlock/lispmode.slisp, 10-Oct-16 12:53:41, Edit by Chiles
+  Rewrote GET-DEFINITION-FILE to match longer, more specific directory
+  specification before matching shorter, less specific specifications.
+  Before it only matched whole directory namestrings.
+
+  Removed all of the definition editing code form Lispmode.slisp.
+
+/sys/slisp/hemlock/echo.slisp#1, 08-Sep-86 01:15:37, Edit by Chiles
+/sys/slisp/hemlock/macros.slisp#1, 08-Sep-86 01:15:37, Edit by Chiles
+  Made error handling stuff use the new error system.
+
+/sys/slisp/hemlock/morecoms.slisp#1, 27-Aug-86 10:51:27, Edit by Chiles
+  Modified "View Page Directory" and "Insert Page Directory" to be smarter
+  when creating a pop-up window and to be more general with respect to a
+  :page-delimiter character that is not also a :whitespace character.
+
+/sys/slisp/hemlock/filecoms.slisp#1, 26-Aug-86 16:18:09, Edit by Chiles
+  Modified WRITE-DA-FILE to display the buffer's name when prompting about
+  tacking a newline at the end of the file.
+
+/sys/slisp/hemlock/filecoms.slisp#1, 05-Aug-86 18:17:17, Edit by Chiles
+  Added *buffer-history-ptr* and modified "Select Previous Buffer" to walk
+  down *buffer-history* (when called repeatedly with an argument), selecting
+  successively previous buffers while leaving *buffer-history* unchanged.
+
+/sys/slisp/hemlock/Bindings.slisp#1, 26-Jul-86 10:57:47, Edit by Chiles
+  Added bindings:
+     (bind-key "Kill Previous Word" #\meta-backspace)
+     (bind-key "Echo Area Kill Previous Word" #\meta-backspace)
+     (bind-key "Complete Keyword" #\altmode :mode "Echo Area")
+  The last one is added in case you hit Esc, see nothing happened, and hit
+  it again.  It doesn't hurt to bind this even if you have to hit Esc Esc
+  to get it to work.
+
+/sys/slisp/hemlock/lispmode.slisp#1, 25-Jul-86 11:49:43, Edit by Chiles
+  Fixed bug involving a comment starting after a function name and the
+  first argument being lined up with the comment instead of under the
+  function name; for example:
+     (cond (special-arg-p ; comment this cond branch
+                          (first-thing-in-branch arg)
+			  ...)
+     becomes
+     (cond (special-arg-p ; comment this cond branch
+            (first-thing-in-branch arg)
+	    ...)
+  Note, this is somewhat kludged since a #|...|# comment will still
+  generate bogus indentation, but the whole LISP-INDENTATION algorithm
+  needs to be revamped anyway.
+
+/sys/slisp/hemlock/lispmode.slisp#1, 24-Jul-86 13:22:30, Edit by Chiles
+  "End of Defun" never worked since it was believed that MARK-AFTER was
+  enough to cause NEXT-TOP-LEVEL to move its argument mark, but actually
+  the use of LINE-OFFSET is required.
+
+/sys/slisp/hemlock/lispmode.slisp#1, 23-Jul-86 10:20:29, Edit by Chiles
+  Made LISP-INDENTATION check that the paren was on the start of a line
+  before doing the "DEF" hack with *indent-defanything*.
+
+/sys/slisp/hemlock/echo.slisp#1, 15-Jul-86 12:10:21, Edit by Chiles
+  Missed :trim argument to PROMPT-FOR-STRING while merging.
+
+08-Jul-86
+  Merged most of Hemlock's changes on the Perq since the fall of 85.
+  Didn't try to pick up anything having to do with the eval server/
+  two Lisps.  The files things were taken from were:
+       abbrev.slisp
+       bindings.slisp
+       command.slisp
+       comments.slisp        
+       echo.slisp
+       filecoms.slisp
+       fill.slisp
+       group.slisp
+       indent.slisp
+       kbdmac.slisp
+       killcoms.slisp
+       lispbuf.slisp
+       lispeval.slisp
+       lispmode.slisp
+       main.slisp
+       morecoms.slisp
+       overwrite.slisp
+       perqsite.slisp
+       scribe.slisp
+       searchcoms.slisp
+       text.slisp
+       undo.slisp
+       vars.slisp
+       window.slisp
Index: /branches/new-random/cocoa-ide/hemlock/doc/misc/hemlock.upd
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/misc/hemlock.upd	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/misc/hemlock.upd	(revision 13309)
@@ -0,0 +1,104 @@
+struct.lisp
+struct-ed.lisp
+rompsite.lisp
+charmacs.lisp
+key-event.lisp
+keysym-defs.lisp
+input.lisp
+macros.lisp
+line.lisp
+ring.lisp
+table.lisp
+htext1.lisp
+htext2.lisp
+htext3.lisp
+htext4.lisp
+search1.lisp
+search2.lisp
+linimage.lisp
+cursor.lisp
+syntax.lisp
+winimage.lisp
+hunk-draw.lisp
+@!bit-stream.lisp
+termcap.lisp
+display.lisp
+bit-display.lisp
+tty-disp-rt.lisp
+tty-display.lisp
+@!tty-stream.lisp
+pop-up-stream.lisp
+screen.lisp
+bit-screen.lisp
+tty-screen.lisp
+window.lisp
+font.lisp
+interp.lisp
+vars.lisp
+buffer.lisp
+files.lisp
+streams.lisp
+echo.lisp
+main.lisp
+echocoms.lisp
+defsyn.lisp
+command.lisp
+morecoms.lisp
+undo.lisp
+killcoms.lisp
+searchcoms.lisp
+filecoms.lisp
+indent.lisp
+lispmode.lisp
+comments.lisp
+fill.lisp
+text.lisp
+doccoms.lisp
+srccom.lisp
+group.lisp
+spell-rt.lisp
+spell-corr.lisp
+spell-aug.lisp
+spell-build.lisp
+spellcoms.lisp
+abbrev.lisp
+overwrite.lisp
+gosmacs.lisp
+ts-buf.lisp
+ts-stream.lisp
+eval-server.lisp
+lispeval.lisp
+lispbuf.lisp
+kbdmac.lisp
+icom.lisp
+scribe.lisp
+pascal.lisp
+edit-defs.lisp
+auto-save.lisp
+register.lisp
+xcoms.lisp
+unixcoms.lisp
+mh.lisp
+highlight.lisp
+dired.lisp
+diredcoms.lisp
+bufed.lisp
+lisp-lib.lisp
+completion.lisp
+shell.lisp
+debug.lisp
+netnews.lisp
+bindings.lisp
+compilation.order
+things-to-do.txt
+
+@! Files that don't get compiled, but you'd expect to be listed in a .upd file.
+@!
+@! .../tools/hemcom.lisp
+@! .../tools/hemload.lisp
+@! ed-integrity.lisp
+@! hi-integrity.lisp
+@! hemlock.log
+@! perq-hemlock.log
+@! hemlock.upd
+@! 
Index: /branches/new-random/cocoa-ide/hemlock/doc/misc/notes.txt
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/misc/notes.txt	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/misc/notes.txt	(revision 13309)
@@ -0,0 +1,27 @@
+(defcommand "Find File From Sources" (p)
+  "" ""
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (with-mark ((start point)
+		(end point))
+      (find-file-command
+       nil
+       (merge-pathnames "src:"
+			(region-to-string (region (line-start start)
+						  (line-end end))))))))
+
+* abbrev.lisp
+* doccoms.lisp
+* echo.lisp
+* echocoms.lisp
+* filecoms.lisp
+* lisp-lib.lisp  ;Blew away help command, should do describe mode.
+* lispbuf.lisp
+* lispeval.lisp  ;Maybe write MESSAGE-EVAL_FORM-RESULTS.
+* macros.lisp    <<< Already changed in WORK:
+* mh.lisp        <<< Ask Bill about INC in "Incorporate New Mail".
+* morecoms.lisp
+* register.lisp
+* scribe.lisp
+* searchcoms.lisp
+* spellcoms.lisp
Index: /branches/new-random/cocoa-ide/hemlock/doc/misc/perq-hemlock.log
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/misc/perq-hemlock.log	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/misc/perq-hemlock.log	(revision 13309)
@@ -0,0 +1,146 @@
+/Lisp2/Slisp/Hemlock/perqsite.slisp#1, 23-Mar-85 11:05:16, Edit by Ram
+  Made wait-for-more use logical-char=.
+
+/lisp2/slisp/hemlock/echocoms.slisp#1, 22-Mar-85 13:41:10, Edit by Ram
+  Made "Complete Keyword" and "Help on Parse" pass the parse default into
+  Complete-File and Ambiguous-Files, respectively.
+
+/Lisp2/Slisp/Hemlock/echocoms.slisp#1, 22-Mar-85 10:51:09, Edit by Ram
+  Updated to correspond to new prompting conventions.
+
+/Lisp2/Slisp/Hemlock/echo.slisp#1, 22-Mar-85 10:21:19, Edit by Ram
+  Changes to make defaulting work better.  *parse-default* is now a string
+  which we pretend we read when we confirm an empty parse.
+  *parse-default-string* is now only used in displaying the default, as it
+  should be.  The prompt and help can now be a list of format string and format
+  arguments.  The feature of help being a function is gone.
+
+/Lisp2/Slisp/Hemlock/echo.slisp#1, 22-Mar-85 08:00:01, Edit by Ram
+  Made Parse-For-Something specify NIL to Recursive-Edit so that C-G's will
+  blow away prompts.
+
+/Lisp2/Slisp/Hemlock/buffer.slisp#1, 22-Mar-85 07:57:49, Edit by Ram
+  Added the optional Handle-Abort argument to recursive-edit so that we can
+  have recursive-edits that aren't blown away by C-G's.
+
+/Lisp2/Slisp/Hemlock/spellcoms.slisp#1, 22-Mar-85 07:35:01, Edit by Ram
+  Made Sub-Correct-Last-Misspelled-Word delete the marks pointing to misspelled
+  words when it pops them off the ring.
+
+/lisp2/slisp/hemlock/syntax.slisp#1, 18-Mar-85 07:20:53, Edit by Ram
+  Fixed problem with the old value not being saved if a shadow-attribute was
+  dowe for a mode that is currently active.
+
+/lisp2/slisp/hemlock/defsyn.slisp#1, 14-Mar-85 09:42:53, Edit by Ram
+  Made #\. be a word delimiter by default.  For old time's sake, it is not
+  a delimiter in "Fundamental" mode.
+
+/Lisp2/Slisp/Hemlock/filecoms.slisp#1, 13-Mar-85 00:25:19, Edit by Ram
+  Changed write-da-file not to compare write dates if the file desn't exist.
+
+/Lisp2/Slisp/Hemlock/perqsite.slisp#1, 13-Mar-85 00:15:31, Edit by Ram
+  Changed emergency message stuff to divide the message size by 8.
+
+/Lisp2/Slisp/Hemlock/htext2.slisp#1, 13-Mar-85 00:07:13, Edit by Ram
+  Changed %set-next-character to use the body of Modifying-Buffer.  Made
+  string-to-region give the region a disembodied buffer count.
+
+/Lisp2/Slisp/Hemlock/htext3.slisp#1, 12-Mar-85 23:53:57, Edit by Ram
+  Changed everyone to use the body of modifying-buffer.
+
+/Lisp2/Slisp/Hemlock/htext1.slisp#1, 12-Mar-85 23:45:51, Edit by Ram
+  Made Modifying-Buffer have a body and wrap a without-interrupts around the
+  body.  Changed %set-line-string to run within the body of modifying-buffer.
+
+/Lisp2/Slisp/Hemlock/echocoms.slisp#1, 12-Mar-85 23:28:40, Edit by Ram
+  Made "Confirm Parse" push the input before calling the confirm function so
+  that if it gets an error, you don't have to type it again.  Also changed it
+  to directly return the default if there is empty input, rather than calling
+  the confirm function on the default string.  It used to be this way, and I
+  changed it, but don't remember why.
+
+/Lisp2/Slisp/Hemlock/group.slisp#1, 12-Mar-85 23:10:43, Edit by Ram
+  Made group-read-file go to the beginning of the buffer, which is useful in
+  the case where the file was already read.
+
+/Lisp2/Slisp/Hemlock/lispbuf.slisp#1, 12-Mar-85 22:58:03, Edit by Ram
+  Made "Compile File" use buffer-default-pathname to get defaults for the
+  prompt.  Added "Compile Group" command.
+
+/lisp2/slisp/hemlock/kbdmac.slisp#1, 09-Mar-85 20:53:33, Edit by Ram
+  Made default-kbdmac-transform bind *invoke-hook* so that recursive edits
+  don't try do clever stuff.
+
+/lisp2/slisp/hemlock/perqsite.slisp#1, 09-Mar-85 14:16:41, Edit by Ram
+  Changed editor-input stream to use new stream representation.  Moved
+  Input-Waiting here from Streams, changed definition to return T or NIL
+  instead of number of chars.  Made Wait-For-More not unread the character if
+  it is rubout.  Made level-1-abort handler clear input.
+
+/lisp2/slisp/hemlock/streams.slisp#1, 09-Mar-85 14:59:02, Edit by Ram
+  Changed to use new stream representation.
+
+/lisp2/slisp/hemlock/pane-stream.slisp#1, 09-Mar-85 14:51:25, Edit by Ram
+  Changed to use new stream representation.
+
+/lisp2/slisp/hemlock/lispmode.slisp#1, 05-Mar-85 11:59:15, Edit by Ram
+  Changed the "Defindent" command to go to the beginning of the line before
+  doing the backward-up-list.  This means that we always find the form
+  controlling indentation for the current line, rather than the enclosing form.
+  Do a "Indent For Lisp" after we redefine the indentation, since it presumably
+  changed.
+
+/lisp2/slisp/hemlock/spell-corr.slisp#1, 05-Mar-85 11:39:19, Edit by Ram
+  Fixed everyone to use gr-call.  Made Correct-Spelling call
+  maybe-read-spell-dictionary, rather than trying to look at
+  *spell-opeining-return*.
+
+/lisp2/slisp/hemlock/spell-augment.slisp#1, 05-Mar-85 11:53:04, Edit by Ram
+  Fixed everyone to use gr-call and friends.
+
+/Lisp2/Slisp/Hemlock/command.slisp#1, 21-Feb-85 00:56:52, Edit by Ram
+  Edited back in change to "Scroll Next Window ..." commands to make them
+  complain if there is only one window.
+
+/Lisp2/Slisp/Hemlock/filecoms.slisp#1, 21-Feb-85 00:48:00, Edit by Ram
+  Edited back in changes:
+    Make "Backup File" message the file written.
+    Make Previous-Buffer return any buffer other than the current buffer
+      and the echo area buffer it there is nothing good in the history.
+
+/Lisp2/Slisp/Hemlock/bindings.slisp#1, 21-Feb-85 00:30:48, Edit by Ram
+  Removed spurious binding of #\' to "Check Word Spelling".
+
+/Lisp2/Boot/Hemlock/spellcoms.slisp#1, 05-Feb-85 13:58:54, Edit by Ram
+  Added call to Region-To-String in "Add Word to Spelling Dictionary" so that
+  it worked.
+
+/Lisp2/Boot/Hemlock/fill.slisp#1, 31-Jan-85 12:09:01, Edit by Ram
+  Made "Set Fill Prefix" and "Set Fill Column" define a buffer local variable
+  so that the values are buffer local.
+
+/Lisp2/Boot/Hemlock/fill.slisp#1, 26-Jan-85 17:19:57, Edit by Ram
+  Made / be a paragraph delimiter.
+
+/Lisp2/Boot/Hemlock/search2.slisp#1, 26-Jan-85 17:07:37, Edit by Ram
+  Fixed the reclaim-function for set search patterns to reclaim the set instead
+  of the search-pattern structure.
+
+/Lisp2/Boot/Hemlock/group.slisp#1, 25-Jan-85 22:07:15, Edit by Ram 
+  Changed the way Group-Read-File works.  We always use "Find File" to read in
+  the file, but if "Group Find File" is false, and we created a new buffer, we
+  rename the buffer to "Group Search", nuking any old buffer of that name.  If
+  we are in the "Group Search" buffer when we finish, we nuke it and go to the
+  previous buffer.
+
+/Lisp2/Boot/Hemlock/macros.slisp#1, 25-Jan-85 22:35:26, Edit by Ram
+  Fixed Hlet so that it worked.  Evidently nobody had used it before.  
+
+/Lisp2/Boot/Hemlock/filecoms.slisp#1, 25-Jan-85 23:26:35, Edit by Ram
+  Made "Log Change" merge the buffer pathname defaults into the log file name.
+  Added the feature that the location for the point in the change log entry
+  template can be specified by placing a "@" in the template.
+
+/Lisp2/Boot/Hemlock/search2.slisp#1, 25-Jan-85 23:23:35, Edit by Ram
+  Fixed various one-off errors in the end args being passed to position and
+  %sp-find-character-with-attribute.
Index: /branches/new-random/cocoa-ide/hemlock/doc/misc/things-to-do.txt
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/misc/things-to-do.txt	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/misc/things-to-do.txt	(revision 13309)
@@ -0,0 +1,630 @@
+-*- Mode: Text; Package: Hemlock; Editor: t -*-
+
+
+
+
+;;;; X problems.
+
+Compute mininum width of a window group by taking the maximum of all the
+windows' font-widths, each multiplied by minimum-window-columns.  Right now it
+just uses the default font or current window.
+
+Compute minimum window split correctly: look at current window's font-height
+and new window's font-height, extra height pixels, whether each has a modeline,
+and minimum-window-lines to determine if we can split the current window.
+
+Server not implementing DRAW-IMAGE-GLYPHS correctly, so we don't have to do our
+pixmap hack.
+
+
+
+
+;;;; Bill and/or Rob.
+
+Make editor-error messages; that is just make many of the (editor-error)
+forms have some string to be printed.
+   Importance: often beeps and don't know why.
+   Difficulty: pervasive search for EDITOR-ERROR.
+
+Probably the ERROR for trying to modify a read-only buffer could/should be an
+EDITOR-ERROR.  Maybe the error message should be a Hemlock variable that can be
+set for certain buffers or modes.
+
+Make definition editing different.  Maybe only one command that offers some
+appropriate default, requiring confirmation.  Maybe some way to rightly know to
+edit the function named under a #'name instead of the function name in a
+function position.  Think about whizzy, general definition location logging and
+finding mechanism that is user extensible.
+
+Think about regular expression searching.
+   Importance: it would be used weekly by some and daily by others.
+
+Make illegal setting window width and height, (or support this).
+
+Think about example init file for randoms.  It should show most of the simple
+through intermediate customizations one would want to do starting to use
+Hemlock.
+  setting variables
+  file type hooks
+  hooks
+  transposing two keys
+  changing modifiers
+  
+DEFMODE should take a keyword argument for the modeline name, so "Fill"
+could be named "Auto Fill" but show "Fill" in the modeline (similarly with
+"Spell" and "Save").
+   Importance: low.
+   Difficulty: low.
+
+Optional doc strings for commands?
+   Importance: suggested by a couple people.
+   Difficulty: ???
+
+Get a real italic comment mode.
+   Importance: some people want it, like Scott.
+   Difficulty: hard to do right.
+
+Line-wrap-character a user feature?  Per device?  Per device set from Hvar?
+   Importance: a few people set this already for bitmap devices.
+   Difficulty: low.
+   Bill should just throw this in.
+
+When MESSAGE'ing the line of a matching open paren, can something be done to
+make the exact open paren more pronounced -- SUBSEQ'ing the line string?
+   Importance: low
+   Difficulty: one line frob to major echo area changes.
+
+Do something about active region highlighting and blank lines.  Consider
+changing redisplay to be able to hack some glyph onto the line, a virtual
+newline or something.
+   Importance: blank lines at the ends of the active region can be confusing.
+   Difficulty: unknown difficult changes to redisplay.
+
+Change redisplay on bitmaps to draw top down?  Currently line writes are queued
+going down the window image but the queue is written backwards.
+   Importance: low, two people commented on how it looks funny.
+   Difficulty: unknown, but probably little.
+
+Disallow tty I/O when the tty is in a bad state.  Since editor is sharing
+Unix standard input with *terminal-io*, doing reads on this is bad among
+other problems.
+   Importance: necessary or non-experienced users.
+   Difficulty: slight.  Error system wants to use *terminal-io* if you go
+               into a break loop from the editor.
+   Bill.
+
+Make Lisp indentation respect user indentation even when in a form with known
+special arguments?
+   Importance: noticeable correctness.
+   Difficulty: Lucid wrote this already with LOOP macro.
+   Rob.
+Make Lisp motion that exceeds the parsed region lose more gracefully by
+informing the user, possibly offering to enlarge the parsing parameters.
+   Importance: very deceptive as it is currently.
+   Difficulty: ???
+   Rob.
+Lisp motion fails to handle correctly vertical bar syntax; for example,
+      package:|foo|
+   Importance: correctness, not too necessary
+   Difficulty: ???
+"Editor Evaluate Defun" does not handle multiple value returns correctly
+... if we admit that this is often used to evaluate non-DEFUN top-level
+forms.
+   Importance: user convenience.
+   Difficulty: low.
+
+Super-confirm select buffer.  Super confirm means "make this be a legal
+input".  Has no interaction with prompting function interface.  More
+generally, make a *super-confirm-parse-function* that can be bound around
+prompters.  One suggestion when prompting for a buffer is to make it, but
+another suggestion is to find file some appropriate file.
+   Importance: multiple people requested.
+   Difficulty: low.
+   Bill.
+A super-confirm for a more facist "Find File" that disallowed creating buffers
+when the file didn't exist could tell the command to really create the buffer.
+
+Displayed-p shouldn't directly call update-window-image, or perhaps uwi should
+be changed to check if the ticks and whatnot indicate recomputation is needed.
+   Importance: minor efficiency hack and maybe a little cleaner.
+   Difficulty: low.
+   Bill.
+
+Fix line-length for hemlock output streams.  The following example causes lines
+to brek incorrectly in "Eval" mode but not in "Typescript" mode:
+   (defun dup (x n &aux r) (dolist (i n r) (push x r)))
+   (dup 'a 100)     ;lines wrap due to faulty line breaking
+   (dup 'aa 100)    ;lines wrap due to faulty line breaking
+   (dup 'aaa 100)   ;now lines break correctly
+   Importance: correctness.  It's not screwing anyone.
+   Difficulty: depends on what the right thing is.
+
+Termcap bug:
+   setenv TERMCAP "foobar:li#65:tc=vt102:"
+   set term = foobar
+This causes an EOF unexpectedly on the string stream.  This is because the
+the termcap parsing stuff wasn't written to go all the way back to the top
+entry point to determine what file to use when the TERMCAP variable had an
+indirection.  The code currently just goes to the beginning of the stream
+and looks for the new tty name.
+
+Make prompt text not part of input buffer.  Do some magical thing to solve
+the problem of having special echo area commands that simply get around the
+prompt text in the echo are buffer.
+   Importance: low sense problem is currently somewhat taken care of.
+	       Possibly resolve problem when new Hemlock environment stuff
+	       goes in.
+   Difficulty: Magical in origin.
+   Rob.
+
+Commonify everything.  Make everything portable that could be made so (file
+system extensions, character att. finding, string ops, etc.) and document
+our expectations of the non-portable stuff we lean on.  Provide portable
+code for stuff done in assembler.
+   Some known problems:
+      %sp- functions aren't documented and don't have portable code for
+         them.
+      semantics of initial values versus declared type.
+      :error-file to COMPILE-FILE calls.
+
+   Importance: cleanliness and portability ease for those who want our
+	       code.
+   Difficulty: identify the problems and alter some code.
+   Bill and Rob.
+
+Fix things that keep text from getting gc'ed.  Buffer local things keep
+pointer to buffer.
+   Importance: could be important, maybe nothing is wrong.
+   Difficulty: identifying problems.
+   Bill or Rob.
+
+Two reproducible window image builder bugs:
+THIS IS NUMBER ONE:
+I wrote this command:
+   (defcommand "Fetch Input" (p)
+     "Does \"Point to Here\" followed by \"Reenter Interactive Input\"."
+     "Does \"Point to Here\" followed by \"Reenter Interactive Input\"."
+     (declare (ignore p))
+     (point-to-here-command nil)
+     (reenter-interactive-input-command nil))
+I made the following bindings:
+   (bind-key "Fetch Input" #\hyper-leftdown :mode "Eval")
+   (bind-key "Fetch Input" #\hyper-leftdown :mode "Typescript")
+   (bind-key "Do Nothing" #\hyper-leftup :mode "Eval")
+   (bind-key "Do Nothing" #\hyper-leftup :mode "Typescript")
+In an interactive buffer I typed hyper-leftdown twice on the same line and
+got the following error:
+   Error in function HEMLOCK-INTERNALS::CACHED-REAL-LINE-LENGTH.
+   Vector index, 14700, out of bounds.
+This index is always the one you get no matter what line of input you try to
+enter twice.
+;;;
+THIS IS NUMBER TWO:
+Put point at the beginning of a small defun that has at least some interior
+lines in addition to the "(defun ..." line and the last line of the routine.
+Mark the defun and save the region.  Now, yank the defun, and note that the
+beginning of the second instance starts at the end of the line the yanked copy
+ends on.  Now type c-w.  You'll delete the yanked copy, and the lines that
+should not have been touched at all end up with font marks.  Interestingly the
+first line of the defun and the last don't get any font marks.
+   Importance: well, they are reproducible, and they're pretty ugly.  No one
+   	       has noticed these yet though.
+   Difficulty: Rob and I didn't conjure up the bugs after a casual inspection.
+   Bill AND Rob
+
+Consider a GNU-style undo where action is undo-able.
+   Importance: low, but people point it out as an inadequacy of Hemlock.
+   Difficulty: possibly very hard.  Have to figure out what's necessary first.
+   Bill and Rob
+
+
+
+;;;; Mailer stuff.
+
+Find all message-info-msgs sets and refs, changing them from possible list
+values to always be a simple-string value.  Maybe must leave a list (or make
+another slot) if I need to indicate that I can't use the value as a msg-id.
+The only problem is coming through SHOW-PROMPTED-MESSAGE.  This could pick or
+something to really know if there were more than one message or not.
+
+Write "Refile Message and Show Next".
+
+Do something about message headers when reading mail.  Suggestions include a
+list of headers components that get deleted from the buffer and simply
+scrolling the window past the "Received:" lines.
+
+Add more folder support and possibly something specific for Bovik groveling.
+For example, rehashing the cached folder names and/or adding new ones from a
+folder spec or root directory (allows adding the bovik folders).
+
+Consistency problems:
+   Expunging message should not JUST delete headers buffers and their
+   associated message buffers.  There could be independent message buffers with
+   invalid message id's.  Since these are independent, though, we might not
+   want to gratuitously delete them.
+
+   "Headers Delete Message" should check for message buffers when virtual
+   message deletion is not used, deleting them I suppose.  Instead of just
+   making headers buffers consistent.
+
+
+
+
+;;;; Spelling stuff.
+
+This stuff is probably for Rob or Bill, but think about undergrad
+dispatching before actually implementing it.
+
+Two apostrophes precede a punctuation character, as in:
+	``This is a very common occurrence in TeX.''
+"Correct Buffer Spelling" complains that '' is an unknown word.  The problem
+doesn't show up if the character preceding the apostrophes is alphabetic.
+
+"Correct Last Misspelled Word" should try to transpose the space on the
+ends of a word if there are more than one misspelling (adjacent?).  This
+would have to be done at the command level trying to correct different
+words formed from the buffer.
+
+Fahlman would like to see a list of words that are treated as errors, even
+though they may be in the dictionary.  These are considered common typos made
+that actually are rarely-used words.  These would be flagged as errors for the
+user to do a conscious double check on.
+
+When the spelling correction stuff cannot find any possible corrections, it
+could try inserting a space between letters that still form legal words,
+checking the two new words are in the dictionary.
+   Importance: possibly pretty useful, especially with "Spell" mode.
+   Difficulty: low to medium.
+   Bill, possibly undergrad after I looked at it.
+
+Fix "Undo Last Spelling" correction interaction with auto-fill.  When this
+command is invoked on a word that made auto-fill break the line, shit
+happens.
+   Importance: Rob noticed it.
+   Difficulty: unknown.
+   Bill or Rob.
+
+
+
+
+;;;; User and Implementors Manuals
+
+User Manual wall chart appendix based on systems (e.g., dired, mailer, Lisp
+editing, spelling, etc.), then modes (e.g., "Headers", "Message", and "Draft"),
+then whatever seems appropriate.
+
+Point out that "Make Buffer Hook" runs after mode setup.
+
+
+
+
+;;;; Things for undergrads.
+
+Create "Remote Load File" and make "Load File" use it the way "Compile File"
+uses "Remote Compile File".
+
+Make "Insert Scribe Directive" undo-able, and make the "command" insertion
+stuff use the active region.  Also, clean up terminology with respect to using
+command and environment.
+   Importance: it would be nice.
+   Difficulty: little
+
+Add a feature that notes modified or new lines, probably down in
+HI::MODIFYING-BUFFER.  Then add interfaces for moving over these lines, moving
+over text structures with these lines such as DEFUN's, paragraphs, etc.  Write
+commands that display these in some way, compile them, etc.
+
+Look at open paren highlighting and the Scribe bracket table stuff to make a
+general bracket highlighter.  Possibly have to call function based on mode or
+something since Lisp parens are found differently than Scribe brackets (Lisp
+parse groveling versus counting open and close brackets).
+
+Make hooks that are lists of function have list in the name, so users can know
+easily whether to set this to a list or function.
+   Importance: low.
+   Difficulty: low, but pervasive.  must be careful.
+
+Make FILTER-REGION not move all marks in the buffer to the end.  It should
+affect each line, letting marks stay on a line, instead of deleting the whole
+region and inserting a new one.
+   Importance: low, but described behaviour is better than current behaviour.
+   Difficulty: low.
+
+Make some "Auto Save Access" variable, so users don't have to write fully
+protected auto save files.  Possibly there could be some variable to that
+represents Hemlock's default file writing protection.
+   Importance: one person requested.
+   Difficulty: easy.
+
+Make "Save" mode on a first write or on startup check for a .CKP file.  If it
+is there and has a later write date than the file, warn the user before a save
+could overwrite this file that potentially has good stuff in it from a previous
+Lisp crash.
+   Importance: good idea, though people should know to check.
+   Difficulty: easier if done on start up.
+
+We need Lisp-like movement in Text mode -- skipping parenthetic and quoted
+expressions while ignoring some Lisp syntax stuff.  Either can write a few
+commands that do what we expect, or we can get really clever with the
+pre-command parse checking and bounds rules for Text mode.  May even be able to
+get the right thing to happen with code fragments in documents.
+   Importance: would be pretty convenient to have it work right all the time.
+   Difficulty: will take some thinking and playing around.  Rob or Bill guidance.
+
+Make "Extended Command" offer a default of the last command entered.
+
+Make "Select Group" command take an optional argument for the group
+pathname and group name.
+   Importance: convenience for init files.
+   Difficulty: low.
+
+Put in buffer percentage.
+   Importance: Lots of people want it.
+   Difficulty: Rob thinks he knows how to do it.
+   Rob will tell some undergrad how to do it.
+
+Make "Unexpand Abbrev" work when no expansion had been done -- test for
+error condition was backwards.
+
+Add modeline display of current eval server and current compile server, when
+appropriate. 
+   Importance: suggested by a couple people.  Low.
+   Difficulty: none.
+   	       Basically, just have to change string and function.
+
+Make "Corrected xxx to yyy" messages use actual case of yyy that was
+inserted into the buffer.
+   Importance: more user friendly.
+   Difficult: low.
+   Anyone could do this, but it wouldn't be very educational for an
+      undergrad. 
+
+"Find all Symbols" does a FIND-ALL-SYMBOLS on previous or current form if
+it is a symbol.  See code for "Where is Symbol" in Scott's
+Hemlock-Init.Lisp file.
+   Importance: probably quite useful.
+   Difficulty: none.
+   Anyone could grab Scott's code.
+
+Make buffer read-only when visiting unwritable file?  Bill and Scott
+vehemently disagreed with this, but thought a variable would make everyone
+happy.
+   Importance: one person suggested.
+   Difficulty: low.
+   Anyone could do this, but it wouldn't be very educational for an
+      undergrad. 
+
+Modify MAKE-BUFFER to error when buffer exists?
+   Importance: more user friendly.
+   Difficulty: none.
+   Anybody could do this, but it wouldn't be very educational for an
+      undergrad. 
+
+Warn when unable to rename a buffer according to its file.  This occurs
+when writing files.
+   Importance: more user friendly.
+   Difficulty: none.
+   Anyone could do this.
+Uniquify buffer names by tacking a roman numeral on the end?
+   Importance: I don't know why this is here.
+   Difficulty: low.
+   Anyone could do this.
+
+Automatically save word abbrevs?
+   Importance: low.
+   Difficulty: low.
+   Some undergrad could do this.
+
+Automatically save named keyboard macros?  Maybe on request?
+   Importance: other editors can do it.
+   Difficulty: this is non-trivial since our kbmacs are based on their own
+	       little interpreter.
+   Medium undergrad task.
+
+Make nested prompts work.
+   Importance: some day this might be useful.
+   Difficulty: medium.
+   Upper level undergrad could do this.
+
+Make character searches deal with newlines.
+   Importance: correctness.
+   Difficulty: medium.
+   Upper level undergrad.
+
+Put argument type checks in the Hemlock primitives.
+   Importance: low, the compiler should do this from type declaration
+	       (cool?!).
+   Difficulty: work in a lot of places.
+   Undergrad could do the things Rob or Bill say.
+
+Add a "Preferred File Types" to work in coordination with "Ignore File Types".
+   Importance: low, suggested by one user.
+   Difficulty: minimal.
+
+Write separate search and i-search commands that do case-sensitive searches, so
+user's don't have to set the Hvar for one search.
+   Importance: low.
+   Difficulty: low.
+
+Add a write-region function which writes to a stream.
+   Importance: low.
+   Difficulty: medium.
+   Undergrad.
+
+
+
+
+;;;; The great rewrite and cleanup.
+
+Compilation order.  Cleanup up defvars, defhvars, proclaims, etc. for clean
+compilation of Hemlock in a Lisp without one.  Rename ED and HI packages
+and start cleaning up compilation.  Defvars should go near pertinent code,
+and proclaims should do the rest.  Do something about macros, rompsite, and
+main.
+   Importance: necessary for those taking our code and sets better example.
+   Difficulty: few days of work.
+   Bill.
+
+Hemlock package cleanup -- exporting Hemlock stuff, so users don't live in
+ED package.
+ Find primitives to export and describe in Command Implementor's Manual.
+ Export existing command names in a separate file.
+ DEFCOMMAND always interns in current package.
+ Variables
+  One global table.
+  DEFHVAR only at top level.  Interns into current package.  WHAT ABOUT SITE-INIT?
+  BIND-VARIABLE, a new form, will be used at top level or in setup
+   functions to establish default values.
+ Find all uses of FIND-PACKAGE, *hemlock-package*, etc. since these are
+  suspect in the new package regime.
+ Put DEFVAR's (esp. from Main.Lisp) in appropriate files, putting PROCLAIM's
+   in a single file or in files with compiler warnings.
+      Importance: really needs to be done along with environment stuff.
+      Difficulty: pervasive changes to get right.
+      Bill!
+
+Generalized environments:
+  Generalize notion of environment to first-class objects.
+  can inherit stuff from other environments.  Shadowing for conflict
+  resolution.  Transparent key bindings another sort of interaction.
+  If we retain modes as a primitive concept, then how do they interact?
+  If not, how do we get the effect?  Each buffer has an environment.
+  This is normally the composition of the default environment and
+  various mode environments.
+
+  Turning modes on and off is simply adding and removing the mode's environment
+  from the buffer's environment's inherit list.  The only sticky issue is the
+  order of the inheritence.  We could assign each environment a precedence.
+
+  I guess we could punt modes as a primitive concept.  The only thing this
+  wouldn't provide that modes do is a namespace and the major/minor
+  distinction.  Setting the major mode is just frobbing the lowest precedence
+  environment in a buffer.  A major mode is distinct from a minor mode in that
+  it inherits the global environment.  An interesting question is at which
+  level precedences should be implemented.  We could have it be a property only
+  of minor modes, which determines only the order in which a buffer inherits
+  its minor modes, or we could make it a property of environments, and have it
+  determine the total order of inheritance.  Probably the former is better: it
+  simpler, and adequate.  Also, at the environment level, it is more powerful
+  to be able to specify inheritance order on a per-case basis.
+
+  Make mode-hooks be a mode-object slot rather than hemlock variables.  [a
+  random cleanup]
+
+  We change the (... &optional kind where) arguments to
+  (... &optional where).  Where can be an environment such as
+  *global-environment* (the default) or a buffer, or it can be a string, in
+  which case it is interpreted as a mode name.
+
+  Instead of having key binding transparentness be a property of modes or of
+  commands, we make it a property of binding.  Each environment has separate
+  key-tables for transparent and opaque bindings, and there is a
+  Transparent-Bind-Key function that is used to make transparent key bindings.
+  [... or something.  This would imply a delete-transparent-key-binding and
+  prehaps other functions, so we might consider passing a transparent flag to
+  the primitives.]
+
+  *current-environment* is the current environment, which is normally eq to the
+  current buffer.  Attributes and variables are implemented using deep-binding
+  and caching.  Whenever there is any change to the inheritance structure or to
+  variable or attribute bindings, then we just totally flush all the caches.
+  The most frequent operation that would cause this to happen would be changing
+  a mode in a buffer, which is rare enough so that there should be no problem.
+
+  For variables, we just have a symbol-name X environment => binding cache.
+
+  For attributes we have two caches: attribute X environment => value vector
+  and attribute X environment X test-function => search vector.  The first
+  translates an attribute and environment to a simple-vector that contains the
+  current value for each character in that environment.  This is used for
+  Character-Attribute and when the Find-Attribute cache misses.  When this
+  cache misses, we fill the vector with a magic "unspecified" object, and then
+  scan up the inheritance, filling in any bindings that are unspecified.  We
+  could optimize this by noting in the character-attribute object when an
+  attribute has no shadowings.  character-attribute hooks have to go away,
+  since they depends on shallow-binding.
+
+  Make Hemlock variables be typed.  Have a :type defhvar argument,
+  variable-type function.  In implementation, create a test function for each
+  variable so that we can efficiently check the type of each assigned value.
+  This implies defhvar should be a macro.  We could make specifying the test
+  function be an explicit feature, but the same effect could always be obtained
+  with a Satisfies type specfier.
+
+  Split binding of hvars from definition.  
+      Bind-Variable Symbol-Name Value &Optional Where
+  Creates a binding.  If :Value is specified to defhvar, then it creates a
+  global binding of that value.  If no :Value is specified, then there is no
+  global binding.  We could flush the :Mode and :Buffer options, and require an
+  explicit Bind-Variable to be done in this case, or we could still allow them.
+  It would probably be better to flush them, since it would break code that is
+  doing run-time defhvars to make buffer-local variables.  Perhaps we would
+  flush only :Buffer, since it is clearly useless, while being able to give an
+  initial mode binding may be useless.
+
+  All variable attributes except for value are global.  Hooks are global.  The
+  concept of a hook is somewhat dubious in the presence of non-global bindings.
+  It might be semi-useful to invoke the hook on each new binding in addition to
+  on each set.
+
+     Importance: Next big step for Hemlock.
+     Difficulty: Two months.
+     Bill will do this.
+
+Multiple font support:
+ Figure what kind of multi-font stuff we want to do.
+ Bogus to use integer constants for facecodes.  It is reasonable within the
+ font mark, but the user interface should be keywords for facecodes.
+   Importance: no documented font support currently.  Really need it.
+   Difficulty: includes massively reworking redisplay data structures.
+   Bill and Rob.
+
+
+
+
+;;;; Things to think about.
+
+;;; These are things that have been thought of, but we don't know much more
+;;; about them.
+
+Some general facility for users to associate definition locations with kinds of
+things and/or forms.
+
+What's the right way to be in a comment in some Lisp file and have filling,
+spelling, and whatever work out just right.  Possibly regions with environment
+information.  Maybe with a whole new hierarchical text representation, this
+would fall out.
+
+Synchronization/exclusion issues:
+    Currently there are non-modification primitives that are looking into a
+    buffer assuming it will not change out from under the primitive.  We
+    need to identify these places and exactly what the nature of this
+    problem is (including whether it exists).  Probably we need to make
+    non-trivial text examination primitives use without-interrupts so that
+    they see a consistent state.
+
+    Find other places where exclusion is needed:
+        Redisplay?
+        Typescript code?
+
+Online documentation stuff: What to do and how to do it.  Rob has some
+notes on this from a year or two ago.
+   Importance: something to do.
+   Difficulty: high.
+   maybe no one.
+
+Think about general "Save My Editor State".  Can generalize notion of
+stateful things? -- Word abbrevs, keyboard macros, defindent, spelling
+stuff, etc.  This could be the last thing we ever do to Hemlock.
+   Importance: low.
+   Difficulty: very.
+   ???
+
+
+
+
+;;;; New Eval Servers
+
+Do something about slaves dieing in init files.  Lisps start up and first load
+init.lisp.  When a slave does this, it goes into the debugger before connecting
+to the editor.
Index: /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/NOTES
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/NOTES	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/NOTES	(revision 13309)
@@ -0,0 +1,13 @@
+Scribe Syntax
+
+The Syntax of Scribe is actually very nice. A command is always
+introduced by #\@ followed by the command name and arguments delimited
+by delimiters (sic).
+
+The following delimiter pairs are supported:
+
+    { }   [ ]   < >   ( )   " "   ' '
+
+
+
+$Id$
Index: /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/README
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/README	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/scribe-converter/README	(revision 13309)
@@ -0,0 +1,12 @@
+This directory should eventually contain a scribe to HTML converter
+using the same backend formatter as i used for the annotatable CLIM
+manual.
+
+Since very rare information about Scribe is available, we'll work by
+infering the neccessary information from the Scribe files we have at
+hand, see file NOTES for details.
+
+$Id$
+
+
+
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/commands.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/commands.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/commands.mss	(revision 13309)
@@ -0,0 +1,822 @@
+@comment{-*- Dictionary: hem; Mode: spell; Package: Hemlock -*-}
+@chap[Basic Commands]
+@section[Motion Commands]
+
+@index[commands, basic]@index[motion]There is a fairly small number of
+basic commands for moving around in the buffer.  While there are many other
+more complex motion commands, these are by far the most commonly used and
+the easiest to learn.
+
+@defcom[com "Forward Character", bind (C-f, Rightarrow)]
+@defcom1[com "Backward Character", bind (C-b, Leftarrow)]
+@index[character, motion]
+@hid[Forward Character] moves the point forward by one character.  If a prefix
+argument is supplied, then the point is moved by that many characters.
+@hid[Backward Character] is identical, except that it moves the point
+backwards.
+@enddefcom
+
+@defcom[com "Forward Word", bind {M-f}]
+@defcom1[com "Backward Word", bind {M-b}]
+@index[word, motion]These commands move the point forward and backward
+over words.  The point is always left between the last word and first
+non-word character in the direction of motion.  This means that after moving
+backward the cursor appears on the first character of the word, while after
+moving forward, the cursor appears on the delimiting character.  Supplying
+a prefix argument moves the point by that many words.
+@enddefcom
+
+@defcom[com "Next Line", bind (C-n, Downarrow)]
+@defcom1[com "Previous Line", bind (C-p, Uparrow)]
+@defcom1[com "Goto Absolute Line"]
+@index[line, motion]
+@hid[Next Line] and @hid[Previous Line] move to adjacent lines, while remaining
+the same distance within a line.  Note that this motion is by logical lines,
+each of which may take up many lines on the screen if it wraps.  If a prefix
+argument is supplied, then the point is moved by that many lines.
+
+The position within the line at the start is recorded, and each successive
+use of @binding[C-p] or @binding[C-n] attempts to move the point to that
+position on the new line.  If it is not possible to move to the recorded
+position because the line is shorter, then the point is left at the end of
+the line.
+
+@hid[Goto Absolute Line] moves to the indicated line, as if you counted them
+starting at the beginning of the buffer with number one.  If the user supplies
+a prefix argument, it is the line number; otherwise, @Hemlock prompts the user
+for the line.
+@enddefcom
+
+@defcom[com "End of Line", bind {C-e}]
+@defcom1[com "Beginning of Line", bind {C-a}]
+@hid[End of Line] moves the point to the end of the current line, while 
+@hid[Beginning of Line] moves to the beginning.  If a prefix argument is
+supplied, then the point is moved to the end or beginning of the line that
+many lines below the current one.
+@enddefcom
+
+@defcom[com "Scroll Window Down", bind {C-v}]
+@defcom1[com "Scroll Window Up", bind {M-v}]
+@index[scrolling]
+@hid[Scroll Window Down] moves forward in the buffer by one screenful of text,
+the exact amount being determined by the size of the window.  If a prefix
+argument is supplied, then this scrolls the screen that many lines.  When this
+action scrolls the line with the point off the screen, it this command moves
+the point to the vertical center of the window.  @hid[Scroll Window Up] is
+identical to @hid[Scroll Window Down], except that it moves backwards.
+@enddefcom
+
+@defhvar[var "Scroll Overlap", val {2}]
+This variable is used by @hid[Scroll Window Down] and @hid[Scroll Window Up] to
+determine the number of lines by which the new and old screen should overlap.
+@enddefhvar
+
+@defcom[com "End of Buffer", bind (M-<)]
+@defcom1[com "Beginning of Buffer", bind (@bf[M->])]
+These commands are used to conveniently get to the very beginning and end of the
+text in a buffer.  Before the point is moved, its position is saved by
+pushing it on the mark stack (see page @pageref[marks]).
+@enddefcom
+
+@defcom[com "Top of Window", bind (M-,)]
+@defcom1[com "Bottom of Window", bind (M-.)]
+@index[window, motion]@hid[Top of Window] moves the point to the beginning of
+the first line displayed in the current window.  @hid[Bottom of Window] moves
+to the beginning of the last line displayed.
+@enddefcom
+
+
+@section[The Mark and The Region]
+
+@label[marks]@index[marks]@index[region]@index[selection]Each buffer has a
+distinguished position known as the @i[mark].  The mark initially points to the
+beginning of the buffer.  The area between the mark and the point is known as
+the @i[region].  Many @hemlock commands which manipulate large pieces of text
+use the text in the region.  To use these commands, one must first use some
+command to mark the region.
+
+@index[active regions]Although the mark is always pointing somewhere (initially
+to the beginning of the buffer), region commands insist that the region be made
+@i[active] before it can be used.  This prevents accidental use of a region
+command from mysteriously mangling large amounts of text.
+
+@defhvar[var "Active Regions Enabled", val {t}]
+When this variable is true, region commands beep unless the region is active.
+This may be set to @false for more traditional @emacs region semantics.
+@enddefhvar
+
+Once a marking command makes the region active, it remains active until:
+@begin[itemize]
+a command uses the region,
+
+a command modifies the buffer,
+
+a command changes the current window or buffer,
+
+a command signals an editor error,
+
+or the user types @binding[C-g].
+@end[itemize]
+Motion commands have the effect of redefining the region, since they move the
+point and leave the region active.
+
+@index[ephemerally active regions]Commands that insert a large chunk of
+text into the buffer usually set an @i[ephemerally active] region around
+the inserted text.  An ephemerally active region is always deactivated by
+the next command, regardless of the kind of command.  The ephemerally
+active region allows an immediately following region command to manipulate
+the inserted text, but doesn't persist annoyingly.  This is also very
+useful with active region highlighting, since it visibly marks the inserted
+text.
+
+
+@defhvar[var "Highlight Active Region", val {t}]
+@defhvar1[var "Active Region Highlighting Font", val {nil}]
+When @hid[Highlight Active Region] is true, @hemlock displays the text in the
+region in a different font whenever the region is active.  This provides a
+visible indication of what text will be manipulated by a region command.
+Active region highlighting is only supported under @windows.
+
+@hid[Active Region Highlighting Font] is the name of the font to use for active
+region highlighting.  If unspecified, @hemlock uses an underline font.
+@enddefhvar
+
+
+@defcom[com "Set/Pop Mark", bind (C-@@)]
+This command moves the mark to the point (saving the old mark on the mark
+stack) and activates the region.  After using this command to mark one end of
+the region, use motion commands to move to the other end, then do the region
+command.  This is the traditional @emacs marking command; when running under a
+windowing system with mouse support, it is usually easier to use the mouse with
+the @comref[Point to Here] and @comref[Generic Pointer Up].
+
+For historical reasons, the prefix argument causes this command to do things
+that are distinct commands in @Hemlock.  A prefix argument of four does
+@hid[Pop and Goto Mark], and a prefix argument of @f[16] does
+@hid[Pop Mark].
+@enddefcom
+
+@defcom[com "Mark Whole Buffer", bind (C-x h)]
+@defcom1[com "Mark to Beginning of Buffer", bind (C-<)]
+@defcom1[com "Mark to End of Buffer", bind (C->)]
+@hid[Mark Whole Buffer] sets the region around the whole buffer, with the point
+at the beginning and the mark at the end.  If a prefix argument is supplied,
+then the mark is put at the beginning and the point at the end.  The mark is
+pushed on the mark stack beforehand, so popping the stack twice will restore
+it.
+
+@hid[Mark to Beginning of Buffer] sets the current region from point to the
+beginning of the buffer.
+
+@hid[Mark to End of Buffer] sets the current region from the end of the buffer
+to point.
+@enddefcom
+
+@defcom[com "Activate Region", bind (C-x C-Space, C-x C-@@)]
+This command makes the region active, using whatever the current position of
+the mark happens to be.  This is useful primarily when the region is
+accidentally deactivated.
+@enddefcom
+
+
+@subsection[The Mark Stack]
+
+@index[mark stack]As was hinted at earlier, each buffer has a @i[mark stack],
+providing a history of positions in that buffer.  The current mark is the mark
+on the top of the stack; earlier values are recovered by popping the stack.
+Since commands that move a long distance save the old position on the mark
+stack, the mark stack commands are useful for jumping to interesting places in
+a buffer without having to do a search.
+
+@defcom[com "Pop Mark", bind (C-M-Space)]
+@defcom1[com "Pop and Goto Mark", bind (M-@@, M-Space)]
+@hid[Pop Mark] pops the mark stack, restoring the current mark to the next most
+recent value.  @hid[Pop and Goto Mark] also pops the mark stack, but instead of
+discarding the current mark, it moves the point to that position.  Both
+commands deactivate the region.
+@enddefcom
+
+@defcom[com "Exchange Point and Mark", bind (C-x C-x)]
+This command interchanges the position of the point and the mark, thus moving
+to where the mark was, and leaving the mark where the point was.  This command
+can be used to switch between two positions in a buffer, since repeating it
+undoes its effect.  The old mark isn't pushed on the mark stack, since it is
+saved in the point.
+@enddefcom
+
+
+@subsection[Using The Mouse]
+
+@index[mouse]It can be convenient to use the mouse to point to positions in
+text, especially when moving large distances.  @hemlock defines several
+commands for using the mouse.  These commands can only be used when running
+under @windows (see page @pageref[using-x].)
+
+@defcom[com "Here to Top of Window", bind (Rightdown)]
+@defcom1[com "Top Line to Here", bind (Leftdown)]
+@index[window, motion]@hid[Here to Top of Window] scrolls the window so as to
+move the line which is under the mouse cursor to the top of the window.  This
+has the effect of moving forward in the buffer by the distance from the top of
+the window to the mouse cursor.  @hid[Top Line to Here] is the inverse
+operation, it scrolls backward, moving current the top line underneath the
+mouse.
+
+If the mouse is near the left edge of a window, then these commands do smooth
+scrolling.  @hid[Here To Top of Window] repeatedly scrolls the window up by one
+line until the mouse button is released.  Similarly, @hid[Top Line to Here]
+smoothly scrolls down.
+@enddefcom
+
+@defcom[com "Point to Here", bind (Middledown, S-Leftdown)]
+This command moves the point to the position of the mouse, changing to a
+different window if necessary.
+
+When used in a window's modeline, this moves the point of the window's buffer
+to the position within the file that is the same percentage, start to end, as
+the horizontal position of the mouse within the modeline.  This also makes this
+window current if necessary.
+
+This command supplies a function @hid[Generic Pointer Up] invokes if it runs
+without any intervening generic pointer up predecessors executing.  If the
+position of the pointer is different than the current point when the user
+invokes @hid[Generic Pointer Up], then this function pushes a buffer mark at
+point and moves point to the pointer's position.  This allows the user to mark
+off a region with the mouse.
+@enddefcom
+
+@defcom[com "Generic Pointer Up", bind (Middleup, S-Leftup)]
+Other commands determine this command's action by supplying functions that
+this command invokes.  The following built-in commands supply the following
+generic up actions:
+@Begin[Description]
+@hid[Point to Here]@\
+ When the position of the pointer is different than the current point, the
+action pushes a buffer mark at point and moves point to the pointer's position.
+
+@hid[Bufed Goto and Quit]@\
+ The action is a no-op.
+@End[Description]
+@enddefcom
+
+@defcom[com "Insert Kill Buffer", bind (S-Rightdown)]
+This command is a combination of @hid[Point to Here] and @comref[Un-Kill].  It
+moves the point to the mouse location and inserts the most recently killed
+text.
+@enddefcom
+
+
+@section[Modification Commands]
+@index[commands, modification]
+
+There is a wide variety of basic text-modification commands, but once again the
+simplest ones are the most often used.
+
+@subsection[Inserting Characters]
+@index[character, insertion]
+@index[insertion, character]
+
+In @hemlock, you can insert characters with graphic representations by typing
+the corresponding key-event which you normally generate with the obvious
+keyboard key.  You can only insert characters whose codes correspond to ASCII
+codes.  To insert those without graphic representations, use @hid[Quoted
+Insert].
+
+@defcom[com "Self Insert"]
+@hid[Self Insert] inserts into the buffer the character corresponding to the
+key-event typed to invoke the command.  This command is normally bound to all
+such key-events @binding[Space].  If a prefix argument is supplied, then this
+inserts the character that many times.
+@enddefcom
+
+@defcom[com "New Line", bind (Return)]
+This command, which has roughly the same effect as inserting a @bf[Newline],
+is used to move onto a new blank line.  If there are at least two blank
+lines beneath the current one then @binding[Return] cleans off any
+whitespace on the next line and uses it, instead of inserting a newline.
+This behavior is desirable when inserting in the middle of text, because
+the bottom half of the screen does not scroll down each time @hid[New Line]
+is used.
+@enddefcom
+
+@defcom[com "Quoted Insert", bind {C-q}]
+Many key-events have corresponding ASCII characters, but these key-events are
+bound to commands other than @hid[Self Insert].  Sometimes they are otherwise
+encumbered such as with @binding[C-g].  @hid[Quoted Insert] prompts for a
+key-event, without any command interpretation semantics, and inserts the
+corresponding character.  If the appropriate character has some code other than
+an ASCII code, this will beep and abort the command.  A common use for this
+command is inserting a @bf[Formfeed] by typing @binding[C-q C-l].  If a prefix
+argument is supplied, then the character is inserted that many times.
+@enddefcom
+
+@defcom[com "Open Line", bind {C-o}]
+This command inserts a newline into the buffer without moving the point.
+This command may also be given a prefix argument to insert a number of
+newlines, thus opening up some room to work in the middle of a screen of
+text.  See also @comref[Delete Blank Lines].
+@enddefcom
+
+
+@subsection[Deleting Characters]
+@index[deletion, character]
+@index[character, deletion]
+There are a number of commands for deleting characters as well.
+
+@defhvar[var "Character Deletion Threshold", val {5}]
+If more than this many characters are deleted by a character deletion command,
+then the deleted text is placed in the kill ring.
+@enddefhvar
+
+@defcom[com "Delete Next Character", bind {C-d}]
+@defcom1[com "Delete Previous Character", bind (Delete, Backspace)]
+@hid[Delete Next Character] deletes the character immediately following the
+point, that is, the character which appears under the cursor.  When given a
+prefix argument, @binding[C-d] deletes that many characters after the
+point.  @hid[Delete Previous Character] is identical, except that it
+deletes characters before the point.
+@enddefcom
+
+@defcom[com "Delete Previous Character Expanding Tabs"]
+@hid[Delete Previous Character Expanding Tabs] is identical to
+@hid[Delete Previous Character], except that it treats tabs as the
+equivalent number of spaces.  Various language modes that use tabs for
+indentation bind @binding[Delete] to this command.
+@enddefcom
+
+
+@subsection[Killing and Deleting]
+
+@index[killing]@index[cutting]@index[pasting]@index[kill ring]@hemlock has many
+commands which kill text.  Killing is a variety of deletion which saves the
+deleted text for later retrieval.  The killed text is saved in a ring buffer
+known as the @i[kill ring].  Killing has two main advantages over deletion:
+@begin[enumerate]
+If text is accidentally killed, a not uncommon occurrence, then it can be
+restored.
+
+Text can be moved from one place to another by killing it and then
+restoring it in the new location.
+@end[enumerate]
+
+Killing is not the same as deleting.  When a command is said to delete
+text, the text is permanently gone and is not pushed on the kill ring.
+Commands which delete text generally only delete things of little
+importance, such as single characters or whitespace.
+
+@subsection[Kill Ring Manipulation]
+@defcom[com "Un-Kill", bind {C-y}]
+@index[kill ring, manipulation]This command "yanks" back the most
+recently killed piece of text, leaving the mark before the inserted text
+and the point after.  If a prefix argument is supplied, then the text that
+distance back in the kill ring is yanked.
+@enddefcom
+
+@defcom[com "Rotate Kill Ring", bind {M-y}]
+This command rotates the kill ring forward, replacing the most recently
+yanked text with the next most recent text in the kill ring. @binding[M-y]
+may only be used immediately after a use of @binding[C-y] or a previous
+use of @binding[M-y].  This command is used to step back through the text
+in the kill ring if the desired text was not the most recently killed, and
+thus could not be retrieved directly with a @binding[C-y].  If a prefix
+argument is supplied, then the kill ring is rotated that many times.
+@enddefcom
+
+@defcom[com "Kill Region", bind {C-w}]
+@index[region, killing]This command kills the text between the point and
+mark, pushing it onto the kill ring.  This command is usually the best way
+to move or remove large quantities of text.
+@enddefcom
+
+@defcom[com "Save Region", bind {M-w}]
+This command pushes the text in the region on the kill ring, but doesn't
+actually kill it, giving an effect similar to typing @binding[C-w C-y].
+This command is useful for duplicating large pieces of text.
+@enddefcom
+
+@subsection[Killing Commands]
+
+@index[commands, killing]Most commands which kill text append into the
+kill ring, meaning that consecutive uses of killing commands will insert
+all text killed into the top entry in the kill ring.  This allows large
+pieces of text to be killed by repeatedly using a killing command.
+
+@defcom[com "Kill Line", bind {C-k}]
+@defcom1[com "Backward Kill Line"]
+@index[line, killing]@hid[Kill Line] kills the text from the point to the
+end of the current line, deleting the line if it is empty.  If a prefix
+argument is supplied, then that many lines are killed.  Note that a prefix
+argument is not the same as a repeat count.
+
+@hid[Backward Kill Line] is similar, except that it kills from the point to the
+beginning of the line.  If it is called at the beginning of the line, it kills
+the newline and any trailing whitespace on the previous line.  With a prefix
+argument, this command is the same as @hid[Kill Line] with a negated argument.
+@enddefcom
+
+@defcom[com "Kill Next Word", bind {M-d}]
+@defcom1[com "Kill Previous Word", bind (M-Backspace, M-Delete)]
+@index[word, killing]@hid[Kill Next Word] kills from the point to the end
+of the current or next word.  If a prefix argument is supplied, then that
+many words are killed.  @hid[Kill Previous Word] is identical, except that
+it kills backward.
+@enddefcom
+
+@subsection[Case Modification Commands]
+
+@index[case modification]@hemlock provides a few case modification
+commands, which are often useful for correcting typos.
+
+@defcom[com "Capitalize Word", bind {M-c}]
+@defcom1[com "Lowercase Word", bind {M-l}]
+@defcom1[com "Uppercase Word", bind {M-u}]
+@index[word, case modification]These commands modify the case of the
+characters from the point to the end of the current or next word, leaving
+the point after the end of the word affected.  A positive prefix argument
+modifies that many words, moving forward.  A negative prefix argument
+modifies that many words before the point, but leaves the point unmoved.
+@enddefcom
+
+@defcom[com "Lowercase Region", bind (C-x C-l)]
+@defcom1[com "Uppercase Region", bind (C-x C-u)]
+@index[region, case modification]These commands case-fold the text in the
+region.  Since these commands can damage large amounts of text, they ask for
+confirmation before modifying large regions and can be undone with @hid[Undo].
+@enddefcom
+
+@subsection[Transposition Commands]
+
+@index[transposition]@index[commands, transposition]@hemlock provides a
+number of transposition commands.  A transposition command swaps the
+"things" before and after the point and moves forward one "thing".  Just
+how a "thing" is defined depends on the particular transposition command.
+Transposition commands, particularly
+@hid[Transpose Characters] and @hid[Transpose Words], are useful for
+correcting typos.  More obscure transposition commands can be used to amaze
+your friends and demonstrate your immense knowledge of exotic @emacs
+commands.
+
+To the uninitiated, the behavior of transposition commands may seem mysterious;
+this has led some implementors to attempt to improve the definition of
+transposition, but right-thinking people will accept no substitutes.  The
+@emacs transposition definition used in @hemlock has two useful properties:
+@begin[enumerate]
+Repeated applications of a transposition command have a useful effect.  The
+way to visualize this effect is that each use of the transposition command
+drags the previous thing over the next thing.  It is possible to correct
+double transpositions easily using @hid[Transpose Characters].
+
+Transposition commands move backward with a negative prefix argument, thus
+undoing the effect of the equivalent positive argument.
+@end[enumerate]
+
+@defcom[com "Transpose Characters", bind {C-t}]
+@index[character, transposition]This command exchanges the characters on
+either side of the point and moves forward, unless at the end of a line, in
+which case it transposes the previous two characters without moving.
+@enddefcom
+
+@defcom[com "Transpose Lines", bind (C-x C-t)]
+@index[line, transposition]This command transposes the previous and
+current line, moving down to the next line.  With a zero argument, it
+transposes the current line and the line the mark is on.
+@enddefcom
+
+@defcom[com "Transpose Words", bind {M-t}]
+@index[word, transposition]This command transposes the previous word and
+the current or next word.
+@enddefcom
+
+
+@defcom[com "Transpose Regions", bind (C-x t)]
+This command transposes two regions with endpoints defined by the mark stack
+and point.  To use this command, place three marks (in order) at the start and
+end of the first region, and at the start of the second region, then place the
+point at the end of the second region.  Unlike the other transposition
+commands, a second use will simply undo the effect of the first use, and to do
+even this, you must reactivate the current region.
+@enddefcom
+
+
+@subsection[Whitespace Manipulation]
+These commands change the amount of space between words.  See also the
+indentation commands in section @ref[indentation].
+
+@defcom[com "Just One Space", bind (M-|)]
+@index[whitespace, manipulation]@index[indentation, manipulation]This
+command deletes all whitespace characters before and after the point and then
+inserts one space.  If a prefix argument is supplied, then that number of
+spaces is inserted.
+@enddefcom
+
+@defcom[com "Delete Horizontal Space", bind (M-\)]
+This command deletes all blank characters around the point.
+@enddefcom
+
+@defcom[com "Delete Blank Lines", bind (C-x C-o)]
+This command deletes all blank lines surrounding the current line, leaving the
+point on a single blank line.  If the point is already on a single blank line,
+then that line is deleted.  If the point is on a non-blank line, then all blank
+lines immediately following that line are deleted.  This command is often used
+to clean up after @comref[Open Line].
+@enddefcom
+
+@section[Filtering]
+
+@i[Filtering] is a simple way to perform a fairly arbitrary transformation
+on text.  Filtering text replaces the string in each line with the result
+of applying a @llisp function of one argument to that string.  The function must 
+neither destructively modify the argument nor the return value.  It is an
+error for the function to return a string containing newline characters.
+
+@defcom[com "Filter Region"]
+This function prompts for an expression which is evaluated to obtain a
+function to be used to filter the text in the region.  For example, to
+capitalize all the words in the region one could respond:
+@begin[programexample]
+Function: #'@comment<>string-capitalize
+@end[programexample]
+Since the function may be called many times, it should probably be
+compiled.  Functions for one-time use can be compiled using the compile
+function as in the following example which removes all the semicolons on any line
+which contains the string "@f[PASCAL]":
+@begin[programexample]
+Function: (compile nil '(lambda (s)
+			  (if (search "PASCAL" s)
+			      (remove #\; s)
+			      s)))
+@end[programexample]
+@enddefcom
+
+@section[Searching and Replacing]
+@index[searching]@index[replacing]
+Searching for some string known to appear in the text is a commonly used method
+of moving long distances in a file.  Replacing occurrences of one pattern with
+another is a useful way to make many simple changes to text.  @hemlock provides
+powerful commands for doing both of these operations.
+
+@defhvar[var "String Search Ignore Case", val {t}]
+@index[case sensitivity]
+This variable determines the kind of search done by searching and replacing
+commands.  
+@enddefhvar
+
+@defcom[com "Incremental Search", bind {C-s}]
+@defcom1[com "Reverse Incremental Search", bind {C-r}]
+@hid[Incremental Search] searches for an occurrence of a string after the
+current point.  It is known as an incremental search because it reads
+key-events form the keyboard one at a time and immediately searches for the
+pattern of corresponding characters as you type.  This is useful because
+it is possible to initially type in a very short pattern and then add more
+characters if it turns out that this pattern has too many spurious matches.
+
+This command dispatches on the following key-events as sub-commands:
+@begin[description]
+@binding[C-s]@\
+ Search forward for an occurrence of the current pattern.  This can be used
+repeatedly to skip from one occurrence of the pattern to the next, or it can be
+used to change the direction of the search if it is currently a reverse search.
+If @binding[C-s] is typed when the search string is empty, then a search is
+done for the string that was used by the last searching command.
+
+@binding[C-r]@\
+ Similar to @binding[C-s], except that it searches backwards.
+
+@binding[Delete, Backspace]@\
+ Undoes the effect of the last key-event typed.  If that key-event simply added
+to the search pattern, then this removes the character from the pattern, moving
+back to the last match found before entering the removed character.  If the
+character was a @binding[C-s] or @binding[C-r], then this moves back to the
+previous match and possibly reverses the search direction.
+
+@binding[C-g]@\
+ If the search is currently failing, meaning that there is no occurrence of the
+search pattern in the direction of search, then @binding[C-g] deletes enough
+characters off the end of the pattern to make it successful.  If the search
+is currently successful, then @binding[C-g] causes the search to be aborted,
+leaving the point where it was when the search started.  Aborting the search
+inhibits the saving of the current search pattern as the last search string.
+
+@binding[Escape]@\
+ Exit at the current position in the text, unless the search string is empty,
+in which case a non-incremental string search is entered.
+
+@binding[C-q]@\
+ Search for the character corresponding to the next key-event, rather than
+treating it as a command.
+@end[description]
+Any key-event not corresponding to a graphic character, except those just
+described, causes the search to exit.  @hemlock then uses the key-event in it
+normal command interpretation.
+
+For example, typing @binding[C-a] will exit the search @i[and] go to the
+beginning of the current line.  When either of these commands successfully
+exits, they push the starting position (before the search) on the mark stack.
+If the current region was active when the search started, this foregoes pushing
+a mark.
+@enddefcom
+
+@defcom[com "Forward Search", bind (M-s)]
+@defcom1[com "Reverse Search", bind (M-r)]
+These commands do a normal dumb string search, prompting for the search
+string in a normal dumb fashion.  One reason for using a non-incremental
+search is that it may be faster since it is possible to specify a long
+search string from the very start.  Since @hemlock uses the Boyer--Moore
+search algorithm, the speed of the search increases with the size of the
+search string.
+When either of these commands successfully exits, they push the starting
+position (before the search) on the mark stack.  This is inhibited when the
+current region is active.
+@enddefcom
+
+@defcom[com "Query Replace", bind (M-%)]
+This command prompts in the echo area for a target string and a replacement
+string.  It then searches for an occurrence of the target after the point.
+When it finds a match, it prompts for a key-event indicating what action to
+take.  The following are valid responses:
+@begin[description]
+@binding[Space, y]@\
+ Replace this occurrence of the target with the replacement string, and search
+again.
+
+@binding[Delete, Backspace, n]@\
+ Do not replace this occurrence, but continue the search.
+
+@binding[!]@\
+ Replace this and all remaining occurrences without prompting again.
+
+@binding[.]@\
+ Replace this occurrence and exit.
+
+@binding[C-r]@\
+ Go into a recursive edit (see page @pageref[recursive-edits]) at the current
+location.  The search will be continued from wherever the point is left when
+the recursive edit is exited.  This is useful for handling more complicated
+cases where a simple replacement will not achieve the desired effect.
+
+@binding[Escape]@\
+ Exit without doing any replacement.
+
+@binding[Home, C-_, ?, h]@\
+ Print a list of all the options available.
+@end[description]
+Any other key-event causes the command to exit, returning the key-event to the
+input stream; thus, @hemlock will interpret it normally for a command binding.
+
+When the current region is active, this command uses it instead of the region
+from point to the end of the buffer.  This is especially useful when you expect
+to use the @binding[!] option.
+
+If the replacement string is all lowercase, then a heuristic is used that
+attempts to make the case of the replacement the same as that of the
+particular occurrence of the target pattern.  If "@f[foo]" is being
+replaced with "@f[bar]" then "@f[Foo]" is replaced with "@f[Bar]" and
+"@f[FOO]" with "@f[BAR]".
+
+This command may be undone with @hid[Undo], but its undoing may not be undone.
+On a successful exit from this command, the starting position (before the
+search) is pushed on the mark stack.
+@enddefcom
+
+@defhvar[var "Case Replace", val {t}]
+@index[case sensitivity]
+If this variable is true then the case preserving heuristic in
+@hid[Query Replace] is enabled, otherwise all replacements are done with
+the replacement string exactly as specified.
+@enddefhvar
+
+@defcom[com "Replace String"]
+This command is the same as @hid[Query Replace] except it operates without ever
+querying the user before making replacements.  After prompting for a target and
+replacement string, it replaces all occurrences of the target string following
+the point.  If a prefix argument is specified, then only that many occurrences
+are replaced.  When the current region is active, this command uses it instead
+of the region from point to the end of the buffer.
+@enddefcom
+
+@defcom[com "List Matching Lines"]
+This command prompts for a search string and displays in a pop-up window all
+the lines containing the string that are after the point.  If a prefix argument
+is specified, then this displays that many lines before and after each matching
+line.  When the current region is active, this command uses it instead of the
+region from point to the end of the buffer.
+@enddefcom
+
+@defcom[com "Delete Matching Lines"]
+@defcom1[com "Delete Non-Matching Lines"]
+@hid[Delete Matching Lines] prompts for a search string and deletes all lines
+containing the string that are after the point.  Similarly, @hid[Delete
+Non-Matching Lines] deletes all lines following the point that do not contain
+the specified string.  When the current region is active, these commands uses
+it instead of the region from point to the end of the buffer.
+@enddefcom
+
+
+@section[Page Commands]
+@index[page commands]
+Another unit of text recognized by @hemlock is the page.  A @i[page] is a piece
+of text delimited by formfeeds (@f[^L]'s.)  The first non-blank line after the
+page marker is the @i[page title].  The page commands are quite useful when
+logically distinct parts of a file are put on separate pages.  See also
+@comref[Count Lines Page].  These commands only recognize @f[^L]'s at the
+beginning of a lines, so those quoted in string literals do not get in the way.
+
+@defcom[com "Previous Page", bind (C-x @bf<]>)]
+@defcom1[com "Next Page", bind (C-x [)]
+@hid[Previous Page] moves the point to the previous page delimiter, while
+@hid[Next Page] moves to the next one.  Any page delimiters next to the point
+are skipped.  The prefix argument is a repeat count.
+@enddefcom
+
+@defcom[com "Mark Page", bind (C-x C-p)]
+This command puts the point at the beginning of the current page and the mark
+at the end.  If given a prefix argument, marks the page that many pages from the
+current one.
+@enddefcom
+
+@defcom[com "Goto Page"]
+This command does various things, depending on the prefix argument:
+@begin[description]
+@i[no argument]@\goes to the next page.
+
+@i[positive argument]@\goes to an absolute page number, moving that many pages
+from the beginning of the file.
+
+@i[zero argument]@\prompts for string and goes to the page with that string in
+its title.  Repeated invocations in this manner continue searching from the
+point of the last find, and a first search with a particular pattern pushes a
+buffer mark.
+
+@i[negative argument]@\moves backward by that many pages, if possible.
+@end[description]
+@enddefcom
+
+@defcom[com "View Page Directory"]
+@defcom1[com "Insert Page Directory"]
+@hid[View Page Directory] uses a pop-up window to display the number and title
+of each page in the current buffer.  @hid[Insert Page Directory] is the same
+except that it inserts the text at the beginning of the buffer.  With a prefix
+argument, @hid[Insert Page Directory] inserts at the point.
+@enddefcom
+
+
+@section[Counting Commands]
+
+@defcom[com "Count Words"]
+This command counts the number of words from the current point to the end of
+the buffer, displaying a message in the echo area.  When the current region is
+active, this uses it instead of the region from the point to the end of the
+buffer.  Word delimiters are determined by the current major mode.
+@enddefcom
+
+@defcom[com "Count Lines"]
+This command counts the number of lines from the current point to the end of
+the buffer, displaying a message in the echo area.  When the current region is
+active, this uses it instead of the region from the point to the end of the
+buffer.  
+@enddefcom
+
+@defcom[com "Count Lines Page", bind (C-x l)]
+This command displays the number of lines in the current page and the number of
+lines before and after the point within that page.  If given a prefix argument,
+the entire buffer is counted instead of just the current page.
+@enddefcom
+
+@defcom[com "Count Occurrences"]
+This command prompts for a search string and displays the number of occurrences
+of that string in the text from the point to the end of the buffer.  When the
+current region is active, this uses it instead of the region from the point to
+the end of the buffer.
+@enddefcom
+
+
+@section[Registers]
+@index[registers]
+Registers allow you to save a text position or chunk of text associated with a
+key-event.  This is a convenient way to repeatedly access a commonly-used
+location or text fragment.  The concept and key bindings should be familiar to
+TECO users.
+
+@defcom[com "Save Position", bind (C-x s)]
+@defcom1[com "Jump to Saved Position", bind (C-x j)]
+These commands manipulate registers containing textual positions.  
+@hid[Save Position] prompts for a register and saves the location of the
+current point in that register.  @hid[Jump to Saved Position] prompts for a
+register and moves the point to the position saved in that register.  If the
+saved position is in a different buffer, then that buffer is made current.
+@enddefcom
+
+@defcom[com "Put Register", bind (C-x x)]
+@defcom1[com "Get Register", bind (C-x g)]
+These commands manipulate registers containing text.  @hid[Put Register]
+prompts for a register and puts the text in the current region into the
+register.  @hid[Get Register] prompts for a register and inserts the text in
+that register at the current point.
+@enddefcom
+
+@defcom[com "List Registers"]
+@defcom1[com "Kill Register"]
+@hid[List Registers] displays a list of all the currently defined registers in
+a pop-up window, along with a brief description of their contents.  
+@hid[Kill Register] prompts for the name of a register and deletes that
+register.
+@enddefcom
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/intro.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/intro.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/intro.mss	(revision 13309)
@@ -0,0 +1,1127 @@
+@comment{-*- Dictionary: target:scribe/hem/hem; Mode: spell; Package: Hemlock -*-}
+@chap[Introduction]
+
+@hemlock is a text editor which follows in the tradition of @emacs
+and the Lisp Machine editor ZWEI.  In its basic form, @hemlock has almost
+the same command set as ITS/TOPS-20 @emacs@foot[In this document, "Emacs"
+refers to this, the original version, rather than to any of the large
+numbers of text editors inspired by it which may go by the same name.],
+and similar features such as multiple windows and extended commands, as
+well as built in documentation features.  The reader should bear in mind
+that whenever some powerful feature of @hemlock is described, it has
+probably been directly inspired by @emacs.
+
+This manual describes @hemlock@comment{}'s commands and other user visible
+features and then goes on to tell how to make simple customizations.  For
+complete documentation of the @hemlock primitives with which commands are
+written, the @i[Hemlock Command Implementor's Manual] is also available.
+
+
+
+@section[The Point and The Cursor]
+
+@index[point]
+@index[cursor]
+The @i[point] is the current focus of editing activity.  Text typed in by the
+user is inserted at the point.  Nearly all commands use the point as a
+indication of what text to examine or modify.  Textual positions in @hemlock
+are between characters.  This may seem a bit curious at first, but it is
+necessary since text must be inserted between characters.  Although the point
+points between characters, it is sometimes said to point @i[at] a character, in
+which case the character after the point is referred to.
+
+The @i[cursor] is the visible indication of the current focus of attention: a
+rectangular blotch under @windows, or the hardware cursor on a terminal.  The
+cursor is usually displayed on the character which is immediately after the
+point, but it may be displayed in other places.  Wherever the cursor is
+displayed it indicates the current focus of attention.  When input is being
+prompted for in the echo area, the cursor is displayed where the input is to
+go.  Under @windows the cursor is only displayed when @hemlock is waiting
+for input.
+
+
+@section[Notation]
+
+There are a number of notational conventions used in this manual which need
+some explanation.
+
+
+@subsection[Key-events]
+
+@label[key-events]
+@index[key-events, notation]
+@index[bits, key-event]
+@index[modifiers, key-event]
+The canonical representation of editor input is a @i[key-event].  When you type
+on the keyboard, @hemlock receives key-events.  Key-events have names for their
+basic form, and we refer to this name as a @i[keysym].  This manual displays
+keysyms in a @bf[Bold] font.  For example, @bf[a] and @bf[b] are the keys that
+normally cause the editor to insert the characters @i[a] and @i[b].
+
+Key-events have @i[modifiers] or @i[bits] indicating a special interpretation
+of the root key-event.  Although the keyboard places limitations on what
+key-events you can actually type, @hemlock understands arbitrary combinations
+of the following modifiers: @i[Control], @i[Meta], @i[Super], @i[Hyper],
+@i[Shift], and @i[Lock].  This manual represents the bits in a key-event by
+prefixing the keysym with combinations of @bf[C-], @bf[M-], @bf[S-], @bf[H-],
+@bf[Shift-], and @bf[Lock].  For example, @bf[a] with both the control and meta
+bits set appears as @bf[C-M-a].  In general, ignore the shift and lock
+modifiers since this manual never talks about keysyms that explicitly have
+these bits set; that is, it may talk about the key-event @bf[A], but it would
+never mention @bf[Shift-a].  These are actually distinct key-events, but
+typical input coercion turns presents @hemlock with the former, not the latter.
+
+Key-event modifiers are totally independent of the keysym.  This may be new to
+you if you are used to thinking in terms of ASCII character codes.  For
+example, with key-events you can distinctly identify both uppercase and
+lowercase keysyms with the control bit set; therefore, @bf[C-a] and @bf[C-A]
+may have different meanings to @hemlock.
+
+Some keysyms' names consist of more than a single character, and these usually
+correspond to the legend on the keyboard.  For example, some keyboards let you
+enter @bf[Home], @bf[Return], @bf[F9], etc.
+
+In addition to a keyboard, you may have a mouse or pointer device.  Key-events
+also represent this kind of input.  For example, the down and up transitions of
+the @i[left button] correspond to the @bf[Leftdown] and @bf[Leftup] keysyms.
+
+See sections @ref[key-bindings], @ref[using-x], @ref[using-terminals]
+
+
+@subsection[Commands]
+
+@index[commands]@label[commands]Nearly everything that can be done in
+@hemlock is done using a command.  Since there are many things worth
+doing, @hemlock provides many commands, currently nearly two hundred.
+Most of this manual is a description of what commands exist, how they are
+invoked, and what they do.  This is the format of a command's
+documentation:
+
+@defcom[com "Sample Command", bind (C-M-q, C-`)]
+@begin[quotation, facecode i, leftmargin 8ems, rightmargin 3.5ems,
+below 0.8 lines]
+This command's name is @hid[Sample Command], and it is bound to
+@w(@bf(C-M-q)) and @bf[C-`], meaning that typing either of these will
+invoke it.  After this header comes a description of what the command does:
+@end[quotation]
+
+This command replaces all occurrences following the point of the string
+"@f[Pascal]" with the string "@f[Lisp]".  If a prefix argument is supplied,
+then it is interpreted as the maximum number of occurrences to replace.  If
+the prefix argument is negative then the replacements are done backwards
+from the point.
+@comment<
+@begin[quotation, facecode i, leftmargin 8ems, rightmargin 3.5ems,
+above 0.8 lines, below 0.8 lines]
+Toward the end of the description there may be information primarily of
+interest to customizers and command implementors.  If you don't understand
+this information, don't worry, the writer probably forgot to speak English.
+@end[quotation]
+
+@b[Arguments:]
+@begin[description]
+@i[target]@\The string to replace with "@f[Lisp]".
+
+@i[buffer]@\The buffer to do the replacement in.  If this is @f[:all] then
+the replacement is done in all buffers.
+@end[description]>
+@enddefcom
+
+
+@subsection[Hemlock Variables]
+
+@index[variables, hemlock]@hemlock variables supply a simple
+customization mechanism by permitting commands to be parameterized.  For
+details see page @pageref[vars].
+
+@defhvar[var "Sample Variable", val {36}]
+@begin[quotation, facecode i, leftmargin 8ems, below 0.8 lines]
+The name of this variable is @hid[Sample Variable] and its initial value is
+36.
+@end[quotation]
+this variable sets a lower limit on the number of replacements that be done
+by @hid[Sample Command].  If the prefix argument is supplied, and smaller
+in absolute value than @hid[Sample Variable], then the user is prompted as
+to whether that small a number of occurrences should be replaced, so as to
+avoid a possibly disastrous error.
+@enddefhvar
+
+
+@section[Invoking Commands]
+@index[invocation, command]
+In order to get a command to do its thing, it must be invoked.  The user can do
+this two ways, by typing the @i[key] to which the command is @i[bound] or by
+using an @i[extended command].  Commonly used commands are invoked via their
+key bindings since they are faster to type, while less used commands are
+invoked as extended commands since they are easier to remember.
+
+
+@subsection[Key Bindings]
+@index[bindings, key]
+@index[key bindings]
+@label[key-bindings]
+A key is a sequence of key-events (see section @ref[key-events]) typed on the
+keyboard, usually only one or two in length.  Sections @ref[using-x] and
+@ref[using-terminals] contain information on particular input devices.
+
+When a command is bound to a key, typing the key causes @hemlock to invoke the
+command.  When the command completes its job, @hemlock returns to reading
+another key, and this continually repeats.
+
+Some commands read key-events interpreting them however each command desires.
+When commands do this, key bindings have no effect, but you can usually abort
+@hemlock whenever it is waiting for input by typing @binding[C-g] (see section
+@ref[aborting]).  You can usually find out what options are available by typing
+@binding[C-_] or @binding[Home] (see section @ref[help]).
+
+The user can easily rebind keys to different commands, bind new keys to
+commands, or establish bindings for commands never bound before (see section
+@ref[binding-keys]).
+
+In addition to the key bindings explicitly listed with each command, there are
+some implicit bindings created by using key translations@foot[Key translations
+are documented in the @i[Hemlock Command Implementor's Manual].].  These
+bindings are not displayed by documentation commands such as @hid[Where Is].
+By default, there are only a few key translations.  The modifier-prefix
+characters @bf[C-^], @bf[Escape], @bf[C-z], or @bf[C-c] may be used when typing
+keys to convert the following key-event to a control, meta, control-meta, or
+hyper key-event.  For example, @bf[C-x Escape b] invokes the same commands as
+@bf[C-x M-b], and @bf[C-z u] is the same as @bf[C-M-u].  This allows user to
+type more interesting keys on limited keyboards that lack control, meta, and
+hyper keys.
+@index[bit-prefix key-events]
+
+
+@defhvar[var "Key Echo Delay", val {1.0}]
+A key binding may be composed of several key-events, especially when you enter
+it using modifier-prefix key-events.  @hemlock provides feedback for partially
+entered keys by displaying the typed key-events in the echo area.  In order to
+avoid excessive output and clearing of the echo area, this display is delayed
+by @hid[Key Echo Delay] seconds.  If this variable is set to @nil, then
+@hemlock foregoes displaying initial subsequences of keys.
+@enddefhvar
+
+
+@subsection[Extended Commands]
+
+@index[commands, extended]A command is invoked as an extended command by
+typing its name to the @hid[Extended Command] command, which is invoked
+using its key binding, @binding[M-x].
+
+@defcom[com "Extended Command", bind {M-x}]
+This command prompts in the echo area for the name of a command, and then
+invokes that command.  The prefix argument is passed through to the command
+invoked.  The command name need not be typed out in full, as long as enough
+of its name is supplied to uniquely identify it.  Completion is available
+using @binding[Escape] and @binding[Space], and a list of possible completions
+is given by @binding[Home] or @binding[C-_].
+@enddefcom
+
+
+@section[The Prefix Argument]
+
+@index[prefix argument]The prefix argument is an integer argument which
+may be supplied to a command.  It is known as the prefix argument because
+it is specified by invoking some prefix argument setting command
+immediately before the command to be given the argument.  The following
+statements about the interpretation of the prefix argument are true:
+@begin[itemize]
+When it is meaningful, most commands interpret the prefix argument as a
+repeat count, causing the same effect as invoking the command that many
+times.
+
+When it is meaningful, most commands that use the prefix argument interpret
+a negative prefix argument as meaning the same thing as a positive
+argument, but the action is done in the opposite direction.
+
+Most commands treat the absence of a prefix argument as meaning the same
+thing as a prefix argument of one.
+
+Many commands ignore the prefix argument entirely.
+
+Some commands do none of the above.
+@end[itemize]
+The following commands are used to set the prefix argument:
+
+@defcom[com "Argument Digit", stuff (bound to all control or meta digits)]
+Typing a number using this command sets the prefix argument to that number,
+for example, typing @binding[M-1 M-2] sets the prefix argument to twelve.
+@enddefcom
+
+@defcom[com "Negative Argument", bind {M--}]
+This command negates the prefix argument, or if there is none, sets it to
+negative one.  For example, typing @binding[M-- M-7] sets the prefix
+argument to negative seven.
+@enddefcom
+
+@defcom[com "Universal Argument", bind {C-u}]
+@defhvar1[var "Universal Argument Default", val {4}]
+This command sets the prefix argument or multiplies it by four.  If digits
+are typed immediately afterward, they are echoed in the echo area, and the
+prefix argument is set to the specified number.  If no digits are typed
+then the prefix argument is multiplied by four.  @binding[C-u - 7] sets the
+prefix argument to negative seven.  @binding[C-u C-u] sets the prefix
+argument to sixteen.  @binding[M-4 M-2 C-u] sets the prefix argument to one
+hundred and sixty-eight.  @binding[C-u M-0] sets the prefix argument to
+forty.
+
+@hid[Universal Argument Default] determines the default value and multiplier
+for the @hid[Universal Argument] command.
+@enddefcom
+
+
+@section[Modes]
+
+@label[modes]@index[modes]A mode provides a way to change @hemlock@comment{}'s
+behavior by specifying a modification to current key bindings, values of
+variables, and other things.  Modes are typically used to adjust @hemlock
+to suit a particular editing task, e.g. @hid[Lisp] mode is used for editing
+@llisp code.
+
+Modes in @hemlock are not like modes in most text editors; @hemlock is really a
+"modeless" editor.  There are two ways that the @hemlock mode concept differs
+from the conventional one:
+@begin[enumerate]
+Modes do not usually alter the environment in a very big way, i.e. replace
+the set of commands bound with another totally disjoint one.  When a mode
+redefines what a key does, it is usually redefined to have a slightly
+different meaning, rather than a totally different one.  For this reason,
+typing a given key does pretty much the same thing no matter what modes are
+in effect.  This property is the distinguishing characteristic of a
+modeless editor.
+
+Once the modes appropriate for editing a given file have been chosen, they
+are seldom, if ever, changed.  One of the advantages of modeless editors is
+that time is not wasted changing modes.
+@end[enumerate]
+
+@index[major mode]A @i[major mode] is used to make some big change in the
+editing environment.  Language modes such as @hid[Pascal] mode are major
+modes.  A major mode is usually turned on by invoking the command
+@i{mode-name}@hid[ Mode] as an extended command.  There is only one major
+mode present at a time.  Turning on a major mode turns off the one that is
+currently in effect.
+
+@index[minor mode]A @i[minor mode] is used to make a small change in the
+environment, such as automatically breaking lines if they get too long.
+Unlike major modes, any number of minor modes may be present at once.
+Ideally minor modes should do the "right thing" no matter what major and
+minor modes are in effect, but this is may not be the case when key
+bindings conflict.
+
+Modes can be envisioned as switches, the major mode corresponding to one big
+switch which is thrown into the correct position for the type of editing being
+done, and each minor mode corresponding to an on-off switch which controls
+whether a certain characteristic is present.
+
+@defcom[com "Fundamental Mode"]
+This command puts the current buffer into @hid[Fundamental] mode.
+@hid[Fundamental] mode is the most basic major mode: it's the next best thing
+to no mode at all.
+@enddefcom
+
+
+@section[Display Conventions]
+@index[display conventions]
+There are two ways that @hemlock displays information on the screen; one is
+normal @i[buffer display], in which the text being edited is shown on the
+screen, and the other is a @i[pop-up window].
+
+
+@subsection[Pop-Up Windows]
+@index[pop-up windows]
+@index[random typeout]
+@label[pop-up]
+Some commands print out information that is of little permanent value, and
+these commands use a @i[pop-up] window to display the information.  It is known
+as a @i[pop-up] window because it temporarily appears on the screen overlaying
+text already displayed.  Most commands of this nature can generate their output
+quickly, but in case there is a lot of output, or the user wants to repeatedly
+refer to the same output while editing, @hemlock saves the output in a buffer.
+Different commands may use different buffers to save their output, and we refer
+to these as @i[random typeout] buffers.
+
+If the amount of output exceeds the size of the pop-up window, @Hemlock
+displays the message @w<"@f[--More--]"> after each window full.  The following
+are valid responses to this prompt:
+@Begin[Description]
+@bf[Space], @bf[y]@\
+ Display the next window full of text.
+
+@bf[Delete], @bf[Backspace], @bf[n]@\
+ Abort any further output.
+
+@bf[Escape], @bf[!]@\
+ Remove the window and continue saving any further output in the buffer.
+
+@bf[k]@\
+ This is the same as @bf[!] or @bf[escape], but @hemlock makes a normal window
+over the pop-up window.  This only works on bitmap devices.
+@End[Description]
+Any other input causes the system to abort using the key-event to determine
+the next command to execute.
+
+When the output is complete, @hemlock displays the string @w<"@f[--Flush--]">
+in the pop-up window's modeline, indicating that the user may flush the
+temporary display.  Typing any of the key-events described above removes the
+pop-up window, but typing @bf[k] still produces a window suitable for normal
+editing.  Any other input also flushes the display, but @hemlock uses the
+key-event to determine the next command to invoke.
+
+@defcom[com "Select Random Typeout Buffer", bind {H-t}]
+This command makes the most recently used random typeout buffer the current
+buffer in the current window.
+@enddefcom
+
+Random typeout buffers are always in @hid[Fundamental] mode.
+
+
+@subsection[Buffer Display]
+@index[buffer, display]
+@index[display, buffer]
+
+If a line of text is too long to fit within the screen width it is @i[wrapped],
+with @hemlock displaying consecutive pieces of the text line on as many screen
+lines as needed to hold the text.  @hemlock indicates a wrapped line by placing
+a line-wrap character in the last column of each screen line.  Currently, the
+line-wrap character is an exclamation point (@f[!]).  It is possible for a line
+to wrap off the bottom of the screen or on to the top.
+
+@hemlock wraps screen lines when the line is completely full regardless of the
+line-wrap character.  Most editors insert the line-wrap character and wrap a
+single character when a screen line would be full if the editor had avoided
+wrapping the line.  In this situation, @hemlock would leave the screen line
+full.  This means there are always at least two characters on the next screen
+line if @hemlock wraps a line of display.  When the cursor is at the end of a
+line which is the full width of the screen, it is displayed in the last column,
+since it cannot be displayed off the edge.
+
+@hemlock displays most characters as themselves, but it treats some
+specially:
+@begin[itemize]
+Tabs are treated as tabs, with eight character tab-stops.
+
+Characters corresponding to ASCII control characters are printed as
+@f[^]@i[char]; for example, a formfeed is @f[^L].
+
+Characters with the most-significant bit on are displayed as
+@f[<]@i[hex-code]@f[>]; for example, @f[<E2>].
+@end[itemize]
+Since a character may be displayed using more than one printing character,
+there are some positions on the screen which are in the middle of a character.
+When the cursor is on a character with a multiple-character representation,
+@hemlock always displays the cursor on the first character.
+
+
+@subsection[Recentering Windows]
+@index[recentering windows]
+@index[windows, recentering]
+
+When redisplaying the current window, @hemlock makes sure the current point is
+visible.  This is the behavior you see when you are entering text near the
+bottom of the window, and suddenly redisplay shifts your position to the
+window's center.
+
+Some buffers receive input from streams and other processes, and you might have
+windows displaying these.  However, if those windows are not the current
+window, the output will run off the bottom of the windows, and you won't be
+able to see the output as it appears in the buffers.  You can change to a
+window in which you want to track output and invoke the following command to
+remedy this situation.
+
+@defcom[com "Track Buffer Point"]
+This command makes the current window track the buffer's point.  This means
+that each time Hemlock redisplays, it will make sure the buffer's point is
+visible in the window.  This is useful for windows that are not current and
+that display buffer's that receive output from streams coming from other
+processes.
+@enddefcom
+
+
+@subsection[Modelines]
+@label[modelines]
+@index[modeline]
+A modeline is the line displayed at the bottom of each window where @hemlock
+shows information about the buffer displayed in that window.  Here is a typical
+modeline:
+@begin[programexample]
+Hemlock USER: (Fundamental Fill)  /usr/slisp/hemlock/user.mss
+@end[programexample]
+This tells us that the file associated with this buffer is
+"@f[/usr/slisp/hemlock/user.mss]", and the @hid[Current Package] for Lisp
+interaction commands is the @f["USER"] package.  The modes currently present
+are @hid[Fundamental] and @hid[Fill]; the major mode is always displayed first,
+followed by any minor modes.  If the buffer has no associated file, then the
+buffer name will be present instead:
+@begin[programexample]
+Hemlock PLAY: (Lisp)  Silly:
+@end[programexample]
+In this case, the buffer is named @hid[Silly] and is in @hid[Lisp] mode.  The
+user has set @hid[Current Package] for this buffer to @f["PLAY"].
+
+@defhvar[var "Maximum Modeline Pathname Length", val {nil}]
+This variable controls how much of a pathname @hemlock displays in a modeline.
+Some distributed file systems can have very long pathnames which leads to the
+more particular information in a pathname running off the end of a modeline.
+When set, the system chops off leading directories until the name is less than
+the integer value of this variable.  Three dots, @f[...], indicate a truncated
+name.  The user can establish this variable buffer locally with the
+@hid[Defhvar] command.
+@enddefhvar
+
+If the user has modified the buffer since the last time it was read from or
+save to a file, then the modeline contains an asterisk (@f[*]) between the
+modes list and the file or buffer name:
+@begin[programexample]
+Hemlock USER: (Fundamental Fill)  * /usr/slisp/hemlock/user.mss
+@end[programexample]
+This serves as a reminder that the buffer should be saved eventually.
+
+@index[status line]
+There is a special modeline known as the @i[status line] which appears as the
+@hid[Echo Area]'s modeline.  @Hemlock and user code use this area to display
+general information not particular to a buffer @dash recursive edits, whether
+you just received mail, etc.
+
+
+@section[Use with X Windows]
+@label[using-x]
+@index[X windows, use with]
+You should use @hemlock on a workstation with a bitmap display and a windowing
+system since @hemlock makes good use of a non-ASCII device, mouse, and the
+extra modifier keys typically associated with workstations.  This section
+discusses using @hemlock under X windows, the only supported windowing system.
+
+
+@subsection[Window Groups]
+@index[window management]
+@label[groups]
+@hemlock manages windows under X in groups.  This allows @hemlock to be more
+sophisticated in its window management without being rude in the X paradigm of
+screen usage.  With window groups, @hemlock can ignore where the groups are,
+but within a group, it can maintain the window creation and deletion behavior
+users expect in editors without any interference from window managers.
+
+Initially there are two groups, a main window and the @hid[Echo Area].  If you
+keep a pop-up display, see section @ref[pop-up], @hemlock puts the window it
+creates in its own group.  There are commands for creating new groups.
+
+@hemlock only links windows within a group for purposes of the @hid[Next
+Window], @hid[Previous Window], and @hid[Delete Next Window] commands.  To move
+between groups, you must use the @hid[Point to Here] command bound to the
+mouse.  
+
+Window manager commands can reshape and move groups on the screen.
+
+
+@subsection[Event Translation]
+@index[keyboard use under X]
+@index[translation of keys under X]
+Each X key event is translated into a canonical input representation, a
+key-event.  The X key event consists of a scan-code and modifier bits, and
+these translate to an X keysym.  This keysym and the modifier bits map to a
+key-event.
+
+If you type a key with a shift key held down, this typically maps to a distinct
+X keysym.  For example, the shift of @bf[3] is @bf[#], and these have different
+X keysyms.  Some keys map to the same X keysym regardless of the shift bit,
+such as @bf[Tab], @bf[Space], @bf[Return], etc.  When the X lock bit is on, the
+system treats this as a caps-lock, only mapping keysyms for lowercase letters
+to shifted keysyms.
+
+The key-event has a keysym and a field of bits.  The X keysyms map directly to
+the key-event keysyms.  There is a distinct mapping for each CLX modifier bit
+to a key-event bit.  This tends to eliminate shift and lock modifiers, so
+key-events usually only have control, meta, hyper, and super bits on.  Hyper
+and super usually get turned on with prefix key-events that set them on the
+following key-event, but you can turn certain keys on the keyboard into hyper
+and super keys.  See the X manuals and the @i[Hemlock Command Implementor's
+Manual] for details.
+
+The system also maps mouse input to key-events.  Each mouse button has distinct
+key-event keysyms for whether the user pressed or released it.  For
+convenience, @hemlock makes use of an odd property of converting mouse events
+to key-events.  If you enter a mouse event with the shift key held down,
+@hemlock sees the key-event keysym for the mouse event, but the key-event has
+the super bit turned on.  For example, if you press the left button with the
+shift key pressed, @hemlock sees @bf[S-Leftdown].
+
+Note that with the two button mouse on the IBM RT PC, the only way to to send
+@bf[Middledown] is to press both the left and right buttons simultaneously.
+This is awkward, and it often confuses the X server.  For this reason, the
+commands bound to the middle button are also bound to the shifted left button,
+@bf[S-Leftdown], which is much easier to type.
+
+
+@subsection[Cut Buffer Commands]
+@index[cutting]@index[pasting] These commands allow the X cut buffer to be
+used from @hemlock .  Although @hemlock can cut arbitrarily large regions,
+a bug in the standard version 10 xterm prevents large regions from being
+pasted into an xterm window.
+
+@defcom[com "Region to Cut Buffer", bind {M-Insert}]
+@defcom1[com "Insert Cut Buffer", bind {Insert}]
+These commands manipulate the X cut buffer.  @hid[Region to Cut Buffer] puts
+the text in the region into the cut buffer.  @hid[Insert Cut Buffer] inserts
+the contents of the cut buffer at the point.
+@enddefcom
+
+@subsection[Redisplay and Screen Management]
+
+These variables control a number of the characteristics of @hemlock bitmap
+screen management.
+
+@defhvar[var "Bell Style", val {:border-flash}]
+@defhvar1[var "Beep Border Width", val {20}]
+@hid[Bell Style] determines what beeps do in @hemlock.  Acceptable values are
+@kwd[border-flash], @kwd[feep], @kwd[border-flash-and-feep], @kwd[flash],
+@kwd[flash-and-feep], and @nil (do nothing).
+
+@hid[Beep Border Width] is the width in pixels of the border flashed by border
+flash beep styles.
+@enddefhvar
+
+@defhvar[var "Reverse Video", val {nil}]
+If this variable is true, then @hemlock paints white on black in window
+bodies, black on white in modelines.
+@enddefhvar
+
+@defhvar[var "Thumb Bar Meter", val {t}]
+If this variable is true, then windows will be created to be displayed with a
+ruler in the bottom border of the window.
+@enddefhvar
+
+@defhvar[var "Set Window Autoraise", val {:echo-only}]
+When true, changing the current window will automatically raise the new current
+window.  If the value is @kwd[echo-only], then only the echo area window will
+be raised automatically upon becoming current.
+@enddefhvar
+
+@defhvar[var "Default Initial Window Width", val {80}]
+@defhvar1[var "Default Initial Window Height", val {24}]
+@defhvar1[var "Default Initial Window X"]
+@defhvar1[var "Default Initial Window Y"]
+@defhvar1[var "Default Window Height", val {24}]
+@defhvar1[var "Default Window Width", val {80}]
+@index[window placement]
+@Hemlock uses the variables with "@hid[Initial]" in their names when it first
+starts up to make its first window.  The width and height are specified in
+character units, but the x and y are specified in pixels.  The other variables
+determine the width and height for interactive window creation, such as making
+a window with @comref[New Window].
+@enddefhvar
+
+@defhvar[var "Cursor Bitmap File", val {"library:hemlock.cursor"}]
+This variable determines where the mouse cursor bitmap is read from when
+@hemlock starts up.  The mask is found by merging this name with "@f[.mask]".
+This has to be a full pathname for the C routine.
+@enddefhvar
+
+
+@defhvar[var "Default Font"]
+This variable holds the string name of the font to be used for normal text
+display: buffer text, modelines, random typeout, etc.  The font is loaded at
+initialization time, so this variable must be set before entering @hemlock.
+When @nil, the display type is used to choose a font.
+@enddefhvar
+
+
+@section[Use With Terminals]
+@label[using-terminals]@index[terminals, use with] @hemlock can also be used
+with ASCII terminals and terminal emulators.  Capabilities that depend on
+@windows (such as mouse commands) are not available, but nearly everything else
+can be done.
+
+@subsection[Terminal Initialization]
+
+@index[terminal speed]
+@index[speed, terminal]
+@index[slow terminals]
+@index[incremental redisplay]
+For best redisplay performance, it is very important to set the terminal speed:
+@lisp
+stty 2400
+@endlisp
+Often when running @hemlock using TTY redisplay, Hemlock will actually be
+talking to a PTY whose speed is initialized to infinity.  In reality, the
+terminal will be much slower, resulting in @hemlock@comment{}'s output getting way ahead
+of the terminal.  This prevents @hemlock from briefly stopping redisplay to
+allow the terminal to catch up.  See also @hvarref<Scroll Redraw Ratio>.
+
+The terminal control sequences are obtained from the termcap database using the
+normal Unix conventions.  The @f["TERM"] environment variable holds the
+terminal type.  The @f["TERMCAP"] environment variable can be used to override
+the default termcap database (in @f["/etc/termcap"]).  The size of the terminal
+can be altered from the termcap default through the use of:
+@lisp
+stty rows @i{height} columns @i{width}
+@endlisp
+
+@subsection[Terminal Input]
+@index[ASCII keyboard translation]
+@index[bit-prefix key-events]
+@index[prefix key-events]
+@index[key-event, prefix]
+The most important limitation of a terminal is its input capabilities.  On a
+workstation with function keys and independent control, meta, and shift
+modifiers, it is possible to type 800 or so distinct single keystrokes.
+Although by default, @hemlock uses only a fraction of these combinations, there
+are many more than the 128 key-events available in ASCII.
+
+On a terminal, @hemlock attempts to translate ASCII control characters into the
+most useful key-event:
+@begin[itemize]
+On a terminal, control does not compose with shift.  If the control key is down
+when you type a letter keys, the terminal always sends one code regardless of
+whether the shift key is held.  Since @hemlock primarily binds commands to
+key-events with keysyms representing lowercase letters regardless of what bits
+are set in the key-event, the system translates the ASCII control codes to a
+keysym representing the appropriate lowercase characters.  This keysym then
+forms a key-event with the control bit set.  Users can type @bf[C-c] followed
+by an uppercase character to form a key-event with a keysym representing an
+uppercase character and bits with the control bit set.
+
+On a terminal, some of the named keys generate an ASCII control code.  For
+example, @f[Return] usually sends a @f[C-m].  The system translates these ASCII
+codes to a key-event with an appropriate keysym instead of the keysym named by
+the character which names the ASCII code.  In the above example, typing the
+@f[Return] key would generate a key-event with the @bf[Return] keysym and no
+bits.  It would NOT translate to a key-event with the @bf[m] keysym and the
+control bit.
+@end[itemize]
+
+Since terminals have no meta key, you must use the @bf[Escape] and @bf[C-Z]
+modifier-prefix key-events to invoke commands bound to key-events with the meta
+bit or meta and control bits set.  ASCII terminals cannot generate all
+key-events which have the control bit on, so you can use the @bf[C-^]
+modifier-prefix.  The @bf[C-c] prefix sets the hyper bit on the next key-event
+typed.
+
+When running @hemlock from a terminal @f[^\] is the interrupt key-event.
+Typing this will place you in the Lisp debugger.
+
+When using a terminal, pop-up output windows cannot be retained after the
+completion of the command.
+
+
+@subsection[Terminal Redisplay]
+
+Redisplay is substantially different on a terminal.  @Hemlock uses different
+algorithms, and different parameters control redisplay and screen management.
+
+Terminal redisplay uses the Unix termcap database to find out how to use a
+terminal.  @hemlock is useful with terminals that lack capabilities for
+inserting and deleting lines and characters, and some terminal emulators
+implement these operations very inefficiently (such as xterm).
+If you realize poor performance when scrolling, create a termcap entry that
+excludes these capabilities.
+
+@defhvar[var "Scroll Redraw Ratio", val {nil}]
+This is a ratio of "inserted" lines to the size of a window.  When this ratio
+is exceeded, insert/delete line terminal optimization is aborted, and every
+altered line is simply redrawn as efficiently as possible.  For example,
+setting this to 1/4 will cause scrolling commands to redraw the entire window
+instead of moving the bottom two lines of the window to the top (typically 3/4
+of the window is being deleted upward and inserted downward, hence a redraw);
+however, commands like @hid[New Line] and @hid[Open Line] will still work
+efficiently, inserting a line and moving the rest of the window's text
+downward.
+@enddefhvar
+
+
+@section[The Echo Area]
+
+@index[echo area]
+@index[prompting]
+The echo area is the region which occupies the bottom few lines on the screen.
+It is used for two purposes: displaying brief messages to the user and
+prompting.
+
+When a command needs some information from the user, it requests it by
+displaying a @i[prompt] in the echo area.  The following is a typical prompt:
+@begin[programexample]
+Select Buffer: [hemlock-init.lisp /usr/foo/]
+@end[programexample]
+The general format of a prompt is a one or two word description of the input
+requested, possibly followed by a @i[default] in brackets.  The default is a
+standard response to the prompt that @hemlock uses if you type @bf[Return]
+without giving any other input.
+
+There are four general kinds of prompts: @comment<Key prompts?>
+@begin[description]
+@i[key-event]@\
+ The response is a single key-event and no confirming @binding[Return] is
+needed.
+
+@i[keyword]@\
+ The response is a selection from one of a limited number of choices.
+Completion is available using @binding[Space] and @binding[Escape], and you
+only need to supply enough of the keyword to distinguish it from any other
+choice.  In some cases a keyword prompt accepts unknown input, indicating the
+prompter should create a new entry.  If this is the case, then you must enter
+the keyword fully specified or completed using @binding[Escape]; this
+distinguishes entering an old keyword from making a new keyword which is a
+prefix of an old one since the system completes partial input automatically.
+
+@i[file]@\
+ The response is the name of a file, which may have to exist.  Unlike other
+prompts, the default has some effect even after the user supplies some input:
+the system @i[merges] the default with the input filename.  See page
+@pageref(merging) for a description of filename merging.  @bf[Escape] and
+@bf[Space] complete the input for a file parse.
+
+@i[string]@\
+ The response is a string which must satisfy some property, such as being the
+name of an existing file.
+@end[description]
+
+@index[history, echo area]
+These key-events have special meanings when prompting:
+@begin[description]
+@binding[Return]@\
+ Confirm the current parse.  If no input has been entered, then use the
+default.  If for some reason the input is unacceptable, @hemlock does two
+things:
+@Begin[enumerate]
+beeps, if the variable @hid[Beep on Ambiguity] set, and
+
+moves the point to the end of the first word requiring disambiguation.
+@End[enumerate]
+This allows you to add to the input before confirming the it again.
+
+@binding[Home, C-_]@\
+ Print some sort of help message.  If the parse is a keyword parse, then print
+all the possible completions of the current input in a pop-up window.
+
+@binding[Escape]@\
+ Attempt to complete the input to a keyword or file parse as far as possible,
+beeping if the result is ambiguous.  When the result is ambiguous, @hemlock
+moves the point to the first ambiguous field, which may be the end of the
+completed input.
+
+@binding[Space]@\
+ In a keyword parse, attempt to complete the input up to the next space.  This
+is useful for completing the names of @hemlock commands and similar things
+without beeping a lot, and you can continue entering fields while leaving
+previous fields ambiguous.  For example, you can invoke @hid[Forward Word] as
+an extended command by typing @binding[M-X f Space w Return].  Each time the
+user enters space, @Hemlock attempts to complete the current field and all
+previous fields.
+
+@binding[C-i, Tab]@\
+ In a string or keyword parse, insert the default so that it may be edited.
+
+@binding[C-p]@\
+ Retrieve the text of the last string input from a history of echo area inputs.
+Repeating this moves to successively earlier inputs.
+
+@binding[C-n]@\
+ Go the other way in the echo area history.
+
+@binding[C-q]@\
+ Quote the next key-event so that it is not interpreted as a command.
+@end[description]
+
+@defhvar[var "Ignore File Types"]
+This variable is a list of file types (or extensions), represented as a string
+without the dot, e.g. @f["fasl"].  Files having any of the specified types will
+be considered nonexistent for completion purposes, making an unambiguous
+completion more likely.  The initial value contains most common binary and
+output file types.
+@enddefhvar
+
+
+@section[Online Help]
+
+@label[help]
+@index[online help]
+@index[documentation, hemlock]
+@hemlock has a fairly good online documentation facility.  You can get brief
+documentation for every command, variable, character attribute, and key
+by typing a key.
+
+@defcom[com "Help", bind (Home, C-_)]
+This command prompt for a key-event indicating one of a number of other
+documentation commands.  The following are valid responses:
+@begin[description]
+@bf[a]@\
+ List commands and other things whose names contain a specified keyword.
+
+@bf[d]@\
+ Give the documentation and bindings for a specified command.
+
+@bf[g]@\
+ Give the documentation for any @hemlock thing.
+
+@bf[v]@\
+ Give the documentation for a @hemlock variable and its values.
+
+@bf[c]@\
+ Give the documentation for a command bound to some key.
+
+@bf[l]@\
+ List the last sixty key-events typed.
+
+@bf[m]@\
+ Give the documentation for a mode followed by a short description of its
+mode-specific bindings.
+
+@bf[p]@\
+ Give the documentation and bindings for commands that have at least one
+binding involving a mouse/pointer key-event.
+
+@bf[w]@\
+ List all the key bindings for a specified command.
+
+@bf[t]@\
+ Describe a @llisp object.
+
+@binding[q]@\
+ Quit without doing anything.
+
+@binding[Home, C-_, ?, h]@\
+ List all of the options and what they do.
+@end[description]
+@enddefcom
+
+@defcom[com "Apropos", bind (Home a, C-_ a)]
+This command prints brief documentation for all commands, variables, and
+character attributes whose names match the input.  This performs a prefix match
+on each supplied word separately, intersecting the names in each word's result.
+For example, giving @hid[Apropos] "@f[f m]" causes it to tersely describe
+following commands and variables:
+@Begin[Itemize]   
+@hid[Auto Fill Mode]
+
+@hid[Fundamental Mode]
+
+@hid[Mark Form]
+
+@hid[Default Modeline Fields]
+
+@hid[Fill Mode Hook]
+
+@hid[Fundamental Mode Hook]
+@End[Itemize]
+Notice @hid[Mark Form] demonstrates that the "@f[f]" words may follow the
+"@f[m]" order of the fields does not matter for @hid[Apropos].
+
+The bindings of commands and values of variables are printed with the
+documentation.
+@enddefcom
+
+@defcom[com "Describe Command", bind (Home d, C-_ d)]
+This command prompts for a command and prints its full documentation and all
+the keys bound to it.
+@enddefcom
+
+@defcom[com "Describe Key", bind (Home c, C-_ c, M-?)]
+This command prints full documentation for the command which is bound to
+the specified key in the current environment.
+@enddefcom
+
+@defcom[com "Describe Mode", bind (Home m, C-_ m)]
+This command prints the documentation for a mode followed by a short
+description of each of its mode-specific bindings.
+@enddefcom
+
+@defcom[com "Show Variable"]
+@defcom1[com "Describe and Show Variable"]
+@hid[Show Variable] prompts for the name of a variable and displays
+the global value of the variable, the value local to the current buffer (if
+any), and the value of the variable in all defined modes that have it as a
+local variable.  @hid[Describe and Show Variable] displays the variable's
+documentation in addition to the values.
+@enddefcom
+
+@defcom[com "What Lossage", bind (Home l, C-_ l)]
+This command displays the last sixty key-events typed.  This can be useful
+if, for example, you are curious what the command was that you typed by
+accident.
+@enddefcom
+
+@defcom[com "Describe Pointer"]
+This command displays the documentation and bindings for commands that have
+some binding involving a mouse/pointer key-event.  It will not show the
+documentation for the @hid[Illegal] command regardless of whether it has a
+pointer binding.
+@enddefcom
+
+@defcom[com "Where Is", bind (Home w, C-_ w)]
+This command prompts for the name of a command and displays its key
+bindings in a pop-up window.  If a key binding is not global, the
+environment in which it is available is displayed.
+@enddefcom
+
+@defcom[com "Generic Describe", bind (Home g, C-_ g)]
+This command prints full documentation for any thing that has
+documentation.  It first prompts for the kind of thing to document, the
+following options being available:
+@begin[description]
+@i[attribute]@\Describe a character attribute, given its name.
+
+@i[command]@\Describe a command, given its name.
+
+@i[key]@\Describe a command, given a key to which it is bound.
+
+@i[variable]@\Describe a variable, given its name.  This is the default.
+@end[description]
+@enddefcom
+
+
+@section[Entering and Exiting]
+
+@index[entering hemlock]@hemlock is entered by using the @clisp @f[ed]
+function.  Simply typing @f[(ed)] will enter @hemlock, leaving you in the state
+that you were in when you left it.  If @hemlock has never been entered before
+then the current buffer will be @hid[Main].  The @f[-edit] command-line switch
+may also be used to enter @hemlock: see page @pageref[edit-switch].
+
+@f[ed] may optionally be given a file name or a symbol argument.  Typing 
+@f[(ed @i[filename])] will cause the specified file to be read into @hemlock,
+as though by @hid[Find File].  Typing @w<@f[(ed @i[symbol])]> will pretty-print
+the definition of the symbol into a buffer whose name is obtained by adding
+"@f[Edit ]" to the beginning of the symbol's name.
+
+@defcom[com "Exit Hemlock", bind (C-c, C-x C-z)]
+@defcom1[com "Pause Hemlock"]
+@index[exiting hemlock]@hid[Exit Hemlock] exits @hemlock, returning @f[t].
+@hid[Exit Hemlock] does not by default save modified buffers, or do
+anything else that you might think it should do; it simply exits.  At any time
+after exiting you may reenter by typing @f[(ed)] to @llisp without losing
+anything.  Before you quit from @llisp using @f[(quit)], you should
+save any modified files that you want to be saved.
+
+@hid[Pause Hemlock] is similar, but it suspends the @llisp process and returns
+control to the shell.  When the process is resumed, it will still be running
+@hemlock.
+@enddefcom
+
+
+@section[Helpful Information]
+
+@label[aborting]
+@index[aborting]
+@index[undoing]
+@index[error recovery]
+This section contains assorted helpful information which may be useful in
+staying out of trouble or getting out of trouble.
+
+@begin[itemize]
+It is possible to get some sort of help nearly everywhere by typing
+@binding[Home] or @binding[C-_].
+
+Various commands take over the keyboard and insist that you type the key-events
+that they want as input.  If you get in such a situation and want to get out,
+you can usually do so by typing @bf[C-g] some small number of times.  If this
+fails you can try typing @binding[C-x C-z] to exit @hemlock and then "@f[(ed)]"
+to re-enter it.
+
+Before you quit, make sure you have saved all your changes.  @binding[C-u C-x
+C-b] will display a list of all modified buffers.  If you exit using @bf[C-x
+M-z], then @hemlock will save all modified buffers with associated files.
+
+If you lose changes to a file due to a crash or accidental failure to save,
+look for backup ("@i[file]@f[.BAK]") or checkpoint ("@i[file]@f[.CKP]") files
+in the same directory where the file was.
+
+If the screen changes unexpectedly, you may have accidentally typed an
+incorrect command.  Use @binding[Home l] to see what it was.  If you are
+not familiar with the command, use @binding[Home c] to see what it is so that
+you know what damage has been done.  Many interesting commands can be found
+in this fashion.  This is an example of the much-underrated learning
+technique known as "Learning by serendipitous malcoordination".  Who would
+ever think of looking for a command that deletes all files in the current
+directory?
+
+If you accidentally type a "killing" command such as @binding[C-w], you can
+get the lost text back using @binding[C-y].  The @hid[Undo] command is also
+useful for recovering from this sort of problem.
+@end[itemize]
+
+@defhvar[var "Region Query Size", val {30}]
+@index[large region]
+Various commands ask for confirmation before modifying a region containing more
+than this number of lines.  If this is @nil, then these commands refrain from
+asking, no matter how large the region is.
+@enddefhvar
+
+@defcom[com "Undo"]
+This command undoes the last major modification.  Killing commands and some
+other commands save information about their modifications, so accidental uses
+may be retracted.  This command displays the name of the operation to be undone
+and asks for confirmation.  If the affected text has been modified between the
+invocations of @hid[Undo] and the command to be undone, then the result may be
+somewhat incorrect but useful.  Often @hid[Undo] itself can be undone by
+invoking it again.
+@enddefcom
+
+
+@section[Recursive Edits]
+@label[recursive-edits]
+@index[recursive edits]
+Some sophisticated commands, such as @hid[Query Replace], can place you in a
+@i[recursive edit].  A recursive edit is simply a recursive invocation of
+@hemlock done within a command.  A recursive edit is useful because it allows
+arbitrary editing to be done during the execution of a command without losing
+any state that the command might have.  When the user exits a recursive edit,
+the command that entered it proceeds as though nothing happened.  @Hemlock
+notes recursive edits in the @hid[Echo Area] modeline, or status line.  A
+counter reflects the number of pending recursive edits.
+
+@defcom[com "Exit Recursive Edit", bind (C-M-z)]
+This command exits the current recursive edit, returning @nil.  If invoked when
+not in a recursive edit, then this signals an user error.
+@enddefcom
+
+@defcom[com "Abort Recursive Edit", bind (@bf<C-]>)]
+This command causes the command which invoked the recursive edit to get an
+error.  If not in a recursive edit, this signals an user error.
+@enddefcom
+
+
+@section[User Errors]
+@index[beeping]
+@index[errors, user]
+When in the course of editing, @hemlock is unable to do what it thinks you want
+to do, then it brings this to your attention by a beep or a screen flash
+(possibly accompanied by an explanatory echo area message such as @w<"@f[No
+next line.]">.)  Although the exact attention-getting mechanism may vary on the
+output device and variable settings, this is always called @i[beeping].
+
+Whatever the circumstances, you had best try something else since @hemlock,
+being far more stupid than you, is far more stubborn.  @hemlock is an
+extensible editor, so it is always possible to change the command that
+complained to do what you wanted it to do.
+
+@section[Internal Errors]
+
+@index[errors, internal]A message of this form may appear in the echo
+area, accompanied by a beep:
+@begin[programexample]
+Internal error:
+Wrong type argument, NIL, should have been of type SIMPLE-VECTOR.
+@end[programexample]
+If the error message is a file related error such as the following, then
+you have probably done something illegal which @hemlock did not catch,
+but was detected by the file system:
+@begin[programexample]
+Internal error:
+No access to "/lisp2/emacs/teco.mid"
+@end[programexample]
+Otherwise, you have found a bug.  Try to avoid the behavior that resulted
+in the error and report the problem to your system maintainer.  Since @llisp
+has fairly robust error recovery mechanisms, probably no damage has been
+done.
+
+If a truly abominable error from which @hemlock cannot recover occurs,
+then you will be thrown into the @llisp debugger.  At this point it would be
+a good idea to save any changes with @f[save-all-buffers] and then start
+a new @llisp.
+
+@index[save-all-buffers, function]The @llisp function @f[save-all-buffers] may
+be used to save modified buffers in a seriously broken @hemlock.  To use this,
+type "@f[(save-all-buffers)]" to the top-level ("@f[* ]") or debugger
+("@f<1] >") prompt and confirm saving of each buffer that should be saved.
+Since this function will prompt in the "@f[Lisp]" window, it isn't very useful
+when called inside of @hemlock.
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/lisp.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/lisp.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/lisp.mss	(revision 13309)
@@ -0,0 +1,822 @@
+@comment{-*- Dictionary: /afs/cs/project/clisp/scribe/hem/hem; Mode: spell; Package: Hemlock -*-}
+@chap[Interacting With Lisp]
+@index[lisp, interaction with]
+
+Lisp encourages highly interactive programming environments by requiring
+decisions about object type and function definition to be postponed until run
+time.  @hemlock supports interactive programming in @llisp by providing
+incremental redefinition and environment examination commands.  @hemlock also
+uses Unix TCP sockets to support multiple Lisp processes, each of which may be
+on any machine.
+
+
+@section[Eval Servers]
+@label[eval-servers]
+@index[eval servers]
+
+@hemlock runs in the editor process and interacts with other Lisp processes
+called @i[eval servers].  A user's Lisp program normally runs in an eval
+server process.  The separation between editor and eval server has several
+advantages:
+@begin[itemize]
+The editor is protected from any bad things which may happen while debugging a
+Lisp program.
+
+Editing may occur while running a Lisp program.
+
+The eval server may be on a different machine, removing the load from the
+editing machine.
+
+Multiple eval servers allow the use of several distinct Lisp environments.
+@end[itemize]
+Instead of providing an interface to a single Lisp environment, @hemlock
+coordinates multiple Lisp environments.
+
+
+@subsection[The Current Eval Server]
+@index[current eval server]
+Although @hemlock can be connected to several eval servers simultaneously, one
+eval server is designated as the @i[current eval server].  This is the eval
+server used to handle evaluation and compilation requests.  Eval servers are
+referred to by name so that there is a convenient way to discriminate between
+servers when the editor is connected to more than one.  The current eval server
+is normally globally specified, but it may also be shadowed locally in specific
+buffers.
+
+@defcom[com "Set Eval Server"]
+@defcom1[com "Set Buffer Eval Server"]
+@defcom1[com "Current Eval Server"]
+@hid[Set Eval Server] prompts for the name of an eval server and makes it the
+the current eval server.  @hid[Set Buffer Eval Server] is the same except that
+is sets the eval server for the current buffer only.  @hid[Current Eval Server]
+displays the name of the current eval server in the echo area, taking any
+buffer eval server into consideration.  See also @comref[Set Compile Server].
+@enddefcom
+
+
+@subsection[Slaves]
+@index[slave buffers]
+@index[slaves]
+For now, all eval servers are @i[slaves].  A slave is a Lisp process that uses
+a typescript (see page @pageref[typescripts]) to run its top-level
+@f[read-eval-print] loop in a @hemlock buffer.  We refer to the buffer that a
+slave uses for I/O as its @i[interactive] or @i[slave] buffer.  The name of the
+interactive buffer is the same as the eval server's name.
+
+@index[background buffers]
+@hemlock creates a @i[background] buffer for each eval server.  The background
+buffer's name is @w<@hid[Background ]@i{name}>, where @i[name] is the name of
+the eval server.  Slaves direct compiler warning output to the background
+buffer to avoid cluttering up the interactive buffer.
+
+@hemlock locally sets @hid[Current Eval Server] in interactive and background
+buffers to their associated slave.  When in a slave or background buffer, eval
+server requests will go to the associated slave, regardless of the global value
+of @hid[Current Eval Server].
+
+@defcom[com "Select Slave", bind (C-M-c)]
+This command changes the current buffer to the current eval server's
+interactive buffer.  If the current eval server is not a slave, then it beeps.
+If there is no current eval server, then this creates a slave (see section
+@ref[slave-creation]).  If a prefix argument is supplied, then this creates a
+new slave regardless of whether there is a current eval server.  This command
+is the standard way to create a slave.
+
+The slave buffer is a typescript (see page @pageref[typescripts]) the slave
+uses for its top-level @f[read-eval-print] loop.
+@enddefcom
+
+@defcom[com "Select Background", bind (C-M-C)]
+This command changes the current buffer to the current eval server's background
+buffer.  If there is no current eval server, then it beeps.
+@enddefcom
+
+
+@subsection[Slave Creation and Destruction]
+@label[slave-creation]
+When @hemlock first starts up, there is no current eval server.  If there is no
+a current eval server, commands that need to use the current eval server will
+create a slave as the current eval server.
+
+If an eval server's Lisp process terminates, then we say the eval server is
+dead.  @hemlock displays a message in the echo area, interactive, and
+background buffers whenever an eval server dies.  If the user deletes an
+interactive or background buffer, the associated eval server effectively
+becomes impotent, but @hemlock does not try to kill the process.  If a command
+attempts to use a dead eval server, then the command will beep and display a
+message.
+
+@defhvar[var "Confirm Slave Creation", val {t}]
+If this variable is true, then @hemlock always prompts the user for
+confirmation before creating a slave.
+@enddefhvar
+
+@defhvar[var "Ask About Old Servers", val {t}]
+If this variable is true, and some slave already exists, @hemlock prompts the
+user for the name of an existing server when there is no current server,
+instead of creating a new one.
+@enddefhvar
+
+@defcom[com "Editor Server Name"]
+This command echos the editor server's name, the machine and port of the
+editor, which is suitable for use with the Lisp processes -slave switch.
+See section @ref[slave-switch].
+@enddefcom
+
+@defcom[com "Accept Slave Connections"]
+This command cause @hemlock to accept slave connections, and it displays the
+editor server's name, which is suitable for use with the Lisp processes -slave
+switch.  See section @ref[slave-switch].  Supplying an argument causes this
+command to inhibit slave connections.
+@enddefcom
+
+@defhvar[var "Slave Utility", val {"/usr/misc/.lisp/bin/lisp"}]
+@defhvar1[var "Slave Utility Switches"]
+A slave is started by running the program @hid[Slave Utility Name] with
+arguments specified by the list of strings @hid[Slave Utility Switches].  This
+is useful primarily when running customized Lisp systems.  For example,
+setting @hid[Slave Utility Switches] to @f[("-core" "my.core")] will cause
+"@f[/usr/hqb/my.core]" to be used instead of the default core image.
+
+The @f[-slave] switch and the editor name are always supplied as arguments, and
+should remain unspecified in @hid[Slave Utility Switches].
+@enddefhvar
+
+@defcom[com "Kill Slave"]
+@defcom1[com "Kill Slave and Buffers"]
+@hid[Kill Slave] prompts for a slave name, aborts any operations in the slave,
+tells the slave to @f[quit], and shuts down the connection to the specified
+eval server.  This makes no attempt to assure the eval server actually dies.
+
+@hid[Kill Slave and Buffers] is the same as @hid[Kill Slave], but it also
+deletes the interactive and background buffers.
+@enddefcom
+
+
+@subsection[Eval Server Operations]
+
+@label[operations]
+@index[eval server operations]@index[operations, eval server]
+@hemlock handles requests for compilation or evaluation by queuing an
+@i[operation] on the current eval server.  Any number of operations may be
+queued, but each eval server can only service one operation at a time.
+Information about the progress of operations is displayed in the echo area.
+
+@defcom[com "Abort Operations", bind (C-c a)]
+This command aborts all operations on the current eval server, either queued or
+in progress.  Any operations already in the @f[Aborted] state will be flushed.
+@enddefcom
+
+@defcom[com "List Operations", bind (C-c l)]
+This command lists all operations which have not yet completed.  Along with a
+description of the operation, the state and eval server is displayed.  The
+following states are used:
+@begin[description]
+@f[Unsent]@\The operation is in local queue in the editor, and hasn't been sent
+yet.
+
+@f[Pending]@\The operation has been sent, but has not yet started execution.
+
+@f[Running]@\The operation is currently being processed.
+
+@f[Aborted]@\The operation has been aborted, but the eval server has not yet
+indicated termination.
+@end[description]
+@enddefcom
+
+
+@section[Typescripts]
+@label[typescripts]
+@index[typescripts]
+
+Both slave buffers and background buffers are typescripts.  The typescript
+protocol allows other processes to do stream-oriented interaction in a @hemlock
+buffer similar to that of a terminal.  When there is a typescript in a buffer,
+the @hid[Typescript] minor mode is present.  Some of the commands described in
+this section are also used by @hid[Eval] mode (page @pageref[eval-mode].)
+
+Typescripts are simple to use.  @hemlock inserts output from the process into
+the buffer.  To give the process input, use normal editing to insert the input
+at the end of the buffer, and then type @bf[Return] to confirm sending the
+input to the process.
+
+@defcom[com "Confirm Typescript Input", 
+        stuff (bound to @bf[Return] in @hid[Typescript] mode)]
+@defhvar1[var "Unwedge Interactive Input Confirm", val {t}]
+This command sends text that has been inserted at the end of the current buffer
+to the process reading on the buffer's typescript.  Before sending the text,
+@hemlock moves the point to the end of the buffer and inserts a newline.
+
+Input may be edited as much as is desired before it is confirmed; the result
+of editing input after it has been confirmed is unpredictable.  For this reason,
+it is desirable to postpone confirming of input until it is actually complete.
+The @hid[Indent New Line] command is often useful for inserting newlines
+without confirming the input.
+
+If the process reading on the buffer's typescript is not waiting for input,
+then the text is queued instead of being sent immediately.  Any number of
+inputs may be typed ahead in this fashion.  @hemlock makes sure that the inputs
+and outputs get interleaved correctly so that when all input has been read, the
+buffer looks the same as it would have if the input had not been typed ahead.
+
+If the buffer's point is before the start of the input area, then various
+actions can occur.  When set, @hid[Unwedge Interactive Input Confirm] causes
+@hemlock to ask the user if it should fix the input buffer which typically
+results in ignoring any current input and refreshing the input area at the end
+of the buffer.  This also has the effect of throwing the slave Lisp to top
+level, which aborts any pending operations or queued input.  This is the only
+way to be sure the user is cleanly set up again after messing up the input
+region.  When this is @nil, @hemlock simply beeps and tells the user in the
+@hid[Echo Area] that the input area is invalid.
+@enddefcom
+
+@defcom[com "Kill Interactive Input", 
+    stuff (bound to @bf[M-i] in @hid[Typescript] and @hid[Eval] modes)]
+This command kills any input that would have been confirmed by @bf[Return].
+@enddefcom
+
+@defcom[com "Next Interactive Input",  
+        stuff (bound to @bf[M-n] in @hid[Typescript] and @hid[Eval] modes)]
+@defcom1[com "Previous Interactive Input",
+        stuff (bound to @bf[M-p] in @hid[Typescript] and @hid[Eval] modes)]
+@defcom1[com "Search Previous Interactive Input",
+	stuff (bound to @bf[M-P] in @hid[Typescript] and @hid[Eval] modes)]
+@defhvar1[var "Interactive History Length", val {10}]
+@defhvar1[var "Minimum Interactive Input Length", val {2}]
+@index[history, typescript]
+@Hemlock maintains a history of interactive inputs.  @hid[Next Interactive
+Input] and @hid[Previous Interactive Input] step forward and backward in the
+history, inserting the current entry in the buffer.  The prefix argument is
+used as a repeat count.
+
+@hid[Search Previous Interactive Input] searches backward through the
+interactive history using the current input as a search string.  Consecutive
+invocations repeat the previous search.
+
+@hid[Interactive History Length] determines the number of entries with which
+@hemlock creates the buffer-specific histories.  @Hemlock only adds an input
+region to the history if its number of characters exceeds @hid[Minimum
+Interactive Input Length].
+@enddefcom
+
+@defcom[com "Reenter Interactive Input",
+	stuff (bound to @bf[C-Return] in @hid[Typescript] and @hid[Eval] modes)]
+ This copies to the end of the buffer the form to the left of the buffer's
+point.  When the current region is active, this copies it instead.  This is
+sometimes easier to use to get a previous input that is either so far back that
+it has fallen off the history or is visible and more readily @i[yanked] than
+gotten with successive invocations of the history commands.
+@enddefcom
+
+@defcom[com "Interactive Beginning of Line", 
+        stuff (bound to @bf[C-a] in @hid[Typescript] and @hid[Eval] modes)]
+This command is identical to @hid[Beginning of Line] unless there is no
+prefix argument and the point is on the same line as the start of the current
+input; then it moves to the beginning of the input.  This is useful since it
+skips over any prompt which may be present.
+@enddefcom
+
+@defhvar[var "Input Wait Alarm", val {:loud-message}]
+@defhvar1[var "Slave GC Alarm", val {:message}]
+@hid[Input Wait Alarm] determines what action to take when a slave Lisp goes
+into an input wait on a typescript that isn't currently displayed in any
+window.  @hid[Slave GC Alarm] determines what action to take when a slave
+notifies that it is GC'ing.
+
+The following are legal values:
+@begin[description]
+@kwd[loud-message]@\Beep and display a message in the echo area indicating
+which buffer is waiting for input.
+
+@kwd[message]@\Display a message, but don't beep.
+
+@nil@\Don't do anything.
+@end[description]
+@enddefhvar
+
+@defcom[com "Typescript Slave BREAK", bind (Typescript: H-b)]
+@defcom1[com "Typescript Slave to Top Level", bind (Typescript: H-g)]
+@defcom1[com "Typescript Slave Status", bind (Typescript: H-s)]
+Some typescripts have associated information which these commands access
+allowing @hemlock to control the process which uses the typescript.
+
+@hid[Typescript Slave BREAK] puts the current process in a break loop so that
+you can be debug it.  This is similar in effect to an interrupt signal (@f[^C]
+or @f[^\] in the editor process).
+
+@hid[Typescript Slave to Top Level] causes the current process to throw to the
+top-level @f[read-eval-print] loop.  This is similar in effect to a quit signal
+(@f[^\]).
+
+@hid[Typescript Slave Status] causes the current process to print status
+information on @var[error-output]:
+@lisp
+; Used 0:06:03, 3851 faults.  In: SYSTEM:SERVE-EVENT
+@endlisp
+The message displays the process run-time, the total number of page faults and
+the name of the currently running function.   This command is useful for
+determining whether the slave is in an infinite loop, waiting for input, or
+whatever.
+@enddefcom
+
+
+@section[The Current Package]
+@label[lisp-package]
+@index[package]
+The current package is the package which Lisp interaction commands use.  The
+current package is specified on a per-buffer basis, and defaults to "@f[USER]".
+If the current package does not exist in the eval server, then it is created.
+If evaluation is being done in the editor process and the current package
+doesn't exist, then the value of @f[*package*] is used.  The current package is
+displayed in the modeline (see section @ref[modelines].)  Normally the package
+for each file is specified using the @f[Package] file option (see page
+@pageref[file-options].)
+
+When in a slave buffer, the current package is controlled by the value of
+@var[package] in that Lisp process.  Modeline display of the current package
+is inhibited in this case.
+
+@defcom[com "Set Buffer Package"]
+This command prompts for the name of a package to make the local package in the
+current buffer.  If the current buffer is a slave, background, or eval buffer,
+then this sets the current package in the associated eval server or editor
+Lisp.  When in an interactive buffer, do not use @f[in-package]; use this
+command instead.
+@enddefcom
+
+
+@section[Compiling and Evaluating Lisp Code]
+
+@index[compilation]@index[evaluation]These commands can greatly speed up
+the edit/debug cycle since they enable incremental reevaluation or
+recompilation of changed code, avoiding the need to compile and load an
+entire file.  
+
+@defcom[com "Evaluate Expression", bind (M-Escape)]
+This command prompts for an expression and prints the result of its evaluation
+in the echo area.  If an error happens during evaluation, the evaluation is
+simply aborted, instead of going into the debugger.  This command doesn't
+return until the evaluation is complete.
+@enddefcom
+
+@defcom[com "Evaluate Defun", bind (C-x C-e)]
+@defcom1[com "Evaluate Region"]
+@defcom1[com "Evaluate Buffer"]
+These commands evaluate text out of the current buffer, reading the current
+defun, the region and the entire buffer, respectively.  The result of the
+evaluation of each form is displayed in the echo area.  If the region is
+active, then @hid[Evaluate Defun] evaluates the current region, just like 
+@hid[Evaluate Region].
+@enddefcom
+
+@defcom[com "Macroexpand Expression", bind (C-M)]
+This command shows the macroexpansion of the next expression in the null
+environment in a pop-up window.  With an argument, it uses @f[macroexpand]
+instead of @f[macroexpand-1].
+@enddefcom
+
+@defcom[com "Re-evaluate Defvar"]
+This command is similar to @hid[Evaluate Defun].  It is used for force the
+re-evaluation of a @f[defvar] init form.  If the current top-level form is a
+@f[defvar], then it does a @f[makunbound] on the variable, and evaluates the
+form.
+@enddefcom
+
+@defcom[com "Compile Defun", bind (C-x C-c)]
+@defcom1[com "Compile Region"]
+These commands compile the text in the current defun and the region,
+respectively.  If the region is active, then @hid[Compile Defun] compiles the
+current region, just like @hid[Compile Region].
+@enddefcom
+
+@defcom[com "Load File"]
+@defhvar1[var "Load Pathname Defaults", val {nil}]
+This command prompts for a file and loads it into the current eval server using
+@f[load].  @hid[Load Pathname Defaults] contains the default pathname for this
+command.  This variable is set to the file loaded; if it is @nil, then there is
+no default.  This command also uses the @hid[Remote Compile File] variable.
+@enddefcom
+
+
+@section[Compiling Files]
+These commands are used to compile source ("@f[.lisp]") files, producing binary
+("@f[.fasl]") output files.  Note that unlike the other compiling and evalating
+commands, this does not have the effect of placing the definitions in the
+environment; to do so, the binary file must be loaded.
+
+@defcom[com "Compile Buffer File", bind (C-x c)]
+@defhvar1[var "Compile Buffer File Confirm", val {t}]
+This command asks for confirmation, then saves the current buffer (when
+modified) and compiles the associated file.  The confirmation prompt indicates
+intent to save and compile or just compile.  If the buffer wasn't modified, and
+a comparison of the write dates for the source and corresponding binary
+("@f[.fasl]") file suggests that recompilation is unnecessary, the confirmation
+also indicates this.  A prefix argument overrides this test and forces
+recompilation.  Since there is a complete log of output in the background
+buffer, the creation of the normal error output ("@f[.err]") file is inhibited.
+
+Setting @hid[Compile Buffer File Confirm] to @nil inhibits confirmation, except
+when the binary is up to date and a prefix argument is not supplied.
+@enddefcom
+
+@defcom[com "Compile File"]
+This command prompts for a file and compiles that file, providing a convenient
+way to compile a file that isn't in any buffer.  Unlike 
+@hid[Compile Buffer File], this command doesn't do any consistency checks such
+as checking whether the source is in a modified buffer or the binary is up to
+date.
+@enddefcom
+
+@defcom[com "Compile Group"]
+@defcom1[com "List Compile Group"]
+@label[compile-group-command]@index[group, compilation]@hid[Compile Group] does
+a @hid[Save All Files] and then compiles every "@f[.lisp]" file for which the
+corresponding "@f[.fasl]" file is older or nonexistent.  The files are compiled
+in the order in which they appear in the group definition.  A prefix argument
+forces compilation of all "@f[.lisp]" files.
+
+@hid[List Compile Group] lists any files that would be compiled by
+@hid[Compile Group].  All Modified files are saved before checking to generate
+a consistent list.
+@enddefcom 
+
+@defcom[com "Set Compile Server"]
+@defcom1[com "Set Buffer Compile Server"]
+@defcom1[com "Current Compile Server"]
+These commands are analogous to @hid[Set Eval Server], @comref[Set Buffer Eval
+Server] and @hid[Current Eval Server], but they determine the eval server used
+for file compilation requests.  If the user specifies a compile server, then
+the file compilation commands send compilation requests to that server instead
+of the current eval server.
+
+Having a separate compile server makes it easy to do compilations in the
+background while continuing to interact with your eval server and editor.  The
+compile server can also run on a remote machine relieving your active
+development machine of the compilation effort.
+@enddefcom
+
+@defcom[com "Next Compiler Error", bind (H-n)]
+@defcom1[com "Previous Compiler Error", bind (H-p)]
+These commands provides a convenient way to inspect compiler errors.  First it
+splits the current window if there is only one window present.  @hemlock
+positions the current point in the first window at the erroneous source code
+for the next (or previous) error.  Then in the second window, it displays the
+error beginning at the top of the window.  Given an argument, this command
+skips that many errors.
+@enddefcom
+
+@defcom[com "Flush Compiler Error Information"]
+This command relieves the current eval server of all infomation about errors
+encountered while compiling.  This is convenient if you have been compiling a
+lot, but you were ignoring errors and warnings.  You don't want to step through
+all the old errors, so you can use this command immediately before compiling a
+file whose errors you intend to edit.
+@enddefcom
+
+
+@defhvar[var "Remote Compile File", val {nil}]
+When true, this variable causes file compilations to be done using the RFS
+remote file system mechanism by prepending "@f[/../]@i[host]" to the file being
+compiled.  This allows the compile server to be run on a different machine, but
+requires that the source be world readable.  If false, commands use source
+filenames directly.  Do NOT use this to compile files in AFS.
+@enddefhvar
+
+
+@section[Querying the Environment]
+@index[documentation, lisp]
+These commands are useful for obtaining various random information from the
+Lisp environment.
+
+@defcom[com "Describe Function Call", bind (C-M-A)]
+@defcom1[com "Describe Symbol", bind (C-M-S)]
+@hid[Describe Function Call] uses the current eval server to describe the
+symbol found at the head of the currently enclosing list, displaying the output
+in a pop-up window.  @hid[Describe Symbol] is the same except that it describes
+the symbol at or before the point.  These commands are primarily useful for
+finding the documentation for functions and variables.  If there is no
+currently valid eval server, then this command uses the editor Lisp's
+environment instead of trying to spawn a slave.
+@enddefcom
+
+
+@section[Editing Definitions]
+The Lisp compiler annotates each compiled function object with the source
+file that the function was originally defined from.  The definition editing
+commands use this information to locate and edit the source for functions
+defined in the environment.
+
+@defcom[com "Edit Definition"]
+@defcom1[com "Goto Definition", bind (C-M-F)]
+@defcom1[com "Edit Command Definition"]
+@hid[Edit Definition] prompts for the name of a function, and then uses the
+current eval server to find out in which file the function is defined.  If
+something other than @f[defun] or @f[defmacro] defined the function, then this
+simply reads in the file, without trying to find its definition point within
+the file.  If the function is uncompiled, then this looks for it in the current
+buffer.  If there is no currently valid eval server, then this command uses the
+editor Lisp's environment instead of trying to spawn a slave.
+
+@hid[Goto Definition] edits the definition of the symbol at the beginning of
+the current list.
+
+@hid[Edit Command Definition] edits the definition of a @hemlock command.  By
+default, this command does a keyword prompt for the command name (as in an
+extended command).  If a prefix argument is specified, then instead prompt for
+a key and edit the definition of the command bound to that key.
+@enddefcom
+
+@defcom[com "Add Definition Directory Translation"]
+@defcom1[com "Delete Definition Directory Translation"]
+The defining file is recorded as an absolute pathname.  The definition editing
+commands have a directory translation mechanism that allow the sources to be
+found when they are not in the location where compilation was originally done.
+@hid[Add Definition Directory Translation] prompts for two directory
+namestrings and causes the first to be mapped to the second.  Longer (more
+specific) directory specifications are matched before shorter (more general)
+ones.
+
+@hid[Delete Definition Directory Translation] prompts for a directory
+namestring and deletes it from the directory translation table.
+@enddefcom
+
+@defhvar[var "Editor Definition Info", val {nil}]
+When this variable is true, the editor Lisp is used to determine definition
+editing information, otherwise the current eval server is used.  This variable
+is true in @hid[Eval] and @hid[Editor] modes.
+@enddefhvar
+
+
+@section[Debugging]
+These commands manipulate the slave when it is in the debugger and provide
+source editing based on the debugger's current frame.  These all affect the
+@hid[Current Eval Server].
+
+
+@subsection[Changing Frames]
+
+@defcom[com "Debug Down", bind (C-M-H-d)]
+This command moves down one debugger frame.
+@enddefcom
+
+@defcom[com "Debug Up", bind (C-M-H-u)]
+This command moves up one debugger frame.
+@enddefcom
+
+@defcom[com "Debug Top", bind (C-M-H-t)]
+This command moves to the top of the debugging stack.
+@enddefcom
+
+@defcom[com "Debug Bottom", bind (C-M-H-b)]
+This command moves to the bottom of the debugging stack.
+@enddefcom
+
+@defcom[com "Debug Frame", bind (C-M-H-f)]
+This command moves to the absolute debugger frame number indicated by the
+prefix argument.
+@enddefcom
+
+
+@subsection[Getting out of the Debugger]
+
+@defcom[com "Debug Quit", bind (C-M-H-q)]
+This command throws to top level out of the debugger in the @hid[Current Eval
+Server].
+@enddefcom
+
+@defcom[com "Debug Go", bind (C-M-H-g)]
+This command tries the @f[continue] restart in the @hid[Current Eval Server].
+@enddefcom
+
+@defcom[com "Debug Abort", bind (C-M-H-a)]
+This command executes the ABORT restart in the @hid[Current Eval Server].
+@enddefcom
+
+@defcom[com "Debug Restart", bind (C-M-H-r)]
+This command executes the restart indicated by the prefix argument in the
+@hid[Current Eval Server].  The debugger enumerates the restart cases upon
+entering it.
+@enddefcom
+
+
+@subsection[Getting Information]
+
+@defcom[com "Debug Help", bind (C-M-H-h)]
+This command in prints the debugger's help text.
+@enddefcom
+
+@defcom[com "Debug Error", bind (C-M-H-e)]
+This command prints the error condition and restart cases displayed upon
+entering the debugger.
+@enddefcom
+
+@defcom[com "Debug Backtrace", bind (C-M-H-B)]
+This command executes the debugger's @f[backtrace] command.
+@enddefcom
+
+@defcom[com "Debug Print", bind (C-M-H-p)]
+This command prints the debugger's current frame in the same fashion as the
+frame motion commands.
+@enddefcom
+
+@defcom[com "Debug Verbose Print", bind (C-M-H-P)]
+This command prints the debugger's current frame without elipsis.
+@enddefcom
+
+@defcom[com "Debug Source", bind (C-M-H-s)]
+This command prints the source form for the debugger's current frame.
+@enddefcom
+
+@defcom[com "Debug Verbose Source"]
+This command prints the source form for the debugger's current frame with
+surrounding forms for context.
+@enddefcom
+
+@defcom[com "Debug List Locals", bind (C-M-H-l)]
+This prints the local variables for the debugger's current frame.
+@enddefcom
+
+
+@subsection[Editing Sources]
+
+@defcom[com "Debug Edit Source", bind (C-M-H-S)]
+This command attempts to place you at the source location of the debugger's
+current frame.  Not all debugger frames represent function's that were compiled
+with the appropriate debug-info policy.  This beeps with a message if it is
+unsuccessful.
+@enddefcom
+
+
+@subsection[Miscellaneous]
+
+@defcom[com "Debug Flush Errors", bind (C-M-H-F)]
+This command toggles whether the debugger ignores errors or recursively enters
+itself.
+@enddefcom
+
+
+
+
+@section[Manipulating the Editor Process]
+When developing @hemlock customizations, it is useful to be able to manipulate
+the editor Lisp environment from @hemlock.
+
+@defcom[com "Editor Describe", bind (Home t, C-_ t)]
+This command prompts for an expression, and then evaluates and describes it
+in the editor process.
+@enddefcom
+
+@defcom[com "Room"]
+Call the @f[room] function in the editor process, displaying information
+about allocated storage in a pop-up window.
+@enddefcom
+
+@defcom[com "Editor Load File"]
+This command is analogous to @comref[Load File], but loads the file into the
+editor process.
+@enddefcom
+
+
+@subsection[Editor Mode]
+When @hid[Editor] mode is on, alternate versions of the Lisp interaction
+commands are bound in place of the eval server based commands.  These commands
+manipulate the editor process instead of the current eval server.  Turning on
+editor mode in a buffer allows incremental development of code within the
+running editor.
+
+@defcom[com "Editor Mode"]
+This command turns on @hid[Editor] minor mode in the current buffer.  If it is
+already on, it is turned off.  @hid[Editor] mode may also be turned on using
+the @f[Mode] file option (see page @pageref[file-options].)
+@enddefcom
+
+@defcom[com "Editor Compile Defun",
+	stuff (bound to @bf[C-x C-c] in @hid[Editor] mode)]
+@defcom1[com "Editor Compile Region"]
+@defcom1[com "Editor Evaluate Buffer"]
+@defcom1[com "Editor Evaluate Defun",
+	stuff (bound to @bf[C-x C-e] in @hid[Editor] mode)]
+@defcom1[com "Editor Evaluate Region"]
+@defcom1[com "Editor Macroexpand Expression", bind (Editor: C-M)]
+@defcom1[com "Editor Re-evaluate Defvar"]
+@defcom1[com "Editor Describe Function Call",
+	stuff (bound to @bf[C-M-A] in @hid[Editor] mode)]
+@defcom1[com "Editor Describe Symbol",
+	stuff (bound to @bf[C-M-S] in @hid[Editor] mode)]
+These commands are similar to the standard commands, but modify or examine the
+Lisp process that @hemlock is running in.  Terminal I/O is done on the
+initial window for the editor's Lisp process.  Output is directed to a pop-up
+window or the editor's window instead of to the background buffer.
+@enddefcom
+
+@defcom[com "Editor Compile Buffer File"]
+@defcom1[com "Editor Compile File"]
+@defcom1[com "Editor Compile Group"]
+In addition to compiling in the editor process, these commands differ from the
+eval server versions in that they direct output to the the 
+@hid[Compiler Warnings] buffer.
+@enddefcom
+
+@defcom[com "Editor Evaluate Expression",
+     stuff (bound to @bf[M-Escape] in @hid[Editor] mode and @bf[C-M-Escape])] 
+This command prompts for an expression and evaluates it in the editor process.
+The results of the evaluation are displayed in the echo area.
+@enddefcom
+
+
+@subsection[Eval Mode]
+@label[eval-mode]
+@index[modes, eval]@hid[Eval] mode is a minor mode that simulates a @f[read]
+@f[eval] @f[print] loop running within the editor process.  Since Lisp
+program development is usually done in a separate eval server process (see page
+@pageref[eval-servers]), @hid[Eval] mode is used primarily for debugging code
+that must run in the editor process.  @hid[Eval] mode shares some commands with
+@hid[Typescript] mode: see section @ref[typescripts].
+
+@hid[Eval] mode doesn't completely support terminal I/O: it binds
+@var[standard-output] to a stream that inserts into the buffer and
+@var[standard-input] to a stream that signals an error for all operations.
+@hemlock cannot correctly support the interactive evaluation of forms that read
+from the @hid[Eval] interactive buffer.
+
+@defcom[com "Select Eval Buffer"]
+This command changes to the @hid[Eval] buffer, creating one if it doesn't
+already exist.  The @hid[Eval] buffer is created with @hid[Lisp] as the major
+mode and @hid[Eval] and @hid[Editor] as minor modes. 
+@enddefcom
+
+@defcom[com "Confirm Eval Input",
+        stuff (bound to @bf[Return] in @hid[Eval] mode)]
+This command evaluates all the forms between the end of the last output and
+the end of the buffer, inserting the results of their evaluation in the buffer.
+This beeps if the form is incomplete.  Use @binding[Linefeed] to insert line
+breaks in the middle of a form.
+
+This command uses @hid[Unwedge Interactive Input Confirm] in the same way
+@hid[Confirm Interactive Input] does.
+@enddefcom
+
+@defcom[com "Abort Eval Input", 
+        stuff (bound to @bf[M-i] in @hid[Eval] mode)]
+This command moves the the end of the buffer and prompts, ignoring any
+input already typed in.
+@enddefcom
+
+
+@subsection[Error Handling]
+@index[error handling]
+When an error happens inside of @hemlock, @hemlock will trap the error and
+display the error message in the echo area, possibly along with the
+"@f[Internal error:]" prefix.  If you want to debug the error, type @bf[?].
+This causes the prompt "@f[Debug:]" to appear in the echo area.  The following
+commands are recognized:
+@begin[description]
+@bf[d]@\Enter a break-loop so that you can use the Lisp debugger.
+Proceeding with "@f[go]" will reenter @hemlock and give the "@f[Debug:]"
+prompt again.
+
+@bf[e]@\Display the original error message in a pop-up window.
+
+@bf[b]@\Show a stack backtrace in a pop-up window.
+
+@bf[q, Escape]@\Quit from this error to the nearest command loop.
+
+@bf[r]@\Display a list of the restart cases and prompt for the number of a
+@f[restart-case] with which to continue.  Restarting may result in prompting in
+the window in which Lisp started.
+@end[description]
+
+Only errors within the editor process are handled in this way.  Errors during
+eval server operations are handled using normal terminal I/O on a typescript in
+the eval server's slave buffer or background buffer (see page
+@pageref[operations]).  Errors due to interaction in a slave buffer will cause
+the debugger to be entered in the slave buffer.
+
+
+@section[Command Line Switches]
+@label[slave-switch]
+Two command line switches control the initialization of editor and eval servers
+for a Lisp process:
+@begin[description]
+@f<-edit>@\
+@label[edit-switch]
+This switch starts up @hemlock.  If there is a non-switch command line word
+immediately following the program name, then the system interprets it as a file
+to edit.  For example, given
+@Begin[ProgramExample]
+lisp file.txt -edit
+@End[ProgramExample]
+Lisp will go immediately into @hemlock finding the file @f[file.txt].
+
+@f<-slave [>@i[name]@f<]>@\
+ This switch causes the Lisp process to become a slave of the editor process
+@i[name].  An editor Lisp determines @i[name] when it allows connections from
+slaves.  Once the editor chooses a name, it keeps the same name until the
+editor's Lisp process terminates.  Since the editor can automatically create
+slaves on its own machine, this switch is useful primarily for creating slaves
+that run on a different machine.  @f[hqb]'s machine is @f[ME.CS.CMU.EDU], and
+he wants want to run a slave on @f[SLAVE.CS.CMU.EDU], then he should use the
+@hid[Accept Slave Connections] command, telnet to the machine, and invoke Lisp
+supplying @f[-slave] and the editor's name.  The command displays the editor's
+name.
+@end[description]
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/mail.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/mail.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/mail.mss	(revision 13309)
@@ -0,0 +1,1343 @@
+@comment{-*- Dictionary: /afs/cs/project/clisp/scribe/hem/hem; Mode: spell; Package: Hemlock -*-}
+@chap[The Mail Interface]
+@section[Introduction to Mail in Hemlock]
+
+@index[MH interface]@label[introduction]
+@hemlock provides an electronic mail handling facility via an interface to the
+public domain @i[Rand MH Message Handling System].  This chapter assumes that
+the user is familiar with the basic features and operation of @mh, but it
+attempts to make allowances for beginners.  Later sections of this chapter
+discuss setting up @mh, profile components and special files for formatting
+outgoing mail headers, and backing up protected mail directories on a
+workstation.  For more information on @mh, see the @i[Rand MH Message Handling
+System Tutorial] and the @i[Rand MH Message Handling System Manual].
+
+The @hemlock interface to @mh provides a means for generating header (@f[scan])
+lines for messages and displaying these headers in a @hid[Headers] buffer.
+This allows the user to operate on the @i[current message] as indicated by the
+position of the cursor in the @hid[Headers] buffer.  The user can read, reply
+to, forward, refile, or perform various other operations on the current
+message.  A user typically generates a @hid[Headers] buffer with the commands
+@hid[Message Headers] or @hid[Incorporate and Read New Mail], and multiple such
+buffers may exist simultaneously.
+
+Reading a message places its text in a @hid[Message] buffer.  In a manner
+similar to a @hid[Headers] buffer, this allows the user to operate on that
+message.  Most @hid[Headers] buffer commands behave the same in a @hid[Message]
+buffer.  For example, the @hid[Reply to Message] command has the same effect in
+both @hid[Headers] mode and @hid[Message] mode.  It creates a @hid[Draft]
+buffer and makes it the current buffer so that the user may type a reply to the
+current message.
+
+The @hid[Send Message] command originates outgoing mail.  It generates a
+@hid[Draft] buffer in which the user composes a mail message.  Each @hid[Draft]
+buffer has an associated pathname, so the user can save the buffer to a file as
+necessary.  Invoking @hid[Send Message] in a @hid[Headers] or @hid[Message]
+buffer associates the @hid[Draft] buffer with a @hid[Message] buffer.  This
+allows the user to easily refer to the message being replied to with the
+command @hid[Goto Message Buffer].  After the user composes a draft message, he
+can deliver the message by invoking the @hid[Deliver Message] command in the
+@hid[Draft] buffer (which deletes both the this buffer and any associated
+@hid[Message] buffer), or he can delay this action.  Invoking @hid[Deliver
+Message] when not in a @hid[Draft] buffer causes it to prompt for a draft
+message ID, allowing previously composed and saved messages to be delivered
+(even across distinct Lisp invocations).
+
+@index[virtual message deletion]
+The @hemlock mail system provides a mechanism for @i[virtual message deletion].
+That is, the @hid[Delete Message] command does not immediately delete a message
+but merely flags the message for future deletion.  This allows the user to
+undelete the messages with the @hid[Undelete Message] command.  The
+@hid[Expunge Messages] command actually removes messages flagged for deletion.
+After expunging a deleted message, @hid[Undelete Messages] can no longer
+retrieve it.  Commands that read messages by sequencing through a @hid[Headers]
+buffer typically ignore those marked for deletion, which makes for more fluid
+reading if a first pass has been made to delete uninteresting messages.
+
+After handling messages in a @hid[Headers] buffer, there may be messages
+flagged for deletion and possibly multiple @hid[Message] buffers lying around.
+There is a variety of commands that help @i[terminate] a mail session.
+@hid[Expunge Messages] will flush the messages to be deleted, leaving the
+buffer in an updated state.  @hid[Delete Headers Buffer and Message Buffers]
+will delete the @hid[Headers] buffer and its corresponding @hid[Message]
+buffers.  @hid[Quit Headers] is a combination of these two commands in that it
+first expunges messages and then deletes all the appropriate buffers.
+
+One does not have to operate only on messages represented in a @hid[Headers]
+buffer.  This is merely the nominal mode of interaction.  There are commands
+that prompt for a folder, an @mh message specification (for example, "@f[1 3 6
+last]", "@f[1-3 5 6]", "@f[all]", "@f[unseen]"), and possibly a @f[pick]
+expression.  @f[Pick] expressions allow messages to be selected based on header
+field pattern matching, body text searching, and date comparisons; these can be
+specified using either a Unix shell-like/switch notation or a Lisp syntax,
+according to one's preference.  See section @ref[scanning] for more details.
+
+A @i[mail-drop] is a file where a Unix-based mail system stores all messages a
+user receives.  The user's mail handling program then fetches these from the
+mail-drop, allowing the user to operate on them.  Traditionally one locates his
+mail-drop and mail directory on a mainframe machine because the information on
+mainframes is backed up on magnetic tape at least once per day.  Since @hemlock
+only runs under CMU @clisp on workstations, and one's mail directory is not
+usually world writable, it is not possible to adhere to a standard arrangement.
+Since @mh provides for a remote mail-drop, and CMU's Remote File System has a
+feature allowing authentication across a local area network, one can use
+@hemlock to fetch his mail from a mainframe mail-drop (where it is backed up
+before @hemlock grabs it) and store it on his workstation.  Reading mail on a
+workstation is often much faster and more comfortable because typically it is a
+single user machine.  Section @ref[backing-up] describes how to back up one's
+mail directory from a workstation to a mainframe.
+
+
+@section[Constraints on MH to use Hemlock's Interface]
+
+@index[constraints for mail interface]@label[constraints]
+There are a couple constaints placed on the user of the @hemlock interface to
+@mh.  The first is that there must be a draft folder specified in one's @mh
+profile to use any command that sends mail.  Also, to read new mail, there must
+be an @f[Unseen-Sequence:] component in one's @mh profile.  The default @mh
+profile does not specify these components, so they must be added by the user.
+The next section of this chapter describes how to add these components.
+Another constraint is that @hemlock requires its own @f[scan] line format to
+display headers lines in a @hid[Headers] buffer.  See the description of the
+variable @hid[MH Scan Line Form] for details.
+
+
+@section[Setting up MH]
+
+@index[setting up the mail interface]@label[setting-up]
+@index[mail profile]@index[MH profile]
+Get an @mh default profile and mail directory by executing the @mh @f[folder]
+utility in a Unix shell.  When it asks if it should make the "@f[inbox]"
+folder, answer "@b[yes]".  This creates a file called "@f[.mh_profile]" in the
+user's home directory and a directory named "@f[Mail]".
+
+Edit the "@f[.mh_profile]" file inserting two additional lines.  To send mail
+in @hemlock, the user must indicate a draft folder by adding a
+@f[Draft-Folder:] line with a draft folder name @dash "@f[drafts]" is a common
+name:
+@begin[example]
+Draft-Folder: drafts
+@end[example]
+
+Since the mail-drop exists on a remote machine, the following line must
+also be added:
+@begin[example]
+MailDrop: /../<hostname>/usr/spool/mail/<username>
+@end[example]
+
+Since the user's mail-drop is on a separate machine from his mail directory
+(and where the user runs @hemlock), it is necessary to issue the following
+command from the Unix shell (on the workstation).  This only needs to be done
+once.
+@begin[programexample]
+/usr/cs/etc/rfslink -host <hostname> /usr/spool/mail/<username>
+@end[programexample]
+Note that @b[<hostname>] is not a full ARPANET domain-style name.  Use an
+abbreviated CMU host name (for example, "@b[spice]" not
+"@b[spice.cs.cmu.edu]").
+
+
+@section[Profile Components and Customized Files]
+
+@subsection[Profile Components]
+
+@label[Profile] 
+The following are short descriptions about profile components that are either
+necessary to using @hemlock@comment{}'s interface to @mh or convenient for using @mh in
+general:
+
+@begin[description]
+@f[Path:]@\
+This specifies the user's mail directory.  It can be either a full pathname or
+a pathname relative to the user's home directory.  This component is
+@i[necessary] for using @mh.
+
+@f[MailDrop:]@\
+This is used to specify one's remote mail-drop.  It is @i[necessary] for
+@hemlock only when using a mail-drop other than "@f[/usr/spool/mail/<user>]" on
+the local machine.
+
+@f[Folder-Protect:], @f[Msg-Protect:]@\
+These are set to 700 and 600 respectively to keep others from reading one's
+mail.  At one time the default values were set for public visibility of mail
+folders.  Though this is no longer true, these can be set for certainty.  The
+700 protection allows only user read, write, and execute (list access for
+directories), and 600 allows only user read and write.  These are not necessary
+for either @mh or the @hemlock interface.
+
+@f[Unseen-Sequence:]@\
+When mail is incorporated, new messages are added to this sequence, and as
+these messages are read they are removed from it.  This allows the user at any
+time to invoke an @mh program on all the unseen messges of a folder easily.  An
+example definition is:
+@begin[example]
+Unseen-Sequence: unseen
+@end[example]
+Specifying an unseen-sequence is @i[necessary] to use @hemlock@comment{}'s
+interface to @mh.
+
+@f[Alternate-Mailboxes:]@\
+This is not necessary for either @mh or the @hemlock interface.  This
+component tells @mh which addresses that it should recognize as the user.  This
+is used for @f[scan] output formatting when the mail was sent by the user.  It
+is also used by @f[repl] when it sets up headers to know who the user is for
+inclusion or exclusion from @b[cc]: lists.  This is case sensitive and takes
+wildcards.  One example is:
+@begin[example]
+Alternate-Mailboxes: *FRED*, *Fred*, *fred*
+@end[example]
+
+@f[Draft-Folder:]@\
+This makes multiple draft creation possible and trivial to use.  Just supply a
+folder name (for example, "@f[drafts]").  Specifying a draft-folder is
+@i[necessary] to use @hemlock@comment{}'s interface to @mh.
+
+@f[repl: -cc all -nocc me -fcc out-copy]@\
+This tells the @f[repl] utility to include everyone but the user in the
+@b[cc:] list when replying to mail.  It also makes @f[repl] keep an copy of the
+message the user sends.  This is mentioned because one probably wants to reply
+to everyone receiving a piece of mail except oneself.  Unlike other utilities
+that send mail, @f[repl] stores personal copies of outgoing mail based on a
+command line switch.  Other @mh utilities use different mechanisms.  This line
+is not necessary to use either @mh or the @hemlock interface.
+
+@f[rmmproc: /usr/cs/bin/rm]@\
+This is not necessary to use @hemlock@comment{}'s interface to @mh, but due to
+@hemlock@comment{}'s virtual message deletion feature, this causes messages to be deleted
+from folder directories in a cleaner fashion when they actually get removed.
+Note that setting this makes @f[rmm] more treacherous if used in the Unix
+shell.
+@end[description]
+@;
+
+
+@subsection[Components Files]
+@index[components]
+@label[components-files]
+@i[Components] files are templates for outgoing mail header fields that specify
+position and sometimes values for specified fields.  Example files are shown
+for each one discussed here.  These should exist in the user's mail directory.
+
+For originating mail there is a components file named "@f[components]", and it
+is used by the @mh utility @f[comp].  An example follows:
+@begin[example]
+   To: 
+   cc: 
+   fcc: out-copy
+   Subject: 
+   --------
+@end[example]
+This example file differs from the default by including the @f[fcc:] line.
+This causes @mh to keep a copy of the outgoing draft message.  Also, though it
+isn't visible here, the @f[To:], @f[cc:], and @f[Subject:] lines have a space
+at the end.
+
+@index[forwarding components]
+The "@f[forwcomps]" components file is a template for the header fields of any
+forwarded message.  Though it may be different, our example is the same as the
+previous one.  These are distinct files for @mh@comment{}'s purposes, and it is more
+flexible since the user might not want to keep copies of forwarded messages.
+
+@index[reply components]
+The "@f[replcomps]" components file is a template for the header fields of any
+draft message composed when replying to a message.  An example
+follows:
+@begin[example]
+   %(lit)%(formataddr %<{reply-to}%|%<{from}%|%{sender}%>%>)\
+   %<(nonnull)%(void(width))%(putaddr To: )\n%>\
+   %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\
+   %(formataddr{resent-to})\
+   %<(nonnull)%(void(width))%(putaddr cc: )\n%>\
+   %<{fcc}Fcc: %{fcc}\n%>\
+   %<{subject}Subject: Re: %{subject}\n%>\
+   %<{date}In-reply-to: Your message of \
+   %<(nodate{date})%{date}%|%(tws{date})%>.%<{message-id}
+		%{message-id}%>\n%>\
+   --------
+@end[example]
+This example file differs from the default by including the @b[resent-to:]
+field (in addition to the @b[to:] and @b[cc:] fields) of the message being
+replied to in the @b[cc:] field of the draft.  This is necessary for replying
+to all recipients of a distributed message.  Keeping a copy of the outgoing
+draft message works a little differently with reply components.  @mh expects a
+switch which the user can put in his profile (see section @ref[Profile] of this
+chapter), and using the @mh formatting language, this file tests for the
+@f[fcc] value as does the standard file.
+
+
+@section[Backing up the Mail Directory]
+@index[backing up mail directories]
+@label[backing-up]
+The easiest method of backing up a protected mail directory is to copy it into
+an Andrew File System (AFS) directory since these are backed up daily as with
+mainframes.  The only problem with this is that the file servers may be down
+when one wants to copy his mail directory since, at the time of this writing,
+these servers are still under active development; however, they are becoming
+more robust daily.  One can read about the current AFS status in the file
+@f[/../fac/usr/gripe/doc/vice/status].
+
+Using AFS, one could keep his actual mail directory (not a copy thereof) in his
+AFS home directory which eliminates the issue of backing it up.  This is
+additionally beneficial if the user does not use the same workstation everyday
+(that is, he does not have his own but shares project owned machines).  Two
+problems with this arrangement result from the AFS being a distributed file
+system.  Besides the chance that the server will be down when the user wants to
+read mail, performance degrades since messages must always be referenced across
+the local area network.
+
+Facilities' official mechanism for backing up protected directories is called
+@f[sup].  This is awkward to use and hard to set up, but a subsection here
+describes a particular arrangement suitable for the user's mail directory.
+
+
+@subsection[Andrew File System]
+If the user choses to use AFS, he should get copies of @i[Getting Started with
+the Andrew File System] and @i[Protecting AFS files and directories].  To use
+AFS, send mail to Gripe requesting an account.  When Gripe replies with a
+password, change it to be the same as the account's password on the
+workstation.  This causes the user to be authenticated into AFS when he logs
+into his workstation (that is, he is automatically logged into his AFS
+account).  To change the password, first log into the AFS account:
+@begin[programexample]
+log <AFS userid>
+@end[programexample]
+Then issue the @f[vpasswd] command.
+
+All of the example command lines in this section assume the user has
+@f[/usr/misc/bin] on his Unix shell @f[PATH] environment variable.
+
+@paragraph[Copy into AFS:]
+
+Make an AFS directory to copy into:
+@begin[programexample]
+mkdir /afs/cs.cmu.edu/user/<AFS userid>/mail-backup
+@end[programexample]
+
+This will be readable by everyone, so protect it with the following:
+@begin[programexample]
+fs sa /afs/cs.cmu.edu/user/<AFSuserid>/mail-backup System:AnyUser none
+@end[programexample]
+
+Once the AFS account and directory to backup into have been established, the
+user needs a means to recursively copy his mail directory updating only those
+file that have changed and deleting those that no longer exist.  To do this,
+issue the following command:
+@begin[programexample]
+copy -2 -v -R <mail directory> <AFS backup directory>
+@end[programexample]
+Do not terminate either of these directory specifications with a @f[/].  The
+@f[-v] switch causes @f[copy] to output a line for copy and deletion, so this
+may be eliminated if the user desires.
+
+@paragraph[Mail Directory Lives in AFS:]
+
+Assuming the AFS account has been established, and the user has followed the
+directions in @ref[setting-up], now make an AFS directory to serve as the mail
+directory:
+@begin[programexample]
+mkdir /afs/cs.cmu.edu/user/<AFS userid>/Mail
+@end[programexample]
+
+This will be readable by everyone, so protect it with the following:
+@begin[programexample]
+fs sa /afs/cs.cmu.edu/user/<AFSuserid>/Mail System:AnyUser none
+@end[programexample]
+
+Tell @mh where the mail directory is by modifying the profile's
+"@f[.mh_profile]" (see section @ref[setting-up]) @f[Path:] component (see
+section @ref[Profile]):
+@begin[programexample]
+Path: /afs/cs.cmu.edu/user/<AFS userid>/Mail
+@end[programexample]
+
+
+@subsection[Sup to a Mainframe]
+To use @f[sup] the user must set up a directory named "@f[sup]" on the
+workstation in the user's home directory.  This contains different directories
+for the various trees that will be backed up, so there will be a "@f[Mail]"
+directory.  This directory will contain two files: "@f[crypt]" and "@f[list]".
+The "@f[crypt]" file contains one line, terminated with a new line, that
+contains a single word @dash an encryption key.  "@f[list]" contains one line,
+terminated with a new line, that contains two words @dash "@b[upgrade Mail]".
+
+On the user's mainframe, a file must be created that will be supplied to the
+@f[sup] program.  It should contain the following line to backup the mail
+directory:
+
+@begin[example]
+Mail delete host=<workstation> hostbase=/usr/<user> base=/usr/<user> \
+crypt=WordInCryptFile login=<user> password=LoginPasswordOnWorkstation
+@end[example]
+Warning: @i[This file contains the user's password and should be
+protected appropriately.] 
+
+The following Unix shell command issued on the mainframe will backup the
+mail directory:
+
+@begin[programexample]
+   sup <name of the sup file used in previous paragraph>
+@end[programexample]
+
+As a specific example, assume user "@f[fred]" has a workstation called
+"@f[fred]", and his mainframe is the "@f[gpa]" machine where he has another
+user account named "@f[fred]".  The password on his workstation is
+"@f[purple]".  On his workstation, he creates the directory
+"@f[/usr/fred/sup/Mail/]" with the two files "@f[crypt]" and "@f[list]".
+The file "@f[/usr/fred/sup/Mail/crypt]" contains only the encryption key:
+@programexample[steppenwolf]
+The file "@f[/usr/fred/sup/Mail/list]" contains the command to upgrade the
+"@f[Mail]" directory:
+@programexample[upgrade Mail]
+
+On the "@f[gpa]" machine, the file "@f[/usr/fred/supfile]" contains the
+following line:
+@begin[programexample]
+Mail delete host=fred hostbase=/usr/fred base=/usr/fred \
+crypt=steppenwolf login=fred password=purple
+@end[programexample]
+This file is protected on "@f[gpa]", so others cannot see @f[fred's] password
+on his workstation.
+
+On the gpa-vax, issuing
+@begin[programexample]
+   sup /usr/fred/supfile
+@end[programexample]
+to the Unix shell will update the @mh mail directory from @f[fred's]
+workstation deleting any files that exist on the gpa that do not exist on the
+workstation.
+
+For a more complete description of the features of @f[sup], see the @i[UNIX
+Workstation Owner's Guide] and @i[The SUP Software Upgrade Protocol].
+
+@section[Introduction to Commands and Variables]
+
+@index[mail commands]@index[mail variables]@label[mhcommands]
+Unless otherwise specified, any command which prompts for a folder name will
+offer the user a default.  Usually this is @mh@comment{}'s idea of the current folder,
+but sometimes it is the folder name associated with the current buffer if there
+is one.  When prompting for a message, any valid @mh message expression may be
+entered (for example, "@f[1 3 6]", "@f[1-3 5 6]", "@f[unseen]", "@f[all]").
+Unless otherwise specified, a default will be offered (usually the current
+message).
+
+Some commands mention specific @mh utilities, so the user knows how the
+@hemlock command affects the state of @mh and what profile components and
+special formatting files will be used.  @hemlock runs the @mh utility programs
+from a directory indicated by the following variable:
+
+@defhvar[var "MH Utility Pathname", val {"/usr/misc/.mh/bin/"}]
+@mh utility names are merged with this pathname to find the executable
+files. 
+@enddefhvar
+
+
+@section[Scanning and Picking Messages]
+@label[scanning]
+As pointed out in the introduction of this chapter, users typically generate
+headers or @f[scan] listings of messages with @hid[Message Headers], using
+commands that operate on the messages represented by the headers.  @hid[Pick
+Headers] (bound to @bf[h] in @hid[Headers] mode) can be used to narrow down (or
+further select over) the headers in the buffer.
+
+A @f[pick] expression may be entered using either a Lisp syntax or a Unix
+shell-like/switch notation as described in the @mh documentation.  The Lisp
+syntax is as follows:
+
+@begin[example]
+   <exp>       ::=  {(not <exp>) | (and <exp>*) | (or <exp>*)
+		    | (cc <pattern>) | (date <pattern>)
+		    | (from <pattern>) | (search <pattern>)
+		    | (subject <pattern>) | (to <pattern>)
+		    | (-- <component> <pattern>)
+		    | (before <date>) | (after <date>)
+		    | (datefield <field>)}
+
+   <pattern>   ::=  {<string> | <symbol>}
+
+   <component> ::=  {<string> | <symbol>}
+
+   <date>      ::=  {<string> | <symbol> | <number>}
+
+   <field>     ::=  <string>
+@end[example]
+
+Anywhere the user enters a @f[<symbol>], its symbol name is used as a string.
+Since @hemlock @f[read]s the expression without evaluating it, single quotes
+("@bf[']") are unnecessary.  From the @mh documentation,
+
+@begin[itemize]
+   A @f[<pattern>] is a Unix @f[ed] regular expression.  When using a string to
+   input these, remember that @f[\] is an escape character in Common Lisp.
+
+   A @f[<component>] is a header field name (for example, @b[reply-to] or
+   @b[resent-to]).
+
+   A @f[<date>] is an @i[822]-style specification, a day of the week,
+   "@b[today]", "@b[yesterday]", "@b[tomorrow]", or a number indicating @i[n]
+   days ago.  The @i[822] standard is basically:
+   @begin[example]
+   dd mmm yy hh:mm:ss zzz
+   @end[example]
+   which is a two digit day, three letter month (first letter capitalized), two
+   digit year, two digit hour (@f[00] through @f[23]), two digit minute, two
+   digit second (this is optional), and a three letter zone (all capitalized).
+   For
+   example:
+   @begin[example]
+   21 Mar 88 16:00 EST
+   @end[example]
+   
+   A @f[<field>] is an alternate @f[Date:] field to use with @f[(before
+   <date>)] and @f[(after <date>)] such as @f[BB-Posted:] or
+   @f[Delivery-Date:].
+
+   Using @f[(before <date>)] and @f[(after <date>)] causes date field parsing,
+   while @f[(date <pattern>)] does string pattern matching.
+@end[itemize]
+
+Since a @f[<pattern>] may be a symbol or string, it should be noted that the
+symbol name is probably all uppercase characters, and @mh will match these
+only against upper case.  @mh will match lowercase characters against lower
+and upper case.  Some examples are:
+@begin[example]
+   ;;; All messages to Gripe.
+   (to "gripe")
+
+   ;;; All messages to Gripe or about Hemlock.
+   (or (to "gripe") (subject "hemlock"))
+
+   ;;; All messages to Gripe with "Hemlock" in the body.
+   (and (to "gripe") (search "hemlock"))
+@end[example]
+
+Matching of @f[<component>] fields is case sensitive, so this example will
+@f[pick] over all messages that have been replied to.
+@example[(or (-- "replied" "") (-- "Replied" ""))]
+
+
+@defhvar[var "MH Scan Line Form", val {"library:mh-scan"}]
+This is a pathname of a file containing an @mh format expression used for
+header lines.
+
+The header line format must display the message ID as the first non-whitespace
+item.  If the user uses the virtual message deletion feature which is on by
+default, there must be a space three characters to the right of the message ID.
+This location is used on header lines to note that a message is flagged for
+deletion.  The second space after the message ID is used for notating answered
+or replied-to messages.
+@enddefhvar
+
+@defcom[com "Message Headers", bind (C-x r)]
+This command prompts for a folder, message (defaulting to "@b[all]"), and an
+optional @f[pick] expression.  Typically this will simply be used to generate
+headers for an entire folder or sequence, and the @f[pick] expression will not
+be used.  A new @hid[Headers] buffer is made, and the output of @f[scan] on the
+messages indicated is inserted into the buffer.  The current window is used,
+the buffer's point is moved to the first header, and the @hid[Headers] buffer
+becomes current.  The current value of the @hemlock @hid[Fill Column] variable
+is supplied to @f[scan] as the @f[-width] switch.  The buffer name is set to a
+string of the form @w<"@f[Headers <folder> <msgs> <pick expression>]">, so the
+modeline will show what is in the buffer.  If no @f[pick] expression was
+supplied, none will be shown in the buffer's name.  As described in the
+introduction to this section, the expression may be entered using either a Lisp
+syntax or a Unix shell-like/switch notation.
+@enddefcom
+
+@defhvar[var "MH Lisp Expression", val {t}]
+When this is set, @mh expression prompts are read in a Lisp syntax.  Otherwise,
+the input is of the form of a Unix shell-like/switch notation as described in
+the @mh documentation.
+@enddefhvar
+
+@defcom[com "Pick Headers", stuff (bound to @bf[h] in @hid[Headers] mode) ]
+This command is only valid in a @hid[Headers] buffer.  It prompts for a
+@f[pick] expression, and the messages shown in the buffer are supplied to
+@f[pick] with the expression.  The resulting messages are @f[scan]'ed, deleting
+the previous contents of the buffer.  The current value of @hid[Fill Column] is
+used for the @f[scan]'ing.  The buffer's point is moved to the first header.
+The buffer's name is set to a string of the form @w<"@f[Headers <folder> <msgs
+picked over> <pick expression>]">, so the modeline will show what is in the
+buffer.  As described in the introduction to this section, the expression may
+be entered using either a Lisp syntax or a Unix shell-like/switch notation.
+@enddefcom
+
+@defcom[com "Headers Help", bind (Headers: ?)]
+This command displays documentation on @hid[Headers] mode.
+@enddefcom
+
+
+@section[Reading New Mail]
+
+@index[reading new mail]@label[reading-new-mail]
+
+@defcom[com "Incorporate and Read New Mail", stuff (bound to @bf[C-x i] globally and @bf[i] in @hid[Headers] and @hid[Message] modes) ]
+This command incorporates new mail into @hid[New Mail Folder] and creates a
+@hid[Headers] buffer with the new messages.  An unseen-sequence must be define
+in the user's @mh profile to use this.  Any headers generated due to
+@hid[Unseen Headers Message Spec] are inserted as well.  The buffer's point is
+positioned on the headers line representing the first unseen message of the
+newly incorporated mail.
+@enddefcom
+
+@defcom[com "Incorporate New Mail" ]
+This command incorporates new mail into @hid[New Mail Folder], displaying
+@f[inc] output in a pop-up window.  This is similar to @hid[Incorporate and
+Read New Mail] except that no @hid[Headers] buffer is generated.
+@enddefcom
+
+@defhvar[var "New Mail Folder", val {"+inbox"}]
+This is the folder into which @mh incorporates new mail.
+@enddefhvar
+
+@defhvar[var "Unseen Headers Message Spec", val {nil}]
+This is an @mh message specification that is suitable for any message prompt.
+When incorporating new mail and after expunging messages, @hemlock uses this
+specification in addition to the unseen-sequence name that is taken from the
+user's @mh profile to generate headers for the unseen @hid[Headers] buffer.
+This value is a string.
+@enddefhvar
+
+@defhvar[var "Incorporate New Mail Hook", val {nil}]
+This is a list of functions which are invoked immediately after new mail is
+incorporated.  The functions should take no arguments.
+@enddefhvar
+
+@defhvar[var "Store Password", val {nil}]
+When this is set, the user is only prompted once for his password, and the
+password is stored for future use.
+@enddefhvar
+
+@defhvar[var "Authenticate Incorporation", val {nil}]
+@defhvar1[var "Authentication User Name", val {nil}]
+When @hid[Authenticate Incorporation] is set, incorporating new mail prompts
+for a password to access a remote mail-drop.
+
+When incorporating new mail accesses a remote mail-drop, @hid[Authentication
+User Name] is the user name supplied for authentication on the remote machine.
+If this is @nil, @hemlock uses the local name.
+@enddefhvar
+
+
+@section[Reading Messages]
+@index[reading messages]
+@label[reading-messages]
+This section describes basic commands that show the current, next, and previous
+messages, as well as a couple advanced commands.  @hid[Show Message] (bound to
+@bf[SPACE] in @hid[Headers] mode) will display the message represented by the
+@f[scan] line the @hemlock cursor is on.  Deleted messages are considered
+special, and the more conveniently bound commands for viewing the next and
+previous messages (@hid[Next Undeleted Message] bound to @bf[n] and
+@hid[Previous Undeleted Message] bound to @bf[p], both in @hid[Headers] and
+@hid[Message] modes) will ignore them.  @hid[Next Message] and @hid[Previous
+Message] (bound to @bf[M-n] and @bf[M-p] in @hid[Headers] and @hid[Message]
+modes) may be invoked if reading a message is desired regardless of whether it
+has been deleted.
+
+
+@defcom[com "Show Message", stuff (bound to @bf[SPACE] and @bf[.] in @hid[Headers] mode) ]
+ This command, when invoked in a @hid[Headers] buffer, displays the current
+message (the message the cursor is on), by replacing any previous message that
+has not been preserved with @hid[Keep Message].  The current message is also
+removed from the unseen sequence.  The @hid[Message] buffer becomes the current
+buffer using the current window.  The buffer's point will be moved to the
+beginning of the buffer, and the buffer's name will be set to a string of the
+form @w<"@f[Message <folder> <msg-id>]">.
+
+The @hid[Message] buffer is read-only and may not be modified.  The command
+@hid[Goto Headers Buffer] issued in the @hid[Message] buffer makes the
+associated @hid[Headers] buffer current.
+
+When not in a @hid[Headers] buffer, this command prompts for a folder and
+message.  A unique @hid[Message] buffer is obtained, and its name is set to a
+string of the form @w<"@f[Message <folder> <msg-id>]">.  The buffer's point is
+moved to the beginning of the buffer, and the current window is used to display
+the message.
+
+Specifying multiple messages inserts all the messages into the same buffer.  If
+the user wishes to show more than one message, it is expected that he will
+generate a @hid[headers] buffer with the intended messages, and then use the
+message sequencing commands described below.
+@enddefcom
+
+@defcom[com "Next Message", stuff (bound to @bf[M-n] in @hid[Headers] and @hid[Message] modes) ]
+ This command is only meaningful in a @hid[Headers] buffer or a @hid[Message]
+buffer associated with a @hid[Headers] buffer.  In a @hid[Headers] buffer, the
+point is moved to the next message, and if there is one, it is shown as
+described in the @hid[Show Message] command.
+
+In a @hid[Message] buffer, the message after the currently visible message is
+displayed.  This clobbers the buffer's contents.  Note, if the @hid[Message]
+buffer is associated with a @hid[Draft] buffer, invoking this command breaks
+that association.  Using @hid[Keep Message] preserves the @hid[Message] buffer
+and any association with a @hid[Draft] buffer.
+
+The @hid[Message] buffer's name is set as described in the @hid[Show Message]
+command.
+@enddefcom
+
+@defcom[com "Previous Message", stuff (bound to @bf[M-p] in @hid[Headers] and @hid[Message] modes) ]
+ This command is only meaningful in a @hid[Headers] buffer or a @hid[Message]
+buffer associated with a @hid[Headers] buffer.  In a @hid[Headers] buffer, the
+point is moved to the previous message, and if there is one, it is shown as
+described in the @hid[Show Message] command.
+
+In a @hid[Message] buffer, the message before the currently visible message is
+displayed.  This clobbers the buffer's contents.  Note, if the @hid[Message]
+buffer is associated with a @hid[Draft] buffer, invoking this command breaks
+that association.  Using @hid[Keep Message] preserves the @hid[Message] buffer
+and any association with a @hid[Draft] buffer.
+
+The @hid[Message] buffer's name is set as described in the @hid[Show Message]
+command.
+@enddefcom
+
+@defcom[com "Next Undeleted Message", stuff (bound to @bf[n] in @hid[Headers] and @hid[Message] modes) ]
+ This command is only meaningful in a @hid[Headers] buffer or a @hid[Message]
+buffer associated with a @hid[Headers] buffer.  In a @hid[Headers] buffer, the
+point is moved to the next undeleted message, and if there is one, it is shown
+as described in the @hid[Show Message] command.
+
+In a @hid[Message] buffer, the first undeleted message after the currently
+visible message is displayed.  This clobbers the buffer's contents.  Note, if
+the @hid[Message] buffer is associated with a @hid[Draft] buffer, invoking this
+command breaks that association.  The @hid[Keep Message] command preserves the
+@hid[Message] buffer and any association with a @hid[Draft] buffer.
+
+The @hid[Message] buffer's name is set as described in the @hid[Show Message]
+command.
+@enddefcom
+
+@defcom[com "Previous Undeleted Message", stuff (bound to @bf[p] in @hid[Headers] and @hid[Message] modes) ]
+ This command is only meaningful in a @hid[Headers] buffer or a @hid[Message]
+buffer associated with a @hid[Headers] buffer.  In a @hid[Headers] buffer, the
+point is moved to the previous undeleted message, and if there is one, it is
+shown as described in the @hid[Show Message] command.
+
+In a @hid[Message] buffer, the first undeleted message before the currently
+visible message is displayed.  This clobbers the buffer's contents.  Note, if
+the @hid[Message] buffer is associated with a @hid[Draft] buffer, invoking this
+command breaks that association.  The @hid[Keep Message] command preserves the
+@hid[Message] buffer and any association with a @hid[Draft] buffer.
+
+The @hid[Message] buffer's name is set as described in the @hid[Show Message]
+command.
+@enddefcom
+
+@defcom[com "Scroll Message", stuff (bound to @bf[SPACE] and @bf[C-v] in @hid[Message] mode) ]
+@defhvar1[var "Scroll Message Showing Next", val {t}]
+ This command scrolls the current window down through the current message.  If
+the end of the message is visible and @hid[Scroll Message Showing Next] is not
+@nil, then show the next undeleted message.
+@enddefcom
+
+@defcom[com "Keep Message" ]
+This command can only be invoked in a @hid[Message] buffer.  It causes the
+@hid[Message] buffer to continue to exist when the user invokes commands to
+view other messages either within the kept @hid[Message] buffer or its
+associated @hid[Headers] buffer.  This is useful for getting two messages into
+different buffers.  It is also useful for retaining @hid[Message] buffers which
+would otherwise be deleted when an associated draft message is delivered.
+@enddefcom
+
+@defcom[com "Message Help", bind (Message: ?)]
+This command displays documentation on @hid[Message] mode.
+@enddefcom
+
+
+@section[Sending Messages]
+@index[sending messages]
+@label[sending-messages]
+The most useful commands for sending mail are @hid[Send Message] (bound to
+@bf[m] and @bf[s] in @hid[Headers] and @hid[Message] modes), @hid[Reply to
+Message] (bound to @bf[r] in @hid[Headers] mode), and @hid[Reply to Message in
+Other Window] (bound to @bf[r] in @hid[Message] mode).  These commands set up a
+@hid[Draft] buffer and associate a @hid[Message] buffer with the draft when
+possible.  To actually deliver the message to its recipient(s), use
+@hid[Deliver Message] (bound to @bf[H-s] in @hid[Draft] mode).  To abort
+sending mail, use @hid[Delete Draft and Buffer] (bound to @bf[H-q] in
+@hid[Draft] mode).  If one wants to temporarily stop composing a draft with the
+intention of finishing it later, then the @hid[Save File] command (bound to
+@bf[C-x C-s]) will save the draft to the user's draft folder.
+
+@hid[Draft] buffers have a special @hemlock minor mode called @hid[Draft] mode.
+The major mode of a @hid[Draft] buffer is taken from the @hid[Default Modes]
+variable.  The user may wish to arrange that @hid[Text] mode (and possibly
+@hid[Fill] mode or @hid[Save] mode) be turned on whenever @hid[Draft] mode is
+set.  For a further description of how to manipulate modes in @hemlock see the
+@i[Hemlock Command Implementor's Manual].
+
+
+@defcom[com "Send Message", stuff (bound to @bf[s] and @bf[m] in @hid[Headers] and @hid[Message] modes and @bf[C-x m] globally) ]
+ This command, when invoked in a @hid[Headers] buffer, creates a unique
+@hid[Draft] buffer and a unique @hid[Message] buffer.  The current message is
+inserted in the @hid[Message] buffer, and the @hid[Draft] buffer is displayed
+in the current window.  The @hid[Draft] buffer's point is moved to the end of
+the line containing @f[To:] if it exists.  The name of the draft message file
+is used to produce the buffer's name.  A pathname is associated with the
+@hid[Draft] buffer so that @hid[Save File] can be used to incrementally save a
+composition before delivering it.  The @f[comp] utility will be used to
+allocate a draft message in the user's @mh draft folder and to insert the
+proper header components into the draft message.  Both the @hid[Draft] and
+@hid[Message] buffers are associated with the @hid[Headers] buffer, and the
+@hid[Draft] buffer is associated with the @hid[Message] buffer.
+
+When invoked in a @hid[Message] buffer, a unique @hid[Draft] buffer is created,
+and these two buffers are associated.  If the @hid[Message] buffer is
+associated with a @hid[Headers] buffer, this association is propagated to the
+@hid[Draft] buffer.  Showing other messages while in this @hid[Headers] buffer
+will not affect this @hid[Message] buffer.
+
+When not in a @hid[Headers] or @hid[Message] buffer, this command does the same
+thing as described in the previous two cases, but there are no @hid[Message] or
+@hid[Headers] buffer manipulations.
+
+@hid[Deliver Message] will deliver the draft to its intended recipient(s).
+
+The @hid[Goto Headers Buffer] command, when invoked in a @hid[Draft] or
+@hid[Message] buffer, makes the associated @hid[Headers] buffer current.  The
+@hid[Goto Message Buffer] command, when invoked in a @hid[Draft] buffer, makes
+the associated @hid[Message] buffer current.
+@enddefcom
+
+@defcom[com "Reply to Message", stuff (bound to @bf[r] in @hid[Headers] mode) ]
+@defcom1[com "Reply to Message in Other Window", stuff (bound to @bf[r] in @hid[Message] mode) ]
+@defhvar1[var "Reply to Message Prefix Action"]
+ @hid[Reply to Message], when invoked in a @hid[Headers] buffer, creates a
+unique @hid[Draft] buffer and a unique @hid[Message] buffer.  The current
+message is inserted in the @hid[Message] buffer, and the @hid[Draft] buffer is
+displayed in the current window.  The draft components are set up in reply to
+the message, and the @hid[Draft] buffer's point is moved to the end of the
+buffer.  The name of the draft message file is used to produce the buffer's
+name.  A pathname is associated with the @hid[Draft] buffer so that @hid[Save
+File] can be used to incrementally save a composition before delivering it.
+The @f[repl] utility will be used to allocate a draft message file in the
+user's @mh draft folder and to insert the proper header components into the
+draft message.  Both the @hid[Draft] and @hid[Message] buffers are associated
+with the @hid[Headers] buffer, and the @hid[Draft] buffer is associated with
+the @hid[Message] buffer.
+
+When invoked in a @hid[Message] buffer, a unique @hid[Draft] buffer is set up
+using the message in the buffer as the associated message.  Any previous
+association between the @hid[Message] buffer and a @hid[Draft] buffer is
+removed.  Any association of the @hid[Message] buffer with a @hid[Headers]
+buffer is propagated to the @hid[Draft] buffer.
+
+When not in a @hid[Headers] buffer or @hid[Message] buffer, this command
+prompts for a folder and message to reply to.  This message is inserted into a
+unique @hid[Message] buffer, and a unique @hid[Draft] buffer is created as in
+the previous two cases.  There is no association of either the @hid[Message]
+buffer or the @hid[Draft] buffer with a @hid[Headers] buffer.
+
+When a prefix argument is supplied, @hid[Reply to Message Prefix Action] is
+considered with respect to supplying carbon copy switches to @f[repl].  This
+variable's value is one of @b[:cc-all], :@b[no-cc-all], or @nil.  See section
+@ref[Styles] for examples of how to use this.
+
+@hid[Reply to Message in Other Window] is identical to @hid[Reply to Message],
+but the current window is split showing the @hid[Draft] buffer in the new
+window.  The split window displays the @hid[Message] buffer.
+
+@hid[Deliver Message] will deliver the draft to its intended recipient(s).
+
+The @hid[Goto Headers Buffer] commmand, when invoked in a @hid[Draft] or
+@hid[Message] buffer, makes the associated @hid[Headers] buffer current.  The
+@hid[Goto Message Buffer] command, when invoked in a @hid[Draft] buffer, makes
+the associated @hid[Message] buffer current.
+@enddefcom
+
+@defcom[com "Forward Message", stuff (bound to @bf[f] in @hid[Headers] and @hid[Message] modes) ]
+ This command, when invoked in a @hid[Headers] buffer, creates a unique
+@hid[Draft] buffer.  The current message is inserted in the draft by using the
+@f[forw] utility, and the @hid[Draft] buffer is shown in the current window.
+The name of the draft message file is used to produce the buffer's name.  A
+pathname is associated with the @hid[Draft] buffer so that @hid[Save File] can
+be used to incrementally save a composition before delivering it.  The
+@hid[Draft] buffer is associated with the @hid[Headers] buffer, but no
+@hid[Message] buffer is created since the message is already a part of the
+draft.
+
+When invoked in a @hid[Message] buffer, a unique @hid[Draft] buffer is set up
+inserting the message into the @hid[Draft] buffer.  The @hid[Message] buffer is
+not associated with the @hid[Draft] buffer because the message is already a
+part of the draft.  However, any association of the @hid[Message] buffer with a
+@hid[Headers] buffer is propagated to the @hid[Draft] buffer.
+
+When not in a @hid[Headers] buffer or @hid[Message] buffer, this command
+prompts for a folder and message to forward.  A @hid[Draft] buffer is created
+as described in the previous two cases.
+
+@hid[Deliver Message] will deliver the draft to its intended recipient(s).
+@enddefcom
+
+@defcom[com "Deliver Message", stuff (bound to @bf[H-s] and @bf[H-c] in @hid[Draft] mode) ]
+@defhvar1[var "Deliver Message Confirm", val {nil}]
+ This command, when invoked in a @hid[Draft] buffer, saves the file and uses
+the @mh @f[send] utility to deliver the draft.  If the draft is a reply to some
+message, then @f[anno] is used to annotate that message with a "@f[replied]"
+component.  Any @hid[Headers] buffers containing the replied-to message are
+updated with an "@b[A]" placed in the appropriate headers line two characters
+after the message ID.  Before doing any of this, confirmation is asked for
+based on @hid[Deliver Message Confirm].
+
+When not in a @hid[Draft] buffer, this prompts for a draft message ID and
+invokes @f[send] on that draft message to deliver it.  Sending a draft in this
+way severs any association that draft may have had with a message being replied
+to, so no annotation will occur.
+@enddefcom
+
+@defcom[com "Delete Draft and Buffer", stuff (bound to @bf[H-q] in @hid[Draft] mode) ]
+This command, when invoked in a @hid[Draft] buffer, deletes the draft message
+file and the buffer.  This also deletes any associated message buffer unless
+the user preserved it with @hid[Keep Message].
+@enddefcom
+
+@defcom[com "Remail Message", stuff (bound to @bf[H-r] in @hid[Headers] and @hid[Message] modes) ]
+ This command, when invoked in a @hid[Headers] or @hid[Message] buffer, prompts
+for resend @f[To:] and resend @f[Cc:] addresses, remailing the current message.
+When invoked in any other kind of buffer, this command prompts for a folder and
+message as well.  @mh@comment{}'s @f[dist] sets up a draft folder message which is then
+modified.  The above mentioned addresses are inserted on the @f[Resent-To:] and
+@f[Resent-Cc:] lines.  Then the message is delivered.
+
+There is no mechanism for annotating messages as having been remailed.
+@enddefcom
+
+@defcom[com "Draft Help", bind (Draft: H-?)]
+This command displays documentation on @hid[Draft] mode.
+@enddefcom
+
+
+@section[Convenience Commands for Message and Draft Buffers]
+@index[message buffer commands]
+@index[draft buffer commands]
+@index[convenience commands for mail interface]
+@label[convenience-coms] 
+This section describes how to switch from a @hid[Message] or @hid[Draft] buffer
+to its associated @hid[Headers] buffer, or from a @hid[Draft] buffer to its
+associated @hid[Message] buffer.  There are also commands for various styles of
+inserting text from a @hid[Message] buffer into a @hid[Draft] buffer.
+
+@defcom[com "Goto Headers Buffer", stuff (bound to @bf[^] in @hid[Message] mode and @bf[H-^] in @hid[Draft] mode) ] 
+This command, when invoked in a @hid[Message] or @hid[Draft] buffer with an
+associated @hid[Headers] buffer, places the associated @hid[Headers] buffer in
+the current window.
+
+The cursor is moved to the headers line of the associated message.
+@enddefcom
+
+@defcom[com "Goto Message Buffer", stuff (bound to @bf[H-m] in @hid[Draft] mode) ]
+This command, when invoked in a @hid[Draft] buffer with an associated
+@hid[Message] buffer, places the associated @hid[Message] buffer in the current
+window.
+@enddefcom
+
+@defcom[com "Insert Message Region", stuff (bound to @bf[H-y] in appropriate modes) ]
+@defhvar1[var "Message Insertion Prefix", val {"   "}]
+@defhvar1[var "Message Insertion Column", val {75}]
+This command, when invoked in a @hid[Message] or @hid[News-Message] (where it
+is bound) buffer that has an associated @hid[Draft] or @hid[Post] buffer,
+copies the current active region into the @hid[Draft] or @hid[Post] buffer.  It
+is filled using @hid[Message Insertion Prefix] (which defaults to three spaces)
+and @hid[Message Insertion Column].  If an argument is supplied, the filling is
+inhibited.
+@enddefcom
+
+@defcom[com "Insert Message Buffer", stuff (bound to @bf[H-y] in appropriate modes) ]
+@defhvar1[var "Message Buffer Insertion Prefix", val {"    "}]
+This command, when invoked in a @hid[Draft] or @hid[Post] (where it is bound)
+buffer with an associated @hid[Message] or @hid[News-Message] buffer, or when
+in a @hid[Message] (or @hid[News-Message]) buffer that has an associated
+@hid[Draft] buffer, inserts the @hid[Message] buffer into the @hid[Draft] (or
+@hid[Post]) buffer.  Each inserted line is modified by prefixing it with
+@hid[Message Buffer Insertion Prefix] (which defaults to four spaces) .  If an
+argument is supplied, the prefixing is inhibited.
+@enddefcom
+
+@defcom[com "Edit Message Buffer", stuff (bound to @bf[e] in @hid[Message] mode) ]
+This command puts the current @hid[Message] buffer in @hid[Text] mode and makes
+it writable (@hid[Message] buffers are normally read-only).  The pathname of
+the file which the message is in is associated with the buffer making saving
+possible.  A recursive edit is entered, and the user is allowed to make changes
+to the message.  When the recursive edit is exited, if the buffer is modified,
+the user is asked if the changes should be saved.  The buffer is marked
+unmodified, and the pathname is disassociated from the buffer.  The buffer
+otherwise returns to its previous state as a @hid[Message] buffer.  If the
+recursive edit is aborted, the user is not asked to save the file, and the
+buffer remains changed though it is marked unmodified.
+@enddefcom
+
+
+@section[Deleting Messages]
+@index[deleting messages]
+@label[deleting]
+The main command described in this section is @hid[Headers Delete Message]
+(bound to @bf[k] in @hid[Headers] and @hid[Message] modes).  A useful command
+for reading new mail is @hid[Delete Message and Show Next] (bound to @bf[d] in
+@hid[Message] mode) which deletes the current message and shows the next
+undeleted message.
+
+Since messages are by default deleted using a virtual message deletion
+mechanism, @hid[Expunge Messages] (bound to @bf[!] in @hid[Headers] mode)
+should be mentioned here.  This is described in section @ref[terminating].
+
+
+@defhvar[var "Virtual Message Deletion", val {t}]
+When set, @hid[Delete Message] adds a message to the "@f[hemlockdeleted]"
+sequence; otherwise, @f[rmm] is invoked on the message immediately.
+@enddefhvar
+
+@defcom[com "Delete Message" ]
+This command prompts for a folder, messages, and an optional @f[pick]
+expression.  When invoked in a @hid[Headers] buffer of the specified folder,
+the prompt for a message specification will default to the those messages in
+that @hid[Headers] buffer.
+
+When the variable @hid[Virtual Message Deletion] is set, this command merely
+flags the messages for deletion by adding them to the "@f[hemlockdeleted]"
+sequence.  Then this updates any @hid[Headers] buffers representing the folder.
+It notates each headers line referring to a deleted message with a "@b[D]" in
+the third character position after the message ID.
+
+When @hid[Virtual Message Deletion] is not set, @f[rmm] is invoked on the
+message, and each headers line referring to the deleted message is deleted from
+its buffer
+@enddefcom
+
+@defcom[com "Headers Delete Message", stuff (bound to @bf[k] in @hid[Headers] and @hid[Message] modes) ]
+This command, when invoked in a @hid[Headers] buffer, deletes the message on
+the current line as described in @hid[Delete Message].
+
+When invoked in a @hid[Message] buffer, the message displayed in it is deleted
+as described in @hid[Delete Message].
+@enddefcom
+
+@defcom[com "Delete Message and Show Next", stuff (bound to @bf[k] in @hid[Headers] and @hid[Message] modes) ]
+This command is only valid in a @hid[Headers] buffer or a @hid[Message] buffer
+associated with some @hid[Headers] buffer.  The current message is deleted as
+with the @hid[Delete Message] command.  Then the next message is shown as with
+@hid[Next Undeleted Message].
+@enddefcom
+
+@defcom[com "Delete Message and Down Line", stuff (bound to @bf[d] in @hid[Headers mode])]
+This command, when invoked in a @hid[Headers] buffer, deletes the message on
+the current line.  Then the point is moved to the next non-blank line.
+@enddefcom
+
+@defcom[com "Undelete Message" ]
+This command is only meaningful when @hid[Virtual Message Deletion] is set.
+This prompts for a folder, messages, and an optional @f[pick] expression.  When
+in a @hid[Headers] buffer of the specified folder, the messages prompt defaults
+to those messages in the buffer.  All @hid[Headers] buffers representing the
+folder are updated.  Each headers line referring to an undeleted message is
+notated by replacing the "@b[D]" in the third character position after the
+message ID with a space.
+@enddefcom
+
+@defcom[com "Headers Undelete Message", stuff (bound to @bf[u] in @hid[Headers] and @hid[Message] modes) ]
+This command is only meaningful when @hid[Virtual Message Deletion] is set.
+When invoked in a @hid[Headers] buffer, the message on the current line is
+undeleted as described in @hid[Undelete Message].
+
+When invoked in a @hid[Message] buffer, the message displayed in it is
+undeleted as described in @hid[Undelete Message].
+@enddefcom
+
+
+@section[Folder Operations]
+
+@index[folder operations]@label[folder]
+@defcom[com "List Folders" ]
+This command displays a list of all current mail folders in the user's
+top-level mail directory in a @hemlock pop-up window.
+@enddefcom
+
+@defcom[com "Create Folder"]
+This command prompts for and creates a folder.  If the folder already exists,
+an error is signaled.
+@enddefcom
+
+@defcom[com "Delete Folder" ]
+This command prompts for a folder and uses @f[rmf] to delete it.  Note that no
+confirmation is asked for.
+@enddefcom
+
+
+@section[Refiling Messages]
+
+@index[refiling messages]@label[refiling]
+@defcom[com "Refile Message" ]
+This command prompts for a folder, messages, an optional @f[pick] expression,
+and a destination folder.  When invoked in a @hid[Headers] buffer of the
+specified folder, the message prompt offers a default of those messages in the
+buffer.  If the destination folder does not exist, the user is asked to create
+it.  The resulting messages are refiled with the @f[refile] utility.  All
+@hid[Headers] buffers for the folder are updated.  Each line referring to a
+refiled message is deleted from its buffer.
+@enddefcom
+
+@defcom[com "Headers Refile Message", stuff (bound to @bf[o] in @hid[Headers] and @hid[Message] modes) ]
+This command, when invoked in a @hid[Headers] buffer, prompts for a destination
+folder, refiling the message on the current line with @f[refile].  If the
+destination folder does not exist, the user is asked to create it.  Any
+@hid[Headers] buffers containing messages for that folder are updated.  Each
+headers line referring to the refiled message is deleted from its buffer.
+
+When invoked in a @hid[Message] buffer, that message is refiled as described
+above.
+@enddefcom
+
+
+@section[Marking Messages]
+@index[marking messages]
+@label[marking]
+@defcom[com "Mark Message" ]
+This command prompts for a folder, message, and sequence and adds (deletes) the
+message specification to (from) the sequence.  By default this adds the
+message, but if an argument is supplied, this deletes the message.  When
+invoked in a @hid[Headers] buffer or @hid[Message] buffer, this only prompts
+for a sequence and uses the current message.
+@enddefcom
+
+
+@section[Terminating Headers Buffers]
+@label[terminating]
+The user never actually @i[exits] the mailer.  He can leave mail buffers lying
+around while conducting other editing tasks, selecting them and continuing his
+mail handling whenever.  There still is a need for various methods of
+terminating or cleaning up @hid[Headers] buffers.  The two most useful commands
+in this section are @hid[Expunge Messages] and @hid[Quit Headers].
+
+
+@defhvar[var "Expunge Messages Confirm", val {t}]
+When this is set, @hid[Quit Headers] and @hid[Expunge Messages] will ask for
+confirmation before expunging messages and packing the folder's message ID's.
+@enddefhvar
+
+@defhvar[var "Temporary Draft Folder", val {nil}]
+This is a folder name where @mh @f[fcc:] messages are kept with the intention
+that this folder's messages will be deleted and expunged whenever messages from
+any folder are expunged (for example, when @hid[Expunge Messages] or @hid[Quit
+Headers] is invoked.
+@enddefhvar
+
+@defcom[com "Expunge Messages", stuff (bound to @bf[!] in @hid[Headers] mode) ]
+This command deletes messages @f[mark]'ed for deletion, and compacts the
+folder's message ID's.  If there are messages to expunge, ask the user for
+confirmation, displaying the folder name.  This can be inhibited by setting
+@hid[Expunge Messages Confirm] to @nil.  When @hid[Temporary Draft Folder] is
+not @nil, this command deletes and expunges that folder's messages regardless
+of the folder in which the user invokes it, and a negative response to the
+request for confirmation inhibits this.
+
+When invoked in a @hid[Headers] buffer, the messages in that folder's
+"@f[hemlockdeleted]" sequence are deleted by invoking @f[rmm].  Then the ID's
+of the folder's remaining messages are compacted using the @f[folder] utility.
+Since headers must be regenerated due to renumbering or reassigning message
+ID's, and because @hid[Headers] buffers become inconsistent after messages are
+deleted, @hemlock must regenerate all the headers for the folder.  Multiple
+@hid[Headers] buffers for the same folder are then collapsed into one buffer,
+deleting unnecessary duplicates.  Any @hid[Message] buffers associated with
+these @hid[Headers] buffers are deleted.
+
+If there is an unseen @hid[Headers] buffer for the folder, it is handled
+separately from the @hid[Headers] buffers described above.  @hemlock tries to
+update it by filling it only with remaining unseen message headers.
+Additionally, any headers generated due to @hid[Unseen Headers Message Spec]
+are inserted.  If there are no headers, unseen or otherwise, the buffer is left
+blank.
+
+Any @hid[Draft] buffer set up as a reply to a message in the folder is affected
+as well since the associated message has possibly been deleted.  When a draft
+of this type is delivered, no message will be annotated as having been replied
+to.
+
+When invoked in a @hid[Message] buffer, this uses its corresponding folder as
+the folder argument.  The same updating as described above occurs.
+
+In any other type of buffer, a folder is prompted for.
+@enddefcom
+
+@defcom[com "Quit Headers", stuff (bound to @bf[q] in @hid[Headers] and @hid[Message] modes) ]
+This command affects the current @hid[Headers] buffer.  When there are deleted
+messages, ask the user for confirmation on expunging the messages and packing
+the folder's message ID's.  This prompting can be inhibited by setting
+@hid[Expunge Messages Confirm] to @nil.  After deleting and packing, this
+deletes the buffer and all its associated @hid[Message] buffers.
+
+Other @hid[Headers] buffers regarding the same folder are handled as described
+in @hid[Expunge Messages], but the buffer this command is invoked in is always
+deleted.
+
+When @hid[Temporary Draft Folder] is not @nil, this folder's messages are
+deleted and expunged regardless of the folder in which the user invokes this
+command.  A negative response to the above mentioned request for confirmation
+inhibits this.
+@enddefcom
+
+@defcom[com "Delete Headers Buffer and Message Buffers" ]
+This command prompts for a @hid[Headers] buffer to delete along with its
+associated @hid[Message] buffers.  Any associated @hid[Draft] buffers are left
+intact, but their corresponding @hid[Message] buffers will be deleted.  When
+invoked in a @hid[Headers] buffer or a @hid[Message] buffer associated with a
+@hid[Headers] buffer, that @hid[Headers] buffer is offered as a default.
+@enddefcom
+
+
+@section[Miscellaneous Commands]
+@label[miscellaneous mail commands]
+@label[miscellaneous]
+
+@defcom[com "List Mail Buffers", stuff (bound to @bf[l] in @hid[Headers] and @hid[Message] modes @bf[H-l] in @hid[Draft] mode) ]
+This command shows a list of all mail @hid[Message], @hid[Headers], and
+@hid[Draft] buffers.
+
+If a @hid[Message] buffer has an associated @hid[Headers] buffer, it is
+displayed to the right of the @hid[Message] buffer's name.
+
+If a @hid[Draft] buffer has an associated @hid[Message] buffer, it is displayed
+to the right of the @hid[Draft] buffer's name.  If a @hid[Draft] buffer has no
+associated @hid[Message] buffer, but it is associated with a @hid[Headers]
+buffer, then the name of the @hid[Headers] buffer is displayed to the right of
+the @hid[Draft] buffer.
+
+For each buffer listed, if it is modified, then an asterisk is displayed before
+the name of the buffer.
+@enddefcom
+
+
+@section[Styles of Usage]
+@index[styles of mail interface usage]
+@label[Styles]
+This section discusses some styles of usage or ways to make use of some of the
+features of @hemlock@comment{}'s interface to @mh that might not be obvious.  In each
+case, setting some variables and/or remembering an extra side effect of a
+command will lend greater flexibility and functionality to the user.
+
+@subsection[Unseen Headers Message Spec]
+The unseen @hid[Headers] buffer by default only shows unseen headers which is
+adequate for one folder, simple mail handling.  Some people use their @hid[New
+Mail Folder] only for incoming mail, refiling or otherwise dispatching a
+message immediately.  Under this mode it is easy to conceive of the user not
+having time to respond to a message, but he would like to leave it in this
+folder to remind him to take care of it.  Using the @hid[Unseen Headers Message
+Spec] variable, the user can cause all the messages the @hid[New Mail Folder] to
+be inserted into the unseen @hid[Headers] buffer whenever just unseen headers
+would be.  This way he sees all the messages that require immediate attention.
+
+To achieve the above effect, @hid[Unseen Headers Message Spec] should be set to
+the string @f["all"].  This variable can be set to any general @mh message
+specification (see section @ref[mhcommands] of this chapter), so the user can
+include headers of messages other than those that have not been seen without
+having to insert all of them.  For example, the user could set the variable to
+@f["flagged"] and use the @hid[Mark Message] command to add messages he's
+concerned about to the @f["flagged"] sequence.  Then the user would see new
+mail and interesting mail in his unseen @hid[Headers] buffer, but he doesn't
+have to see everything in his @hid[New Mail Folder].
+
+
+@subsection[Temporary Draft Folder]
+Section @ref[components-files] of this chapter discusses how to make @mh keep
+personal copies of outgoing mail.  The method described will cause a copy of
+every outgoing message to be saved forever and requires the user to go through
+his @f[Fcc:] folder, weeding out those he does not need.  The @hid[Temporary
+Draft Folder] variable can name a folder whose messages will be deleted and
+expunged whenever any folder's messages are expunged.  By naming this folder in
+the @mh profile and components files, copies of outgoing messages can be saved
+temporarily.  They will be cleaned up automatically, but the user still has a
+time frame in which he can permanently save a copy of an outgoing message.
+This folder can be visited with @hid[Message Headers], and messages can be
+refiled just like any other folder.
+
+
+@subsection[Reply to Message Prefix Action]
+Depending on the kinds of messages one tends to handle, the user may find
+himself usually replying to everyone who receives a certain message, or he may
+find that this is only desired occasionally.  In either case, the user
+can set up his @mh profile to do one thing by default, using the @hid[Reply
+to Message Prefix Action] variable in combination with a prefix argument to the
+@hid[Reply to Message] command to get the other effect.
+
+For example, the following line in one's @mh profile will cause @mh to reply to
+everyone receiving a certain message (except for the user himself since he
+saves personal copies with the @f[-fcc] switch):
+@begin[programexample]
+repl: -cc all -nocc me -fcc out-copy
+@end[programexample]
+This user can set @hid[Reply to Message Prefix Action] to be @f[:no-cc-all].
+Then whenever he invokes @hid[Reply to Message] with a prefix argument, instead
+of replying to everyone, the draft will be set up in reply only to the person
+who sent the mail.
+
+As an alternative example, not specifying anything in one's @mh profile and
+setting this variable to @f[:cc-all] will have a default effect of replying
+only to the sender of a piece of mail.  Then invoking @hid[Reply to Message]
+with a prefix argument will cause everyone who received the mail to get a copy
+of the reply.  If the user does not want a @f[cc:] copy, then he can add
+@f[-nocc me] as a default switch and value in his @mh profile.
+
+
+@newpage
+@section[Wallchart]
+
+@tabclear
+@tabdivide(3)
+
+@begin[format, spacing 1.5]
+
+@Begin[Center] @b[Global bindings:] @End[Center]
+
+@hid[Incorporate and Read New Mail]@\@\@bf[C-x i]
+@hid[Send Message]@\@\@bf[C-x m]
+@hid[Message Headers]@\@\@bf[C-x r]
+
+
+@Begin[Center] @b[Headers and Message modes bindings:] @End[Center]
+
+@hid[Next Undeleted Message]@\@\@bf[n]
+@hid[Previous Undeleted Message]@\@\@bf[p]
+@hid[Send Message]@\@\@bf[s], @bf[m]
+@hid[Forward Message]@\@\@bf[f]
+@hid[Headers Delete Message]@\@\@bf[k]
+@hid[Headers Undelete Message]@\@\@bf[u]
+@hid[Headers Refile Message]@\@\@bf[o]
+@hid[List Mail Buffers]@\@\@bf[l]
+@hid[Quit Headers]@\@\@bf[q]
+@hid[Incorporate and Read New Mail]@\@\@bf[i]
+@hid[Next Message]@\@\@bf[M-n]
+@hid[Previous Message]@\@\@bf[M-p]
+@hid[Beginning of Buffer]@\@\@bf[<]
+@hid[End of Buffer]@\@\@bf[>]
+
+
+@Begin[Center] @b[Headers mode bindings:] @End[Center]
+
+@hid[Delete Message and Down Line]@\@\@bf[d]
+@hid[Pick Headers]@\@\@bf[h]
+@hid[Show Message]@\@\@bf[space], @bf[.]
+@hid[Reply to Message]@\@\@bf[r]
+@hid[Expunge Messages]@\@\@bf[!]
+
+
+@Begin[Center] @b[Message mode bindings:] @End[Center]
+
+@hid[Delete Message and Show Next]@\@\@bf[d]
+@hid[Goto Headers Buffer]@\@\@bf[^]
+@hid[Scroll Message]@\@\@bf[space]
+@hid[Scroll Message]@\@\@bf[C-v]
+@hid[Scroll Window Up]@\@\@bf[backspace], @bf[delete]
+@hid[Reply to Message in Other Window]@\@bf[r]
+@hid[Edit Message Buffer]@\@\@bf[e]
+@hid[Insert Message Region]@\@\@bf[H-y]
+
+
+@Begin[Center] @b[Draft mode bindings:] @End[Center]
+
+@hid[Goto Headers Buffer]@\@\@bf[H-^]
+@hid[Goto Message Buffer]@\@\@bf[H-m]
+@hid[Deliver Message]@\@\@bf[H-s], @bf[H-c]
+@hid[Insert Message Buffer]@\@\@bf[H-y]
+@hid[Delete Draft and Buffer]@\@\@bf[H-q]
+@hid[List Mail Buffers]@\@\@bf[H-l]
+
+@end[format]
+@tabclear
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/netnews.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/netnews.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/netnews.mss	(revision 13309)
@@ -0,0 +1,488 @@
+@comment{-*- Dictionary: /afs/cs/project/clisp/docs/hem/hem; Mode: spell; Package: Hemlock -*-}
+
+@chap[The Hemlock Netnews Interface]
+@section[Introduction to Netnews in Hemlock]
+
+
+@hemlock provides a facility for reading bulletin boards through the
+NetNews Transfer Protocol (NNTP).  You can easily read Netnews, reply to
+news posts, post messages, etc.  The news reading interface is consistent
+with that of the @hemlock mailer, and most Netnews commands function in the
+same manner as their mailer counterparts.
+
+Netnews can be read in one of two different modes.  The first mode, invoked
+by the @hid(Netnews) command, allows the user to read new messages in
+groups which the user has specified.  This method of reading netnews will
+track the highest numbered message in each newsgroup and only show new
+messages which have arrived since then.  The @hid(Netnews Browse) command
+invokes the other method of reading netnews.  This mode displays a list of
+all newsgroups, and the user may choose to read messages in any of them.
+By default, the news reader will not track the latest message read when
+browsing, and it will always display the last few messages.
+
+
+@section[Setting Up Netnews]
+
+To start reading bulletin boards from @hemlock you probably need to create a
+file containing the newsgroups you want to read.
+
+@defhvar[var "Netnews Group File", val {".hemlock-groups"}]
+   When you invoke the @hid(Netnews) command, @hemlock merges the value of
+   this variable with your home directory and looks there for a list of
+   groups (one per line) to read.
+@enddefhvar
+
+@defhvar[var "Netnews Database File", val{".hemlock-netnews"}]
+When you invoke the @hid(Netnews) command, @hemlock merges the value of
+this variable with your home directory.  This file maintains a pointer to
+the highest numbered message read in each group in @hid(Netnews Group
+File).
+@enddefhvar
+
+@defcom[com "List All Groups"]
+   When you invoke this command, @hemlock creates a buffer called
+   @hid(Netnews Groups) and inserts the names of all accessible Netnews
+   groups into it alphabetically.  You may find this useful if you choose to set
+   up your @hid(Netnews Group File) manually.
+@enddefcom
+
+@defhvar[var "Netnews NNTP Server", val{"netnews.srv.cs.cmu.edu"}]
+This variable stores the host name of the machine which @hemlock will use
+as the NNTP server.
+@enddefhvar
+
+@defhvar[var "Netnews NNTP Timeout Period", val{30}]
+This is the number of seconds @hemlock will wait trying to connect to the
+NNTP server.  If a connection is not made within this time period, the
+connection will time out and an error will be signalled.
+@enddefhvar
+
+@subsection[News-Browse Mode]
+
+   @hid(News-Browse) mode provides an easy method of adding groups to
+   your @hid(Netnews Group File).
+
+@defcom[com "Netnews Browse"]
+   This command sets up a buffer in @hid{News-Browse} mode with all
+   available groups listed one per line.  Groups may be read or added
+   to your group file using various commands in this mode.
+@enddefcom
+
+@defcom[com "Netnews Browse Add Group To File", stuff (bound to @bf[a] in @hid[News-Browse] mode)]
+@defcom1[com "Netnews Browse Pointer Add Group to File"]
+@hid(Netnews Browse Add Group to File) adds the group under the point to
+your group file, and @hid(Netnews Browse Pointer Add Group To File) adds
+the group under the mouse pointer without moving the point.
+@enddefcom
+
+@defcom[com "Netnews Browse Read Group", stuff (bound to @bf[space] in @hid[News-Browse] mode)]
+@defcom1[com "Netnews Browse Pointer Read Group"]
+@hid(Netnews Browse Read Group) and @hid(Netnews Browse Pointer Read Group)
+read the group under the cursor and the group under the mouse pointer,
+respectively.  These commands neither use nor modify the contents of your
+@hid(Netnews Database File); they will always present the last few messages
+in the newsgroup, regardless of the last message read.  @hid(Netnews Browse
+Pointer Read Group) does not modify the position of the point.
+@enddefcom
+
+@defcom[com "Netnews Quit Browse"]
+   This command exits @hid(News-Browse) mode.
+@enddefcom
+
+The @hid(Next Line) and @hid(Previous Line) commands are conveniently bound to
+@bf[n] and @bf[p] in this mode.
+
+@section[Starting Netnews]
+
+Once your @hid(Netnews Group File) is set up, you may begin reading netnews.
+
+@defcom[com "Netnews"]
+   This command is the main entry point for reading bulletin boards in
+   @hemlock.  Without an argument, the system looks for what bulletin boards to
+   read in the value of @hid(Netnews Group File) and reads each of them in
+   succession.  @hemlock keeps a pointer to the last message you read in each
+   of these groups in your @hid(Netnews Database File).  Bulletin boards may
+   be added to your @hid(Netnews Group File) manually or by using
+   the @hid(Netnews Browse) facility.  With an argument, @hemlock prompts the 
+   user for the name of a bulletin board and reads it.
+@enddefcom
+
+@defcom[com "Netnews Look at Group"]
+   This command prompts for a group and reads it, ignoring the information
+   in your @hid(Netnews Database File).
+@enddefcom
+
+When you read a group, @hemlock creates a buffer that contains important
+header information for the messages in that group.  There are four fields
+in each header, one each for the @i(date), @i(lines), @i(from), and
+@i(subject).  The @i(date) field shows when the message was sent, the
+@i(lines) field displays how long the message is in lines, the @i(from)
+field shows who sent the message, and the @i(subject) field displays the
+subject of this message.  If a field for a message is not available, @f(NA)
+will appear instead.  You may alter the length of each of these fields by
+modifying the following @hemlock variables:
+
+@defhvar[var "Netnews Before Date Field Pad", val 1]
+   How many spaces should be inserted before the date in @hid(News-Headers)
+   buffers.
+@enddefhvar
+
+@defhvar[var "Netnews Date Field Length", val 6]
+@defhvar1[var "Netnews Line Field Length", val 3]
+@defhvar1[var "Netnews From Field Length", val 20]
+@defhvar1[var "Netnews Subject Field Length", val 43]
+   These variables control how long the @i(date), @i(line), @i(from), and
+   @i(subject) fields should be in @hid{News-Headers} buffers.
+@enddefhvar
+
+@defhvar[var "Netnews Field Padding", val 2]
+   How many spaces should be left between the Netnews @i(date), @i(from), 
+   @i(lines), and @i(subject) fields after padding to the required length.
+@enddefhvar
+
+For increased speed, @hemlock only inserts headers for a subset of the
+messages in each group.  If you have never read a certain group, and the
+value of @hid(Netnews New Group Style) is @f(:from-end) (the default),
+@hemlock inserts some number of the last messages in the group, determined
+by the value of @hid(Netnews Batch Count).  If the value of @hid(Netnews
+New Group Style) is @f(:from-start), @hemlock will insert the first batch
+of messages in the group.  If you have read a group before, @hemlock will
+insert the batch of messages following the highest numbered message that
+you had read previously.
+
+@defhvar[var "Netnews Start Over Threshold", val {350}]
+   If the number of new messages in a group exceeds the value of this
+   variable and @hid(Netnews New Group Style) is @f(:from-end), @hemlock asks
+   if you would like to start reading this group from the end.
+@enddefhvar
+
+You may at any time go beyond the messages that are visible using the 
+@hid(Netnews Next Line), @hid(Netnews Previous Line),
+@hid(Netnews Headers Scroll Window Up), and
+@hid(Netnews Headers Scroll Down) commands in @hid(News-Headers) mode,
+or the @hid(Netnews Next Article) and @hid(Netnews Previous Article)
+commands in @hid(News-Message) mode.
+
+@defhvar[var "Netnews Fetch All Headers", val {nil}]
+This variable determines whether Netnews will fetch all headers immediately
+upon entering a new group.
+@enddefhvar
+
+@defhvar[var "Netnews Batch Count", val {50}]
+   This variable determines how many headers the Netnews facility will fetch
+   at a time.
+@enddefhvar
+
+@defhvar[var "Netnews New Group Style", val {:from-end}]
+This variable determines what happens when you read a group that you have
+never read before.  When it is @f(:from-start), the @hid(Netnews) command
+will read from the beginning of a new group forward.  When it is @f(:from-end),
+the default, @hid(Netnews) will read the group from the end backward.
+@enddefhvar
+
+@section[Reading Messages]
+
+From a @hid{News-Headers} buffer, you may read messages, reply to messages
+via the @hemlock mailer, or reply to messages via post.  Some commands are
+also bound to ease getting from one header to another.
+
+@defcom[com "Netnews Show Article", stuff (bound to @bf[space] in @hid{News-Headers} mode)]
+@defhvar1[var "Netnews Read Style", val {:multiple}]
+@defhvar1[var "Netnews Headers Proportion", val {0.25}]
+This command puts the body of the message header under the current point
+into a @hid{News-Message} buffer.  If the value of @hid(Netnews Read
+Style) is @f(:single), @hemlock changes to the @hid{News-Message}
+buffer.  If it is @f(:multiple), then @hemlock splits the current window
+into two windows, one for headers and one for message bodies.  The headers
+window takes up a proportion of the current window based on the value of
+@hid(Netnews Headers Proportion).  If the window displaying the
+@hid(News-Headers) buffer has already been split, and the message
+currently displayed in the @hid(News-Message) window is the same as the
+one under the current point, this command behaves just like @hid(Netnews
+Message Scroll Down).
+@enddefcom
+
+@defhvar[var "Netnews Message Header Fields", val {nil}]
+   When this variable is @nil, all available fields are displayed in the
+   header of a message.  Otherwise, this variable should containt a list of
+   fields to include in message headers.  If an element of this
+   list is an atom, then it should be the string name of a field.  If it is
+   a cons, then the car should be the string name of a field, and the cdr
+   should be the length to which this field should be limited.  Any string
+   name is acceptable, and fields that do not exist are ignored.
+@enddefhvar   
+
+@defcom[com "Netnews Show Whole Header", stuff (bound to @bf[w] in @hid{News-Headers} and @hid{News-Message} modes.)]
+This command displays the entire header for the message currently being
+read.  This is to undo the effects of @hid{Netnews Message Header Fields}
+for the current message.
+@enddefcom
+
+@defcom[com "Netnews Next Line", stuff (bound to @bf[C-n] and @bf[Downarrow] in @hid{News-Headers} mode)]
+@defhvar1[var "Netnews Last Header Style", val {:next-headers}]
+This command moves the current point to the next line.  If you are on the
+last visible message, and there are more in the current group, headers for
+these messages will be inserted.  If you are on the last header and there
+are no more messages in this group, then @hemlock will take some action
+based on the value of @hid(Netnews Last Header Style).  If the value of
+this variable is @f(:feep), @hemlock feeps you indicating there are no
+more messages.  If the value is @f(:next-headers), @hemlock reads in the
+headers for the next group in your @hid(Netnews Group File).  If the value
+is @f(:next-article), @hemlock goes on to the next group and shows you
+the first unread message.
+@enddefcom
+					 
+@defcom[com "Netnews Previous Line", stuff (bound to @bf[C-p] and @bf[Uparrow] in @hid{News-Headers} mode)]
+This command moves the current point to the previous line.  If you are on
+the first visible header, and there are more previous messages, @hemlock
+inserts the headers for these messages.
+@enddefcom
+
+@defcom[com "Netnews Headers Scroll Window Down", stuff (bound to @bf[C-v] in @hid{News-Headers} mode)]
+@defcom1[com "Netnews Headers Scroll Window Up", stuff (bound to @bf[M-v] in @hid{News-Headers} mode)]
+   These commands scroll the headers window up or down one screenfull.  If the
+   end of the buffer is visible, @hemlock inserts the next batch of headers.
+@enddefcom
+
+@defcom[com "Netnews Next Article", stuff (bound to @bf[n] in @hid{News-Message} and @hid{News-Headers} modes)]
+@defcom1[com "Netnews Previous Article", stuff (bound to @bf[p] in @hid{News-Message} and @hid{News-Headers} modes)]
+   These commands insert the next or previous message into a message buffer.
+@enddefcom
+
+@defcom[com "Netnews Message Scroll Down", stuff (bound to @bf[space] in @hid{News-Message} mode)]
+@defhvar1[var "Netnews Scroll Show Next Message", val {t}]
+If the end of the current message is visible, @hemlock feeps the user if
+the value of @hid(Netnews Scroll Show Next Message) is non-@nil, or it
+inserts the next message into this message buffer if that variable is @nil.
+If the end of the message is not visible, then @hemlock shows the next
+screenfull of the current message.
+@enddefcom
+
+@defcom[com "Netnews Message Quit", stuff (bound to @bf[q] in @hid{News-Message} mode)]
+   This command deletes the current message buffer and makes the associated
+   @hid{News-Headers} buffer current.
+@enddefcom
+ 
+@defcom[com "Netnews Goto Headers Buffer", stuff (bound to @bf[H-h] in @hid{News-Message} mode)]
+   This command, when invoked from a @hid(News-Message) buffer with an
+   associated @hid(News-Headers) buffer, places the associated 
+   @hid(News-Headers) buffer into the current window.
+@enddefcom
+
+@defcom[com "Netnews Message Keep Buffer", stuff (bound to @bf[k] in @hid{News-Message} mode)]
+   By default, @hemlock uses one buffer to display all messages in a group,
+   one at a time.  This command tells @hemlock to keep the current message
+   buffer intact and start reading messages in another buffer.
+@enddefcom
+
+@defcom[com "Netnews Select Message Buffer", stuff (bound to @bf[H-m] in @hid{News-Headers} and @hid{Post} modes.)]
+   In @hid{News-Headers} mode, this command selects the buffer
+   containing the last message read.  In @hid{Post} mode, it selects the
+   associated @hid{News-Message} buffer, if there is one.
+@enddefcom
+
+@defcom[com "Netnews Append to File", stuff (bound to @bf[a] in @hid{News-Headers} and @hid{News-Message} modes.)]
+@defhvar1[var "Netnews Message File", val {"netnews-messages.txt"}]
+This command prompts for a file which the current message will be appended
+to.  The default file is the value of @hid(Netnews Message File) merged
+with your home directory.
+@enddefcom
+
+@defcom[com "Netnews Headers File Message", stuff (bound to @bf[o] in @hid{News-Headers} mode)]
+This command prompts for a mail folder and files the message under the
+point into it.  If the folder does not exist, @hemlock will ask if it should
+be created.
+@enddefcom
+
+@defcom[com "Netnews Message File Message", stuff (bound to @bf[o] in @hid{News-Message} mode)]
+This command prompts for a mail folder and files the current message there.
+If the folder does not exist, @hemlock will ask if it should be created.
+@enddefcom
+
+@defcom[com "Fetch All Headers", stuff (bound to @bf[f] in @hid{Netnews Headers} mode)]
+   In a forward reading @hid(Netnews headers) buffer, this command inserts
+   all headers after the last visible one into the headers buffer.  If
+   @hemlock is reading this group backward, the system inserts all headers
+   before the first visible one into the headers buffer.
+@enddefcom
+
+@defcom[com "Netnews Go to Next Group", stuff (bound to @bf[g] in @hid{News-Headers} and @hid{News-Message} modes.)]
+This command goes to the next group in your @hid(Netnews Group File).
+Before going on, it sets the group pointer in @hid(Netnews Database
+Filename) to the last message you read.  With an argument, the command does
+not modify the group pointer for the current group.
+@enddefcom
+
+@defcom[com "Netnews Quit Starting Here", stuff (bound to @bf[.] in @hid{News-Headers} and @hid{News-Message} modes)]
+   This command goes to the next group in your @hid(Netnews Group File), 
+   setting the netnews pointer for this group to the message before the one
+   under the current point, so the next time you read this group, the message
+   indicated by the point will appear first.
+@enddefcom
+
+@defcom[com "Netnews Group Punt Messages", stuff (bound to @bf[G] in @hid{News-Headers} mode)]
+   This command goes on to the next bulletin board in your group
+   file.  Without an argument, the system sets the pointer for the current
+   group to the last message.  With an argument, @hemlock sets the
+   pointer to the last visible message in the group.
+@enddefcom
+
+@defcom[com "Netnews Exit", stuff (bound to @bf[q] in @hid{News-Headers} mode)]
+@defhvar1[var "Netnews Exit Confirm", val {t}]
+   This command cleans up and deletes the @hid(News-Headers) buffer and
+   all associated @hid(News-Message) buffers.  If the value of
+   @hid(Netnews Exit Confirm) is @nil, then @hemlock will not prompt before
+   exiting.
+@enddefcom
+
+@section[Replying to Messages]
+
+The @hemlock Netnews interface also provides an easy way of replying to
+messages through the @hemlock Mailer or via @hid{Post} mode.
+
+@defcom[com "Netnews Reply to Sender"]
+   When you invoke this command, @hemlock creates a @hid(Draft) buffer and
+   tries to fill in the @i(to) and @i(subject) fields of the draft.  For
+   the @i(to) field, @hemlock looks at the @i(reply-to) field of the
+   message you are replying to, or failing that, the @i(from) field.  If
+   the @i(subject) field does not start with @f(Re:), @hemlock inserts this
+   string, signifying that this is a reply.
+@enddefcom
+
+@defcom[com "Netnews Reply to Sender in Other Window", stuff (bound to @bf[r] in @hid{News-Headers} and @hid{News-Message}.)]
+This command splits the current window, placing the message you are
+replying to in the top window and a new @hid{Draft} buffer in the bottom
+one.  This command fills in the header fields in the same manner as
+@hid(Netnews Reply to Sender).
+@enddefcom
+
+@defcom[com "Netnews Reply to Group"]
+This command creates a @hid{Post} buffer with the @i(newsgroups) field set
+to the current group and the @i(subject) field constructed in the same way
+as in @hid(Netnews Reply to Sender).
+@enddefcom
+
+@defcom[com "Netnews Reply to Group in Other Window", stuff (bound to @bf[R] in @hid{News-Headers} and @hid{News-Message}.)]
+   This command splits the current window, placing the message you are
+   replying to in the top window and a new @hid{Post} buffer in the bottom
+   one.  This command will fill in the header fields in the same manner as
+   @hid(Netnews Reply to Group).
+@enddefcom
+
+@defcom[com "Netnews Post Message", stuff (bound to @bf[C-x P])]
+   This command creates a @hid{Post} buffer.  If you are in a 
+   @hid(News-Headers) or @hid{News-Message} buffer, @hemlock fills in the
+   @i(newsgroups) field with the current group.
+@enddefcom
+
+@defcom[com "Netnews Forward Message", stuff (bound to @bf[f] in @hid{News-Headers} and @hid{News-Message} modes.)]
+This command creates a @hid{Post} buffer.  If you are in a @hid{Netnews
+Headers} or @hid{News-Message} buffer, @hemlock will put the text of the
+current message into the buffer along with lines delimiting the forwarded
+message.
+@enddefcom
+
+@defcom[com "Netnews Goto Post Buffer", stuff (bound to @bf[H-p] in @hid{News-Message} mode)]
+   This command, when invoked in a @hid(News-Message) or @hid(Draft) buffer
+   with an associated @hid(News-Headers) buffer, places the associated
+   @hid(News-Headers) buffer into the current window.
+@enddefcom
+
+@defcom[com "Netnews Goto Draft Buffer", stuff (bound to @bf[H-d] in @hid{News-Message} mode)]
+   This command, when invoked in a @hid(News-Message) buffer with an 
+   associated @hid(Draft) buffer, places the @hid(Draft) buffer into the 
+   current window.
+@enddefcom
+
+@section[Posting Messages]
+
+@defcom[com "Netnews Deliver Post", stuff (bound to @bf[H-s] in @hid{Post} mode)]
+@defhvar1[var "Netnews Deliver Post Confirm", val "t"]
+This command delivers the contents of a @hid(Post) buffer to the NNTP
+server.  If @hid(Netnews Deliver Post Confirm) is @f(t), @hemlock will ask for
+confirmation before posting the message.  @hemlock feeps you if NNTP does
+not accept the message.
+@enddefcom
+
+@defcom[com "Netnews Abort Post", stuff (bound to @bf[H-q] in @hid{Post} mode)]
+   This command deletes the current @hid(Post) buffer.
+@enddefcom
+
+
+As in the mailer, when replying to a message you can be excerpt sections of
+it using @hid(Insert Message Buffer) and @hid(Insert Message Region) in
+@hid(Post) and @hid(News-Message) modes, respectively.  You can also use
+these commands when replying to a message via mail in a @hid(Draft) buffer.
+In all cases, the same binding is used: @bf[H-y].
+
+@newpage
+@section[Wallchart]
+
+@tabclear
+@tabdivide(5)
+
+@begin[format, spacing 1.5]
+
+
+@Begin[Center] @b[Global bindings:] @End[Center]
+
+@hid[Netnews Post Message]@\@\@bf[C-x P]
+
+
+@Begin[Center] @b[News-Headers and News-Message modes bindings:] @End[Center]
+
+@hid[Netnews Next Article]@\@\@\@bf[n]
+@hid[Netnews Previous Article]@\@\@bf[p]
+@hid[Netnews Go to Next Group]@\@\@bf[g]
+@hid[Netnews Group Punt Messages]@\@\@bf[G]
+@hid[List All Groups]@\@\@\@bf[l]
+@hid[Netnews Append to File]@\@\@bf[a]
+@hid[Netnews Forward Message]@\@\@bf[f]
+@hid[Netnews Reply to Sender in Other Window]@\@\@bf[r]
+@hid[Netnews Reply to Group in Other Window]@\@\@bf[R]
+@hid[Netnews Quit Starting Here]@\@\@bf[.]
+
+@Begin[Center] @b[News-Headers mode bindings:] @End[Center]
+
+@hid[Netnews Show Article]@\@\@bf[Space]
+@hid[Netnews Previous Line]@\@\@bf[C-p], @bf[Uparrow]
+@hid[Netnews Next Line]@\@\@\@bf[C-n], @bf[Downarrow]
+@hid[Netnews Headers Scroll Window Down]@\@\@bf[C-v]
+@hid[Netnews Headers Scroll Window Up]@\@\@bf[M-v]
+@hid[Netnews Select Message Buffer]@\@\@bf[H-m]
+@hid[Netnews Exit]@\@\@\@bf[q]
+@hid[Netnews Headers File Message]@\@\@bf[o]
+
+
+@Begin[Center] @b[News-Message mode bindings:] @End[Center]
+
+@hid[Netnews Message Scroll Down]@\@\@bf[Space]
+@hid[Scroll Window Up]@\@\@\@bf[Backspace]
+@hid[Netnews Goto Headers Buffer]@\@\@bf[H-h], @bf[^]
+@hid[Netnews Message Keep Buffer]@\@\@bf[k]
+@hid[Netnews Message Quit]@\@\@bf[q]
+@hid[Netnews Message File Message]@\@\@bf[o]
+@hid[Netnews Goto Post Buffer]@\@\@bf[H-p]
+@hid[Netnews Goto Draft Buffer]@\@\@bf[H-d]
+@hid[Insert Message Region]@\@\@bf[H-y]
+
+
+@Begin[Center] @b[Post mode bindings:] @End[Center]
+
+@hid[Netnews Select Message Buffer]@\@\@bf[H-m]
+@hid[Netnews Deliver Post]@\@\@bf[H-s]
+@hid[Netnews Abort Post]@\@\@\@bf[H-q]
+@hid[Insert Message Buffer]@\@\@bf[H-y]
+
+
+@Begin[Center] @b[News-Browse mode bindings:] @End[Center]
+
+@hid[Netnews Quit Browse]@\@\@bf[q]
+@hid[Netnews Browse Add Group To File]@\@\@bf[a]
+@hid[Netnews Browse Read Group]@\@\@bf[Space]
+@hid[Next Line]@\@\@\@bf[n]
+@hid[Previous Line]@\@\@\@bf[p]
+
+
+@end[format]
+@tabclear
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/special-modes.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/special-modes.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/special-modes.mss	(revision 13309)
@@ -0,0 +1,738 @@
+@comment{-*- Dictionary: bld:scribe/hem/hem; Mode: spell; Package: Hemlock -*-}
+@chap[Special Modes]
+
+@section[Dired Mode]
+@label[dired]
+@index[directory editing]
+
+@hemlock provides a directory editing mechanism.  The user can flag files and
+directories for deletion, undelete flagged files, and with a keystroke read in
+files and descend into directories.  In some implementations, it also supports
+copying, renaming, and a simple wildcard feature.
+
+
+@subsection[Inspecting Directories]
+@defcom[com "Dired", bind (C-x C-M-d)]
+This command prompts for a directory and fills a buffer with a verbose listing
+of that directory.  When the prefix argument is supplied, this includes Unix
+dot files.  If a dired buffer already exists for the directory, this switches
+to the buffer and makes sure it displays dot files if appropriate.
+@enddefcom
+
+@defcom[com "Dired with Pattern", bind (C-x C-M-d)]
+This command prompts for a directory and a pattern that may contain at most one
+wildcard, an asterisk, and it fills a buffer with a verbose listing of the
+files in the directory matching the pattern.  When the prefix argument is
+supplied, this includes Unix dot files.  If a dired buffer already exists for
+this directory, this switches to the buffer and makes sure it displays dot
+files if appropriate.
+@enddefcom
+
+@defcom[com "Dired from Buffer Pathname"]
+This command invokes @hid[Dired] on the directory name of the current buffer's
+pathname.
+@enddefcom
+
+@defcom[com "Dired Help", bind (Dired: ?)]
+This command pops up a help window listing the various @hid[Dired] commands.
+@enddefcom
+
+@defcom[com "Dired View File", bind (Dired: Space)]
+@defcom1[com "Dired Edit File", bind (Dired: e)]
+These command read in the file on the current line with the point.  If the line
+describes a directory instead of a file, then this command effectively invokes
+@hid[Dired] on the specification.  This associates the file's buffer with the
+@hid[Dired] buffer.
+
+@hid[Dired View File] reads in the file as if by @hid[View File], and
+@hid[Dired Edit File] as if by @hid[Find File].
+
+@hid[Dired View File] always reads into a newly created buffer, warning if the
+file already exists in some buffer.
+@enddefcom
+
+@defcom[com "Dired Up Directory", bind (Dired: ^)]
+This command invokes @hid[Dired] on the directory up one level from the current
+@hid[Dired] buffer.  This is useful for going backwards after repeatedly
+invoking @hid[Dired View File] and descending into a series of subdirectories.
+Remember, @hid[Dired] only generates directory listings when no buffer contains
+a dired for the specified directory.
+@enddefcom
+
+@defcom[com "Dired Update Buffer", bind (Dired: H-u)]
+This command is useful when the user knows the directory in the current
+@hid[Dired] buffer has changed.  @hemlock cannot know the directory structure
+has changed, but the user can explicitly update the buffer with this command
+instead of having to delete it and invoke @hid[Dired] again.
+@enddefcom
+
+@defcom[com "Dired Next File"]
+@defcom1[com "Dired Previous File"]
+These commands move to next or previous undeleted file.
+@enddefcom
+
+
+@subsection[Deleting Files]
+@defcom[com "Dired Delete File and Down Line", bind (Dired: d)]
+This command marks for deletion the file on the current line with the point and
+moves point down a line.
+@enddefcom
+
+@defcom[com "Dired Delete File with Pattern", bind (Dired: D)]
+This command prompts for a name pattern that may contain at most one wildcard,
+an asterisk, and marks for deletion all the names matching the pattern.
+@enddefcom
+
+@defcom[com "Dired Delete File", bind (Dired: C-d)]
+This command marks for deletion the file on the current line with the point
+without moving the point.
+@enddefcom
+
+
+@subsection[Undeleting Files]
+@defcom[com "Dired Undelete File and Down Line", bind (Dired: u)]
+This command unmarks for deletion the file on the current line with the point
+and moves point down a line.
+@enddefcom
+
+@defcom[com "Dired Undelete File with Pattern", bind (Dired: U)]
+This command prompts for a name pattern that may contain at most one wildcard,
+an asterisk, and unmarks for deletion all the names matching the pattern.
+@enddefcom
+
+@defcom[com "Dired Undelete File", bind (Dired: C-u)]
+This command unmarks for deletion the file on the current line with the point
+without moving the point.
+@enddefcom
+
+
+@subsection[Expunging and Quitting]
+@defcom[com "Dired Expunge Files", bind (Dired: !)]
+@defhvar1[var "Dired File Expunge Confirm", val {t}]
+@defhvar1[var "Dired Directory Expunge Confirm", val {t}]
+This command deletes files marked for deletion, asking the user for
+confirmation once for all the files flagged.  It recursively deletes any marked
+directories, asking the user for confirmation once for all those marked.
+@hid[Dired File Expunge Confirm] and @hid[Dired Directory Expunge Confirm] when
+set to @nil individually inhibit the confirmation prompting for the appropriate
+deleting.
+@enddefcom
+
+@defcom[com "Dired Quit", bind (Dired: q)]
+This command expunges any marked files or directories as if by @hid[Expunge
+Dired Files] before deleting the @hid[Dired] buffer.
+@enddefcom
+
+
+@subsection[Copying Files]
+@defcom[com "Dired Copy File", bind (Dired: c)]
+This command prompts for a destination specification and copies the file on the
+line with the point.  When prompting, the current line's specification is the
+default, which provides some convenience in supplying the destination.  The
+destination is either a directory specification or a file name, and when it is
+the former, the source is copied into the directory under its current file name
+and extension.
+@enddefcom
+
+@defcom[com "Dired Copy with Wildcard", bind (Dired: C)]
+This command prompts for a name pattern that may contain at most one wildcard,
+an asterisk, and copies all the names matching the pattern.  When prompting for
+a destination, this provides the @hid[Dired] buffer's directory as a default.
+The destination is either a directory specification or a file name with a
+wildcard.  When it is the former, all the source files are copied into the
+directory under their current file names and extensions.  When it is the later,
+each sources file's substitution for the wildcard causing it to match the first
+pattern replaces the wildcard in the destination pattern; for example, you
+might want to copy @f["*.txt"] to @f["*.text"].
+@enddefcom
+
+@defhvar[var "Dired Copy File Confirm", val {t}]
+@label[copy-confirm]
+This variable controls interaction with the user when it is not obvious what
+the copying process should do.  This takes one of the following values:
+@Begin[Description]
+@true@\
+When the destination specification exists, the copying process stops and asks
+the user if it should overwrite the destination.
+
+@nil@\
+The copying process always copies the source file to the destination
+specification without interacting with the user.
+
+@kwd[update]@\
+When the destination specification exists, and its write date is newer than
+the source's write date, then the copying process stops and asks the user if it
+should overwrite the destination.
+@End[Description]
+@enddefhvar
+
+
+@subsection[Renaming Files]
+@defcom[com "Dired Rename File", bind (Dired: r)]
+Rename the file or directory under the point
+@enddefcom
+
+@defcom[com "Dired Rename with Wildcard", bind (Dired: R)]
+Rename files that match a pattern containing ONE wildcard.
+@enddefcom
+
+@defhvar[var "Dired Rename File Confirm", val {t}]
+When non-nil, @hid[Dired] will query before clobbering an existing file.
+@enddefhvar
+
+
+@section[View Mode]
+@hid[View] mode provides for scrolling through a file read-only, terminating
+the buffer upon reaching the end.
+
+@defcom[com "View File"]
+This command reads a file into a new buffer as if by "Visit File", but
+read-only.  Bindings exist for scrolling and backing up in a single key stroke.
+@enddefcom
+
+@defcom[com "View Help", bind (View: ?)]
+This command shows a help message for @hid[View] mode.
+@enddefcom
+
+@defcom[com "View Edit File", bind (View: e)]
+This commands makes a buffer in @hid[View] mode a normal editing buffer,
+warning if the file exists in another buffer simultaneously.
+@enddefcom
+
+@defcom[com "View Scroll Down", bind (View: Space)]
+@defhvar1[var "View Scroll Deleting Buffer", val {t}]
+This command scrolls the current window down through its buffer.  If the end of
+the file is visible, then this deletes the buffer if @hid[View Scroll Deleting
+Buffer] is set.  If the buffer is associated with a @hid[Dired] buffer, this
+returns there instead of to the previous buffer.
+@enddefcom
+
+@defcom[com "View Return", bind (View: ^)]
+@defcom1[com "View Quit", bind (View: q)]
+These commands invoke a function that returns to the buffer that created the
+current buffer in @hid[View] mode.  Sometimes this function does nothing, but
+it is useful for returning to @hid[Dired] buffers and similar @hemlock
+features.
+
+After invoking the viewing return function if there is one, @hid[View Quit]
+deletes the buffer that is current when the user invokes it.
+@enddefcom
+
+Also, bound in @hid[View] mode are the following commands:
+@Begin[Description]
+@binding[backspace], @binding[delete]@\Scrolls the window up.
+
+@binding[<]@\Goes to the beginning of the buffer.
+
+@binding[>]@\Goes to the end of the buffer.
+@End[Description]
+
+
+@section[Process Mode]
+@Label[process]
+@Index[shells]
+@Index[processes]
+
+@hid[Process] mode allows the user to execute a Unix process within a @hemlock
+buffer.  These commands and default bindings cater to running Unix shells in
+buffers.  For example, @hid[Stop Buffer Subprocess] is bound to @binding[H-z]
+to stop the process you are running in the shell instead of binding @hid[Stop
+Main Process] to this key which would stop the shell itself.
+
+@defcom[com "Shell", bind (C-M-s)]
+@defhvar1[var "Shell Utility", val {"/bin/csh"}]
+@defhvar1[var "Shell Utility Switches", val {@nil}]
+@defhvar1[var "Current Shell"]
+@defhvar1[var "Ask about Old Shells"]
+This command executes the process determined by the values of @hid(Shell
+Utility) and @hid(Shell Utility Switches) in a new buffer named @f["Shell n"]
+where @f["n"] is some distinguishing integer.
+
+@hid[Current Shell] is a @hemlock variable that holds to the current shell
+buffer.  When @hid[Shell] is invoked, if there is a @hid[Current Shell], the
+command goes to that buffer.
+
+When there is no @hid[Current Shell], but shell buffers do exist, if @hid[Ask
+about Old Shells] is set, the @hid[Shell] command prompts for one of them,
+setting @hid[Current Shell] to the indicated shell, and goes to the buffer.
+
+Invoking @hid[Shell] with an argument forces the creation of a new shell
+buffer.
+
+@hid[Shell Utility] is the string name of the process to execute.
+
+@hid[Shell Utility Switches] is a string containing the default command line
+arguments to @hid[Shell Utility].  This is a string since the utility is
+typically @f["/bin/csh"], and this string can contain I/O redirection and other
+shell directives.
+@enddefcom
+
+@defcom[com "Shell Command Line in Buffer"]
+This command prompts for a buffer and a shell command line.  It then runs a
+shell, giving it the command line, in the buffer.
+@enddefcom
+
+@defcom[com "Set Current Shell"]
+This command sets the value of @hid[Current Shell].
+@enddefcom
+
+@defcom[com "Stop Main Process"]
+This command stops the process running in the current buffer by sending a
+@f[:SIGTSTP] to that process.  With an argument, stops the process using
+@f[:SIGSTOP].
+@enddefcom
+
+@defcom[com "Continue Main Process"]
+If the process in the current buffer is stopped, this command continues it.
+@enddefcom
+
+@defcom[com "Kill Main Process"]
+@defhvar1[var "Kill Process Confirm", val {t}]
+This command prompts for confirmation and kills the process running in the
+current buffer.
+
+Setting this variable to @nil inhibits @hemlock@comment{}'s prompting for confirmation.
+@enddefcom
+
+@defcom[com "Stop Buffer Subprocess", stuff (bound to @bf[H-z] in @hid[Process] mode)]
+This command stops the foreground subprocess of the process in the current
+buffer, similar to the effect of @binding[C-Z] in a shell.
+@enddefcom
+
+@defcom[com "Kill Buffer Subprocess"]
+This command kills the foreground subprocess of the process in the current
+buffer.
+@enddefcom
+
+@defcom[com "Interrupt Buffer Subprocess", stuff (bound to  @bf[H-c] in @hid[Process] mode)]
+This command interrupts the foreground subprocess of the process in the
+current buffer, similar to the effect of @binding[C-C] in a shell.
+@enddefcom
+
+@defcom[com "Quit Buffer Subprocess", stuff (bound to @bf[H-\] in @hid[Process] mode)]
+This command dumps the core of the foreground subprocess of the processs in
+the current buffer, similar to the effect of @binding[C-\] in a shell.
+@enddefcom
+
+@defcom[com "Send EOF to Process", stuff (bound to @bf[H-d] in @hid[Process] mode)]
+This command sends the end of file character to the process in the current
+buffer, similar to the effect of @binding[C-D] in a shell.
+@enddefcom
+
+@defcom[com "Confirm Process Input", stuff (bound to @bf[Return] in @hid[Process] mode)]
+This command sends the text the user has inserted at the end of a process
+buffer to the process in that buffer.  Resulting output is inserted at the end
+of the process buffer.
+@enddefcom
+
+The user may edit process input using commands that are shared with
+@hid[Typescript] mode, see section @ref[typescripts].
+
+
+@section[Bufed Mode]
+@hemlock provides a mechanism for managing buffers as an itemized list.
+@hid[Bufed] supports conveniently deleting several buffers at once, saving
+them, going to one, etc., all in a key stroke.
+
+@defcom[com "Bufed", bind (C-x C-M-b)]
+This command creates a list of buffers in a buffer supporting operations such
+as deletion, saving, and selection.  If there already is a @hid[Bufed] buffer,
+this just goes to it.
+@enddefcom
+
+@defcom[com "Bufed Help"]
+This command pops up a display of @hid[Bufed] help.
+@enddefcom
+
+@defcom[com "Bufed Delete", bind (Bufed: C-d, C-D, D, d)]
+@defhvar1[var "Virtual Buffer Deletion", val {t}]
+@defhvar1[var "Bufed Delete Confirm", val {t}]
+@hid[Bufed Delete] deletes the buffer on the current line.
+
+When @hid[Virtual Buffer Deletion] is set, this merely flags the buffer for
+deletion until @hid[Bufed Expunge] or @hid[Bufed Quit] executes.
+
+Whenever these commands actually delete a buffer, if @hid[Bufed Delete Confirm]
+is set, then @hemlock prompts the user for permission; if more than one buffer
+is flagged for deletion, this only prompts once.  For each modified buffer,
+@hemlock asks to save the buffer before deleting it.
+@enddefcom
+
+@defcom[com "Bufed Undelete", bind (Bufed: U, u)]
+This command undeletes the buffer on the current line.
+@enddefcom
+
+@defcom[com "Bufed Expunge", bind (Bufed: !)]
+This command expunges any buffers marked for deletion regarding @hid[Bufed
+Delete Confirm].
+@enddefcom
+
+@defcom[com "Bufed Quit", bind (Bufed: q)]
+This command kills the @hid[Bufed] buffer, expunging any buffers marked for
+deletion.
+@enddefcom
+
+@defcom[com "Bufed Goto", bind (Bufed: Space)]
+This command selects the buffer on the current line, switching to it.
+@enddefcom
+
+@defcom[com "Bufed Goto and Quit", bind (Bufed: S-leftdown)]
+This command goes to the buffer under the pointer, quitting @hid[Bufed].  It
+supplies a function for @hid[Generic Pointer Up] which is a no-op.
+@enddefcom
+
+@defcom[com "Bufed Save File", bind (Bufed: s)]
+This command saves the buffer on the current line.
+@enddefcom
+
+
+@section[Completion]
+This is a minor mode that saves words greater than three characters in length,
+allowing later completion of those words.  This is very useful for the often
+long identifiers used in Lisp programs.  As you type a word, such as a Lisp
+symbol when in @hid[Lisp] mode, and you progress to typing the third letter,
+@hemlock displays a possible completion in the status line.  You can then
+rotate through the possible completions or type some more letters to narrow
+down the possibilities.  If you choose a completion, you can also rotate
+through the possibilities in the buffer instead of in the status line.
+Choosing a completion or inserting a character that delimits words moves the
+word forward in the ring of possible completions, so the next time you enter
+its initial characters, @hemlock will prefer it over less recently used
+completions.
+
+@defcom[com "Completion Mode"]
+This command toggles @hid[Completion] mode in the current buffer.
+@enddefcom
+
+@defcom[com "Completion Self Insert"]
+This command is like @hid[Self Insert], but it also checks for possible
+completions displaying any result in the status line.  This is bound to most of
+the key-events with corresponding graphic characters.
+@enddefcom
+
+@defcom[com "Completion Complete Word", bind (Completion: End)]
+This command selects the currently displayed completion if there is one,
+guessing the case of the inserted text as with @hid[Query Replace].  Invoking
+this immediately in succession rotates through possible completions in the
+buffer.  If there is no currently displayed completion on a first invocation,
+this tries to find a completion from text immediately before the point and
+displays the completion if found.
+@enddefcom
+
+@defcom[com "Completion Rotate Completions", bind (Completion: M-End)]
+This command displays the next possible completion in the status line.  If
+there is no currently displayed completion, this tries to find a completion
+from text immediately before the point and displays the completion if found.
+@enddefcom
+
+@defcom[com "List Possible Completions"]
+This command lists all the possible completions for the text immediately before
+the point in a pop-up display.  Sometimes this is more useful than rotating
+through several completions to see if what you want is available.
+@enddefcom
+
+@defhvar[var "Completion Bucket Size", val {20}]
+Completions are stored in buckets determined by the first three letters of a
+word. This variable limits the number of completions saved for each combination
+of the first three letters of a word.  If you have many identifier in some
+module beginning with the same first three letters, you'll need increase this
+variable to accommodate all the names.
+@enddefhvar
+
+
+@defcom[com "Save Completions"]
+@defcom1[com "Read Completions"]
+@defhvar1[var "Completion Database Filename", val {nil}]
+@hid[Save Completions] writes the current completions to the file
+@hid[Completion Database Filename].  It writes them, so @hid[Read Completions]
+can read them back in preserving the most-recently-used order.  If the user
+supplies an argument, then this prompts for a pathname.
+
+@hid[Read Completions] reads completions saved in @hid[Completion Database
+Filename].  It moves any current completions to a less-recently-used status,
+and it removes any in a given bucket that exceed the limit @hid[Completion
+Bucket Size].
+@enddefcom
+
+@defcom[com "Parse Buffer for Completions"]
+This command passes over the current buffer putting each valid completion word
+into the database.  This is a good way of picking up many useful completions
+upon visiting a new file for which there are no saved completions.
+@enddefcom
+
+
+@section[CAPS-LOCK Mode]
+
+@hid[CAPS-LOCK] is a minor mode in which @hemlock that inserts all alphabetic
+characters as uppercase letters.
+
+@defcom[com "Caps Lock Mode"]
+This command toggles @hid[CAPS-LOCK] mode for the current buffer; it is most
+useful when bound to a key, so you can enter and leave @hid[CAPS-LOCK] mode
+casually.
+@enddefcom
+
+@defcom[com "Self Insert Caps Lock"]
+This command inserts the uppercase version of the character corresponding to
+the last key-event typed.
+@enddefcom
+
+
+
+@section[Overwrite Mode]
+
+@hid[Overwrite] mode is a minor mode which is useful for creating figures and
+tables out of text.  In this mode, typing a key-event with a corresponding
+graphic character replaces the character at the point instead of inserting the
+character.  @hid[Quoted Insert] can be used to insert characters normally.
+
+@defcom[com "Overwrite Mode"]
+This command turns on @hid[Overwrite] mode in the current buffer.  If it is
+already on, then it is turned off.  A positive argument turns @hid[Overwrite]
+mode on, while zero or a negative argument turns it off.
+@enddefcom
+
+@defcom[com "Self Overwrite"]
+This command replaces the next character with the character corresponding to
+the key-event used to invoke the command.  After replacing the character, this
+moves past it.  If the next character is a tab, this first expands the tab into
+the appropriate number of spaces, replacing just the next space character.
+At the end of the line, it inserts the
+character instead of clobbering the newline.
+
+This is bound to key-events with corresponding graphic characters in
+@hid[Overwrite] mode.
+@enddefcom
+
+@defcom[com "Overwrite Delete Previous Character",
+       stuff (bound to @bf[Delete] and @bf[Backspace] in @hid[Overwrite] mode)]
+This command replaces the previous character with a space and moves backwards.
+This deletes tabs and newlines.
+@enddefcom
+
+
+@section[Word Abbreviation]
+@index[word abbreviation]
+Word abbreviation provides a way to speed the typing of frequently used words
+and phrases.  When in @hid[Abbrev] mode, typing a word delimiter causes the
+previous word to be replaced with its @i[expansion] if there is one currently
+defined.  The expansion for an abbrev may be any string, so this mode can be
+used for abbreviating programming language constructs and other more obscure
+uses.  For example, @hid[Abbrev] mode can be used to automatically correct
+common spelling mistakes and to enforce consistent capitalization of
+identifiers in programs.
+
+@i[Abbrev] is an abbreviation for @i[abbreviation], which is used for
+historical reasons.  Obviously the original writer of @hid[Abbrev] mode hated
+to type long words and could hardly use @hid[Abbrev] mode while writing
+@hid[Abbrev] mode. 
+
+A word abbrev can be either global or local to a major mode.  A global word
+abbrev is defined no matter what the current major mode is, while a mode word
+abbrev is only defined when its mode is the major mode in the current buffer.
+Mode word abbrevs can be used to prevent abbrev expansion in inappropriate
+contexts.
+
+
+@subsection[Basic Commands]
+
+@defcom[com "Abbrev Mode"]
+This command turns on @hid[Abbrev] mode in the current buffer.  If @hid[Abbrev]
+mode is already on, it is turned off.  @hid[Abbrev] mode must be on for the
+automatic expansion of word abbrevs to occur, but the abbreviation commands are
+bound globally and may be used at any time.
+@enddefcom
+
+@defcom[com "Abbrev Expand Only", 
+        stuff (bound to word-delimiters in @hid[Abbrev] mode)]
+This is the word abbrev expansion command.  If the word before the point is a
+defined word abbrev, then it is replaced with its expansion.  The replacement
+is done using the same case-preserving heuristic as is used by
+@hid[Query Replace].  This command is globally bound to @binding[M-Space] so
+that abbrevs can be expanded when @hid[Abbrev] mode is off.  An undesirable
+expansion may be inhibited by using @binding[C-q] to insert the delimiter.
+@enddefcom
+
+@defcom[com "Inverse Add Global Word Abbrev", bind (C-x -)]
+@defcom1[com "Inverse Add Mode Word Abbrev", bind (C-x C-h, C-x Backspace)]
+@hid[Inverse Add Global Word Abbrev] prompts for a string and makes it the
+global word abbrev expansion for the word before the point.
+
+@hid[Inverse Add Mode Word Abbrev] is identical to 
+@hid[Inverse Add Global Word Abbrev] except that it defines an expansion which
+is local to the current major mode.
+@enddefcom
+
+@defcom[com "Make Word Abbrev"]
+This command defines an arbitrary word abbreviation.  It prompts for the mode,
+abbreviation and expansion.  If the mode @f["Global"] is specified, then it
+makes a global abbrev.
+@enddefcom
+
+@defcom[com "Add Global Word Abbrev", bind (C-x +)]
+@defcom1[com "Add Mode Word Abbrev", bind (C-x C-a)]
+@hid[Add Global Word Abbrev] prompts for a word and defines it to be a global
+word abbreviation.  The prefix argument determines which text is used as the
+expansion:
+@begin[description]
+@i[no prefix argument]@\The word before the point is used as the expansion of
+the abbreviation.
+
+@i[zero prefix argument]@\The text in the region is used as the expansion of the
+abbreviation.
+
+@i[positive prefix argument]@\That many words before the point are made the
+expansion of the abbreviation.
+
+@i[negative prefix argument]@\Do the same thing as 
+@hid[Delete Global Word Abbrev] instead of defining an abbreviation.
+@end[description]
+
+@hid[Add Mode Word Abbrev] is identical to @hid[Add Global Word Abbrev] except
+that it defines or deletes mode word abbrevs in the current major mode.
+@enddefcom
+
+@defcom[com "Word Abbrev Prefix Mark", bind (M-")]
+This command allows @hid[Abbrev Expand Only] to recognize abbreviations when
+they have prefixes attached.  First type the prefix, then use this command.  A
+hyphen (@f[-]) will be inserted in the buffer.  Now type the abbreviation and
+the word delimiter.  @hid[Abbrev Expand Only] will expand the abbreviation and
+remove the hyphen.
+
+Note that there is no need for a suffixing command, since 
+@hid[Abbrev Expand Only] may be used explicitly by typing @binding[M-Space].
+@enddefcom
+
+@defcom[com "Unexpand Last Word", bind (C-x u)]
+This command undoes the last word abbrev expansion.  If repeated, undoes its
+own effect.
+@enddefcom
+
+
+@subsection[Word Abbrev Files]
+A word abbrev file is a file which holds word abbrev definitions.  Word abbrev
+files allow abbrevs to be saved so that they may be used across many editing
+sessions.
+
+@defhvar[var "Abbrev Pathname Defaults", val {(pathname "abbrev.defns")}]
+This is sticky default for the following commands.  When they prompt for a file
+to write, they offer this and set it for the next time one of them executes.
+@enddefhvar
+
+@defcom[com "Read Word Abbrev File"]
+This command reads in a word abbrev file, adding all the definitions to those
+currently defined.  If a definition in the file is different from the current
+one, the current definition is replaced.
+@enddefcom
+
+@defcom[com "Write Word Abbrev File"]
+This command prompts for a file and writes all currently defined word abbrevs
+out to it.
+@enddefcom
+
+@defcom[com "Append to Word Abbrev File"]
+This command prompts for a word abbrev file and appends any new definitions to
+it.  An abbrev is new if it has been defined or redefined since the last use of
+this command.  Definitions made by reading word abbrev files are not
+considered.
+@enddefcom
+
+
+@subsection[Listing Word Abbrevs]
+@defcom[com "List Word Abbrevs"]
+@defcom1[com "Word Abbrev Apropos"]
+@hid[List Word Abbrevs] displays a list of each defined word abbrev, with its
+mode and expansion.
+
+@hid[Word Abbrev Apropos] is similar, except that it only displays abbrevs
+which contain a specified string, either in the definition, expansion or mode.
+@enddefcom
+
+@subsection[Editing Word Abbrevs]
+Word abbrev definition lists are edited by editing the text representation
+of the definitions.  Word abbrev files may be edited directly, like any other
+text file.  The set of abbrevs currently defined in @hemlock may be edited
+using the commands described in this section.
+
+The text representation of a word abbrev is fairly simple.  Each definition
+begins at the beginning of a line.  Each line has three fields which are
+separated by ASCII tab characters.  The fields are the abbreviation, the mode
+of the abbreviation and the expansion.  The mode is represented as the mode
+name inside of parentheses.  If the abbrev is global, then the mode field is
+empty.  The expansion is represented as a quoted string since it may contain
+any character.  The string is quoted with double-quotes (@f["]); double-quotes
+in the expansion are represented by doubled double-quotes.  The expansion may
+contain newline characters, in which case the definition will take up more than
+one line.
+
+@defcom[com "Edit Word Abbrevs"]
+This command inserts the current word abbrev definitions into the 
+@hid[Edit Word Abbrevs] buffer and then enters a recursive edit on the buffer.
+When the recursive edit is exited, the definitions in the buffer become the new
+current abbrev definitions.
+@enddefcom
+
+@defcom[com "Insert Word Abbrevs"]
+This command inserts at the point the text representation of the currently
+defined word abbrevs.
+@enddefcom
+
+@defcom[com "Define Word Abbrevs"]
+This command interprets the text of the current buffer as a word abbrev
+definition list, adding all the definitions to those currently defined.
+@enddefcom
+
+
+@subsection[Deleting Word Abbrevs]
+The user may delete word abbrevs either individually or collectively.
+Individual abbrev deletion neutralizes single abbrevs which have outlived their
+usefulness; collective deletion provides a clean slate from which to initiate
+abbrev definitions.
+
+@defcom[com "Delete All Word Abbrevs"]
+This command deletes all word abbrevs which are currently defined.
+@enddefcom
+
+@defcom[com "Delete Global Word Abbrev"]
+@defcom1[com "Delete Mode Word Abbrev"]
+@hid[Delete Global Word Abbrev] prompts for a word abbreviation and deletes its
+global definition.  If given a prefix argument, deletes all global abbrev
+definitions.
+
+@hid[Delete Mode Word Abbrev] is identical to @hid[Delete Global Word Abbrev]
+except that it deletes definitions in the current major mode.
+@enddefcom
+
+
+@section[Lisp Library]
+This is an implementation dependent feature.  The Lisp library is a collection
+of local hacks that users can submit and share that is maintained by the Lisp
+group.  These commands help peruse the catalog or description files and figure
+out how to load the entries.
+
+@defcom[com "Lisp Library"]
+This command finds all the library entries and lists them in a buffer.  The
+following commands describe and load those entries.
+@enddefcom
+
+@defcom[com "Describe Library Entry", bind (Lisp-Lib: space)]
+@defcom1[com "Describe Pointer Library Entry", bind (Lisp-Lib: leftdown)]
+@defcom1[com "Load Library Entry", bind (Lisp-Lib: rightdown)]
+@defcom1[com "Load Pointer Library Entry", bind (Lisp-Lib: l)]
+@defcom1[com "Editor Load Library Entry"]
+@defcom1[com "Editor Load Pointer Library Entry"]
+@hid[Load Library Entry] and @hid[Load Pointer Library Entry] load the library
+entry indicated by the line on which the point lies or where the user clicked
+the pointer, respectively.  These load the entry into the current slave Lisp.
+
+@hid[Editor Load Library Entry] and @hid[Editor Load Pointer Library Entry] are
+the same, but they load the entry into the editor Lisp.
+@enddefcom
+
+@defcom[com "Exit Lisp Library", bind (Lisp-Lib: q)]
+This command deletes the @hid[Lisp Library] buffer.
+@enddefcom
+
+@defcom[com "Lisp Library Help", bind (Lisp-Lib: ?)]
+This command pops up a help window listing @hid[Lisp-Lib] commands.
+@enddefcom
Index: /branches/new-random/cocoa-ide/hemlock/doc/user/user.mss
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/doc/user/user.mss	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/doc/user/user.mss	(revision 13309)
@@ -0,0 +1,2003 @@
+@Make[Manual] @comment{-*- Dictionary: /afs/cs/project/clisp/scribe/hem/hem; Mode: spell; Package: Hemlock -*-}
+@Device[postscript]
+@Style(Spacing = 1.2 lines)
+@Style(StringMax = 5000)
+@Use(Database "/afs/cs/project/clisp/docs/database/")
+@Style(FontFamily=TimesRoman)
+@Style(Date="March 1952")
+@style(DOUBLESIDED)
+@Libraryfile[ArpaCredit]
+@libraryfile[hem]
+@Libraryfile[Spice]
+@Libraryfile[Uttir]
+
+@String(REPORTTITLE "Hemlock User's Manual")
+
+@comment<@begin[TitlePage]
+@begin[TitleBox]
+>
+@blankspace(1.3inches)
+@heading[Hemlock User's Manual]
+
+@center[@b<Bill Chiles>
+@b<Robert A. MacLachlan>
+
+
+@b<@value[date]>
+
+@b<CMU-CS-89-133-R1>
+]
+@comment<@end[TitleBox]>
+@blankspace(2lines)
+@begin[Center]
+School of Computer Science
+Carnegie Mellon University
+Pittsburgh, PA 15213
+@end[Center]
+@blankspace[2lines]
+
+@begin[Center]
+This is a revised version of Technical Report CMU-CS-87-158.
+@end[Center]
+
+@heading<Abstract>
+@begin(Text, indent 0)
+This document describes the @Hemlock text editor, version M3.2.  @Hemlock is a
+customizable, extensible text editor whose initial command set closely
+resembles that of ITS/TOPS-20 @Emacs.  @Hemlock is written in CMU Common Lisp
+and has been ported to other implementations.
+@end(Text)
+
+@begin[ResearchCredit]
+@ArpaCredit[Contract=Basic87-90]
+@end[ResearchCredit]
+@comment<@end[TitlePage]>
+
+
+@commandstring(mh = "@f1(MH)")
+@commandstring(dash = "@Y[M]")
+
+@comment[This tabclear is necessary since the definition macros don't
+	 take care of the own tabbing needs]
+@tabclear
+
+
+@comment[@chap (Introduction)]
+@include(intro)
+
+
+@comment[@chap (Basic Commands)]
+@include(commands)
+
+
+
+@chap[Files, Buffers, and Windows]
+
+@section[Introduction]
+
+@index[files]
+@index[buffers]
+@index[windows]
+@hemlock provides three different abstractions which are used in combination to
+solve the text-editing problem, while other editors tend to mash these ideas
+together into two or even one.
+@begin[description]
+File@\A file provides permanent storage of text.  @hemlock has commands
+to read files into buffers and write buffers out into files.
+
+Buffer@\A buffer provides temporary storage of text and a capability to
+edit it.  A buffer may or may not have a file associated with it; if it
+does, the text in the buffer need bear no particular relation to the text
+in the file.  In addition, text in a buffer may be displayed in any number
+of windows, or may not be displayed at all.
+
+Window@\A window displays some portion of a buffer on the screen.  There
+may be any number of windows on the screen, each of which may display any
+position in any buffer.  It is thus possible, and often useful, to have
+several windows displaying different places in the same buffer.
+@end[description]
+
+
+@section[Buffers]
+In addition to some text, a buffer has several other user-visible attributes:
+@begin[description]
+A name@\
+A buffer is identified by its name, which allows it to be selected, destroyed,
+or otherwise manipulated.
+
+A collection of modes@\
+The modes present in a buffer alter the set of commands available and
+otherwise alter the behavior of the editor.  For details see page
+@pageref[modes].
+
+A modification flag @\
+This flag is set whenever the text in a buffer is modified.  It is often
+useful to know whether a buffer has been changed, since if it has it should
+probably be saved in its associated file eventually.
+
+A write-protect flag @\
+If this flag is true, then any attempt to modify the buffer will result in an
+error.
+@end[description]
+
+@defcom[com "Select Buffer", bind (C-x b)]
+This command prompts for the name of a existing buffer and makes that buffer
+the @i[current buffer].  The newly selected buffer is displayed in the
+current window, and editing commands now edit the text in that buffer.
+Each buffer has its own point, thus the point will be in the place it was
+the last time the buffer was selected.  When prompting for the buffer, the
+default is the buffer that was selected before the current one.
+@enddefcom
+
+@defcom[com "Select Previous Buffer", bind (C-M-l)]
+@defcom1[com "Circulate Buffers", bind (C-M-L)]
+With no prefix argument, @hid[Select Previous Buffer] selects the buffer that
+has been selected most recently, similar to @binding[C-x b Return].  If given a
+prefix argument, then it does the same thing as @hid[Circulate Buffers].
+
+@hid[Circulate Buffers] moves back into successively earlier buffers in the
+buffer history.  If the previous command was not @hid[Circulate Buffers] or
+@hid[Select Previous Buffer], then it does the same thing as
+@hid[Select Previous Buffer], otherwise it moves to the next most recent
+buffer.  The original buffer at the start of the excursion is made the previous
+buffer, so @hid[Select Previous Buffer] will always take you back to where you
+started.
+
+These commands are generally used together.  Often @hid[Select Previous Buffer]
+will take you where you want to go.  If you don't end up there, then using
+@hid[Circulate Buffers] will do the trick.
+@enddefcom
+
+@defcom[com "Create Buffer", bind (C-x M-b)]
+This command is very similar to @hid[Select Buffer], but the buffer need not
+already exist.  If the buffer does not exist, a new empty buffer is created
+with the specified name.
+@enddefcom
+
+@defcom[com "Kill Buffer", bind (C-x k)]
+This command is used to make a buffer go away.  There is no way to restore
+a buffer that has been accidentally deleted, so the user is given a chance
+to save the hapless buffer if it has been modified.  This command is poorly
+named, since it has nothing to do with killing text.
+@enddefcom
+
+@defcom[com "List Buffers", bind (C-x C-b)]
+This command displays a list of all existing buffers in a pop-up window.  A
+"@f[*]" is displayed before the name of each modified buffer.  A buffer with no
+associated file is represented by the buffer name followed by the number of
+lines in the buffer.  A buffer with an associated file are is represented by
+the name and type of the file, a space, and the device and directory.  If the
+buffer name doesn't match the associated file, then the buffer name is also
+displayed.  When given a prefix argument, this command lists only the modified
+buffers.
+@enddefcom
+
+@defcom[com "Buffer Not Modified", bind (M-~)]
+This command resets the current buffer's modification flag @dash @i[it does not
+save any changes].  This is primarily useful in cases where a user accidentally
+modifies a buffer and then undoes the change.  Resetting the modified flag
+indicates that the buffer has no changes that need to be written out.
+@enddefcom
+
+@defcom[com "Check Buffer Modified", bind (C-x ~)]
+This command displays a message indicating whether the current buffer is modified.
+@enddefcom
+
+@defcom[com "Set Buffer Read-Only"]
+This command changes the flag that allows the current buffer to be modified.
+If a buffer is read-only, any attempt to modify it will result in an error.  The
+buffer may be made writable again by repeating this command.
+@enddefcom
+
+@defcom[com "Set Buffer Writable"]
+This command ensures the current buffer is modifiable.
+@enddefcom
+
+@defcom[com "Insert Buffer"]
+This command prompts for the name of a buffer and inserts its contents at the
+point, pushing a buffer mark before inserting.  The buffer inserted is
+unaffected.
+@enddefcom  
+
+@defcom[com "Rename Buffer"]
+This command prompts for a new name for the current buffer, which defaults
+to a name derived from the associated filename.
+@enddefcom
+
+
+@section[Files]
+@index[files]
+These commands either read a file into the current buffer or write it out to
+some file.  Various other bookkeeping operations are performed as well.
+
+@defcom[com "Find File", bind (C-x C-f)]
+This is the command normally used to get a file into @hemlock.  It prompts
+for the name of a file, and if that file has already been read in, selects
+that buffer; otherwise, it reads file into a new buffer whose name is
+derived from the name of the file.  If the file does not exist, then the
+buffer is left empty, and @w<"@f[(New File)]"> is displayed in the echo area;
+the file may then be created by saving the buffer.
+
+The buffer name created is in the form @w<"@i[name] @i[type] @i[directory]">.
+This means that the filename "@f[/sys/emacs/teco.mid]" has
+@w<"@f[Teco Mid /Sys/Emacs/]"> as its the corresponding buffer name.  The
+reason for rearranging the fields in this fashion is that it facilitates
+recognition since the components most likely to differ are placed first.  If
+the buffer cannot be created because it already exists, but has another file in
+it (an unlikely occurrence), then the user is prompted for the buffer to use,
+as by @hid[Create Buffer].
+
+@hid[Find File] takes special action if the file has been modified on disk
+since it was read into @hemlock.  This usually happens when several people are
+simultaneously editing a file, an unhealthy circumstance.  If the buffer is
+unmodified, @hid[Find File] just asks for confirmation before reading in the
+new version.  If the buffer is modified, then @hid[Find File] beeps and prompts
+for a single key-event to indicate what action to take.  It recognizes
+the following key-events:
+@begin[description]
+@binding[Return, Space, y]@\
+ Prompt for a file in which to save the current buffer and then read in the
+file found to be modified on disk.
+
+@binding[Delete, Backspace, n]@\
+ Forego reading the file.
+
+@binding[r]@\
+ Read the file found to be modified on disk into the buffer containing the
+earlier version with modifications.  This loses all changes you had in the
+buffer.
+@end[description]
+@enddefcom
+
+@defcom[com "Save File", bind (C-x C-s)]
+This command writes the current buffer out to its associated file and
+resets the buffer modification flag.  If there is no associated file, then
+the user is prompted for a file, which is made the associated file.  If
+the buffer is not modified, then the user is asked whether to actually
+write it or not.
+
+If the file has been modified on disk since the last time it was read,
+@hid[Save File] prompts for confirmation before overwriting the file.
+@enddefcom
+
+@defcom[com "Save All Files", bind (C-x C-m)]
+@defcom1[com "Save All Files and Exit", bind (C-x M-z)]
+@defhvar1[var "Save All Files Confirm", val {t}]
+@hid[Save All Files] does a @hid[Save File] on all buffers which have an
+associated file.  @hid[Save All Files and Exit] does the same thing and then
+exits @hemlock.
+
+When @hid[Save All Files Confirm] is true, these commands will ask for
+confirmation before saving a file.
+@enddefcom
+
+@defcom[com "Visit File", bind (C-x C-v)]
+This command prompts for a file and reads it into the current buffer,
+setting the associated filename.  Since the old contents of the buffer are
+destroyed, the user is given a chance to save the buffer if it is modified.
+As for @hid[Find File], the file need not actually exist.  This command warns
+if some other buffer also contains the file.
+@enddefcom
+
+@defcom[com "Write File", bind (C-x C-w)] This command prompts for a file
+and writes the current buffer out to it, changing the associated filename
+and resetting the modification flag.  When the buffer's associated file is
+specified this command does the same thing as @hid[Save File].  @enddefcom
+
+@defcom[com "Backup File"]
+This command is similar to @hid[Write File], but it neither sets the
+associated filename nor clears the modification flag.  This is useful for
+saving the current state somewhere else, perhaps on a reliable machine.
+
+Since @hid[Backup File] doesn't update the write date for the buffer,
+@hid[Find File] and @hid[Save File] will get all upset if you back up
+a buffer on any file that has been read into @hemlock.
+@enddefcom
+
+@defcom[com "Revert File"]
+@defhvar1[var "Revert File Confirm", val {t}]
+This command replaces the text in the current buffer with the contents of the
+associated file or the checkpoint file for that file, whichever is more recent.
+The point is put in approximately the same place that it was before the file
+was read.  If the original file is reverted to, then clear the modified flag,
+otherwise leave it set.  If a prefix argument is specified, then always revert
+to the original file, ignoring any checkpoint file.
+
+If the buffer is modified and @hid[Revert File Confirm] is true, then the user
+is asked for confirmation.
+@enddefcom
+
+@defcom[com "Insert File", bind (C-x C-r)]
+This command prompts for a file and inserts it at the point, pushing a buffer
+mark before inserting.
+@enddefcom
+
+@defcom[com "Write Region"]
+This command prompts for a file and writes the text in the region out to it.
+@enddefcom
+
+@defhvar[var "Add Newline at EOF on Writing File", val {:ask-user}]
+This variable controls whether some file writing commands add a newline at the
+end of the file if the last line is non-empty.
+@begin[description]
+@f[:ask-user]@\Ask the user whether to add a newline.
+
+@f[t]@\Automatically add a newline and inform the user.
+
+@nil@\Never add a newline and do not ask.
+@end[description]
+Some programs will lose the text on the last line or get an
+error when the last line does not have a newline at the end.
+@enddefhvar
+
+@defhvar[var "Keep Backup Files", val {nil}]
+Whenever a file is written by @hid[Save File] and similar commands, the old
+file is renamed by appending "@f[.BAK]" to the name, ensuring that some version
+of the file will survive a system crash during the write.  If set to true, this
+backup file will not deleted even when the write successfully completes.
+@enddefhvar
+
+
+@subsection[Auto Save Mode]
+
+@hid[Save] mode protects against loss of work in system crashes by periodically
+saving modified buffers in checkpoint files.
+
+@defcom[com "Auto Save Mode"]
+This command turns on @hid[Save] mode if it is not on, and turns off when it is
+on.  @hid[Save] mode is on by default.
+@enddefcom
+
+@defhvar[var "Auto Save Checkpoint Frequency", val {120}]
+@defhvar1[var "Auto Save Key Count Threshold", val {256}]
+These variables determine how often modified buffers in @hid[Save] mode will be
+checkpointed.  Checkpointing is done after
+@hid[Auto Save Checkpoint Frequency] seconds, or after
+@hid[Auto Save Key Count Threshold] keystrokes that modify the buffer
+(whichever comes first).  Either kind of checkpointing may be disabled by
+setting the corresponding variable to @nil.
+@enddefhvar
+
+@defhvar[var "Auto Save Cleanup Checkpoints", val {t}]
+If this variable is true, then any checkpoint file for a buffer will be deleted
+when the buffer is successfully saved in its associated file.
+@enddefhvar
+
+@defhvar[var "Auto Save Filename Pattern", val {"~A~A.CKP"}]
+@defhvar1[var "Auto Save Pathname Hook", val {make-unique-save-pathname}]
+These variables determine the naming of checkpoint files.
+@hid[Auto Save Filename Pattern] is a format string used to name the checkpoint
+files for buffers with associated files.  Format is called with two arguments:
+the directory and file namestrings of the associated file.
+
+@hid[Auto Save Pathname Hook] is a function called by @hid[Save] mode to get a
+checkpoint pathname when there is no pathname associated with a buffer.  It
+should take a buffer as its argument and return either a pathname or @nil.  If
+a pathname is returned, then it is used as the name of the checkpoint file.  If
+the function returns @nil, or if the hook variable is @nil, then @hid[Save]
+mode is turned off in the buffer.  The default value for this variable returns
+a pathname in the default directory of the form "@w<@f[save-]@i[number]>",
+where @i[number] is a number used to make the file unique.
+@enddefhvar
+
+
+@subsection[Filename Defaulting and Merging]
+@index[merging, filename]
+@index[defaulting, filename]
+@index[filename defaulting]
+@label[merging]
+@index[pathnames]
+When @hemlock prompts for the name of a file, it always offers a default.
+Except for a few commands that have their own defaults, filename defaults are
+computed in a standard way.  If it exists, the associated file for the current
+buffer is used as the default, otherwise a more complex mechanism creates a
+default.
+
+@defhvar[var "Pathname Defaults", val {(pathname "gazonk.del")}]
+@defhvar1[var "Last Resort Pathname Defaults Function"]
+@defhvar1[var "Last Resort Pathname Defaults", val {(pathname "gazonk")}]
+These variables control the computation of default filename defaults when the
+current buffer has no associated file.
+
+@hid[Pathname Defaults] holds a "sticky" filename default.  Commands that
+prompt for files set this to the file specified, and the value is used as a
+basis for filename defaults.  It is undesirable to offer the unmodified value
+as a default, since it is usually the name of an existing file that we don't
+want to overwrite.  If the current buffer's name is all alphanumeric, then the
+default is computed by substituting the buffer name for the the name portion of
+@hid[Pathname Defaults].  Otherwise, the default is computed by calling
+@hid[Last Resort Pathname Defaults Function] with the buffer as an argument.
+
+The default value of @hid[Last Resort Pathname Defaults Function] merges 
+@hid[Last Resort Pathname Defaults] with @hid[Pathname Defaults].
+Unlike @hid[Pathname Defaults], @hid[Last Resort Pathname Defaults] is not
+modified by file commands, so setting it to a silly name ensures that real
+files aren't inappropriately offered as defaults.
+@enddefhvar
+
+When a default is present in the prompt for a file, @hemlock @i[merges] the
+given input with the default filename.  The semantics of merging, described in
+the Common Lisp manual, is somewhat involved, but @hemlock has a few rules it
+uses:
+@begin[enumerate]
+If @hemlock can find the user's input as a file on the @f["default:"] search
+list, then it forgoes merging with the displayed default.  Basically, the
+system favors the files in your current working directory over those found by
+merging with the defaults offered in the prompt.
+
+Merging comes in two flavors, just merge with the displayed default's directory
+or just merge with the displayed default's @f[file-namestring].  If the user
+only responds with a directory specification, without any name or type
+information, then @hemlock merges the default's @f[file-namestring].  If the
+user responds with any name or type information, then @hemlock only merges with
+the default's directory.  Specifying relative directories in this second
+situation coordinates with the displayed defaults, not the current working
+directory.
+@end[enumerate]
+
+
+@subsection[Type Hooks and File Options]
+@index[mode comment]
+@index[type hooks]
+When a file is read either by @hid[Find File] or @hid[Visit File], @hemlock
+attempts to guess the correct mode in which to put the buffer, based on the
+file's @i[type] (the part of the filename after the last dot).  Any default
+action may be overridden by specifying the mode in the file's @i[file
+options].@index[modes]@index[package]
+
+@label[file-options]@index[file options] 
+The user specifies file options with a special syntax on the first line of a
+file.  If the first line contains the string "@f[-*-]", then @hemlock
+interprets the text between the first such occurrence and the second, which
+must be contained in one line , as a list of @w{"@f<@i[option]: @i[value]>"}
+pairs separated by semicolons.  The following is a typical example:
+@begin[programexample]
+;;; -*- Mode: Lisp, Editor; Package: Hemlock -*-
+@end[programexample]
+
+These options are currently defined:
+@begin[description]
+Dictionary@\The argument is the filename of a spelling dictionary associated
+with this file.  The handler for this option merges the argument with the
+name of this file.  See @comref[Set Buffer Spelling Dictionary].
+
+Log@\The argument is the name of the change log file associated with this file
+(see page @pageref[log-files]).  The handler for this option merges the
+argument with the name of this file.
+
+Mode@\The argument is a comma-separated list of the names of modes to turn on
+in the buffer that the file is read into.
+
+Package@\The argument is the name of the package to be used for reading code in
+the file.  This is only meaningful for Lisp code (see page
+@pageref[lisp-package].)
+
+Editor@\The handler for this option ignores its argument and turns on
+@hid[Editor] mode (see @comref[Editor Mode]).
+
+@end[description]
+If the option list contains no "@f[:]" then the entire string is used as
+the name of the major mode for the buffer.
+
+@defcom[com "Process File Options"]
+This command processes the file options in the current buffer as described
+above.  This is useful when the options have been changed or when a file is
+created.
+@enddefcom
+
+
+@section[Windows]
+@index[windows]
+
+@hemlock windows display a portion of a buffer's text.  See the section on
+@i[window groups], @ref[groups], for a discussion of managing windows on bitmap
+device.
+
+@defcom[com "New Window", bind (C-x C-n)]
+This command prompts users for a new window which they can place anywhere on
+the screen.  This window is in its own group.  This only works with bitmap
+devices.
+@enddefcom
+
+@defcom[com "Split Window", bind (C-x 2)]
+This command splits the current window roughly in half to make two windows.  If
+the current window is too small to be split, the command signals a user error.
+@enddefcom
+
+@defcom[com "Next Window", bind (C-x n)]
+@defcom1[com "Previous Window", bind (C-x p)]
+These commands make the next or previous window the new current window, often
+changing the current buffer in the process.  When a window is created, it is
+arbitrarily made the next window of the current window.  The location of the
+next window is, in general, unrelated to that of the current window.
+@enddefcom
+
+@defcom[com "Delete Window", bind (C-x C-d, C-x d)]
+@defcom1[com "Delete Next Window", bind (C-x 1)]
+@hid[Delete Window] makes the current window go away, making the next window
+current.  @hid[Delete Next Window] deletes the next window, leaving the current
+window unaffected.
+
+On bitmap devices, if there is only one window in the group, either command
+deletes the group, making some window in another group the current window.  If
+there are no other groups, they signal a user error.
+@enddefcom
+
+@defcom[com "Go to One Window"]
+This command deletes all window groups leaving one with the @hid[Default
+Initial Window X], @hid[Default Initial Window Y], @hid[Default Initial Window
+Width], and @hid[Default Initial Window Height].  This remaining window
+retains the contents of the current window.
+@enddefcom
+
+@defcom[com "Line to Top of Window", bind (M-!)]
+@defcom1[com "Line to Center of Window", bind (M-#)]
+@index[scrolling]@hid[Line to Top of Window] scrolls the current window up
+until the current line is at the top of the screen.
+
+@hid[Line to Center of Window] attempts to scroll the current window so that
+the current line is vertically centered.
+@enddefcom
+
+@defcom[com "Scroll Next Window Down", bind (C-M-v)]
+@defcom1[com "Scroll Next Window Up", bind (C-M-V)]
+These commands are the same as @hid[Scroll Window Up] and
+@hid[Scroll Window Down] except that they operate on the next window.
+@enddefcom
+
+@defcom[com "Refresh Screen", bind {C-l}]
+This command refreshes all windows, which is useful if the screen got trashed,
+centering the current window about the current line.  When the user supplies a
+positive argument, it scrolls that line to the top of the window.  When the
+argument is negative, the line that far from the bottom of the window is moved
+to the bottom of the window.  In either case when an argument is supplied, this
+command only refreshes the current window.
+@enddefcom
+
+
+@chap[Editing Documents]
+@index[documents, editing]
+Although @hemlock is not dedicated to editing documents as word processing
+systems are, it provides a number of commands for this purpose.  If @hemlock is
+used in conjunction with a text-formatting program, then its lack of complex
+formatting commands is no liability.
+
+
+@defcom[com "Text Mode"]
+This commands puts the current buffer into "Text" mode.
+@enddefcom
+
+
+@section[Sentence Commands]
+@index[sentence commands]
+A sentence is defined as a sequence of characters ending with a period,
+question mark or exclamation point, followed by either two spaces or a newline.
+A sentence may also be terminated by the end of a paragraph.  Any number of
+closing delimiters, such as brackets or quotes, may be between the punctuation
+and the whitespace.  This somewhat complex definition of a sentence is used so
+that periods in abbreviations are not misinterpreted as sentence ends.
+
+@defcom[com "Forward Sentence", bind {M-a}]
+@defcom1[com "Backward Sentence", bind {M-e}]
+@index[motion, sentence]@hid[Forward Sentence] moves the point forward
+past the next sentence end. @hid[Backward Sentence] moves to the beginning
+of the current sentence. A prefix argument may be used as a repeat count.
+@enddefcom
+
+@defcom[com "Forward Kill Sentence", bind {M-k}]
+@defcom1[com "Backward Kill Sentence", bind (C-x Delete, C-x Backspace)]
+@index[killing, sentence]@hid[Forward Kill Sentence] kills text from the
+point through to the end of the current sentence.  @hid[Backward Kill Sentence]
+kills from the point to the beginning of the current sentence.  A
+prefix argument may be used as a repeat count.
+@enddefcom
+
+@defcom[com "Mark Sentence"]
+This command puts the point at the beginning and the mark at the end of the
+next or current sentence.
+@enddefcom
+
+
+@section[Paragraph Commands]
+
+@index[paragraph commands]A paragraph may be delimited by a blank line or a
+line beginning with "@f[']" or "@f[.]", in which case the delimiting line is
+not part of the paragraph.  Other characters may be paragraph delimiters in
+some modes.  A line with at least one leading whitespace character may also
+introduce a paragraph and is considered to be part of the paragraph.  Any
+fill-prefix which is present on a line is disregarded for the purpose of
+locating a paragraph boundary.
+
+@defcom[com "Forward Paragraph", bind (@bf<M-]>)]
+@defcom1[com "Backward Paragraph", bind (M-[)]
+@index[motion, paragraph]@index[paragraph, motion]@hid[Forward Paragraph]
+moves to the end of the current or next paragraph. @hid[Backward Paragraph]
+moves to the beginning of the current or previous paragraph.  A prefix
+argument may be used as a repeat count.
+@enddefcom
+
+@defcom[com "Mark Paragraph", bind {M-h}]
+This command puts the point at the beginning and the mark at the end of the
+current paragraph.
+@enddefcom
+
+@defhvar[var "Paragraph Delimiter Function", val {default-para-delim-function}]
+This variable holds a function that takes a mark as its argument and returns
+true when the line it points to should break the paragraph.
+@enddefhvar
+
+@section[Filling]
+
+@index[filling]@index[formatting]Filling is a coarse text-formatting
+process which attempts to make all the lines roughly the same length, but
+doesn't vary the amount of space between words.  Editing text may leave
+lines with all sorts of strange lengths; filling this text will return it
+to a moderately aesthetic form.
+
+@defcom[com "Set Fill Column", bind (C-x f)]
+This command sets the fill column to the column that the point is currently at,
+or the one specified by the absolute value of prefix argument, if it is
+supplied.  The fill column is the column past which no text is permitted to
+extend.
+@enddefcom
+
+@defcom[com "Set Fill Prefix", bind (C-x .)]
+This command sets the fill prefix to the text from the beginning of the
+current line to the point.  The fill-prefix is a string which filling commands
+leave at the beginning of every line filled.  This feature is useful for
+filling indented text or comments.
+@enddefcom
+
+@defhvar[var "Fill Column", val {75}]
+@defhvar1[var "Fill Prefix", val {nil}]
+These variables hold the value of the fill prefix and fill column, thus
+setting these variables will change the way filling is done.  If
+@hid[Fill Prefix] is @nil, then there is no fill prefix.
+@enddefcom
+
+@defcom[com "Fill Paragraph", bind {M-q}]
+@index[paragraph, filling]This command fills the text in the current or next
+paragraph.  The point is not moved.
+@enddefcom
+
+@defcom[com "Fill Region", bind {M-g}]
+@index[region, filling]This command fills the text in the region.  Since
+filling can mangle a large quantity of text, this command asks for confirmation
+before filling a large region (see @hid[Region Query Size].)
+@enddefcom
+
+
+@defcom[com "Auto Fill Mode"]
+@index[modes, auto fill]This command turns on or off the @hid[Fill]
+minor mode in the current buffer.  When in @hid[Fill] mode, @bf[Space],
+@bf[Return] and @bf[Linefeed] are rebound to commands that check whether
+the point is past the fill column and fill the current line if it is.
+This enables typing text without having to break the lines manually.
+
+If a prefix argument is supplied, then instead of toggling, the sign
+determines whether @hid[Fill] mode is turned off; a positive argument
+argument turns in on, and a negative one turns it off.
+@enddefcom
+
+@defcom[com "Auto Fill Linefeed", stuff (bound to @bf[Linefeed] in @hid[Fill] mode)]
+@defcom1[com "Auto Fill Return", stuff (bound to @bf[Return] in @hid[Fill] mode)]
+@hid[Auto Fill Linefeed] fills the current line if it needs it and then goes to
+a new line and inserts the fill prefix.  @hid[Auto Fill Return] is similar, but
+does not insert the fill prefix on the new line.
+@enddefcom
+
+@defcom[com "Auto Fill Space", stuff (bound to @bf[Space] in @hid[Fill] mode)]
+If no prefix argument is supplied, this command inserts a space and
+fills the current line if it extends past the fill column.  If the argument is
+zero, then it fills the line if needed, but does not insert a space.  If the
+argument is positive, then that many spaces are inserted without filling.
+@enddefcom
+
+@defhvar[var "Auto Fill Space Indent", val {nil}]
+This variable determines how lines are broken by the auto fill commands.  If it
+is true, new lines are created using the @hid[Indent New Comment Line] command,
+otherwise the @hid[New Line] command is used.  Language modes should define
+this variable to be true so that auto fill mode can be used on code.
+@enddefhvar
+
+
+@section[Scribe Mode]
+
+@hid[Scribe] mode provides a number of facilities useful for editing Scribe
+documents.  It is also sufficiently parameterizable to be adapted to other
+similar syntaxes.
+
+@defcom[com "Scribe Mode"]
+@index[modes, scribe]This command puts the current buffer in @hid[Scribe] mode.
+Except for special Scribe commands, the only difference between @hid[Scribe]
+mode and @hid[Text] mode is that the rules for determining paragraph breaks are
+different.  In @hid[Scribe] mode, paragraphs delimited by Scribe commands are
+normally placed on their own line, in addition to the normal paragraph breaks.
+The main reason for doing this is that it prevents @hid[Fill Paragraph] from
+mashing these commands into the body of a paragraph.
+@enddefcom
+
+@defcom[com "Insert Scribe Directive", stuff (@bf[C-h] in @hid[Scribe] mode)]
+This command prompts for a key-event to determine which Scribe directive to
+insert.  Directives are inserted differently depending on their kind:
+@begin[description]
+@i[environment]@\
+The current or next paragraph is enclosed in a begin-end pair:
+@f<@@begin[@i{directive}]> @i[paragraph] @f<@@end[@i{directive}]>.  If the
+current region is active, then this command encloses the region instead of the
+paragraph it would otherwise chose.
+
+@i[command]@\
+The previous word is enclosed by @f<@@@i[directive][@i[word]]>.  If the
+previous word is already enclosed by a use of the same command, then the
+beginning of the command is extended backward by one word.
+@end[description]
+
+Typing @bf[Home] or @bf[C-_] to this command's prompt will display a list of
+all the defined key-events on which it dispatches.
+@enddefcom
+
+@defcom[com "Add Scribe Directive"]
+This command adds to the database of directives recognized by the 
+@hid[Insert Scribe Directive] command.  It prompts for the directive's name,
+the kind of directive (environment or command) and the key-event on which to
+dispatch.
+@enddefcom
+
+@defcom[com "Add Scribe Paragraph Delimiter"]
+@defcom1[com "List Scribe Paragraph Delimiters"]
+@hid[Add Scribe Paragraph Delimiter] prompts for a string to add to the list of
+formatting commands that delimit paragraphs in @hid[Scribe] mode.  If the user
+supplies a prefix argument, then this command removes the string as a
+delimiter.
+
+@hid[List Scribe Paragraph Delimiters] displays in a pop-up window the Scribe
+commands that delimit paragraphs.
+@enddefcom
+
+@defhvar[var "Escape Character", val {#\@@}]
+@defhvar1[var "Close Paren Character", val {#\]}]
+@defhvar1[var "Open Paren Character", val {#\[}]
+These variables determine the characters used when a Scribe directive is
+inserted.
+@enddefhvar
+
+@defcom[com "Scribe Insert Bracket"]
+@defhvar1[var "Scribe Bracket Table"]
+@hid[Scribe Insert Bracket] inserts a bracket (@bf[>], @bf[}], @bf[)], or
+@bf<]>), that caused its invocation, and then shows the matching bracket.
+
+@hid[Scribe Bracket Table] holds a @f[simple-vector] indexed by character
+codes.  If a character is a bracket, then the entry for its @f[char-code]
+should be the opposite bracket.  If a character is not a bracket, then the
+entry should be @nil.
+@enddefcom
+
+
+@section[Spelling Correction]
+@index[spelling correction]
+@hemlock has a spelling correction facility based on the dictionary for the ITS
+spell program.  This dictionary is fairly small, having only 45,000 word or so,
+which means it fits on your disk, but it also means that many reasonably common
+words are not in the dictionary.  A correct spelling for a misspelled word will
+be found if the word is in the dictionary and is only erroneous in that it has
+a wrong character, a missing character, an extra character or a transposition
+of two characters.
+
+
+@defcom[com "Check Word Spelling", bind (M-$)]
+This command looks up the previous or current word in the dictionary and
+attempts to correct the spelling if it is misspelled.  There are four possible
+results of invoking this command:
+@begin[enumerate]
+This command displays the message "@f[Found it.]" in the echo area.  This means
+it found the word in the dictionary exactly as given.
+
+This command displays the message "@f[Found it because of @i[word].]", where
+@i[word] is some other word with the same root but a different ending.  The
+word is no less correct than if the first message is given, but an additional
+piece of useless information is supplied to make you feel like you are using a
+computer.
+
+The command prompts with "@f[Correction choice:]" in the echo area and lists
+possible correct spellings associated with numbers in a pop-up display.  Typing
+a number selects the corresponding correction, and the command replaces the
+erroneous word, preserving case as though by @hid[Query Replace].  Typing
+anything else rejects all the choices.
+
+This commands displays the message "@f[Word not found.]".  The word is not in
+the dictionary and possibly spelled correctly anyway.  Furthermore, no
+similarly spelled words were found to offer as possible corrections.  If this
+happens, it is worth trying some alternate spellings since one of them might
+be close enough to some known words that this command could display.
+@end[enumerate]
+@enddefcom
+
+@defcom[com "Correct Buffer Spelling"]
+This command scans the entire buffer looking for misspelled words and offers to
+correct them.  It creates a window into the @hid[Spell Corrections] buffer, and
+in this buffer it maintains a log of any actions taken by the user.  When this
+finds an unknown word, it prompts for a key-event.  The user has the following
+options:
+@begin[description]
+@bf[a]@\
+ Ignore this word.  If the command finds the word again, it will prompt again.
+
+@bf[i]@\
+ Insert this word in the dictionary.
+
+@bf[c]@\
+ Choose one of the corrections displayed in the @hid[Spell Corrections] window
+by specifying the correction number.  If the same misspelling is encountered
+again, then the command will make the same correction automatically, leaving a
+note in the log window.
+
+@bf[r]@\
+ Prompt for a word to use instead of the misspelled one, remembering the
+correction as with @bf[c].
+
+@binding[C-r]@\
+ Go into a recursive edit at the current position, and resume checking when the
+recursive edit is exited.
+@end[description]
+After this command completes, it deletes the log window leaving the buffer
+around for future reference.
+@enddefcom
+
+@defhvar[var "Spell Ignore Uppercase", val {nil}]
+@index[case sensitivity]
+If this variable is true, then @hid[Auto Check Word Spelling] and @hid[Correct
+Buffer Spelling] will ignore unknown words that are all uppercase.  This is
+useful for acronyms and cryptic formatter directives.
+@enddefhvar
+
+@defcom[com "Add Word to Spelling Dictionary", bind (C-x $)]
+This command adds the previous or current word to the spelling dictionary.
+@enddefcom
+
+@defcom[com "Remove Word from Spelling Dictionary"]
+This command prompts for a word to remove from the spelling dictionary.  Due to
+the dictionary representation, removal of a word in the initial spelling
+dictionary will remove all words with the same root.  The user is asked for
+confirmation before removing a root word with valid suffix flags.
+@enddefcom
+
+@defcom[com "List Incremental Spelling Insertions"]
+This command displays the incremental spelling insertions for the current
+buffer's associated spelling dictionary file.
+@enddefcom
+
+@defcom[com "Read Spelling Dictionary"]
+This command adds some words from a file to the spelling dictionary.  The
+format of the file is a list of words, one on each line.
+@enddefcom
+
+@defcom[com "Save Incremental Spelling Insertions"]
+This command appends incremental dictionary insertions to a file.  Any words
+added to the dictionary since the last time this was done will be appended to
+the file.  Except for @hid[Augment Spelling Dictionary], all the commands that
+add words to the dictionary put their insertions in this list.  The file is
+prompted for unless @hid[Set Buffer Spelling Dictionary] has been executed in
+the buffer.
+@enddefcom
+
+@defcom[com "Set Buffer Spelling Dictionary"]
+This command Prompts for the dictionary file to associate with the current
+buffer.  If the specified dictionary file has not been read for any other
+buffer, then it is read.  Incremental spelling insertions from this buffer
+can be appended to this file with @hid[Save Incremental Spelling
+Insertions].  If a buffer has an associated spelling dictionary, then
+saving the buffer's associated file also saves any incremental dictionary
+insertions.  The @w<"@f[Dictionary: ]@i[file]"> file option may also be
+used to specify the dictionary for a buffer (see section
+@ref[file-options]).
+@enddefcom
+
+@defhvar[var "Default User Spelling Dictionary", val {nil}]
+This variable holds the pathname of a dictionary to read the first time
+@hid[Spell] mode is entered in a given editing session.  When
+@hid[Set Buffer Spelling Dictionary] or the "@f[dictionary]" file option is
+used to specify a dictionary, this default one is read also.  It defaults to
+nil.
+@enddefhvar
+
+
+@subsection[Auto Spell Mode]
+@hid[Auto Spell Mode] checks the spelling of each word as it is typed.
+When an unknown word is typed the user is notified and allowed to take a
+number of actions to correct the word.
+
+@defcom[com "Auto Spell Mode"]
+This command turns @hid[Spell] mode on or off in the current buffer.
+@enddefcom
+
+@defcom[com "Auto Check Word Spelling",
+	stuff (bound to word delimiters in @hid[Spell] mode)]
+@defhvar1[var "Check Word Spelling Beep", val {t}]
+@defhvar1[var "Correct Unique Spelling Immediately", val {t}]
+This command checks the spelling of the word before the point, doing nothing if
+the word is in the dictionary.  If the word is misspelled but has a known
+correction previously supplied by the user, then this command corrects the
+spelling.  If there is no correction, then this displays a message in the echo
+area indicating the word is unknown.  An unknown word detected by this command
+may be corrected using the @hid[Correct Last Misspelled Word] command.  This
+command executes in addition to others bound to the same key; for example, if
+@hid[Fill] mode is on, any of its commands bound to the same keys as this
+command also run.
+
+If @hid[Check Word Spelling Beep] is true, then this command will beep when an
+unknown word is found.  If @hid[Correct Unique Spelling Immediately] is true,
+then this command will immediately attempt to correct any unknown word,
+automatically making the correction if there is only one possible.
+@enddefhvar
+
+@defcom[com "Undo Last Spelling Correction", bind (C-x a)]
+@defhvar1[var "Spelling Un-Correct Prompt for Insert", val {nil}]
+@hid[Undo Last Spelling Correction] undoes the last incremental spelling
+correction.  The "correction" is replaced with the old word, and the old word
+is inserted in the dictionary.  Any automatic replacement for the old word is
+eliminated.  When @hid[Spelling Un-Correct Prompt for Insert] is true, the user
+is asked to confirm the insertion into the dictionary.
+@enddefcom
+
+@defcom[com "Correct Last Misspelled Word", bind (M-:)]
+This command places the cursor after the last misspelled word detected by the
+@hid[Auto Check Word Spelling] command and then prompts for a key-event on
+which it dispatches:
+@begin[description]
+@bf[c]@\
+ Display possible corrections in a pop-up window, and prompt for the one to
+make according to the corresponding displayed digit or letter.
+
+@i[any digit]@\
+ Similar to @bf[c] @i[digit], but immediately makes the correction, dispensing
+with display of the possible corrections.  This is shorter, but only works when
+there are less than ten corrections.
+
+@bf[i]@\
+ Insert the word in the dictionary.
+
+@bf[r]@\
+ Replace the word with another.
+
+@binding[Backspace, Delete, n]@\
+ Skip this word and try again on the next most recently misspelled word.
+
+@binding[C-r]@\
+ Enter a recursive edit at the word, exiting the command when the recursive
+edit is exited.
+
+@binding[Escape]@\
+ Exit and forget about this word.
+@end[description]
+As in @hid[Correct Buffer Spelling], the @bf[c] and @bf[r] commands add the
+correction to the known corrections.
+@enddefcom
+
+
+
+@chap[Managing Large Systems]
+
+@hemlock provides three tools which help to manage large systems:
+@begin[enumerate]
+File groups, which provide several commands that operate on all the files
+in a possibly large collection, instead of merely on a single buffer.
+
+A source comparison facility with semi-automatic merging, which can be used
+to compare and merge divergent versions of a source file.
+
+A change log facility, which maintains a single file containing a record of the
+edits done on a system.
+@end[enumerate]
+
+
+@section[File Groups]
+
+@index[file groups]@index[searching, group]@index[replacing, group]
+A file group is a set of files, upon which various editing operations can be
+performed.  The files in a group are specified by a file in the following
+format:
+@begin[itemize]
+Any line which begins with one "@f[@@]" is ignored.
+
+Any line which does not begin with an "@f[@@]" is the name of a file in the
+group.
+
+A line which begins with "@f[@@@@]" specifies another file having this
+syntax, which is recursively examined to find more files in the group.
+@end[itemize]
+This syntax is used for historical reasons.  Although any number of file groups
+may be read into @hemlock, there is only one @i[active group], which is the
+file group implicitly used by all of the file group commands.  
+Page @pageref[compile-group-command] describes the @hid[Compile Group] command.
+
+@defcom[com "Select Group"]
+This command prompts for the name of a file group to make the active group.
+If the name entered is not the name of a group whose definition has been
+read, then the user is prompted for the name of a file to read the group
+definition from.  The name of the default pathname is the name of the
+group, and the type is "@f[upd]".
+@enddefcom
+
+@defcom[com "Group Query Replace"]
+This command prompts for target and replacement strings and then executes an
+interactive string replace on each file in the active group.  This reads in
+each file as if @hid[Find File] were used and processes it as if @hid[Query
+Replace] were executing.
+@enddefcom
+
+@defcom[com "Group Replace"]
+This is like @hid[Group Query Replace] except that it executes a
+non-interactive replacement, similar to @hid[Replace String].
+@enddefcom
+
+@defcom[com "Group Search"]
+This command prompts for a string and then searches for it in each file in the
+active group.  This reads in each file as if @hid[Find File] were used.  When
+it finds an occurrence, it prompts the user for a key-event indicating what
+action to take.  The following commands are defined:
+@begin[description]
+@binding[Escape, Space, y]@\
+ Exit @hid[Group Search].
+
+@binding[Delete, Backspace, n]@\
+ Continue searching for the next occurrence of the string.
+
+@binding[!]@\
+ Continue the search at the beginning of the next file, skipping the remainder
+of the current file.
+
+@binding[C-r]@\
+ Go into a recursive edit at the current location, and continue the search when
+it is exited.
+@end[description]
+@enddefcom
+
+@defhvar[var "Group Find File", val {nil}]
+The group searching and replacing commands read each file into its own buffer
+using @hid[Find File].  Since this may result in large amounts of memory being
+consumed by unwanted buffers, this variable controls whether to delete the
+buffer after processing it.  When this variable is false, the default, the
+commands delete the buffer if it did not previously exist; however, regardless
+of this variable, if the user leaves the buffer modified, the commands will not
+delete it.
+@enddefhvar
+
+@defhvar[var "Group Save File Confirm", val {t}]
+If this variable is true, the group searching and replacing commands ask for
+confirmation before saving any modified file.  The commands attempt to save
+each file processed before going on to the next one in the group.
+@enddefhvar
+
+
+@section[Source Comparison]
+@index[buffer, merging]
+@index[buffer, comparison]
+@index[source comparison]
+
+These commands can be used to find exactly how the text in two buffers differs,
+and to generate a new version that combines features of both versions.
+
+@defhvar[var "Source Compare Default Destination", val {"Differences"}]
+This is a sticky default buffer name to offer when comparison commands prompt
+for a buffer in which to insert the results.
+@enddefhvar
+
+@defcom[com "Compare Buffers"]
+This command prompts for three buffers and then does a buffer comparison.
+The first two buffers must exist, as they are the buffers to be compared.
+The last buffer, which is created if it does not exist, is the buffer to
+which output is directed.  The output buffer is selected during the
+comparison so that its progress can be monitored.  There are various variables
+that control exactly how the comparison is done.
+
+If a prefix argument is specified, then only only the lines in the the regions
+of the two buffers are compared.
+@enddefcom
+
+@defcom[com "Buffer Changes"]
+This command compares the contents of the current buffer with the disk version
+of the associated file.  It reads the file into the buffer 
+@hid[Buffer Changes File], and generates the comparison in the buffer
+@hid[Buffer Changes Result].  As with @hid[Compare Buffers], the output buffer
+is displayed in the current window.
+@enddefcom
+
+@defcom[com "Merge Buffers"]
+This command functions in a very similar fashion to @hid[Compare Buffers], the
+difference being that a version which is a combination of the two buffers being
+compared is generated in the output buffer.  This copies text that is identical
+in the two comparison buffers to the output buffer.  When it encounters a
+difference, it displays the two differing sections in the output buffer and
+prompts the user for a key-event indicating what action to take.  The following
+commands are defined:
+@begin[description]
+@bf[1]@\
+ Use the first version of the text.
+
+@bf[2]@\
+ Use the second version.
+
+@bf[b]@\
+ Insert the string @w<"@f[**** MERGE LOSSAGE ****]"> followed by both versions.
+This is useful if the differing sections are too complex, or it is unclear
+which is the correct version.  If you cannot make the decision conveniently at
+this point, you can later search for the marking string above.
+
+@binding[C-r]@\
+ Do a recursive edit and ask again when the edit is exited.
+@end[description]
+@enddefcom
+
+
+@defhvar[var "Source Compare Ignore Case", val {nil}]
+@index[case sensitivity]
+If this variable is non-@nil, @hid[Compare Buffers] and @hid[Merge Buffers]
+will do comparisons case-insensitively.
+@enddefhvar
+
+@defhvar[var "Source Compare Ignore Indentation", val {nil}] 
+If this variable is non-@nil, @hid[Compare Buffers] and @hid[Merge Buffers]
+ignore initial whitespace when comparing lines.
+@enddefhvar
+
+@defhvar[var "Source Compare Ignore Extra Newlines", val {t}]
+If this variable is true, @hid[Compare Buffers] and @hid[Merge Buffers]
+will treat all groups of newlines as if they were a single newline.
+@enddefhvar
+
+@defhvar[var "Source Compare Number of Lines", val {3}]
+This variable controls the number of lines @hid[Compare Buffers] and
+@hid[Merge Buffers] will compare when resynchronizing after a difference
+has been encountered.
+@enddefhvar
+
+
+@section[Change Logs]
+@label[log-files]
+@index[edit history]
+@index[change log]
+
+The @hemlock change log facility encourages the recording of changes to a
+system by making it easy to do so.  The change log is kept in a separate file
+so that it doesn't clutter up the source code.  The name of the log for a file
+is specified by the @f[Log] file option (see page @pageref[file-options].)
+
+@defcom[com "Log Change"]
+@defhvar1[var "Log Entry Template"]
+@hid[Log Change] makes a new entry in the change log associated with the file.
+Any changes in the current buffer are saved, and the associated log file is
+read into its own buffer.  The name of the log file is determined by merging
+the name specified in the @f[Log] option with the current buffer's file name,
+so it is not usually necessary to put the full name there.  After inserting a
+template for the log entry at the beginning of the buffer, the command enters a
+recursive edit (see page @pageref[recursive-edits]) so that the text of the
+entry may be filled in.  When the user exits the recursive edit, the log file
+is saved.
+
+The variable @hid[Log Entry Template] determines the format of the change log
+entry.  Its value is a @clisp @f[format] control string.  The format string is
+passed three string arguments: the full name of the file, the creation date for
+the file and the name of the file author.  If the creation date is not
+available, the current date is used.  If the author is not available then @nil
+is passed.  If there is an @f[@@] in the template, then it is deleted and the
+point is left at that position.
+@enddefcom
+
+
+
+@comment[@chap (Special Modes)]
+@include(special-modes)
+
+
+
+@chap[Editing Programs]
+
+
+@section[Comment Manipulation]
+@index[comment manipulation]
+@hemlock has commenting commands which can be used in almost any language.  The
+behavior of these commands is determined by several @hemlock variables which
+language modes should define appropriately.
+
+@defcom[com "Indent for Comment", bind (M-;)]
+@index[indentation, comment]@label[comment-indentation]
+This is the most basic commenting command.  If there is already a comment on
+the current line, then this moves the point to the start of the comment.  If
+there no comment, this creates an empty one.
+
+This command normally indents the comment to start at @hid[Comment Column].
+The comment indents differently in the following cases:
+@begin[enumerate]
+If the comment currently starts at the beginning of the line, or if the last
+character in the @hid[Comment Start] appears three times, then the comment
+remains unmoved.
+
+If the last character in the @hid[Comment Start] appears two times, then the
+comment is indented like a line of code.
+
+If text on the line prevents the comment occurring in the desired position,
+this places the comment at the end of the line, separated from the text by a
+space.
+@end[enumerate]
+Although the rules about replication in the comment start are oriented toward
+Lisp commenting styles, you can exploit these properties in other languages.
+
+When given a prefix argument, this command indents any existing comment on that
+many consecutive lines.  This is useful for fixing up the indentation of a
+group of comments.
+@enddefcom
+
+@defcom[com "Indent New Comment Line", bind {M-j, M-Linefeed}]
+This commend ends the current comment and starts a new comment on a blank line,
+indenting the comment the same way that @hid[Indent for Comment] does.
+When not in a comment, this command is the same as @hid[Indent New Line].
+@enddefcom
+
+@defcom[com "Up Comment Line", bind {M-p}]
+@defcom1[com "Down Comment Line", bind {M-n}]
+These commands are similar to @hid[Previous Line] or @hid[Next Line]
+followed by @hid[Indent for Comment].  Any empty comment on the current line is
+deleted before moving to the new line.
+@enddefcom
+
+@defcom[com "Kill Comment", bind (C-M-;)]
+This command kills any comment on the current line.  When given a prefix
+argument, it kills comments on that many consecutive lines.  @hid[Undo] will
+restore the unmodified text.
+@enddefcom
+
+@defcom[com "Set Comment Column", bind (C-x ;)]
+This command sets the comment column to its prefix argument.  If used without a
+prefix argument, it sets the comment column to the column the point is at.
+@enddefcom
+
+@defhvar[var "Comment Start", val {nil}]
+@defhvar1[var "Comment End", val {nil}]
+@defhvar1[var "Comment Begin", val {nil}]
+@defhvar1[var "Comment Column", val {0}]
+These variables determine the behavior of the comment commands.
+@begin[description]
+@hid[Comment Start]@\The string which indicates the start of a comment.  If
+this is @nil, then there is no defined comment syntax.
+
+@hid[Comment End]@\The string which ends a comment.  If this is @nil, then
+the comment is terminated by the end of the line.
+
+@hid[Comment Begin]@\The string inserted to begin a new comment.
+
+@hid[Comment Column]@\The column that normal comments start at.
+@end[description]
+@enddefcom
+
+
+@section[Indentation]
+@label[indentation]
+@index[indentation]
+Nearly all programming languages have conventions for indentation or leading
+whitespace at the beginning of lines.  The @hemlock indentation facility is
+integrated into the command set so that it interacts well with other features
+such as filling and commenting.
+
+@defcom[com "Indent", bind (Tab, C-i)]
+This command indents the current line.  With a prefix argument, indents that
+many lines and moves down.  Exactly what constitutes indentation depends on the
+current mode (see @hid[Indent Function]).
+@enddefcom
+
+@defcom[com "Indent New Line", bind (Linefeed)]
+This command starts a new indented line.  Deletes any whitespace before the
+point and inserts indentation on a blank line.  The effect of this is similar
+to @binding[Return] followed by @binding[Tab].  The prefix argument is passed
+to @hid[New Line], which is used to insert the blank line.
+@enddefcom
+
+@defcom[com "Indent Region", bind (C-M-\)]
+This command indents every line in the region.  It may be undone with
+@hid[Undo].
+@enddefcom
+
+@defcom[com "Back to Indentation", bind {M-m, C-M-m}]
+@index[motion, indentation]
+This command moves point to the first non-whitespace character on the current
+line.
+@enddefcom
+
+@defcom[com "Delete Indentation", bind (M-^, C-M-^)]
+@hid[Delete Indentation] joins the current line with the previous one, deleting
+excess whitespace.  This operation is the inverse of the @bf[Linefeed] command
+in most modes.  Usually this leaves one space between the two joined lines, but
+there are several exceptions.
+
+The non-whitespace immediately surrounding the deleted line break determine the
+amount of space inserted.
+@begin[enumerate]
+If the preceding character is an "@f[(]" or the following character is a
+"@f[)]", then this inserts no space.
+
+If the preceding character is a newline, then this inserts no space.  This will
+happen if the previous line was blank.
+
+If the preceding character is a sentence terminator, then this inserts two
+spaces.
+@end[enumerate]
+
+When given a prefix argument, this command joins the current and next lines,
+rather than the previous and current lines.
+@enddefcom
+
+@defcom[com "Quote Tab", bind (M-Tab)]
+This command inserts a tab character.
+@enddefcom
+
+@defcom[com "Indent Rigidly", bind (C-x Tab, C-x C-i)]
+This command changes the indentation of all the lines in the region.  Each
+line is moved to the right by the number of spaces specified by the prefix
+argument, which defaults to eight.  A negative prefix argument moves lines
+left.
+@enddefcom
+
+@defcom[com "Center Line"]
+This indents the current line so that it is centered between the left margin
+and @hvarref[Fill Column].  If a prefix argument is supplied, then it is used
+as the width instead of @hid[Fill Column].
+@enddefcom
+
+@defhvar[var "Indent Function", val {tab-to-tab-stop}]
+The value of this variable determines how indentation is done, and it is a
+function which is passed a mark as its argument.  The function should indent
+the line which the mark points to.  The function may move the mark around on
+the line.  The mark will be @f[:left-inserting].  The default simply inserts a
+tab character at the mark.
+@enddefhvar
+
+@defhvar[var "Indent with Tabs", val {indent-using-tabs}]
+@defhvar1[var "Spaces per Tab", val {8}]
+@hid[Indent with Tabs] holds a function that takes a mark and a number of
+spaces.  The function will insert a maximum number of tabs and a minimum number
+of spaces at mark to move the specified number of columns.  The default
+definition uses @hid[Spaces per Tab] to determine the size of a tab.  @i[Note,]
+@hid[Spaces per Tab] @i[is not used everywhere in @hemlock yet, so changing
+this variable could have unexpected results.]
+@enddefhvar
+
+
+@section[Language Modes]
+
+@hemlock@comment{}'s language modes are currently fairly crude, but probably
+provide better programming support than most non-extensible editors.
+
+@defcom[com "Pascal Mode"]
+@index[indentation, pascal]@index[modes, pascal]This command sets the current
+buffer's major mode to @hid[Pascal].  @hid[Pascal] mode borrows parenthesis
+matching from Scribe mode and indents lines under the previous line.
+@enddefcom
+
+
+@chap[Editing Lisp]
+@index[lisp, editing]
+@hemlock provides a large number of powerful commands for editing Lisp code.
+It is possible for a text editor to provide a much higher level of support for
+editing Lisp than ordinary programming languages, since its syntax is much
+simpler.
+
+
+@section[Lisp Mode]
+@index[lisp mode]
+@index[modes, lisp]
+@hid[Lisp] mode is a major mode used for editing Lisp code.  Although most
+Lisp specific commands are globally bound, @hid[Lisp] mode is necessary to
+enable Lisp indentation, commenting, and parenthesis-matching.  Whenever the
+user or some @hemlock mechanism turns on @hid[Lisp] mode, the mode's setup
+includes locally setting @hid[Current Package] (see section @ref[lisp-package])
+in that buffer if its value is non-existent there; the value used is
+@f["USER"].
+
+@defcom[com "Lisp Mode"]
+This command sets the major mode of the current buffer to @hid[Lisp].
+@enddefcom
+
+
+@section[Form Manipulation]
+@index[form manipulation]
+These commands manipulate Lisp forms, the printed representations of Lisp
+objects.  A form is either an expression balanced with respect to parentheses
+or an atom such as a symbol or string.
+
+@defcom[com "Forward Form", bind (C-M-f)]
+@defcom1[com "Backward Form", bind (C-M-b)]
+@index[motion, form]@hid[Forward Form] moves to the end of the current or
+next form, while @hid[Backward Form] moves to the beginning of the current
+or previous form.  A prefix argument is treated as a repeat count.
+@enddefcom
+
+@defcom[com "Forward Kill Form", bind (C-M-k)]
+@defcom1[com "Backward Kill Form", bind (C-M-Delete, C-M-Backspace)]
+@index[killing, form]@hid[Forward Kill Form] kills text from the point to
+the end of the current form.  If at the end of a list, but inside the close
+parenthesis, then kill the close parenthesis.  @hid[Backward Kill Form] is
+the same, except it goes in the other direction.  A prefix argument is
+treated as a repeat count.
+@enddefcom
+
+@defcom[com "Mark Form", bind (C-M-@@)]
+This command sets the mark at the end of the current or next form.
+@enddefcom
+
+@defcom[com "Transpose Forms", bind (C-M-t)]
+This command transposes the forms before and after the point and moves
+forward.  A prefix argument is treated as a repeat count.  If the prefix
+argument is negative, then the point is moved backward after the
+transposition is done, reversing the effect of the equivalent positive
+argument.
+@enddefcom
+
+@defcom[com "Insert ()", bind {M-(}]
+This command inserts an open and a close parenthesis, leaving the point
+inside the open parenthesis.  If a prefix argument is supplied, then the
+close parenthesis is put at the end of the form that many forms from the
+point.
+@enddefcom
+
+@defcom[com "Extract Form"]
+This command replaces the current containing list with the next form.  The
+entire affected area is pushed onto the kill ring.  If an argument is supplied,
+that many upward levels of list nesting is replaced by the next form.  This is
+similar to @hid[Extract List], but this command is more generally useful since
+it works on any kind of form; it is also more intuitive since it operates on
+the next form as many @hid[Lisp] mode commands do.
+@enddefcom
+
+
+@section[List Manipulation]
+
+@index[list manipulation]List commands are similar to form commands, but
+they only pay attention to lists, ignoring any atomic objects that may
+appear.  These commands are useful because they can skip over many symbols
+and move up and down in the list structure.
+
+@defcom[com "Forward List", bind (C-M-n)]
+@defcom1[com "Backward List", bind (C-M-p)]
+@index[motion, list]@hid[Forward List] moves the point to immediately
+after the end of the next list at the current level of list structure.  If
+there is not another list at the current level, then it moves up past
+the end of the containing list.
+@hid[Backward List] is identical, except that it moves backward and leaves
+the point at the beginning of the list.  The prefix argument is used as a
+repeat count.
+@enddefcom
+
+@defcom[com "Forward Up List", bind {C-M-@bf<)>}]
+@defcom1[com "Backward Up List", bind (C-M-@bf<(>, C-M-u)]
+@hid[Forward Up List] moves to after the end of the enclosing list.
+@hid[Backward Up List] moves to the beginning.  The prefix argument is used
+as a repeat count.
+@enddefcom
+
+@defcom[com "Down List", bind (C-M-d)]
+This command moves to just after the beginning of the next list.  The
+prefix argument is used as a repeat count.
+@enddefcom
+
+@defcom[com "Extract List", bind (C-M-x)]
+This command "extracts" the current list from the list which contains it.
+The outer list is deleted, leaving behind the current list.  The entire
+affected area is pushed on the kill ring, so that this possibly catastrophic
+operation can be undone.  The prefix argument is used as a repeat count.
+@enddefcom
+
+
+
+@section[Defun Manipulation]
+
+@index[defun manipulation]A @i[defun] is a list whose open parenthesis is
+against the left margin.  It is called this because an occurrence of the
+@f[defun] top level form usually satisfies this definition, but
+other top level forms such as a @f[defstruct] and @f[defmacro] work just as
+well.
+
+@defcom[com "End of Defun", bind (@bf<C-M-e, C-M-]>)]
+@defcom1[com "Beginning of Defun", bind (C-M-a, C-M-[)]
+@index[motion, defun]@hid[End of Defun] moves to the end of the current
+or next defun. @hid[Beginning of Defun] moves to the beginning of the
+current or previous defun.  @hid[End of Defun] will not work if the
+parentheses are not balanced.
+@enddefcom
+
+@defcom[com "Mark Defun", bind (C-M-h)]
+This command puts the point at the beginning and the mark at the end of the
+current or next defun.
+@enddefcom
+
+
+
+@section[Indentation]
+
+@index[indentation, lisp]
+One of the most important features provided by @hid[Lisp] mode is automatic
+indentation of Lisp code.  Since unindented Lisp is unreadable, poorly indented
+Lisp is hard to manage, and inconsistently indented Lisp is subtly misleading.
+See section @ref[indentation] for a description of the general-purpose
+indentation commands.  @hid[Lisp] mode uses these indentation rules:
+@begin[itemize]
+If in a semicolon (@f[;]) comment, then use the standard comment indentation
+rules.  See page @pageref[comment-indentation].
+
+If in a quoted string, then indent to the column one greater than the column
+containing the opening double quote.  This is exactly what you want in function
+documentation strings and wrapping @f[error] strings.
+
+If there is no enclosing list, then use no indentation.
+
+If enclosing list resembles a call to a known macro or special-form, then the
+first few arguments are given greater indentation and the first body form is
+indented two spaces.  If the first special argument is on the same line as the
+beginning of the form, then following special arguments will be indented to the
+start of the first special argument, otherwise all special arguments are
+indented four spaces.
+
+If the previous form starts on its own line, then the indentation is copied
+from that form.  This rule allows the default indentation to be overridden:
+once a form has been manually indented to the user's satisfaction, subsequent
+forms will be indented in the same way.
+
+If the enclosing list has some arguments on the same line as the form start,
+then subsequent arguments will be indented to the start of the first argument.
+
+If the enclosing list has no argument on the same line as the form start, then
+arguments will be indented one space.
+@end[itemize]
+
+
+@defcom[com "Indent Form", bind (C-M-q)]
+This command indents all the lines in the current form, leaving the point
+unmoved.  This is undo-able.
+@enddefcom
+
+@defcom[com "Fill Lisp Comment Paragraph",
+	stuff <bound to @bf[M-q] in @hid[Lisp] mode>]
+@defhvar1[var "Fill Lisp Comment Paragraph Confirm", val {t}]
+This fills a flushleft or indented Lisp comment.  This also fills Lisp string
+literals using the proper indentation as a filling prefix.  When invoked
+outside of a comment or string, this tries to fill all contiguous lines
+beginning with the same initial, non-empty blankspace.  When filling a comment,
+the current line is used to determine a fill prefix by taking all the initial
+whitespace on the line, the semicolons, and any whitespace following the
+semicolons.
+
+When invoked outside of a comment or string, this command prompts for
+confirmation before filling.  It is useful to use this for filling long
+@f[export] lists or other indented text or symbols, but since this is a less
+common use, this command tries to make sure that is what you wanted.  Setting
+@hid[Fill Lisp Comment Paragraph Confirm] to @nil inhibits the confirmation
+prompt.
+@enddefcom
+
+@defcom[com "Defindent", bind (C-M-#)]
+This command prompts for the number of special arguments to associate with
+the symbol at the beginning of the current or containing list.
+@enddefcom
+
+@defhvar[var "Indent Defanything", val {2}]
+This is the number of special arguments implicitly assumed to be supplied in
+calls to functions whose names begin with "@f[def]".  If set to @nil, this
+feature is disabled.
+@enddefhvar
+
+@defcom[com "Move Over )", bind {M-)}]
+This command moves past the next close parenthesis and then does the equivalent
+of @hid[Indent New Line].
+@enddefcom       
+
+
+@section[Parenthesis Matching]
+
+@index[parenthesis matching]Another very important facility provided by
+@hid[Lisp] mode is @i[parenthesis matching].  Two different styles of
+parenthesis matching are supported: highlighting and pausing.
+
+@defhvar[var "Highlight Open Parens", val {t}]
+@defhvar1[var "Open Paren Highlighting Font", val {nil}]
+When @hid[Highlight Open Parens] is true, and a close paren is immediately
+before the point, then @hemlock displays the matching open paren in @hid[Open
+Paren Highlighting Font].
+
+@hid[Open Paren Highlighting Font] is the string name of the font used for
+paren highlighting.  Only the "@f[(]" character is used in this font.  If null,
+then a reasonable default is chosen.  The highlighting font is read at
+initialization time, so this variable must be set before the editor is first
+entered to have any effect.
+@enddefhvar
+
+@defcom[com "Lisp Insert )", stuff <bound to @bf[)] in @hid[Lisp] mode>]
+@defhvar1[var "Paren Pause Period", val {0.5}]
+This command inserts a close parenthesis and then attempts to display the
+matching open parenthesis by placing the cursor on top of it for
+@hid[Paren Pause Period] seconds.  If there is no matching parenthesis then
+beep.  If the matching parenthesis is off the top of the screen, then the line
+on which it appears is displayed in the echo area.  Paren pausing may be
+disabled by setting @hid[Paren Pause Period] to @nil. 
+@enddefcom
+
+The initial values shown for @hid[Highlight Open Parens] and @hid[Paren Pause
+Period] are only approximately correct.  Since paren highlighting is only
+meaningful in Lisp mode, @hid[Highlight Open Parens] is false globally, and
+has a mode-local value of @true in Lisp mode.  It it redundant to do both
+kinds of paren matching, so there is also a binding of @hid[Paren Pause Period]
+to @false in Lisp mode.
+
+Paren highlighting is only supported under @windows, so the above defaults are
+conditional on the device type.  If @hemlock is started on a terminal, the
+initialization code makes Lisp mode bindings of @false and @f[0.5] for
+@hid[Highlight Open Parens] and @hid[Paren Pause Period].  Since these
+alternate default bindings are made at initialization time, the only way to
+affect them is to use the @f[after-editor-initializations] macro.
+
+
+@section[Parsing Lisp]
+Lisp mode has a fairly complete knowledge of Lisp syntax, but since it does
+not use the reader, and must work incrementally, it can be confused by legal
+constructs.  Lisp mode totally ignores the read-table, so user-defined read
+macros have no effect on the editor.  In some cases, the values the @hid[Lisp
+Syntax] character attribute can be changed to get a similar effect.
+
+Lisp commands consistently treat semicolon (@f[;]) style comments as
+whitespace when parsing, so a Lisp command used in a comment will affect the
+next (or previous) form outside of the comment.  Since @f[#| ... |#] comments
+are not recognized, they can used to comment out code, while still allowing
+Lisp editing commands to be used.
+
+Strings are parsed similarly to symbols.  When within a string, the next form
+is after the end of the string, and the previous form is the beginning of the
+string.
+
+
+@defhvar[var "Defun Parse Goal", val {2}]
+@defhvar1[var "Maximum Lines Parsed", val {500}]
+@defhvar1[var "Minimum Lines Parsed", val {50}]
+In order to save time, Lisp mode does not parse the entire buffer every time
+a Lisp command is used.  Instead, it uses a heuristic to guess the region of
+the buffer that is likely to be interesting.  These variables control the
+heuristic.
+
+Normally, parsing begins and ends on defun boundaries (an open parenthesis at
+the beginning of a line).  @hid[Defun Parse Goal] specifies the number of
+defuns before and after the point to parse.  If this parses fewer lines than
+@hid[Minimum Lines Parsed], then parsing continues until this lower limit is
+reached.  If we cannot find enough defuns within @hid[Maximum Lines Parsed]
+lines then we stop on the farthest defun found, or at the point where we
+stopped if no defuns were found.
+
+When the heuristic fails, and does not parse enough of the buffer, then
+commands usually act as though a syntax error was detected.  If the parse
+starts in a bad place (such as in the middle of a string), then Lisp commands
+will be totally confused.  Such problems can usually be eliminated by
+increasing the values of some of these variables.
+@enddefhvar
+
+@defhvar[var "Parse Start Function", val {start-of-parse-block}]
+@defhvar1[var "Parse End Function", val {end-of-parse-block}]
+These variables determine the region of the buffer parsed.  The values are
+functions that take a mark and move it to the start or end of the parse region.
+The default values implement the heuristic described above.
+@enddefhvar
+
+
+
+@comment[@chap(Interacting With Lisp)]
+@include(lisp)
+
+
+@comment[@chap(Mail Interface)]
+@include(mail)
+
+
+@comment[@chap(Netnews Interface)]
+@include(netnews)
+
+
+
+@chap[System Interface]
+
+@hemlock provides a number of commands that access operating system resources
+such as the filesystem and print servers.  These commands offer an alternative
+to leaving the editor and using the normal operating system command language
+(such as the Unix shell), but they are implementation dependent.  Therefore,
+they might not even exist in some implementations.
+
+
+@section[File Utility Commands]
+This section describes some general file operation commands and quick directory
+commands. 
+
+See section @ref[dired] for a description @hemlock@comment{}'s directory editing
+mechanism, @hid[Dired] mode.
+
+@defcom[com "Copy File"]
+This command copies a file, allowing one wildcard in the filename.  It prompts
+for source and destination specifications.
+
+If these are both directories, then the copying process is recursive on the
+source, and if the destination is in the subdirectory structure of the source,
+the recursion excludes this portion of the directory tree.  Use
+@f[dir-spec-1/*] to copy only the files in a source directory without
+recursively descending into subdirectories.
+
+If the destination specification is a directory, and the source is a file, then
+it is copied into the destination with the same filename.
+
+The copying process copies files maintaining the source's write date.
+
+See the description of @hid[Dired Copy File Confirm], page
+@pageref[copy-confirm], for controlling user interaction when the destination
+exists.
+@enddefcom
+
+@defcom[com "Rename File"]
+This command renames a file, allowing one wildcard in the filename.  It prompts
+for source and destination specifications.
+
+If the destination is a directory, then the renaming process moves file(s)
+indicated by the source into the directory with their original filenames.
+
+For Unix-based implementations, if you want to rename a directory, do not
+specify the trailing slash in the source specification.
+@enddefcom
+
+@defcom[com "Delete File"]
+This command prompts for the name of a file and deletes it.
+@enddefcom
+
+@defcom[com "Directory", bind (C-x C-d)]
+@defcom1[com "Verbose Directory", bind (C-x C-D)]
+These commands prompt for a pathname (which may contain wildcards), and display
+a directory listing in a pop-up window.  If a prefix argument is supplied, then
+normally hidden files such as Unix dot-files will also be displayed.  
+@hid[Directory] uses a compact, multiple-column format; 
+@hid[Verbose Directory] displays one file on a line, with information about
+protection, size, etc.
+@enddefcom
+
+
+@section[Printing]
+
+@defcom[com "Print Region"]
+@defcom1[com "Print Buffer"]
+@defcom1[com "Print File"]
+@hid[Print Region] and @hid[Print Buffer] print the contents of the current
+region and the current buffer, respectively.  @hid[Print File] prompts for a
+the name of a file and prints that file.  Any error messages will be displayed
+in the echo area.
+@enddefcom
+
+@defhvar[var "Print Utility", val {"/usr/cs/bin/lpr"}]
+@defhvar1[var "Print Utility Switches", val {()}]
+@hid[Print Utility] is the program the print commands use to send files to the
+printer.  The program should act like @f[lpr]: if a filename is given as an
+argument, it should print that file, and if no name appears, standard input
+should be assumed.  @hid[Print Utility Switches] is a list of strings
+specifying the options to pass to the program.
+@enddefhvar
+
+
+@section[Scribe]
+@defcom[com "Scribe Buffer File",
+	stuff (bound to @bf[C-x c] in @hid[Scribe] mode)]
+@defhvar1[var "Scribe Buffer File Confirm", val {t}]
+@defcom1[com "Scribe File"]
+@hid[Scribe Buffer File] invokes @hid[Scribe Utility] on the file associated
+with the current buffer.  That process's default directory is the directory of
+the file.  The process sends its output to the @hid[Scribe Warnings] buffer.
+Before doing anything, this asks the user to confirm saving and formatting the
+file.  This prompting can be inhibited with "Scribe Buffer File Confirm".
+
+@hid[Scribe File] invokes @hid[Scribe Utility] on a file supplied by the user
+in the same manner as describe above.
+@enddefcom
+
+@defhvar[var "Scribe Utility", val {"/usr/misc/bin/scribe"}]
+@defhvar1[var "Scribe Utility Switches"]
+@hid[Scribe Utility] is the program the Scribe commands use to compile the text
+formatting.  @hid[Scribe Utility Switches] is a list of strings whose contents
+would be contiguous characters, other than space, had the user invoked this
+program on a command line outside of @hemlock.  Do not include the name of the
+file to compile in this variable; the Scribe commands supply this.
+@enddefhvar
+
+@defcom[com "Select Scribe Warnings", bind (Scribe: C-M-C)]
+This command makes the @hid[Scribe Warnings] buffer current if it exists.
+@enddefcom
+
+
+@section[Miscellaneous]
+
+@defcom[com "Manual Page"]
+This command displays a Unix manual page in a buffer which is in @hid[View]
+mode.  When given an argument, this puts the manual page in a pop-up display.
+@enddefcom
+
+@defcom[com "Unix Filter Region"]
+This command prompts for a UNIX program and then passes the current region to
+the program as standard input.  The standard output from the program is used to
+replace the region.  This command is undoable.
+@enddefcom
+
+
+
+@chap[Simple Customization]
+
+@index[customization]@hemlock can be customized and extended to a very
+large degree, but in order to do much of this a knowledge of Lisp is
+required.  These advanced aspects of customization are discussed in the
+@i[Hemlock Command Implementor's Manual], while simpler methods of
+customization are discussed here.
+
+
+@section[Keyboard Macros]
+@index[keyboard macros]
+Keyboard macros provide a facility to turn a sequence of commands into one
+command.
+
+@defcom[com "Define Keyboard Macro", bind {C-x (}]
+@defcom1[com "End Keyboard Macro", bind {C-x )}]
+@hid[Define Keyboard Macro] starts the definition of a keyboard macro.  The
+commands which are invoked up until @hid[End Keyboard Macro] is invoked
+become the definition for the keyboard macro, thus replaying the keyboard
+macro is synonymous with invoking that sequence of commands.
+@enddefcom
+
+@defcom[com "Last Keyboard Macro", bind (C-x e)]
+This command is the keyboard macro most recently defined; invoking it will
+replay the keyboard macro.  The prefix argument is used as a repeat count.
+@enddefcom
+
+@defcom[com "Define Keyboard Macro Key", bind (C-x M-(; )]
+@defhvar1[var "Define Keyboard Macro Key Confirm", val {t}]
+This command prompts for a key before going into a mode for defining keyboard
+macros.  After defining the macro @hemlock binds it to the key.  If the key is
+already bound, @hemlock asks for confirmation before clobbering the binding;
+this prompting can be inhibited by setting @hid[Define Keyboard Macro Key
+Confirm] to @nil.
+@enddefcom
+
+@defcom[com "Keyboard Macro Query", bind (C-x q)]
+This command conditionalizes the execution of a keyboard macro.  When invoked
+during the definition of a macro, it does nothing.  When the macro replays, it
+prompts the user for a key-event indicating what action to take.  The following
+commands are defined:
+@begin[description]
+@binding[Escape]@\
+ Exit all repetitions of this keyboard macro.  More than one may have been
+specified using a prefix argument.
+
+@binding[Space, y]@\
+ Proceed with the execution of the keyboard macro.
+
+@binding[Delete, Backspace, n]@\
+ Skip the remainder of the keyboard macro and go on to the next repetition, if
+any.
+
+@binding[!]@\
+ Do all remaining repetitions of the keyboard macro without prompting.
+
+@binding[.]@\
+ Complete this repetition of the macro and then exit without doing any of the
+remaining repetitions.
+
+@binding[C-r]@\
+ Do a recursive edit and then prompt again.
+@end[description]
+@enddefcom
+
+@defcom[com "Name Keyboard Macro"]
+This command prompts for the name of a command and then makes the
+definition for that command the same as @hid[Last Keyboard Macro]'s current
+definition.  The command which results is not clobbered when another
+keyboard macro is defined, so it is possible to keep several keyboard
+macros around at once.  The resulting command may also be bound to a key
+using @hid[Bind Key], in the same way any other command is.
+@enddefcom
+
+Many keyboard macros are not for customization, but rather for one-shot
+use, a typical example being performing some operation on each line of a file.
+To add "@f[del ]" to the beginning and "@f[.*]" to the end of every line in
+in a buffer, one could do this:
+@begin[programexample]
+C-x ( d e l Space C-e . * C-n C-a C-x ) C-u 9 9 9 C-x e
+@end[programexample]
+First a keyboard macro is defined which performs the desired operation on
+one line, and then the keyboard macro is invoked with a large prefix
+argument.  The keyboard macro will not actually execute that many times;
+when the end of the buffer is reached the @binding[C-n] will get an error
+and abort the execution.
+
+
+@section[Binding Keys]
+@index[key bindings]
+@label[binding-keys]
+
+@defcom[com "Bind Key"]
+This command prompts for a command, a key and a kind of binding to make,
+and then makes the specified binding.  The following kinds of bindings are
+allowed:
+@begin[description]
+@i[buffer]@\Prompts for a buffer and then makes a key binding which is
+only present when that buffer is the current buffer.
+
+@i[mode]@\Prompts for the name of a mode and then makes a key binding which
+is only in present when that mode is active in the current buffer.
+
+@i[global]@\Makes a global key binding which is in effect when there is
+no applicable mode or buffer key binding.  This is the default.
+@end[description]
+@enddefcom
+
+@defcom[com "Delete Key Binding"]
+This command prompts for a key binding the same way that @hid[Bind Key]
+does and makes the specified binding go away.
+@enddefcom
+
+@section[Hemlock Variables]
+
+@label[vars]@index[variables, hemlock]@index[hemlock variables]A number
+of commands use @hemlock variables as flags to control their behavior.  Often
+you can get a command to do what you want by setting a variable.  Generally the
+default value for a variable is chosen to be the safest value for novice users.
+
+@defcom[com "Set Variable"]
+This command prompts for the name of a @hemlock variable and an expression,
+then sets the current value of the variable to the result of the evaluation of
+the expression.
+@enddefcom
+
+
+@defcom[com "Defhvar"]
+Like @hid[Set Variable], this command prompts for the name of a @hemlock
+variable and an expression.  Like @hid[Bind Key], this command prompts for a
+place: mode, buffer or local.  The result of evaluating the expression is
+defined to be the value of the named variable in the specified place.
+
+This command is most useful for making mode or buffer local bindings of
+variables.  Redefining a variable in a mode or buffer will create a
+customization that takes effect only when in that mode or buffer.
+
+Unlike @hid[Set Variable], the variable name need not be the name of an
+existing variable: new variables may be defined.  If the variable is already
+defined in the current environment, @hemlock copies the documentation and hooks
+to the new definition.
+@enddefcom
+
+
+@section[Init Files]
+@index[init files]
+@hemlock customizations are normally put in @hemlock@comment{}'s initialization file,
+"@f[hemlock-init.lisp]", or when compiled "@f[hemlock-init.fasl]".  When
+starting up Lisp, use the @f[-hinit] switch to indicate a particular file.  The
+contents of the init file must be Lisp code, but there is a fairly
+straightforward correspondence between the basic customization commands and the
+equivalent Lisp code.  Rather than describe these functions in depth here, a
+brief example follows:
+@begin[programexample]
+;;; -*- Mode: Lisp; Package: Hemlock -*-
+
+;;; It is necessary to specify that the customizations go in
+;;; the hemlock package.
+(in-package 'hemlock)
+
+;;; Bind @hid[Kill Previous Word] to @binding[M-h].
+(bind-key "Kill Previous Word" '#(#\m-h))
+;;;
+;;; Bind @hid[Extract List] to @binding[C-M-?] when in @hid[Lisp] mode.
+(bind-key "Extract List" '#(#\c-m-?) :mode "Lisp")
+
+;;; Make @binding[C-w] globally unbound.
+(delete-key-binding '#(#\c-w))
+
+;;; Make string searches case-sensitive.
+(setv string-search-ignore-case nil)
+;;;
+;;; Make "Query Replace" replace strings literally.
+(setv case-replace nil)
+@end[programexample]
+For a detailed description of these functions, see the @i[Hemlock Command
+Implementor's Manual].
Index: /branches/new-random/cocoa-ide/hemlock/hemlock.system
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/hemlock.system	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/hemlock.system	(revision 13309)
@@ -0,0 +1,162 @@
+;; -*- Mode: Lisp; -*-
+
+(defpackage #:hemlock-system
+  (:use #:cl)
+  (:export #:*hemlock-base-directory*))
+
+(in-package #:hemlock-system)
+
+
+(pushnew :command-bits *features*)
+(pushnew :buffered-lines *features*)
+
+(defparameter *hemlock-base-directory*
+  (make-pathname :name nil :type nil :version nil
+                 :defaults (parse-namestring *load-truename*)))
+
+(defparameter *binary-pathname*
+  (make-pathname :directory
+                 (append (pathname-directory *hemlock-base-directory*)
+                         (list "bin"
+                               #+CLISP "clisp"
+                               #+CMU   "cmu"
+                               #+EXCL  "acl"
+                               #+SBCL  "sbcl"
+                               #-(or CLISP CMU EXCL SBCL)
+                               (string-downcase (lisp-implementation-type))))
+                 :defaults *hemlock-base-directory*))
+       
+(mk:defsystem :hemlock
+    :source-pathname #.(make-pathname :directory
+                                      (append (pathname-directory *hemlock-base-directory*)
+                                              (list "src"))
+                                      :defaults *hemlock-base-directory*)
+    :source-extension "lisp"
+    :binary-pathname #.*binary-pathname*
+    ;; ehem ..
+    :initially-do
+    (progn
+      ;; try to load clx
+      (unless (ignore-errors (fboundp (find-symbol "OPEN-DISPLAY" "XLIB")))
+        (ignore-errors (require :clx))
+        (ignore-errors (require :cmucl-clx)))
+      (unless (ignore-errors (fboundp (find-symbol "OPEN-DISPLAY" "XLIB")))
+        (error "Please provide me with CLX."))
+      ;; Create binary pathnames
+      (ensure-directories-exist *binary-pathname*)
+      (dolist (subdir '("tty" "wire"))
+        (ensure-directories-exist (merge-pathnames (make-pathname :directory (list :relative subdir))
+                                                   *binary-pathname*)
+                                  :verbose t)))
+    :components
+    ("package"
+
+     ;; Lisp implementation specific stuff goes into one of the next
+     ;; two files.
+     "lispdep"
+     "hemlock-ext"                     
+
+     "decls"                            ;early declarations of functions and stuff
+     
+     "struct"
+     ;; "struct-ed"
+     "charmacs"
+     "key-event" 
+     "keysym-defs"
+
+     "rompsite"
+     
+     "input"
+     "macros"
+     "line"
+     "ring"
+     "vars"
+     "interp"
+     "syntax"
+     "htext1"
+     "buffer"  
+     "htext2"
+     "htext3"
+     "htext4"
+     "files"
+     "search1"
+     "search2"
+     "table"
+     #+clx
+     "hunk-draw"
+     "window"
+     "screen"
+     "winimage"
+     "linimage"
+     "display"
+     #+clx
+     "bit-display"
+
+     "tty/termcap"
+     ;"tty-disp-rt"
+     ;"tty-display"
+     "pop-up-stream"
+     "bit-screen"
+     "tty/tty-screen"
+     "cursor"
+     "font"
+     "streams"
+;     "hacks"
+     "main"
+     "echo"
+     "echocoms"
+     "command"
+     "indent"
+;; moved     "comments"
+     "morecoms"
+     "undo"
+     "killcoms"
+     "searchcoms"
+     "filecoms"
+     "doccoms"
+     "srccom"
+     "group"
+     "fill"
+     "text"
+     "lispmode"
+;;     "ts-buf"
+;;     "ts-stream"
+;;     "eval-server"
+     "lispbuf"
+;;     "lispeval"
+;;     "spell-rt"
+;;     "spell-corr"
+;;     "spell-aug"
+;;     "spellcoms"
+
+     "comments"
+     "overwrite"
+     "abbrev"
+     "icom"
+     "kbdmac"
+     "defsyn"
+     #+why
+     "scribe"
+     #+what
+     "pascal"
+     #+who
+     "dylan"
+     "edit-defs"
+     "auto-save"
+     "register"
+     "xcoms"
+;;     "unixcoms"
+;;     "mh"
+     "highlight"
+;;     "dired"
+;;     "diredcoms"
+     "bufed"
+     "lisp-lib"
+     "completion"
+;;     "shell"
+;;     "debug"
+;;     "netnews"
+;;     "rcs"
+     "bindings"
+     "bindings-gb"
+     ))
Index: /branches/new-random/cocoa-ide/hemlock/hemlock11.cursor
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/hemlock11.cursor	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/hemlock11.cursor	(revision 13309)
@@ -0,0 +1,8 @@
+#define noname_width 16
+#define noname_height 16
+#define noname_x_hot 3
+#define noname_y_hot 1
+static char noname_bits[] = {
+ 0x00,0x00,0x08,0x00,0x18,0x00,0x38,0x00,0x78,0x00,0xf8,0x00,0xf8,0x01,0xf8,
+ 0x03,0xf8,0x07,0xf8,0x00,0xd8,0x00,0x88,0x01,0x80,0x01,0x00,0x03,0x00,0x03,
+ 0x00,0x00};
Index: /branches/new-random/cocoa-ide/hemlock/hemlock11.mask
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/hemlock11.mask	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/hemlock11.mask	(revision 13309)
@@ -0,0 +1,6 @@
+#define noname_width 16
+#define noname_height 16
+static char noname_bits[] = {
+ 0x0c,0x00,0x1c,0x00,0x3c,0x00,0x7c,0x00,0xfc,0x00,0xfc,0x01,0xfc,0x03,0xfc,
+ 0x07,0xfc,0x0f,0xfc,0x0f,0xfc,0x01,0xdc,0x03,0xcc,0x03,0x80,0x07,0x80,0x07,
+ 0x00,0x03};
Index: /branches/new-random/cocoa-ide/hemlock/maint/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/maint/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/maint/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/maint/publish
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/maint/publish	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/maint/publish	(revision 13309)
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+now=`date --iso`
+tempdir=/tmp/hemlock-publish/
+rm -rf $tempdir
+mkdir $tempdir
+cd $tempdir ;
+cvs -d :pserver:gilbert@localhost:/hemlock export -D "`date`" -d hemlock-$now hemlock ;
+tar zcvf hemlock-$now.tar.gz hemlock-$now
+
+sed -e "s/%%DATE%%/$now/g" < hemlock-$now/website/index.html.in > index.html
+
+scp hemlock-$now.tar.gz unk6@rzstud1.rz.uni-karlsruhe.de:.public_html/export/
+scp index.html unk6@rzstud1.rz.uni-karlsruhe.de:.public_html/hemlock/
+
+ssh -l unk6 rzstud1.rz.uni-karlsruhe.de chmod a+r .public_html/export/hemlock-$now.tar.gz .public_html/hemlock/index.html
+
+# $Id$
Index: /branches/new-random/cocoa-ide/hemlock/resources/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/resources/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/resources/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/resources/XKeysymDB
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/resources/XKeysymDB	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/resources/XKeysymDB	(revision 13309)
@@ -0,0 +1,159 @@
+! $XConsortium: XKeysymDB,v 1.2 91/06/18 13:43:07 rws Exp $
+
+hpmute_acute		:100000A8
+hpmute_grave		:100000A9
+hpmute_asciicircum	:100000AA
+hpmute_diaeresis	:100000AB
+hpmute_asciitilde	:100000AC
+hplira			:100000AF
+hpguilder		:100000BE
+hpYdiaeresis		:100000EE
+hpIO			:100000EE
+hplongminus		:100000F6
+hpblock			:100000FC
+apLineDel		:1000FF00
+apCharDel		:1000FF01
+apCopy			:1000FF02
+apCut			:1000FF03
+apPaste			:1000FF04
+apMove			:1000FF05
+apGrow			:1000FF06
+apCmd			:1000FF07
+apShell			:1000FF08
+apLeftBar		:1000FF09
+apRightBar		:1000FF0A
+apLeftBox		:1000FF0B
+apRightBox		:1000FF0C
+apUpBox			:1000FF0D
+apDownBox		:1000FF0E
+apPop			:1000FF0F
+apRead			:1000FF10
+apEdit			:1000FF11
+apSave			:1000FF12
+apExit			:1000FF13
+apRepeat		:1000FF14
+hpModelock1		:1000FF48
+hpModelock2		:1000FF49
+hpReset			:1000FF6C
+hpSystem		:1000FF6D
+hpUser			:1000FF6E
+hpClearLine		:1000FF6F
+hpInsertLine		:1000FF70
+hpDeleteLine		:1000FF71
+hpInsertChar		:1000FF72
+hpDeleteChar		:1000FF73
+hpBackTab		:1000FF74
+hpKP_BackTab		:1000FF75
+apKP_parenleft		:1000FFA8
+apKP_parenright		:1000FFA9
+
+I2ND_FUNC_L		:10004001
+I2ND_FUNC_R		:10004002
+IREMOVE			:10004003
+IREPEAT			:10004004
+IA1			:10004101
+IA2			:10004102
+IA3			:10004103
+IA4			:10004104
+IA5			:10004105
+IA6			:10004106
+IA7			:10004107
+IA8			:10004108
+IA9			:10004109
+IA10			:1000410A
+IA11			:1000410B
+IA12			:1000410C
+IA13			:1000410D
+IA14			:1000410E
+IA15			:1000410F
+IB1			:10004201
+IB2			:10004202
+IB3			:10004203
+IB4			:10004204
+IB5			:10004205
+IB6			:10004206
+IB7			:10004207
+IB8			:10004208
+IB9			:10004209
+IB10			:1000420B
+IB11			:1000420B
+IB12			:1000420C
+IB13			:1000420D
+IB14			:1000420E
+IB15			:1000420F
+IB16			:10004210
+
+DRemove			:1000FF00
+Dring_accent		:1000FEB0
+Dcircumflex_accent	:1000FE5E
+Dcedilla_accent		:1000FE2C
+Dacute_accent		:1000FE27
+Dgrave_accent		:1000FE60
+Dtilde			:1000FE7E
+Ddiaeresis		:1000FE22
+
+osfCopy			:1004FF02
+osfCut			:1004FF03
+osfPaste		:1004FF04
+osfBackTab		:1004FF07
+osfBackSpace		:1004FF08
+osfClear		:1004FF0B
+osfEscape		:1004FF1B
+osfAddMode		:1004FF31
+osfPrimaryPaste		:1004FF32
+osfQuickPaste		:1004FF33
+osfPageLeft		:1004FF40
+osfPageUp		:1004FF41
+osfPageDown		:1004FF42
+osfPageRight		:1004FF43
+osfActivate		:1004FF44
+osfMenuBar		:1004FF45
+osfLeft			:1004FF51
+osfUp			:1004FF52
+osfRight		:1004FF53
+osfDown			:1004FF54
+osfEndLine		:1004FF57
+osfBeginLine		:1004FF58
+osfEndData		:1004FF59
+osfBeginData		:1004FF5A
+osfPrevMenu		:1004FF5B
+osfNextMenu		:1004FF5C
+osfPrevField		:1004FF5D
+osfNextField		:1004FF5E
+osfSelect		:1004FF60
+osfInsert		:1004FF63
+osfUndo			:1004FF65
+osfMenu			:1004FF67
+osfCancel		:1004FF69
+osfHelp			:1004FF6A
+osfSelectAll		:1004FF71
+osfDeselectAll		:1004FF72
+osfReselect		:1004FF73
+osfExtend		:1004FF74
+osfRestore		:1004FF78
+osfDelete		:1004FFFF
+
+SunFA_Grave		:1005FF00
+SunFA_Circum		:1005FF01
+SunFA_Tilde		:1005FF02
+SunF36			:1005FF10
+SunF37			:1005FF11
+SunSys_Req		:1005FF60
+SunProps		:1005FF70
+SunFront		:1005FF71
+SunCopy			:1005FF72
+SunOpen			:1005FF73
+SunPaste		:1005FF74
+SunCut			:1005FF75
+
+SunCompose		:FF20
+SunPageUp		:FF55
+SunPageDown		:FF56
+SunPrint_Screen		:FF61
+SunUndo			:FF65
+SunAgain		:FF66
+SunFind			:FF68
+SunStop			:FF69
+SunAltGraph		:FF7E	
+
+WYSetup			:1006FF00
Index: /branches/new-random/cocoa-ide/hemlock/resources/mh-scan
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/resources/mh-scan	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/resources/mh-scan	(revision 13309)
@@ -0,0 +1,5 @@
+%4(putnumf(msg))%<(cur)+%| %>%<{replied}A%| %> \
+%02(putnumf(mday{date}))-%(putstr(month{date}))%<{date} %|*%>\
+%5(size) \
+%<(mymbox{from})To:%14(putstrf(friendly{to}))%|%17(putstrf(friendly{from}))%> \
+%{subject}%<{body}   <<%{body}%>
Index: /branches/new-random/cocoa-ide/hemlock/resources/spell-dictionary.text
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/resources/spell-dictionary.text	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/resources/spell-dictionary.text	(revision 13309)
@@ -0,0 +1,15505 @@
+AAAI
+ABACK
+ABAFT
+ABANDON/D/G/S
+ABANDONMENT
+ABASE/D/G/S
+ABASEMENT/S
+ABASH/D/G/S
+ABATE/D/R/G/S
+ABATEMENT/S
+ABBE
+ABBEY/M/S
+ABBOT/M/S
+ABBREVIATE/D/G/N/X/S
+ABDOMEN/M/S
+ABDOMINAL
+ABDUCT/D/S
+ABDUCTION/M/S
+ABDUCTOR/M/S
+ABED
+ABERRANT
+ABERRATION/S
+ABET/S
+ABETTED
+ABETTER
+ABETTING
+ABETTOR
+ABEYANCE
+ABHOR/S
+ABHORRED
+ABHORRENT
+ABHORRER
+ABHORRING
+ABIDE/D/G/S
+ABILITY/M/S
+ABJECT/P/Y
+ABJECTION/S
+ABJURE/D/G/S
+ABLATE/D/G/N/V/S
+ABLAZE
+ABLE/T/R
+ABLUTE
+ABLY
+ABNORMAL/Y
+ABNORMALITY/S
+ABOARD
+ABODE/M/S
+ABOLISH/D/R/Z/G/S
+ABOLISHMENT/M/S
+ABOLITION
+ABOLITIONIST/S
+ABOMINABLE
+ABORIGINAL
+ABORIGINE/M/S
+ABORT/D/G/V/S
+ABORTION/M/S
+ABORTIVE/Y
+ABOUND/D/G/S
+ABOUT
+ABOVE
+ABOVEGROUND
+ABRADE/D/G/S
+ABRASION/M/S
+ABREACTION/S
+ABREAST
+ABRIDGE/D/G/S
+ABRIDGMENT
+ABROAD
+ABROGATE/D/G/S
+ABRUPT/P/Y
+ABSCESS/D/S
+ABSCISSA/M/S
+ABSCOND/D/G/S
+ABSENCE/M/S
+ABSENT/D/G/Y/S
+ABSENTEE/M/S
+ABSENTEEISM
+ABSENTIA
+ABSENTMINDED
+ABSINTHE
+ABSOLUTE/P/N/Y/S
+ABSOLVE/D/G/S
+ABSORB/D/R/G/S
+ABSORBENCY
+ABSORBENT
+ABSORPTION/M/S
+ABSORPTIVE
+ABSTAIN/D/R/G/S
+ABSTENTION/S
+ABSTINENCE
+ABSTRACT/P/D/G/Y/S
+ABSTRACTION/M/S
+ABSTRACTIONISM
+ABSTRACTIONIST
+ABSTRACTOR/M/S
+ABSTRUSE/P
+ABSURD/Y
+ABSURDITY/M/S
+ABUNDANCE
+ABUNDANT/Y
+ABUSE/D/G/V/S
+ABUT/S
+ABUTMENT
+ABUTTED
+ABUTTER/M/S
+ABUTTING
+ABYSMAL/Y
+ABYSS/M/S
+ACACIA
+ACADEMIA
+ACADEMIC/S
+ACADEMICALLY
+ACADEMY/M/S
+ACCEDE/D/S
+ACCELERATE/D/G/N/X/S
+ACCELERATOR/S
+ACCELEROMETER/M/S
+ACCENT/D/G/S
+ACCENTUAL
+ACCENTUATE/D/G/N/S
+ACCEPT/D/R/Z/G/S
+ACCEPTABILITY
+ACCEPTABLE
+ACCEPTABLY
+ACCEPTANCE/M/S
+ACCEPTOR/M/S
+ACCESS/D/G/S
+ACCESSIBILITY
+ACCESSIBLE
+ACCESSIBLY
+ACCESSION/M/S
+ACCESSOR/M/S
+ACCESSORY/M/S
+ACCIDENT/M/S
+ACCIDENTAL/Y
+ACCLAIM/D/G/S
+ACCLAMATION
+ACCLIMATE/D/G/S
+ACCLIMATIZATION
+ACCLIMATIZED
+ACCOLADE/S
+ACCOMMODATE/D/G/N/X/S
+ACCOMPANIMENT/M/S
+ACCOMPANIST/M/S
+ACCOMPANY/D/G/S
+ACCOMPLICE/S
+ACCOMPLISH/D/R/Z/G/S
+ACCOMPLISHMENT/M/S
+ACCORD/D/R/Z/G/S
+ACCORDANCE
+ACCORDINGLY
+ACCORDION/M/S
+ACCOST/D/G/S
+ACCOUNT/D/G/S
+ACCOUNTABILITY
+ACCOUNTABLE
+ACCOUNTABLY
+ACCOUNTANCY
+ACCOUNTANT/M/S
+ACCOUTREMENT/S
+ACCREDIT/D
+ACCREDITATION/S
+ACCRETION/M/S
+ACCRUE/D/G/S
+ACCULTURATE/D/G/N/S
+ACCUMULATE/D/G/N/X/S
+ACCUMULATOR/M/S
+ACCURACY/S
+ACCURATE/P/Y
+ACCURSED
+ACCUSAL
+ACCUSATION/M/S
+ACCUSATIVE
+ACCUSE/D/R/G/S
+ACCUSINGLY
+ACCUSTOM/D/G/S
+ACE/M/S
+ACETATE
+ACETONE
+ACETYLENE
+ACHE/D/G/S
+ACHIEVABLE
+ACHIEVE/D/R/Z/G/S
+ACHIEVEMENT/M/S
+ACHILLES
+ACID/Y/S
+ACIDIC
+ACIDITY/S
+ACIDULOUS
+ACKNOWLEDGE/D/R/Z/G/S
+ACKNOWLEDGMENT/M/S
+ACM
+ACME
+ACNE
+ACOLYTE/S
+ACORN/M/S
+ACOUSTIC/S
+ACOUSTICAL/Y
+ACOUSTICIAN
+ACQUAINT/D/G/S
+ACQUAINTANCE/M/S
+ACQUIESCE/D/G/S
+ACQUIESCENCE
+ACQUIRABLE
+ACQUIRE/D/G/S
+ACQUISITION/M/S
+ACQUISITIVENESS
+ACQUIT/S
+ACQUITTAL
+ACQUITTED
+ACQUITTER
+ACQUITTING
+ACRE/M/S
+ACREAGE
+ACRID
+ACRIMONIOUS
+ACRIMONY
+ACROBAT/M/S
+ACROBATIC/S
+ACRONYM/M/S
+ACROPOLIS
+ACROSS
+ACRYLIC
+ACT/D/G/V/S
+ACTINIUM
+ACTINOMETER/S
+ACTION/M/S
+ACTIVATE/D/G/N/X/S
+ACTIVATOR/M/S
+ACTIVELY
+ACTIVISM
+ACTIVIST/M/S
+ACTIVITY/M/S
+ACTOR/M/S
+ACTRESS/M/S
+ACTUAL/Y/S
+ACTUALITY/S
+ACTUALIZATION
+ACTUARIAL/Y
+ACTUATE/D/G/S
+ACTUATOR/M/S
+ACUITY
+ACUMEN
+ACUTE/P/Y
+ACYCLIC
+ACYCLICALLY
+AD
+ADAGE/S
+ADAGIO/S
+ADAMANT/Y
+ADAPT/D/R/Z/G/V/S
+ADAPTABILITY
+ADAPTABLE
+ADAPTATION/M/S
+ADAPTIVELY
+ADAPTOR/S
+ADD/D/R/Z/G/S
+ADDENDA
+ADDENDUM
+ADDICT/D/G/S
+ADDICTION/M/S
+ADDISON
+ADDITION/M/S
+ADDITIONAL/Y
+ADDITIVE/M/S
+ADDITIVITY
+ADDRESS/D/R/Z/G/S
+ADDRESSABILITY
+ADDRESSABLE
+ADDRESSEE/M/S
+ADDUCE/D/G/S
+ADDUCIBLE
+ADDUCT/D/G/S
+ADDUCTION
+ADDUCTOR
+ADEPT
+ADEQUACY/S
+ADEQUATE/Y
+ADHERE/D/R/Z/G/S
+ADHERENCE
+ADHERENT/M/S
+ADHESION/S
+ADHESIVE/M/S
+ADIABATIC
+ADIABATICALLY
+ADIEU
+ADJACENCY
+ADJACENT
+ADJECTIVE/M/S
+ADJOIN/D/G/S
+ADJOURN/D/G/S
+ADJOURNMENT
+ADJUDGE/D/G/S
+ADJUDICATE/D/G/S
+ADJUDICATION/M/S
+ADJUNCT/M/S
+ADJURE/D/G/S
+ADJUST/D/R/Z/G/S
+ADJUSTABLE
+ADJUSTABLY
+ADJUSTMENT/M/S
+ADJUSTOR/M/S
+ADJUTANT/S
+ADMINISTER/D/G/J/S
+ADMINISTRATION/M/S
+ADMINISTRATIVE/Y
+ADMINISTRATOR/M/S
+ADMIRABLE
+ADMIRABLY
+ADMIRAL/M/S
+ADMIRALTY
+ADMIRATION/S
+ADMIRE/D/R/Z/G/S
+ADMIRING/Y
+ADMISSIBILITY
+ADMISSIBLE
+ADMISSION/M/S
+ADMIT/S
+ADMITTANCE
+ADMITTED/Y
+ADMITTER/S
+ADMITTING
+ADMIX/D/S
+ADMIXTURE
+ADMONISH/D/G/S
+ADMONISHMENT/M/S
+ADMONITION/M/S
+ADO
+ADOBE
+ADOLESCENCE
+ADOLESCENT/M/S
+ADOPT/D/R/Z/G/V/S
+ADOPTION/M/S
+ADORABLE
+ADORATION
+ADORE/D/S
+ADORN/D/S
+ADORNMENT/M/S
+ADRENAL
+ADRENALINE
+ADRIFT
+ADROIT/P
+ADS
+ADSORB/D/G/S
+ADSORPTION
+ADULATION
+ADULT/M/S
+ADULTERATE/D/G/S
+ADULTERER/M/S
+ADULTEROUS/Y
+ADULTERY
+ADULTHOOD
+ADUMBRATE/D/G/S
+ADVANCE/D/G/S
+ADVANCEMENT/M/S
+ADVANTAGE/D/S
+ADVANTAGEOUS/Y
+ADVENT
+ADVENTIST/S
+ADVENTITIOUS
+ADVENTURE/D/R/Z/G/S
+ADVENTUROUS
+ADVERB/M/S
+ADVERBIAL
+ADVERSARY/M/S
+ADVERSE/Y
+ADVERSITY/S
+ADVERTISE/D/R/Z/G/S
+ADVERTISEMENT/M/S
+ADVICE
+ADVISABILITY
+ADVISABLE
+ADVISABLY
+ADVISE/D/R/Z/G/S
+ADVISEDLY
+ADVISEE/M/S
+ADVISEMENT/S
+ADVISOR/M/S
+ADVISORY
+ADVOCACY
+ADVOCATE/D/G/S
+AEGIS
+AERATE/D/G/N/S
+AERATOR/S
+AERIAL/M/S
+AEROACOUSTIC
+AEROBIC/S
+AERODYNAMIC/S
+AERONAUTIC/S
+AERONAUTICAL
+AEROSOL/S
+AEROSOLIZE
+AEROSPACE
+AESTHETIC/M/S
+AESTHETICALLY
+AFAR
+AFFABLE
+AFFAIR/M/S
+AFFECT/D/G/V/S
+AFFECTATION/M/S
+AFFECTINGLY
+AFFECTION/M/S
+AFFECTIONATE/Y
+AFFECTOR
+AFFERENT
+AFFIANCED
+AFFIDAVIT/M/S
+AFFILIATE/D/G/N/X/S
+AFFINITY/M/S
+AFFIRM/D/G/S
+AFFIRMATION/M/S
+AFFIRMATIVE/Y
+AFFIX/D/G/S
+AFFLICT/D/G/V/S
+AFFLICTION/M/S
+AFFLUENCE
+AFFLUENT
+AFFORD/D/G/S
+AFFORDABLE
+AFFRICATE/S
+AFFRIGHT
+AFFRONT/D/G/S
+AFGHAN/S
+AFGHANISTAN
+AFICIONADO
+AFIELD
+AFIRE
+AFLAME
+AFLOAT
+AFOOT
+AFORE
+AFOREMENTIONED
+AFORESAID
+AFORETHOUGHT
+AFOSR
+AFOUL
+AFRAID
+AFRESH
+AFRICA
+AFRICAN/S
+AFT/R
+AFTEREFFECT
+AFTERMATH
+AFTERMOST
+AFTERNOON/M/S
+AFTERSHOCK/S
+AFTERTHOUGHT/S
+AFTERWARD/S
+AGAIN
+AGAINST
+AGAPE
+AGAR
+AGATE/S
+AGE/D/R/Z/G/S
+AGELESS
+AGENCY/M/S
+AGENDA/M/S
+AGENT/M/S
+AGGLOMERATE/D/N/S
+AGGLUTINATE/D/G/N/S
+AGGLUTININ/S
+AGGRAVATE/D/N/S
+AGGREGATE/D/G/N/X/Y/S
+AGGRESSION/M/S
+AGGRESSIVE/P/Y
+AGGRESSOR/S
+AGGRIEVE/D/G/S
+AGHAST
+AGILE/Y
+AGILITY
+AGITATE/D/G/N/X/S
+AGITATOR/M/S
+AGLEAM
+AGLOW
+AGNOSTIC/M/S
+AGO
+AGOG
+AGONIZE/D/G/S
+AGONY/S
+AGRARIAN
+AGREE/D/R/Z/S
+AGREEABLE/P
+AGREEABLY
+AGREEING
+AGREEMENT/M/S
+AGRICULTURAL/Y
+AGRICULTURE
+AGUE
+AH
+AHEAD
+AI
+AID/D/G/S
+AIDE/D/G/S
+AIL/G
+AILERON/S
+AILMENT/M/S
+AIM/D/R/Z/G/S
+AIMLESS/Y
+AIR/D/R/Z/G/J/S
+AIRBAG/S
+AIRBORNE
+AIRCRAFT
+AIRDROP/S
+AIREDALE
+AIRFIELD/M/S
+AIRFLOW
+AIRFOIL/S
+AIRFRAME/S
+AIRILY
+AIRLESS
+AIRLIFT/M/S
+AIRLINE/R/S
+AIRLOCK/M/S
+AIRMAIL/S
+AIRMAN
+AIRMEN
+AIRPLANE/M/S
+AIRPORT/M/S
+AIRSHIP/M/S
+AIRSPACE
+AIRSPEED
+AIRSTRIP/M/S
+AIRWAY/M/S
+AIRY
+AISLE
+AJAR
+AKIMBO
+AKIN
+AL/M
+ALABAMA
+ALABAMIAN
+ALABASTER
+ALACRITY
+ALARM/D/G/S
+ALARMINGLY
+ALARMIST
+ALAS
+ALASKA
+ALBA
+ALBACORE
+ALBANIA
+ALBANIAN/S
+ALBEIT
+ALBUM/S
+ALBUMIN
+ALCHEMY
+ALCIBIADES
+ALCOHOL/M/S
+ALCOHOLIC/M/S
+ALCOHOLISM
+ALCOVE/M/S
+ALDEN
+ALDER
+ALDERMAN/M
+ALDERMEN
+ALE/V
+ALEE
+ALERT/P/D/R/Z/G/Y/S
+ALERTEDLY
+ALEXANDER/M
+ALFALFA
+ALFRED/M
+ALFRESCO
+ALGA
+ALGAE
+ALGAECIDE
+ALGEBRA/M/S
+ALGEBRAIC
+ALGEBRAICALLY
+ALGERIA
+ALGERIAN
+ALGINATE
+ALGOL
+ALGORITHM/M/S
+ALGORITHMIC
+ALGORITHMICALLY
+ALIAS/D/G/S
+ALIBI/M/S
+ALIEN/M/S
+ALIENATE/D/G/N/S
+ALIGHT
+ALIGN/D/G/S
+ALIGNMENT/S
+ALIKE
+ALIMENT/S
+ALIMONY
+ALKALI/M/S
+ALKALINE
+ALKALOID/M/S
+ALKYL
+ALL
+ALLAH/M
+ALLAY/D/G/S
+ALLEGATION/M/S
+ALLEGE/D/G/S
+ALLEGEDLY
+ALLEGIANCE/M/S
+ALLEGORIC
+ALLEGORICAL/Y
+ALLEGORY/M/S
+ALLEGRETTO/M/S
+ALLEGRO/M/S
+ALLELE/S
+ALLEMANDE
+ALLEN/M
+ALLERGIC
+ALLERGY/M/S
+ALLEVIATE/D/R/Z/G/N/S
+ALLEY/M/S
+ALLEYWAY/M/S
+ALLIANCE/M/S
+ALLIGATOR/M/S
+ALLITERATION/M/S
+ALLITERATIVE
+ALLOCATE/D/G/N/X/S
+ALLOCATOR/M/S
+ALLOPHONE/S
+ALLOPHONIC
+ALLOT/S
+ALLOTMENT/M/S
+ALLOTTED
+ALLOTTER
+ALLOTTING
+ALLOW/D/G/S
+ALLOWABLE
+ALLOWABLY
+ALLOWANCE/M/S
+ALLOY/M/S
+ALLUDE/D/G/S
+ALLURE/G
+ALLUREMENT
+ALLUSION/M/S
+ALLUSIVE/P
+ALLY/D/G/S
+ALMA
+ALMANAC/M/S
+ALMIGHTY
+ALMOND/M/S
+ALMONER
+ALMOST
+ALMS
+ALMSMAN
+ALNICO
+ALOE/S
+ALOFT
+ALOHA
+ALONE/P
+ALONG
+ALONGSIDE
+ALOOF/P
+ALOUD
+ALPHA
+ALPHABET/M/S
+ALPHABETIC/S
+ALPHABETICAL/Y
+ALPHABETIZE/D/G/S
+ALPHANUMERIC
+ALPINE
+ALPS
+ALREADY
+ALSO
+ALTAR/M/S
+ALTER/D/R/Z/G/S
+ALTERABLE
+ALTERATION/M/S
+ALTERCATION/M/S
+ALTERNATE/D/G/N/X/V/Y/S
+ALTERNATIVE/Y/S
+ALTERNATOR/M/S
+ALTHOUGH
+ALTITUDE/S
+ALTMODE
+ALTO/M/S
+ALTOGETHER
+ALTRUISM
+ALTRUIST
+ALTRUISTIC
+ALTRUISTICALLY
+ALUM
+ALUMINUM
+ALUMNA/M
+ALUMNAE
+ALUMNI
+ALUMNUS
+ALUNDUM
+ALVEOLAR
+ALVEOLI
+ALVEOLUS
+ALWAYS
+ALZHEIMER/M
+AM/N
+AMAIN
+AMALGAM/M/S
+AMALGAMATE/D/G/N/S
+AMANUENSIS
+AMASS/D/G/S
+AMATEUR/M/S
+AMATEURISH/P
+AMATEURISM
+AMATORY
+AMAZE/D/R/Z/G/S
+AMAZEDLY
+AMAZEMENT
+AMAZING/Y
+AMAZON/M/S
+AMBASSADOR/M/S
+AMBER
+AMBIANCE
+AMBIDEXTROUS/Y
+AMBIENT
+AMBIGUITY/M/S
+AMBIGUOUS/Y
+AMBITION/M/S
+AMBITIOUS/Y
+AMBIVALENCE
+AMBIVALENT/Y
+AMBLE/D/R/G/S
+AMBROSIAL
+AMBULANCE/M/S
+AMBULATORY
+AMBUSCADE
+AMBUSH/D/S
+AMDAHL/M
+AMELIA
+AMELIORATE/D/G
+AMENABLE
+AMEND/D/G/S
+AMENDMENT/M/S
+AMENITY/S
+AMENORRHEA
+AMERICA/M/S
+AMERICAN/M/S
+AMERICANA
+AMERICIUM
+AMIABLE
+AMICABLE
+AMICABLY
+AMID
+AMIDE
+AMIDST
+AMIGO
+AMINO
+AMISS
+AMITY
+AMMO
+AMMONIA
+AMMONIAC
+AMMONIUM
+AMMUNITION
+AMNESTY
+AMOEBA/M/S
+AMOK
+AMONG
+AMONGST
+AMORAL
+AMORALITY
+AMORIST
+AMOROUS
+AMORPHOUS/Y
+AMORTIZE/D/G/S
+AMOUNT/D/R/Z/G/S
+AMOUR
+AMP/Y/S
+AMPERE/S
+AMPERSAND/M/S
+AMPHETAMINE/S
+AMPHIBIAN/M/S
+AMPHIBIOUS/Y
+AMPHIBOLOGY
+AMPHITHEATER/M/S
+AMPLE
+AMPLIFY/D/R/Z/G/N/S
+AMPLITUDE/M/S
+AMPOULE/M/S
+AMPUTATE/D/G/S
+AMSTERDAM
+AMTRAK
+AMULET/S
+AMUSE/D/R/Z/G/S
+AMUSEDLY
+AMUSEMENT/M/S
+AMUSINGLY
+AMYL
+AN
+ANABAPTIST/M/S
+ANACHRONISM/M/S
+ANACHRONISTICALLY
+ANACONDA/S
+ANAEROBIC
+ANAESTHESIA
+ANAGRAM/M/S
+ANAL
+ANALOG
+ANALOGICAL
+ANALOGOUS/Y
+ANALOGUE/M/S
+ANALOGY/M/S
+ANALYSES
+ANALYSIS
+ANALYST/M/S
+ANALYTIC
+ANALYTICAL/Y
+ANALYTICITY/S
+ANALYZABLE
+ANALYZE/D/R/Z/G/S
+ANAPHORA
+ANAPHORIC
+ANAPHORICALLY
+ANAPLASMOSIS
+ANARCHIC
+ANARCHICAL
+ANARCHIST/M/S
+ANARCHY
+ANASTOMOSES
+ANASTOMOSIS
+ANASTOMOTIC
+ANATHEMA
+ANATOMIC
+ANATOMICAL/Y
+ANATOMY
+ANCESTOR/M/S
+ANCESTRAL
+ANCESTRY
+ANCHOR/D/G/S
+ANCHORAGE/M/S
+ANCHORITE
+ANCHORITISM
+ANCHOVY/S
+ANCIENT/Y/S
+ANCILLARY
+AND/Z/G
+ANDERSON/M
+ANDORRA
+ANDREW/M
+ANDY/M
+ANECDOTAL
+ANECDOTE/M/S
+ANECHOIC
+ANEMIA
+ANEMIC
+ANEMOMETER/M/S
+ANEMOMETRY
+ANEMONE
+ANESTHESIA
+ANESTHETIC/M/S
+ANESTHETICALLY
+ANESTHETIZE/D/G/S
+ANEW
+ANGEL/M/S
+ANGELIC
+ANGER/D/G/S
+ANGIOGRAPHY
+ANGLE/D/R/Z/G/S
+ANGLICAN/S
+ANGLICANISM
+ANGLOPHILIA
+ANGLOPHOBIA
+ANGOLA
+ANGRILY
+ANGRY/T/R
+ANGST
+ANGSTROM
+ANGUISH/D
+ANGULAR/Y
+ANHYDROUS/Y
+ANILINE
+ANIMAL/M/S
+ANIMATE/P/D/G/N/X/Y/S
+ANIMATEDLY
+ANIMATOR/M/S
+ANIMISM
+ANIMIZED
+ANIMOSITY
+ANION/M/S
+ANIONIC
+ANISE
+ANISEIKONIC
+ANISOTROPIC
+ANISOTROPY
+ANKLE/M/S
+ANNAL/S
+ANNEAL/G
+ANNEX/D/G/S
+ANNEXATION
+ANNIHILATE/D/G/N/S
+ANNIVERSARY/M/S
+ANNOTATE/D/G/N/X/S
+ANNOUNCE/D/R/Z/G/S
+ANNOUNCEMENT/M/S
+ANNOY/D/G/S
+ANNOYANCE/M/S
+ANNOYER/S
+ANNOYINGLY
+ANNUAL/Y/S
+ANNUITY
+ANNUL/S
+ANNULLED
+ANNULLING
+ANNULMENT/M/S
+ANNUM
+ANNUNCIATE/D/G/S
+ANNUNCIATOR/S
+ANODE/M/S
+ANODIZE/D/S
+ANOINT/D/G/S
+ANOMALOUS/Y
+ANOMALY/M/S
+ANOMIC
+ANOMIE
+ANON
+ANONYMITY
+ANONYMOUS/Y
+ANOREXIA
+ANOTHER/M
+ANSI
+ANSWER/D/R/Z/G/S
+ANSWERABLE
+ANT/M/S
+ANTAGONISM/S
+ANTAGONIST/M/S
+ANTAGONISTIC
+ANTAGONISTICALLY
+ANTAGONIZE/D/G/S
+ANTARCTIC
+ANTARCTICA
+ANTE
+ANTEATER/M/S
+ANTECEDENT/M/S
+ANTEDATE
+ANTELOPE/M/S
+ANTENNA/M/S
+ANTENNAE
+ANTERIOR
+ANTHEM/M/S
+ANTHER
+ANTHOLOGY/S
+ANTHONY
+ANTHRACITE
+ANTHROPOLOGICAL/Y
+ANTHROPOLOGIST/M/S
+ANTHROPOLOGY
+ANTHROPOMORPHIC
+ANTHROPOMORPHICALLY
+ANTI
+ANTIBACTERIAL
+ANTIBIOTIC/S
+ANTIBODY/S
+ANTIC/M/S
+ANTICIPATE/D/G/N/X/S
+ANTICIPATORY
+ANTICOAGULATION
+ANTICOMPETITIVE
+ANTIDISESTABLISHMENTARIANISM
+ANTIDOTE/M/S
+ANTIFORMANT
+ANTIFUNDAMENTALIST
+ANTIGEN/M/S
+ANTIHISTORICAL
+ANTIMICROBIAL
+ANTIMONY
+ANTINOMIAN
+ANTINOMY
+ANTIPATHY
+ANTIPHONAL
+ANTIPODE/M/S
+ANTIQUARIAN/M/S
+ANTIQUATE/D
+ANTIQUE/M/S
+ANTIQUITY/S
+ANTIREDEPOSITION
+ANTIRESONANCE
+ANTIRESONATOR
+ANTISEPTIC
+ANTISERA
+ANTISERUM
+ANTISLAVERY
+ANTISOCIAL
+ANTISUBMARINE
+ANTISYMMETRIC
+ANTISYMMETRY
+ANTITHESIS
+ANTITHETICAL
+ANTITHYROID
+ANTITOXIN/M/S
+ANTITRUST
+ANTLER/D
+ANUS
+ANVIL/M/S
+ANXIETY/S
+ANXIOUS/Y
+ANY
+ANYBODY
+ANYHOW
+ANYMORE
+ANYONE
+ANYPLACE
+ANYTHING
+ANYTIME
+ANYWAY
+ANYWHERE
+AORTA
+APACE
+APART
+APARTHEID
+APARTMENT/M/S
+APATHETIC
+APATHY
+APE/D/G/S
+APERIODIC
+APERIODICITY
+APERTURE
+APEX
+APHASIA
+APHASIC
+APHID/M/S
+APHONIC
+APHORISM/M/S
+APHRODITE
+APIARY/S
+APICAL
+APIECE
+APISH
+APLENTY
+APLOMB
+APOCALYPSE
+APOCALYPTIC
+APOCRYPHA
+APOCRYPHAL
+APOGEE/S
+APOLLO
+APOLLONIAN
+APOLOGETIC
+APOLOGETICALLY
+APOLOGIA
+APOLOGIST/M/S
+APOLOGIZE/D/G/S
+APOLOGY/M/S
+APOSTATE
+APOSTLE/M/S
+APOSTOLIC
+APOSTROPHE/S
+APOTHECARY
+APOTHEOSES
+APOTHEOSIS
+APPALACHIA
+APPALACHIAN/S
+APPALL/D/G
+APPALLINGLY
+APPANAGE
+APPARATUS
+APPAREL/D
+APPARENT/Y
+APPARITION/M/S
+APPEAL/D/R/Z/G/S
+APPEALINGLY
+APPEAR/D/R/Z/G/S
+APPEARANCE/S
+APPEASE/D/G/S
+APPEASEMENT
+APPELLANT/M/S
+APPELLATE
+APPEND/D/R/Z/G/S
+APPENDAGE/M/S
+APPENDICES
+APPENDICITIS
+APPENDIX/M/S
+APPERTAIN/S
+APPETITE/M/S
+APPETIZER
+APPETIZING
+APPLAUD/D/G/S
+APPLAUSE
+APPLE/M/S
+APPLEJACK
+APPLIANCE/M/S
+APPLICABILITY
+APPLICABLE
+APPLICANT/M/S
+APPLICATION/M/S
+APPLICATIVE/Y
+APPLICATOR/M/S
+APPLIQUE
+APPLY/D/R/Z/G/N/X/S
+APPOINT/D/R/Z/G/V/S
+APPOINTEE/M/S
+APPOINTMENT/M/S
+APPORTION/D/G/S
+APPORTIONMENT/S
+APPRAISAL/M/S
+APPRAISE/D/R/Z/G/S
+APPRAISINGLY
+APPRECIABLE
+APPRECIABLY
+APPRECIATE/D/G/N/X/V/S
+APPRECIATIVELY
+APPREHEND/D
+APPREHENSIBLE
+APPREHENSION/M/S
+APPREHENSIVE/P/Y
+APPRENTICE/D/S
+APPRENTICESHIP
+APPRISE/D/G/S
+APPROACH/D/R/Z/G/S
+APPROACHABILITY
+APPROACHABLE
+APPROBATE/N
+APPROPRIATE/P/D/G/N/X/Y/S
+APPROPRIATOR/M/S
+APPROVAL/M/S
+APPROVE/D/R/Z/G/S
+APPROVINGLY
+APPROXIMATE/D/G/N/X/Y/S
+APPURTENANCE/S
+APRICOT/M/S
+APRIL
+APRON/M/S
+APROPOS
+APSE
+APSIS
+APT/P/Y
+APTITUDE/S
+AQUA
+AQUARIA
+AQUARIUM
+AQUARIUS
+AQUATIC
+AQUEDUCT/M/S
+AQUEOUS
+AQUIFER/S
+ARAB/M/S
+ARABESQUE
+ARABIA
+ARABIAN/S
+ARABIC
+ARABLE
+ARACHNID/M/S
+ARBITER/M/S
+ARBITRARILY
+ARBITRARY/P
+ARBITRATE/D/G/N/S
+ARBITRATOR/M/S
+ARBOR/M/S
+ARBOREAL
+ARC/D/G/S
+ARCADE/D/M/S
+ARCANE
+ARCH/D/R/Z/G/Y/S
+ARCHAEOLOGICAL
+ARCHAEOLOGIST/M/S
+ARCHAEOLOGY
+ARCHAIC/P
+ARCHAICALLY
+ARCHAISM
+ARCHAIZE
+ARCHANGEL/M/S
+ARCHBISHOP
+ARCHDIOCESE/S
+ARCHENEMY
+ARCHEOLOGICAL
+ARCHEOLOGIST
+ARCHEOLOGY
+ARCHERY
+ARCHETYPE
+ARCHFOOL
+ARCHIPELAGO
+ARCHIPELAGOES
+ARCHITECT/M/S
+ARCHITECTONIC
+ARCHITECTURAL/Y
+ARCHITECTURE/M/S
+ARCHIVAL
+ARCHIVE/D/R/Z/G/S
+ARCHIVIST
+ARCLIKE
+ARCTIC
+ARDENT/Y
+ARDOR
+ARDUOUS/P/Y
+ARE
+AREA/M/S
+AREN'T
+ARENA/M/S
+ARGENTINA
+ARGO/S
+ARGON
+ARGONAUT/S
+ARGOT
+ARGUABLE
+ARGUABLY
+ARGUE/D/R/Z/G/S
+ARGUMENT/M/S
+ARGUMENTATION
+ARGUMENTATIVE
+ARIANISM
+ARIANIST/S
+ARID
+ARIDITY
+ARIES
+ARIGHT
+ARISE/R/G/J/S
+ARISEN
+ARISTOCRACY
+ARISTOCRAT/M/S
+ARISTOCRATIC
+ARISTOCRATICALLY
+ARISTOTELIAN
+ARISTOTLE
+ARITHMETIC/S
+ARITHMETICAL/Y
+ARITHMETIZE/D/S
+ARIZONA
+ARK
+ARKANSAS
+ARM/D/R/Z/G/S
+ARMADILLO/S
+ARMAGEDDON
+ARMAMENT/M/S
+ARMCHAIR/M/S
+ARMENIAN
+ARMFUL
+ARMHOLE
+ARMISTICE
+ARMLOAD
+ARMOR/D/R
+ARMORY
+ARMOUR
+ARMPIT/M/S
+ARMSTRONG
+ARMY/M/S
+AROMA/S
+AROMATIC
+AROSE
+AROUND
+AROUSAL
+AROUSE/D/G/S
+ARPA
+ARPANET
+ARPEGGIO/M/S
+ARRACK
+ARRAIGN/D/G/S
+ARRAIGNMENT/M/S
+ARRANGE/D/R/Z/G/S
+ARRANGEMENT/M/S
+ARRANT
+ARRAY/D/S
+ARREARS
+ARREST/D/R/Z/G/S
+ARRESTINGLY
+ARRESTOR/M/S
+ARRIVAL/M/S
+ARRIVE/D/G/S
+ARROGANCE
+ARROGANT/Y
+ARROGATE/D/G/N/S
+ARROW/D/S
+ARROWHEAD/M/S
+ARROYO/S
+ARSENAL/M/S
+ARSENIC
+ARSINE
+ARSON
+ART/M/S
+ARTEMIS
+ARTERIAL
+ARTERIOLAR
+ARTERIOLE/M/S
+ARTERIOSCLEROSIS
+ARTERY/M/S
+ARTFUL/P/Y
+ARTHOGRAM
+ARTHRITIS
+ARTHROPOD/M/S
+ARTICHOKE/M/S
+ARTICLE/M/S
+ARTICULATE/P/D/G/N/X/Y/S
+ARTICULATOR/S
+ARTICULATORY
+ARTIFACT/M/S
+ARTIFACTUALLY
+ARTIFICE/R/S
+ARTIFICIAL/P/Y
+ARTIFICIALITY/S
+ARTILLERIST
+ARTILLERY
+ARTISAN/M/S
+ARTIST/M/S
+ARTISTIC
+ARTISTICALLY
+ARTISTRY
+ARTLESS
+ARTWORK
+ARYAN
+AS
+ASBESTOS
+ASCEND/D/R/Z/G/S
+ASCENDANCY
+ASCENDANT
+ASCENDENCY
+ASCENDENT
+ASCENSION/S
+ASCENT
+ASCERTAIN/D/G/S
+ASCERTAINABLE
+ASCETIC/M/S
+ASCETICISM
+ASCII
+ASCOT
+ASCRIBABLE
+ASCRIBE/D/G/S
+ASCRIPTION
+ASEPTIC
+ASH/R/N/S
+ASHAMED/Y
+ASHMAN
+ASHORE
+ASHTRAY/M/S
+ASIA
+ASIAN/S
+ASIATIC
+ASIDE
+ASININE
+ASK/D/R/Z/G/S
+ASKANCE
+ASKEW
+ASLEEP
+ASOCIAL
+ASP/N
+ASPARAGUS
+ASPECT/M/S
+ASPERSION/M/S
+ASPHALT
+ASPHYXIA
+ASPIC
+ASPIRANT/M/S
+ASPIRATE/D/G/S
+ASPIRATION/M/S
+ASPIRATOR/S
+ASPIRE/D/G/S
+ASPIRIN/S
+ASS/M/S
+ASSAIL/D/G/S
+ASSAILANT/M/S
+ASSASSIN/M/S
+ASSASSINATE/D/G/N/X/S
+ASSAULT/D/G/S
+ASSAY/D/G
+ASSEMBLAGE/M/S
+ASSEMBLE/D/R/Z/G/S
+ASSEMBLY/M/S
+ASSENT/D/R/G/S
+ASSERT/D/R/Z/G/V/S
+ASSERTION/M/S
+ASSERTIVELY
+ASSERTIVENESS
+ASSESS/D/G/S
+ASSESSMENT/M/S
+ASSESSOR/S
+ASSET/M/S
+ASSIDUITY
+ASSIDUOUS/Y
+ASSIGN/D/R/Z/G/S
+ASSIGNABLE
+ASSIGNEE/M/S
+ASSIGNMENT/M/S
+ASSIMILATE/D/G/N/X/S
+ASSIST/D/G/S
+ASSISTANCE/S
+ASSISTANT/M/S
+ASSISTANTSHIP/S
+ASSOCIATE/D/G/N/X/V/S
+ASSOCIATIONAL
+ASSOCIATIVELY
+ASSOCIATIVITY
+ASSOCIATOR/M/S
+ASSONANCE
+ASSONANT
+ASSORT/D/S
+ASSORTMENT/M/S
+ASSUAGE/D/S
+ASSUME/D/G/S
+ASSUMPTION/M/S
+ASSURANCE/M/S
+ASSURE/D/R/Z/G/S
+ASSUREDLY
+ASSURINGLY
+ASSYRIAN
+ASSYRIOLOGY
+ASTATINE
+ASTER/M/S
+ASTERISK/M/S
+ASTEROID/M/S
+ASTEROIDAL
+ASTHMA
+ASTONISH/D/G/S
+ASTONISHINGLY
+ASTONISHMENT
+ASTOUND/D/G/S
+ASTRAL
+ASTRAY
+ASTRIDE
+ASTRINGENCY
+ASTRINGENT
+ASTRONAUT/M/S
+ASTRONAUTICS
+ASTRONOMER/M/S
+ASTRONOMICAL/Y
+ASTRONOMY
+ASTROPHYSICAL
+ASTROPHYSICS
+ASTUTE/P
+ASUNDER
+ASYLUM
+ASYMMETRIC
+ASYMMETRICALLY
+ASYMMETRY
+ASYMPTOMATICALLY
+ASYMPTOTE/M/S
+ASYMPTOTIC
+ASYMPTOTICALLY
+ASYNCHRONISM
+ASYNCHRONOUS/Y
+ASYNCHRONY
+AT
+ATAVISTIC
+ATE
+ATEMPORAL
+ATHEIST/M/S
+ATHEISTIC
+ATHENA
+ATHENIAN/S
+ATHENS
+ATHEROSCLEROSIS
+ATHLETE/M/S
+ATHLETIC/S
+ATHLETICISM
+ATLANTIC
+ATLAS
+ATMOSPHERE/M/S
+ATMOSPHERIC
+ATOLL/M/S
+ATOM/M/S
+ATOMIC/S
+ATOMICALLY
+ATOMIZATION
+ATOMIZE/D/G/S
+ATONAL/Y
+ATONE/D/S
+ATONEMENT
+ATOP
+ATROCIOUS/Y
+ATROCITY/M/S
+ATROPHIC
+ATROPHY/D/G/S
+ATTACH/D/R/Z/G/S
+ATTACHE/D/G/S
+ATTACHMENT/M/S
+ATTACK/D/R/Z/G/S
+ATTACKABLE
+ATTAIN/D/R/Z/G/S
+ATTAINABLE
+ATTAINABLY
+ATTAINMENT/M/S
+ATTEMPT/D/R/Z/G/S
+ATTEND/D/R/Z/G/S
+ATTENDANCE/M/S
+ATTENDANT/M/S
+ATTENDEE/M/S
+ATTENTION/M/S
+ATTENTIONAL
+ATTENTIONALITY
+ATTENTIVE/P/Y
+ATTENUATE/D/G/N/S
+ATTENUATOR/M/S
+ATTEST/D/G/S
+ATTIC/M/S
+ATTIRE/D/G/S
+ATTITUDE/M/S
+ATTITUDINAL
+ATTORNEY/M/S
+ATTRACT/D/G/V/S
+ATTRACTION/M/S
+ATTRACTIVELY
+ATTRACTIVENESS
+ATTRACTOR/M/S
+ATTRIBUTABLE
+ATTRIBUTE/D/G/N/X/V/S
+ATTRIBUTIVELY
+ATTRITION
+ATTUNE/D/G/S
+ATYPICAL/Y
+AUBURN
+AUCKLAND
+AUCTION
+AUCTIONEER/M/S
+AUDACIOUS/P/Y
+AUDACITY
+AUDIBLE
+AUDIBLY
+AUDIENCE/M/S
+AUDIO
+AUDIOGRAM/M/S
+AUDIOLOGICAL
+AUDIOLOGIST/M/S
+AUDIOLOGY
+AUDIOMETER/S
+AUDIOMETRIC
+AUDIOMETRY
+AUDIT/D/G/S
+AUDITION/D/M/G/S
+AUDITOR/M/S
+AUDITORIUM
+AUDITORY
+AUDUBON
+AUGER/M/S
+AUGHT
+AUGMENT/D/G/S
+AUGMENTATION
+AUGUR/S
+AUGUST/P/Y
+AUGUSTA
+AUNT/M/S
+AURA/M/S
+AURAL/Y
+AUREOLE
+AUREOMYCIN
+AURORA
+AUSCULTATE/D/G/N/X/S
+AUSPICE/S
+AUSPICIOUS/Y
+AUSTERE/Y
+AUSTERITY
+AUSTIN
+AUSTRALIA
+AUSTRALIAN
+AUSTRIA
+AUSTRIAN
+AUTHENTIC
+AUTHENTICALLY
+AUTHENTICATE/D/G/N/X/S
+AUTHENTICATOR/S
+AUTHENTICITY
+AUTHOR/D/G/S
+AUTHORITARIAN
+AUTHORITARIANISM
+AUTHORITATIVE/Y
+AUTHORITY/M/S
+AUTHORIZATION/M/S
+AUTHORIZE/D/R/Z/G/S
+AUTHORSHIP
+AUTISM
+AUTISTIC
+AUTO/M/S
+AUTOBIOGRAPHIC
+AUTOBIOGRAPHICAL
+AUTOBIOGRAPHY/M/S
+AUTOCOLLIMATOR
+AUTOCORRELATE/N
+AUTOCRACY/S
+AUTOCRAT/M/S
+AUTOCRATIC
+AUTOCRATICALLY
+AUTOFLUORESCENCE
+AUTOGRAPH/D/G
+AUTOGRAPHS
+AUTOMATA
+AUTOMATE/D/G/N/S
+AUTOMATIC
+AUTOMATICALLY
+AUTOMATON
+AUTOMOBILE/M/S
+AUTOMOTIVE
+AUTONAVIGATOR/M/S
+AUTONOMIC
+AUTONOMOUS/Y
+AUTONOMY
+AUTOPILOT/M/S
+AUTOPSY/D/S
+AUTOREGRESSIVE
+AUTOSUGGESTIBILITY
+AUTOTRANSFORMER
+AUTUMN/M/S
+AUTUMNAL
+AUXILIARY/S
+AVAIL/D/R/Z/G/S
+AVAILABILITY/S
+AVAILABLE
+AVAILABLY
+AVALANCHE/D/G/S
+AVANT
+AVARICE
+AVARICIOUS/Y
+AVE
+AVENGE/D/R/G/S
+AVENUE/M/S
+AVER/S
+AVERAGE/D/G/S
+AVERRED
+AVERRER
+AVERRING
+AVERSE/N
+AVERSION/M/S
+AVERT/D/G/S
+AVIAN
+AVIARY/S
+AVIATION
+AVIATOR/M/S
+AVID/Y
+AVIDITY
+AVIONIC/S
+AVOCADO/S
+AVOCATION/M/S
+AVOID/D/R/Z/G/S
+AVOIDABLE
+AVOIDABLY
+AVOIDANCE
+AVOUCH
+AVOW/D/S
+AWAIT/D/G/S
+AWAKE/G/S
+AWAKEN/D/G/S
+AWARD/D/R/Z/G/S
+AWARE/P
+AWASH
+AWAY
+AWE/D
+AWESOME
+AWFUL/P/Y
+AWHILE
+AWKWARD/P/Y
+AWL/M/S
+AWNING/M/S
+AWOKE
+AWRY
+AX/D/R/Z/G/S
+AXE/D/S
+AXIAL/Y
+AXIOLOGICAL
+AXIOM/M/S
+AXIOMATIC
+AXIOMATICALLY
+AXIOMATIZATION/M/S
+AXIOMATIZE/D/G/S
+AXIS
+AXLE/M/S
+AXOLOTL/M/S
+AXON/M/S
+AYE/S
+AZALEA/M/S
+AZIMUTH/M
+AZIMUTHS
+AZURE
+BABBLE/D/G/S
+BABE/M/S
+BABEL/M
+BABY/D/G/S
+BABYHOOD
+BABYISH
+BACCALAUREATE
+BACH/M
+BACHELOR/M/S
+BACILLI
+BACILLUS
+BACK/D/R/Z/G/S
+BACKACHE/M/S
+BACKARROW/S
+BACKBEND/M/S
+BACKBONE/M/S
+BACKDROP/M/S
+BACKGAMMON
+BACKGROUND/M/S
+BACKLASH
+BACKLOG/M/S
+BACKPACK/M/S
+BACKPLANE/M/S
+BACKPOINTER/M/S
+BACKPROPAGATE/D/G/N/X/S
+BACKSCATTER/D/G/S
+BACKSLASH/S
+BACKSPACE/D/S
+BACKSTAGE
+BACKSTAIRS
+BACKSTITCH/D/G/S
+BACKTRACK/D/R/Z/G/S
+BACKUP/S
+BACKWARD/P/S
+BACKWATER/M/S
+BACKWOODS
+BACKYARD/M/S
+BACON
+BACTERIA
+BACTERIAL
+BACTERIUM
+BAD/P/Y
+BADE
+BADGE/R/Z/S
+BADGER'S
+BADGERED
+BADGERING
+BADLANDS
+BADMINTON
+BAFFLE/D/R/Z/G
+BAG/M/S
+BAGATELLE/M/S
+BAGEL/M/S
+BAGGAGE
+BAGGED
+BAGGER/M/S
+BAGGING
+BAGGY
+BAGPIPE/M/S
+BAH
+BAIL/G
+BAILIFF/M/S
+BAIT/D/R/G/S
+BAKE/D/R/Z/G/S
+BAKERY/M/S
+BAKLAVA
+BALALAIKA/M/S
+BALANCE/D/R/Z/G/S
+BALCONY/M/S
+BALD/P/G/Y
+BALE/R/S
+BALEFUL
+BALK/D/G/S
+BALKAN/S
+BALKANIZE/D/G
+BALKY/P
+BALL/D/R/Z/G/S
+BALLAD/M/S
+BALLAST/M/S
+BALLERINA/M/S
+BALLET/M/S
+BALLGOWN/M/S
+BALLISTIC/S
+BALLOON/D/R/Z/G/S
+BALLOT/M/S
+BALLPARK/M/S
+BALLPLAYER/M/S
+BALLROOM/M/S
+BALLYHOO
+BALM/M/S
+BALMY
+BALSA
+BALSAM
+BALTIC
+BALUSTRADE/M/S
+BAMBOO
+BAN/M/S
+BANAL/Y
+BANANA/M/S
+BAND/D/G/S
+BANDAGE/D/G/S
+BANDIT/M/S
+BANDLIMIT/D/G/S
+BANDPASS
+BANDSTAND/M/S
+BANDWAGON/M/S
+BANDWIDTH
+BANDWIDTHS
+BANDY/D/G/S
+BANE
+BANEFUL
+BANG/D/G/S
+BANGLADESH
+BANGLE/M/S
+BANISH/D/G/S
+BANISHMENT
+BANISTER/M/S
+BANJO/M/S
+BANK/D/R/Z/G/S
+BANKRUPT/D/G/S
+BANKRUPTCY/M/S
+BANNED
+BANNER/M/S
+BANNING
+BANQUET/G/J/S
+BANSHEE/M/S
+BANTAM
+BANTER/D/G/S
+BANTU/S
+BAPTISM/M/S
+BAPTISMAL
+BAPTIST/M/S
+BAPTISTERY
+BAPTISTRY/M/S
+BAPTIZE/D/G/S
+BAR/M/S
+BARB/D/R/S
+BARBADOS
+BARBARA/M
+BARBARIAN/M/S
+BARBARIC
+BARBARITY/S
+BARBAROUS/Y
+BARBECUE/D/S/G
+BARBELL/M/S
+BARBITAL
+BARBITURATE/S
+BARD/M/S
+BARE/P/D/T/R/G/Y/S
+BAREFOOT/D
+BARFLY/M/S
+BARGAIN/D/G/S
+BARGE/G/S
+BARITONE/M/S
+BARIUM
+BARK/D/R/Z/G/S
+BARLEY
+BARN/M/S
+BARNSTORM/D/G/S
+BARNYARD/M/S
+BAROMETER/M/S
+BAROMETRIC
+BARON/M/S
+BARONESS
+BARONIAL
+BARONY/M/S
+BAROQUE/P
+BARRACK/S
+BARRAGE/M/S
+BARRED
+BARREL/M/S/D/G
+BARRELLED
+BARRELLING
+BARREN/P
+BARRICADE/M/S
+BARRIER/M/S
+BARRING/R
+BARROW
+BARTENDER/M/S
+BARTER/D/G/S
+BAS
+BASAL
+BASALT
+BASE/P/D/R/G/Y/S
+BASEBALL/M/S
+BASEBOARD/M/S
+BASELESS
+BASELINE/M/S
+BASEMAN
+BASEMENT/M/S
+BASH/D/G/S
+BASHFUL/P
+BASIC/S
+BASICALLY
+BASIL
+BASIN/M/S
+BASIS
+BASK/D/G
+BASKET/M/S
+BASKETBALL/M/S
+BASS/M/S
+BASSET
+BASSINET/M/S
+BASSO
+BASTARD/M/S
+BASTE/D/G/N/X/S
+BASTION'S
+BAT/M/S
+BATCH/D/S
+BATH
+BATHE/D/R/Z/G/S
+BATHOS
+BATHROBE/M/S
+BATHROOM/M/S
+BATHS
+BATHTUB/M/S
+BATON/M/S
+BATTALION/M/S
+BATTED
+BATTEN/S
+BATTER/D/G/S
+BATTERY/M/S
+BATTING
+BATTLE/D/R/Z/G/S
+BATTLEFIELD/M/S
+BATTLEFRONT/M/S
+BATTLEGROUND/M/S
+BATTLEMENT/M/S
+BATTLESHIP/M/S
+BAUBLE/M/S
+BAUD
+BAUXITE
+BAWDY
+BAWL/D/G/S
+BAY/D/G/S
+BAYONET/M/S
+BAYOU/M/S
+BAZAAR/M/S
+BE/D/G/Y
+BEACH/D/G/S
+BEACHHEAD/M/S
+BEACON/M/S
+BEAD/D/G/S
+BEADLE/M/S
+BEADY
+BEAGLE/M/S
+BEAK/D/R/Z/S
+BEAM/D/R/Z/G/S
+BEAN/D/R/Z/G/S
+BEAR/R/Z/G/J/S
+BEARABLE
+BEARABLY
+BEARD/D/S
+BEARDLESS
+BEARISH
+BEAST/Y/S
+BEAT/R/Z/G/N/J/S
+BEATABLE
+BEATABLY
+BEATIFIC
+BEATIFY/N
+BEATITUDE/M/S
+BEATNIK/M/S
+BEAU/M/S
+BEAUTEOUS/Y
+BEAUTIFUL/Y
+BEAUTIFY/D/R/Z/G/X/S
+BEAUTY/M/S
+BEAVER/M/S
+BECALM/D/G/S
+BECAME
+BECAUSE
+BECK
+BECKON/D/G/S
+BECOME/G/S
+BECOMINGLY
+BED/M/S
+BEDAZZLE/D/G/S
+BEDAZZLEMENT
+BEDBUG/M/S
+BEDDED
+BEDDER/M/S
+BEDDING
+BEDEVIL/D/G/S
+BEDFAST
+BEDLAM
+BEDPOST/M/S
+BEDRAGGLE/D
+BEDRIDDEN
+BEDROCK/M
+BEDROOM/M/S
+BEDSIDE
+BEDSPREAD/M/S
+BEDSPRING/M/S
+BEDSTEAD/M/S
+BEDTIME
+BEE/R/Z/G/J/S
+BEECH/R/N
+BEEF/D/R/Z/G/S
+BEEFSTEAK
+BEEFY
+BEEHIVE/M/S
+BEEN
+BEEP/S
+BEET/M/S
+BEETHOVEN
+BEETLE/D/M/G/S
+BEFALL/G/N/S
+BEFELL
+BEFIT/M/S
+BEFITTED
+BEFITTING
+BEFOG
+BEFOGGED
+BEFOGGING
+BEFORE
+BEFOREHAND
+BEFOUL/D/G/S
+BEFRIEND/D/G/S
+BEFUDDLE/D/G/S
+BEG/S
+BEGAN
+BEGET/S
+BEGETTING
+BEGGAR/Y/S
+BEGGARY
+BEGGED
+BEGGING
+BEGIN/S
+BEGINNER/M/S
+BEGINNING/M/S
+BEGOT
+BEGOTTEN
+BEGRUDGE/D/G/S
+BEGRUDGINGLY
+BEGUILE/D/G/S
+BEGUN
+BEHALF
+BEHAVE/D/G/S
+BEHAVIOR/S
+BEHAVIORAL/Y
+BEHAVIORISM
+BEHAVIORISTIC
+BEHEAD/G
+BEHELD
+BEHEST
+BEHIND
+BEHOLD/R/Z/G/N/S
+BEHOOVE/S
+BEIGE
+BEIJING
+BELABOR/D/G/S
+BELATED/Y
+BELAY/D/G/S
+BELCH/D/G/S
+BELFRY/M/S
+BELGIAN/M/S
+BELGIUM
+BELIE/D/S
+BELIEF/M/S
+BELIEVABLE
+BELIEVABLY
+BELIEVE/D/R/Z/G/S
+BELITTLE/D/G/S
+BELL/M/S
+BELLBOY/M/S
+BELLE/M/S
+BELLHOP/M/S
+BELLICOSE
+BELLICOSITY
+BELLIGERENCE
+BELLIGERENT/M/Y/S
+BELLMAN
+BELLMEN
+BELLOW/D/G/S
+BELLWETHER/M/S
+BELLY/M/S
+BELLYFUL
+BELONG/D/G/J/S
+BELOVED
+BELOW
+BELT/D/G/S
+BELYING
+BEMOAN/D/G/S
+BENCH/D/S
+BENCHMARK/M/S
+BEND/R/Z/G/S
+BENDABLE
+BENEATH
+BENEDICT
+BENEDICTINE
+BENEDICTION/M/S
+BENEFACTOR/M/S
+BENEFICENCE/S
+BENEFICIAL/Y
+BENEFICIARY/S
+BENEFIT/D/G/S
+BENEFITTED
+BENEFITTING
+BENEVOLENCE
+BENEVOLENT
+BENGAL
+BENGALI
+BENIGHTED
+BENIGN/Y
+BENT
+BENZEDRINE
+BENZENE
+BEQUEATH/D/G/S
+BEQUEST/M/S
+BERATE/D/G/S
+BEREAVE/D/G/S
+BEREAVEMENT/S
+BEREFT
+BERET/M/S
+BERIBBONED
+BERIBERI
+BERKELEY
+BERKELIUM
+BERLIN/R/Z
+BERMUDA
+BERRY/M/S
+BERTH
+BERTHS
+BERYL
+BERYLLIUM
+BESEECH/G/S
+BESET/S
+BESETTING
+BESIDE/S
+BESIEGE/D/R/Z/G
+BESMIRCH/D/G/S
+BESOTTED
+BESOTTER
+BESOTTING
+BESOUGHT
+BESPEAK/S
+BESPECTACLED
+BESSEL
+BEST/D/G/S
+BESTIAL
+BESTOW/D
+BESTOWAL
+BESTSELLER/M/S
+BESTSELLING
+BET/M/S
+BETA
+BETHESDA
+BETIDE
+BETRAY/D/R/G/S
+BETRAYAL
+BETROTH/D
+BETROTHAL
+BETTER/D/G/S
+BETTERMENT/S
+BETTING
+BETWEEN
+BETWIXT
+BEVEL/D/G/S
+BEVERAGE/M/S
+BEVY
+BEWAIL/D/G/S
+BEWARE
+BEWHISKERED
+BEWILDER/D/G/S
+BEWILDERINGLY
+BEWILDERMENT
+BEWITCH/D/G/S
+BEYOND
+BEZIER
+BIANNUAL
+BIAS/D/G/S
+BIB/M/S
+BIBBED
+BIBBING
+BIBLE/M/S
+BIBLICAL/Y
+BIBLIOGRAPHIC
+BIBLIOGRAPHICAL
+BIBLIOGRAPHY/M/S
+BIBLIOPHILE
+BICAMERAL
+BICARBONATE
+BICENTENNIAL
+BICEP/M/S
+BICKER/D/G/S
+BICONCAVE
+BICONVEX
+BICYCLE/D/R/Z/G/S
+BID/M/S
+BIDDABLE
+BIDDEN
+BIDDER/M/S
+BIDDING
+BIDDY/S
+BIDE
+BIDIRECTIONAL
+BIENNIAL
+BIENNIUM
+BIFOCAL/S
+BIG/P
+BIGGER
+BIGGEST
+BIGHT/M/S
+BIGNUM
+BIGOT/D/M/S
+BIGOTRY
+BIJECTION/M/S
+BIJECTIVE/Y
+BIKE/M/G/S
+BIKINI/M/S
+BILABIAL
+BILATERAL/Y
+BILE
+BILGE/M/S
+BILINEAR
+BILINGUAL
+BILK/D/G/S
+BILL/D/R/Z/G/J/S/M
+BILLBOARD/M/S
+BILLET/D/G/S
+BILLIARD/S
+BILLION/H/S
+BILLOW/D/S
+BIMODAL
+BIMOLECULAR
+BIMONTHLY/S
+BIN/M/S
+BINARY
+BINAURAL
+BIND/R/Z/G/J/S
+BINGE/S
+BINGO
+BINOCULAR/S
+BINOMIAL
+BINUCLEAR
+BIOCHEMICAL
+BIOCHEMISTRY
+BIOFEEDBACK
+BIOGRAPHER/M/S
+BIOGRAPHIC
+BIOGRAPHICAL/Y
+BIOGRAPHY/M/S
+BIOLOGICAL/Y
+BIOLOGIST/M/S
+BIOLOGY
+BIOMEDICAL
+BIOMEDICINE
+BIOPHYSICAL
+BIOPHYSICS
+BIOPSY/S
+BIOTECHNOLOGY
+BIPARTISAN
+BIPARTITE
+BIPED/S
+BIPLANE/M/S
+BIPOLAR
+BIRACIAL
+BIRCH/N/S
+BIRD/M/S
+BIRDBATH/M
+BIRDBATHS
+BIRDIE/D/S
+BIRDLIKE
+BIREFRINGENCE
+BIREFRINGENT
+BIRMINGHAM
+BIRTH/D
+BIRTHDAY/M/S
+BIRTHPLACE/S
+BIRTHRIGHT/M/S
+BIRTHS
+BISCUIT/M/S
+BISECT/D/G/S
+BISECTION/M/S
+BISECTOR/M/S
+BISHOP/M/S
+BISMUTH
+BISON/M/S
+BISQUE/S
+BIT/M/S
+BITCH/M/S
+BITE/G/R/S/Z
+BITINGLY
+BITMAP/S
+BITMAPPED
+BITTEN
+BITTER/P/T/R/Y/S
+BITTERSWEET
+BITUMINOUS
+BITWISE
+BIVALVE/M/S
+BIVARIATE
+BIVOUAC/S
+BIWEEKLY
+BIZARRE
+BLAB/S
+BLABBED
+BLABBERMOUTH
+BLABBERMOUTHS
+BLABBING
+BLACK/P/D/T/R/G/N/X/Y/S
+BLACKBERRY/M/S
+BLACKBIRD/M/S
+BLACKBOARD/M/S
+BLACKENED
+BLACKENING
+BLACKJACK/M/S
+BLACKLIST/D/G/S
+BLACKMAIL/D/R/Z/G/S
+BLACKOUT/M/S
+BLACKSMITH
+BLACKSMITHS
+BLADDER/M/S
+BLADE/M/S
+BLAINE
+BLAMABLE
+BLAME/D/R/Z/G/S
+BLAMELESS/P
+BLANCH/D/G/S
+BLAND/P/Y
+BLANK/P/D/T/R/G/Y/S
+BLANKET/D/R/Z/G/S
+BLARE/D/G/S
+BLASE
+BLASPHEME/D/G/S
+BLASPHEMOUS/P/Y
+BLASPHEMY/S
+BLAST/D/R/Z/G/S
+BLATANT/Y
+BLAZE/D/R/Z/G/S
+BLEACH/D/R/Z/G/S
+BLEAK/P/Y
+BLEAR
+BLEARY
+BLEAT/G/S
+BLED
+BLEED/R/G/J/S
+BLEMISH/M/S
+BLEND/D/G/S
+BLESS/D/G/J
+BLEW
+BLIGHT/D
+BLIMP/M/S
+BLIND/P/D/R/Z/G/Y/S
+BLINDFOLD/D/G/S
+BLINDINGLY
+BLINK/D/R/Z/G/S
+BLIP/M/S
+BLISS
+BLISSFUL/Y
+BLISTER/D/G/S
+BLITHE/Y
+BLITZ/M/S
+BLITZKRIEG
+BLIZZARD/M/S
+BLOAT/D/R/G/S
+BLOB/M/S
+BLOC/M/S
+BLOCK'S
+BLOCK/D/R/Z/G/S
+BLOCKADE/D/G/S
+BLOCKAGE/M/S
+BLOCKHOUSE/S
+BLOKE/M/S
+BLOND/M/S
+BLONDE/M/S
+BLOOD/D/S
+BLOODHOUND/M/S
+BLOODLESS
+BLOODSHED
+BLOODSHOT
+BLOODSTAIN/D/M/S
+BLOODSTREAM
+BLOODY/D/T
+BLOOM/D/Z/G/S
+BLOSSOM/D/S
+BLOT/M/S
+BLOTTED
+BLOTTING
+BLOUSE/M/S
+BLOW/R/Z/G/S
+BLOWFISH
+BLOWN
+BLOWUP
+BLUBBER
+BLUDGEON/D/G/S
+BLUE/P/T/R/G/S
+BLUEBERRY/M/S
+BLUEBIRD/M/S
+BLUEBONNET/M/S
+BLUEFISH
+BLUEPRINT/M/S
+BLUESTOCKING
+BLUFF/G/S
+BLUISH
+BLUNDER/D/G/J/S
+BLUNT/P/D/T/R/G/Y/S
+BLUR/M/S
+BLURB
+BLURRED
+BLURRING
+BLURRY
+BLURT/D/G/S
+BLUSH/D/G/S
+BLUSTER/D/G/S
+BLUSTERY
+BOAR
+BOARD/D/R/Z/G/S
+BOARDINGHOUSE/M/S
+BOAST/D/R/Z/G/J/S
+BOASTFUL/Y
+BOAT/R/Z/G/S
+BOATHOUSE/M/S
+BOATLOAD/M/S
+BOATMAN
+BOATMEN
+BOATSMAN
+BOATSMEN
+BOATSWAIN/M/S
+BOATYARD/M/S
+BOB/M/S
+BOBBED
+BOBBIN/M/S
+BOBBING
+BOBBY
+BOBOLINK/M/S
+BOBWHITE/M/S
+BODE/S
+BODICE
+BODILY
+BODONI
+BODY/D/S
+BODYBUILDER/M/S
+BODYBUILDING
+BODYGUARD/M/S
+BODYWEIGHT
+BOG/M/S
+BOGGED
+BOGGLE/D/G/S
+BOGUS
+BOIL/D/R/Z/G/S
+BOILERPLATE
+BOISTEROUS/Y
+BOLD/P/T/R/Y
+BOLDFACE
+BOLIVIA
+BOLL
+BOLOGNA
+BOLSHEVIK/M/S
+BOLSHEVISM
+BOLSTER/D/G/S
+BOLT/D/G/S
+BOLTZMANN
+BOMB/D/R/Z/G/J/S
+BOMBARD/D/G/S
+BOMBARDMENT
+BOMBAST
+BOMBASTIC
+BOMBPROOF
+BONANZA/M/S
+BOND/D/R/Z/G/S
+BONDAGE
+BONDSMAN
+BONDSMEN
+BONE/D/R/Z/G/S
+BONFIRE/M/S
+BONG
+BONNET/D/S
+BONNY
+BONUS/M/S
+BONY
+BOO/H/S
+BOOB
+BOOBOO
+BOOBY
+BOOK/D/R/Z/G/J/S
+BOOKCASE/M/S
+BOOKIE/M/S
+BOOKISH
+BOOKKEEPER/M/S
+BOOKKEEPING
+BOOKLET/M/S
+BOOKSELLER/M/S
+BOOKSHELF/M
+BOOKSHELVES
+BOOKSTORE/M/S
+BOOLEAN
+BOOM/D/G/S
+BOOMERANG/M/S
+BOOMTOWN/M/S
+BOON
+BOOR/M/S
+BOORISH
+BOOST/D/R/G/S
+BOOT/D/G/S
+BOOTHS
+BOOTLEG/S
+BOOTLEGGED
+BOOTLEGGER/M/S
+BOOTLEGGING
+BOOTSTRAP/M/S
+BOOTSTRAPPED
+BOOTSTRAPPING
+BOOTY
+BOOZE
+BORATE/S
+BORAX
+BORDELLO/M/S
+BORDER/D/G/J/S
+BORDERLAND/M/S
+BORDERLINE
+BORE/D/R/G/S
+BOREDOM
+BORIC
+BORN
+BORNE
+BORNEO
+BORON
+BOROUGH
+BOROUGHS
+BORROW/D/R/Z/G/S
+BOSOM/M/S
+BOSS/D/S
+BOSTON
+BOSTONIAN/M/S
+BOSUN
+BOTANICAL
+BOTANIST/M/S
+BOTANY
+BOTCH/D/R/Z/G/S
+BOTH/Z
+BOTHER/D/G/S
+BOTHERSOME
+BOTSWANA
+BOTTLE/D/R/Z/G/S
+BOTTLENECK/M/S
+BOTTOM/D/G/S
+BOTTOMLESS
+BOTULINUS
+BOTULISM
+BOUFFANT
+BOUGH/M
+BOUGHS
+BOUGHT
+BOULDER/M/S
+BOULEVARD/M/S
+BOUNCE/D/R/G/S
+BOUNCY
+BOUND/D/G/N/S
+BOUNDARY/M/S
+BOUNDLESS/P
+BOUNTEOUS/Y
+BOUNTY/M/S
+BOUQUET/M/S
+BOURBON
+BOURGEOIS
+BOURGEOISIE
+BOUT/M/S
+BOVINE/S
+BOW/D/R/Z/G/S
+BOWDLERIZE/D/G/S
+BOWEL/M/S
+BOWL/D/R/Z/G/S
+BOWLINE/M/S
+BOWMAN
+BOWSTRING/M/S
+BOX/D/R/Z/G/S
+BOXCAR/M/S
+BOXTOP/M/S
+BOXWOOD
+BOY/M/S
+BOYCOTT/D/S
+BOYFRIEND/M/S
+BOYHOOD
+BOYISH/P
+BRA/M/S
+BRACE/D/G/S
+BRACELET/M/S
+BRACKET/D/G/S
+BRACKISH
+BRAD/M
+BRAE/M/S
+BRAG/S
+BRAGGED
+BRAGGER
+BRAGGING
+BRAID/D/G/S
+BRAILLE
+BRAIN/D/G/S
+BRAINCHILD/M
+BRAINSTEM/M/S
+BRAINSTORM/M/S
+BRAINWASH/D/G/S
+BRAINY
+BRAKE/D/G/S
+BRAMBLE/M/S
+BRAMBLY
+BRAN
+BRANCH/D/G/J/S
+BRAND/D/G/S
+BRANDISH/G/S
+BRANDY
+BRASH/P/Y
+BRASS/S
+BRASSIERE
+BRASSY
+BRAT/M/S
+BRAVADO
+BRAVE/P/D/T/R/G/Y/S
+BRAVERY
+BRAVO/S
+BRAVURA
+BRAWL/R/G
+BRAWN
+BRAY/D/R/G/S
+BRAZE/D/G/S
+BRAZEN/P/Y
+BRAZIER/M/S
+BRAZIL
+BRAZILIAN
+BREACH/D/R/Z/G/S
+BREAD/D/G/H/S
+BREADBOARD/M/S
+BREADBOX/M/S
+BREADWINNER/M/S
+BREAK/R/Z/G/S
+BREAKABLE/S
+BREAKAGE
+BREAKAWAY
+BREAKDOWN/M/S
+BREAKFAST/D/R/Z/G/S
+BREAKPOINT/M/S
+BREAKTHROUGH/M/S
+BREAKTHROUGHS
+BREAKUP
+BREAKWATER/M/S
+BREAST/D/S
+BREASTWORK/M/S
+BREATH
+BREATHABLE
+BREATHE/D/R/Z/G/S
+BREATHLESS/Y
+BREATHS
+BREATHTAKING/Y
+BREATHY
+BRED
+BREECH/M/S
+BREED/R/G/S
+BREEZE/M/S
+BREEZILY
+BREEZY
+BREMSSTRAHLUNG
+BRETHREN
+BREVE
+BREVET/D/G/S
+BREVITY
+BREW/D/R/Z/G/S
+BREWERY/M/S
+BRIAN/M
+BRIAR/M/S
+BRIBE/D/R/Z/G/S
+BRICK/D/R/S
+BRICKLAYER/M/S
+BRICKLAYING
+BRIDAL
+BRIDE/M/S
+BRIDEGROOM
+BRIDESMAID/M/S
+BRIDGE/D/G/S
+BRIDGEABLE
+BRIDGEHEAD/M/S
+BRIDGEWORK/M
+BRIDLE/D/G/S
+BRIEF/P/D/T/R/Y/S
+BRIEFCASE/M/S
+BRIEFING/M/S
+BRIER
+BRIG/M/S
+BRIGADE/M/S
+BRIGADIER/M/S
+BRIGANTINE
+BRIGHT/P/T/R/X/Y
+BRIGHTEN/D/R/Z/G/S
+BRILLIANCE
+BRILLIANCY
+BRILLIANT/Y
+BRIM
+BRIMFUL
+BRIMMED
+BRINDLE/D
+BRINE
+BRING/G/R/S/Z
+BRINK
+BRINKMANSHIP
+BRISK/P/R/Y
+BRISTLE/D/G/S
+BRITAIN
+BRITCHES
+BRITISH/R
+BRITON/M/S
+BRITTLE/P
+BROACH/D/G/S
+BROAD/P/T/R/X/Y
+BROADBAND
+BROADCAST/R/Z/G/J/S
+BROADEN/D/R/Z/G/J/S
+BROADSIDE
+BROCADE/D
+BROCCOLI
+BROCHURE/M/S
+BROIL/D/R/Z/G/S
+BROKE/R/Z
+BROKEN/P/Y
+BROKERAGE
+BROMIDE/M/S
+BROMINE
+BRONCHI
+BRONCHIAL
+BRONCHIOLE/M/S
+BRONCHITIS
+BRONCHUS
+BRONZE/D/S
+BROOCH/M/S
+BROOD/R/G/S
+BROOK/D/S
+BROOKHAVEN
+BROOM/M/S
+BROOMSTICK/M/S
+BROTH/R/Z
+BROTHEL/M/S
+BROTHER'S
+BROTHERHOOD
+BROTHERLY/P
+BROUGHT
+BROW/M/S
+BROWBEAT/G/N/S
+BROWN/P/D/T/R/G/S
+BROWNIE/M/S
+BROWNISH
+BROWSE/G
+BROWSER/S
+BRUCE/M
+BRUISE/D/G/S
+BRUNCH/S
+BRUNETTE
+BRUNT
+BRUSH/D/G/S
+BRUSHFIRE/M/S
+BRUSHLIKE
+BRUSHY
+BRUSQUE/Y
+BRUTAL/Y
+BRUTALITY/S
+BRUTALIZE/D/G/S
+BRUTE/M/S
+BRUTISH
+BSD
+BUBBLE/D/G/S
+BUBBLY
+BUCK/D/G/S
+BUCKBOARD/M/S
+BUCKET/M/S
+BUCKLE/D/R/G/S
+BUCKSHOT
+BUCKSKIN/S
+BUCKWHEAT
+BUCOLIC
+BUD/M/S
+BUDDED
+BUDDING
+BUDDY/M/S
+BUDGE/D/G/S
+BUDGET/D/R/Z/G/S
+BUDGETARY
+BUFF/M/S
+BUFFALO
+BUFFALOES
+BUFFER/D/M/G/S
+BUFFERER/M/S
+BUFFET/D/G/J/S
+BUFFOON/M/S
+BUG/M/S
+BUGGED
+BUGGER/M/S
+BUGGING
+BUGGY/M/S
+BUGLE/D/R/G/S
+BUILD/R/Z/G/J/S
+BUILDUP/M/S
+BUILT
+BULB/M/S
+BULGE/D/G
+BULK/D/S
+BULKHEAD/M/S
+BULKY
+BULL/D/G/S
+BULLDOG/M/S
+BULLDOZE/D/R/G/S
+BULLET/M/S
+BULLETIN/M/S
+BULLION
+BULLISH
+BULLY/D/G/S
+BULWARK
+BUM/M/S
+BUMBLE/D/R/Z/G/S
+BUMBLEBEE/M/S
+BUMMED
+BUMMING
+BUMP/D/R/Z/G/S
+BUMPTIOUS/P/Y
+BUN/M/S
+BUNCH/D/G/S
+BUNDLE/D/G/S
+BUNGALOW/M/S
+BUNGLE/D/R/Z/G/S
+BUNION/M/S
+BUNK/R/Z/S
+BUNKER'S
+BUNKERED
+BUNKHOUSE/M/S
+BUNKMATE/M/S
+BUNNY/M/S
+BUNT/D/R/Z/G/S
+BUOY/D/S
+BUOYANCY
+BUOYANT
+BURDEN/D/G/S
+BURDENSOME
+BUREAU/M/S
+BUREAUCRACY/M/S
+BUREAUCRAT/M/S
+BUREAUCRATIC
+BURGEON/D/G
+BURGESS/M/S
+BURGHER/M/S
+BURGLAR/M/S
+BURGLARIZE/D/G/S
+BURGLARPROOF/D/G/S
+BURGLARY/M/S
+BURIAL
+BURL
+BURLESQUE/S
+BURLY
+BURN/D/R/Z/G/J/S
+BURNINGLY
+BURNISH/D/G/S
+BURNT/P/Y
+BURP/D/G/S
+BURR/M/S
+BURRO/M/S
+BURROW/D/R/G/S
+BURSA
+BURSITIS
+BURST/G/S
+BURY/D/G/S
+BUS/D/G/S
+BUSBOY/M/S
+BUSH/G/S
+BUSHEL/M/S
+BUSHWHACK/D/G/S
+BUSHY
+BUSILY
+BUSINESS/M/S
+BUSINESSLIKE
+BUSINESSMAN
+BUSINESSMEN
+BUSS/D/G/S
+BUST/D/R/S
+BUSTARD/M/S
+BUSTLE/G
+BUSY/D/T/R
+BUT
+BUTANE
+BUTCHER/D/S
+BUTCHERY
+BUTLER/M/S
+BUTT/M/S
+BUTTE/D/Z/G/S
+BUTTER/D/R/Z/G
+BUTTERFAT
+BUTTERFLY/M/S
+BUTTERNUT
+BUTTOCK/M/S
+BUTTON/D/G/S
+BUTTONHOLE/M/S
+BUTTRESS/D/G/S
+BUTYL
+BUTYRATE
+BUXOM
+BUY/G/S
+BUYER/M/S
+BUZZ/D/R/G/S
+BUZZARD/M/S
+BUZZWORD/M/S
+BUZZY
+BY/R
+BYE
+BYGONE
+BYLAW/M/S
+BYLINE/M/S
+BYPASS/D/G/S
+BYPRODUCT/M/S
+BYSTANDER/M/S
+BYTE/M/S
+BYWAY/S
+BYWORD/M/S
+CAB/M/S
+CABBAGE/M/S
+CABIN/M/S
+CABINET/M/S
+CABLE/D/G/S
+CACHE/M/S/G/D
+CACKLE/D/R/G/S
+CACTI
+CACTUS
+CADENCE/D
+CADUCEUS
+CAFE/M/S
+CAGE/D/R/Z/G/S
+CAJOLE/D/G/S
+CAKE/D/G/S
+CALAMITY/M/S
+CALCIUM
+CALCULATE/D/G/N/X/V/S
+CALCULATOR/M/S
+CALCULUS
+CALENDAR/M/S
+CALF
+CALIBER/S
+CALIBRATE/D/G/N/X/S
+CALICO
+CALIFORNIA
+CALIPH
+CALIPHS
+CALL/D/R/Z/G/S
+CALLIGRAPHY
+CALLOUS/P/D/Y
+CALM/P/D/T/R/G/Y/S
+CALMINGLY
+CALORIE/M/S
+CALVES
+CAMBRIDGE
+CAME
+CAMEL/M/S
+CAMERA/M/S
+CAMOUFLAGE/D/G/S
+CAMP/D/R/Z/G/S
+CAMPAIGN/D/R/Z/G/S
+CAMPUS/M/S
+CAN'T
+CAN/M/S
+CANADA
+CANAL/M/S
+CANARY/M/S
+CANCEL/D/G/S
+CANCELLATION/M/S
+CANCER/M/S
+CANDID/P/Y
+CANDIDATE/M/S
+CANDLE/R/S
+CANDLESTICK/M/S
+CANDOR
+CANDY/D/S
+CANE/R
+CANINE
+CANKER
+CANNED
+CANNER/M/S
+CANNIBAL/M/S
+CANNIBALIZE/D/G/S
+CANNING
+CANNISTER/M/S
+CANNON/M/S
+CANNOT
+CANOE/M/S
+CANON/M/S
+CANONICAL/Y/S
+CANONICALIZATION
+CANONICALIZE/D/G/S
+CANOPY
+CANTANKEROUS/Y
+CANTO
+CANTON/M/S
+CANTOR/M/S
+CANVAS/M/S
+CANVASS/D/R/Z/G/S
+CANYON/M/S
+CAP/M/S
+CAPABILITY/M/S
+CAPABLE
+CAPABLY
+CAPACIOUS/P/Y
+CAPACITANCE/S
+CAPACITIVE
+CAPACITOR/M/S
+CAPACITY/S
+CAPE/R/Z/S
+CAPILLARY
+CAPITA
+CAPITAL/Y/S
+CAPITALISM
+CAPITALIST/M/S
+CAPITALIZATION/S
+CAPITALIZE/D/R/Z/G/S
+CAPITOL/M/S
+CAPPED
+CAPPING
+CAPRICIOUS/P/Y
+CAPTAIN/D/G/S
+CAPTION/M/S
+CAPTIVATE/D/G/N/S
+CAPTIVE/M/S
+CAPTIVITY
+CAPTOR/M/S
+CAPTURE/D/R/Z/G/S
+CAR/M/S
+CARAVAN/M/S
+CARBOHYDRATE
+CARBOLIC
+CARBON/M/S
+CARBONATE/N/S
+CARBONIC
+CARBONIZATION
+CARBONIZE/D/R/Z/G/S
+CARCASS/M/S
+CARCINOMA
+CARD/R/S
+CARDBOARD
+CARDIAC
+CARDINAL/Y/S
+CARDINALITY/M/S
+CARDIOLOGY
+CARDIOPULMONARY
+CARE/D/G/S
+CAREER/M/S
+CAREFREE
+CAREFUL/P/Y
+CARELESS/P/Y
+CARESS/D/R/G/S
+CARET
+CARGO
+CARGOES
+CARIBOU
+CARNEGIE
+CARNIVAL/M/S
+CARNIVOROUS/Y
+CAROL/M/S
+CAROLINA/M/S
+CARPENTER/M/S
+CARPET/D/G/S
+CARRIAGE/M/S
+CARROT/M/S
+CARRY/D/R/Z/G/S
+CARRYOVER/S
+CART/D/R/Z/G/S
+CARTESIAN
+CARTOGRAPHIC
+CARTOGRAPHY
+CARTON/M/S
+CARTOON/M/S
+CARTRIDGE/M/S
+CARVE/D/R/G/J/S
+CASCADE/D/G/S
+CASE/D/G/J/S
+CASEMENT/M/S
+CASH/D/R/Z/G/S
+CASHIER/M/S
+CASK/M/S
+CASKET/M/S
+CASSEROLE/M/S
+CAST/G/M/S
+CASTE/R/S/Z
+CASTLE/D/S
+CASUAL/P/Y/S
+CASUALTY/M/S
+CAT/M/S
+CATALOG/D/R/G/S
+CATALOGUE/D/S
+CATALYST/M/S
+CATARACT
+CATASTROPHE
+CATASTROPHIC
+CATCH/G/R/S/Z
+CATCHABLE
+CATEGORICAL/Y
+CATEGORIZATION
+CATEGORIZE/D/R/Z/G/S
+CATEGORY/M/S
+CATER/D/R/G/S
+CATERPILLAR/M/S
+CATHEDRAL/M/S
+CATHERINE/M
+CATHETER/S
+CATHODE/M/S
+CATHOLIC/M/S
+CATSUP
+CATTLE
+CAUGHT
+CAUSAL/Y
+CAUSALITY
+CAUSATION/M/S
+CAUSE/D/R/G/S
+CAUSEWAY/M/S
+CAUSTIC/Y/S
+CAUTION/D/R/Z/G/J/S
+CAUTIOUS/P/Y
+CAVALIER/P/Y
+CAVALRY
+CAVE/D/G/S
+CAVEAT/M/S
+CAVERN/M/S
+CAVITY/M/S
+CAW/G
+CDR
+CEASE/D/G/S
+CEASELESS/P/Y
+CEDAR
+CEILING/M/S
+CELEBRATE/D/G/N/X/S
+CELEBRITY/M/S
+CELERY
+CELESTIAL/Y
+CELL/D/S
+CELLAR/M/S
+CELLIST/M/S
+CELLULAR
+CELSIUS
+CEMENT/D/G/S
+CEMETERY/M/S
+CENSOR/D/G/S
+CENSORSHIP
+CENSURE/D/R/S
+CENSUS/M/S
+CENT/Z/S
+CENTER/D/G/S
+CENTERPIECE/M/S
+CENTIMETER/S
+CENTIPEDE/M/S
+CENTRAL/Y
+CENTRALIZATION
+CENTRALIZE/D/G/S
+CENTRIPETAL
+CENTURY/M/S
+CEREAL/M/S
+CEREBRAL
+CEREMONIAL/P/Y
+CEREMONY/M/S
+CERTAIN/Y
+CERTAINTY/S
+CERTIFIABLE
+CERTIFICATE/N/X/S
+CERTIFY/D/R/Z/G/N/S
+CESSATION/M/S
+CHAFE/R/G
+CHAFF/R/G
+CHAGRIN
+CHAIN/D/G/S
+CHAIR/D/G/S
+CHAIRMAN
+CHAIRMEN
+CHAIRPERSON/M/S
+CHALICE/M/S
+CHALK/D/G/S
+CHALLENGE/D/R/Z/G/S
+CHAMBER/D/S
+CHAMBERLAIN/M/S
+CHAMPAGNE
+CHAMPAIGN
+CHAMPION/D/G/S
+CHAMPIONSHIP/M/S
+CHANCE/D/G/S
+CHANCELLOR
+CHANDELIER/M/S
+CHANGE/D/R/Z/G/S
+CHANGEABILITY
+CHANGEABLE
+CHANGEABLY
+CHANNEL/D/G/S
+CHANNELLED
+CHANNELLER/M/S
+CHANNELLING
+CHANT/D/R/G/S
+CHANTICLEER/M/S
+CHAOS
+CHAOTIC
+CHAP/M/S
+CHAPEL/M/S
+CHAPERON/D
+CHAPLAIN/M/S
+CHAPTER/M/S
+CHAR/S
+CHARACTER/M/S
+CHARACTERISTIC/M/S
+CHARACTERISTICALLY
+CHARACTERIZABLE
+CHARACTERIZATION/M/S
+CHARACTERIZE/D/R/Z/G/S
+CHARCOAL/D
+CHARGE/D/R/Z/G/S
+CHARGEABLE
+CHARIOT/M/S
+CHARISMA
+CHARISMATIC
+CHARITABLE/P
+CHARITY/M/S
+CHARLES
+CHARM/D/R/Z/G/S
+CHARMINGLY
+CHART/D/R/Z/G/J/S
+CHARTABLE
+CHARTERED
+CHARTERING
+CHASE/D/R/Z/G/S
+CHASM/M/S
+CHASTE/P/Y
+CHASTISE/D/R/Z/G/S
+CHAT
+CHATEAU/M/S
+CHATTER/D/R/G/S/Z
+CHAUFFEUR/D
+CHEAP/P/T/R/X/Y
+CHEAPEN/D/G/S
+CHEAT/D/R/Z/G/S
+CHECK/D/R/Z/G/S
+CHECKABLE
+CHECKBOOK/M/S
+CHECKOUT
+CHECKPOINT/M/S
+CHECKSUM/M/S
+CHEEK/M/S
+CHEER/D/R/G/S
+CHEERFUL/P/Y
+CHEERILY
+CHEERLESS/P/Y
+CHEERY/P
+CHEESE/M/S
+CHEF/M/S
+CHEMICAL/Y/S
+CHEMISE
+CHEMIST/M/S
+CHEMISTRY/S
+CHERISH/D/G/S
+CHERRY/M/S
+CHERUB/M/S
+CHERUBIM
+CHESS
+CHEST/R/S
+CHESTNUT/M/S
+CHEW/D/R/Z/G/S
+CHICK/N/X/S
+CHICKADEE/M/S
+CHIDE/D/G/S
+CHIEF/Y/S
+CHIEFTAIN/M/S
+CHIFFON
+CHILD
+CHILDHOOD
+CHILDISH/P/Y
+CHILDREN
+CHILES
+CHILL/D/R/Z/G/S
+CHILLINGLY
+CHILLY/P/R
+CHIME/M/S
+CHIMNEY/M/S
+CHIN/M/S
+CHINA
+CHINESE
+CHINK/D/S
+CHINNED
+CHINNER/S
+CHINNING
+CHINTZ
+CHIP/M/S
+CHIPMUNK/M/S
+CHIRP/D/G/S
+CHISEL/D/R/S
+CHIVALROUS/P/Y
+CHIVALRY
+CHLORINE
+CHLOROPLAST/M/S
+CHOCK/M/S
+CHOCOLATE/M/S
+CHOICE/T/S
+CHOIR/M/S
+CHOKE/D/R/Z/G/S
+CHOLERA
+CHOOSE/R/Z/G/S
+CHOP/S
+CHOPPED
+CHOPPER/M/S
+CHOPPING
+CHORAL
+CHORD/M/S
+CHORE/G/S
+CHORUS/D/S
+CHOSE
+CHOSEN
+CHRIS
+CHRISTEN/D/G/S
+CHRISTIAN/M/S
+CHRISTMAS
+CHRISTOPHER/M
+CHROMOSOME
+CHRONIC
+CHRONICLE/D/R/Z/S
+CHRONOLOGICAL/Y
+CHRONOLOGY/M/S
+CHUBBY/P/T/R
+CHUCK/M/S
+CHUCKLE/D/S
+CHUM
+CHUNK/G/D/S/M
+CHURCH/Y/S
+CHURCHMAN
+CHURCHYARD/M/S
+CHURN/D/G/S
+CHUTE/M/S
+CIDER
+CIGAR/M/S
+CIGARETTE/M/S
+CINCINNATI
+CINDER/M/S
+CINNAMON
+CIPHER/M/S
+CIRCLE/D/G/S
+CIRCUIT/M/S
+CIRCUITOUS/Y
+CIRCUITRY
+CIRCULAR/Y
+CIRCULARITY/S
+CIRCULATE/D/G/N/S
+CIRCUMFERENCE
+CIRCUMFLEX
+CIRCUMLOCUTION/M/S
+CIRCUMSPECT/Y
+CIRCUMSTANCE/M/S
+CIRCUMSTANTIAL/Y
+CIRCUMVENT/D/G/S
+CIRCUMVENTABLE
+CIRCUS/M/S
+CISTERN/M/S
+CITADEL/M/S
+CITATION/M/S
+CITE/D/G/S
+CITIZEN/M/S
+CITIZENSHIP
+CITY/M/S
+CIVIC/S
+CIVIL/Y
+CIVILIAN/M/S
+CIVILITY
+CIVILIZATION/M/S
+CIVILIZE/D/G/S
+CLAD
+CLAIM/D/G/S
+CLAIMABLE
+CLAIMANT/M/S
+CLAIRVOYANT/Y
+CLAM/M/S
+CLAMBER/D/G/S
+CLAMOR/D/G/S
+CLAMOROUS
+CLAMP/D/G/S
+CLAN
+CLANG/D/G/S
+CLAP/S
+CLARA/M
+CLARIFY/D/G/N/X/S
+CLARITY
+CLASH/D/G/S
+CLASP/D/G/S
+CLASS/D/S
+CLASSIC/S
+CLASSICAL/Y
+CLASSIFIABLE
+CLASSIFY/D/R/Z/G/N/X/S
+CLASSMATE/M/S
+CLASSROOM/M/S
+CLATTER/D/G
+CLAUSE/M/S
+CLAW/D/G/S
+CLAY/M/S
+CLEAN/P/D/T/G/Y/S
+CLEANER/M/S
+CLEANLINESS
+CLEANSE/D/R/Z/G/S
+CLEAR/P/D/T/R/Y/S
+CLEARANCE/M/S
+CLEARING/M/S
+CLEAVAGE
+CLEAVE/D/R/Z/G/S
+CLEFT/M/S
+CLENCH/D/S
+CLERGY
+CLERGYMAN
+CLERICAL
+CLERK/D/G/S
+CLEVER/P/T/R/Y
+CLICHE/M/S
+CLICK/D/G/S
+CLIENT/M/S
+CLIFF/M/S
+CLIMATE/M/S
+CLIMATIC
+CLIMATICALLY
+CLIMAX/D/S
+CLIMB/D/R/Z/G/S
+CLIME/M/S
+CLINCH/D/R/S
+CLING/G/S
+CLINIC/M/S
+CLINICAL/Y
+CLINK/D/R
+CLIP/M/S
+CLIPPED
+CLIPPER/M/S
+CLIPPING/M/S
+CLIQUE/M/S
+CLOAK/M/S
+CLOBBER/D/G/S
+CLOCK/D/R/Z/G/J/S
+CLOCKWISE
+CLOCKWORK
+CLOD/M/S
+CLOG/M/S
+CLOGGED
+CLOGGING
+CLOISTER/M/S
+CLONE/D/G/S
+CLOSE/D/T/G/Y/S
+CLOSENESS/S
+CLOSER/S
+CLOSET/D/S
+CLOSURE/M/S
+CLOT
+CLOTH
+CLOTHE/D/G/S
+CLOUD/D/G/S
+CLOUDLESS
+CLOUDY/P/T/R
+CLOUT
+CLOVE/R/S
+CLOWN/G/S
+CLUB/M/S
+CLUBBED
+CLUBBING
+CLUCK/D/G/S
+CLUE/M/S
+CLUMP/D/G/S
+CLUMSILY
+CLUMSY/P
+CLUNG
+CLUSTER/D/G/J/S
+CLUTCH/D/G/S
+CLUTTER/D/G/S
+CLX
+CLYDE/M
+CMU/M
+COACH/D/R/G/S
+COACHMAN
+COAGULATION
+COAL/S
+COALESCE/D/G/S
+COALITION
+COARSE/P/T/R/Y
+COARSEN/D
+COAST/D/R/Z/G/S
+COASTAL
+COAT/D/G/J/S
+COAX/D/R/G/S
+COBBLER/M/S
+COBOL
+COBWEB/M/S
+COCK/D/G/S
+COCKATOO
+COCKTAIL/M/S
+COCOA
+COCONUT/M/S
+COCOON/M/S
+COD
+CODE/D/R/Z/G/J/S
+CODEWORD/M/S
+CODIFICATION/M/S
+CODIFIER/M/S
+CODIFY/D/G/S
+COEFFICIENT/M/S
+COERCE/D/G/N/V/S
+COEXIST/D/G/S
+COEXISTENCE
+COFFEE/M/S
+COFFER/M/S
+COFFIN/M/S
+COGENT/Y
+COGITATE/D/G/N/S
+COGNITION
+COGNITIVE/Y
+COGNIZANCE
+COGNIZANT
+COHABIT/S
+COHABITATION/S
+COHERE/D/G/S
+COHERENCE
+COHERENT/Y
+COHESION
+COHESIVE/P/Y
+COIL/D/G/S
+COIN/D/R/G/S
+COINAGE
+COINCIDE/D/G/S
+COINCIDENCE/M/S
+COINCIDENTAL
+COKE/S
+COLD/P/T/R/Y/S
+COLLABORATE/D/G/N/X/V/S
+COLLABORATOR/M/S
+COLLAPSE/D/G/S
+COLLAR/D/G/S
+COLLATERAL
+COLLEAGUE/M/S
+COLLECT/D/G/V/S
+COLLECTIBLE
+COLLECTION/M/S
+COLLECTIVE/Y/S
+COLLECTOR/M/S
+COLLEGE/M/S
+COLLEGIATE
+COLLIDE/D/G/S
+COLLIE/R/S
+COLLISION/M/S
+COLLOQUIA
+COLOGNE
+COLON/M/S
+COLONEL/M/S
+COLONIAL/Y/S
+COLONIST/M/S
+COLONIZATION
+COLONIZE/D/R/Z/G/S
+COLONY/M/S
+COLOR/D/R/Z/G/J/S
+COLORADO
+COLORFUL
+COLORLESS
+COLOSSAL
+COLT/M/S
+COLUMBUS
+COLUMN/M/S
+COLUMNAR
+COLUMNIZE/D/G/S
+COMB/D/R/Z/G/J/S
+COMBAT/D/G/V/S
+COMBATANT/M/S
+COMBINATION/M/S
+COMBINATIONAL
+COMBINATOR/M/S
+COMBINATORIAL/Y
+COMBINATORIC/S
+COMBINE/D/G/S
+COMBUSTION
+COME/R/Z/G/Y/J/S
+COMEDIAN/M/S
+COMEDIC
+COMEDY/M/S
+COMELINESS
+COMESTIBLE
+COMET/M/S
+COMFORT/D/R/Z/G/S
+COMFORTABILITY/S
+COMFORTABLE
+COMFORTABLY
+COMFORTINGLY
+COMIC/M/S
+COMICAL/Y
+COMMA/M/S
+COMMAND'S
+COMMAND/D/R/Z/G/S
+COMMANDANT/M/S
+COMMANDINGLY
+COMMANDMENT/M/S
+COMMEMORATE/D/G/N/V/S
+COMMENCE/D/G/S
+COMMENCEMENT/M/S
+COMMEND/D/G/S
+COMMENDABLE
+COMMENDATION/M/S
+COMMENSURATE
+COMMENT/D/G/S
+COMMENTARY/M/S
+COMMENTATOR/M/S
+COMMERCE
+COMMERCIAL/P/Y/S
+COMMISSION/D/R/Z/G/S
+COMMIT/S
+COMMITMENT/M/S
+COMMITTED
+COMMITTEE/M/S
+COMMITTING
+COMMODITY/M/S
+COMMODORE/M/S
+COMMON/P/T/Y/S
+COMMONALITY/S
+COMMONER/M/S
+COMMONPLACE/S
+COMMONWEALTH
+COMMONWEALTHS
+COMMOTION
+COMMUNAL/Y
+COMMUNE/N/S
+COMMUNICANT/M/S
+COMMUNICATE/D/G/N/X/V/S
+COMMUNICATOR/M/S
+COMMUNIST/M/S
+COMMUNITY/M/S
+COMMUTATIVE
+COMMUTATIVITY
+COMMUTE/D/R/Z/G/S
+COMPACT/P/D/T/R/G/Y/S
+COMPACTOR/M/S
+COMPANION/M/S
+COMPANIONABLE
+COMPANIONSHIP
+COMPANY/M/S
+COMPARABILITY
+COMPARABLE
+COMPARABLY
+COMPARATIVE/Y/S
+COMPARATOR/M/S
+COMPARE/D/G/S
+COMPARISON/M/S
+COMPARTMENT/D/S
+COMPARTMENTALIZE/D/G/S
+COMPASS
+COMPASSION
+COMPASSIONATE/Y
+COMPATIBILITY/M/S
+COMPATIBLE
+COMPATIBLY
+COMPEL/S
+COMPELLED
+COMPELLING/Y
+COMPENDIUM
+COMPENSATE/D/G/N/X/S
+COMPENSATORY
+COMPETE/D/G/S
+COMPETENCE
+COMPETENT/Y
+COMPETITION/M/S
+COMPETITIVE/Y
+COMPETITOR/M/S
+COMPILATION/M/S
+COMPILE/D/R/Z/G/S
+COMPILER'S
+COMPLAIN/D/R/Z/G/S
+COMPLAINT/M/S
+COMPLEMENT/D/R/Z/G/S
+COMPLEMENTARY
+COMPLETE/P/D/G/N/X/Y/S
+COMPLEX/Y/S
+COMPLEXION
+COMPLEXITY/S
+COMPLIANCE
+COMPLICATE/D/G/N/X/S
+COMPLICATOR/M/S
+COMPLICITY
+COMPLIMENT/D/R/Z/G/S
+COMPLIMENTARY
+COMPLY/D/G
+COMPONENT/M/S
+COMPONENTWISE
+COMPOSE/D/R/Z/G/S
+COMPOSEDLY
+COMPOSITE/N/X/S
+COMPOSITIONAL
+COMPOSURE
+COMPOUND/D/G/S
+COMPREHEND/D/G/S
+COMPREHENSIBILITY
+COMPREHENSIBLE
+COMPREHENSION
+COMPREHENSIVE/Y
+COMPRESS/D/G/V/S
+COMPRESSIBLE
+COMPRESSION
+COMPRISE/D/G/S
+COMPROMISE/D/R/Z/G/S
+COMPROMISING/Y
+COMPTROLLER/M/S
+COMPULSION/M/S
+COMPULSORY
+COMPUNCTION
+COMPUTABILITY
+COMPUTABLE
+COMPUTATION/M/S
+COMPUTATIONAL/Y
+COMPUTE/D/R/Z/G/S
+COMPUTER'S
+COMPUTERIZE/D/G/S
+COMRADE/Y/S
+COMRADESHIP
+CONCATENATE/D/G/N/X/S
+CONCEAL/D/R/Z/G/S
+CONCEALMENT
+CONCEDE/D/G/S
+CONCEIT/D/S
+CONCEIVABLE
+CONCEIVABLY
+CONCEIVE/D/G/S
+CONCENTRATE/D/G/N/X/S
+CONCENTRATOR/S
+CONCENTRIC
+CONCEPT/M/S
+CONCEPTION/M/S
+CONCEPTUAL/Y
+CONCEPTUALIZATION/M/S
+CONCEPTUALIZE/D/G/S
+CONCERN/D/G/S
+CONCERNEDLY
+CONCERT/D/S
+CONCESSION/M/S
+CONCISE/P/Y
+CONCLUDE/D/G/S
+CONCLUSION/M/S
+CONCLUSIVE/Y
+CONCOCT
+CONCOMITANT
+CONCORD
+CONCORDANCE
+CONCRETE/P/N/Y/S
+CONCUR/S
+CONCURRED
+CONCURRENCE
+CONCURRENCY/S
+CONCURRENT/Y
+CONCURRING
+CONDEMN/D/R/Z/G/S
+CONDEMNATION/S
+CONDENSATION
+CONDENSE/D/R/G/S
+CONDESCEND/G
+CONDITION/D/R/Z/G/S
+CONDITIONAL/Y/S
+CONDONE/D/G/S
+CONDUCIVE
+CONDUCT/D/G/V/S
+CONDUCTION
+CONDUCTIVITY
+CONDUCTOR/M/S
+CONE/M/S
+CONFEDERACY
+CONFEDERATE/N/X/S
+CONFER/S
+CONFERENCE/M/S
+CONFERRED
+CONFERRER/M/S
+CONFERRING
+CONFESS/D/G/S
+CONFESSION/M/S
+CONFESSOR/M/S
+CONFIDANT/M/S
+CONFIDE/D/G/S
+CONFIDENCE/S
+CONFIDENT/Y
+CONFIDENTIAL/Y
+CONFIDENTIALITY
+CONFIDINGLY
+CONFIGURABLE
+CONFIGURATION/M/S
+CONFIGURE/D/G/S
+CONFINE/D/R/G/S
+CONFINEMENT/M/S
+CONFIRM/D/G/S
+CONFIRMATION/M/S
+CONFISCATE/D/G/N/X/S
+CONFLICT/D/G/S
+CONFORM/D/G/S
+CONFORMITY
+CONFOUND/D/G/S
+CONFRONT/D/R/Z/G/S
+CONFRONTATION/M/S
+CONFUSE/D/R/Z/G/N/X/S
+CONFUSINGLY
+CONGENIAL/Y
+CONGESTED
+CONGESTION
+CONGRATULATE/D/N/X
+CONGREGATE/D/G/N/X/S
+CONGRESS/M/S
+CONGRESSIONAL/Y
+CONGRESSMAN
+CONGRUENCE
+CONGRUENT
+CONIC
+CONJECTURE/D/G/S
+CONJOINED
+CONJUNCT/D/V/S
+CONJUNCTION/M/S
+CONJUNCTIVELY
+CONJURE/D/R/G/S
+CONNECT/D/G/S
+CONNECTEDNESS
+CONNECTICUT
+CONNECTION/M/S
+CONNECTIONIST
+CONNECTIVE/M/S
+CONNECTIVITY
+CONNECTOR/M/S
+CONNOISSEUR/M/S
+CONNOTE/D/G/S
+CONQUER/D/R/Z/G/S
+CONQUERABLE
+CONQUEROR/M/S
+CONQUEST/M/S
+CONS
+CONSCIENCE/M/S
+CONSCIENTIOUS/Y
+CONSCIOUS/P/Y
+CONSECRATE/N
+CONSECUTIVE/Y
+CONSENSUS
+CONSENT/D/R/Z/G/S
+CONSEQUENCE/M/S
+CONSEQUENT/Y/S
+CONSEQUENTIAL
+CONSEQUENTIALITY/S
+CONSERVATION/M/S
+CONSERVATIONIST/M/S
+CONSERVATISM
+CONSERVATIVE/Y/S
+CONSERVE/D/G/S
+CONSIDER/D/G/S
+CONSIDERABLE
+CONSIDERABLY
+CONSIDERATE/N/X/Y
+CONSIGN/D/G/S
+CONSIST/D/G/S
+CONSISTENCY
+CONSISTENT/Y
+CONSOLABLE
+CONSOLATION/M/S
+CONSOLE/D/R/Z/G/S
+CONSOLIDATE/D/G/N/S
+CONSOLINGLY
+CONSONANT/M/S
+CONSORT/D/G/S
+CONSORTIUM
+CONSPICUOUS/Y
+CONSPIRACY/M/S
+CONSPIRATOR/M/S
+CONSPIRE/D/S
+CONSTABLE/M/S
+CONSTANCY
+CONSTANT/Y/S
+CONSTELLATION/M/S
+CONSTERNATION
+CONSTITUENCY/M/S
+CONSTITUENT/M/S
+CONSTITUTE/D/G/N/X/V/S
+CONSTITUTIONAL/Y
+CONSTITUTIONALITY
+CONSTRAIN/D/G/S
+CONSTRAINT/M/S
+CONSTRUCT/D/G/V/S
+CONSTRUCTIBILITY
+CONSTRUCTIBLE
+CONSTRUCTION/M/S
+CONSTRUCTIVELY
+CONSTRUCTOR/M/S
+CONSTRUE/D/G
+CONSUL/M/S
+CONSULATE/M/S
+CONSULT/D/G/S
+CONSULTANT/M/S
+CONSULTATION/M/S
+CONSUMABLE
+CONSUME/D/R/Z/G/S
+CONSUMER'S
+CONSUMMATE/D/N/Y
+CONSUMPTION/M/S
+CONSUMPTIVE/Y
+CONTACT/D/G/S
+CONTAGION
+CONTAGIOUS/Y
+CONTAIN/D/R/Z/G/S
+CONTAINABLE
+CONTAINMENT/M/S
+CONTAMINATE/D/G/N/S
+CONTEMPLATE/D/G/N/X/V/S
+CONTEMPORARY/P/S
+CONTEMPT
+CONTEMPTIBLE
+CONTEMPTUOUS/Y
+CONTEND/D/R/Z/G/S
+CONTENT/D/G/Y/S
+CONTENTION/M/S
+CONTENTMENT
+CONTEST/D/R/Z/G/S
+CONTESTABLE
+CONTEXT/M/S
+CONTEXTUAL/Y
+CONTIGUITY
+CONTIGUOUS/Y
+CONTINENT/M/S
+CONTINENTAL/Y
+CONTINGENCY/M/S
+CONTINGENT/M/S
+CONTINUAL/Y
+CONTINUANCE/M/S
+CONTINUATION/M/S
+CONTINUE/D/G/S
+CONTINUITY/S
+CONTINUO
+CONTINUOUS/Y
+CONTINUUM
+CONTOUR/D/M/G/S
+CONTRACT/D/G/S
+CONTRACTION/M/S
+CONTRACTOR/M/S
+CONTRACTUAL/Y
+CONTRADICT/D/G/S
+CONTRADICTION/M/S
+CONTRADICTORY
+CONTRADISTINCTION/S
+CONTRAPOSITIVE/S
+CONTRAPTION/M/S
+CONTRARY/P
+CONTRAST/D/R/Z/G/S
+CONTRASTINGLY
+CONTRIBUTE/D/G/N/X/S
+CONTRIBUTOR/M/S
+CONTRIBUTORILY
+CONTRIBUTORY
+CONTRIVANCE/M/S
+CONTRIVE/D/R/G/S
+CONTROL/M/S
+CONTROLLABILITY
+CONTROLLABLE
+CONTROLLABLY
+CONTROLLED
+CONTROLLER/M/S
+CONTROLLING
+CONTROVERSIAL
+CONTROVERSY/M/S
+CONUNDRUM/M/S
+CONVENE/D/G/S
+CONVENIENCE/M/S
+CONVENIENT/Y
+CONVENT/M/S
+CONVENTION/M/S
+CONVENTIONAL/Y
+CONVERGE/D/G/S
+CONVERGENCE
+CONVERGENT
+CONVERSANT/Y
+CONVERSATION/M/S
+CONVERSATIONAL/Y
+CONVERSE/D/G/N/X/Y/S
+CONVERT/D/R/Z/G/S
+CONVERTIBILITY
+CONVERTIBLE
+CONVEX
+CONVEY/D/R/Z/G/S
+CONVEYANCE/M/S
+CONVICT/D/G/S
+CONVICTION/M/S
+CONVINCE/D/R/Z/G/S
+CONVINCINGLY
+CONVOLUTED
+CONVOY/D/G/S
+CONVULSION/M/S
+COO/G
+COOK/D/G/S
+COOKERY
+COOKIE/M/S
+COOKY
+COOL/P/D/T/G/Y/S
+COOLER/M/S
+COOLIE/M/S
+COON/M/S
+COOP/D/R/Z/S
+COOPERATE/D/G/N/X/V/S
+COOPERATIVELY
+COOPERATIVES
+COOPERATOR/M/S
+COORDINATE/D/G/N/X/S
+COORDINATOR/M/S
+COP/M/S
+COPE/D/G/J/S
+COPIOUS/P/Y
+COPPER/M/S
+COPSE
+COPY/D/R/Z/G/S
+COPYRIGHT/M/S
+CORAL
+CORD/D/R/S
+CORDIAL/Y
+CORE/D/R/Z/G/S
+CORK/D/R/Z/G/S
+CORMORANT
+CORN/R/Z/G/S
+CORNERED
+CORNERSTONE/M/S
+CORNFIELD/M/S
+COROLLARY/M/S
+CORONARY/S
+CORONATION
+CORONET/M/S
+COROUTINE/M/S
+CORPOCRACY/S
+CORPORAL/M/S
+CORPORATE/N/X/Y
+CORPORATION'S
+CORPS
+CORPSE/M/S
+CORPUS
+CORRECT/P/D/G/Y/S
+CORRECTABLE
+CORRECTION/S
+CORRECTIVE/Y/S
+CORRECTOR
+CORRELATE/D/G/N/X/V/S
+CORRESPOND/D/G/S
+CORRESPONDENCE/M/S
+CORRESPONDENT/M/S
+CORRESPONDINGLY
+CORRIDOR/M/S
+CORROBORATE/D/G/N/X/V/S
+CORROSION
+CORRUPT/D/R/G/S
+CORRUPTION
+CORSET
+CORTEX
+CORTICAL
+COSINE/S
+COSMETIC/S
+COSMOLOGY
+COSMOPOLITAN
+COST/D/G/Y/S
+COSTUME/D/R/G/S
+COT/M/S
+COTTAGE/R/S
+COTTON/S
+COTYLEDON/M/S
+COUCH/D/G/S
+COUGH/D/G
+COUGHS
+COULD
+COULDN'T
+COUNCIL/M/S
+COUNCILLOR/M/S
+COUNSEL/D/G/S
+COUNSELLED
+COUNSELLING
+COUNSELLOR/M/S
+COUNSELOR/M/S
+COUNT/D/Z/G/S
+COUNTABLE
+COUNTABLY
+COUNTENANCE
+COUNTER/D/G/S
+COUNTERACT/D/G/V
+COUNTERCLOCKWISE
+COUNTEREXAMPLE/S
+COUNTERFEIT/D/R/G
+COUNTERMEASURE/M/S
+COUNTERPART/M/S
+COUNTERPOINT/G
+COUNTERPRODUCTIVE
+COUNTERREVOLUTION
+COUNTESS
+COUNTLESS
+COUNTRY/M/S
+COUNTRYMAN
+COUNTRYSIDE
+COUNTY/M/S
+COUPLE/D/R/Z/G/J/S
+COUPON/M/S
+COURAGE
+COURAGEOUS/Y
+COURIER/M/S
+COURSE/D/R/G/S
+COURT/D/R/Z/G/Y/S
+COURTEOUS/Y
+COURTESY/M/S
+COURTHOUSE/M/S
+COURTIER/M/S
+COURTROOM/M/S
+COURTSHIP
+COURTYARD/M/S
+COUSIN/M/S
+COVE/Z/S
+COVENANT/M/S
+COVER/D/G/J/S
+COVERABLE
+COVERAGE
+COVERLET/M/S
+COVERT/Y
+COVET/D/G/S
+COVETOUS/P
+COW/D/Z/G/S
+COWARD/Y
+COWARDICE
+COWBOY/M/S
+COWER/D/R/Z/G/S
+COWERINGLY
+COWL/G/S
+COWSLIP/M/S
+COYOTE/M/S
+COZY/P/R
+CPU
+CRAB/M/S
+CRACK/D/R/Z/G/S
+CRACKLE/D/G/S
+CRADLE/D/S
+CRAFT/D/R/G/S
+CRAFTSMAN
+CRAFTY/P
+CRAG/M/S
+CRAM/S
+CRAMP/M/S
+CRANBERRY/M/S
+CRANE/M/S
+CRANK/D/G/S
+CRANKILY
+CRANKY/T/R
+CRASH/D/R/Z/G/S
+CRATE/R/Z/S
+CRAVAT/M/S
+CRAVE/D/G/S
+CRAVEN
+CRAWL/D/R/Z/G/S
+CRAY
+CRAZE/D/G/S
+CRAZILY
+CRAZY/P/T/R
+CREAK/D/G/S
+CREAM/D/R/Z/G/S
+CREAMY
+CREASE/D/G/S
+CREATE/D/G/N/X/V/S
+CREATIVELY
+CREATIVENESS
+CREATIVITY
+CREATOR/M/S
+CREATURE/M/S
+CREDENCE
+CREDIBILITY
+CREDIBLE
+CREDIBLY
+CREDIT/D/G/S
+CREDITABLE
+CREDITABLY
+CREDITOR/M/S
+CREDULITY
+CREDULOUS/P
+CREED/M/S
+CREEK/M/S
+CREEP/R/Z/G/S
+CREMATE/D/G/N/X/S
+CREPE
+CREPT
+CRESCENT/M/S
+CREST/D/S
+CREVICE/M/S
+CREW/D/G/S
+CRIB/M/S
+CRICKET/M/S
+CRIME/M/S
+CRIMINAL/Y/S
+CRIMSON/G
+CRINGE/D/G/S
+CRIPPLE/D/G/S
+CRISES
+CRISIS
+CRISP/P/Y
+CRITERIA
+CRITERION
+CRITIC/M/S
+CRITICAL/Y
+CRITICISE/D
+CRITICISM/M/S
+CRITICIZE/D/G/S
+CRITIQUE/G/S
+CROAK/D/G/S
+CROCHET/S
+CROOK/D/S
+CROP/M/S
+CROPPED
+CROPPER/M/S
+CROPPING
+CROSS/D/R/Z/G/Y/J/S
+CROSSABLE
+CROSSBAR/M/S
+CROSSOVER/M/S
+CROSSWORD/M/S
+CROUCH/D/G
+CROW/D/G/S
+CROWD/D/R/G/S
+CROWN/D/G/S
+CRT
+CRUCIAL/Y
+CRUCIFY/D/G/S
+CRUDE/P/T/Y
+CRUEL/T/R/Y
+CRUELTY
+CRUISE/R/Z/G/S
+CRUMB/Y/S
+CRUMBLE/D/G/S
+CRUMPLE/D/G/S
+CRUNCH/D/G/S
+CRUNCHY/T/R
+CRUSADE/R/Z/G/S
+CRUSH/D/R/Z/G/S
+CRUSHABLE
+CRUSHINGLY
+CRUST/M/S
+CRUSTACEAN/M/S
+CRUTCH/M/S
+CRUX/M/S
+CRY/D/R/Z/G/S
+CRYPTANALYSIS
+CRYPTOGRAPHIC
+CRYPTOGRAPHY
+CRYPTOLOGY
+CRYSTAL/M/S
+CRYSTALLINE
+CRYSTALLIZE/D/G/S
+CS
+CSD
+CUB/M/S
+CUBE/D/S
+CUBIC
+CUCKOO/M/S
+CUCUMBER/M/S
+CUDDLE/D
+CUDGEL/M/S
+CUE/D/S
+CUFF/M/S
+CULL/D/R/G/S
+CULMINATE/D/G/N/S
+CULPRIT/M/S
+CULT/M/S
+CULTIVATE/D/G/N/X/S
+CULTIVATOR/M/S
+CULTURAL/Y
+CULTURE/D/G/S
+CUMBERSOME
+CUMULATIVE/Y
+CUNNING/Y
+CUP/M/S
+CUPBOARD/M/S
+CUPFUL
+CUPPED
+CUPPING
+CUR/Y/S
+CURABLE
+CURABLY
+CURB/G/S
+CURD
+CURE/D/G/S
+CURFEW/M/S
+CURIOSITY/M/S
+CURIOUS/T/R/Y
+CURL/D/R/Z/G/S
+CURRANT/M/S
+CURRENCY/M/S
+CURRENT/P/Y/S
+CURRICULA
+CURRICULAR
+CURRICULUM/M/S
+CURRY/D/G/S
+CURSE/D/G/V/S
+CURSOR/M/S
+CURSORILY
+CURSORY
+CURT/P/Y
+CURTAIL/D/S
+CURTAIN/D/S
+CURTATE
+CURTSY/M/S
+CURVATURE
+CURVE/D/G/S
+CUSHION/D/G/S
+CUSP/M/S
+CUSTARD
+CUSTODIAN/M/S
+CUSTODY
+CUSTOM/R/Z/S
+CUSTOMARILY
+CUSTOMARY
+CUSTOMIZABLE
+CUSTOMIZATION/M/S
+CUSTOMIZE/D/R/Z/G/S
+CUT/M/S
+CUTE/T
+CUTOFF
+CUTTER/M/S
+CUTTING/Y/S
+CYBERNETIC
+CYCLE/D/G/S
+CYCLIC
+CYCLICALLY
+CYCLOID/M/S
+CYCLOIDAL
+CYCLONE/M/S
+CYLINDER/M/S
+CYLINDRICAL
+CYMBAL/M/S
+CYNICAL/Y
+CYPRESS
+CYST/S
+CYTOLOGY
+CZAR
+DABBLE/D/R/G/S
+DAD/M/S
+DADDY
+DAEMON/M/S
+DAFFODIL/M/S
+DAGGER
+DAILY/S
+DAINTILY
+DAINTY/P
+DAIRY
+DAISY/M/S
+DALE/M/S
+DAM/M/S
+DAMAGE/D/R/Z/G/S
+DAMASK
+DAME
+DAMN/D/G/S
+DAMNATION
+DAMP/P/R/G/N/X
+DAMSEL/M/S
+DAN/M
+DANCE/D/R/Z/G/S
+DANDELION/M/S
+DANDY
+DANGER/M/S
+DANGEROUS/Y
+DANGLE/D/G/S
+DANIEL/M
+DARE/D/R/Z/G/S
+DARESAY
+DARINGLY
+DARK/P/T/R/N/Y
+DARLING/M/S
+DARN/D/R/G/S
+DARPA
+DART/D/R/G/S
+DASH/D/R/Z/G/S
+DASHING/Y
+DATA
+DATABASE/M/S
+DATE/D/R/G/V/S
+DATUM
+DAUGHTER/Y/S
+DAUNT/D
+DAUNTLESS
+DAVE/M
+DAVID/M
+DAWN/D/G/S
+DAY/M/S
+DAYBREAK
+DAYDREAM/G/S
+DAYLIGHT/M/S
+DAYTIME
+DAZE/D
+DAZZLE/D/R/G/S
+DAZZLINGLY
+DBMS
+DEACON/M/S
+DEAD/P/N/Y
+DEADLINE/M/S
+DEADLOCK/D/G/S
+DEAF/P/T/R/N
+DEAL/R/Z/G/J/S
+DEALLOCATE/D/G/N/X/S
+DEALLOCATED
+DEALLOCATION
+DEALT
+DEAN/M/S
+DEAR/P/T/R/H/Y
+DEARTHS
+DEATH/Y
+DEATHRATE/M/S
+DEATHS
+DEBATABLE
+DEBATE/D/R/Z/G/S
+DEBBIE/M
+DEBILITATE/D/G/S
+DEBRIS
+DEBT/M/S
+DEBTOR
+DEBUG/S
+DEBUGGED
+DEBUGGER/M/S
+DEBUGGING
+DECADE/M/S
+DECADENCE
+DECADENT/Y
+DECAY/D/G/S
+DECEASE/D/G/S
+DECEIT
+DECEITFUL/P/Y
+DECEIVE/D/R/Z/G/S
+DECELERATE/D/G/N/S
+DECEMBER
+DECENCY/M/S
+DECENT/Y
+DECENTRALIZATION
+DECENTRALIZED
+DECEPTION/M/S
+DECEPTIVE/Y
+DECIDABILITY
+DECIDABLE
+DECIDE/D/G/S
+DECIDEDLY
+DECIMAL/S
+DECIMATE/D/G/N/S
+DECIPHER/D/R/G/S
+DECISION/M/S
+DECISIVE/P/Y
+DECK/D/G/J/S
+DECLARATION/M/S
+DECLARATIVE/Y/S
+DECLARE/D/R/Z/G/S
+DECLINATION/M/S
+DECLINE/D/R/Z/G/S
+DECODE/D/R/Z/G/J/S
+DECOMPOSABILITY
+DECOMPOSABLE
+DECOMPOSE/D/G/S
+DECOMPOSITION/M/S
+DECOMPRESSION
+DECONSTRUCT/D/G/S
+DECONSTRUCTION
+DECORATE/D/G/N/X/V/S
+DECORUM
+DECOUPLE/D/G/S
+DECOY/M/S
+DECREASE/D/G/S
+DECREASINGLY
+DECREE/D/S
+DECREEING
+DECREMENT/D/G/S
+DEDICATE/D/G/N/S
+DEDUCE/D/R/G/S
+DEDUCIBLE
+DEDUCT/D/G/V
+DEDUCTION/M/S
+DEED/D/G/S
+DEEM/D/G/S
+DEEMPHASIZE/D/G/S
+DEEP/T/R/N/Y/S
+DEEPEN/D/G/S
+DEER
+DEFAULT/D/R/G/S
+DEFEAT/D/G/S
+DEFECT/D/G/V/S
+DEFECTION/M/S
+DEFEND/D/R/Z/G/S
+DEFENDANT/M/S
+DEFENESTRATE/D/G/N/S
+DEFENSE/V/S
+DEFENSELESS
+DEFER/S
+DEFERENCE
+DEFERMENT/M/S
+DEFERRABLE
+DEFERRED
+DEFERRER/M/S
+DEFERRING
+DEFIANCE
+DEFIANT/Y
+DEFICIENCY/S
+DEFICIENT
+DEFICIT/M/S
+DEFILE/G
+DEFINABLE
+DEFINE/D/R/G/S
+DEFINITE/P/N/X/Y
+DEFINITION/M/S
+DEFINITIONAL
+DEFINITIVE
+DEFORMATION/M/S
+DEFORMED
+DEFORMITY/M/S
+DEFTLY
+DEFY/D/G/S
+DEGENERATE/D/G/N/V/S
+DEGRADABLE
+DEGRADATION/M/S
+DEGRADE/D/G/S
+DEGREE/M/S
+DEIGN/D/G/S
+DEITY/M/S
+DEJECTED/Y
+DELAWARE
+DELAY/D/G/S
+DELEGATE/D/G/N/X/S
+DELETE/D/R/G/N/X/S
+DELIBERATE/P/D/G/N/X/Y/S
+DELIBERATIVE
+DELIBERATOR/M/S
+DELICACY/M/S
+DELICATE/Y
+DELICIOUS/Y
+DELIGHT/D/G/S
+DELIGHTEDLY
+DELIGHTFUL/Y
+DELIMIT/D/R/Z/G/S
+DELINEATE/D/G/N/S
+DELIRIOUS/Y
+DELIVER/D/R/Z/G/S
+DELIVERABLE/S
+DELIVERANCE
+DELIVERY/M/S
+DELL/M/S
+DELTA/M/S
+DELUDE/D/G/S
+DELUGE/D/S
+DELUSION/M/S
+DELVE/G/S
+DEMAND/D/R/G/S
+DEMANDINGLY
+DEMARCATE/N/D/G/S
+DEMEANOR
+DEMISE
+DEMO/S
+DEMOCRACY/M/S
+DEMOCRAT/M/S
+DEMOCRATIC
+DEMOCRATICALLY
+DEMOGRAPHIC
+DEMOLISH/D/S
+DEMOLITION
+DEMON/M/S
+DEMONSTRABLE
+DEMONSTRATE/D/G/N/X/V/S
+DEMONSTRATIVELY
+DEMONSTRATOR/M/S
+DEMORALIZE/D/G/S
+DEMUR
+DEN/M/S
+DENDRITE/S
+DENIABLE
+DENIAL/M/S
+DENIGRATE/D/G/S
+DENMARK
+DENOMINATION/M/S
+DENOMINATOR/M/S
+DENOTABLE
+DENOTATION/M/S
+DENOTATIONAL/Y
+DENOTE/D/G/S
+DENOUNCE/D/G/S
+DENSE/P/T/R/Y
+DENSITY/M/S
+DENT/D/G/S
+DENTAL/Y
+DENTIST/M/S
+DENY/D/R/G/S
+DEPART/D/G/S
+DEPARTMENT/M/S
+DEPARTMENTAL
+DEPARTURE/M/S
+DEPEND/D/G/S
+DEPENDABILITY
+DEPENDABLE
+DEPENDABLY
+DEPENDENCE
+DEPENDENCY/S
+DEPENDENT/Y/S
+DEPICT/D/G/S
+DEPLETE/D/G/N/X/S
+DEPLORABLE
+DEPLORE/D/S
+DEPLOY/D/G/S
+DEPLOYABLE
+DEPLOYMENT/M/S
+DEPORTATION
+DEPORTMENT
+DEPOSE/D/S
+DEPOSIT/D/G/S
+DEPOSITION/M/S
+DEPOSITOR/M/S
+DEPOT/M/S
+DEPRAVE/D
+DEPRECIATE/N/S
+DEPRESS/D/G/S
+DEPRESSION/M/S
+DEPRIVATION/M/S
+DEPRIVE/D/G/S
+DEPT
+DEPTH
+DEPTHS
+DEPUTY/M/S
+DEQUEUE/D/G/S
+DERAIL/D/G/S
+DERBY
+DERIDE
+DERISION
+DERIVABLE
+DERIVATION/M/S
+DERIVATIVE/M/S
+DERIVE/D/G/S
+DESCEND/D/R/Z/G/S
+DESCENDANT/M/S
+DESCENT/M/S
+DESCRIBABLE
+DESCRIBE/D/R/G/S
+DESCRIPTION/M/S
+DESCRIPTIVE/Y/S
+DESCRIPTOR/M/S
+DESCRY
+DESELECTED
+DESERT/D/R/Z/G/S
+DESERTION/S
+DESERVE/D/G/J/S
+DESERVINGLY
+DESIDERATA
+DESIDERATUM
+DESIGN/D/R/Z/G/S
+DESIGNATE/D/G/N/X/S
+DESIGNATOR/M/S
+DESIGNER'S
+DESIRABILITY
+DESIRABLE
+DESIRABLY
+DESIRE/D/G/S
+DESIROUS
+DESK/M/S
+DESOLATE/N/X/Y
+DESPAIR/D/G/S
+DESPAIRINGLY
+DESPATCH/D
+DESPERATE/N/Y
+DESPISE/D/G/S
+DESPITE
+DESPOT/M/S
+DESPOTIC
+DESSERT/M/S
+DESTINATION/M/S
+DESTINE/D
+DESTINY/M/S
+DESTITUTE/N
+DESTROY/D/G/S
+DESTROYER/M/S
+DESTRUCTION/M/S
+DESTRUCTIVE/P/Y
+DETACH/D/R/G/S
+DETACHMENT/M/S
+DETAIL/D/G/S
+DETAIN/D/G/S
+DETECT/D/G/V/S
+DETECTABLE
+DETECTABLY
+DETECTION/M/S
+DETECTIVES
+DETECTOR/M/S
+DETENTION
+DETERIORATE/D/G/N/S
+DETERMINABLE
+DETERMINACY
+DETERMINANT/M/S
+DETERMINATE/N/X/V/Y
+DETERMINE/D/R/Z/G/S
+DETERMINISM
+DETERMINISTIC
+DETERMINISTICALLY
+DETERRENT
+DETEST/D
+DETESTABLE
+DETRACT/S
+DETRACTOR/M/S
+DETRIMENT
+DETRIMENTAL
+DEVASTATE/D/G/N/S
+DEVELOP/D/R/Z/G/S
+DEVELOPMENT/M/S
+DEVELOPMENTAL
+DEVIANT/M/S
+DEVIATE/D/G/N/X/S
+DEVICE/M/S
+DEVIL/M/S
+DEVILISH/Y
+DEVISE/D/G/J/S
+DEVOID
+DEVOTE/D/G/N/X/S
+DEVOTEDLY
+DEVOTEE/M/S
+DEVOUR/D/R/S
+DEVOUT/P/Y
+DEW
+DEWDROP/M/S
+DEWY
+DEXTERITY
+DIADEM
+DIAGNOSABLE
+DIAGNOSE/D/G/S
+DIAGNOSIS
+DIAGNOSTIC/M/S
+DIAGONAL/Y/S
+DIAGRAM/M/S
+DIAGRAMMABLE
+DIAGRAMMATIC
+DIAGRAMMATICALLY
+DIAGRAMMED
+DIAGRAMMER/M/S
+DIAGRAMMING
+DIAL/D/G/S
+DIALECT/M/S
+DIALOG/M/S
+DIALOGUE/M/S
+DIAMETER/M/S
+DIAMETRICALLY
+DIAMOND/M/S
+DIAPER/M/S
+DIAPHRAGM/M/S
+DIARY/M/S
+DIATRIBE/M/S
+DICE
+DICHOTOMIZE
+DICHOTOMY
+DICKENS
+DICKY
+DICTATE/D/G/N/X/S
+DICTATOR/M/S
+DICTATORSHIP
+DICTION
+DICTIONARY/M/S
+DICTUM/M/S
+DID
+DIDN'T
+DIE/D/S
+DIEGO
+DIELECTRIC/M/S
+DIET/R/Z/S
+DIETITIAN/M/S
+DIFFER/D/G/R/S/Z
+DIFFERENCE/M/S
+DIFFERENT/Y
+DIFFERENTIAL/M/S
+DIFFERENTIATE/D/G/N/X/S
+DIFFERENTIATORS
+DIFFICULT/Y
+DIFFICULTY/M/S
+DIFFUSE/D/R/Z/G/N/X/Y/S
+DIG/S
+DIGEST/D/G/V/S
+DIGESTIBLE
+DIGESTION
+DIGGER/M/S
+DIGGING/S
+DIGIT/M/S
+DIGITAL/Y
+DIGITIZE/S/G/D
+DIGNIFY/D
+DIGNITY/S
+DIGRESS/D/G/V/S
+DIGRESSION/M/S
+DIKE/M/S
+DILATE/D/G/N/S
+DILEMMA/M/S
+DILIGENCE
+DILIGENT/Y
+DILUTE/D/G/N/S
+DIM/P/Y/S
+DIME/M/S
+DIMENSION/D/G/S
+DIMENSIONAL/Y
+DIMENSIONALITY
+DIMINISH/D/G/S
+DIMINUTION
+DIMINUTIVE
+DIMMED
+DIMMER/M/S
+DIMMEST
+DIMMING
+DIMPLE/D
+DIN
+DINE/D/R/Z/G/S
+DINGY/P
+DINNER/M/S
+DINT
+DIODE/M/S
+DIOPHANTINE
+DIOXIDE
+DIP/S
+DIPHTHERIA
+DIPLOMA/M/S
+DIPLOMACY
+DIPLOMAT/M/S
+DIPLOMATIC
+DIPPED
+DIPPER/M/S
+DIPPING/S
+DIRE
+DIRECT/P/D/G/Y/S
+DIRECTION/M/S
+DIRECTIONAL/Y
+DIRECTIONALITY
+DIRECTIVE/M/S
+DIRECTOR/M/S
+DIRECTORY/M/S
+DIRGE/M/S
+DIRT/S
+DIRTILY
+DIRTY/P/T/R
+DISABILITY/M/S
+DISABLE/D/R/Z/G/S
+DISADVANTAGE/M/S
+DISAGREE/D/S
+DISAGREEABLE
+DISAGREEING
+DISAGREEMENT/M/S
+DISALLOW/D/G/S
+DISAMBIGUATE/D/G/N/X/S
+DISAPPEAR/D/G/S
+DISAPPEARANCE/M/S
+DISAPPOINT/D/G
+DISAPPOINTMENT/M/S
+DISAPPROVAL
+DISAPPROVE/D/S
+DISARM/D/G/S
+DISARMAMENT
+DISASSEMBLE/D/G/S
+DISASTER/M/S
+DISASTROUS/Y
+DISBAND/D/G/S
+DISBURSE/D/G/S
+DISBURSEMENT/M/S
+DISC/M/S
+DISCARD/D/G/S
+DISCERN/D/G/S
+DISCERNIBILITY
+DISCERNIBLE
+DISCERNIBLY
+DISCERNINGLY
+DISCERNMENT
+DISCHARGE/D/G/S
+DISCIPLE/M/S
+DISCIPLINARY
+DISCIPLINE/D/G/S
+DISCLAIM/D/R/S
+DISCLOSE/D/G/S
+DISCLOSURE/M/S
+DISCOMFORT
+DISCONCERT
+DISCONCERTING/Y
+DISCONNECT/D/G/S
+DISCONNECTION
+DISCONTENT/D
+DISCONTINUANCE
+DISCONTINUE/D/S
+DISCONTINUITY/M/S
+DISCONTINUOUS
+DISCORD
+DISCOUNT/D/G/S
+DISCOURAGE/D/G/S
+DISCOURAGEMENT
+DISCOURSE/M/S
+DISCOVER/D/R/Z/G/S
+DISCOVERY/M/S
+DISCREDIT/D
+DISCREET/Y
+DISCREPANCY/M/S
+DISCRETE/P/N/Y
+DISCRIMINATE/D/G/N/S
+DISCRIMINATORY
+DISCUSS/D/G/S
+DISCUSSION/M/S
+DISDAIN/G/S
+DISEASE/D/S
+DISENGAGE/D/G/S
+DISFIGURE/D/G/S
+DISGORGE
+DISGRACE/D/S
+DISGRACEFUL/Y
+DISGRUNTLED
+DISGUISE/D/S
+DISGUST/D/G/S
+DISGUSTEDLY
+DISGUSTINGLY
+DISH/D/G/S
+DISHEARTEN/G
+DISHONEST/Y
+DISHONOR/D/G/S
+DISHWASHER/S
+DISHWASHING
+DISILLUSION/D/G
+DISILLUSIONMENT/M/S
+DISINTERESTED/P
+DISJOINT/P/D
+DISJUNCT/V/S
+DISJUNCTION/S
+DISJUNCTIVELY
+DISK/M/S
+DISKETTE/S
+DISLIKE/D/G/S
+DISLOCATE/D/G/N/X/S
+DISLODGE/D
+DISMAL/Y
+DISMAY/D/G
+DISMISS/D/R/Z/G/S
+DISMISSAL/M/S
+DISMOUNT/D/G/S
+DISOBEDIENCE
+DISOBEY/D/G/S
+DISORDER/D/Y/S
+DISORGANIZED
+DISORIENTED
+DISOWN/D/G/S
+DISPARATE
+DISPARITY/M/S
+DISPATCH/D/R/Z/G/S
+DISPEL/S
+DISPELLED
+DISPELLING
+DISPENSATION
+DISPENSE/D/R/Z/G/S
+DISPERSE/D/G/N/X/S
+DISPLACE/D/G/S
+DISPLACEMENT/M/S
+DISPLAY/D/G/S
+DISPLEASE/D/G/S
+DISPLEASURE
+DISPOSABLE
+DISPOSAL/M/S
+DISPOSE/D/R/G/S
+DISPOSITION/M/S
+DISPROVE/D/G/S
+DISPUTE/D/R/Z/G/S
+DISQUALIFY/D/G/N/S
+DISQUIET/G
+DISREGARD/D/G/S
+DISRUPT/D/G/V/S
+DISRUPTION/M/S
+DISSATISFACTION/M/S
+DISSATISFIED
+DISSEMINATE/D/G/N/S
+DISSENSION/M/S
+DISSENT/D/R/Z/G/S
+DISSERTATION/M/S
+DISSERVICE
+DISSIDENT/M/S
+DISSIMILAR
+DISSIMILARITY/M/S
+DISSIPATE/D/G/N/S
+DISSOCIATE/D/G/N/S
+DISSOLUTION/M/S
+DISSOLVE/D/G/S
+DISTAL/Y
+DISTANCE/S
+DISTANT/Y
+DISTASTE/S
+DISTASTEFUL/Y
+DISTEMPER
+DISTILL/D/R/Z/G/S
+DISTILLATION
+DISTINCT/P/Y
+DISTINCTION/M/S
+DISTINCTIVE/P/Y
+DISTINGUISH/D/G/S
+DISTINGUISHABLE
+DISTORT/D/G/S
+DISTORTION/M/S
+DISTRACT/D/G/S
+DISTRACTION/M/S
+DISTRAUGHT
+DISTRESS/D/G/S
+DISTRIBUTE/D/G/N/V/S
+DISTRIBUTION/M/S
+DISTRIBUTIONAL
+DISTRIBUTIVITY
+DISTRIBUTOR/M/S
+DISTRICT/M/S
+DISTRUST/D
+DISTURB/D/R/G/S
+DISTURBANCE/M/S
+DISTURBINGLY
+DITCH/M/S
+DITTO
+DIVAN/M/S
+DIVE/D/R/Z/G/S
+DIVERGE/D/G/S
+DIVERGENCE/M/S
+DIVERGENT
+DIVERSE/N/X/Y
+DIVERSIFY/D/G/N/S
+DIVERSITY/S
+DIVERT/D/G/S
+DIVEST/D/G/S
+DIVIDE/D/R/Z/G/S
+DIVIDEND/M/S
+DIVINE/R/G/Y
+DIVINITY/M/S
+DIVISION/M/S
+DIVISOR/M/S
+DIVORCE/D
+DIVULGE/D/G/S
+DIZZY/P
+DNA
+DO/R/Z/G/J
+DOCK/D/S
+DOCTOR/D/S
+DOCTORAL
+DOCTORATE/M/S
+DOCTRINE/M/S
+DOCUMENT/D/R/Z/G/S
+DOCUMENTARY/M/S
+DOCUMENTATION/M/S
+DODGE/D/R/Z/G
+DOES
+DOESN'T
+DOG/M/S
+DOGGED/P/Y
+DOGGING
+DOGMA/M/S
+DOGMATISM
+DOLE/D/S
+DOLEFUL/Y
+DOLL/M/S
+DOLLAR/S
+DOLLY/M/S
+DOLPHIN/M/S
+DOMAIN/M/S
+DOME/D/S
+DOMESTIC
+DOMESTICALLY
+DOMESTICATE/D/G/N/S
+DOMINANCE
+DOMINANT/Y
+DOMINATE/D/G/N/S
+DOMINION
+DON'T
+DON/S
+DONALD/M
+DONATE/D/G/S
+DONE
+DONKEY/M/S
+DOOM/D/G/S
+DOOR/M/S
+DOORSTEP/M/S
+DOORWAY/M/S
+DOPE/D/R/Z/G/S
+DORMANT
+DORMITORY/M/S
+DOSE/D/S
+DOT/M/S
+DOTE/D/G/S
+DOTINGLY
+DOTTED
+DOTTING
+DOUBLE/D/R/Z/G/S
+DOUBLET/M/S
+DOUBLY
+DOUBT/D/R/Z/G/S
+DOUBTABLE
+DOUBTFUL/Y
+DOUBTLESS/Y
+DOUG/M
+DOUGH
+DOUGHNUT/M/S
+DOUGLAS
+DOVE/R/S
+DOWN/D/Z/G/S
+DOWNCAST
+DOWNFALL/N
+DOWNPLAY/D/G/S
+DOWNRIGHT
+DOWNSTAIRS
+DOWNSTREAM
+DOWNTOWN/S
+DOWNWARD/S
+DOWNY
+DOZE/D/G/S
+DOZEN/H/S
+DR
+DRAB
+DRAFT/D/R/Z/G/S
+DRAFTSMAN
+DRAFTSMEN
+DRAG/S
+DRAGGED
+DRAGGING
+DRAGON/M/S
+DRAGOON/D/S
+DRAIN/D/R/G/S
+DRAINAGE
+DRAKE
+DRAMA/M/S
+DRAMATIC/S
+DRAMATICALLY
+DRAMATIST/M/S
+DRANK
+DRAPE/D/R/Z/S
+DRAPERY/M/S
+DRASTIC
+DRASTICALLY
+DRAUGHT/M/S
+DRAW/R/Z/G/J/S
+DRAWBACK/M/S
+DRAWBRIDGE/M/S
+DRAWL/D/G/S
+DRAWN/P/Y
+DREAD/D/G/S
+DREADFUL/Y
+DREAM/D/R/Z/G/S
+DREAMILY
+DREAMY
+DREARY/P
+DREGS
+DRENCH/D/G/S
+DRESS/D/R/Z/G/J/S
+DRESSMAKER/M/S
+DREW
+DRIER/M/S
+DRIFT/D/R/Z/G/S
+DRILL/D/R/G/S
+DRILY
+DRINK/R/Z/G/S
+DRINKABLE
+DRIP/M/S
+DRIVE/R/Z/G/S
+DRIVEN
+DRIVEWAY/M/S
+DRONE/M/S
+DROOP/D/G/S
+DROP/M/S
+DROPPED
+DROPPER/M/S
+DROPPING/M/S
+DROUGHT/M/S
+DROVE/R/Z/S
+DROWN/D/G/J/S
+DROWSY/P
+DRUDGERY
+DRUG/M/S
+DRUGGIST/M/S
+DRUM/M/S
+DRUMMED
+DRUMMER/M/S
+DRUMMING
+DRUNK/R/N/Y/S
+DRUNKARD/M/S
+DRUNKENNESS
+DRY/D/T/G/Y/S
+DUAL
+DUALITY/M/S
+DUANE/M
+DUB/S
+DUBBED
+DUBIOUS/P/Y
+DUCHESS/M/S
+DUCHY
+DUCK/D/G/S
+DUE/S
+DUEL/G/S
+DUG
+DUKE/M/S
+DULL/P/D/T/R/G/S
+DULLY
+DULY
+DUMB/P/T/R/Y
+DUMBBELL/M/S
+DUMMY/M/S
+DUMP/D/R/G/S
+DUMPLING
+DUNCE/M/S
+DUNE/M/S
+DUNGEON/M/S
+DUPLICATE/D/G/N/X/S
+DUPLICATOR/M/S
+DURABILITY/S
+DURABLE
+DURABLY
+DURATION/M/S
+DURING
+DUSK
+DUSKY/P
+DUST/D/R/Z/G/S
+DUSTY/T/R
+DUTIFUL/P/Y
+DUTY/M/S
+DWARF/D/S
+DWELL/D/R/Z/G/J/S
+DWINDLE/D/G
+DYE/D/R/Z/G/S
+DYEING
+DYNAMIC/S
+DYNAMICAL
+DYNAMICALLY
+DYNAMITE/D/G/S
+DYNASTY/M/S
+EACH
+EAGER/P/Y
+EAGLE/M/S
+EAR/D/H/S
+EARL/M/S
+EARLY/P/T/R
+EARMARK/D/G/J/S
+EARN/D/T/G/J/S
+EARNER/M/S
+EARNESTLY
+EARNESTNESS
+EARRING/M/S
+EARTHEN
+EARTHENWARE
+EARTHLY/P
+EARTHQUAKE/M/S
+EARTHS
+EARTHWORM/M/S
+EASE/D/G/S
+EASEMENT/M/S
+EASILY
+EAST/R
+EASTERN/R/Z
+EASTWARD/S
+EASY/P/T/R
+EAT/R/Z/G/N/J/S
+EAVES
+EAVESDROP/S
+EAVESDROPPED
+EAVESDROPPER/M/S
+EAVESDROPPING
+EBB/G/S
+EBONY
+ECCENTRIC/M/S
+ECCENTRICITY/S
+ECCLESIASTICAL
+ECHO/D/G
+ECHOES
+ECHOIC
+ECLIPSE/D/G/S
+ECOLOGY
+ECONOMIC/S
+ECONOMICAL/Y
+ECONOMIST/M/S
+ECONOMIZE/D/R/Z/G/S
+ECONOMY/M/S
+ECSTASY
+EDDY/M/S
+EDGE/D/G/S
+EDIBLE
+EDICT/M/S
+EDIFICE/M/S
+EDIT/D/G/S
+EDITION/M/S
+EDITOR/M/S
+EDITORIAL/Y/S
+EDUCATE/D/G/N/X/S
+EDUCATIONAL/Y
+EDUCATOR/M/S
+EDWARD/M
+EEL/M/S
+EERIE
+EFFECT/D/G/V/S
+EFFECTIVELY
+EFFECTIVENESS
+EFFECTOR/M/S
+EFFECTUALLY
+EFFEMINATE
+EFFICACY
+EFFICIENCY/S
+EFFICIENT/Y
+EFFIGY
+EFFORT/M/S
+EFFORTLESS/P/Y
+EGG/D/G/S
+EGO/S
+EIGENVALUE/M/S
+EIGHT/S
+EIGHTEEN/H/S
+EIGHTH/M/S
+EIGHTY/H/S
+EITHER
+EJACULATE/D/G/N/X/S
+EJECT/D/G/S
+EKE/D/S
+EL
+ELABORATE/P/D/G/N/X/Y/S
+ELABORATORS
+ELAPSE/D/G/S
+ELASTIC
+ELASTICALLY
+ELASTICITY
+ELBOW/G/S
+ELDER/Y/S
+ELDEST
+ELECT/D/G/V/S
+ELECTION/M/S
+ELECTIVES
+ELECTOR/M/S
+ELECTORAL
+ELECTRIC
+ELECTRICAL/P/Y
+ELECTRICITY
+ELECTRIFY/G/N
+ELECTROCUTE/D/G/N/X/S
+ELECTRODE/M/S
+ELECTROLYTE/M/S
+ELECTROLYTIC
+ELECTRON/M/S
+ELECTRONIC/S
+ELECTRONICALLY
+ELEGANCE
+ELEGANT/Y
+ELEGY
+ELEMENT/M/S
+ELEMENTAL/S
+ELEMENTARY
+ELEPHANT/M/S
+ELEVATE/D/N/S
+ELEVATOR/M/S
+ELEVEN/H/S
+ELF
+ELICIT/D/G/S
+ELIGIBILITY
+ELIGIBLE
+ELIMINATE/D/G/N/X/S
+ELIMINATOR/S
+ELISION
+ELK/M/S
+ELLIPSE/M/S
+ELLIPSIS
+ELLIPSOID/M/S
+ELLIPSOIDAL
+ELLIPTIC
+ELLIPTICAL/Y
+ELM/R/S
+ELOQUENCE
+ELOQUENT/Y
+ELSE
+ELSEWHERE
+ELUCIDATE/D/G/N/S
+ELUDE/D/G/S
+ELUSIVE/P/Y
+ELVES
+ELWOOD
+EMACIATED
+EMACS
+EMANATING
+EMANCIPATION
+EMBARK/D/S
+EMBARRASS/D/G/S
+EMBARRASSING/Y
+EMBARRASSMENT
+EMBASSY/M/S
+EMBED/S
+EMBEDDED
+EMBEDDING
+EMBELLISH/D/G/S
+EMBELLISHMENT/M/S
+EMBER
+EMBLEM
+EMBODIMENT/M/S
+EMBODY/D/G/S
+EMBRACE/D/G/S
+EMBROIDER/D/S
+EMBROIDERY/S
+EMBRYO/M/S
+EMBRYOLOGY
+EMERALD/M/S
+EMERGE/D/G/S
+EMERGENCE
+EMERGENCY/M/S
+EMERGENT
+EMERY
+EMIGRANT/M/S
+EMIGRATE/D/G/N/S
+EMINENCE
+EMINENT/Y
+EMIT/S
+EMITTED
+EMOTION/M/S
+EMOTIONAL/Y
+EMPATHY
+EMPEROR/M/S
+EMPHASES
+EMPHASIS
+EMPHASIZE/D/G/S
+EMPHATIC
+EMPHATICALLY
+EMPIRE/M/S
+EMPIRICAL/Y
+EMPIRICIST/M/S
+EMPLOY/D/G/S
+EMPLOYABLE
+EMPLOYEE/M/S
+EMPLOYER/M/S
+EMPLOYMENT/M/S
+EMPOWER/D/G/S
+EMPRESS
+EMPTILY
+EMPTY/P/D/T/R/G/S
+EMULATE/D/N/X/S
+EMULATOR/M/S
+ENABLE/D/R/Z/G/S
+ENACT/D/G/S
+ENACTMENT
+ENAMEL/D/G/S
+ENCAMP/D/G/S
+ENCAPSULATE/D/G/N/S
+ENCHANT/D/R/G/S
+ENCHANTMENT
+ENCIPHER/D/G/S
+ENCIRCLE/D/S
+ENCLOSE/D/G/S
+ENCLOSURE/M/S
+ENCODE/D/R/G/J/S
+ENCOMPASS/D/G/S
+ENCOUNTER/D/G/S
+ENCOURAGE/D/G/S
+ENCOURAGEMENT/S
+ENCOURAGINGLY
+ENCRYPT/D/G/S
+ENCRYPTION
+ENCUMBER/D/G/S
+ENCYCLOPEDIA/M/S
+ENCYCLOPEDIC
+END/D/R/Z/G/J/S
+ENDANGER/D/G/S
+ENDEAR/D/G/S
+ENDEAVOR/D/G/S
+ENDLESS/P/Y
+ENDORSE/D/G/S
+ENDORSEMENT
+ENDOW/D/G/S
+ENDOWMENT/M/S
+ENDPOINT/S
+ENDURABLE
+ENDURABLY
+ENDURANCE
+ENDURE/D/G/S
+ENDURINGLY
+ENEMA/M/S
+ENEMY/M/S
+ENERGETIC
+ENERGY/S
+ENFORCE/D/R/Z/G/S
+ENFORCEMENT
+ENGAGE/D/G/S
+ENGAGEMENT/M/S
+ENGAGINGLY
+ENGENDER/D/G/S
+ENGINE/M/S
+ENGINEER/D/M/G/S
+ENGLAND/R/Z
+ENGLISH
+ENGRAVE/D/R/G/J/S
+ENGROSS/D/G
+ENHANCE/D/G/S
+ENHANCEMENT/M/S
+ENIGMATIC
+ENJOIN/D/G/S
+ENJOY/D/G/S
+ENJOYABLE
+ENJOYABLY
+ENJOYMENT
+ENLARGE/D/R/Z/G/S
+ENLARGEMENT/M/S
+ENLIGHTEN/D/G
+ENLIGHTENMENT
+ENLIST/D/S
+ENLISTMENT
+ENLIVEN/D/G/S
+ENMITY/S
+ENNOBLE/D/G/S
+ENNUI
+ENORMITY/S
+ENORMOUS/Y
+ENOUGH
+ENQUEUE/D/S
+ENQUIRE/D/R/S
+ENRAGE/D/G/S
+ENRICH/D/G/S
+ENROLL/D/G/S
+ENROLLMENT/M/S
+ENSEMBLE/M/S
+ENSIGN/M/S
+ENSLAVE/D/G/S
+ENSNARE/D/G/S
+ENSUE/D/G/S
+ENSURE/D/R/Z/G/S
+ENTAIL/D/G/S
+ENTANGLE
+ENTER/D/G/S
+ENTERPRISE/G/S
+ENTERTAIN/D/R/Z/G/S
+ENTERTAININGLY
+ENTERTAINMENT/M/S
+ENTHUSIASM/S
+ENTHUSIAST/M/S
+ENTHUSIASTIC
+ENTHUSIASTICALLY
+ENTICE/D/R/Z/G/S
+ENTIRE/Y
+ENTIRETY/S
+ENTITLE/D/G/S
+ENTITY/M/S
+ENTRANCE/D/S
+ENTREAT/D
+ENTREATY
+ENTRENCH/D/G/S
+ENTREPRENEUR/M/S
+ENTROPY
+ENTRUST/D/G/S
+ENTRY/M/S
+ENUMERABLE
+ENUMERATE/D/G/N/V/S
+ENUMERATOR/S
+ENUNCIATION
+ENVELOP/S
+ENVELOPE/D/R/G/S
+ENVIOUS/P/Y
+ENVIRON/G/S
+ENVIRONMENT/M/S
+ENVIRONMENTAL
+ENVISAGE/D/S
+ENVISION/D/G/S
+ENVOY/M/S
+ENVY/D/S
+EOF
+EPAULET/M/S
+EPHEMERAL
+EPIC/M/S
+EPIDEMIC/M/S
+EPISCOPAL
+EPISODE/M/S
+EPISTEMOLOGICAL/Y
+EPISTEMOLOGY
+EPISTLE/M/S
+EPITAPH
+EPITAPHS
+EPITAXIAL/Y
+EPITHET/M/S
+EPITOMIZE/D/G/S
+EPOCH
+EPOCHS
+EPSILON
+EQUAL/D/G/Y/S
+EQUALITY/M/S
+EQUALIZE/D/R/Z/G/S
+EQUATE/D/G/N/X/S
+EQUATOR/M/S
+EQUATORIAL
+EQUILIBRIUM/S
+EQUIP/S
+EQUIPMENT
+EQUIPPED
+EQUIPPING
+EQUITABLE
+EQUITABLY
+EQUITY
+EQUIVALENCE/S
+EQUIVALENT/Y/S
+ERA/M/S
+ERADICATE/D/G/N/S
+ERASABLE
+ERASE/D/R/Z/G/S
+ERASURE
+ERE
+ERECT/D/G/S
+ERECTION/M/S
+ERECTOR/M/S
+ERGO
+ERGONOMIC/S
+ERMINE/M/S
+ERR/D/G/S
+ERRAND
+ERRATIC
+ERRINGLY
+ERRONEOUS/P/Y
+ERROR/M/S
+ERUPTION
+ESCALATE/D/G/N/S
+ESCAPABLE
+ESCAPADE/M/S
+ESCAPE/D/G/S
+ESCAPEE/M/S
+ESCHEW/D/G/S
+ESCORT/D/G/S
+ESOTERIC
+ESPECIAL/Y
+ESPERANTO
+ESPIONAGE
+ESPOUSE/D/G/S
+ESPRIT
+ESPY
+ESQUIRE/S
+ESSAY/D/S
+ESSENCE/M/S
+ESSENTIAL/Y/S
+ESTABLISH/D/G/S
+ESTABLISHMENT/M/S
+ESTATE/M/S
+ESTEEM/D/G/S
+ESTIMATE/D/G/N/X/S
+ETA
+ETC
+ETERNAL/Y
+ETERNITY/S
+ETHER/M/S
+ETHEREAL/Y
+ETHERNET
+ETHICAL/Y
+ETHICS
+ETHNIC
+ETHNOCENTRIC
+ETIQUETTE
+ETYMOLOGICAL
+ETYMOLOGY
+EUNUCH
+EUNUCHS
+EUPHEMISM/M/S
+EUPHORIA
+EUROPE
+EUROPEAN/S
+EVACUATE/D/N
+EVADE/D/G/S
+EVALUATE/D/G/N/X/V/S
+EVALUATOR/M/S
+EVAPORATE/D/G/N/V
+EVE/R
+EVEN/P/D/Y/S
+EVENHANDED/P/Y
+EVENING/M/S
+EVENT/M/S
+EVENTFUL/Y
+EVENTUAL/Y
+EVENTUALITY/S
+EVERGREEN
+EVERLASTING/Y
+EVERMORE
+EVERY
+EVERYBODY
+EVERYDAY
+EVERYONE/M
+EVERYTHING
+EVERYWHERE
+EVICT/D/G/S
+EVICTION/M/S
+EVIDENCE/D/G/S
+EVIDENT/Y
+EVIL/Y/S
+EVINCE/D/S
+EVOKE/D/G/S
+EVOLUTE/M/S
+EVOLUTION/M/S
+EVOLUTIONARY
+EVOLVE/D/G/S
+EWE/M/S
+EXACERBATE/D/G/N/X/S
+EXACT/P/D/G/Y/S
+EXACTINGLY
+EXACTION/M/S
+EXACTITUDE
+EXAGGERATE/D/G/N/X/S
+EXALT/D/G/S
+EXAM/M/S
+EXAMINATION/M/S
+EXAMINE/D/R/Z/G/S
+EXAMPLE/M/S
+EXASPERATE/D/G/N/S
+EXCAVATE/D/G/N/X/S
+EXCEED/D/G/S
+EXCEEDINGLY
+EXCEL/S
+EXCELLED
+EXCELLENCE/S
+EXCELLENCY
+EXCELLENT/Y
+EXCELLING
+EXCEPT/D/G/S
+EXCEPTION/M/S
+EXCEPTIONAL/Y
+EXCERPT/D/S
+EXCESS/V/S
+EXCESSIVELY
+EXCHANGE/D/G/S
+EXCHANGEABLE
+EXCHEQUER/M/S
+EXCISE/D/G/N/S
+EXCITABLE
+EXCITATION/M/S
+EXCITATORY
+EXCITE/D/G/S
+EXCITEDLY
+EXCITEMENT
+EXCITINGLY
+EXCLAIM/D/R/Z/G/S
+EXCLAMATION/M/S
+EXCLUDE/D/G/S
+EXCLUSION/S
+EXCLUSIVE/P/Y
+EXCLUSIVITY
+EXCOMMUNICATE/D/G/N/S
+EXCRETE/D/G/N/X/S
+EXCURSION/M/S
+EXCUSABLE
+EXCUSABLY
+EXCUSE/D/G/S
+EXECUTABLE
+EXECUTE/D/G/N/X/V/S
+EXECUTIONAL
+EXECUTIVE/M/S
+EXECUTOR/M/S
+EXEMPLAR
+EXEMPLARY
+EXEMPLIFY/D/R/Z/G/N/S
+EXEMPT/D/G/S
+EXERCISE/D/R/Z/G/S
+EXERT/D/G/S
+EXERTION/M/S
+EXHALE/D/G/S
+EXHAUST/D/G/V/S
+EXHAUSTEDLY
+EXHAUSTIBLE
+EXHAUSTION
+EXHAUSTIVELY
+EXHIBIT/D/G/S
+EXHIBITION/M/S
+EXHIBITOR/M/S
+EXHORTATION/M/S
+EXILE/D/G/S
+EXIST/D/G/S
+EXISTENCE
+EXISTENT
+EXISTENTIAL/Y
+EXISTENTIALISM
+EXISTENTIALIST/M/S
+EXIT/D/G/S
+EXORBITANT/Y
+EXOTIC
+EXPAND/D/G/S
+EXPANDABLE
+EXPANDER/M/S
+EXPANSE/N/X/V/S
+EXPANSIONISM
+EXPECT/D/G/S
+EXPECTANCY
+EXPECTANT/Y
+EXPECTATION/M/S
+EXPECTEDLY
+EXPECTINGLY
+EXPEDIENT/Y
+EXPEDITE/D/G/S
+EXPEDITION/M/S
+EXPEDITIOUS/Y
+EXPEL/S
+EXPELLED
+EXPELLING
+EXPEND/D/G/S
+EXPENDABLE
+EXPENDITURE/M/S
+EXPENSE/V/S
+EXPENSIVELY
+EXPERIENCE/D/G/S
+EXPERIMENT/D/R/Z/G/S
+EXPERIMENTAL/Y
+EXPERIMENTATION/M/S
+EXPERT/P/Y/S
+EXPERTISE
+EXPIRATION/M/S
+EXPIRE/D/S
+EXPLAIN/D/R/Z/G/S
+EXPLAINABLE
+EXPLANATION/M/S
+EXPLANATORY
+EXPLICIT/P/Y
+EXPLODE/D/G/S
+EXPLOIT/D/R/Z/G/S
+EXPLOITABLE
+EXPLOITATION/M/S
+EXPLORATION/M/S
+EXPLORATORY
+EXPLORE/D/R/Z/G/S
+EXPLOSION/M/S
+EXPLOSIVE/Y/S
+EXPONENT/M/S
+EXPONENTIAL/Y/S
+EXPONENTIATE/D/G/S
+EXPONENTIATION/M/S
+EXPORT/D/R/Z/G/S
+EXPOSE/D/R/Z/G/S
+EXPOSITION/M/S
+EXPOSITORY
+EXPOSURE/M/S
+EXPOUND/D/R/G/S
+EXPRESS/D/G/V/Y/S
+EXPRESSIBILITY
+EXPRESSIBLE
+EXPRESSIBLY
+EXPRESSION/M/S
+EXPRESSIVELY
+EXPRESSIVENESS
+EXPULSION
+EXPUNGE/D/G/S
+EXQUISITE/P/Y
+EXTANT
+EXTEND/D/G/S
+EXTENDIBLE
+EXTENSIBILITY
+EXTENSIBLE
+EXTENSION/M/S
+EXTENSIVE/Y
+EXTENT/M/S
+EXTENUATE/D/G/N
+EXTERIOR/M/S
+EXTERMINATE/D/G/N/S
+EXTERNAL/Y
+EXTINCT
+EXTINCTION
+EXTINGUISH/D/R/G/S
+EXTOL
+EXTRA/S
+EXTRACT/D/G/S
+EXTRACTION/M/S
+EXTRACTOR/M/S
+EXTRACURRICULAR
+EXTRANEOUS/P/Y
+EXTRAORDINARILY
+EXTRAORDINARY/P
+EXTRAPOLATE/D/G/N/X/S
+EXTRAVAGANCE
+EXTRAVAGANT/Y
+EXTREMAL
+EXTREME/Y/S
+EXTREMIST/M/S
+EXTREMITY/M/S
+EXTRINSIC
+EXUBERANCE
+EXULT
+EXULTATION
+EYE/D/R/Z/G/S
+EYEBROW/M/S
+EYEGLASS/S
+EYEING
+EYELID/M/S
+EYEPIECE/M/S
+EYESIGHT
+EYEWITNESS/M/S
+FABLE/D/S
+FABRIC/M/S
+FABRICATE/D/G/N/S
+FABULOUS/Y
+FACADE/D/S
+FACE/D/G/J/S
+FACET/D/S
+FACIAL
+FACILE/Y
+FACILITATE/D/G/S
+FACILITY/M/S
+FACSIMILE/M/S
+FACT/M/S
+FACTION/M/S
+FACTO
+FACTOR/D/G/S
+FACTORIAL
+FACTORIZATION/M/S
+FACTORY/M/S
+FACTUAL/Y
+FACULTY/M/S
+FADE/D/R/Z/G/S
+FAG/S
+FAHLMAN/M
+FAHRENHEIT
+FAIL/D/G/J/S
+FAILURE/M/S
+FAIN
+FAINT/P/D/T/R/G/Y/S
+FAIR/P/T/R/G/Y/S
+FAIRY/M/S
+FAIRYLAND
+FAITH
+FAITHFUL/P/Y
+FAITHLESS/P/Y
+FAITHS
+FAKE/D/R/G/S
+FALCON/R/S
+FALL/G/N/S
+FALLACIOUS
+FALLACY/M/S
+FALLIBILITY
+FALLIBLE
+FALSE/P/Y
+FALSEHOOD/M/S
+FALSIFY/D/G/N/S
+FALSITY
+FALTER/D/S
+FAME/D/S
+FAMILIAR/P/Y
+FAMILIARITY/S
+FAMILIARIZATION
+FAMILIARIZE/D/G/S
+FAMILY/M/S
+FAMINE/M/S
+FAMISH
+FAMOUS/Y
+FAN/M/S
+FANATIC/M/S
+FANCIER/M/S
+FANCIFUL/Y
+FANCILY
+FANCY/P/D/T/G/S
+FANG/M/S
+FANNED
+FANNING
+FANTASTIC
+FANTASY/M/S
+FAR
+FARADAY/M
+FARAWAY
+FARCE/M/S
+FARE/D/G/S
+FAREWELL/S
+FARM/D/R/Z/G/S
+FARMHOUSE/M/S
+FARMINGTON
+FARMYARD/M/S
+FARTHER
+FARTHEST
+FARTHING
+FASCINATE/D/G/N/S
+FASHION/D/G/S
+FASHIONABLE
+FASHIONABLY
+FAST/P/D/T/R/G/X/S
+FASTEN/D/R/Z/G/J/S
+FAT/P/S
+FATAL/Y/S
+FATALITY/M/S
+FATE/D/S
+FATHER/D/M/Y/S
+FATHERLAND
+FATHOM/D/G/S
+FATIGUE/D/G/S
+FATTEN/D/R/Z/G/S
+FATTER
+FATTEST
+FAULT/D/G/S
+FAULTLESS/Y
+FAULTY
+FAVOR/D/R/G/S
+FAVORABLE
+FAVORABLY
+FAVORITE/S
+FAWN/D/G/S
+FEAR/D/G/S
+FEARFUL/Y
+FEARLESS/P/Y
+FEASIBILITY
+FEASIBLE
+FEAST/D/G/S
+FEAT/M/S
+FEATHER/D/R/Z/G/S
+FEATHERY
+FEATURE/D/G/S
+FEBRUARY/M/S
+FED
+FEDERAL/Y/S
+FEDERATION
+FEE/S
+FEEBLE/P/T/R
+FEEBLY
+FEED/G/J/R/S/Z
+FEEDBACK
+FEEL/R/Z/G/J/S
+FEELINGLY
+FEET
+FEIGN/D/G
+FELICITY/S
+FELINE
+FELL/D/G
+FELLOW/M/S
+FELLOWSHIP/M/S
+FELT/S
+FEMALE/M/S
+FEMININE
+FEMININITY
+FEMUR/M/S
+FEN/S
+FENCE/D/R/Z/G/S
+FERMENT/D/G/S
+FERMENTATION/M/S
+FERN/M/S
+FEROCIOUS/P/Y
+FEROCITY
+FERRITE
+FERRY/D/S
+FERTILE/Y
+FERTILITY
+FERTILIZATION
+FERTILIZE/D/R/Z/G/S
+FERVENT/Y
+FERVOR/M/S
+FESTIVAL/M/S
+FESTIVE/Y
+FESTIVITY/S
+FETCH/D/G/S
+FETCHINGLY
+FETTER/D/S
+FEUD/M/S
+FEUDAL
+FEUDALISM
+FEVER/D/S
+FEVERISH/Y
+FEW/P/T/R
+FIBER/M/S
+FIBROSITY/S
+FIBROUS/Y
+FICKLE/P
+FICTION/M/S
+FICTIONAL/Y
+FICTITIOUS/Y
+FIDDLE/R/G/S
+FIDELITY
+FIELD/D/R/Z/G/S
+FIEND
+FIERCE/P/T/R/Y
+FIERY
+FIFE
+FIFO
+FIFTEEN/H/S
+FIFTH
+FIFTY/H/S
+FIG/M/S
+FIGHT/R/Z/G/S
+FIGURATIVE/Y
+FIGURE/D/G/J/S
+FILAMENT/M/S
+FILE/D/R/M/G/J/S
+FILENAME/M/S
+FILIAL
+FILL/D/R/Z/G/J/S
+FILLABLE
+FILM/D/G/S
+FILTER/D/M/G/S
+FILTH
+FILTHY/P/T/R
+FIN/M/S
+FINAL/Y/S
+FINALITY
+FINALIZATION
+FINALIZE/D/G/S
+FINANCE/D/G/S
+FINANCIAL/Y
+FINANCIER/M/S
+FIND/R/Z/G/J/S
+FINE/P/D/T/R/G/Y/S
+FINGER/D/G/J/S
+FINISH/D/R/Z/G/S
+FINITE/P/Y
+FIR
+FIRE/D/R/Z/G/J/S
+FIREARM/M/S
+FIREFLY/M/S
+FIRELIGHT
+FIREMAN
+FIREPLACE/M/S
+FIRESIDE
+FIREWOOD
+FIREWORKS
+FIRM/P/D/T/R/G/Y/S
+FIRMAMENT
+FIRMWARE
+FIRST/Y/S
+FIRSTHAND
+FISCAL/Y
+FISH/D/R/Z/G/S
+FISHERMAN
+FISHERY
+FISSURE/D
+FIST/D/S
+FIT/P/Y/S
+FITFUL/Y
+FITTED
+FITTER/M/S
+FITTING/Y/S
+FIVE/S
+FIX/D/R/Z/G/J/S
+FIXATE/D/G/N/X/S
+FIXEDLY
+FIXEDNESS
+FIXNUM
+FIXTURE/M/S
+FLAG/M/S
+FLAGGED
+FLAGGING
+FLAGRANT/Y
+FLAKE/D/G/S
+FLAME/D/R/Z/G/S
+FLAMINGO
+FLAMMABLE
+FLANK/D/R/G/S
+FLANNEL/M/S
+FLAP/M/S
+FLARE/D/G/S
+FLASH/D/R/Z/G/S
+FLASHLIGHT/M/S
+FLASK
+FLAT/P/Y/S
+FLATTEN/D/G
+FLATTER/D/R/G
+FLATTERY
+FLATTEST
+FLAUNT/D/G/S
+FLAVOR/D/G/J/S
+FLAW/D/S
+FLAWLESS/Y
+FLAX/N
+FLEA/M/S
+FLED
+FLEDGED
+FLEDGLING/M/S
+FLEE/S
+FLEECE/M/S
+FLEECY
+FLEEING
+FLEET/P/T/G/Y/S
+FLESH/D/G/Y/S
+FLESHY
+FLEW
+FLEXIBILITY/S
+FLEXIBLE
+FLEXIBLY
+FLICK/D/R/G/S
+FLICKERING
+FLIGHT/M/S
+FLINCH/D/G/S
+FLING/M/S
+FLINT
+FLIP/S
+FLIRT/D/G/S
+FLIT
+FLOAT/D/R/G/S
+FLOCK/D/G/S
+FLOOD/D/G/S
+FLOOR/D/G/J/S
+FLOP/M/S
+FLOPPILY
+FLOPPY
+FLORA
+FLORIDA
+FLORIN
+FLOSS/D/G/S
+FLOUNDER/D/G/S
+FLOUR/D
+FLOURISH/D/G/S
+FLOW/D/Z/G/S
+FLOWCHART/G/S
+FLOWER/D/G/S
+FLOWERY/P
+FLOWN
+FLUCTUATE/G/N/X/S
+FLUENT/Y
+FLUFFY/T/R
+FLUID/Y/S
+FLUIDITY
+FLUNG
+FLURRY/D
+FLUSH/D/G/S
+FLUTE/D/G
+FLUTTER/D/G/S
+FLY/R/Z/G/S
+FLYABLE
+FLYER/M/S
+FOAM/D/G/S
+FOCAL/Y
+FOCI
+FOCUS/D/G/S
+FODDER
+FOE/M/S
+FOG/M/S
+FOGGED
+FOGGILY
+FOGGING
+FOGGY/T/R
+FOIL/D/G/S
+FOLD/D/R/Z/G/S
+FOLIAGE
+FOLK/M/S
+FOLKLORE
+FOLLOW/D/R/Z/G/J/S
+FOLLY/S
+FOND/P/R/Y
+FONDLE/D/G/S
+FONT/M/S
+FOOD/M/S
+FOODSTUFF/M/S
+FOOL/D/G/S
+FOOLISH/P/Y
+FOOLPROOF
+FOOT/D/R/Z/G
+FOOTBALL/M/S
+FOOTHOLD
+FOOTMAN
+FOOTNOTE/M/S
+FOOTPRINT/M/S
+FOOTSTEP/S
+FOR/H
+FORAGE/D/G/S
+FORAY/M/S
+FORBADE
+FORBEAR/M/S
+FORBEARANCE
+FORBES
+FORBID/S
+FORBIDDEN
+FORBIDDING
+FORCE/D/R/M/G/S
+FORCEFUL/P/Y
+FORCIBLE
+FORCIBLY
+FORD/S
+FORE/T
+FOREARM/M/S
+FOREBODING
+FORECAST/D/R/Z/G/S
+FORECASTLE
+FOREFATHER/M/S
+FOREFINGER/M/S
+FOREGO/G
+FOREGOES
+FOREGONE
+FOREGROUND
+FOREHEAD/M/S
+FOREIGN/R/Z/S
+FOREMAN
+FOREMOST
+FORENOON
+FORESEE/S
+FORESEEABLE
+FORESEEN
+FORESIGHT/D
+FOREST/D/R/Z/S
+FORESTALL/D/G/S
+FORESTALLMENT
+FORETELL/G/S
+FORETOLD
+FOREVER
+FOREWARN/D/G/J/S
+FORFEIT/D
+FORGAVE
+FORGE/D/R/G/S
+FORGERY/M/S
+FORGET/S
+FORGETFUL/P
+FORGETTABLE
+FORGETTABLY
+FORGETTING
+FORGIVABLE
+FORGIVABLY
+FORGIVE/P/G/S
+FORGIVEN
+FORGIVINGLY
+FORGOT
+FORGOTTEN
+FORK/D/G/S
+FORLORN/Y
+FORM/D/R/G/S
+FORMAL/Y
+FORMALISM/M/S
+FORMALITY/S
+FORMALIZATION/M/S
+FORMALIZE/D/G/S
+FORMANT/S
+FORMAT/V/S
+FORMATION/M/S
+FORMATIVELY
+FORMATTED
+FORMATTER/M/S
+FORMATTING
+FORMERLY
+FORMIDABLE
+FORMULA/M/S
+FORMULAE
+FORMULATE/D/G/N/X/S
+FORMULATOR/M/S
+FORNICATION
+FORSAKE/G/S
+FORSAKEN
+FORT/M/S
+FORTE
+FORTHCOMING
+FORTHWITH
+FORTIFY/D/G/N/X/S
+FORTITUDE
+FORTNIGHT/Y
+FORTRAN
+FORTRESS/M/S
+FORTUITOUS/Y
+FORTUNATE/Y
+FORTUNE/M/S
+FORTY/R/H/S
+FORUM/M/S
+FORWARD/P/D/R/G/S
+FOSSIL
+FOSTER/D/G/S
+FOUGHT
+FOUL/P/D/T/G/Y/S
+FOUND/D/R/Z/G/S
+FOUNDATION/M/S
+FOUNDERED
+FOUNDRY/M/S
+FOUNT/M/S
+FOUNTAIN/M/S
+FOUR/H/S
+FOURIER
+FOURSCORE
+FOURTEEN/H/S
+FOWL/R/S
+FOX/M/S
+FRACTION/M/S
+FRACTIONAL/Y
+FRACTURE/D/G/S
+FRAGILE
+FRAGMENT/D/G/S
+FRAGMENTARY
+FRAGRANCE/M/S
+FRAGRANT/Y
+FRAIL/T
+FRAILTY
+FRAME/D/R/G/S
+FRAMEWORK/M/S
+FRANC/S
+FRANCE/M/S
+FRANCHISE/M/S
+FRANCISCO
+FRANK/P/D/T/R/G/Y/S
+FRANTIC
+FRANTICALLY
+FRATERNAL/Y
+FRATERNITY/M/S
+FRAUD/M/S
+FRAUGHT
+FRAY/D/G/S
+FREAK/M/S
+FRECKLE/D/S
+FREE/P/D/T/R/Y/S
+FREEDOM/M/S
+FREEING/S
+FREEMAN
+FREEZE/R/Z/G/S
+FREIGHT/D/R/Z/G/S
+FRENCH
+FRENZY/D
+FREQUENCY/S
+FREQUENT/D/R/Z/G/Y/S
+FRESH/P/T/R/X/Y
+FRESHEN/D/R/Z/G/S
+FRESHMAN
+FRESHMEN
+FRET
+FRETFUL/P/Y
+FRIAR/M/S
+FRICATIVE/S
+FRICTION/M/S
+FRICTIONLESS
+FRIDAY/M/S
+FRIEND/M/S
+FRIENDLESS
+FRIENDLY/P/T/R
+FRIENDSHIP/M/S
+FRIEZE/M/S
+FRIGATE/M/S
+FRIGHT/X
+FRIGHTEN/D/G/S
+FRIGHTENINGLY
+FRIGHTFUL/P/Y
+FRILL/M/S
+FRINGE/D
+FRISK/D/G/S
+FRIVOLOUS/Y
+FROCK/M/S
+FROG/M/S
+FROLIC/S
+FROM
+FRONT/D/G/S
+FRONTAL
+FRONTIER/M/S
+FROST/D/G/S
+FROSTY
+FROTH/G
+FROWN/D/G/S
+FROZE
+FROZEN/Y
+FRUGAL/Y
+FRUIT/M/S
+FRUITFUL/P/Y
+FRUITION
+FRUITLESS/Y
+FRUSTRATE/D/G/N/X/S
+FRY/D/S
+FUDGE
+FUEL/D/G/S
+FUGITIVE/M/S
+FUGUE
+FULFILL/D/G/S
+FULFILLMENT/S
+FULL/P/T/R
+FULLY
+FUMBLE/D/G
+FUME/D/G/S
+FUN
+FUNCTION/D/M/G/S
+FUNCTIONAL/Y/S
+FUNCTIONALITY/S
+FUNCTOR/M/S
+FUND/D/R/Z/G/S
+FUNDAMENTAL/Y/S
+FUNERAL/M/S
+FUNGUS
+FUNNEL/D/G/S
+FUNNILY
+FUNNY/P/T/R
+FUR/M/S
+FURIOUS/R/Y
+FURNACE/M/S
+FURNISH/D/G/J/S
+FURNITURE
+FURROW/D/S
+FURTHER/D/G/S
+FURTHERMORE
+FURTIVE/P/Y
+FURY/M/S
+FUSE/D/G/N/S
+FUSS/G
+FUTILE
+FUTILITY
+FUTURE/M/S
+FUZZY/P/R
+GABARDINE
+GABLE/D/R/S
+GAD
+GADGET/M/S
+GAG/G/S
+GAGGED
+GAGGING
+GAIETY/S
+GAILY
+GAIN/D/R/Z/G/S
+GAIT/D/R/Z
+GALAXY/M/S
+GALE
+GALL/D/G/S
+GALLANT/Y/S
+GALLANTRY
+GALLERY/D/S
+GALLEY/M/S
+GALLON/M/S
+GALLOP/D/R/G/S
+GALLOWS
+GAMBLE/D/R/Z/G/S
+GAME/P/D/G/Y/S
+GAMMA
+GANG/M/S
+GANGRENE
+GANGSTER/M/S
+GAP/M/S
+GAPE/D/G/S
+GARAGE/D/S
+GARB/D
+GARBAGE/M/S
+GARDEN/D/R/Z/G/S
+GARGLE/D/G/S
+GARLAND/D
+GARLIC
+GARMENT/M/S
+GARNER/D
+GARNET
+GARNISH
+GARRISON/D
+GARTER/M/S
+GARY/M
+GAS/M/S
+GASEOUS/Y
+GASH/M/S
+GASOLINE
+GASP/D/G/S
+GASSED
+GASSER
+GASSING/S
+GASTRIC
+GASTROINTESTINAL
+GATE/D/G/S
+GATEWAY/M/S
+GATHER/D/R/Z/G/J/S
+GAUDY/P
+GAUGE/D/S
+GAUNT/P
+GAUZE
+GAVE
+GAY/P/T/R/Y
+GAZE/D/R/Z/G/S
+GAZORCH/D/G
+GCD
+GEAR/D/G/S
+GEESE
+GEL/M/S
+GELATIN
+GELLED
+GELLING
+GEM/M/S
+GENDER/M/S
+GENE/M/S
+GENERAL/Y/S
+GENERALIST/M/S
+GENERALITY/S
+GENERALIZATION/M/S
+GENERALIZE/D/R/Z/G/S
+GENERATE/D/G/N/S/V/X
+GENERATOR/M/S
+GENERIC
+GENERICALLY
+GENEROSITY/M/S
+GENEROUS/P/Y
+GENETIC/S
+GENETICALLY
+GENEVA
+GENIAL/Y
+GENIUS/M/S
+GENRE/M/S
+GENTEEL
+GENTLE/P/T/R
+GENTLEMAN/Y
+GENTLEWOMAN
+GENTLY
+GENTRY
+GENUINE/P/Y
+GENUS
+GEOGRAPHIC
+GEOGRAPHICAL/Y
+GEOGRAPHY
+GEOLOGICAL
+GEOLOGIST/M/S
+GEOMETRIC
+GEOMETRICAL
+GEOMETRY/S
+GEORGETOWN
+GERANIUM
+GERM/M/S
+GERMAN/M/S
+GERMANE
+GERMANY
+GERMINATE/D/G/N/S
+GESTALT
+GESTURE/D/G/S
+GET/S
+GETTER/M/S
+GETTING
+GHASTLY
+GHOST/D/Y/S
+GIANT/M/S
+GIBBERISH
+GIDDY/P
+GIFT/D/S
+GIG
+GIGANTIC
+GIGGLE/D/G/S
+GILD/D/G/S
+GILL/M/S
+GILT
+GIMMICK/M/S
+GIN/M/S
+GINGER/Y
+GINGERBREAD
+GINGHAM/S
+GIPSY/M/S
+GIRAFFE/M/S
+GIRD
+GIRDER/M/S
+GIRDLE
+GIRL/M/S
+GIRT
+GIRTH
+GIVE/R/Z/G/S
+GIVEN
+GLACIAL
+GLACIER/M/S
+GLAD/P/Y
+GLADDER
+GLADDEST
+GLADE
+GLAMOROUS
+GLAMOUR
+GLANCE/D/G/S
+GLAND/M/S
+GLARE/D/G/S
+GLARINGLY
+GLASS/D/S
+GLASSY
+GLAZE/D/R/G/S
+GLEAM/D/G/S
+GLEAN/D/R/G/J/S
+GLEE/S
+GLEEFUL/Y
+GLEN/M/S
+GLIDE/D/R/Z/S
+GLIMMER/D/G/S
+GLIMPSE/D/S
+GLINT/D/G/S
+GLISTEN/D/G/S
+GLITCH/S
+GLITTER/D/G/S
+GLOBAL/Y
+GLOBE/M/S
+GLOBULAR
+GLOBULARITY
+GLOOM
+GLOOMILY
+GLOOMY
+GLORIFY/D/N/S
+GLORIOUS/Y
+GLORY/G/S
+GLOSS/D/G/S
+GLOSSARY/M/S
+GLOSSY
+GLOTTAL
+GLOVE/D/R/Z/G/S
+GLOW/D/R/Z/G/S
+GLOWINGLY
+GLUE/D/G/S
+GLYPH/S
+GNAT/M/S
+GNAW/D/G/S
+GNU
+GO/G/J
+GOAD/D
+GOAL/M/S
+GOAT/M/S
+GOATEE/M/S
+GOBBLE/D/R/Z/S
+GOBLET/M/S
+GOBLIN/M/S
+GOD/M/Y/S
+GODDESS/M/S
+GODLIKE
+GODMOTHER/M/S
+GOES
+GOLD/G/N/S
+GOLDENLY
+GOLDENNESS
+GOLDSMITH
+GOLF/R/Z/G
+GONE/R
+GONG/M/S
+GOOD/P/Y/S
+GOODY/M/S
+GOOSE
+GORDON/M
+GORE
+GORGE/G/S
+GORGEOUS/Y
+GORILLA/M/S
+GOSH
+GOSLING/M
+GOSPEL/Z/S
+GOSSIP/D/G/S
+GOT
+GOTHIC
+GOTO
+GOTTEN
+GOUGE/D/G/S
+GOURD
+GOVERN/D/G/S
+GOVERNESS
+GOVERNMENT/M/S
+GOVERNMENTAL/Y
+GOVERNOR/M/S
+GOWN/D/S
+GRAB/S
+GRABBED
+GRABBER/M/S
+GRABBING/S
+GRACE/D/G/S
+GRACEFUL/P/Y
+GRACIOUS/P/Y
+GRAD
+GRADATION/M/S
+GRADE/D/R/Z/G/J/S
+GRADIENT/M/S
+GRADUAL/Y
+GRADUATE/D/G/N/X/S
+GRAFT/D/R/G/S
+GRAHAM/M/S
+GRAIN/D/G/S
+GRAM/S
+GRAMMAR/M/S
+GRAMMATICAL/Y
+GRANARY/M/S
+GRAND/P/T/R/Y/S
+GRANDEUR
+GRANDFATHER/M/S
+GRANDIOSE
+GRANDMA
+GRANDMOTHER/M/S
+GRANDPA
+GRANDPARENT/S/M
+GRANDSON/M/S
+GRANGE
+GRANITE
+GRANNY
+GRANT/D/R/G/S
+GRANULARITY
+GRANULATE/D/G/S
+GRAPE/M/S
+GRAPH/D/M/G
+GRAPHIC/S
+GRAPHICAL/Y
+GRAPHITE
+GRAPHS
+GRAPPLE/D/G
+GRASP/D/G/S
+GRASPABLE
+GRASPING/Y
+GRASS/D/Z/S
+GRASSY/T/R
+GRATE/D/R/G/J/S
+GRATEFUL/P/Y
+GRATIFY/D/G/N
+GRATITUDE
+GRATUITOUS/P/Y
+GRATUITY/M/S
+GRAVE/P/T/R/Y/S
+GRAVEL/Y
+GRAVITATION
+GRAVITATIONAL
+GRAVITY
+GRAVY
+GRAY/P/D/T/R/G
+GRAZE/D/R/G
+GREASE/D/S
+GREASY
+GREAT/P/T/R/Y
+GREED
+GREEDILY
+GREEDY/P
+GREEK/M/S
+GREEN/P/T/R/G/Y/S
+GREENHOUSE/M/S
+GREENISH
+GREET/D/R/G/J/S
+GRENADE/M/S
+GREW
+GREY/T/G
+GRID/M/S
+GRIEF/M/S
+GRIEVANCE/M/S
+GRIEVE/D/R/Z/G/S
+GRIEVINGLY
+GRIEVOUS/Y
+GRIFFIN
+GRILL/D/G/S
+GRIM/P/D/Y
+GRIN/S
+GRIND/R/Z/G/J/S
+GRINDSTONE/M/S
+GRIP/D/G/S
+GRIPE/D/G/S
+GRIPPED
+GRIPPING/Y
+GRIT/M/S
+GRIZZLY
+GROAN/D/R/Z/G/S
+GROCER/M/S
+GROCERY/S
+GROOM/D/G/S
+GROOVE/D/S
+GROPE/D/G/S
+GROSS/P/D/T/R/G/Y/S
+GROTESQUE/Y/S
+GROTTO/M/S
+GROUND/D/R/Z/G/S
+GROUNDWORK
+GROUP/D/G/J/S
+GROUSE
+GROVE/R/Z/S
+GROVEL/D/G/S
+GROW/R/Z/G/H/S
+GROWL/D/G/S
+GROWN
+GROWNUP/M/S
+GROWTHS
+GRUB/M/S
+GRUDGE/M/S
+GRUESOME
+GRUFF/Y
+GRUMBLE/D/G/S
+GRUNT/D/G/S
+GUARANTEE/D/R/Z/S
+GUARANTEEING
+GUARANTY
+GUARD/D/G/S
+GUARDEDLY
+GUARDIAN/M/S
+GUARDIANSHIP
+GUERRILLA/M/S
+GUESS/D/G/S
+GUEST/M/S
+GUIDANCE
+GUIDE/D/G/S
+GUIDEBOOK/M/S
+GUIDELINE/M/S
+GUILD/R
+GUILE
+GUILT
+GUILTILY
+GUILTLESS/Y
+GUILTY/P/T/R
+GUINEA
+GUISE/M/S
+GUITAR/M/S
+GULCH/M/S
+GULF/M/S
+GULL/D/G/S
+GULLY/M/S
+GULP/D/S
+GUM/M/S
+GUN/M/S
+GUNFIRE
+GUNNED
+GUNNER/M/S
+GUNNING
+GUNPOWDER
+GURGLE
+GUSH/D/R/G/S
+GUST/M/S
+GUT/S
+GUTTER/D/S
+GUY/D/G/S
+GUYER/S
+GYMNASIUM/M/S
+GYMNAST/M/S
+GYMNASTIC/S
+GYPSY/M/S
+GYROSCOPE/M/S
+HA
+HABIT/M/S
+HABITAT/M/S
+HABITATION/M/S
+HABITUAL/P/Y
+HACK/D/R/Z/G/S
+HAD
+HADN'T
+HAG
+HAGGARD/Y
+HAIL/D/G/S
+HAIR/M/S
+HAIRCUT/M/S
+HAIRDRYER/M/S
+HAIRLESS
+HAIRY/P/R
+HALE/R
+HALF
+HALFTONE
+HALFWAY
+HALL/M/S
+HALLMARK/M/S
+HALLOW/D
+HALLWAY/M/S
+HALT/D/R/Z/G/S
+HALTINGLY
+HALVE/D/Z/G/S
+HAM/M/S
+HAMBURGER/M/S
+HAMLET/M/S
+HAMMER/D/G/S
+HAMMOCK/M/S
+HAMPER/D/S
+HAND/D/G/S
+HANDBAG/M/S
+HANDBOOK/M/S
+HANDCUFF/D/G/S
+HANDFUL/S
+HANDICAP/M/S
+HANDICAPPED
+HANDILY
+HANDIWORK
+HANDKERCHIEF/M/S
+HANDLE/D/R/Z/G/S
+HANDSOME/P/T/R/Y
+HANDWRITING
+HANDWRITTEN
+HANDY/P/T/R
+HANG/D/R/Z/G/S
+HANGAR/M/S
+HANGOVER/M/S
+HAP/Y
+HAPHAZARD/P/Y
+HAPLESS/P/Y
+HAPPEN/D/G/J/S
+HAPPILY
+HAPPY/P/T/R
+HARASS/D/G/S
+HARASSMENT
+HARBOR/D/G/S
+HARD/P/T/R/N/Y
+HARDCOPY
+HARDSHIP/M/S
+HARDWARE
+HARDWIRED
+HARDY/P
+HARE/M/S
+HARK/N
+HARLOT/M/S
+HARM/D/G/S
+HARMFUL/P/Y
+HARMLESS/P/Y
+HARMONIOUS/P/Y
+HARMONIZE
+HARMONY/S
+HARNESS/D/G
+HARP/R/Z/G
+HARROW/D/G/S
+HARRY/D/R
+HARSH/P/R/Y
+HART
+HARVARD
+HARVEST/D/R/G/S
+HAS
+HASH/D/R/G/S
+HASN'T
+HASTE/J
+HASTEN/D/G/S
+HASTILY
+HASTY/P
+HAT/M/S
+HATCH/D/G
+HATCHET/M/S
+HATE/D/R/G/S
+HATEFUL/P/Y
+HATRED
+HAUGHTILY
+HAUGHTY/P
+HAUL/D/R/G/S
+HAUNCH/M/S
+HAUNT/D/R/G/S
+HAVE/G/S
+HAVEN'T
+HAVEN/M/S
+HAVOC
+HAWAII
+HAWK/D/R/Z/S
+HAY/G/S
+HAZARD/M/S
+HAZARDOUS
+HAZE/M/S
+HAZEL
+HAZY/P
+HE'D
+HE'LL
+HE/D/M/V
+HEAD/D/R/Z/G/S
+HEADACHE/M/S
+HEADGEAR
+HEADING/M/S
+HEADLAND/M/S
+HEADLINE/D/G/S
+HEADLONG
+HEADQUARTERS
+HEADWAY
+HEAL/D/R/Z/G/H/S
+HEALTHFUL/P/Y
+HEALTHILY
+HEALTHY/P/T/R
+HEALY/M
+HEAP/D/G/S
+HEAR/R/Z/G/H/J/S
+HEARD
+HEARKEN
+HEARSAY
+HEART/N/S
+HEARTILY
+HEARTLESS
+HEARTY/P/T
+HEAT/D/R/Z/G/S
+HEATABLE
+HEATEDLY
+HEATH/R/N
+HEAVE/D/R/Z/G/S
+HEAVEN/Y/S
+HEAVILY
+HEAVY/P/T/R
+HEBREW
+HEDGE/D/S
+HEDGEHOG/M/S
+HEED/D/S
+HEEDLESS/P/Y
+HEEL/D/Z/G/S
+HEIDELBERG
+HEIFER
+HEIGHT/X/S
+HEIGHTEN/D/G/S
+HEINOUS/Y
+HEIR/M/S
+HEIRESS/M/S
+HELD
+HELL/M/S
+HELLO
+HELM
+HELMET/M/S
+HELP/D/R/Z/G/S
+HELPFUL/P/Y
+HELPLESS/P/Y
+HELVETICA
+HEM/M/S
+HEMISPHERE/M/S
+HEMLOCK/M/S
+HEMOSTAT/S
+HEMP/N
+HEN/M/S
+HENCE
+HENCEFORTH
+HENCHMAN
+HENCHMEN
+HER/S
+HERALD/D/G/S
+HERB/M/S
+HERBERT/M
+HERBIVORE
+HERBIVOROUS
+HERD/D/R/G/S
+HERE/M/S
+HEREABOUT/S
+HEREAFTER
+HEREBY
+HEREDITARY
+HEREDITY
+HEREIN
+HEREINAFTER
+HERESY
+HERETIC/M/S
+HERETOFORE
+HEREWITH
+HERITAGE/S
+HERMIT/M/S
+HERO
+HEROES
+HEROIC/S
+HEROICALLY
+HEROIN
+HEROINE/M/S
+HEROISM
+HERON/M/S
+HERRING/M/S
+HERSELF
+HESITANT/Y
+HESITATE/D/G/N/X/S
+HESITATINGLY
+HETEROGENEITY
+HETEROGENEOUS/P/Y
+HEURISTIC/M/S
+HEURISTICALLY
+HEW/D/R/S
+HEX
+HEXAGONAL/Y
+HEY
+HIATUS
+HICKORY
+HID
+HIDDEN
+HIDE/G/S
+HIDEOUS/P/Y
+HIDEOUT/M/S
+HIERARCHICAL/Y
+HIERARCHY/M/S
+HIGH/T/R/Y
+HIGHLAND/R/S
+HIGHLIGHT/D/G/S
+HIGHNESS/M/S
+HIGHWAY/M/S
+HIKE/D/R/G/S
+HILARIOUS/Y
+HILL/M/S
+HILLOCK
+HILLSIDE
+HILLTOP/M/S
+HILT/M/S
+HIM
+HIMSELF
+HIND/R/Z
+HINDERED
+HINDERING
+HINDRANCE/S
+HINDSIGHT
+HINGE/D/S
+HINT/D/G/S
+HIP/M/S
+HIRE/D/R/Z/G/J/S
+HIS
+HISS/D/G/S
+HISTOGRAM/M/S
+HISTORIAN/M/S
+HISTORIC
+HISTORICAL/Y
+HISTORY/M/S
+HIT/M/S
+HITCH/D/G
+HITCHHIKE/D/R/Z/G/S
+HITHER
+HITHERTO
+HITTER/M/S
+HITTING
+HOAR
+HOARD/R/G
+HOARSE/P/Y
+HOARY/P
+HOBBLE/D/G/S
+HOBBY/M/S
+HOBBYIST/M/S
+HOCKEY
+HOE/M/S
+HOG/M/S
+HOIST/D/G/S
+HOLD/R/Z/G/N/J/S
+HOLE/D/S
+HOLIDAY/M/S
+HOLISTIC
+HOLLAND
+HOLLOW/P/D/G/Y/S
+HOLLY
+HOLOCAUST
+HOLOGRAM/M/S
+HOLY/P/S
+HOMAGE
+HOME/D/R/Z/G/Y/S
+HOMELESS
+HOMEMADE
+HOMEMAKER/M/S
+HOMEOMORPHIC
+HOMEOMORPHISM/M/S
+HOMESICK/P
+HOMESPUN
+HOMESTEAD/R/Z/S
+HOMEWARD/S
+HOMEWORK
+HOMOGENEITY/M/S
+HOMOGENEOUS/P/Y
+HOMOMORPHIC
+HOMOMORPHISM/M/S
+HONE/D/T/R/G/S
+HONESTLY
+HONESTY
+HONEY
+HONEYCOMB/D
+HONEYMOON/D/R/Z/G/S
+HONEYSUCKLE
+HONG
+HONOLULU
+HONOR/D/R/G/S
+HONORABLE/P
+HONORABLY
+HONORARY/S
+HOOD/D/S
+HOODWINK/D/G/S
+HOOF/M/S
+HOOK/D/R/Z/G/S
+HOOP/R/S
+HOOT/D/R/G/S
+HOOVER/M
+HOP/S
+HOPE/D/G/S
+HOPEFUL/P/Y/S
+HOPELESS/P/Y
+HOPPER/M/S
+HORDE/M/S
+HORIZON/M/S
+HORIZONTAL/Y
+HORMONE/M/S
+HORN/D/S
+HORNET/M/S
+HORRENDOUS/Y
+HORRIBLE/P
+HORRIBLY
+HORRID/Y
+HORRIFY/D/G/S
+HORROR/M/S
+HORSE/Y/S
+HORSEBACK
+HORSEMAN
+HORSEPOWER
+HORSESHOE/R
+HOSE/M/S
+HOSPITABLE
+HOSPITABLY
+HOSPITAL/M/S
+HOSPITALITY
+HOSPITALIZE/D/G/S
+HOST/D/G/S
+HOSTAGE/M/S
+HOSTESS/M/S
+HOSTILE/Y
+HOSTILITY/S
+HOT/P/Y
+HOTEL/M/S
+HOTTER
+HOTTEST
+HOUND/D/G/S
+HOUR/Y/S
+HOUSE/D/G/S
+HOUSEFLY/M/S
+HOUSEHOLD/R/Z/S
+HOUSEKEEPER/M/S
+HOUSEKEEPING
+HOUSETOP/M/S
+HOUSEWIFE/Y
+HOUSEWORK
+HOUSTON
+HOVEL/M/S
+HOVER/D/G/S
+HOW
+HOWARD
+HOWEVER
+HOWL/D/R/G/S
+HUB/M/S
+HUBRIS
+HUDDLE/D/G
+HUDSON
+HUE/M/S
+HUG
+HUGE/P/Y
+HUH
+HULL/M/S
+HUM/S
+HUMAN/P/Y/S
+HUMANE/P/Y
+HUMANITY/M/S
+HUMBLE/P/D/T/R/G
+HUMBLY
+HUMID/Y
+HUMIDIFY/D/R/Z/G/N/S
+HUMIDITY
+HUMILIATE/D/G/N/X/S
+HUMILITY
+HUMMED
+HUMMING
+HUMOR/D/R/Z/G/S
+HUMOROUS/P/Y
+HUMP/D
+HUNCH/D/S
+HUNDRED/H/S
+HUNG/R/Z
+HUNGER/D/G
+HUNGRILY
+HUNGRY/T/R
+HUNK/M/S
+HUNT/D/R/Z/G/S
+HUNTSMAN
+HURL/D/R/Z/G
+HURRAH
+HURRICANE/M/S
+HURRIEDLY
+HURRY/D/G/S
+HURT/G/S
+HUSBAND/M/S
+HUSBANDRY
+HUSH/D/G/S
+HUSK/D/R/G/S
+HUSKY/P
+HUSTLE/D/R/G/S
+HUT/M/S
+HYACINTH
+HYATT
+HYBRID
+HYDRAULIC
+HYDRODYNAMIC/S
+HYDROGEN/M/S
+HYGIENE
+HYMN/M/S
+HYPER
+HYPERBOLIC
+HYPERCUBE/S
+HYPERMEDIA
+HYPERTEXT
+HYPERTEXTUAL
+HYPHEN/M/S
+HYPOCRISY/S
+HYPOCRITE/M/S
+HYPODERMIC/S
+HYPOTHESES
+HYPOTHESIS
+HYPOTHESIZE/D/R/G/S
+HYPOTHETICAL/Y
+HYSTERESIS
+HYSTERICAL/Y
+I'D
+I'LL
+I'M
+I'VE
+IBM
+ICE/D/G/J/S
+ICEBERG/M/S
+ICON/S
+ICONIC
+ICONOCLASTIC
+ICY/P
+IDEA/M/S
+IDEAL/Y/S
+IDEALISM
+IDEALISTIC
+IDEALIZATION/M/S
+IDEALIZE/D/G/S
+IDENTICAL/Y
+IDENTIFIABLE
+IDENTIFIABLY
+IDENTIFY/D/R/Z/G/N/X/S
+IDENTITY/M/S
+IDEOLOGICAL/Y
+IDEOLOGY/S
+IDIOM/S
+IDIOMATIC
+IDIOSYNCRASY/M/S
+IDIOSYNCRATIC
+IDIOT/M/S
+IDIOTIC
+IDLE/P/D/T/R/G/S
+IDLERS
+IDLY
+IDOL/M/S
+IDOLATRY
+IEEE
+IF
+IGNITION
+IGNOBLE
+IGNORANCE
+IGNORANT/Y
+IGNORE/D/G/S
+III
+ILL/S
+ILLEGAL/Y
+ILLEGALITY/S
+ILLICIT/Y
+ILLINOIS
+ILLITERATE
+ILLNESS/M/S
+ILLOGICAL/Y
+ILLUMINATE/D/G/N/X/S
+ILLUSION/M/S
+ILLUSIVE/Y
+ILLUSTRATE/D/G/N/X/V/S
+ILLUSTRATIVELY
+ILLUSTRATOR/M/S
+ILLUSTRIOUS/P
+ILLY
+IMAGE/G/S
+IMAGINABLE
+IMAGINABLY
+IMAGINARY
+IMAGINATION/M/S
+IMAGINATIVE/Y
+IMAGINE/D/G/J/S
+IMBALANCE/S
+IMITATE/D/G/N/X/V/S
+IMMACULATE/Y
+IMMATERIAL/Y
+IMMATURE
+IMMATURITY
+IMMEDIACY/S
+IMMEDIATE/Y
+IMMEMORIAL
+IMMENSE/Y
+IMMERSE/D/N/S
+IMMIGRANT/M/S
+IMMIGRATE/D/G/N/S
+IMMINENT/Y
+IMMORTAL/Y
+IMMORTALITY
+IMMOVABILITY
+IMMOVABLE
+IMMOVABLY
+IMMUNE
+IMMUNITY/M/S
+IMMUTABLE
+IMP
+IMPACT/D/G/S
+IMPACTION
+IMPACTOR/M/S
+IMPAIR/D/G/S
+IMPART/D/S
+IMPARTIAL/Y
+IMPASSE/V
+IMPATIENCE
+IMPATIENT/Y
+IMPEACH
+IMPEDANCE/M/S
+IMPEDE/D/G/S
+IMPEDIMENT/M/S
+IMPEL
+IMPENDING
+IMPENETRABILITY
+IMPENETRABLE
+IMPENETRABLY
+IMPERATIVE/Y/S
+IMPERFECT/Y
+IMPERFECTION/M/S
+IMPERIAL
+IMPERIALISM
+IMPERIALIST/M/S
+IMPERIL/D
+IMPERIOUS/Y
+IMPERMANENCE
+IMPERMANENT
+IMPERMISSIBLE
+IMPERSONAL/Y
+IMPERSONATE/D/G/N/X/S
+IMPERTINENT/Y
+IMPERVIOUS/Y
+IMPETUOUS/Y
+IMPETUS
+IMPINGE/D/G/S
+IMPIOUS
+IMPLANT/D/G/S
+IMPLAUSIBLE
+IMPLEMENT/D/G/S
+IMPLEMENTABLE
+IMPLEMENTATION/M/S
+IMPLEMENTOR/M/S
+IMPLICANT/M/S
+IMPLICATE/D/G/N/X/S
+IMPLICIT/P/Y
+IMPLORE/D/G
+IMPLY/D/G/N/X/S
+IMPORT/D/R/Z/G/S
+IMPORTANCE
+IMPORTANT/Y
+IMPORTATION
+IMPOSE/D/G/S
+IMPOSITION/M/S
+IMPOSSIBILITY/S
+IMPOSSIBLE
+IMPOSSIBLY
+IMPOSTOR/M/S
+IMPOTENCE
+IMPOTENT
+IMPOVERISH/D
+IMPOVERISHMENT
+IMPRACTICABLE
+IMPRACTICAL/Y
+IMPRACTICALITY
+IMPRECISE/N/Y
+IMPREGNABLE
+IMPRESS/D/R/G/V/S
+IMPRESSION/M/S
+IMPRESSIONABLE
+IMPRESSIONIST
+IMPRESSIONISTIC
+IMPRESSIVE/P/Y
+IMPRESSMENT
+IMPRINT/D/G/S
+IMPRISON/D/G/S
+IMPRISONMENT/M/S
+IMPROBABLE
+IMPROMPTU
+IMPROPER/Y
+IMPROVE/D/G/S
+IMPROVEMENT/S
+IMPROVISATION/M/S
+IMPROVISATIONAL
+IMPROVISE/D/R/Z/G/S
+IMPUDENT/Y
+IMPULSE/N/V/S
+IMPUNITY
+IMPURE
+IMPURITY/M/S
+IMPUTE/D
+IN
+INABILITY
+INACCESSIBLE
+INACCURACY/S
+INACCURATE
+INACTIVE
+INACTIVITY
+INADEQUACY/S
+INADEQUATE/P/Y
+INADMISSIBILITY
+INADVERTENT/Y
+INADVISABLE
+INANIMATE/Y
+INAPPLICABLE
+INAPPROPRIATE/P
+INASMUCH
+INAUGURAL
+INAUGURATE/D/G/N
+INC
+INCAPABLE
+INCAPACITATING
+INCARNATION/M/S
+INCENDIARY/S
+INCENSE/D/S
+INCENTIVE/M/S
+INCEPTION
+INCESSANT/Y
+INCH/D/G/S
+INCIDENCE
+INCIDENT/M/S
+INCIDENTAL/Y/S
+INCIPIENT
+INCITE/D/G/S
+INCLINATION/M/S
+INCLINE/D/G/S
+INCLOSE/D/G/S
+INCLUDE/D/G/S
+INCLUSION/M/S
+INCLUSIVE/P/Y
+INCOHERENT/Y
+INCOME/G/S
+INCOMMENSURATE
+INCOMPARABLE
+INCOMPARABLY
+INCOMPATIBILITY/M/S
+INCOMPATIBLE
+INCOMPATIBLY
+INCOMPETENCE
+INCOMPETENT/M/S
+INCOMPLETE/P/Y
+INCOMPREHENSIBILITY
+INCOMPREHENSIBLE
+INCOMPREHENSIBLY
+INCONCEIVABLE
+INCONCLUSIVE
+INCONSEQUENTIAL/Y
+INCONSIDERATE/P/Y
+INCONSISTENCY/M/S
+INCONSISTENT/Y
+INCONVENIENCE/D/G/S
+INCONVENIENT/Y
+INCORPORATE/D/G/N/S
+INCORRECT/P/Y
+INCREASE/D/G/S
+INCREASINGLY
+INCREDIBLE
+INCREDIBLY
+INCREDULOUS/Y
+INCREMENT/D/G/S
+INCREMENTAL/Y
+INCUBATE/D/G/N/S
+INCUBATOR/M/S
+INCUR/S
+INCURABLE
+INCURRED
+INCURRING
+INDEBTED/P
+INDECISION
+INDEED
+INDEFINITE/P/Y
+INDEMNITY
+INDENT/D/G/S
+INDENTATION/M/S
+INDEPENDENCE
+INDEPENDENT/Y/S
+INDESCRIBABLE
+INDETERMINACY/M/S
+INDETERMINATE/Y
+INDEX/D/G/S
+INDEXABLE
+INDIA
+INDIAN/M/S
+INDIANA
+INDICATE/D/G/N/X/V/S
+INDICATOR/M/S
+INDICES
+INDICTMENT/M/S
+INDIFFERENCE
+INDIFFERENT/Y
+INDIGENOUS/P/Y
+INDIGESTION
+INDIGNANT/Y
+INDIGNATION
+INDIGNITY/S
+INDIGO
+INDIRECT/D/G/Y/S
+INDIRECTION/S
+INDISCRIMINATE/Y
+INDISPENSABILITY
+INDISPENSABLE
+INDISPENSABLY
+INDISTINGUISHABLE
+INDIVIDUAL/M/Y/S
+INDIVIDUALISTIC
+INDIVIDUALITY
+INDIVIDUALIZE/D/G/S
+INDIVISIBILITY
+INDIVISIBLE
+INDOCTRINATE/D/G/N/S
+INDOLENT/Y
+INDOMITABLE
+INDOOR/S
+INDUCE/D/R/G/S
+INDUCEMENT/M/S
+INDUCT/D/G/S
+INDUCTANCE/S
+INDUCTION/M/S
+INDUCTIVE/Y
+INDUCTOR/M/S
+INDULGE/D/G
+INDULGENCE/M/S
+INDUSTRIAL/Y/S
+INDUSTRIALIST/M/S
+INDUSTRIALIZATION
+INDUSTRIOUS/P/Y
+INDUSTRY/M/S
+INEFFECTIVE/P/Y
+INEFFICIENCY/S
+INEFFICIENT/Y
+INELEGANT
+INEQUALITY/S
+INERT/P/Y
+INERTIA
+INESCAPABLE
+INESCAPABLY
+INESSENTIAL
+INESTIMABLE
+INEVITABILITY/S
+INEVITABLE
+INEVITABLY
+INEXACT
+INEXCUSABLE
+INEXCUSABLY
+INEXORABLE
+INEXORABLY
+INEXPENSIVE/Y
+INEXPERIENCE/D
+INEXPLICABLE
+INFALLIBILITY
+INFALLIBLE
+INFALLIBLY
+INFAMOUS/Y
+INFANCY
+INFANT/M/S
+INFANTRY
+INFEASIBLE
+INFECT/D/G/V/S
+INFECTION/M/S
+INFECTIOUS/Y
+INFER/S
+INFERENCE/M/S
+INFERENTIAL
+INFERIOR/M/S
+INFERIORITY
+INFERNAL/Y
+INFERNO/M/S
+INFERRED
+INFERRING
+INFEST/D/G/S
+INFIDEL/M/S
+INFINITE/P/Y
+INFINITESIMAL
+INFINITIVE/M/S
+INFINITUM
+INFINITY
+INFIRMITY
+INFIX
+INFLAME/D
+INFLAMMABLE
+INFLATABLE
+INFLATE/D/G/N/S
+INFLATIONARY
+INFLEXIBILITY
+INFLEXIBLE
+INFLICT/D/G/S
+INFLUENCE/D/G/S
+INFLUENTIAL/Y
+INFLUENZA
+INFO
+INFORM/D/R/Z/G/S
+INFORMAL/Y
+INFORMALITY
+INFORMANT/M/S
+INFORMATION
+INFORMATIONAL
+INFORMATIVE/Y
+INFREQUENT/Y
+INFRINGE/D/G/S
+INFRINGEMENT/M/S
+INFURIATE/D/G/N/S
+INFUSE/D/G/N/X/S
+INGENIOUS/P/Y
+INGENUITY
+INGRATITUDE
+INGREDIENT/M/S
+INGRES
+INHABIT/D/G/S
+INHABITABLE
+INHABITANCE
+INHABITANT/M/S
+INHALE/D/R/G/S
+INHERE/S
+INHERENT/Y
+INHERIT/D/G/S
+INHERITABLE
+INHERITANCE/M/S
+INHERITOR/M/S
+INHERITRESS/M/S
+INHERITRICES
+INHERITRIX
+INHIBIT/D/G/S
+INHIBITION/M/S
+INHIBITORS
+INHIBITORY
+INHOMOGENEITY/S
+INHUMAN
+INHUMANE
+INIQUITY/M/S
+INITIAL/D/G/Y/S
+INITIALIZATION/M/S
+INITIALIZE/D/R/Z/G/S
+INITIATE/D/G/N/X/V/S
+INITIATIVE/M/S
+INITIATOR/M/S
+INJECT/D/G/V/S
+INJECTION/M/S
+INJUNCTION/M/S
+INJURE/D/G/S
+INJURIOUS
+INJURY/M/S
+INJUSTICE/M/S
+INK/D/R/Z/G/J/S
+INKLING/M/S
+INLAID
+INLAND
+INLET/M/S
+INLINE
+INMATE/M/S
+INN/R/G/J/S
+INNARDS
+INNATE/Y
+INNERMOST
+INNOCENCE
+INNOCENT/Y/S
+INNOCUOUS/P/Y
+INNOVATE/N/X/V
+INNOVATION/M/S
+INNUMERABILITY
+INNUMERABLE
+INNUMERABLY
+INORDINATE/Y
+INPUT/M/S
+INQUIRE/D/R/Z/G/S
+INQUIRY/M/S
+INQUISITION/M/S
+INQUISITIVE/P/Y
+INROAD/S
+INSANE/Y
+INSANITY
+INSCRIBE/D/G/S
+INSCRIPTION/M/S
+INSECT/M/S
+INSECURE/Y
+INSENSIBLE
+INSENSITIVE/Y
+INSENSITIVITY
+INSEPARABLE
+INSERT/D/G/S
+INSERTION/M/S
+INSIDE/R/Z/S
+INSIDIOUS/P/Y
+INSIGHT/M/S
+INSIGNIA
+INSIGNIFICANCE
+INSIGNIFICANT
+INSINUATE/D/G/N/X/S
+INSIST/D/G/S
+INSISTENCE
+INSISTENT/Y
+INSOFAR
+INSOLENCE
+INSOLENT/Y
+INSOLUBLE
+INSPECT/D/G/S
+INSPECTION/M/S
+INSPECTOR/M/S
+INSPIRATION/M/S
+INSPIRE/D/R/G/S
+INSTABILITY/S
+INSTALL/D/R/Z/G/S
+INSTALLATION/M/S
+INSTALLMENT/M/S
+INSTANCE/S
+INSTANT/R/Y/S
+INSTANTANEOUS/Y
+INSTANTIATE/D/G/N/X/S
+INSTANTIATION/M/S
+INSTEAD
+INSTIGATE/D/G/S
+INSTIGATOR/M/S
+INSTINCT/M/V/S
+INSTINCTIVELY
+INSTITUTE/D/R/Z/G/N/X/S
+INSTITUTIONAL/Y
+INSTITUTIONALIZE/D/G/S
+INSTRUCT/D/G/V/S
+INSTRUCTION/M/S
+INSTRUCTIONAL
+INSTRUCTIVELY
+INSTRUCTOR/M/S
+INSTRUMENT/D/G/S
+INSTRUMENTAL/Y/S
+INSTRUMENTALIST/M/S
+INSTRUMENTATION
+INSUFFICIENT/Y
+INSULATE/D/G/N/S
+INSULATOR/M/S
+INSULT/D/G/S
+INSUPERABLE
+INSURANCE
+INSURE/D/R/Z/G/S
+INSURGENT/M/S
+INSURMOUNTABLE
+INSURRECTION/M/S
+INTACT
+INTANGIBLE/M/S
+INTEGER/M/S
+INTEGRAL/M/S
+INTEGRATE/D/G/N/X/V/S
+INTEGRITY
+INTELLECT/M/S
+INTELLECTUAL/Y/S
+INTELLIGENCE
+INTELLIGENT/Y
+INTELLIGIBILITY
+INTELLIGIBLE
+INTELLIGIBLY
+INTEND/D/G/S
+INTENSE/V/Y
+INTENSIFY/D/R/Z/G/N/S
+INTENSITY/S
+INTENSIVELY
+INTENT/P/Y/S
+INTENTION/D/S
+INTENTIONAL/Y
+INTER
+INTERACT/D/G/V/S
+INTERACTION/M/S
+INTERACTIVELY
+INTERACTIVITY
+INTERCEPT/D/G/S
+INTERCHANGE/D/G/J/S
+INTERCHANGEABILITY
+INTERCHANGEABLE
+INTERCHANGEABLY
+INTERCITY
+INTERCOMMUNICATE/D/G/N/S
+INTERCONNECT/D/G/S
+INTERCONNECTION/M/S
+INTERCOURSE
+INTERDEPENDENCE
+INTERDEPENDENCY/S
+INTERDEPENDENT
+INTERDISCIPLINARY
+INTEREST/D/G/S
+INTERESTINGLY
+INTERFACE/D/R/G/S
+INTERFERE/D/G/S
+INTERFERENCE/S
+INTERFERINGLY
+INTERIM
+INTERIOR/M/S
+INTERLACE/D/G/S
+INTERLEAVE/D/G/S
+INTERLINK/D/S
+INTERLISP
+INTERMEDIARY
+INTERMEDIATE/M/S
+INTERMINABLE
+INTERMINGLE/D/G/S
+INTERMITTENT/Y
+INTERMIXED
+INTERMODULE
+INTERN/D/S
+INTERNAL/Y/S
+INTERNALIZE/D/G/S
+INTERNATIONAL/Y
+INTERNATIONALITY
+INTERNET
+INTERNIST
+INTERPERSONAL
+INTERPLAY
+INTERPOLATE/D/G/N/X/S
+INTERPOSE/D/G/S
+INTERPRET/D/R/Z/G/V/S
+INTERPRETABLE
+INTERPRETATION/M/S
+INTERPRETIVELY
+INTERPROCESS
+INTERRELATE/D/G/N/X/S
+INTERRELATIONSHIP/M/S
+INTERROGATE/D/G/N/X/V/S
+INTERRUPT/D/G/V/S
+INTERRUPTIBLE
+INTERRUPTION/M/S
+INTERSECT/D/G/S
+INTERSECTION/M/S
+INTERSPERSE/D/G/N/S
+INTERSTAGE
+INTERSTATE
+INTERTEXUALITY
+INTERTWINE/D/G/S
+INTERVAL/M/S
+INTERVENE/D/G/S
+INTERVENTION/M/S
+INTERVIEW/D/R/Z/G/S
+INTERWOVEN
+INTESTINAL
+INTESTINE/M/S
+INTIMACY
+INTIMATE/D/G/N/X/Y
+INTIMIDATE/D/G/N/S
+INTO
+INTOLERABLE
+INTOLERABLY
+INTOLERANCE
+INTOLERANT
+INTONATION/M/S
+INTOXICATE/D/G/N
+INTRA
+INTRACTABILITY
+INTRACTABLE
+INTRACTABLY
+INTRAMURAL
+INTRANSIGENT
+INTRANSITIVE/Y
+INTRAPROCESS
+INTRICACY/S
+INTRICATE/Y
+INTRIGUE/D/G/S
+INTRINSIC
+INTRINSICALLY
+INTRODUCE/D/G/S
+INTRODUCTION/M/S
+INTRODUCTORY
+INTROSPECT/V
+INTROSPECTION/S
+INTROVERT/D
+INTRUDE/D/R/G/S
+INTRUDER/M/S
+INTRUSION/M/S
+INTRUST
+INTUBATE/D/N/S
+INTUITION/M/S
+INTUITIONIST
+INTUITIVE/Y
+INTUITIVENESS
+INVADE/D/R/Z/G/S
+INVALID/Y/S
+INVALIDATE/D/G/N/X/S
+INVALIDITY/S
+INVALUABLE
+INVARIABLE
+INVARIABLY
+INVARIANCE
+INVARIANT/Y/S
+INVASION/M/S
+INVENT/D/G/V/S
+INVENTION/M/S
+INVENTIVELY
+INVENTIVENESS
+INVENTOR/M/S
+INVENTORY/M/S
+INVERSE/N/X/Y/S
+INVERT/D/R/Z/G/S
+INVERTEBRATE/M/S
+INVERTIBLE
+INVEST/D/G/S
+INVESTIGATE/D/G/N/X/V/S
+INVESTIGATOR/M/S
+INVESTMENT/M/S
+INVESTOR/M/S
+INVINCIBLE
+INVISIBILITY
+INVISIBLE
+INVISIBLY
+INVITATION/M/S
+INVITE/D/G/S
+INVOCABLE
+INVOCATION/M/S
+INVOICE/D/G/S
+INVOKE/D/R/G/S
+INVOLUNTARILY
+INVOLUNTARY
+INVOLVE/D/G/S
+INVOLVEMENT/M/S
+INWARD/P/Y/S
+IODINE
+ION/S
+IPC
+IQ
+IRATE/P/Y
+IRE/M/S
+IRELAND/M
+IRIS
+IRK/D/G/S
+IRKSOME
+IRON/D/G/J/S
+IRONICAL/Y
+IRONY/S
+IRRATIONAL/Y/S
+IRRECOVERABLE
+IRREDUCIBLE
+IRREDUCIBLY
+IRREFLEXIVE
+IRREFUTABLE
+IRREGULAR/Y/S
+IRREGULARITY/S
+IRRELEVANCE/S
+IRRELEVANT/Y
+IRREPRESSIBLE
+IRRESISTIBLE
+IRRESPECTIVE/Y
+IRRESPONSIBLE
+IRRESPONSIBLY
+IRREVERSIBLE
+IRRIGATE/D/G/N/S
+IRRITATE/D/G/N/X/S
+IS
+ISLAND/R/Z/S
+ISLE/M/S
+ISLET/M/S
+ISN'T
+ISOLATE/D/G/N/X/S
+ISOMETRIC
+ISOMORPHIC
+ISOMORPHICALLY
+ISOMORPHISM/M/S
+ISOTOPE/M/S
+ISRAEL
+ISSUANCE
+ISSUE/D/R/Z/G/S
+ISTHMUS
+IT/M
+ITALIAN/M/S
+ITALIC/S
+ITALICIZE/D
+ITALY
+ITCH/G/S
+ITEM/M/S
+ITEMIZATION/M/S
+ITEMIZE/D/G/S
+ITERATE/D/G/N/X/V/S
+ITERATIVE/Y
+ITERATOR/M/S
+ITS
+ITSELF
+ITT
+IV
+IVORY
+IVY/M/S
+JAB/M/S
+JABBED
+JABBING
+JACK
+JACKET/D/S
+JADE/D
+JAIL/D/R/Z/G/S
+JAM/S
+JAMES
+JAMMED
+JAMMING
+JANITOR/M/S
+JANUARY/M/S
+JAPAN
+JAPANESE
+JAR/M/S
+JARGON
+JARRED
+JARRING/Y
+JASMINE/M
+JAUNDICE
+JAUNT/M/S
+JAUNTY/P
+JAVELIN/M/S
+JAW/M/S
+JAY
+JAZZ
+JEALOUS/Y
+JEALOUSY/S
+JEAN/M/S
+JEEP/M/S
+JEER/M/S
+JELLY/M/S
+JELLYFISH
+JENNY
+JEOPARDIZE/D/G/S
+JERK/D/G/J/S
+JERKY/P
+JERSEY/M/S
+JEST/D/R/G/S
+JET/M/S
+JETTED
+JETTING
+JEWEL/D/R/S
+JEWELRY/S
+JIG/M/S
+JILL
+JIM/M
+JINGLE/D/G
+JOAN/M
+JOB/M/S
+JOCUND
+JOE/M
+JOG/S
+JOHN/M
+JOIN/D/R/Z/G/S
+JOINT/M/Y/S
+JOKE/D/R/Z/G/S
+JOLLY
+JOLT/D/G/S
+JOSE/M
+JOSTLE/D/G/S
+JOT/S
+JOTTED
+JOTTING
+JOURNAL/M/S
+JOURNALISM
+JOURNALIST/M/S
+JOURNALIZE/D/G/S
+JOURNEY/D/G/J/S
+JOUST/D/G/S
+JOY/M/S
+JOYFUL/Y
+JOYOUS/P/Y
+JOYSTICK
+JR
+JUBILEE
+JUDGE/D/G/S
+JUDGMENT/M/S
+JUDICABLE
+JUDICIAL
+JUDICIARY
+JUDICIOUS/Y
+JUDY/M
+JUG/M/S
+JUGGLE/R/Z/G/S
+JUICE/M/S
+JUICY/T
+JULY/M/S
+JUMBLE/D/S
+JUMP/D/R/Z/G/S
+JUMPY
+JUNCTION/M/S
+JUNCTURE/M/S
+JUNE
+JUNGLE/M/S
+JUNIOR/M/S
+JUNIPER
+JUNK/R/Z/S
+JURISDICTION/M/S
+JUROR/M/S
+JURY/M/S
+JUST/P/Y
+JUSTICE/M/S
+JUSTIFIABLE
+JUSTIFIABLY
+JUSTIFIER'S
+JUSTIFY/D/R/Z/G/N/X/S
+JUT
+JUVENILE/M/S
+JUXTAPOSE/D/G/S
+KAISER
+KANJI
+KEEL/D/G/S
+KEEN/P/T/R/Y
+KEEP/R/Z/G/S
+KEN
+KENNEL/M/S
+KEPT
+KERCHIEF/M/S
+KERNEL/M/S
+KERNING
+KEROSENE
+KETCHUP
+KETTLE/M/S
+KEY/D/G/S
+KEYBOARD/M/S
+KEYNOTE
+KEYPAD/M/S
+KEYSTROKE/M/S
+KEYWORD/M/S
+KICK/D/R/Z/G/S
+KID/M/S
+KIDDED
+KIDDING
+KIDNAP/S/R/D/G/M
+KIDNAPPED
+KIDNAPPER/M/S
+KIDNAPPING/M/S
+KIDNEY/M/S
+KILL/D/R/Z/G/J/S
+KILLINGLY
+KILOGRAM/S
+KILOMETER/S
+KIN
+KIND/P/T/R/Y/S
+KINDERGARTEN
+KINDHEARTED
+KINDLE/D/G/S
+KINDRED
+KING/Y/S
+KINGDOM/M/S
+KINSHIP
+KINSMAN
+KISS/D/R/Z/G/S
+KIT/M/S
+KITCHEN/M/S
+KITE/D/G/S
+KITTEN/M/S
+KITTY
+KLUDGES
+KNACK
+KNAPSACK/M/S
+KNAVE/M/S
+KNEAD/S
+KNEE/D/S
+KNEEING
+KNEEL/D/G/S
+KNELL/M/S
+KNELT
+KNEW
+KNICKERBOCKER/M/S
+KNIFE/D/G/S
+KNIGHT/D/G/Y/S
+KNIGHTHOOD
+KNIT/S
+KNIVES
+KNOB/M/S
+KNOCK/D/R/Z/G/S
+KNOLL/M/S
+KNOT/M/S
+KNOTTED
+KNOTTING
+KNOW/R/G/S
+KNOWABLE
+KNOWHOW
+KNOWINGLY
+KNOWLEDGE
+KNOWLEDGEABLE
+KNOWN
+KNUCKLE/D/S
+KONG
+KYOTO
+LAB/M/S
+LABEL/S/D/R/G/M
+LABOR/D/R/Z/G/J/S
+LABORATORY/M/S
+LABORIOUS/Y
+LABYRINTH
+LABYRINTHS
+LACE/D/G/S
+LACERATE/D/G/N/X/S
+LACK/D/G/S
+LACQUER/D/S
+LAD/G/N/S
+LADDER
+LADLE
+LADY/M/S
+LAG/R/Z/S
+LAGOON/M/S
+LAGRANGIAN
+LAID
+LAIN
+LAIR/M/S
+LAKE/M/S
+LAMB/M/S
+LAMBDA
+LAME/P/D/G/Y/S
+LAMENT/D/G/S
+LAMENTABLE
+LAMENTATION/M/S
+LAMINAR
+LAMP/M/S
+LANCE/D/R/S
+LANCHESTER
+LAND/D/R/Z/G/J/S
+LANDLADY/M/S
+LANDLORD/M/S
+LANDMARK/M/S
+LANDOWNER/M/S
+LANDSCAPE/D/G/S
+LANE/M/S
+LANGUAGE/M/S
+LANGUID/P/Y
+LANGUISH/D/G/S
+LANSING
+LANTERN/M/S
+LAP/M/S
+LAPEL/M/S
+LAPIDARY
+LAPSE/D/G/S
+LARD/R
+LARGE/P/T/R/Y
+LARK/M/S
+LARVA
+LARVAE
+LAS
+LASER/M/S
+LASH/D/G/J/S
+LASS/M/S
+LAST/D/G/Y/S
+LATCH/D/G/S
+LATE/P/T/R/Y
+LATENCY
+LATENT
+LATERAL/Y
+LATITUDE/M/S
+LATRINE/M/S
+LATTER/Y
+LATTICE/M/S
+LAUGH/D/G
+LAUGHABLE
+LAUGHABLY
+LAUGHINGLY
+LAUGHS
+LAUGHTER
+LAUNCH/D/R/G/J/S
+LAUNDER/D/R/G/J/S
+LAUNDRY
+LAURA/M
+LAUREL/M/S
+LAVA
+LAVATORY/M/S
+LAVENDER
+LAVISH/D/G/Y
+LAW/M/S
+LAWFUL/Y
+LAWLESS/P
+LAWN/M/S
+LAWRENCE/M
+LAWSUIT/M/S
+LAWYER/M/S
+LAY/G/S
+LAYER/D/G/S
+LAYMAN
+LAYMEN
+LAYOFFS
+LAYOUT/M/S
+LAZED
+LAZILY
+LAZING
+LAZY/P/T/R
+LEAD/D/R/Z/G/N/J/S
+LEADERSHIP/M/S
+LEAF/D/G
+LEAFLESS
+LEAFLET/M/S
+LEAFY/T
+LEAGUE/D/R/Z/S
+LEAK/D/G/S
+LEAKAGE/M/S
+LEAN/P/D/T/R/G/S
+LEAP/D/G/S
+LEAPT
+LEARN/D/R/Z/G/S
+LEASE/D/G/S
+LEASH/M/S
+LEAST
+LEATHER/D/S
+LEATHERN
+LEAVE/D/G/J/S
+LEAVEN/D/G
+LECTURE/D/R/Z/G/S
+LED
+LEDGE/R/Z/S
+LEE/R/S
+LEECH/M/S
+LEFT
+LEFTIST/M/S
+LEFTMOST
+LEFTOVER/M/S
+LEFTWARD
+LEG/S
+LEGACY/M/S
+LEGAL/Y
+LEGALITY
+LEGALIZATION
+LEGALIZE/D/G/S
+LEGEND/M/S
+LEGENDARY
+LEGGED
+LEGGINGS
+LEGIBILITY
+LEGIBLE
+LEGIBLY
+LEGION/M/S
+LEGISLATE/D/G/N/V/S
+LEGISLATOR/M/S
+LEGISLATURE/M/S
+LEGITIMACY
+LEGITIMATE/Y
+LEGUME/S
+LEISURE/Y
+LEMMA/M/S
+LEMON/M/S
+LEMONADE
+LEND/R/Z/G/S
+LENGTH/N/Y
+LENGTHEN/D/G/S
+LENGTHS
+LENGTHWISE
+LENGTHY
+LENIENCY
+LENIENT/Y
+LENS/M/S
+LENT/N
+LENTIL/M/S
+LEOPARD/M/S
+LEPROSY
+LESS/R
+LESSEN/D/G/S
+LESSON/M/S
+LEST/R
+LET/M/S
+LETTER/D/R/G/S
+LETTING
+LETTUCE
+LEUKEMIA
+LEVEE/M/S
+LEVEL/P/D/R/G/Y/S/T
+LEVELLED
+LEVELLER
+LEVELLEST
+LEVELLING
+LEVER/M/S
+LEVERAGE
+LEVY/D/G/S
+LEWD/P/Y
+LEXIA/S
+LEXICAL/Y
+LEXICOGRAPHIC
+LEXICOGRAPHICAL/Y
+LEXICON/M/S
+LIABILITY/M/S
+LIABLE
+LIAISON/M/S
+LIAR/M/S
+LIBERAL/Y/S
+LIBERALIZE/D/G/S
+LIBERATE/D/G/N/S
+LIBERATOR/M/S
+LIBERTY/M/S
+LIBIDO
+LIBRARIAN/M/S
+LIBRARY/M/S
+LICENSE/D/G/S
+LICHEN/M/S
+LICK/D/G/S
+LID/M/S
+LIE/D/S
+LIEGE
+LIEN/M/S
+LIEU
+LIEUTENANT/M/S
+LIFE/R
+LIFELESS/P
+LIFELIKE
+LIFELONG
+LIFESTYLE/S
+LIFETIME/M/S
+LIFT/D/R/Z/G/S
+LIGHT/P/D/T/G/N/X/Y/S
+LIGHTER/M/S
+LIGHTHOUSE/M/S
+LIGHTNING/M/S
+LIGHTWEIGHT
+LIKE/D/G/S
+LIKELIHOOD/S
+LIKELY/P/T/R
+LIKEN/D/G/S
+LIKENESS/M/S
+LIKEWISE
+LILAC/M/S
+LILY/M/S
+LIMB/R/S
+LIME/M/S
+LIMESTONE
+LIMIT/D/R/Z/G/S
+LIMITABILITY
+LIMITABLY
+LIMITATION/M/S
+LIMITLESS
+LIMP/P/D/G/Y/S
+LINDA/M
+LINDEN
+LINE'S
+LINE/D/R/Z/G/J/S
+LINEAR/Y
+LINEARITY/S
+LINEARIZABLE
+LINEARIZE/D/G/S
+LINEFEED
+LINEN/M/S
+LINGER/D/G/S
+LINGUIST/M/S
+LINGUISTIC/S
+LINGUISTICALLY
+LINK/D/R/G/S
+LINKAGE/M/S
+LINOLEUM
+LINSEED
+LION/M/S
+LIONESS/M/S
+LIP/M/S
+LIPSTICK
+LIQUEFY/D/R/Z/G/S
+LIQUID/M/S
+LIQUIDATION/M/S
+LIQUIDITY
+LIQUIFY/D/R/Z/G/S
+LISBON
+LISP/D/M/G/S
+LIST/D/R/Z/G/X/S
+LISTEN/D/R/Z/G/S
+LISTING/M/S
+LIT/R/Z
+LITERACY
+LITERAL/P/Y/S
+LITERARY
+LITERATE
+LITERATURE/M/S
+LITHE
+LITTER/D/G/S
+LITTLE/P/T/R
+LIVABLE
+LIVABLY
+LIVE/P/D/R/Z/G/Y/S
+LIVELIHOOD
+LIVERY/D
+LIZARD/M/S
+LOAD/D/R/Z/G/J/S
+LOAF/D/R
+LOAN/D/G/S
+LOATH/Y
+LOATHE/D/G
+LOATHSOME
+LOAVES
+LOBBY/D/S
+LOBE/M/S
+LOBSTER/M/S
+LOCAL/Y/S
+LOCALITY/M/S
+LOCALIZATION
+LOCALIZE/D/G/S
+LOCATE/D/G/N/X/V/S
+LOCATIVES
+LOCATOR/M/S
+LOCI
+LOCK/D/R/Z/G/J/S
+LOCKOUT/M/S
+LOCKUP/M/S
+LOCOMOTION
+LOCOMOTIVE/M/S
+LOCUS
+LOCUST/M/S
+LODGE/D/R/G/J/S
+LOFT/M/S
+LOFTY/P
+LOG/M/S
+LOGARITHM/M/S
+LOGGED
+LOGGER/M/S
+LOGGING
+LOGIC/M/S
+LOGICAL/Y
+LOGICIAN/M/S
+LOGISTIC/S
+LOIN/M/S
+LOITER/D/R/G/S
+LONDON
+LONE/R/Z
+LONELY/P/T/R
+LONESOME
+LONG/D/T/R/G/J/S
+LONGITUDE/M/S
+LOOK/D/R/Z/G/S
+LOOKAHEAD
+LOOKOUT
+LOOKUP/M/S
+LOOM/D/G/S
+LOON
+LOOP/D/G/S
+LOOPHOLE/M/S
+LOOSE/P/D/T/R/G/Y/S
+LOOSEN/D/G/S
+LOOT/D/R/G/S
+LORD/Y/S
+LORDSHIP
+LORE
+LORRY
+LOSE/R/Z/G/S
+LOSS/M/S
+LOSSAGE
+LOSSY/T/R
+LOST
+LOT/M/S
+LOTTERY
+LOUD/P/T/R/Y
+LOUDSPEAKER/M/S
+LOUNGE/D/G/S
+LOUSY
+LOVABLE
+LOVABLY
+LOVE/D/R/Z/G/S
+LOVELY/P/T/R/S
+LOVINGLY
+LOW/P/T/Y/S
+LOWER/D/G/S
+LOWERCASE
+LOWLAND/S
+LOWLIEST
+LOYAL/Y
+LOYALTY/M/S
+LTD
+LUBRICANT/M
+LUBRICATION
+LUCID
+LUCK/D/S
+LUCKILY
+LUCKLESS
+LUCKY/T/R
+LUDICROUS/P/Y
+LUGGAGE
+LUKEWARM
+LULL/D/S
+LULLABY
+LUMBER/D/G
+LUMINOUS/Y
+LUMP/D/G/S
+LUNAR
+LUNATIC
+LUNCH/D/G/S
+LUNCHEON/M/S
+LUNG/D/S
+LURCH/D/G/S
+LURE/D/G/S
+LURK/D/G/S
+LUSCIOUS/P/Y
+LUST/R/S
+LUSTILY
+LUSTROUS
+LUSTY/P
+LUTE/M/S
+LUXURIANT/Y
+LUXURIOUS/Y
+LUXURY/M/S
+LYING
+LYMPH
+LYNCH/D/R/S
+LYNX/M/S
+LYRE
+LYRIC/S
+MA'AM
+MACE/D/S
+MACH
+MACHINE/D/M/G/S
+MACHINERY
+MACLACHLAN/M
+MACRO/M/S
+MACROECONOMICS
+MACROMOLECULAR
+MACROMOLECULE/M/S
+MACROSCOPIC
+MACROSTEP/S
+MACROSTRUCTURE
+MAD/P/Y
+MADAM
+MADDEN/G
+MADDER
+MADDEST
+MADE
+MADEMOISELLE
+MADISON
+MADMAN
+MADRAS
+MAGAZINE/M/S
+MAGGOT/M/S
+MAGIC
+MAGICAL/Y
+MAGICIAN/M/S
+MAGISTRATE/M/S
+MAGNESIUM
+MAGNET
+MAGNETIC
+MAGNETISM/M/S
+MAGNIFICENCE
+MAGNIFICENT/Y
+MAGNIFY/D/R/G/N/S
+MAGNITUDE/M/S
+MAHOGANY
+MAID/N/X/S
+MAIL/D/R/G/J/S
+MAILABLE
+MAILBOX/M/S
+MAIM/D/G/S
+MAIN/Y/S
+MAINE
+MAINFRAME/M/S
+MAINLAND
+MAINSTAY
+MAINSTREAM
+MAINTAIN/D/R/Z/G/S
+MAINTAINABILITY
+MAINTAINABLE
+MAINTENANCE/M/S
+MAIZE
+MAJESTIC
+MAJESTY/M/S
+MAJOR/D/S
+MAJORITY/M/S
+MAKABLE
+MAKE/R/Z/G/J/S
+MAKESHIFT
+MAKEUP/S
+MALADY/M/S
+MALARIA
+MALE/P/M/S
+MALEFACTOR/M/S
+MALFUNCTION/D/G/S
+MALICE
+MALICIOUS/P/Y
+MALIGNANT/Y
+MALLET/M/S
+MALNUTRITION
+MALT/D/S
+MAMA
+MAMMA/M/S
+MAMMAL/M/S
+MAMMOTH
+MAN/M/Y/S
+MANAGE/D/R/Z/G/S
+MANAGEABLE/P
+MANAGEMENT/M/S
+MANAGER/M/S
+MANAGERIAL
+MANDATE/D/G/S
+MANDATORY
+MANDIBLE
+MANE/M/S
+MANEUVER/D/G/S
+MANGER/M/S
+MANGLE/D/R/G/S
+MANHOOD
+MANIAC/M/S
+MANICURE/D/G/S
+MANIFEST/D/G/Y/S
+MANIFESTATION/M/S
+MANIFOLD/M/S
+MANILA
+MANIPULABILITY
+MANIPULABLE
+MANIPULATABLE
+MANIPULATE/D/G/N/X/V/S
+MANIPULATOR/M/S
+MANIPULATORY
+MANKIND
+MANNED
+MANNER/D/Y/S
+MANNING
+MANOMETER/M/S
+MANOR/M/S
+MANPOWER
+MANSION/M/S
+MANTEL/M/S
+MANTISSA/M/S
+MANTLE/M/S
+MANUAL/M/Y/S
+MANUFACTURE/D/R/Z/G/S
+MANUFACTURER/M/S
+MANURE
+MANUSCRIPT/M/S
+MANY
+MAP/M/S
+MAPLE/M/S
+MAPPABLE
+MAPPED
+MAPPING/M/S
+MAR/S
+MARBLE/G/S
+MARC/M
+MARCH/D/R/G/S
+MARE/M/S
+MARGIN/M/S
+MARGINAL/Y
+MARIGOLD
+MARIJUANA
+MARINE/R/S
+MARIO/M
+MARITAL
+MARITIME
+MARK/D/R/Z/G/J/S
+MARKABLE
+MARKEDLY
+MARKET/D/G/J/S
+MARKETABILITY
+MARKETABLE
+MARKETPLACE/M/S
+MARKOV
+MARQUIS
+MARRIAGE/M/S
+MARROW
+MARRY/D/G/S
+MARSH/M/S
+MARSHAL/D/G/S
+MART/N/S
+MARTHA/M
+MARTIAL
+MARTIN/M
+MARTYR/M/S
+MARTYRDOM
+MARVEL/D/S/G
+MARVELLED
+MARVELLING
+MARVELOUS/P/Y
+MARVIN/M
+MARY/M
+MARYLAND
+MASCULINE/Y
+MASCULINITY
+MASH/D/G/S
+MASK/D/R/G/J/S
+MASOCHIST/M/S
+MASON/M/S
+MASONRY
+MASQUERADE/R/G/S
+MASS/D/G/V/S
+MASSACHUSETTS
+MASSACRE/D/S
+MASSAGE/G/S
+MASSIVE/Y
+MAST/D/Z/S
+MASTER/D/M/G/Y/J/S
+MASTERFUL/Y
+MASTERPIECE/M/S
+MASTERY
+MASTURBATE/D/G/N/S
+MAT/M/S
+MATCH/D/R/Z/G/J/S
+MATCHABLE
+MATCHLESS
+MATE/D/R/M/G/J/S
+MATERIAL/Y/S
+MATERIALIZE/D/G/S
+MATERNAL/Y
+MATH
+MATHEMATICAL/Y
+MATHEMATICIAN/M/S
+MATHEMATICS
+MATRICES
+MATRICULATION
+MATRIMONY
+MATRIX
+MATRON/Y
+MATTED
+MATTER/D/S
+MATTRESS/M/S
+MATURATION
+MATURE/D/G/Y/S
+MATURITY/S
+MAURICE/M
+MAX
+MAXIM/M/S
+MAXIMAL/Y
+MAXIMIZE/D/R/Z/G/S
+MAXIMUM/S
+MAY
+MAYBE
+MAYHAP
+MAYHEM
+MAYONNAISE
+MAYOR/M/S
+MAYORAL
+MAZE/M/S
+MCDONALD/M
+ME
+MEAD
+MEADOW/M/S
+MEAGER/P/Y
+MEAL/M/S
+MEAN/P/T/R/Y/S
+MEANDER/D/G/S
+MEANING/M/S
+MEANINGFUL/P/Y
+MEANINGLESS/P/Y
+MEANT
+MEANTIME
+MEANWHILE
+MEASLES
+MEASURABLE
+MEASURABLY
+MEASURE/D/R/G/S
+MEASUREMENT/M/S
+MEAT/M/S
+MECHANIC/M/S
+MECHANICAL/Y
+MECHANISM/M/S
+MECHANIZATION/M/S
+MECHANIZE/D/G/S
+MEDAL/M/S
+MEDALLION/M/S
+MEDDLE/D/R/G/S
+MEDIA
+MEDIAN/M/S
+MEDIATE/D/G/N/X/S
+MEDIC/M/S
+MEDICAL/Y
+MEDICINAL/Y
+MEDICINE/M/S
+MEDIEVAL
+MEDIOCRE
+MEDITATE/D/G/N/X/V/S
+MEDIUM/M/S
+MEDUSA
+MEEK/P/T/R/Y
+MEET/G/J/S
+MELANCHOLY
+MELLON/M
+MELLOW/P/D/G/S
+MELODIOUS/P/Y
+MELODRAMA/M/S
+MELODY/M/S
+MELON/M/S
+MELT/D/G/S
+MELTINGLY
+MEMBER/M/S
+MEMBERSHIP/M/S
+MEMBRANE
+MEMO/M/S
+MEMOIR/S
+MEMORABLE/P
+MEMORANDA
+MEMORANDUM
+MEMORIAL/Y/S
+MEMORIZATION
+MEMORIZE/D/R/G/S
+MEMORY/M/S
+MEMORYLESS
+MEN/M/S
+MENACE/D/G
+MENAGERIE
+MEND/D/R/G/S
+MENIAL/S
+MENTAL/Y
+MENTALITY/S
+MENTION/D/R/Z/G/S
+MENTIONABLE
+MENTOR/M/S
+MENU/M/S
+MERCATOR
+MERCENARY/P/M/S
+MERCHANDISE/R/G
+MERCHANT/M/S
+MERCIFUL/Y
+MERCILESS/Y
+MERCURY
+MERCY
+MERE/T/Y
+MERGE/D/R/Z/G/S
+MERIDIAN
+MERIT/D/G/S
+MERITORIOUS/P/Y
+MERRILY
+MERRIMENT
+MERRY/T
+MESH
+MESS/D/G/S
+MESSAGE/M/S
+MESSENGER/M/S
+MESSIAH
+MESSIAHS
+MESSIEURS
+MESSILY
+MESSY/P/T/R
+MET/S
+META
+METACIRCULAR
+METACIRCULARITY
+METACLASS/S
+METAL/M/S
+METALANGUAGE
+METALLIC
+METALLIZATION/S
+METALLURGY
+METAMATHEMATICAL
+METAMORPHOSIS
+METAPHOR/M/S
+METAPHORICAL/Y
+METAPHYSICAL/Y
+METAPHYSICS
+METAVARIABLE
+METE/D/R/Z/G/S
+METEOR/M/S
+METEORIC
+METEOROLOGY
+METERING
+METHOD/M/S
+METHODICAL/P/Y
+METHODIST/M/S
+METHODOLOGICAL/Y
+METHODOLOGISTS
+METHODOLOGY/M/S
+METRIC/M/S
+METRICAL
+METROPOLIS
+METROPOLITAN
+MEW/D/S
+MICA
+MICE
+MICHAEL/M
+MICHIGAN
+MICRO
+MICROBICIDAL
+MICROBICIDE
+MICROBIOLOGY
+MICROCODE/D/G/S
+MICROCOMPUTER/M/S
+MICROECONOMICS
+MICROFILM/M/S
+MICROINSTRUCTION/M/S
+MICROPHONE/G/S
+MICROPROCESSING
+MICROPROCESSOR/M/S
+MICROPROGRAM/M/S
+MICROPROGRAMMED
+MICROPROGRAMMING
+MICROSCOPE/M/S
+MICROSCOPIC
+MICROSECOND/M/S
+MICROSOFT
+MICROSTEP/S
+MICROSTORE
+MICROSTRUCTURE
+MICROSYSTEM/S
+MICROWORD/S
+MID
+MIDDAY
+MIDDLE/G/S
+MIDNIGHT/S
+MIDPOINT/M/S
+MIDST/S
+MIDSUMMER
+MIDWAY
+MIDWEST
+MIDWINTER
+MIEN
+MIGHT
+MIGHTILY
+MIGHTY/P/T/R
+MIGRATE/D/G/N/X/S
+MIKE/M
+MILANO
+MILD/P/T/R/Y
+MILDEW
+MILE/M/S
+MILEAGE
+MILESTONE/M/S
+MILITANT/Y
+MILITARILY
+MILITARISM
+MILITARY
+MILITIA
+MILK/D/R/Z/G/S
+MILKMAID/M/S
+MILKY/P
+MILL/D/R/G/S
+MILLET
+MILLIMETER/S
+MILLION/H/S
+MILLIONAIRE/M/S
+MILLIPEDE/M/S
+MILLISECOND/S
+MILLSTONE/M/S
+MIMIC/S
+MIMICKED
+MIMICKING
+MINCE/D/G/S
+MIND/D/G/S
+MINDFUL/P/Y
+MINDLESS/Y
+MINE/D/R/Z/G/N/S
+MINERAL/M/S
+MINGLE/D/G/S
+MINI
+MINIATURE/M/S
+MINIATURIZATION
+MINIATURIZE/D/G/S
+MINICOMPUTER/M/S
+MINIMA
+MINIMAL/Y
+MINIMIZATION/M/S
+MINIMIZE/D/R/Z/G/S
+MINIMUM
+MINISTER/D/M/G/S
+MINISTRY/M/S
+MINK/M/S
+MINNEAPOLIS
+MINNESOTA/M
+MINNOW/M/S
+MINOR/M/S
+MINORITY/M/S
+MINSKY/M
+MINSTREL/M/S
+MINT/D/R/G/S
+MINUS
+MINUTE/P/R/Y/S
+MIRACLE/M/S
+MIRACULOUS/Y
+MIRAGE
+MIRE/D/S
+MIRROR/D/G/S
+MIRTH
+MISBEHAVING
+MISCALCULATION/M/S
+MISCELLANEOUS/P/Y
+MISCHIEF
+MISCHIEVOUS/P/Y
+MISCONCEPTION/M/S
+MISCONSTRUE/D/S
+MISER/Y/S
+MISERABLE/P
+MISERABLY
+MISERY/M/S
+MISFIT/M/S
+MISFORTUNE/M/S
+MISGIVING/S
+MISHAP/M/S
+MISINTERPRETATION
+MISJUDGMENT
+MISLEAD/G/S
+MISLED
+MISMATCH/D/G/S
+MISNOMER
+MISPLACE/D/G/S
+MISREPRESENTATION/M/S
+MISS/D/G/V/S
+MISSILE/M/S
+MISSION/R/S
+MISSIONARY/M/S
+MISSPELL/D/G/J/S
+MIST/D/R/Z/G/S
+MISTAKABLE
+MISTAKE/G/S
+MISTAKEN/Y
+MISTRESS
+MISTRUST/D
+MISTY/P
+MISTYPE/D/G/S
+MISUNDERSTAND/R/Z/G
+MISUNDERSTANDING/M/S
+MISUNDERSTOOD
+MISUSE/D/G/S
+MIT/R/M
+MITIGATE/D/G/N/V/S
+MITTEN/M/S
+MIX/D/R/Z/G/S
+MIXTURE/M/S
+MNEMONIC/M/S
+MNEMONICALLY
+MOAN/D/S
+MOAT/M/S
+MOB/M/S
+MOCCASIN/M/S
+MOCK/D/R/G/S
+MOCKERY
+MODAL/Y
+MODALITY/M/S
+MODE/T/S
+MODEL/D/G/J/S/M
+MODEM
+MODERATE/P/D/G/N/Y/S
+MODERATOR/M/S
+MODERN/P/Y/S
+MODERNISM
+MODERNITY
+MODERNIZE/D/R/G
+MODESTLY
+MODESTY
+MODIFIABILITY
+MODIFIABLE
+MODIFY/D/R/Z/G/N/X/S
+MODULAR/Y
+MODULARITY
+MODULARIZATION
+MODULARIZE/D/G/S
+MODULATE/D/G/N/X/S
+MODULATOR/M/S
+MODULE/M/S
+MODULO
+MODULUS
+MODUS
+MOHAWK
+MOIST/P/N/Y
+MOISTURE
+MOLASSES
+MOLD/D/R/G/S
+MOLE/T/S
+MOLECULAR
+MOLECULE/M/S
+MOLEST/D/G/S
+MOLTEN
+MOMENT/M/S
+MOMENTARILY
+MOMENTARY/P
+MOMENTOUS/P/Y
+MOMENTUM
+MONARCH
+MONARCHS
+MONARCHY/M/S
+MONASTERY/M/S
+MONASTIC
+MONDAY/M/S
+MONETARY
+MONEY/D/S
+MONITOR/D/G/S
+MONK/M/S
+MONKEY/D/G/S
+MONOCHROME
+MONOGRAM/M/S
+MONOGRAPH/M/S
+MONOGRAPHS
+MONOLITHIC
+MONOPOLY/M/S
+MONOTHEISM
+MONOTONE
+MONOTONIC
+MONOTONICALLY
+MONOTONICITY
+MONOTONOUS/P/Y
+MONOTONY
+MONSTER/M/S
+MONSTROUS/Y
+MONTANA/M
+MONTH/Y
+MONTHS
+MONUMENT/M/S
+MONUMENTAL/Y
+MOOD/M/S
+MOODY/P
+MOON/D/G/S
+MOONLIGHT/R/G
+MOONLIT
+MOONSHINE
+MOOR/D/G/J/S
+MOOSE
+MOOT
+MOP/D/S
+MORAL/Y/S
+MORALE
+MORALITY/S
+MORASS
+MORBID/P/Y
+MORE/S
+MOREOVER
+MORN/G/J
+MORPHISM/S
+MORPHOLOGICAL
+MORPHOLOGY
+MORROW
+MORSEL/M/S
+MORTAL/Y/S
+MORTALITY
+MORTAR/D/G/S
+MORTGAGE/M/S
+MORTIFY/D/G/N/S
+MOSAIC/M/S
+MOSQUITO/S
+MOSQUITOES
+MOSS/M/S
+MOSSY
+MOST/Y
+MOTEL/M/S
+MOTH/Z
+MOTHER'S
+MOTHER/D/R/Z/G/Y/S
+MOTIF/M/S
+MOTION/D/G/S
+MOTIONLESS/P/Y
+MOTIVATE/D/G/N/X/S
+MOTIVATIONAL
+MOTIVE/S
+MOTLEY
+MOTOR/G/S
+MOTORCAR/M/S
+MOTORCYCLE/M/S
+MOTORIST/M/S
+MOTORIZE/D/G/S
+MOTOROLA/M
+MOTTO/S
+MOTTOES
+MOULD/G
+MOUND/D/S
+MOUNT/D/R/G/J/S
+MOUNTAIN/M/S
+MOUNTAINEER/G/S
+MOUNTAINOUS/Y
+MOURN/D/R/Z/G/S
+MOURNFUL/P/Y
+MOUSE/R/S
+MOUTH/D/G
+MOUTHFUL
+MOUTHS
+MOVABLE
+MOVE/D/R/Z/G/J/S
+MOVEMENT/M/S
+MOVIE/M/S
+MOW/D/R/S
+MR
+MRS
+MS
+MUCH
+MUCK/R/G
+MUD
+MUDDLE/D/R/Z/G/S
+MUDDY/P/D
+MUFF/M/S
+MUFFIN/M/S
+MUFFLE/D/R/G/S
+MUG/M/S
+MULBERRY/M/S
+MULE/M/S
+MULTI
+MULTICELLULAR
+MULTIDIMENSIONAL
+MULTILEVEL
+MULTINATIONAL
+MULTIPLE/M/S
+MULTIPLEX/D/G/S
+MULTIPLEXOR/M/S
+MULTIPLICAND/M/S
+MULTIPLICATIVE/S
+MULTIPLICITY
+MULTIPLY/D/R/Z/G/N/X/S
+MULTIPROCESS/G
+MULTIPROCESSOR/M/S
+MULTIPROGRAM
+MULTIPROGRAMMED
+MULTIPROGRAMMING
+MULTIPURPOSE
+MULTISTAGE
+MULTITUDE/M/S
+MULTIVARIATE
+MUMBLE/D/R/Z/G/J/S
+MUMMY/M/S
+MUNCH/D/G
+MUNDANE/Y
+MUNICIPAL/Y
+MUNICIPALITY/M/S
+MUNITION/S
+MURAL
+MURDER/D/R/Z/G/S
+MURDEROUS/Y
+MURKY
+MURMUR/D/R/G/S
+MUSCLE/D/G/S
+MUSCULAR
+MUSE/D/G/J/S
+MUSEUM/M/S
+MUSHROOM/D/G/S
+MUSHY
+MUSIC
+MUSICAL/Y/S
+MUSICIAN/Y/S
+MUSK/S
+MUSKET/M/S
+MUSKRAT/M/S
+MUSLIN
+MUSSEL/M/S
+MUST/R/S
+MUSTACHE/D/S
+MUSTARD
+MUSTY/P
+MUTABILITY
+MUTABLE/P
+MUTATE/D/G/N/X/V/S
+MUTE/P/D/Y
+MUTILATE/D/G/N/S
+MUTINY/M/S
+MUTTER/D/R/Z/G/S
+MUTTON
+MUTUAL/Y
+MUZZLE/M/S
+MY
+MYRIAD
+MYRTLE
+MYSELF
+MYSTERIOUS/P/Y
+MYSTERY/M/S
+MYSTIC/M/S
+MYSTICAL
+MYTH
+MYTHICAL
+MYTHOLOGY/M/S
+NAG/M/S
+NAIL/D/G/S
+NAIVE/P/Y
+NAIVETE
+NAKED/P/Y
+NAME/D/R/Z/G/Y/S
+NAMEABLE
+NAMELESS/Y
+NAMESAKE/M/S
+NANOSECOND/S
+NAP/M/S
+NAPKIN/M/S
+NARCISSUS
+NARCOTIC/S
+NARRATIVE/M/S
+NARROW/P/D/T/R/G/Y/S
+NASAL/Y
+NASTILY
+NASTY/P/T/R
+NATHANIEL/M
+NATION/M/S
+NATIONAL/Y/S
+NATIONALIST/M/S
+NATIONALITY/M/S
+NATIONALIZATION
+NATIONALIZE/D/G/S
+NATIONWIDE
+NATIVE/Y/S
+NATIVITY
+NATURAL/P/Y/S
+NATURALISM
+NATURALIST
+NATURALIZATION
+NATURE/D/M/S
+NAUGHT
+NAUGHTY/P/R
+NAVAL/Y
+NAVIGABLE
+NAVIGATE/D/G/N/S
+NAVIGATOR/M/S
+NAVY/M/S
+NAY
+NAZI/M/S
+NEAR/P/D/T/R/G/Y/S
+NEARBY
+NEAT/P/T/R/Y
+NEBRASKA
+NEBULA
+NECESSARILY
+NECESSARY/S
+NECESSITATE/D/G/N/S
+NECESSITY/S
+NECK/G/S
+NECKLACE/M/S
+NECKTIE/M/S
+NEE
+NEED/D/G/S
+NEEDFUL
+NEEDLE/D/R/Z/G/S
+NEEDLESS/P/Y
+NEEDLEWORK
+NEEDN'T
+NEEDY
+NEGATE/D/G/N/X/V/S
+NEGATIVELY
+NEGATIVES
+NEGATOR/S
+NEGLECT/D/G/S
+NEGLIGENCE
+NEGLIGIBLE
+NEGOTIATE/D/G/N/X/S
+NEGRO
+NEGROES
+NEIGH
+NEIGHBOR/G/Y/S
+NEIGHBORHOOD/M/S
+NEITHER
+NEOPHYTE/S
+NEPAL
+NEPHEW/M/S
+NERVE/M/S
+NERVOUS/P/Y
+NEST/D/R/G/S
+NESTLE/D/G/S
+NET/M/S
+NETHER
+NETHERLANDS
+NETMAIL
+NETNEWS
+NETTED
+NETTING
+NETTLE/D
+NETWORK/D/M/G/S
+NEUMANN/M
+NEURAL
+NEUROLOGICAL
+NEUROLOGISTS
+NEURON/M/S
+NEUROPHYSIOLOGY
+NEUROSCIENCE/S
+NEUTRAL/Y
+NEUTRALITY/S
+NEUTRALIZE/D/G
+NEUTRINO/M/S
+NEVER
+NEVERTHELESS
+NEW/P/T/R/Y/S
+NEWBORN
+NEWCOMER/M/S
+NEWLINE
+NEWSMAN
+NEWSMEN
+NEWSPAPER/M/S
+NEWTONIAN
+NEXT
+NIBBLE/D/R/Z/G/S
+NICE/P/T/R/Y
+NICHE/S
+NICK/D/R/G/S
+NICKEL/M/S
+NICKNAME/D/S
+NIECE/M/S
+NIFTY
+NIGH
+NIGHT/Y/S
+NIGHTFALL
+NIGHTGOWN
+NIGHTINGALE/M/S
+NIGHTMARE/M/S
+NIL
+NIMBLE/P/R
+NIMBLY
+NINE/S
+NINETEEN/H/S
+NINETY/H/S
+NINTH
+NIP/S
+NITROGEN
+NO
+NOBILITY
+NOBLE/P/T/R/S
+NOBLEMAN
+NOBLY
+NOBODY
+NOCTURNAL/Y
+NOD/M/S
+NODDED
+NODDING
+NODE/M/S
+NOISE/S
+NOISELESS/Y
+NOISILY
+NOISY/P/R
+NOMENCLATURE
+NOMINAL/Y
+NOMINATE/D/G/N/V
+NON
+NONBLOCKING
+NONCONSERVATIVE
+NONCYCLIC
+NONDECREASING
+NONDESCRIPT/Y
+NONDESTRUCTIVELY
+NONDETERMINACY
+NONDETERMINATE/Y
+NONDETERMINISM
+NONDETERMINISTIC
+NONDETERMINISTICALLY
+NONE
+NONEMPTY
+NONETHELESS
+NONEXISTENCE
+NONEXISTENT
+NONEXTENSIBLE
+NONFUNCTIONAL
+NONINTERACTING
+NONINTERFERENCE
+NONINTUITIVE
+NONLINEAR/Y
+NONLINEARITY/M/S
+NONLOCAL
+NONNEGATIVE
+NONORTHOGONAL
+NONORTHOGONALITY
+NONPERISHABLE
+NONPROCEDURAL/Y
+NONPROGRAMMABLE
+NONPROGRAMMER
+NONSENSE
+NONSENSICAL
+NONSPECIALIST/M/S
+NONTECHNICAL
+NONTERMINAL/M/S
+NONTERMINATING
+NONTERMINATION
+NONTRIVIAL
+NONUNIFORM
+NONZERO
+NOODLE/S
+NOOK/M/S
+NOON/S
+NOONDAY
+NOONTIDE
+NOR/H
+NORM/M/S
+NORMAL/Y/S
+NORMALCY
+NORMALITY
+NORMALIZATION
+NORMALIZE/D/G/S
+NORTHEAST/R
+NORTHEASTERN
+NORTHERN/R/Z/Y
+NORTHWARD/S
+NORTHWEST
+NORTHWESTERN
+NOSE/D/G/S
+NOSTRIL/M/S
+NOT
+NOTABLE/S
+NOTABLY
+NOTARIZE/D/G/S
+NOTATION/M/S
+NOTATIONAL
+NOTCH/D/G/S
+NOTE/D/G/N/X/S
+NOTEBOOK/M/S
+NOTEWORTHY
+NOTHING/P/S
+NOTICE/D/G/S
+NOTICEABLE
+NOTICEABLY
+NOTIFY/D/R/Z/G/N/X/S
+NOTORIOUS/Y
+NOTWITHSTANDING
+NOUN/M/S
+NOURISH/D/G/S
+NOURISHMENT
+NOVEL/M/S
+NOVELIST/M/S
+NOVELTY/M/S
+NOVEMBER
+NOVICE/M/S
+NOW
+NOWADAYS
+NOWHERE
+NSF
+NUANCES
+NUCLEAR
+NUCLEOTIDE/M/S
+NUCLEUS
+NUISANCE/M/S
+NULL/D/S
+NULLARY
+NULLIFY/D/Z/G/S
+NUMB/P/D/Z/G/Y/S
+NUMBER/D/R/G/S
+NUMBERLESS
+NUMERAL/M/S
+NUMERATOR/M/S
+NUMERIC/S
+NUMERICAL/Y
+NUMEROUS
+NUN/M/S
+NUPTIAL
+NURSE/D/G/S
+NURSERY/M/S
+NURTURE/D/G/S
+NUT/M/S
+NUTRITION
+NYMPH
+NYMPHS
+O'CLOCK
+OAK/N/S
+OAR/M/S
+OASIS
+OAT/N/S
+OATH
+OATHS
+OATMEAL
+OBEDIENCE/S
+OBEDIENT/Y
+OBEY/D/G/S
+OBJECT/D/G/M/S/V
+OBJECTION/M/S
+OBJECTIONABLE
+OBJECTIVELY
+OBJECTIVES
+OBJECTOR/M/S
+OBLIGATION/M/S
+OBLIGATORY
+OBLIGE/D/G/S
+OBLIGINGLY
+OBLIQUE/P/Y
+OBLITERATE/D/G/N/S
+OBLIVION
+OBLIVIOUS/P/Y
+OBLONG
+OBSCENE
+OBSCURE/D/R/G/Y/S
+OBSCURITY/S
+OBSERVABILITY
+OBSERVABLE
+OBSERVANCE/M/S
+OBSERVANT
+OBSERVATION/M/S
+OBSERVATORY
+OBSERVE/D/R/Z/G/S
+OBSESSION/M/S
+OBSOLESCENCE
+OBSOLETE/D/G/S
+OBSTACLE/M/S
+OBSTINACY
+OBSTINATE/Y
+OBSTRUCT/D/G/V
+OBSTRUCTION/M/S
+OBTAIN/D/G/S
+OBTAINABLE
+OBTAINABLY
+OBVIATE/D/G/N/X/S
+OBVIOUS/P/Y
+OCCASION/D/G/J/S
+OCCASIONAL/Y
+OCCLUDE/D/S
+OCCLUSION/M/S
+OCCUPANCY/S
+OCCUPANT/M/S
+OCCUPATION/M/S
+OCCUPATIONAL/Y
+OCCUPY/D/R/G/S
+OCCUR/S
+OCCURRED
+OCCURRENCE/M/S
+OCCURRING
+OCEAN/M/S
+OCTAL
+OCTAVE/S
+OCTOBER
+OCTOPUS
+ODD/P/T/R/Y/S
+ODDITY/M/S
+ODE/M/S
+ODIOUS/P/Y
+ODOR/M/S
+ODOROUS/P/Y
+ODYSSEY
+OEDIPUS
+OF
+OFF/G
+OFFEND/D/R/Z/G/S
+OFFENSE/V/S
+OFFENSIVELY
+OFFENSIVENESS
+OFFER/D/R/Z/G/J/S
+OFFICE/R/Z/S
+OFFICER'S
+OFFICIAL/Y/S
+OFFICIO
+OFFICIOUS/P/Y
+OFFSET/M/S
+OFFSPRING
+OFT/N
+OFTENTIMES
+OH
+OHIO/M
+OIL/D/R/Z/G/S
+OILCLOTH
+OILY/T/R
+OINTMENT
+OK
+OKAY
+OLD/P/T/R/N
+OLIVE/M/S
+OLIVETTI
+OMEN/M/S
+OMINOUS/P/Y
+OMISSION/M/S
+OMIT/S
+OMITTED
+OMITTING
+OMNIPRESENT
+OMNISCIENT/Y
+OMNIVORE
+ON/Y
+ONANISM
+ONBOARD
+ONCE
+ONCOLOGY
+ONE/P/M/N/X/S
+ONEROUS
+ONESELF
+ONGOING
+ONLINE
+ONSET/M/S
+ONTO
+ONWARD/S
+OOZE/D
+OPACITY
+OPAL/M/S
+OPAQUE/P/Y
+OPCODE
+OPEN/P/D/R/Z/Y/S
+OPENING/M/S
+OPERA/M/S
+OPERABLE
+OPERAND/M/S
+OPERANDI
+OPERATE/D/G/N/X/V/S
+OPERATIONAL/Y
+OPERATIVES
+OPERATOR/M/S
+OPINION/M/S
+OPIUM
+OPPONENT/M/S
+OPPORTUNE/Y
+OPPORTUNISM
+OPPORTUNISTIC
+OPPORTUNITY/M/S
+OPPOSE/D/G/S
+OPPOSITE/P/N/Y/S
+OPPRESS/D/G/V/S
+OPPRESSION
+OPPRESSOR/M/S
+OPT/D/G/S
+OPTIC/S
+OPTICAL/Y
+OPTIMAL/Y
+OPTIMALITY
+OPTIMISM
+OPTIMISTIC
+OPTIMISTICALLY
+OPTIMIZATION/M/S
+OPTIMIZE/D/R/Z/G/S
+OPTIMUM
+OPTION/M/S
+OPTIONAL/Y
+OR/M/Y
+ORACLE/M/S
+ORAL/Y
+ORANGE/M/S
+ORATION/M/S
+ORATOR/M/S
+ORATORY/M/S
+ORB
+ORBIT/D/R/Z/G/S
+ORBITAL/Y
+ORCHARD/M/S
+ORCHESTRA/M/S
+ORCHID/M/S
+ORDAIN/D/G/S
+ORDEAL
+ORDER/D/G/Y/J/S
+ORDERLIES
+ORDINAL
+ORDINANCE/M/S
+ORDINARILY
+ORDINARY/P
+ORDINATE/N/S
+ORE/M/S
+ORGAN/M/S
+ORGANIC
+ORGANISM/M/S
+ORGANIST/M/S
+ORGANIZABLE
+ORGANIZATION/M/S
+ORGANIZATIONAL/Y
+ORGANIZE/D/R/Z/G/S
+ORGY/M/S
+ORIENT/D/G/S
+ORIENTAL
+ORIENTATION/M/S
+ORIFICE/M/S
+ORIGIN/M/S
+ORIGINAL/Y/S
+ORIGINALITY
+ORIGINATE/D/G/N/S
+ORIGINATOR/M/S
+ORLEANS
+ORNAMENT/D/G/S
+ORNAMENTAL/Y
+ORNAMENTATION
+ORPHAN/D/S
+ORTHODOX
+ORTHOGONAL/Y
+ORTHOGONALITY
+ORTHOGRAPHIC
+OSAKA
+OSCILLATE/D/G/N/X/S
+OSCILLATION/M/S
+OSCILLATOR/M/S
+OSCILLATORY
+OSCILLOSCOPE/M/S
+OSTRICH/M/S
+OTHER/S
+OTHERWISE
+OTTER/M/S
+OUGHT
+OUNCE/S
+OUR/S
+OURSELF
+OURSELVES
+OUT/R/G/S
+OUTBREAK/M/S
+OUTBURST/M/S
+OUTCAST/M/S
+OUTCOME/M/S
+OUTCRY/S
+OUTDOOR/S
+OUTERMOST
+OUTFIT/M/S
+OUTGOING
+OUTGREW
+OUTGROW/G/H/S
+OUTGROWN
+OUTLAST/S
+OUTLAW/D/G/S
+OUTLAY/M/S
+OUTLET/M/S
+OUTLINE/D/G/S
+OUTLIVE/D/G/S
+OUTLOOK
+OUTPERFORM/D/G/S
+OUTPOST/M/S
+OUTPUT/M/S
+OUTPUTTING
+OUTRAGE/D/S
+OUTRAGEOUS/Y
+OUTRIGHT
+OUTRUN/S
+OUTSET
+OUTSIDE/R
+OUTSIDER/M/S
+OUTSKIRTS
+OUTSTANDING/Y
+OUTSTRETCHED
+OUTSTRIP/S
+OUTSTRIPPED
+OUTSTRIPPING
+OUTVOTE/D/G/S
+OUTWARD/Y
+OUTWEIGH/D/G
+OUTWEIGHS
+OUTWIT/S
+OUTWITTED
+OUTWITTING
+OVAL/M/S
+OVARY/M/S
+OVEN/M/S
+OVER/Y
+OVERALL/M/S
+OVERBOARD
+OVERCAME
+OVERCOAT/M/S
+OVERCOME/G/S
+OVERCROWD/D/G/S
+OVERDONE
+OVERDRAFT/M/S
+OVERDUE
+OVEREMPHASIS
+OVEREMPHASIZED
+OVERESTIMATE/D/G/N/S
+OVERFLOW/D/G/S
+OVERHANG/G/S
+OVERHAUL/G
+OVERHEAD/S
+OVERHEAR/G/S
+OVERHEARD
+OVERJOY/D
+OVERLAND
+OVERLAP/M/S
+OVERLAPPED
+OVERLAPPING
+OVERLAY/G/S
+OVERLOAD/D/G/S
+OVERLOOK/D/G/S
+OVERNIGHT/R/Z
+OVERPOWER/D/G/S
+OVERPRINT/D/G/S
+OVERPRODUCTION
+OVERRIDDEN
+OVERRIDE/G/S
+OVERRODE
+OVERRULE/D/S
+OVERRUN/S
+OVERSEAS
+OVERSEE/R/Z/S
+OVERSEEING
+OVERSHADOW/D/G/S
+OVERSHOOT
+OVERSHOT
+OVERSIGHT/M/S
+OVERSIMPLIFY/D/G/S
+OVERSTATE/D/G/S
+OVERSTATEMENT/M/S
+OVERSTOCKS
+OVERT/Y
+OVERTAKE/R/Z/G/S
+OVERTAKEN
+OVERTHREW
+OVERTHROW
+OVERTHROWN
+OVERTIME
+OVERTONE/M/S
+OVERTOOK
+OVERTURE/M/S
+OVERTURN/D/G/S
+OVERUSE
+OVERVIEW/M/S
+OVERWHELM/D/G/S
+OVERWHELMINGLY
+OVERWORK/D/G/S
+OVERWRITE/G/S
+OVERWRITTEN
+OVERZEALOUS
+OWE/D/G/S
+OWL/M/S
+OWN/D/R/Z/G/S
+OWNERSHIP/S
+OX/N
+OXFORD
+OXIDE/M/S
+OXIDIZE/D
+OXYGEN
+OYSTER/M/S
+PA/H
+PACE/D/R/Z/G/S
+PACHELBEL
+PACIFIC
+PACIFY/R/N/S
+PACK/D/R/Z/G/S
+PACKAGE/D/R/Z/G/J/S
+PACKET/M/S
+PACT/M/S
+PAD/M/S
+PADDED
+PADDING
+PADDLE
+PADDY
+PAGAN/M/S
+PAGE'S
+PAGE/D/R/Z/G/S
+PAGEANT/M/S
+PAGINATE/D/G/N/S
+PAID
+PAIL/M/S
+PAIN/D/S
+PAINFUL/Y
+PAINSTAKING/Y
+PAINT/D/R/Z/G/J/S
+PAIR/D/G/J/S
+PAIRWISE
+PAJAMA/S
+PAL/M/S
+PALACE/M/S
+PALATE/M/S
+PALE/P/D/T/R/G/Y/S
+PALETTE
+PALFREY
+PALL
+PALLIATE/V
+PALLID
+PALM/D/R/G/S
+PALPATION
+PAMPHLET/M/S
+PAN/M/S
+PANACEA/M/S
+PANCAKE/M/S
+PANDEMONIUM
+PANE/M/S
+PANEL/D/G/S
+PANELIST/M/S
+PANG/M/S
+PANIC/M/S
+PANNED
+PANNING
+PANSY/M/S
+PANT/D/G/S
+PANTHER/M/S
+PANTRY/M/S
+PANTY/S
+PAPA
+PAPAL
+PAPER'S
+PAPER/D/R/Z/G/J/S
+PAPERBACK/M/S
+PAPERWORK
+PAPRIKA
+PAR/S
+PARACHUTE/M/S
+PARADE/D/G/S
+PARADIGM/M/S
+PARADISE
+PARADOX/M/S
+PARADOXICAL/Y
+PARAFFIN
+PARAGON/M/S
+PARAGRAPH/G
+PARAGRAPHS
+PARALLEL/D/G/S
+PARALLELISM
+PARALLELIZE/D/G/S
+PARALLELLED
+PARALLELLING
+PARALLELOGRAM/M/S
+PARALYSIS
+PARALYZE/D/G/S
+PARAMETER/M/S
+PARAMETERIZABLE
+PARAMETERIZATION/M/S
+PARAMETERIZE/D/G/S
+PARAMETERLESS
+PARAMETRIC
+PARAMILITARY
+PARAMOUNT
+PARANOIA
+PARANOID
+PARAPET/M/S
+PARAPHRASE/D/G/S
+PARASITE/M/S
+PARASITIC/S
+PARCEL/D/G/S
+PARCH/D
+PARCHMENT
+PARDON/D/R/Z/G/S
+PARDONABLE
+PARDONABLY
+PARE/G/J/S
+PARENT/M/S
+PARENTAGE
+PARENTAL
+PARENTHESES
+PARENTHESIS
+PARENTHESIZED
+PARENTHETICAL/Y
+PARENTHOOD
+PARISH/M/S
+PARITY
+PARK/D/R/Z/G/S
+PARLIAMENT/M/S
+PARLIAMENTARY
+PARLOR/M/S
+PAROLE/D/G/S
+PARROT/G/S
+PARRY/D
+PARSE/D/R/Z/G/J/S
+PARSIMONY
+PARSLEY
+PARSON/M/S
+PART/D/R/Z/G/Y/J/S
+PARTAKE/R/G/S
+PARTIAL/Y
+PARTIALITY
+PARTICIPANT/M/S
+PARTICIPATE/D/G/N/S
+PARTICLE/M/S
+PARTICULAR/Y/S
+PARTISAN/M/S
+PARTITION/D/G/S
+PARTNER/D/S
+PARTNERSHIP
+PARTRIDGE/M/S
+PARTY/M/S
+PASCAL
+PASS
+PASSAGE/M/S
+PASSAGEWAY
+PASSE/D/R/Z/G/N/X/S
+PASSENGER/M/S
+PASSIONATE/Y
+PASSIVE/P/Y
+PASSIVITY
+PASSPORT/M/S
+PASSWORD/M/S
+PAST/P/M/S
+PASTE/D/G/S
+PASTEBOARD
+PASTIME/M/S
+PASTOR/M/S
+PASTORAL
+PASTRY
+PASTURE/M/S
+PAT/S
+PATCH/D/G/S
+PATCHWORK
+PATENT/D/R/Z/G/Y/S
+PATENTABLE
+PATERNAL/Y
+PATHETIC
+PATHOLOGICAL
+PATHOLOGY
+PATHOS
+PATHS
+PATHWAY/M/S
+PATIENCE
+PATIENT/Y/S
+PATRIARCH
+PATRIARCHS
+PATRICIAN/M/S
+PATRIOT/M/S
+PATRIOTIC
+PATRIOTISM
+PATROL/M/S
+PATRON/M/S
+PATRONAGE
+PATRONIZE/D/G/S
+PATTER/D/G/J/S
+PATTERN/D/G/S
+PATTY/M/S
+PAUCITY
+PAUL/M
+PAUSE/D/G/S
+PAVE/D/G/S
+PAVEMENT/M/S
+PAVILION/M/S
+PAW/G/S
+PAWN/M/S
+PAY/G/S
+PAYABLE
+PAYCHECK/M/S
+PAYER/M/S
+PAYMENT/M/S
+PAYOFF/M/S
+PAYROLL
+PC
+PDP
+PEA/M/S
+PEACE
+PEACEABLE
+PEACEFUL/P/Y
+PEACH/M/S
+PEACOCK/M/S
+PEAK/D/S
+PEAL/D/G/S
+PEANUT/M/S
+PEAR/Y/S
+PEARL/M/S
+PEASANT/M/S
+PEASANTRY
+PEAT
+PEBBLE/M/S
+PECK/D/G/S
+PECULIAR/Y
+PECULIARITY/M/S
+PEDAGOGIC
+PEDAGOGICAL
+PEDANTIC
+PEDDLER/M/S
+PEDESTAL
+PEDESTRIAN/M/S
+PEDIATRIC/S
+PEEK/D/G/S
+PEEL/D/G/S
+PEEP/D/R/G/S
+PEER/D/G/S
+PEERLESS
+PEG/M/S
+PELT/G/S
+PEN
+PENALIZE/D/G/S
+PENALTY/M/S
+PENANCE
+PENCE
+PENCIL/D/S
+PEND/D/G/S
+PENDULUM/M/S
+PENETRATE/D/G/N/X/V/S
+PENETRATINGLY
+PENETRATOR/M/S
+PENGUIN/M/S
+PENINSULA/M/S
+PENITENT
+PENITENTIARY
+PENNED
+PENNILESS
+PENNING
+PENNSYLVANIA
+PENNY/M/S
+PENS/V
+PENSION/R/S
+PENT
+PENTAGON/M/S
+PEOPLE/D/M/S
+PEP
+PEPPER/D/G/S
+PER
+PERCEIVABLE
+PERCEIVABLY
+PERCEIVE/D/R/Z/G/S
+PERCENT/S
+PERCENTAGE/S
+PERCENTILE/S
+PERCEPTIBLE
+PERCEPTIBLY
+PERCEPTION/S
+PERCEPTIVE/Y
+PERCEPTRON/S
+PERCEPTUAL/Y
+PERCH/D/G/S
+PERCHANCE
+PERCUSSION
+PERCUTANEOUS
+PEREMPTORY
+PERENNIAL/Y
+PERFECT/P/D/G/Y/S
+PERFECTION
+PERFECTIONIST/M/S
+PERFORCE
+PERFORM/D/R/Z/G/S
+PERFORMANCE/M/S
+PERFUME/D/G/S
+PERHAPS
+PERIL/M/S
+PERILOUS/Y
+PERIMETER/S
+PERIOD/M/S
+PERIODIC
+PERIODICAL/Y/S
+PERIPHERAL/Y/S
+PERIPHERY/M/S
+PERISH/D/R/Z/G/S
+PERISHABLE/M/S
+PERMANENCE
+PERMANENT/Y
+PERMEATE/D/G/N/S
+PERMISSIBILITY
+PERMISSIBLE
+PERMISSIBLY
+PERMISSION/S
+PERMISSIVE/Y
+PERMIT/M/S
+PERMITTED
+PERMITTING
+PERMUTATION/M/S
+PERMUTE/D/G/S
+PERPENDICULAR/Y/S
+PERPETRATE/D/G/N/X/S
+PERPETRATOR/M/S
+PERPETUAL/Y
+PERPETUATE/D/G/N/S
+PERPLEX/D/G
+PERPLEXITY
+PERSECUTE/D/G/N/S
+PERSECUTOR/M/S
+PERSEVERANCE
+PERSEVERE/D/G/S
+PERSIST/D/G/S
+PERSISTENCE
+PERSISTENT/Y
+PERSON/M/S
+PERSONAGE/M/S
+PERSONAL/Y
+PERSONALITY/M/S
+PERSONALIZATION
+PERSONALIZE/D/G/S
+PERSONIFY/D/G/N/S
+PERSONNEL
+PERSPECTIVE/M/S
+PERSPICUOUS/Y
+PERSPIRATION
+PERSUADABLE
+PERSUADE/D/R/Z/G/S
+PERSUASION/M/S
+PERSUASIVE/P/Y
+PERTAIN/D/G/S
+PERTINENT
+PERTURB/D
+PERTURBATION/M/S
+PERUSAL
+PERUSE/D/R/Z/G/S
+PERVADE/D/G/S
+PERVASIVE/Y
+PERVERT/D/S
+PESSIMISTIC
+PEST/R/S
+PESTILENCE
+PET/R/Z/S
+PETAL/M/S
+PETITION/D/R/G/S
+PETROLEUM
+PETTED
+PETTER/M/S
+PETTICOAT/M/S
+PETTING
+PETTY/P
+PEW/M/S
+PEWTER
+PHANTOM/M/S
+PHASE/D/R/Z/G/S
+PHEASANT/M/S
+PHENOMENA
+PHENOMENAL/Y
+PHENOMENOLOGICAL/Y
+PHENOMENOLOGY/S
+PHENOMENON
+PHILADELPHIA
+PHILOSOPHER/M/S
+PHILOSOPHIC
+PHILOSOPHICAL/Y
+PHILOSOPHIZE/D/R/Z/G/S
+PHILOSOPHY/M/S
+PHONE/D/G/S
+PHONEME/M/S
+PHONEMIC
+PHONETIC/S
+PHONOGRAPH
+PHONOGRAPHS
+PHOSPHATE/M/S
+PHOSPHORIC
+PHOTO/M/S
+PHOTOCOPY/D/G/S
+PHOTOGRAPH/D/R/Z/G
+PHOTOGRAPHIC
+PHOTOGRAPHS
+PHOTOGRAPHY
+PHOTOTYPESETTER/S
+PHRASE/D/G/J/S
+PHYLA
+PHYLUM
+PHYSIC/S
+PHYSICAL/P/Y/S
+PHYSICIAN/M/S
+PHYSICIST/M/S
+PHYSIOLOGICAL/Y
+PHYSIOLOGY
+PHYSIQUE
+PI
+PIANO/M/S
+PIAZZA/M/S
+PICAYUNE
+PICK/D/R/Z/G/J/S
+PICKET/D/R/Z/G/S
+PICKLE/D/G/S
+PICKUP/M/S
+PICKY
+PICNIC/M/S
+PICTORIAL/Y
+PICTURE/D/G/S
+PICTURESQUE/P
+PIE/R/Z/S
+PIECE/D/G/S
+PIECEMEAL
+PIECEWISE
+PIERCE/D/G/S
+PIETY
+PIG/M/S
+PIGEON/M/S
+PIGMENT/D/S
+PIKE/R/S
+PILE/D/Z/G/J/S
+PILFERAGE
+PILGRIM/M/S
+PILGRIMAGE/M/S
+PILL/M/S
+PILLAGE/D
+PILLAR/D/S
+PILLOW/M/S
+PILOT/G/S
+PIN/M/S
+PINCH/D/G/S
+PINE/D/G/N/S
+PINEAPPLE/M/S
+PING
+PINK/P/T/R/Y/S
+PINNACLE/M/S
+PINNED
+PINNING/S
+PINPOINT/G/S
+PINT/M/S
+PIONEER/D/G/S
+PIOUS/Y
+PIPE/D/R/Z/G/S
+PIPELINE/D/G/S
+PIQUE
+PIRATE/M/S
+PISTIL/M/S
+PISTOL/M/S
+PISTON/M/S
+PIT/M/S
+PITCH/D/R/Z/G/S
+PITEOUS/Y
+PITFALL/M/S
+PITH/D/G/S
+PITHY/P/T/R
+PITIABLE
+PITIFUL/Y
+PITILESS/Y
+PITTED
+PITTSBURGH/M
+PITY/D/R/Z/G/S
+PITYINGLY
+PIVOT/G/S
+PIVOTAL
+PIXEL/S
+PLACARD/M/S
+PLACE/D/R/G/S
+PLACEMENT/M/S
+PLACID/Y
+PLAGUE/D/G/S
+PLAID/M/S
+PLAIN/P/T/R/Y/S
+PLAINTIFF/M/S
+PLAINTIVE/P/Y
+PLAIT/M/S
+PLAN/M/S
+PLANAR
+PLANARITY
+PLANE'S
+PLANE/D/R/Z/G/S
+PLANET/M/S
+PLANETARY
+PLANK/G/S
+PLANNED
+PLANNER/M/S
+PLANNING
+PLANT/D/R/Z/G/J/S
+PLANTATION/M/S
+PLASMA
+PLASTER/D/R/G/S
+PLASTIC/S
+PLASTICITY
+PLATE/D/G/S
+PLATEAU/M/S
+PLATELET/M/S
+PLATEN/M/S
+PLATFORM/M/S
+PLATINUM
+PLATO
+PLATTER/M/S
+PLAUSIBILITY
+PLAUSIBLE
+PLAY/D/G/S
+PLAYABLE
+PLAYER/M/S
+PLAYFUL/P/Y
+PLAYGROUND/M/S
+PLAYMATE/M/S
+PLAYTHING/M/S
+PLAYWRIGHT/M/S
+PLAZA
+PLEA/M/S
+PLEAD/D/R/G/S
+PLEASANT/P/Y
+PLEASE/D/G/S
+PLEASINGLY
+PLEASURE/S
+PLEBEIAN
+PLEBISCITE/M/S
+PLEDGE/D/S
+PLENARY
+PLENTEOUS
+PLENTIFUL/Y
+PLENTY
+PLEURISY
+PLIGHT
+PLOD
+PLOT/M/S
+PLOTTED
+PLOTTER/M/S
+PLOTTING
+PLOUGH
+PLOUGHMAN
+PLOW/D/R/G/S
+PLOWMAN
+PLOY/M/S
+PLUCK/D/G
+PLUCKY
+PLUG/M/S
+PLUGGED
+PLUGGING
+PLUM/M/S
+PLUMAGE
+PLUMB/D/M/G/S
+PLUME/D/S
+PLUMMETING
+PLUMP/P/D
+PLUNDER/D/R/Z/G/S
+PLUNGE/D/R/Z/G/S
+PLURAL/S
+PLURALITY
+PLUS
+PLUSH
+PLY/D/Z/S
+PNEUMONIA
+POACH/R/S
+POCKET/D/G/S
+POCKETBOOK/M/S
+POD/M/S
+POEM/M/S
+POET/M/S
+POETIC/S
+POETICAL/Y
+POETRY/M/S
+POINT/D/R/Z/G/S
+POINTEDLY
+POINTLESS
+POINTY
+POISE/D/S
+POISON/D/R/G/S
+POISONOUS/P
+POKE/D/R/G/S
+POLAND
+POLAR
+POLARITY/M/S
+POLE/D/G/S
+POLEMIC/S
+POLICE/D/M/G/S
+POLICEMAN
+POLICEMEN
+POLICY/M/S
+POLISH/D/R/Z/G/S
+POLITE/P/T/R/Y
+POLITIC/S
+POLITICAL/Y
+POLITICIAN/M/S
+POLL/D/G/N/S
+POLLUTANT/S
+POLLUTE/D/G/N/S
+POLO
+POLYGON/S
+POLYGONAL
+POLYHEDRA
+POLYHEDRON
+POLYLINE
+POLYMER/M/S
+POLYMORPHIC
+POLYMORPHISM
+POLYNOMIAL/M/S
+POLYTECHNIC
+POMP
+POMPOUS/P/Y
+POND/R/S
+PONDER/D/G/S
+PONDEROUS
+PONY/M/S
+POOL/D/G/S
+POOR/P/T/R/Y
+POP/M/S
+POPLAR
+POPPED
+POPPING
+POPPY/M/S
+POPULACE
+POPULAR/Y
+POPULARITY
+POPULARIZATION
+POPULARIZE/D/G/S
+POPULATE/D/G/N/X/S
+POPULOUS/P
+PORCELAIN
+PORCH/M/S
+PORCUPINE/M/S
+PORE/D/G/S
+PORK/R
+PORNOGRAPHIC
+PORRIDGE
+PORT/R/Z/Y/S/D/G
+PORTABILITY
+PORTABLE
+PORTAL/M/S
+PORTEND/D/G/S
+PORTION/M/S
+PORTRAIT/M/S
+PORTRAY/D/G/S
+PORTUGUESE
+POSE/D/R/Z/G/S
+POSIT/D/G/S
+POSITION/D/G/S
+POSITIONAL
+POSITIVE/P/Y/S
+POSSESS/D/G/V/S
+POSSESSION/M/S
+POSSESSIONAL
+POSSESSIVE/P/Y
+POSSESSOR/M/S
+POSSIBILITY/M/S
+POSSIBLE
+POSSIBLY
+POSSUM/M/S
+POST/D/R/Z/G/S
+POSTAGE
+POSTAL
+POSTCONDITION
+POSTDOCTORAL
+POSTERIOR
+POSTERITY
+POSTMAN
+POSTMASTER/M/S
+POSTMODERNISM
+POSTOFFICE/M/S
+POSTPONE/D/G
+POSTSCRIPT/M/S
+POSTSTRUCTURALISM
+POSTSTRUCTURALIST
+POSTULATE/D/G/N/X/S
+POSTURE/M/S
+POT/M/S
+POTASH
+POTASSIUM
+POTATO
+POTATOES
+POTENT
+POTENTATE/M/S
+POTENTIAL/Y/S
+POTENTIALITY/S
+POTENTIATING
+POTENTIOMETER/M/S
+POTTED
+POTTER/M/S
+POTTERY
+POTTING
+POUCH/M/S
+POUGHKEEPSIE
+POULTRY
+POUNCE/D/G/S
+POUND/D/R/Z/G/S
+POUR/D/R/Z/G/S
+POUT/D/G/S
+POVERTY
+POWDER/D/G/S
+POWER/D/G/S
+POWERFUL/P/Y
+POWERLESS/P/Y
+POWERSET/M/S
+POX
+PRACTICABLE
+PRACTICABLY
+PRACTICAL/Y
+PRACTICALITY
+PRACTICE/D/G/S
+PRACTISE/D/G
+PRACTITIONER/M/S
+PRAGMATIC/S
+PRAGMATICALLY
+PRAIRIE
+PRAISE/D/R/Z/G/S
+PRAISINGLY
+PRANCE/D/R/G
+PRANK/M/S
+PRATE
+PRAY/D/G
+PRAYER/M/S
+PRE
+PREACH/D/R/Z/G/S
+PREAMBLE
+PREASSIGN/D/G/S
+PRECARIOUS/P/Y
+PRECAUTION/M/S
+PRECEDE/D/G/S
+PRECEDENCE/M/S
+PRECEDENT/D/S
+PRECEPT/M/S
+PRECINCT/M/S
+PRECIOUS/P/Y
+PRECIPICE
+PRECIPITATE/P/D/G/N/Y/S
+PRECIPITOUS/Y
+PRECISE/P/N/X/Y
+PRECLUDE/D/G/S
+PRECOCIOUS/Y
+PRECONCEIVE/D
+PRECONCEPTION/M/S
+PRECONDITION/D/S
+PRECURSOR/M/S
+PREDATE/D/G/S
+PREDECESSOR/M/S
+PREDEFINE/D/G/S
+PREDEFINITION/M/S
+PREDETERMINE/D/G/S
+PREDICAMENT
+PREDICATE/D/G/N/X/S
+PREDICT/D/G/V/S
+PREDICTABILITY
+PREDICTABLE
+PREDICTABLY
+PREDICTION/M/S
+PREDISPOSE/D/G
+PREDOMINANT/Y
+PREDOMINATE/D/G/N/Y/S
+PREEMPT/D/G/V/S
+PREEMPTION
+PREFACE/D/G/S
+PREFER/S
+PREFERABLE
+PREFERABLY
+PREFERENCE/M/S
+PREFERENTIAL/Y
+PREFERRED
+PREFERRING
+PREFIX/D/S
+PREGNANT
+PREHISTORIC
+PREINITIALIZE/D/G/S
+PREJUDGE/D
+PREJUDICE/D/S
+PRELATE
+PRELIMINARY/S
+PRELUDE/M/S
+PREMATURE/Y
+PREMATURITY
+PREMEDITATED
+PREMIER/M/S
+PREMISE/M/S
+PREMIUM/M/S
+PREOCCUPATION
+PREOCCUPY/D/S
+PREPARATION/M/S
+PREPARATIVE/M/S
+PREPARATORY
+PREPARE/D/G/S
+PREPOSITION/M/S
+PREPOSITIONAL
+PREPOSTEROUS/Y
+PREPROCESS/D/G
+PREPRODUCTION
+PREPROGRAMMED
+PREREQUISITE/M/S
+PREROGATIVE/M/S
+PRESBYTERIAN
+PRESCRIBE/D/S
+PRESCRIPTION/M/S
+PRESCRIPTIVE
+PRESELECT/D/G/S
+PRESENCE/M/S
+PRESENT/P/D/R/G/Y/S
+PRESENTATION/M/S
+PRESERVATION/S
+PRESERVE/D/R/Z/G/S
+PRESET
+PRESIDE/D/G/S
+PRESIDENCY
+PRESIDENT/M/S
+PRESIDENTIAL
+PRESS/D/R/G/J/S
+PRESSURE/D/G/S
+PRESSURIZE/D
+PRESTIGE
+PRESTO
+PRESUMABLY
+PRESUME/D/G/S
+PRESUMPTION/M/S
+PRESUMPTUOUS/P
+PRESUPPOSE/D/G/S
+PRESYNAPTIC
+PRETEND/D/R/Z/G/S
+PRETENSE/N/X/S
+PRETENTIOUS/P/Y
+PRETEXT/M/S
+PRETTILY
+PRETTY/P/T/R
+PREVAIL/D/G/S
+PREVAILINGLY
+PREVALENCE
+PREVALENT/Y
+PREVENT/D/G/V/S
+PREVENTABLE
+PREVENTABLY
+PREVENTION
+PREVENTIVES
+PREVIEW/D/G/S
+PREVIOUS/Y
+PREY/D/G/S
+PRICE/D/R/Z/G/S
+PRICELESS
+PRICK/D/G/Y/S
+PRIDE/D/G/S
+PRIMACY
+PRIMARILY
+PRIMARY/M/S
+PRIME/P/D/R/Z/G/S
+PRIMEVAL
+PRIMITIVE/P/Y/S
+PRIMROSE
+PRINCE/Y/S
+PRINCESS/M/S
+PRINCETON
+PRINCIPAL/Y/S
+PRINCIPALITY/M/S
+PRINCIPLE/D/S
+PRINT/D/R/Z/G/S
+PRINTABLE
+PRINTABLY
+PRINTOUT
+PRIOR
+PRIORI
+PRIORITY/M/S
+PRIORY
+PRISM/M/S
+PRISON/R/Z/S
+PRISONER'S
+PRIVACY/S
+PRIVATE/N/X/Y/S
+PRIVILEGE/D/S
+PRIVY/M/S
+PRIZE/D/R/Z/G/S
+PRO/M/S
+PROBABILISTIC
+PROBABILISTICALLY
+PROBABILITY/S
+PROBABLE
+PROBABLY
+PROBATE/D/G/N/V/S
+PROBE/D/G/J/S
+PROBLEM/M/S
+PROBLEMATIC
+PROBLEMATICAL/Y
+PROCEDURAL/Y
+PROCEDURE/M/S
+PROCEED/D/G/J/S
+PROCESS/D/M/G/S
+PROCESSION
+PROCESSOR/M/S
+PROCLAIM/D/R/Z/G/S
+PROCLAMATION/M/S
+PROCLIVITY/M/S
+PROCRASTINATE/D/G/N/S
+PROCURE/D/R/Z/G/S
+PROCUREMENT/M/S
+PRODIGAL/Y
+PRODIGIOUS
+PRODIGY
+PRODUCE/D/R/Z/G/S
+PRODUCIBLE
+PRODUCT/M/V/S
+PRODUCTION/M/S
+PRODUCTIVELY
+PRODUCTIVITY
+PROFANE/Y
+PROFESS/D/G/S
+PROFESSION/M/S
+PROFESSIONAL/Y/S
+PROFESSIONALISM
+PROFESSOR/M/S
+PROFFER/D/S
+PROFICIENCY
+PROFICIENT/Y
+PROFILE/D/G/S
+PROFIT/D/G/S/R/M/Z
+PROFITABILITY
+PROFITABLE
+PROFITABLY
+PROFITEER/M/S
+PROFOUND/T/Y
+PROG
+PROGENY
+PROGRAM/M/S
+PROGRAMMABILITY
+PROGRAMMABLE
+PROGRAMMED
+PROGRAMMER/M/S
+PROGRAMMING
+PROGRESS/D/G/V/S
+PROGRESSION/M/S
+PROGRESSIVE/Y
+PROHIBIT/D/G/V/S
+PROHIBITION/M/S
+PROHIBITIVELY
+PROJECT/D/G/V/S/M
+PROJECTION/M/S
+PROJECTIVELY
+PROJECTOR/M/S
+PROLEGOMENA
+PROLETARIAT
+PROLIFERATE/D/G/N/S
+PROLIFIC
+PROLOG
+PROLOGUE
+PROLONG/D/G/S
+PROMENADE/M/S
+PROMINENCE
+PROMINENT/Y
+PROMISE/D/G/S
+PROMONTORY
+PROMOTE/D/R/Z/G/N/X/S
+PROMOTIONAL
+PROMPT/P/D/T/R/Y/S
+PROMPTING/S
+PROMULGATE/D/G/N/S
+PRONE/P
+PRONG/D/S
+PRONOUN/M/S
+PRONOUNCE/D/G/S
+PRONOUNCEABLE
+PRONOUNCEMENT/M/S
+PRONUNCIATION/M/S
+PROOF/M/S
+PROP/R/S
+PROPAGANDA
+PROPAGATE/D/G/N/X/S
+PROPEL/S
+PROPELLED
+PROPELLER/M/S
+PROPENSITY
+PROPERLY
+PROPERNESS
+PROPERTY/D/S
+PROPHECY/M/S
+PROPHESY/D/R/S
+PROPHET/M/S
+PROPHETIC
+PROPITIOUS
+PROPONENT/M/S
+PROPORTION/D/G/S
+PROPORTIONAL/Y
+PROPORTIONATELY
+PROPORTIONMENT
+PROPOSAL/M/S
+PROPOSE/D/R/G/S
+PROPOSITION/D/G/S
+PROPOSITIONAL/Y
+PROPOUND/D/G/S
+PROPRIETARY
+PROPRIETOR/M/S
+PROPRIETY
+PROPULSION/M/S
+PROSE
+PROSECUTE/D/G/N/X/S
+PROSELYTIZE/D/G/S
+PROSODIC/S
+PROSPECT/D/G/V/S
+PROSPECTION/M/S
+PROSPECTIVELY
+PROSPECTIVES
+PROSPECTOR/M/S
+PROSPECTUS
+PROSPER/D/G/S
+PROSPERITY
+PROSPEROUS
+PROSTITUTION
+PROSTRATE/N
+PROTECT/D/G/V/S
+PROTECTION/M/S
+PROTECTIVELY
+PROTECTIVENESS
+PROTECTOR/M/S
+PROTECTORATE
+PROTEGE/M/S
+PROTEIN/M/S
+PROTEST/D/G/S/R/Z/M
+PROTESTATION/S
+PROTESTER'S
+PROTESTINGLY
+PROTESTOR/M/S
+PROTOCOL/M/S
+PROTON/M/S
+PROTOPLASM
+PROTOTYPE/D/G/S
+PROTOTYPICAL/Y
+PROTRUDE/D/G/S
+PROTRUSION/M/S
+PROVABILITY
+PROVABLE
+PROVABLY
+PROVE/D/R/Z/G/S
+PROVEN
+PROVERB/M/S
+PROVIDE/D/R/Z/G/S
+PROVIDENCE
+PROVINCE/M/S
+PROVINCIAL
+PROVINCIALISM
+PROVISION/D/G/S
+PROVISIONAL/Y
+PROVOCATION
+PROVOKE/D/S
+PROW/M/S
+PROWESS
+PROWL/D/R/Z/G
+PROXIMAL
+PROXIMATE
+PROXIMITY
+PRUDENCE
+PRUDENT/Y
+PRUNE/D/R/Z/G/S
+PRY/T/G
+PSALM/M/S
+PSEUDO
+PSYCHE/M/S
+PSYCHIATRIST/M/S
+PSYCHIATRY
+PSYCHOLOGICAL/Y
+PSYCHOLOGIST/M/S
+PSYCHOLOGY
+PSYCHOMETRIC
+PSYCHOSOCIAL
+PUB/M/S
+PUBLIC/Y
+PUBLICATION/M/S
+PUBLICITY
+PUBLICIZE/D/G/S
+PUBLISH/D/R/Z/G/S
+PUCKER/D/G/S
+PUDDING/M/S
+PUDDLE/G/S
+PUFF/D/G/S
+PULL/D/R/G/J/S
+PULLEY/M/S
+PULMONARY
+PULP/G
+PULPIT/M/S
+PULSE/D/G/S
+PUMP/D/G/S
+PUMPKIN/M/S
+PUN/M/S
+PUNCH/D/R/G/S
+PUNCTUAL/Y
+PUNCTUATION
+PUNCTURE/D/M/G/S
+PUNISH/D/G/S
+PUNISHABLE
+PUNISHMENT/M/S
+PUNITIVE
+PUNT/D/G/S
+PUNY
+PUP/M/S
+PUPA
+PUPIL/M/S
+PUPPET/M/S
+PUPPY/M/S
+PURCHASABLE
+PURCHASE/D/R/Z/G/S
+PURCHASEABLE
+PURE/T/R/Y
+PURGE/D/G/S
+PURIFY/D/R/Z/G/N/X/S
+PURITY
+PURPLE/T/R
+PURPORT/D/R/Z/G/S
+PURPORTEDLY
+PURPOSE/D/V/Y/S
+PURPOSEFUL/Y
+PURR/D/G/S
+PURSE/D/R/S
+PURSUE/D/R/Z/G/S
+PURSUIT/M/S
+PURVIEW
+PUSHDOWN
+PUSS
+PUSSY
+PUT/S
+PUTRID
+PUTTER/G/S
+PUTTING
+PUZZLE/D/R/Z/G/J/S
+PUZZLEMENT
+PYGMY/M/S
+PYRAMID/M/S
+QUACK/D/S
+QUADRANT/M/S
+QUADRATIC/S
+QUADRATICAL/Y
+QUADRATURE/M/S
+QUADRUPLE/D/G/S
+QUAGMIRE/M/S
+QUAIL/M/S
+QUAINT/P/Y
+QUAKE/D/R/Z/G/S
+QUALIFY/D/R/Z/G/N/X/S
+QUALITATIVE/Y
+QUALITY/M/S
+QUANDARY/M/S
+QUANTA
+QUANTIFIABLE
+QUANTIFY/D/R/Z/G/N/X/S
+QUANTITATIVE/Y
+QUANTITY/M/S
+QUANTIZATION
+QUANTIZE/D/G/S
+QUANTUM
+QUARANTINE/M/S
+QUARREL/D/G/S
+QUARRELSOME
+QUARRY/M/S
+QUART/Z/S
+QUARTER/D/G/Y/S
+QUARTET/M/S
+QUARTZ
+QUASH/D/G/S
+QUASI
+QUAVER/D/G/S
+QUAY
+QUEEN/M/Y/S
+QUEER/P/T/R/Y
+QUELL/G
+QUENCH/D/G/S
+QUERY/D/G/S
+QUEST/D/R/Z/G/S
+QUESTION/D/R/Z/G/J/S
+QUESTIONABLE
+QUESTIONABLY
+QUESTIONINGLY
+QUESTIONNAIRE/M/S
+QUEUE/D/R/Z/G/S
+QUICK/P/T/R/N/X/Y
+QUICKENED
+QUICKENING
+QUICKSILVER
+QUIESCENT
+QUIET/P/D/T/R/G/Y/S
+QUIETUDE
+QUILL
+QUILT/D/G/S
+QUININE
+QUIT/S
+QUITE
+QUITTER/M/S
+QUITTING
+QUIVER/D/G/S
+QUIXOTE
+QUIZ
+QUIZZED
+QUIZZES
+QUIZZING
+QUO/H
+QUOTA/M/S
+QUOTATION/M/S
+QUOTE/D/G/S
+QUOTIENT
+RABBIT/M/S
+RABBLE
+RACCOON/M/S
+RACE/D/R/Z/G/S
+RACIAL/Y
+RACK/D/G/S
+RACKET/M/S
+RACKETEER/G/S
+RADAR/M/S
+RADIAL/Y
+RADIAN/S
+RADIANCE
+RADIANT/Y
+RADIATE/D/G/N/X/S
+RADIATOR/M/S
+RADICAL/Y/S
+RADII
+RADIO/D/G/S
+RADIOLOGY
+RADISH/M/S
+RADIUS
+RADIX
+RAFT/R/Z/S
+RAG/M/S
+RAGE/D/G/S
+RAGGED/P/Y
+RAID/D/R/Z/G/S
+RAIL/D/R/Z/G/S
+RAILROAD/D/R/Z/G/S
+RAILWAY/M/S
+RAIMENT
+RAIN/D/G/S
+RAINBOW
+RAINCOAT/M/S
+RAINDROP/M/S
+RAINFALL
+RAINY/T/R
+RAISE/D/R/Z/G/S
+RAISIN
+RAKE/D/G/S
+RALLY/D/G/S
+RAM/M/S
+RAMBLE/R/G/J/S
+RAMIFICATION/M/S
+RAMP/M/S
+RAMPART
+RAN
+RANCH/D/R/Z/G/S
+RANDOLPH/M
+RANDOM/P/Y
+RANDY/M
+RANG
+RANGE/D/R/Z/G/S
+RANK/P/D/T/Y/S
+RANKER/M/S
+RANKING/M/S
+RANSACK/D/G/S
+RANSOM/R/G/S
+RANT/D/R/Z/G/S
+RAP/M/S
+RAPE/D/R/G/S
+RAPID/Y/S
+RAPIDITY
+RAPT/Y
+RAPTURE/M/S
+RAPTUROUS
+RARE/P/T/R/Y
+RARITY/M/S
+RASCAL/Y/S
+RASH/P/R/Y
+RASP/D/G/S
+RASPBERRY
+RASTER
+RASTEROP
+RAT/M/S
+RATE/D/R/Z/G/N/X/J/S
+RATHER
+RATIFY/D/G/N/S
+RATIO/M/S
+RATIONAL/Y
+RATIONALE/M/S
+RATIONALITY/S
+RATIONALIZE/D/G/S
+RATTLE/D/R/Z/G/S
+RATTLESNAKE/M/S
+RAVAGE/D/R/Z/G/S
+RAVE/D/G/J/S
+RAVEN/G/S
+RAVENOUS/Y
+RAVINE/M/S
+RAW/P/T/R/Y
+RAY/M/S
+RAZOR/M/S
+RE/D/Y/J
+REABBREVIATE/D/G/S
+REACH/D/R/G/S
+REACHABLE
+REACHABLY
+REACT/D/G/V/S
+REACTION/M/S
+REACTIONARY/M/S
+REACTIVATE/D/G/N/S
+REACTIVELY
+REACTIVITY
+REACTOR/M/S
+READ/R/Z/G/J/S
+READABILITY
+READABLE
+READILY
+READJUSTED
+READJUSTMENT
+READOUT/M/S
+READY/P/D/T/R/G/S
+REAL/P/S/T/Y
+REALIGN/D/G/S
+REALISM
+REALIST/M/S
+REALISTIC
+REALISTICALLY
+REALITY/S
+REALIZABLE
+REALIZABLY
+REALIZATION/M/S
+REALIZE/D/G/S
+REALM/M/S
+REANALYZE/G/S
+REAP/D/R/G/S
+REAPPEAR/D/G/S
+REAPPRAISAL/S
+REAR/D/G/S
+REARRANGE/D/G/S
+REARRANGEABLE
+REARRANGEMENT/M/S
+REARREST/D
+REASON/D/R/G/J/S
+REASONABLE/P
+REASONABLY
+REASSEMBLE/D/G/S
+REASSESSMENT/M/S
+REASSIGN/D/G/S
+REASSIGNMENT/M/S
+REASSURE/D/G/S
+REAWAKEN/D/G/S
+REBATE/M/S
+REBEL/M/S
+REBELLION/M/S
+REBELLIOUS/P/Y
+REBOUND/D/G/S
+REBROADCAST
+REBUFF/D
+REBUILD/G/S
+REBUILT
+REBUKE/D/G/S
+REBUTTAL
+RECALCULATE/D/G/N/X/S
+RECALL/D/G/S
+RECAPITULATE/D/N/S
+RECAPTURE/D/G/S
+RECAST/G/S
+RECEDE/D/G/S
+RECEIPT/M/S
+RECEIVABLE
+RECEIVE/D/R/Z/G/S
+RECENT/P/Y
+RECEPTACLE/M/S
+RECEPTION/M/S
+RECEPTIVE/P/Y
+RECEPTIVITY
+RECESS/D/V/S
+RECESSION
+RECIPE/M/S
+RECIPIENT/M/S
+RECIPROCAL/Y
+RECIPROCATE/D/G/N/S
+RECIPROCITY
+RECIRCULATE/D/G/S
+RECITAL/M/S
+RECITATION/M/S
+RECITE/D/R/G/S
+RECKLESS/P/Y
+RECKON/D/R/G/J/S
+RECLAIM/D/R/Z/G/S
+RECLAIMABLE
+RECLAMATION/S
+RECLASSIFY/D/G/N/S
+RECLINE/G
+RECODE/D/G/S
+RECOGNITION/M/S
+RECOGNIZABILITY
+RECOGNIZABLE
+RECOGNIZABLY
+RECOGNIZE/D/R/Z/G/S
+RECOIL/D/G/S
+RECOLLECT/D/G
+RECOLLECTION/M/S
+RECOMBINE/D/G/S
+RECOMMEND/D/R/G/S
+RECOMMENDATION/M/S
+RECOMPENSE
+RECOMPILATION
+RECOMPILE/D/G
+RECOMPUTE/D/G/S
+RECONCILE/D/R/G/S
+RECONCILIATION
+RECONFIGURABLE
+RECONFIGURATION/M/S
+RECONFIGURE/D/R/G/S
+RECONNECT/D/G/S
+RECONNECTION
+RECONSIDER/D/G/S
+RECONSIDERATION
+RECONSTRUCT/D/G/S
+RECONSTRUCTION
+RECORD/D/R/Z/G/J/S
+RECOUNT/D/G/S
+RECOURSE
+RECOVER/D/G/S
+RECOVERABLE
+RECOVERY/M/S
+RECREATE/D/G/N/X/V/S
+RECREATION/S
+RECREATIONAL
+RECRUIT/D/R/M/G/S
+RECRUITMENT
+RECTA
+RECTANGLE/M/S
+RECTANGULAR
+RECTIFY
+RECTOR/M/S
+RECTUM/M/S
+RECUR/S
+RECURRENCE/M/S
+RECURRENT/Y
+RECURRING
+RECURSE/D/G/N/S
+RECURSION/M/S
+RECURSIVE/Y
+RECYCLABLE
+RECYCLE/D/G/S
+RED/P/Y/S
+REDBREAST
+REDDEN/D
+REDDER
+REDDEST
+REDDISH/P
+REDECLARE/D/G/S
+REDEEM/D/R/Z/G/S
+REDEFINE/D/G/S
+REDEFINITION/M/S
+REDEMPTION
+REDESIGN/D/G/S
+REDEVELOPMENT
+REDIRECT/D/G
+REDIRECTING
+REDIRECTION/S
+REDISPLAY/D/G/S
+REDISTRIBUTE/D/G/S
+REDONE
+REDOUBLE/D
+REDRAW/G
+REDRAWN
+REDRESS/D/G/S
+REDUCE/D/R/Z/G/S
+REDUCIBILITY
+REDUCIBLE
+REDUCIBLY
+REDUCTION/M/S
+REDUNDANCY/S
+REDUNDANT/Y
+REED/M/S
+REEDUCATION
+REEF/R/S
+REEL/D/R/G/S
+REELECT/D/G/S
+REEMPHASIZE/D/G/S
+REENFORCEMENT
+REENTER/D/G/S
+REENTRANT
+REESTABLISH/D/G/S
+REEVALUATE/D/G/N/S
+REEXAMINE/D/G/S
+REFER/S
+REFEREE/D/S
+REFEREEING
+REFERENCE/D/R/G/S
+REFERENDUM
+REFERENT/M/S
+REFERENTIAL/Y
+REFERENTIALITY
+REFERRAL/M/S
+REFERRED
+REFERRING
+REFILL/D/G/S
+REFILLABLE
+REFINE/D/R/G/S
+REFINEMENT/M/S
+REFLECT/D/G/V/S
+REFLECTION/M/S
+REFLECTIVELY
+REFLECTIVITY
+REFLECTOR/M/S
+REFLEX/M/S
+REFLEXIVE/P/Y
+REFLEXIVITY
+REFORM/D/R/Z/G/S
+REFORMABLE
+REFORMAT/S
+REFORMATION
+REFORMATTED
+REFORMATTING
+REFORMULATE/D/G/N/S
+REFRACTORY
+REFRAIN/D/G/S
+REFRESH/D/R/Z/G/S
+REFRESHINGLY
+REFRESHMENT/M/S
+REFRIGERATOR/M/S
+REFUEL/D/G/S
+REFUGE
+REFUGEE/M/S
+REFUSAL
+REFUSE/D/G/S
+REFUTABLE
+REFUTATION
+REFUTE/D/R/G/S
+REGAIN/D/G/S
+REGAL/D/Y
+REGARD/D/G/S
+REGARDLESS
+REGENERATE/D/G/N/V/S
+REGENT/M/S
+REGIME/M/S
+REGIMEN
+REGIMENT/D/S
+REGION/M/S
+REGIONAL/Y
+REGISTER/D/G/S
+REGISTRATION/M/S
+REGRESS/D/G/V/S
+REGRESSION/M/S
+REGRET/S
+REGRETFUL/Y
+REGRETTABLE
+REGRETTABLY
+REGRETTED
+REGRETTING
+REGROUP/D/G
+REGULAR/Y/S
+REGULARITY/S
+REGULATE/D/G/N/X/V/S
+REGULATOR/M/S
+REHABILITATE/D/G/N
+REHEARSAL/M/S
+REHEARSE/D/R/G/S
+REIGN/D/G/S
+REIMBURSED
+REIMBURSEMENT/M/S
+REIMPLEMENT/D/G
+REIN/D/S
+REINCARNATE/D/N
+REINDEER
+REINFORCE/D/R/G/S
+REINFORCEMENT/M/S
+REINITIALIZE/D/G
+REINSERT/D/G/S
+REINSTATE/D/G/S
+REINSTATEMENT
+REINTERPRET/D/G/S
+REINTRODUCE/D/G/S
+REINVENT/D/G/S
+REITERATE/D/G/N/S
+REJECT/D/G/S
+REJECTION/M/S
+REJECTOR/M/S
+REJOICE/D/R/G/S
+REJOIN/D/G/S
+RELABEL/S/D/G/R/Z
+RELAPSE
+RELATE/D/R/G/N/X/S
+RELATIONAL/Y
+RELATIONSHIP/M/S
+RELATIVE/P/Y/S
+RELATIVISM
+RELATIVISTIC
+RELATIVISTICALLY
+RELATIVITY
+RELAX/D/R/G/S
+RELAXATION/M/S
+RELAY/D/G/S
+RELEARN/D/G
+RELEASE/D/G/S
+RELEGATE/D/G/S
+RELENT/D/G/S
+RELENTLESS/P/Y
+RELEVANCE/S
+RELEVANT/Y
+RELIABILITY
+RELIABLE/P
+RELIABLY
+RELIANCE
+RELIC/M/S
+RELIEF
+RELIEVE/D/R/Z/G/S
+RELIGION/M/S
+RELIGIOUS/P/Y
+RELINQUISH/D/G/S
+RELISH/D/G/S
+RELIVE/G/S
+RELOAD/D/R/G/S
+RELOCATE/D/G/N/X/S
+RELUCTANCE
+RELUCTANT/Y
+RELY/D/G/S
+REMAIN/D/G/S
+REMAINDER/M/S
+REMARK/D/G/S
+REMARKABLE/P
+REMARKABLY
+REMEDIAL
+REMEDY/D/G/S
+REMEMBER/D/G/S
+REMEMBRANCE/M/S
+REMIND/D/R/Z/G/S
+REMINISCENCE/M/S
+REMINISCENT/Y
+REMITTANCE
+REMNANT/M/S
+REMODEL/D/G/S
+REMONSTRATE/D/G/N/V/S
+REMORSE
+REMOTE/P/T/Y
+REMOVABLE
+REMOVAL/M/S
+REMOVE/D/R/G/S
+RENAISSANCE
+RENAL
+RENAME/D/G/S
+REND/Z/G/S
+RENDER/D/G/J/S
+RENDEZVOUS
+RENDITION/M/S
+RENEW/D/R/G/S
+RENEWAL
+RENOUNCE/G/S
+RENOWN/D
+RENT/D/G/S
+RENTAL/M/S
+RENUMBER/G/S
+REOPEN/D/G/S
+REORDER/D/G/S
+REORGANIZATION/M/S
+REORGANIZE/D/G/S
+REPAID
+REPAIR/D/R/G/S
+REPAIRMAN
+REPARATION/M/S
+REPAST/M/S
+REPAY/G/S
+REPEAL/D/R/G/S
+REPEAT/D/R/Z/G/S
+REPEATABLE
+REPEATEDLY
+REPEL/S
+REPENT/D/G/S
+REPENTANCE
+REPERCUSSION/M/S
+REPERTOIRE
+REPETITION/M/S
+REPETITIVE/P/Y
+REPHRASE/D/G/S
+REPINE
+REPLACE/D/R/G/S
+REPLACEABLE
+REPLACEMENT/M/S
+REPLAY/D/G/S
+REPLENISH/D/G/S
+REPLETE/P/N
+REPLICA
+REPLICATE/D/G/N/S
+REPLY/D/G/N/X/S
+REPORT/D/R/Z/G/S
+REPORTEDLY
+REPOSE/D/G/S
+REPOSITION/D/G/S
+REPOSITORY/M/S
+REPRESENT/D/G/S
+REPRESENTABLE
+REPRESENTABLY
+REPRESENTATION/M/S
+REPRESENTATIONAL/Y
+REPRESENTATIVE/P/Y/S
+REPRESS/D/G/V/S
+REPRESSION/M/S
+REPRIEVE/D/G/S
+REPRINT/D/G/S
+REPRISAL/M/S
+REPROACH/D/G/S
+REPRODUCE/D/R/Z/G/S
+REPRODUCIBILITY/S
+REPRODUCIBLE
+REPRODUCIBLY
+REPRODUCTION/M/S
+REPROGRAM/S
+REPROGRAMMED
+REPROGRAMMING
+REPROOF
+REPROVE/R
+REPTILE/M/S
+REPUBLIC/M/S
+REPUBLICAN/M/S
+REPUDIATE/D/G/N/X/S
+REPULSE/D/G/N/X/V/S
+REPUTABLE
+REPUTABLY
+REPUTATION/M/S
+REPUTE/D/S
+REPUTEDLY
+REQUEST/D/R/Z/G/S
+REQUIRE/D/G/S
+REQUIREMENT/M/S
+REQUISITE/X/S
+REQUISITION/D/G/S
+REREAD
+REROUTE/D/G/S
+RESCUE/D/R/Z/G/S
+RESEARCH/D/R/Z/G/S
+RESELECT/D/G/S
+RESEMBLANCE/M/S
+RESEMBLE/D/G/S
+RESENT/D/G/S
+RESENTFUL/Y
+RESENTMENT
+RESERVATION/M/S
+RESERVE/D/R/G/S
+RESERVOIR/M/S
+RESET/S
+RESETTING/S
+RESHAPE/D/G
+RESIDE/D/G/S
+RESIDENCE/M/S
+RESIDENT/M/S
+RESIDENTIAL/Y
+RESIDUE/M/S
+RESIGN/D/G/S
+RESIGNATION/M/S
+RESIN/M/S
+RESIST/D/G/V/S
+RESISTANCE/S
+RESISTANT/Y
+RESISTIBLE
+RESISTIBLY
+RESISTIVITY
+RESISTOR/M/S
+RESIZE/D/G
+RESOLUTE/P/N/X/Y
+RESOLVABLE
+RESOLVE/D/R/Z/G/S
+RESONANCE/S
+RESONANT
+RESORT/D/G/S
+RESOUND/G/S
+RESOURCE/M/S
+RESOURCEFUL/P/Y
+RESPECT/D/R/G/V/S
+RESPECTABILITY
+RESPECTABLE
+RESPECTABLY
+RESPECTFUL/P/Y
+RESPECTIVELY
+RESPIRATION
+RESPITE
+RESPLENDENT/Y
+RESPOND/D/R/G/S
+RESPONDENT/M/S
+RESPONSE/V/S
+RESPONSIBILITY/S
+RESPONSIBLE/P
+RESPONSIBLY
+RESPONSIVELY
+RESPONSIVENESS
+REST/D/G/V/S
+RESTART/D/G/S
+RESTATE/D/G/S
+RESTATEMENT
+RESTAURANT/M/S
+RESTFUL/P/Y
+RESTLESS/P/Y
+RESTORATION/M/S
+RESTORE/D/R/Z/G/S
+RESTRAIN/D/R/Z/G/S
+RESTRAINT/M/S
+RESTRICT/D/G/V/S
+RESTRICTION/M/S
+RESTRICTIVELY
+RESTRUCTURE/D/G/S
+RESULT/D/G/S
+RESULTANT/Y/S
+RESUMABLE
+RESUME/D/G/S
+RESUMPTION/M/S
+RESURRECT/D/G/S
+RESURRECTION/M/S
+RESURRECTOR/S
+RETAIL/R/Z/G
+RETAIN/D/R/Z/G/S
+RETAINMENT
+RETALIATION
+RETARD/D/R/G
+RETENTION/S
+RETENTIVE/P/Y
+RETHINK
+RETICLE/M/S
+RETICULAR
+RETICULATE/D/G/N/Y/S
+RETINA/M/S
+RETINAL
+RETINUE
+RETIRE/D/G/S
+RETIREMENT/M/S
+RETORT/D/S
+RETRACE/D/G
+RETRACT/D/G/S
+RETRACTION/S
+RETRAIN/D/G/S
+RETRANSMISSION/M/S
+RETRANSMIT/S
+RETRANSMITTED
+RETRANSMITTING
+RETREAT/D/G/S
+RETRIEVABLE
+RETRIEVAL/M/S
+RETRIEVE/D/R/Z/G/S
+RETROACTIVE
+RETROACTIVELY
+RETROSPECT/V
+RETROSPECTION
+RETRY/D/R/Z/G/S
+RETURN/D/R/G/S
+RETURNABLE
+RETYPE/D/G/S
+REUNION/M/S
+REUNITE/D/G
+REUSABILITY
+REUSABLE
+REUSE/D/G/S
+REVAMP/D/G/S
+REVEAL/D/G/S
+REVEL/D/R/G/S
+REVELATION/M/S
+REVELRY
+REVENGE/R
+REVENUE/Z/S
+REVERE/D/G/S
+REVERENCE
+REVEREND/M/S
+REVERENTLY
+REVERIFY/D/G/S
+REVERSAL/M/S
+REVERSE/D/R/G/N/Y/S
+REVERSIBLE
+REVERT/D/G/S
+REVIEW/D/R/Z/G/S
+REVILE/D/R/G
+REVISE/D/R/G/N/X/S
+REVISION/M/S
+REVISIT/D/G/S
+REVIVAL/M/S
+REVIVE/D/R/G/S
+REVOCATION
+REVOKE/D/R/G/S
+REVOLT/D/R/G/S
+REVOLTINGLY
+REVOLUTION/M/S
+REVOLUTIONARY/M/S
+REVOLUTIONIZE/D/R
+REVOLVE/D/R/Z/G/S
+REWARD/D/G/S
+REWARDINGLY
+REWIND/G/S
+REWORK/D/G/S
+REWOUND
+REWRITE/G/S
+REWRITTEN
+RHETORIC
+RHEUMATISM
+RHEUMATOLOGY
+RHINOCEROS
+RHUBARB
+RHYME/D/G/S
+RHYTHM/M/S
+RHYTHMIC
+RHYTHMICALLY
+RIB/M/S
+RIBBED
+RIBBING
+RIBBON/M/S
+RICE
+RICH/P/T/R/Y/S
+RICHARD/M
+RICK/M
+RICKSHAW/M/S
+RID
+RIDDEN
+RIDDLE/D/G/S
+RIDE/R/Z/G/S
+RIDGE/M/S
+RIDICULE/D/G/S
+RIDICULOUS/P/Y
+RIFLE/D/R/G/S
+RIFLEMAN
+RIFT
+RIG/M/S
+RIGGING
+RIGHT/P/D/R/G/Y/S
+RIGHTEOUS/P/Y
+RIGHTFUL/P/Y
+RIGHTMOST
+RIGHTWARD
+RIGID/Y
+RIGIDITY
+RIGOR/S
+RIGOROUS/Y
+RILL
+RIM/M/S
+RIME
+RIND/M/S
+RING/D/R/Z/G/J/S
+RINGINGLY
+RINSE/D/R/G/S
+RIOT/D/R/Z/G/S
+RIOTOUS
+RIP/N/S
+RIPE/P/Y
+RIPPED
+RIPPING
+RIPPLE/D/G/S
+RISE/R/Z/G/J/S
+RISEN
+RISK/D/G/S
+RITE/M/S
+RITUAL/Y/S
+RIVAL/D/S/G
+RIVALLED
+RIVALLING
+RIVALRY/M/S
+RIVER/M/S
+RIVERSIDE
+RIVET/R/S
+RIVULET/M/S
+ROAD/M/S
+ROADSIDE
+ROADSTER/M/S
+ROADWAY/M/S
+ROAM/D/G/S
+ROAR/D/R/G/S
+ROAST/D/R/G/S
+ROB/S/M
+ROBBED
+ROBBER/M/S
+ROBBERY/M/S
+ROBBING
+ROBE/D/G/S
+ROBERT/M
+ROBIN/M/S
+ROBOT/M/S
+ROBOTIC
+ROBOTICS
+ROBUST/P/Y
+ROCK/D/R/Z/G/S
+ROCKET/D/G/S
+ROCKY/S
+ROD/M/S
+RODE
+ROE
+ROGER/M
+ROGUE/M/S
+ROLE/M/S
+ROLL/D/R/Z/G/S
+ROMAN
+ROMANCE/R/Z/G/S
+ROMANTIC/M/S
+ROMP/D/R/G/S
+ROOF/D/R/G/S
+ROOK
+ROOM/D/R/Z/G/S
+ROOST/R/Z
+ROOT/D/R/M/G/S
+ROPE/D/R/Z/G/S
+ROSE/M/S
+ROSEBUD/M/S
+ROSY/P
+ROT/S
+ROTARY
+ROTATE/D/G/N/X/S
+ROTATOR
+ROTTEN/P
+ROUGE
+ROUGH/P/D/T/R/N/Y
+ROUND/P/D/T/R/G/Y/S
+ROUNDABOUT
+ROUNDEDNESS
+ROUNDOFF
+ROUSE/D/G/S
+ROUT
+ROUTE/D/R/Z/G/J/S
+ROUTINE/Y/S
+ROVE/D/R/G/S
+ROW/D/R/G/S
+ROY/M
+ROYAL/Y
+ROYALIST/M/S
+ROYALTY/M/S
+RUB/X/S
+RUBBED
+RUBBER/M/S
+RUBBING
+RUBBISH
+RUBBLE
+RUBLE/M/S
+RUBOUT
+RUBY/M/S
+RUDDER/M/S
+RUDDY/P
+RUDE/P/Y
+RUDIMENT/M/S
+RUDIMENTARY
+RUE
+RUEFULLY
+RUFFIAN/Y/S
+RUFFLE/D/S
+RUG/M/S
+RUGGED/P/Y
+RUIN/D/G/S
+RUINATION/M/S
+RUINOUS/Y
+RULE/D/R/Z/G/J/S
+RUM/N
+RUMBLE/D/R/G/S
+RUMOR/D/S
+RUMP/Y
+RUMPLE/D
+RUN/S
+RUNAWAY
+RUNG/M/S
+RUNNER/M/S
+RUNNING
+RUNTIME
+RUPTURE/D/G/S
+RURAL/Y
+RUSH/D/R/G/S
+RUSSELL/M
+RUSSET
+RUSSIAN/M/S
+RUST/D/G/S
+RUSTIC
+RUSTICATE/D/G/N/S
+RUSTLE/D/R/Z/G
+RUSTY
+RUT/M/S
+RUTGERS
+RUTH/M
+RUTHLESS/P/Y
+RYE
+SABER/M/S
+SABLE/M/S
+SABOTAGE
+SACK/R/G/S
+SACRED/P/Y
+SACRIFICE/D/R/Z/G/S
+SACRIFICIAL/Y
+SAD/P/Y
+SADDEN/D/S
+SADDER
+SADDEST
+SADDLE/D/S
+SADISM
+SADIST/M/S
+SADISTIC
+SADISTICALLY
+SAFE/P/T/R/Y/S
+SAFEGUARD/D/G/S
+SAFETY/S
+SAG/S
+SAGACIOUS
+SAGACITY
+SAGE/Y/S
+SAID
+SAIL/D/G/S
+SAILOR/Y/S
+SAINT/D/Y/S
+SAKE/S
+SALABLE
+SALAD/M/S
+SALARY/D/S
+SALE/M/S
+SALESMAN
+SALESMEN
+SALIENT
+SALINE
+SALIVA
+SALLOW
+SALLY/G/S
+SALMON
+SALON/M/S
+SALOON/M/S
+SALT/D/R/Z/G/S
+SALTY/P/T/R
+SALUTARY
+SALUTATION/M/S
+SALUTE/D/G/S
+SALVAGE/D/R/G/S
+SALVATION
+SALVE/R/S
+SAM/M
+SAME/P
+SAMPLE/D/R/Z/G/J/S
+SAN
+SANCTIFY/D/N
+SANCTION/D/G/S
+SANCTITY
+SANCTUARY/M/S
+SAND/D/R/Z/G/S
+SANDAL/M/S
+SANDPAPER
+SANDSTONE
+SANDWICH/S
+SANDY
+SANE/T/R/Y
+SANG
+SANGUINE
+SANITARIUM
+SANITARY
+SANITATION
+SANITY
+SANK
+SANTA/M
+SAP/M/S
+SAPLING/M/S
+SAPPHIRE
+SARCASM/M/S
+SARCASTIC
+SASH
+SAT
+SATCHEL/M/S
+SATE/D/G/S
+SATELLITE/M/S
+SATIN
+SATIRE/M/S
+SATISFACTION/M/S
+SATISFACTORILY
+SATISFACTORY
+SATISFIABILITY
+SATISFIABLE
+SATISFY/D/G/S
+SATURATE/D/G/N/S
+SATURDAY/M/S
+SATYR
+SAUCE/R/Z/S
+SAUCEPAN/M/S
+SAUCY
+SAUL/M
+SAUNA
+SAUNTER
+SAUSAGE/M/S
+SAVAGE/P/D/R/Z/G/Y/S
+SAVE/D/R/Z/G/J/S
+SAVIOR/M/S
+SAVOR/D/G/S
+SAVORY
+SAW/D/G/S
+SAWMILL/M/S
+SAWTOOTH
+SAY/R/Z/G/J/S
+SCABBARD/M/S
+SCAFFOLD/G/J/S
+SCALABLE
+SCALAR/M/S
+SCALD/D/G
+SCALE/D/G/J/S
+SCALLOP/D/S
+SCALP/M/S
+SCALY
+SCAMPER/G/S
+SCAN/S
+SCANDAL/M/S
+SCANDALOUS
+SCANNED
+SCANNER/M/S
+SCANNING
+SCANT/Y
+SCANTILY
+SCANTY/P/T/R
+SCAR/M/S
+SCARCE/P/Y
+SCARCITY
+SCARE/D/G/S
+SCARF
+SCARLET
+SCARY
+SCATTER/D/G/S
+SCENARIO/M/S
+SCENE/M/S
+SCENERY
+SCENIC
+SCENT/D/S
+SCEPTER/M/S
+SCHEDULE/D/R/Z/G/S
+SCHEMA/M/S
+SCHEMATA
+SCHEMATIC/S
+SCHEMATICALLY
+SCHEME'S
+SCHEME/D/R/Z/G/S
+SCHENLEY
+SCHIZOPHRENIA
+SCHOLAR/Y/S
+SCHOLARSHIP/M/S
+SCHOLASTIC/S
+SCHOLASTICALLY
+SCHOOL/D/R/Z/G/S
+SCHOOLBOY/M/S
+SCHOOLHOUSE/M/S
+SCHOOLMASTER/M/S
+SCHOOLMATE
+SCHOOLROOM/M/S
+SCHOONER
+SCIENCE/M/S
+SCIENTIFIC
+SCIENTIFICALLY
+SCIENTIST/M/S
+SCISSOR/D/G/S
+SCOFF/D/R/G/S
+SCOLD/D/G/S
+SCOOP/D/G/S
+SCOPE/D/G/S
+SCORCH/D/R/G/S
+SCORE/D/R/Z/G/J/S
+SCORN/D/R/G/S
+SCORNFUL/Y
+SCORPION/M/S
+SCOTLAND
+SCOTT/M
+SCOUNDREL/M/S
+SCOUR/D/G/S
+SCOURGE
+SCOUT/D/G/S
+SCOW
+SCOWL/D/G/S
+SCRAMBLE/D/R/G/S
+SCRAP/M/S
+SCRAPE/D/R/Z/G/J/S
+SCRAPPED
+SCRATCH/D/R/Z/G/S
+SCRATCHPAD/M/S
+SCRAWL/D/G/S
+SCREAM/D/R/Z/G/S
+SCREECH/D/G/S
+SCREEN/D/G/J/S
+SCREW/D/G/S
+SCRIBBLE/D/R/S
+SCRIBE/G/S
+SCRIPT/M/S
+SCRIPTURE/S
+SCROLL/D/G/S
+SCRUB
+SCRUPLE
+SCRUPULOUS/Y
+SCRUTINIZE/D/G
+SCRUTINY
+SCS
+SCUFFLE/D/G/S
+SCULPT/D/S
+SCULPTOR/M/S
+SCULPTURE/D/S
+SCURRY/D
+SCUTTLE/D/G/S
+SCYTHE/M/S
+SEA/Y/S
+SEABOARD
+SEACOAST/M/S
+SEAL/D/R/G/S
+SEALEVEL
+SEAM/D/G/N/S
+SEAMAN
+SEAN/M
+SEAPORT/M/S
+SEAR/D/G/S
+SEARCH/D/R/Z/G/J/S
+SEARCHINGLY
+SEARING/Y
+SEASHORE/M/S
+SEASIDE
+SEASON/D/R/Z/G/J/S
+SEASONABLE
+SEASONABLY
+SEASONAL/Y
+SEAT/D/G/S
+SEAWARD
+SEAWEED
+SECEDE/D/G/S
+SECLUDED
+SECLUSION
+SECOND/D/R/Z/G/Y/S
+SECONDARILY
+SECONDARY
+SECONDHAND
+SECRECY
+SECRET/Y/S
+SECRETARIAL
+SECRETARY/M/S
+SECRETE/D/G/N/X/V/S
+SECRETIVELY
+SECT/M/S
+SECTION/D/G/S
+SECTIONAL
+SECTOR/M/S
+SECULAR
+SECURE/D/G/Y/J/S
+SECURITY/S
+SEDGE
+SEDIMENT/M/S
+SEDUCE/D/R/Z/G/S
+SEDUCTIVE
+SEE/R/Z/S
+SEED/D/R/Z/G/J/S
+SEEDLING/M/S
+SEEING
+SEEK/R/Z/G/S
+SEEM/D/G/Y/S
+SEEMINGLY
+SEEN
+SEEP/D/G/S
+SEETHE/D/G/S
+SEGMENT/D/G/S
+SEGMENTATION/M/S
+SEGREGATE/D/G/N/S
+SEISMIC
+SEIZE/D/G/S
+SEIZURE/M/S
+SELDOM
+SELECT/D/G/V/S
+SELECTABLE
+SELECTION/M/S
+SELECTIVE/Y
+SELECTIVITY
+SELECTOR/M/S
+SELF
+SELFISH/P/Y
+SELFSAME
+SELL/R/Z/G/S
+SELVES
+SEMANTIC/S
+SEMANTICAL/Y
+SEMANTICIST/M/S
+SEMAPHORE/M/S
+SEMBLANCE
+SEMESTER/M/S
+SEMI
+SEMIAUTOMATED
+SEMIAUTOMATIC
+SEMICOLON/M/S
+SEMICONDUCTOR/M/S
+SEMINAL
+SEMINAR/M/S
+SEMINARY/M/S
+SEMIPERMANENT/Y
+SENATE/M/S
+SENATOR/M/S
+SEND/R/Z/G/S
+SENIOR/M/S
+SENIORITY
+SENSATION/M/S
+SENSATIONAL/Y
+SENSE/D/G/S
+SENSELESS/P/Y
+SENSIBILITY/S
+SENSIBLE
+SENSIBLY
+SENSITIVE/P/Y/S
+SENSITIVITY/S
+SENSOR/M/S
+SENSORY
+SENT
+SENTENCE/D/G/S
+SENTENTIAL
+SENTIMENT/M/S
+SENTIMENTAL/Y
+SENTINEL/M/S
+SENTRY/M/S
+SEPARABLE
+SEPARATE/P/D/G/N/X/Y/S
+SEPARATOR/M/S
+SEPTEMBER
+SEPULCHER/M/S
+SEQUEL/M/S
+SEQUENCE/D/R/Z/G/J/S
+SEQUENTIAL/Y
+SEQUENTIALITY
+SEQUENTIALIZE/D/G/S
+SEQUESTER
+SERENDIPITOUS
+SERENDIPITY
+SERENE/Y
+SERENITY
+SERF/M/S
+SERGEANT/M/S
+SERIAL/Y/S
+SERIALIZATION/M/S
+SERIALIZE/D/G/S
+SERIES
+SERIOUS/P/Y
+SERMON/M/S
+SERPENT/M/S
+SERPENTINE
+SERUM/M/S
+SERVANT/M/S
+SERVE/D/R/Z/G/J/S
+SERVICE/D/G/S
+SERVICEABLE
+SERVILE
+SERVITUDE
+SESAME
+SESSION/M/S
+SET/M/S
+SETTER/M/S
+SETTING/S
+SETTLE/D/R/Z/G/S
+SETTLEMENT/M/S
+SETUP/S
+SEVEN/H/S
+SEVENTEEN/H/S
+SEVENTY/H/S
+SEVER/S
+SEVERAL/Y
+SEVERANCE
+SEVERE/D/T/R/G/Y
+SEVERITY/M/S
+SEW/D/R/Z/G/S
+SEX/D/S
+SEXUAL/Y
+SEXUALITY
+SHABBY
+SHACK/D/S
+SHACKLE/D/G/S
+SHADE/D/G/J/S
+SHADILY
+SHADOW/D/G/S
+SHADOWY
+SHADY/P/T/R
+SHAFT/M/S
+SHAGGY
+SHAKABLE
+SHAKABLY
+SHAKE/R/Z/G/S
+SHAKEN
+SHAKY/P
+SHALE
+SHALL
+SHALLOW/P/R/Y
+SHAM/M/S
+SHAMBLES
+SHAME/D/G/S
+SHAMEFUL/Y
+SHAMELESS/Y
+SHAN'T
+SHANGHAI
+SHANTY/M/S
+SHAPE/D/R/Z/G/Y/S
+SHAPELESS/P/Y
+SHARABLE
+SHARE/D/R/Z/G/S
+SHARECROPPER/M/S
+SHAREHOLDER/M/S
+SHARK/M/S
+SHARON/M
+SHARP/P/T/R/N/X/Y
+SHARPENED
+SHARPENING
+SHATTER/D/G/S
+SHAVE/D/G/J/S
+SHAVEN
+SHAWL/M/S
+SHE'LL
+SHE/M
+SHEAF
+SHEAR/D/R/G/S
+SHEATH/G
+SHEATHS
+SHEAVES
+SHED/S
+SHEEP
+SHEER/D
+SHEET/D/G/S
+SHELF
+SHELL/D/R/G/S
+SHELTER/D/G/S
+SHELVE/D/G/S
+SHEPHERD/M/S
+SHERIFF/M/S
+SHIELD/D/G/S
+SHIFT/D/R/Z/G/S
+SHIFTILY
+SHIFTY/P/T/R
+SHILLING/S
+SHIMMER/G
+SHIN
+SHINE/D/R/Z/G/S
+SHINGLE/M/S
+SHININGLY
+SHINY
+SHIP/M/S
+SHIPBOARD
+SHIPBUILDING
+SHIPMENT/M/S
+SHIPPED
+SHIPPER/M/S
+SHIPPING
+SHIPWRECK/D/S
+SHIRK/R/G/S
+SHIRT/G/S
+SHIVER/D/R/G/S
+SHOAL/M/S
+SHOCK/D/R/Z/G/S
+SHOCKINGLY
+SHOD
+SHOE/D/S
+SHOEING
+SHOEMAKER
+SHONE
+SHOOK
+SHOOT/R/Z/G/J/S
+SHOP/M/S
+SHOPKEEPER/M/S
+SHOPPED
+SHOPPER/M/S
+SHOPPING
+SHORE/M/S
+SHORN
+SHORT/P/D/T/R/G/Y/S
+SHORTAGE/M/S
+SHORTCOMING/M/S
+SHORTCUT/M/S
+SHORTEN/D/G/S
+SHORTHAND/D
+SHOT/M/S
+SHOTGUN/M/S
+SHOULD/Z
+SHOULDER/D/G/S
+SHOULDN'T
+SHOUT/D/R/Z/G/S
+SHOVE/D/G/S
+SHOVEL/D/S
+SHOW/D/R/Z/G/J/S
+SHOWER/D/G/S
+SHOWN
+SHRANK
+SHRED/M/S
+SHREW/M/S
+SHREWD/P/T/Y
+SHRIEK/D/G/S
+SHRILL/P/D/G
+SHRILLY
+SHRIMP
+SHRINE/M/S
+SHRINK/G/S
+SHRINKABLE
+SHRIVEL/D
+SHROUD/D
+SHRUB/M/S
+SHRUBBERY
+SHRUG/S
+SHRUNK/N
+SHUDDER/D/G/S
+SHUFFLE/D/G/S
+SHUN/S
+SHUT/S
+SHUTDOWN/M/S
+SHUTTER/D/S
+SHUTTING
+SHUTTLE/D/G/S
+SHY/D/Y/S
+SHYNESS
+SIBLING/M/S
+SICK/T/R/N/Y
+SICKLE
+SICKNESS/M/S
+SIDE/D/G/J/S
+SIDEBOARD/M/S
+SIDEBURN/M/S
+SIDELIGHT/M/S
+SIDEWALK/M/S
+SIDEWAYS
+SIDEWISE
+SIEGE/M/S
+SIEMENS
+SIERRA
+SIEVE/M/S
+SIFT/D/R/G
+SIGH/D/G
+SIGHS
+SIGHT/D/G/Y/J/S
+SIGMA
+SIGN/D/R/Z/G/S
+SIGNAL/D/G/Y/S/R
+SIGNALLED
+SIGNALLER
+SIGNALLING
+SIGNATURE/M/S
+SIGNET
+SIGNIFICANCE
+SIGNIFICANT/Y/S
+SIGNIFY/D/G/N/S
+SIGNOR
+SIKKIM
+SILENCE/D/R/Z/G/S
+SILENT/Y
+SILHOUETTE/D/S
+SILICON
+SILICONE
+SILK/N/S
+SILKILY
+SILKINE
+SILKY/T/R
+SILL/M/S
+SILLY/P/T
+SILT/D/G/S
+SILVER/D/G/S
+SILVERY
+SIMILAR/Y
+SIMILARITY/S
+SIMILITUDE
+SIMMER/D/G/S
+SIMON/M
+SIMPLE/P/T/R
+SIMPLEX
+SIMPLICITY/M/S
+SIMPLIFY/D/R/Z/G/N/X/S
+SIMPLISTIC
+SIMPLY
+SIMULATE/D/G/N/X/S
+SIMULATOR/M/S
+SIMULTANEITY
+SIMULTANEOUS/Y
+SIN/M/S
+SINCE
+SINCERE/T/Y
+SINCERITY
+SINE/S
+SINEW/M/S
+SINFUL/P/Y
+SING/D/R/Z/G/Y/S
+SINGABLE
+SINGAPORE
+SINGINGLY
+SINGLE/P/D/G/S
+SINGLETON/M/S
+SINGULAR/Y
+SINGULARITY/M/S
+SINISTER
+SINK/D/R/Z/G/S
+SINNED
+SINNER/M/S
+SINNING
+SINUSITIS
+SINUSOIDAL
+SINUSOIDS
+SIP/S
+SIR/N/X/S
+SIRE/D/S
+SIRUP
+SISTER/Y/S
+SIT/S
+SITE/D/G/S
+SITTER/M/S
+SITTING/S
+SITUATE/D/G/N/X/S
+SITUATIONAL/Y
+SIX/H/S
+SIXPENCE
+SIXTEEN/H/S
+SIXTY/H/S
+SIZABLE
+SIZE/D/G/J/S
+SKATE/D/R/Z/G/S
+SKELETAL
+SKELETON/M/S
+SKEPTIC/M/S
+SKEPTICAL/Y
+SKETCH/D/G/S
+SKETCHILY
+SKETCHY
+SKEW/D/R/Z/G/S
+SKI/G/S
+SKILL/D/S
+SKILLFUL/P/Y
+SKIM/M/S
+SKIMP/D/G/S
+SKIN/M/S
+SKINNED
+SKINNER/M/S
+SKINNING
+SKIP/S
+SKIPPED
+SKIPPER/M/S
+SKIPPING
+SKIRMISH/D/R/Z/G/S
+SKIRT/D/G/S
+SKULK/D/R/G/S
+SKULL/M/S
+SKUNK/M/S
+SKY/M/S
+SKYLARK/G/S
+SKYLIGHT/M/S
+SKYSCRAPER/M/S
+SLAB
+SLACK/P/R/G/N/Y/S
+SLAIN
+SLAM/S
+SLAMMED
+SLAMMING
+SLANDER/R/S
+SLANG
+SLANT/D/G/S
+SLAP/S
+SLAPPED
+SLAPPING
+SLASH/D/G/S
+SLAT/M/S
+SLATE/D/R/S
+SLAUGHTER/D/G/S
+SLAVE/R/S
+SLAVERY
+SLAY/R/Z/G/S
+SLED/M/S
+SLEDGE/M/S
+SLEEK
+SLEEP/R/Z/G/S
+SLEEPILY
+SLEEPLESS/P/Y
+SLEEPY/P
+SLEET
+SLEEVE/M/S
+SLEIGH
+SLEIGHS
+SLENDER/R
+SLEPT
+SLEW/G
+SLICE/D/R/Z/G/S
+SLICK/R/Z/S
+SLID
+SLIDE/R/Z/G/S
+SLIGHT/P/D/T/R/G/Y/S
+SLIM/Y
+SLIME/D
+SLIMY
+SLING/G/S
+SLIP/M/S
+SLIPPAGE
+SLIPPED
+SLIPPER/M/S
+SLIPPERY/P
+SLIPPING
+SLIT/M/S
+SLOGAN/M/S
+SLOP/S
+SLOPE/D/R/Z/G/S
+SLOPPED
+SLOPPING
+SLOPPY/P
+SLOT/M/S
+SLOTH
+SLOTHS
+SLOTTED
+SLOUCH/D/G/S
+SLOW/P/D/T/R/G/Y/S
+SLUG/S
+SLUGGISH/P/Y
+SLUM/M/S
+SLUMBER/D
+SLUMP/D/S
+SLUNG
+SLUR/M/S
+SLY/Y
+SMACK/D/G/S
+SMALL/P/T/R
+SMALLPOX
+SMALLTALK
+SMART/P/D/T/R/Y
+SMASH/D/R/Z/G/S
+SMASHINGLY
+SMEAR/D/G/S
+SMELL/D/G/S
+SMELLY
+SMELT/R/S
+SMILE/D/G/S
+SMILINGLY
+SMITE
+SMITH
+SMITHS
+SMITHY
+SMITTEN
+SMOCK/G/S
+SMOG
+SMOKABLE
+SMOKE/D/R/Z/G/S
+SMOKY/S
+SMOLDER/D/G/S
+SMOOTH/P/D/T/R/G/Y/S
+SMOTE
+SMOTHER/D/G/S
+SMUGGLE/D/R/Z/G/S
+SNAIL/M/S
+SNAKE/D/S
+SNAP/S
+SNAPPED
+SNAPPER/M/S
+SNAPPILY
+SNAPPING
+SNAPPY
+SNAPSHOT/M/S
+SNARE/D/G/S
+SNARL/D/G
+SNATCH/D/G/S
+SNEAK/D/R/Z/G/S
+SNEAKILY
+SNEAKY/P/T/R
+SNEER/D/G/S
+SNEEZE/D/G/S
+SNIFF/D/G/S
+SNOOP/D/G/S
+SNORE/D/G/S
+SNORT/D/G/S
+SNOUT/M/S
+SNOW/D/G/S
+SNOWILY
+SNOWMAN
+SNOWMEN
+SNOWSHOE/M/S
+SNOWY/T/R
+SNUFF/D/R/G/S
+SNUG/P/Y
+SNUGGLE/D/G/S
+SO
+SOAK/D/G/S
+SOAP/D/G/S
+SOAR/D/G/S
+SOB/R/S
+SOBER/P/D/G/Y/S
+SOCCER
+SOCIABILITY
+SOCIABLE
+SOCIABLY
+SOCIAL/Y
+SOCIALISM
+SOCIALIST/M/S
+SOCIALIZATION
+SOCIALIZE/D/G/S
+SOCIETAL
+SOCIETY/M/S
+SOCIOLOGICAL/Y
+SOCIOLOGY
+SOCK/D/G/S
+SOCKET/M/S
+SOD/M/S
+SODA
+SODIUM
+SODOMY
+SOFA/M/S
+SOFT/P/T/R/X/Y
+SOFTEN/D/G/S
+SOFTWARE/M/S
+SOIL/D/G/S
+SOJOURN/R/Z
+SOLACE/D
+SOLAR
+SOLD/R
+SOLDIER/G/Y/S
+SOLE/Y/S
+SOLEMN/P/Y
+SOLEMNITY
+SOLICIT/D/G/S
+SOLICITOR
+SOLID/P/Y/S
+SOLIDIFY/D/G/N/S
+SOLIDITY
+SOLITAIRE
+SOLITARY
+SOLITUDE/M/S
+SOLO/M/S
+SOLUBILITY
+SOLUBLE
+SOLUTION/M/S
+SOLVABLE
+SOLVE/D/R/Z/G/S
+SOLVENT/M/S
+SOMBER/Y
+SOME
+SOMEBODY
+SOMEDAY
+SOMEHOW
+SOMEONE/M
+SOMETHING
+SOMETIME/S
+SOMEWHAT
+SOMEWHERE
+SON/M/S
+SONAR
+SONG/M/S
+SONNET/M/S
+SOON/T/R
+SOOT
+SOOTH
+SOOTHE/D/R/G/S
+SOPHIE/M
+SOPHISTICATED
+SOPHISTICATION
+SOPHOMORE/M/S
+SORCERER/M/S
+SORCERY
+SORDID/P/Y
+SORE/P/T/R/Y/S
+SORROW/M/S
+SORROWFUL/Y
+SORRY/T/R
+SORT/D/R/Z/G/S
+SOUGHT
+SOUL/M/S
+SOUND/P/D/T/R/Y/S
+SOUNDING/M/S
+SOUP/M/S
+SOUR/P/D/T/R/G/Y/S
+SOURCE/M/S
+SOUTH
+SOUTHERN/R/Z
+SOVEREIGN/M/S
+SOVIET/M/S
+SOY
+SPACE/D/R/Z/G/J/S
+SPACECRAFT/S
+SPACESHIP/M/S
+SPADE/D/G/S
+SPAGHETTI
+SPAIN
+SPAN/M/S
+SPANISH
+SPANK/D/G/S
+SPANKINGLY
+SPANNED
+SPANNER/M/S
+SPANNING
+SPARE/P/D/T/R/G/Y/S
+SPARINGLY
+SPARK/D/G/S
+SPARROW/M/S
+SPARSE/P/T/R/Y
+SPAT
+SPATE/M/S
+SPATIAL/Y
+SPATTER/D
+SPAWN/D/G/S
+SPEAK/R/Z/G/S
+SPEAKABLE
+SPEAR/D/S
+SPECIAL/Y/S
+SPECIALIST/M/S
+SPECIALIZATION/M/S
+SPECIALIZE/D/G/S
+SPECIALTY/M/S
+SPECIES
+SPECIFIABLE
+SPECIFIC/S
+SPECIFICALLY
+SPECIFICITY
+SPECIFY/D/R/Z/G/N/X/S
+SPECIMEN/M/S
+SPECK/M/S
+SPECKLE/D/S
+SPECTACLE/D/S
+SPECTACULAR/Y
+SPECTATOR/M/S
+SPECTER/M/S
+SPECTRA
+SPECTROGRAM/M/S
+SPECTRUM
+SPECULATE/D/G/N/X/V/S
+SPECULATOR/M/S
+SPED
+SPEECH/M/S
+SPEECHLESS/P
+SPEED/D/R/Z/G/S
+SPEEDILY
+SPEEDUP/M/S
+SPEEDY
+SPELL/D/R/Z/G/J/S
+SPENCER
+SPEND/R/Z/G/S
+SPENT
+SPHERE/M/S
+SPHERICAL/Y
+SPICE/D/S
+SPICY/P
+SPIDER/M/S
+SPIKE/D/S
+SPILL/D/R/G/S
+SPIN/S
+SPINACH
+SPINAL/Y
+SPINDLE/G
+SPINE
+SPINNER/M/S
+SPINNING
+SPIRAL/D/G/Y
+SPIRE/M/S
+SPIRIT/D/G/S
+SPIRITEDLY
+SPIRITUAL/Y/S
+SPIT/S
+SPITE/D/G/S
+SPITEFUL/P/Y
+SPITTING
+SPLASH/D/G/S
+SPLEEN
+SPLENDID/Y
+SPLENDOR
+SPLICE/D/R/Z/G/J/S
+SPLINE/M/S
+SPLINTER/D/S
+SPLIT/M/S
+SPLITTER/M/S
+SPLITTING
+SPOIL/D/R/Z/G/S
+SPOKE/D/S
+SPOKEN
+SPOKESMAN
+SPOKESMEN
+SPONGE/D/R/Z/G/S
+SPONSOR/D/G/S
+SPONSORSHIP
+SPONTANEOUS/Y
+SPOOK
+SPOOKY
+SPOOL/D/R/G/S
+SPOON/D/G/S
+SPORE/M/S
+SPORT/D/G/V/S
+SPORTINGLY
+SPORTSMAN
+SPOT/M/S
+SPOTLESS/Y
+SPOTTED
+SPOTTER/M/S
+SPOTTING
+SPOUSE/M/S
+SPOUT/D/G/S
+SPRANG
+SPRAWL/D/G/S
+SPRAY/D/R/G/S
+SPREAD/R/Z/G/J/S
+SPREE/M/S
+SPRIG
+SPRIGHTLY
+SPRING/R/Z/G/S
+SPRINGTIME
+SPRINGY/P/T/R
+SPRINKLE/D/R/G/S
+SPRINT/D/R/Z/G/S
+SPRITE
+SPROUT/D/G
+SPRUCE/D
+SPRUNG
+SPUN
+SPUR/M/S
+SPURIOUS
+SPURN/D/G/S
+SPURT/D/G/S
+SPUTTER/D
+SPY/G/S
+SQUABBLE/D/G/S
+SQUAD/M/S
+SQUADRON/M/S
+SQUALL/M/S
+SQUARE/P/D/T/R/G/Y/S
+SQUASH/D/G
+SQUAT/S
+SQUAWK/D/G/S
+SQUEAK/D/G/S
+SQUEAL/D/G/S
+SQUEEZE/D/R/G/S
+SQUID
+SQUINT/D/G
+SQUIRE/M/S
+SQUIRM/D/S
+SQUIRREL/D/G/S
+SR
+STAB/Y/S
+STABBED
+STABBING
+STABILITY/M/S
+STABILIZE/D/R/Z/G/S
+STABLE/D/R/G/S
+STACK/D/M/G/S
+STAFF/D/R/Z/G/S
+STAG/M/S
+STAGE/D/R/Z/G/S
+STAGECOACH
+STAGGER/D/G/S
+STAGNANT
+STAID
+STAIN/D/G/S
+STAINLESS
+STAIR/M/S
+STAIRCASE/M/S
+STAIRWAY/M/S
+STAKE/D/S
+STALE
+STALK/D/G
+STALL/D/G/J/S
+STALWART/Y
+STAMEN/M/S
+STAMINA
+STAMMER/D/R/G/S
+STAMP/D/R/Z/G/S
+STAMPEDE/D/G/S
+STANCH/T
+STAND/G/J/S
+STANDARD/Y/S
+STANDARDIZATION
+STANDARDIZE/D/G/S
+STANDBY
+STANDPOINT/M/S
+STANDSTILL
+STANFORD
+STANZA/M/S
+STAPLE/R/G/S
+STAR/M/S
+STARBOARD
+STARCH/D
+STARE/D/R/G/S
+STARFISH
+STARK/Y
+STARLIGHT
+STARRED
+STARRING
+STARRY
+START/D/R/Z/G/S
+STARTLE/D/G/S
+STARTUP/M/S
+STARVATION
+STARVE/D/G/S
+STATE/D/M/G/X/Y/S
+STATEMENT/M/S
+STATESMAN
+STATIC
+STATICALLY
+STATION/D/R/G/S
+STATIONARY
+STATISTIC/S
+STATISTICAL/Y
+STATISTICIAN/M/S
+STATUE/M/S
+STATUESQUE/P/Y
+STATURE
+STATUS/S
+STATUTE/M/S
+STATUTORILY
+STATUTORY/P
+STAUNCH/T/Y
+STAVE/D/S
+STAY/D/G/S
+STEAD
+STEADFAST/P/Y
+STEADILY
+STEADY/P/D/T/R/G/S
+STEAK/M/S
+STEAL/R/G/H/S
+STEALTHILY
+STEALTHY
+STEAM/D/R/Z/G/S
+STEAMBOAT/M/S
+STEAMSHIP/M/S
+STEED
+STEEL/D/Z/G/S
+STEEP/P/D/T/R/G/Y/S
+STEEPLE/M/S
+STEER/D/G/S
+STELLAR
+STEM/M/S
+STEMMED
+STEMMING
+STENCH/M/S
+STENCIL/M/S
+STENOGRAPHER/M/S
+STEP/M/S
+STEPHEN/M
+STEPMOTHER/M/S
+STEPPED
+STEPPING
+STEPWISE
+STEREO/M/S
+STEREOGRAPHIC
+STEREOTYPE/D/S
+STEREOTYPICAL
+STERILE
+STERILIZATION/M/S
+STERILIZE/D/R/G/S
+STERLING
+STERN/P/Y/S
+STEVE/M
+STEW/D/S
+STEWARD/M/S
+STICK/G/R/S/Z
+STICKILY
+STICKY/P/T/R
+STIFF/P/T/R/N/X/Y/S
+STIFLE/D/G/S
+STIGMA
+STILE/M/S
+STILL/P/D/T/R/G/S
+STIMULANT/M/S
+STIMULATE/D/G/N/X/V/S
+STIMULI
+STIMULUS
+STING/G/S
+STINK/R/Z/G/S
+STINT
+STIPEND/M/S
+STIPULATE/D/G/N/X/S
+STIR/S
+STIRRED
+STIRRER/M/S
+STIRRING/Y/S
+STIRRUP
+STITCH/D/G/S
+STOCHASTIC
+STOCHASTICALLY
+STOCK/D/R/Z/G/J/S
+STOCKADE/M/S
+STOCKHOLDER/M/S
+STOLE/M/S
+STOLEN
+STOMACH/D/R/G/S
+STONE/D/G/S
+STONY
+STOOD
+STOOL
+STOOP/D/G/S
+STOP/S
+STOPCOCK/S
+STOPPABLE
+STOPPAGE
+STOPPED
+STOPPER/M/S
+STOPPING
+STORAGE/M/S
+STORE/D/G/S
+STOREHOUSE/M/S
+STORK/M/S
+STORM/D/G/S
+STORMY/P/T/R
+STORY/D/S
+STOUT/P/T/R/Y
+STOVE/M/S
+STOW/D
+STRAGGLE/D/R/Z/G/S
+STRAIGHT/P/T/R/N/X
+STRAIGHTFORWARD/P/Y
+STRAIGHTWAY
+STRAIN/D/R/Z/G/S
+STRAIT/N/S
+STRAND/D/G/S
+STRANGE/P/R/Z/Y
+STRANGEST
+STRANGLE/D/R/Z/G/J/S
+STRANGULATION/M/S
+STRAP/M/S
+STRATAGEM/M/S
+STRATEGIC
+STRATEGY/M/S
+STRATIFY/D/N/X/S
+STRATUM
+STRAW/M/S
+STRAWBERRY/M/S
+STRAY/D/S
+STREAK/D/S
+STREAM/D/R/Z/G/S
+STREAMLINE/D/R/G/S
+STREET/Z/S
+STREETCAR/M/S
+STRENGTH/N
+STRENGTHEN/D/R/G/S
+STRENGTHS
+STRENUOUS/Y
+STRESS/D/G/S
+STRETCH/D/R/Z/G/S
+STREW/S
+STREWN
+STRICT/P/T/R/Y
+STRIDE/R/G/S
+STRIFE
+STRIKE/R/Z/G/S
+STRIKINGLY
+STRING'S
+STRING/D/R/Z/G/S
+STRINGENT/Y
+STRINGY/P/T/R
+STRIP/M/S
+STRIPE/D/S
+STRIPPED
+STRIPPER/M/S
+STRIPPING
+STRIVE/G/J/S
+STRODE
+STROKE/D/R/Z/G/S
+STROLL/D/R/G/S
+STRONG/T/R/Y
+STRONGHOLD
+STROVE
+STRUCK
+STRUCTURAL/Y
+STRUCTURE/D/R/G/S
+STRUGGLE/D/G/S
+STRUNG
+STRUT/S
+STUB/M/S
+STUBBLE
+STUBBORN/P/Y
+STUCK
+STUD/M/S
+STUDENT/M/S
+STUDIO/M/S
+STUDIOUS/Y
+STUDY/D/G/S
+STUFF/D/G/S
+STUFFY/T/R
+STUMBLE/D/G/S
+STUMP/D/G/S
+STUN
+STUNG
+STUNNING/Y
+STUNT/M/S
+STUPEFY/G
+STUPENDOUS/Y
+STUPID/T/Y
+STUPIDITY/S
+STUPOR
+STURDY/P
+STYLE/D/R/Z/G/S
+STYLISH/P/Y
+STYLISTIC
+STYLISTICALLY
+STYLIZED
+SUB/S
+SUBATOMIC
+SUBCLASS/M/S
+SUBCOMPONENT/M/S
+SUBCOMPUTATION/M/S
+SUBCONSCIOUS/Y
+SUBCULTURE/M/S
+SUBDIVIDE/D/G/S
+SUBDIVISION/M/S
+SUBDUE/D/G/S
+SUBEXPRESSION/M/S
+SUBFIELD/M/S
+SUBFILE/M/S
+SUBGOAL/M/S
+SUBGRAPH
+SUBGRAPHS
+SUBGROUP/M/S
+SUBINTERVAL/M/S
+SUBJECT/D/G/V/S
+SUBJECTION
+SUBJECTIVELY
+SUBJECTIVITY
+SUBLIMATION/S
+SUBLIME/D
+SUBLIST/M/S
+SUBMARINE/R/Z/S
+SUBMERGE/D/G/S
+SUBMISSION/M/S
+SUBMIT/S
+SUBMITTED
+SUBMITTING
+SUBMODE/S
+SUBMODULE/M/S
+SUBNETWORK/M/S
+SUBORDINATE/D/N/S
+SUBPROBLEM/M/S
+SUBPROGRAM/M/S
+SUBPROJECT
+SUBPROOF/M/S
+SUBRANGE/M/S
+SUBROUTINE/M/S
+SUBSCHEMA/M/S
+SUBSCRIBE/D/R/Z/G/S
+SUBSCRIPT/D/G/S
+SUBSCRIPTION/M/S
+SUBSECTION/M/S
+SUBSEGMENT/M/S
+SUBSEQUENCE/M/S
+SUBSEQUENT/Y
+SUBSET/M/S
+SUBSIDE/D/G/S
+SUBSIDIARY/M/S
+SUBSIDIZE/D/G/S
+SUBSIDY/M/S
+SUBSIST/D/G/S
+SUBSISTENCE
+SUBSPACE/M/S
+SUBSTANCE/M/S
+SUBSTANTIAL/Y
+SUBSTANTIATE/D/G/N/X/S
+SUBSTANTIVE/Y
+SUBSTANTIVITY
+SUBSTITUTABILITY
+SUBSTITUTABLE
+SUBSTITUTE/D/G/N/X/S
+SUBSTRATE/M/S
+SUBSTRING/S
+SUBSTRUCTURE/M/S
+SUBSUME/D/G/S
+SUBSYSTEM/M/S
+SUBTASK/M/S
+SUBTERRANEAN
+SUBTITLE/S
+SUBTLE/P/T/R
+SUBTLETY/S
+SUBTLY
+SUBTRACT/D/G/S/R/Z
+SUBTRACTER'S
+SUBTRACTION/S
+SUBTRAHEND/M/S
+SUBTREE/M/S
+SUBTYPE/S
+SUBUNIT/M/S
+SUBURB/M/S
+SUBURBAN
+SUBVERSION
+SUBVERT/D/R/G/S
+SUBWAY/M/S
+SUCCEED/D/G/S
+SUCCESS/V/S
+SUCCESSFUL/Y
+SUCCESSION/M/S
+SUCCESSIVELY
+SUCCESSOR/M/S
+SUCCINCT/P/Y
+SUCCOR
+SUCCUMB/D/G/S
+SUCH
+SUCK/D/R/Z/G/S
+SUCKLE/G
+SUCTION
+SUDDEN/P/Y
+SUDS/G
+SUE/D/G/S
+SUFFER/D/R/Z/G/J/S
+SUFFERANCE
+SUFFICE/D/G/S
+SUFFICIENCY
+SUFFICIENT/Y
+SUFFIX/D/R/G/S
+SUFFOCATE/D/G/N/S
+SUFFRAGE
+SUGAR/D/G/J/S
+SUGGEST/D/G/V/S
+SUGGESTIBLE
+SUGGESTION/M/S
+SUGGESTIVELY
+SUICIDAL/Y
+SUICIDE/M/S
+SUIT/M/S
+SUITABILITY
+SUITABLE/P
+SUITABLY
+SUITCASE/M/S
+SUITE/D/Z/G/S
+SUITOR/M/S
+SULK/D/G/S
+SULKY/P
+SULLEN/P/Y
+SULPHATE
+SULPHUR/D
+SULPHURIC
+SULTAN/M/S
+SULTRY
+SUM/M/S
+SUMMAND/M/S
+SUMMARIZATION/M/S
+SUMMARIZE/D/G/S
+SUMMARY/M/S
+SUMMATION/M/S
+SUMMED
+SUMMER/M/S
+SUMMING
+SUMMIT
+SUMMON/D/R/Z/G/S
+SUMMONSES
+SUMPTUOUS
+SUN/M/S
+SUNBEAM/M/S
+SUNBURN
+SUNDAY/M/S
+SUNDOWN
+SUNDRY/S
+SUNG
+SUNGLASS/S
+SUNK/N
+SUNLIGHT
+SUNNED
+SUNNING
+SUNNY
+SUNNYVALE
+SUNRISE
+SUNSET
+SUNSHINE
+SUP/R
+SUPERB/Y
+SUPERCLASS/S
+SUPERCOMPUTER/M/S
+SUPERCOMPUTING
+SUPEREGO/M/S
+SUPERFICIAL/Y
+SUPERFLUITY/M/S
+SUPERFLUOUS/Y
+SUPERHUMAN/Y
+SUPERIMPOSE/D/G/S
+SUPERINTEND
+SUPERINTENDENT/M/S
+SUPERIOR/M/S
+SUPERIORITY
+SUPERLATIVE/Y/S
+SUPERMARKET/M/S
+SUPERPOSE/D/G/S
+SUPERSCRIPT/D/G/S
+SUPERSEDE/D/G/S
+SUPERSET/M/S
+SUPERSTITION/M/S
+SUPERSTITIOUS
+SUPERVISE/D/G/N/S
+SUPERVISOR/M/S
+SUPERVISORY
+SUPPER/M/S
+SUPPLANT/D/G/S
+SUPPLE/P
+SUPPLEMENT/D/G/S
+SUPPLEMENTAL
+SUPPLEMENTARY
+SUPPLY/D/R/Z/G/N/S
+SUPPORT/D/R/Z/G/V/S
+SUPPORTABLE
+SUPPORTINGLY
+SUPPORTIVELY
+SUPPOSE/D/G/S
+SUPPOSEDLY
+SUPPOSITION/M/S
+SUPPRESS/D/G/S
+SUPPRESSION
+SUPREMACY
+SUPREME/Y/P
+SURE/P/Y
+SURETY/S
+SURF
+SURFACE/P/D/G/S
+SURGE/D/G/S
+SURGEON/M/S
+SURGERY
+SURGICAL/Y
+SURLY/P
+SURMISE/D/S
+SURMOUNT/D/G/S
+SURNAME/M/S
+SURPASS/D/G/S
+SURPLUS/M/S
+SURPRISE/D/G/S
+SURPRISINGLY
+SURRENDER/D/G/S
+SURROGATE/M/S
+SURROUND/D/G/J/S
+SURVEY/D/G/S
+SURVEYOR/M/S
+SURVIVAL/S
+SURVIVE/D/G/S
+SURVIVOR/M/S
+SUSCEPTIBLE
+SUSPECT/D/G/S
+SUSPEND/D/G/S
+SUSPENDER/M/S
+SUSPENSE/N/X/S
+SUSPICION/M/S
+SUSPICIOUS/Y
+SUSTAIN/D/G/S
+SUTURE/S
+SUZANNE/M
+SWAGGER/D/G
+SWAIN/M/S
+SWALLOW/D/G/S
+SWAM
+SWAMP/D/G/S
+SWAMPY
+SWAN/M/S
+SWAP/S
+SWAPPED
+SWAPPING
+SWARM/D/G/S
+SWARTHY
+SWATTED
+SWAY/D/G
+SWEAR/R/G/S
+SWEAT/D/R/Z/G/S
+SWEEP/R/Z/G/J/S
+SWEET/P/T/R/X/Y/S
+SWEETEN/D/R/Z/G/J/S
+SWEETHEART/M/S
+SWELL/D/G/J/S
+SWEPT
+SWERVE/D/G/S
+SWIFT/P/T/R/Y
+SWIM/S
+SWIMMER/M/S
+SWIMMING/Y
+SWINE
+SWING/R/Z/G/S
+SWIRL/D/G
+SWISH/D
+SWITCH/D/R/Z/G/J/S
+SWITCHBOARD/M/S
+SWITZERLAND
+SWOLLEN
+SWOON
+SWOOP/D/G/S
+SWORD/M/S
+SWORE
+SWORN
+SWUM
+SWUNG
+SYCAMORE
+SYLLABI
+SYLLABLE/M/S
+SYLLABUS
+SYLLOGISM/M/S
+SYMBIOSIS
+SYMBIOTIC
+SYMBOL/M/S
+SYMBOLIC
+SYMBOLICALLY
+SYMBOLISM
+SYMBOLIZATION
+SYMBOLIZE/D/G/S
+SYMMETRIC
+SYMMETRICAL/Y
+SYMMETRY/M/S
+SYMPATHETIC
+SYMPATHIZE/D/R/Z/G/S
+SYMPATHIZINGLY
+SYMPATHY/M/S
+SYMPHONY/M/S
+SYMPOSIUM/S
+SYMPTOM/M/S
+SYMPTOMATIC
+SYNAPSE/M/S
+SYNCHRONIZATION
+SYNCHRONIZE/D/R/Z/G/S
+SYNCHRONOUS/Y
+SYNCHRONY
+SYNDICATE/D/N/S
+SYNDROME/M/S
+SYNERGISM
+SYNERGISTIC
+SYNONYM/M/S
+SYNONYMOUS/Y
+SYNOPSES
+SYNOPSIS
+SYNTACTIC
+SYNTACTICAL/Y
+SYNTAX
+SYNTHESIS
+SYNTHESIZE/D/R/Z/G/S
+SYNTHETIC/S
+SYRACUSE
+SYRINGE/S
+SYRUP
+SYSTEM/M/S
+SYSTEMATIC
+SYSTEMATICALLY
+SYSTEMATIZE/D/G/S
+SYSTOLIC
+TAB/S
+TABERNACLE/M/S
+TABLE/D/G/S
+TABLEAU/M/S
+TABLECLOTH
+TABLECLOTHS
+TABLESPOON/M/S
+TABLESPOONFUL/M/S
+TABLET/M/S
+TABOO/M/S
+TABULAR
+TABULATE/D/G/N/X/S
+TABULATOR/M/S
+TACHOMETER/M/S
+TACIT/Y
+TACK/D/G
+TACKLE/M/S
+TACT
+TACTICS
+TACTILE
+TAG/M/S
+TAGGED
+TAGGING
+TAIL/D/G/S
+TAILOR/D/G/S
+TAINT/D
+TAIWAN
+TAKE/R/Z/G/J/S
+TAKEN
+TALE/M/S
+TALENT/D/S
+TALK/D/R/Z/G/S
+TALKATIVE/P/Y
+TALKIE
+TALL/P/T/R
+TALLOW
+TAME/P/D/R/G/Y/S
+TAMPER/D/G/S
+TAN
+TANDEM
+TANG
+TANGENT/M/S
+TANGENTIAL
+TANGIBLE
+TANGIBLY
+TANGLE/D
+TANGY
+TANK/R/Z/S
+TANNER/M/S
+TANTALIZING/Y
+TANTAMOUNT
+TANTRUM/M/S
+TAP/M/S
+TAPE/D/R/Z/G/J/S
+TAPERED
+TAPERING
+TAPESTRY/M/S
+TAPPED
+TAPPER/M/S
+TAPPING
+TAPROOT/M/S
+TAR
+TARDY/P
+TARGET/D/G/S
+TARIFF/M/S
+TARRY
+TART/P/Y
+TASK/D/G/S
+TASSEL/M/S
+TASTE/D/R/Z/G/S
+TASTEFUL/P/Y
+TASTELESS/Y
+TASTY
+TATTER/D
+TATTOO/D/S
+TAU
+TAUGHT
+TAUNT/D/R/G/S
+TAUT/P/Y
+TAUTOLOGICAL/Y
+TAUTOLOGY/M/S
+TAVERN/M/S
+TAWNY
+TAX/D/G/S
+TAXABLE
+TAXATION
+TAXI/D/G/S
+TAXICAB/M/S
+TAXONOMIC
+TAXONOMICALLY
+TAXONOMY
+TAXPAYER/M/S
+TEA/S
+TEACH/R/Z/G/J/S
+TEACHABLE
+TEACHER'S
+TEAHOUSE
+TEAM/D/G/S
+TEAR/D/G/S
+TEARFUL/Y
+TEASE/D/G/S
+TEASPOON/M/S
+TEASPOONFUL/M/S
+TECHNICAL/Y
+TECHNICALITY/M/S
+TECHNICIAN/M/S
+TECHNIQUE/M/S
+TECHNOLOGICAL/Y
+TECHNOLOGIST/M/S
+TECHNOLOGY/S
+TEDDY/M
+TEDIOUS/P/Y
+TEDIUM
+TEEM/D/G/S
+TEEN/S
+TEENAGE/D/R/Z
+TEETH
+TEETHE/D/G/S
+TEFLON
+TELECOMMUNICATION/S
+TELEGRAM/M/S
+TELEGRAPH/D/R/Z/G
+TELEGRAPHIC
+TELEGRAPHS
+TELEOLOGICAL/Y
+TELEOLOGY
+TELEPHONE/D/R/Z/G/S
+TELEPHONIC
+TELEPHONY
+TELESCOPE/D/G/S
+TELETYPE/M/S
+TELEVISE/D/G/N/X/S
+TELEVISOR/M/S
+TELL/R/Z/G/S
+TEMPER/D/G/S
+TEMPERAMENT/S
+TEMPERAMENTAL
+TEMPERANCE
+TEMPERATE/P/Y
+TEMPERATURE/M/S
+TEMPEST
+TEMPESTUOUS/Y
+TEMPLATE/M/S
+TEMPLE/M/S
+TEMPORAL/Y
+TEMPORARILY
+TEMPORARY/S
+TEMPT/D/R/Z/G/S
+TEMPTATION/M/S
+TEMPTINGLY
+TEN/H/S
+TENACIOUS/Y
+TENANT/M/S
+TEND/D/R/Z/G/S
+TENDENCY/S
+TENDERLY
+TENDERNESS
+TENEMENT/M/S
+TENNESSEE
+TENNIS
+TENOR/M/S
+TENSE/P/D/T/R/G/N/X/Y/S
+TENSOR
+TENT/D/G/S
+TENTACLE/D/S
+TENTATIVE/Y
+TENURE
+TERM/D/G/S
+TERMINAL/M/Y/S
+TERMINATE/D/G/N/X/S
+TERMINATOR/M/S
+TERMINOLOGY/S
+TERMINUS
+TERMWISE
+TERNARY
+TERRACE/D/S
+TERRAIN/M/S
+TERRESTRIAL
+TERRIBLE
+TERRIBLY
+TERRIER/M/S
+TERRIFIC
+TERRIFY/D/G/S
+TERRITORIAL
+TERRITORY/M/S
+TERROR/M/S
+TERRORISM
+TERRORIST/M/S
+TERRORISTIC
+TERRORIZE/D/G/S
+TERSE
+TERTIARY
+TEST/D/R/Z/G/J/S
+TESTABILITY
+TESTABLE
+TESTAMENT/M/S
+TESTICLE/M/S
+TESTIFY/D/R/Z/G/S
+TESTIMONY/M/S
+TEXAS
+TEXT/M/S
+TEXTBOOK/M/S
+TEXTILE/M/S
+TEXTUAL/Y
+TEXTURE/D/S
+THAN
+THANK/D/G/S
+THANKFUL/P/Y
+THANKLESS/P/Y
+THANKSGIVING
+THAT/M/S
+THATCH/S
+THAW/D/G/S
+THE/G/J
+THEATER/M/S
+THEATRICAL/Y/S
+THEFT/M/S
+THEIR/S
+THEM
+THEMATIC
+THEME/M/S
+THEMSELVES
+THEN
+THENCE
+THENCEFORTH
+THEOLOGICAL
+THEOLOGY
+THEOREM/M/S
+THEORETIC
+THEORETICAL/Y
+THEORETICIANS
+THEORIST/M/S
+THEORIZATION/M/S
+THEORIZE/D/R/Z/G/S
+THEORY/M/S
+THERAPEUTIC
+THERAPIST/M/S
+THERAPY/M/S
+THERE/M
+THEREABOUTS
+THEREAFTER
+THEREBY
+THEREFORE
+THEREIN
+THEREOF
+THEREON
+THERETO
+THEREUPON
+THEREWITH
+THERMAL
+THERMODYNAMIC/S
+THERMOMETER/M/S
+THERMOSTAT/M/S
+THESAURI
+THESE/S
+THESIS
+THETA
+THEY
+THEY'D
+THEY'LL
+THEY'RE
+THEY'VE
+THICK/P/T/R/N/X/Y
+THICKET/M/S
+THIEF
+THIEVE/G/S
+THIGH
+THIGHS
+THIMBLE/M/S
+THIN/P/Y
+THINK/R/Z/G/S
+THINKABLE
+THINKABLY
+THINNER
+THINNEST
+THIRD/Y/S
+THIRST/D/S
+THIRSTY
+THIRTEEN/H/S
+THIRTY/H/S
+THIS
+THISTLE
+THOMAS
+THOMPSON/M
+THONG
+THORN/M/S
+THORNY
+THOROUGH/P/Y
+THOROUGHFARE/M/S
+THOSE
+THOUGH
+THOUGHT/M/S
+THOUGHTFUL/P/Y
+THOUGHTLESS/P/Y
+THOUSAND/H/S
+THRASH/D/R/G/S
+THREAD/D/R/Z/G/S
+THREAT/N/S
+THREATEN/D/G/S
+THREE/M/S
+THREESCORE
+THRESHOLD/M/S
+THREW
+THRICE
+THRIFT
+THRIFTY
+THRILL/D/R/Z/G/S
+THRILLING/Y
+THRIVE/D/G/S
+THROAT/D/S
+THROB/S
+THROBBED
+THROBBING
+THRONE/M/S
+THRONG/M/S
+THROTTLE/D/G/S
+THROUGH
+THROUGHOUT
+THROUGHPUT
+THROW/R/G/S
+THROWN
+THRUSH
+THRUST/R/Z/G/S
+THUD/S
+THUG/M/S
+THUMB/D/G/S
+THUMP/D/G
+THUNDER/D/R/Z/G/S
+THUNDERBOLT/M/S
+THUNDERSTORM/M/S
+THURSDAY/M/S
+THUS/Y
+THWART/D/G
+THYSELF
+TICK/D/R/Z/G/S
+TICKET/M/S
+TICKLE/D/G/S
+TIDAL/Y
+TIDE/D/G/J/S
+TIDY/P/D/G
+TIE/D/R/Z/S
+TIGER/M/S
+TIGHT/P/T/R/X/Y
+TIGHTEN/D/R/Z/G/J/S
+TILDE
+TILE/D/G/S
+TILL/D/R/Z/G/S
+TILLABLE
+TILT/D/G/S
+TIMBER/D/G/S
+TIME/D/R/Z/G/Y/J/S
+TIMESHARING
+TIMETABLE/M/S
+TIMID/Y
+TIMIDITY
+TIN/M/S
+TINGE/D
+TINGLE/D/G/S
+TINILY
+TINKER/D/G/S
+TINKLE/D/G/S
+TINNILY
+TINNY/P/T/R
+TINT/D/G/S
+TINY/P/T/R
+TIP/M/S
+TIPPED
+TIPPER/M/S
+TIPPING
+TIPTOE
+TIRE/D/G/S
+TIREDLY
+TIRELESS/P/Y
+TIRESOME/P/Y
+TISSUE/M/S
+TIT/R/Z/S
+TITHE/R/S
+TITLE/D/S
+TO
+TOAD/M/S
+TOAST/D/R/G/S
+TOBACCO
+TODAY
+TOE/M/S
+TOFU
+TOGETHER/P
+TOGGLE/D/G/S
+TOIL/D/R/G/S
+TOILET/M/S
+TOKEN/M/S
+TOLD
+TOLERABILITY
+TOLERABLE
+TOLERABLY
+TOLERANCE/S
+TOLERANT/Y
+TOLERATE/D/G/N/S
+TOLL/D/S
+TOM/M
+TOMAHAWK/M/S
+TOMATO
+TOMATOES
+TOMB/M/S
+TOMOGRAPHY
+TOMORROW
+TON/M/S
+TONAL
+TONE/D/R/G/S
+TONGS
+TONGUE/D/S
+TONIC/M/S
+TONIGHT
+TONNAGE
+TONSIL
+TOO/H
+TOOK
+TOOL/D/R/Z/G/S
+TOOLKIT/S
+TOOTHBRUSH/M/S
+TOOTHPICK/M/S
+TOP/R/S
+TOPIC/M/S
+TOPICAL/Y
+TOPMOST
+TOPOGRAPHIC
+TOPOGRAPHICAL
+TOPOLOGIC
+TOPOLOGICAL
+TOPOLOGY/S
+TOPPLE/D/G/S
+TORCH/M/S
+TORE
+TORMENT/D/R/Z/G
+TORN
+TORNADO/S
+TORNADOES
+TORPEDO/S
+TORPEDOES
+TORQUE
+TORRENT/M/S
+TORRID
+TORTOISE/M/S
+TORTURE/D/R/Z/G/S
+TORUS/M/S
+TOSS/D/G/S
+TOTAL/D/G/Y/S/R/Z/M
+TOTALER'S
+TOTALITY/M/S
+TOTALLED
+TOTALLER/S/M
+TOTALLING
+TOTTER/D/G/S
+TOUCH/D/G/S
+TOUCHABLE
+TOUCHILY
+TOUCHINGLY
+TOUCHY/P/T/R
+TOUGH/P/T/R/N/Y
+TOUR/D/G/S
+TOURETZKY/M
+TOURISM
+TOURIST/M/S
+TOURNAMENT/M/S
+TOW/D/Z
+TOWARD/S
+TOWEL/G/S/D/M
+TOWELLED
+TOWELLING
+TOWER/D/G/S
+TOWN/M/S
+TOWNSHIP/M/S
+TOY/D/G/S
+TRACE/D/R/Z/G/J/S
+TRACEABLE
+TRACK/D/R/Z/G/S
+TRACT/M/V/S
+TRACTABILITY
+TRACTABLE
+TRACTOR/M/S
+TRADE/D/R/Z/G/S
+TRADEMARK/M/S
+TRADESMAN
+TRADITION/M/S
+TRADITIONAL/Y
+TRAFFIC/M/S
+TRAFFICKED
+TRAFFICKER/M/S
+TRAFFICKING
+TRAGEDY/M/S
+TRAGIC
+TRAGICALLY
+TRAIL/D/R/Z/G/J/S
+TRAIN/D/R/Z/G/S
+TRAINABLE
+TRAINEE/M/S
+TRAIT/M/S
+TRAITOR/M/S
+TRAJECTORY/M/S
+TRAMP/D/G/S
+TRAMPLE/D/R/G/S
+TRANCE/M/S
+TRANQUIL/Y
+TRANQUILITY
+TRANQUILLITY
+TRANSACT
+TRANSACTION/M/S
+TRANSCEND/D/G/S
+TRANSCENDENT
+TRANSCONTINENTAL
+TRANSCRIBE/D/R/Z/G/S
+TRANSCRIPT/M/S
+TRANSCRIPTION/M/S
+TRANSFER/M/S/D/G
+TRANSFERABLE
+TRANSFERAL/M/S
+TRANSFERRAL/M/S
+TRANSFERRED
+TRANSFERRER/M/S
+TRANSFERRING
+TRANSFINITE
+TRANSFORM/D/G/S
+TRANSFORMABLE
+TRANSFORMATION/M/S
+TRANSFORMATIONAL
+TRANSGRESS/D
+TRANSGRESSION/M/S
+TRANSIENT/Y/S
+TRANSISTOR/M/S
+TRANSIT
+TRANSITION/D/S
+TRANSITIONAL
+TRANSITIVE/P/Y
+TRANSITIVITY
+TRANSITORY
+TRANSLATABILITY
+TRANSLATABLE
+TRANSLATE/D/G/N/X/S
+TRANSLATIONAL
+TRANSLATOR/M/S
+TRANSLITERATE/N/D/G
+TRANSLUCENT
+TRANSMISSION/M/S
+TRANSMIT/S
+TRANSMITTAL
+TRANSMITTED
+TRANSMITTER/M/S
+TRANSMITTING
+TRANSMOGRIFY/N
+TRANSPARENCY/M/S
+TRANSPARENT/Y
+TRANSPIRE/D/G/S
+TRANSPLANT/D/G/S
+TRANSPORT/D/R/Z/G/S
+TRANSPORTABILITY
+TRANSPORTATION
+TRANSPOSE/D/G/S
+TRANSPOSITION
+TRAP/M/S
+TRAPEZOID/M/S
+TRAPEZOIDAL
+TRAPPED
+TRAPPER/M/S
+TRAPPING/S
+TRASH
+TRAUMA
+TRAUMATIC
+TRAVAIL
+TRAVEL/D/R/Z/G/J/S
+TRAVERSAL/M/S
+TRAVERSE/D/G/S
+TRAVESTY/M/S
+TRAY/M/S
+TREACHEROUS/Y
+TREACHERY/M/S
+TREAD/G/S
+TREASON
+TREASURE/D/R/G/S
+TREASURY/M/S
+TREAT/D/G/S
+TREATISE/M/S
+TREATMENT/M/S
+TREATY/M/S
+TREBLE
+TREE/M/S
+TREETOP/M/S
+TREK/M/S
+TREMBLE/D/G/S
+TREMENDOUS/Y
+TREMOR/M/S
+TRENCH/R/S
+TREND/G/S
+TRESPASS/D/R/Z/S
+TRESS/M/S
+TRIAL/M/S
+TRIANGLE/M/S
+TRIANGULAR/Y
+TRIBAL
+TRIBE/M/S
+TRIBUNAL/M/S
+TRIBUNE/M/S
+TRIBUTARY
+TRIBUTE/M/S
+TRICHOTOMY
+TRICK/D/G/S
+TRICKLE/D/G/S
+TRICKY/P/T/R
+TRIFLE/R/G/S
+TRIGGER/D/G/S
+TRIGONOMETRIC
+TRIGONOMETRY
+TRIHEDRAL
+TRILL/D
+TRILLION/H/S
+TRIM/P/Y/S
+TRIMMED
+TRIMMER
+TRIMMEST
+TRIMMING/S
+TRINKET/M/S
+TRIP/M/S
+TRIPLE/D/G/S
+TRIPLET/M/S
+TRIUMPH/D/G
+TRIUMPHAL
+TRIUMPHANTLY
+TRIUMPHS
+TRIVIA
+TRIVIAL/Y
+TRIVIALITY/S
+TROD
+TROLL/M/S
+TROLLEY/M/S
+TROOP/R/Z/S
+TROPHY/M/S
+TROPIC/M/S
+TROPICAL
+TROT/S
+TROUBLE/D/G/S
+TROUBLEMAKER/M/S
+TROUBLESHOOT/R/Z/G/S
+TROUBLESOME/Y
+TROUGH
+TROUSER/S
+TROUT
+TROWEL/M/S
+TRUANT/M/S
+TRUCE
+TRUCK/D/R/Z/G/S
+TRUDGE/D
+TRUE/D/T/R/G/S
+TRUISM/M/S
+TRULY
+TRUMP/D/S
+TRUMPET/R
+TRUNCATE/D/G/S
+TRUNCATION/M/S
+TRUNK/M/S
+TRUST/D/G/S
+TRUSTEE/M/S
+TRUSTFUL/P/Y
+TRUSTINGLY
+TRUSTWORTHY/P
+TRUSTY
+TRUTH
+TRUTHFUL/P/Y
+TRUTHS
+TRY/D/R/Z/G/S
+TUB/M/S
+TUBE/R/Z/G/S
+TUBERCULOSIS
+TUCK/D/R/G/S
+TUESDAY/M/S
+TUFT/M/S
+TUG/S
+TUITION
+TULIP/M/S
+TUMBLE/D/R/Z/G/S
+TUMOR/S
+TUMULT/M/S
+TUMULTUOUS
+TUNABLE
+TUNE/D/R/Z/G/S
+TUNIC/M/S
+TUNNEL/D/S
+TUPLE/M/S
+TURBAN/M/S
+TURBO
+TURBULENT/Y
+TURF
+TURING
+TURKEY/M/S
+TURMOIL/M/S
+TURN/D/R/Z/G/J/S
+TURNABLE
+TURNIP/M/S
+TURNOVER
+TURPENTINE
+TURQUOISE
+TURRET/M/S
+TURTLE/M/S
+TUTOR/D/G/S
+TUTORIAL/M/S
+TV
+TWAIN
+TWANG
+TWAS
+TWEED
+TWELFTH
+TWELVE/S
+TWENTY/H/S
+TWICE
+TWIG/M/S
+TWILIGHT/M/S
+TWILL
+TWIN/M/S
+TWINE/D/R
+TWINKLE/D/R/G/S
+TWIRL/D/R/G/S
+TWIST/D/R/Z/G/S
+TWITCH/D/G
+TWITTER/D/G
+TWO/M/S
+TWOFOLD
+TYING
+TYPE/D/M/G/S
+TYPECHECK/G/S/R
+TYPEOUT
+TYPESCRIPT/S
+TYPEWRITER/M/S
+TYPHOID
+TYPICAL/P/Y
+TYPIFY/D/G/S
+TYPIST/M/S
+TYPOGRAPHICAL/Y
+TYPOGRAPHY
+TYRANNY
+TYRANT/M/S
+UBIQUITOUS/Y
+UBIQUITY
+UGH
+UGLY/P/T/R
+UIMS
+ULCER/M/S
+ULTIMATE/Y
+UMBRELLA/M/S
+UMPIRE/M/S
+UNABATED
+UNABBREVIATED
+UNABLE
+UNACCEPTABILITY
+UNACCEPTABLE
+UNACCEPTABLY
+UNACCUSTOMED
+UNACKNOWLEDGED
+UNADULTERATED
+UNAESTHETICALLY
+UNAFFECTED/P/Y
+UNAIDED
+UNALIENABILITY
+UNALIENABLE
+UNALTERABLY
+UNALTERED
+UNAMBIGUOUS/Y
+UNAMBITIOUS
+UNANALYZABLE
+UNANIMOUS/Y
+UNANSWERED
+UNANTICIPATED
+UNARMED
+UNARY
+UNASSAILABLE
+UNASSIGNED
+UNATTAINABILITY
+UNATTAINABLE
+UNATTENDED
+UNATTRACTIVE/Y
+UNAUTHORIZED
+UNAVAILABILITY
+UNAVAILABLE
+UNAVOIDABLE
+UNAVOIDABLY
+UNAWARE/P/S
+UNBALANCED
+UNBEARABLE
+UNBELIEVABLE
+UNBIASED
+UNBLOCK/D/G/S
+UNBORN
+UNBOUND/D
+UNBREAKABLE
+UNBROKEN
+UNBUFFERED
+UNCANCELED
+UNCANCELLED
+UNCANNY
+UNCAPITALIZED
+UNCAUGHT
+UNCERTAIN/Y
+UNCERTAINTY/S
+UNCHANGEABLE
+UNCHANGED
+UNCHANGING
+UNCHARTED
+UNCLAIMED
+UNCLE/M/S
+UNCLEAN/P/Y
+UNCLEAR/D
+UNCLOSED
+UNCOMFORTABLE
+UNCOMFORTABLY
+UNCOMMITTED
+UNCOMMON/Y
+UNCOMPROMISING
+UNCOMPUTABLE
+UNCONCERNED/Y
+UNCONDITIONAL/Y
+UNCONNECTED
+UNCONSCIOUS/P/Y
+UNCONSTRAINED
+UNCONTROLLABILITY
+UNCONTROLLABLE
+UNCONTROLLABLY
+UNCONTROLLED
+UNCONVENTIONAL/Y
+UNCONVINCED
+UNCONVINCING
+UNCORRECTABLE
+UNCORRECTED
+UNCOUNTABLE
+UNCOUNTABLY
+UNCOUTH
+UNCOVER/D/G/S
+UNDAUNTED/Y
+UNDECIDABLE
+UNDECIDED
+UNDECLARED
+UNDECOMPOSABLE
+UNDEFINABILITY
+UNDEFINED
+UNDELETE
+UNDELETED
+UNDENIABLY
+UNDER
+UNDERBRUSH
+UNDERDONE
+UNDERESTIMATE/D/G/N/S
+UNDERFLOW/D/G/S
+UNDERFOOT
+UNDERGO/G
+UNDERGOES
+UNDERGONE
+UNDERGRADUATE/M/S
+UNDERGROUND
+UNDERLIE/S
+UNDERLINE/D/G/J/S
+UNDERLING/M/S
+UNDERLYING
+UNDERMINE/D/G/S
+UNDERNEATH
+UNDERPINNING/S
+UNDERPLAY/D/G/S
+UNDERSCORE/D/S
+UNDERSTAND/G/J/S
+UNDERSTANDABILITY
+UNDERSTANDABLE
+UNDERSTANDABLY
+UNDERSTANDINGLY
+UNDERSTATED
+UNDERSTOOD
+UNDERTAKE/R/Z/G/J/S
+UNDERTAKEN
+UNDERTOOK
+UNDERWAY
+UNDERWEAR
+UNDERWENT
+UNDERWORLD
+UNDERWRITE/R/Z/G/S
+UNDESIRABILITY
+UNDESIRABLE
+UNDETECTABLE
+UNDETECTED
+UNDETERMINED
+UNDEVELOPED
+UNDID
+UNDIRECTED
+UNDISCIPLINED
+UNDISCOVERED
+UNDISTORTED
+UNDISTURBED
+UNDIVIDED
+UNDO/G/J
+UNDOCUMENTED
+UNDOES
+UNDONE
+UNDOUBTEDLY
+UNDRESS/D/G/S
+UNDUE
+UNDULY
+UNEASILY
+UNEASY/P
+UNECONOMICAL
+UNEMBELLISHED
+UNEMPLOYED
+UNEMPLOYMENT
+UNENDING
+UNENLIGHTENING
+UNEQUAL/D/Y
+UNEQUIVOCAL/Y
+UNESSENTIAL
+UNEVALUATED
+UNEVEN/P/Y
+UNEVENTFUL
+UNEXCUSED
+UNEXPANDED
+UNEXPECTED/Y
+UNEXPLAINED
+UNEXPLORED
+UNEXTENDED
+UNFAIR/P/Y
+UNFAITHFUL/P/Y
+UNFAMILIAR/Y
+UNFAMILIARITY
+UNFAVORABLE
+UNFETTERED
+UNFINISHED
+UNFIT/P
+UNFLAGGING
+UNFOLD/D/G/S
+UNFORESEEN
+UNFORGEABLE
+UNFORGIVING
+UNFORMATTED
+UNFORTUNATE/Y/S
+UNFOUNDED
+UNFRIENDLY/P
+UNFULFILLED
+UNGRAMMATICAL
+UNGRATEFUL/P/Y
+UNGROUNDED
+UNGUARDED
+UNGUIDED
+UNHAPPILY
+UNHAPPY/P/T/R
+UNHEALTHY
+UNHEEDED
+UNICORN/M/S
+UNIDENTIFIED
+UNIDIRECTIONAL/Y
+UNIDIRECTIONALITY
+UNIFORM/D/Y/S
+UNIFORMITY
+UNIFY/D/R/Z/G/N/X/S
+UNILATERAL
+UNILLUMINATING
+UNIMAGINABLE
+UNIMPEDED
+UNIMPLEMENTED
+UNIMPORTANT
+UNINDENTED
+UNINFORMED
+UNINITIALIZED
+UNINTELLIGIBLE
+UNINTENDED
+UNINTENTIONAL/Y
+UNINTERESTING/Y
+UNINTERPRETED
+UNINTERRUPTED/Y
+UNION/M/S
+UNIONIZATION
+UNIONIZE/D/R/Z/G/S
+UNIQUE/P/Y
+UNISON
+UNIT/M/S
+UNITE/D/G/S
+UNITY/M/S
+UNIVALVE/M/S
+UNIVERSAL/Y/S
+UNIVERSALITY
+UNIVERSE/M/S
+UNIVERSITY/M/S
+UNIX
+UNJUST/Y
+UNJUSTIFIED
+UNKIND/P/Y
+UNKNOWABLE
+UNKNOWING/Y
+UNKNOWN/S
+UNLABELED
+UNLAWFUL/Y
+UNLEASH/D/G/S
+UNLESS
+UNLIKE/P/Y
+UNLIMITED
+UNLINK/D/G/S
+UNLOAD/D/G/S
+UNLOCK/D/G/S
+UNLUCKY
+UNMANAGEABLE
+UNMANAGEABLY
+UNMANNED
+UNMARKED
+UNMARRIED
+UNMASKED
+UNMATCHED
+UNMISTAKABLE
+UNMODIFIED
+UNMOVED
+UNNAMED
+UNNATURAL/P/Y
+UNNECESSARILY
+UNNECESSARY
+UNNEEDED
+UNNOTICED
+UNOBSERVABLE
+UNOBSERVED
+UNOBTAINABLE
+UNOCCUPIED
+UNOFFICIAL/Y
+UNOPENED
+UNOPTIMIZED
+UNORDERED
+UNPACK/D/G/S
+UNPARALLELED
+UNPARSED
+UNPLANNED
+UNPLEASANT/P/Y
+UNPOPULAR
+UNPOPULARITY
+UNPRECEDENTED
+UNPREDICTABLE
+UNPRESCRIBED
+UNPRESERVED
+UNPRIMED
+UNPROFITABLE
+UNPROJECTED
+UNPROTECTED
+UNPROVABILITY
+UNPROVABLE
+UNPROVEN
+UNPUBLISHED
+UNQUALIFIED/Y
+UNQUESTIONABLY
+UNQUESTIONED
+UNQUOTED
+UNRAVEL/D/G/S
+UNREACHABLE
+UNREADABLE
+UNREAL
+UNREALISTIC
+UNREALISTICALLY
+UNREASONABLE/P
+UNREASONABLY
+UNRECOGNIZABLE
+UNRECOGNIZED
+UNRELATED
+UNRELIABILITY
+UNRELIABLE
+UNREPORTED
+UNREPRESENTABLE
+UNRESOLVED
+UNRESPONSIVE
+UNREST
+UNRESTRAINED
+UNRESTRICTED/Y
+UNRESTRICTIVE
+UNROLL/D/G/S
+UNRULY
+UNSAFE/Y
+UNSANITARY
+UNSATISFACTORY
+UNSATISFIABILITY
+UNSATISFIABLE
+UNSATISFIED
+UNSATISFYING
+UNSCRUPULOUS
+UNSEEDED
+UNSEEN
+UNSELECTED
+UNSELFISH/P/Y
+UNSENT
+UNSETTLED
+UNSETTLING
+UNSHAKEN
+UNSHARED
+UNSIGNED
+UNSKILLED
+UNSOLVABLE
+UNSOLVED
+UNSOPHISTICATED
+UNSOUND
+UNSPEAKABLE
+UNSPECIFIED
+UNSTABLE
+UNSTEADY/P
+UNSTRUCTURED
+UNSUCCESSFUL/Y
+UNSUITABLE
+UNSUITED
+UNSUPPORTED
+UNSURE
+UNSURPRISING/Y
+UNSYNCHRONIZED
+UNTAPPED
+UNTERMINATED
+UNTESTED
+UNTHINKABLE
+UNTIDY/P
+UNTIE/D/S
+UNTIL
+UNTIMELY
+UNTO
+UNTOLD
+UNTOUCHABLE/M/S
+UNTOUCHED
+UNTOWARD
+UNTRAINED
+UNTRANSLATED
+UNTREATED
+UNTRIED
+UNTRUE
+UNTRUTHFUL/P
+UNTYING
+UNUSABLE
+UNUSED
+UNUSUAL/Y
+UNVARYING
+UNVEIL/D/G/S
+UNWANTED
+UNWELCOME
+UNWHOLESOME
+UNWIELDY/P
+UNWILLING/P/Y
+UNWIND/R/Z/G/S
+UNWISE/Y
+UNWITTING/Y
+UNWORTHY/P
+UNWOUND
+UNWRITTEN
+UP
+UPBRAID
+UPDATE/D/R/G/S
+UPGRADE/D/G/S
+UPHELD
+UPHILL
+UPHOLD/R/Z/G/S
+UPHOLSTER/D/R/G/S
+UPKEEP
+UPLAND/S
+UPLIFT
+UPON
+UPPER
+UPPERMOST
+UPRIGHT/P/Y
+UPRISING/M/S
+UPROAR
+UPROOT/D/G/S
+UPSET/S
+UPSHOT/M/S
+UPSIDE
+UPSTAIRS
+UPSTREAM
+UPTURN/D/G/S
+UPWARD/S
+URBAN
+URBANA
+URCHIN/M/S
+URGE/D/G/J/S
+URGENT/Y
+URINATE/D/G/N/S
+URINE
+URN/M/S
+US
+USA
+USABILITY
+USABLE
+USABLY
+USAGE/S
+USE/D/R/Z/G/S
+USEFUL/P/Y
+USELESS/P/Y
+USENIX
+USER'S
+USHER/D/G/S
+USUAL/Y
+USURP/D/R
+UTAH
+UTENSIL/M/S
+UTILITY/M/S
+UTILIZATION/M/S
+UTILIZE/D/G/S
+UTMOST
+UTOPIAN/M/S
+UTTER/D/G/Y/S
+UTTERANCE/M/S
+UTTERMOST
+UUCP
+UZI
+VACANCY/M/S
+VACANT/Y
+VACATE/D/G/X/S
+VACATION/D/R/Z/G/S
+VACUO
+VACUOUS/Y
+VACUUM/D/G
+VAGABOND/M/S
+VAGARY/M/S
+VAGINA/M/S
+VAGRANT/Y
+VAGUE/P/T/R/Y
+VAINLY
+VALE/M/S
+VALENCE/M/S
+VALENTINE/M/S
+VALET/M/S
+VALIANT/Y
+VALID/P/Y
+VALIDATE/D/G/N/S
+VALIDITY
+VALLEY/M/S
+VALOR
+VALUABLE/S
+VALUABLY
+VALUATION/M/S
+VALUE/D/R/Z/G/S
+VALVE/M/S
+VAN/M/S
+VANCOUVER
+VANDALIZE/D/G/S
+VANE/M/S
+VANILLA
+VANISH/D/R/G/S
+VANISHINGLY
+VANITY/S
+VANQUISH/D/G/S
+VANTAGE
+VAPOR/G/S
+VARIABILITY
+VARIABLE/P/M/S
+VARIABLY
+VARIANCE/M/S
+VARIANT/Y/S
+VARIATION/M/S
+VARIETY/M/S
+VARIOUS/Y
+VARNISH/M/S
+VARY/D/G/J/S
+VASE/M/S
+VASSAL
+VAST/P/T/R/Y
+VAT/M/S
+VAUDEVILLE
+VAULT/D/R/G/S
+VAUNT/D
+VAX
+VAXEN
+VAXES
+VEAL
+VECTOR/M/S
+VECTORIZATION
+VECTORIZING
+VEE
+VEER/D/G/S
+VEGAS
+VEGETABLE/M/S
+VEGETARIAN/M/S
+VEGETATE/D/G/N/V/S
+VEHEMENCE
+VEHEMENT/Y
+VEHICLE/M/S
+VEHICULAR
+VEIL/D/G/S
+VEIN/D/G/S
+VELOCITY/M/S
+VELVET
+VENDOR/M/S
+VENERABLE
+VENGEANCE
+VENISON
+VENOM
+VENOMOUS/Y
+VENT/D/S
+VENTILATE/D/G/N/S
+VENTRICLE/M/S
+VENTURE/D/R/Z/G/J/S
+VERACITY
+VERANDA/M/S
+VERB/M/S
+VERBAL/Y
+VERBATIM
+VERBOSE
+VERBOSITY
+VERDICT
+VERDURE
+VERGE/R/S
+VERIFIABILITY
+VERIFIABLE
+VERIFY/D/R/Z/G/N/X/S
+VERILY
+VERITABLE
+VERMIN
+VERNACULAR
+VERSA
+VERSATILE
+VERSATILITY
+VERSE/D/G/N/X/S
+VERSUS
+VERTEBRATE/M/S
+VERTEX
+VERTICAL/P/Y
+VERTICES
+VERY
+VESSEL/M/S
+VEST/D/S
+VESTIGE/M/S
+VESTIGIAL
+VETERAN/M/S
+VETERINARIAN/M/S
+VETERINARY
+VETO/D/R
+VETOES
+VEX/D/G/S
+VEXATION
+VIA
+VIABILITY
+VIABLE
+VIABLY
+VIAL/M/S
+VIBRATE/D/G/N/X
+VICE/M/S
+VICEROY
+VICINITY
+VICIOUS/P/Y
+VICISSITUDE/M/S
+VICTIM/M/S
+VICTIMIZE/D/R/Z/G/S
+VICTOR/M/S
+VICTORIA
+VICTORIOUS/Y
+VICTORY/M/S
+VICTUAL/R/S
+VIDEO
+VIDEOTAPE/M/S
+VIE/D/R/S
+VIEW/D/R/Z/G/S
+VIEWABLE
+VIEWPOINT/M/S
+VIEWPORT/S
+VIGILANCE
+VIGILANT/Y
+VIGILANTE/M/S
+VIGNETTE/M/S
+VIGOR
+VIGOROUS/Y
+VILE/P/Y
+VILIFY/D/G/N/X/S
+VILLA/M/S
+VILLAGE/R/Z/S
+VILLAIN/M/S
+VILLAINOUS/P/Y
+VILLAINY
+VINDICTIVE/P/Y
+VINE/M/S
+VINEGAR
+VINEYARD/M/S
+VINTAGE
+VIOLATE/D/G/N/X/S
+VIOLATOR/M/S
+VIOLENCE
+VIOLENT/Y
+VIOLET/M/S
+VIOLIN/M/S
+VIOLINIST/M/S
+VIPER/M/S
+VIRGIN/M/S
+VIRGINIA
+VIRGINITY
+VIRTUAL/Y
+VIRTUE/M/S
+VIRTUOSO/M/S
+VIRTUOUS/Y
+VIRUS/M/S
+VISA/S
+VISAGE
+VISCOUNT/M/S
+VISCOUS
+VISIBILITY
+VISIBLE
+VISIBLY
+VISION/M/S
+VISIONARY
+VISIT/D/G/S
+VISITATION/M/S
+VISITOR/M/S
+VISOR/M/S
+VISTA/M/S
+VISUAL/Y
+VISUALIZATION
+VISUALIZE/D/R/G/S
+VITA
+VITAE
+VITAL/Y/S
+VITALITY
+VIVID/P/Y
+VIZIER
+VLSI
+VMS
+VOCABULARY/S
+VOCAL/Y/S
+VOCATION/M/S
+VOCATIONAL/Y
+VOGUE
+VOICE/D/R/Z/G/S
+VOID/D/R/G/S
+VOLATILE
+VOLATILITY/S
+VOLCANIC
+VOLCANO/M/S
+VOLLEY
+VOLLEYBALL/M/S
+VOLT/S
+VOLTAGE/S
+VOLUME/M/S
+VOLUNTARILY
+VOLUNTARY
+VOLUNTEER/D/G/S
+VOMIT/D/G/S
+VON
+VOTE/D/R/Z/G/V/S
+VOUCH/R/Z/G/S
+VOW/D/R/G/S
+VOWEL/M/S
+VOYAGE/D/R/Z/G/J/S
+VS
+VULGAR/Y
+VULNERABILITY/S
+VULNERABLE
+VULTURE/M/S
+WADE/D/R/G/S
+WAFER/M/S
+WAFFLE/M/S
+WAFT
+WAG/S
+WAGE/D/R/Z/G/S
+WAGON/R/S
+WAIL/D/G/S
+WAIST/M/S
+WAISTCOAT/M/S
+WAIT/D/R/Z/G/S
+WAITRESS/M/S
+WAIVE/D/R/G/S
+WAIVERABLE
+WAKE/D/G/S
+WAKEN/D/G
+WALK/D/R/Z/G/S
+WALL/D/G/S
+WALLET/M/S
+WALLOW/D/G/S
+WALNUT/M/S
+WALRUS/M/S
+WALTZ/D/G/S
+WAN/Y
+WAND/Z
+WANDER/D/R/Z/G/J/S
+WANE/D/G/S
+WANG
+WANT/D/G/S
+WANTON/P/Y
+WAR/M/S
+WARBLE/D/R/G/S
+WARD/R/N/X/S
+WARDROBE/M/S
+WARE/S
+WAREHOUSE/G/S
+WARFARE
+WARILY
+WARLIKE
+WARM/D/T/G/H/Y/S
+WARMER/S
+WARN/D/R/G/J/S
+WARNINGLY
+WARP/D/G/S
+WARRANT/D/G/S
+WARRANTY/M/S
+WARRED
+WARRING
+WARRIOR/M/S
+WARSHIP/M/S
+WART/M/S
+WARY/P
+WAS
+WASH/D/R/Z/G/J/S
+WASHINGTON
+WASN'T
+WASP/M/S
+WASTE/D/G/S
+WASTEFUL/P/Y
+WATCH/D/R/Z/G/J/S
+WATCHFUL/P/Y
+WATCHMAN
+WATCHWORD/M/S
+WATER/D/G/J/S
+WATERFALL/M/S
+WATERMELON
+WATERPROOF/G
+WATERWAY/M/S
+WATERY
+WAVE/D/R/Z/G/S
+WAVEFORM/M/S
+WAVEFRONT/M/S
+WAVELENGTH
+WAVELENGTHS
+WAX/D/R/Z/G/N/S
+WAXY
+WAY/M/S
+WAYSIDE
+WAYWARD
+WE'D
+WE'LL
+WE'RE
+WE'VE
+WE/T
+WEAK/T/R/N/X/Y
+WEAKEN/D/G/S
+WEAKNESS/M/S
+WEALTH
+WEALTHS
+WEALTHY/T
+WEAN/D/G
+WEAPON/M/S
+WEAR/R/G/S
+WEARABLE
+WEARILY
+WEARISOME/Y
+WEARY/P/D/T/R/G
+WEASEL/M/S
+WEATHER/D/G/S
+WEATHERCOCK/M/S
+WEAVE/R/G/S
+WEB/M/S
+WED/S
+WEDDED
+WEDDING/M/S
+WEDGE/D/G/S
+WEDNESDAY/M/S
+WEE/D
+WEEDS
+WEEK/Y/S
+WEEKEND/M/S
+WEEP/G/R/S/Z
+WEIGH/D/G/J
+WEIGHS
+WEIGHT/D/G/S
+WEIRD/Y
+WELCOME/D/G/S
+WELD/D/R/G/S
+WELFARE
+WELL/D/G/S
+WENCH/M/S
+WENT
+WEPT
+WERE
+WEREN'T
+WESLEY
+WESTERN/R/Z
+WESTWARD/S
+WET/P/Y/S
+WETTED
+WETTER
+WETTEST
+WETTING
+WHACK/D/G/S
+WHALE/R/G/S
+WHARF
+WHARVES
+WHAT/M
+WHATEVER
+WHATSOEVER
+WHEAT/N
+WHEEL/D/R/Z/G/J/S
+WHELP
+WHEN
+WHENCE
+WHENEVER
+WHERE/M
+WHEREABOUTS
+WHEREAS
+WHEREBY
+WHEREIN
+WHEREUPON
+WHEREVER
+WHETHER
+WHICH
+WHICHEVER
+WHILE
+WHIM/M/S
+WHIMPER/D/G/S
+WHIMSICAL/Y
+WHIMSY/M/S
+WHINE/D/G/S
+WHIP/M/S
+WHIPPED
+WHIPPER/M/S
+WHIPPING/M/S
+WHIRL/D/G/S
+WHIRLPOOL/M/S
+WHIRLWIND
+WHIRR/G
+WHISK/D/R/Z/G/S
+WHISKEY
+WHISPER/D/G/J/S
+WHISTLE/D/R/Z/G/S
+WHIT/X
+WHITE/P/T/R/G/Y/S
+WHITEN/D/R/Z/G/S
+WHITESPACE
+WHITEWASH/D
+WHITTLE/D/G/S
+WHIZ
+WHIZZED
+WHIZZES
+WHIZZING
+WHO/M
+WHOEVER
+WHOLE/P/S
+WHOLEHEARTED/Y
+WHOLESALE/R/Z
+WHOLESOME/P
+WHOLLY
+WHOM
+WHOMEVER
+WHOOP/D/G/S
+WHORE/M/S
+WHORL/M/S
+WHOSE
+WHY
+WICK/D/R/S
+WICKED/P/Y
+WIDE/T/R/Y
+WIDEN/D/R/G/S
+WIDESPREAD
+WIDOW/D/R/Z/S
+WIDTH
+WIDTHS
+WIELD/D/R/G/S
+WIFE/M/Y
+WIG/M/S
+WIGWAM
+WILD/P/T/R/Y
+WILDCARD/S
+WILDCAT/M/S
+WILDERNESS
+WILDLIFE
+WILE/S
+WILL/D/G/S
+WILLFUL/Y
+WILLIAM/M
+WILLINGLY
+WILLINGNESS
+WILLOW/M/S
+WILT/D/G/S
+WILY/P
+WIN/S
+WINCE/D/G/S
+WIND/D/R/Z/G/S
+WINDMILL/M/S
+WINDOW/M/S
+WINDY
+WINE/D/R/Z/G/S
+WING/D/G/S
+WINK/D/R/G/S
+WINNER/M/S
+WINNING/Y/S
+WINTER/D/G/S
+WINTRY
+WIPE/D/R/Z/G/S
+WIRE/D/G/S
+WIRELESS
+WIRETAP/M/S
+WIRY/P
+WISCONSIN
+WISDOM/S
+WISE/D/T/R/Y
+WISH/D/R/Z/G/S
+WISHFUL
+WISP/M/S
+WISTFUL/P/Y
+WIT/M/S
+WITCH/G/S
+WITCHCRAFT
+WITH/R/Z
+WITHAL
+WITHDRAW/G/S
+WITHDRAWAL/M/S
+WITHDRAWN
+WITHDREW
+WITHHELD
+WITHHOLD/R/Z/G/J/S
+WITHIN
+WITHOUT
+WITHSTAND/G/S
+WITHSTOOD
+WITNESS/D/G/S
+WITTY
+WIVES
+WIZARD/M/S
+WOE
+WOEFUL/Y
+WOKE
+WOLF
+WOLVES
+WOMAN/M/Y
+WOMANHOOD
+WOMB/M/S
+WOMEN/M
+WON
+WON'T
+WONDER/D/G/S
+WONDERFUL/P/Y
+WONDERINGLY
+WONDERMENT
+WONDROUS/Y
+WONT/D
+WOO/D/R/G/S
+WOOD/D/N/S
+WOODCHUCK/M/S
+WOODCOCK/M/S
+WOODENLY
+WOODENNESS
+WOODLAND
+WOODMAN
+WOODPECKER/M/S
+WOODWORK/G
+WOODY
+WOOF/D/R/Z/G/S
+WOOL/N/Y/S
+WORD/D/M/G/S
+WORDILY
+WORDY/P
+WORE
+WORK/D/R/Z/G/J/S
+WORKABLE
+WORKABLY
+WORKBENCH/M/S
+WORKBOOK/M/S
+WORKHORSE/M/S
+WORKINGMAN
+WORKLOAD
+WORKMAN
+WORKMANSHIP
+WORKMEN
+WORKSHOP/M/S
+WORKSTATION/S
+WORLD/M/Y/S
+WORLDLINESS
+WORLDWIDE
+WORM/D/G/S
+WORN
+WORRISOME
+WORRY/D/R/Z/G/S
+WORRYINGLY
+WORSE
+WORSHIP/D/R/G/S
+WORSHIPFUL
+WORST/D
+WORTH
+WORTHLESS/P
+WORTHS
+WORTHWHILE/P
+WORTHY/P/T
+WOULD
+WOULDN'T
+WOUND/D/G/S
+WOVE
+WOVEN
+WRANGLE/D/R
+WRAP/M/S
+WRAPPED
+WRAPPER/M/S
+WRAPPING/S
+WRATH
+WREAK/S
+WREATH/D/S
+WRECK/D/R/Z/G/S
+WRECKAGE
+WREN/M/S
+WRENCH/D/G/S
+WREST
+WRESTLE/R/G/J/S
+WRETCH/D/S
+WRETCHEDNESS
+WRIGGLE/D/R/G/S
+WRING/R/S
+WRINKLE/D/S
+WRIST/M/S
+WRISTWATCH/M/S
+WRIT/M/S
+WRITABLE
+WRITE/R/Z/G/J/S
+WRITER'S
+WRITHE/D/G/S
+WRITTEN
+WRONG/D/G/Y/S
+WROTE
+WROUGHT
+WRUNG
+XENIX
+XEROX
+YALE
+YANK/D/G/S
+YARD/M/S
+YARDSTICK/M/S
+YARN/M/S
+YAWN/R/G
+YEA/S
+YEAR/M/Y/S
+YEARN/D/G/J
+YEAST/M/S
+YELL/D/R/G
+YELLOW/P/D/T/R/G/S
+YELLOWISH
+YELP/D/G/S
+YEOMAN
+YEOMEN
+YES
+YESTERDAY
+YET
+YIELD/D/G/S
+YOKE/M/S
+YON
+YONDER
+YORK/R/Z
+YORKTOWN
+YOU'D
+YOU'LL
+YOU'RE
+YOU'VE
+YOU/H
+YOUNG/T/R/Y
+YOUNGSTER/M/S
+YOUR/S
+YOURSELF
+YOURSELVES
+YOUTHFUL/P/Y
+YOUTHS
+YUGOSLAVIA
+ZEAL
+ZEALOUS/P/Y
+ZEBRA/M/S
+ZENITH
+ZERO/D/G/H/S
+ZEROES
+ZEST
+ZIGZAG
+ZINC
+ZODIAC
+ZONAL/Y
+ZONE/D/G/S
+ZOO/M/S
+ZOOLOGICAL/Y
+ZOOM/G
Index: /branches/new-random/cocoa-ide/hemlock/src/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/src/bindings.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/bindings.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/bindings.lisp	(revision 13309)
@@ -0,0 +1,991 @@
+;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+       "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Some bindings:
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; Default key translations:
+
+;;; This page defines prefix characters that set specified modifier bits on
+;;; the next character typed.
+;;;
+(setf (key-translation #k"escape") '(:bits :meta))
+(setf (key-translation #k"control-[") '(:bits :meta))
+(setf (key-translation #k"control-z") '(:bits :control :meta))
+(setf (key-translation #k"control-Z") '(:bits :control :meta))
+(setf (key-translation #k"control-^") '(:bits :control))
+(setf (key-translation #k"control-c") '(:bits :hyper))
+(setf (key-translation #k"control-C") '(:bits :hyper))
+
+
+
+
+;;;; Most every binding.
+
+;;; Self insert letters:
+;;;
+(do-alpha-key-events (key-event :both)
+  (bind-key "Self Insert" key-event))
+
+(bind-key "Beginning of Line" #k"control-a")
+(bind-key "Select to Beginning of Line" #k"control-A")
+(bind-key "Delete Next Character" #k"control-d")
+(bind-key "Delete Next Character" #k"del")
+(bind-key "End of Line" #k"control-e")
+(bind-key "Select to End of Line" #k"control-E")
+(bind-key "Forward Character" #k"control-f")
+(bind-key "Forward Character" #k"rightarrow")
+(bind-key "Select Forward Character" #k"control-F")
+(bind-key "Select Forward Character" #k"shift-rightarrow")
+(bind-key "Backward Character" #k"control-b")
+(bind-key "Backward Character" #k"leftarrow")
+(bind-key "Select Backward Character" #k"control-B")
+(bind-key "Select Backward Character" #k"shift-leftarrow")
+(bind-key "Kill Line" #k"control-k")
+(bind-key "Refresh Screen" #k"control-l")
+(bind-key "Next Line" #k"control-n")
+(bind-key "Next Line" #k"downarrow")
+(bind-key "Select Next Line" #k"control-N")
+(bind-key "Select Next Line" #k"shift-downarrow")
+(bind-key "Previous Line" #k"control-p")
+(bind-key "Previous Line" #k"uparrow")
+(bind-key "Select Previous Line" #k"control-P")
+(bind-key "Select Previous Line" #k"shift-uparrow")
+(bind-key "Query Replace" #k"meta-%")
+(bind-key "Reverse Incremental Search" #k"control-r")
+(bind-key "Incremental Search" #k"control-s")
+(bind-key "Forward Search" #k"meta-s")
+(bind-key "Reverse Search" #k"meta-r")
+(bind-key "Transpose Characters" #k"control-t")
+(bind-key "Universal Argument" #k"control-u")
+(bind-key "Scroll Window Down" #k"control-v")
+(bind-key "Page Down" #k"pagedown")
+(bind-key "Scroll Window Up" #k"meta-v")
+(bind-key "Page Up" #k"pageup")
+;(bind-key "Scroll Next Window Down" #k"control-meta-v")
+;(bind-key "Scroll Next Window Up" #k"control-meta-V")
+
+(bind-key "Do Nothing" #k"leftdown")
+;(bind-key "Do Nothing" #k"leftup")
+
+(bind-key "Abort Command" #k"control-g")
+(bind-key "Abort Command" #k"control-G")
+(bind-key "Abort Command" #k"control-x control-g")
+(bind-key "Abort Command" #k"control-x control-G")
+
+
+(bind-key "Process File Options" #k"control-x m" :global)
+(bind-key "Ensure File Options Line" #k"control-meta-M" :global)
+(bind-key "Beginning of Buffer" #k"home")
+(bind-key "End of Buffer" #k"end")
+(bind-key "Undo" #k"control-_")
+(bind-key "Undo" #k"control-\/")
+(bind-key "Describe Key" #k"meta-?")
+(bind-key "What Cursor Position" #k"control-x =")
+
+
+#||
+(bind-key "Here to Top of Window" #k"leftdown")
+(bind-key "Do Nothing" #k"leftup")
+(bind-key "Top Line to Here" #k"rightdown")
+(bind-key "Do Nothing" #k"rightup")
+(bind-key "Point to Here" #k"middledown")
+(bind-key "Point to Here" #k"super-leftdown")
+(bind-key "Generic Pointer Up" #k"middleup")
+(bind-key "Generic Pointer Up" #k"super-leftup")
+(bind-key "Do Nothing" #k"super-rightup")
+(bind-key "Insert Kill Buffer" #k"super-rightdown")
+||#
+
+(bind-key "Insert File" #k"control-x control-r")
+(bind-key "Save File" #k"control-x control-s")
+(bind-key "Write File" #k"control-x control-w")
+;(bind-key "Visit File" #k"control-x control-v")
+(bind-key "Find File" #k"control-x control-v")
+(bind-key "Find File" #k"control-x control-f")
+(bind-key "Backup File" #k"control-x meta-b")
+;(bind-key "Save All Files" #k"control-x control-m")
+;(bind-key "Save All Files" #k"control-x return")
+;(bind-key "Save All Files and Exit" #k"control-x meta-z")
+
+;(bind-key "List Buffers" #k"control-x control-b")
+(bind-key "Buffer Not Modified" #k"meta-~")
+;(bind-key "Check Buffer Modified" #k"control-x ~")
+;(bind-key "Select Buffer" #k"control-x b")
+;(bind-key "Select Previous Buffer" #k"control-meta-l")
+;(bind-key "Circulate Buffers" #k"control-meta-L")
+;(bind-key "Create Buffer" #k"control-x meta-b")
+;(bind-key "Kill Buffer" #k"control-x k")
+;(bind-key "Select Random Typeout Buffer" #k"hyper-t")
+
+;(bind-key "Next Window" #k"control-x n")
+;(bind-key "Next Window" #k"control-x o")
+;(bind-key "Previous Window" #k"control-x p")
+;(bind-key "Split Window" #k"control-x 2")
+;(bind-key "New Window" #k"control-x control-n")
+;(bind-key "Delete Window" #k"control-x d")
+;(bind-key "Delete Next Window" #k"control-x 1")
+;(bind-key "Line to Top of Window" #k"meta-!")
+;(bind-key "Line to Center of Window" #k"meta-#")
+;(bind-key "Top of Window" #k"meta-,")
+;(bind-key "Bottom of Window" #k"meta-.")
+
+(bind-key "Delete Previous Character" #k"delete")
+(bind-key "Delete Previous Character" #k"backspace")
+(bind-key "Kill Next Word" #k"meta-d")
+(bind-key "Kill Previous Word" #k"meta-delete")
+(bind-key "Kill Previous Word" #k"meta-backspace")
+(bind-key "Exchange Point and Mark" #k"control-x control-x")
+(bind-key "Mark Whole Buffer" #k"control-x h")
+(bind-key "Set/Pop Mark" #k"control-@")
+(bind-key "Set/Pop Mark" #k"control-space")
+(bind-key "Pop and Goto Mark" #k"meta-@")
+(bind-key "Pop Mark" #k"control-meta-space") ;#k"control-meta-@" = "Mark Form".
+(bind-key "Kill Region" #k"control-w")
+(bind-key "Save Region" #k"meta-w")
+(bind-key "Un-Kill" #k"control-y")
+(bind-key "Rotate Kill Ring" #k"meta-y")
+
+(bind-key "Forward Word" #k"meta-f")
+(bind-key "Forward Word" #k"meta-rightarrow")
+(bind-key "Select Forward Word" #k"meta-F")
+(bind-key "Select Forward Word" #k"meta-shift-rightarrow")
+(bind-key "Backward Word" #k"meta-b")
+(bind-key "Backward Word" #k"meta-leftarrow")
+(bind-key "Select Backward Word" #k"meta-B")
+(bind-key "Select Backward Word" #k"meta-shift-leftarrow")
+
+(bind-key "Forward Paragraph" #k"meta-]")
+(bind-key "Forward Sentence" #k"meta-e")
+(bind-key "Backward Paragraph" #k"meta-[")
+(bind-key "Backward Sentence" #k"meta-a")
+
+(bind-key "Mark Paragraph" #k"meta-h")
+
+(bind-key "Forward Kill Sentence" #k"meta-k")
+(bind-key "Backward Kill Sentence" #k"control-x delete")
+(bind-key "Backward Kill Sentence" #k"control-x backspace")
+
+(bind-key "Beginning of Buffer" #k"meta-\<")
+(bind-key "End of Buffer" #k"meta-\>")
+(bind-key "Mark to Beginning of Buffer" #k"control-\<")
+(bind-key "Mark to End of Buffer" #k"control-\>")
+
+(bind-key "Extended Command" #k"meta-x")
+
+(bind-key "Uppercase Word" #k"meta-u")
+(bind-key "Lowercase Word" #k"meta-l")
+(bind-key "Capitalize Word" #k"meta-c")
+
+;(bind-key "Previous Page" #k"control-x [")
+;(bind-key "Next Page" #k"control-x ]")
+;(bind-key "Mark Page" #k"control-x control-p")
+;(bind-key "Count Lines Page" #k"control-x l")
+
+(bind-key "Expand Dynamic Abbreviation" #k"meta-/") ;; Aquamacs and LW binding
+(bind-key "Expand Dynamic Abbreviation" #k"meta-`") ;; MCL binding
+
+(bind-key "Help" #k"control-h")
+
+
+;;;; Argument Digit and Negative Argument.
+
+(bind-key "Argument Digit" #k"meta-\-")
+(bind-key "Argument Digit" #k"meta-0")
+(bind-key "Argument Digit" #k"meta-1")
+(bind-key "Argument Digit" #k"meta-2")
+(bind-key "Argument Digit" #k"meta-3")
+(bind-key "Argument Digit" #k"meta-4")
+(bind-key "Argument Digit" #k"meta-5")
+(bind-key "Argument Digit" #k"meta-6")
+(bind-key "Argument Digit" #k"meta-7")
+(bind-key "Argument Digit" #k"meta-8")
+(bind-key "Argument Digit" #k"meta-9")
+(bind-key "Argument Digit" #k"control-\-")
+(bind-key "Argument Digit" #k"control-0")
+(bind-key "Argument Digit" #k"control-1")
+(bind-key "Argument Digit" #k"control-2")
+(bind-key "Argument Digit" #k"control-3")
+(bind-key "Argument Digit" #k"control-4")
+(bind-key "Argument Digit" #k"control-5")
+(bind-key "Argument Digit" #k"control-6")
+(bind-key "Argument Digit" #k"control-7")
+(bind-key "Argument Digit" #k"control-8")
+(bind-key "Argument Digit" #k"control-9")
+(bind-key "Argument Digit" #k"control-meta-\-")
+(bind-key "Argument Digit" #k"control-meta-0")
+(bind-key "Argument Digit" #k"control-meta-1")
+(bind-key "Argument Digit" #k"control-meta-2")
+(bind-key "Argument Digit" #k"control-meta-3")
+(bind-key "Argument Digit" #k"control-meta-4")
+(bind-key "Argument Digit" #k"control-meta-5")
+(bind-key "Argument Digit" #k"control-meta-6")
+(bind-key "Argument Digit" #k"control-meta-7")
+(bind-key "Argument Digit" #k"control-meta-8")
+(bind-key "Argument Digit" #k"control-meta-9")
+
+(bind-key "Digit" #k"\-")
+(bind-key "Digit" #k"0")
+(bind-key "Digit" #k"1")
+(bind-key "Digit" #k"2")
+(bind-key "Digit" #k"3")
+(bind-key "Digit" #k"4")
+(bind-key "Digit" #k"5")
+(bind-key "Digit" #k"6")
+(bind-key "Digit" #k"7")
+(bind-key "Digit" #k"8")
+(bind-key "Digit" #k"9")
+
+
+
+;;;; Self Insert and Quoted Insert.
+
+(bind-key "Quoted Insert" #k"control-q")
+(bind-key "Native Quoted Insert" #k"meta-!")
+
+(bind-key "Self Insert" #k"space")
+(bind-key "Self Insert" #k"!")
+(bind-key "Self Insert" #k"@")
+(bind-key "Self Insert" #k"#")
+(bind-key "Self Insert" #k"$")
+(bind-key "Self Insert" #k"%")
+(bind-key "Self Insert" #k"^")
+(bind-key "Self Insert" #k"&")
+(bind-key "Self Insert" #k"*")
+(bind-key "Self Insert" #k"(")
+(bind-key "Self Insert" #k")")
+(bind-key "Self Insert" #k"_")
+(bind-key "Self Insert" #k"+")
+(bind-key "Self Insert" #k"~")
+(bind-key "Self Insert" #k"[")
+(bind-key "Self Insert" #k"]")
+(bind-key "Self Insert" #k"\\")
+(bind-key "Self Insert" #k"|")
+(bind-key "Self Insert" #k":")
+(bind-key "Self Insert" #k";")
+(bind-key "Self Insert" #k"\"")
+(bind-key "Self Insert" #k"'")
+(bind-key "Self Insert" #k"=")
+(bind-key "Self Insert" #k"`")
+(bind-key "Self Insert" #k"\<")
+(bind-key "Self Insert" #k"\>")
+(bind-key "Self Insert" #k",")
+(bind-key "Self Insert" #k".")
+(bind-key "Self Insert" #k"?")
+(bind-key "Self Insert" #k"/")
+(bind-key "Self Insert" #k"{")
+(bind-key "Self Insert" #k"}")
+
+
+
+
+;;;; Echo Area.
+
+;;; Basic echo-area commands.
+;;; 
+(bind-key "Help on Parse" #k"home" :mode "Echo Area")
+(bind-key "Help on Parse" #k"control-_" :mode "Echo Area")
+
+(bind-key "Complete Keyword" #k"escape" :mode "Echo Area")
+(bind-key "Complete Field" #k"space" :mode "Echo Area")
+(bind-key "Confirm Parse" #k"return" :mode "Echo Area")
+
+;;; Rebind some standard commands to behave better.
+;;; 
+;;(bind-key "Kill Parse" #k"control-u" :mode "Echo Area")
+(bind-key "Insert Parse Default" #k"control-i" :mode "Echo Area")
+(bind-key "Insert Parse Default" #k"tab" :mode "Echo Area")
+(bind-key "Echo Area Delete Previous Character" #k"delete" :mode "Echo Area")
+(bind-key "Echo Area Delete Previous Character" #k"backspace" :mode "Echo Area")
+(bind-key "Echo Area Kill Previous Word" #k"meta-h" :mode "Echo Area")
+(bind-key "Echo Area Kill Previous Word" #k"meta-delete" :mode "Echo Area")
+(bind-key "Echo Area Kill Previous Word" #k"meta-backspace" :mode "Echo Area")
+(bind-key "Echo Area Kill Previous Word" #k"control-w" :mode "Echo Area")
+(bind-key "Beginning of Parse" #k"control-a" :mode "Echo Area")
+(bind-key "Beginning of Parse" #k"meta-\<" :mode "Echo Area")
+(bind-key "Echo Area Backward Character" #k"control-b" :mode "Echo Area")
+(bind-key "Echo Area Backward Word" #k"meta-b" :mode "Echo Area")
+(bind-key "Next Parse" #k"control-n" :mode "Echo Area")
+(bind-key "Previous Parse" #k"control-p" :mode "Echo Area")
+
+;;; Remove some dangerous standard bindings.
+;;; 
+(bind-key "Illegal" #k"control-x" :mode "Echo Area")
+(bind-key "Illegal" #k"control-meta-c" :mode "Echo Area")
+(bind-key "Illegal" #k"control-meta-s" :mode "Echo Area")
+(bind-key "Illegal" #k"control-meta-l" :mode "Echo Area")
+(bind-key "Illegal" #k"meta-x" :mode "Echo Area")
+(bind-key "Illegal" #k"control-s" :mode "Echo Area")
+(bind-key "Illegal" #k"control-r" :mode "Echo Area")
+(bind-key "Illegal" #k"hyper-t" :mode "Echo Area")
+
+
+
+
+;;;; Listener and Editor Modes.
+(bind-key "Confirm Listener Input" #k"return" :mode "Listener")
+(bind-key "Confirm Listener Input" #k"shift-return" :mode "Listener")
+(bind-key "Previous Interactive Input" #k"meta-p" :mode "Listener")
+(bind-key "Search Previous Interactive Input" #k"meta-P" :mode "Listener")
+(bind-key "Next Interactive Input" #k"meta-n" :mode "Listener")
+(bind-key "Kill Interactive Input" #k"meta-i" :mode "Listener")
+;(bind-key "Abort Eval Input" #k"control-meta-i" :mode "Listener")
+(bind-key "Interactive Beginning of Line" #k"control-a" :mode "Listener")
+(bind-key "POP Or Delete Forward" #k"control-d" :mode "Listener")
+(bind-key "Reenter Interactive Input" #k"control-return" :mode "Listener")
+
+;;; Make the user use C-x C-w to save the file, and take care
+;;; not to associate the Listener document with any particular
+;;; file or type.
+(bind-key "Illegal" #k"control-x control-s" :mode "Listener")
+(bind-key "Save To File" #k"control-x control-w" :mode "Listener")
+
+(bind-key "Editor Evaluate Expression" #k"control-meta-escape")
+(bind-key "Editor Evaluate Expression" #k"meta-escape"  :mode "Editor")
+
+(bind-key "Editor Execute Expression" #k"enter" :mode "Editor")
+(bind-key "Editor Execute Expression" #k"control-x control-e" :mode "Editor")
+(bind-key "Editor Execute Defun" #k"control-meta-x" :mode "Editor")
+(bind-key "Editor Execute Defun" #k"control-x control-c" :mode "Editor")
+(bind-key "Editor Execute Defun" #k"control-x control-C" :mode "Editor")
+
+(bind-key "Editor Macroexpand-1 Expression" #k"control-m" :mode "Editor")
+(bind-key "Editor Macroexpand Expression" #k"control-x control-m" :mode "Editor")
+(bind-key "Editor Describe Function Call" #k"control-meta-A" :mode "Editor")
+(bind-key "Editor Describe Symbol" #k"control-meta-S" :mode "Editor")
+
+
+
+;;;; Lisp (some).
+
+(bind-key "Indent Form" #k"control-meta-q")
+(bind-key "Fill Lisp Comment Paragraph" #k"meta-q" :mode "Lisp")
+(bind-key "Current Function Arglist" #k"control-x control-a" :mode "Lisp")
+(bind-key "Arglist On Space" #k"Space" :mode "Lisp")
+(bind-key "Defindent" #k"control-meta-#")
+(bind-key "Beginning of Defun" #k"control-meta-a")
+(bind-key "Select to Beginning of Defun" #k"control-meta-A")
+(bind-key "End of Defun" #k"control-meta-e")
+(bind-key "Select to End of Defun" #k"control-meta-E")
+(bind-key "Forward Form" #k"control-meta-f")
+(bind-key "Forward Form" #k"control-rightarrow")
+(bind-key "Select Forward Form" #k"control-meta-F")
+(bind-key "Select Forward Form" #k"control-shift-rightarrow")
+(bind-key "Backward Form" #k"control-meta-b")
+(bind-key "Backward Form" #k"control-leftarrow")
+(bind-key "Select Backward Form" #k"control-meta-B")
+(bind-key "Select Backward Form" #k"control-shift-leftarrow")
+(bind-key "Forward List" #k"control-meta-n")
+(bind-key "Select Forward List" #k"control-meta-N")
+(bind-key "Backward List" #k"control-meta-p")
+(bind-key "Select Backward List" #k"control-meta-P")
+(bind-key "Transpose Forms" #k"control-meta-t")
+(bind-key "Forward Kill Form" #k"control-meta-k")
+(bind-key "Backward Kill Form" #k"control-meta-backspace")
+(bind-key "Backward Kill Form" #k"control-meta-delete")
+(bind-key "Mark Form" #k"control-meta-@")
+(bind-key "Mark Defun" #k"control-meta-h")
+(bind-key "Insert ()" #k"meta-(")
+(bind-key "Move over )" #k"meta-)")
+(bind-key "Backward Up List" #k"control-meta-(")
+(bind-key "Backward Up List" #k"control-meta-u")
+(bind-key "Forward Up List" #k"control-meta-)")
+(bind-key "Down List" #k"control-meta-d")
+(bind-key "Extract List" #k"control-meta-l")
+;;(bind-key "Lisp Insert )" #k")" :mode "Lisp")
+(bind-key "Delete Previous Character Expanding Tabs" #k"backspace" :mode "Lisp")
+(bind-key "Delete Previous Character Expanding Tabs" #k"delete" :mode "Lisp")
+(bind-key "Goto Absolute Line" #k"meta-g")
+;;;(bind-key "Set Package Name" #k"control-x p" :mode "Lisp")
+
+#+listener-bindings
+(progn
+(bind-key "Evaluate Expression" #k"meta-escape")
+(bind-key "Evaluate Defun" #k"control-x control-e")
+(bind-key "Compile Defun" #k"control-x control-c")
+(bind-key "Compile Buffer File" #k"control-x c")
+
+(bind-key "Describe Function Call" #k"control-meta-A")
+(bind-key "Describe Symbol" #k"control-meta-S")
+)
+
+(bind-key "Goto Definition" #k"meta-.")
+
+#+debugger-bindings
+(progn
+(bind-key "Debug Up" #k"control-meta-hyper-u")
+(bind-key "Debug Down" #k"control-meta-hyper-d")
+(bind-key "Debug Top" #k"control-meta-hyper-t")
+(bind-key "Debug Bottom" #k"control-meta-hyper-b")
+(bind-key "Debug Frame" #k"control-meta-hyper-f")
+(bind-key "Debug Quit" #k"control-meta-hyper-q")
+(bind-key "Debug Go" #k"control-meta-hyper-g")
+(bind-key "Debug Abort" #k"control-meta-hyper-a")
+(bind-key "Debug Restart" #k"control-meta-hyper-r")
+(bind-key "Debug Help" #k"control-meta-hyper-h")
+(bind-key "Debug Error" #k"control-meta-hyper-e")
+(bind-key "Debug Backtrace" #k"control-meta-hyper-B")
+(bind-key "Debug Print" #k"control-meta-hyper-p")
+(bind-key "Debug Verbose Print" #k"control-meta-hyper-P")
+(bind-key "Debug List Locals" #k"control-meta-hyper-l")
+(bind-key "Debug Source" #k"control-meta-hyper-s")
+(bind-key "Debug Edit Source" #k"control-meta-hyper-S")
+(bind-key "Debug Flush Errors" #k"control-meta-hyper-F")
+)
+
+
+
+;;;; More Miscellaneous bindings.
+
+(bind-key "Open Line" #k"Control-o")
+(bind-key "New Line" #k"return")
+(bind-key "New Line" #k"shift-return")
+
+(bind-key "Transpose Words" #k"meta-t")
+(bind-key "Transpose Lines" #k"control-x control-t")
+(bind-key "Transpose Regions" #k"control-x t")
+
+;(bind-key "Uppercase Region" #k"control-x control-u")
+;(bind-key "Lowercase Region" #k"control-x control-l")
+;(bind-key "Capitalize Region" #k"control-x control-c")
+
+(bind-key "Delete Indentation" #k"meta-^")
+(bind-key "Delete Indentation" #k"control-meta-^")
+(bind-key "Delete Horizontal Space" #k"meta-\\")
+(bind-key "Delete Blank Lines" #k"control-x control-o" :global)
+(bind-key "Just One Space" #k"meta-space")
+(bind-key "Back to Indentation" #k"meta-m")
+(bind-key "Back to Indentation" #k"control-meta-m")
+(bind-key "Indent Rigidly" #k"control-x tab")
+(bind-key "Indent Rigidly" #k"control-x control-i")
+
+(bind-key "Indent New Line" #k"linefeed")
+(bind-key "Indent New Line" #k"control-return")
+(bind-key "Indent" #k"tab")
+(bind-key "Indent" #k"control-i")
+(bind-key "Indent Region" #k"control-meta-\\")
+(bind-key "Quote Tab" #k"meta-tab")
+
+#||
+(bind-key "Directory" #k"control-x control-\d")
+(bind-key "Verbose Directory" #k"control-x control-D")
+||#
+
+(bind-key "Activate Region" #k"control-x control-@")
+(bind-key "Activate Region" #k"control-x control-space")
+
+(bind-key "Save Position" #k"control-x s")
+(bind-key "Jump to Saved Position" #k"control-x j")
+(bind-key "Put Register" #k"control-x x")
+(bind-key "Get Register" #k"control-x g")
+
+#+pascal-mode
+(progn
+(bind-key "Delete Previous Character Expanding Tabs" #k"backspace"
+          :mode "Pascal")
+(bind-key "Delete Previous Character Expanding Tabs" #k"delete" :mode "Pascal")
+(bind-key "Scribe Insert Bracket" #k")" :mode "Pascal")
+(bind-key "Scribe Insert Bracket" #k"]" :mode "Pascal")
+(bind-key "Scribe Insert Bracket" #k"}" :mode "Pascal")
+)
+
+
+
+;;;; Auto Fill Mode.
+
+(bind-key "Fill Paragraph" #k"meta-q")
+(bind-key "Fill Region" #k"meta-g")
+(bind-key "Set Fill Prefix" #k"control-x .")
+(bind-key "Set Fill Column" #k"control-x f")
+(bind-key "Auto Fill Return" #k"return" :mode "Fill")
+(bind-key "Auto Fill Space" #k"space" :mode "Fill")
+(bind-key "Auto Fill Linefeed" #k"linefeed" :mode "Fill")
+
+
+
+
+#|
+;;;; Keyboard macro bindings.
+
+(bind-key "Define Keyboard Macro" #k"control-x (")
+(bind-key "Define Keyboard Macro Key" #k"control-x meta-(")
+(bind-key "End Keyboard Macro" #k"control-x )")
+(bind-key "End Keyboard Macro" #k"control-x hyper-)")
+(bind-key "Last Keyboard Macro" #k"control-x e")
+(bind-key "Keyboard Macro Query" #k"control-x q")
+|#
+
+
+
+;;;; Spell bindings.
+#||
+(progn
+  (bind-key "Check Word Spelling" #k"meta-$")
+  (bind-key "Add Word to Spelling Dictionary" #k"control-x $")
+
+  (dolist (info (command-bindings (getstring "Self Insert" *command-names*)))
+    (let* ((key (car info))
+           (key-event (svref key 0))
+           (character (key-event-char key-event)))
+      (unless (or (alpha-char-p character) (eq key-event #k"'"))
+        (bind-key "Auto Check Word Spelling" key :mode "Spell"))))
+  (bind-key "Auto Check Word Spelling" #k"return" :mode "Spell")
+  (bind-key "Auto Check Word Spelling" #k"tab" :mode "Spell")
+  (bind-key "Auto Check Word Spelling" #k"linefeed" :mode "Spell")
+  (bind-key "Correct Last Misspelled Word" #k"meta-:")
+  (bind-key "Undo Last Spelling Correction" #k"control-x a")
+  )
+
+
+;;;; Overwrite Mode.
+||#
+
+#||
+(bind-key "Overwrite Delete Previous Character" #k"delete" :mode "Overwrite")
+(bind-key "Overwrite Delete Previous Character" #k"backspace" :mode "Overwrite")
+
+;;; Do up the printing characters ...
+(do ((i 33 (1+ i)))
+    ((= i 126))
+  (let ((key-event (hi:char-key-event (code-char i))))
+    (bind-key "Self Overwrite" key-event :mode "Overwrite")))
+
+(bind-key "Self Overwrite" #k"space" :mode "Overwrite")
+||#
+
+
+
+;;;; Comment bindings.
+
+(bind-key "Indent for Comment" #k"meta-;")
+(bind-key "Set Comment Column" #k"control-x ;")
+(bind-key "Kill Comment" #k"control-meta-;")
+(bind-key "Down Comment Line" #k"meta-n")
+(bind-key "Up Comment Line" #k"meta-p")
+(bind-key "Indent New Comment Line" #k"meta-j")
+(bind-key "Indent New Comment Line" #k"meta-linefeed")
+
+
+
+#||
+;;;; Word Abbrev Mode.
+
+(bind-key "Add Mode Word Abbrev" #k"control-x control-a")
+(bind-key "Add Global Word Abbrev" #k"control-x +")
+(bind-key "Inverse Add Mode Word Abbrev" #k"control-x control-h")
+(bind-key "Inverse Add Global Word Abbrev" #k"control-x \-")
+;; Removed in lieu of "Pop and Goto Mark".
+;;(bind-key "Abbrev Expand Only" #k"meta-space")
+(bind-key "Word Abbrev Prefix Mark" #k"meta-\"")
+(bind-key "Unexpand Last Word" #k"control-x u")
+
+(dolist (key (list #k"!" #k"~" #k"@" #k"#" #k";" #k"$" #k"%" #k"^" #k"&" #k"*"
+                   #k"\-" #k"_" #k"=" #k"+" #k"[" #k"]" #k"(" #k")" #k"/" #k"|"
+                   #k":" #k"'" #k"\"" #k"{" #k"}" #k"," #k"\<" #k"." #k"\>"
+                   #k"`" #k"\\" #k"?" #k"return" #k"newline" #k"tab" #k"space"))
+  (bind-key "Abbrev Expand Only" key :mode "Abbrev"))
+
+||#
+
+
+
+;;;; Scribe Mode.
+
+#+scribe-mode
+(progn
+(dolist (key (list #k"]" #k")" #k"}" #k"\>"))
+  (bind-key "Scribe Insert Bracket" key :mode "Scribe"))
+
+;;GB (bind-key "Scribe Buffer File" #k"control-x c" :mode "Scribe")
+(bind-key "Select Scribe Warnings" #k"control-meta-C" :mode "Scribe")
+
+(bind-key "Insert Scribe Directive" #k"hyper-i" :mode "Scribe")
+)
+
+
+
+;;;; Mailer commands.
+#+mail-mode
+(progn
+;;; Clear everything user might hit to avoid getting the internal error
+;;; message about modifying read-only buffers.
+;;;
+(do-alpha-key-events (key-event :both)
+  (bind-key "Illegal" key-event :mode "Headers")
+  (bind-key "Illegal" key-event :mode "Message"))
+
+;;; Global.
+;;;
+(bind-key "Incorporate and Read New Mail" #k"control-x i")
+(bind-key "Send Message" #k"control-x m")
+(bind-key "Message Headers" #k"control-x r")
+
+;;; Both Headers and Message modes.
+;;;
+;;; The bindings in these two blocks should be the same, one for "Message" mode
+;;; and one for "Headers" mode.
+;;;
+(bind-key "Next Message" #k"meta-n" :mode "Message")
+(bind-key "Previous Message" #k"meta-p" :mode "Message")
+(bind-key "Next Undeleted Message" #k"n" :mode "Message")
+(bind-key "Previous Undeleted Message" #k"p" :mode "Message")
+(bind-key "Send Message" #k"s" :mode "Message")
+(bind-key "Send Message" #k"m" :mode "Message")
+(bind-key "Forward Message" #k"f" :mode "Message")
+(bind-key "Headers Delete Message" #k"k" :mode "Message")
+(bind-key "Headers Undelete Message" #k"u" :mode "Message")
+(bind-key "Headers Refile Message" #k"o" :mode "Message")
+(bind-key "List Mail Buffers" #k"l" :mode "Message")
+(bind-key "Quit Headers" #k"q" :mode "Message")
+(bind-key "Incorporate and Read New Mail" #k"i" :mode "Message")
+(bind-key "Beginning of Buffer" #k"\<" :mode "Message")
+(bind-key "End of Buffer" #k"\>" :mode "Message")
+;;;
+(bind-key "Next Message" #k"meta-n" :mode "Headers")
+(bind-key "Previous Message" #k"meta-p" :mode "Headers")
+(bind-key "Next Undeleted Message" #k"n" :mode "Headers")
+(bind-key "Previous Undeleted Message" #k"p" :mode "Headers")
+(bind-key "Send Message" #k"s" :mode "Headers")
+(bind-key "Send Message" #k"m" :mode "Headers")
+(bind-key "Forward Message" #k"f" :mode "Headers")
+(bind-key "Headers Delete Message" #k"k" :mode "Headers")
+(bind-key "Headers Undelete Message" #k"u" :mode "Headers")
+(bind-key "Headers Refile Message" #k"o" :mode "Headers")
+(bind-key "List Mail Buffers" #k"l" :mode "Headers")
+(bind-key "Quit Headers" #k"q" :mode "Headers")
+(bind-key "Incorporate and Read New Mail" #k"i" :mode "Headers")
+(bind-key "Beginning of Buffer" #k"\<" :mode "Headers")
+(bind-key "End of Buffer" #k"\>" :mode "Headers")
+
+
+;;; Headers mode.
+;;;
+(bind-key "Delete Message and Down Line" #k"d" :mode "Headers")
+(bind-key "Pick Headers" #k"h" :mode "Headers")
+(bind-key "Show Message" #k"space" :mode "Headers")
+(bind-key "Show Message" #k"." :mode "Headers")
+(bind-key "Reply to Message" #k"r" :mode "Headers")
+(bind-key "Expunge Messages" #k"!" :mode "Headers")
+(bind-key "Headers Help" #k"?" :mode "Headers")
+
+
+;;; Message mode.
+;;;
+(bind-key "Delete Message and Show Next" #k"d" :mode "Message")
+(bind-key "Goto Headers Buffer" #k"^" :mode "Message")
+(bind-key "Scroll Message" #k"space" :mode "Message")
+(bind-key "Scroll Message" #k"control-v" :mode "Message")
+(bind-key "Scroll Window Up" #k"backspace" :mode "Message")
+(bind-key "Scroll Window Up" #k"delete" :mode "Message")
+(bind-key "Reply to Message in Other Window" #k"r" :mode "Message")
+(bind-key "Edit Message Buffer" #k"e" :mode "Message")
+(bind-key "Insert Message Region" #k"hyper-y" :mode "Message")
+(bind-key "Message Help" #k"?" :mode "Message")
+
+
+;;; Draft mode.
+;;;
+(bind-key "Goto Headers Buffer" #k"hyper-^" :mode "Draft")
+(bind-key "Goto Message Buffer" #k"hyper-m" :mode "Draft")
+(bind-key "Deliver Message" #k"hyper-s" :mode "Draft")
+(bind-key "Deliver Message" #k"hyper-c" :mode "Draft")
+(bind-key "Insert Message Buffer" #k"hyper-y" :mode "Draft")
+(bind-key "Delete Draft and Buffer" #k"hyper-q" :mode "Draft")
+(bind-key "List Mail Buffers" #k"hyper-l" :mode "Draft")
+(bind-key "Draft Help" #k"hyper-?" :mode "Draft")
+);#+mail-mode
+
+
+
+;;;; Netnews.
+
+#+netnews-mode
+(progn
+;;; Clear everything user might hit to avoid getting the internal error
+;;; message about modifying read-only buffers.
+;;;
+(do-alpha-key-events (key-event :both)
+  (bind-key "Illegal" key-event :mode "News-Headers")
+  (bind-key "Illegal" key-event :mode "News-Message"))
+
+
+;;; Global Netnews bindings
+;;;
+(bind-key "Netnews Post Message" #k"C-x P")
+
+
+;;; Both News-Headers and News-Message modes.
+;;;
+;;; The bindings in these two blocks should be the same, one for "News-Message"
+;;; mode and one for "News-Headers" mode.
+;;;
+(bind-key "List All Groups" #k"l" :mode "News-Headers")
+(bind-key "Netnews Append to File" #k"a" :mode "News-Headers")
+(bind-key "Netnews Forward Message" #k"f" :mode "News-Headers")
+(bind-key "Netnews Go to Next Group" #k"g" :mode "News-Headers")
+(bind-key "Netnews Next Article" #k"n" :mode "News-Headers")
+(bind-key "Netnews Previous Article" #k"p" :mode "News-Headers")
+(bind-key "Netnews Quit Starting Here" #k"." :mode "News-Headers")
+(bind-key "Netnews Group Punt Messages" #k"G" :mode "News-Headers")
+(bind-key "Netnews Show Whole Header" #k"w" :mode "News-Headers")
+(bind-key "Netnews Reply to Sender in Other Window" #k"r" :mode "News-Headers")
+(bind-key "Netnews Reply to Group in Other Window" #k"R" :mode "News-Headers")
+;;;
+(bind-key "List All Groups" #k"l" :mode "News-Message")
+(bind-key "Netnews Append to File" #k"a" :mode "News-Message")
+(bind-key "Netnews Forward Message" #k"f" :mode "News-Message")
+(bind-key "Netnews Go to Next Group" #k"g" :mode "News-Message")
+(bind-key "Netnews Next Article" #k"n" :mode "News-Message")
+(bind-key "Netnews Previous Article" #k"p" :mode "News-Message")
+(bind-key "Netnews Quit Starting Here" #k"." :mode "News-Message")
+(bind-key "Netnews Group Punt Messages" #k"G" :mode "News-Message")
+(bind-key "Netnews Show Whole Header" #k"w" :mode "News-Message")
+(bind-key "Netnews Reply to Sender in Other Window" #k"r" :mode "News-Message")
+(bind-key "Netnews Reply to Group in Other Window" #k"R" :mode "News-Message")
+
+
+;;; News-Headers.
+;;;
+(bind-key "Netnews Exit" #k"q" :mode "News-Headers")
+(bind-key "Netnews Headers File Message" #k"o" :mode "News-Headers")
+(bind-key "Netnews Headers Scroll Window Down" #k"c-v" :mode "News-Headers")
+(bind-key "Netnews Headers Scroll Window Up" #k"m-v" :mode "News-Headers")
+(bind-key "Netnews Next Line" #k"C-n" :mode "News-Headers")
+(bind-key "Netnews Next Line" #k"Downarrow" :mode "News-Headers")
+(bind-key "Netnews Previous Line" #k"C-p" :mode "News-Headers")
+(bind-key "Netnews Previous Line" #k"Uparrow" :mode "News-Headers")
+(bind-key "Netnews Select Message Buffer" #k"hyper-m" :mode "News-Headers")
+(bind-key "Netnews Show Article" #k"space" :mode "News-Headers")
+
+
+;;; News-Message.
+;;;
+(bind-key "Insert Message Region" #k"Hyper-y" :mode "News-Message")
+(bind-key "Netnews Message File Message" #k"o" :mode "News-Message")
+(bind-key "Netnews Message Keep Buffer" #k"k" :mode "News-Message")
+(bind-key "Netnews Message Quit" #k"q" :mode "News-Message")
+(bind-key "Netnews Message Scroll Down"  #k"space" :mode "News-Message")
+(bind-key "Netnews Goto Draft Buffer" #k"hyper-d" :mode "News-Message")
+(bind-key "Netnews Goto Headers Buffer" #k"^" :mode "News-Message")
+(bind-key "Netnews Goto Headers Buffer" #k"hyper-h" :mode "News-Message")
+(bind-key "Netnews Goto Post Buffer" #k"hyper-p" :mode "News-Message")
+(bind-key "Scroll Window Up" #k"backspace" :mode "News-Message")
+
+
+;;; Post.
+;;;
+(bind-key "Netnews Select Message Buffer" #k"hyper-m" :mode "Post")
+(bind-key "Netnews Deliver Post" #k"hyper-s" :mode "Post")
+(bind-key "Netnews Abort Post" #k"hyper-q" :mode "Post")
+(bind-key "Insert Message Buffer" #k"Hyper-y" :mode "Post")
+
+
+;;; News-Browse.
+
+(bind-key "Netnews Quit Browse" #k"q" :mode "News-Browse")
+(bind-key "Netnews Browse Add Group To File" #k"a" :mode "News-Browse")
+(bind-key "Netnews Browse Read Group" #k"space" :mode "News-Browse")
+(bind-key "Next Line" #k"n" :mode "News-Browse")
+(bind-key "Previous Line" #k"p" :mode "News-Browse")
+)
+
+
+;;;; Process (Shell).
+
+#+shell-mode
+(progn
+(bind-key "Shell" #k"control-meta-s")
+(bind-key "Confirm Process Input" #k"return" :mode "Process")
+(bind-key "Shell Complete Filename" #k"M-escape" :mode "Process")
+(bind-key "Interrupt Buffer Subprocess" #k"hyper-c" :mode "Process")
+(bind-key "Stop Buffer Subprocess" #k"hyper-z" :mode "Process")
+(bind-key "Quit Buffer Subprocess" #k"hyper-\\")
+(bind-key "Send EOF to Process" #k"hyper-d")
+
+(bind-key "Previous Interactive Input" #k"meta-p" :mode "Process")
+(bind-key "Search Previous Interactive Input" #k"meta-P" :mode "Process")
+(bind-key "Interactive Beginning of Line" #k"control-a" :mode "Process")
+(bind-key "Kill Interactive Input" #k"meta-i" :mode "Process")
+(bind-key "Next Interactive Input" #k"meta-n" :mode "Process")
+(bind-key "Reenter Interactive Input" #k"control-return" :mode "Process")
+)
+
+
+;;;; Bufed.
+
+#||
+(bind-key "Bufed" #k"control-x control-meta-b")
+(bind-key "Bufed Delete" #k"d" :mode "Bufed")
+(bind-key "Bufed Delete" #k"control-d" :mode "Bufed")
+(bind-key "Bufed Undelete" #k"u" :mode "Bufed")
+(bind-key "Bufed Expunge" #k"!" :mode "Bufed")
+(bind-key "Bufed Quit" #k"q" :mode "Bufed")
+(bind-key "Bufed Goto" #k"space" :mode "Bufed")
+(bind-key "Bufed Goto and Quit" #k"super-leftdown" :mode "Bufed")
+(bind-key "Bufed Save File" #k"s" :mode "Bufed")
+(bind-key "Next Line" #k"n" :mode "Bufed")
+(bind-key "Previous Line" #k"p" :mode "Bufed")
+
+
+(bind-key "Bufed Help" #k"?" :mode "Bufed")
+|#
+
+
+
+;;;; Dired.
+#||
+(progn
+(bind-key "Dired" #k"control-x control-meta-d")
+
+(bind-key "Dired Delete File and Down Line" #k"d" :mode "Dired")
+(bind-key "Dired Delete File with Pattern" #k"D" :mode "Dired")
+(bind-key "Dired Delete File" #k"control-d" :mode "Dired")
+(bind-key "Dired Delete File" #k"k" :mode "Dired")
+
+(bind-key "Dired Undelete File and Down Line" #k"u" :mode "Dired")
+(bind-key "Dired Undelete File with Pattern" #k"U" :mode "Dired")
+(bind-key "Dired Undelete File" #k"control-u" :mode "Dired")
+
+(bind-key "Dired Expunge Files" #k"!" :mode "Dired")
+(bind-key "Dired Update Buffer" #k"hyper-u" :mode "Dired")
+(bind-key "Dired View File" #k"space" :mode "Dired")
+(bind-key "Dired Edit File" #k"e" :mode "Dired")
+(bind-key "Dired Up Directory" #k"^" :mode "Dired")
+(bind-key "Dired Quit" #k"q" :mode "Dired")
+(bind-key "Dired Help" #k"?" :mode "Dired")
+
+(bind-key "Dired Copy File" #k"c" :mode "Dired")
+(bind-key "Dired Copy with Wildcard" #k"C" :mode "Dired")
+(bind-key "Dired Rename File" #k"r" :mode "Dired")
+(bind-key "Dired Rename with Wildcard" #k"R" :mode "Dired")
+
+(bind-key "Next Line" #k"n" :mode "Dired")
+(bind-key "Previous Line" #k"p" :mode "Dired")
+)
+||#
+
+
+;;;; View Mode.
+#||
+(progn
+(bind-key "View Scroll Down" #k"space" :mode "View")
+(bind-key "Scroll Window Up" #k"b" :mode "View")
+(bind-key "Scroll Window Up" #k"backspace" :mode "View")
+(bind-key "Scroll Window Up" #k"delete" :mode "View")
+(bind-key "View Return" #k"^" :mode "View")
+(bind-key "View Quit" #k"q" :mode "View")
+(bind-key "View Edit File" #k"e" :mode "View")
+(bind-key "View Help" #k"?" :mode "View")
+(bind-key "Beginning of Buffer" #k"\<" :mode "View")
+(bind-key "End of Buffer" #k"\>" :mode "View")
+)
+||#
+
+
+;;;; Lisp Library.
+
+#||
+(bind-key "Describe Pointer Library Entry" #k"leftdown" :mode "Lisp-Lib")
+(bind-key "Load Pointer Library Entry" #k"rightdown" :mode "Lisp-Lib")
+(bind-key "Describe Library Entry" #k"space" :mode "Lisp-Lib")
+(bind-key "Load Library Entry" #k"l" :mode "Lisp-Lib")
+(bind-key "Exit Lisp Library" #k"q" :mode "Lisp-Lib")
+(bind-key "Lisp Library Help" #k"?" :mode "Lisp-Lib")
+||#
+
+
+
+;;;; Completion mode.
+
+(dolist (c (command-bindings (getstring "Self Insert" *command-names*)))
+  (bind-key "Completion Self Insert" (car c) :mode "Completion"))
+
+(bind-key "Completion Self Insert" #k"space" :mode "Completion")
+(bind-key "Completion Self Insert" #k"tab" :mode "Completion")
+(bind-key "Completion Self Insert" #k"return" :mode "Completion")
+(bind-key "Completion Self Insert" #k"linefeed" :mode "Completion")
+
+(bind-key "Completion Complete Word" #k"end" :mode "Completion")
+(bind-key "Completion Rotate Completions" #k"meta-end" :mode "Completion")
+
+
+;;;; Caps-Lock mode.
+
+(do-alpha-key-events (key-event :lower)
+  (bind-key "Self Insert Caps Lock" key-event :mode "CAPS-LOCK"))
+
+
+
+;;;; I-Search mode.
+;;;;
+;;;; Anything that's not explicitly bound here will exit i-search.
+
+(dotimes (n hi::hemlock-char-code-limit)
+  (when (standard-char-p (code-char n))
+    (let ((key (make-key-event n)))
+      (bind-key "I-Search Self Insert" key :mode "I-Search"))))
+
+(bind-key "I-Search Repeat Forward" #k"control-s" :mode "I-Search")
+(bind-key "I-Search Repeat Backward" #k"control-r" :mode "I-Search")
+(bind-key "I-Search Backup" #k"backspace" :mode "I-Search")
+(bind-key "I-Search Backup" #k"delete" :mode "I-Search")
+(bind-key "I-Search Abort" #k"control-g" :mode "I-Search")
+(bind-key "I-Search Abort" #k"control-G" :mode "I-Search")
+(bind-key "I-Search Exit or Search" #k"escape" :mode "I-Search")
+(bind-key "I-Search Yank Word" #k"control-w" :mode "I-Search")
+(bind-key "Quoted Insert" #k"control-q" :mode "I-Search")
+
+
+;;;; Query/Replace mode.
+;;;;
+;;;; Anything that's not explicitly bound here will exit i-search.
+
+(bind-key "Query/Replace This" #k"y" :mode "Query/Replace")
+(bind-key "Query/Replace This" #k"space" :mode "Query/Replace")
+(bind-key "Query/Replace Skip" #k"n" :mode "Query/Replace")
+(bind-key "Query/Replace Skip" #k"backspace" :mode "Query/Replace")
+(bind-key "Query/Replace Skip" #k"delete" :mode "Query/Replace")
+(bind-key "Query/Replace All" #k"!" :mode "Query/Replace")
+(bind-key "Query/Replace Last" #k"." :mode "Query/Replace")
+(bind-key "Query/Replace Exit" #k"q" :mode "Query/Replace")
+(bind-key "Query/Replace Exit" #k"escape" :mode "Query/Replace")
+(bind-key "Query/Replace Abort" #k"control-g" :mode "Query/Replace")
+(bind-key "Query/Replace Abort" #k"control-G" :mode "Query/Replace")
+(bind-key "Query/Replace Help" #k"h" :mode "Query/Replace")
+(bind-key "Query/Replace Help" #k"?" :mode "Query/Replace")
+(bind-key "Query/Replace Help" #k"home" :mode "Query/Replace")
+(bind-key "Query/Replace Help" #k"control-_" :mode "Query/Replace")
+
+;;;; Logical characters.
+ 
+(setf (logical-key-event-p #k"control-g" :abort) t)
+(setf (logical-key-event-p #k"y" :yes) t)
+(setf (logical-key-event-p #k"space" :yes) t)
+(setf (logical-key-event-p #k"n" :no) t)
+(setf (logical-key-event-p #k"backspace" :no) t)
+(setf (logical-key-event-p #k"delete" :no) t)
+(setf (logical-key-event-p #k"home" :help) t)
+(setf (logical-key-event-p #k"h" :help) t)
+(setf (logical-key-event-p #k"?" :help) t)
+(setf (logical-key-event-p #k"control-_" :help) t)
+(setf (logical-key-event-p #k"return" :confirm) t)
+(setf (logical-key-event-p #k"control-q" :quote) t)
+(setf (logical-key-event-p #k"k" :keep) t)
+(setf (logical-key-event-p #k"y" :y) t)
+(setf (logical-key-event-p #k"Y" :y) t)
+(setf (logical-key-event-p #k"n" :n) t)
+(setf (logical-key-event-p #k"N" :n) t)
+
Index: /branches/new-random/cocoa-ide/hemlock/src/buffer.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/buffer.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/buffer.lisp	(revision 13309)
@@ -0,0 +1,585 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Rob MacLachlan
+;;;
+;;; This file contains functions for changing modes and buffers.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Some buffer structure support.
+
+(defun buffer-writable (buffer)
+  "Returns whether buffer may be modified."
+  (buffer-%writable buffer))
+
+(defun %set-buffer-writable (buffer value)
+  (invoke-hook hemlock::buffer-writable-hook buffer value)
+  (setf (buffer-%writable buffer) value))
+
+;;; BUFFER-MODIFIED uses the buffer modification tick which is for redisplay.
+;;; We can never set this down to "unmodify" a buffer, so we keep an
+;;; unmodification tick.  The buffer is modified only if this is less than the
+;;; modification tick.
+;;;
+(defun buffer-modified (buffer)
+  "Return T if Buffer has been modified, NIL otherwise.  Can be set with Setf."
+  (unless (bufferp buffer) (error "~S is not a buffer." buffer))
+  (> (buffer-modified-tick buffer) (buffer-unmodified-tick buffer)))
+
+(defun %set-buffer-modified (buffer sense)
+  "If true make the buffer modified, if NIL unmodified."
+  (unless (bufferp buffer) (error "~S is not a buffer." buffer))
+  (let* ((was-modified (buffer-modified buffer))
+	 (changed (not (eq was-modified (buffer-modified buffer)))))
+    (invoke-hook hemlock::buffer-modified-hook buffer sense)
+    (if sense
+      (setf (buffer-modified-tick buffer) (tick))
+      (setf (buffer-unmodified-tick buffer) (tick)))
+    (when changed
+      (if sense
+	(hemlock-ext:note-buffer-unsaved buffer)
+	(hemlock-ext:note-buffer-saved buffer))
+      (note-modeline-change buffer)))
+  sense)
+
+
+(declaim (inline buffer-name buffer-pathname buffer-region))
+
+(defun buffer-region (buffer)
+  "Return the region which contains Buffer's text."
+  (buffer-%region buffer))
+
+(defun %set-buffer-region (buffer new-region)
+  (let ((old (buffer-region buffer)))
+    (delete-region old)
+    (ninsert-region (region-start old) new-region)
+    old))
+
+(defun buffer-name (buffer)
+  "Return Buffer's string name."
+  (buffer-%name buffer))
+
+(declaim (special *buffer-names*))
+
+(defun %set-buffer-name (buffer name)
+  (multiple-value-bind (entry foundp) (getstring name *buffer-names*)
+    (cond ((or (not foundp) (eq entry buffer))
+	   (invoke-hook hemlock::buffer-name-hook buffer name)
+	   (delete-string (buffer-%name buffer) *buffer-names*)
+	   (setf (getstring name *buffer-names*) buffer)
+	   (setf (buffer-%name buffer) name))
+	  (t (error "Cannot rename buffer ~S to ~S.  Name already in use."
+		    buffer name)))))
+
+(defun buffer-pathname (buffer)
+  "Return a pathname for the file in Buffer.  This is the truename
+  of the file as of the last time it was read or written."
+  (buffer-%pathname buffer))
+
+
+(defun %set-buffer-pathname (buffer pathname)
+  (invoke-hook hemlock::buffer-pathname-hook buffer pathname)
+  (setf (buffer-%pathname buffer) pathname))
+
+(defun buffer-modeline-fields (buffer)
+  "Return a copy of the buffer's modeline fields list."
+  (do ((finfos (buffer-%modeline-fields buffer) (cdr finfos))
+       (result () (cons (ml-field-info-field (car finfos)) result)))
+      ((null finfos) (nreverse result))))
+
+(defun set-buffer-modeline-fields (buffer modeline-fields)
+  (unless (every #'modeline-field-p modeline-fields)
+    (error "Fields must be a list of modeline-field objects."))
+  (setf (buffer-%modeline-fields buffer)
+	(do ((fields modeline-fields (cdr fields))
+	     (res nil (cons (make-ml-field-info (car fields))
+			    res)))
+	    ((null fields) (nreverse res)))))
+
+(defun buffer-modeline-field-p (buffer field)
+  "If field, a modeline-field or the name of one, is in buffer's list of
+   modeline-fields, it is returned; otherwise, nil."
+  (let ((finfo (internal-buffer-modeline-field-p buffer field)))
+    (if finfo (ml-field-info-field finfo))))
+
+(defun internal-buffer-modeline-field-p (buffer field)
+  (let ((fields (buffer-%modeline-fields buffer)))
+    (if (modeline-field-p field)
+	(find field fields :test #'eq :key #'ml-field-info-field)
+	(find field fields
+	      :key #'(lambda (f)
+		       (modeline-field-name (ml-field-info-field f)))))))
+
+
+
+
+;;;; BUFFER-MAJOR-MODE.
+
+(defmacro with-mode-and-buffer ((name major-p buffer) &body forms)
+  `(let ((mode (get-mode-object ,name)))
+    (setq ,name (mode-object-name mode))
+    (,(if major-p 'unless 'when) (mode-object-major-p mode)
+      (error "~S is not a ~:[Minor~;Major~] Mode." ,name ,major-p))
+    (check-type ,buffer buffer)
+    ,@forms))
+
+;;; BUFFER-MAJOR-MODE  --  Public
+;;;
+;;;
+(defun buffer-major-mode (buffer)
+  "Return the name of Buffer's major mode.  To change tha major mode
+  use Setf."
+  (check-type buffer buffer)
+  (mode-object-name (buffer-major-mode-object buffer)))
+
+;;; %SET-BUFFER-MAJOR-MODE  --  Public
+;;;
+(defun %set-buffer-major-mode (buffer name)
+  "Set the major mode of some buffer to the Name'd mode."
+  (with-mode-and-buffer (name t buffer)
+    (invoke-hook hemlock::buffer-major-mode-hook buffer name)
+    (let ((old-mode (buffer-major-mode-object buffer)))
+      (invoke-hook (%value (mode-object-hook-name old-mode)) buffer nil)
+      (funcall (mode-object-cleanup-function old-mode) buffer))
+    (setf (buffer-major-mode-object buffer) mode)
+    (invalidate-shadow-attributes buffer)
+    (funcall (mode-object-setup-function mode) buffer)
+    (invoke-hook (%value (mode-object-hook-name mode)) buffer t))
+  nil)
+
+
+
+
+;;;; BUFFER-MINOR-MODE.
+
+;;; BUFFER-MINOR-MODE  --  Public
+;;;
+;;;    Check if the mode-object is in the buffer's mode-list.
+;;;
+(defun buffer-minor-mode (buffer name)
+  "Return true if the minor mode named Name is active in Buffer.
+  A minor mode can be turned on or off with Setf."
+  (with-mode-and-buffer (name nil buffer)
+    (not (null (member mode (buffer-minor-mode-objects buffer))))))
+    
+(declaim (special *mode-names*))
+
+;;; %SET-BUFFER-MINOR-MODE  --  Public
+;;;
+;;;    Activate or deactivate a minor mode, with due respect for
+;;; bindings.
+;;;
+(defun %set-buffer-minor-mode (buffer name new-value)
+  (with-mode-and-buffer (name nil buffer)
+    (let ((objects (buffer-minor-mode-objects buffer)))
+      (unless (if (member mode objects) new-value (not new-value))
+        (invoke-hook hemlock::buffer-minor-mode-hook buffer name new-value)
+        (cond
+         ;; Adding a new mode, insert sorted.
+         (new-value
+          (do ((m objects (cdr m))
+               (prev nil m))
+              ((or (null m)
+                   (< (mode-object-precedence (car m))
+                      (mode-object-precedence mode)))
+               (if prev
+                 (setf (cdr prev) (cons mode m))
+                 (setf (buffer-minor-mode-objects buffer) (setq objects (cons mode m))))))
+          (funcall (mode-object-setup-function mode) buffer)
+          (invoke-hook (%value (mode-object-hook-name mode)) buffer t))
+         (t
+          ;; Removing an active mode.
+          (invoke-hook (%value (mode-object-hook-name mode)) buffer nil)
+          (funcall (mode-object-cleanup-function mode) buffer)
+          (setf (buffer-minor-mode-objects buffer) (delq mode (buffer-minor-mode-objects buffer)))))))
+    new-value))
+
+;;; BUFFER-MODES -- Public
+;;; List of buffer mode names, in precendence order, major mode first.
+;;;
+(defun buffer-modes (buffer)
+  "Return the list of the names of the modes active in a given buffer."
+  (cons (buffer-major-mode buffer)
+        (nreverse (mapcar #'mode-object-name (buffer-minor-mode-objects buffer)))))
+
+
+
+;;;; CURRENT-BUFFER, CURRENT-POINT, and buffer using setup and cleanup.
+
+(declaim (inline current-buffer))
+
+(defun current-buffer () "Return the current buffer object." *current-buffer*)
+
+(defun current-point ()
+  "Return the Buffer-Point of the current buffer."
+  (buffer-point *current-buffer*))
+
+
+
+(defun current-point-collapsing-selection ()
+  "Return the Buffer-Point of the current buffer, deactivating the
+   region."
+  (let* ((b *current-buffer*)
+         (point (buffer-point b)))
+    ;; Deactivate the region
+    (setf (buffer-region-active b) nil)
+    point))
+
+(defun current-point-extending-selection ()
+  "Return the Buffer-Point of the current buffer, ensuring that
+   the region's active."
+  (let* ((b *current-buffer*)
+         (point (buffer-point b)))
+    ;; If the region is active, keep it active.  Otherwise,
+    ;; establish a new (empty) region at point.
+    (unless (%buffer-current-region-p b)
+      (push-new-buffer-mark point t))
+    point))
+
+(defun current-point-for-selection-start ()
+  "Return the Buffer-Point of the current buffer, ensuring that
+   the region's active.  If the region was active but the
+   buffer's SELECTION-SET-BY-COMMAND flag is false, ensure that
+   point precedes mark by exchanging their positions if necessary."
+  (let* ((b *current-buffer*)
+         (point (buffer-point b)))
+    ;; If the region is active, keep it active.  Otherwise,
+    ;; establish a new (empty) region at point.
+    (if (%buffer-current-region-p b)
+      (unless (buffer-selection-set-by-command b)
+        (let* ((mark (current-mark)))
+          (if (mark< mark point)
+            (with-mark ((temp point))
+              (move-mark point mark)
+              (move-mark mark temp)))))
+      (push-new-buffer-mark point t))
+    point))
+
+(defun current-point-for-selection-end ()
+  "Return the Buffer-Point of the current buffer, ensuring that
+   the region's active.  If the region was active but the
+   buffer's SELECTION-SET-BY-COMMAND flag is false, ensure that
+   point follows mark by exchanging their positions if necessary."
+  (let* ((b *current-buffer*)
+         (point (buffer-point b)))
+    ;; If the region is active, keep it active.  Otherwise,
+    ;; establish a new (empty) region at point.
+    (if (%buffer-current-region-p b)
+      (unless (buffer-selection-set-by-command b)
+        (let* ((mark (current-mark)))
+          (if (mark> mark point)
+            (with-mark ((temp point))
+              (move-mark point mark)
+              (move-mark mark temp)))))
+      (push-new-buffer-mark point t))
+    point))
+  
+
+
+(defun current-point-for-insertion ()
+  "Check to see if the current buffer can be modified at its
+  current point; error if not.  If there's a selection in the
+  current buffer, delete it.  Return the current point."
+  (let* ((buffer *current-buffer*)
+         (point (buffer-point buffer)))
+    (check-buffer-modification buffer point)
+    (let* ((region (%buffer-current-region buffer)))
+      (when region
+        (delete-region region))
+      point)))
+
+(defun current-point-for-deletion ()
+  "Check to see if the current buffer can be modified at its
+  current point; error if not.  If there's a selection in the
+  current buffer, delete it and return NIL, else return the
+  current point."
+  (let* ((buffer *current-buffer*)
+         (point (buffer-point buffer)))
+    (check-buffer-modification buffer point)
+    (let* ((region (%buffer-current-region buffer)))
+      (if region
+        (progn
+          (delete-region region)
+          nil)
+        point))))
+
+(defun current-point-unless-selection ()
+  "Check to see if the current buffer can be modified at its
+  current point; error if not.  If there's a selection in the
+  current buffer, return NIL, else return the  current point."
+  (let* ((buffer *current-buffer*)
+         (point (buffer-point buffer)))
+    (check-buffer-modification buffer point)
+    (let* ((region (%buffer-current-region buffer)))
+      (unless region
+        point))))
+
+;;;; WITH-WRITABLE-BUFFER
+
+;;; This list indicates recursive use of WITH-WRITABLE-BUFFER on the same
+;;; buffer.
+;;;
+(defvar *writable-buffers* ())
+
+(defmacro with-writable-buffer ((buffer) &body body)
+  "Executes body in a scope where buffer is writable.  After body executes,
+   this sets the buffer's modified and writable status to nil."
+  (let ((buf (gensym))
+	(no-unwind (gensym)))
+    `(let* ((,buf ,buffer)
+	    (,no-unwind (member ,buf *writable-buffers* :test #'eq))
+	    (*writable-buffers* (if ,no-unwind
+				    *writable-buffers*
+				    (cons ,buf *writable-buffers*))))
+       (unwind-protect
+	   (progn
+	     (setf (buffer-writable ,buf) t)
+	     ,@body)
+	 (unless ,no-unwind
+	   (setf (buffer-modified ,buf) nil)
+	   (setf (buffer-writable ,buf) nil))))))
+
+
+
+
+;;;; DEFMODE.
+
+(defun defmode (name &key (setup-function #'identity) 
+		     (cleanup-function #'identity) major-p transparent-p
+		     precedence documentation hidden default-command)
+  "Define a new mode, specifying whether it is a major mode, and what the
+   setup and cleanup functions are.  Precedence, which defaults to 0.0, and is
+   any integer or float, determines the order of the minor modes in a buffer.
+   A minor mode having a greater precedence is always considered before a mode
+   with lesser precedence when searching for key-bindings and variable values.
+   If Transparent-p is true, then all key-bindings local to the defined mode
+   are transparent, meaning that they do not shadow other bindings, but rather
+   are executed in addition to them.  Documentation is used as introductory
+   text for mode describing commands."
+  (let ((hook-str (concatenate 'string name " Mode Hook"))
+	(mode (getstring name *mode-names*)))
+    (cond
+     (mode
+      (when (if major-p
+		(not (mode-object-major-p mode))
+		(mode-object-major-p mode))
+	(cerror "Let bad things happen"
+		"Mode ~S is being redefined as a ~:[Minor~;Major~] mode ~
+		where it was ~%~
+		previously a ~:*~:[Major~;Minor~] mode." name major-p))
+      (warn "Mode ~S is being redefined, variables and bindings will ~
+	    be preserved." name)
+      (setq name (mode-object-name mode)))
+     (t
+      (defhvar hook-str
+	       (concatenate 'string "This is the mode hook variable for "
+	       name " Mode."))
+      (setq mode (make-mode-object
+		  :variables (make-string-table)
+		  :bindings (make-hash-table)
+		  :hook-name (getstring hook-str *global-variable-names*)
+                  :hidden hidden))
+      (setf (getstring name *mode-names*) mode)))
+
+    (when (eq precedence :highest)
+      (setq precedence most-positive-double-float))
+    (if precedence
+	(if major-p
+	    (error "Precedence ~S is meaningless for a major mode." precedence)
+	    (check-type precedence number))
+	(setq precedence 0))
+    
+    (when default-command
+      (setf (mode-object-default-command mode) default-command))
+
+    (setf (mode-object-major-p mode) major-p
+	  (mode-object-documentation mode) documentation
+	  (mode-object-transparent-p mode) transparent-p
+	  (mode-object-precedence mode) precedence
+	  (mode-object-setup-function mode) setup-function
+	  (mode-object-cleanup-function mode) cleanup-function
+	  (mode-object-name mode) name))
+  nil)
+
+(defun mode-major-p (name)
+  "Returns T if Name is the name of a major mode, or NIL if is the name of
+  a minor mode."
+  (mode-object-major-p (get-mode-object name)))
+
+(defun mode-variables (name)
+  "Return the string-table that contains the names of the modes variables."
+  (mode-object-variables (get-mode-object name)))
+
+(defun mode-documentation (name)
+  "Returns the documentation for mode with name."
+  (mode-object-documentation (get-mode-object name)))
+
+
+
+
+;;;; Making and Deleting buffers.
+
+(defvar *buffer-list* () "A list of all the buffer objects.")
+
+(defvar *current-buffer* ()
+  "Internal variable which might contain the current buffer." )
+
+(defun all-buffers ()
+  "List of all buffers"
+  (remove-if #'echo-buffer-p *buffer-list*))
+
+(ccl:defloadvar *echo-area-counter* 0)
+
+(defun make-echo-buffer ()
+  (let* ((name (loop as name = (format nil "Echo Area ~d" (incf *echo-area-counter*))
+		  until (null (getstring name *buffer-names*))
+		  finally (return name)))
+         (buffer (internal-make-echo-buffer
+                  :%name name
+                  :major-mode-object (getstring "Echo Area" *mode-names*))))
+    (initialize-buffer buffer)))
+
+(defun make-buffer (name &key (modes (value hemlock::default-modes))
+                              (modeline-fields (value hemlock::default-modeline-fields))
+                              delete-hook)
+  "Creates and returns a buffer with the given Name if a buffer with Name does
+   not already exist, otherwise returns nil.  Modes is a list of mode names,
+   and Modeline-fields is a list of modeline field objects.  Delete-hook is a
+   list of functions that take a buffer as the argument."
+  (when (getstring name *buffer-names*)
+    (cerror "Try to delete" "~s already exists" name)
+    (let ((buffer (getstring name *buffer-names*)))
+      (delete-buffer buffer)))
+  (cond ((getstring name *buffer-names*)
+	 nil)
+	(t
+	 (unless (listp delete-hook)
+	   (error ":delete-hook is a list of functions -- ~S." delete-hook))
+	 (let* ((buffer (internal-make-buffer
+                         :%name name
+                         :major-mode-object (getstring "Fundamental" *mode-names*)
+                         :delete-hook delete-hook)))
+           (initialize-buffer buffer :modeline-fields modeline-fields :modes modes)))))
+
+(defun initialize-buffer (buffer &key modeline-fields modes)
+  (setf (buffer-bindings buffer) (make-hash-table))
+  (setf (buffer-variables buffer) (make-string-table))
+  (let ((region (make-empty-region)))
+    (setf (line-%buffer (mark-line (region-start region))) buffer)
+    (setf (buffer-%region buffer) region)
+    (setf (buffer-point buffer) (copy-mark (region-end region))))
+  (setf (getstring (buffer-%name buffer) *buffer-names*) buffer)
+  (push buffer *buffer-list*)
+  (set-buffer-modeline-fields buffer modeline-fields)
+  (when modes
+    (unless (equalp modes '("Fundamental"))
+      (setf (buffer-major-mode buffer) (car modes))
+      (dolist (m (cdr modes))
+        (setf (buffer-minor-mode buffer m) t))))
+  (invoke-hook hemlock::make-buffer-hook buffer)
+  buffer)
+
+(defun delete-buffer (buffer)
+  "Deletes a buffer.  If buffer is current, an error is signaled."
+  (when (eq buffer *current-buffer*)
+    (error "Cannot delete current buffer ~S." buffer))
+  (when (buffer-document buffer)
+    (error "Cannot delete displayed buffer ~S." buffer))
+  (invoke-hook (buffer-delete-hook buffer) buffer)
+  (invoke-hook hemlock::delete-buffer-hook buffer)
+  (setq *buffer-list* (delq buffer *buffer-list*))
+  (delete-string (buffer-name buffer) *buffer-names*)
+  nil)
+
+(defun buffer-lines (buffer)
+  (let ((lines (buffer-%lines buffer)))
+    (when (eql (fill-pointer lines) 0)
+      (loop for origin = 0 then (+ origin (buffer-line-length l) 1)
+            for l = (mark-line (region-start (buffer-%region buffer))) then (line-next l) while l
+            do (setf (line-origin l) origin)
+            do (vector-push-extend l lines)))
+    lines))
+
+;; This will return the last line if posn is out of range (or first line if it's negative)
+(defun buffer-line-at-absolute-position (buffer posn)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((lines (buffer-lines (ccl:require-type buffer 'buffer)))
+         (posn (ccl:require-type posn 'fixnum))
+         (vec (ccl::array-data-and-offset lines))
+         (start 0)
+         (end (fill-pointer lines)))
+    (declare (fixnum start end posn))
+    (loop
+      (let* ((middle (ash (the fixnum (+ start end)) -1))
+             (line (svref vec middle)))
+        (declare (fixnum middle))
+        (when (= middle start)
+          (return line))
+        (if (< posn (the fixnum (line-origin line)))
+          (setq end middle)
+          (setq start middle))))))
+
+;; Called whenever change a line's next or previous pointer.  Don't update immediately
+;; so don't thrash when inserting multiple lines.
+(declaim (inline invalidate-buffer-lines))
+(defun invalidate-buffer-lines (buffer)
+  (setf (fill-pointer (buffer-%lines buffer)) 0))
+
+;;;; Buffer start and end marks.
+
+(defun buffer-start-mark (buffer)
+  "Returns the buffer-region's start mark."
+  (region-start (buffer-region buffer)))
+
+(defun buffer-end-mark (buffer)
+  "Returns the buffer-region's end mark."
+  (region-end (buffer-region buffer)))
+
+
+
+
+;;;; Setting up initial buffer.
+
+;;; SETUP-INITIAL-BUFFER  --  Internal
+;;;
+;;;    Create the buffer "Main" and the mode "Fundamental".  We make a
+;;; dummy fundamental mode before we make the buffer Main, because
+;;; "make-buffer" wants fundamental to be defined when it is called, and we
+;;; can't make the real fundamental mode until there is a current buffer
+;;; because "defmode" wants to invoke its mode definition hook.  Also,
+;;; when creating the "Main" buffer, "Default Modeline Fields" is not yet
+;;; defined, so we supply this argument to MAKE-BUFFER as nil.  This is
+;;; fine since firing up the editor in a core must set the "Main" buffer's
+;;; modeline according to this variable in case the user changed it in his
+;;; init file.  After the main buffer is created we then define the real
+;;; fundamental mode and bash it into the buffer.
+;;;
+(defun setup-initial-buffer ()
+  ;; Make it look like the mode is there so make-buffer doesn't die.
+  (setf (getstring "Fundamental" *mode-names*)
+	(make-mode-object :major-p t))
+  ;; Make it look like there is a make-buffer-hook...
+  (setf (get 'hemlock::make-buffer-hook 'hemlock-variable-value)
+	(make-variable-object 'foo))
+  (setq *current-buffer* (make-buffer "Main" :modes '("Fundamental")
+				      :modeline-fields nil))
+  ;; Make the bogus variable go away...
+  (remf (symbol-plist 'hemlock::make-buffer-hook) 'hemlock-variable-value)
+  ;; Make it go away so defmode doesn't die.
+  (setf (getstring "Fundamental" *mode-names*) nil)
+  (defmode "Fundamental" :major-p t)
+  ;; Bash the real mode object into the buffer.
+  (let ((obj (getstring "Fundamental" *mode-names*)))
+    (setf (buffer-major-mode-object *current-buffer*) obj)))
Index: /branches/new-random/cocoa-ide/hemlock/src/charmacs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/charmacs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/charmacs.lisp	(revision 13309)
@@ -0,0 +1,104 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Implementation specific character-hacking macros and constants.
+;;;
+(in-package :hemlock-internals)
+
+;;; This file contains various constants and macros which are implementation or
+;;; ASCII dependant.  It contains some versions of CHAR-CODE which do not check
+;;; types and ignore the top bit so that various structures can be allocated
+;;; 128 long instead of 256, and we don't get errors if a loser visits a binary
+;;; file.
+;;;
+;;; There are so many different constants and macros implemented the same.
+;;; This is to separate various mechanisms; for example, in principle the
+;;; char-code-limit for the syntax functions is independant of that for the
+;;; searching functions
+;;;
+
+
+
+
+;;;; Stuff for the Syntax table functions (syntax)
+
+(defconstant syntax-char-code-limit hemlock-char-code-limit
+  "The highest char-code which a character argument to the syntax
+  table functions may have.")
+
+
+;;; This has the effect of treating all characters with code > 255
+;;; as if they were #\u+00ff.  Not quite right, but better than
+;;; flying off the end.
+(defmacro syntax-char-code (char)
+  (let* ((code (gensym)))
+    `(let* ((,code (char-code ,char)))
+      (declare (type (mod #x110000) ,code))
+      (if (< ,code 256)
+        ,code
+        (char-code #\A)))))
+
+
+;;;; Stuff used by the searching primitives (search)
+;;;
+(defconstant search-char-code-limit char-code-limit
+  "The exclusive upper bound on significant char-codes for searching.")
+(defmacro search-char-code (ch)
+  `(char-code ,ch))
+;;;
+;;;    search-hash-code must be a function with the following properties:
+;;; given any character it returns a number between 0 and 
+;;; search-char-code-limit, and the same hash code must be returned 
+;;; for the upper and lower case forms of each character.
+;;;    In ASCII this is can be done by ANDing out the 5'th bit.
+;;;
+(defmacro search-hash-code (ch)
+  `(char-code (char-upcase ,ch)))
+
+;;; Doesn't do anything special, but it should fast and not waste any time
+;;; checking type and whatnot.
+(defmacro search-char-upcase (ch)
+  `(char-upcase (the base-char ,ch)))
+
+
+
+
+;;;; DO-ALPHA-CHARS.
+
+;;; ALPHA-CHARS-LOOP loops from start-char through end-char binding var
+;;; to the alphabetic characters and executing body.  Note that the manual
+;;; guarantees lower and upper case char codes to be separately in order,
+;;; but other characters may be interspersed within that ordering.
+(defmacro alpha-chars-loop (var test result body)
+  (let ((n (gensym))
+	(end-char-code (gensym)))
+    `(do ((,n (char-code #\A) (1+ ,n))
+	  (,end-char-code 255))
+	 ((> ,n ,end-char-code) ,result)
+       (let ((,var (code-char ,n)))
+	 (when (,test ,var)
+	   ,@body)))))
+
+(defmacro do-alpha-chars ((var kind &optional result) &rest forms)
+  "(do-alpha-chars (var kind [result]) . body).  Kind is one of
+   :lower, :upper, or :both, and var is bound to each character in
+   order as specified under character relations in the manual.  When
+   :both is specified, lowercase letters are processed first."
+  (case kind
+    (:both
+     `(progn (alpha-chars-loop ,var lower-case-p nil ,forms)
+	     (alpha-chars-loop ,var upper-case-p ,result ,forms)))
+    (:lower
+     `(alpha-chars-loop ,var lower-case-p ,result ,forms))
+    (:upper
+     `(alpha-chars-loop ,var upper-case-p ,result ,forms))
+    (t (error "Kind argument not one of :lower, :upper, or :both -- ~S."
+	      kind))))
Index: /branches/new-random/cocoa-ide/hemlock/src/charprops.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/charprops.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/charprops.lisp	(revision 13309)
@@ -0,0 +1,795 @@
+(in-package "HI")
+
+(defun make-empty-charprops-changes (&optional (size 2))
+  (make-array size :adjustable t :fill-pointer 0))
+
+(defun insert-charprops-change (changes index new)
+  "Insert a new change into the charprops changes vector at index.  Objects
+   at and beyond INDEX are shifted right to make room."
+  (vector-push-extend nil changes)
+  (replace changes changes :start1 (1+ index) :start2 index)
+  (setf (aref changes index) new))
+
+(defun delete-charprops-change (changes index)
+  "Delete the change at index from the charprops changes vector.  Objects
+   beyond INDEX are shifted left to fill the empty spot."
+  (unless (= (fill-pointer changes) index)
+    (replace changes changes :start1 index :start2 (1+ index)))
+  (decf (fill-pointer changes)))
+
+(defun push-charprops-change (change changes)
+  (vector-push-extend change changes))
+
+;;; Return the index of the charprops change that applies to
+;;; charpos, or else NIL if the charpos has (implicit)
+;;; default properties.
+(defun charprops-change-index-for-position (changes charpos)
+  (do ((i 0 (1+ i))
+       (i-1 nil i)
+       (change nil))
+      ((= i (length changes)) i-1)
+    (setq change (aref changes i))
+    (when (< charpos (charprops-change-index change))
+      (return i-1))))
+
+;;; Real programmers can write assembly in any language.
+(defun line-charprops-for-position (line charpos)
+  "Return, as multiple values, the plist, and start position and end
+   position over which the plist applies."
+  (unless (and (>= charpos 0)
+               (<= charpos (line-length line)))
+    (error "index ~d out of range" charpos))
+  (let* ((changes (line-charprops-changes line))
+         (change nil)
+         (prior-change nil)
+         (start-pos 0)
+         (end-pos 0))
+    (dotimes (i (length changes) (values (and change
+                                              (charprops-change-plist change))
+                                         start-pos (1+ (line-length line))))
+      (setq prior-change change)
+      (setq change (aref changes i))
+      (setq end-pos (charprops-change-index change))
+      (when (< charpos (charprops-change-index change))
+        (return (values (and prior-change (charprops-change-plist prior-change))
+                        start-pos end-pos)))
+      (setq start-pos (charprops-change-index change)))))
+
+(defun squeeze-out-superseded-changes (changes idx)
+  (let* ((base-change (aref changes idx)))
+    (do* ((i (1+ idx) (1+ i))
+          (change nil)
+          (n 0))
+         ((= i (length changes))
+          ;;(format t "~&start1 = ~d start2 = ~d" (1+ idx) (+ n 1 idx))
+          (replace changes changes :start1 (1+ idx) :start2 (+ n 1 idx))
+          (decf (fill-pointer changes) n)
+          changes)
+      (setq change (aref changes i))
+      (when (<= (charprops-change-index change)
+                (charprops-change-index base-change))
+        (setf (charprops-change-plist base-change) (charprops-change-plist change))
+        (incf n)
+        (setf (aref changes i) nil)))))
+
+;;; Set the charprops of the specified LINE between positions START and
+;;; END.  If END is NIL, that means the end of the line.  Note that this
+;;; doesn't merge in properties: it replaces whatever is there.
+(defun set-line-charprops (line charprops &key (start 0) end &aux plist)
+  (setq plist (charprops-as-plist charprops))
+  (when (and end (= end (line-length line)))
+    (setq end nil))
+  (when (and (null plist) (= start 0) (null end))
+    (setf (line-charprops-changes line) nil)
+    (return-from set-line-charprops))
+  (let* ((changes (line-charprops-changes line))
+         (new-change (make-charprops-change start plist)))
+    (if (null changes)
+      (let ((new-changes (make-array 2 :adjustable t :fill-pointer 0)))
+        (vector-push new-change new-changes)
+        (when end
+          (vector-push (make-charprops-change end nil) new-changes))
+        (setf (line-charprops-changes line) new-changes)
+        (line-charprops-changes line))
+      ;; Put the new charprops change into the right place in the charprops
+      ;; changes vector, making note of its position.
+      (do* ((i 0 (1+ i))
+            (change nil)
+            (prior-change nil change))
+           ((= i (length changes))
+            (insert-charprops-change changes i new-change)
+            (when end
+              (let ((prior-plist (and prior-change
+                                      (charprops-change-plist prior-change))))
+                (insert-charprops-change changes (1+ i)
+                                         (make-charprops-change end prior-plist)))))
+        (setq change (aref changes i))
+        (when (<= start (charprops-change-index change))
+          (insert-charprops-change changes i new-change)
+          (incf i)
+          (if (null end)
+            (setf (fill-pointer changes) i)
+            (let ((prior-plist (and prior-change
+                                    (charprops-change-plist prior-change))))
+              (insert-charprops-change changes i (make-charprops-change end prior-plist))
+              (squeeze-out-superseded-changes changes i)))
+          (return))))))
+
+(defun add-line-charprop-value (line name value &key (start 0) end)
+  (let* ((changes (line-charprops-changes line))
+         (start-idx (charprops-change-index-for-position changes start))
+         (end-idx (charprops-change-index-for-position changes
+                                                       (or end
+                                                           (setq end (line-length line))))))
+    (cond ((or (null changes)
+               (and (null start-idx) (null end-idx)))
+           ;; Either the line has no existing charprops, or we're within the
+           ;; implicit run of default properties at the start of the line.
+           ;; Just set the charprops over the relevant range and return.
+           (set-line-charprops line (list name value) :start start :end end)
+           (return-from add-line-charprop-value changes))
+          ((null start-idx)
+           ;; The starting position is in the implicit run of default
+           ;; properties at the start of the line.
+           (let ((new-change (make-charprops-change start (list name value))))
+             (insert-charprops-change changes 0 new-change)
+             (setq start-idx 0)
+             (incf end-idx))
+           (let ((end-change (aref changes end-idx)))
+             (unless (= (charprops-change-index end-change) end)
+               (let ((new-change (copy-charprops-change end-change)))
+                 (setf (charprops-change-index new-change) end)
+                 (insert-charprops-change changes (1+ end-idx) new-change)
+                 (incf end-idx)))))
+          ((and start-idx end-idx)
+           (let ((start-change (aref changes start-idx)))
+             (unless (= (charprops-change-index start-change) start)
+               (let ((new-change (copy-charprops-change start-change)))
+                 (setf (charprops-change-index new-change) start)
+                 (insert-charprops-change  changes (1+ start-idx) new-change)
+                 (incf start-idx)
+                 (incf end-idx))))
+           (let ((end-change (aref changes end-idx))
+                 (next-end-idx (charprops-change-index-for-position changes (1+ end))))
+             ;; If end-idx and next-end-idx differ, then the end
+             ;; position comes at the very end of a run, and we don't
+             ;; need to split.  We also don't need to split if end is
+             ;; at the very end of the line.
+             (when (and (= end-idx next-end-idx)
+                        (not (= end (line-length line))))
+               (let ((new-change (copy-charprops-change end-change)))
+                 (setf (charprops-change-index new-change) end)
+                 (insert-charprops-change changes (1+ end-idx) new-change)))))
+          (t (error "how did we get here?")))
+    (loop for i from start-idx to end-idx
+      as change = (aref changes i)
+      do (if (null value)
+           (remf (charprops-change-plist change) name)
+           (setf (getf (charprops-change-plist change) name) value)))))
+
+(defun set-region-charprops (region charprops)
+  (let* ((start (region-start region))
+         (end (region-end region))
+         (first-line (mark-line start))
+         (last-line (mark-line end)))
+    (cond ((eq first-line last-line)
+           (set-line-charprops first-line charprops :start (mark-charpos start)
+                               :end (mark-charpos end))
+	   (coalesce-line-charprops first-line))
+          (t
+           (set-line-charprops first-line charprops :start (mark-charpos start))
+           (do* ((line (line-next first-line) (line-next line)))
+                ((eq line last-line)
+                 (set-line-charprops line charprops :end (mark-charpos end)))
+             (set-line-charprops line charprops))))))
+
+;;; Returns two values: fresh charprops change vectors for the line's characters
+;;; before and after charpos.
+(defun split-line-charprops (line charpos)
+  (let* ((changes (line-charprops-changes line))
+         (nchanges (length changes)))
+    (when (> nchanges 0)
+      (let ((left (make-array 2 :adjustable t :fill-pointer 0))
+            (right (make-array 2 :adjustable t :fill-pointer 0))
+            (pivot nil)
+            (prior-change nil))
+        (do* ((i 0 (1+ i))
+              (change nil))
+             ((or pivot
+                  (= i nchanges))
+              (if (null pivot)
+                ;; The last change extends to the end of line, so that will be the
+                ;; charprops in effect at the beginning of the new line.
+                (if (null (charprops-change-plist change))
+                  (setq right nil)
+                  (let* ((c (copy-charprops-change change)))
+                    (setf (charprops-change-index c) 0)
+                    (push-charprops-change c right)))
+                ;; Some charprops changes remain.  First, split the prior change
+                ;; if necessary, and then pick up the rest of the shifts.
+                (progn
+                  (when (and prior-change
+                             (> charpos (charprops-change-index prior-change)))
+                    ;; need to split change
+                    (let* ((c (copy-charprops-change prior-change)))
+                      (setf (charprops-change-index c) 0)
+                      (push-charprops-change c right)))
+                  (loop for i from pivot below nchanges
+                    as change = (aref changes i)
+                    do (decf (charprops-change-index change) charpos)
+                    (push-charprops-change (aref changes i) right))))
+              (values left right pivot))
+          (setq change (aref changes i))
+          (if (< (charprops-change-index change) charpos)
+            (progn
+              (push-charprops-change change left)
+              (setq prior-change change))
+            (setq pivot i)))))))
+
+(defun append-line-charprops (line changes)
+  (let* ((left (line-charprops-changes line))
+         (len (line-length line))
+         (right changes))
+    (cond ((and left right)
+           (loop for c across right
+                 for new-change = (copy-charprops-change c)
+                 do (incf (charprops-change-index new-change) len)
+                    (push-charprops-change new-change left)))
+          ((and (null left) right)
+           (setq left (copy-charprops-changes right))
+           (adjust-charprops-change-indexes left len)
+           (setf (line-charprops-changes line) left))
+          ((and left (null right))
+           (push-charprops-change (make-charprops-change len nil) left)))
+    left))
+
+;;; Append the charprops-changes from line2 onto line1, modifying their
+;;; indexes appropriately.
+(defun join-line-charprops (line1 line2)
+  (let* ((left (line-charprops-changes line1))
+         (lidx (1- (length left)))
+         (right (line-charprops-changes line2))
+         (ridx 0)
+         (line1-len (line-length line1)))
+    (cond ((and left right)
+           ;; If the last change on line1 and the first change on line2
+           ;; represent the same properties, then omit line2's first
+           ;; change.
+           (let* ((lchange (aref left lidx))
+                  (lprops (charprops-change-plist lchange))
+                  (rchange (aref right ridx))
+                  (rprops (charprops-change-plist rchange)))
+             (if (> 0 (charprops-change-index rchange))
+               ;; There is an implicit run of default charprops at the
+               ;; start of the line.
+               (unless (null lprops)
+                 ;; The last change on line1 represents some non-default
+                 ;; set of charprops, so insert an explicit change to the
+                 ;; default set before copying over the rest.
+                 (push-charprops-change (make-charprops-change (1+ line1-len) nil)
+                                        left))
+               (when (charprops-equal lprops rprops)
+                 (incf ridx)))
+             (do* ((i ridx (1+ i))
+                   (change nil))
+                  ((= i (length right)))
+               (setq change (aref right i))
+               (incf (charprops-change-index change) (1+ line1-len))
+               (push-charprops-change change left))))
+          ((and (null left) right)
+           (adjust-charprops-change-indexes right line1-len)
+           (setf (line-charprops-changes line1) right))
+          ((and left (null right))
+           (let* ((lchange (aref left lidx)))
+             (unless (null (charprops-change-plist lchange))
+               (push-charprops-change (make-charprops-change (1+ line1-len) nil)
+                                   left))))
+          ;; otherwise both nil, so don't need to do anything.
+          )
+    left))
+
+(defun copy-line-charprops (line &key (start 0) end)
+  "Return a freshly-consed vector of charprops changes that applies to the
+   characters in the interval [start, end) on the specified line.  If the
+   charprops in between start and end are the default charprops, return
+   NIL."
+  (let ((changes (line-charprops-changes line)))
+    ;; some early-out special cases
+    (cond ((null changes)
+           (return-from copy-line-charprops))
+          ((and (= start 0) (null end))
+           (return-from copy-line-charprops (copy-charprops-changes changes))))
+    (unless end
+      (setq end (line-length line)))
+    (let* ((new-changes (make-empty-charprops-changes))
+           (start-idx (charprops-change-index-for-position changes start))
+           (end-idx (charprops-change-index-for-position changes (1- end))))
+      (if (eql start-idx end-idx)
+        (if (null start-idx)
+          (setq new-changes nil)
+          (let* ((change (aref changes start-idx))
+                 (plist (charprops-change-plist change)))
+            (if (null plist)
+              (setq new-changes nil)
+              (push-charprops-change (make-charprops-change start plist)
+                                     new-changes))))
+        (do ((i (or start-idx 0) (1+ i)))
+            ((> i end-idx))
+          (let* ((change (aref changes i))
+                 (index (charprops-change-index change))
+                 (plist (charprops-change-plist change)))
+          (push-charprops-change (make-charprops-change
+                                  (max 0 (- index start)) plist)
+                                 new-changes))))
+      new-changes)))
+
+(defun delete-line-charprops (line &key (start 0) end)
+  (let ((changes (line-charprops-changes line)))
+    ;; some early-out special cases
+    (cond ((null changes)
+           (return-from delete-line-charprops))
+          ((and (= start 0) (null end))
+           (setf (line-charprops-changes line) nil)
+           (return-from delete-line-charprops)))
+    (unless end
+      (setq end (line-length line)))
+    (assert (<= start end) (start end))
+    (let* ((start-idx (charprops-change-index-for-position changes start))
+           (end-idx (charprops-change-index-for-position changes (1- end))))
+      (cond ((null start-idx)
+             (if (null end-idx)
+               (adjust-charprops-change-indexes changes (- start end) :start 0)
+               (progn
+                 ;; delete changes before end-idx
+                 (replace changes changes :start1 0 :start2 end-idx)
+                 (decf (fill-pointer changes) end-idx)
+                 (setf (charprops-change-index (aref changes 0)) start)
+                 ;; move back start of subsequent changes, if there are any
+                 (when (> (length changes) 1)
+                   (adjust-charprops-change-indexes changes (- start end)
+                                                    :start 1)
+                   ;; if the change is now zero-length, remove it
+                   (when (= (charprops-change-index (aref changes 0))
+                            (charprops-change-index (aref changes 1)))
+                     (delete-charprops-change changes 0))))))
+            ((eql start-idx end-idx)
+             ;; The deletion takes place within the scope of a single
+             ;; charprops run.
+             ;; Move back start of subsequent changes, if there are any
+             (when (> (length changes) (1+ start-idx))
+               (adjust-charprops-change-indexes changes (- start end)
+                                                :start (1+ start-idx))
+               ;; if the change is now zero-length, remove it
+               (when (= (charprops-change-index (aref changes start-idx))
+                        (charprops-change-index (aref changes (1+ start-idx))))
+                 (delete-charprops-change changes start-idx))))
+            (t
+             ;; Remove changes between start-idx and and end-idx.
+             (replace changes changes :start1 (1+ start-idx)
+                      :start2 end-idx)
+             (decf (fill-pointer changes) (- end-idx (1+ start-idx)))
+             (setf (charprops-change-index (aref changes (1+ start-idx))) start)
+             (when (> (length changes) (1+ start-idx))
+               (adjust-charprops-change-indexes changes (- start end)
+                                                :start (+ 2 start-idx))
+               ;; if first change is now zero-length, remove it
+               (when (= (charprops-change-index (aref changes start-idx))
+                        (charprops-change-index (aref changes (1+ start-idx))))
+                 (delete-charprops-change changes start-idx))))))
+    (coalesce-line-charprops line)))
+
+;;; Coalesce adjacent changes with CHARPROP-EQUAL plists.
+;;; Maybe make this remove zero-length changes, too?
+(defun coalesce-line-charprops (line)
+  (let ((changes (line-charprops-changes line)))
+    (do* ((i 0 (1+ i))
+          (change nil))
+         ((>= i (length changes)))
+      (setq change (aref changes i))
+      (loop with j = (1+ i)
+        while (and (< j (length changes))
+                   (charprops-equal (charprops-change-plist change)
+                                    (charprops-change-plist (aref changes j))))
+        do (delete-charprops-change changes j)))
+    ;; Elide any changes with NIL plists at the start of the line.
+    (loop
+      while (and (> (length changes) 0)
+                 (null (charprops-change-plist (aref changes 0))))
+      do (delete-charprops-change changes 0))
+    (when (zerop (length changes))
+      (setf (line-charprops-changes line) nil)))
+  (line-charprops-changes line))
+      
+(defun adjust-charprops-change-indexes (changes delta &key (start 0))
+  (do* ((i start (1+ i))
+        (change nil))
+       ((>= i (length changes))
+        changes)
+    (setq change (aref changes i))
+    (incf (charprops-change-index change) delta)))
+
+;;; Add delta to the starting index of all charprops changes after the one
+;;; containing start.
+(defun adjust-line-charprops (line delta &key (start 0))
+  (let* ((changes (line-charprops-changes line))
+         (start-idx (charprops-change-index-for-position changes start)))
+    (adjust-charprops-change-indexes changes delta :start (if start-idx
+                                                            (1+ start-idx)
+                                                            0))))
+
+(defun apply-line-charprops (line changes start-pos end-pos)
+  (cond ((null changes)
+         (set-line-charprops line nil :start start-pos :end end-pos))
+        (t
+         (setq changes (copy-charprops-changes changes))
+         (do* ((i 0 (1+ i))
+               (change nil))
+              ((= i (length changes)))
+           (setq change (aref changes i))
+           (set-line-charprops line (charprops-change-plist change)
+                               :start (+ (charprops-change-index change) start-pos)
+                               :end end-pos))
+         (coalesce-line-charprops line)))
+  (line-charprops-changes line))
+
+(defvar *display-properties*
+  '(:font-name
+    :font-size
+    :font-weight
+    :font-width
+    :font-slant
+    :font-underline
+    :font-color
+    :background-color))
+
+;;; Setting and accessing charprops
+
+(defun next-charprop-value (mark name &key view)
+  (let ((props (next-charprops mark :view view)))
+    (getf props name)))
+
+(defun previous-charprop-value (mark name &key view)
+  (let ((props (previous-charprops mark :view view)))
+    (getf props name)))
+
+(defun set-charprop-value (mark name value &key (count 1 count-supplied-p) end view)
+  (declare (ignore view))
+  (when (and count-supplied-p end)
+    (error "Cannot specify both :COUNT and :END"))
+  (with-mark ((start-mark mark)
+              (end-mark mark))
+    (if end
+      (move-mark end-mark end)
+      (character-offset end-mark count))
+    (let* ((start-line (mark-line start-mark))
+           (start-charpos (mark-charpos start-mark))
+           (end-line (mark-line end-mark))
+           (end-charpos (mark-charpos end-mark)))
+      (cond ((eq start-line end-line)
+	     (add-line-charprop-value start-line name value
+				      :start start-charpos
+				      :end end-charpos))
+	    (t
+	     (do* ((line start-line (line-next line))
+		   (start start-charpos 0))
+		  ((eq line end-line)
+		   (add-line-charprop-value end-line name value
+					    :start 0
+					    :end end-charpos))
+	       (add-line-charprop-value line name value :start start))))
+      (let ((n (count-characters (region start-mark end-mark)))
+	    (buffer (line-%buffer start-line)))
+	(hemlock-ext:buffer-note-modification buffer mark n)))))
+
+(defun find-line-charprop-value (line name value &key (start 0) end)
+  (unless end
+    (setq end (line-length line)))
+  (let* ((changes (line-charprops-changes line))
+	 (start-idx (or (charprops-change-index-for-position changes start) 0))
+	 (end-idx (or (charprops-change-index-for-position changes end) 0)))
+    (when changes
+      (loop for i from start-idx to end-idx
+	 as change = (aref changes i)
+	 as plist = (charprops-change-plist change)
+	 as found-value = (getf plist name)
+	 do (when (and found-value
+		       (charprop-equal found-value value))
+	      (return (max start (charprops-change-index change))))))))
+
+(defun find-charprop-value (mark name value &key (count nil count-supplied-p)
+			    end view from-end)
+  (declare (ignore from-end view))
+  (with-mark ((start-mark mark)
+	      (end-mark mark))
+    (when (and count-supplied-p end)
+      (error "Cannot specify both :COUNT and :END"))
+    (let* ((buffer (line-buffer (mark-line mark))))
+      (unless (bufferp buffer)
+	(error "text must be in a buffer"))
+      (if count-supplied-p
+	(character-offset end-mark count)
+	(move-mark end-mark (buffer-end-mark buffer)))
+      (let* ((start-line (mark-line start-mark))
+	     (start-charpos (mark-charpos start-mark))
+	     (end-line (mark-line end-mark))
+	     (end-charpos (mark-charpos end-mark)))
+	(do* ((line start-line (line-next line))
+	      (charpos start-charpos 0))
+             ((eq line end-line)
+              (let ((pos (find-line-charprop-value end-line name value
+                                                   :start charpos
+                                                   :end end-charpos)))
+                (when pos
+                  (move-to-position mark pos end-line)
+                  mark)))
+	  (let ((pos (find-line-charprop-value line name value :start charpos)))
+	    (when pos
+	      (move-to-position mark pos line)
+	      (return mark))))))))
+
+(defun filter-match (filter name)
+  (cond ((functionp filter)
+         (funcall filter name))
+        ((eq filter :display)
+         (member name *display-properties* :test #'eq))
+        ((typep filter 'sequence)
+         (member name filter))
+        (t
+         name)))
+
+(defun filter-charprops (filter charprops)
+  (if (eq filter t)
+    charprops
+    (typecase charprops
+      ((satisfies ccl::plistp) (loop for (k v) on charprops by #'cddr
+                                 when (filter-match filter k)
+                                 collect k and collect v))
+      (hash-table (loop for k being the hash-keys of charprops using (hash-value v)
+                    when (filter-match filter k)
+                    collect k and collect v)))))
+
+(defun next-charprops (mark &key view (filter t))
+  "Return the properties of the character after MARK."
+  (declare (ignore view))
+  (when (next-character mark)
+    (let* ((props (line-charprops-for-position (mark-line mark) (mark-charpos mark))))
+      (filter-charprops filter props))))
+
+(defun previous-charprops (mark &key view (filter t))
+  "Return the properties of the character before MARK."
+  (with-mark ((m mark))
+    (when (mark-before m)
+      (next-charprops m :view view :filter filter))))
+
+(defun set-charprops (mark charprops &key (count 1 count-supplied-p)
+                           (end nil end-supplied-p) (filter (charprops-names charprops)))
+  (when (and count-supplied-p end-supplied-p)
+    (error "Only one of count or end can be supplied."))
+  (setq charprops (charprops-as-plist charprops :filter filter))
+  (with-mark ((start-mark mark)
+              (end-mark mark))
+    (if end
+      (move-mark end-mark end)
+      (character-offset end-mark count))
+    ;; lame.
+    (loop for (k v) on charprops by #'cddr
+       do (set-charprop-value start-mark k v :end end-mark))))
+
+;;; Return a list of charprops-change vectors that correspond to the lines
+;;; of text in the region defined by the paramaters.
+(defun charprops-in-region (region-or-mark &key (count 1 count-supplied-p)
+                                           end filter)
+  (declare (ignore filter))
+  (when (and count-supplied-p end)
+    (error "Only one of count or end can be supplied."))
+  (let (region result)
+    (etypecase region-or-mark
+      (mark (with-mark ((m region-or-mark))
+	      (when end
+		(setq count (- end (mark-absolute-position m))))
+	      (character-offset m count)
+	      (setq region (region region-or-mark m))))
+      (region (when (or count-supplied-p end)
+                (error "Can't specify count or end when passing in a region."))
+              (setq region region-or-mark)))
+    (let* ((start (region-start region))
+           (first-line (mark-line start))
+           (first-charpos (mark-charpos start))
+           (end (region-end region))
+           (last-line (mark-line end))
+           (last-charpos (mark-charpos end)))
+      (cond
+       ((eq first-line last-line)
+        (list (copy-line-charprops first-line :start first-charpos)))
+       (t
+        (push (copy-line-charprops first-line :start first-charpos) result)
+        (do* ((line (line-next first-line) (line-next line))
+              (m (copy-mark start) (line-start m line)))
+             ((eq line last-line)
+              (push (copy-line-charprops last-line :end last-charpos) result)
+              (nreverse result))
+          (push (copy-line-charprops line) result)))))))
+
+(defun apply-charprops (mark charprops-range &key filter from-end)
+  (declare (ignore from-end filter charprops-range mark)))
+
+#|
+  (let* ((start-line (mark-line mark))
+         (start-charpos (mark-charpos))
+         (nlines (length charprops-range))
+         (first-changes (pop charprops-range)))
+
+    ;; do possibly-partial first line
+    (let ((left (split-line-charprops start-line start-charpos)))
+      (setf (line-charprops start-line) left)
+      (append-line-charprops start-line first-changes))
+    ;; do some number of whole lines
+    (do* ((line (line-next start-line) (line-next line))
+          (previous-line start-line (line-next previous-line))
+          (cc-list charprops-range (cdr charprops-range))
+          (changes (car cc-list) (car cc-list)))
+         ((or (null line) (endp cc-list)))
+      (setf (line-charprops-changes line) (copy-charprops-changes changes)))
+    ;; I don't know what to do about a partial last line.  There's no
+    ;; way that I can see to know whether the last charprops change vector
+    ;; in the charprops-range list is to apply to an entire line or to end
+    ;; at a particular charpos on that line.  Maybe that information needs
+    ;; to be stored as part of the charprops-range list.  For example, if the
+    ;; element of the charprops-range list is a non-null list, the list could
+    ;; be (charprops-change-vector start-charpos end-charpos).
+
+    (multiple-value-bind (left right)
+                         (split-line-charprops last-line last-charpos)
+      (setf (line-charprops last-line) last-changes)
+      (append-line-charprops last-line right)))
+|#
+
+(defun find-charprops (mark charprops &key count end view filter from-end)
+  (declare (ignore from-end filter view end count charprops mark)))
+
+(defun find-charprops-change (mark &key count end view filter from-end)
+  (declare (ignore from-end filter view end count))
+  (let* ((line (mark-line mark))
+         (charpos (mark-charpos mark))
+         (changes (line-charprops-changes line))
+         (idx (charprops-change-index-for-position changes charpos)))
+    (loop
+      (incf idx)
+      (if (= idx (length changes))
+        (setf line (line-next line)
+              charpos 0
+              changes (line-charprops-changes line)
+              idx (charprops-change-index-for-position changes charpos))
+        (return (move-mark mark (charprops-change-index (aref changes idx))))))))
+
+(defun print-line-charprops (line &key (start 0) (end (hi:line-length line)))
+  (let* ((string (hi:line-string line))
+         (charprops-changes (hi::line-charprops-changes line)))
+    (let ((index start)
+          (plist nil)
+          (x 0))
+      (loop for change across charprops-changes
+        do (let* ((next-index (charprops-change-index change))
+                  (next-plist (charprops-change-plist change))
+                  (end (min end next-index)))
+             (when (and (>= index start)
+                        (< index end))
+               (format t "~& ~d: [~d, ~d) ~s: ~s" x index end
+                       (subseq string index end) plist))
+             (setq index next-index)
+             (setq plist next-plist)
+             (incf x)))
+      ;; final part of line
+      (format t "~& ~d: [~d, ~d) ~s: ~s" x index end
+              (subseq string index end) plist))))
+
+(defun copy-charprops (charprops)
+  (copy-list charprops))
+
+
+;;; Utility functions
+
+(defun charprop-equal (value1 value2)
+  (cond ((and (stringp value1) (stringp value2))
+         (string= value1 value2))
+        ((and (numberp value1) (numberp value2))
+         (= value1 value2))
+        (t
+         (eql value1 value2))))
+
+(defun charprops-get (charprops name &key (filter t))
+  (when (and name (filter-match filter name))
+    (etypecase charprops
+      ((satisfies ccl::plistp) (getf charprops name))
+      (hash-table (gethash name charprops)))))
+
+(defun charprops-set (charprops name value)
+  (etypecase charprops
+    ((satisfies ccl::plistp) (setf (getf charprops name) value))
+    (hash-table (setf (gethash name charprops) value)))
+  charprops)
+
+(defun same-sets (s1 s2 &key (test #'eql))
+  (and (subsetp s1 s2 :test test)
+       (subsetp s2 s1 :test test)))
+
+;; I wonder if this will be a hot spot...
+(defun charprops-equal (charprops1 charprops2 &key (filter t))
+  (setq charprops1 (charprops-as-plist charprops1 :filter filter)
+        charprops2 (charprops-as-plist charprops2 :filter filter))
+  (let (keys1 values1 keys2 values2)
+    (loop for (k1 v1) on charprops1 by #'cddr
+      do (push k1 keys1)
+         (push v1 values1))
+    (loop for (k2 v2) on charprops2 by #'cddr
+      do (push k2 keys2)
+         (push v2 values2))
+    (and (same-sets keys1 keys2)
+         (same-sets values1 values2 :test #'charprop-equal))))
+
+(defun charprops-as-plist (charprops &key (filter t))
+  (etypecase charprops
+    ((satisfies ccl::plistp) (if (eq filter t)
+                               charprops
+                               (loop for (k v) on charprops by #'cddr
+                                 when (filter-match filter k)
+                                 collect k and collect v)))
+    (hash-table (loop for k being the hash-keys of charprops using (hash-value v)
+                  when (filter-match filter k)
+                  collect k and collect v))))
+
+(defun charprops-as-hash (charprops &key (filter t))
+  (etypecase charprops
+    ((satisfies ccl::plistp) (let ((hash (make-hash-table)))
+                               (loop for (k v) on charprops by #'cddr
+                                 when (filter-match filter k)
+                                 do (setf (gethash k hash) v))
+                               hash))
+    (hash-table (if (eq filter t)
+                  charprops
+                  (let ((hash (make-hash-table)))
+                    (maphash #'(lambda (k v)
+                                 (when (filter-match filter k)
+                                   (setf (gethash k hash) v)))
+                             charprops))))))
+
+(defun charprops-names (charprops &key (filter t))
+  (etypecase charprops
+    ((satisfies ccl::plistp) (loop for name in charprops by #'cddr
+                               when (filter-match filter name)
+                               collect name))
+    (hash-table (loop for name being the hash-keys of charprops
+                  when (filter-match filter name)
+                  collect name))))
+
+;;; From <AppKit/NSAttributedString.h>
+(defparameter *cocoa-attributes*
+  `((:ns-font . ,#&NSFontAttributeName)
+    (:ns-paragraph-style . ,#&NSParagraphStyleAttributeName)
+    (:ns-foreground-color . ,#&NSForegroundColorAttributeName)
+    (:ns-underline-style . ,#&NSUnderlineStyleAttributeName)
+    (:ns-superscript . ,#&NSSuperscriptAttributeName)
+    (:ns-background-color . ,#&NSBackgroundColorAttributeName)
+    (:ns-attachment . ,#&NSAttachmentAttributeName)
+    (:ns-ligature . ,#&NSLigatureAttributeName)
+    (:ns-baseline-offset . ,#&NSBaselineOffsetAttributeName)
+    (:ns-kern . ,#&NSKernAttributeName)
+    (:ns-link . ,#&NSLinkAttributeName)
+    (:ns-stroke-width . ,#&NSStrokeWidthAttributeName)
+    (:ns-stroke-color . ,#&NSStrokeColorAttributeName)
+    (:ns-underline-color . ,#&NSUnderlineColorAttributeName)
+    (:ns-strikethrough-style . ,#&NSStrikethroughStyleAttributeName)
+    (:ns-strikethrough-color . ,#&NSStrikethroughColorAttributeName)
+    (:ns-shadow . ,#&NSShadowAttributeName)
+    (:ns-obliqueness . ,#&NSObliquenessAttributeName)
+    (:ns-expansion . ,#&NSExpansionAttributeName)
+    (:ns-cursor . ,#&NSCursorAttributeName)
+    (:ns-tool-tip . ,#&NSToolTipAttributeName)
+    #-cocotron
+    (:ns-character-shape . ,#&NSCharacterShapeAttributeName)
+    #-cocotron
+    (:ns-glyph-info . ,#&NSGlyphInfoAttributeName)
+    ;;(:ns-marked-clause-segment . #&NSMarkedClauseSegmentAttributeName)
+    ;;(:ns-spelling-state . #&NSSpellingStateAttributeName)
+    ))
+
Index: /branches/new-random/cocoa-ide/hemlock/src/cocoa-hemlock.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/cocoa-hemlock.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/cocoa-hemlock.lisp	(revision 13309)
@@ -0,0 +1,86 @@
+;;; -*- Mode: Lisp; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; Hemlock was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+
+(in-package :hemlock-internals)
+
+(defun add-buffer-font-region (buffer region)
+  (when (typep buffer 'buffer)
+    (let* ((header (buffer-font-regions buffer))
+           (node (make-font-region-node region)))
+      (ccl::append-dll-node node  header)
+      (setf (font-region-node region) node)
+      region)))
+
+(defun remove-font-region (region)
+  (ccl::remove-dll-node (font-region-node region)))
+
+(defun previous-font-region (region)
+  (let* ((prev-node (ccl::dll-node-pred (font-region-node region))))
+    (if (typep prev-node 'font-region-node)
+      (font-region-node-region prev-node))))
+
+(defun next-font-region (region)
+  (let* ((next-node (ccl::dll-node-succ (font-region-node region))))
+    (if (typep next-node 'font-region-node)
+      (font-region-node-region next-node))))
+
+;;; Make the specified font region "active", if it's non-nil and not
+;;; already active.   A font region is "active" if it and all of its
+;;; successors have "end" marks that're left-inserting, and all of its
+;;; predecessors have "end" marks that're right-inserting.
+;;; It's assumed that when this is called, no other font region is
+;;; active in the buffer.
+
+(defun activate-buffer-font-region (buffer region)
+  (let* ((current (buffer-active-font-region buffer)))
+    (unless (eq current region)
+      (deactivate-buffer-font-region buffer current)
+      (when region
+        (setf (mark-%kind (region-end region)) :left-inserting
+              (mark-%kind (region-start region)) :right-inserting)
+        (do* ((r (next-font-region region) (next-font-region r)))
+             ((null r)
+              current)
+          (setf (mark-%kind (region-end r)) :left-inserting
+                (mark-%kind (region-start r)) :left-inserting)))
+      (setf (buffer-active-font-region buffer) region)
+      current)))
+
+(defun deactivate-buffer-font-region (buffer region)
+  (when (and region (eq (buffer-active-font-region buffer) region))
+    (do* ((r region (next-font-region r)))
+         ((null r) (setf (buffer-active-font-region buffer) nil))
+      (setf (mark-%kind (region-end r)) :right-inserting
+            (mark-%kind (region-start r)) :right-inserting))))
+
+
+(defmacro with-active-font-region ((buffer region) &body body)
+  (let* ((b (gensym))
+         (old (gensym)))
+    `(let* ((,b ,buffer)
+            (,old (activate-buffer-font-region ,b ,region)))
+      (unwind-protect
+           (progn ,@body)
+        (activate-buffer-font-region ,b ,old)))))
+
+    
+(defun show-buffer-font-regions (buffer)
+  (ccl::do-dll-nodes (node (buffer-font-regions buffer))
+    (let* ((r (font-region-node-region node))
+           (start (region-start r))
+           (end (region-end r)))
+      (format t "~& style ~d ~d [~s]/ ~d [~s] ~a"
+              (font-mark-font start)
+              (mark-absolute-position start)
+              (mark-%kind start)
+              (mark-absolute-position end)
+              (mark-%kind end)
+              (eq r (buffer-active-font-region buffer))))))
+
+;;; Clipboard
+(defun region-to-clipboard (region)
+  (hemlock-ext:string-to-clipboard (region-to-string region)))
+
Index: /branches/new-random/cocoa-ide/hemlock/src/command.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/command.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/command.lisp	(revision 13309)
@@ -0,0 +1,570 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains the definitions for the basic Hemlock commands.
+;;;
+
+(in-package :hemlock)
+
+;;; utility for collapsing selections from movement commands
+;;; returns a true value if a selection was collapsed, false otherwise
+
+(defun collapse-if-selection (&key (direction :forward))
+  (assert (memq direction '(:backward :forward))()
+          "collapse-if-selection requires a :direction argument equal to either :backward or :forward")
+  (let ((b (current-buffer)))
+    (if (hi::%buffer-current-region-p b)
+        (let* ((point (buffer-point b))
+               (region (current-region)))
+          ;; Deactivate the region
+          (ecase direction
+            ((:backward) (move-mark point (region-start region)))
+            ((:forward) (move-mark point (region-end region))))
+          (setf (hi::buffer-region-active b) nil)
+          point)
+        nil)))
+
+;;; Make a mark for buffers as they're consed:
+
+(defun hcmd-new-buffer-hook-fun (buff)
+  (let ((ring (make-ring 10 #'delete-mark)))
+    (defhvar "Buffer Mark Ring" 
+      "This variable holds this buffer's mark ring."
+      :buffer buff
+      :value ring)
+    (setf (hi::buffer-%mark buff) (copy-mark (buffer-point buff) :right-inserting))))
+
+(add-hook make-buffer-hook #'hcmd-new-buffer-hook-fun)
+(dolist (buff *buffer-list*) (hcmd-new-buffer-hook-fun buff))
+
+
+
+
+
+;;;; Simple character manipulation:
+
+(defcommand "Self Insert" (p)
+  "Insert the last character typed.
+  With prefix argument insert the character that many times."
+  "Implements ``Self Insert'', calling this function is not meaningful."
+  (let ((char (last-char-typed)))
+    (unless char (editor-error "Can't insert that character."))
+    (if (and p (> p 1))
+	(insert-string
+	 (current-point-for-insertion)
+	 (make-string p :initial-element char))
+	(insert-character (current-point-for-insertion) char))))
+
+(defcommand "Quoted Insert" (p)
+  "Causes the next character typed to be inserted in the current
+   buffer, even if would normally be interpreted as an editor command."
+  (declare (ignore p))
+  (setf (hi::hemlock-view-quote-next-p hi::*current-view*) t))
+
+(defcommand "Native Quoted Insert" (p)
+  "Causes the next character typed to be processed by the native text-handling
+   facility."
+  (declare (ignore p))
+  (setf (hi::hemlock-view-quote-next-p hi::*current-view*) :native))
+
+
+(defcommand "Forward Character" (p)
+    "Move the point forward one character, collapsing the selection.
+   With prefix argument move that many characters, with negative argument
+   go backwards."
+    "Move the point of the current buffer forward p characters, collapsing the selection."
+  (or (collapse-if-selection :direction :forward)
+      (let* ((p (cond
+                  (p p)
+                  ((hi::%buffer-current-region-p hi::*current-buffer*) 0)
+                  (t 1)))
+             (point (current-point-collapsing-selection)))
+        (cond ((character-offset point p))
+              ((= p 1)
+               (editor-error "No next character."))
+              ((= p -1)
+               (editor-error "No previous character."))
+              (t
+               (if (plusp p)
+                   (buffer-end point)
+                   (buffer-start point))
+               (editor-error "Not enough characters."))))))
+
+(defcommand "Select Forward Character" (p)
+  "Move the point forward one character, extending the selection.
+   With prefix argument move that many characters, with negative argument
+   go backwards."
+  "Move the point of the current buffer forward p characters, extending the selection."
+  (let* ((p (or p 1)))
+    (if (< p 0)
+      (select-backward-character-command (- p))
+      (let* ((point (current-point-for-selection-end)))
+        (cond ((character-offset point p))
+              ((= p 1)
+               (editor-error "No next character."))
+              (t
+               (buffer-end point)
+               (editor-error "Not enough characters.")))))))
+
+(defcommand "Backward Character" (p)
+    "Move the point backward one character, collapsing the selection.
+  With prefix argument move that many characters backward."
+    "Move the point p characters backward, collapsing the selection."
+  (or (collapse-if-selection :direction :backward)
+      (forward-character-command (if p (- p) -1))))
+
+(defcommand "Select Backward Character" (p)
+  "Move the point backward one character, extending the selection.
+  With prefix argument move that many characters backward."
+  "Move the point p characters backward, extending the selection."
+  (let* ((p (or p 1)))
+    (if (< p 0)
+      (select-forward-character-command (- p))
+      (let* ((point (current-point-for-selection-start)))
+        (cond ((character-offset point (- p)))
+              ((= p 1)
+               (editor-error "No previous character."))
+              (t
+               (buffer-start point)
+               (editor-error "Not enough characters.")))))))
+
+#|
+(defcommand "Delete Next Character" (p)
+  "Deletes the character to the right of the point.
+  With prefix argument, delete that many characters to the right
+  (or left if prefix is negative)."
+  "Deletes p characters to the right of the point."
+  (unless (delete-characters (current-point) (or p 1))
+    (buffer-end (current-point))
+    (editor-error "No next character.")))
+
+(defcommand "Delete Previous Character" (p)
+  "Deletes the character to the left of the point.
+  With prefix argument, delete that many characters to the left 
+  (or right if prefix is negative)."
+  "Deletes p characters to the left of the point."
+  (unless (delete-characters (current-point) (if p (- p) -1))
+    (editor-error "No previous character.")))
+|#
+
+(defcommand "Delete Next Character" (p)
+  "Deletes the character to the right of the point.
+   With prefix argument, delete that many characters to the right
+  (or left if prefix is negative)."
+  "Deletes p characters to the right of the point."
+  (let* ((point (current-point-for-deletion)))
+    (when point
+      (cond ((kill-characters point (or p 1)))
+	    ((and p (minusp p))
+	     (editor-error "Not enough previous characters."))
+	    (t
+	     (editor-error "Not enough next characters."))))))
+
+(defcommand "Delete Previous Character" (p)
+  "Deletes the character to the left of the point.
+   Will push characters from successive deletes on to the kill ring."
+  "Deletes the character to the left of the point.
+   Will push characters from successive deletes on to the kill ring."
+  (delete-next-character-command (- (or p 1))))
+
+(defcommand "Transpose Characters" (p)
+  "Exchanges the characters on either side of the point and moves forward
+  With prefix argument, does this that many times.  A negative prefix
+  argument causes the point to be moved backwards instead of forwards."
+  "Exchanges the characters on either side of the point and moves forward."
+  (let ((arg (or p 1))
+	(point (current-point-unless-selection)))
+    (when point
+      (dotimes (i (abs arg))
+        (when (minusp arg) (mark-before point))
+        (let ((prev (previous-character point))
+              (next (next-character point)))
+
+          (cond ((not prev) (editor-error "No previous character."))
+                ((not next) (editor-error "No next character."))
+                (t
+                 (setf (previous-character point) next)
+                 (setf (next-character point) prev))))
+        (when (plusp arg) (mark-after point))))))
+
+
+;;;; Word hacking commands:
+
+;;; WORD-OFFSET 
+;;;
+;;;    Move a mark forward/backward some words.
+;;;
+(defun word-offset (mark offset)
+  "Move Mark by Offset words."
+  (if (minusp offset)
+      (do ((cnt offset (1+ cnt)))
+	  ((zerop cnt) mark)
+	(cond
+	 ((null (reverse-find-attribute mark :word-delimiter #'zerop))
+	  (return nil))
+	 ((reverse-find-attribute mark :word-delimiter))
+	 (t
+	  (move-mark
+	   mark (buffer-start-mark (mark-buffer mark))))))
+      (do ((cnt offset (1- cnt)))
+	  ((zerop cnt) mark)
+	(cond
+	 ((null (find-attribute mark :word-delimiter #'zerop))
+	  (return nil))
+	 ((null (find-attribute mark :word-delimiter))
+	  (return nil))))))
+
+(defcommand "Forward Word" (p)
+    "Moves forward one word, collapsing the selection.
+  With prefix argument, moves the point forward over that many words."
+    "Moves the point forward p words, collapsing the selection."
+  (or (collapse-if-selection :direction :forward)
+      (let* ((point (current-point-collapsing-selection)))
+        (cond ((word-offset point (or p 1)))
+              ((and p (minusp p))
+               (buffer-start point)
+               (editor-error "No previous word."))
+              (t
+               (buffer-end point)
+               (editor-error "No next word."))))))
+
+(defcommand "Select Forward Word" (p)
+  "Moves forward one word, extending the selection.
+  With prefix argument, moves the point forward over that many words."
+  "Moves the point forward p words, extending the selection."
+  (let* ((p (or p 1)))
+    (if (< p 0)
+      (select-backward-word-command (- p))
+      (let* ((point (current-point-for-selection-end)))
+        (cond ((word-offset point p))
+              (t
+               (buffer-end point)
+               (editor-error "No next word.")))))))
+
+(defcommand "Backward Word" (p)
+  "Moves forward backward word.
+  With prefix argument, moves the point back over that many words."
+  "Moves the point backward p words."
+  (or (collapse-if-selection :direction :backward)
+   (forward-word-command (- (or p 1)))))
+
+(defcommand "Select Backward Word" (p)
+  "Moves forward backward word, extending the selection.
+  With prefix argument, moves the point back over that many words."
+  "Moves the point backward p words, extending the selection."
+  (let* ((p (or p 1)))
+    (if (< p 0)
+      (select-forward-word-command (- p))
+      (let* ((point (current-point-for-selection-start)))
+        (cond ((word-offset point (- p)))
+              (t
+               (buffer-start point)
+               (editor-error "No previous word.")))))))
+
+
+
+
+;;;; Moving around:
+
+(defun set-target-column (mark)
+  (if (eq (last-command-type) :line-motion)
+    (hi::hemlock-target-column hi::*current-view*)
+    (setf (hi::hemlock-target-column hi::*current-view*) (mark-column mark))))
+
+(defhvar "Next Line Inserts Newlines"
+    "If true, causes the \"Next Line\" command to insert newlines when
+     moving past the end of the buffer."
+  :value nil)
+
+
+(defcommand "Next Line" (p)
+  "Moves the point to the next line, collapsing the selection.
+   With prefix argument, moves the point that many lines down (or up if
+   the prefix is negative)."
+  "Moves the down p lines, collapsing the selection."
+  (let* ((point (current-point-collapsing-selection))
+	 (target (set-target-column point))
+         (count (or p 1)))
+    (unless (line-offset point count)
+      (cond ((and (not p) (value next-line-inserts-newlines))
+             (when (same-line-p point (buffer-end-mark (current-buffer)))
+               (line-end point))
+             (insert-character point #\newline))
+            ((minusp count)
+             (buffer-start point)
+             (editor-error "No previous line."))
+            (t
+             (buffer-end point)
+             (editor-error "No next line."))))
+    (unless (move-to-position point target) (line-end point))
+    (setf (last-command-type) :line-motion)))
+
+(defcommand "Select Next Line" (p)
+  "Moves the point to the next line, extending the selection.
+   With prefix argument, moves the point that many lines down (or up if
+   the prefix is negative)."
+  "Moves the down p lines, extending the selection."
+  (let* ((p (or p 1)))
+    (if (< p 0)
+      (select-previous-line-command (- p))
+      (let* ((point (current-point-for-selection-end))
+             (target (set-target-column point)))
+        (unless (line-offset point (or p 1))
+          (when (value next-line-inserts-newlines)
+            (cond ((not p)
+                   (when (same-line-p point (buffer-end-mark (current-buffer)))
+                     (line-end point))
+                   (insert-character point #\newline))
+                  (t
+                   (buffer-end point)
+                   (when p (editor-error "No next line."))))))
+        (unless (move-to-position point target) (line-end point))
+        (setf (last-command-type) :line-motion)))))
+
+
+(defcommand "Previous Line" (p)
+  "Moves the point to the previous line, collapsing the selection.
+  With prefix argument, moves the point that many lines up (or down if
+  the prefix is negative)."
+  "Moves the point up p lines, collapsing the selection."
+  (next-line-command (- (or p 1))))
+
+(defcommand "Select Previous Line" (p)
+  "Moves the point to the previous line, collapsing the selection.
+  With prefix argument, moves the point that many lines up (or down if
+  the prefix is negative)."
+  "Moves the point up p lines, collapsing the selection."
+  (let* ((p (or p 1)))
+    (if (< p 0)
+      (select-next-line-command (- p))
+      (let* ((point (current-point-for-selection-start))
+             (target (set-target-column point)))
+        (line-offset point (- p))
+        (unless (move-to-position point target) (line-end point))
+        (setf (last-command-type) :line-motion)))))
+
+(defcommand "Mark to End of Buffer" (p)
+  "Sets the current region from point to the end of the buffer."
+  "Sets the current region from point to the end of the buffer."
+  (declare (ignore p))
+  (buffer-end (push-new-buffer-mark (current-point) t)))
+
+(defcommand "Mark to Beginning of Buffer" (p)
+  "Sets the current region from the beginning of the buffer to point."
+  "Sets the current region from the beginning of the buffer to point."
+  (declare (ignore p))
+  (buffer-start (push-new-buffer-mark (current-point) t)))
+
+(defcommand "Beginning of Buffer" (p)
+  "Moves the point to the beginning of the current buffer, collapsing the selection."
+  "Moves the point to the beginning of the current buffer, collapsing the selection."
+  (declare (ignore p))
+  (let ((point (current-point-collapsing-selection)))
+    (push-new-buffer-mark point)
+    (buffer-start point)))
+
+(defcommand "End of Buffer" (p)
+  "Moves the point to the end of the current buffer."
+  "Moves the point to the end of the current buffer."
+  (declare (ignore p))
+  (let ((point (current-point-collapsing-selection)))
+    (push-new-buffer-mark point)
+    (buffer-end point)))
+
+(defcommand "Beginning of Line" (p)
+  "Moves the point to the beginning of the current line, collapsing the selection.
+  With prefix argument, moves the point to the beginning of the prefix'th
+  next line."
+  "Moves the point down p lines and then to the beginning of the line, collapsing the selection."
+  (let ((point (current-point-collapsing-selection)))
+    (unless (line-offset point (if p p 0)) (editor-error "No such line."))
+    (line-start point)))
+
+(defcommand "Select to Beginning of Line" (p)
+    "Moves the point to the beginning of the current line, extending the selection.
+  With prefix argument, moves the point to the beginning of the prefix'th
+  next line."
+    "Moves the point down p lines and then to the beginning of the line, extending the selection."
+  (let ((point (current-point-for-selection-start)))
+    (unless (line-offset point (if p p 0)) (editor-error "No such line."))
+    (line-start point)))
+
+(defcommand "End of Line" (p)
+  "Moves the point to the end of the current line, collapsing the selection.
+  With prefix argument, moves the point to the end of the prefix'th next line."
+  "Moves the point down p lines and then to the end of the line, collapsing the selection."
+  (let ((point (current-point-collapsing-selection)))
+    (unless (line-offset point (if p p 0)) (editor-error "No such line."))
+    (line-end point)))
+
+(defcommand "Select to End of Line" (p)
+  "Moves the point to the end of the current line, extending the selection.
+  With prefix argument, moves the point to the end of the prefix'th next line."
+  "Moves the point down p lines and then to the end of the line, extending the selection."
+  (let ((point (current-point-for-selection-end)))
+    (unless (line-offset point (if p p 0)) (editor-error "No such line."))
+    (line-end point)))
+
+(defhvar "Scroll Overlap"
+  "The \"Scroll Window\" commands leave this much overlap between screens."
+  :value 2)
+
+(defhvar "Scroll Redraw Ratio"
+  "This is a ratio of \"inserted\" lines to the size of a window.  When this
+   ratio is exceeded, insert/delete line terminal optimization is aborted, and
+   every altered line is simply redrawn as efficiently as possible.  For example,
+   setting this to 1/4 will cause scrolling commands to redraw the entire window
+   instead of moving the bottom two lines of the window to the top (typically
+   3/4 of the window is being deleted upward and inserted downward, hence a
+   redraw); however, commands line \"New Line\" and \"Open Line\" will still
+   efficiently, insert a line moving the rest of the window's text downward."
+  :value nil)
+
+(defcommand "Scroll Window Down" (p)
+  "Move down one screenfull.
+  With prefix argument scroll down that many lines."
+  "If P is NIL then scroll Window, which defaults to the current
+  window, down one screenfull.  If P is supplied then scroll that
+  many lines."
+  (if p
+    (set-scroll-position :lines-down p)
+    (set-scroll-position :page-down)))
+
+(defcommand "Page Down" (p)
+  "Move down one screenfull, without changing the selection."
+  "Ignores prefix argument"
+  (declare (ignore p))
+  (set-scroll-position :view-page-down))
+
+(defcommand "Scroll Window Up" (p)
+  "Move up one screenfull.
+  With prefix argument scroll up that many lines."
+  "If P is NIL then scroll Window, which defaults to the current
+  window, up one screenfull.  If P is supplied then scroll that
+  many lines."
+  (if p
+    (set-scroll-position :lines-up p)
+    (set-scroll-position :page-up)))
+
+(defcommand "Page Up" (p)
+  "Move up one screenfull, without changing the selection."
+  "Ignores prefix argument."
+  (declare (ignore p))
+  (set-scroll-position :view-page-up))
+
+;;;; Kind of miscellaneous commands:
+
+(defcommand "Refresh Screen" (p)
+  "Refreshes everything in the window, centering current line.
+With prefix argument, puts moves current line to top of window"
+  (if p
+    (set-scroll-position :line (current-point))
+    (set-scroll-position :center-selection)))
+
+
+(defcommand "Extended Command" (p)
+  "Prompts for and executes an extended command."
+  "Prompts for and executes an extended command.  The prefix argument is
+  passed to the command."
+  (let* ((name (prompt-for-keyword :tables (list *command-names*)
+				   :prompt "Extended Command: "
+				   :help "Name of a Hemlock command"))
+	 (function (command-function (getstring name *command-names*))))
+    (funcall function p)))
+
+(defhvar "Universal Argument Default"
+  "Default value for \"Universal Argument\" command."
+  :value 4)
+
+(defstruct (prefix-argument-state (:conc-name "PS-"))
+  sign
+  multiplier
+  read-some-digit-p
+  ;; This is NIL if haven't started and don't have a universal argument, else a number
+  result
+  ;; This is cleared by prefix-argument-resetting-state (called at the start of each
+  ;; command) and can be set by a command to avoid the state being reset at
+  ;; the end of the command.
+  set-p)
+
+(defun prefix-argument-resetting-state (&optional (ps (current-prefix-argument-state)))
+  "Fetches the prefix argument and uses it up, i.e. marks it as not being set"
+  (unless (ps-set-p ps)
+    (setf (ps-sign ps) 1
+	  (ps-multiplier ps) 1
+	  (ps-read-some-digit-p ps) nil
+	  (ps-result ps) nil))
+  (setf (ps-set-p ps) nil) ;; mark it for death unless explicitly revived.
+  (when (ps-result ps)
+    (* (ps-sign ps)
+       (if (ps-read-some-digit-p ps)
+	 (ps-result ps)
+	 (expt (value universal-argument-default) (ps-multiplier ps))))))
+
+(defun note-prefix-argument-set (ps)
+  (assert (ps-result ps))
+  (setf (ps-set-p ps) t)
+  (message (with-output-to-string (s)
+	     (dotimes (i (ps-multiplier ps))
+	       (write-string "C-U " s))
+	     (cond ((ps-read-some-digit-p ps)
+		    (format s "~d" (* (ps-sign ps) (ps-result ps))))
+		   ((< (ps-sign ps) 0)
+		    (write-string "-" s))))))
+
+(defcommand "Universal Argument" (p)
+  "Sets prefix argument for next command.
+   Typing digits, regardless of any modifier keys, specifies the argument.
+   Optionally, you may first type a sign (- or +).  While typing digits, if you
+   type C-U or C-u, the digits following the C-U form a number this command
+   multiplies by the digits preceding the C-U.  The default value for this
+   command and any number following a C-U is the value of \"Universal Argument
+   Default\"."
+  (declare (ignore p)) ;; we operate on underlying state instead
+  (let ((ps (current-prefix-argument-state)))
+    (if (ps-result ps)
+      (incf (ps-multiplier ps))
+      (setf (ps-result ps) 0))
+    (note-prefix-argument-set ps)))
+
+(defcommand "Argument Digit" (p)
+  "This command is equivalent to invoking \"Universal Argument\" and typing
+   the key used to invoke this command.  It waits for more digits and a
+   command to which to give the prefix argument."
+  (declare (ignore p)) ;; we operate on underlying state instead
+  (let* ((ps (current-prefix-argument-state))
+	 (key-event (last-key-event-typed))
+	 (stripped-key-event (make-key-event key-event))
+	 (char (key-event-char stripped-key-event))
+	 (digit (if char (digit-char-p char))))
+    (when (null (ps-result ps))
+      (setf (ps-result ps) 0))
+    (case char
+      (#\-
+       (when (ps-read-some-digit-p ps) ;; could just insert it up front...
+	 (editor-error "Must type minus sign first."))
+       (setf (ps-sign ps) (- (ps-sign ps))))
+      (#\+
+       (when (ps-read-some-digit-p ps) ;; could just insert it up front...
+	 (editor-error "Must type plus sign first.")))
+      (t
+       (unless digit
+	 (editor-error "Argument Digit must be bound to a digit!"))
+       (setf (ps-read-some-digit-p ps) t)
+       (setf (ps-result ps) (+ digit (* (ps-result ps) 10)))))
+    (note-prefix-argument-set ps)))
+
+(defcommand "Digit" (p)
+  "With a numeric argument, this command extends the argument.
+   Otherwise it does self insert"
+  (if p
+    (argument-digit-command p)
+    (self-insert-command p)))
Index: /branches/new-random/cocoa-ide/hemlock/src/comments.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/comments.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/comments.lisp	(revision 13309)
@@ -0,0 +1,407 @@
+;;; -*- Log: Hemlock.Log; Package: Hemlock -*-
+;;; 
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;
+;;; This file contains the implementation of comment commands.
+
+(in-package hemlock)
+
+
+
+;;;; -- Variables --
+
+(defhvar "Comment Column"
+  "Colmun to start comments in."
+  :value 0)
+
+(defhvar "Comment Start"
+  "String that indicates the start of a comment."
+  :value nil)
+
+(defhvar "Comment End"
+  "String that ends comments.  Nil indicates #\newline termination."
+  :value nil)
+
+(defhvar "Comment Begin"
+  "String that is inserted to begin a comment."
+  :value nil)
+
+
+;;;; -- Internal Specials --
+
+;;; For the search pattern state specials, we just use " " as the comment
+;;; start and end if none exist, so we are able to make search patterns.
+;;; This is reasonable since any use of these will cause the patterns to be
+;;; made consistent with the actual start and end strings.
+
+(defvar *comment-start-pattern*
+  (new-search-pattern :string-insensitive :forward (or (value comment-start) " "))
+  "Search pattern to keep around for looking for comment starts.")
+
+(defvar *last-comment-start*
+  (or (value comment-start) " ")
+  "Previous comment start used to make *comment-start-pattern*.")
+
+(defvar *comment-end-pattern*
+  (new-search-pattern :string-insensitive :forward (or (value comment-end) " "))
+  "Search pattern to keep around for looking for comment ends.")
+
+(defvar *last-comment-end*
+  (or (value comment-end) " ")
+  "Previous comment end used to make *comment-end-pattern*.")
+
+
+(eval-when (:compile-toplevel :execute)
+(defmacro get-comment-pattern (string kind) ;kind is either :start or :end
+  (let (pattern-var last-var)
+    (cond ((eq kind :start)
+	   (setf pattern-var '*comment-start-pattern*)
+	   (setf last-var '*last-comment-start*))
+	  (t (setf pattern-var '*comment-end-pattern*)
+	     (setf last-var '*last-comment-end*)))
+    `(cond ((string= (the simple-string ,string) (the simple-string ,last-var))
+	    ,pattern-var)
+	   (t (setf ,last-var ,string)
+	      (new-search-pattern :string-insensitive :forward
+				  ,string ,pattern-var)))))
+) ;eval-when
+
+
+
+;;;;  -- Commands --
+
+(defcommand "Set Comment Column" (p)
+  "Set Comment Column to current column or argument.
+   If argument is provided use its absolute value."
+  "Set Comment Column to current column or argument.
+   If argument is provided use its absolute value."
+  (let ((new-column (or (and p (abs p))
+			(mark-column (current-point)))))
+    (defhvar "Comment Column" "This buffer's column to start comments."
+      :value new-column  :buffer (current-buffer))
+    (message "Comment Column = ~D" new-column)))
+
+
+(defcommand "Indent for Comment" (p)
+  "Move to or create a comment.  Moves to the start of an existing comment
+   and indents it to start in Comment Column.  An existing double semicolon
+   comment is aligned like a line of code.  An existing triple semicolon
+   comment or any that start in column 0 is not moved.  With argument,
+   aligns any comments on the next argument lines but does not create any.
+   If characters extend past comment column, a space is added before
+   starting comment."
+  "Create comment or move to beginning of existing one aligning it."
+  (let* ((column (value comment-column))
+	 (start (value comment-start))
+	 (begin (value comment-begin))
+	 (end (value comment-end)))
+    (unless (stringp start) (editor-error "No comment start string -- ~S." start))
+    (indent-for-comment (current-point) column start begin end (or p 1))))
+
+
+(defcommand "Up Comment Line" (p)
+  "Equivalent to Previous Line followed by Indent for Comment (C-P ALT-;)."
+  "Equivalent to Previous Line followed by Indent for Comment (C-P ALT-;)."
+  (let ((column (value comment-column))
+	(start (value comment-start))
+	(begin (value comment-begin))
+	(end (value comment-end)))
+    (unless (stringp start) (editor-error "No comment start string -- ~S." start))
+    (change-comment-line (current-point) column start
+			 begin end (or (and p (- p)) -1))))
+
+(defcommand "Down Comment Line" (p)
+  "Equivalent to Next Line followed by Indent for Comment (C-N ALT-;)."
+  "Equivalent to Next Line followed by Indent for Comment (C-N ALT-;)."
+  (let ((column (value comment-column))
+	(start (value comment-start))
+	(begin (value comment-begin))
+	(end (value comment-end)))
+    (unless (stringp start) (editor-error "No comment start string -- ~S." start))
+    (change-comment-line (current-point) column start begin end (or p 1))))
+
+
+(defcommand "Kill Comment" (p)
+  "Kills the comment (if any) on the current line.
+   With argument, applies to specified number of lines, and moves past them."
+  "Kills the comment (if any) on the current line.
+   With argument, applies to specified number of lines, and moves past them."
+  (let ((start (value comment-start)))
+    (when start
+      (if (not (stringp start))
+	  (editor-error "Comment start not string or nil -- ~S." start))
+      (kill-comment (current-point) start (or p 1)))))
+
+
+(defcommand "Indent New Comment Line" (p)
+  "Inserts comment end and then starts a comment on a new line.
+   The indentation and number of additional comment-start characters are
+   copied from the previous line's comment.  Acts like Linefeed, when done
+   while not inside a comment, assuming a comment is the last thing on a line."
+  "complete a current comment and start another a new line, copying indentation
+   and start characters.  If no comment, call Linefeed command."
+  (let ((start (value comment-start))
+	(begin (value comment-begin))
+	(end (value comment-end))
+	(point (current-point)))
+    (with-mark ((tmark point :left-inserting))
+      (if start
+	  (cond ((not (stringp start))
+		 (editor-error "Comment start not string or nil -- ~S." start))
+		((and (to-line-comment tmark start) (mark> point tmark))
+		 (with-mark ((emark tmark))
+		   (let ((endp (if end (to-comment-end emark end))))
+		     (cond ((and endp (mark= emark point))
+			    (insert-string point end)
+			    (indent-new-comment-line point tmark start begin end))
+			   ((and endp
+				 (character-offset emark endp)
+				 (mark>= point emark))
+			    (indent-new-line-command p))
+			   (t (delete-horizontal-space point)
+			      (if end (insert-string point end))
+			      (indent-new-comment-line point tmark
+						       start begin end))))))
+		(t (indent-new-line-command p)))
+	  (indent-new-line-command p)))))
+
+
+
+;;;; -- Support Routines --
+
+(eval-when (:compile-toplevel :execute)
+(defmacro %do-comment-lines ((var number) mark1 &rest forms)
+  (let ((next-line-p (gensym)))
+    `(do ((,var (if (plusp ,number) ,number 0) (1- ,var))
+	  (,next-line-p t))
+	 ((or (zerop ,var) (not ,next-line-p))
+	  (zerop ,var))
+       ,@forms
+       (setf ,next-line-p (line-offset ,mark1 1)))))
+) ;eval-when
+
+
+;;; CHANGE-COMMENT-LINE closes any comment on the current line, deleting
+;;; an empty comment.  After offsetting by lines, a comment is either
+;;; aligned or created.
+(defun change-comment-line (mark column start begin end lines)
+  (with-mark ((tmark1 mark :left-inserting)
+	      (tmark2 mark))
+    (let ((start-len (to-line-comment mark start))
+	  end-len)
+      (when start-len
+	(if end
+	    (setf end-len (to-comment-end (move-mark tmark1 mark) end))
+	    (line-end tmark1))
+	(character-offset (move-mark tmark2 mark) start-len)
+	(find-attribute tmark2 :whitespace #'zerop)
+	(cond ((mark>= tmark2 tmark1)
+	       (if end-len (character-offset tmark1 end-len))
+	       ;; even though comment is blank, the line might not be blank
+	       ;; after it in languages that have comment terminators.
+	       (when (blank-after-p tmark1)
+		 (reverse-find-attribute mark :whitespace #'zerop)
+		 (if (not (same-line-p mark tmark1))
+		     (line-start mark (mark-line tmark1)))
+		 (delete-region (region mark tmark1))))
+	      ((and end (not end-len)) (insert-string tmark1 end))))
+      (if (line-offset mark lines)
+	  (indent-for-comment mark column start begin end 1)
+	  (editor-error)))))
+
+
+(defun indent-for-comment (mark column start begin end times)
+  (with-mark ((tmark mark :left-inserting))
+    (if (= times 1)
+	(let ((start-len (to-line-comment tmark start)))
+	  (cond (start-len
+		 (align-comment tmark start start-len column)
+		 (character-offset (move-mark mark tmark) start-len))
+		(t (comment-line mark column start begin end))))
+	(unless (%do-comment-lines (n times) mark
+		  (let ((start-len (to-line-comment mark start)))
+		    (if start-len (align-comment mark start start-len column))))
+	  (buffer-end mark)
+	  (editor-error)))))
+
+
+;;; KILL-COMMENT assumes a comment is the last thing on a line, so it does
+;;; not deal with comment-end.  The Tao of EMACS.
+(defun kill-comment (mark start times)
+  (with-mark ((tmark mark :left-inserting))
+    (if (= times 1)
+	(when (to-line-comment mark start)
+	  (with-mark ((u-start mark)
+		      (u-end (line-end (move-mark tmark mark))))
+	    (rev-scan-char u-start :whitespace nil)
+	    (let ((undo-region (copy-region (region u-start u-end))))
+	      (kill-ring-push (delete-and-save-region (region mark tmark)))
+	      (delete-horizontal-space mark)
+	      (make-region-undo :insert "Kill Comment" undo-region
+				(copy-mark mark :left-inserting)))))
+	(let* ((kill-region (delete-and-save-region (region mark tmark)))
+	       (insert-mark (region-end kill-region))
+	       ;; don't delete u-start and u-end since undo stuff handles that.
+	       (u-start (line-start (copy-mark mark :left-inserting)))
+	       (u-end (copy-mark mark :left-inserting))
+	       (undo-region (copy-region (region u-start
+						 (if (line-offset u-end times)
+						     (line-start u-end)
+						     (buffer-end u-end)))))
+	       (n-times-p
+		(%do-comment-lines (n times) mark
+		  (when (to-line-comment mark start)
+		    (line-end (move-mark tmark mark))
+		    (ninsert-region insert-mark
+				    (delete-and-save-region (region mark tmark)))
+		    (insert-character insert-mark #\newline)
+		    (delete-horizontal-space mark)))))
+	  (kill-ring-push kill-region)
+	  (make-region-undo :twiddle "Kill Comment"
+			    (region u-start u-end) undo-region)
+	  (unless n-times-p
+	    (buffer-end mark)
+	    (editor-error))))))
+
+(defun comment-line (point column start begin end)
+  (let* ((open (or begin start))
+	 (open-len (length (the simple-string open)))
+	 (end-len (if end (length (the simple-string end)) 0))
+	 (insert-len (+ open-len end-len)))
+    (line-end point)
+    (insert-string point open)
+    (if end (insert-string point end))
+    (character-offset point (- insert-len))
+    (adjust-comment point column)
+    (character-offset point open-len)))
+
+
+(eval-when (:compile-toplevel :execute)
+(defmacro count-extra-last-chars (mark start-len start-char)
+  (let ((count (gensym))
+	(tmark (gensym)))
+    `(with-mark ((,tmark ,mark))
+       (character-offset ,tmark ,start-len)
+       (do ((,count 0 (1+ ,count)))
+	   ((char/= (next-character ,tmark) ,start-char) ,count)
+	 (mark-after ,tmark)))))
+)
+
+
+;;; ALIGN-COMMENT sets a comment starting at mark to start in column
+;;; column.  If the comment starts at the beginning of the line, it is not
+;;; moved.  If the comment start is a single character and duplicated, then
+;;; it is indented as if it were code, and if it is triplicated, it is not
+;;; moved.  If the comment is to be moved to column, then we check to see
+;;; if it is already there and preceded by whitespace.
+
+(defun align-comment (mark start start-len column)
+  (unless (start-line-p mark)
+    (case (count-extra-last-chars mark start-len (schar start (1- start-len)))
+      (1 (funcall (value indent-function) mark))
+      (2 )
+      (t (if (or (/= (mark-column mark) column)
+		 (zerop (character-attribute
+			 :whitespace (previous-character mark))))
+	     (adjust-comment mark column))))))
+
+
+;;; ADJUST-COMMENT moves the comment starting at mark to start in column
+;;; column, inserting a space if the line extends past column.
+(defun adjust-comment (mark column)
+  (delete-horizontal-space mark)
+  (let ((current-column (mark-column mark))
+	(spaces-per-tab (value spaces-per-tab))
+	tabs spaces next-tab-pos)
+    (cond ((= current-column column)
+	   (if (/= column 0) (insert-character mark #\space)))
+	  ((> current-column column) (insert-character mark #\space))
+	  (t (multiple-value-setq (tabs spaces)
+	       (floor current-column spaces-per-tab))
+	     (setf next-tab-pos
+		   (if (zerop spaces)
+		       current-column
+		       (+ current-column (- spaces-per-tab spaces))))
+	     (cond ((= next-tab-pos column)
+		    (insert-character mark #\tab))
+		   ((> next-tab-pos column)
+		    (dotimes (i (- column current-column))
+		      (insert-character mark #\space)))
+		   (t (multiple-value-setq (tabs spaces)
+			(floor (- column next-tab-pos) spaces-per-tab))
+		      (dotimes (i (if (= current-column next-tab-pos)
+				      tabs
+				      (1+ tabs)))
+			(insert-character mark #\tab))
+		      (dotimes (i spaces)
+			(insert-character mark #\space))))))))
+
+
+;;; INDENT-NEW-COMMENT-LINE makes a new line at point starting a comment
+;;; in the same way as the one at start-mark.
+(defun indent-new-comment-line (point start-mark start begin end)
+  (new-line-command nil)
+  (insert-string point (gen-comment-prefix start-mark start begin))
+  (if end
+      (when (not (to-comment-end (move-mark start-mark point) end))
+	(insert-string start-mark end)
+	(if (mark= start-mark point)
+	    ;; This occurs when nothing follows point on the line and
+	    ;; both marks are left-inserting.
+	    (character-offset
+	     point (- (length (the simple-string end))))))))
+
+
+;;; GEN-COMMENT-PREFIX returns a string suitable for beginning a line
+;;; with a comment lined up with mark and starting the same as the comment
+;;; immediately following mark.  This is used in the auto filling stuff too.
+(defun gen-comment-prefix (mark start begin)
+  (let* ((start-len (length (the simple-string start)))
+	 (last-char (schar start (1- start-len)))
+	 (extra-start-chars (count-extra-last-chars mark start-len last-char))
+	 (spaces-per-tab (value spaces-per-tab))
+	 (begin-end (if begin
+			(subseq begin start-len (length (the simple-string begin)))
+			"")))
+    (multiple-value-bind (tabs spaces) (floor (mark-column mark) spaces-per-tab)
+      (concatenate 'simple-string
+		   (make-string tabs :initial-element #\tab)
+		   (make-string spaces :initial-element #\space)
+		   start
+		   (make-string extra-start-chars :initial-element last-char)
+		   begin-end))))
+
+
+;;; TO-LINE-COMMENT moves mark to the first comment start character on its
+;;; line if there is a comment and returns the length of start, otherwise
+;;; nil is returned.  Start must be a string.  This is used by the auto
+;;; filling stuff too.
+(defun to-line-comment (mark start)
+  (with-mark ((tmark mark))
+    (line-start tmark)
+    (let ((start-len (find-pattern tmark (get-comment-pattern start :start))))
+      (when (and start-len (same-line-p mark tmark))
+	(move-mark mark tmark)
+	start-len))))
+
+
+;;; TO-COMMENT-END moves mark to the first comment end character on its
+;;; line if end is there and returns the length of comment end, otherwise
+;;; mark is moved to the end of the line returning nil.  This is used by
+;;; the auto filling stuff too.
+(defun to-comment-end (mark end)
+  (with-mark ((tmark mark))
+    (let ((end-len (find-pattern tmark (get-comment-pattern end :end))))
+      (cond ((and end-len (same-line-p mark tmark))
+	     (move-mark mark tmark)
+	     end-len)
+	    (t (line-end mark) nil)))))
Index: /branches/new-random/cocoa-ide/hemlock/src/completion.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/completion.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/completion.lisp	(revision 13309)
@@ -0,0 +1,530 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Skef Wholey and Blaine Burks.
+;;; General idea stolen from Jim Salem's TMC LISPM completion code.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; The Completion Database.
+
+;;; The top level structure here is an array that gets indexed with the
+;;; first three characters of the word to be completed.  That will get us to
+;;; a list of the strings with that prefix sorted in most-recently-used order.
+;;; The number of strings in any given bucket will never exceed
+;;; Completion-Bucket-Size-Limit.  Strings are stored in the database in
+;;; lowercase form always.
+
+(defconstant completion-table-size 991)
+
+(defvar *completions* (make-array completion-table-size :initial-element nil))
+
+(defhvar "Completion Bucket Size"
+  "This limits the number of completions saved for a particular combination of
+   the first three letters of any word."
+  :value 20)
+
+
+;;; Mapping strings into buckets.
+
+;;; The characters that are considered parts of "words" change from mode
+;;; to mode.
+;;;
+(defattribute "Completion Wordchar"
+  "1 for characters we consider to be constituents of words.")
+
+(defvar default-other-wordchars
+  '(#\- #\* #\' #\_))
+
+(do-alpha-chars (char :both)
+  (setf (character-attribute :completion-wordchar char) 1))
+
+(dolist (char '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
+  (setf (character-attribute :completion-wordchar char) 1))
+
+(dolist (char default-other-wordchars)
+  (setf (character-attribute :completion-wordchar char) 1))
+
+
+;;; The difference between Lisp mode and the other modes is pretty radical in
+;;; this respect.  These are interesting too, but they're on by default: #\*,
+;;; #\-, and #\_.  #\' is on by default too, but it's uninteresting in "Lisp"
+;;; mode.
+;;;
+(defvar default-lisp-wordchars
+  '(#\~ #\! #\@ #\$ #\% #\^ #\& #\+ #\= #\< #\> #\. #\/ #\?))
+
+(dolist (char default-lisp-wordchars)
+  (shadow-attribute :completion-wordchar char 1 "Lisp"))
+
+(shadow-attribute :completion-wordchar #\' 0 "Lisp")
+
+(defmacro completion-char-p (char)
+  `(= (the fixnum (character-attribute :completion-wordchar ,char)) 1))
+
+;;; COMPLETION-BUCKET-FOR returns the Completion-Bucket that might hold a
+;;; completion for the given String.  With optional Value, sets the bucket.
+;;;
+(defun completion-bucket-for (string length &optional (value nil value-p))
+  (declare (simple-string string)
+	   (fixnum length))
+  (when (and (>= length 3)
+	     (completion-char-p (char string 0))
+	     (completion-char-p (char string 1))
+	     (completion-char-p (char string 2)))
+    (let ((index (mod (logxor (ash
+			       (logxor
+				(ash (hi::search-hash-code (schar string 0))
+				     5)
+				(hi::search-hash-code (schar string 1)))
+			       3)
+			      (hi::search-hash-code (schar string 2)))
+		      completion-table-size)))
+      (declare (fixnum index))
+      (if value-p
+	  (setf (svref *completions* index) value)
+	  (svref *completions* index)))))
+
+(defsetf completion-bucket-for completion-bucket-for)
+
+
+;;; FIND-COMPLETION returns the most recent string matching the given
+;;; Prefix, or Nil if nothing appropriate is in the database.  We assume
+;;; the Prefix is passed to us in lowercase form so we can use String=.  If
+;;; we find something appropriate, we bring it to the front of the list.
+;;; Prefix-Length, if supplied restricts us to look at just the start of
+;;; the string...
+;;;
+(defun find-completion (prefix &optional (prefix-length (length prefix)))
+  (declare (simple-string prefix)
+	   (fixnum prefix-length))
+  (let ((bucket (completion-bucket-for prefix prefix-length)))
+    (do ((list bucket (cdr list)))
+	((null list))
+      (let ((completion (car list)))
+	(declare (simple-string completion))
+	(when (and (>= (length completion) prefix-length)
+		   (string= prefix completion
+			    :end1 prefix-length
+			    :end2 prefix-length))
+	  (unless (eq list bucket)
+	    (rotatef (car list) (car bucket)))
+	  (return completion))))))
+
+;;; RECORD-COMPLETION saves string in the completion database as the first item
+;;; in the bucket, that's the most recently used completion.  If the bucket is
+;;; full, drop the oldest item in the list.  If string is already in the
+;;; bucket, simply move it to the front.  The way we move an element to the
+;;; front requires a full bucket to be at least three elements long.
+;;;
+(defun record-completion (string)
+  (declare (simple-string string))
+  (let ((string-length (length string)))
+    (declare (fixnum string-length))
+    (when (> string-length 3)
+      (let ((bucket (completion-bucket-for string string-length))
+	    (limit (value completion-bucket-size)))
+	(do ((list bucket (cdr list))
+	     (last nil list)
+	     (length 1 (1+ length)))
+	    ((null list)
+	     (setf (completion-bucket-for string string-length)
+		   (cons string bucket)))
+	  (cond ((= length limit)
+		 (setf (car list) string)
+		 (setf (completion-bucket-for string string-length) list)
+		 (setf (cdr list) bucket)
+		 (setf (cdr last) nil)
+		 (return))
+		((string= string (the simple-string (car list)))
+		 (unless (eq list bucket)
+		   (rotatef (car list) (car bucket)))
+		 (return))))))))
+
+;;; ROTATE-COMPLETIONS rotates the completion bucket for the given Prefix.
+;;; We just search for the first thing in the bucket with the Prefix, then
+;;; move that to the end of the list.  If there ain't no such thing there,
+;;; or if it's already at the end, we do nothing.
+;;;
+(defun rotate-completions (prefix &optional (prefix-length (length prefix)))
+  (declare (simple-string prefix))
+  (let ((bucket (completion-bucket-for prefix prefix-length)))
+    (do ((list bucket (cdr list))
+	 (prev nil list))
+	((null list))
+      (let ((completion (car list)))
+	(declare (simple-string completion))
+	(when (and (>= (length completion) prefix-length)
+		   (string= prefix completion
+			    :end1 prefix-length :end2 prefix-length))
+	  (when (cdr list)
+	    (if prev
+		(setf (cdr prev) (cdr list))
+		(setf (completion-bucket-for prefix prefix-length) (cdr list)))
+	    (setf (cdr (last list)) list)
+	    (setf (cdr list) nil))
+	  (return nil))))))
+
+
+
+
+;;;; Hemlock interface.
+
+(defmode "Completion" :transparent-p t :precedence 10.0
+  :documentation
+  "This is a minor mode that saves words greater than three characters in length,
+   allowing later completion of those words.  This is very useful for often
+   long identifiers used in Lisp code.  All words with the same first three
+   letters are in one list sorted by most recently used.  \"Completion Bucket
+   Size\" limits the number of completions saved in each list.")
+
+(defvar *completion-modeline-field* (modeline-field :completion))
+
+(defcommand "Completion Mode" (p)
+  "Toggles Completion Mode in the current buffer."
+  "Toggles Completion Mode in the current buffer."
+  (declare (ignore p))
+  (let ((buffer (current-buffer)))
+    (setf (buffer-minor-mode buffer "Completion")
+          (not (buffer-minor-mode buffer "Completion")))
+    (let ((fields (buffer-modeline-fields buffer)))
+      (if (buffer-minor-mode buffer "Completion")
+        (unless (member *completion-modeline-field* fields)
+          (hi::set-buffer-modeline-fields buffer
+                                          (append fields
+                                                  (list *completion-modeline-field*))))
+        (when (member *completion-modeline-field* fields)
+          (hi::set-buffer-modeline-fields buffer
+                                          (remove *completion-modeline-field*
+                                                  fields)))))))
+
+
+;;; Consecutive alphanumeric keystrokes that start a word cause a possible
+;;; completion to be displayed in the echo area's modeline, the status line.
+;;; Since most insertion is building up a word that was already started, we
+;;; keep track of the word in *completion-prefix* that the user is typing.  The
+;;; length of the thing is kept in *completion-prefix-length*.
+;;;
+(defconstant completion-prefix-max-size 100)
+
+(defvar *completion-prefix* (make-string completion-prefix-max-size))
+
+(defvar *completion-prefix-length* 0)
+
+
+;;; "Completion Self Insert" does different stuff depending on whether or
+;;; not the thing to be inserted is Completion-Char-P.  If it is, then we
+;;; try to come up with a possible completion, using Last-Command-Type to
+;;; tense things up a bit.  Otherwise, if Last-Command-Type says we were
+;;; just doing a word, then we record that word in the database.
+;;;
+(defcommand "Completion Self Insert" (p)
+  "Insert the last character typed, showing possible completions.  With prefix
+   argument insert the character that many times."
+  "Implements \"Completion Self Insert\". Calling this function is not
+   meaningful."
+  (let ((char (last-char-typed)))
+    (unless char (editor-error "Can't insert that character."))
+    (cond ((completion-char-p char)
+	   ;; If start of word not already in *completion-prefix*, put it 
+	   ;; there.
+	   (unless (eq (last-command-type) :completion-self-insert)
+	     (set-completion-prefix))
+	   ;; Then add new stuff.
+	   (cond ((and p (> p 1))
+		  (fill *completion-prefix* (char-downcase char)
+			:start *completion-prefix-length*
+			:end (+ *completion-prefix-length* p))
+		  (incf *completion-prefix-length* p))
+		 (t
+		  (setf (schar *completion-prefix* *completion-prefix-length*)
+			(char-downcase char))
+		  (incf *completion-prefix-length*)))
+	   ;; Display possible completion, if any.
+	   (display-possible-completion *completion-prefix*
+					*completion-prefix-length*)
+	   (setf (last-command-type) :completion-self-insert))
+	  (t
+	   (when (eq (last-command-type) :completion-self-insert)
+	     (record-completion (subseq *completion-prefix*
+					0 *completion-prefix-length*)))))))
+
+;;; SET-COMPLETION-PREFIX grabs any completion-wordchars immediately before
+;;; point and stores these into *completion-prefix*.
+;;;
+(defun set-completion-prefix ()
+  (let* ((point (current-point))
+	 (point-line (mark-line point)))
+    (cond ((and (previous-character point)
+		(completion-char-p (previous-character point)))
+	   (with-mark ((mark point))
+	     (reverse-find-attribute mark :completion-wordchar #'zerop)
+	     (unless (eq (mark-line mark) point-line)
+	       (editor-error "No completion wordchars on this line!"))
+	     (let ((insert-string (nstring-downcase
+				   (region-to-string
+				    (region mark point)))))
+	       (replace *completion-prefix* insert-string)
+	       (setq *completion-prefix-length* (length insert-string)))))
+	  (t
+	   (setq *completion-prefix-length* 0)))))
+
+
+(defcommand "Completion Complete Word" (p)
+  "Complete the word if we've got a completion, fixing up the case.  Invoking
+   this immediately in succession rotates through possible completions in the
+   buffer.  If there is no currently displayed completion, this tries to choose
+   a completion from text immediately before the point and displays the
+   completion if found."
+  "Complete the word if we've got a completion, fixing up the case."
+  (declare (ignore p))
+  (let ((last-command-type (last-command-type)))
+    ;; If the user has been cursoring around and then tries to complete,
+    ;; let him.
+    ;;
+    (unless (member last-command-type '(:completion-self-insert :completion))
+      (set-completion-prefix)
+      (setf last-command-type :completion-self-insert))
+    (case last-command-type
+      (:completion-self-insert
+       (do-completion))
+      (:completion
+       (rotate-completions *completion-prefix* *completion-prefix-length*)
+       (do-completion))))
+  (setf (last-command-type) :completion))
+
+(defcommand "List Possible Completions" (p)
+  "List all possible completions of the prefix the user has typed."
+  "List all possible completions of the prefix the user has typed."
+  (declare (ignore p))
+  (let ((last-command-type (last-command-type)))
+    (unless (member last-command-type '(:completion-self-insert :completion))
+      (set-completion-prefix))
+    (let* ((prefix *completion-prefix*)
+	   (prefix-length *completion-prefix-length*)
+	   (bucket (completion-bucket-for prefix prefix-length)))
+      (with-pop-up-display (s)
+	(dolist (completion bucket)
+	  (when (and (> (length completion) prefix-length)
+		     (string= completion prefix
+			      :end1 prefix-length
+			      :end2 prefix-length))
+	    (write-line completion s))))))
+  ;; Keep the redisplay hook from clearing any possibly displayed completion.
+  (setf (last-command-type) :completion-self-insert))
+
+(defvar *last-completion-mark* nil)
+
+(defun do-completion ()
+  (let ((completion (find-completion *completion-prefix*
+				     *completion-prefix-length*))
+	(point (current-point)))
+    (when completion
+      (if *last-completion-mark*
+	  (move-mark *last-completion-mark* point)
+	  (setq *last-completion-mark* (copy-mark point :temporary)))
+      (let ((mark *last-completion-mark*))
+	(reverse-find-attribute mark :completion-wordchar #'zerop)
+	(let* ((region (region mark point))
+	       (string (region-to-string region)))
+	  (declare (simple-string string))
+	  (delete-region region)
+	  (let* ((first (position-if #'alpha-char-p string))
+		 (next (if first (position-if #'alpha-char-p string
+					      :start (1+ first)))))
+	    ;; Often completions start with asterisks when hacking on Lisp
+	    ;; code, so we look for alphabetic characters.
+	    (insert-string point
+			   ;; Leave the cascading IF's alone.
+			   ;; Writing this as a COND, using LOWER-CASE-P as
+			   ;; the test is not equivalent to this code since
+			   ;; numbers (and such) are nil for LOWER-CASE-P and
+			   ;; UPPER-CASE-P.
+			   (if (and first (upper-case-p (schar string first)))
+			       (if (and next
+					(upper-case-p (schar string next)))
+				   (string-upcase completion)    
+				   (word-capitalize completion))
+			       completion))))))))
+
+
+;;; WORD-CAPITALIZE is like STRING-CAPITALIZE except that it treats apostrophes
+;;; the Right Way.
+;;;
+(defun word-capitalize (string)
+  (let* ((length (length string))
+	 (strung (make-string length)))
+    (do  ((i 0 (1+ i))
+	  (new-word t))
+	 ((= i length))
+      (let ((char (schar string i)))
+	(cond ((or (alphanumericp char)
+		   (char= char #\'))
+	       (setf (schar strung i)
+		     (if new-word (char-upcase char) (char-downcase char)))
+	       (setq new-word nil))
+	      (t
+	       (setf (schar strung i) char)
+	       (setq new-word t)))))
+    strung))
+
+(defcommand "Completion Rotate Completions" (p)
+  "Show another possible completion in the status line, if there is one.
+   If there is no currently displayed completion, this tries to choose a
+   completion from text immediately before the point and displays the
+   completion if found.  With an argument, rotate the completion ring that many
+   times."
+  "Show another possible completion in the status line, if there is one.
+   With an argument, rotate the completion ring that many times."
+  (unless (eq (last-command-type) :completion-self-insert)
+    (set-completion-prefix)
+    (setf (last-command-type) :completion-self-insert))
+  (dotimes (i (or p 1))
+    (rotate-completions *completion-prefix* *completion-prefix-length*))
+  (display-possible-completion *completion-prefix* *completion-prefix-length*)
+  (setf (last-command-type) :completion-self-insert))
+
+
+
+;;;; Nifty database and parsing machanisms.
+
+(defhvar "Completion Database Filename"
+  "The file that \"Save Completions\" and \"Read Completions\" will
+   respectively write and read the completion database to and from."
+  :value nil)
+
+(defvar *completion-default-default-database-filename*
+  "hemlock-completions.txt"
+  "The file that will be defaultly written to and read from by \"Save
+   Completions\" and \"Read Completions\".")
+
+(defcommand "Save Completions" (p)
+  "Writes the current completion database to a file, defaultly the value of
+   \"Completion Database Filename\".  With an argument, prompts for a
+   filename."
+  "Writes the current completion database to a file, defaultly the value of
+   \"Completion Database Filename\".  With an argument, prompts for a
+   filename."
+  (let ((filename (or (and (not p) (value completion-database-filename))
+		      (prompt-for-file
+		       :must-exist nil
+		       :default *completion-default-default-database-filename*
+		       :prompt "File to write completions to: "))))
+    (with-open-file (s filename
+		       :direction :output
+		       :if-exists :rename-and-delete
+		       :if-does-not-exist :create)
+      (message "Saving completions...")
+      (dotimes (i (length *completions*))
+	(let ((bucket (svref *completions* i)))
+	  (when bucket
+	    (write i :stream s :base 10 :radix 10)
+	    (write-char #\newline s)
+	    (dolist (completion bucket)
+	      (write-line completion s))
+	    (terpri s))))
+      (message "Done."))))
+
+(defcommand "Read Completions" (p)
+  "Reads some completions from a file, defaultly the value of \"Completion
+   Database File\".  With an argument, prompts for a filename."
+  "Reads some completions from a file, defaultly the value of \"Completion
+   Database File\".  With an argument, prompts for a filename."
+  (let ((filename (or (and (not p) (value completion-database-filename))
+		      (prompt-for-file
+		       :must-exist nil
+		       :default *completion-default-default-database-filename*
+		       :prompt "File to read completions from: ")))
+	(index nil)
+	(completion nil))
+    (with-open-file (s filename :if-does-not-exist :error)
+      (message "Reading in completions...")
+      (loop
+	(let ((new-completions '()))
+	  (unless (setf index (read-preserving-whitespace s nil nil))
+	    (return))
+	  ;; Zip past the newline that I know is directly after the number.
+	  ;; All this to avoid consing.  I love it.
+	  (read-char s)
+	  (loop
+	    (setf completion (read-line s))
+	    (when (string= completion "") (return))
+	    (unless (member completion (svref *completions* index))
+	      (push completion new-completions)))
+	  (let ((new-bucket (nconc (nreverse new-completions)
+					    (svref *completions* index))))
+	    (setf (svref *completions* index) new-bucket)
+	    (do ((completion new-bucket (cdr completion))
+		 (end (1- (value completion-bucket-size)))
+		 (i 0 (1+ i)))
+		((endp completion))
+	      (when (= i end) (setf (cdr completion) nil))))))
+      (message "Done."))))
+
+(defcommand "Parse Buffer for Completions" (p)
+  "Zips over a buffer slamming everything that is a valid completion word
+   into the completion hashtable."
+  "Zips over a buffer slamming everything that is a valid completion word
+   into the completion hashtable."
+  (declare (ignore p))
+  (let ((buffer (prompt-for-buffer :prompt "Buffer to parse: "
+				   :must-exist t
+				   :default (current-buffer)
+				   :default-string (buffer-name
+						    (current-buffer)))))
+    (with-mark ((word-start (buffer-start-mark buffer) :right-inserting)
+		(word-end (buffer-start-mark buffer) :left-inserting)
+		(buffer-end-mark (buffer-start-mark buffer)))
+      (message "Starting parse of ~S..." (buffer-name buffer))
+      (loop
+	(unless (find-attribute word-start :completion-wordchar) (return))
+	(record-completion
+	 (region-to-string (region word-start
+				   (or (find-attribute
+					(move-mark word-end word-start)
+					:completion-wordchar #'zerop)
+				       buffer-end-mark))))
+	(move-mark word-start word-end))
+      (message "Done."))))
+
+
+
+
+;;;; Modeline hackery:
+
+(defvar *completion-mode-possibility* "")
+
+(defun display-possible-completion (prefix
+				    &optional (prefix-length (length prefix)))
+  (let ((old *completion-mode-possibility*))
+    (setq *completion-mode-possibility*
+	  (or (find-completion prefix prefix-length) ""))
+    (unless (eq old *completion-mode-possibility*)
+      (hi::note-modeline-change (current-buffer)))))
+
+(defun clear-completion-display ()
+  (unless (= (length (the simple-string *completion-mode-possibility*)) 0)
+    (setq *completion-mode-possibility* "")
+    (hi::note-modeline-change (current-buffer))))
+
+#|
+;;; COMPLETION-REDISPLAY-FUN erases any completion displayed in the status line.
+;;;
+(defun completion-redisplay-fun (window)
+  (declare (ignore window))
+  (unless (eq (last-command-type) :completion-self-insert)
+    (clear-completion-display)))
+(add-hook redisplay-hook #'completion-redisplay-fun)
+|#
Index: /branches/new-random/cocoa-ide/hemlock/src/decls.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/decls.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/decls.lisp	(revision 13309)
@@ -0,0 +1,63 @@
+(in-package :hemlock-internals)
+
+;;; Use #.*fast* for optimizations.
+
+(eval-when (compile eval load)
+  (defparameter *fast*
+    '(declare (optimize speed)))
+
+  (defparameter *fast*
+    '(declare)))
+
+
+;; Since the declaim form for functions looks clumsy and is
+;; syntax-wise different from defun, we define us a new declfun, which
+;; fixes this.
+
+(defmacro declfun (name lambda-list)
+  `(declaim (ftype (function
+                    ,(let ((q lambda-list)
+                           res)
+                          (do () ((or (null q)
+                                      (member (car q) '(&optional &rest &key))))
+                            (push 't res)
+                            (pop q))
+                          (when (eq (car q) '&optional)
+                            (push '&optional res)
+                            (pop q)
+                            (do () ((or (null q)
+                                        (member (car q) '(&rest &key))))
+                              (push 't res)))
+                          (when (eq (car q) '&rest)
+                            (push '&rest res)
+                            (pop q)
+                            (push 't res)
+                            (pop q))
+                          (when (eq (car q) '&key)
+                            (push '&key res)
+                            (pop q)
+                            (do () ((or (null q)
+                                        (member (car q) '(&allow-other-keys))))
+                              (push (list (intern (string (if (consp (car q))
+                                                              (if (consp (caar q))
+                                                                  (caaar q)
+                                                                  (caar q))
+                                                              (car q)))
+                                                  :keyword)
+                                          't)
+                                    res)
+                              (pop q)))
+                          (when (eq (car q) '&allow-other-keys)
+                            (push '&allow-other-keys res)
+                            (pop q))
+                          (reverse res))
+                    t)
+             ,name)))
+
+;;; Some special variables are forward-referenced, and we don't even
+;;; need to invent a new language to advise the compiler of that ...
+(declaim (special *mode-names* *current-buffer*
+		  *the-sentinel*
+		  *in-the-editor* *buffer-list* *things-to-do-once*
+		  *gc-notify-before* *gc-notify-after*
+                  *key-event-history*))
Index: /branches/new-random/cocoa-ide/hemlock/src/defsyn.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/defsyn.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/defsyn.lisp	(revision 13309)
@@ -0,0 +1,196 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains definitions of various character attributes.
+;;;
+(in-package :hemlock)
+
+(defattribute "Whitespace"
+  "A value of 1 for this attribute indicates that the corresponding character
+  should be considered as whitespace.  This is used by the Blank-Line-P
+  function.")
+
+(setf (character-attribute :whitespace #\space) 1)
+(setf (character-attribute :whitespace #\linefeed) 1)
+(setf (character-attribute :whitespace #\tab) 1)
+(setf (character-attribute :whitespace #\newline) 1)
+(setf (character-attribute :whitespace #\return) 1)
+
+(defattribute "Word Delimiter"
+  "A value of 1 for this attribute indicates that the corresponding character
+  separates words.  This is used by the word manipulating commands.")
+
+(setf (character-attribute :word-delimiter nil) 1)
+(setf (character-attribute :word-delimiter #\!) 1)
+(setf (character-attribute :word-delimiter #\@) 1)
+(setf (character-attribute :word-delimiter #\#) 1)
+(setf (character-attribute :word-delimiter #\$) 1)
+(setf (character-attribute :word-delimiter #\%) 1)
+(setf (character-attribute :word-delimiter #\^) 1)
+(setf (character-attribute :word-delimiter #\&) 1)
+(setf (character-attribute :word-delimiter #\*) 1)
+(setf (character-attribute :word-delimiter #\() 1)
+(setf (character-attribute :word-delimiter #\)) 1)
+(setf (character-attribute :word-delimiter #\-) 1)
+(setf (character-attribute :word-delimiter #\_) 1)
+(setf (character-attribute :word-delimiter #\=) 1)
+(setf (character-attribute :word-delimiter #\+) 1)
+(setf (character-attribute :word-delimiter #\[) 1)
+(setf (character-attribute :word-delimiter #\]) 1)
+(setf (character-attribute :word-delimiter #\\) 1)
+(setf (character-attribute :word-delimiter #\|) 1)
+(setf (character-attribute :word-delimiter #\;) 1)
+(setf (character-attribute :word-delimiter #\:) 1)
+(setf (character-attribute :word-delimiter #\') 1)
+(setf (character-attribute :word-delimiter #\") 1)
+(setf (character-attribute :word-delimiter #\{) 1)
+(setf (character-attribute :word-delimiter #\}) 1)
+(setf (character-attribute :word-delimiter #\,) 1)
+(setf (character-attribute :word-delimiter #\.) 1)
+(setf (character-attribute :word-delimiter #\<) 1)
+(setf (character-attribute :word-delimiter #\>) 1)
+(setf (character-attribute :word-delimiter #\/) 1)
+(setf (character-attribute :word-delimiter #\?) 1)
+(setf (character-attribute :word-delimiter #\`) 1)
+(setf (character-attribute :word-delimiter #\~) 1)
+(setf (character-attribute :word-delimiter #\space) 1)
+(setf (character-attribute :word-delimiter #\linefeed) 1)
+(setf (character-attribute :word-delimiter
+                           #+CMU #\formfeed
+                           #+(or EXCL sbcl CLISP Clozure) #\page) 1)
+(setf (character-attribute :word-delimiter #\tab) 1)
+(setf (character-attribute :word-delimiter #\return) 1)
+
+(shadow-attribute :word-delimiter #\. 0 "Fundamental")
+(shadow-attribute :word-delimiter #\' 0 "Text")
+(shadow-attribute :word-delimiter #\backspace 0 "Text")
+(shadow-attribute :word-delimiter #\_ 0 "Text")
+
+;; These aren't generally used to separate words in a Lisp symbol
+(shadow-attribute :word-delimiter #\* 0 "Lisp")
+(shadow-attribute :word-delimiter #\! 0 "Lisp")
+(shadow-attribute :word-delimiter #\$ 0 "Lisp")
+(shadow-attribute :word-delimiter #\+ 0 "Lisp")
+(shadow-attribute :word-delimiter #\% 0 "Lisp")
+(shadow-attribute :word-delimiter #\^ 0 "Lisp")
+(shadow-attribute :word-delimiter #\& 0 "Lisp")
+(shadow-attribute :word-delimiter #\? 0 "Lisp")
+(shadow-attribute :word-delimiter #\_ 0 "Lisp")
+(shadow-attribute :word-delimiter #\= 0 "Lisp")
+(shadow-attribute :word-delimiter #\[ 0 "Lisp")
+(shadow-attribute :word-delimiter #\] 0 "Lisp")
+(shadow-attribute :word-delimiter #\\ 0 "Lisp")
+(shadow-attribute :word-delimiter #\| 0 "Lisp")
+(shadow-attribute :word-delimiter #\{ 0 "Lisp")
+(shadow-attribute :word-delimiter #\} 0 "Lisp")
+(shadow-attribute :word-delimiter #\< 0 "Lisp")
+(shadow-attribute :word-delimiter #\> 0 "Lisp")
+(shadow-attribute :word-delimiter #\/ 0 "Lisp")
+(shadow-attribute :word-delimiter #\~ 0 "Lisp")
+
+
+
+(defattribute "Page Delimiter"
+  "This attribute is 1 for characters that separate pages, 0 otherwise.")
+(setf (character-attribute :page-delimiter nil) 1)
+(setf (character-attribute :page-delimiter #\page) 1)
+
+
+
+(defattribute "Lisp Syntax"
+  "These character attribute is used by the lisp mode commands, and possibly
+  other people.  The value of ths attribute is always a symbol.  Currently
+  defined values are:
+   NIL - No interesting properties.
+   :space - Acts like whitespace, should not include newline.
+   :newline - Newline, man.
+   :open-paren - An opening bracket.
+   :close-paren - A closing bracket.
+   :prefix - A character that is a part of any form it appears before.
+   :prefix-dispatch - a prefix char that converts :symbol-quote to multi-line comment
+   :string-quote - The character that quotes a string.
+   :char-quote - The character that escapes a single character.
+   :symbol-quote - The character that escapes a range of characters
+   :comment - The character that comments out to end of line.
+   :constituent - Things that make up symbols."
+  'symbol nil)
+
+;; Default from lisp readtable.
+(dotimes (i 256)
+ (let ((c (code-char i)))
+  (setf (character-attribute :lisp-syntax c)
+   (case (ccl::%get-readtable-char c ccl::%standard-readtable%)
+    (#.ccl::$cht_wsp :space)
+    (#.ccl::$cht_sesc :char-quote)
+    (#.ccl::$cht_mesc :symbol-quote)
+    (#.ccl::$cht_cnst :constituent)))))
+
+(setf (character-attribute :lisp-syntax #\() :open-paren)
+(setf (character-attribute :lisp-syntax #\)) :close-paren)
+(setf (character-attribute :lisp-syntax #\') :prefix)
+(setf (character-attribute :lisp-syntax #\`) :prefix)
+(setf (character-attribute :lisp-syntax #\,) :prefix)
+(setf (character-attribute :lisp-syntax #\#) :prefix-dispatch)
+(setf (character-attribute :lisp-syntax #\") :string-quote)
+(setf (character-attribute :lisp-syntax #\;) :comment)
+
+(setf (character-attribute :lisp-syntax #\newline) :newline)
+(setf (character-attribute :lisp-syntax nil) :newline)
+
+#|
+(do-alpha-chars (ch :both)
+  (setf (character-attribute :lisp-syntax ch) :constituent))
+
+(setf (character-attribute :lisp-syntax #\0) :constituent)
+(setf (character-attribute :lisp-syntax #\1) :constituent)
+(setf (character-attribute :lisp-syntax #\2) :constituent)
+(setf (character-attribute :lisp-syntax #\3) :constituent)
+(setf (character-attribute :lisp-syntax #\4) :constituent)
+(setf (character-attribute :lisp-syntax #\5) :constituent)
+(setf (character-attribute :lisp-syntax #\6) :constituent)
+(setf (character-attribute :lisp-syntax #\7) :constituent)
+(setf (character-attribute :lisp-syntax #\8) :constituent)
+(setf (character-attribute :lisp-syntax #\9) :constituent)
+
+(setf (character-attribute :lisp-syntax #\!) :constituent)
+(setf (character-attribute :lisp-syntax #\{) :constituent)
+(setf (character-attribute :lisp-syntax #\}) :constituent)
+(setf (character-attribute :lisp-syntax #\[) :constituent)
+(setf (character-attribute :lisp-syntax #\]) :constituent)
+(setf (character-attribute :lisp-syntax #\/) :constituent)
+(setf (character-attribute :lisp-syntax #\@) :constituent)
+(setf (character-attribute :lisp-syntax #\-) :constituent)
+(setf (character-attribute :lisp-syntax #\_) :constituent)
+(setf (character-attribute :lisp-syntax #\+) :constituent)
+(setf (character-attribute :lisp-syntax #\%) :constituent)
+(setf (character-attribute :lisp-syntax #\*) :constituent)
+(setf (character-attribute :lisp-syntax #\$) :constituent)
+(setf (character-attribute :lisp-syntax #\^) :constituent)
+(setf (character-attribute :lisp-syntax #\&) :constituent)
+(setf (character-attribute :lisp-syntax #\~) :constituent)
+(setf (character-attribute :lisp-syntax #\=) :constituent)
+(setf (character-attribute :lisp-syntax #\<) :constituent)
+(setf (character-attribute :lisp-syntax #\>) :constituent)
+(setf (character-attribute :lisp-syntax #\?) :constituent)
+(setf (character-attribute :lisp-syntax #\.) :constituent)
+(setf (character-attribute :lisp-syntax #\:) :constituent)
+|#
+
+(defattribute "Sentence Terminator"
+  "Used for terminating sentences -- ., !, ?.
+   Possibly could make type (mod 3) and use the value of 2 and 1 for spaces
+   to place after chacter."
+  '(mod 2)
+  0)
+
+(setf (character-attribute :sentence-terminator #\.) 1)
+(setf (character-attribute :sentence-terminator #\!) 1)
+(setf (character-attribute :sentence-terminator #\?) 1)
Index: /branches/new-random/cocoa-ide/hemlock/src/doccoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/doccoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/doccoms.lisp	(revision 13309)
@@ -0,0 +1,371 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock Documentation and Help commands.
+;;; Written by Rob MacLachlan and Bill Chiles.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; Help.
+
+(defcommand "Help" (p)
+  "Give helpful information.
+  This command dispatches to a number of other documentation commands,
+  on the basis of a character command."
+  "Prompt for a single character command to dispatch to another helping
+  function."
+  (declare (ignore p))
+  (command-case (:prompt "Doc (Help for Help): "
+		 :help "Type a Help option to say what kind of help you want:")
+    (#\a "List all commands, variables and attributes Apropos a keyword."
+     (apropos-command nil))
+    (#\d "Describe a command, given its name."
+     (describe-command-command nil))
+    (#\g "Generic describe, any Hemlock thing (e.g., variables, keys, attributes)."
+     (generic-describe-command nil))
+    (#\v "Describe variable and show its values."
+     (describe-and-show-variable-command nil))
+    (#\c "Describe the command bound to a Character."
+     (describe-key-command nil))
+    (#\l "List the last 60 characters typed."
+     (what-lossage-command nil))
+    (#\m "Describe a mode."
+     (describe-mode-command nil))
+    ;(#\p "Describe commands with mouse/pointer bindings."
+    ; (describe-pointer-command nil))
+    (#\w "Find out Where a command is bound."
+     (where-is-command nil))
+    (#\t "Describe a Lisp object."
+     (editor-describe-command nil))
+    ((#\q :no) "Quits, You don't really want help.")))
+
+(defcommand "Where Is" (p)
+  "Find what key a command is bound to.
+   Prompts for the command to look for, and says what environment it is
+   available in."
+  "List places where a command is bound."
+  (declare (ignore p))
+  (multiple-value-bind (nam cmd)
+		       (prompt-for-keyword :tables (list *command-names*)
+					   :prompt "Command: "
+					   :help "Name of command to look for.")
+    (let ((bindings (command-bindings cmd)))
+      (with-pop-up-display (s :title (format nil "Bindings of ~s" nam))
+	(cond
+	 ((null bindings)
+	  (format s "~S may only be invoked as an extended command.~%" nam))
+	 (t
+	  (format s "~S may be invoked in the following ways:~%" nam)
+	  (print-command-bindings bindings s)))))))
+
+
+
+
+;;;; Apropos.
+
+(defcommand "Apropos" (p)
+  "List things whose names contain a keyword."
+  "List things whose names contain a keyword."
+  (declare (ignore p))
+  (let* ((str (prompt-for-string
+		:prompt "Apropos keyword: "
+		:help
+ "String to look for in command, variable and attribute names."))
+	 (coms (find-containing str *command-names*))
+	 (vars (mapcar #'(lambda (table)
+			   (let ((res (find-containing str table)))
+			     (if res (cons table res))))
+		       (current-variable-tables)))
+	 (attr (find-containing str *character-attribute-names*)))
+    (if (or coms vars attr)
+      (apropos-command-output str coms vars attr)
+      (message "No command, attribute or variable name contains ~S." str))))
+
+(defun apropos-command-output (str coms vars attr)
+  (declare (list coms vars attr))
+  (with-pop-up-display (s :title "Apropos Output")
+    (when coms
+      (format s "Commands with ~S in their names:~%" str)
+      (dolist (com coms)
+	(let ((obj (getstring com *command-names*)))
+	  (write-string com s)
+	  (write-string "   " s)
+	  (print-command-bindings (command-bindings obj) s)
+	  (terpri s)
+	  (print-doc (command-documentation obj) s))))
+    (when vars
+      (when coms (terpri s))
+      (format s "Variables with ~S in their names:~%" str)
+      (dolist (stuff vars)
+	(let ((table (car stuff)))
+	  (dolist (var (cdr stuff))
+	    (let ((obj (getstring var table)))
+	      (write-string var s)
+	      (write-string "   " s)
+	      (let ((*print-level* 2) (*print-length* 3))
+		(prin1 (variable-value obj) s))
+	      (terpri s)
+	      (print-doc (variable-documentation obj) s))))))
+    (when attr
+      (when (or coms vars) (terpri s))
+      (format s "Attributes with ~S in their names:~%" str)
+      (dolist (att attr)
+	(let ((obj (getstring att *character-attribute-names*)))
+	  (write-line att s)
+	  (print-doc (character-attribute-documentation obj) s))))))
+
+;;; PRINT-DOC takes doc, a function or string, and gets it out on stream.
+
+(defun print-doc (doc stream)
+  (let ((str (typecase doc
+	       (function (funcall doc :short))
+	       (simple-string doc)
+	       (t
+		(error "Bad documentation: ~S" doc)))))
+    (write-string "  " stream)
+    (write-line str stream)))
+
+
+
+
+;;;; Describe command, key, pointer.
+
+(defcommand "Describe Command" (p)
+  "Describe a command.
+  Prompts for a command and then prints out it's full documentation."
+  "Print out the command documentation for a command which is prompted for."
+  (declare (ignore p))
+  (multiple-value-bind (nam com)
+		       (prompt-for-keyword
+			:tables (list *command-names*)
+			:prompt "Describe command: "
+			:help "Name of a command to document.")
+    (let ((bindings (command-bindings com)))
+      (with-pop-up-display (s :title (format nil "~s command documentation" nam))
+	(format s "Documentation for ~S:~%   ~A~%"
+		nam (command-documentation com))
+	(cond ((not bindings)
+	       (write-line
+		"This can only be invoked as an extended command." s))
+	      (t
+	       (write-line
+		"This can be invoked in the following ways:" s)
+	       (write-string "   " s)
+	       (print-command-bindings bindings s)
+	       (terpri s)))))))
+
+(defcommand "Describe Key" (p)
+  "Prompt for a sequence of characters.  When the first character is typed that
+   terminates a key binding in the current context, describe the command bound
+   to it.  When the first character is typed that no longer allows a correct
+   key to be entered, tell the user that this sequence is not bound to
+   anything."
+  "Print out the command documentation for a key
+  which is prompted for."
+  (declare (ignore p))
+  (multiple-value-bind (key res) (prompt-for-key :prompt "Describe key: "
+						 :must-exist t)
+    (cond ((commandp res)
+	   (with-pop-up-display (s :title "Key documentation")
+	     (write-string (pretty-key-string key) s)
+	     (format s " is bound to ~S.~%" (command-name res))
+	     (format s "Documentation for this command:~%   ~A"
+		     (command-documentation res))))
+	  (t
+	   (with-pop-up-display (s :height 1)
+	     (write-string (pretty-key-string key) s)
+	     (write-string " is not bound to anything." s))))))
+
+;;;; Generic describe variable, command, key, attribute.
+
+(defvar *generic-describe-kinds*
+  (list (make-string-table :initial-contents
+			   '(("Variable" . :variable)
+			     ("Command" . :command)
+			     ("Key" . :key)
+			     ("Attribute" . :attribute)))))
+
+(defcommand "Generic Describe" (p)
+  "Describe some Hemlock thing.
+  First prompt for the kind of thing, then prompt for the thing to describe.
+  Currently supported kinds of things are variables, commands, keys and
+  character attributes."
+  "Prompt for some Hemlock thing to describe."
+  (declare (ignore p))
+  (multiple-value-bind (ignore kwd)
+		       (prompt-for-keyword :tables *generic-describe-kinds*
+					   :default "Variable"
+					   :help "Kind of thing to describe."
+					   :prompt "Kind: ")
+    (declare (ignore ignore))
+    (case kwd
+      (:variable
+       (describe-and-show-variable-command nil))
+      (:command (describe-command-command ()))
+      (:key (describe-key-command ()))
+      (:attribute
+       (multiple-value-bind (name attr)
+			    (prompt-for-keyword
+			     :tables (list *character-attribute-names*)
+			     :help "Name of character attribute to describe."
+			     :prompt "Attribute: ")
+	 (print-full-doc name (character-attribute-documentation attr)))))))
+
+;;; PRINT-FULL-DOC displays whole documentation string in a pop-up window.
+;;; Doc may be a function that takes at least one arg, :short or :full.
+;;;
+(defun print-full-doc (nam doc)
+  (typecase doc
+    (function (funcall doc :full))
+    (simple-string
+     (with-pop-up-display (s :title (format nil "~s documentation" nam))
+       (format s "Documentation for ~S:~%  ~A" nam doc)))
+    (t (error "Bad documentation: ~S" doc))))
+
+
+
+
+;;;; Describing and show variables.
+
+(defcommand "Show Variable" (p)
+  "Display the values of a Hemlock variable."
+  "Display the values of a Hemlock variable."
+  (declare (ignore p))
+  (multiple-value-bind (name var)
+		       (prompt-for-variable
+			:help "Name of variable to describe."
+			:prompt "Variable: ")
+    (with-pop-up-display (s :title (format nil "~S Variable documentation" name))
+      (show-variable s name var))))
+
+(defcommand "Describe and Show Variable" (p)
+  "Describe in full and show all of variable's value.
+   Variable is prompted for."
+  "Describe in full and show all of variable's value."
+  (declare (ignore p))
+  (multiple-value-bind (name var)
+		       (prompt-for-variable
+			:help "Name of variable to describe."
+			:prompt "Variable: ")
+    (with-pop-up-display (s :title (format nil "~s" name))
+      (format s "Documentation for ~S:~%  ~A~&~%"
+	      name (variable-documentation var))
+      (show-variable s name var))))
+
+(defun show-variable (s name var)
+  (when (hemlock-bound-p var :global)
+    (format s "Global value of ~S:~%  ~S~%"
+	    name (variable-value var :global)))
+  (let ((buffer (current-buffer)))
+    (when (hemlock-bound-p var :buffer (current-buffer))
+      (format s "Value of ~S in buffer ~A:~%  ~S~%"
+	      name (buffer-name buffer)
+	      (variable-value var :buffer buffer))))
+  (do-strings (mode-name val *mode-names*)
+    (declare (ignore val))
+    (when (hemlock-bound-p var :mode mode-name)
+      (format s "Value of ~S in ~S Mode:~%  ~S~%"
+	      name mode-name
+	      (variable-value var :mode mode-name)))))
+
+
+
+
+;;;; Describing modes.
+
+(defvar *describe-mode-ignore* (list "Illegal" "Do Nothing"))
+
+(defcommand "Describe Mode" (p &optional name)
+  "Describe a mode showing special bindings for that mode."
+  "Describe a mode showing special bindings for that mode."
+  (declare (ignore p))
+  (let ((name (or name
+		  (prompt-for-keyword :tables (list *mode-names*)
+				      :prompt "Mode: "
+				      :help "Enter mode to describe."
+				      :default
+				      (buffer-major-mode (current-buffer))))))
+    (with-pop-up-display (s :title (format nil "~A mode" name))
+      (format s "~A mode description:~%" name)
+      (let ((doc (mode-documentation name)))
+	(when doc
+	  (write-line doc s)
+	  (terpri s)))
+      (map-bindings 
+       #'(lambda (key cmd)
+	   (unless (member (command-name cmd)
+			   *describe-mode-ignore*
+			   :test #'string-equal)
+	     (let ((str (pretty-key-string key)))
+	       (cond ((= (length str) 1)
+		      (write-string str s)
+		      (write-string "  - " s))
+		     (t (write-line str s)
+			(write-string "   - " s)))
+	       (print-doc (command-documentation cmd) s))))
+       :mode name))))
+		    
+;;;; Printing bindings and last N characters typed.
+
+(defcommand "What Lossage" (p)
+  "Display the last 60 characters typed."
+  "Display the last 60 characters typed."
+  (declare (ignore p))
+  (with-pop-up-display (s :title (format nil "The last characters typed") :height 7)
+    (let ((num (ring-length *key-event-history*)))
+      (format s "The last ~D characters typed:~%" num)
+      (do ((i (1- num) (1- i)))
+	  ((minusp i))
+        (write-string (pretty-key-string (ring-ref *key-event-history* i)) s)
+	(write-char #\space s)))))
+
+(defun print-command-bindings (bindings stream)
+  (let ((buffer ())
+	(mode ())
+	(global ()))
+    (dolist (b bindings)
+      (case (second b)
+	(:global (push (first b) global))
+	(:mode
+	 (let ((m (assoc (third b) mode :test #'string=)))
+	   (if m
+	       (push (first b) (cdr m))
+	       (push (list (third b) (first b)) mode))))
+	(t
+	 (let ((f (assoc (third b) buffer)))
+	   (if f
+	       (push (first b) (cdr f))
+	       (push (list (third b) (first b)) buffer))))))
+    (when global
+      (print-some-keys global stream)
+      (write-string "; " stream))
+    (dolist (b buffer)
+      (format stream "Buffer ~S: " (buffer-name (car b)))
+      (print-some-keys (cdr b) stream)
+      (write-string "; " stream))
+    (dolist (m mode)
+      (write-string (car m) stream)
+      (write-string ": " stream)
+      (print-some-keys (cdr m) stream)
+      (write-string "; " stream))))
+
+;;; PRINT-SOME-KEYS prints the list of keys onto Stream.
+;;;
+(defun print-some-keys (keys stream)
+  (do ((key keys (cdr key)))
+      ((null (cdr key))
+       (write-string (pretty-key-string (car key)) stream))
+    (write-string (pretty-key-string (car key)) stream)
+    (write-string ", " stream)))
Index: /branches/new-random/cocoa-ide/hemlock/src/echo.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/echo.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/echo.lisp	(revision 13309)
@@ -0,0 +1,776 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock Echo Area stuff.
+;;; Written by Skef Wholey and Rob MacLachlan.
+;;; Modified by Bill Chiles.
+;;;
+;;; Totally rewritten for Clozure CL.
+
+(in-package :hemlock-internals)
+
+(defmacro modifying-echo-buffer (&body body)
+  `(modifying-buffer-storage ((hemlock-echo-area-buffer *current-view*))
+     ,@body))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;
+;;;; Echo area output.
+
+(defvar *last-message-time* (get-internal-real-time))
+
+(defun clear-echo-area ()
+  "You guessed it."
+  (modifying-echo-buffer
+   (delete-region (buffer-region *current-buffer*))))
+
+;;; Message  --  Public
+;;;
+;;;    Display the stuff on *echo-area-stream* 
+;;;
+(defun message (string &rest args)
+  "Nicely display a message in the echo-area.
+  String and Args are a format control string and format arguments, respectively."
+  ;; TODO: used to do something cleverish if in the middle of reading prompted input, might
+  ;; want to address that.
+  (if *current-view*
+    (let ((message (apply #'format nil string args)))
+      (modifying-echo-buffer
+       (delete-region (buffer-region *current-buffer*))
+       (insert-string (buffer-point *current-buffer*) message)
+       (setq *last-message-time* (get-internal-real-time))
+       ))
+    ;; For some reason this crashes.  Perhaps something is too aggressive about
+    ;; catching conditions in events??
+    #+not-yet(apply #'warn string args)
+    #-not-yet (apply #'format t string args)))
+
+;;; LOUD-MESSAGE -- Public.
+;;;
+;;; Like message, only more provocative.
+;;;
+(defun loud-message (&rest args)
+  "This is the same as MESSAGE, but it beeps and clears the echo area before
+   doing anything else."
+  (beep)
+  (apply #'message args))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Echo area input
+
+(defmode "Echo Area" :major-p t)
+
+
+(defstruct (echo-parse-state (:conc-name "EPS-"))
+  (parse-verification-function nil)
+  (parse-string-tables ())
+  (parse-value-must-exist ())
+  ;; When the user attempts to default a parse, we call the verification function
+  ;; on this string.  This is not the :Default argument to the prompting function,
+  ;; but rather a string representation of it.
+  (parse-default ())
+  ;; String that we show the user to inform him of the default.  If this
+  ;; is NIL then we just use Parse-Default.
+  (parse-default-string ())
+  ;; Prompt for the current parse.
+  (parse-prompt ())
+  ;; Help string for the current parse.
+  (parse-help ())
+  ;; :String, :File or :Keyword.
+  (parse-type :string)
+  ;; input region
+  parse-starting-mark
+  parse-input-region
+  ;; key handler, nil to use the standard one
+  (parse-key-handler nil)
+  ;; Store result here
+  (parse-results ()))
+
+(defun current-echo-parse-state (&key (must-exist t))
+  (or (hemlock-prompted-input-state *current-view*)
+      (and must-exist (error "Can't do that when not in echo area input"))))
+
+
+
+;;;; DISPLAY-PROMPT-NICELY and PARSE-FOR-SOMETHING.
+
+(defun display-prompt-nicely (eps &optional (prompt (eps-parse-prompt eps))
+				            (default (or (eps-parse-default-string eps)
+							 (eps-parse-default eps))))
+  (modifying-echo-buffer 
+   (let* ((buffer *current-buffer*)
+	  (point (buffer-point buffer)))
+     (delete-region (buffer-region buffer))
+     (insert-string point (if (listp prompt)
+			    (apply #'format nil prompt)
+			    prompt))
+     (when default
+       (insert-character point #\[)
+       (insert-string point default)
+       (insert-string point "] "))
+     (move-mark (eps-parse-starting-mark eps) point))))
+
+;; This is used to prevent multiple buffers trying to do echo area input
+;; at the same time - there would be no way to exit the earlier one
+;; without exiting the later one, because they're both on the same stack.
+(defvar *recursive-edit-view* nil)
+
+(defun parse-for-something (&key verification-function
+				 type
+				 string-tables
+				 value-must-exist
+				 default-string
+				 default
+				 prompt
+				 help
+                                 key-handler)
+  ;; We can't do a "recursive" edit in more than one view, because if the earlier
+  ;; one wants to exit first, we'd have to unwind the stack to allow it to exit,
+  ;; which would force the later one to exit whether it wants to or not.
+  (when (and *recursive-edit-view* (not (eq *recursive-edit-view* *current-view*)))
+    (editor-error "~s is already waiting for input"
+		  (buffer-name (hemlock-view-buffer *recursive-edit-view*))))
+  (modifying-echo-buffer
+   (let* ((view *current-view*)
+	  (buffer *current-buffer*)
+	  (old-eps (hemlock-prompted-input-state view))
+	  (parse-mark (copy-mark (buffer-point buffer) :right-inserting))
+	  (end-mark (buffer-end-mark buffer))
+	  (eps (make-echo-parse-state
+		:parse-starting-mark parse-mark
+		:parse-input-region (region parse-mark end-mark)
+		:parse-verification-function verification-function
+		:parse-type type
+		:parse-string-tables string-tables
+		:parse-value-must-exist value-must-exist
+		:parse-default-string default-string
+		:parse-default default
+		:parse-prompt prompt
+		:parse-help help
+                :parse-key-handler key-handler)))
+     ;; TODO: There is really no good reason to disallow recursive edits in the same
+     ;; buffer, I'm just too lazy.  Should save contents, starting mark, and point,
+     ;; and restore them at the end.
+     (when old-eps
+       (editor-error "Attempt to recursively use echo area"))
+     (display-prompt-nicely eps)
+     (modifying-buffer-storage (nil)
+       (unwind-protect
+	    (let ((*recursive-edit-view* view))
+	      (setf (hemlock-prompted-input-state view) eps)
+	      (unless old-eps
+		(hemlock-ext:change-active-pane view :echo))
+	      (with-standard-standard-output
+		  (gui::event-loop #'(lambda () (eps-parse-results eps))))
+	      #+debug (log-debug "~&Event loop exited!, results = ~s" (eps-parse-results eps)))
+	 (unless old-eps
+	   (hemlock-ext:change-active-pane view :text))
+	 (setf (hemlock-prompted-input-state view) old-eps)
+	 (delete-mark parse-mark)))
+     (let ((results (eps-parse-results eps)))
+       (if (listp results)
+	 (apply #'values results)
+	 (abort-to-toplevel))))))
+
+(defun exit-echo-parse (eps results)
+  #+debug (log-debug "~&exit echo parse, results = ~s" results)
+  ;; Must be set to non-nil to indicate parse done.
+  (setf (eps-parse-results eps) (or results '(nil)))
+  (gui::stop-event-loop) ;; this just marks it for dead then returns.
+  ;; this exits current event, and since the event loop is stopped, it
+  ;; will exit the event loop, which will return to parse-for-something,
+  ;; which will notice we have the result set and will handle it accordingly.
+  (exit-event-handler))
+
+;;;; Buffer prompting.
+
+(defun prompt-for-buffer (&key (must-exist t)
+				default
+				default-string
+			       (prompt "Buffer: ")
+			       (help "Type a buffer name."))
+  "Prompts for a buffer name and returns the corresponding buffer.  If
+   :must-exist is nil, then return the input string.  This refuses to accept
+   the empty string as input when no default is supplied.  :default-string
+   may be used to supply a default buffer name even when :default is nil, but
+   when :must-exist is non-nil, :default-string must be the name of an existing
+   buffer."
+  (when (and must-exist
+	     (not default)
+	     (not (getstring default-string *buffer-names*)))
+    (error "Default-string must name an existing buffer when must-exist is non-nil -- ~S."
+	   default-string))
+  (parse-for-something
+   :verification-function #'buffer-verification-function
+   :type :keyword
+   :string-tables (list *buffer-names*)
+   :value-must-exist must-exist
+   :default-string default-string
+   :default (if default (buffer-name default) default-string)
+   :prompt prompt
+   :help help))
+
+(defun buffer-verification-function (eps string)
+  (declare (simple-string string))
+  (modifying-echo-buffer
+   (cond ((string= string "") nil)
+         ((eps-parse-value-must-exist eps)
+          (multiple-value-bind
+              (prefix key value field ambig)
+              (complete-string string (eps-parse-string-tables eps))
+            (declare (ignore field))
+            (ecase key
+              (:none nil)
+              ((:unique :complete)
+               (list value))
+              (:ambiguous
+	       (let ((input-region (eps-parse-input-region eps)))
+		 (delete-region input-region)
+		 (insert-string (region-start input-region) prefix)
+		 (let ((point (current-point)))
+		   (move-mark point (region-start input-region))
+		   (unless (character-offset point ambig)
+		     (buffer-end point)))
+		 nil)))))
+         (t
+          (list (or (getstring string *buffer-names*) string))))))
+
+
+
+
+;;;; File Prompting.
+
+(defun prompt-for-file (&key (must-exist t)
+			     default
+			     default-string
+			     (prompt "Filename: ")
+			     (help "Type a file name."))
+  "Prompts for a filename."
+  (parse-for-something
+   :verification-function #'file-verification-function
+   :type :file
+   :string-tables nil
+   :value-must-exist must-exist
+   :default-string default-string
+   :default (if default (namestring default))
+   :prompt prompt
+   :help help))
+
+(defun file-verification-function (eps string)
+  (let ((pn (pathname-or-lose eps string)))
+    (if pn
+	(let ((merge
+	       (cond ((not (eps-parse-default eps)) nil)
+		     ((ccl:directory-pathname-p pn)
+		      (merge-pathnames pn (eps-parse-default eps)))
+		     (t
+		      (merge-pathnames pn
+				       (or (directory-namestring
+					    (eps-parse-default eps))
+					   ""))))))
+	  (cond ((probe-file pn) (list pn))
+		((and merge (probe-file merge)) (list merge))
+		((not (eps-parse-value-must-exist eps)) (list (or merge pn)))
+		(t nil))))))
+
+;;; PATHNAME-OR-LOSE tries to convert string to a pathname using
+;;; PARSE-NAMESTRING.  If it succeeds, this returns the pathname.  Otherwise,
+;;; this deletes the offending characters from *parse-input-region* and signals
+;;; an editor-error.
+;;;
+(defun pathname-or-lose (eps string)
+  (multiple-value-bind (pn idx)
+		       (parse-namestring string nil *default-pathname-defaults*
+					 :junk-allowed t)
+    (cond (pn)
+	  (t (modifying-echo-buffer
+              (delete-characters (region-end (eps-parse-input-region eps))
+				 (- idx (length string))))
+	     nil))))
+
+
+
+
+;;;; Keyword and variable prompting.
+
+(defun prompt-for-keyword (&key
+			   tables
+			   (must-exist t)
+			   default
+			   default-string
+			   (prompt "Keyword: ")
+			   (help "Type a keyword."))
+  "Prompts for a keyword using the String Tables."
+  (parse-for-something
+   :verification-function #'keyword-verification-function
+   :type :keyword
+   :string-tables tables
+   :value-must-exist must-exist
+   :default-string default-string
+   :default default
+   :prompt prompt
+   :help help))
+
+
+
+(defun prompt-for-variable (&key (must-exist t)
+				 default
+				 default-string
+				 (prompt "Variable: ")
+				 (help "Type the name of a variable."))
+  "Prompts for a variable defined in the current scheme of things."
+  (parse-for-something
+   :verification-function  #'keyword-verification-function
+   :type :keyword
+   :string-tables (current-variable-tables)
+   :value-must-exist must-exist
+   :default-string default-string
+   :default default
+   :prompt prompt
+   :help help))
+
+(defun current-variable-tables ()
+  "Returns a list of all the variable tables currently established globally,
+   by the current buffer, and by any modes for the current buffer."
+  (nconc (list (buffer-variables *current-buffer*))
+         (mapcar #'mode-object-variables (buffer-minor-mode-objects *current-buffer*))
+         (list (mode-object-variables (buffer-major-mode-object *current-buffer*)))
+         (list *global-variable-names*)))
+
+(defun keyword-verification-function (eps string)
+  (declare (simple-string string))
+  (multiple-value-bind
+      (prefix key value field ambig)
+      (complete-string string (eps-parse-string-tables eps))
+    (declare (ignore field))
+    (modifying-echo-buffer
+     (cond ((eps-parse-value-must-exist eps)
+            (ecase key
+              (:none nil)
+              ((:unique :complete)
+               (list prefix value))
+              (:ambiguous
+	       (let ((input-region (eps-parse-input-region eps)))
+		 (delete-region input-region)
+		 (insert-string (region-start input-region) prefix)
+		 (let ((point (current-point)))
+		   (move-mark point (region-start input-region))
+		   (unless (character-offset point ambig)
+		     (buffer-end point)))
+		 nil))))
+           (t
+            ;; HACK: If it doesn't have to exist, and the completion does not
+            ;; add anything, then return the completion's capitalization,
+            ;; instead of the user's input.
+            (list (if (= (length string) (length prefix)) prefix string)))))))
+
+
+
+
+;;;; Integer, expression, and string prompting.
+
+(defun prompt-for-integer (&key (must-exist t)
+				default
+				default-string
+				(prompt "Integer: ")
+				(help "Type an integer."))
+  "Prompt for an integer.  If :must-exist is Nil, then we return as a string
+  whatever was input if it is not a valid integer."
+
+  (parse-for-something
+   :verification-function #'(lambda (eps string)
+			      (let ((number (parse-integer string  :junk-allowed t)))
+				(if (eps-parse-value-must-exist eps)
+				  (if number (list number))
+				  (list (or number string)))))
+   :type :string
+   :string-tables nil
+   :value-must-exist must-exist
+   :default-string default-string
+   :default (if default (write-to-string default :base 10))
+   :prompt prompt
+   :help help))
+
+
+(defvar hemlock-eof '(())
+  "An object that won't be EQ to anything read.")
+
+(defun prompt-for-expression (&key (must-exist t)
+				   (default nil defaultp)
+				   default-string
+				   (prompt "Expression: ")
+				   (help "Type a Lisp expression."))
+  "Prompts for a Lisp expression."
+  (parse-for-something
+   :verification-function #'(lambda (eps string)
+			      (let* ((input-region (eps-parse-input-region eps))
+				     (expr (with-input-from-region (stream input-region)
+					     (handler-case (read stream nil hemlock-eof)
+					       (error () hemlock-eof)))))
+				(if (eq expr hemlock-eof)
+				  (unless (eps-parse-value-must-exist eps) (list string))
+				  (values (list expr) t))))
+   :type :string
+   :string-tables nil
+   :value-must-exist must-exist
+   :default-string default-string
+   :default (if defaultp (prin1-to-string default))
+   :prompt prompt
+   :help help))
+
+
+(defun prompt-for-string (&key default
+			       default-string
+			       (trim ())
+			       (prompt "String: ")
+			       (help "Type a string."))
+  "Prompts for a string.  If :trim is t, then leading and trailing whitespace
+   is removed from input, otherwise it is interpreted as a Char-Bag argument
+   to String-Trim."
+  (when (eq trim t) (setq trim '(#\space #\tab)))
+  (parse-for-something
+   :verification-function #'(lambda (eps string)
+			      (declare (ignore eps))
+			      (list (string-trim trim string)))
+   :type :string
+   :string-tables nil
+   :value-must-exist nil
+   :default-string default-string
+   :default default
+   :prompt prompt
+   :help help))
+
+
+
+;;;; Package names.
+(defun make-package-string-table ()
+  (let ((names ()))
+    (dolist (p (list-all-packages))
+      (let* ((name (package-name p)))
+        (push (cons name name) names)
+        (dolist (nick (package-nicknames p))
+          (push (cons nick name) names))))
+    (make-string-table :initial-contents names)))
+
+#||
+(defun prompt-for-package (&key (must-exist t)
+				(default nil defaultp)
+				default-string
+				(prompt "Package Name:")
+				(help "Type a package name."))
+)
+||#
+
+
+
+;;;; Yes-or-no and y-or-n prompting.
+
+(defvar *yes-or-no-string-table*
+  (make-string-table :initial-contents '(("Yes" . t) ("No" . nil))))
+
+(defun prompt-for-yes-or-no (&key (must-exist t)
+				  (default nil defaultp)
+				  default-string
+				  (prompt "Yes or No? ")
+				  (help "Type Yes or No."))
+  "Prompts for Yes or No."
+  (parse-for-something
+   :verification-function #'(lambda (eps string)
+			      (multiple-value-bind
+				  (prefix key value field ambig)
+				  (complete-string string (eps-parse-string-tables eps))
+				(declare (ignore prefix field ambig))
+				(let ((won (or (eq key :complete) (eq key :unique))))
+				  (if (eps-parse-value-must-exist eps)
+				    (if won (values (list value) t))
+				    (list (if won (values value t) string))))))
+   :type :keyword
+   :string-tables (list *yes-or-no-string-table*)
+   :value-must-exist must-exist
+   :default-string default-string
+   :default (if defaultp (if default "Yes" "No"))
+   :prompt prompt
+   :help help))
+
+(defun prompt-for-y-or-n (&key (must-exist t)
+			       (default nil defaultp)
+			       default-string
+			       (prompt "Y or N? ")
+			       (help "Type Y or N."))
+  "Prompts for Y or N."
+  (parse-for-something
+   :verification-function #'(lambda (eps key-event)
+                              (cond ((logical-key-event-p key-event :y)
+                                     (values (list t) t))
+                                    ((logical-key-event-p key-event :n)
+                                     (values (list nil) t))
+                                    ((and (eps-parse-default eps)
+                                          (logical-key-event-p key-event :confirm))
+                                     (values (list (equalp (eps-parse-default eps) "y")) t))
+                                    ((logical-key-event-p key-event :abort)
+                                     :abort)
+                                    ((logical-key-event-p key-event :help)
+                                     :help)
+                                    (t
+                                     (if (eps-parse-value-must-exist eps)
+                                       :error
+                                       (values (list key-event) t)))))
+   :type :key
+   :value-must-exist must-exist
+   :default-string default-string
+   :default (and defaultp (if default "Y" "N"))
+   :prompt prompt
+   :help help
+   :key-handler (getstring "Key Input Handler" *command-names*)))
+
+
+
+
+;;;; Key-event and key prompting.
+
+(defun prompt-for-key-event (&key (prompt "Key-event: ")
+                                  (help "Type any key"))
+  "Prompts for a key-event."
+  (parse-for-something
+   :verification-function #'(lambda (eps key-event)
+                              (declare (ignore eps))
+                              (values (list key-event) t))
+   :type :key
+   :prompt prompt
+   :help help
+   :key-handler (getstring "Key Input Handler" *command-names*)))
+
+(defun verify-key (eps key-event key quote-p)
+  ;; This is called with the echo buffer as the current buffer.  We want to look
+  ;; up the commands in the main buffer.
+  (let* ((buffer (hemlock-view-buffer (current-view)))
+         (n (length key)))
+    (block nil
+      (unless quote-p
+	(cond ((logical-key-event-p key-event :help)
+	       (return :help))
+	      ((logical-key-event-p key-event :abort)
+	       (return :abort))
+	      ((and (not (eps-parse-value-must-exist eps))
+		    (logical-key-event-p key-event :confirm))
+	       (return
+		 (cond ((eql n 0)
+			(let ((key (eps-parse-default eps))
+			      (cmd (and key (let ((*current-buffer* buffer))
+					      (get-command key :current)))))
+			  (if (commandp cmd)
+			    (values (list key cmd) :confirmed)
+			    :error)))
+		       ((> n 0)
+			(values (list key nil) :confirmed))
+		       (t :error))))))
+      (vector-push-extend key-event key)
+      (let ((cmd (if (eps-parse-value-must-exist eps)
+                   (let ((*current-buffer* buffer)) (get-command key :current))
+                   :prefix)))
+        (cond ((commandp cmd)
+               (values (list key cmd) t))
+              ((eq cmd :prefix)
+               nil)
+              (t
+               (vector-pop key)
+               :error))))))
+
+(defun prompt-for-key (&key (prompt "Key: ")
+                            (help "Type a key.")
+                            default default-string
+                            (must-exist t))
+  (parse-for-something
+   :verification-function (let ((key (make-array 10 :adjustable t :fill-pointer 0))
+				(quote-p nil))
+                            #'(lambda (eps key-event)
+				(if (and (not quote-p) (logical-key-event-p key-event :quote))
+				  (progn
+				    (setq quote-p t)
+				    (values :ignore nil))
+				  (verify-key eps key-event key (shiftf quote-p nil)))))
+   :type :command
+   :prompt prompt
+   :help help
+   :value-must-exist must-exist
+   :default default
+   :default-string default-string
+   :key-handler (getstring "Key Input Handler" *command-names*)))
+
+
+
+;;;; Logical key-event stuff.
+
+(defvar *logical-key-event-names* (make-string-table)
+  "This variable holds a string-table from logical-key-event names to the
+   corresponding keywords.")
+
+(defvar *real-to-logical-key-events* (make-hash-table :test #'eql)
+  "A hashtable from real key-events to their corresponding logical
+   key-event keywords.")
+
+(defvar *logical-key-event-descriptors* (make-hash-table :test #'eq)
+  "A hashtable from logical-key-events to logical-key-event-descriptors.")
+
+(defstruct (logical-key-event-descriptor
+	    (:constructor make-logical-key-event-descriptor ()))
+  name
+  key-events
+  documentation)
+
+;;; LOGICAL-KEY-EVENT-P  --  Public
+;;;
+(defun logical-key-event-p (key-event keyword)
+  "Return true if key-event has been defined to have Keyword as its
+   logical key-event.  The relation between logical and real key-events
+   is defined by using SETF on LOGICAL-KEY-EVENT-P.  If it is set to
+   true then calling LOGICAL-KEY-EVENT-P with the same key-event and
+   Keyword, will result in truth.  Setting to false produces the opposite
+   result.  See DEFINE-LOGICAL-KEY-EVENT and COMMAND-CASE."
+  (not (null (member keyword (gethash key-event *real-to-logical-key-events*)))))
+
+;;; GET-LOGICAL-KEY-EVENT-DESC  --  Internal
+;;;
+;;;    Return the descriptor for the logical key-event keyword, or signal
+;;; an error if it isn't defined.
+;;;
+(defun get-logical-key-event-desc (keyword)
+  (let ((res (gethash keyword *logical-key-event-descriptors*)))
+    (unless res
+      (error "~S is not a defined logical-key-event keyword." keyword))
+    res))
+
+;;; %SET-LOGICAL-KEY-EVENT-P  --  Internal
+;;;
+;;;    Add or remove a logical key-event link by adding to or deleting from
+;;; the list in the from-char hashtable and the descriptor.
+;;;
+(defun %set-logical-key-event-p (key-event keyword new-value)
+  (let ((entry (get-logical-key-event-desc keyword)))
+    (cond
+     (new-value
+      (pushnew keyword (gethash key-event *real-to-logical-key-events*))
+      (pushnew key-event (logical-key-event-descriptor-key-events entry)))
+     (t
+      (setf (gethash key-event *real-to-logical-key-events*)
+	    (delete keyword (gethash key-event *real-to-logical-key-events*)))
+      (setf (logical-key-event-descriptor-key-events entry)
+	    (delete keyword (logical-key-event-descriptor-key-events entry))))))
+  new-value)
+
+;;; LOGICAL-KEY-EVENT-DOCUMENTATION, NAME, KEY-EVENTS  --  Public
+;;;
+;;;    Grab the right field out of the descriptor and return it.
+;;;
+(defun logical-key-event-documentation (keyword)
+  "Return the documentation for the logical key-event Keyword."
+  (logical-key-event-descriptor-documentation
+   (get-logical-key-event-desc keyword)))
+;;;
+(defun logical-key-event-name (keyword)
+  "Return the string name for the logical key-event Keyword."
+  (logical-key-event-descriptor-name (get-logical-key-event-desc keyword)))
+;;;
+(defun logical-key-event-key-events (keyword)
+  "Return the list of key-events for which Keyword is the logical key-event."
+  (logical-key-event-descriptor-key-events
+   (get-logical-key-event-desc keyword)))
+
+;;; DEFINE-LOGICAL-KEY-EVENT  --  Public
+;;;
+;;;    Make the entries in the two hashtables and the string-table.
+;;;
+(defun define-logical-key-event (name documentation)
+  "Define a logical key-event having the specified Name and Documentation.
+  See LOGICAL-KEY-EVENT-P and COMMAND-CASE."
+  (check-type name string)
+  (check-type documentation (or string function))
+  (let* ((keyword (string-to-keyword name))
+	 (entry (or (gethash keyword *logical-key-event-descriptors*)
+		    (setf (gethash keyword *logical-key-event-descriptors*)
+			  (make-logical-key-event-descriptor)))))
+    (setf (logical-key-event-descriptor-name entry) name)
+    (setf (logical-key-event-descriptor-documentation entry) documentation)
+    (setf (getstring name *logical-key-event-names*) keyword)))
+
+
+
+
+;;;; Some standard logical-key-events:
+
+(define-logical-key-event "Abort"
+  "This key-event is used to abort the command in progress.")
+(define-logical-key-event "Yes"
+  "This key-event is used to indicate a positive response.")
+(define-logical-key-event "No"
+  "This key-event is used to indicate a negative response.")
+(define-logical-key-event "Do All"
+  "This key-event means do it as many times as you can.")
+(define-logical-key-event "Do Once"
+  "This key-event means, do it this time, then exit.")
+(define-logical-key-event "Help"
+  "This key-event is used to ask for help.")
+(define-logical-key-event "Confirm"
+  "This key-event is used to confirm some choice.")
+(define-logical-key-event "Quote"
+  "This key-event is used to quote the next key-event of input.")
+(define-logical-key-event "Keep"
+  "This key-event means exit but keep something around.")
+(define-logical-key-event "y"
+  "This key-event is used to indicate a short positive response.")
+(define-logical-key-event "n"
+  "This key-event is used to indicate a short negative response.")
+
+
+
+;;;; COMMAND-CASE help message printing.
+
+(defvar *my-string-output-stream* (make-string-output-stream))
+
+(defun chars-to-string (chars)
+  (do ((s *my-string-output-stream*)
+       (chars chars (cdr chars)))
+      ((null chars)
+       (get-output-stream-string s))
+    (let ((char (car chars)))
+      (if (characterp char)
+	  (write-char char s)
+	  (do ((key-events
+		(logical-key-event-key-events char)
+		(cdr key-events)))
+	      ((null key-events))
+            (write-string (pretty-key-string (car key-events)) s)
+	    (unless (null (cdr key-events))
+	      (write-string ", " s))))
+      (unless (null (cdr chars))
+	(write-string ", " s)))))
+
+;;; COMMAND-CASE-HELP  --  Internal
+;;;
+;;;    Print out a help message derived from the options in a
+;;; random-typeout window.
+;;;
+(defun command-case-help (help options)
+  (let ((help (if (listp help)
+		  (apply #'format nil help) help)))
+    (with-pop-up-display (s :title "Help")
+      (write-string help s)
+      (fresh-line s)
+      (do ((o options (cdr o)))
+	  ((null o))
+	(let ((string (chars-to-string (caar o))))
+	  (declare (simple-string string))
+	  (if (= (length string) 1)
+	      (write-char (char string 0) s)
+	      (write-line string s))
+	  (write-string "  - " s)
+	  (write-line (cdar o) s))))))
Index: /branches/new-random/cocoa-ide/hemlock/src/echocoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/echocoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/echocoms.lisp	(revision 13309)
@@ -0,0 +1,374 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Echo area commands.
+;;;
+;;; Written by Rob MacLachlan and Skef Wholey.
+;;;
+(in-package :hemlock)
+
+(defhvar "Beep on Ambiguity"
+  "If non-NIL, beep when completion of a parse is ambiguous."
+  :value t)
+
+(defhvar "Ignore File Types"
+  "File types to ignore when trying to complete a filename."
+  :value
+  (list "fasl" "cfsl" "dfsl" "cfasl"
+	"pmaxf" "sparcf" "rtf" "hpf" "axpf" "sgif" "err"
+	"x86f" "lbytef"	"core" "trace"	    ; Lisp
+	"BAK" "CKP"			    ; Backups & Checkpoints
+	"PS" "ps" "press" "otl" "dvi" "toc" ; Formatting
+	"bbl" "lof" "idx" "lot" "aux"	    ; Formatting
+	"mo" "elc"			    ; Other editors
+	"bin" "lbin"			    ; Obvious binary extensions.
+	"o" "a" "aout" "out"		    ; UNIXY stuff
+	"bm" "onx" "snf"		    ; X stuff
+	"UU" "uu" "arc" "Z" "gz" "tar"	    ; Binary encoded files
+	))
+
+
+;;; Field separator characters separate fields for TOPS-20 ^F style 
+;;; completion.
+(defattribute "Parse Field Separator"
+  "A value of 1 for this attribute indicates that the corresponding character
+  should be considered to be a field separator by the prompting commands.")
+(setf (character-attribute :parse-field-separator #\space) 1)
+
+
+;;; Find-All-Completions  --  Internal
+;;;
+;;;    Return as a list of all the possible completions of String in the
+;;; list of string-tables Tables.
+;;;
+(defun find-all-completions (string tables)
+  (do ((table tables (cdr table))
+       (res () 
+	    (merge 'list (find-ambiguous string (car table)) 
+		   res #'string-lessp)))
+      ((null table) res)))
+
+(defun get-parse-input-string (eps)
+  (region-to-string (eps-parse-input-region eps)))
+
+(defun replace-parse-input-string (eps string)
+  (delete-region (eps-parse-input-region eps))
+  (insert-string (eps-parse-starting-mark eps) string))
+
+(defcommand "Help on Parse" (p)
+  "Display help for parse in progress.
+  If there are a limited number of options then display them."
+  "Display the *Parse-Help* and any possibly completions of the current
+  input."
+  (declare (ignore p))
+  (let* ((eps (current-echo-parse-state))
+	 (raw-help (eps-parse-help eps))
+	 (help (typecase raw-help
+		 (null (error "There is no parse help."))
+		 (list (apply #'format nil raw-help))
+		 (string raw-help)
+		 (t (error "Parse help is not a string or list: ~S" raw-help))))
+	 (input (get-parse-input-string eps)))
+    (cond
+     ((eq (eps-parse-type eps) :keyword)
+      (let ((strings (find-all-completions input (eps-parse-string-tables eps))))
+	(with-pop-up-display (s :title "input help" :height (+ (length strings) 2))
+	  (write-line help s)
+	  (cond (strings
+		 (write-line "Possible completions of what you have typed:" s)
+		 (dolist (string strings)
+		   (write-line string s)))
+		(t
+		 (write-line "There are no possible completions of what you have typed." s))))))
+     ((and (eq (eps-parse-type eps) :file) (not (zerop (length input))))
+      (let ((pns (ambiguous-files input (eps-parse-default eps))))
+	(declare (list pns))
+	(with-pop-up-display(s :title "Completion help" :height (+ (length pns) 2))
+	  (write-line help s)
+	  (cond (pns
+		 (write-line "Possible completions of what you have typed:" s)
+		 (let ((width 55))
+		   (dolist (pn pns)
+		     (let* ((dir (directory-namestring pn))
+			    (len (length dir)))
+		       (unless (<= len width)
+			 (let ((slash (position #\/ dir
+						:start (+ (- len width) 3))))
+			   (setf dir
+				 (if slash
+				     (concatenate 'string "..."
+						  (subseq dir slash))
+				     "..."))))
+		       (format s " ~A~25T ~A~%"
+			       (file-namestring pn) dir)))))
+		(t
+		 (write-line  "There are no possible completions of what you have typed." s))))))
+     (t
+      (with-pop-up-display (s :title "input help" :height 2)
+	(write-line help s))))))
+
+(defun file-completion-action (eps typein)
+  (declare (simple-string typein))
+  (when (zerop (length typein)) (editor-error))
+  (multiple-value-bind
+      (result win)
+      (complete-file typein
+		     :defaults (directory-namestring (eps-parse-default eps))
+		     :ignore-types (value ignore-file-types))
+    (when result
+      (replace-parse-input-string eps (namestring result)))
+    (when (and (not win) (value beep-on-ambiguity))
+      (editor-error))))
+
+(defcommand "Complete Keyword" (p)
+  "Trys to complete the text being read in the echo area as a string in
+  *parse-string-tables*"
+  "Complete the keyword being parsed as far as possible.
+  If it is ambiguous and ``Beep On Ambiguity'' true beep."
+  (declare (ignore p))
+  (let* ((eps (current-echo-parse-state))
+	 (typein (get-parse-input-string eps)))
+    (declare (simple-string typein))
+    (case (eps-parse-type eps)
+      (:keyword
+       (multiple-value-bind (prefix key value field ambig)
+			    (complete-string typein (eps-parse-string-tables eps))
+	 (declare (ignore value field))
+	 (when prefix
+	   (replace-parse-input-string eps prefix)
+	   (when (eq key :ambiguous)
+	     (let ((point (current-point)))
+	       (move-mark point (eps-parse-starting-mark eps))
+	       (unless (character-offset point ambig)
+		 (buffer-end point)))))
+	 (when (and (or (eq key :ambiguous) (eq key :none))
+		    (value beep-on-ambiguity))
+	   (editor-error))))
+      (:file
+       (file-completion-action eps typein))
+      (t
+       (editor-error "Cannot complete input for this prompt.")))))
+
+(defun field-separator-p (x)
+  (plusp (character-attribute :parse-field-separator x)))
+
+(defcommand "Complete Field" (p)
+  "Complete a field in a parse.
+  Fields are defined by the :field separator attribute,
+  the text being read in the echo area as a string in *parse-string-tables*"
+  "Complete a field in a keyword.
+  If it is ambiguous and ``Beep On Ambiguity'' true beep.  Fields are
+  separated by characters having a non-zero :parse-field-separator attribute,
+  and this command should only be bound to characters having that attribute."
+  (let* ((eps (current-echo-parse-state))
+	 (typein (get-parse-input-string eps)))
+    (declare (simple-string typein))
+    (case (eps-parse-type eps)
+      (:string
+       (self-insert-command p))
+      (:file
+       (file-completion-action eps typein))
+      (:keyword
+       (let ((point (current-point)))
+	 (unless (blank-after-p point)
+	   (insert-character point (last-char-typed))))
+       (multiple-value-bind
+	   (prefix key value field ambig)
+	   (complete-string typein (eps-parse-string-tables eps))
+	 (declare (ignore value ambig))
+	 (when (eq key :none) (editor-error "No possible completion."))
+	 (let ((new-typein (if (and (eq key :unique) (null field))
+			       (subseq prefix 0 field)
+			       (concatenate 'string
+					    (subseq prefix 0 field)
+					    (string (last-char-typed))))))
+	   (replace-parse-input-string eps new-typein))))
+      (t
+       (editor-error "Cannot complete input for this prompt.")))))
+
+
+
+;;; *** TODO: this needs to be view-local
+(defvar *echo-area-history* (make-ring 10)
+  "This ring-buffer contains strings which were previously input in the
+  echo area.")
+
+(defvar *echo-history-pointer* 0
+  "This is our current position to the ring during a historical exploration.")
+
+
+(defcommand "Confirm Parse" (p)
+  "Terminate echo-area input.
+  If the input is invalid then an editor-error will signalled."
+  "If no input has been given, exits the recursive edit with the default,
+  otherwise calls the verification function."
+  (declare (ignore p))
+  (let* ((eps (current-echo-parse-state))
+	 (string (get-parse-input-string eps))
+	 (empty (zerop (length string))))
+    (declare (simple-string string))
+    (if empty
+	(when (eps-parse-default eps) (setq string (eps-parse-default eps)))
+	(when (or (zerop (ring-length *echo-area-history*))
+		  (string/= string (ring-ref *echo-area-history* 0)))
+	  (ring-push string *echo-area-history*)))
+    (multiple-value-bind (vals flag)
+			 (funcall (eps-parse-verification-function eps) eps string)
+      ;; flag is to distinguish vals=() to return 0 values vs vals=nil because invalid.
+      (unless (or vals flag) (editor-error))
+      (exit-echo-parse eps vals))))
+
+(defcommand "Previous Parse" (p)
+  "Rotate the echo-area history forward.
+  If current input is non-empty and different from what is on the top
+  of the ring then push it on the ring before inserting the new input."
+  "Pop the *echo-area-history* ring buffer."
+  (let* ((eps (current-echo-parse-state))
+	 (length (ring-length *echo-area-history*))
+	 (p (or p 1)))
+    (when (zerop length) (editor-error))
+    (cond
+     ((eq (last-command-type) :echo-history)
+      (let ((base (mod (+ *echo-history-pointer* p) length)))
+	(replace-parse-input-string eps (ring-ref *echo-area-history* base))
+	(setq *echo-history-pointer* base)))
+     (t
+      (let ((current (get-parse-input-string eps))
+	    (base (mod (if (minusp p) p (1- p)) length)))
+	(replace-parse-input-string eps (ring-ref *echo-area-history* base))
+	(when (and (plusp (length current))
+		   (string/= (ring-ref *echo-area-history* 0) current))
+	  (ring-push current *echo-area-history*)
+	  (incf base))
+	(setq *echo-history-pointer* base))))
+    (setf (last-command-type) :echo-history)))
+
+(defcommand "Next Parse" (p)
+  "Rotate the echo-area history backward.
+  If current input is non-empty and different from what is on the top
+  of the ring then push it on the ring before inserting the new input."
+  "Push the *echo-area-history* ring buffer."
+  (previous-parse-command (- (or p 1))))
+
+
+(defcommand "Illegal" (p)
+  "This signals an editor-error.
+  It is useful for making commands locally unbound."
+  "Just signals an editor-error."
+  (declare (ignore p))
+  (editor-error))
+
+(defcommand "Beginning Of Parse" (p)
+  "Moves to immediately after the prompt when in the echo area."
+  "Move the point of the echo area buffer to *parse-starting-mark*."
+  (declare (ignore p))
+  (let* ((eps (current-echo-parse-state))
+	 (start (eps-parse-starting-mark eps)))
+    (move-mark (current-point) start)))
+
+(defcommand "Echo Area Delete Previous Character" (p)
+  "Delete the previous character, up to the prompt."
+  (let* ((eps (current-echo-parse-state))
+	 (start (eps-parse-starting-mark eps)))
+    (with-mark ((tem (current-point)))
+      (unless (character-offset tem (- (or p 1))) (editor-error))
+      (when (mark< tem start) (editor-error))
+      (delete-previous-character-command p))))
+
+(defcommand "Echo Area Kill Previous Word" (p)
+  "Kill the previous word, up to the prompt."
+  (let* ((eps (current-echo-parse-state))
+	 (start (eps-parse-starting-mark eps)))
+    (with-mark ((tem (current-point)))
+      (unless (word-offset tem (- (or p 1))) (editor-error))
+      (when (mark< tem start) (editor-error))
+      (kill-previous-word-command p))))
+
+(declaim (special *kill-ring*))
+
+(defcommand "Kill Parse" (p)
+  "Kills any input so far."
+  "Kills *parse-input-region*."
+  (declare (ignore p))
+  (let* ((eps (current-echo-parse-state)))
+    (if (end-line-p (current-point))
+      (kill-region (eps-parse-input-region eps) :kill-backward)
+      (ring-push (delete-and-save-region (eps-parse-input-region eps))
+		 *kill-ring*))))
+
+(defcommand "Insert Parse Default" (p)
+  "Inserts the default for the parse in progress.
+  The text is inserted at the point."
+  (declare (ignore p))
+  (let* ((eps (current-echo-parse-state))
+	 (default (eps-parse-default eps)))
+    (unless default (editor-error))
+    (insert-string (current-point) default)))
+
+(defcommand "Echo Area Backward Character" (p)
+  "Go back one character.
+   Don't let the luser move into the prompt."
+  "Signal an editor-error if we try to go into the prompt, otherwise
+   do a backward-character command."
+  (let* ((eps (current-echo-parse-state))
+	 (start (eps-parse-starting-mark eps))
+	 (point (current-point)))
+    (when (mark<= point start)
+      (editor-error))
+    (backward-character-command p)
+    (when (mark< point start)
+      (beginning-of-parse-command nil))))
+
+(defcommand "Echo Area Backward Word" (p)
+  "Go back one word.
+  Don't let the luser move into the prompt."
+  "Signal an editor-error if we try to go into the prompt, otherwise
+  do a backward-word command."
+  (let* ((eps (current-echo-parse-state))
+	 (start (eps-parse-starting-mark eps))
+	 (point (current-point)))
+    (when (mark<= point start)
+      (editor-error))
+    (backward-word-command p)
+    (when (mark< point start)
+      (beginning-of-parse-command nil))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+
+(defun append-key-name (key-event)
+  (let ((point (current-point)))
+    (insert-string point (pretty-key-string key-event t))
+    (insert-character point #\Space)))
+
+(defcommand "Key Input Handler" (p)
+  "Internal command to handle input during y-or-n or key-event prompting"
+  (declare (ignore p))
+  (let* ((eps (current-echo-parse-state))
+         (key-event (last-key-event-typed)))
+    (multiple-value-bind (res exit-p)
+                         (funcall (eps-parse-verification-function eps) eps key-event)
+      #+debug (log-debug "Key Input Hander: res: ~s exit-p ~s" res exit-p)
+      (cond (exit-p
+	     (unless (eq exit-p :confirmed)
+	       (append-key-name key-event))
+             (exit-echo-parse eps res))
+            ((eq res :abort)
+             (abort-to-toplevel))
+            ((eq res :help)
+             (help-on-parse-command nil))
+            ((eq res :error)
+             (beep))
+	    ((eq res :ignore)
+	     nil)
+	    (t
+	     (append-key-name key-event))))))
+
Index: /branches/new-random/cocoa-ide/hemlock/src/edit-defs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/edit-defs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/edit-defs.lisp	(revision 13309)
@@ -0,0 +1,417 @@
+;;; -*- Log: hemlock.log; Package: hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Editing DEFMACRO and DEFUN definitions.  Also, has directory translation
+;;; code for moved and/or different sources.
+;;;
+
+(in-package :hemlock)
+
+
+;;; Definition Editing Commands.
+
+
+
+;;; For the "Go to Definition" search pattern, we just use " " as the initial
+;;; pattern, so we can make a search pattern.  Invocation of the command alters
+;;; the search pattern.
+
+(defvar *go-to-def-pattern*
+  (new-search-pattern :string-insensitive :forward " "))
+
+(defvar *last-go-to-def-string* "")
+(declaim (simple-string *last-go-to-def-string*))
+  
+(defun symbol-at-point (buffer point)
+  "Returns symbol at point, or contents of selection if there is one"
+  (with-mark ((mark1 point)
+	      (mark2 point))
+    (if (hi::%buffer-current-region-p buffer)
+	(let* ((mark (hi::buffer-%mark buffer)))
+	  (if (mark< mark point)
+              (move-mark mark1 mark)
+              (move-mark mark2 mark)))
+	;; This doesn't handle embedded #'s or escaped chars in names.
+	;; So let them report it as a bug...
+	(progn
+	  (when (test-char (previous-character point) :lisp-syntax :constituent)
+	    (or (rev-scan-char mark1 :lisp-syntax (not :constituent))
+		(buffer-start mark1))
+	    (scan-char mark1 :lisp-syntax :constituent))
+	  (when (test-char (next-character point) :lisp-syntax :constituent)
+	    (or (scan-char mark2 :lisp-syntax (not :constituent))
+		(buffer-end mark2)))
+	  (when (mark= mark1 mark2)
+	    ;; Try to get whole form
+	    (pre-command-parse-check point)
+            (move-mark mark1 point)
+            (form-offset mark1 -1)
+            (move-mark mark2 mark1)
+            (form-offset mark2 1))))
+    (unless (mark= mark1 mark2)
+      (region-to-string (region mark1 mark2)))))
+
+(defcommand "Goto Definition" (p)
+  "Go to the current function/macro's definition.  With a numarg, prompts for name to go to."
+  (if p
+      (edit-definition-command nil)
+      (let* ((point (current-point))
+	     (buffer (current-buffer))
+	     (fun-name (symbol-at-point buffer point)))
+	(if fun-name
+	    (get-def-info-and-go-to-it fun-name (or
+						 (buffer-package (current-buffer))
+						 *package*))
+	    (beep)))))
+
+(defcommand "Edit Definition" (p)
+  "Prompts for function/macro's definition name and goes to it for editing."
+  (declare (ignore p))
+  (let ((fun-name (prompt-for-string
+		   :prompt "Name: "
+		   :help "Symbol name of function.")))
+    (get-def-info-and-go-to-it fun-name (or
+                                         (buffer-package (current-buffer))
+                                         *package*))))
+
+(defun get-def-info-and-go-to-it (string package)
+  (multiple-value-bind (fun-name error)
+      (let* ((*package* (ccl:require-type package 'package)))
+        (ignore-errors (values (read-from-string string))))
+    (if error
+      (editor-error "unreadable name: ~s" string)
+      (handler-case (edit-definition fun-name)
+        (error (c) (editor-error "~a" c))))))
+
+(defcommand "Edit Command Definition" (p)
+  "Prompts for command definition name and goes to it for editing."
+  (multiple-value-bind
+      (name command)
+      (if p
+        (multiple-value-bind (key cmd)
+                             (prompt-for-key :prompt "Edit command bound to: "
+                                             :must-exist t)
+          (declare (ignore key))
+          (values (command-name cmd) cmd))
+        (prompt-for-keyword :tables (list *command-names*)
+                            :prompt "Command to edit: "))
+    (declare (ignore name))
+    (handler-case (edit-definition (command-function command))
+      (error (c) (editor-error "~a" c)))))
+
+#|
+;;; FUN-DEFINED-FROM-PATHNAME takes a symbol or function object.  It
+;;; returns a pathname for the file the function was defined in.  If it was
+;;; not defined in some file, then nil is returned.
+;;; 
+(defun fun-defined-from-pathname (function)
+  "Takes a symbol or function and returns the pathname for the file the
+   function was defined in.  If it was not defined in some file, nil is
+   returned."
+  (flet ((true-namestring (path) (namestring (truename path))))
+    (typecase function
+      (function (fun-defined-from-pathname (ccl:function-name function)))
+      (symbol (let* ((info (ccl::%source-files function)))
+                (if (atom info)
+                  (true-namestring info)
+                  (let* ((finfo (assq 'function info)))
+                    (when finfo
+                      (true-namestring
+                       (if (atom finfo)
+                         finfo
+                         (car finfo)))))))))))
+
+;;; GO-TO-DEFINITION tries to find name in file with a search pattern based
+;;; on type (defun or defmacro).  File may be translated to another source
+;;; file, and if type is a function that cannot be found, we try to find a
+;;; command by an appropriate name.
+;;; 
+(defun go-to-definition (file type name)
+  (let ((pattern (get-definition-pattern type name)))
+    (cond
+     (file
+      (setf file (go-to-definition-file file))
+      (let* ((buffer (old-find-file-command nil file))
+	     (point (buffer-point buffer))
+	     (name-len (length name)))
+	(declare (fixnum name-len))
+	(with-mark ((def-mark point))
+	  (buffer-start def-mark)
+	  (unless (find-pattern def-mark pattern)
+	    (if (and (or (eq type :function) (eq type :unknown-function))
+		     (> name-len 7)
+		     (string= name "COMMAND" :start1 (- name-len 7)))
+		(let ((prev-search-str *last-go-to-def-string*))
+		  (unless (find-pattern def-mark
+					(get-definition-pattern :command name))
+		    (editor-error "~A is not defined with ~S or ~S, ~
+				   but this is the defined-in file."
+				  (string-upcase name) prev-search-str
+				  *last-go-to-def-string*)))
+		(editor-error "~A is not defined with ~S, ~
+			       but this is the defined-in file."
+			      (string-upcase name) *last-go-to-def-string*)))
+	  (if (eq buffer (current-buffer))
+	      (push-new-buffer-mark point))
+	  (move-mark point def-mark))))
+     (t
+      (when (or (eq type :unknown-function) (eq type :unknown-macro))
+	(with-mark ((m (buffer-start-mark (current-buffer))))
+	  (unless (find-pattern m pattern)
+	    (editor-error
+	     "~A is not compiled and not defined in current buffer with ~S"
+	     (string-upcase name) *last-go-to-def-string*))
+	  (let ((point (current-point)))
+	    (push-new-buffer-mark point)
+	    (move-mark point m))))))))
+|#
+
+(defparameter *type-defining-operators* ())
+
+(defun define-type-defining-operators (name &rest operators)
+  (assert (subtypep name 'ccl::definition-type))
+  (let ((a (assoc name *type-defining-operators*)))
+    (when (null a)
+      (push (setq a (cons name nil)) *type-defining-operators*))
+    (loop for op in operators do (pushnew op (cdr a)))
+    name))
+
+(defun type-defining-operator-p (def-type operator)
+  (loop for (type . ops) in *type-defining-operators*
+    thereis (and (typep def-type type) (memq operator ops))))
+
+(define-type-defining-operators 'ccl::class-definition-type 'defclass)
+(define-type-defining-operators 'ccl::type-definition-type 'deftype)
+(define-type-defining-operators 'ccl::function-definition-type 'defun 'defmacro 'defgeneric #+x8664-target 'ccl::defx86lapfunction #+ppc-target 'ccl::defppclapfunction)
+(define-type-defining-operators 'ccl::constant-definition-type 'defconstant)
+(define-type-defining-operators 'ccl::variable-definition-type 'defvar 'defparameter 'ccl::defstatic 'ccl::defglobal)
+(define-type-defining-operators 'ccl::method-combination-definition-type 'define-method-combination)
+(define-type-defining-operators 'ccl::compiler-macro-definition-type 'define-compiler-macro)
+
+
+(defun match-definition-context-for-method (end-mark package indicator)
+  (let* ((specializers (openmcl-mop:method-specializers indicator))
+         (qualifiers (openmcl-mop:method-qualifiers indicator)))
+    (block win
+      (with-mark ((work end-mark))
+        (when qualifiers
+          (dotimes (i (length qualifiers))
+            (unless (and (form-offset end-mark 1)
+                         (progn
+                           (move-mark work end-mark)
+                           (form-offset work -1)))
+              (return-from win nil))
+            (let* ((qualifier (ignore-errors
+                                (let* ((*package* package))
+                                  (values
+                                   (read-from-string (region-to-string
+                                                      (region
+                                                       work
+                                                       end-mark))))))))
+              (unless (member qualifier qualifiers)
+                (return-from win nil)))))
+        ;; end-mark is now either at end of last qualifier or
+        ;; after method name.  Try to read the lambda list and
+        ;; match specializers.
+        (unless (and (form-offset end-mark 1)
+                     (progn
+                       (move-mark work end-mark)
+                       (form-offset work -1)))
+          (return-from win nil))
+        (multiple-value-bind (lambda-list error)
+            (ignore-errors
+              (let* ((*package* package))
+                (values
+                 (read-from-string (region-to-string
+                                    (region
+                                     work
+                                     end-mark))))))
+          (unless (and (null error)
+                       (consp lambda-list)
+                       (ccl::proper-list-p lambda-list))
+            (return-from win nil))
+          (flet ((match-specializer (spec)
+                   (when lambda-list
+                     (let* ((arg (pop lambda-list)))
+                       (typecase spec
+                         (ccl::eql-specializer
+                          (let* ((obj (openmcl-mop:eql-specializer-object spec)))
+                            (and (ccl::proper-list-p arg)
+                                 (= 2 (length arg))
+                                 (symbolp (pop arg))
+                                 (ccl::proper-list-p (setq arg (car arg)))
+                                 (= (length arg) 2)
+                                 (eq (car arg) 'eql)
+                                 (eql (cadr arg) obj))))
+                         (class
+                          (let* ((name (class-name spec)))
+                            (or (and (eq name t) (symbolp arg))
+                                (and (consp arg)
+                                     (symbolp (car arg))
+                                     (consp (cdr arg))
+                                     (null (cddr arg))
+                                     (eq name (cadr arg)))))))))))
+            (dolist (spec specializers t)
+              (unless (match-specializer spec)
+                (return nil)))))))))
+                                 
+;;; START and END delimit a function name that matches what we're looking for
+(defun match-context-for-indicator (start end def-type full-name)
+  (with-mark ((op-start start)
+              (op-end start))
+    (and (form-offset op-start -1)
+         (progn
+           (move-mark op-end op-start)
+           (form-offset op-end 1))
+         (let* ((package (or (find-package (variable-value 'current-package :buffer (current-buffer)))
+                             *package*))
+                (defining-operator
+                    (ignore-errors
+                      (let* ((*package* package))
+                        (values (read-from-string (region-to-string (region op-start op-end))))))))
+           (and (type-defining-operator-p def-type defining-operator)
+                (or (not (typep full-name 'method))
+                    (match-definition-context-for-method end package full-name)))))))
+
+(defun match-definition-context (mark def-type full-name)
+  (pre-command-parse-check mark)
+  (when (valid-spot mark t)
+    (with-mark ((start mark)
+                (end mark))
+      (and (form-offset end 1)
+           (progn
+             (move-mark start end)
+             (form-offset start -1))
+           (let ((package (or (find-package (variable-value 'current-package :buffer (current-buffer)))
+                              *package*)))
+             (eq (ccl::definition-base-name def-type full-name)
+                 (ignore-errors
+                  (let* ((*package* package))
+                    (values (read-from-string (region-to-string (region start end))))))))
+           (match-context-for-indicator start end def-type full-name)))))
+
+(defun find-definition-by-context (def-type full-name)
+  (let* ((base-name (ccl::definition-base-name def-type full-name))
+	 (string (string base-name))
+         (pattern (new-search-pattern :string-insensitive :forward string))
+         (found 0))
+    (with-mark ((mark (buffer-start-mark (current-buffer))))
+      (when (or (loop
+                  while (and (find-pattern mark pattern) (incf found))
+                  thereis (and (match-definition-context mark def-type full-name)
+                               (backward-up-list mark))
+                  do (character-offset mark 1))
+                ;; if there is only one instance, just go there
+                (and (eql found 1) (find-pattern (buffer-start mark) pattern))
+                ;; Else should try again, being less strict...
+                )
+        (move-point-leaving-mark mark)))))
+
+(defun move-point-leaving-mark (target)
+  (let ((point (current-point-collapsing-selection)))
+    (push-new-buffer-mark point)
+    (move-mark point target)
+    point))
+
+(defun move-to-source-note (source)
+  (let ((start-pos (ccl:source-note-start-pos source)))
+    (when start-pos
+      (let ((full-text (ccl:source-note-text source))
+            (pattern nil)
+            (offset 0))
+        (flet ((search (mark string direction)
+                 (find-pattern mark
+                               (setq pattern (new-search-pattern :string-insensitive
+                                                                 direction
+                                                                 string
+                                                                 pattern)))))
+          (declare (inline search))
+          (with-mark ((temp-mark (current-point)))
+            (unless full-text
+              ;; Someday, might only store a snippet for toplevel, so inner notes
+              ;; might not have text, but can still find them through the toplevel.
+              (let* ((toplevel (ccl::source-note-toplevel-note source))
+                     (toplevel-start-pos (and (not (eq toplevel source))
+                                              (ccl:source-note-start-pos toplevel)))
+                     (text (and toplevel-start-pos (ccl:source-note-text toplevel))))
+                (when text
+                  (setq offset (- start-pos toplevel-start-pos))
+                  (setq start-pos toplevel-start-pos)
+                  (setq full-text text)
+                  (character-offset temp-mark (- offset)))))
+            (unless (move-to-absolute-position temp-mark start-pos)
+              (buffer-end temp-mark))
+
+            (when (or (null full-text)
+                      (or (search temp-mark full-text :forward)
+                          (search temp-mark full-text :backward))
+                      ;; Maybe body changed, try at least to match the start of it
+                      (let ((snippet (and (> (length full-text) 60) (subseq full-text 0 60))))
+                        (and snippet
+                             (or (search temp-mark snippet :forward)
+                                 (search temp-mark snippet :backward)))))
+              (let ((point (move-point-leaving-mark temp-mark)))
+                (or (character-offset point offset)
+                    (buffer-end point))))))))))
+
+(defun find-definition-in-buffer (def-type full-name source)
+  (or (and (ccl:source-note-p source)
+           (move-to-source-note source))
+      (find-definition-by-context def-type full-name)
+      (editor-error "Couldn't find definition for ~s" full-name)))
+
+;; Note this isn't necessarily called from hemlock, e.g. it might be called by cl:ed,
+;; from any thread, or it might be called from a sequence dialog, etc.
+(defun edit-definition (name)
+  (flet ((get-source-alist (name)
+           (let ((list (ccl:find-definition-sources name t)))
+             ;; filter interactive-only defs
+             (loop for (id . sources) in list as source = (find-if-not #'null sources)
+               when source collect (cons id source))))
+         (defn-name (defn stream)
+           (destructuring-bind (dt . full-name) (car defn)
+             (format stream "~s ~s" (ccl:definition-type-name dt) (ccl:name-of full-name))))
+         (defn-action (defn &optional msg)
+           (destructuring-bind ((def-type . full-name) . source) defn
+             (hemlock-ext:execute-in-file-view
+              (ccl:source-note-filename source)
+              (lambda ()
+                (when msg (loud-message msg))
+                (find-definition-in-buffer def-type full-name source))))))
+    (let* ((info (get-source-alist name))
+           (msg nil))
+      (when (and (null info) (symbolp name))
+        (let* ((seen (list name))
+               (found ())
+               (pname (symbol-name name)))
+          (dolist (pkg (list-all-packages))
+            (let ((sym (find-symbol pname pkg)))
+              (when (and sym (not (member sym seen :test 'eq)))
+                (let ((new (get-source-alist sym)))
+                  (when new
+                    (setq info (nconc new info))
+                    (push sym found)))
+                (push sym seen))))
+          (when found
+            (setq msg (format nil "No definitions for ~s, found ~s instead"
+                              name (if (cdr found) found (car found)))))))
+      (if info
+        (if (cdr info)
+          (progn
+            (when msg (loud-message msg))
+            (hemlock-ext:open-sequence-dialog
+             :title (format nil "Definitions of ~s" name)
+             :sequence info
+             :action #'defn-action
+             :printer #'defn-name))
+          (defn-action (car info) msg))
+        (editor-error "No known definitions for ~s" name)))))
+
Index: /branches/new-random/cocoa-ide/hemlock/src/filecoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/filecoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/filecoms.lisp	(revision 13309)
@@ -0,0 +1,678 @@
+;;; -*- Package: Hemlock; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains file/buffer manipulating commands.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; PROCESS-FILE-OPTIONS.
+
+(defvar *mode-option-handlers* ()
+  "Do not modify this; use Define-File-Option instead.")
+
+(defvar *file-type-hooks* ()
+  "Do not modify this; use Define-File-Type-Hook instead.")  
+
+(defun trim-subseq (string start end)
+  (declare (simple-string string))
+  (string-trim '(#\Space #\Tab) (subseq string start end)))
+
+;;; PROCESS-FILE-OPTIONS checks the first line of buffer for the file options
+;;; indicator "-*-".  IF it finds this, then it enters a do-file-options block.
+;;; If any parsing errors occur while picking out options, we return from this
+;;; block.  Staying inside this function at this point, allows us to still set
+;;; a major mode if no file option specified one.
+;;;
+;;; We also cater to old style mode comments:
+;;;    -*- Lisp -*-
+;;;    -*- Text -*-
+;;; This kicks in if we find no colon on the file options line.
+;;;
+(defun process-file-options (&optional (buffer (current-buffer))
+                                       (pathname (buffer-pathname buffer)))
+  "Checks for file options and invokes handlers if there are any.  If no
+   \"Mode\" mode option is specified, then this tries to invoke the appropriate
+   file type hook."
+  (let* ((string
+	  (line-string (mark-line (buffer-start-mark buffer))))
+	 (found (search "-*-" string))
+	 (no-major-mode t)
+	 (type (if pathname (pathname-type pathname))))
+    (declare (simple-string string))
+    (when found
+      (block do-file-options
+	(let* ((start (+ found 3))
+	       (end (search "-*-" string :start2 start)))
+	  (unless end
+	    (loud-message "No closing \"-*-\".  Aborting file options.")
+	    (return-from do-file-options))
+	  (cond
+	   ((find #\: string :start start :end end)
+	    (do ((opt-start start (1+ semi)) colon semi)
+		(nil)
+	      (setq colon (position #\: string :start opt-start :end end))
+	      (unless colon
+		(loud-message "Missing \":\".  Aborting file options.")
+		(return-from do-file-options))
+	      (setq semi (or (position #\; string :start colon :end end) end))
+	      (let* ((option (nstring-downcase
+			      (trim-subseq string opt-start colon)))
+		     (handler (assoc option *mode-option-handlers*
+				     :test #'string=)))
+		(declare (simple-string option))
+		(cond
+		 (handler
+		  (let ((result (funcall (cdr handler) buffer
+					 (trim-subseq string (1+ colon) semi))))
+		    (when (string= option "mode")
+		      (setq no-major-mode (not result)))))
+		 (t (message "Unknown file option: ~S" option)))
+		(when (= semi end) (return nil)))))
+	   (t
+	    ;; Old style mode comment.
+	    (setq no-major-mode nil)
+	    (funcall (cdr (assoc "mode" *mode-option-handlers* :test #'string=))
+		     buffer (trim-subseq string start end)))))))
+    (when (and no-major-mode type)
+      (let ((hook (assoc (string-downcase type) *file-type-hooks*
+			 :test #'string=)))
+	(when hook (funcall (cdr hook) buffer type))))))
+
+
+
+
+;;;; File options and file type hooks.
+
+(defmacro define-file-option (name lambda-list &body body)
+  "Define-File-Option Name (Buffer Value) {Form}*
+   Defines a new file option to be user in the -*- line at the top of a file.
+   The body is evaluated with Buffer bound to the buffer the file has been read
+   into and Value to the string argument to the option."
+  (let ((name (string-downcase name)))
+    `(setf (cdr (or (assoc ,name *mode-option-handlers*  :test #'string=)
+		    (car (push (cons ,name nil) *mode-option-handlers*))))
+	   #'(lambda ,lambda-list ,@body))))
+
+(define-file-option "Mode" (buffer str)
+  (let ((seen-major-mode-p nil)
+	(lastpos 0))
+    (loop
+      (let* ((pos (position #\, str :start lastpos))
+	     (substr (trim-subseq str lastpos pos)))
+	(cond ((getstring substr *mode-names*)
+	       (cond ((mode-major-p substr)
+		      (when seen-major-mode-p
+			(loud-message
+			 "Major mode already processed. Using ~S now."
+			 substr))
+		      (setf seen-major-mode-p t)
+		      (setf (buffer-major-mode buffer) substr))
+		     (t
+ 		      (setf (buffer-minor-mode buffer substr) t))))
+	      (t
+	       (loud-message "~S is not a defined mode -- ignored." substr)))
+	(unless pos
+	  (return seen-major-mode-p))
+	(setf lastpos (1+ pos))))))
+
+(define-file-option "log" (buffer string)
+  (declare (ignore buffer string)))
+
+
+
+(defmacro define-file-type-hook (type-list (buffer type) &body body)
+  "Define-File-Type-Hook ({Type}*) (Buffer Type) {Form}*
+  Define some code to be evaluated when a file having one of the specified
+  Types is read by a file command.  Buffer is bound to the buffer the
+  file is in, and Type is the actual type read."
+  (let ((fun (gensym)) (str (gensym)))
+    `(flet ((,fun (,buffer ,type) ,@body))
+       (dolist (,str ',(mapcar #'string-downcase type-list))
+	 (setf (cdr (or (assoc ,str *file-type-hooks*  :test #'string=)
+			(car (push (cons ,str nil) *file-type-hooks*))))
+	       #',fun)))))
+
+(define-file-type-hook ("pas" "pasmac" "macro" "defs" "spc" "bdy")
+  		       (buffer type)
+  (declare (ignore type))
+  (setf (buffer-major-mode buffer) "Pascal"))
+
+(define-file-type-hook ("lisp" "slisp" "l" "lsp" "mcl" "cl") (buffer type)
+  (declare (ignore type))
+  (setf (buffer-major-mode buffer) "Lisp"))
+
+(define-file-type-hook ("txt" "text" "tx") (buffer type)
+  (declare (ignore type))
+  (setf (buffer-major-mode buffer) "Text"))
+
+
+
+
+;;;; Support for file hacking commands:
+
+(defhvar "Pathname Defaults"
+  "This variable contains a pathname which is used to supply defaults
+   when we don't have anything better."
+  :value (pathname "gazonk.del"))
+
+(defhvar "Last Resort Pathname Defaults"
+  "This variable contains a pathname which is used to supply defaults when
+   we don't have anything better, but unlike \"Pathname Defaults\", this is
+   never set to some buffer's pathname."
+  :value (pathname "gazonk"))
+
+(defhvar "Last Resort Pathname Defaults Function"
+  "This variable contains a function that is called when a default pathname is
+   needed, the buffer has no pathname, and the buffer's name is not entirely
+   composed of alphanumerics.  The default value is a function that simply
+   returns \"Last Resort Pathname Defaults\".  The function must take a buffer
+   as an argument, and it must return some pathname."
+  :value #'(lambda (buffer)
+	     (declare (ignore buffer))
+	     (merge-pathnames (value last-resort-pathname-defaults)
+			      (value pathname-defaults))))
+
+(defun buffer-default-pathname (buffer)
+  "Returns \"Buffer Pathname\" if it is bound.  If it is not, and buffer's name
+   is composed solely of alphnumeric characters, then return a pathname formed
+   from the buffer's name.  If the buffer's name has other characters in it,
+   then return the value of \"Last Resort Pathname Defaults Function\" called
+   on buffer."
+  (or (buffer-pathname buffer)
+      (if (every #'alphanumericp (the simple-string (buffer-name buffer)))
+	  (merge-pathnames (make-pathname :name (buffer-name buffer))
+			   (value pathname-defaults))
+	  (funcall (value last-resort-pathname-defaults-function) buffer))))
+
+
+(defun pathname-to-buffer-name (pathname)
+  "Returns a simple-string using components from pathname."
+  (let ((pathname (pathname pathname)))
+    (concatenate 'simple-string
+		 (file-namestring pathname)
+		 " "
+		 (directory-namestring pathname))))
+
+
+
+
+;;;; File hacking commands.
+
+(defcommand "Process File Options" (p)
+  "Reprocess this buffer's file options."
+  "Reprocess this buffer's file options."
+  (declare (ignore p))
+  (process-file-options))
+
+(defcommand "Ensure File Options Line" (p)
+  "Insert a default file options line at the beginning of the buffer, unless such a line already exists."
+  "Insert a default file options line at the beginning of the buffer, unless such a line already exists."
+  (declare (ignore p))
+  (let* ((buffer (current-buffer))
+	 (string
+	  (line-string (mark-line (buffer-start-mark buffer))))
+	 (found (search "-*-" string))
+	 (end (if found (search "-*-" string :start2 (+ found 3)))))
+    (unless end
+      (let* ((mode (buffer-major-mode buffer)))
+	(unless mode
+	  ;; Try to derive the buffer's major mode from its pathname's
+	  ;; type.
+	  (let* ((pathname (buffer-pathname buffer))
+		 (type (if pathname (pathname-type pathname)))
+		 (hook (if type
+			 (assoc (string-downcase type) *file-type-hooks*
+				:test #'string=))))
+	    (when hook
+	      (funcall (cdr hook) buffer type)
+	      (setq mode (buffer-major-mode buffer)))))
+	(with-mark ((mark (buffer-start-mark buffer) :left-inserting))
+	  (if (string-equal mode "Lisp")
+	    (let* ((package-name
+		    (if (hemlock-bound-p 'current-package :buffer buffer)
+		      (variable-value 'hemlock::current-package
+				      :buffer buffer)
+		      "CL-USER")))
+	      (insert-string
+	       mark
+	       (format nil ";;; -*- Mode: Lisp; Package: ~a -*-" package-name)))
+	    (insert-string
+	     mark
+	     (format nil ";;; -*- Mode: ~a -*-" (or mode "Fundamental"))))
+	  (insert-character mark #\NewLine))))
+    (buffer-start (buffer-point buffer))))
+    
+    
+			 
+			   
+	    
+	
+	    
+	    
+	  
+		 
+	
+  
+
+(defcommand "Insert File" (p &optional pathname (buffer (current-buffer)))
+  "Inserts a file which is prompted for into the current buffer at the point.
+  The prefix argument is ignored."
+  "Inserts the file named by Pathname into Buffer at the point."
+  (declare (ignore p))
+  (let* ((pn (or pathname
+		 (prompt-for-file :default (buffer-default-pathname buffer)
+				  :prompt "Insert File: "
+				  :help "Name of file to insert")))
+	 (point (buffer-point buffer))
+	 ;; start and end will be deleted by undo stuff
+	 (start (copy-mark point :right-inserting))
+	 (end (copy-mark point :left-inserting))
+	 (region (region start end)))
+    (setv pathname-defaults pn)
+    (push-new-buffer-mark end)
+    (read-file pn end)
+    (make-region-undo :delete "Insert File" region)))
+
+(defcommand "Write Region" (p &optional pathname)
+  "Writes the current region to a file. "
+  "Writes the current region to a file. "
+  (declare (ignore p))
+  (let ((region (current-region))
+	(pn (or pathname
+		(prompt-for-file :prompt "File to Write: "
+				 :help "The name of the file to write the region to. "
+				 :default (buffer-default-pathname
+					   (current-buffer))
+				 :must-exist nil))))
+    (write-file region pn)
+    (message "~A written." (namestring (truename pn)))))
+
+
+
+
+;;;; Visiting and reverting files.
+
+#+No  ;; Dubious semantics in a document-centered model. Also, doesn't work, see bug #476.
+(defcommand "Visit File" (p &optional pathname (buffer (current-buffer)))
+  "Replaces the contents of Buffer with the file Pathname.  The prefix
+   argument is ignored.  The buffer is set to be writable, so its region
+   can be deleted."
+  "Replaces the contents of the current buffer with the text in the file
+   which is prompted for.  The prefix argument is, of course, ignored p times."
+  (declare (ignore p))
+  (when (and (buffer-modified buffer)
+	     (prompt-for-y-or-n :prompt "Buffer is modified, save it? "))
+    (save-file-command () buffer))
+  (let ((pn (or pathname
+		(prompt-for-file :prompt "Visit File: "
+				 :must-exist nil
+				 :help "Name of file to visit."
+				 :default (buffer-default-pathname buffer)))))
+    (setf (buffer-writable buffer) t)
+    (read-buffer-file pn buffer)
+    (let ((n (pathname-to-buffer-name (buffer-pathname buffer))))
+      (unless (getstring n *buffer-names*)
+	(setf (buffer-name buffer) n))
+      (warn-about-visit-file-buffers buffer))))
+
+(defun warn-about-visit-file-buffers (buffer)
+  (let ((buffer-pn (buffer-pathname buffer)))
+    (dolist (b *buffer-list*)
+      (unless (eq b buffer)
+	(let ((bpn (buffer-pathname b)))
+	  (when (equal bpn buffer-pn)
+	    (loud-message "Buffer ~A also contains ~A."
+			  (buffer-name b) (namestring buffer-pn))
+	    (return)))))))
+
+
+(defhvar "Revert File Confirm"
+  "If this is true, Revert File will prompt before reverting."
+  :value t)
+
+(defcommand "Revert File" (p)
+  "Unless in Save Mode, reads in the last saved version of the file in
+   the current buffer. When in Save Mode, reads in the last checkpoint or
+   the last saved version, whichever is more recent. An argument will always
+   force Revert File to use the last saved version. In either case, if the
+   buffer has been modified and \"Revert File Confirm\" is true, then Revert
+   File will ask for confirmation beforehand. An attempt is made to maintain
+   the point's relative position."
+  "With an argument reverts to the last saved version of the file in the
+   current buffer. Without, reverts to the last checkpoint or last saved
+   version, whichever is more recent."
+  (declare (ignore p))
+  (hemlock-ext:revert-hemlock-buffer (current-buffer))
+  (clear-echo-area))
+
+
+;;;; Find file.
+
+
+(defcommand "Find File" (p)
+  "Visit a file in its own buffer.
+   If the file is already in some buffer, select that buffer,
+   otherwise make a new buffer with the same name as the file and
+   read the file into it."
+  (declare (ignore p))
+  (hi::allowing-buffer-display ((current-buffer))
+    (hemlock-ext:open-hemlock-buffer :pathname :prompt)))
+  
+
+#|
+(defun find-file-buffer (pathname)
+  "Return a buffer associated with the file Pathname, reading the file into a
+   new buffer if necessary.  The second value is T if we created a buffer, NIL
+   otherwise.  If the file has already been read, we check to see if the file
+   has been modified on disk since it was read, giving the user various
+   recovery options."
+  (let* ((pathname (pathname pathname))
+	 (trial-pathname (or (probe-file pathname)
+			     (merge-pathnames pathname (default-directory))))
+	 (found (find trial-pathname (the list *buffer-list*)
+		     :key #'buffer-pathname :test #'equal)))
+    (cond ((not found)
+           (if (and (null (pathname-name trial-pathname))
+                    (null (pathname-type trial-pathname))
+                    (pathname-directory trial-pathname))
+               ;; This looks like a directory -- make dired buffer
+               (dired-guts nil nil trial-pathname)
+
+               (let* ((name (pathname-to-buffer-name trial-pathname))
+                      (found (getstring name *buffer-names*))
+                      (use (if found
+                               (prompt-for-buffer
+                                :prompt "Buffer to use: "
+                                :help
+                                "Buffer name in use; give another buffer name, or confirm to reuse."
+                                :default found
+                                :must-exist nil)
+                               (make-buffer name)))
+                      (buffer (if (stringp use) (make-buffer use) use)))
+                 (when (and (buffer-modified buffer)
+                            (prompt-for-y-or-n :prompt
+                                               "Buffer is modified, save it? "))
+                   (save-file-command () buffer))
+                 (read-buffer-file pathname buffer)
+                 (values buffer (stringp use)))))
+	  ((check-disk-version-consistent pathname found)
+	   (values found nil))
+	  (t
+	   (read-buffer-file pathname found)
+	   (values found nil)))))
+|#
+
+;;; Check-Disk-Version-Consistent  --  Internal
+;;;
+;;;    Check that Buffer contains a valid version of the file Pathname,
+;;; harrassing the user if not.  We return true if the buffer is O.K., and
+;;; false if the file should be read. 
+;;;
+(defun check-disk-version-consistent (pathname buffer)
+  (let ((ndate (file-write-date pathname))
+	(odate (buffer-write-date buffer)))
+    (cond ((not (and ndate odate (/= ndate odate)))
+	   t)
+	  ((buffer-modified buffer)
+	   (beep)
+	   (clear-input)
+	   (command-case (:prompt (list
+ "File has been changed on disk since it was read and you have made changes too!~
+ ~%Read in the disk version of ~A? [Y] " (namestring pathname))
+			  :help
+ "The file in disk has been changed since Hemlock last saved it, meaning that
+ someone else has probably overwritten it.  Since the version read into Hemlock
+ has been changed as well, the two versions may have inconsistent changes.  If
+ this is the case, it would be a good idea to save your changes in another file
+ and compare the two versions.
+ 
+ Type one of the following commands:")
+	     ((:confirm :yes)
+ "Prompt for a file to write the buffer out to, then read in the disk version."
+	      (write-buffer-file
+	       buffer
+	       (prompt-for-file
+		:prompt "File to save changes in: "
+		:help (list "Save buffer ~S to this file before reading ~A."
+			    (buffer-name buffer) (namestring pathname))
+		:must-exist nil
+		:default (buffer-default-pathname buffer)))
+	      nil)
+	     (:no
+	      "Change to the buffer without reading the new version."
+	      t)
+	     (#\r
+	      "Read in the new version, clobbering the changes in the buffer."
+	      nil)))
+	   (t
+	    (not (prompt-for-yes-or-no :prompt
+				       (list
+ "File has been changed on disk since it was read.~
+ ~%Read in the disk version of ~A? "
+					(namestring pathname))
+				       :help
+ "Type Y to read in the new version or N to just switch to the buffer."
+				       :default t))))))
+
+
+(defhvar "Read File Hook"
+  "These functions are called when a file is read into a buffer.  Each function
+   must take two arguments -- the buffer the file was read into and whether the
+   file existed (non-nil) or not (nil).")
+
+(defun read-buffer-file (pathname buffer)
+  "Delete the buffer's region, and uses READ-FILE to read pathname into it.
+   If the file exists, set the buffer's write date to the file's; otherwise,
+   MESSAGE that this is a new file and set the buffer's write date to nil.
+   Move buffer's point to the beginning, set the buffer unmodified.  If the
+   file exists, set the buffer's pathname to the probed pathname; else, set it
+   to pathname merged with DEFAULT-DIRECTORY.  Set \"Pathname Defaults\" to the
+   same thing.  Process the file options, and then invoke \"Read File Hook\"."
+  (setf (buffer-writable buffer) t)
+  (delete-region (buffer-region buffer))
+  (let* ((pathname (pathname pathname))
+	 (probed-pathname (probe-file pathname))
+         (hi::*current-buffer* buffer))
+    (cond (probed-pathname
+	   (read-file probed-pathname (buffer-point buffer))
+	   (setf (buffer-write-date buffer) (file-write-date probed-pathname)))
+	  (t
+	   (message "(New File)")
+	   (setf (buffer-write-date buffer) nil)))
+    (buffer-start (buffer-point buffer))
+    (setf (buffer-modified buffer) nil)
+    (let ((stored-pathname (or probed-pathname
+			       (merge-pathnames pathname (default-directory)))))
+      (setf (buffer-pathname buffer) stored-pathname)
+      (setf (value pathname-defaults) stored-pathname)
+      (process-file-options buffer stored-pathname)
+      (invoke-hook read-file-hook buffer probed-pathname))))
+
+
+
+
+;;;; File writing.
+
+(defhvar "Add Newline at EOF on Writing File"
+  "This controls whether WRITE-BUFFER-FILE adds a newline at the end of the
+   file when it ends at the end of a non-empty line.  When set, this may be
+   :ask-user and WRITE-BUFFER-FILE will prompt; otherwise, just add one and
+   inform the user.  When nil, never add one and don't ask."
+  :value :ask-user)
+
+(defhvar "Keep Backup Files"
+  "When set, .BAK files will be saved upon file writing.  This defaults to nil."
+  :value nil)
+
+(defhvar "Write File Hook"
+  "These functions are called when a buffer has been written.  Each function
+   must take the buffer as an argument.")
+
+(defun write-buffer-file (buffer pathname)
+  "Write's buffer to pathname.  This assumes pathname is somehow related to
+   the buffer's pathname, and if the buffer's write date is not the same as
+   pathname's, then this prompts the user for confirmation before overwriting
+   the file.  This consults \"Add Newline at EOF on Writing File\" and
+   interacts with the user if necessary.  This sets \"Pathname Defaults\", and
+   the buffer is marked unmodified.  The buffer's pathname and write date are
+   updated, and the buffer is renamed according to the new pathname if possible.
+   This invokes \"Write File Hook\"."
+  (let ((buffer-pn (buffer-pathname buffer)))
+    (let ((date (buffer-write-date buffer))
+	  (file-date (when (probe-file pathname) (file-write-date pathname))))
+      (when (and buffer-pn date file-date
+		 (equal (make-pathname :version nil :defaults buffer-pn)
+			(make-pathname :version nil :defaults pathname))
+		 (/= date file-date))
+	(unless (prompt-for-yes-or-no :prompt (list
+ "File has been changed on disk since it was read.~%Overwrite ~A anyway? "
+ (namestring buffer-pn))
+				      :help
+				      "Type No to abort writing the file or Yes to overwrite the disk version."
+				      :default nil)
+	  (editor-error "Write aborted."))))
+    (let ((val (value add-newline-at-eof-on-writing-file)))
+      (when val
+	(let ((end (buffer-end-mark buffer)))
+	  (unless (start-line-p end)
+	    (when (if (eq val :ask-user)
+		      (prompt-for-y-or-n
+		       :prompt
+		       (list "~A~%File does not have a newline at EOF, add one? "
+			     (buffer-name buffer))
+		       :default t)
+		      t)
+	      (insert-character end #\newline)
+	      (message "Added newline at EOF."))))))
+    (setv pathname-defaults pathname)
+    (write-file (buffer-region buffer) pathname)
+    (let ((tn (truename pathname)))
+      (message "~A written." (namestring tn))
+      (setf (buffer-modified buffer) nil)
+      (unless (equal tn buffer-pn)
+	(setf (buffer-pathname buffer) tn))
+      (setf (buffer-write-date buffer) (file-write-date tn))
+      (let ((name (pathname-to-buffer-name tn)))
+	(unless (getstring name *buffer-names*)
+	  (setf (buffer-name buffer) name)))))
+  (invoke-hook write-file-hook buffer))
+ 
+(defcommand "Write File" (p &optional (buffer (current-buffer)))
+  "Prompts for a filename, changes the buffer pathname to it and saves it.
+  The prefix argument is ignored."
+  (declare (ignore p))
+  (hemlock-ext:save-hemlock-buffer buffer :pathname :prompt))
+
+(defcommand "Save To File" (p &optional (buffer (current-buffer)))
+  "Prompts for a filename and writes a copy of the buffer to it.  Buffer's
+   pathname (and modified state) is unchanged.
+  The prefix argument is ignored."
+  (declare (ignore p))
+  (hemlock-ext:save-hemlock-buffer buffer :pathname :prompt :copy t))
+
+(defcommand "Save File" (p &optional (buffer (current-buffer)))
+  "Writes the contents of the current buffer to the associated file.  If there
+  is no associated file, one is prompted for."
+  "Writes the contents of the current buffer to the associated file."
+  (declare (ignore p))
+  (when (buffer-modified buffer)
+    (hemlock-ext:save-hemlock-buffer buffer)))
+
+(defhvar "Save All Files Confirm"
+  "When non-nil, prompts for confirmation before writing each modified buffer."
+  :value t)
+
+(defcommand "Save All Files" (p)
+  "Saves all modified buffers in their associated files.
+  If a buffer has no associated file it is ignored even if it is modified.."
+  "Saves each modified buffer that has a file."
+  (declare (ignore p))
+  (let ((saved-count 0))
+    (dolist (b *buffer-list*)
+      (let ((pn (buffer-pathname b))
+	    (name (buffer-name b)))
+	(when
+	    (and (buffer-modified b)
+		 pn
+		 (or (not (value save-all-files-confirm))
+		     (prompt-for-y-or-n
+		      :prompt (list
+			       "Write ~:[buffer ~A as file ~S~;file ~*~S~], ~
+			       Y or N: "
+			       (string= (pathname-to-buffer-name pn) name)
+			       name (namestring pn))
+		      :default t)))
+	  (write-buffer-file b pn)
+	  (incf saved-count))))
+    (if (zerop saved-count)
+	(message "No files were saved.")
+	(message "Saved ~S file~:P." saved-count))))
+
+(defcommand "Backup File" (p)
+  "Write the buffer to a file without changing the associated name."
+  "Write the buffer to a file without changing the associated name."
+  (declare (ignore p))
+  (let ((file (prompt-for-file :prompt "Backup to File: "
+			       :help
+ "Name of a file to backup the current buffer in."
+			       :default (buffer-default-pathname (current-buffer))
+			       :must-exist nil)))
+    (write-file (buffer-region (current-buffer)) file)
+    (message "~A written." (namestring (truename file)))))
+
+
+
+
+;;;; Buffer hacking commands:
+
+
+(defcommand "Buffer Not Modified" (p)
+  "Make the current buffer not modified."
+  "Make the current buffer not modified."
+  (declare (ignore p))
+  (setf (buffer-modified (current-buffer)) nil)
+  (message "Buffer marked as unmodified."))
+
+
+
+(defcommand "Set Buffer Read-Only" (p)
+  "Toggles the read-only flag for the current buffer."
+  "Toggles the read-only flag for the current buffer."
+  (declare (ignore p))
+  (let ((buffer (current-buffer)))
+    (message "Buffer ~S is now ~:[read-only~;writable~]."
+	     (buffer-name buffer)
+	     (setf (buffer-writable buffer) (not (buffer-writable buffer))))))
+
+(defcommand "Set Buffer Writable" (p)
+  "Make the current buffer modifiable."
+  "Make the current buffer modifiable."
+  (declare (ignore p))
+  (let ((buffer (current-buffer)))
+    (setf (buffer-writable buffer) t)
+    (message "Buffer ~S is now writable." (buffer-name buffer))))
+
+
+
+
+(defun universal-time-to-string (ut)
+  (multiple-value-bind (sec min hour day month year)
+		       (decode-universal-time ut)
+    (format nil "~2,'0D-~A-~2,'0D ~2,'0D:~2,'0D:~2,'0D"
+	    day (svref '#("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug"
+			  "Sep" "Oct" "Nov" "Dec")
+		       (1- month))
+	    (rem year 100)
+	    hour min sec)))
Index: /branches/new-random/cocoa-ide/hemlock/src/files.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/files.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/files.lisp	(revision 13309)
@@ -0,0 +1,115 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock File manipulation functions.
+;;; Written by Skef Wholey, Horribly Hacked by Rob MacLachlan.
+;;; Unhacked by Gilbert Baumann.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Utility functions.
+
+;; FIND-CHAR-FROM-SAP was here, deleted --GB
+
+
+
+;;; Read-File:
+
+(defun read-file (pathname mark)
+  "Inserts the contents of the file named by Pathname at the Mark."
+  (with-mark ((mark mark :left-inserting))
+    (let* ((first-line (mark-line mark))
+           (buffer (line-%buffer first-line)))
+      (modifying-buffer buffer)
+      (with-open-file (input pathname :direction :input :element-type 'character)
+        (do ((line (read-line input nil :eof) (read-line input nil :eof)))
+            ((eql line :eof))
+	  (insert-string mark line)
+          (insert-character mark #\newline))))))
+
+
+
+;;; Write-File:
+
+(defun write-file (region pathname &key append
+			  (keep-backup (value hemlock::keep-backup-files))
+			  access)
+  "Writes the characters in region to the file named by pathname.  This writes
+   region using a stream opened with :if-exists :rename-and-delete, unless
+   either append or keep-backup is supplied.  If append is supplied, this
+   writes the file opened with :if-exists :append.  If keep-backup is supplied,
+   this writes the file opened with :if-exists :rename.  This signals an error
+   if both append and keep-backup are supplied.  Access is an implementation
+   dependent value that is suitable for setting pathname's access or protection
+   bits."
+  (declare (ignorable access))
+  (let ((if-exists-action (cond ((and keep-backup append)
+				 (error "Cannot supply non-nil values for ~
+				         both keep-backup and append."))
+				(keep-backup :rename)
+				(append :append)
+				(t :rename-and-delete))))
+    (with-open-file (file pathname :direction :output
+			  :element-type 'base-char
+			  :if-exists if-exists-action)
+      (close-line)
+      (fast-write-file region file))
+    ;; ### access is always ignored
+    #+NIL
+    (when access
+      (multiple-value-bind
+	  (winp code)
+	  ;; Must do a TRUENAME in case the file has never been written.
+	  ;; It may have Common Lisp syntax that Unix can't handle.
+	  ;; If this is ever moved to the beginning of this function to use
+	  ;; Unix CREAT to create the file protected initially, they TRUENAME
+	  ;; will signal an error, and LISP::PREDICT-NAME will have to be used.
+	  (unix:unix-chmod (namestring (truename pathname)) access)
+	(unless winp
+	  (error "Could not set access code: ~S"
+		 (unix:get-unix-error-msg code)))))))
+
+(defun fast-write-file (region file)
+  (let* ((start (region-start region))
+	 (start-line (mark-line start))
+	 (start-charpos (mark-charpos start))
+	 (end (region-end region))
+	 (end-line (mark-line end))
+	 (end-charpos (mark-charpos end)))
+    (if (eq start-line end-line)
+        ;; just one line (fragment)
+        (write-string (line-chars start-line) file
+                      :start start-charpos :end end-charpos)
+        ;; multiple lines
+        (let* ((first-length (- (line-length start-line) start-charpos))
+               (length (+ first-length end-charpos 1)))
+          ;; count number of octets to be written
+          (do ((line (line-next start-line) (line-next line)))
+              ((eq line end-line))
+            (incf length (1+ (line-length line))))
+          ;;
+          (macrolet ((chars (line)
+                       `(line-%chars ,line)))
+            (write-sequence (chars start-line) file :start start-charpos :end (+ start-charpos first-length))
+            (write-char #\newline file)
+            (let ((offset (1+ first-length)))
+              (do ((line (line-next start-line)
+                         (line-next line)))
+                  ((eq line end-line))
+                (let ((end (+ offset (line-length line))))
+                  (write-sequence (chars line) file :start 0 :end (- end offset))
+                  (write-char #\newline file)      
+                  (setf offset (1+ end))))
+              (unless (zerop end-charpos)
+                (write-sequence (chars end-line) file :start 0 :end end-charpos))))))))
Index: /branches/new-random/cocoa-ide/hemlock/src/fill.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/fill.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/fill.lisp	(revision 13309)
@@ -0,0 +1,738 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;
+;;; This file contains the implementation of Auto Fill Mode.  Also,
+;;;   paragraph and region filling stuff is here.
+;;;
+
+(in-package :hemlock)
+
+
+;;; Fill Mode should be defined with some transparent bindings (linefeed and
+;;; return) but with some that are not (space), so until this is possible, we
+;;; kludge this effect by altering Auto Fill Linefeed and Auto Fill Return.
+(defmode "Fill")
+
+
+
+;;;; -- Variables --
+
+(defhvar "Fill Column"
+  "Used to determine at what column to force text to the next line."
+  :value 75)
+
+(defhvar "Fill Prefix"
+  "String to put before each line when filling."
+  :value ())
+
+(defhvar "Auto Fill Space Indent"
+  "When non-nil, uses \"Indent New Comment Line\" to break lines instead of
+   \"New Line\".  However, if there is a fill prefix, it is still preferred."
+  :value nil)
+
+
+
+;;;; -- New Attributes --
+
+(defattribute "Paragraph Delimiter"
+  "is a character that delimits a paragraph by beginning a line."
+  '(mod 2)
+  0)
+
+
+;;; (setf (character-attribute :paragraph-delimiter #\@) 1)
+;;; (setf (character-attribute :paragraph-delimiter #\\) 1)
+;;; (setf (character-attribute :paragraph-delimiter #\/) 1)
+;;; (setf (character-attribute :paragraph-delimiter #\-) 1)
+;;; (setf (character-attribute :paragraph-delimiter #\') 1)
+;;; (setf (character-attribute :paragraph-delimiter #\.) 1)
+;;;    These are useful for making certain text formatting command lines
+;;; delimit paragraphs.  Anyway, this is what EMACS documentation states,
+;;; and #\' and #\. are always paragraph delimiters (don't ask me).
+
+(setf (character-attribute :paragraph-delimiter #\space) 1)
+(setf (character-attribute :paragraph-delimiter #\linefeed) 1)
+(setf (character-attribute :paragraph-delimiter
+			   #+CMU #\formfeed #+(or sbcl EXCL CLISP Clozure) #\page) 1)
+(setf (character-attribute :paragraph-delimiter #\tab) 1)
+(setf (character-attribute :paragraph-delimiter #\newline) 1)
+
+
+
+(defattribute "Sentence Closing Char"
+  "is a delimiting character that may follow a sentence terminator
+   such as quotation marks and parentheses."
+  '(mod 2)
+  0)
+
+
+(setf (character-attribute :sentence-closing-char #\") 1)
+(setf (character-attribute :sentence-closing-char #\') 1)
+(setf (character-attribute :sentence-closing-char #\)) 1)
+(setf (character-attribute :sentence-closing-char #\]) 1)
+(setf (character-attribute :sentence-closing-char #\|) 1)
+(setf (character-attribute :sentence-closing-char #\>) 1)
+
+
+;;;; -- Commands --
+
+(defcommand "Auto Fill Mode" (p)
+  "Breaks lines between words at the right margin.
+   A positive argument turns Fill mode on, while zero or a negative
+   argument turns it off.  With no arguments, it is toggled.  When space
+   is typed, text that extends past the right margin is put on the next
+   line.  The right column is controlled by Fill Column."
+  "Determine if in Fill mode or not and set the mode accordingly."
+  (setf (buffer-minor-mode (current-buffer) "Fill")
+	(if p
+	    (plusp p)
+	    (not (buffer-minor-mode (current-buffer) "Fill")))))
+
+
+;;; This command should not have a transparent binding since it sometimes does
+;;; not insert a spaces, and transparency would propagate to "Self Insert".
+(defcommand "Auto Fill Space" (p)
+  "Insert space and a CRLF if text extends past margin.
+   If arg is 0, then may break line but will not insert the space.
+   If arg is positive, then inserts that many spaces without filling."
+  "Insert space and CRLF if text extends past margin.
+   If arg is 0, then may break line but will not insert the space.
+   If arg is positive, then inserts that many spaces without filling."
+  (let ((point (current-point)))
+    (check-fill-prefix (value fill-prefix) (value fill-column) point)
+    (cond ((and p (plusp p))
+	   (dotimes (x p) (insert-character point #\space)))
+	  ((and p (zerop p)) (%auto-fill-space point nil))
+	  (t (%auto-fill-space point t)))))
+
+
+(defcommand "Auto Fill Linefeed" (p)
+  "Does an immediate CRLF inserting Fill Prefix if it exists."
+  "Does an immediate CRLF inserting Fill Prefix if it exists."
+  (let ((point (current-point)))
+    (check-fill-prefix (value fill-prefix) (value fill-column) point)
+    (%auto-fill-space point nil)
+    ;; The remainder of this function should go away when
+    ;; transparent key bindings are per binding instead of
+    ;; per mode.
+    (multiple-value-bind (command t-bindings)
+			 (get-command #k"Linefeed" :current)
+      (declare (ignore command)) ;command is this one, so don't invoke it
+      (dolist (c t-bindings) (invoke-command c p)))
+    (indent-new-line-command nil)))
+
+
+
+(defcommand "Auto Fill Return" (p)
+  "Does an Auto Fill Space with a prefix argument of 0
+   followed by a newline."
+  "Does an Auto Fill Space with a prefix argument of 0
+   followed by a newline."
+  (let ((point (current-point)))
+    (check-fill-prefix (value fill-prefix) (value fill-column) point)
+    (%auto-fill-space point nil)
+    ;; The remainder of this function should go away when
+    ;; transparent key bindings are per binding instead of
+    ;; per mode.
+    (multiple-value-bind (command t-bindings)
+			 (get-command #k"Return" :current)
+      (declare (ignore command)) ;command is this one, so don't invoke it
+      (dolist (c t-bindings) (invoke-command c p)))
+    (new-line-command nil)))
+
+
+
+(defcommand "Fill Paragraph" (p)
+  "Fill this or next paragraph.
+   Point stays fixed, but text may move past it due to filling.
+   A paragraph is delimited by a blank line, a line beginning with a
+   special character (@,\,-,',and .), or it is begun with a line with at
+   least one whitespace character starting it.  Prefixes are ignored or
+   skipped over before determining if a line starts or delimits a
+   paragraph."
+  "Fill this or next paragraph.
+   Point stays fixed, but text may move past it due to filling."
+  (let* ((prefix (value fill-prefix))
+	 (prefix-len (length prefix))
+	 (column (if p (abs p) (value fill-column)))
+	 (point (current-point)))
+    (with-mark ((m point))
+      (let ((paragraphp (paragraph-offset m 1)))
+	(unless (or paragraphp
+		    (and (last-line-p m)
+			 (end-line-p m)
+			 (not (blank-line-p (mark-line m)))))
+	  (editor-error))
+	;;
+	;; start and end get deleted by the undo cleanup function
+	(let ((start (copy-mark m :right-inserting))
+	      (end (copy-mark m :left-inserting)))
+	  (%fill-paragraph-start start prefix prefix-len)
+	  (let* ((region (region start end))
+		 (undo-region (copy-region region)))
+	    (fill-region region prefix column)
+	    (make-region-undo :twiddle "Fill Paragraph" region undo-region)))))))
+
+
+(defcommand "Fill Region" (p)
+  "Fill text from point to mark."
+  "Fill text from point to mark."
+  (let* ((region (current-region))
+	 (prefix (value fill-prefix))
+	 (column (if p (abs p) (value fill-column))))
+    (check-fill-prefix prefix column (current-point))
+    (fill-region-by-paragraphs region prefix column)))
+
+
+
+(defcommand "Set Fill Column" (p)
+  "Set Fill Column to current column or argument.
+   If argument is provided use its absolute value."
+  "Set Fill Column to current column or argument.
+   If argument is provided use its absolute value."
+  (let ((new-column (or (and p (abs p))
+			(mark-column (current-point)))))
+    (defhvar "Fill Column" "This buffer's fill column"
+      :value new-column  :buffer (current-buffer))
+    (message "Fill Column = ~D" new-column)))
+
+
+(defcommand "Set Fill Prefix" (p) 
+  "Define Fill Prefix from the current line.
+   All of the current line up to point is the prefix.  This may be
+   turned off by placing point at the beginning of a line when setting."
+  "Define Fill Prefix from the current line.
+   All of the current line up to point is the prefix.  This may be
+   turned off by placing point at the beginning of a line when setting."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (with-mark ((mark point))
+      (line-start mark)
+      (let ((val (if (mark/= mark point) (region-to-string (region mark point)))))
+	(defhvar "Fill Prefix" "This buffer's fill prefix"
+	  :value val  :buffer (current-buffer))
+	(message "Fill Prefix now ~:[empty~;~:*~S~]" val)))))
+
+#+cmucl
+(eval-when (:compile-toplevel)
+  (declaim (optimize (speed 2)))); turn off byte compilation.
+
+;;;; -- Auto Filling --
+
+;;;      %AUTO-FILL-SPACE takes a point and an argument indicating
+;;; whether it should insert a space or not.  If point is past Fill
+;;; Column then text is filled. Usually  the else clause of the if
+;;; will be executed.  If the then clause is executed, then the first
+;;; branch of the COND will usually be executed.  The first branch
+;;; handles the case of the end of a word extending past Fill Column
+;;; while the second handles whitespace preceded by non-whitespace
+;;; extending past the Fill Column.  The last branch is for those who
+;;; like to whitespace out a blank line.
+
+(defun %auto-fill-space (point insertp)
+  "Insert space, but CRLF if text extends past margin.
+   If arg is 0, then may break line but will not insert the space.
+   If arg is positive, then inserts that many spaces without filling."
+  (if (> (mark-column point) (value fill-column))
+      (with-mark ((mark1 point :left-inserting))
+	(let ((not-all-blank (reverse-find-attribute mark1 :whitespace #'zerop))
+	      (prefix (value fill-prefix))
+	      (column (value fill-column)))
+	  (cond ((and not-all-blank (mark= point mark1))
+		 (%auto-fill-word-past-column point mark1 insertp prefix column))
+		((and not-all-blank (same-line-p mark1 point))
+		 (delete-region (region mark1 point))
+		 (if (> (mark-column point) column)
+		     (%auto-fill-word-past-column point mark1 insertp prefix column)
+		     (%filling-set-next-line point nil prefix)))
+		(t
+		 (line-start mark1 (mark-line point))
+		 (delete-region (region mark1 point))
+		 (%filling-set-next-line point nil prefix)))))
+      (if insertp (insert-character point #\space))))
+
+
+
+;;;      %AUTO-FILL-WORD-PAST-COLUMN takes a point, a second mark that is
+;;; mark= at the end of some word, and an indicator of whether a space
+;;; should be inserted or not.  First, point is moved before the previous
+;;; "word."  If the word is effectively the only word on the line, it
+;;; should not be moved down to the next line as it will leave a blank
+;;; line.  The third branch handles when the typing began in the middle of
+;;; some line (that is, right in front of some word).  Note that the else
+;;; clause is the usual case.
+
+(defun %auto-fill-word-past-column (point mark1 insertp prefix column)
+  (let ((point-moved-p (reverse-find-attribute point :whitespace)))
+    (with-mark ((mark2 point :left-inserting))
+      (cond ((or (not point-moved-p)
+		 (%auto-fill-blank-before-p point prefix))
+	     (move-mark point mark1)
+	     (%filling-set-next-line point nil prefix))
+	    ((%auto-fill-line-as-region-p point mark2 column)
+	     (if (and insertp
+		      (not (or (end-line-p mark1)
+			       (whitespace-attribute-p (next-character mark1)))))
+		 (insert-character mark1 #\space))
+	     (auto-fill-line-as-region point (move-mark mark2 point) prefix column)
+	     (move-mark point mark1)
+	     (if (and insertp (end-line-p point))
+		 (insert-character point #\space)))
+	    ((not (or (end-line-p mark1)
+		      (whitespace-attribute-p (next-character mark1))))
+	     (insert-character mark1 #\space)
+	     (%filling-set-next-line point nil prefix)
+	     (mark-after point)
+	     (%auto-fill-clean-previous-line mark1 mark2))
+	    (t
+	     (%filling-set-next-line point insertp prefix)
+	     (%auto-fill-clean-previous-line mark1 mark2))))))
+
+
+
+;;; AUTO-FILL-LINE-AS-REGION basically grabs a line as a region and fills
+;;; it.  However, it knows about comments and makes auto filling a comment
+;;; line as a region look the same as a typical "back up a word and break
+;;; the line."  When there is a comment, then region starts where the
+;;; comment starts instead of the beginning of the line, but the presence
+;;; of a prefix overrides all this.
+
+(defun auto-fill-line-as-region (point mark prefix column)
+  (let* ((start (value comment-start))
+	 (begin (value comment-begin))
+	 (end (value comment-end)))
+    (line-start mark)
+    (cond ((and (not prefix) start (to-line-comment mark start))
+	   (fill-region (region mark (line-end point))
+			(gen-comment-prefix mark start begin)
+			column)
+	   (when end
+	     (line-start point)
+	     (do ()
+		 ((mark>= mark point))
+	       (if (not (to-comment-end mark end)) (insert-string mark end))
+	       (line-offset mark 1 0))))	   
+	  (t (fill-region (region mark (line-end point)) prefix column)))))
+
+
+
+(defun %auto-fill-blank-before-p (point prefix)
+  "is true if whitespace only precedes point except for the prefix."
+  (or (blank-before-p point)
+      (with-mark ((temp point))
+	(reverse-find-attribute temp :whitespace #'zerop)
+	(<= (mark-column temp) (length prefix)))))
+
+
+
+;;;      %AUTO-FILL-LINE-AS-REGION-P determines if the line point and mark2
+;;; sit on is so long that it might as well be filled as if it were a
+;;; region.  Mark2 is mark= to point at the beginning of the last word on
+;;; the line and is then moved over the whitespace before point.  If the
+;;; word end prior the last word on the line is on the same line and not
+;;; before column, then fill the line as a region.
+
+(defun %auto-fill-line-as-region-p (point mark2 column)
+  (reverse-find-attribute mark2 :whitespace #'zerop)
+  (and (same-line-p mark2 point)
+       (> (mark-column mark2) column)))
+
+
+
+(defun %auto-fill-clean-previous-line (mark1 mark2)
+  (when (line-offset mark1 -1)
+    (line-end mark1)
+    (move-mark mark2 mark1)
+    (unless (and (reverse-find-attribute mark1 :whitespace #'zerop)
+		 (same-line-p mark1 mark2))
+      (line-start mark1 (mark-line mark2)))
+    (delete-region (region mark1 mark2))))
+
+
+
+;;; %FILLING-SET-NEXT-LINE gets a new blank line and sets it up with the
+;;; prefix and places the point correctly.  The argument point must alias
+;;; (current-point).
+
+(defun %filling-set-next-line (point insertp prefix)
+  (cond ((and (value auto-fill-space-indent) (not prefix))
+	 (indent-new-comment-line-command nil))
+	(t (new-line-command nil)
+	   (if prefix (insert-string point prefix))))
+  (if (not (find-attribute point :whitespace)) (line-end point))
+  (if insertp (insert-character point #\space)))
+
+
+
+;;;; -- Paragraph Filling --
+
+
+;;;      %FILL-PARAGRAPH-START takes a mark that has just been moved
+;;; forward over some paragraph.  After moving to the beginning of it, we
+;;; place the mark appropriately for filling the paragraph as a region.
+
+(defun %fill-paragraph-start (mark prefix prefix-len)
+  (paragraph-offset mark -1)
+  (skip-prefix-if-here mark prefix prefix-len)
+  (if (text-blank-line-p mark)
+      (line-offset mark 1 0)
+      (line-start mark)))
+
+
+
+;;;; -- Region Filling --
+
+
+;;;      FILL-REGION-BY-PARAGRAPHS finds paragraphs and uses region filling
+;;; primitives to fill them.  Tmark2 is only used for the first paragraph; we
+;;; need a mark other than start in case start is in the middle of a paragraph
+;;; instead of between two.
+;;;
+(defun fill-region-by-paragraphs (region &optional
+					 (prefix (value fill-prefix))
+					 (column (value fill-column)))
+  "Finds paragraphs in region and fills them as distinct regions using
+   FILL-REGION."
+  (with-mark ((start (region-start region) :left-inserting))
+    (with-mark ((tmark1 start :left-inserting)
+		(tmark2 start :left-inserting)) ;only used for first para.
+      (let ((region (region (copy-mark (region-start region)) ;deleted by undo.
+			    (copy-mark (region-end region))))
+	    (undo-region (copy-region region))
+	    (end (region-end region))
+	    (prefix-len (length prefix))
+	    (paragraphp (paragraph-offset tmark1 1)))
+	(when paragraphp
+	  (%fill-paragraph-start (move-mark tmark2 tmark1) prefix prefix-len)
+	  (if (mark>= tmark2 start) (move-mark start tmark2))
+	  (cond ((mark>= tmark1 end)
+		 (fill-region-aux start end prefix prefix-len column))
+		(t
+		 (fill-region-aux start tmark1 prefix prefix-len column)
+		 (do ((paragraphp (mark-paragraph start tmark1)
+				  (mark-paragraph start tmark1)))
+		     ((not paragraphp))
+		   (if (mark> start end)
+		       (return)
+		       (cond ((mark>= tmark1 end)
+			      (fill-region-aux start end prefix
+					       prefix-len column)
+			      (return))
+			     (t (fill-region-aux start tmark1
+						 prefix prefix-len column))))))))
+	(make-region-undo :twiddle "Fill Region" region undo-region)))))
+
+(defun fill-region (region &optional
+			   (prefix (value fill-prefix))
+			   (column (value fill-column)))
+  "Fills a region using the given prefix and column."
+  (let ((prefix (if (and prefix (string= prefix "")) () prefix)))
+    (with-mark ((start (region-start region) :left-inserting))
+      (check-fill-prefix prefix column start)
+      (fill-region-aux start (region-end region)
+		       prefix (length prefix) column))))
+
+
+
+;;;      FILL-REGION-AUX grinds over a region between fill-mark and
+;;; end-mark deleting blank lines and filling lines.  For each line, the
+;;; extra whitespace between words is collapsed to one space, and at the
+;;; end and beginning of the line it is deleted.  We do not return after
+;;; realizing that fill-mark is after end-mark if the line needs to be
+;;; broken; it may be the case that there are several filled line lengths
+;;; of material before end-mark on the current line.
+
+(defun fill-region-aux (fill-mark end-mark prefix prefix-len column)
+  (if (and (start-line-p fill-mark) prefix)
+      (fill-region-prefix-line fill-mark prefix prefix-len))
+  (with-mark ((mark1 fill-mark :left-inserting)
+	      (cmark fill-mark :left-inserting))
+    (do ((collapse-p t))
+	(nil)
+      (line-end fill-mark)
+      (line-start (move-mark mark1 fill-mark))
+      (skip-prefix-if-here mark1 prefix prefix-len)
+      (cond ((mark>= fill-mark end-mark)
+	     (if (mark= fill-mark end-mark)
+		 (fill-region-clear-eol fill-mark))
+	     (cond ((> (mark-column end-mark) column)
+		    (when collapse-p
+		      (fill-region-collapse-whitespace cmark end-mark)
+		      (setf collapse-p nil))
+		    (fill-region-break-line fill-mark prefix
+					    prefix-len end-mark column))
+		   (t (return))))
+	    ((blank-after-p mark1)
+	     (fill-region-delete-blank-lines fill-mark end-mark prefix prefix-len)
+	     (cond ((mark< fill-mark end-mark)
+		    (if prefix
+			(fill-region-prefix-line fill-mark prefix prefix-len))
+		    (fill-region-clear-bol fill-mark)
+		    (move-mark cmark fill-mark))
+		   (t (return)))
+	     (setf collapse-p t))
+	    (t (fill-region-clear-eol fill-mark)
+	       (if collapse-p (fill-region-collapse-whitespace cmark fill-mark))
+	       (cond ((> (mark-column fill-mark) column)
+		      (fill-region-break-line fill-mark prefix
+					      prefix-len end-mark column)
+		      (setf collapse-p nil))
+		     (t (fill-region-get-next-line fill-mark column
+						   prefix prefix-len end-mark)
+			(move-mark cmark fill-mark)
+			(setf collapse-p t))))))
+    (move-mark fill-mark end-mark)))
+
+
+
+;;;      FILL-REGION-BREAK-LINE breaks lines as close to the low side
+;;; column as possible.  The first branch handles a word lying across
+;;; column while the second takes care of whitespace passing column.  If
+;;; FILL-REGION-WORD-PAST-COLUMN encountered a single word stretching over
+;;; column, it would leave an extra opened line that needs to be cleaned up
+;;; or filled up.
+
+(defun fill-region-break-line (fill-mark prefix prefix-length
+					  end-mark column)
+  (with-mark ((mark1 fill-mark :left-inserting))
+    (move-to-position mark1 column)
+    (cond ((not (whitespace-attribute-p (next-character mark1)))
+	   (if (not (find-attribute mark1 :whitespace))
+	       (line-end mark1))
+	   (move-mark fill-mark mark1)
+	   (if (eq (fill-region-word-past-column fill-mark mark1 prefix)
+		   :handled-oversized-word)
+	       (if (mark>= fill-mark end-mark)
+		   (delete-characters (line-start fill-mark)
+				      prefix-length)
+		   (delete-characters fill-mark 1))))
+	  (t (move-mark fill-mark mark1)
+	     (unless (and (reverse-find-attribute mark1 :whitespace #'zerop)
+			  (same-line-p mark1 fill-mark))
+	       (line-start mark1 (mark-line fill-mark)))
+	     ;; forward find must move mark because of cond branch we are in.
+	     (find-attribute fill-mark :whitespace #'zerop)
+	     (unless (same-line-p mark1 fill-mark)
+	       (line-end fill-mark (mark-line mark1)))
+	     (delete-region (region mark1 fill-mark))
+	     (insert-character fill-mark #\newline)
+	     (if prefix (insert-string fill-mark prefix))))))
+
+
+
+;;;      FILL-REGION-WORD-PAST-COLUMN takes a point and a second mark that
+;;; is mark= at the end of some word.  First, point is moved before the
+;;; previous "word."  If the word is effectively the only word on the line,
+;;; it should not be moved down to the next line as it will leave a blank
+;;; line.
+
+(defun fill-region-word-past-column (point mark1 prefix)
+  (with-mark ((mark2 (copy-mark point :left-inserting)))
+    (let ((point-moved-p (reverse-find-attribute point :whitespace))
+	  (hack-for-fill-region :handled-normal-case))
+      (cond ((or (not point-moved-p)
+		 (%auto-fill-blank-before-p point prefix))
+	     (setf hack-for-fill-region :handled-oversized-word)
+	     (move-mark point mark1)
+	     (fill-region-set-next-line point prefix))
+	    (t (fill-region-set-next-line point prefix)
+	       (%auto-fill-clean-previous-line mark1 mark2)))
+      hack-for-fill-region)))
+
+(defun fill-region-set-next-line (point prefix)
+  (insert-character point #\newline)
+  (if prefix (insert-string point prefix))
+  (if (not (find-attribute point :whitespace)) (line-end point)))
+
+
+
+;;;      FILL-REGION-GET-NEXT-LINE gets another line when the current one
+;;; is short of the fill column.  It cleans extraneous whitespace from the
+;;; beginning of the next line to fill.  To save typical redisplay the
+;;; length of the first word is added to the ending column of the current
+;;; line to see if it extends past the fill column; if it does, then the
+;;; fill-mark is left on the new line instead of merging the new line with
+;;; the current one.  The fill-mark is left after a prefix (if there is one)
+;;; on a new line, before the first word brought up to the current line, or
+;;; after the end mark.
+
+(defun fill-region-get-next-line (fill-mark column prefix prefix-len end-mark)
+  (let ((prev-end-pos (mark-column fill-mark))
+	(two-spaces-p (fill-region-insert-two-spaces-p fill-mark)))
+    (with-mark ((tmark fill-mark :left-inserting))
+      (fill-region-find-next-line fill-mark prefix prefix-len end-mark)
+      (move-mark tmark fill-mark)
+      (cond ((mark< fill-mark end-mark)
+	     (skip-prefix-if-here tmark prefix prefix-len)
+	     (fill-region-clear-bol tmark)
+	     (let ((beginning-pos (mark-column tmark)))
+	       (find-attribute tmark :whitespace)
+	       (cond ((> (+ prev-end-pos (if two-spaces-p 2 1)
+			    (- (mark-column tmark) beginning-pos))
+			 column)
+		      (if prefix
+			  (fill-region-prefix-line fill-mark prefix prefix-len)))
+		     (t
+		      (if (and prefix
+			       (%line-has-prefix-p fill-mark prefix prefix-len))
+			  (delete-characters fill-mark prefix-len))
+		      (delete-characters fill-mark -1)
+		      (insert-character fill-mark #\space)
+		      (if two-spaces-p (insert-character fill-mark #\space))))))
+	    (t
+	     (mark-after fill-mark))))))
+
+
+
+;;;      FILL-REGION-FIND-NEXT-LINE finds the next non-blank line, modulo
+;;; fill prefixes, and deletes the intervening lines.  Fill-mark is left at
+;;; the beginning of the next line.
+
+(defun fill-region-find-next-line (fill-mark prefix prefix-len end-mark)
+  (line-offset fill-mark 1 0)
+  (when (mark< fill-mark end-mark)
+    (skip-prefix-if-here fill-mark prefix prefix-len)
+    (if (blank-after-p fill-mark)
+	(fill-region-delete-blank-lines fill-mark end-mark prefix prefix-len)
+	(line-start fill-mark))))
+
+
+
+;;;      FILL-REGION-DELETE-BLANK-LINES deletes the blank line mark is on
+;;; and all successive blank lines.  Mark is left at the beginning of the
+;;; first non-blank line by virtue of its placement and region deletions.
+
+(defun fill-region-delete-blank-lines (mark end-mark prefix prefix-len)
+  (line-start mark)
+  (with-mark ((tmark mark :left-inserting))
+    (do ((linep (line-offset tmark 1 0) (line-offset tmark 1 0)))
+	((not linep)
+	 (move-mark tmark end-mark)
+	 (delete-region (region mark tmark)))
+      (skip-prefix-if-here tmark prefix prefix-len)
+      (when (mark>= tmark end-mark)
+	(move-mark tmark end-mark)
+	(delete-region (region mark tmark))
+	(return))
+      (unless (blank-after-p tmark)
+	(line-start tmark)
+	(delete-region (region mark tmark))
+	(return)))))
+
+
+
+;;;      FILL-REGION-CLEAR-BOL clears the initial whitespace on a line
+;;; known to be non-blank.  Note that the fill prefix is not considered, so
+;;; the mark must have been moved over it already if there is one.
+
+(defun fill-region-clear-bol (mark)
+  (with-mark ((tmark mark :left-inserting))
+    (find-attribute tmark :whitespace #'zerop)
+    (unless (mark= mark tmark)
+      (delete-region (region mark tmark)))))
+
+
+
+;;;      FILL-REGION-COLLAPSE-WHITESPACE deletes extra whitespace between
+;;; blocks of non-whitespace characters from mark1 to mark2.  Tabs are
+;;; converted into a single space.  Mark2 must be on the same line as mark1
+;;; since there is no concern of newlines, prefixes on a new line, blank
+;;; lines between blocks of non-whitespace characters, etc.
+
+(defun fill-region-collapse-whitespace (mark1 mark2)
+  (with-mark ((tmark mark1 :left-inserting))
+    ;; skip whitespace at beginning of line or single space between words
+    (find-attribute mark1 :whitespace #'zerop)
+    (unless (mark>= mark1 mark2)
+      (do ()
+	  (nil)
+	(if (not (find-attribute mark1 :whitespace)) ;not end of buffer
+	    (return))
+	(if (mark>= mark1 mark2) (return))
+	(if (char/= (next-character mark1) #\space)
+	    ;; since only on one line, must be tab or space
+	    (setf (next-character mark1) #\space))
+	(move-mark tmark mark1)
+	(if (mark= (mark-after mark1) mark2) (return))
+	(let ((char (next-character mark1)))
+	  (when (and (fill-region-insert-two-spaces-p tmark)
+		     (char= char #\space))
+	    ;; if at the end of a sentence, don't blow away the second space
+	    (if (mark= (mark-after mark1) mark2)
+		(return)
+		(setf char (next-character mark1))))
+	  (when (whitespace-attribute-p char) ;more whitespace than necessary
+	    (find-attribute (move-mark tmark mark1) :whitespace #'zerop)
+	    (if (mark>= tmark mark2) (move-mark tmark mark2))
+	    (delete-region (region mark1 tmark))))))))
+
+
+
+;;;      FILL-REGION-CLEAR-EOL must check the result of
+;;; REVERSE-FIND-ATTRIBUTE because if fill-mark did not move, then we are
+;;; only whitespace away from the beginning of the buffer.
+
+(defun fill-region-clear-eol (fill-mark)
+  (with-mark ((mark1 fill-mark :left-inserting))
+    (unless (and (reverse-find-attribute mark1 :whitespace #'zerop)
+		 (same-line-p mark1 fill-mark))
+      (line-start mark1 (mark-line fill-mark)))
+    (delete-region (region mark1 fill-mark))))
+
+
+
+(defun fill-region-prefix-line (fill-mark prefix prefix-length)
+  (if (%line-has-prefix-p fill-mark prefix prefix-length)
+      (character-offset fill-mark prefix-length)
+      (insert-string fill-mark prefix)))
+
+
+
+(defun %line-has-prefix-p (mark prefix prefix-length)
+  (declare (simple-string prefix))
+  (if (>= (line-length (mark-line mark)) prefix-length)
+      (string= prefix (the simple-string (line-string (mark-line mark)))
+	       :end2 prefix-length)))
+
+
+
+;;;      FILL-REGION-INSERT-TWO-SPACES-P returns true if a sentence
+;;; terminator is followed by any number of "closing characters" such as
+;;; ",',),etc.  If there is a sentence terminator at the end of the current
+;;; line, it must be assumed to be the end of a sentence as opposed to an
+;;; abbreviation.  Why?  Because EMACS does, and besides, what would Lisp
+;;; code be without heuristics.
+
+(defun fill-region-insert-two-spaces-p (mark)
+  (do ((n 0 (1+ n)))
+      ((not (sentence-closing-char-attribute-p (previous-character mark)))
+       (cond ((sentence-terminator-attribute-p (previous-character mark))
+	      (character-offset mark n))
+	     (t (character-offset mark n) nil)))
+    (mark-before mark)))
+
+
+
+(defun check-fill-prefix (prefix column mark)
+  (when prefix
+    (insert-character mark #\newline)
+    (insert-character mark #\newline)
+    (mark-before mark)
+    (insert-string mark prefix)
+    (let ((pos (mark-column mark)))
+      (declare (simple-string prefix))
+      (mark-after mark)
+      (delete-characters mark (- (+ (length prefix) 2)))
+      (if (>= pos column)
+	  (editor-error
+	   "The fill prefix length is longer than the fill column.")))))
Index: /branches/new-random/cocoa-ide/hemlock/src/font.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/font.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/font.lisp	(revision 13309)
@@ -0,0 +1,90 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Rob MacLachlan
+;;; Modified by Bill Chiles toward Hemlock running under X.
+;;;
+;;;    This file contains various functions that make up the user interface to
+;;; fonts.
+;;;
+
+(in-package :hemlock-internals)
+
+;;;; Creating, Deleting, and Moving.
+
+(defun new-font-region (buffer start-mark end-mark  font)
+  (let* ((start-line (mark-line start-mark))
+         (end-line (mark-line end-mark))
+         (font-start (internal-make-font-mark start-line
+                                              (mark-charpos start-mark)
+                                              :right-inserting
+                                              font))
+         (font-end (internal-make-font-mark end-line
+                                              (mark-charpos end-mark)
+                                              :right-inserting
+                                              font))
+         (region (internal-make-font-region font-start font-end)))
+    (setf (font-mark-region font-start) region
+          (font-mark-region font-end) region)
+    (push font-start (line-marks start-line))
+    (push font-end (line-marks end-line))
+    (add-buffer-font-region buffer region)
+    (hemlock-ext:buffer-note-font-change buffer region font)
+    region))
+
+
+
+
+
+(defun font-mark (line charpos font &optional (kind :right-inserting))
+  "Returns a font on line at charpos with font.  Font marks must be permanent
+   marks."
+  (unless (or (eq kind :right-inserting) (eq kind :left-inserting))
+    (error "A Font-Mark must be :left-inserting or :right-inserting."))
+  (unless (and (>= font 0) (< font font-map-size))
+    (error "Font number ~S out of range." font))
+  (let ((new (internal-make-font-mark line charpos kind font)))
+    (new-font-mark new line)
+    (push new (line-marks line))
+    new))
+
+(defun delete-font-mark (font-mark)
+  "Deletes a font mark."
+  (check-type font-mark font-mark)
+  (let ((line (mark-line font-mark)))
+    (when line
+      (setf (line-marks line) (delq font-mark (line-marks line)))
+      (nuke-font-mark font-mark line)
+      (setf (mark-line font-mark) nil))))
+
+(defun delete-line-font-marks (line)
+  "Deletes all font marks on line."
+  (dolist (m (line-marks line))
+    (when (fast-font-mark-p m)
+      (delete-font-mark m))))
+
+(defun move-font-mark (font-mark new-position)
+  "Moves font mark font-mark to location of mark new-position."
+  (check-type font-mark font-mark)
+  (let ((old-line (mark-line font-mark))
+	(new-line (mark-line new-position)))
+    (nuke-font-mark font-mark old-line)
+    (move-mark font-mark new-position)
+    (new-font-mark font-mark new-line)
+    font-mark))
+
+(defun nuke-font-mark (mark line)
+  (new-font-mark mark line))
+
+(defun new-font-mark (mark line)
+  (declare (ignore mark line))
+)
+
Index: /branches/new-random/cocoa-ide/hemlock/src/hemlock-ext.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/hemlock-ext.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/hemlock-ext.lisp	(revision 13309)
@@ -0,0 +1,163 @@
+;;; -*- Mode: LISP; Package: Hemlock-Internals -*-
+
+(in-package :hemlock-internals)
+
+(defconstant hemlock-char-code-limit 256)
+
+(defvar *command-line-switches* nil)
+
+(defun default-directory ()
+  "Returns the pathname for the default directory.  This is the place where
+  a file will be written if no directory is specified.  This may be changed
+  with setf."
+  (truename #p""))
+
+(defun file-writable (pathname)
+  "File-writable accepts a pathname and returns T if the current
+  process can write it, and NIL otherwise. Also if the file does
+  not exist return T."
+  #+(or CMU scl)
+  (ext:file-writable pathname)
+  #-(or cmu scl)
+  (handler-case (let ((io (open pathname
+                                :direction :output
+                                :if-exists :append
+                                :if-does-not-exist nil)))
+                  (if io
+                      (close io :abort t)
+                      ;; more complicate situation:
+                      ;; we want test if we can create the file.
+                      (let ((io (open pathname
+                                      :direction :output
+                                      :if-exists nil
+                                      :if-does-not-exist :create)))
+                        (if io
+                            (progn
+                              (close io)
+                              (delete-file io))
+                            t))))
+    (file-error (err)
+                (declare (ignore err))
+                nil)) )
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun %sp-byte-blt (src start dest dstart end)
+  (declare (type simple-base-string src dest))
+  (loop for s from start
+        for d from dstart below end
+        do
+        (setf (aref dest d) (aref src s))))
+
+(defun %sp-find-character-with-attribute (string start end table mask)
+  ;;(declare (type (simple-array (mod 256) char-code-max) table))
+  (declare (simple-string string))
+  (declare (fixnum start end))
+  "%SP-Find-Character-With-Attribute  String, Start, End, Table, Mask
+  The codes of the characters of String from Start to End are used as indices
+  into the Table, which is a U-Vector of 8-bit bytes. When the number picked
+  up from the table bitwise ANDed with Mask is non-zero, the current
+  index into the String is returned. The corresponds to SCANC on the Vax."
+  (do ((index start (1+ index)))
+      ((= index end) nil)
+    (declare (fixnum index))
+    (if (/= (logand (aref table (min 255 (char-code (schar string index)))) mask) 0)
+	(return index))))
+
+(defun %sp-reverse-find-character-with-attribute (string start end table
+							  mask)
+  ;;(declare (type (simple-array (mod 256) char-code-max) table))
+  (declare (simple-string string))
+  (declare (fixnum start end))
+  "Like %SP-Find-Character-With-Attribute, only sdrawkcaB."
+  (do ((index (1- end) (1- index)))
+      ((< index start) nil)
+    (declare (fixnum index))
+    (if (/= (logand (aref table (min 255 (char-code (aref string index)))) mask) 0)
+	(return index))))
+
+(defun %sp-find-character (string start end character)
+  "%SP-Find-Character  String, Start, End, Character
+  Searches String for the Character from Start to End.  If the character is
+  found, the corresponding index into String is returned, otherwise NIL is
+  returned."
+  (declare (simple-string string)
+           (fixnum start end)
+           (optimize (speed 3) (safety 0)))
+  (do* ((i start (1+ i)))
+       ((= i end))
+    (declare (fixnum i))
+    (when (eq character (schar string i))
+      (return i))))
+
+;;;; complete-file
+
+(defun complete-file (pathname &key (defaults *default-pathname-defaults*)
+			       ignore-types)
+  (let ((files (complete-file-directory pathname defaults)))
+    (cond ((null files)
+	   (values nil nil))
+	  ((null (cdr files))
+	   (values (car files) 
+		   t))
+	  (t
+	   (let ((good-files
+		  (delete-if #'(lambda (pathname)
+				 (and (simple-string-p
+				       (pathname-type pathname))
+				      (member (pathname-type pathname)
+					      ignore-types
+					      :test #'string=)))
+			     files)))
+	     (cond ((null good-files))
+		   ((null (cdr good-files))
+		    (return-from complete-file
+				 (values (car good-files)
+					 t)))
+		   (t
+		    (setf files good-files)))
+	     (let ((common (file-namestring (car files))))
+	       (dolist (file (cdr files))
+		 (let ((name (file-namestring file)))
+		   (dotimes (i (min (length common) (length name))
+			       (when (< (length name) (length common))
+				 (setf common name)))
+		     (unless (char= (schar common i) (schar name i))
+		       (setf common (subseq common 0 i))
+		       (return)))))
+	       (values (merge-pathnames common pathname)
+		       nil)))))))
+
+;;; COMPLETE-FILE-DIRECTORY-ARG -- Internal.
+;;;
+(defun complete-file-directory (pathname defaults)
+  (let* ((pathname (merge-pathnames pathname (directory-namestring defaults)))
+	 (type (pathname-type pathname)))
+    (setf pathname
+	  (make-pathname :defaults (truename (make-pathname :defaults pathname :name nil :type nil))
+			 :name (pathname-name pathname)
+			 :type type))
+    (delete-if-not (lambda (candidate)
+		     (search (namestring pathname) (namestring candidate)))
+		   (append
+		    #+CLISP 
+		    (directory
+		     (make-pathname :defaults pathname
+				    :name :wild
+				    :type nil)) ;gosh!
+		    #+CLISP 
+		    (directory
+		     (make-pathname :defaults pathname
+				    :directory (append (pathname-directory pathname) (list "*")) ;gosh gosh!
+				    :name nil
+				    :type nil))))))
+
+;;; Ambiguous-Files  --  Public
+;;;
+(defun ambiguous-files (pathname
+			&optional (defaults *default-pathname-defaults*))
+  "Return a list of all files which are possible completions of Pathname.
+   We look in the directory specified by Defaults as well as looking down
+   the search list."
+  (complete-file-directory pathname defaults))
Index: /branches/new-random/cocoa-ide/hemlock/src/htext1.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/htext1.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/htext1.lisp	(revision 13309)
@@ -0,0 +1,754 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock Text-Manipulation functions.
+;;; Written by Skef Wholey.
+;;;
+;;; The code in this file implements the functions in the "Representation
+;;; of Text," "Buffers," and "Predicates" chapters of the Hemlock design
+;;; document.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Representation of Text:
+
+;;; Line cache mechanism.
+;;;
+;;; The "open line" is used when inserting and deleting characters from a line.
+;;; It acts as a cache that provides a more flexible (but more expensive)
+;;; representation of the line for multiple insertions and deletions.  When a
+;;; line is open, it is represented as a vector of characters and two indices:
+;;;
+;;; +-----------------------------------------------------------+
+;;; | F | O | O |   | B | x | x | x | x | x | x | x | x | A | R |
+;;; +-----------------------------------------------------------+
+;;;			  ^			          ^
+;;;		      Left Pointer		     Right Pointer
+;;;
+;;; The open line is represented by 4 special variables:
+;;;	(current-open-line): the line object that is opened
+;;;	(current-open-chars): the vector of cached characters
+;;;	(current-left-open-pos): index of first free character in the gap
+;;;	(current-right-open-pos): index of first used character after the gap
+;;;
+;;; Note:
+;;;    Any modificiation of the line cache must be protected by
+;;; Without-Interrupts.  This is done automatically by modifying-buffer; other
+;;; users beware.
+
+
+
+#+no
+(defvar *line-cache-length* 200
+  "Length of Open-Chars.")
+
+
+
+#+no
+(defvar *open-line* ()
+  "Line open for hacking on.")
+
+
+
+#+no
+(defvar *open-chars*  (make-string *line-cache-length*)
+  "Vector of characters for hacking on.")
+
+
+
+#+no
+(defvar *left-open-pos* 0
+  "Index to first free character to left of mark in *Open-Chars*.")
+
+
+
+#+no
+(defvar *right-open-pos* 0
+  "Index to first used character to right of mark in *Open-Chars*.")
+
+(defun grow-open-chars (&optional (new-length (* (current-line-cache-length) 2)))
+  "Grows (current-open-chars) to twice its current length, or the New-Length if
+  specified."
+  (let* ((old-chars (current-open-chars))
+	 (old-right (current-right-open-pos))
+	 (new-chars (make-string new-length))
+	 (new-right (- new-length (- (current-line-cache-length) old-right))))
+    (%sp-byte-blt old-chars 0 new-chars 0 (current-left-open-pos))
+    (%sp-byte-blt old-chars old-right new-chars new-right new-length)
+    (setf (current-right-open-pos) new-right)
+    (setf (current-open-chars) new-chars)
+    (setf (current-line-cache-length) new-length)))
+
+
+(defun close-line ()
+  "Stuffs the characters in the currently open line back into the line they
+  came from, and sets (current-open-line) to Nil."
+  (when (current-open-line)
+    (without-interrupts
+      (let* ((open-chars (current-open-chars))
+	     (right-pos (current-right-open-pos))
+	     (left-pos (current-left-open-pos))
+	     (length (+ left-pos (- (current-line-cache-length) right-pos)))
+	     (string (make-string length)))
+	(%sp-byte-blt open-chars 0 string 0 left-pos)
+	(%sp-byte-blt open-chars right-pos string left-pos length)
+	(setf (line-chars (current-open-line)) string)
+	(setf (current-open-line) nil)))))
+
+;;; We stick decrementing fixnums in the line-chars slot of the open line
+;;; so that whenever the cache is changed the chars are no longer eq.
+;;; They decrement so that they will be distinct from positive fixnums,
+;;; which might mean something else.
+;;;
+(defvar *cache-modification-tick* -1
+  "The counter for the fixnums we stick in the chars of the cached line.")
+
+(defun next-cache-modification-tick ()
+  (ccl::atomic-decf *cache-modification-tick*))
+
+(defun open-line (line mark)
+  "Closes the current open line and opens the given Line at the Mark.
+  Don't call this, use modifying-line instead."
+  (cond ((current-open-line-p line)
+	   (let ((charpos (mark-charpos mark))
+		 (open-chars (current-open-chars)))
+	     (cond ((< charpos (current-left-open-pos)) ; BLT 'em right!
+		    (let ((right-start (- (current-right-open-pos)
+					  (- (current-left-open-pos) charpos))))
+		      (%sp-byte-blt open-chars
+				    charpos
+				    open-chars
+				    right-start
+				    (current-right-open-pos))
+		      (setf (current-left-open-pos) charpos)
+		      (setf (current-right-open-pos) right-start)))
+		   ((> charpos (current-left-open-pos)) ; BLT 'em left!
+		    (%sp-byte-blt open-chars
+				  (current-right-open-pos)
+				  open-chars
+				  (current-left-open-pos)
+				  charpos)
+		    (incf (current-right-open-pos) (- charpos (current-left-open-pos)))
+		    (setf (current-left-open-pos) charpos)))))
+
+	  (t
+	   (close-line)
+	   (let* ((chars (line-chars line))
+		  (len (length chars)))
+	     (declare (simple-string chars))
+	     (when (> len (current-line-cache-length))
+	       (setf (current-line-cache-length) (* len 2))
+	       (setf (current-open-chars) (make-string (current-line-cache-length))))
+	     (setf (current-open-line) line)
+	     (setf (current-left-open-pos) (mark-charpos mark))
+	     (setf (current-right-open-pos)
+		   (- (current-line-cache-length)
+		      (- (length chars) (current-left-open-pos))))
+	     (%sp-byte-blt chars 0 (current-open-chars) 0
+			   (current-left-open-pos))
+	     (%sp-byte-blt chars (current-left-open-pos)
+			   (current-open-chars)
+			   (current-right-open-pos)
+			   (current-line-cache-length))))))
+
+
+;;;; Some macros for Text hacking:
+
+
+(defmacro modifying-line (line mark)
+  "Checks to see if the Line is already opened at the Mark, and calls Open-Line
+  if not.  Sticks a tick in the current-open-line's chars.  This must be called within
+  the body of a Modifying-Buffer form."
+  `(progn
+    (unless (and (= (mark-charpos ,mark) (current-left-open-pos)) (current-open-line-p ,line))
+      (open-line ,line ,mark))
+    (setf (line-chars (current-open-line)) (next-cache-modification-tick))))
+
+;;; Now-Tick tells us when now is and isn't.
+;;;
+(defvar now-tick 0 "Current tick.")
+
+(defmacro tick ()
+  "Increments the ``now'' tick."
+  `(ccl::atomic-incf now-tick))
+
+  
+;;; Yeah, the following is kind of obscure, but at least it doesn't
+;;; call Bufferp twice.  The without-interrupts is just to prevent
+;;; people from being screwed by interrupting when the buffer structure
+;;; is in an inconsistent state.
+;;;
+(defmacro modifying-buffer (buffer &body forms)
+  "Does groovy stuff for modifying buffers."
+  (let* ((b (gensym))
+         (bp (gensym)))
+    `(let* ((,b ,buffer)
+            (,bp (bufferp ,b)))
+      (when ,bp
+        (unless (buffer-writable ,b)
+          (error "Buffer ~S is read only." (buffer-name ,b)))
+        (when (< (buffer-modified-tick ,b)
+                 (buffer-unmodified-tick ,b))
+          (invoke-hook hemlock::buffer-modified-hook ,b t))
+        (setf (buffer-modified ,b) t))
+      (without-interrupts ,@forms))))
+
+(defmacro always-change-line (mark new-line)
+  (let ((scan (gensym))
+	(prev (gensym))
+	(old-line (gensym)))
+    `(let ((,old-line (mark-line ,mark)))
+       (when (not (eq (mark-%kind ,mark) :temporary))
+	 (do ((,scan (line-marks ,old-line) (cdr ,scan))
+	      (,prev () ,scan))
+	     ((eq (car ,scan) ,mark)
+	      (if ,prev
+		  (setf (cdr ,prev) (cdr ,scan))
+		  (setf (line-marks ,old-line) (cdr ,scan)))
+	      (setf (cdr ,scan) (line-marks ,new-line)
+		    (line-marks ,new-line) ,scan))))
+       (setf (mark-line ,mark) ,new-line))))
+
+(defmacro change-line (mark new-line)
+  (let ((scan (gensym))
+	(prev (gensym))
+	(old-line (gensym)))
+    `(let ((,old-line (mark-line ,mark)))
+       (unless (or (eq (mark-%kind ,mark) :temporary)
+		   (eq ,old-line ,new-line))
+	 (do ((,scan (line-marks ,old-line) (cdr ,scan))
+	      (,prev () ,scan))
+	     ((eq (car ,scan) ,mark)
+	      (if ,prev
+		  (setf (cdr ,prev) (cdr ,scan))
+		  (setf (line-marks ,old-line) (cdr ,scan)))
+	      (setf (cdr ,scan) (line-marks ,new-line)
+		    (line-marks ,new-line) ,scan))))
+       (setf (mark-line ,mark) ,new-line))))
+
+;;; MOVE-SOME-MARKS  --  Internal
+;;;
+;;;    Move all the marks from the line Old to New, performing some
+;;; function on their charpos'es.  Charpos is bound to the charpos of
+;;; the mark, and the result of the evaluation of the last form in 
+;;; the body should be the new charpos for the mark.  If New is
+;;; not supplied then the marks are left on the old line.
+;;;
+(defmacro move-some-marks ((charpos old &optional new) &body body)
+  (let ((last (gensym)) (mark (gensym)) (marks (gensym)))
+    (if new
+	`(let ((,marks (line-marks ,old)))
+	   (do ((,mark ,marks (cdr ,mark))
+		(,last nil ,mark))
+	       ((null ,mark)
+		(when ,last
+		  (shiftf (cdr ,last) (line-marks ,new) ,marks))
+		(setf (line-marks ,old) nil))
+	     (setf (mark-line (car ,mark)) ,new)
+	     (setf (mark-charpos (car ,mark))
+		   (let ((,charpos (mark-charpos (car ,mark))))
+		     ,@body))))
+	`(dolist (,mark (line-marks ,old))
+	   (setf (mark-charpos ,mark)
+		 (let ((,charpos (mark-charpos ,mark)))
+		   ,@body))))))
+
+;;; Maybe-Move-Some-Marks  --  Internal
+;;;
+;;;    Like Move-Some-Marks, but only moves the mark if the 
+;;; charpos is greater than the bound, OR the charpos equals the bound
+;;; and the marks %kind is :left-inserting.
+;;;
+(defmacro maybe-move-some-marks ((charpos old &optional new) bound &body body)
+  (let ((mark (gensym)) (marks (gensym)) (prev (gensym)))
+    (if new
+      `(do ((,mark (line-marks ,old))
+            (,marks (line-marks ,new))
+            (,prev ()))
+        ((null ,mark)
+         (setf (line-marks ,new) ,marks))
+        (let ((,charpos (mark-charpos (car ,mark))))
+          (cond
+            ((or (> ,charpos ,bound)
+                 (and (= ,charpos ,bound) 
+                      (eq (mark-%kind (car ,mark)) :left-inserting)))
+             (setf (mark-line (car ,mark)) ,new)
+             (setf (mark-charpos (car ,mark)) (progn ,@body))
+             (if ,prev
+               (setf (cdr ,prev) (cdr ,mark))
+               (setf (line-marks ,old) (cdr ,mark)))
+             (rotatef (cdr ,mark) ,marks ,mark))
+            (t
+             (setq ,prev ,mark  ,mark (cdr ,mark))))))
+      `(dolist (,mark (line-marks ,old))
+        (let ((,charpos (mark-charpos ,mark)))
+          (when (or (> ,charpos ,bound)
+                    (and (= ,charpos ,bound)
+                         (eq (mark-%kind ,mark) :left-inserting)))
+            (setf (mark-charpos ,mark) (progn ,@body))))))))
+
+
+
+;;; Maybe-Move-Some-Marks*  --  Internal
+;;;
+;;;    Like Maybe-Move-Some-Marks, but ignores the mark %kind.
+;;;
+(defmacro maybe-move-some-marks* ((charpos old &optional new) bound &body body)
+  (let ((mark (gensym)) (marks (gensym)) (prev (gensym)))
+    (if new
+	`(do ((,mark (line-marks ,old))
+	      (,marks (line-marks ,new))
+	      (,prev ()))
+	     ((null ,mark)
+	      (setf (line-marks ,new) ,marks))
+	   (let ((,charpos (mark-charpos (car ,mark))))
+	     (cond
+	       ((> ,charpos ,bound)
+		(setf (mark-line (car ,mark)) ,new)
+		(setf (mark-charpos (car ,mark)) (progn ,@body))
+		(if ,prev
+		    (setf (cdr ,prev) (cdr ,mark))
+		    (setf (line-marks ,old) (cdr ,mark)))
+		(rotatef (cdr ,mark) ,marks ,mark))
+	       (t
+		(setq ,prev ,mark  ,mark (cdr ,mark))))))
+	`(dolist (,mark (line-marks ,old))
+	   (let ((,charpos (mark-charpos ,mark)))
+	     (when (> ,charpos ,bound)
+	       (setf (mark-charpos ,mark) (progn ,@body))))))))
+
+
+;;;; Lines.
+
+(defun line-length (line)
+  "Returns the number of characters on the line."
+  (if (linep line)
+    (buffer-line-length line)
+    (error "~S is not a line!" line)))
+
+(defun line-buffer (line)
+  "Returns the buffer with which the Line is associated.  If the line is
+  not in any buffer then Nil is returned."
+  (let ((buffer (line-%buffer line)))
+    (if (bufferp buffer) buffer)))
+
+(defun line-string (line)
+  "Returns the characters in the line as a string.  The resulting string
+  must not be destructively modified.  This may be set with Setf."
+  (if (current-open-line-p line)
+    (close-line))
+  (line-chars line))
+
+(defun %set-line-string (line string)
+  (let ((buffer (line-%buffer line)))
+    (modifying-buffer buffer
+      (unless (simple-string-p string) 
+	(setq string (coerce string 'simple-string)))
+      (when (current-open-line-p line) (setf (current-open-line) nil))
+      (let ((length (length (the simple-string string))))
+	(dolist (m (line-marks line))
+	  (if (eq (mark-%kind m) :left-inserting)
+	      (setf (mark-charpos m) length)
+	      (setf (mark-charpos m) 0))))
+      (setf (line-chars line) string))))
+
+(defun line-character (line index)
+  "Return the Index'th character in Line.  If the index is the length of the
+  line then #\newline is returned."
+  (if (current-open-line-p line)
+      (if (< index (current-left-open-pos))
+	  (schar (current-open-chars) index)
+	  (let ((index (+ index (- (current-right-open-pos) (current-left-open-pos)))))
+	    (if (= index (current-line-cache-length))
+		#\newline
+		(schar (current-open-chars) index))))
+      (let ((chars (line-chars line)))
+	(declare (simple-string chars))
+	(if (= index (length chars))
+	    #\newline
+	    (schar chars index)))))
+
+
+;;;; Marks.
+
+(defun mark (line charpos &optional (kind :temporary))
+  "Returns a mark to the Charpos'th character of the Line.  Kind is the
+  kind of mark to make, one of :temporary (the default), :left-inserting
+  or :right-inserting."
+  (let ((mark (internal-make-mark line charpos kind)))
+    (if (not (eq kind :temporary))
+	(push mark (line-marks line)))
+    mark))
+
+(defun mark-kind (mark)
+  "Returns the kind of the given Mark, :Temporary, :Left-Inserting, or
+  :Right-Inserting.  This may be set with Setf."
+  (mark-%kind mark))
+
+(defun %set-mark-kind (mark kind)
+  (let ((line (mark-line mark)))
+    (cond ((eq kind :temporary)
+	   (setf (line-marks line) (delq mark (line-marks line)))
+	   (setf (mark-%kind mark) kind))
+	  ((or (eq kind :left-inserting) (eq kind :right-inserting))
+	   (if (not (member mark (line-marks line)))
+	       (push mark (line-marks line)))
+	   (setf (mark-%kind mark) kind))
+	  (t
+	   (error "~S is an invalid mark type." kind)))))
+
+(defun mark-buffer (mark)
+  (line-buffer (mark-line mark)))
+
+(defun copy-mark (mark &optional (kind (mark-%kind mark)))
+  "Returns a new mark pointing to the same position as Mark.  The kind
+  of mark created may be specified by Kind, which defaults to the
+  kind of the copied mark."
+  (let ((mark (internal-make-mark (mark-line mark) (mark-charpos mark) kind)))
+    (if (not (eq kind :temporary))
+	(push mark (line-marks (mark-line mark))))
+    mark))
+
+(defun delete-mark (mark)
+  "Deletes the Mark.  This should be done to any mark that may not be
+  temporary which is no longer needed."
+  (if (not (eq (mark-%kind mark) :temporary))
+      (let ((line (mark-line mark)))
+	(when line
+	  (setf (line-marks line) (delq mark (line-marks line))))
+	nil))
+  (setf (mark-line mark) nil))
+
+(defun move-to-position (mark charpos &optional (line (mark-line mark)))
+  "Changes the Mark to point to the given character position on the Line,
+  which defaults to the line the mark is currently on."
+  (when (<= charpos (line-length line))
+    (change-line mark line)
+    (setf (mark-charpos mark) charpos)
+    mark))
+
+(defun mark-absolute-position (mark)
+  (+ (get-line-origin (mark-line mark))
+     (mark-charpos mark)))
+
+(defun move-to-absolute-position (mark position)
+  (let* ((buffer (mark-buffer mark))
+         (line (buffer-line-at-absolute-position buffer position))
+         (offset (- position (get-line-origin line))))
+    (when (<= 0 offset (line-length line))
+      (change-line mark line)
+      (setf (mark-charpos mark) offset)
+      mark)))
+
+(defun buffer-selection-range (buffer)
+  "Absolute start and end positions of the current selection"
+  (let* ((point (buffer-point buffer))
+         (pos-1 (mark-absolute-position point))
+         (mark (and (hemlock::%buffer-region-active-p buffer) (buffer-%mark buffer)))
+         (pos-2 (if mark (mark-absolute-position mark) pos-1)))
+    (values (min pos-1 pos-2) (max pos-1 pos-2))))
+
+(defun mark-column (mark)
+  (let ((column 0)
+        (tab-spaces (value hemlock::spaces-per-tab))
+        (line (mark-line mark))
+        (charpos (mark-charpos mark)))
+    (multiple-value-bind (chars gap-start gap-end)
+                         (if (current-open-line-p line)
+                           (values (current-open-chars)
+                                   (current-left-open-pos)
+                                   (current-right-open-pos))
+                           (values (line-chars line) charpos charpos))
+      (when (< gap-start charpos)
+        (incf charpos (- gap-end gap-start)))
+      (loop with pos = 0
+        do (when (eql pos gap-start) (setq pos gap-end))
+        while (< pos charpos)
+        do (incf column (if (eql (schar chars pos) #\tab)
+                          (- tab-spaces (mod column tab-spaces))
+                          1))
+        do (incf pos))
+      column)))
+
+(defun move-to-column (mark column &optional (line (mark-line mark)))
+  (let ((tab-spaces (value hemlock::spaces-per-tab)))
+    (multiple-value-bind (chars gap-start gap-end end-pos)
+                         (if (current-open-line-p line)
+                           (values (current-open-chars)
+                                   (current-left-open-pos)
+                                   (current-right-open-pos)
+                                   (current-line-cache-length))
+                           (values (line-%chars line)
+                                   0
+                                   0
+                                   (length (line-%chars line))))
+      (loop with col = 0 with pos = 0
+        do (when (eql pos gap-start) (setq pos gap-end))
+        while (and (< pos end-pos) (< col column))
+        do (incf col (if (eql (schar chars pos) #\tab)
+                           (- tab-spaces (mod col tab-spaces))
+                           1))
+        do (incf pos)
+        finally (return (unless (< col column)
+                          (move-to-position mark pos line)))))))
+
+
+
+;;;; Regions.
+
+(defun region (start end)
+  "Returns a region constructed from the marks Start and End."
+  (let ((l1 (mark-line start))
+	(l2 (mark-line end)))
+    (unless (eq (line-%buffer l1) (line-%buffer l2))
+      (error "Can't make a region with lines of different buffers."))
+    (unless (if (eq l1 l2)
+		(<= (mark-charpos start) (mark-charpos end))
+		(< (line-number l1) (line-number l2)))
+      (error "Start ~S is after end ~S." start end)))
+  (internal-make-region start end))
+
+;;; The *Disembodied-Buffer-Counter* exists to give that are not in any buffer
+;;; unique buffer slots.
+
+(defvar *disembodied-buffer-counter* 0
+  "``Buffer'' given to lines in regions not in any buffer.")
+
+(defun next-disembodied-buffer-counter ()
+  (ccl::atomic-incf *disembodied-buffer-counter*))
+
+(defun make-empty-region ()
+  "Returns a region with start and end marks pointing to the start of one empty
+  line.  The start mark is right-inserting and the end mark is left-inserting."
+  (let* ((line (make-line :chars ""  :number 0
+			  :%buffer (next-disembodied-buffer-counter)))
+	 (start (mark line 0 :right-inserting))
+	 (end (mark line 0 :left-inserting)))
+    (internal-make-region start end)))
+
+;;; Line-Increment is the default difference for line numbers when we don't
+;;; know any better.
+
+(defconstant line-increment 256 "Default difference for line numbers.")
+
+;;; Renumber-Region is used internally to keep line numbers in ascending order.
+;;; The lines in the region are numbered starting with the given Start value
+;;; by increments of the given Step value.  It returns the region.
+
+(defun renumber-region (region &optional (start 0) (step line-increment))
+  (do ((line (mark-line (region-start region)) (line-next line))
+       (last-line (mark-line (region-end region)))
+       (number start (+ number step)))
+      ((eq line last-line)
+       (setf (line-number line) number)
+       region)
+    (setf (line-number line) number))
+  region)
+
+;;; Renumber-Region-Containing renumbers the region containing the given line.
+
+(defun renumber-region-containing (line)
+  (cond ((line-buffer line)
+	 (renumber-region (buffer-region (line-%buffer line))))
+	(t
+	 (do ((line line (line-previous line))
+	      (number 0 (- number line-increment)))
+	     ((null line))
+	   (setf (line-number line) number))
+	 (do ((line (line-next line) (line-next line))
+	      (number line-increment (+ number line-increment)))
+	     ((null line))
+	   (setf (line-number line) number)))))
+  
+
+;;; Number-Line numbers a newly created line.  The line has to have a previous
+;;; line.
+(defun number-line (line)
+  (let ((prev (line-number (line-previous line)))
+	(next (line-next line)))
+    (if (null next)
+	(setf (line-number line) (+ prev line-increment))
+	(let ((new (+ prev (truncate (- (line-number next) prev) 2))))
+	  (if (= new prev)
+	      (renumber-region-containing line)
+	      (setf (line-number line) new))))))
+
+
+
+
+;;;; Buffers.
+
+;;; BUFFER-SIGNATURE is the exported interface to the internal function,
+;;; BUFFER-MODIFIED-TICK
+;;; 
+(defun buffer-signature (buffer)
+  "Returns an arbitrary number which reflects the buffers current
+  \"signature.\" The value returned by buffer-signature is guaranteed
+  to be eql to the value returned by a previous call of buffer-signature
+  iff the buffer has not been modified between the calls."
+  (unless (bufferp buffer)
+    (error "~S is not a buffer." buffer))
+  (buffer-modified-tick buffer))
+
+
+
+
+;;;; Predicates:
+
+
+(defun start-line-p (mark)
+  "Returns T if the Mark points before the first character in a line, Nil
+  otherwise."
+  (= (mark-charpos mark) 0))
+
+(defun end-line-p (mark)
+  "Returns T if the Mark points after the last character in a line, Nil
+  otherwise."
+  (= (mark-charpos mark) (line-length (mark-line mark))))
+
+(defun empty-line-p (mark)
+  "Returns T if the line pointer to by Mark contains no characters, Nil 
+  or otherwise."
+  (let ((line (mark-line mark)))
+    (if (current-open-line-p line)
+	(and (= (current-left-open-pos) 0) (= (current-right-open-pos) (current-line-cache-length)))
+	(= (length (line-chars line)) 0))))
+
+;;; blank-between-positions  --  Internal
+;;;
+;;;    Check if a line is blank between two positions.  Used by blank-XXX-p.
+;;;
+(eval-when (:compile-toplevel :execute)
+(defmacro check-range (chars start end)
+  `(do ((i ,start (1+ i)))
+       ((= i ,end) t)
+     (when (zerop (character-attribute :whitespace (schar ,chars i)))
+       (return nil)))))
+;;;
+(defun blank-between-positions (line start end)
+  (if (current-open-line-p line)
+      (let ((gap (- (current-right-open-pos) (current-left-open-pos))))
+	(cond ((>= start (current-left-open-pos))
+	       (check-range (current-open-chars) (+ start gap) (+ end gap)))
+	      ((<= end (current-left-open-pos))
+	       (check-range (current-open-chars) start end))
+	      (t
+	       (and (check-range (current-open-chars) start (current-left-open-pos))
+		    (check-range (current-open-chars) (current-right-open-pos) (+ end gap))))))
+      (let ((chars (line-chars line)))
+	(check-range chars start end))))
+
+(defun blank-line-p (line)
+  "True if line contains only characters with a :whitespace attribute of 1."
+  (blank-between-positions line 0 (line-length line)))
+
+(defun blank-before-p (mark)
+  "True is all of the characters before Mark on the line it is on have a
+  :whitespace attribute of 1."
+  (blank-between-positions (mark-line mark) 0 (mark-charpos mark)))
+
+(defun blank-after-p (mark)
+  "True if all characters on the part part of the line after Mark have
+  a :whitespace attribute of 1."
+  (let ((line (mark-line mark)))
+    (blank-between-positions line (mark-charpos mark)
+			     (line-length line))))
+  
+(defun same-line-p (mark1 mark2)
+  "Returns T if Mark1 and Mark2 point to the same line, Nil otherwise."
+  (eq (mark-line mark1) (mark-line mark2)))
+
+(defun mark< (mark1 mark2)
+  "Returns T if Mark1 points to a character before Mark2, Nil otherwise."
+  (if (not (eq (line-%buffer (mark-line mark1))
+	       (line-%buffer (mark-line mark2))))
+      (error "Marks in different buffers have no relation."))
+  (or (< (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+      (and (= (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+	   (< (mark-charpos mark1) (mark-charpos mark2)))))
+
+(defun mark<= (mark1 mark2)
+  "Returns T if Mark1 points to a character at or before Mark2, Nil otherwise."
+  (if (not (eq (line-%buffer (mark-line mark1))
+	       (line-%buffer (mark-line mark2))))
+      (error "Marks in different buffers have no relation."))
+  (or (< (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+      (and (= (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+	   (<= (mark-charpos mark1) (mark-charpos mark2)))))
+
+(defun mark> (mark1 mark2)
+  "Returns T if Mark1 points to a character after Mark2, Nil otherwise."
+  (if (not (eq (line-%buffer (mark-line mark1))
+	       (line-%buffer (mark-line mark2))))
+      (error "Marks in different buffers have no relation."))
+  (or (> (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+      (and (= (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+	   (> (mark-charpos mark1) (mark-charpos mark2)))))
+
+(defun mark>= (mark1 mark2)
+  "Returns T if Mark1 points to a character at or after Mark2, Nil otherwise."
+  (if (not (eq (line-%buffer (mark-line mark1))
+	       (line-%buffer (mark-line mark2))))
+      (error "Marks in different buffers have no relation."))
+  (or (> (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+      (and (= (line-number (mark-line mark1)) (line-number (mark-line mark2)))
+	   (>= (mark-charpos mark1) (mark-charpos mark2)))))
+
+(defun mark= (mark1 mark2)
+  "Returns T if both marks point to the same position, Nil otherwise."
+  (and (eq (mark-line mark1) (mark-line mark2))
+       (= (mark-charpos mark1) (mark-charpos mark2))))
+
+(defun mark/= (mark1 mark2)
+  "Returns T if both marks point to different positions, Nil otherwise."
+  (not (and (eq (mark-line mark1) (mark-line mark2))
+	    (= (mark-charpos mark1) (mark-charpos mark2)))))
+
+(defun line< (line1 line2)
+  "Returns T if Line1 comes before Line2, NIL otherwise."
+  (if (neq (line-%buffer line1) (line-%buffer line2))
+      (error "Lines in different buffers have no relation."))
+  (< (line-number line1) (line-number line2)))
+
+(defun line<= (line1 line2)
+  "Returns T if Line1 comes before or is the same as Line2, NIL otherwise."
+  (if (neq (line-%buffer line1) (line-%buffer line2))
+      (error "Lines in different buffers have no relation."))
+  (<= (line-number line1) (line-number line2)))
+
+(defun line>= (line1 line2)
+  "Returns T if Line1 comes after or is the same as Line2, NIL otherwise."
+  (if (neq (line-%buffer line1) (line-%buffer line2))
+      (error "Lines in different buffers have no relation."))
+  (>= (line-number line1) (line-number line2)))
+
+(defun line> (line1 line2)
+  "Returns T if Line1 comes after Line2, NIL otherwise."
+  (if (neq (line-%buffer line1) (line-%buffer line2))
+      (error "Lines in different buffers have no relation."))
+  (> (line-number line1) (line-number line2)))
+
+(defun lines-related (line1 line2)
+  "Returns T if an order relation exists between Line1 and Line2."
+  (eq (line-%buffer line1) (line-%buffer line2)))
+
+(defun first-line-p (mark)
+  "Returns T if the line pointed to by mark has no previous line,
+  Nil otherwise."
+  (null (line-previous (mark-line mark))))
+
+(defun last-line-p (mark)
+  "Returns T if the line pointed to by mark has no next line,
+  Nil otherwise."
+  (null (line-next (mark-line mark))))
Index: /branches/new-random/cocoa-ide/hemlock/src/htext2.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/htext2.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/htext2.lisp	(revision 13309)
@@ -0,0 +1,538 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; More Hemlock Text-Manipulation functions.
+;;; Written by Skef Wholey.
+;;;
+;;; The code in this file implements the non-insert/delete functions in the
+;;; "Doing Stuff and Going Places" chapter of the Hemlock Design document.
+;;;
+
+(in-package :hemlock-internals)
+
+
+    
+	 
+
+
+(defun region-to-string (region &optional output-string)
+  "Returns a string containing the characters in the given Region."
+  (close-line)
+  (let* ((dst-length (count-characters region))
+	 (string (if (and output-string
+			  (<= dst-length (length output-string)))
+		     output-string
+		     (make-string dst-length)))
+	 (start-mark (region-start region))
+	 (end-mark (region-end region))
+	 (start-line (mark-line start-mark))
+	 (end-line (mark-line end-mark))
+	 (start-charpos (mark-charpos start-mark)))
+    (declare (simple-string string))
+    (if (eq start-line end-line)
+	(%sp-byte-blt (line-chars start-line) start-charpos string 0
+		      dst-length)
+	(let ((index ()))
+	  (let* ((line-chars (line-chars start-line))
+		 (dst-end (- (length line-chars) start-charpos)))
+	    (declare (simple-string line-chars))
+	    (%sp-byte-blt line-chars start-charpos string 0 dst-end)
+	    (setf (char string dst-end) #\newline)
+	    (setq index (1+ dst-end)))
+	  (do* ((line (line-next start-line) (line-next line))
+		(chars (line-chars line) (line-chars line)))
+	       ((eq line end-line)
+		(%sp-byte-blt (line-chars line) 0 string index dst-length))
+	    (declare (simple-string chars))
+	    (%sp-byte-blt (line-chars line) 0 string index
+			  (incf index (length chars)))
+	    (setf (char string index) #\newline)
+	    (setq index (1+ index)))))
+    (values string dst-length)))
+
+
+(defun string-to-region (string &key charprops)
+  "Returns a region containing the characters in the given String."
+  (let* ((string (if (simple-string-p string)
+		     string (coerce string 'simple-string)))
+	 (end (length string)))
+    (declare (simple-string string))
+    (do* ((index 0)
+	  (buffer (next-disembodied-buffer-counter))
+	  (previous-line)
+	  (line (make-line :%buffer buffer))
+	  (first-line line))
+	 (())
+      (set-line-charprops line charprops)
+      (let ((right-index (%sp-find-character string index end #\newline)))
+	(cond (right-index
+	       (let* ((length (- right-index index))
+		      (chars (make-string length)))
+		 (%sp-byte-blt string index chars 0 length)
+		 (setf (line-chars line) chars))
+	       (setq index (1+ right-index))
+	       (setq previous-line line)
+	       (setq line (make-line :%buffer buffer))
+	       (setf (line-next previous-line) line)
+	       (setf (line-previous line) previous-line))
+	      (t
+	       (let* ((length (- end index))
+		      (chars (make-string length)))
+		 (%sp-byte-blt string index chars 0 length)
+		 (setf (line-chars line) chars))
+	       (return (renumber-region
+			(internal-make-region
+			 (mark first-line 0 :right-inserting)
+			 (mark line (length (line-chars line))
+			       :left-inserting))))))))))
+
+(defun line-to-region (line)
+  "Returns a region containing the specified line."
+  (internal-make-region (mark line 0 :right-inserting)
+			(mark line (line-length* line) :left-inserting)))
+
+
+(defun previous-character (mark)
+  "Returns the character immediately before the given Mark."
+  (let ((line (mark-line mark))
+	(charpos (mark-charpos mark)))
+    (if (= charpos 0)
+	(if (line-previous line)
+	    #\newline
+	    nil)
+	(if (current-open-line-p line)
+	    (char (the simple-string (current-open-chars))
+		  (if (<= charpos (current-left-open-pos))
+		      (1- charpos)
+		      (1- (+ (current-right-open-pos) (- charpos (current-left-open-pos))))))
+	    (schar (line-chars line) (1- charpos))))))
+
+(defun next-character (mark)
+  "Returns the character immediately after the given Mark."
+  (let ((line (mark-line mark))
+	(charpos (mark-charpos mark)))
+    (if (current-open-line-p line)
+	(if (= charpos (- (current-line-cache-length) (- (current-right-open-pos) (current-left-open-pos))))
+	    (if (line-next line)
+		#\newline
+		nil)
+	    (schar (current-open-chars)
+		   (if (< charpos (current-left-open-pos))
+		       charpos
+		       (+ (current-right-open-pos) (- charpos (current-left-open-pos))))))
+	(let ((chars (line-chars line)))
+	  (if (= charpos (strlen chars))
+	      (if (line-next line)
+		  #\newline
+		  nil)
+	      (schar chars charpos))))))
+
+
+;;; %Set-Next-Character  --  Internal
+;;;
+;;;    This is the setf form for Next-Character.  Since we may change a
+;;; character to or from a newline, we must be prepared to split and
+;;; join lines.  We cannot just delete  a character and insert the new one
+;;; because the marks would not be right.
+;;;
+(defun %set-next-character (mark character)
+  (let* ((line (mark-line mark))
+         (charpos (mark-charpos mark))
+	 (next (line-next line))
+	 (buffer (line-%buffer line)))
+    (check-buffer-modification buffer mark)
+    (modifying-buffer buffer
+      (modifying-line line mark)
+      (cond ((= (mark-charpos mark)
+		(- (current-line-cache-length) (- (current-right-open-pos) (current-left-open-pos))))
+	     ;; The mark is at the end of the line.
+	     (unless next
+	       (error "~S has no next character, so it cannot be set." mark))
+	     (unless (char= character #\newline)
+	       ;; If the character is no longer a newline then mash two
+	       ;; lines together.
+	       (let ((chars (line-chars next)))
+		 (declare (simple-string chars))
+		 (setf (current-right-open-pos) (- (current-line-cache-length) (length chars)))
+		 (when (<= (current-right-open-pos) (current-left-open-pos))
+		   (grow-open-chars (* (+ (length chars) (current-left-open-pos) 1) 2)))
+		 (%sp-byte-blt chars 0 (current-open-chars) (current-right-open-pos) 
+			       (current-line-cache-length))
+		 (setf (schar (current-open-chars) (current-left-open-pos)) character)
+		 (incf (current-left-open-pos)))
+
+               ;; merge charprops
+               (join-line-charprops line (line-next line))
+                   
+	       (move-some-marks (charpos next line) 
+				(+ charpos (current-left-open-pos)))
+	       (setq next (line-next next))
+	       (setf (line-next line) next)
+	       (when next (setf (line-previous next) line))))
+	    ((char= character #\newline)
+	     ;; The char is being changed to a newline, so we must split lines.
+	     (incf (current-right-open-pos))
+	     (let* ((len (- (current-line-cache-length) (current-right-open-pos)))	   
+		    (chars (make-string len))
+		    (new (make-line :chars chars  :previous line 
+				    :next next  :%buffer buffer)))
+	       (%sp-byte-blt (current-open-chars) (current-right-open-pos) chars 0 len)
+
+               ;; split charprops
+               (multiple-value-bind (left right)
+                                    (split-line-charprops line charpos)
+                 (setf (line-charprops-changes line) left
+                       (line-charprops-changes new) right))
+
+	       (maybe-move-some-marks* (charpos line new) (current-left-open-pos)
+				       (- charpos (current-left-open-pos) 1))
+	       (setf (line-next line) new)
+	       (when next (setf (line-previous next) new))
+	       (setf (current-right-open-pos) (current-line-cache-length))
+	       (number-line new)))
+	    (t
+	     (setf (char (the simple-string (current-open-chars)) (current-right-open-pos))
+		   character)
+	     (hemlock-ext:buffer-note-modification buffer mark 1)))))
+  character)
+
+;;; %Set-Previous-Character  --  Internal
+;;;
+;;;    The setf form for Previous-Character.  We just Temporarily move the
+;;; mark back one and call %Set-Next-Character.
+;;;
+(defun %set-previous-character (mark character)
+  (unless (mark-before mark)
+    (error "~S has no previous character, so it cannot be set." mark))
+  (%set-next-character mark character)
+  (mark-after mark)
+  character)
+
+
+(defun count-lines (region)
+  "Returns the number of lines in the region, first and last lines inclusive."
+  (do ((line (mark-line (region-start region)) (line-next line))
+       (count 1 (1+ count))
+       (last-line (mark-line (region-end region))))
+      ((eq line last-line) count)))
+
+(defun count-characters (region)
+  "Returns the number of characters in the region."
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (first-line (mark-line start))
+	 (last-line (mark-line end)))
+    (if (eq first-line last-line)
+      (- (mark-charpos end) (mark-charpos start))
+      (do ((line (line-next first-line) (line-next line))
+           (count (1+ (- (line-length* first-line) (mark-charpos start)))))
+          ((eq line last-line)
+           (+ count (mark-charpos end)))
+        (setq count (+ 1 count (line-length* line)))))))
+
+(defun line-start (mark &optional line)
+  "Changes the Mark to point to the beginning of the Line and returns it.
+  Line defaults to the line Mark is on."
+  (when line
+    (change-line mark line))
+  (setf (mark-charpos mark) 0)
+  mark)
+
+(defun line-end (mark &optional line)
+  "Changes the Mark to point to the end of the line and returns it.
+  Line defaults to the line Mark is on."
+  (if line
+      (change-line mark line)
+      (setq line (mark-line mark)))
+  (setf (mark-charpos mark) (line-length* line))
+  mark)
+
+(defun buffer-start (mark &optional (buffer (mark-buffer mark)))
+  "Change Mark to point to the beginning of Buffer, which defaults to
+  the buffer Mark is currently in."
+  (unless buffer (error "Mark ~S does not point into a buffer." mark))
+  (move-mark mark (buffer-start-mark buffer)))
+
+(defun buffer-end (mark &optional (buffer (mark-buffer mark)))
+  "Change Mark to point to the end of Buffer, which defaults to
+  the buffer Mark is currently in."
+  (unless buffer (error "Mark ~S does not point into a buffer." mark))
+  (move-mark mark (buffer-end-mark buffer)))
+
+(defun move-mark (mark new-position)
+  "Changes the Mark to point to the same position as New-Position."
+  (let* ((line (mark-line new-position)))
+    (change-line mark line))
+  (setf (mark-charpos mark) (mark-charpos new-position))
+  mark)
+
+
+
+(defun mark-before (mark)
+  "Changes the Mark to point one character before where it currently points.
+  NIL is returned if there is no previous character."
+  (let ((charpos (mark-charpos mark)))
+    (cond ((zerop charpos)
+	   (let ((prev (line-previous (mark-line mark))))
+	     (when prev
+	       (always-change-line mark prev)
+	       (setf (mark-charpos mark) (line-length* prev))
+	       mark)))
+	  (t
+	   (setf (mark-charpos mark) (1- charpos))
+	   mark))))
+
+(defun mark-after (mark)
+  "Changes the Mark to point one character after where it currently points.
+  NIL is returned if there is no next character."
+  (let ((line (mark-line mark))
+	(charpos (mark-charpos mark)))
+    (cond ((= charpos (line-length* line))
+	   (let ((next (line-next line)))
+	     (when next
+	       (always-change-line mark next)
+	       (setf (mark-charpos mark) 0)
+	       mark)))
+	  (t
+	   (setf (mark-charpos mark) (1+ charpos))
+	   mark))))
+
+
+(defun character-offset (mark n)
+  "Changes the Mark to point N characters after (or -N before if N is negative)
+  where it currently points.  If there aren't N characters before (or after)
+  the mark, Nil is returned."
+  (let* ((charpos (mark-charpos mark)))
+    (if (< n 0)
+      (let ((n (- n)))
+        (if (< charpos n)
+          (do ((line (line-previous (mark-line mark)) (line-previous line))
+               (n (- n charpos 1)))
+              ((null line) nil)
+            (let ((length (line-length* line)))
+              (cond ((<= n length)
+                     (always-change-line mark line)
+                     (setf (mark-charpos mark) (- length n))
+                     (return mark))
+                    (t
+                     (setq n (- n (1+ length)))))))
+          (progn (setf (mark-charpos mark) (- charpos n))
+                 mark)))
+      (let* ((line (mark-line mark))
+             (length (line-length* line)))
+        (if (> (+ charpos n) length)
+          (do ((line (line-next line) (line-next line))
+               (n (- n (1+ (- length charpos)))))
+              ((null line) nil)
+            (let ((length (line-length* line)))
+              (cond ((<= n length)
+                     (always-change-line mark line)
+                     (setf (mark-charpos mark) n)
+                     (return mark))
+                    (t
+                     (setq n (- n (1+ length)))))))
+          (progn (setf (mark-charpos mark) (+ charpos n))
+                 mark))))))
+
+
+(defun line-offset (mark n &optional charpos)
+  "Changes to Mark to point N lines after (-N before if N is negative) where
+  it currently points.  If there aren't N lines after (or before) the Mark,
+  Nil is returned."
+    (if (< n 0)
+            (do ((line (mark-line mark) (line-previous line))
+                 (n n (1+ n)))
+                ((null line) nil)
+              (when (= n 0)
+                (always-change-line mark line)
+                (setf (mark-charpos mark)
+                      (if charpos
+                        (min (line-length line) charpos)
+                        (min (line-length line) (mark-charpos mark))))
+                (return mark)))
+            (do ((line (mark-line mark) (line-next line))
+                 (n n (1- n)))
+                ((null line) nil)
+              (when (= n 0)
+                (change-line mark line)
+                (setf (mark-charpos mark)
+                      (if charpos
+                        (min (line-length line) charpos)
+                        (min (line-length line) (mark-charpos mark))))
+                (return mark)))))
+
+;;; region-bounds  --  Public
+;;;
+(defun region-bounds (region)
+  "Return as multiple-value the start and end of Region."
+  (values (region-start region) (region-end region)))
+
+(defun set-region-bounds (region start end)
+  "Set the start and end of Region to the marks Start and End."
+  (let ((sl (mark-line start))
+	(el (mark-line end)))
+    (when (or (neq (line-%buffer sl) (line-%buffer el))
+	      (> (line-number sl) (line-number el))
+	      (and (eq sl el) (> (mark-charpos start) (mark-charpos end))))
+      (error "Marks ~S and ~S cannot be made into a region." start end))
+    (setf (region-start region) start  (region-end region) end))
+  region)
+
+
+
+;;;; Debugging stuff.
+
+(defun slf (string)
+  "For a good time, figure out what this function does, and why it was written."
+  (delete #\linefeed (the simple-string string)))
+
+(defun %print-whole-line (structure stream)
+  (let* ((hi::*current-buffer* (or (line-buffer structure) hi::*current-buffer*)))
+    (cond ((current-open-line-p structure)
+	   (write-string (current-open-chars) stream :end (current-left-open-pos))
+	   (write-string (current-open-chars) stream :start (current-right-open-pos)
+			 :end (current-line-cache-length)))
+	  (t
+	   (write-string (line-chars structure) stream)))))
+
+(defun %print-before-mark (mark stream)
+  (let* ((hi::*current-buffer* (or (mark-buffer mark) hi::*current-buffer*)))
+    (if (mark-line mark)
+	(let* ((line (mark-line mark))
+	       (chars (line-chars line))
+	       (charpos (mark-charpos mark))
+	       (length (line-length line)))
+	  (declare (simple-string chars))
+	  (cond ((or (> charpos length) (< charpos 0))
+		 (write-string "{bad mark}" stream))
+		((current-open-line-p line)
+		 (cond ((< charpos (current-left-open-pos))
+			(write-string (current-open-chars) stream :end charpos))
+		       (t
+			(write-string (current-open-chars) stream :end (current-left-open-pos))
+			(let ((p (+ charpos (- (current-right-open-pos) (current-left-open-pos)))))
+			  (write-string (current-open-chars) stream  :start (current-right-open-pos)
+					:end p)))))
+		(t
+		 (write-string chars stream :end charpos))))
+	(write-string "{deleted mark}" stream))))
+
+
+(defun %print-after-mark (mark stream)
+  (let* ((hi::*current-buffer* (or (mark-buffer mark) hi::*current-buffer*)))
+    (if (mark-line mark)
+	(let* ((line (mark-line mark))
+	       (chars (line-chars line))
+	       (charpos (mark-charpos mark))
+	       (length (line-length line)))
+	  (declare (simple-string chars))
+	  (cond ((or (> charpos length) (< charpos 0))
+		 (write-string "{bad mark}" stream))
+		((current-open-line-p line)
+		 (cond ((< charpos (current-left-open-pos))
+			(write-string (current-open-chars) stream  :start charpos
+				      :end (current-left-open-pos))
+			(write-string (current-open-chars) stream  :start (current-right-open-pos)
+				      :end (current-line-cache-length)))
+		       (t
+			(let ((p (+ charpos (- (current-right-open-pos) (current-left-open-pos)))))
+			  (write-string (current-open-chars) stream :start p
+					:end (current-line-cache-length))))))
+		(t
+		 (write-string chars stream  :start charpos  :end length))))
+	(write-string "{deleted mark}" stream))))
+
+(defun %print-hline (structure stream d)
+  (declare (ignore d))
+  (write-string "#<Hemlock Line \"" stream)
+  (%print-whole-line structure stream)
+  (write-string "\">" stream))
+
+(defun %print-hmark (structure stream d)
+  (declare (ignore d))
+  (let ((hi::*current-buffer* (or (mark-buffer structure) hi::*current-buffer*)))
+    (write-string "#<Hemlock Mark \"" stream)
+    (%print-before-mark structure stream)
+    (write-string "^" stream)
+    (%print-after-mark structure stream)
+    (write-string "\">" stream)))
+
+(defvar *print-region* 10
+  "The number of lines to print out of a region, or NIL if none.")
+
+(defun %print-hregion (region stream d)
+  (declare (ignore d))
+  (write-string "#<Hemlock Region \"" stream)
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (hi::*current-buffer* (or (mark-buffer start) hi::*current-buffer*))
+	 (first-line (mark-line start))
+	 (last-line (mark-line end)))
+    (cond
+     ((not (and (linep first-line) (linep last-line)
+		(eq (line-%buffer first-line) (line-%buffer last-line))
+		(mark<= start end)))
+      (write-string "{bad region}" stream))
+     (*print-region*
+      (cond ((eq first-line last-line)
+	     (let ((cs (mark-charpos start))
+		   (ce (mark-charpos end))
+		   (len (line-length first-line)))
+	       (cond
+		((or (< cs 0) (> ce len))
+		 (write-string "{bad region}" stream))
+		((current-open-line-p first-line)
+		 (let ((gap (- (current-right-open-pos) (current-left-open-pos))))
+		   (cond
+		    ((<= ce (current-left-open-pos))
+		     (write-string (current-open-chars) stream  :start cs  :end ce))
+		    ((>= cs (current-left-open-pos))
+		     (write-string (current-open-chars) stream  :start (+ cs gap)
+				   :end (+ ce gap)))
+		    (t
+		     (write-string (current-open-chars) stream :start cs
+				   :end (current-left-open-pos))
+		     (write-string (current-open-chars) stream :start (current-right-open-pos)
+				   :end (+ gap ce))))))
+		(t
+		 (write-string (line-chars first-line) stream  :start cs
+			       :end ce)))))
+	    (t
+	     (%print-after-mark start stream)
+	     (write-char #\/ stream)
+	     (do ((line (line-next first-line) (line-next line))
+		  (last-line (mark-line end))
+		  (cnt *print-region* (1- cnt)))
+		 ((or (eq line last-line)
+		      (when (zerop cnt) (write-string "..." stream) t))
+		  (%print-before-mark end stream))
+	       (%print-whole-line line stream)
+	       (write-char #\/ stream)))))
+     (t
+      (write-string "{mumble}" stream))))
+  (write-string "\">" stream))
+
+(defun %print-hbuffer (structure stream d)
+  (declare (ignore d))
+  (write-string "#<Hemlock Buffer \"" stream)
+  (write-string (buffer-name structure) stream)
+  (write-string "\">" stream))
+
+(defun check-buffer-modification (buffer mark)
+  (when (typep buffer 'buffer)
+    (let* ((protected-region (buffer-protected-region buffer)))
+      (when protected-region
+        (let* ((prot-start (region-start protected-region))
+               (prot-end (region-end protected-region)))
+          
+          (when (and (mark>= mark prot-start)
+                     (mark< mark prot-end))
+            (editor-error "Can't modify protected buffer region.")))))))
Index: /branches/new-random/cocoa-ide/hemlock/src/htext3.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/htext3.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/htext3.lisp	(revision 13309)
@@ -0,0 +1,349 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; More Hemlock Text-Manipulation functions.
+;;; Written by Skef Wholey.
+;;;
+;;; The code in this file implements the insert functions in the
+;;; "Doing Stuff and Going Places" chapter of the Hemlock Design document.
+;;;
+
+(in-package :hemlock-internals)
+
+;;; Return (and deactivate) the current region.
+(defun %buffer-current-region (b)
+  (when (and (typep b 'buffer)
+             (variable-value 'hemlock::active-regions-enabled)
+             (eql (buffer-signature b)
+                  (buffer-region-active b)))
+    (let* ((mark (buffer-%mark b))
+           (point (buffer-point b)))
+      (setf (buffer-region-active b) nil)
+      (if (mark< mark point)
+        (region mark point)
+        (region point mark)))))
+
+;;; Return T if the buffer has an active region (without deactivating
+;;; it), NIL otherwise.
+(defun %buffer-current-region-p (b)
+  (and (typep b 'buffer)
+             (variable-value 'hemlock::active-regions-enabled)
+             (eql (buffer-signature b)
+                  (buffer-region-active b))))
+
+
+             
+
+
+(defun insert-character (mark character &key (charprops :neighbor))
+  "Inserts the Character at the specified Mark."
+  (declare (type base-char character))
+  (let* ((line (mark-line mark))
+         (charpos (mark-charpos mark))
+	 (buffer (line-%buffer line)))
+    (modifying-buffer buffer
+      (modifying-line line mark)
+      (cond ((char= character #\newline)
+             (let* ((next (line-next line))
+                    (new-chars (subseq (the simple-string (current-open-chars))
+                                       0 (current-left-open-pos)))
+                    (new-line (make-line :%buffer buffer
+                                         :chars (next-cache-modification-tick)
+                                         :previous line
+                                         :next next)))
+
+               ;; Do newlines get properties?  What if a charprops arg is
+               ;; specified here?
+               (multiple-value-bind (left right)
+                                    (split-line-charprops line charpos)
+                 (setf (line-charprops-changes line) left
+                       (line-charprops-changes new-line) right))
+
+               (maybe-move-some-marks (charpos line new-line) (current-left-open-pos)
+                                      (- charpos (current-left-open-pos)))
+                 
+               (setf (line-%chars line) new-chars)
+               (setf (line-next line) new-line)
+               (if next (setf (line-previous next) new-line))
+               (number-line new-line)
+               (setf (current-open-line) new-line
+                     (current-left-open-pos) 0)))
+            (t
+             (if (= (current-right-open-pos) (current-left-open-pos))
+               (grow-open-chars))
+
+             ;; Rule: when charprops is :neighbor, an inserted character
+             ;; takes on on the properties of the preceding character,
+             ;; unless the character is being inserted at the beginning of
+             ;; a line, in which case it takes on the the properties of the
+             ;; following character.
+
+             (if (eq charprops :neighbor)
+               (if (start-line-p mark)
+                 (adjust-line-charprops line 1)
+                 (adjust-line-charprops line 1 :start (1- charpos)))
+               (let* ((next-props (next-charprops mark))
+                      (prev-props (previous-charprops mark)))
+                 (cond ((charprops-equal charprops prev-props)
+                        ;;(format t "~& prev props (~s) equal" prev-props)
+                        (adjust-line-charprops line 1 :start (1- charpos)))
+                       ((charprops-equal charprops next-props)
+                        ;;(format t "~& next props (~s) equal" next-props)
+                        (adjust-line-charprops (line-charprops-changes line) 1 :start charpos))
+                       (t
+                        ;;(format t "~& surrounding props (~s, ~s) not equal" prev-props next-props)
+                        (adjust-line-charprops line 1 :start charpos)
+                        (set-line-charprops line charprops :start charpos
+                                        :end (1+ charpos))))))
+
+             (maybe-move-some-marks (charpos line) (current-left-open-pos)
+                                    (1+ charpos))
+	     
+             (cond
+              ((eq (mark-%kind mark) :right-inserting)
+               (decf (current-right-open-pos))
+               (setf (char (the simple-string (current-open-chars)) (current-right-open-pos))
+                     character))
+              (t
+               (setf (char (the simple-string (current-open-chars)) (current-left-open-pos))
+                     character)
+               (incf (current-left-open-pos))))))
+      (adjust-line-origins-forward line)
+      (hemlock-ext:buffer-note-insertion buffer mark 1))))
+
+
+
+(defun insert-string (mark string &key (charprops :neighbor))
+  "Inserts the String at the Mark."
+  (let* ((line (mark-line mark))
+         (charpos (mark-charpos mark))
+         (len (length string))
+	 (buffer (line-%buffer line))
+	 (string (coerce string 'simple-string)))
+    (declare (simple-string string))
+    (unless (zerop len)
+      (if (%sp-find-character string 0 len #\newline)
+        (progn
+          (when (eq charprops :neighbor)
+            (if (start-line-p mark)
+              (setq charprops (next-charprops mark))
+              (setq charprops (previous-charprops mark))))
+          (ninsert-region mark (string-to-region string :charprops charprops)))
+        (modifying-buffer buffer
+          (modifying-line line mark)
+          (if (<= (current-right-open-pos) (+ (current-left-open-pos) len))
+            (grow-open-chars (* (+ (current-line-cache-length) len) 2)))
+
+          (if (eq charprops :neighbor)
+            (if (start-line-p mark)
+              (adjust-line-charprops line len)
+              (adjust-line-charprops line len :start (1- charpos)))
+            (let* ((next-props (next-charprops mark))
+                   (prev-props (previous-charprops mark)))
+              (cond ((charprops-equal charprops prev-props)
+                     ;;(format t "~& prev props (~s) equal" prev-props)
+                     (adjust-line-charprops line len :start (1- charpos)))
+                    ((charprops-equal charprops next-props)
+                     ;;(format t "~& next props (~s) equal" next-props)
+                     (adjust-line-charprops line len :start charpos))
+                    (t
+                     ;;(format t "~& surrounding props (~s, ~s) not equal" prev-props next-props)
+                     (set-line-charprops line charprops :start charpos
+                                     :end (+ charpos len))))))
+
+          (maybe-move-some-marks (charpos line) (current-left-open-pos)
+                                 (+ charpos len))
+          (cond
+           ((eq (mark-%kind mark) :right-inserting)
+            (let ((new (- (current-right-open-pos) len)))
+              (%sp-byte-blt string 0 (current-open-chars) new (current-right-open-pos))
+              (setf (current-right-open-pos) new)))
+           (t
+            (let ((new (+ (current-left-open-pos) len)))
+              (%sp-byte-blt string 0 (current-open-chars) (current-left-open-pos) new)
+              (setf (current-left-open-pos) new))))
+	  (adjust-line-origins-forward line)
+	  (hemlock-ext:buffer-note-insertion buffer mark (length string)))))))
+
+
+(defconstant line-number-interval-guess 8
+  "Our first guess at how we should number an inserted region's lines.")
+
+(defun insert-region (mark region)
+  "Inserts the given Region at the Mark."
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (first-line (mark-line start))
+	 (last-line (mark-line end))
+	 (first-charpos (mark-charpos start))
+	 (last-charpos (mark-charpos end))
+         (nins (count-characters region))
+         (dest-line (mark-line mark))
+         (dest-charpos (mark-charpos mark)))
+    (cond
+     ((eq first-line last-line)
+      ;; simple case -- just BLT the characters in with insert-string
+      (if (current-open-line-p first-line) (close-line))
+      (let* ((string (line-chars first-line)))
+        (unless (and (eql first-charpos 0)
+                     (eql last-charpos (length string)))
+          (setq string (subseq string first-charpos last-charpos)))
+        (insert-string mark string)
+        (apply-line-charprops dest-line (line-charprops-changes first-line)
+                              dest-charpos (+ dest-charpos (length string)))))
+     (t
+      (close-line)
+      (let* ((line (mark-line mark))
+	     (next (line-next line))
+	     (charpos (mark-charpos mark))
+	     (buffer (line-%buffer line))
+	     (old-chars (line-chars line)))
+	(declare (simple-string old-chars))
+	(modifying-buffer buffer
+	  ;;hack marked line's chars
+	  (let* ((first-chars (line-chars first-line))
+		 (first-length (length first-chars))
+		 (new-length (+ charpos (- first-length first-charpos)))
+		 (new-chars (make-string new-length)))
+	    (declare (simple-string first-chars new-chars))
+	    (%sp-byte-blt old-chars 0 new-chars 0 charpos)
+	    (%sp-byte-blt first-chars first-charpos new-chars charpos new-length)
+	    (setf (line-chars line) new-chars)
+            (apply-line-charprops line (line-charprops-changes first-line)
+                                  charpos (+ charpos first-length)))
+
+	  ;; Copy intervening lines.  We don't link the lines in until we are
+	  ;; done in case the mark is within the region we are inserting.
+	  (do* ((this-line (line-next first-line) (line-next this-line))
+		(number (+ (line-number line) line-number-interval-guess)
+			(+ number line-number-interval-guess))
+		(first (%copy-line this-line  :previous line
+				   :%buffer buffer  :number number))
+		(previous first)
+		(new-line first (%copy-line this-line  :previous previous
+					    :%buffer buffer  :number number)))
+	       ((eq this-line last-line)
+		;;make last line
+		(let* ((last-chars (line-chars new-line))
+		       (old-length (length old-chars))
+		       (new-length (+ last-charpos (- old-length charpos)))
+		       (new-chars (make-string new-length)))
+		  (%sp-byte-blt last-chars 0 new-chars 0 last-charpos)
+		  (%sp-byte-blt old-chars charpos new-chars last-charpos
+				new-length)
+		  (setf (line-next line) first)
+		  (setf (line-chars new-line) new-chars)
+                  (apply-line-charprops new-line (line-charprops-changes last-line)
+                                        0 last-charpos)
+		  (setf (line-next previous) new-line)
+		  (setf (line-next new-line) next)
+		  (when next
+		    (setf (line-previous next) new-line)
+		    (if (<= (line-number next) number)
+			(renumber-region-containing new-line)))
+		  ;;fix up the marks
+		  (maybe-move-some-marks (this-charpos line new-line) charpos
+		    (+ last-charpos (- this-charpos charpos)))))
+	    (setf (line-next previous) new-line  previous new-line))
+          (adjust-line-origins-forward line)
+          (hemlock-ext:buffer-note-insertion buffer  mark nins)))))))
+
+
+(defun ninsert-region (mark region)
+  "Inserts the given Region at the Mark, possibly destroying the Region.
+  Region may not be a part of any buffer's region."
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (first-line (mark-line start))
+	 (last-line (mark-line end))
+	 (first-charpos (mark-charpos start))
+	 (last-charpos (mark-charpos end))
+         (nins (count-characters region))
+         (dest-line (mark-line mark))
+         (dest-charpos (mark-charpos mark)))
+    (cond
+     ((eq first-line last-line)
+      ;; Simple case -- just BLT the characters in with insert-string.
+      (if (current-open-line-p first-line) (close-line))
+      (let* ((string (line-chars first-line)))
+        (unless (and (eq first-charpos 0)
+                     (eql last-charpos (length string)))
+          (setq string (subseq string first-charpos last-charpos)))
+        (insert-string mark string)
+        (apply-line-charprops dest-line (line-charprops-changes first-line)
+                              dest-charpos (+ dest-charpos (length string)))))
+     (t
+      (when (bufferp (line-%buffer first-line))
+	(error "Region is linked into Buffer ~S." (line-%buffer first-line)))
+      (close-line)
+      (let* ((line (mark-line mark))
+	     (second-line (line-next first-line))
+	     (next (line-next line))
+	     (charpos (mark-charpos mark))
+	     (buffer (line-%buffer line))
+	     (old-chars (line-chars line)))
+	(declare (simple-string old-chars))
+	(modifying-buffer buffer
+	  ;; Make new chars for first and last lines.
+	  (let* ((first-chars (line-chars first-line))
+		 (first-length (length first-chars))
+		 (new-length (+ charpos (- first-length first-charpos)))
+		 (new-chars (make-string new-length)))
+	    (declare (simple-string first-chars new-chars))
+	    (%sp-byte-blt old-chars 0 new-chars 0 charpos)
+	    (%sp-byte-blt first-chars first-charpos new-chars charpos
+			  new-length)
+	    (setf (line-chars line) new-chars)
+            (apply-line-charprops line (line-charprops-changes first-line)
+                                  charpos (+ charpos first-length)))
+	  (let* ((last-chars (line-chars last-line))
+		 (old-length (length old-chars))
+		 (new-length (+ last-charpos (- old-length charpos)))
+		 (new-chars (make-string new-length)))
+	    (%sp-byte-blt last-chars 0 new-chars 0 last-charpos)
+	    (%sp-byte-blt old-chars charpos new-chars last-charpos new-length)
+	    (setf (line-chars last-line) new-chars)
+	    (apply-line-charprops last-line (line-charprops-changes last-line)
+				  0 last-charpos))
+	  ;;; Link stuff together.
+	  (setf (line-next last-line) next)
+	  (setf (line-next line) second-line)
+	  (setf (line-previous second-line) line)
+
+	  ;;Number the inserted stuff and mash any marks.
+	  (do ((line second-line (line-next line))
+	       (number (+ (line-number line) line-number-interval-guess)
+		       (+ number line-number-interval-guess)))
+	      ((eq line next)
+	       (when next
+		 (setf (line-previous next) last-line)	       
+		 (if (<= (line-number next) number)
+		     (renumber-region-containing last-line))))
+	    (when (line-marks line)
+	      (dolist (m (line-marks line))
+		(setf (mark-line m) nil))
+	      (setf (line-marks line) nil))
+	    (setf (line-number line) number  (line-%buffer line) buffer))
+	  
+	  ;; Fix up the marks in the line inserted into.
+	  (maybe-move-some-marks (this-charpos line last-line) charpos
+	    (+ last-charpos (- this-charpos charpos)))
+          (adjust-line-origins-forward line)
+          (hemlock-ext:buffer-note-insertion buffer mark nins)))))))
+
+(defun paste-characters (position count string)
+  "Replace COUNT characters at POSITION with STRING.  POSITION is the
+absolute character position in buffer"
+  (with-mark ((m (buffer-start-mark (current-buffer))))
+    (unless (character-offset m position)
+      (buffer-end m))
+    (when (> count 0) (delete-characters m count))
+    (when string (insert-string m string))))
Index: /branches/new-random/cocoa-ide/hemlock/src/htext4.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/htext4.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/htext4.lisp	(revision 13309)
@@ -0,0 +1,454 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; More Hemlock Text-Manipulation functions.
+;;; Written by Skef Wholey and Rob MacLachlan.
+;;; Modified by Bill Chiles.
+;;; 
+;;; The code in this file implements the delete and copy functions in the
+;;; "Doing Stuff and Going Places" chapter of the Hemlock Design document.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; DELETE-CHARACTERS.
+
+(defun delete-characters (mark &optional (n 1))
+  "Deletes N characters after the mark (or -N before if N is negative)."
+  (let* ((line (mark-line mark))
+	 (charpos (mark-charpos mark))
+	 (length (line-length* line)))
+    (check-buffer-modification (line-%buffer line) mark)
+    (cond
+     ((zerop n) t)
+     ;; Deleting chars on one line, just bump the pointers.
+     ((<= 0 (+ charpos n) length)
+      (let* ((buffer (line-%buffer line)))
+        (modifying-buffer buffer
+          (modifying-line line mark)
+          (cond
+           ((minusp n)
+            (delete-line-charprops line :start (+ charpos n) :end charpos)
+            (setf (current-left-open-pos) (+ (current-left-open-pos) n))
+            (move-some-marks (pos line)
+                             (if (> pos (current-left-open-pos))
+                               (if (<= pos charpos) (current-left-open-pos) (+ pos n))
+                               pos)))
+           
+           (t
+            (delete-line-charprops line :start charpos :end (+ charpos n))
+            (setf (current-right-open-pos) (+ (current-right-open-pos) n))
+            (let ((bound (+ charpos n)))
+              (move-some-marks (pos line)
+                               (if (> pos charpos)
+                                 (if (<= pos bound) (current-left-open-pos) (- pos n))
+                                 pos)))))
+          (adjust-line-origins-forward line)
+          (hemlock-ext:buffer-note-deletion buffer mark n)
+          t)))
+     
+     ;; Deleting some newlines, punt out to delete-region.
+     (t
+      (let* ((temp-mark (mark line charpos))
+             (other-mark (character-offset temp-mark n))
+             (temp-region (make-empty-region)))
+        (cond
+         (other-mark
+          (if (< n 0)
+            (setf (region-start temp-region) other-mark
+                  (region-end temp-region) mark)
+            (setf (region-start temp-region) mark
+                  (region-end temp-region) other-mark))
+          (delete-region temp-region) t)
+         (t nil)))))))
+
+
+;;;; DELETE-REGION.
+
+(defun delete-region (region)
+  "Deletes the Region."
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (first-line (mark-line start))
+	 (last-line (mark-line end))
+	 (first-charpos (mark-charpos start))
+	 (last-charpos (mark-charpos end))
+	 (buffer (line-%buffer first-line))
+         (ndel (count-characters region)))
+    (unless (and (eq first-line last-line)
+		 (= first-charpos last-charpos))
+      (modifying-buffer buffer
+	(cond ((eq first-line last-line)
+	       ;; Simple case -- just skip over the characters:
+	       (modifying-line first-line start)
+	       (let ((num (- last-charpos first-charpos)))
+		 (setf (current-right-open-pos) (+ (current-right-open-pos) num))
+		 ;; and fix up any charprops or marks in there:
+                 (delete-line-charprops first-line :start first-charpos
+                                        :end last-charpos)
+		 (move-some-marks (charpos first-line)
+		   (if (> charpos first-charpos)
+		       (if (<= charpos last-charpos) 
+			   first-charpos
+			   (- charpos num))
+		       charpos))))
+	      (t
+	       ;; hairy case -- squish lines together:
+	       (close-line)
+	       (let* ((first-chars (line-chars first-line))
+		      (last-chars (line-chars last-line))
+		      (last-length (length last-chars)))
+		 (declare (simple-string last-chars first-chars))
+		 ;; Cons new chars for the first line.
+		 (let* ((length (+ first-charpos (- last-length last-charpos)))
+			(new-chars (make-string length)))
+		   (%sp-byte-blt first-chars 0 new-chars 0 first-charpos)
+		   (%sp-byte-blt last-chars last-charpos new-chars first-charpos
+				 length)
+		   (setf (line-chars first-line) new-chars))
+                 (copy-line-charprops last-line :start last-charpos
+                                      :end last-length)
+		 ;; fix up the first line's marks:
+		 (move-some-marks (charpos first-line)
+		   (if (> charpos first-charpos)
+		       first-charpos
+		       charpos))
+		 ;; fix up the marks of the lines in the middle and mash
+		 ;;line-%buffer:
+		 (do* ((line (line-next first-line) (line-next line))
+		       (count (next-disembodied-buffer-counter)))
+		      ((eq line last-line)
+		       (setf (line-%buffer last-line) count))
+		   (setf (line-%buffer line) count)
+		   (move-some-marks (ignore line first-line)
+		     (declare (ignore ignore))
+		     first-charpos))
+		 ;; and fix up the last line's marks:
+		 (move-some-marks (charpos last-line first-line)
+		   (if (<= charpos last-charpos)
+		       first-charpos
+		       (+ (- charpos last-charpos)
+			  first-charpos)))
+		 ;; And splice the losers out:
+		 (let ((next (line-next last-line)))
+		   (setf (line-next first-line) next)
+		   (when next (setf (line-previous next) first-line))))))
+        (adjust-line-origins-forward first-line)
+        (hemlock-ext:buffer-note-deletion buffer start ndel)))))
+
+
+
+
+;;;; DELETE-AND-SAVE-REGION.
+
+(defun delete-and-save-region (region)
+  "Deletes Region and returns a region containing the deleted characters."
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (first-line (mark-line start))
+	 (last-line (mark-line end))
+	 (first-charpos (mark-charpos start))
+	 (last-charpos (mark-charpos end))
+	 (buffer (line-%buffer first-line))
+         (ndel (count-characters region)))
+    (check-buffer-modification buffer start)
+    (check-buffer-modification buffer end)
+    (cond
+      ((and (eq first-line last-line)
+            (= first-charpos last-charpos))
+       (make-empty-region))
+      (t
+       (modifying-buffer
+        buffer
+        (prog1
+            (cond ((eq first-line last-line)
+                   ;; simple case -- just skip over the characters:
+                   (modifying-line first-line start)
+                   (let* ((num (- last-charpos first-charpos))
+                          (new-right (+ (current-right-open-pos) num))
+                          (new-chars (make-string num))
+                          (new-line (make-line
+                                     :chars new-chars  :number 0
+                                     :charprops-changes
+                                     (copy-line-charprops first-line
+                                                          :start first-charpos
+                                                          :end last-charpos)
+                                     :%buffer (next-disembodied-buffer-counter))))
+                     (declare (simple-string new-chars))
+                     (%sp-byte-blt (current-open-chars) (current-right-open-pos) new-chars 0 num) 
+                     (setf (current-right-open-pos) new-right)
+                     ;; and fix up any charprops or marks in there:
+                     (delete-line-charprops first-line :start first-charpos
+					    :end last-charpos)
+                     (move-some-marks (charpos first-line)
+                                      (if (> charpos first-charpos)
+                                        (if (<= charpos last-charpos)
+                                          first-charpos
+                                          (- charpos num))
+                                        charpos))
+                     ;; And return the region with the nuked characters:
+                     (internal-make-region (mark new-line 0 :right-inserting)
+                                           (mark new-line num :left-inserting))))
+                  (t
+                   ;; hairy case -- squish lines together:
+                   (close-line)
+                   (let* ((first-chars (line-chars first-line))
+                          (last-chars (line-chars last-line))
+                          (first-length (length first-chars))
+                          (last-length (length last-chars))
+                          (saved-first-length (- first-length first-charpos))
+                          (saved-first-chars (make-string saved-first-length))
+                          (saved-last-chars (make-string last-charpos))
+                          (count (next-disembodied-buffer-counter))
+                          (saved-line (make-line :chars saved-first-chars
+                                                 :%buffer count)))
+                     (declare (simple-string first-chars last-chars
+                                             saved-first-chars saved-last-chars))
+                     ;; Cons new chars for victim line.
+                     (let* ((length (+ first-charpos (- last-length last-charpos)))
+                            (new-chars (make-string length)))
+                       (%sp-byte-blt first-chars 0 new-chars 0 first-charpos)
+                       (%sp-byte-blt last-chars last-charpos new-chars first-charpos
+                                     length)
+                       (setf (line-chars first-line) new-chars))
+                     ;; Make a region with all the lost stuff:
+                     (%sp-byte-blt first-chars first-charpos saved-first-chars 0
+                                   saved-first-length)
+                     (%sp-byte-blt last-chars 0 saved-last-chars 0 last-charpos)
+                     ;; Mash the chars and buff of the last line.
+                     (setf (line-chars last-line) saved-last-chars
+                           (line-%buffer last-line) count)
+                     ;; fix up the marks of the lines in the middle and mash
+                     ;;line-%buffer:
+                     (do ((line (line-next first-line) (line-next line)))
+                         ((eq line last-line)
+                          (setf (line-%buffer last-line) count))
+                       (setf (line-%buffer line) count)
+                       (move-some-marks (ignore line first-line)
+                                        (declare (ignore ignore))
+                                        first-charpos))
+                     ;; And splice the losers out:
+                     (let ((next (line-next first-line))
+                           (after (line-next last-line)))
+                       (setf (line-next saved-line) next
+                             (line-previous next) saved-line
+                             (line-next first-line) after)
+                       (when after
+                         (setf (line-previous after) first-line
+                               (line-next last-line) nil)))
+                     
+                     ;; fix up the first line's marks:
+                     (move-some-marks (charpos first-line)
+                                      (if (> charpos first-charpos)
+                                        first-charpos
+                                        charpos))
+                     ;; and fix up the last line's marks:
+                     (move-some-marks (charpos last-line first-line)
+                                      (if (<= charpos last-charpos)
+                                        first-charpos
+                                        (+ (- charpos last-charpos)
+                                           first-charpos)))
+                     ;; And return the region with the nuked characters:
+                     (renumber-region
+                      (internal-make-region
+                       (mark saved-line 0 :right-inserting)
+                       (mark last-line last-charpos :left-inserting))))))
+          (adjust-line-origins-forward first-line)
+          (hemlock-ext:buffer-note-deletion buffer start ndel)))))))
+
+
+
+
+;;;; COPY-REGION.
+
+(defun copy-region (region)
+  "Returns a region containing a copy of the text within Region."
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (first-line (mark-line start))
+	 (last-line (mark-line end))
+	 (first-charpos (mark-charpos start))
+	 (last-charpos (mark-charpos end))
+	 (count (next-disembodied-buffer-counter)))
+    (cond
+     ((eq first-line last-line)
+      (when (current-open-line-p first-line) (close-line))
+      (let* ((length (- last-charpos first-charpos))
+	     (chars (make-string length))
+	     (line (make-line :chars chars  :%buffer count  :number 0)))
+	(%sp-byte-blt (line-chars first-line) first-charpos chars 0 length)
+        (setf (line-charprops-changes line)
+              (copy-line-charprops line :start first-charpos :end last-charpos))
+	(internal-make-region (mark line 0 :right-inserting)
+			      (mark line length :left-inserting))))
+     (t
+      (close-line)
+      (let* ((first-chars (line-chars first-line))
+	     (length (- (length first-chars) first-charpos))
+	     (chars (make-string length))
+	     (first-copied-line (make-line :chars chars  :%buffer count
+					   :number 0)))
+	(declare (simple-string first-chars))
+	(%sp-byte-blt first-chars first-charpos chars 0 length)
+        (setf (line-charprops-changes first-copied-line)
+              (copy-line-charprops first-line :start first-charpos))
+	(do ((line (line-next first-line) (line-next line))
+	     (previous first-copied-line)
+	     (number line-increment (+ number line-increment)))
+	    ((eq line last-line)
+	     (let* ((chars (make-string last-charpos))
+		    (last-copied-line (make-line :chars chars
+						 :number number
+						 :%buffer count
+						 :previous previous)))
+	       (%sp-byte-blt (line-chars last-line) 0 chars 0 last-charpos)
+               (setf (line-charprops-changes last-copied-line)
+                     (copy-line-charprops last-line :end last-charpos))
+	       (setf (line-next previous) last-copied-line)
+	       (internal-make-region
+		(mark first-copied-line 0 :right-inserting)
+		(mark last-copied-line last-charpos :left-inserting))))
+	  (let* ((new-line (%copy-line line :%buffer count
+				       :number number
+				       :previous previous)))
+            ;; note that %copy-line also copies charprops changes
+	    (setf (line-next previous) new-line)
+	    (setq previous new-line))))))))
+
+
+
+
+;;;; FILTER-REGION.
+
+(eval-when (:compile-toplevel :execute)
+(defmacro fcs (fun str)
+  `(let ((rs (funcall ,fun ,str)))
+     (if (simple-string-p rs) rs
+	 (coerce rs 'simple-string))))
+); eval-when
+
+;;; FILTER-REGION  --  Public
+;;;
+;;;    After we deal with the nasty boundry conditions of the first and
+;;; last lines, we just scan through lines in the region replacing their
+;;; chars with the result of applying the function to the chars.
+;;;
+(defun filter-region (function region)
+  "This function filters the text in a region though a Lisp function.  The
+   argument function must map from a string to a string.  It is passed each
+   line string from region in order, and each resulting string replaces the
+   original.  The function must neither destructively modify its argument nor
+   modify the result string after it is returned.  The argument will always be
+   a simple-string.  It is an error for any string returned to contain
+   newlines."
+  (let* ((start (region-start region))
+         (count (hemlock::count-characters region))
+         (origin (copy-mark start :right-inserting))
+	 (start-line (mark-line start))
+	 (first (mark-charpos start))
+	 (end (region-end region))
+	 (end-line (mark-line end))
+	 (last (mark-charpos end))
+	 (marks ())
+         (buffer (line-%buffer start-line)))
+    (check-buffer-modification buffer start)
+    (check-buffer-modification buffer end)
+    (modifying-buffer buffer
+      (modifying-line end-line end)
+      (cond ((eq start-line end-line)
+	     (let* ((res (fcs function (subseq (current-open-chars) first last)))
+		    (rlen (length res))
+		    (new-left (+ first rlen))
+		    (delta (- new-left (current-left-open-pos))))
+	       (declare (simple-string res))
+	       (when (> new-left (current-right-open-pos))
+		 (grow-open-chars (+ new-left (current-line-cache-length))))
+	       (%sp-byte-blt res 0 (current-open-chars) first (current-left-open-pos))
+	       ;;
+	       ;; Move marks to start or end of region, depending on kind.
+	       (dolist (m (line-marks start-line))
+		 (let ((charpos (mark-charpos m)))
+		   (when (>= charpos first)
+		     (setf (mark-charpos m)
+			   (if (<= charpos last)
+			       (if (eq (mark-%kind m) :left-inserting)
+				   new-left first)
+			       (+ charpos delta))))))
+	       (setf (current-left-open-pos) new-left)))
+	    (t
+	     ;;
+	     ;; Do the chars for the first line.
+	     (let* ((first-chars (line-chars start-line))
+		    (first-len (length first-chars))
+		    (res (fcs function (subseq first-chars first first-len)))
+		    (rlen (length res))
+		    (nlen (+ first rlen))
+		    (new (make-string nlen)))
+	       (declare (simple-string res first-chars new))
+	       (%sp-byte-blt first-chars 0 new 0 first)
+	       (%sp-byte-blt res 0 new first nlen)
+	       (setf (line-%chars start-line) new))
+	     ;;
+	     ;; Fix up marks on the first line, saving any within the region
+	     ;; to be dealt with later.
+	     (let ((outside ()))
+	       (dolist (m (line-marks start-line))
+		 (if (<= (mark-charpos m) first)
+		     (push m outside) (push m marks)))
+	       (setf (line-marks start-line) outside))
+	     ;;
+	     ;; Do chars of intermediate lines in the region, saving their
+	     ;; marks.
+	     (do ((line (line-next start-line) (line-next line)))
+		 ((eq line end-line))
+	       (when (line-marks line)
+		 (setq marks (nconc (line-marks line) marks))
+		 (setf (line-marks line) nil))
+	       (setf (line-%chars line) (fcs function (line-chars line))))
+	     ;;
+	     ;; Do the last line, which is cached.
+	     (let* ((res (fcs function (subseq (the simple-string (current-open-chars))
+					       0 last)))
+		    (rlen (length res))
+		    (delta (- rlen last)))
+	       (declare (simple-string res))
+	       (when (> rlen (current-right-open-pos))
+		 (grow-open-chars (+ rlen (current-line-cache-length))))
+	       (%sp-byte-blt res 0 (current-open-chars) 0 rlen)
+	       (setf (current-left-open-pos) rlen)
+	       ;;
+	       ;; Adjust marks after the end of the region and save ones in it.
+	       (let ((outside ()))
+		 (dolist (m (line-marks end-line))
+		   (let ((charpos (mark-charpos m)))
+		     (cond ((> charpos last)
+			    (setf (mark-charpos m) (+ charpos delta))
+			    (push m outside))
+			   (t
+			    (push m marks)))))
+		 (setf (line-marks end-line) outside))
+	       ;;
+	       ;; Scan over saved marks, moving them to the correct end of the
+	       ;; region.
+	       (dolist (m marks)
+		 (cond ((eq (mark-%kind m) :left-inserting)
+			(setf (mark-charpos m) rlen)
+			(setf (mark-line m) end-line)
+			(push m (line-marks end-line)))
+		       (t
+			(setf (mark-charpos m) first)
+			(setf (mark-line m) start-line)
+			(push m (line-marks start-line)))))))))
+    (hemlock-ext:buffer-note-modification buffer origin count)
+    (delete-mark origin)
+    region))
Index: /branches/new-random/cocoa-ide/hemlock/src/icom.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/icom.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/icom.lisp	(revision 13309)
@@ -0,0 +1,74 @@
+;;; -*- Package: hemlock; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;   This is an italicized comment.
+
+(in-package :hemlock)
+
+(defun delete-line-italic-marks (line)
+  (dolist (m (hi::line-marks line))
+    (when (and (hi::fast-font-mark-p m)
+	       (eql (hi::font-mark-font m) 1))
+      (delete-font-mark m))))
+
+(defun set-comment-font (region font)
+  (do ((line (mark-line (region-start region))
+	     (line-next line))
+       (end (line-next (mark-line (region-end region)))))
+      ((eq line end))
+    (delete-line-italic-marks line)
+    (let ((pos (position #\; (the simple-string (line-string line)))))
+      (when pos
+	(font-mark line pos font :left-inserting)))))
+
+(defun delete-italic-marks-region (region)
+  (do ((line (mark-line (region-start region))
+	     (line-next line))
+       (end (line-next (mark-line (region-end region)))))
+      ((eq line end))
+    (delete-line-italic-marks line)))
+
+
+(defmode "Italic"
+  :setup-function
+  #'(lambda (buffer) (set-comment-font (buffer-region buffer) 1))
+  :cleanup-function
+  #'(lambda (buffer) (delete-italic-marks-region (buffer-region buffer))))
+
+(define-file-option "Italicize Comments" (buffer value)
+  (declare (ignore value))
+  (setf (buffer-minor-mode buffer "Italic") t))
+
+(defcommand "Italic Comment Mode" (p)
+  "Toggle \"Italic\" mode in the current buffer.  When in \"Italic\" mode,
+  semicolon comments are displayed in an italic font."
+  "Toggle \"Italic\" mode in the current buffer."
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Italic")
+	(not (buffer-minor-mode (current-buffer) "Italic"))))
+
+
+(defcommand "Start Italic Comment" (p)
+  "Italicize the text in this comment."
+  "Italicize the text in this comment."
+  (declare (ignore p))
+  (let* ((point (current-point))
+	 (pos (mark-charpos point))
+	 (line (mark-line point)))
+    (delete-line-italic-marks line)
+    (insert-character point #\;)
+    (font-mark
+     line
+     (or (position #\; (the simple-string (line-string line))) pos)
+     1
+     :left-inserting)))
+
+(bind-key "Start Italic Comment" #k";" :mode "Italic")
Index: /branches/new-random/cocoa-ide/hemlock/src/indent.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/indent.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/indent.lisp	(revision 13309)
@@ -0,0 +1,291 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock indentation commands
+;;;
+;;; Written by Bill Maddox and Bill Chiles
+;;;
+(in-package :hemlock)
+
+
+
+(defhvar "Spaces per Tab"
+  "The number of spaces a tab is equivalent to.  NOTE: This is not incorporated
+   everywhere in Hemlock yet, so do not change it."
+  :value 8)
+
+(defhvar "Indent with Tabs"
+  "If true, indentation is done using a mixture of tabs and spaces.  If false,
+   only spaces are used."
+  :value nil)
+
+
+(defun indent-using-tabs (mark column)
+  "Inserts at mark a maximum number of tabs and a minimum number of spaces to
+   move mark to column.  This assumes mark is at the beginning of a line."
+  (multiple-value-bind (tabs spaces) (floor column (value spaces-per-tab))
+    (dotimes (i tabs) (insert-character mark #\tab))
+    (dotimes (i spaces) (insert-character mark #\space))))
+
+(defun indent-using-spaces (mark column)
+  "Inserts some spaces at MARK so that it moves to COLUMN.  This assumes
+   mark is at the beginning of a line."
+  (insert-string mark (make-string column :initial-element #\space)))
+
+
+(defun indent-to-column (mark column)
+  "Inserts whitespace to move MARK to COLUMN, assuming mark is at column 0"
+  (if (value indent-with-tabs)
+      (indent-using-tabs mark column)
+      (indent-using-spaces mark column)))
+
+(defun indent-to-tab-stop (mark)
+  (if (value indent-with-tabs)
+      (insert-character mark #\tab)
+      (let* ((tab (value spaces-per-tab)))
+	(dotimes (i (- tab (mod (mark-column mark) tab)))
+	  (insert-character mark #\space)))))
+
+(defhvar "Indent Function"
+  "Indentation function which is invoked by \"Indent\" command.
+   It takes a :left-inserting mark that may be moved."
+  :value #'indent-to-tab-stop)
+
+
+(defun generic-indent (mark)
+  (let* ((line (mark-line mark))
+	 (prev (do ((line (line-previous line) (line-previous line)))
+		   ((or (null line) (not (blank-line-p line))) line))))
+    (unless prev (editor-error))
+    (line-start mark prev)
+    (find-attribute mark :space #'zerop)
+    (let ((indentation (mark-column mark)))
+      (line-start mark line)
+      (delete-horizontal-space mark)
+      (indent-to-column mark indentation))))
+
+
+(defcommand "Indent New Line" (p)
+  "Moves point to a new blank line and indents it.
+   Any whitespace before point is deleted.  The value of \"Indent Function\"
+   is used for indentation unless there is a Fill Prefix, in which case it is
+   used.  Any argument is passed onto \"New Line\"."
+  "Moves point to a new blank line and indents it.
+   Any whitespace before point is deleted.  The value of \"Indent Function\"
+   is used for indentation unless there is a Fill Prefix, in which case it is
+   used.  Any argument is passed onto \"New Line\"."
+  (let ((point (current-point))
+	(prefix (value fill-prefix)))
+    (delete-horizontal-space point)
+    (new-line-command p)
+    (if prefix
+	(insert-string point prefix)
+	(funcall (value indent-function) point))))
+
+
+(defcommand "Indent" (p)
+  "Invokes function held by the Hemlock variable \"Indent Function\",
+   moving point past region if called with argument."
+  "Invokes function held by the Hemlock variable \"Indent Function\"
+   moving point past region if called with argument."
+  (let ((point (current-point)))
+    (with-mark ((mark point :left-inserting))
+      (cond ((or (not p) (zerop p))
+	     (funcall (value indent-function) mark)
+             (when (mark< point mark)
+               (move-mark point mark)))
+	    (t
+	     (if (plusp p)
+		 (unless (line-offset point (1- p))
+		   (buffer-end point))
+		 (unless (line-offset mark (1+ p))
+		   (buffer-start mark)))
+	     (indent-region-for-commands (region mark point))
+	     (find-attribute (line-start point) :whitespace #'zerop))))))
+
+(defcommand "Indent Region" (p)
+  "Invokes function held by Hemlock variable \"Indent Function\" on every
+   line between point and mark, inclusively."
+  "Invokes function held by Hemlock variable \"Indent Function\" on every
+   line between point and mark, inclusively."
+  (declare (ignore p))
+  (let* ((region (current-region)))
+    (with-mark ((start (region-start region) :left-inserting)
+		(end (region-end region) :left-inserting))
+      (indent-region-for-commands (region start end)))))
+
+(defun indent-region-for-commands (region)
+  "Indents region undoably with INDENT-REGION."
+  (let* ((start (region-start region))
+	 (end (region-end region))
+	 (undo-region (copy-region (region (line-start start) (line-end end)))))
+    (indent-region region)
+    (make-region-undo :twiddle "Indent"
+		      (region (line-start (copy-mark start :left-inserting))
+			      (line-end (copy-mark end :right-inserting)))
+		      undo-region)))
+
+(defun indent-region (region)
+  "Invokes function held by Hemlock variable \"Indent Function\" on every
+   line of region."
+  (let ((indent-function (value indent-function)))
+    (with-mark ((start (region-start region) :left-inserting)
+		(end (region-end region)))
+      (line-start start)
+      (line-start end)
+      (loop (when (mark= start end)
+	      (funcall indent-function start)
+	      (return))
+	    (funcall indent-function start)
+	    (line-offset start 1 0)))))
+
+(defcommand "Center Line" (p)
+  "Centers current line using \"Fill Column\".  If an argument is supplied,
+   it is used instead of the \"Fill Column\"."
+  "Centers current line using fill-column."
+  (let* ((region (if (region-active-p)
+		     (current-region)
+		     (region (current-point) (current-point))))
+	 (end (region-end region)))
+    (with-mark ((temp (region-start region) :left-inserting))
+      (loop
+	(when (mark> temp end) (return))
+	(delete-horizontal-space (line-end temp))
+	(delete-horizontal-space (line-start temp))
+	(let* ((len (line-length (mark-line temp)))
+	       (spaces (- (or p (value fill-column)) len)))
+	  (if (and (plusp spaces) 
+		   (not (zerop len)))
+	      (indent-to-column temp (ceiling spaces 2)))
+	  (unless (line-offset temp 1) (return))
+	  (line-start temp))))))
+
+
+(defcommand "Quote Tab" (p)
+  "Insert tab character."
+  "Insert tab character."
+  (if (and p (> p 1))
+      (insert-string (current-point) (make-string p :initial-element #\tab))
+      (insert-character (current-point) #\tab)))
+
+
+(defcommand "Open Line" (p)
+  "Inserts a newline into the buffer without moving the point."
+  "Inserts a newline into the buffer without moving the point.
+  With argument, inserts p newlines."
+  (let ((point (current-point-collapsing-selection))
+	(count (if p p 1)))
+    (if (not (minusp count))
+	(dotimes (i count)
+	  (insert-character point #\newline)
+	  (mark-before point))
+	(editor-error))))
+
+
+(defcommand "New Line" (p)
+    "Moves the point to a new blank line.
+  A newline is inserted.
+  With an argument, repeats p times."
+    "Moves the point to a new blank line."
+  (let ((point (current-point-for-insertion))
+        (count (if p p 1)))
+    (if (not (minusp count))
+        (dotimes (i count) (insert-character point #\newline))
+        (editor-error))))
+
+
+
+
+(defattribute "Space"
+  "This attribute is used by the indentation commands to determine which
+  characters are treated as space."
+  '(mod 2) 0)
+
+(setf (character-attribute :space #\space) 1)
+(setf (character-attribute :space #\tab) 1)
+
+(defun delete-horizontal-space (mark)
+  "Deletes all :space characters on either side of mark."
+  (with-mark ((start mark))
+    (reverse-find-attribute start :space #'zerop)
+    (find-attribute mark :space #'zerop)
+    (delete-region (region start mark))))
+
+
+
+(defcommand "Delete Indentation" (p)
+  "Join current line with the previous one, deleting excess whitespace.
+  All whitespace is replaced with a single space, unless it is at the beginning
+  of a line, immmediately following a \"(\", or immediately preceding a \")\",
+  in which case the whitespace is merely deleted.  If the preceeding character
+  is a sentence terminator, two spaces are left instead of one.  If a prefix
+  argument is given, the following line is joined with the current line."
+  "Join current line with the previous one, deleting excess whitespace."
+  (with-mark ((m (current-point) :right-inserting))
+    (when p (line-offset m 1))
+    (line-start m)
+    (unless (delete-characters m -1) (editor-error "No previous line."))
+    (delete-horizontal-space m)
+    (let ((prev (previous-character m)))
+      (when (and prev (char/= prev #\newline))
+	(cond ((not (zerop (character-attribute :sentence-terminator prev)))
+	       (insert-string m "  "))
+	      ((not (or (eq (character-attribute :lisp-syntax prev) :open-paren)
+			(eq (character-attribute :lisp-syntax (next-character m))
+			    :close-paren)))
+	       (insert-character m #\space)))))))
+
+
+(defcommand "Delete Horizontal Space" (p)
+  "Delete spaces and tabs surrounding the point."
+  "Delete spaces and tabs surrounding the point."
+  (declare (ignore p))
+  (delete-horizontal-space (current-point)))
+
+(defcommand "Just One Space" (p)
+  "Leave one space.
+  Surrounding space is deleted, and then one space is inserted.
+  with prefix argument insert that number of spaces."
+  "Delete surrounding space and insert P spaces."
+  (let ((point (current-point)))
+    (delete-horizontal-space point)
+    (dotimes (i (or p 1)) (insert-character point #\space))))
+
+(defcommand "Back to Indentation" (p)
+  "Move point to the first non-whitespace character on the line."
+  "Move point to the first non-whitespace character on the line."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (line-start point)
+    (find-attribute point :whitespace #'zerop)))
+
+(defcommand "Indent Rigidly" (p)
+  "Indent the region rigidly by p spaces.
+   Each line in the region is moved p spaces to the right (left if p is
+   negative).  When moving a line to the left, tabs are converted to spaces."
+  "Indent the region rigidly p spaces to the right (left if p is negative)."
+  (let ((p (or p (value spaces-per-tab)))
+	(region (current-region)))
+    (with-mark ((mark1 (region-start region) :left-inserting)
+		(mark2 (region-end region) :left-inserting))
+      (line-start mark1)
+      (line-start mark2)
+      (do ()
+	  ((mark= mark1 mark2))
+	(cond ((empty-line-p mark1))
+	      ((blank-after-p mark1)
+	       (delete-characters mark1 (line-length (mark-line mark1))))
+	      (t (find-attribute mark1 :whitespace #'zerop)
+		 (let ((new-column (+ p (mark-column mark1))))
+		   (delete-characters mark1 (- (mark-charpos mark1)))
+		   (if (plusp new-column)
+		       (indent-to-column mark1 new-column)))))
+	(line-offset mark1 1 0)))))
Index: /branches/new-random/cocoa-ide/hemlock/src/interp.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/interp.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/interp.lisp	(revision 13309)
@@ -0,0 +1,432 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Rob MacLachlan and Blaine Burks.
+;;;
+;;; This file contains the routines which define hemlock commands and
+;;; the command interpreter.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+
+(defun %print-hcommand (obj stream depth)
+  (declare (ignore depth))
+  (write-string "#<Hemlock Command \"" stream)
+  (write-string (command-name obj) stream)
+  (write-string "\">" stream))
+
+
+
+
+;;;; Key Tables:
+;;;
+;;;    A key table provides a way to translate a sequence of characters to some
+;;; lisp object.  It is currently represented by a tree of hash-tables, where
+;;; each level is a hashing from a key to either another hash-table or a value.
+
+
+;;; GET-TABLE-ENTRY returns the value at the end of a series of hashings.  For
+;;; our purposes it is presently used to look up commands and key-translations.
+;;;
+(defun get-table-entry (table key &key (end (length key)))
+  (let ((foo nil))
+    (dotimes (i end foo)
+      (let ((key-event (aref key i)))
+	(setf foo (gethash key-event table))
+	(unless (hash-table-p foo) (return foo))
+	(setf table foo)))))
+
+;;; SET-TABLE-ENTRY sets the entry for key in table to val, creating new
+;;; tables as needed.  If val is nil, then use REMHASH to remove this element
+;;; from the hash-table.
+;;;
+(defun set-table-entry (table key val)
+  (dotimes (i (1- (length key)))
+    (let* ((key-event (aref key i))
+	   (foo (gethash key-event table)))
+      (if (hash-table-p foo)
+	  (setf table foo)
+	  (let ((new-table (make-hash-table)))
+	    (setf (gethash key-event table) new-table)
+	    (setf table new-table)))))
+  (if (null val)
+      (remhash (aref key (1- (length key))) table)
+      (setf (gethash (aref key (1- (length key))) table) val)))
+
+
+
+;;;; Key Translation:
+;;;
+;;;    Key translations are maintained using a key table.  If a value is an
+;;; integer, then it is prefix bits to be OR'ed with the next character.  If it
+;;; is a key, then we translate to that key.
+
+(defvar *key-translations* (make-hash-table))
+
+;;; TRANSLATE-KEY  --  Internal
+;;;
+;;;    This is used internally to do key translations when we want the
+;;; canonical representation for Key.  Result, if supplied, is an adjustable
+;;; vector with a fill pointer.  We compute the output in this vector.  If the
+;;; key ends in the prefix of a translation, we just return that part
+;;; untranslated and return the second value true.
+;;;
+(defun translate-key (key &optional (result (make-array (length key)
+							:fill-pointer 0
+							:adjustable t))
+			            (temp (make-array 10 :fill-pointer 0 :adjustable t)))
+  (let ((key-len (length key))
+	(start 0)
+	(try-pos 0)
+	(prefix 0))
+    (setf (fill-pointer temp) 0)
+    (setf (fill-pointer result) 0)
+    (loop
+      (when (= try-pos key-len) (return))
+      (let ((key-event (aref key try-pos)))
+	(vector-push-extend
+	 (make-key-event key-event (logior (key-event-bits key-event) prefix))
+	 temp)
+	(setf prefix 0))
+      (let ((entry (get-table-entry *key-translations* temp)))
+	(cond ((hash-table-p entry)
+	       (incf try-pos))
+	      (t
+	       (etypecase entry
+		 (null
+		  (vector-push-extend (aref temp 0) result)
+		  (incf start))
+		 (simple-vector
+		  (dotimes (i (length entry))
+		    (vector-push-extend (aref entry i) result))
+		  (setf start (1+ try-pos)))
+		 (integer
+		  (setf start (1+ try-pos))
+		  (when (= start key-len) (return))
+		  (setf prefix (logior entry prefix))))
+	       (setq try-pos start)
+	       (setf (fill-pointer temp) 0)))))
+    (dotimes (i (length temp))
+      (vector-push-extend (aref temp i) result))
+    (values result (not (zerop (length temp))))))
+
+
+;;; KEY-TRANSLATION -- Public.
+;;;
+(defun key-translation (key)
+  "Return the key translation for Key, or NIL if there is none.  If Key is a
+   prefix of a translation, then :Prefix is returned.  Whenever Key appears as a
+   subsequence of a key argument to the binding manipulation functions, that
+   portion will be replaced with the translation.  A key translation may also be
+   a list (:Bits {Bit-Name}*).  In this case, the named bits will be set in the
+   next character in the key being translated."
+  (let ((entry (get-table-entry *key-translations* (crunch-key key))))
+    (etypecase entry
+      (hash-table :prefix)
+      ((or simple-vector null) entry)
+      (integer
+       (cons :bits (key-event-bits-modifiers entry))))))
+
+;;; %SET-KEY-TRANSLATION  --  Internal
+;;;
+(defun %set-key-translation (key new-value)
+  (let ((entry (cond ((and (consp new-value) (eq (car new-value) :bits))
+		      (apply #'make-key-event-bits (cdr new-value)))
+		     (new-value (crunch-key new-value))
+		     (t new-value))))
+    (set-table-entry *key-translations* (crunch-key key) entry)
+    new-value))
+;;;
+(defsetf key-translation %set-key-translation
+  "Set the key translation for a key.  If set to null, deletes any
+  translation.")
+
+
+
+
+;;;; Interface Utility Functions:
+
+(defvar *global-command-table* (make-hash-table)
+  "The command table for global key bindings.")
+
+;;; GET-RIGHT-TABLE  --  Internal
+;;;
+;;;    Return a hash-table depending on "kind" and checking for errors.
+;;;
+(defun get-right-table (kind where)
+  (case kind
+     (:global
+      (when where
+	(error "Where argument ~S is meaningless for :global bindings."
+	       where))
+      *global-command-table*)
+     (:mode (let ((mode (getstring where *mode-names*)))
+	      (unless mode
+		(error "~S is not a defined mode." where))
+	      (mode-object-bindings mode)))
+     (:buffer (unless (bufferp where)
+		(error "~S is not a buffer." where))
+	      (buffer-bindings where))
+     (t (error "~S is not a valid binding type." kind))))
+
+
+;;; CRUNCH-KEY  --  Internal.
+;;;
+;;; Take a key in one of the various specifications and turn it into the
+;;; standard one: a simple-vector of characters.
+;;;
+(defun crunch-key (key)
+  (typecase key
+    (key-event (vector key))
+    ((or list vector) ;List thrown in gratuitously.
+     (when (zerop (length key))
+       (error "A zero length key is illegal."))
+     (unless (every #'key-event-p key)
+       (error "A Key ~S must contain only key-events." key))
+     (coerce key 'simple-vector))
+    (t
+     (error "Key ~S is not a key-event or sequence of key-events." key))))
+
+
+
+
+;;;; Exported Primitives:
+
+(declaim (special *command-names*))
+
+;;; BIND-KEY  --  Public.
+;;;
+(defun bind-key (name key &optional (kind :global) where)
+  "Bind a Hemlock command to some key somewhere.  Name is the string name
+   of a Hemlock command, Key is either a key-event or a vector of key-events.
+   Kind is one of :Global, :Mode or :Buffer, and where is the mode name or
+   buffer concerned.  Kind defaults to :Global."
+  ;;(with-simple-restart (continue "Go on, ignoring binding attempt."))
+  (handler-bind ((error
+                  #'(lambda (condition)
+                      (format *error-output*
+                              "~&Error while trying to bind key ~A: ~A~%"
+                              key condition)
+		      (message (format nil "~a" condition))
+                      #-GZ (return-from bind-key nil)
+		      )))
+                (let ((cmd (getstring name *command-names*))
+                      (table (get-right-table kind where))
+                      (key (copy-seq (translate-key (crunch-key key)))))
+                  (cond (cmd
+                         (set-table-entry table key cmd)
+                         (push (list key kind where) (command-%bindings cmd))
+                         cmd)
+                        (t
+                         (error "~S is not a defined command." name))))))
+
+
+;;; DELETE-KEY-BINDING  --  Public
+;;;
+;;;    Stick NIL in the key table specified.
+;;;
+(defun delete-key-binding (key &optional (kind :global) where)
+  "Remove a Hemlock key binding somewhere.  Key is either a key-event or a
+   vector of key-events.  Kind is one of :Global, :Mode or :Buffer, andl where
+   is the mode name or buffer concerned.  Kind defaults to :Global."
+  (set-table-entry (get-right-table kind where)
+		   (translate-key (crunch-key key))
+		   nil))
+
+
+;;; GET-CURRENT-BINDING  --  Internal
+;;;
+;;;    Look up a key in the current environment.
+;;;
+(defun get-current-binding (key)
+  (let ((buffer *current-buffer*)
+        (t-bindings nil) res t-res)
+    (multiple-value-setq (res t-res) (get-binding-in-buffer key buffer))
+    (when t-res (push t-res t-bindings))
+    (loop while (null res)
+      for mode in (buffer-minor-mode-objects buffer)
+      do (multiple-value-setq (res t-res) (get-binding-in-mode key mode))
+      do (when t-res (push t-res t-bindings)))
+    (when (null res)
+      (multiple-value-setq (res t-res)
+        (get-binding-in-mode key (buffer-major-mode-object buffer)))
+      (when t-res (push t-res t-bindings)))
+    (values (or res (get-table-entry *global-command-table* key))
+            (nreverse t-bindings))))
+
+(defun get-binding-in-buffer (key buffer)
+  (let ((res (get-table-entry (buffer-bindings buffer) key)))
+    (when res
+      (if (and (commandp res) (command-transparent-p res))
+        (values nil res)
+        (values res nil)))))
+
+(defun get-binding-in-mode (key mode)
+  (let* ((res (or (get-table-entry (mode-object-bindings mode) key)
+                  (let ((default (mode-object-default-command mode)))
+                    (and default (getstring default *command-names*))))))
+    (when res
+      (if (or (mode-object-transparent-p mode)
+              (and (commandp res) (command-transparent-p res)))
+        (values nil res)
+        (values res nil)))))
+  
+
+;;; GET-COMMAND -- Public.
+;;;
+(defun get-command (key &optional (kind :global) where)
+  "Return the command object for the command bound to key somewhere.
+   If key is not bound, return nil.  Key is either a key-event or a vector of
+   key-events.  If key is a prefix of a key-binding, then return :prefix.
+   Kind is one of :global, :mode or :buffer, and where is the mode name or
+   buffer concerned.  Kind defaults to :Global."
+  (multiple-value-bind (key prefix-p)
+		       (translate-key (crunch-key key))
+    (let ((entry (if (eq kind :current)
+		     (get-current-binding key)
+		     (get-table-entry (get-right-table kind where) key))))
+      (etypecase entry
+	(null (if prefix-p :prefix nil))
+	(command entry)
+	(hash-table :prefix)))))
+
+(defvar *map-bindings-key* (make-array 5 :adjustable t :fill-pointer 0))
+
+;;; MAP-BINDINGS -- Public.
+;;;
+(defun map-bindings (function kind &optional where)
+  "Map function over the bindings in some place.  The function is passed the
+   key and the command to which it is bound."
+  (labels ((mapping-fun (hash-key hash-value)
+	     (vector-push-extend hash-key *map-bindings-key*)
+	     (etypecase hash-value
+	       (command (funcall function *map-bindings-key* hash-value))
+	       (hash-table (maphash #'mapping-fun hash-value)))
+	     (decf (fill-pointer *map-bindings-key*))))
+    (setf (fill-pointer *map-bindings-key*) 0)
+    (maphash #'mapping-fun (get-right-table kind where))))
+
+;;; MAKE-COMMAND -- Public.
+;;;
+;;; If the command is already defined, then alter the command object;
+;;; otherwise, make a new command object and enter it into the *command-names*.
+;;;
+(defun make-command (name documentation function &key transparent-p)
+  "Create a new Hemlock command with Name and Documentation which is
+   implemented by calling the function-value of the symbol Function"
+  (let ((entry (getstring name *command-names*)))
+    (cond
+     (entry
+      (setf (command-name entry) name)
+      (setf (command-documentation entry) documentation)
+      (setf (command-function entry) function)
+      (setf (command-transparent-p entry) transparent-p))
+     (t
+      (setf (getstring name *command-names*)
+	    (internal-make-command name documentation function transparent-p))))))
+
+
+;;; COMMAND-NAME, %SET-COMMAND-NAME -- Public.
+;;;
+(defun command-name (command)
+  "Returns the string which is the name of Command."
+  (command-%name command))
+;;;
+(defun %set-command-name (command new-name)
+  (check-type command command)
+  (check-type new-name string)
+  (setq new-name (coerce new-name 'simple-string))
+  (delete-string (command-%name command) *command-names*)
+  (setf (getstring new-name *command-names*) command)
+  (setf (command-%name command) new-name))
+
+
+;;; COMMAND-BINDINGS -- Public.
+;;;
+;;; Check that all the supposed bindings really exists.  Bindings which
+;;; were once made may have been overwritten.  It is easier to filter
+;;; out bogus bindings here than to catch all the cases that can make a
+;;; binding go away.
+;;;
+(defun command-bindings (command)
+  "Return a list of lists of the form (key kind where) describing
+   all the places where Command is bound."
+  (check-type command command)
+  (let (result)
+    (declare (list result))
+    (dolist (place (command-%bindings command))
+      (let ((table (case (cadr place)
+		   (:global *global-command-table*)
+		   (:mode
+		    (let ((m (getstring (caddr place) *mode-names*)))
+		      (when m (mode-object-bindings m))))
+		   (t
+		    (when (member (caddr place) *buffer-list*)
+		      (buffer-bindings (caddr place)))))))
+	(when (and table
+		   (eq (get-table-entry table (car place)) command)
+		   (not (member place result :test #'equalp)))
+	  (push place result))))
+    result))
+
+(defvar *key-event-history* (make-ring 60)) 
+
+;;; LAST-COMMAND-TYPE  --  Public
+;;;
+;;;
+(defun last-command-type ()
+  "Return the command-type of the last command invoked.
+  If no command-type has been set then return NIL.  Setting this with
+  Setf sets the value for the next command."
+  *last-last-command-type*)
+
+;;; %SET-LAST-COMMAND-TYPE  --  Internal
+;;;
+(defun %set-last-command-type (type)
+  (setf (hemlock-last-command-type *current-view*) type))
+
+
+;;; PREFIX-ARGUMENT  --  Public
+;;;
+;;;
+(defun prefix-argument ()
+  "Return the current value of prefix argument."
+  *last-prefix-argument*)
+
+(defun get-self-insert-command ()
+  ;; Get the command used to implement normal character insertion in current buffer.
+  (getstring (value hemlock::self-insert-command-name) *command-names*))
+
+(defun get-default-command ()
+  ;; Get the command used when no binding is present in current buffer.
+  (getstring (value hemlock::default-command-name) *command-names*))
+
+(defun get-system-default-behavior-command ()
+  ;; Get the command used to invoke "System Default Behavior"
+  (getstring (value hemlock::system-default-behavior-command-name) *command-names*))
+
+(defvar *native-key-events* (make-hash-table :test #'eq))
+
+
+
+(defun native-key-event-p (key)
+  (check-type key key-event)
+  (gethash key *native-key-events*))
+
+
+(defun (setf native-key-event-p) (flag key)
+  (check-type key key-event)
+  (if flag
+    (setf (gethash key *native-key-events*) flag)
+    (remhash key *native-key-events*)))
Index: /branches/new-random/cocoa-ide/hemlock/src/isearchcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/isearchcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/isearchcoms.lisp	(revision 13309)
@@ -0,0 +1,322 @@
+;;; -*- Mode: Lisp; Package: hemlock -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package :hemlock)
+
+(defmode "I-Search" :precedence :highest
+  ;; Make anything that's not otherwise overridden exit i-search.
+  :default-command "I-Search Exit and Redo")
+
+(add-hook abort-hook 'end-isearch-mode)
+
+(defhvar "Self Insert Command Name"
+  "The name of the command to handle quoted input (i.e. after c-q) in I-Search"
+  :value "I-Search Self Insert"
+  :mode "I-Search")
+
+(defcommand "Incremental Search" (p)
+  "Searches for input string as characters are provided.
+
+  These are the default I-Search command characters:
+     ^Q quotes the next character typed.
+     ^W extends the search string to include the the word after the point. 
+     Delete cancels the last key typed.
+     ^G during a successful search aborts and returns point to where it started.
+       During a failing search, ^G backs up to last non-failing point.
+     ^S repeats forward, and ^R repeats backward.
+     ^R or ^S with empty string either changes the direction or yanks the previous search string.
+     Escape exits the search unless the string is empty.
+     Escape with an empty search string calls the non-incremental search command. 
+
+  Other control characters cause exit and execution of the appropriate 
+  command.
+"
+  "Set up Incremental Search mode"
+  (declare (ignore p))
+  (start-isearch-mode :forward))
+
+(defcommand "Reverse Incremental Search" (p)
+  "Searches for input string as characters are provided.
+
+  These are the default I-Search command characters:
+     ^Q quotes the next character typed.
+     ^W extends the search string to include the the word after the point. 
+     Delete cancels the last key typed.
+     ^G during a successful search aborts and returns point to where it started.
+       During a failing search, ^G backs up to last non-failing point.
+     ^S repeats forward, and ^R repeats backward.
+     ^R or ^S with empty string either changes the direction or yanks the previous search string.
+     Escape exits the search unless the string is empty.
+     Escape with an empty search string calls the non-incremental search command. 
+
+  Other control characters cause exit and execution of the appropriate 
+  command.
+"
+  "Set up Incremental Search mode"
+  (declare (ignore p))
+  (start-isearch-mode :backward))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+
+(defstruct (isearch-state (:conc-name "ISS-"))
+  string
+  direction
+  pattern
+  failure
+  wrapped-p
+  history
+  start-region)
+
+(defun current-region-info ()
+  (list (copy-mark (current-point) :temporary)
+	(copy-mark (current-mark) :temporary)
+	(region-active-p)))
+
+(defun set-current-region-info (info)
+  (destructuring-bind (point mark active-p) info
+    (move-mark (current-point) point)
+    (move-mark (current-mark) mark)
+    (if active-p
+      (progn
+	(activate-region)
+	(note-current-selection-set-by-search))
+      (deactivate-region))))
+
+(defun %i-search-save-state (iss)
+  (push (list* (iss-string iss)
+	       (iss-direction iss)
+	       (iss-failure iss)
+	       (iss-wrapped-p iss)
+	       (current-region-info))
+	(iss-history iss)))
+
+(defun %i-search-pop-state (iss)
+  (destructuring-bind (string direction failure wrapped-p . region-info)
+		      (pop (iss-history iss))
+    (setf (iss-failure iss) failure)
+    (setf (iss-wrapped-p iss) wrapped-p)
+    (%i-search-set-pattern iss :string string :direction direction)
+    (set-current-region-info region-info)))
+
+(defun %i-search-message (iss)
+  (when t ;(interactive)
+    (message "~:[~;Failing ~]~:[~;Wrapped ~]~:[Reverse I-Search~;I-Search~]: ~A"
+	     (iss-failure iss)
+	     (iss-wrapped-p iss)
+	     (eq (iss-direction iss) :forward)
+	     (or (iss-string iss) ""))))
+
+
+;; Minor errors that don't cause isearch mode to be exited, except while
+;; executing keyboard macros.
+(defun %i-search-perhaps-error (message)
+  message
+  (if t ;(interactive)
+      (beep)
+      (abort-current-command message)))
+
+;;;;
+;;
+
+(defun current-isearch-state ()
+  (or (value i-search-state)
+      (error "I-Search command invoked outside I-Search")))
+
+(defun start-isearch-mode (direction)
+  (let* ((buffer (current-buffer))
+         (iss (make-isearch-state :direction direction
+				  :start-region (current-region-info))))
+    (setf (buffer-minor-mode buffer "I-Search") t)
+    (unless (hemlock-bound-p 'i-search-state :buffer buffer)
+      (defhvar "I-Search State"
+        "Internal variable containing current state of I-Search"
+        :buffer buffer))
+    (push-new-buffer-mark (current-point))
+    (setf (value i-search-state) iss)
+    (%i-search-message iss)))
+
+(defun end-isearch-mode ()
+  (setf (buffer-minor-mode (current-buffer) "I-Search") nil))
+
+(defun i-search-backup (iss)
+  (if (iss-history iss)
+    (progn
+      (%i-search-pop-state iss)
+      (%i-search-message iss))
+    (%i-search-perhaps-error "I-Search Backup failed")))
+
+(defun i-search-revert (iss)
+  (loop while (iss-failure iss) do (%i-search-pop-state iss))
+  (%i-search-message iss))
+
+(defun i-search-repeat (iss)
+  (cond ((null (iss-string iss))
+	 ;; No search string, so "repeat" really means fetch last successful search string
+	 (if (zerop (length *last-search-string*))
+	   (%i-search-perhaps-error "No previous search string")
+	   (progn
+	     (%i-search-save-state iss)
+	     (%i-search-set-pattern iss :string *last-search-string*)
+	     (%i-search-do-search iss (current-mark)))))
+	((iss-failure iss)
+	 (%i-search-save-state iss)
+	 ;; If failed last time, "repeat" really means try again from the top.
+	 (setf (iss-wrapped-p iss) t) ;; start saying "Wrapped i-search" to remind 'em.
+	 (%i-search-do-search iss (if (eq (iss-direction iss) :forward)
+				    (buffer-start-mark (current-buffer))
+				    (buffer-end-mark (current-buffer)))))
+	(t
+	 (%i-search-save-state iss)
+	 ;; Have a non-empty string and a successful search, just find the next one!
+	 (%i-search-do-search iss (current-point))))
+  (%i-search-message iss))
+
+(defun i-search-reverse (iss)
+  (%i-search-save-state iss)
+  (%i-search-set-pattern iss :direction (ecase (iss-direction iss)
+					  (:forward :backward)
+					  (:backward :forward)))
+  (let* ((mark (current-mark))
+	 (point (current-point)))
+    (with-mark ((temp point))
+      (move-mark point mark)
+      (move-mark mark temp))
+    (when (iss-failure iss)
+      ;; if we were failing before, search immediately, otherwise wait til asked
+      (%i-search-do-search iss mark)))
+  (%i-search-message iss))
+
+(defun i-search-extend (iss extension)
+  (%i-search-save-state iss)
+  (let* ((new-string (concatenate 'simple-string (iss-string iss) extension)))
+    (%i-search-set-pattern iss :string new-string))
+  (unless (iss-failure iss)  ;; Can't succeed now if failed before, so don't try
+    (with-mark ((temp (current-mark)))
+      (when (eq (iss-direction iss) :backward)
+	(or (character-offset temp (length extension))
+	    (buffer-end temp)))
+      (%i-search-do-search iss temp)))
+  (%i-search-message iss))
+
+(defun i-search-exit (iss)
+  (let* ((string (iss-string iss)))
+    (when (and string (not (iss-failure iss)))
+      (setf *last-search-string* string)))
+  (end-isearch-mode)
+  (message ""))
+
+(defun %i-search-set-pattern (iss &key (string nil s-p) (direction nil d-p))
+  (when s-p
+    (setf (iss-string iss) (and (not (zerop (length string))) string)))
+  (when d-p
+    (setf (iss-direction iss) direction))
+  (setf (iss-pattern iss)
+	(new-search-pattern (if (value string-search-ignore-case)
+			      :string-insensitive
+			      :string-sensitive)
+			    (iss-direction iss)
+			    (or (iss-string iss) "")
+			    (iss-pattern iss))))
+
+;; Do a search for the current pattern starting at START going to
+;; end/beginning as per ISS-DIRECTION.  Sets ISS-FAILURE depending on
+;; whether found or not.  If successful, moves region to surround the
+;; found string (with point at the end for :forward search and at the
+;; beginning for :backward) and activates the region.  If failed,
+;; leaves region unchanged.  Never modifies START.
+(defun %i-search-do-search (iss start)
+  (let* ((temp (copy-mark start :temporary))
+	 (found-offset (find-pattern temp (iss-pattern iss))))
+    (setf (iss-failure iss) (not found-offset))
+    (if (iss-failure iss)
+      (%i-search-perhaps-error "I-Search failed")
+      (let* ((point (current-point))
+	     (mark (current-mark)))
+	(move-mark point temp)
+	(if (eq (iss-direction iss) :forward)
+	  (character-offset point found-offset)
+	  (character-offset temp found-offset))
+	(move-mark mark temp)
+	(activate-region)
+	(note-current-selection-set-by-search)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+
+(defcommand "I-Search Repeat Forward" (p)
+  "Repeat forward incremental search, or reverse direction if currently searching backward"
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state)))
+    (if (eq (iss-direction iss) :forward)
+      (i-search-repeat iss)
+      (i-search-reverse iss))))
+
+(defcommand "I-Search Repeat Backward" (p)
+  "Repeat backward incremental search, or reverse direction if currently searching forward"
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state)))
+    (if (eq (iss-direction iss) :backward)
+      (i-search-repeat iss)
+      (i-search-reverse iss))))
+
+(defcommand "I-Search Backup" (p)
+  "Undo last incremental search command"
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state)))
+    (i-search-backup iss)))
+
+(defcommand "I-Search Yank Word" (p)
+  "Extend the search string to include the the word after the point."
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state))
+	(point (current-point)))
+    (with-mark ((end point))
+      (if (word-offset end 1)
+	(i-search-extend iss (region-to-string (region point end)))
+	(%i-search-perhaps-error "No more words")))))
+
+(defcommand "I-Search Self Insert" (p)
+  "Add character typed to search string"
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state))
+	(char (last-char-typed)))
+    (unless char (editor-error "Can't insert that character."))
+    (i-search-extend iss (string char))))
+
+(defcommand "I-Search Abort" (p)
+  "Abort incremental search mode if search is successful.  Otherwise, revert to last
+successful search and continue searching."
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state)))
+    (if (iss-failure iss)
+      (i-search-revert iss)
+      ;; Else move back to starting point and stop searching
+      (progn
+	(set-current-region-info (iss-start-region iss))
+	(abort-current-command "Search aborted")))))
+
+;; The transparent-p flag takes care of executing the key normally when we're done,
+;; as long as we don't take a non-local exit.
+(defcommand ("I-Search Exit and Redo" :transparent-p t) (p)
+  "Exit Incremental Search and then execute the key normally"
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state)))
+    (i-search-exit iss)))
+
+(defcommand "I-Search Exit or Search" (p)
+  "Exit incremental search.  If the search string is empty, switch to non-incremental search,
+otherwise just quit"
+  (declare (ignore p))
+  (let* ((iss (current-isearch-state))
+	 (string (iss-string iss))
+	 (direction (iss-direction iss)))
+    (i-search-exit iss)
+    (when (null string)
+      (if (eq direction :forward)
+	(forward-search-command nil)
+	(reverse-search-command nil)))))
+
+
+
Index: /branches/new-random/cocoa-ide/hemlock/src/key-event.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/key-event.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/key-event.lisp	(revision 13309)
@@ -0,0 +1,698 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file implements key-events for representing editor input.
+;;;
+;;; Written by Blaine Burks and Bill Chiles.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;; Objects involved in key events:
+;;; (1) a KEY-EVENT describes a combination of a KEYSYM and MODIFIERS.  KEY-EVENTS
+;;;   are interned, so there is a unique key-event for each combination of keysym and
+;;;   modifiers.
+;;; (2) A KEYSYM is an object representing a key.  It must be declared to be so via
+;;;  define-keysym.  A KEYSYM must be defined before a key-event based on it can be
+;;;  defined.
+;;; (3) A CODE is a system-dependent fixnum value for a KEYSYM.  It must be defined
+;;; before any events actually occur, but it doesn't need to be defined in order to
+;;; create key-events.
+;;;
+;;; The Keysym can be the same as a code, but separating them deals with a bootstrapping
+;;; problem: keysyms cannot be defined before hemlock is loaded, but hemlock wants to
+;;; define key events while it's loading.  So we define key events using keysyms, and let
+;;; their codes be defined later
+
+
+;;;; Keysym <==> Name translation.
+
+;;; Keysyms are named by case-insensitive names.  However, if the name
+;;; consists of a single character, the name is case-sensitive.
+;;;
+
+;;; This table maps a keysym to a list of names.  The first name is the
+;;; preferred printing name.
+;;;
+(defvar *keysyms-to-names*)
+ 
+;;; This table maps all keysym names to the appropriate keysym.
+;;;
+(defvar *names-to-keysyms*)
+
+(declaim (inline name-keysym keysym-names keysym-preferred-name))
+
+(defun name-keysym (name)
+  "This returns the keysym named name.  If name is unknown, this returns nil."
+  (gethash (get-name-case-right name) *names-to-keysyms*))
+
+(defun keysym-names (keysym)
+  "This returns the list of all names for keysym.  If keysym is undefined,
+   this returns nil."
+  (or (gethash keysym *keysyms-to-names*)
+      (let* ((name (char-name (code-char keysym))))
+        (when name (setf (gethash keysym *keysyms-to-names*)
+                         (list name))))))
+
+(defun keysym-preferred-name (keysym)
+  "This returns the preferred name for keysym, how it is typically printed.
+   If keysym is undefined, this returns nil."
+  (car (keysym-names keysym)))
+
+
+
+
+;;;; Character key-event stuff.
+
+;;; GET-NAME-CASE-RIGHT -- Internal.
+;;;
+;;; This returns the canonical string for a keysym name for use with
+;;; hash tables.
+;;;
+(defun get-name-case-right (string)
+  (if (= (length string) 1) string (string-downcase string)))
+
+;;; DEFINE-KEYSYM -- Public
+;;;
+(defun define-keysym (keysym preferred-name &rest other-names)
+  "This establishes a mapping from preferred-name to keysym for purposes of
+   specifying key-events in #k syntax.  Other-names also map to keysym, but the
+   system uses preferred-name when printing key-events.  The names are
+   case-insensitive simple-strings.  Redefining a keysym or re-using names has
+   undefined effects."
+  (setf (gethash keysym *keysyms-to-names*) (cons preferred-name other-names))
+  (dolist (name (cons preferred-name other-names))
+    (setf (gethash (get-name-case-right name) *names-to-keysyms*) keysym)))
+
+;;; This is an a-list mapping native modifier bit masks to defined key-event
+;;; modifier names.
+;;; 
+(defvar *modifier-translations*)
+
+;;; This is an ordered a-list mapping defined key-event modifier names to the
+;;; appropriate mask for the modifier.  Modifier names have a short and a long
+;;; version.  For each pair of names for the same mask, the names are
+;;; contiguous in this list, and the short name appears first.
+;;; PRINT-PRETTY-KEY-EVENT and KEY-EVENT-BITS-MODIFIERS rely on this.
+;;;
+(defvar *modifiers-to-internal-masks*)
+
+
+
+
+
+(defvar *mouse-translation-info*)
+
+;;; MOUSE-TRANSLATION-INFO -- Internal.
+;;;
+;;; This returns the requested information, :keysym or :shifted-modifier-name,
+;;; for the button cross event-key.  If the information is undefined, this
+;;; signals an error.
+;;;
+#+unused
+(defun mouse-translation-info (button event-key info)
+  (let ((event-dispatch (svref *mouse-translation-info* button)))
+    (unless event-dispatch
+      (error "No defined mouse translation information for button ~S." button))
+    (let ((data (ecase event-key
+		  (:button-press (button-press-info event-dispatch))
+		  (:button-release (button-release-info event-dispatch)))))
+      (unless data
+	(error
+	 "No defined mouse translation information for button ~S and event ~S."
+	 button event-key))
+      (ecase info
+	(:keysym (button-keysym data))
+	(:shifted-modifier-name (button-shifted-modifier-name data))))))
+
+
+(eval-when (:compile-toplevel :execute)
+  (defmacro button-press-info (event-dispatch) `(car ,event-dispatch))
+  (defmacro button-release-info (event-dispatch) `(cdr ,event-dispatch))
+  (defmacro button-keysym (info) `(car ,info))
+  (defmacro button-shifted-modifier-name (info) `(cdr ,info))
+)
+
+;;; MOUSE-TRANSLATION-INFO -- Internal.
+;;;
+;;; This returns the requested information, :keysym or :shifted-modifier-name,
+;;; for the button cross event-key.  If the information is undefined, this
+;;; signals an error.
+;;;
+(defun mouse-translation-info (button event-key info)
+  (let ((event-dispatch (svref *mouse-translation-info* button)))
+    (unless event-dispatch
+      (error "No defined mouse translation information for button ~S." button))
+    (let ((data (ecase event-key
+		  (:button-press (button-press-info event-dispatch))
+		  (:button-release (button-release-info event-dispatch)))))
+      (unless data
+	(error
+	 "No defined mouse translation information for button ~S and event ~S."
+	 button event-key))
+      (ecase info
+	(:keysym (button-keysym data))
+	(:shifted-modifier-name (button-shifted-modifier-name data))))))
+
+;;; (setf MOUSE-TRANSLATION-INFO) -- Internal.
+;;;
+;;; This walks into *mouse-translation-info* the same way MOUSE-TRANSLATION-INFO
+;;; does, filling in the data structure on an as-needed basis, and stores
+;;; the value for the indicated info.
+;;;
+(defun (setf mouse-translation-info) (value button event-key info)
+  (let ((event-dispatch (svref *mouse-translation-info* button)))
+    (unless event-dispatch
+      (setf event-dispatch
+	    (setf (svref *mouse-translation-info* button) (cons nil nil))))
+    (let ((data (ecase event-key
+		  (:button-press (button-press-info event-dispatch))
+		  (:button-release (button-release-info event-dispatch)))))
+      (unless data
+	(setf data
+	      (ecase event-key
+		(:button-press
+		 (setf (button-press-info event-dispatch) (cons nil nil)))
+		(:button-release
+		 (setf (button-release-info event-dispatch) (cons nil nil))))))
+      (ecase info
+	(:keysym
+	 (setf (button-keysym data) value))
+	(:shifted-modifier-name
+	 (setf (button-shifted-modifier-name data) value))))))
+
+
+
+;;; DEFINE-MOUSE-KEYSYM -- Public.
+;;;
+(defun define-mouse-keysym (button keysym name shifted-bit event-key)
+  "This defines keysym named name for the X button cross the X event-key."
+  (unless (<= 1 button 5)
+    (error "Buttons are number 1-5, not ~D." button))
+  (setf (gethash keysym *keysyms-to-names*) (list name))
+  (setf (gethash  (get-name-case-right name) *names-to-keysyms*) keysym)
+  (setf (mouse-translation-info button event-key :keysym) keysym)
+  (setf (mouse-translation-info button event-key :shifted-modifier-name)
+	shifted-bit))
+
+
+
+
+;;;; Stuff for parsing #k syntax.
+
+
+
+(defstruct (key-event (:print-function %print-key-event)
+		      (:constructor %make-key-event (keysym bits)))
+  (bits nil :type fixnum)
+  (keysym nil))
+
+(defun %print-key-event (object stream ignore)
+  (declare (ignore ignore))
+  (write-string "#<Key-Event " stream)
+  (print-pretty-key object stream)
+  (write-char #\> stream))
+
+;;; This maps Common Lisp CHAR-CODE's to character classes for parsing #k
+;;; syntax.
+;;;
+(defvar *key-character-classes* (make-array hemlock-char-code-limit
+					    :initial-element :other))
+
+;;; These characters are special:
+;;;    #\<  ..........  :ISO-start - Signals start of an ISO character.
+;;;    #\>  ..........  :ISO-end - Signals end of an ISO character.
+;;;    #\-  ..........  :modifier-terminator - Indicates last *id-namestring*
+;;;                                            was a modifier.
+;;;    #\"  ..........  :EOF - Means we have come to the end of the character.
+;;;    #\{a-z, A-Z} ..  :letter - Means the char is a letter.
+;;;    #\space .......  :event-terminator- Indicates the last *id-namestring*
+;;;                                        was a character name.
+;;;
+;;; Every other character has class :other.
+;;;
+(hi::do-alpha-chars (char :both)
+  (setf (svref *key-character-classes* (char-code char)) :letter))
+(setf (svref *key-character-classes* (char-code #\<)) :ISO-start)
+(setf (svref *key-character-classes* (char-code #\>)) :ISO-end)
+(setf (svref *key-character-classes* (char-code #\-)) :modifier-terminator)
+(setf (svref *key-character-classes* (char-code #\space)) :event-terminator)
+(setf (svref *key-character-classes* (char-code #\")) :EOF)
+  
+;;; This holds the characters built up while lexing a potential keysym or
+;;; modifier identifier.
+;;;
+(defvar *id-namestring*
+  (make-array 30 :adjustable t :fill-pointer 0 :element-type 'base-char))
+
+;;; PARSE-KEY-FUN -- Internal.
+;;;
+;;; This is the #k dispatch macro character reader.  It is a FSM that parses
+;;; key specifications.  It returns either a VECTOR form or a MAKE-KEY-EVENT
+;;; form.  Since key-events are unique at runtime, we cannot create them at
+;;; readtime, returning the constant object from READ.  Wherever a #k appears,
+;;; there's a form that at loadtime or runtime will return the unique key-event
+;;; or vector of unique key-events.
+;;;
+(defun parse-key-fun (stream sub-char count)
+  (declare (ignore sub-char count))
+  (setf (fill-pointer *id-namestring*) 0)
+  (prog ((bits 0)
+	 (key-event-list ())
+	 char class)
+	(unless (char= (read-char stream) #\")
+	  (error "Keys must be delimited by ~S." #\"))
+	;; Skip any leading spaces in the string.
+	(peek-char t stream)
+	(multiple-value-setq (char class) (get-key-char stream))
+	(ecase class
+	  ((:letter :other :escaped) (go ID))
+	  (:ISO-start (go ISOCHAR))
+	  (:ISO-end (error "Angle brackets must be escaped."))
+	  (:modifier-terminator (error "Dash must be escaped."))
+	  (:EOF (error "No key to read.")))
+	ID
+	(vector-push-extend char *id-namestring*)
+	(multiple-value-setq (char class) (get-key-char stream))
+	(ecase class
+	  ((:letter :other :escaped) (go ID))
+	  (:event-terminator (go GOT-CHAR))
+	  (:modifier-terminator (go GOT-MODIFIER))
+	  ((:ISO-start :ISO-end) (error "Angle brackets must be escaped."))
+	  (:EOF (go GET-LAST-CHAR)))
+	GOT-CHAR
+	(push `(make-key-event ,(copy-seq *id-namestring*) ,bits)
+	      key-event-list)
+	(setf (fill-pointer *id-namestring*) 0)
+	(setf bits 0)
+	;; Skip any whitespace between characters.
+	(peek-char t stream)
+	(multiple-value-setq (char class) (get-key-char stream))
+	(ecase class
+	  ((:letter :other :escaped) (go ID))
+	  (:ISO-start (go ISOCHAR))
+	  (:ISO-end (error "Angle brackets must be escaped."))
+	  (:modifier-terminator (error "Dash must be escaped."))
+	  (:EOF (go FINAL)))
+	GOT-MODIFIER
+	(let ((modifier-name (car (assoc *id-namestring*
+					 *modifiers-to-internal-masks*
+					 :test #'string-equal))))
+	  (unless modifier-name
+	    (error "~S is not a defined modifier." *id-namestring*))
+	  (setf (fill-pointer *id-namestring*) 0)
+	  (setf bits (logior bits (key-event-modifier-mask modifier-name))))
+	(multiple-value-setq (char class) (get-key-char stream))
+	(ecase class
+	  ((:letter :other :escaped) (go ID))
+	  (:ISO-start (go ISOCHAR))
+	  (:ISO-end (error "Angle brackets must be escaped."))
+	  (:modifier-terminator (error "Dash must be escaped."))
+	  (:EOF (error "Expected something naming a key-event, got EOF.")))
+	ISOCHAR
+	(multiple-value-setq (char class) (get-key-char stream))
+	(ecase class
+	  ((:letter :event-terminator :other :escaped)
+	   (vector-push-extend char *id-namestring*)
+	   (go ISOCHAR))
+	  (:ISO-start (error "Open Angle must be escaped."))
+	  (:modifier-terminator (error "Dash must be escaped."))
+	  (:EOF (error "Bad syntax in key specification, hit eof."))
+	  (:ISO-end (go GOT-CHAR)))
+	GET-LAST-CHAR
+	(push `(make-key-event ,(copy-seq *id-namestring*) ,bits)
+	      key-event-list)
+	FINAL
+	(return (if (cdr key-event-list)
+		    `(vector ,@(nreverse key-event-list))
+		    `,(car key-event-list)))))
+
+(set-dispatch-macro-character #\# #\k #'parse-key-fun)
+
+(defconstant key-event-escape-char #\\
+  "The escape character that #k uses.")
+
+;;; GET-KEY-CHAR -- Internal.
+;;;
+;;; This is used by PARSE-KEY-FUN.
+;;;
+(defun get-key-char (stream)
+  (let ((char (read-char stream t nil t)))
+    (cond ((char= char key-event-escape-char)
+	   (let ((char (read-char stream t nil t)))
+	     (values char :escaped)))
+	  (t (values char (svref *key-character-classes* (char-code char)))))))
+
+
+
+
+;;;; Code to deal with modifiers.
+
+(defvar *modifier-count* 0
+  "The number of modifiers that is currently defined.")
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+
+(defconstant modifier-count-limit 6
+  "The maximum number of modifiers supported.")
+
+); eval-when
+
+;;; This is purely a list for users.
+;;;
+(defvar *all-modifier-names* ()
+  "A list of all the names of defined modifiers.")
+
+;;; Note that short-name is pushed into *modifiers-to-internal-masks* after
+;;; long-name.  PRINT-PRETTY-KEY-EVENT and KEY-EVENT-BITS-MODIFIERS rely on
+;;; this feature.
+;;;
+(defun define-key-event-modifier (long-name short-name)
+  "This establishes long-name and short-name as modifier names for purposes
+   of specifying key-events in #k syntax.  The names are case-insensitive and
+   must be strings.  If either name is already defined, this signals an error."
+  (when (= *modifier-count* modifier-count-limit)
+    (error "Maximum of ~D modifiers allowed." modifier-count-limit))
+  (let ((long-name (string-capitalize long-name))
+	(short-name (string-capitalize short-name)))
+    (flet ((frob (name)
+	     (when (assoc name *modifiers-to-internal-masks*
+			  :test #'string-equal)
+	       (restart-case
+		   (error "Modifier name has already been defined -- ~S" name)
+		 (blow-it-off ()
+		  :report "Go on without defining this modifier."
+		  (return-from define-key-event-modifier nil))))))
+      (frob long-name)
+      (frob short-name))
+    (unwind-protect
+	(let ((new-bits (ash 1 *modifier-count*)))
+	  (push (cons long-name new-bits) *modifiers-to-internal-masks*)
+	  (push (cons short-name new-bits) *modifiers-to-internal-masks*)
+	  (pushnew long-name *all-modifier-names* :test #'string-equal)
+	  ;; Sometimes the long-name is the same as the short-name.
+	  (pushnew short-name *all-modifier-names* :test #'string-equal))
+      (incf *modifier-count*))))
+
+;;;
+;;; RE-INITIALIZE-KEY-EVENTS at the end of this file defines the system
+;;; default key-event modifiers.
+;;; 
+
+;;; DEFINE-MODIFIER-BIT -- Public.
+;;;
+(defun define-modifier-bit (bit-mask modifier-name)
+  "This establishes a mapping from bit-mask to a define key-event modifier-name."
+  (let ((map (assoc modifier-name *modifiers-to-internal-masks*
+		    :test #'string-equal)))
+    (unless map (error "~S an undefined modifier name." modifier-name))
+    (push (cons bit-mask (car map)) *modifier-translations*)))
+
+;;;
+;;; RE-INITIALIZE-KEY-EVENTS at the end of this file defines the system
+;;; default modifiers, mapping them to some system default key-event
+;;; modifiers.
+;;; 
+
+(defun make-key-event-bits (&rest modifier-names)
+  "This returns bits suitable for MAKE-KEY-EVENT from the supplied modifier
+   names.  If any name is undefined, this signals an error."
+  (let ((mask 0))
+    (dolist (mod modifier-names mask)
+      (let ((this-mask (cdr (assoc mod *modifiers-to-internal-masks*
+				   :test #'string-equal))))
+	(unless this-mask (error "~S is an undefined modifier name." mod))
+	(setf mask (logior mask this-mask))))))
+
+;;; KEY-EVENT-BITS-MODIFIERS -- Public.
+;;;
+(defun key-event-bits-modifiers (bits)
+  "This returns a list of key-event modifier names, one for each modifier
+   set in bits."
+  (let ((res nil))
+    (do ((map (cdr *modifiers-to-internal-masks*) (cddr map)))
+	((null map) res)
+      (when (logtest bits (cdar map))
+	(push (caar map) res)))))
+
+;;; KEY-EVENT-MODIFIER-MASK -- Public.
+;;;
+(defun key-event-modifier-mask (modifier-name)
+  "This function returns a mask for modifier-name.  This mask is suitable
+   for use with KEY-EVENT-BITS.  If modifier-name is undefined, this signals
+   an error."
+  (let ((res (cdr (assoc modifier-name *modifiers-to-internal-masks*
+			 :test #'string-equal))))
+    (unless res (error "Undefined key-event modifier -- ~S." modifier-name))
+    res))
+
+
+
+
+;;;; Key event lookup -- GET-KEY-EVENT and MAKE-KEY-EVENT.
+
+(defvar *key-events*)
+
+;;; GET-KEY-EVENT* -- Internal.
+;;;
+;;; This finds the key-event specified by keysym and bits.  If the key-event
+;;; does not already exist, this creates it.  This assumes keysym is defined,
+;;; and if it isn't, this will make a key-event anyway that will cause an
+;;; error when the system tries to print it.
+;;;
+(defun get-key-event* (keysym bits)
+  (let* ((char (and (fixnump keysym) (code-char keysym))))
+    (when (and char (standard-char-p char))
+      (let* ((mask (key-event-modifier-mask "Shift")))
+        (when (logtest bits mask)
+          (setq bits (logandc2 bits mask)
+                keysym (char-code (char-upcase char)))))))
+  (let* ((data (cons keysym bits)))
+    (or (gethash data *key-events*)
+	(setf (gethash data *key-events*) (%make-key-event keysym bits)))))
+
+;;;
+(defvar *keysym-to-code*)
+(defvar *code-to-keysym*)
+
+(defmacro define-keysym-code (keysym code)
+  `(progn
+     (setf (gethash ,keysym *keysym-to-code*) ,code)
+     (setf (gethash ,code *code-to-keysym*) ,keysym)))
+
+(defun keysym-for-code (code)
+  (or (gethash code *code-to-keysym*) code))
+
+(defun code-for-keysym (keysym)
+  (or (gethash keysym *keysym-to-code*) (and (fixnump keysym) keysym)))
+
+;;;
+(defun make-key-event (object &optional (bits 0))
+  "This returns a key-event described by object with bits.  Object is one of
+   keysym, string, or key-event.  When object is a key-event, this uses
+   KEY-EVENT-KEYSYM.  You can form bits with MAKE-KEY-EVENT-BITS or
+   KEY-EVENT-MODIFIER-MASK."
+  (etypecase object
+    (integer
+     (let ((keysym (keysym-for-code object)))
+       (unless (keysym-names keysym)
+	 (error "~S is an undefined code." object))
+       (get-key-event* keysym bits)))
+    #|(character
+     (let* ((name (char-name object))
+	    (keysym (name-keysym (or name (string object)))))
+       (unless keysym
+	 (error "~S is an undefined keysym." object))
+       (get-key-event* keysym bits)))|#
+    (string
+     (let ((keysym (name-keysym object)))
+       (unless keysym
+	 (error "~S is an undefined keysym." object))
+       (get-key-event* keysym bits)))
+    (key-event
+     (get-key-event* (key-event-keysym object) bits))))
+
+;;; KEY-EVENT-BIT-P -- Public.
+;;;
+(defun key-event-bit-p (key-event bit-name)
+  "This returns whether key-event has the bit set named by bit-name.  This
+   signals an error if bit-name is undefined."
+  (let ((mask (cdr (assoc bit-name *modifiers-to-internal-masks*
+			  :test #'string-equal))))
+    (unless mask
+      (error "~S is not a defined modifier." bit-name))
+    (not (zerop (logand (key-event-bits key-event) mask)))))
+
+
+
+
+;;;; KEY-EVENT-CHAR and CHAR-KEY-EVENT.
+
+;;; This maps key-events to characters.  Users modify this by SETF'ing
+;;; KEY-EVENT-CHAR.
+;;;
+(defvar *key-event-characters*)
+
+(defun key-event-char (key-event)
+  "Returns the character associated with key-event. This is SETF'able."
+  (check-type key-event key-event)
+  (or (gethash key-event *key-event-characters*)
+      (code-char (code-for-keysym (key-event-keysym key-event)))))
+
+(defun %set-key-event-char (key-event character)
+  (check-type character character)
+  (check-type key-event key-event)
+  (setf (gethash key-event *key-event-characters*) character))
+;;;
+(defsetf key-event-char %set-key-event-char)
+
+
+;;; This maps characters to key-events.  Users modify this by SETF'ing
+;;; CHAR-KEY-EVENT.
+;;;
+(defvar *character-key-events*)
+
+(defun char-key-event (char)
+  "Returns the key-event associated with char.  This is SETF'able."
+  (check-type char character)
+  (svref *character-key-events* (char-code char)))
+
+(defun %set-char-key-event (char key-event)
+  (check-type char character)
+  (check-type key-event key-event)
+  (setf (svref *character-key-events* (char-code char)) key-event))
+;;;
+(defsetf char-key-event %set-char-key-event)
+
+
+
+
+;;;; DO-ALPHA-KEY-EVENTS.
+
+(defmacro alpha-key-events-loop (var start-keysym end-keysym result body)
+  (let ((n (gensym)))
+    `(do ((,n ,start-keysym (1+ ,n)))
+	 ((> ,n ,end-keysym) ,result)
+       (let ((,var (make-key-event ,n 0)))
+	 (when (alpha-char-p (key-event-char ,var))
+	   ,@body)))))
+
+(defmacro do-alpha-key-events ((var kind &optional result) &rest forms)
+  "(DO-ALPHA-KEY-EVENTS (var kind [result]) {form}*)
+   This macro evaluates each form with var bound to a key-event representing an
+   alphabetic character.  Kind is one of :lower, :upper, or :both, and this
+   binds var to each key-event in order as specified in the X11 protocol
+   specification.  When :both is specified, this processes lowercase letters
+   first."
+  (case kind
+    (:both
+     `(progn (alpha-key-events-loop ,var 97 122 nil ,forms)
+	     (alpha-key-events-loop ,var 65 90 ,result ,forms)))
+    (:lower
+     `(alpha-key-events-loop ,var 97 122 ,result ,forms))
+    (:upper
+     `(alpha-key-events-loop ,var 65 90 ,result ,forms))
+    (t (error "Kind argument not one of :lower, :upper, or :both -- ~S."
+	      kind))))
+
+
+
+
+;;;; PRINT-PRETTY-KEY and PRINT-PRETTY-KEY-EVENT.
+
+;;; PRINT-PRETTY-KEY -- Internal
+;;;
+(defun print-pretty-key (key &optional (stream *standard-output*) long-names-p)
+  "This prints key, a key-event or vector of key-events, to stream in a
+   user-expected fashion.  Long-names-p indicates whether modifiers should
+   print with their long or short name."
+  (etypecase key
+    (key-event (print-pretty-key-event key stream long-names-p))
+    (vector
+     (let ((length-1 (1- (length key))))
+       (dotimes (i (length key))
+	 (let ((key-event (aref key i)))
+	   (print-pretty-key-event key-event stream long-names-p)
+	   (unless (= i length-1) (write-char #\space stream))))))))
+
+;;; PRINT-PRETTY-KEY-EVENT -- Internal
+;;;
+;;; Note, this makes use of the ordering in the a-list
+;;; *modifiers-to-internal-masks* by CDDR'ing down it by starting on a short
+;;; name or a long name.
+;;;
+(defun print-pretty-key-event (key-event &optional (stream *standard-output*)
+					 long-names-p)
+  "This prints key-event to stream.  Long-names-p indicates whether modifier
+   names should appear using the long name or short name."
+  (do ((map (if long-names-p
+		(cdr *modifiers-to-internal-masks*)
+		*modifiers-to-internal-masks*)
+	    (cddr map)))
+      ((null map))
+    (when (not (zerop (logand (cdar map) (key-event-bits key-event))))
+      (write-string (caar map) stream)
+      (write-char #\- stream)))
+  (let* ((name (keysym-preferred-name (key-event-keysym key-event)))
+	 (spacep (position #\space (the simple-string name))))
+    (when spacep (write-char #\< stream))
+    (write-string name stream)
+    (when spacep (write-char #\> stream))))
+
+;;; PRETTY-KEY-STRING - Public.
+;;;
+(defun pretty-key-string (key &optional long-names-p)
+  (with-output-to-string (s)
+    (print-pretty-key key s long-names-p)))
+
+
+;;;; Re-initialization.
+
+;;; RE-INITIALIZE-KEY-EVENTS -- Internal.
+;;;
+(defun re-initialize-key-events ()
+  "This blows away all data associated with keysyms, modifiers, mouse
+   translations, and key-event/characters mapping.  Then it re-establishes
+   the system defined key-event modifiers and the system defined
+   modifier mappings to some of those key-event modifiers.
+
+   When recompiling this file, you should load it and call this function
+   before using any part of the key-event interface, especially before
+   defining all your keysyms and using #k syntax."
+  (setf *keysyms-to-names* (make-hash-table :test #'eql))
+  (setf *names-to-keysyms* (make-hash-table :test #'equal))
+  (setf *keysym-to-code* (make-hash-table :test #'eql))
+  (setf *code-to-keysym* (make-hash-table :test #'eql))
+  (setf *modifier-translations* ())
+  (setf *modifiers-to-internal-masks* ())
+  (setf *mouse-translation-info* (make-array 6 :initial-element nil))
+  (setf *modifier-count* 0)
+  (setf *all-modifier-names* ())
+  (setf *key-events* (make-hash-table :test #'equal))
+  (setf *key-event-characters* (make-hash-table))
+  (setf *character-key-events*
+	(make-array hemlock-char-code-limit :initial-element nil))
+  
+  (define-key-event-modifier "Hyper" "H")
+  (define-key-event-modifier "Super" "S")
+  (define-key-event-modifier "Meta" "M")
+  (define-key-event-modifier "Control" "C")
+  (define-key-event-modifier "Shift" "Shift")
+  (define-key-event-modifier "Lock" "Lock")
+
+)
+
+;;; Initialize stuff if not already initialized.
+;;;
+(unless (boundp '*keysyms-to-names*)
+  (re-initialize-key-events))
Index: /branches/new-random/cocoa-ide/hemlock/src/keysym-defs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/keysym-defs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/keysym-defs.lisp	(revision 13309)
@@ -0,0 +1,198 @@
+;;; -*- Log: hemlock.log; Mode: Lisp; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;
+;;; Written by Bill Chiles
+;;; Modified by Blaine Burks.
+;;;
+;;; This file defines all the "portable" keysyms.
+
+(in-package :hemlock-internals)
+
+;;; "Named" keys.
+;;;
+(define-keysym 9 "Tab")
+(define-keysym 27 "Escape" "Altmode" "Alt")		;escape
+(define-keysym #+cocotron 8 #-cocotron 127 "Delete" "Backspace")  ;backspace
+(define-keysym 13 "Return" "Newline")
+(define-keysym 10 "LineFeed")
+(define-keysym 3 "Enter")
+(define-keysym 32 "Space" " ")
+
+;;; Letters.
+;;;
+(define-keysym 97 "a") (define-keysym 65 "A")
+(define-keysym 98 "b") (define-keysym 66 "B")
+(define-keysym 99 "c") (define-keysym 67 "C")
+(define-keysym 100 "d") (define-keysym 68 "D")
+(define-keysym 101 "e") (define-keysym 69 "E")
+(define-keysym 102 "f") (define-keysym 70 "F")
+(define-keysym 103 "g") (define-keysym 71 "G")
+(define-keysym 104 "h") (define-keysym 72 "H")
+(define-keysym 105 "i") (define-keysym 73 "I")
+(define-keysym 106 "j") (define-keysym 74 "J")
+(define-keysym 107 "k") (define-keysym 75 "K")
+(define-keysym 108 "l") (define-keysym 76 "L")
+(define-keysym 109 "m") (define-keysym 77 "M")
+(define-keysym 110 "n") (define-keysym 78 "N")
+(define-keysym 111 "o") (define-keysym 79 "O")
+(define-keysym 112 "p") (define-keysym 80 "P")
+(define-keysym 113 "q") (define-keysym 81 "Q")
+(define-keysym 114 "r") (define-keysym 82 "R")
+(define-keysym 115 "s") (define-keysym 83 "S")
+(define-keysym 116 "t") (define-keysym 84 "T")
+(define-keysym 117 "u") (define-keysym 85 "U")
+(define-keysym 118 "v") (define-keysym 86 "V")
+(define-keysym 119 "w") (define-keysym 87 "W")
+(define-keysym 120 "x") (define-keysym 88 "X")
+(define-keysym 121 "y") (define-keysym 89 "Y")
+(define-keysym 122 "z") (define-keysym 90 "Z")
+
+;;; Standard number keys.
+;;;
+(define-keysym 49 "1") (define-keysym 33 "!")
+(define-keysym 50 "2") (define-keysym 64 "@")
+(define-keysym 51 "3") (define-keysym 35 "#")
+(define-keysym 52 "4") (define-keysym 36 "$")
+(define-keysym 53 "5") (define-keysym 37 "%")
+(define-keysym 54 "6") (define-keysym 94 "^")
+(define-keysym 55 "7") (define-keysym 38 "&")
+(define-keysym 56 "8") (define-keysym 42 "*")
+(define-keysym 57 "9") (define-keysym 40 "(")
+(define-keysym 48 "0") (define-keysym 41 ")")
+
+;;; "Standard" symbol keys.
+;;;
+(define-keysym 96 "`") (define-keysym 126 "~")
+(define-keysym 45 "-") (define-keysym 95 "_")
+(define-keysym 61 "=") (define-keysym 43 "+")
+(define-keysym 91 "[") (define-keysym 123 "{")
+(define-keysym 93 "]") (define-keysym 125 "}")
+(define-keysym 92 "\\") (define-keysym 124 "|")
+(define-keysym 59 ";") (define-keysym 58 ":")
+(define-keysym 39 "'") (define-keysym 34 "\"")
+(define-keysym 44 ",") (define-keysym 60 "<")
+(define-keysym 46 ".") (define-keysym 62 ">")
+(define-keysym 47 "/") (define-keysym 63 "?")
+
+
+(define-keysym :F1 "F1")
+(define-keysym :F2 "F2")
+(define-keysym :F3 "F3")
+(define-keysym :F4 "F4")
+(define-keysym :F5 "F5")
+(define-keysym :F6 "F6")
+(define-keysym :F7 "F7")
+(define-keysym :F8 "F8")
+(define-keysym :F9 "F9")
+(define-keysym :F10 "F10")
+(define-keysym :F11 "F11")
+(define-keysym :F12 "F12")
+(define-keysym :F13 "F13")
+(define-keysym :F14 "F14")
+(define-keysym :F15 "F15")
+(define-keysym :F16 "F16")
+(define-keysym :F17 "F17")
+(define-keysym :F18 "F18")
+(define-keysym :F19 "F19")
+(define-keysym :F20 "F20")
+(define-keysym :F21 "F21")
+(define-keysym :F22 "F22")
+(define-keysym :F23 "F23")
+(define-keysym :F24 "F24")
+(define-keysym :F25 "F25")
+(define-keysym :F26 "F26")
+(define-keysym :F27 "F27")
+(define-keysym :F28 "F28")
+(define-keysym :F29 "F29")
+(define-keysym :F30 "F30")
+(define-keysym :F31 "F31")
+(define-keysym :F32 "F32")
+(define-keysym :F33 "F33")
+(define-keysym :F34 "F34")
+(define-keysym :F35 "F35")
+
+;;; Upper right key bank.
+;;;
+(define-keysym :printscreen "Printscreen")
+;; Couldn't type scroll lock.
+(define-keysym :pause "Pause")
+
+;;; Middle right key bank.
+;;;
+(define-keysym :insert "Insert")
+(define-keysym :del "Del" "Rubout" (string (code-char 127)))
+(define-keysym :home "Home")
+(define-keysym :pageup "Pageup")
+(define-keysym :end "End")
+(define-keysym :pagedown "Pagedown")
+
+;;; Arrows.
+;;;
+(define-keysym :leftarrow "Leftarrow")
+(define-keysym :uparrow "Uparrow")
+(define-keysym :downarrow "Downarrow")
+(define-keysym :rightarrow "Rightarrow")
+
+
+(define-mouse-keysym 1 #xffff "Leftdown" "Super" :button-press)
+
+
+;;;; SETFs of KEY-EVENT-CHAR and CHAR-KEY-EVENT.
+
+;;; Converting ASCII control characters to Common Lisp control characters:
+;;; ASCII control character codes are separated from the codes of the
+;;; "non-controlified" characters by the code of atsign.  The ASCII control
+;;; character codes range from ^@ (0) through ^_ (one less than the code of
+;;; space).  We iterate over this range adding the ASCII code of atsign to
+;;; get the "non-controlified" character code.  With each of these, we turn
+;;; the code into a Common Lisp character and set its :control bit.  Certain
+;;; ASCII control characters have to be translated to special Common Lisp
+;;; characters outside of the loop.
+;;;    With the advent of Hemlock running under X, and all the key bindings
+;;; changing, we also downcase each Common Lisp character (where normally
+;;; control characters come in upcased) in an effort to obtain normal command
+;;; bindings.  Commands bound to uppercase modified characters will not be
+;;; accessible to terminal interaction.
+;;; 
+(let ((@-code (char-code #\@)))
+  (dotimes (i (char-code #\space))
+    (setf (char-key-event (code-char i))
+	  (make-key-event (string (char-downcase (code-char (+ i @-code))))
+			  (key-event-modifier-mask "control")))))
+(setf (char-key-event (code-char 9)) (make-key-event #k"Tab"))
+(setf (char-key-event (code-char 10)) (make-key-event #k"Linefeed"))
+(setf (char-key-event (code-char 13)) (make-key-event #k"Return"))
+(setf (char-key-event (code-char 27)) (make-key-event #k"Alt"))
+(setf (char-key-event (code-char 8)) (make-key-event #k"Backspace"))
+;;;
+;;; Other ASCII codes are exactly the same as the Common Lisp codes.
+;;; 
+(do ((i (char-code #\space) (1+ i)))
+    ((= i 128))
+  (setf (char-key-event (code-char i))
+	(make-key-event (string (code-char i)))))
+
+;;; This makes KEY-EVENT-CHAR the inverse of CHAR-KEY-EVENT from the start.
+;;; It need not be this way, but it is.
+;;;
+(dotimes (i 128)
+  (let ((character (code-char i)))
+    (setf (key-event-char (char-key-event character)) character)))
+
+;;; Since we treated these characters specially above when setting
+;;; CHAR-KEY-EVENT above, we must set these KEY-EVENT-CHAR's specially
+;;; to make quoting characters into Hemlock buffers more obvious for users.
+;;;
+(setf (key-event-char #k"C-h") #\backspace)
+(setf (key-event-char #k"C-i") #\tab)
+(setf (key-event-char #k"C-j") #\linefeed)
+(setf (key-event-char #k"C-m") #\return)
Index: /branches/new-random/cocoa-ide/hemlock/src/killcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/killcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/killcoms.lisp	(revision 13309)
@@ -0,0 +1,504 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Killing and unkilling things.
+;;;
+;;; Written by Bill Chiles and Rob MacLachlan.
+;;;
+
+(in-package :hemlock)
+
+(defvar *kill-ring* (make-ring 10) "The Hemlock kill ring.")
+
+
+
+
+;;;; Active Regions.
+
+(defhvar "Active Regions Enabled"
+  "When set, some commands that affect the current region only work when the
+   region is active."
+  :value t)
+
+(defhvar "Highlight Active Region"
+  "When set, the active region will be highlighted on the display if possible."
+  :value t)
+
+
+(defvar *ephemerally-active-command-types* (list :ephemerally-active)
+  "This is a list of command types that permit the current region to be active
+   for the immediately following command.")
+
+(declaim (inline activate-region deactivate-region region-active-p))
+
+(defun %buffer-activate-region (buffer)
+  (setf (hi::buffer-region-active buffer) (buffer-signature buffer)))
+
+(defun activate-region ()
+  "Make the current region active."
+  (%buffer-activate-region (current-buffer)))
+
+(defun %buffer-deactivate-region (buffer)
+  (setf (hi::buffer-region-active buffer) nil))
+
+(defun deactivate-region ()
+  "Make the current region not active, in the current buffer."
+  (%buffer-deactivate-region (current-buffer)))
+
+(defun %buffer-region-active-p (b)
+  (eql (buffer-signature b)
+       (hi::buffer-region-active b)))
+
+(defun region-active-p ()
+  "Returns t or nil, depending on whether the current region is active."
+  (%buffer-region-active-p (current-buffer)))
+
+(defun check-region-active ()
+  "Signals an error when active regions are enabled and the current region
+   is not active."
+  (when (and (value active-regions-enabled) (not (region-active-p)))
+    (editor-error "The current region is not active.")))
+
+(defun current-region (&optional (error-if-not-active t)
+				 (deactivate-region t))
+  "Returns a region formed by CURRENT-MARK and CURRENT-POINT, optionally
+   signalling an editor error if the current region is not active.  A new
+   region is cons'ed on each call.  This optionally deactivates the region."
+  (when error-if-not-active (check-region-active))
+  (when deactivate-region (deactivate-region))
+  (let ((point (current-point))
+	(mark (current-mark)))
+    (if (mark< mark point) (region mark point) (region point mark))))
+
+
+
+
+(defcommand "Activate Region" (p)
+  "Make the current region active.  ^G deactivates the region."
+  "Make the current region active."
+  (declare (ignore p))
+  (activate-region))
+
+
+
+(defun control-g-deactivate-region ()
+  (deactivate-region))
+;;;
+(add-hook abort-hook 'control-g-deactivate-region)
+
+
+
+
+;;;; Buffer-Mark primitives and commands.
+
+;;; See Command.Lisp for #'hcmd-make-buffer-hook-fun which makes the
+;;; stack for each buffer.
+
+(defun current-mark ()
+  "Returns the top of the current buffer's mark stack."
+  (buffer-mark (current-buffer)))
+
+(defun buffer-mark (buffer)
+  "Returns the top of buffer's mark stack."
+  (hi::buffer-%mark buffer))
+
+(defun pop-buffer-mark ()
+  "Pops the current buffer's mark stack, returning the mark.  If the stack
+   becomes empty, a mark is push on the stack pointing to the buffer's start.
+   This always makes the current region not active."
+  (let* ((ring (value buffer-mark-ring))
+         (buffer (current-buffer))
+	 (mark (buffer-mark buffer)))
+    (deactivate-region)
+    (setf (hi::buffer-%mark buffer)
+          (if (zerop (ring-length ring))
+            (copy-mark
+             (buffer-start-mark (current-buffer)) :right-inserting)
+            (ring-pop ring)))
+    mark))
+
+
+(defun %buffer-push-buffer-mark (b mark activate-region)
+  (cond ((eq (mark-buffer mark) b)
+         (setf (mark-kind mark) :right-inserting)
+         (let* ((old-mark (hi::buffer-%mark b)))
+           (when old-mark
+             (ring-push old-mark (variable-value 'buffer-mark-ring :buffer b))))
+         (setf (hi::buffer-%mark b) mark))
+        (t (error "Mark not in the current buffer.")))
+  (when activate-region (%buffer-activate-region b))
+  mark)
+        
+
+(defun push-buffer-mark (mark &optional (activate-region nil))
+  "Pushes mark into buffer's mark ring, ensuring that the mark is in the right
+   buffer and :right-inserting.  Optionally, the current region is made active.
+   This never deactivates the current region.  Mark is returned."
+  (%buffer-push-buffer-mark (current-buffer) mark activate-region))
+
+(defun push-new-buffer-mark (mark &optional (activate-region nil))
+  "Pushes a new mark at argument position"
+  (push-buffer-mark (copy-mark mark :right-inserting) activate-region))
+
+(defcommand "Set/Pop Mark" (p)
+  "Set or Pop the mark ring.
+   With no C-U's, pushes point as the mark, activating the current region.
+   With one C-U's, pops the mark into point, de-activating the current region.
+   With two C-U's, pops the mark and throws it away, de-activating the current
+   region."
+  "Set or Pop the mark ring."
+  (cond ((not p)
+	 (push-new-buffer-mark (current-point) t)
+	 (message "Mark pushed."))
+	((= p (value universal-argument-default))
+	 (pop-and-goto-mark-command nil))
+	((= p (expt (value universal-argument-default) 2))
+	 (delete-mark (pop-buffer-mark)))
+	(t (editor-error))))
+
+(defcommand "Pop and Goto Mark" (p)
+  "Pop mark into point, de-activating the current region."
+  "Pop mark into point."
+  (declare (ignore p))
+  (let ((mark (pop-buffer-mark)))
+    (move-mark (current-point) mark)
+    (delete-mark mark)))
+
+(defcommand "Pop Mark" (p)
+  "Pop mark and throw it away, de-activating the current region."
+  "Pop mark and throw it away."
+  (declare (ignore p))
+  (delete-mark (pop-buffer-mark)))
+
+(defcommand "Exchange Point and Mark" (p)
+  "Swap the positions of the point and the mark, activating region"
+  "Swap the positions of the point and the mark."
+  (declare (ignore p))
+  (let ((point (current-point))
+	(mark (current-mark)))
+    (with-mark ((temp point))
+      (move-mark point mark)
+      (move-mark mark temp)))
+  (activate-region))
+
+(defcommand "Mark Whole Buffer"  (p)
+  "Set the region around the whole buffer, activating the region.
+   Pushes the point on the mark ring first, so two pops get it back.
+   With prefix argument, put mark at beginning and point at end."
+  "Put point at beginning and part at end of current buffer.
+  If P, do it the other way around."
+  (let* ((region (buffer-region (current-buffer)))
+	 (start (region-start region))
+	 (end (region-end region))
+	 (point (current-point)))
+    (push-new-buffer-mark point)
+    (cond (p (push-new-buffer-mark start t)
+	     (move-mark point end))
+	  (t (push-new-buffer-mark end t)
+	     (move-mark point start)))))
+
+
+
+
+;;;; KILL-REGION and KILL-CHARACTERS primitives.
+
+(declaim (special *delete-char-region*))
+
+;;; KILL-REGION first checks for any characters that may need to be added to
+;;; the region.  If there are some, we possibly push a region onto *kill-ring*,
+;;; and we use the top of *kill-ring*.  If there are no characters to deal
+;;; with, then we make sure the ring isn't empty; if it is, just push our
+;;; region.  If there is some region in *kill-ring*, then see if the last
+;;; command type was a region kill.  Otherwise, just push the region.
+;;;
+(defun kill-region (region current-type)
+  "Kills the region saving it in *kill-ring*.  Current-type is either
+   :kill-forward or :kill-backward.  When LAST-COMMAND-TYPE is one of these,
+   region is appended or prepended, respectively, to the top of *kill-ring*.
+   The killing of the region is undo-able with \"Undo\".  LAST-COMMAND-TYPE
+   is set to current-type.  This interacts with KILL-CHARACTERS."
+  (let ((last-type (last-command-type))
+	(insert-mark (copy-mark (region-start region) :left-inserting)))
+    (cond ((or (eq last-type :char-kill-forward)
+	       (eq last-type :char-kill-backward))
+	   (when *delete-char-region*
+	     (kill-ring-push *delete-char-region*)
+	     (setf *delete-char-region* nil))
+	   (setf region (kill-region-top-of-ring region current-type)))
+	  ((zerop (ring-length *kill-ring*))
+	   (setf region (delete-and-save-region region))
+	   (kill-ring-push region))
+	  ((or (eq last-type :kill-forward) (eq last-type :kill-backward))
+	   (setf region (kill-region-top-of-ring region current-type)))
+	  (t
+	   (setf region (delete-and-save-region region))
+	   (kill-ring-push region)))
+    (make-region-undo :insert "kill" (copy-region region) insert-mark)
+    (setf (last-command-type) current-type)))
+
+(defun kill-region-top-of-ring (region current-type)
+  (let ((r (ring-ref *kill-ring* 0)))
+    (ninsert-region (if (eq current-type :kill-forward)
+			(region-end r)
+			(region-start r))
+		    (delete-and-save-region region))
+    r))
+
+(defhvar "Character Deletion Threshold"
+  "When this many characters are deleted contiguously via KILL-CHARACTERS,
+   they are saved on the kill ring -- for example, \"Delete Next Character\",
+   \"Delete Previous Character\", or \"Delete Previous Character Expanding
+   Tabs\"."
+  :value 5)
+
+(defvar *delete-char-region* nil)
+(defvar *delete-char-count* 0)
+
+;;; KILL-CHARACTERS makes sure there are count characters with CHARACTER-OFFSET.
+;;; If the last command type was a region kill, we just use the top region
+;;; in *kill-ring* by making KILL-CHAR-REGION believe *delete-char-count* is
+;;; over the threshold.  We don't call KILL-REGION in this case to save making
+;;; undo's -- no good reason.  If we were just called, then increment our
+;;; global counter.  Otherwise, make an empty region to keep KILL-CHAR-REGION
+;;; happy and increment the global counter.
+;;;
+(defun kill-characters (mark count)
+  "Kills count characters after mark if positive, before mark if negative.
+   If called multiple times contiguously such that the sum of the count values
+   equals \"Character Deletion Threshold\", then the characters are saved on
+   *kill-ring*.  This relies on setting LAST-COMMAND-TYPE, and it interacts
+   with KILL-REGION.  If there are not count characters in the appropriate
+   direction, no characters are deleted, and nil is returned; otherwise, mark
+   is returned."
+  (if (zerop count)
+      mark
+      (with-mark ((temp mark :left-inserting))
+	(if (character-offset temp count)
+	    (let ((current-type (if (plusp count)
+				    :char-kill-forward
+				    :char-kill-backward))
+		  (last-type (last-command-type))
+		  (del-region (if (mark< temp mark)
+				  (region temp mark)
+				  (region mark temp))))
+	      (cond ((or (eq last-type :kill-forward)
+			 (eq last-type :kill-backward))
+		     (setf *delete-char-count*
+			   (value character-deletion-threshold))
+		     (setf *delete-char-region* nil))
+		    ((or (eq last-type :char-kill-backward)
+			 (eq last-type :char-kill-forward))
+		     (incf *delete-char-count* (abs count)))
+		    (t
+		     (setf *delete-char-region* (make-empty-region))
+		     (setf *delete-char-count* (abs count))))
+	      (kill-char-region del-region current-type)
+	      mark)
+	    nil))))
+
+(defun kill-char-region (region current-type)
+  (let ((deleted-region (delete-and-save-region region)))
+    (cond ((< *delete-char-count* (value character-deletion-threshold))
+	   (ninsert-region (if (eq current-type :char-kill-forward)
+			       (region-end *delete-char-region*)
+			       (region-start *delete-char-region*))
+			   deleted-region)
+	   (setf (last-command-type) current-type))
+	  (t
+	   (when *delete-char-region*
+	     (kill-ring-push *delete-char-region*)
+	     (setf *delete-char-region* nil))
+	   (let ((r (ring-ref *kill-ring* 0)))
+	     (ninsert-region (if (eq current-type :char-kill-forward)
+				 (region-end r)
+				 (region-start r))
+			     deleted-region))
+	   (setf (last-command-type)
+		 (if (eq current-type :char-kill-forward)
+		     :kill-forward
+		     :kill-backward))))))
+
+(defun kill-ring-push (region)
+  (hi::region-to-clipboard region)
+  (ring-push region *kill-ring*))
+
+
+  
+
+
+
+;;;; Commands.
+
+(defcommand "Kill Region" (p)
+  "Kill the region, pushing on the kill ring.
+   If the region is not active nor the last command a yank, signal an error."
+  "Kill the region, pushing on the kill ring."
+  (declare (ignore p))
+  (kill-region (current-region)
+		(if (mark< (current-mark) (current-point))
+		    :kill-backward
+		    :kill-forward)))
+
+(defcommand "Save Region" (p)
+  "Insert the region into the kill ring.
+   If the region is not active nor the last command a yank, signal an error."
+  "Insert the region into the kill ring."
+  (declare (ignore p))
+  (kill-ring-push (copy-region (current-region))))
+
+(defcommand "Kill Next Word" (p)
+  "Kill a word at the point.
+  With prefix argument delete that many words.  The text killed is
+  appended to the text currently at the top of the kill ring if it was
+  next to the text being killed."
+  "Kill p words at the point"
+  (let ((point (current-point-for-deletion)))
+    (when point
+      (let* ((num (or p 1)))
+        (with-mark ((mark point :temporary))
+          (if (word-offset mark num)
+            (if (minusp num)
+	      (kill-region (region mark point) :kill-backward)
+	      (kill-region (region point mark) :kill-forward))
+            (editor-error)))))))
+
+(defcommand "Kill Previous Word" (p)
+  "Kill a word before the point.
+  With prefix argument kill that many words before the point.  The text
+  being killed is appended to the text currently at the top of the kill
+  ring if it was next to the text being killed."
+  "Kill p words before the point"
+  (kill-next-word-command (- (or p 1))))
+
+
+(defcommand "Kill Line" (p)
+  "Kills the characters to the end of the current line.
+  If the line is empty then the line is deleted.  With prefix argument,
+  deletes that many lines past the point (or before if the prefix is negative)."
+  "Kills p lines after the point."
+  (let* ((point (current-point-for-deletion)))
+    (when point
+      (let* ((line (mark-line point)))
+        (with-mark ((mark point))
+          (cond 
+            (p
+             (when (and (/= (mark-charpos point) 0) (minusp p))
+               (incf p))
+             (unless (line-offset mark p 0)
+               (if (plusp p)
+                 (kill-region (region point (buffer-end mark)) :kill-forward)
+                 (kill-region (region (buffer-start mark) point) :kill-backward))
+               (editor-error))
+             (if (plusp p)
+               (kill-region (region point mark) :kill-forward)
+               (kill-region (region mark point) :kill-backward)))
+            (t
+             (cond ((not (blank-after-p mark))
+                    (line-end mark))
+                   ((line-next line)
+                    (line-start mark (line-next line)))
+                   ((not (end-line-p mark))
+                    (line-end mark))
+                   (t 
+                    (editor-error)))
+             (kill-region (region point mark) :kill-forward))))))))
+
+(defcommand "Backward Kill Line" (p)
+  "Kill from the point to the beginning of the line.
+  If at the beginning of the line, kill the newline and any trailing space
+  on the previous line.  With prefix argument, call \"Kill Line\" with
+  the argument negated."
+  "Kills p lines before the point."
+  (if p
+      (kill-line-command (- p))
+    (let* ((point (current-point-for-deletion)))
+      (when point
+        (with-mark ((m point))
+          (cond ((zerop (mark-charpos m))
+                 (mark-before m)
+                 (unless (reverse-find-attribute m :space #'zerop)
+                   (buffer-start m)))
+                (t
+                 (line-start m)))
+          (kill-region (region m (current-point)) :kill-backward))))))
+
+
+(defcommand "Delete Blank Lines" (p)
+  "On a blank line, deletes all surrounding blank lines, leaving just
+  one. On an isolated blank line, deletes that one. On a non-blank line,
+  deletes all blank following that one."
+  "Kill blank lines around the point"
+  (declare (ignore p))
+  (let ((point (current-point-for-deletion)))
+    (when point
+      (with-mark ((beg-mark point :left-inserting)
+                  (end-mark point :right-inserting))
+        ;; handle case when the current line is blank
+        (when (blank-line-p (mark-line point))
+          ;; back up to last non-whitespace character
+          (reverse-find-attribute beg-mark :whitespace #'zerop)
+          (when (previous-character beg-mark)
+            ;; that is, we didn't back up to the beginning of the buffer
+            (unless (same-line-p beg-mark end-mark)
+              (line-offset beg-mark 1 0)))
+          ;; if isolated, zap the line else zap the blank ones above
+          (cond ((same-line-p beg-mark end-mark)
+                 (line-offset end-mark 1 0))
+                (t
+                 (line-start end-mark)))
+          (delete-region (region beg-mark end-mark)))
+        ;; always delete all blank lines after the current line
+        (move-mark beg-mark point)
+        (when (line-offset beg-mark 1 0)
+          (move-mark end-mark beg-mark)
+          (find-attribute end-mark :whitespace #'zerop)
+          (when (next-character end-mark)
+            ;; that is, we didn't go all the way to the end of the buffer
+            (line-start end-mark))
+          (delete-region (region beg-mark end-mark)))))))
+
+
+(defcommand "Un-Kill" (p)
+  "Inserts the top item in the kill-ring at the point.
+  The mark is left mark before the insertion and the point after.  With prefix
+  argument inserts the prefix'th most recent item."
+  "Inserts the item with index p in the kill ring at the point, leaving 
+  the mark before and the point after."
+  (let ((idx (1- (or p 1))))
+    (cond ((> (ring-length *kill-ring*) idx -1)
+	   (let* ((region (ring-ref *kill-ring* idx))
+		  (point (current-point-for-insertion))
+		  (mark (push-new-buffer-mark point)))
+	     (insert-region point region)
+	     (make-region-undo :delete "Un-Kill"
+			       (region (copy-mark mark) (copy-mark point))))
+	   (setf (last-command-type) :unkill))
+	  (t (editor-error)))))
+;;;
+(push :unkill *ephemerally-active-command-types*)
+
+(defcommand "Rotate Kill Ring" (p)
+  "Replace un-killed text with previously killed text.
+  Kills the current region, rotates the kill ring, and inserts the new top
+  item.  With prefix argument rotates the kill ring that many times."
+  "This function will not behave in any reasonable fashion when
+  called as a lisp function."
+  (let ((point (current-point))
+        (mark (current-mark)))
+    (cond ((or (not (eq (last-command-type) :unkill))
+	       (zerop (ring-length *kill-ring*)))
+	   (editor-error))
+	  (t (delete-region (region mark point))
+	     (rotate-ring *kill-ring* (or p 1))
+	     (insert-region point (ring-ref *kill-ring* 0))
+	     (make-region-undo :delete "Un-Kill"
+			       (region (copy-mark mark) (copy-mark point)))
+	     (setf (last-command-type) :unkill)))))
Index: /branches/new-random/cocoa-ide/hemlock/src/line.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/line.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/line.lisp	(revision 13309)
@@ -0,0 +1,208 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains definitions for the Line structure, and some 
+;;; functions and macros to manipulate them.
+;;;
+;;;    This stuff was allowed to become implementation dependant because
+;;; you make thousands of lines, so speed is real important.  In some
+;;; implementations (the Perq for example) it may be desirable to 
+;;; not actually cons the strings in the line objects until someone
+;;; touches them, and just keep a pointer in the line to where the file 
+;;; is mapped in memory.  Such lines are called "buffered".  This stuff
+;;; links up with the file-reading stuff and the line-image building stuff.
+;;;
+(in-package :hemlock-internals)
+
+(setf (documentation 'linep 'function)
+  "Returns true if its argument is a Hemlock line object, Nil otherwise.")
+(setf (documentation 'line-previous 'function)
+  "Return the Hemlock line that precedes this one, or Nil if there is no
+  previous line.")
+(setf (documentation 'line-next 'function)
+  "Return the Hemlock line that follows this one, or Nil if there is no
+  next line.")
+(setf (documentation 'line-plist 'function)
+  "Return a line's property list.  This may be manipulated with Setf and Getf.")
+
+
+;;;; The line object:
+
+(declaim (inline %make-line))
+(defstruct (line (:print-function %print-hline)
+		 (:constructor %make-line)
+		 (:predicate linep))
+  "A Hemlock line object.  See Hemlock design document for details."
+  ;;
+  ;; Something that represents the contents of the line.  This is
+  ;; guaranteed to change (as compared by EQL) whenver the contents of the
+  ;; line changes, but might at arbitarary other times.  There are
+  ;; currently about three different cases:
+  ;;
+  ;; Normal:
+  ;;    A simple string holding the contents of the line.
+  ;;
+  ;; A cached line:
+  ;;    The line is eq to Open-Line, and the actual contents are in the
+  ;;    line cache.  The %Chars may be either the original contents or a
+  ;;    negative fixnum.
+  ;;
+  ;; A buffered line:
+  ;;    The line hasn't been touched since it was read from a file, and the
+  ;;    actual contents are in some system I/O area.  This is indicated by
+  ;;    the Line-Buffered-P slot being true.  In buffered lines on the RT,
+  ;;    the %Chars slot contains the system-area-pointer to the beginning
+  ;;    of the characters.
+  (%chars "")
+  ;;
+  ;; Pointers to the next and previous lines in the doubly linked list of
+  ;; line structures.
+  %previous
+  %next
+  ;;
+  ;; A list of all the permanent marks pointing into this line.
+  (marks ())
+  ;;
+  ;; The buffer to which this line belongs, or a *disembodied-buffer-count*
+  ;; if the line is not in any buffer.
+  %buffer
+  ;;
+  ;; A non-negative integer (fixnum) that represents the ordering of lines
+  ;; within continguous range of lines (a buffer or disembuffered region).
+  ;; The number of the Line-Next is guaranteed to be strictly greater than
+  ;; our number, and the Line-Previous is guaranteed to be strictly less.
+  (number 0)
+  ;;
+  ;; The line property list, used by user code to annotate the text.
+  plist
+  ;;
+  ;; The (logical) origin within a buffer or disembodied region, or NIL
+  ;; if we aren't sure.
+  origin
+  ;; A vector of charprops-change objects or NIL if the whole line has
+  ;; the buffer's default character properties.
+  charprops-changes)
+
+(declaim (inline line-next line-previous set-line-next set-line-previous))
+(defun line-next (line) (line-%next line))
+(defun line-previous (line) (line-%previous line))
+
+(defsetf line-next set-line-next)
+(defsetf line-previous set-line-previous)
+
+(defun set-line-next (line next)
+  (let ((buffer (line-buffer line)))
+    (when buffer (invalidate-buffer-lines buffer)))
+  (setf (line-%next line) next))
+
+(defun set-line-previous (line previous)
+  (let ((buffer (line-buffer line)))
+    (when buffer (invalidate-buffer-lines buffer)))
+  (setf (line-%previous line) previous))
+
+(defstruct (charprops-change
+            (:copier nil)
+            (:constructor make-charprops-change (index plist)))
+  index
+  plist)
+
+(defun copy-charprops-change (c)
+  (make-charprops-change (charprops-change-index c)
+                         (copy-list (charprops-change-plist c))))
+
+;;; If buffered lines are supported, then we create the string
+;;; representation for the characters when someone uses Line-Chars.  People
+;;; who are prepared to handle buffered lines or who just want a signature
+;;; for the contents can use Line-%chars directly.
+;;;
+(defmacro line-chars (line)
+  `(the simple-string (line-%chars ,line)))
+;;;
+(defsetf line-chars %set-line-chars)
+;;;
+(defmacro %set-line-chars (line chars)
+  `(setf (line-%chars ,line) ,chars))
+
+
+;;; Line-Signature  --  Public
+;;;
+;;;    We can just return the Line-%Chars.
+;;;
+(declaim (inline line-signature))
+(defun line-signature (line)
+  "This function returns an object which serves as a signature for a line's
+  contents.  It is guaranteed that any modification of text on the line will
+  result in the signature changing so that it is not EQL to any previous value.
+  Note that the signature may change even when the text hasn't been modified, but
+  this probably won't happen often."
+  (line-%chars line))
+
+(defun copy-charprops-changes (changes)
+  (when changes
+    (let* ((new (make-array (length changes) :adjustable t :fill-pointer 0)))
+      (map-into new #'copy-charprops-change changes))))
+
+;;; Return a copy of Line in buffer Buffer with the same chars.  We use
+;;; this macro where we want to copy a line because it takes care of
+;;; the case where the line is buffered.
+;;;
+(defmacro %copy-line (line &key previous number %buffer)
+  `(make-line :chars (line-%chars ,line)
+              :charprops-changes (copy-charprops-changes
+                                  (line-charprops-changes ,line))
+	      :previous ,previous
+	      :number ,number
+	      :%buffer ,%buffer ))
+
+;;; Hide the fact that the slot isn't really called CHARS.
+;;;
+(defmacro make-line (&rest keys)
+  (loop for (old . new) in '((:chars . :%chars) (:next . :%next) (:previous . :%previous))
+        do (setq keys (substitute new old keys)))
+  `(%make-line ,@keys))
+
+(defmacro line-length* (line)
+  "Returns the number of characters on the line, but it's a macro!"
+  `(cond ((current-open-line-p ,line)
+	  (+ (current-left-open-pos) (- (current-line-cache-length) (current-right-open-pos))))
+	 (t
+	  (length (the simple-string (line-%chars ,line))))))
+
+(defun buffer-line-length (line)
+  (let ((buffer (line-buffer line)))
+    (cond ((null buffer)
+	   (line-length* line))
+	  ((eq line (buffer-open-line buffer))
+	   (buffer-open-line-length buffer))
+	  (t (length (line-chars line))))))
+
+(defun get-line-origin (line)
+  (or (line-origin line)
+      (do* ((prev (line-previous line) (line-previous prev))
+            (this line))
+           ((or (null prev) (line-origin this))
+            (let* ((start (or (line-origin this)
+                              (setf (line-origin this) 0))))
+              (do* ((next (line-next this) (line-next next)))
+                   ((null next) 0)
+                (incf start (1+ (line-length this)))
+                (setq this next)
+                (setf (line-origin this) start)
+                (when (eq this line) (return start)))))
+        (setq this prev))))
+
+(defun adjust-line-origins-forward (line)
+  (let* ((start (get-line-origin line)))
+    (do* ((next (line-next line) (line-next next)))
+         ((null next))
+      (incf start (1+ (line-length* line)))
+      (setf (line-origin next) start)
+      (setq line next))))
Index: /branches/new-random/cocoa-ide/hemlock/src/lispmode.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/lispmode.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/lispmode.lisp	(revision 13309)
@@ -0,0 +1,2294 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock LISP Mode commands
+;;;
+;;; Written by Ivan Vazquez and Bill Maddox.
+;;;
+
+(in-package :hemlock)
+
+;; (declaim (optimize (speed 2))); turn off byte compilation.
+
+
+
+;;;; Variables and lisp-info structure.
+
+;;; These routines are used to define, for standard LISP mode, the start and end
+;;; of a block to parse.  If these need to be changed for a minor mode that sits
+;;; on top of LISP mode, simply do a DEFHVAR with the minor mode and give the
+;;; name of the function to use instead of START-OF-PARSE-BLOCK and 
+;;; END-OF-PARSE-BLOCK.
+;;; 
+
+(defhvar "Parse Start Function"
+  "Take a mark and move it to the top of a block for paren parsing."
+  :value 'start-of-parse-block)
+
+(defhvar "Parse End Function"
+  "Take a mark and move it to the bottom of a block for paren parsing."
+  :value 'end-of-parse-block)
+
+	    
+;;; LISP-INFO is the structure used to store the data about the line in its
+;;; Plist.
+;;;
+;;;     -> BEGINS-QUOTED, ENDING-QUOTED are both slots that tell whether or not
+;;;        a line's begining and/or ending are quoted, and if so, how.
+;;; 
+;;;     -> RANGES-TO-IGNORE is a list of cons cells, each having the form
+;;;        ( [begining-charpos] [end-charpos] ) each of these cells indicating
+;;;        a range where :lisp-syntax attributes are ignored.  End is exclusive.
+;;; 
+;;;     -> NET-OPEN-PARENS, NET-CLOSE-PARENS integers that are the number of 
+;;;        unmatched opening and closing parens that there are on a line.
+;;; 
+;;;     -> SIGNATURE-SLOT ...
+;;; 
+
+(defstruct (lisp-info (:constructor make-lisp-info ()))
+  (begins-quoted nil)		; nil or quote char attribute or comment nesting depth
+  (ending-quoted nil)		; nil or quote char attribute or comment nesting depth
+  (ranges-to-ignore nil)
+  (net-open-parens 0 :type fixnum)
+  (net-close-parens 0 :type fixnum)
+  (signature-slot))
+
+
+
+
+;;;; Macros.
+
+;;; The following Macros exist to make it easy to acces the Syntax primitives
+;;; without uglifying the code.  They were originally written by Maddox.
+;;; 
+
+(defmacro scan-char (mark attribute values)
+  `(find-attribute ,mark ',attribute ,(attr-predicate values)))
+
+(defmacro rev-scan-char (mark attribute values)
+  `(reverse-find-attribute ,mark ',attribute ,(attr-predicate values)))
+
+(defmacro test-char (char attribute values)
+  `(let ((x (character-attribute ',attribute ,char)))
+     ,(attr-predicate-aux values)))
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+(defun attr-predicate (values)
+  (cond ((eq values 't)
+	 '#'plusp)
+	((eq values 'nil)
+	 '#'zerop)
+	(t `#'(lambda (x) ,(attr-predicate-aux values)))))
+
+(defun attr-predicate-aux (values)
+  (cond ((eq values t)
+	 '(plusp x))
+	((eq values nil)
+	 '(zerop x))
+	((symbolp values)
+	 `(eq x ',values))
+	((and (listp values) (member (car values) '(and or not)))
+	 (cons (car values) (mapcar #'attr-predicate-aux (cdr values))))
+	(t (error "Illegal form in attribute pattern - ~S" values))))
+
+); Eval-When
+
+;;; 
+;;; FIND-LISP-CHAR
+
+(defmacro find-lisp-char (mark)
+  "Move MARK to next :LISP-SYNTAX character, if one isn't found, return NIL."
+  `(find-attribute ,mark :lisp-syntax
+		   #'(lambda (x)
+		       (member x '(:open-paren :close-paren :newline :comment :prefix-dispatch
+					       :char-quote :symbol-quote :string-quote)))))
+;;; 
+;;; PUSH-RANGE
+
+(defmacro push-range (new-range info-struct)
+  "Insert NEW-RANGE into the LISP-INFO-RANGES-TO-IGNORE slot of the INFO-STRUCT."
+  `(when ,new-range
+     (setf (lisp-info-ranges-to-ignore ,info-struct) 
+	   (cons ,new-range (lisp-info-ranges-to-ignore ,info-struct)))))
+;;; 
+;;; SCAN-DIRECTION
+
+(defmacro scan-direction (mark forwardp &rest forms)
+  "Expand to a form that scans either backward or forward according to Forwardp."
+  (if forwardp
+      `(scan-char ,mark ,@forms)
+      `(rev-scan-char ,mark ,@forms)))
+;;; 
+;;; DIRECTION-CHAR
+
+(defmacro direction-char (mark forwardp)
+  "Expand to a form that returns either the previous or next character according
+  to Forwardp."
+  (if forwardp
+      `(next-character ,mark)
+      `(previous-character ,mark)))
+
+;;; 
+;;; NEIGHBOR-MARK
+
+(defmacro neighbor-mark (mark forwardp)
+  "Expand to a form that moves MARK either backward or forward one character, 
+  depending on FORWARDP."
+  (if forwardp
+      `(mark-after ,mark)
+      `(mark-before ,mark)))
+
+;;; 
+;;; NEIGHBOR-LINE
+
+(defmacro neighbor-line (line forwardp)
+  "Expand to return the next or previous line, according to Forwardp."
+  (if forwardp
+      `(line-next ,line)
+      `(line-previous ,line)))
+
+
+
+;;;; Parsing functions.
+
+;;; PRE-COMMAND-PARSE-CHECK -- Public.
+;;;
+(defun pre-command-parse-check (mark &optional (fer-sure-parse nil))
+  "Parse the area before the command is actually executed."
+  (with-mark ((top mark)
+	      (bottom mark))
+    (funcall (value parse-start-function) top)
+    (funcall (value parse-end-function) bottom)
+    (parse-over-block (mark-line top) (mark-line bottom) fer-sure-parse)))
+
+;;; PARSE-OVER-BLOCK
+;;;
+(defun parse-over-block (start-line end-line &optional (fer-sure-parse nil))
+  "Parse over an area indicated from END-LINE to START-LINE."
+  (let ((test-line start-line)
+	prev-line-info)
+    
+    (with-mark ((mark (mark test-line 0)))
+      
+      ; Set the pre-begining and post-ending lines to delimit the range
+      ; of action any command will take.  This means set the lisp-info of the 
+      ; lines immediately before and after the block to Nil.
+      
+      (when (line-previous start-line)
+	(setf (getf (line-plist (line-previous start-line)) 'lisp-info) nil))
+      (when (line-next end-line)
+	(setf (getf (line-plist (line-next end-line)) 'lisp-info) nil))
+      
+      (loop
+       (let ((line-info (getf (line-plist test-line) 'lisp-info)))
+	 
+	 ;;    Reparse the line when any of the following are true:
+	 ;;
+	 ;;      FER-SURE-PARSE is T
+	 ;;
+	 ;;      LINE-INFO or PREV-LINE-INFO are Nil.
+	 ;;
+	 ;;      If the line begins quoted and the previous one wasn't 
+	 ;;      ended quoted.
+	 ;;
+	 ;;      The Line's signature slot is invalid (the line has changed).
+	 ;;
+	 
+	 (when (or fer-sure-parse      
+		   (not line-info)
+		   (not (eq (lisp-info-begins-quoted line-info)
+                            (let ((prev (and prev-line-info (lisp-info-ending-quoted prev-line-info))))
+                              (and (not (eq prev :char-quote)) prev))))
+		   (not (eql (line-signature test-line)
+			     (lisp-info-signature-slot line-info))))
+
+	   (move-to-position mark 0 test-line)
+	   
+	   (unless line-info
+	     (setf line-info (make-lisp-info))
+	     (setf (getf (line-plist test-line) 'lisp-info) line-info))
+	   
+	   (parse-lisp-line-info mark line-info prev-line-info))
+	 
+	 (when (eq end-line test-line)
+	   (return nil))
+	 
+	 (setq prev-line-info line-info)
+	 
+	 (setq test-line (line-next test-line)))))))
+
+
+
+;;;; Parse block finders.
+
+
+(defun start-of-parse-block (mark)
+  (buffer-start mark))
+
+(defun end-of-parse-block (mark)
+  (buffer-end mark))
+
+;;; 
+;;; START-OF-SEARCH-LINE
+
+(defun start-of-search-line (line)
+  "Set LINE to the begining line of the block of text to parse."
+  (with-mark ((mark (mark line 0)))
+    (funcall (value 'Parse-Start-Function) mark)
+    (setq line (mark-line mark))))
+
+;;; 
+;;; END-OF-SEACH-LINE
+
+(defun end-of-search-line (line)
+  "Set LINE to the ending line of the block of text to parse."
+  (with-mark ((mark (mark line 0)))
+    (funcall (value 'Parse-End-Function) mark)
+    (setq line (mark-line mark))))
+
+
+
+;;;; PARSE-LISP-LINE-INFO.
+
+;;; PARSE-LISP-LINE-INFO -- Internal.
+;;;
+;;; This parses through the line doing the following things:
+;;;
+;;;      Counting/Setting the NET-OPEN-PARENS & NET-CLOSE-PARENS.
+;;;
+;;;      Making all areas of the line that should be invalid (comments,
+;;;      char-quotes, and the inside of strings) and such be in
+;;;      RANGES-TO-IGNORE.
+;;;
+;;;      Set BEGINS-QUOTED and ENDING-QUOTED 
+;;;
+(defun parse-lisp-line-info (mark line-info prev-line-info)
+  "Parse line and set line information like NET-OPEN-PARENS, NET-CLOSE-PARENS,
+   RANGES-TO-INGORE, and ENDING-QUOTED."
+  (let ((net-open-parens 0)
+	(net-close-parens 0))
+    (declare (fixnum net-open-parens net-close-parens))
+
+    ;; Re-set the slots necessary
+
+    (setf (lisp-info-ranges-to-ignore line-info) nil)
+
+    (setf (lisp-info-ending-quoted line-info) nil)
+
+    ;; The only way the current line begins quoted is when there
+    ;; is a previous line and it's ending was quoted.
+    
+    (setf (lisp-info-begins-quoted line-info)
+	  (and prev-line-info 
+	       (let ((prev (lisp-info-ending-quoted prev-line-info)))
+		 (and (not (eq prev :char-quote)) prev))))
+
+    (assert (eq (hi::mark-buffer mark) (current-buffer)))
+
+    (when (lisp-info-begins-quoted line-info)
+      (deal-with-quote (lisp-info-begins-quoted line-info) mark line-info))
+
+    (unless (lisp-info-ending-quoted line-info)
+      (loop 
+
+        (unless (find-lisp-char mark)
+          (error "Expected at least a newline!"))
+        (case (character-attribute :lisp-syntax (next-character mark))
+	  
+	  (:open-paren
+	   (setq net-open-parens (1+ net-open-parens))
+	   (mark-after mark))
+	  
+	  (:close-paren
+	   (if (zerop net-open-parens)
+	       (setq net-close-parens (1+ net-close-parens))
+	       (setq net-open-parens (1- net-open-parens)))
+	   (mark-after mark))
+	  
+	  (:newline
+	   (setf (lisp-info-ending-quoted line-info) nil)
+	   (return t))
+	  
+	  (:comment
+	   (push-range (cons (mark-charpos mark) (line-length (mark-line mark)))
+		       line-info)
+	   (setf (lisp-info-ending-quoted line-info) nil)
+	   (return t))
+	  
+	  (:char-quote
+	   (mark-after mark)
+           (let* ((charpos (mark-charpos mark))
+                  (nextpos (1+ charpos))
+                  (linelen (line-length (mark-line mark))))
+             (when (< linelen nextpos)
+               (setf (lisp-info-ending-quoted line-info) :char-quote)
+               (return t))
+             (push-range (cons charpos nextpos) line-info)
+             (mark-after mark)))
+
+          (:prefix-dispatch
+           (mark-after mark)
+           (when (test-char (next-character mark) :lisp-syntax :symbol-quote)
+             (mark-after mark)
+             (unless (deal-with-quote 1 mark line-info (- (mark-charpos mark) 2))
+               (return t))))
+
+          (:symbol-quote
+           (mark-after mark)
+           (unless (deal-with-quote :symbol-quote mark line-info)
+             (return t)))
+
+	  (:string-quote
+	   (mark-after mark)
+	   (unless (deal-with-quote :string-quote mark line-info)
+	     (return t)))
+
+          (t (ERROR "character attribute of: ~s is ~s, at ~s"
+                    (next-character mark)
+                    (character-attribute :lisp-syntax (next-character mark))
+                    mark)))))
+    (setf (lisp-info-net-open-parens line-info) net-open-parens)
+    (setf (lisp-info-net-close-parens line-info) net-close-parens)
+    (setf (lisp-info-signature-slot line-info) 
+	  (line-signature (mark-line mark)))))
+
+
+
+
+;;;; String/symbol quote utilities.
+
+;;; VALID-QUOTE-P
+;;;
+(defmacro valid-quote-p (quote mark forwardp)
+  "Return T if the string-quote indicated by MARK is valid."
+  `(and (eq (character-attribute :lisp-syntax (direction-char ,mark ,forwardp)) ,quote)
+        (not (char-quoted-at-mark-p ,mark ,forwardp))))
+
+(defun char-quoted-at-mark-p (mark forwardp)
+  (unless forwardp
+    (unless (mark-before mark)
+      (return-from char-quoted-at-mark-p nil)))
+  (loop for count upfrom 0
+    do (unless (test-char (previous-character mark) :lisp-syntax :char-quote)
+         (character-offset mark count) ;; go back to where started
+         (unless forwardp
+           (mark-after mark))
+         (return (oddp count)))
+    do (mark-before mark)))
+
+;;; 
+;;; FIND-VALID-QUOTE
+
+(defmacro find-valid-quote (quote mark &key forwardp (cease-at-eol nil))
+  "Expand to a form that will leave MARK before a valid string-quote character,
+  in either a forward or backward direction, according to FORWARDP.  If 
+  CEASE-AT-EOL is T then it will return nil if encountering the EOL before a
+  valid string-quote."
+  (let ((e-mark (gensym))
+        (pred (gensym)))
+    `(with-mark ((,e-mark ,mark))
+       (let ((,pred ,(if cease-at-eol
+                       `#'(lambda (x) (or (eq x :newline) (eq x ,quote)))
+                       `#'(lambda (x) (eq x ,quote)))))
+
+         (loop
+           (unless (,(if forwardp 'find-attribute 'reverse-find-attribute)
+                    ,e-mark :lisp-syntax ,pred)
+             (return nil))
+
+	,@(if cease-at-eol
+	      `((when (test-char (direction-char ,e-mark ,forwardp) :lisp-syntax
+				 :newline)
+		  (return nil))))
+	
+	(when (valid-quote-p ,quote ,e-mark ,forwardp)
+	  (move-mark ,mark ,e-mark)
+	  (return t))
+	
+	(neighbor-mark ,e-mark ,forwardp))))))
+
+
+;;; DEAL-WITH-QUOTE
+;;;
+;;; Called when a quoted area is begun (i.e. parse hits a #\" or #\|).  It checks for a
+;;; matching quote on the line that MARK points to, and puts the appropriate
+;;; area in the RANGES-TO-IGNORE slot and leaves MARK pointing after this area.
+;;; The "appropriate area" is from MARK to the end of the line or the matching
+;;; string-quote, whichever comes first.
+;;;
+
+(defun deal-with-quote (quote mark info-struct &optional (start (mark-charpos mark)))
+  "Alter the current line's info struct as necessary as due to encountering a
+  string or symbol quote character."
+  (if (fixnump quote) ;; nesting multi-line comments
+    (loop
+      (unless (and (scan-char mark :lisp-syntax (or :newline :symbol-quote))
+                   (test-char (next-character mark) :lisp-syntax :symbol-quote))
+        (line-end mark)
+        (push-range (cons start (mark-charpos mark)) info-struct)
+        (setf (lisp-info-ending-quoted info-struct) quote)
+        (return nil))
+      (if (prog1 (test-char (previous-character mark) :lisp-syntax :prefix-dispatch) (mark-after mark))
+        (incf quote)
+        (when (test-char (next-character mark) :lisp-syntax :prefix-dispatch)
+          (mark-after mark)
+          (decf quote)
+          (when (<= quote 0)
+            (push-range (cons start (mark-charpos mark)) info-struct)
+            (setf (lisp-info-ending-quoted info-struct) nil)
+            (return mark)))))
+    (cond ((find-valid-quote quote mark :forwardp t :cease-at-eol t)
+	   ;; If matching quote is on this line then mark the area between the
+	   ;; first quote (MARK) and the matching quote as invalid by pushing
+	   ;; its begining and ending into the IGNORE-RANGE.
+	   (push-range (cons start (mark-charpos mark)) info-struct)
+	   (mark-after mark))
+	  ;; If the EOL has been hit before the matching quote then mark the
+	  ;; area from MARK to the EOL as invalid.
+	  (t
+	   (line-end mark)
+	   (push-range (cons start (mark-charpos mark)) info-struct)
+	   ;; The Ending is marked as still being quoted. 
+	   (setf (lisp-info-ending-quoted info-struct) quote)
+	   nil))))
+
+;;;; Character validity checking:
+
+;;; Find-Ignore-Region  --  Internal
+;;;
+;;;    If the character in the specified direction from Mark is in an ignore
+;;; region, then return the region and the line that the region is in as
+;;; values.  If there is no ignore region, then return NIL and the Mark-Line.
+;;; If the line is not parsed, or there is no character (because of being at
+;;; the buffer beginning or end), then return both values NIL.
+;;;
+(defun find-ignore-region (mark forwardp)
+  (flet ((scan (line pos)
+	   (declare (fixnum pos))
+	   (let ((info (getf (line-plist line) 'lisp-info)))
+	     (if info
+		 (dolist (range (lisp-info-ranges-to-ignore info)
+				(values nil line))
+		   (let ((start (car range))
+			 (end (cdr range)))
+		     (declare (fixnum start end))
+		     (when (and (>= pos start) (< pos end))
+		       (return (values range line)))))
+		 (values nil nil)))))
+    (let ((pos (mark-charpos mark))
+	  (line (mark-line mark)))
+      (declare (fixnum pos))
+      (cond (forwardp (scan line pos))
+	    ((> pos 0) (scan line (1- pos)))
+	    (t
+	     (let ((prev (line-previous line)))
+	       (if prev
+		   (scan prev (line-length prev))
+		   (values nil nil))))))))
+
+
+;;; Valid-Spot  --  Public
+;;;
+(defun valid-spot (mark forwardp)
+  "Return true if the character pointed to by Mark is not in a quoted context,
+  false otherwise.  If Forwardp is true, we use the next character, otherwise
+  we use the previous."
+  (if (and (not forwardp)
+	   (null (previous-character mark)))
+    t			      ;beginning of buffer always a valid spot
+    (multiple-value-bind (region line)
+	(find-ignore-region mark forwardp)
+      (and line (not region)))))
+
+;;; Scan-Direction-Valid  --  Internal
+;;;
+;;;    Like scan-direction, but only stop on valid characters.
+;;;
+(defmacro scan-direction-valid (mark forwardp &rest forms)
+  (let ((n-mark (gensym))
+	(n-line (gensym))
+	(n-region (gensym))
+	(n-won (gensym)))
+    `(let ((,n-mark ,mark) (,n-won nil))
+       (loop
+	 (multiple-value-bind (,n-region ,n-line)
+			      (find-ignore-region ,n-mark ,forwardp)
+	   (unless ,n-line (return nil))
+	   (if ,n-region
+	       (move-to-position ,n-mark
+				 ,(if forwardp
+				      `(cdr ,n-region) 
+				      `(car ,n-region))
+				 ,n-line)
+	       (when ,n-won (return t)))
+	   ;;
+	   ;; Peculiar condition when a quoting character terminates a line.
+	   ;; The ignore region is off the end of the line causing %FORM-OFFSET
+	   ;; to infinitely loop.
+	   (when (> (mark-charpos ,n-mark) (line-length ,n-line))
+	     #+gz (break "This shouldn't happen any more")
+	     (line-offset ,n-mark 1 0))
+	   (unless (scan-direction ,n-mark ,forwardp ,@forms)
+	     (return nil))
+	   (setq ,n-won t))))))
+
+
+
+;;;; List offseting.
+
+;;; %LIST-OFFSET allows for BACKWARD-LIST and FORWARD-LIST to be built
+;;; with the same existing structure, with the altering of one variable.
+;;; This one variable being FORWARDP.
+;;; 
+(defmacro %list-offset (actual-mark forwardp &key (extra-parens 0) )
+  "Expand to code that will go forward one list either backward or forward, 
+   according to the FORWARDP flag."
+  (let ((mark (gensym)))
+    `(with-mark ((,mark ,actual-mark))
+       (if (valid-spot ,mark ,forwardp)
+         (let ((paren-count ,extra-parens))
+           (declare (fixnum paren-count))
+           (loop
+             (unless (scan-direction-valid ,mark ,forwardp :lisp-syntax
+                                           (or :close-paren :open-paren :newline))
+               (return nil))
+             (let ((ch (direction-char ,mark ,forwardp)))
+               (case (character-attribute :lisp-syntax ch)
+                 (:close-paren
+                  (decf paren-count)
+                  ,(when forwardp
+                     ;; When going forward, an unmatching close-paren means the
+                     ;; end of list.
+                     `(when (<= paren-count 0)
+                        (neighbor-mark ,mark ,forwardp)
+                        (move-mark ,actual-mark ,mark)
+                        (return t))))
+                 (:open-paren
+                  (incf paren-count)
+                  ,(unless forwardp             ; Same as above only end of list
+                     `(when (>= paren-count 0)  ; is opening parens.
+                        (neighbor-mark ,mark ,forwardp)
+                        (move-mark ,actual-mark ,mark)
+                          (return t))))
+                   
+                   (:newline 
+                    ;; When a #\Newline is hit, then the matching paren must lie
+                    ;; on some other line so drop down into the multiple line
+                    ;; balancing function: QUEST-FOR-BALANCING-PAREN If no paren
+                    ;; seen yet, keep going.
+                    (cond ((zerop paren-count))
+                          ((quest-for-balancing-paren ,mark paren-count ,forwardp)
+                           (move-mark ,actual-mark ,mark)
+                           (return t))
+                          (t
+                           (return nil))))))
+             (neighbor-mark ,mark ,forwardp)))
+         ;; We're inside a comment or a string.  Try anyway.
+         (when ,(if forwardp
+                  `(%forward-list-at-mark ,mark ,extra-parens t)
+                  `(%backward-list-at-mark ,mark ,extra-parens t))
+           (move-mark ,actual-mark ,mark))))))
+
+;;; 
+;;; QUEST-FOR-BALANCING-PAREN
+
+(defmacro quest-for-balancing-paren (mark paren-count forwardp)
+  "Expand to a form that finds the the balancing paren for however many opens or
+  closes are registered by Paren-Count."
+  `(let* ((line (mark-line ,mark)))
+     (loop
+       (setq line (neighbor-line line ,forwardp))
+       (unless line (return nil))
+       (let ((line-info (getf (line-plist line) 'lisp-info))
+	     (unbal-paren ,paren-count))
+	 (unless line-info (return nil))
+	 
+	 ,(if forwardp
+	      `(decf ,paren-count (lisp-info-net-close-parens line-info))
+	      `(incf ,paren-count (lisp-info-net-open-parens line-info)))
+	 
+	 (when ,(if forwardp
+		    `(<= ,paren-count 0)
+		    `(>= ,paren-count 0))
+	   ,(if forwardp
+		`(line-start ,mark line)
+		`(line-end ,mark line))
+	   (return (goto-correct-paren-char ,mark unbal-paren ,forwardp)))
+
+	 ,(if forwardp
+	      `(incf ,paren-count (lisp-info-net-open-parens line-info))
+	      `(decf ,paren-count (lisp-info-net-close-parens line-info)))))))
+		   
+
+;;; 
+;;; GOTO-CORRECT-PAREN-CHAR
+
+(defmacro goto-correct-paren-char (mark paren-count forwardp)
+  "Expand to a form that will leave MARK on the correct balancing paren matching 
+   however many are indicated by COUNT." 
+  `(with-mark ((m ,mark))
+     (let ((count ,paren-count))
+       (loop
+	 (scan-direction m ,forwardp :lisp-syntax 
+			 (or :close-paren :open-paren :newline))
+	 (when (valid-spot m ,forwardp)
+	   (ecase (character-attribute :lisp-syntax (direction-char m ,forwardp))
+	     (:close-paren 
+	      (decf count)
+	      ,(when forwardp
+		 `(when (zerop count)
+		    (neighbor-mark m ,forwardp)
+		    (move-mark ,mark m)
+		    (return t))))
+	     
+	     (:open-paren 
+	      (incf count)
+	      ,(unless forwardp
+		 `(when (zerop count)
+		    (neighbor-mark m ,forwardp)
+		    (move-mark ,mark m)
+		    (return t))))))
+	 (neighbor-mark m ,forwardp)))))
+
+
+(defun list-offset (mark offset)
+  (if (plusp offset)
+      (dotimes (i offset t)
+	(unless (%list-offset mark t) (return nil)))
+      (dotimes (i (- offset) t)
+	(unless (%list-offset mark nil) (return nil)))))
+
+(defun forward-up-list (mark)
+  "Moves mark just past the closing paren of the immediately containing list."
+  (%list-offset mark t :extra-parens 1))
+
+(defun backward-up-list (mark)
+  "Moves mark just before the opening paren of the immediately containing list."
+  (%list-offset mark nil :extra-parens -1))
+
+
+
+
+;;;; Top level form location hacks (open parens beginning lines).
+
+;;; NEIGHBOR-TOP-LEVEL is used only in TOP-LEVEL-OFFSET.
+;;; 
+(eval-when (:compile-toplevel :execute)
+(defmacro neighbor-top-level (line forwardp)
+  `(loop
+     (when (test-char (line-character ,line 0) :lisp-syntax :open-paren)
+       (return t))
+     (setf ,line ,(if forwardp `(line-next ,line) `(line-previous ,line)))
+     (unless ,line (return nil))))
+) ;eval-when
+
+(defun top-level-offset (mark offset)
+  "Go forward or backward offset number of top level forms.  Mark is
+   returned if offset forms exists, otherwise nil."
+  (declare (fixnum offset))
+  (let* ((line (mark-line mark))
+	 (at-start (test-char (line-character line 0) :lisp-syntax :open-paren)))
+    (cond ((zerop offset) mark)
+	  ((plusp offset)
+	   (do ((offset (if at-start offset (1- offset))
+			(1- offset)))
+	       (nil)
+	     (declare (fixnum offset))
+	     (unless (neighbor-top-level line t) (return nil))
+	     (when (zerop offset) (return (line-start mark line)))
+	     (unless (setf line (line-next line)) (return nil))))
+	  (t
+	   (do ((offset (if (and at-start (start-line-p mark))
+			    offset
+			    (1+ offset))
+			(1+ offset)))
+		(nil)
+	     (declare (fixnum offset))
+	     (unless (neighbor-top-level line nil) (return nil))
+	     (when (zerop offset) (return (line-start mark line)))
+	     (unless (setf line (line-previous line)) (return nil)))))))
+
+
+(defun mark-top-level-form (mark1 mark2)
+  "Moves mark1 and mark2 to the beginning and end of the current or next defun.
+   Mark1 one is used as a reference.  The marks may be altered even if
+   unsuccessful.  if successful, return mark2, else nil."
+  (let ((winp (cond ((inside-defun-p mark1)
+		     (cond ((not (top-level-offset mark1 -1)) nil)
+			   ((not (form-offset (move-mark mark2 mark1) 1)) nil)
+			   (t mark2)))
+		    ((start-defun-p mark1)
+		     (form-offset (move-mark mark2 mark1) 1))
+		    ((and (top-level-offset (move-mark mark2 mark1) -1)
+			  (start-defun-p mark2)
+			  (form-offset mark2 1)
+			  (same-line-p mark1 mark2))
+		     (form-offset (move-mark mark1 mark2) -1)
+		     mark2)
+		    ((top-level-offset mark1 1)
+		     (form-offset (move-mark mark2 mark1) 1)))))
+    (when winp
+      (when (blank-after-p mark2) (line-offset mark2 1 0))
+      mark2)))
+
+(defun inside-defun-p (mark)
+  "T if the current point is (supposedly) in a top level form."
+  (with-mark ((m mark))
+    (when (top-level-offset m -1)
+      (form-offset m 1)
+      (mark> m mark))))
+
+(defun start-defun-p (mark)
+  "Returns t if mark is sitting before an :open-paren at the beginning of a
+   line."
+  (and (start-line-p mark)
+       (test-char (next-character mark) :lisp-syntax :open-paren)))
+
+;;;; Form offseting.
+
+;; Heuristic versions, for navigating inside comments, doesn't make use of line info
+
+(defun unparsed-form-offset (mark forwardp)
+  ;; TODO: if called in "invalid" spot, arrange to stay within bounds of current invalid region.
+  ;; For now, just stop at #||# boundaries, as first approximation.
+  (if forwardp
+    (forward-form mark t)
+    (backward-form mark t)))
+
+(defun forward-form (mark &optional in-comment-p)
+  ;; If in-comment-p is true, tries not to go past a |#.
+  (with-mark ((m mark))
+    (when (and (scan-char m :lisp-syntax (or :open-paren :close-paren :prefix-dispatch
+                                             :symbol-quote :string-quote :char-quote
+                                             :comment :constituent))
+               (%forward-form-at-mark m in-comment-p))
+      (move-mark mark m))))
+
+(defun backward-form (mark &optional in-comment-p)
+  ;; If in-comment-p is true, tries not to go past a #|.
+  (with-mark ((m mark))
+    (when (%backward-form-at-mark m in-comment-p)
+      (loop while (test-char (previous-character m) :lisp-syntax :prefix) do (mark-before m))
+      (move-mark mark m))))
+
+(defun %forward-form-at-mark (mark in-comment-p)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (case (character-attribute :lisp-syntax (next-character mark))
+    (:open-paren
+     (mark-after mark)
+     (%forward-list-at-mark mark 1))
+    (:close-paren
+     nil)
+    (:char-quote
+     (%forward-symbol-at-mark mark in-comment-p))
+    (:symbol-quote
+     (mark-after mark)
+     (unless (and in-comment-p (test-char (next-character mark) :lisp-syntax :prefix-dispatch))
+       (mark-before mark)
+       (%forward-symbol-at-mark mark in-comment-p)))
+    (:prefix-dispatch
+     (mark-after mark)
+     (if (test-char (next-character mark) :lisp-syntax :symbol-quote)
+       (progn
+         (mark-after mark)
+         (%forward-nesting-comment-at-mark mark 1))
+       (progn
+         (mark-before mark)
+         (%forward-symbol-at-mark mark in-comment-p))))
+    (:string-quote
+     (%forward-string-at-mark mark))
+    (:constituent
+     (%forward-symbol-at-mark mark in-comment-p))
+    (:comment
+     (%forward-comments-at-mark mark))
+    (t
+     (mark-after mark)
+     (%forward-form-at-mark mark in-comment-p))))
+
+(defun %backward-form-at-mark (mark in-comment-p)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (let* ((char (previous-character mark))
+         (attrib (character-attribute :lisp-syntax char)))
+    (when char
+      (mark-before mark)
+      (when (char-quoted-at-mark-p mark t)
+        (setq attrib :constituent))
+      (case attrib
+        (:open-paren
+         nil)
+        (:close-paren
+         (%backward-list-at-mark mark 1))
+        (:char-quote  ;;; can only happen if starting right after an unquoted char-quote
+         (%backward-symbol-at-mark mark in-comment-p))
+        (:symbol-quote
+         (unless (and in-comment-p (test-char (previous-character mark) :lisp-syntax :prefix-dispatch))
+           (mark-after mark)
+           (%backward-symbol-at-mark mark in-comment-p)))
+        (:prefix-dispatch
+         (if (test-char (previous-character mark) :lisp-syntax :symbol-quote)
+           (progn
+             (mark-before mark)
+             (%backward-nesting-comment-at-mark mark 1))
+           (progn
+             (mark-after mark)
+             (%backward-symbol-at-mark mark in-comment-p))))
+        (:string-quote
+         (mark-after mark)
+         (%backward-string-at-mark mark))
+        (:constituent
+         (mark-after mark)
+         (%backward-symbol-at-mark mark in-comment-p))
+        (:prefix
+         (loop while (test-char (previous-character mark) :lisp-syntax :prefix) do (mark-before mark))
+         mark)
+        (:comment
+         (loop while (test-char (previous-character mark) :lisp-syntax :comment) do (mark-before mark))
+         mark)
+        ;; TODO: it would be nice to skip over ;; comments if starting outside one, i.e. if encounter a newline
+        ;; before a form starts.
+        (t (%backward-form-at-mark mark in-comment-p))))))
+
+(defun %forward-symbol-at-mark (mark in-comment-p)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (loop
+    (unless (scan-char mark :lisp-syntax (not (or :constituent :prefix-dispatch)))
+      (return (buffer-end mark)))
+    (case (character-attribute :lisp-syntax (next-character mark))
+      (:symbol-quote
+       (mark-after mark)
+       (when (and in-comment-p (test-char (next-character mark) :lisp-syntax :prefix-dispatch))
+         (return (mark-before mark)))
+       (unless (loop
+                 (unless (scan-char mark :lisp-syntax (or :char-quote :symbol-quote))
+                   (return nil))
+                 (when (test-char (next-character mark) :lisp-syntax :symbol-quote)
+                   (return t))
+                 (character-offset mark 2))
+         (return nil))
+       (mark-after mark))
+      (:char-quote
+       (character-offset mark 2))
+      (t (return mark)))))
+
+(defun %backward-symbol-at-mark (mark in-comment-p)
+  (loop
+    (unless (rev-scan-char mark :lisp-syntax (not (or :constituent :prefix-dispatch :char-quote)))
+      (buffer-start mark)
+      (return mark))
+    (mark-before mark)
+    (if (char-quoted-at-mark-p mark t)
+      (mark-before mark)
+      (let* ((char (next-character mark)))
+        (case (character-attribute :lisp-syntax char)
+          (:symbol-quote
+           (when (and in-comment-p (test-char (previous-character mark) :lisp-syntax :prefix-dispatch))
+             (return (mark-after mark)))
+           (unless (loop
+                     (unless (rev-scan-char mark :lisp-syntax :symbol-quote)
+                       (return nil))
+                     (mark-before mark)
+                     (unless (char-quoted-at-mark-p mark t)
+                       (return t))
+                     (mark-before mark))
+             (return nil)))
+          (t (mark-after mark)
+             (return mark)))))))
+
+(defun %forward-nesting-comment-at-mark (mark nesting)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (loop
+    (unless (scan-char mark :lisp-syntax :symbol-quote)
+      (return nil))
+    (let ((prev (previous-character mark)))
+      (mark-after mark)
+      (cond ((test-char prev :lisp-syntax :prefix-dispatch)
+             (incf nesting))
+            ((test-char (next-character mark) :lisp-syntax :prefix-dispatch)
+             (mark-after mark)
+             (when (<= (decf nesting) 0)
+               (return mark)))))))
+
+(defun %backward-nesting-comment-at-mark (mark nesting)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (loop
+    (unless (rev-scan-char mark :lisp-syntax :symbol-quote)
+      (return nil))
+    (let ((next (next-character mark)))
+      (mark-before mark)
+      (cond ((test-char next :lisp-syntax :prefix-dispatch)
+             (incf nesting))
+            ((test-char (previous-character mark) :lisp-syntax :prefix-dispatch)
+             (mark-before mark)
+             (when (<= (decf nesting) 0)
+               (return mark)))))))
+
+
+;; %FORM-OFFSET
+
+(defmacro %form-offset (mark forwardp)
+  `(if (valid-spot ,mark ,forwardp)
+     (with-mark ((m ,mark))
+       (when (scan-direction-valid m ,forwardp :lisp-syntax
+                                   (or :open-paren :close-paren
+                                       :char-quote :string-quote :symbol-quote
+                                       :prefix-dispatch :constituent))
+         (ecase (character-attribute :lisp-syntax (direction-char m ,forwardp))
+           (:open-paren
+            (when ,(if forwardp `(list-offset m 1) `(mark-before m))
+              ,(unless forwardp
+                 '(scan-direction m nil :lisp-syntax (not :prefix)))
+              (move-mark ,mark m)
+              t))
+           (:close-paren
+            (when ,(if forwardp `(mark-after m) `(list-offset m -1))
+              ,(unless forwardp
+                 '(scan-direction m nil :lisp-syntax (not :prefix)))
+              (move-mark ,mark m)
+              t))
+           ((:constituent :char-quote :symbol-quote :prefix-dispatch)
+            ,(if forwardp
+               `(scan-direction-valid m t :lisp-syntax
+                                      (not (or :constituent :char-quote :symbol-quote :prefix-dispatch)))
+               `(scan-direction-valid m nil :lisp-syntax
+                                      (not (or :constituent :char-quote :symbol-quote :prefix-dispatch
+                                               :prefix))))
+            (move-mark ,mark m)
+            t)
+           (:string-quote
+            (neighbor-mark m ,forwardp)
+            (when (scan-direction-valid m ,forwardp :lisp-syntax
+                                        :string-quote)
+              (neighbor-mark m ,forwardp)
+              (move-mark ,mark m)
+              t)))))
+     ;; Inside a comment or a string.  Switch to heuristic method.
+     (unparsed-form-offset ,mark ,forwardp)))
+
+(defun %forward-list-at-mark (mark nesting &optional in-comment-p)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (loop
+    (unless (scan-char mark :lisp-syntax (or :open-paren :close-paren :prefix-dispatch
+                                             :symbol-quote :string-quote :char-quote :comment))
+      (return nil))
+    (case (character-attribute :lisp-syntax (next-character mark))
+      (:open-paren
+       (mark-after mark)
+       (incf nesting))
+      (:close-paren
+       (mark-after mark)
+       (when (<= (decf nesting) 0)
+         (return (and (eql nesting 0) mark))))
+      (t
+       (unless (%forward-form-at-mark mark in-comment-p)
+         (return nil))))))
+
+(defun %backward-list-at-mark (mark nesting &optional in-comment-p)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (loop
+    (unless (rev-scan-char mark :lisp-syntax (or :open-paren :close-paren :prefix-dispatch
+                                                 :symbol-quote :string-quote :comment))
+      (return nil))
+    (mark-before mark)
+    (if (char-quoted-at-mark-p mark t)
+      (mark-before mark)
+      (case (character-attribute :lisp-syntax (next-character mark))
+        (:close-paren
+         (incf nesting))
+        (:open-paren
+         (when (<= (decf nesting) 0)
+           (return mark)))
+        (t
+         (mark-after mark)
+         (unless (%backward-form-at-mark mark in-comment-p)
+           (return nil)))))))
+
+(defun %forward-string-at-mark (mark)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (mark-after mark)
+  (loop
+    (unless (scan-char mark :lisp-syntax (or :char-quote :string-quote))
+      (return nil))
+    (unless (test-char (next-character mark) :lisp-syntax :char-quote)
+      (return (mark-after mark)))
+    (character-offset mark 2)))
+
+
+(defun %backward-string-at-mark (mark)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (mark-before mark)
+  (loop
+    (unless (rev-scan-char mark :lisp-syntax :string-quote)
+      (return nil))
+    (mark-before mark)
+    (unless (char-quoted-at-mark-p mark t)
+      (return mark))
+    (mark-before mark)))
+
+(defun %forward-comments-at-mark (mark)
+  ;; Warning: moves mark even if returns nil (hence the % in name).
+  (with-mark ((m mark))
+    (loop
+      (line-end m)
+      (mark-after m)
+      (move-mark mark m)
+      (unless (and (scan-char m :lisp-syntax (not :space))
+                   (test-char (next-character m) :lisp-syntax :comment))
+        (return mark)))))
+
+(defun form-offset (mark offset)
+  "Move mark offset number of forms, after if positive, before if negative.
+   Mark is always moved.  If there weren't enough forms, returns nil instead of
+   mark."
+  (if (plusp offset)
+      (dotimes (i offset t)
+	(unless (%form-offset mark t) (return nil)))
+      (dotimes (i (- offset) t)
+	(unless (%form-offset mark nil) (return nil)))))
+
+;; Return region for the "current form" at mark.
+;; TODO: See also mark-nearest-form, should merge them
+(defun form-region-at-mark (mark)
+  (with-mark ((bwd-start mark)
+              (bwd-end mark)
+              (fwd-start mark)
+              (fwd-end mark))
+    (let* ((fwd (and (or (and (char-quoted-at-mark-p mark t)       ;; back-up so get whole character
+                              (mark-before fwd-end))
+                         (test-char (next-character mark) :lisp-syntax
+                                    (or :open-paren :string-quote
+                                        :char-quote :symbol-quote :constituent :prefix-dispatch
+                                        :prefix)))
+                     (form-offset fwd-end 1)
+                     (form-offset (move-mark fwd-start fwd-end) -1)
+                     (mark<= fwd-start mark)))
+           (bwd (and (or (char-quoted-at-mark-p mark nil)
+                         (test-char (previous-character mark) :lisp-syntax
+                                    (or :close-paren :string-quote
+                                        :char-quote :symbol-quote :constituent :prefix-dispatch)))
+                     ;; Special case - if at an open paren, always select forward because that's
+                     ;; the matching paren that's highlighted.
+                     (not (and fwd (test-char (next-character mark) :lisp-syntax :open-paren)))
+                     ;; Also prefer string over anything but close paren.
+                     (not (and fwd (test-char (next-character mark) :lisp-syntax :string-quote)
+                               (not (test-char (previous-character mark) :lisp-syntax :close-paren))))
+                     (form-offset bwd-start -1)
+                     (form-offset (move-mark bwd-end bwd-start) 1)
+                     (mark<= mark bwd-end))))
+      (if bwd
+        (when (or (not fwd) ;; back is only option
+                  (and (mark= bwd-start fwd-start) (mark= bwd-end fwd-end)) ;; or they're the same
+                  (and (mark= bwd-start fwd-end)  ;; or had to skip prefix chars to get to forward
+                       (test-char (next-character fwd-start) :lisp-syntax (or :prefix :prefix-dispatch))))
+          (region bwd-start bwd-end))
+        (if fwd
+          (region fwd-start fwd-end))))))
+
+;;;; Table of special forms with special indenting requirements.
+
+(defhvar "Indent Defanything"
+  "This is the number of special arguments implicitly assumed to be supplied
+   in calls to functions whose names begin with \"DEF\".  If set to NIL, this
+   feature is disabled."
+  :value 2)
+
+(defhvar "Indent With-anything"
+  "This is the number of special arguments implicitly assumed to be supplied
+   in calls to functions whose names begin with \"WITH-\". If set to NIL, this
+   feature is disabled."
+  :value 1)
+
+(defvar *special-forms* (make-hash-table :test #'equal))
+
+(defun defindent (fname args)
+  "Define Fname to have Args special arguments.  If args is null then remove
+   any special arguments information."
+  (check-type fname string)
+  (let ((fname (string-upcase fname)))
+    (cond ((null args) (remhash fname *special-forms*))
+	  (t
+	   (check-type args integer)
+	   (setf (gethash fname *special-forms*) args)))))
+
+
+;;; Hemlock forms.
+;;; 
+(defindent "defhvar" 1)
+(defindent "hlet" 1)
+(defindent "defcommand" 2)
+(defindent "defattribute" 1)
+(defindent "command-case" 1)
+(defindent "do-strings" 1)
+(defindent "save-for-undo" 1)
+(defindent "do-alpha-chars" 1)
+(defindent "do-headers-buffers" 1)
+(defindent "do-headers-lines" 1)
+(defindent "frob" 1) ;cover silly FLET and MACROLET names for Rob and Bill.
+(defindent "modifying-buffer" 1)
+
+;;; Common Lisp forms.
+;;; 
+(defindent "block" 1)
+(defindent "case" 1)
+(defindent "catch" 1)
+(defindent "ccase" 1)			   
+(defindent "compiler-let" 1)
+(defindent "ctypecase" 1)
+(defindent "defconstant" 1)
+(defindent "define-compiler-macro" 2)
+(defindent "define-setf-method" 2)
+(defindent "destructuring-bind" 2)
+(defindent "defmacro" 2)
+(defindent "defpackage" 1)
+(defindent "defparameter" 1)
+(defindent "defstruct" 1)
+(defindent "deftype" 2)
+(defindent "defun" 2)
+(defindent "defvar" 1)
+(defindent "do" 2)
+(defindent "do*" 2)
+(defindent "do-all-symbols" 1)
+(defindent "do-external-symbols" 1)
+(defindent "do-symbols" 1)
+(defindent "dolist" 1)
+(defindent "dotimes" 1)
+(defindent "ecase" 1)
+(defindent "etypecase" 1)
+(defindent "eval-when" 1)
+(defindent "flet" 1)
+(defindent "if" 1)
+(defindent "labels" 1)
+(defindent "lambda" 1)
+(defindent "let" 1)
+(defindent "let*" 1)
+(defindent "locally" 0)
+(defindent "loop" 0)
+(defindent "macrolet" 1)
+(defindent "multiple-value-bind" 2)
+(defindent "multiple-value-call" 1)
+(defindent "multiple-value-prog1" 1)
+(defindent "multiple-value-setq" 1)
+(defindent "prog" 1)
+(defindent "prog*" 1)
+(defindent "prog1" 1)
+(defindent "progv" 2)
+(defindent "progn" 0)
+(defindent "typecase" 1)
+(defindent "unless" 1)
+(defindent "unwind-protect" 1)
+(defindent "when" 1)
+
+;;; Error/condition system forms.
+;;; 
+(defindent "define-condition" 2)
+(defindent "handler-bind" 1)
+(defindent "handler-case" 1)
+(defindent "restart-bind" 1)
+(defindent "restart-case" 1)
+;;; These are for RESTART-CASE branch formatting.
+(defindent "store-value" 1)
+(defindent "use-value" 1)
+(defindent "muffle-warning" 1)
+(defindent "abort" 1)
+(defindent "continue" 1)
+
+;;; Debug-internals forms.
+;;;
+(defindent "do-debug-function-blocks" 1)
+(defindent "di:do-debug-function-blocks" 1)
+(defindent "do-debug-function-variables" 1)
+(defindent "di:do-debug-function-variables" 1)
+(defindent "do-debug-block-locations" 1)
+(defindent "di:do-debug-block-locations" 1)
+;;;
+;;; Debug-internals conditions
+;;; (define these to make uses of HANDLER-CASE indent branches correctly.)
+;;;
+(defindent "debug-condition" 1)
+(defindent "di:debug-condition" 1)
+(defindent "no-debug-info" 1)
+(defindent "di:no-debug-info" 1)
+(defindent "no-debug-function-returns" 1)
+(defindent "di:no-debug-function-returns" 1)
+(defindent "no-debug-blocks" 1)
+(defindent "di:no-debug-blocks" 1)
+(defindent "lambda-list-unavailable" 1)
+(defindent "di:lambda-list-unavailable" 1)
+(defindent "no-debug-variables" 1)
+(defindent "di:no-debug-variables" 1)
+(defindent "invalid-value" 1)
+(defindent "di:invalid-value" 1)
+(defindent "ambiguous-variable-name" 1)
+(defindent "di:ambiguous-variable-name" 1)
+(defindent "debug-error" 1)
+(defindent "di:debug-error" 1)
+(defindent "unhandled-condition" 1)
+(defindent "di:unhandled-condition" 1)
+(defindent "unknown-code-location" 1)
+(defindent "di:unknown-code-location" 1)
+(defindent "unknown-debug-variable" 1)
+(defindent "di:unknown-debug-variable" 1)
+(defindent "invalid-control-stack-pointer" 1)
+(defindent "di:invalid-control-stack-pointer" 1)
+(defindent "frame-function-mismatch" 1)
+(defindent "di:frame-function-mismatch" 1)
+
+
+;;; CLOS forms.
+;;; 
+(defindent "with-accessors" 2)
+(defindent "defclass" 2)
+(defindent "print-unreadable-object" 1)
+(defindent "defmethod" 2)
+(defindent "make-instance" 1)
+
+;;; System forms.
+;;;
+(defindent "rlet" 1)
+
+;;; Multiprocessing forms.
+(defindent "process-wait" 1)
+
+
+
+
+;;;; Indentation.
+
+;;; LISP-INDENTATION -- Internal Interface.
+
+(defun strip-package-prefix (string)
+  (let* ((p (position #\: string :from-end t)))
+    (if p
+      (subseq string (1+ p))
+      string)))
+;;;
+(defun lisp-indentation (mark)
+  "Compute number of spaces which mark should be indented according to
+   local context and lisp grinding conventions.  This assumes mark is at the
+   beginning of the line to be indented."
+  (with-mark ((m mark)
+	      (temp mark))
+    ;; See if we are in a quoted context.
+    (unless (valid-spot m nil)
+      (return-from lisp-indentation (lisp-generic-indentation m)))
+    ;; Look for the paren that opens the containing form.
+    (unless (backward-up-list m)
+      (return-from lisp-indentation 0))
+    ;; Move after the paren, save the start, and find the form name.
+    (mark-after m)
+    (with-mark ((start m))
+      (unless (and (scan-char m :lisp-syntax
+			      (not (or :space :prefix :prefix-dispatch :char-quote)))
+		   (test-char (next-character m) :lisp-syntax :constituent))
+	(return-from lisp-indentation (mark-column start)))
+      (with-mark ((fstart m))
+	(scan-char m :lisp-syntax (not :constituent))
+	(let* ((fname (nstring-upcase
+                       (strip-package-prefix (region-to-string (region fstart m)))))
+	       (special-args (or (gethash fname *special-forms*)
+				 (and (> (length fname) 2)
+				      (string= fname "DEF" :end1 3)
+				      (value indent-defanything))
+                                 (and (> (length fname) 4)
+                                      (string= fname "WITH-" :end1 5)
+                                      (value indent-with-anything)))))
+	  (declare (simple-string fname))
+	  ;; Now that we have the form name, did it have special syntax?
+	  (cond (special-args
+		 (with-mark ((spec m))
+		   (cond ((and (form-offset spec special-args)
+			       (mark<= spec mark))
+			  (1+ (mark-column start)))
+			 ((skip-valid-space m)
+			  (mark-column m))
+			 (t
+			  (+ (mark-column start) 3)))))
+		;; See if the user seems to have altered the editor's
+		;; indentation, and if so, try to adhere to it.  This usually
+		;; happens when you type in a quoted list constant that line
+		;; wraps.  You want all the items on successive lines to fall
+		;; under the first character after the opening paren, not as if
+		;; you are calling a function.
+		((and (form-offset temp -1)
+		      (or (blank-before-p temp) (not (same-line-p temp fstart)))
+		      (not (same-line-p temp mark)))
+		 (unless (blank-before-p temp)
+		   (line-start temp)
+		   (find-attribute temp :space #'zerop))
+		 (mark-column temp))
+		;; Appears to be a normal form.  Is the first arg on the same
+		;; line as the form name?
+		((skip-valid-space m)
+		 (or (lisp-indentation-check-for-local-def
+		      mark temp fstart start t)
+		     (mark-column m)))
+		;; Okay, fall under the first character after the opening paren.
+		(t
+		 (or (lisp-indentation-check-for-local-def
+		      mark temp fstart start nil)
+		     (mark-column start)))))))))
+
+(defhvar "Lisp Indentation Local Definers"
+  "Forms with syntax like LABELS, MACROLET, etc."
+  :value '("LABELS" "MACROLET" "FLET"))
+
+;;; LISP-INDENTATION-CHECK-FOR-LOCAL-DEF -- Internal.
+;;;
+;;; This is a temporary hack to see how it performs.  When we are indenting
+;;; what appears to be a function call, let's look for FLET or MACROLET to see
+;;; if we really are indenting a local definition.  If we are, return the
+;;; indentation for a DEFUN; otherwise, nil
+;;;
+;;; Mark is the argument to LISP-INDENTATION.  Start is just inside the paren
+;;; of what looks like a function call.  If we are in an FLET, arg-list
+;;; indicates whether the local function's arg-list has been entered, that is,
+;;; whether we need to normally indent for a DEFUN body or indent specially for
+;;; the arg-list.
+;;;
+(defun lisp-indentation-check-for-local-def (mark temp1 temp2 start arg-list)
+  ;; We know this succeeds from LISP-INDENTATION.
+  (backward-up-list (move-mark temp1 mark)) ;Paren for local definition.
+  (cond ((and (backward-up-list temp1)	    ;Paren opening the list of defs
+	      (form-offset (move-mark temp2 temp1) -1)
+	      (mark-before temp2)
+	      (backward-up-list temp1)	    ;Paren for FLET or MACROLET.
+	      (mark= temp1 temp2))	    ;Must be in first arg form.
+	 ;; See if the containing form is named FLET or MACROLET.
+	 (mark-after temp1)
+	 (unless (and (scan-char temp1 :lisp-syntax
+				 (not (or :space :prefix :prefix-dispatch :char-quote)))
+		      (test-char (next-character temp1) :lisp-syntax
+				 :constituent))
+	   (return-from lisp-indentation-check-for-local-def nil))
+	 (move-mark temp2 temp1)
+	 (scan-char temp2 :lisp-syntax (not :constituent))
+	 (let ((fname (nstring-upcase (region-to-string (region temp1 temp2)))))
+	   (cond ((not (member fname (value lisp-indentation-local-definers)
+			       :test #'string=))
+		  nil)
+		 (arg-list
+		  (1+ (mark-column start)))
+		 (t
+		  (+ (mark-column start) 3)))))))
+
+;;; LISP-GENERIC-INDENTATION -- Internal.
+;;;
+;;; LISP-INDENTATION calls this when mark is in a invalid spot, or quoted
+;;; context.  If we are inside a string, we return the column one greater
+;;; than the opening double quote.  Otherwise, we just use the indentation
+;;; of the first preceding non-blank line.
+;;;
+(defun lisp-generic-indentation (mark)
+  (with-mark ((m mark))
+    (form-offset m -1)
+    (cond ((eq (character-attribute :lisp-syntax (next-character m))
+	       :string-quote)
+	   (1+ (mark-column m)))
+	  (t
+	   (let* ((line (mark-line mark))
+		  (prev (do ((line (line-previous line) (line-previous line)))
+			    ((not (and line (blank-line-p line))) line))))
+	     (cond (prev
+		    (line-start mark prev)
+		    (find-attribute mark :space #'zerop)
+		    (mark-column mark))
+		   (t 0)))))))
+
+;;; Skip-Valid-Space  --  Internal
+;;;
+;;;    Skip over any space on the line Mark is on, stopping at the first valid
+;;; non-space character.  If there is none on the line, return nil.
+;;;
+(defun skip-valid-space (mark)
+  (loop
+    (scan-char mark :lisp-syntax (not :space))
+    (let ((val (character-attribute :lisp-syntax
+				    (next-character mark))))
+      (cond ((eq val :newline) (return nil))
+	    ((valid-spot mark t) (return mark))))
+    (mark-after mark)))
+
+;; (declaim (optimize (speed 0))); byte compile again
+
+
+
+;;;; Indentation commands and hook functions.
+
+(defcommand "Defindent" (p)
+  "Define the Lisp indentation for the current function.
+  The indentation is a non-negative integer which is the number
+  of special arguments for the form.  Examples: 2 for Do, 1 for Dolist.
+  If a prefix argument is supplied, then delete the indentation information."
+  "Do a defindent, man!"
+  (with-mark ((m (current-point)))
+    (pre-command-parse-check m)
+    (unless (backward-up-list m) (editor-error))
+    (mark-after m)
+    (with-mark ((n m))
+      (scan-char n :lisp-syntax (not :constituent))
+      (let ((s (region-to-string (region m n))))
+	(declare (simple-string s))
+	(when (zerop (length s)) (editor-error))
+	(if p
+	    (defindent s nil)
+	    (let ((i (prompt-for-integer
+		      :prompt (format nil "Indentation for ~A: " s)
+		      :help "Number of special arguments.")))
+	      (when (minusp i)
+		(editor-error "Indentation must be non-negative."))
+	      (defindent s i))))))
+  (indent-command nil))
+
+(defcommand "Indent Form" (p)
+  "Indent Lisp code in the next form."
+  "Indent Lisp code in the next form."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (with-mark ((m point))
+      (unless (form-offset m 1) (editor-error))
+      (lisp-indent-region (region point m) "Indent Form"))))
+
+;;; LISP-INDENT-REGION -- Internal.
+;;;
+;;; This indents a region of Lisp code without doing excessive redundant
+;;; computation.  We parse the entire region once, then scan through doing
+;;; indentation on each line.  We forcibly reparse each line that we indent so
+;;; that the list operations done to determine indentation of subsequent lines
+;;; will work.  This is done undoably with save1, save2, buf-region, and
+;;; undo-region.
+;;;
+(defun lisp-indent-region (region &optional (undo-text "Lisp region indenting"))
+  (let* ((start (region-start region))
+         (end (region-end region))
+         (buffer (hi::line-%buffer (mark-line start))))
+    (with-mark ((m1 start)
+		(m2 end))
+      (funcall (value parse-start-function) m1)
+      (funcall (value parse-end-function) m2)
+      (parse-over-block (mark-line m1) (mark-line m2)))
+    (hi::check-buffer-modification buffer start)
+    (hi::check-buffer-modification buffer end)
+    (let* ((first-line (mark-line start))
+              (last-line (mark-line end))
+              (prev (line-previous first-line))
+              (prev-line-info
+               (and prev (getf (line-plist prev) 'lisp-info)))
+              (save1 (line-start (copy-mark start :right-inserting)))
+              (save2 (line-end (copy-mark end :left-inserting)))
+              (buf-region (region save1 save2))
+              (undo-region (copy-region buf-region)))
+         (with-mark ((bol start :left-inserting))
+           (do ((line first-line (line-next line)))
+               (nil)
+             (line-start bol line)
+             (ensure-lisp-indentation bol)
+             (let ((line-info (getf (line-plist line) 'lisp-info)))
+               (parse-lisp-line-info bol line-info prev-line-info)
+               (setq prev-line-info line-info))
+             (when (eq line last-line) (return nil))))
+         (make-region-undo :twiddle undo-text buf-region undo-region))))
+
+;;; INDENT-FOR-LISP -- Internal.
+;;;
+;;; This is the value of "Indent Function" for "Lisp" mode.
+;;;
+(defun indent-for-lisp (mark)
+  (line-start mark)
+  (pre-command-parse-check mark)
+  (ensure-lisp-indentation mark))
+
+(defun count-leading-whitespace (mark)
+  (with-mark ((m mark))
+    (line-start m)
+    (do* ((p 0)
+	  (q 0 (1+ q))
+          (tab-width (value spaces-per-tab)))
+         ()
+      (case (next-character m)
+        (#\space (incf p))
+        (#\tab (setq p (* tab-width (ceiling (1+ p) tab-width))))
+        (t (return (values p q))))
+      (character-offset m 1))))
+
+;;; Don't do anything if M's line is already correctly indented.
+(defun ensure-lisp-indentation (m)
+  (let* ((col (lisp-indentation m)))
+    (multiple-value-bind (curcol curpos) (count-leading-whitespace m)
+      (cond ((= curcol col) (setf (mark-charpos m) curpos))
+	    (t
+	     (delete-horizontal-space m)
+	     (indent-to-column m col))))))
+
+
+
+
+
+;;;; Most "Lisp" mode commands.
+
+(defcommand "Beginning of Defun" (p)
+  "Move the point to the beginning of a top-level form, collapsing the selection.
+  with an argument, skips the previous p top-level forms."
+  "Move the point to the beginning of a top-level form, collapsing the selection."
+  (let ((point (current-point-collapsing-selection))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (if (minusp count)
+	(end-of-defun-command (- count))
+	(unless (top-level-offset point (- count))
+	  (editor-error)))))
+
+(defcommand "Select to Beginning of Defun" (p)
+  "Move the point to the beginning of a top-level form, extending the selection.
+  with an argument, skips the previous p top-level forms."
+  "Move the point to the beginning of a top-level form, extending the selection."
+  (let ((point (current-point-for-selection-start))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (if (minusp count)
+	(end-of-defun-command (- count))
+	(unless (top-level-offset point (- count))
+	  (editor-error)))))
+
+;;; "End of Defun", with a positive p (the normal case), does something weird.
+;;; Get a mark at the beginning of the defun, and then offset it forward one
+;;; less top level form than we want.  This sets us up to use FORM-OFFSET which
+;;; allows us to leave the point immediately after the defun.  If we used
+;;; TOP-LEVEL-OFFSET one less than p on the mark at the end of the current
+;;; defun, point would be left at the beginning of the p+1'st form instead of
+;;; at the end of the p'th form.
+;;;
+(defcommand "End of Defun" (p)
+  "Move the point to the end of a top-level form, collapsing the selection.
+   With an argument, skips the next p top-level forms."
+  "Move the point to the end of a top-level form, collapsing the selection."
+  (let ((point (current-point-collapsing-selection))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (if (minusp count)
+	(beginning-of-defun-command (- count))
+	(with-mark ((m point)
+		    (dummy point))
+	  (cond ((not (mark-top-level-form m dummy))
+		 (editor-error "No current or next top level form."))
+		(t 
+		 (unless (top-level-offset m (1- count))
+		   (editor-error "Not enough top level forms."))
+		 ;; We might be one unparsed for away.
+		 (pre-command-parse-check m)
+		 (unless (form-offset m 1)
+		   (editor-error "Not enough top level forms."))
+		 (when (blank-after-p m) (line-offset m 1 0))
+		 (move-mark point m)))))))
+
+(defcommand "Select to End of Defun" (p)
+  "Move the point to the end of a top-level form, extending the selection.
+   With an argument, skips the next p top-level forms."
+  "Move the point to the end of a top-level form, extending the selection."
+  (let ((point (current-point-for-selection-end))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (if (minusp count)
+	(beginning-of-defun-command (- count))
+	(with-mark ((m point)
+		    (dummy point))
+	  (cond ((not (mark-top-level-form m dummy))
+		 (editor-error "No current or next top level form."))
+		(t 
+		 (unless (top-level-offset m (1- count))
+		   (editor-error "Not enough top level forms."))
+		 ;; We might be one unparsed for away.
+		 (pre-command-parse-check m)
+		 (unless (form-offset m 1)
+		   (editor-error "Not enough top level forms."))
+		 (when (blank-after-p m) (line-offset m 1 0))
+		 (move-mark point m)))))))
+
+(defcommand "Forward List" (p)
+  "Skip over the next Lisp list, collapsing the selection.
+  With argument, skips the next p lists."
+  "Skip over the next Lisp list, collapsing the selection."
+  (or (collapse-if-selection :direction :forward)
+      (let ((point (current-point-collapsing-selection))
+            (count (or p 1)))
+        (pre-command-parse-check point)
+        (unless (list-offset point count) (editor-error)))))
+
+(defcommand "Select Forward List" (p)
+  "Skip over the next Lisp list, extending the selection.
+  With argument, skips the next p lists."
+  "Skip over the next Lisp list, extending the selection."
+  (let ((point (current-point-for-selection-end))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (unless (list-offset point count) (editor-error))))
+
+(defcommand "Backward List" (p)
+  "Skip over the previous Lisp list, collapsing the selection.
+  With argument, skips the previous p lists."
+  "Skip over the previous Lisp list, collapsing the selection."
+  (or (collapse-if-selection :direction :backward)
+   (let ((point (current-point-collapsing-selection))
+	(count (- (or p 1))))
+    (pre-command-parse-check point)
+    (unless (list-offset point count) (editor-error)))))
+
+(defcommand "Select Backward List" (p)
+  "Skip over the previous Lisp list, extending the selection.
+  With argument, skips the previous p lists."
+  "Skip over the previous Lisp list, extending the selection."
+  (let ((point (current-point-for-selection-start))
+	(count (- (or p 1))))
+    (pre-command-parse-check point)
+    (unless (list-offset point count) (editor-error))))
+
+(defcommand "Forward Form" (p)
+    "Skip over the next Form, collapsing the selection.
+  With argument, skips the next p Forms."
+    "Skip over the next Form, collapsing the selection."
+  (or (collapse-if-selection :direction :forward)
+      (let ((point (current-point-collapsing-selection))
+            (count (or p 1)))
+        (pre-command-parse-check point)
+        (unless (form-offset point count) (editor-error)))))
+
+(defcommand "Select Forward Form" (p)
+  "Skip over the next Form, extending the selection.
+  With argument, skips the next p Forms."
+  "Skip over the next Form, extending the selection."
+  (let ((point (current-point-for-selection-end))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (unless (form-offset point count) (editor-error))))
+
+(defcommand "Backward Form" (p)
+    "Skip over the previous Form, collapsing the selection.
+  With argument, skips the previous p Forms."
+    "Skip over the previous Form, collaspsing the selection."
+  (or (collapse-if-selection :direction :backward)
+      (let ((point (current-point-collapsing-selection))
+            (count (- (or p 1))))
+        (pre-command-parse-check point)
+        (unless (form-offset point count) (editor-error)))))
+
+(defcommand "Select Backward Form" (p)
+  "Skip over the previous Form, extending the selection.
+  With argument, skips the previous p Forms."
+  "Skip over the previous Form, extending the selection."
+  (let ((point (current-point-for-selection-start))
+	(count (- (or p 1))))
+    (pre-command-parse-check point)
+    (unless (form-offset point count) (editor-error))))
+
+(defcommand "Mark Form" (p)
+  "Set the mark at the end of the next Form.
+   With a positive argument, set the mark after the following p
+   Forms. With a negative argument, set the mark before
+   the preceding -p Forms."
+  "Set the mark at the end of the next Form."
+  (with-mark ((m (current-point)))
+    (pre-command-parse-check m)
+    (let ((count (or p 1))
+	  (mark (push-new-buffer-mark m t)))
+      (if (form-offset m count)
+	  (move-mark mark m)
+	  (editor-error)))))
+
+(defcommand "Mark Defun" (p)
+  "Puts the region around the next or containing top-level form.
+   The point is left before the form and the mark is placed immediately
+   after it."
+  "Puts the region around the next or containing top-level form."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (with-mark ((start point)
+		(end point))
+      (cond ((not (mark-top-level-form start end))
+	     (editor-error "No current or next top level form."))
+	    (t
+	     (move-mark point start)
+	     (move-mark (push-new-buffer-mark point t) end))))))
+
+(defcommand "Forward Kill Form" (p)
+  "Kill the next Form.
+   With a positive argument, kills the next p Forms.
+   Kills backward with a negative argument."
+  "Kill the next Form."
+  (with-mark ((m1 (current-point))
+	      (m2 (current-point)))
+    (pre-command-parse-check m1)
+    (let ((count (or p 1)))
+      (unless (form-offset m1 count) (editor-error))
+      (if (minusp count)
+	  (kill-region (region m1 m2) :kill-backward)
+	  (kill-region (region m2 m1) :kill-forward)))))
+
+(defcommand "Backward Kill Form" (p)
+  "Kill the previous Form.
+  With a positive argument, kills the previous p Forms.
+  Kills forward with a negative argument."
+  "Kill the previous Form."
+  (forward-kill-form-command (- (or p 1))))
+
+(defcommand "Extract Form" (p)
+  "Replace the current containing list with the next form.  The entire affected
+   area is pushed onto the kill ring.  If an argument is supplied, that many
+   upward levels of list nesting is replaced by the next form."
+  "Replace the current containing list with the next form.  The entire affected
+   area is pushed onto the kill ring.  If an argument is supplied, that many
+   upward levels of list nesting is replaced by the next form."
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (with-mark ((form-start point :right-inserting)
+		(form-end point))
+      (unless (form-offset form-end 1) (editor-error))
+      (form-offset (move-mark form-start form-end) -1)
+      (with-mark ((containing-start form-start :left-inserting)
+		  (containing-end form-end :left-inserting))
+	(dotimes (i (or p 1))
+	  (unless (and (forward-up-list containing-end)
+		       (backward-up-list containing-start))
+	    (editor-error)))
+	(let ((r (copy-region (region form-start form-end))))
+	  (ring-push (delete-and-save-region
+		      (region containing-start containing-end))
+		     *kill-ring*)
+	  (ninsert-region point r)
+	  (move-mark point form-start))))))
+
+(defcommand "Extract List" (p)
+  "Extract the current list.
+  The current list replaces the surrounding list.  The entire affected
+  area is pushed on the kill-ring.  With prefix argument, remove that
+  many surrounding lists."
+  "Replace the P containing lists with the current one."
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (with-mark ((lstart point :right-inserting)
+		(lend point))
+      (if (eq (character-attribute :lisp-syntax (next-character lstart))
+	      :open-paren)
+	  (mark-after lend)
+	  (unless (backward-up-list lstart) (editor-error)))
+      (unless (forward-up-list lend) (editor-error))
+      (with-mark ((rstart lstart)
+		  (rend lend))
+	(dotimes (i (or p 1))
+	  (unless (and (forward-up-list rend) (backward-up-list rstart))
+	    (editor-error)))
+	(let ((r (copy-region (region lstart lend))))
+	  (ring-push (delete-and-save-region (region rstart rend))
+		     *kill-ring*)
+	  (ninsert-region point r)
+	  (move-mark point lstart))))))
+
+(defcommand "Transpose Forms" (p)
+  "Transpose Forms immediately preceding and following the point.
+  With a zero argument, tranposes the Forms at the point and the mark.
+  With a positive argument, transposes the Form preceding the point
+  with the p-th one following it.  With a negative argument, transposes the
+  Form following the point with the p-th one preceding it."
+  "Transpose Forms immediately preceding and following the point."
+  (let ((point (current-point))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (if (zerop count)
+	(let ((mark (current-mark)))
+	  (with-mark ((s1 mark :left-inserting)
+		      (s2 point :left-inserting))
+	    (scan-char s1 :whitespace nil)
+	    (scan-char s2 :whitespace nil)
+	    (with-mark ((e1 s1 :right-inserting)
+			(e2 s2 :right-inserting))
+	      (unless (form-offset e1 1) (editor-error))
+	      (unless (form-offset e2 1) (editor-error))
+	      (ninsert-region s1 (delete-and-save-region (region s2 e2)))
+	      (ninsert-region s2 (delete-and-save-region (region s1 e1))))))
+	(let ((fcount (if (plusp count) count 1))
+	      (bcount (if (plusp count) 1 count)))
+	  (with-mark ((s1 point :left-inserting)
+		      (e2 point :right-inserting))
+	    (dotimes (i bcount)
+	      (unless (form-offset s1 -1) (editor-error)))
+	    (dotimes (i fcount)
+	      (unless (form-offset e2 1) (editor-error)))
+	    (with-mark ((e1 s1 :right-inserting)
+			(s2 e2 :left-inserting))
+	      (unless (form-offset e1 1) (editor-error))
+	      (unless (form-offset s2 -1) (editor-error))
+	      (ninsert-region s1 (delete-and-save-region (region s2 e2)))
+	      (ninsert-region s2 (delete-and-save-region (region s1 e1)))
+	      (move-mark point s2)))))))
+
+
+(defcommand "Insert ()" (count)
+  "Insert a pair of parentheses ().  With positive argument, puts
+   parentheses around the next COUNT Forms, or previous COUNT forms, if
+   COUNT is negative.  The point is positioned after the open parenthesis."
+  "Insert a pair of parentheses ()."
+  ;; TODO Form navigation is broken, so this is broken too -- it is
+  ;; possible to put parens around more forms than there are in current
+  ;; expression.  It works by moving past as many forms as there is, and
+  ;; then each delimiting paren also counts as a form.
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (cond (count
+	   (when (minusp count)
+	     (form-offset point count)
+	     (setq count (- count)))
+	   (insert-character point #\()
+	   (with-mark ((m point))
+	     (unless (form-offset m count)
+	       (editor-error "Could not find that many forms."))
+	     (insert-character m #\))))
+	  ;; The simple case with no prefix argument
+	  (t
+	   (insert-character point #\()
+	   (insert-character point #\))
+	   (mark-before point)))))
+
+
+(defcommand "Move Over )" (p)
+  "Move past the next close parenthesis, and start a new line.  Any
+   indentation preceding the preceding the parenthesis is deleted, and the
+   new line is indented.  If there is only whitespace preceding the close
+   paren, the paren is moved to the end of the previous line. With prefix
+   argument, this command moves past next closing paren and inserts space."
+  "Move past the next close parenthesis, and start a new line."
+  ;; TODO This is still not complete, because SCAN-CHAR finds the next
+  ;; close-paren, but we need to find the next paren that closes current
+  ;; expression.  This will have to be updated when form navigation is
+  ;; fixed.
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (with-mark ((m point :right-inserting))
+      (cond ((scan-char m :lisp-syntax :close-paren)
+	     (cond ((same-line-p point m)
+		    (delete-horizontal-space m))
+		   (t
+		    (move-mark point m)
+		    (reverse-find-attribute point :whitespace #'zerop)
+		    (delete-region (region point m))))
+	     (cond ((not p)
+		    ;; Move to the previous line if current is empty
+		    (when (zerop (mark-charpos m))
+		      (delete-characters m -1))
+		    (mark-after m)
+		    (move-mark point m)
+		    (indent-new-line-command 1))
+		   (t
+		    (mark-after m)
+		    (move-mark point m)
+		    (insert-character m #\space))))
+	    (t 
+	     (editor-error "Could not find closing paren."))))))
+
+
+(defcommand "Forward Up List" (p)
+    "Move forward past a one containing )."
+    "Move forward past a one containing )."
+  (or (collapse-if-selection :direction :forward)
+      (let ((point (current-point-collapsing-selection))
+            (count (or p 1)))
+        (pre-command-parse-check point)
+        (if (minusp count)
+            (backward-up-list-command (- count))
+            (with-mark ((m point))
+              (dotimes (i count (move-mark point m))
+                (unless (forward-up-list m) (editor-error))))))))
+
+(defcommand "Backward Up List" (p)
+    "Move backward past a one containing (."
+    "Move backward past a one containing (."
+  (or (collapse-if-selection :direction :backward)
+      (let ((point (current-point-collapsing-selection))
+            (count (or p 1)))
+        (pre-command-parse-check point)
+        (if (minusp count)
+            (forward-up-list-command (- count))
+            (with-mark ((m point))
+              (dotimes (i count (move-mark point m))
+                (unless (backward-up-list m) (editor-error))))))))
+
+
+(defcommand "Down List" (p)
+  "Move down a level in list structure.  With positive argument, moves down
+   p levels.  With negative argument, moves down backward, but only one
+   level."
+  "Move down a level in list structure."
+  (let ((point (current-point-collapsing-selection))
+	(count (or p 1)))
+    (pre-command-parse-check point)
+    (with-mark ((m point))
+      (cond ((plusp count)
+	     (loop repeat count
+                   do (unless (and (scan-char m :lisp-syntax :open-paren)
+                                   (mark-after m))
+                        (editor-error))))
+	    (t
+	     (unless (and (rev-scan-char m :lisp-syntax :close-paren)
+			  (mark-before m))
+	       (editor-error))))
+      (move-mark point m))))
+
+
+
+
+;;;; Filling Lisp comments, strings, and indented text.
+
+(defhvar "Fill Lisp Comment Paragraph Confirm"
+  "This determines whether \"Fill Lisp Comment Paragraph\" will prompt for
+   confirmation to fill contiguous lines with the same initial whitespace when
+   it is invoked outside of a comment or string."
+  :value t)
+
+(defcommand "Fill Lisp Comment Paragraph" (p)
+  "This fills a flushleft or indented Lisp comment.
+   This also fills Lisp string literals using the proper indentation as a
+   filling prefix.  When invoked outside of a comment or string, this tries
+   to fill all contiguous lines beginning with the same initial, non-empty
+   blankspace.  When filling a comment, the current line is used to determine a
+   fill prefix by taking all the initial whitespace on the line, the semicolons,
+   and any whitespace following the semicolons."
+  "Fills a flushleft or indented Lisp comment."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (with-mark ((start point)
+		(end point)
+		(m point))
+      (let ((commentp (fill-lisp-comment-paragraph-prefix start end)))
+	(cond (commentp
+	       (fill-lisp-comment-or-indented-text start end))
+	      ((and (not (valid-spot m nil))
+		    (form-offset m -1)
+		    (eq (character-attribute :lisp-syntax (next-character m))
+			:string-quote))
+	       (fill-lisp-string m))
+	      ((or (not (value fill-lisp-comment-paragraph-confirm))
+		   (prompt-for-y-or-n
+		    :prompt '("Not in a comment or string.  Fill contiguous ~
+			       lines with the same initial whitespace? ")))
+	       (fill-lisp-comment-or-indented-text start end)))))))
+
+;;; FILL-LISP-STRING -- Internal.
+;;;
+;;; This fills the Lisp string containing mark as if it had been entered using
+;;; Hemlock's Lisp string indentation, "Indent Function" for "Lisp" mode.  This
+;;; assumes the area around mark has already been PRE-COMMAND-PARSE-CHECK'ed,
+;;; and it ensures the string ends before doing any filling.  This function
+;;; is undo'able.
+;;;
+(defun fill-lisp-string (mark)
+  (with-mark ((end mark))
+    (unless (form-offset end 1)
+      (editor-error "Attempted to fill Lisp string, but it doesn't end?"))
+    (let* ((mark (copy-mark mark :left-inserting))
+	   (end (copy-mark end :left-inserting))
+	   (string-region (region mark end))
+	   (undo-region (copy-region string-region))
+	   (hack (make-empty-region)))
+      ;; Generate prefix.
+      (indent-to-column (region-end hack) (1+ (mark-column mark)))
+      ;; Skip opening double quote and fill string starting on its own line.
+      (mark-after mark)
+      (insert-character mark #\newline)
+      (line-start mark)
+      (setf (mark-kind mark) :right-inserting)
+      (fill-region string-region (region-to-string hack))
+      ;; Clean up inserted prefix on first line, delete inserted newline, and
+      ;; move before the double quote for undo.
+      (with-mark ((text mark :left-inserting))
+	(find-attribute text :whitespace #'zerop)
+	(delete-region (region mark text)))
+      (delete-characters mark -1)
+      (mark-before mark)
+      ;; Save undo.
+      (make-region-undo :twiddle "Fill Lisp Comment Paragraph"
+			string-region undo-region))))
+
+;;; FILL-LISP-COMMENT-OR-INDENTED-TEXT -- Internal.
+;;;
+;;; This fills all contiguous lines around start and end containing fill prefix
+;;; designated by the region between start and end.  These marks can only be
+;;; equal when there is no comment and no initial whitespace.  This is a bad
+;;; situation since this function in that situation would fill the entire
+;;; buffer into one paragraph.  This function is undo'able.
+;;;
+(defun fill-lisp-comment-or-indented-text (start end)
+  (when (mark= start end)
+    (editor-error "This command only fills Lisp comments, strings, or ~
+		   indented text, but this line is flushleft."))
+  ;;
+  ;; Find comment block.
+  (let* ((prefix (region-to-string (region start end)))
+	 (length (length prefix)))
+    (declare (simple-string prefix))
+    (flet ((frob (mark direction)
+	     (loop
+	       (let* ((line (line-string (mark-line mark)))
+		      (line-len (length line)))
+		 (declare (simple-string line))
+		 (unless (string= line prefix :end1 (min line-len length))
+		   (when (= direction -1)
+		     (unless (same-line-p mark end) (line-offset mark 1 0)))
+		   (return)))
+	       (unless (line-offset mark direction 0)
+		 (when (= direction 1) (line-end mark))
+		 (return)))))
+      (frob start -1)
+      (frob end 1))
+    ;;
+    ;; Do it undoable.
+    (let* ((start1 (copy-mark start :right-inserting))
+	   (end2 (copy-mark end :left-inserting))
+	   (region (region start1 end2))
+	   (undo-region (copy-region region)))
+      (fill-region region prefix)
+      (make-region-undo :twiddle "Fill Lisp Comment Paragraph"
+			region undo-region))))
+
+;;; FILL-LISP-COMMENT-PARAGRAPH-PREFIX -- Internal.
+;;;
+;;; This sets start and end around the prefix to be used for filling.  We
+;;; assume we are dealing with a comment.  If there is no ";", then we try to
+;;; find some initial whitespace.  If there is a ";", we make sure the line is
+;;; blank before it to eliminate ";"'s in the middle of a line of text.
+;;; Finally, if we really have a comment instead of some indented text, we skip
+;;; the ";"'s and any immediately following whitespace.  We allow initial
+;;; whitespace, so we can fill strings with the same command.
+;;;
+(defun fill-lisp-comment-paragraph-prefix (start end)
+  (line-start start)
+  (let ((commentp t)) ; Assumes there's a comment.
+    (unless (to-line-comment (line-start end) ";")
+      (find-attribute end :whitespace #'zerop)
+      #|(when (start-line-p end)
+	(editor-error "No comment on line, and no initial whitespace."))|#
+      (setf commentp nil))
+    (when commentp
+      (unless (blank-before-p end)
+	(find-attribute (line-start end) :whitespace #'zerop)
+	#|(when (start-line-p end)
+	  (editor-error "Semicolon preceded by unindented text."))|#
+	(setf commentp nil)))
+    (when commentp
+      (find-attribute end :lisp-syntax #'(lambda (x) (not (eq x :comment))))
+      (find-attribute end :whitespace #'zerop))
+    commentp))
+
+
+
+
+;;;; "Lisp" mode.
+
+(defcommand "LISP Mode" (p)
+  "Put current buffer in LISP mode." 
+  "Put current buffer in LISP mode."  
+  (declare (ignore p))
+  (setf (buffer-major-mode (current-buffer)) "LISP"))
+
+
+(defmode "Lisp" :major-p t :setup-function 'setup-lisp-mode)
+
+
+(defun buffer-first-in-package-form (buffer)
+  "Returns the package name referenced in the first apparent IN-PACKAGE
+   form in buffer, or NIL if it can't find an IN-PACKAGE."
+  (let* ((pattern (new-search-pattern :string-insensitive :forward "in-package" nil))
+         (mark (copy-mark (buffer-start-mark buffer))))
+    (with-mark ((start mark)
+                (end mark))
+      (loop
+        (unless (find-pattern mark pattern)
+          (return))
+        (pre-command-parse-check mark)
+        (when (valid-spot mark t)
+          (move-mark end mark)
+          (when (form-offset end 1)
+            (move-mark start end)
+            (when (backward-up-list start)
+              (when (scan-char start :lisp-syntax :constituent)
+                (let* ((s (nstring-upcase (region-to-string (region start end))))
+                       (*package* (find-package "CL-USER")))
+                  (unless (eq (ignore-errors (values (read-from-string s)))
+                              'in-package)
+                    (return)))
+                (unless (form-offset end 1) (return))
+                (move-mark start end)
+                (form-offset start -1)
+                (let* ((pkgname (ignore-errors (values (read-from-string (region-to-string (region start end)))))))
+                  (return
+                    (if pkgname
+                      (values (ignore-errors (string pkgname))))))))))))))
+
+(defparameter *previous-in-package-search-pattern*
+    (new-search-pattern :string-insensitive :backward "in-package" nil))
+
+(defun package-at-mark (start-mark)
+  (let* ((pattern *previous-in-package-search-pattern*)
+         (mark (copy-mark start-mark :temporary)))
+    (with-mark ((start mark)
+                (end mark)
+                (list-end mark))
+      (loop
+        (unless (find-pattern mark pattern)
+          (return))
+        (pre-command-parse-check mark)
+        (when (valid-spot mark t)
+          (move-mark end mark)
+          (when (form-offset end 1)
+            (move-mark start end)
+            (when (backward-up-list start)
+              (move-mark list-end start)
+              (unless (and (list-offset list-end 1)
+                           (mark<= list-end start-mark))
+                (return))
+              (when (scan-char start :lisp-syntax :constituent)
+                (unless (or (mark= mark start)
+                            (let* ((s (nstring-upcase (region-to-string (region start end))))
+                                   (*package* (find-package "CL-USER")))
+                              (eq (ignore-errors (values (read-from-string s)))
+                                  'in-package)))
+                  (return))
+                (unless (form-offset end 1) (format t "~& worse") (return 4))
+                (move-mark start end)
+                (form-offset start -1)
+                (return
+                  (if (eql (next-character start) #\")
+                    (progn
+                      (character-offset start 1)
+                      (character-offset end -1)
+                      (region-to-string (region start end)))
+                    (let* ((pkgname (ignore-errors (values (read-from-string (region-to-string (region start end)))))))
+                      (if pkgname
+                        (values (ignore-errors (string pkgname)))))))))))))))
+
+(defun ensure-buffer-package (buffer)
+  (or (variable-value 'current-package :buffer buffer)
+      (setf (variable-value 'current-package :buffer buffer)
+            (buffer-first-in-package-form buffer))))
+
+(defun buffer-package (buffer)
+  (when (hemlock-bound-p 'current-package :buffer buffer)
+    (let ((package-name (variable-value 'current-package :buffer buffer)))
+      (find-package package-name))))
+
+(defun setup-lisp-mode (buffer)
+  (unless (hemlock-bound-p 'current-package :buffer buffer)
+    (defhvar "Current Package"
+      "The package used for evaluation of Lisp in this buffer."
+      :buffer buffer
+      :value nil
+      :hooks (list 'package-name-change-hook)))
+  (unless (hemlock-bound-p 'default-package :buffer buffer)
+    (defhvar "Default Package"
+      "The package to use if the current package doesn't exist or isn't set."
+      :buffer buffer
+      :value (package-name *package*))))
+
+
+
+
+
+
+;;;; Some mode variables to coordinate with other stuff.
+
+(defhvar "Auto Fill Space Indent"
+  "When non-nil, uses \"Indent New Comment Line\" to break lines instead of
+   \"New Line\"."
+  :mode "Lisp" :value t)
+
+(defhvar "Comment Start"
+  "String that indicates the start of a comment."
+  :mode "Lisp" :value ";")
+
+(defhvar "Comment Begin"
+  "String that is inserted to begin a comment."
+  :mode "Lisp" :value "; ")
+
+(defhvar "Indent Function"
+  "Indentation function which is invoked by \"Indent\" command.
+   It must take one argument that is the prefix argument."
+  :value 'indent-for-lisp
+  :mode "Lisp")
+
+(defun string-to-arglist (string buffer &optional quiet-if-unknown)
+  (multiple-value-bind (name error)
+      (let* ((*package* (or
+                         (find-package
+                          (variable-value 'current-package :buffer buffer))
+                         *package*)))
+        (ignore-errors (values (read-from-string string))))
+    (unless error
+      (when (typep name 'symbol)
+        (multiple-value-bind (arglist win)
+            (ccl::arglist-string name)
+          (if (or win (not quiet-if-unknown))
+            (format nil "~S : ~A" name (if win (or arglist "()") "(unknown)"))))))))
+
+(defcommand "Current Function Arglist" (p)
+  "Show arglist of function whose name precedes point."
+  "Show arglist of function whose name precedes point."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (with-mark ((mark1 point)
+		(mark2 point))
+      (when (backward-up-list mark1)
+        (when (form-offset (move-mark mark2 (mark-after mark1)) 1)
+          (let* ((fun-name (region-to-string (region mark1 mark2)))
+                 (arglist-string (string-to-arglist fun-name (current-buffer))))
+            (when arglist-string
+              (message "~a" arglist-string))))))))
+
+(defcommand "Arglist On Space" (p)
+  "Insert a space, then show the current function's arglist."
+  "Insert a space, then show the current function's arglist."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (insert-character point #\Space)
+    (pre-command-parse-check point)
+    (with-mark ((mark1 point)
+		(mark2 point))
+      (when (backward-up-list mark1)
+        (when (form-offset (move-mark mark2 (mark-after mark1)) 1)
+          (with-mark ((mark3 mark2))
+            (do* ()
+                 ((mark= mark3 point)
+                  (let* ((fun-name (region-to-string (region mark1 mark2)))
+                         (arglist-string
+                          (string-to-arglist fun-name (current-buffer) t)))
+                    (when arglist-string
+                      (message "~a" arglist-string))))
+              (if (ccl::whitespacep (next-character mark3))
+                (mark-after mark3)
+                (return nil)))))))))
+
+(hi:defcommand "Show Callers" (p)
+  "Display a scrolling list of the callers of the symbol at point.
+   Double-click a row to go to the caller's definition."
+  (declare (ignore p))
+  (with-mark ((mark1 (current-point))
+              (mark2 (current-point)))
+    (mark-symbol mark1 mark2)
+    (with-input-from-region (s (region mark1 mark2))
+      (let* ((symbol (read s)))
+	(hemlock-ext:open-sequence-dialog
+	 :title (format nil "Callers of ~a" symbol)
+	 :sequence (ccl::callers symbol)
+	 :action #'edit-definition)))))
+
+#||
+(defcommand "Set Package Name" (p)
+  (variable-value 'current-package :buffer buffer)
+||#                
Index: /branches/new-random/cocoa-ide/hemlock/src/listener.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/listener.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/listener.lisp	(revision 13309)
@@ -0,0 +1,808 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+;;;
+;;; **********************************************************************
+;;;
+;;; Listener mode, dervived (sort of) from Hemlock's "Eval" mode.
+;;;
+
+(in-package :hemlock)
+
+
+(defmacro in-lisp (&body body)
+  "Evaluates body inside HANDLE-LISP-ERRORS.  *package* is bound to the package
+   named by \"Current Package\" if it is non-nil."
+  (let ((name (gensym)) (package (gensym)))
+    `(handle-lisp-errors
+      (let* ((,name (variable-value 'current-package :buffer (current-buffer)))
+	     (,package (and ,name (find-package ,name))))
+	(progv (if ,package '(*package*)) (if ,package (list ,package))
+	  ,@body)))))
+
+
+(defun package-name-change-hook (name kind where new-value)
+  (declare (ignore name new-value))
+  (if (eq kind :buffer)
+    (hi::note-modeline-change where)))
+
+(define-file-option "Package" (buffer value)
+  (let* ((thing (handler-case (read-from-string value t)
+                  (error () (editor-error "Bad package file option value"))))
+         (name
+          (cond
+           ((or (stringp thing) (symbolp thing))
+            (string thing))
+           ((and (consp thing) ;; e.g. Package: (foo :use bar)
+                 (or (stringp (car thing)) (symbolp (car thing))))
+            (string (car thing)))
+           (t
+            (message "Ignoring \"package:\" file option ~a" thing)
+            nil))))
+    (when name
+      (ignore-errors (let* ((*package* *package*))
+                       (apply 'ccl::old-in-package (if (atom thing) (list thing) thing)))))
+    (defhvar "Current Package"
+      "The package used for evaluation of Lisp in this buffer."
+      :buffer buffer
+      :value (or name (package-name *package*))
+      :hooks (list 'package-name-change-hook))
+    (defhvar "Default Package"
+      "The buffer's default package."
+      :buffer buffer
+      :value (or name (package-name *package*)))))
+      
+
+
+
+;;;; Listener Mode Interaction.
+
+
+
+(defun setup-listener-mode (buffer)
+  (let ((point (buffer-point buffer)))
+    (setf (buffer-minor-mode buffer "Listener") t)
+    (setf (buffer-minor-mode buffer "Editor") t)
+    (setf (buffer-major-mode buffer) "Lisp")
+    (buffer-end point)
+    (defhvar "Current Package"
+      "This variable holds the name of the package currently used for Lisp
+       evaluation and compilation.  If it is Nil, the value of *Package* is used
+       instead."
+      :value nil
+      :buffer buffer)
+    (unless (hemlock-bound-p 'buffer-input-mark :buffer buffer)
+      (defhvar "Buffer Input Mark"
+	"Mark used for Listener Mode input."
+	:buffer buffer
+	:value (copy-mark point :right-inserting))
+      (defhvar "Buffer Output Mark"
+	"Mark used for Listener Mode output."
+	:buffer buffer
+	:value (copy-mark point :left-inserting))
+      (defhvar "Interactive History"
+	"A ring of the regions input to an interactive mode (Eval or Typescript)."
+	:buffer buffer
+	:value (make-ring (value interactive-history-length)))
+      (defhvar "Interactive Pointer"
+	"Pointer into \"Interactive History\"."
+	:buffer buffer
+	:value 0)
+      (defhvar "Searching Interactive Pointer"
+	"Pointer into \"Interactive History\"."
+	:buffer buffer
+	:value 0)
+      (defhvar "Input Regions"
+        "Input region history list."
+        :buffer buffer
+        :value nil)
+      (defhvar "Current Input Font Region"
+          "Current font region, for listener input"
+        :buffer buffer
+        :value nil)
+      (defhvar "Current Output Font Region"
+          "Current font region, for listener output"
+        :buffer buffer
+        :value nil)
+      )
+    (let* ((input-mark (variable-value 'buffer-input-mark :buffer buffer)))
+      (when (hemlock-ext:read-only-listener-p)
+	(setf (hi::buffer-protected-region buffer)
+	      (region (buffer-start-mark buffer) input-mark)))
+      (move-mark input-mark point)
+      (append-font-regions buffer))))
+
+(defmode "Listener" :major-p nil :setup-function #'setup-listener-mode)
+
+(declaim (special hi::*listener-input-style* hi::*listener-output-style*))
+
+(defun append-font-regions (buffer)
+  (let* ((end (region-end (buffer-region buffer))))
+    (setf (variable-value 'current-output-font-region :buffer buffer)
+          (hi::new-font-region buffer end end hi::*listener-output-style*))
+    (let* ((input (hi::new-font-region buffer end end hi::*listener-input-style*)))
+      (hi::activate-buffer-font-region buffer input)
+      (setf (variable-value 'current-input-font-region :buffer buffer) input))))
+
+(defun append-buffer-output (buffer string)
+  (let* ((output-region (variable-value 'current-output-font-region
+                                        :buffer buffer))
+         (output-end (region-end output-region)))
+    (hi::with-active-font-region (buffer output-region)
+      (with-mark ((output-mark output-end :left-inserting))
+        ;(setf (mark-charpos output-mark) 0)
+        (insert-string output-mark string))
+      (move-mark (variable-value 'buffer-input-mark :buffer buffer)
+                 output-end))))
+
+
+
+(defparameter *listener-modeline-fields*
+  (list	(modeline-field :package)
+	(modeline-field :modes)
+	(modeline-field :process-info)))
+  
+(defun listener-mode-lisp-mode-hook (buffer on)
+  "Turn on Lisp mode when we go into Listener Mode."
+  (when on
+    (setf (buffer-major-mode buffer) "Lisp")))
+;;;
+(add-hook listener-mode-hook 'listener-mode-lisp-mode-hook)
+
+
+
+
+
+(defvar lispbuf-eof '(nil))
+
+(defun skip-line-comment (mark)
+  ;; return t if we skipped a comment, nil otherwise
+  (let ((cstart (to-line-comment mark ";")))
+    (if cstart
+        (progn (to-comment-end mark (string #\newline))
+               t)
+        nil)))
+
+(defun balanced-expressions-in-region (region)
+  "Return true if there's at least one syntactically well-formed S-expression
+between the region's start and end, and if there are no ill-formed expressions in that region."
+  ;; It helps to know that END-MARK immediately follows a #\newline.
+  (let* ((start-mark (region-start region))
+         (end-mark (region-end region))
+         (end-line (mark-line end-mark))
+         (end-charpos (mark-charpos end-mark)))
+    (with-mark ((m start-mark))
+      (pre-command-parse-check m)
+      (when (form-offset m 1)
+        (let* ((skip-whitespace t))
+          (loop
+            (let* ((current-line (mark-line m))
+                   (current-charpos (mark-charpos m)))
+              (when (and (eq current-line end-line)
+                         (eql current-charpos end-charpos))
+                (return t))
+              (if skip-whitespace
+                (progn
+                  (scan-char m :whitespace nil)
+                  (setq skip-whitespace nil))
+                (progn
+                  (pre-command-parse-check m)
+                  (unless (or (form-offset m 1)
+                              (skip-line-comment m))
+                    (return nil))
+                  (setq skip-whitespace t))))))))))
+               
+#| old version
+(defcommand "Confirm Listener Input" (p)
+  "Evaluate Listener Mode input between point and last prompt."
+  (declare (ignore p))
+  (let* ((input-region (get-interactive-input))
+         (r (if input-region
+              (region (copy-mark (region-start input-region))
+                      (copy-mark (region-end input-region) :right-inserting)))))
+
+    (when input-region
+      (insert-character (current-point-for-insertion) #\NewLine)
+      (when (or (input-stream-reading-line
+                 (top-listener-input-stream))
+                (balanced-expressions-in-region input-region))
+        (let* ((string (region-to-string input-region)))
+          (push (cons r nil) (value input-regions))
+          (move-mark (value buffer-input-mark) (current-point))
+          (append-font-regions (current-buffer))
+          (hemlock-ext:send-string-to-listener (current-buffer) string))))))
+|#
+
+(defun point-at-prompt-p ()
+  (with-mark ((input-mark (value buffer-input-mark))
+              (end-mark (value buffer-input-mark)))
+    (buffer-end end-mark)
+    (and (mark>= (current-point) input-mark)
+         (mark>= end-mark (current-point)))))
+
+(defun send-input-region-to-lisp ()
+  (let* ((input-mark (value buffer-input-mark))
+         (end-mark (region-end (buffer-region (current-buffer))))
+         (input-region (region input-mark end-mark))
+         (r (if input-region
+                (region (copy-mark (region-start input-region))
+                        (copy-mark (region-end input-region) :right-inserting)))))
+    (when input-region
+      (if (or (input-stream-reading-line
+               (top-listener-input-stream))
+              (balanced-expressions-in-region input-region))
+        ;; complete expression: send it to lisp
+        (let* ((string (region-to-string input-region))
+               (ring (value interactive-history)))
+          (when (and (or (zerop (ring-length ring))
+                         (string/= string (region-to-string (ring-ref ring 0))))
+                     (> (length string) (value minimum-interactive-input-length)))
+            (ring-push (copy-region input-region) ring))
+          (insert-character (region-end input-region) #\NewLine)
+          (push (cons r nil) (value input-regions))
+          (set-charprop-value (region-start input-region) :font-weight :bold
+                              :end (region-end input-region))
+          (move-mark (value buffer-input-mark) (current-point))
+          (append-font-regions (current-buffer))
+          (hemlock-ext:send-string-to-listener (current-buffer) (concatenate 'string string '(#\Newline)))
+          (buffer-end (current-point)))
+        ;; incomplete expression: enter a newline
+        (progn
+          (insert-character (current-point-for-insertion) #\NewLine))))))
+
+(defun copy-region-to-input (region)
+  (let* ((region-string (when region (region-to-string region)))
+         (input-mark (value buffer-input-mark))
+         (end-mark (region-end (buffer-region (current-buffer))))
+         (input-region (region input-mark end-mark)))
+    (with-mark ((input-mark (value buffer-input-mark)))
+      (move-mark (current-point) input-mark)
+      (delete-region input-region)
+      (insert-string (current-point) region-string)
+      (buffer-end (current-point)))))
+
+(defun find-backward-form (mark)
+  (let ((start (copy-mark mark))
+        (end (copy-mark mark)))
+    (block finding
+      (or (form-offset start -1) (return-from finding nil))
+      (or (form-offset end -1) (return-from finding nil))
+      (or (form-offset end 1) (return-from finding nil))
+      (region start end))))
+
+(defun find-forward-form (mark)
+  (let ((start (copy-mark mark))
+        (end (copy-mark mark)))
+    (block finding
+      (or (form-offset start 1) (return-from finding nil))
+      (or (form-offset end 1) (return-from finding nil))
+      (or (form-offset start -1) (return-from finding nil))
+      (region start end))))
+
+(defun region= (r1 r2)
+  (multiple-value-bind (r1-start r1-end)(region-bounds r1)
+    (multiple-value-bind (r2-start r2-end)(region-bounds r2)
+      (and (mark= r1-start r2-start)
+           (mark= r1-end r2-end)))))
+
+;;; find the start or end of the nearest lisp form. return a region if
+;;; one is found, nil otherwise. try for a commonsense result.
+(defun mark-nearest-form (mark)
+  (let* ((backward-region (find-backward-form mark))
+         (forward-region (find-forward-form mark)))
+    (if backward-region
+        (if forward-region
+            ;; if we're in the middle of a token, then the backward
+            ;; and forward regions will be the same
+            (if (region= backward-region forward-region)
+                backward-region
+                ;; not equal, so figure out which is closer
+                (let* ((mark-pos (mark-absolute-position mark))
+                       (backward-dist (abs (- mark-pos (mark-absolute-position (region-end backward-region)))))
+                       (forward-dist (abs (- (mark-absolute-position (region-start forward-region)) mark-pos))))
+                  (if (< forward-dist backward-dist)
+                      forward-region
+                      backward-region)))
+            backward-region)
+        forward-region)))
+
+(defun copy-expression-at-point-to-input ()
+  (let* ((nearest-form-region (mark-nearest-form (current-point))))
+    (if nearest-form-region
+        (copy-region-to-input nearest-form-region)
+        (beep))))
+
+(defcommand "Confirm Listener Input" (p)
+    "Evaluate Listener Mode input between point and last prompt."
+  (declare (ignore p))
+  (if (point-at-prompt-p)
+    (progn
+      (if (eq (character-attribute :lisp-syntax (previous-character (buffer-end-mark (current-buffer)))) :char-quote)
+        (let* ((point (current-point))) 
+          (buffer-end point)
+          (insert-character point #\newline))
+        (send-input-region-to-lisp)))
+      (if (region-active-p)
+          (let ((selected-region (current-region nil nil)))
+            (copy-region-to-input selected-region))
+          (let ((prior-region (input-region-containing-mark (current-point) (value input-regions))))
+            (if prior-region
+                (copy-region-to-input prior-region)
+                (copy-expression-at-point-to-input))))))
+
+
+(defparameter *pop-string* ":POP
+" "what you have to type to exit a break loop")
+
+(defcommand "POP or Delete Forward" (p)
+  "Send :POP if input-mark is at buffer's end, else delete forward character."
+  (let* ((input-mark (value buffer-input-mark))
+         (point (current-point-for-deletion)))
+    (when point
+      (if (and (null (next-character point))
+	       (null (next-character input-mark)))
+        (hemlock-ext:send-string-to-listener (current-buffer) *pop-string*)
+        (delete-next-character-command p)))))
+
+
+
+;;;; General interactive commands used in eval and typescript buffers.
+
+(defhvar "Interactive History Length"
+  "This is the length used for the history ring in interactive buffers.
+   It must be set before turning on the mode."
+  :value 10)
+
+(defun input-region-containing-mark (m history-list)
+  (dolist (pair history-list)
+    (let* ((actual (car pair))
+           (start (region-start actual))
+           (end (region-end actual)))
+      (when (and (mark>= m start)
+                 (mark<= m end))        ; sic: inclusive
+        (return (or (cdr pair) (setf (cdr pair) (copy-region actual))))))))
+
+
+(defun get-interactive-input ()
+  "Tries to return a region.  When the point is not past the input mark, and
+   the user has \"Unwedge Interactive Input Confirm\" set, the buffer is
+   optionally fixed up, and nil is returned.  Otherwise, an editor error is
+   signalled.  When a region is returned, the start is the current buffer's
+   input mark, and the end is the current point moved to the end of the buffer."
+  (let ((point (current-point))
+        (mark (value buffer-input-mark)))
+    (cond
+      ((mark>= point mark)
+       (buffer-end point)
+       (let* ((input-region (region mark point))
+              (string (region-to-string input-region))
+              (ring (value interactive-history)))
+         (when (and (or (zerop (ring-length ring))
+                        (string/= string (region-to-string (ring-ref ring 0))))
+                    (> (length string) (value minimum-interactive-input-length)))
+           (ring-push (copy-region input-region) ring))
+         input-region))
+      (t
+       (let* ((region (input-region-containing-mark point (value input-regions ))))
+         (buffer-end point)
+         (if region
+             (progn
+               (delete-region (region mark point))
+               (insert-region point region))
+             (beep))
+         nil)))))
+
+
+(defhvar "Minimum Interactive Input Length"
+  "When the number of characters in an interactive buffer exceeds this value,
+   it is pushed onto the interactive history, otherwise it is lost forever."
+  :value 2)
+
+
+(defvar *previous-input-search-string* "ignore")
+
+(defvar *previous-input-search-pattern*
+  ;; Give it a bogus string since you can't give it the empty string.
+  (new-search-pattern :string-insensitive :forward "ignore"))
+
+(defun get-previous-input-search-pattern (string)
+  (if (string= *previous-input-search-string* string)
+      *previous-input-search-pattern*
+      (new-search-pattern :string-insensitive :forward 
+			  (setf *previous-input-search-string* string)
+			  *previous-input-search-pattern*)))
+
+(defcommand "Search Previous Interactive Input" (p)
+  "Search backward through the interactive history using the current input as
+   a search string.  Consecutive invocations repeat the previous search."
+  (declare (ignore p))
+  (let* ((mark (value buffer-input-mark))
+	 (ring (value interactive-history))
+	 (point (current-point))
+	 (just-invoked (eq (last-command-type) :searching-interactive-input)))
+    (when (mark<= point mark)
+      (editor-error "Point not past input mark."))
+    (when (zerop (ring-length ring))
+      (editor-error "No previous input in this buffer."))
+    (unless just-invoked
+      (get-previous-input-search-pattern (region-to-string (region mark point))))
+    (let ((found-it (find-previous-input ring just-invoked)))
+      (unless found-it 
+	(editor-error "Couldn't find ~a." *previous-input-search-string*))
+      (delete-region (region mark point))
+      (insert-region point (ring-ref ring found-it))
+      (setf (value searching-interactive-pointer) found-it))
+  (setf (last-command-type) :searching-interactive-input)))
+
+(defun find-previous-input (ring againp)
+  (let ((ring-length (ring-length ring))
+	(base (if againp
+		  (+ (value searching-interactive-pointer) 1)
+		  0)))
+      (loop
+	(when (= base ring-length)
+	  (if againp
+	      (setf base 0)
+	      (return nil)))
+	(with-mark ((m (region-start (ring-ref ring base))))
+	  (when (find-pattern m *previous-input-search-pattern*)
+	    (return base)))
+	(incf base))))
+
+(defcommand "Previous Interactive Input" (p)
+  "Insert the previous input in an interactive mode (Listener or Typescript).
+   If repeated, keep rotating the history.  With prefix argument, rotate
+   that many times."
+  "Pop the *interactive-history* at the point."
+  (let* ((point (current-point))
+	 (mark (value buffer-input-mark))
+	 (ring (value interactive-history))
+	 (length (ring-length ring))
+	 (p (or p 1)))
+    (when (or (mark< point mark) (zerop length)) (editor-error "Can't get command history"))
+    (cond
+     ((eq (last-command-type) :interactive-history)
+      (let ((base (mod (+ (value interactive-pointer) p) length)))
+	(delete-region (region mark point))
+	(insert-region point (ring-ref ring base))
+	(setf (value interactive-pointer) base)))
+     (t
+      (let ((base (mod (if (minusp p) p (1- p)) length))
+	    (region (delete-and-save-region (region mark point))))
+	(insert-region point (ring-ref ring base))
+	(when (mark/= (region-start region) (region-end region))
+	  (ring-push region ring)
+	  (incf base))
+	(setf (value interactive-pointer) base)))))
+  (setf (last-command-type) :interactive-history))
+
+(defcommand "Next Interactive Input" (p)
+  "Rotate the interactive history backwards.  The region is left around the
+   inserted text.  With prefix argument, rotate that many times."
+  (previous-interactive-input-command (- (or p 1))))
+
+(defcommand "Kill Interactive Input" (p)
+  "Kill any input to an interactive mode (Listener or Typescript)."
+  (declare (ignore p))
+  (let ((point (buffer-point (current-buffer)))
+	(mark (value buffer-input-mark)))
+    (when (mark< point mark) (editor-error))
+    (kill-region (region mark point) :kill-backward)))
+
+(defcommand "Interactive Beginning of Line" (p)
+  "If on line with current prompt, go to after it, otherwise do what
+  \"Beginning of Line\" always does."
+  "Go to after prompt when on prompt line."
+  (let ((mark (value buffer-input-mark))
+	(point (current-point)))
+    (if (and (same-line-p point mark) (or (not p) (= p 1)))
+	(move-mark point mark)
+	(beginning-of-line-command p))))
+
+(defcommand "Reenter Interactive Input" (p)
+  "Copies the form to the left of point to be after the interactive buffer's
+   input mark.  When the current region is active, it is copied instead."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'buffer-input-mark)
+    (editor-error "Not in an interactive buffer."))
+  (let ((point (current-point)))
+    (let ((region (if (region-active-p)
+		      ;; Copy this, so moving point doesn't affect the region.
+		      (copy-region (current-region))
+		      (with-mark ((start point)
+				  (end point))
+			(pre-command-parse-check start)
+			(unless (form-offset start -1)
+			  (editor-error "Not after complete form."))
+			(region (copy-mark start) (copy-mark end))))))
+      (buffer-end point)
+      (push-new-buffer-mark point)
+      (insert-region point region)
+      (setf (last-command-type) :ephemerally-active))))
+
+
+
+
+;;; Other stuff.
+
+(defmode "Editor" :hidden t)
+
+(defcommand "Editor Mode" (p)
+  "Toggle \"Editor\" mode in the current buffer.  
+  When in editor mode, most lisp compilation and evaluation commands
+  manipulate the editor process instead of the current eval server."
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Editor")
+	(not (buffer-minor-mode (current-buffer) "Editor"))))
+
+(define-file-option "Editor" (buffer value)
+  (declare (ignore value))
+  (setf (buffer-minor-mode buffer "Editor") t))
+
+
+
+(defun defun-region (mark)
+  "This returns a region around the current or next defun with respect to mark.
+   Mark is not used to form the region.  If there is no appropriate top level
+   form, this signals an editor-error.  This calls PRE-COMMAND-PARSE-CHECK."
+  (with-mark ((start mark)
+	      (end mark))
+    (pre-command-parse-check start)
+    (cond ((not (mark-top-level-form start end))
+	   (editor-error "No current or next top level form."))
+	  (t (region start end)))))
+
+(defun current-form-region (&optional (error t))
+  (if (region-active-p)
+    (current-region)
+    (let ((point (current-point)))
+      (pre-command-parse-check point)
+      (or (form-region-at-mark point)
+          (and error (editor-error "No current expression"))))))
+
+(defun eval-region (region
+		    &key
+		    (package (variable-value 'current-package :buffer (current-buffer)))
+		    (path (buffer-pathname (current-buffer))))
+  (ccl::application-ui-operation ccl:*application*
+                                 :eval-selection
+                                 (list package
+                                       path
+                                       (region-to-string region)
+                                       (mark-absolute-position (region-start region)))))
+
+
+(defcommand "Editor Execute Defun" (p)
+  "Executes the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (region-active-p)
+    (eval-region (current-region))
+    (eval-region (defun-region (current-point)))))
+
+(defcommand "Editor Execute Expression" (p)
+  "Executes the current region in the editor Lisp."
+  (declare (ignore p))
+  (eval-region (current-form-region)))
+
+(defcommand "Editor Re-evaluate Defvar" (p)
+  "Evaluate the current or next top-level form if it is a DEFVAR.  Treat the
+   form as if the variable is not bound."
+  (declare (ignore p))
+  (with-input-from-region (stream (defun-region (current-point)))
+    (clear-echo-area)
+    (in-lisp
+     (let ((form (read stream)))
+       (unless (eq (car form) 'defvar) (editor-error "Not a DEFVAR."))
+       (makunbound (cadr form))
+       (message "Evaluation returned ~S" (eval form))))))
+
+(defun macroexpand-expression (expander)
+  (in-lisp
+   (let* ((region (current-form-region))
+          (expr (with-input-from-region (s region)
+                  (read s))))
+     (let* ((*print-pretty* t)
+            (expansion (funcall expander expr)))
+       (format t "~&~s~&" expansion)))))
+
+(defcommand "Editor Macroexpand-1 Expression" (p)
+  "Show the macroexpansion of the current expression in the null environment.
+   With an argument, use MACROEXPAND instead of MACROEXPAND-1."
+  (macroexpand-expression (if p 'macroexpand 'macroexpand-1)))
+
+(defcommand "Editor Macroexpand Expression" (p)
+  "Show the macroexpansion of the current expression in the null environment.
+   With an argument, use MACROEXPAND-1 instead of MACROEXPAND."
+  (macroexpand-expression (if p 'macroexpand-1 'macroexpand)))
+
+
+(defcommand "Editor Evaluate Expression" (p)
+  "Prompt for an expression to evaluate in the editor Lisp."
+  (declare (ignore p))
+  (in-lisp
+   (multiple-value-call #'message "=> ~@{~#[~;~S~:;~S, ~]~}"
+     (eval (prompt-for-expression
+	    :prompt "Editor Eval: "
+	    :help "Expression to evaluate")))))
+
+(defcommand "Editor Evaluate Buffer" (p)
+  "Evaluates the text in the current buffer in the editor Lisp."
+  (declare (ignore p))
+  (message "Evaluating buffer in the editor ...")
+  (with-input-from-region (stream (buffer-region (current-buffer)))
+    (in-lisp
+     (do ((object (read stream nil lispbuf-eof) 
+                  (read stream nil lispbuf-eof)))
+         ((eq object lispbuf-eof))
+       (eval object)))
+    (message "Evaluation complete.")))
+
+
+
+(defcommand "Editor Compile File" (p)
+  "Prompts for file to compile in the editor Lisp.  Does not compare source
+   and binary write dates.  Does not check any buffer for that file for
+   whether the buffer needs to be saved."
+  (declare (ignore p))
+  (let ((pn (prompt-for-file :default
+			     (buffer-default-pathname (current-buffer))
+			     :prompt "File to compile: ")))
+    (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil))))
+
+
+(defun older-or-non-existent-fasl-p (pathname &optional definitely)
+  (let ((obj-pn (probe-file (compile-file-pathname pathname))))
+    (or definitely
+	(not obj-pn)
+	(< (file-write-date obj-pn) (file-write-date pathname)))))
+
+
+(defcommand "Editor Compile Buffer File" (p)
+  "Compile the file in the current buffer in the editor Lisp if its associated
+   binary file (of type .fasl) is older than the source or doesn't exist.  When
+   the binary file is up to date, the user is asked if the source should be
+   compiled anyway.  When the prefix argument is supplied, compile the file
+   without checking the binary file.  When \"Compile Buffer File Confirm\" is
+   set, this command will ask for confirmation when it otherwise would not."
+  "Compile the file in the current buffer in the editor Lisp if the fasl file
+   isn't up to date.  When p, always do it."
+  (let* ((buf (current-buffer))
+	 (pn (buffer-pathname buf)))
+    (unless pn (editor-error "Buffer has no associated pathname."))
+    (cond ((buffer-modified buf)
+	   (when (or (not (value compile-buffer-file-confirm))
+		     (prompt-for-y-or-n
+		      :default t :default-string "Y"
+		      :prompt (list "Save and compile file ~A? "
+				    (namestring pn))))
+	     (write-buffer-file buf pn)
+	     (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil))))
+	  ((older-or-non-existent-fasl-p pn p)
+	   (when (or (not (value compile-buffer-file-confirm))
+		     (prompt-for-y-or-n
+		      :default t :default-string "Y"
+		      :prompt (list "Compile file ~A? " (namestring pn))))
+	     (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil))))
+	  (t (when (or p
+		       (prompt-for-y-or-n
+			:default t :default-string "Y"
+			:prompt
+			"Fasl file up to date, compile source anyway? "))
+	       (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil)))))))
+
+
+
+
+
+
+
+
+;;;; Lisp documentation stuff.
+
+;;; FUNCTION-TO-DESCRIBE is used in "Editor Describe Function Call" and
+;;; "Describe Function Call".
+;;;
+(defmacro function-to-describe (var error-name)
+  `(cond ((not (symbolp ,var))
+	  (,error-name "~S is not a symbol." ,var))
+         ((special-operator-p ,var) ,var)
+	 ((macro-function ,var))
+	 ((fboundp ,var))
+	 (t
+	  (,error-name "~S is not a function." ,var))))
+
+(defcommand "Editor Describe Function Call" (p)
+  "Describe the most recently typed function name in the editor Lisp."
+  (declare (ignore p))
+  (with-mark ((mark1 (current-point))
+	      (mark2 (current-point)))
+    (pre-command-parse-check mark1)
+    (unless (backward-up-list mark1) (editor-error))
+    (form-offset (move-mark mark2 (mark-after mark1)) 1)
+    (with-input-from-region (s (region mark1 mark2))
+      (in-lisp
+       (let* ((sym (read s))
+	      (fun (function-to-describe sym editor-error)))
+	 (with-pop-up-display (*standard-output* :title (format nil "~s" sym))
+	   (editor-describe-function fun sym)))))))
+
+
+(defcommand "Editor Describe Symbol" (p)
+  "Describe the previous s-expression if it is a symbol in the editor Lisp."
+  (declare (ignore p))
+  (with-mark ((mark1 (current-point))
+	      (mark2 (current-point)))
+    (mark-symbol mark1 mark2)
+    (with-input-from-region (s (region mark1 mark2))
+      (let ((thing (in-lisp (read s))))
+        (if (symbolp thing)
+          (with-pop-up-display (*standard-output* :title (format nil "~s" thing))
+            (describe thing))
+          (if (and (consp thing)
+                   (or (eq (car thing) 'quote)
+                       (eq (car thing) 'function))
+                   (symbolp (cadr thing)))
+            (with-pop-up-display (*standard-output* :title (format nil "~s" (cadr thing)))
+              (describe (cadr thing)))
+            (editor-error "~S is not a symbol, or 'symbol, or #'symbol."
+                          thing)))))))
+
+;;; MARK-SYMBOL moves mark1 and mark2 around the previous or current symbol.
+;;; However, if the marks are immediately before the first constituent char
+;;; of the symbol name, we use the next symbol since the marks probably
+;;; correspond to the point, and Hemlock's cursor display makes it look like
+;;; the point is within the symbol name.  This also tries to ignore :prefix
+;;; characters such as quotes, commas, etc.
+;;;
+(defun mark-symbol (mark1 mark2)
+  (pre-command-parse-check mark1)
+  (with-mark ((tmark1 mark1)
+	      (tmark2 mark1))
+    (cond ((and (form-offset tmark1 1)
+		(form-offset (move-mark tmark2 tmark1) -1)
+		(or (mark= mark1 tmark2)
+		    (and (find-attribute tmark2 :lisp-syntax
+					 #'(lambda (x) (not (eq x :prefix))))
+			 (mark= mark1 tmark2))))
+	   (form-offset mark2 1))
+	  (t
+	   (form-offset mark1 -1)
+	   (find-attribute mark1 :lisp-syntax
+			   #'(lambda (x) (not (eq x :prefix))))
+	   (form-offset (move-mark mark2 mark1) 1)))))
+
+
+(defcommand "Editor Describe" (p)
+  "Call Describe on a Lisp object.
+  Prompt for an expression which is evaluated to yield the object."
+  (declare (ignore p))
+  (in-lisp
+   (let* ((exp (prompt-for-expression
+		:prompt "Object: "
+		:help "Expression to evaluate to get object to describe."))
+	  (obj (eval exp)))
+     (with-pop-up-display (*standard-output* :title (format nil "~s" exp))
+       (describe obj)))))
+
+
+(defcommand "Filter Region" (p)
+  "Apply a Lisp function to each line of the region.
+  An expression is prompted for which should evaluate to a Lisp function
+  from a string to a string.  The function must neither modify its argument
+  nor modify the return value after it is returned."
+  "Call prompt for a function, then call Filter-Region with it and the region."
+  (declare (ignore p))
+  (let* ((exp (prompt-for-expression
+	       :prompt "Function: "
+	       :help "Expression to evaluate to get function to use as filter."))
+	 (fun (in-lisp (eval exp)))
+	 (region (current-region)))
+    (let* ((start (copy-mark (region-start region) :left-inserting))
+	   (end (copy-mark (region-end region) :left-inserting))
+	   (region (region start end))
+	   (undo-region (copy-region region)))
+      (filter-region fun region)
+      (make-region-undo :twiddle "Filter Region" region undo-region))))
Index: /branches/new-random/cocoa-ide/hemlock/src/macros.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/macros.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/macros.lisp	(revision 13309)
@@ -0,0 +1,573 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains most of the junk that needs to be in the compiler
+;;; to compile Hemlock commands.
+;;;
+;;; Written by Rob MacLachlin and Bill Chiles.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Macros used for manipulating Hemlock variables.
+
+(defmacro invoke-hook (place &rest args)
+  "Call the functions in place with args.  If place is a symbol, then this
+   interprets it as a Hemlock variable rather than a Lisp variable, using its
+   current value as the list of functions."
+  (let ((f (gensym)))
+    `(dolist (,f ,(if (symbolp place) `(%value ',place) place))
+       (funcall ,f ,@args))))
+
+(defmacro value (name)
+  "Return the current value of the Hemlock variable name."
+  `(%value ',name))
+
+(defmacro setv (name new-value)
+  "Set the current value of the Hemlock variable name, calling any hook
+   functions with new-value before setting the value."
+  `(%set-value ',name ,new-value))
+
+;;; WITH-VARIABLE-OBJECT  --  Internal
+;;;
+;;;    Look up the variable object for name and bind it to obj, giving error
+;;; if there is no such variable.
+;;;
+(defmacro with-variable-object (name &body forms)
+  `(let ((obj (get-variable-object ,name :current)))
+     (unless obj (undefined-variable-error ,name))
+     ,@forms))
+
+(defmacro hlet (binds &rest forms)
+  "Hlet ({Var Value}*) {Form}*
+   Similar to Let, only it creates temporary Hemlock variable bindings.  Each
+   of the vars have the corresponding value during the evaluation of the
+   forms."
+  (let ((lets ())
+	(sets ())
+	(unsets ()))
+    (dolist (bind binds)
+      (let ((n-obj (gensym))
+	    (n-val (gensym))
+	    (n-old (gensym)))
+	(push `(,n-val ,(second bind)) lets)
+	(push `(,n-old (variable-object-value ,n-obj)) lets)
+	(push `(,n-obj (with-variable-object ',(first bind) obj)) lets)
+	(push `(setf (variable-object-value ,n-obj) ,n-val) sets)
+	(push `(setf (variable-object-value ,n-obj) ,n-old) unsets)))
+    `(let* ,lets
+       (unwind-protect
+	 (progn ,@sets nil ,@forms)
+	 ,@unsets))))
+
+
+;; MODIFYING-BUFFER-STORAGE
+;;
+;; This is kinda Cocoa-specific, but we'll pretend it's not. It gets wrapped around
+;; possible multiple modifications of the buffer's text, so that the OS can defer
+;; layout and redisplay until the end.  It takes care of showing the spin cursor
+;; if the command takes too long, and it ensures that the cocoa selection matches
+;; hemlock's idea of selection.
+;; As a special hack, buffer can be NIL to temporarily turn off the grouping.
+
+(defmacro modifying-buffer-storage ((buffer) &body body)
+  (if (eq buffer '*current-buffer*)
+    `(hemlock-ext:invoke-modifying-buffer-storage *current-buffer* #'(lambda () ,@body))
+    `(let ((*current-buffer* ,buffer))
+       (hemlock-ext:invoke-modifying-buffer-storage *current-buffer* #'(lambda () ,@body)))))
+
+;; If we've done a (cocoa-specific) "beginEditing" on a buffer, finish that (to allow
+;; layout, etc.)  Call thunk, and maybe restore the editing state after.
+(defmacro allowing-buffer-display ((buffer) &body body)
+  `(hemlock-ext:invoke-allowing-buffer-display ,buffer (lambda () ,@body)))
+
+
+;;;; A couple funs to hack strings to symbols.
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+
+(defun bash-string-to-symbol (name suffix)
+  (intern (nsubstitute #\- #\space
+		       #-scl
+		       (nstring-upcase
+			(concatenate 'simple-string
+				     name (symbol-name suffix)))
+		       #+scl
+		       (let ((base (concatenate 'simple-string
+						name (symbol-name suffix))))
+			 (if (eq ext:*case-mode* :upper)
+			     (nstring-upcase base)
+			     (nstring-downcase base))))))
+
+;;; string-to-variable  --  Exported
+;;;
+;;;    Return the symbol which corresponds to the string name
+;;; "string".
+(defun string-to-variable (string)
+  "Returns the symbol name of a Hemlock variable from the corresponding string
+   name."
+  (intern (nsubstitute #\- #\space
+		       #-scl
+		       (the simple-string (string-upcase string))
+		       #+scl
+		       (if (eq ext:*case-mode* :upper)
+			   (string-upcase string)
+			   (string-downcase string)))
+	  (find-package :hemlock)))
+
+); eval-when
+
+;;; string-to-keyword  --  Internal
+;;;
+;;;    Mash a string into a Keyword.
+;;;
+(defun string-to-keyword (string)
+  (intern (nsubstitute #\- #\space
+		       #-scl
+		       (the simple-string (string-upcase string))
+		       #+scl
+		       (if (eq ext:*case-mode* :upper)
+			   (string-upcase string)
+			   (string-downcase string)))
+	  (find-package :keyword)))
+
+
+
+;;;; Macros to add and delete hook functions.
+
+;;; add-hook  --  Exported
+;;;
+;;;    Add a hook function to a hook, defining a variable if
+;;; necessary.
+;;;
+(defmacro add-hook (place hook-fun)
+  "Add-Hook Place Hook-Fun
+  Add Hook-Fun to the list stored in Place.  If place is a symbol then it
+  it is interpreted as a Hemlock variable rather than a Lisp variable."
+  (if (symbolp place)
+      `(pushnew ,hook-fun (value ,place))
+      `(pushnew ,hook-fun ,place)))
+
+;;; remove-hook  --  Public
+;;;
+;;;    Delete a hook-function from somewhere.
+;;;
+(defmacro remove-hook (place hook-fun)
+  "Remove-Hook Place Hook-Fun
+  Remove Hook-Fun from the list in Place.  If place is a symbol then it
+  it is interpreted as a Hemlock variable rather than a Lisp variable."
+  (if (symbolp place)
+      `(setf (value ,place) (delete ,hook-fun (value ,place)))
+      `(setf ,place (delete ,hook-fun ,place))))
+
+
+
+
+;;;; DEFCOMMAND.
+
+;;; Defcommand  --  Public
+;;;
+(defmacro defcommand (name lambda-list command-doc function-doc
+			   &body forms)
+  "Defcommand Name Lambda-List Command-Doc [Function-Doc] {Declaration}* {Form}*
+
+  Define a new Hemlock command named Name.  Lambda-List becomes the
+  lambda-list, Function-Doc the documentation, and the Forms the
+  body of the function which implements the command.  The first
+  argument, which must be present, is the prefix argument.  The name
+  of this function is derived by replacing all spaces in the name with
+  hyphens and appending \"-COMMAND\".  Command-Doc becomes the
+  documentation for the command.  See the command implementor's manual
+  for further details.
+
+  An example:
+    (defcommand \"Forward Character\" (p)
+      \"Move the point forward one character.
+       With prefix argument move that many characters, with negative argument
+       go backwards.\"
+      \"Move the point of the current buffer forward p characters.\"
+      (unless (character-offset (buffer-point (current-buffer)) (or p 1))
+        (editor-error)))"
+
+  (unless (stringp function-doc)
+    (setq forms (cons function-doc forms))
+    (setq function-doc command-doc))
+  (when (atom lambda-list)
+    (error "Command argument list is not a list: ~S." lambda-list))
+  (let (command-name function-name extra-args)
+    (cond ((listp name)
+	   (setq command-name (car name) function-name (cadr name))
+	   (unless (symbolp function-name)
+	     (error "Function name is not a symbol: ~S" function-name))
+	   (if (keywordp function-name)
+	     (setq function-name nil extra-args (cdr name))
+	     (setq extra-args (cddr name))))
+	  (t
+	   (setq command-name name)))
+    (when (null function-name)
+      (setq function-name (bash-string-to-symbol command-name '-command)))
+    (unless (stringp command-name)
+      (error "Command name is not a string: ~S." name))
+    `(eval-when (:load-toplevel :execute)
+       (defun ,function-name ,lambda-list ,function-doc
+              ,@forms)
+       (make-command ,command-name ,command-doc ',function-name ,@extra-args)
+       ',function-name)))
+
+
+
+
+;;;; PARSE-FORMS
+
+;;; Parse-Forms  --  Internal
+;;;
+;;;    Used for various macros to get the declarations out of a list of
+;;; forms.
+;;;
+(eval-when (:compile-toplevel :execute :load-toplevel)
+(defmacro parse-forms ((decls-var forms-var forms) &body gorms)
+  "Parse-Forms (Decls-Var Forms-Var Forms) {Form}*
+  Binds Decls-Var to leading declarations off of Forms and Forms-Var
+  to what is left."
+  `(do ((,forms-var ,forms (cdr ,forms-var))
+	(,decls-var ()))
+       ((or (atom ,forms-var) (atom (car ,forms-var))
+	    (not (eq (caar ,forms-var) 'declare)))
+	,@gorms)
+     (push (car ,forms-var) ,decls-var)))
+)
+
+
+
+
+;;;; WITH-MARK and USE-BUFFER.
+
+(defmacro with-mark (mark-bindings &rest forms)
+  "With-Mark ({(Mark Pos [Kind])}*) {declaration}* {form}*
+  With-Mark binds a variable named Mark to a mark specified by Pos.  This
+  mark is :temporary, or of kind Kind.  The forms are then evaluated."
+  (do ((bindings mark-bindings (cdr bindings))
+       (let-slots ())
+       (cleanup ()))
+      ((null bindings)
+       (if cleanup
+	   (parse-forms (decls forms forms)
+	     `(let ,(nreverse let-slots)
+		,@decls
+		(unwind-protect
+		  (progn ,@forms)
+		  ,@cleanup)))
+	   `(let ,(nreverse let-slots) ,@forms)))
+    (let ((name (caar bindings))
+	  (pos (cadar bindings))
+	  (type (or (caddar bindings) :temporary)))
+      (cond ((not (eq type :temporary))
+	     (push `(,name (copy-mark ,pos ,type)) let-slots)
+	     (push `(delete-mark ,name) cleanup))
+	    (t
+	     (push `(,name (copy-mark ,pos :temporary)) let-slots))))))
+
+#||SAve this shit in case we want WITH-MARKto no longer cons marks.
+(defconstant with-mark-total 50)
+(defvar *with-mark-free-marks* (make-array with-mark-total))
+(defvar *with-mark-next* 0)
+
+(defmacro with-mark (mark-bindings &rest forms)
+  "WITH-MARK ({(Mark Pos [Kind])}*) {declaration}* {form}*
+   WITH-MARK evaluates each form with each Mark variable bound to a mark
+   specified by the respective Pos, a mark.  The created marks are of kind
+   :temporary, or of kind Kind."
+  (do ((bindings mark-bindings (cdr bindings))
+       (let-slots ())
+       (cleanup ()))
+      ((null bindings)
+       (let ((old-next (gensym)))
+	 (parse-forms (decls forms forms)
+	   `(let ((*with-mark-next* *with-mark-next*)
+		  (,old-next *with-mark-next*))
+	      (let ,(nreverse let-slots)
+		,@decls
+		(unwind-protect
+		    (progn ,@forms)
+		  ,@cleanup))))))
+       (let ((name (caar bindings))
+	     (pos (cadar bindings))
+	     (type (or (caddar bindings) :temporary)))
+	 (push `(,name (mark-for-with-mark ,pos ,type)) let-slots)
+	 (if (eq type :temporary)
+	     (push `(delete-mark ,name) cleanup)
+	     ;; Assume mark is on free list and drop its hold on data.
+	     (push `(setf (mark-line ,name) nil) cleanup)))))
+
+;;; MARK-FOR-WITH-MARK -- Internal.
+;;;
+;;; At run time of a WITH-MARK form, this returns an appropriate mark at the
+;;; position mark of type kind.  First it uses one from the vector of free
+;;; marks, possibly storing one in the vector if we need more marks than we
+;;; have before, and that need is still less than the total free marks we are
+;;; willing to hold onto.  If we're over the free limit, just make one for
+;;; throwing away.
+;;;
+(defun mark-for-with-mark (mark kind)
+  (let* ((line (mark-line mark))
+	 (charpos (mark-charpos mark))
+	 (mark (cond ((< *with-mark-next* with-mark-total)
+		      (let ((m (svref *with-mark-free-marks* *with-mark-next*)))
+			(cond ((markp m)
+			       (setf (mark-line m) line)
+			       (setf (mark-charpos m) charpos)
+			       (setf (mark-%kind m) kind))
+			      (t
+			       (setf m (internal-make-mark line charpos kind))
+			       (setf (svref *with-mark-free-marks*
+					    *with-mark-next*)
+				     m)))
+			(incf *with-mark-next*)
+			m))
+		     (t (internal-make-mark line charpos kind)))))
+    (unless (eq kind :temporary)
+      (push mark (line-marks (mark-line mark))))
+    mark))
+||#
+
+
+;;;; EDITOR-ERROR.
+
+(defun editor-error (&rest args)
+  "This function is called to signal minor errors within Hemlock;
+   these are errors that a normal user could encounter in the course of editing
+   such as a search failing or an attempt to delete past the end of the buffer."
+  (if (current-view nil)
+    (let ((message (and args (apply #'format nil args))))
+      (abort-current-command message))
+    (apply #'error args)))
+
+
+;;;; Do-Strings
+
+(defmacro do-strings ((string-var value-var table &optional result) &body forms)
+  "Do-Strings (String-Var Value-Var Table [Result]) {declaration}* {form}*
+  Iterate over the strings in a String Table.  String-Var and Value-Var
+  are bound to the string and value respectively of each successive entry
+  in the string-table Table in alphabetical order.  If supplied, Result is
+  a form to evaluate to get the return value."
+  (let ((value-nodes (gensym))
+	(num-nodes (gensym))
+	(value-node (gensym))
+	(i (gensym)))
+    `(let ((,value-nodes (string-table-value-nodes ,table))
+	   (,num-nodes (string-table-num-nodes ,table)))
+       (dotimes (,i ,num-nodes ,result)
+	 (declare (fixnum ,i))
+	 (let* ((,value-node (svref ,value-nodes ,i))
+		(,value-var (value-node-value ,value-node))
+		(,string-var (value-node-proper ,value-node)))
+	   (declare (simple-string ,string-var))
+	   ,@forms)))))
+
+
+
+
+;;;; COMMAND-CASE
+
+;;; COMMAND-CASE  --  Public
+;;;
+;;;    Grovel the awful thing and spit out the corresponding Cond.  See Echo
+;;; for the definition of COMMAND-CASE-HELP and logical char stuff.
+;;;
+(eval-when (:compile-toplevel :execute :load-toplevel)
+(defun command-case-tag (tag key-event char)
+  (cond ((and (characterp tag) (standard-char-p tag))
+	 `(and ,char (char= ,char ,tag)))
+	((and (symbolp tag) (keywordp tag))
+	 `(logical-key-event-p ,key-event ,tag))
+	(t
+	 (error "Tag in COMMAND-CASE is not a standard character or keyword: ~S"
+		tag))))
+); eval-when
+;;;  
+(defmacro command-case ((&key (prompt "Command character: ")
+			      (help "Choose one of the following characters:")
+			      (bind (gensym)))
+			&body forms)
+  "This is analogous to the Common Lisp CASE macro.  Commands can use this
+   to get a key-event, translate it to a character, and then to dispatch on
+   the character to the specified case.  The syntax is
+   as follows:
+      (COMMAND-CASE ( {key value}* )
+        {( {( {tag}* )  |  tag}  help  {form}* )}*
+        )
+   Each tag is either a character or a logical key-event.  The user's typed
+   key-event is compared using either LOGICAL-KEY-EVENT-P or CHAR= of
+   KEY-EVENT-CHAR.
+
+   The legal keys of the key/value pairs are :help, :prompt, and :bind."
+  (do* ((forms forms (cdr forms))
+	(form (car forms) (car forms))
+	(cases ())
+	(bname (gensym))
+	(again (gensym))
+	(n-prompt (gensym))
+	(bind-char (gensym))
+	(docs ())
+	(t-case `(t (beep) (reprompt))))
+       ((atom forms)
+	`(macrolet ((reprompt ()
+		      `(progn
+			 (setf ,',bind
+			       (prompt-for-key-event :prompt ,',n-prompt))
+			 (setf ,',bind-char (key-event-char ,',bind))
+			 (go ,',again))))
+	   (block ,bname
+	     (let* ((,n-prompt ,prompt)
+		    (,bind (prompt-for-key-event :prompt ,n-prompt))
+		    (,bind-char (key-event-char ,bind)))
+	       (declare (ignorable,bind ,bind-char))
+	       (tagbody
+		,again
+		(return-from
+		 ,bname
+		 (cond ,@(nreverse cases)
+		       ((logical-key-event-p ,bind :abort)
+			(editor-error))
+		       ((logical-key-event-p ,bind :help)
+			(command-case-help ,help ',(nreverse docs))
+			(reprompt))
+		       ,t-case)))))))
+    
+    (cond ((atom form)
+	   (error "Malformed Command-Case clause: ~S" form))
+	  ((eq (car form) t)
+	   (setq t-case form))
+	  ((or (< (length form) 2)
+	       (not (stringp (second form))))
+	   (error "Malformed Command-Case clause: ~S" form))
+	  (t
+	   (let ((tag (car form))
+		 (rest (cddr form)))
+	     (cond ((atom tag)
+		    (push (cons (command-case-tag tag bind bind-char) rest)
+			  cases)
+		    (setq tag (list tag)))
+		   (t
+		    (do ((tag tag (cdr tag))
+			 (res ()
+			      (cons (command-case-tag (car tag) bind bind-char)
+				    res)))
+			((null tag)
+			 (push `((or ,@res) . ,rest) cases)))))
+	     (push (cons tag (second form)) docs))))))
+
+    
+
+
+;;;; Some random macros used everywhere.
+
+(defmacro strlen (str) `(length (the simple-string ,str)))
+(defmacro neq (a b) `(not (eq ,a ,b)))
+
+
+
+
+;;;; Stuff from here on is implementation dependant.
+
+(defvar *saved-standard-output* nil)
+
+(defmacro with-output-to-listener (&body body)
+  `(let* ((*saved-standard-output* (or *saved-standard-output* *standard-output*))
+	  (*standard-output* (hemlock-ext:top-listener-output-stream)))	  
+     ,@body))
+
+(defmacro with-standard-standard-output (&body body)
+  `(let* ((*standard-output* (or *saved-standard-output* *standard-output*)))
+     ,@body))
+
+
+
+
+;;;; WITH-INPUT & WITH-OUTPUT macros.
+
+(defvar *free-hemlock-output-streams* ()
+  "This variable contains a list of free Hemlock output streams.")
+
+(defmacro with-output-to-mark ((var mark &optional (buffered ':line))
+			       &body gorms)
+  "With-Output-To-Mark (Var Mark [Buffered]) {Declaration}* {Form}*
+  During the evaluation of Forms, Var is bound to a stream which inserts
+  output at the permanent mark Mark.  Buffered is the same as for
+  Make-Hemlock-Output-Stream."
+  (parse-forms (decls forms gorms)
+    `(let ((,var (pop *free-hemlock-output-streams*)))
+       ,@decls
+       (if ,var
+	   (modify-hemlock-output-stream ,var ,mark ,buffered)
+	   (setq ,var (make-hemlock-output-stream ,mark ,buffered)))
+       (unwind-protect
+	 (progn ,@forms)
+	 (setf (hemlock-output-stream-mark ,var) nil)
+	 (push ,var *free-hemlock-output-streams*)))))
+
+(defvar *free-hemlock-region-streams* ()
+  "This variable contains a list of free Hemlock input streams.")
+
+(defmacro with-input-from-region ((var region) &body gorms)
+  "With-Input-From-Region (Var Region) {Declaration}* {Form}*
+  During the evaluation of Forms, Var is bound to a stream which
+  returns input from Region."
+  (parse-forms (decls forms gorms)
+    `(let ((,var (pop *free-hemlock-region-streams*)))
+       ,@decls
+       (if ,var
+	   (setq ,var (modify-hemlock-region-stream ,var ,region))
+	   (setq ,var (make-hemlock-region-stream ,region)))
+       (unwind-protect
+	 (progn ,@forms)
+	 (delete-mark (hemlock-region-stream-mark ,var))
+	 (push ,var *free-hemlock-region-streams*)))))
+
+
+
+(defmacro with-pop-up-display ((var &key height title)
+			       &body body)
+
+  "Execute body in a context with var bound to a stream.  Output to the stream
+   appears in the buffer named buffer-name.  The pop-up display appears after
+   the body completes, but if you supply :height, the output is line buffered,
+   displaying any current output after each line."
+  (when (and (numberp height) (zerop height))
+    (editor-error "I doubt that you really want a window with no height"))
+  (let ((stream (gensym)))
+    `(let ()
+       (let ((,stream (gui::typeout-stream ,title)))
+         (clear-output ,stream)
+       (unwind-protect
+	   (progn
+	     (catch 'more-punt
+	       (let ((,var ,stream))
+                 ,@body)))
+         (force-output ,stream))))))
+
+
+(declaim (special *random-typeout-ml-fields* *buffer-names*))
+
+
+
+;;;; Error handling stuff.
+
+(defmacro handle-lisp-errors (&body body)
+  "Handle-Lisp-Errors {Form}*
+  If a Lisp error happens during the evaluation of the body, then it is
+  handled in some fashion.  This should be used by commands which may
+  get a Lisp error due to some action of the user."
+  `(handler-bind ((error #'lisp-error-error-handler))
+     ,@body))
Index: /branches/new-random/cocoa-ide/hemlock/src/main.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/main.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/main.lisp	(revision 13309)
@@ -0,0 +1,222 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock initialization code and random debugging stuff.
+;;;
+;;; Written by Bill Chiles and Rob MacLachlan
+;;;
+
+(in-package :hemlock-internals)
+
+;;;; Definition of *hemlock-version*.
+
+(defvar *hemlock-version* "3.5")
+(pushnew :hemlock *features*)
+#+(or CMU scl)
+(setf (getf ext:*herald-items* :hemlock) 
+      `("    Hemlock " ,*hemlock-version*))
+
+
+
+;;;; %INIT-HEMLOCK.
+
+(defvar *hemlock-initialized* nil)
+
+(defun %init-hemlock ()
+  "Initialize hemlock's internal data structures."
+  (let ((*current-buffer* nil)) ;; don't set it globally
+    ;;
+    ;; This function is defined in Buffer.Lisp.  It creates fundamental mode
+    ;; and the buffer main.  Until this is done it is not possible to define
+    ;; or use Hemlock variables.
+    (setup-initial-buffer)
+    ;;
+    ;; Define some of the system variables.
+    (define-some-variables)
+    ;;
+    ;; Site initializations such as window system variables.
+    (site-init)
+    ;;
+    ;; Set up syntax table data structures.
+    (%init-syntax-table)
+    ;;
+    (setq *hemlock-initialized* t)))
+
+
+
+;;;; Define some globals.
+
+;;; These globals cannot be defined in the appropriate file due to compilation
+;;; or load time constraints.
+;;;
+
+;;; The following belong in other files, but those files are loaded before
+;;; table.lisp which defines MAKE-STRING-TABLE.
+;;;
+;;; vars.lisp
+(defvar *global-variable-names* (make-string-table)
+  "A String Table of global variable names, the values are the symbol names.") 
+;;;
+;;; buffer.lisp
+(defvar *mode-names* (make-string-table) "A String Table of Mode names.")
+(defvar *buffer-names* (make-string-table)
+  "A String Table of Buffer names and their corresponding objects.")
+;;;
+;;; interp.lisp
+(defvar *command-names* (make-string-table) "String table of command names.")
+;;;
+;;; syntax.lisp
+(defvar *character-attribute-names* (make-string-table)
+ "String Table of character attribute names and their corresponding keywords.")
+
+
+
+
+;;;; DEFINE-SOME-VARIABLES.
+
+(defun define-some-variables ()
+  (defhvar "Default Modes"
+    "This variable contains the default list of modes for new buffers."
+    :value '("Fundamental"))
+  (defhvar "Make Buffer Hook"
+    "This hook is called with the new buffer whenever a buffer is created.")
+  (defhvar "Delete Buffer Hook"
+    "This hook is called with the buffer whenever a buffer is deleted.")
+  (defhvar "Buffer Major Mode Hook"
+    "This hook is called with the buffer and the new mode when a buffer's
+     major mode is changed.")
+  (defhvar "Buffer Minor Mode Hook"
+    "This hook is called a minor mode is changed.  The arguments are 
+     the buffer, the mode affected and T or NIL depending on when the
+     mode is being turned on or off.")
+  (defhvar "Buffer Writable Hook"
+    "This hook is called whenever someone sets whether the buffer is
+     writable.")
+  (defhvar "Buffer Name Hook"
+    "This hook is called with the buffer and the new name when the name of a
+     buffer is changed.")
+  (defhvar "Buffer Pathname Hook"
+    "This hook is called with the buffer and the new Pathname when the Pathname
+     associated with the buffer is changed.")
+  (defhvar "Buffer Modified Hook"
+    "This hook is called whenever a buffer changes from unmodified to modified
+     and vice versa.  It takes the buffer and the new value for modification
+     flag.")
+  (defhvar "Buffer Package Hook"
+      "This hook is called with the new package name whenever a (Lisp) buffer's package changes")
+  (defhvar "Delete Variable Hook"
+    "This hook is called when a variable is deleted with the args to
+     delete-variable.")
+  (defhvar "Key Echo Delay"
+    "Wait this many seconds before echoing keys in the command loop.  This
+     feature is inhibited when nil."
+    :value 1.0)
+  (defhvar "Input Hook"
+    "The functions in this variable are invoked each time a character enters
+     Hemlock."
+    :value nil)
+  (defhvar "Abort Hook"
+    "These functions are invoked when ^G is typed.  No arguments are passed."
+    :value nil)
+  (defhvar "Command Abort Hook"
+    "These functions get called when commands are aborted, such as with
+     EDITOR-ERROR."
+    :value nil)
+  (defhvar "Character Attribute Hook"
+    "This hook is called with the attribute, character and new value
+     when the value of a character attribute is changed.")
+  (defhvar "Shadow Attribute Hook"
+    "This hook is called when a mode character attribute is made.")
+  (defhvar "Unshadow Attribute Hook"
+    "This hook is called when a mode character attribute is deleted.")
+  (defhvar "Default Modeline Fields"
+    "The default list of modeline-fields for MAKE-BUFFER."
+    :value *default-modeline-fields*)
+  (defhvar "Maximum Modeline Pathname Length"
+    "When set, this variable is the maximum length of the display of a pathname
+     in a modeline.  When the pathname is too long, the :buffer-pathname
+     modeline-field function chops off leading directory specifications until
+     the pathname fits.  \"...\" indicates a truncated pathname."
+    :value nil
+    :hooks (list 'maximum-modeline-pathname-length-hook))
+  (defhvar "Self Insert Command Name"
+    "The name of the command to invoke to handle quoted input (i.e. after c-q).
+     By default, this is \"Self Insert\"."
+    :value "Self Insert")
+  (defhvar "Default Command Name"
+    "The name of the command to invoke to handle keys that have no binding
+     defined.  By default, this is \"Illegal\"."
+    :value "Illegal")
+  )
+
+
+
+
+;;;; ED.
+
+(defvar *editor-has-been-entered* ()
+  "True if and only if the editor has been entered.")
+(defvar *in-the-editor* ()
+  "True if we are inside the editor.  This is used to prevent ill-advised
+   \"recursive\" edits.")
+
+(defvar *after-editor-initializations-funs* nil
+  "A list of functions to be called after the editor has been initialized upon
+   entering the first time.")
+
+(defmacro after-editor-initializations (&rest forms)
+  "Causes forms to be executed after the editor has been initialized.
+   Forms supplied with successive uses of this macro will be executed after
+   forms supplied with previous uses."
+  `(push #'(lambda () ,@forms)
+	 *after-editor-initializations-funs*))
+
+;;;; SAVE-ALL-BUFFERS.
+
+;;; SAVE-ALL-BUFFERS -- Public.
+;;;
+(defun save-all-buffers (&optional (list-unmodified-buffers nil))
+  "This prompts users with each modified buffer as to whether they want to
+   write it out.  If the buffer has no associated file, this will also prompt
+   for a file name.  Supplying the optional argument non-nil causes this
+   to prompt for every buffer."
+  (dolist (buffer *buffer-list*)
+    (when (or list-unmodified-buffers (buffer-modified buffer))
+      (maybe-save-buffer buffer))))
+
+(defun maybe-save-buffer (buffer)
+  (let* ((modified (buffer-modified buffer))
+	 (pathname (buffer-pathname buffer))
+	 (name (buffer-name buffer))
+	 (string (if pathname (namestring pathname))))
+    (format t "Buffer ~S is ~:[UNmodified~;modified~], Save it? "
+	    name modified)
+    (force-output)
+    (when (y-or-n-p)
+      (let ((name (read-line-default "File to write" string)))
+	(format t "Writing file ~A..." name)
+	(force-output)
+	(write-file (buffer-region buffer) name)
+	(write-line "write WON")))))
+
+(defun read-line-default (prompt default)
+  (format t "~A:~@[ [~A]~] " prompt default)
+  (force-output)
+  (do ((result (read-line) (read-line)))
+      (())
+    (declare (simple-string result))
+    (when (plusp (length result)) (return result))
+    (when default (return default))
+    (format t "~A:~@[ [~A]~] " prompt default)
+    (force-output)))
+
+(unless *hemlock-initialized*
+  (%init-hemlock))
Index: /branches/new-random/cocoa-ide/hemlock/src/modeline.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/modeline.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/modeline.lisp	(revision 13309)
@@ -0,0 +1,232 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+
+(in-package :hemlock-internals)
+
+
+;;;; Modelines-field structure support.
+
+(defun print-modeline-field (obj stream ignore)
+  (declare (ignore ignore))
+  (write-string "#<Hemlock Modeline-field " stream)
+  (prin1 (modeline-field-%name obj) stream)
+  (write-string ">" stream))
+
+(defun print-modeline-field-info (obj stream ignore)
+  (declare (ignore ignore))
+  (write-string "#<Hemlock Modeline-field-info " stream)
+  (prin1 (modeline-field-%name (ml-field-info-field obj)) stream)
+  (write-string ">" stream))
+
+
+(defvar *modeline-field-names* (make-hash-table))
+
+(defun make-modeline-field (&key name width function)
+  "Returns a modeline-field object."
+  (unless (or (eq width nil) (and (integerp width) (plusp width)))
+    (error "Width must be nil or a positive integer."))
+  (when (gethash name *modeline-field-names*)
+    (with-simple-restart (continue
+			  "Use the new definition for this modeline field.")
+      (error "Modeline field ~S already exists."
+	     (gethash name *modeline-field-names*))))
+  (setf (gethash name *modeline-field-names*)
+	(%make-modeline-field name function width)))
+
+(defun modeline-field (name)
+  "Returns the modeline-field object named name.  If none exists, return nil."
+  (gethash name *modeline-field-names*))
+
+
+(declaim (inline modeline-field-name modeline-field-width modeline-field-function))
+
+(defun modeline-field-name (ml-field)
+  "Returns the name of a modeline field object."
+  (modeline-field-%name ml-field))
+
+(defun %set-modeline-field-name (ml-field name)
+  (check-type ml-field modeline-field)
+  (when (gethash name *modeline-field-names*)
+    (error "Modeline field ~S already exists."
+	   (gethash name *modeline-field-names*)))
+  (remhash (modeline-field-%name ml-field) *modeline-field-names*)
+  (setf (modeline-field-%name ml-field) name)
+  (setf (gethash name *modeline-field-names*) ml-field))
+
+(defun modeline-field-width (ml-field)
+  "Returns the width of a modeline field."
+  (modeline-field-%width ml-field))
+
+(declaim (special *buffer-list*))
+
+(defun modeline-field-function (ml-field)
+  "Returns the function of a modeline field object.  It returns a string."
+  (modeline-field-%function ml-field))
+
+
+;;;; Default modeline and update hooks.
+
+(make-modeline-field :name :hemlock-literal :width 8
+		     :function #'(lambda (buffer)
+				   "Returns \"Hemlock \"."
+				   (declare (ignore buffer))
+				   "Hemlock "))
+
+(make-modeline-field
+ :name :external-format
+ :function #'(lambda (buffer)
+	       "Returns an indication of buffer's external-format, iff it's
+other than :DEFAULT"
+	       (let* ((line-termination-string
+                       (case (buffer-line-termination buffer)
+                         ((:lf nil))
+                         ((:cr) "CR")
+                         ((:crlf) "CRLF")))
+                      (encoding-name (or (hemlock-ext:buffer-encoding-name buffer)
+					 "Default")))
+                 (format nil "[~a~@[ ~a~]] "
+                         encoding-name line-termination-string))))
+
+
+(make-modeline-field
+ :name :package
+ :function #'(lambda (buffer)
+	       "Returns the value of buffer's \"Current Package\" followed
+		by a colon and two spaces, or a string with one space."
+	       (if (hemlock-bound-p 'hemlock::current-package :buffer buffer)
+		   (let ((val (variable-value 'hemlock::current-package
+					      :buffer buffer)))
+		     (if (stringp val)
+                       (if (find-package val)
+			 (format nil "~A:  " val)
+                         (format nil "?~A?:  " val))
+                       " "))
+		   " ")))
+
+(make-modeline-field
+ :name :modes
+ :function #'(lambda (buffer)
+	       "Returns buffer's modes followed by one space."
+               (let* ((m ()))
+                 (dolist (mode (buffer-minor-mode-objects buffer))
+                   (unless (mode-object-hidden mode)
+                     (push (mode-object-name mode) m)))
+                 (format nil "~A  " (cons (buffer-major-mode buffer)
+                                          (nreverse m))))))
+
+(make-modeline-field
+ :name :modifiedp
+ :function #'(lambda (buffer)
+	       "Returns \"* \" if buffer is modified, or \"  \"."
+	       (let ((modifiedp (buffer-modified buffer)))
+		 (if modifiedp
+		     "* "
+		     "  "))))
+
+(make-modeline-field
+ :name :buffer-name
+ :function #'(lambda (buffer)
+	       "Returns buffer's name followed by a colon and a space if the
+		name is not derived from the buffer's pathname, or the empty
+		string."
+	       (let ((pn (buffer-pathname buffer))
+		     (name (buffer-name buffer)))
+		 (cond ((not pn)
+			(format nil "~A: " name))
+		       ((string/= (hemlock::pathname-to-buffer-name pn) name)
+			(format nil "~A: " name))
+		       (t "")))))
+
+(make-modeline-field
+ :name :completion :width 40
+ :function #'(lambda (buffer)
+               (declare (special hemlock::*completion-mode-possibility*))
+	       (declare (ignore buffer))
+	       hemlock::*completion-mode-possibility*))
+
+
+
+
+;;; MAXIMUM-MODELINE-PATHNAME-LENGTH-HOOK is called whenever "Maximum Modeline
+;;; Pathname Length" is set.
+;;;
+(defun maximum-modeline-pathname-length-hook (name kind where new-value)
+  (declare (ignore name new-value))
+  (if (eq kind :buffer)
+    (note-modeline-change where)
+    (dolist (buffer *buffer-list*)
+      (when (buffer-modeline-field-p buffer :buffer-pathname)
+	(note-modeline-change buffer)))))
+
+(defun buffer-pathname-ml-field-fun (buffer)
+  "Returns the namestring of buffer's pathname if there is one.  When
+   \"Maximum Modeline Pathname Length\" is set, and the namestring is too long,
+   return a truncated namestring chopping off leading directory specifications."
+  (let ((pn (buffer-pathname buffer)))
+    (if pn
+	(let* ((name (namestring pn))
+	       (length (length name))
+	       ;; Prefer a buffer local value over the global one.
+	       ;; Because variables don't work right, blow off looking for
+	       ;; a value in the buffer's modes.  In the future this will
+	       ;; be able to get the "current" value as if buffer were current.
+	       (max (if (hemlock-bound-p 'hemlock::maximum-modeline-pathname-length
+					  :buffer buffer)
+			 (variable-value 'hemlock::maximum-modeline-pathname-length
+					 :buffer buffer)
+			 (variable-value 'hemlock::maximum-modeline-pathname-length
+					 :global))))
+	  (declare (simple-string name))
+	  (if (or (not max) (<= length max))
+	      name
+	      (let* ((extra-chars (+ (- length max) 3))
+		     (slash (or (position #\/ name :start extra-chars)
+				;; If no slash, then file-namestring is very
+				;; long, and we should include all of it:
+				(position #\/ name :from-end t
+					  :end extra-chars))))
+		(if slash
+		    (concatenate 'simple-string "..." (subseq name slash))
+		    name))))
+	"")))
+
+
+
+(make-modeline-field
+ :name :buffer-pathname
+ :function 'buffer-pathname-ml-field-fun)
+
+
+
+(make-modeline-field
+ :name :process-info
+ :function #'(lambda (buffer)
+               (hemlock-ext:buffer-process-description buffer)))
+
+(defparameter *default-modeline-fields*
+  (list (modeline-field :modifiedp) ;(modeline-field :hemlock-literal)
+	(modeline-field :external-format)
+	(modeline-field :package)
+	(modeline-field :modes))
+  "This is the default value for \"Default Modeline Fields\".")
+
+(defun %init-mode-redisplay ()
+  (add-hook hemlock::buffer-major-mode-hook 'note-modeline-change)
+  (add-hook hemlock::buffer-minor-mode-hook 'note-modeline-change)
+  (add-hook hemlock::buffer-name-hook 'note-modeline-change)
+  (add-hook hemlock::buffer-pathname-hook 'note-modeline-change)
+  ;; (SETF (BUFFER-MODIFIED ...)) handles updating the modeline;
+  ;; it only wants to do so if the buffer's modified state changes.
+;  (add-hook hemlock::buffer-modified-hook 'note-modeline-change)
+)
+
+(defun note-modeline-change (buffer &rest more)
+  (declare (ignore more)) ;; used as hooks some of which pass more info
+  (hemlock-ext:invalidate-modeline buffer))
+
+;; Public version
+(defun update-modeline-fields (buffer)
+  (note-modeline-change buffer))
Index: /branches/new-random/cocoa-ide/hemlock/src/morecoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/morecoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/morecoms.lisp	(revision 13309)
@@ -0,0 +1,515 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Bill Chiles and Rob MacLachlan.
+;;;
+;;; Even more commands...
+
+(in-package :hemlock)
+
+(defhvar "Region Query Size"
+  "A number-of-lines threshold that destructive, undoable region commands
+   should ask the user about when the indicated region is too big."
+  :value 30)
+
+(defun check-region-query-size (region)
+  "Checks the number of lines in region against \"Region Query Size\" and
+   asks the user if the region crosses this threshold.  If the user responds
+   negatively, then an editor error is signaled."
+  (let ((threshold (or (value region-query-size) 0)))
+    (if (and (plusp threshold)
+	     (>= (count-lines region) threshold)
+	     (not (prompt-for-y-or-n
+		   :prompt "Region size exceeds \"Region Query Size\".  Confirm: "
+		   :must-exist t)))
+	(editor-error))))
+
+;;; Do nothing, but do it well ...
+(defcommand "Do Nothing" (p)
+  "Do nothing."
+  "Absolutely nothing."
+  (declare (ignore p)))
+
+
+(defcommand "Abort Command" (p)
+  "Abort reading a command in current view"
+  "Aborts c-q, multi-key commands (e.g. c-x), prefix translation (e.g.
+ESC as Meta-), prefix arguments (e.g. c-u), ephemeral modes such as
+i-search, and prompted input (e.g. m-x)"
+  (declare (ignore p))
+  (abort-to-toplevel))
+
+;;;; Casing commands...
+
+(defcommand "Uppercase Word" (p)
+  "Uppercase a word at point.
+   With prefix argument uppercase that many words."
+  "Uppercase p words at the point."
+  (if (region-active-p)
+    (hemlock::uppercase-region-command p)
+    (filter-words p (current-point) #'string-upcase)))
+
+(defcommand "Lowercase Word" (p)
+  "Uppercase a word at point.
+   With prefix argument uppercase that many words."
+  "Uppercase p words at the point."
+  (if (region-active-p)
+    (hemlock::lowercase-region-command p)
+    (filter-words p (current-point) #'string-downcase)))
+
+;;; FILTER-WORDS implements "Uppercase Word" and "Lowercase Word".
+;;;
+(defun filter-words (p point function)
+  (let ((arg (or p 1)))
+    (with-mark ((mark point))
+      (if (word-offset (if (minusp arg) mark point) arg)
+	  (filter-region function (region mark point))
+	  (editor-error "Not enough words.")))))
+
+;;; "Capitalize Word" is different than uppercasing and lowercasing because
+;;; the differences between Hemlock's notion of what a word is and Common
+;;; Lisp's notion are too annoying.
+;;;
+(defcommand "Capitalize Word" (p)
+  "Lowercase a word capitalizing the first character.  With a prefix
+  argument, capitalize that many words.  A negative argument capitalizes
+  words before the point, but leaves the point where it was."
+  "Capitalize p words at the point."
+  (if (region-active-p)
+    (hemlock::capitalize-region-command p)
+    (let ((point (current-point))
+          (arg (or p 1)))
+      (with-mark ((start point)
+                  (end point))
+        (when (minusp arg)
+          (unless (word-offset start arg) (editor-error "No previous word.")))
+        (do ((region (region start end))
+             (cnt (abs arg) (1- cnt)))
+            ((zerop cnt) (move-mark point end))
+          (unless (find-not-attribute start :word-delimiter)
+            (editor-error "No next word."))
+          (move-mark end start)
+          (unless (find-attribute end :word-delimiter)
+            (buffer-end end))
+          (capitalize-one-word region))))))
+
+(defun capitalize-one-word (region)
+  "Capitalize first word in region, moving region-start to region-end"
+  (let* ((start (region-start region))
+         (end (region-end region)))
+    ;; (assert (mark<= start end))
+    (loop
+      (when (mark= start end)
+        (return nil))
+      (let ((ch (next-character start)))
+        (when (alpha-char-p ch)
+          (setf (next-character start) (char-upcase ch))
+          ;; Yikes!  Somebody should do this at a lower level!
+          (hemlock-ext:buffer-note-modification (current-buffer) start 1)
+          (mark-after start)
+          (filter-region #'string-downcase region)
+          (move-mark start end)
+          (return t)))
+      (mark-after start))))
+
+(defcommand "Uppercase Region" (p)
+  "Uppercase words from point to mark."
+  "Uppercase words from point to mark."
+  (declare (ignore p))
+  (twiddle-region (current-region) #'string-upcase "Uppercase Region"))
+
+(defcommand "Lowercase Region" (p)
+  "Lowercase words from point to mark."
+  "Lowercase words from point to mark."
+  (declare (ignore p))
+  (twiddle-region (current-region) #'string-downcase "Lowercase Region"))
+
+;;; TWIDDLE-REGION implements "Uppercase Region" and "Lowercase Region".
+;;;
+(defun twiddle-region (region function name)
+  (let* (;; don't delete marks start and end since undo stuff will.
+	 (start (copy-mark (region-start region) :left-inserting))
+	 (end (copy-mark (region-end region) :left-inserting)))
+    (let* ((region (region start end))
+	   (undo-region (copy-region region)))
+      (filter-region function region)
+      (move-mark (current-point) end)
+      (make-region-undo :twiddle name region undo-region))))
+
+(defcommand "Capitalize Region" (p)
+  "Capitalize words from point to mark."
+  (declare (ignore p))
+  (let* ((current-region (current-region))
+         (start (copy-mark (region-start current-region) :left-inserting))
+         (end (copy-mark (region-end current-region) :left-inserting))
+         (region (region start end))
+         (undo-region (copy-region region)))
+    (capitalize-words-in-region region)
+    (move-mark (current-point) end)
+    (make-region-undo :twiddle "Capitalize Region" region undo-region)))
+
+(defun capitalize-words-in-region (region)
+  (let ((limit (region-end region)))
+    (with-mark ((start (region-start region)))
+      (with-mark ((end start))
+        (let ((region (region start end)))
+          (loop
+            (unless (and (find-not-attribute start :word-delimiter)
+                         (mark< start limit))
+              (return))
+            ;; start is at a word constituent, there is at least one start <  limit
+            (move-mark end start)
+            (unless (find-attribute end :word-delimiter)
+              (buffer-end end))
+            (when (mark< limit end)
+              (move-mark end limit))
+            (capitalize-one-word region)
+            (move-mark start end)))))))
+
+
+;;;; More stuff.
+
+(defcommand "Delete Previous Character Expanding Tabs" (p)
+  "Delete the previous character.
+  When deleting a tab pretend it is the equivalent number of spaces.
+  With prefix argument, do it that many times."
+  "Delete the P previous characters, expanding tabs into spaces."
+  (let* ((buffer (current-buffer))
+         (region (hi::%buffer-current-region buffer)))
+    (if region
+      (delete-region region)
+      (let ((point (current-point))
+            (n (or p 1)))
+        (when (minusp n)
+          (editor-error "Delete Previous Character Expanding Tabs only accepts ~
+                     positive arguments."))
+        ;; Pre-calculate the number of characters that need to be deleted
+        ;; and any remaining white space filling, allowing modification to
+        ;; be avoided if there are not enough characters to delete.
+        (let ((errorp nil)
+              (del 0)
+              (fill 0))
+          (with-mark ((mark point))
+            (dotimes (i n)
+              (if (> fill 0)
+                (decf fill)
+                (let ((prev (previous-character mark)))
+                  (cond ((and prev (char= prev #\tab))
+                         (let ((pos (mark-column mark)))
+                           (mark-before mark)
+                           (incf fill (- pos (mark-column mark) 1)))
+                         (incf del))
+                        ((mark-before mark)
+                         (incf del))
+                        (t
+                         (setq errorp t)
+                         (return)))))))
+          (cond ((and (not errorp) (kill-characters point (- del)))
+                 (with-mark ((mark point :left-inserting))
+                   (dotimes (i fill)
+                     (insert-character mark #\space))))
+                (t
+                 (editor-error "There were not ~D characters before point." n))))))))
+
+
+(defvar *scope-table*
+  (list (make-string-table :initial-contents
+			   '(("Global" . :global)
+			     ("Buffer" . :buffer)
+			     ("Mode" . :mode)))))
+
+(defun prompt-for-place (prompt help)
+  (multiple-value-bind (word val)
+		       (prompt-for-keyword :tables *scope-table*
+					   :prompt prompt
+					   :help help :default "Global")
+    (declare (ignore word))
+    (case val
+      (:buffer
+       (values :buffer (prompt-for-buffer :help "Buffer to be local to."
+					  :default (current-buffer))))
+      (:mode
+       (values :mode (prompt-for-keyword 
+		      :tables (list *mode-names*)
+		      :prompt "Mode: "
+		      :help "Mode to be local to."
+		      :default (buffer-major-mode (current-buffer)))))
+      (:global :global))))
+
+(defcommand "Bind Key" (p)
+  "Bind a command to a key.
+  The command, key and place to make the binding are prompted for."
+  "Prompt for stuff to do a bind-key."
+  (declare (ignore p))
+  (multiple-value-call #'bind-key 
+    (values (prompt-for-keyword
+	     :tables (list *command-names*)
+	     :prompt "Command to bind: "
+	     :help "Name of command to bind to a key."))
+    (values (prompt-for-key 
+             :must-exist nil
+	     :prompt "Bind to: "
+	     :help "Key to bind command to, confirm to complete."))
+    (prompt-for-place "Kind of binding: "
+		      "The kind of binding to make.")))
+
+(defcommand "Delete Key Binding" (p)
+  "Delete a key binding.
+  The key and place to remove the binding are prompted for."
+  "Prompt for stuff to do a delete-key-binding."
+  (declare (ignore p))
+  (let ((key (prompt-for-key 
+              :must-exist nil
+	      :prompt "Delete binding: "
+	      :help "Key to delete binding from.")))
+    (multiple-value-bind (kind where)
+			 (prompt-for-place "Kind of binding: "
+					   "The kind of binding to make.")
+      (unless (get-command key kind where) 
+	(editor-error "No such binding: ~S" key))
+      (delete-key-binding key kind where))))
+
+
+(defcommand "Set Variable" (p)
+  "Prompt for a Hemlock variable and a new value."
+  "Prompt for a Hemlock variable and a new value."
+  (declare (ignore p))
+  (multiple-value-bind (name var)
+		       (prompt-for-variable
+			:prompt "Variable: "
+			:help "The name of a variable to set.")
+    (declare (ignore name))
+    (setf (variable-value var)
+	  (handle-lisp-errors
+	   (eval (prompt-for-expression
+		  :prompt "Value: "
+		  :help "Expression to evaluate for new value."))))))
+
+(defcommand "Defhvar" (p)
+  "Define a hemlock variable in some location.  If the named variable exists
+   currently, its documentation is propagated to the new instance, but this
+   never prompts for documentation."
+  "Define a hemlock variable in some location."
+  (declare (ignore p))
+  (let* ((name (nstring-capitalize (prompt-for-variable :must-exist nil)))
+	 (var (string-to-variable name))
+	 (doc (if (hemlock-bound-p var)
+		  (variable-documentation var)
+		  ""))
+	 (hooks (if (hemlock-bound-p var) (variable-hooks var)))
+	 (val (prompt-for-expression :prompt "Variable value: "
+				     :help "Value for the variable.")))
+    (multiple-value-bind
+	(kind where)
+	(prompt-for-place
+	 "Kind of binding: "
+	 "Whether the variable is global, mode, or buffer specific.")
+      (if (eq kind :global)
+	  (defhvar name doc :value val :hooks hooks)
+	  (defhvar name doc kind where :value val :hooks hooks)))))
+
+
+;;; TRANSPOSE REGIONS uses CURRENT-REGION to signal an error if the current
+;;; region is not active and to get start2 and end2 in proper order.  Delete1,
+;;; delete2, and delete3 are necessary since we are possibly ROTATEF'ing the
+;;; locals end1/start1, start1/start2, and end1/end2, and we need to know which
+;;; marks to dispose of at the end of all this stuff.  When we actually get to
+;;; swapping the regions, we must delete both up front if they both are to be
+;;; deleted since we don't know what kind of marks are in start1, start2, end1,
+;;; and end2, and the marks will be moving around unpredictably as we insert
+;;; text at them.  We copy point into ipoint for insertion purposes since one
+;;; of our four marks is the point.
+;;; 
+(defcommand "Transpose Regions" (p)
+  "Transpose two regions with endpoints defined by the mark stack and point.
+   To use:  mark start of region1, mark end of region1, mark start of region2,
+   and place point at end of region2.  Invoking this immediately following
+   one use will put the regions back, but you will have to activate the
+   current region."
+  "Transpose two regions with endpoints defined by the mark stack and point."
+  (declare (ignore p))
+  (unless (>= (ring-length (value buffer-mark-ring)) 3)
+    (editor-error "Need two marked regions to do Transpose Regions."))
+  (let* ((region (current-region))
+	 (end2 (region-end region))
+	 (start2 (region-start region))
+	 (delete1 (pop-buffer-mark))
+	 (end1 (pop-buffer-mark))
+	 (delete2 end1)
+	 (start1 (pop-buffer-mark))
+	 (delete3 start1))
+    ;;get marks in the right order, to simplify the code that follows
+    (unless (mark<= start1 end1) (rotatef start1 end1))
+    (unless (mark<= start1 start2)
+      (rotatef start1 start2)
+      (rotatef end1 end2))
+    ;;order now guaranteed:  <Buffer Start> start1 end1 start2 end2 <Buffer End>
+    (unless (mark<= end1 start2)
+      (editor-error "Can't transpose overlapping regions."))
+    (let* ((adjacent-p (mark= end1 start2))
+	   (region1 (delete-and-save-region (region start1 end1)))
+	   (region2 (unless adjacent-p
+		      (delete-and-save-region (region start2 end2))))
+	   (point (current-point)))
+      (with-mark ((ipoint point :left-inserting))
+	(let ((save-end2-loc (push-new-buffer-mark end2)))
+	  (ninsert-region (move-mark ipoint end2) region1)
+	  (push-new-buffer-mark ipoint)
+	  (cond (adjacent-p
+		 (push-new-buffer-mark start2)
+		 (move-mark point save-end2-loc))
+		(t (push-new-buffer-mark end1)
+		   (ninsert-region (move-mark ipoint end1) region2)
+		   (move-mark point ipoint))))))
+    (delete-mark delete1)
+    (delete-mark delete2)
+    (delete-mark delete3)))
+
+
+(defcommand "Goto Absolute Line" (p)
+  "Goes to the indicated line, if you counted them starting at the beginning
+   of the buffer with the number one.  If a prefix argument is supplied, that
+   is the line number; otherwise, the user is prompted."
+  "Go to a user perceived line number."
+  (let ((p (or p (prompt-for-expression
+		  :prompt "Line number: "
+		  :help "Enter an absolute line number to goto."))))
+    (unless (and (integerp p) (plusp p))
+      (editor-error "Must supply a positive integer."))
+    (let ((point (current-point)))
+      (with-mark ((m point))
+	(unless (line-offset (buffer-start m) (1- p) 0)
+	  (editor-error "Not enough lines in buffer."))
+	(move-mark point m)))))
+
+(defcommand "Goto Absolute Position" (p)
+  "Goes to the indicated character position, if you counted them
+   starting at the beginning of the buffer with the number zero.  If a
+   prefix argument is supplied, that is the line number; otherwise, the
+  user is prompted."
+  "Go to a user perceived character position."
+  (let ((p (or p (prompt-for-expression
+		  :prompt "Character Position: "
+		  :help "Enter an absolute character position to goto."))))
+    (unless (and (integerp p) (not (minusp p)))
+      (editor-error "Must supply a non-negatige integer."))
+    (let ((point (current-point-unless-selection)))
+      (when point
+	(unless (move-to-absolute-position point p)
+	  (buffer-end point))))))
+
+(defcommand "What Cursor Position" (p)
+  "Print info on current point position"
+  "Print info on current point position"
+  (declare (ignore p))
+  (let* ((point (current-point))
+	 (line-number (do* ((l 1 (1+ l))
+			    (mark-line (line-previous (mark-line point)) (line-previous mark-line)))
+			   ((null mark-line) l)))
+	 (charpos (mark-charpos point))
+	 (abspos (mark-absolute-position point))
+	 (char (next-character point))
+	 (size (count-characters (buffer-region (current-buffer)))))
+    (message "Char: ~s point = ~d of ~d(~d%) line ~d column ~d"
+	     char abspos size (round (/ (* 100 abspos) size)) line-number charpos)))
+
+(defcommand "Count Lines" (p)
+  "Display number of lines in the region."
+  "Display number of lines in the region."
+  (declare (ignore p))
+  (multiple-value-bind (region activep) (get-count-region)
+    (message "~:[After point~;Active region~]: ~A lines"
+	     activep (count-lines region))))
+
+(defcommand "Count Words" (p)
+  "Prints in the Echo Area the number of words in the region
+   between the point and the mark by using word-offset. The
+   argument is ignored."
+  "Prints Number of Words in the Region"
+  (declare (ignore p))
+  (multiple-value-bind (region activep) (get-count-region)
+    (let ((end-mark (region-end region)))
+      (with-mark ((beg-mark (region-start region)))
+	(let ((word-count 0))
+	  (loop
+	    (when (mark>= beg-mark end-mark)
+	      (return))
+	    (unless (word-offset beg-mark 1)
+	      (return))
+	    (incf word-count))
+	  (message "~:[After point~;Active region~]: ~D Word~:P"
+		   activep word-count))))))
+
+;;; GET-COUNT-REGION -- Internal Interface.
+;;;
+;;; Returns the active region or the region between point and end-of-buffer.
+;;; As a second value, it returns whether the region was active.
+;;;
+;;; Some searching commands use this routine.
+;;;
+(defun get-count-region ()
+  (if (region-active-p)
+      (values (current-region) t)
+      (values (region (current-point) (buffer-end-mark (current-buffer)))
+	      nil)))
+
+
+
+
+;;;; Some modes:
+
+(defcommand "Fundamental Mode" (p)
+  "Put the current buffer into \"Fundamental\" mode."
+  "Put the current buffer into \"Fundamental\" mode."
+  (declare (ignore p))
+  (setf (buffer-major-mode (current-buffer)) "Fundamental"))
+
+;;;
+;;; Text mode.
+;;;
+
+(defmode "Text" :major-p t)
+
+(defcommand "Text Mode" (p)
+  "Put the current buffer into \"Text\" mode."
+  "Put the current buffer into \"Text\" mode."
+  (declare (ignore p))
+  (setf (buffer-major-mode (current-buffer)) "Text"))
+
+;;;
+;;; Caps-lock mode.
+;;;
+
+(defmode "CAPS-LOCK")
+
+(defcommand "Caps Lock Mode" (p)
+  "Simulate having a CAPS LOCK key.  Toggle CAPS-LOCK mode.  Zero or a
+   negative argument turns it off, while a positive argument turns it
+   on."
+  "Simulate having a CAPS LOCK key.  Toggle CAPS-LOCK mode.  Zero or a
+   negative argument turns it off, while a positive argument turns it
+   on."
+  (setf (buffer-minor-mode (current-buffer) "CAPS-LOCK")
+	(if p
+	    (plusp p)
+	    (not (buffer-minor-mode (current-buffer) "CAPS-LOCK")))))
+
+(defcommand "Self Insert Caps Lock" (p)
+  "Insert the last character typed, or the argument number of them.
+   If the last character was an alphabetic character, then insert its
+   capital form."
+  "Insert the last character typed, or the argument number of them.
+   If the last character was an alphabetic character, then insert its
+   capital form."
+  (let ((char (char-upcase (last-char-typed))))
+    (if (and p (> p 1))
+	(insert-string (current-point) (make-string p :initial-element char))
+	(insert-character (current-point) char))))
Index: /branches/new-random/cocoa-ide/hemlock/src/package.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/package.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/package.lisp	(revision 13309)
@@ -0,0 +1,652 @@
+(in-package :cl-user)
+
+(defpackage :hemlock-interface
+  (:use)
+  (:export
+   ;; Symbols from the CIM, by chapter:
+
+   ;; Representation of Text
+   #:linep
+   #:line-string
+   #:line-previous
+   #:line-next
+   #:line-buffer
+   #:line-length
+   #:line-character
+   #:line-plist
+   #:line-signature
+   #:markp
+   #:mark-line
+   #:mark-charpos
+   #:mark-kind
+   #:mark-buffer
+   #:mark-absolute-position
+   #:previous-character
+   #:next-character
+   #:mark
+   #:copy-mark
+   #:delete-mark
+   #:with-mark
+   #:move-to-position
+   #:move-to-absolute-position
+   #:move-mark
+   #:line-start
+   #:line-end
+   #:buffer-start
+   #:buffer-end
+   #:mark-before
+   #:mark-after
+   #:character-offset
+   #:line-offset
+   #:region
+   #:regionp
+   #:make-empty-region
+   #:copy-region
+   #:region-to-string
+   #:string-to-region
+   #:line-to-region
+   #:region-start
+   #:region-end
+   #:region-bounds
+   #:set-region-bounds
+   #:count-lines
+   #:count-characters
+
+   ;; charprops
+   #:next-charprop-value
+   #:previous-charprop-value
+   #:set-charprop-value
+   #:find-charprop-value
+   #:next-charprops
+   #:previous-charprops
+   #:set-charprops
+   #:charprops-in-region
+   #:apply-charprops
+   #:find-charprops
+   #:find-charprops-change
+   #:charprop-equal
+   #:charprops-get
+   #:charprops-set
+   #:charprops-equal
+   #:charprops-as-plist
+   #:charprops-as-hash
+   #:charprops-names
+   #:set-buffer-charprops
+   #:buffer-charprops
+
+   ;; Buffers
+   #:current-buffer
+   #:current-point-for-insertion
+   #:current-point-for-deletion
+   #:current-point-unless-selection
+   #:current-point-collapsing-selection
+   #:current-point-extending-selection
+   #:current-point-for-selection-start
+   #:current-point-for-selection-end
+   #:current-point
+   #:current-mark
+   #:pop-buffer-mark
+   #:push-buffer-mark
+   #:push-new-buffer-mark
+   #:all-buffers
+   #:make-buffer
+   #:bufferp
+   #:buffer-name
+   #:buffer-region
+   #:buffer-pathname
+   #:buffer-write-date
+   #:buffer-point
+   #:buffer-mark
+   #:buffer-start-mark
+   #:buffer-end-mark
+   #:buffer-writable
+   #:buffer-modified
+   #:buffer-signature
+   #:buffer-variables
+   #:buffer-modes
+   #:buffer-delete-hook
+   #:buffer-package
+   #:delete-buffer
+   #:with-writable-buffer
+   #:make-modeline-field
+   #:modeline-field-p
+   #:modeline-field-name
+   #:modeline-field
+   #:modeline-field-function
+   #:modeline-field-width
+   #:buffer-modeline-fields
+   #:buffer-modeline-field-p
+   #:update-modeline-fields
+
+   ;; Altering and Searching Text
+   #:insert-character
+   #:insert-string
+   #:insert-region
+   #:ninsert-region
+   #:delete-characters
+   #:delete-region
+   #:delete-and-save-region
+   #:filter-region
+   #:start-line-p
+   #:end-line-p
+   #:empty-line-p
+   #:blank-line-p
+   #:blank-before-p
+   #:blank-after-p
+   #:same-line-p
+   #:mark<
+   #:mark<=
+   #:mark=
+   #:mark/=
+   #:mark>=
+   #:mark>
+   #:line<
+   #:line<=
+   #:line>=
+   #:line>
+   #:lines-related
+   #:first-line-p
+   #:last-line-p
+   #:kill-region
+   #:kill-characters
+   #:*ephemerally-active-command-types*
+   #:activate-region
+   #:deactivate-region
+   #:region-active-p
+   #:check-region-active
+   #:current-region
+   #:new-search-pattern
+   #:search-pattern-p
+   #:get-search-pattern
+   #:find-pattern
+   #:replace-pattern
+   #:*last-search-string*
+   #:collapse-if-selection
+
+   ;; Hemlock Variables
+   #:*global-variable-names*
+   #:current-variable-tables
+   #:defhvar
+   #:variable-value
+   #:variable-documentation
+   #:variable-hooks
+   #:variable-name
+   #:string-to-variable
+   #:value
+   #:setv
+   #:hlet
+   #:hemlock-bound-p
+   #:delete-variable
+   #:add-hook
+   #:remove-hook
+   #:invoke-hook
+
+   ;; Commands
+   #:*command-names*
+   #:defcommand
+   #:make-command
+   #:commandp
+   #:command-documentation
+   #:command-function
+   #:command-name
+   #:bind-key
+   #:command-bindings
+   #:delete-key-binding
+   #:get-command
+   #:map-bindings
+   #:key-translation
+   #:last-command-type
+   #:prefix-argument
+
+   ;; Modes
+   #:*mode-names*
+   #:defmode
+   #:mode-documentation
+   #:buffer-major-mode
+   #:buffer-minor-mode
+   #:mode-variables
+   #:mode-major-p
+
+   ;; Character attributes
+   #:*character-attribute-names*
+   #:defattribute
+   #:character-attribute-name
+   #:character-attribute-documentation
+   #:character-attribute
+   #:character-attribute-p
+   #:shadow-attribute
+   #:unshadow-attribute
+   #:find-attribute
+   #:find-not-attribute
+   #:reverse-find-attribute
+   #:reverse-find-not-attribute
+   #:character-attribute-hooks
+
+   ;; Controlling the Display
+   #:current-view
+   #:hemlock-view-p
+   #:hemlock-view-buffer
+   #:mark-column
+   #:move-to-column
+   #:set-scroll-position
+
+   ;; Logical Key Events
+   #:*logical-key-event-names*
+   #:define-logical-key-event
+   #:logical-key-event-key-events
+   #:logical-key-event-name
+   #:logical-key-event-documentation
+   #:logical-key-event-p
+
+   ;; The Echo Area
+   #:clear-echo-area
+   #:message
+   #:loud-message
+   #:beep
+   #:command-case
+   #:prompt-for-buffer
+   #:prompt-for-key-event
+   #:prompt-for-key
+   #:prompt-for-file
+   #:prompt-for-integer
+   #:prompt-for-keyword
+   #:prompt-for-expression
+   #:prompt-for-string
+   #:prompt-for-variable
+   #:prompt-for-y-or-n
+   #:prompt-for-yes-or-no
+   #:parse-for-something
+
+   ;; Files
+   #:define-file-option
+   #:define-file-type-hook
+   #:process-file-options
+   #:pathname-to-buffer-name
+   #:buffer-default-pathname
+   #:read-file
+   #:write-file
+   #:write-buffer-file
+   #:read-buffer-file
+  ;; #:find-file-buffer
+
+   ;;# Hemlock's Lisp Environment
+   ;;   #:ed
+   #:*key-event-history*
+   #:last-key-event-typed
+   #:last-char-typed
+   #:make-hemlock-output-stream
+   #:hemlock-output-stream-p
+   #:make-hemlock-region-stream
+   #:hemlock-region-stream-p
+   #:with-input-from-region
+   #:with-output-to-mark
+   #:with-pop-up-display
+   #:editor-error
+   #:handle-lisp-errors
+   #:in-lisp
+   #:do-alpha-chars
+
+   ;; Higher-Level Text Primitives
+   #:indent-region
+   #:indent-region-for-commands
+   #:delete-horizontal-space
+   #:pre-command-parse-check
+   #:form-offset
+   #:top-level-offset
+   #:mark-top-level-form
+   #:defun-region
+   #:inside-defun-p
+   #:start-defun-p
+   #:forward-up-list
+   #:backward-up-list
+   #:valid-spot
+   #:defindent
+   #:word-offset
+   #:sentence-offset
+   #:paragraph-offset
+   #:mark-paragraph
+   #:fill-region
+   #:fill-region-by-paragraphs
+
+   ;; Utilities
+   #:make-string-table
+   #:string-table-p
+   #:string-table-separator
+   #:delete-string
+   #:clrstring
+   #:getstring
+   #:complete-string
+   #:find-ambiguous
+   #:find-containing
+   #:do-strings
+   #:make-ring
+   #:ringp
+   #:ring-length
+   #:ring-ref
+   #:ring-push
+   #:ring-pop
+   #:rotate-ring
+   #:save-for-undo
+   #:make-region-undo
+
+   ;; Miscellaneous
+
+   #:define-keysym
+   #:define-keysym-code
+   #:define-mouse-keysym
+   #:name-keysym
+   #:keysym-names
+   #:keysym-preferred-name
+   #:define-key-event-modifier
+   #:*all-modifier-names*
+   #:make-key-event-bits
+   #:key-event-modifier-mask
+   #:key-event-bits-modifiers
+   #:make-key-event
+   #:key-event-p
+   #:key-event-bits
+   #:key-event-keysym
+   #:char-key-event
+   #:key-event-char
+   #:key-event-bit-p
+   #:do-alpha-key-events
+   #:pretty-key-string
+   ))
+
+;; Functions defined externally (i.e. used by but not defined in hemlock).  In theory,
+;; these (and codes for the symbolic keysyms in keysym-defs.lisp, q.v.) is all you need
+;; to implement to port the IDE to a different window system.
+(defpackage :hemlock-ext
+  (:use)
+  ;;
+  (:export
+   #:invoke-modifying-buffer-storage
+   #:invoke-allowing-buffer-display
+   #:note-selection-set-by-search
+   #:buffer-note-font-change
+   #:buffer-note-insertion
+   #:buffer-note-modification
+   #:buffer-note-deletion
+   #:buffer-encoding-name
+   #:scroll-view
+   #:ensure-selection-visible
+   #:report-hemlock-error
+   #:top-listener-output-stream
+   #:top-listener-input-stream
+   #:invalidate-modeline
+   #:note-buffer-saved
+   #:note-buffer-unsaved
+   #:read-only-listener-p
+   #:all-hemlock-views
+   #:open-hemlock-buffer
+   #:save-hemlock-buffer
+   #:revert-hemlock-buffer
+   #:open-sequence-dialog
+   #:execute-in-file-view
+   #:change-active-pane
+   #:send-string-to-listener
+   #:buffer-process-description
+   #:raise-buffer-view
+   #:string-to-clipboard
+   ))
+
+(defpackage :hi
+  (:use :common-lisp :hemlock-interface)
+  (:nicknames :hemlock-internals)
+  (:import-from
+   ;; gray streams
+   #+EXCL  :excl
+   #+CLISP :gray
+   #+CMU   :ext
+   #+sbcl  :sb-gray
+   #+scl   :ext
+   #+clozure :gray
+   ;;
+   ;; Note the patch i received from DTC mentions character-output and
+   ;; character-input-stream here, so we actually see us faced to
+   ;; provide for compatibility classes. --GB
+   #-scl   #:fundamental-character-output-stream
+   #-scl   #:fundamental-character-input-stream
+   ;; There is conditionalization in streams.lisp, see above --GB
+   #+scl   #:character-output-stream
+   #+scl   #:character-input-stream
+   
+   #:stream-write-char
+   #-scl   #:stream-write-string     ; wonder what that is called --GB
+   #:stream-read-char
+   #:stream-listen
+   #:stream-unread-char
+   #:stream-clear-input
+   #:stream-finish-output
+   #:stream-force-output
+   #:stream-line-column)
+  (:import-from :ccl
+                #:delq #:memq #:assq
+                #:getenv
+                #:fixnump)
+  (:import-from :gui
+		#:log-debug)
+  ;; ** TODO: get rid of this.  The code that uses it assumes it guarantees atomicity,
+  ;; and it doesn't.
+  (:import-from :ccl #:without-interrupts)
+  ;;
+  (:export
+   #:*FAST*                             ;hmm not sure about this one
+   
+   ;; Imported
+   #:delq #:memq #:assq #:getenv #:fixnump #:log-debug
+
+   ;; hemlock-ext.lisp
+   #:hemlock-char-code-limit
+   #:file-writable #:default-directory #:complete-file #:ambiguous-files
+
+   ;; rompsite.lisp
+   #:editor-describe-function
+   #:merge-relative-pathnames
+   ;;
+   ;; Export default-font to prevent a name conflict that occurs due to
+   ;; the Hemlock variable "Default Font" defined in SITE-INIT below.
+   ;;
+   #:default-font
+   #:*beep-function* #:beep
+
+   ;; 
+   #:mark #:mark-line #:mark-charpos #:mark-column #:move-to-column
+   #:markp #:region #:region-start #:region-end
+   #:regionp #:buffer #:bufferp #:buffer-modes #:buffer-point #:buffer-writable
+   #:buffer-delete-hook #:buffer-variables #:buffer-write-date
+   #:region #:regionp #:region-start #:region-end
+   #:commandp #:command #:command-function
+   #:command-documentation #:modeline-field #:modeline-field-p
+
+   ;; from macros.lisp
+   #:invoke-hook #:value #:setv #:hlet #:string-to-variable #:add-hook #:remove-hook
+   #:defcommand #:with-mark #:use-buffer #:editor-error
+   #:editor-error-format-string #:editor-error-format-arguments #:do-strings
+   #:command-case #:reprompt #:with-output-to-mark #:with-input-from-region
+   #:handle-lisp-errors #:with-pop-up-display
+
+   ;; from views.lisp
+   #:hemlock-view #:current-view #:hemlock-view-buffer
+   #:current-prefix-argument-state #:last-key-event-typed #:last-char-typed
+   #:invoke-command
+   #:abort-to-toplevel #:abort-current-command
+   #:set-scroll-position
+   #:native-key-event-p
+
+   ;; from line.lisp
+   #:line #:linep #:line-previous #:line-next #:line-plist #:line-signature
+
+   ;; from ring.lisp
+   #:ring #:ringp #:make-ring #:ring-push #:ring-pop #:ring-length #:ring-ref
+   #:rotate-ring
+
+   ;; from table.lisp
+   #:string-table #:string-table-p #:make-string-table
+   #:string-table-separator #:getstring
+   #:find-ambiguous #:complete-string #:find-containing
+   #:delete-string #:clrstring #:do-strings
+
+   ;; buffer.lisp
+   #:buffer-modified #:buffer-region #:buffer-name #:buffer-pathname
+   #:buffer-major-mode #:buffer-minor-mode #:buffer-modeline-fields
+   #:buffer-modeline-field-p #:current-buffer #:current-point
+   #:defmode #:mode-major-p #:mode-variables #:mode-documentation
+   #:make-buffer #:delete-buffer #:with-writable-buffer #:buffer-start-mark
+   #:buffer-end-mark #:*buffer-list*
+
+   ;; charmacs.lisp
+   #:syntax-char-code-limit #:search-char-code-limit #:do-alpha-chars
+
+   ;; charprops.lisp
+   #:next-charprop-value #:previous-charprop-value
+   #:set-charprop-value #:find-charprop-value #:next-charprops
+   #:previous-charprops #:set-charprops #:charprops-in-region
+   #:apply-charprops #:find-charprops #:find-charprops-change
+   #:charprop-equal #:charprops-get #:charprops-set #:charprops-equal
+   #:charprops-as-plist #:charprops-as-hash #:charprops-names
+   #:set-buffer-charprops #:buffer-charprops
+
+   ;; key-event.lisp
+   #:define-keysym-code #:define-mouse-keysym #:define-modifier-bit
+   #:*all-modifier-names* #:*modifier-translations*
+   #:make-key-event #:char-key-event #:do-alpha-key-events
+   #:key-event-modifier-mask #:key-event-char #:key-event-bit-p
+   #:pretty-key-string
+
+   ;; echo.lisp
+   #:*echo-area-stream*
+   #:clear-echo-area #:message #:loud-message
+   #:current-echo-parse-state #:exit-echo-parse
+   #:eps-parse-type #:eps-parse-starting-mark #:eps-parse-input-region
+   #:eps-parse-verification-function #:eps-parse-string-tables
+   #:eps-parse-default #:eps-parse-help #:eps-parse-key-handler
+   #:prompt-for-buffer #:prompt-for-file #:prompt-for-integer
+   #:prompt-for-keyword #:prompt-for-expression #:prompt-for-string
+   #:prompt-for-variable #:prompt-for-yes-or-no #:prompt-for-y-or-n
+   #:prompt-for-key-event #:prompt-for-key
+   #:*logical-key-event-names*
+   #:logical-key-event-p #:logical-key-event-documentation
+   #:logical-key-event-name #:logical-key-event-key-events
+   #:define-logical-key-event #:current-variable-tables
+
+
+   ;; commands
+   #:make-prefix-argument-state #:prefix-argument-resetting-state
+
+  
+   ;; files.lisp
+   #:read-file #:write-file
+
+
+   ;; font.lisp
+   #:font-mark #:delete-font-mark #:delete-line-font-marks #:move-font-mark
+   #:window-font
+
+   ;; htext1.lisp
+   #:line-length #:line-buffer #:line-string #:line-character #:mark #:mark-kind
+   #:copy-mark #:delete-mark #:move-to-position #:mark-absolute-position
+   #:move-to-absolute-position #:buffer-selection-range #:region #:make-empty-region
+   #:start-line-p #:end-line-p #:empty-line-p #:blank-line-p #:blank-before-p
+   #:blank-after-p #:same-line-p #:mark< #:mark<= #:mark> #:mark>= #:mark= #:mark/=
+   #:line< #:line<= #:line> #:line>= #:first-line-p #:last-line-p #:buffer-signature
+   #:lines-related
+
+
+   ;; htext2.lisp
+   #:region-to-string #:string-to-region #:line-to-region
+   #:previous-character #:next-character #:count-lines
+   #:count-characters #:line-start #:line-end #:buffer-start
+   #:buffer-end #:move-mark #:mark-before #:mark-after
+   #:character-offset #:line-offset #:region-bounds
+   #:set-region-bounds #:*print-region*
+
+
+   ;; htext3.lisp
+   #:insert-character #:insert-string #:insert-region #:ninsert-region
+   #:paste-characters
+
+   ;; htext4.lisp
+   #:delete-characters #:delete-region #:delete-and-save-region #:copy-region
+   #:filter-region
+
+
+   ;; interp.lisp
+   #:bind-key #:delete-key-binding #:get-command #:map-bindings
+   #:make-command #:command-name #:command-bindings #:last-command-type
+   #:prefix-argument #:key-translation
+
+
+   ;; main.lisp
+   #:*global-variable-names* #:*mode-names* #:*buffer-names*
+   #:*character-attribute-names* #:*command-names* #:*buffer-list*
+   #:after-editor-initializations
+
+   ;; search1.lisp
+   #:search-pattern #:search-pattern-p #:find-pattern #:replace-pattern
+   #:new-search-pattern
+
+   ;; modeline.lisp
+   #:modeline-field-width
+   #:modeline-field-function #:make-modeline-field
+   #:update-modeline-field #:modeline-field-name #:modeline-field
+
+   ;; streams.lisp
+   #:make-hemlock-output-stream
+   #:hemlock-region-stream #:hemlock-region-stream-p
+   #:hemlock-output-stream #:make-hemlock-region-stream
+   #:hemlock-output-stream-p #:make-kbdmac-stream
+   #:modify-kbdmac-stream
+
+   ;; syntax.lisp
+   #:character-attribute-name
+   #:defattribute #:character-attribute-documentation #:character-attribute
+   #:character-attribute-hooks #:character-attribute-p #:shadow-attribute
+   #:unshadow-attribute #:find-attribute #:reverse-find-attribute
+
+   ;; vars.lisp
+   #:variable-value #:variable-hooks #:variable-documentation #:variable-name
+   #:hemlock-bound-p #:defhvar #:delete-variable
+
+   #:input-stream-reading-line
+
+   ))
+
+
+(defpackage :hemlock
+  (:use :common-lisp :hemlock-interface :hemlock-internals :hemlock-ext)
+  )
+
+
+;; $Log$
+;; Revision 1.2  2005/08/01 10:54:17  gb
+;; Don't export CHECK-REGION-QUERY-SIZE.
+;;
+;; Revision 1.1.1.1  2003/10/19 08:57:16  gb
+;; recovered 0.14 sources
+;;
+;; Revision 1.1.2.1  2003/08/10 19:11:33  gb
+;; New files, imported from upstream CVS as of 03/08/09.
+;;
+;; Revision 1.9  2003/08/05 19:58:21  gilbert
+;; - we now have a HEMLOCK-INTERFACE package which exports symbols mentioned
+;;   in the Command Implementors Manual.
+;;
+;; Revision 1.8  2003/07/28 20:35:32  jdz
+;; BEEP function now works.
+;;
+;; Revision 1.7  2003/07/27 10:11:06  jdz
+;; HEMLOCK-EXT package is now used by HEMLOCK.  Conflicting symbols from
+;; EXTENSIONS package in CMUCL are shadowed.
+;;
+;; Revision 1.6  2003/05/12 11:01:48  gbyers
+;; Conditionalize (Gray streams package) for OpenMCL.
+;;
+;; Revision 1.5  2003/03/26 07:50:10  gilbert
+;; Port to SCL by Douglas Crosher
+;;
+;; Revision 1.4  2003/03/06 21:38:58  gilbert
+;; The symbol *FAST* is now exported from HI (no idea if that is the
+;; right thing to do) and imported into HEMLOCK. Fixes bug:
+;; auto-save.lisp was not compiling.
+;;
Index: /branches/new-random/cocoa-ide/hemlock/src/pop-up-stream.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/pop-up-stream.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/pop-up-stream.lisp	(revision 13309)
@@ -0,0 +1,37 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contatins the stream operations for pop-up-displays.
+;;;
+;;; Written by Blaine Burks.
+;;;
+
+(in-package :hemlock-internals)
+
+
+(defmethod stream-write-char ((stream random-typeout-stream) char)
+  (insert-character (random-typeout-stream-mark stream) char))
+
+(defmethod stream-write-string ((stream random-typeout-stream) string &optional start end)
+  (setf start (or start 0))
+  (setf end (or end (length string)))
+  (unless (and (eql start 0) (eql end (length string)))
+    (setq string (subseq string start end)))
+  (insert-string (random-typeout-stream-mark stream) string))
+
+(defmethod stream-finish-output ((stream random-typeout-stream))
+  nil)
+
+(defmethod stream-force-output ((stream random-typeout-stream))
+  (stream-finish-output stream))
+
+(defmethod stream-line-column ((stream random-typeout-stream))
+  (mark-charpos (random-typeout-stream-mark stream)))
Index: /branches/new-random/cocoa-ide/hemlock/src/register.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/register.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/register.lisp	(revision 13309)
@@ -0,0 +1,182 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Registers for holding text and positions.
+;;;
+;;; Written by Dave Touretzky.
+;;; Modified by Bill Chiles for Hemlock consistency.
+;;;
+(in-package :hemlock)
+
+
+
+
+;;;; Registers implementation.
+
+;;; Registers are named by characters.  Each register refers to a mark or
+;;; a cons of a region and the buffer it came from.
+;;; 
+(defvar *registers* (make-hash-table))
+
+(defun register-count ()
+  (hash-table-count *registers*))
+
+(defun register-value (reg-name)
+  (gethash reg-name *registers*))
+
+(defsetf register-value (reg-name) (new-value)
+  (let ((name (gensym))
+	(value (gensym))
+	(old-value (gensym)))
+    `(let* ((,name ,reg-name)
+	    (,value ,new-value)
+	    (,old-value (gethash ,name *registers*)))
+       (when (and ,old-value (markp ,old-value))
+	 (delete-mark ,old-value))
+       (setf (gethash ,name *registers*) ,value))))
+
+(defun prompt-for-register (&optional (prompt "Register: ") must-exist)
+  (let ((reg-name (prompt-for-key-event :prompt prompt)))
+    (unless (or (not must-exist) (gethash reg-name *registers*))
+      (editor-error "Register ~A is empty." reg-name))
+    reg-name))
+
+     
+(defmacro do-registers ((name value &optional sorted) &rest body)
+  (if sorted
+      (let ((sorted-regs (gensym))
+	    (reg (gensym)))
+	`(let ((,sorted-regs nil))
+	   (declare (list ,sorted-regs))
+	   (maphash #'(lambda (,name ,value)
+			(push (cons ,name ,value) ,sorted-regs))
+		    *registers*)
+	   (setf ,sorted-regs (sort ,sorted-regs #'char-lessp :key #'car))
+	   (dolist (,reg ,sorted-regs)
+	     (let ((,name (car ,reg))
+		   (,value (cdr ,reg)))
+	       ,@body))))
+      `(maphash #'(lambda (,name ,value)
+		    ,@body)
+		*registers*)))
+
+
+;;; Hook to clean things up if a buffer is deleted while registers point to it.
+;;; 
+(defun flush-reg-references-to-deleted-buffer (buffer)
+  (do-registers (name value)
+    (etypecase value
+      (mark (when (eq (mark-buffer value) buffer)
+	      (free-register name)))
+      (cons (free-register-value value buffer)))))
+;;;
+(add-hook delete-buffer-hook 'flush-reg-references-to-deleted-buffer)
+
+
+(defun free-register (name)
+  (let ((value (register-value name)))
+    (when value (free-register-value value)))
+  (remhash name *registers*))
+
+(defun free-register-value (value &optional buffer)
+  (etypecase value
+    (mark
+     (when (or (not buffer) (eq (mark-buffer value) buffer))
+       (delete-mark value)))
+    (cons
+     (when (and buffer (eq (cdr value) buffer))
+       (setf (cdr value) nil)))))
+
+
+
+
+;;;; Commands.
+
+;;; These commands all stash marks and regions with marks that point into some
+;;; buffer, and they assume that the register values have the same property.
+;;; 
+
+(defcommand "Save Position" (p)
+  "Saves the current location in a register.  Prompts for register name."
+  (declare (ignore p))
+  (let ((reg-name (prompt-for-register)))
+    (setf (register-value reg-name)
+	  (copy-mark (current-point) :left-inserting))))
+
+(defcommand "Jump to Saved Position" (p)
+  "Moves the point to a location previously saved in a register."
+  (declare (ignore p))
+  (let* ((reg-name (prompt-for-register "Jump to Register: " t))
+	 (val (register-value reg-name)))
+    (unless (markp val)
+      (editor-error "Register ~A does not hold a location." reg-name))
+    (unless (eq (mark-buffer val) (current-buffer))
+      (hemlock-ext:raise-buffer-view (mark-buffer val)
+                                     #'(lambda ()
+                                         (move-mark (current-point) val))))))
+
+(defcommand "Kill Register" (p)
+  "Kill a register.  Prompts for the name."
+  (declare (ignore p))
+  (free-register (prompt-for-register "Register to kill: ")))
+
+(defcommand "List Registers" (p)
+  "Lists all registers in a pop-up window."
+  "Lists all registers in a pop-up window."
+  (declare (ignore p))
+  (with-pop-up-display (f :height (* 2 (register-count)))
+    (do-registers (name val :sorted)
+      (write-string "Reg " f)
+      (write-string (pretty-key-string name) f)
+      (write-string ":  " f)
+      (etypecase val
+	(mark
+	 (let* ((line (mark-line val))
+		(buff (line-buffer line))
+		(len (line-length line)))
+	   (format f "Line ~S, col ~S in buffer ~A~%   ~A~:[~;...~]~%"
+		   (count-lines (region (buffer-start-mark buff) val))
+		   (mark-column val)
+		   (buffer-name buff)
+		   (subseq (line-string line) 0 (min 61 len))
+		   (> len 60))))
+	(cons
+	 (let* ((str (region-to-string (car val)))
+		(nl (position #\newline str :test #'char=))
+		(len (length str))
+		(buff (cdr val)))
+	   (declare (simple-string str))
+	   (format f "Text~@[ from buffer ~A~]~%   ~A~:[~;...~]~%"
+		   (if buff (buffer-name buff))
+		   (subseq str 0 (if nl (min 61 len nl) (min 61 len)))
+		   (> len 60))))))))
+
+(defcommand "Put Register" (p)
+  "Copies a region into a register.  Prompts for register name."
+  "Copies a region into a register.  Prompts for register name."
+  (declare (ignore p))
+  (let ((region (current-region)))
+    ;; Bind the region before prompting in case the region isn't active.
+    (setf (register-value (prompt-for-register))
+	  (cons (copy-region region) (current-buffer)))))
+
+(defcommand "Get Register" (p)
+  "Copies a region from a register to the current point."
+  "Copies a region from a register to the current point."
+  (declare (ignore p))
+  (let* ((reg-name (prompt-for-register "Register from which to get text: " t))
+	 (val (register-value reg-name)))
+    (unless (and (consp val) (regionp (car val)))
+      (editor-error "Register ~A does not hold a region." reg-name))
+    (let ((point (current-point)))
+      (push-new-buffer-mark point)
+      (insert-region point (car val))))
+  (setf (last-command-type) :ephemerally-active))
Index: /branches/new-random/cocoa-ide/hemlock/src/ring.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/ring.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/ring.lisp	(revision 13309)
@@ -0,0 +1,217 @@
+;;; -*- Log: Hemlock.Log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Rob MacLachlan
+;;;
+;;;  This file defines a ring-buffer type and access functions.
+;;;
+(in-package :hemlock-internals)
+
+(defun %print-hring (obj stream depth)
+  (declare (ignore depth obj))
+  (write-string "#<Hemlock Ring>" stream))
+
+;;;; The ring data structure:
+;;;
+;;;    An empty ring is indicated by an negative First value.
+;;; The Bound is made (1- (- Size)) to make length work.  Things are
+;;; pushed at high indices first.
+;;;
+(defstruct (ring (:predicate ringp)
+		 (:constructor internal-make-ring)
+		 (:print-function %print-hring))
+  "Used with Ring-Push and friends to implement ring buffers."
+  (first -1 :type fixnum)	   ;The index of the first position used.
+  (bound -1 :type fixnum)          ;The index after the last element.
+  delete-function                  ;The function  to be called on deletion. 
+  (vector #() :type simple-vector) ;The vector.
+  (lock (ccl:make-lock)))
+                         
+(defmacro with-ring-locked ((ring) &body body)
+  `(ccl:with-lock-grabbed ((ring-lock ,ring))
+    ,@body))
+
+;;; make-ring  --  Public
+;;;
+;;;    Make a new empty ring with some maximum size and type.
+;;;
+(defun make-ring (size &optional (delete-function #'identity))
+  "Make a ring-buffer which can hold up to Size objects.  Delete-Function
+  is a function which is called with each object that falls off the
+  end."
+  (unless (and (fixnump size) (> size 0))
+    (error "Ring size, ~S is not a positive fixnum." size))
+  (internal-make-ring :delete-function delete-function
+		      :vector (make-array size)
+		      :bound  (1- (- size))))
+
+
+;;; ring-push  --  Public
+;;;
+;;;    Decrement first modulo the maximum size, delete any old
+;;; element, and add the new one.
+;;;
+(defun ring-push (object ring)
+  "Push an object into a ring, deleting an element if necessary."
+  (with-ring-locked (ring)
+    (let ((first (ring-first ring))
+          (vec (ring-vector ring))
+          (victim 0))
+      (declare (simple-vector vec) (fixnum first victim))
+      (cond
+        ;; If zero, wrap around to end.
+        ((zerop first)
+         (setq victim (1- (length vec))))
+        ;; If empty then fix up pointers.
+        ((minusp first)
+         (setf (ring-bound ring) 0)
+         (setq victim (1- (length vec))))
+        (t
+         (setq victim (1- first))))
+      (when (= first (ring-bound ring))
+        (funcall (ring-delete-function ring) (aref vec victim))
+        (setf (ring-bound ring) victim))
+      (setf (ring-first ring) victim)
+      (setf (aref vec victim) object))))
+
+
+;;; ring-pop  --  Public
+;;;
+;;;    Increment first modulo the maximum size.
+;;;
+(defun ring-pop (ring)
+  "Pop an object from a ring and return it."
+  (with-ring-locked (ring)
+    (let* ((first (ring-first ring))
+           (vec (ring-vector ring))
+           (new (if (= first (1- (length vec))) 0 (1+ first)))
+           (bound (ring-bound ring)))
+      (declare (fixnum first new bound) (simple-vector vec))
+      (cond
+        ((minusp bound)
+         (error "Cannot pop from an empty ring."))
+        ((= new bound)
+         (setf (ring-first ring) -1  (ring-bound ring) (1- (- (length vec)))))
+        (t
+         (setf (ring-first ring) new)))
+      (shiftf (aref vec first) nil))))
+
+
+;;; ring-length  --  Public
+;;;
+;;;    Return the current and maximum size.
+;;;
+(defun ring-length (ring)
+  "Return as values the current and maximum size of a ring."
+  (with-ring-locked (ring)
+    (let ((diff (- (ring-bound ring) (ring-first ring)))
+          (max (length (ring-vector ring))))
+      (declare (fixnum diff max))
+      (values (if (plusp diff) diff (+ max diff)) max))))
+
+
+;;; ring-ref  --  Public
+;;;
+;;;    Do modulo arithmetic to find the correct element.
+;;;
+(defun ring-ref (ring index)
+  (declare (fixnum index))
+  "Return the index'th element of a ring.  This can be set with Setf."
+  (with-ring-locked (ring)
+    (let ((first (ring-first ring)))
+      (declare (fixnum first))
+      (cond
+        ((and (zerop index) (not (minusp first)))
+         (aref (ring-vector ring) first))
+        (t
+         (let* ((diff (- (ring-bound ring) first))
+                (sum (+ first index))
+                (vec (ring-vector ring))
+                (max (length vec)))
+           (declare (fixnum diff max sum) (simple-vector vec))
+           (when (or (>= index (if (plusp diff) diff (+ max diff)))
+                     (minusp index))
+             (error "Ring index ~D out of bounds." index))
+           (aref vec (if (>= sum max) (- sum max) sum))))))))
+
+
+;;; %set-ring-ref  --  Internal
+;;;
+;;;    Setf form for ring-ref, set a ring element.
+;;;
+(defun %set-ring-ref (ring index value)
+  (declare (fixnum index))
+  (with-ring-locked (ring)
+    (let* ((first (ring-first ring))
+           (diff (- (ring-bound ring) first))
+           (sum (+ first index))
+           (vec (ring-vector ring))
+           (max (length vec)))
+      (declare (fixnum diff first max) (simple-vector vec))
+      (when (or (>= index (if (plusp diff) diff (+ max diff))) (minusp index))
+        (error "Ring index ~D out of bounds." index))
+      (setf (aref vec (if (>= sum max) (- sum max) sum)) value))))
+
+
+(eval-when (:compile-toplevel :execute)
+(defmacro 1+m (exp base)
+  `(if (= ,exp ,base) 0 (1+ ,exp)))
+(defmacro 1-m (exp base)
+  `(if (zerop ,exp) ,base (1- ,exp)))
+) ;eval-when (:compile-toplevel :execute)
+
+;;; rotate-ring  --  Public
+;;;
+;;;    Rotate a ring, blt'ing elements as necessary.
+;;;
+(defun rotate-ring (ring offset)
+  "Rotate a ring forward, i.e. second -> first, with positive offset,
+  or backwards with negative offset."
+  (declare (fixnum offset))
+  (with-ring-locked (ring)
+    (let* ((first (ring-first ring))
+           (bound (ring-bound ring))
+           (vec (ring-vector ring))
+           (max (length vec)))
+      (declare (fixnum first bound max) (simple-vector vec))
+      (cond
+        ((= first bound)
+         (let ((new (rem (+ offset first) max)))
+           (declare (fixnum new))
+           (if (minusp new) (setq new (+ new max)))
+           (setf (ring-first ring) new)
+           (setf (ring-bound ring) new)))
+        ((not (minusp first))
+         (let* ((diff (- bound first))
+                (1-max (1- max))
+                (length (if (plusp diff) diff (+ max diff)))
+                (off (rem offset length)))
+           (declare (fixnum diff length off 1-max))
+           (cond
+             ((minusp offset)
+              (do ((dst (1-m first 1-max) (1-m dst 1-max))
+                   (src (1-m bound 1-max) (1-m src 1-max))
+                   (cnt off (1+ cnt)))
+                  ((zerop cnt)
+                   (setf (ring-first ring) (1+m dst 1-max))
+                   (setf (ring-bound ring) (1+m src 1-max)))
+                (declare (fixnum dst src cnt))
+                (shiftf (aref vec dst) (aref vec src) nil)))
+             (t
+              (do ((dst bound (1+m dst 1-max))
+                   (src first (1+m src 1-max))
+                   (cnt off (1- cnt)))
+                  ((zerop cnt)
+                   (setf (ring-first ring) src)
+                   (setf (ring-bound ring) dst))
+                (declare (fixnum dst src cnt))
+                (shiftf (aref vec dst) (aref vec src) nil)))))))))
+  ring)
Index: /branches/new-random/cocoa-ide/hemlock/src/rompsite.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/rompsite.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/rompsite.lisp	(revision 13309)
@@ -0,0 +1,160 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU
+(ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; "Site dependent" stuff for the editor while on the IBM RT PC machine.
+;;;
+
+(in-package :hi)
+
+;;; SITE-INIT  --  Internal
+;;;
+;;;    This function is called at init time to set up any site stuff.
+;;;
+(defun site-init ()
+  (defhvar "Beep Border Width"
+    "Width in pixels of the border area inverted by beep."
+    :value 20)
+  (defhvar "Default Window Width"
+    "This is used to make a window when prompting the user.  The value is in
+     characters."
+    :value 80)
+  (defhvar "Default Window Height"
+    "This is used to make a window when prompting the user.  The value is in
+     characters."
+    :value 24)
+  (defhvar "Default Initial Window Width"
+    "This is used when Hemlock first starts up to make its first window.
+     The value is in characters."
+    :value 80)
+  (defhvar "Default Initial Window Height"
+    "This is used when Hemlock first starts up to make its first window.
+     The value is in characters."
+    :value 24)
+  (defhvar "Default Initial Window X"
+    "This is used when Hemlock first starts up to make its first window.
+     The value is in pixels."
+    :value nil)
+  (defhvar "Default Initial Window Y"
+    "This is used when Hemlock first starts up to make its first window.
+     The value is in pixels."
+    :value nil)
+  (defhvar "Bell Style"
+    "This controls what beeps do in Hemlock.  Acceptable values are :border-flash
+     (which is the default), :feep, :border-flash-and-feep, :flash,
+     :flash-and-feep, and NIL (do nothing)."
+    :value :border-flash)
+  (defhvar "Reverse Video"
+    "Paints white on black in window bodies, black on white in modelines."
+    :value nil)
+  (defhvar "Default Font"
+    "The string name of the font to be used for Hemlock -- buffer text,
+     modelines, random typeout, etc.  The font is loaded when initializing
+     Hemlock."
+    :value "*-courier-medium-r-normal--*-120-*")
+  (defhvar "Active Region Highlighting Font"
+    "The string name of the font to be used for highlighting active regions.
+     The font is loaded when initializing Hemlock."
+    :value "*-courier-medium-o-normal--*-120-*")
+  (defhvar "Open Paren Highlighting Font"
+    "The string name of the font to be used for highlighting open parens.
+     The font is loaded when initializing Hemlock."
+    :value "*-courier-bold-r-normal--*-120-*")
+  (defhvar "Thumb Bar Meter"
+    "When non-nil (the default), windows will be created to be displayed with
+     a ruler in the bottom border of the window."
+    :value t)
+  nil)
+
+
+
+;;;; Some generally useful file-system functions.
+
+;;; MERGE-RELATIVE-PATHNAMES takes a pathname that is either absolute or
+;;; relative to default-dir, merging it as appropriate and returning a definite
+;;; directory pathname.
+;;;
+;;; This function isn't really needed anymore now that merge-pathnames does
+;;; this, but the semantics are slightly different.  So it's easier to just
+;;; keep this around instead of changing all the uses of it.
+;;; 
+(defun merge-relative-pathnames (pathname default-directory)
+  "Merges pathname with default-directory.  If pathname is not absolute, it
+   is assumed to be relative to default-directory.  The result is always a
+   directory."
+  (let ((pathname (merge-pathnames pathname default-directory)))
+    (if (ccl:directory-pathname-p pathname)
+	pathname
+	(pathname (concatenate 'simple-string
+			       (namestring pathname)
+			       "/")))))
+
+
+;;;; I/O specials and initialization
+
+;;; File descriptor for the terminal.
+;;; 
+(defvar *editor-file-descriptor*)
+
+(declaim (special *editor-input* *real-editor-input*))
+
+(declaim (declaration values))
+
+;;; font-map-size should be defined in font.lisp, but SETUP-FONT-FAMILY would
+;;; assume it to be special, issuing a nasty warning.
+;;;
+(defconstant font-map-size 32)
+
+
+
+;;;; HEMLOCK-BEEP.
+
+(defvar *beep-function* #'(lambda () (print "BEEP!")))
+
+(defun beep (&optional (stream *terminal-io*))
+  (funcall *beep-function* stream))
+
+
+
+;;;; Line Wrap Char.
+
+(defvar *line-wrap-char* #\!
+  "The character to be displayed to indicate wrapped lines.")
+
+
+(defvar *editor-describe-stream*
+  #+CMU (system:make-indenting-stream *standard-output*)
+  #-CMU *standard-output*)
+
+;;; EDITOR-DESCRIBE-FUNCTION has to mess around to get indenting streams to
+;;; work.  These apparently work fine for DESCRIBE, for which they were defined,
+;;; but not in general.  It seems they don't indent initial text, only that
+;;; following a newline, so inside our use of INDENTING-FURTHER, we need some
+;;; form before the WRITE-STRING.  To get this to work, I had to remove the ~%
+;;; from the FORMAT string, and use FRESH-LINE; simply using FRESH-LINE with
+;;; the ~% caused an extra blank line.  Possibly I should not have glommed onto
+;;; this hack whose interface comes from three different packages, but it did
+;;; the right thing ....
+;;;
+;;; Also, we have set INDENTING-STREAM-STREAM to make sure the indenting stream
+;;; is based on whatever *standard-output* is when we are called.
+;;;
+(defun editor-describe-function (fun sym)
+  "Calls DESCRIBE on fun.  If fun is compiled, and its original name is not sym,
+   then this also outputs any 'function documentation for sym to
+   *standard-output*."
+  (declare (ignorable sym))
+  (describe fun)
+  (let ((doc (documentation sym 'function)))
+    (when doc
+      (format *standard-output* "~%Function documentation for ~S:~&~%" sym)
+      	  (write-string doc *standard-output*))))
+
Index: /branches/new-random/cocoa-ide/hemlock/src/search1.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/search1.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/search1.lisp	(revision 13309)
@@ -0,0 +1,687 @@
+;;; -*- Log: Hemlock.Log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Searching and replacing functions for Hemlock.
+;;; Originally written by Skef Wholey, Rewritten by Rob MacLachlan.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;; The search pattern structure is used only by simple searches, more
+;;; complex ones make structures which include it.
+
+(defstruct (search-pattern (:print-function %print-search-pattern)
+			   (:constructor internal-make-search-pattern))
+  kind			      ; The kind of pattern to search for.
+  direction		      ; The direction to search in.
+  pattern		      ; The search pattern to use.
+  search-function	      ; The function to call to search.
+  reclaim-function)	      ; The function to call to reclaim this pattern.
+
+(setf (documentation 'search-pattern-p 'function)
+  "Returns true if its argument is a Hemlock search-pattern object,
+  Nil otherwise.")
+
+(defun %print-search-pattern (object stream depth)
+  (let ((*print-level* (and *print-level* (- *print-level* depth)))
+	(*print-case* :downcase))
+    (declare (special *print-level* *print-case*))
+    (write-string "#<Hemlock " stream)
+    (princ (search-pattern-direction object) stream)
+    (write-char #\space stream)
+    (princ (search-pattern-kind object) stream)
+    (write-string " Search-Pattern for ")
+    (prin1 (search-pattern-pattern object) stream)
+    (write-char #\> stream)
+    (terpri stream)))
+
+(defvar *search-pattern-experts* (make-hash-table :test #'eq)
+  "Holds an eq hashtable which associates search kinds with the functions
+  that know how to make patterns of that kind.")
+(defvar *search-pattern-documentation* ()
+  "A list of all the kinds of search-pattern that are defined.")
+
+;;; define-search-kind  --  Internal
+;;;
+;;;    This macro is used to define a new kind of search pattern.  Kind
+;;; is the kind of search pattern to define.  Lambda-list is the argument 
+;;; list for the expert-function to be built and forms it's body.
+;;; The arguments passed are the direction, the pattern, and either
+;;; an old search-pattern of the same type or nil.  Documentation
+;;; is put on the search-pattern-documentation property of the kind
+;;; keyword.
+;;;
+(defmacro define-search-kind (kind lambda-list documentation &body forms)
+  `(progn
+     (push ,documentation *search-pattern-documentation*)
+     (setf (gethash ,kind *search-pattern-experts*)
+           #'(lambda ,lambda-list ,@forms))))
+
+
+;;; new-search-pattern  --  Public
+;;;
+;;;    This function deallocates any old search-pattern and then dispatches
+;;; to the correct expert.
+;;;
+(defun new-search-pattern (kind direction pattern &optional
+				result-search-pattern)
+  "Makes a new Hemlock search pattern of kind Kind to search direction
+  using Pattern.  Direction is either :backward or :forward.
+  If supplied, result-search-pattern is a pattern to destroy to make
+  the new one.  The variable *search-pattern-documentation* contains
+  documentation for each kind."
+  (unless (or (eq direction :forward) (eq direction :backward))
+    (error "~S is not a legal search direction." direction))
+  (when result-search-pattern
+    (funcall (search-pattern-reclaim-function result-search-pattern)
+	     result-search-pattern)
+    (unless (eq kind (search-pattern-kind result-search-pattern))
+      (setq result-search-pattern nil)))
+  (let ((expert (gethash kind *search-pattern-experts*)))
+    (unless expert
+      (error "~S is not a defined search pattern kind." kind))
+    (funcall expert direction pattern result-search-pattern)))
+
+(defun new-search-vector (vec access-fn)
+  (let* ((max 0))
+    (declare (fixnum max))
+    (dotimes (i (length vec))
+      (let* ((code (funcall access-fn vec i)))
+        (when (> code max)
+          (setq max code))))
+    (make-array (the fixnum (1+ max)))))
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro dispose-search-vector (vec)
+  vec)
+); eval-when (:compile-toplevel :execute)
+
+
+;;;; macros used by various search kinds:
+
+;;; search-once-forward-macro  --  Internal
+;;;
+;;;    Passes search-fun strings, starts and lengths to do a forward
+;;; search.  The other-args are passed through to the searching
+;;; function after after everything else  The search-fun is
+;;; expected to return NIL if nothing is found, or it index where the
+;;; match ocurred.  Something non-nil is returned if something is
+;;; found and line and start are set to where it was found.
+;;;
+(defmacro search-once-forward-macro (line start search-fun &rest other-args)
+  `(do* ((l ,line)
+	 (chars (line-chars l) (line-chars l))
+	 (len (length chars) (length chars))
+	 (start-pos ,start 0)
+	 (index 0))
+	(())
+     (declare (simple-string chars) (fixnum start-pos len)
+	      (type (or fixnum null) index))
+     (setq index (,search-fun chars start-pos len ,@other-args))
+     (when index
+       (setq ,start index  ,line l)
+       (return t))
+     (setq l (line-next l))
+     (when (null l) (return nil))))
+
+
+;;; search-once-backward-macro  --  Internal
+;;;
+;;;    Like search-once-forward-macro, except it goes backwards.  Length
+;;; is not passed to the search function, since it won't need it.
+;;;
+(defmacro search-once-backward-macro (line start search-fun &rest other-args)
+  `(do* ((l ,line)
+	 (chars (line-chars l) (line-chars l))
+	 (start-pos (1- ,start) (1- (length chars)))
+	 (index 0))
+	(())
+     (declare (simple-string chars) (fixnum start-pos)
+	      (type (or fixnum null) index))
+     (setq index (,search-fun chars start-pos ,@other-args))
+     (when index
+       (setq ,start index  ,line l)
+       (return t))
+     (setq l (line-previous l))
+     (when (null l) (return nil))))
+
+
+
+;;;; String Searches.
+;;;
+;;; We use the Boyer-Moore algorithm for string searches.
+;;;
+
+;;; sensitive-string-search-macro  --  Internal
+;;;
+;;;    This macro does a case-sensitive Boyer-Moore string search.
+;;;
+;;; Args:
+;;;    String - The string to search in.
+;;;    Start - The place to start searching at.
+;;;    Length - NIL if going backward, the length of String if going forward.
+;;;    Pattern - A simple-vector of characters.  A simple-vector is used 
+;;; rather than a string because it is believed that simple-vector access
+;;; will be faster in most implementations.
+;;;    Patlen - The length of Pattern.
+;;;    Last - (1- Patlen)
+;;;    Jumps - The jump vector as given by compute-boyer-moore-jumps
+;;;    +/- - The function to increment with, either + (forward) or -
+;;; (backward)
+;;;    -/+ - Like +/-, only the other way around.
+(eval-when (:compile-toplevel :execute)
+(defmacro sensitive-string-search-macro (string start length pattern patlen
+						last jumps +/- -/+)
+  (let* ((jumpslen (gensym))
+         (charcode (gensym)))
+  `(do ((scan (,+/- ,start ,last))
+        (,jumpslen (length ,jumps))
+	(patp ,last))
+       (,(if length `(>= scan ,length) '(minusp scan)))
+     (declare (fixnum scan patp))
+     (let ((char (schar ,string scan)))
+       (cond
+	((char= char (svref ,pattern patp))
+	 (if (zerop patp)
+	     (return scan)
+	     (setq scan (,-/+ scan 1)  patp (1- patp))))
+	(t
+	 ;; If mismatch consult jump table to find amount to skip.
+	 (let* ((,charcode (search-char-code char))
+                (jump (if (< ,charcode ,jumpslen)
+                        (svref ,jumps ,charcode)
+                        ,patlen)))
+	   (declare (fixnum jump))
+	   (if (> jump (- ,patlen patp))
+	       (setq scan (,+/- scan jump))
+	       (setq scan (,+/- scan (- ,patlen patp)))))
+	 (setq patp ,last)))))))
+
+
+;;; insensitive-string-search-macro  --  Internal
+;;;
+;;;    This macro is very similar to the case sensitive one, except that
+;;; we do the search for a hashed string, and then when we find a match
+;;; we compare the uppercased search string with the found string uppercased
+;;; and only say we win when they match too.
+;;;
+(defmacro insensitive-string-search-macro (string start length pattern
+						  folded-string patlen last
+						  jumps  +/- -/+)
+  (let* ((jumpslen (gensym)))
+    `(do ((scan (,+/- ,start ,last))
+          (,jumpslen (length ,jumps))
+          (patp ,last))
+      (,(if length `(>= scan ,length) '(minusp scan)))
+      (declare (fixnum scan patp))
+      (let ((hash (search-hash-code (schar ,string scan))))
+        (declare (fixnum hash))
+        (cond
+          ((= hash (the fixnum (svref ,pattern patp)))
+           (if (zerop patp)
+	     (if (do ((i ,last (1- i)))
+		     (())
+		   (when (char/=
+			  (search-char-upcase (schar ,string (,+/- scan i)))
+			  (schar ,folded-string i))
+		     (return nil))
+		   (when (zerop i) (return t)))
+               (return scan)
+               (setq scan (,+/- scan ,patlen)  patp ,last))
+	     (setq scan (,-/+ scan 1)  patp (1- patp))))
+          (t
+           ;; If mismatch consult jump table to find amount to skip.
+           (let ((jump (if (< hash ,jumpslen)
+                         (svref ,jumps hash)
+                         ,patlen)))
+             (declare (fixnum jump))
+             (if (> jump (- ,patlen patp))
+	       (setq scan (,+/- scan jump))
+	       (setq scan (,+/- scan (- ,patlen patp)))))
+           (setq patp ,last)))))))
+
+
+;;;; Searching for strings with newlines in them:
+;;;
+;;;    Due to the buffer representation, search-strings with embedded 
+;;; newlines need to be special-cased.  What we do is break
+;;; the search string up into lines and then searching for a line with
+;;; the correct prefix.  This is actually a faster search.
+;;; For this one we just have one big hairy macro conditionalized for
+;;; both case-sensitivity and direction.  Have fun!!
+
+;;; newline-search-macro  --  Internal
+;;;
+;;;    Do a search for a string containing newlines.  Line is the line
+;;; to start on, and Start is the position to start at.  Pattern and
+;;; optionally Pattern2, are simple-vectors of things that represent
+;;; each line in the pattern, and are passed to Test-Fun.  Pattern
+;;; must contain simple-strings so we can take the length.  Test-Fun is a
+;;; thing to compare two strings and see if they are equal.  Forward-p
+;;; tells whether to go forward or backward.
+;;;
+(defmacro newline-search-macro (line start test-fun pattern forward-p
+				     &optional pattern2)
+  `(let* ((patlen (length ,pattern))
+	  (first (svref ,pattern 0))
+	  (firstlen (length first))
+	  (l ,line)
+	  (chars (line-chars l))
+	  (len (length chars))
+	  ,@(if pattern2 `((other (svref ,pattern2 0)))))
+     (declare (simple-string first chars) (fixnum firstlen patlen len))
+     ,(if forward-p
+	  ;; If doing a forward search, go to the next line if we could not
+	  ;; match due to the start position.
+	  `(when (< (- len ,start) firstlen)
+	     (setq l (line-next l)))
+	  ;; If doing a backward search, go to the previous line if the current
+	  ;; line could not match the last line in the pattern, and then go
+	  ;; back the 1- number of lines in the pattern to avoid a possible
+	  ;; match across the starting point.
+	  `(let ((1-len (1- patlen)))
+	     (declare (fixnum 1-len))
+	     (when (< ,start (length (the simple-string
+					  (svref ,pattern 1-len))))
+	       (setq l (line-previous l)))
+	     (dotimes (i 1-len)
+	       (when (null l) (return nil))
+	       (setq l (line-previous l)))))
+     (do* ()
+	  ((null l))
+       (setq chars (line-chars l)  len (length chars))
+       ;; If the end of this line is the first line in the pattern then check
+       ;; to see if the other lines match.
+       (when (and (>= len firstlen)
+		  (,test-fun chars first other
+			     :start1 (- len firstlen) :end1 len
+			     :end2 firstlen))
+	 (when
+	  (do ((m (line-next l) (line-next m))
+	       (i 2 (1+ i))
+	       (next (svref ,pattern 1) (svref ,pattern i))
+	       ,@(if pattern2
+		     `((another (svref ,pattern2 1)
+				(svref ,pattern2 i))))
+	       (len 0)
+	       (nextlen 0)
+	       (chars ""))
+	      ((null m))
+	    (declare (simple-string next chars) (fixnum len nextlen i))
+	    (setq chars (line-chars m)  nextlen (length next)
+		  len (length chars))
+	    ;; When on last line of pattern, check if prefix of line.
+	    (when (= i patlen)
+	      (return (and (>= len nextlen)
+			   (,test-fun chars next another :end1 nextlen
+				      :end2 nextlen))))
+	    (unless (,test-fun chars next another :end1 len
+			       :end2 nextlen)
+	      (return nil)))
+	  (setq ,line l  ,start (- len firstlen))
+	  (return t)))
+       ;; If not, try the next line
+       (setq l ,(if forward-p '(line-next l) '(line-previous l))))))
+
+
+;;;; String-comparison macros that are passed to newline-search-macro
+
+;;; case-sensitive-test-fun  --  Internal
+;;;
+;;;    Just thows away the extra arg and calls string=.
+;;;
+(defmacro case-sensitive-test-fun (string1 string2 ignore &rest keys)
+  (declare (ignore ignore))
+  `(string= ,string1 ,string2 ,@keys))
+
+;;; case-insensitive-test-fun  --  Internal
+;;;
+;;;    First compare the characters hashed with hashed-string2 and then
+;;; only if they agree do an actual compare with case-folding.
+;;;
+(defmacro case-insensitive-test-fun (string1 string2 hashed-string2
+					     &key end1 (start1 0) end2)
+  `(when (= (- ,end1 ,start1) ,end2)
+     (do ((i 0 (1+ i)))
+	 ((= i ,end2)
+	  (dotimes (i ,end2 t)
+	    (when (char/= (search-char-upcase (schar ,string1 (+ ,start1 i)))
+			  (schar ,string2 i))
+	      (return nil))))
+       (when (/= (search-hash-code (schar ,string1 (+ ,start1 i)))
+		 (svref ,hashed-string2 i))
+	 (return nil)))))
+); eval-when (:compile-toplevel :execute)
+
+
+;;; compute-boyer-moore-jumps  --  Internal
+;;;
+;;;    Compute return a jump-vector to do a Boyer-Moore search for 
+;;; the "string" of things in Vector.  Access-fun is a function
+;;; that aref's vector and returns a number.
+;;;
+(defun compute-boyer-moore-jumps (vec access-fun)
+  (declare (simple-vector vec))
+  (let ((jumps (new-search-vector vec access-fun))
+	(len (length vec)))
+    (declare (simple-vector jumps))
+    (when (zerop len) (editor-error "Zero length search string not allowed."))
+    ;; The default jump is the length of the search string.
+    (dotimes (i len)
+      (setf (aref jumps i) len))
+    ;; For chars in the string the jump is the distance from the end.
+    (dotimes (i len)
+      (setf (aref jumps (funcall access-fun vec i)) (- len i 1)))
+    jumps))
+
+
+;;;; Case insensitive searches
+
+;;; In order to avoid case folding, we do a case-insensitive hash of
+;;; each character.  We then search for string in this translated
+;;; character set, and reject false successes by checking of the found
+;;; string is string-equal the the original search string.
+;;;
+
+(defstruct (string-insensitive-search-pattern
+	    (:include search-pattern)
+	    (:conc-name string-insensitive-)
+	    (:print-function %print-search-pattern))
+  jumps
+  hashed-string
+  folded-string)
+
+;;;  Search-Hash-String  --  Internal
+;;;
+;;;    Return a simple-vector containing the search-hash-codes of the
+;;; characters in String.
+;;;
+(defun search-hash-string (string)
+  (declare (simple-string string))
+  (let* ((len (length string))
+	 (result (make-array len)))
+    (declare (fixnum len) (simple-vector result))
+    (dotimes (i len result)
+      (setf (aref result i) (search-hash-code (schar string i))))))
+
+;;; make-insensitive-newline-pattern  -- Internal
+;;;
+;;;    Make bash in fields in a string-insensitive-search-pattern to
+;;; do a search for a string with newlines in it.
+;;;
+(defun make-insensitive-newline-pattern (pattern folded-string)
+  (declare (simple-string folded-string))
+  (let* ((len (length folded-string))
+	 (num (1+ (count #\newline folded-string :end len)))
+	 (hashed (make-array num))
+	 (folded (make-array num)))
+    (declare (simple-vector hashed folded) (fixnum len num))
+    (do ((prev 0 nl)
+	 (i 0 (1+ i))
+	 (nl (position #\newline folded-string :end len)
+	     (position #\newline folded-string :start nl  :end len)))
+	((null nl)
+	 (let ((piece (subseq folded-string prev len)))
+	   (setf (aref folded i) piece)
+	   (setf (aref hashed i) (search-hash-string piece))))
+      (let ((piece (subseq folded-string prev nl)))
+	(setf (aref folded i) piece)
+	(setf (aref hashed i) (search-hash-string piece)))
+      (incf nl))
+    (setf (string-insensitive-folded-string pattern) folded
+	  (string-insensitive-hashed-string pattern) hashed)))
+
+
+
+(define-search-kind :string-insensitive (direction pattern old)
+  ":string-insensitive - Pattern is a string to do a case-insensitive
+  search for."
+  (unless old (setq old (make-string-insensitive-search-pattern)))
+  (setf (search-pattern-kind old) :string-insensitive
+	(search-pattern-direction old) direction
+	(search-pattern-pattern old) pattern)
+  (let* ((folded-string (string-upcase pattern)))
+    (declare (simple-string folded-string))
+    (cond
+     ((find #\newline folded-string)
+      (make-insensitive-newline-pattern old folded-string)
+      (setf (search-pattern-search-function old)
+	    (if (eq direction :forward)
+		#'insensitive-find-newline-once-forward-method
+		#'insensitive-find-newline-once-backward-method))
+      (setf (search-pattern-reclaim-function old) #'identity))
+     (t
+      (case direction
+	(:forward
+	 (setf (search-pattern-search-function old)
+	       #'insensitive-find-string-once-forward-method))
+	(t
+	 (setf (search-pattern-search-function old)
+	       #'insensitive-find-string-once-backward-method)
+	 (setq folded-string (nreverse folded-string))))
+      (let ((hashed-string (search-hash-string folded-string)))
+	(setf (string-insensitive-hashed-string old) hashed-string
+	      (string-insensitive-folded-string old) folded-string)
+	(setf (string-insensitive-jumps old)
+	      (compute-boyer-moore-jumps hashed-string #'svref))
+	(setf (search-pattern-reclaim-function old)
+	      #'(lambda (p)
+		  (dispose-search-vector (string-insensitive-jumps p))))))))
+  old)
+
+
+(defun insensitive-find-string-once-forward-method (pattern line start)
+  (let* ((hashed-string (string-insensitive-hashed-string pattern))
+	 (folded-string (string-insensitive-folded-string pattern))
+	 (jumps (string-insensitive-jumps pattern))
+	 (patlen (length hashed-string))
+	 (last (1- patlen)))
+    (declare (simple-vector jumps hashed-string) (simple-string folded-string)
+	     (fixnum patlen last))
+    (when (search-once-forward-macro
+	   line start insensitive-string-search-macro
+	   hashed-string folded-string patlen last jumps + -)
+      (values line start patlen))))
+
+(defun insensitive-find-string-once-backward-method (pattern line start)
+  (let* ((hashed-string (string-insensitive-hashed-string pattern))
+	 (folded-string (string-insensitive-folded-string pattern))
+	 (jumps (string-insensitive-jumps pattern))
+	 (patlen (length hashed-string))
+	 (last (1- patlen)))
+    (declare (simple-vector jumps hashed-string) (simple-string folded-string)
+	     (fixnum patlen last))
+    (when (search-once-backward-macro
+	   line start insensitive-string-search-macro
+	   nil hashed-string folded-string patlen last jumps - +)
+      (values line (- start last) patlen))))
+
+(eval-when (:compile-toplevel :execute)
+(defmacro def-insensitive-newline-search-method (name direction)
+  `(defun ,name (pattern line start)
+     (let* ((hashed (string-insensitive-hashed-string pattern))
+	    (folded-string (string-insensitive-folded-string pattern))
+	    (patlen (length (the string (search-pattern-pattern pattern)))))
+       (declare (simple-vector hashed folded-string))
+       (when (newline-search-macro line start case-insensitive-test-fun
+				   folded-string ,direction hashed)
+	 (values line start patlen)))))
+); eval-when (:compile-toplevel :execute)
+
+(def-insensitive-newline-search-method
+  insensitive-find-newline-once-forward-method t)
+(def-insensitive-newline-search-method
+  insensitive-find-newline-once-backward-method nil)
+
+
+;;;; And Snore, case sensitive.
+;;;
+;;;    This is horribly repetitive, but if I introduce another level of
+;;; macroexpansion I will go Insaaaane....
+;;;
+(defstruct (string-sensitive-search-pattern
+	    (:include search-pattern)
+	    (:conc-name string-sensitive-)
+	    (:print-function %print-search-pattern))
+  string
+  jumps)
+
+;;; make-sensitive-newline-pattern  -- Internal
+;;;
+;;;    The same, only more sensitive (it hurts when you do that...)
+;;;
+(defun make-sensitive-newline-pattern (pattern string)
+  (declare (simple-vector string))
+  (let* ((string (coerce string 'simple-string))
+	 (len (length string))
+	 (num (1+ (count #\newline string :end len)))
+	 (sliced (make-array num)))
+    (declare (simple-string string) (simple-vector sliced) (fixnum len num))
+    (do ((prev 0 nl)
+	 (i 0 (1+ i))
+	 (nl (position #\newline string :end len)
+	     (position #\newline string :start nl  :end len)))
+	((null nl)
+	 (setf (aref sliced i) (subseq string prev len)))
+      (setf (aref sliced i) (subseq string prev nl))
+      (incf nl))
+    (setf (string-sensitive-string pattern) sliced)))
+
+
+
+(define-search-kind :string-sensitive (direction pattern old)
+  ":string-sensitive - Pattern is a string to do a case-sensitive
+  search for."
+  (unless old (setq old (make-string-sensitive-search-pattern)))
+  (setf (search-pattern-kind old) :string-sensitive
+	(search-pattern-direction old) direction
+	(search-pattern-pattern old) pattern)
+  (let* ((string (coerce pattern 'simple-vector)))
+    (declare (simple-vector string))
+    (cond
+     ((find #\newline string)
+      (make-sensitive-newline-pattern old string)
+      (setf (search-pattern-search-function old)
+	    (if (eq direction :forward)
+		#'sensitive-find-newline-once-forward-method
+		#'sensitive-find-newline-once-backward-method))
+      (setf (search-pattern-reclaim-function old) #'identity))
+     (t
+      (case direction
+	(:forward
+	 (setf (search-pattern-search-function old)
+	       #'sensitive-find-string-once-forward-method))
+	(t
+	 (setf (search-pattern-search-function old)
+	       #'sensitive-find-string-once-backward-method)
+	 (setq string (nreverse string))))
+      (setf (string-sensitive-string old) string)
+      (setf (string-sensitive-jumps old)
+	    (compute-boyer-moore-jumps
+	     string #'(lambda (v i) (char-code (svref v i)))))
+      (setf (search-pattern-reclaim-function old)
+	    #'(lambda (p)
+		(dispose-search-vector (string-sensitive-jumps p)))))))
+  old)
+
+
+
+(defun sensitive-find-string-once-forward-method (pattern line start)
+  (let* ((string (string-sensitive-string pattern))
+	 (jumps (string-sensitive-jumps pattern))
+	 (patlen (length string))
+	 (last (1- patlen)))
+    (declare (simple-vector jumps string) (fixnum patlen last))
+    (when (search-once-forward-macro
+	   line start sensitive-string-search-macro
+	   string patlen last jumps + -)
+      (values line start patlen))))
+
+(defun sensitive-find-string-once-backward-method (pattern line start)
+  (let* ((string (string-sensitive-string pattern))
+	 (jumps (string-sensitive-jumps pattern))
+	 (patlen (length string))
+	 (last (1- patlen)))
+    (declare (simple-vector jumps string) (fixnum patlen last))
+    (when (search-once-backward-macro
+	   line start sensitive-string-search-macro
+	   nil string patlen last jumps - +)
+      (values line (- start last) patlen))))
+
+(eval-when (:compile-toplevel :execute)
+(defmacro def-sensitive-newline-search-method (name direction)
+  `(defun ,name (pattern line start)
+     (let* ((string (string-sensitive-string pattern))
+	    (patlen (length (the string (search-pattern-pattern pattern)))))
+       (declare (simple-vector string))
+       (when (newline-search-macro line start case-sensitive-test-fun
+				   string ,direction)
+	 (values line start patlen)))))
+); eval-when (:compile-toplevel :execute)
+
+(def-sensitive-newline-search-method
+  sensitive-find-newline-once-forward-method t)
+(def-sensitive-newline-search-method
+  sensitive-find-newline-once-backward-method nil)
+
+
+(defun find-pattern (mark search-pattern &optional stop-mark)
+  "Find a match of Search-Pattern starting at Mark.  Mark is moved to
+  point before the match and the number of characters matched is returned.
+  If there is no match for the pattern then Mark is not modified and NIL
+  is returned.
+  If stop-mark is specified, NIL is returned and mark is not moved if
+  the point before the match is after stop-mark for forward search or
+  before stop-mark for backward search"
+  (close-line)
+  (multiple-value-bind (line start matched)
+		       (funcall (search-pattern-search-function search-pattern)
+				search-pattern (mark-line mark)
+				(mark-charpos mark))
+    (when (and matched
+	       (or (null stop-mark)
+                   (if (eq (search-pattern-direction search-pattern) :forward)
+                     (or (< (line-number line) (line-number (mark-line stop-mark)))
+                         (and (eq line (mark-line stop-mark))
+                              (<= start (mark-charpos stop-mark))))
+                     (or (< (line-number (mark-line stop-mark)) (line-number line))
+                         (and (eq (mark-line stop-mark) line)
+                              (<= (mark-charpos stop-mark) start))))))
+      (move-to-position mark start line)
+      matched)))
+
+;;; replace-pattern  --  Public
+;;;
+;;;
+(defun replace-pattern (mark search-pattern replacement &optional n)
+  "Replaces N occurrences of the Search-Pattern with the Replacement string
+  in the text starting at the given Mark.  If N is Nil, all occurrences 
+  following the Mark are replaced."
+  (close-line)
+  (do* ((replacement (coerce replacement 'simple-string))
+	(new (length (the simple-string replacement)))
+	(fun (search-pattern-search-function search-pattern))
+	(forward-p (eq (search-pattern-direction search-pattern) :forward))
+	(n (if n (1- n) -1) (1- n))
+	(m (copy-mark mark :temporary)) line start matched)
+       (())
+    (multiple-value-setq (line start matched)
+      (funcall fun search-pattern (mark-line m) (mark-charpos m)))
+    (unless matched (return m))
+    (setf (mark-line m) line  (mark-charpos m) start)
+    (delete-characters m matched)
+    (insert-string m replacement)
+    (when forward-p (character-offset m new))
+    (when (zerop n) (return m))
+    (close-line)))
Index: /branches/new-random/cocoa-ide/hemlock/src/search2.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/search2.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/search2.lisp	(revision 13309)
@@ -0,0 +1,211 @@
+;;; -*- Log: Hemlock.Log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;     More searching function for Hemlock.  This file contains the stuff
+;;; to implement the various kinds of character searches.
+;;;
+;;;    Written by Rob MacLachlan
+;;;
+
+(in-package :hemlock-internals)
+
+;;;; Character and Not-Character search kinds:
+
+(eval-when (:compile-toplevel :execute)
+(defmacro forward-character-search-macro (string start length char test)
+  `(position ,char ,string  :start ,start  :end ,length  :test ,test))
+
+(defmacro backward-character-search-macro (string start char test)
+  `(position ,char ,string  :end (1+ ,start)  :test ,test  :from-end t))
+
+(defmacro define-character-search-method (name search macro test)
+  `(defun ,name (pattern line start)
+     (let ((char (search-pattern-pattern pattern)))
+       (when (,search line start ,macro char ,test)
+	 (values line start 1)))))
+); eval-when (:compile-toplevel :execute)
+
+(define-character-search-method find-character-once-forward-method
+  search-once-forward-macro forward-character-search-macro #'char=)
+(define-character-search-method find-not-character-once-forward-method
+  search-once-forward-macro forward-character-search-macro #'char/=)
+(define-character-search-method find-character-once-backward-method
+  search-once-backward-macro backward-character-search-macro #'char=)
+(define-character-search-method find-not-character-once-backward-method
+  search-once-backward-macro backward-character-search-macro #'char/=)
+
+
+
+(define-search-kind :character (direction pattern old)
+  ":character - Pattern is a character to search for."
+  (unless old (setq old (internal-make-search-pattern)))
+  (setf (search-pattern-kind old) :character
+	(search-pattern-direction old) direction
+	(search-pattern-pattern old) pattern
+	(search-pattern-reclaim-function old) #'identity
+	(search-pattern-search-function old)
+	(if (eq direction :forward)
+	    #'find-character-once-forward-method
+	    #'find-character-once-backward-method))
+  old)
+
+(define-search-kind :not-character (direction pattern old)
+  ":not-character - Find the first character which is not Char= to Pattern."
+  (unless old (setq old (internal-make-search-pattern)))
+  (setf (search-pattern-kind old) :not-character
+	(search-pattern-direction old) direction
+	(search-pattern-pattern old) pattern
+	(search-pattern-reclaim-function old) #'identity
+	(search-pattern-search-function old)
+	(if (eq direction :forward)
+	    #'find-not-character-once-forward-method
+	    #'find-not-character-once-backward-method))
+  old)
+
+
+;;;; Character set searching.
+;;;
+;;;    These functions implement the :test, :test-not, :any and :not-any
+;;; search-kinds.
+
+;;; The Character-Set abstraction is used to hide somewhat the fact that
+;;; we are using %Sp-Find-Character-With-Attribute to implement the
+;;; character set searches.
+
+(defvar *free-character-sets* ()
+  "A list of unused character-set objects for use by the Hemlock searching
+  primitives.")
+
+;;; Create-Character-Set  --  Internal
+;;;
+;;;    Create-Character-Set returns a character-set which will search
+;;; for no character.
+;;;
+(defun create-character-set ()
+  (let ((set (or (pop *free-character-sets*)
+		 (make-array 256 :element-type '(mod 256)))))
+    (declare (type (simple-array (mod 256)) set))
+    (dotimes (i search-char-code-limit)
+      (setf (aref set i) 0))
+    set))
+
+;;; Add-Character-To-Set  --  Internal
+;;;
+;;;    Modify the character-set Set to succeed for Character.
+;;;
+(declaim (inline add-character-to-set))
+(defun add-character-to-set (character set)
+  (setf (aref (the (simple-array (mod 256)) set)
+	      (search-char-code character))
+	1))
+
+;;; Release-Character-Set  --  Internal
+;;;
+;;;    Release the storage for the character set Set.
+;;;
+(defun release-character-set (set)
+  (push set *free-character-sets*))
+
+(eval-when (:compile-toplevel :execute)
+;;; Forward-Set-Search-Macro  --  Internal
+;;;
+;;;    Do a search for some character in Set in String starting at Start
+;;; and ending at End.
+;;;
+(defmacro forward-set-search-macro (string start last set)
+  `(%sp-find-character-with-attribute ,string ,start ,last ,set 1))
+
+;;; Backward-Set-Search-Macro  --  Internal
+;;;
+;;;    Like forward-set-search-macro, only :from-end, and start is
+;;; implicitly 0.
+;;;
+(defmacro backward-set-search-macro (string last set)
+  `(%sp-reverse-find-character-with-attribute ,string 0 (1+ ,last) ,set 1))
+); eval-when (:compile-toplevel :execute)
+
+
+(defstruct (set-search-pattern
+	    (:include search-pattern)
+	    (:print-function %print-search-pattern))
+  set)
+
+(eval-when (:compile-toplevel :execute)
+(defmacro define-set-search-method (name search macro)
+  `(defun ,name (pattern line start)
+     (let ((set (set-search-pattern-set pattern)))
+       (when (,search line start ,macro set)
+	 (values line start 1)))))
+); eval-when (:compile-toplevel :execute)
+
+(define-set-search-method find-set-once-forward-method
+  search-once-forward-macro forward-set-search-macro)
+
+(define-set-search-method find-set-once-backward-method
+  search-once-backward-macro backward-set-search-macro)
+
+(defun frob-character-set (pattern direction old kind)
+  (unless old (setq old (make-set-search-pattern)))
+  (setf (search-pattern-kind old) kind
+	(search-pattern-direction old) direction
+	(search-pattern-pattern old) pattern
+	(search-pattern-search-function old)
+	(if (eq direction :forward)
+	    #'find-set-once-forward-method
+	    #'find-set-once-backward-method)
+	(search-pattern-reclaim-function old)
+	#'(lambda (x) (release-character-set (set-search-pattern-set x))))
+  old)
+
+
+(define-search-kind :test (direction pattern old)
+  ":test - Find the first character which satisfies the test function Pattern.
+  Pattern must be a function of its argument only."
+  (setq old (frob-character-set pattern direction old :test))
+  (let ((set (create-character-set)))
+    (dotimes (i search-char-code-limit)
+      (when (funcall pattern (code-char i))
+	(add-character-to-set (code-char i) set)))
+    (setf (set-search-pattern-set old) set))
+  old)
+
+
+(define-search-kind :test-not (direction pattern old)
+  ":test-not - Find the first character which does not satisfy the
+  test function Pattern.  Pattern must be a function of its argument only."
+  (setq old (frob-character-set pattern direction old :test-not))
+  (let ((set (create-character-set)))
+    (dotimes (i search-char-code-limit)
+      (unless (funcall pattern (code-char i))
+	(add-character-to-set (code-char i) set)))
+    (setf (set-search-pattern-set old) set))
+  old)
+
+(define-search-kind :any (direction pattern old)
+  ":any - Find the first character which is the string Pattern."
+  (declare (string pattern))
+  (setq old (frob-character-set pattern direction old :any))
+  (let ((set (create-character-set)))
+    (dotimes (i (length pattern))
+      (add-character-to-set (char pattern i) set))
+    (setf (set-search-pattern-set old) set))
+  old)
+
+(define-search-kind :not-any (direction pattern old)
+  ":not-any - Find the first character which is not in the string Pattern."
+  (declare (string pattern))
+  (setq old (frob-character-set pattern direction old :not-any))
+  (let ((set (create-character-set)))
+    (dotimes (i search-char-code-limit)
+      (unless (find (code-char i) pattern)
+	(add-character-to-set (code-char i) set)))
+    (setf (set-search-pattern-set old) set))
+  old)
Index: /branches/new-random/cocoa-ide/hemlock/src/searchcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/searchcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/searchcoms.lisp	(revision 13309)
@@ -0,0 +1,459 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains searching and replacing commands.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; Some global state.
+
+(defvar *last-search-string* () "Last string searched for.")
+(defvar *last-search-pattern*
+  (new-search-pattern :string-insensitive :forward "Foo")
+  "Search pattern we keep around so we don't cons them all the time.")
+(defvar *search-wrapped-p* nil "True if search wrapped")
+
+(defhvar "String Search Ignore Case"
+  "When set, string searching commands use case insensitive."
+  :value t)
+
+(defun get-search-pattern (string direction)
+  (declare (simple-string string))
+  (when (zerop (length string)) (editor-error))
+  (setq *last-search-string* string)
+  (setq *last-search-pattern*
+	(new-search-pattern (if (value string-search-ignore-case)
+				:string-insensitive
+				:string-sensitive)
+			    direction string *last-search-pattern*)))
+
+
+(defun note-current-selection-set-by-search ()
+  (hemlock-ext:note-selection-set-by-search (current-buffer)))
+
+
+;;;; Vanilla searching.
+
+(defcommand "Forward Search" (p &optional string)
+  "Do a forward search for a string.
+  Prompt for the string and leave the point after where it is found."
+  "Searches for the specified String in the current buffer."
+  (declare (ignore p))
+  (if (not string)
+      (setq string (prompt-for-string :prompt "Search: "
+				      :default *last-search-string*
+				      :help "String to search for")))
+  (let* ((pattern (get-search-pattern string :forward))
+	 (point (current-point))
+	 (mark (copy-mark point))
+	 ;; find-pattern moves point to start of match, and returns is # chars matched
+	 (won (find-pattern point pattern)))
+    (cond (won (move-mark mark point)
+	       (character-offset point won)
+               (push-buffer-mark mark t)
+	       (note-current-selection-set-by-search))
+	  (t (delete-mark mark)
+	     (editor-error)))
+    (clear-echo-area)))
+
+(defcommand "Reverse Search" (p &optional string)
+  "Do a backward search for a string.
+   Prompt for the string and leave the point before where it is found."
+  "Searches backwards for the specified String in the current buffer."
+  (declare (ignore p))
+  (if (not string)
+      (setq string (prompt-for-string :prompt "Reverse Search: "
+				      :default *last-search-string* 
+				      :help "String to search for")))
+  (let* ((pattern (get-search-pattern string :backward))
+	 (point (current-point))
+	 (mark (copy-mark point))
+	 (won (find-pattern point pattern)))
+    (cond (won (move-mark mark point)
+	       (character-offset mark won)
+	       (push-buffer-mark mark t)
+	       (note-current-selection-set-by-search))
+	  (t (delete-mark mark)
+	     (editor-error)))
+    (clear-echo-area)))
+
+
+
+
+;;;; Replacement commands:
+
+(defmode "Query/Replace" :precedence :highest
+  :documentation "Type one of the following single-character commands:"
+  ;; Make anything that's not otherwise overridden exit query/replace
+  :default-command "Query/Replace Exit and Redo")
+
+(add-hook abort-hook 'abort-query/replace-mode)
+
+(defhvar "Case Replace"
+  "If this is true then \"Query Replace\" will try to preserve case when
+  doing replacements."
+  :value t)
+
+(defcommand "Replace String" (p &optional
+				(target (prompt-for-string
+					 :prompt "Replace String: "
+					 :help "Target string"
+					 :default *last-search-string*))
+				(replacement (prompt-for-string
+					      :prompt "With: "
+					      :help "Replacement string")))
+  "Replaces the specified Target string with the specified Replacement
+   string in the current buffer for all occurrences after the point or within
+   the active region, depending on whether it is active."
+  (let ((qrs (query/replace-init :count p :target target :replacement replacement
+                                 :undo-name "Replace String")))
+    (query/replace-all qrs)
+    (query/replace-finish qrs)))
+
+(defun current-query-replace-state ()
+  (or (value query/replace-state)
+      (error "Query/Replace command invoked outside Query Replace")))
+
+(defcommand "Query Replace" (p &optional
+			       (target (prompt-for-string
+					:prompt "Query Replace: "
+					:help "Target string"
+					:default *last-search-string*))
+			       (replacement (prompt-for-string
+					     :prompt "With: "
+					     :help "Replacement string")))
+  "Replaces the Target string with the Replacement string if confirmation
+   from the keyboard is given.  If the region is active, limit queries to
+   occurrences that occur within it, otherwise use point to end of buffer."
+  (let* ((buffer (current-buffer))
+         (qrs (query/replace-init :count p :target target :replacement replacement
+                                  :undo-name "Query Replace")))
+    (setf (buffer-minor-mode (current-buffer) "Query/Replace") t)
+    (unless (hemlock-bound-p 'query/replace-state :buffer buffer)
+      (defhvar "Query/Replace State"
+        "Internal variable containing current state of Query/Replace"
+        :buffer buffer))
+    (setf (value query/replace-state) qrs)
+    (query/replace-find-next qrs)))
+
+(defstruct (replace-undo (:constructor make-replace-undo (mark region)))
+  mark
+  region)
+
+(setf (documentation 'replace-undo-mark 'function)
+      "Return the mark where a replacement was made.")
+(setf (documentation 'replace-undo-region 'function)
+      "Return region deleted due to replacement.")
+
+
+(defstruct (query-replace-state (:conc-name "QRS-"))
+  count
+  target
+  replacement
+  undo-name
+  dumb-p
+  upper
+  cap
+  start-mark
+  last-found
+  stop-mark
+  undo-data)
+
+(defun query/replace-init (&key count target replacement undo-name)
+  (when (and count (minusp count))
+    (editor-error "Replacement count is negative."))
+  (let* ((point (current-point))
+         (region (get-count-region))
+         (start-mark (copy-mark (region-start region) :temporary))
+         (end-mark (copy-mark (region-end region) :left-inserting)))
+    (move-mark point start-mark)
+    (get-search-pattern target :forward)
+    (make-query-replace-state
+     :count (or count -1)
+     :target target
+     :replacement replacement
+     :undo-name undo-name
+     :dumb-p (not (and (every #'(lambda (ch) (or (not (both-case-p ch))
+                                                 (lower-case-p ch)))
+                              (the string replacement))
+                       (value case-replace)))
+     :upper (string-upcase replacement)
+     :cap (string-capitalize replacement)
+     :start-mark start-mark
+     :last-found (copy-mark start-mark :temporary)
+     :stop-mark end-mark
+     :undo-data nil)))
+
+
+(defun query/replace-find-next (qrs &key (interactive t))
+  (let* ((point (current-point))
+         (won (and (not (zerop (qrs-count qrs)))
+		   (find-pattern point *last-search-pattern* (qrs-stop-mark qrs)))))
+    (if won
+      (progn
+	(decf (qrs-count qrs))
+	(move-mark (qrs-last-found qrs) (current-point))
+	(character-offset point (length (qrs-target qrs)))
+	(when interactive
+	  (message "Query Replace (type ? for help): "))
+	T)
+      (progn
+	(when interactive
+	  (end-query/replace-mode))
+	nil))))
+
+(defun query/replace-replace (qrs)
+  (let* ((replacement (qrs-replacement qrs))
+         (point (current-point))
+         (length (length (qrs-target qrs))))
+    (with-mark ((undo-mark1 point :left-inserting)
+		(undo-mark2 point :left-inserting))
+      (character-offset undo-mark1 (- length))
+      (let ((string (cond ((qrs-dumb-p qrs) replacement)
+			  ((upper-case-p (next-character undo-mark1))
+			   (prog2
+			    (mark-after undo-mark1)
+			    (if (upper-case-p (next-character undo-mark1))
+			      (qrs-upper qrs)
+			      (qrs-cap qrs))
+			    (mark-before undo-mark1)))
+			  (t replacement))))
+	(push (make-replace-undo
+               ;; Save :right-inserting, so the INSERT-STRING at mark below
+               ;; doesn't move the copied mark the past replacement.
+               (copy-mark undo-mark1 :right-inserting)
+               (delete-and-save-region (region undo-mark1 undo-mark2)))
+              (qrs-undo-data qrs))
+	(insert-string point string)))))
+
+(defun query/replace-all (qrs)
+  (loop
+    while (query/replace-find-next qrs :interactive nil)
+    do (query/replace-replace qrs)))
+
+(defun query/replace-finish (qrs &key (report t))
+  (let* ((undo-data (nreverse (qrs-undo-data qrs)))
+	 (count (length undo-data))
+	 (replacement-len (length (qrs-replacement qrs))))
+    (save-for-undo (qrs-undo-name qrs)
+      #'(lambda ()
+          (dolist (ele undo-data)
+            (setf (mark-kind (replace-undo-mark ele)) :left-inserting))
+          (dolist (ele undo-data)
+            (let ((mark (replace-undo-mark ele)))
+              (delete-characters mark replacement-len)
+              (ninsert-region mark (replace-undo-region ele)))))
+      #'(lambda ()
+          (dolist (ele undo-data)
+            (delete-mark (replace-undo-mark ele)))))
+    (unless (mark= (current-point) (qrs-start-mark qrs))
+      (push-buffer-mark (qrs-start-mark qrs)))
+    (delete-mark (qrs-stop-mark qrs))
+    (when report
+      (message "~D occurrence~:P replaced." count))))
+
+
+(defun abort-query/replace-mode ()
+  (when (buffer-minor-mode (current-buffer) "Query/Replace")
+    (end-query/replace-mode :report nil)))
+
+(defun end-query/replace-mode (&key (report t))
+  (let* ((qrs (current-query-replace-state)))
+    (query/replace-finish qrs :report report)
+    (setf (buffer-minor-mode (current-buffer) "Query/Replace") nil)))
+
+(defcommand "Query/Replace This" (p)
+  "Replace this occurence"
+  (declare (ignore p))
+  (let ((qrs (current-query-replace-state)))
+    (query/replace-replace qrs)
+    (query/replace-find-next qrs)))
+
+(defcommand "Query/Replace Skip" (p)
+  "Don't replace this occurence, but continue"
+  (declare (ignore p))
+  (let ((qrs (current-query-replace-state)))
+    (query/replace-find-next qrs)))
+
+(defcommand "Query/Replace All" (p)
+  "Replace this and all remaining occurences"
+  (declare (ignore p))
+  (let ((qrs (current-query-replace-state)))
+    (query/replace-replace qrs)
+    (query/replace-all qrs))
+  (end-query/replace-mode))
+
+(defcommand "Query/Replace Last" (p)
+  "Replace this occurrence, then exit"
+  (declare (ignore p))
+  (let ((qrs (current-query-replace-state)))
+    (query/replace-replace qrs))
+  (end-query/replace-mode))
+
+(defcommand "Query/Replace Exit" (p)
+  "Exit Query Replace mode"
+  (declare (ignore p))
+  (end-query/replace-mode))
+
+(defcommand "Query/Replace Abort" (p)
+  "Abort Query/Replace mode"
+  (declare (ignore p))
+  (abort-current-command "Query/Replace aborted"))
+
+(defcommand "Query/Replace Help" (p)
+  "Describe Query/Replace commands"
+  (describe-mode-command p "Query/Replace"))
+
+;; The transparent-p flag takes care of executing the key normally when we're done,
+;; as long as we don't take a non-local exit.
+(defcommand ("Query/Replace Exit and Redo" :transparent-p t) (p)
+  "Exit Query Replace and then execute the key normally"
+  (declare (ignore p))
+  (end-query/replace-mode))
+
+;;;; Occurrence searching.
+
+(defcommand "List Matching Lines" (p &optional string)
+  "Prompts for a search string and lists all matching lines after the point or
+   within the current-region, depending on whether it is active or not.
+   With an argument, lists p lines before and after each matching line."
+  "Prompts for a search string and lists all matching lines after the point or
+   within the current-region, depending on whether it is active or not.
+   With an argument, lists p lines before and after each matching line."
+  (unless string
+    (setf string (prompt-for-string :prompt "List Matching: "
+				    :default *last-search-string*
+				    :help "String to search for")))
+  (let ((pattern (get-search-pattern string :forward))
+	(matching-lines nil)
+	(region (get-count-region)))
+    (with-mark ((mark (region-start region))
+		(end-mark (region-end region)))
+      (loop
+	(when (or (null (find-pattern mark pattern)) (mark> mark end-mark))
+	  (return))
+	(setf matching-lines
+	      (nconc matching-lines (list-lines mark (or p 0))))
+	(unless (line-offset mark 1 0)
+	  (return))))
+    (with-pop-up-display (s :height (length matching-lines) :title (format nil "Lines matching ~s" string))
+      (dolist (line matching-lines)
+	(write-line line s)))))
+
+;;; LIST-LINES creates a lists of strings containing (num) lines before the
+;;; line that the point is on, the line that the point is on, and (num)
+;;; lines after the line that the point is on. If (num) > 0, a string of
+;;; dashes will be added to make life easier for List Matching Lines.
+;;; 
+(defun list-lines (mark num)
+  (if (<= num 0)
+      (list (line-string (mark-line mark)))
+      (with-mark ((mark mark)
+		  (beg-mark mark))
+	(unless (line-offset beg-mark (- num))
+	  (buffer-start beg-mark))
+	(unless (line-offset mark num)
+	  (buffer-end mark))
+	(let ((lines (list "--------")))
+	  (loop
+	    (push (line-string (mark-line mark)) lines)
+	    (when (same-line-p mark beg-mark)
+	      (return lines))
+	    (line-offset mark -1))))))
+
+(defcommand "Delete Matching Lines" (p &optional string)
+  "Deletes all lines that match the search pattern using delete-region. If
+   the current region is active, limit the search to it. The argument is
+   ignored."
+  "Deletes all lines that match the search pattern using delete-region. If
+   the current region is active, limit the search to it. The argument is
+   ignored."
+  (declare (ignore p))
+  (unless string
+    (setf string (prompt-for-string :prompt "Delete Matching: "
+				    :default *last-search-string*
+				    :help "String to search for")))
+  (let* ((region (get-count-region))
+	 (pattern (get-search-pattern string :forward))
+	 (start-mark (region-start region))
+	 (end-mark (region-end region)))
+    (with-mark ((bol-mark start-mark :left-inserting)
+		(eol-mark start-mark :right-inserting))
+      (loop
+	(unless (and (find-pattern bol-mark pattern) (mark< bol-mark end-mark))
+	  (return))
+	(move-mark eol-mark bol-mark)
+	(line-start bol-mark)
+	(unless (line-offset eol-mark 1 0)
+	  (buffer-end eol-mark))
+	(delete-region (region bol-mark eol-mark))))))
+
+(defcommand "Delete Non-Matching Lines" (p &optional string)
+  "Deletes all lines that do not match the search pattern using delete-region.
+   If the current-region is active, limit the search to it. The argument is
+   ignored."
+  "Deletes all lines that do not match the search pattern using delete-region.
+   If the current-region is active, limit the search to it. The argument is
+   ignored."
+  (declare (ignore p))
+  (unless string
+    (setf string (prompt-for-string :prompt "Delete Non-Matching:"
+				    :default *last-search-string*
+				    :help "String to search for")))
+  (let* ((region (get-count-region))
+	 (start-mark (region-start region))
+	 (stop-mark (region-end region))
+	 (pattern (get-search-pattern string :forward)))
+    (with-mark ((beg-mark start-mark :left-inserting)
+		(end-mark start-mark :right-inserting))
+      (loop
+	(move-mark end-mark beg-mark)
+	(cond ((and (find-pattern end-mark pattern) (mark< end-mark stop-mark))
+	       (line-start end-mark)
+	       (delete-region (region beg-mark end-mark))
+	       (unless (line-offset beg-mark 1 0)
+		 (return)))
+	      (t
+	       (delete-region (region beg-mark stop-mark))
+	       (return)))))))
+
+(defcommand "Count Occurrences" (p &optional string)
+  "Prompts for a search string and counts occurrences of it after the point or
+   within the current-region, depending on whether it is active or not. The
+   argument is ignored."
+  "Prompts for a search string and counts occurrences of it after the point or
+   within the current-region, depending on whether it is active or not. The
+   argument is ignored."
+  (declare (ignore p))
+  (unless string
+    (setf string (prompt-for-string
+		  :prompt "Count Occurrences: "
+		  :default *last-search-string*
+		  :help "String to search for")))
+  (message "~D occurrence~:P"
+	   (count-occurrences-region (get-count-region) string)))
+
+(defun count-occurrences-region (region string)
+  (let ((pattern (get-search-pattern string :forward))
+	(end-mark (region-end region)))
+    (let ((occurrences 0))
+      (with-mark ((mark (region-start region)))
+	(loop
+	  (let ((won (find-pattern mark pattern)))
+	    (when (or (null won) (mark> mark end-mark))
+	      (return))
+	    (incf occurrences)
+	    (character-offset mark won))))
+      occurrences)))
Index: /branches/new-random/cocoa-ide/hemlock/src/streams.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/streams.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/streams.lisp	(revision 13309)
@@ -0,0 +1,250 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    This file contains definitions of various types of streams used
+;;; in Hemlock.  They are implementation dependant, but should be
+;;; portable to all implementations based on Spice Lisp with little
+;;; difficulty.
+;;;
+;;; Written by Skef Wholey and Rob MacLachlan.
+;;;
+
+(in-package :hemlock-internals)
+
+(defclass hemlock-output-stream (#-scl fundamental-character-output-stream
+				 #+scl character-output-stream)
+  ((mark
+    :initform nil
+    :accessor hemlock-output-stream-mark
+    :documentation "The mark we insert at.")
+   (out
+    :accessor old-lisp-stream-out)
+   (sout
+    :accessor old-lisp-stream-sout)
+   ) )
+
+;; this should suffice for now:
+(defmethod stream-write-char ((stream hemlock-output-stream) char)
+  (funcall (old-lisp-stream-out stream) stream char))
+
+(defmethod stream-write-string ((stream hemlock-output-stream) string
+                                &optional
+                                (start 0)
+                                (end (length string)))
+  (funcall (old-lisp-stream-sout stream) stream string start end))
+                                
+
+(defmethod print-object ((object hemlock-output-stream) stream)
+  (write-string "#<Hemlock output stream>" stream))
+
+(defun make-hemlock-output-stream (mark &optional (buffered :line))
+  "Returns an output stream whose output will be inserted at the Mark.
+  Buffered, which indicates to what extent the stream may be buffered
+  is one of the following:
+   :None  -- The screen is brought up to date after each stream operation.
+   :Line  -- The screen is brought up to date when a newline is written.
+   :Full  -- The screen is not updated except explicitly via Force-Output."
+  (modify-hemlock-output-stream (make-instance 'hemlock-output-stream) mark
+                                buffered))
+
+
+(defun modify-hemlock-output-stream (stream mark buffered)
+  (unless (and (markp mark)
+	       (member (mark-kind mark) '(:right-inserting :left-inserting)))
+    (error "~S is not a permanent mark." mark))
+  (setf (hemlock-output-stream-mark stream) mark)
+  (case buffered
+    (:none
+     (setf (old-lisp-stream-out stream) #'hemlock-output-unbuffered-out
+	   (old-lisp-stream-sout stream) #'hemlock-output-unbuffered-sout))
+    (:line
+     (setf (old-lisp-stream-out stream) #'hemlock-output-line-buffered-out
+	   (old-lisp-stream-sout stream) #'hemlock-output-line-buffered-sout))
+    (:full
+     (setf (old-lisp-stream-out stream) #'hemlock-output-buffered-out
+	   (old-lisp-stream-sout stream) #'hemlock-output-buffered-sout))
+    (t
+     (error "~S is a losing value for Buffered." buffered)))
+  stream)
+
+(defun hemlock-output-unbuffered-out (stream character)
+  (let ((mark (hemlock-output-stream-mark stream)))
+    (modifying-buffer-storage ((mark-buffer mark))
+      (insert-character mark character)
+      (unless (eq (mark-kind mark) :left-inserting)
+	(character-offset mark 1)))))
+
+(defun hemlock-output-unbuffered-sout (stream string start end)
+  (unless (and (eql start 0)
+	       (eql end (length string)))
+    (setq string (subseq string start end)))
+  (let ((mark (hemlock-output-stream-mark stream)))
+    (modifying-buffer-storage ((mark-buffer mark))
+      (insert-string mark string)
+      (unless (eq (mark-kind mark) :left-inserting)
+	(character-offset mark (- end start))))))
+
+(defun hemlock-output-buffered-out (stream character)
+  (hemlock-output-unbuffered-out stream character))
+
+
+(defun hemlock-output-buffered-sout (stream string start end)
+  (hemlock-output-unbuffered-sout stream string start end))
+
+(defun hemlock-output-line-buffered-out (stream character)
+  (hemlock-output-unbuffered-out stream character))
+
+(defun hemlock-output-line-buffered-sout (stream string start end)
+  (hemlock-output-unbuffered-sout stream string start end))
+
+
+(defmethod stream-finish-output ((stream hemlock-output-stream)))
+
+(defmethod stream-force-output ((stream hemlock-output-stream)))
+
+(defmethod close ((stream hemlock-output-stream) &key abort)
+  (declare (ignore abort))
+  (setf (hemlock-output-stream-mark stream) nil))
+
+(defmethod stream-line-column ((stream hemlock-output-stream))
+  (mark-charpos (hemlock-output-stream-mark stream)))
+
+
+
+
+(defclass hemlock-region-stream (#-scl fundamental-character-input-stream
+				 #+scl character-input-stream)
+  ;;
+  ;; The region we read from.
+  ((region :initarg :region
+           :accessor hemlock-region-stream-region)
+   ;;
+   ;; The mark pointing to the next character to read.
+   (mark :initarg :mark
+         :accessor hemlock-region-stream-mark)) )
+
+(defmethod print-object ((object hemlock-region-stream) stream)
+  (declare (ignorable object))
+  (write-string "#<Hemlock region stream>" stream))
+
+(defun make-hemlock-region-stream (region)
+  "Returns an input stream that will return successive characters from the
+  given Region when asked for input."
+  (make-instance 'hemlock-region-stream
+                 :region region
+                 :mark (copy-mark (region-start region) :right-inserting)))
+
+(defun modify-hemlock-region-stream (stream region)
+  (setf (hemlock-region-stream-region stream) region)
+  (let* ((mark (hemlock-region-stream-mark stream))
+	 (start (region-start region))
+	 (start-line (mark-line start)))
+    ;; Make sure it's dead.
+    (delete-mark mark)
+    (setf (mark-line mark) start-line  (mark-charpos mark) (mark-charpos start))
+    (push mark (line-marks start-line)))
+  stream)
+
+(defmethod stream-read-char ((stream hemlock-region-stream))
+  (let ((mark (hemlock-region-stream-mark stream)))
+    (cond ((mark< mark
+		  (region-end (hemlock-region-stream-region stream)))
+	   (prog1 (next-character mark) (mark-after mark)))
+	  (t :eof))))
+
+(defmethod stream-listen ((stream hemlock-region-stream))
+  (mark< (hemlock-region-stream-mark stream)
+         (region-end (hemlock-region-stream-region stream))))
+
+(defmethod stream-unread-char ((stream hemlock-region-stream) char)
+  (let ((mark (hemlock-region-stream-mark stream)))
+    (unless (mark> mark
+                   (region-start (hemlock-region-stream-region stream)))
+      (error "Nothing to unread."))
+    (unless (char= char (previous-character mark))
+      (error "Unreading something not read: ~S" char))
+    (mark-before mark)))
+
+(defmethod stream-clear-input ((stream hemlock-region-stream))
+  (move-mark
+   (hemlock-region-stream-mark stream)
+   (region-end (hemlock-region-stream-region stream)))
+  nil)
+
+(defmethod close ((stream hemlock-region-stream) &key abort)
+  (declare (ignorable abort))
+  (delete-mark (hemlock-region-stream-mark stream))
+  (setf (hemlock-region-stream-region stream) nil))
+
+#+excl
+(defmethod excl:stream-read-char-no-hang ((stream hemlock-region-stream))
+  (stream-read-char stream))
+
+#||  
+(defmethod excl::stream-file-position ((stream hemlock-output-stream) &optional pos)
+  (assert (null pos))
+  (mark-charpos (hemlock-output-stream-mark stream)))
+
+(defun region-misc (stream operation &optional arg1 arg2)
+  (declare (ignore arg2))
+  (case operation
+
+    (:file-position
+     (let ((start (region-start (hemlock-region-stream-region stream)))
+	   (mark (hemlock-region-stream-mark stream)))
+       (cond (arg1
+	      (move-mark mark start)
+	      (character-offset mark arg1))
+	     (t
+	      (count-characters (region start mark)))))) ))
+||#
+
+
+
+;;;; Stuff to support keyboard macros.
+
+#+later
+(progn
+  
+(defstruct (kbdmac-stream
+	    (:include editor-input
+		      (get #'kbdmac-get)
+		      (unget #'kbdmac-unget)
+		      (listen #'kbdmac-listen))
+	    (:constructor make-kbdmac-stream ()))
+  buffer    ; The simple-vector that holds the characters.
+  index)    ; Index of the next character.
+
+(defun kbdmac-get (stream ignore-abort-attempts-p)
+  (declare (ignore ignore-abort-attempts-p))
+  (let ((index (kbdmac-stream-index stream)))
+    (setf (kbdmac-stream-index stream) (1+ index))
+    (setf (last-key-event-typed) (svref (kbdmac-stream-buffer stream) index))))
+
+(defun kbdmac-unget (ignore stream)
+  (declare (ignore ignore))
+  (if (plusp (kbdmac-stream-index stream))
+      (decf (kbdmac-stream-index stream))
+      (error "Nothing to unread.")))
+
+(defun kbdmac-listen (stream)
+  (declare (ignore stream))
+  t)
+
+;;; MODIFY-KBDMAC-STREAM  --  Internal
+;;;
+;;;    Bash the kbdmac-stream Stream so that it will return the Input.
+;;;
+(defun modify-kbdmac-stream (stream input)
+  (setf (kbdmac-stream-index stream) 0)
+  (setf (kbdmac-stream-buffer stream) input)
+  stream)
+)
Index: /branches/new-random/cocoa-ide/hemlock/src/struct.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/struct.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/struct.lisp	(revision 13309)
@@ -0,0 +1,429 @@
+ ;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Structures and assorted macros for Hemlock.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Marks.
+
+(defstruct (mark (:print-function %print-hmark)
+		 (:predicate markp)
+		 (:copier nil)
+		 (:constructor internal-make-mark (line charpos %kind)))
+  "A Hemlock mark object.  See Hemlock Command Implementor's Manual for details."
+  line					; pointer to line
+  charpos				; character position
+  %kind)				; type of mark
+
+(setf (documentation 'markp 'function)
+  "Returns true if its argument is a Hemlock mark object, false otherwise.")
+(setf (documentation 'mark-line 'function)
+  "Returns line that a Hemlock mark points to.")
+(setf (documentation 'mark-charpos 'function)
+  "Returns the character position of a Hemlock mark.
+  A mark's character position is the index within the line of the character
+  following the mark.")
+
+
+(defstruct (font-mark (:print-function
+		       (lambda (s stream d)
+			 (declare (ignore d))
+			 (write-string "#<Hemlock Font-Mark \"" stream)
+			 (%print-before-mark s stream)
+			 (write-string "/\\" stream)
+			 (%print-after-mark s stream)
+			 (write-string "\">" stream)))
+		      (:include mark)
+		      (:copier nil)
+		      (:constructor internal-make-font-mark
+				    (line charpos %kind font)))
+  font
+  region)
+
+(defmacro fast-font-mark-p (s)
+  `(typep ,s 'font-mark))
+
+
+
+;;;; Regions, buffers, modeline fields.
+
+;;; The region object:
+;;;
+(defstruct (region (:print-function %print-hregion)
+		   (:predicate regionp)
+		   (:copier nil)
+		   (:constructor internal-make-region (start end)))
+  "A Hemlock region object.  See Hemlock Command Implementor's Manual for details."
+  start					; starting mark
+  end)					; ending mark
+
+(setf (documentation 'regionp 'function)
+  "Returns true if its argument is a Hemlock region object, Nil otherwise.")
+(setf (documentation 'region-end 'function)
+  "Returns the mark that is the end of a Hemlock region.")
+(setf (documentation 'region-start 'function)
+  "Returns the mark that is the start of a Hemlock region.")
+
+(defstruct (font-region (:include region)
+                        (:constructor internal-make-font-region (start end)))
+  node)
+
+;;; The buffer object:
+;;;
+(defstruct (buffer (:constructor internal-make-buffer)
+		   (:print-function %print-hbuffer)
+		   (:copier nil)
+		   (:predicate bufferp))
+  "A Hemlock buffer object.  See Hemlock Command Implementor's Manual for details."
+  %name			      ; name of the buffer (a string)
+  %region		      ; the buffer's region
+  %pathname		      ; associated pathname
+  major-mode-object           ; buffer's major mode mode object
+  minor-mode-objects	      ; list of buffer's minor mode objects, reverse precedence order
+  bindings		      ; buffer's command table
+  (shadow-syntax nil)         ; buffer's changes to syntax attributes.
+  point			      ; current position in buffer
+  %mark                       ; a saved buffer position
+  region-active               ; modified-tick when region last activated
+  (%writable t)		      ; t => can alter buffer's region
+  (modified-tick -2)	      ; The last time the buffer was modified.
+  (unmodified-tick -1)	      ; The last time the buffer was unmodified
+  #+clx
+  windows		      ; List of all windows into this buffer.
+  #+clozure ;; should be #+Cocoa
+  document		      ; NSDocument object associated with this buffer
+  var-values		      ; the buffer's local variables
+  variables		      ; string-table of local variables
+  write-date		      ; File-Write-Date for pathname.
+  %modeline-fields	      ; List of modeline-field-info's.
+  (delete-hook nil)	      ; List of functions to call upon deletion.
+  (line-termination :lf)      ; Line-termination, for the time being
+  process		      ; Maybe a listener
+  (gap-context )	      ; The value of *buffer-gap-context*
+                              ; in the thread that can modify the buffer.
+  protected-region            ; (optional) write-protected region
+  (font-regions (ccl::init-dll-header (ccl::make-dll-header)))
+                                        ; a doubly-linked list of font regions.
+  active-font-region                    ; currently active font region
+  charprops		      ; the buffer's default charprops
+  (selection-set-by-command nil) ; boolean: true if selection set by (shifted) motion command.
+  (%lines (make-array 10 :adjustable t :fill-pointer 0)) ;; all lines in the buffer
+  )
+
+(defun set-buffer-charprops (buffer charprops)
+  (setf (buffer-charprops buffer) charprops))
+
+(defstruct (echo-buffer (:include buffer)
+                        (:constructor internal-make-echo-buffer))
+  )
+
+(defstruct (font-region-node (:include ccl::dll-node)
+                             (:constructor make-font-region-node (region)))
+  region)
+
+(setf (documentation 'buffer-point 'function)
+  "Return the mark that is the current focus of attention in a buffer.")
+(setf (documentation 'buffer-variables 'function)
+  "Return the string-table of the variables local to the specifed buffer.")
+(setf (documentation 'buffer-write-date 'function)
+  "Return in universal time format the write date for the file associated
+   with the buffer.  If the pathname is set, then this should probably
+   be as well.  Should be NIL if the date is unknown or there is no file.")
+(setf (documentation 'buffer-delete-hook 'function)
+  "This is the list of buffer specific functions that Hemlock invokes when
+   deleting this buffer.")
+
+
+;;; Modeline fields.
+;;;
+(defstruct (modeline-field (:print-function print-modeline-field)
+			   (:constructor %make-modeline-field
+					 (%name %function %width)))
+  "This is one item displayed in a Hemlock window's modeline."
+  %name		; EQL name of this field.
+  %function	; Function that returns a string for this field.
+  %width)	; Width to display this field in.
+
+(setf (documentation 'modeline-field-p 'function)
+      "Returns true if its argument is a modeline field object, nil otherwise.")
+
+(defstruct (modeline-field-info (:print-function print-modeline-field-info)
+				(:conc-name ml-field-info-)
+				(:constructor make-ml-field-info (field)))
+  field
+  (start nil)
+  (end nil))
+
+
+
+
+;;;; The mode object.
+
+(defstruct (mode-object (:predicate modep)
+			(:copier nil)
+			(:print-function %print-hemlock-mode))
+  name                   ; name of this mode
+  setup-function         ; setup function for this mode
+  cleanup-function       ; Cleanup function for this mode
+  bindings               ; The mode's command table.
+  default-command        ; If non-nil, default command
+  transparent-p		 ; Are key-bindings transparent?
+  hook-name              ; The name of the mode hook.
+  major-p                ; Is this a major mode?
+  precedence		 ; The precedence for a minor mode.
+  character-attributes   ; Mode local character attributes
+  variables              ; String-table of mode variables
+  var-values             ; Alist for saving mode variables
+  documentation          ; Introductory comments for mode describing commands.
+  hidden                 ; Not listed in modeline fields
+)
+
+(defun %print-hemlock-mode (object stream depth)
+  (declare (ignore depth))
+  (write-string "#<Hemlock Mode \"" stream)
+  (write-string (mode-object-name object) stream)
+  (write-string "\">" stream))
+
+
+
+
+;;;; Variables.
+
+;;; This holds information about Hemlock variables, and the system stores
+;;; these structures on the property list of the variable's symbolic
+;;; representation under the 'hemlock-variable-value property.
+;;;
+(defstruct (variable-object
+	    (:print-function
+	     (lambda (object stream depth)
+	       (declare (ignore depth))
+	       (format stream "#<Hemlock Variable-Object ~S>"
+		       (variable-object-name object))))
+	    (:copier nil)
+	    (:constructor make-variable-object (symbol-name)))
+  value		; The value of this variable.
+  hooks		; The hook list for this variable.
+  documentation ; The documentation.
+  name		; The string name.
+  symbol-name)  ; The corresponding symbol name.
+
+;;;; Attribute descriptors.
+
+(defstruct (attribute-descriptor
+	    (:copier nil)
+	    (:print-function %print-attribute-descriptor))
+  "This structure is used internally in Hemlock to describe a character
+  attribute."
+  name
+  keyword
+  documentation
+  (vector #() :type (simple-array * (*)))
+  hooks
+  end-value)
+
+
+
+
+;;;; Commands.
+
+(defstruct (command (:constructor internal-make-command
+				  (%name documentation function transparent-p))
+		    (:copier nil)
+		    (:predicate commandp)
+		    (:print-function %print-hcommand))
+  %name				   ;The name of the command
+  documentation			   ;Command documentation string or function
+  function			   ;The function which implements the command
+  transparent-p                    ;If true, this command is transparent
+  %bindings)			   ;Places where command is bound
+
+(setf (documentation 'commandp 'function)
+  "Returns true if its argument is a Hemlock command object, Nil otherwise.")
+(setf (documentation 'command-documentation 'function)
+  "Return the documentation for a Hemlock command, given the command-object.
+  Command documentation may be either a string or a function.  This may
+  be set with Setf.")
+
+
+
+
+;;;; Random typeout streams.
+
+;;; These streams write to random typeout buffers for WITH-POP-UP-DISPLAY.
+;;;
+
+(defclass random-typeout-stream (#-scl fundamental-character-output-stream
+				 #+scl character-output-stream)
+  ((mark         :initarg :mark
+                 :initform nil
+                 :accessor random-typeout-stream-mark
+                 :documentation "The buffer point of the associated buffer.")))
+
+(defun make-random-typeout-stream (mark)
+  (make-instance 'random-typeout-stream
+                 :mark mark))
+
+(defmethod print-object ((object random-typeout-stream) stream)
+  (format stream "#<Hemlock Random-Typeout-Stream ~S>"
+          (ignore-errors
+            (buffer-name
+             (mark-buffer (random-typeout-stream-mark object))))))
+
+
+
+;;;; Some defsetfs:
+
+(defsetf buffer-writable %set-buffer-writable
+  "Sets whether the buffer is writable and invokes the Buffer Writable Hook.")
+(defsetf buffer-name %set-buffer-name
+  "Sets the name of a specified buffer, invoking the Buffer Name Hook.")
+(defsetf buffer-modified %set-buffer-modified
+  "Make a buffer modified or unmodified.")
+(defsetf buffer-pathname %set-buffer-pathname
+  "Sets the pathname of a buffer, invoking the Buffer Pathname Hook.")
+
+(defsetf getstring %set-string-table
+  "Sets the value for a string-table entry, making a new one if necessary.")
+
+(define-setf-expander value (var)
+  "Set the value of a Hemlock variable, calling any hooks."
+  (let ((svar (gensym)))
+    (values
+     ()
+     ()
+     (list svar)
+     `(%set-value ',var ,svar)
+     `(value ,var))))
+
+(defsetf variable-value (name &optional (kind :current) where) (new-value)
+  "Set the value of a Hemlock variable, calling any hooks."
+  `(%set-variable-value ,name ,kind ,where ,new-value))
+
+(defsetf variable-hooks (name &optional (kind :current) where) (new-value)
+  "Set the list of hook functions for a Hemlock variable."
+  `(%set-variable-hooks ,name ,kind ,where ,new-value))
+
+(defsetf variable-documentation (name &optional (kind :current) where) (new-value)
+  "Set a Hemlock variable's documentation."
+  `(%set-variable-documentation ,name ,kind ,where ,new-value))
+
+(defsetf buffer-minor-mode %set-buffer-minor-mode
+  "Turn a buffer minor mode on or off.")
+(defsetf buffer-major-mode %set-buffer-major-mode
+  "Set a buffer's major mode.")
+(defsetf previous-character %set-previous-character
+  "Sets the character to the left of the given Mark.")
+(defsetf next-character %set-next-character
+  "Sets the characters to the right of the given Mark.")
+(defsetf character-attribute %set-character-attribute
+  "Set the value for a character attribute.")
+(defsetf character-attribute-hooks %set-character-attribute-hooks
+  "Set the hook list for a Hemlock character attribute.")
+(defsetf ring-ref %set-ring-ref "Set an element in a ring.")
+(defsetf mark-kind %set-mark-kind "Used to set the kind of a mark.")
+(defsetf buffer-region %set-buffer-region "Set a buffer's region.")
+(defsetf command-name %set-command-name
+  "Change a Hemlock command's name.")
+(defsetf line-string %set-line-string
+  "Replace the contents of a line.")
+(defsetf last-command-type %set-last-command-type
+  "Set the Last-Command-Type for use by the next command.")
+(defsetf logical-key-event-p %set-logical-key-event-p
+  "Change what Logical-Char= returns for the specified arguments.")
+(defsetf window-font %set-window-font
+  "Change the font-object associated with a font-number in a window.")
+(defsetf default-font %set-default-font
+  "Change the font-object associated with a font-number in new windows.")
+
+(defsetf modeline-field-name %set-modeline-field-name
+  "Sets a modeline-field's name.  If one already exists with that name, an
+   error is signaled.")
+
+;;; Shared buffer-gap context, used to communicate between command threads
+;;; and the event thread.  Note that this isn't buffer-specific; in particular,
+;;; OPEN-LINE and friends may not point at a line that belongs to any
+;;; buffer.
+
+(defstruct buffer-gap-context
+  (lock (ccl::make-lock))
+  (left-open-pos 0)
+  (right-open-pos 0)
+  (line-cache-length 200)
+  (open-line nil)
+  (open-chars (make-string 200))
+)
+
+(defun ensure-buffer-gap-context (buffer)
+  (or (buffer-gap-context buffer)
+      (setf (buffer-gap-context buffer) (make-buffer-gap-context))))
+
+(defun buffer-lock (buffer)
+  (buffer-gap-context-lock (ensure-buffer-gap-context buffer)))
+
+(defun buffer-open-line (buffer)
+  (buffer-gap-context-open-line (ensure-buffer-gap-context buffer)))
+
+(defun buffer-open-line-length (buffer)
+  (let ((context (ensure-buffer-gap-context buffer)))
+    (+ (buffer-gap-context-left-open-pos context)
+       (-   (buffer-gap-context-line-cache-length context)
+            (buffer-gap-context-right-open-pos context)))))
+
+(defun buffer-left-open-pos (buffer)
+  (buffer-gap-context-left-open-pos (ensure-buffer-gap-context buffer)))
+
+(defun buffer-right-open-pos (buffer)
+  (buffer-gap-context-right-open-pos (ensure-buffer-gap-context buffer)))
+
+(defun buffer-open-chars (buffer)
+  (buffer-gap-context-open-chars (ensure-buffer-gap-context buffer)))
+
+(defun current-gap-context ()
+  (unless (boundp '*current-buffer*)
+    (error "Gap context not bound"))
+  (ensure-buffer-gap-context *current-buffer*))
+
+(defun current-line-cache-length ()
+  (buffer-gap-context-line-cache-length (current-gap-context)))
+
+(defun (setf current-line-cache-length) (len)
+  (setf (buffer-gap-context-line-cache-length (current-gap-context)) len))
+
+(defun current-open-line ()
+  (buffer-gap-context-open-line (current-gap-context)))
+
+(defun current-open-line-p (line)
+  (eq line (current-open-line)))
+
+(defun (setf current-open-line) (value)
+  (setf (buffer-gap-context-open-line (current-gap-context)) value))
+
+(defun current-open-chars ()
+  (buffer-gap-context-open-chars (current-gap-context)))
+
+(defun (setf current-open-chars) (value)
+  (setf (buffer-gap-context-open-chars (current-gap-context)) value))
+  
+(defun current-left-open-pos ()
+  (buffer-gap-context-left-open-pos (current-gap-context)))
+
+(defun (setf current-left-open-pos) (value)
+  (setf (buffer-gap-context-left-open-pos (current-gap-context)) value))
+
+(defun current-right-open-pos ()
+  (buffer-gap-context-right-open-pos (current-gap-context)))
+
+(defun (setf current-right-open-pos) (value)
+  (setf (buffer-gap-context-right-open-pos (current-gap-context)) value))
Index: /branches/new-random/cocoa-ide/hemlock/src/symbol-completion.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/symbol-completion.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/symbol-completion.lisp	(revision 13309)
@@ -0,0 +1,392 @@
+;;; -*- Package: Hemlock -*-
+;;;
+;;; Copyright (c) 2007 Clozure Associates
+;;; This file is part of Clozure Common Lisp.
+;;;
+;;; Dynamic symbol completion
+;;; gz@clozure.com
+;;;
+;;; This uses wordchar attributes set up in completion.lisp, but otherwise is unrelated.
+
+(in-package :hemlock)
+
+;; Context maintained so repeated M-/'s can walk through all available abbreviations
+
+(defstruct (dabbrev-context (:conc-name "DABBREV."))
+  ;; The buffer this context belongs to
+  (buffer nil)
+  ;; The last expansion
+  (expansion nil)
+  ;; The thing that was expanded.  This is usually a prefix of expansion, but it might
+  ;; be initials (i.e. abbrev = mvb, expansion = multiple-value-bind).
+  (abbrev "" :type simple-string)
+  ;; The package prefix if any, including the ending colon(s).
+  (prefix nil)
+  ;; The position of the end of the expansion
+  (end-mark nil)
+  ;; buffer-signature as of the time the expansion was inserted.
+  (signature nil)
+  ;; list of expansions already tried and rejected
+  (seen ())
+  ;; List of places to try next
+  (state-path '(:before-point :after-point :other-buffers :this-package :other-packages))
+  ;; Sequence of sources to go thru before changing state
+  (sources '(:last-used))
+  ;; a sequence of expansions to go thru before changing source
+  (seq (make-array 10 :fill-pointer 0 :adjustable t)))
+
+(defun symbol-completion-buffer-hook (buffer)
+  (defhvar "DAbbrev Context"
+    "Internal variable for cycling through symbol completions"
+    :buffer buffer
+    :value nil)
+  (defhvar "DAbbrev Cache"
+    "Internal variable for caching symbols in buffer"
+    :buffer buffer
+    ;; Cons of buffer sig and a vector of all symbols in buffer as of the time
+    ;; of the buffer sig.
+    :value (cons nil nil))
+  )
+
+(add-hook make-buffer-hook #'symbol-completion-buffer-hook)
+
+;; Global table of all abbrevs expanded in this session, and the last value they expanded to.
+(defvar *dabbrevs* (make-hash-table :test #'equalp))
+
+(defun dabbrev-package (context)
+  (or (dabbrev-package-for-prefix (dabbrev.prefix context))
+      ;; TODO: look for in-package form preceeding point...
+      (buffer-package (dabbrev.buffer context))))
+
+(defun dabbrev-external-symbol-p (context)
+  ;; True if explicitly looking for an external symbol.
+  (let* ((prefix (dabbrev.prefix context))
+	 (prefix-len (length prefix)))
+    (or (eql prefix-len 1)
+	(and (>= prefix-len 2)
+	     (not (eql (aref prefix (- prefix-len 2)) #\:))))))
+
+(defun dabbrev-package-for-prefix (prefix)
+  (when prefix
+    (let* ((prefix-len (length prefix)))
+      (if (eql prefix-len 1)
+	ccl::*keyword-package*
+	(find-package (subseq prefix 0 (if (eql (aref prefix (- prefix-len 2)) #\:)
+					 (- prefix-len 2)
+					 (- prefix-len 1))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; State machine support:
+
+(defun dabbrev-next-expansion (context)
+  (cond ((> (length (dabbrev.seq context)) 0)
+	 (let* ((exp (vector-pop (dabbrev.seq context))))
+	   (if (find exp (dabbrev.seen context) :test #'string=)
+	     (dabbrev-next-expansion context)
+	     exp)))
+	((dabbrev.sources context)
+	 (dabbrev-collect-expansions (pop (dabbrev.sources context)) context)
+	 (dabbrev-next-expansion context))
+	((dabbrev.state-path context)
+	 (setf (dabbrev.sources context)
+	       (dabbrev-sources-in (pop (dabbrev.state-path context)) context))
+	 (dabbrev-next-expansion context))
+	(t nil)))
+
+
+;; dabbrev-sources-in: maps state -> sources
+
+(defmethod dabbrev-sources-in ((state t) context)
+  (declare (ignore context))
+  (list state))
+
+(defmethod dabbrev-sources-in ((state (eql :other-buffers)) context)
+  (let* ((buffers (mapcar #'hemlock-view-buffer (hemlock-ext:all-hemlock-views))))
+    ;; Remove duplicates, always keeping the first occurance (frontmost window)
+    (loop for blist on buffers do (setf (cdr blist) (delete (car blist) (cdr blist))))
+    (delete (dabbrev.buffer context) buffers)))
+
+(defmethod dabbrev-sources-in ((state (eql :other-packages)) context)
+  (let* ((all (copy-list (list-all-packages)))
+	 (this-package (dabbrev-package context))
+	 (keyword-package ccl::*keyword-package*))
+    (setq all (delete this-package all))
+    (unless (eq this-package keyword-package)
+      (setq all (nconc (delete keyword-package all) (list keyword-package))))
+    all))
+
+;; dabbrev-collect-expansion: maps source -> expansions
+;; Note that in general these methods don't bother to check for dabbrev.seen
+;; or duplicates, even though they could, because there is no reason to spend
+;; time up front on checking expansions we might never get to.
+
+(defun dabbrev-match-p (context exp)
+  (let* ((abbrev (dabbrev.abbrev context))
+	 (abbrev-len (length abbrev)))
+    (or (and (< abbrev-len (length exp))
+	     (string-equal abbrev exp :end1 abbrev-len :end2 abbrev-len))
+	;; Check for initials.
+	(loop
+	  for char across abbrev
+	  for pos = 0 then (and (setq pos (position-if-not #'alphanumericp exp :start pos))
+				(position-if #'alphanumericp exp :start (1+ pos)))
+	  always (and pos (char-equal char (aref exp pos)))))))
+
+(defmethod dabbrev-collect-expansions ((source (eql :last-used)) context)
+  (let* ((abbrev (dabbrev.abbrev context))
+	 (prefix (dabbrev.prefix context))
+	 (abbrev-len (length abbrev))
+	 (prefix-len (length prefix))
+	 (string (concatenate 'string abbrev prefix)))
+    (loop
+      for end from (+ abbrev-len prefix-len) downto prefix-len
+      for key = string then (subseq string 0 end)
+      as exp = (gethash key *dabbrevs*)
+      when (and exp (dabbrev-match-p context exp))
+      do (return (vector-push-extend exp (dabbrev.seq context))))))
+
+(defmethod dabbrev-collect-expansions ((buffer buffer) context)
+  ;; TODO: need to take prefix into account - give preferences to things
+  ;; matching prefix.  For now, ignore the prefix-only case here since can't
+  ;; do anything useful.
+  (unless (equal (dabbrev.abbrev context) "")
+    (let* ((vec (dabbrev-symbols-in-buffer buffer))
+	   (seq (dabbrev.seq context)))
+      (loop
+	for exp across vec
+	when (dabbrev-match-p context exp)
+	do (vector-push-extend exp seq))
+      seq)))
+
+;; TODO: have a background process that does this. (Since the architecture doesn't allow locking
+;; against buffer changes, might need to do ignore-errors and just bludgeon through, checking
+;; for sig changes at end.  Or perhaps could use the modification hook, if that's reliable)
+(defun dabbrev-symbols-in-buffer (buffer)
+  (let* ((cache (variable-value 'dabbrev-cache :buffer buffer)))
+    (unless (and cache (eql (car cache) (buffer-signature buffer)))
+      (let* ((hi::*current-buffer* buffer)
+	     (start-mark (buffer-start-mark buffer))
+	     (symbols (make-array 100 :adjustable t :fill-pointer 0)))
+	(with-mark ((word-start start-mark)
+		    (word-end start-mark))
+	  (loop
+	    (unless (find-attribute word-end :completion-wordchar) (return))
+	    (move-mark word-start word-end)
+	    (unless (find-not-attribute word-end :completion-wordchar)
+	      (buffer-end word-end))
+	    (let* ((word (region-to-string (region word-start word-end))))
+	      (unless (find word symbols :test #'equal)
+		(vector-push-extend word symbols)))))
+	(setf (variable-value 'dabbrev-cache :buffer buffer)
+	      (setq cache (cons (buffer-signature buffer) (coerce symbols 'simple-vector))))))
+    (cdr cache)))
+
+(defun dabbrev-next-in-buffer (mark temp-mark temp-string)
+  ;; Leaves temp-mark at start and point-mark at end of next symbol
+  (when (find-attribute mark :completion-wordchar)
+    (move-mark temp-mark mark)
+    (unless (find-not-attribute mark :completion-wordchar)
+      (buffer-end mark))
+    (region-to-string (region temp-mark mark) temp-string)))
+
+(defun dabbrev-prev-in-buffer (mark temp-mark temp-string)
+  (when (reverse-find-attribute mark :completion-wordchar)
+    (move-mark temp-mark mark)
+    (unless (reverse-find-not-attribute mark :completion-wordchar)
+      (buffer-start mark))
+    (region-to-string (region mark temp-mark) temp-string)))
+
+(defmethod dabbrev-collect-expansions ((source (eql :before-point)) context)
+  (dabbrev-collect-expansions-1 source context))
+
+(defmethod dabbrev-collect-expansions ((source (eql :after-point)) context)
+  (dabbrev-collect-expansions-1 source context))
+
+(defun dabbrev-collect-expansions-1 (direction context)
+  (let* ((buffer (dabbrev.buffer context))
+	 (point (buffer-point buffer))
+	 (abbrev (dabbrev.abbrev context))
+	 (abbrev-len (length abbrev))
+	 (seq (dabbrev.seq context))
+	 (temp-string (make-string 30)))
+    ;; TODO: need to take prefix into account - give preferences to things
+    ;; matching prefix.  For now, ignore the prefix-only case here since can't
+    ;; do anything useful.
+    (when (eql abbrev-len 0)
+      (return-from dabbrev-collect-expansions-1))
+    (with-mark ((mark point) (temp-mark point))
+      (when (eq direction :before-point) (character-offset mark (- abbrev-len)))
+      (loop
+	(multiple-value-bind (word word-len)
+			     (if (eq direction :before-point)
+			       (dabbrev-prev-in-buffer mark temp-mark temp-string)
+			       (dabbrev-next-in-buffer mark temp-mark temp-string))
+	  (unless word (return))
+	  (when (and (< abbrev-len word-len)
+		     (string-equal word abbrev :end1 abbrev-len :end2 abbrev-len))
+	    (let* ((word (subseq word 0 word-len)))
+	      (unless (find word seq :test #'equal)
+		(vector-push-extend word seq)))))))
+    (nreverse seq)))
+
+(defmethod dabbrev-collect-expansions ((source (eql :this-package)) context)
+  (let* ((pkg (dabbrev-package context))
+	 (seq (dabbrev.seq context)))
+    (when pkg
+      (when (dabbrev.prefix context)
+	(if (or (dabbrev-external-symbol-p context)
+		(eq pkg ccl::*keyword-package*))
+	  (do-external-symbols (sym pkg)
+	    (when (and (not (find sym seq :test #'eq))
+		       (dabbrev-match-p context (symbol-name sym)))
+	      (vector-push-extend sym seq)))
+	  (ccl::do-present-symbols (sym pkg)
+	    (when (and (not (find sym seq :test #'eq))
+		       (dabbrev-match-p context (symbol-name sym)))
+	      (vector-push-extend sym seq)))))
+      (unless (eq pkg ccl::*keyword-package*)
+	(do-symbols (sym pkg)
+	  (when (and (not (find sym seq :test #'eq))
+		     (dabbrev-match-p context (symbol-name sym)))
+	    (vector-push-extend sym seq))))
+      (setq seq
+	    (stable-sort seq #'(lambda (s1 s2)
+				 (and (or (boundp s1) (fboundp s1))
+				      (not (or (boundp s2) (fboundp s2)))))))
+      ;; Now convert to strings - and downcase for inserting in buffer.
+      (dotimes (i (length seq))
+	(setf (aref seq i) (string-downcase (symbol-name (aref seq i))))))
+    seq))
+
+(defmethod dabbrev-collect-expansions ((pkg package) context)
+  ;; For random packages, only need to do present symbols, since imported ones will be
+  ;; shown in their own package.
+  (let* ((seq (dabbrev.seq context)))
+    (ccl::do-present-symbols (sym pkg)
+      (let* ((name (symbol-name sym)))
+	(when (dabbrev-match-p context name)
+	  (vector-push-extend (string-downcase name) seq))))
+    seq))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; the command
+
+
+(defcommand "Expand Dynamic Abbreviation" (p)
+  "Treats the symbol before point as an abbreviation and expands it.
+It checks the following in order until a suitable expansion is found:
+  - last accepted expansion for this abbreviation, if any
+  - symbols in current buffer before point
+  - symbols in current buffer after point
+  - symbols in all other editor windows, front to back
+  - symbols visible in the current package, fbound/bound symbols first
+  - symbols in all other packages (in no particular order)
+
+If called repeatedly from the same position, replaces the previous expansion
+with the next possible one.
+
+A symbol is a suitable expansion for an abbreviation if the abbreviation is
+a proper prefix of the symbol, or the abbreviation consists of the initials
+of the individual words within the symbol (e.g. mvb => multiple-value-bind).
+"
+  (declare (ignore p))
+  (let* ((buffer (current-buffer))
+	 (point (buffer-point buffer))
+	 (context (dabbrev-command-init buffer))
+	 (abbrev (dabbrev.abbrev context))
+	 (abbrev-len (length abbrev))
+	 (expansion (dabbrev-next-expansion context))
+	 (expansion-len (length expansion)))
+    (when (null expansion)
+      (editor-error "No~:[ more~;~] expansions for ~s"
+		    (null (dabbrev.expansion context))
+		    abbrev))
+    (push expansion (dabbrev.seen context))
+    (setf (dabbrev.expansion context) expansion)
+    (setf (gethash abbrev *dabbrevs*) expansion)
+    (if (and (>= expansion-len abbrev-len)
+	     (string= abbrev expansion :end2 abbrev-len))
+      (insert-string point (subseq expansion abbrev-len))
+      (progn
+	(delete-characters point (- abbrev-len))
+	(insert-string point expansion)))
+    (move-mark (dabbrev.end-mark context) point)
+    (setf (dabbrev.signature context) (buffer-signature buffer))))
+
+#+gz ;; This tests the generation of completion candidates
+;; (time(hemlock::test-completions (cadr hi::*buffer-list*) "dabbrev"))
+(defun test-completions (buffer abbrev)
+  (let* ((hi::*current-buffer* buffer)
+	 (point (buffer-point buffer))
+	 (context (make-dabbrev-context
+		   :buffer buffer
+		   :abbrev abbrev
+		   ;; Can use a temp mark (i.e. the kind that doesn't automatically
+		   ;; update) because we only use it while buffer is unmodified.
+		   :end-mark (copy-mark point :temporary))))
+    (loop as expansion = (dabbrev-next-expansion context) while expansion
+      do (push expansion (dabbrev.seen context))
+      do (setf (dabbrev.expansion context) expansion)
+      do (setf (gethash abbrev *dabbrevs*) expansion))
+    (dabbrev.seen context)))
+
+;; Reinitialize context to either restart or cycle to next completion.
+;; In the latter case, undoes the last completion in the buffer.
+(defun dabbrev-command-init (buffer)
+  (let* ((point (buffer-point buffer))
+	 (context (variable-value 'dabbrev-context :buffer buffer)))
+    (if (and context
+	     ;; If buffer not modified since last time
+	     (eql (dabbrev.signature context) (buffer-signature buffer))
+	     ;; and cursor not moved elsewhere
+	     (mark= (dabbrev.end-mark context) point))
+      ;; This means rejected previous attempt, get rid of it.
+      (let* ((abbrev (dabbrev.abbrev context))
+	     (abbrev-len (length abbrev))
+	     (expansion (dabbrev.expansion context))
+	     (expansion-len (length expansion)))
+	;; Sanity check, because I don't totally trust buffer-signature ...
+	(with-mark ((mark point))
+	  (assert (and (character-offset mark (- (length expansion)))
+		       (equal (region-to-string (region mark point)) expansion))
+		  () "Bug! Buffer changed unexpectedly"))
+	(if (and (>= expansion-len abbrev-len)
+		 (string= abbrev expansion :end2 abbrev-len))
+	  (delete-characters point (- abbrev-len expansion-len))
+	  (progn
+	    (delete-characters point (- expansion-len))
+	    (insert-string point abbrev))))
+      ;; Else starting a new attempt, create a new context
+      (let* ((mark (copy-mark point :temporary)))
+	(multiple-value-bind (abbrev prefix) (dabbrev-get-abbrev mark point)
+	  (when (and (equal abbrev "") (equal prefix ""))
+	    (editor-error "Nothing to expand"))
+	  (setq context (make-dabbrev-context
+			 :buffer buffer
+			 :abbrev abbrev
+			 :prefix prefix
+			 ;; Can use a temp mark (i.e. the kind that doesn't automatically
+			 ;; update) because we only use it while buffer is unmodified.
+			 :end-mark mark)))
+	(setf (variable-value 'dabbrev-context :buffer buffer) context)))
+    (move-mark (dabbrev.end-mark context) point)
+    context))
+
+(defun dabbrev-get-abbrev (mark point)
+  (declare (values abbrev package-prefix))
+  (move-mark mark point)
+  (unless (reverse-find-not-attribute mark :completion-wordchar)
+    (buffer-start mark))
+  (values (region-to-string (region mark point))
+	  (when (eql (previous-character mark) #\:)
+	    (with-mark ((temp mark))
+	      (character-offset temp -1)
+	      (when (eql (previous-character temp) #\:)
+		(character-offset temp -1))
+	      (unless (reverse-find-not-attribute temp :completion-wordchar)
+		(buffer-start temp))
+	      (region-to-string (region temp mark))))))
+
+
Index: /branches/new-random/cocoa-ide/hemlock/src/syntax.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/syntax.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/syntax.lisp	(revision 13309)
@@ -0,0 +1,597 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock syntax table routines.
+;;;
+;;; Written by Rob MacLachlan.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Character attribute caching.
+;;;
+;;;    In order to permit the %SP-Find-Character-With-Attribute sub-primitive
+;;; to be used for a fast implementation of find-attribute and
+;;; reverse-find-attribute, there must be some way of translating 
+;;; attribute/test-function pairs into a attribute vector and a mask.
+;;;    What we do is maintain a eq-hash-cache of attribute/test-function
+;;; pairs.  If the desired pair is not in the cache then we reclaim an old
+;;; attribute bit in the bucket we hashed to and stuff it by calling the
+;;; test function on the value of the attribute for all characters.
+
+(defvar *character-attribute-cache* ()
+  "This is the cache used to translate attribute/test-function pairs to
+  attribute-vector/mask pairs for find-attribute and reverse-find-attribute.")
+
+(defconstant character-attribute-cache-size 13
+  "The number of buckets in the *character-attribute-cache*.")
+(defconstant character-attribute-bucket-size 3
+  "The number of bits to use in each bucket of the
+  *character-attribute-cache*.")
+
+
+(defconstant character-attribute-cache-size 13
+  "The number of buckets in the character-attribute-cache.")
+(defconstant character-attribute-bucket-size 3
+  "The number of bits to use in each bucket of the character-attribute-cache.")
+
+(defstruct (shadow-syntax (:conc-name "SS-"))
+  ;;;    In addition, since a common pattern in code which uses find-attribute
+  ;;; is to repeatedly call it with the same function and attribute, we
+  ;;; remember the last attribute/test-function pair that was used, and check
+  ;;; if it is the same pair beforehand, thus often avoiding the hastable lookup.
+  ;; TODO: another common pattern is to use the same attribute but
+  ;;       different functions (toggling between zerop and not-zerop), so
+  ;;       should use a scheme that handles that - this doesn't.
+  ;; The attribute which we last did a find-attribute on
+  (last-find-attribute-attribute ())
+  ;; The last test-function used for find-attribute.
+  (last-find-attribute-function ())
+  ;; The %SP-Find-Character-With-Attribute vector corresponding to the last
+  ;; attribute/function pair used for find-attribute.
+  (last-find-attribute-vector ())
+  ;; The the mask to use with *last-find-attribute-vector* to do a search
+  ;; for the last attribute/test-function pair.
+  (last-find-attribute-mask ())
+  ;; The the value of End-Wins for the last attribute/test-function pair.
+  (last-find-attribute-end-wins ())
+
+  ;; The last character attribute which was asked for
+  (last-character-attribute-requested nil)
+  ;; The value of the most recent character attribute
+  (value-of-last-character-attribute-requested #() :type (simple-array * (*)))
+
+  ;; list of shadowed bits.
+  (shadow-bit-descriptors ())
+  ;; List of shadowed attribute vectors
+  (shadow-attributes ())
+  ;; Syntax tick count at the time shadow info was computed.
+  (global-syntax-tick -1))
+
+(defvar *global-syntax-tick* 0 "Tick count noting changes in global syntax settings")
+
+(declaim (special *current-buffer*))
+
+
+(declaim (inline current-buffer-shadow-syntax))
+(defun current-buffer-shadow-syntax ()
+  (let ((buffer *current-buffer*))
+    (when buffer
+      (let ((ss (buffer-shadow-syntax buffer)))
+	(if (and ss (eql (ss-global-syntax-tick ss) *global-syntax-tick*))
+	  ss
+	  (progn
+	    (%init-shadow-attributes buffer)
+	    (buffer-shadow-syntax buffer)))))))
+
+(defvar *character-attributes* (make-hash-table :test #'eq)
+  "A hash table which translates character attributes to their values.")
+
+(declaim (special *character-attribute-names*))
+
+
+;;; Each bucket contains a list of character-attribute-bucket-size
+;;; bit-descriptors.
+;;;
+(defstruct (bit-descriptor)
+  function		      ; The test on the attribute.
+  attribute		      ; The attribute this is a test of.
+  (mask 0 :type fixnum)	      ; The mask for the corresponding bit.
+  vector		      ; The vector the bit is in.
+  end-wins)		      ; Is this test true of buffer ends?
+
+;;;
+;;; In a descriptor for an unused bit, the function is nil, preventing a
+;;; hit.  Whenever we change the value of an attribute for some character,
+;;; we need to flush the cache of any entries for that attribute.  Currently
+;;; we do this by mapping down the list of all bit descriptors.  Note that
+;;; we don't have to worry about GC, since this is just a hint.
+;;;
+(defvar *all-bit-descriptors* () "The list of all the bit descriptors.")
+
+
+
+(defmacro allocate-bit (vec bit-num)
+  `(progn
+    (when (= ,bit-num 8)
+      (setq ,bit-num 0  ,vec (make-array 256 :element-type '(mod 256))))
+    (car (push (make-bit-descriptor
+		:vector ,vec
+		:mask (ash 1 (prog1 ,bit-num (incf ,bit-num))))
+	       *all-bit-descriptors*))))
+;;;    
+(defun %init-syntax-table ()
+  (let ((tab (make-array character-attribute-cache-size))
+	(bit-num 8) vec)
+    (setq *character-attribute-cache* tab)
+    (dotimes (c character-attribute-cache-size)
+      (setf (svref tab c)
+	    (do ((i 0 (1+ i))
+		 (res ()))
+		((= i character-attribute-bucket-size) res)
+	      (push (allocate-bit vec bit-num) res))))))
+
+
+#+NIL
+(defmacro hash-it (attribute function)
+  `(abs (rem (logxor (ash (lisp::%sp-make-fixnum ,attribute) -3)
+		     (lisp::%sp-make-fixnum ,function))
+	     character-attribute-cache-size)))
+(defmacro hash-it (attribute function)
+  `(abs (rem (logxor (ash (sxhash ,attribute) -3)
+		     (sxhash ,function))
+	     character-attribute-cache-size)))
+
+;;; CACHED-ATTRIBUTE-LOOKUP  --  Internal
+;;;
+;;;    Sets Vector and Mask such that they can be used as arguments
+;;; to %sp-find-character-with-attribute to effect a search with attribute 
+;;; Attribute and test Function.  If the function and attribute
+;;; are the same as the last ones then we just set them to that, otherwise
+;;; we do the hash-cache lookup and update the *last-find-attribute-<mumble>*
+;;;
+(defmacro cached-attribute-lookup (attribute function vector mask end-wins)
+  `(let ((ss (current-buffer-shadow-syntax)))
+     (if (and (eq ,function (ss-last-find-attribute-function ss))
+	      (eq ,attribute (ss-last-find-attribute-attribute ss)))
+       (setq ,vector (ss-last-find-attribute-vector ss)
+	     ,mask (ss-last-find-attribute-mask ss)
+	     ,end-wins (ss-last-find-attribute-end-wins ss))
+       (let ((b (or (loop for b in (ss-shadow-bit-descriptors ss)
+		      when (and (eq (bit-descriptor-attribute b) ,attribute)
+				(eq (bit-descriptor-function b) ,function))
+		      return b)
+		    (loop for b in (svref *character-attribute-cache*
+					  (hash-it ,attribute ,function))
+		      when (and (eq (bit-descriptor-attribute b) ,attribute)
+				(eq (bit-descriptor-function b) ,function))
+		      return b))))
+	 (cond (b 
+		(setq ,vector (bit-descriptor-vector b)
+		      ,mask (bit-descriptor-mask b)
+		      ,end-wins (bit-descriptor-end-wins b)))
+	       (t
+		(multiple-value-setq (,vector ,mask ,end-wins)
+		  (new-cache-attribute ,attribute ,function))))
+	 (setf (ss-last-find-attribute-attribute ss) ,attribute
+	       (ss-last-find-attribute-function ss) ,function
+	       (ss-last-find-attribute-vector ss) ,vector
+	       (ss-last-find-attribute-mask ss) ,mask
+	       (ss-last-find-attribute-end-wins ss) ,end-wins)))))
+
+;;; NEW-CACHE-ATTRIBUTE  --  Internal
+;;;
+;;;    Pick out an old attribute to punt out of the cache and put in the
+;;; new one.  We pick a bit off of the end of the bucket and pull it around
+;;; to the beginning to get a degree of LRU'ness.
+;;;
+(defun new-cache-attribute (attribute function)
+  (let* ((hash (hash-it attribute function))
+	 (values (or (gethash attribute *character-attributes*)
+		     (error "~S is not a defined character attribute."
+			    attribute)))
+	 (bucket (svref *character-attribute-cache* hash))
+	 (bit (nthcdr (- character-attribute-bucket-size 2) bucket))
+	 (end-wins (funcall function (attribute-descriptor-end-value values))))
+    (shiftf bit (cdr bit) nil)
+    (setf (svref *character-attribute-cache* hash) bit
+	  (cdr bit) bucket  bit (car bit))
+    (setf (bit-descriptor-attribute bit) attribute
+	  (bit-descriptor-function bit) function
+	  (bit-descriptor-end-wins bit) end-wins)
+    (incf *global-syntax-tick*)
+    (setq values (attribute-descriptor-vector values))
+    (do ((mask (bit-descriptor-mask bit))
+	 (fun (bit-descriptor-function bit))
+	 (vec (bit-descriptor-vector bit))
+	 (i 0 (1+ i)))
+	((= i syntax-char-code-limit) (values vec mask end-wins))
+      (declare (type (simple-array (mod 256)) vec))
+      (if (funcall fun (aref (the simple-array values) i))
+	(setf (aref vec i) (logior (aref vec i) mask))
+	(setf (aref vec i) (logandc2 (aref vec i) mask))))))
+
+
+(defun %print-attribute-descriptor (object stream depth)
+  (declare (ignore depth))
+  (format stream "#<Hemlock Attribute-Descriptor ~S>"
+	  (attribute-descriptor-name object)))
+
+;;; DEFATTRIBUTE  --  Public
+;;;
+;;;    Make a new vector of some type and enter it in the table.
+;;;
+(defun defattribute (name documentation &optional (type '(mod 2))
+			  (initial-value 0))
+  "Define a new Hemlock character attribute with named Name with
+  the supplied Documentation, Type and Initial-Value.  Type
+  defaults to (mod 2) and Initial-Value defaults to 0."
+  (setq name (coerce name 'simple-string))
+  (let* ((attribute (string-to-keyword name))
+	 (new (make-attribute-descriptor
+	       :vector (make-array syntax-char-code-limit
+				   :element-type type
+				   :initial-element initial-value)
+	       :name name
+	       :keyword attribute
+	       :documentation documentation
+	       :end-value initial-value)))
+    (when (gethash attribute *character-attributes*)
+      (warn "Character Attribute ~S is being redefined." name))
+    (setf (getstring name *character-attribute-names*) attribute)
+    (setf (gethash attribute *character-attributes*) new))
+    (incf *global-syntax-tick*)
+  name)
+
+;;; WITH-ATTRIBUTE  --  Internal
+;;;
+;;;    Bind obj to the attribute descriptor corresponding to symbol,
+;;; giving error if it is not a defined attribute.
+;;;
+(defmacro with-attribute ((obj symbol) &body forms)
+  `(let ((,obj (gethash ,symbol *character-attributes*)))
+     (unless ,obj
+       (error "~S is not a defined character attribute." ,symbol))
+     ,@forms))
+
+(defun character-attribute-name (attribute)
+  "Return the string-name of the character-attribute Attribute."
+  (with-attribute (obj attribute)
+    (attribute-descriptor-name obj)))
+
+(defun character-attribute-documentation (attribute)
+  "Return the documentation for the character-attribute Attribute."
+  (with-attribute (obj attribute)
+    (attribute-descriptor-documentation obj)))
+
+(defun character-attribute-hooks (attribute)
+  "Return the hook-list for the character-attribute Attribute.  This can
+  be set with Setf."
+  (with-attribute (obj attribute)
+    (attribute-descriptor-hooks obj)))
+
+(defun %set-character-attribute-hooks (attribute new-value)
+  (with-attribute (obj attribute)
+    (setf (attribute-descriptor-hooks obj) new-value)))
+
+;;; CHARACTER-ATTRIBUTE  --  Public
+;;;
+;;;    Return the value of a character attribute for some character.
+;;;
+(defun character-attribute (attribute character)
+  "Return the value of the the character-attribute Attribute for Character.
+  If Character is Nil then return the end-value."
+  (let ((ss (current-buffer-shadow-syntax)))
+    (if (and character ss (eq attribute (ss-last-character-attribute-requested ss)))
+      (aref (ss-value-of-last-character-attribute-requested ss) (syntax-char-code character))
+      (sub-character-attribute attribute character))))
+;;;
+(defun sub-character-attribute (attribute character)
+  (with-attribute (obj attribute)
+    (let* ((ss (current-buffer-shadow-syntax))
+	   (cell (and ss (cdr (assoc obj (ss-shadow-attributes ss) :test #'eq)))))
+      (if character
+	(let ((vec (if cell (car cell) (attribute-descriptor-vector obj))))
+	  (when ss
+	    (setf (ss-last-character-attribute-requested ss) attribute)
+	    (setf (ss-value-of-last-character-attribute-requested ss) vec))
+	  (aref (the simple-array vec) (syntax-char-code character)))
+	(if cell (cdr cell) (attribute-descriptor-end-value obj))))))
+
+;;; CHARACTER-ATTRIBUTE-P
+;;;
+;;;    Look up attribute in table.
+;;;
+(defun character-attribute-p (symbol)
+  "Return true if Symbol is the symbol-name of a character-attribute, Nil
+  otherwise."
+  (not (null (gethash symbol *character-attributes*))))
+
+
+
+;;; %SET-CHARACTER-ATTRIBUTE  --  Internal
+;;;
+;;;    Set the global value of a character attribute.
+;;;
+(defun %set-character-attribute (attribute character new-value)
+  (with-attribute (obj attribute)
+    (invoke-hook hemlock::character-attribute-hook attribute character new-value)
+    (invoke-hook (attribute-descriptor-hooks obj) attribute character new-value)
+    (cond
+     ;;
+     ;; Setting the value for a real character.
+     (character
+      (let ((value (attribute-descriptor-vector obj))
+	    (code (syntax-char-code character)))
+	(declare (type (simple-array *) value))
+	(dolist (bit *all-bit-descriptors*)
+	  (when (eq (bit-descriptor-attribute bit) attribute)
+	    (let ((vec (bit-descriptor-vector bit)))
+	      (declare (type (simple-array (mod 256)) vec))
+	      (setf (aref vec code)
+		    (if (funcall (bit-descriptor-function bit) new-value)
+			(logior (bit-descriptor-mask bit) (aref vec code))
+			(logandc1 (bit-descriptor-mask bit) (aref vec code)))))))
+	(setf (aref value code) new-value)))
+     ;;
+     ;; Setting the magical end-value.
+     (t
+      (setf (attribute-descriptor-end-value obj) new-value)
+      (dolist (bit *all-bit-descriptors*)
+	(when (eq (bit-descriptor-attribute bit) attribute)
+	  (setf (bit-descriptor-end-wins bit)
+		(funcall (bit-descriptor-function bit) new-value))))))
+    (incf *global-syntax-tick*)
+    new-value))
+
+
+;; This is called when change buffer mode.  It used to invoke attribute-descriptor-hooks on
+;; all the shadowed attributes.  We don't do that any more, should update doc if any.
+(defun invalidate-shadow-attributes (buffer)
+  (let ((ss (buffer-shadow-syntax buffer)))
+    (when ss (setf (ss-global-syntax-tick ss) -1))))
+
+(defun %init-one-shadow-attribute (ss desc vals)
+  ;; Shadow all bits for this attribute
+  (loop with key = (attribute-descriptor-keyword desc)
+    for bit in *all-bit-descriptors*
+    when (eq key (bit-descriptor-attribute bit))
+    do (let* ((fun (bit-descriptor-function bit))
+	      (b (or (find-if #'(lambda (b)
+				  (and (eq (bit-descriptor-function b) fun)
+				       (eq (bit-descriptor-attribute b) key)))
+			      (ss-shadow-bit-descriptors ss))
+		     (let ((new (make-bit-descriptor
+				 :attribute key
+				 :function fun
+				 :vector (copy-seq (bit-descriptor-vector bit))
+				 :mask (bit-descriptor-mask bit))))
+		       (push new (ss-shadow-bit-descriptors ss))
+		       new)))
+	      (vec (bit-descriptor-vector b)))
+	 (loop for (code . value) in vals
+	   ;; Since we don't share the shadow vecs, no need to preserve other bits.
+	   do (setf (aref vec code) (if (funcall fun value) #xFF #x00)))))
+  ;; Shadow the attribute values
+  (let ((vec (cadr (or (assoc desc (ss-shadow-attributes ss) :test #'eq)
+		       (let ((new (list* desc 
+					 (copy-seq (attribute-descriptor-vector desc))
+					 (attribute-descriptor-end-value desc))))
+			 (push new (ss-shadow-attributes ss))
+			 new)))))
+    (loop for (code . value) in vals do (setf (aref vec code) value))))
+
+(defun %init-shadow-attributes (buffer)
+  (let* ((mode (buffer-major-mode-object buffer))
+	 (ss (or (buffer-shadow-syntax buffer)
+		 (setf (buffer-shadow-syntax buffer) (make-shadow-syntax)))))
+    (loop for (desc .  vals) in (mode-object-character-attributes mode)
+      do (%init-one-shadow-attribute ss desc vals))
+    (setf (ss-last-find-attribute-attribute ss) nil)
+    (setf (ss-last-find-attribute-function ss) nil)
+    (setf (ss-global-syntax-tick ss) *global-syntax-tick*)))
+
+(declaim (special *mode-names*))
+
+;;; SHADOW-ATTRIBUTE  --  Public
+;;;
+;;;    Stick mode character attribute information in the mode object.
+;;;
+(defun shadow-attribute (attribute character value mode)
+  "Make a mode specific character attribute value.  The value of
+  Attribute for Character when we are in Mode will be Value."
+  (let ((desc (gethash attribute *character-attributes*))
+	(obj (getstring mode *mode-names*)))
+    (unless desc
+      (error "~S is not a defined Character Attribute." attribute))
+    (unless obj (error "~S is not a defined Mode." mode))
+    (let* ((current (assoc desc (mode-object-character-attributes obj)))
+	   (code (syntax-char-code character))
+	   (cons (cons code value)))
+      (if current
+	  (let ((old (assoc code (cdr current))))
+	    (if old
+		(setf (cdr old) value  cons old)
+		(push cons (cdr current))))
+	  (push (list desc cons)
+		(mode-object-character-attributes obj)))
+      (incf *global-syntax-tick*)
+      (invoke-hook hemlock::shadow-attribute-hook attribute character value mode)))
+  attribute)
+
+;;; UNSHADOW-ATTRIBUTE  --  Public
+;;;
+;;;    Nuke a mode character attribute.
+;;;
+(defun unshadow-attribute (attribute character mode)
+  "Make the value of Attribte for Character no longer shadowed in Mode."
+  (let ((desc (gethash attribute *character-attributes*))
+	(obj (getstring mode *mode-names*)))
+    (unless desc
+      (error "~S is not a defined Character Attribute." attribute))
+    (unless obj
+      (error "~S is not a defined Mode." mode))
+    (invoke-hook hemlock::shadow-attribute-hook mode attribute character)
+    (let* ((current (assoc desc (mode-object-character-attributes obj)))
+	   (char (assoc (syntax-char-code character) (cdr current))))
+      (unless char
+	(error "Character Attribute ~S is not defined for character ~S ~
+	       in Mode ~S." attribute character mode))
+      (incf *global-syntax-tick*)
+      (setf (cdr current) (delete char (the list (cdr current))))))
+  attribute)
+
+
+
+;;; NOT-ZEROP, the default test function for find-attribute etc.
+;;;
+(defun not-zerop (n)
+  (not (zerop n)))
+
+;;; find-attribute  --  Public
+;;;
+;;;    Do hairy cache lookup to find a find-character-with-attribute style
+;;; vector that we can use to do the search.
+;;;
+(defmacro normal-find-attribute (line start result vector mask)
+  `(let ((chars (line-chars ,line)))
+     (setq ,result (%sp-find-character-with-attribute
+		   chars ,start (strlen chars) ,vector ,mask))))
+;;;
+(defmacro cache-find-attribute (start result vector mask)
+  `(let ((gap (- (current-right-open-pos) (current-left-open-pos))))
+     (declare (fixnum gap))
+     (cond
+      ((>= ,start (current-left-open-pos))
+       (setq ,result
+	     (%sp-find-character-with-attribute
+	      (current-open-chars) (+ ,start gap) (current-line-cache-length) ,vector ,mask))
+       (when ,result (decf ,result gap)))
+      ((setq ,result (%sp-find-character-with-attribute
+		      (current-open-chars) ,start (current-left-open-pos) ,vector ,mask)))
+      (t
+       (setq ,result
+	     (%sp-find-character-with-attribute
+	      (current-open-chars) (current-right-open-pos) (current-line-cache-length) ,vector ,mask))
+       (when ,result (decf ,result gap))))))
+
+;;;
+(defun find-attribute (mark attribute &optional (test #'not-zerop))
+  "Find the next character whose attribute value satisfies test."
+  (let ((charpos (mark-charpos mark))
+	(line (mark-line mark))
+	(mask 0)
+	vector end-wins)
+    (declare (type (or (simple-array (mod 256)) null) vector) (fixnum mask)
+	     (type (or fixnum null) charpos))
+    (cached-attribute-lookup attribute test vector mask end-wins)
+    (cond
+     ((cond
+       ((current-open-line-p line)
+	(when (cache-find-attribute charpos charpos vector mask)
+	  (setf (mark-charpos mark) charpos) mark))
+       (t
+	(when (normal-find-attribute line charpos charpos vector mask)
+	  (setf (mark-charpos mark) charpos) mark))))
+     ;; Newlines win and there is one.
+     ((and (not (zerop (logand mask (aref vector (char-code #\newline)))))
+	   (line-next line))
+      (move-to-position mark (line-length line) line))
+     ;; We can ignore newlines.
+     (t
+      (do (prev)
+	  (())
+	(setq prev line  line (line-next line))
+	(cond
+	 ((null line)
+	  (if end-wins
+	      (return (line-end mark prev))
+	      (return nil)))
+	 ((current-open-line-p line)
+	  (when (cache-find-attribute 0 charpos vector mask)
+	    (return (move-to-position mark charpos line))))
+	 (t
+	  (when (normal-find-attribute line 0 charpos vector mask)
+	    (return (move-to-position mark charpos line))))))))))
+
+(defun find-not-attribute (mark attribute)
+  (find-attribute mark attribute #'zerop))
+
+
+;;; REVERSE-FIND-ATTRIBUTE  --  Public
+;;;
+;;;    Line find-attribute, only goes backwards.
+;;;
+(defmacro rev-normal-find-attribute (line start result vector mask)
+  `(let ((chars (line-chars ,line)))
+     (setq ,result (%sp-reverse-find-character-with-attribute
+		    chars 0 ,(or start '(strlen chars)) ,vector ,mask))))
+;;;
+(defmacro rev-cache-find-attribute (start result vector mask)
+  `(let ((gap (- (current-right-open-pos) (current-left-open-pos))))
+     (declare (fixnum gap))
+     (cond
+      ,@(when start
+	  `(((<= ,start (current-left-open-pos))
+	     (setq ,result
+		   (%sp-reverse-find-character-with-attribute
+		    (current-open-chars) 0 ,start ,vector ,mask)))))
+      ((setq ,result (%sp-reverse-find-character-with-attribute
+		      (current-open-chars) (current-right-open-pos)
+		      ,(if start `(+ ,start gap) '(current-line-cache-length))
+		      ,vector ,mask))
+       (decf ,result gap))
+      (t
+       (setq ,result
+	     (%sp-reverse-find-character-with-attribute
+	      (current-open-chars) 0 (current-left-open-pos) ,vector ,mask))))))
+
+;;;
+;;; This moves the mark so that previous-character satisfies the test.
+(defun reverse-find-attribute (mark attribute &optional (test #'not-zerop))
+  "Find the previous character whose attribute value satisfies test."
+  (let* ((charpos (mark-charpos mark))
+	 (line (mark-line mark)) vector mask end-wins)
+    (declare (type (or (simple-array (mod 256)) null) vector)
+	     (type (or fixnum null) charpos))
+    (cached-attribute-lookup attribute test vector mask end-wins)
+    (cond 
+     ((cond
+       ((current-open-line-p line)
+	(when (rev-cache-find-attribute charpos charpos vector mask)
+	  (setf (mark-charpos mark) (1+ charpos)) mark))
+       (t
+	(when (rev-normal-find-attribute line charpos charpos vector mask)
+	  (setf (mark-charpos mark) (1+ charpos)) mark))))
+     ;; Newlines win and there is one.
+     ((and (line-previous line)
+	   (not (zerop (logand mask (aref vector (char-code #\newline))))))
+      (move-to-position mark 0 line))
+     (t
+      (do (next)
+	  (())
+	(setq next line  line (line-previous line))
+	(cond
+	 ((null line)
+	  (if end-wins
+	      (return (line-start mark next))
+	      (return nil)))
+	 ((current-open-line-p line)
+	  (when (rev-cache-find-attribute nil charpos vector mask)
+	    (return (move-to-position mark (1+ charpos) line))))
+	 (t
+	  (when (rev-normal-find-attribute line nil charpos vector mask)
+	    (return (move-to-position mark (1+ charpos) line))))))))))
+
+(defun reverse-find-not-attribute (mark attribute)
+  (reverse-find-attribute mark attribute #'zerop))
Index: /branches/new-random/cocoa-ide/hemlock/src/table.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/table.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/table.lisp	(revision 13309)
@@ -0,0 +1,742 @@
+;;; -*- Log: hemlock.log; Package: hemlock-internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Reluctantly written by Christopher Hoover
+;;; Supporting cast includes Rob and Bill.
+;;;
+;;; This file defines a data structure, analogous to a Common Lisp
+;;; hashtable, which translates strings to values and facilitates
+;;; recognition and completion of these strings.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Implementation Details
+
+;;; String tables are a data structure somewhat analogous to Common Lisp
+;;; hashtables.  String tables are case-insensitive.  Functions are
+;;; provided to quickly look up strings, insert strings, disambiguate or
+;;; complete strings, and to provide a variety of ``help'' when
+;;; disambiguating or completing strings.
+;;; 
+;;; String tables are represented as a series of word tables which form
+;;; a tree.  Four structures are used to implement this data structure.
+;;; The first is a STRING-TABLE.  This structure has severals slots one
+;;; of which, FIRST-WORD-TABLE, points to the first word table.  This
+;;; first word table is also the root of tree.  The STRING-TABLE
+;;; structure also contains slots to keep track of the number of nodes,
+;;; the string table separator (which is used to distinguish word or
+;;; field boundaries), and a pointer to an array of VALUE-NODE's.
+;;; 
+;;; A WORD-TABLE is simply an array of pointers to WORD-ENTRY's.  This
+;;; array is kept sorted by the FOLDED slot in each WORD-ENTRY so that a
+;;; binary search can be used.  Each WORD-ENTRY contains a case-folded
+;;; string and a pointer to the next WORD-TABLE in the tree.  By
+;;; traversing the tree made up by these structures, searching and
+;;; completion can easily be done.
+;;; 
+;;; Another structure, a VALUE-NODE, is used to hold each entry in the
+;;; string table and contains both a copy of the original string and a
+;;; case-folded version of the original string along with the value.
+;;; All of these value nodes are stored in a array (pointed at by the
+;;; VALUE-NODES slot of the STRING-TABLE structure) and sorted by the
+;;; FOLDED slot in the VALUE-NODE structure so that a binary search may
+;;; be used to quickly find existing strings.
+;;;
+
+
+
+;;;; Structure Definitions
+
+(defparameter initial-string-table-size 20
+  "Initial size of string table array for value nodes.")
+(defparameter initial-word-table-size 2
+  "Inital size of each word table array for each tree node.")
+
+(defstruct (string-table
+	    (:constructor %make-string-table (separator))
+	    (:print-function print-string-table))
+  "This structure is used to implement the Hemlock string-table type."
+  ;; Character used to 
+  (separator #\Space :type base-char) ; character used for word separator
+  (num-nodes 0 :type fixnum)		   ; number of nodes in string table
+  (value-nodes (make-array initial-string-table-size)) ; value node array
+  (first-word-table (make-word-table)))	   ; pointer to first WORD-TABLE
+
+(defun print-string-table (table stream depth)
+  (declare (ignore table depth))
+  (format stream "#<String Table>"))
+
+(defun make-string-table (&key (separator #\Space) initial-contents)
+  "Creates and returns a Hemlock string-table.  If Intitial-Contents is
+  supplied in the form of an A-list of string-value pairs, these pairs
+  will be used to initialize the table.  If Separator, which must be a
+  base-char, is specified then it will be used to distinguish word
+  boundaries."
+  (let ((table (%make-string-table separator)))
+    (dolist (x initial-contents)
+      (setf (getstring (car x) table) (cdr x)))
+    table))
+
+
+(defstruct (word-table
+	    (:print-function print-word-table))
+  "This structure is a word-table which is part of a Hemlock string-table."
+  (num-words 0 :type fixnum)		   ; Number of words
+  (words (make-array initial-word-table-size))) ; Array of WORD-ENTRY's
+
+(defun print-word-table (table stream depth)
+  (declare (ignore table depth))
+  (format stream "#<Word Table>"))
+
+
+(defstruct (word-entry
+	    (:constructor make-word-entry (folded))
+	    (:print-function print-word-entry))
+  "This structure is an entry in a word table which is part of a Hemlock
+  string-table."
+  next-table				   ; Pointer to next WORD-TABLE
+  folded				   ; Downcased word
+  value-node)				   ; Pointer to value node or NIL
+
+(defun print-word-entry (entry stream depth)
+  (declare (ignore depth))
+  (format stream "#<Word Table Entry: \"~A\">" (word-entry-folded entry)))
+
+
+(defstruct (value-node
+	    (:constructor make-value-node (proper folded value))
+	    (:print-function print-value-node))
+  "This structure is a node containing a value in a Hemlock string-table."
+  folded				   ; Downcased copy of string
+  proper				   ; Proper copy of string entry
+  value)				   ; Value of entry
+
+(defun print-value-node (node stream depth)
+  (declare (ignore depth))
+  (format stream "<Value Node \"~A\">" (value-node-proper node)))
+
+
+
+;;;; Bi-SvPosition, String-Compare, String-Compare*
+
+;;; Much like the CL function POSITION; however, this is a fast binary
+;;; search for simple vectors.  Vector must be a simple vector and Test
+;;; must be a function which returns either :equal, :less, or :greater.
+;;; (The vector must be sorted from lowest index to highest index by the
+;;; Test function.)  Two values are returned: the first is the position
+;;; Item was found or if it was not found, where it should be inserted;
+;;; the second is a boolean flag indicating whether or not Item was
+;;; found.
+;;; 
+(defun bi-svposition (item vector test &key (start 0) end key)
+  (declare (simple-vector vector) (fixnum start))
+  (let ((low start)
+	(high (if end end (length vector)))
+	(mid 0))
+    (declare (fixnum low high mid))
+    (loop
+      (when (< high low) (return (values low nil)))
+      (setf mid (+ (the fixnum (ash (the fixnum (- high low)) -1)) low))
+      (let* ((array-item (svref vector mid))
+	     (test-item (if key (funcall key array-item) array-item)))
+	(ecase (funcall test item test-item)
+	  (:equal (return (values mid t)))
+	  (:less (setf high (1- mid)))
+	  (:greater (setf low (1+ mid))))))))
+
+;;; A simple-string comparison appropriate for use with BI-SVPOSITION.
+;;; 
+(defun string-compare (s1 s2 &key (start1 0) end1 (start2 0) end2)
+  (declare (simple-string s1 s2) (fixnum start1 start2))
+  (let* ((end1 (or end1 (length s1)))
+	 (end2 (or end2 (length s2)))
+	 (pos1 (string/= s1 s2
+			 :start1 start1 :end1 end1 :start2 start2 :end2 end2)))
+    (if (null pos1)
+	:equal
+	(let ((pos2 (+ (the fixnum pos1) (- start2 start1))))
+	  (declare (fixnum pos2))
+	  (cond ((= pos1 (the fixnum end1)) :less)
+		((= pos2 (the fixnum end2)) :greater)
+		((char< (schar s1 (the fixnum pos1)) (schar s2 pos2)) :less)
+		(t :greater))))))
+
+;;; Macro to return a closure to call STRING-COMPARE with the given
+;;; keys.
+;;; 
+(defmacro string-compare* (&rest keys)
+  `#'(lambda (x y) (string-compare x y ,@keys)))
+
+
+
+;;;; Insert-Element, Nconcf
+
+;;; Insert-Element is a macro which encapsulates the hairiness of
+;;; inserting an element into a simple vector.  Vector should be a
+;;; simple vector with Num elements (which may be less than or equal to
+;;; the length of the vector) and Element is the element to insert at
+;;; Pos.  The optional argument Grow-Factor may be specified to control
+;;; the new size of the array if a new vector is necessary.  The result
+;;; of INSERT-ELEMENT must be used as a new vector may be created.
+;;; (Note that the arguments should probably be lexicals since some of
+;;; them are evaluated more than once.)
+;;;
+;;; We clear out the old vector so that it won't hold on to garbage if it
+;;; happens to be in static space.
+;;; 
+(defmacro insert-element (vector pos element num &optional (grow-factor 2))
+  `(let ((new-num (1+ ,num))
+	 (max (length ,vector)))
+     (declare (fixnum new-num max))
+     (cond ((= ,num max)
+	    ;; grow the vector
+	    (let ((new (make-array (truncate (* max ,grow-factor)))))
+	      (declare (simple-vector new))
+	      ;; Blt the new buggers into place leaving a space for
+	      ;; the new element
+	      (replace new ,vector :end1 ,pos :end2 ,pos)
+	      (replace new ,vector :start1 (1+ ,pos) :end1 new-num
+		       :start2 ,pos :end2 ,num)
+	      (fill ,vector nil)
+	      (setf (svref new ,pos) ,element)
+	      new))
+	   (t
+	    ;; move the buggers down a slot
+	    (replace ,vector ,vector :start1 (1+ ,pos) :start2 ,pos)
+	    (setf (svref ,vector ,pos) ,element)
+	    ,vector))))
+
+(define-modify-macro nconcf (&rest args) nconc)
+
+
+
+;;;; With-Folded-String, Do-Words
+
+;;; With-Folded-String is a macro which deals with strings from the
+;;; user.  First, if the original string is not a simple string then it
+;;; is coerced to one.  Next, the string is trimmed using the separator
+;;; character and all separators between words are collapsed to a single
+;;; separator.  The word boundaries are pushed on to a list so that the
+;;; Do-Words macro can be called anywhere within the dynamic extent of a
+;;; With-Folded-String to ``do'' over the words.
+
+(defvar *separator-positions* nil)
+
+(defmacro do-words ((start-var end-var) &body body)
+  (let ((sep-pos (gensym)))
+    `(dolist (,sep-pos *separator-positions*)
+       (let ((,start-var (car ,sep-pos))
+	     (,end-var (cdr ,sep-pos)))
+         (locally
+             ,@body)))))
+
+(defmacro with-folded-string ((str-var len-var orig-str separator)
+			      &body body)
+  `(let* ((,str-var (make-string (length ,orig-str)))
+          (*separator-positions* nil))
+     (declare (simple-string ,str-var)
+              (dynamic-extent ,str-var))
+     ;; make the string simple if it isn't already
+     (unless (simple-string-p ,orig-str)
+       (setq ,orig-str (coerce ,orig-str 'simple-string)))
+     ;; munge it into stack-allocated ,str-var and do the body
+     (let ((,len-var (with-folded-munge-string ,str-var ,orig-str ,separator)))
+       ,@body)))
+
+(defun with-folded-munge-string (buf str separator)
+  (declare (simple-string str) (base-char separator))
+  (let ((str-len (length str))
+	(sep-pos nil)
+	(buf-pos 0))
+    ;; Bash the spaces out of the string remembering where the words are.
+    (let ((start-pos (position separator str :test-not #'char=)))
+      (when start-pos
+	(loop
+	  (let* ((end-pos (position separator str
+				    :start start-pos :test #'char=))
+		 (next-start-pos (and end-pos (position separator str
+							:start end-pos
+							:test-not #'char=)))
+		 (word-len (- (or end-pos str-len) start-pos))
+		 (new-buf-pos (+ buf-pos word-len)))
+	    (replace buf str
+		     :start1 buf-pos :start2 start-pos :end2 end-pos)
+	    (push (cons buf-pos new-buf-pos) sep-pos)
+	    (setf buf-pos new-buf-pos)
+	    (when (or (null end-pos) (null next-start-pos))
+	      (return))
+	    (setf start-pos next-start-pos)
+	    (setf (schar buf buf-pos) separator)
+	    (incf buf-pos)))))
+    (nstring-downcase buf :end buf-pos)
+    (setf *separator-positions* (nreverse sep-pos))
+    buf-pos))
+
+
+
+;;;; Getstring, Setf Method for Getstring
+
+(defun getstring (string string-table)
+  "Looks up String in String-Table.  Returns two values: the first is
+  the value of String or NIL if it does not exist; the second is a
+  boolean flag indicating whether or not String was found in
+  String-Table."
+  (with-folded-string (folded len string (string-table-separator string-table))
+    (let ((nodes (string-table-value-nodes string-table))
+	  (num-nodes (string-table-num-nodes string-table)))
+      (declare (simple-vector nodes) (fixnum num-nodes))
+      (multiple-value-bind
+	  (pos found-p)
+	  (bi-svposition folded nodes (string-compare* :end1 len)
+			 :end (1- num-nodes) :key #'value-node-folded)
+	(if found-p
+	    (values (value-node-value (svref nodes pos)) t)
+	    (values nil nil))))))
+
+(defun %set-string-table (string table value)
+  "Sets the value of String in Table to Value.  If necessary, creates
+  a new entry in the string table."
+  (with-folded-string (folded len string (string-table-separator table))
+    (when (zerop len)
+      (error "An empty string cannot be inserted into a string-table."))
+    (let ((nodes (string-table-value-nodes table))
+	  (num-nodes (string-table-num-nodes table)))
+      (declare (simple-string folded) (simple-vector nodes) (fixnum num-nodes))
+      (multiple-value-bind
+	  (pos found-p)
+	  (bi-svposition folded nodes (string-compare* :end1 len)
+			 :end (1- num-nodes) :key #'value-node-folded)
+	(cond (found-p
+ 	       (setf (value-node-value (svref nodes pos)) value))
+	      (t
+	       ;; Note that a separator collapsed copy of string is NOT
+	       ;; used here ...
+	       ;; 
+	       (let ((node (make-value-node string (subseq folded 0 len) value))
+		     (word-table (string-table-first-word-table table)))
+		 ;; put in the value nodes array
+		 (setf (string-table-value-nodes table)
+		       (insert-element nodes pos node num-nodes))
+		 (incf (string-table-num-nodes table))
+		 ;; insert it into the word tree
+		 (%set-insert-words folded word-table node))))))
+    value))
+
+(defun %set-insert-words (folded first-word-table value-node)
+  (declare (simple-string folded))
+  (let ((word-table first-word-table)
+	(entry nil))
+    (do-words (word-start word-end)
+      (let ((word-array (word-table-words word-table))
+	    (num-words (word-table-num-words word-table)))
+	(declare (simple-vector word-array) (fixnum num-words))
+	;; find the entry or create a new one and insert it
+	(multiple-value-bind
+	    (pos found-p)
+	    (bi-svposition folded word-array
+			   (string-compare* :start1 word-start :end1 word-end)
+			   :end (1- num-words) :key #'word-entry-folded)
+	  (declare (fixnum pos))
+	  (cond (found-p
+		 (setf entry (svref word-array pos)))
+		(t
+		 (setf entry (make-word-entry
+			      (subseq folded word-start word-end)))
+		 (setf (word-table-words word-table)
+		       (insert-element word-array pos entry num-words))
+		 (incf (word-table-num-words word-table)))))
+	(let ((next-table (word-entry-next-table entry)))
+	  (unless next-table
+	    (setf next-table (make-word-table))
+	    (setf (word-entry-next-table entry) next-table))
+	  (setf word-table next-table))))
+    (setf (word-entry-value-node entry) value-node)))
+
+
+
+;;;; Find-Bound-Entries
+
+(defun find-bound-entries (word-entries)
+  (let ((res nil))
+    (dolist (entry word-entries)
+      (nconcf res (sub-find-bound-entries entry)))
+    res))
+
+(defun sub-find-bound-entries (entry)
+  (let ((bound-entries nil))
+    (when (word-entry-value-node entry) (push entry bound-entries))
+    (let ((next-table (word-entry-next-table entry)))
+      (when next-table
+	(let ((word-array (word-table-words next-table))
+	      (num-words (word-table-num-words next-table)))
+	  (declare (simple-vector word-array) (fixnum num-words))
+	  (dotimes (i num-words)
+	    (declare (fixnum i))
+	    (nconcf bound-entries
+		    (sub-find-bound-entries (svref word-array i)))))))
+    bound-entries))
+
+
+
+;;;; Find-Ambiguous
+
+(defun find-ambiguous (string string-table)
+  "Returns a list, in alphabetical order, of all the strings in String-Table
+  which String matches."
+  (with-folded-string (folded len string (string-table-separator string-table))
+    (find-ambiguous* folded len string-table)))
+
+(defun find-ambiguous* (folded len table)
+  (let ((word-table (string-table-first-word-table table))
+	(word-entries nil))
+    (cond ((zerop len)
+	   (setf word-entries (find-ambiguous-entries "" 0 0 word-table)))
+	  (t
+	   (let ((word-tables (list word-table)))
+	     (do-words (start end)
+	       (setf word-entries nil)
+	       (dolist (wt word-tables)
+		 (nconcf word-entries
+			 (find-ambiguous-entries folded start end wt)))
+	       (unless word-entries (return))
+	       (let ((next-word-tables nil))
+		 (dolist (entry word-entries)
+		   (let ((next-word-table (word-entry-next-table entry)))
+		     (when next-word-table
+		       (push next-word-table next-word-tables))))
+		 (unless next-word-tables (return))
+		 (setf word-tables (nreverse next-word-tables)))))))
+    (let ((bound-entries (find-bound-entries word-entries))
+	  (res nil))
+      (dolist (be bound-entries)
+	(push (value-node-proper (word-entry-value-node be)) res))
+      (nreverse res))))
+
+(defun find-ambiguous-entries (folded start end word-table)
+  (let ((word-array (word-table-words word-table))
+	(num-words (word-table-num-words word-table))
+	(res nil))
+    (declare (simple-vector word-array) (fixnum num-words))
+    (unless (zerop num-words)
+      (multiple-value-bind
+	  (pos found-p)
+	  (bi-svposition folded word-array
+			 (string-compare* :start1 start :end1 end)
+			 :end (1- num-words) :key #'word-entry-folded)
+	(declare (ignore found-p))
+	;;
+	;; Find last ambiguous string, checking for the end of the table.
+	(do ((i pos (1+ i)))
+	    ((= i num-words))
+	  (declare (fixnum i))
+	  (let* ((entry (svref word-array i))
+		 (str (word-entry-folded entry))
+		 (str-len (length str))
+		 (index (string/= folded str :start1 start :end1 end
+				  :end2 str-len)))
+	    (declare (simple-string str) (fixnum str-len))
+	    (when (and index (/= index end)) (return nil))
+	    (push entry res)))
+	(setf res (nreverse res))
+	;;
+	;; Scan back to the first string, checking for the beginning.
+	(do ((i (1- pos) (1- i)))
+	    ((minusp i))
+	  (declare (fixnum i))
+	  (let* ((entry (svref word-array i))
+		 (str (word-entry-folded entry))
+		 (str-len (length str))
+		 (index (string/= folded str :start1 start :end1 end
+				  :end2 str-len)))
+	    (declare (simple-string str) (fixnum str-len))
+	    (when (and index (/= index end)) (return nil))
+	    (push entry res)))))
+    res))
+
+
+
+;;;; Find-Containing
+
+(defun find-containing (string string-table)
+  "Return a list in alphabetical order of all the strings in Table which 
+  contain String as a substring."
+  (with-folded-string (folded len string (string-table-separator string-table))
+    (declare (ignore len))
+    (let ((word-table (string-table-first-word-table string-table))
+	  (words nil))
+      ;; cons up a list of the words
+      (do-words (start end)
+	(push (subseq folded start end) words))
+      (setf words (nreverse words))
+      (let ((entries (sub-find-containing words word-table))
+	    (res nil))
+	(dolist (e entries)
+	  (push (value-node-proper (word-entry-value-node e)) res))
+	(nreverse res)))))
+
+(defun sub-find-containing (words word-table)
+  (let ((res nil)
+	(word-array (word-table-words word-table))
+	(num-words (word-table-num-words word-table)))
+    (declare (simple-vector word-array) (fixnum num-words))
+    (dotimes (i num-words)
+      (declare (fixnum i))
+      (let* ((entry (svref word-array i))
+	     (word (word-entry-folded entry))
+	     (found (find word words
+			  :test #'(lambda (y x)
+				    (let ((lx (length x))
+					  (ly (length y)))
+				      (and (<= lx ly)
+					   (string= x y :end2 lx))))))
+	     (rest-words (if found
+			     (remove found words :test #'eq :count 1)
+			     words)))
+	(declare (simple-string word))
+	(cond (rest-words
+	       (let ((next-table (word-entry-next-table entry)))
+		 (when next-table
+		   (nconcf res (sub-find-containing rest-words next-table)))))
+	      (t
+	       (nconcf res (sub-find-bound-entries entry))))))
+    res))
+
+
+
+;;;; Complete-String
+
+(defvar *complete-string-buffer-size* 128)
+(defvar *complete-string-buffer* (make-string *complete-string-buffer-size*))
+(declaim (simple-string *complete-string-buffer*))
+
+(defun complete-string (string tables)
+  "Attempts to complete the string String against the string tables in the
+   list Tables.  Tables must all use the same separator character.  See the
+   manual for details on return values."
+  (let ((separator (string-table-separator (car tables))))
+    #|(when (member separator (cdr tables)
+		  :key #'string-table-separator :test-not #'char=)
+      (error "All tables must have the same separator."))|#
+    (with-folded-string (folded len string separator)
+      (let ((strings nil))
+	(dolist (table tables)
+	  (nconcf strings (find-ambiguous* folded len table)))
+	;; pick off easy case
+	(when (null strings)
+	  (return-from complete-string (values nil :none nil nil nil)))
+	;; grow complete-string buffer if necessary
+	(let ((size-needed (1+ len)))
+	  (when (> size-needed *complete-string-buffer-size*)
+	    (let* ((new-size (* size-needed 2))
+		   (new-buffer (make-string new-size)))
+	      (setf *complete-string-buffer* new-buffer)
+	      (setf *complete-string-buffer-size* new-size))))
+	(multiple-value-bind
+	    (str ambig-pos unique-p)
+	    (find-longest-completion strings separator)
+	  (multiple-value-bind (value found-p) (find-values str tables)
+	    (let ((field-pos (compute-field-pos string str separator)))
+	      (cond ((not found-p)
+		     (values str :ambiguous nil field-pos ambig-pos))
+		    (unique-p
+		     (values str :unique value field-pos nil))
+		    (t
+		     (values str :complete value field-pos ambig-pos))))))))))
+
+(defun find-values (string tables)
+  (dolist (table tables)
+    (multiple-value-bind (value found-p) (getstring string table)
+      (when found-p
+	(return-from find-values (values value t)))))
+  (values nil nil))
+
+(defun compute-field-pos (given best separator)
+  (declare (simple-string given best) (base-char separator))
+  (let ((give-pos 0)
+	(best-pos 0))
+    (loop
+      (setf give-pos (position separator given :start give-pos :test #'char=))
+      (setf best-pos (position separator best :start best-pos :test #'char=))
+      (unless (and give-pos best-pos) (return best-pos))
+      (incf (the fixnum give-pos))
+      (incf (the fixnum best-pos)))))
+
+
+
+;;;; Find-Longest-Completion
+
+(defun find-longest-completion (strings separator)
+  (declare (base-char separator))
+  (let ((first (car strings))
+	(rest-strings (cdr strings))
+	(punt-p nil)
+	(buf-pos 0)
+	(first-start 0)
+	(first-end -1)
+	(ambig-pos nil)
+	(maybe-unique-p nil))
+    (declare (simple-string first) (fixnum buf-pos first-start))
+    ;;
+    ;; Make room to store each string's next separator index.
+    (do ((l rest-strings (cdr l)))
+	((endp l))
+      (setf (car l) (cons (car l) -1)))
+    ;;
+    ;; Compare the rest of the strings to the first one.
+    ;; It's our de facto standard for how far we can go.
+    (loop
+      (setf first-start (1+ first-end))
+      (setf first-end
+	    (position separator first :start first-start :test #'char=))
+      (unless first-end
+	(setf first-end (length first))
+	(setf punt-p t)
+	(setf maybe-unique-p t))
+      (let ((first-max first-end)
+	    (word-ambiguous-p nil))
+	(declare (fixnum first-max))
+	;;
+	;; For each string, store the separator's next index.
+	;; If there's no separator, store nil and prepare to punt.
+	;; If the string's field is not equal to the first's, shorten the max
+	;;   expectation for this field, and declare ambiguity.
+	(dolist (s rest-strings)
+	  (let* ((str (car s))
+		 (str-last-pos (cdr s))
+		 (str-start (1+ str-last-pos))
+		 (str-end (position separator str
+				    :start str-start :test #'char=))
+		 (index (string-not-equal first str
+					  :start1 first-start :end1 first-max
+					  :start2 str-start :end2 str-end)))
+	    (declare (simple-string str) (fixnum str-last-pos str-start))
+	    (setf (cdr s) str-end)
+	    (unless str-end
+	      (setf punt-p t)
+	      (setf str-end (length str)))
+	    (when index
+	      (setf word-ambiguous-p t) ; not equal for some reason
+	      (when (< index first-max)
+		(setf first-max index)))))
+	;;
+	;; Store what we matched into the result buffer and save the
+	;; ambiguous position if its the first ambiguous field.
+	(let ((length (- first-max first-start)))
+	  (declare (fixnum length))
+	  (unless (zerop length)
+	    (unless (zerop buf-pos)
+	      (setf (schar *complete-string-buffer* buf-pos) separator)
+	      (incf buf-pos))
+	    (replace *complete-string-buffer* first
+		     :start1 buf-pos :start2 first-start :end2 first-max)
+	    (incf buf-pos length))
+	  (when (and (null ambig-pos) word-ambiguous-p)
+	    (setf ambig-pos buf-pos))
+	  (when (or punt-p (zerop length)) (return)))))
+    (values
+     (subseq *complete-string-buffer* 0 buf-pos)
+     ;; If every corresponding field in each possible completion was equal,
+     ;; our result string is an initial substring of some other completion,
+     ;; so we're ambiguous at the end.
+     (or ambig-pos buf-pos)
+     (and (null ambig-pos)
+	  maybe-unique-p
+	  (every #'(lambda (x) (null (cdr x))) rest-strings)))))
+		 
+
+
+;;;; Clrstring
+
+(defun clrstring (string-table)
+  "Delete all the entries in String-Table."
+  (fill (the simple-vector (string-table-value-nodes string-table)) nil)
+  (setf (string-table-num-nodes string-table) 0)
+  (let ((word-table (string-table-first-word-table string-table)))
+    (fill (the simple-vector (word-table-words word-table)) nil)
+    (setf (word-table-num-words word-table) 0))
+  t)
+
+
+
+;;;; Delete-String
+
+(defun delete-string (string string-table)
+  (with-folded-string (folded len string (string-table-separator string-table))
+    (when (plusp len)
+      (let* ((nodes (string-table-value-nodes string-table))
+	     (num-nodes (string-table-num-nodes string-table))
+	     (end (1- num-nodes)))
+	(declare (simple-string folded) (simple-vector nodes)
+		 (fixnum num-nodes end))
+	(multiple-value-bind
+	    (pos found-p)
+	    (bi-svposition folded nodes (string-compare* :end1 len)
+			   :end end :key #'value-node-folded)
+	  (cond (found-p
+		 (replace nodes nodes
+			  :start1 pos :end1 end :start2 (1+ pos) :end2 num-nodes)
+		 (setf (svref nodes end) nil)
+		 (setf (string-table-num-nodes string-table) end)
+		 (sub-delete-string folded string-table)
+		 t)
+		(t nil)))))))
+
+(defun sub-delete-string (folded string-table)
+  (let ((next-table (string-table-first-word-table string-table))
+	(word-table nil)
+	(node nil)
+	(entry nil)
+	(level -1)
+	last-table last-table-level last-table-pos
+	last-entry last-entry-level)
+    (declare (fixnum level))
+    (do-words (start end)
+      (when node
+	(setf last-entry entry)
+	(setf last-entry-level level))
+      (setf word-table next-table)
+      (incf level)
+      (let ((word-array (word-table-words word-table))
+	    (num-words (word-table-num-words word-table)))
+	(declare (simple-vector word-array) (fixnum num-words))
+	(multiple-value-bind
+	    (pos found-p)
+	    (bi-svposition folded word-array
+			   (string-compare* :start1 start :end1 end)
+			   :end (1- num-words) :key #'word-entry-folded)
+	  (declare (fixnum pos) (ignore found-p))
+	  (setf entry (svref word-array pos))
+	  (setf next-table (word-entry-next-table entry))
+	  (setf node (word-entry-value-node entry))
+	  (when (or (null last-table) (> num-words 1))
+	    (setf last-table word-table)
+	    (setf last-table-pos pos)
+	    (setf last-table-level level)))))
+    (cond (next-table
+	   (setf (word-entry-value-node entry) nil))
+	  ((and last-entry-level
+		(>= last-entry-level last-table-level))
+	   (setf (word-entry-next-table last-entry) nil))
+	  (t
+	   (let* ((del-word-array (word-table-words last-table))
+		  (del-num-words (word-table-num-words last-table))
+		  (del-end (1- del-num-words)))
+	     (declare (simple-vector del-word-array)
+		      (fixnum del-num-words del-end))
+	     (replace del-word-array del-word-array
+		      :start1 last-table-pos :end1 del-end
+		      :start2 (1+ last-table-pos)
+		      :end2 del-num-words)
+	     (setf (svref del-word-array del-end) nil)
+	     (setf (word-table-num-words last-table) del-end))))))
Index: /branches/new-random/cocoa-ide/hemlock/src/text.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/text.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/text.lisp	(revision 13309)
@@ -0,0 +1,585 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;
+;;; This file contains stuff that operates on units of texts, such as
+;;;    paragraphs, sentences, lines, and words.
+;;;
+
+(in-package :hemlock)
+
+;;;; -- New Variables --
+
+(defhvar "Paragraph Delimiter Function"
+  "The function that returns whether or not the current line should break the 
+  paragraph." 
+  :value 'default-para-delim-function)
+
+;;; The standard paragraph delimiting function is DEFAULT-PARA-DELIM-FUNCTION
+(defun default-para-delim-function (mark)
+  "Return whether or not to break on this line."
+  (paragraph-delimiter-attribute-p (next-character mark)))
+
+
+;;;; -- Paragraph Commands --
+
+(defcommand "Forward Paragraph" (p)
+    "moves point to the end of the current (next) paragraph."
+    "moves point to the end of the current (next) paragraph."
+  (or (collapse-if-selection :direction :forward)
+      (let ((point (current-point)))
+        (unless (paragraph-offset point (or p 1))
+          (buffer-end point)
+          (editor-error)))))
+
+(defcommand "Backward Paragraph" (p)
+    "moves point to the start of the current (previous) paragraph."
+    "moves point to the start of the current (previous) paragraph."
+  (or (collapse-if-selection :direction :backward)
+      (let ((point (current-point)))
+        (unless (paragraph-offset point (- (or p 1)))
+          (buffer-start point)
+          (editor-error)))))
+
+(defcommand "Mark Paragraph" (p)
+  "Put mark and point around current or next paragraph.
+   A paragraph is delimited by a blank line, a line beginning with a
+   special character (@,\,-,',and .), or it is begun with a line with at
+   least one whitespace character starting it.  Prefixes are ignored or
+   skipped over before determining if a line starts or delimits a
+   paragraph."
+  "Put mark and point around current or next paragraph."
+  (declare (ignore p))
+  (let* ((point (current-point))
+	 (mark (copy-mark point :temporary)))
+    (if (mark-paragraph point mark)
+	(push-buffer-mark mark t)
+	(editor-error))))
+
+(defun mark-paragraph (mark1 mark2)
+  "Mark the next or current paragraph, setting mark1 to the beginning and mark2
+   to the end.  This uses \"Fill Prefix\", and mark1 is always on the first
+   line of the paragraph.  If no paragraph is found, then the marks are not
+   moved, and nil is returned."
+  (with-mark ((tmark1 mark1)
+	      (tmark2 mark2))
+    (let* ((prefix (value fill-prefix))
+	   (prefix-len (length prefix))
+	   (paragraphp (paragraph-offset tmark2 1)))
+      (when (or paragraphp
+		(and (last-line-p tmark2)
+		     (end-line-p tmark2)
+		     (not (blank-line-p (mark-line tmark2)))))
+	(mark-before (move-mark tmark1 tmark2))
+	(%fill-paragraph-start tmark1 prefix prefix-len)
+	(move-mark mark1 tmark1)
+	(move-mark mark2 tmark2)))))
+
+
+
+(eval-when (:compile-toplevel :execute)
+
+;;;      %MARK-TO-PARAGRAPH moves mark to next immediate (current)
+;;; paragraph in the specified direction.  Nil is returned when no
+;;; paragraph is found.  NOTE: the order of the arguments to OR within the
+;;; first branch of the COND must be as it is, and mark must be at the
+;;; beginning of the line it is on.
+(defmacro %mark-to-paragraph (mark prefix prefix-length
+				   &optional (direction :forward))
+  `(do ((skip-prefix-p)
+	(paragraph-delim-function (value paragraph-delimiter-function)))
+       (nil)
+     (setf skip-prefix-p
+	   (and ,prefix (%line-has-prefix-p ,mark ,prefix ,prefix-length)))
+     (if skip-prefix-p (character-offset ,mark ,prefix-length))
+     (let ((next-char (next-character ,mark)))
+       (cond ((and (not (blank-after-p ,mark))
+		   (or (whitespace-attribute-p next-char)
+		       (not (funcall paragraph-delim-function ,mark))))
+	      (return (if skip-prefix-p (line-start ,mark) ,mark)))
+	     (,(if (eq direction :forward)
+		   `(last-line-p ,mark)
+		   `(first-line-p ,mark))
+	      (if skip-prefix-p (line-start ,mark))
+	      (return nil)))
+       (line-offset ,mark ,(if (eq direction :forward) 1 -1) 0))))
+
+
+;;;      %PARAGRAPH-OFFSET-AUX is the inner loop of PARAGRAPH-OFFSET.  It
+;;; moves over a paragraph to find the beginning or end depending on
+;;; direction.  Prefixes on a line are ignored or skipped over before it
+;;; is determined if the line is a paragraph boundary.
+(defmacro %paragraph-offset-aux (mark prefix prefix-length
+				       &optional (direction :forward))
+  `(do ((paragraph-delim-function (value paragraph-delimiter-function))
+	(skip-prefix-p))
+       (nil)
+     (setf skip-prefix-p
+	   (and ,prefix (%line-has-prefix-p ,mark ,prefix ,prefix-length)))
+     (if skip-prefix-p (character-offset ,mark ,prefix-length))
+     (cond ((or (blank-after-p ,mark)
+		(funcall paragraph-delim-function ,mark))
+	    (return (line-start ,mark)))
+	   (,(if (eq direction :forward)
+		 `(last-line-p ,mark)
+		 `(first-line-p ,mark))
+	    (return ,(if (eq direction :forward)
+			 `(line-end ,mark)
+			 `(line-start ,mark)))))
+     (line-offset ,mark ,(if (eq direction :forward) 1 -1) 0)))
+
+); eval-when
+
+
+
+
+;;;      PARAGRAPH-OFFSET takes a mark and a number of paragraphs to
+;;; move over.  If the specified number of paragraphs does not exist in
+;;; the direction indicated by the sign of number, then nil is
+;;; returned, otherwise the mark is returned.
+
+(defun paragraph-offset (mark number &optional (prefix (value fill-prefix)))
+  "moves mark past the specified number of paragraph, forward if the number
+   is positive and vice versa.  If the specified number of paragraphs do
+   not exist in the direction indicated by the sign of the number, then nil
+   is returned, otherwise the mark is returned."
+  (if (plusp number)
+      (%paragraph-offset-forward mark number prefix)
+      (%paragraph-offset-backward mark number prefix)))
+
+
+
+;;;      %PARAGRAPH-OFFSET-FORWARD moves mark forward over number
+;;; paragraphs.  The first branch of the COND is necessary for the side
+;;; effect provided by LINE-OFFSET.  If %MARK-TO-PARAGRAPH left tmark at
+;;; the beginning of some paragraph %PARAGRAPH-OFFSET-AUX will think it has
+;;; moved mark past a paragraph, so we make sure tmark is inside the
+;;; paragraph or after it.
+
+(defun %paragraph-offset-forward (mark number prefix)
+  (do* ((n number (1- n))
+	(tmark (line-start (copy-mark mark :temporary)))
+	(prefix-length (length prefix))
+	(paragraphp (%mark-to-paragraph tmark prefix prefix-length)
+		    (if (plusp n)
+			(%mark-to-paragraph tmark prefix prefix-length))))
+       ((zerop n) (move-mark mark tmark))
+    (cond ((and paragraphp (not (line-offset tmark 1))) ; 
+	   (if (or (> n 1) (and (last-line-p mark) (end-line-p mark)))
+	       (return nil))
+	   (return (line-end (move-mark mark tmark))))
+	  (paragraphp (%paragraph-offset-aux tmark prefix prefix-length))
+	  (t (return nil)))))
+  
+
+
+(defun %paragraph-offset-backward (mark number prefix)
+  (with-mark ((tmark1 mark)
+	      (tmark2 mark))
+    (do* ((n (abs number) (1- n))
+	  (prefix-length (length prefix))
+	  (paragraphp (%para-offset-back-find-para tmark1 prefix
+						   prefix-length mark)
+		      (if (plusp n)
+			  (%para-offset-back-find-para tmark1 prefix
+						       prefix-length tmark2))))
+	 ((zerop n) (move-mark mark tmark1))
+      (cond ((and paragraphp (first-line-p tmark1))
+	     (if (and (first-line-p mark) (start-line-p mark))
+		 (return nil)
+		 (if (> n 1) (return nil))))
+	    (paragraphp
+	     (%paragraph-offset-aux tmark1 prefix prefix-length :backward)
+	     (%para-offset-back-place-mark tmark1 prefix prefix-length))
+	    (t (return nil))))))
+
+
+
+
+;;;      %PARA-OFFSET-BACK-PLACE-MARK makes sure that mark is in
+;;; the right place when it has been moved backward over a paragraph.  The
+;;; "right place" is defined to be where EMACS leaves it for a given
+;;; situation or where it is necessary to ensure the mark's skipping
+;;; backward over another paragraph if PARAGRAPH-OFFSET was given an
+;;; argument with a greater magnitude than one.  I believe these two
+;;; constraints are equivalent; that is, neither changes what the other
+;;; would dictate.
+
+(defun %para-offset-back-place-mark (mark prefix prefix-length)
+  (skip-prefix-if-here mark prefix prefix-length)
+  (cond ((text-blank-line-p mark) (line-start mark))
+	((not (first-line-p mark))
+	 (line-offset mark -1 0)
+	 (skip-prefix-if-here mark prefix prefix-length)
+	 (if (text-blank-line-p mark)
+	     (line-start mark)
+	     (line-offset mark 1 0)))))
+
+
+
+(defun %para-offset-back-find-para (mark1 prefix prefix-length mark2)
+  (move-mark mark2 mark1)
+  (line-start mark1)
+  (let ((para-p (%mark-to-paragraph mark1 prefix prefix-length :backward)))
+    (cond ((and para-p (same-line-p mark1 mark2))
+	   (skip-prefix-if-here mark1 prefix prefix-length)
+	   (find-attribute mark1 :whitespace #'zerop)
+	   (cond ((mark<= mark2 mark1)
+		  (line-offset mark1 -1 0)
+		  (%mark-to-paragraph mark1 prefix prefix-length :backward))
+		 (t (line-start mark1))))
+	  (t para-p))))
+
+
+
+
+;;;; -- Sentence Commands --
+
+(defcommand "Forward Sentence" (p)
+    "Moves forward one sentence or the specified number.
+   A sentence terminates with a .,?, or ! followed by any number of closing
+   delimiters (such as \",',),],>,|) which are followed by either two
+   spaces or a newline."
+    "Moves forward one sentence or the specified number."
+  (or (collapse-if-selection :direction :forward)
+      (unless (sentence-offset (current-point) (or p 1))
+        (editor-error))))
+
+
+
+(defcommand "Backward Sentence" (p)
+    "Moves backward one sentence or the specified number.
+   A sentence terminates with a .,?, or ! followed by any number of closing
+   delimiters (such as \",',),],>,|) which are followed by either two
+   spaces or a newline."
+    "Moves backward one sentence or the specified number."
+  (or (collapse-if-selection :direction :backward)
+      (unless (sentence-offset (current-point) (- (or p 1)))
+        (editor-error))))
+
+
+
+(defcommand "Mark Sentence" (p)
+  "Put mark and point around current or next sentence.
+   A sentence terminates with a .,?, or ! followed by any number of closing
+   delimiters (such as \",',),],>,|) which are followed by either two
+   spaces or a newline."
+  "Put mark and point around current or next sentence."
+  (declare (ignore p))
+  (let* ((point (current-point))
+	 (end (copy-mark point :temporary)))
+    (unless (sentence-offset end 1) (editor-error))
+    (move-mark point end)
+    (sentence-offset point -1)
+    (push-buffer-mark end t)))
+
+
+(defcommand "Forward Kill Sentence" (p)
+  "Kill forward to end of sentence."
+  "Kill forward to end of sentence."
+  (let ((point (current-point))
+	(offset (or p 1)))
+    (with-mark ((mark point))
+      (if (sentence-offset mark offset)
+	  (if (plusp offset)
+	      (kill-region (region point mark) :kill-forward)
+	      (kill-region (region mark point) :kill-backward))
+	  (editor-error)))))
+
+(defcommand "Backward Kill Sentence" (p)
+  "Kill backward to beginning of sentence."
+  "Kill backward to beginning of sentence."
+  (forward-kill-sentence-command (- (or p 1))))
+
+
+;;;      SENTENCE-OFFSET-END-P returns true if mark is at the end of a
+;;; sentence.  If that the end of a sentence, it leaves mark at an
+;;; appropriate position with respect to the sentence-terminator character,
+;;; the beginning of the next sentence, and direction.  See the commands
+;;; "Forward Sentence" and "Backward Sentence" for a definition of a sentence.
+
+(eval-when (:compile-toplevel :execute)
+(defmacro sentence-offset-end-p (mark &optional (direction :forward))
+  `(let ((start (mark-charpos ,mark)))
+     (do ()
+	 ((not (sentence-closing-char-attribute-p (next-character ,mark))))
+       (mark-after ,mark))
+     (let ((next (next-character ,mark)))
+       (cond ((or (not next)
+		  (char= next #\newline))
+	      ,(if (eq direction :forward) mark `(mark-after ,mark)))
+	     ((and (char= next #\space)
+		   (member (next-character (mark-after ,mark))
+			   '(nil #\space #\newline)))
+	      ,(if (eq direction :forward)
+		   `(mark-before ,mark)
+		   `(mark-after ,mark)))
+	     (t (move-to-position ,mark start)
+		nil)))))
+); eval-when
+
+
+
+
+;;;      SENTENCE-OFFSET-FIND-END moves in the direction direction stopping
+;;; at sentence terminating characters until either there are not any more
+;;; such characters or one is found that defines the end of a sentence.
+;;; When looking backwards, we may be at the beginning of some sentence,
+;;; and if we are, then we must move mark before the sentence terminator;
+;;; otherwise, we would find the immediately preceding sentence terminator
+;;; and end up right where we started.
+
+(eval-when (:compile-toplevel :execute)
+(defmacro sentence-offset-find-end (mark &optional (direction :forward))
+  `(progn
+    ,@(if (eq direction :backward)
+	  `((reverse-find-attribute ,mark :whitespace #'zerop)
+	    (when (fill-region-insert-two-spaces-p ,mark)
+	      (reverse-find-attribute ,mark :sentence-terminator)
+	      (mark-before ,mark))))
+    (do ((foundp) (endp)) (nil)
+      (setf foundp ,(if (eq direction :forward)
+			`(find-attribute ,mark :sentence-terminator)
+			`(reverse-find-attribute ,mark :sentence-terminator)))
+      (setf endp ,(if (eq direction :forward)
+		      `(if foundp (progn (mark-after ,mark)
+					 (sentence-offset-end-p ,mark)))
+		      `(if foundp (sentence-offset-end-p ,mark :backward))))
+      (if endp (return ,mark))
+      ,(if (eq direction :forward)
+	   `(unless foundp (return nil))
+	   `(if foundp (mark-before ,mark) (return nil))))))
+); eval-when
+
+
+
+;;;      SENTENCE-OFFSET takes a mark and a number of paragraphs to move
+;;; over.  If the specified number of paragraphs does not exist in
+;;; the direction indicated by the sign of the number, then nil is returned,
+;;; otherwise the mark is returned.
+
+(defun sentence-offset (mark number)
+  (if (plusp number)
+      (sentence-offset-forward mark number)
+      (sentence-offset-backward mark (abs number))))
+
+
+
+
+;;;      SENTENCE-OFFSET-FORWARD tries to move mark forward over number
+;;; sentences.  If it can, then mark is moved and returned; otherwise, mark
+;;; remains unmoved, and nil is returned.  When tmark2 is moved to the end
+;;; of a new paragraph, we reverse find for a non-whitespace character to
+;;; bring tmark2 to the end of the previous line.  This is necessary to
+;;; detect if tmark1 is at the end of the paragraph, in which case tmark2
+;;; wants to be moved over another paragraph.
+
+(defun sentence-offset-forward (mark number)
+  (with-mark ((tmark1 mark)
+	      (tmark2 mark))
+    (do ((n number (1- n))
+	 (found-paragraph-p))
+	((zerop n) (move-mark mark tmark1))
+      (when (and (mark<= tmark2 tmark1)
+		 (setf found-paragraph-p (paragraph-offset tmark2 1)))
+	(reverse-find-attribute tmark2 :whitespace #'zerop)
+	(when (mark>= tmark1 tmark2)
+	  (line-offset tmark2 1 0)
+	  (setf found-paragraph-p (paragraph-offset tmark2 1))
+	  (reverse-find-attribute tmark2 :whitespace #'zerop)))
+      (cond ((sentence-offset-find-end tmark1)
+	     (if (mark> tmark1 tmark2) (move-mark tmark1 tmark2)))
+	    (found-paragraph-p (move-mark tmark1 tmark2))
+	    (t (return nil))))))
+
+
+
+(defun sentence-offset-backward (mark number)
+  (with-mark ((tmark1 mark)
+	      (tmark2 mark)
+	      (tmark3 mark))
+    (do* ((n number (1- n))
+	  (prefix (value fill-prefix))
+	  (prefix-length (length prefix))
+	  (found-paragraph-p
+	   (cond ((paragraph-offset tmark2 -1)
+		  (sent-back-place-para-start tmark2 prefix prefix-length)
+		  t))))
+	 ((zerop n) (move-mark mark tmark1))
+      (move-mark tmark3 tmark1)
+      (when (and (sent-back-para-start-p tmark1 tmark3 prefix prefix-length)
+		 (setf found-paragraph-p
+		       (paragraph-offset (move-mark tmark2 tmark3) -1)))
+	(paragraph-offset (move-mark tmark1 tmark2) 1)
+	(sent-back-place-para-start tmark2 prefix prefix-length))
+      (cond ((sentence-offset-find-end tmark1 :backward)
+	     (if (mark< tmark1 tmark2) (move-mark tmark1 tmark2)))
+	    (found-paragraph-p (move-mark tmark1 tmark2))
+	    (t (return nil))))))
+
+
+
+(defun sent-back-para-start-p (mark1 mark2 prefix prefix-length)
+  (skip-prefix-if-here (line-start mark2) prefix prefix-length)
+  (cond ((text-blank-line-p mark2)
+	 (line-start mark2))
+	((whitespace-attribute-p (next-character mark2))
+	 (find-attribute mark2 :whitespace #'zerop)
+	 (if (mark= mark1 mark2) (line-offset mark2 -1 0)))
+	((and (mark= mark2 mark1) (line-offset mark2 -1 0))
+	 (skip-prefix-if-here mark2 prefix prefix-length)
+	 (if (text-blank-line-p mark2)
+	     (line-start mark2)))))
+
+
+
+(defun sent-back-place-para-start (mark2 prefix prefix-length)
+  (skip-prefix-if-here mark2 prefix prefix-length)
+  (when (text-blank-line-p mark2)
+    (line-offset mark2 1 0)
+    (skip-prefix-if-here mark2 prefix prefix-length))
+  (find-attribute mark2 :whitespace #'zerop))
+
+
+
+
+;;;; -- Transposing Stuff --
+
+(defcommand "Transpose Words" (p)
+  "Transpose the words before and after the cursor.
+   With a positive argument it transposes the words before and after the
+   cursor, moves right, and repeats the specified number of times,
+   dragging the word to the left of the cursor right.  With a negative
+   argument, it transposes the two words to the left of the cursor, moves
+   between them, and repeats the specified number of times, exactly undoing
+   the positive argument form."
+  "Transpose the words before and after the cursor."
+  (let ((num (or p 1))
+	(point (current-point-unless-selection)))
+    (when point
+      (with-mark ((mark point :left-inserting)
+                  (start point :left-inserting))
+        (let ((mark-prev (previous-character mark))
+              (mark-next (next-character mark)))
+          (cond ((plusp num)
+                 (let ((forwardp (word-offset point num))
+                       (backwardp (if (or (word-delimiter-attribute-p mark-next)
+                                          (word-delimiter-attribute-p mark-prev))
+				    (word-offset mark -1)
+				    (word-offset mark -2))))
+                   (if (and forwardp backwardp)
+		     (transpose-words-forward mark point start)
+		     (editor-error))))
+                ((minusp num)
+                 (let ((enoughp (word-offset point (1- num))))
+                   (if (word-delimiter-attribute-p mark-prev)
+		     (reverse-find-attribute mark :word-delimiter #'zerop)
+		     (find-attribute mark :word-delimiter))
+                   (if enoughp
+		     (transpose-words-backward point mark start)
+		     (editor-error))))
+                (t (editor-error))))))))
+
+
+(defun transpose-words-forward (mark1 end mark2)
+  (with-mark ((tmark1 mark1 :left-inserting)
+	      (tmark2 mark2 :left-inserting))
+    (find-attribute tmark1 :word-delimiter)
+    (do ((region1 (delete-and-save-region (region mark1 tmark1))))
+	((mark= tmark2 end) (ninsert-region end region1))
+      (word-offset tmark2 1)
+      (reverse-find-attribute (move-mark tmark1 tmark2) :word-delimiter)
+      (ninsert-region mark1 (delete-and-save-region (region tmark1 tmark2)))
+      (move-mark mark1 tmark1))))
+
+
+(defun transpose-words-backward (start mark1 mark2)
+  (with-mark ((tmark1 mark1 :left-inserting)
+	      (tmark2 mark2 :left-inserting))
+    (reverse-find-attribute tmark1 :word-delimiter)
+    (move-mark mark2 mark1)
+    (do ((region1 (delete-and-save-region (region tmark1 mark1))))
+	((mark= tmark1 start) (ninsert-region start region1))
+      (word-offset tmark1 -1)
+      (find-attribute (move-mark tmark2 tmark1) :word-delimiter)
+      (ninsert-region mark1 (delete-and-save-region (region tmark1 tmark2)))
+      (move-mark mark1 tmark1))))
+
+
+(defcommand "Transpose Lines" (p)
+  "Transpose the current line with the line before the cursor.
+   With a positive argument it transposes the current line with the one
+   before, moves down a line, and repeats the specified number of times,
+   dragging the originally current line down.  With a negative argument, it
+   transposes the two lines to the prior to the current, moves up a line,
+   and repeats the specified number of times, exactly undoing the positive
+   argument form.  With a zero argument, it transposes the lines at point
+   and mark."
+  "Transpose the current line with the line before the cursor."
+  (let ((num (or p 1))
+        (point (current-point-unless-selection)))
+    (when point
+      (with-mark ((mark point :left-inserting))
+        (cond ((plusp num)
+               (if (and (line-offset mark -1 0)
+                        (line-offset point num 0))
+		 (transpose-lines mark point)
+		 (editor-error)))
+              ((minusp num)
+               (cond ((and (line-offset mark (1- num) 0)
+                           (line-offset point -1 0))
+                      (transpose-lines point mark)
+                      (move-mark point mark))
+                     (t (editor-error))))
+              (t
+               (rotatef (line-string (mark-line point))
+                        (line-string (mark-line (current-mark))))
+               (line-start point)))))))
+
+
+(defun transpose-lines (mark1 mark2)
+  (with-mark ((tmark1 mark1))
+    (line-offset tmark1 1)
+    (ninsert-region mark2 (delete-and-save-region (region mark1 tmark1)))))
+
+
+
+;;;; -- Utilities --
+
+(defun skip-prefix-if-here (mark prefix prefix-length)
+  (if (and prefix (%line-has-prefix-p mark prefix prefix-length))
+      (character-offset mark prefix-length)))
+
+
+
+(defun text-blank-line-p (mark)
+  (let ((next-char (next-character mark)))
+    (or (blank-after-p mark)
+	(and (funcall (value paragraph-delimiter-function) mark)
+	     (not (whitespace-attribute-p next-char))))))
+
+
+
+(defun whitespace-attribute-p (char)
+  (= (character-attribute :whitespace char) 1))
+
+(defun sentence-terminator-attribute-p (char)
+  (= (character-attribute :sentence-terminator char) 1))
+
+(defun sentence-closing-char-attribute-p (char)
+  (= (character-attribute :sentence-closing-char char) 1))
+
+(defun paragraph-delimiter-attribute-p (char)
+  (= (character-attribute :paragraph-delimiter char) 1))
+
+(defun word-delimiter-attribute-p (char)
+  (= (character-attribute :word-delimiter char) 1))
Index: /branches/new-random/cocoa-ide/hemlock/src/undo.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/undo.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/undo.lisp	(revision 13309)
@@ -0,0 +1,223 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;; 
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;
+;;; This file contains the implementation of the undo mechanism.
+
+(in-package :hemlock)
+
+
+
+;;;; -- Constants --
+
+(defvar undo-name "Undo")
+
+
+
+;;;; -- Variables --
+
+(defvar *undo-info* nil
+  "Structure containing necessary info to undo last undoable operation.")
+
+
+
+;;;; -- Structures --
+
+(defstruct (undo-info (:print-function %print-undo-info)
+		      (:constructor %make-undo-info
+				    (name method cleanup method-undo buffer))
+		      (:copier nil))
+  name		; string displayed for user to know what's being undone --
+		; typically a command's name.
+  (hold-name undo-name)	; holds a name for successive invocations of the
+			; "Undo" command.
+  method	; closure stored by command that undoes the command when invoked.
+  method-undo	; closure stored by command that undoes what method does.
+  cleanup	; closure stored by command that cleans up any data for method,
+		; such as permanent marks.
+  buffer)	; buffer the command was invoked in.
+
+(setf (documentation 'undo-info-name 'function)
+      "Return the string indicating what would be undone for given undo info.")
+(setf (documentation 'undo-info-method 'function)
+      "Return the closure that undoes a command when invoked.")
+(setf (documentation 'undo-info-cleanup 'function)
+      "Return the closure that cleans up data necessary for an undo method.")
+(setf (documentation 'undo-info-buffer 'function)
+      "Return the buffer that the last undoable command was invoked in.")
+(setf (documentation 'undo-info-hold-name 'function)
+      "Return the name being held since the last invocation of \"Undo\"")
+(setf (documentation 'undo-info-method-undo 'function)
+      "Return the closure that undoes what undo-info-method does.")
+      
+
+(defun %print-undo-info (obj s depth)
+  (declare (ignore depth))
+  (format s "#<Undo Info ~S>" (undo-info-name obj)))
+
+
+
+;;;; -- Commands --
+
+(defcommand "Undo" (p)
+  "Undo last major change, kill, etc.
+   Simple insertions and deletions cannot be undone.  If you change the buffer
+   in this way before you undo, you may get slightly wrong results, but this
+   is probably still useful."
+  "This is not intended to be called in Lisp code."
+  (declare (ignore p))
+  (if (not *undo-info*) (editor-error "No currently undoable command."))
+  (let ((buffer (undo-info-buffer *undo-info*))
+	(cleanup (undo-info-cleanup *undo-info*))
+	(method-undo (undo-info-method-undo *undo-info*)))
+    (if (not (eq buffer (current-buffer)))
+	(editor-error "Undo info is for buffer ~S." (buffer-name buffer)))
+    (when (prompt-for-y-or-n :prompt (format nil "Undo the last ~A? "
+					     (undo-info-name *undo-info*))
+			     :must-exist t)
+      (funcall (undo-info-method *undo-info*))
+      (cond (method-undo
+	     (rotatef (undo-info-name *undo-info*)
+		      (undo-info-hold-name *undo-info*))
+	     (rotatef (undo-info-method *undo-info*)
+		      (undo-info-method-undo *undo-info*)))
+	    (t (if cleanup (funcall cleanup))
+	       (setf *undo-info* nil))))))
+
+
+
+;;;; -- Primitives --
+
+(defun save-for-undo (name method
+		      &optional cleanup method-undo (buffer (current-buffer)))
+  "Stashes information for next \"Undo\" command invocation.  If there is
+   an undo-info object, it is cleaned up first."
+  (cond (*undo-info*
+	 (let ((old-cleanup (undo-info-cleanup *undo-info*)))
+	   (if old-cleanup (funcall old-cleanup))
+	   (setf (undo-info-name *undo-info*) name)
+	   (setf (undo-info-hold-name *undo-info*) undo-name)
+	   (setf (undo-info-method *undo-info*) method)
+	   (setf (undo-info-method-undo *undo-info*) method-undo)
+	   (setf (undo-info-cleanup *undo-info*) cleanup)
+	   (setf (undo-info-buffer *undo-info*) buffer)
+	   *undo-info*))
+	(t (setf *undo-info*
+		 (%make-undo-info name method cleanup method-undo buffer)))))
+
+
+
+(eval-when (:compile-toplevel :execute)
+
+;;; MAKE-TWIDDLE-REGION-UNDO sets up an undo method that deletes region1,
+;;; saving the deleted region and eventually storing it in region2.  After
+;;; deleting region1, its start and end are made :right-inserting and
+;;; :left-inserting, so it will contain region2 when it is inserted at region1's
+;;; end.  This results in a method that takes region1 with permanent marks
+;;; into some buffer and results with the contents of region2 in region1 (with
+;;; permanent marks into a buffer) and the contents of region1 (from the buffer)
+;;; in region2 (a region without marks into any buffer).
+;;;
+(defmacro make-twiddle-region-undo (region1 region2)
+  `#'(lambda ()
+       (let* ((tregion (delete-and-save-region ,region1))
+	      (mark (region-end ,region1)))
+	 (setf (mark-kind (region-start ,region1)) :right-inserting)
+	 (setf (mark-kind mark) :left-inserting)
+	 (ninsert-region mark ,region2)
+	 (setf ,region2 tregion))))
+
+;;; MAKE-DELETE-REGION-UNDO sets up an undo method that deletes region with
+;;; permanent marks into a buffer, saving the region in region without any
+;;; marks into a buffer, deleting one of the permanent marks, and saving one
+;;; permanent mark in the variable mark.  This is designed to work with
+;;; MAKE-INSERT-REGION-UNDO, so mark results in the location in a buffer where
+;;; region will be inserted if this method is undone.
+;;;
+(defmacro make-delete-region-undo (region mark)
+  `#'(lambda ()
+       (let ((tregion (delete-and-save-region ,region)))
+	 (delete-mark (region-start ,region))
+	 (setf ,mark (region-end ,region))
+	 (setf ,region tregion))))
+
+;;; MAKE-INSERT-REGION-UNDO sets up an undo method that inserts region at mark,
+;;; saving in the variable region a region with permanent marks in a buffer.
+;;; This is designed to work with MAKE-DELETE-REGION-UNDO, so region can later
+;;; be deleted.
+;;;
+(defmacro make-insert-region-undo (region mark)
+  `#'(lambda ()
+       (let ((tregion (region (copy-mark ,mark :right-inserting) ,mark)))
+	 (setf (mark-kind ,mark) :left-inserting)
+	 (ninsert-region ,mark ,region)
+	 (setf ,region tregion))))
+
+) ;eval-when
+
+;;; MAKE-REGION-UNDO handles three common cases that undo'able commands often
+;;; need.  This function sets up three closures via SAVE-FOR-UNDO that do
+;;; an original undo, undo the original undo, and clean up any permanent marks
+;;; the next time SAVE-FOR-UNDO is called.  Actually, the original undo and
+;;; the undo for the original undo setup here are reversible in that each
+;;; invocation of "Undo" switches these, so an undo setup by the function is
+;;; undo'able, and the undo of the undo is undo'able, and the ....
+;;;
+;;; :twiddle
+;;;    Region has permanent marks into a buffer.  Mark-or-region is a region
+;;;    not connected to any buffer.  A first undo deletes region, saving it and
+;;;    inserting mark-or-region.  This also sets region around the inserted
+;;;    region in the buffer and sets mark-or-region to be the deleted and saved
+;;;    region.  Thus the undo and the undo of the undo are the same action.
+;;; :insert
+;;;    Region is not connected to any buffer.  Mark-or-region is a permanent
+;;;    mark into a buffer where region is to be inserted on a first undo, and
+;;;    this mark is used to form a region on the first undo that will be
+;;;    deleted upon a subsequent undo.  The cleanup method knows mark-or-region
+;;;    is a permanent mark into a buffer, but it has to determine if region
+;;;    has marks into a buffer because if a subsequent undo does occur, region
+;;;    does point into a buffer.
+;;; :delete
+;;;    Region has permanent marks into a buffer.  Mark-or-region should not
+;;;    have been supplied.  A first undo deletes region, saving the deleted
+;;;    region in region and creating a permanent mark that indicates where to
+;;;    put region back.  The permanent mark is stored in mark-or-region.  The
+;;;    cleanup method has to check that mark-or-region is a mark since it won't
+;;;    be unless there was a subsequent undo.
+;;;
+(defun make-region-undo (kind name region &optional mark-or-region)
+  (case kind
+    (:twiddle
+     (save-for-undo name
+       (make-twiddle-region-undo region mark-or-region)
+       #'(lambda ()
+	   (delete-mark (region-start region))
+	   (delete-mark (region-end region)))
+       (make-twiddle-region-undo region mark-or-region)))
+    (:insert
+     (save-for-undo name
+       (make-insert-region-undo region mark-or-region)
+       #'(lambda ()
+	   (let ((mark (region-start region)))
+	     (delete-mark mark-or-region)
+	     (when (mark-buffer mark)
+	       (delete-mark mark)
+	       (delete-mark (region-end region)))))
+       (make-delete-region-undo region mark-or-region)))
+    (:delete
+     (save-for-undo name
+       (make-delete-region-undo region mark-or-region)
+       #'(lambda ()
+	   (delete-mark (region-start region))
+	   (delete-mark (region-end region))
+	   (if (markp mark-or-region) (delete-mark mark-or-region)))
+       (make-insert-region-undo region mark-or-region)))))
Index: /branches/new-random/cocoa-ide/hemlock/src/vars.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/vars.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/vars.lisp	(revision 13309)
@@ -0,0 +1,217 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Rob MacLachlan
+;;;
+;;; The file contains the routines which define Hemlock variables.
+;;;
+
+(in-package :hemlock-internals)
+
+;;; UNDEFINED-VARIABLE-ERROR  --  Internal
+;;;
+;;;    Complain about an undefined Hemlock variable in a helpful fashion.
+;;;
+(defun undefined-variable-error (name)
+  (if (eq (symbol-package name) (find-package :hemlock))
+      (error "Undefined Hemlock variable ~A." name)
+      (error "Hemlock variables must be in the \"HEMLOCK\" package, but~%~
+	     ~S is in the ~S package."
+	     name (package-name (symbol-package name)))))
+
+;;; GET-MODE-OBJECT  --  Internal
+;;;
+;;;    Get the mode-object corresponding to name or die trying.
+;;;
+(defun get-mode-object (name)
+  (unless (stringp name) (error "Mode name ~S is not a string." name))
+  (let ((res (getstring name *mode-names*)))
+    (unless res (error "~S is not a defined mode." name))
+    res))
+
+;;; FIND-BINDING  --  Internal
+;;;
+;;;    Return the Binding object corresponding to Name in the collection
+;;; of binding Binding, or NIL if none.
+;;;
+(defun find-binding (symbol-name bindings)
+  (find symbol-name bindings :key #'variable-object-symbol-name :test #'eq))
+
+;;; GET-VARIABLE-OBJECT  --  Internal
+;;;
+;;;    Get the variable-object with the specified symbol-name, kind and where,
+;;; or die trying.
+;;;
+(defun get-variable-object (name kind &optional where)
+  (or (lookup-variable-object name kind where)
+      (undefined-variable-error name)))
+
+(defun lookup-variable-object (name kind where)
+  (ecase kind
+    (:current
+     (let ((buffer (current-buffer)))
+       (if (null buffer)
+         (lookup-variable-object name :global t)
+         (or (find-binding name (buffer-var-values buffer))
+             (loop for mode in (buffer-minor-mode-objects buffer)
+               thereis (find-binding name (mode-object-var-values mode)))
+             (find-binding name (mode-object-var-values (buffer-major-mode-object buffer)))
+             (get name 'hemlock-variable-value)))))
+    (:buffer
+     (find-binding name (buffer-var-values (ccl:require-type where 'buffer))))
+    (:mode
+     (find-binding name (mode-object-var-values (get-mode-object where))))
+    (:global
+     (get name 'hemlock-variable-value))))
+
+;;; VARIABLE-VALUE  --  Public
+;;;
+;;;    Get the value of the Hemlock variable "name".
+;;;
+(defun variable-value (name &optional (kind :current) where)
+  "Return the value of the Hemlock variable given."
+  (variable-object-value (get-variable-object name kind where)))
+
+;;; %SET-VARIABLE-VALUE  --  Internal
+;;;
+;;;   Set the Hemlock variable with the symbol name "name".
+;;;
+(defun %set-variable-value (name kind where new-value)
+  (let ((obj (get-variable-object name kind where)))
+    (invoke-hook (variable-object-hooks obj) name kind where new-value)
+    (setf (variable-object-value obj) new-value)))
+
+;;; %VALUE  --  Internal
+;;;
+;;;    This function is called by the expansion of Value.
+;;;
+(defun %value (name)
+  (variable-value name :current t))
+
+;;; %SET-VALUE  --  Internal
+;;;
+;;;    The setf-inverse of Value, set the current value.
+;;;
+(defun %set-value (name new-value)
+  (%set-variable-value name :current t new-value))
+
+
+;;; VARIABLE-HOOKS  --  Public
+;;;
+;;;    Return the list of hooks for "name".
+;;;
+(defun variable-hooks (name &optional (kind :current) where)
+  "Return the list of hook functions for the Hemlock variable given."
+  (variable-object-hooks (get-variable-object name kind where)))
+
+;;; %SET-VARIABLE-HOOKS --  Internal
+;;;
+;;;    Set the hook-list for Hemlock variable Name.
+;;;
+(defun %set-variable-hooks (name kind where new-value)
+  (setf (variable-object-hooks (get-variable-object name kind where)) new-value))
+
+;;; VARIABLE-DOCUMENTATION  --  Public
+;;;
+;;;    Return the documentation for "name".
+;;;
+(defun variable-documentation (name &optional (kind :current) where)
+  "Return the documentation for the Hemlock variable given."
+  (variable-object-documentation (get-variable-object name kind where)))
+
+;;; %SET-VARIABLE-DOCUMENTATION  --  Internal
+;;;
+;;;    Set a variables documentation.
+;;;
+(defun %set-variable-documentation (name kind where new-value)
+  (setf (variable-object-documentation (get-variable-object name kind where))
+	new-value))
+
+;;; VARIABLE-NAME  --  Public
+;;;
+;;;    Return the String Name for a Hemlock variable.
+;;;
+(defun variable-name (name &optional (kind :current) where)
+   "Return the string name of a Hemlock variable."
+  (variable-object-name (get-variable-object name kind where)))
+
+;;; HEMLOCK-BOUND-P  --  Public
+;;;
+(defun hemlock-bound-p (name &optional (kind :current) where)
+  "Returns T Name is a Hemlock variable defined in the specifed place, or
+  NIL otherwise."
+  (not (null (lookup-variable-object name kind where))))
+
+
+(declaim (special *global-variable-names*))
+
+;;; DEFHVAR  --  Public
+;;;
+;;;    Define a Hemlock variable somewhere.
+;;;
+(defun defhvar (name documentation &key mode buffer (hooks nil hook-p)
+		     (value nil value-p))
+  (let* ((symbol-name (string-to-variable name)) var)
+    (cond
+     (mode
+      (let* ((mode-obj (get-mode-object mode)))
+        (setf (getstring name (mode-object-variables mode-obj)) symbol-name)
+        (unless (setq var (find-binding symbol-name (mode-object-var-values mode-obj)))
+          (push (setq var (make-variable-object symbol-name))
+                (mode-object-var-values mode-obj)))))
+     (buffer
+      (check-type buffer buffer)
+      (setf (getstring name (buffer-variables buffer)) symbol-name)
+      (unless (setq var (find-binding symbol-name (buffer-var-values buffer)))
+        (push (setq var (make-variable-object symbol-name))
+              (buffer-var-values buffer))))
+     (t
+      (setf (getstring name *global-variable-names*) symbol-name)
+      (unless (setq var (get symbol-name 'hemlock-variable-value))
+        (setf (get symbol-name 'hemlock-variable-value)
+              (setq var (make-variable-object symbol-name))))))
+    (setf (variable-object-name var) name)
+    (when (> (length documentation) 0)
+      (setf (variable-object-documentation var) documentation))
+    (when hook-p
+      (setf (variable-object-hooks var) hooks))
+    (when value-p
+      (setf (variable-object-value var) value)))
+  name)
+
+;;; DELETE-VARIABLE  --  Public
+;;;
+;;; Make a Hemlock variable no longer bound, fixing up the saved
+;;;binding values as necessary.
+;;;
+(defun delete-variable (name &optional (kind :global) where)
+  "Delete a Hemlock variable somewhere."
+  (let* ((obj (get-variable-object name kind where))
+	 (sname (variable-object-name obj)))
+    (ecase kind
+      (:buffer
+       (let* ((values (buffer-var-values where))
+	      (binding (find-binding name values)))
+	 (invoke-hook hemlock::delete-variable-hook name :buffer where)
+         (delete-string sname (buffer-variables where))
+         (setf (buffer-var-values where) (delete binding values))))
+      (:mode
+       (let* ((mode (get-mode-object where))
+	      (values (mode-object-var-values mode))
+	      (binding (find-binding name values)))
+	 (invoke-hook hemlock::delete-variable-hook name :mode where)
+	 (delete-string sname (mode-object-variables mode))
+         (setf (mode-object-var-values mode) (delete binding values))))
+      (:global
+       (invoke-hook hemlock::delete-variable-hook name :global nil)
+       (delete-string sname *global-variable-names*)
+       (setf (get name 'hemlock-variable-value) nil)))
+    nil))
Index: /branches/new-random/cocoa-ide/hemlock/src/views.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/src/views.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/src/views.lisp	(revision 13309)
@@ -0,0 +1,282 @@
+;;; -*- Mode: Lisp; Package: hemlock-internals -*-
+
+(in-package :hemlock-internals)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; A HEMLOCK-VIEW represents text displayed in a (pane inside a) window.
+;; Conceptually it consists of a text buffer, a modeline for semi-permanent status
+;; info, an echo area for transient status info, and a text input area for reading
+;; prompted input.  Currently the last two are conflated.
+;;
+;; A HEMLOCK-VIEW never changes which text buffer it displays (unlike in emacs).  A
+;; text buffer can be displayed in multiple HEMLOCK-VIEW's, although currently there
+;; is no UI to make that happen.  But we try take care to distinguish per-buffer info
+;; from per-view info.  The former is stored in the buffer struct and in buffer
+;; variables.  The latter is currently stored in HEMLOCK-VIEW slots, although I'd
+;; like to introduce user-definable "view variables" and get rid of some of these
+;; user-level slots.  [Note: currently, multiple views on a buffer are but a remote
+;; dream.  Basic things like the insertion point are still per buffer when they
+;; should be per view]
+;;
+;; The user interacts with a HEMLOCK-VIEW using events.  Each time the user presses a
+;; key, the OS arranges to invoke our event handler.  The event handler computes and
+;; invokes a hemlock command bound to the key.  The command is invoked in a
+;; dynamic context most suitable for modifying the text buffer associated with the
+;; HEMLOCK-VIEW, but by jumping through a few hoops, it can modify other buffers.
+
+(defvar *current-view* nil)
+
+(defun current-view (&optional (must-exist t))
+  (or *current-view*
+      (and must-exist (error "Hemlock view context not established"))))
+
+(defclass hemlock-view ()
+  ((pane :initarg :pane :reader hemlock-view-pane)
+   (buffer :initarg :buffer :reader hemlock-view-buffer)
+   (echo-area-buffer :initarg :echo-area-buffer :reader hemlock-echo-area-buffer)
+   (echo-area-stream :reader hemlock-echo-area-stream)
+
+   ;; Input state
+   (quote-next-p :initform nil :accessor hemlock-view-quote-next-p)
+   (current-command :initform (make-array 10 :fill-pointer 0 :adjustable t)
+		    :accessor hemlock-current-command)
+   (last-command :initform (make-array 10 :fill-pointer 0 :adjustable t)
+                 :accessor hemlock-last-command)
+   (prefix-argument-state :initform (make-prefix-argument-state)
+			  :accessor hemlock-prefix-argument-state)
+   ;; If set, events are diverted to the echo area for reading prompt-for-xxx input.
+   (prompted-input-state :initform nil :accessor hemlock-prompted-input-state)
+
+   (cancel-message :initform nil :accessor hemlock-cancel-message)
+
+   ;; User level "view variables", for now give each its own slot.
+   (last-command-type :initform nil :accessor hemlock-last-command-type)
+   (target-column :initform 0 :accessor hemlock-target-column)
+   ))
+
+(defun hemlock-view-p (object)
+  (typep object 'hemlock-view))
+
+(defmethod initialize-instance ((view hemlock-view) &key)
+  (call-next-method)
+  (with-slots (echo-area-buffer echo-area-stream) view
+    (setf echo-area-stream
+	  (make-hemlock-output-stream (buffer-end-mark echo-area-buffer) :full))))
+
+(defun current-prefix-argument-state ()
+  (hemlock-prefix-argument-state (current-view)))
+
+(defun last-key-event-typed ()
+  "This function returns the last key-event typed by the user and read as input."
+  (let* ((view (current-view))
+         (keys (hemlock-current-command view)))
+    (when (= (length keys) 0) ;; the normal case, when executing a command.
+      (setq keys (hemlock-last-command view)))
+    (when (> (length keys) 0)
+      (aref keys (1- (length keys))))))
+
+(defun last-char-typed ()
+  (let ((key (last-key-event-typed)))
+    (and key (key-event-char key))))
+
+;; This handles errors in event handling.  It assumes it's called in a normal
+;; event handling context for some view.
+(defun lisp-error-error-handler (condition &key debug-p)
+  (with-standard-standard-output
+    (handler-case
+        (progn
+          (hemlock-ext:report-hemlock-error (current-view) condition debug-p)
+          (let ((emsg (ignore-errors (princ-to-string condition))))
+            (abort-to-toplevel (or emsg "Error"))))
+      (error (cc)
+	     (ignore-errors (format t "~&Event error handling failed"))
+	     (ignore-errors (format t ": ~a" cc))
+	     (abort)))))
+
+
+;; This resets the command accumulation state in the current view.
+(defmethod reset-command-state ()
+  (let ((view (current-view)))
+    ;; This resets c-q
+    (setf (hemlock-view-quote-next-p view) nil)
+    ;; This resets c-x (multi-key command) and c-c (modifier prefix command)
+    (setf (fill-pointer (hemlock-current-command view)) 0)
+    ;; This resets the numarg state.
+    (prefix-argument-resetting-state (hemlock-prefix-argument-state view))))
+
+;; This is called for ^G and for lisp errors.  It aborts all editor state,
+;; including recursive reading input and incremental search.
+(defun abort-to-toplevel (&optional (message "Cancelled"))
+  ;; This assumes it's called in normal event state.
+  (assert (and *current-view* (find-restart 'exit-event-handler)))
+  (reset-command-state)
+  (invoke-hook hemlock::abort-hook) ;; reset ephemeral modes such as i-search.
+  (setf (hemlock-cancel-message (current-view)) message)
+  (let ((eps (current-echo-parse-state :must-exist nil)))
+    (when eps
+      (exit-echo-parse eps :aborted)))
+  (exit-event-handler))
+
+;; Called for editor errors.  This aborts command accumulation and i-search,
+;; but not recursive reading of input.
+(defun abort-current-command (&optional (message "Cancelled"))
+  ;; This assumes it's called in normal event state.
+  (assert (and *current-view* (find-restart 'exit-event-handler)))
+  (reset-command-state)
+  (invoke-hook hemlock::abort-hook)
+  (setf (hemlock-cancel-message (current-view)) message)
+  (exit-event-handler))
+
+(defun exit-event-handler (&optional message)
+  (when (and *current-view* message)
+    (setf (hemlock-cancel-message *current-view*) message))
+  (let ((restart (find-restart 'exit-event-handler)))
+    (if restart
+      (ccl::invoke-restart-no-return restart)
+      (abort))))
+
+;; These are only used in event handling, and as such are serialized
+(defparameter *translation-temp-1* (make-array 10 :fill-pointer 0 :adjustable t))
+(defparameter *translation-temp-2* (make-array 10 :fill-pointer 0 :adjustable t))
+
+(defmethod translate-and-lookup-command (keys)
+  ;; Returns NIL if we're in the middle of a command (either multi-key, as in c-x,
+  ;; or translation prefix, as in ESC for Meta-), else a command.
+  (multiple-value-bind (translated-key prefix-p)
+		       (translate-key keys *translation-temp-1* *translation-temp-2*)
+    (multiple-value-bind (res t-bindings)
+			 (get-current-binding translated-key)
+      (etypecase res
+	(command
+	 (values res t-bindings))
+	(hash-table 	;; we're part-way through a multi-key command
+	 nil)
+	(null
+	 (if prefix-p   ;; we're part-way through a translation prefix
+	   nil
+	   (values (get-default-command) nil)))))))
+
+
+;; This has a side effect of resetting the quoting state and current command.
+(defmethod get-command-binding-for-key ((view hemlock-view) key)
+  (let ((current-keys (hemlock-current-command view)))
+    (vector-push-extend key current-keys)
+    (multiple-value-bind (main-binding t-bindings)
+                         (if (shiftf (hemlock-view-quote-next-p view) nil)
+                           (values (get-self-insert-command) nil)
+                           (let ((eps (hemlock-prompted-input-state view)))
+                             (or (and eps (eps-parse-key-handler eps))
+                                 (translate-and-lookup-command current-keys))))
+      (when main-binding
+        (let ((vec (hemlock-last-command view))) ;; reuse vector
+          (setf (hemlock-last-command view) current-keys)
+          (setf (fill-pointer vec) 0)
+          (setf (hemlock-current-command view) vec))
+        (values main-binding t-bindings)))))
+
+(defvar *last-last-command-type*)
+(defvar *last-prefix-argument*)
+
+(defun invoke-command (command p)
+  (funcall (command-function command) p))
+
+(defmethod execute-hemlock-key ((view hemlock-view) key)
+  #+debug (log-debug "~&execute-hemlock-key ~s" key)
+  (with-output-to-listener
+   (if (or (symbolp key) (functionp key))
+     (funcall key)
+     (multiple-value-bind (main-binding transparent-bindings)
+                          (get-command-binding-for-key view key)
+       #+debug (log-debug "~&  binding ~s ~s" main-binding transparent-bindings)
+       (ring-push key *key-event-history*)
+       ;; If the key represents an "alphabetic" character (of which there
+       ;; are about 94000), and the event has no modifiers or only a shift
+       ;; modifier, treat it if it were bound to "Self Insert".
+       
+       (when (eq main-binding (get-default-command))
+	 (let* ((modifiers (key-event-bits-modifiers (key-event-bits key)))
+                (char (key-event-char key)))
+	   (when (and char
+                      (graphic-char-p char)
+		      (or (null modifiers)
+			  (equal '("Shift") modifiers)))
+	     (setq main-binding (get-self-insert-command)))))
+       (when main-binding
+         (let* ((*last-last-command-type* (shiftf (hemlock-last-command-type view) nil))
+                (*last-prefix-argument* (hemlock::prefix-argument-resetting-state)))
+           (dolist (binding transparent-bindings)
+             (invoke-command binding *last-prefix-argument*))
+           (invoke-command main-binding *last-prefix-argument*)))))))
+
+
+
+(defmethod update-echo-area-after-command ((view hemlock-view))
+  (let* ((eps (hemlock-prompted-input-state view)))
+    ;;if we're in the process of returning from a recursive parse,
+    ;; don't do anything, let the outer event handle it.
+    (unless (and eps (eps-parse-results eps))
+      (let ((msg (shiftf (hemlock-cancel-message view) nil)))
+	(if msg
+	  (loud-message msg)
+	  ;; Echo command in progress if there is one, unless in a recursive parse
+	  (unless eps
+	    (let ((cmd (hemlock-current-command view)))
+	      (unless (eql 0 (length cmd))
+		(let ((cstr (concatenate 'string (pretty-key-string cmd) " ")))
+		  (message cstr))))))))))
+
+(defmethod hemlock-view-current-buffer ((view hemlock-view))
+  (if (hemlock-prompted-input-state view)
+    (hemlock-echo-area-buffer view)
+    (hemlock-view-buffer view)))
+
+(defun buffer-modification-state (buffer)
+  (multiple-value-bind (start end) (buffer-selection-range buffer)
+    (list* (buffer-signature buffer) start end)))
+
+(defvar *next-view-start* nil)
+
+(defun set-scroll-position (how &optional where)
+  "Set the desired scroll position of the current view"
+  (when (markp where)
+    (unless (eq (mark-buffer where)
+                (hemlock-view-buffer (current-view)))
+      (error "~s is not a mark in the current view." where))
+    (setq where (mark-absolute-position where)))
+  (setf *next-view-start* (cons how where)))
+
+(defmethod handle-hemlock-event ((view hemlock-view) key)
+  ;; Key can also be a function, in which case it will get executed in the view event context
+  #+debug (log-debug "handle-hemlock-event ~s~:[~; (recursive)~]"
+                  key
+                  (and (eq view *current-view*)
+                       (eq (hemlock-view-current-buffer view) *current-buffer*)))
+  (if (and (eq view *current-view*)
+           (eq (hemlock-view-current-buffer view) *current-buffer*))
+    ;; KLUDGE: This might happen with stuff that normally switches buffers (e.g. meta-.)
+    ;; but happens not to.  Because of the stupid buffer binding/unbinding, it's currently
+    ;; problematic to just recurse here, so don't.
+    (progn
+      ;; TODO: should this catch exit-event or let outer one do it?  Check callers.
+      (execute-hemlock-key view key)
+      )
+    (ccl::with-standard-abort-handling "Abort editor event handling"
+      (let* ((*current-view* view)
+             (*current-buffer* (hemlock-view-current-buffer view))
+             (*next-view-start* nil) ;; gets set by scrolling commands
+             (text-buffer (hemlock-view-buffer view))
+             (mod (buffer-modification-state text-buffer)))
+        (modifying-buffer-storage (*current-buffer*)
+          (restart-case
+              (handler-bind ((error #'(lambda (c)
+                                        (lisp-error-error-handler c :debug-p t))))
+                (execute-hemlock-key view key))
+            (exit-event-handler () :report "Exit from hemlock event handler")))
+        ;; Update display
+        (if *next-view-start*
+          (destructuring-bind (how . where) *next-view-start*
+            (hemlock-ext:scroll-view view how where))
+          (unless (equal mod (buffer-modification-state text-buffer))
+            ;; Modified buffer, make sure user sees what happened
+            (hemlock-ext:ensure-selection-visible view)))
+        (update-echo-area-after-command view)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/abbrev.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/abbrev.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/abbrev.lisp	(revision 13309)
@@ -0,0 +1,690 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;		     Hemlock Word Abbreviation Mode
+;;;		          by Jamie W. Zawinski
+;;;		           24 September 1985
+;;;
+(in-package :hemlock)
+
+;;;; These Things are Here:
+
+;;; C-X C-A    Add Mode Word Abbrev 
+;;;               Define a mode abbrev for the word before point.
+;;; C-X +      Add Global Word Abbrev 
+;;;               Define a global abbrev for the word before point.
+;;; C-X C-H    Inverse Add Mode Word Abbrev
+;;;               Define expansion for mode abbrev before point.
+;;; C-X -      Inverse Add Global Word Abbrev
+;;;               Define expansion for global abbrev before point.
+;;; Alt Space  Abbrev Expand Only
+;;;               Expand abbrev without inserting anything.
+;;; M-'        Word Abbrev Prefix Mark
+;;;               Mark a prefix to be glued to an abbrev following.
+;;; C-X U      Unexpand Last Word
+;;;               Unexpands last abbrev or undoes C-X U.
+
+;;; List Word Abbrevs                 Shows definitions of all word abbrevs.
+;;; Edit Word Abbrevs                 Lets you edit the definition list directly.
+;;; Read Word Abbrev File <filename>  Define word abbrevs from a definition file.
+;;; Write Word Abbrev File            Make a definition file from current abbrevs.
+
+;;; Make Word Abbrev <abbrev><expansion><mode> More General form of C-X C-A, etc.
+;;; Delete All Word Abbrevs                      Wipes them all.
+;;; Delete Mode Word Abbrev                      Kills all Mode abbrev.
+;;; Delete Global Word Abbrev                    Kills all Global abbrev.
+
+;;; Insert Word Abbrevs          Inserts a list of current definitions in the
+;;;                                format that Define Word Abbrevs uses.
+;;; Define Word Abbrevs          Defines set of abbrevs from a definition list in 
+;;;                                the buffer.
+;;; Word Abbrev Apropos <string> Shows definitions containing <string> in abbrev,
+;;;                                definition, or mode.
+
+;;; Append Incremental Word Abbrev File           Appends to a file changed abbrev
+;;;                                                 definitions since last dumping.
+
+(defmode "Abbrev" :major-p nil :transparent-p t :precedence 2.0)
+
+
+(defvar *global-abbrev-table* (make-hash-table :test #'equal)
+  "Hash table holding global abbrev definitions.")
+
+(defhvar "Abbrev Pathname Defaults"
+  "Holds the name of the last Abbrev-file written."
+  :value (pathname "abbrev.defns"))
+
+(defvar *new-abbrevs* ()
+ "holds a list of abbrevs (and their definitions and modes) changed since saving.")
+
+
+
+;;; C-X C-H    Inverse Add Mode Word Abbrev 
+;;;               Define a mode expansion for the word before point.
+
+(defcommand "Inverse Add Mode Word Abbrev" (p)
+  "Defines a mode word abbrev expansion for the word before the point."
+  "Defines a mode word abbrev expansion for the word before the point."
+  (declare (ignore p))
+  (let ((word (prev-word 1 (current-point)))
+	(mode (buffer-major-mode (current-buffer))))
+    (make-word-abbrev-command nil word nil mode)))
+
+
+;;; C-X C-A    Add Mode Word Abbrev
+;;;               Define mode abbrev for word before point.
+
+(defcommand "Add Mode Word Abbrev" (p)
+  "Defines a mode word abbrev for the word before the point.
+  With a positive argument, uses that many preceding words as the expansion.
+  With a zero argument, uses the region as the expansion.  With a negative
+  argument, prompts for a word abbrev to delete in the current mode."
+  "Defines or deletes a mode word abbrev."
+  (if (and p (minusp p))
+      (delete-mode-word-abbrev-command nil)
+      (let* ((val (if (eql p 0)
+		      (region-to-string (current-region nil))
+		      (prev-word (or p 1) (current-point))))
+	     (mode (buffer-major-mode (current-buffer))))
+	(make-word-abbrev-command nil nil val mode))))
+
+
+
+;;; C-X -    Inverse Add Global Word Abbrev
+;;;               Define global expansion for word before point.
+
+(defcommand "Inverse Add Global Word Abbrev" (p)
+  "Defines a Global expansion for the word before point."
+  "Defines a Global expansion for the word before point."
+  (declare (ignore p))
+  (let ((word (prev-word 1 (current-point))))
+    (make-word-abbrev-command nil word nil "Global")))
+
+
+
+;;; C-X +      Add Global Word Abbrev
+;;;               Define global Abbrev for word before point.
+
+(defcommand "Add Global Word Abbrev" (p)
+  "Defines a global word abbrev for the word before the point.
+  With a positive argument, uses that many preceding words as the expansion.
+  With a zero argument, uses the region as the expansion.  With a negative
+  argument, prompts for a global word abbrev to delete."
+  "Defines or deletes a global word abbrev."
+  (if (and p (minusp p))
+      (delete-global-word-abbrev-command nil)
+      (let ((val (if (eql p 0)
+		     (region-to-string (current-region nil))
+		     (prev-word (or p 1) (current-point)))))
+	(make-word-abbrev-command nil nil val "Global"))))
+
+
+
+;;;; Defining Abbrevs
+
+;;; Make Word Abbrev <abbrev><expansion><mode>  More General form of C-X C-A, etc.
+
+(defvar *global-abbrev-string-table*
+  (make-string-table :initial-contents '(("Global" . nil))))
+
+(defcommand "Make Word Abbrev" (p &optional abbrev expansion mode)
+  "Defines an arbitrary word abbreviation.
+  Prompts for abbrev, expansion, and mode."
+  "Makes Abbrev be a word abbreviation for Expansion when in Mode.  If
+  mode is \"Global\" then make a global abbrev."
+  (declare (ignore p))
+  (unless mode
+    (setq mode
+	  (prompt-for-keyword
+	   (list *mode-names* *global-abbrev-string-table*)
+	   :prompt "Mode of abbrev to add: "
+	   :default "Global"
+	   :help 
+	   "Type the mode of the Abbrev you want to add, or confirm for Global.")))
+  (let ((globalp (string-equal mode "Global")))
+    (unless (or globalp (mode-major-p mode))
+      (editor-error "~A is not a major mode." mode))
+    (unless abbrev
+      (setq abbrev
+	    (prompt-for-string
+	     :trim t
+	     :prompt
+	     (list "~A abbreviation~@[ of ~S~]: " mode expansion)
+	     :help
+	     (list "Define a ~A word abbrev." mode))))
+    (when (zerop (length abbrev))
+      (editor-error "Abbreviation must be at least one character long."))
+    (unless (every #'(lambda (ch)
+		       (zerop (character-attribute :word-delimiter ch)))
+		   (the simple-string abbrev))
+      (editor-error "Word Abbrevs must be a single word."))
+    (unless expansion
+      (setq expansion
+	    (prompt-for-string
+	     :prompt (list "~A expansion for ~S: " mode abbrev)
+	     :help (list "Define the ~A expansion of ~S." mode abbrev))))
+    (setq abbrev (string-downcase abbrev))
+    (let* ((table (cond (globalp *global-abbrev-table*)
+			((hemlock-bound-p 'Mode-Abbrev-Table :mode mode)
+			 (variable-value 'Mode-Abbrev-Table :mode mode))
+			(t
+			 (let ((new (make-hash-table :test #'equal)))
+			   (defhvar "Mode Abbrev Table"
+			     "Hash Table of Mode Abbrevs"
+			     :value new :mode mode)
+			   new))))
+	   (old (gethash abbrev table)))
+      (when (or (not old)
+		(prompt-for-y-or-n
+		 :prompt
+		 (list "Current ~A definition of ~S is ~S.~%Redefine?"
+		       mode abbrev old)
+		 :default t
+		 :help (list "Redefine the expansion of ~S." abbrev)))
+	(setf (gethash abbrev table) expansion)
+	(push (list abbrev expansion (if globalp nil mode))
+	      *new-abbrevs*)))))
+
+
+
+;;; Alt Space  Abbrev Expand Only
+;;;               Expand abbrev without inserting anything.
+
+(defcommand "Abbrev Expand Only" (p)
+  "This command expands the word before point into its abbrev definition 
+  (if indeed it has one)."
+  "This command expands the word before point into its abbrev definition 
+  (if indeed it has one)."
+  (declare (ignore p))
+  (let* ((word (prev-word 1 (current-point)))
+	 (glob (gethash (string-downcase word) *global-abbrev-table*))
+	 (mode (if (hemlock-bound-p 'Mode-Abbrev-Table)
+		   (gethash (string-downcase word)
+			    (value Mode-Abbrev-Table))))
+	 (end-word (reverse-find-attribute (copy-mark (current-point)
+						      :right-inserting)
+					   :word-delimiter #'zerop))
+	 (result (if mode mode glob)))
+    (when (or mode glob)
+      (delete-characters end-word (- (length word)))
+      (cond ((equal word (string-capitalize word))
+	     (setq result (string-capitalize result)))
+	    ((equal word (string-upcase word))
+	     (setq result (string-upcase result))))
+      (insert-string end-word result)
+      (unless (hemlock-bound-p 'last-expanded)
+	(defhvar "last expanded"
+            "Holds a mark, the last expanded abbrev, and its expansion in a list."
+            :buffer (current-buffer)))
+      (setf (value last-expanded)
+	    (list (copy-mark (current-point) :right-inserting)
+		  word result)))
+    (delete-mark end-word))
+  (when (and (hemlock-bound-p 'prefix-mark)
+	     (value prefix-mark))
+    (delete-characters (value prefix-mark) 1)
+    (delete-mark (value prefix-mark))
+    (setf (value prefix-mark) nil)))
+
+
+
+;;; This function returns the n words immediately before the mark supplied.
+
+(defun prev-word (n mark)
+  (let* ((mark-1 (reverse-find-attribute (copy-mark mark :temporary)
+					 :word-delimiter #'zerop))
+	 (mark-2 (copy-mark mark-1)))
+    (dotimes (x n (region-to-string (region mark-2 mark-1)))
+      (reverse-find-attribute (mark-before mark-2) :word-delimiter))))
+
+
+
+;;; M-'        Word Abbrev Prefix Mark
+;;;               Mark a prefix to be glued to an abbrev following.
+
+;;; When "Abbrev Expand Only" expands the abbrev (because #\- is an expander)
+;;; it will see that prefix-mark is non-nil, and will delete the #\- immediately
+;;; after prefix-mark.
+
+(defcommand "Word Abbrev Prefix Mark" (p)
+  "Marks a prefix to be glued to an abbrev following." 
+  "Marks a prefix to be glued to an abbrev following."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'prefix-mark)
+    (defhvar "prefix mark"
+             "Holds a mark (or not) pointing to the current Prefix Mark."
+             :buffer (current-buffer)))
+  (when (value prefix-mark)
+    (delete-mark (value prefix-mark)))
+  (setf (value prefix-mark) (copy-mark (current-point) :right-inserting))
+  (insert-character (value prefix-mark) #\-))
+
+
+
+;;; C-X U     Unexpand Last Word
+;;;              Unexpands last abbrev or undoes last C-X U.
+
+(defcommand "Unexpand Last Word" (p)
+  "Undoes the last abbrev expansion, or undoes \"Unexpand Last Word\".
+  Only one abbrev may be undone."
+  "Undoes the last abbrev expansion, or undoes \"Unexpand Last Word\"."
+  (declare (ignore p))
+  (unless (or (not (hemlock-bound-p 'last-expanded))
+	      (value last-expanded))
+    (editor-error "Nothing to Undo."))
+  (let ((mark (car (value last-expanded)))
+	(word1 (second (value last-expanded)))
+	(word2 (third (value last-expanded))))
+    (unless (string= word2
+		     (region-to-string
+		      (region (character-offset (copy-mark mark :temporary)
+						(- (length word2)))
+			      mark)))
+      (editor-error "The last expanded Abbrev has been altered in the text."))
+    (delete-characters mark (- (length word2)))
+    (insert-string mark word1)
+    (character-offset mark (length word1))
+    (setf (value last-expanded) (list mark word2 word1))))
+
+ 
+  
+;;; Delete Mode Word Abbrev                       Kills some Mode abbrevs.
+
+(defcommand "Delete Mode Word Abbrev"
+	    (p &optional abbrev
+	       (mode (buffer-major-mode (current-buffer))))
+  "Prompts for a word abbrev and deletes the mode expansion in the current mode.
+  If called with a prefix argument, deletes all word abbrevs define in the
+  current mode."
+  "Deletes Abbrev in Mode, or all abbrevs in Mode if P is true."
+  (let ((boundp (hemlock-bound-p 'Mode-Abbrev-Table :mode mode)))
+    (if p
+	(when boundp
+	  (delete-variable 'Mode-Abbrev-Table :mode mode))
+	(let ((down
+	       (string-downcase
+		(or abbrev
+		    (prompt-for-string
+		     :prompt (list "~A abbrev to delete: " mode)
+		     :help
+ (list "Give the name of a ~A mode word abbrev to delete." mode)
+		     :trim t))))
+	      (table (and boundp (variable-value 'mode-abbrev-table :mode mode))))
+	  (unless (and table (gethash down table))
+	    (editor-error "~S is not the name of an abbrev in ~A mode."
+			  down mode))
+	  (remhash down table)))))
+
+
+;;; Delete Global Word Abbrevs                    Kills some Global abbrevs.
+
+(defcommand "Delete Global Word Abbrev" (p &optional abbrev)
+  "Prompts for a word abbrev and delete the global expansion.
+  If called with a prefix argument, deletes all global abbrevs."
+  "Deletes the global word abbreviation named Abbrev.  If P is true,
+  deletes all global abbrevs."
+  (if p
+      (setq *global-abbrev-table* (make-hash-table :test #'equal))
+      (let ((down 
+	     (string-downcase
+	      (or abbrev
+		  (prompt-for-string
+		   :prompt "Global abbrev to delete: "
+		   :help "Give the name of a global word abbrev to delete."
+		   :trim t)))))
+	(unless (gethash down *global-abbrev-table*)
+	  (editor-error "~S is not the name of a global word abbrev." down))
+	(remhash down *global-abbrev-table*))))
+	
+;;; Delete All Word Abbrevs                       Wipes them all.
+
+(defcommand "Delete All Word Abbrevs" (p)
+  "Deletes all currently defined Word Abbrevs"
+  "Deletes all currently defined Word Abbrevs"
+  (declare (ignore p))
+  (Delete-Global-Word-Abbrev-Command 1)
+  (Delete-Mode-Word-Abbrev-Command 1))
+
+
+
+;;;; Abbrev I/O
+
+;;; List Word Abbrevs                 Shows definitions of all word abbrevs.
+
+(defcommand "List Word Abbrevs" (p)
+  "Lists all of the currently defined Word Abbrevs."
+  "Lists all of the currently defined Word Abbrevs."
+  (word-abbrev-apropos-command p ""))
+
+
+;;; Word Abbrev Apropos <string> Shows definitions containing <string> in abbrev,
+;;;                                definition, or mode.
+
+(defcommand "Word Abbrev Apropos" (p &optional search-string)
+  "Lists all of the currently defined Word Abbrevs which contain a given string
+  in their abbrev. definition, or mode."
+  "Lists all of the currently defined Word Abbrevs which contain a given string
+  in their abbrev. definition, or mode."
+  (declare (ignore p))
+  (unless search-string
+    (setq search-string
+	  (string-downcase
+	   (prompt-for-string
+	    :prompt "Apropos string: "
+	    :help "The string to search word abbrevs and definitions for."))))
+  (multiple-value-bind (count mode-tables) (count-abbrevs)
+    (with-pop-up-display (s :height (min (1+ count) 30))
+      (unless (zerop (hash-table-count *global-abbrev-table*))
+	(maphash #'(lambda (key val)
+		     (when (or (search search-string (string-downcase key))
+			       (search search-string (string-downcase val)))
+		       (write-abbrev key val nil s t)))
+		 *global-abbrev-table*))
+      (dolist (modename mode-tables)
+	(let ((table (variable-value 'Mode-Abbrev-Table :mode modename)))
+	  (if (search search-string (string-downcase modename))
+	      (maphash #'(lambda (key val)
+			   (write-abbrev key val modename s t))
+		       table)
+	      (maphash #'(lambda (key val)
+			   (when (or (search search-string (string-downcase key))
+				     (search search-string (string-downcase val)))
+			     (write-abbrev key val modename s t)))
+		       table))))
+      (terpri s))))
+
+
+
+(defun count-abbrevs ()
+  (let* ((count (hash-table-count *global-abbrev-table*))
+	 (mode-tables nil))
+    (do-strings (which x *mode-names*)
+      (declare (ignore x))
+      (when (hemlock-bound-p 'Mode-Abbrev-Table :mode which)
+	(let ((table-count (hash-table-count (variable-value 'Mode-Abbrev-Table
+							     :mode which))))
+	  (unless (zerop table-count)
+	    (incf count table-count)
+	    (push which mode-tables)))))
+    (values count mode-tables)))
+
+
+
+;;; Edit Word Abbrevs                 Lets you edit the definition list directly.
+
+(defcommand "Edit Word Abbrevs" (p)
+  "Allows direct editing of currently defined Word Abbrevs."
+  "Allows direct editing of currently defined Word Abbrevs."
+  (declare (ignore p))
+  (when (getstring "Edit Word Abbrevs" *buffer-names*)
+    (delete-buffer (getstring "Edit Word Abbrevs" *buffer-names*)))
+  (let ((old-buf (current-buffer))
+	(new-buf (make-buffer "Edit Word Abbrevs")))
+    (change-to-buffer new-buf)
+    (unwind-protect
+      (progn
+       (insert-word-abbrevs-command nil)
+       (do-recursive-edit)
+       (unless (equal #\newline (previous-character (buffer-end (current-point))))
+	 (insert-character (current-point) #\newline))
+       (delete-all-word-abbrevs-command nil)
+       (define-word-abbrevs-command nil))
+      (progn
+       (change-to-buffer old-buf)
+       (delete-buffer new-buf)))))
+
+
+
+;;; Insert Word Abbrevs          Inserts a list of current definitions in the
+;;;                                format that Define Word Abbrevs uses.
+
+(defcommand "Insert Word Abbrevs" (p)
+  "Inserts into the current buffer a list of all currently defined abbrevs in the
+  format used by \"Define Word Abbrevs\"."
+  "Inserts into the current buffer a list of all currently defined abbrevs in the
+  format used by \"Define Word Abbrevs\"."
+  
+  (declare (ignore p))
+  (multiple-value-bind (x mode-tables)
+		       (count-abbrevs)
+    (declare (ignore x))
+    (with-output-to-mark (stream (current-point) :full)
+      (maphash #'(lambda (key val)
+		   (write-abbrev key val nil stream))
+	       *global-abbrev-table*)
+      
+      (dolist (mode mode-tables)
+	(let ((modename (if (listp mode) (car mode) mode)))
+	  (maphash #'(lambda (key val)
+		       (write-abbrev key val modename stream))
+		   (variable-value 'Mode-Abbrev-Table :mode modename)))))))
+
+
+
+;;; Define Word Abbrevs          Defines set of abbrevs from a definition list in 
+;;;                                the buffer.
+
+(defcommand "Define Word Abbrevs" (p)
+  "Defines Word Abbrevs from the definition list in the current buffer.  The 
+  definition list must be in the format produced by \"Insert Word Abbrevs\"."
+  "Defines Word Abbrevs from the definition list in the current buffer.  The
+  definition list must be in the format produced by \"Insert Word Abbrevs\"."
+  
+  (declare (ignore p))
+  (with-input-from-region (file (buffer-region (current-buffer)))
+    (read-abbrevs file)))
+
+
+
+;;; Read Word Abbrev file <filename>   Define word abbrevs from a definition file.
+
+;;; Ignores all lines less than 4 characters, i.e. blankspace or errors. That is
+;;; the minimum number of characters possible to define an abbrev.  It thinks the 
+;;; current abbrev "wraps" if there is no #\" at the end of the line or there are
+;;; two #\"s at the end of the line (unless that is the entire definition string,
+;;; i.e, a null-abbrev).
+
+;;; The format of the Abbrev files is 
+;;;
+;;;                   ABBREV<tab><tab>"ABBREV DEFINITION"
+;;;
+;;; for Global Abbrevs, and
+;;;
+;;;                   ABBREV<tab>(MODE)<tab>"ABBREV DEFINITION"
+;;;
+;;; for Modal Abbrevs.  
+;;; Double-quotes contained within the abbrev definition are doubled.  If the first
+;;; line of an abbrev definition is not closed by a single double-quote, then
+;;; the subsequent lines are read in until a single double-quote is found.
+
+(defcommand "Read Word Abbrev File" (p &optional filename)
+  "Reads in a file of previously defined abbrev definitions."
+  "Reads in a file of previously defined abbrev definitions."
+  (declare (ignore p))
+  (setf (value abbrev-pathname-defaults)
+	(if filename
+	    filename
+	    (prompt-for-file
+	     :prompt "Name of abbrev file: "
+	     :help "The name of the abbrev file to load."
+	     :default (value abbrev-pathname-defaults)
+	     :must-exist nil)))
+  (with-open-file (file (value abbrev-pathname-defaults) :direction :input
+			:element-type 'base-char :if-does-not-exist :error)
+    (read-abbrevs file)))
+
+
+;;; Does the actual defining of abbrevs from a given stream, expecting tabs and
+;;; doubled double-quotes.
+
+(defun read-abbrevs (file)
+  (do ((line (read-line file nil nil)
+	     (read-line file nil nil)))
+      ((null line))
+    (unless (< (length line) 4)
+      (let* ((tab (position #\tab line))
+	     (tab2 (position #\tab line :start (1+ tab)))
+	     (abbrev (subseq line 0 tab))
+	     (modename (subseq line (1+ tab) tab2))
+	     (expansion (do* ((last (1+ (position #\" line))
+				    (if found (min len (1+ found)) 0))
+			      (len (length line))
+			      (found (if (position #\" line :start last)
+					 (1+ (position #\" line :start last)))
+				     (if (position #\" line :start last)
+					 (1+ (position #\" line :start last))))
+			      (expansion (subseq line last (if found found len))
+					 (concatenate 'simple-string expansion
+						      (subseq line last
+							      (if found found
+								  len)))))
+			     ((and (or (null found) (= found len))
+				   (equal #\" (char line (1- len)))
+				   (or (not (equal #\" (char line (- len 2))))
+				       (= (- len 3) tab2)))
+			      (subseq expansion 0 (1- (length expansion))))
+			  
+			  (when (null found)
+			    (setq line (read-line file nil nil)
+				  last 0
+				  len (length line)
+				  found (if (position #\" line)
+					    (1+ (position #\" line)))
+				  expansion (format nil "~A~%~A" expansion
+						    (subseq line 0 (if found
+								       found
+								       0))))))))
+	
+	(cond ((equal modename "")
+	       (setf (gethash abbrev *global-abbrev-table*)
+		     expansion))
+	      (t (setq modename (subseq modename 1 (1- (length modename))))
+		 (unless (hemlock-bound-p 'Mode-Abbrev-Table
+					  :mode modename)
+		   (defhvar "Mode Abbrev Table"
+    			    "Hash Table of Mode Abbrevs"
+    			    :value (make-hash-table :test #'equal)
+  			    :mode modename))
+		 (setf (gethash abbrev (variable-value
+					'Mode-Abbrev-Table :mode modename))
+		       expansion)))))))
+
+
+;;; Write Word Abbrev File            Make a definition file from current abbrevs.
+
+(defcommand "Write Word Abbrev File" (p &optional filename)
+  "Saves the currently defined Abbrevs to a file."
+  "Saves the currently defined Abbrevs to a file."
+  (declare (ignore p))
+  (unless filename
+    (setq filename
+	  (prompt-for-file
+	   :prompt "Write abbrevs to file: "
+	   :default (value abbrev-pathname-defaults)
+	   :help "Name of the file to write current abbrevs to."
+	   :must-exist nil)))
+  (with-open-file (file filename :direction :output
+			:element-type 'base-char :if-exists :supersede
+			:if-does-not-exist :create)
+    (multiple-value-bind (x mode-tables) (count-abbrevs)
+      (declare (ignore x))
+      (maphash #'(lambda (key val)
+		   (write-abbrev key val nil file))
+	       *global-abbrev-table*)
+      
+      (dolist (modename mode-tables)
+	(let ((mode (if (listp modename) (car modename) modename)))
+	  (maphash #'(lambda (key val)
+		       (write-abbrev key val mode file))
+		   (variable-value 'Mode-Abbrev-Table :mode mode))))))
+  (let ((tn (truename filename)))
+    (setf (value abbrev-pathname-defaults) tn)
+    (message "~A written." (namestring tn))))
+
+
+
+;;; Append to Word Abbrev File          Appends to a file changed abbrev 
+;;;                                     definitions since last dumping.
+
+(defcommand "Append to Word Abbrev File" (p &optional filename)
+  "Appends Abbrevs defined or redefined since the last save to a file."
+  "Appends Abbrevs defined or redefined since the last save to a file."
+  (declare (ignore p))
+  (cond
+   (*new-abbrevs*
+    (unless filename
+      (setq filename
+	    (prompt-for-file
+	     :prompt
+	     "Append incremental abbrevs to file: "
+	     :default (value abbrev-pathname-defaults)
+	     :must-exist nil
+	     :help "Filename to append recently defined Abbrevs to.")))
+    (write-incremental :append filename))
+   (t
+    (message "No Abbrev definitions have been changed since the last write."))))
+
+
+(defun write-incremental (mode filename)
+  (with-open-file (file filename :direction :output
+			:element-type 'base-char
+			:if-exists mode :if-does-not-exist :create)
+    (dolist (def *new-abbrevs*)
+      (let ((abb (car def))
+	    (val (second def))
+	    (mode (third def)))
+	(write-abbrev abb val mode file))))
+  (let ((tn (truename filename)))
+    (setq *new-abbrevs* nil)
+    (setf (value abbrev-pathname-defaults) tn)
+    (message "~A written." (namestring tn))))
+
+
+;;; Given an Abbrev, expansion, mode (nil for Global), and stream, this function
+;;; writes to the stream with doubled double-quotes and stuff.
+;;; If the flag is true, then the output is in a pretty format (like "List Word
+;;; Abbrevs" uses), otherwise output is in tabbed format (like "Write Word 
+;;; Abbrev File" uses).
+
+(defun write-abbrev (abbrev expansion modename file &optional flag)
+  (if flag
+      (if modename
+	  (format file "~5t~A~20t(~A)~35t\"" abbrev modename); pretty format
+	  (format file "~5t~A~35t\"" abbrev))                ; pretty format
+      (cond (modename
+	     (write-string abbrev file)
+	     (write-char #\tab file)
+	     (format file "(~A)" modename)                   ; "~A<tab>(~A)<tab>\""
+	     (write-char #\tab file)
+	     (write-char #\" file))
+	    (t
+	     (write-string abbrev file)
+	     (write-char #\tab file)                         ; "~A<tab><tab>\""
+	     (write-char #\tab file)
+	     (write-char #\" file))))
+  (do* ((prev 0 found)
+	(found (position #\" expansion)
+	       (position #\" expansion :start found)))
+       ((not found)
+	(write-string expansion file :start prev)
+	(write-char #\" file)
+	(terpri file))
+    (incf found)
+    (write-string expansion file :start prev :end found)
+    (write-char #\" file)))
+
+
+(defcommand "Abbrev Mode" (p)
+  "Put current buffer in Abbrev mode." 
+  "Put current buffer in Abbrev mode."  
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Abbrev")
+	(not (buffer-minor-mode (current-buffer) "Abbrev"))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/auto-save.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/auto-save.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/auto-save.lisp	(revision 13309)
@@ -0,0 +1,401 @@
+;;; -*- Package: Hemlock; Log: hemlock.log -*-
+;;; 
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;; 
+;;; Auto-Save Mode
+;;; Written by Christopher Hoover
+;;;
+
+(in-package :hemlock)
+
+
+
+;;;; Per Buffer State Information
+
+;;; 
+;;; The auto-save-state structure is used to store the state information for
+;;; a particular buffer in "Save" mode, namely the buffer-signature at the last
+;;; key stroke, the buffer-signature at the time of the last checkpoint, a count
+;;; of the number of destructive keystrokes which have occured since the time of
+;;; the last checkpoint, and the pathname used to write the last checkpoint.  It
+;;; is generally kept in a buffer-local hvar called "Auto Save State".
+;;; 
+(defstruct (auto-save-state
+	    (:conc-name save-state-)
+	    (:print-function print-auto-save-state))
+  "Per buffer state for auto-save"
+  (buffer nil)				   ; buffer this state is for; for printing
+  (key-signature 0 :type fixnum)	   ; buffer-signature at last keystroke
+  (last-ckp-signature 0 :type fixnum)	   ; buffer-signature at last checkpoint
+  (key-count 0 :type fixnum)		   ; # destructive keystrokes since ckp
+  (pathname nil))			   ; pathname used to write last ckp file
+
+(defun print-auto-save-state (auto-save-state stream depth)
+  (declare (ignore depth))
+  (format stream "#<Auto Save Buffer State for buffer ~A>"
+	  (buffer-name (save-state-buffer auto-save-state))))
+
+
+;;; GET-AUTO-SAVE-STATE tries to get the auto-save-state for the buffer.  If
+;;; the buffer is not in "Save" mode then this function returns NIL.
+;;;
+(defun get-auto-save-state (buffer)
+  (if (hemlock-bound-p 'auto-save-state :buffer buffer)
+       (variable-value 'auto-save-state :buffer buffer)))
+
+;;; RESET-AUTO-SAVE-STATE resets the auto-save-state of the buffer making it
+;;; look as if the buffer was just checkpointed.  This is in fact how
+;;; checkpoint-buffer updates the state.  If the buffer is not in "Save" mode
+;;; this function punts the attempt and does nothing.
+;;;
+(defun reset-auto-save-state (buffer)
+  (let ((state (get-auto-save-state buffer)))
+    (when state
+      (let ((signature (buffer-signature buffer)))
+	(setf (save-state-key-signature state)
+	      signature)
+	(setf (save-state-last-ckp-signature state)
+	      signature)
+	(setf (save-state-key-count state)
+	      0)))))
+
+
+
+
+;;;; Checkpoint Pathname Interface/Internal Routines
+
+;;; GET-CHECKPOINT-PATHNAME -- Interface
+;;;
+;;; Returns the pathname of the checkpoint file for the specified
+;;; buffer;  Returns NIL if no checkpoints have been written thus
+;;; far or if the buffer isn't in "Save" mode.
+;;; 
+(defun get-checkpoint-pathname (buffer)
+  "Returns the pathname of the checkpoint file for the specified buffer.
+   If no checkpoints have been written thus far, or if the buffer is not in
+   \"Save\" mode, return nil."
+  (let ((state (get-auto-save-state buffer)))
+    (if state
+	(save-state-pathname state))))
+
+;;; MAKE-UNIQUE-SAVE-PATHNAME is used as the default value for "Auto Save
+;;; Pathname Hook" and is mentioned in the User's manual, so it gets a doc
+;;; doc string.
+;;;
+(defun make-unique-save-pathname (buffer)
+  "Returns a pathname for a non-existing file in DEFAULT-DIRECTORY.  Uses
+   GENSYM to for a file name: save-GENSYM.CKP."
+  (declare (ignore buffer))
+  (let ((def-dir (hemlock-ext:default-directory)))
+    (loop
+      (let* ((sym (gensym))
+	     (f (merge-pathnames (format nil "save-~A.CKP" sym) def-dir)))
+	(unless (probe-file f)
+	  (return f))))))
+    
+(defhvar "Auto Save Pathname Hook"
+  "This hook is called by Auto Save to get a checkpoint pathname when there
+   is no pathname associated with a buffer.  If this value is NIL, then
+   \"Save\" mode is turned off in the buffer.  Otherwise, the function
+   will be called. It should take a buffer as its argument and return either
+   NIL or a pathname.  If NIL is returned, then \"Save\" mode is turned off
+   in the buffer;  else the pathname returned is used as the checkpoint
+   pathname for the buffer."
+  :value #'make-unique-save-pathname)
+
+
+;;; MAKE-BUFFER-CKP-PATHNAME attempts to form a pathname by using the buffer's
+;;; associated pathname (from buffer-pathname).  If there isn't a pathname
+;;; associated with the buffer, the function returns nil.  Otherwise, it uses
+;;; the "Auto Save Filename Pattern" and FORMAT to make the checkpoint
+;;; pathname.
+;;;
+(defun make-buffer-ckp-pathname (buffer)
+  (let ((buffer-pn (buffer-pathname buffer)))
+    (if buffer-pn
+	(pathname (format nil
+			  (value auto-save-filename-pattern)
+			  (directory-namestring buffer-pn)
+			  (file-namestring buffer-pn))))))
+
+
+
+
+;;;; Buffer-level Checkpoint Routines
+
+;;;
+;;; write-checkpoint-file -- Internal
+;;;
+;;; Does the low-level write of the checkpoint.  Returns T if it succeeds
+;;; and NIL if it fails.  Echoes winnage or lossage to the luser.
+;;;
+(defun write-checkpoint-file (pathname buffer)
+  (let ((ns (namestring pathname)))
+    (cond ((hemlock-ext:file-writable pathname)
+	   (message "Saving ~A" ns)
+	   (handler-case (progn
+			   (write-file (buffer-region buffer) pathname
+				       :keep-backup nil
+				       :access #o600) ;read/write by owner.
+			   t)
+	     (error (condition)
+	       (loud-message "Auto Save failure: ~A" condition)
+	       nil)))
+	  (t
+	   (message "Can't write ~A" ns)
+	   nil))))
+
+
+;;;
+;;; To save, or not to save... and to save as what?
+;;;
+;;; First, make-buffer-ckp-pathname is called. It will return either NIL or
+;;; a pathname formed by using buffer-pathname in conjunction with the hvar
+;;; "Auto Save Filename Pattern".  If there isn't an associated pathname or
+;;; make-buffer-ckp-pathname returns NIL, then we use the pathname we used
+;;; the last time we checkpointed the buffer.  If we've never checkpointed
+;;; the buffer, then we check "Auto Save Pathname Hook".  If it is NIL then
+;;; we turn Save mode off for the buffer, else we funcall the function on
+;;; the hook with the buffer as an argument.  The function on the hook should
+;;; return either NIL or a pathname. If it returns NIL, we toggle Save mode
+;;; off for the buffer;  otherwise, we use the pathname it returned.
+;;;
+
+;;; 
+;;; checkpoint-buffer -- Internal
+;;;
+;;; This functions takes a buffer as its argument and attempts to write a
+;;; checkpoint for that buffer.  See the notes at the beginning of this page
+;;; for how it determines what pathname to use as the checkpoint pathname.
+;;; Note that a checkpoint is not necessarily written -- instead "Save"
+;;; mode may be turned off for the buffer.
+;;;
+(defun checkpoint-buffer (buffer)
+  (let* ((state (get-auto-save-state buffer))
+	 (buffer-ckp-pn (make-buffer-ckp-pathname buffer))
+	 (last-pathname (save-state-pathname state)))
+    (cond (buffer-ckp-pn
+	   (when (write-checkpoint-file buffer-ckp-pn buffer)
+	     (reset-auto-save-state buffer)
+	     (setf (save-state-pathname state) buffer-ckp-pn)
+	     (when (and last-pathname
+			(not (equal last-pathname buffer-ckp-pn))
+			(probe-file last-pathname))
+	       (delete-file last-pathname))))
+	  (last-pathname
+	   (when (write-checkpoint-file last-pathname buffer)
+	     (reset-auto-save-state buffer)))
+	  (t
+	   (let* ((save-pn-hook (value auto-save-pathname-hook))
+		  (new-pn (if save-pn-hook
+			      (funcall save-pn-hook buffer))))
+	     (cond ((or (not new-pn)
+			(zerop (length
+				(the simple-string (namestring new-pn)))))
+		    (setf (buffer-minor-mode buffer "Save") nil))
+		   (t
+		    (when (write-checkpoint-file new-pn buffer)
+		      (reset-auto-save-state buffer)
+		      (setf (save-state-pathname state) new-pn)))))))))
+
+;;;
+;;; checkpoint-all-buffers -- Internal
+;;; 
+;;; This function looks through the buffer list and checkpoints
+;;; each buffer that is in "Save" mode that has been modified since
+;;; its last checkpoint. 
+;;; 
+(defun checkpoint-all-buffers (elapsed-time)
+  (declare (ignore elapsed-time))
+  (dolist (buffer *buffer-list*)
+    (let ((state (get-auto-save-state buffer)))
+      (when (and state
+		 (buffer-modified buffer)
+		 (not (eql
+		       (save-state-last-ckp-signature state)
+		       (buffer-signature buffer))))
+	(checkpoint-buffer buffer)))))
+
+
+
+;;;; Random Hooks: cleanup, buffer-modified, change-save-freq.
+
+;;;
+;;; cleanup-checkpoint -- Internal
+;;; 
+;;; Cleans up checkpoint file for a given buffer if Auto Save Cleanup
+;;; Checkpoints is non-NIL.  This is called via "Write File Hook"
+;;; 
+(defun cleanup-checkpoint (buffer)
+  (let ((ckp-pathname (get-checkpoint-pathname buffer)))
+    (when (and (value auto-save-cleanup-checkpoints)
+	       ckp-pathname
+	       (probe-file ckp-pathname))
+      (delete-file ckp-pathname))))
+
+(add-hook write-file-hook 'cleanup-checkpoint)
+
+;;;
+;;; notice-buffer-modified -- Internal
+;;;
+;;; This function is called on "Buffer Modified Hook" to reset
+;;; the Auto Save state.  It makes the buffer look like it has just
+;;; been checkpointed.
+;;;
+(defun notice-buffer-modified (buffer flag)
+  ;; we care only when the flag has gone to false
+  (when (not flag)
+    (reset-auto-save-state buffer)))
+
+(add-hook buffer-modified-hook 'notice-buffer-modified)
+
+;;;
+;;; change-save-frequency -- Internal
+;;; 
+;;; This keeps us scheduled at the proper interval.  It is stuck on
+;;; the hook list for the hvar "Auto Save Checkpoint Frequency" and
+;;; is therefore called whenever this value is set.
+;;; 
+(defun change-save-frequency (name kind where new-value)
+  (declare (ignore name kind where))
+  (setq new-value (truncate new-value))
+  (remove-scheduled-event 'checkpoint-all-buffers)
+  (when (and new-value
+	     (plusp new-value))
+    (schedule-event new-value 'checkpoint-all-buffers t)))
+
+
+;;; "Save" mode is in "Default Modes", so turn it off in these modes.
+;;;
+
+(defun interactive-modes (buffer on)
+  (when on (setf (buffer-minor-mode buffer "Save") nil)))
+
+#+GBNIL (add-hook typescript-mode-hook 'interactive-modes)
+#+GBNIL (add-hook eval-mode-hook 'interactive-modes)
+
+
+
+
+;;;; Key Count Routine for Input Hook
+
+;;; 
+;;; auto-save-count-keys -- Internal
+;;;
+;;; This function sits on the Input Hook to eat cycles.  If the current
+;;; buffer is not in Save mode or if the current buffer is the echo area
+;;; buffer, it does nothing.  Otherwise, we check to see if we have exceeded
+;;; the key count threshold (and write a checkpoint if we have) and we
+;;; increment the key count for the buffer.
+;;;
+(defun auto-save-count-keys ()
+  #.*fast*
+  (let ((buffer (current-buffer)))
+    (unless (eq buffer *echo-area-buffer*)
+      (let ((state (value auto-save-state))
+	    (threshold (value auto-save-key-count-threshold)))
+	(when (and state threshold)
+	  (let ((signature (buffer-signature buffer)))
+	    (declare (fixnum signature))
+	    (when (not (eql signature
+			    (save-state-key-signature state)))
+	      ;; see if we exceeded threshold last time...
+	      (when (>= (save-state-key-count state)
+			(the fixnum threshold))
+		(checkpoint-buffer buffer))
+	      ;; update state
+	      (setf (save-state-key-signature state) signature)
+	      (incf (save-state-key-count state)))))))))
+
+(add-hook input-hook 'auto-save-count-keys)
+
+
+
+;;;; Save Mode Hemlock Variables
+
+;;; 
+;;; Hemlock variables/parameters for Auto-Save Mode
+;;;
+
+(defhvar "Auto Save Filename Pattern"
+  "This control-string is used with format to make the filename of the
+  checkpoint file.  Format is called with two arguments, the first
+  being the directory namestring and the second being the file
+  namestring of the default buffer pathname."
+  :value "~A~A.CKP")
+
+(defhvar "Auto Save Key Count Threshold"
+  "This value is the number of destructive/modifying keystrokes that will
+  automatically trigger an checkpoint.  This value may be NIL to turn this
+  feature off."
+  :value 256)
+
+(defhvar "Auto Save Cleanup Checkpoints"
+  "This variable controls whether or not \"Save\" mode will delete the
+  checkpoint file for a buffer after it is saved.  If this value is
+  non-NIL then cleanup will occur."
+  :value t)
+
+(defhvar "Auto Save Checkpoint Frequency"
+  "All modified buffers (in \"Save\" mode) will be checkpointed after this
+  amount of time (in seconds).  This value may be NIL (or non-positive)
+  to turn this feature off."
+  :value (* 2 60)
+  :hooks '(change-save-frequency))
+
+(defhvar "Auto Save State"
+  "Shadow magic.  This variable is seen when in buffers that are not
+  in \"Save\" mode.  Do not change this value or you will lose."
+  :value nil)
+
+
+
+;;;; "Save" mode
+
+(defcommand "Auto Save Mode" (p)
+  "If the argument is zero or negative, turn \"Save\" mode off.  If it
+  is positive turn \"Save\" mode on.  If there is no argument, toggle
+  \"Save\" mode in the current buffer.  When in \"Save\" mode, files
+  are automatically checkpointed every \"Auto Save Checkpoint Frequency\"
+  seconds or every \"Auto Save Key Count Threshold\" destructive
+  keystrokes.  If there is a pathname associated with the buffer, the
+  filename used for the checkpoint file is controlled by the hvar \"Auto
+  Save Filename Pattern\".  Otherwise, the hook \"Auto Save Pathname Hook\"
+  is used to generate a checkpoint pathname.  If the buffer's pathname
+  changes between checkpoints, the checkpoint file will be written under
+  the new name and the old checkpoint file will be deleted if it exists.
+  When a buffer is written out, the checkpoint will be deleted if the
+  hvar \"Auto Save Cleanup Checkpoints\" is non-NIL."
+  "Turn on, turn off, or toggle \"Save\" mode in the current buffer."
+  (setf (buffer-minor-mode (current-buffer) "Save")
+	(if p
+	    (plusp p)
+	    (not (buffer-minor-mode (current-buffer) "Save")))))
+
+(defun setup-auto-save-mode (buffer)
+  (let* ((signature (buffer-signature buffer))
+	 (state (make-auto-save-state
+		 :buffer buffer
+		 :key-signature (the fixnum signature)
+		 :last-ckp-signature (the fixnum signature))))
+    ;; shadow the global value with a variable which will
+    ;; contain our per buffer state information
+    (defhvar "Auto Save State"
+      "This is the \"Save\" mode state information for this buffer."
+      :buffer buffer
+      :value state)))
+
+(defun cleanup-auto-save-mode (buffer)
+  (delete-variable 'auto-save-state
+		   :buffer buffer))
+
+(defmode "Save"
+  :setup-function 'setup-auto-save-mode
+  :cleanup-function 'cleanup-auto-save-mode)
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/bit-display.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/bit-display.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/bit-display.lisp	(revision 13309)
@@ -0,0 +1,292 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Rob MacLachlan
+;;;    Modified by Bill Chiles to run under X on IBM RT's.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;; prepare-window-for-redisplay  --  Internal
+;;;
+;;;    Called by make-window to do whatever redisplay wants to set up
+;;; a new window.
+;;;
+(defun prepare-window-for-redisplay (window)
+  (setf (window-old-lines window) 0))
+
+
+
+
+;;;; Dumb window redisplay.
+
+;;; DUMB-WINDOW-REDISPLAY redraws an entire window using dumb-line-redisplay.
+;;; This assumes the cursor has been lifted if necessary.
+;;;
+(defun dumb-window-redisplay (window)
+  (let* ((hunk (window-hunk window))
+	 (first (window-first-line window)))
+    (hunk-reset hunk)
+    (do ((i 0 (1+ i))
+	 (dl (cdr first) (cdr dl)))
+	((eq dl *the-sentinel*)
+	 (setf (window-old-lines window) (1- i)))
+      (dumb-line-redisplay hunk (car dl)))
+    (setf (window-first-changed window) *the-sentinel*
+	  (window-last-changed window) first)
+    (when (window-modeline-buffer window)
+      (hunk-replace-modeline hunk)
+      (setf (dis-line-flags (window-modeline-dis-line window))
+	    unaltered-bits))
+    (setf (bitmap-hunk-start hunk) (cdr (window-first-line window)))))
+
+
+;;; DUMB-LINE-REDISPLAY is used when the line is known to be cleared already.
+;;;
+(defun dumb-line-redisplay (hunk dl)
+  (hunk-write-line hunk dl)
+  (setf (dis-line-flags dl) unaltered-bits (dis-line-delta dl) 0))
+
+
+
+
+;;;; Smart window redisplay.
+
+;;; We scan through the changed dis-lines, and condense the information
+;;; obtained into five categories: Unchanged lines moved down, unchanged
+;;; lines moved up, lines that need to be cleared, lines that are in the
+;;; same place (but changed), and new or moved-and-changed lines to write.
+;;; Each such instance of a thing that needs to be done is remembered be
+;;; throwing needed information on a stack specific to the thing to be
+;;; done.  We cannot do any of these things right away because each may
+;;; confict with the previous.
+;;; 
+;;; Each stack is represented by a simple-vector big enough to hold the
+;;; worst-case number of entries and a pointer to the next free entry.  The
+;;; pointers are local variables returned from COMPUTE-CHANGES and used by
+;;; SMART-WINDOW-REDISPLAY.  Note that the order specified in these tuples
+;;; is the order in which they were pushed.
+;;; 
+(defvar *display-down-move-stack* (make-array (* hunk-height-limit 2))
+  "This is the vector that we stash info about which lines moved down in
+  as (Start, End, Count) triples.")
+(defvar *display-up-move-stack* (make-array (* hunk-height-limit 2))
+  "This is the vector that we stash info about which lines moved up in
+  as (Start, End, Count) triples.")
+(defvar *display-erase-stack* (make-array hunk-height-limit)
+  "This is the vector that we stash info about which lines need to be erased
+  as (Start, Count) pairs.")
+(defvar *display-write-stack* (make-array hunk-height-limit)
+  "This is the vector that we stash dis-lines in that need to be written.")
+(defvar *display-rewrite-stack* (make-array hunk-height-limit)
+  "This is the vector that we stash dis-lines in that need to be written.
+  with clear-to-end.")
+
+;;; Accessor macros to push and pop on the stacks:
+;;;
+(eval-when (:compile-toplevel :execute)
+
+(defmacro spush (thing stack stack-pointer)
+  `(progn
+    (setf (svref ,stack ,stack-pointer) ,thing)
+    (incf ,stack-pointer)))
+
+(defmacro spop (stack stack-pointer)
+  `(svref ,stack (decf ,stack-pointer)))
+
+(defmacro snext (stack stack-pointer)
+  `(prog1 (svref ,stack ,stack-pointer) (incf ,stack-pointer)))
+
+); eval-when
+
+
+;;; SMART-WINDOW-REDISPLAY only re-writes lines which may have been changed,
+;;; and updates them with smart-line-redisplay if not very much has changed.
+;;; Lines which have moved are copied.  We must be careful not to redisplay
+;;; the window with the cursor down since it is not guaranteed to be out of
+;;; the way just because we are in redisplay; LIFT-CURSOR is called just before
+;;; the screen may be altered, and it takes care to know whether the cursor
+;;; is lifted already or not.  At the end, if the cursor had been down,
+;;; DROP-CURSOR puts it back; it doesn't matter if LIFT-CURSOR was never called
+;;; since it does nothing if the cursor is already down.
+;;; 
+(defun smart-window-redisplay (window)
+  ;; This isn't actually called --GB
+  (let* ((hunk (window-hunk window))
+	 (liftp (and (eq *cursor-hunk* hunk) *cursor-dropped*)))
+    (when (bitmap-hunk-trashed hunk)
+      (when liftp (lift-cursor))
+      (dumb-window-redisplay window)
+      (when liftp (drop-cursor))
+      (return-from smart-window-redisplay nil))
+    (let ((first-changed (window-first-changed window))
+	  (last-changed (window-last-changed window)))
+      ;; Is there anything to do?
+      (unless (eq first-changed *the-sentinel*)
+	(when liftp (lift-cursor))
+	(if (and (eq first-changed last-changed)
+		 (zerop (dis-line-delta (car first-changed))))
+	    ;; One line changed.
+	    (smart-line-redisplay hunk (car first-changed))
+	    ;; More than one line changed.
+	    (multiple-value-bind (up down erase write rewrite)
+				 (compute-changes first-changed last-changed)
+	      (do-down-moves hunk down)
+	      (do-up-moves hunk up)
+	      (do-erases hunk erase)
+	      (do-writes hunk write)
+	      (do-rewrites hunk rewrite)))
+	;; Set the bounds so we know we displayed...
+	(setf (window-first-changed window) *the-sentinel*
+	      (window-last-changed window) (window-first-line window))))
+    ;;
+    ;; Clear any extra lines at the end of the window.
+    (let ((pos (dis-line-position (car (window-last-line window)))))
+      (when (< pos (window-old-lines window))
+	(when liftp (lift-cursor))
+	(hunk-clear-lines hunk (1+ pos) (- (window-height window) pos 1)))
+      (setf (window-old-lines window) pos))
+    ;;
+    ;; Update the modeline if needed.
+    (when (window-modeline-buffer window)
+      (when (/= (dis-line-flags (window-modeline-dis-line window))
+		unaltered-bits)
+	(hunk-replace-modeline hunk)
+	(setf (dis-line-flags (window-modeline-dis-line window))
+	      unaltered-bits)))
+    ;;
+    (setf (bitmap-hunk-start hunk) (cdr (window-first-line window)))
+    (when liftp (drop-cursor))))
+
+;;; COMPUTE-CHANGES is used once in smart-window-redisplay, and it scans
+;;; through the changed dis-lines in a window, computes the changes needed
+;;; to bring the screen into corespondence, and throws the information
+;;; needed to do the change onto the apropriate stack.  The pointers into
+;;; the stacks (up, down, erase, write, and rewrite) are returned.
+;;; 
+;;; The algorithm is as follows:
+;;; 1] If the line is moved-and-changed or new then throw the line on
+;;; the write stack and increment the clear count.  Repeat until no more
+;;; such lines are found.
+;;; 2] If the line is moved then flush any pending clear, find how many
+;;; consecutive lines are moved the same amount, and put the numbers
+;;; on the correct move stack.
+;;; 3] If the line is changed and unmoved throw it on a write stack.
+;;; If a clear is pending throw it in the write stack and bump the clear
+;;; count, otherwise throw it on the rewrite stack.
+;;; 4] The line is unchanged, do nothing.
+;;;
+(defun compute-changes (first-changed last-changed)
+  (let* ((dl first-changed)
+	 (flags (dis-line-flags (car dl)))
+	 (up 0) (down 0) (erase 0) (write 0) (rewrite 0) ;return values.
+	 (clear-count 0)
+	 prev clear-start)
+    (declare (fixnum up down erase write rewrite clear-count))
+    (loop
+      (cond
+       ;; Line moved-and-changed or new.
+       ((> flags moved-bit)
+	(when (zerop clear-count)
+	  (setq clear-start (dis-line-position (car dl))))
+	(loop
+	  (setf (dis-line-delta (car dl)) 0)
+	  (spush (car dl) *display-write-stack* write)
+	  (incf clear-count)
+	  (setq prev dl  dl (cdr dl)  flags (dis-line-flags (car dl)))
+	  (when (<= flags moved-bit) (return nil))))
+       ;; Line moved, unchanged.
+       ((= flags moved-bit)
+	(unless (zerop clear-count)
+	  (spush clear-count *display-erase-stack* erase)
+	  (spush clear-start *display-erase-stack* erase)
+	  (setq clear-count 0))
+	(do ((delta (dis-line-delta (car dl)))
+	     (end (dis-line-position (car dl)))
+	     (count 1 (1+ count)))
+	    (())
+	  (setf (dis-line-delta (car dl)) 0
+		(dis-line-flags (car dl)) unaltered-bits)
+	  (setq prev dl  dl (cdr dl)  flags (dis-line-flags (car dl)))
+	  (when (or (/= (dis-line-delta (car dl)) delta) (/= flags moved-bit))
+	    ;; We push in different order because we pop in different order.
+	    (cond
+	     ((minusp delta)
+	      (spush (- end delta) *display-up-move-stack* up)
+	      (spush end *display-up-move-stack* up)
+	      (spush count *display-up-move-stack* up))
+	     (t
+	      (spush count *display-down-move-stack* down)
+	      (spush end *display-down-move-stack* down)
+	      (spush (- end delta) *display-down-move-stack* down)))
+	    (return nil))))
+       ;; Line changed, unmoved.
+       ((= flags changed-bit)
+	(cond ((zerop clear-count)
+	       (spush (car dl) *display-rewrite-stack* rewrite))
+	      (t
+	       (spush (car dl) *display-write-stack* write)
+	       (incf clear-count)))
+	(setq prev dl  dl (cdr dl)  flags (dis-line-flags (car dl))))
+       ;; Line unmoved, unchanged.
+       (t
+	(unless (zerop clear-count)
+	  (spush clear-count *display-erase-stack* erase)
+	  (spush clear-start *display-erase-stack* erase)
+	  (setq clear-count 0))
+	(setq prev dl  dl (cdr dl)  flags (dis-line-flags (car dl)))))
+     
+     (when (eq prev last-changed)
+       ;; If done flush any pending clear.
+       (unless (zerop clear-count)
+	 (spush clear-count *display-erase-stack* erase)
+	 (spush clear-start *display-erase-stack* erase))
+       (return (values up down erase write rewrite))))))
+
+(defun do-up-moves (hunk up)
+  (do ((i 0))
+      ((= i up))
+    (hunk-copy-lines hunk (snext *display-up-move-stack* i)
+		     (snext *display-up-move-stack* i)
+		     (snext *display-up-move-stack* i))))
+
+(defun do-down-moves (hunk down)
+  (do ()
+      ((zerop down))
+    (hunk-copy-lines hunk (spop *display-down-move-stack* down)
+		     (spop *display-down-move-stack* down)
+		     (spop *display-down-move-stack* down))))
+
+(defun do-erases (hunk erase)
+  (do ()
+      ((zerop erase))
+    (hunk-clear-lines hunk (spop *display-erase-stack* erase)
+		      (spop *display-erase-stack* erase))))
+
+(defun do-writes (hunk write)
+  (do ((i 0))
+      ((= i write))
+    (dumb-line-redisplay hunk (snext *display-write-stack* i))))
+
+(defun do-rewrites (hunk rewrite)
+  (do ()
+      ((zerop rewrite))
+    (smart-line-redisplay hunk (spop *display-rewrite-stack* rewrite))))
+
+
+;;; SMART-LINE-REDISPLAY is called when the screen is mostly the same,
+;;; clear to eol after we write it to avoid annoying flicker.
+;;;
+(defun smart-line-redisplay (hunk dl)
+  (hunk-replace-line hunk dl)
+  (setf (dis-line-flags dl) unaltered-bits (dis-line-delta dl) 0))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/bit-screen.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/bit-screen.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/bit-screen.lisp	(revision 13309)
@@ -0,0 +1,1873 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Screen allocation functions.
+;;;
+;;; This is the screen management and event handlers for Hemlock under X.
+;;;
+;;; Written by Bill Chiles, Rob MacLachlan, and Blaine Burks.
+;;;
+
+(in-package :hemlock-internals)
+
+(declaim (special *echo-area-window*))
+
+;;; We have an internal notion of window groups on bitmap devices.  Every
+;;; Hemlock window has a hunk slot which holds a structure with information
+;;; about physical real-estate on some device.  Bitmap-hunks have an X window
+;;; and a window-group.  The X window is a child of the window-group's window.
+;;; The echo area, pop-up display window, and the initial window are all in
+;;; their own group.
+;;;
+;;; MAKE-WINDOW splits the current window which is some child window in a group.
+;;; If the user supplied an X window, it becomes the parent window of some new
+;;; group, and we make a child for the Hemlock window.  If the user supplies
+;;; ask-user, we prompt for a group/parent window.  We link the hunks for
+;;; NEXT-WINDOW and PREVIOUS-WINDOW only within a group, so the group maintains
+;;; a stack of windows that always fill the entire group window.
+;;;
+
+;;; This is the object set for Hemlock windows.  All types of incoming
+;;; X events on standard editing windows have the same handlers via this set.
+;;; We also include the group/parent windows in here, but they only handle
+;;; :configure-notify events.
+;;;
+(defvar *hemlock-windows*
+  #+clx
+  (hemlock-ext:make-object-set "Hemlock Windows" #'hemlock-ext:default-clx-event-handler))
+
+
+
+
+;;;; Some window making parameters.
+
+;;; These could be parameters, but they have to be set after the display is
+;;; opened.  These are set in INIT-BITMAP-SCREEN-MANAGER.
+
+(defvar *default-background-pixel* nil
+  "Default background color.  It defaults to white.")
+  
+(defvar *default-foreground-pixel* nil
+  "Default foreground color.  It defaults to black.")
+
+(defvar *foreground-background-xor* nil
+  "The LOGXOR of *default-background-pixel* and *default-foreground-pixel*.")
+
+(defvar *default-border-pixmap* nil
+  "This is the default color of X window borders.  It defaults to a
+  grey pattern.")
+
+(defvar *highlight-border-pixmap* nil
+  "This is the color of the border of the current window when the mouse
+  cursor is over any Hemlock window.")
+
+
+
+
+;;;; Exposed region handling.
+
+;;; :exposure events are sent because we selected them.  :graphics-exposure
+;;; events are generated because of a slot in our graphics contexts.  These are
+;;; generated from using XLIB:COPY-AREA when the source could not be generated.
+;;; Also, :no-exposure events are sent when a :graphics-exposure event could
+;;; have been sent but wasn't.
+;;;
+#|
+;;; This is an old handler that doesn't do anything clever about multiple
+;;; exposures.
+(defun hunk-exposed-region (hunk &key y height &allow-other-keys)
+  (if (bitmap-hunk-lock hunk)
+      (setf (bitmap-hunk-trashed hunk) t)
+      (let ((liftp (and (eq *cursor-hunk* hunk) *cursor-dropped*)))
+	(when liftp (lift-cursor))
+	;; (hunk-draw-top-border hunk)
+	(let* ((font-family (bitmap-hunk-font-family hunk))
+	       (font-height (font-family-height font-family))
+	       (co (font-family-cursor-y-offset font-family))
+	       (start (truncate (- y hunk-top-border) font-height))
+	       (end (ceiling (- (+ y height) hunk-top-border) font-height))
+	       (start-bit (+ (* start font-height) co hunk-top-border))
+	       (nheight (- (* (- end start) font-height) co))
+	       (end-line (bitmap-hunk-end hunk)))
+	  (declare (fixnum font-height co start end start-bit nheight))
+	  (xlib:clear-area (bitmap-hunk-xwindow hunk) :x 0 :y start-bit
+			   :width (bitmap-hunk-width hunk) :height nheight)
+	  (do ((dl (bitmap-hunk-start hunk) (cdr dl))
+	       (i 0 (1+ i)))
+	      ((or (eq dl end-line) (= i start))
+	       (do ((i i (1+ i))
+		    (dl dl (cdr dl)))
+		   ((or (eq dl end-line) (= i end)))
+		 (declare (fixnum i))
+		 (hunk-write-line hunk (car dl) i)))
+	    (declare (fixnum i)))
+	  (when (and (bitmap-hunk-modeline-pos hunk)
+		     (>= (the fixnum (+ nheight start-bit))
+			 (the fixnum (bitmap-hunk-modeline-pos hunk))))
+	    (hunk-replace-modeline hunk)))
+	(when liftp (drop-cursor)))))
+|#
+
+;;; HUNK-EXPOSED-REGION redisplays the appropriate rectangle from the hunk
+;;; dis-lines.  Don't do anything if the hunk is trashed since redisplay is
+;;; probably about to fix everything; specifically, this keeps new windows
+;;; from getting drawn twice (once for the exposure and once for being trashed).
+;;;
+;;; Exposure and graphics-exposure events pass in a different number of
+;;; arguments, with some the same but in a different order, so we just bind
+;;; and ignore foo, bar, baz, and quux.
+;;;
+#+clx
+(defun hunk-exposed-region (hunk event-key event-window x y width height
+				 foo bar &optional baz quux)
+  (declare (ignore event-key event-window x width foo bar baz quux))
+  (unless (bitmap-hunk-trashed hunk)
+    (let ((liftp (and (eq *cursor-hunk* hunk) *cursor-dropped*))
+	  (display (bitmap-device-display (device-hunk-device hunk))))
+      (when liftp (lift-cursor))
+      (multiple-value-bind (y-peek height-peek)
+			   (exposed-region-peek-event display
+						      (bitmap-hunk-xwindow hunk))
+	(if y-peek
+	    (let ((n (coelesce-exposed-regions hunk display
+					       y height y-peek height-peek)))
+	      (write-n-exposed-regions hunk n))
+	    (write-one-exposed-region hunk y height)))
+      (xlib:display-force-output display)
+      (when liftp (drop-cursor)))))
+;;;
+#+clx (hemlock-ext:serve-exposure *hemlock-windows* #'hunk-exposed-region)
+#+clx (hemlock-ext:serve-graphics-exposure *hemlock-windows* #'hunk-exposed-region)
+
+
+;;; HUNK-NO-EXPOSURE handles this bullshit event that gets sent without its
+;;; being requested.
+;;;
+(defun hunk-no-exposure (hunk event-key event-window major minor send-event-p)
+  (declare (ignore hunk event-key event-window major minor send-event-p))
+  t)
+;;;
+#+clx (hemlock-ext:serve-no-exposure *hemlock-windows* #'hunk-no-exposure)
+
+
+;;; EXPOSED-REGION-PEEK-EVENT returns the position and height of an :exposure
+;;; or :graphics-exposure event on win if one exists.  If there are none, then
+;;; nil and nil are returned.
+;;;
+#+clx
+(defun exposed-region-peek-event (display win)
+  (xlib:display-finish-output display)
+  (let ((result-y nil)
+	(result-height nil))
+    (xlib:process-event
+     display :timeout 0
+     :handler #'(lambda (&key event-key event-window window y height
+			      &allow-other-keys)
+		  (cond ((and (or (eq event-key :exposure)
+				  (eq event-key :graphics-exposure))
+			      (or (eq event-window win) (eq window win)))
+			 (setf result-y y)
+			 (setf result-height height)
+			 t)
+			(t nil))))
+    (values result-y result-height)))
+
+;;; COELESCE-EXPOSED-REGIONS insert sorts exposed region events from the X
+;;; input queue into *coelesce-buffer*.  Then the regions are merged into the
+;;; same number or fewer regions that are vertically distinct
+;;; (non-overlapping).  When this function is called, one event has already
+;;; been popped from the queue, the first event that caused HUNK-EXPOSED-REGION
+;;; to be called.  That information is passed in as y1 and height1.  There is
+;;; a second event that also has already been popped from the queue, the
+;;; event resulting from peeking for multiple "exposure" events.  That info
+;;; is passed in as y2 and height2.
+;;;
+(defun coelesce-exposed-regions (hunk display y1 height1 y2 height2)
+  (let ((len 0))
+    (declare (fixnum len))
+    ;;
+    ;; Insert sort the exposeevents as we pick them off the event queue.
+    (let* ((font-family (bitmap-hunk-font-family hunk))
+	   (font-height (font-family-height font-family))
+	   (co (font-family-cursor-y-offset font-family))
+	   (xwindow (bitmap-hunk-xwindow hunk)))
+      ;;
+      ;; Insert the region the exposedregion handler was called on.
+      (multiple-value-bind (start-line start-bit end-line expanded-height)
+			   (exposed-region-bounds y1 height1 co font-height)
+	(setf len
+	      (coelesce-buffer-insert start-bit start-line
+				      expanded-height end-line len)))
+      ;;
+      ;; Peek for exposedregion events on xwindow, inserting them into
+      ;; the buffer.
+      (let ((y y2)
+	    (height height2))
+	(loop
+	  (multiple-value-bind (start-line start-bit end-line expanded-height)
+			       (exposed-region-bounds y height co font-height)
+	    (setf len
+		  (coelesce-buffer-insert start-bit start-line
+					  expanded-height end-line len)))
+	  (multiple-value-setq (y height)
+	    (exposed-region-peek-event display xwindow))
+	  (unless y (return)))))
+    (coelesce-exposed-regions-merge len)))
+
+;;; *coelesce-buffer* is a vector of records used to sort exposure events on a
+;;; single hunk, so we can merge them into fewer, larger regions of exposure.
+;;; COELESCE-BUFFER-INSERT places elements in this buffer, and each element
+;;; is referenced with COELESCE-BUFFER-ELT.  Each element of the coelescing
+;;; buffer has the following accessors defined:
+;;;    COELESCE-BUFFER-ELT-START	in pixels.
+;;;    COELESCE-BUFFER-ELT-START-LINE	in dis-lines.
+;;;    COELESCE-BUFFER-ELT-HEIGHT	in pixels.
+;;;    COELESCE-BUFFER-ELT-END-LINE	in dis-lines.
+;;; These are used by COELESCE-BUFFER-INSERT, COELESCE-EXPOSED-REGIONS-MERGE,
+;;; and WRITE-N-EXPOSED-REGIONS.
+
+(defvar *coelesce-buffer-fill-ptr* 25)
+(defvar *coelesce-buffer* (make-array *coelesce-buffer-fill-ptr*))
+(dotimes (i *coelesce-buffer-fill-ptr*)
+  (setf (svref *coelesce-buffer* i) (make-array 4)))
+
+(defmacro coelesce-buffer-elt-start (elt)
+  `(svref ,elt 0))
+(defmacro coelesce-buffer-elt-start-line (elt)
+  `(svref ,elt 1))
+(defmacro coelesce-buffer-elt-height (elt)
+  `(svref ,elt 2))
+(defmacro coelesce-buffer-elt-end-line (elt)
+  `(svref ,elt 3))
+(defmacro coelesce-buffer-elt (i)
+  `(svref *coelesce-buffer* ,i))
+
+;;; COELESCE-BUFFER-INSERT inserts an exposed region record into
+;;; *coelesce-buffer* such that start is less than all successive
+;;; elements.  Returns the new length of the buffer.
+;;; 
+(defun coelesce-buffer-insert (start start-line height end-line len)
+  (declare (fixnum start start-line height end-line len))
+  ;;
+  ;; Add element if len is to fill pointer.  If fill pointer is to buffer
+  ;; length, then grow buffer.
+  (when (= len (the fixnum *coelesce-buffer-fill-ptr*))
+    (when (= (the fixnum *coelesce-buffer-fill-ptr*)
+	     (the fixnum (length (the simple-vector *coelesce-buffer*))))
+      (let ((new (make-array (ash (length (the simple-vector *coelesce-buffer*))
+				  1))))
+	(replace (the simple-vector new) (the simple-vector *coelesce-buffer*)
+		 :end1 *coelesce-buffer-fill-ptr*
+		 :end2 *coelesce-buffer-fill-ptr*)
+	(setf *coelesce-buffer* new)))
+    (setf (coelesce-buffer-elt len) (make-array 4))
+    (incf *coelesce-buffer-fill-ptr*))
+  ;;
+  ;; Find point to insert record: start, start-line, height, and end-line.
+  (do ((i 0 (1+ i)))
+      ((= i len)
+       ;; Start is greater than all previous starts.  Add it to the end.
+       (let ((region (coelesce-buffer-elt len)))
+	 (setf (coelesce-buffer-elt-start region) start)
+	 (setf (coelesce-buffer-elt-start-line region) start-line)
+	 (setf (coelesce-buffer-elt-height region) height)
+	 (setf (coelesce-buffer-elt-end-line region) end-line)))
+    (declare (fixnum i))
+    (when (< start (the fixnum
+			(coelesce-buffer-elt-start (coelesce-buffer-elt i))))
+      ;;
+      ;; Insert new element at i, using storage allocated at element len.
+      (let ((last (coelesce-buffer-elt len)))
+	(setf (coelesce-buffer-elt-start last) start)
+	(setf (coelesce-buffer-elt-start-line last) start-line)
+	(setf (coelesce-buffer-elt-height last) height)
+	(setf (coelesce-buffer-elt-end-line last) end-line)
+	;;
+	;; Shift elements after i (inclusively) to the right.
+	(do ((j (1- len) (1- j))
+	     (k len j)
+	     (terminus (1- i)))
+	    ((= j terminus))
+	  (declare (fixnum j k terminus))
+	  (setf (coelesce-buffer-elt k) (coelesce-buffer-elt j)))
+	;;
+	;; Stash element to insert at i.
+	(setf (coelesce-buffer-elt i) last))
+      (return)))
+  (1+ len))
+
+
+;;; COELESCE-EXPOSED-REGIONS-MERGE merges/coelesces the regions in
+;;; *coelesce-buffer*.  It takes the number of elements and returns the new
+;;; number of elements.  The regions are examined one at a time relative to
+;;; the current one.  The current region remains so, with next advancing
+;;; through the buffer, until a next region is found that does not overlap
+;;; and is not adjacent.  When this happens, the current values are stored
+;;; in the current region, and the buffer's element after the current element
+;;; becomes current.  The next element that was found not to be in contact
+;;; the old current element is stored in the new current element by copying
+;;; its values there.  The buffer's elements always stay in place, and their
+;;; storage is re-used.  After this process which makes the next region be
+;;; the current region, the next pointer is incremented.
+;;;
+(defun coelesce-exposed-regions-merge (len)
+    (let* ((current 0)
+	   (next 1)
+	   (current-region (coelesce-buffer-elt 0))
+	   (current-height (coelesce-buffer-elt-height current-region))
+	   (current-end-line (coelesce-buffer-elt-end-line current-region))
+	   (current-end-bit (+ (the fixnum
+				    (coelesce-buffer-elt-start current-region))
+			       current-height)))
+      (declare (fixnum current next current-height
+		       current-end-line current-end-bit))
+      (loop
+	(let* ((next-region (coelesce-buffer-elt next))
+	       (next-start (coelesce-buffer-elt-start next-region))
+	       (next-height (coelesce-buffer-elt-height next-region))
+	       (next-end-bit (+ next-start next-height)))
+	  (declare (fixnum next-start next-height next-end-bit))
+	  (cond ((<= next-start current-end-bit)
+		 (let ((extra-height (- next-end-bit current-end-bit)))
+		   (declare (fixnum extra-height))
+		   ;; Maybe the next region is contained in the current.
+		   (when (plusp extra-height)
+		     (incf current-height extra-height)
+		     (setf current-end-bit next-end-bit)
+		     (setf current-end-line
+			   (coelesce-buffer-elt-end-line next-region)))))
+		(t
+		 ;;
+		 ;; Update current record since next does not overlap
+		 ;; with current.
+		 (setf (coelesce-buffer-elt-height current-region)
+		       current-height)
+		 (setf (coelesce-buffer-elt-end-line current-region)
+		       current-end-line)
+		 ;;
+		 ;; Move to new distinct region, copying data from next region.
+		 (incf current)
+		 (setf current-region (coelesce-buffer-elt current))
+		 (setf (coelesce-buffer-elt-start current-region) next-start)
+		 (setf (coelesce-buffer-elt-start-line current-region)
+		       (coelesce-buffer-elt-start-line next-region))
+		 (setf current-height next-height)
+		 (setf current-end-bit next-end-bit)
+		 (setf current-end-line
+		       (coelesce-buffer-elt-end-line next-region)))))
+	(incf next)
+	(when (= next len)
+	  (setf (coelesce-buffer-elt-height current-region) current-height)
+	  (setf (coelesce-buffer-elt-end-line current-region) current-end-line)
+	  (return)))
+      (1+ current)))
+
+;;; EXPOSED-REGION-BOUNDS returns as multiple values the first line affected,
+;;; the first possible bit affected (accounting for the cursor), the end line
+;;; affected, and the height of the region.
+;;; 
+(defun exposed-region-bounds (y height cursor-offset font-height)
+  (declare (fixnum y height cursor-offset font-height))
+  (let* ((start (truncate (the fixnum (- y hunk-top-border))
+			  font-height))
+	 (end (ceiling (the fixnum (- (the fixnum (+ y height))
+				      hunk-top-border))
+		       font-height)))
+    (values
+     start
+     (+ (the fixnum (* start font-height)) cursor-offset hunk-top-border)
+     end
+     (- (the fixnum (* (the fixnum (- end start)) font-height))
+	cursor-offset))))
+
+#+clx
+(defun write-n-exposed-regions (hunk n)
+  (declare (fixnum n))
+  (let* (;; Loop constants.
+	 (end-dl (bitmap-hunk-end hunk))
+	 (xwindow (bitmap-hunk-xwindow hunk))
+	 (hunk-width (bitmap-hunk-width hunk))
+	 ;; Loop variables.
+	 (dl (bitmap-hunk-start hunk))
+	 (i 0)
+	 (region (coelesce-buffer-elt 0))
+	 (start-line (coelesce-buffer-elt-start-line region))
+	 (start (coelesce-buffer-elt-start region))
+	 (height (coelesce-buffer-elt-height region))
+	 (end-line (coelesce-buffer-elt-end-line region))
+	 (region-idx 0))
+    (declare (fixnum i start start-line height end-line region-idx))
+    (loop
+      (xlib:clear-area xwindow :x 0 :y start :width hunk-width :height height)
+      ;; Find this regions first line.
+      (loop
+	(when (or (eq dl end-dl) (= i start-line))
+	  (return))
+	(incf i)
+	(setf dl (cdr dl)))
+      ;; Write this region's lines.
+      (loop
+	(when (or (eq dl end-dl) (= i end-line))
+	  (return))
+	(hunk-write-line hunk (car dl) i)
+	(incf i)
+	(setf dl (cdr dl)))
+      ;; Get next region unless we're done.
+      (when (= (incf region-idx) n) (return))
+      (setf region (coelesce-buffer-elt region-idx))
+      (setf start (coelesce-buffer-elt-start region))
+      (setf start-line (coelesce-buffer-elt-start-line region))
+      (setf height (coelesce-buffer-elt-height region))
+      (setf end-line (coelesce-buffer-elt-end-line region)))
+    ;;
+    ;; Check for modeline exposure.
+    (setf region (coelesce-buffer-elt (1- n)))
+    (setf start (coelesce-buffer-elt-start region))
+    (setf height (coelesce-buffer-elt-height region))
+    (when (and (bitmap-hunk-modeline-pos hunk)
+	       (> (+ start height)
+		  (- (bitmap-hunk-modeline-pos hunk)
+		     (bitmap-hunk-bottom-border hunk))))
+      (hunk-replace-modeline hunk)
+      (hunk-draw-bottom-border hunk))))
+
+#+clx
+(defun write-one-exposed-region (hunk y height)
+  (let* ((font-family (bitmap-hunk-font-family hunk))
+	 (font-height (font-family-height font-family))
+	 (co (font-family-cursor-y-offset font-family))
+	 (start-line (truncate (- y hunk-top-border) font-height))
+	 (end-line (ceiling (- (+ y height) hunk-top-border) font-height))
+	 (start-bit (+ (* start-line font-height) co hunk-top-border))
+	 (nheight (- (* (- end-line start-line) font-height) co))
+	 (hunk-end-line (bitmap-hunk-end hunk)))
+    (declare (fixnum font-height co start-line end-line start-bit nheight))
+    (xlib:clear-area (bitmap-hunk-xwindow hunk) :x 0 :y start-bit
+		     :width (bitmap-hunk-width hunk) :height nheight)
+    (do ((dl (bitmap-hunk-start hunk) (cdr dl))
+	 (i 0 (1+ i)))
+	((or (eq dl hunk-end-line) (= i start-line))
+	 (do ((i i (1+ i))
+	      (dl dl (cdr dl)))
+	     ((or (eq dl hunk-end-line) (= i end-line)))
+	   (declare (fixnum i))
+	   (hunk-write-line hunk (car dl) i)))
+      (declare (fixnum i)))
+    (when (and (bitmap-hunk-modeline-pos hunk)
+	       (> (+ start-bit nheight)
+		  (- (bitmap-hunk-modeline-pos hunk)
+		     (bitmap-hunk-bottom-border hunk))))
+      (hunk-replace-modeline hunk)
+      (hunk-draw-bottom-border hunk))))
+
+
+
+
+;;;; Resized window handling.
+
+;;; :configure-notify events are sent because we select :structure-notify.
+;;; This buys us a lot of events we have to write dummy handlers to ignore.
+;;;
+
+;;; HUNK-RECONFIGURED -- Internal.
+;;;
+;;; This must note that the hunk changed to prevent certain redisplay problems
+;;; with recentering the window that caused bogus lines to be drawn after the
+;;; actual visible text in the window.  We must also indicate the hunk is
+;;; trashed to eliminate exposure event handling that comes after resizing.
+;;; This also causes a full redisplay on the window which is the easiest and
+;;; generally best looking thing.
+;;;
+(defun hunk-reconfigured (object event-key event-window window x y width
+				 height border-width above-sibling
+				 override-redirect-p send-event-p)
+  (declare (ignore event-key event-window window x y border-width
+		   above-sibling override-redirect-p send-event-p))
+  (typecase object
+    (bitmap-hunk
+     (when (or (/= width (bitmap-hunk-width object))
+	       (/= height (bitmap-hunk-height object)))
+       (hunk-changed object width height nil)
+       ;; Under X11, don't redisplay since an exposure event is coming next.
+       (setf (bitmap-hunk-trashed object) t)))
+    (window-group
+     (let ((old-width (window-group-width object))
+	   (old-height (window-group-height object)))
+       (when (or (/= width old-width) (/= height old-height))
+	 (window-group-changed object width height))))))
+;;;
+#+clx (hemlock-ext:serve-configure-notify *hemlock-windows* #'hunk-reconfigured)
+
+
+;;; HUNK-IGNORE-EVENT ignores the following unrequested events.  They all take
+;;; at least five arguments, but then there are up to four more optional.
+;;;
+(defun hunk-ignore-event (hunk event-key event-window window one
+			       &optional two three four five)
+  (declare (ignore hunk event-key event-window window one two three four five))
+  t)
+;;;
+#+clx (hemlock-ext:serve-destroy-notify *hemlock-windows* #'hunk-ignore-event)
+#+clx (hemlock-ext:serve-unmap-notify *hemlock-windows* #'hunk-ignore-event)
+#+clx (hemlock-ext:serve-map-notify *hemlock-windows* #'hunk-ignore-event)
+#+clx (hemlock-ext:serve-reparent-notify *hemlock-windows* #'hunk-ignore-event)
+#+clx (hemlock-ext:serve-gravity-notify *hemlock-windows* #'hunk-ignore-event)
+#+clx (hemlock-ext:serve-circulate-notify *hemlock-windows* #'hunk-ignore-event)
+#+clx (hemlock-ext:serve-client-message *hemlock-windows* #'hunk-ignore-event)
+
+
+
+;;;; Interface to X input events.
+
+;;; HUNK-KEY-INPUT and HUNK-MOUSE-INPUT.
+;;; Each key and mouse event is turned into a character via
+;;; HEMLOCK-EXT:TRANSLATE-CHARACTER or HEMLOCK-EXT:TRANSLATE-MOUSE-CHARACTER, either of which
+;;; may return nil.  Nil is returned for input that is considered uninteresting
+;;; input; for example, shift and control.
+;;;
+
+(defun hunk-key-input (hunk event-key event-window root child same-screen-p x y
+		       root-x root-y modifiers time key-code send-event-p)
+  (declare (ignore event-key event-window root child same-screen-p root-x
+		   root-y time send-event-p))
+  (hunk-process-input hunk
+		      (hemlock-ext:translate-key-event
+		       (bitmap-device-display (device-hunk-device hunk))
+		       key-code modifiers)
+		      x y))
+;;;
+#+clx (hemlock-ext:serve-key-press *hemlock-windows* #'hunk-key-input)
+
+(defun hunk-mouse-input (hunk event-key event-window root child same-screen-p x y
+			 root-x root-y modifiers time key-code send-event-p)
+  (declare (ignore event-window root child same-screen-p root-x root-y
+		   time send-event-p))
+  (hunk-process-input hunk
+		      (hemlock-ext:translate-mouse-key-event key-code modifiers
+						     event-key)
+		      x y))
+;;;
+#+clx (hemlock-ext:serve-button-press *hemlock-windows* #'hunk-mouse-input)
+#+clx (hemlock-ext:serve-button-release *hemlock-windows* #'hunk-mouse-input)
+
+(defun hunk-process-input (hunk char x y)
+  (when char
+    (let* ((font-family (bitmap-hunk-font-family hunk))
+	   (font-width (font-family-width font-family))
+	   (font-height (font-family-height font-family))
+	   (ml-pos (bitmap-hunk-modeline-pos hunk))
+	   (height (bitmap-hunk-height hunk))
+	   (width (bitmap-hunk-width hunk))
+	   (handler (bitmap-hunk-input-handler hunk))
+	   (char-width (bitmap-hunk-char-width hunk)))
+      (cond ((not (and (< -1 x width) (< -1 y height)))
+	     (funcall handler hunk char nil nil))
+	    ((and ml-pos (> y (- ml-pos (bitmap-hunk-bottom-border hunk))))
+	     (funcall handler hunk char
+		      ;; (/ width x) doesn't handle ends of thumb bar
+		      ;; and eob right, so do a bunch of truncating.
+		      (min (truncate x (truncate width char-width))
+			   (1- char-width))
+		      nil))
+	    (t
+	     (let* ((cx (truncate (- x hunk-left-border) font-width))
+		    (temp (truncate (- y hunk-top-border) font-height))
+		    (char-height (bitmap-hunk-char-height hunk))
+		    ;; Extra bits below bottom line and above modeline and
+		    ;; thumb bar are considered part of the bottom line since
+		    ;; we have already picked off the y=nil case.
+		    (cy (if (< temp char-height) temp (1- char-height))))
+	       (if (and (< -1 cx char-width)
+			(< -1 cy))
+		   (funcall handler hunk char cx cy)
+		   (funcall handler hunk char nil nil))))))))
+
+
+
+
+;;;; Handling boundary crossing events.
+
+;;; Entering and leaving a window are handled basically the same except that it
+;;; is possible to get an entering event under X without getting an exiting
+;;; event; specifically, when the mouse is in a Hemlock window that is over
+;;; another window, and someone buries the top window, Hemlock only gets an
+;;; entering event on the lower window (no exiting event for the buried
+;;; window).
+;;;
+;;; :enter-notify and :leave-notify events are sent because we select
+;;; :enter-window and :leave-window events.
+;;;
+
+#+clx
+(defun hunk-mouse-entered (hunk event-key event-window root child same-screen-p
+			   x y root-x root-y state time mode kind send-event-p)
+  (declare (ignore event-key event-window child root same-screen-p
+		   x y root-x root-y state time mode kind send-event-p))
+  (when (and *cursor-dropped* (not *hemlock-listener*))
+    (cursor-invert-center))
+  (setf *hemlock-listener* t)
+  (let ((current-hunk (window-hunk (current-window))))
+    (unless (and *current-highlighted-border*
+		 (eq *current-highlighted-border* current-hunk))
+      (setf (xlib:window-border (window-group-xparent
+				 (bitmap-hunk-window-group current-hunk)))
+	    *highlight-border-pixmap*)
+      (xlib:display-force-output
+       (bitmap-device-display (device-hunk-device current-hunk)))
+      (setf *current-highlighted-border* current-hunk)))
+  (let ((window (bitmap-hunk-window hunk)))
+    (when window (invoke-hook hemlock::enter-window-hook window))))
+;;;
+#+clx (hemlock-ext:serve-enter-notify *hemlock-windows* #'hunk-mouse-entered)
+
+#+clx
+(defun hunk-mouse-left (hunk event-key event-window root child same-screen-p
+			x y root-x root-y state time mode kind send-event-p)
+  (declare (ignore event-key event-window child root same-screen-p
+		   x y root-x root-y state time mode kind send-event-p))
+  (setf *hemlock-listener* nil)
+  (when *cursor-dropped* (cursor-invert-center))
+  (when *current-highlighted-border*
+    (setf (xlib:window-border (window-group-xparent
+			       (bitmap-hunk-window-group
+				*current-highlighted-border*)))
+	  *default-border-pixmap*)
+    (xlib:display-force-output
+     (bitmap-device-display (device-hunk-device *current-highlighted-border*)))
+    (setf *current-highlighted-border* nil))
+  (let ((window (bitmap-hunk-window hunk)))
+    (when window (invoke-hook hemlock::exit-window-hook window))))
+;;;
+#+clx (hemlock-ext:serve-leave-notify *hemlock-windows* #'hunk-mouse-left)
+
+
+
+
+;;;; Making a Window.
+
+(defparameter minimum-window-height 100
+  "If the window created by splitting a window would be shorter than this,
+  then we create an overlapped window the same size instead.")
+
+;;; The width must be that of a tab for the screen image builder, and the
+;;; height must be one line (two with a modeline).
+;;; 
+(defconstant minimum-window-lines 2
+  "Windows must have at least this many lines.")
+(defconstant minimum-window-columns 10
+  "Windows must be at least this many characters wide.")
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+(defconstant xwindow-border-width 2 "X border around X windows")
+(defconstant xwindow-border-width*2 (* xwindow-border-width 2))
+); eval-when
+
+;;; We must name windows (set the "name" property) to get around a bug in
+;;; awm and twm.  They will not handle menu clicks without a window having
+;;; a name.  We set the name to this silly thing.
+;;;
+(defvar *hemlock-window-count* 0)
+;;;
+(defun new-hemlock-window-name ()
+  (let ((*print-base* 10))
+    (format nil "Hemlock ~S" (incf *hemlock-window-count*))))
+
+(declaim (inline surplus-window-height surplus-window-height-w/-modeline))
+;;;
+(defun surplus-window-height (thumb-bar-p)
+  (+ hunk-top-border (if thumb-bar-p
+			 hunk-thumb-bar-bottom-border
+			 hunk-bottom-border)))
+;;;
+(defun surplus-window-height-w/-modeline (thumb-bar-p)
+  (+ (surplus-window-height thumb-bar-p)
+     hunk-modeline-top
+     hunk-modeline-bottom))
+
+
+;;; DEFAULT-CREATE-WINDOW-HOOK -- Internal.
+;;;
+;;; This is the default value for *create-window-hook*.  It makes an X window
+;;; for a new group/parent on the given display possibly prompting the user.
+;;;
+#+clx
+(defun default-create-window-hook (display x y width height name font-family
+				   &optional modelinep thumb-bar-p)
+  (maybe-prompt-user-for-window
+   (xlib:screen-root (xlib:display-default-screen display))
+   x y width height font-family modelinep thumb-bar-p name))
+
+#-clx
+(defun default-create-window-hook (display x y width height name font-family
+					   &optional modelinep thumb-bar-p)
+  (declare (ignore display x y width height name font-family
+					    modelinep thumb-bar-p)))
+
+;;; MAYBE-PROMPT-USER-FOR-WINDOW -- Internal.
+;;;
+;;; This makes an X window and sets its standard properties according to
+;;; supplied values.  When some of these are nil, the window manager should
+;;; prompt the user for those missing values when the window gets mapped.  We
+;;; use this when making new group/parent windows.  Returns the window without
+;;; mapping it.
+;;;
+(defun maybe-prompt-user-for-window (root x y width height font-family
+				     modelinep thumb-bar-p icon-name)
+  (let ((font-height (font-family-height font-family))
+	(font-width (font-family-width font-family))
+	(extra-y (surplus-window-height thumb-bar-p))
+	(extra-y-w/-modeline (surplus-window-height-w/-modeline thumb-bar-p)))
+    (create-window-with-properties
+     root x y
+     (if width (+ (* width font-width) hunk-left-border))
+     (if height
+	 (if modelinep
+	     (+ (* (1+ height) font-height) extra-y-w/-modeline)
+	     (+ (* height font-height) extra-y)))
+     font-width font-height icon-name
+     (+ (* minimum-window-columns font-width) hunk-left-border)
+     (if modelinep
+	 (+ (* (1+ minimum-window-lines) font-height) extra-y-w/-modeline)
+	 (+ (* minimum-window-lines font-height) extra-y))
+     t)))
+
+(defvar *create-window-hook* #'default-create-window-hook
+  "Hemlock calls this function when it makes a new X window for a new group.
+   It passes as arguments the X display, x (from MAKE-WINDOW), y (from
+   MAKE-WINDOW), width (from MAKE-WINDOW), height (from MAKE-WINDOW), a name
+   for the window's icon-name, font-family (from MAKE-WINDOW), modelinep (from
+   MAKE-WINDOW), and whether the window will have a thumb-bar meter.  The
+   function returns a window or nil.")
+ 
+;;; BITMAP-MAKE-WINDOW -- Internal.
+;;; 
+#+clx
+(defun bitmap-make-window (device start modelinep window font-family
+				  ask-user x y width-arg height-arg proportion)
+  (let* ((display (bitmap-device-display device))
+	 (thumb-bar-p (value hemlock::thumb-bar-meter))
+	 (hunk (make-bitmap-hunk
+		:font-family font-family
+		:end *the-sentinel*  :trashed t
+		:input-handler #'window-input-handler
+		:device device
+		:thumb-bar-p (and modelinep thumb-bar-p))))
+    (multiple-value-bind
+	(xparent xwindow)
+	(maybe-make-x-window-and-parent window display start ask-user x y
+					width-arg height-arg font-family
+					modelinep thumb-bar-p proportion)
+      (unless xwindow (return-from bitmap-make-window nil))
+      (let ((window-group (make-window-group xparent
+					     (xlib:drawable-width xparent)
+					     (xlib:drawable-height xparent))))
+	(setf (bitmap-hunk-xwindow hunk) xwindow)
+	(setf (bitmap-hunk-window-group hunk) window-group)
+	(setf (bitmap-hunk-gcontext hunk)
+	      (default-gcontext xwindow font-family))
+	;;
+	;; Select input and enable event service before showing the window.
+	(setf (xlib:window-event-mask xwindow) child-interesting-xevents-mask)
+	(setf (xlib:window-event-mask xparent) group-interesting-xevents-mask)
+	(add-xwindow-object xwindow hunk *hemlock-windows*)
+	(add-xwindow-object xparent window-group *hemlock-windows*))
+      (when xparent (xlib:map-window xparent))
+      (xlib:map-window xwindow)
+      (xlib:display-finish-output display)
+      ;; A window is not really mapped until it is viewable.  It is said to be
+      ;; mapped if a map request has been sent whether it is handled or not.
+      (loop (when (and (eq (xlib:window-map-state xwindow) :viewable)
+		       (eq (xlib:window-map-state xparent) :viewable))
+	      (return)))
+      ;;
+      ;; Find out how big it is...
+      (xlib:with-state (xwindow)
+	(set-hunk-size hunk (xlib:drawable-width xwindow)
+		       (xlib:drawable-height xwindow) modelinep)))
+    (setf (bitmap-hunk-window hunk)
+	  (window-for-hunk hunk start modelinep))
+    ;; If window is non-nil, then it is a new group/parent window, so don't
+    ;; link it into the current window's group.  When ask-user is non-nil,
+    ;; we make a new group too.
+    (cond ((or window ask-user)
+	   ;; This occurs when we make the world's first Hemlock window.
+	   (unless *current-window*
+	     (setq *current-window* (bitmap-hunk-window hunk)))
+	   (setf (bitmap-hunk-previous hunk) hunk)
+	   (setf (bitmap-hunk-next hunk) hunk))
+	  (t
+	   (let ((h (window-hunk *current-window*)))
+	     (shiftf (bitmap-hunk-next hunk) (bitmap-hunk-next h) hunk)
+	     (setf (bitmap-hunk-previous (bitmap-hunk-next hunk)) hunk)
+	     (setf (bitmap-hunk-previous hunk) h))))
+    (push hunk (device-hunks device))
+    (bitmap-hunk-window hunk)))
+
+;;; MAYBE-MAKE-X-WINDOW-AND-PARENT -- Internal.
+;;;
+;;; BITMAP-MAKE-WINDOW calls this.  If xparent is non-nil, we clear it and
+;;; return it with a child that fills it.  If xparent is nil, and ask-user is
+;;; non-nil, then we invoke *create-window-hook* to get a parent window and
+;;; return it with a child that fills it.  By default, we make a child in the
+;;; CURRENT-WINDOW's parent.
+;;;
+#+clx
+(defun maybe-make-x-window-and-parent (xparent display start ask-user x y width
+				       height font-family modelinep thumb-p
+				       proportion)
+  (let ((icon-name (buffer-name (line-buffer (mark-line start)))))
+    (cond (xparent
+	   (check-type xparent xlib:window)
+	   (let ((width (xlib:drawable-width xparent))
+		 (height (xlib:drawable-height xparent)))
+	     (xlib:clear-area xparent :width width :height height)
+	     (modify-parent-properties :set xparent modelinep thumb-p
+				       (font-family-width font-family)
+				       (font-family-height font-family))
+	     (values xparent (xwindow-for-xparent xparent icon-name))))
+	  (ask-user
+	   (let ((xparent (funcall *create-window-hook*
+				   display x y width height icon-name
+				   font-family modelinep thumb-p)))
+	     (values xparent (xwindow-for-xparent xparent icon-name))))
+	  (t
+	   (let ((xparent (window-group-xparent
+			   (bitmap-hunk-window-group
+			    (window-hunk (current-window))))))
+	     (values xparent
+		     (create-window-from-current
+		      proportion font-family modelinep thumb-p xparent
+		      icon-name)))))))
+
+;;; XWINDOW-FOR-XPARENT -- Internal.
+;;;
+;;; This returns a child of xparent that completely fills that parent window.
+;;; We supply the font-width and font-height as nil because these are useless
+;;; for child windows.
+;;;
+#+clx
+(defun xwindow-for-xparent (xparent icon-name)
+  (xlib:with-state (xparent)
+    (create-window-with-properties xparent 0 0
+				   (xlib:drawable-width xparent)
+				   (xlib:drawable-height xparent)
+				   nil nil icon-name)))
+
+;;; CREATE-WINDOW-FROM-CURRENT -- Internal.
+;;;
+;;; This makes a child window on parent by splitting the current window.  If
+;;; the result will be too small, this returns nil.  If the current window's
+;;; height is odd, the extra pixel stays with it, and the new window is one
+;;; pixel smaller.
+;;;
+#+clx
+(defun create-window-from-current (proportion font-family modelinep thumb-p
+				   parent icon-name)
+  (let* ((cur-hunk (window-hunk *current-window*))
+	 (cwin (bitmap-hunk-xwindow cur-hunk)))
+    ;; Compute current window's height and take a proportion of it.
+    (xlib:with-state (cwin)
+      (let* ((cw (xlib:drawable-width cwin))
+	     (ch (xlib:drawable-height cwin))
+	     (cy (xlib:drawable-y cwin))
+	     (new-ch (truncate (* ch (- 1 proportion))))
+	     (font-height (font-family-height font-family))
+	     (font-width (font-family-width font-family))
+	     (cwin-min (minimum-window-height
+			(font-family-height
+			 (bitmap-hunk-font-family cur-hunk))
+			(bitmap-hunk-modeline-pos cur-hunk)
+			(bitmap-hunk-thumb-bar-p cur-hunk)))
+	     (new-min (minimum-window-height font-height modelinep
+					     thumb-p)))
+	(declare (fixnum cw cy ch new-ch))
+	;; See if we have room for a new window.  This should really
+	;; check the current window and the new one against their
+	;; relative fonts and the minimal window columns and line
+	;; (including whether there is a modeline).
+	(if (and (> new-ch cwin-min)
+		 (> (- ch new-ch) new-min))
+	    (let ((win (create-window-with-properties
+			parent 0 (+ cy new-ch)
+			cw (- ch new-ch) font-width font-height
+			icon-name)))
+	      ;; No need to reshape current Hemlock window structure here
+	      ;; since this call will send an appropriate event.
+	      (setf (xlib:drawable-height cwin) new-ch)
+	      ;; Set hints on parent, so the user can't resize it to be
+	      ;; smaller than what will hold the current number of
+	      ;; children.
+	      (modify-parent-properties :add parent modelinep
+					thumb-p
+					(font-family-width font-family)
+					font-height)
+	      win)
+	    nil)))))
+
+
+;;; MAKE-XWINDOW-LIKE-HWINDOW -- Interface.
+;;;
+;;; The window name is set to get around an awm and twm bug that inhibits menu
+;;; clicks unless the window has a name; this could be used better.
+;;;
+#+clx
+(defun make-xwindow-like-hwindow (window)
+  "This returns an group/parent xwindow with dimensions suitable for making a
+   Hemlock window like the argument window.  The new window's position should
+   be the same as the argument window's position relative to the root.  When
+   setting standard properties, we set x, y, width, and height to tell window
+   managers to put the window where we intend without querying the user."
+  (let* ((hunk (window-hunk window))
+	 (font-family (bitmap-hunk-font-family hunk))
+	 (xwin (bitmap-hunk-xwindow hunk)))
+    (multiple-value-bind (x y)
+			 (window-root-xy xwin)
+      (create-window-with-properties
+       (xlib:screen-root (xlib:display-default-screen
+			  (bitmap-device-display (device-hunk-device hunk))))
+       x y (bitmap-hunk-width hunk) (bitmap-hunk-height hunk)
+       (font-family-width font-family)
+       (font-family-height font-family)
+       (buffer-name (window-buffer window))
+       ;; When the user hands this window to MAKE-WINDOW, it will set the
+       ;; minimum width and height properties.
+       nil nil
+       t))))
+
+
+
+
+;;;; Deleting a window.
+
+;;; DEFAULT-DELETE-WINDOW-HOOK -- Internal.
+;;;
+#+clx
+(defun default-delete-window-hook (xparent)
+  (xlib:destroy-window xparent))
+#-clx
+(defun default-delete-window-hook (xparent)
+  (declare (ignore xparent)))
+;;;
+(defvar *delete-window-hook* #'default-delete-window-hook
+  "Hemlock calls this function to delete an X group/parent window.  It passes
+   the X window as an argument.")
+
+
+;;; BITMAP-DELETE-WINDOW  --  Internal
+;;;
+;;;
+#+clx
+(defun bitmap-delete-window (window)
+  (let* ((hunk (window-hunk window))
+	 (xwindow (bitmap-hunk-xwindow hunk))
+	 (xparent (window-group-xparent (bitmap-hunk-window-group hunk)))
+	 (display (bitmap-device-display (device-hunk-device hunk))))
+    (remove-xwindow-object xwindow)
+    (setq *window-list* (delete window *window-list*))
+    (when (eq *current-highlighted-border* hunk)
+      (setf *current-highlighted-border* nil))
+    (when (and (eq *cursor-hunk* hunk) *cursor-dropped*) (lift-cursor))
+    (xlib:display-force-output display)
+    (bitmap-delete-and-reclaim-window-space xwindow window)
+    (loop (unless (deleting-window-drop-event display xwindow) (return)))
+    (let ((device (device-hunk-device hunk)))
+      (setf (device-hunks device) (delete hunk (device-hunks device))))
+    (cond ((eq hunk (bitmap-hunk-next hunk))
+	   ;; Is this the last window in the group?
+	   (remove-xwindow-object xparent)
+	   (xlib:display-force-output display)
+	   (funcall *delete-window-hook* xparent)
+	   (loop (unless (deleting-window-drop-event display xparent)
+		   (return)))
+	   (let ((window (find-if-not #'(lambda (window)
+					  (eq window *echo-area-window*))
+				      *window-list*)))
+	     (setf (current-buffer) (window-buffer window)
+		   (current-window) window)))
+	  (t
+	   (modify-parent-properties :delete xparent
+				     (bitmap-hunk-modeline-pos hunk)
+				     (bitmap-hunk-thumb-bar-p hunk)
+				     (font-family-width
+				      (bitmap-hunk-font-family hunk))
+				     (font-family-height
+				      (bitmap-hunk-font-family hunk)))
+	   (let ((next (bitmap-hunk-next hunk))
+		 (prev (bitmap-hunk-previous hunk)))
+	     (setf (bitmap-hunk-next prev) next)
+	     (setf (bitmap-hunk-previous next) prev))))
+    (let ((buffer (window-buffer window)))
+      (setf (buffer-windows buffer) (delete window (buffer-windows buffer)))))
+  nil)
+
+;;; BITMAP-DELETE-AND-RECLAIM-WINDOW-SPACE -- Internal.
+;;;
+;;; This destroys the X window after obtaining its necessary state information.
+;;; If the previous or next window (in that order) is "stacked" over or under
+;;; the target window, then it is grown to fill in the newly opened space.  We
+;;; fetch all the necessary configuration data up front, so we don't have to
+;;; call XLIB:DESTROY-WINDOW while in the XLIB:WITH-STATE.
+;;;
+#+clx
+(defun bitmap-delete-and-reclaim-window-space (xwindow hwindow)
+  (multiple-value-bind (y height)
+		       (xlib:with-state (xwindow)
+			 (values (xlib:drawable-y xwindow)
+				 (xlib:drawable-height xwindow)))
+    (xlib:destroy-window xwindow)
+    (let ((hunk (window-hunk hwindow)))
+      (xlib:free-gcontext (bitmap-hunk-gcontext hunk))
+      (unless (eq hunk (bitmap-hunk-next hunk))
+	(unless (maybe-merge-with-previous-window hunk y height)
+	  (merge-with-next-window hunk y height))))))
+
+;;; MAYBE-MERGE-WITH-PREVIOUS-WINDOW -- Internal.
+;;;
+;;; This returns non-nil when it grows the previous hunk to include the
+;;; argument hunk's screen space.
+;;;
+#+clx
+(defun maybe-merge-with-previous-window (hunk y h)
+  (declare (fixnum y h))
+  (let* ((prev (bitmap-hunk-previous hunk))
+	 (prev-xwin (bitmap-hunk-xwindow prev)))
+    (xlib:with-state (prev-xwin)
+      (if (< (xlib:drawable-y prev-xwin) y)
+	  (incf (xlib:drawable-height prev-xwin) h)))))
+
+;;; MERGE-WITH-NEXT-WINDOW -- Internal.
+;;;
+;;; This trys to grow the next hunk's window to make use of the space created
+;;; by deleting hunk's window.  If this is possible, then we must also move the
+;;; next window up to where hunk's window was.
+;;;
+;;; When we reconfigure the window, we must set the hunk trashed.  This is a
+;;; hack since twm is broken again and is sending exposure events before
+;;; reconfigure notifications.  Hemlock relies on the protocol's statement that
+;;; reconfigures come before exposures to set the hunk trashed before getting
+;;; the exposure.  For now, we'll do it here too.
+;;;
+#+clx
+(defun merge-with-next-window (hunk y h)
+  (declare (fixnum y h))
+  (let* ((next (bitmap-hunk-next hunk))
+	 (next-xwin (bitmap-hunk-xwindow next)))
+    ;; Fetch height before setting y to save an extra round trip to the X
+    ;; server.
+    (let ((next-h (xlib:drawable-height next-xwin)))
+      (setf (xlib:drawable-y next-xwin) y)
+      (setf (xlib:drawable-height next-xwin) (+ next-h h)))
+    (setf (bitmap-hunk-trashed next) t)
+    (let ((hints (xlib:wm-normal-hints next-xwin)))
+      (setf (xlib:wm-size-hints-y hints) y)
+      (setf (xlib:wm-normal-hints next-xwin) hints))))
+
+
+;;; DELETING-WINDOW-DROP-EVENT -- Internal.
+;;;
+;;; This checks for any events on win.  If there is one, remove it from the
+;;; queue and return t.  Otherwise, return nil.
+;;;
+#+clx
+(defun deleting-window-drop-event (display win)
+  (xlib:display-finish-output display)
+  (let ((result nil))
+    (xlib:process-event
+     display :timeout 0
+     :handler #'(lambda (&key event-window window &allow-other-keys)
+		  (if (or (eq event-window win) (eq window win))
+		      (setf result t)
+		      nil)))
+    result))
+
+
+;;; MODIFY-PARENT-PROPERTIES -- Internal.
+;;;
+;;; This adds or deletes from xparent's min-height and min-width hints, so the
+;;; window manager will hopefully prevent users from making a window group too
+;;; small to hold all the windows in it.  We add to the height when we split
+;;; windows making additional ones, and we delete from it when we delete a
+;;; window.
+;;;
+;;; NOTE, THIS FAILS TO MAINTAIN THE WIDTH CORRECTLY.  We need to maintain the
+;;; width as the MAX of all the windows' minimal widths.  A window's minimal
+;;; width is its font's width multiplied by minimum-window-columns.
+;;;
+#+clx
+(defun modify-parent-properties (type xparent modelinep thumb-p
+				 font-width font-height)
+  (let ((hints (xlib:wm-normal-hints xparent)))
+    (xlib:set-wm-properties
+     xparent
+     :resource-name "Hemlock"
+     :x (xlib:wm-size-hints-x hints)
+     :y (xlib:wm-size-hints-y hints)
+     :width (xlib:drawable-width xparent)
+     :height (xlib:drawable-height xparent)
+     :user-specified-position-p t
+     :user-specified-size-p t
+     :width-inc (xlib:wm-size-hints-width-inc hints)
+     :height-inc (xlib:wm-size-hints-height-inc hints)
+     :min-width (or (xlib:wm-size-hints-min-width hints)
+		    (+ (* minimum-window-columns font-width) hunk-left-border))
+     :min-height
+     (let ((delta (minimum-window-height font-height modelinep thumb-p)))
+       (ecase type
+	 (:delete (- (xlib:wm-size-hints-min-height hints) delta))
+	 (:add (+ (or (xlib:wm-size-hints-min-height hints) 0)
+		  delta))
+	 (:set delta))))))
+
+;;; MINIMUM-WINDOW-HEIGHT -- Internal.
+;;;
+;;; This returns the minimum height necessary for a window given some of its
+;;; parameters.  This is the number of lines times font-height plus any extra
+;;; pixels for aesthetics.
+;;;
+(defun minimum-window-height (font-height modelinep thumb-p)
+  (if modelinep
+      (+ (* (1+ minimum-window-lines) font-height)
+	 (surplus-window-height-w/-modeline thumb-p))
+      (+ (* minimum-window-lines font-height)
+	 (surplus-window-height thumb-p))))
+
+
+
+
+;;;; Next and Previous windows.
+
+(defun bitmap-next-window (window)
+  "Return the next window after Window, wrapping around if Window is the
+  bottom window."
+  (check-type window window)
+  (bitmap-hunk-window (bitmap-hunk-next (window-hunk window))))
+
+(defun bitmap-previous-window (window)
+  "Return the previous window after Window, wrapping around if Window is the
+  top window."
+  (check-type window window)
+  (bitmap-hunk-window (bitmap-hunk-previous (window-hunk window))))
+
+
+
+
+;;;; Setting window width and height.
+
+;;; %SET-WINDOW-WIDTH  --  Internal
+;;;
+;;;    Since we don't support non-full-width windows, this does nothing.
+;;;
+(defun %set-window-width (window new-value)
+  (declare (ignore window))
+  new-value)
+
+;;; %SET-WINDOW-HEIGHT  --  Internal
+;;;
+;;;    Can't change window height either.
+;;;
+(defun %set-window-height (window new-value)
+  (declare (ignore window))
+  new-value)
+
+
+
+
+;;;; Random Typeout
+
+;;; Random typeout is done to a bitmap-hunk-output-stream
+;;; (Bitmap-Hunk-Stream.Lisp).  These streams have an associated hunk
+;;; that is used for its font-family, foreground and background color,
+;;; and X window pointer.  The hunk is not associated with any Hemlock
+;;; window, and the low level painting routines that use hunk dimensions
+;;; are not used for output.  The X window is resized as necessary with
+;;; each use, but the hunk is only registered for input and boundary
+;;; crossing event service; therefore, it never gets exposure or changed
+;;; notifications. 
+
+;;; These are set in INIT-BITMAP-SCREEN-MANAGER.
+;;; 
+(defvar *random-typeout-start-x* 0
+  "Where we put the the random typeout window.")
+(defvar *random-typeout-start-y* 0
+  "Where we put the the random typeout window.")
+(defvar *random-typeout-start-width* 0
+  "How wide the random typeout window is.")
+
+
+;;; DEFAULT-RANDOM-TYPEOUT-HOOK  --  Internal
+;;;
+;;;    The default hook-function for random typeout.  Nothing very fancy
+;;; for now.  If not given a window, makes one on top of the initial
+;;; Hemlock window using specials set in INIT-BITMAP-SCREEN-MANAGER.  If
+;;; given a window, we will change the height subject to the constraint
+;;; that the bottom won't be off the screen.  Any resulting window has
+;;; input and boundary crossing events selected, a hemlock cursor defined,
+;;; and is mapped.
+;;; 
+#+clx
+(defun default-random-typeout-hook (device window height)
+  (declare (fixnum height))
+    (let* ((display (bitmap-device-display device))
+	   (root (xlib:screen-root (xlib:display-default-screen display)))
+	   (full-height (xlib:drawable-height root))
+	   (actual-height (if window
+			      (multiple-value-bind (x y) (window-root-xy window)
+				(declare (ignore x) (fixnum y))
+				(min (- full-height y xwindow-border-width*2)
+				     height))
+			      (min (- full-height *random-typeout-start-y*
+				      xwindow-border-width*2)
+				   height)))
+	   (win (cond (window
+		       (setf (xlib:drawable-height window) actual-height)
+		       window)
+		      (t
+		       (let ((win (xlib:create-window
+				   :parent root
+				   :x *random-typeout-start-x*
+				   :y *random-typeout-start-y*
+				   :width *random-typeout-start-width*
+				   :height actual-height
+				   :background *default-background-pixel*
+				   :border-width xwindow-border-width
+				   :border *default-border-pixmap*
+				   :event-mask random-typeout-xevents-mask
+				   :override-redirect :on :class :input-output
+				   :cursor *hemlock-cursor*)))
+			 (xlib:set-wm-properties
+			  win :name "Pop-up Display" :icon-name "Pop-up Display"
+			  :resource-name "Hemlock"
+			  :x *random-typeout-start-x*
+			  :y *random-typeout-start-y*
+			  :width *random-typeout-start-width*
+			  :height actual-height
+			  :user-specified-position-p t :user-specified-size-p t
+			  ;; Tell OpenLook pseudo-X11 server we want input.
+			  :input :on)
+			 win))))
+	   (gcontext (if (not window) (default-gcontext win))))
+      (values win gcontext)))
+
+#-clx
+(defun default-random-typeout-hook (device window height)
+  (declare (ignore device window height)))
+
+(defvar *random-typeout-hook* #'default-random-typeout-hook
+  "This function is called when a window is needed to display random typeout.
+   It is called with the Hemlock device, a pre-existing window or NIL, and the
+   number of pixels needed to display the number of lines requested in
+   WITH-RANDOM-TYPEOUT.  It should return a window, and if a new window was
+   created, then a gcontext must be returned as the second value.")
+
+;;; BITMAP-RANDOM-TYPEOUT-SETUP  --  Internal
+;;;
+;;;    This function is called by the with-random-typeout macro to
+;;; to set things up.  It calls the *Random-Typeout-Hook* to get a window
+;;; to work with, and then adjusts the random typeout stream's data-structures
+;;; to match.
+;;;
+#+clx
+(defun bitmap-random-typeout-setup (device stream height)
+  (let* ((*more-prompt-action* :empty)
+	 (hwin-exists-p (random-typeout-stream-window stream))
+	 (hwindow (if hwin-exists-p
+		      (change-bitmap-random-typeout-window hwin-exists-p height)
+		      (setf (random-typeout-stream-window stream)
+			    (make-bitmap-random-typeout-window
+			     device
+			     (buffer-start-mark
+			      (line-buffer
+			       (mark-line (random-typeout-stream-mark stream))))
+			     height)))))
+    (let ((xwindow (bitmap-hunk-xwindow (window-hunk hwindow)))
+	  (display (bitmap-device-display device)))
+      (xlib:display-finish-output display)
+      (loop
+	(unless (xlib:event-case (display :timeout 0)
+		  (:exposure (event-window)
+		    (eq event-window xwindow))
+		  (t () nil))
+	  (return))))))
+
+#+clx
+(defun change-bitmap-random-typeout-window (hwindow height)
+  (update-modeline-field (window-buffer hwindow) hwindow :more-prompt)
+  (let* ((hunk (window-hunk hwindow))
+	 (xwin (bitmap-hunk-xwindow hunk)))
+    ;;
+    ;; *random-typeout-hook* sets the window's height to the right value.
+    (funcall *random-typeout-hook* (device-hunk-device hunk) xwin
+	     (+ (* height (font-family-height (bitmap-hunk-font-family hunk)))
+		hunk-top-border (bitmap-hunk-bottom-border hunk)
+		hunk-modeline-top hunk-modeline-bottom))
+    (xlib:with-state (xwin)
+      (hunk-changed hunk (xlib:drawable-width xwin) (xlib:drawable-height xwin)
+		    nil))
+    ;;
+    ;; We push this on here because we took it out the last time we cleaned up.
+    (push hwindow (buffer-windows (window-buffer hwindow)))
+    (setf (bitmap-hunk-trashed hunk) t)
+    (xlib:map-window xwin)
+    (setf (xlib:window-priority xwin) :above))
+  hwindow)
+  
+#+clx
+(defun make-bitmap-random-typeout-window (device mark height)
+  (let* ((display (bitmap-device-display device))
+	 (hunk (make-bitmap-hunk
+		:font-family *default-font-family*
+		:end *the-sentinel* :trashed t
+		:input-handler #'window-input-handler
+		:device device :thumb-bar-p nil)))
+    (multiple-value-bind
+	(xwindow gcontext)
+	(funcall *random-typeout-hook*
+		 device (bitmap-hunk-xwindow hunk)
+		 (+ (* height (font-family-height *default-font-family*))
+		    hunk-top-border (bitmap-hunk-bottom-border hunk)
+		hunk-modeline-top hunk-modeline-bottom))
+      ;;
+      ;; When gcontext, we just made the window, so tie some stuff together.
+      (when gcontext
+	(setf (xlib:gcontext-font gcontext)
+	      (svref (font-family-map *default-font-family*) 0))
+	(setf (bitmap-hunk-xwindow hunk) xwindow)
+	(setf (bitmap-hunk-gcontext hunk) gcontext)
+	;;
+	;; Select input and enable event service before showing the window.
+	(setf (xlib:window-event-mask xwindow) random-typeout-xevents-mask)
+	(add-xwindow-object xwindow hunk *hemlock-windows*))
+      ;;
+      ;; Put the window on the screen so it's visible and we can know the size.
+      (xlib:map-window xwindow)
+      (xlib:display-finish-output display)
+      ;; A window is not really mapped until it is viewable (not visible).
+      ;; It is said to be mapped if a map request has been sent whether it
+      ;; is handled or not.
+      (loop (when (eq (xlib:window-map-state xwindow) :viewable)
+	      (return)))
+      (xlib:with-state (xwindow)
+	(set-hunk-size hunk (xlib:drawable-width xwindow)
+		       (xlib:drawable-height xwindow) t))
+      ;;
+      ;; Get a Hemlock window and hide it from the rest of Hemlock.
+      (let ((hwin (window-for-hunk hunk mark *random-typeout-ml-fields*)))
+	(update-modeline-field (window-buffer hwin) hwin :more-prompt)
+	(setf (bitmap-hunk-window hunk) hwin)
+	(setf *window-list* (delete hwin *window-list*))
+	hwin))))
+
+  
+;;; RANDOM-TYPEOUT-CLEANUP  --  Internal
+;;;
+;;;    Clean up after random typeout.  This just removes the window from
+;;; the screen and sets the more-prompt action back to normal.
+;;;
+#+clx
+(defun bitmap-random-typeout-cleanup (stream degree)
+  (when degree
+    (xlib:unmap-window (bitmap-hunk-xwindow
+			(window-hunk (random-typeout-stream-window stream))))))
+
+
+
+
+;;;; Initialization.
+
+;;; DEFAULT-CREATE-INITIAL-WINDOWS-HOOK makes the initial windows, main and
+;;; echo.  The main window is made according to "Default Initial Window X",
+;;; "Default Initial Window Y", "Default Initial Window Width", and "Default
+;;; Initial Window Height", prompting the user for any unspecified components.
+;;; DEFAULT-CREATE-INITIAL-WINDOWS-ECHO is called to return the location and
+;;; size of the echo area including how big its font is, and the main xwindow
+;;; is potentially modified by this function.  The window name is set to get
+;;; around an awm and twm bug that inhibits menu clicks unless the window has a
+;;; name; this could be used better.
+;;;
+#+clx
+(defun default-create-initial-windows-hook (device)
+  (let ((root (xlib:screen-root (xlib:display-default-screen
+				 (bitmap-device-display device)))))
+    (let* ((xwindow (maybe-prompt-user-for-window
+		     root
+		     (value hemlock::default-initial-window-x)
+		     (value hemlock::default-initial-window-y)
+		     (value hemlock::default-initial-window-width)
+		     (value hemlock::default-initial-window-height)
+		     *default-font-family*
+		     t ;modelinep
+		     (value hemlock::thumb-bar-meter)
+		     "Hemlock")))
+      (setf (xlib:window-border xwindow) *highlight-border-pixmap*)
+      (let ((main-win (make-window (buffer-start-mark *current-buffer*)
+				   :device device
+				   :window xwindow)))
+	(multiple-value-bind
+	    (echo-x echo-y echo-width echo-height)
+	    (default-create-initial-windows-echo
+		(xlib:drawable-height root)
+		(window-hunk main-win))
+	  (let ((echo-xwin (make-echo-xwindow root echo-x echo-y echo-width
+					      echo-height)))
+	    (setf *echo-area-window*
+		  (hlet ((hemlock::thumb-bar-meter nil))
+		    (make-window
+		     (buffer-start-mark *echo-area-buffer*)
+		     :device device :modelinep t
+		     :window echo-xwin)))))
+	(setf *current-window* main-win)))))
+
+#-clx
+(defun default-create-initial-windows-hook (device)
+  (declare (ignore device)))
+
+;;; DEFAULT-CREATE-INITIAL-WINDOWS-ECHO makes the echo area window as wide as
+;;; the main window and places it directly under it.  If the echo area does not
+;;; fit on the screen, we change the main window to make it fit.  There is
+;;; a problem in computing main-xwin's x and y relative to the root window
+;;; which is where we line up the echo and main windows.  Some losing window
+;;; managers (awm and twm) reparent the window, so we have to make sure
+;;; main-xwin's x and y are relative to the root and not some false parent.
+;;;
+#+clx
+(defun default-create-initial-windows-echo (full-height hunk)
+  (declare (fixnum full-height))
+  (let ((font-family (bitmap-hunk-font-family hunk))
+	(xwindow (bitmap-hunk-xwindow hunk))
+	(xparent (window-group-xparent (bitmap-hunk-window-group hunk))))
+    (xlib:with-state (xwindow)
+      (let ((w (xlib:drawable-width xwindow))
+	    (h (xlib:drawable-height xwindow)))
+	(declare (fixnum w h))
+	(multiple-value-bind (x y)
+			     (window-root-xy xwindow
+					     (xlib:drawable-x xwindow)
+					     (xlib:drawable-y xwindow))
+	  (declare (fixnum x y))
+	  (let* ((ff-height (font-family-height font-family))
+		 (ff-width (font-family-width font-family))
+		 (echo-height (+ (* ff-height 4)
+				 hunk-top-border hunk-bottom-border
+				 hunk-modeline-top hunk-modeline-bottom)))
+	    (declare (fixnum echo-height))
+	    (if (<= (+ y h echo-height xwindow-border-width*2) full-height)
+		(values x (+ y h xwindow-border-width*2)
+			w echo-height ff-width ff-height)
+		(let* ((newh (- full-height y echo-height xwindow-border-width*2
+				;; Since y is really the outside y, subtract
+				;; two more borders, so the echo area's borders
+				;; both appear on the screen.
+				xwindow-border-width*2)))
+		  (setf (xlib:drawable-height xparent) newh)
+		  (values x (+ y newh xwindow-border-width*2)
+			  w echo-height ff-width ff-height)))))))))
+
+(defvar *create-initial-windows-hook* #'default-create-initial-windows-hook
+  "Hemlock uses this function when it initializes the screen manager to make
+   the first windows, typically the main and echo area windows.  It takes a
+   Hemlock device as a required argument.  It sets *current-window* and
+   *echo-area-window*.")
+
+(defun make-echo-xwindow (root x y width height)
+  (let* ((font-width (font-family-width *default-font-family*))
+	 (font-height (font-family-height *default-font-family*)))
+    (create-window-with-properties root x y width height
+				   font-width font-height
+				   "Echo Area" nil nil t)))
+
+#+clx
+(defun init-bitmap-screen-manager (display)
+  ;;
+  ;; Setup stuff for X interaction.
+  (cond ((value hemlock::reverse-video)
+	 (setf *default-background-pixel*
+	       (xlib:screen-black-pixel (xlib:display-default-screen display)))
+	 (setf *default-foreground-pixel*
+	       (xlib:screen-white-pixel (xlib:display-default-screen display)))
+	 (setf *cursor-background-color* (make-black-color))
+	 (setf *cursor-foreground-color* (make-white-color))
+	 (setf *hack-hunk-replace-line* nil))
+	(t (setf *default-background-pixel*
+		 (xlib:screen-white-pixel (xlib:display-default-screen display)))
+	   (setf *default-foreground-pixel*
+		 (xlib:screen-black-pixel (xlib:display-default-screen display)))
+	   (setf *cursor-background-color* (make-white-color))
+	   (setf *cursor-foreground-color* (make-black-color))))
+  (setf *foreground-background-xor*
+	(logxor *default-foreground-pixel* *default-background-pixel*))
+  (setf *highlight-border-pixmap* *default-foreground-pixel*)
+  (setf *default-border-pixmap* (get-hemlock-grey-pixmap display))
+  (get-hemlock-cursor display)
+  (add-hook hemlock::make-window-hook 'define-window-cursor)
+  ;;
+  ;; Make the device for the rest of initialization.
+  (let ((device (make-default-bitmap-device display)))
+    ;;
+    ;; Create initial windows.
+    (funcall *create-initial-windows-hook* device)
+    ;;
+    ;; Setup random typeout over the user's main window.
+    (let ((xwindow (bitmap-hunk-xwindow (window-hunk *current-window*))))
+      (xlib:with-state (xwindow)
+	(multiple-value-bind (x y)
+			     (window-root-xy xwindow (xlib:drawable-x xwindow)
+					     (xlib:drawable-y xwindow))
+	  (setf *random-typeout-start-x* x)
+	  (setf *random-typeout-start-y* y))
+	(setf *random-typeout-start-width* (xlib:drawable-width xwindow)))))
+  (add-hook hemlock::window-buffer-hook 'set-window-name-for-window-buffer)
+  (add-hook hemlock::buffer-name-hook 'set-window-name-for-buffer-name)
+  (add-hook hemlock::set-window-hook 'set-window-hook-raise-fun)
+  (add-hook hemlock::buffer-modified-hook 'raise-echo-area-when-modified))
+
+(defun make-default-bitmap-device (display)
+  (make-bitmap-device
+   :name "Windowed Bitmap Device"
+   :init #'init-bitmap-device
+   :exit #'exit-bitmap-device
+   :smart-redisplay #'smart-window-redisplay
+   :dumb-redisplay #'dumb-window-redisplay
+   :after-redisplay #'bitmap-after-redisplay
+   :clear nil
+   :note-read-wait #'frob-cursor
+   :put-cursor #'hunk-show-cursor
+   :show-mark #'bitmap-show-mark
+   :next-window #'bitmap-next-window
+   :previous-window #'bitmap-previous-window
+   :make-window #'bitmap-make-window
+   :delete-window #'bitmap-delete-window
+   :force-output #'bitmap-force-output
+   :finish-output #'bitmap-finish-output
+   :random-typeout-setup #'bitmap-random-typeout-setup
+   :random-typeout-cleanup #'bitmap-random-typeout-cleanup
+   :random-typeout-full-more #'do-bitmap-full-more
+   :random-typeout-line-more #'update-bitmap-line-buffered-stream
+   :beep #'bitmap-beep
+   :display display))
+
+(defun init-bitmap-device (device)
+  (let ((display (bitmap-device-display device)))
+    (hemlock-ext:flush-display-events display)
+    (hemlock-window display t)))
+
+(defun exit-bitmap-device (device)
+  (hemlock-window (bitmap-device-display device) nil))
+
+#+clx
+(defun bitmap-finish-output (device window)
+  (declare (ignore window))
+  (xlib:display-finish-output (bitmap-device-display device)))
+
+#+clx
+(defun bitmap-force-output ()
+  (xlib:display-force-output
+   (bitmap-device-display (device-hunk-device (window-hunk (current-window))))))
+
+(defun bitmap-after-redisplay (device)
+  (let ((display (bitmap-device-display device)))
+    (loop (unless (hemlock-ext:object-set-event-handler display) (return)))))
+
+
+
+
+;;;; Miscellaneous.
+
+;;; HUNK-RESET is called in redisplay to make sure the hunk is up to date.
+;;; If the size is wrong, or it is trashed due to font changes, then we
+;;; call HUNK-CHANGED.  We also clear the hunk.
+;;;
+#+clx
+(defun hunk-reset (hunk)
+  (let ((xwindow (bitmap-hunk-xwindow hunk))
+	(trashed (bitmap-hunk-trashed hunk)))
+    (when trashed
+      (setf (bitmap-hunk-trashed hunk) nil)
+      (xlib:with-state (xwindow)
+	(let ((w (xlib:drawable-width xwindow))
+	      (h (xlib:drawable-height xwindow)))
+	  (when (or (/= w (bitmap-hunk-width hunk))
+		    (/= h (bitmap-hunk-height hunk))
+		    (eq trashed :font-change))
+	    (hunk-changed hunk w h nil)))))
+    (xlib:clear-area xwindow :width (bitmap-hunk-width hunk)
+		     :height (bitmap-hunk-height hunk))
+    (hunk-draw-bottom-border hunk)))
+
+;;; HUNK-CHANGED -- Internal.
+;;;
+;;; HUNK-RESET and the changed window handler call this.  Don't go through
+;;; REDISPLAY-WINDOW-ALL since the window changed handler updates the window
+;;; image.
+;;;
+(defun hunk-changed (hunk new-width new-height redisplay)
+  (set-hunk-size hunk new-width new-height)
+  (funcall (bitmap-hunk-changed-handler hunk) hunk)
+  (when redisplay (dumb-window-redisplay (bitmap-hunk-window hunk))))
+
+;;; WINDOW-GROUP-CHANGED -- Internal.
+;;;
+;;; HUNK-RECONFIGURED calls this when the hunk was a window-group.  This finds
+;;; the windows in the changed group, sorts them by their vertical stacking
+;;; order, and tries to resize the windows proportioned by their old sizes
+;;; relative to the old group size.  If that fails, this tries to make all the
+;;; windows the same size, dividing up the new group's size.
+;;;
+#+clx
+(defun window-group-changed (window-group new-width new-height)
+  (let ((xparent (window-group-xparent window-group))
+	(affected-windows nil)
+	(count 0)
+	(old-xparent-height (window-group-height window-group)))
+    (setf (window-group-width window-group) new-width)
+    (setf (window-group-height window-group) new-height)
+    (dolist (window *window-list*)
+      (let ((test (window-group-xparent (bitmap-hunk-window-group
+					 (window-hunk window)))))
+	(when (eq test xparent)
+	  (push window affected-windows)
+	  (incf count))))
+    ;; Probably shoulds insertion sort them, but I'm lame.
+    ;;
+    (xlib:with-state (xparent)
+      (sort affected-windows #'<
+	    :key #'(lambda (window)
+		     (xlib:drawable-y
+		      (bitmap-hunk-xwindow (window-hunk window))))))
+    (let ((start 0))
+      (declare (fixnum start))
+      (do ((windows affected-windows (cdr windows)))
+	  ((endp windows))
+	(let* ((xwindow (bitmap-hunk-xwindow (window-hunk (car windows))))
+	       (new-child-height (round
+				  (* new-height
+				     (/ (xlib:drawable-height xwindow)
+					old-xparent-height))))
+	       (hunk (window-hunk (car windows))))
+	  ;; If there is not enough room for one of the windows, space them out
+	  ;; evenly so there will be room.
+	  ;; 
+	  (when (< new-child-height (minimum-window-height
+				     (font-family-height
+				      (bitmap-hunk-font-family hunk))
+				     (bitmap-hunk-modeline-pos hunk)
+				     (bitmap-hunk-thumb-bar-p hunk)))
+	    (reconfigure-windows-evenly affected-windows new-width new-height)
+	    (return))
+	  (xlib:with-state (xwindow)
+	    (setf (xlib:drawable-y xwindow) start
+		  ;; Make the last window absorb or lose the number of pixels
+		  ;; lost in rounding.
+		  ;;
+		  (xlib:drawable-height xwindow) (if (cdr windows)
+						     new-child-height
+						     (- new-height start))
+		  (xlib:drawable-width xwindow) new-width
+		  start (+ start new-child-height 1))))))))
+
+#+clx
+(defun reconfigure-windows-evenly (affected-windows new-width new-height)
+  (let ((count (length affected-windows)))
+    (multiple-value-bind
+	(pixels-per-window remainder)
+	(truncate new-height count)
+      (let ((count-1 (1- count)))
+	(do ((windows affected-windows (cdr windows))
+	     (i 0 (1+ i)))
+	    ((endp windows))
+	  (let ((xwindow (bitmap-hunk-xwindow (window-hunk (car windows)))))
+	    (setf (xlib:drawable-y xwindow) (* i pixels-per-window))
+	    (setf (xlib:drawable-width xwindow) new-width)
+	    (if (= i count-1)
+		(return (setf (xlib:drawable-height
+			       (bitmap-hunk-xwindow
+				(window-hunk (car windows))))
+			      (+ pixels-per-window remainder)))
+		(setf (xlib:drawable-height xwindow) pixels-per-window))))))))
+
+;;; SET-HUNK-SIZE  --  Internal
+;;;
+;;;    Given a pixel size for a bitmap hunk, set the char size.  If the window
+;;; is too small, we refuse to admit it; if the user makes unreasonably small
+;;; windows, our only responsibity is to not blow up.  X will clip any stuff
+;;; that doesn't fit.
+;;;
+(defun set-hunk-size (hunk w h &optional modelinep)
+  (let* ((font-family (bitmap-hunk-font-family hunk))
+	 (font-width (font-family-width font-family))
+	 (font-height (font-family-height font-family)))
+    (setf (bitmap-hunk-height hunk) h)
+    (setf (bitmap-hunk-width hunk) w)
+    (setf (bitmap-hunk-char-width hunk)
+	  (max (truncate (- w hunk-left-border) font-width)
+	       minimum-window-columns))
+    (let* ((h-minus-borders (- h hunk-top-border
+			       (bitmap-hunk-bottom-border hunk)))
+	   (hwin (bitmap-hunk-window hunk))
+	   (modelinep (or modelinep (and hwin (window-modeline-buffer hwin)))))
+      (setf (bitmap-hunk-char-height hunk)
+	    (max (if modelinep
+		     (1- (truncate (- h-minus-borders
+				      hunk-modeline-top hunk-modeline-bottom)
+				   font-height))
+		     (truncate h-minus-borders font-height))
+		 minimum-window-lines))
+      (setf (bitmap-hunk-modeline-pos hunk)
+	    (if modelinep (- h font-height
+			     hunk-modeline-top hunk-modeline-bottom))))))
+
+;;; BITMAP-HUNK-BOTTOM-BORDER -- Internal.
+;;;
+(defun bitmap-hunk-bottom-border (hunk)
+  (if (bitmap-hunk-thumb-bar-p hunk)
+      hunk-thumb-bar-bottom-border
+      hunk-bottom-border))
+
+
+;;; DEFAULT-GCONTEXT is used when making hunks.
+;;;
+#+clx
+(defun default-gcontext (drawable &optional font-family)
+  (xlib:create-gcontext
+   :drawable drawable
+   :foreground *default-foreground-pixel*
+   :background *default-background-pixel*
+   :font (if font-family (svref (font-family-map font-family) 0))))
+
+
+;;; WINDOW-ROOT-XY returns the x and y coordinates for a window relative to
+;;; its root.  Some window managers reparent Hemlock's window, so we have
+;;; to mess around possibly to get this right.  If x and y are supplied, they
+;;; are relative to xwin's parent.
+;;;
+#+clx
+(defun window-root-xy (xwin &optional x y)
+  (multiple-value-bind (children parent root)
+		       (xlib:query-tree xwin)
+    (declare (ignore children))
+    (if (eq parent root)
+	(if (and x y)
+	    (values x y)
+	    (xlib:with-state (xwin)
+	      (values (xlib:drawable-x xwin) (xlib:drawable-y xwin))))
+	(multiple-value-bind
+	    (tx ty)
+	    (if (and x y)
+		(xlib:translate-coordinates parent x y root)
+		(xlib:with-state (xwin)
+		  (xlib:translate-coordinates
+		   parent (xlib:drawable-x xwin) (xlib:drawable-y xwin) root)))
+	  (values (- tx xwindow-border-width)
+		  (- ty xwindow-border-width))))))
+
+;;; CREATE-WINDOW-WITH-PROPERTIES makes an X window with parent.  X, y, w, and
+;;; h are possibly nil, so we supply zero in this case.  This would be used
+;;; for prompting the user.  Some standard properties are set to keep window
+;;; managers in line.  We name all windows because awm and twm window managers
+;;; refuse to honor menu clicks over windows without names.  Min-width and
+;;; min-height are optional and only used for prompting the user for a window.
+;;;
+#+clx
+(defun create-window-with-properties (parent x y w h font-width font-height
+				      icon-name
+				      &optional min-width min-height
+				      window-group-p)
+  (let* ((win (xlib:create-window
+	       :parent parent :x (or x 0) :y (or y 0)
+	       :width (or w 0) :height (or h 0)
+	       :background (if window-group-p :none *default-background-pixel*)
+	       :border-width (if window-group-p xwindow-border-width 0)
+	       :border (if window-group-p *default-border-pixmap* nil)
+	       :class :input-output)))
+    (xlib:set-wm-properties
+     win :name (new-hemlock-window-name) :icon-name icon-name
+     :resource-name "Hemlock"
+     :x x :y y :width w :height h
+     :user-specified-position-p t :user-specified-size-p t
+     :width-inc font-width :height-inc font-height
+     :min-width min-width :min-height min-height
+     ;; Tell OpenLook pseudo-X11 server we want input.
+     :input :on)
+    win))
+
+
+;;; SET-WINDOW-HOOK-RAISE-FUN is a "Set Window Hook" function controlled by
+;;; "Set Window Autoraise".  When autoraising, check that it isn't only the
+;;; echo area window that we autoraise; if it is only the echo area window,
+;;; then see if window is the echo area window.
+;;; 
+#+clx
+(defun set-window-hook-raise-fun (window)
+  (let ((auto (value hemlock::set-window-autoraise)))
+    (when (and auto
+	       (or (not (eq auto :echo-only))
+		   (eq window *echo-area-window*)))
+      (let* ((hunk (window-hunk window))
+	     (win (window-group-xparent (bitmap-hunk-window-group hunk))))
+	(xlib:map-window win)
+	(setf (xlib:window-priority win) :above)
+	(xlib:display-force-output
+	 (bitmap-device-display (device-hunk-device hunk)))))))
+
+
+;;; REVERSE-VIDEO-HOOK-FUN is called when the variable "Reverse Video" is set.
+;;; If we are running on a windowed bitmap, we first setup the default
+;;; foregrounds and backgrounds.  Having done that, we get a new cursor.  Then
+;;; we do over all the hunks, updating their graphics contexts, cursors, and
+;;; backgrounds.  The current window's border is given the new highlight pixmap.
+;;; Lastly, we update the random typeout hunk and redisplay everything.
+;;;
+
+#+clx
+(defun reverse-video-hook-fun (name kind where new-value)
+  (declare (ignore name kind where))
+  (when (windowed-monitor-p)
+    (let* ((current-window (current-window))
+	   (current-hunk (window-hunk current-window))
+	   (device (device-hunk-device current-hunk))
+	   (display (bitmap-device-display device)))
+      (cond
+       (new-value
+	(setf *default-background-pixel*
+	      (xlib:screen-black-pixel (xlib:display-default-screen display)))
+	(setf *default-foreground-pixel*
+	      (xlib:screen-white-pixel (xlib:display-default-screen display)))
+	(setf *cursor-background-color* (make-black-color))
+	(setf *cursor-foreground-color* (make-white-color))
+	(setf *hack-hunk-replace-line* nil))
+       (t (setf *default-background-pixel*
+		(xlib:screen-white-pixel (xlib:display-default-screen display)))
+	  (setf *default-foreground-pixel*
+		(xlib:screen-black-pixel (xlib:display-default-screen display)))
+	  (setf *cursor-background-color* (make-white-color))
+	  (setf *cursor-foreground-color* (make-black-color))))
+      (setf *highlight-border-pixmap* *default-foreground-pixel*)
+      (get-hemlock-cursor display)
+      (dolist (hunk (device-hunks device))
+	(reverse-video-frob-hunk hunk))
+      (dolist (rt-info *random-typeout-buffers*)
+	(reverse-video-frob-hunk
+	 (window-hunk (random-typeout-stream-window (cdr rt-info)))))
+      (setf (xlib:window-border (bitmap-hunk-xwindow current-hunk))
+	    *highlight-border-pixmap*))
+    (redisplay-all)))
+
+#-clx
+(defun reverse-video-hook-fun (name kind where new-value)
+  (declare (ignore name kind where new-value)))
+
+#+clx
+(defun reverse-video-frob-hunk (hunk)
+  (let ((gcontext (bitmap-hunk-gcontext hunk)))
+    (setf (xlib:gcontext-foreground gcontext) *default-foreground-pixel*)
+    (setf (xlib:gcontext-background gcontext) *default-background-pixel*))
+  (let ((xwin (bitmap-hunk-xwindow hunk)))
+    (setf (xlib:window-cursor xwin) *hemlock-cursor*)
+    (setf (xlib:window-background xwin) *default-background-pixel*)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/bufed.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/bufed.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/bufed.lisp	(revision 13309)
@@ -0,0 +1,301 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains Bufed (Buffer Editing) code.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; Representation of existing buffers.
+
+;;; This is the array of buffers in the bufed buffer.  Each element is a cons,
+;;; where the CAR is the buffer, and the CDR indicates whether the buffer
+;;; should be deleted (t deleted, nil don't).
+;;;
+(defvar *bufed-buffers* nil)
+(defvar *bufed-buffers-end* nil)
+;;;
+(defmacro bufed-buffer (x) `(car ,x))
+(defmacro bufed-buffer-deleted (x) `(cdr ,x))
+(defmacro make-bufed-buffer (buffer) `(list ,buffer))
+
+
+;;; This is the bufed buffer if it exists.
+;;;
+(defvar *bufed-buffer* nil)
+
+;;; This is the cleanup method for deleting *bufed-buffer*.
+;;;
+(defun delete-bufed-buffers (buffer)
+  (when (eq buffer *bufed-buffer*)
+    (setf *bufed-buffer* nil)
+    (setf *bufed-buffers* nil)))
+
+
+
+
+;;;; Commands.
+
+(defmode "Bufed" :major-p t
+  :documentation
+  "Bufed allows the user to quickly save, goto, delete, etc., his buffers.")
+
+(defhvar "Virtual Buffer Deletion"
+  "When set, \"Bufed Delete\" marks a buffer for deletion instead of immediately
+   deleting it."
+  :value t)
+
+(defhvar "Bufed Delete Confirm"
+  "When set, \"Bufed\" commands that actually delete buffers ask for
+   confirmation before taking action."
+  :value t)
+
+(defcommand "Bufed Delete" (p)
+  "Delete the buffer.
+   Any windows displaying this buffer will display some other buffer."
+  "Delete the buffer indicated by the current line.  Any windows displaying this
+   buffer will display some other buffer."
+  (declare (ignore p))
+  (let* ((point (current-point))
+	 (buf-info (array-element-from-mark point *bufed-buffers*)))
+    (if (and (not (value virtual-buffer-deletion))
+	     (or (not (value bufed-delete-confirm))
+		 (prompt-for-y-or-n :prompt "Delete buffer? " :default t
+				    :must-exist t :default-string "Y")))
+	(delete-bufed-buffer (bufed-buffer buf-info))
+	(with-writable-buffer (*bufed-buffer*)
+	  (setf (bufed-buffer-deleted buf-info) t)
+	  (with-mark ((point point))
+	    (setf (next-character (line-start point)) #\D))))))
+
+(defcommand "Bufed Undelete" (p)
+  "Undelete the buffer.
+   Any windows displaying this buffer will display some other buffer."
+  "Undelete the buffer.  Any windows displaying this buffer will display some
+   other buffer."
+  (declare (ignore p))
+  (with-writable-buffer (*bufed-buffer*)
+    (setf (bufed-buffer-deleted (array-element-from-mark
+				 (current-point) *bufed-buffers*))
+	  nil)
+    (with-mark ((point (current-point)))
+      (setf (next-character (line-start point)) #\space))))
+
+(defcommand "Bufed Expunge" (p)
+  "Expunge buffers marked for deletion."
+  "Expunge buffers marked for deletion."
+  (declare (ignore p))
+  (expunge-bufed-buffers))
+
+(defcommand "Bufed Quit" (p)
+  "Kill the bufed buffer, expunging any buffer marked for deletion."
+  "Kill the bufed buffer, expunging any buffer marked for deletion."
+  (declare (ignore p))
+  (expunge-bufed-buffers)
+  (when *bufed-buffer* (delete-buffer-if-possible *bufed-buffer*)))
+
+;;; EXPUNGE-BUFED-BUFFERS deletes the marked buffers in the bufed buffer,
+;;; signalling an error if the current buffer is not the bufed buffer.  This
+;;; returns t if it deletes some buffer, otherwise nil.  We build a list of
+;;; buffers before deleting any because the BUFED-DELETE-HOOK moves elements
+;;; around in *bufed-buffers*.
+;;;
+(defun expunge-bufed-buffers ()
+  (unless (eq *bufed-buffer* (current-buffer))
+    (editor-error "Not in the Bufed buffer."))
+  (let (buffers)
+    (dotimes (i *bufed-buffers-end*)
+      (let ((buf-info (svref *bufed-buffers* i)))
+	(when (bufed-buffer-deleted buf-info)
+	  (push (bufed-buffer buf-info) buffers))))
+    (if (and buffers
+	     (or (not (value bufed-delete-confirm))
+		 (prompt-for-y-or-n :prompt "Delete buffers? " :default t
+				    :must-exist t :default-string "Y")))
+	(dolist (b buffers t) (delete-bufed-buffer b)))))
+
+(defun delete-bufed-buffer (buf)
+  (when (and (buffer-modified buf)
+	     (prompt-for-y-or-n :prompt (list "~A is modified.  Save it first? "
+					      (buffer-name buf))))
+    (save-file-command nil buf))
+  (delete-buffer-if-possible buf))
+
+
+(defcommand "Bufed Goto" (p)
+  "Change to the buffer."
+  "Change to the buffer."
+  (declare (ignore p))
+  (change-to-buffer
+   (bufed-buffer (array-element-from-mark (current-point) *bufed-buffers*))))
+
+(defcommand "Bufed Goto and Quit" (p)
+  "Change to the buffer quitting Bufed.
+   This supplies a function for \"Generic Pointer Up\" which is a no-op."
+  "Change to the buffer quitting Bufed."
+  (declare (ignore p))
+  (expunge-bufed-buffers)
+  (point-to-here-command nil)
+  (change-to-buffer
+   (bufed-buffer (array-element-from-pointer-pos *bufed-buffers*
+		 "No buffer on that line.")))
+  (when *bufed-buffer* (delete-buffer-if-possible *bufed-buffer*))
+  (supply-generic-pointer-up-function #'(lambda () nil)))
+
+(defcommand "Bufed Save File" (p)
+  "Save the buffer."
+  "Save the buffer."
+  (declare (ignore p))
+  (save-file-command
+   nil
+   (bufed-buffer (array-element-from-mark (current-point) *bufed-buffers*))))
+
+(defcommand "Bufed" (p)
+  "Creates a list of buffers in a buffer supporting operations such as deletion
+   and selection.  If there already is a bufed buffer, just go to it."
+  "Creates a list of buffers in a buffer supporting operations such as deletion
+   and selection.  If there already is a bufed buffer, just go to it."
+  (declare (ignore p))
+  (let ((buf (or *bufed-buffer*
+		 (make-buffer "Bufed" :modes '("Bufed")
+			      :delete-hook (list #'delete-bufed-buffers)))))
+
+    (unless *bufed-buffer*
+      (setf *bufed-buffer* buf)
+      (setf *bufed-buffers-end*
+	    ;; -1 echo, -1 bufed.
+	    (- (length (the list *buffer-list*)) 2))
+      (setf *bufed-buffers* (make-array *bufed-buffers-end*))
+      (setf (buffer-writable buf) t)
+      (with-output-to-mark (s (buffer-point buf))
+	(let ((i 0))
+	  (do-strings (n b *buffer-names*)
+	    (declare (simple-string n))
+	    (unless (or (eq b *echo-area-buffer*)
+			(eq b buf))
+	      (bufed-write-line b n s)
+	      (setf (svref *bufed-buffers* i) (make-bufed-buffer b))
+	      (incf i)))))
+      (setf (buffer-writable buf) nil)
+      (setf (buffer-modified buf) nil)
+      (let ((fields (buffer-modeline-fields *bufed-buffer*)))
+	(setf (cdr (last fields))
+	      (list (or (modeline-field :bufed-cmds)
+			(make-modeline-field
+			 :name :bufed-cmds :width 18
+			 :function
+			 #'(lambda (buffer window)
+			     (declare (ignore buffer window))
+			     "  Type ? for help.")))))
+	(setf (buffer-modeline-fields *bufed-buffer*) fields))
+      (buffer-start (buffer-point buf)))
+    (change-to-buffer buf)))
+
+(defun bufed-write-line (buffer name s
+		         &optional (buffer-pathname (buffer-pathname buffer)))
+  (let ((modified (buffer-modified buffer)))
+    (write-string (if modified " *" "  ") s)
+    (if buffer-pathname
+	(format s "~A  ~A~:[~50T~A~;~]~%"
+		(file-namestring buffer-pathname)
+		(directory-namestring buffer-pathname)
+		(string= (pathname-to-buffer-name buffer-pathname) name)
+		name)
+	(write-line name s))))
+
+
+(defcommand "Bufed Help" (p)
+  "Show this help."
+  "Show this help."
+  (declare (ignore p))
+  (describe-mode-command nil "Bufed"))
+
+
+
+
+;;;; Maintenance hooks.
+
+(eval-when (:compile-toplevel :execute)
+(defmacro with-bufed-point ((point buffer &optional pos) &rest body)
+  (let ((pos (or pos (gensym))))
+    `(when (and *bufed-buffers*
+		(not (eq *bufed-buffer* ,buffer))
+		(not (eq *echo-area-buffer* ,buffer)))
+       (let ((,pos (position ,buffer *bufed-buffers* :key #'car
+			     :test #'eq :end *bufed-buffers-end*)))
+	 (unless ,pos (error "Unknown Bufed buffer."))
+	 (let ((,point (buffer-point *bufed-buffer*)))
+	   (unless (line-offset (buffer-start ,point) ,pos 0)
+	     (error "Bufed buffer not displayed?"))
+	   (with-writable-buffer (*bufed-buffer*) ,@body))))))
+) ;eval-when
+
+
+(defun bufed-modified-hook (buffer modified)
+  (with-bufed-point (point buffer)
+    (setf (next-character (mark-after point)) (if modified #\* #\space))))
+;;;
+(add-hook buffer-modified-hook 'bufed-modified-hook)
+
+(defun bufed-make-hook (buffer)
+  (declare (ignore buffer))
+  (when *bufed-buffer* (delete-buffer-if-possible *bufed-buffer*)))
+;;;
+(add-hook make-buffer-hook 'bufed-make-hook)
+
+(defun bufed-delete-hook (buffer)
+  (with-bufed-point (point buffer pos)
+    (with-mark ((temp point :left-inserting))
+      (line-offset temp 1)
+      (delete-region (region point temp)))
+    (let ((len-1 (1- *bufed-buffers-end*)))
+      (replace *bufed-buffers* *bufed-buffers*
+	       :start1 pos :end1 len-1
+	       :start2 (1+ pos) :end1 *bufed-buffers-end*)
+      (setf (svref *bufed-buffers* len-1) nil)
+      (setf *bufed-buffers-end* len-1))))
+;;;
+(add-hook delete-buffer-hook 'bufed-delete-hook)
+
+(defun bufed-name-hook (buffer name)
+  (with-bufed-point (point buffer)
+    (with-mark ((temp point :left-inserting))
+      (line-offset temp 1)
+      (delete-region (region point temp)))
+    (with-output-to-mark (s point)
+      (bufed-write-line buffer name s))))
+;;;
+(add-hook buffer-name-hook 'bufed-name-hook)
+
+(defun bufed-pathname-hook (buffer pathname)
+  (with-bufed-point (point buffer)
+    (with-mark ((temp point :left-inserting))
+      (line-offset temp 1)
+      (delete-region (region point temp)))
+    (with-output-to-mark (s point)
+      (bufed-write-line buffer (buffer-name buffer) s pathname))))
+;;;
+(add-hook buffer-pathname-hook 'bufed-pathname-hook)
+
+
+
+;;;; Utilities
+
+(defun array-element-from-pointer-pos (vector &optional
+					      (error-msg "Invalid line."))
+  (multiple-value-bind (x y window) (last-key-event-cursorpos)
+    (declare (ignore x window))
+    (when (>= y (length vector))
+      (editor-error error-msg))
+    (svref vector y)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/debug.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/debug.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/debug.lisp	(revision 13309)
@@ -0,0 +1,561 @@
+;;; -*- Mode: Lisp; Package: ED; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This contains commands for sending debugger commands to slaves in the
+;;; debugger.
+;;;
+;;; Written by Bill Chiles.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; DEFINE-DEBUGGER-COMMAND.
+
+(defmacro define-debugger-command (name doc cmd &key uses-argument)
+  `(defcommand ,(concatenate 'simple-string "Debug " name) (p)
+     ,doc ,doc
+     ,@(if uses-argument
+	   nil
+	   '((declare (ignore p))))
+     (let* ((server-info (get-current-eval-server t))
+	    (wire (server-info-wire server-info)))
+       (wire:remote wire
+	 (ts-stream-accept-input
+	  (ts-data-stream (server-info-slave-info server-info))
+	  ,(if uses-argument
+	       `(list ,cmd p)
+	       cmd)))
+       (wire:wire-force-output wire))))
+
+
+
+
+;;;; Frame changing commands.
+
+(define-debugger-command "Up"
+  "Moves the \"Current Eval Server\" up one debugger frame."
+  :up)
+
+(define-debugger-command "Down"
+  "Moves the \"Current Eval Server\" down one debugger frame."
+  :down)
+
+(define-debugger-command "Top"
+  "Moves the \"Current Eval Server\" to the top of the debugging stack."
+  :top)
+
+(define-debugger-command "Bottom"
+  "Moves the \"Current Eval Server\" to the bottom of the debugging stack."
+  :bottom)
+
+(define-debugger-command "Frame"
+  "Moves the \"Current Eval Server\" to the absolute debugger frame number
+   indicated by the prefix argument."
+  :frame
+  :uses-argument t)
+
+
+
+
+;;;; In and Out commands.
+
+(define-debugger-command "Quit"
+  "In the \"Current Eval Server\", throws to top level out of the debugger."
+  :quit)
+
+(define-debugger-command "Go"
+  "In the \"Current Eval Server\", tries the CONTINUE restart."
+  :go)
+
+(define-debugger-command "Abort"
+  "In the \"Current Eval Server\", execute the previous ABORT restart."
+  :abort)
+
+(define-debugger-command "Restart"
+  "In the \"Current Eval Server\", executes the restart indicated by the
+   prefix argument."
+  :restart
+  :uses-argument t)
+
+
+
+
+;;;; Information commands.
+
+(define-debugger-command "Help"
+  "In the \"Current Eval Server\", prints the debugger's help text."
+  :help)
+
+(define-debugger-command "Error"
+  "In the \"Current Eval Server\", print the error condition and restart cases
+   upon entering the debugger."
+  :error)
+
+(define-debugger-command "Backtrace"
+  "Executes the debugger's BACKTRACE command."
+  :backtrace)
+
+(define-debugger-command "Print"
+  "In the \"Current Eval Server\", prints a representation of the debugger's
+   current frame."
+  :print)
+
+(define-debugger-command "Verbose Print"
+  "In the \"Current Eval Server\", prints a representation of the debugger's
+   current frame without elipsis."
+  :vprint)
+
+(define-debugger-command "List Locals"
+  "In the \"Current Eval Server\", prints the local variables for the debugger's
+   current frame."
+  :list-locals)
+
+(define-debugger-command "Source"
+  "In the \"Current Eval Server\", prints the source form for the debugger's
+   current frame."
+  :source)
+
+(define-debugger-command "Verbose Source"
+  "In the \"Current Eval Server\", prints the source form for the debugger's
+   current frame with surrounding forms for context."
+  :vsource)
+
+
+
+
+;;;; Source editing.
+
+;;; "Debug Edit Source" -- Command.
+;;;
+;;; The :edit-source command in the slave debugger initiates a synchronous RPC
+;;; into the editor via the wire in *terminal-io*, a typescript stream.  This
+;;; routine takes the necessary values, a file and source-path, and changes the
+;;; editor's state to display that location.
+;;;
+;;; This command has to wait on SERVE-EVENT until some special is set by the
+;;; RPC routine saying it is okay to return to the editor's top level.
+;;;
+(defvar *debug-editor-source-data* nil)
+(defvar *in-debug-edit-source* nil)
+
+(defcommand "Debug Edit Source" (p)
+  "Given the \"Current Eval Server\"'s current debugger frame, place the user
+   at the location's source in the editor."
+  "Given the \"Current Eval Server\"'s current debugger frame, place the user
+   at the location's source in the editor."
+  (declare (ignore p))
+  (let* ((server-info (get-current-eval-server t))
+	 (wire (server-info-wire server-info)))
+    ;;
+    ;; Tell the slave to tell the editor some source info.
+    (wire:remote wire
+      (ts-stream-accept-input
+       (ts-data-stream (server-info-slave-info server-info))
+       :edit-source))
+    (wire:wire-force-output wire)
+    ;;
+    ;; Wait for the source info.
+    (let ((*debug-editor-source-data* nil)
+	  (*in-debug-edit-source* t))
+      (catch 'blow-debug-edit-source
+	(loop
+	  (system:serve-event)
+	  (when *debug-editor-source-data* (return)))))))
+
+;;; EDIT-SOURCE-LOCATION -- Internal Interface.
+;;;
+;;; The slave calls this in the editor when the debugger gets an :edit-source
+;;; command.  This receives the information necessary to take the user in
+;;; Hemlock to the source location, and does it.
+;;;
+(defun edit-source-location (name source-created-date tlf-offset
+			     local-tlf-offset char-offset form-number)
+  (let ((pn (pathname name)))
+    (unless (probe-file pn)
+      (editor-error "Source file no longer exists: ~A." name))
+    (multiple-value-bind (buffer newp) (find-file-buffer pn)
+      (let ((date (buffer-write-date buffer))
+	    (point (buffer-point buffer)))
+	(when newp (push-buffer-mark (copy-mark point) nil))
+	(buffer-start point)
+	;;
+	;; Get to the top-level form in the buffer.
+	(cond ((buffer-modified buffer)
+	       (loud-message "Buffer has been modified.  Using form offset ~
+			      instead of character position.")
+	       (dotimes (i local-tlf-offset) 
+		 (pre-command-parse-check point)
+		 (form-offset point 1)))
+	      ((not date)
+	       (loud-message "Cannot compare write dates.  Assuming source ~
+			      has not been modified -- ~A."
+			     name)
+	       (character-offset point char-offset))
+	      ((= source-created-date date)
+	       (character-offset point char-offset))
+	      (t
+	       (loud-message "File has been modified since reading the source.  ~
+			      Using form offset instead of character position.")
+	       (dotimes (i local-tlf-offset) 
+		 (pre-command-parse-check point)
+		 (form-offset point 1))))
+	;;
+	;; Read our form, get form-number translations, get the source-path,
+	;; and make it usable.
+	;;
+	;; NOTE: Here READ is used in the editor lisp to look at a form
+	;; that the compiler has digested in the slave lisp. The editor
+	;; does not have the same environment at the slave so bad things
+	;; can happen if READ hits a #. reader macro (like unknown package
+	;; or undefined function errors) which can break the editor. This
+	;; code basically inhibits the read-time eval. This doesn't always
+	;; work right as the compiler may be seeing a different form structure
+	;; and the compiler's version of PATH may not match the editor's.
+	;; The main trouble seen in testing is that the 'form-number'
+	;; supplied by the compiler was one more than what the vector
+	;; returned by form-number-translations contained. For lack of a
+	;; better solution, I (pw) just limit the form-number to legal range.
+	;; This has worked ok on test code but may be off for some 
+	;; forms. At least the editor won't break.
+
+	(let* ((vector (di:form-number-translations
+			(with-input-from-region
+			    (s (region point (buffer-end-mark buffer)))
+			  (let ((*read-suppress* t))
+			    (read s)))
+			tlf-offset))
+	       ;; Don't signal error on index overrun.It may be due
+	       ;; to read-time eval getting form editing blind to
+	       ;; editor
+	       (index (min form-number (1- (length vector))))
+	       (path (nreverse (butlast (cdr (svref vector index))))))
+	  ;;
+	  ;; Walk down to the form.  Change to buffer in case we get an error
+	  ;; while finding the form.
+	  (change-to-buffer buffer)
+	  (mark-to-debug-source-path point path)))))
+  (setf *debug-editor-source-data* t)
+  ;;
+  ;; While Hemlock was setting up the source edit, the user could have typed
+  ;; while looking at a buffer no longer current when the commands execute.
+  (clear-editor-input *editor-input*))
+
+;;; CANNOT-EDIT-SOURCE-LOCATION -- Interface.
+;;;
+;;; The slave calls this when the debugger command "EDIT-SOURCE" runs, and the
+;;; slave cannot give the editor source information.
+;;;
+(defun cannot-edit-source-location ()
+  (loud-message "Can't edit source.")
+  (when *in-debug-edit-source*
+    (throw 'blow-debug-edit-source nil)))
+
+
+
+;;;; Breakpoints.
+
+;;;
+;;; Breakpoint information for editor management.
+;;;
+
+;;; This holds all the stuff we might want to know about a breakpoint in some
+;;; slave.
+;;;
+(defstruct (breakpoint-info (:print-function print-breakpoint-info)
+			    (:constructor make-breakpoint-info
+					  (slave buffer remote-object name)))
+  (slave nil :type server-info)
+  (buffer nil :type buffer)
+  (remote-object nil :type wire:remote-object)
+  (name nil :type simple-string))
+;;;
+(defun print-breakpoint-info (obj str n)
+  (declare (ignore n))
+  (format str "#<Breakpoint-Info for ~S>" (breakpoint-info-name obj)))
+
+(defvar *breakpoints* nil)
+
+(macrolet ((frob (name accessor)
+	     `(defun ,name (key)
+		(let ((res nil))
+		  (dolist (bpt-info *breakpoints* res)
+		    (when (eq (,accessor bpt-info) key)
+		      (push bpt-info res)))))))
+  (frob slave-breakpoints breakpoint-info-slave)
+  (frob buffer-breakpoints breakpoint-info-buffer))
+
+(defun delete-breakpoints-buffer-hook (buffer)
+  (let ((server-info (value current-eval-server)))
+    (when server-info
+      (let ((bpts (buffer-breakpoints buffer))
+	    (wire (server-info-wire server-info)))
+	  (dolist (b bpts)
+	    (setf *breakpoints* (delete b *breakpoints*))
+	    (when wire
+	      (wire:remote wire
+		(di:delete-breakpoint (breakpoint-info-remote-object b))))
+	(when wire
+	  (wire:wire-force-output wire)))))))
+;;;
+(add-hook delete-buffer-hook 'delete-breakpoints-buffer-hook)
+
+;;;
+;;; Setting breakpoints.
+;;;
+
+;;; "Debug Breakpoint" uses this to prompt for :function-end and
+;;; :function-start breakpoints.
+;;;
+(defvar *function-breakpoint-strings*
+  (make-string-table :initial-contents
+		     '(("Start" . :function-start) ("End" . :function-end))))
+;;;
+;;; Maybe this should use the wire level directly and hold onto remote-objects
+;;; identifying the breakpoints.  Then we could write commands to show where
+;;; the breakpoints were and to individually deactivate or delete them.  As it
+;;; is now we probably have to delete all for a given function.  What about
+;;; setting user supplied breakpoint hook-functions, or Hemlock supplying a
+;;; nice set such as something to simply print all locals at a certain
+;;; location.
+;;;
+(defcommand "Debug Breakpoint" (p)
+  "This tries to set a breakpoint in the \"Current Eval Server\" at the
+   location designated by the current point.  If there is no known code
+   location at the point, then this moves the point to the closest location
+   before the point.  With an argument, this sets a breakpoint at the start
+   or end of the function, prompting the user for which one to use."
+  "This tries to set a breakpoint in the \"Current Eval Server\" at the
+   location designated by the current point.  If there is no known code
+   location at the point, then this moves the point to the closest location
+   before the point.  With an argument, this sets a breakpoint at the start
+   or end of the function, prompting the user for which one to use."
+  (let ((point (current-point)))
+    (pre-command-parse-check point)
+    (let ((name (find-defun-for-breakpoint point)))
+      (if p
+	  (multiple-value-bind (str place)
+			       (prompt-for-keyword
+				(list *function-breakpoint-strings*)
+				:prompt "Set breakpoint at function: "
+				:default :start :default-string "Start")
+	    (declare (ignore str))
+	    (set-breakpoint-in-slave (get-current-eval-server t) name place))
+	  (let* ((path (find-path-for-breakpoint point))
+		 (server-info (get-current-eval-server t))
+		 (res (set-breakpoint-in-slave server-info name path)))
+	    (cond ((not res)
+		   (message "No code locations correspond with point."))
+		  ((wire:remote-object-p res)
+		   (push (make-breakpoint-info server-info (current-buffer)
+					       res name)
+			 *breakpoints*)
+		   (message "Breakpoint set."))
+		  (t
+		   (resolve-ambiguous-breakpoint-location server-info
+							  name res))))))))
+
+;;; FIND-PATH-FOR-BREAKPOINT -- Internal.
+;;;
+;;; This walks up from point to the beginning of its containing DEFUN to return
+;;; the pseudo source-path (no form-number, no top-level form offset, and in
+;;; descent order from start of the DEFUN).
+;;;
+(defun find-path-for-breakpoint (point)
+  (with-mark ((m point)
+	      (end point))
+    (let ((path nil))
+      (top-level-offset end -1)
+      (with-mark ((containing-form m))
+	(loop
+	  (when (mark= m end) (return))
+	  (backward-up-list containing-form)
+	  (do ((count 0 (1+ count)))
+	      ((mark= m containing-form)
+	       ;; Count includes moving from the first form inside the
+	       ;; containing-form paren to the outside of the containing-form
+	       ;; paren -- one too many.
+	       (push (1- count) path))
+	    (form-offset m -1))))
+      path)))
+
+;;; SET-BREAKPOINT-IN-SLAVE -- Internal.
+;;;
+;;; This tells the slave to set a breakpoint for name.  Path is a modified
+;;; source-path (with no form-number or top-level-form offset) or a symbol
+;;; (:function-start or :function-end).  If the server dies while evaluating
+;;; form, then this signals an editor-error.
+;;;
+(defun set-breakpoint-in-slave (server-info name path)
+  (when (server-info-notes server-info)
+    (editor-error "Server ~S is currently busy.  See \"List Operations\"."
+		  (server-info-name server-info)))
+  (multiple-value-bind (res error)
+		       (wire:remote-value (server-info-wire server-info)
+			 (di:set-breakpoint-for-editor (value current-package)
+						       name path))
+    (when error (editor-error "The server died before finishing."))
+    res))
+
+;;; RESOLVE-AMBIGUOUS-BREAKPOINT-LOCATION -- Internal.
+;;;
+;;; This helps the user select an ambiguous code location for "Debug
+;;; Breakpoint".
+;;;
+(defun resolve-ambiguous-breakpoint-location (server-info name locs)
+  (declare (list locs))
+  (let ((point (current-point))
+	(loc-num (length locs))
+	(count 1)
+	(cur-loc locs))
+    (flet ((show-loc ()
+	     (top-level-offset point -1)
+	     (mark-to-debug-source-path point (cdar cur-loc))))
+      (show-loc)
+      (command-case (:prompt `("Ambiguous location ~D of ~D: " ,count ,loc-num)
+		      :help "Pick a location to set a breakpoint."
+		      :change-window nil)
+	(#\space "Move point to next possible location."
+	  (setf cur-loc (cdr cur-loc))
+	  (cond (cur-loc
+		 (incf count))
+		(t
+		 (setf cur-loc locs)
+		 (setf count 1)))
+	  (show-loc)
+	  (reprompt))
+	(:confirm "Choose the current location."
+	  (let ((res (wire:remote-value (server-info-wire server-info)
+		       (di:set-location-breakpoint-for-editor (caar cur-loc)))))
+	    (unless (wire:remote-object-p res)
+	      (editor-error "Couldn't set breakpoint from location?"))
+	    (push (make-breakpoint-info server-info (current-buffer) res name)
+		  *breakpoints*))
+	  (message "Breakpoint set."))))))
+
+;;; MARK-TO-DEBUG-SOURCE-PATH -- Internal.
+;;;
+;;; This takes a mark at the beginning of a top-level form and modified debugger
+;;; source-path.  Path has no form number or top-level-form offset element, and
+;;; it has been reversed to actually be usable.
+;;;
+(defun mark-to-debug-source-path (mark path)
+  (let ((quote-or-function nil))
+    (pre-command-parse-check mark)
+    (dolist (n path)
+      (when quote-or-function
+	(editor-error
+	 "Apparently settled on the symbol QUOTE or FUNCTION via their ~
+	  read macros, which is odd, but furthermore there seems to be ~
+	  more source-path left."))
+      (unless (form-offset mark 1)
+	;; Want to use the following and delete the next FORM-OFFSET -1.
+	;; (scan-direction-valid mark t (or :open-paren :prefix))
+	(editor-error
+	 "Ran out of text in buffer with more source-path remaining."))
+      (form-offset mark -1)
+      (ecase (next-character mark)
+	(#\(
+	 (mark-after mark)
+	 (form-offset mark n))
+	(#\'
+	 (case n
+	   (0 (setf quote-or-function t))
+	   (1 (mark-after mark))
+	   (t (editor-error "Next form is QUOTE, but source-path index ~
+			     is other than zero or one."))))
+	(#\#
+	 (case (next-character (mark-after mark))
+	   (#\'
+	    (case n
+	      (0 (setf quote-or-function t))
+	      (1 (mark-after mark))
+	      (t (editor-error "Next form is FUNCTION, but source-path ~
+				index is other than zero or one."))))
+	   (t (editor-error
+	       "Can only parse ' and #' read macros."))))))
+    ;; Get to the beginning of the form.
+    (form-offset mark 1)
+    (form-offset mark -1)))
+
+;;;
+;;; Deleting breakpoints.
+;;;
+
+(defhvar "Delete Breakpoints Confirm"
+  "This determines whether \"Debug Delete Breakpoints\" should ask for
+   confirmation before deleting breakpoints."
+  :value t)
+
+(defcommand "Debug Delete Breakpoints" (p)
+  "This deletes all breakpoints for the named DEFUN containing the point.
+   This affects the \"Current Eval Server\"."
+  "This deletes all breakpoints for the named DEFUN containing the point.
+   This affects the \"Current Eval Server\"."
+  (declare (ignore p))
+  (let* ((server-info (get-current-eval-server t))
+	 (wire (server-info-wire server-info))
+	 (name (find-defun-for-breakpoint (current-point)))
+	 (bpts (slave-breakpoints server-info)))
+    (cond ((not bpts)
+	   (message "No breakpoints recorded for ~A." name))
+	  ((or (not (value delete-breakpoints-confirm))
+	       (prompt-for-y-or-n :prompt `("Delete breakpoints for ~A? " ,name)
+				  :default t
+				  :default-string "Y"))
+	   (dolist (b bpts)
+	     (when (string= name (breakpoint-info-name b))
+	       (setf *breakpoints* (delete b *breakpoints*))
+	       (wire:remote wire
+		 (di:delete-breakpoint-for-editor
+		  (breakpoint-info-remote-object b)))))
+	   (wire:wire-force-output wire)))))
+
+;;;
+;;; Breakpoint utilities.
+;;;
+
+;;; FIND-DEFUN-FOR-BREAKPOINT -- Internal.
+;;;
+;;; This returns as a string the name of the DEFUN containing point.  It
+;;; signals any errors necessary to ensure "we are in good form".
+;;;
+(defun find-defun-for-breakpoint (point)
+  (with-mark ((m1 point)
+	      (m2 point))
+    (unless (top-level-offset m2 -1)
+      (editor-error "Must be inside a DEFUN."))
+    ;;
+    ;; Check for DEFUN.
+    (mark-after (move-mark m1 m2))
+    (unless (find-attribute m1 :whitespace #'zerop)
+      (editor-error "Must be inside a DEFUN."))
+    (word-offset (move-mark m2 m1) 1)
+    (unless (string-equal (region-to-string (region m1 m2)) "defun")
+      (editor-error "Must be inside a DEFUN."))
+    ;;
+    ;; Find name.
+    (unless (find-attribute m2 :whitespace #'zerop)
+      (editor-error "Function unnamed?"))
+    (form-offset (move-mark m1 m2) 1)
+    (region-to-string (region m2 m1))))
+
+
+
+
+;;;; Miscellaneous commands.
+
+(define-debugger-command "Flush Errors"
+  "In the \"Current Eval Server\", toggles whether the debugger ignores errors
+   or recursively enters itself."
+  :flush)
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/dired.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/dired.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/dired.lisp	(revision 13309)
@@ -0,0 +1,701 @@
+;;; -*- Log: hemlock.log; Package: dired -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains site dependent code for dired.
+;;; Written by Bill Chiles.
+;;;
+
+(defpackage "DIRED"
+  (:shadow "RENAME-FILE" "DELETE-FILE")
+  (:export "COPY-FILE" "RENAME-FILE" "FIND-FILE" "DELETE-FILE"
+	   "MAKE-DIRECTORY"
+	   "*UPDATE-DEFAULT*" "*CLOBBER-DEFAULT*" "*RECURSIVE-DEFAULT*"
+	   "*REPORT-FUNCTION*" "*ERROR-FUNCTION*" "*YESP-FUNCTION*"
+	   "PATHNAMES-FROM-PATTERN"))
+  
+(in-package "DIRED")
+
+
+
+;;;; Exported parameters.
+
+(defparameter *update-default* nil
+  "Update arguments to utilities default to this value.")
+
+(defparameter *clobber-default* t
+  "Clobber arguments to utilities default to this value.")
+
+(defparameter *recursive-default* nil
+  "Recursive arguments to utilities default to this value.")
+
+
+
+
+;;;; WILDCARDP
+
+(defconstant wildcard-char #\*
+  "Wildcard designator for file names will match any substring.")
+
+(defmacro wildcardp (file-namestring)
+  `(position wildcard-char (the simple-string ,file-namestring) :test #'char=))
+
+
+
+
+;;;; User interaction functions, variable declarations, and their defaults.
+
+(defun default-error-function (string &rest args)
+  (apply #'error string args))
+;;;
+(defvar *error-function* #'default-error-function
+  "This function is called when an error is encountered in dired code.")
+
+(defun default-report-function (string &rest args)
+  (apply #'format t string args))
+;;;
+(defvar *report-function* #'default-report-function
+  "This function is called when the user needs to be informed of something.")
+
+(defun default-yesp-function (string &rest args)
+  (apply #'format t string args)
+  (let ((answer (nstring-downcase (string-trim '(#\space #\tab) (read-line)))))
+    (declare (simple-string answer))
+    (or (string= answer "")
+	(string= answer "y")
+	(string= answer "yes")
+	(string= answer "ye"))))
+;;;
+(defvar *yesp-function* #'default-yesp-function
+  "Function to query the user about clobbering an already existent file.")
+
+
+
+
+;;;; Copy-File
+
+;;; WILD-MATCH objects contain information about wildcard matches.  File is the
+;;; Sesame namestring of the file matched, and substitute is a substring of the
+;;; file-namestring of file.
+;;;
+(defstruct (wild-match (:print-function print-wild-match)
+		       (:constructor make-wild-match (file substitute)))
+  file
+  substitute)
+
+(defun print-wild-match (obj str n)
+  (declare (ignore n))
+  (format str "#<Wild-Match  ~S  ~S>"
+	  (wild-match-file obj) (wild-match-substitute obj)))
+
+
+(defun copy-file (spec1 spec2 &key (update *update-default*)
+				   (clobber *clobber-default*)
+				   (directory () directoryp))
+  "Copy file spec1 to spec2.  A single wildcard is acceptable, and directory
+   names may be used.  If spec1 and spec2 are both directories, then a
+   recursive copy is done of the files and subdirectory structure of spec1;
+   if spec2 is in the subdirectory structure of spec1, the recursion will
+   not descend into it.  Use spec1/* to copy only the files in spec1 to
+   directory spec2.  If spec2 is a directory, and spec1 is a file, then
+   spec1 is copied into spec2 with the same pathname-name.  Files are
+   copied maintaining the source's write date.  If :update is non-nil, then
+   files are only copied if the source is newer than the destination, still
+   maintaining the source's write date; the user is not warned if the
+   destination is newer (not the same write date) than the source.  If
+   :clobber and :update are nil, then if any file spec2 already exists, the
+   user will be asked whether it should be overwritten or not."
+  (cond
+   ((not directoryp)
+    (let* ((ses-name1 (ext:unix-namestring spec1 t))
+	   (exists1p (unix:unix-file-kind ses-name1))
+	   (ses-name2 (ext:unix-namestring spec2 nil))
+	   (pname1 (pathname ses-name1))
+	   (pname2 (pathname ses-name2))
+	   (dirp1 (directoryp pname1))
+	   (dirp2 (directoryp pname2))
+	   (wildp1 (wildcardp (file-namestring pname1)))
+	   (wildp2 (wildcardp (file-namestring pname2))))
+      (when (and dirp1 wildp1)
+	(funcall *error-function*
+		 "Cannot have wildcards in directory names -- ~S." pname1))
+      (when (and dirp2 wildp2)
+	(funcall *error-function*
+		 "Cannot have wildcards in directory names -- ~S." pname2))
+      (when (and dirp1 (not dirp2))
+	(funcall *error-function*
+		 "Cannot handle spec1 being a directory and spec2 a file."))
+      (when (and wildp2 (not wildp1))
+	(funcall *error-function*
+		 "Cannot handle destination having wildcards without ~
+		 source having wildcards."))
+      (when (and wildp1 (not wildp2) (not dirp2))
+	(funcall *error-function*
+		 "Cannot handle source with wildcards and destination ~
+		 without, unless destination is a directory."))
+      (cond ((and dirp1 dirp2)
+	     (unless (directory-existsp ses-name1)
+	       (funcall *error-function*
+			"Directory does not exist -- ~S." pname1))
+	     (unless (directory-existsp ses-name2)
+	       (enter-directory ses-name2))
+	     (recursive-copy pname1 pname2 update clobber pname2
+			     ses-name1 ses-name2))
+	    (dirp2
+	     ;; merge pname2 with pname1 to pick up a similar file-namestring.
+	     (copy-file-1 pname1 wildp1 exists1p
+			  (merge-pathnames pname2 pname1)
+			  wildp1 update clobber))
+	    (t (copy-file-1 pname1 wildp1 exists1p
+			    pname2 wildp2 update clobber)))))
+    (directory
+     (when (pathname-directory spec1)
+       (funcall *error-function*
+		"Spec1 is just a pattern when supplying directory -- ~S."
+		spec1))
+     (let* ((pname2 (pathname (ext:unix-namestring spec2 nil)))
+	    (dirp2 (directoryp pname2))
+	    (wildp1 (wildcardp spec1))
+	    (wildp2 (wildcardp (file-namestring pname2))))
+       (unless wildp1
+	 (funcall *error-function*
+		  "Pattern, ~S, does not contain a wildcard."
+		  spec1))
+       (when (and (not wildp2) (not dirp2))
+	 (funcall *error-function*
+		  "Cannot handle source with wildcards and destination ~
+		   without, unless destination is a directory."))
+       (copy-wildcard-files spec1 wildp1
+			    (if dirp2 (merge-pathnames pname2 spec1) pname2)
+			    (if dirp2 wildp1 wildp2)
+			    update clobber directory))))
+  (values))
+
+;;; RECURSIVE-COPY takes two pathnames that represent directories, and
+;;; the files in pname1 are copied into pname2, recursively descending into
+;;; subdirectories.  If a subdirectory of pname1 does not exist in pname2,
+;;; it is created.  Pname1 is known to exist.  Forbidden-dir is originally
+;;; the same as pname2; this keeps us from infinitely recursing if pname2
+;;; is in the subdirectory structure of pname1.  Returns t if some file gets
+;;; copied.
+;;; 
+(defun recursive-copy (pname1 pname2 update clobber
+		       forbidden-dir ses-name1 ses-name2)
+  (funcall *report-function* "~&~S  ==>~%  ~S~%" ses-name1 ses-name2)
+  (dolist (spec (directory (directory-namestring pname1)))
+    (let ((spec-ses-name (namestring spec)))
+      (if (directoryp spec)
+	  (unless (equal (pathname spec-ses-name) forbidden-dir)
+	    (let* ((dir2-pname (merge-dirs spec pname2))
+		   (dir2-ses-name (namestring dir2-pname)))
+	      (unless (directory-existsp dir2-ses-name)
+		(enter-directory dir2-ses-name))
+	      (recursive-copy spec dir2-pname update clobber forbidden-dir
+			      spec-ses-name dir2-ses-name)
+	      (funcall *report-function* "~&~S  ==>~%  ~S~%" ses-name1
+		       ses-name2)))
+	  (copy-file-2 spec-ses-name
+		       (namestring (merge-pathnames pname2 spec))
+		       update clobber)))))
+
+;;; MERGE-DIRS picks out the last directory name in the pathname pname1 and
+;;; adds it to the end of the sequence of directory names from pname2, returning
+;;; a pathname.
+;;;
+#|
+(defun merge-dirs (pname1 pname2)
+  (let* ((dirs1 (pathname-directory pname1))
+	 (dirs2 (pathname-directory pname2))
+	 (dirs2-len (length dirs2))
+	 (new-dirs2 (make-array (1+ dirs2-len))))
+    (declare (simple-vector dirs1 dirs2 new-dirs2))
+    (replace new-dirs2 dirs2)
+    (setf (svref new-dirs2 dirs2-len)
+	  (svref dirs1 (1- (length dirs1))))
+    (make-pathname :directory new-dirs2 :device :absolute)))
+|#
+
+(defun merge-dirs (pname1 pname2)
+  (let* ((dirs1 (pathname-directory pname1))
+	 (dirs2 (pathname-directory pname2))
+	 (dirs2-len (length dirs2))
+	 (new-dirs2 (make-list (1+ dirs2-len))))
+    (replace new-dirs2 dirs2)
+    (setf (nth dirs2-len new-dirs2)
+	  (nth (1- (length dirs1)) dirs1))
+    (make-pathname :directory new-dirs2 :device :unspecific)))
+
+;;; COPY-FILE-1 takes pathnames which either both contain a single wildcard
+;;; or none.  Wildp1 and Wildp2 are either nil or indexes into the
+;;; file-namestring of pname1 and pname2, respectively, indicating the position
+;;; of the wildcard character.  If there is no wildcard, then simply call
+;;; COPY-FILE-2; otherwise, resolve the wildcard and copy those matching files.
+;;;
+(defun copy-file-1 (pname1 wildp1 exists1p pname2 wildp2 update clobber)
+  (if wildp1 
+      (copy-wildcard-files pname1 wildp1 pname2 wildp2 update clobber)
+      (let ((ses-name1 (namestring pname1)))
+	(unless exists1p (funcall *error-function*
+				  "~S does not exist." ses-name1))
+	(copy-file-2 ses-name1 (namestring pname2) update clobber))))
+
+(defun copy-wildcard-files (pname1 wildp1 pname2 wildp2 update clobber
+				   &optional directory)
+  (multiple-value-bind (dst-before dst-after)
+		       (before-wildcard-after (file-namestring pname2) wildp2)
+    (dolist (match (resolve-wildcard pname1 wildp1 directory))
+      (copy-file-2 (wild-match-file match)
+		   (namestring (concatenate 'simple-string
+					    (directory-namestring pname2)
+					    dst-before
+					    (wild-match-substitute match)
+					    dst-after))
+		   update clobber))))
+
+;;; COPY-FILE-2 copies ses-name1 to ses-name2 depending on the values of update
+;;; and clobber, with respect to the documentation of COPY-FILE.  If ses-name2
+;;; doesn't exist, then just copy it; otherwise, if update, then only copy it
+;;; if the destination's write date precedes the source's, and if not clobber
+;;; and not update, then ask the user before doing the copy.
+;;;
+(defun copy-file-2 (ses-name1 ses-name2 update clobber)
+  (let ((secs1 (get-write-date ses-name1)))
+    (cond ((not (probe-file ses-name2))
+	   (do-the-copy ses-name1 ses-name2 secs1))
+	  (update
+	   (let ((secs2 (get-write-date ses-name2)))
+	     (cond (clobber
+		    (do-the-copy ses-name1 ses-name2 secs1))
+		   ((and (> secs2 secs1)
+			 (funcall *yesp-function*
+				  "~&~S  ==>  ~S~%  ~
+				  ** Destination is newer than source.  ~
+				  Overwrite it? "
+				  ses-name1 ses-name2))
+		    (do-the-copy ses-name1 ses-name2 secs1))
+		   ((< secs2 secs1)
+		    (do-the-copy ses-name1 ses-name2 secs1)))))
+	  ((not clobber)
+	   (when (funcall *yesp-function*
+			  "~&~S  ==>  ~S~%  ** Destination already exists.  ~
+			  Overwrite it? "
+			  ses-name1 ses-name2)
+	     (do-the-copy ses-name1 ses-name2 secs1)))
+	  (t (do-the-copy ses-name1 ses-name2 secs1)))))
+
+(defun do-the-copy (ses-name1 ses-name2 secs1)
+  (let* ((fd (open-file ses-name1)))
+    (unwind-protect
+	(multiple-value-bind (data byte-count mode)
+			     (read-file fd ses-name1)
+	  (unwind-protect (write-file ses-name2 data byte-count mode)
+	    (system:deallocate-system-memory data byte-count)))
+      (close-file fd)))
+  (set-write-date ses-name2 secs1)
+  (funcall *report-function* "~&~S  ==>~%  ~S~%" ses-name1 ses-name2))
+
+
+
+;;;; Rename-File
+
+(defun rename-file (spec1 spec2 &key (clobber *clobber-default*)
+			  (directory () directoryp))
+  "Rename file spec1 to spec2.  A single wildcard is acceptable, and spec2 may
+   be a directory with the result spec being the merging of spec2 with spec1.
+   If clobber is nil and spec2 exists, then the user will be asked to confirm
+   the renaming.  As with Unix mv, if you are renaming a directory, don't
+   specify the trailing slash."
+  (cond
+   ((not directoryp)
+    (let* ((ses-name1 (ext:unix-namestring spec1 t))
+	   (exists1p (unix:unix-file-kind ses-name1))
+	   (ses-name2 (ext:unix-namestring spec2 nil))
+	   (pname1 (pathname ses-name1))
+	   (pname2 (pathname ses-name2))
+	   (dirp2 (directoryp pname2))
+	   (wildp1 (wildcardp (file-namestring pname1)))
+	   (wildp2 (wildcardp (file-namestring pname2))))
+      (if (and dirp2 wildp2)
+	  (funcall *error-function*
+		   "Cannot have wildcards in directory names -- ~S." pname2))
+      (if (and wildp2 (not wildp1))
+	  (funcall *error-function*
+		   "Cannot handle destination having wildcards without ~
+		   source having wildcards."))
+      (if (and wildp1 (not wildp2) (not dirp2))
+	  (funcall *error-function*
+		   "Cannot handle source with wildcards and destination ~
+		   without, unless destination is a directory."))
+      (if dirp2
+	  (rename-file-1 pname1 wildp1 exists1p (merge-pathnames pname2
+								 pname1)
+			 wildp1 clobber)
+	  (rename-file-1 pname1 wildp1 exists1p pname2 wildp2 clobber))))
+    (directory
+     (when (pathname-directory spec1)
+       (funcall *error-function*
+		"Spec1 is just a pattern when supplying directory -- ~S."
+		spec1))
+
+     (let* ((pname2 (pathname (ext:unix-namestring spec2 nil)))
+	    (dirp2 (directoryp pname2))
+	    (wildp1 (wildcardp spec1))
+	    (wildp2 (wildcardp (file-namestring pname2))))
+       (unless wildp1
+	 (funcall *error-function*
+		  "Pattern, ~S, does not contain a wildcard."
+		  spec1))
+       (when (and (not wildp2) (not dirp2))
+	 (funcall *error-function*
+		  "Cannot handle source with wildcards and destination ~
+		   without, unless destination is a directory."))
+       (rename-wildcard-files spec1 wildp1
+			      (if dirp2 (merge-pathnames pname2 spec1) pname2)
+			      (if dirp2 wildp1 wildp2)
+			      clobber directory))))
+  (values))
+
+;;; RENAME-FILE-1 takes pathnames which either both contain a single wildcard
+;;; or none.  Wildp1 and Wildp2 are either nil or indexes into the
+;;; file-namestring of pname1 and pname2, respectively, indicating the position
+;;; of the wildcard character.  If there is no wildcard, then simply call
+;;; RENAME-FILE-2; otherwise, resolve the wildcard and rename those matching files.
+;;;
+(defun rename-file-1 (pname1 wildp1 exists1p pname2 wildp2 clobber)
+  (if wildp1
+      (rename-wildcard-files pname1 wildp1 pname2 wildp2 clobber)
+      (let ((ses-name1 (namestring pname1)))
+	(unless exists1p (funcall *error-function*
+				  "~S does not exist." ses-name1))
+	(rename-file-2 ses-name1 (namestring pname2) clobber))))
+
+(defun rename-wildcard-files (pname1 wildp1 pname2 wildp2 clobber
+				   &optional directory)
+  (multiple-value-bind (dst-before dst-after)
+		       (before-wildcard-after (file-namestring pname2) wildp2)
+    (dolist (match (resolve-wildcard pname1 wildp1 directory))
+      (rename-file-2 (wild-match-file match)
+		     (namestring (concatenate 'simple-string
+					      (directory-namestring pname2)
+					      dst-before
+					      (wild-match-substitute match)
+					      dst-after))
+		     clobber))))
+
+(defun rename-file-2 (ses-name1 ses-name2 clobber)
+  (cond ((and (probe-file ses-name2) (not clobber))
+	 (when (funcall *yesp-function*
+			"~&~S  ==>  ~S~%  ** Destination already exists.  ~
+			Overwrite it? "
+			ses-name1 ses-name2)
+	   (sub-rename-file ses-name1 ses-name2)
+	   (funcall *report-function* "~&~S  ==>~%  ~S~%" ses-name1 ses-name2)))
+	(t (sub-rename-file ses-name1 ses-name2)
+	   (funcall *report-function* "~&~S  ==>~%  ~S~%" ses-name1 ses-name2))))
+
+
+
+
+;;;; Find-File
+
+(defun find-file (file-name &optional (directory "")
+			    (find-all-p nil find-all-suppliedp))
+  "Find the file with file-namestring file recursively looking in directory.
+   If find-all-p is non-nil, then do not stop searching upon finding the first
+   occurance of file.  File may contain a single wildcard, which causes
+   find-all-p to default to t instead of nil."
+  (let* ((file (coerce file-name 'simple-string))
+	 (wildp (wildcardp file))
+	 (find-all-p (if find-all-suppliedp find-all-p wildp)))
+    (declare (simple-string file))
+    (catch 'found-file
+      (if wildp
+	  (multiple-value-bind (before after)
+			       (before-wildcard-after file wildp)
+	    (find-file-aux file directory find-all-p before after))
+	  (find-file-aux file directory find-all-p))))
+  (values))
+
+(defun find-file-aux (the-file directory find-all-p &optional before after)
+  (declare (simple-string the-file))
+  (dolist (spec (directory directory))
+    (let* ((spec-ses-name (namestring spec))
+	   (spec-file-name (file-namestring spec-ses-name)))
+      (declare (simple-string spec-ses-name spec-file-name))
+      (if (directoryp spec)
+	  (find-file-aux the-file spec find-all-p before after)
+	  (when (if before
+		    (find-match before after spec-file-name :no-cons)
+		    (string-equal the-file spec-file-name))
+	    (print spec-ses-name)
+	    (unless find-all-p (throw 'found-file t)))))))
+
+
+
+
+;;;; Delete-File
+
+;;; DELETE-FILE
+;;;    If spec is a directory, but recursive is nil, just pass the directory
+;;; down through, letting LISP:DELETE-FILE signal an error if the directory
+;;; is not empty.
+;;; 
+(defun delete-file (spec &key (recursive *recursive-default*)
+			      (clobber *clobber-default*))
+  "Delete spec asking confirmation on each file if clobber is nil.  A single
+   wildcard is acceptable.  If recursive is non-nil, then a directory spec may
+   be given to recursively delete the entirety of the directory and its
+   subdirectory structure.  An empty directory may be specified without
+   recursive being non-nil.  When specifying a directory, the trailing slash
+   must be included."
+  (let* ((ses-name (ext:unix-namestring spec t))
+	 (pname (pathname ses-name)) 
+	 (wildp (wildcardp (file-namestring pname)))
+	 (dirp (directoryp pname)))
+    (if dirp
+	(if recursive
+	    (recursive-delete pname ses-name clobber)
+	    (delete-file-2 ses-name clobber))
+	(delete-file-1 pname ses-name wildp clobber)))
+  (values))
+
+(defun recursive-delete (directory dir-ses-name clobber)
+  (dolist (spec (directory (directory-namestring directory)))
+    (let ((spec-ses-name (namestring spec)))
+      (if (directoryp spec)
+	  (recursive-delete (pathname spec-ses-name) spec-ses-name clobber)
+	  (delete-file-2 spec-ses-name clobber))))
+  (delete-file-2 dir-ses-name clobber))
+
+(defun delete-file-1 (pname ses-name wildp clobber)
+  (if wildp
+      (dolist (match (resolve-wildcard pname wildp))
+	(delete-file-2 (wild-match-file match) clobber))
+      (delete-file-2 ses-name clobber)))
+
+(defun delete-file-2 (ses-name clobber)
+  (when (or clobber (funcall *yesp-function* "~&Delete ~S? " ses-name))
+    (if (directoryp ses-name)
+	(delete-directory ses-name)
+	(lisp:delete-file ses-name))
+    (funcall *report-function* "~&~A~%" ses-name)))
+
+
+
+
+;;;; Wildcard resolution
+
+(defun pathnames-from-pattern (pattern files)
+  "Return a list of pathnames from files whose file-namestrings match
+   pattern.  Pattern must be a non-empty string and contains only one
+   asterisk.  Files contains no directories."
+  (declare (simple-string pattern))
+  (when (string= pattern "")
+    (funcall *error-function* "Must be a non-empty pattern."))
+  (unless (= (count wildcard-char pattern :test #'char=) 1)
+    (funcall *error-function* "Pattern must contain one asterisk."))
+  (multiple-value-bind (before after)
+		       (before-wildcard-after pattern (wildcardp pattern))
+    (let ((result nil))
+      (dolist (f files result)
+	(let* ((ses-namestring (namestring f))
+	       (f-namestring (file-namestring ses-namestring))
+	       (match (find-match before after f-namestring)))
+	  (when match (push f result)))))))
+
+
+;;; RESOLVE-WILDCARD takes a pathname with a wildcard and the position of the
+;;; wildcard character in the file-namestring and returns a list of wild-match
+;;; objects.  When directory is supplied, pname is just a pattern, or a
+;;; file-namestring.  It is an error for directory to be anything other than
+;;; absolute pathnames in the same directory.  Each wild-match object contains
+;;; the Sesame namestring of a file in the same directory as pname, or
+;;; directory, and a simple-string representing what the wildcard matched.
+;;;
+(defun resolve-wildcard (pname wild-pos &optional directory)
+  (multiple-value-bind (before after)
+		       (before-wildcard-after (if directory
+						  pname
+						  (file-namestring pname))
+					      wild-pos)
+    (let (result)
+      (dolist (f (or directory (directory (directory-namestring pname)))
+		 (nreverse result))
+	(unless (directoryp f)
+	  (let* ((ses-namestring (namestring f))
+		 (f-namestring (file-namestring ses-namestring))
+		 (match (find-match before after f-namestring)))
+	    (if match
+		(push (make-wild-match ses-namestring match) result))))))))
+
+;;; FIND-MATCH takes a "before wildcard" and "after wildcard" string and a
+;;; file-namestring.  If before and after match a substring of file-namestring
+;;; and are respectively left bound and right bound, then anything left in
+;;; between is the match returned.  If no match is found, nil is returned.
+;;; NOTE: if version numbers ever really exist, then this code will have to be
+;;; changed since the file-namestring of a pathname contains the version number.
+;;; 
+(defun find-match (before after file-namestring &optional no-cons)
+  (declare (simple-string before after file-namestring))
+  (let ((before-len (length before))
+	(after-len (length after))
+	(name-len (length file-namestring)))
+    (if (>= name-len (+ before-len after-len))
+	(let* ((start (if (string= before file-namestring
+				   :end1 before-len :end2 before-len)
+			  before-len))
+	       (end (- name-len after-len))
+	       (matchp (and start
+			    (string= after file-namestring :end1 after-len
+				     :start2 end :end2 name-len))))
+	  (if matchp
+	      (if no-cons
+		  t
+		  (subseq file-namestring start end)))))))
+
+(defun before-wildcard-after (file-namestring wild-pos)
+  (declare (simple-string file-namestring))
+  (values (subseq file-namestring 0 wild-pos)
+	  (subseq file-namestring (1+ wild-pos) (length file-namestring))))
+
+
+
+
+;;;; Miscellaneous Utilities (e.g., MAKEDIR).
+
+(defun make-directory (name)
+  "Creates directory name.  If name exists, then an error is signaled."
+  (let ((ses-name (ext:unix-namestring name nil)))
+    (when (unix:unix-file-kind ses-name)
+      (funcall *error-function* "Name already exists -- ~S" ses-name))
+    (enter-directory ses-name))
+  t)
+
+
+
+
+;;;; Mach Operations
+
+(defun open-file (ses-name)
+  (multiple-value-bind (fd err)
+		       (unix:unix-open ses-name unix:o_rdonly 0)
+    (unless fd
+      (funcall *error-function* "Opening ~S failed: ~A." ses-name err))
+    fd))
+
+(defun close-file (fd)
+  (unix:unix-close fd))
+
+(defun read-file (fd ses-name)
+  (multiple-value-bind (winp dev-or-err ino mode nlink uid gid rdev size)
+		       (unix:unix-fstat fd)
+    (declare (ignore ino nlink uid gid rdev))
+    (unless winp (funcall *error-function*
+			  "Opening ~S failed: ~A."  ses-name dev-or-err))
+    (let ((storage (system:allocate-system-memory size)))
+      (multiple-value-bind (read-bytes err)
+			   (unix:unix-read fd storage size)
+	(when (or (null read-bytes) (not (= size read-bytes)))
+	  (system:deallocate-system-memory storage size)
+	  (funcall *error-function*
+		   "Reading file ~S failed: ~A." ses-name err)))
+      (values storage size mode))))
+
+(defun write-file (ses-name data byte-count mode)
+  (multiple-value-bind (fd err) (unix:unix-creat ses-name #o644)
+    (unless fd
+      (funcall *error-function* "Couldn't create file ~S: ~A"
+	       ses-name (unix:get-unix-error-msg err)))
+    (multiple-value-bind (winp err) (unix:unix-write fd data 0 byte-count)
+      (unless winp
+	(funcall *error-function* "Writing file ~S failed: ~A"
+	       ses-name
+	       (unix:get-unix-error-msg err))))
+    (unix:unix-fchmod fd (logand mode #o777))
+    (unix:unix-close fd)))
+
+(defun set-write-date (ses-name secs)
+  (multiple-value-bind (winp dev-or-err ino mode nlink uid gid rdev size atime)
+		       (unix:unix-stat ses-name)
+    (declare (ignore ino mode nlink uid gid rdev size))
+    (unless winp
+      (funcall *error-function* "Couldn't stat file ~S failed: ~A."
+	       ses-name dev-or-err))
+    (multiple-value-bind (winp err)
+	(unix:unix-utimes ses-name atime 0 secs 0)
+      (unless winp
+	(funcall *error-function* "Couldn't set write date of file ~S: ~A"
+		 ses-name (unix:get-unix-error-msg err))))))
+
+(defun get-write-date (ses-name)
+  (multiple-value-bind (winp dev-or-err ino mode nlink uid gid rdev size
+			atime mtime)
+ 		       (unix:unix-stat ses-name)
+    (declare (ignore ino mode nlink uid gid rdev size atime))
+    (unless winp (funcall *error-function* "Couldn't stat file ~S failed: ~A."
+			  ses-name dev-or-err))
+    mtime))
+
+;;; SUB-RENAME-FILE must exist because we can't use Common Lisp's RENAME-FILE.
+;;; This is because it merges the new name with the old name to pick up
+;;; defaults, and this conflicts with Unix-oid names.  For example, renaming
+;;; "foo.bar" to ".baz" causes a result of "foo.baz"!  This routine doesn't
+;;; have this problem.
+;;;
+(defun sub-rename-file (ses-name1 ses-name2)
+  (multiple-value-bind (res err) (unix:unix-rename ses-name1 ses-name2)
+    (unless res
+      (funcall *error-function* "Failed to rename ~A to ~A: ~A."
+	       ses-name1 ses-name2 (unix:get-unix-error-msg err)))))
+
+(defun directory-existsp (ses-name)
+  (eq (unix:unix-file-kind ses-name) :directory))
+
+(defun enter-directory (ses-name)
+  (declare (simple-string ses-name))
+  (let* ((length-1 (1- (length ses-name)))
+	 (name (if (= (position #\/ ses-name :test #'char= :from-end t)
+		      length-1)
+		   (subseq ses-name 0 (1- (length ses-name)))
+		   ses-name)))
+    (multiple-value-bind (winp err) (unix:unix-mkdir name #o755)
+      (unless winp
+	(funcall *error-function* "Couldn't make directory ~S: ~A"
+		 name
+		 (unix:get-unix-error-msg err))))))
+
+(defun delete-directory (ses-name)
+  (declare (simple-string ses-name))
+  (multiple-value-bind (winp err)
+		       (unix:unix-rmdir (subseq ses-name 0
+						(1- (length ses-name))))
+    (unless winp
+      (funcall *error-function* "Couldn't delete directory ~S: ~A"
+	       ses-name
+	       (unix:get-unix-error-msg err)))))
+
+
+
+
+;;;; Misc. Utility Utilities
+
+;;; NSEPARATE-FILES destructively returns a list of file specs from listing.
+(defun nseparate-files (listing)
+  (do (files hold)
+      ((null listing) files)
+    (setf hold (cdr listing))
+    (unless (directoryp (car listing))
+      (setf (cdr listing) files)
+      (setf files listing))
+    (setf listing hold)))
+
+
+(defun directoryp (p)
+  (not (or (pathname-name p) (pathname-type p))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/diredcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/diredcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/diredcoms.lisp	(revision 13309)
@@ -0,0 +1,905 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Simple directory editing support.
+;;; This file contains site dependent calls.
+;;;
+;;; Written by Blaine Burks and Bill Chiles.
+;;;
+
+(in-package :hemlock)
+
+
+(defmode "Dired" :major-p t
+  :documentation
+  "Dired permits convenient directory browsing and file operations including
+   viewing, deleting, copying, renaming, and wildcard specifications.")
+
+
+(defstruct (dired-information (:print-function print-dired-information)
+			      (:conc-name dired-info-))
+  pathname		; Pathname of directory.
+  pattern		; FILE-NAMESTRING with wildcard possibly.
+  dot-files-p		; Whether to include UNIX dot files. 
+  write-date		; Write date of directory.
+  files			; Simple-vector of dired-file structures.
+  file-list)		; List of pathnames for files, excluding directories.
+
+(defun print-dired-information (obj str n)
+  (declare (ignore n))
+  (format str "#<Dired Info ~S>" (namestring (dired-info-pathname obj))))
+
+
+(defstruct (dired-file (:print-function print-dired-file)
+		       (:constructor make-dired-file (pathname)))
+  pathname
+  (deleted-p nil)
+  (write-date nil))
+
+(defun print-dired-file (obj str n)
+  (declare (ignore n))
+  (format str "#<Dired-file ~A>" (namestring (dired-file-pathname obj))))
+
+
+
+
+;;;; "Dired" command.
+     
+;;; *pathnames-to-dired-buffers* is an a-list mapping directory namestrings to
+;;; buffers that display their contents.
+;;;
+(defvar *pathnames-to-dired-buffers* ())
+
+(make-modeline-field
+ :name :dired-cmds :width 20
+ :function
+ #'(lambda (buffer window)
+     (declare (ignore buffer window))
+     "  Type ? for help.  "))
+
+(defcommand "Dired" (p &optional directory)
+  "Prompts for a directory and edits it.  If a dired for that directory already
+   exists, go to that buffer, otherwise create one.  With an argument, include
+   UNIX dot files."
+  "Prompts for a directory and edits it.  If a dired for that directory already
+   exists, go to that buffer, otherwise create one.  With an argument, include
+   UNIX dot files."
+  (let ((info (if (hemlock-bound-p 'dired-information)
+		  (value dired-information))))
+    (dired-guts nil
+		;; Propagate dot-files property to subdirectory edits.
+		(or (and info (dired-info-dot-files-p info))
+		    p)
+		directory)))
+
+(defcommand "Dired with Pattern" (p)
+  "Do a dired, prompting for a pattern which may include a single *.  With an
+   argument, include UNIX dit files."
+  "Do a dired, prompting for a pattern which may include a single *.  With an
+   argument, include UNIX dit files."
+  (dired-guts t p nil))
+
+(defun dired-guts (patternp dot-files-p directory)
+  (let* ((dpn (value pathname-defaults))
+	 (directory (dired-directorify
+		     (or directory
+			 (prompt-for-file
+			  :prompt "Edit Directory: "
+			  :help "Pathname to edit."
+			  :default (make-pathname
+				    :device (pathname-device dpn)
+				    :directory (pathname-directory dpn))
+			  :must-exist nil))))
+	 (pattern (if patternp
+		      (prompt-for-string
+		       :prompt "Filename pattern: "
+		       :help "Type a filename with a single asterisk."
+		       :trim t)))
+	 (full-name (namestring (if pattern
+				    (merge-pathnames directory pattern)
+				    directory)))
+	 (name (concatenate 'simple-string "Dired " full-name))
+	 (buffer (cdr (assoc full-name *pathnames-to-dired-buffers*
+			     :test #'string=))))
+    (declare (simple-string full-name))
+    (setf (value pathname-defaults) (merge-pathnames directory dpn))
+    (change-to-buffer
+     (cond (buffer
+	    (when (and dot-files-p
+		       (not (dired-info-dot-files-p
+			     (variable-value 'dired-information
+					     :buffer buffer))))
+	      (setf (dired-info-dot-files-p (variable-value 'dired-information
+							    :buffer buffer))
+		    t)
+	      (update-dired-buffer directory pattern buffer))
+	    buffer)
+	   (t
+	    (let ((buffer (make-buffer
+			   name :modes '("Dired")
+			   :modeline-fields
+			   (append (value default-modeline-fields)
+				   (list (modeline-field :dired-cmds)))
+			   :delete-hook (list 'dired-buffer-delete-hook))))
+	      (unless (initialize-dired-buffer directory pattern
+					       dot-files-p buffer)
+		(delete-buffer-if-possible buffer)
+		(editor-error "No entries for ~A." full-name))
+	      (push (cons full-name buffer) *pathnames-to-dired-buffers*)
+	      buffer))))))
+
+;;; INITIALIZE-DIRED-BUFFER gets a dired in the buffer and defines some
+;;; variables to make it usable as a dired buffer.  If there are no file
+;;; satisfying directory, then this returns nil, otherwise t.
+;;;
+(defun initialize-dired-buffer (directory pattern dot-files-p buffer)
+  (multiple-value-bind (pathnames dired-files)
+		       (dired-in-buffer directory pattern dot-files-p buffer)
+    (if (zerop (length dired-files))
+	nil
+	(defhvar "Dired Information"
+	  "Contains the information neccessary to manipulate dired buffers."
+	  :buffer buffer
+	  :value (make-dired-information :pathname directory
+					 :pattern pattern
+					 :dot-files-p dot-files-p
+					 :write-date (file-write-date directory)
+					 :files dired-files
+					 :file-list pathnames)))))
+
+;;; CALL-PRINT-DIRECTORY gives us a nice way to report PRINT-DIRECTORY errors
+;;; to the user and to clean up the dired buffer.
+;;;
+(defun call-print-directory (directory mark dot-files-p)
+  (handler-case (with-output-to-mark (s mark :full)
+		  (print-directory directory s
+				   :all dot-files-p :verbose t :return-list t))
+    (error (condx)
+      (delete-buffer-if-possible (line-buffer (mark-line mark)))
+      (editor-error "~A" condx))))
+
+;;; DIRED-BUFFER-DELETE-HOOK is called on dired buffers upon deletion.  This
+;;; removes the buffer from the pathnames mapping, and it deletes and buffer
+;;; local variables referring to it.
+;;;
+(defun dired-buffer-delete-hook (buffer)
+  (setf *pathnames-to-dired-buffers*
+	(delete buffer *pathnames-to-dired-buffers* :test #'eq :key #'cdr)))
+
+
+
+
+;;;; Dired deletion and undeletion.
+
+(defcommand "Dired Delete File" (p)
+  "Marks a file for deletion; signals an error if not in a dired buffer.
+   With an argument, this prompts for a pattern that may contain at most one
+   wildcard, an asterisk, and all names matching the pattern will be flagged
+   for deletion."
+  "Marks a file for deletion; signals an error if not in a dired buffer."
+  (dired-frob-deletion p t))
+
+(defcommand "Dired Undelete File" (p)
+  "Removes a mark for deletion; signals and error if not in a dired buffer.
+   With an argument, this prompts for a pattern that may contain at most one
+   wildcard, an asterisk, and all names matching the pattern will be unflagged
+   for deletion."
+  "Removes a mark for deletion; signals and error if not in a dired buffer."
+  (dired-frob-deletion p nil))
+
+(defcommand "Dired Delete File and Down Line" (p)
+  "Marks file for deletion and moves down a line.
+   See \"Dired Delete File\"."
+  "Marks file for deletion and moves down a line.
+   See \"Dired Delete File\"."
+  (declare (ignore p))
+  (dired-frob-deletion nil t)
+  (dired-down-line (current-point)))
+
+(defcommand "Dired Undelete File and Down Line" (p)
+  "Marks file undeleted and moves down a line.
+   See \"Dired Delete File\"."
+  "Marks file undeleted and moves down a line.
+   See \"Dired Delete File\"."
+  (declare (ignore p))
+  (dired-frob-deletion nil nil)
+  (dired-down-line (current-point)))
+
+(defcommand "Dired Delete File with Pattern" (p)
+  "Prompts for a pattern and marks matching files for deletion.
+   See \"Dired Delete File\"."
+  "Prompts for a pattern and marks matching files for deletion.
+   See \"Dired Delete File\"."
+  (declare (ignore p))
+  (dired-frob-deletion t t)
+  (dired-down-line (current-point)))
+
+(defcommand "Dired Undelete File with Pattern" (p)
+  "Prompts for a pattern and marks matching files undeleted.
+   See \"Dired Delete File\"."
+  "Prompts for a pattern and marks matching files undeleted.
+   See \"Dired Delete File\"."
+  (declare (ignore p))
+  (dired-frob-deletion t nil)
+  (dired-down-line (current-point)))
+
+;;; DIRED-FROB-DELETION takes arguments indicating whether to prompt for a
+;;; pattern and whether to mark the file deleted or undeleted.  This uses
+;;; CURRENT-POINT and CURRENT-BUFFER, and if not in a dired buffer, signal
+;;; an error.
+;;; 
+(defun dired-frob-deletion (patternp deletep)
+  (unless (hemlock-bound-p 'dired-information)
+    (editor-error "Not in Dired buffer."))
+  (with-mark ((mark (current-point) :left-inserting))
+    (let* ((dir-info (value dired-information))
+	   (files (dired-info-files dir-info))
+	   (del-files
+	    (if patternp
+		(dired:pathnames-from-pattern
+		 (prompt-for-string
+		  :prompt "Filename pattern: "
+		  :help "Type a filename with a single asterisk."
+		  :trim t)
+		 (dired-info-file-list dir-info))
+		(list (dired-file-pathname
+		       (array-element-from-mark mark files)))))
+	   (note-char (if deletep #\D #\space)))
+      (with-writable-buffer ((current-buffer))
+	(dolist (f del-files)
+	  (let* ((pos (position f files :test #'equal
+				:key #'dired-file-pathname))
+		 (dired-file (svref files pos)))
+	    (buffer-start mark)
+	    (line-offset mark pos 0)
+	    (setf (dired-file-deleted-p dired-file) deletep)
+	    (if deletep
+		(setf (dired-file-write-date dired-file)
+		      (file-write-date (dired-file-pathname dired-file)))
+		(setf (dired-file-write-date dired-file) nil))
+	    (setf (next-character mark) note-char)))))))
+
+(defun dired-down-line (point)
+  (line-offset point 1)
+  (when (blank-line-p (mark-line point))
+    (line-offset point -1)))
+
+
+
+
+;;;; Dired file finding and going to dired buffers.
+
+(defcommand "Dired Edit File" (p)
+  "Read in file or recursively \"Dired\" a directory."
+  "Read in file or recursively \"Dired\" a directory."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (when (blank-line-p (mark-line point)) (editor-error "Not on a file line."))
+    (let ((pathname (dired-file-pathname
+		     (array-element-from-mark
+		      point (dired-info-files (value dired-information))))))
+      (if (directoryp pathname)
+	  (dired-command nil (directory-namestring pathname))
+	  (change-to-buffer (find-file-buffer pathname))))))
+
+(defcommand "Dired View File" (p)
+  "Read in file as if by \"View File\" or recursively \"Dired\" a directory.
+   This associates the file's buffer with the dired buffer."
+  "Read in file as if by \"View File\".
+   This associates the file's buffer with the dired buffer."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (when (blank-line-p (mark-line point)) (editor-error "Not on a file line."))
+    (let ((pathname (dired-file-pathname
+		     (array-element-from-mark
+		      point (dired-info-files (value dired-information))))))
+      (if (directoryp pathname)
+	  (dired-command nil (directory-namestring pathname))
+	  (let* ((dired-buf (current-buffer))
+		 (buffer (view-file-command nil pathname)))
+	    (push #'(lambda (buffer)
+		      (declare (ignore buffer))
+		      (setf dired-buf nil))
+		  (buffer-delete-hook dired-buf))
+	    (setf (variable-value 'view-return-function :buffer buffer)
+		  #'(lambda ()
+		      (if dired-buf
+			  (change-to-buffer dired-buf)
+			  (dired-from-buffer-pathname-command nil)))))))))
+
+(defcommand "Dired from Buffer Pathname" (p)
+  "Invokes \"Dired\" on the directory part of the current buffer's pathname.
+   With an argument, also prompt for a file pattern within that directory."
+  "Invokes \"Dired\" on the directory part of the current buffer's pathname.
+   With an argument, also prompt for a file pattern within that directory."
+  (let ((pathname (buffer-pathname (current-buffer))))
+    (if pathname
+	(dired-command p (directory-namestring pathname))
+	(editor-error "No pathname associated with buffer."))))
+
+(defcommand "Dired Up Directory" (p)
+  "Invokes \"Dired\" on the directory up one level from the current Dired
+   buffer."
+  "Invokes \"Dired\" on the directory up one level from the current Dired
+   buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'dired-information)
+    (editor-error "Not in Dired buffer."))
+  (let ((dirs (or (pathname-directory
+		   (dired-info-pathname (value dired-information)))
+		  '(:relative))))
+    (dired-command nil
+		   (truename (make-pathname :directory (nconc dirs '(:UP)))))))
+
+
+
+
+;;;; Dired misc. commands -- update, help, line motion.
+
+(defcommand "Dired Update Buffer" (p)
+  "Recompute the contents of a dired buffer.
+   This maintains delete flags for files that have not been modified."
+  "Recompute the contents of a dired buffer.
+   This maintains delete flags for files that have not been modified."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'dired-information)
+    (editor-error "Not in Dired buffer."))
+  (let ((buffer (current-buffer))
+	(dir-info (value dired-information)))
+    (update-dired-buffer (dired-info-pathname dir-info)
+			 (dired-info-pattern dir-info)
+			 buffer)))
+
+;;; UPDATE-DIRED-BUFFER updates buffer with a dired of directory, deleting
+;;; whatever is in the buffer already.  This assumes buffer was previously
+;;; used as a dired buffer having necessary variables bound.  The new files
+;;; are compared to the old ones propagating any deleted flags if the name
+;;; and the write date is the same for both specifications.
+;;;
+(defun update-dired-buffer (directory pattern buffer)
+  (with-writable-buffer (buffer)
+    (delete-region (buffer-region buffer))
+    (let ((dir-info (variable-value 'dired-information :buffer buffer)))
+      (multiple-value-bind (pathnames new-dired-files)
+			   (dired-in-buffer directory pattern
+					    (dired-info-dot-files-p dir-info)
+					    buffer)
+	(let ((point (buffer-point buffer))
+	      (old-dired-files (dired-info-files dir-info)))
+	  (declare (simple-vector old-dired-files))
+	  (dotimes (i (length old-dired-files))
+	    (let ((old-file (svref old-dired-files i)))
+	      (when (dired-file-deleted-p old-file)
+		(let ((pos (position (dired-file-pathname old-file)
+				     new-dired-files :test #'equal
+				     :key #'dired-file-pathname)))
+		  (when pos
+		    (let* ((new-file (svref new-dired-files pos))
+			   (write-date (file-write-date
+					(dired-file-pathname new-file))))
+		      (when (= (dired-file-write-date old-file) write-date)
+			(setf (dired-file-deleted-p new-file) t)
+			(setf (dired-file-write-date new-file) write-date)
+			(setf (next-character
+			       (line-offset (buffer-start point) pos 0))
+			      #\D))))))))
+	  (setf (dired-info-files dir-info) new-dired-files)
+	  (setf (dired-info-file-list dir-info) pathnames)
+	  (setf (dired-info-write-date dir-info)
+		(file-write-date directory))
+	  (move-mark point (buffer-start-mark buffer)))))))
+
+;;; DIRED-IN-BUFFER inserts a dired listing of directory in buffer returning
+;;; two values: a list of pathnames of files only, and an array of dired-file
+;;; structures.  This uses FILTER-REGION to insert a space for the indication
+;;; of whether the file is flagged for deletion.  Then we clean up extra header
+;;; and trailing lines known to be in the output (into every code a little
+;;; slime must fall).
+;;;
+(defun dired-in-buffer (directory pattern dot-files-p buffer)
+  (let ((point (buffer-point buffer)))
+    (with-writable-buffer (buffer)
+      (let* ((pathnames (call-print-directory
+			 (if pattern
+			     (merge-pathnames directory pattern)
+			     directory)
+			 point
+			 dot-files-p))
+	     (dired-files (make-array (length pathnames))))
+	(declare (list pathnames) (simple-vector dired-files))
+	(filter-region #'(lambda (str)
+			   (concatenate 'simple-string "  " str))
+		       (buffer-region buffer))
+	(delete-characters point -2)
+	(delete-region (line-to-region (mark-line (buffer-start point))))
+	(delete-characters point)
+	(do ((p pathnames (cdr p))
+	     (i 0 (1+ i)))
+	    ((null p))
+	  (setf (svref dired-files i) (make-dired-file (car p))))
+	(values (delete-if #'directoryp pathnames) dired-files)))))
+
+
+(defcommand "Dired Help" (p)
+  "How to use dired."
+  "How to use dired."
+  (declare (ignore p))
+  (describe-mode-command nil "Dired"))
+
+(defcommand "Dired Next File" (p)
+  "Moves to next undeleted file."
+  "Moves to next undeleted file."
+  (unless (dired-line-offset (current-point) (or p 1))
+    (editor-error "Not enough lines.")))
+
+(defcommand "Dired Previous File" (p)
+  "Moves to previous undeleted file."
+  "Moves to next undeleted file."
+  (unless (dired-line-offset (current-point) (or p -1))
+    (editor-error "Not enough lines.")))
+
+;;; DIRED-LINE-OFFSET moves mark n undeleted file lines, returning mark.  If
+;;; there are not enough lines, mark remains unmoved, this returns nil.
+;;;
+(defun dired-line-offset (mark n)
+  (with-mark ((m mark))
+    (let ((step (if (plusp n) 1 -1)))
+      (dotimes (i (abs n) (move-mark mark m))
+	(loop
+	  (unless (line-offset m step 0)
+	    (return-from dired-line-offset nil))
+	  (when (blank-line-p (mark-line m))
+	    (return-from dired-line-offset nil))
+	  (when (char= (next-character m) #\space)
+	    (return)))))))
+
+
+
+
+;;;; Dired user interaction functions.
+
+(defun dired-error-function (string &rest args)
+  (apply #'editor-error string args))
+
+(defun dired-report-function (string &rest args)
+  (clear-echo-area)
+  (apply #'message string args))
+
+(defun dired-yesp-function (string &rest args)
+  (prompt-for-y-or-n :prompt (cons string args) :default t))
+
+
+
+
+;;;; Dired expunging and quitting.
+
+(defcommand "Dired Expunge Files" (p)
+  "Expunges files marked for deletion.
+   Query the user if value of \"Dired File Expunge Confirm\" is non-nil.  Do
+   the same with directories and the value of \"Dired Directory Expunge
+   Confirm\"."
+  "Expunges files marked for deletion.
+   Query the user if value of \"Dired File Expunge Confirm\" is non-nil.  Do
+   the same with directories and the value of \"Dired Directory Expunge
+   Confirm\"."
+  (declare (ignore p)) 
+  (when (expunge-dired-files)
+    (dired-update-buffer-command nil))
+  (maintain-dired-consistency))
+
+(defcommand "Dired Quit" (p)
+  "Expunges the files in a dired buffer and then exits."
+  "Expunges the files in a dired buffer and then exits."
+  (declare (ignore p))
+  (expunge-dired-files)
+  (delete-buffer-if-possible (current-buffer)))
+
+(defhvar "Dired File Expunge Confirm"
+  "When set (the default), \"Dired Expunge Files\" and \"Dired Quit\" will ask
+   for confirmation before deleting the marked files."
+  :value t)
+
+(defhvar "Dired Directory Expunge Confirm"
+  "When set (the default), \"Dired Expunge Files\" and \"Dired Quit\" will ask
+   for confirmation before deleting each marked directory."
+  :value t)
+
+(defun expunge-dired-files ()
+  (multiple-value-bind (marked-files marked-dirs) (get-marked-dired-files)
+    (let ((dired:*error-function* #'dired-error-function)
+	  (dired:*report-function* #'dired-report-function)
+	  (dired:*yesp-function* #'dired-yesp-function)
+	  (we-did-something nil))
+      (when (and marked-files
+		 (or (not (value dired-file-expunge-confirm))
+		     (prompt-for-y-or-n :prompt "Really delete files? "
+					:default t
+					:must-exist t
+					:default-string "Y")))
+	(setf we-did-something t)
+	(dolist (file-info marked-files)
+	  (let ((pathname (car file-info))
+		(write-date (cdr file-info)))
+	    (if (= write-date (file-write-date pathname))
+		(dired:delete-file (namestring pathname) :clobber t
+				   :recursive nil)
+		(message "~A has been modified, it remains unchanged."
+			 (namestring pathname))))))
+      (when marked-dirs
+	(dolist (dir-info marked-dirs)
+	  (let ((dir (car dir-info))
+		(write-date (cdr dir-info)))
+	    (if (= write-date (file-write-date dir))
+		(when (or (not (value dired-directory-expunge-confirm))
+			  (prompt-for-y-or-n
+			   :prompt (list "~a is a directory. Delete it? "
+					 (directory-namestring dir))
+			   :default t
+			   :must-exist t
+			   :default-string "Y"))
+		  (dired:delete-file (directory-namestring dir) :clobber t
+				     :recursive t)
+		  (setf we-did-something t))
+		(message "~A has been modified, it remains unchanged.")))))
+      we-did-something)))
+
+
+
+
+;;;; Dired copying and renaming.
+
+(defhvar "Dired Copy File Confirm"
+  "Can be either t, nil, or :update.  T means always query before clobbering an
+   existing file, nil means don't query before clobbering an existing file, and
+   :update means only ask if the existing file is newer than the source."
+  :value T)
+
+(defhvar "Dired Rename File Confirm"
+  "When non-nil, dired will query before clobbering an existing file."
+  :value T)
+
+(defcommand "Dired Copy File" (p)
+  "Copy the file under the point"
+  "Copy the file under the point"
+  (declare (ignore p))
+  (let* ((point (current-point))
+	 (confirm (value dired-copy-file-confirm))
+	 (source (dired-file-pathname
+		  (array-element-from-mark
+		   point (dired-info-files (value dired-information)))))
+	 (dest (prompt-for-file
+		:prompt (if (directoryp source)
+			    "Destination Directory Name: "
+			    "Destination Filename: ")
+		:help "Name of new file."
+		:default source
+		:must-exist nil))
+	 (dired:*error-function* #'dired-error-function)
+	 (dired:*report-function* #'dired-report-function)
+	 (dired:*yesp-function* #'dired-yesp-function))
+    (dired:copy-file source dest :update (if (eq confirm :update) t nil)
+		     :clobber (not confirm)))
+  (maintain-dired-consistency))
+
+(defcommand "Dired Rename File" (p)
+  "Rename the file or directory under the point"
+  "Rename the file or directory under the point"
+  (declare (ignore p))
+  (let* ((point (current-point))
+	 (source (dired-namify (dired-file-pathname
+				(array-element-from-mark
+				 point
+				 (dired-info-files (value dired-information))))))
+	 (dest (prompt-for-file
+		:prompt "New Filename: "
+		:help "The new name for this file."
+		:default source
+		:must-exist nil))
+	 (dired:*error-function* #'dired-error-function)
+	 (dired:*report-function* #'dired-report-function)
+	 (dired:*yesp-function* #'dired-yesp-function))
+    ;; ARRAY-ELEMENT-FROM-MARK moves mark to line start.
+    (dired:rename-file source dest :clobber (value dired-rename-file-confirm)))
+  (maintain-dired-consistency))
+
+(defcommand "Dired Copy with Wildcard" (p)
+  "Copy files that match a pattern containing ONE wildcard."
+  "Copy files that match a pattern containing ONE wildcard."
+  (declare (ignore p))
+  (let* ((dir-info (value dired-information))
+	 (confirm (value dired-copy-file-confirm))
+	 (pattern (prompt-for-string
+		   :prompt "Filename pattern: "
+		   :help "Type a filename with a single asterisk."
+		   :trim t))
+	 (destination (namestring
+		       (prompt-for-file
+			:prompt "Destination Spec: "
+			:help "Destination spec.  May contain ONE asterisk."
+			:default (dired-info-pathname dir-info)
+			:must-exist nil)))
+	 (dired:*error-function* #'dired-error-function)
+	 (dired:*yesp-function* #'dired-yesp-function)
+	 (dired:*report-function* #'dired-report-function))
+    (dired:copy-file pattern destination :update (if (eq confirm :update) t nil)
+		     :clobber (not confirm)
+		     :directory (dired-info-file-list dir-info)))
+  (maintain-dired-consistency))
+
+(defcommand "Dired Rename with Wildcard" (p)
+  "Rename files that match a pattern containing ONE wildcard."
+  "Rename files that match a pattern containing ONE wildcard."
+  (declare (ignore p))
+  (let* ((dir-info (value dired-information))
+	 (pattern (prompt-for-string
+		   :prompt "Filename pattern: "
+		   :help "Type a filename with a single asterisk."
+		   :trim t))
+	 (destination (namestring
+		       (prompt-for-file
+			:prompt "Destination Spec: "
+			:help "Destination spec.  May contain ONE asterisk."
+			:default (dired-info-pathname dir-info)
+			:must-exist nil)))
+	 (dired:*error-function* #'dired-error-function)
+	 (dired:*yesp-function* #'dired-yesp-function)
+	 (dired:*report-function* #'dired-report-function))
+    (dired:rename-file pattern destination
+		       :clobber (not (value dired-rename-file-confirm))
+		       :directory (dired-info-file-list dir-info)))
+  (maintain-dired-consistency))
+
+(defcommand "Delete File" (p)
+  "Delete a file.  Specify directories with a trailing slash."
+  "Delete a file.  Specify directories with a trailing slash."
+  (declare (ignore p))
+  (let* ((spec (namestring
+		(prompt-for-file
+		 :prompt "Delete File: "
+		 :help '("Name of File or Directory to delete.  ~
+			  One wildcard is permitted.")
+		 :must-exist nil)))
+	 (directoryp (directoryp spec))
+	 (dired:*error-function* #'dired-error-function)
+	 (dired:*report-function* #'dired-report-function)
+	 (dired:*yesp-function* #'dired-yesp-function))
+    (when (or (not directoryp)
+	      (not (value dired-directory-expunge-confirm))
+	      (prompt-for-y-or-n
+	       :prompt (list "~A is a directory. Delete it? "
+			     (directory-namestring spec))
+	       :default t :must-exist t :default-string "Y")))
+    (dired:delete-file spec :recursive t
+		       :clobber (or directoryp
+				    (value dired-file-expunge-confirm))))
+  (maintain-dired-consistency))
+
+(defcommand "Copy File" (p)
+  "Copy a file, allowing ONE wildcard."
+  "Copy a file, allowing ONE wildcard."
+  (declare (ignore p))
+  (let* ((confirm (value dired-copy-file-confirm))
+	 (source (namestring
+		  (prompt-for-file
+		   :prompt "Source Filename: "
+		   :help "Name of File to copy.  One wildcard is permitted."
+		   :must-exist nil)))
+	 (dest (namestring
+		(prompt-for-file
+		 :prompt (if (directoryp source)
+			     "Destination Directory Name: "
+			     "Destination Filename: ")
+		 :help "Name of new file."
+		 :default source
+		 :must-exist nil)))
+	 (dired:*error-function* #'dired-error-function)
+	 (dired:*report-function* #'dired-report-function)
+	 (dired:*yesp-function* #'dired-yesp-function))
+    (dired:copy-file source dest :update (if (eq confirm :update) t nil)
+		     :clobber (not confirm)))
+  (maintain-dired-consistency))
+
+(defcommand "Rename File" (p)
+  "Rename a file, allowing ONE wildcard."
+  "Rename a file, allowing ONE wildcard."
+  (declare (ignore p))
+  (let* ((source (namestring
+		  (prompt-for-file
+		   :prompt "Source Filename: "
+		   :help "Name of file to rename.  One wildcard is permitted."
+		   :must-exist nil)))
+	 (dest (namestring
+		(prompt-for-file
+		 :prompt (if (directoryp source)
+			     "Destination Directory Name: "
+			     "Destination Filename: ")
+		 :help "Name of new file."
+		 :default source
+		 :must-exist nil)))
+	 (dired:*error-function* #'dired-error-function)
+	 (dired:*report-function* #'dired-report-function)
+	 (dired:*yesp-function* #'dired-yesp-function))
+    (dired:rename-file source dest
+		       :clobber (not (value dired-rename-file-confirm))))
+  (maintain-dired-consistency))
+
+(defun maintain-dired-consistency ()
+  (dolist (info *pathnames-to-dired-buffers*)
+    (let* ((directory (directory-namestring (car info)))
+	   (buffer (cdr info))
+	   (dir-info (variable-value 'dired-information :buffer buffer))
+	   (write-date (file-write-date directory)))
+      (unless (= (dired-info-write-date dir-info) write-date)
+	(update-dired-buffer directory (dired-info-pattern dir-info) buffer)))))
+
+
+
+
+;;;; Dired utilities.
+
+;;; GET-MARKED-DIRED-FILES returns as multiple values a list of file specs
+;;; and a list of directory specs that have been marked for deletion.  This
+;;; assumes the current buffer is a "Dired" buffer.
+;;;
+(defun get-marked-dired-files ()
+  (let* ((files (dired-info-files (value dired-information)))
+	 (length (length files))
+	 (marked-files ())
+	 (marked-dirs ()))
+    (unless files (editor-error "Not in Dired buffer."))
+    (do ((i 0 (1+ i)))
+	((= i length) (values (nreverse marked-files) (nreverse marked-dirs)))
+      (let* ((thing (svref files i))
+	     (pathname (dired-file-pathname thing)))
+	(when (and (dired-file-deleted-p thing) ; file marked for delete
+		   (probe-file pathname)) 	; file still exists 
+	  (if (directoryp pathname)
+	      (push (cons pathname (file-write-date pathname)) marked-dirs)
+	      (push (cons pathname (file-write-date pathname))
+		    marked-files)))))))
+
+;;; ARRAY-ELEMENT-FROM-MARK -- Internal Interface.
+;;;
+;;; This counts the lines between it and the beginning of the buffer.  The
+;;; number is used to index vector as if each line mapped to an element
+;;; starting with the zero'th element (lines are numbered starting at 1).
+;;; This must use AREF since some modes use this with extendable vectors.
+;;;
+(defun array-element-from-mark (mark vector
+				&optional (error-msg "Invalid line."))
+  (when (blank-line-p (mark-line mark)) (editor-error error-msg))
+  (aref vector
+	 (1- (count-lines (region
+			   (buffer-start-mark (line-buffer (mark-line mark)))
+			   mark)))))
+
+;;; DIRED-NAMIFY and DIRED-DIRECTORIFY are implementation dependent slime.
+;;;
+(defun dired-namify (pathname)
+  (let* ((string (namestring pathname))
+	 (last (1- (length string))))
+    (if (char= (schar string last) #\/)
+	(subseq string 0 last)
+	string)))
+;;;
+;;; This is necessary to derive a canonical representation for directory
+;;; names, so "Dired" can map various strings naming one directory to that
+;;; one directory.
+;;;
+(defun dired-directorify (pathname)
+  (let ((directory (ext:unix-namestring pathname)))
+    (if (directoryp directory)
+	directory
+	(pathname (concatenate 'simple-string (namestring directory) "/")))))
+
+
+
+
+;;;; View Mode.
+
+(defmode "View" :major-p nil
+  :setup-function 'setup-view-mode
+  :cleanup-function 'cleanup-view-mode
+  :precedence 5.0
+  :documentation
+  "View mode scrolls forwards and backwards in a file with the buffer read-only.
+   Scrolling off the end optionally deletes the buffer.")
+
+(defun setup-view-mode (buffer)
+  (defhvar "View Return Function"
+    "Function that gets called when quitting or returning from view mode."
+    :value nil
+    :buffer buffer)
+  (setf (buffer-writable buffer) nil))
+;;;
+(defun cleanup-view-mode (buffer)
+  (delete-variable 'view-return-function :buffer buffer)
+  (setf (buffer-writable buffer) t))
+
+(defcommand "View File" (p &optional pathname)
+  "Reads a file in as if by \"Find File\", but read-only.  Commands exist
+   for scrolling convenience."
+  "Reads a file in as if by \"Find File\", but read-only.  Commands exist
+   for scrolling convenience."
+  (declare (ignore p))
+  (let* ((pn (or pathname
+		 (prompt-for-file 
+		  :prompt "View File: " :must-exist t
+		  :help "Name of existing file to read into its own buffer."
+		  :default (buffer-default-pathname (current-buffer)))))
+	 (buffer (make-buffer (format nil "View File ~A" (gensym)))))
+    (visit-file-command nil pn buffer)
+    (setf (buffer-minor-mode buffer "View") t)
+    (change-to-buffer buffer)
+    buffer))
+
+(defcommand "View Return" (p)
+  "Return to a parent buffer, if it exists."
+  "Return to a parent buffer, if it exists."
+  (declare (ignore p))
+  (unless (call-view-return-fun)
+    (editor-error "No View return method for this buffer.")))
+
+(defcommand "View Quit" (p)
+  "Delete a buffer in view mode."
+  "Delete a buffer in view mode, invoking VIEW-RETURN-FUNCTION if it exists for
+   this buffer."
+  (declare (ignore p))
+  (let* ((buf (current-buffer))
+	 (funp (call-view-return-fun)))
+    (delete-buffer-if-possible buf)
+    (unless funp (editor-error "No View return method for this buffer."))))
+
+;;; CALL-VIEW-RETURN-FUN returns nil if there is no current
+;;; view-return-function.  If there is one, it calls it and returns t.
+;;;
+(defun call-view-return-fun ()
+  (if (hemlock-bound-p 'view-return-function)
+      (let ((fun (value view-return-function)))
+	(cond (fun
+	       (funcall fun)
+	       t)))))
+
+
+(defhvar "View Scroll Deleting Buffer"
+  "When this is set, \"View Scroll Down\" deletes the buffer when the end
+   of the file is visible."
+  :value t)
+
+(defcommand "View Scroll Down" (p)
+  "Scroll the current window down through its buffer.
+   If the end of the file is visible, then delete the buffer if \"View Scroll
+   Deleting Buffer\" is set.  If the buffer is associated with a dired buffer,
+   this returns there instead of to the previous buffer."
+  "Scroll the current window down through its buffer.
+   If the end of the file is visible, then delete the buffer if \"View Scroll
+   Deleting Buffer\" is set.  If the buffer is associated with a dired buffer,
+   this returns there instead of to the previous buffer."
+  (if (and (not p)
+	   (displayed-p (buffer-end-mark (current-buffer))
+			(current-window))
+	   (value view-scroll-deleting-buffer))
+      (view-quit-command nil)
+      (scroll-window-down-command p)))
+
+(defcommand "View Edit File" (p)
+  "Turn off \"View\" mode in this buffer."
+  "Turn off \"View\" mode in this buffer."
+  (declare (ignore p))
+  (let ((buf (current-buffer)))
+    (setf (buffer-minor-mode buf "View") nil)
+    (warn-about-visit-file-buffers buf)))
+
+(defcommand "View Help" (p)
+  "Shows \"View\" mode help message."
+  "Shows \"View\" mode help message."
+  (declare (ignore p))
+  (describe-mode-command nil "View"))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/display.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/display.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/display.lisp	(revision 13309)
@@ -0,0 +1,310 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Bill Chiles.
+;;;
+;;; This is the device independent redisplay entry points for Hemlock.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Main redisplay entry points.
+
+(defvar *things-to-do-once* ()
+  "This is a list of lists of functions and args to be applied to.  The 
+  functions are called with args supplied at the top of the command loop.")
+
+(defvar *screen-image-trashed* ()
+  "This variable is set to true if the screen has been trashed by some screen
+   manager operation, and thus should be totally refreshed.  This is currently
+   only used by tty redisplay.")
+
+;;; True if we are in redisplay, and thus don't want to enter it recursively.
+;;;
+(defvar *in-redisplay* nil)
+
+(declaim (special *window-list*))
+
+(eval-when (:compile-toplevel :execute)
+
+;;; REDISPLAY-LOOP -- Internal.
+;;;
+;;; This executes internal redisplay routines on all windows interleaved with
+;;; checking for input, and if any input shows up we punt returning
+;;; :editor-input.  Special-fun is for windows that the redisplay interface
+;;; wants to recenter to keep the window's buffer's point visible.  General-fun
+;;; is for other windows.
+;;;
+;;; Whenever we invoke one of the internal routines, we keep track of the
+;;; non-nil return values, so we can return t when we are done.  Returning t
+;;; means redisplay should run again to make sure it converged.  To err on the
+;;; safe side, if any window had any changed lines, then let's go through
+;;; redisplay again; that is, return t.
+;;;
+;;; After checking each window, we put the cursor in the appropriate place and
+;;; force output.  When we try to position the cursor, it may no longer lie
+;;; within the window due to buffer modifications during redisplay.  If it is
+;;; out of the window, return t to indicate we need to finish redisplaying.
+;;;
+;;; Then we check for the after-redisplay method.  Routines such as REDISPLAY
+;;; and REDISPLAY-ALL want to invoke the after method to make sure we handle
+;;; any events generated from redisplaying.  There wouldn't be a problem with
+;;; handling these events if we were going in and out of Hemlock's event
+;;; handling, but some user may loop over one of these interface functions for
+;;; a long time without going through Hemlock's input loop; when that happens,
+;;; each call to redisplay may not result in a complete redisplay of the
+;;; device.  Routines such as INTERNAL-REDISPLAY don't want to worry about this
+;;; since Hemlock calls them while going in and out of the input/event-handling
+;;; loop.
+;;;
+;;; Around all of this, we establish the 'redisplay-catcher tag.  Some device
+;;; redisplay methods throw to this to abort redisplay in addition to this
+;;; code.
+;;;
+(defmacro redisplay-loop (general-fun special-fun &optional (afterp t))
+  (let* ((device (gensym)) (point (gensym)) (hunk (gensym)) (n-res (gensym))
+	 (win-var (gensym))
+	 (general-form (if (symbolp general-fun)
+			   `(,general-fun ,win-var)
+			   `(funcall ,general-fun ,win-var)))
+	 (special-form (if (symbolp special-fun)
+			   `(,special-fun ,win-var)
+			   `(funcall ,special-fun ,win-var))))
+    `(let ((,n-res nil)
+	   (*in-redisplay* t))
+       (catch 'redisplay-catcher
+	 (when (listen-editor-input *real-editor-input*)
+	   (throw 'redisplay-catcher :editor-input))
+	 (let ((,win-var *current-window*))
+	   (when ,special-form (setf ,n-res t)))
+	 (dolist (,win-var *window-list*)
+	   (unless (eq ,win-var *current-window*)
+	     (when (listen-editor-input *real-editor-input*)
+	       (throw 'redisplay-catcher :editor-input))
+	     (when (if (window-display-recentering ,win-var)
+		       ,special-form
+		       ,general-form)
+	        (setf ,n-res t))))
+	 (let* ((,hunk (window-hunk *current-window*))
+		(,device (device-hunk-device ,hunk))
+		(,point (window-point *current-window*)))
+	   (move-mark ,point (buffer-point (window-buffer *current-window*)))
+	   (multiple-value-bind (x y)
+				(mark-to-cursorpos ,point *current-window*)
+	     (if x
+		 (funcall (device-put-cursor ,device) ,hunk x y)
+		 (setf ,n-res t)))
+	   (when (device-force-output ,device)
+	     (funcall (device-force-output ,device)))
+	   ,@(if afterp
+		 `((when (device-after-redisplay ,device)
+		     (funcall (device-after-redisplay ,device) ,device)
+		     ;; The after method may have queued input that the input
+		     ;; loop won't see until the next input arrives, so check
+		     ;; here to return the correct value as per the redisplay
+		     ;; contract.
+		     (when (listen-editor-input *real-editor-input*)
+		       (setf ,n-res :editor-input)))))
+	   ,n-res)))))
+
+) ;eval-when
+
+
+;;; REDISPLAY -- Public.
+;;;
+;;; This function updates the display of all windows which need it.  It assumes
+;;; it's internal representation of the screen is accurate and attempts to do
+;;; the minimal amount of output to bring the screen into correspondence.
+;;; *screen-image-trashed* is only used by terminal redisplay.
+;;;
+(defun redisplay ()
+  "The main entry into redisplay; updates any windows that seem to need it."
+  (when *things-to-do-once*
+    (dolist (thing *things-to-do-once*) (apply (car thing) (cdr thing)))
+    (setf *things-to-do-once* nil))
+  (cond (*in-redisplay* t)
+	(*screen-image-trashed*
+	 (when (eq (redisplay-all) t)
+	   (setf *screen-image-trashed* nil)
+	   t))
+	(t
+	 (redisplay-loop redisplay-window redisplay-window-recentering))))
+
+
+;;; REDISPLAY-ALL -- Public.
+;;;
+;;; Update the screen making no assumptions about its correctness.  This is
+;;; useful if the screen gets trashed, or redisplay gets lost.  Since windows
+;;; may be on different devices, we have to go through the list clearing all
+;;; possible devices.  Always returns T or :EDITOR-INPUT, never NIL.
+;;;
+(defun redisplay-all ()
+  "An entry into redisplay; causes all windows to be fully refreshed."
+  (let ((cleared-devices nil))
+    (dolist (w *window-list*)
+      (let* ((hunk (window-hunk w))
+	     (device (device-hunk-device hunk)))
+	(unless (member device cleared-devices :test #'eq)
+	  (when (device-clear device)
+	    (funcall (device-clear device) device))
+	  ;;
+	  ;; It's cleared whether we did clear it or there was no method.
+	  (push device cleared-devices)))))
+  (redisplay-loop
+   redisplay-window-all
+   #'(lambda (window)
+       (setf (window-tick window) (tick))
+       (update-window-image window)
+       (maybe-recenter-window window)
+       (funcall (device-dumb-redisplay
+		 (device-hunk-device (window-hunk window)))
+		window)
+       t)))
+
+
+
+
+;;;; Internal redisplay entry points.
+
+(defun internal-redisplay ()
+  "The main internal entry into redisplay.  This is just like REDISPLAY, but it
+   doesn't call the device's after-redisplay method."
+  (when *things-to-do-once*
+    (dolist (thing *things-to-do-once*) (apply (car thing) (cdr thing)))
+    (setf *things-to-do-once* nil))
+  (cond (*in-redisplay* t)
+	(*screen-image-trashed*
+	 (when (eq (redisplay-all) t)
+	   (setf *screen-image-trashed* nil)
+	   t))
+	(t
+	 (redisplay-loop redisplay-window redisplay-window-recentering))))
+
+;;; REDISPLAY-WINDOWS-FROM-MARK -- Internal Interface.
+;;;
+;;; hemlock-output-stream methods call this to update the screen.  It only
+;;; redisplays windows which are displaying the buffer concerned and doesn't
+;;; deal with making the cursor track the point.  *screen-image-trashed* is
+;;; only used by terminal redisplay.  This must call the device after-redisplay
+;;; method since stream output may occur without ever returning to the
+;;; Hemlock input/event-handling loop.
+;;;
+(defun redisplay-windows-from-mark (mark)
+  (when *things-to-do-once*
+    (dolist (thing *things-to-do-once*) (apply (car thing) (cdr thing)))
+    (setf *things-to-do-once* nil))
+  (cond ((or *in-redisplay* (not *in-the-editor*)) t)
+	((listen-editor-input *real-editor-input*) :editor-input)
+	(*screen-image-trashed*
+	 (when (eq (redisplay-all) t)
+	   (setf *screen-image-trashed* nil)
+	   t))
+	(t
+	 (catch 'redisplay-catcher
+	   (let ((buffer (line-buffer (mark-line mark))))
+	     (when buffer
+	       (flet ((frob (win)
+			(let* ((device (device-hunk-device (window-hunk win)))
+			       (force (device-force-output device))
+			       (after (device-after-redisplay device)))
+			  (when force (funcall force))
+			  (when after (funcall after device)))))
+		 (let ((windows (buffer-windows buffer)))
+		   (when (member *current-window* windows :test #'eq)
+		     (redisplay-window-recentering *current-window*)
+		     (frob *current-window*))
+		   (dolist (window windows)
+		     (unless (eq window *current-window*)
+		       (redisplay-window window)
+		       (frob window)))))))))))
+
+;;; REDISPLAY-WINDOW -- Internal.
+;;;
+;;; Return t if there are any changed lines, nil otherwise.
+;;;
+(defun redisplay-window (window)
+  "Maybe updates the window's image and calls the device's smart redisplay
+   method.  NOTE: the smart redisplay method may throw to
+   'hi::redisplay-catcher to abort redisplay."
+  (maybe-update-window-image window)
+  (prog1
+      (not (eq (window-first-changed window) *the-sentinel*))
+    (funcall (device-smart-redisplay (device-hunk-device (window-hunk window)))
+	     window)))
+
+(defun redisplay-window-all (window)
+  "Updates the window's image and calls the device's dumb redisplay method."
+  (setf (window-tick window) (tick))
+  (update-window-image window)
+  (funcall (device-dumb-redisplay (device-hunk-device (window-hunk window)))
+	   window)
+  t)
+
+(defun random-typeout-redisplay (window)
+  (catch 'redisplay-catcher
+    (maybe-update-window-image window)
+    (let* ((device (device-hunk-device (window-hunk window)))
+	   (force (device-force-output device)))
+      (funcall (device-smart-redisplay device) window)
+      (when force (funcall force)))))
+
+
+
+;;;; Support for redisplay entry points.
+
+;;; REDISPLAY-WINDOW-RECENTERING -- Internal.
+;;;
+;;; This tries to be clever about updating the window image unnecessarily,
+;;; recenters the window if the window's buffer's point moved off the window,
+;;; and does a smart redisplay.  We call the redisplay method even if we didn't
+;;; update the image or recenter because someone else may have modified the
+;;; window's image and already have updated it; if nothing happened, then the
+;;; smart method shouldn't do anything anyway.  NOTE: the smart redisplay
+;;; method may throw to 'hi::redisplay-catcher to abort redisplay.
+;;;
+;;; This return t if there are any changed lines, nil otherwise.
+;;; 
+(defun redisplay-window-recentering (window)
+  (setup-for-recentering-redisplay window)
+  (invoke-hook hemlock::redisplay-hook window)
+  (setup-for-recentering-redisplay window)
+  (prog1
+      (not (eq (window-first-changed window) *the-sentinel*))
+    (funcall (device-smart-redisplay (device-hunk-device (window-hunk window)))
+	     window)))
+
+(defun setup-for-recentering-redisplay (window)
+  (let* ((display-start (window-display-start window))
+	 (old-start (window-old-start window)))
+    ;;
+    ;; If the start is in the middle of a line and it wasn't before,
+    ;; then move the start there.
+    (when (and (same-line-p display-start old-start)
+	       (not (start-line-p display-start))
+	       (start-line-p old-start))
+      (line-start display-start))
+    (maybe-update-window-image window)
+    (maybe-recenter-window window)))
+
+
+;;; MAYBE-UPDATE-WINDOW-IMAGE only updates if the text has changed or the
+;;; display start.
+;;; 
+(defun maybe-update-window-image (window)
+  (when (or (> (buffer-modified-tick (window-buffer window))
+	       (window-tick window))
+	    (mark/= (window-display-start window)
+		    (window-old-start window)))
+    (setf (window-tick window) (tick))
+    (update-window-image window)
+    t))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/dylan.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/dylan.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/dylan.lisp	(revision 13309)
@@ -0,0 +1,66 @@
+;;; -*- Package: hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains a minimal dylan mode.
+;;;
+(in-package :hemlock)
+
+;;; hack ..
+
+(setf (getstring "dylan" *mode-names*) nil)
+
+
+(defmode "Dylan" :major-p t)
+(defcommand "Dylan Mode" (p)
+  "Put the current buffer into \"Dylan\" mode."
+  "Put the current buffer into \"Dylan\" mode."
+  (declare (ignore p))
+  (setf (buffer-major-mode (current-buffer)) "Dylan"))
+
+(define-file-type-hook ("dylan") (buffer type)
+  (declare (ignore type))
+  (setf (buffer-major-mode buffer) "Dylan"))
+
+(defhvar "Indent Function"
+  "Indentation function which is invoked by \"Indent\" command.
+   It must take one argument that is the prefix argument."
+  :value #'generic-indent
+  :mode "Dylan")
+
+(defhvar "Auto Fill Space Indent"
+  "When non-nil, uses \"Indent New Comment Line\" to break lines instead of
+   \"New Line\"."
+  :mode "Dylan" :value t)
+
+(defhvar "Comment Start"
+  "String that indicates the start of a comment."
+  :mode "Dylan" :value "//")
+
+(defhvar "Comment End"
+  "String that ends comments.  Nil indicates #\newline termination."
+  :mode "Dylan" :value nil)
+
+(defhvar "Comment Begin"
+  "String that is inserted to begin a comment."
+  :mode "Dylan" :value "// ")
+
+(bind-key "Delete Previous Character Expanding Tabs" #k"backspace"
+	  :mode "Dylan")
+(bind-key "Delete Previous Character Expanding Tabs" #k"delete" :mode "Dylan")
+
+;;; hacks...
+
+(shadow-attribute :scribe-syntax #\< nil "Dylan")
+(shadow-attribute :scribe-syntax #\> nil "Dylan")
+(bind-key "Self Insert" #k"\>" :mode "Dylan")
+(bind-key "Scribe Insert Bracket" #k")" :mode "Dylan")
+(bind-key "Scribe Insert Bracket" #k"]" :mode "Dylan")
+(bind-key "Scribe Insert Bracket" #k"}" :mode "Dylan")
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/README
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/README	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/README	(revision 13309)
@@ -0,0 +1,52 @@
+This is currently a work-in-progess.
+
+The aim is to build an environment taht lets most elisp packages run inside
+PHemlock. Two things that explicitly will not be handled is "emacs sockets"
+and "emacs sub-processes". There may be stubs for them, actuallym, there
+will probably be stubs for them.
+
+Currently, most of the code is horribly uncommented and there's next-to-no
+docstrings. This will be fixed, at some point.
+
+The current files in the implementation, with a description of my
+generals thoughts of what should go where:
+
+base.lisp: This is the "base elisp" implementation. Things here end up
+           in the ELISP package and should in general be "user visible".
+
+codewalker.lisp: This is a code walker necessary to wrap "variable
+           access". It's not the most well-tested piece of code in the
+           world, but so far it hasn't fallen over on my test cases.
+
+hemlock-shims.lisp: This is functions that need to interact deeply
+                    with Hemlock (key definitions etc, etc).
+
+internals.lisp: This is the file for what ends up being needed but not
+                fitting anywhere else.
+
+loadup.lisp: Load all files, in something approaching a sensible order.
+
+packages.lisp: Package definitions.
+
+read-table.lisp: Readtables and support functions.
+
+implementation-needed: Contains a tentative list of symbols in GNU
+    Emacs that may or may not need sensible implementation before
+    we're done. Theory is, once all built-ins are in place, we can
+    then bootstrap off whatever files tag along with emacs, should
+    anyone want to.
+
+Here are some things to look at before releasing:
+[new-bbox]
+|Warning: These variables are undefined:
+|  MAJOR-MODE MODE-NAME
+|
+|
+|Warning: These functions are undefined:
+|  DEFINE-KEY GET-BUFFER-CREATE MAKE-SPARSE-KEYMAP SET-BUFFER SWITCH-TO-BUFFER 
+|  USE-LOCAL-MAP
+
+
+
+
+//Ingvar <ingvar@bofh.se>
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/base.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/base.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/base.lisp	(revision 13309)
@@ -0,0 +1,260 @@
+(in-package "ELISP")
+
+(defvar load-path nil)
+(defvar features nil)
+(defvar *buffer-locals* (make-hash-table))
+(defvar *current-buffer* nil)
+(define-symbol-macro major-mode (buffer-major-mode (current-buffer)))
+
+
+(cl:defun make-sparse-keymap (&optional string)
+  (if string
+      (list 'keymap string)
+    (list 'keymap)))
+
+(cl:defun make-keymap (&optional string)
+  (if string
+      (list 'keymap string (make-vector 256))
+    (list 'keymap (make-vector 256))))
+
+(cl:defun make-sparse-keymap (&optional string)
+  (if string
+      (list 'keymap string)
+    (list 'keymap)))
+
+(cl:defun buffer-local-p (sym)
+  (multiple-value-bind (expansion expanded) (macroexpand sym)
+    (declare (ignore expansion))
+    expanded))
+
+(cl:defun elisp-value (sym)
+  (cl:let ((marker (gensym)))
+    (multiple-value-bind (value exists)
+	(gethash sym *buffer-locals*)
+      (if exists
+	  (hemlock::variable-value sym)
+	  (eval sym)))))
+
+(cl:defun = (a b)
+  (cond ((and (characterp a) (characterp b))
+	 (char= a b))
+	((and (numberp a) (characterp b))
+	 (cl:= a (char-code b)))
+	((and (characterp a) (numberp b))
+	 (cl:= (char-code a) b))
+	((and (numberp a) (numberp b))
+	 (cl:= a b))
+	(t (error "Wrong type argument ~a" (if (or (numberp a) (characterp a))
+					       b
+					     a)))))
+
+(cl:defun make-variable-buffer-local (sym)
+  (make-variable-foo-local sym :buffer))
+
+(cl:defun make-variable-foo-local (sym kind)
+  "MAKE-VARIABLES-BUFFER-LOCAL
+Arguments SYMBOL
+
+Will make a variable buffer-local UNLESS it has prior special binding,
+this may be a grave incompatibility with Emacs Lisp.
+
+In a buffer where no dedicated value has been set, will use the
+default-value. The default value is set with SET-DEFAULT."
+  (unless (hemlock::hemlock-bound-p sym)
+    (setf (gethash sym *buffer-locals*) kind)
+    (defhvar sym "Variable automatically set from ELISP" :mode :kind)
+    ))
+
+
+;;; Troublesome? Looks like it IM -- 2003-04-05
+(cl:defun set-default (sym value)
+  "SET-DEFAULT
+Args: SYMBOL VALUE
+
+Will set the default value of (the buffer-local) SYMBOL to VALUE"
+  (if (buffer-local-p sym)
+      (setf (gethash *buffer-locals* (gethash sym *buffer-locals*)) value)
+      (set sym value)))
+
+;;; Troublesome? Looks like it IM -- 2003-04-05
+(cl:defun get-default (sym)
+  "GET-DEFAULT
+Args: SYMBOL
+
+Returns the default value for SYMBOL"
+  (if (buffer-local-p sym)
+      (gethash *buffer-locals* (gethash sym *buffer-locals*))
+      (symbol-value sym)))
+
+(cl:defmacro interactive (&rest spec)
+  (declare (ignore spec))
+  nil)
+
+;;; This really should generate a glue function to handle the differences
+;;; betwen emacs command calling conventions and Hemlock ccc.
+;;; Basically, what we need is a layer that does all the prompting that
+;;; would've been done on an interactive call in emacs. Probably simplest
+;;; to just generate a lambda with the right stuff prompted for, then have
+;;; that call the function proper.
+(cl:defmacro defun (name args &body body)
+  (cl:let ((real-args (elisp-internals:find-lambda-list-variables args))
+	   (body (walk-code `(defun ,name ,args ,@body)))
+	   (maybe-docstring (car body))
+	   (interactive-p (member 'interactive body :key #'(lambda (x) (when (consp x) (car x))))))
+    (if interactive-p
+	`(prog1
+	  (cl:defun ,name ,args
+	    (declare (special ,@real-args))
+	    ,@(cdddr body))
+	  (make-command ,(string-downcase (string name))
+	   ,(if (stringp maybe-docstring)
+	       maybe-docstring
+	       (format nil "This implements the elisp command for function ~a." (string name))) ,(elisp-internals:interactive-glue (cadr (car interactive-p)) name)))
+	
+	`(cl:defun ,name ,args
+	  (declare (special ,@real-args))
+	  ,@(cdddr body)))))
+
+(cl:defmacro let (inits &body body)
+  (cl:let ((vars (loop for var in inits
+		       collect (cl:if (symbolp var) var (car var)))))
+    `(cl:let ,inits
+      (declare (special ,@vars))
+      ,@body)))
+
+(cl:defmacro if (test true &rest falses)
+  `(cl:if ,test ,true (progn ,@falses)))
+
+(cl:defmacro lexical-let (&rest body)
+  `(cl:let ,@body ))
+
+(cl:defmacro setq (&rest rest)
+  `(cl:setf ,@rest))
+
+(cl:defun provide (feature)
+  (cl:push feature features))
+
+(cl:defun require (feature &optional filename noerror)
+  (let ((*readtable* elisp-internals:*elisp-readtable*))
+    (or
+     (car (member feature features))
+     (loop for directory in load-path
+	   if (elisp-internals:require-load directory feature filename)
+	   return feature)
+     (unless noerror
+       (error "Cannot open file ~a." (if filename
+					 filename
+				       (cl:string-downcase feature)))))))
+
+;; Done via CL:DEFUN since the code walker wreaks havoc with the loop macro.
+;; Keep these together for sanity's sake
+(cl:defun load-library (library-name)
+  (loop for directory in load-path
+	do (loop for ext in '(".el" "")
+		 for name = (format nil "~a/~a~a" directory library-name ext)
+		 if (cl:probe-file name)
+		 do (return-from load-library
+		      (let (*package* (find-package "ELISP-USER"))
+			(let ((*readtable* elisp-internals:*elisp-readtable*))
+			  (cl:load name)))))))
+
+(cl:defun load-file (filename)
+  (let ((*readtable* elisp-internals:*elisp-readtable*)
+	(*package* (find-package "ELISP-USER")))
+    (load filename)))
+
+(make-command "load-file" "Load a file, elisp style" #'(lambda (p) (declare (ignore p)) (load-file (hemlock-internals:prompt-for-file :prompt "Load file: "))))
+(make-command "load-library" "Load a library, elisp-style" #'(lambda (p) (declare (ignore p)) (load-library (hemlock-internals:prompt-for-string :prompt "Load library: "))))
+;; End of things kept together
+
+;; Unfinished, including at least *one* function taht isn't implemented
+;; (and will be hell to make portably, I'm afraid)
+(cl:defun expand-file-name (name &optional default-directory)
+  (cl:let ((result (search "~" name)))
+    (if result
+      (cl:let ((name (subseq name result)))
+	(if (char= (cl:aref name 1) #\/)
+	    (merge-pathnames (subseq name 2) (elisp-internals:get-user-homedir))
+	  (cl:let ((username (subseq name 1 (search "/" name)))
+		   (directory (subseq name (1+ (search "/" name)))))
+	    (merge-pathnames directory (elisp-internals:get-user-homedir username)))))
+      name
+      )))
+
+(cl:defmacro while (test &body body)
+  `(cl:do ()
+       ((not ,test) nil)
+     ,@body))
+
+(cl:defmacro aset (array index new-element)
+  `(setf (cl:aref ,array ,index) ,new-element))
+
+(cl:defmacro assq (key list)
+  `(cl:assoc ,key ,list :test 'eq))
+
+(cl:defmacro assoc (key list)
+  `(cl:assoc ,key ,list :test 'equal))
+
+(cl:defun % (x y)
+  "Return the remainder of X divided by Y, both X and Y must be integers"
+  (declare (integer x y))
+  (mod x y))
+
+(cl:defun car-safe (object)
+  (when (consp object)
+    (car object)))
+
+(cl:defun cdr-safe (object)
+  (when (consp object)
+    (cdr object)))
+
+(cl:defun car-less-than-car (a b)
+  (< (car a) (car b)))
+
+(cl:defun bool-vector-p (array)
+  (and (simple-vector-p array)
+       (eq (element-type array) 'bit)))
+
+(cl:defun aref (vector &rest indices)
+  (if (bool-vector-p vector)
+      (= 1 (apply #'cl:aref vector indices))
+    (apply #'cl:aref vector indices)))
+
+(cl:defun make-bool-vector (length init)
+  (make-array (list length) :element-type bit :initial-element (if init 1 0)))
+
+(cl:defun delq (element list)
+  (cl:delete element list :test #'cl:eq))
+
+(cl:defun fset (symbol function)
+  (cl:setf (symbol-function symbol) function))
+
+(cl:defmacro autoload (function file &optional docstring interactive type)
+  (cond ((and docstring interactive)
+	 `(defun ,function (&rest args)
+	    ,docstring
+	    (interactive)
+	    (unless (gethash ',function elisp-internals::*autoloads* nil)
+	      (setf (gethash ',function elisp-internals::*autoloads*) t)
+	      (load ,file))
+	    (apply ',function args)))
+	((and docstring (not interactive))
+	 `(defun ,function (&rest args)
+	    ,docstring
+	    (unless (gethash ',function elisp-internals::*autoloads* nil)
+	      (setf (gethash ',function elisp-internals::*autoloads*) t)
+	      (load ,file))
+	    (apply ',function args)))
+	(interactive
+	 `(defun ,function (&rest args)
+	    (interactive)
+	    (unless (gethash ',function elisp-internals::*autoloads* nil)
+	      (setf (gethash ',function elisp-internals::*autoloads*) t)
+	      (load ,file))
+	    (apply ',function args)))
+	(t
+	 `(defun ,function (&rest args)
+	    (unless (gethash ',function elisp-internals::*autoloads* nil)
+	      (setf (gethash ',function elisp-internals::*autoloads*) t)
+	      (load ,file))
+	    (apply ',function args)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/cmucl-hemlock-glue.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/cmucl-hemlock-glue.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/cmucl-hemlock-glue.lisp	(revision 13309)
@@ -0,0 +1,15 @@
+;;; File to fix Irritating Impedance Mismatch between
+;;; CMU CL Hemlock and PortableHemlock.
+
+#+cmu
+(unless (find-package :hemlock-ext)
+  #-hemlock
+  (progn
+    (load "/usr/share/common-lisp/systems/cmucl-hemlock.system")
+    (mk:oos :cmucl-hemlock :load))
+
+  ;; OK, here comes the nasty. CMUCLHemlock stuffs things in the "EXT"
+  ;; package (system-dependent stuff, basically). We expect things to be
+  ;; orderly and live in a Hemlock package. Thus:
+  (common-lisp::enter-new-nicknames (find-package "EXTENSIONS") '("HEMLOCK-EXT")))
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/codewalker.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/codewalker.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/codewalker.lisp	(revision 13309)
@@ -0,0 +1,71 @@
+;;; The code walker should ideally be in ELISP-INTERNALS, however
+;;; getting it there won't be trivial, so ignoring that for now.
+(in-package "ELISP")
+
+(cl:defun walk-code (form &optional lexicals)
+  (cond ((null form) nil)
+	((numberp form) form)
+	((stringp form) form)
+	((atom form) (if (member form lexicals)
+			    form
+			  `(elisp-value ',form)))
+	(t (cl:let ((head (car form))
+		    (rest (cdr form)))
+	     (cond ((eq head 'lexical-let)
+		    (cl:let ((bindings (append lexicals
+					       (mapcar #'(lambda (x)
+							   (cl:if (symbolp x)
+								  x
+								  (car x)))
+						       (car rest))))
+			     (tail (cdr rest)))
+		      (cons head
+			    (cons (mapcar #'(lambda (form)
+					      (walk-code form lexicals))
+					  (car rest))
+				  (mapcar #'(lambda (form)
+					      (walk-code form bindings))
+					  tail)))))
+		   ((eq head 'let)
+		    (cons head (cons (mapcar #'(lambda (form)
+					     (walk-code form lexicals))
+					     (car rest))
+				     (mapcar #'(lambda (form)
+					     (walk-code form lexicals))
+					     (cdr rest)))))
+		   ((member head '(defun defmacro))
+		    (cl:let ((name (car rest))
+			     (new-vars
+			      (cl:loop for sym in (cadr rest)
+				       if (not
+					   (member sym '(&optional &rest
+							 &aux &key)))
+				       collect sym))
+			     (forms (cddr rest))
+			     (vars (cadr rest)))
+		      `(,head ,name ,vars
+			,@(mapcar
+			   #'(lambda (form)
+			       (walk-code form
+					  (append lexicals new-vars)))
+			   forms))))
+		   ((eq head 'cond)
+		    (cons head
+			  (cl:loop for cond-form in rest
+				collect
+				(cl:loop for form in cond-form
+					 collect (walk-code form lexicals)))))
+		   ((eq head 'quote)
+		    (cons head rest))
+		   ((member head '(setq setf))
+		    (cons head
+			  (loop for symbol in rest
+				for toggle = t then (not toggle)
+				if toggle
+				collect symbol
+				else
+				collect (walk-code symbol lexicals))))
+		   (t (cons head (mapcar #'(lambda (form)
+					     (walk-code form lexicals))
+					 rest))))))))
+	  
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/compile.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/compile.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/compile.lisp	(revision 13309)
@@ -0,0 +1,6 @@
+(load "loadup")
+(compile-file "read-table")
+(compile-file "internals")
+(compile-file "codewalker")
+(compile-file "base")
+(compile-file "hemlock-shims")
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/hemlock-shims.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/hemlock-shims.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/hemlock-shims.lisp	(revision 13309)
@@ -0,0 +1,77 @@
+(in-package "ELISP")
+
+(cl:defun mangle-key (key)
+  "Turn a CL-elisp key designator to a PHemlock KEY-EVENT"
+  (typecase key
+;    (string (with-input-from-string (stream key)
+;	       (let ((*readtable* elisp-internals:*elisp-readtable*))
+;		 (elisp-internals::read-string-char stream :event))))
+    (string (map 'vector #'mangle-key key))
+    ((or vector array)
+     (map 'vector #'mangle-key key))
+    (hemlock-ext:key-event key)
+    ((or integer character)
+     (multiple-value-bind (ismeta ischar) (truncate (if (characterp key)
+							(char-code key)
+						      key) 
+						    128)
+		 (cl:let ((charspec (if (cl:= 1 ismeta) (list :meta))))
+		   (when (< ischar 32)
+		       (push :control charspec)
+		       (setq ischar (1- (+ ischar (char-code #\a)))))
+		   (push (code-char ischar) charspec)
+		   (elisp-internals::emit-character (reverse charspec) :event)
+		   )))))
+
+(cl:defun global-set-key (key command)
+  (let ((key (mangle-key key)))
+    (bind-key (string command) key :global)))
+
+(cl:defun local-set-key (key command)
+  (let ((key (mangle-key key)))
+    (bind-key (string command) key :mode major-mode)))
+
+(cl:defun use-local-map (keymap)
+  (cond ((and (listp keymap)
+	      (eq (car keymap) 'keymap))
+	 (cl:let ((has-menu-name (stringp (cadr keymap))))
+	   (let ((char-table (if has-menu-name
+				 (if (vectorp (caddr keymap))
+				     (caddr keymap))
+			       (if (vectorp (cadr keymap))
+				     (cadr keymap))))
+		 (the-alist (if has-menu-name
+				(if (vectorp (caddr keymap))
+				     (cdddr keymap))
+			      (if (vectorp (cadr keymap))
+				     (cddr keymap)))))
+	     ; iterate through the relevant sections
+	     )))
+	((symbolp keymap)
+	 (use-local-map (eval keymap)))))
+
+(cl:defun get-buffer-create (buffer-name)
+  (or (getstring buffer-name *buffer-names*)
+      (make-buffer buffer-name)))
+
+(cl:defun get-buffer (buffer-name)
+   (getstring buffer-name *buffer-names*))
+
+(cl:defun commandp (function-designator)
+  (typecase function-designator
+    (symbol (hemlock-internals:commandp (getstring (string-downcase (string function-designator)) hemlock-internals:*command-names*)))
+    (function nil) ; Bug, but as far as I can tell, we can't portably
+                   ; extract the name from the function object
+    (string (hemlock-internals:commandp (getstring (string-downcase function-designator) hemlock-internals:*command-names*)))
+    (t nil)))
+
+(cl:defun bolp ()
+  (= 0 (hemlock-internals:mark-charpos (hemlock-internals:current-point))))
+
+(cl:defun bobp ()
+  (and (= 0 (hemlock-internals::line-number (hemlock-internals:mark-line (hemlock-internals:current-point))))
+       (bolp)))
+
+(cl:defun abort-recursive-edit ()
+  (and (hemlock-internals:in-recursive-edit)
+       (hemlock-internals:exit-recursive-edit)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/implementation-needed
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/implementation-needed	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/implementation-needed	(revision 13309)
@@ -0,0 +1,779 @@
+abbrev-expansion ; elisp
+abbrev-symbol ; elisp
+accept-process-output ; elisp
+access-file ; elisp
+accessible-keymaps ; elisp
+active-minibuffer-window ; elisp
+add-name-to-file ; elisp
+add-text-properties ; elisp
+all-completions ; elisp
+apropos-internal ; elisp
+backtrace ; elisp
+backtrace-debug ; elisp
+backward-char ; elisp
+backward-prefix-chars ; elisp
+barf-if-buffer-read-only ; elisp
+base64-decode-region ; elisp
+base64-decode-string ; elisp
+base64-encode-region ; elisp
+base64-encode-string ; elisp
+beginning-of-line ; elisp
+bitmap-spec-p ; elisp
+buffer-base-buffer ; elisp
+buffer-disable-undo ; elisp
+buffer-enable-undo ; elisp
+buffer-file-name ; elisp
+buffer-has-markers-at ; elisp
+buffer-list ; elisp
+buffer-live-p ; elisp
+buffer-local-variables ; elisp
+buffer-modified-p ; elisp
+buffer-modified-tick ; elisp
+buffer-name ; elisp
+buffer-size ; elisp
+buffer-string ; elisp
+buffer-substring ; elisp
+buffer-substring-no-properties ; elisp
+bufferp ; elisp
+bury-buffer ; elisp
+byte-code ; elisp
+byte-code-function-p ; elisp
+byte-to-position ; elisp
+c-beginning-of-defun ; elisp
+call-interactively ; elisp
+call-last-kbd-macro ; elisp
+call-process ; elisp
+call-process-region ; elisp
+cancel-kbd-macro-events ; elisp
+capitalize ; elisp
+capitalize-region ; elisp
+capitalize-word ; elisp
+case-table-p ; elisp
+category-docstring ; elisp
+category-set-mnemonics ; elisp
+category-table ; elisp
+category-table-p ; elisp
+ccl-execute ; elisp
+ccl-execute-on-string ; elisp
+ccl-program-p ; elisp
+char-after ; elisp
+char-before ; elisp
+char-bytes ; elisp
+char-category-set ; elisp
+char-charset ; elisp
+char-direction ; elisp
+char-or-string-p ; elisp
+char-syntax ; elisp
+char-table-extra-slot ; elisp
+char-table-p ; elisp
+char-table-parent ; elisp
+char-table-range ; elisp
+char-table-subtype ; elisp
+char-to-string ; elisp
+char-valid-p ; elisp
+char-width ; elisp
+chars-in-region ; elisp
+charset-after ; elisp
+check-coding-system ; elisp
+clear-abbrev-table ; elisp
+clear-buffer-auto-save-failure ; elisp
+clear-face-cache ; elisp
+clear-image-cache ; elisp
+clear-this-command-keys ; elisp
+clear-visited-file-modtime ; elisp
+coding-system-p ; elisp
+color-gray-p ; elisp
+color-supported-p ; elisp
+combine-after-change-execute ; elisp
+command-execute ; elisp
+compare-buffer-substrings ; elisp
+compare-strings ; elisp
+compare-window-configurations ; elisp
+completing-read ; elisp
+compose-region-internal ; elisp
+compose-string-internal ; elisp
+compute-motion ; elisp
+concat ; elisp
+condition-case ; elisp
+constrain-to-field ; elisp
+continue-process ; elisp
+coordinates-in-window-p ; elisp
+copy-category-table ; elisp
+copy-file ; elisp
+copy-hash-table ; elisp
+copy-keymap ; elisp
+copy-marker ; elisp
+copy-sequence ; elisp
+copy-syntax-table ; elisp
+cp-make-coding-systems-for-codepage ; elisp
+cperl-mode ; elisp
+current-buffer ; elisp
+current-case-table ; elisp
+current-column ; elisp
+current-global-map ; elisp
+current-indentation ; elisp
+current-input-mode ; elisp
+current-local-map ; elisp
+current-message ; elisp
+current-minor-mode-maps ; elisp
+current-time ; elisp
+current-time-string ; elisp
+current-time-zone ; elisp
+current-window-configuration ; elisp
+declare-equiv-charset ; elisp
+decode-big5-char ; elisp
+decode-coding-region ; elisp
+decode-coding-string ; elisp
+decode-sjis-char ; elisp
+decode-time ; elisp
+defalias ; elisp
+default-boundp ; elisp
+default-file-modes ; elisp
+default-value ; elisp
+defconst ; elisp
+define-abbrev ; elisp
+define-abbrev-table ; elisp
+define-category ; elisp
+define-charset ; elisp
+define-global-abbrev ; elisp
+define-hash-table-test ; elisp
+define-key ; elisp
+define-mode-abbrev ; elisp
+define-prefix-command ; elisp
+defining-kbd-macro ; elisp
+delete-and-extract-region ; elisp
+delete-backward-char ; elisp
+delete-char ; elisp
+delete-directory ; elisp
+delete-field ; elisp
+delete-frame ; elisp
+delete-other-windows ; elisp
+delete-overlay ; elisp
+delete-process ; elisp
+delete-region ; elisp
+delete-window ; elisp
+delete-windows-on ; elisp
+describe-bindings-internal ; elisp
+describe-categories ; elisp
+describe-syntax ; elisp
+describe-vector ; elisp
+detect-coding-region ; elisp
+detect-coding-string ; elisp
+ding ; elisp
+directory-file-name ; elisp
+directory-files ; elisp
+directory-files-and-attributes ; elisp
+discard-input ; elisp
+display-buffer ; elisp
+display-completion-list ; elisp
+do-auto-save ; elisp
+documentation-property ; elisp
+downcase ; elisp
+downcase-region ; elisp
+downcase-word ; elisp
+dump-emacs ; elisp
+emacs-pid ; elisp
+encode-big5-char ; elisp
+encode-coding-region ; elisp
+encode-coding-string ; elisp
+encode-sjis-char ; elisp
+encode-time ; elisp
+end-kbd-macro ; elisp
+end-of-line ; elisp
+enlarge-window ; elisp
+eobp ; elisp
+eolp ; elisp
+erase-buffer ; elisp
+error-message-string ; elisp
+eval-buffer ; elisp
+eval-minibuffer ; elisp
+eval-region ; elisp
+event-convert-list ; elisp
+execute-extended-command ; elisp
+execute-kbd-macro ; elisp
+exit-minibuffer ; elisp
+exit-recursive-edit ; elisp
+expand-abbrev ; elisp
+expand-file-name ; elisp
+external-debugging-output ; elisp
+f90-mode ; elisp
+face-font ; elisp
+featurep ; elisp
+fetch-bytecode ; elisp
+field-beginning ; elisp
+field-end ; elisp
+field-string ; elisp
+field-string-no-properties ; elisp
+file-accessible-directory-p ; elisp
+file-attributes ; elisp
+file-attributes-lessp ; elisp
+file-directory-p ; elisp
+file-executable-p ; elisp
+file-exists-p ; elisp
+file-locked-p ; elisp
+file-modes ; elisp
+file-name-absolute-p ; elisp
+file-name-all-completions ; elisp
+file-name-as-directory ; elisp
+file-name-completion ; elisp
+file-name-directory ; elisp
+file-name-nondirectory ; elisp
+file-newer-than-file-p ; elisp
+file-readable-p ; elisp
+file-regular-p ; elisp
+file-symlink-p ; elisp
+file-writable-p ; elisp
+fillarray ; elisp
+find-charset-region ; elisp
+find-charset-string ; elisp
+find-coding-systems-region-internal ; elisp
+find-composition-internal ; elisp
+find-file-name-handler ; elisp
+find-operation-coding-system ; elisp
+float-time ; elisp
+following-char ; elisp
+font-info ; elisp
+fontset-font ; elisp
+fontset-info ; elisp
+fontset-list ; elisp
+format-time-string ; elisp
+fortran-mode ; elisp
+forward-char ; elisp
+forward-comment ; elisp
+forward-line ; elisp
+forward-point ; elisp
+forward-word ; elisp
+frame-char-height ; elisp
+frame-char-width ; elisp
+frame-face-alist ; elisp
+frame-first-window ; elisp
+frame-focus ; elisp
+frame-list ; elisp
+frame-live-p ; elisp
+frame-or-buffer-changed-p ; elisp
+frame-parameter ; elisp
+frame-parameters ; elisp
+frame-pixel-height ; elisp
+frame-pixel-width ; elisp
+frame-root-window ; elisp
+frame-selected-window ; elisp
+frame-visible-p ; elisp
+framep ; elisp
+gap-position ; elisp
+gap-size ; elisp
+garbage-collect ; elisp
+generate-new-buffer-name ; elisp
+generic-character-list ; elisp
+get-buffer-process ; elisp
+get-buffer-window ; elisp
+get-char-property ; elisp
+get-file-buffer ; elisp
+get-file-char ; elisp
+get-largest-window ; elisp
+get-lru-window ; elisp
+get-process ; elisp
+get-text-property ; elisp
+get-unused-category ; elisp
+get-unused-iso-final-char ; elisp
+getenv-internal ; elisp
+global-key-binding ; elisp
+goto-char ; elisp
+handle-switch-frame ; elisp
+hash-table-weakness ; elisp
+iconify-frame ; elisp
+ignore-event ; elisp
+image-mask-p ; elisp
+image-size ; elisp
+indent-to ; elisp
+indirect-function ; elisp
+input-pending-p ; elisp
+insert ; elisp
+insert-abbrev-table-description ; elisp
+insert-and-inherit ; elisp
+insert-before-markers ; elisp
+insert-before-markers-and-inherit ; elisp
+insert-buffer-substring ; elisp
+insert-char ; elisp
+insert-file-contents ; elisp
+insert-string ; elisp
+integer-or-marker-p ; elisp
+interactive-p ; elisp
+intern-soft ; elisp
+internal-char-font ; elisp
+internal-copy-lisp-face ; elisp
+internal-face-x-get-resource ; elisp
+internal-get-lisp-face-attribute ; elisp
+internal-lisp-face-attribute-values ; elisp
+internal-lisp-face-empty-p ; elisp
+internal-lisp-face-equal-p ; elisp
+internal-lisp-face-p ; elisp
+internal-make-lisp-face ; elisp
+internal-merge-in-global-face ; elisp
+internal-set-alternative-font-family-alist ; elisp
+internal-set-alternative-font-registry-alist ; elisp
+internal-set-font-selection-order ; elisp
+internal-set-lisp-face-attribute ; elisp
+internal-set-lisp-face-attribute-from-resource ; elisp
+internal-show-cursor ; elisp
+internal-show-cursor-p ; elisp
+interrupt-process ; elisp
+invocation-directory ; elisp
+invocation-name ; elisp
+iso-charset ; elisp
+iswitchb-read-buffer ; elisp
+key-binding ; elisp
+key-description ; elisp
+keyboard-coding-system ; elisp
+keymap-parent ; elisp
+keymapp ; elisp
+kill-all-local-variables ; elisp
+kill-buffer ; elisp
+kill-emacs ; elisp
+kill-local-variable ; elisp
+kill-process ; elisp
+line-beginning-position ; elisp
+line-end-position ; elisp
+list-processes ; elisp
+load-average ; elisp
+local-key-binding ; elisp
+local-variable-if-set-p ; elisp
+local-variable-p ; elisp
+lock-buffer ; elisp
+log10 ; elisp
+logb ; elisp
+looking-at ; elisp
+lookup-key ; elisp
+lower-frame ; elisp
+lsh ; elisp
+make-abbrev-table ; elisp
+make-byte-code ; elisp
+make-category-set ; elisp
+make-category-table ; elisp
+make-char-internal ; elisp
+make-char-table ; elisp
+make-directory-internal ; elisp
+make-frame-invisible ; elisp
+make-frame-visible ; elisp
+make-indirect-buffer ; elisp
+make-local-variable ; elisp
+make-marker ; elisp
+make-overlay ; elisp
+make-symbolic-link ; elisp
+make-temp-name ; elisp
+make-terminal-frame ; elisp
+make-variable-frame-local ; elisp
+make-vector ; elisp
+makehash ; elisp
+map-char-table ; elisp
+mapatoms ; elisp
+mapconcat ; elisp
+mark-marker ; elisp
+marker-buffer ; elisp
+marker-insertion-type ; elisp
+marker-position ; elisp
+markerp ; elisp
+match-beginning ; elisp
+match-data ; elisp
+match-end ; elisp
+matching-paren ; elisp
+md5 ; elisp
+memory-limit ; elisp
+memory-use-counts ; elisp
+memq ; elisp
+message ; elisp
+message-box ; elisp
+message-or-box ; elisp
+minibuffer-complete ; elisp
+minibuffer-complete-and-exit ; elisp
+minibuffer-complete-word ; elisp
+minibuffer-completion-help ; elisp
+minibuffer-depth ; elisp
+minibuffer-message ; elisp
+minibuffer-prompt ; elisp
+minibuffer-window ; elisp
+minor-mode-key-binding ; elisp
+ml-arg ; elisp
+ml-if ; elisp
+ml-interactive ; elisp
+ml-nargs ; elisp
+ml-prefix-argument-loop ; elisp
+ml-provide-prefix-argument ; elisp
+modify-category-entry ; elisp
+modify-frame-parameters ; elisp
+modify-syntax-entry ; elisp
+mouse-pixel-position ; elisp
+mouse-position ; elisp
+move-overlay ; elisp
+move-to-column ; elisp
+move-to-window-line ; elisp
+multibyte-char-to-unibyte ; elisp
+multibyte-string-p ; elisp
+narrow-to-region ; elisp
+natnump ; elisp
+new-fontset ; elisp
+next-char-property-change ; elisp
+next-frame ; elisp
+next-overlay-change ; elisp
+next-property-change ; elisp
+next-single-char-property-change ; elisp
+next-single-property-change ; elisp
+next-window ; elisp
+nlistp ; elisp
+number-or-marker-p ; elisp
+number-to-string ; elisp
+open-dribble-file ; elisp
+open-network-stream ; elisp
+open-termscript ; elisp
+optimize-char-table ; elisp
+other-buffer ; elisp
+other-window ; elisp
+other-window-for-scrolling ; elisp
+overlay-buffer ; elisp
+overlay-end ; elisp
+overlay-get ; elisp
+overlay-lists ; elisp
+overlay-properties ; elisp
+overlay-put ; elisp
+overlay-recenter ; elisp
+overlay-start ; elisp
+overlayp ; elisp
+overlays-at ; elisp
+overlays-in ; elisp
+parse-partial-sexp ; elisp
+play-sound ; elisp
+plist-get ; elisp
+plist-member ; elisp
+plist-put ; elisp
+point ; elisp
+point-marker ; elisp
+point-max ; elisp
+point-max-marker ; elisp
+point-min ; elisp
+point-min-marker ; elisp
+pop-to-buffer ; elisp
+pos-visible-in-window-p ; elisp
+position-bytes ; elisp
+posix-looking-at ; elisp
+posix-search-backward ; elisp
+posix-search-forward ; elisp
+posix-string-match ; elisp
+preceding-char ; elisp
+prefix-numeric-value ; elisp
+previous-char-property-change ; elisp
+previous-frame ; elisp
+previous-overlay-change ; elisp
+previous-property-change ; elisp
+previous-single-char-property-change ; elisp
+previous-single-property-change ; elisp
+previous-window ; elisp
+primitive-undo ; elisp
+process-buffer ; elisp
+process-coding-system ; elisp
+process-command ; elisp
+process-contact ; elisp
+process-exit-status ; elisp
+process-filter ; elisp
+process-id ; elisp
+process-inherit-coding-system-flag ; elisp
+process-kill-without-query ; elisp
+process-list ; elisp
+process-mark ; elisp
+process-name ; elisp
+process-running-child-p ; elisp
+process-send-eof ; elisp
+process-send-region ; elisp
+process-send-string ; elisp
+process-sentinel ; elisp
+process-status ; elisp
+process-tty-name ; elisp
+processp ; elisp
+propertize ; elisp
+purecopy ; elisp
+put ; elisp
+put-text-property ; elisp
+puthash ; elisp
+query-fontset ; elisp
+quit-process ; elisp
+raise-frame ; elisp
+rassq ; elisp
+re-search-backward ; elisp
+re-search-forward ; elisp
+read-buffer ; elisp
+read-char-exclusive ; elisp
+read-coding-system ; elisp
+read-command ; elisp
+read-event ; elisp
+read-file-name ; elisp
+read-file-name-internal ; elisp
+read-from-minibuffer ; elisp
+read-key-sequence ; elisp
+read-key-sequence-vector ; elisp
+read-minibuffer ; elisp
+read-no-blanks-input ; elisp
+read-non-nil-coding-system ; elisp
+read-string ; elisp
+read-variable ; elisp
+recent-auto-save-p ; elisp
+recent-keys ; elisp
+recenter ; elisp
+recursion-depth ; elisp
+recursive-edit ; elisp
+redirect-frame-focus ; elisp
+redraw-display ; elisp
+redraw-frame ; elisp
+regexp-quote ; elisp
+region-beginning ; elisp
+region-end ; elisp
+register-ccl-program ; elisp
+register-code-conversion-map ; elisp
+remove-text-properties ; elisp
+rename-buffer ; elisp
+replace-buffer-in-windows ; elisp
+replace-match ; elisp
+reset-this-command-lengths ; elisp
+restore-buffer-modified-p ; elisp
+run-hook-with-args ; elisp
+run-hook-with-args-until-failure ; elisp
+run-hook-with-args-until-success ; elisp
+run-hooks ; elisp
+safe-length ; elisp
+same-window-p ; elisp
+save-current-buffer ; elisp
+save-excursion ; elisp
+save-restriction ; elisp
+save-window-excursion ; elisp
+scan-lists ; elisp
+scan-sexps ; elisp
+scroll-down ; elisp
+scroll-left ; elisp
+scroll-other-window ; elisp
+scroll-right ; elisp
+scroll-up ; elisp
+search-backward ; elisp
+search-backward-regexp ; elisp
+search-forward ; elisp
+search-forward-regexp ; elisp
+select-frame ; elisp
+select-window ; elisp
+selected-frame ; elisp
+selected-window ; elisp
+self-insert-and-exit ; elisp
+self-insert-command ; elisp
+send-string-to-terminal ; elisp
+sequencep ; elisp
+set-buffer ; elisp
+set-buffer-auto-saved ; elisp
+set-buffer-major-mode ; elisp
+set-buffer-modified-p ; elisp
+set-buffer-multibyte ; elisp
+set-case-table ; elisp
+set-category-table ; elisp
+set-char-table-default ; elisp
+set-char-table-extra-slot ; elisp
+set-char-table-parent ; elisp
+set-char-table-range ; elisp
+set-coding-priority-internal ; elisp
+set-default-file-modes ; elisp
+set-file-modes ; elisp
+set-fontset-font ; elisp
+set-frame-height ; elisp
+set-frame-position ; elisp
+set-frame-selected-window ; elisp
+set-frame-size ; elisp
+set-frame-width ; elisp
+set-input-mode ; elisp
+set-keyboard-coding-system-internal ; elisp
+set-keymap-parent ; elisp
+set-marker ; elisp
+set-marker-insertion-type ; elisp
+set-match-data ; elisp
+set-minibuffer-window ; elisp
+set-mouse-pixel-position ; elisp
+set-mouse-position ; elisp
+set-process-buffer ; elisp
+set-process-coding-system ; elisp
+set-process-filter ; elisp
+set-process-inherit-coding-system-flag ; elisp
+set-process-sentinel ; elisp
+set-process-window-size ; elisp
+set-safe-terminal-coding-system-internal ; elisp
+set-standard-case-table ; elisp
+set-syntax-table ; elisp
+set-terminal-coding-system-internal ; elisp
+set-text-properties ; elisp
+set-time-zone-rule ; elisp
+set-visited-file-modtime ; elisp
+set-window-buffer ; elisp
+set-window-configuration ; elisp
+set-window-dedicated-p ; elisp
+set-window-display-table ; elisp
+set-window-hscroll ; elisp
+set-window-margins ; elisp
+set-window-point ; elisp
+set-window-redisplay-end-trigger ; elisp
+set-window-start ; elisp
+set-window-vscroll ; elisp
+setcar ; elisp
+setcdr ; elisp
+setplist ; elisp
+setq-default ; elisp
+setup-special-charsets ; elisp
+shrink-window ; elisp
+signal-process ; elisp
+single-key-description ; elisp
+sit-for ; elisp
+skip-chars-backward ; elisp
+skip-chars-forward ; elisp
+skip-syntax-backward ; elisp
+skip-syntax-forward ; elisp
+sleep-for ; elisp
+special-display-p ; elisp
+split-char ; elisp
+split-window ; elisp
+standard-case-table ; elisp
+standard-category-table ; elisp
+standard-syntax-table ; elisp
+start-kbd-macro ; elisp
+start-process ; elisp
+stop-process ; elisp
+store-kbd-macro-event ; elisp
+string-as-multibyte ; elisp
+string-as-unibyte ; elisp
+string-bytes ; elisp
+string-make-multibyte ; elisp
+string-make-unibyte ; elisp
+string-match ; elisp
+string-to-char ; elisp
+string-to-number ; elisp
+string-to-syntax ; elisp
+string-width ; elisp
+subr-interactive-form ; elisp
+subrp ; elisp
+subst-char-in-region ; elisp
+substitute-command-keys ; elisp
+substitute-in-file-name ; elisp
+substring ; elisp
+suspend-emacs ; elisp
+switch-to-buffer ; elisp
+syntax-table ; elisp
+syntax-table-p ; elisp
+system-name ; elisp
+terminal-coding-system ; elisp
+text-char-description ; elisp
+text-properties-at ; elisp
+text-property-any ; elisp
+text-property-not-all ; elisp
+this-command-keys ; elisp
+this-command-keys-vector ; elisp
+this-single-command-keys ; elisp
+this-single-command-raw-keys ; elisp
+tool-bar-lines-needed ; elisp
+top-level ; elisp
+track-mouse ; elisp
+translate-region ; elisp
+transpose-regions ; elisp
+try-completion ; elisp
+tty-display-color-p ; elisp
+tty-suppress-bold-inverse-default-colors ; elisp
+undo-boundary ; elisp
+unexpand-abbrev ; elisp
+unhandled-file-name-directory ; elisp
+unibyte-char-to-multibyte ; elisp
+unix-sync ; elisp
+unlock-buffer ; elisp
+upcase ; elisp
+upcase-initials ; elisp
+upcase-initials-region ; elisp
+upcase-region ; elisp
+upcase-word ; elisp
+update-coding-systems-internal ; elisp
+use-global-map ; elisp
+user-full-name ; elisp
+user-login-name ; elisp
+user-real-login-name ; elisp
+user-real-uid ; elisp
+user-uid ; elisp
+user-variable-p ; elisp
+vconcat ; elisp
+vector-or-char-table-p ; elisp
+verify-visited-file-modtime ; elisp
+vertical-motion ; elisp
+visible-frame-list ; elisp
+visited-file-modtime ; elisp
+waiting-for-user-input-p ; elisp
+where-is-internal ; elisp
+wholenump ; elisp
+widen ; elisp
+widget-apply ; elisp
+widget-get ; elisp
+widget-put ; elisp
+window-at ; elisp
+window-buffer ; elisp
+window-configuration-frame ; elisp
+window-configuration-p ; elisp
+window-dedicated-p ; elisp
+window-display-table ; elisp
+window-edges ; elisp
+window-end ; elisp
+window-frame ; elisp
+window-height ; elisp
+window-hscroll ; elisp
+window-list ; elisp
+window-live-p ; elisp
+window-margins ; elisp
+window-minibuffer-p ; elisp
+window-point ; elisp
+window-redisplay-end-trigger ; elisp
+window-start ; elisp
+window-text-height ; elisp
+window-vscroll ; elisp
+window-width ; elisp
+windowp ; elisp
+with-output-to-temp-buffer ; elisp
+word-search-backward ; elisp
+word-search-forward ; elisp
+write-region ; elisp
+x-backspace-delete-keys-p ; elisp
+x-change-window-property ; elisp
+x-close-connection ; elisp
+x-create-frame ; elisp
+x-delete-window-property ; elisp
+x-disown-selection-internal ; elisp
+x-display-backing-store ; elisp
+x-display-color-cells ; elisp
+x-display-grayscale-p ; elisp
+x-display-list ; elisp
+x-display-mm-height ; elisp
+x-display-mm-width ; elisp
+x-display-pixel-height ; elisp
+x-display-pixel-width ; elisp
+x-display-planes ; elisp
+x-display-save-under ; elisp
+x-display-screens ; elisp
+x-display-visual-class ; elisp
+x-family-fonts ; elisp
+x-focus-frame ; elisp
+x-font-family-list ; elisp
+x-get-cut-buffer-internal ; elisp
+x-get-resource ; elisp
+x-get-selection-internal ; elisp
+x-hide-tip ; elisp
+x-list-fonts ; elisp
+x-open-connection ; elisp
+x-own-selection-internal ; elisp
+x-parse-geometry ; elisp
+x-popup-dialog ; elisp
+x-popup-menu ; elisp
+x-rotate-cut-buffers-internal ; elisp
+x-selection-exists-p ; elisp
+x-selection-owner-p ; elisp
+x-server-max-request-size ; elisp
+x-server-vendor ; elisp
+x-server-version ; elisp
+x-show-tip ; elisp
+x-store-cut-buffer-internal ; elisp
+x-synchronize ; elisp
+x-window-property ; elisp
+xw-color-defined-p ; elisp
+xw-color-values ; elisp
+xw-display-color-p ; elisp
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/internals.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/internals.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/internals.lisp	(revision 13309)
@@ -0,0 +1,162 @@
+(in-package "ELISP-INTERNALS")
+
+(defvar *my-symbols* nil)
+(defvar *cl-symbols* nil)
+(defvar *cl-kluge-symbols* nil)
+(defvar *autoloads* (make-hash-table))
+
+(cl:defun find-lambda-list-variables (list)
+  (loop for elem in list
+	if (and (symbolp elem)
+		(not (member elem '(&optional &rest))))
+	collect elem))
+
+(cl:defun generate-cl-package ()
+  (when (and (null *my-symbols*)
+	     (null *cl-symbols*)
+	     (null *cl-kluge-symbols*))
+    (setf *my-symbols* (make-hash-table :test 'equal))
+    (loop for sym being the present-symbols of (find-package "ELISP")
+	  do (cl:let ((name (symbol-name sym)))
+	       (setf (gethash name *my-symbols*) name)))
+    (setf *cl-kluge-symbols*
+	  (loop for sym being the external-symbol
+		of (find-package "COMMON-LISP")
+		collect sym))
+    (setf *cl-symbols*
+	  (loop for sym in *cl-kluge-symbols*
+		when (and (not (gethash (symbol-name sym) *my-symbols*))
+			  (fboundp sym))
+		collect (symbol-name sym)))
+    (cl:let ((rv (with-output-to-string (s)
+		   (format s "(in-package \"ELISP\")~%")
+		   (loop for symname in *cl-symbols*
+			 do
+			 (format s "(cl:defmacro cl-~a (&rest args)~%`(cl:~a ,@args))~%~%~%" symname symname)
+			 finally (format s "(export '~a (find-package \"ELISP\"))~%" *cl-kluge-symbols*)))))
+      (with-input-from-string (stream rv)
+	(load stream)))))
+
+(cl:defun require-load (directory feature filename)
+  (if filename
+      (cl:let ((fname (format nil "~a/~a" directory filename)))
+	(when (cl:probe-file fname)
+	  (cl:let ((*package* (cl:find-package "ELISP-USER")))
+	    (load fname)
+	    (cl:if (member feature elisp::features)
+		   feature)))) 
+      (cl:let ((fname-1
+		(format nil "~a.el" (cl:string-downcase feature)))
+	       (fname-2
+		(format nil "~a" (cl:string-downcase feature))))
+	(or (require-load directory feature fname-1)
+	    (require-load directory feature fname-2)))))
+
+;;; Almost there!
+;;; Basic thought: "generate a lambda expression that acts as a shim"
+;;; NB: Does not handle "*" (read-only buffer signals error) or
+;;; "@" (magic find-window-specifying--set-window indicator)
+(cl:defun interactive-glue (initform function)
+  (if initform	  
+      (cl:let ((args (cl:with-input-from-string (s initform)
+			(cl:loop for l = (cl:read-line s nil nil)
+				 while l collect l))))
+	      (multiple-value-bind (types prompt)
+		  (cl:loop for l in args
+			   collect (aref l 0) into type
+			   collect (subseq l 1) into prompt
+			   finally (return (values type prompt)))
+		`(lambda (p)
+		   (funcall #',function
+			    ,@(cl:loop for type in types
+				       for pr in prompt
+				       for extracollect = nil
+				       collect
+				       (case type
+					 (#\a ;; unimplemented -- function
+					  )
+					 (#\b ;; existing buffer
+					  `(hemlock-internals:prompt-for-buffer
+					    :prompt :pr
+					    :must-exist nil))
+					 (#\B	; unimplemented -- buffer name
+					; Note, this may need a wrapper to
+					; coerce stuff to buffers
+					  `(hemlock-internals:prompt-for-buffer
+					    :prompt :pr
+					    :must-exist nil))
+					 (#\c ;; unimplemented -- character
+					  )
+					 (#\d '(hemlock-internals::current-point))
+					 (#\D ;; unimplemented -- directory name
+					  )
+					 (#\e ;; unimplemented -- event
+					  )
+					 (#\f ;; existing file
+					  `(hemlock-internals:prompt-for-file
+					    :prompt ,pr
+					    :must-exist t))
+					 (#\F ;; file name
+					  `(hemlock-internals:prompt-for-file
+					    :prompt ,pr
+					    :must-exist nil))
+					 (#\i nil)
+					 (#\k ;; unimplemented -- key sequence
+					  )
+					 (#\K ;; unimplemented -- key sequence
+					  )
+					 (#\m '(hemlock::current-mark))
+					 (#\M ;; any string
+					  `(hemlock-internals:prompt-for-string
+					    :prompt ,pr))
+					 (#\n ;; number read
+					  `(hemlock-internals:prompt-for-integer
+					    :prompt ,pr))
+					 (#\N ;; raw prefix or #\n
+					  `(cl:if p
+						  p
+						  (hemlock-internals:prompt-for-integer
+						   :prompt ,pr)))
+					 (#\p ;; raw prefix as number
+					  '(cl:if p p 0))
+					 (#\P 'p)
+					 (#\r
+					  (setf extracollect
+						'(cl:let ((mark (hemlock::current-mark))
+							  (point (hemlock-internals::current-point)))
+							 (if (<= (hemlock-internals::mark-charpos mark)
+								 (hemlock-internals::mark-charpos point))
+							     point
+							   mark)))
+					  '(cl:let ((mark (hemlock::current-mark))
+						    (point (hemlock-internals::current-point)))
+						   (if (<= (hemlock-internals::mark-charpos mark)
+							   (hemlock-internals::mark-charpos point))
+						       mark
+						     point)))
+					 (#\s ; any string
+					  `(hemlock-internals:prompt-for-string
+					    :prompt ,pr))
+					 (#\S ; any symbol
+					  `(intern (hemlock-internals:prompt-for-string
+						    :prompt ,pr)
+						   *package*))
+					 (#\v ; variable name
+					  `(hemlock-internals:prompt-for-variable
+					    :prompt ,pr)
+					  )
+					 (#\x ; lisp expr read but not eval
+					  `(hemlock-internals:prompt-for-expression
+					    :prompt ,pr))
+					 (#\X ; lisp expr, read and evalled
+					  `(eval (hemlock-internals:prompt-for-expression
+						  :prompt ,pr))
+					  ))
+				       if extracollect
+				       collect extracollect
+				       )))))
+    `(lambda (arg) (declare (ignore arg)) (,function))))
+  
+(defun get-user-homedir (&optional username)
+  (unless username
+    (user-homedir-pathname)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/loadup.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/loadup.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/loadup.lisp	(revision 13309)
@@ -0,0 +1,11 @@
+;; Files to load
+(load "packages")
+(load "read-table")
+(load "base")
+(load "codewalker")
+(load "internals")
+(load "hemlock-shims")
+
+;; Functions to call
+(let ((*package* (find-package :elisp)))
+  (elisp-internals:generate-cl-package))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/packages.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/packages.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/packages.lisp	(revision 13309)
@@ -0,0 +1,66 @@
+(defpackage "ELISP"
+  (:shadow "=" "DEFUN" "LET" "IF" "SETQ" "ASSOC" "COMMANDP" "AREF")
+  (:use "COMMON-LISP" "HEMLOCK-INTERNALS")
+  (:export
+   "%"
+   "="
+   "ABORT-RECURSIVE-EDIT"
+   "AREF"
+   "ASET"
+   "ASSQ"
+   "ASSOC"
+   "AUTOLOAD"
+   "BOBP"
+   "BODY"
+   "BOLP"
+   "BOOL-VECTOR-P"
+   "BUFFER-LOCAL-P"
+   "CAR-LESS-THAN-CAR"
+   "CAR-SAFE"
+   "CDR-SAFE"
+   "COMMANDP"
+   "DEFMACRO"
+   "DEFUN"
+   "DEFVAR"
+   "FEATURES"
+   "FILENAME"
+   "GET-BUFFER"
+   "GET-BUFFER-CREATE"
+   "GET-DEFAULT"
+   "GLOBAL-SET-KEY"
+   "IF"
+   "INTERACTIVE"
+   "KEY"
+   "KEYMAP"
+   "LET"
+   "LEXICAL-LET"
+   "LOAD-FILE"
+   "LOAD-LIBRARY"
+   "LOAD-PATH"
+   "LOCAL-SET-KEY"
+   "MAKE-BOOL-VECTOR"
+   "MAKE-KEYMAP"
+   "MAKE-VARIABLE-BUFFER-LOCAL"
+   "MAKE-SPARSE-KEYMAP"
+   "NOERROR"
+   "SET-DEFAULT"
+   "SETQ"
+   "USE-LOCAL-MAP"
+   "WHILE"
+ )
+)
+(defpackage "ELISP-INTERNALS"
+  (:shadow "READ-STRING")
+  (:use "COMMON-LISP")
+  (:export
+   "FIND-LAMBDA-LIST-VARIABLES"
+   "GENERATE-CL-PACKAGE"
+   "REQUIRE-LOAD"
+   "GET-USER-HOMEDIR"
+   "INTERACTIVE-GLUE"
+   "*ELISP-READTABLE*"
+   )
+  )
+(defpackage "ELISP-USER"
+  (:use "ELISP" "ELISP-INTERNALS")
+  )
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/read-table.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/read-table.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/elisp/read-table.lisp	(revision 13309)
@@ -0,0 +1,131 @@
+(in-package "ELISP-INTERNALS")
+
+(defvar *elisp-readtable* (copy-readtable))
+
+(cl:defun read-vector (stream char)
+  (when (char= char #\[)
+    (coerce (read-delimited-list #\] stream t) 'vector)))
+
+(cl:defun read-character (stream char)
+  (if (char= char #\?) 
+      (read-string-char stream :event)
+      (values)))
+
+;;; Note to self. Implement this, head hurts, another day.
+;;; Is hopefully mostly done...
+(cl:defun emit-character (charspec context)
+  (cl:case context
+    (:character
+     (cl:let ((char (char-code (car (last charspec)))))
+       (if (member :control charspec)
+	   (setf char (mod char 32)))
+       (if (member :meta charspec)
+	   (setf char (+ 128 char)))
+       (code-char char)
+     ))
+    (:event
+     (cl:let ((string (with-output-to-string (s)
+			(write-char #\" s)
+			(loop for entity in charspec
+			      do (case entity
+				   (:control
+				    (write-char #\C s)
+				    (write-char #\- s))
+				   (:meta
+				    (write-char #\M s)
+				    (write-char #\- s))
+				   (t (write-char entity s))))
+			(write-char #\" s))))
+       (with-input-from-string (hackstring string)
+	 (eval (hemlock-ext::parse-key-fun hackstring #\k 2))))
+     )))
+
+(defun read-octal (stream acc level)
+  (cl:if (= level 3)
+      (code-char acc)
+    (let ((char (cl:read-char stream nil stream t)))
+      (case char
+	((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7)
+	 (if (and (char= char #\0) (zerop acc))
+	     (code-char 0)
+	   (let ((value (position char '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7) :test #'char=)))
+	     (cl:if (< (+ value (* 8 acc)) 256)
+		    (read-octal stream (+ value (* 8 acc)) (1+ level))
+		    (progn (unread-char char stream) (code-char acc))))))
+	(t (if (zerop acc)
+	       char
+	     (progn
+	       (unread-char char stream)
+	       (code-char acc))))))))
+
+(cl:defun read-string-char (stream context)
+  (cl:let ((char (cl:read-char stream nil stream t)))
+    (if (char= char #\\)
+	(cl:let ((next (cl:read-char stream nil stream t)))
+	  (case next
+	    (#\a (emit-character '(:control #\g) context))
+	    (#\n (emit-character '(:control #\j) context)) 
+	    (#\b (emit-character '(:control #\h) context))
+	    (#\r (emit-character '(:control #\m) context))
+	    (#\v (emit-character '(:control #\k) context))
+	    (#\f (emit-character '(:control #\l) context))
+	    (#\t (emit-character '(:control #\i) context))
+	    (#\e (emit-character '(:control #\[) context))
+	    (#\\ #\\)
+	    (#\" #\")
+	    (#\d (emit-character '(#\Rubout) context))
+	    ((#\C #\M)
+	     (unread-char next stream)
+	     (emit-character
+	      (do ((char (read-char stream) (read-char stream))
+		   (expect-dash nil (not expect-dash))
+		   (terminate nil)
+		   (collection nil))
+		  ((or (and expect-dash (not (char= char #\-)))
+		       terminate)
+		   (unread-char char stream)
+		   (nreverse collection))
+		(cond (expect-dash)
+		      ((char= char #\M)
+		       (setf collection (cons :meta collection)))
+		      ((char= char #\C)
+		       (setf collection (cons :control collection)))
+		      (t (setf terminate t)
+			 (setf collection (cons char collection)))))
+	      context))
+	    ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7)
+	     (read-octal stream 0 0)
+	    )))
+      char)))
+
+(cl:defun read-string (stream char)
+  (if (char= char #\")
+      (with-output-to-string (s)
+	(loop for char = (read-string-char stream :character)
+	      if (char= char #\") return s
+	      else do (cl:write-char char s)))))
+
+(cl:defun sharp-ampersand (stream ignore arg)
+  (declare (ignore ignore arg))
+  (let ((length (cl:read stream t stream t)))
+    (if (not (integerp length))
+	(values)
+      (let ((string (read stream stream stream t))
+	    (rv (make-array (list length) :element-type 'bit :initial-element 0)))
+	(if (stringp string)
+	    (progn
+	      (loop for ix from 0 to (1- length)
+		  do (multiple-value-bind (char shift) (truncate ix 8)
+		       (let ((val (char-code (char string char))))
+			 (unless (zerop (logand val (ash 1 shift)))
+			   (setf (aref rv ix) 1)))))
+	      rv)
+	  (values))))))
+
+(set-macro-character #\[ 'read-vector nil *elisp-readtable*)
+(set-macro-character #\] (get-macro-character #\)) nil *elisp-readtable*)
+(set-macro-character #\? 'read-character nil *elisp-readtable*)
+(set-macro-character #\" 'read-string nil *elisp-readtable*)
+(set-dispatch-macro-character #\# #\& #'sharp-ampersand *elisp-readtable*)
+(set-syntax-from-char #\[ #\()
+(set-syntax-from-char #\] #\))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/eval-server.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/eval-server.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/eval-server.lisp	(revision 13309)
@@ -0,0 +1,1097 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+(hemlock-ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains code for connecting to eval servers and some command
+;;; level stuff too.
+;;;
+;;; Written by William Lott.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; Structures.
+
+(defstruct (server-info (:print-function print-server-info))
+  name			      ; String name of this server.
+  wire			      ; Wire connected to this server.
+  notes			      ; List of note objects for operations
+			      ;  which have not yet completed.
+  slave-info		      ; Ts-Info used in "Slave Lisp" buffer
+			      ;  (formerly the "Lisp Listener" buffer).
+  slave-buffer		      ; "Slave Lisp" buffer for slave's *terminal-io*.
+  background-info	      ; Ts-Info structure of typescript we use in
+			      ;  "background" buffer.
+  background-buffer	      ; Buffer "background" typescript is in.
+  (errors		      ; Array of errors while compiling
+   (make-array 16 :adjustable t :fill-pointer 0))
+  error-index)		      ; Index of current error.
+;;;
+(defun print-server-info (obj stream n)
+  (declare (ignore n))
+  (format stream "#<Server-info for ~A>" (server-info-name obj)))
+
+
+(defstruct (error-info (:print-function print-error-info))
+  buffer		      ; Buffer this error is for.
+  message		      ; Error Message
+  line			      ; Pointer to message in log buffer.
+  region)		      ; Region of faulty text
+;;;
+(defun print-error-info (obj stream n)
+  (declare (ignore n))
+  (format stream "#<Error: ~A>" (error-info-message obj)))
+
+
+(defvar *server-names* (make-string-table)
+  "A string-table of the name of all Eval servers and their corresponding
+   server-info structures.")
+
+(defvar *abort-operations* nil
+  "T iff we should ignore any operations sent to us.")
+
+(defvar *inside-operation* nil
+  "T iff we are currenly working on an operation. A catcher for the tag 
+   abort-operation will be established whenever this is T.")
+
+(defconstant *slave-connect-wait* 300)
+
+;;; Used internally for communications.
+;;;
+(defvar *newly-created-slave* nil)
+(defvar *compiler-wire* nil)
+(defvar *compiler-error-stream* nil)
+(defvar *compiler-note* nil)
+
+
+
+
+;;;; Hemlock Variables
+
+(defhvar "Current Compile Server"
+  "The Server-Info object for the server currently used for compilation
+   requests."
+  :value nil)
+
+(defhvar "Current Package"
+  "This variable holds the name of the package currently used for Lisp
+   evaluation and compilation.  If it is Nil, the value of *Package* is used
+   instead."
+  :value nil)
+
+(defhvar "Slave Utility"
+  "This is the pathname of the utility to fire up slave Lisps.  It defaults
+   to \"cmucl\"."
+  :value "cmucl")
+
+(defhvar "Slave Utility Switches"
+  "These are additional switches to pass to the Slave Utility.
+   For example, (list \"-core\" <core-file-name>).  The -slave
+   switch and the editor name are always supplied, and they should
+   not be present in this variable."
+  :value nil)
+
+(defhvar "Ask About Old Servers"
+  "When set (the default), Hemlock will prompt for an existing server's name
+   in preference to prompting for a new slave's name and creating it."
+  :value t)
+
+(defhvar "Confirm Slave Creation"
+  "When set (the default), Hemlock always confirms a slave's creation for
+   whatever reason."
+  :value t)
+
+
+(defhvar "Slave GC Alarm"
+  "Determines that is done when the slave notifies that it is GCing.
+  :MESSAGE prints a message in the echo area, :LOUD-MESSAGE beeps as well.
+  NIL does nothing."
+  :value :message)
+
+
+
+;;;; Slave destruction.
+
+;;; WIRE-DIED -- Internal.
+;;;
+;;; The routine is called whenever a wire dies.  We roll through all the
+;;; servers looking for any that use this wire and nuke them with server-died.
+;;;
+(defun wire-died (wire)
+  (let ((servers nil))
+    (do-strings (name info *server-names*)
+      (declare (ignore name))
+      (when (eq wire (server-info-wire info))
+	(push info servers)))
+    (dolist (server servers)
+      (server-died server))))
+
+;;; SERVER-DIED -- Internal.
+;;;
+;;; Clean up the server. Remove any references to it from variables, etc.
+;;;
+(defun server-died (server)
+  (declare (special *breakpoints*))
+  (let ((name (server-info-name server)))
+    (delete-string name *server-names*)
+    (message "Server ~A just died." name))
+  (when (server-info-wire server)
+    #+NILGB
+    (let ((fd (hemlock.wire:wire-fd (server-info-wire server))))
+      (system:invalidate-descriptor fd)
+      (unix:unix-close fd))
+    (setf (server-info-wire server) nil))
+  (when (server-info-slave-info server)
+    (ts-buffer-wire-died (server-info-slave-info server))
+    (setf (server-info-slave-info server) nil))
+  (when (server-info-background-info server)
+    (ts-buffer-wire-died (server-info-background-info server))
+    (setf (server-info-background-info server) nil))
+  (clear-server-errors server)
+  (when (eq server (variable-value 'current-eval-server :global))
+    (setf (variable-value 'current-eval-server :global) nil))
+  (when (eq server (variable-value 'current-compile-server :global))
+    (setf (variable-value 'current-compile-server :global) nil))
+  (dolist (buffer *buffer-list*)
+    (dolist (var '(current-eval-server current-compile-server server-info))
+      (when (and (hemlock-bound-p var :buffer buffer)
+		 (eq (variable-value var :buffer buffer) server))
+	(delete-variable var :buffer buffer))))
+  (setf *breakpoints* (delete-if #'(lambda (b)
+				     (eq (breakpoint-info-slave b) server))
+				 *breakpoints*)))
+
+;;; SERVER-CLEANUP -- Internal.
+;;;
+;;; This routine is called as a buffer delete hook.  It takes care of any
+;;; per-buffer cleanup that is necessary.  It clears out all references to the
+;;; buffer from server-info structures and that any errors that refer to this
+;;; buffer are finalized.
+;;;
+(defun server-cleanup (buffer)
+  (let ((info (if (hemlock-bound-p 'server-info :buffer buffer)
+		  (variable-value 'server-info :buffer buffer))))
+    (when info
+      (when (eq buffer (server-info-slave-buffer info))
+	(setf (server-info-slave-buffer info) nil)
+	(setf (server-info-slave-info info) nil))
+      (when (eq buffer (server-info-background-buffer info))
+	(setf (server-info-background-buffer info) nil)
+	(setf (server-info-background-info info) nil))))
+  (do-strings (string server *server-names*)
+    (declare (ignore string))
+    (clear-server-errors server
+			 #'(lambda (error)
+			     (eq (error-info-buffer error) buffer)))))
+;;;
+(add-hook delete-buffer-hook 'server-cleanup)
+
+;;; CLEAR-SERVER-ERRORS -- Public.
+;;;
+;;; Clears all known errors for the given server and resets it so more can
+;;; accumulate.
+;;;
+(defun clear-server-errors (server &optional test-fn)
+  "This clears compiler errors for server cleaning up any pointers for GC
+   purposes and allowing more errors to register."
+  (let ((array (server-info-errors server))
+	(current nil))
+    (dotimes (i (fill-pointer array))
+      (let ((error (aref array i)))
+	(when (or (null test-fn)
+		  (funcall test-fn error))
+	  (let ((region (error-info-region error)))
+	    (when (regionp region)
+	      (delete-mark (region-start region))
+	      (delete-mark (region-end region))))
+	  (setf (aref array i) nil))))
+    (let ((index (server-info-error-index server)))
+      (when index
+	(setf current
+	      (or (aref array index)
+		  (find-if-not #'null array
+			       :from-end t
+			       :end current)))))
+    (delete nil array)
+    (setf (server-info-error-index server)
+	  (position current array))))
+
+
+
+
+;;;; Slave creation.
+
+;;; INITIALIZE-SERVER-STUFF -- Internal.
+;;;
+;;; Reinitialize stuff when a core file is saved.
+;;;
+(defun initialize-server-stuff ()
+  (clrstring *server-names*))
+
+
+(defvar *editor-name* nil "Name of this editor.")
+(defvar *accept-connections* nil
+  "When set, allow slaves to connect to the editor.")
+
+;;; GET-EDITOR-NAME -- Internal.
+;;;
+;;; Pick a name for the editor.  Names consist of machine-name:port-number.  If
+;;; in ten tries we can't get an unused port, choak.  We don't save the result
+;;; of HEMLOCK.WIRE:CREATE-REQUEST-SERVER because we don't think the editor needs to
+;;; ever kill the request server, and we can always inhibit connection with
+;;; "Accept Connections".
+;;;
+(defun get-editor-name ()
+  (if *editor-name*
+      *editor-name*
+      (let ((random-state (make-random-state t)))
+	(dotimes (tries 10 (error "Could not create an internet listener."))
+	  (let ((port (+ 2000 (random 10000 random-state))))
+            (setf port 4711)            ;###
+	    (when (handler-case (hemlock.wire:create-request-server
+				 port
+				 #'(lambda (wire addr)
+				     (declare (ignore addr))
+				     (values *accept-connections*
+					     #'(lambda () (wire-died wire)))))
+		    (error () nil))
+	      (return (setf *editor-name*
+			    (format nil "~A:~D" (machine-instance) port)))))))))
+
+
+;;; MAKE-BUFFERS-FOR-TYPESCRIPT -- Internal.
+;;;
+;;; This function returns no values because it is called remotely for value by
+;;; connecting slaves.  Though we know the system will propagate nil back to
+;;; the slave, we indicate here that nil is meaningless.
+;;;
+(defun make-buffers-for-typescript (slave-name background-name)
+  "Make the interactive and background buffers slave-name and background-name.
+   If either is nil, then prompt the user."
+  (multiple-value-bind (slave-name background-name)
+		       (cond ((not (and slave-name background-name))
+			      (pick-slave-buffer-names))
+			     ((getstring slave-name *server-names*)
+			      (multiple-value-bind
+				  (new-sn new-bn)
+				  (pick-slave-buffer-names)
+				(message "~S is already an eval server; ~
+					  using ~S instead."
+					 slave-name new-sn)
+				(values new-sn new-bn)))
+			     (t (values slave-name background-name)))
+    (let* ((slave-buffer (or (getstring slave-name *buffer-names*)
+			     (make-buffer slave-name :modes '("Lisp"))))
+	   (background-buffer (or (getstring background-name *buffer-names*)
+				  (make-buffer background-name
+					       :modes '("Lisp"))))
+	   (server-info (make-server-info :name slave-name
+					  :wire hemlock.wire:*current-wire*
+					  :slave-buffer slave-buffer
+					  :background-buffer background-buffer))
+	   (slave-info (typescriptify-buffer slave-buffer server-info
+					     hemlock.wire:*current-wire*))
+	   (background-info (typescriptify-buffer background-buffer server-info
+						  hemlock.wire:*current-wire*)))
+      (setf (server-info-slave-info server-info) slave-info)
+      (setf (server-info-background-info server-info) background-info)
+      (setf (getstring slave-name *server-names*) server-info)
+      (unless (variable-value 'current-eval-server :global)
+	(setf (variable-value 'current-eval-server :global) server-info))
+      (hemlock.wire:remote-value
+       hemlock.wire:*current-wire*
+       (made-buffers-for-typescript (hemlock.wire:make-remote-object slave-info)
+				    (hemlock.wire:make-remote-object background-info)))
+      (setf *newly-created-slave* server-info)
+      (values))))
+
+
+;;; CREATE-SLAVE -- Public.
+;;;
+#+NILGB
+(defun create-slave (&optional name)
+  "This creates a slave that tries to connect to the editor.  When the slave
+   connects to the editor, this returns a slave-information structure.  Name is
+   the name of the interactive buffer.  If name is nil, this generates a name.
+   If name is supplied, and a buffer with that name already exists, this
+   signals an error.  In case the slave never connects, this will eventually
+   timeout and signal an editor-error."
+  (when (and name (getstring name *buffer-names*))
+    (editor-error "Buffer ~A is already in use." name))
+  (let ((lisp (unix-namestring (merge-pathnames (value slave-utility) "path:")
+			       t t)))
+    (unless lisp
+      (editor-error "Can't find ``~S'' in your path to run."
+		    (value slave-utility)))
+    (multiple-value-bind (slave background)
+			 (if name
+			     (values name (format nil "Background ~A" name))
+			     (pick-slave-buffer-names))
+      (when (value confirm-slave-creation)
+	(setf slave (prompt-for-string
+		     :prompt "New slave name? "
+		     :help "Enter the name to use for the newly created slave."
+		     :default slave
+		     :default-string slave))
+	(setf background (format nil "Background ~A" slave))
+	(when (getstring slave *buffer-names*)
+	  (editor-error "Buffer ~A is already in use." slave))
+	(when (getstring background *buffer-names*)
+	  (editor-error "Buffer ~A is already in use." background)))
+      (message "Spawning slave ... ")
+      (let ((proc
+	     (ext:run-program lisp
+			      `("-slave" ,(get-editor-name)
+				,@(if slave (list "-slave-buffer" slave))
+				,@(if background
+				      (list "-background-buffer" background))
+				,@(value slave-utility-switches))
+			      :wait nil
+			      :output "/dev/null"
+			      :if-output-exists :append))
+	    (*accept-connections* t)
+	    (*newly-created-slave* nil))
+	(unless proc
+	  (editor-error "Could not start slave."))
+	(dotimes (i *slave-connect-wait*
+		    (editor-error
+		     "Client Lisp is still unconnected.  ~
+		      You must use \"Accept Slave Connections\" to ~
+		      allow the slave to connect at this point."))
+	  (system:serve-event 1)
+	  (case (ext:process-status proc)
+	    (:exited
+	     (editor-error "The slave lisp exited before connecting."))
+	    (:signaled
+	     (editor-error "The slave lisp was kill before connecting.")))
+	  (when *newly-created-slave*
+	    (message "DONE")
+	    (return *newly-created-slave*)))))))
+  
+;;; MAYBE-CREATE-SERVER -- Internal interface.
+;;;
+(defun maybe-create-server ()
+  "If there is an existing server and \"Ask about Old Servers\" is set, then
+   prompt for a server's name and return that server's info.  Otherwise,
+   create a new server."
+  (if (value ask-about-old-servers)
+      (multiple-value-bind (first-server-name first-server-info)
+			   (do-strings (name info *server-names*)
+			     (return (values name info)))
+	(if first-server-info
+	    (multiple-value-bind
+		(name info)
+		(prompt-for-keyword (list *server-names*)
+				    :prompt "Existing server name: "
+				    :default first-server-name
+				    :default-string first-server-name
+				    :help
+				    "Enter the name of an existing eval server."
+				    :must-exist t)
+	      (declare (ignore name))
+	      (or info (create-slave)))
+	    (create-slave)))
+      (create-slave)))
+
+
+(defvar *next-slave-index* 0
+  "Number to use when creating the next slave.")
+
+;;; PICK-SLAVE-BUFFER-NAMES -- Internal.
+;;;
+;;; Return two unused names to use for the slave and background buffers.
+;;;
+(defun pick-slave-buffer-names ()
+  (loop
+    (let ((slave (format nil "Slave ~D" (incf *next-slave-index*)))
+	  (background (format nil "Background Slave ~D" *next-slave-index*)))
+      (unless (or (getstring slave *buffer-names*)
+		  (getstring background *buffer-names*))
+	(return (values slave background))))))
+
+
+
+
+;;;; Slave selection.
+
+;;; GET-CURRENT-EVAL-SERVER -- Public.
+;;;
+(defun get-current-eval-server (&optional errorp)
+  "Returns the server-info struct for the current eval server.  If there is
+   none, and errorp is non-nil, then signal an editor error.  If there is no
+   current server, and errorp is nil, then create one, prompting the user for
+   confirmation.  Also, set the current server to be the newly created one."
+  (let ((info (value current-eval-server)))
+    (cond (info)
+	  (errorp
+	   (editor-error "No current eval server."))
+	  (t
+	   (setf (value current-eval-server) (maybe-create-server))))))
+
+;;; GET-CURRENT-COMPILE-SERVER -- Public.
+;;;
+;;; If a current compile server is defined, return it, otherwise return the
+;;; current eval server using get-current-eval-server.
+;;;
+(defun get-current-compile-server (&optional errorp)
+  "Returns the server-info struct for the current compile server. If there is
+   no current compile server, return the current eval server."
+  (or (value current-compile-server)
+      (get-current-eval-server errorp)))
+
+
+
+
+;;;; Server Manipulation commands.
+
+(defcommand "Select Slave" (p)
+  "Switch to the current slave's buffer.  When given an argument, create a new
+   slave."
+  "Switch to the current slave's buffer.  When given an argument, create a new
+   slave."
+  (let* ((info (if p (create-slave) (get-current-eval-server)))
+	 (slave (server-info-slave-buffer info)))
+    (unless slave
+      (editor-error "The current eval server doesn't have a slave buffer!"))
+    (change-to-buffer slave)))
+
+(defcommand "Select Background" (p)
+  "Switch to the current slave's background buffer. When given an argument, use
+   the current compile server instead of the current eval server."
+  "Switch to the current slave's background buffer. When given an argument, use
+   the current compile server instead of the current eval server."
+  (let* ((info (if p
+		 (get-current-compile-server t)
+		 (get-current-eval-server t)))
+	 (background (server-info-background-buffer info)))
+    (unless background
+      (editor-error "The current ~A server doesn't have a background buffer!"
+		    (if p "compile" "eval")))
+    (change-to-buffer background)))
+
+#+NILGB
+(defcommand "Kill Slave" (p)
+  "This aborts any operations in the slave, tells the slave to QUIT, and shuts
+   down the connection to the specified eval server.  This makes no attempt to
+   assure the eval server actually dies."
+  "This aborts any operations in the slave, tells the slave to QUIT, and shuts
+   down the connection to the specified eval server.  This makes no attempt to
+   assure the eval server actually dies."
+  (declare (ignore p))
+  (let ((default (and (value current-eval-server)
+		      (server-info-name (value current-eval-server)))))
+    (multiple-value-bind
+	(name info)
+	(prompt-for-keyword
+	 (list *server-names*)
+	 :prompt "Kill Slave: "
+	 :help "Enter the name of the eval server you wish to destroy."
+	 :must-exist t
+	 :default default
+	 :default-string default)
+      (declare (ignore name))
+      (let ((wire (server-info-wire info)))
+	(when wire
+	  (ext:send-character-out-of-band (hemlock.wire:wire-fd wire) #\N)
+	  (hemlock.wire:remote wire (ext:quit))
+	  (hemlock.wire:wire-force-output wire)))
+      (server-died info))))
+
+#+NILGB
+(defcommand "Kill Slave and Buffers" (p)
+  "This is the same as \"Kill Slave\", but it also deletes the slaves
+   interaction and background buffers."
+  "This is the same as \"Kill Slave\", but it also deletes the slaves
+   interaction and background buffers."
+  (declare (ignore p))
+  (let ((default (and (value current-eval-server)
+		      (server-info-name (value current-eval-server)))))
+    (multiple-value-bind
+	(name info)
+	(prompt-for-keyword
+	 (list *server-names*)
+	 :prompt "Kill Slave: "
+	 :help "Enter the name of the eval server you wish to destroy."
+	 :must-exist t
+	 :default default
+	 :default-string default)
+      (declare (ignore name))
+      (let ((wire (server-info-wire info)))
+	(when wire
+	  (ext:send-character-out-of-band (hemlock.wire:wire-fd wire) #\N)
+	  (hemlock.wire:remote wire (ext:quit))
+	  (hemlock.wire:wire-force-output wire)))
+      (let ((buffer (server-info-slave-buffer info)))
+	(when buffer (delete-buffer-if-possible buffer)))
+      (let ((buffer (server-info-background-buffer info)))
+	(when buffer (delete-buffer-if-possible buffer)))
+      (server-died info))))
+
+(defcommand "Accept Slave Connections" (p)
+  "This causes Hemlock to accept slave connections and displays the port of
+   the editor's connections request server.  This is suitable for use with the
+   Lisp's -slave switch.  Given an argument, this inhibits slave connections."
+  "This causes Hemlock to accept slave connections and displays the port of
+   the editor's connections request server.  This is suitable for use with the
+   Lisp's -slave switch.  Given an argument, this inhibits slave connections."
+  (let ((accept (not p)))
+    (setf *accept-connections* accept)
+    (message "~:[Inhibiting~;Accepting~] connections to ~S"
+	     accept (get-editor-name))))
+
+
+
+
+;;;; Slave initialization junk.
+
+(defvar *original-beep-function* nil
+  "Handle on original beep function.")
+
+(defvar *original-gc-notify-before* nil
+  "Handle on original before-GC notification function.")
+
+(defvar *original-gc-notify-after* nil
+  "Handle on original after-GC notification function.")
+
+(defvar *original-terminal-io* nil
+  "Handle on original *terminal-io* so we can restore it.")
+
+(defvar *original-standard-input* nil
+  "Handle on original *standard-input* so we can restore it.")
+
+(defvar *original-standard-output* nil
+  "Handle on original *standard-output* so we can restore it.")
+
+(defvar *original-error-output* nil
+  "Handle on original *error-output* so we can restore it.")
+
+(defvar *original-debug-io* nil
+  "Handle on original *debug-io* so we can restore it.")
+
+(defvar *original-query-io* nil
+  "Handle on original *query-io* so we can restore it.")
+
+(defvar *original-trace-output* nil
+  "Handle on original *trace-output* so we can restore it.")
+
+(defvar *background-io* nil
+  "Stream connected to the editor's background buffer in case we want to use it
+  in the future.")
+
+;;; CONNECT-STREAM -- internal
+;;;
+;;; Run in the slave to create a new stream and connect it to the supplied
+;;; buffer.  Returns the stream.
+;;; 
+(defun connect-stream (remote-buffer)
+  (let ((stream (make-ts-stream hemlock.wire:*current-wire* remote-buffer)))
+    (hemlock.wire:remote hemlock.wire:*current-wire*
+      (ts-buffer-set-stream remote-buffer
+			    (hemlock.wire:make-remote-object stream)))
+    stream))
+
+;;; MADE-BUFFERS-FOR-TYPESCRIPT -- Internal Interface.
+;;;
+;;; Run in the slave by the editor with the two buffers' info structures,
+;;; actually remote-objects in the slave.  Does any necessary stream hacking.
+;;; Return nil to make sure no weird objects try to go back over the wire
+;;; since the editor calls this in the slave for value.  The editor does this
+;;; for synch'ing, not for values.
+;;;
+(defun made-buffers-for-typescript (slave-info background-info)
+  (setf *original-terminal-io* *terminal-io*)
+  (warn "made-buffers-for-typescript ~S ~S ~S."
+        (connect-stream slave-info)
+        *terminal-io*
+        (connect-stream background-info))
+  (sleep 3)
+  (macrolet ((frob (symbol new-value)
+	       `(setf ,(intern (concatenate 'simple-string
+					    "*ORIGINAL-"
+					    (subseq (string symbol) 1)))
+                 ,symbol
+                 ,symbol ,new-value)))
+    #+NILGB
+    (let ((wire hemlock.wire:*current-wire*))
+      (frob system:*beep-function*
+	    #'(lambda (&optional stream)
+		(declare (ignore stream))
+		(hemlock.wire:remote-value wire (beep))))
+      (frob ext:*gc-notify-before*
+	    #'(lambda (bytes-in-use)
+		(hemlock.wire:remote wire
+                                     (slave-gc-notify-before
+                                      slave-info
+                                      (format nil
+                                              "~%[GC threshold exceeded with ~:D bytes in use.  ~
+			   Commencing GC.]~%"
+                                              bytes-in-use)))
+		(hemlock.wire:wire-force-output wire)))
+      (frob ext:*gc-notify-after*
+	    #'(lambda (bytes-retained bytes-freed new-trigger)
+		(hemlock.wire:remote wire
+                                     (slave-gc-notify-after
+                                      slave-info
+                                      (format nil
+                                              "[GC completed with ~:D bytes retained and ~:D ~
+			   bytes freed.]~%[GC will next occur when at least ~
+			   ~:D bytes are in use.]~%"
+                                              bytes-retained bytes-freed new-trigger)))
+		(hemlock.wire:wire-force-output wire))))
+    (warn "#7")(sleep 1)
+    (frob *terminal-io* (connect-stream slave-info))
+    #+NIL
+    (progn
+        (setf cl-user::*io* (connect-stream slave-info))
+        (let ((*terminal-io* *original-terminal-io*))
+          (warn "#8")(sleep 1))
+        (frob *standard-input* (make-synonym-stream '*terminal-io*))
+        (let ((*terminal-io* *original-terminal-io*))
+          (warn "#9")(sleep 1))
+        (frob *standard-output* *standard-input*)
+        (let ((*terminal-io* *original-terminal-io*))
+          (warn "#10")(sleep 1))
+        ;;###
+        ;;(frob *error-output* *standard-input*)
+        ;;(frob *debug-io* *standard-input*)
+        (let ((*terminal-io* *original-terminal-io*))
+          (warn "#11")(sleep 1))
+        (frob *query-io* *standard-input*)
+        (let ((*terminal-io* *original-terminal-io*))
+          (warn "#12")(sleep 1)))
+    (frob *trace-output* *original-terminal-io*)
+    )
+  #+NILGB (setf *background-io* (connect-stream background-info))
+  nil)
+
+;;; SLAVE-GC-NOTIFY-BEFORE and SLAVE-GC-NOTIFY-AFTER -- internal
+;;;
+;;; These two routines are run in the editor by the slave's gc notify routines.
+;;; 
+(defun slave-gc-notify-before (remote-ts message)
+  (let ((ts (hemlock.wire:remote-object-value remote-ts)))
+    (ts-buffer-output-string ts message t)
+    (when (value slave-gc-alarm)
+      (message "~A is GC'ing." (buffer-name (ts-data-buffer ts)))
+      (when (eq (value slave-gc-alarm) :loud-message)
+	(beep)))))
+
+(defun slave-gc-notify-after (remote-ts message)
+  (let ((ts (hemlock.wire:remote-object-value remote-ts)))
+    (ts-buffer-output-string ts message t)
+    (when (value slave-gc-alarm)
+      (message "~A is done GC'ing." (buffer-name (ts-data-buffer ts)))
+      (when (eq (value slave-gc-alarm) :loud-message)
+	(beep)))))
+
+;;; EDITOR-DIED -- internal
+;;;
+;;; Run in the slave when the editor goes belly up.
+;;; 
+(defun editor-died ()
+  (macrolet ((frob (symbol)
+	       (let ((orig (intern (concatenate 'simple-string
+						"*ORIGINAL-"
+						(subseq (string symbol) 1)))))
+		 `(when ,orig
+		    (setf ,symbol ,orig)))))
+    #+NILGB
+    (progn
+      (frob system:*beep-function*)
+      (frob ext:*gc-notify-before*)
+      (frob ext:*gc-notify-after*))
+    (frob *terminal-io*)
+    (frob *standard-input*)
+    (frob *standard-output*)
+    (frob *error-output*)
+    (frob *debug-io*)
+    (frob *query-io*)
+    (frob *trace-output*))
+  (setf *background-io* nil)
+  (format t "~2&Connection to editor died.~%")
+  #+NILGB
+  (ext:quit))
+
+;;; START-SLAVE -- internal
+;;;
+;;; Initiate the process by which a lisp becomes a slave.
+;;; 
+(defun start-slave (editor)
+  (declare (simple-string editor))
+  (let ((seperator (position #\: editor :test #'char=)))
+    (unless seperator
+      (error "Editor name ~S invalid. ~
+              Must be of the form \"MachineName:PortNumber\"."
+	     editor))
+    (let ((machine (subseq editor 0 seperator))
+	  (port (parse-integer editor :start (1+ seperator))))
+      (format t "Connecting to ~A:~D~%" machine port)
+      (connect-to-editor machine port))))
+
+
+;;; PRINT-SLAVE-STATUS  --  Internal
+;;;
+;;;    Print out some useful information about what the slave is up to.
+;;;
+#+NILGB
+(defun print-slave-status ()
+  (ignore-errors
+    (multiple-value-bind (sys user faults)
+			 (system:get-system-info)
+      (let* ((seconds (truncate (+ sys user) 1000000))
+	     (minutes (truncate seconds 60))
+	     (hours (truncate minutes 60))
+	     (days (truncate hours 24)))
+	(format *error-output* "~&; Used ~D:~2,'0D:~2,'0D~V@{!~}, "
+		hours (rem minutes 60) (rem seconds 60) days))
+      (format *error-output* "~D fault~:P.  In: " faults)
+	    
+      (do ((i 0 (1+ i))
+	   (frame (di:top-frame) (di:frame-down frame)))
+	  (#-x86(= i 3)
+	   #+x86
+	   (and (> i 6)		; get past extra cruft
+		(let ((name (di:debug-function-name
+			     (di:frame-debug-function frame))))
+		  (and (not (string= name "Bogus stack frame"))
+		       (not (string= name "Foreign function call land")))))
+	   (prin1 (di:debug-function-name (di:frame-debug-function frame))
+		  *error-output*))
+	(unless frame (return)))
+      (terpri *error-output*)
+      (force-output *error-output*)))
+  (values))
+
+
+;;; CONNECT-TO-EDITOR -- internal
+;;;
+;;; Do the actual connect to the editor.
+;;; 
+(defun connect-to-editor (machine port
+			  &optional
+			  (slave (find-eval-server-switch "slave-buffer"))
+			  (background (find-eval-server-switch
+				       "background-buffer")))
+  (let ((wire (hemlock.wire:connect-to-remote-server machine port 'editor-died)))
+    #+NILGB
+    (progn
+      (ext:add-oob-handler (hemlock.wire:wire-fd wire)
+                           #\B
+                           #'(lambda ()
+                               (system:without-hemlock
+                                (system:with-interrupts
+                                    (break "Software Interrupt")))))
+      (ext:add-oob-handler (hemlock.wire:wire-fd wire)
+                           #\T
+                           #'(lambda ()
+                               (when lisp::*in-top-level-catcher*
+                                 (throw 'lisp::top-level-catcher nil))))
+      (ext:add-oob-handler (hemlock.wire:wire-fd wire)
+                           #\A
+                           #'abort)
+      (ext:add-oob-handler (hemlock.wire:wire-fd wire)
+                           #\N
+                           #'(lambda ()
+                               (setf *abort-operations* t)
+                               (when *inside-operation*
+                                 (throw 'abort-operation
+                                   (if debug::*in-the-debugger*
+                                       :was-in-debugger)))))
+      (ext:add-oob-handler (hemlock.wire:wire-fd wire) #\S #'print-slave-status))
+
+    (hemlock.wire:remote-value wire
+      (make-buffers-for-typescript slave background))))
+
+
+
+;;;; Eval server evaluation functions.
+
+(defvar *eval-form-stream*
+  (make-two-way-stream
+   #+NILGB
+   (lisp::make-lisp-stream
+    :in #'(lambda (&rest junk)
+	    (declare (ignore junk))
+	    (error "You cannot read when handling an eval_form request.")))
+   #-NILGB
+   (make-concatenated-stream)
+   (make-broadcast-stream)))
+
+;;; SERVER-EVAL-FORM -- Public.
+;;;   Evaluates the given form (which is a string to be read from in the given
+;;; package) and returns the results as a list.
+;;;
+(defun server-eval-form (package form)
+  (declare (type (or string null) package) (simple-string form))
+  (handler-bind
+      ((error #'(lambda (condition)
+		  (hemlock.wire:remote hemlock.wire:*current-wire*
+			       (eval-form-error (format nil "~A~&" condition)))
+		  (return-from server-eval-form nil))))
+    (let ((*package* (if package
+			 (lisp::package-or-lose package)
+			 *package*))
+	  (*terminal-io* *eval-form-stream*))
+      (stringify-list (multiple-value-list (eval (read-from-string form)))))))
+
+
+;;; DO-OPERATION -- Internal.
+;;;   Checks to see if we are aborting operations. If not, do the operation
+;;; wrapping it with operation-started and operation-completed calls. Also
+;;; deals with setting up *terminal-io* and *package*.
+;;;
+(defmacro do-operation ((note package terminal-io) &body body)
+  `(let ((aborted t)
+	 (*terminal-io* (if ,terminal-io
+			  (hemlock.wire:remote-object-value ,terminal-io)
+			  *terminal-io*))
+	 (*package* (maybe-make-package ,package)))
+     (unwind-protect
+	 (unless *abort-operations*
+	   (when (eq :was-in-debugger
+		     (catch 'abort-operation
+		       (let ((*inside-operation* t))
+			 (hemlock.wire:remote hemlock.wire:*current-wire*
+				      (operation-started ,note))
+			 (hemlock.wire:wire-force-output hemlock.wire:*current-wire*)
+			 ,@body
+			 (setf aborted nil))))
+	     (format t
+		     "~&[Operation aborted.  ~
+		      You are no longer in this instance of the debugger.]~%")))
+       (hemlock.wire:remote hemlock.wire:*current-wire*
+	 (operation-completed ,note aborted))
+       (hemlock.wire:wire-force-output hemlock.wire:*current-wire*))))
+
+
+;;; unique-thingie is a unique eof-value for READ'ing.  Its a parameter, so
+;;; we can reload the file.
+;;;
+(defparameter unique-thingie (gensym)
+  "Used as eof-value in reads to check for the end of a file.")
+
+;;; SERVER-EVAL-TEXT -- Public.
+;;;
+;;;   Evaluate all the forms read from text in the given package, and send the
+;;; results back.  The error handler bound does not handle any errors.  It
+;;; simply notifies the client that an error occurred and then returns.
+;;;
+(defun server-eval-text (note package text terminal-io)
+  (do-operation (note package terminal-io)
+    (with-input-from-string (stream text)
+      (let ((last-pos 0))
+	(handler-bind
+	    ((error
+	      #'(lambda (condition)
+		  (hemlock.wire:remote hemlock.wire:*current-wire*
+			       (lisp-error note last-pos
+					   (file-position stream)
+					   (format nil "~A~&" condition))))))
+	  (loop
+	    (let ((form (read stream nil unique-thingie)))
+	      (when (eq form unique-thingie)
+		(return nil))
+	      (let* ((values (stringify-list (multiple-value-list (eval form))))
+		     (pos (file-position stream)))
+		(hemlock.wire:remote hemlock.wire:*current-wire*
+		  (eval-text-result note last-pos pos values))
+		(setf last-pos pos)))))))))
+
+(defun stringify-list (list)
+  (mapcar #'prin1-to-string list))
+#|
+(defun stringify-list (list)
+  (mapcar #'(lambda (thing)
+	      (with-output-to-string (stream)
+		(write thing
+		       :stream stream :radix nil :base 10 :circle t
+		       :pretty nil :level nil :length nil :case :upcase
+		       :array t :gensym t)))
+	  list))
+|#
+
+
+
+;;;; Eval server compilation stuff.
+
+;;; DO-COMPILER-OPERATION -- Internal.
+;;;
+;;; Useful macro that does the operation with *compiler-note* and
+;;; *compiler-wire* bound.
+;;;
+(defmacro do-compiler-operation ((note package terminal-io error) &body body)
+  #+NILGB
+  `(let ((*compiler-note* ,note)
+	 (*compiler-error-stream* ,error)
+	 (*compiler-wire* hemlock.wire:*current-wire*)
+	 (c:*compiler-notification-function* #'compiler-note-in-editor))
+     (do-operation (*compiler-note* ,package ,terminal-io)
+		   (unwind-protect
+		       (handler-bind ((error #'compiler-error-handler))
+			 ,@body)
+		     (when *compiler-error-stream*
+		       (force-output *compiler-error-stream*))))))
+
+;;; COMPILER-NOTE-IN-EDITOR -- Internal.
+;;;
+;;; DO-COMPILER-OPERATION binds c:*compiler-notification-function* to this, so
+;;; interesting observations in the compilation can be propagated back to the
+;;; editor.  If there is a notification point defined, we send information
+;;; about the position and kind of error.  The actual error text is written out
+;;; using typescript operations.
+;;;
+;;; Start and End are the compiler's best guess at the file position where the
+;;; error occurred.  Function is some string describing where the error was.
+;;;
+(defun compiler-note-in-editor (severity function name pos)
+  (declare (ignore name))
+  (when *compiler-wire*
+    (force-output *compiler-error-stream*)
+    (hemlock.wire:remote *compiler-wire*
+      (compiler-error *compiler-note* pos pos function severity)))
+    (hemlock.wire:wire-force-output *compiler-wire*))
+
+
+;;; COMPILER-ERROR-HANDLER -- Internal.
+;;;
+;;;    The error handler function for the compiler interfaces.
+;;; DO-COMPILER-OPERATION binds this as an error handler while evaluating the
+;;; compilation form.
+;;;
+(defun compiler-error-handler (condition)
+  (when *compiler-wire*
+    (hemlock.wire:remote *compiler-wire*
+      (lisp-error *compiler-note* nil nil
+		  (format nil "~A~&" condition)))))
+
+
+;;; SERVER-COMPILE-TEXT -- Public.
+;;;
+;;;    Similar to server-eval-text, except that the stuff is compiled.
+;;;
+#+NILGB
+(defun server-compile-text (note package text defined-from
+			    terminal-io error-output)
+  (let ((error-output (if error-output
+			(hemlock.wire:remote-object-value error-output))))
+    (do-compiler-operation (note package terminal-io error-output)
+      (with-input-from-string (input-stream text)
+	(terpri error-output)
+	(c::compile-from-stream input-stream
+				:error-stream error-output
+				:source-info defined-from)))))
+
+;;; SERVER-COMPILE-FILE -- Public.
+;;;
+;;;    Compiles the file sending error info back to the editor.
+;;;
+(defun server-compile-file (note package input output error trace
+			    load terminal background)
+  (macrolet ((frob (x)
+	       `(if (hemlock.wire:remote-object-p ,x)
+		  (hemlock.wire:remote-object-value ,x)
+		  ,x)))
+    (let ((error-stream (frob background)))
+      (do-compiler-operation (note package terminal error-stream)
+	(compile-file (frob input)
+		      :output-file (frob output)
+		      :error-file (frob error)
+		      :trace-file (frob trace)
+		      :load load
+		      :error-output error-stream)))))
+
+
+
+;;;; Other random eval server stuff.
+
+;;; MAYBE-MAKE-PACKAGE -- Internal.
+;;;
+;;; Returns a package for a name.  Creates it if it doesn't already exist.
+;;;
+(defun maybe-make-package (name)
+  (cond ((null name) *package*)
+	((find-package name))
+	(t
+	 (hemlock.wire:remote-value (ts-stream-wire *terminal-io*)
+	   (ts-buffer-output-string
+	    (ts-stream-typescript *terminal-io*)
+	    (format nil "~&Creating package ~A.~%" name)
+	    t))
+	 (make-package name))))
+
+;;; SERVER-SET-PACKAGE -- Public.
+;;;
+;;;   Serves package setting requests.  It simply sets
+;;; *package* to an already existing package or newly created one.
+;;;
+(defun server-set-package (package)
+  (setf *package* (maybe-make-package package)))
+
+;;; SERVER-ACCEPT-OPERATIONS -- Public.
+;;;
+;;;   Start accepting operations again.
+;;;
+(defun server-accept-operations ()
+  (setf *abort-operations* nil))
+
+
+
+
+;;;; Command line switches.
+
+#+NILGB
+(progn
+
+;;; FIND-EVAL-SERVER-SWITCH -- Internal.
+;;;
+;;; This is special to the switches supplied by CREATE-SLAVE and fetched by
+;;; CONNECT-EDITOR-SERVER, so we can use STRING=.
+;;;
+(defun find-eval-server-switch (string)
+  #+NILGB
+  (let ((switch (find string ext:*command-line-switches*
+		      :test #'string=
+		      :key #'ext:cmd-switch-name)))
+    (if switch
+	(or (ext:cmd-switch-value switch)
+	    (car (ext:cmd-switch-words switch))))))
+
+
+(defun slave-switch-demon (switch)
+  (let ((editor (ext:cmd-switch-arg switch)))
+    (unless editor
+      (error "Editor to connect to unspecified."))
+    (start-slave editor)
+    (setf debug:*help-line-scroll-count* most-positive-fixnum)))
+;;;
+(defswitch "slave" 'slave-switch-demon)
+(defswitch "slave-buffer")
+(defswitch "background-buffer")
+
+
+(defun edit-switch-demon (switch)
+  (declare (ignore switch))
+#|  (let ((arg (or (ext:cmd-switch-value switch)
+		 (car (ext:cmd-switch-words switch)))))
+    (when (stringp arg) (setq *editor-name* arg)))|#
+  (let ((initp (not (ext:get-command-line-switch "noinit"))))
+    (if (stringp (car ext:*command-line-words*))
+	(ed (car ext:*command-line-words*) :init initp)
+	(ed nil :init initp))))
+;;;
+(defswitch "edit" 'edit-switch-demon)
+)
+
+#+SBCL
+(defun hemlock.wire::serve-all-events ()
+  (sleep .1))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/group.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/group.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/group.lisp	(revision 13309)
@@ -0,0 +1,238 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; File group stuff for Hemlock.
+;;; Written by Skef Wholey and Rob MacLachlan.
+;;;
+;;;    The "Compile Group" and "List Compile Group" commands in lispeval
+;;;    also know about groups.
+;;;
+;;; This file provides Hemlock commands for manipulating groups of files
+;;; that make up a larger system.  A file group is a set of files whose
+;;; names are listed in some other file.  At any given time one group of
+;;; files is the Active group.  The Select Group command makes a group the
+;;; Active group, prompting for the name of a definition file if the group
+;;; has not been selected before.  Once a group has been selected once, the
+;;; name of the definition file associated with that group is retained.  If
+;;; one wishes to change the name of the definition file after a group has
+;;; been selected, one should call Select Group with a prefix argument.
+
+(in-package :hemlock)
+
+(defvar *file-groups* (make-string-table)
+  "A string table of file groups.")
+
+(defvar *active-file-group* ()
+  "The list of files in the currently active group.")
+
+(defvar *active-file-group-name* ()
+  "The name of the currently active group.")
+
+
+
+
+;;;; Selecting the active group.
+
+(defcommand "Select Group" (p)
+  "Makes a group the active group.  With a prefix argument, changes the
+  definition file associated with the group."
+  "Makes a group the active group."
+  (let* ((group-name
+	  (prompt-for-keyword
+	   (list *file-groups*)
+	   :must-exist nil
+	   :prompt "Select Group: "
+	   :help
+	   "Type the name of the file group you wish to become the active group."))
+	 (old (getstring group-name *file-groups*))
+	 (pathname
+	  (if (and old (not p))
+	      old
+	      (prompt-for-file :must-exist t
+			       :prompt "From File: "
+			       :default (merge-pathnames
+					 (make-pathname
+					  :name group-name
+					  :type "upd")
+					 (value pathname-defaults))))))
+    (setq *active-file-group-name* group-name)
+    (setq *active-file-group* (nreverse (read-file-group pathname nil)))
+    (setf (getstring group-name *file-groups*) pathname)))
+
+
+;;; READ-FILE-GROUP reads an Update format file and returns a list of pathnames
+;;; of the files named in that file.  This guy knows about @@ indirection and
+;;; ignores empty lines and lines that begin with @ but not @@.  A simpler
+;;; scheme could be used for non-Spice implementations, but all this hair is
+;;; probably useful, so Update format may as well be a standard for this sort
+;;; of thing.
+;;;
+(defun read-file-group (pathname tail)
+  (with-open-file (file pathname)
+    (do* ((name (read-line file nil nil) (read-line file nil nil))
+	  (length (if name (length name)) (if name (length name))))
+	 ((null name) tail)
+      (declare (type (or simple-string null) name))
+      (cond ((zerop length))
+	    ((char= (char name 0) #\@)
+	     (when (and (> length 1) (char= (char name 1) #\@))
+	       (setq tail (read-file-group
+			   (merge-pathnames (subseq name 2)
+					    pathname)
+			   tail))))
+	    (t
+	     (push (merge-pathnames (pathname name) pathname) tail))))))
+
+
+
+
+;;;; DO-ACTIVE-GROUP.
+
+(defhvar "Group Find File"
+  "If true, group commands use \"Find File\" to read files, otherwise
+  non-resident files are read into the \"Group Search\" buffer."
+  :value nil)
+
+(defhvar "Group Save File Confirm"
+  "If true, then the group commands will ask for confirmation before saving
+  a modified file." :value t)
+
+(defmacro do-active-group (&rest forms)
+  "This iterates over the active file group executing forms once for each
+   file.  When forms are executed, the file will be in the current buffer,
+   and the point will be at the start of the file."
+  (let ((n-buf (gensym))
+	(n-start-buf (gensym))
+	(n-save (gensym)))
+    `(progn
+       (unless *active-file-group*
+	 (editor-error "There is no active file group."))
+
+       (let ((,n-start-buf (current-buffer))
+	     (,n-buf nil))
+	 (unwind-protect
+	     (dolist (file *active-file-group*)
+	       (catch 'file-not-found
+		 (setq ,n-buf (group-read-file file ,n-buf))
+		 (with-mark ((,n-save (current-point) :right-inserting))
+		   (unwind-protect
+		       (progn
+			 (buffer-start (current-point))
+			 ,@forms)
+		     (move-mark (current-point) ,n-save)))
+		 (group-save-file)))
+	   (if (member ,n-start-buf *buffer-list*)
+	       (setf (current-buffer) ,n-start-buf
+		     (window-buffer (current-window)) ,n-start-buf)
+	       (editor-error "Original buffer deleted!")))))))
+
+;;; GROUP-READ-FILE reads in files for the group commands via DO-ACTIVE-GROUP.
+;;; We use FIND-FILE-BUFFER, which creates a new buffer when the file hasn't
+;;; already been read, to get files in, and then we delete the buffer if it is
+;;; newly created and "Group Find File" is false.  This lets FIND-FILE-BUFFER
+;;; do all the work.  We don't actually use the "Find File" command, so the
+;;; buffer history isn't affected.
+;;;
+;;; Search-Buffer is any temporary search buffer left over from the last file
+;;; that we want deleted.  We don't do the deletion if the buffer is modified.
+;;;
+(defun group-read-file (name search-buffer)
+  (unless (probe-file name)
+    (message "File ~A not found." name)
+    (throw 'file-not-found nil))
+  (multiple-value-bind (buffer created-p)
+		       (find-file-buffer name)
+    (setf (current-buffer) buffer)
+    (setf (window-buffer (current-window)) buffer)
+
+    (when (and search-buffer (not (buffer-modified search-buffer)))
+      (dolist (w (buffer-windows search-buffer))
+	(setf (window-buffer w) (current-buffer)))
+      (delete-buffer search-buffer))
+
+    (if (and created-p (not (value group-find-file)))
+	(current-buffer) nil)))
+
+;;; GROUP-SAVE-FILE is used by DO-ACTIVE-GROUP.
+;;;
+(defun group-save-file ()
+  (let* ((buffer (current-buffer))
+	 (pn (buffer-pathname buffer))
+	 (name (namestring pn)))
+    (when (and (buffer-modified buffer)
+	       (or (not (value group-save-file-confirm))
+		   (prompt-for-y-or-n
+		    :prompt (list "Save changes in ~A? " name)
+		    :default t)))
+      (save-file-command ()))))
+
+
+
+
+;;;; Searching and Replacing commands.
+
+(defcommand "Group Search" (p)
+  "Searches the active group for a specified string, which is prompted for."
+  "Searches the active group for a specified string."
+  (declare (ignore p))
+  (let ((string (prompt-for-string :prompt "Group Search: "
+				   :help "String to search for in active file group"
+				   :default *last-search-string*)))
+    (get-search-pattern string :forward)
+    (do-active-group
+     (do ((won (find-pattern (current-point) *last-search-pattern*)
+	       (find-pattern (current-point) *last-search-pattern*)))
+	 ((not won))
+       (character-offset (current-point) won)
+       (command-case
+	   (:prompt "Group Search: "
+		    :help "Type a character indicating the action to perform."
+		    :change-window nil)
+	 (:no "Search for the next occurrence.")
+	 (:do-all "Go on to the next file in the group."
+	  (return nil))
+	 ((:exit :yes) "Exit the search."
+	  (return-from group-search-command))
+	 (:recursive-edit "Enter a recursive edit."
+	  (do-recursive-edit)
+	  (get-search-pattern string :forward)))))
+    (message "All files in group ~S searched." *active-file-group-name*)))
+
+(defcommand "Group Replace" (p)
+  "Replaces one string with another in the active file group."
+  "Replaces one string with another in the active file group."
+  (declare (ignore p))
+  (let* ((target (prompt-for-string :prompt "Group Replace: "
+				    :help "Target string"
+				    :default *last-search-string*))
+	 (replacement (prompt-for-string :prompt "With: "
+					 :help "Replacement string")))
+    (do-active-group
+     (query-replace-function nil target replacement
+			     "Group Replace on previous file" t))
+    (message "Replacement done in all files in group ~S."
+	     *active-file-group-name*)))
+
+(defcommand "Group Query Replace" (p)
+  "Query Replace for the active file group."
+  "Query Replace for the active file group."
+  (declare (ignore p))
+  (let ((target (prompt-for-string :prompt "Group Query Replace: "
+				   :help "Target string"
+				   :default *last-search-string*)))
+    (let ((replacement (prompt-for-string :prompt "With: "
+					  :help "Replacement string")))
+      (do-active-group
+       (unless (query-replace-function
+		nil target replacement "Group Query Replace on previous file")
+	 (return nil)))
+      (message "Replacement done in all files in group ~S."
+	       *active-file-group-name*))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/highlight.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/highlight.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/highlight.lisp	(revision 13309)
@@ -0,0 +1,211 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Highlighting paren and some other good stuff.
+;;;
+;;; Written by Bill Chiles and Jim Healy.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; Open parens.
+
+(defhvar "Highlight Open Parens"
+  "When non-nil, causes open parens to be displayed in a different font when
+   the cursor is directly to the right of the corresponding close paren."
+  :value nil)
+
+(defhvar "Open Paren Finder Function"
+  "Should be a function that takes a mark for input and returns either NIL
+   if the mark is not after a close paren, or two (temporary) marks
+   surrounding the corresponding open paren."
+  :value 'lisp-open-paren-finder-function)
+
+
+(defvar *open-paren-font-marks* nil
+  "The pair of font-marks surrounding the currently highlighted open-
+   paren or nil if there isn't one.")
+
+(defvar *open-paren-highlight-font* 2
+  "The index into the font-map for the open paren highlighting font.")
+
+
+;;; MAYBE-HIGHLIGHT-OPEN-PARENS is a redisplay hook that matches parens by
+;;; highlighting the corresponding open-paren after a close-paren is
+;;; typed.
+;;; 
+(defun maybe-highlight-open-parens (window)
+  (declare (ignore window))
+  (when (value highlight-open-parens)
+    (if (and (value highlight-active-region) (region-active-p))
+	(kill-open-paren-font-marks)
+	(multiple-value-bind
+	    (start end)
+	    (funcall (value open-paren-finder-function)
+		     (current-point))
+	  (if (and start end)
+	      (set-open-paren-font-marks start end)
+	      (kill-open-paren-font-marks))))))
+;;;
+(add-hook redisplay-hook 'maybe-highlight-open-parens)
+
+(defun set-open-paren-font-marks (start end)
+  (if *open-paren-font-marks*
+      (flet ((maybe-move (dst src)
+	       (unless (mark= dst src)
+		 (move-font-mark dst src))))
+	(declare (inline maybe-move))
+	(maybe-move (region-start *open-paren-font-marks*) start)
+	(maybe-move (region-end *open-paren-font-marks*) end))
+      (let ((line (mark-line start)))
+	(setf *open-paren-font-marks*
+	      (region
+	       (font-mark line (mark-charpos start)
+			  *open-paren-highlight-font*)
+	       (font-mark line (mark-charpos end) 0))))))
+
+(defun kill-open-paren-font-marks ()
+  (when *open-paren-font-marks*
+    (delete-font-mark (region-start *open-paren-font-marks*))
+    (delete-font-mark (region-end *open-paren-font-marks*))
+    (setf *open-paren-font-marks* nil)))
+
+
+
+
+
+;;;; Active regions.
+
+(defvar *active-region-font-marks* nil)
+(defvar *active-region-highlight-font* 3
+  "The index into the font-map for the active region highlighting font.")
+
+
+;;; HIGHLIGHT-ACTIVE-REGION is a redisplay hook for active regions.
+;;; Since it is too hard to know how the region may have changed when it is
+;;; active and already highlighted, if it does not check out to being exactly
+;;; the same, we just delete all the font marks and make new ones.  When
+;;; the current window is the echo area window, just pretend everything is
+;;; okay; this keeps the region highlighted while we're in there.
+;;;
+(defun highlight-active-region (window)
+  (unless (eq window *echo-area-window*)
+    (when (value highlight-active-region)
+      (cond ((region-active-p)
+	     (cond ((not *active-region-font-marks*)
+		    (set-active-region-font-marks))
+		   ((check-active-region-font-marks))
+		   (t (kill-active-region-font-marks)
+		      (set-active-region-font-marks))))
+	    (*active-region-font-marks*
+	     (kill-active-region-font-marks))))))
+;;;
+(add-hook redisplay-hook 'highlight-active-region)
+
+(defun set-active-region-font-marks ()
+  (flet ((stash-a-mark (m &optional (font *active-region-highlight-font*))
+	   (push (font-mark (mark-line m) (mark-charpos m) font)
+		 *active-region-font-marks*)))
+    (let* ((region (current-region nil nil))
+	   (start (region-start region))
+	   (end (region-end region)))
+      (with-mark ((mark start))
+	(unless (mark= mark end)
+	  (loop
+	    (stash-a-mark mark)
+	    (unless (line-offset mark 1 0) (return))
+	    (when (mark>= mark end) (return)))
+	  (unless (start-line-p end) (stash-a-mark end 0))))))
+  (setf *active-region-font-marks* (nreverse *active-region-font-marks*)))
+
+(defun kill-active-region-font-marks ()
+  (dolist (m *active-region-font-marks*)
+    (delete-font-mark m))
+  (setf *active-region-font-marks* nil))
+
+;;; CHECK-ACTIVE-REGION-FONT-MARKS returns t if the current region is the same
+;;; as that what is highlighted on the screen.  This assumes
+;;; *active-region-font-marks* is non-nil.  At the very beginning, our start
+;;; mark must not be at the end; it must be at the first font mark; and the
+;;; font marks must be in the current buffer.  We don't make font marks if the
+;;; start is at the end, so if this is the case, then they just moved together.
+;;; We return nil in this case to kill all the font marks and make new ones, but
+;;; no new ones will be made.
+;;;
+;;; Sometimes we hack the font marks list and return t because we can easily
+;;; adjust the highlighting to be correct.  This keeps all the font marks from
+;;; being killed and re-established.  In the loop, if there are no more font
+;;; marks, we either ended a region already highlighted on the next line down,
+;;; or we have to revamp the font marks.  Before returning here, we see if the
+;;; region ends one more line down at the beginning of the line.  If this is
+;;; true, then the user is simply doing "Next Line" at the beginning of the
+;;; line.
+;;;
+;;; Each time through the loop we look at the top font mark, move our roving
+;;; mark down one line, and see if they compare.  If they are not equal, the
+;;; region may still be the same as that highlighted on the screen.  If this
+;;; is the last font mark, not at the beginning of the line, and it is at the
+;;; region's end, then this last font mark is in the middle of a line somewhere
+;;; changing the font from the highlighting font to the default font.  Return
+;;; t.
+;;;
+;;; If our roving mark is not at the current font mark, but it is at or after
+;;; the end of the active region, then the end of the active region has moved
+;;; before its previous location.
+;;;
+;;; Otherwise, move on to the next font mark.
+;;;
+;;; If our roving mark never moved onto a next line, then the buffer ends on the
+;;; previous line, and the last font mark changes from the highlighting font to
+;;; the default font.
+;;;
+(defun check-active-region-font-marks ()
+  (let* ((region (current-region nil nil))
+	 (end (region-end region)))
+    (with-mark ((mark (region-start region)))
+      (let ((first-active-mark (car *active-region-font-marks*))
+	    (last-active-mark (last *active-region-font-marks*)))
+	(if (and (mark/= mark end)
+		 (eq (current-buffer)
+		     (line-buffer (mark-line first-active-mark)))
+		 (mark= first-active-mark mark))
+	    (let ((marks (cdr *active-region-font-marks*)))
+	      (loop
+		(unless marks
+		  (let ((res (and (line-offset mark 1 0)
+				  (mark= mark end))))
+		    (when (and (not res)
+			       (line-offset mark 1 0)
+			       (mark= mark end)
+			       (start-line-p (car last-active-mark)))
+		      (setf (cdr last-active-mark)
+			    (list (font-mark (line-previous (mark-line mark))
+					     0
+					     *active-region-highlight-font*)))
+		      (return t))
+		    (return res)))
+		(let ((fmark (car marks)))
+		  (if (line-offset mark 1 0)
+		      (cond ((mark/= mark fmark)
+			     (return (and (not (cdr marks))
+					  (not (start-line-p fmark))
+					  (mark= fmark end))))
+			    ((mark>= mark end)
+			     (return nil))
+			    (t (setf marks (cdr marks))))
+
+		      (return (and (not (cdr marks))
+				   (not (start-line-p fmark))
+				   (mark= fmark end))))))))))))
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/hunk-draw.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/hunk-draw.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/hunk-draw.lisp	(revision 13309)
@@ -0,0 +1,504 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Bill Chiles and Rob MacLachlan.
+;;;
+;;; Hemlock screen painting routines for the IBM RT running X.
+;;;
+(in-package :hemlock-internals)
+
+
+;;;; TODO
+
+;; . do away with these bogus macros HUNK-PUT-STRING and HUNK-REPLACE-LINE-STRING.
+
+;; . concentrate these in a single point where we draw a string, so that we
+;;   can easily introduce foreground and background colors for syntax
+;;   highlighting and neater region highlighting.
+
+;; --GB 2003-05-22
+
+(defparameter hunk-height-limit 80 "Maximum possible height for any hunk.")
+(defparameter hunk-width-limit 200 "Maximum possible width for any hunk.")
+(defparameter hunk-top-border 2 "Clear area at beginning.")
+(defparameter hunk-left-border 10 "Clear area before first character.")
+(defparameter hunk-bottom-border 3 "Minimum Clear area at end.")
+(defparameter hunk-thumb-bar-bottom-border 10
+  "Minimum Clear area at end including room for thumb bar." )
+(defparameter hunk-modeline-top 2 "Extra black pixels above modeline chars.")
+(defparameter hunk-modeline-bottom 2 "Extra black pixels below modeline chars.")
+
+
+
+
+;;;; Character translations for CLX
+
+;;; HEMLOCK-TRANSLATE-DEFAULT.
+;;;
+;;; CLX glyph drawing routines allow for a character translation function.  The
+;;; default one takes a string (any kind) or a vector of numbers and slams them
+;;; into the outgoing request buffer.  When the argument is a string, it stops
+;;; processing if it sees a character that is not GRAPHIC-CHAR-P.  For each
+;;; graphical character, the function ultimately calls CHAR-CODE.
+;;;
+;;; Hemlock only passes simple-strings in, and these can only contain graphical
+;;; characters because of the line image builder, except for one case --
+;;; *line-wrap-char* which anyone can set.  Those who want to do evil things
+;;; with this should know what they are doing: if they want a funny glyph as
+;;; a line wrap char, then they should use CODE-CHAR on the font index.  This
+;;; allows the following function to translate everything with CHAR-CODE, and
+;;; everybody's happy.
+;;;
+;;; Actually, Hemlock can passes the line string when doing random-typeout which
+;;; does contain ^L's, tabs, etc.  Under X10 these came out as funny glyphs,
+;;; and under X11 the output is aborted without this function.
+;;;
+(defun hemlock-translate-default (src src-start src-end font dst dst-start)
+  (declare (simple-string src)
+	   (fixnum src-start src-end dst-start)
+	   (vector dst)
+	   (ignore font))
+  (do ((i src-start (1+ i))
+       (j dst-start (1+ j)))
+      ((>= i src-end) i)
+    (declare (fixnum i j))
+    (setf (aref dst j) (char-code (schar src i)))))
+
+#+clx
+(defvar *glyph-translate-function* #'xlib:translate-default)
+
+
+
+
+;;;; Drawing a line.
+
+;;;; We hack along --GB
+#+clx
+(defun find-color (window color)
+  (let ((ht (or (getf (xlib:window-plist window) :color-hash)
+                (setf (getf (xlib:window-plist window) :color-hash)
+                      (make-hash-table :test #'equalp)))))
+    (or (gethash color ht)
+        (setf (gethash color ht) (xlib:alloc-color (xlib:window-colormap window) color)))))
+
+(defparameter *color-map*
+  #("black" "white"
+    "black" "white"
+    "black" "white"
+    "black" "cornflower blue"
+
+    "black" "white"
+    "black" "white"
+    "black" "white"
+    "black" "white"
+
+    "blue4" "white"                     ;8 = comments
+    "green4" "white"                     ;9 = strings
+    "red" "white"                       ;10 = quote
+    "black" "white"
+
+    "black" "white"
+    "black" "white"
+    "black" "white"
+    "black" "white"))
+
+;;; HUNK-PUT-STRING takes a character (x,y) pair and computes at which pixel
+;;; coordinate to draw string with font from start to end.
+;;; 
+(defmacro hunk-put-string (x y font string start end)
+  (let ((gcontext (gensym)))
+    `(let ((,gcontext (bitmap-hunk-gcontext hunk)))
+       (xlib:with-gcontext (,gcontext :font ,font)
+	 (xlib:draw-image-glyphs
+	  (bitmap-hunk-xwindow hunk) ,gcontext
+	  (+ hunk-left-border (* ,x (font-family-width font-family)))
+	  (+ hunk-top-border (* ,y (font-family-height font-family))
+	     (font-family-baseline font-family))
+	  ,string :start ,start :end ,end
+	  :translate *glyph-translate-function*)))))
+
+(defun hunk-put-string* (hunk x y font-family font string start end)
+  (let ((gcontext (bitmap-hunk-gcontext hunk))
+        (font (svref (font-family-map font-family) font))
+        (fg   (find-color (bitmap-hunk-xwindow hunk) (svref *color-map* (* font 2))))
+        (bg   (find-color (bitmap-hunk-xwindow hunk) (svref *color-map* (1+ (* font 2))))))
+    (xlib:with-gcontext (gcontext :font font
+                                  :foreground fg
+                                  :background bg)
+      (xlib:draw-image-glyphs
+       (bitmap-hunk-xwindow hunk) gcontext
+       (+ hunk-left-border (* x (font-family-width font-family)))
+       (+ hunk-top-border (* y (font-family-height font-family))
+          (font-family-baseline font-family))
+       string :start start :end end
+       :translate *glyph-translate-function*))))
+
+;;; HUNK-REPLACE-LINE-STRING takes a character (x,y) pair and computes at
+;;; which pixel coordinate to draw string with font from start to end. We draw
+;;; the text on a pixmap and later blast it out to avoid line flicker since
+;;; server on the RT is not very clever; it clears the entire line before
+;;; drawing text.
+
+(defun hunk-replace-line-string* (hunk gcontext x y font-family font string start end)
+  (declare (ignore y))
+  (let ((font (svref (font-family-map font-family) font))
+        (fg   (find-color (bitmap-hunk-xwindow hunk) (svref *color-map* (* font 2))))
+        (bg   (find-color (bitmap-hunk-xwindow hunk) (svref *color-map* (1+ (* font 2))))))
+    (xlib:with-gcontext (gcontext :font font
+                                  :foreground fg
+                                  :background bg)
+      (xlib:draw-image-glyphs
+       (hunk-replace-line-pixmap) gcontext
+       (+ hunk-left-border (* x (font-family-width font-family)))
+       (font-family-baseline font-family)
+       string :start start :end end
+       :translate *glyph-translate-function*))))
+
+;;; Hunk-Write-Line  --  Internal
+;;;
+;;;    Paint a dis-line on a hunk, taking font-changes into consideration.
+;;; The area of the hunk drawn on is assumed to be cleared.  If supplied,
+;;; the line is written at Position, and the position in the dis-line
+;;; is ignored.
+;;;
+(defun hunk-write-line (hunk dl &optional (position (dis-line-position dl)))
+  (let* ((font-family (bitmap-hunk-font-family hunk))
+	 (chars (dis-line-chars dl))
+	 (length (dis-line-length dl)))
+    (let ((last 0)
+	  (last-font 0))
+      (do ((change (dis-line-font-changes dl) (font-change-next change)))
+	  ((null change)
+           (hunk-put-string* hunk last position font-family last-font chars last length))
+	(let ((x (font-change-x change)))
+          (hunk-put-string* hunk last position font-family last-font chars last x)
+	  (setq last x
+                last-font (font-change-font change)) )))))
+
+
+;;; We hack this since the X11 server's aren't clever about DRAW-IMAGE-GLYPHS;
+;;; that is, they literally clear the line, and then blast the new glyphs.
+;;; We don't hack replacing the line when reverse video is turned on because
+;;; this doesn't seem to work too well.  Also, hacking replace line on the
+;;; color Megapel display is SLOW!
+;;;
+(defvar *hack-hunk-replace-line* t)
+
+;;; Hunk-Replace-Line  --  Internal
+;;;
+;;;    Similar to Hunk-Write-Line, but the line need not be clear.
+;;;
+(defun hunk-replace-line (hunk dl &optional
+			       (position (dis-line-position dl)))
+  (if *hack-hunk-replace-line*
+      (hunk-replace-line-on-a-pixmap hunk dl position)
+      (old-hunk-replace-line hunk dl position)))
+
+(defun old-hunk-replace-line (hunk dl &optional (position (dis-line-position dl)))
+  (let* ((font-family (bitmap-hunk-font-family hunk))
+	 (chars (dis-line-chars dl))
+	 (length (dis-line-length dl))
+	 (height (font-family-height font-family)) )
+    (let ((last 0)
+	  (last-font 0))
+      (do ((change (dis-line-font-changes dl) (font-change-next change)))
+	  ((null change)
+	   (hunk-put-string* hunk last position font-family last-font chars last length)
+	   (let ((dx (+ hunk-left-border
+			(* (font-family-width font-family) length))))
+	     (xlib:clear-area (bitmap-hunk-xwindow hunk)
+			      :x dx
+			      :y (+ hunk-top-border (* position height))
+			      :width (- (bitmap-hunk-width hunk) dx)
+			      :height height)))
+	(let ((x (font-change-x change)))
+          (hunk-put-string* hunk last position font-family last-font chars last x)
+	  (setq last x  last-font (font-change-font change)) )))))
+
+(defvar *hunk-replace-line-pixmap* nil)
+
+(defun hunk-replace-line-pixmap ()
+  (if *hunk-replace-line-pixmap*
+      *hunk-replace-line-pixmap*
+      (let* ((hunk (window-hunk *current-window*))
+	     (gcontext (bitmap-hunk-gcontext hunk))
+	     (screen (xlib:display-default-screen
+		      (bitmap-device-display (device-hunk-device hunk))))
+	     (height (font-family-height *default-font-family*))
+	     (pixmap (xlib:create-pixmap
+		     :width (* hunk-width-limit
+			       (font-family-width *default-font-family*))
+		     :height height :depth (xlib:screen-root-depth screen)
+		     :drawable (xlib:screen-root screen))))
+	(xlib:with-gcontext (gcontext :function boole-1
+				      :foreground *default-background-pixel*)
+	  (xlib:draw-rectangle pixmap gcontext 0 0 hunk-left-border height t))
+	(setf *hunk-replace-line-pixmap* pixmap))))
+
+(defun hunk-replace-line-on-a-pixmap (hunk dl position)
+  (let* ((font-family (bitmap-hunk-font-family hunk))
+	 (chars (dis-line-chars dl))
+	 (length (dis-line-length dl))
+	 (height (font-family-height font-family))
+	 (last 0)
+	 (last-font 0)
+	 (gcontext (bitmap-hunk-gcontext hunk)))
+    (do ((change (dis-line-font-changes dl) (font-change-next change)))
+	((null change)
+	 (hunk-replace-line-string* hunk gcontext last position font-family last-font chars last length)
+	 (let* ((dx (+ hunk-left-border
+		       (* (font-family-width font-family) length)))
+		(dy (+ hunk-top-border (* position height)))
+		(xwin (bitmap-hunk-xwindow hunk)))
+	   (xlib:with-gcontext (gcontext :exposures nil)
+	     (xlib:copy-area (hunk-replace-line-pixmap) gcontext
+			     0 0 dx height xwin 0 dy))
+	   (xlib:clear-area xwin :x dx :y dy
+			    :width (- (bitmap-hunk-width hunk) dx)
+			    :height height)))
+      (let ((x (font-change-x change)))
+        (hunk-replace-line-string* hunk gcontext last position font-family last-font chars last x)
+	(setq last x  last-font (font-change-font change))))))
+
+
+;;; HUNK-REPLACE-MODELINE sets the entire mode line to the the foreground
+;;; color, so the initial bits where no characters go also is highlighted.
+;;; Then the text is drawn background on foreground (hightlighted).  This
+;;; function assumes that BITMAP-HUNK-MODELINE-POS will not return nil;
+;;; that is, there is a modeline.  This function should assume the gcontext's
+;;; font is the default font of the hunk.  We must LET bind the foreground and
+;;; background values before entering XLIB:WITH-GCONTEXT due to a non-obvious
+;;; or incorrect implementation.
+;;; 
+(defun hunk-replace-modeline (hunk)
+  (let* ((dl (bitmap-hunk-modeline-dis-line hunk))
+	 (font-family (bitmap-hunk-font-family hunk))
+	 (default-font (svref (font-family-map font-family) 0))
+	 (modeline-pos (bitmap-hunk-modeline-pos hunk))
+	 (xwindow (bitmap-hunk-xwindow hunk))
+	 (gcontext (bitmap-hunk-gcontext hunk)))
+    (xlib:draw-rectangle xwindow gcontext 0 modeline-pos
+			 (bitmap-hunk-width hunk)
+			 (+ hunk-modeline-top hunk-modeline-bottom
+			    (font-family-height font-family))
+			 t)
+    (xlib:with-gcontext (gcontext :foreground
+				  (xlib:gcontext-background gcontext)
+				  :background
+				  (xlib:gcontext-foreground gcontext)
+				  :font default-font)
+      (xlib:draw-image-glyphs xwindow gcontext hunk-left-border
+			      (+ modeline-pos hunk-modeline-top
+				 (font-family-baseline font-family))
+			      (dis-line-chars dl)
+			      :end (dis-line-length dl)
+			      :translate *glyph-translate-function*))))
+
+
+
+;;;; Cursor/Border color manipulation.
+
+;;; *hemlock-listener* is set to t by default because we can't know from X
+;;; whether we come up with the pointer in our window.  There is no initial
+;;; :enter-window event.  Defaulting this to nil causes the cursor to be hollow
+;;; when the window comes up under the mouse, and you have to know how to fix
+;;; it.  Defaulting it to t causes the cursor to always come up full, as if
+;;; Hemlock is the X listener, but this recovers naturally as you move into the
+;;; window.  This also coincides with Hemlock's border coming up highlighted,
+;;; even when Hemlock is not the listener.
+;;;
+(defvar *hemlock-listener* t
+  "Highlight border when the cursor is dropped and Hemlock can receive input.")
+(defvar *current-highlighted-border* nil
+  "When non-nil, the bitmap-hunk with the highlighted border.")
+
+(defvar *hunk-cursor-x* 0 "The current cursor X position in pixels.")
+(defvar *hunk-cursor-y* 0 "The current cursor Y position in pixels.")
+(defvar *cursor-hunk* nil "Hunk the cursor is displayed on.")
+(defvar *cursor-dropped* nil) ; True if the cursor is currently displayed.
+
+;;; HUNK-SHOW-CURSOR locates the cursor at character position (x,y) in hunk.
+;;; If the cursor is currently displayed somewhere, then lift it, and display
+;;; it at its new location.
+;;; 
+(defun hunk-show-cursor (hunk x y)
+  (unless (and (= x *hunk-cursor-x*)
+	       (= y *hunk-cursor-y*)
+	       (eq hunk *cursor-hunk*))
+    (let ((cursor-down *cursor-dropped*))
+      (when cursor-down (lift-cursor))
+      (setf *hunk-cursor-x* x)
+      (setf *hunk-cursor-y* y)
+      (setf *cursor-hunk* hunk)
+      (when cursor-down (drop-cursor)))))
+
+;;; FROB-CURSOR is the note-read-wait method for bitmap redisplay.  We
+;;; show a cursor and highlight the listening window's border when waiting
+;;; for input.
+;;; 
+(defun frob-cursor (on)
+  (if on (drop-cursor) (lift-cursor)))
+
+(declaim (special *default-border-pixmap* *highlight-border-pixmap*))
+
+;;; DROP-CURSOR and LIFT-CURSOR are separate functions from FROB-CURSOR
+;;; because they are called a couple places (e.g., HUNK-EXPOSED-REGION
+;;; and SMART-WINDOW-REDISPLAY).  When the cursor is being dropped, since
+;;; this means Hemlock is listening in the *cursor-hunk*, make sure the
+;;; border of the window is highlighted as well.
+;;;
+(defun drop-cursor ()
+  (unless *cursor-dropped*
+    (unless *hemlock-listener* (cursor-invert-center))
+    (cursor-invert)
+    (when *hemlock-listener*
+      (cond (*current-highlighted-border*
+	     (unless (eq *current-highlighted-border* *cursor-hunk*)
+	       (setf (xlib:window-border
+		      (window-group-xparent
+		       (bitmap-hunk-window-group *current-highlighted-border*)))
+		     *default-border-pixmap*)
+	       (setf (xlib:window-border
+		      (window-group-xparent
+		       (bitmap-hunk-window-group *cursor-hunk*)))
+		     *highlight-border-pixmap*)
+	       ;; For complete gratuitous pseudo-generality, should force
+	       ;; output on *current-highlighted-border* device too.
+	       (xlib:display-force-output
+		(bitmap-device-display (device-hunk-device *cursor-hunk*)))))
+	    (t (setf (xlib:window-border
+		      (window-group-xparent
+		       (bitmap-hunk-window-group *cursor-hunk*)))
+		     *highlight-border-pixmap*)
+	       (xlib:display-force-output
+		(bitmap-device-display (device-hunk-device *cursor-hunk*)))))
+      (setf *current-highlighted-border* *cursor-hunk*))
+    (setq *cursor-dropped* t)))
+
+;;;
+(defun lift-cursor ()
+  (when *cursor-dropped*
+    (unless *hemlock-listener* (cursor-invert-center))
+    (cursor-invert)
+    (setq *cursor-dropped* nil)))
+
+
+(defun cursor-invert-center ()
+  (let ((family (bitmap-hunk-font-family *cursor-hunk*))
+	(gcontext (bitmap-hunk-gcontext *cursor-hunk*)))
+    (xlib:with-gcontext (gcontext :function boole-xor
+				  :foreground *foreground-background-xor*)
+      (xlib:draw-rectangle (bitmap-hunk-xwindow *cursor-hunk*)
+			   gcontext
+			   (+ hunk-left-border
+			      (* *hunk-cursor-x* (font-family-width family))
+			      (font-family-cursor-x-offset family)
+			      1)
+			   (+ hunk-top-border
+			      (* *hunk-cursor-y* (font-family-height family))
+			      (font-family-cursor-y-offset family)
+			      1)
+			   (- (font-family-cursor-width family) 2)
+			   (- (font-family-cursor-height family) 2)
+			   t)))
+  (xlib:display-force-output
+   (bitmap-device-display (device-hunk-device *cursor-hunk*))))
+
+(defun cursor-invert ()
+  (let ((family (bitmap-hunk-font-family *cursor-hunk*))
+	(gcontext (bitmap-hunk-gcontext *cursor-hunk*)))
+    (xlib:with-gcontext (gcontext :function boole-xor
+				  :foreground *foreground-background-xor*)
+      (xlib:draw-rectangle (bitmap-hunk-xwindow *cursor-hunk*)
+			   gcontext
+			   (+ hunk-left-border
+			      (* *hunk-cursor-x* (font-family-width family))
+			      (font-family-cursor-x-offset family))
+			   (+ hunk-top-border
+			      (* *hunk-cursor-y* (font-family-height family))
+			      (font-family-cursor-y-offset family))
+			   (font-family-cursor-width family)
+			   (font-family-cursor-height family)
+			   t)))
+  (xlib:display-force-output
+   (bitmap-device-display (device-hunk-device *cursor-hunk*))))
+
+
+
+
+;;;; Clearing and Copying Lines.
+
+(defun hunk-clear-lines (hunk start count)
+  (let ((height (font-family-height (bitmap-hunk-font-family hunk))))
+    (xlib:clear-area (bitmap-hunk-xwindow hunk)
+		     :x 0 :y (+ hunk-top-border (* start height))
+		     :width (bitmap-hunk-width hunk)
+		     :height (* count height))))
+
+(defun hunk-copy-lines (hunk src dst count)
+  (let ((height (font-family-height (bitmap-hunk-font-family hunk)))
+	(xwindow (bitmap-hunk-xwindow hunk)))
+    (xlib:copy-area xwindow (bitmap-hunk-gcontext hunk)
+		    0 (+ hunk-top-border (* src height))
+		    (bitmap-hunk-width hunk) (* height count)
+		    xwindow 0 (+ hunk-top-border (* dst height)))))
+
+
+
+
+;;;; Drawing bottom border meter.
+
+;;; HUNK-DRAW-BOTTOM-BORDER assumes eight-character-space tabs.  The LOGAND
+;;; calls in the loop are testing for no remainder when dividing by 8, 4,
+;;; and other.  This lets us quickly draw longer notches at tab stops and
+;;; half way in between.  This function assumes that
+;;; BITMAP-HUNK-MODELINE-POS will not return nil; that is, that there is a
+;;; modeline.
+;;; 
+(defun hunk-draw-bottom-border (hunk)
+  (when (bitmap-hunk-thumb-bar-p hunk)
+    (let* ((xwindow (bitmap-hunk-xwindow hunk))
+	   (gcontext (bitmap-hunk-gcontext hunk))
+	   (modeline-pos (bitmap-hunk-modeline-pos hunk))
+	   (font-family (bitmap-hunk-font-family hunk))
+	   (font-width (font-family-width font-family)))
+      (xlib:clear-area xwindow :x 0 :y (- modeline-pos
+					  hunk-thumb-bar-bottom-border)
+		       :width (bitmap-hunk-width hunk)
+		       :height hunk-bottom-border)
+      (let ((x (+ hunk-left-border (ash font-width -1)))
+	    (y7 (- modeline-pos 7))
+	    (y5 (- modeline-pos 5))
+	    (y3 (- modeline-pos 3)))
+	(dotimes (i (bitmap-hunk-char-width hunk))
+	  (cond ((zerop (logand i 7))
+		 (xlib:draw-rectangle xwindow gcontext
+				      x y7 (if (= i 80) 2 1) 7 t))
+		((zerop (logand i 3))
+		 (xlib:draw-rectangle xwindow gcontext x y5 1 5 t))
+		(t
+		 (xlib:draw-rectangle xwindow gcontext x y3 1 3 t)))
+	  (incf x font-width))))))
+
+;; $Log$
+;; Revision 1.1  2003/10/19 08:57:15  gb
+;; Initial revision
+;;
+;; Revision 1.1.2.2  2003/09/18 13:40:16  gb
+;; Conditionalize for #-CLX, a little more.
+;;
+;; Revision 1.1.2.1  2003/08/10 19:11:27  gb
+;; New files, imported from upstream CVS as of 03/08/09.
+;;
+;; Revision 1.4  2003/08/05 19:54:17  gilbert
+;; - did away with some macros
+;; - invested in a left margin for added readability of hemlock frames.
+;;
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/input.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/input.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/input.lisp	(revision 13309)
@@ -0,0 +1,501 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains the code that handles input to Hemlock.
+;;;
+(in-package :hemlock-internals)
+
+;;;
+;;; INPUT-WAITING is exported solely as a hack for the kbdmac definition
+;;; mechanism.
+;;;
+
+
+;;; These are public variables users hand to the four basic editor input
+;;; routines for method dispatching:
+;;;    GET-KEY-EVENT
+;;;    UNGET-KEY-EVENT
+;;;    LISTEN-EDITOR-INPUT
+;;;    CLEAR-EDITOR-INPUT
+;;;
+(defvar *editor-input* nil
+  "A structure used to do various operations on terminal input.")
+
+(defvar *real-editor-input* ()
+  "Useful when we want to read from the terminal when *editor-input* is
+   rebound.")
+
+
+
+
+;;;; editor-input structure.
+
+(defstruct (editor-input (:print-function
+			  (lambda (s stream d)
+			    (declare (ignore s d))
+			    (write-string "#<Editor-Input stream>" stream))))
+  get          ; A function that returns the next key-event in the queue.
+  unget        ; A function that puts a key-event at the front of the queue.
+  listen       ; A function that tells whether the queue is empty.
+  clear        ; A function that empties the queue.
+  ;;
+  ;; Queue of events on this stream.  The queue always contains at least one
+  ;; one element, which is the key-event most recently read.  If no event has
+  ;; been read, the event is a dummy with a nil key-event.
+  head
+  tail)
+
+
+;;; These are the elements of the editor-input event queue.
+;;;
+(defstruct (input-event (:constructor make-input-event ())) 
+  next		; Next queued event, or NIL if none.
+  hunk		; Screen hunk event was read from.
+  key-event     ; Key-event read.
+  x		; X and Y character position of mouse cursor.
+  y
+  unread-p)
+
+(defvar *free-input-events* ())
+
+(defun new-event (key-event x y hunk next &optional unread-p)
+  (let ((res (if *free-input-events*
+		 (shiftf *free-input-events*
+			 (input-event-next *free-input-events*))
+		 (make-input-event))))
+    (setf (input-event-key-event res) key-event)
+    (setf (input-event-x res) x)
+    (setf (input-event-y res) y)
+    (setf (input-event-hunk res) hunk)
+    (setf (input-event-next res) next)
+    (setf (input-event-unread-p res) unread-p)
+    res))
+
+;;; This is a public variable.
+;;;
+(defvar *last-key-event-typed* ()
+  "This variable contains the last key-event typed by the user and read as
+   input.")
+
+;;; This is a public variable.  SITE-INIT initializes this.
+;;;
+(defvar *key-event-history* nil
+  "This ring holds the last 60 key-events read by the command interpreter.")
+
+(declaim (special *input-transcript*))
+
+;;; DQ-EVENT is used in editor stream methods for popping off input.
+;;; If there is an event not yet read in Stream, then pop the queue
+;;; and return the character.  If there is none, return NIL.
+;;;
+(defun dq-event (stream)
+  (hemlock-ext:without-interrupts
+   (let* ((head (editor-input-head stream))
+	  (next (input-event-next head)))
+     (if next
+	 (let ((key-event (input-event-key-event next)))
+	   (setf (editor-input-head stream) next)
+	   (shiftf (input-event-next head) *free-input-events* head)
+	   (ring-push key-event *key-event-history*)
+	   (setf *last-key-event-typed* key-event)
+	   (when *input-transcript* 
+	     (vector-push-extend key-event *input-transcript*))
+	   key-event)))))
+
+;;; Q-EVENT is used in low level input fetching routines to add input to the
+;;; editor stream.
+;;; 
+(defun q-event (stream key-event &optional x y hunk)
+  (hemlock-ext:without-interrupts
+   (let ((new (new-event key-event x y hunk nil))
+	 (tail (editor-input-tail stream)))
+     (setf (input-event-next tail) new)
+     (setf (editor-input-tail stream) new))))
+
+(defun un-event (key-event stream)
+  (hemlock-ext:without-interrupts
+   (let* ((head (editor-input-head stream))
+	  (next (input-event-next head))
+	  (new (new-event key-event (input-event-x head) (input-event-y head)
+			  (input-event-hunk head) next t)))
+     (setf (input-event-next head) new)
+     (unless next (setf (editor-input-tail stream) new)))))
+
+
+
+
+;;;; Keyboard macro hacks.
+
+(defvar *input-transcript* ()
+  "If this variable is non-null then it should contain an adjustable vector
+  with a fill pointer into which all keyboard input will be pushed.")
+
+;;; INPUT-WAITING  --  Internal
+;;;
+;;;    An Evil hack that tells us whether there is an unread key-event on
+;;; *editor-input*.  Note that this is applied to the real *editor-input*
+;;; rather than to a kbdmac stream.
+;;;
+(defun input-waiting ()
+  "Returns true if there is a key-event which has been unread-key-event'ed
+   on *editor-input*.  Used by the keyboard macro stuff."
+  (let ((next (input-event-next
+	       (editor-input-head *real-editor-input*))))
+    (and next (input-event-unread-p next))))
+
+
+
+
+;;;; Input method macro.
+
+(defvar *in-hemlock-stream-input-method* nil
+  "This keeps us from undefined nasties like re-entering Hemlock stream
+   input methods from input hooks and scheduled events.")
+
+(declaim (special *screen-image-trashed*))
+
+;;; These are the characters GET-KEY-EVENT notices when it pays attention
+;;; to aborting input.  This happens via EDITOR-INPUT-METHOD-MACRO.
+;;;
+(defparameter editor-abort-key-events (list #k"Control-g" #k"Control-G"))
+
+#+clx
+(defun cleanup-for-wm-closed-display(closed-display)
+  ;; Remove fd-handlers
+  (hemlock-ext:disable-clx-event-handling closed-display)
+  ;; Close file descriptor and note DEAD.
+  (xlib:close-display closed-display)
+  ;;
+  ;; At this point there is not much sense to returning to Lisp
+  ;; as the editor cannot be re-entered (there are lots of pointers
+  ;; to the dead display around that will cause subsequent failures).
+  ;; Maybe could switch to tty mode then (save-all-files-and-exit)?
+  ;; For now, just assume user wanted an easy way to kill the session.
+  (hemlock-ext:quit))
+
+(defmacro abort-key-event-p (key-event)
+  `(member ,key-event editor-abort-key-events))
+
+;;; EDITOR-INPUT-METHOD-MACRO  --  Internal.
+;;;
+;;; WINDOWED-GET-KEY-EVENT and TTY-GET-KEY-EVENT use this.  Somewhat odd stuff
+;;; goes on here because this is the place where Hemlock waits, so this is
+;;; where we redisplay, check the time for scheduled events, etc.  In the loop,
+;;; we call the input hook when we get a character and leave the loop.  If
+;;; there isn't any input, invoke any scheduled events whose time is up.
+;;; Unless SERVE-EVENT returns immediately and did something, (serve-event 0),
+;;; call redisplay, note that we are going into a read wait, and call
+;;; SERVE-EVENT with a wait or infinite timeout.  Upon exiting the loop, turn
+;;; off the read wait note and check for the abort character.  Return the
+;;; key-event we got.  We bind an error condition handler here because the
+;;; default Hemlock error handler goes into a little debugging prompt loop, but
+;;; if we got an error in getting input, we should prompt the user using the
+;;; input method (recursively even).
+;;;
+(eval-when (:compile-toplevel :execute)
+
+(defmacro editor-input-method-macro ()
+  `(handler-bind
+       ((error
+	 (lambda (condition)
+	   (when (typep condition 'stream-error)
+	     (let* ((stream (stream-error-stream condition))
+		    (display *editor-windowed-input*)
+		    (display-stream 
+		     #+CLX
+		     (and display (xlib::display-input-stream display))))
+	       (when (eq stream display-stream)
+		 ;;(format *error-output* "~%Hemlock: Display died!~%~%")
+		 (cleanup-for-wm-closed-display display)
+		 (exit-hemlock nil))
+	       (let ((device
+		      (device-hunk-device (window-hunk (current-window)))))
+		 (funcall (device-exit device) device))
+	       (invoke-debugger condition)))))
+	#+(and CLX )
+	(xlib:closed-display
+	 (lambda(condition)
+	   (let ((display (xlib::closed-display-display condition)))
+	     (format *error-output*
+		     "Closed display on stream ~a~%"
+		     (xlib::display-input-stream display)))
+	   (exit-hemlock nil)))
+	)
+;     (when *in-hemlock-stream-input-method*
+;       (error "Entering Hemlock stream input method recursively!"))
+     (let ((*in-hemlock-stream-input-method* t)
+	   (nrw-fun (device-note-read-wait
+		     (device-hunk-device (window-hunk (current-window)))))
+	   key-event)
+       (loop
+	 (when (setf key-event (dq-event stream))
+	   (dolist (f (variable-value 'hemlock::input-hook)) (funcall f))
+	   (return))
+	 (invoke-scheduled-events)
+	 (unless (or (hemlock-ext:serve-event 0)
+		     (internal-redisplay))
+	   (internal-redisplay)
+	   (when nrw-fun (funcall nrw-fun t))
+	   (let ((wait (next-scheduled-event-wait)))
+	     (if wait (hemlock-ext:serve-event wait) (hemlock-ext:serve-event)))))
+       (when nrw-fun (funcall nrw-fun nil))
+       (when (and (abort-key-event-p key-event)
+		  ;; ignore-abort-attempts-p must exist outside the macro.
+		  ;; in this case it is bound in GET-KEY-EVENT.
+		  (not ignore-abort-attempts-p))
+	 (beep)
+	 (throw 'editor-top-level-catcher nil))
+       key-event)))
+) ;eval-when
+
+
+
+
+;;;; Editor input from windowing system.
+#+clx
+(defstruct (windowed-editor-input
+	    (:include editor-input
+		      (get #'windowed-get-key-event)
+		      (unget #'windowed-unget-key-event)
+		      (listen #'windowed-listen)
+		      (clear #'windowed-clear-input))
+	    (:print-function
+	     (lambda (s stream d)
+	       (declare (ignore s d))
+	       (write-string "#<Editor-Window-Input stream>" stream)))
+	    (:constructor make-windowed-editor-input
+			  (&optional (head (make-input-event)) (tail head))))
+  hunks)      ; List of bitmap-hunks which input to this stream.
+
+#+clx
+;;; There's actually no difference from the TTY case...
+(defun windowed-get-key-event (stream ignore-abort-attempts-p)
+  (tty-get-key-event stream ignore-abort-attempts-p))
+
+#+clx
+(defun windowed-unget-key-event (key-event stream)
+  (un-event key-event stream))
+
+#+clx
+(defun windowed-clear-input (stream)
+  (loop (unless (hemlock-ext:serve-event 0) (return)))
+  (hemlock-ext:without-interrupts
+   (let* ((head (editor-input-head stream))
+	  (next (input-event-next head)))
+     (when next
+       (setf (input-event-next head) nil)
+       (shiftf (input-event-next (editor-input-tail stream))
+	       *free-input-events* next)
+       (setf (editor-input-tail stream) head)))))
+
+#+clx
+(defun windowed-listen (stream)
+  (loop
+    ;; Don't service anymore events if we just got some input.
+    (when (input-event-next (editor-input-head stream))
+      (return t))
+    ;;
+    ;; If nothing is pending, check the queued input.
+    (unless (hemlock-ext:serve-event 0)
+      (return (not (null (input-event-next (editor-input-head stream))))))))
+
+
+
+;;;; Editor input from a tty.
+
+(defstruct (tty-editor-input
+	    (:include editor-input
+		      (get #'tty-get-key-event)
+		      (unget #'tty-unget-key-event)
+		      (listen #'tty-listen)
+		      (clear #'tty-clear-input))
+	    (:print-function
+	     (lambda (obj stream n)
+	       (declare (ignore obj n))
+	       (write-string "#<Editor-Tty-Input stream>" stream)))
+	    (:constructor make-tty-editor-input
+			  (fd &optional (head (make-input-event)) (tail head))))
+  fd)
+
+(defun tty-get-key-event (stream ignore-abort-attempts-p)
+  (editor-input-method-macro))
+
+(defun tty-unget-key-event (key-event stream)
+  (un-event key-event stream))
+
+(defun tty-clear-input (stream)
+  (hemlock-ext:without-interrupts
+   (let* ((head (editor-input-head stream))
+	  (next (input-event-next head)))
+     (when next
+       (setf (input-event-next head) nil)
+       (shiftf (input-event-next (editor-input-tail stream))
+	       *free-input-events* next)
+       (setf (editor-input-tail stream) head)))))
+
+;;; Note that we never return NIL as long as there are events to be served with
+;;; SERVE-EVENT.  Thus non-keyboard input (i.e. process output) 
+;;; effectively causes LISTEN to block until either all the non-keyboard input
+;;; has happened, or there is some real keyboard input.
+;;;
+(defun tty-listen (stream)
+  (loop
+    ;; Don't service anymore events if we just got some input.
+    (when (or (input-event-next (editor-input-head stream))
+	      (editor-tty-listen stream))
+      (return t))
+    ;; If nothing is pending, check the queued input.
+    (unless (hemlock-ext:serve-event 0)
+      (return (not (null (input-event-next (editor-input-head stream))))))))
+
+
+
+;;;; GET-KEY-EVENT, UNGET-KEY-EVENT, LISTEN-EDITOR-INPUT, CLEAR-EDITOR-INPUT.
+
+;;; GET-KEY-EVENT -- Public.
+;;;
+(defun get-key-event (editor-input &optional ignore-abort-attempts-p)
+  "This function returns a key-event as soon as it is available on
+   editor-input.  Editor-input is either *editor-input* or *real-editor-input*.
+   Ignore-abort-attempts-p indicates whether #k\"C-g\" and #k\"C-G\" throw to
+   the editor's top-level command loop; when this is non-nil, this function
+   returns those key-events when the user types them.  Otherwise, it aborts the
+   editor's current state, returning to the command loop."
+  (funcall (editor-input-get editor-input) editor-input ignore-abort-attempts-p))
+
+;;; UNGET-KEY-EVENT -- Public.
+;;;
+(defun unget-key-event (key-event editor-input)
+  "This function returns the key-event to editor-input, so the next invocation
+   of GET-KEY-EVENT will return the key-event.  If the key-event is #k\"C-g\"
+   or #k\"C-G\", then whether GET-KEY-EVENT returns it depends on its second
+   argument.  Editor-input is either *editor-input* or *real-editor-input*."
+  (funcall (editor-input-unget editor-input) key-event editor-input))
+
+;;; CLEAR-EDITOR-INPUT -- Public.
+;;;
+(defun clear-editor-input (editor-input)
+  "This function flushes any pending input on editor-input.  Editor-input
+   is either *editor-input* or *real-editor-input*."
+  (funcall (editor-input-clear editor-input) editor-input))
+
+;;; LISTEN-EDITOR-INPUT -- Public.
+;;;
+(defun listen-editor-input (editor-input)
+  "This function returns whether there is any input available on editor-input.
+   Editor-input is either *editor-input* or *real-editor-input*."
+  (funcall (editor-input-listen editor-input) editor-input))
+
+
+
+
+;;;; LAST-KEY-EVENT-CURSORPOS and WINDOW-INPUT-HANDLER.
+
+;;; LAST-KEY-EVENT-CURSORPOS  --  Public
+;;;
+;;; Just look up the saved info in the last read key event.
+;;;
+(defun last-key-event-cursorpos ()
+  "Return as values, the (X, Y) character position and window where the
+   last key event happened.  If this cannot be determined, Nil is returned.
+   If in the modeline, return a Y position of NIL and the correct X and window.
+   Returns nil for terminal input."
+  (let* ((ev (editor-input-head *real-editor-input*))
+	 (hunk (input-event-hunk ev))
+	 (window (and hunk (device-hunk-window hunk))))
+    (when window
+      (values (input-event-x ev) (input-event-y ev) window))))
+
+;;; WINDOW-INPUT-HANDLER  --  Internal
+;;;
+;;; This is the input-handler function for hunks that implement windows.  It
+;;; just queues the events on *real-editor-input*.
+;;;
+(defun window-input-handler (hunk char x y)
+  (q-event *real-editor-input* char x y hunk))
+
+
+
+
+;;;; Random typeout input routines.
+
+(defun wait-for-more (stream)
+  (let ((key-event (more-read-key-event)))
+    (cond ((logical-key-event-p key-event :yes))
+	  ((or (logical-key-event-p key-event :do-all)
+	       (logical-key-event-p key-event :exit))
+	   (setf (random-typeout-stream-no-prompt stream) t)
+	   (random-typeout-cleanup stream))
+	  ((logical-key-event-p key-event :keep)
+	   (setf (random-typeout-stream-no-prompt stream) t)
+	   (maybe-keep-random-typeout-window stream)
+	   (random-typeout-cleanup stream))
+	  ((logical-key-event-p key-event :no)
+	   (random-typeout-cleanup stream)
+	   (throw 'more-punt nil))
+	  (t
+	   (unget-key-event key-event *editor-input*)
+	   (random-typeout-cleanup stream)
+	   (throw 'more-punt nil)))))
+
+(declaim (special *more-prompt-action*))
+
+(defun maybe-keep-random-typeout-window (stream)
+  (let* ((window (random-typeout-stream-window stream))
+	 (buffer (window-buffer window))
+	 (start (buffer-start-mark buffer)))
+    (when (typep (hi::device-hunk-device (hi::window-hunk window))
+		 'hi::bitmap-device)
+      (let ((*more-prompt-action* :normal))
+	(update-modeline-field buffer window :more-prompt)
+	(random-typeout-redisplay window))
+      (buffer-start (buffer-point buffer))
+      (let* ((xwindow (make-xwindow-like-hwindow window))
+	     (window (make-window start :window xwindow)))
+	(unless window
+	  #+clx(xlib:destroy-window xwindow)
+	  (editor-error "Could not create random typeout window."))))))
+
+(defun end-random-typeout (stream)
+  (let ((*more-prompt-action* :flush)
+	(window (random-typeout-stream-window stream)))
+    (update-modeline-field (window-buffer window) window :more-prompt)
+    (random-typeout-redisplay window))
+  (unless (random-typeout-stream-no-prompt stream)
+    (let* ((key-event (more-read-key-event))
+	   (keep-p (logical-key-event-p key-event :keep)))
+      (when keep-p (maybe-keep-random-typeout-window stream))
+      (random-typeout-cleanup stream)
+      (unless (or (logical-key-event-p key-event :do-all)
+		  (logical-key-event-p key-event :exit)
+		  (logical-key-event-p key-event :no)
+		  (logical-key-event-p key-event :yes)
+		  keep-p)
+	(unget-key-event key-event *editor-input*)))))
+
+;;; MORE-READ-KEY-EVENT -- Internal.
+;;;
+;;; This gets some input from the type of stream bound to *editor-input*.  Need
+;;; to loop over SERVE-EVENT since it returns on any kind of event (not
+;;; necessarily a key or button event).
+;;;
+;;; Currently this does not work for keyboard macro streams!
+;;; 
+(defun more-read-key-event ()
+  (clear-editor-input *editor-input*)
+  (let ((key-event (loop
+		     (let ((key-event (dq-event *editor-input*)))
+		       (when key-event (return key-event))
+		       (hemlock-ext:serve-event)))))
+    (when (abort-key-event-p key-event)
+      (beep)
+      (throw 'editor-top-level-catcher nil))
+    key-event))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/lisp-lib.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/lisp-lib.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/lisp-lib.lisp	(revision 13309)
@@ -0,0 +1,175 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains code to peruse the CMU Common Lisp library of hacks.
+;;;
+;;; Written by Blaine Burks.
+;;;
+
+(in-package :hemlock)
+
+
+(defmode "Lisp-Lib" :major-p t)
+
+;;; The library should be in *lisp-library-directory*
+
+(defvar *lisp-library-directory*  "/afs/cs.cmu.edu/project/clisp/library/")
+
+(defvar *selected-library-buffer* nil)
+
+
+
+;;;; Commands.
+
+(defcommand "Lisp Library" (p)
+  "Goto buffer in 'Lisp-Lib' mode, creating one if necessary."
+  "Goto buffer in 'Lisp-Lib' mode, creating one if necessary."
+  (declare (ignore p))
+  (when (not (and *selected-library-buffer*
+		  (member *selected-library-buffer* *buffer-list*)))
+    (when (getstring "Lisp Library" *buffer-names*)
+      (editor-error "There is already a buffer named \"Lisp Library\"."))
+    (setf *selected-library-buffer*
+	  (make-buffer "Lisp Library" :modes '("Lisp-Lib")))
+    (message "Groveling library ...")
+    (let ((lib-directory (directory *lisp-library-directory*))
+	  (lib-entries ()))
+      (with-output-to-mark (s (buffer-point *selected-library-buffer*))
+	(dolist (lib-spec lib-directory)
+	  (let* ((path-parts (pathname-directory lib-spec))
+		 (last (elt path-parts (1- (length path-parts))))
+		 (raw-pathname (merge-pathnames last lib-spec)))
+	    (when (and (directoryp lib-spec)
+		       (probe-file (merge-pathnames
+				    (make-pathname :type "catalog")
+				    raw-pathname)))
+	      (push raw-pathname lib-entries)
+	      (format s "~d~%" last)))))
+      (defhvar "Library Entries"
+	"Holds a list of library entries for the 'Lisp Library' buffer"
+	:buffer *selected-library-buffer*
+	:value (coerce (nreverse lib-entries) 'simple-vector))))
+  (setf (buffer-writable *selected-library-buffer*) nil)
+  (setf (buffer-modified *selected-library-buffer*) nil)
+  (change-to-buffer *selected-library-buffer*)
+  (buffer-start (current-point)))
+
+(defcommand "Describe Pointer Library Entry" (p)
+  "Finds the file that describes the lisp library entry indicated by the
+   pointer."
+  "Finds the file that describes the lisp library entry indicated by the
+   pointer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'library-entries :buffer (current-buffer))
+    (editor-error "Not in a Lisp Library buffer."))
+  (describe-library-entry (array-element-from-pointer-pos
+			   (value library-entries) "No entry on current line")))
+
+(defcommand "Describe Library Entry" (p)
+  "Find the file that describes the lisp library entry on the current line."
+  "Find the file that describes the lisp library entry on the current line."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'library-entries :buffer (current-buffer))
+    (editor-error "Not in a Lisp Library buffer."))
+  (describe-library-entry (array-element-from-mark (current-point)
+			   (value library-entries) "No entry on current line")))
+
+(defun describe-library-entry (pathname)
+  (let ((lisp-buf (current-buffer))
+	(buffer (view-file-command
+		 nil
+		 (merge-pathnames (make-pathname :type "catalog") pathname))))
+    (push #'(lambda (buffer)
+	      (declare (ignore buffer))
+	      (setf lisp-buf nil))
+	  (buffer-delete-hook lisp-buf))
+    (setf (variable-value 'view-return-function :buffer buffer)
+	  #'(lambda () (if lisp-buf
+			   (change-to-buffer lisp-buf)
+			   (lisp-library-command nil))))))
+
+(defcommand "Load Library Entry" (p)
+  "Loads the current library entry into the current slave."
+  "Loads the current library entry into the current slave."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'library-entries :buffer (current-buffer))
+    (editor-error "Not in a Lisp Library buffer."))
+  (string-eval (format nil "(load ~S)"
+		       (namestring (library-entry-load-file nil)))))
+
+(defcommand "Load Pointer Library Entry" (p)
+  "Loads the library entry indicated by the mouse into the current slave."
+  "Loads the library entry indicated by the mouse into the current slave."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'library-entries :buffer (current-buffer))
+    (editor-error "Not in a Lisp Library buffer."))
+  (string-eval (format nil "(load ~S)"
+		       (namestring (library-entry-load-file t)))))
+
+(defcommand "Editor Load Library Entry" (p)
+  "Loads the current library entry into the editor Lisp."
+  "Loads the current library entry into the editor Lisp."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'library-entries :buffer (current-buffer))
+    (editor-error "Not in a Lisp Library buffer."))
+  (in-lisp (load (library-entry-load-file nil))))
+
+(defcommand "Editor Load Pointer Library Entry" (p)
+  "Loads the library entry indicated by the mouse into the editor Lisp."
+  "Loads the library entry indicated by the mouse into the editor Lisp."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'library-entries :buffer (current-buffer))
+    (editor-error "Not in a Lisp Library buffer."))
+  (in-lisp (load (library-entry-load-file t))))
+
+;;; LIBRARY-ENTRY-LOAD-FILE uses the mouse's position or the current point,
+;;; depending on pointerp, to return a file that will load that library entry.
+;;;
+(defun library-entry-load-file (pointerp)
+  (let* ((lib-entries (value library-entries))
+	 (error-msg "No entry on current-line")
+	 (base-name (if pointerp
+			(array-element-from-pointer-pos lib-entries error-msg)
+			(array-element-from-mark (current-point) lib-entries
+						 error-msg)))
+	 (parts (pathname-directory base-name))
+	 (load-name (concatenate 'simple-string
+				 "load-" (elt parts (1- (length parts)))))
+	 (load-pathname (merge-pathnames load-name base-name))
+	 (file-to-load
+	  (or
+	   (probe-file (compile-file-pathname load-pathname))
+	   (probe-file (merge-pathnames (make-pathname :type "fasl")
+					load-pathname))
+	   (probe-file (merge-pathnames (make-pathname :type "lisp")
+					load-pathname))
+	   (probe-file (compile-file-pathname base-name))
+	   (probe-file (merge-pathnames (make-pathname :type "fasl")
+					base-name))
+	   (probe-file (merge-pathnames (make-pathname :type "lisp")
+					base-name)))))
+    (unless file-to-load (editor-error "You'll have to load it yourself."))
+    file-to-load))
+
+(defcommand "Exit Lisp Library" (p)
+  "Exit Lisp-Lib Mode, deleting the buffer when possible."
+  "Exit Lisp-Lib Mode, deleting the buffer when possible."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'library-entries :buffer (current-buffer))
+    (editor-error "Not in a Lisp Library buffer."))
+  (delete-buffer-if-possible (getstring "Lisp Library" *buffer-names*)))
+
+(defcommand "Lisp Library Help" (p)
+  "Show this help."
+  "Show this help."
+  (declare (ignore p))
+  (describe-mode-command nil "Lisp-Lib"))
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/lispbuf.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/lispbuf.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/lispbuf.lisp	(revision 13309)
@@ -0,0 +1,794 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Stuff to do a little lisp hacking in the editor's Lisp environment.
+;;;
+
+(in-package :hemlock)
+
+
+(defmacro in-lisp (&body body)
+  "Evaluates body inside HANDLE-LISP-ERRORS.  *package* is bound to the package
+   named by \"Current Package\" if it is non-nil."
+  (let ((name (gensym)) (package (gensym)))
+    `(handle-lisp-errors
+      (let* ((,name (value current-package))
+	     (,package (and ,name (find-package ,name))))
+	(progv (if ,package '(*package*)) (if ,package (list ,package))
+	  ,@body)))))
+
+
+(define-file-option "Package" (buffer value)
+  (defhvar "Current Package"
+    "The package used for evaluation of Lisp in this buffer."
+    :buffer buffer
+    :value
+    (let* ((eof (list nil))
+	   (thing (read-from-string value nil eof)))
+      (when (eq thing eof) (error "Bad package file option value."))
+      (cond
+       ((stringp thing)
+	thing)
+       ((symbolp thing)
+	(symbol-name thing))
+       ((characterp thing)
+	(string thing))
+       (t
+	(message
+	 "Ignoring \"package\" file option -- cannot convert to a string."))))
+    :hooks (list 'package-name-change-hook)))
+
+
+
+;;;; Eval Mode Interaction.
+
+(declaim (special * ** *** - + ++ +++ / // ///))
+
+
+(defun get-prompt ()
+  #+cmu (locally (declare (special ext:*prompt*))
+          (if (functionp ext:*prompt*)
+              (funcall ext:*prompt*)
+              ext:*prompt*))
+  #+sbcl (with-output-to-string (out)
+           (funcall sb-int:*repl-prompt-fun* out))
+  #-(or cmu sbcl) "* ")
+
+
+(defun show-prompt (&optional (stream *standard-output*))
+  #-sbcl (princ (get-prompt) stream)
+  #+sbcl (funcall sb-int:*repl-prompt-fun* stream))
+
+
+(defun setup-eval-mode (buffer)
+  (let ((point (buffer-point buffer)))
+    (setf (buffer-minor-mode buffer "Eval") t)
+    (setf (buffer-minor-mode buffer "Editor") t)
+    (setf (buffer-major-mode buffer) "Lisp")
+    (buffer-end point)
+    (defhvar "Current Package"
+      "This variable holds the name of the package currently used for Lisp
+       evaluation and compilation.  If it is Nil, the value of *Package* is used
+       instead."
+      :value nil
+      :buffer buffer)
+    (unless (hemlock-bound-p 'buffer-input-mark :buffer buffer)
+      (defhvar "Buffer Input Mark"
+	"Mark used for Eval Mode input."
+	:buffer buffer
+	:value (copy-mark point :right-inserting))
+      (defhvar "Eval Output Stream"
+	"Output stream used for Eval Mode output in this buffer."
+	:buffer buffer
+	:value (make-hemlock-output-stream point))
+      (defhvar "Interactive History"
+	"A ring of the regions input to an interactive mode (Eval or Typescript)."
+	:buffer buffer
+	:value (make-ring (value interactive-history-length)))
+      (defhvar "Interactive Pointer"
+	"Pointer into \"Interactive History\"."
+	:buffer buffer
+	:value 0)
+      (defhvar "Searching Interactive Pointer"
+	"Pointer into \"Interactive History\"."
+	:buffer buffer
+	:value 0))
+    (let ((*standard-output*
+	   (variable-value 'eval-output-stream :buffer buffer)))
+      (fresh-line)
+      (show-prompt))
+    (move-mark (variable-value 'buffer-input-mark :buffer buffer) point)))
+
+(defmode "Eval" :major-p nil :setup-function #'setup-eval-mode)
+
+(defun eval-mode-lisp-mode-hook (buffer on)
+  "Turn on Lisp mode when we go into Eval Mode."
+  (when on
+    (setf (buffer-major-mode buffer) "Lisp")))
+;;;
+(add-hook eval-mode-hook 'eval-mode-lisp-mode-hook)
+
+(defhvar "Editor Definition Info"
+  "When this is non-nil, the editor Lisp is used to determine definition
+   editing information; otherwise, the slave Lisp is used."
+  :value t
+  :mode "Eval")
+
+
+(defvar *selected-eval-buffer* nil)
+
+(defcommand "Select Eval Buffer" (p)
+  "Goto buffer in \"Eval\" mode, creating one if necessary."
+  "Goto buffer in \"Eval\" mode, creating one if necessary."
+  (declare (ignore p))
+  (unless *selected-eval-buffer*
+    (when (getstring "Eval" *buffer-names*)
+      (editor-error "There is already a buffer named \"Eval\"!"))
+    (setf *selected-eval-buffer*
+	  (make-buffer "Eval"
+		       :delete-hook
+		       (list #'(lambda (buf)
+				 (declare (ignore buf))
+				 (setf *selected-eval-buffer* nil)))))
+    (setf (buffer-minor-mode *selected-eval-buffer* "Eval") t))
+  (change-to-buffer *selected-eval-buffer*))
+
+
+(defvar lispbuf-eof '(nil))
+
+(defhvar "Unwedge Interactive Input Confirm"
+  "When set (the default), trying to confirm interactive input when the
+   point is not after the input mark causes Hemlock to ask the user if he
+   needs to be unwedged.  When not set, an editor error is signaled
+   informing the user that the point is before the input mark."
+  :value t)
+
+(defun unwedge-eval-buffer ()
+  (abort-eval-input-command nil))
+
+(defhvar "Unwedge Interactive Input Fun"
+  "Function to call when input is confirmed, but the point is not past the
+   input mark."
+  :value #'unwedge-eval-buffer
+  :mode "Eval")
+
+(defhvar "Unwedge Interactive Input String"
+  "String to add to \"Point not past input mark.  \" explaining what will
+   happen if the the user chooses to be unwedged."
+  :value "Prompt again at the end of the buffer? "
+  :mode "Eval")
+
+(defcommand "Confirm Eval Input" (p)
+  "Evaluate Eval Mode input between point and last prompt."
+  "Evaluate Eval Mode input between point and last prompt."
+  (declare (ignore p))
+  (let ((input-region (get-interactive-input)))
+    (when input-region
+      (let* ((output (value eval-output-stream))
+	     (*standard-output* output)
+	     (*error-output* output)
+	     (*trace-output* output))
+	(fresh-line)
+	(in-lisp
+	 ;; Copy the region to keep the output and input streams from interacting
+	 ;; since input-region is made of permanent marks into the buffer.
+	 (with-input-from-region (stream (copy-region input-region))
+	   (loop
+	     (let ((form (read stream nil lispbuf-eof)))
+	       (when (eq form lispbuf-eof)
+		 ;; Move the buffer's input mark to the end of the buffer.
+		 (move-mark (region-start input-region)
+			    (region-end input-region))
+		 (return))
+	       (setq +++ ++ ++ + + - - form)
+	       (let ((this-eval (multiple-value-list (eval form))))
+		 (fresh-line)
+		 (dolist (x this-eval) (prin1 x) (terpri))
+		 (show-prompt)
+		 (setq /// // // / / this-eval)
+		 (setq *** ** ** * * (car this-eval)))))))))))
+
+(defcommand "Abort Eval Input" (p)
+  "Move to the end of the buffer and prompt."
+  "Move to the end of the buffer and prompt."
+  (declare (ignore p))
+  (let ((point (current-point)))
+    (buffer-end point)
+    (insert-character point #\newline)
+    (insert-string point "Aborted.")
+    (insert-character point #\newline)
+    (insert-string point (get-prompt))
+    (move-mark (value buffer-input-mark) point)))
+
+
+
+
+;;;; General interactive commands used in eval and typescript buffers.
+
+(defun get-interactive-input ()
+  "Tries to return a region.  When the point is not past the input mark, and
+   the user has \"Unwedge Interactive Input Confirm\" set, the buffer is
+   optionally fixed up, and nil is returned.  Otherwise, an editor error is
+   signalled.  When a region is returned, the start is the current buffer's
+   input mark, and the end is the current point moved to the end of the buffer."
+  (let ((point (current-point))
+	(mark (value buffer-input-mark)))
+    (cond
+     ((mark>= point mark)
+      (buffer-end point)
+      (let* ((input-region (region mark point))
+	     (string (region-to-string input-region))
+	     (ring (value interactive-history)))
+	(when (and (or (zerop (ring-length ring))
+		       (string/= string (region-to-string (ring-ref ring 0))))
+		   (> (length string) (value minimum-interactive-input-length)))
+	  (ring-push (copy-region input-region) ring))
+	input-region))
+     ((value unwedge-interactive-input-confirm)
+      (beep)
+      (when (prompt-for-y-or-n
+	     :prompt (concatenate 'simple-string
+				  "Point not past input mark.  "
+				  (value unwedge-interactive-input-string))
+	     :must-exist t :default t :default-string "yes")
+	(funcall (value unwedge-interactive-input-fun))
+	(message "Unwedged."))
+      nil)
+     (t
+      (editor-error "Point not past input mark.")))))
+
+(defhvar "Interactive History Length"
+  "This is the length used for the history ring in interactive buffers.
+   It must be set before turning on the mode."
+  :value 10)
+
+(defhvar "Minimum Interactive Input Length"
+  "When the number of characters in an interactive buffer exceeds this value,
+   it is pushed onto the interactive history, otherwise it is lost forever."
+  :value 2)
+
+
+(defvar *previous-input-search-string* "ignore")
+
+(defvar *previous-input-search-pattern*
+  ;; Give it a bogus string since you can't give it the empty string.
+  (new-search-pattern :string-insensitive :forward "ignore"))
+
+(defun get-previous-input-search-pattern (string)
+  (if (string= *previous-input-search-string* string)
+      *previous-input-search-pattern*
+      (new-search-pattern :string-insensitive :forward 
+			  (setf *previous-input-search-string* string)
+			  *previous-input-search-pattern*)))
+
+(defcommand "Search Previous Interactive Input" (p)
+  "Search backward through the interactive history using the current input as
+   a search string.  Consecutive invocations repeat the previous search."
+  "Search backward through the interactive history using the current input as
+   a search string.  Consecutive invocations repeat the previous search."
+  (declare (ignore p))
+  (let* ((mark (value buffer-input-mark))
+	 (ring (value interactive-history))
+	 (point (current-point))
+	 (just-invoked (eq (last-command-type) :searching-interactive-input)))
+    (when (mark<= point mark)
+      (editor-error "Point not past input mark."))
+    (when (zerop (ring-length ring))
+      (editor-error "No previous input in this buffer."))
+    (unless just-invoked
+      (get-previous-input-search-pattern (region-to-string (region mark point))))
+    (let ((found-it (find-previous-input ring just-invoked)))
+      (unless found-it 
+	(editor-error "Couldn't find ~a." *previous-input-search-string*))
+      (delete-region (region mark point))
+      (insert-region point (ring-ref ring found-it))
+      (setf (value searching-interactive-pointer) found-it))
+  (setf (last-command-type) :searching-interactive-input)))
+
+(defun find-previous-input (ring againp)
+  (let ((ring-length (ring-length ring))
+	(base (if againp
+		  (+ (value searching-interactive-pointer) 1)
+		  0)))
+      (loop
+	(when (= base ring-length)
+	  (if againp
+	      (setf base 0)
+	      (return nil)))
+	(with-mark ((m (region-start (ring-ref ring base))))
+	  (when (find-pattern m *previous-input-search-pattern*)
+	    (return base)))
+	(incf base))))
+
+(defcommand "Previous Interactive Input" (p)
+  "Insert the previous input in an interactive mode (Eval or Typescript).
+   If repeated, keep rotating the history.  With prefix argument, rotate
+   that many times."
+  "Pop the *interactive-history* at the point."
+  (let* ((point (current-point))
+	 (mark (value buffer-input-mark))
+	 (ring (value interactive-history))
+	 (length (ring-length ring))
+	 (p (or p 1)))
+    (when (or (mark< point mark) (zerop length)) (editor-error))
+    (cond
+     ((eq (last-command-type) :interactive-history)
+      (let ((base (mod (+ (value interactive-pointer) p) length)))
+	(delete-region (region mark point))
+	(insert-region point (ring-ref ring base))
+	(setf (value interactive-pointer) base)))
+     (t
+      (let ((base (mod (if (minusp p) p (1- p)) length))
+	    (region (delete-and-save-region (region mark point))))
+	(insert-region point (ring-ref ring base))
+	(when (mark/= (region-start region) (region-end region))
+	  (ring-push region ring)
+	  (incf base))
+	(setf (value interactive-pointer) base)))))
+  (setf (last-command-type) :interactive-history))
+
+(defcommand "Next Interactive Input" (p)
+  "Rotate the interactive history backwards.  The region is left around the
+   inserted text.  With prefix argument, rotate that many times."
+  "Call previous-interactive-input-command with negated arg."
+  (previous-interactive-input-command (- (or p 1))))
+
+(defcommand "Kill Interactive Input" (p)
+  "Kill any input to an interactive mode (Eval or Typescript)."
+  "Kill any input to an interactive mode (Eval or Typescript)."
+  (declare (ignore p))
+  (let ((point (buffer-point (current-buffer)))
+	(mark (value buffer-input-mark)))
+    (when (mark< point mark) (editor-error))
+    (kill-region (region mark point) :kill-backward)))
+
+(defcommand "Interactive Beginning of Line" (p)
+  "If on line with current prompt, go to after it, otherwise do what
+  \"Beginning of Line\" always does."
+  "Go to after prompt when on prompt line."
+  (let ((mark (value buffer-input-mark))
+	(point (current-point)))
+    (if (and (same-line-p point mark) (or (not p) (= p 1)))
+	(move-mark point mark)
+	(beginning-of-line-command p))))
+
+(defcommand "Reenter Interactive Input" (p)
+  "Copies the form to the left of point to be after the interactive buffer's
+   input mark.  When the current region is active, it is copied instead."
+  "Copies the form to the left of point to be after the interactive buffer's
+   input mark.  When the current region is active, it is copied instead."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'buffer-input-mark)
+    (editor-error "Not in an interactive buffer."))
+  (let ((point (current-point)))
+    (let ((region (if (region-active-p)
+		      ;; Copy this, so moving point doesn't affect the region.
+		      (copy-region (current-region))
+		      (with-mark ((start point)
+				  (end point))
+			(pre-command-parse-check start)
+			(unless (form-offset start -1)
+			  (editor-error "Not after complete form."))
+			(region (copy-mark start) (copy-mark end))))))
+      (buffer-end point)
+      (push-buffer-mark (copy-mark point))
+      (insert-region point region)
+      (setf (last-command-type) :ephemerally-active))))
+
+
+
+
+;;; Other stuff.
+
+(defmode "Editor")
+
+(defcommand "Editor Mode" (p)
+  "Turn on \"Editor\" mode in the current buffer.  If it is already on, turn it
+  off.  When in editor mode, most lisp compilation and evaluation commands
+  manipulate the editor process instead of the current eval server."
+  "Toggle \"Editor\" mode in the current buffer."
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Editor")
+	(not (buffer-minor-mode (current-buffer) "Editor"))))
+
+(define-file-option "Editor" (buffer value)
+  (declare (ignore value))
+  (setf (buffer-minor-mode buffer "Editor") t))
+
+(defhvar "Editor Definition Info"
+  "When this is non-nil, the editor Lisp is used to determine definition
+   editing information; otherwise, the slave Lisp is used."
+  :value t
+  :mode "Editor")
+
+(defcommand "Editor Compile Defun" (p)
+  "Compiles the current or next top-level form in the editor Lisp.
+   First the form is evaluated, then the result of this evaluation
+   is passed to compile.  If the current region is active, this
+   compiles the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (region-active-p)
+      (editor-compile-region (current-region))
+      (editor-compile-region (defun-region (current-point)) t)))
+
+(defcommand "Editor Compile Region" (p)
+  "Compiles lisp forms between the point and the mark in the editor Lisp."
+  "Compiles lisp forms between the point and the mark in the editor Lisp."
+  (declare (ignore p))
+  (editor-compile-region (current-region)))
+
+(defun defun-region (mark)
+  "This returns a region around the current or next defun with respect to mark.
+   Mark is not used to form the region.  If there is no appropriate top level
+   form, this signals an editor-error.  This calls PRE-COMMAND-PARSE-CHECK."
+  (with-mark ((start mark)
+	      (end mark))
+    (pre-command-parse-check start)
+    (cond ((not (mark-top-level-form start end))
+	   (editor-error "No current or next top level form."))
+	  (t (region start end)))))
+
+(defun editor-compile-region (region &optional quiet)
+  (unless quiet (message "Compiling region ..."))
+  (in-lisp
+   (with-input-from-region (stream region)
+     (with-pop-up-display (*error-output* :height 19)
+       ;; JDz: We don't record source locations and what not, but this
+       ;; is portable.  CMUCL specific implementation removed because
+       ;; it does not work on HEMLOCK-REGION-STREAM (but it can be
+       ;; added back later if CMUCL starts using user-extensible
+       ;; streams internally.)
+       (funcall (compile nil `(lambda ()
+                                ,@(loop for form = (read stream nil stream)
+                                        until (eq form stream)
+                                        collect form))))))))
+
+
+(defcommand "Editor Evaluate Defun" (p)
+  "Evaluates the current or next top-level form in the editor Lisp.
+   If the current region is active, this evaluates the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (region-active-p)
+      (editor-evaluate-region-command nil)
+      (with-input-from-region (stream (defun-region (current-point)))
+	(clear-echo-area)
+	(in-lisp
+	 (message "Editor Evaluation returned ~S"
+		  (eval (read stream)))))))
+
+(defcommand "Editor Evaluate Region" (p)
+  "Evaluates lisp forms between the point and the mark in the editor Lisp."
+  "Evaluates lisp forms between the point and the mark in the editor Lisp."
+  (declare (ignore p))
+  (with-input-from-region (stream (current-region))
+    (clear-echo-area)
+    (write-string "Evaluating region in the editor ..." *echo-area-stream*)
+    (finish-output *echo-area-stream*)
+    (in-lisp
+     (do ((object (read stream nil lispbuf-eof) 
+		  (read stream nil lispbuf-eof)))
+	 ((eq object lispbuf-eof))
+       (eval object)))
+    (message "Evaluation complete.")))
+           
+(defcommand "Editor Re-evaluate Defvar" (p)
+  "Evaluate the current or next top-level form if it is a DEFVAR.  Treat the
+   form as if the variable is not bound.  This occurs in the editor Lisp."
+  "Evaluate the current or next top-level form if it is a DEFVAR.  Treat the
+   form as if the variable is not bound.  This occurs in the editor Lisp."
+  (declare (ignore p))
+  (with-input-from-region (stream (defun-region (current-point)))
+    (clear-echo-area)
+    (in-lisp
+     (let ((form (read stream)))
+       (unless (eq (car form) 'defvar) (editor-error "Not a DEFVAR."))
+       (makunbound (cadr form))
+       (message "Evaluation returned ~S" (eval form))))))
+
+(defcommand "Editor Macroexpand Expression" (p)
+  "Show the macroexpansion of the current expression in the null environment.
+   With an argument, use MACROEXPAND instead of MACROEXPAND-1."
+  "Show the macroexpansion of the current expression in the null environment.
+   With an argument, use MACROEXPAND instead of MACROEXPAND-1."
+  (let ((point (buffer-point (current-buffer))))
+    (with-mark ((start point))
+      (pre-command-parse-check start)
+      (with-mark ((end start))
+        (unless (form-offset end 1) (editor-error))
+	(in-lisp
+	 (with-pop-up-display (rts)
+	   (write-string (with-input-from-region (s (region start end))
+			   (prin1-to-string (funcall (if p
+							 'macroexpand
+							 'macroexpand-1)
+						     (read s))))
+			 rts)))))))
+
+(defcommand "Editor Evaluate Expression" (p)
+  "Prompt for an expression to evaluate in the editor Lisp."
+  "Prompt for an expression to evaluate in the editor Lisp."
+  (declare (ignore p))
+  (in-lisp
+   (multiple-value-call #'message "=> ~@{~#[~;~S~:;~S, ~]~}"
+     (eval (prompt-for-expression
+	    :prompt "Editor Eval: "
+	    :help "Expression to evaluate")))))
+
+(defcommand "Editor Evaluate Buffer" (p)
+  "Evaluates the text in the current buffer in the editor Lisp."
+  "Evaluates the text in the current buffer redirecting *Standard-Output* to
+   the echo area.  This occurs in the editor Lisp.  The prefix argument is
+   ignored."
+  (declare (ignore p))
+  (clear-echo-area)
+  (write-string "Evaluating buffer in the editor ..." *echo-area-stream*)
+  (finish-output *echo-area-stream*)
+  (with-input-from-region (stream (buffer-region (current-buffer)))
+    (let ((*standard-output* *echo-area-stream*))
+      (in-lisp
+       (do ((object (read stream nil lispbuf-eof) 
+		    (read stream nil lispbuf-eof)))
+	   ((eq object lispbuf-eof))
+	 (eval object))))
+    (message "Evaluation complete.")))
+
+
+
+;;; With-Output-To-Window  --  Internal
+;;;
+;;;
+(defmacro with-output-to-window ((stream name) &body forms)
+  "With-Output-To-Window (Stream Name) {Form}*
+  Bind Stream to a stream that writes into the buffer named Name a la
+  With-Output-To-Mark.  The buffer is created if it does not exist already
+  and a window is created to display the buffer if it is not displayed.
+  For the duration of the evaluation this window is made the current window."
+  (let ((nam (gensym)) (buffer (gensym)) (point (gensym)) 
+	(window (gensym)) (old-window (gensym)))
+    `(let* ((,nam ,name)
+	    (,buffer (or (getstring ,nam *buffer-names*) (make-buffer ,nam)))
+	    (,point (buffer-end (buffer-point ,buffer)))
+	    (,window (or (car (buffer-windows ,buffer)) (make-window ,point)))
+	    (,old-window (current-window)))
+       (unwind-protect
+	 (progn (setf (current-window) ,window)
+		(buffer-end ,point)
+		(with-output-to-mark (,stream ,point) ,@forms))
+	 (setf (current-window) ,old-window)))))
+
+(defcommand "Editor Compile File" (p)
+  "Prompts for file to compile in the editor Lisp.  Does not compare source
+   and binary write dates.  Does not check any buffer for that file for
+   whether the buffer needs to be saved."
+  "Prompts for file to compile."
+  (declare (ignore p))
+  (let ((pn (prompt-for-file :default
+			     (buffer-default-pathname (current-buffer))
+			     :prompt "File to compile: ")))
+    (with-output-to-window (*error-output* "Compiler Warnings")
+      (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil)))))
+
+
+(defun older-or-non-existent-fasl-p (pathname &optional definitely)
+  (let ((obj-pn (probe-file (compile-file-pathname pathname))))
+    (or definitely
+	(not obj-pn)
+	(< (file-write-date obj-pn) (file-write-date pathname)))))
+
+
+(defcommand "Editor Compile Buffer File" (p)
+  "Compile the file in the current buffer in the editor Lisp if its associated
+   binary file (of type .fasl) is older than the source or doesn't exist.  When
+   the binary file is up to date, the user is asked if the source should be
+   compiled anyway.  When the prefix argument is supplied, compile the file
+   without checking the binary file.  When \"Compile Buffer File Confirm\" is
+   set, this command will ask for confirmation when it otherwise would not."
+  "Compile the file in the current buffer in the editor Lisp if the fasl file
+   isn't up to date.  When p, always do it."
+  (let* ((buf (current-buffer))
+	 (pn (buffer-pathname buf)))
+    (unless pn (editor-error "Buffer has no associated pathname."))
+    (cond ((buffer-modified buf)
+	   (when (or (not (value compile-buffer-file-confirm))
+		     (prompt-for-y-or-n
+		      :default t :default-string "Y"
+		      :prompt (list "Save and compile file ~A? "
+				    (namestring pn))))
+	     (write-buffer-file buf pn)
+	     (with-output-to-window (*error-output* "Compiler Warnings")
+	       (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil)))))
+	  ((older-or-non-existent-fasl-p pn p)
+	   (when (or (not (value compile-buffer-file-confirm))
+		     (prompt-for-y-or-n
+		      :default t :default-string "Y"
+		      :prompt (list "Compile file ~A? " (namestring pn))))
+	     (with-output-to-window (*error-output* "Compiler Warnings")
+	       (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil)))))
+	  (t (when (or p
+		       (prompt-for-y-or-n
+			:default t :default-string "Y"
+			:prompt
+			"Fasl file up to date, compile source anyway? "))
+	       (with-output-to-window (*error-output* "Compiler Warnings")
+		 (in-lisp (compile-file (namestring pn) #+cmu :error-file #+cmu nil))))))))
+
+(defcommand "Editor Compile Group" (p)
+  "Compile each file in the current group which needs it in the editor Lisp.
+   If a file has type LISP and there is a curresponding file with type
+   FASL which has been written less recently (or it doesn't exit), then
+   the file is compiled, with error output directed to the \"Compiler Warnings\"
+   buffer.  If a prefix argument is provided, then all the files are compiled.
+   All modified files are saved beforehand."
+  "Do a Compile-File in each file in the current group that seems to need it
+   in the editor Lisp."
+  (save-all-files-command ())
+  (unless *active-file-group* (editor-error "No active file group."))
+  (dolist (file *active-file-group*)
+    (when (string-equal (pathname-type file) "lisp")
+      (let ((tn (probe-file file)))
+	(cond ((not tn)
+	       (message "File ~A not found." (namestring file)))
+	      ((older-or-non-existent-fasl-p tn p)
+	       (with-output-to-window (*error-output* "Compiler Warnings")
+		 (in-lisp (compile-file (namestring tn) #+cmu :error-file #+cmu nil)))))))))
+
+(defcommand "List Compile Group" (p)
+  "List any files that would be compiled by \"Compile Group\".  All Modified
+   files are saved before checking to generate a consistent list."
+  "Do a Compile-File in each file in the current group that seems to need it."
+  (declare (ignore p))
+  (save-all-files-command ())
+  (unless *active-file-group* (editor-error "No active file group."))
+  (with-pop-up-display (s)
+    (write-line "\"Compile Group\" would compile the following files:" s)
+    (force-output s)
+    (dolist (file *active-file-group*)
+      (when (string-equal (pathname-type file) "lisp")
+	(let ((tn (probe-file file)))
+	  (cond ((not tn)
+		 (format s "File ~A not found.~%" (namestring file)))
+		((older-or-non-existent-fasl-p tn)
+		 (write-line (namestring tn) s)))
+	  (force-output s))))))
+
+(defhvar "Load Pathname Defaults"
+  "The default pathname used by the load command.")
+
+(defcommand "Editor Load File" (p)
+  "Prompt for a file to load into Editor Lisp."
+  "Prompt for a file to load into the Editor Lisp."
+  (declare (ignore p))
+  (let ((name (truename (prompt-for-file
+			 :default
+			 (or (value load-pathname-defaults)
+			     (buffer-default-pathname (current-buffer)))
+			 :prompt "Editor file to load: "
+			 :help "The name of the file to load"))))
+    (setv load-pathname-defaults name)
+    (in-lisp (load name))))
+
+
+
+
+;;;; Lisp documentation stuff.
+
+;;; FUNCTION-TO-DESCRIBE is used in "Editor Describe Function Call" and
+;;; "Describe Function Call".
+;;;
+(defmacro function-to-describe (var error-name)
+  `(cond ((not (symbolp ,var))
+	  (,error-name "~S is not a symbol." ,var))
+	 ((macro-function ,var))
+	 ((fboundp ,var)
+	  (if (listp (symbol-function ,var))
+	      ,var
+	      (symbol-function ,var)))
+	 (t
+	  (,error-name "~S is not a function." ,var))))
+
+(defcommand "Editor Describe Function Call" (p)
+  "Describe the most recently typed function name in the editor Lisp."
+  "Describe the most recently typed function name in the editor Lisp."
+  (declare (ignore p))
+  (with-mark ((mark1 (current-point))
+	      (mark2 (current-point)))
+    (pre-command-parse-check mark1)
+    (unless (backward-up-list mark1) (editor-error))
+    (form-offset (move-mark mark2 (mark-after mark1)) 1)
+    (with-input-from-region (s (region mark1 mark2))
+      (in-lisp
+       (let* ((sym (read s))
+	      (fun (function-to-describe sym editor-error)))
+	 (with-pop-up-display (*standard-output*)
+	   (editor-describe-function fun sym)))))))
+
+
+(defcommand "Editor Describe Symbol" (p)
+  "Describe the previous s-expression if it is a symbol in the editor Lisp."
+  "Describe the previous s-expression if it is a symbol in the editor Lisp."
+  (declare (ignore p))
+  (with-mark ((mark1 (current-point))
+	      (mark2 (current-point)))
+    (mark-symbol mark1 mark2)
+    (with-input-from-region (s (region mark1 mark2))
+      (in-lisp
+       (let ((thing (read s)))
+	 (if (symbolp thing)
+	     (with-pop-up-display (*standard-output*)
+	       (describe thing))
+	     (if (and (consp thing)
+		      (or (eq (car thing) 'quote)
+			  (eq (car thing) 'function))
+		      (symbolp (cadr thing)))
+		 (with-pop-up-display (*standard-output*)
+		   (describe (cadr thing)))
+		 (editor-error "~S is not a symbol, or 'symbol, or #'symbol."
+			       thing))))))))
+
+;;; MARK-SYMBOL moves mark1 and mark2 around the previous or current symbol.
+;;; However, if the marks are immediately before the first constituent char
+;;; of the symbol name, we use the next symbol since the marks probably
+;;; correspond to the point, and Hemlock's cursor display makes it look like
+;;; the point is within the symbol name.  This also tries to ignore :prefix
+;;; characters such as quotes, commas, etc.
+;;;
+(defun mark-symbol (mark1 mark2)
+  (pre-command-parse-check mark1)
+  (with-mark ((tmark1 mark1)
+	      (tmark2 mark1))
+    (cond ((and (form-offset tmark1 1)
+		(form-offset (move-mark tmark2 tmark1) -1)
+		(or (mark= mark1 tmark2)
+		    (and (find-attribute tmark2 :lisp-syntax
+					 #'(lambda (x) (not (eq x :prefix))))
+			 (mark= mark1 tmark2))))
+	   (form-offset mark2 1))
+	  (t
+	   (form-offset mark1 -1)
+	   (find-attribute mark1 :lisp-syntax
+			   #'(lambda (x) (not (eq x :prefix))))
+	   (form-offset (move-mark mark2 mark1) 1)))))
+
+
+(defcommand "Editor Describe" (p)
+  "Call Describe on a Lisp object.
+  Prompt for an expression which is evaluated to yield the object."
+  "Prompt for an object to describe."
+  (declare (ignore p))
+  (in-lisp
+   (let* ((exp (prompt-for-expression
+		:prompt "Object: "
+		:help "Expression to evaluate to get object to describe."))
+	  (obj (eval exp)))
+     (with-pop-up-display (*standard-output*)
+       (describe obj)))))
+
+
+(defcommand "Filter Region" (p)
+  "Apply a Lisp function to each line of the region.
+  An expression is prompted for which should evaluate to a Lisp function
+  from a string to a string.  The function must neither modify its argument
+  nor modify the return value after it is returned."
+  "Call prompt for a function, then call Filter-Region with it and the region."
+  (declare (ignore p))
+  (let* ((exp (prompt-for-expression
+	       :prompt "Function: "
+	       :help "Expression to evaluate to get function to use as filter."))
+	 (fun (in-lisp (eval exp)))
+	 (region (current-region)))
+    (let* ((start (copy-mark (region-start region) :left-inserting))
+	   (end (copy-mark (region-end region) :left-inserting))
+	   (region (region start end))
+	   (undo-region (copy-region region)))
+      (filter-region fun region)
+      (make-region-undo :twiddle "Filter Region" region undo-region))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/lispeval.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/lispeval.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/lispeval.lisp	(revision 13309)
@@ -0,0 +1,978 @@
+;;; -*- Package: Hemlock; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains code for sending requests to eval servers and the
+;;; commands based on that code.
+;;;
+;;; Written by William Lott and Rob MacLachlan.
+;;;
+
+(in-package :hemlock)
+
+
+;;; The note structure holds everything we need to know about an
+;;; operation.  Not all operations use all the available fields.
+;;;
+(defstruct (note (:print-function %print-note))
+  (state :unsent)	      ; :unsent, :pending, :running, :aborted or :dead.
+  server		      ; Server-Info for the server this op is on.
+  context		      ; Short string describing what this op is doing.
+  kind			      ; Either :eval, :compile, or :compile-file
+  buffer		      ; Buffer source came from.
+  region		      ; Region of request
+  package		      ; Package or NIL if none
+  text			      ; string containing request
+  input-file		      ; File to compile or where stuff was found
+  net-input-file	      ; Net version of above.
+  output-file		      ; Temporary output file for compiler fasl code.
+  net-output-file	      ; Net version of above
+  output-date		      ; Temp-file is created before calling compiler,
+			      ;  and this is its write date.
+  lap-file		      ; The lap file for compiles
+  error-file		      ; The file to dump errors into
+  load			      ; Load compiled file or not?
+  (errors 0)		      ; Count of compiler errors.
+  (warnings 0)		      ; Count of compiler warnings.
+  (notes 0))		      ; Count of compiler notes.
+;;;
+(defun %print-note (note stream d)
+  (declare (ignore d))
+  (format stream "#<Eval-Server-Note for ~A [~A]>"
+	  (note-context note)
+	  (note-state note)))
+
+
+
+
+;;;; Note support routines.
+
+;;; QUEUE-NOTE -- Internal.
+;;;
+;;; This queues note for server.  SERVER-INFO-NOTES keeps notes in stack order,
+;;; not queue order.  We also link the note to the server and try to send it
+;;; to the server.  If we didn't send this note, we tell the user the server
+;;; is busy and that we're queuing his note to be sent later.
+;;;
+(defun queue-note (note server)
+  (push note (server-info-notes server))
+  (setf (note-server note) server)
+  (maybe-send-next-note server)
+  (when (eq (note-state note) :unsent)
+    (message "Server ~A busy, ~A queued."
+	     (server-info-name server)
+	     (note-context note))))
+
+;;; MAYBE-SEND-NEXT-NOTE -- Internal.
+;;;
+;;; Loop over all notes in server.  If we see any :pending or :running, then
+;;; punt since we can't send one.  Otherwise, by the end of the list, we may
+;;; have found an :unsent one, and if we did, next will be the last :unsent
+;;; note.  Remember, SERVER-INFO-NOTES is kept in stack order not queue order.
+;;;
+(defun maybe-send-next-note (server)
+  (let ((busy nil)
+	(next nil))
+    (dolist (note (server-info-notes server))
+      (ecase (note-state note)
+	((:pending :running)
+	 (setf busy t)
+	 (return))
+	(:unsent
+	 (setf next note))
+	(:aborted :dead)))
+    (when (and (not busy) next)
+      (send-note next))))
+
+(defun send-note (note)
+  (let* ((remote (hemlock.wire:make-remote-object note))
+	 (server (note-server note))
+	 (ts (server-info-slave-info server))
+	 (bg (server-info-background-info server))
+	 (wire (server-info-wire server)))
+    (setf (note-state note) :pending)
+    (message "Sending ~A." (note-context note))
+    (case (note-kind note)
+      (:eval
+       (hemlock.wire:remote wire
+	 (server-eval-text remote
+			   (note-package note)
+			   (note-text note)
+			   (and ts (ts-data-stream ts)))))
+      (:compile
+       (hemlock.wire:remote wire
+	 (server-compile-text remote
+			      (note-package note)
+			      (note-text note)
+			      (note-input-file note)
+			      (and ts (ts-data-stream ts))
+			      (and bg (ts-data-stream bg)))))
+      (:compile-file
+       (macrolet ((frob (x)
+		    `(if (pathnamep ,x)
+		       (namestring ,x)
+		       ,x)))
+	 (hemlock.wire:remote wire
+	   (server-compile-file remote
+				(note-package note)
+				(frob (or (note-net-input-file note)
+					  (note-input-file note)))
+				(frob (or (note-net-output-file note)
+					  (note-output-file note)))
+				(frob (note-error-file note))
+				(frob (note-lap-file note))
+				(note-load note)
+				(and ts (ts-data-stream ts))
+				(and bg (ts-data-stream bg))))))
+      (t
+       (error "Unknown note kind ~S" (note-kind note))))
+    (hemlock.wire:wire-force-output wire)))
+
+
+
+;;;; Server Callbacks.
+
+(defun operation-started (note)
+  (let ((note (hemlock.wire:remote-object-value note)))
+    (setf (note-state note) :running)
+    (message "The ~A started." (note-context note)))
+  (values))
+
+(defun eval-form-error (message)
+  (editor-error message))
+
+(defun lisp-error (note start end msg)
+  (declare (ignore start end))
+  (let ((note (hemlock.wire:remote-object-value note)))
+    (loud-message "During ~A: ~A"
+		  (note-context note)
+		  msg))
+  (values))
+
+(defun compiler-error (note start end function severity)
+  (let* ((note (hemlock.wire:remote-object-value note))
+	 (server (note-server note))
+	 (line (mark-line
+		(buffer-end-mark
+		 (server-info-background-buffer server))))
+	 (message (format nil "~:(~A~) ~@[in ~A ~]during ~A."
+			  severity
+			  function
+			  (note-context note)))
+	 (error (make-error-info :buffer (note-buffer note)
+				 :message message
+				 :line line)))
+    (message "~A" message)
+    (case severity
+      (:error (incf (note-errors note)))
+      (:warning (incf (note-warnings note)))
+      (:note (incf (note-notes note))))
+    (let ((region (case (note-kind note)
+		    (:compile
+		     (note-region note))
+		    (:compile-file
+		     (let ((buff (note-buffer note)))
+		       (and buff (buffer-region buff))))
+		    (t
+		     (error "Compiler error in ~S?" note)))))
+      (when region
+	(let* ((region-end (region-end region))
+	       (m1 (copy-mark (region-start region) :left-inserting))
+	       (m2 (copy-mark m1 :left-inserting)))
+	  (when start
+	    (character-offset m1 start)
+	    (when (mark> m1 region-end)
+	      (move-mark m1 region-end)))
+	  (unless (and end (character-offset m2 end))
+	    (move-mark m2 region-end))
+	  
+	  (setf (error-info-region error)
+		(region m1 m2)))))
+
+    (vector-push-extend error (server-info-errors server)))
+
+  (values))
+
+(defun eval-text-result (note start end values)
+  (declare (ignore note start end))
+  (message "=> ~{~#[~;~A~:;~A, ~]~}" values)
+  (values))
+
+(defun operation-completed (note abortp)
+  (let* ((note (hemlock.wire:remote-object-value note))
+	 (server (note-server note))
+	 (file (note-output-file note)))
+    (hemlock.wire:forget-remote-translation note)
+    (setf (note-state note) :dead)
+    (setf (server-info-notes server)
+	  (delete note (server-info-notes server)
+		  :test #'eq))
+    (setf (note-server note) nil)
+
+    (if abortp
+	(loud-message "The ~A aborted." (note-context note))
+	(let ((errors (note-errors note))
+	      (warnings (note-warnings note))
+	      (notes (note-notes note)))
+	  (message "The ~A complete.~
+		    ~@[ ~D error~:P~]~@[ ~D warning~:P~]~@[ ~D note~:P~]"
+		   (note-context note)
+		   (and (plusp errors) errors)
+		   (and (plusp warnings) warnings)
+		   (and (plusp notes) notes))))
+
+    (let ((region (note-region note)))
+      (when (regionp region)
+	(delete-mark (region-start region))
+	(delete-mark (region-end region))
+	(setf (note-region note) nil)))
+
+    (when (and (eq (note-kind note)
+		   :compile-file)
+	       (not (eq file t))
+	       file)
+      (if (> (file-write-date file)
+	     (note-output-date note))
+	  (let ((new-name (make-pathname :type "fasl"
+					 :defaults (note-input-file note))))
+	    (rename-file file new-name)
+	    #+NILGB
+            (unix:unix-chmod (namestring new-name) #o644))
+	  (delete-file file)))
+    (maybe-send-next-note server))
+  (values))
+
+
+
+;;;; Stuff to send noise to the server.
+
+;;; EVAL-FORM-IN-SERVER -- Public.
+;;;
+(defun eval-form-in-server (server-info form
+			    &optional (package (value current-package)))
+  "This evals form, a simple-string, in the server for server-info.  Package
+   is the name of the package in which the server reads form, and it defaults
+   to the value of \"Current Package\".  If package is nil, then the slave uses
+   the value of *package*.  If server is busy with other requests, this signals
+   an editor-error to prevent commands using this from hanging.  If the server
+   dies while evaluating form, then this signals an editor-error.  This returns
+   a list of strings which are the printed representation of all the values
+   returned by form in the server."
+  (declare (simple-string form))
+  (when (server-info-notes server-info)
+    (editor-error "Server ~S is currently busy.  See \"List Operations\"."
+		  (server-info-name server-info)))
+  (multiple-value-bind (values error)
+		       (hemlock.wire:remote-value (server-info-wire server-info)
+			 (server-eval-form package form))
+    (when error
+      (editor-error "The server died before finishing"))
+    values))
+
+;;; EVAL-FORM-IN-SERVER-1 -- Public.
+;;;
+;;; We use VALUES to squelch the second value of READ-FROM-STRING.
+;;;
+(defun eval-form-in-server-1 (server-info form
+			      &optional (package (value current-package)))
+  "This calls EVAL-FORM-IN-SERVER and returns the result of READ'ing from
+   the first string EVAL-FORM-IN-SERVER returns."
+  (values (read-from-string
+	   (car (eval-form-in-server server-info form package)))))
+
+(defun string-eval (string
+		    &key
+		    (server (get-current-eval-server))
+		    (package (value current-package))
+		    (context (format nil
+				     "evaluation of ~S"
+				     string)))
+  "Queues the evaluation of string on an eval server.  String is a simple
+   string.  If package is not supplied, the string is eval'ed in the slave's
+   current package."
+  (declare (simple-string string))
+  (queue-note (make-note :kind :eval
+			 :context context
+			 :package package
+			 :text string)
+	      server)
+  (values))
+
+(defun region-eval (region
+		    &key
+		    (server (get-current-eval-server))
+		    (package (value current-package))
+		    (context (region-context region "evaluation")))
+  "Queues the evaluation of a region of text on an eval server.  If package
+   is not supplied, the string is eval'ed in the slave's current package."
+  (let ((region (region (copy-mark (region-start region) :left-inserting)
+			(copy-mark (region-end region) :left-inserting))))
+    (queue-note (make-note :kind :eval
+			   :context context
+			   :region region
+			   :package package
+			   :text (region-to-string region))
+		server))
+  (values))
+
+(defun region-compile (region
+		       &key
+		       (server (get-current-eval-server))
+		       (package (value current-package)))
+  "Queues a compilation on an eval server.  If package is not supplied, the
+   string is eval'ed in the slave's current package."
+  (let* ((region (region (copy-mark (region-start region) :left-inserting)
+			 (copy-mark (region-end region) :left-inserting)))
+	 (buf (line-buffer (mark-line (region-start region))))
+	 (pn (and buf (buffer-pathname buf)))
+	 (defined-from (if pn (namestring pn) "unknown")))
+    (queue-note (make-note :kind :compile
+			   :context (region-context region "compilation")
+			   :buffer (and region
+					(region-start region)
+					(mark-line (region-start region))
+					(line-buffer (mark-line
+						      (region-start region))))
+			   :region region
+			   :package package
+			   :text (region-to-string region)
+			   :input-file defined-from)
+		server))
+  (values))
+
+
+
+
+;;;; File compiling noise.
+
+(defhvar "Remote Compile File"
+  "When set (the default), this causes slave file compilations to assume the
+   compilation is occurring on a remote machine.  This means the source file
+   must be world readable.  Unsetting this, causes no file accesses to go
+   through the super root."
+  :value nil)
+
+;;; FILE-COMPILE compiles files in a client Lisp.  Because of Unix file
+;;; protection, one cannot write files over the net unless they are publicly
+;;; writeable.  To get around this, we create a temporary file that is
+;;; publicly writeable for compiler output.  This file is renamed to an
+;;; ordinary output name if the compiler wrote anything to it, or deleted
+;;; otherwise.  No temporary file is created when output-file is not t.
+;;;
+
+(defun file-compile (file
+		     &key
+		     buffer
+		     (output-file t)
+		     error-file
+		     lap-file
+		     load
+		     (server (get-current-compile-server))
+		     (package (value current-package)))
+  "Compiles file in a client Lisp.  When output-file is t, a temporary
+   output file is used that is publicly writeable in case the client is on
+   another machine.  This file is renamed or deleted after compilation.
+   Setting \"Remote Compile File\" to nil, inhibits this.  If package is not
+   supplied, the string is eval'ed in the slave's current package."
+
+  (let* ((file (truename file)) ; in case of search-list in pathname.
+	 (namestring (namestring file))
+	 (note (make-note
+		:kind :compile-file
+		:context (format nil "compilation of ~A" namestring)
+		:buffer buffer
+		:region nil
+		:package package
+		:input-file file
+		:output-file output-file
+		:error-file error-file
+		:lap-file lap-file
+		:load load)))
+
+    (when (and (value remote-compile-file)
+	       (eq output-file t))
+      (multiple-value-bind (net-infile ofile net-ofile date)
+			   (file-compile-temp-file file)
+	(setf (note-net-input-file note) net-infile)
+	(setf (note-output-file note) ofile)
+	(setf (note-net-output-file note) net-ofile)
+	(setf (note-output-date note) date)))
+
+    (clear-server-errors server
+			 #'(lambda (error)
+			     (eq (error-info-buffer error)
+				 buffer)))
+    (queue-note note server)))
+
+;;; FILE-COMPILE-TEMP-FILE creates a a temporary file that is publicly
+;;; writable in the directory file is in and with a .fasl type.  Four values
+;;; are returned -- a pathname suitable for referencing file remotely, the
+;;; pathname of the temporary file created, a pathname suitable for referencing
+;;; the temporary file remotely, and the write date of the temporary file.
+;;; 
+
+#+NILGB
+(defun file-compile-temp-file (file)
+  (let ((ofile (loop (let* ((sym (gensym))
+			    (f (merge-pathnames
+				(format nil "compile-file-~A.fasl" sym)
+				file)))
+		       (unless (probe-file f) (return f))))))
+    (multiple-value-bind (fd err)
+			 (unix:unix-open (namestring ofile)
+					 unix:o_creat #o666)
+      (unless fd
+	(editor-error "Couldn't create compiler temporary output file:~%~
+	~A" (unix:get-unix-error-msg err)))
+      (unix:unix-fchmod fd #o666)
+      (unix:unix-close fd))
+    (let ((net-ofile (pathname-for-remote-access ofile)))
+      (values (make-pathname :directory (pathname-directory net-ofile)
+			     :defaults file)
+	      ofile
+	      net-ofile
+	      (file-write-date ofile)))))
+
+(defun pathname-for-remote-access (file)
+  (let* ((machine (machine-instance))
+	 (usable-name (nstring-downcase
+		       (the simple-string
+			    (subseq machine 0 (position #\. machine))))))
+    (declare (simple-string machine usable-name))
+    (make-pathname :directory (concatenate 'simple-string
+					   "/../"
+					   usable-name
+					   (directory-namestring file))
+		   :defaults file)))
+
+;;; REGION-CONTEXT -- internal
+;;;
+;;;    Return a string which describes the code in a region.  Thing is the
+;;; thing being done to the region.  "compilation" or "evaluation"...
+
+(defun region-context (region thing)
+  (declare (simple-string thing))
+  (pre-command-parse-check (region-start region))
+  (let ((start (region-start region)))
+    (with-mark ((m1 start))
+      (unless (start-defun-p m1)
+	(top-level-offset m1 1))
+      (with-mark ((m2 m1))
+	(mark-after m2)
+	(form-offset m2 2)
+	(format nil
+		"~A of ~S"
+		thing
+		(if (eq (mark-line m1) (mark-line m2))
+		  (region-to-string (region m1 m2))
+		  (concatenate 'simple-string
+			       (line-string (mark-line m1))
+			       "...")))))))
+
+
+
+;;;; Commands (Gosh, wow gee!)
+
+(defcommand "Editor Server Name" (p)
+  "Echos the editor server's name which can be supplied with the -slave switch
+   to connect to a designated editor."
+  "Echos the editor server's name which can be supplied with the -slave switch
+   to connect to a designated editor."
+  (declare (ignore p))
+  (if *editor-name*
+    (message "This editor is named ~S." *editor-name*)
+    (message "This editor is not currently named.")))
+
+(defcommand "Set Buffer Package" (p)
+  "Set the package to be used by Lisp evaluation and compilation commands
+   while in this buffer.  When in a slave's interactive buffers, do NOT
+   set the editor's package variable, but changed the slave's *package*."
+  "Prompt for a package to make into a buffer-local variable current-package."
+  (declare (ignore p))
+  (let* ((name (string (prompt-for-expression
+			:prompt "Package name: "
+			:help "Name of package to associate with this buffer.")))
+	 (buffer (current-buffer))
+	 (info (value current-eval-server)))
+    (cond ((and info
+		(or (eq (server-info-slave-buffer info) buffer)
+		    (eq (server-info-background-buffer info) buffer)))
+	   (hemlock.wire:remote (server-info-wire info)
+	     (server-set-package name))
+	   (hemlock.wire:wire-force-output (server-info-wire info)))
+	  ((eq buffer *selected-eval-buffer*)
+	   (setf *package* (maybe-make-package name)))
+	  (t
+	   (defhvar "Current Package"
+	     "The package used for evaluation of Lisp in this buffer."
+	     :buffer buffer  :value name)))
+    (when (buffer-modeline-field-p buffer :package)
+      (dolist (w (buffer-windows buffer))
+	(update-modeline-field buffer w :package)))))
+
+(defcommand "Current Compile Server" (p)
+  "Echos the current compile server's name.  With prefix argument,
+   shows global one.  Does not signal an error or ask about creating a slave."
+  "Echos the current compile server's name.  With prefix argument,
+  shows global one."
+  (let ((info (if p
+		  (variable-value 'current-compile-server :global)
+		  (value current-compile-server))))
+    (if info
+	(message "~A" (server-info-name info))
+	(message "No ~:[current~;global~] compile server." p))))
+
+(defcommand "Set Compile Server" (p)
+  "Specifies the name of the server used globally for file compilation requests."
+  "Call select-current-compile-server."
+  (declare (ignore p))
+  (hlet ((ask-about-old-servers t))
+    (setf (variable-value 'current-compile-server :global)
+	  (maybe-create-server))))
+
+(defcommand "Set Buffer Compile Server" (p)
+  "Specifies the name of the server used for file compilation requests in
+   the current buffer."
+  "Call select-current-compile-server after making a buffer local variable."
+  (declare (ignore p))
+  (hlet ((ask-about-old-servers t))
+    (defhvar "Current Compile Server"
+      "The Server-Info object for the server currently used for compilation requests."
+      :buffer (current-buffer)
+      :value (maybe-create-server))))
+
+(defcommand "Current Eval Server" (p)
+  "Echos the current eval server's name.  With prefix argument, shows
+   global one.  Does not signal an error or ask about creating a slave."
+  "Echos the current eval server's name.  With prefix argument, shows
+   global one.  Does not signal an error or ask about creating a slave."
+  (let ((info (if p
+		  (variable-value 'current-eval-server :global)
+		  (value current-eval-server))))
+    (if info
+	(message "~A" (server-info-name info))
+	(message "No ~:[current~;global~] eval server." p))))
+
+(defcommand "Set Eval Server" (p)
+  "Specifies the name of the server used globally for evaluation and
+   compilation requests."
+  "Call select-current-server."
+  (declare (ignore p))
+  (hlet ((ask-about-old-servers t))
+    (setf (variable-value 'current-eval-server :global)
+	  (maybe-create-server))))
+
+(defcommand "Set Buffer Eval Server" (p)
+  "Specifies the name of the server used for evaluation and compilation
+   requests in the current buffer."
+  "Call select-current-server after making a buffer local variable."
+  (declare (ignore p))
+  (hlet ((ask-about-old-servers t))
+    (defhvar "Current Eval Server"
+      "The Server-Info for the eval server used in this buffer."
+      :buffer (current-buffer)
+      :value (maybe-create-server))))
+
+(defcommand "Evaluate Defun" (p)
+  "Evaluates the current or next top-level form.
+   If the current region is active, then evaluate it."
+  "Evaluates the current or next top-level form."
+  (declare (ignore p))
+  (if (region-active-p)
+      (evaluate-region-command nil)
+      (region-eval (defun-region (current-point)))))
+
+(defcommand "Re-evaluate Defvar" (p)
+  "Evaluate the current or next top-level form if it is a DEFVAR.  Treat the
+   form as if the variable is not bound."
+  "Evaluate the current or next top-level form if it is a DEFVAR.  Treat the
+   form as if the variable is not bound."
+  (declare (ignore p))
+  (let* ((form (defun-region (current-point)))
+	 (start (region-start form)))
+    (with-mark ((var-start start)
+		(var-end start))
+      (mark-after var-start)
+      (form-offset var-start 1)
+      (form-offset (move-mark var-end var-start) 1)
+      (let ((exp (concatenate 'simple-string
+			      "(makunbound '"
+			      (region-to-string (region var-start var-end))
+			      ")")))
+	(eval-form-in-server (get-current-eval-server) exp)))
+    (region-eval form)))
+
+;;; We use Prin1-To-String in the client so that the expansion gets pretty
+;;; printed.  Since the expansion can contain unreadable stuff, we can't expect
+;;; to be able to read that string back in the editor.  We shove the region
+;;; at the client Lisp as a string, so it can read from the string with the
+;;; right package environment.
+;;;
+
+(defcommand "Macroexpand Expression" (p)
+  "Show the macroexpansion of the current expression in the null environment.
+   With an argument, use MACROEXPAND instead of MACROEXPAND-1."
+  "Show the macroexpansion of the current expression in the null environment.
+   With an argument, use MACROEXPAND instead of MACROEXPAND-1."
+  (let ((point (current-point)))
+    (with-mark ((start point))
+      (pre-command-parse-check start)
+      (with-mark ((end start))
+        (unless (form-offset end 1) (editor-error))
+	(with-pop-up-display (s)
+	  (write-string
+	   (eval-form-in-server-1
+	    (get-current-eval-server)
+	    (format nil "(prin1-to-string (~S (read-from-string ~S)))"
+		    (if p 'macroexpand 'macroexpand-1)
+		    (region-to-string (region start end))))
+	   s))))))
+
+(defcommand "Evaluate Expression" (p)
+  "Prompt for an expression to evaluate."
+  "Prompt for an expression to evaluate."
+  (declare (ignore p))
+  (let ((exp (prompt-for-string
+	      :prompt "Eval: "
+	      :help "Expression to evaluate.")))
+    (message "=> ~{~#[~;~A~:;~A, ~]~}"
+	     (eval-form-in-server (get-current-eval-server) exp))))
+
+(defcommand "Compile Defun" (p)
+  "Compiles the current or next top-level form.
+   First the form is evaluated, then the result of this evaluation
+   is passed to compile.  If the current region is active, compile
+   the region."
+  "Evaluates the current or next top-level form."
+  (declare (ignore p))
+  (if (region-active-p)
+      (compile-region-command nil)
+      (region-compile (defun-region (current-point)))))
+
+(defcommand "Compile Region" (p)
+  "Compiles lisp forms between the point and the mark."
+  "Compiles lisp forms between the point and the mark."
+  (declare (ignore p))
+  (region-compile (current-region)))
+
+(defcommand "Evaluate Region" (p)
+  "Evaluates lisp forms between the point and the mark."
+  "Evaluates lisp forms between the point and the mark."
+  (declare (ignore p))
+  (region-eval (current-region)))
+           
+(defcommand "Evaluate Buffer" (p)
+  "Evaluates the text in the current buffer."
+  "Evaluates the text in the current buffer redirecting *Standard-Output* to
+  the echo area.  The prefix argument is ignored."
+  (declare (ignore p))
+  (let ((b (current-buffer)))
+    (region-eval (buffer-region b)
+		 :context (format nil
+				  "evaluation of buffer ``~A''"
+				  (buffer-name b)))))
+
+(defcommand "Load File" (p)
+  "Prompt for a file to load into the current eval server."
+  "Prompt for a file to load into the current eval server."
+  (declare (ignore p))
+  (let ((name (truename (prompt-for-file
+			 :default
+			 (or (value load-pathname-defaults)
+			     (buffer-default-pathname (current-buffer)))
+			 :prompt "File to load: "
+			 :help "The name of the file to load"))))
+    (setv load-pathname-defaults name)
+    (string-eval (format nil "(load ~S)"
+			 (namestring
+			  (if (value remote-compile-file)
+			      (pathname-for-remote-access name)
+			      name))))))
+
+(defcommand "Compile File" (p)
+  "Prompts for file to compile.  Does not compare source and binary write
+   dates.  Does not check any buffer for that file for whether the buffer
+   needs to be saved."
+  "Prompts for file to compile."
+  (declare (ignore p))
+  (let ((pn (prompt-for-file :default
+			     (buffer-default-pathname (current-buffer))
+			     :prompt "File to compile: ")))
+    (file-compile pn)))
+
+(defhvar "Compile Buffer File Confirm"
+  "When set, \"Compile Buffer File\" prompts before doing anything."
+  :value t)
+
+(defcommand "Compile Buffer File" (p)
+  "Compile the file in the current buffer if its associated binary file
+   (of type .fasl) is older than the source or doesn't exist.  When the
+   binary file is up to date, the user is asked if the source should be
+   compiled anyway.  When the prefix argument is supplied, compile the
+   file without checking the binary file.  When \"Compile Buffer File
+   Confirm\" is set, this command will ask for confirmation when it
+   otherwise would not."
+  "Compile the file in the current buffer if the fasl file isn't up to date.
+   When p, always do it."
+  (let* ((buf (current-buffer))
+	 (pn (buffer-pathname buf)))
+    (unless pn (editor-error "Buffer has no associated pathname."))
+    (cond ((buffer-modified buf)
+	   (when (or (not (value compile-buffer-file-confirm))
+		     (prompt-for-y-or-n
+		      :default t :default-string "Y"
+		      :prompt (list "Save and compile file ~A? "
+				    (namestring pn))))
+	     (write-buffer-file buf pn)
+	     (file-compile pn :buffer buf)))
+	  ((older-or-non-existent-fasl-p pn p)
+	   (when (or (not (value compile-buffer-file-confirm))
+		     (prompt-for-y-or-n
+		      :default t :default-string "Y"
+		      :prompt (list "Compile file ~A? " (namestring pn))))
+	     (file-compile pn :buffer buf)))
+	  ((or p
+	       (prompt-for-y-or-n
+		:default t :default-string "Y"
+		:prompt
+		"Fasl file up to date, compile source anyway? "))
+	   (file-compile pn :buffer buf)))))
+
+(defcommand "Compile Group" (p)
+  "Compile each file in the current group which needs it.
+  If a file has type LISP and there is a curresponding file with type
+  FASL which has been written less recently (or it doesn't exit), then
+  the file is compiled, with error output directed to the \"Compiler Warnings\"
+  buffer.  If a prefix argument is provided, then all the files are compiled.
+  All modified files are saved beforehand."
+  "Do a Compile-File in each file in the current group that seems to need it."
+  (save-all-files-command ())
+  (unless *active-file-group* (editor-error "No active file group."))
+  (dolist (file *active-file-group*)
+    (when (string-equal (pathname-type file) "lisp")
+      (let ((tn (probe-file file)))
+	(cond ((not tn)
+	       (message "File ~A not found." (namestring file)))
+	      ((older-or-non-existent-fasl-p tn p)
+	       (file-compile tn)))))))
+
+
+
+;;;; Error hacking stuff.
+
+(defcommand "Flush Compiler Error Information" (p)
+  "Flushes all infomation about errors encountered while compiling using the
+   current server"
+  "Flushes all infomation about errors encountered while compiling using the
+   current server"
+  (declare (ignore p))
+  (clear-server-errors (get-current-compile-server t)))
+
+(defcommand "Next Compiler Error" (p)
+  "Move to the next compiler error for the current server.  If an argument is 
+   given, advance that many errors."
+  "Move to the next compiler error for the current server.  If an argument is 
+   given, advance that many errors."
+  (let* ((server (get-current-compile-server t))
+	 (errors (server-info-errors server))
+	 (fp (fill-pointer errors)))
+    (when (zerop fp)
+      (editor-error "There are no compiler errors."))
+    (let* ((old-index (server-info-error-index server))
+	   (new-index (+ (or old-index -1) (or p 1))))
+      (when (< new-index 0)
+	(if old-index
+	    (editor-error "Can't back up ~R, only at the ~:R compiler error."
+			  (- p) (1+ old-index))
+	    (editor-error "Not even at the first compiler error.")))
+      (when (>= new-index fp)
+	(if (= (1+ (or old-index -1)) fp)
+	    (editor-error "No more compiler errors.")
+	    (editor-error "Only ~R remaining compiler error~:P."
+			  (- fp old-index 1))))
+      (setf (server-info-error-index server) new-index)
+      ;; Display the silly error.
+      (let ((error (aref errors new-index)))
+	(let ((region (error-info-region error)))
+	  (if region
+	      (let* ((start (region-start region))
+		     (buffer (line-buffer (mark-line start))))
+		(change-to-buffer buffer)
+		(move-mark (buffer-point buffer) start))
+	      (message "Hmm, no region for this error.")))
+	(let* ((line (error-info-line error))
+	       (buffer (line-buffer line)))
+	  (if (and line (bufferp buffer))
+	      (let ((mark (mark line 0)))
+		(unless (buffer-windows buffer)
+		  (let ((window (find-if-not
+				 #'(lambda (window)
+				     (or (eq window (current-window))
+					 (eq window *echo-area-window*)))
+				 *window-list*)))
+		    (if window
+			(setf (window-buffer window) buffer)
+			(make-window mark))))
+		(move-mark (buffer-point buffer) mark)
+		(dolist (window (buffer-windows buffer))
+		  (move-mark (window-display-start window) mark)
+		  (move-mark (window-point window) mark))
+		(delete-mark mark))
+	      (message "Hmm, no line for this error.")))))))
+
+(defcommand "Previous Compiler Error" (p)
+  "Move to the previous compiler error. If an argument is given, move back
+   that many errors."
+  "Move to the previous compiler error. If an argument is given, move back
+   that many errors."
+  (next-compiler-error-command (- (or p 1))))
+
+
+
+
+;;;; Operation management commands:
+
+(defcommand "Abort Operations" (p)
+  "Abort all operations on current eval server connection."
+  "Abort all operations on current eval server connection."
+  (declare (ignore p))
+  (let* ((server (get-current-eval-server))
+	 (wire (server-info-wire server)))
+    ;; Tell the slave to abort the current operation and to ignore any further
+    ;; operations.
+    (dolist (note (server-info-notes server))
+      (setf (note-state note) :aborted))
+    #+NILGB (ext:send-character-out-of-band (hemlock.wire:wire-fd wire) #\N)
+    (hemlock.wire:remote-value wire (server-accept-operations))
+    ;; Synch'ing with server here, causes any operations queued at the socket or
+    ;; in the server to be ignored, and the last thing evaluated is an
+    ;; instruction to go on accepting operations.
+    (hemlock.wire:wire-force-output wire)
+    (dolist (note (server-info-notes server))
+      (when (eq (note-state note) :pending)
+	;; The HEMLOCK.WIRE:REMOTE-VALUE call should have allowed a handshake to
+	;; tell the editor anything :pending was aborted.
+	(error "Operation ~S is still around after we aborted it?" note)))
+    ;; Forget anything queued in the editor.
+    (setf (server-info-notes server) nil)))
+
+(defcommand "List Operations" (p)
+  "List all eval server operations which have not yet completed."
+  "List all eval server operations which have not yet completed."
+  (declare (ignore p))
+  (let ((notes nil))
+    ;; Collect all notes, reversing them since they act like a queue but
+    ;; are not in queue order.
+    (do-strings (str val *server-names*)
+      (declare (ignore str))
+      (setq notes (nconc notes (reverse (server-info-notes val)))))
+    (if notes
+	(with-pop-up-display (s)
+	  (dolist (note notes)
+	    (format s "~@(~8A~) ~A on ~A.~%"
+		    (note-state note)
+		    (note-context note)
+		    (server-info-name (note-server note)))))
+	(message "No uncompleted operations.")))
+  (values))
+
+
+
+;;;; Describing in the client lisp.
+
+;;; "Describe Function Call" gets the function name from the current form
+;;; as a string.  This string is used as the argument to a call to
+;;; DESCRIBE-FUNCTION-CALL-AUX which is eval'ed in the client lisp.  The
+;;; auxiliary function's name is qualified since it is read in the client
+;;; Lisp with *package* bound to the buffer's package.  The result comes
+;;; back as a list of strings, so we read the first string to get out the
+;;; string value returned by DESCRIBE-FUNCTION-CALL-AUX in the client Lisp.
+;;;
+(defcommand "Describe Function Call" (p)
+  "Describe the current function call."
+  "Describe the current function call."
+  (let ((info (value current-eval-server)))
+    (cond
+     ((not info)
+      (message "Describing from the editor Lisp ...")
+      (editor-describe-function-call-command p))
+     (t
+      (with-mark ((mark1 (current-point))
+		  (mark2 (current-point)))
+	(pre-command-parse-check mark1)
+	(unless (backward-up-list mark1) (editor-error))
+	(form-offset (move-mark mark2 (mark-after mark1)) 1)
+	(let* ((package (value current-package))
+	       (package-exists
+		(eval-form-in-server-1
+		 info
+		 (format nil
+			 "(if (find-package ~S) t (package-name *package*))"
+			 package)
+		 nil)))
+	  (unless (eq package-exists t)
+	    (message "Using package ~S in ~A since ~
+		      ~:[there is no current package~;~:*~S does not exist~]."
+		     package-exists (server-info-name info) package))
+	  (with-pop-up-display (s)
+	    (write-string (eval-form-in-server-1
+			   info
+			   (format nil "(hemlock::describe-function-call-aux ~S)"
+				   (region-to-string (region mark1 mark2)))
+			   (if (eq package-exists t) package nil))
+			   s))))))))
+
+;;; DESCRIBE-FUNCTION-CALL-AUX is always evaluated in a client Lisp to some
+;;; editor, relying on the fact that the cores have the same functions.  String
+;;; is the name of a function that is read (in the client Lisp).  The result is
+;;; a string of all the output from EDITOR-DESCRIBE-FUNCTION.
+;;;
+(defun describe-function-call-aux (string)
+  (let* ((sym (read-from-string string))
+	 (fun (function-to-describe sym error)))
+    (with-output-to-string (*standard-output*)
+      (editor-describe-function fun sym))))
+
+;;; "Describe Symbol" gets the symbol name and quotes it as the argument to a
+;;; call to DESCRIBE-SYMBOL-AUX which is eval'ed in the client lisp.  The
+;;; auxiliary function's name is qualified since it is read in the client Lisp
+;;; with *package* bound to the buffer's package.  The result comes back as a
+;;; list of strings, so we read the first string to get out the string value
+;;; returned by DESCRIBE-SYMBOL-AUX in the client Lisp.
+;;;
+
+(defcommand "Describe Symbol" (p)
+  "Describe the previous s-expression if it is a symbol."
+  "Describe the previous s-expression if it is a symbol."
+  (declare (ignore p))
+  (let ((info (value current-eval-server)))
+    (cond
+     ((not info)
+      (message "Describing from the editor Lisp ...")
+      (editor-describe-symbol-command nil))
+     (t
+      (with-mark ((mark1 (current-point))
+		  (mark2 (current-point)))
+	(mark-symbol mark1 mark2)
+	(with-pop-up-display (s)
+	  (write-string (eval-form-in-server-1
+			 info
+			 (format nil "(hemlock::describe-symbol-aux '~A)"
+				 (region-to-string (region mark1 mark2))))
+			s)))))))
+
+(defun describe-symbol-aux (thing)
+  (with-output-to-string (*standard-output*)
+    (describe (if (and (consp thing)
+		       (or (eq (car thing) 'quote)
+			   (eq (car thing) 'function))
+		       (symbolp (cadr thing)))
+		  (cadr thing)
+		  thing))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/mh.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/mh.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/mh.lisp	(revision 13309)
@@ -0,0 +1,3180 @@
+;;; -*- Package: Hemlock; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This is a mailer interface to MH.
+;;; 
+;;; Written by Bill Chiles.
+;;;
+
+(in-package :hemlock)
+
+
+
+
+;;;; General stuff.
+
+(defvar *new-mail-buffer* nil)
+
+(defvar *mh-utility-bit-bucket* (make-broadcast-stream))
+
+
+(defattribute "Digit"
+  "This is just a (mod 2) attribute for base 10 digit characters.")
+;;;
+(dotimes (i 10)
+  (setf (character-attribute :digit (digit-char i)) 1))
+
+
+(defmacro number-string (number)
+  `(let ((*print-base* 10))
+     (prin1-to-string ,number)))
+
+
+(defmacro do-headers-buffers ((buffer-var folder &optional hinfo-var)
+			      &rest forms)
+  "The Forms are evaluated with Buffer-Var bound to each buffer containing
+   headers lines for folder.  Optionally Hinfo-Var is bound to the
+   headers-information structure."
+  (let ((folder-var (gensym))
+	(hinfo (gensym)))
+    `(let ((,folder-var ,folder))
+       (declare (simple-string ,folder-var))
+       (dolist (,buffer-var *buffer-list*)
+	 (when (hemlock-bound-p 'headers-information :buffer ,buffer-var)
+	   (let ((,hinfo (variable-value 'headers-information
+					 :buffer ,buffer-var)))
+	     (when (string= (the simple-string (headers-info-folder ,hinfo))
+			    ,folder-var)
+	       ,@(if hinfo-var
+		     `((let ((,hinfo-var ,hinfo))
+			 ,@forms))
+		     forms))))))))
+
+(defmacro do-headers-lines ((hbuffer &key line-var mark-var) &rest forms)
+  "Forms are evaluated for each non-blank line.  When supplied Line-Var and
+   Mark-Var are to the line and a :left-inserting mark at the beginning of the
+   line.  This works with DELETE-HEADERS-BUFFER-LINE, but one should be careful
+   using this to modify the hbuffer."
+  (let ((line-var (or line-var (gensym)))
+	(mark-var (or mark-var (gensym)))
+	(id (gensym)))
+    `(with-mark ((,mark-var (buffer-point ,hbuffer) :left-inserting))
+       (buffer-start ,mark-var)
+       (loop
+	 (let* ((,line-var (mark-line ,mark-var))
+		(,id (line-message-id ,line-var)))
+	   (unless (blank-line-p ,line-var)
+	     ,@forms)
+	   (if (or (not (eq ,line-var (mark-line ,mark-var)))
+		   (string/= ,id (line-message-id ,line-var)))
+	       (line-start ,mark-var)
+	       (unless (line-offset ,mark-var 1 0) (return))))))))
+
+(defmacro with-headers-mark ((mark-var hbuffer msg) &rest forms)
+  "Forms are executed with Mark-Var bound to a :left-inserting mark at the
+   beginning of the headers line representing msg.  If no such line exists,
+   no execution occurs."
+  (let ((line (gensym)))    
+    `(do-headers-lines (,hbuffer :line-var ,line :mark-var ,mark-var)
+       (when (string= (the simple-string (line-message-id ,line))
+		      (the simple-string ,msg))
+	 ,@forms
+	 (return)))))
+
+
+
+
+;;;; Headers Mode.
+
+(defmode "Headers" :major-p t)
+
+(defhvar "Headers Information"
+  "This holds the information about the current headers buffer."
+  :value nil)
+
+(defstruct (headers-info (:print-function print-headers-info))
+  buffer		;Buffer for these headers.
+  folder		;String name of folder with leading MH "+".
+  msg-seq		;MH sequence of messages in buffer.
+  msg-strings		;List of strings representing msg-seq.
+  other-msg-bufs	;List of message buffers referencing this headers buffer.
+  draft-bufs		;List of draft buffers referencing this headers buffer.
+  msg-buffer)
+
+(defun print-headers-info (obj str n)
+  (declare (ignore n))
+  (format str "#<Headers Info ~S>" (headers-info-folder obj)))
+
+(defmacro line-message-deleted (line)
+  `(getf (line-plist ,line) 'mh-msg-deleted))
+
+(defmacro line-message-id (line)
+  `(getf (line-plist ,line) 'mh-msg-id))
+
+(defun headers-current-message (hinfo)
+  (let* ((point (buffer-point (headers-info-buffer hinfo)))
+	 (line (mark-line point)))
+    (unless (blank-line-p line)
+      (values (line-message-id line)
+	      (copy-mark point)))))
+
+(defcommand "Message Headers" (p)
+  "Prompts for a folder and messages, displaying headers in a buffer in the
+   current window.  With an argument, prompt for a pick expression."
+  "Show some headers."
+  (let ((folder (prompt-for-folder)))
+    (new-message-headers
+     folder
+     (prompt-for-message :prompt (if p
+				     "MH messages to pick from: "
+				     "MH messages: ")
+			 :folder folder
+			 :messages "all")
+			 p)))
+
+(defcommand "Pick Headers" (p)
+  "Further narrow the selection of this folders headers.
+   Prompts for a pick expression to pick over the headers in the current
+   buffer.  Entering an empty expression displays all the headers for that
+   folder."
+  "Prompts for a pick expression to pick over the headers in the current
+   buffer."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information)))
+    (unless hinfo
+      (editor-error "Pick Headers only works in a headers buffer."))
+    (pick-message-headers hinfo)))
+
+;;; PICK-MESSAGE-HEADERS picks messages from info's messages based on an
+;;; expression provided by the user.  If the expression is empty, we do
+;;; headers on all the messages in folder.  The buffer's name is changed to
+;;; reflect the messages picked over and the expression used.
+;;; 
+(defun pick-message-headers (hinfo)
+  (let ((folder (headers-info-folder hinfo))
+	(msgs (headers-info-msg-strings hinfo)))
+    (multiple-value-bind (pick user-pick)
+			 (prompt-for-pick-expression)
+      (let* ((hbuffer (headers-info-buffer hinfo))
+	     (new-mail-buf-p (eq hbuffer *new-mail-buffer*))
+	     (region (cond (pick
+			    (message-headers-to-region
+			     folder (pick-messages folder msgs pick)))
+			   (new-mail-buf-p
+			    (maybe-get-new-mail-msg-hdrs folder))
+			   (t (message-headers-to-region folder
+							 (list "all"))))))
+	(with-writable-buffer (hbuffer)
+	  (revamp-headers-buffer hbuffer hinfo)
+	  (when region (insert-message-headers hbuffer hinfo region)))
+	(setf (buffer-modified hbuffer) nil)
+	(buffer-start (buffer-point hbuffer))
+	(setf (buffer-name hbuffer)
+	      (cond (pick (format nil "Headers ~A ~A ~A" folder msgs user-pick))
+		    (new-mail-buf-p (format nil "Unseen Headers ~A" folder))
+		    (t (format nil "Headers ~A (all)" folder))))))))
+
+;;; NEW-MESSAGE-HEADERS picks over msgs if pickp is non-nil, or it just scans
+;;; msgs.  It is important to pick and get the message headers region before
+;;; making the buffer and info structures since PICK-MESSAGES and
+;;; MESSAGE-HEADERS-TO-REGION will call EDITOR-ERROR if they fail.  The buffer
+;;; name is chosen based on folder, msgs, and an optional pick expression.
+;;;
+(defun new-message-headers (folder msgs &optional pickp)
+  (multiple-value-bind (pick-exp user-pick)
+		       (if pickp (prompt-for-pick-expression))
+    (let* ((pick (if pick-exp (pick-messages folder msgs pick-exp)))
+	   (region (message-headers-to-region folder (or pick msgs)))
+	   (hbuffer (maybe-make-mh-buffer (format nil "Headers ~A ~A~:[~; ~S~]"
+					       folder msgs pick user-pick)
+				       :headers))
+	   (hinfo (make-headers-info :buffer hbuffer :folder folder)))
+      (insert-message-headers hbuffer hinfo region)
+      (defhvar "Headers Information"
+	"This holds the information about the current headers buffer."
+	:value hinfo :buffer hbuffer)
+      (setf (buffer-modified hbuffer) nil)
+      (setf (buffer-writable hbuffer) nil)
+      (buffer-start (buffer-point hbuffer))
+      (change-to-buffer hbuffer))))
+
+(defhvar "MH Scan Line Form"
+  "This is a pathname of a file containing an MH format expression for headers
+   lines."
+  :value (pathname "library:mh-scan"))
+
+;;; MESSAGE-HEADERS-TO-REGION uses the MH "scan" utility output headers into
+;;; buffer for folder and msgs.
+;;;
+;;; (value fill-column) should really be done as if the buffer were current,
+;;; but Hemlock doesn't let you do this without the buffer being current.
+;;;
+(defun message-headers-to-region (folder msgs &optional width)
+  (let ((region (make-empty-region)))
+    (with-output-to-mark (*standard-output* (region-end region) :full)
+      (mh "scan"
+	  `(,folder ,@msgs
+	    "-form" ,(namestring (truename (value mh-scan-line-form)))
+	    "-width" ,(number-string (or width (value fill-column)))
+	    "-noheader")))
+    region))
+
+(defun insert-message-headers (hbuffer hinfo region)
+  (ninsert-region (buffer-point hbuffer) region)
+  (let ((seq (set-message-headers-ids hbuffer :return-seq)))
+    (setf (headers-info-msg-seq hinfo) seq)
+    (setf (headers-info-msg-strings hinfo) (mh-sequence-strings seq)))
+  (when (value virtual-message-deletion)
+    (note-deleted-headers hbuffer
+			  (mh-sequence-list (headers-info-folder hinfo)
+					    "hemlockdeleted"))))
+
+(defun set-message-headers-ids (hbuffer &optional return-seq)
+  (let ((msgs nil))
+    (do-headers-lines (hbuffer :line-var line)
+      (let* ((line-str (line-string line))
+	     (num (parse-integer line-str :junk-allowed t)))
+	(declare (simple-string line-str))
+	(unless num
+	  (editor-error "MH scan lines must contain the message id as the ~
+	                 first thing on the line for the Hemlock interface."))
+	(setf (line-message-id line) (number-string num))
+	(when return-seq (setf msgs (mh-sequence-insert num msgs)))))
+    msgs))
+
+(defun note-deleted-headers (hbuffer deleted-seq)
+  (when deleted-seq
+    (do-headers-lines (hbuffer :line-var line :mark-var hmark)
+      (if (mh-sequence-member-p (line-message-id line) deleted-seq)
+	  (note-deleted-message-at-mark hmark)
+	  (setf (line-message-deleted line) nil)))))
+
+;;; PICK-MESSAGES  --  Internal Interface.
+;;;
+;;; This takes a folder (with a + in front of the name), messages to pick
+;;; over, and an MH pick expression (in the form returned by
+;;; PROMPT-FOR-PICK-EXPRESSION).  Sequence is an MH sequence to set to exactly
+;;; those messages chosen by the pick when zerop is non-nil; when zerop is nil,
+;;; pick adds the messages to the sequence along with whatever messages were
+;;; already in the sequence.  This returns a list of message specifications.
+;;;
+(defun pick-messages (folder msgs expression &optional sequence (zerop t))
+  (let* ((temp (with-output-to-string (*standard-output*)
+		 (unless
+		     ;; If someone bound *signal-mh-errors* to nil around this
+		     ;; function, MH pick outputs bogus messages (for example,
+		     ;; "0"), and MH would return without calling EDITOR-ERROR.
+		     (mh "pick" `(,folder
+				  ,@msgs
+				  ,@(if sequence `("-sequence" ,sequence))
+				  ,@(if zerop '("-zero"))
+				  "-list"	; -list must follow -sequence.
+				  ,@expression))
+		   (return-from pick-messages nil))))
+	 (len (length temp))
+	 (start 0)
+	 (result nil))
+    (declare (simple-string temp))
+    (loop
+      (let ((end (position #\newline temp :start start :test #'char=)))
+	(cond ((not end)
+	       (return (nreverse (cons (subseq temp start) result))))
+	      ((= start end)
+	       (return (nreverse result)))
+	      (t
+	       (push (subseq temp start end) result)
+	       (when (>= (setf start (1+ end)) len)
+		 (return (nreverse result)))))))))
+
+
+(defcommand "Delete Headers Buffer and Message Buffers" (p &optional buffer)
+  "Prompts for a headers buffer to delete along with its associated message
+   buffers.  Any associated draft buffers are left alone, but their associated
+   message buffers will be deleted."
+  "Deletes the current headers buffer and its associated message buffers."
+  (declare (ignore p))
+  (let* ((default (cond ((value headers-information) (current-buffer))
+			((value message-information) (value headers-buffer))))
+	 (buffer (or buffer
+		     (prompt-for-buffer :default default
+					:default-string
+					(if default (buffer-name default))))))
+    (unless (hemlock-bound-p 'headers-information :buffer buffer)
+      (editor-error "Not a headers buffer -- ~A" (buffer-name buffer)))
+    (let* ((hinfo (variable-value 'headers-information :buffer buffer))
+	   ;; Copy list since buffer cleanup hook is destructive.
+	   (other-bufs (copy-list (headers-info-other-msg-bufs hinfo)))
+	   (msg-buf (headers-info-msg-buffer hinfo)))
+      (when msg-buf (delete-buffer-if-possible msg-buf))
+      (dolist (b other-bufs) (delete-buffer-if-possible b))
+      (delete-buffer-if-possible (headers-info-buffer hinfo)))))
+
+(defhvar "Expunge Messages Confirm"
+  "When set (the default), \"Expunge Messages\" and \"Quit Headers\" will ask
+   for confirmation before expunging messages and packing the folder's message
+   id's."
+  :value t)
+
+(defhvar "Temporary Draft Folder"
+  "This is the folder name where MH fcc: messages are kept that are intended
+   to be deleted and expunged when messages are expunged for any other
+   folder -- \"Expunge Messages\" and \"Quit Headers\"."
+  :value nil)
+
+;;; "Quit Headers" doesn't expunge or compact unless there is a deleted
+;;; sequence.  This collapses other headers buffers into the same folder
+;;; differently than "Expunge Messages" since the latter assumes there will
+;;; always be one remaining headers buffer.  This command folds all headers
+;;; buffers into the folder that are not the current buffer or the new mail
+;;; buffer into one buffer.  When the current buffer is the new mail buffer
+;;; we do not check for more unseen headers since we are about to delete
+;;; the buffer anyway.  The other headers buffers must be deleted before
+;;; making the new one due to aliasing the buffer structure and
+;;; MAYBE-MAKE-MH-BUFFER.
+;;;
+(defcommand "Quit Headers" (p)
+  "Quit headers buffer possibly expunging deleted messages.
+   This affects the current headers buffer.  When there are deleted messages
+   the user is asked for confirmation on expunging the messages and packing the
+   folder's message id's.  Then the buffer and all its associated message
+   buffers are deleted.  Setting \"Quit Headers Confirm\" to nil inhibits
+   prompting.  When \"Temporary Draft Folder\" is bound, this folder's messages
+   are deleted and expunged."
+  "This affects the current headers buffer.  When there are deleted messages
+   the user is asked for confirmation on expunging the messages and packing
+   the folder.  Then the buffer and all its associated message buffers are
+   deleted."
+  (declare (ignore p))
+  (let* ((hinfo (value headers-information))
+	 (minfo (value message-information))
+	 (hdrs-buf (cond (hinfo (current-buffer))
+			 (minfo (value headers-buffer)))))
+    (unless hdrs-buf
+      (editor-error "Not in or associated with any headers buffer."))
+    (let* ((folder (cond (hinfo (headers-info-folder hinfo))
+			 (minfo (message-info-folder minfo))))
+	   (deleted-seq (mh-sequence-list folder "hemlockdeleted")))
+      (when (and deleted-seq
+		 (or (not (value expunge-messages-confirm))
+		     (prompt-for-y-or-n
+		      :prompt (list "Expunge messages and pack folder ~A? "
+				    folder)
+		      :default t
+		      :default-string "Y")))
+	(message "Deleting messages ...")
+	(mh "rmm" (list folder "hemlockdeleted"))
+	(let ((*standard-output* *mh-utility-bit-bucket*))
+	  (message "Compacting folder ...")
+	  (mh "folder" (list folder "-fast" "-pack")))
+	(message "Maintaining consistency ...")
+	(let (hbufs)
+	  (declare (list hbufs))
+	  (do-headers-buffers (b folder)
+	    (unless (or (eq b hdrs-buf) (eq b *new-mail-buffer*))
+	      (push b hbufs)))
+	  (dolist (b hbufs)
+	    (delete-headers-buffer-and-message-buffers-command nil b))
+	  (when hbufs
+	    (new-message-headers folder (list "all"))))
+	(expunge-messages-fix-draft-buffers folder)
+	(unless (eq hdrs-buf *new-mail-buffer*)
+	  (expunge-messages-fix-unseen-headers folder))
+	(delete-and-expunge-temp-drafts)))
+    (delete-headers-buffer-and-message-buffers-command nil hdrs-buf)))
+
+;;; DELETE-AND-EXPUNGE-TEMP-DRAFTS deletes all the messages in the
+;;; temporary draft folder if there is one defined.  Any headers buffers
+;;; into this folder are deleted with their message buffers.  We have to
+;;; create a list of buffers to delete since buffer deletion destructively
+;;; modifies the same list DO-HEADERS-BUFFERS uses.  "rmm" is run without
+;;; error reporting since it signals an error if there are no messages to
+;;; delete.  This function must return; for example, "Quit Headers" would
+;;; not complete successfully if this ended up calling EDITOR-ERROR.
+;;;
+(defun delete-and-expunge-temp-drafts ()
+  (let ((temp-draft-folder (value temporary-draft-folder)))
+    (when temp-draft-folder
+      (setf temp-draft-folder (coerce-folder-name temp-draft-folder))
+      (message "Deleting and expunging temporary drafts ...")
+      (when (mh "rmm" (list temp-draft-folder "all") :errorp nil)
+	(let (hdrs)
+	  (declare (list hdrs))
+	  (do-headers-buffers (b temp-draft-folder)
+	    (push b hdrs))
+	  (dolist (b hdrs)
+	    (delete-headers-buffer-and-message-buffers-command nil b)))))))
+
+
+
+
+;;;; Message Mode.
+
+(defmode "Message" :major-p t)
+
+(defhvar "Message Information"
+  "This holds the information about the current message buffer."
+  :value nil)
+
+(defstruct message/draft-info
+  headers-mark)		;Mark pointing to a headers line in a headers buffer.
+
+(defstruct (message-info (:include message/draft-info)
+			 (:print-function print-message-info))
+  folder		;String name of folder with leading MH "+".
+  msgs			;List of strings representing messages to be shown.
+  draft-buf		;Possible draft buffer reference.
+  keep)			;Whether message buffer may be re-used.
+
+(defun print-message-info (obj str n)
+  (declare (ignore n))
+  (format str "#<Message Info ~S ~S>"
+	  (message-info-folder obj) (message-info-msgs obj)))
+
+
+(defcommand "Next Message" (p)
+  "Show the next message.
+   When in a message buffer, shows the next message in the associated headers
+   buffer.  When in a headers buffer, moves point down a line and shows that
+   message."
+  "When in a message buffer, shows the next message in the associated headers
+   buffer.  When in a headers buffer, moves point down a line and shows that
+   message."
+  (declare (ignore p))
+  (show-message-offset 1))
+
+(defcommand "Previous Message" (p)
+  "Show the previous message.
+   When in a message buffer, shows the previous message in the associated
+   headers buffer.  When in a headers buffer, moves point up a line and shows
+   that message."
+  "When in a message buffer, shows the previous message in the associated
+   headers buffer.  When in a headers buffer, moves point up a line and
+   shows that message."
+  (declare (ignore p))
+  (show-message-offset -1))
+
+(defcommand "Next Undeleted Message" (p)
+  "Show the next undeleted message.
+   When in a message buffer, shows the next undeleted message in the associated
+   headers buffer.  When in a headers buffer, moves point down to a line
+   without a deleted message and shows that message."
+  "When in a message buffer, shows the next undeleted message in the associated
+   headers buffer.  When in a headers buffer, moves point down to a line without
+   a deleted message and shows that message."
+  (declare (ignore p))
+  (show-message-offset 1 :undeleted))
+
+(defcommand "Previous Undeleted Message" (p)
+  "Show the previous undeleted message.
+   When in a message buffer, shows the previous undeleted message in the
+   associated headers buffer.  When in a headers buffer, moves point up a line
+   without a deleted message and shows that message."
+  "When in a message buffer, shows the previous undeleted message in the
+   associated headers buffer.  When in a headers buffer, moves point up a line
+   without a deleted message and shows that message."
+  (declare (ignore p))
+  (show-message-offset -1 :undeleted))
+
+(defun show-message-offset (offset &optional undeleted)
+  (let ((minfo (value message-information)))
+    (cond
+     ((not minfo)
+      (let ((hinfo (value headers-information)))
+	(unless hinfo (editor-error "Not in a message or headers buffer."))
+	(show-message-offset-hdrs-buf hinfo offset undeleted)))
+     ((message-info-keep minfo)
+      (let ((hbuf (value headers-buffer)))
+	(unless hbuf (editor-error "Not associated with a headers buffer."))
+	(let ((hinfo (variable-value 'headers-information :buffer hbuf))
+	      (point (buffer-point hbuf)))
+	  (move-mark point (message-info-headers-mark minfo))
+	  (show-message-offset-hdrs-buf hinfo offset undeleted))))
+     (t
+      (show-message-offset-msg-buf minfo offset undeleted)))))
+
+(defun show-message-offset-hdrs-buf (hinfo offset undeleted)
+  (unless hinfo (editor-error "Not in a message or headers buffer."))
+  (unless (show-message-offset-mark (buffer-point (headers-info-buffer hinfo))
+				    offset undeleted)
+    (editor-error "No ~:[previous~;next~] ~:[~;undeleted ~]message."
+		  (plusp offset) undeleted))
+  (show-headers-message hinfo))
+
+(defun show-message-offset-msg-buf (minfo offset undeleted)
+  (let ((msg-mark (message-info-headers-mark minfo)))
+    (unless msg-mark (editor-error "Not associated with a headers buffer."))
+    (unless (show-message-offset-mark msg-mark offset undeleted)
+      (let ((hbuf (value headers-buffer))
+	    (mbuf (current-buffer)))
+	(setf (current-buffer) hbuf)
+	(setf (window-buffer (current-window)) hbuf)
+	(delete-buffer-if-possible mbuf))
+      (editor-error "No ~:[previous~;next~] ~:[~;undeleted ~]message."
+		    (plusp offset) undeleted))
+    (move-mark (buffer-point (line-buffer (mark-line msg-mark))) msg-mark)
+    (let* ((next-msg (line-message-id (mark-line msg-mark)))
+	   (folder (message-info-folder minfo))
+	   (mbuffer (current-buffer)))
+      (with-writable-buffer (mbuffer)
+	(delete-region (buffer-region mbuffer))
+	(setf (buffer-name mbuffer) (get-storable-msg-buf-name folder next-msg))
+	(setf (message-info-msgs minfo) next-msg)
+	(read-mh-file (merge-pathnames next-msg
+				       (merge-relative-pathnames
+					(strip-folder-name folder)
+					(mh-directory-pathname)))
+		      mbuffer)
+	(let ((unseen-seq (mh-profile-component "unseen-sequence")))
+	  (when unseen-seq
+	    (mark-one-message folder next-msg unseen-seq :delete))))))
+  (let ((dbuffer (message-info-draft-buf minfo)))
+    (when dbuffer
+      (delete-variable 'message-buffer :buffer dbuffer)
+      (setf (message-info-draft-buf minfo) nil))))
+
+(defun get-storable-msg-buf-name (folder msg)
+  (let ((name (format nil "Message ~A ~A" folder msg)))
+    (if (not (getstring name *buffer-names*))
+	name
+	(let ((n 2))
+	  (loop
+	    (setf name (format nil "Message ~A ~A copy ~D" folder msg n))
+	    (unless (getstring name *buffer-names*)
+	      (return name))
+	    (incf n))))))
+
+(defun show-message-offset-mark (msg-mark offset undeleted)
+  (with-mark ((temp msg-mark))
+    (let ((winp 
+	   (cond (undeleted
+		  (loop
+		    (unless (and (line-offset temp offset 0)
+				 (not (blank-line-p (mark-line temp))))
+		      (return nil))
+		    (unless (line-message-deleted (mark-line temp))
+		      (return t))))
+		 ((and (line-offset temp offset 0)
+		       (not (blank-line-p (mark-line temp)))))
+		 (t nil))))
+      (if winp (move-mark msg-mark temp)))))
+
+
+(defcommand "Show Message" (p)
+  "Shows the current message.
+   Prompts for a folder and message(s), displaying this in the current window.
+   When invoked in a headers buffer, shows the message on the current line."
+  "Show a message."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information)))
+    (if hinfo
+	(show-headers-message hinfo)
+	(let ((folder (prompt-for-folder)))
+	  (show-prompted-message folder (prompt-for-message :folder folder))))))
+
+;;; SHOW-HEADERS-MESSAGE shows the current message for hinfo.  If there is a
+;;; main message buffer, clobber it, and we don't have to deal with kept
+;;; messages or draft associations since those operations should have moved
+;;; the message buffer into the others list.  Remove the message from the
+;;; unseen sequence, and make sure the message buffer is displayed in some
+;;; window.
+;;;
+(defun show-headers-message (hinfo)
+  (multiple-value-bind (cur-msg cur-mark)
+		       (headers-current-message hinfo)
+    (unless cur-msg (editor-error "Not on a header line."))
+    (let* ((mbuffer (headers-info-msg-buffer hinfo))
+	   (folder (headers-info-folder hinfo))
+	   (buf-name (get-storable-msg-buf-name folder cur-msg))
+	   (writable nil))
+      (cond (mbuffer
+	     (setf (buffer-name mbuffer) buf-name)
+	     (setf writable (buffer-writable mbuffer))
+	     (setf (buffer-writable mbuffer) t)
+	     (delete-region (buffer-region mbuffer))
+	     (let ((minfo (variable-value 'message-information :buffer mbuffer)))
+	       (move-mark (message-info-headers-mark minfo) cur-mark)
+	       (delete-mark cur-mark)
+	       (setf (message-info-msgs minfo) cur-msg)))
+	    (t (setf mbuffer (maybe-make-mh-buffer buf-name :message))
+	       (setf (headers-info-msg-buffer hinfo) mbuffer)
+	       (defhvar "Message Information"
+		 "This holds the information about the current headers buffer."
+		 :value (make-message-info :folder folder
+					   :msgs cur-msg
+					   :headers-mark cur-mark)
+		 :buffer mbuffer)
+	       (defhvar "Headers Buffer"
+		 "This is bound in message and draft buffers to their
+		  associated headers buffer."
+		 :value (headers-info-buffer hinfo) :buffer mbuffer)))
+      (read-mh-file (merge-pathnames
+		     cur-msg
+		     (merge-relative-pathnames (strip-folder-name folder)
+					       (mh-directory-pathname)))
+		    mbuffer)
+      (setf (buffer-writable mbuffer) writable)
+      (let ((unseen-seq (mh-profile-component "unseen-sequence")))
+	(when unseen-seq (mark-one-message folder cur-msg unseen-seq :delete)))
+      (get-message-buffer-window mbuffer))))
+    
+;;; SHOW-PROMPTED-MESSAGE takes an arbitrary message spec and blasts those
+;;; messages into a message buffer.  First we pick the message to get them
+;;; individually specified as normalized message ID's -- all integers and
+;;; no funny names such as "last".
+;;;
+(defun show-prompted-message (folder msgs)
+  (let* ((msgs (pick-messages folder msgs nil))
+	 (mbuffer (maybe-make-mh-buffer (format nil "Message ~A ~A" folder msgs)
+					:message)))
+    (defhvar "Message Information"
+      "This holds the information about the current headers buffer."
+      :value (make-message-info :folder folder :msgs msgs)
+      :buffer mbuffer)
+    (let ((*standard-output* (make-hemlock-output-stream (buffer-point mbuffer)
+							 :full)))
+      (mh "show" `(,folder ,@msgs "-noshowproc" "-noheader"))
+      (setf (buffer-modified mbuffer) nil))
+    (buffer-start (buffer-point mbuffer))
+    (setf (buffer-writable mbuffer) nil)
+    (get-message-buffer-window mbuffer)))
+
+;;; GET-MESSAGE-BUFFER-WINDOW currently just changes to buffer, unless buffer
+;;; has any windows, in which case it uses the first one.  It could prompt for
+;;; a window, split the current window, split the current window or use the
+;;; next one if there is one, funcall an Hvar.  It could take a couple
+;;; arguments to control its behaviour.  Whatever.
+;;;
+(defun get-message-buffer-window (mbuffer)
+  (let ((wins (buffer-windows mbuffer)))
+    (cond (wins
+	   (setf (current-buffer) mbuffer)
+	   (setf (current-window) (car wins)))
+	  (t (change-to-buffer mbuffer)))))
+
+
+(defhvar "Scroll Message Showing Next"
+  "When this is set, \"Scroll Message\" shows the next message when the end
+   of the current message is visible."
+  :value t)
+
+(defcommand "Scroll Message" (p)
+  "Scroll the current window down through the current message.
+   If the end of the message is visible, then show the next undeleted message
+   if \"Scroll Message Showing Next\" is non-nil."
+  "Scroll the current window down through the current message."
+  (if (and (not p)
+	   (displayed-p (buffer-end-mark (current-buffer)) (current-window))
+	   (value scroll-message-showing-next))
+      (show-message-offset 1 :undeleted)
+      (scroll-window-down-command p)))
+
+
+(defcommand "Keep Message" (p)
+  "Keeps the current message buffer from being re-used.  Also, if the buffer
+   would be deleted due to a draft completion, it will not be."
+  "Keeps the current message buffer from being re-used.  Also, if the buffer
+   would be deleted due to a draft completion, it will not be."
+  (declare (ignore p))
+  (let ((minfo (value message-information)))
+    (unless minfo (editor-error "Not in a message buffer."))
+    (let ((hbuf (value headers-buffer)))
+      (when hbuf
+	(let ((mbuf (current-buffer))
+	      (hinfo (variable-value 'headers-information :buffer hbuf)))
+	  (when (eq (headers-info-msg-buffer hinfo) mbuf)
+	    (setf (headers-info-msg-buffer hinfo) nil)
+	    (push mbuf (headers-info-other-msg-bufs hinfo))))))
+    (setf (message-info-keep minfo) t)))
+
+(defcommand "Edit Message Buffer" (p)
+  "Recursively edit message buffer.
+   Puts the current message buffer into \"Text\" mode allowing modifications in
+   a recursive edit.  While in this state, the buffer is associated with the
+   pathname of the message, so saving the file is possible."
+  "Puts the current message buffer into \"Text\" mode allowing modifications in
+   a recursive edit.  While in this state, the buffer is associated with the
+   pathname of the message, so saving the file is possible."
+  (declare (ignore p))
+  (let* ((minfo (value message-information)))
+    (unless minfo (editor-error "Not in a message buffer."))
+    (let* ((msgs (message-info-msgs minfo))
+	   (mbuf (current-buffer))
+	   (mbuf-name (buffer-name mbuf))
+	   (writable (buffer-writable mbuf))
+	   (abortp t))
+      (when (consp msgs)
+	(editor-error
+	 "There appears to be more than one message in this buffer."))
+      (unwind-protect
+	  (progn
+	    (setf (buffer-writable mbuf) t)
+	    (setf (buffer-pathname mbuf)
+		  (merge-pathnames
+		   msgs
+		   (merge-relative-pathnames
+		    (strip-folder-name (message-info-folder minfo))
+		    (mh-directory-pathname))))
+	    (setf (buffer-major-mode mbuf) "Text")
+	    (do-recursive-edit)
+	    (setf abortp nil))
+	(when (and (not abortp)
+		   (buffer-modified mbuf)
+		   (prompt-for-y-or-n
+		    :prompt "Message buffer modified, save it? "
+		    :default t))
+	  (save-file-command nil mbuf))
+	(setf (buffer-modified mbuf) nil)
+	;; "Save File", which the user may have used, changes the buffer's name.
+	(unless (getstring mbuf-name *buffer-names*)
+	  (setf (buffer-name mbuf) mbuf-name))
+	(setf (buffer-writable mbuf) writable)
+	(setf (buffer-pathname mbuf) nil)
+	(setf (buffer-major-mode mbuf) "Message")))))
+
+
+
+
+;;;; Draft Mode.
+
+(defmode "Draft")
+
+(defhvar "Draft Information"
+  "This holds the information about the current draft buffer."
+  :value nil)
+
+(defstruct (draft-info (:include message/draft-info)
+		       (:print-function print-draft-info))
+  folder		;String name of draft folder with leading MH "+".
+  message		;String id of draft folder message.
+  pathname		;Pathname of draft in the draft folder directory.
+  delivered		;This is set when the draft was really sent.
+  replied-to-folder	;Folder of message draft is in reply to.
+  replied-to-msg)	;Message draft is in reply to.
+
+(defun print-draft-info (obj str n)
+  (declare (ignore n))
+  (format str "#<Draft Info ~A>" (draft-info-message obj)))
+
+
+(defhvar "Reply to Message Prefix Action"
+  "This is one of :cc-all, :no-cc-all, or nil.  When an argument is supplied to
+   \"Reply to Message\", this value determines how arguments passed to the
+   MH utility."
+  :value nil)
+
+(defcommand "Reply to Message" (p)
+  "Sets up a draft in reply to the current message.
+   Prompts for a folder and message to reply to.  When in a headers buffer,
+   replies to the message on the current line.  When in a message buffer,
+   replies to that message.  With an argument, regard \"Reply to Message Prefix
+   Action\" for carbon copy arguments to the MH utility."
+  "Prompts for a folder and message to reply to.  When in a headers buffer,
+   replies to the message on the current line.  When in a message buffer,
+   replies to that message."
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (setup-reply-draft (headers-info-folder hinfo)
+				cur-msg hinfo cur-mark p)))
+	  (minfo
+	   (setup-message-buffer-draft (current-buffer) minfo :reply p))
+	  (t
+	   (let ((folder (prompt-for-folder)))
+	     (setup-reply-draft folder
+				(car (prompt-for-message :folder folder))
+				nil nil p))))))
+
+;;; SETUP-REPLY-DRAFT takes a folder and msg to draft a reply to.  Optionally,
+;;; a headers buffer and mark are associated with the draft.  First, the draft
+;;; buffer is associated with the headers buffer if there is one.  Then the
+;;; message buffer is created and associated with the drafter buffer and
+;;; headers buffer.  Argument may be used to pass in the argument from the
+;;; command.
+;;;
+(defun setup-reply-draft (folder msg &optional hinfo hmark argument)
+  (let* ((dbuffer (sub-setup-message-draft
+		   "repl" :end-of-buffer
+		   `(,folder ,msg
+			     ,@(if argument
+				   (case (value reply-to-message-prefix-action)
+				     (:no-cc-all '("-nocc" "all"))
+				     (:cc-all '("-cc" "all")))))))
+	 (dinfo (variable-value 'draft-information :buffer dbuffer))
+	 (h-buf (if hinfo (headers-info-buffer hinfo))))
+    (setf (draft-info-replied-to-folder dinfo) folder)
+    (setf (draft-info-replied-to-msg dinfo) msg)
+    (when h-buf
+      (defhvar "Headers Buffer"
+	"This is bound in message and draft buffers to their associated
+	headers buffer."
+	:value h-buf :buffer dbuffer)
+      (setf (draft-info-headers-mark dinfo) hmark)
+      (push dbuffer (headers-info-draft-bufs hinfo)))
+    (let ((msg-buf (maybe-make-mh-buffer (format nil "Message ~A ~A" folder msg)
+					 :message)))
+      (defhvar "Message Information"
+	"This holds the information about the current headers buffer."
+	:value (make-message-info :folder folder :msgs msg
+				  :headers-mark
+				  (if h-buf (copy-mark hmark) hmark)
+				  :draft-buf dbuffer)
+	:buffer msg-buf)
+      (when h-buf
+	(defhvar "Headers Buffer"
+	  "This is bound in message and draft buffers to their associated
+	  headers buffer."
+	  :value h-buf :buffer msg-buf)
+	(push msg-buf (headers-info-other-msg-bufs hinfo)))
+      (read-mh-file (merge-pathnames
+		     msg
+		     (merge-relative-pathnames (strip-folder-name folder)
+					       (mh-directory-pathname)))
+		    msg-buf)
+      (setf (buffer-writable msg-buf) nil)
+      (defhvar "Message Buffer"
+	"This is bound in draft buffers to their associated message buffer."
+	:value msg-buf :buffer dbuffer))
+    (get-draft-buffer-window dbuffer)))
+
+
+(defcommand "Forward Message" (p)
+  "Forward current message.
+   Prompts for a folder and message to forward.  When in a headers buffer,
+   forwards the message on the current line.  When in a message buffer,
+   forwards that message."
+  "Prompts for a folder and message to reply to.  When in a headers buffer,
+   replies to the message on the current line.  When in a message buffer,
+   replies to that message."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (setup-forward-draft (headers-info-folder hinfo)
+				  cur-msg hinfo cur-mark)))
+	  (minfo
+	   (setup-message-buffer-draft (current-buffer) minfo :forward))
+	  (t
+	   (let ((folder (prompt-for-folder)))
+	     (setup-forward-draft folder
+				  (car (prompt-for-message :folder folder))))))))
+
+;;; SETUP-FORWARD-DRAFT sets up a draft forwarding folder's msg.  When there
+;;; is a headers buffer involved (hinfo and hmark), the draft is associated
+;;; with it.
+;;;
+;;; This function is like SETUP-REPLY-DRAFT (in addition to "forw" and
+;;; :to-field), but it does not setup a message buffer.  If this is added as
+;;; something forward drafts want, then SETUP-REPLY-DRAFT should be
+;;; parameterized and renamed.
+;;;
+(defun setup-forward-draft (folder msg &optional hinfo hmark)
+  (let* ((dbuffer (sub-setup-message-draft "forw" :to-field
+					   (list folder msg)))
+	 (dinfo (variable-value 'draft-information :buffer dbuffer))
+	 (h-buf (if hinfo (headers-info-buffer hinfo))))
+    (when h-buf
+      (defhvar "Headers Buffer"
+	"This is bound in message and draft buffers to their associated
+	headers buffer."
+	:value h-buf :buffer dbuffer)
+      (setf (draft-info-headers-mark dinfo) hmark)
+      (push dbuffer (headers-info-draft-bufs hinfo)))
+    (get-draft-buffer-window dbuffer)))
+
+
+(defcommand "Send Message" (p)
+  "Setup a draft buffer.
+   Setup a draft buffer, reserving a draft folder message.  When invoked in a
+   headers buffer, the current message is available in an associated message
+   buffer."
+  "Setup a draft buffer, reserving a draft folder message.  When invoked in
+   a headers buffer, the current message is available in an associated
+   message buffer."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo (setup-headers-message-draft hinfo))
+	  (minfo (setup-message-buffer-draft (current-buffer) minfo :compose))
+	  (t (setup-message-draft)))))
+
+(defun setup-message-draft ()
+  (get-draft-buffer-window (sub-setup-message-draft "comp" :to-field)))
+
+;;; SETUP-HEADERS-MESSAGE-DRAFT sets up a draft buffer associated with a
+;;; headers buffer and a message buffer.  The headers current message is
+;;; inserted in the message buffer which is also associated with the headers
+;;; buffer.  The draft buffer is associated with the message buffer.
+;;;
+(defun setup-headers-message-draft (hinfo)
+  (multiple-value-bind (cur-msg cur-mark)
+		       (headers-current-message hinfo)
+    (unless cur-msg (message "Draft not associated with any message."))
+    (let* ((dbuffer (sub-setup-message-draft "comp" :to-field))
+	   (dinfo (variable-value 'draft-information :buffer dbuffer))
+	   (h-buf (headers-info-buffer hinfo)))
+      (when cur-msg
+	(defhvar "Headers Buffer"
+	  "This is bound in message and draft buffers to their associated headers
+	  buffer."
+	  :value h-buf :buffer dbuffer)
+	(push dbuffer (headers-info-draft-bufs hinfo)))
+      (when cur-msg
+	(setf (draft-info-headers-mark dinfo) cur-mark)
+	(let* ((folder (headers-info-folder hinfo))
+	       (msg-buf (maybe-make-mh-buffer
+			 (format nil "Message ~A ~A" folder cur-msg)
+			 :message)))
+	  (defhvar "Message Information"
+	    "This holds the information about the current headers buffer."
+	    :value (make-message-info :folder folder :msgs cur-msg
+				      :headers-mark (copy-mark cur-mark)
+				      :draft-buf dbuffer)
+	    :buffer msg-buf)
+	  (defhvar "Headers Buffer"
+	    "This is bound in message and draft buffers to their associated
+	     headers buffer."
+	    :value h-buf :buffer msg-buf)
+	  (push msg-buf (headers-info-other-msg-bufs hinfo))
+	  (read-mh-file (merge-pathnames
+			 cur-msg
+			 (merge-relative-pathnames (strip-folder-name folder)
+						   (mh-directory-pathname)))
+			msg-buf)
+	  (setf (buffer-writable msg-buf) nil)
+	  (defhvar "Message Buffer"
+	    "This is bound in draft buffers to their associated message buffer."
+	    :value msg-buf :buffer dbuffer)))
+      (get-draft-buffer-window dbuffer))))
+
+;;; SETUP-MESSAGE-BUFFER-DRAFT takes a message buffer and its message
+;;; information.  A draft buffer is created according to type, and the two
+;;; buffers are associated.  Any previous association of the message buffer and
+;;; a draft buffer is dropped.  Any association between the message buffer and
+;;; a headers buffer is propagated to the draft buffer, and if the message
+;;; buffer is the headers buffer's main message buffer, it is moved to "other"
+;;; status.  Argument may be used to pass in the argument from the command.
+;;;
+(defun setup-message-buffer-draft (msg-buf minfo type &optional argument)
+  (let* ((msgs (message-info-msgs minfo))
+	 (cur-msg (if (consp msgs) (car msgs) msgs))
+	 (folder (message-info-folder minfo))
+	 (dbuffer
+	  (ecase type
+	    (:reply
+	     (sub-setup-message-draft
+	      "repl" :end-of-buffer
+	      `(,folder ,cur-msg
+			,@(if argument
+			      (case (value reply-to-message-prefix-action)
+				(:no-cc-all '("-nocc" "all"))
+				(:cc-all '("-cc" "all")))))))
+	    (:compose
+	     (sub-setup-message-draft "comp" :to-field))
+	    (:forward
+	     (sub-setup-message-draft "forw" :to-field
+				      (list folder cur-msg)))))
+	 (dinfo (variable-value 'draft-information :buffer dbuffer)))
+    (when (message-info-draft-buf minfo)
+      (delete-variable 'message-buffer :buffer (message-info-draft-buf minfo)))
+    (setf (message-info-draft-buf minfo) dbuffer)
+    (when (eq type :reply)
+      (setf (draft-info-replied-to-folder dinfo) folder)
+      (setf (draft-info-replied-to-msg dinfo) cur-msg))
+    (when (hemlock-bound-p 'headers-buffer :buffer msg-buf)
+      (let* ((hbuf (variable-value 'headers-buffer :buffer msg-buf))
+	     (hinfo (variable-value 'headers-information :buffer hbuf)))
+	(defhvar "Headers Buffer"
+	  "This is bound in message and draft buffers to their associated
+	  headers buffer."
+	  :value hbuf :buffer dbuffer)
+	(setf (draft-info-headers-mark dinfo)
+	      (copy-mark (message-info-headers-mark minfo)))
+	(push dbuffer (headers-info-draft-bufs hinfo))
+	(when (eq (headers-info-msg-buffer hinfo) msg-buf)
+	  (setf (headers-info-msg-buffer hinfo) nil)
+	  (push msg-buf (headers-info-other-msg-bufs hinfo)))))
+    (defhvar "Message Buffer"
+      "This is bound in draft buffers to their associated message buffer."
+      :value msg-buf :buffer dbuffer)
+    (get-draft-buffer-window dbuffer)))
+
+(defvar *draft-to-pattern*
+  (new-search-pattern :string-insensitive :forward "To:"))
+
+(defun sub-setup-message-draft (utility point-action &optional args)
+  (mh utility `(,@args "-nowhatnowproc"))
+  (let* ((folder (mh-draft-folder))
+	 (draft-msg (mh-current-message folder))
+	 (msg-pn (merge-pathnames draft-msg (mh-draft-folder-pathname)))
+	 (dbuffer (maybe-make-mh-buffer (format nil "Draft ~A" draft-msg)
+				     :draft)))
+    (read-mh-file msg-pn dbuffer)
+    (setf (buffer-pathname dbuffer) msg-pn)
+    (defhvar "Draft Information"
+      "This holds the information about the current draft buffer."
+      :value (make-draft-info :folder (coerce-folder-name folder)
+			      :message draft-msg
+			      :pathname msg-pn)
+      :buffer dbuffer)
+    (let ((point (buffer-point dbuffer)))
+      (ecase point-action
+	(:to-field
+	 (when (find-pattern point *draft-to-pattern*)
+	   (line-end point)))
+	(:end-of-buffer (buffer-end point))))
+    dbuffer))
+
+(defun read-mh-file (pathname buffer)
+  (unless (probe-file pathname)
+    (editor-error "No such message -- ~A" (namestring pathname)))
+  (read-file pathname (buffer-point buffer))
+  (setf (buffer-write-date buffer) (file-write-date pathname))
+  (buffer-start (buffer-point buffer))
+  (setf (buffer-modified buffer) nil))
+
+
+(defvar *draft-buffer-window-fun* 'change-to-buffer
+  "This is called by GET-DRAFT-BUFFER-WINDOW to display a new draft buffer.
+   The default is CHANGE-TO-BUFFER which uses the current window.")
+
+;;; GET-DRAFT-BUFFER-WINDOW is called to display a new draft buffer.
+;;;
+(defun get-draft-buffer-window (dbuffer)
+  (funcall *draft-buffer-window-fun* dbuffer))
+
+
+(defcommand "Reply to Message in Other Window" (p)
+  "Reply to message, creating another window for draft buffer.
+   Prompts for a folder and message to reply to.  When in a headers buffer,
+   replies to the message on the current line.  When in a message buffer,
+   replies to that message.  The current window is split displaying the draft
+   buffer in the new window and the message buffer in the current."
+  "Prompts for a folder and message to reply to.  When in a headers buffer,
+   replies to the message on the current line.  When in a message buffer,
+   replies to that message."
+  (let ((*draft-buffer-window-fun* #'draft-buffer-in-other-window))
+    (reply-to-message-command p)))
+
+(defun draft-buffer-in-other-window (dbuffer)
+  (when (hemlock-bound-p 'message-buffer :buffer dbuffer)
+    (let ((mbuf (variable-value 'message-buffer :buffer dbuffer)))
+      (when (not (eq (current-buffer) mbuf))
+	(change-to-buffer mbuf))))
+  (setf (current-buffer) dbuffer)
+  (setf (current-window) (make-window (buffer-start-mark dbuffer)))
+  (defhvar "Split Window Draft"
+    "Indicates window needs to be cleaned up for draft."
+    :value t :buffer dbuffer))
+
+(defhvar "Deliver Message Confirm"
+  "When set, \"Deliver Message\" will ask for confirmation before sending the
+   draft.  This is off by default since \"Deliver Message\" is not bound to
+   any key by default."
+  :value t)
+
+(defcommand "Deliver Message" (p)
+  "Save and deliver the current draft buffer.
+   When in a draft buffer, this saves the file and uses SEND to deliver the
+   draft.  Otherwise, this prompts for a draft message id, invoking SEND."
+  "When in a draft buffer, this saves the file and uses SEND to deliver the
+   draft.  Otherwise, this prompts for a draft message id, invoking SEND."
+  (declare (ignore p))
+  (let ((dinfo (value draft-information)))
+    (cond (dinfo
+	   (deliver-draft-buffer-message dinfo))
+	  (t
+	   (let* ((folder (coerce-folder-name (mh-draft-folder)))
+		  (msg (prompt-for-message :folder folder)))
+	     (mh "send" `("-draftfolder" ,folder "-draftmessage" ,@msg)))))))
+
+(defun deliver-draft-buffer-message (dinfo)
+  (when (draft-info-delivered dinfo)
+    (editor-error "This draft has already been delivered."))
+  (when (or (not (value deliver-message-confirm))
+	    (prompt-for-y-or-n :prompt "Deliver message? " :default t))
+    (let ((dbuffer (current-buffer)))
+      (when (buffer-modified dbuffer)
+	(write-buffer-file dbuffer (buffer-pathname dbuffer)))
+      (message "Delivering draft ...")
+      (mh "send" `("-draftfolder" ,(draft-info-folder dinfo)
+		   "-draftmessage" ,(draft-info-message dinfo)))
+      (setf (draft-info-delivered dinfo) t)
+      (let ((replied-folder (draft-info-replied-to-folder dinfo))
+	    (replied-msg (draft-info-replied-to-msg dinfo)))
+	(when replied-folder
+	  (message "Annotating message being replied to ...")
+	  (mh "anno" `(,replied-folder ,replied-msg "-component" "replied"))
+	  (do-headers-buffers (hbuf replied-folder)
+	    (with-headers-mark (hmark hbuf replied-msg)
+	      (mark-to-note-replied-msg hmark)
+	      (with-writable-buffer (hbuf)
+		(setf (next-character hmark) #\A))))
+	  (dolist (b *buffer-list*)
+	    (when (and (hemlock-bound-p 'message-information :buffer b)
+		       (buffer-modeline-field-p b :replied-to-message))
+	      (dolist (w (buffer-windows b))
+		(update-modeline-field b w :replied-to-message))))))
+      (maybe-delete-extra-draft-window dbuffer (current-window))
+      (let ((mbuf (value message-buffer)))
+	(when (and mbuf
+		   (not (hemlock-bound-p 'netnews-message-info :buffer mbuf)))
+	  (let ((minfo (variable-value 'message-information :buffer mbuf)))
+	    (when (and minfo (not (message-info-keep minfo)))
+	      (delete-buffer-if-possible mbuf)))))
+      (delete-buffer-if-possible dbuffer))))
+
+(defcommand "Delete Draft and Buffer" (p)
+  "Delete the current draft and associated message and buffer."
+  "Delete the current draft and associated message and buffer."
+  (declare (ignore p))
+  (let ((dinfo (value draft-information))
+	(dbuffer (current-buffer)))
+    (unless dinfo (editor-error "No draft associated with buffer."))
+    (maybe-delete-extra-draft-window dbuffer (current-window))
+    (delete-file (draft-info-pathname dinfo))
+    (let ((mbuf (value message-buffer)))
+      (when (and mbuf
+		 (not (hemlock-bound-p 'netnews-message-info :buffer mbuf)))
+	(let ((minfo (variable-value 'message-information :buffer mbuf)))
+	  (when (and minfo (not (message-info-keep minfo)))
+	    (delete-buffer-if-possible mbuf)))))
+    (delete-buffer-if-possible dbuffer)))    
+
+;;; MAYBE-DELETE-EXTRA-DRAFT-WINDOW -- Internal.
+;;;
+;;; This takes a draft buffer and a window into it that should not be deleted.
+;;; If "Split Window Draft" is bound in the buffer, and there are at least two
+;;; windows in dbuffer-window's group, then we delete some window.  Blow away
+;;; the variable, so we don't think this is still a split window draft buffer.
+;;;
+(defun maybe-delete-extra-draft-window (dbuffer dbuffer-window)
+  (when (and (hemlock-bound-p 'split-window-draft :buffer dbuffer)
+	     ;; Since we know bitmap devices have window groups, this loop is
+	     ;; more correct than testing the length of *window-list* and
+	     ;; accounting for *echo-area-window* being in there.
+	     (do ((start dbuffer-window)
+		  (count 1 (1+ count))
+		  (w (next-window dbuffer-window) (next-window w)))
+		 ((eq start w) (> count 1))))
+    (delete-window (next-window dbuffer-window))
+    (delete-variable 'split-window-draft :buffer dbuffer)))
+
+(defcommand "Remail Message" (p)
+  "Prompts for a folder and message to remail.  Prompts for a resend-to
+   address string and resend-cc address string.  When in a headers buffer,
+   remails the message on the current line.  When in a message buffer,
+   remails that message."
+  "Prompts for a folder and message to remail.  Prompts for a resend-to
+   address string and resend-cc address string.  When in a headers buffer,
+   remails the message on the current line.  When in a message buffer,
+   remails that message."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (delete-mark cur-mark)
+	     (remail-message (headers-info-folder hinfo) cur-msg
+			     (prompt-for-string :prompt "Resend To: ")
+			     (prompt-for-string :prompt "Resend Cc: "))))
+	  (minfo
+	   (remail-message (message-info-folder minfo)
+			   (message-info-msgs minfo)
+			   (prompt-for-string :prompt "Resend To: ")
+			   (prompt-for-string :prompt "Resend Cc: ")))
+	  (t
+	   (let ((folder (prompt-for-folder)))
+	     (remail-message folder
+			     (car (prompt-for-message :folder folder))
+			     (prompt-for-string :prompt "Resend To: ")
+			     (prompt-for-string :prompt "Resend Cc: "))))))
+  (message "Message remailed."))
+
+
+;;; REMAIL-MESSAGE claims a draft folder message with "dist".  This is then
+;;; sucked into a buffer and modified by inserting the supplied addresses.
+;;; "send" is used to deliver the draft, but it requires certain evironment
+;;; variables to make it do the right thing.  "mhdist" says the draft is only
+;;; remailing information, and "mhaltmsg" is the message to send.  "mhannotate"
+;;; must be set due to a bug in MH's "send"; it will not notice the "mhdist"
+;;; flag unless there is some message to be annotated.  This command does not
+;;; provide for annotation of the remailed message.
+;;;
+(defun remail-message (folder msg resend-to resend-cc)
+  (mh "dist" `(,folder ,msg "-nowhatnowproc"))
+  (let* ((draft-folder (mh-draft-folder))
+	 (draft-msg (mh-current-message draft-folder)))
+    (setup-remail-draft-message draft-msg resend-to resend-cc)
+    (mh "send" `("-draftfolder" ,draft-folder "-draftmessage" ,draft-msg)
+	:environment
+	`((:|mhdist| . "1")
+	  (:|mhannotate| . "1")
+	  (:|mhaltmsg| . ,(namestring
+			 (merge-pathnames msg (merge-relative-pathnames
+					       (strip-folder-name folder)
+					       (mh-directory-pathname)))))))))
+
+;;; SETUP-REMAIL-DRAFT-MESSAGE takes a draft folder and message that have been
+;;; created with the MH "dist" utility.  A buffer is created with this
+;;; message's pathname, searching for "resent-to:" and "resent-cc:", filling in
+;;; the supplied argument values.  After writing out the results, the buffer
+;;; is deleted.
+;;;
+(defvar *draft-resent-to-pattern*
+  (new-search-pattern :string-insensitive :forward "resent-to:"))
+(defvar *draft-resent-cc-pattern*
+  (new-search-pattern :string-insensitive :forward "resent-cc:"))
+
+(defun setup-remail-draft-message (msg resend-to resend-cc)
+  (let* ((msg-pn (merge-pathnames msg (mh-draft-folder-pathname)))
+	 (dbuffer (maybe-make-mh-buffer (format nil "Draft ~A" msg)
+					:draft))
+	 (point (buffer-point dbuffer)))
+    (read-mh-file msg-pn dbuffer)
+    (when (find-pattern point *draft-resent-to-pattern*)
+      (line-end point)
+      (insert-string point resend-to))
+    (buffer-start point)
+    (when (find-pattern point *draft-resent-cc-pattern*)
+      (line-end point)
+      (insert-string point resend-cc))
+    (write-file (buffer-region dbuffer) msg-pn :keep-backup nil)
+    ;; The draft buffer delete hook expects this to be bound.
+    (defhvar "Draft Information"
+      "This holds the information about the current draft buffer."
+      :value :ignore
+      :buffer dbuffer)
+    (delete-buffer dbuffer)))
+
+
+
+
+;;;; Message and Draft Stuff.
+
+(defhvar "Headers Buffer"
+  "This is bound in message and draft buffers to their associated headers
+   buffer."
+  :value nil)
+
+(defcommand "Goto Headers Buffer" (p)
+  "Selects associated headers buffer if it exists.
+   The headers buffer's point is moved to the appropriate line, pushing a
+   buffer mark where point was."
+  "Selects associated headers buffer if it exists."
+  (declare (ignore p))
+  (let ((h-buf (value headers-buffer)))
+    (unless h-buf (editor-error "No associated headers buffer."))
+    (let ((info (or (value message-information) (value draft-information))))
+      (change-to-buffer h-buf)
+      (push-buffer-mark (copy-mark (current-point)))
+      (move-mark (current-point) (message/draft-info-headers-mark info)))))
+
+(defhvar "Message Buffer"
+  "This is bound in draft buffers to their associated message buffer."
+  :value nil)
+
+(defcommand "Goto Message Buffer" (p)
+  "Selects associated message buffer if it exists."
+  "Selects associated message buffer if it exists."
+  (declare (ignore p))
+  (let ((msg-buf (value message-buffer)))
+    (unless msg-buf (editor-error "No associated message buffer."))
+    (change-to-buffer msg-buf)))
+
+
+(defhvar "Message Insertion Prefix"
+  "This is a fill prefix that is used when inserting text from a message buffer
+   into a draft buffer by \"Insert Message Region\".  It defaults to three
+   spaces."
+  :value "   ")
+
+(defhvar "Message Insertion Column"
+  "This is a fill column that is used when inserting text from a message buffer
+   into a draft buffer by \"Insert Message Region\"."
+  :value 75)
+
+(defcommand "Insert Message Region" (p)
+  "Copy the current region into the associated draft or post buffer.  When
+   in a message buffer that has an associated draft or post buffer, the
+   current active region is copied into the draft or post buffer.  It is
+   filled using \"Message Insertion Prefix\" and \"Message Insertion
+   Column\".  If an argument is supplied, the filling is inhibited.
+   If both a draft buffer and post buffer are associated with this, then it
+   is inserted into the draft buffer."
+  "When in a message buffer that has an associated draft or post buffer,
+   the current active region is copied into the post or draft buffer.  It is
+   filled using \"Message Insertion Prefix\" and \"Message Insertion
+   Column\".  If an argument is supplied, the filling is inhibited."
+  (let* ((minfo (value message-information))
+	 (nm-info (if (hemlock-bound-p 'netnews-message-info)
+		      (value netnews-message-info)))
+	 (post-buffer (and nm-info (nm-info-post-buffer nm-info)))
+	 (post-info (and post-buffer
+			 (variable-value 'post-info :buffer post-buffer)))
+	 dbuf kind)
+    (cond (minfo
+	   (setf kind :mail)
+	   (setf dbuf (message-info-draft-buf minfo)))
+	  (nm-info
+	   (setf kind :netnews)
+	   (setf dbuf (or (nm-info-draft-buffer nm-info)
+			  (nm-info-post-buffer nm-info))))
+	  (t (editor-error "Not in a netnews message or message buffer.")))
+    (unless dbuf
+      (editor-error "Message buffer not associated with any draft or post ~
+                     buffer."))
+    (let* ((region (copy-region (current-region)))
+	   (dbuf-point (buffer-point dbuf))
+	   (dbuf-mark (copy-mark dbuf-point)))
+      (cond ((and (eq kind :mail)
+		  (hemlock-bound-p 'split-window-draft :buffer dbuf)
+		  (> (length (the list *window-list*)) 2)
+		  (buffer-windows dbuf))
+	     (setf (current-buffer) dbuf
+		   (current-window) (car (buffer-windows dbuf))))
+	    ((and (eq kind :netnews)
+		  (and (member (post-info-message-window post-info)
+			       *window-list*)
+		       (member (post-info-reply-window post-info)
+			       *window-list*)))
+	     (setf (current-buffer) dbuf
+		   (current-window) (post-info-reply-window post-info)))
+	    (t (change-to-buffer dbuf)))
+      (push-buffer-mark dbuf-mark)
+      (ninsert-region dbuf-point region)
+      (unless p
+	(fill-region-by-paragraphs (region dbuf-mark dbuf-point)
+				   (value message-insertion-prefix)
+				   (value message-insertion-column)))))
+  (setf (last-command-type) :ephemerally-active))
+
+
+(defhvar "Message Buffer Insertion Prefix"
+  "This is a line prefix that is inserted at the beginning of every line in
+   a message buffer when inserting those lines into a draft buffer with
+   \"Insert Message Buffer\".  It defaults to four spaces."
+  :value "    ")
+
+(defcommand "Insert Message Buffer" (p)
+  "Insert entire (associated) message buffer into (associated) draft or
+   post buffer.  When in a draft or post buffer with an associated message
+   buffer, or when in a message buffer that has an associated draft or post
+   buffer, the message buffer is inserted into the draft buffer.  When
+   there are both an associated draft and post buffer, the text is inserted
+   into the draft buffer.  Each inserted line is modified by prefixing it
+   with \"Message Buffer Insertion Prefix\".  If an argument is supplied
+   the prefixing is inhibited."
+  "When in a draft or post buffer with an associated message buffer, or
+   when in a message buffer that has an associated draft or post buffer, the
+   message buffer is inserted into the draft buffer.  Each inserted line is
+   modified by prefixing it with \"Message Buffer Insertion Prefix\".  If an
+   argument is supplied the prefixing is inhibited."
+  (let ((minfo (value message-information))
+	(dinfo (value draft-information))
+	mbuf dbuf message-kind)
+    (cond (minfo
+	   (setf message-kind :mail)
+	   (setf dbuf (message-info-draft-buf minfo))
+	   (unless dbuf
+	     (editor-error
+	      "Message buffer not associated with any draft buffer."))
+	   (setf mbuf (current-buffer))
+	   (change-to-buffer dbuf))
+	  (dinfo
+	   (setf message-kind :mail)
+	   (setf mbuf (value message-buffer))
+	   (unless mbuf
+	     (editor-error
+	      "Draft buffer not associated with any message buffer."))
+	   (setf dbuf (current-buffer)))
+	  ((hemlock-bound-p 'netnews-message-info)
+	   (setf message-kind :netnews)
+	   (setf mbuf (current-buffer))
+	   (let ((nm-info (value netnews-message-info)))
+	     (setf dbuf (or (nm-info-draft-buffer nm-info)
+			    (nm-info-post-buffer nm-info)))
+	     (unless dbuf
+	       (editor-error "Message buffer not associated with any draft ~
+	       		      or post buffer.")))
+	   (change-to-buffer dbuf))
+	  ((hemlock-bound-p 'post-info)
+	   (setf message-kind :netnews)
+	   (let ((post-info (value post-info)))
+	     (setf mbuf (post-info-message-buffer post-info))
+	     (unless mbuf
+	       (editor-error "Post buffer not associated with any message ~
+	                      buffer.")))
+	   (setf dbuf (current-buffer)))
+	  (t (editor-error "Not in a draft, message, news-message, or post ~
+	                    buffer.")))	  
+    (let* ((dbuf-point (buffer-point dbuf))
+	   (dbuf-mark (copy-mark dbuf-point)))
+      (push-buffer-mark dbuf-mark)
+      (insert-region dbuf-point (buffer-region mbuf))
+      (unless p
+	(let ((prefix (value message-buffer-insertion-prefix)))
+	  (with-mark ((temp dbuf-mark :left-inserting))
+	    (loop
+	      (when (mark>= temp dbuf-point) (return))
+	      (insert-string temp prefix)
+	      (unless (line-offset temp 1 0) (return)))))))
+    (ecase message-kind
+      (:mail
+       (insert-message-buffer-cleanup-split-draft dbuf mbuf))
+      (:netnews 
+       (nn-reply-cleanup-split-windows dbuf))))
+  (setf (last-command-type) :ephemerally-active))
+
+;;; INSERT-MESSAGE-BUFFER-CLEANUP-SPLIT-DRAFT tries to delete an extra window
+;;; due to "Reply to Message in Other Window".  Since we just inserted the
+;;; message buffer in the draft buffer, we don't need the other window into
+;;; the message buffer.
+;;;
+(defun insert-message-buffer-cleanup-split-draft (dbuf mbuf)
+  (when (and (hemlock-bound-p 'split-window-draft :buffer dbuf)
+	     (> (length (the list *window-list*)) 2))
+    (let ((win (car (buffer-windows mbuf))))
+      (cond
+       (win
+	(when (eq win (current-window))
+	  (let ((dwin (car (buffer-windows dbuf))))
+	    (unless dwin
+	      (editor-error "Couldn't fix windows for split window draft."))
+	    (setf (current-buffer) dbuf)
+	    (setf (current-window) dwin)))
+	(delete-window win))
+       (t ;; This happens when invoked with the message buffer current.
+	(let ((dwins (buffer-windows dbuf)))
+	  (when (> (length (the list dwins)) 1)
+	    (delete-window (find-if #'(lambda (w)
+					(not (eq w (current-window))))
+				    dwins)))))))
+    (delete-variable 'split-window-draft :buffer dbuf)))
+
+
+;;; CLEANUP-MESSAGE-BUFFER is called when a buffer gets deleted.  It cleans
+;;; up references to a message buffer.
+;;; 
+(defun cleanup-message-buffer (buffer)
+  (let ((minfo (variable-value 'message-information :buffer buffer)))
+    (when (hemlock-bound-p 'headers-buffer :buffer buffer)
+      (let* ((hinfo (variable-value 'headers-information
+				    :buffer (variable-value 'headers-buffer
+							    :buffer buffer)))
+	     (msg-buf (headers-info-msg-buffer hinfo)))
+	(if (eq msg-buf buffer)
+	    (setf (headers-info-msg-buffer hinfo) nil)
+	    (setf (headers-info-other-msg-bufs hinfo)
+		  (delete buffer (headers-info-other-msg-bufs hinfo)
+			  :test #'eq))))
+      (delete-mark (message-info-headers-mark minfo))
+      ;;
+      ;; Do this for MAYBE-MAKE-MH-BUFFER since it isn't necessary for GC.
+      (delete-variable 'headers-buffer :buffer buffer))
+    (when (message-info-draft-buf minfo)
+      (delete-variable 'message-buffer
+		       :buffer (message-info-draft-buf minfo)))))
+
+;;; CLEANUP-DRAFT-BUFFER is called when a buffer gets deleted.  It cleans
+;;; up references to a draft buffer.
+;;;
+(defun cleanup-draft-buffer (buffer)
+  (let ((dinfo (variable-value 'draft-information :buffer buffer)))
+    (when (hemlock-bound-p 'headers-buffer :buffer buffer)
+      (let* ((hinfo (variable-value 'headers-information
+				    :buffer (variable-value 'headers-buffer
+							    :buffer buffer))))
+	(setf (headers-info-draft-bufs hinfo)
+	      (delete buffer (headers-info-draft-bufs hinfo) :test #'eq))
+	(delete-mark (draft-info-headers-mark dinfo))))
+    (when (hemlock-bound-p 'message-buffer :buffer buffer)
+      (setf (message-info-draft-buf
+	     (variable-value 'message-information
+			     :buffer (variable-value 'message-buffer
+						     :buffer buffer)))
+	    nil))))
+
+;;; CLEANUP-HEADERS-BUFFER is called when a buffer gets deleted.  It cleans
+;;; up references to a headers buffer.
+;;; 
+(defun cleanup-headers-buffer (buffer)
+  (let* ((hinfo (variable-value 'headers-information :buffer buffer))
+	 (msg-buf (headers-info-msg-buffer hinfo)))
+    (when msg-buf
+      (cleanup-headers-reference
+       msg-buf (variable-value 'message-information :buffer msg-buf)))
+    (dolist (b (headers-info-other-msg-bufs hinfo))
+      (cleanup-headers-reference
+       b (variable-value 'message-information :buffer b)))
+    (dolist (b (headers-info-draft-bufs hinfo))
+      (cleanup-headers-reference
+       b (variable-value 'draft-information :buffer b)))))
+
+(defun cleanup-headers-reference (buffer info)
+  (delete-mark (message/draft-info-headers-mark info))
+  (setf (message/draft-info-headers-mark info) nil)
+  (delete-variable 'headers-buffer :buffer buffer)
+  (when (typep info 'draft-info)
+    (setf (draft-info-replied-to-folder info) nil)
+    (setf (draft-info-replied-to-msg info) nil)))
+
+;;; REVAMP-HEADERS-BUFFER cleans up a headers buffer for immediate re-use.
+;;; After deleting the buffer's region, there will be one line in the buffer
+;;; because of how Hemlock regions work, so we have to delete that line's
+;;; plist.  Then we clean up any references to the buffer and delete the
+;;; main message buffer.  The other message buffers are left alone assuming
+;;; they are on the "others" list because they are being used in some
+;;; particular way (for example, a draft buffer refers to one or the user has
+;;; kept it).  Then some slots of the info structure are set to nil.
+;;;
+(defun revamp-headers-buffer (hbuffer hinfo)
+  (delete-region (buffer-region hbuffer))
+  (setf (line-plist (mark-line (buffer-point hbuffer))) nil)
+  (let ((msg-buf (headers-info-msg-buffer hinfo)))
+    ;; Deleting the buffer sets the slot to nil.
+    (when msg-buf (delete-buffer-if-possible msg-buf))
+    (cleanup-headers-buffer hbuffer))
+  (setf (headers-info-other-msg-bufs hinfo) nil)
+  (setf (headers-info-draft-bufs hinfo) nil)
+  (setf (headers-info-msg-seq hinfo) nil)
+  (setf (headers-info-msg-strings hinfo) nil))
+
+
+
+
+;;;; Incorporating new mail.
+
+(defhvar "New Mail Folder"
+  "This is the folder new mail is incorporated into."
+  :value "+inbox")
+
+(defcommand "Incorporate New Mail" (p)
+  "Incorporates new mail into \"New Mail Folder\", displaying INC output in
+   a pop-up window."
+  "Incorporates new mail into \"New Mail Folder\", displaying INC output in
+   a pop-up window."
+  (declare (ignore p))
+  (with-pop-up-display (s)
+    (incorporate-new-mail s)))
+
+(defhvar "Unseen Headers Message Spec"
+  "This is an MH message spec suitable any message prompt.  It is used to
+   supply headers for the unseen headers buffer, in addition to the
+   unseen-sequence name that is taken from the user's MH profile, when
+   incorporating new mail and after expunging.  This value is a string."
+  :value nil)
+
+(defcommand "Incorporate and Read New Mail" (p)
+  "Incorporates new mail and generates a headers buffer.
+   Incorporates new mail into \"New Mail Folder\", and creates a headers buffer
+   with the new messages.  To use this, you must define an unseen- sequence in
+   your profile.  Each time this is invoked the unseen-sequence is SCAN'ed, and
+   the headers buffer's contents are replaced."
+  "Incorporates new mail into \"New Mail Folder\", and creates a headers
+   buffer with the new messages.  This buffer will be appended to with
+   successive uses of this command."
+  (declare (ignore p))
+  (let ((unseen-seq (mh-profile-component "unseen-sequence")))
+    (unless unseen-seq
+      (editor-error "No unseen-sequence defined in MH profile."))
+    (incorporate-new-mail)
+    (let* ((folder (value new-mail-folder))
+	   ;; Stash current message before fetching unseen headers.
+	   (cur-msg (mh-current-message folder))
+	   (region (get-new-mail-msg-hdrs folder unseen-seq)))
+      ;; Fetch message headers before possibly making buffer in case we error.
+      (when (not (and *new-mail-buffer*
+		      (member *new-mail-buffer* *buffer-list* :test #'eq)))
+	(let ((name (format nil "Unseen Headers ~A" folder)))
+	  (when (getstring name *buffer-names*)
+	    (editor-error "There already is a buffer named ~S!" name))
+	  (setf *new-mail-buffer*
+		(make-buffer name :modes (list "Headers")
+			     :delete-hook '(new-mail-buf-delete-hook)))
+	  (setf (buffer-writable *new-mail-buffer*) nil)))
+      (cond ((hemlock-bound-p 'headers-information
+			      :buffer *new-mail-buffer*)
+	     (let ((hinfo (variable-value 'headers-information
+					  :buffer *new-mail-buffer*)))
+	       (unless (string= (headers-info-folder hinfo) folder)
+		 (editor-error
+		  "An unseen headers buffer already exists but into another ~
+		   folder.  Your mail has already been incorporated into the ~
+		   specified folder."))
+	       (with-writable-buffer (*new-mail-buffer*)
+		 (revamp-headers-buffer *new-mail-buffer* hinfo))
+	       ;; Restore the name in case someone used "Pick Headers".
+	       (setf (buffer-name *new-mail-buffer*)
+		     (format nil "Unseen Headers ~A" folder))
+	       (insert-new-mail-message-headers hinfo region cur-msg)))
+	    (t
+	     (let ((hinfo (make-headers-info :buffer *new-mail-buffer*
+					     :folder folder)))
+	       (defhvar "Headers Information"
+		 "This holds the information about the current headers buffer."
+		 :value hinfo :buffer *new-mail-buffer*)
+	       (insert-new-mail-message-headers hinfo region cur-msg)))))))
+
+;;; NEW-MAIL-BUF-DELETE-HOOK is invoked whenever the new mail buffer is
+;;; deleted.
+;;;
+(defun new-mail-buf-delete-hook (buffer)
+  (declare (ignore buffer))
+  (setf *new-mail-buffer* nil))
+
+;;; GET-NEW-MAIL-MSG-HDRS takes a folder and the unseen-sequence name.  It
+;;; returns a region with the unseen message headers and any headers due to
+;;; the "Unseen Headers Message Spec" variable.
+;;;
+(defun get-new-mail-msg-hdrs (folder unseen-seq)
+  (let* ((unseen-headers-message-spec (value unseen-headers-message-spec))
+	 (other-msgs (if unseen-headers-message-spec
+			 (breakup-message-spec
+			  (string-trim '(#\space #\tab)
+				       unseen-headers-message-spec))))
+	 (msg-spec (cond ((null other-msgs)
+			  (list unseen-seq))
+			 ((member unseen-seq other-msgs :test #'string=)
+			  other-msgs)
+			 (t (cons unseen-seq other-msgs)))))
+    (message-headers-to-region folder msg-spec)))
+
+;;; INSERT-NEW-MAIL-MESSAGE-HEADERS inserts region in the new mail buffer.
+;;; Then we look for the header line with cur-msg id, moving point there.
+;;; There may have been unseen messages before incorporating new mail, and
+;;; cur-msg should be the first new message.  Then we either switch to the
+;;; new mail headers, or show the current message.
+;;;
+(defun insert-new-mail-message-headers (hinfo region cur-msg)
+  (declare (simple-string cur-msg))
+  (with-writable-buffer (*new-mail-buffer*)
+    (insert-message-headers *new-mail-buffer* hinfo region))
+  (let ((point (buffer-point *new-mail-buffer*)))
+    (buffer-start point)
+    (with-headers-mark (cur-mark *new-mail-buffer* cur-msg)
+      (move-mark point cur-mark)))
+  (change-to-buffer *new-mail-buffer*))
+
+
+(defhvar "Incorporate New Mail Hook"
+  "Functions on this hook are invoked immediately after new mail is
+   incorporated."
+  :value nil)
+
+(defun incorporate-new-mail (&optional stream)
+  "Incorporates new mail, passing INC's output to stream.  When stream is
+   nil, output is flushed."
+  (unless (new-mail-p) (editor-error "No new mail."))
+  (let ((args `(,(coerce-folder-name (value new-mail-folder))
+		,@(if stream nil '("-silent"))
+		"-form" ,(namestring (truename (value mh-scan-line-form)))
+		"-width" ,(number-string (value fill-column)))))
+    (message "Incorporating new mail ...")
+    (mh "inc" args))
+  (when (value incorporate-new-mail-hook)
+    (message "Invoking new mail hooks ..."))
+  (invoke-hook incorporate-new-mail-hook))
+
+
+
+
+;;;; Deletion.
+
+(defhvar "Virtual Message Deletion"
+  "When set, \"Delete Message\" merely MARK's a message into the
+   \"hemlockdeleted\" sequence; otherwise, RMM is invoked."
+  :value t)
+
+(defcommand "Delete Message and Show Next" (p)
+  "Delete message and show next undeleted message.
+   This command is only valid in a headers buffer or a message buffer
+   associated with some headers buffer.  The current message is deleted, and
+   the next undeleted one is shown."
+  "Delete the current message and show the next undeleted one."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (delete-mark cur-mark)
+	     (delete-message (headers-info-folder hinfo) cur-msg)))
+	  (minfo
+	   (delete-message (message-info-folder minfo)
+			   (message-info-msgs minfo)))
+	  (t
+	   (editor-error "Not in a headers or message buffer."))))
+  (show-message-offset 1 :undeleted))
+
+(defcommand "Delete Message and Down Line" (p)
+  "Deletes the current message, moving point to the next line.
+   When in a headers buffer, deletes the message on the current line.  Then it
+   moves point to the next non-blank line."
+  "Deletes current message and moves point down a line."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information)))
+    (unless hinfo (editor-error "Not in a headers buffer."))
+    (multiple-value-bind (cur-msg cur-mark)
+			 (headers-current-message hinfo)
+      (unless cur-msg (editor-error "Not on a header line."))
+      (delete-message (headers-info-folder hinfo) cur-msg)
+      (when (line-offset cur-mark 1)
+	(unless (blank-line-p (mark-line cur-mark))
+	  (move-mark (current-point) cur-mark)))
+      (delete-mark cur-mark))))
+
+;;; "Delete Message" unlike "Headers Delete Message" cannot know for sure
+;;; which message id's have been deleted, so when virtual message deletion
+;;; is not used, we cannot use DELETE-HEADERS-BUFFER-LINE to keep headers
+;;; buffers consistent.  However, the message id's in the buffer (if deleted)
+;;; will generate MH errors if operations are attempted with them, and
+;;; if the user ever packs the folder with "Expunge Messages", the headers
+;;; buffer will be updated.
+;;;
+(defcommand "Delete Message" (p)
+  "Prompts for a folder, messages to delete, and pick expression.  When in
+   a headers buffer into the same folder specified, the messages prompt
+   defaults to those messages in the buffer; \"all\" may be entered if this is
+   not what is desired.  When \"Virtual Message Deletion\" is set, messages are
+   only MARK'ed for deletion.  See \"Expunge Messages\".  When this feature is
+   not used, headers and message buffers message id's my not be consistent
+   with MH."
+  "Prompts for a folder and message to delete.  When \"Virtual Message
+   Deletion\" is set, messages are only MARK'ed for deletion.  See \"Expunge
+   Messages\"."
+  (declare (ignore p))
+  (let* ((folder (prompt-for-folder))
+	 (hinfo (value headers-information))
+	 (temp-msgs (prompt-for-message
+		     :folder folder
+		     :messages
+		     (if (and hinfo
+			      (string= folder
+				       (the simple-string
+					    (headers-info-folder hinfo))))
+			 (headers-info-msg-strings hinfo))
+		     :prompt "MH messages to pick from: "))
+	 (pick-exp (prompt-for-pick-expression))
+	 (msgs (pick-messages folder temp-msgs pick-exp))
+	 (virtually (value virtual-message-deletion)))
+    (declare (simple-string folder))
+    (if virtually
+	(mh "mark" `(,folder ,@msgs "-sequence" "hemlockdeleted" "-add"))
+	(mh "rmm" `(,folder ,@msgs)))
+    (if virtually    
+	(let ((deleted-seq (mh-sequence-list folder "hemlockdeleted")))
+	  (when deleted-seq
+	    (do-headers-buffers (hbuf folder)
+	      (with-writable-buffer (hbuf)
+		(note-deleted-headers hbuf deleted-seq)))))
+	(do-headers-buffers (hbuf folder hinfo)
+	  (do-headers-lines (hbuf :line-var line :mark-var hmark)
+	    (when (member (line-message-id line) msgs :test #'string=)
+	      (delete-headers-buffer-line hinfo hmark)))))))
+
+(defcommand "Headers Delete Message" (p)
+  "Delete current message.
+   When in a headers buffer, deletes the message on the current line.  When
+   in a message buffer, deletes that message.  When \"Virtual Message
+   Deletion\" is set, messages are only MARK'ed for deletion.  See \"Expunge
+   Messages\"."
+  "When in a headers buffer, deletes the message on the current line.  When
+   in a message buffer, deletes that message.  When \"Virtual Message
+   Deletion\" is set, messages are only MARK'ed for deletion.  See \"Expunge
+   Messages\"."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (delete-mark cur-mark)
+	     (delete-message (headers-info-folder hinfo) cur-msg)))
+	  (minfo
+	   (let ((msgs (message-info-msgs minfo)))
+	     (delete-message (message-info-folder minfo)
+			     (if (consp msgs) (car msgs) msgs)))
+	   (message "Message deleted."))
+	  (t (editor-error "Not in a headers or message buffer.")))))
+
+;;; DELETE-MESSAGE takes a folder and message id and either flags this message
+;;; for deletion or deletes it.  All headers buffers into folder are updated,
+;;; either by flagging a headers line or deleting it.
+;;;
+(defun delete-message (folder msg)
+  (cond ((value virtual-message-deletion)
+	 (mark-one-message folder msg "hemlockdeleted" :add)
+	 (do-headers-buffers (hbuf folder)
+	   (with-headers-mark (hmark hbuf msg)
+	     (with-writable-buffer (hbuf)
+	       (note-deleted-message-at-mark hmark)))))
+	(t (mh "rmm" (list folder msg))
+	   (do-headers-buffers (hbuf folder hinfo)
+	     (with-headers-mark (hmark hbuf msg)
+	       (delete-headers-buffer-line hinfo hmark)))))
+  (dolist (b *buffer-list*)
+    (when (and (hemlock-bound-p 'message-information :buffer b)
+	       (buffer-modeline-field-p b :deleted-message))
+      (dolist (w (buffer-windows b))
+	(update-modeline-field b w :deleted-message)))))
+
+;;; NOTE-DELETED-MESSAGE-AT-MARK takes a mark at the beginning of a valid
+;;; headers line, sticks a "D" on the line, and frobs the line's deleted
+;;; property.  This assumes the headers buffer is modifiable.
+;;;
+(defun note-deleted-message-at-mark (mark)
+  (find-attribute mark :digit)
+  (find-attribute mark :digit #'zerop)
+  (character-offset mark 2)
+  (setf (next-character mark) #\D)
+  (setf (line-message-deleted (mark-line mark)) t))
+
+;;; DELETE-HEADERS-BUFFER-LINE takes a headers information and a mark on the
+;;; line to be deleted.  Before deleting the line, we check to see if any
+;;; message or draft buffers refer to the buffer because of the line.  Due
+;;; to how regions are deleted, line plists get messed up, so they have to
+;;; be regenerated.  We regenerate them for the whole buffer, so we don't have
+;;; to hack the code to know which lines got messed up.
+;;;
+(defun delete-headers-buffer-line (hinfo hmark)
+  (delete-headers-line-references hinfo hmark)
+  (let ((id (line-message-id (mark-line hmark)))
+	(hbuf (headers-info-buffer hinfo)))
+    (with-writable-buffer (hbuf)
+      (with-mark ((end (line-start hmark) :left-inserting))
+	(unless (line-offset end 1 0) (buffer-end end))
+	(delete-region (region hmark end))))
+    (let ((seq (mh-sequence-delete id (headers-info-msg-seq hinfo))))
+      (setf (headers-info-msg-seq hinfo) seq)
+      (setf (headers-info-msg-strings hinfo) (mh-sequence-strings seq)))
+    (set-message-headers-ids hbuf)
+    (when (value virtual-message-deletion)
+      (let ((deleted-seq (mh-sequence-list (headers-info-folder hinfo)
+					   "hemlockdeleted")))
+	(do-headers-lines (hbuf :line-var line)
+	  (setf (line-message-deleted line)
+		(mh-sequence-member-p (line-message-id line) deleted-seq)))))))
+
+
+;;; DELETE-HEADERS-LINE-REFERENCES removes any message buffer or draft buffer
+;;; pointers to a headers buffer or marks into the headers buffer.  Currently
+;;; message buffers and draft buffers are identified differently for no good
+;;; reason; probably message buffers should be located in the same way draft
+;;; buffers are.  Also, we currently assume only one of other-msg-bufs could
+;;; refer to the line (similarly for draft-bufs), but this might be bug
+;;; prone.  The message buffer case couldn't happen since the buffer name
+;;; would cause MAYBE-MAKE-MH-BUFFER to re-use the buffer, but you could reply
+;;; to the same message twice simultaneously.
+;;;
+(defun delete-headers-line-references (hinfo hmark)
+  (let ((msg-id (line-message-id (mark-line hmark)))
+	(main-msg-buf (headers-info-msg-buffer hinfo)))
+    (declare (simple-string msg-id))
+    (when main-msg-buf
+      (let ((minfo (variable-value 'message-information :buffer main-msg-buf)))
+	(when (string= (the simple-string (message-info-msgs minfo))
+		       msg-id)
+	  (cond ((message-info-draft-buf minfo)
+		 (cleanup-headers-reference main-msg-buf minfo)
+		 (setf (headers-info-msg-buffer hinfo) nil))
+		(t (delete-buffer-if-possible main-msg-buf))))))
+    (dolist (mbuf (headers-info-other-msg-bufs hinfo))
+      (let ((minfo (variable-value 'message-information :buffer mbuf)))
+	(when (string= (the simple-string (message-info-msgs minfo))
+		       msg-id)
+	  (cond ((message-info-draft-buf minfo)
+		 (cleanup-headers-reference mbuf minfo)
+		 (setf (headers-info-other-msg-bufs hinfo)
+		       (delete mbuf (headers-info-other-msg-bufs hinfo)
+			       :test #'eq)))
+		(t (delete-buffer-if-possible mbuf)))
+	  (return)))))
+  (dolist (dbuf (headers-info-draft-bufs hinfo))
+    (let ((dinfo (variable-value 'draft-information :buffer dbuf)))
+      (when (same-line-p (draft-info-headers-mark dinfo) hmark)
+	(cleanup-headers-reference dbuf dinfo)
+	(setf (headers-info-draft-bufs hinfo)
+	      (delete dbuf (headers-info-draft-bufs hinfo) :test #'eq))
+	(return)))))
+
+
+(defcommand "Undelete Message" (p)
+  "Prompts for a folder, messages to undelete, and pick expression.  When in
+   a headers buffer into the same folder specified, the messages prompt
+   defaults to those messages in the buffer; \"all\" may be entered if this is
+   not what is desired.  This command is only meaningful if you have
+   \"Virtual Message Deletion\" set."
+  "Prompts for a folder, messages to undelete, and pick expression.  When in
+   a headers buffer into the same folder specified, the messages prompt
+   defaults to those messages in the buffer; \"all\" may be entered if this is
+   not what is desired.  This command is only meaningful if you have
+   \"Virtual Message Deletion\" set."
+  (declare (ignore p))
+  (unless (value virtual-message-deletion)
+    (editor-error "You don't use virtual message deletion."))
+  (let* ((folder (prompt-for-folder))
+	 (hinfo (value headers-information))
+	 (temp-msgs (prompt-for-message
+		     :folder folder
+		     :messages
+		     (if (and hinfo
+			      (string= folder
+				       (the simple-string
+					    (headers-info-folder hinfo))))
+			 (headers-info-msg-strings hinfo))
+		     :prompt "MH messages to pick from: "))
+	 (pick-exp (prompt-for-pick-expression))
+	 (msgs (if pick-exp
+		   (or (pick-messages folder temp-msgs pick-exp) temp-msgs)
+		   temp-msgs)))
+    (declare (simple-string folder))
+    (mh "mark" `(,folder ,@msgs "-sequence" "hemlockdeleted" "-delete"))
+    (let ((deleted-seq (mh-sequence-list folder "hemlockdeleted")))
+      (do-headers-buffers (hbuf folder)
+	(with-writable-buffer (hbuf)
+	  (do-headers-lines (hbuf :line-var line :mark-var hmark)
+	    (when (and (line-message-deleted line)
+		       (not (mh-sequence-member-p (line-message-id line)
+						  deleted-seq)))
+	      (note-undeleted-message-at-mark hmark))))))))
+
+(defcommand "Headers Undelete Message" (p)
+  "Undelete the current message.
+   When in a headers buffer, undeletes the message on the current line.  When
+   in a message buffer, undeletes that message.  This command is only
+   meaningful if you have \"Virtual Message Deletion\" set."
+  "When in a headers buffer, undeletes the message on the current line.  When
+   in a message buffer, undeletes that message.  This command is only
+   meaningful if you have \"Virtual Message Deletion\" set."
+  (declare (ignore p))
+  (unless (value virtual-message-deletion)
+    (editor-error "You don't use virtual message deletion."))
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (delete-mark cur-mark)
+	     (undelete-message (headers-info-folder hinfo) cur-msg)))
+	  (minfo
+	   (undelete-message (message-info-folder minfo)
+			     (message-info-msgs minfo))
+	   (message "Message undeleted."))
+	  (t (editor-error "Not in a headers or message buffer.")))))
+
+;;; UNDELETE-MESSAGE takes a folder and a message id.  All headers buffers into
+;;; folder are updated.
+;;;
+(defun undelete-message (folder msg)
+  (mark-one-message folder msg "hemlockdeleted" :delete)
+  (do-headers-buffers (hbuf folder)
+    (with-headers-mark (hmark hbuf msg)
+      (with-writable-buffer (hbuf)
+	(note-undeleted-message-at-mark hmark))))
+  (dolist (b *buffer-list*)
+    (when (and (hemlock-bound-p 'message-information :buffer b)
+	       (buffer-modeline-field-p b :deleted-message))
+      (dolist (w (buffer-windows b))
+	(update-modeline-field b w :deleted-message)))))
+
+;;; NOTE-UNDELETED-MESSAGE-AT-MARK takes a mark at the beginning of a valid
+;;; headers line, sticks a space on the line in place of a "D", and frobs the
+;;; line's deleted property.  This assumes the headers buffer is modifiable.
+;;;
+(defun note-undeleted-message-at-mark (hmark)
+  (find-attribute hmark :digit)
+  (find-attribute hmark :digit #'zerop)
+  (character-offset hmark 2)
+  (setf (next-character hmark) #\space)
+  (setf (line-message-deleted (mark-line hmark)) nil))
+
+
+(defcommand "Expunge Messages" (p)
+  "Expunges messages marked for deletion.
+   This command prompts for a folder, invoking RMM on the \"hemlockdeleted\"
+   sequence after asking the user for confirmation.  Setting \"Quit Headers
+   Confirm\" to nil inhibits prompting.  The folder's message id's are packed
+   with FOLDER -pack.  When in a headers buffer, uses that folder.  When in a
+   message buffer, uses its folder, updating any associated headers buffer.
+   When \"Temporary Draft Folder\" is bound, this folder's messages are deleted
+   and expunged."
+  "Prompts for a folder, invoking RMM on the \"hemlockdeleted\" sequence and
+   packing the message id's with FOLDER -pack.  When in a headers buffer,
+   uses that folder."
+  (declare (ignore p))
+  (let* ((hinfo (value headers-information))
+	 (minfo (value message-information))
+	 (folder (cond (hinfo (headers-info-folder hinfo))
+		       (minfo (message-info-folder minfo))
+		       (t (prompt-for-folder))))
+	 (deleted-seq (mh-sequence-list folder "hemlockdeleted")))
+    ;;
+    ;; Delete the messages if there are any.
+    ;; This deletes "hemlockdeleted" from sequence file; we don't have to.
+    (when (and deleted-seq
+	       (or (not (value expunge-messages-confirm))
+		   (prompt-for-y-or-n
+		    :prompt (list "Expunge messages and pack folder ~A? "
+				  folder)
+		    :default t
+		    :default-string "Y")))
+      (message "Deleting messages ...")
+      (mh "rmm" (list folder "hemlockdeleted"))
+      ;;
+      ;; Compact the message id's after deletion.
+      (let ((*standard-output* *mh-utility-bit-bucket*))
+	(message "Compacting folder ...")
+	(mh "folder" (list folder "-fast" "-pack")))
+      ;;
+      ;; Do a bunch of consistency maintenance.
+      (let ((new-buf-p (eq (current-buffer) *new-mail-buffer*)))
+	(message "Maintaining consistency ...")
+	(expunge-messages-fold-headers-buffers folder)
+	(expunge-messages-fix-draft-buffers folder)
+	(expunge-messages-fix-unseen-headers folder)
+	(when new-buf-p (change-to-buffer *new-mail-buffer*)))
+      (delete-and-expunge-temp-drafts))))
+
+;;; EXPUNGE-MESSAGES-FOLD-HEADERS-BUFFERS deletes all headers buffers into the
+;;; compacted folder.  We can only update the headers buffers by installing all
+;;; headers, so there may as well be only one such buffer.  First we get a list
+;;; of the buffers since DO-HEADERS-BUFFERS is trying to iterate over a list
+;;; being destructively modified by buffer deletions.
+;;;
+(defun expunge-messages-fold-headers-buffers (folder)
+  (let (hbufs)
+    (declare (list hbufs))
+    (do-headers-buffers (b folder)
+      (unless (eq b *new-mail-buffer*)
+	(push b hbufs)))
+    (unless (zerop (length hbufs))
+      (dolist (b hbufs)
+	(delete-headers-buffer-and-message-buffers-command nil b))
+      (new-message-headers folder (list "all")))))
+
+;;; EXPUNGE-MESSAGES-FIX-DRAFT-BUFFERS finds any draft buffer that was set up
+;;; as a reply to some message in folder, removing this relationship in case
+;;; that message id does not exist after expunge folder compaction.
+;;;
+(defun expunge-messages-fix-draft-buffers (folder)
+  (declare (simple-string folder))
+  (dolist (b *buffer-list*)
+    (when (hemlock-bound-p 'draft-information :buffer b)
+      (let* ((dinfo (variable-value 'draft-information :buffer b))
+	     (reply-folder (draft-info-replied-to-folder dinfo)))
+	(when (and reply-folder
+		   (string= (the simple-string reply-folder) folder))
+	  (setf (draft-info-replied-to-folder dinfo) nil)
+	  (setf (draft-info-replied-to-msg dinfo) nil))))))
+
+;;; EXPUNGE-MESSAGES-FIX-UNSEEN-HEADERS specially handles the unseen headers
+;;; buffer apart from the other headers buffers into the same folder when
+;;; messages have been expunged.  We must delete the associated message buffers
+;;; since REVAMP-HEADERS-BUFFER does not, and these potentially reference bad
+;;; message id's.  When doing this we must copy the other-msg-bufs list since
+;;; the delete buffer cleanup hook for them is destructive.  Then we check for
+;;; more unseen messages.
+;;;
+(defun expunge-messages-fix-unseen-headers (folder)
+  (declare (simple-string folder))
+  (when *new-mail-buffer*
+    (let ((hinfo (variable-value 'headers-information
+				 :buffer *new-mail-buffer*)))
+      (when (string= (the simple-string (headers-info-folder hinfo))
+		     folder)
+	(let ((other-bufs (copy-list (headers-info-other-msg-bufs hinfo))))
+	  (dolist (b other-bufs) (delete-buffer-if-possible b)))
+	(with-writable-buffer (*new-mail-buffer*)
+	  (revamp-headers-buffer *new-mail-buffer* hinfo)
+	  ;; Restore the name in case someone used "Pick Headers".
+	  (setf (buffer-name *new-mail-buffer*)
+		(format nil "Unseen Headers ~A" folder))
+	  (let ((region (maybe-get-new-mail-msg-hdrs folder)))
+	    (when region
+	      (insert-message-headers *new-mail-buffer* hinfo region))))))))
+
+;;; MAYBE-GET-NEW-MAIL-MSG-HDRS returns a region suitable for a new mail buffer
+;;; or nil.  Folder is probed for unseen headers, and if there are some, then
+;;; we call GET-NEW-MAIL-MSG-HDRS which also uses "Unseen Headers Message Spec".
+;;; If there are no unseen headers, we only look for "Unseen Headers Message
+;;; Spec" messages.  We go through these contortions to keep MH from outputting
+;;; errors.
+;;;
+(defun maybe-get-new-mail-msg-hdrs (folder)
+  (let ((unseen-seq-name (mh-profile-component "unseen-sequence")))
+    (multiple-value-bind (unseen-seq foundp)
+			 (mh-sequence-list folder unseen-seq-name)
+      (if (and foundp unseen-seq)
+	  (get-new-mail-msg-hdrs folder unseen-seq-name)
+	  (let ((spec (value unseen-headers-message-spec)))
+	    (when spec
+	      (message-headers-to-region
+	       folder
+	       (breakup-message-spec (string-trim '(#\space #\tab) spec)))))))))
+
+
+
+
+;;;; Folders.
+
+(defvar *folder-name-table* nil)
+
+(defun check-folder-name-table ()
+  (unless *folder-name-table*
+    (message "Finding folder names ...")
+    (setf *folder-name-table* (make-string-table))
+    (let* ((output (with-output-to-string (*standard-output*)
+		     (mh "folders" '("-fast"))))
+	   (length (length output))
+	   (start 0))
+      (declare (simple-string output))
+      (loop
+	(when (> start length) (return))
+	(let ((nl (position #\newline output :start start)))
+	  (unless nl (return))
+	  (unless (= start nl)
+	    (setf (getstring (subseq output start nl) *folder-name-table*) t))
+	  (setf start (1+ nl)))))))
+
+(defcommand "List Folders" (p)
+  "Pop up a list of folders at top-level."
+  "Pop up a list of folders at top-level."
+  (declare (ignore p))
+  (check-folder-name-table)
+  (with-pop-up-display (s)
+    (do-strings (f ignore *folder-name-table*)
+      (declare (ignore ignore))
+      (write-line f s))))
+
+(defcommand "Create Folder" (p)
+  "Creates a folder.  If the folder already exists, an error is signaled."
+  "Creates a folder.  If the folder already exists, an error is signaled."
+  (declare (ignore p))
+  (let ((folder (prompt-for-folder :must-exist nil)))
+    (when (folder-existsp folder)
+      (editor-error "Folder already exists -- ~S!" folder))
+    (create-folder folder)))
+
+(defcommand "Delete Folder" (p)
+  "Prompts for a folder and uses RMF to delete it."
+  "Prompts for a folder and uses RMF to delete it."
+  (declare (ignore p))
+  (let* ((folder (prompt-for-folder))
+	 (*standard-output* *mh-utility-bit-bucket*))
+    (mh "rmf" (list folder))
+		    ;; RMF doesn't recognize this documented switch.
+		    ;; "-nointeractive"))))
+    (check-folder-name-table)
+    (delete-string (strip-folder-name folder) *folder-name-table*)))
+
+
+(defvar *refile-default-destination* nil)
+
+(defcommand "Refile Message" (p)
+  "Prompts for a source folder, messages, pick expression, and a destination
+   folder to refile the messages."
+  "Prompts for a source folder, messages, pick expression, and a destination
+   folder to refile the messages."
+  (declare (ignore p))
+  (let* ((src-folder (prompt-for-folder :prompt "Source folder: "))
+	 (hinfo (value headers-information))
+	 (temp-msgs (prompt-for-message
+		     :folder src-folder
+		     :messages
+		     (if (and hinfo
+			      (string= src-folder
+				       (the simple-string
+					    (headers-info-folder hinfo))))
+			 (headers-info-msg-strings hinfo))
+		     :prompt "MH messages to pick from: "))
+	 (pick-exp (prompt-for-pick-expression))
+	 ;; Return pick result or temp-msgs individually specified in a list.
+	 (msgs (pick-messages src-folder temp-msgs pick-exp)))
+    (declare (simple-string src-folder))
+    (refile-message src-folder msgs
+		    (prompt-for-folder :must-exist nil
+				       :prompt "Destination folder: "
+				       :default *refile-default-destination*))))
+
+(defcommand "Headers Refile Message" (p)
+  "Refile the current message.
+   When in a headers buffer, refiles the message on the current line, and when
+   in a message buffer, refiles that message, prompting for a destination
+   folder."
+  "When in a headers buffer, refiles the message on the current line, and when
+   in a message buffer, refiles that message, prompting for a destination
+   folder."
+  (declare (ignore p))
+  (let ((hinfo (value headers-information))
+	(minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (delete-mark cur-mark)
+	     (refile-message (headers-info-folder hinfo) cur-msg
+			     (prompt-for-folder
+			      :must-exist nil
+			      :prompt "Destination folder: "
+			      :default *refile-default-destination*))))
+	  (minfo
+	   (refile-message
+	    (message-info-folder minfo) (message-info-msgs minfo)
+	    (prompt-for-folder :must-exist nil
+			       :prompt "Destination folder: "
+			       :default *refile-default-destination*))
+	   (message "Message refiled."))
+	  (t
+	   (editor-error "Not in a headers or message buffer.")))))
+
+;;; REFILE-MESSAGE refiles msg from src-folder to dst-folder.  If dst-buffer
+;;; doesn't exist, the user is prompted for creating it.  All headers buffers
+;;; concerning src-folder are updated.  When msg is a list, we did a general
+;;; message prompt, and we cannot know which headers lines to delete.
+;;;
+(defun refile-message (src-folder msg dst-folder)
+  (unless (folder-existsp dst-folder)
+    (cond ((prompt-for-y-or-n
+	    :prompt "Destination folder doesn't exist.  Create it? "
+	    :default t :default-string "Y")
+	   (create-folder dst-folder))
+	  (t (editor-error "Not refiling message."))))
+  (mh "refile" `(,@(if (listp msg) msg (list msg))
+		 "-src" ,src-folder ,dst-folder))
+  (setf *refile-default-destination* (strip-folder-name dst-folder))
+  (if (listp msg)
+      (do-headers-buffers (hbuf src-folder hinfo)
+	(do-headers-lines (hbuf :line-var line :mark-var hmark)
+	  (when (member (line-message-id line) msg :test #'string=)
+	    (delete-headers-buffer-line hinfo hmark))))
+      (do-headers-buffers (hbuf src-folder hinfo)
+	(with-headers-mark (hmark hbuf msg)
+	  (delete-headers-buffer-line hinfo hmark)))))
+
+
+
+
+;;;; Miscellaneous commands.
+
+(defcommand "Mark Message" (p)
+  "Prompts for a folder, message, and sequence.  By default the message is
+   added, but if an argument is supplied, the message is deleted.  When in
+   a headers buffer or message buffer, only a sequence is prompted for."
+  "Prompts for a folder, message, and sequence.  By default the message is
+   added, but if an argument is supplied, the message is deleted.  When in
+   a headers buffer or message buffer, only a sequence is prompted for."
+  (let* ((hinfo (value headers-information))
+	 (minfo (value message-information)))
+    (cond (hinfo
+	   (multiple-value-bind (cur-msg cur-mark)
+				(headers-current-message hinfo)
+	     (unless cur-msg (editor-error "Not on a header line."))
+	     (delete-mark cur-mark)
+	     (let ((seq-name (prompt-for-string :prompt "Sequence name: "
+						:trim t)))
+	       (declare (simple-string seq-name))
+	       (when (string= "" seq-name)
+		 (editor-error "Sequence name cannot be empty."))
+	       (mark-one-message (headers-info-folder hinfo)
+				 cur-msg seq-name (if p :delete :add)))))
+	  (minfo
+	   (let ((msgs (message-info-msgs minfo))
+		 (seq-name (prompt-for-string :prompt "Sequence name: "
+					      :trim t)))
+	     (declare (simple-string seq-name))
+	     (when (string= "" seq-name)
+	       (editor-error "Sequence name cannot be empty."))
+	     (mark-one-message (message-info-folder minfo)
+			       (if (consp msgs) (car msgs) msgs)
+			       seq-name (if p :delete :add))))
+	  (t
+	   (let ((folder (prompt-for-folder))
+		 (seq-name (prompt-for-string :prompt "Sequence name: "
+					      :trim t)))
+	     (declare (simple-string seq-name))
+	     (when (string= "" seq-name)
+	       (editor-error "Sequence name cannot be empty."))
+	     (mh "mark" `(,folder ,@(prompt-for-message :folder folder)
+			  "-sequence" ,seq-name
+			  ,(if p "-delete" "-add"))))))))
+
+
+(defcommand "List Mail Buffers" (p)
+  "Show a list of all mail associated buffers.
+   If the buffer has an associated message buffer, it is displayed to the right
+   of the buffer name.  If there is no message buffer, but the buffer is
+   associated with a headers buffer, then it is displayed.  If the buffer is
+   modified then a * is displayed before the name."
+  "Display the names of all buffers in a with-random-typeout window."
+  (declare (ignore p))
+  (let ((buffers nil))
+    (declare (list buffers))
+    (do-strings (n b *buffer-names*)
+      (declare (ignore n))
+      (unless (eq b *echo-area-buffer*)
+	(cond ((hemlock-bound-p 'message-buffer :buffer b)
+	       ;; Catches draft buffers associated with message buffers first.
+	       (push (cons b (variable-value 'message-buffer :buffer b))
+		     buffers))
+	      ((hemlock-bound-p 'headers-buffer :buffer b)
+	       ;; Then draft or message buffers associated with headers buffers.
+	       (push (cons b (variable-value 'headers-buffer :buffer b))
+		     buffers))
+	      ((or (hemlock-bound-p 'draft-information :buffer b)
+		   (hemlock-bound-p 'message-information :buffer b)
+		   (hemlock-bound-p 'headers-information :buffer b))
+	       (push b buffers)))))
+    (with-pop-up-display (s :height (length buffers))
+      (dolist (ele (nreverse buffers))
+	(let* ((association (if (consp ele) (cdr ele)))
+	       (b (if association (car ele) ele))
+	       (buffer-pathname (buffer-pathname b))
+	       (buffer-name (buffer-name b)))
+	  (write-char (if (buffer-modified b) #\* #\space) s)
+	  (if buffer-pathname
+	      (format s "~A  ~A~:[~;~50T~:*~A~]~%"
+		      (file-namestring buffer-pathname)
+		      (directory-namestring buffer-pathname)
+		      (if association (buffer-name association)))
+	      (format s "~A~:[~;~50T~:*~A~]~%"
+		      buffer-name
+		      (if association (buffer-name association)))))))))
+
+
+(defcommand "Message Help" (p)
+  "Show this help."
+  "Show this help."
+  (declare (ignore p))
+  (describe-mode-command nil "Message"))
+
+(defcommand "Headers Help" (p)
+  "Show this help."
+  "Show this help."
+  (declare (ignore p))
+  (describe-mode-command nil "Headers"))
+
+(defcommand "Draft Help" (p)
+  "Show this help."
+  "Show this help."
+  (declare (ignore p))
+  (describe-mode-command nil "Draft"))
+
+
+
+
+;;;; Prompting.
+
+;;; Folder prompting.
+;;; 
+
+(defun prompt-for-folder (&key (must-exist t) (prompt "MH Folder: ")
+			       (default (mh-current-folder)))
+  "Prompts for a folder, using MH's idea of the current folder as a default.
+   The result will have a leading + in the name."
+  (check-folder-name-table)
+  (let ((folder (prompt-for-keyword (list *folder-name-table*)
+				    :must-exist must-exist :prompt prompt
+				    :default default :default-string default
+				    :help "Enter folder name.")))
+    (declare (simple-string folder))
+    (when (string= folder "") (editor-error "Must supply folder!"))
+    (let ((name (coerce-folder-name folder)))
+      (when (and must-exist (not (folder-existsp name)))
+	(editor-error "Folder does not exist -- ~S." name))
+      name)))
+
+(defun coerce-folder-name (folder)
+  (if (char= (schar folder 0) #\+)
+      folder
+      (concatenate 'simple-string "+" folder)))
+
+(defun strip-folder-name (folder)
+  (if (char= (schar folder 0) #\+)
+      (subseq folder 1)
+      folder))
+
+
+;;; Message prompting.
+;;; 
+
+(defun prompt-for-message (&key (folder (mh-current-folder))
+				(prompt "MH messages: ")
+				messages)
+   "Prompts for a message spec, using messages as a default.  If messages is
+    not supplied, then the current message for folder is used.  The result is
+    a list of strings which are the message ids, intervals, and/or sequence
+    names the user entered."
+  (let* ((cur-msg (cond ((not messages) (mh-current-message folder))
+			((stringp messages) messages)
+			((consp messages)
+			 (if (= (length (the list messages)) 1)
+			     (car messages)
+			     (format nil "~{~A~^ ~}" messages))))))
+    (breakup-message-spec (prompt-for-string :prompt prompt
+					     :default cur-msg
+					     :default-string cur-msg
+					     :trim t
+					     :help "Enter MH message id(s)."))))
+
+(defun breakup-message-spec (msgs)
+  (declare (simple-string msgs))
+  (let ((start 0)
+	(result nil))
+    (loop
+      (let ((end (position #\space msgs :start start :test #'char=)))
+	(unless end
+	  (return (if (zerop start)
+		      (list msgs)
+		      (nreverse (cons (subseq msgs start) result)))))
+	(push (subseq msgs start end) result)
+	(setf start (1+ end))))))
+
+
+;;; PICK expression prompting.
+;;; 
+
+(defhvar "MH Lisp Expression"
+  "When this is set (the default), MH expression prompts are read in a Lisp
+   syntax.  Otherwise, the input is as if it had been entered on a shell
+   command line."
+  :value t)
+
+;;; This is dynamically bound to nil for argument processing routines.
+;;; 
+(defvar *pick-expression-strings* nil)
+
+(defun prompt-for-pick-expression ()
+  "Prompts for an MH PICK-like expression that is converted to a list of
+   strings suitable for EXT:RUN-PROGRAM.  As a second value, the user's
+   expression is as typed in is returned."
+  (let ((exp (prompt-for-string :prompt "MH expression: "
+				:help "Expression to PICK over mail messages."
+				:trim t))
+	(*pick-expression-strings* nil))
+    (if (value mh-lisp-expression)
+	(let ((exp (let ((*package* *keyword-package*))
+		     (read-from-string exp))))
+	  (if exp
+	      (if (consp exp)
+		  (lisp-to-pick-expression exp)
+		  (editor-error "Lisp PICK expressions cannot be atomic."))))
+	(expand-mh-pick-spec exp))
+    (values (nreverse *pick-expression-strings*)
+	    exp)))
+
+(defun lisp-to-pick-expression (exp)
+  (ecase (car exp)
+    (:and (lpe-and/or exp "-and"))
+    (:or (lpe-and/or exp "-or"))
+    (:not (push "-not" *pick-expression-strings*)
+	  (let ((nexp (cadr exp)))
+	    (unless (consp nexp) (editor-error "Bad expression -- ~S" nexp))
+	    (lisp-to-pick-expression nexp)))
+    
+    (:cc (lpe-output-and-go exp "-cc"))
+    (:date (lpe-output-and-go exp "-date"))
+    (:from (lpe-output-and-go exp "-from"))
+    (:search (lpe-output-and-go exp "-search"))
+    (:subject (lpe-output-and-go exp "-subject"))
+    (:to (lpe-output-and-go exp "-to"))
+    (:-- (lpe-output-and-go (cdr exp)
+			    (concatenate 'simple-string
+					 "--" (string (cadr exp)))))
+
+    (:before (lpe-after-and-before exp "-before"))
+    (:after (lpe-after-and-before exp "-after"))
+    (:datefield (lpe-output-and-go exp "-datefield"))))
+
+(defun lpe-after-and-before (exp op)
+  (let ((operand (cadr exp)))
+    (when (numberp operand)
+      (setf (cadr exp)
+	    (if (plusp operand)
+		(number-string (- operand))
+		(number-string operand)))))
+  (lpe-output-and-go exp op))
+
+(defun lpe-output-and-go (exp op)
+  (push op *pick-expression-strings*)
+  (let ((operand (cadr exp)))
+    (etypecase operand
+      (string (push operand *pick-expression-strings*))
+      (symbol (push (symbol-name operand)
+		    *pick-expression-strings*)))))
+
+(defun lpe-and/or (exp op)
+  (push "-lbrace" *pick-expression-strings*)
+  (dolist (ele (cdr exp))
+    (lisp-to-pick-expression ele)
+    (push op *pick-expression-strings*))
+  (pop *pick-expression-strings*) ;Clear the extra "-op" arg.
+  (push "-rbrace" *pick-expression-strings*))
+
+;;; EXPAND-MH-PICK-SPEC takes a string of "words" assumed to be separated
+;;; by single spaces.  If a "word" starts with a quotation mark, then
+;;; everything is grabbed up to the next one and used as a single word.
+;;; Currently, this does not worry about extra spaces (or tabs) between
+;;; "words".
+;;; 
+(defun expand-mh-pick-spec (spec)
+  (declare (simple-string spec))
+  (let ((start 0))
+    (loop
+      (let ((end (position #\space spec :start start :test #'char=)))
+	(unless end
+	  (if (zerop start)
+	      (setf *pick-expression-strings* (list spec))
+	      (push (subseq spec start) *pick-expression-strings*))
+	  (return))
+	(cond ((char= #\" (schar spec start))
+	       (setf end (position #\" spec :start (1+ start) :test #'char=))
+	       (unless end (editor-error "Bad quoting syntax."))
+	       (push (subseq spec (1+ start) end) *pick-expression-strings*)
+	       (setf start (+ end 2)))
+	      (t (push (subseq spec start end) *pick-expression-strings*)
+		 (setf start (1+ end))))))))
+
+
+;;; Password prompting.
+;;;
+
+(defun prompt-for-password (&optional (prompt "Password: "))
+  "Prompts for password with prompt."
+  (let ((hi::*parse-verification-function* #'(lambda (string) (list string))))
+    (let ((hi::*parse-prompt* prompt))
+      (hi::display-prompt-nicely))
+    (let ((start-window (current-window)))
+      (move-mark *parse-starting-mark* (buffer-point *echo-area-buffer*))
+      (setf (current-window) *echo-area-window*)
+      (unwind-protect
+	  (use-buffer *echo-area-buffer*
+	    (let ((result ()))
+	      (declare (list result))
+	      (loop
+		(let ((key-event (get-key-event *editor-input*)))
+		  (ring-pop hi::*key-event-history*)
+		  (cond ((eq key-event #k"return")
+			 (return (prog1 (coerce (nreverse result)
+						'simple-string)
+				   (fill result nil))))
+			((or (eq key-event #k"control-u")
+			     (eq key-event #k"control-U"))
+			 (setf result nil))
+			(t (push (ext:key-event-char key-event) result)))))))
+	(setf (current-window) start-window)))))
+
+
+
+
+
+;;;; Making mail buffers.
+
+;;; MAYBE-MAKE-MH-BUFFER looks up buffer with name, returning it if it exists
+;;; after cleaning it up to a state "good as new".  Currently, we don't
+;;; believe it is possible to try to make two draft buffers with the same name
+;;; since that would mean that composition, draft folder interaction, and
+;;; draft folder current message didn't do what we expected -- or some user
+;;; was modifying the draft folder in some evil way.
+;;;
+(defun maybe-make-mh-buffer (name use)
+  (let ((buf (getstring name *buffer-names*)))
+    (cond ((not buf)
+	   (ecase use
+	     (:headers (make-buffer name
+				    :modes '("Headers")
+				    :delete-hook '(cleanup-headers-buffer)))
+
+	     (:message
+	      (make-buffer name :modes '("Message")
+			   :modeline-fields
+			   (value default-message-modeline-fields)
+			   :delete-hook '(cleanup-message-buffer)))
+
+	     (:draft
+	      (let ((buf (make-buffer
+			  name :delete-hook '(cleanup-draft-buffer))))
+		(setf (buffer-minor-mode buf "Draft") t)
+		buf))))
+	  ((hemlock-bound-p 'headers-information :buffer buf)
+	   (setf (buffer-writable buf) t)
+	   (delete-region (buffer-region buf))
+	   (cleanup-headers-buffer buf)
+	   (delete-variable 'headers-information :buffer buf)
+	   buf)
+	  ((hemlock-bound-p 'message-information :buffer buf)
+	   (setf (buffer-writable buf) t)
+	   (delete-region (buffer-region buf))
+	   (cleanup-message-buffer buf)
+	   (delete-variable 'message-information :buffer buf)
+	   buf)
+	  ((hemlock-bound-p 'draft-information :buffer buf)
+	   (error "Attempt to create multiple draft buffers to same draft ~
+	           folder message -- ~S"
+		  name)))))
+
+
+
+;;;; Message buffer modeline fields.
+
+(make-modeline-field
+ :name :deleted-message :width 2
+ :function
+ #'(lambda (buffer window)
+     "Returns \"D \" when message in buffer is deleted."
+     (declare (ignore window))
+     (let* ((minfo (variable-value 'message-information :buffer buffer))
+	    (hmark (message-info-headers-mark minfo)))
+       (cond ((not hmark)
+	      (let ((msgs (message-info-msgs minfo)))
+		(if (and (value virtual-message-deletion)
+			 (mh-sequence-member-p
+			  (if (consp msgs) (car msgs) msgs)
+			  (mh-sequence-list (message-info-folder minfo)
+					    "hemlockdeleted")))
+		    "D "
+		    "")))
+	     ((line-message-deleted (mark-line hmark))
+	      "D ")
+	     (t "")))))
+
+(make-modeline-field
+ :name :replied-to-message :width 1
+ :function
+ #'(lambda (buffer window)
+     "Returns \"A\" when message in buffer is deleted."
+     (declare (ignore window))
+     (let* ((minfo (variable-value 'message-information :buffer buffer))
+	    (hmark (message-info-headers-mark minfo)))
+       (cond ((not hmark)
+	      ;; Could do something nasty here to figure out the right value.
+	      "")
+	     (t
+	      (mark-to-note-replied-msg hmark)
+	      (if (char= (next-character hmark) #\A)
+		  "A"
+		  ""))))))
+
+;;; MARK-TO-NOTE-REPLIED-MSG moves the headers-buffer mark to a line position
+;;; suitable for checking or setting the next character with respect to noting
+;;; that a message has been replied to.
+;;;
+(defun mark-to-note-replied-msg (hmark)
+  (line-start hmark)
+  (find-attribute hmark :digit)
+  (find-attribute hmark :digit #'zerop)
+  (character-offset hmark 1))
+
+
+(defhvar "Default Message Modeline Fields"
+  "This is the default list of modeline-field objects for message buffers."
+  :value
+  (list (modeline-field :hemlock-literal) (modeline-field :package)
+	(modeline-field :modes) (modeline-field :buffer-name)
+	(modeline-field :replied-to-message) (modeline-field :deleted-message)
+	(modeline-field :buffer-pathname) (modeline-field :modifiedp)))
+
+
+
+
+;;;; MH interface.
+
+;;; Running an MH utility.
+;;; 
+
+(defhvar "MH Utility Pathname"
+  "MH utility names are merged with this.  The default is
+   \"/usr/misc/.mh/bin/\"."
+  :value (pathname "/usr/misc/.mh/bin/"))
+
+(defvar *signal-mh-errors* t
+  "This is the default value for whether MH signals errors.  It is useful to
+   bind this to nil when using PICK-MESSAGES with the \"Incorporate New Mail
+   Hook\".")
+
+(defvar *mh-error-output* (make-string-output-stream))
+
+(defun mh (utility args &key (errorp *signal-mh-errors*) environment)
+  "Runs the MH utility with the list of args (suitable for EXT:RUN-PROGRAM),
+   outputting to *standard-output*.  Environment is a list of strings
+   appended with ext:*environment-list*.  This returns t, unless there is
+   an error.  When errorp, this reports any MH errors in the echo area as
+   an editor error, and this does not return; otherwise, nil and the error
+   output from the MH utility are returned."
+  (fresh-line)
+  (let* ((utility
+	  (namestring
+	   (or (probe-file (merge-pathnames utility
+					    (value mh-utility-pathname)))
+	       utility)))
+	 (proc (ext:run-program
+		utility args
+		:output *standard-output*
+		:error *mh-error-output*
+		:env (append environment ext:*environment-list*))))
+    (fresh-line)
+    (ext:process-close proc)
+    (cond ((zerop (ext:process-exit-code proc))
+	   (values t nil))
+	  (errorp
+	   (editor-error "MH Error -- ~A"
+			 (get-output-stream-string *mh-error-output*)))
+	  (t (values nil (get-output-stream-string *mh-error-output*))))))
+
+
+
+;;; Draft folder name and pathname.
+;;; 
+
+(defun mh-draft-folder ()
+  (let ((drafts (mh-profile-component "draft-folder")))
+    (unless drafts
+      (error "There must be a draft-folder component in your profile."))
+    drafts))
+
+(defun mh-draft-folder-pathname ()
+  "Returns the pathname of the MH draft folder directory."
+  (let ((drafts (mh-profile-component "draft-folder")))
+    (unless drafts
+      (error "There must be a draft-folder component in your profile."))
+    (merge-relative-pathnames drafts (mh-directory-pathname))))
+
+
+;;; Current folder name.
+;;; 
+
+(defun mh-current-folder ()
+  "Returns the current MH folder from the context file."
+  (mh-profile-component "current-folder" (mh-context-pathname)))
+
+
+;;; Current message name.
+;;; 
+
+(defun mh-current-message (folder)
+  "Returns the current MH message from the folder's sequence file."
+  (declare (simple-string folder))
+  (let ((folder (strip-folder-name folder)))
+    (mh-profile-component
+     "cur"
+     (merge-pathnames ".mh_sequences"
+		      (merge-relative-pathnames folder
+						(mh-directory-pathname))))))
+
+
+;;; Context pathname.
+;;; 
+
+(defvar *mh-context-pathname* nil)
+
+(defun mh-context-pathname ()
+  "Returns the pathname of the MH context file."
+  (or *mh-context-pathname*
+      (setf *mh-context-pathname*
+	    (merge-pathnames (or (mh-profile-component "context") "context")
+			     (mh-directory-pathname)))))
+
+
+;;; MH directory pathname.
+;;; 
+
+(defvar *mh-directory-pathname* nil)
+
+;;; MH-DIRECTORY-PATHNAME fetches the "path" MH component and bashes it
+;;; appropriately to get an absolute directory pathname.  
+;;; 
+(defun mh-directory-pathname ()
+  "Returns the pathname of the MH directory."
+  (if *mh-directory-pathname*
+      *mh-directory-pathname*
+      (let ((path (mh-profile-component "path")))
+	(unless path (error "MH profile does not contain a Path component."))
+	(setf *mh-directory-pathname*
+	      (truename (merge-relative-pathnames path
+						  (user-homedir-pathname)))))))
+
+;;; Profile components.
+;;; 
+
+(defun mh-profile-component (name &optional (pathname (mh-profile-pathname))
+				            (error-on-open t))
+  "Returns the trimmed string value for the MH profile component name.  If
+   the component is not present, nil is returned.  This may be used on MH
+   context and sequence files as well due to their having the same format.
+   Error-on-open indicates that errors generated by OPEN should not be ignored,
+   which is the default.  When opening a sequence file, it is better to supply
+   this as nil since the file may not exist or be readable in another user's
+   MH folder, and returning nil meaning the sequence could not be found is just
+   as useful."
+  (with-open-stream (s (if error-on-open
+			   (open pathname)
+			   (ignore-errors (open pathname))))
+    (if s
+	(loop
+	  (multiple-value-bind (line eofp) (read-line s nil :eof)
+	    (when (eq line :eof) (return nil))
+	    (let ((colon (position #\: (the simple-string line) :test #'char=)))
+	      (unless colon
+		(error "Bad record ~S in file ~S." line (namestring pathname)))
+	      (when (string-equal name line :end2 colon)
+		(return (string-trim '(#\space #\tab)
+				     (subseq line (1+ colon))))))
+	    (when eofp (return nil)))))))
+
+
+;;; Profile pathname.
+;;; 
+
+(defvar *mh-profile-pathname* nil)
+
+(defun mh-profile-pathname ()
+  "Returns the pathname of the MH profile."
+  (or *mh-profile-pathname*
+      (setf *mh-profile-pathname*
+	    (merge-pathnames (or (cdr (assoc :mh ext:*environment-list*))
+				 ".mh_profile")
+			     (truename (user-homedir-pathname))))))
+
+
+
+
+;;;; Sequence handling.
+
+(declaim (optimize (speed 2))); byte compile off
+
+(defun mark-one-message (folder msg sequence add-or-delete)
+  "Msg is added or deleted to the sequence named sequence in the folder's
+   \".mh_sequence\" file.  Add-or-delete is either :add or :delete."
+  (let ((seq-list (mh-sequence-list folder sequence)))
+    (ecase add-or-delete
+      (:add
+       (write-mh-sequence folder sequence (mh-sequence-insert msg seq-list)))
+      (:delete
+       (when (mh-sequence-member-p msg seq-list)
+	 (write-mh-sequence folder sequence
+			    (mh-sequence-delete msg seq-list)))))))
+
+
+(defun mh-sequence-list (folder name)
+  "Returns a list representing the messages and ranges of id's for the
+   sequence name in folder from the \".mh_sequences\" file.  A second value
+   is returned indicating whether the sequence was found or not."
+  (declare (simple-string folder))
+  (let* ((folder (strip-folder-name folder))
+	 (seq-string (mh-profile-component
+		      name
+		      (merge-pathnames ".mh_sequences"
+				       (merge-relative-pathnames
+					folder (mh-directory-pathname)))
+		      nil)))
+    (if (not seq-string)
+	(values nil nil)
+	(let ((length (length (the simple-string seq-string)))
+	      (result ())
+	      (intervalp nil)
+	      (start 0))
+	  (declare (fixnum length start))
+	  (loop
+	    (multiple-value-bind (msg index)
+				 (parse-integer seq-string
+						:start start :end length
+						:junk-allowed t)
+	      (unless msg (return))
+	      (cond ((or (= index length)
+			 (char/= (schar seq-string index) #\-))
+		     (if intervalp
+			 (setf (cdar result) msg)
+			 (push (cons msg msg) result))
+		     (setf intervalp nil)
+		     (setf start index))
+		    (t
+		     (push (cons msg nil) result)
+		     (setf intervalp t)
+		     (setf start (1+ index)))))
+	    (when (>= start length) (return)))
+	  (values (nreverse result) t)))))
+
+(defun write-mh-sequence (folder name seq-list)
+  "Writes seq-list to folder's \".mh_sequences\" file.  If seq-list is nil,
+   the sequence is removed from the file."
+  (declare (simple-string folder))
+  (let* ((folder (strip-folder-name folder))
+	 (input (merge-pathnames ".mh_sequences"
+				 (merge-relative-pathnames
+				  folder (mh-directory-pathname))))
+	 (input-dir (pathname (directory-namestring input)))
+	 (output (loop (let* ((sym (gensym))
+			      (f (merge-pathnames
+				  (format nil "sequence-file-~A.tmp" sym)
+				  input-dir)))
+			 (unless (probe-file f) (return f)))))
+	 (found nil))
+    (cond ((not (hemlock-ext:file-writable output))
+	   (loud-message "Cannot write sequence temp file ~A.~%~
+	                  Aborting output of ~S sequence."
+			 name (namestring output)))
+	  (t
+	   (with-open-file (in input)
+	     (with-open-file (out output :direction :output)
+	       (loop
+		 (multiple-value-bind (line eofp) (read-line in nil :eof)
+		   (when (eq line :eof)
+		     (return nil))
+		   (let ((colon (position #\: (the simple-string line)
+					  :test #'char=)))
+		     (unless colon
+		       (error "Bad record ~S in file ~S."
+			      line (namestring input)))
+		     (cond ((and (not found) (string-equal name line
+							   :end2 colon))
+			    (sub-write-mh-sequence
+			     out (subseq line 0 colon) seq-list)
+			    (setf found t))
+			   (t (write-line line out))))
+		   (when eofp (return))))
+	       (unless found
+		 (fresh-line out)
+		 (sub-write-mh-sequence out name seq-list))))
+	   (hacking-rename-file output input)))))
+
+(defun sub-write-mh-sequence (stream name seq-list)
+  (when seq-list
+    (write-string name stream)
+    (write-char #\: stream)
+    (let ((*print-base* 10))
+      (dolist (range seq-list)
+	(write-char #\space stream)
+	(let ((low (car range))
+	      (high (cdr range)))
+	  (declare (fixnum low high))
+	  (cond ((= low high)
+		 (prin1 low stream))
+		(t (prin1 low stream)
+		   (write-char #\- stream)
+		   (prin1 high stream))))))
+    (terpri stream)))
+
+
+;;; MH-SEQUENCE-< keeps SORT from consing rest args when FUNCALL'ing #'<.
+;;;
+(defun mh-sequence-< (x y)
+  (< x y))
+
+(defun mh-sequence-insert (item seq-list)
+  "Inserts item into an mh sequence list.  Item can be a string (\"23\"),
+   number (23), or a cons of two numbers ((23 . 23) or (3 . 5))."
+  (let ((range (typecase item
+		 (string (let ((id (parse-integer item)))
+			   (cons id id)))
+		 (cons item)
+		 (number (cons item item)))))
+    (cond (seq-list
+	   (setf seq-list (sort (cons range seq-list)
+				#'mh-sequence-< :key #'car))
+	   (coelesce-mh-sequence-ranges seq-list))
+	  (t (list range)))))
+
+(defun coelesce-mh-sequence-ranges (seq-list)
+  (when seq-list
+    (let* ((current seq-list)
+	   (next (cdr seq-list))
+	   (current-range (car current))
+	   (current-end (cdr current-range)))
+      (declare (fixnum current-end))
+      (loop
+	(unless next
+	  (setf (cdr current-range) current-end)
+	  (setf (cdr current) nil)
+	  (return))
+	(let* ((next-range (car next))
+	       (next-start (car next-range))
+	       (next-end (cdr next-range)))
+	  (declare (fixnum next-start next-end))
+	  (cond ((<= (1- next-start) current-end)
+		 ;;
+		 ;; Extend the current range since the next one overlaps.
+		 (when (> next-end current-end)
+		   (setf current-end next-end)))
+		(t
+		 ;;
+		 ;; Update the current range since the next one doesn't overlap.
+		 (setf (cdr current-range) current-end)
+		 ;;
+		 ;; Make the next range succeed current.  Then make it current.
+		 (setf (cdr current) next)
+		 (setf current next)
+		 (setf current-range next-range)
+		 (setf current-end next-end))))
+	(setf next (cdr next))))
+    seq-list))
+
+
+(defun mh-sequence-delete (item seq-list)
+  "Inserts item into an mh sequence list.  Item can be a string (\"23\"),
+   number (23), or a cons of two numbers ((23 . 23) or (3 . 5))."
+  (let ((range (typecase item
+		 (string (let ((id (parse-integer item)))
+			   (cons id id)))
+		 (cons item)
+		 (number (cons item item)))))
+    (when seq-list
+      (do ((id (car range) (1+ id))
+	   (end (cdr range)))
+	  ((> id end))
+	(setf seq-list (sub-mh-sequence-delete id seq-list)))
+      seq-list)))
+
+(defun sub-mh-sequence-delete (id seq-list)
+  (do ((prev nil seq)
+       (seq seq-list (cdr seq)))
+      ((null seq))
+    (let* ((range (car seq))
+	   (low (car range))
+	   (high (cdr range)))
+      (cond ((> id high))
+	    ((< id low)
+	     (return))
+	    ((= id low)
+	     (cond ((/= low high)
+		    (setf (car range) (1+ id)))
+		   (prev
+		    (setf (cdr prev) (cdr seq)))
+		   (t (setf seq-list (cdr seq-list))))
+	     (return))
+	    ((= id high)
+	     (setf (cdr range) (1- id))
+	     (return))
+	    ((< low id high)
+	     (setf (cdr range) (1- id))
+	     (setf (cdr seq) (cons (cons (1+ id) high) (cdr seq)))
+	     (return)))))
+  seq-list)
+
+
+(defun mh-sequence-member-p (item seq-list)
+  "Returns to or nil whether item is in the mh sequence list.  Item can be a
+   string (\"23\") or a number (23)."
+  (let ((id (typecase item
+	      (string (parse-integer item))
+	      (number item))))
+    (dolist (range seq-list nil)
+      (let ((low (car range))
+	    (high (cdr range)))
+	(when (<= low id high) (return t))))))
+
+
+(defun mh-sequence-strings (seq-list)
+  "Returns a list of strings representing the ranges and messages id's in
+   seq-list."
+  (let ((result nil))
+    (dolist (range seq-list)
+      (let ((low (car range))
+	    (high (cdr range)))
+	(if (= low high)
+	    (push (number-string low) result)
+	    (push (format nil "~D-~D" low high) result))))
+    (nreverse result)))
+
+(declaim (optimize (speed 0))); byte compile again.
+
+
+;;;; CMU Common Lisp support.
+
+;;; HACKING-RENAME-FILE renames old to new.  This is used instead of Common
+;;; Lisp's RENAME-FILE because it merges new pathname with old pathname,
+;;; which loses when old has a name and type, and new has only a type (a
+;;; Unix-oid "dot" file).
+;;;
+(defun hacking-rename-file (old new)
+  (let ((ses-name1 (namestring old))
+	(ses-name2 (namestring new)))
+    (multiple-value-bind (res err) (unix:unix-rename ses-name1 ses-name2)
+      (unless res
+	(error "Failed to rename ~A to ~A: ~A."
+	       ses-name1 ses-name2 (unix:get-unix-error-msg err))))))
+
+
+;;; Folder existence and creation.
+;;;
+
+(defun folder-existsp (folder)
+  "Returns t if the directory for folder exists.  Folder is a simple-string
+   specifying a folder name relative to the MH mail directoy."
+  (declare (simple-string folder))
+  (let* ((folder (strip-folder-name folder))
+	 (pathname (merge-relative-pathnames folder (mh-directory-pathname)))
+	 (pf (probe-file pathname)))
+    (and pf
+	 (null (pathname-name pf))
+	 (null (pathname-type pf)))))
+
+(defun create-folder (folder)
+  "Creates folder directory with default protection #o711 but considers the
+   MH profile for the \"Folder-Protect\" component.  Folder is a simple-string
+   specifying a folder name relative to the MH mail directory."
+  (declare (simple-string folder))
+  (let* ((folder (strip-folder-name folder))
+	 (pathname (merge-relative-pathnames folder (mh-directory-pathname)))
+	 (ses-name (namestring pathname))
+	 (length-1 (1- (length ses-name)))
+	 (name (if (= (position #\/ ses-name :test #'char= :from-end t)
+		      length-1)
+		   (subseq ses-name 0 (1- (length ses-name)))
+		   ses-name))
+	 (protection (mh-profile-component "folder-protect")))
+    (when protection
+      (setf protection
+	    (parse-integer protection :radix 8 :junk-allowed t)))
+    (multiple-value-bind (winp err)
+			 (unix:unix-mkdir name (or protection #o711))
+      (unless winp
+	(error "Couldn't make directory ~S: ~A"
+	       name
+	       (unix:get-unix-error-msg err)))
+      (check-folder-name-table)
+      (setf (getstring folder *folder-name-table*) t))))
+
+
+;;; Checking for mail.
+;;;
+
+(defvar *mailbox* nil)
+
+(defun new-mail-p ()
+ (unless *mailbox*
+   (setf *mailbox*
+	 (probe-file (or (cdr (assoc :mail ext:*environment-list*))
+			 (cdr (assoc :maildrop ext:*environment-list*))
+			 (mh-profile-component "MailDrop")
+			 (merge-pathnames
+			  (cdr (assoc :user ext:*environment-list*))
+			  "/usr/spool/mail/")))))
+  (when *mailbox*
+    (multiple-value-bind (success dev ino mode nlink uid gid rdev size
+			  atime)
+			 (unix:unix-stat (namestring *mailbox*))
+      (declare (ignore dev ino nlink uid gid rdev atime))
+      (and success
+	   (plusp (logand unix:s-ifreg mode))
+	   (not (zerop size))))))
+
+
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/netnews.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/netnews.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/netnews.lisp	(revision 13309)
@@ -0,0 +1,2407 @@
+;;; -*- Package: Hemlock; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Blaine Burks
+;;;
+;;; This file implements the reading of bulletin boards from within Hemlock
+;;; via a known NNTP server.  Something should probably be done so that
+;;; when the server is down Hemlock doesn't hang as I suspect it will.
+;;;
+;;; Warning:    Throughout this file, it may appear I should have bound
+;;;             the nn-info-stream and nn-info-header-stream slots instead
+;;;             of making multiple structure accesses.  This was done on
+;;;             purpose because we don't find out if NNTP timed us out until
+;;;             we make an attempt to execute another command.  This code
+;;;             recovers by resetting the header-stream and stream slots in
+;;;             the nn-info structure to new streams.  If the structure
+;;;             access were not made again and NNTP had timed us out, we
+;;;             would be making requests on a defunct stream.
+;;; 
+
+(in-package :hemlock)
+
+
+
+
+;;;; Netnews data structures.
+
+(defparameter default-netnews-headers-length 1000
+  "How long the header-cache and message-ids arrays should be made on startup.")
+
+(defstruct (netnews-info
+	    (:conc-name nn-info-)
+	    (:print-function
+	     (lambda (nn s d)
+	       (declare (ignore nn d))
+	       (write-string "#<Netnews Info>" s))))
+  (updatep (ext:required-argument) :type (or null t))
+  (from-end-p nil :type (or null t))
+  ;;
+  ;; The string name of the current group.
+  (current (ext:required-argument) :type simple-string)
+  ;;
+  ;; The number of the latest message read in the current group.
+  (latest nil :type (or null fixnum))
+  ;;
+  ;; The cache of header info for the current group.  Each element contains
+  ;; an association list of header fields to contents of those fields.  Indexed
+  ;; by id offset by the first message in the group.
+  (header-cache nil :type (or null simple-vector))
+  ;;
+  ;; The number of HEAD requests currently waiting on the header stream.
+  (batch-count nil :type (or null fixnum))
+  ;;
+  ;; The list of newsgroups to read.
+  (groups (ext:required-argument) :type cons)
+  ;;
+  ;; A vector of message ids indexed by buffer-line for this headers buffer.
+  (message-ids nil :type (or null vector))
+  ;;
+  ;; Where to insert the next batch of headers.
+  mark
+  ;;
+  ;; The message buffer used to view article bodies.
+  buffer
+  ;;
+  ;; A list of message buffers that have been marked as undeletable by the user.
+  (other-buffers nil :type (or null cons))
+  ;;
+  ;; The window used to display buffer when \"Netnews Read Style\" is :multiple.
+  message-window
+  ;;
+  ;; The window used to display headers when \"Netnews Read Style\" is
+  ;; :multiple.
+  headers-window
+  ;;
+  ;; How long the message-ids and header-cache arrays are.  Reuse this array,
+  ;; but don't break if there are more messages than we can handle.
+  (array-length default-netnews-headers-length :type fixnum)
+  ;;
+  ;; The id of the first message in the current group.
+  (first nil :type (or null fixnum))
+  ;;
+  ;; The id of the last message in the current-group.
+  (last nil :type (or null fixnum))
+  ;;
+  ;; Article number of the first visible header.
+  (first-visible nil :type (or null fixnum))
+  ;;
+  ;; Article number of the last visible header.
+  (last-visible nil :type (or null fixnum))
+  ;;
+  ;; Number of the message that is currently displayed in buffer.  Initialize
+  ;; to -1 so I don't have to constantly check for the nullness of it.
+  (current-displayed-message -1 :type (or null fixnum))
+  ;;
+  ;; T if the last batch of headers is waiting on the header stream.
+  ;; This is needed so NN-WRITE-HEADERS-TO-MARK can set the messages-waiting
+  ;; slot to nil.
+  (last-batch-p nil :type (or null t))
+  ;;
+  ;; T if there are more headers in the current group. Nil otherwise.
+  (messages-waiting nil :type (or null t))
+  ;;
+  ;; The stream on which we request headers from NNTP.
+  header-stream
+  ;;
+  ;; The stream on which we request everything but headers from NNTP.
+  stream)
+
+(defmode "News-Headers" :major-p t)
+
+
+
+
+;;;; The netnews-message-info and post-info structures.
+
+(defstruct (netnews-message-info
+	    (:conc-name nm-info-)
+	    (:print-function
+	     (lambda (nn s d)
+	       (declare (ignore nn d))
+	       (write-string "#<Netnews Message Info>" s))))
+  ;; The headers buffer (if there is one) associated with this message buffer.
+  headers-buffer
+  ;; The draft buffer (if there is one) associated with this message buffer.
+  draft-buffer
+  ;; The post buffer (if there is one) associated with this message buffer.
+  post-buffer
+  ;; This is need because we want to display what message this is in the
+  ;; modeline field of a message buffer.
+  (message-number nil :type (or null fixnum))
+  ;;  Set to T when we do not want to reuse this buffer.
+  keep-p)
+
+(defstruct (post-info
+	    (:print-function
+	     (lambda (nn s d)
+	       (declare (ignore nn d))
+	       (write-string "#<Post Info>" s))))
+  ;; The NNTP stream over which to send this post.
+  stream
+  ;; When replying in another window, the reply window.
+  reply-window
+  ;; When replying in another window, the message window.
+  message-window
+  ;; The message buffer associated with this post.
+  message-buffer
+  ;; The Headers buffer associated with this post.
+  headers-buffer)
+
+
+
+
+;;;; Command Level Implementation of "News-Headers" mode.
+
+(defhvar "Netnews Database File"
+  "This value is merged with your home directory to get a path to your netnews
+   pointers file."
+  :value ".hemlock-netnews")
+
+(defhvar "Netnews Read Style"
+  "How you like to read netnews.  A value of :single will cause netnews
+   mode to use a single window for headers and messages, and a value of
+   :multiple will cause the current window to be split so that Headers take
+   up \"Netnews Headers Proportion\" of what was the current window, and a
+   message bodies buffer the remaining portion.  Changing the value of this
+   variable dynamically affects netnews reading."
+  :value :multiple)
+
+(unless (modeline-field :netnews-message)
+  (make-modeline-field
+   :name :netnews-message
+   :width 14
+   :function #'(lambda (buffer window)
+		 (declare (ignore window))
+		 (let* ((nm-info (variable-value 'netnews-message-info
+						 :buffer buffer))
+			(nn-info (variable-value 'netnews-info
+						 :buffer (nm-info-headers-buffer
+							  nm-info))))
+		   (format nil "~D of ~D"
+			   (nm-info-message-number nm-info)
+			   (1+ (- (nn-info-last nn-info)
+				  (nn-info-first nn-info))))))))
+
+(unless (modeline-field :netnews-header-info)
+  (make-modeline-field
+   :name :netnews-header-info
+   :width 24
+   :function
+   #'(lambda (buffer window)
+       (declare (ignore window))
+       (let ((nn-info (variable-value 'netnews-info :buffer buffer)))
+	 (format nil "~D before, ~D after"
+		 (- (nn-info-first-visible nn-info) (nn-info-first nn-info))
+		 (- (nn-info-last nn-info) (nn-info-last-visible nn-info)))))))
+
+(defvar *nn-headers-buffer* nil
+  "If \"Netnews\" was invoked without an argument an not exited, this
+   holds the headers buffer for reading netnews.")
+
+(defvar *netnews-kill-strings* nil)
+
+(defhvar "Netnews Kill File"
+  "This value is merged with your home directory to get the pathname of
+   your netnews kill file.  If any of the strings in this file (one per
+   line) appear in a subject header while reading netnews, they will have a
+   \"K\" in front of them, and \"Netnews Next Line\" and \"Netnews Previous
+   Line\" will never land you on one.  Use \"Next Line\" and \"Previous
+   Line\" to read Killed messages.  Defaults to \".hemlock-kill\"."
+  :value ".hemlock-kill")
+
+(defhvar "Netnews New Group Style"
+  "Determines what happend when you read a group that you have never read
+   before.  When :from-start, \"Netnews\" will read from the beginning of a
+   new group forward.  When :from-end, the default, \"Netnews\" will read
+   from the end backward group.  Otherwise this variable is a number
+   indicating that \"Netnews\" should start that many messages from the end
+   of the group and read forward from there."
+  :value :from-end)
+
+(defhvar "Netnews Start Over Threshold"
+  "If you have read a group before, and the number of new messages exceeds
+   this number, Hemlock asks whether you want to start reading from the end
+   of this group.  The default is 300."
+  :value 300)
+
+(defcommand "Netnews" (p &optional group-name from-end-p browse-buf (updatep t))
+  "Enter a headers buffer and read groups from \"Netnews Group File\".
+   With an argument prompts for a group and reads it."
+  "Enter a headers buffer and read groups from \"Netnews Group File\".
+   With an argument prompts for a group and reads it."
+  (cond
+   ((and *nn-headers-buffer* (not p) (not group-name))
+    (change-to-buffer *nn-headers-buffer*))
+   (t
+    (let* ((single-group (if p (prompt-for-string :prompt "Group to read: "
+						  :help "Type the name of ~
+						  the group you want ~
+						  to scan."
+						  :trim t)))
+	   (groups (cond
+		    (group-name (list group-name))
+		    (single-group (list single-group))
+		    (t
+		     (let ((group-file (merge-pathnames
+					(value netnews-group-file)
+					(user-homedir-pathname)))) 
+		       (when (probe-file group-file)
+			 (let ((res nil))
+			   (with-open-file (s group-file :direction :input)
+			     (loop
+			       (let ((group (read-line s nil nil)))
+				 (unless group (return (nreverse res)))
+				 (pushnew group res)))))))))))
+      (unless (or p groups)
+	(editor-error "No groups to read.  See \"Netnews Group File\" and ~
+	               \"Netnews Browse\"."))
+      (when updatep (nn-assure-database-exists))
+      (nn-parse-kill-file)
+      (multiple-value-bind (stream header-stream) (streams-for-nntp)
+	(multiple-value-bind
+	    (buffer-name clashp)
+	    (nn-unique-headers-name (car groups))
+	  (if (and (or p group-name) clashp)
+	      (change-to-buffer (getstring clashp *buffer-names*))
+	      (let* ((buffer (make-buffer
+			      buffer-name
+			      :modes '("News-Headers")
+			      :modeline-fields
+			      (append (value default-modeline-fields)
+				      (list (modeline-field
+					     :netnews-header-info)))
+			      :delete-hook 
+			      (list #'netnews-headers-delete-hook)))
+		     (nn-info (make-netnews-info
+			       :current (car groups)
+			       :groups groups
+			       :updatep updatep
+			       :headers-window (current-window)
+			       :mark (copy-mark (buffer-point buffer))
+			       :header-stream header-stream
+			       :stream stream)))
+		(unless (or p group-name) (setf *nn-headers-buffer* buffer))
+		(when (and clashp (not (or p group-name)))
+		  (message "Buffer ~S also contains headers for ~A"
+			   clashp (car groups)))
+		(defhvar "Netnews Info"
+		  "A structure containing the current group, a list of
+		   groups, a book-keeping mark, a stream we get headers on,
+		   and the stream on which we request articles."
+		  :buffer buffer
+		  :value nn-info)
+		(setf (buffer-writable buffer) nil)
+		(defhvar "Netnews Browse Buffer"
+		  "This variable is the associated \"News-Browse\" buffer
+		   in a \"News-Headers\" buffer created from
+		   \"News-Browse\" mode."
+		  :buffer buffer
+		  :value browse-buf)
+		(setup-group (car groups) nn-info buffer from-end-p)))))))))
+
+
+(defun nn-parse-kill-file ()
+  (let ((filename (merge-pathnames (value netnews-kill-file)
+				   (user-homedir-pathname))))
+    (when (probe-file filename)
+      (with-open-file (s filename :direction :input)
+	(loop
+	  (let ((kill-string (read-line s nil nil)))
+	    (unless kill-string (return))
+	    (pushnew kill-string *netnews-kill-strings*)))))))
+
+;;; NETNEWS-HEADERS-DELETE-HOOK closes the stream slots in netnews-info,
+;;; deletes the bookkeeping mark into buffer, sets the headers slots of any
+;;; associated post-info or netnews-message-info structures to nil so
+;;; "Netnews Go To Headers Buffer" will not land you in a buffer that does
+;;; not exist, and sets *nn-headers-buffer* to nil so next time we invoke
+;;; "Netnews" it will start over.
+;;; 
+(defun netnews-headers-delete-hook (buffer)
+  (let ((nn-info (variable-value 'netnews-info :buffer buffer)))
+    ;; Disassociate all message buffers.
+    ;; 
+    (dolist (buf (nn-info-other-buffers nn-info))
+      (setf (nm-info-headers-buffer (variable-value 'netnews-message-info
+						    :buffer buf))
+	    nil))
+    (let ((message-buffer (nn-info-buffer nn-info)))
+      (when message-buffer
+	(setf (nm-info-headers-buffer (variable-value 'netnews-message-info
+						      :buffer message-buffer))
+	      nil)))
+    (close (nn-info-stream nn-info))
+    (close (nn-info-header-stream nn-info))
+    (delete-mark (nn-info-mark nn-info))
+    (when (eq *nn-headers-buffer* buffer)
+      (setf *nn-headers-buffer* nil))))
+
+(defun nn-unique-headers-name (group-name)
+  (let ((original-name (concatenate 'simple-string "Netnews " group-name)))
+    (if (getstring original-name *buffer-names*)
+	(let ((name nil)
+	      (number 0))
+	  (loop
+	    (setf name (format nil "Netnews ~A ~D" group-name (incf number)))
+	    (unless (getstring name *buffer-names*)
+	      (return (values name original-name)))))
+	(values original-name nil))))
+
+;;; NN-ASSURE-DATABASE-EXISTS does just that.  If the file determined by the
+;;; value of "Netnews Database Filename" does not exist, then it gets
+;;; created.
+;;; 
+(defun nn-assure-database-exists ()
+  (let ((filename (merge-pathnames (value netnews-database-file)
+				   (user-homedir-pathname))))
+    (unless (probe-file filename)
+      (message "Creating netnews database file.")
+      (close (open filename :direction :output :if-does-not-exist :create)))))
+
+(defhvar "Netnews Fetch All Headers"
+  "When NIL, all netnews reading commands will fetch headers in batches for
+   increased efficiency.  Any other value will cause these commands to fetch
+   all the headers.  This will take a long time if there are a lot."
+  :value nil)
+
+(defcommand "Netnews Look at Newsgroup" (p)
+  "Prompts for the name of a newsgroup and reads it, regardless of what is
+   in and not modifying the \"Netnews Database File\"."
+  "Prompts for the name of a newsgroup and reads it, regardless of what is
+   in and not modifying the \"Netnews Database File\"."
+  (declare (ignore p))
+  (netnews-command nil (prompt-for-string :prompt "Group to look at: "
+					  :help "Type the name of ~
+					  the group you want ~
+					  to look at."
+					  :trim t)
+		   nil nil nil))
+  
+;;; SETUP-GROUP is the guts of this group reader.  It sets up a headers
+;;; buffer in buffer for group group-name.  This consists of sending a group
+;;; command to both the header-stream and normal stream and then getting the
+;;; last message read in group-name from the database file and setting the
+;;; appropriate slots in the nn-info structure.  The first batch of messages
+;;; is then requested and inserted, and room for message-ids is allocated.
+;;; 
+(defun setup-group (group-name nn-info buffer &optional from-end-p)
+  ;; Do not bind stream or header-stream because if a timeout has occurred
+  ;; before these calls are invoked, they would be bogus.
+  ;; 
+  (nntp-group group-name (nn-info-stream nn-info)
+	      (nn-info-header-stream nn-info))
+  (process-status-response (nn-info-stream nn-info) nn-info)
+  (let ((response (process-status-response (nn-info-header-stream nn-info)
+					   nn-info)))
+    (cond ((not response)
+	   (message "~A is not the name of a netnews group.~%"
+		    (nn-info-current nn-info))
+	   (change-to-next-group nn-info buffer))
+	  (t
+	   (multiple-value-bind (number first last)
+				(group-response-args response)
+	     (declare (ignore first))
+	     (message "Setting up ~A" group-name)
+	     ;; If nn-info-updatep is nil, then we fool ourselves into
+	     ;; thinking we've never read this group before by making
+	     ;; last-read nil.  We determine first here because the first
+	     ;; that NNTP gives us is way way out of line.
+	     ;;
+	     (let ((last-read (if (nn-info-updatep nn-info)
+				  (nn-last-read-message-number group-name)))
+		   (first (1+ (- last number))))
+	       ;; Make sure there is at least one new message in this group.
+	       (cond
+		((and last-read (= last-read last))
+		 (message "No new messages in ~A" group-name)
+		 (setf (nn-info-latest nn-info) last)
+		 (change-to-next-group nn-info buffer))
+		((zerop number)
+		 (message "No messages AVAILABLE in ~A" group-name)
+		 (setf (nn-info-latest nn-info) last)
+		 (change-to-next-group nn-info buffer))
+		(t
+		 (let ((latest (if (and last-read (> last-read first))
+				   last-read
+				   first)))
+		   (if (or (and (eq (value netnews-new-group-style) :from-end)
+				(or (= latest first)
+				    (and (> (- last latest)
+					    (value
+					     netnews-start-over-threshold))
+					 (prompt-for-y-or-n
+					  :prompt
+					  `("There are ~D new messages.  ~
+					     Read from the end of this ~
+					     group? " ,(- last latest))
+					  :default "Y"
+					  :default-string "Y"
+					  :help "Y starts reading from the ~
+					         end.  N starts reading where ~
+						 you left off many messages ~
+						 back."))))
+			   from-end-p)
+		       (setf (nn-info-from-end-p nn-info) t))
+
+		   (cond ((nn-info-from-end-p nn-info)
+			  (setf (nn-info-first-visible nn-info) nil)
+			  (setf (nn-info-last-visible nn-info) last))
+			 (t
+			  ; (setf (nn-info-first-visible nn-info) latest)
+			  (setf (nn-info-first-visible nn-info) (1+ latest))
+			  (setf (nn-info-last-visible nn-info) nil)))
+		   (setf (nn-info-first nn-info) first)
+		   (setf (nn-info-last nn-info) last)
+		   (setf (nn-info-latest nn-info) latest))
+		 ;;
+		 ;; Request the batch before setting message-ids so they start
+		 ;; coming before we need them.
+		 (nn-request-next-batch nn-info
+					(value netnews-fetch-all-headers))
+		 (let ((message-ids (nn-info-message-ids nn-info))
+		       (header-cache (nn-info-header-cache nn-info))
+		       (length (1+ (- last first))))
+		   (multiple-value-setq
+		       (message-ids header-cache)
+		       (cond ((> length (nn-info-array-length nn-info))
+			      (setf (nn-info-array-length nn-info) length)
+			      (values (make-array length :fill-pointer 0)
+				      (make-array length
+						  :initial-element nil)))
+			     (message-ids
+			      (setf (fill-pointer message-ids) 0)
+			      (values message-ids header-cache))
+			     (t
+			      (values (make-array (nn-info-array-length nn-info)
+						  :fill-pointer 0)
+				      (make-array (nn-info-array-length nn-info)
+						  :initial-element nil)))))
+		   (setf (nn-info-message-ids nn-info) message-ids)
+		   (setf (nn-info-header-cache nn-info) header-cache))
+		 (nn-write-headers-to-mark nn-info buffer)
+		 (change-to-buffer buffer)))))))))
+
+;;; NN-LAST-READ-MESSAGE-NUMBER reads the last read message in group-name
+;;; from the value of "Netnews Database File".  It is SETF'able and the
+;;; SETF method is %SET-LAST-READ-MESSAGE-NUMBER.
+;;; 
+(defun nn-last-read-message-number (group-name)
+  (with-open-file (s (merge-pathnames (value netnews-database-file)
+				      (user-homedir-pathname))
+		     :direction :input :if-does-not-exist :error)
+    (loop
+      (let ((read-group-name (read-line s nil nil)))
+	(unless read-group-name (return nil))
+	(when (string-equal read-group-name group-name)
+	  (let ((last-read (read-line s nil nil)))
+	    (if last-read
+		(return (parse-integer last-read))
+		(error "Should have been a message number ~
+		following ~S in database file."
+		       group-name))))))))
+
+(defun %set-nn-last-read-message-number (group-name new-value)
+  (with-open-file (s (merge-pathnames (value netnews-database-file)
+				      (user-homedir-pathname))
+		     :direction :io :if-does-not-exist :error
+		     :if-exists :overwrite)
+    (unless (loop
+	      (let ((read-group-name (read-line s nil nil)))
+		(unless read-group-name (return nil))
+		(when (string-equal read-group-name group-name)
+		  ;; File descriptor streams do not do the right thing with
+		  ;; :io/:overwrite streams, so work around it by setting it
+		  ;; explicitly.
+		  ;;
+		  (file-position s (file-position s))
+		  ;; Justify the number so that if the number of digits in it
+		  ;; changes, we won't overwrite the next group name.
+		  ;;
+		  (format s "~14D~%" new-value)
+		  (return t))))
+      (write-line group-name s)
+      (format s "~14D~%" new-value))))
+
+(defsetf nn-last-read-message-number %set-nn-last-read-message-number)
+
+(defconstant nntp-eof ".
+"
+  "NNTP marks the end of a textual response with this.  NNTP also recognizes
+   this as the end of a post.")
+
+;;; This macro binds a variable to each successive line of input from NNTP
+;;; and exits when it sees the NNTP end-of-file-marker, a period by itself on
+;;; a line.
+;;;
+(defmacro with-input-from-nntp ((var stream) &body body)
+  "Body is executed with var bound to successive lines of input from nntp.
+   Exits at the end of a response, returning whatever the last execution of
+   Body returns, or nil if there was no input.
+   Take note: this is only to be used for textual responses.  Status responses
+   are of an entirely different nature."
+  (let ((return-value (gensym)))
+    `(let ((,return-value nil)
+	   (,var ""))
+       (declare (simple-string ,var))
+       (loop
+	 (setf ,var (read-line ,stream))
+	 (when (string= ,var nntp-eof) (return ,return-value))
+	 (setf ,return-value (progn ,@body))))))
+
+
+;;; Writing the date, from, and subject fields to a mark.
+
+(defhvar "Netnews Before Date Field Pad"
+  "How many spaces should be inserted before the date in Netnews.  The default
+   is 1."
+  :value 1)
+
+(defhvar "Netnews Date Field Length"
+  "How long the date field should be in \"News-Headers\" buffers.  The
+   default is 6"
+  :value 6)
+
+(defhvar "Netnews Line Field Length"
+  "How long the line field should be in \"News-Headers\" buffers. The
+   default is 3"
+  :value 3)
+
+(defhvar "Netnews From Field Length"
+  "How long the from field should be in \"News-Headers\" buffers.  The
+   default is 20."
+  :value 20)
+
+(defhvar "Netnews Subject Field Length"
+  "How long the subject field should be in \"News-Headers\" buffers.  The
+   default is 43."
+  :value 43)
+
+(defhvar "Netnews Field Padding"
+  "How many spaces should be left between the netnews date, from, lines, and
+   subject fields.  The default is 2."
+  :value 2)
+
+;;;
+(defconstant netnews-space-string
+  (make-string 70 :initial-element #\space))
+;;;
+(defconstant missing-message (cons nil nil)
+  "Use this as a marker so nn-write-headers-to-mark doesn't try to insert
+   a message that is not really there.")
+
+;;; NN-CACHE-HEADER-INFO stashes all header information into an array for
+;;; later use.
+;;; 
+(defun nn-cache-header-info (nn-info howmany use-header-stream-p)
+  (let* ((cache (nn-info-header-cache nn-info))
+	 (message-ids (nn-info-message-ids nn-info))
+	 (stream (if use-header-stream-p
+		     (nn-info-header-stream nn-info)
+		     (nn-info-stream nn-info)))
+	 (from-end-p (nn-info-from-end-p nn-info))
+	 (old-count 0))
+    (declare (fixnum old-count))
+    (when from-end-p
+      (setf old-count (length message-ids))
+      (do ((i (length message-ids) (1- i)))
+	  ((minusp i) nil)
+	(setf (aref message-ids (+ i howmany)) (aref message-ids i)))
+      (setf (fill-pointer message-ids) 0))
+    (let ((missing-message-count 0)
+	  (offset (nn-info-first nn-info)))
+      (dotimes (i howmany)
+	(let ((response (process-status-response stream)))
+	  (if response
+	      (let* ((id (head-response-args response))
+		     (index (- id offset)))
+		(vector-push id message-ids)
+		(setf (svref cache index) nil)
+		(with-input-from-nntp (string stream)
+				      (let ((colonpos (position #\: string)))
+					(when colonpos
+					  (push (cons (subseq string 0 colonpos)
+						      (subseq string
+							      (+ colonpos 2)))
+						(svref cache index))))))
+	      (incf missing-message-count))))
+      (when from-end-p
+	(when (plusp missing-message-count)
+	  (dotimes (i old-count)
+	    (setf (aref message-ids (- (+ i howmany) missing-message-count))
+		  (aref message-ids (+ i howmany)))))
+	(setf (fill-pointer message-ids)
+	      (- (+ old-count howmany) missing-message-count))))))
+
+(defconstant netnews-field-na "NA"
+  "This string gets inserted when NNTP doesn't find a field.")
+
+(defconstant netnews-field-na-length (length netnews-field-na)
+  "The length of netnews-field-na")
+
+(defun nn-write-headers-to-mark (nn-info buffer &optional fetch-rest-p
+					 out-of-order-p)
+  (let* ((howmany (nn-info-batch-count nn-info))
+	 (from-end-p (nn-info-from-end-p nn-info))
+	 (cache (nn-info-header-cache nn-info))
+	 (old-point (copy-mark (buffer-point buffer) (if from-end-p
+							 :left-inserting
+							 :right-inserting)))
+	 (messages-waiting (nn-info-messages-waiting nn-info))
+	 (mark (nn-info-mark nn-info)))
+    (unless messages-waiting
+      (return-from nn-write-headers-to-mark nil))
+    (if from-end-p
+	(buffer-start mark)
+	(buffer-end mark))
+    (nn-cache-header-info nn-info howmany (not out-of-order-p))
+    (with-writable-buffer (buffer)
+      (with-mark ((check-point mark :right-inserting))
+	(macrolet ((mark-to-pos (mark pos)
+		     `(insert-string ,mark netnews-space-string
+				     0 (- ,pos (mark-column ,mark))))
+		   (insert-field (mark field-string field-length)
+		     `(if ,field-string
+			  (insert-string ,mark ,field-string
+					 0 (min ,field-length
+						(1- (length ,field-string))))
+			  (insert-string ,mark netnews-field-na
+					 0 (min ,field-length
+						netnews-field-na-length)))))
+	  (let* ((line-start (+ (value netnews-before-date-field-pad)
+				(value netnews-date-field-length)
+				(value netnews-field-padding)))
+		 (from-start (+ line-start
+				(value netnews-line-field-length)
+				(value netnews-field-padding)))
+		 (subject-start (+ from-start
+				   (value netnews-from-field-length)
+				   (value netnews-field-padding)))
+		 (start (- messages-waiting (nn-info-first nn-info)))
+		 (end (1- (+ start howmany))))
+	    (do ((i start (1+ i)))
+		((> i end))
+	      (let ((assoc-list (svref cache i)))
+		(unless (null assoc-list)
+		  (insert-string mark netnews-space-string
+				 0 (value netnews-before-date-field-pad))
+		  (let* ((date-field (cdr (assoc "date" assoc-list
+						 :test #'string-equal)))
+			 (universal-date (if date-field
+					     (ext:parse-time date-field
+							     :end (1- (length date-field))))))
+		    (insert-field
+		     mark
+		     (if universal-date
+			 (string-capitalize
+			  (format-universal-time nil universal-date
+						 :style :government
+						 :print-weekday nil))
+			 date-field)
+		     (value netnews-date-field-length)))
+		  (mark-to-pos mark line-start)
+		  (insert-field mark (cdr (assoc "lines" assoc-list
+						 :test #'string-equal))
+				(value netnews-line-field-length))
+		  (mark-to-pos mark from-start)
+		  (insert-field mark (cdr (assoc "from" assoc-list
+						 :test #'string-equal))
+				(value netnews-from-field-length))
+		  (mark-to-pos mark subject-start)
+		  (insert-field mark (cdr (assoc "subject" assoc-list
+						 :test #'string-equal))
+				(value netnews-subject-field-length))
+		  (insert-character mark #\newline))))))
+	(cond (out-of-order-p
+	       (setf (nn-info-first-visible nn-info) messages-waiting))
+	      (t
+	       (if (nn-info-from-end-p nn-info)
+		   (setf (nn-info-first-visible nn-info) messages-waiting)
+		   (setf (nn-info-last-visible nn-info)
+			 (1- (+ messages-waiting howmany))))
+	       (if (nn-info-last-batch-p nn-info)
+		   (setf (nn-info-messages-waiting nn-info) nil)
+		   (nn-request-next-batch nn-info fetch-rest-p))))
+	(when (mark= mark check-point)
+	  (message "All messages in last batch were missing, getting more."))
+	(move-mark (buffer-point buffer) old-point)
+	(delete-mark old-point)))))
+
+;;; NN-MAYBE-GET-MORE-HEADERS gets more headers if the point of the headers
+;;; buffer is on an empty line and there are some.  Returns whether it got more
+;;; headers, i.e., if it is time to go on to the next group.
+;;; 
+(defun nn-maybe-get-more-headers (nn-info)
+  (let ((headers-buffer (line-buffer (mark-line (nn-info-mark nn-info)))))
+    (when (empty-line-p (buffer-point headers-buffer))
+      (cond ((and (nn-info-messages-waiting nn-info)
+		  (not (nn-info-from-end-p nn-info)))
+	     (nn-write-headers-to-mark nn-info headers-buffer)
+	     t)
+	    (t :go-on)))))
+
+(defhvar "Netnews Batch Count"
+  "Determines how many headers the Netnews facility will fetch at a time.
+   The default is 50."
+  :value 50)
+
+;;; NN-REQUEST-NEXT-BATCH requests the next batch of messages in a group.
+;;; For safety, don't do anything if there is no next-batch start.
+;;; 
+(defun nn-request-next-batch (nn-info &optional fetch-rest-p)
+  (if (nn-info-from-end-p nn-info)
+      (nn-request-backward nn-info fetch-rest-p)
+      (nn-request-forward nn-info fetch-rest-p)))
+
+(defun nn-request-forward (nn-info fetch-rest-p)
+  (let* ((last-visible (nn-info-last-visible nn-info))
+	 (last (nn-info-last nn-info))
+	 (batch-start (if last-visible
+			  (1+ (nn-info-last-visible nn-info))
+			  (1+ (nn-info-latest nn-info))))
+	 (header-stream (nn-info-header-stream nn-info))
+	 (batch-end (if fetch-rest-p
+			last
+			(1- (+ batch-start (value netnews-batch-count))))))
+    ;; If this is the last batch, adjust batch-end appropriately.
+    ;;
+    (when (>= batch-end last)
+      (setf batch-end last)
+      (setf (nn-info-last-batch-p nn-info) t))
+    (setf (nn-info-batch-count nn-info) (1+ (- batch-end batch-start)))
+    (setf (nn-info-messages-waiting nn-info) batch-start)
+    (nn-send-many-head-requests header-stream batch-start batch-end nil)))
+
+(defun nn-request-backward (nn-info fetch-rest-p
+				    &optional (use-header-stream-p t))
+  (let* ((first-visible (nn-info-first-visible nn-info))
+	 (batch-end (if first-visible
+			(1- (nn-info-first-visible nn-info))
+			(nn-info-last nn-info)))
+	 (stream (if use-header-stream-p
+		     (nn-info-header-stream nn-info)
+		     (nn-info-stream nn-info)))
+	 (first (nn-info-first nn-info))
+	 (batch-start (if fetch-rest-p
+			  first
+			  (1+ (- batch-end (value netnews-batch-count))))))
+    ;; If this is the last batch, adjust batch-end appropriately.
+    ;;
+    (when (<= batch-start first)
+      (setf batch-start first)
+      (setf (nn-info-last-batch-p nn-info) t))
+    (setf (nn-info-batch-count nn-info) (1+ (- batch-end batch-start)))
+    (setf (nn-info-messages-waiting nn-info) batch-start)
+    (nn-send-many-head-requests stream batch-start batch-end
+				(not use-header-stream-p))))
+
+;;; NN-REQUEST-OUT-OF-ORDER is called when the user is reading a group normally
+;;; and decides he wants to see some messages before the first one visible.
+;;; To accomplish this without disrupting the normal flow of things, we fool
+;;; ourselves into thinking we are reading the group from the end, remembering
+;;; several slots that could be modified in requesting thesse messages.
+;;; When we are done, return state to what it was for reading a group forward.
+;;; 
+(defun nn-request-out-of-order (nn-info headers-buffer)
+  (let ((messages-waiting (nn-info-messages-waiting nn-info))
+	(batch-count (nn-info-batch-count nn-info))
+	(last-batch-p (nn-info-last-batch-p nn-info)))
+    (nn-request-backward nn-info nil nil)
+    (setf (nn-info-from-end-p nn-info) t)
+    (nn-write-headers-to-mark nn-info headers-buffer nil t)
+    (setf (nn-info-messages-waiting nn-info) messages-waiting)
+    (setf (nn-info-batch-count nn-info) batch-count)
+    (setf (nn-info-last-batch-p nn-info) last-batch-p)
+    (setf (nn-info-from-end-p nn-info) nil)))
+
+(declaim (special *nn-last-command-issued*))
+
+(defun nn-send-many-head-requests (stream first last out-of-order-p)
+  (do ((i first (1+ i)))
+      ((> i last))
+    (nntp-head i stream))
+  (setf *nn-last-command-issued*
+	(list (if out-of-order-p :out-of-order :header)
+	      first last out-of-order-p)))
+
+(defvar nn-minimum-header-batch-count 30
+  "The minimum number of headers to fetch at any given time.")
+
+
+
+
+;;;; "News-Message" mode.
+
+(defmode "News-Message" :major-p t)
+
+
+
+
+;;;; Commands for viewing articles.
+
+(defcommand "Netnews Show Article" (p)
+  "Show the message the point is on.  If it is the same message that is
+   already in the message buffer and \"Netnews Read Style\" is :multiple,
+   then just scroll the window down prefix argument lines"
+  "Show the message the point is on.  If it is the same message that is
+   already in the message buffer and \"Netnews Read Style\" is :multiple,
+   then just scroll the window down prefix argument lines"
+  (nn-show-article (value netnews-info) p))
+
+(defcommand "Netnews Next Article" (p)
+  "Show the next article in the current newsgroup."
+  "Shows the article on the line preceeding the point in the headers buffer."
+  (declare (ignore p))
+  (let* ((what-next (netnews-next-line-command nil (nn-get-headers-buffer))))
+    (when (and (not (eq what-next :done))
+	       (or (eq what-next t)
+		   (eq (value netnews-last-header-style) :next-article)))
+      ;; Reget the headers buffer because the call to netnews-next-line-command
+      ;; might have moved us into a different buffer.
+      ;; 
+      (nn-show-article (variable-value 'netnews-info
+				       :buffer (nn-get-headers-buffer))
+		       t))))
+
+(defcommand "Netnews Previous Article" (p)
+  "Show the previous article in the current newsgroup."
+  "Shows the article on the line after the point in the headers buffer."
+  (declare (ignore p))
+  (let ((buffer (nn-get-headers-buffer)))
+    (netnews-previous-line-command nil buffer)
+    (nn-show-article (variable-value 'netnews-info :buffer buffer) t)))
+
+;;; NN-SHOW-ARTICLE checks first to see if we need to get more headers.  If
+;;; NN-MAYBE-GET-MORE-HEADERS returns nil then don't do anything because we
+;;; changed to the next group.  Then see if the message the user has
+;;; requested is already in the message buffer.  If the it isn't, put it
+;;; there.  If it is, and maybe-scroll-down is t, then scroll the window
+;;; down p lines in :multiple mode, or just change to the buffer in :single
+;;; mode.  I use scroll-window down becuase this function is called by
+;;; "Netnews Show Article", "Netnews Next Article", and "Netnews Previous
+;;; Article".  It doesn't make sense to scroll the window down if the guy
+;;; just read a message, moved the point up one line and invoked "Netnews
+;;; Next Article".  He expects to see the article again, not the second
+;;; page of it.  Also check to make sure there is a message under the
+;;; point.  If there is not, then get some more headers.  If there are no
+;;; more headers, then go on to the next group.  I can read and write.  Hi
+;;; Bill.  Are you having fun grokking my code?  Hope so -- Dude.  Nothing
+;;; like stream of consciousness is there?  Come to think of it, this is
+;;; kind of like recursive stream of conscious because I'm writing down my
+;;; stream of conscious which is about my stream of conscious. I think I'm
+;;; insane.  In fact I know I am.
+;;;
+(defun nn-show-article (nn-info dont-scroll-down &optional p)
+  (let ((headers-buffer (nn-get-headers-buffer))
+	(message-buffer (nn-info-buffer nn-info)))
+    (cond
+     ((eq (nn-maybe-get-more-headers nn-info) :go-on)
+      (case (value netnews-last-header-style)
+	(:this-headers (change-to-buffer headers-buffer)
+		       (buffer-start (buffer-point headers-buffer))
+		       (editor-error "Last header."))
+	(:next-headers (change-to-next-group nn-info headers-buffer))
+	(:next-article (change-to-next-group nn-info headers-buffer)
+		       (netnews-show-article-command nil))))
+     (t
+      (cond ((and (not dont-scroll-down)
+		  (= (nn-info-current-displayed-message nn-info)
+		     (array-element-from-mark (buffer-point headers-buffer)
+					      (nn-info-message-ids nn-info))))
+	     (ecase (value netnews-read-style)
+	       (:single (buffer-start (buffer-point message-buffer))
+			(change-to-buffer message-buffer))
+	       (:multiple
+		(multiple-value-bind
+		    (headers-window message-window newp)
+		    (nn-assure-multi-windows nn-info)
+		  (nn-put-buffers-in-windows headers-buffer message-buffer
+					     headers-window message-window
+					     :headers)
+		  ;; If both windows were visible to start with, just scroll
+		  ;; down.  If they weren't, then show the message over
+		  ;; again.
+		  ;; 
+		  (cond (newp (buffer-start (buffer-point message-buffer))
+			      (buffer-start (window-point message-window)))
+			(t (netnews-message-scroll-down-command
+			    p message-buffer message-window)))))))
+ 	    (t
+	     (nn-put-article-in-buffer nn-info headers-buffer)
+	     (setf message-buffer (nn-info-buffer nn-info))
+	     (multiple-value-bind
+		 (headers-window message-window)
+		 (ecase (value netnews-read-style) ; Only need windows in
+		   (:single (values nil nil))      ; :multiple mode.
+		   (:multiple (nn-assure-multi-windows nn-info)))
+	       (ecase (value netnews-read-style)
+		 (:multiple
+		  ;; When there is only one window displaying the headers
+		  ;; buffer, move the window point of that buffer to the
+		  ;; buffer-point.
+		  (when (= (length (buffer-windows headers-buffer)) 1)
+		    (move-mark (window-point headers-window)
+			       (buffer-point headers-buffer)))
+		  (buffer-start (window-point message-window))
+		  (nn-put-buffers-in-windows headers-buffer message-buffer
+					     headers-window message-window
+					     :headers))
+		 (:single (change-to-buffer message-buffer))))))))))
+
+(defcommand "Netnews Message Quit" (p)
+  "Destroy this message buffer, and pop back to the associated headers buffer."
+  "Destroy this message buffer, and pop back to the associated headers buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'netnews-message-info)
+    (editor-error "Not in a News-Message Buffer"))
+  (let ((message-buffer (current-buffer)))
+    (change-to-buffer (nn-get-headers-buffer))
+    (delete-buffer-if-possible message-buffer)))
+
+(defhvar "Netnews Message Header Fields"
+  "When NIL, the default, all available fields are displayed in the header
+  of a message.  Otherwise, this variable should containt a list of fields
+  that should be included in the message header when a message is
+  displayed.  Any string name is acceptable.  Fields that do not exist are
+  ignored.  If an element of this list is an atom, then it should be the
+  string name of a field.  If it is a cons, then the car should be the
+  string name of a field, and the cdr should be the length to which this
+  field should be limited."
+  :value nil)
+
+
+(defcommand "Netnews Show Whole Header" (p)
+  "This command will display the entire header of the message currently
+   being read."
+  "This command will display the entire header of the message currently
+   being read."
+  (declare (ignore p))
+  (let* ((headers-buffer (nn-get-headers-buffer))
+	 (nn-info (variable-value 'netnews-info :buffer headers-buffer))
+	 (buffer (nn-get-message-buffer nn-info)))
+    (with-writable-buffer (buffer)
+      (delete-region (buffer-region buffer))
+      (nn-put-article-in-buffer nn-info headers-buffer t))))
+
+;;; NN-PUT-ARTICLE-IN-BUFFER puts the article under the point into the
+;;; associated message buffer if it is not there already.  Uses value of
+;;; "Netnews Message Header Fields" to determine what fields should appear
+;;; in the message header.  Returns the number of the article under the
+;;; point.
+;;;
+(defun nn-put-article-in-buffer (nn-info headers-buffer &optional override)
+  (let ((stream (nn-info-stream nn-info))
+	(article-number (array-element-from-mark 
+			 (buffer-point headers-buffer)
+			 (nn-info-message-ids nn-info)))
+	(message-buffer (nn-get-message-buffer nn-info)))
+    (setf (nm-info-message-number (variable-value 'netnews-message-info
+						  :buffer message-buffer))
+	  (1+ (- article-number (nn-info-first nn-info))))
+    (cond ((and (= (nn-info-current-displayed-message nn-info) article-number)
+		(not override))
+	   (buffer-start (buffer-point message-buffer)))
+	  (t
+	   ;; Request article as soon as possible to avoid waiting for reply.
+	   ;;
+	   (nntp-body article-number stream)
+	   (setf (nn-info-current-displayed-message nn-info) article-number)
+	   (process-status-response stream nn-info)
+	   (with-writable-buffer (message-buffer)
+	     (let ((point (buffer-point message-buffer))
+		   (info (svref (nn-info-header-cache nn-info)
+				(- article-number (nn-info-first nn-info))))
+		   (message-fields (value netnews-message-header-fields))
+		   key field-length)
+	       (cond ((and message-fields
+			   (not override))
+		      (dolist (ele message-fields)
+			(etypecase ele
+			  (atom (setf key ele field-length nil))
+			  (cons (setf key (car ele) field-length (cdr ele))))
+			(let ((field-string (cdr (assoc key info
+							:test #'string-equal))))
+			  (when field-string
+			    (insert-string point (string-capitalize key))
+			    (insert-string point ": ")
+			    (insert-string point field-string
+					   0
+					   (max
+					    (if field-length
+						(min field-length
+						     (1- (length field-string)))
+						(1- (length field-string)))
+					    0))
+			    (insert-character point #\newline)))))
+		     (t
+		      (dolist (ele info)
+			(insert-string point (string-capitalize (car ele)))
+			(insert-string point ": ")
+			(insert-string point (cdr ele)
+				       0 (max 0 (1- (length (cdr ele)))))
+			(insert-character point #\newline))))
+	       (insert-character point #\newline)
+	       (nntp-insert-textual-response point (nn-info-stream nn-info))))
+	   (buffer-start (buffer-point message-buffer))
+	   (when (> article-number (nn-info-latest nn-info))
+	     (setf (nn-info-latest nn-info) article-number))))
+    article-number))
+
+;;; NN-PUT-BUFFERS-IN-WINDOWS makes sure the message buffer goes in the message
+;;; window and the headers buffer in the headers window.  If which-current
+;;; is :headers, the headers buffer/window will be made current, if it is
+;;; :message, the message buffer/window will be made current.
+;;;
+(defun nn-put-buffers-in-windows (headers-buffer message-buffer headers-window
+				  message-window which-current)
+  (setf (window-buffer message-window) message-buffer
+	(window-buffer headers-window) headers-buffer)
+  (setf (current-window) (ecase which-current
+			   (:headers headers-window)
+			   (:message message-window))
+	(current-buffer) (case which-current
+			   (:headers headers-buffer)
+			   (:message message-buffer))))
+
+(defhvar "Netnews Headers Proportion"
+  "Determines how much of the current window will display headers when
+   \"Netnews Read Style\" is :multiple.  Defaults to .25"
+  :value .25)
+
+(defun nn-assure-multi-windows (nn-info)
+  (let ((newp nil))
+    (unless (and (member (nn-info-message-window nn-info) *window-list*)
+		 (member (nn-info-headers-window nn-info) *window-list*))
+      (setf newp t)
+      (setf (nn-info-message-window nn-info) (current-window)
+	    (nn-info-headers-window nn-info)
+	    (make-window (buffer-start-mark (nn-get-headers-buffer))
+			 :proportion (value netnews-headers-proportion))))
+    (values (nn-info-headers-window nn-info)
+	    (nn-info-message-window nn-info)
+	    newp)))
+
+;;; NN-GET-MESSAGE-BUFFER returns the message buffer for an nn-info structure.
+;;; If there is not one, this function makes it and sets the slot in nn-info.
+;;;
+(defun nn-get-message-buffer (nn-info)
+  (let* ((message-buffer (nn-info-buffer nn-info))
+	 (nm-info (if message-buffer
+		      (variable-value 'netnews-message-info
+				      :buffer message-buffer))))
+    (cond ((and message-buffer (not (nm-info-keep-p nm-info)))
+	   (with-writable-buffer (message-buffer)
+	     (delete-region (buffer-region message-buffer)))
+	   message-buffer)
+	  (t
+	   (let ((buf (make-buffer (nn-unique-message-buffer-name
+				    (nn-info-current nn-info))
+				   :modeline-fields
+				   (append (value default-modeline-fields)
+					   (list (modeline-field
+						  :netnews-message)))
+				   :modes '("News-Message")
+				   :delete-hook
+				   (list #'nn-message-buffer-delete-hook))))
+	     (setf (nn-info-buffer nn-info) buf)
+	     (defhvar "Netnews Message Info"
+	       "Structure that keeps track of buffers in \"News-Message\"
+	        mode."
+	       :value (make-netnews-message-info
+		       :headers-buffer (current-buffer))
+	       :buffer buf)
+	     buf)))))
+
+;;; The usual.  Clean everything up.
+;;; 
+(defun nn-message-buffer-delete-hook (buffer)
+  (let* ((headers-buffer (nm-info-headers-buffer
+			  (variable-value 'netnews-message-info
+					  :buffer buffer)))
+	 (nn-info (variable-value 'netnews-info :buffer headers-buffer))
+	 (nm-info (variable-value 'netnews-message-info :buffer buffer)))
+    (setf (nn-info-buffer nn-info) nil)
+    (setf (nn-info-current-displayed-message nn-info) -1)
+    (let ((post-buffer (nm-info-post-buffer nm-info)))
+      (when post-buffer
+	(setf (post-info-message-buffer (variable-value
+					 'post-info :buffer post-buffer))
+	      nil)))))
+
+
+;;; NN-UNIQUE-MESSAGE-BUFFER-NAME likes to have a simple name, i.e.
+;;; "Netnews Message for rec.music.synth".  When there is already a buffer
+;;; by this name, however, we start counting until the name is unique.
+;;; 
+(defun nn-unique-message-buffer-name (group)
+  (let ((name (concatenate 'simple-string "Netnews Message for " group))
+	(number 0))
+    (loop
+      (unless (getstring name *buffer-names*) (return name))
+      (setf name (format nil "Netnews Message ~D" number))
+      (incf number))))
+
+;;; INSERT-TEXTUAL-RESPONSE inserts a textual response from nntp at mark.
+;;;
+(defun nntp-insert-textual-response (mark stream)
+  (with-input-from-nntp (string stream)
+    (insert-string mark string 0 (1- (length string)))
+    (insert-character mark #\newline)))
+
+;;; NN-GET-HEADERS-BUFFER returns the headers buffer if we are in a message or
+;;; headers buffer.
+;;;
+(defun nn-get-headers-buffer ()
+  (cond ((hemlock-bound-p 'netnews-info)
+	 (current-buffer))
+	((hemlock-bound-p 'netnews-message-info)
+	 (nm-info-headers-buffer (value netnews-message-info)))
+	((hemlock-bound-p 'post-info)
+	 (post-info-headers-buffer (value post-info)))
+	(t nil)))
+
+
+(defcommand "Netnews Previous Line" (p &optional
+				       (headers-buffer (current-buffer)))
+  "Moves the point to the last header before the point that is not in your
+   kill file.  If you move off the end of the buffer and there are more
+   headers, then get them.  Otherwise go on to the next group in \"Netnews
+   Groups\"."
+  "Moves the point to the last header before the point that is not in your
+   kill file.  If you move off the end of the buffer and there are more
+   headers, then get them.  Otherwise go on to the next group in \"Netnews
+   Groups\"."
+  (declare (ignore p))
+  (let ((point (buffer-point headers-buffer))
+	(nn-info (variable-value 'netnews-info :buffer headers-buffer)))
+    (with-mark ((original-position point)
+		(start point)
+		(end point))
+      (loop
+	(unless (line-offset point -1)
+	  (cond ((and (nn-info-from-end-p nn-info)
+		      (nn-info-messages-waiting nn-info))
+		 (nn-write-headers-to-mark nn-info headers-buffer)
+		 (netnews-previous-line-command nil headers-buffer))
+		(t
+		 (cond ((= (nn-info-first-visible nn-info)
+			   (nn-info-first nn-info))
+			(move-mark point original-position)
+			(editor-error "No previous unKilled headers."))
+		       (t
+			(message "Requesting backward...")
+			(nn-request-out-of-order nn-info headers-buffer)
+			(netnews-previous-line-command nil headers-buffer))))))
+	(line-start (move-mark start point))
+	(character-offset (move-mark end start) 1)
+	(unless (string= (region-to-string (region start end)) "K")
+	  (return))))))
+
+(defhvar "Netnews Last Header Style"
+  "When you read the last message in a newsgroup, this variable determines
+   what will happen next.  Takes one of three values: :this-headers,
+   :next-headers, or :next-article.  :this-headers, the default means put me
+   in the headers buffer for this newsgroup.  :next-headers means go to the
+   next newsgroup and put me in that headers buffer.  :next-article means go
+   on to the next newsgroup and show me the first unread article."
+  :value :next-headers)
+
+(defcommand "Netnews Next Line"
+	    (p &optional (headers-buffer (current-buffer)))
+  "Moves the point to the next header that is not in your kill file.  If you
+   move off the end of the buffer and there are more headers, then get them.
+   Otherwise go on to the next group in \"Netnews Groups\"."
+  "Moves the point to the next header that is not in your kill file.  If you
+   move off the end of the buffer and there are more headers, then get them.
+   Otherwise go on to the next group in \"Netnews Groups\".
+   Returns nil if we have gone on to the next group, :done if there are no
+   more groups to read, or T if everything is normal."
+  (declare (ignore p))
+  (let* ((nn-info (variable-value 'netnews-info :buffer headers-buffer))
+	 (point (buffer-point headers-buffer)))
+    (with-mark ((start point)
+		(end point))
+      (loop
+	(line-offset point 1)
+	(cond ((eq (nn-maybe-get-more-headers nn-info) :go-on)
+	       (cond ((eq (value netnews-last-header-style) :this-headers)
+		      (let ((headers-buffer (nn-get-headers-buffer)))
+			(change-to-buffer headers-buffer))
+		      (editor-error "Last header."))
+		     (t
+		      (return (change-to-next-group nn-info headers-buffer)))))
+	      (t
+	       (line-start (move-mark start point))
+	       (character-offset (move-mark end start) 1)
+	       (unless (string= (region-to-string (region start end)) "K")
+		 (return t))))))))
+
+(defcommand "Netnews Headers Scroll Window Up" (p)
+  "Does what \"Scroll Window Up\" does, but fetches backward when the point
+   reaches the start of the headers buffer."
+  "Does what \"Scroll Window Up\" does, but fetches backward when the point
+   reaches the start of the headers buffer."
+  (scroll-window-up-command p)
+  (let ((headers-buffer (current-buffer))
+	(nn-info (value netnews-info)))
+    (when (and (displayed-p (buffer-start-mark headers-buffer)
+			    (current-window))
+	       (not (= (nn-info-first nn-info)
+		       (nn-info-first-visible nn-info))))
+      (buffer-start (current-point))
+      (netnews-previous-line-command nil))))
+	    
+(defcommand "Netnews Headers Scroll Window Down" (p)
+  "Does what \"Scroll Window Down\" does, but when the point reaches the end of
+   the headers buffer, pending headers are inserted."
+  "Does what \"Scroll Window Down\" does, but when the point reaches the end of
+   the headers buffer, pending headers are inserted."
+  (scroll-window-down-command p)
+  (let ((headers-buffer (current-buffer))
+	(nn-info (value netnews-info)))
+    (when (and (displayed-p (buffer-end-mark headers-buffer) (current-window))
+	       (not (= (nn-info-last nn-info) (nn-info-last-visible nn-info))))
+      (buffer-end (current-point))
+      (netnews-next-line-command nil))))
+
+(defcommand "Netnews Message Keep Buffer" (p)
+  "Specifies that you don't want Hemlock to reuse the current message buffer."
+  "Specifies that you don't want Hemlock to reuse the current message buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'netnews-message-info)
+    (editor-error "Not in a News-Message buffer."))
+  (setf (nm-info-keep-p (value netnews-message-info)) t))
+
+(defcommand "Netnews Goto Headers Buffer" (p)
+  "From \"Message Mode\", switch to the associated headers buffer."
+  "From \"Message Mode\", switch to the associated headers buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'netnews-message-info)
+    (editor-error "Not in a message buffer."))
+  (let ((headers-buffer (nm-info-headers-buffer (value netnews-message-info))))
+    (unless headers-buffer (editor-error "Headers buffer has been deleted"))
+    (change-to-buffer headers-buffer)))
+
+(defcommand "Netnews Goto Post Buffer" (p)
+  "Change to the associated \"Post\" buffer (if there is one) from a
+   \"News-Message\" buffer."
+  "Change to the associated \"Post\" buffer (if there is one) from a
+   \"News-Message\" buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'netnews-message-info)
+    (editor-error "Not in a News-Message buffer."))
+  (let ((post-buffer (nm-info-post-buffer (value netnews-message-info))))
+    (unless post-buffer (editor-error "No associated post buffer."))
+    (change-to-buffer post-buffer)))
+
+(defcommand "Netnews Goto Draft Buffer" (p)
+  "Change to the associated \"Draft\" buffer (if there is one) from a
+   \"News-Message\" buffer."
+  "Change to the associated \"Draft\" buffer (if there is one) from a
+   \"News-Message\" buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'netnews-message-info)
+    (editor-error "Not in a News-Message buffer."))
+  (let ((draft-buffer (nm-info-draft-buffer (value netnews-message-info))))
+    (unless draft-buffer (editor-error "No associated post buffer."))
+    (change-to-buffer draft-buffer)))
+  
+(defcommand "Netnews Select Message Buffer" (p)
+  "Change to the associated message buffer (if there is one) in \"Post\" or
+   \"News-Headers\" modes."
+  "Change to the associated message buffer (if there is one) in \"Post\" or
+   \"News-Headers\" modes."
+  (declare (ignore p))
+  (let* ((cbuf (current-buffer))
+	 (mbuf (cond ((hemlock-bound-p 'post-info :buffer cbuf)
+		      (post-info-message-buffer (value post-info)))
+		     ((hemlock-bound-p 'netnews-info :buffer cbuf)
+		      (nn-info-buffer (value netnews-info)))
+		     (t
+		      (editor-error "Not in a \"Post\" or \"News-Headers\" ~
+		                     buffer.")))))
+    (unless mbuf (editor-error "No assocated message buffer."))
+    (change-to-buffer mbuf)))
+    
+;;; CHANGE-TO-NEXT-GROUP deletes nn-info's headers buffer region and sets
+;;; up the next group in that buffer.  If there are no more groups to read,
+;;; exits gracefully.
+;;;
+(defun change-to-next-group (nn-info headers-buffer)
+  (when (nn-info-updatep nn-info)
+    (nn-update-database-file (nn-info-latest nn-info)
+			     (nn-info-current nn-info)))
+  (let ((next-group (cadr (member (nn-info-current nn-info)
+				  (nn-info-groups nn-info) :test #'string=))))
+    (cond (next-group
+	   (message "Going on to ~A" next-group)
+	   (force-output *echo-area-stream*)
+	   (let ((message-buffer (nn-info-buffer nn-info)))
+	     (when message-buffer
+	       (setf (buffer-name message-buffer)
+		     (nn-unique-message-buffer-name next-group))))
+	   (setf (buffer-name headers-buffer)
+		 (nn-unique-headers-name next-group))
+	   (setf (nn-info-current nn-info) next-group)
+	   (with-writable-buffer (headers-buffer)
+	     (delete-region (buffer-region headers-buffer)))
+	   (setup-group next-group nn-info headers-buffer)
+	   nil)
+	  (t
+	   (if (eq headers-buffer *nn-headers-buffer*)
+	       (message "This was your last group.  Exiting Netnews.")
+	       (message "Done with ~A.  Exiting Netnews."
+			(nn-info-current nn-info)))
+	   (netnews-exit-command nil t headers-buffer)
+	   :done))))
+
+(defun nn-update-database-file (latest group-name)
+  (when latest (setf (nn-last-read-message-number group-name) latest)))
+
+
+
+
+;;;; More commands.
+
+(defhvar "Netnews Scroll Show Next Message"
+  "When non-nil, the default, Hemlock will show the next message in a group
+   when you scroll off the end of one.  Otherwise Hemlock will editor error
+   that you are at the end of the buffer."
+  :value T)
+
+(defcommand "Netnews Message Scroll Down" (p &optional (buffer (current-buffer))
+					     (window (current-window)))
+  "Scrolls the current window down one screenful, checking to see if we need
+   to get the next message."
+  "Scrolls the current window down one screenful, checking to see if we need
+   to get the next message."
+  (if (displayed-p (buffer-end-mark buffer) window)
+      (if (value netnews-scroll-show-next-message)
+	  (netnews-next-article-command nil)
+	  (editor-error "At end of buffer."))
+      (scroll-window-down-command p window)))
+
+(defcommand "Netnews Go to Next Group" (p)
+  "Goes on to the next group in \"Netnews Group File\", setting the group
+   pointer for this group to the the latest message read.  With an argument
+   does not modify the group pointer."
+  "Goes on to the next group in \"Netnews Group File\", setting the group
+   pointer for this group to the the latest message read.  With an argument
+   does not modify the group pointer."
+  (nn-punt-headers (if p :none :latest)))
+
+(defcommand "Netnews Group Punt Messages" (p)
+  "Go on to the next group in \"Netnews Group File\" setting the netnews
+   pointer for this group to the last message.  With an argument, set the
+   pointer to the last visible message in this group."
+  "Go on to the next group in \"Netnews Group File\" setting the netnews
+   pointer for this group to the last message.  With an argument, set the
+   pointer to the last visible message in this group."
+  (nn-punt-headers (if p :last-visible :punt)))
+
+(defcommand "Netnews Quit Starting Here" (p)
+  "Go on to the next group in \"Netnews Group File\", setting the group
+   pointer for this group to the message before the currently displayed one
+   or the message under the point if none is currently displayed."
+  "Go on to the next group in \"Netnews Group File\", setting the group
+   pointer for this group to the message before the currently displayed one
+   or the message under the point if none is currently displayed."
+  (declare (ignore p))
+  (nn-punt-headers :this-one))
+
+(defun nn-punt-headers (pointer-type)
+  (let* ((headers-buffer (nn-get-headers-buffer))
+	 (nn-info (variable-value 'netnews-info :buffer headers-buffer))
+	 (stream (nn-info-header-stream nn-info)))
+    (message "Exiting ~A" (nn-info-current nn-info))
+    (setf (nn-info-latest nn-info)
+	  (ecase pointer-type
+	    (:latest (nn-info-latest nn-info))
+	    (:punt (nn-info-last nn-info))
+	    (:last-visible (nn-info-last-visible nn-info))
+	    (:this-one
+	     (1- (if (minusp (nn-info-current-displayed-message nn-info))
+		     (array-element-from-mark (buffer-point headers-buffer)
+					      (nn-info-message-ids nn-info))
+		     (nn-info-current-displayed-message nn-info))))
+	    (:none nil)))
+    ;; This clears out all headers that waiting on header-stream.
+    ;; Must process each response in case a message is not really there.
+    ;; If it isn't, then the call to WITH-INPUT-FROM-NNTP will gobble up
+    ;; the error message and the next real article.
+    ;; 
+    (when (nn-info-messages-waiting nn-info)
+      (dotimes (i (nn-info-batch-count nn-info))
+	(let ((response (process-status-response stream)))
+	  (when response (with-input-from-nntp (string stream))))))
+    (change-to-next-group nn-info headers-buffer)))
+  
+(defcommand "Fetch All Headers" (p)
+  "Fetches the rest of the headers in the current group.
+   Warning: This will take a while if there are a lot."
+  "Fetches the rest of the headers in the current group.
+   Warning: This will take a while if there are a lot."
+  (declare (ignore p))
+  (let* ((headers-buffer (nn-get-headers-buffer))
+         (nn-info (variable-value 'netnews-info :buffer headers-buffer)))
+    (if (nn-info-messages-waiting nn-info)
+        (message "Fetching the rest of the headers for ~A"
+                 (nn-info-current nn-info))
+        (editor-error "All headers are in buffer."))
+    ;; The first of these calls writes the headers that are waiting on the
+    ;; headers stream and requests the rest.  The second inserts the rest, if
+    ;; there are any.
+    ;;
+    (nn-write-headers-to-mark nn-info headers-buffer t)
+    (nn-write-headers-to-mark nn-info headers-buffer)))
+
+
+(defcommand "List All Groups" (p &optional buffer)
+  "Shows all available newsgroups in a buffer."
+  "Shows all available newsgroups in a buffer."
+  (declare (ignore p))
+  (let* ((headers-buffer (nn-get-headers-buffer))
+	 (nn-info (if headers-buffer
+		      (variable-value 'netnews-info :buffer headers-buffer)))
+	 (stream (if headers-buffer
+		     (nn-info-stream nn-info)
+		     (connect-to-nntp))))
+    (nntp-list stream)
+    (message "Fetching group list...")
+    (process-status-response stream)
+    (let* ((buffer (or buffer (make-buffer (nn-new-list-newsgroups-name))))
+	   (point (buffer-point buffer))
+	   (groups (make-array 1500 :fill-pointer 0 :adjustable t)))
+      (with-input-from-nntp (string (if headers-buffer
+					(nn-info-stream nn-info)
+					stream))
+	(vector-push-extend string groups))
+      (sort groups #'string<)
+      (dotimes (i (length groups))
+	(let ((group (aref groups i)))
+	  (multiple-value-bind (last first) (list-response-args group)
+	    (declare (ignore first))
+	    (insert-string point group 0 (position #\space group))
+	    (insert-string point (format nil ": ~D~%" last)))))
+      (setf (buffer-modified buffer) nil)
+      (buffer-start point)
+      (change-to-buffer buffer))
+    (unless headers-buffer (close stream))))
+
+(defun nn-new-list-newsgroups-name ()
+  (let ((name "Newsgroups List")
+	(number 0))
+    (declare (simple-string name)
+	     (fixnum number))
+    (loop
+      (unless (getstring name *buffer-names*) (return name))
+      (setf name (format nil "Newsgroups List ~D" number))
+      (incf number))))
+
+(defhvar "Netnews Message File"
+  "This value is merged with your home directory to get the pathname of the
+   file to which Hemlock will append messages."
+  :value "hemlock.messages")
+
+(defhvar "Netnews Exit Confirm"
+  "When non-nil, the default, \"Netnews Exit\" will ask you if you really
+   want to.  If this variable is NIL, you will not be prompted."
+  :value T)
+
+(defcommand "Netnews Exit" (p &optional no-prompt-p
+			      (headers-buf (nn-get-headers-buffer)))
+  "Exit Netnews from a netnews headers or netnews message buffer."
+  "Exit Netnews from a netnews headers or netnews message buffer."
+  (declare (ignore p))
+  (let ((browse-buffer (variable-value 'netnews-browse-buffer
+				       :buffer headers-buf)))
+    (when (or browse-buffer
+	      no-prompt-p
+	      (not (value netnews-exit-confirm))
+	      (prompt-for-y-or-n :prompt "Exit Netnews? "
+				 :default "Y"
+				 :default-string "Y"
+				 :help "Yes exits netnews mode."))
+      (let* ((nn-info (variable-value 'netnews-info :buffer headers-buf))
+	     (message-buffer (nn-info-buffer nn-info))
+	     (headers-window (nn-info-headers-window nn-info))
+	     (message-window (nn-info-message-window nn-info)))
+	(when (nn-info-updatep nn-info)
+	  (nn-update-database-file (nn-info-latest nn-info)
+				   (nn-info-current nn-info)))
+	(when (and (eq (value netnews-read-style) :multiple)
+		   (member headers-window *window-list*)
+		   (member message-window *window-list*))
+	  (delete-window message-window))
+	(when message-buffer (delete-buffer-if-possible message-buffer))
+	(delete-buffer-if-possible headers-buf)
+	(when browse-buffer (change-to-buffer browse-buffer))))))
+
+
+
+
+;;;; Commands to append messages to a file or file messages into mail folders.
+
+(defcommand "Netnews Append to File" (p)
+  "In a \"News-Headers\" buffer, appends the message under the point onto
+   the file named by \"Netnews Message File\".  In a \"News-Message\" buffer,
+   appends the message in the current buffer to the same file."
+  "In a \"News-Headers\" buffer, appends the message under the point onto
+   the file named by \"Netnews Message File\".  In a \"News-Message\" buffer,
+   appends the message in the current buffer to the same file."
+  (let* ((filename (merge-pathnames (value netnews-message-file)
+				    (user-homedir-pathname)))
+	 (file (prompt-for-file :prompt "Append to what file: "
+				:must-exist nil
+				:default filename
+				:default-string (namestring filename))))
+    (when (and p (probe-file file))
+      (delete-file file))
+    (message "Appending message to ~S" (namestring file))
+    (cond ((hemlock-bound-p 'netnews-info)
+	   (let* ((nn-info (value netnews-info))
+		  (stream (nn-info-stream nn-info))
+		  (article-number (array-element-from-mark
+				   (current-point)
+				   (nn-info-message-ids nn-info)
+				   "No header under point.")))
+	     (with-open-file (file file :direction :output
+				   :if-exists :append
+				   :if-does-not-exist :create)
+	       (nntp-article article-number stream)
+	       (process-status-response stream)
+	       (with-input-from-nntp (string (nn-info-stream nn-info))
+		 (write-line string file :end (1- (length string)))))))
+	  (t
+	   (write-file (buffer-region (current-buffer)) file)))
+    ;; Put a page separator and some whitespace between messages for
+    ;; readability when printing or scanning.
+    ;; 
+    (with-open-file (f file :direction :output :if-exists :append)
+      (terpri f)
+      (terpri f)
+      (write-line "
+" f)
+      (terpri f))))
+
+(defcommand "Netnews Headers File Message" (p)
+  "Files the message under the point into a folder of your choice.  If the
+   folder you select does not exist, it is created."
+  "Files the message under the point into a folder of your choice.  If the
+   folder you select does not exist, it is created."
+  (declare (ignore p))
+  (nn-file-message (value netnews-info) :headers))
+
+(defcommand "Netnews Message File Message" (p)
+  "Files the message in the current buffer into a folder of your choice.  If
+   folder you select does not exist, it is created."
+  "Files the message in the current buffer into a folder of your choice.  If
+   folder you select does not exist, it is created."
+  (declare (ignore p))
+  (nn-file-message (variable-value 'netnews-info
+				   :buffer (nn-get-headers-buffer))
+		   :message))
+
+(defun nn-file-message (nn-info kind)
+  (let ((article-number (array-element-from-mark (current-point)
+						 (nn-info-message-ids nn-info)
+						 "No header under point."))
+	(folder (prompt-for-folder :prompt "MH Folder: "
+				   :must-exist nil)))
+    (unless (folder-existsp folder)
+      (if (prompt-for-y-or-n
+	   :prompt "Destination folder doesn't exist.  Create it? "
+	   :default t :default-string "Y")
+	  (create-folder folder)
+	  (editor-error "Not filing message.")))
+    (message "Filing message into ~A" folder)
+    (ecase kind
+      (:headers (nntp-article article-number (nn-info-stream nn-info))
+		(process-status-response (nn-info-stream nn-info))
+		(with-open-file (s "/tmp/temp.msg" :direction :output
+				   :if-exists :rename-and-delete
+				   :if-does-not-exist :create)
+		  (with-input-from-nntp (string (nn-info-stream nn-info))
+		    (write-line string s :end (1- (length string))))))
+      (:message (write-file (buffer-region (current-buffer)) "/tmp/temp.msg"
+			    :keep-backup nil)))
+    (mh "inc" `(,folder "-silent" "-file" "/tmp/temp.msg"))
+    (message "Done.")))
+
+
+
+
+;;;; "Post" Mode and supporting commands.
+
+(defmode "Post" :major-p nil)
+
+(defun nn-unique-post-buffer-name ()
+  (let ((name "Post")
+	(number 0))
+    (loop
+      (unless (getstring name *buffer-names*) (return name))
+      (setf name (format nil "Post ~D" number))
+      (incf number))))
+
+;;; We usually know what the subject and newsgroups are, so keep these patterns
+;;; around to make finding where to insert the information easy.
+;;; 
+(defvar *draft-subject-pattern*
+  (new-search-pattern :string-insensitive :forward "Subject:"))
+
+(defvar *draft-newsgroups-pattern*
+  (new-search-pattern :string-insensitive :forward "Newsgroups:"))
+
+(defcommand "Netnews Post Message" (p)
+  "Set up a buffer for posting to netnews."
+  "Set up a buffer for posting to netnews."
+  (declare (ignore p))
+  (let ((headers-buf (nn-get-headers-buffer))
+	(post-buf (nn-make-post-buffer)))
+    ;; If we're in a "News-Headers" or "News-Message" buffer, fill in the
+    ;; newsgroups: slot in the header.
+    (when headers-buf
+      (insert-string-after-pattern (buffer-point post-buf)
+				   *draft-newsgroups-pattern*
+				   (nn-info-current
+				    (variable-value
+				     'netnews-info :buffer headers-buf))))
+    (nn-post-message nil post-buf)))
+
+(defcommand "Netnews Abort Post" (p)
+  "Abort the current post."
+  "Abort the current post."
+  (declare (ignore p))
+  (delete-buffer-if-possible (current-buffer)))
+
+(defun foobie-frob (post-info buffer)
+  (declare (ignore post-info))
+  (change-to-buffer buffer))
+#|
+ #'(lambda (post-info buffer)
+     (declare (ignore post-info))
+     (print :changing) (force-output)
+     (change-to-buffer buffer)
+     (print :changed) (force-output))
+|#
+(defvar *netnews-post-frob-windows-hook* #'foobie-frob
+  "This hook is FUNCALled in NN-POST-MESSAGE with a post-info structure and
+   the corresponding \"POST\" buffer before a post is done.")
+
+;;; NN-POST-MESSAGE sets up a buffer for posting.  If message buffer is
+;;; supplied, it is associated with the post-info structure for the post
+;;; buffer.
+;;; 
+(defun nn-post-message (message-buffer &optional (buffer (nn-make-post-buffer)))
+  (setf (buffer-modified buffer) nil)
+  (when message-buffer
+    (setf (nm-info-post-buffer (variable-value 'netnews-message-info
+					       :buffer message-buffer))
+	  buffer))
+  (let ((post-info (make-post-info :stream (connect-to-nntp)
+				   :headers-buffer (nn-get-headers-buffer)
+				   :message-buffer message-buffer)))
+    (defhvar "Post Info"
+      "Information needed to manipulate post buffers."
+      :buffer buffer
+      :value post-info)
+    (funcall *netnews-post-frob-windows-hook* post-info buffer)))
+
+(defun nn-make-post-buffer ()
+  (let* ((buffer (make-buffer (nn-unique-post-buffer-name)
+			      :delete-hook (list #'nn-post-buffer-delete-hook)))
+	 (stream (make-hemlock-output-stream (buffer-point buffer))))
+    (setf (buffer-minor-mode buffer "Post") t)
+    (write-line "Newsgroups: " stream)
+    (write-line "Subject: " stream)
+;   (write-string "Date: " stream)
+;   (format stream "~A~%" (string-capitalize
+;			   (format-universal-time nil (get-universal-time)
+;						  :style :government
+;						  :print-weekday nil)))
+    (write-char #\newline stream)
+    (write-char #\newline stream)
+    buffer))
+
+;;; The usual again.  NULLify the appropriate stream slots in associated
+;;; structures.  Also call NN-REPLY-CLEANUP-SPLIT-WINDOWS to see if we
+;;; need to delete one of the current windows.
+;;; 
+(defun nn-post-buffer-delete-hook (buffer)
+  (when (hemlock-bound-p 'post-info)
+    (nn-reply-cleanup-split-windows buffer)
+    (let* ((post-info (variable-value 'post-info :buffer buffer))
+	   (message-buffer (post-info-message-buffer post-info)))
+      (close (post-info-stream post-info))
+      (when message-buffer
+	(setf (nm-info-post-buffer (variable-value 'netnews-message-info
+						   :buffer message-buffer))
+	      nil)))))
+
+;;; NN-REPLY-USING-CURRENT-WINDOW makes sure there is only one window for a
+;;; normal reply.  *netnews-post-frob-windows-hook* is bound to this when
+;;; "Netnews Reply to Group" is invoked."
+;;;
+(defun nn-reply-using-current-window (post-info buffer)
+  (declare (ignore post-info))
+  ;; Make sure there is only one window in :multiple mode.
+  ;;
+  (let* ((nn-info (variable-value 'netnews-info
+				  :buffer (nn-get-headers-buffer)))
+	 (headers-window (nn-info-headers-window nn-info))
+	 (message-window (nn-info-message-window nn-info)))
+    (when (and (eq (value netnews-read-style) :multiple)
+	       (member message-window *window-list*)
+	       (member headers-window *window-list*))
+      (setf (current-window) message-window)
+      (delete-window headers-window))
+    (change-to-buffer buffer)))
+
+;;; NN-REPLY-IN-OTHER-WINDOW-HOOK does what NN-REPLY-USING-CURRENT-WINDOW
+;;; does, but in addition splits the current window in half, displaying the
+;;; message buffer on top, and the reply buffer on the bottom.  Also set some
+;;; slots in the post info structure so the cleanup function knowd to delete
+;;; one of the two windows we've created.
+;;;
+(defun nn-reply-in-other-window-hook (post-info buffer)
+  (nn-reply-using-current-window post-info buffer)
+  (let* ((message-window (current-window))
+	 (reply-window (make-window (buffer-start-mark buffer))))
+    (setf (window-buffer message-window) (post-info-message-buffer post-info)
+	  (current-window) reply-window
+	  (post-info-message-window post-info) message-window
+	  (post-info-reply-window post-info) reply-window)))
+
+;;; NN-REPLY-CLEANUP-SPLIT-WINDOWS just deletes one of the windows that
+;;; "Netnews Reply to Group in Other Window" created, if they still exist.
+;;; 
+(defun nn-reply-cleanup-split-windows (post-buffer)
+  (let* ((post-info (variable-value 'post-info :buffer post-buffer))
+	 (message-window (post-info-message-window post-info)))
+    (when (and (member (post-info-reply-window post-info) *window-list*)
+	       (member message-window *window-list*))
+      (delete-window message-window))))
+
+(defcommand "Netnews Reply to Group" (p)
+  "Set up a POST buffer and insert the proper newgroups: and subject: fields.
+   Should be invoked from a \"News-Message\" or \"News-Headers\" buffer.
+   In a message buffer, reply to the message in that buffer, in a headers
+   buffer, reply to the message under the point."
+  "Set up a POST buffer and insert the proper newgroups: and subject: fields.
+   Should be invoked from a \"News-Message\" or \"News-Headers\" buffer.
+   In a message buffer, reply to the message in that buffer, in a headers
+   buffer, reply to the message under the point."
+  (declare (ignore p))
+  (let ((*netnews-post-frob-windows-hook* #'nn-reply-using-current-window))
+    (nn-reply-to-message)))
+
+(defcommand "Netnews Reply to Group in Other Window" (p)
+  "Does exactly what \"Netnews Reply to Group\" does, but makes two windows.
+   One of the windows displays the message being replied to, and the other
+   displays the reply."
+  "Does exactly what \"Netnews Reply to Group\" does, but makes two windows.
+   One of the windows displays the message being replied to, and the other
+   displays the reply."
+  (declare (ignore p))
+  (let ((*netnews-post-frob-windows-hook* #'nn-reply-in-other-window-hook))
+    (nn-reply-to-message)))
+
+
+(defun nn-setup-for-reply-by-mail ()
+  (let* ((headers-buffer (nn-get-headers-buffer))
+	 (nn-info (variable-value 'netnews-info :buffer headers-buffer))
+	 (message-buffer (nn-info-buffer nn-info))
+	 (nm-info (variable-value 'netnews-message-info :buffer message-buffer))
+	 (draft-buffer (sub-setup-message-draft "comp" :to-field))
+	 (dinfo (variable-value 'draft-information :buffer draft-buffer)))
+    (setf (buffer-delete-hook draft-buffer)
+	  (list #'cleanup-netnews-draft-buffer))
+    (when (nm-info-draft-buffer nm-info)
+      (delete-variable 'message-buffer :buffer (nm-info-draft-buffer nm-info)))
+    (setf (nm-info-draft-buffer nm-info) draft-buffer)
+    (when headers-buffer
+      (defhvar "Headers Buffer"
+	"This is bound in message and draft buffers to their associated
+	 headers-buffer"
+	:value headers-buffer :buffer draft-buffer))
+    (setf (draft-info-headers-mark dinfo)
+	  (copy-mark (buffer-point headers-buffer)))
+    (defhvar "Message Buffer"
+      "This is bound in draft buffers to their associated message buffer."
+      :value message-buffer :buffer draft-buffer)
+    (values draft-buffer message-buffer)))
+
+
+(defcommand "Netnews Forward Message" (p)
+  "Creates a Draft buffer and places a copy of the current message in
+   it, delimited by forwarded message markers."
+  "Creates a Draft buffer and places a copy of the current message in
+   it, delimited by forwarded message markers."
+  (declare (ignore p))
+  (multiple-value-bind (draft-buffer message-buffer)
+		       (nn-setup-for-reply-by-mail)
+    (with-mark ((mark (buffer-point draft-buffer) :left-inserting))
+      (buffer-end mark)
+      (insert-string mark (format nil "~%------- Forwarded Message~%~%"))
+      (insert-string mark (format nil "~%------- End of Forwarded Message~%"))
+      (line-offset mark -2 0)
+      (insert-region mark (buffer-region message-buffer)))
+    (nn-reply-using-current-window nil draft-buffer)))
+
+
+(defun nn-reply-to-sender ()
+  (let* ((headers-buffer (nn-get-headers-buffer))
+	 (nn-info (variable-value 'netnews-info :buffer headers-buffer))
+	 (article (if (and (hemlock-bound-p 'netnews-info)
+			   (minusp (nn-info-current-displayed-message
+				    nn-info)))
+		      (nn-put-article-in-buffer nn-info headers-buffer)
+		      (nn-info-current-displayed-message nn-info))))
+    (multiple-value-bind (draft-buffer message-buffer)
+			 (nn-setup-for-reply-by-mail)
+      (let ((point (buffer-point draft-buffer))
+	    (to-field (or (nn-get-one-field nn-info "Reply-To" article)
+			  (nn-get-one-field nn-info "From" article))))
+	(insert-string-after-pattern point
+				     *draft-to-pattern*
+				     to-field
+				     :end (1- (length to-field)))
+	(let ((subject-field (nn-subject-replyify
+			      (nn-get-one-field nn-info "Subject" article))))
+	  (insert-string-after-pattern point
+				       *draft-subject-pattern*
+				       subject-field
+				       :end (1- (length subject-field)))))
+      (nn-reply-using-current-window nil draft-buffer)
+      (values draft-buffer message-buffer))))
+
+(defcommand "Netnews Reply to Sender" (p)
+  "Reply to the sender of a message via mail using the Hemlock mailer."
+  "Reply to the sender of a message via mail using the Hemlock mailer."
+  (declare (ignore p))
+  (nn-reply-to-sender))
+
+(defcommand "Netnews Reply to Sender in Other Window" (p)
+  "Reply to the sender of a message via mail using the Hemlock mailer.  The
+   screen will be split in half, displaying the post and the draft being
+   composed."
+  "Reply to the sender of a message via mail using the Hemlock mailer.  The
+   screen will be split in half, displaying the post and the draft being
+   composed."
+  (declare (ignore p))
+  (multiple-value-bind (draft-buffer message-buffer)
+		       (nn-reply-to-sender)
+    (let* ((message-window (current-window))
+	   (reply-window (make-window (buffer-start-mark draft-buffer))))
+      (defhvar "Split Window Draft"
+	"Indicates window needs to be cleaned up for draft."
+	:value t :buffer draft-buffer)
+      (setf (window-buffer message-window) message-buffer
+	    (current-window) reply-window))))
+
+;;; CLEANUP-NETNEWS-DRAFT-BUFFER replaces the normal draft buffer delete hook
+;;; because the generic one tries to set some slots in the related message-info
+;;; structure which doesn't exist.  This function just sets the draft buffer
+;;; slot of netnews-message-info to nil so it won't screw you when you try
+;;; to change to the associated draft buffer.
+;;; 
+(defun cleanup-netnews-draft-buffer (buffer)
+  (when (hemlock-bound-p 'message-buffer :buffer buffer)
+    (setf (nm-info-draft-buffer
+	   (variable-value 'netnews-message-info
+			   :buffer (variable-value 'message-buffer
+						   :buffer buffer)))
+	  nil)))
+
+;;; NN-REPLYIFY-SUBJECT simply adds "Re: " to the front of a string if it is
+;;; not already there.
+;;; 
+(defun nn-subject-replyify (subject)
+  (if (>= (length subject) 3)
+      (if (not (string= subject "Re:" :end1 3 :end2 3))
+	  (concatenate 'simple-string "Re: " subject)
+	  subject)
+      (concatenate 'simple-string "Re: " subject)))
+
+(defun insert-string-after-pattern (mark search-pattern string
+				    &key (start 0) (end (length string)))
+  (buffer-start mark)
+  (when (and (plusp end)
+	     (find-pattern mark search-pattern))
+    (insert-string (line-end mark) string start end))
+  (buffer-end mark))
+
+(defun nn-reply-to-message ()
+  (let* ((headers-buffer (nn-get-headers-buffer))
+	 (nn-info (variable-value 'netnews-info :buffer headers-buffer))
+	 (article (if (and (hemlock-bound-p 'netnews-info)
+			   (minusp (nn-info-current-displayed-message nn-info)))
+		      (nn-put-article-in-buffer nn-info headers-buffer)
+		      (nn-info-current-displayed-message nn-info)))
+	 (post-buffer (nn-make-post-buffer))
+	 (point (buffer-point post-buffer)))
+
+    (let ((groups-field (nn-get-one-field nn-info "Newsgroups" article)))
+      (insert-string-after-pattern point
+				   *draft-newsgroups-pattern*
+				   groups-field
+				   :end (1- (length groups-field))))
+    (let ((subject-field (nn-subject-replyify
+			  (nn-get-one-field nn-info "Subject" article))))
+      (insert-string-after-pattern point
+				   *draft-subject-pattern*
+				   subject-field
+				   :end (1- (length subject-field))))
+    (nn-post-message (nn-info-buffer nn-info) post-buffer)))
+
+(defun nn-get-one-field (nn-info field article)
+  (cdr (assoc field (svref (nn-info-header-cache nn-info)
+			  (- article (nn-info-first nn-info)))
+	      :test #'string-equal)))
+		     
+(defvar *nntp-timeout-handler* 'nn-recover-from-timeout
+  "This function gets FUNCALled when NNTP times out on us with the note passed
+   to PROCESS-STATUS-RESPONSE.  The default assumes the note is an NN-INFO
+   structure and tries to recover from the timeout.")
+
+(defvar *nn-last-command-issued* nil
+  "The last string issued to one of the NNTP streams.  Used to recover from
+   a nntp timeout.")
+
+;;; NN-RECOVER-FROM-POSTING-TIMEOUT is the recover method used when posting.
+;;; It just resets the value of \"NNTP Stream\" and issues the last command
+;;; again.
+;;;
+(defun nn-recover-from-posting-timeout (ignore)
+  (declare (ignore ignore))
+  (let ((stream (connect-to-nntp)))
+    (setf (post-info-stream (value post-info)) stream)
+    (write-nntp-command *nn-last-command-issued* stream :recover)
+    (process-status-response stream)))
+  
+(defhvar "Netnews Reply Address"
+  "What the From: field will be when you post messages.  If this is nil,
+   the From: field will be determined using the association of :USER
+   in *environment-list* and your machine name."
+  :value NIL)
+
+(defhvar "Netnews Signature Filename"
+  "This value is merged with your home directory to get the pathname your
+   signature, which is appended to every post you make."
+  :value ".hemlock-sig")
+
+(defhvar "Netnews Deliver Post Confirm"
+  "This determines whether Netnews Deliver Post will ask for confirmation
+   before posting the current message."
+  :value t)
+
+(defcommand "Netnews Deliver Post" (p)
+  "Deliver the current Post buffer to the NNTP server.  If the file named by
+   the value of \"Netnews Signature Filename\" exists, it is appended to the
+   end of the message after adding a newline."
+  "Deliver the current Post buffer to the NNTP server, cleaning up any windows
+   we need and landing us in the headers buffer if this was a reply."
+  (declare (ignore p))
+  (when (or (not (value netnews-deliver-post-confirm))
+	    (prompt-for-y-or-n :prompt "Post message? " :default t))
+    (let* ((*nntp-timeout-handler* #'nn-recover-from-posting-timeout)
+	   (stream (post-info-stream (value post-info))))
+      (nntp-post stream)
+      (let ((winp (process-status-response stream))
+	    ;; Rebind stream here because the stream may have been pulled out
+	    ;; from under us by an NNTP timeout.  The recover method for posting
+	    ;; resets the Hemlock Variable.
+	    (stream (post-info-stream (value post-info))))
+	(unless winp (editor-error "Posting prohibited in this group."))
+	(let ((buffer (current-buffer))
+	      (username (value netnews-reply-address)))
+	  (nn-write-line (format nil "From: ~A"
+				 (if username
+				     username
+				     (string-downcase
+				      (format nil "~A@~A"
+					      (cdr (assoc :user
+							  ext:*environment-list*))
+					      (machine-instance)))))
+			 stream)
+	  (filter-region #'(lambda (string)
+			     (when (string= string ".")
+			       (write-char #\. stream))
+			     (nn-write-line string stream))
+			 (buffer-region buffer))
+	  ;; Append signature
+	  ;;
+	  (let ((filename (merge-pathnames (value netnews-signature-filename)
+					   (user-homedir-pathname))))
+	    (when (probe-file filename)
+	      (with-open-file (istream filename :direction :input)
+		(loop
+		  (let ((line (read-line istream nil nil)))
+		    (unless line (return))
+		    (nn-write-line line stream))))))
+	  (write-line nntp-eof stream)
+	  (delete-buffer-if-possible buffer)
+	  (let ((headers-buffer (nn-get-headers-buffer)))
+	    (when headers-buffer (change-to-buffer headers-buffer)))
+	  (message "Message Posted."))))))
+
+(defun nn-write-line (line stream)
+  (write-string line stream)
+  (write-char #\return stream)
+  (write-char #\newline stream)
+  line)
+
+
+
+
+;;;; News-Browse mode.
+
+(defmode "News-Browse" :major-p t)
+
+(defhvar "Netnews Group File"
+  "If the value of \"Netnews Groups\" is nil, \"Netnews\" merges this
+   variable with your home directory and looks there for a list of newsgroups
+   (one per line) to read.  Groups may be added using \"Netnews Browse\ and
+   related commands, or by editing this file."
+  :value ".hemlock-groups")
+
+(defcommand "Netnews Browse" (p)
+  "Puts all netnews groups in a buffer and provides commands for reading them
+   and adding them to the file specified by the merge of \"Netnews Group File\"
+   and your home directory."
+  "Puts all netnews groups in a buffer and provides commands for reading them
+   and adding them to the file specified by the merge of \"Netnews Group File\"
+   and your home directory."
+  (declare (ignore p))
+  (let ((buffer (make-buffer "Netnews Browse")))
+    (cond (buffer
+	   (list-all-groups-command nil buffer)
+	   (setf (buffer-major-mode buffer) "News-Browse")
+	   (setf (buffer-writable buffer) nil))
+	  (t (change-to-buffer (getstring "Netnews Browse" *buffer-names*))))))
+
+(defcommand "Netnews Quit Browse" (p)
+  "Exit News-Browse Mode."
+  "Exit News-Browse Mode."
+  (declare (ignore p))
+  (delete-buffer-if-possible (current-buffer)))
+
+(defcommand "Netnews Browse Read Group" (p &optional (mark (current-point)))
+  "Read the group on the line under the current point paying no attention to
+    the \"Hemlock Database File\" entry for this group.  With an argument, use
+    and modify the database file."
+  "Read the group on the line under the current point paying no attention to
+    the \"Hemlock Database File\" entry for this group.  With an argument, use
+    and modify the database file."
+  (let ((group-info-string (line-string (mark-line mark))))
+    (netnews-command nil (subseq group-info-string
+				 0 (position #\: group-info-string))
+		     nil (current-buffer) p)))
+
+(defcommand "Netnews Browse Pointer Read Group" (p)
+  "Read the group on the line where you just clicked paying no attention to the
+   \"Hemlock Databse File\" entry for this group.  With an argument, use and
+   modify the databse file."
+  "Read the group on the line where you just clicked paying no attention to the
+   \"Hemlock Databse File\" entry for this group.  With an argument, use and
+   modify the databse file."
+  (multiple-value-bind (x y window) (last-key-event-cursorpos)
+    (unless window (editor-error "Couldn't figure out where last click was."))
+    (unless y (editor-error "There is no group in the modeline."))
+    (netnews-browse-read-group-command p (cursorpos-to-mark x y window))))
+
+(defcommand "Netnews Browse Add Group to File" (p &optional
+						      (mark (current-point)))
+  "Append the newsgroup on the line under the point to the file specified by
+   \"Netnews Group File\".  With an argument, delete all groups that were
+   there to start with."
+  "Append the newsgroup on the line under the point to the file specified by
+   \"Netnews Group File\".  With an argument, delete all groups that were
+   there to start with."
+  (declare (ignore p))
+  (let* ((group-info-string (line-string (mark-line mark)))
+	 (group (subseq group-info-string 0 (position #\: group-info-string))))
+    (with-open-file (s (merge-pathnames (value netnews-group-file)
+					(user-homedir-pathname))
+		       :direction :output
+		       :if-exists :append
+		       :if-does-not-exist :create)
+      (write-line group s))
+    (message "Adding ~S to newsgroup file." group)))
+      
+(defcommand "Netnews Browse Pointer Add Group to File" (p)
+  "Append the newsgroup you just clicked on to the file specified by
+   \"Netnews Group File\"."
+  "Append the newsgroup you just clicked on to the file specified by
+   \"Netnews Group File\"."
+  (declare (ignore p))
+  (multiple-value-bind (x y window) (last-key-event-cursorpos)
+    (unless window (editor-error "Couldn't figure out where last click was."))
+    (unless y (editor-error "There is no group in the modeline."))
+    (netnews-browse-add-group-to-file-command
+     nil (cursorpos-to-mark x y window))))
+
+
+
+
+;;;; Low-level stream operations.
+
+(defun streams-for-nntp ()
+  (clear-echo-area)
+  (format *echo-area-stream* "Connecting to NNTP...~%")
+  (force-output *echo-area-stream*)
+  (values (connect-to-nntp) (connect-to-nntp)))
+
+
+(defparameter *nntp-port* 119
+  "The nntp port number for NNTP as specified in RFC977.")
+
+(defhvar "Netnews NNTP Server"
+  "The hostname of the NNTP server to use for reading Netnews."
+  :value "netnews.srv.cs.cmu.edu")
+
+(defhvar "Netnews NNTP Timeout Period"
+  "The number of seconds to wait before timing out when trying to connect
+   to the NNTP server."
+  :value 30)
+
+(defun raw-connect-to-nntp ()
+  (let ((stream (system:make-fd-stream
+		 (ext:connect-to-inet-socket (value netnews-nntp-server)
+					     *nntp-port*)
+		 :input t :output t :buffering :line :name "NNTP"
+		 :timeout (value netnews-nntp-timeout-period))))
+    (process-status-response stream)
+    stream))
+
+(defun connect-to-nntp ()
+  (handler-case
+      (raw-connect-to-nntp)
+    (io-timeout ()
+      (editor-error "Connection to NNTP timed out.  Try again later."))))
+
+(defvar *nn-last-command-type* nil
+  "Used to recover from a nntp timeout.")
+
+(defun write-nntp-command (command stream type)
+  (setf *nn-last-command-type* type)
+  (setf *nn-last-command-issued* command)
+  (write-string command stream)
+  (write-char #\return stream)
+  (write-char #\newline stream)
+  (force-output stream))
+
+
+
+
+;;;; PROCESS-STATUS-RESPONSE and NNTP error handling.
+
+(defconstant nntp-error-codes '(#\4 #\5)
+  "These codes signal that NNTP could not complete the request you asked for.")
+
+(defvar *nntp-error-handlers* nil)
+
+;;; PROCESS-STATUS-RESPONSE makes sure a response waiting at the server is
+;;; valid.  If the response code starts with a 4 or 5, then look it up in
+;;; *nntp-error-handlers*.  If an error handler is defined, then FUNCALL it
+;;; on note.  Otherwise editor error.  If the response is not an error code,
+;;; then just return what NNTP returned to us for parsing later.
+;;;
+(defun process-status-response (stream &optional note)
+  (let ((str (read-line stream)))
+    (if (member (schar str 0) nntp-error-codes :test #'char=)
+	(let ((error-handler (cdr (assoc str *nntp-error-handlers*
+					 :test #'(lambda (string1 string2)
+						   (string= string1 string2
+							    :end1 3
+							    :end2 3))))))
+	  (unless error-handler
+	    (error "NNTP error -- ~A" (subseq str 4 (1- (length str)))))
+	  (funcall error-handler note))
+	str)))
+
+(defun nn-recover-from-timeout (nn-info)
+  (message "NNTP timed out, attempting to reconnect and continue...")
+  (let ((stream (nn-info-stream nn-info))
+	(header-stream (nn-info-header-stream nn-info)))
+    ;; If some messages are waiting on the header stream, insert them.
+    ;;
+    (when (listen header-stream)
+      (nn-write-headers-to-mark nn-info (nn-get-headers-buffer)))
+    (close stream)
+    (close header-stream)
+    (setf stream (connect-to-nntp)
+	  header-stream (connect-to-nntp)
+	  (nn-info-stream nn-info) stream
+	  (nn-info-header-stream nn-info) header-stream)
+    (let ((last-command *nn-last-command-issued*)
+	  (last-command-type *nn-last-command-type*)
+	  (current (nn-info-current nn-info)))
+      (nntp-group current stream header-stream)
+      (process-status-response stream)
+      (process-status-response header-stream)
+      (if (consp last-command)
+	  (let ((stream-type (car last-command)))
+	    (apply #'nn-send-many-head-requests
+		   (cons (if (eq stream-type :header) header-stream stream)
+			 (cdr last-command))))
+	  (ecase last-command-type
+	    ((:list :article :body)
+	     (write-nntp-command last-command stream :recover)
+	     (process-status-response stream))
+	    ((:header-group :normal-group)
+	     (write-nntp-command last-command stream :recover)
+	     (write-nntp-command last-command header-stream :recover)))))))
+
+;;; DEF-NNTP-ERROR-HANDLER takes a code and a function and associates the two
+;;; in *nntp-error-handlers*.  If while PROCESSING a STATUS RESPONSE we come
+;;; across one of these error codes, then FUNCALL the appropriate handler.
+;;; 
+(defun def-nntp-error-handler (code function)
+  (pushnew (cons (format nil "~D" code) function) *nntp-error-handlers*))
+
+;;; 503 is an NNTP timeout.  The code I wrote reconnects and recovers
+;;; completely.
+;;; 
+(def-nntp-error-handler 503 #'(lambda (note)
+				(funcall *nntp-timeout-handler* note)))
+
+;;; 400 means NNTP is cutting us of for some reason.  There is really nothing
+;;; we can do.
+;;; 
+(def-nntp-error-handler 400 #'(lambda (ignore)
+				(declare (ignore ignore))
+				(editor-error "NNTP discontinued service.  ~
+				You should probably quit netnews and try ~
+				again later.")))
+
+;;; Some functions just need to know that something went wrong so they can
+;;; do something about it, so let them know by returning nil.
+;;;
+;;; 411  -   The group you tried to read is not a netnews group.
+;;; 423  -   You requested a message that wasn't really there.
+;;; 440  -   Posting is not allowed.
+;;; 441  -   Posting is allowed, but the attempt failed for some other reason.
+;;; 
+(flet ((nil-function (ignore)
+	 (declare (ignore ignore))
+	 nil))
+  (def-nntp-error-handler 423 #'nil-function)
+  (def-nntp-error-handler 411 #'nil-function)
+  (def-nntp-error-handler 440 #'nil-function)
+  (def-nntp-error-handler 441 #'nil-function))
+
+
+
+
+;;;; Implementation of NNTP response argument parsing.
+
+;;; DEF-NNTP-ARG-PARSER returns a form that parses a string for arguments
+;;; corresponding to each element of types.  For instance, if types is
+;;; (:integer :string :integer :integer), this function returns a form that
+;;; parses an integer, a string, and two more integers out of an nntp status
+;;; response.
+;;;
+(defmacro def-nntp-arg-parser (types)
+  (let ((form (gensym))
+	(start (gensym))
+	(res nil))
+    (do ((type types (cdr type)))
+	((endp type) form)
+      (ecase (car type)
+	(:integer
+	 (push `(parse-integer string :start ,start
+			       :end (setf ,start
+					  (position #\space string
+						    :start (1+ ,start)))
+			       :junk-allowed t)
+	       res))
+	(:string
+	 (push `(subseq string (1+ ,start)
+			(position #\space string
+				  :start (setf ,start (1+ ,start))))
+	       res))))
+    `(let ((,start (position #\space string)))
+       (values ,@(nreverse res)))))
+
+(defun def-nntp-xhdr-arg-parser (string)
+  (let ((position (position #\space string)))
+    (values (subseq string (1+ position))
+	    (parse-integer string :start 0 :end position))))
+
+(defun xhdr-response-args (string)
+  (def-nntp-xhdr-arg-parser string))
+
+;;; GROUP-RESPONSE-ARGS, ARTICLER-RESPONSE-ARGS, HEAD-RESPONSE-ARGS,
+;;; BODY-RESPONSE-ARGS, and STAT-RESPONSE-ARGS define NNTP argument parsers
+;;; for the types of arguments each command will return.
+;;; 
+(defun group-response-args (string)
+  "Group response args are an estimate of how many messages there are, the
+   number of the first message, the number of the last message, and \"y\"
+   or \"n\", indicating whether the user has rights to post in this group."
+  (def-nntp-arg-parser (:integer :integer :integer)))
+
+(defun list-response-args (string)
+  (def-nntp-arg-parser (:integer :integer)))
+
+(defun article-response-args (string)
+  "Article response args are the message number and the message ID."
+  (def-nntp-arg-parser (:integer :string)))
+
+(defun head-response-args (string)
+  "Head response args are the message number and the message ID."
+  (def-nntp-arg-parser (:integer :string)))
+
+(defun body-response-args (string)
+  "Body response args are the message number and the message ID."
+  (def-nntp-arg-parser (:integer :string)))
+
+(defun stat-response-args (string)
+  "Stat response args are the message number and the message ID."
+  (def-nntp-arg-parser (:integer :string)))
+
+
+
+
+;;;; Functions that send standard NNTP commands.
+
+;;; NNTP-XHDR sends an XHDR command to the NNTP server.  We think this is a
+;;; local extension, but not using it is not pragmatic.  It takes over three
+;;; minutes to HEAD every message in a newsgroup.
+;;; 
+(defun nntp-xhdr (field start end stream)
+  (write-nntp-command (format nil "xhdr ~A ~D-~D"
+			      field
+			      (if (numberp start) start (parse-integer start))
+			      (if (numberp end) end (parse-integer end)))
+		      stream
+		      :xhdr))
+
+(defun nntp-group (group-name stream header-stream)
+  (let ((command (concatenate 'simple-string "group " group-name)))
+    (write-nntp-command command stream :normal-group)
+    (write-nntp-command command header-stream :header-group)))
+
+(defun nntp-list (stream)
+  (write-nntp-command "list" stream :list))
+
+(defun nntp-head (article stream)
+  (write-nntp-command (format nil "head ~D" article) stream :head))
+
+(defun nntp-article (number stream)
+  (write-nntp-command (format nil "article ~D" number) stream :article))
+
+(defun nntp-body (number stream)
+  (write-nntp-command (format nil "body ~D" number) stream :body))
+
+(defun nntp-post (stream)
+  (write-nntp-command "post" stream :post))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/overwrite.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/overwrite.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/overwrite.lisp	(revision 13309)
@@ -0,0 +1,65 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles.
+;;;
+
+(in-package :hemlock)
+
+
+(defmode "Overwrite")
+
+
+(defcommand "Overwrite Mode" (p)
+  "Printing characters overwrite characters instead of pushing them to the right.
+   A positive argument turns Overwrite mode on, while zero or a negative
+   argument turns it off.  With no arguments, it is toggled.  Use C-Q to
+   insert characters normally."
+  "Determine if in Overwrite mode or not and set the mode accordingly."
+  (setf (buffer-minor-mode (current-buffer) "Overwrite")
+	(if p
+	    (plusp p)
+	    (not (buffer-minor-mode (current-buffer) "Overwrite")))))
+
+
+(defcommand "Self Overwrite" (p)
+  "Replace the next character with the last character typed,
+   but insert at end of line.  With prefix argument, do it that many times."
+  "Implements ``Self Overwrite'', calling this function is not meaningful."
+  (let ((char (hemlock-ext:key-event-char *last-key-event-typed*))
+	(point (current-point)))
+    (unless char (editor-error "Can't insert that character."))
+    (do ((n (or p 1) (1- n)))
+	((zerop n))
+      (case (next-character point)
+	(#\tab
+	 (let ((col1 (mark-column point))
+	       (col2 (mark-column (mark-after point))))
+	   (if (= (- col2 col1) 1)
+	       (setf (previous-character point) char)
+	       (insert-character (mark-before point) char))))
+	((#\newline nil) (insert-character point char))
+	(t (setf (next-character point) char)
+	   (mark-after point))))))
+
+
+(defcommand "Overwrite Delete Previous Character" (p)
+  "Replaces previous character with space, but tabs and newlines are deleted.
+   With prefix argument, do it that many times."
+  "Replaces previous character with space, but tabs and newlines are deleted."
+  (do ((point (current-point))
+       (n (or p 1) (1- n)))
+      ((zerop n))
+    (case (previous-character point)
+      ((#\newline #\tab) (delete-characters point -1))
+      ((nil) (editor-error))
+      (t (setf (previous-character point) #\space)
+	 (mark-before point)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/pascal.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/pascal.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/pascal.lisp	(revision 13309)
@@ -0,0 +1,46 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Just barely enough to be a Pascal/C mode.  Maybe more some day.
+;;; 
+(in-package :hemlock)
+
+(defmode "Pascal" :major-p t)
+(defcommand "Pascal Mode" (p)
+  "Put the current buffer into \"Pascal\" mode."
+  "Put the current buffer into \"Pascal\" mode."
+  (declare (ignore p))
+  (setf (buffer-major-mode (current-buffer)) "Pascal"))
+
+(defhvar "Indent Function"
+  "Indentation function which is invoked by \"Indent\" command.
+   It must take one argument that is the prefix argument."
+  :value #'generic-indent
+  :mode "Pascal")
+
+(defhvar "Auto Fill Space Indent"
+  "When non-nil, uses \"Indent New Comment Line\" to break lines instead of
+   \"New Line\"."
+  :mode "Pascal" :value t)
+
+(defhvar "Comment Start"
+  "String that indicates the start of a comment."
+  :mode "Pascal" :value "(*")
+
+(defhvar "Comment End"
+  "String that ends comments.  Nil indicates #\newline termination."
+  :mode "Pascal" :value " *)")
+
+(defhvar "Comment Begin"
+  "String that is inserted to begin a comment."
+  :mode "Pascal" :value "(* ")
+
+(shadow-attribute :scribe-syntax #\< nil "Pascal")
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/rcs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/rcs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/rcs.lisp	(revision 13309)
@@ -0,0 +1,526 @@
+;;; -*- Package: HEMLOCK; Mode: Lisp -*-
+;;;
+;;; $Header$
+;;;
+;;; Various commands for dealing with RCS under Hemlock.
+;;;
+;;; Written by William Lott and Christopher Hoover.
+;;; 
+(in-package :hemlock)
+
+
+
+;;;;
+
+(defun current-buffer-pathname ()
+  (let ((pathname (buffer-pathname (current-buffer))))
+    (unless pathname
+      (editor-error "The buffer has no pathname."))
+    pathname))
+
+
+(defmacro in-directory (directory &body forms)
+  (let ((cwd (gensym)))
+    `(let ((,cwd (ext:default-directory)))
+       (unwind-protect
+	   (progn
+	     (setf (ext:default-directory) (directory-namestring ,directory))
+	     ,@forms)
+	 (setf (ext:default-directory) ,cwd)))))
+
+
+(defvar *last-rcs-command-name* nil)
+(defvar *last-rcs-command-output-string* nil)
+(defvar *rcs-output-stream* (make-string-output-stream))
+
+(defmacro do-command (command &rest args)
+  `(progn
+     (setf *last-rcs-command-name* ',command)
+     (get-output-stream-string *rcs-output-stream*)
+     (let ((process (ext:run-program ',command ,@args
+				     :error *rcs-output-stream*)))
+       (setf *last-rcs-command-output-string*
+	     (get-output-stream-string *rcs-output-stream*))
+       (case (ext:process-status process)
+	 (:exited
+	  (unless (zerop (ext:process-exit-code process))
+	    (editor-error "~A aborted with an error; ~
+			   use the ``RCS Last Command Output'' command for ~
+			   more information" ',command)))
+	 (:signaled
+	  (editor-error "~A killed with signal ~A~@[ (core dumped)]."
+			',command
+			(ext:process-exit-code process)
+			(ext:process-core-dumped process)))
+	 (t
+	  (editor-error "~S still alive?" process))))))
+
+(defun buffer-different-from-file (buffer filename)
+  (with-open-file (file filename)
+    (do ((buffer-line (mark-line (buffer-start-mark buffer))
+		      (line-next buffer-line))
+	 (file-line (read-line file nil nil)
+		    (read-line file nil nil)))
+	((and (or (null buffer-line)
+		  (zerop (line-length buffer-line)))
+	      (null file-line))
+	 nil)
+      (when (or (null buffer-line)
+		(null file-line)
+		(string/= (line-string buffer-line) file-line))
+	(return t)))))
+
+(defun turn-auto-save-off (buffer)
+  (setf (buffer-minor-mode buffer "Save") nil)
+  ;;
+  ;; William's personal hack
+  (when (getstring "Ckp" *mode-names*)
+    (setf (buffer-minor-mode buffer "Ckp") nil)))
+
+
+(defhvar "RCS Lock File Hook"
+  "RCS Lock File Hook"
+  :value nil)
+
+(defun rcs-lock-file (buffer pathname)
+  (message "Locking ~A ..." (namestring pathname))
+  (in-directory pathname
+    (let ((file (file-namestring pathname)))
+      (do-command "rcs" `("-l" ,file))
+      (multiple-value-bind (won dev ino mode) (unix:unix-stat file)
+	(declare (ignore ino))
+	(cond (won
+	       (unix:unix-chmod file (logior mode unix:writeown)))
+	      (t
+	       (editor-error "UNIX:UNIX-STAT lost in RCS-LOCK-FILE: ~A"
+			     (unix:get-unix-error-msg dev)))))))
+  (invoke-hook rcs-lock-file-hook buffer pathname))
+
+
+(defhvar "RCS Unlock File Hook"
+  "RCS Unlock File Hook"
+  :value nil)
+
+(defun rcs-unlock-file (buffer pathname)
+  (message "Unlocking ~A ..." (namestring pathname))
+  (in-directory pathname
+    (do-command "rcs" `("-u" ,(file-namestring pathname))))
+  (invoke-hook rcs-unlock-file-hook buffer pathname))
+
+
+
+;;;; Check In
+
+(defhvar "RCS Check In File Hook"
+  "RCS Check In File Hook"
+  :value nil)
+
+(defhvar "RCS Keep Around After Unlocking"
+  "If non-NIL (the default) keep the working file around after unlocking it.
+   When NIL, the working file and buffer are deleted."
+  :value t)
+
+(defun rcs-check-in-file (buffer pathname keep-lock)
+  (let ((old-buffer (current-buffer))
+	(allow-delete nil)
+	(log-buffer nil))
+    (unwind-protect
+	(when (block in-recursive-edit
+		(do ((i 0 (1+ i)))
+		    ((not (null log-buffer)))
+		  (setf log-buffer
+			(make-buffer
+			 (format nil "RCS Log Entry ~D for ~S" i
+				 (file-namestring pathname))
+			 :modes '("Text")
+			 :delete-hook
+			 (list #'(lambda (buffer)
+				   (declare (ignore buffer))
+				   (unless allow-delete
+				     (return-from in-recursive-edit t)))))))
+		(turn-auto-save-off log-buffer)
+		(change-to-buffer log-buffer)
+		(do-recursive-edit)
+	  
+		(message "Checking in ~A~:[~; keeping the lock~] ..."
+			 (namestring pathname) keep-lock)
+		(let ((log-stream (make-hemlock-region-stream
+				   (buffer-region log-buffer))))
+		  (sub-check-in-file pathname buffer keep-lock log-stream))
+		(invoke-hook rcs-check-in-file-hook buffer pathname)
+		nil)
+	  (editor-error "Someone deleted the RCS Log Entry buffer."))
+      (when (member old-buffer *buffer-list*)
+	(change-to-buffer old-buffer))
+      (setf allow-delete t)
+      (delete-buffer-if-possible log-buffer))))
+
+(defun sub-check-in-file (pathname buffer keep-lock log-stream)
+  (let* ((filename (file-namestring pathname))
+	 (rcs-filename (concatenate 'simple-string
+				    "./RCS/" filename ",v"))
+	 (keep-working-copy (or keep-lock
+				(not (hemlock-bound-p
+				      'rcs-keep-around-after-unlocking
+				      :buffer buffer))
+				(variable-value
+				 'rcs-keep-around-after-unlocking
+				 :buffer buffer))))
+    (in-directory pathname
+      (do-command "ci" `(,@(if keep-lock '("-l"))
+			    ,@(if keep-working-copy '("-u"))
+			    ,filename)
+		  :input log-stream)
+      (if keep-working-copy
+	  ;; 
+	  ;; Set the times on the user's file to be equivalent to that of
+	  ;; the rcs file.
+	  #-(or hpux svr4)
+	  (multiple-value-bind
+	      (dev ino mode nlink uid gid rdev size atime mtime)
+	      (unix:unix-stat rcs-filename)
+	    (declare (ignore mode nlink uid gid rdev size))
+	    (cond (dev
+		   (multiple-value-bind
+		       (wonp errno)
+		       (unix:unix-utimes filename atime 0 mtime 0)
+		     (unless wonp
+		       (editor-error "UNIX:UNIX-UTIMES failed: ~A"
+				     (unix:get-unix-error-msg errno)))))
+		  (t
+		   (editor-error "UNIX:UNIX-STAT failed: ~A"
+				 (unix:get-unix-error-msg ino)))))
+	  (delete-buffer-if-possible buffer)))))
+
+
+
+
+;;;; Check Out
+
+(defhvar "RCS Check Out File Hook"
+  "RCS Check Out File Hook"
+  :value nil)
+
+(defvar *translate-file-names-before-locking* nil)
+
+(defun maybe-rcs-check-out-file (buffer pathname lock always-overwrite-p)
+  (when (and lock *translate-file-names-before-locking*)
+    (multiple-value-bind (unmatched-dir new-dirs file-name)
+			 (maybe-translate-definition-file pathname)
+      (when new-dirs
+	(let ((new-name (translate-definition-file unmatched-dir
+						   (car new-dirs)
+						   file-name)))
+	  (when (probe-file (directory-namestring new-name))
+	    (setf pathname new-name))))))
+  (cond
+   ((and (not always-overwrite-p)
+	 (let ((pn (probe-file pathname)))
+	   (and pn (hemlock-ext:file-writable pn))))
+    ;; File exists and is writable so check and see if the user really
+    ;; wants to check it out.
+    (command-case (:prompt
+		   (format nil "The file ~A is writable.  Overwrite? "
+			   (file-namestring pathname))
+		   :help
+		   "Type one of the following single-character commands:")
+      ((:yes :confirm)
+       "Overwrite the file."
+       (rcs-check-out-file buffer pathname lock))
+      (:no
+       "Don't check it out after all.")
+      ((#\r #\R)
+       "Rename the file before checking it out."
+       (let ((new-pathname (prompt-for-file
+			    :prompt "New Filename: "
+			    :default (buffer-default-pathname
+				      (current-buffer))
+			    :must-exist nil)))
+	 (rename-file pathname new-pathname)
+	 (rcs-check-out-file buffer pathname lock)))))
+   (t
+    (rcs-check-out-file buffer pathname lock)))
+  pathname)
+
+(defun rcs-check-out-file (buffer pathname lock)
+  (message "Checking out ~A~:[~; with a lock~] ..." (namestring pathname) lock)
+  (in-directory pathname
+    (let* ((file (file-namestring pathname))
+	   (backup (if (probe-file file)
+		       (lisp::pick-backup-name file))))
+      (when backup (rename-file file backup))
+      (do-command "co" `(,@(if lock '("-l")) ,file))
+      (invoke-hook rcs-check-out-file-hook buffer pathname)
+      (when backup (delete-file backup)))))
+
+
+
+;;;; Last Command Output
+
+(defcommand "RCS Last Command Output" (p)
+  "Print the full output of the last RCS command."
+  "Print the full output of the last RCS command."
+  (declare (ignore p))
+  (unless (and *last-rcs-command-name* *last-rcs-command-output-string*)
+    (editor-error "No RCS commands have executed!"))
+  (with-pop-up-display (s :buffer-name "*RCS Command Output*")
+    (format s "Output from ``~A'':~%~%" *last-rcs-command-name*)
+    (write-line *last-rcs-command-output-string* s)))
+
+
+
+;;;; Commands for Checking In / Checking Out and Locking / Unlocking 
+
+(defun pick-temp-file (defaults)
+  (let ((index 0))
+    (loop
+      (let ((name (merge-pathnames (format nil ",rcstmp-~D" index) defaults)))
+	(cond ((probe-file name)
+	       (incf index))
+	      (t
+	       (return name)))))))
+
+(defcommand "RCS Lock Buffer File" (p)
+  "Attempt to lock the file in the current buffer."
+  "Attempt to lock the file in the current buffer."
+  (declare (ignore p))
+  (let ((file (current-buffer-pathname))
+	(buffer (current-buffer))
+	(name (pick-temp-file "/tmp/")))
+    (rcs-lock-file buffer file)
+    (unwind-protect
+	(progn
+	  (in-directory file
+  	    (do-command "co" `("-p" ,(file-namestring file))
+			:output (namestring name)))
+	  (when (buffer-different-from-file buffer name)
+	    (message
+	     "RCS file is different; be sure to merge in your changes."))
+	  (setf (buffer-writable buffer) t)
+	  (message "Buffer is now writable."))
+      (when (probe-file name)
+	(delete-file name)))))
+
+(defcommand "RCS Lock File" (p)
+  "Prompt for a file, and attempt to lock it."
+  "Prompt for a file, and attempt to lock it."
+  (declare (ignore p))
+  (rcs-lock-file nil (prompt-for-file :prompt "File to lock: "
+				      :default (buffer-default-pathname
+						(current-buffer))
+				      :must-exist nil)))
+
+(defcommand "RCS Unlock Buffer File" (p)
+  "Unlock the file in the current buffer."
+  "Unlock the file in the current buffer."
+  (declare (ignore p))
+  (rcs-unlock-file (current-buffer) (current-buffer-pathname))
+  (setf (buffer-writable (current-buffer)) nil)
+  (message "Buffer is no longer writable."))
+
+(defcommand "RCS Unlock File" (p)
+  "Prompt for a file, and attempt to unlock it."
+  "Prompt for a file, and attempt to unlock it."
+  (declare (ignore p))
+  (rcs-unlock-file nil (prompt-for-file :prompt "File to unlock: "
+					:default (buffer-default-pathname
+						  (current-buffer))
+					:must-exist nil)))
+
+(defcommand "RCS Check In Buffer File" (p)
+  "Checkin the file in the current buffer.  With an argument, do not
+  release the lock."
+  "Checkin the file in the current buffer.  With an argument, do not
+  release the lock."
+  (let ((buffer (current-buffer))
+	(pathname (current-buffer-pathname)))
+    (when (buffer-modified buffer)
+      (save-file-command nil))
+    (rcs-check-in-file buffer pathname p)
+    (when (member buffer *buffer-list*)
+      ;; If the buffer has not been deleted, make sure it is up to date
+      ;; with respect to the file.
+      (visit-file-command nil pathname buffer))))
+
+(defcommand "RCS Check In File" (p)
+  "Prompt for a file, and attempt to check it in.  With an argument, do
+  not release the lock."
+  "Prompt for a file, and attempt to check it in.  With an argument, do
+  not release the lock."
+  (rcs-check-in-file nil (prompt-for-file :prompt "File to lock: "
+					  :default
+					  (buffer-default-pathname
+					   (current-buffer))
+					  :must-exist nil)
+		     p))
+
+(defcommand "RCS Check Out Buffer File" (p)
+  "Checkout the file in the current buffer.  With an argument, lock the
+  file."
+  "Checkout the file in the current buffer.  With an argument, lock the
+  file."
+  (let* ((buffer (current-buffer))
+	 (pathname (current-buffer-pathname))
+	 (point (current-point))
+	 (lines (1- (count-lines (region (buffer-start-mark buffer) point)))))
+    (when (buffer-modified buffer)
+      (when (not (prompt-for-y-or-n :prompt "Buffer is modified, overwrite? "))
+	(editor-error "Aborted.")))
+    (setf (buffer-modified buffer) nil)
+    (setf pathname (maybe-rcs-check-out-file buffer pathname p nil))
+    (when p
+      (setf (buffer-writable buffer) t)
+      (message "Buffer is now writable."))
+    (visit-file-command nil pathname)
+    (unless (line-offset point lines)
+      (buffer-end point))))
+
+(defcommand "RCS Check Out File" (p)
+  "Prompt for a file and attempt to check it out.  With an argument,
+  lock the file."
+  "Prompt for a file and attempt to check it out.  With an argument,
+  lock the file."
+  (let ((pathname (prompt-for-file :prompt "File to check out: "
+				   :default (buffer-default-pathname
+					     (current-buffer))
+				   :must-exist nil)))
+    (setf pathname (maybe-rcs-check-out-file nil pathname p nil))
+    (find-file-command nil pathname)))
+
+
+
+;;;; Log File
+
+(defhvar "RCS Log Entry Buffer"
+  "Name of the buffer to put RCS log entries into."
+  :value "RCS Log")
+
+(defhvar "RCS Log Buffer Hook"
+  "RCS Log Buffer Hook"
+  :value nil)
+
+(defun get-log-buffer ()
+  (let ((buffer (getstring (value rcs-log-entry-buffer) *buffer-names*)))
+    (unless buffer
+      (setf buffer (make-buffer (value rcs-log-entry-buffer)))
+      (turn-auto-save-off buffer)
+      (invoke-hook rcs-log-buffer-hook buffer))
+    buffer))
+
+(defcommand "RCS Buffer File Log Entry" (p)
+  "Get the RCS Log for the file in the current buffer in a buffer."
+  "Get the RCS Log for the file in the current buffer in a buffer."
+  (declare (ignore p))
+  (let ((buffer (get-log-buffer))
+	(pathname (current-buffer-pathname)))
+    (delete-region (buffer-region buffer))
+    (message "Extracting log info ...")
+    (with-mark ((mark (buffer-start-mark buffer) :left-inserting))
+      (in-directory pathname
+	(do-command "rlog" (list (file-namestring pathname))
+		    :output (make-hemlock-output-stream mark))))
+    (change-to-buffer buffer)
+    (buffer-start (current-point))
+    (setf (buffer-modified buffer) nil)))
+
+(defcommand "RCS File Log Entry" (p)
+  "Prompt for a file and get its RCS log entry in a buffer."
+  "Prompt for a file and get its RCS log entry in a buffer."
+  (declare (ignore p))
+  (let ((file (prompt-for-file :prompt "File to get log of: "
+			       :default (buffer-default-pathname
+					 (current-buffer))
+			       :must-exist nil))
+	(buffer (get-log-buffer)))
+    (delete-region (buffer-region buffer))
+    (message "Extracing log info ...")
+    (with-mark ((mark (buffer-start-mark buffer) :left-inserting))
+      (in-directory file
+	(do-command "rlog" (list (file-namestring file))
+		    :output (make-hemlock-output-stream mark))))
+    (change-to-buffer buffer)
+    (buffer-start (current-point))
+    (setf (buffer-modified buffer) nil)))
+
+
+
+;;;; Status and Modeline Frobs.
+
+(defhvar "RCS Status"
+  "RCS status of this buffer.  Either nil, :locked, :out-of-date, or
+  :unlocked."
+  :value nil)
+
+;;;
+;;; Note: This doesn't behave correctly w/r/t to branched files.
+;;; 
+(defun rcs-file-status (pathname)
+  (let* ((directory (directory-namestring pathname))
+	 (filename (file-namestring pathname))
+	 (rcs-file (concatenate 'simple-string directory
+				"RCS/" filename ",v")))
+    (if (probe-file rcs-file)
+	;; This is an RCS file
+	(let ((probe-file (probe-file pathname)))
+	  (cond ((and probe-file (hemlock-ext:file-writable probe-file))
+		 :locked)
+		((or (not probe-file)
+		     (< (file-write-date pathname)
+			(file-write-date rcs-file)))
+		 :out-of-date)
+		(t
+		 :unlocked))))))
+
+(defun rcs-update-buffer-status (buffer &optional tn)
+  (unless (hemlock-bound-p 'rcs-status :buffer buffer)
+    (defhvar "RCS Status"
+      "RCS Status of this buffer."
+      :buffer buffer
+      :value nil))
+  (let ((tn (or tn (buffer-pathname buffer))))
+    (setf (variable-value 'rcs-status :buffer buffer)
+	  (if tn (rcs-file-status tn))))
+  (hi::update-modelines-for-buffer buffer))
+;;; 
+(add-hook read-file-hook 'rcs-update-buffer-status)
+(add-hook write-file-hook 'rcs-update-buffer-status)
+
+(defcommand "RCS Update All RCS Status Variables" (p)
+  "Update the ``RCS Status'' variable for all buffers."
+  "Update the ``RCS Status'' variable for all buffers."
+  (declare (ignore p))
+  (dolist (buffer *buffer-list*)
+    (rcs-update-buffer-status buffer))
+  (dolist (window *window-list*)
+    (update-modeline-fields (window-buffer window) window)))
+
+;;; 
+;;; Action Hooks
+(defun rcs-action-hook (buffer pathname)
+  (cond (buffer
+	 (rcs-update-buffer-status buffer))
+	(t
+	 (let ((pathname (probe-file pathname)))
+	   (when pathname
+	     (dolist (buffer *buffer-list*)
+	       (let ((buffer-pathname (buffer-pathname buffer)))
+		 (when (equal pathname buffer-pathname)
+		   (rcs-update-buffer-status buffer)))))))))
+;;; 
+(add-hook rcs-check-in-file-hook 'rcs-action-hook)
+(add-hook rcs-check-out-file-hook 'rcs-action-hook)
+(add-hook rcs-lock-file-hook 'rcs-action-hook)
+(add-hook rcs-unlock-file-hook 'rcs-action-hook)
+
+
+;;;
+;;; RCS Modeline Field
+(make-modeline-field
+ :name :rcs-status
+ :function #'(lambda (buffer window)
+	       (declare (ignore buffer window))
+	       (ecase (value rcs-status)
+		 (:out-of-date "[OLD]  ")
+		 (:locked "[LOCKED]  ")
+		 (:unlocked "[RCS]  ")
+		 ((nil) ""))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/screen.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/screen.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/screen.lisp	(revision 13309)
@@ -0,0 +1,204 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles.
+;;;
+;;; Device independent screen management functions.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Screen management initialization.
+
+(declaim (special *echo-area-buffer*))
+
+;;; %INIT-SCREEN-MANAGER creates the initial windows and sets up the data
+;;; structures used by the screen manager.  The "Main" and "Echo Area" buffer
+;;; modelines are set here in case the user modified these Hemlock variables in
+;;; his init file.  Since these buffers don't have windows yet, these sets
+;;; won't cause any updates to occur.  This is called from %INIT-REDISPLAY.
+;;;
+(defun %init-screen-manager (display)
+  (setf (buffer-modeline-fields *current-buffer*)
+	(value hemlock::default-modeline-fields))
+  (setf (buffer-modeline-fields *echo-area-buffer*)
+	(value hemlock::default-status-line-fields))
+  (if (windowed-monitor-p)
+      (init-bitmap-screen-manager display)
+      (init-tty-screen-manager (get-terminal-name))))
+
+
+
+
+;;;; Window operations.
+
+(defun make-window (start &key (modelinep t) (device nil) window
+			  (proportion .5)			  
+			  (font-family *default-font-family*)
+			  (ask-user nil) x y
+			  (width (value hemlock::default-window-width))
+			  (height (value hemlock::default-window-height)))
+  "Make a window that displays text starting at the mark start.  The default
+   action is to make the new window a proportion of the current window's height
+   to make room for the new window.
+
+   Proportion determines what proportion of the current window's height
+   the new window will use.  The current window retains whatever space left
+   after accommodating the new one.  The default is to split the current window
+   in half.
+
+   Modelinep specifies whether the window should display buffer modelines.
+
+   Device is the Hemlock device to make the window on.  If it is nil, then
+   the window is made on the same device as CURRENT-WINDOW.
+
+   Window is an X window to be used with the Hemlock window.  The supplied
+   window becomes the parent window for a new group of windows that behave
+   in a stack orientation as windows do on the terminal.
+
+   Font-Family is the font-family used for displaying text in the window.
+
+   If Ask-User is non-nil, Hemlock prompts the user for missing X, Y, Width,
+   and Height arguments to make a new group of windows that behave in a stack
+   orientation as windows do on the terminal.  This occurs by invoking
+   hi::*create-window-hook*.  X and Y are supplied as pixels, but Width and
+   Height are supplied in characters."
+
+  (let* ((device (or device (device-hunk-device (window-hunk (current-window)))))
+	 (window (funcall (device-make-window device)
+			  device start modelinep window font-family
+			  ask-user x y width height proportion)))
+    (unless window (editor-error "Could not make a window."))
+    (invoke-hook hemlock::make-window-hook window)
+    window))
+
+(defun delete-window (window)
+  "Make Window go away, removing it from the screen.  This uses
+   hi::*delete-window-hook* to get rid of parent windows on a bitmap device
+   when you delete the last Hemlock window in a group."
+  (when (<= (length *window-list*) 2)
+    (error "Cannot kill the only window."))
+  (invoke-hook hemlock::delete-window-hook window)
+  (setq *window-list* (delq window *window-list*))
+  (funcall (device-delete-window (device-hunk-device (window-hunk window)))
+	   window)
+  ;;
+  ;; Since the programmer's interface fails to allow users to determine if
+  ;; they're commands delete the current window, this primitive needs to
+  ;; make sure Hemlock doesn't get screwed.  This inadequacy comes from the
+  ;; bitmap window groups and the vague descriptions of PREVIOUS-WINDOW and
+  ;; NEXT-WINDOW.
+  (when (eq window *current-window*)
+    (let ((window (find-if-not #'(lambda (w) (eq w *echo-area-window*))
+			       *window-list*)))
+      (setf (current-buffer) (window-buffer window)
+	    (current-window) window))))
+
+(defun next-window (window)
+  "Return the next window after Window, wrapping around if Window is the
+  bottom window."
+  (check-type window window)
+  (funcall (device-next-window (device-hunk-device (window-hunk window)))
+	   window))
+
+(defun previous-window (window)
+  "Return the previous window after Window, wrapping around if Window is the
+  top window."
+  (check-type window window)
+  (funcall (device-previous-window (device-hunk-device (window-hunk window)))
+	   window))
+
+
+
+
+;;;; Random typeout support.
+
+;;; PREPARE-FOR-RANDOM-TYPEOUT  --  Internal
+;;;
+;;; The WITH-POP-UP-DISPLAY macro calls this just before displaying output
+;;; for the user.  This goes to some effor to compute the height of the window
+;;; in text lines if it is not supplied.  Whether it is supplied or not, we
+;;; add one to the height for the modeline, and we subtract one line if the
+;;; last line is empty.  Just before using the height, make sure it is at
+;;; least two -- one for the modeline and one for text, so window making
+;;; primitives don't puke.
+;;;
+(defun prepare-for-random-typeout (stream height)
+  (let* ((buffer (line-buffer (mark-line (random-typeout-stream-mark stream))))
+	 (real-height (1+ (or height (rt-count-lines buffer))))
+	 (device (device-hunk-device (window-hunk (current-window)))))
+    (funcall (device-random-typeout-setup device) device stream
+	     (max (if (and (empty-line-p (buffer-end-mark buffer)) (not height))
+		      (1- real-height)
+		      real-height)
+		  2))))
+
+;;; RT-COUNT-LINES computes the correct height for a window.  This includes
+;;; taking wrapping line characters into account.  Take the MARK-COLUMN at
+;;; the end of each line.  This is how many characters long hemlock thinks
+;;; the line is.  When it is displayed, however, end of line characters are
+;;; added to the end of each line that wraps.  The second INCF form adds
+;;; these to the current line length.  Then INCF the current height by the
+;;; CEILING of the width of the random typeout window and the line length
+;;; (with added line-end chars).  Use CEILING because there is always at
+;;; least one line.  Finally, jump out of the loop if we're at the end of
+;;; the buffer.
+;;;
+(defun rt-count-lines (buffer)
+  (with-mark ((mark (buffer-start-mark buffer)))
+    (let ((width (window-width (current-window)))
+	  (count 0))
+	(loop
+	  (let* ((column (mark-column (line-end mark)))
+		 (temp (ceiling (incf column (floor (1- column) width))
+				width)))
+	    ;; Lines with no characters yield zero temp.
+	    (incf count (if (zerop temp) 1 temp))
+	    (unless (line-offset mark 1) (return count)))))))
+
+
+;;; RANDOM-TYPEOUT-CLEANUP  --  Internal
+;;;
+;;;    Clean up after random typeout.  This clears the area where the 
+;;; random typeout was and redisplays any affected windows.
+;;;
+(defun random-typeout-cleanup (stream &optional (degree t))
+  (let* ((window (random-typeout-stream-window stream))
+	 (buffer (window-buffer window))
+	 (device (device-hunk-device (window-hunk window)))
+	 (*more-prompt-action* :normal))
+    (update-modeline-field buffer window :more-prompt)
+    (random-typeout-redisplay window)
+    (setf (buffer-windows buffer) (delete window (buffer-windows buffer)))
+    (funcall (device-random-typeout-cleanup device) stream degree)
+    (when (device-force-output device)
+      (funcall (device-force-output device)))))
+
+;;; *more-prompt-action* is bound in random typeout streams before
+;;; redisplaying.
+;;;
+(defvar *more-prompt-action* :normal)
+(defvar *random-typeout-ml-fields*
+  (list (make-modeline-field
+	 :name :more-prompt
+	 :function #'(lambda (buffer window)
+		       (declare (ignore window))
+		       (ecase *more-prompt-action*
+			 (:more "--More--")
+			 (:flush "--Flush--")
+			 (:empty "")
+			 (:normal
+			  (concatenate 'simple-string
+				       "Random Typeout Buffer          ["
+				       (buffer-name buffer)
+				       "]")))))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/scribe.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/scribe.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/scribe.lisp	(revision 13309)
@@ -0,0 +1,501 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+
+(in-package :hemlock)
+
+
+
+;;;; Variables.
+
+(defvar *scribe-para-break-table* (make-hash-table :test #'equal)
+  "A table of the Scribe commands that should be paragraph delimiters.")
+;;;
+(dolist (todo '("begin" "newpage" "make" "device" "caption" "tag" "end" 
+		"chapter" "section" "appendix" "subsection" "paragraph"
+		"unnumbered" "appendixsection" "prefacesection" "heading"
+		"majorheading" "subheading")) 
+  (setf (gethash todo *scribe-para-break-table*) t))
+
+(defhvar "Open Paren Character"
+  "The open bracket inserted by Scribe commands."
+  :value #\[)
+
+(defhvar "Close Paren Character"
+  "The close bracket inserted by Scribe commands."
+  :value #\])
+
+(defhvar "Escape Character"
+  "The escape character inserted by Scribe commands."
+  :value #\@)
+
+(defhvar "Scribe Bracket Table"
+  "This table maps a Scribe brackets, open and close, to their opposing
+   brackets."
+  :value (make-array char-code-limit))
+;;;
+(mapc #'(lambda (x y)
+	  (setf (svref (value scribe-bracket-table) (char-code x)) y)
+	  (setf (svref (value scribe-bracket-table) (char-code y)) x))
+      '(#\( #\[ #\{ #\<) '(#\) #\] #\} #\>))
+;;;
+(defun opposing-bracket (bracket)
+  (svref (value scribe-bracket-table) (char-code bracket)))
+
+
+
+
+;;;; "Scribe Syntax" Attribute.
+
+(defattribute "Scribe Syntax" 
+  "For Scribe Syntax, Possible types are:
+   :ESCAPE           ; basically #\@.
+   :OPEN-PAREN       ; Characters that open a Scribe paren:  #\[, #\{, #\(, #\<.
+   :CLOSE-PAREN      ; Characters that close a Scribe paren:  #\], #\}, #\), #\>.
+   :SPACE            ; Delimits end of a Scribe command.
+   :NEWLINE          ; Delimits end of a Scribe command."
+  'symbol nil)
+
+(setf (character-attribute :scribe-syntax #\)) :close-paren) 
+(setf (character-attribute :scribe-syntax #\]) :close-paren) 
+(setf (character-attribute :scribe-syntax #\}) :close-paren) 
+(setf (character-attribute :scribe-syntax #\>) :close-paren) 
+
+(setf (character-attribute :scribe-syntax #\() :open-paren)     
+(setf (character-attribute :scribe-syntax #\[) :open-paren)
+(setf (character-attribute :scribe-syntax #\{) :open-paren)
+(setf (character-attribute :scribe-syntax #\<) :open-paren)
+
+(setf (character-attribute :scribe-syntax #\space)   :space)
+(setf (character-attribute :scribe-syntax #\newline) :newline)
+(setf (character-attribute :scribe-syntax #\@)       :escape)
+
+
+
+
+;;;; "Scribe" mode and setup.
+
+(defmode "Scribe" :major-p t)
+
+(shadow-attribute :paragraph-delimiter #\@ 1 "Scribe")
+(shadow-attribute :word-delimiter #\' 0 "Scribe")		;from Text Mode
+(shadow-attribute :word-delimiter #\backspace 0 "Scribe")	;from Text Mode
+(shadow-attribute :word-delimiter #\_ 0 "Scribe")		;from Text Mode
+
+(define-file-type-hook ("mss") (buffer type)
+  (declare (ignore type))
+  (setf (buffer-major-mode buffer) "Scribe"))
+
+
+
+
+;;;; Commands.
+
+(defcommand "Scribe Mode" (p)
+  "Puts buffer in Scribe mode.  Sets up comment variables and has delimiter
+   matching.  The definition of paragraphs is changed to know about scribe
+   commands."
+  "Puts buffer in Scribe mode."
+  (declare (ignore p))
+  (setf (buffer-major-mode (current-buffer)) "Scribe"))
+
+(defcommand "Select Scribe Warnings" (p)
+  "Goes to the Scribe Warnings buffer if it exists."
+  "Goes to the Scribe Warnings buffer if it exists."
+  (declare (ignore p))
+  (let ((buffer (getstring "Scribe Warnings" *buffer-names*)))
+    (if buffer
+	(change-to-buffer buffer)
+	(editor-error "There is no Scribe Warnings buffer."))))
+
+(defcommand "Add Scribe Paragraph Delimiter"
+	    (p &optional
+	       (word (prompt-for-string
+		      :prompt "Scribe command: "
+		      :help "Name of Scribe command to make delimit paragraphs."
+		      :trim t)))
+  "Prompts for a name to add to the table of commands that delimit paragraphs
+   in Scribe mode.  If a prefix argument is supplied, then the command name is
+   removed from the table."
+  "Add or remove Word in the *scribe-para-break-table*, depending on P."
+  (setf (gethash word *scribe-para-break-table*) (not p)))
+
+(defcommand "List Scribe Paragraph Delimiters" (p)
+  "Pops up a display of the Scribe commands that delimit paragraphs."
+  "Pops up a display of the Scribe commands that delimit paragraphs."
+  (declare (ignore p))
+  (let (result)
+    (maphash #'(lambda (k v)
+		 (declare (ignore v))
+		 (push k result))
+	     *scribe-para-break-table*)
+    (setf result (sort result #'string<))
+    (with-pop-up-display (s :height (length result))
+      (dolist (ele result) (write-line ele s)))))
+
+(defcommand "Scribe Insert Bracket" (p)
+  "Inserts a the bracket it is bound to and then shows the matching bracket."
+  "Inserts a the bracket it is bound to and then shows the matching bracket."
+  (declare (ignore p))
+  (scribe-insert-paren (current-point)
+		       (hemlock-ext:key-event-char *last-key-event-typed*)))
+
+
+(defhvar "Scribe Command Table"
+  "This is a character dispatching table indicating which Scribe command or
+   environment to use."
+  :value (make-hash-table)
+  :mode "Scribe")
+
+(defvar *scribe-directive-type-table*
+  (make-string-table :initial-contents
+		     '(("Command" . :command)
+		       ("Environment" . :environment))))
+
+(defcommand "Add Scribe Directive" (p &optional
+				      (command-name nil command-name-p)
+				      type key-event mode)
+  "Adds a new scribe function to put into \"Scribe Command Table\"."
+  "Adds a new scribe function to put into \"Scribe Command Table\"."
+  (declare (ignore p))
+  (let ((command-name (if command-name-p
+			  command-name
+			  (or command-name
+			      (prompt-for-string :help "Directive Name"
+						 :prompt "Directive: ")))))
+    (multiple-value-bind (ignore type)
+			 (if type
+			     (values nil type)
+			     (prompt-for-keyword
+			      (list *scribe-directive-type-table*)
+			      :help "Enter Command or Environment."
+			      :prompt "Command or Environment: "))
+      (declare (ignore ignore))
+      (let ((key-event (or key-event
+			   (prompt-for-key-event :prompt
+						 "Dispatch Character: "))))
+	(setf (gethash key-event
+		       (cond (mode
+			      (variable-value 'scribe-command-table :mode mode))
+			     ((hemlock-bound-p 'scribe-command-table)
+			      (value scribe-command-table))
+			     (t (editor-error
+				 "Could not find \"Scribe Command Table\"."))))
+	      (cons type command-name))))))
+
+(defcommand "Insert Scribe Directive" (p)
+  "Prompts for a character to dispatch on.  Some indicate \"commands\" versus
+   \"environments\".  Commands are wrapped around the previous or current word.
+   If there is no previous word, the command is insert, leaving point between
+   the brackets.  Environments are wrapped around the next or current
+   paragraph, but when the region is active, this wraps the environment around
+   the region.  Each uses \"Open Paren Character\" and \"Close Paren
+   Character\"."
+  "Wrap some text with some stuff."
+  (declare (ignore p))
+  (loop
+    (let ((key-event (prompt-for-key-event :prompt "Dispatch Character: ")))
+      (if (logical-key-event-p key-event :help)
+	  (directive-help)
+	  (let ((table-entry (gethash key-event (value scribe-command-table))))
+	    (ecase (car table-entry)
+	      (:command
+	       (insert-scribe-directive (current-point) (cdr table-entry))
+	       (return))
+	      (:environment
+	       (enclose-with-environment (current-point) (cdr table-entry))
+	       (return))
+	      ((nil) (editor-error "Unknown dispatch character."))))))))
+
+
+
+
+;;;; "Insert Scribe Directive" support.
+
+(defun directive-help ()
+  (let ((commands ())
+	(environments ()))
+    (declare (list commands environments))
+    (maphash #'(lambda (k v)
+		 (if (eql (car v) :command)
+		     (push (cons k (cdr v)) commands)
+		     (push (cons k (cdr v)) environments)))
+	     (value scribe-command-table))
+    (setf commands (sort commands #'string< :key #'cdr))
+    (setf environments (sort environments #'string< :key #'cdr))
+    (with-pop-up-display (s :height (1+ (max (length commands)
+					     (length environments))))
+      (format s "~2TCommands~47TEnvironments~%")
+      (do ((commands commands (rest commands))
+	   (environments environments (rest environments)))
+	   ((and (endp commands) (endp environments)))
+	(let* ((command (first commands))
+	       (environment (first environments))
+	       (cmd-char (first command))
+	       (cmd-name (rest command))
+	       (env-char (first environment))
+	       (env-name (rest environment)))
+	  (write-string "  " s)
+	  (when cmd-char
+	    (hemlock-ext:print-pretty-key-event cmd-char s)
+	    (format s "~7T")
+	    (write-string (or cmd-name "<prompts for command name>") s))
+	  (when env-char
+	    (format s "~47T")
+	    (hemlock-ext:print-pretty-key-event env-char s)
+	    (format s "~51T")
+	    (write-string (or env-name "<prompts for command name>") s))
+	  (terpri s))))))
+
+;;;
+;;; Inserting and extending :command directives.
+;;;
+
+(defhvar "Insert Scribe Directive Function"
+  "\"Insert Scribe Directive\" calls this function when the directive type
+   is :command.  The function takes four arguments: a mark pointing to the word
+   start, the formatting command string, the open-paren character to use, and a
+   mark pointing to the word end."
+  :value 'scribe-insert-scribe-directive-fun
+  :mode "Scribe")
+
+(defun scribe-insert-scribe-directive-fun (word-start command-string
+					   open-paren-char word-end)
+  (insert-character word-start (value escape-character))
+  (insert-string word-start command-string)
+  (insert-character word-start open-paren-char)
+  (insert-character word-end (value close-paren-character)))
+
+(defhvar "Extend Scribe Directive Function"
+  "\"Insert Scribe Directive\" calls this function when the directive type is
+   :command to extend the the commands effect.  This function takes a string
+   and three marks: the first on pointing before the open-paren character for
+   the directive.  The string is the command-string to selected by the user
+   which this function uses to determine if it is actually extending a command
+   or inserting a new one.  The function must move the first mark before any
+   command text for the directive and the second mark to the end of any command
+   text.  It moves the third mark to the previous word's start where the
+   command region should be.  If this returns non-nil \"Insert Scribe
+   Directive\" moves the command region previous one word, and otherwise it
+   inserts the directive."
+  :value 'scribe-extend-scribe-directive-fun
+  :mode "Scribe")
+
+(defun scribe-extend-scribe-directive-fun (command-string
+					   command-end command-start word-start)
+  (word-offset (move-mark command-start command-end) -1)
+  (when (string= (the simple-string (region-to-string
+				     (region command-start command-end)))
+		 command-string)
+    (mark-before command-start)
+    (mark-after command-end)
+    (word-offset (move-mark word-start command-start) -1)))
+
+;;; INSERT-SCRIBE-DIRECTIVE first looks for the current or previous word at
+;;; mark.  Word-p says if we found one.  If mark is immediately before a word,
+;;; we use that word instead of the previous.  This is because if mark
+;;; corresponds to the CURRENT-POINT, the Hemlock cursor is displayed on the
+;;; first character of the word making users think the mark is in the word
+;;; instead of before it.  If we find a word, then we see if it already has
+;;; the given command-string, and if it does, we extend the use of the command-
+;;; string to the previous word.  At the end, if we hadn't found a word, we
+;;; backup the mark one character to put it between the command brackets.
+;;;
+(defun insert-scribe-directive (mark &optional command-string)
+  (with-mark ((word-start mark :left-inserting)
+	      (word-end mark :left-inserting))
+    (let ((open-paren-char (value open-paren-character))
+	  (word-p (if (and (zerop (character-attribute
+				   :word-delimiter
+				   (next-character word-start)))
+			   (= (character-attribute
+			       :word-delimiter
+			       (previous-character word-start))
+			      1))
+		      word-start
+		      (word-offset word-start -1)))
+	  (command-string (or command-string
+			      (prompt-for-string
+			       :trim t :prompt "Environment: "
+			       :help "Name of environment to enclose with."))))
+      (declare (simple-string command-string))
+      (cond
+       (word-p
+	(word-offset (move-mark word-end word-start) 1)
+	(if (test-char (next-character word-end) :scribe-syntax
+		       :close-paren)
+	    (with-mark ((command-start word-start :left-inserting)
+			(command-end word-end :left-inserting))
+	      ;; Move command-end from word-end to open-paren of command.
+	      (balance-paren (mark-after command-end))
+	      (if (funcall (value extend-scribe-directive-function)
+			   command-string command-end command-start word-start)
+		  (let ((region (delete-and-save-region
+				 (region command-start command-end))))
+		    (word-offset (move-mark word-start command-start) -1)
+		    (ninsert-region word-start region))
+		  (funcall (value insert-scribe-directive-function)
+			   word-start command-string open-paren-char
+			   word-end)))
+	    (funcall (value insert-scribe-directive-function)
+		     word-start command-string open-paren-char word-end)))
+	(t
+	 (funcall (value insert-scribe-directive-function)
+		  word-start command-string open-paren-char word-end)
+	 (mark-before mark))))))
+
+;;;
+;;; Inserting :environment directives.
+;;;
+
+(defun enclose-with-environment (mark &optional environment)
+  (if (region-active-p)
+      (let ((region (current-region)))
+	(with-mark ((top (region-start region) :left-inserting)
+		    (bottom (region-end region) :left-inserting))
+	  (get-and-insert-environment top bottom environment)))
+      (with-mark ((bottom-mark mark :left-inserting))
+	(let ((paragraphp (paragraph-offset bottom-mark 1)))
+	  (unless (or paragraphp
+		      (and (last-line-p bottom-mark)
+			   (end-line-p bottom-mark)
+			   (not (blank-line-p (mark-line bottom-mark)))))
+	    (editor-error "No paragraph to enclose."))
+	  (with-mark ((top-mark bottom-mark :left-inserting))
+	    (paragraph-offset top-mark -1)
+	    (cond ((not (blank-line-p (mark-line top-mark)))
+		   (insert-character top-mark #\Newline)
+		   (mark-before top-mark))
+		  (t
+		   (insert-character top-mark #\Newline)))
+	    (cond ((and (last-line-p bottom-mark)
+			(not (blank-line-p (mark-line bottom-mark))))
+		   (insert-character bottom-mark #\Newline))
+		  (t
+		   (insert-character bottom-mark #\Newline)
+		   (mark-before bottom-mark)))
+	    (get-and-insert-environment top-mark bottom-mark environment))))))
+
+(defun get-and-insert-environment (top-mark bottom-mark environment)
+  (let ((environment (or environment
+			 (prompt-for-string
+			  :trim t :prompt "Environment: "
+			  :help "Name of environment to enclose with."))))
+    (insert-environment top-mark "begin" environment)
+    (insert-environment bottom-mark "end" environment)))
+
+(defun insert-environment (mark command environment)
+  (let ((esc-char (value escape-character))
+	(open-paren (value open-paren-character))
+	(close-paren (value close-paren-character)))
+      (insert-character mark esc-char)
+      (insert-string mark command)
+      (insert-character mark open-paren)
+      (insert-string mark environment)
+      (insert-character mark close-paren)))
+
+
+(add-scribe-directive-command nil nil :Environment #k"Control-l" "Scribe")
+(add-scribe-directive-command nil nil :Command #k"Control-w" "Scribe")
+(add-scribe-directive-command nil "Begin" :Command #k"b" "Scribe")
+(add-scribe-directive-command nil "End" :Command #k"e" "Scribe")
+(add-scribe-directive-command nil "Center" :Environment #k"c" "Scribe")
+(add-scribe-directive-command nil "Description" :Environment #k"d" "Scribe")
+(add-scribe-directive-command nil "Display" :Environment #k"Control-d" "Scribe")
+(add-scribe-directive-command nil "Enumerate" :Environment #k"n" "Scribe")
+(add-scribe-directive-command nil "Example" :Environment #k"x" "Scribe")
+(add-scribe-directive-command nil "FileExample" :Environment #k"y" "Scribe")
+(add-scribe-directive-command nil "FlushLeft" :Environment #k"l" "Scribe")
+(add-scribe-directive-command nil "FlushRight" :Environment #k"r" "Scribe")
+(add-scribe-directive-command nil "Format" :Environment #k"f" "Scribe")
+(add-scribe-directive-command nil "Group" :Environment #k"g" "Scribe")
+(add-scribe-directive-command nil "Itemize" :Environment #k"Control-i" "Scribe")
+(add-scribe-directive-command nil "Multiple" :Environment #k"m" "Scribe")
+(add-scribe-directive-command nil "ProgramExample" :Environment #k"p" "Scribe")
+(add-scribe-directive-command nil "Quotation" :Environment #k"q" "Scribe")
+(add-scribe-directive-command nil "Text" :Environment #k"t" "Scribe")
+(add-scribe-directive-command nil "i" :Command #k"i" "Scribe")
+(add-scribe-directive-command nil "b" :Command #k"Control-b" "Scribe")
+(add-scribe-directive-command nil "-" :Command #k"\-" "Scribe")
+(add-scribe-directive-command nil "+" :Command #k"+" "Scribe")
+(add-scribe-directive-command nil "u" :Command #k"Control-j" "Scribe")
+(add-scribe-directive-command nil "p" :Command #k"Control-p" "Scribe")
+(add-scribe-directive-command nil "r" :Command #k"Control-r" "Scribe")
+(add-scribe-directive-command nil "t" :Command #k"Control-t" "Scribe")
+(add-scribe-directive-command nil "g" :Command #k"Control-a" "Scribe")
+(add-scribe-directive-command nil "un" :Command #k"Control-n" "Scribe")
+(add-scribe-directive-command nil "ux" :Command #k"Control-x" "Scribe")
+(add-scribe-directive-command nil "c" :Command #k"Control-k" "Scribe")
+
+
+
+
+;;;; Scribe paragraph delimiter function.
+
+(defhvar "Paragraph Delimiter Function"
+  "Scribe Mode's way of delimiting paragraphs."
+  :mode "Scribe" 
+  :value 'scribe-delim-para-function)
+
+(defun scribe-delim-para-function (mark)
+  "Returns whether there is a paragraph delimiting Scribe command on the
+   current line.  Add or remove commands for this purpose with the command
+   \"Add Scribe Paragraph Delimiter\"."
+  (let ((next-char (next-character mark)))
+    (when (paragraph-delimiter-attribute-p next-char)
+      (if (eq (character-attribute :scribe-syntax next-char) :escape)
+	  (with-mark ((begin mark)
+		      (end mark))
+	    (mark-after begin)
+	    (if (scan-char end :scribe-syntax (or :space :newline :open-paren))
+		(gethash (nstring-downcase (region-to-string (region begin end)))
+			 *scribe-para-break-table*)
+		(editor-error "Unable to find Scribe command ending.")))
+	  t))))
+
+
+
+
+;;;; Bracket matching.
+
+(defun scribe-insert-paren (mark bracket-char)
+  (insert-character mark bracket-char)
+  (with-mark ((m mark))
+    (if (balance-paren m)
+	(when (value paren-pause-period)
+	  (unless (show-mark m (current-window) (value paren-pause-period))
+	    (clear-echo-area)
+	    (message "~A" (line-string (mark-line m)))))
+	(editor-error))))
+
+;;; BALANCE-PAREN moves the mark to the matching open paren character, or
+;;; returns nil.  The mark must be after the closing paren.
+;;;
+(defun balance-paren (mark)
+  (with-mark ((m mark))
+    (when (rev-scan-char m :scribe-syntax (or :open-paren :close-paren))
+      (mark-before m)
+      (let ((paren-count 1)
+	    (first-paren (next-character m)))
+	(loop
+	  (unless (rev-scan-char m :scribe-syntax (or :open-paren :close-paren))
+	    (return nil))
+	  (if (test-char (previous-character m) :scribe-syntax :open-paren)
+	      (setq paren-count (1- paren-count))
+	      (setq paren-count (1+ paren-count)))
+	  (when (< paren-count 0) (return nil))
+	  (when (= paren-count 0) 
+	    ;; OPPOSING-BRACKET calls VALUE (each time around the loop)
+	    (cond ((char= (opposing-bracket (previous-character m)) first-paren)
+		   (mark-before (move-mark mark m))
+		   (return t))
+		  (t (editor-error "Scribe paren mismatch."))))
+	  (mark-before m))))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/shell.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/shell.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/shell.lisp	(revision 13309)
@@ -0,0 +1,558 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Hemlock command level support for processes.
+;;;
+;;; Written by Blaine Burks.
+;;;
+
+(in-package :hemlock)
+
+
+(defun setup-process-buffer (buffer)
+  (let ((mark (copy-mark (buffer-point buffer) :right-inserting)))
+    (defhvar "Buffer Input Mark"
+      "The buffer input mark for this buffer."
+      :buffer buffer
+      :value mark)
+    (defhvar "Process Output Stream"
+      "The process structure for this buffer."
+      :buffer buffer
+      :value (make-hemlock-output-stream mark :full))
+    (defhvar "Interactive History"
+      "A ring of the regions input to an interactive mode (Eval or Typescript)."
+      :buffer buffer
+      :value (make-ring (value interactive-history-length)))
+    (defhvar "Interactive Pointer"
+      "Pointer into \"Interactive History\"."
+      :buffer buffer
+      :value 0)
+    (defhvar "Searching Interactive Pointer"
+      "Pointer into \"Interactive History\"."
+      :buffer buffer
+      :value 0)
+    (unless (buffer-modeline-field-p buffer :process-status)
+      (setf (buffer-modeline-fields buffer)
+	    (nconc (buffer-modeline-fields buffer)
+		   (list (modeline-field :process-status)))))))
+
+(defmode "Process" :major-p nil :setup-function #'setup-process-buffer)
+
+
+
+
+;;;; Shell-filter streams.
+
+;;; We use shell-filter-streams to capture text going from the shell process to
+;;; a Hemlock output stream.  They pass character and misc operations through
+;;; to the attached hemlock-output-stream.  The string output function scans
+;;; the string for ^A_____^B, denoting a change of directory.
+;;;
+;;; The following aliases in a .cshrc file are required for using filename
+;;; completion:
+;;;    alias cd 'cd \!* ; echo ""`pwd`"/"'
+;;;    alias popd 'popd \!* ; echo ""`pwd`"/"'
+;;;    alias pushd 'pushd \!* ; echo ""`pwd`"/"'
+;;;
+
+(defstruct (shell-filter-stream
+	    (:include sys:lisp-stream
+		      (:out #'shell-filter-out)
+		      (:sout #'shell-filter-string-out)
+		      (:misc #'shell-filter-output-misc))
+	    (:print-function print-shell-filter-stream)
+	    (:constructor 
+	     make-shell-filter-stream (buffer hemlock-stream)))
+  ;; The buffer where output will be going
+  buffer
+  ;; The Hemlock stream to which output will be directed
+  hemlock-stream)
+
+
+;;; PRINT-SHELL-FILTER-STREAM  -- Internal
+;;;
+;;; Function for printing a shell-filter-stream.
+;;;
+(defun print-shell-filter-stream (s stream d)
+  (declare (ignore d s))
+  (write-string "#<Shell filter stream>" stream))
+
+
+;;; SHELL-FILTER-OUT -- Internal
+;;;
+;;; This is the character-out handler for the shell-filter-stream.
+;;; It writes the character it is given to the underlying
+;;; hemlock-output-stream.
+;;;
+(defun shell-filter-out (stream character)
+  (write-char character (shell-filter-stream-hemlock-stream stream)))
+
+
+;;; SHELL-FILTER-OUTPUT-MISC -- Internal
+;;;
+;;; This will also simply pass the output request on the the
+;;; attached hemlock-output-stream.
+;;;
+(defun shell-filter-output-misc (stream operation &optional arg1 arg2)
+  (let ((hemlock-stream (shell-filter-stream-hemlock-stream stream)))
+    (funcall (hi::hemlock-output-stream-misc hemlock-stream)
+	     hemlock-stream operation arg1 arg2)))
+
+
+;;; CATCH-CD-STRING -- Internal
+;;;
+;;; Scans String for the sequence ^A...^B.  Returns as multiple values
+;;; the breaks in the string.  If the second start/end pair is nil, there
+;;; was no cd sequence.
+;;;
+(defun catch-cd-string (string start end)
+  (declare (simple-string string))
+  (let ((cd-start (position (code-char 1) string :start start :end end)))
+    (if cd-start
+	(let ((cd-end (position (code-char 2) string :start cd-start :end end)))
+	  (if cd-end
+	      (values start cd-start cd-end end)
+	      (values start end nil nil)))
+	(values start end nil nil))))
+
+;;; SHELL-FILTER-STRING-OUT -- Internal
+;;;
+;;; The string output function for shell-filter-stream's.
+;;; Any string containing a ^A...^B is caught and assumed to be
+;;; the path-name of the new current working directory.  This is
+;;; removed from the orginal string and the result is passed along
+;;; to the Hemlock stream.
+;;;
+(defun shell-filter-string-out (stream string start end)
+  (declare (simple-string string))
+  (let ((hemlock-stream (shell-filter-stream-hemlock-stream stream))
+	(buffer (shell-filter-stream-buffer stream)))
+
+    (multiple-value-bind (start1 end1 start2 end2)
+			 (catch-cd-string string start end)
+      (write-string string hemlock-stream :start start1 :end end1)
+      (when start2
+	(write-string string hemlock-stream :start (+ 2 start2) :end end2)
+	(let ((cd-string (subseq string (1+ end1) start2)))
+	  (setf (variable-value 'current-working-directory :buffer buffer)
+		(pathname cd-string)))))))
+
+
+;;; FILTER-TILDES -- Internal
+;;;
+;;; Since COMPLETE-FILE does not seem to deal with ~'s in the filename
+;;; this function expands them to a full path name.
+;;;
+(defun filter-tildes (name)
+  (declare (simple-string name))
+  (if (char= (schar name 0) #\~)
+      (concatenate 'simple-string
+		   (if (or (= (length name) 1)
+			   (char= (schar name 1) #\/))
+		       (cdr (assoc :home *environment-list*))
+		       "/usr/")
+		 (subseq name 1))
+      name))
+
+
+
+
+;;;; Support for handling input before the prompt in process buffers.
+
+(defun unwedge-process-buffer ()
+  (buffer-end (current-point))
+  (deliver-signal-to-process :SIGINT (value process))
+  (editor-error "Aborted."))
+
+(defhvar "Unwedge Interactive Input Fun"
+  "Function to call when input is confirmed, but the point is not past the
+   input mark."
+  :value #'unwedge-process-buffer
+  :mode "Process")
+
+(defhvar "Unwedge Interactive Input String"
+  "String to add to \"Point not past input mark.  \" explaining what will
+   happen if the the user chooses to be unwedged."
+  :value "Interrupt and throw to end of buffer?"
+  :mode "Process")
+
+
+
+
+;;;; Some Global Variables.
+
+(defhvar "Current Shell"
+  "The shell to which \"Select Shell\" goes."
+  :value nil)
+
+(defhvar "Ask about Old Shells"
+  "When set (the default), Hemlock prompts for an existing shell buffer in
+   preference to making a new one when there is no \"Current Shell\"."
+  :value t)
+  
+(defhvar "Kill Process Confirm"
+  "When set, Hemlock prompts for confirmation before killing a buffer's process."
+  :value t)
+
+(defhvar "Shell Utility"
+  "The \"Shell\" command uses this as the default command line."
+  :value "/bin/csh")
+
+(defhvar "Shell Utility Switches"
+  "This is a string containing the default command line arguments to the
+   utility in \"Shell Utility\".  This is a string since the utility is
+   typically \"/bin/csh\", and this string can contain I/O redirection and
+   other shell directives."
+  :value "")
+
+
+
+
+;;;; The Shell, New Shell, and Set Current Shell Commands.
+
+(defvar *shell-names* (make-string-table)
+  "A string-table of the string-name of all process buffers and corresponding
+   buffer structures.")
+
+(defcommand "Set Current Shell" (p)
+  "Sets the value of \"Current Shell\", which the \"Shell\" command uses."
+  "Sets the value of \"Current Shell\", which the \"Shell\" command uses."
+  (declare (ignore p))
+  (set-current-shell))
+
+;;; SET-CURRENT-SHELL -- Internal.
+;;;
+;;; This prompts for a known shell buffer to which it sets "Current Shell".
+;;; It signals an error if there are none.
+;;;
+(defun set-current-shell ()
+  (let ((old-buffer (value current-shell))
+	(first-old-shell (do-strings (var val *shell-names* nil)
+			   (declare (ignore val))
+			   (return var))))
+    (when (and (not old-buffer) (not first-old-shell))
+      (editor-error "Nothing to set current shell to."))
+    (let ((default-shell (if old-buffer
+			     (buffer-name old-buffer)
+			     first-old-shell)))
+      (multiple-value-bind
+	  (new-buffer-name new-buffer) 
+	  (prompt-for-keyword (list *shell-names*)
+			      :must-exist t
+			      :default default-shell
+			      :default-string default-shell
+			      :prompt "Existing Shell: "
+			      :help "Enter the name of an existing shell.")
+	(declare (ignore new-buffer-name))
+	(setf (value current-shell) new-buffer)))))
+
+(defcommand "Shell" (p)
+  "This spawns a shell in a buffer.  If there already is a \"Current Shell\",
+   this goes to that buffer.  If there is no \"Current Shell\", there are
+   shell buffers, and \"Ask about Old Shells\" is set, this prompts for one
+   of them, setting \"Current Shell\" to that shell.  Supplying an argument
+   forces the creation of a new shell buffer."
+  "This spawns a shell in a buffer.  If there already is a \"Current Shell\",
+   this goes to that buffer.  If there is no \"Current Shell\", there are
+   shell buffers, and \"Ask about Old Shells\" is set, this prompts for one
+   of them, setting \"Current Shell\" to that shell.  Supplying an argument
+   forces the creation of a new shell buffer."
+  (let ((shell (value current-shell))
+	(no-shells-p (do-strings (var val *shell-names* t)
+		       (declare (ignore var val))
+		       (return nil))))
+    (cond (p (make-new-shell nil no-shells-p))
+	  (shell (change-to-buffer shell))
+	  ((and (value ask-about-old-shells) (not no-shells-p))
+	   (set-current-shell)
+	   (change-to-buffer (value current-shell)))
+	  (t (make-new-shell nil)))))
+
+(defcommand "Shell Command Line in Buffer" (p)
+  "Prompts the user for a process and a buffer in which to run the process."
+  "Prompts the user for a process and a buffer in which to run the process."
+  (declare (ignore p))
+  (make-new-shell t))
+
+;;; MAKE-NEW-SHELL -- Internal.
+;;;
+;;; This makes new shells for us dealing with prompting for various things and
+;;; setting "Current Shell" according to user documentation.
+;;;
+(defun make-new-shell (prompt-for-command-p &optional (set-current-shell-p t)
+		       (command-line (get-command-line) clp))
+  (let* ((command (or (and clp command-line)
+		      (if prompt-for-command-p
+			  (prompt-for-string
+			   :default command-line :trim t
+			   :prompt "Command to execute: "
+			   :help "Shell command line to execute.")
+			  command-line)))
+	 (buffer-name (if prompt-for-command-p
+			  (prompt-for-string
+			   :default
+			   (concatenate 'simple-string command " process")
+			   :trim t
+			   :prompt `("Buffer in which to execute ~A? "
+				     ,command)
+			   :help "Where output from this process will appear.")
+			  (new-shell-name)))
+	 (temp (make-buffer
+		  buffer-name
+		  :modes '("Fundamental" "Process")
+		  :delete-hook
+		  (list #'(lambda (buffer)
+			    (when (eq (value current-shell) buffer)
+			      (setf (value current-shell) nil))
+			    (delete-string (buffer-name buffer) *shell-names*)
+			    (kill-process (variable-value 'process
+							  :buffer buffer))))))
+	 (buffer (or temp (getstring buffer-name *buffer-names*)))
+	 (stream (variable-value 'process-output-stream :buffer buffer))
+	 (output-stream
+	  ;; If we re-used an old shell buffer, this isn't necessary.
+	  (if (hemlock-output-stream-p stream)
+	      (setf (variable-value 'process-output-stream :buffer buffer)
+		    (make-shell-filter-stream buffer stream))
+	      stream)))
+    (buffer-end (buffer-point buffer))
+    (defhvar "Process"
+      "The process for Shell and Process buffers."
+      :buffer buffer
+      :value (ext::run-program "/bin/sh" (list "-c" command)
+			       :wait nil
+			       :pty output-stream
+			       :env (frob-environment-list
+				     (car (buffer-windows buffer)))
+			       :status-hook #'(lambda (process)
+						(declare (ignore process))
+						(update-process-buffer buffer))
+			       :input t :output t))
+    (defhvar "Current Working Directory"
+      "The pathname of the current working directory for this buffer."
+      :buffer buffer
+      :value (default-directory))
+    (setf (getstring buffer-name *shell-names*) buffer)
+    (update-process-buffer buffer)
+    (when (and (not (value current-shell)) set-current-shell-p)
+      (setf (value current-shell) buffer))
+    (change-to-buffer buffer)))
+
+;;; GET-COMMAND-LINE -- Internal.
+;;;
+;;; This just conses up a string to feed to the shell.
+;;;
+(defun get-command-line ()
+  (concatenate 'simple-string (value shell-utility) " "
+	       (value shell-utility-switches)))
+
+;;; FROB-ENVIRONMENT-LIST -- Internal.
+;;;
+;;; This sets some environment variables so the shell will be in the proper
+;;; state when it comes up.
+;;;
+(defun frob-environment-list (window)
+  (list* (cons :termcap  (concatenate 'simple-string
+				      "emacs:co#"
+				      (if window
+					  (lisp::quick-integer-to-string
+					   (window-width window))
+					  "")
+				      ":tc=unkown:"))
+	 (cons :emacs "t") (cons :term "emacs")
+	 (remove-if #'(lambda (keyword)
+			(member keyword '(:termcap :emacs :term)
+				:test #'(lambda (cons keyword)
+					  (eql (car cons) keyword))))
+		    ext:*environment-list*)))
+
+;;; NEW-SHELL-NAME -- Internal.
+;;;
+;;; This returns a unique buffer name for a shell by incrementing the value of
+;;; *process-number* until "Process <*process-number*> is not already the name
+;;; of a buffer.  Perhaps this is being overly cautious, but I've seen some
+;;; really stupid users.
+;;;
+(defvar *process-number* 0)
+;;;
+(defun new-shell-name ()
+  (loop
+    (let ((buffer-name (format nil "Shell ~D" (incf *process-number*))))
+      (unless (getstring buffer-name *buffer-names*) (return buffer-name)))))
+
+
+
+;;;; Modeline support.
+
+(defun modeline-process-status (buffer window)
+  (declare (ignore window))
+  (when (hemlock-bound-p 'process :buffer buffer)
+    (let ((process (variable-value 'process :buffer buffer)))
+      (ecase (ext:process-status process)
+	(:running "running")
+	(:stopped "stopped")
+	(:signaled "killed by signal ~D" (unix:unix-signal-name
+					  (ext:process-exit-code process)))
+	(:exited (format nil "exited with status ~D"
+			 (ext:process-exit-code process)))))))
+			 
+
+(make-modeline-field :name :process-status
+		     :function #'modeline-process-status)
+
+(defun update-process-buffer (buffer)
+  (when (buffer-modeline-field-p buffer :process-status)
+    (dolist (window (buffer-windows buffer))
+      (update-modeline-field buffer window :process-status)))
+  (let ((process (variable-value 'process :buffer buffer)))
+    (unless (ext:process-alive-p process)
+      (ext:process-close process)
+      (when (eq (value current-shell) buffer)
+	(setf (value current-shell) nil)))))
+
+
+
+;;;; Supporting Commands.
+
+(defcommand "Confirm Process Input" (p)
+  "Evaluate Process Mode input between the point and last prompt."
+  "Evaluate Process Mode input between the point and last prompt."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))
+  (let* ((process (value process))
+	 (stream (ext:process-pty process)))
+    (case (ext:process-status process)
+      (:running)
+      (:stopped (editor-error "The process has been stopped."))
+      (t (editor-error "The process is dead.")))
+    (let ((input-region (get-interactive-input)))
+      (write-line (region-to-string input-region) stream)
+      (force-output (ext:process-pty process))
+      (insert-character (current-point) #\newline)
+      ;; Move "Buffer Input Mark" to end of buffer.
+      (move-mark (region-start input-region) (region-end input-region)))))
+
+(defcommand "Shell Complete Filename" (p)
+  "Attempts to complete the filename immediately preceding the point.
+   It will beep if the result of completion is not unique."
+  "Attempts to complete the filename immediately preceding the point.
+   It will beep if the result of completion is not unique."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'current-working-directory)
+    (editor-error "Shell filename completion only works in shells."))
+  (let ((point (current-point)))
+    (with-mark ((start point))
+      (pre-command-parse-check start)
+      (unless (form-offset start -1) (editor-error "Can't grab filename."))
+      (when (member (next-character start) '(#\" #\' #\< #\>))
+	(mark-after start))
+      (let* ((name-region (region start point))
+	     (fragment (filter-tildes (region-to-string name-region)))
+	     (dir (default-directory))
+	     (shell-dir (value current-working-directory)))
+	(multiple-value-bind (filename unique)
+			     (unwind-protect
+				 (progn
+				   (setf (default-directory) shell-dir)
+				   (complete-file fragment :defaults shell-dir))
+			       (setf (default-directory) dir))
+	  (cond (filename
+		 (delete-region name-region)
+		 (insert-string point (namestring filename))
+		 (when (not unique)
+		   (editor-error)))
+		(t (editor-error "No such file exists."))))))))
+
+(defcommand "Kill Main Process" (p)
+  "Kills the process in the current buffer."
+  "Kills the process in the current buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))
+  (when (or (not (value kill-process-confirm))
+	    (prompt-for-y-or-n :default nil
+			       :prompt "Really blow away shell? "
+			       :default nil
+			       :default-string "no"))
+    (kill-process (value process))))
+
+(defcommand "Stop Main Process" (p)
+  "Stops the process in the current buffer.  With an argument use :SIGSTOP
+   instead of :SIGTSTP."
+  "Stops the process in the current buffer.  With an argument use :SIGSTOP
+  instead of :SIGTSTP."
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))
+  (deliver-signal-to-process (if p :SIGSTOP :SIGTSTP) (value process)))
+
+(defcommand "Continue Main Process" (p)
+  "Continues the process in the current buffer."
+  "Continues the process in the current buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))
+  (deliver-signal-to-process :SIGCONT (value process)))
+  
+(defun kill-process (process)
+  "Self-explanatory."
+  (deliver-signal-to-process :SIGKILL process))
+
+(defun deliver-signal-to-process (signal process)
+  "Delivers a signal to a process."
+  (ext:process-kill process signal :process-group))
+
+(defcommand "Send EOF to Process" (p)
+  "Sends a Ctrl-D to the process in the current buffer."
+  "Sends a Ctrl-D to the process in the current buffer."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))
+  (let ((stream (ext:process-pty (value process))))
+    (write-char (code-char 4) stream)
+    (force-output stream)))
+
+(defcommand "Interrupt Buffer Subprocess" (p)
+  "Stop the subprocess currently executing in this shell."
+  "Stop the subprocess currently executing in this shell."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))
+  (buffer-end (current-point))
+  (buffer-end (value buffer-input-mark))
+  (deliver-signal-to-subprocess :SIGINT (value process)))
+
+(defcommand "Kill Buffer Subprocess" (p)
+  "Kill the subprocess currently executing in this shell."
+  "Kill the subprocess currently executing in this shell."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))  
+  (deliver-signal-to-subprocess :SIGKILL (value process)))
+
+(defcommand "Quit Buffer Subprocess" (p)
+  "Quit the subprocess currently executing int his shell."
+  "Quit the subprocess currently executing int his shell."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))
+  (deliver-signal-to-subprocess :SIGQUIT (value process)))
+
+(defcommand "Stop Buffer Subprocess" (p)
+  "Stop the subprocess currently executing in this shell."
+  "Stop the subprocess currently executing in this shell."
+  (unless (hemlock-bound-p 'process :buffer (current-buffer))
+    (editor-error "Not in a process buffer."))  
+  (deliver-signal-to-subprocess (if p :SIGSTOP :SIGTSTP) (value process)))
+
+(defun deliver-signal-to-subprocess (signal process)
+  "Delivers a signal to a subprocess of a shell."
+  (ext:process-kill process signal :pty-process-group))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-aug.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-aug.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-aug.lisp	(revision 13309)
@@ -0,0 +1,237 @@
+;;; -*- Log: hemlock.log; Package: Spell -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;    Designed by Bill Chiles and Rob Maclachlan
+;;;
+;;; This file contains the code to grow the spelling dictionary in system
+;;; space by reading a text file of entries or adding one at a time.  This
+;;; code relies on implementation dependent code found in Spell-RT.Lisp.
+
+
+(in-package "SPELL")
+
+
+
+;;;; Converting Flags to Masks
+
+(defconstant flag-names-to-masks
+  `((#\V . ,V-mask) (#\N . ,N-mask) (#\X . ,X-mask)
+    (#\H . ,H-mask) (#\Y . ,Y-mask) (#\G . ,G-mask)
+    (#\J . ,J-mask) (#\D . ,D-mask) (#\T . ,T-mask)
+    (#\R . ,R-mask) (#\Z . ,Z-mask) (#\S . ,S-mask)
+    (#\P . ,P-mask) (#\M . ,M-mask)))
+
+(defvar *flag-masks*
+  (make-array 128 :element-type '(unsigned-byte 16) :initial-element 0)
+  "This holds the masks for character flags, which is used when reading
+   a text file of dictionary words.  Illegal character flags hold zero.")
+
+(eval-when (:compile-toplevel :execute)
+(defmacro flag-mask (char)
+  `(aref *flag-masks* (char-code ,char)))
+) ;eval-when
+
+(dolist (e flag-names-to-masks)
+  (let ((char (car e))
+	(mask (cdr e)))
+    (setf (flag-mask char) mask)
+    (setf (flag-mask (char-downcase char)) mask)))
+
+
+
+
+;;;; String and Hashing Macros
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro string-table-replace (src-string dst-start length)
+  `(sap-replace *string-table* ,src-string 0 ,dst-start (+ ,dst-start ,length)))
+
+;;; HASH-ENTRY is used in SPELL-ADD-ENTRY to find a dictionary location for
+;;; adding a new entry.  If a location contains a zero, then it has never been
+;;; used, and no entries have ever been "hashed past" it.  If a location
+;;; contains SPELL-DELETED-ENTRY, then it once contained an entry that has
+;;; since been deleted.
+;;;
+(defmacro hash-entry (entry entry-len)
+  (let ((loop-loc (gensym)) (loc-contents (gensym))
+	(hash (gensym)) (loc (gensym)))
+    `(let* ((,hash (string-hash ,entry ,entry-len))
+	    (,loc (rem ,hash (the fixnum *dictionary-size*)))
+	    (,loc-contents (dictionary-ref ,loc)))
+       (declare (fixnum ,loc ,loc-contents))
+       (if (or (zerop ,loc-contents) (= ,loc-contents spell-deleted-entry))
+	   ,loc
+	   (hash2-loop (,loop-loc ,loc-contents) ,loc ,hash
+	     ,loop-loc nil t)))))
+
+) ;eval-when
+
+
+
+
+;;;; Top Level Stuff
+
+(defun spell-read-dictionary (filename)
+  "Add entries to dictionary from lines in the file filename."
+  (with-open-file (s filename :direction :input)
+    (loop (multiple-value-bind (entry eofp) (read-line s nil nil)
+	    (declare (type (or simple-string null) entry))
+	    (unless entry (return))
+	    (spell-add-entry entry)
+	    (if eofp (return))))))
+
+
+;;; This is used to break up an 18 bit string table index into two parts
+;;; for storage in a word descriptor unit.  See the documentation at the
+;;; top of Spell-Correct.Lisp.
+;;;
+(defconstant whole-index-low-byte (byte 16 0))
+
+(defun spell-add-entry (line &optional
+			     (word-end (or (position #\/ line :test #'char=)
+					   (length line))))
+  "Line is of the form \"entry/flag1/flag2\" or \"entry\".  It is parsed and
+   added to the spelling dictionary.  Line is desstructively modified."
+  (declare (simple-string line) (fixnum word-end))
+  (nstring-upcase line :end word-end)
+  (when (> word-end max-entry-length)
+    (return-from spell-add-entry nil))
+  (let ((entry (lookup-entry line word-end)))
+    (when entry
+      (add-flags (+ entry 2) line word-end)
+      (return-from spell-add-entry nil)))
+  (let* ((hash-loc (hash-entry line word-end))
+	 (string-ptr *string-table-size*)
+	 (desc-ptr *descriptors-size*)
+	 (desc-ptr+1 (1+ desc-ptr))
+	 (desc-ptr+2 (1+ desc-ptr+1)))
+    (declare (fixnum string-ptr))
+    (when (not hash-loc) (error "Dictionary Overflow!"))
+    (when (> 3 *free-descriptor-elements*) (grow-descriptors))
+    (when (> word-end *free-string-table-bytes*) (grow-string-table))
+    (decf *free-descriptor-elements* 3)
+    (incf *descriptors-size* 3)
+    (decf *free-string-table-bytes* word-end)
+    (incf *string-table-size* word-end)
+    (setf (dictionary-ref hash-loc) desc-ptr)
+    (setf (descriptor-ref desc-ptr)
+	  (dpb (the fixnum (ldb new-hash-byte (string-hash line word-end)))
+	       stored-hash-byte
+	       word-end))
+    (setf (descriptor-ref desc-ptr+1)
+	  (ldb whole-index-low-byte string-ptr))
+    (setf (descriptor-ref desc-ptr+2)
+	  (dpb (the fixnum (ldb whole-index-high-byte string-ptr))
+	       stored-index-high-byte
+	       0))
+    (add-flags desc-ptr+2 line word-end)
+    (string-table-replace line string-ptr word-end))
+  t)
+
+(defun add-flags (loc line word-end)
+  (declare (simple-string line) (fixnum word-end))
+  (do ((flag (1+ word-end) (+ 2 flag))
+       (line-end (length line)))
+      ((>= flag line-end))
+    (declare (fixnum flag line-end))
+    (let ((flag-mask (flag-mask (schar line flag))))
+      (declare (fixnum flag-mask))
+      (unless (zerop flag-mask)
+	(setf (descriptor-ref loc)
+	      (logior flag-mask (descriptor-ref loc)))))))
+
+;;; SPELL-REMOVE-ENTRY destructively uppercases entry in removing it from
+;;; the dictionary.  First entry is looked up, and if it is found due to a
+;;; flag, the flag is cleared in the descriptor table.  If entry is a root
+;;; word in the dictionary (that is, looked up without the use of a flag),
+;;; then the root and all its derivitives are deleted by setting its
+;;; dictionary location to spell-deleted-entry.
+;;; 
+(defun spell-remove-entry (entry)
+  "Removes entry from the dictionary, so it will be an unknown word.  Entry
+   is a simple string and is destructively modified.  If entry is a root
+   word, then all words derived with entry and its flags will also be deleted."
+  (declare (simple-string entry))
+  (nstring-upcase entry)
+  (let ((entry-len (length entry)))
+    (declare (fixnum entry-len))
+    (when (<= 2 entry-len max-entry-length)
+      (multiple-value-bind (index flagp)
+			   (spell-try-word entry entry-len)
+	(when index
+	  (if flagp
+	      (setf (descriptor-ref (+ 2 index))
+		    (logandc2 (descriptor-ref (+ 2 index)) flagp))
+	      (let* ((hash (string-hash entry entry-len))
+		     (hash-and-len (dpb (the fixnum (ldb new-hash-byte hash))
+					stored-hash-byte
+					(the fixnum entry-len)))
+		     (loc (rem hash (the fixnum *dictionary-size*)))
+		     (loc-contents (dictionary-ref loc)))
+		(declare (fixnum hash hash-and-len loc))
+		(cond ((zerop loc-contents) nil)
+		      ((found-entry-p loc-contents entry entry-len hash-and-len)
+		       (setf (dictionary-ref loc) spell-deleted-entry))
+		      (t
+		       (hash2-loop (loop-loc loc-contents) loc hash
+				   nil
+				   (when (found-entry-p loc-contents entry
+							entry-len hash-and-len)
+				     (setf (dictionary-ref loop-loc)
+					   spell-deleted-entry)
+				     (return spell-deleted-entry))))))))))))
+
+(defun spell-root-flags (index)
+  "Return the flags associated with the root word corresponding to a
+   dictionary entry at index."
+  (let ((desc-word (descriptor-ref (+ 2 index)))
+	(result ()))
+    (declare (fixnum desc-word))
+    (dolist (ele flag-names-to-masks result)
+      (unless (zerop (logand (the fixnum (cdr ele)) desc-word))
+	(push (car ele) result)))))
+
+
+
+
+;;;; Growing Dictionary Structures
+
+;;; GROW-DESCRIPTORS grows the descriptors vector by 10%.
+;;;
+(defun grow-descriptors ()
+  (let* ((old-size (+ (the fixnum *descriptors-size*)
+		      (the fixnum *free-descriptor-elements*)))
+	 (new-size (truncate (* old-size 1.1)))
+	 (new-bytes (* new-size 2))
+	 (new-sap (allocate-bytes new-bytes)))
+    (declare (fixnum new-size old-size))
+    (sap-replace new-sap *descriptors* 0 0
+		 (* 2 (the fixnum *descriptors-size*)))
+    (deallocate-bytes (system-address *descriptors*) (* 2 old-size))
+    (setf *free-descriptor-elements*
+	  (- new-size (the fixnum *descriptors-size*)))
+    (setf *descriptors* new-sap)))
+
+;;; GROW-STRING-TABLE grows the string table by 10%.
+;;;
+(defun grow-string-table ()
+  (let* ((old-size (+ (the fixnum *string-table-size*)
+		      (the fixnum *free-string-table-bytes*)))
+	 (new-size (truncate (* old-size 1.1)))
+	 (new-sap (allocate-bytes new-size)))
+    (declare (fixnum new-size old-size))
+    (sap-replace new-sap *string-table* 0 0 *string-table-size*)
+    (setf *free-string-table-bytes*
+	  (- new-size (the fixnum *string-table-size*)))
+    (deallocate-bytes (system-address *string-table*) old-size)
+    (setf *string-table* new-sap)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-corr.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-corr.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-corr.lisp	(revision 13309)
@@ -0,0 +1,816 @@
+;;; -*- Log: hemlock.log; Package: Spell -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;    Designed by Bill Chiles and Rob Maclachlan
+;;;
+
+;;;      This is the file that deals with checking and correcting words
+;;; using a dictionary read in from a binary file.  It has been written
+;;; from the basic ideas used in Ispell (on DEC-20's) which originated as
+;;; Spell on the ITS machines at MIT.  There are flags which have proper
+;;; uses defined for them that indicate permissible suffixes to entries.
+;;; This allows for about three times as many known words than are actually
+;;; stored.  When checking the spelling of a word, first it is looked up;
+;;; if this fails, then possible roots are looked up, and if any has the
+;;; appropriate suffix flag, then the word is considered to be correctly
+;;; spelled.  For an unknown word, the following rules define "close" words
+;;; which are possible corrections:
+;;;    1] two adjacent letters are transposed to form a correct spelling;
+;;;    2] one letter is changed to form a correct spelling;
+;;;    3] one letter is added to form a correct spelling; and/or
+;;;    4] one letter is removed to form a correct spelling. 
+;;; There are two restrictions on the length of a word in regards to its
+;;; worthiness of recognition: it must be at least more than two letters
+;;; long, and if it has a suffix, then it must be at least four letters
+;;; long.  More will be said about this when the flags are discussed.
+;;;      This is implemented in as tense a fashion as possible, and it uses
+;;; implementation dependent code from Spell-RT.Lisp to accomplish this.
+;;; In general the file I/O and structure accesses encompass the system
+;;; dependencies.
+
+;;;      This next section will discuss the storage of the dictionary
+;;; information.  There are three data structures that "are" the
+;;; dictionary: a hash table, descriptors table, and a string table.  The
+;;; hash table is a vector of type '(unsigned-byte 16), whose elements
+;;; point into the descriptors table.  This is a cyclic hash table to
+;;; facilitate dumping it to a file.  The descriptors table (also of type
+;;; '(unsigned-byte 16)) dedicates three elements to each entry in the
+;;; dictionary.  Each group of three elements has the following organization
+;;; imposed on them:
+;;;    ----------------------------------------------
+;;;    |  15..5  hash code  |      4..0 length      |
+;;;    ----------------------------------------------
+;;;    |           15..0 character index            |
+;;;    ----------------------------------------------
+;;;    |  15..14 character index  |  13..0 flags    |
+;;;    ----------------------------------------------
+;;; "Length" is the number of characters in the entry; "hash code" is some
+;;; eleven bits from the hash code to allow for quicker lookup, "flags"
+;;; indicate possible suffixes for the basic entry, and "character index"
+;;; is the index of the start of the entry in the string table.
+;;;      This was originally adopted due to the Perq's word size (can you guess?
+;;; 16 bits, that's right).  Note the constraint that is placed on the number
+;;; of the entries, 21845, because the hash table could not point to more
+;;; descriptor units (16 bits of pointer divided by three).  Since a value of
+;;; zero as a hash table element indicates an empty location, the zeroth element
+;;; of the descriptors table must be unused (it cannot be pointed to).
+
+
+;;;      The following is a short discussion with examples of the correct
+;;; use of the suffix flags.  Let # and @ be symbols that can stand for any
+;;; single letter.  Upper case letters are constants.  "..." stands for any
+;;; string of zero or more letters,  but note that no word may exist in the
+;;; dictionary which is not at least 2 letters long, so, for example, FLY
+;;; may not be produced by placing the "Y" flag on "F".  Also, no flag is
+;;; effective unless the word that it creates is at least 4 letters long,
+;;; so, for example, WED may not be produced by placing the "D" flag on
+;;; "WE".  These flags and examples are from the Ispell documentation with
+;;; only slight modifications.  Here are the correct uses of the flags:
+;;; 
+;;; "V" flag:
+;;;         ...E => ...IVE  as in  create => creative
+;;;         if # .ne. E, then  ...# => ...#IVE  as in  prevent => preventive
+;;; 
+;;; "N" flag:
+;;;         ...E => ...ION  as in create => creation
+;;;         ...Y => ...ICATION  as in  multiply => multiplication
+;;;         if # .ne. E or Y, then  ...# => ...#EN  as in  fall => fallen
+;;; 
+;;; "X" flag:
+;;;         ...E => ...IONS  as in  create => creations
+;;;         ...Y => ...ICATIONS  as in  multiply => multiplications
+;;;         if # .ne. E or Y, ...# => ...#ENS  as in  weak => weakens
+;;; 
+;;; "H" flag:
+;;;         ...Y => ...IETH  as in  twenty => twentieth
+;;;         if # .ne. Y, then  ...# => ...#TH  as in  hundred => hundredth
+;;; 
+;;; "Y" FLAG:
+;;;         ... => ...LY  as in  quick => quickly
+;;; 
+;;; "G" FLAG:
+;;;         ...E => ...ING  as in  file => filing
+;;;         if # .ne. E, then  ...# => ...#ING  as in  cross => crossing
+;;; 
+;;; "J" FLAG"
+;;;         ...E => ...INGS  as in  file => filings
+;;;         if # .ne. E, then  ...# => ...#INGS  as in  cross => crossings
+;;; 
+;;; "D" FLAG:
+;;;         ...E => ...ED  as in  create => created
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IED  as in  imply => implied
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#ED  as in  convey => conveyed
+;;;         if # .ne. E or Y, then  ...# => ...#ED  as in  cross => crossed
+;;; 
+;;; "T" FLAG:
+;;;         ...E => ...EST  as in  late => latest
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IEST  as in  dirty => dirtiest
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#EST  as in  gray => grayest
+;;;         if # .ne. E or Y, then  ...# => ...#EST  as in  small => smallest
+;;; 
+;;; "R" FLAG:
+;;;         ...E => ...ER  as in  skate => skater
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IER  as in  multiply => multiplier
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then ...@# => ...@#ER  as in  convey => conveyer
+;;;         if # .ne. E or Y, then  ...# => ...#ER  as in  build => builder
+;;; 
+
+;;; "Z FLAG:
+;;;         ...E => ...ERS  as in  skate => skaters
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IERS  as in  multiply => multipliers
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#ERS  as in  slay => slayers
+;;;         if # .ne. E or Y, then  ...@# => ...@#ERS  as in  build => builders
+;;; 
+;;; "S" FLAG:
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IES  as in  imply => implies
+;;;         if # .eq. S, X, Z, or H,
+;;;            then  ...# => ...#ES  as in  fix => fixes
+;;;         if # .ne. S, X, Z, H, or Y,
+;;;            then  ...# => ...#S  as in  bat => bats
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#S  as in  convey => conveys
+;;; 
+;;; "P" FLAG:
+;;;         if # .ne. Y, or @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#NESS  as in  late => lateness and
+;;;                                             gray => grayness
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@INESS  as in  cloudy => cloudiness
+;;; 
+;;; "M" FLAG:
+;;;         ... => ...'S  as in DOG => DOG'S
+
+(in-package "SPELL")
+
+
+
+;;;; Some Constants
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+
+(defconstant spell-deleted-entry #xFFFF)
+
+;;; The next number (using 6 bits) is 63, and that's pretty silly because
+;;; "supercalafragalistic" is less than 31 characters long.
+;;;
+(defconstant max-entry-length 31
+  "This the maximum number of characters an entry may have.")
+
+;;; These are the flags (described above), and an entry is allowed a
+;;; certain suffix if the appropriate bit is on in the third element of
+;;; its descriptor unit (described above).
+;;;
+(defconstant V-mask (ash 1 13))
+(defconstant N-mask (ash 1 12))
+(defconstant X-mask (ash 1 11))
+(defconstant H-mask (ash 1 10))
+(defconstant Y-mask (ash 1 9))
+(defconstant G-mask (ash 1 8))
+(defconstant J-mask (ash 1 7))
+(defconstant D-mask (ash 1 6))
+(defconstant T-mask (ash 1 5))
+(defconstant R-mask (ash 1 4))
+(defconstant Z-mask (ash 1 3))
+(defconstant S-mask (ash 1 2))
+(defconstant P-mask (ash 1 1))
+(defconstant M-mask 1)
+
+
+;;; These are the eleven bits of a computed hash that are stored as part of
+;;; an entries descriptor unit.  The shifting constant is how much the
+;;; eleven bits need to be shifted to the right, so they take up the upper
+;;; eleven bits of one 16-bit element in a descriptor unit.
+;;;
+(defconstant new-hash-byte (byte 11 13))
+(defconstant stored-hash-byte (byte 11 5))
+
+
+;;; The next two constants are used to extract information from an entry's
+;;; descriptor unit.  The first is the two most significant bits of 18
+;;; bits that hold an index into the string table where the entry is
+;;; located.  If this is confusing, regard the diagram of the descriptor
+;;; units above.
+;;;
+(defconstant whole-index-high-byte (byte 2 16))
+(defconstant stored-index-high-byte (byte 2 14))
+(defconstant stored-length-byte (byte 5 0))
+
+
+); eval-when (:compile-toplevel :execute :load-toplevel)
+
+
+
+;;;; Some Specials and Accesses
+
+;;; *spell-aeiou* will have bits on that represent the capital letters
+;;; A, E, I, O, and U to be used to determine if some word roots are legal
+;;; for looking up.
+;;;
+(defvar *aeiou*
+  (make-array 128 :element-type 'bit :initial-element 0))
+
+(setf (aref *aeiou* (char-code #\A)) 1)
+(setf (aref *aeiou* (char-code #\E)) 1)
+(setf (aref *aeiou* (char-code #\I)) 1)
+(setf (aref *aeiou* (char-code #\O)) 1)
+(setf (aref *aeiou* (char-code #\U)) 1)
+
+
+;;; *sxzh* will have bits on that represent the capital letters
+;;; S, X, Z, and H to be used to determine if some word roots are legal for
+;;; looking up.
+;;;
+(defvar *sxzh*
+  (make-array 128 :element-type 'bit :initial-element 0))
+
+(setf (aref *sxzh* (char-code #\S)) 1)
+(setf (aref *sxzh* (char-code #\X)) 1)
+(setf (aref *sxzh* (char-code #\Z)) 1)
+(setf (aref *sxzh* (char-code #\H)) 1)
+
+
+;;; SET-MEMBER-P will be used with *aeiou* and *sxzh* to determine if a
+;;; character is in the specified set.
+;;;
+(eval-when (:compile-toplevel :execute)
+(defmacro set-member-p (char set)
+  `(not (zerop (the fixnum (aref (the simple-bit-vector ,set)
+				 (char-code ,char))))))
+) ;eval-when
+
+
+(defvar *dictionary*)
+(defvar *dictionary-size*)
+(defvar *descriptors*)
+(defvar *descriptors-size*)
+(defvar *string-table*)
+(defvar *string-table-size*)
+
+
+(eval-when (:compile-toplevel :execute)
+
+;;; DICTIONARY-REF and DESCRIPTOR-REF are references to implementation
+;;; dependent structures.  *dictionary* and *descriptors* are "system
+;;; area pointers" as a result of the way the binary file is opened for
+;;; fast access.
+;;;
+(defmacro dictionary-ref (idx)
+  `(sapref *dictionary* ,idx))
+
+(defmacro descriptor-ref (idx)
+  `(sapref *descriptors* ,idx))
+
+
+;;; DESCRIPTOR-STRING-START access an entry's (indicated by idx)
+;;; descriptor unit (described at the beginning of the file) and returns
+;;; the start index of the entry in the string table.  The second of three
+;;; words in the descriptor holds the 16 least significant bits of 18, and
+;;; the top two bits of the third word are the 2 most significant bits.
+;;; These 18 bits are the index into the string table.
+;;;
+(defmacro descriptor-string-start (idx)
+  `(dpb (the fixnum (ldb stored-index-high-byte
+			 (the fixnum (descriptor-ref (+ 2 ,idx)))))
+	whole-index-high-byte
+	(the fixnum (descriptor-ref (1+ ,idx)))))
+
+) ;eval-when
+
+
+
+
+;;;; Top level Checking/Correcting
+
+;;; CORRECT-SPELLING can be called from top level to check/correct a words
+;;; spelling.  It is not used for any other purpose.
+;;; 
+(defun correct-spelling (word)
+  "Check/correct the spelling of word.  Output is done to *standard-output*."
+  (setf word (coerce word 'simple-string))
+  (let ((word (string-upcase (the simple-string word)))
+	(word-len (length (the simple-string word))))
+    (declare (simple-string word) (fixnum word-len))
+    (maybe-read-spell-dictionary)
+    (when (= word-len 1)
+      (error "Single character words are not in the dictionary."))
+    (when (> word-len max-entry-length)
+      (error "~A is too long for the dictionary." word))
+    (multiple-value-bind (idx used-flag-p)
+			 (spell-try-word word word-len)
+      (if idx
+	  (format t "Found it~:[~; because of ~A~]." used-flag-p
+		  (spell-root-word idx))
+	  (let ((close-words (spell-collect-close-words word)))
+	    (if close-words
+		(format *standard-output*
+			"The possible correct spelling~[~; is~:;s are~]:~
+			~:*~[~; ~{~A~}~;~{ ~A~^ and~}~:;~
+			~{~#[~; and~] ~A~^,~}~]."
+			(length close-words)
+			close-words)
+		(format *standard-output* "Word not found.")))))))
+
+
+(defvar *dictionary-read-p* nil)
+
+;;; MAYBE-READ-SPELL-DICTIONARY  --  Public
+;;;
+(defun maybe-read-spell-dictionary ()
+  "Read the spelling dictionary if it has not be read already."
+  (unless *dictionary-read-p* (read-dictionary)))
+
+
+(defun spell-root-word (index)
+  "Return the root word corresponding to a dictionary entry at index."
+  (let* ((start (descriptor-string-start index))
+	 (len (the fixnum (ldb stored-length-byte
+			       (the fixnum (descriptor-ref index)))))
+	 (result (make-string len)))
+    (declare (fixnum start len)
+	     (simple-string result))
+    (sap-replace result (the system-area-pointer *string-table*)
+		 start 0 len)
+    result))
+
+
+(eval-when (:compile-toplevel :execute)
+(defmacro check-closeness (word word-len closeness-list)
+  `(if (spell-try-word ,word ,word-len)
+       (pushnew (subseq ,word 0 ,word-len) ,closeness-list :test #'string=)))
+) ;eval-when
+
+(defconstant spell-alphabet
+  (list #\A #\B #\C #\D #\E #\F #\G #\H
+	#\I #\J #\K #\L #\M #\N #\O #\P
+	#\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z))
+
+;;; SPELL-COLLECT-CLOSE-WORDS Returns a list of all "close" correctly spelled
+;;; words.  The definition of "close" is at the beginning of the file, and
+;;; there are four sections to this function which collect each of the four
+;;; different kinds of close words.
+;;; 
+(defun spell-collect-close-words (word)
+  "Returns a list of all \"close\" correctly spelled words.  This has the
+   same contraints as SPELL-TRY-WORD, which you have probably already called
+   if you are calling this."
+  (declare (simple-string word))
+  (let* ((word-len (length word))
+	 (word-len--1 (1- word-len))
+	 (word-len-+1 (1+ word-len))
+	 (result ())
+	 (correcting-buffer (make-string max-entry-length)))
+    (declare (simple-string correcting-buffer)
+	     (fixnum word-len word-len--1 word-len-+1))
+    (replace correcting-buffer word :end1 word-len :end2 word-len)
+
+    ;; Misspelled because one letter is different.
+    (dotimes (i word-len)
+      (do ((save-char (schar correcting-buffer i))
+	   (alphabet spell-alphabet (cdr alphabet)))
+	  ((null alphabet)
+	   (setf (schar correcting-buffer i) save-char))
+	(setf (schar correcting-buffer i) (car alphabet))
+	(check-closeness correcting-buffer word-len result)))
+
+    ;; Misspelled because two adjacent letters are transposed.
+    (dotimes (i word-len--1)
+      (rotatef (schar correcting-buffer i) (schar correcting-buffer (1+ i)))
+      (check-closeness correcting-buffer word-len result)
+      (rotatef (schar correcting-buffer i) (schar correcting-buffer (1+ i))))
+
+    ;; Misspelled because of extraneous letter.
+    (replace correcting-buffer word
+	     :start2 1 :end1 word-len--1 :end2 word-len)
+    (check-closeness correcting-buffer word-len--1 result)
+    (dotimes (i word-len--1)
+      (setf (schar correcting-buffer i) (schar word i))
+      (replace correcting-buffer word
+	       :start1 (1+ i) :start2 (+ i 2) :end1 word-len--1 :end2 word-len)
+      (check-closeness correcting-buffer word-len--1 result))
+
+    ;; Misspelled because a letter is missing.
+    (replace correcting-buffer word
+	     :start1 1 :end1 word-len-+1 :end2 word-len)
+    (dotimes (i word-len-+1)
+      (do ((alphabet spell-alphabet (cdr alphabet)))
+	  ((null alphabet)
+	   (rotatef (schar correcting-buffer i)
+		    (schar correcting-buffer (1+ i))))
+	(setf (schar correcting-buffer i) (car alphabet))
+	(check-closeness correcting-buffer word-len-+1 result)))
+    result))
+
+;;; SPELL-TRY-WORD The literal 4 is not a constant defined somewhere since it
+;;; is part of the definition of the function of looking up words.
+;;; TRY-WORD-ENDINGS relies on the guarantee that word-len is at least 4.
+;;; 
+(defun spell-try-word (word word-len)
+  "See if the word or an appropriate root is in the spelling dicitionary.
+   Word-len must be inclusively in the range 2..max-entry-length."
+  (or (lookup-entry word word-len)
+      (if (>= (the fixnum word-len) 4)
+	  (try-word-endings word word-len))))
+
+
+
+
+;;;; Divining Correct Spelling
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro setup-root-buffer (word buffer root-len)
+  `(replace ,buffer ,word :end1 ,root-len :end2 ,root-len))
+
+(defmacro try-root (word root-len flag-mask)
+  (let ((result (gensym)))
+    `(let ((,result (lookup-entry ,word ,root-len)))
+       (if (and ,result (descriptor-flag ,result ,flag-mask))
+	   (return (values ,result ,flag-mask))))))
+
+;;; TRY-MODIFIED-ROOT is used for root words that become truncated
+;;; when suffixes are added (e.g., skate => skating).  Char-idx is the last
+;;; character in the root that has to typically be changed from a #\I to a
+;;; #\Y or #\E.
+;;;
+(defmacro try-modified-root (word buffer root-len flag-mask char-idx new-char)
+  (let ((root-word (gensym)))
+    `(let ((,root-word (setup-root-buffer ,word ,buffer ,root-len)))
+       (setf (schar ,root-word ,char-idx) ,new-char)
+       (try-root ,root-word ,root-len ,flag-mask))))
+
+) ;eval-when
+
+
+(defvar *rooting-buffer* (make-string max-entry-length))
+
+;;; TRY-WORD-ENDINGS takes a word that is at least of length 4 and
+;;; returns multiple values on success (the index where the word's root's
+;;; descriptor starts and :used-flag), otherwise nil.  It looks at
+;;; characters from the end to the beginning of the word to determine if it
+;;; has any known suffixes.  This is a VERY simple finite state machine
+;;; where all of the suffixes are narrowed down to one possible one in at
+;;; most two state changes.  This is a PROG form for speed, and in some sense,
+;;; readability.  The states of the machine are the flag names that denote
+;;; suffixes.  The two points of branching to labels are the very beginning
+;;; of the PROG and the S state.  This is a fairly straight forward
+;;; implementation of the flag rules presented at the beginning of this
+;;; file, with char-idx checks, so we do not index the string below zero.
+
+(defun try-word-endings (word word-len)
+  (declare (simple-string word)
+	   (fixnum word-len))
+  (prog* ((char-idx (1- word-len))
+	  (char (schar word char-idx))
+	  (rooting-buffer *rooting-buffer*)
+	  flag-mask)
+         (declare (simple-string rooting-buffer)
+		  (fixnum char-idx))
+         (case char
+	   (#\S (go S))        ;This covers over half of the possible endings
+	                       ;by branching off the second to last character
+	                       ;to other flag states that have plural endings.
+	   (#\R (setf flag-mask R-mask)		   ;"er" and "ier"
+		(go D-R-Z-FLAG))
+	   (#\T (go T-FLAG))			   ;"est" and "iest"
+	   (#\D (setf flag-mask D-mask)		   ;"ed" and "ied"
+	        (go D-R-Z-FLAG))
+	   (#\H (go H-FLAG))			   ;"th" and "ieth"
+	   (#\N (setf flag-mask N-mask)		   ;"ion", "ication", and "en"
+		(go N-X-FLAG))
+	   (#\G (setf flag-mask G-mask)		   ;"ing"
+		(go G-J-FLAG))
+	   (#\Y (go Y-FLAG))			   ;"ly"
+	   (#\E (go V-FLAG)))			   ;"ive"
+         (return nil)
+
+    S
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*)
+		 (try-root word (1+ char-idx) S-mask)
+		 (return nil))
+	     (if (not (set-member-p char *sxzh*))
+		 (try-root word (1+ char-idx) S-mask)))
+         (case char
+	   (#\E (go S-FLAG))                    ;"es" and "ies"
+	   (#\R (setf flag-mask Z-mask)		;"ers" and "iers"
+		(go D-R-Z-FLAG))
+	   (#\G (setf flag-mask J-mask)		;"ings"
+		(go G-J-FLAG))
+	   (#\S (go P-FLAG))			;"ness" and "iness"
+	   (#\N (setf flag-mask X-mask)		;"ions", "ications", and "ens"
+		(go N-X-FLAG))
+	   (#\' (try-root word char-idx M-mask)))
+         (return nil)
+
+    S-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+	 (if (set-member-p char *sxzh*)
+	     (try-root word (1+ char-idx) S-mask))
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root word rooting-buffer (1+ char-idx)
+				S-mask char-idx #\Y))
+         (return nil)
+
+    D-R-Z-FLAG
+         (if (char/= (schar word (1- char-idx)) #\E) (return nil))
+         (try-root word char-idx flag-mask)
+         (if (<= (setf char-idx (- char-idx 2)) 0) (return nil))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*) 
+		 (try-root word (1+ char-idx) flag-mask)
+		 (return nil))
+	     (if (char/= (schar word char-idx) #\E)
+		 (try-root word (1+ char-idx) flag-mask)))
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root word rooting-buffer (1+ char-idx)
+				flag-mask char-idx #\Y))
+         (return nil)
+
+    P-FLAG
+         (if (or (char/= (schar word (1- char-idx)) #\E)
+		 (char/= (schar word (- char-idx 2)) #\N))
+	     (return nil))
+         (if (<= (setf char-idx (- char-idx 3)) 0) (return nil))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*) 
+		 (try-root word (1+ char-idx) P-mask)
+		 (return nil)))
+         (try-root word (1+ char-idx) P-mask)
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root word rooting-buffer (1+ char-idx)
+				P-mask char-idx #\Y))
+         (return nil)
+
+    G-J-FLAG
+         (if (< char-idx 3) (return nil))
+         (setf char-idx (- char-idx 2))
+         (setf char (schar word char-idx))
+         (if (or (char/= char #\I) (char/= (schar word (1+ char-idx)) #\N))
+	     (return nil))
+         (if (char/= (schar word (1- char-idx)) #\E)
+	     (try-root word char-idx flag-mask))
+         (try-modified-root word rooting-buffer (1+ char-idx)
+			    flag-mask char-idx #\E)
+         (return nil)
+
+    N-X-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (cond ((char= char #\E)
+		(setf char (schar word (1- char-idx)))
+		(if (and (char/= char #\Y) (char/= char #\E))
+		    (try-root word char-idx flag-mask))
+		(return nil))
+	       ((char= char #\O)
+		(if (char= (schar word (1- char-idx)) #\I)
+		    (try-modified-root word rooting-buffer char-idx
+				       flag-mask (1- char-idx) #\E)
+		    (return nil))
+		(if (< char-idx 5) (return nil))
+		(if (or (char/= (schar word (- char-idx 2)) #\T)
+			(char/= (schar word (- char-idx 3)) #\A)
+			(char/= (schar word (- char-idx 4)) #\C)
+			(char/= (schar word (- char-idx 5)) #\I))
+		    (return nil)
+		    (setf char-idx (- char-idx 4)))
+		(try-modified-root word rooting-buffer char-idx
+				   flag-mask (1- char-idx) #\Y))
+	       (t (return nil)))
+
+    T-FLAG
+         (if (or (char/= (schar word (1- char-idx)) #\S)
+		 (char/= (schar word (- char-idx 2)) #\E))
+	     (return nil)
+	     (setf char-idx (1- char-idx)))
+         (try-root word char-idx T-mask)
+         (if (<= (setf char-idx (- char-idx 2)) 0) (return nil))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*) 
+		 (try-root word (1+ char-idx) T-mask)
+		 (return nil))
+	     (if (char/= (schar word char-idx) #\E)
+		 (try-root word (1+ char-idx) T-mask)))
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root word rooting-buffer (1+ char-idx)
+				T-mask char-idx #\Y))
+         (return nil)
+
+    H-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (if (char/= char #\T) (return nil))
+         (if (char/= (schar word (1- char-idx)) #\Y)
+	     (try-root word char-idx H-mask))
+         (if (and (char= (schar word (1- char-idx)) #\E)
+		  (char= (schar word (- char-idx 2)) #\I))
+	     (try-modified-root word rooting-buffer (1- char-idx)
+				H-mask (- char-idx 2) #\Y))
+         (return nil)
+
+    Y-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (if (char= char #\L)
+	     (try-root word char-idx Y-mask))
+         (return nil)
+
+    V-FLAG
+         (setf char-idx (- char-idx 2))
+         (setf char (schar word char-idx))
+         (if (or (char/= char #\I) (char/= (schar word (1+ char-idx)) #\V))
+	     (return nil))
+         (if (char/= (schar word (1- char-idx)) #\E)
+	     (try-root word char-idx V-mask))
+         (try-modified-root word rooting-buffer (1+ char-idx)
+			    V-mask char-idx #\E)
+         (return nil)))
+
+
+
+;;; DESCRIPTOR-FLAG returns t or nil based on whether the flag is on.
+;;; From the diagram at the beginning of the file, we see that the flags
+;;; are stored two words off of the first word in the descriptor unit for
+;;; an entry.
+;;;
+(defun descriptor-flag (descriptor-start flag-mask)
+  (not (zerop
+	(the fixnum
+	     (logand
+	      (the fixnum (descriptor-ref (+ 2 (the fixnum descriptor-start))))
+	      (the fixnum flag-mask))))))
+
+
+
+;;;; Looking up Trials
+
+(eval-when (:compile-toplevel :execute)
+
+;;; SPELL-STRING= determines if string1 and string2 are the same.  Before
+;;; it is called it is known that they are both of (- end1 0) length, and
+;;; string2 is in system space.  This is used in FOUND-ENTRY-P.
+;;;
+(defmacro spell-string= (string1 string2 end1 start2)
+  (let ((idx1 (gensym))
+	(idx2 (gensym)))
+    `(do ((,idx1 0 (1+ ,idx1))
+	  (,idx2 ,start2 (1+ ,idx2)))
+	 ((= ,idx1 ,end1) t)
+       (declare (fixnum ,idx1 ,idx2))
+       (unless (= (the fixnum (char-code (schar ,string1 ,idx1)))
+		  (the fixnum (string-sapref ,string2 ,idx2)))
+	 (return nil)))))
+
+;;; FOUND-ENTRY-P determines if entry is what is described at idx.
+;;; Hash-and-length is 16 bits that look just like the first word of any
+;;; entry's descriptor unit (see diagram at the beginning of the file).  If
+;;; the word stored at idx and entry have the same hash bits and length,
+;;; then we compare characters to see if they are the same.
+;;;
+(defmacro found-entry-p (idx entry entry-len hash-and-length)
+  `(if (= (the fixnum (descriptor-ref ,idx))
+	  (the fixnum ,hash-and-length))
+      (spell-string= ,entry *string-table* ,entry-len
+		     (descriptor-string-start ,idx))))
+
+(defmacro hash2-increment (hash)
+  `(- (the fixnum *dictionary-size*)
+      2
+      (the fixnum (rem ,hash (- (the fixnum *dictionary-size*) 2)))))
+
+(defmacro hash2-loop ((location-var contents-var)
+		       loc hash zero-contents-form
+		       &optional body-form (for-insertion-p nil))
+  (let ((incr (gensym)))
+    `(let* ((,incr (hash2-increment ,hash))
+	    (,location-var ,loc)
+	    (,contents-var 0))
+	(declare (fixnum ,location-var ,contents-var ,incr))
+       (loop (setf ,location-var
+		   (rem (+ ,location-var ,incr) (the fixnum *dictionary-size*)))
+	     (setf ,contents-var (dictionary-ref ,location-var))
+	     (if (zerop ,contents-var) (return ,zero-contents-form))
+	     ,@(if for-insertion-p
+		   `((if (= ,contents-var spell-deleted-entry)
+			 (return ,zero-contents-form))))
+	     (if (= ,location-var ,loc) (return nil))
+	     ,@(if body-form `(,body-form))))))
+
+) ;eval-when
+
+
+;;; LOOKUP-ENTRY returns the index of the first element of entry's
+;;; descriptor unit on success, otherwise nil.  
+;;;
+(defun lookup-entry (entry &optional len)
+  (declare (simple-string entry))
+  (let* ((entry-len (or len (length entry)))
+	 (hash (string-hash entry entry-len))
+	 (hash-and-len (dpb (the fixnum (ldb new-hash-byte hash))
+			    stored-hash-byte
+			    (the fixnum entry-len)))
+	 (loc (rem hash (the fixnum *dictionary-size*)))
+	 (loc-contents (dictionary-ref loc)))
+    (declare (fixnum entry-len hash hash-and-len loc))
+    (cond ((zerop loc-contents) nil)
+	  ((found-entry-p loc-contents entry entry-len hash-and-len)
+	   loc-contents)
+	  (t
+	   (hash2-loop (loop-loc loc-contents) loc hash
+	     nil
+	     (if (found-entry-p loc-contents entry entry-len hash-and-len)
+		 (return loc-contents)))))))
+
+
+;;;; Binary File Reading
+
+(defparameter default-binary-dictionary
+  "library:spell-dictionary.bin")
+
+;;; This is the first thing in a spell binary dictionary file to serve as a
+;;; quick check of its proposed contents.  This particular number is
+;;; "BILLS" on a calculator held upside-down.
+;;;
+(defconstant magic-file-id 57718)
+
+;;; These constants are derived from the order things are written to the
+;;; binary dictionary in Spell-Build.Lisp.
+;;;
+(defconstant magic-file-id-loc 0)
+(defconstant dictionary-size-loc 1)
+(defconstant descriptors-size-loc 2)
+(defconstant string-table-size-low-byte-loc 3)
+(defconstant string-table-size-high-byte-loc 4)
+(defconstant file-header-bytes 10)
+
+;;; Initially, there are no free descriptor elements and string table bytes,
+;;; but when these structures are grown, they are grown by more than that
+;;; which is necessary.
+;;;
+(defvar *free-descriptor-elements* 0)
+(defvar *free-string-table-bytes* 0)
+
+;;; READ-DICTIONARY opens the dictionary and sets up the global structures
+;;; manifesting the spelling dictionary.  When computing the start addresses
+;;; of these structures, we multiply by two since their sizes are in 16bit
+;;; lengths while the RT is 8bit-byte addressable.
+;;;
+(defun read-dictionary (&optional (f default-binary-dictionary))
+  (when *dictionary-read-p*
+    (setf *dictionary-read-p* nil)
+    (deallocate-bytes (system-address *dictionary*)
+		      (* 2 (the fixnum *dictionary-size*)))
+    (deallocate-bytes (system-address *descriptors*)
+		      (* 2 (the fixnum
+				(+ (the fixnum *descriptors-size*)
+				   (the fixnum *free-descriptor-elements*)))))
+    (deallocate-bytes (system-address *string-table*)
+		      (+ (the fixnum *string-table-size*)
+			 (the fixnum *free-string-table-bytes*))))
+  (setf *free-descriptor-elements* 0)
+  (setf *free-string-table-bytes* 0)
+  (let* ((fd (open-dictionary f))
+	 (header-info (read-dictionary-structure fd file-header-bytes)))
+    (unless (= (sapref header-info magic-file-id-loc) magic-file-id)
+      (deallocate-bytes (system-address header-info) file-header-bytes)
+      (error "File is not a dictionary: ~S." f))
+    (setf *dictionary-size* (sapref header-info dictionary-size-loc))
+    (setf *descriptors-size* (sapref header-info descriptors-size-loc))
+    (setf *string-table-size* (sapref header-info string-table-size-low-byte-loc))
+    (setf (ldb (byte 12 16) (the fixnum *string-table-size*))
+	  (the fixnum (sapref header-info string-table-size-high-byte-loc)))
+    (deallocate-bytes (system-address header-info) file-header-bytes)
+    (setf *dictionary*
+	  (read-dictionary-structure fd (* 2 (the fixnum *dictionary-size*))))
+    (setf *descriptors*
+	  (read-dictionary-structure fd (* 2 (the fixnum *descriptors-size*))))
+    (setf *string-table* (read-dictionary-structure fd *string-table-size*))
+    (setf *dictionary-read-p* t)
+    (close-dictionary fd)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-rt.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-rt.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell-rt.lisp	(revision 13309)
@@ -0,0 +1,107 @@
+;;; -*- Log: hemlock.log; Package: Spell -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;
+;;; This file contains system dependent primitives for the spelling checking/
+;;; correcting code in Spell-Correct.Lisp, Spell-Augment.Lisp, and
+;;; Spell-Build.Lisp.
+
+(defpackage "SPELL"
+  (:use "LISP" "EXTENSIONS" "SYSTEM")
+  (:export spell-try-word spell-root-word spell-collect-close-words
+	   maybe-read-spell-dictionary correct-spelling max-entry-length
+	   spell-read-dictionary spell-add-entry spell-root-flags
+	   spell-remove-entry))
+
+(in-package "SPELL")
+
+
+
+;;;; System Area Referencing and Setting
+
+(eval-when (:compile-toplevel :execute)
+
+;;; MAKE-SAP returns pointers that *dictionary*, *descriptors*, and
+;;; *string-table* are bound to.  Address is in the system area.
+;;;
+(defmacro make-sap (address)
+  `(system:int-sap ,address))
+
+(defmacro system-address (sap)
+  `(system:sap-int ,sap))
+
+
+(defmacro allocate-bytes (count)
+  `(system:allocate-system-memory ,count))
+
+(defmacro deallocate-bytes (address byte-count)
+  `(system:deallocate-system-memory (int-sap ,address) ,byte-count))
+
+
+(defmacro sapref (sap offset)
+  `(system:sap-ref-16 ,sap (* ,offset 2)))
+
+(defsetf sapref (sap offset) (value)
+  `(setf (system:sap-ref-16 ,sap (* ,offset 2)) ,value))
+
+
+(defmacro sap-replace (dst-string src-string src-start dst-start dst-end)
+  `(%primitive byte-blt ,src-string ,src-start ,dst-string ,dst-start ,dst-end))
+
+(defmacro string-sapref (sap index)
+  `(system:sap-ref-8 ,sap ,index))
+
+
+
+
+;;;; Primitive String Hashing
+
+;;; STRING-HASH employs the instruction SXHASH-SIMPLE-SUBSTRING which takes
+;;; an end argument, so we do not have to use SXHASH.  SXHASH would mean
+;;; doing a SUBSEQ of entry.
+;;;
+(defmacro string-hash (string length)
+  `(ext:truly-the lisp::index
+		  (%primitive sxhash-simple-substring
+			      ,string
+			      (the fixnum ,length))))
+
+) ;eval-when
+
+
+
+
+;;;; Binary Dictionary File I/O
+
+(defun open-dictionary (f)
+  (let* ((filename (ext:unix-namestring f))
+	 (kind (unix:unix-file-kind filename)))
+    (unless kind (error "Cannot find dictionary -- ~S." filename))
+    (multiple-value-bind (fd err)
+			 (unix:unix-open filename unix:o_rdonly 0)
+      (unless fd
+	(error "Opening ~S failed: ~A." filename err))
+      (multiple-value-bind (winp dev-or-err) (unix:unix-fstat fd)
+	(unless winp (error "Opening ~S failed: ~A." filename dev-or-err))
+	fd))))
+
+(defun close-dictionary (fd)
+  (unix:unix-close fd))
+
+(defun read-dictionary-structure (fd bytes)
+  (let* ((structure (allocate-bytes bytes)))
+    (multiple-value-bind (read-bytes err)
+			 (unix:unix-read fd structure bytes)
+      (when (or (null read-bytes) (not (= bytes read-bytes)))
+	(deallocate-bytes (system-address structure) bytes)
+	(error "Reading dictionary structure failed: ~A." err))
+      structure)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/README
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/README	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/README	(revision 13309)
@@ -0,0 +1,26 @@
+SPELL was originally part of Hemlock, CMUCL's Common Lisp text editor.
+This version has been mostly rewritten in portable ANSI CL.  The only
+file that remains to be converted is spell-aug.lisp.  Besides ripping
+out implementation-specific code, the biggest change is that the spelling
+dictionary is no longer a global variable.  Instead, it has been
+converted to be a class; multiple dictionaries may thus coexist at any
+one time.  Most functions have therefore been changed to take an extra
+DICTIONARY parameter.
+
+An ASDF system definition is contained in spell.asd.
+
+Semi-extensive testing has been done.  However, a test suite would be
+a good thing to write.
+
+To get started, compile and load the system, then enter
+
+(SPELL::BUILD-DICTIONARY #p"/path/to/spell-dictionary.text" "outfile")
+(SETF MY-DICTIONARY *)
+(CORRECT-SPELLING MY-DICTIONARY "debugg")
+
+spellcoms.lisp is a file containing Hemlock commands and functions to
+integrate the SPELL package into Hemlock.  It needs to be rewritten
+to work with the new code, but is an example of what can be done with
+the provided interfaces.
+
+Please email any comments, questions, or bug fixes to froydnj@cs.rice.edu.
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/build.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/build.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/build.lisp	(revision 13309)
@@ -0,0 +1,200 @@
+;;; -*- Log: hemlock.log; Package: Spell -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;    Designed by Bill Chiles and Rob Maclachlan
+;;;
+
+;;; This file contains code to build a new binary dictionary file from
+;;; text in system space.  This code relies on implementation dependent
+;;; code from spell-rt.lisp.  Also, it is expected that spell-corr.lisp
+;;; and spell-aug.lisp have been loaded.  In order to compile this file,
+;;; you must first compile spell-rt, spell-corr.lisp, and spell-aug.lisp.
+
+;;; The text file must be in the following format:
+;;;      entry1/flag1/flag2/flag3
+;;;      entry2
+;;;      entry3/flag1/flag2/flag3/flag4/flag5.
+;;; The flags are single letter indicators of legal suffixes for the entry;
+;;; the available flags and their correct use may be found at the beginning
+;;; of spell-corr.lisp in the Hemlock sources.  There must be exactly one 
+;;; entry per line, and each line must be flushleft.
+
+
+(in-package "SPELL")
+
+;;; An interesting value when building an initial dictionary.
+(defvar *collision-count* 0)
+
+(defvar *new-dictionary*)
+(defvar *new-descriptors*)
+(defvar *new-string-table*)
+
+(declaim (optimize (debug 3)))
+
+
+
+;;;; Constants
+
+;;; This is an upper bound estimate of the number of stored entries in the
+;;; dictionary.  It should not be more than 21,845 because the dictionary
+;;; is a vector of type '(unsigned-byte 16), and the descriptors' vector
+;;; for the entries uses three '(unsigned-byte 16) elements per descriptor
+;;; unit.  See the beginning of Spell-Correct.Lisp.
+;;;
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+(defconstant +max-entry-count-estimate+ 15600)
+
+(defconstant +new-dictionary-size+ 20011)
+
+(defconstant +new-descriptors-size+ (1+ +max-entry-count-estimate+))
+
+(defconstant +max-string-table-length+ (* 10 +max-entry-count-estimate+))
+
+); eval-when
+
+
+
+;;;; Hashing
+
+;;; These hashing macros are different from the ones in Spell-Correct.Lisp
+;;; simply because we are using separate space and global specials/constants.
+;;; Of course, they should be identical, but it doesn't seem worth cluttering
+;;; up Spell-Correct with macro generating macros for this file.
+
+;;; Well, we've made them functions now.  we should really clean up the
+;;; other macros mentioned above by merging them with these
+
+(declaim (inline hash-increment handle-collision get-hash-index))
+(defun hash-increment (hash size)
+  (- size 2 (rem hash (- size 2))))
+
+(defun handle-collision (descriptor-table hash location)
+  (do* ((incr (hash-increment hash +new-dictionary-size+))
+        (collide-location (rem (+ location incr)
+                               +new-dictionary-size+)
+                          (rem (+ collide-location incr)
+                               +new-dictionary-size+)))
+       ;; if we've found our way back to where we started, there are
+       ;; no free slots available.  indicate failure.
+       ((= collide-location location) nil)
+    (when (zerop (aref descriptor-table collide-location))
+      (return-from handle-collision collide-location))))
+
+(defun get-hash-index (descriptor-table entry entry-length)
+  "Finds a suitable position in DESCRIPTOR-TABLE for ENTRY.
+   Returns NIL if one cannot be located."
+  (let* ((hash (string-hash entry entry-length))
+         (location (rem hash +new-dictionary-size+)))
+    (cond
+      ((not (zerop (aref descriptor-table location)))
+       ;; crud.  the desirable spot was already taken.  hunt for another
+       (incf *collision-count*)
+       (handle-collision descriptor-table hash location))
+      (t location))))
+
+
+
+;;;; Build-Dictionary
+
+(defun build-dictionary (input output)
+  (let* ((descriptors (make-array +new-descriptors-size+))
+         (string-table (make-string +max-string-table-length+))
+         (descriptor-table (make-array +new-dictionary-size+
+                                 :element-type '(unsigned-byte 16)))
+         (new-dictionary (make-instance 'dictionary
+                                        :string-table string-table
+                                        :descriptors descriptors
+                                        :descriptor-table descriptor-table)))
+    (write-line "Reading dictionary ...")
+    (force-output)
+    (setf *collision-count* 0)
+    (multiple-value-bind (entry-count string-table-length)
+			 (read-initial-dictionary input descriptor-table
+						  descriptors string-table)
+      (write-line "Writing dictionary ...")
+      (force-output)
+      (write-dictionary output new-dictionary entry-count string-table-length)
+      (format t "~D entries processed with ~D collisions."
+	      entry-count *collision-count*)
+      new-dictionary)))
+
+(defun read-initial-dictionary (f dictionary descriptors string-table)
+  (let* ((filename (pathname f))
+	 (s (open filename :direction :input :if-does-not-exist nil)))
+    (unless s (error "File ~S does not exist." f))
+    (multiple-value-prog1
+     (let ((descriptor-ptr 1)
+	   (string-ptr 0)
+	   (entry-count 0))
+       (declare (fixnum descriptor-ptr string-ptr entry-count))
+       (loop (multiple-value-bind (line eofp) (read-line s nil nil)
+	       (declare (type (or null simple-string) line))
+	       (unless line (return (values entry-count string-ptr)))
+	       (incf entry-count)
+	       (when (> entry-count +max-entry-count-estimate+)
+		 (error "There are too many entries in text file!~%~
+			Please change constants in spell-build.lisp, ~
+			recompile the file, and reload it.~%~
+			Be sure to understand the constraints of permissible ~
+			values."))
+	       (let ((flags (or (position #\/ line :test #'char=)
+                                (length line))))
+		 (declare (fixnum flags))
+		 (cond ((> flags +max-entry-length+)
+			(format t "Entry ~s too long." (subseq line 0 flags))
+			(force-output))
+		       (t (let ((new-string-ptr (+ string-ptr flags)))
+			    (declare (fixnum new-string-ptr))
+			    (when (> new-string-ptr +max-string-table-length+)
+			      (error "Spell string table overflow!~%~
+				     Please change constants in ~
+				     spell-build.lisp, recompile the file, ~
+				     and reload it.~%~
+				     Be sure to understand the constraints ~
+				     of permissible values."))
+			    (spell-place-entry line flags
+					       dictionary descriptors string-table
+					       descriptor-ptr string-ptr)
+			    (incf descriptor-ptr)
+			    (setf string-ptr new-string-ptr)))))
+	       (when eofp (return (values entry-count string-ptr))))))
+     (close s))))
+
+(defun word-flags (line word-end)
+  (declare (simple-string line) (fixnum word-end))
+  (let ((word-flags 0))
+    (do ((flag (1+ word-end) (+ 2 flag))
+         (line-end (length line)))
+        ((>= flag line-end) word-flags)
+      (declare (fixnum flag line-end))
+      (let ((flag-mask (flag-mask (schar line flag))))
+        (declare (fixnum flag-mask))
+        (if (zerop flag-mask)
+            (format t "Illegal flag ~S on word ~S."
+                    (schar line flag) (subseq line 0 word-end))
+            (setf word-flags
+                  (logior flag-mask word-flags)))))))
+
+(defun spell-place-entry (line word-end dictionary descriptors string-table
+			       descriptor-ptr string-ptr)
+  (declare (simple-string line string-table)
+	   (fixnum word-end descriptor-ptr string-ptr))
+  (nstring-upcase line :end word-end)
+  (let* ((hash-loc (get-hash-index dictionary line word-end)))
+    (unless hash-loc (error "Dictionary Overflow!"))
+    (setf (aref dictionary hash-loc) descriptor-ptr)
+    (let* ((hash-code (ldb +new-hash-byte+
+                           (string-hash line word-end)))
+           (descriptor (make-descriptor :hash-code hash-code
+                                        :length word-end
+                                        :string-index string-ptr)))
+      (setf (desc-flags descriptor) (word-flags line word-end)
+            (aref descriptors descriptor-ptr) descriptor)
+      (replace string-table line :start1 string-ptr :end2 word-end))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/classes.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/classes.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/classes.lisp	(revision 13309)
@@ -0,0 +1,21 @@
+(in-package :spell)
+
+(defclass dictionary ()
+  ((string-table :accessor string-table :initarg :string-table)
+   (descriptors :accessor descriptors :initarg :descriptors)
+   ;; maps from hashes of strings to their corresponding descriptors
+   (descriptor-table :accessor descriptor-table
+                     :initarg :descriptor-table)
+   (free-descriptors :accessor free-descriptors
+                     :initarg :free-descriptors
+                     :initform 0)
+   (free-string-table-bytes :accessor free-string-table-bytes
+                            :initarg :free-string-table-bytes
+                            :initform 0)))
+
+(defstruct (descriptor
+             (:conc-name desc-))
+  hash-code
+  length
+  string-index
+  flags)
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/constants.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/constants.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/constants.lisp	(revision 13309)
@@ -0,0 +1,61 @@
+(in-package "SPELL")
+
+(defconstant +spell-deleted-entry+ #xFFFF)
+
+;;; The next number (using 6 bits) is 63, and that's pretty silly because
+;;; "supercalafragalistic" is less than 31 characters long.
+;;;
+(defconstant +max-entry-length+ 31
+  "This the maximum number of characters an entry may have.")
+
+
+
+;;; These are the eleven bits of a computed hash that are stored as part of
+;;; an entries descriptor unit.  The shifting constant is how much the
+;;; eleven bits need to be shifted to the right, so they take up the upper
+;;; eleven bits of one 16-bit element in a descriptor unit.
+;;;
+(defconstant +new-hash-byte+ (byte 11 13))
+(defconstant +stored-hash-byte+ (byte 11 5))
+
+
+;;; The next two constants are used to extract information from an entry's
+;;; descriptor unit.  The first is the two most significant bits of 18
+;;; bits that hold an index into the string table where the entry is
+;;; located.  If this is confusing, regard the diagram of the descriptor
+;;; units above.
+;;;
+;;; This is used to break up an 18 bit string table index into two parts
+;;; for storage in a word descriptor unit.  See the documentation at the
+;;; top of Spell-Correct.Lisp.
+;;;
+(defconstant +whole-index-low-byte+ (byte 16 0))
+(defconstant +whole-index-high-byte+ (byte 2 16))
+
+(defconstant +stored-index-high-byte+ (byte 2 14))
+(defconstant +stored-length-byte+ (byte 5 0))
+
+(defconstant +spell-alphabet+
+  (list #\A #\B #\C #\D #\E #\F #\G #\H
+	#\I #\J #\K #\L #\M #\N #\O #\P
+	#\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z))
+
+;;; This is the first thing in a spell binary dictionary file to serve as a
+;;; quick check of its proposed contents.  This particular number is
+;;; "BILLS" on a calculator held upside-down.
+;;;
+(defconstant +magic-file-id+ 57718)
+
+;;; These constants are derived from the order things are written to the
+;;; binary dictionary in Spell-Build.Lisp.
+;;;
+(defconstant +magic-file-id-loc+ 0)
+(defconstant +dictionary-size-loc+ 1)
+(defconstant +descriptors-size-loc+ 2)
+(defconstant +string-table-size-low-byte-loc+ 3)
+(defconstant +string-table-size-high-byte-loc+ 4)
+(defconstant +file-header-bytes+ 10)
+
+;;; bump this up a bit, but do not lower it.  TRY-WORD-ENDINGS depends on
+;;; this value being at least 4.
+(defconstant +minimum-try-word-endings-length+ 4)
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/correlate.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/correlate.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/correlate.lisp	(revision 13309)
@@ -0,0 +1,648 @@
+;;; -*- Log: hemlock.log; Package: Spell -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;    Designed by Bill Chiles and Rob Maclachlan
+;;;
+
+;;;      This is the file that deals with checking and correcting words
+;;; using a dictionary read in from a binary file.  It has been written
+;;; from the basic ideas used in Ispell (on DEC-20's) which originated as
+;;; Spell on the ITS machines at MIT.  There are flags which have proper
+;;; uses defined for them that indicate permissible suffixes to entries.
+;;; This allows for about three times as many known words than are actually
+;;; stored.  When checking the spelling of a word, first it is looked up;
+;;; if this fails, then possible roots are looked up, and if any has the
+;;; appropriate suffix flag, then the word is considered to be correctly
+;;; spelled.  For an unknown word, the following rules define "close" words
+;;; which are possible corrections:
+;;;    1] two adjacent letters are transposed to form a correct spelling;
+;;;    2] one letter is changed to form a correct spelling;
+;;;    3] one letter is added to form a correct spelling; and/or
+;;;    4] one letter is removed to form a correct spelling. 
+;;; There are two restrictions on the length of a word in regards to its
+;;; worthiness of recognition: it must be at least more than two letters
+;;; long, and if it has a suffix, then it must be at least four letters
+;;; long.  More will be said about this when the flags are discussed.
+;;;      This is implemented in as tense a fashion as possible, and it uses
+;;; implementation dependent code from Spell-RT.Lisp to accomplish this.
+;;; In general the file I/O and structure accesses encompass the system
+;;; dependencies.
+
+;;;      This next section will discuss the storage of the dictionary
+;;; information.  There are three data structures that "are" the
+;;; dictionary: a hash table, descriptors table, and a string table.  The
+;;; hash table is a vector of type '(unsigned-byte 16), whose elements
+;;; point into the descriptors table.  This is a cyclic hash table to
+;;; facilitate dumping it to a file.  The descriptors table (also of type
+;;; '(unsigned-byte 16)) dedicates three elements to each entry in the
+;;; dictionary.  Each group of three elements has the following organization
+;;; imposed on them:
+;;;    ----------------------------------------------
+;;;    |  15..5  hash code  |      4..0 length      |
+;;;    ----------------------------------------------
+;;;    |           15..0 character index            |
+;;;    ----------------------------------------------
+;;;    |  15..14 character index  |  13..0 flags    |
+;;;    ----------------------------------------------
+;;; "Length" is the number of characters in the entry; "hash code" is some
+;;; eleven bits from the hash code to allow for quicker lookup, "flags"
+;;; indicate possible suffixes for the basic entry, and "character index"
+;;; is the index of the start of the entry in the string table.
+;;;      This was originally adopted due to the Perq's word size (can you guess?
+;;; 16 bits, that's right).  Note the constraint that is placed on the number
+;;; of the entries, 21845, because the hash table could not point to more
+;;; descriptor units (16 bits of pointer divided by three).  Since a value of
+;;; zero as a hash table element indicates an empty location, the zeroth element
+;;; of the descriptors table must be unused (it cannot be pointed to).
+
+
+;;;      The following is a short discussion with examples of the correct
+;;; use of the suffix flags.  Let # and @ be symbols that can stand for any
+;;; single letter.  Upper case letters are constants.  "..." stands for any
+;;; string of zero or more letters,  but note that no word may exist in the
+;;; dictionary which is not at least 2 letters long, so, for example, FLY
+;;; may not be produced by placing the "Y" flag on "F".  Also, no flag is
+;;; effective unless the word that it creates is at least 4 letters long,
+;;; so, for example, WED may not be produced by placing the "D" flag on
+;;; "WE".  These flags and examples are from the Ispell documentation with
+;;; only slight modifications.  Here are the correct uses of the flags:
+;;; 
+;;; "V" flag:
+;;;         ...E => ...IVE  as in  create => creative
+;;;         if # .ne. E, then  ...# => ...#IVE  as in  prevent => preventive
+;;; 
+;;; "N" flag:
+;;;         ...E => ...ION  as in create => creation
+;;;         ...Y => ...ICATION  as in  multiply => multiplication
+;;;         if # .ne. E or Y, then  ...# => ...#EN  as in  fall => fallen
+;;; 
+;;; "X" flag:
+;;;         ...E => ...IONS  as in  create => creations
+;;;         ...Y => ...ICATIONS  as in  multiply => multiplications
+;;;         if # .ne. E or Y, ...# => ...#ENS  as in  weak => weakens
+;;; 
+;;; "H" flag:
+;;;         ...Y => ...IETH  as in  twenty => twentieth
+;;;         if # .ne. Y, then  ...# => ...#TH  as in  hundred => hundredth
+;;; 
+;;; "Y" FLAG:
+;;;         ... => ...LY  as in  quick => quickly
+;;; 
+;;; "G" FLAG:
+;;;         ...E => ...ING  as in  file => filing
+;;;         if # .ne. E, then  ...# => ...#ING  as in  cross => crossing
+;;; 
+;;; "J" FLAG"
+;;;         ...E => ...INGS  as in  file => filings
+;;;         if # .ne. E, then  ...# => ...#INGS  as in  cross => crossings
+;;; 
+;;; "D" FLAG:
+;;;         ...E => ...ED  as in  create => created
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IED  as in  imply => implied
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#ED  as in  convey => conveyed
+;;;         if # .ne. E or Y, then  ...# => ...#ED  as in  cross => crossed
+;;; 
+;;; "T" FLAG:
+;;;         ...E => ...EST  as in  late => latest
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IEST  as in  dirty => dirtiest
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#EST  as in  gray => grayest
+;;;         if # .ne. E or Y, then  ...# => ...#EST  as in  small => smallest
+;;; 
+;;; "R" FLAG:
+;;;         ...E => ...ER  as in  skate => skater
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IER  as in  multiply => multiplier
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then ...@# => ...@#ER  as in  convey => conveyer
+;;;         if # .ne. E or Y, then  ...# => ...#ER  as in  build => builder
+;;; 
+
+;;; "Z FLAG:
+;;;         ...E => ...ERS  as in  skate => skaters
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IERS  as in  multiply => multipliers
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#ERS  as in  slay => slayers
+;;;         if # .ne. E or Y, then  ...@# => ...@#ERS  as in  build => builders
+;;; 
+;;; "S" FLAG:
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@IES  as in  imply => implies
+;;;         if # .eq. S, X, Z, or H,
+;;;            then  ...# => ...#ES  as in  fix => fixes
+;;;         if # .ne. S, X, Z, H, or Y,
+;;;            then  ...# => ...#S  as in  bat => bats
+;;;         if # = Y, and @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#S  as in  convey => conveys
+;;; 
+;;; "P" FLAG:
+;;;         if # .ne. Y, or @ = A, E, I, O, or U,
+;;;            then  ...@# => ...@#NESS  as in  late => lateness and
+;;;                                             gray => grayness
+;;;         if @ .ne. A, E, I, O, or U,
+;;;            then  ...@Y => ...@INESS  as in  cloudy => cloudiness
+;;; 
+;;; "M" FLAG:
+;;;         ... => ...'S  as in DOG => DOG'S
+
+(in-package "SPELL")
+
+
+
+;;;; Some Specials and Accesses
+
+;;; *spell-aeiou* will have bits on that represent the capital letters
+;;; A, E, I, O, and U to be used to determine if some word roots are legal
+;;; for looking up.
+;;;
+(defvar *aeiou*
+  (make-array 128 :element-type 'bit :initial-element 0))
+
+(setf (aref *aeiou* (char-code #\A)) 1)
+(setf (aref *aeiou* (char-code #\E)) 1)
+(setf (aref *aeiou* (char-code #\I)) 1)
+(setf (aref *aeiou* (char-code #\O)) 1)
+(setf (aref *aeiou* (char-code #\U)) 1)
+
+
+;;; *sxzh* will have bits on that represent the capital letters
+;;; S, X, Z, and H to be used to determine if some word roots are legal for
+;;; looking up.
+;;;
+(defvar *sxzh*
+  (make-array 128 :element-type 'bit :initial-element 0))
+
+(setf (aref *sxzh* (char-code #\S)) 1)
+(setf (aref *sxzh* (char-code #\X)) 1)
+(setf (aref *sxzh* (char-code #\Z)) 1)
+(setf (aref *sxzh* (char-code #\H)) 1)
+
+
+;;; SET-MEMBER-P will be used with *aeiou* and *sxzh* to determine if a
+;;; character is in the specified set.
+;;;
+(declaim (inline set-member-p))
+(defun set-member-p (char set)
+  (not (zerop (the fixnum (aref (the simple-bit-vector set)
+                                (char-code char))))))
+
+;;; DESC-TABLE-REF and DESCRIPTOR-REF are references to implementation
+;;; dependent structures.
+;;;
+(declaim (inline desc-table-ref descriptor-ref))
+(defun desc-table-ref (dictionary index)
+  (aref (descriptor-table dictionary) index))
+(defun %set-desc-table-ref (dictionary index value)
+  (setf (aref (descriptor-table dictionary) index) value))
+
+(defsetf desc-table-ref %set-desc-table-ref)
+
+(defun descriptor-ref (dictionary index)
+  (aref (descriptors dictionary) index))
+
+
+;;; DESCRIPTOR-STRING-START access an entry's (indicated by idx)
+;;; descriptor unit (described at the beginning of the file) and returns
+;;; the start index of the entry in the string table.  The second of three
+;;; words in the descriptor holds the 16 least significant bits of 18, and
+;;; the top two bits of the third word are the 2 most significant bits.
+;;; These 18 bits are the index into the string table.
+;;;
+(defun descriptor-string-start (dictionary index)
+  (desc-string-index (descriptor-ref dictionary index)))
+
+
+
+;;;; Top level Checking/Correcting
+
+;;; CORRECT-SPELLING can be called from top level to check/correct a words
+;;; spelling.  It is not used for any other purpose.
+;;; 
+(defun correct-spelling (dictionary word)
+  "Check/correct the spelling of word.  Output is done to *standard-output*."
+  (setf word (coerce word 'simple-string))
+  (let ((word (string-upcase (the simple-string word)))
+	(word-len (length (the simple-string word))))
+    (declare (simple-string word) (fixnum word-len))
+    (when (= word-len 1)
+      (error "Single character words are not in the dictionary."))
+    (when (> word-len +max-entry-length+)
+      (error "~A is too long for the dictionary." word))
+    (multiple-value-bind (idx used-flag-p)
+			 (spell-try-word dictionary word word-len)
+      (if idx
+	  (format t "Found it~:[~; because of ~A~]." used-flag-p
+		  (spell-root-word dictionary idx))
+	  (let ((close-words (spell-collect-close-words dictionary word)))
+	    (if close-words
+		(format *standard-output*
+			"The possible correct spelling~[~; is~:;s are~]:~
+			~:*~[~; ~{~A~}~;~{ ~A~^ and~}~:;~
+			~{~#[~; and~] ~A~^,~}~]."
+			(length close-words)
+			close-words)
+		(format *standard-output* "Word not found.")))))))
+
+
+(defun spell-root-word (dictionary index)
+  "Return the root word corresponding to a dictionary entry at index."
+  (let* ((descriptor (descriptor-ref dictionary index))
+         (start (desc-string-index descriptor))
+	 (len (desc-length descriptor)))
+    (declare (fixnum start len))
+    ;; return a copy
+    (subseq (string-table dictionary) start (+ start len))))
+
+
+;;; SPELL-COLLECT-CLOSE-WORDS Returns a list of all "close" correctly spelled
+;;; words.  The definition of "close" is at the beginning of the file, and
+;;; there are four sections to this function which collect each of the four
+;;; different kinds of close words.
+;;; 
+(defun spell-collect-close-words (dictionary word)
+  "Returns a list of all \"close\" correctly spelled words.  This has the
+   same contraints as SPELL-TRY-WORD, which you have probably already called
+   if you are calling this."
+  (declare (simple-string word))
+  (let* ((word-len (length word))
+	 (word-len--1 (1- word-len))
+	 (word-len-+1 (1+ word-len))
+	 (result ())
+	 (correcting-buffer (make-string +max-entry-length+)))
+    (macrolet ((check-closeness (dictionary word word-len closeness-list)
+                 `(when (spell-try-word ,dictionary ,word ,word-len)
+                   (pushnew (subseq ,word 0 ,word-len)
+                    ,closeness-list :test #'string=))))
+      (declare (simple-string correcting-buffer)
+               (fixnum word-len word-len--1 word-len-+1))
+      (replace correcting-buffer word :end1 word-len :end2 word-len)
+
+      ;; Misspelled because one letter is different.
+      (dotimes (i word-len)
+        (do ((save-char (schar correcting-buffer i))
+             (alphabet +spell-alphabet+ (cdr alphabet)))
+            ((null alphabet)
+             (setf (schar correcting-buffer i) save-char))
+          (setf (schar correcting-buffer i) (car alphabet))
+          (check-closeness dictionary correcting-buffer word-len result)))
+
+      ;; Misspelled because two adjacent letters are transposed.
+      (dotimes (i word-len--1)
+        (rotatef (schar correcting-buffer i) (schar correcting-buffer (1+ i)))
+        (check-closeness dictionary  correcting-buffer word-len result)
+        (rotatef (schar correcting-buffer i) (schar correcting-buffer (1+ i))))
+
+      ;; Misspelled because of extraneous letter.
+      (replace correcting-buffer word
+               :start2 1 :end1 word-len--1 :end2 word-len)
+      (check-closeness dictionary correcting-buffer word-len--1 result)
+      (dotimes (i word-len--1)
+        (setf (schar correcting-buffer i) (schar word i))
+        (replace correcting-buffer word
+                 :start1 (1+ i) :start2 (+ i 2) :end1 word-len--1 :end2 word-len)
+        (check-closeness dictionary correcting-buffer word-len--1 result))
+
+      ;; Misspelled because a letter is missing.
+      (replace correcting-buffer word
+               :start1 1 :end1 word-len-+1 :end2 word-len)
+      (dotimes (i word-len-+1)
+        (do ((alphabet +spell-alphabet+ (cdr alphabet)))
+            ((null alphabet)
+             (rotatef (schar correcting-buffer i)
+                      (schar correcting-buffer (1+ i))))
+          (setf (schar correcting-buffer i) (car alphabet))
+          (check-closeness dictionary correcting-buffer word-len-+1 result)))
+      result)))
+
+;;; SPELL-TRY-WORD The literal 4 is not a constant defined somewhere since it
+;;; is part of the definition of the function of looking up words.
+;;; TRY-WORD-ENDINGS relies on the guarantee that word-len is at least 4.
+;;; 
+(defun spell-try-word (dictionary word word-len)
+  "See if the word or an appropriate root is in the spelling dicitionary.
+   Word-len must be inclusively in the range 2..max-entry-length."
+  (or (lookup-entry dictionary word word-len)
+      (if (>= (the fixnum word-len) +minimum-try-word-endings-length+)
+	  (try-word-endings dictionary word word-len))))
+
+
+
+
+;;;; Divining Correct Spelling
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro setup-root-buffer (word buffer root-len)
+  `(replace ,buffer ,word :end1 ,root-len :end2 ,root-len))
+
+(defmacro try-root (dictionary word root-len flag-mask)
+  (let ((result (gensym)))
+    `(let ((,result (lookup-entry ,dictionary ,word ,root-len)))
+       (if (and ,result (descriptor-flag ,dictionary ,result ,flag-mask))
+	   (return (values ,result ,flag-mask))))))
+
+;;; TRY-MODIFIED-ROOT is used for root words that become truncated
+;;; when suffixes are added (e.g., skate => skating).  Char-idx is the last
+;;; character in the root that has to typically be changed from a #\I to a
+;;; #\Y or #\E.
+;;;
+(defmacro try-modified-root (dictionary word buffer
+                             root-len flag-mask char-idx new-char)
+  (let ((root-word (gensym)))
+    `(let ((,root-word (setup-root-buffer ,word ,buffer ,root-len)))
+       (setf (schar ,root-word ,char-idx) ,new-char)
+       (try-root ,dictionary ,root-word ,root-len ,flag-mask))))
+
+) ;eval-when
+
+(defvar *rooting-buffer* (make-string +max-entry-length+))
+
+;;; TRY-WORD-ENDINGS takes a word that is at least of length 4 and
+;;; returns multiple values on success (the index where the word's root's
+;;; descriptor starts and :used-flag), otherwise nil.  It looks at
+;;; characters from the end to the beginning of the word to determine if it
+;;; has any known suffixes.  This is a VERY simple finite state machine
+;;; where all of the suffixes are narrowed down to one possible one in at
+;;; most two state changes.  This is a PROG form for speed, and in some sense,
+;;; readability.  The states of the machine are the flag names that denote
+;;; suffixes.  The two points of branching to labels are the very beginning
+;;; of the PROG and the S state.  This is a fairly straight forward
+;;; implementation of the flag rules presented at the beginning of this
+;;; file, with char-idx checks, so we do not index the string below zero.
+
+(defun try-word-endings (dictionary word word-len)
+  (declare (simple-string word)
+	   (fixnum word-len))
+  (prog* ((char-idx (1- word-len))
+	  (char (schar word char-idx))
+	  (rooting-buffer *rooting-buffer*)
+	  flag-mask)
+         (declare (simple-string rooting-buffer)
+		  (fixnum char-idx))
+         (case char
+	   (#\S (go S))        ;This covers over half of the possible endings
+	                       ;by branching off the second to last character
+	                       ;to other flag states that have plural endings.
+	   (#\R (setf flag-mask +R-mask+)		   ;"er" and "ier"
+		(go D-R-Z-FLAG))
+	   (#\T (go T-FLAG))			   ;"est" and "iest"
+	   (#\D (setf flag-mask +D-mask+)		   ;"ed" and "ied"
+	        (go D-R-Z-FLAG))
+	   (#\H (go H-FLAG))			   ;"th" and "ieth"
+	   (#\N (setf flag-mask +N-mask+)		   ;"ion", "ication", and "en"
+		(go N-X-FLAG))
+	   (#\G (setf flag-mask +G-mask+)		   ;"ing"
+		(go G-J-FLAG))
+	   (#\Y (go Y-FLAG))			   ;"ly"
+	   (#\E (go V-FLAG)))			   ;"ive"
+         (return nil)
+
+    S
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*)
+		 (try-root dictionary word (1+ char-idx) +S-mask+)
+		 (return nil))
+	     (if (not (set-member-p char *sxzh*))
+		 (try-root dictionary word (1+ char-idx) +S-mask+)))
+         (case char
+	   (#\E (go S-FLAG))                    ;"es" and "ies"
+	   (#\R (setf flag-mask +Z-mask+)		;"ers" and "iers"
+		(go D-R-Z-FLAG))
+	   (#\G (setf flag-mask +J-mask+)		;"ings"
+		(go G-J-FLAG))
+	   (#\S (go P-FLAG))			;"ness" and "iness"
+	   (#\N (setf flag-mask +X-mask+)		;"ions", "ications", and "ens"
+		(go N-X-FLAG))
+	   (#\' (try-root dictionary word char-idx +M-mask+)))
+         (return nil)
+
+    S-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+	 (if (set-member-p char *sxzh*)
+	     (try-root dictionary word (1+ char-idx) +S-mask+))
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root dictionary word rooting-buffer (1+ char-idx)
+				+S-mask+ char-idx #\Y))
+         (return nil)
+
+    D-R-Z-FLAG
+         (if (char/= (schar word (1- char-idx)) #\E) (return nil))
+         (try-root dictionary word char-idx flag-mask)
+         (if (<= (setf char-idx (- char-idx 2)) 0) (return nil))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*) 
+		 (try-root dictionary word (1+ char-idx) flag-mask)
+		 (return nil))
+	     (if (char/= (schar word char-idx) #\E)
+		 (try-root dictionary word (1+ char-idx) flag-mask)))
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root dictionary word rooting-buffer (1+ char-idx)
+				flag-mask char-idx #\Y))
+         (return nil)
+
+    P-FLAG
+         (if (or (char/= (schar word (1- char-idx)) #\E)
+		 (char/= (schar word (- char-idx 2)) #\N))
+	     (return nil))
+         (if (<= (setf char-idx (- char-idx 3)) 0) (return nil))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*) 
+		 (try-root dictionary word (1+ char-idx) +P-mask+)
+		 (return nil)))
+         (try-root dictionary word (1+ char-idx) +P-mask+)
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root dictionary word rooting-buffer (1+ char-idx)
+				+P-mask+ char-idx #\Y))
+         (return nil)
+
+    G-J-FLAG
+         (if (< char-idx 3) (return nil))
+         (setf char-idx (- char-idx 2))
+         (setf char (schar word char-idx))
+         (if (or (char/= char #\I) (char/= (schar word (1+ char-idx)) #\N))
+	     (return nil))
+         (if (char/= (schar word (1- char-idx)) #\E)
+	     (try-root dictionary word char-idx flag-mask))
+         (try-modified-root dictionary word rooting-buffer (1+ char-idx)
+			    flag-mask char-idx #\E)
+         (return nil)
+
+    N-X-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (cond ((char= char #\E)
+		(setf char (schar word (1- char-idx)))
+		(if (and (char/= char #\Y) (char/= char #\E))
+		    (try-root dictionary word char-idx flag-mask))
+		(return nil))
+	       ((char= char #\O)
+		(if (char= (schar word (1- char-idx)) #\I)
+		    (try-modified-root dictionary word rooting-buffer char-idx
+				       flag-mask (1- char-idx) #\E)
+		    (return nil))
+		(if (< char-idx 5) (return nil))
+		(if (or (char/= (schar word (- char-idx 2)) #\T)
+			(char/= (schar word (- char-idx 3)) #\A)
+			(char/= (schar word (- char-idx 4)) #\C)
+			(char/= (schar word (- char-idx 5)) #\I))
+		    (return nil)
+		    (setf char-idx (- char-idx 4)))
+		(try-modified-root dictionary word rooting-buffer char-idx
+				   flag-mask (1- char-idx) #\Y))
+	       (t (return nil)))
+
+    T-FLAG
+         (if (or (char/= (schar word (1- char-idx)) #\S)
+		 (char/= (schar word (- char-idx 2)) #\E))
+	     (return nil)
+	     (setf char-idx (1- char-idx)))
+         (try-root dictionary word char-idx +T-mask+)
+         (if (<= (setf char-idx (- char-idx 2)) 0) (return nil))
+         (setf char (schar word char-idx))
+         (if (char= char #\Y)
+	     (if (set-member-p (schar word (1- char-idx)) *aeiou*) 
+		 (try-root dictionary word (1+ char-idx) +T-mask+)
+		 (return nil))
+	     (if (char/= (schar word char-idx) #\E)
+		 (try-root dictionary word (1+ char-idx) +T-mask+)))
+         (if (and (char= char #\I)
+		  (not (set-member-p (schar word (1- char-idx)) *aeiou*)))
+	     (try-modified-root dictionary word rooting-buffer (1+ char-idx)
+				+T-mask+ char-idx #\Y))
+         (return nil)
+
+    H-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (if (char/= char #\T) (return nil))
+         (if (char/= (schar word (1- char-idx)) #\Y)
+	     (try-root dictionary word char-idx +H-mask+))
+         (if (and (char= (schar word (1- char-idx)) #\E)
+		  (char= (schar word (- char-idx 2)) #\I))
+	     (try-modified-root dictionary word rooting-buffer (1- char-idx)
+				+H-mask+ (- char-idx 2) #\Y))
+         (return nil)
+
+    Y-FLAG
+         (setf char-idx (1- char-idx))
+         (setf char (schar word char-idx))
+         (if (char= char #\L)
+	     (try-root dictionary word char-idx +Y-mask+))
+         (return nil)
+
+    V-FLAG
+         (setf char-idx (- char-idx 2))
+         (setf char (schar word char-idx))
+         (if (or (char/= char #\I) (char/= (schar word (1+ char-idx)) #\V))
+	     (return nil))
+         (if (char/= (schar word (1- char-idx)) #\E)
+	     (try-root dictionary word char-idx +V-mask+))
+         (try-modified-root dictionary word rooting-buffer (1+ char-idx)
+			    +V-mask+ char-idx #\E)
+         (return nil)))
+
+
+
+;;; DESCRIPTOR-FLAG returns t or nil based on whether the flag is on.
+;;; From the diagram at the beginning of the file, we see that the flags
+;;; are stored two words off of the first word in the descriptor unit for
+;;; an entry.
+;;;
+;;; Note: modified for new descriptor scheme
+(defun descriptor-flag (dictionary descriptor flag-mask)
+  (not (zerop
+	(the fixnum
+	     (logand
+	      (the fixnum (desc-flags (descriptor-ref dictionary descriptor)))
+	      (the fixnum flag-mask))))))
+
+
+
+;;;; Looking up Trials
+
+;;; these functions used to be macros
+(declaim (inline spell-string= found-entry-p))
+
+(defun spell-string= (string1 string2 end1 start2)
+  (string= string1 string2
+           :end1 end1
+           :start2 start2
+           :end2 (+ start2 end1)))
+
+;;; FOUND-ENTRY-P determines if entry is what is described at idx.
+;;; Hash-and-length is 16 bits that look just like the first word of any
+;;; entry's descriptor unit (see diagram at the beginning of the file).  If
+;;; the word stored at idx and entry have the same hash bits and length,
+;;; then we compare characters to see if they are the same.
+;;;
+(defun found-entry-p (dictionary idx entry entry-len hash)
+  (let ((desc (descriptor-ref dictionary idx)))
+    (if (and (= (desc-hash-code desc) hash)
+             (= (desc-length desc) entry-len))
+        hash
+        (spell-string= entry (string-table dictionary) entry-len
+                       (desc-string-index desc)))))
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro hash2-loop ((location-var contents-var)
+		       dictionary loc hash zero-contents-form
+		       &optional body-form (for-insertion-p nil))
+  (let ((incr (gensym)))
+    `(let* ((,incr (hash-increment ,hash +new-dictionary-size+))
+	    (,location-var ,loc)
+	    (,contents-var 0))
+	(declare (fixnum ,location-var ,contents-var ,incr))
+       (loop (setf ,location-var
+		   (rem (+ ,location-var ,incr) (the fixnum +new-dictionary-size+)))
+	     (setf ,contents-var (desc-table-ref ,dictionary ,location-var))
+	     (if (zerop ,contents-var) (return ,zero-contents-form))
+	     ,@(if for-insertion-p
+		   `((if (= ,contents-var spell-deleted-entry)
+			 (return ,zero-contents-form))))
+	     (if (= ,location-var ,loc) (return nil))
+	     ,@(if body-form `(,body-form))))))
+
+) ;eval-when
+
+
+;;; LOOKUP-ENTRY returns the index of the first element of entry's
+;;; descriptor unit on success, otherwise nil.  
+;;;
+(defun lookup-entry (dictionary entry &optional length)
+  (declare (simple-string entry))
+  (let* ((entry-length (or length (length entry)))
+	 (hash (string-hash entry entry-length))
+	 (loc (rem hash (the fixnum +new-dictionary-size+)))
+	 (loc-contents (desc-table-ref dictionary loc)))
+    (declare (fixnum entry-length hash loc))
+    (cond ((zerop loc-contents) nil)
+	  ((found-entry-p dictionary loc-contents entry entry-length hash)
+	   loc-contents)
+	  (t
+	   (hash2-loop (loop-loc loc-contents)
+             dictionary loc hash
+	     nil
+	     (if (found-entry-p dictionary loc-contents entry
+                                entry-length hash)
+		 (return loc-contents)))))))
+
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/flags.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/flags.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/flags.lisp	(revision 13309)
@@ -0,0 +1,43 @@
+(in-package "SPELL")
+
+;;; FIXME: show where these things are documented
+(defconstant +V-mask+ (ash 1 13))
+(defconstant +N-mask+ (ash 1 12))
+(defconstant +X-mask+ (ash 1 11))
+(defconstant +H-mask+ (ash 1 10))
+(defconstant +Y-mask+ (ash 1 9))
+(defconstant +G-mask+ (ash 1 8))
+(defconstant +J-mask+ (ash 1 7))
+(defconstant +D-mask+ (ash 1 6))
+(defconstant +T-mask+ (ash 1 5))
+(defconstant +R-mask+ (ash 1 4))
+(defconstant +Z-mask+ (ash 1 3))
+(defconstant +S-mask+ (ash 1 2))
+(defconstant +P-mask+ (ash 1 1))
+(defconstant +M-mask+ 1)
+
+(defconstant flag-names-to-masks
+  `((#\V . ,+V-mask+) (#\N . ,+N-mask+) (#\X . ,+X-mask+)
+    (#\H . ,+H-mask+) (#\Y . ,+Y-mask+) (#\G . ,+G-mask+)
+    (#\J . ,+J-mask+) (#\D . ,+D-mask+) (#\T . ,+T-mask+)
+    (#\R . ,+R-mask+) (#\Z . ,+Z-mask+) (#\S . ,+S-mask+)
+    (#\P . ,+P-mask+) (#\M . ,+M-mask+)))
+
+(defvar *flag-masks*
+  (make-array 128 :element-type '(unsigned-byte 16) :initial-element 0)
+  "This holds the masks for character flags, which is used when reading
+   a text file of dictionary words.  Illegal character flags hold zero.")
+
+(declaim (inline flag-mask))
+(defun flag-mask (char)
+  (aref *flag-masks* (char-code char)))
+(defun %set-flag-mask (char value)
+  (setf (aref *flag-masks* (char-code char)) value))
+
+(defsetf flag-mask %set-flag-mask)
+
+(dolist (e flag-names-to-masks)
+  (let ((char (car e))
+	(mask (cdr e)))
+    (setf (flag-mask char) mask)
+    (setf (flag-mask (char-downcase char)) mask)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/hashing.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/hashing.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/hashing.lisp	(revision 13309)
@@ -0,0 +1,14 @@
+(in-package "SPELL")
+
+;;; FIXME: the original code included the below comment; obviously, it
+;;; utilized implementation-specific primitives to speed up hashing.  is
+;;; this reasonable to do?
+;;;
+;;; STRING-HASH employs the instruction SXHASH-SIMPLE-SUBSTRING which takes
+;;; an end argument, so we do not have to use SXHASH.  SXHASH would mean
+;;; doing a SUBSEQ of entry.
+(declaim (inline string-hash))
+(defun string-hash (string length)
+  (if (= length (length string))
+      (sxhash string)
+      (sxhash (subseq string 0 length))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/io.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/io.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/io.lisp	(revision 13309)
@@ -0,0 +1,95 @@
+(in-package "SPELL")
+
+(defparameter default-binary-dictionary #p"HOME:spell.bin")
+
+(defconstant +descriptor-bytes+ 10
+  "The number of bytes a descriptor takes up on disk.")
+
+;;; going for ease of writing on this first pass.  later we'll pack things
+;;; together a little bit more and document it.
+(defun read-descriptor (stream)
+  (let ((hash-code (read-byte stream))
+        (length (read-byte stream))
+        (low-index (read-byte stream))
+        (high-index (read-byte stream))
+        (flags (read-byte stream)))
+    (make-descriptor :hash-code hash-code
+                     :length length
+                     :char-index (dpb high-index +whole-index-high-byte+
+                                      low-index)
+                     :flags flags)))
+
+(defun write-descriptor (descriptor stream)
+  (write-byte (desc-hash-code descriptor) stream)
+  (write-byte (desc-length descriptor) stream)
+  (write-byte (ldb +whole-index-low-byte+ (desc-string-index descriptor))
+              stream)
+  (write-byte (ldb +whole-index-high-byte+ (desc-string-index descriptor))
+              stream)
+  (write-byte (desc-flags descriptor) stream)
+  (values))
+
+(defun write-dictionary (filename dictionary entry-count string-table-length)
+  (declare (fixnum string-table-length))
+  (with-open-file (s filename
+                     :direction :output
+                     :element-type '(unsigned-byte 16)
+                     :if-exists :overwrite
+                     :if-does-not-exist :create)
+    (write-byte +magic-file-id+ s)
+    (write-byte +new-dictionary-size+ s)
+    (write-byte entry-count s)
+    (write-byte (ldb +whole-index-low-byte+ string-table-length) s)
+    (write-byte (ldb +whole-index-high-byte+ string-table-length) s)
+    (dotimes (i +new-dictionary-size+)
+      (write-byte (aref (descriptor-table dictionary) i) s))
+    (dotimes (i entry-count)
+      ;; hack, because the 0th element goes unused.  see if we can
+      ;; fix this assumption in the code elsewhere
+      (unless (zerop i)
+        (write-descriptor (aref (descriptors dictionary) i) s)))
+    (with-open-file (s filename
+                       :direction :output
+                       :element-type 'base-char
+                       :if-exists :append)
+      (write-string (string-table dictionary)
+                    s :end string-table-length))))
+
+(defun read-dictionary (&optional (filename default-binary-dictionary))
+  (with-open-file (stream filename
+                          :direction :input
+                          :if-does-not-exist :error
+                          :element-type '(unsigned-byte 16))
+    (let* ((header (make-array 5 :element-type '(unsigned-byte 16)))
+           (header-len (read-sequence header stream)))
+      (unless (= header-len 5)
+        (error "File is not a dictionary: ~S." filename))
+      (unless (= (aref header 0) +magic-file-id+)
+        (error "File is not a dictionary: ~S." filename))
+      (let* ((dict-size (read-byte stream))
+             (entry-count (read-byte stream))
+             (string-table-length-low (read-byte stream))
+             (string-table-length-high (read-byte stream))
+             (string-table-length (dpb string-table-length-high
+                                       +whole-index-high-byte+
+                                       string-table-length-low))
+             (word-table (make-array dict-size
+                                     :element-type '(unsigned-byte 16)))
+             (descriptors (make-array (1+ entry-count)
+                                      :initial-element nil))
+             (string-table (make-array string-table-length
+                                       :element-type 'base-char)))
+        (read-sequence word-table stream)
+        (dotimes (i entry-count)
+          (setf (aref descriptors (1+ i)) (read-descriptor stream)))
+        (with-open-file (s filename
+                           :direction :input
+                           :if-does-not-exist :error
+                           :element-type 'base-char)
+          ;; ??? is this portable?
+          (file-position s (file-position stream))
+          (read-sequence string-table s))
+        (make-instance 'dictionary
+                       :string-table string-table
+                       :descriptors descriptors
+                       :descriptor-table word-table)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/package.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/package.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/package.lisp	(revision 13309)
@@ -0,0 +1,7 @@
+(defpackage "SPELL"
+  (:use "COMMON-LISP")
+  (:export #:spell-try-word #:spell-root-word #:spell-collect-close-words
+	   #:correct-spelling
+           #:+max-entry-length+
+	   #:spell-read-dictionary #:spell-add-entry #:spell-root-flags
+	   #:spell-remove-entry))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell-aug.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell-aug.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell-aug.lisp	(revision 13309)
@@ -0,0 +1,181 @@
+; -*- Log: hemlock.log; Package: Spell -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;    Designed by Bill Chiles and Rob Maclachlan
+;;;
+;;; This file contains the code to grow the spelling dictionary in system
+;;; space by reading a text file of entries or adding one at a time.  This
+;;; code relies on implementation dependent code found in Spell-RT.Lisp.
+
+
+(in-package "SPELL")
+
+
+
+;;;; String and Hashing Macros
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro string-table-replace (src-string dst-start length)
+  `(sap-replace *string-table* ,src-string 0 ,dst-start (+ ,dst-start ,length)))
+
+;;; HASH-ENTRY is used in SPELL-ADD-ENTRY to find a dictionary location for
+;;; adding a new entry.  If a location contains a zero, then it has never been
+;;; used, and no entries have ever been "hashed past" it.  If a location
+;;; contains SPELL-DELETED-ENTRY, then it once contained an entry that has
+;;; since been deleted.
+;;;
+(defmacro hash-entry (entry entry-len)
+  (let ((loop-loc (gensym)) (loc-contents (gensym))
+	(hash (gensym)) (loc (gensym)))
+    `(let* ((,hash (string-hash ,entry ,entry-len))
+	    (,loc (rem ,hash (the fixnum *dictionary-size*)))
+	    (,loc-contents (dictionary-ref ,loc)))
+       (declare (fixnum ,loc ,loc-contents))
+       (if (or (zerop ,loc-contents) (= ,loc-contents spell-deleted-entry))
+	   ,loc
+	   (hash2-loop (,loop-loc ,loc-contents) ,loc ,hash
+	     ,loop-loc nil t)))))
+
+) ;eval-when
+
+
+
+
+;;;; Top Level Stuff
+
+(defun spell-read-dictionary (dictionary filename)
+  "Add entries to DICTIONARY from lines in the file FILENAME."
+  (with-open-file (s filename :direction :input)
+    (loop (multiple-value-bind (entry eofp) (read-line s nil nil)
+	    (declare (type (or simple-string null) entry))
+	    (unless entry (return))
+	    (spell-add-entry entry)
+	    (if eofp (return))))))
+
+
+(defun spell-add-entry (dictionary line &optional
+                                   (word-end (or (position #\/ line :test #'char=)
+                                                 (length line))))
+  "Line is of the form \"entry/flag1/flag2\" or \"entry\".  It is parsed and
+   added to the spelling dictionary.  Line is destructively modified."
+  (declare (simple-string line) (fixnum word-end))
+  (nstring-upcase line :end word-end)
+  (when (> word-end max-entry-length)
+    (return-from spell-add-entry nil))
+  (let ((entry (lookup-entry line word-end)))
+    (when entry
+      (add-flags (+ entry 2) line word-end)
+      (return-from spell-add-entry nil)))
+  (let* ((hash-loc (hash-entry line word-end))
+	 (string-ptr *string-table-size*)
+	 (desc-ptr *descriptors-size*)
+	 (desc-ptr+1 (1+ desc-ptr))
+	 (desc-ptr+2 (1+ desc-ptr+1)))
+    (declare (fixnum string-ptr))
+    (when (not hash-loc) (error "Dictionary Overflow!"))
+    (when (> 3 *free-descriptor-elements*) (grow-descriptors))
+    (when (> word-end *free-string-table-bytes*) (grow-string-table))
+    (decf *free-descriptor-elements* 3)
+    (incf *descriptors-size* 3)
+    (decf *free-string-table-bytes* word-end)
+    (incf *string-table-size* word-end)
+    (setf (dictionary-ref hash-loc) desc-ptr)
+    (let ((desc (make-descriptor :hash-code (ldb new-hash-byte
+                                                 (string-hash line word-end))
+                                 :length word-end
+                                 :string-index string-ptr
+                                 :flags (word-flags line word-end))))
+    (add-flags desc-ptr+2 line word-end)
+    (string-table-replace line string-ptr word-end))
+  t)
+
+;;; SPELL-REMOVE-ENTRY destructively uppercases entry in removing it from
+;;; the dictionary.  First entry is looked up, and if it is found due to a
+;;; flag, the flag is cleared in the descriptor table.  If entry is a root
+;;; word in the dictionary (that is, looked up without the use of a flag),
+;;; then the root and all its derivitives are deleted by setting its
+;;; dictionary location to spell-deleted-entry.
+;;; 
+(defun spell-remove-entry (dictionary entry)
+  "Removes ENTRY from DICTIONARY, so it will be an unknown word.  Entry
+   is a simple string and is destructively modified.  If entry is a root
+   word, then all words derived with entry and its flags will also be deleted."
+  (declare (simple-string entry))
+  (nstring-upcase entry)
+  (let ((entry-len (length entry)))
+    (declare (fixnum entry-len))
+    (when (<= 2 entry-len max-entry-length)
+      (multiple-value-bind (index flagp)
+			   (spell-try-word entry entry-len)
+	(when index
+	  (if flagp
+	      (setf (descriptor-ref (+ 2 index))
+		    (logandc2 (descriptor-ref (+ 2 index)) flagp))
+	      (let* ((hash (string-hash entry entry-len))
+		     (hash-and-len (dpb (the fixnum (ldb new-hash-byte hash))
+					stored-hash-byte
+					(the fixnum entry-len)))
+		     (loc (rem hash (the fixnum *dictionary-size*)))
+		     (loc-contents (dictionary-ref loc)))
+		(declare (fixnum hash hash-and-len loc))
+		(cond ((zerop loc-contents) nil)
+		      ((found-entry-p loc-contents entry entry-len hash-and-len)
+		       (setf (dictionary-ref loc) spell-deleted-entry))
+		      (t
+		       (hash2-loop (loop-loc loc-contents) loc hash
+				   nil
+				   (when (found-entry-p loc-contents entry
+							entry-len hash-and-len)
+				     (setf (dictionary-ref loop-loc)
+					   spell-deleted-entry)
+				     (return spell-deleted-entry))))))))))))
+
+(defun spell-root-flags (dictionary index)
+  "Return the flags associated with the root word corresponding to a
+   dictionary entry at index."
+  (let* ((descriptor (descriptor-ref dictionary index))
+         (desc-flags (desc-flags descriptor)))
+    (loop for element in flag-names-to-masks
+          unless (zerop (logand (cdr element) desc-flags))
+          collect (car element))))
+
+
+
+;;;; Growing Dictionary Structures
+
+;;; GROW-DESCRIPTORS grows the descriptors vector by 10%.
+;;;
+(defun grow-descriptors (dictionary)
+  (let* ((old-size (+ (the fixnum *descriptors-size*)
+		      (the fixnum *free-descriptor-elements*)))
+	 (new-size (truncate (* old-size 1.1)))
+	 (new-bytes (* new-size 2))
+	 (new-sap (allocate-bytes new-bytes)))
+    (declare (fixnum new-size old-size))
+    (sap-replace new-sap *descriptors* 0 0
+		 (* 2 (the fixnum *descriptors-size*)))
+    (deallocate-bytes (system-address *descriptors*) (* 2 old-size))
+    (setf *free-descriptor-elements*
+	  (- new-size (the fixnum *descriptors-size*)))
+    (setf *descriptors* new-sap)))
+
+;;; GROW-STRING-TABLE grows the string table by 10%.
+;;;
+(defun grow-string-table (dictionary)
+  (let* ((old-size (+ (the fixnum *string-table-size*)
+		      (the fixnum *free-string-table-bytes*)))
+	 (new-size (truncate (* old-size 1.1)))
+	 (new-sap (allocate-bytes new-size)))
+    (declare (fixnum new-size old-size))
+    (sap-replace new-sap *string-table* 0 0 *string-table-size*)
+    (setf *free-string-table-bytes*
+	  (- new-size (the fixnum *string-table-size*)))
+    (deallocate-bytes (system-address *string-table*) old-size)
+    (setf *string-table* new-sap)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell-dictionary.text
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell-dictionary.text	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell-dictionary.text	(revision 13309)
@@ -0,0 +1,15505 @@
+AAAI
+ABACK
+ABAFT
+ABANDON/D/G/S
+ABANDONMENT
+ABASE/D/G/S
+ABASEMENT/S
+ABASH/D/G/S
+ABATE/D/R/G/S
+ABATEMENT/S
+ABBE
+ABBEY/M/S
+ABBOT/M/S
+ABBREVIATE/D/G/N/X/S
+ABDOMEN/M/S
+ABDOMINAL
+ABDUCT/D/S
+ABDUCTION/M/S
+ABDUCTOR/M/S
+ABED
+ABERRANT
+ABERRATION/S
+ABET/S
+ABETTED
+ABETTER
+ABETTING
+ABETTOR
+ABEYANCE
+ABHOR/S
+ABHORRED
+ABHORRENT
+ABHORRER
+ABHORRING
+ABIDE/D/G/S
+ABILITY/M/S
+ABJECT/P/Y
+ABJECTION/S
+ABJURE/D/G/S
+ABLATE/D/G/N/V/S
+ABLAZE
+ABLE/T/R
+ABLUTE
+ABLY
+ABNORMAL/Y
+ABNORMALITY/S
+ABOARD
+ABODE/M/S
+ABOLISH/D/R/Z/G/S
+ABOLISHMENT/M/S
+ABOLITION
+ABOLITIONIST/S
+ABOMINABLE
+ABORIGINAL
+ABORIGINE/M/S
+ABORT/D/G/V/S
+ABORTION/M/S
+ABORTIVE/Y
+ABOUND/D/G/S
+ABOUT
+ABOVE
+ABOVEGROUND
+ABRADE/D/G/S
+ABRASION/M/S
+ABREACTION/S
+ABREAST
+ABRIDGE/D/G/S
+ABRIDGMENT
+ABROAD
+ABROGATE/D/G/S
+ABRUPT/P/Y
+ABSCESS/D/S
+ABSCISSA/M/S
+ABSCOND/D/G/S
+ABSENCE/M/S
+ABSENT/D/G/Y/S
+ABSENTEE/M/S
+ABSENTEEISM
+ABSENTIA
+ABSENTMINDED
+ABSINTHE
+ABSOLUTE/P/N/Y/S
+ABSOLVE/D/G/S
+ABSORB/D/R/G/S
+ABSORBENCY
+ABSORBENT
+ABSORPTION/M/S
+ABSORPTIVE
+ABSTAIN/D/R/G/S
+ABSTENTION/S
+ABSTINENCE
+ABSTRACT/P/D/G/Y/S
+ABSTRACTION/M/S
+ABSTRACTIONISM
+ABSTRACTIONIST
+ABSTRACTOR/M/S
+ABSTRUSE/P
+ABSURD/Y
+ABSURDITY/M/S
+ABUNDANCE
+ABUNDANT/Y
+ABUSE/D/G/V/S
+ABUT/S
+ABUTMENT
+ABUTTED
+ABUTTER/M/S
+ABUTTING
+ABYSMAL/Y
+ABYSS/M/S
+ACACIA
+ACADEMIA
+ACADEMIC/S
+ACADEMICALLY
+ACADEMY/M/S
+ACCEDE/D/S
+ACCELERATE/D/G/N/X/S
+ACCELERATOR/S
+ACCELEROMETER/M/S
+ACCENT/D/G/S
+ACCENTUAL
+ACCENTUATE/D/G/N/S
+ACCEPT/D/R/Z/G/S
+ACCEPTABILITY
+ACCEPTABLE
+ACCEPTABLY
+ACCEPTANCE/M/S
+ACCEPTOR/M/S
+ACCESS/D/G/S
+ACCESSIBILITY
+ACCESSIBLE
+ACCESSIBLY
+ACCESSION/M/S
+ACCESSOR/M/S
+ACCESSORY/M/S
+ACCIDENT/M/S
+ACCIDENTAL/Y
+ACCLAIM/D/G/S
+ACCLAMATION
+ACCLIMATE/D/G/S
+ACCLIMATIZATION
+ACCLIMATIZED
+ACCOLADE/S
+ACCOMMODATE/D/G/N/X/S
+ACCOMPANIMENT/M/S
+ACCOMPANIST/M/S
+ACCOMPANY/D/G/S
+ACCOMPLICE/S
+ACCOMPLISH/D/R/Z/G/S
+ACCOMPLISHMENT/M/S
+ACCORD/D/R/Z/G/S
+ACCORDANCE
+ACCORDINGLY
+ACCORDION/M/S
+ACCOST/D/G/S
+ACCOUNT/D/G/S
+ACCOUNTABILITY
+ACCOUNTABLE
+ACCOUNTABLY
+ACCOUNTANCY
+ACCOUNTANT/M/S
+ACCOUTREMENT/S
+ACCREDIT/D
+ACCREDITATION/S
+ACCRETION/M/S
+ACCRUE/D/G/S
+ACCULTURATE/D/G/N/S
+ACCUMULATE/D/G/N/X/S
+ACCUMULATOR/M/S
+ACCURACY/S
+ACCURATE/P/Y
+ACCURSED
+ACCUSAL
+ACCUSATION/M/S
+ACCUSATIVE
+ACCUSE/D/R/G/S
+ACCUSINGLY
+ACCUSTOM/D/G/S
+ACE/M/S
+ACETATE
+ACETONE
+ACETYLENE
+ACHE/D/G/S
+ACHIEVABLE
+ACHIEVE/D/R/Z/G/S
+ACHIEVEMENT/M/S
+ACHILLES
+ACID/Y/S
+ACIDIC
+ACIDITY/S
+ACIDULOUS
+ACKNOWLEDGE/D/R/Z/G/S
+ACKNOWLEDGMENT/M/S
+ACM
+ACME
+ACNE
+ACOLYTE/S
+ACORN/M/S
+ACOUSTIC/S
+ACOUSTICAL/Y
+ACOUSTICIAN
+ACQUAINT/D/G/S
+ACQUAINTANCE/M/S
+ACQUIESCE/D/G/S
+ACQUIESCENCE
+ACQUIRABLE
+ACQUIRE/D/G/S
+ACQUISITION/M/S
+ACQUISITIVENESS
+ACQUIT/S
+ACQUITTAL
+ACQUITTED
+ACQUITTER
+ACQUITTING
+ACRE/M/S
+ACREAGE
+ACRID
+ACRIMONIOUS
+ACRIMONY
+ACROBAT/M/S
+ACROBATIC/S
+ACRONYM/M/S
+ACROPOLIS
+ACROSS
+ACRYLIC
+ACT/D/G/V/S
+ACTINIUM
+ACTINOMETER/S
+ACTION/M/S
+ACTIVATE/D/G/N/X/S
+ACTIVATOR/M/S
+ACTIVELY
+ACTIVISM
+ACTIVIST/M/S
+ACTIVITY/M/S
+ACTOR/M/S
+ACTRESS/M/S
+ACTUAL/Y/S
+ACTUALITY/S
+ACTUALIZATION
+ACTUARIAL/Y
+ACTUATE/D/G/S
+ACTUATOR/M/S
+ACUITY
+ACUMEN
+ACUTE/P/Y
+ACYCLIC
+ACYCLICALLY
+AD
+ADAGE/S
+ADAGIO/S
+ADAMANT/Y
+ADAPT/D/R/Z/G/V/S
+ADAPTABILITY
+ADAPTABLE
+ADAPTATION/M/S
+ADAPTIVELY
+ADAPTOR/S
+ADD/D/R/Z/G/S
+ADDENDA
+ADDENDUM
+ADDICT/D/G/S
+ADDICTION/M/S
+ADDISON
+ADDITION/M/S
+ADDITIONAL/Y
+ADDITIVE/M/S
+ADDITIVITY
+ADDRESS/D/R/Z/G/S
+ADDRESSABILITY
+ADDRESSABLE
+ADDRESSEE/M/S
+ADDUCE/D/G/S
+ADDUCIBLE
+ADDUCT/D/G/S
+ADDUCTION
+ADDUCTOR
+ADEPT
+ADEQUACY/S
+ADEQUATE/Y
+ADHERE/D/R/Z/G/S
+ADHERENCE
+ADHERENT/M/S
+ADHESION/S
+ADHESIVE/M/S
+ADIABATIC
+ADIABATICALLY
+ADIEU
+ADJACENCY
+ADJACENT
+ADJECTIVE/M/S
+ADJOIN/D/G/S
+ADJOURN/D/G/S
+ADJOURNMENT
+ADJUDGE/D/G/S
+ADJUDICATE/D/G/S
+ADJUDICATION/M/S
+ADJUNCT/M/S
+ADJURE/D/G/S
+ADJUST/D/R/Z/G/S
+ADJUSTABLE
+ADJUSTABLY
+ADJUSTMENT/M/S
+ADJUSTOR/M/S
+ADJUTANT/S
+ADMINISTER/D/G/J/S
+ADMINISTRATION/M/S
+ADMINISTRATIVE/Y
+ADMINISTRATOR/M/S
+ADMIRABLE
+ADMIRABLY
+ADMIRAL/M/S
+ADMIRALTY
+ADMIRATION/S
+ADMIRE/D/R/Z/G/S
+ADMIRING/Y
+ADMISSIBILITY
+ADMISSIBLE
+ADMISSION/M/S
+ADMIT/S
+ADMITTANCE
+ADMITTED/Y
+ADMITTER/S
+ADMITTING
+ADMIX/D/S
+ADMIXTURE
+ADMONISH/D/G/S
+ADMONISHMENT/M/S
+ADMONITION/M/S
+ADO
+ADOBE
+ADOLESCENCE
+ADOLESCENT/M/S
+ADOPT/D/R/Z/G/V/S
+ADOPTION/M/S
+ADORABLE
+ADORATION
+ADORE/D/S
+ADORN/D/S
+ADORNMENT/M/S
+ADRENAL
+ADRENALINE
+ADRIFT
+ADROIT/P
+ADS
+ADSORB/D/G/S
+ADSORPTION
+ADULATION
+ADULT/M/S
+ADULTERATE/D/G/S
+ADULTERER/M/S
+ADULTEROUS/Y
+ADULTERY
+ADULTHOOD
+ADUMBRATE/D/G/S
+ADVANCE/D/G/S
+ADVANCEMENT/M/S
+ADVANTAGE/D/S
+ADVANTAGEOUS/Y
+ADVENT
+ADVENTIST/S
+ADVENTITIOUS
+ADVENTURE/D/R/Z/G/S
+ADVENTUROUS
+ADVERB/M/S
+ADVERBIAL
+ADVERSARY/M/S
+ADVERSE/Y
+ADVERSITY/S
+ADVERTISE/D/R/Z/G/S
+ADVERTISEMENT/M/S
+ADVICE
+ADVISABILITY
+ADVISABLE
+ADVISABLY
+ADVISE/D/R/Z/G/S
+ADVISEDLY
+ADVISEE/M/S
+ADVISEMENT/S
+ADVISOR/M/S
+ADVISORY
+ADVOCACY
+ADVOCATE/D/G/S
+AEGIS
+AERATE/D/G/N/S
+AERATOR/S
+AERIAL/M/S
+AEROACOUSTIC
+AEROBIC/S
+AERODYNAMIC/S
+AERONAUTIC/S
+AERONAUTICAL
+AEROSOL/S
+AEROSOLIZE
+AEROSPACE
+AESTHETIC/M/S
+AESTHETICALLY
+AFAR
+AFFABLE
+AFFAIR/M/S
+AFFECT/D/G/V/S
+AFFECTATION/M/S
+AFFECTINGLY
+AFFECTION/M/S
+AFFECTIONATE/Y
+AFFECTOR
+AFFERENT
+AFFIANCED
+AFFIDAVIT/M/S
+AFFILIATE/D/G/N/X/S
+AFFINITY/M/S
+AFFIRM/D/G/S
+AFFIRMATION/M/S
+AFFIRMATIVE/Y
+AFFIX/D/G/S
+AFFLICT/D/G/V/S
+AFFLICTION/M/S
+AFFLUENCE
+AFFLUENT
+AFFORD/D/G/S
+AFFORDABLE
+AFFRICATE/S
+AFFRIGHT
+AFFRONT/D/G/S
+AFGHAN/S
+AFGHANISTAN
+AFICIONADO
+AFIELD
+AFIRE
+AFLAME
+AFLOAT
+AFOOT
+AFORE
+AFOREMENTIONED
+AFORESAID
+AFORETHOUGHT
+AFOSR
+AFOUL
+AFRAID
+AFRESH
+AFRICA
+AFRICAN/S
+AFT/R
+AFTEREFFECT
+AFTERMATH
+AFTERMOST
+AFTERNOON/M/S
+AFTERSHOCK/S
+AFTERTHOUGHT/S
+AFTERWARD/S
+AGAIN
+AGAINST
+AGAPE
+AGAR
+AGATE/S
+AGE/D/R/Z/G/S
+AGELESS
+AGENCY/M/S
+AGENDA/M/S
+AGENT/M/S
+AGGLOMERATE/D/N/S
+AGGLUTINATE/D/G/N/S
+AGGLUTININ/S
+AGGRAVATE/D/N/S
+AGGREGATE/D/G/N/X/Y/S
+AGGRESSION/M/S
+AGGRESSIVE/P/Y
+AGGRESSOR/S
+AGGRIEVE/D/G/S
+AGHAST
+AGILE/Y
+AGILITY
+AGITATE/D/G/N/X/S
+AGITATOR/M/S
+AGLEAM
+AGLOW
+AGNOSTIC/M/S
+AGO
+AGOG
+AGONIZE/D/G/S
+AGONY/S
+AGRARIAN
+AGREE/D/R/Z/S
+AGREEABLE/P
+AGREEABLY
+AGREEING
+AGREEMENT/M/S
+AGRICULTURAL/Y
+AGRICULTURE
+AGUE
+AH
+AHEAD
+AI
+AID/D/G/S
+AIDE/D/G/S
+AIL/G
+AILERON/S
+AILMENT/M/S
+AIM/D/R/Z/G/S
+AIMLESS/Y
+AIR/D/R/Z/G/J/S
+AIRBAG/S
+AIRBORNE
+AIRCRAFT
+AIRDROP/S
+AIREDALE
+AIRFIELD/M/S
+AIRFLOW
+AIRFOIL/S
+AIRFRAME/S
+AIRILY
+AIRLESS
+AIRLIFT/M/S
+AIRLINE/R/S
+AIRLOCK/M/S
+AIRMAIL/S
+AIRMAN
+AIRMEN
+AIRPLANE/M/S
+AIRPORT/M/S
+AIRSHIP/M/S
+AIRSPACE
+AIRSPEED
+AIRSTRIP/M/S
+AIRWAY/M/S
+AIRY
+AISLE
+AJAR
+AKIMBO
+AKIN
+AL/M
+ALABAMA
+ALABAMIAN
+ALABASTER
+ALACRITY
+ALARM/D/G/S
+ALARMINGLY
+ALARMIST
+ALAS
+ALASKA
+ALBA
+ALBACORE
+ALBANIA
+ALBANIAN/S
+ALBEIT
+ALBUM/S
+ALBUMIN
+ALCHEMY
+ALCIBIADES
+ALCOHOL/M/S
+ALCOHOLIC/M/S
+ALCOHOLISM
+ALCOVE/M/S
+ALDEN
+ALDER
+ALDERMAN/M
+ALDERMEN
+ALE/V
+ALEE
+ALERT/P/D/R/Z/G/Y/S
+ALERTEDLY
+ALEXANDER/M
+ALFALFA
+ALFRED/M
+ALFRESCO
+ALGA
+ALGAE
+ALGAECIDE
+ALGEBRA/M/S
+ALGEBRAIC
+ALGEBRAICALLY
+ALGERIA
+ALGERIAN
+ALGINATE
+ALGOL
+ALGORITHM/M/S
+ALGORITHMIC
+ALGORITHMICALLY
+ALIAS/D/G/S
+ALIBI/M/S
+ALIEN/M/S
+ALIENATE/D/G/N/S
+ALIGHT
+ALIGN/D/G/S
+ALIGNMENT/S
+ALIKE
+ALIMENT/S
+ALIMONY
+ALKALI/M/S
+ALKALINE
+ALKALOID/M/S
+ALKYL
+ALL
+ALLAH/M
+ALLAY/D/G/S
+ALLEGATION/M/S
+ALLEGE/D/G/S
+ALLEGEDLY
+ALLEGIANCE/M/S
+ALLEGORIC
+ALLEGORICAL/Y
+ALLEGORY/M/S
+ALLEGRETTO/M/S
+ALLEGRO/M/S
+ALLELE/S
+ALLEMANDE
+ALLEN/M
+ALLERGIC
+ALLERGY/M/S
+ALLEVIATE/D/R/Z/G/N/S
+ALLEY/M/S
+ALLEYWAY/M/S
+ALLIANCE/M/S
+ALLIGATOR/M/S
+ALLITERATION/M/S
+ALLITERATIVE
+ALLOCATE/D/G/N/X/S
+ALLOCATOR/M/S
+ALLOPHONE/S
+ALLOPHONIC
+ALLOT/S
+ALLOTMENT/M/S
+ALLOTTED
+ALLOTTER
+ALLOTTING
+ALLOW/D/G/S
+ALLOWABLE
+ALLOWABLY
+ALLOWANCE/M/S
+ALLOY/M/S
+ALLUDE/D/G/S
+ALLURE/G
+ALLUREMENT
+ALLUSION/M/S
+ALLUSIVE/P
+ALLY/D/G/S
+ALMA
+ALMANAC/M/S
+ALMIGHTY
+ALMOND/M/S
+ALMONER
+ALMOST
+ALMS
+ALMSMAN
+ALNICO
+ALOE/S
+ALOFT
+ALOHA
+ALONE/P
+ALONG
+ALONGSIDE
+ALOOF/P
+ALOUD
+ALPHA
+ALPHABET/M/S
+ALPHABETIC/S
+ALPHABETICAL/Y
+ALPHABETIZE/D/G/S
+ALPHANUMERIC
+ALPINE
+ALPS
+ALREADY
+ALSO
+ALTAR/M/S
+ALTER/D/R/Z/G/S
+ALTERABLE
+ALTERATION/M/S
+ALTERCATION/M/S
+ALTERNATE/D/G/N/X/V/Y/S
+ALTERNATIVE/Y/S
+ALTERNATOR/M/S
+ALTHOUGH
+ALTITUDE/S
+ALTMODE
+ALTO/M/S
+ALTOGETHER
+ALTRUISM
+ALTRUIST
+ALTRUISTIC
+ALTRUISTICALLY
+ALUM
+ALUMINUM
+ALUMNA/M
+ALUMNAE
+ALUMNI
+ALUMNUS
+ALUNDUM
+ALVEOLAR
+ALVEOLI
+ALVEOLUS
+ALWAYS
+ALZHEIMER/M
+AM/N
+AMAIN
+AMALGAM/M/S
+AMALGAMATE/D/G/N/S
+AMANUENSIS
+AMASS/D/G/S
+AMATEUR/M/S
+AMATEURISH/P
+AMATEURISM
+AMATORY
+AMAZE/D/R/Z/G/S
+AMAZEDLY
+AMAZEMENT
+AMAZING/Y
+AMAZON/M/S
+AMBASSADOR/M/S
+AMBER
+AMBIANCE
+AMBIDEXTROUS/Y
+AMBIENT
+AMBIGUITY/M/S
+AMBIGUOUS/Y
+AMBITION/M/S
+AMBITIOUS/Y
+AMBIVALENCE
+AMBIVALENT/Y
+AMBLE/D/R/G/S
+AMBROSIAL
+AMBULANCE/M/S
+AMBULATORY
+AMBUSCADE
+AMBUSH/D/S
+AMDAHL/M
+AMELIA
+AMELIORATE/D/G
+AMENABLE
+AMEND/D/G/S
+AMENDMENT/M/S
+AMENITY/S
+AMENORRHEA
+AMERICA/M/S
+AMERICAN/M/S
+AMERICANA
+AMERICIUM
+AMIABLE
+AMICABLE
+AMICABLY
+AMID
+AMIDE
+AMIDST
+AMIGO
+AMINO
+AMISS
+AMITY
+AMMO
+AMMONIA
+AMMONIAC
+AMMONIUM
+AMMUNITION
+AMNESTY
+AMOEBA/M/S
+AMOK
+AMONG
+AMONGST
+AMORAL
+AMORALITY
+AMORIST
+AMOROUS
+AMORPHOUS/Y
+AMORTIZE/D/G/S
+AMOUNT/D/R/Z/G/S
+AMOUR
+AMP/Y/S
+AMPERE/S
+AMPERSAND/M/S
+AMPHETAMINE/S
+AMPHIBIAN/M/S
+AMPHIBIOUS/Y
+AMPHIBOLOGY
+AMPHITHEATER/M/S
+AMPLE
+AMPLIFY/D/R/Z/G/N/S
+AMPLITUDE/M/S
+AMPOULE/M/S
+AMPUTATE/D/G/S
+AMSTERDAM
+AMTRAK
+AMULET/S
+AMUSE/D/R/Z/G/S
+AMUSEDLY
+AMUSEMENT/M/S
+AMUSINGLY
+AMYL
+AN
+ANABAPTIST/M/S
+ANACHRONISM/M/S
+ANACHRONISTICALLY
+ANACONDA/S
+ANAEROBIC
+ANAESTHESIA
+ANAGRAM/M/S
+ANAL
+ANALOG
+ANALOGICAL
+ANALOGOUS/Y
+ANALOGUE/M/S
+ANALOGY/M/S
+ANALYSES
+ANALYSIS
+ANALYST/M/S
+ANALYTIC
+ANALYTICAL/Y
+ANALYTICITY/S
+ANALYZABLE
+ANALYZE/D/R/Z/G/S
+ANAPHORA
+ANAPHORIC
+ANAPHORICALLY
+ANAPLASMOSIS
+ANARCHIC
+ANARCHICAL
+ANARCHIST/M/S
+ANARCHY
+ANASTOMOSES
+ANASTOMOSIS
+ANASTOMOTIC
+ANATHEMA
+ANATOMIC
+ANATOMICAL/Y
+ANATOMY
+ANCESTOR/M/S
+ANCESTRAL
+ANCESTRY
+ANCHOR/D/G/S
+ANCHORAGE/M/S
+ANCHORITE
+ANCHORITISM
+ANCHOVY/S
+ANCIENT/Y/S
+ANCILLARY
+AND/Z/G
+ANDERSON/M
+ANDORRA
+ANDREW/M
+ANDY/M
+ANECDOTAL
+ANECDOTE/M/S
+ANECHOIC
+ANEMIA
+ANEMIC
+ANEMOMETER/M/S
+ANEMOMETRY
+ANEMONE
+ANESTHESIA
+ANESTHETIC/M/S
+ANESTHETICALLY
+ANESTHETIZE/D/G/S
+ANEW
+ANGEL/M/S
+ANGELIC
+ANGER/D/G/S
+ANGIOGRAPHY
+ANGLE/D/R/Z/G/S
+ANGLICAN/S
+ANGLICANISM
+ANGLOPHILIA
+ANGLOPHOBIA
+ANGOLA
+ANGRILY
+ANGRY/T/R
+ANGST
+ANGSTROM
+ANGUISH/D
+ANGULAR/Y
+ANHYDROUS/Y
+ANILINE
+ANIMAL/M/S
+ANIMATE/P/D/G/N/X/Y/S
+ANIMATEDLY
+ANIMATOR/M/S
+ANIMISM
+ANIMIZED
+ANIMOSITY
+ANION/M/S
+ANIONIC
+ANISE
+ANISEIKONIC
+ANISOTROPIC
+ANISOTROPY
+ANKLE/M/S
+ANNAL/S
+ANNEAL/G
+ANNEX/D/G/S
+ANNEXATION
+ANNIHILATE/D/G/N/S
+ANNIVERSARY/M/S
+ANNOTATE/D/G/N/X/S
+ANNOUNCE/D/R/Z/G/S
+ANNOUNCEMENT/M/S
+ANNOY/D/G/S
+ANNOYANCE/M/S
+ANNOYER/S
+ANNOYINGLY
+ANNUAL/Y/S
+ANNUITY
+ANNUL/S
+ANNULLED
+ANNULLING
+ANNULMENT/M/S
+ANNUM
+ANNUNCIATE/D/G/S
+ANNUNCIATOR/S
+ANODE/M/S
+ANODIZE/D/S
+ANOINT/D/G/S
+ANOMALOUS/Y
+ANOMALY/M/S
+ANOMIC
+ANOMIE
+ANON
+ANONYMITY
+ANONYMOUS/Y
+ANOREXIA
+ANOTHER/M
+ANSI
+ANSWER/D/R/Z/G/S
+ANSWERABLE
+ANT/M/S
+ANTAGONISM/S
+ANTAGONIST/M/S
+ANTAGONISTIC
+ANTAGONISTICALLY
+ANTAGONIZE/D/G/S
+ANTARCTIC
+ANTARCTICA
+ANTE
+ANTEATER/M/S
+ANTECEDENT/M/S
+ANTEDATE
+ANTELOPE/M/S
+ANTENNA/M/S
+ANTENNAE
+ANTERIOR
+ANTHEM/M/S
+ANTHER
+ANTHOLOGY/S
+ANTHONY
+ANTHRACITE
+ANTHROPOLOGICAL/Y
+ANTHROPOLOGIST/M/S
+ANTHROPOLOGY
+ANTHROPOMORPHIC
+ANTHROPOMORPHICALLY
+ANTI
+ANTIBACTERIAL
+ANTIBIOTIC/S
+ANTIBODY/S
+ANTIC/M/S
+ANTICIPATE/D/G/N/X/S
+ANTICIPATORY
+ANTICOAGULATION
+ANTICOMPETITIVE
+ANTIDISESTABLISHMENTARIANISM
+ANTIDOTE/M/S
+ANTIFORMANT
+ANTIFUNDAMENTALIST
+ANTIGEN/M/S
+ANTIHISTORICAL
+ANTIMICROBIAL
+ANTIMONY
+ANTINOMIAN
+ANTINOMY
+ANTIPATHY
+ANTIPHONAL
+ANTIPODE/M/S
+ANTIQUARIAN/M/S
+ANTIQUATE/D
+ANTIQUE/M/S
+ANTIQUITY/S
+ANTIREDEPOSITION
+ANTIRESONANCE
+ANTIRESONATOR
+ANTISEPTIC
+ANTISERA
+ANTISERUM
+ANTISLAVERY
+ANTISOCIAL
+ANTISUBMARINE
+ANTISYMMETRIC
+ANTISYMMETRY
+ANTITHESIS
+ANTITHETICAL
+ANTITHYROID
+ANTITOXIN/M/S
+ANTITRUST
+ANTLER/D
+ANUS
+ANVIL/M/S
+ANXIETY/S
+ANXIOUS/Y
+ANY
+ANYBODY
+ANYHOW
+ANYMORE
+ANYONE
+ANYPLACE
+ANYTHING
+ANYTIME
+ANYWAY
+ANYWHERE
+AORTA
+APACE
+APART
+APARTHEID
+APARTMENT/M/S
+APATHETIC
+APATHY
+APE/D/G/S
+APERIODIC
+APERIODICITY
+APERTURE
+APEX
+APHASIA
+APHASIC
+APHID/M/S
+APHONIC
+APHORISM/M/S
+APHRODITE
+APIARY/S
+APICAL
+APIECE
+APISH
+APLENTY
+APLOMB
+APOCALYPSE
+APOCALYPTIC
+APOCRYPHA
+APOCRYPHAL
+APOGEE/S
+APOLLO
+APOLLONIAN
+APOLOGETIC
+APOLOGETICALLY
+APOLOGIA
+APOLOGIST/M/S
+APOLOGIZE/D/G/S
+APOLOGY/M/S
+APOSTATE
+APOSTLE/M/S
+APOSTOLIC
+APOSTROPHE/S
+APOTHECARY
+APOTHEOSES
+APOTHEOSIS
+APPALACHIA
+APPALACHIAN/S
+APPALL/D/G
+APPALLINGLY
+APPANAGE
+APPARATUS
+APPAREL/D
+APPARENT/Y
+APPARITION/M/S
+APPEAL/D/R/Z/G/S
+APPEALINGLY
+APPEAR/D/R/Z/G/S
+APPEARANCE/S
+APPEASE/D/G/S
+APPEASEMENT
+APPELLANT/M/S
+APPELLATE
+APPEND/D/R/Z/G/S
+APPENDAGE/M/S
+APPENDICES
+APPENDICITIS
+APPENDIX/M/S
+APPERTAIN/S
+APPETITE/M/S
+APPETIZER
+APPETIZING
+APPLAUD/D/G/S
+APPLAUSE
+APPLE/M/S
+APPLEJACK
+APPLIANCE/M/S
+APPLICABILITY
+APPLICABLE
+APPLICANT/M/S
+APPLICATION/M/S
+APPLICATIVE/Y
+APPLICATOR/M/S
+APPLIQUE
+APPLY/D/R/Z/G/N/X/S
+APPOINT/D/R/Z/G/V/S
+APPOINTEE/M/S
+APPOINTMENT/M/S
+APPORTION/D/G/S
+APPORTIONMENT/S
+APPRAISAL/M/S
+APPRAISE/D/R/Z/G/S
+APPRAISINGLY
+APPRECIABLE
+APPRECIABLY
+APPRECIATE/D/G/N/X/V/S
+APPRECIATIVELY
+APPREHEND/D
+APPREHENSIBLE
+APPREHENSION/M/S
+APPREHENSIVE/P/Y
+APPRENTICE/D/S
+APPRENTICESHIP
+APPRISE/D/G/S
+APPROACH/D/R/Z/G/S
+APPROACHABILITY
+APPROACHABLE
+APPROBATE/N
+APPROPRIATE/P/D/G/N/X/Y/S
+APPROPRIATOR/M/S
+APPROVAL/M/S
+APPROVE/D/R/Z/G/S
+APPROVINGLY
+APPROXIMATE/D/G/N/X/Y/S
+APPURTENANCE/S
+APRICOT/M/S
+APRIL
+APRON/M/S
+APROPOS
+APSE
+APSIS
+APT/P/Y
+APTITUDE/S
+AQUA
+AQUARIA
+AQUARIUM
+AQUARIUS
+AQUATIC
+AQUEDUCT/M/S
+AQUEOUS
+AQUIFER/S
+ARAB/M/S
+ARABESQUE
+ARABIA
+ARABIAN/S
+ARABIC
+ARABLE
+ARACHNID/M/S
+ARBITER/M/S
+ARBITRARILY
+ARBITRARY/P
+ARBITRATE/D/G/N/S
+ARBITRATOR/M/S
+ARBOR/M/S
+ARBOREAL
+ARC/D/G/S
+ARCADE/D/M/S
+ARCANE
+ARCH/D/R/Z/G/Y/S
+ARCHAEOLOGICAL
+ARCHAEOLOGIST/M/S
+ARCHAEOLOGY
+ARCHAIC/P
+ARCHAICALLY
+ARCHAISM
+ARCHAIZE
+ARCHANGEL/M/S
+ARCHBISHOP
+ARCHDIOCESE/S
+ARCHENEMY
+ARCHEOLOGICAL
+ARCHEOLOGIST
+ARCHEOLOGY
+ARCHERY
+ARCHETYPE
+ARCHFOOL
+ARCHIPELAGO
+ARCHIPELAGOES
+ARCHITECT/M/S
+ARCHITECTONIC
+ARCHITECTURAL/Y
+ARCHITECTURE/M/S
+ARCHIVAL
+ARCHIVE/D/R/Z/G/S
+ARCHIVIST
+ARCLIKE
+ARCTIC
+ARDENT/Y
+ARDOR
+ARDUOUS/P/Y
+ARE
+AREA/M/S
+AREN'T
+ARENA/M/S
+ARGENTINA
+ARGO/S
+ARGON
+ARGONAUT/S
+ARGOT
+ARGUABLE
+ARGUABLY
+ARGUE/D/R/Z/G/S
+ARGUMENT/M/S
+ARGUMENTATION
+ARGUMENTATIVE
+ARIANISM
+ARIANIST/S
+ARID
+ARIDITY
+ARIES
+ARIGHT
+ARISE/R/G/J/S
+ARISEN
+ARISTOCRACY
+ARISTOCRAT/M/S
+ARISTOCRATIC
+ARISTOCRATICALLY
+ARISTOTELIAN
+ARISTOTLE
+ARITHMETIC/S
+ARITHMETICAL/Y
+ARITHMETIZE/D/S
+ARIZONA
+ARK
+ARKANSAS
+ARM/D/R/Z/G/S
+ARMADILLO/S
+ARMAGEDDON
+ARMAMENT/M/S
+ARMCHAIR/M/S
+ARMENIAN
+ARMFUL
+ARMHOLE
+ARMISTICE
+ARMLOAD
+ARMOR/D/R
+ARMORY
+ARMOUR
+ARMPIT/M/S
+ARMSTRONG
+ARMY/M/S
+AROMA/S
+AROMATIC
+AROSE
+AROUND
+AROUSAL
+AROUSE/D/G/S
+ARPA
+ARPANET
+ARPEGGIO/M/S
+ARRACK
+ARRAIGN/D/G/S
+ARRAIGNMENT/M/S
+ARRANGE/D/R/Z/G/S
+ARRANGEMENT/M/S
+ARRANT
+ARRAY/D/S
+ARREARS
+ARREST/D/R/Z/G/S
+ARRESTINGLY
+ARRESTOR/M/S
+ARRIVAL/M/S
+ARRIVE/D/G/S
+ARROGANCE
+ARROGANT/Y
+ARROGATE/D/G/N/S
+ARROW/D/S
+ARROWHEAD/M/S
+ARROYO/S
+ARSENAL/M/S
+ARSENIC
+ARSINE
+ARSON
+ART/M/S
+ARTEMIS
+ARTERIAL
+ARTERIOLAR
+ARTERIOLE/M/S
+ARTERIOSCLEROSIS
+ARTERY/M/S
+ARTFUL/P/Y
+ARTHOGRAM
+ARTHRITIS
+ARTHROPOD/M/S
+ARTICHOKE/M/S
+ARTICLE/M/S
+ARTICULATE/P/D/G/N/X/Y/S
+ARTICULATOR/S
+ARTICULATORY
+ARTIFACT/M/S
+ARTIFACTUALLY
+ARTIFICE/R/S
+ARTIFICIAL/P/Y
+ARTIFICIALITY/S
+ARTILLERIST
+ARTILLERY
+ARTISAN/M/S
+ARTIST/M/S
+ARTISTIC
+ARTISTICALLY
+ARTISTRY
+ARTLESS
+ARTWORK
+ARYAN
+AS
+ASBESTOS
+ASCEND/D/R/Z/G/S
+ASCENDANCY
+ASCENDANT
+ASCENDENCY
+ASCENDENT
+ASCENSION/S
+ASCENT
+ASCERTAIN/D/G/S
+ASCERTAINABLE
+ASCETIC/M/S
+ASCETICISM
+ASCII
+ASCOT
+ASCRIBABLE
+ASCRIBE/D/G/S
+ASCRIPTION
+ASEPTIC
+ASH/R/N/S
+ASHAMED/Y
+ASHMAN
+ASHORE
+ASHTRAY/M/S
+ASIA
+ASIAN/S
+ASIATIC
+ASIDE
+ASININE
+ASK/D/R/Z/G/S
+ASKANCE
+ASKEW
+ASLEEP
+ASOCIAL
+ASP/N
+ASPARAGUS
+ASPECT/M/S
+ASPERSION/M/S
+ASPHALT
+ASPHYXIA
+ASPIC
+ASPIRANT/M/S
+ASPIRATE/D/G/S
+ASPIRATION/M/S
+ASPIRATOR/S
+ASPIRE/D/G/S
+ASPIRIN/S
+ASS/M/S
+ASSAIL/D/G/S
+ASSAILANT/M/S
+ASSASSIN/M/S
+ASSASSINATE/D/G/N/X/S
+ASSAULT/D/G/S
+ASSAY/D/G
+ASSEMBLAGE/M/S
+ASSEMBLE/D/R/Z/G/S
+ASSEMBLY/M/S
+ASSENT/D/R/G/S
+ASSERT/D/R/Z/G/V/S
+ASSERTION/M/S
+ASSERTIVELY
+ASSERTIVENESS
+ASSESS/D/G/S
+ASSESSMENT/M/S
+ASSESSOR/S
+ASSET/M/S
+ASSIDUITY
+ASSIDUOUS/Y
+ASSIGN/D/R/Z/G/S
+ASSIGNABLE
+ASSIGNEE/M/S
+ASSIGNMENT/M/S
+ASSIMILATE/D/G/N/X/S
+ASSIST/D/G/S
+ASSISTANCE/S
+ASSISTANT/M/S
+ASSISTANTSHIP/S
+ASSOCIATE/D/G/N/X/V/S
+ASSOCIATIONAL
+ASSOCIATIVELY
+ASSOCIATIVITY
+ASSOCIATOR/M/S
+ASSONANCE
+ASSONANT
+ASSORT/D/S
+ASSORTMENT/M/S
+ASSUAGE/D/S
+ASSUME/D/G/S
+ASSUMPTION/M/S
+ASSURANCE/M/S
+ASSURE/D/R/Z/G/S
+ASSUREDLY
+ASSURINGLY
+ASSYRIAN
+ASSYRIOLOGY
+ASTATINE
+ASTER/M/S
+ASTERISK/M/S
+ASTEROID/M/S
+ASTEROIDAL
+ASTHMA
+ASTONISH/D/G/S
+ASTONISHINGLY
+ASTONISHMENT
+ASTOUND/D/G/S
+ASTRAL
+ASTRAY
+ASTRIDE
+ASTRINGENCY
+ASTRINGENT
+ASTRONAUT/M/S
+ASTRONAUTICS
+ASTRONOMER/M/S
+ASTRONOMICAL/Y
+ASTRONOMY
+ASTROPHYSICAL
+ASTROPHYSICS
+ASTUTE/P
+ASUNDER
+ASYLUM
+ASYMMETRIC
+ASYMMETRICALLY
+ASYMMETRY
+ASYMPTOMATICALLY
+ASYMPTOTE/M/S
+ASYMPTOTIC
+ASYMPTOTICALLY
+ASYNCHRONISM
+ASYNCHRONOUS/Y
+ASYNCHRONY
+AT
+ATAVISTIC
+ATE
+ATEMPORAL
+ATHEIST/M/S
+ATHEISTIC
+ATHENA
+ATHENIAN/S
+ATHENS
+ATHEROSCLEROSIS
+ATHLETE/M/S
+ATHLETIC/S
+ATHLETICISM
+ATLANTIC
+ATLAS
+ATMOSPHERE/M/S
+ATMOSPHERIC
+ATOLL/M/S
+ATOM/M/S
+ATOMIC/S
+ATOMICALLY
+ATOMIZATION
+ATOMIZE/D/G/S
+ATONAL/Y
+ATONE/D/S
+ATONEMENT
+ATOP
+ATROCIOUS/Y
+ATROCITY/M/S
+ATROPHIC
+ATROPHY/D/G/S
+ATTACH/D/R/Z/G/S
+ATTACHE/D/G/S
+ATTACHMENT/M/S
+ATTACK/D/R/Z/G/S
+ATTACKABLE
+ATTAIN/D/R/Z/G/S
+ATTAINABLE
+ATTAINABLY
+ATTAINMENT/M/S
+ATTEMPT/D/R/Z/G/S
+ATTEND/D/R/Z/G/S
+ATTENDANCE/M/S
+ATTENDANT/M/S
+ATTENDEE/M/S
+ATTENTION/M/S
+ATTENTIONAL
+ATTENTIONALITY
+ATTENTIVE/P/Y
+ATTENUATE/D/G/N/S
+ATTENUATOR/M/S
+ATTEST/D/G/S
+ATTIC/M/S
+ATTIRE/D/G/S
+ATTITUDE/M/S
+ATTITUDINAL
+ATTORNEY/M/S
+ATTRACT/D/G/V/S
+ATTRACTION/M/S
+ATTRACTIVELY
+ATTRACTIVENESS
+ATTRACTOR/M/S
+ATTRIBUTABLE
+ATTRIBUTE/D/G/N/X/V/S
+ATTRIBUTIVELY
+ATTRITION
+ATTUNE/D/G/S
+ATYPICAL/Y
+AUBURN
+AUCKLAND
+AUCTION
+AUCTIONEER/M/S
+AUDACIOUS/P/Y
+AUDACITY
+AUDIBLE
+AUDIBLY
+AUDIENCE/M/S
+AUDIO
+AUDIOGRAM/M/S
+AUDIOLOGICAL
+AUDIOLOGIST/M/S
+AUDIOLOGY
+AUDIOMETER/S
+AUDIOMETRIC
+AUDIOMETRY
+AUDIT/D/G/S
+AUDITION/D/M/G/S
+AUDITOR/M/S
+AUDITORIUM
+AUDITORY
+AUDUBON
+AUGER/M/S
+AUGHT
+AUGMENT/D/G/S
+AUGMENTATION
+AUGUR/S
+AUGUST/P/Y
+AUGUSTA
+AUNT/M/S
+AURA/M/S
+AURAL/Y
+AUREOLE
+AUREOMYCIN
+AURORA
+AUSCULTATE/D/G/N/X/S
+AUSPICE/S
+AUSPICIOUS/Y
+AUSTERE/Y
+AUSTERITY
+AUSTIN
+AUSTRALIA
+AUSTRALIAN
+AUSTRIA
+AUSTRIAN
+AUTHENTIC
+AUTHENTICALLY
+AUTHENTICATE/D/G/N/X/S
+AUTHENTICATOR/S
+AUTHENTICITY
+AUTHOR/D/G/S
+AUTHORITARIAN
+AUTHORITARIANISM
+AUTHORITATIVE/Y
+AUTHORITY/M/S
+AUTHORIZATION/M/S
+AUTHORIZE/D/R/Z/G/S
+AUTHORSHIP
+AUTISM
+AUTISTIC
+AUTO/M/S
+AUTOBIOGRAPHIC
+AUTOBIOGRAPHICAL
+AUTOBIOGRAPHY/M/S
+AUTOCOLLIMATOR
+AUTOCORRELATE/N
+AUTOCRACY/S
+AUTOCRAT/M/S
+AUTOCRATIC
+AUTOCRATICALLY
+AUTOFLUORESCENCE
+AUTOGRAPH/D/G
+AUTOGRAPHS
+AUTOMATA
+AUTOMATE/D/G/N/S
+AUTOMATIC
+AUTOMATICALLY
+AUTOMATON
+AUTOMOBILE/M/S
+AUTOMOTIVE
+AUTONAVIGATOR/M/S
+AUTONOMIC
+AUTONOMOUS/Y
+AUTONOMY
+AUTOPILOT/M/S
+AUTOPSY/D/S
+AUTOREGRESSIVE
+AUTOSUGGESTIBILITY
+AUTOTRANSFORMER
+AUTUMN/M/S
+AUTUMNAL
+AUXILIARY/S
+AVAIL/D/R/Z/G/S
+AVAILABILITY/S
+AVAILABLE
+AVAILABLY
+AVALANCHE/D/G/S
+AVANT
+AVARICE
+AVARICIOUS/Y
+AVE
+AVENGE/D/R/G/S
+AVENUE/M/S
+AVER/S
+AVERAGE/D/G/S
+AVERRED
+AVERRER
+AVERRING
+AVERSE/N
+AVERSION/M/S
+AVERT/D/G/S
+AVIAN
+AVIARY/S
+AVIATION
+AVIATOR/M/S
+AVID/Y
+AVIDITY
+AVIONIC/S
+AVOCADO/S
+AVOCATION/M/S
+AVOID/D/R/Z/G/S
+AVOIDABLE
+AVOIDABLY
+AVOIDANCE
+AVOUCH
+AVOW/D/S
+AWAIT/D/G/S
+AWAKE/G/S
+AWAKEN/D/G/S
+AWARD/D/R/Z/G/S
+AWARE/P
+AWASH
+AWAY
+AWE/D
+AWESOME
+AWFUL/P/Y
+AWHILE
+AWKWARD/P/Y
+AWL/M/S
+AWNING/M/S
+AWOKE
+AWRY
+AX/D/R/Z/G/S
+AXE/D/S
+AXIAL/Y
+AXIOLOGICAL
+AXIOM/M/S
+AXIOMATIC
+AXIOMATICALLY
+AXIOMATIZATION/M/S
+AXIOMATIZE/D/G/S
+AXIS
+AXLE/M/S
+AXOLOTL/M/S
+AXON/M/S
+AYE/S
+AZALEA/M/S
+AZIMUTH/M
+AZIMUTHS
+AZURE
+BABBLE/D/G/S
+BABE/M/S
+BABEL/M
+BABY/D/G/S
+BABYHOOD
+BABYISH
+BACCALAUREATE
+BACH/M
+BACHELOR/M/S
+BACILLI
+BACILLUS
+BACK/D/R/Z/G/S
+BACKACHE/M/S
+BACKARROW/S
+BACKBEND/M/S
+BACKBONE/M/S
+BACKDROP/M/S
+BACKGAMMON
+BACKGROUND/M/S
+BACKLASH
+BACKLOG/M/S
+BACKPACK/M/S
+BACKPLANE/M/S
+BACKPOINTER/M/S
+BACKPROPAGATE/D/G/N/X/S
+BACKSCATTER/D/G/S
+BACKSLASH/S
+BACKSPACE/D/S
+BACKSTAGE
+BACKSTAIRS
+BACKSTITCH/D/G/S
+BACKTRACK/D/R/Z/G/S
+BACKUP/S
+BACKWARD/P/S
+BACKWATER/M/S
+BACKWOODS
+BACKYARD/M/S
+BACON
+BACTERIA
+BACTERIAL
+BACTERIUM
+BAD/P/Y
+BADE
+BADGE/R/Z/S
+BADGER'S
+BADGERED
+BADGERING
+BADLANDS
+BADMINTON
+BAFFLE/D/R/Z/G
+BAG/M/S
+BAGATELLE/M/S
+BAGEL/M/S
+BAGGAGE
+BAGGED
+BAGGER/M/S
+BAGGING
+BAGGY
+BAGPIPE/M/S
+BAH
+BAIL/G
+BAILIFF/M/S
+BAIT/D/R/G/S
+BAKE/D/R/Z/G/S
+BAKERY/M/S
+BAKLAVA
+BALALAIKA/M/S
+BALANCE/D/R/Z/G/S
+BALCONY/M/S
+BALD/P/G/Y
+BALE/R/S
+BALEFUL
+BALK/D/G/S
+BALKAN/S
+BALKANIZE/D/G
+BALKY/P
+BALL/D/R/Z/G/S
+BALLAD/M/S
+BALLAST/M/S
+BALLERINA/M/S
+BALLET/M/S
+BALLGOWN/M/S
+BALLISTIC/S
+BALLOON/D/R/Z/G/S
+BALLOT/M/S
+BALLPARK/M/S
+BALLPLAYER/M/S
+BALLROOM/M/S
+BALLYHOO
+BALM/M/S
+BALMY
+BALSA
+BALSAM
+BALTIC
+BALUSTRADE/M/S
+BAMBOO
+BAN/M/S
+BANAL/Y
+BANANA/M/S
+BAND/D/G/S
+BANDAGE/D/G/S
+BANDIT/M/S
+BANDLIMIT/D/G/S
+BANDPASS
+BANDSTAND/M/S
+BANDWAGON/M/S
+BANDWIDTH
+BANDWIDTHS
+BANDY/D/G/S
+BANE
+BANEFUL
+BANG/D/G/S
+BANGLADESH
+BANGLE/M/S
+BANISH/D/G/S
+BANISHMENT
+BANISTER/M/S
+BANJO/M/S
+BANK/D/R/Z/G/S
+BANKRUPT/D/G/S
+BANKRUPTCY/M/S
+BANNED
+BANNER/M/S
+BANNING
+BANQUET/G/J/S
+BANSHEE/M/S
+BANTAM
+BANTER/D/G/S
+BANTU/S
+BAPTISM/M/S
+BAPTISMAL
+BAPTIST/M/S
+BAPTISTERY
+BAPTISTRY/M/S
+BAPTIZE/D/G/S
+BAR/M/S
+BARB/D/R/S
+BARBADOS
+BARBARA/M
+BARBARIAN/M/S
+BARBARIC
+BARBARITY/S
+BARBAROUS/Y
+BARBECUE/D/S/G
+BARBELL/M/S
+BARBITAL
+BARBITURATE/S
+BARD/M/S
+BARE/P/D/T/R/G/Y/S
+BAREFOOT/D
+BARFLY/M/S
+BARGAIN/D/G/S
+BARGE/G/S
+BARITONE/M/S
+BARIUM
+BARK/D/R/Z/G/S
+BARLEY
+BARN/M/S
+BARNSTORM/D/G/S
+BARNYARD/M/S
+BAROMETER/M/S
+BAROMETRIC
+BARON/M/S
+BARONESS
+BARONIAL
+BARONY/M/S
+BAROQUE/P
+BARRACK/S
+BARRAGE/M/S
+BARRED
+BARREL/M/S/D/G
+BARRELLED
+BARRELLING
+BARREN/P
+BARRICADE/M/S
+BARRIER/M/S
+BARRING/R
+BARROW
+BARTENDER/M/S
+BARTER/D/G/S
+BAS
+BASAL
+BASALT
+BASE/P/D/R/G/Y/S
+BASEBALL/M/S
+BASEBOARD/M/S
+BASELESS
+BASELINE/M/S
+BASEMAN
+BASEMENT/M/S
+BASH/D/G/S
+BASHFUL/P
+BASIC/S
+BASICALLY
+BASIL
+BASIN/M/S
+BASIS
+BASK/D/G
+BASKET/M/S
+BASKETBALL/M/S
+BASS/M/S
+BASSET
+BASSINET/M/S
+BASSO
+BASTARD/M/S
+BASTE/D/G/N/X/S
+BASTION'S
+BAT/M/S
+BATCH/D/S
+BATH
+BATHE/D/R/Z/G/S
+BATHOS
+BATHROBE/M/S
+BATHROOM/M/S
+BATHS
+BATHTUB/M/S
+BATON/M/S
+BATTALION/M/S
+BATTED
+BATTEN/S
+BATTER/D/G/S
+BATTERY/M/S
+BATTING
+BATTLE/D/R/Z/G/S
+BATTLEFIELD/M/S
+BATTLEFRONT/M/S
+BATTLEGROUND/M/S
+BATTLEMENT/M/S
+BATTLESHIP/M/S
+BAUBLE/M/S
+BAUD
+BAUXITE
+BAWDY
+BAWL/D/G/S
+BAY/D/G/S
+BAYONET/M/S
+BAYOU/M/S
+BAZAAR/M/S
+BE/D/G/Y
+BEACH/D/G/S
+BEACHHEAD/M/S
+BEACON/M/S
+BEAD/D/G/S
+BEADLE/M/S
+BEADY
+BEAGLE/M/S
+BEAK/D/R/Z/S
+BEAM/D/R/Z/G/S
+BEAN/D/R/Z/G/S
+BEAR/R/Z/G/J/S
+BEARABLE
+BEARABLY
+BEARD/D/S
+BEARDLESS
+BEARISH
+BEAST/Y/S
+BEAT/R/Z/G/N/J/S
+BEATABLE
+BEATABLY
+BEATIFIC
+BEATIFY/N
+BEATITUDE/M/S
+BEATNIK/M/S
+BEAU/M/S
+BEAUTEOUS/Y
+BEAUTIFUL/Y
+BEAUTIFY/D/R/Z/G/X/S
+BEAUTY/M/S
+BEAVER/M/S
+BECALM/D/G/S
+BECAME
+BECAUSE
+BECK
+BECKON/D/G/S
+BECOME/G/S
+BECOMINGLY
+BED/M/S
+BEDAZZLE/D/G/S
+BEDAZZLEMENT
+BEDBUG/M/S
+BEDDED
+BEDDER/M/S
+BEDDING
+BEDEVIL/D/G/S
+BEDFAST
+BEDLAM
+BEDPOST/M/S
+BEDRAGGLE/D
+BEDRIDDEN
+BEDROCK/M
+BEDROOM/M/S
+BEDSIDE
+BEDSPREAD/M/S
+BEDSPRING/M/S
+BEDSTEAD/M/S
+BEDTIME
+BEE/R/Z/G/J/S
+BEECH/R/N
+BEEF/D/R/Z/G/S
+BEEFSTEAK
+BEEFY
+BEEHIVE/M/S
+BEEN
+BEEP/S
+BEET/M/S
+BEETHOVEN
+BEETLE/D/M/G/S
+BEFALL/G/N/S
+BEFELL
+BEFIT/M/S
+BEFITTED
+BEFITTING
+BEFOG
+BEFOGGED
+BEFOGGING
+BEFORE
+BEFOREHAND
+BEFOUL/D/G/S
+BEFRIEND/D/G/S
+BEFUDDLE/D/G/S
+BEG/S
+BEGAN
+BEGET/S
+BEGETTING
+BEGGAR/Y/S
+BEGGARY
+BEGGED
+BEGGING
+BEGIN/S
+BEGINNER/M/S
+BEGINNING/M/S
+BEGOT
+BEGOTTEN
+BEGRUDGE/D/G/S
+BEGRUDGINGLY
+BEGUILE/D/G/S
+BEGUN
+BEHALF
+BEHAVE/D/G/S
+BEHAVIOR/S
+BEHAVIORAL/Y
+BEHAVIORISM
+BEHAVIORISTIC
+BEHEAD/G
+BEHELD
+BEHEST
+BEHIND
+BEHOLD/R/Z/G/N/S
+BEHOOVE/S
+BEIGE
+BEIJING
+BELABOR/D/G/S
+BELATED/Y
+BELAY/D/G/S
+BELCH/D/G/S
+BELFRY/M/S
+BELGIAN/M/S
+BELGIUM
+BELIE/D/S
+BELIEF/M/S
+BELIEVABLE
+BELIEVABLY
+BELIEVE/D/R/Z/G/S
+BELITTLE/D/G/S
+BELL/M/S
+BELLBOY/M/S
+BELLE/M/S
+BELLHOP/M/S
+BELLICOSE
+BELLICOSITY
+BELLIGERENCE
+BELLIGERENT/M/Y/S
+BELLMAN
+BELLMEN
+BELLOW/D/G/S
+BELLWETHER/M/S
+BELLY/M/S
+BELLYFUL
+BELONG/D/G/J/S
+BELOVED
+BELOW
+BELT/D/G/S
+BELYING
+BEMOAN/D/G/S
+BENCH/D/S
+BENCHMARK/M/S
+BEND/R/Z/G/S
+BENDABLE
+BENEATH
+BENEDICT
+BENEDICTINE
+BENEDICTION/M/S
+BENEFACTOR/M/S
+BENEFICENCE/S
+BENEFICIAL/Y
+BENEFICIARY/S
+BENEFIT/D/G/S
+BENEFITTED
+BENEFITTING
+BENEVOLENCE
+BENEVOLENT
+BENGAL
+BENGALI
+BENIGHTED
+BENIGN/Y
+BENT
+BENZEDRINE
+BENZENE
+BEQUEATH/D/G/S
+BEQUEST/M/S
+BERATE/D/G/S
+BEREAVE/D/G/S
+BEREAVEMENT/S
+BEREFT
+BERET/M/S
+BERIBBONED
+BERIBERI
+BERKELEY
+BERKELIUM
+BERLIN/R/Z
+BERMUDA
+BERRY/M/S
+BERTH
+BERTHS
+BERYL
+BERYLLIUM
+BESEECH/G/S
+BESET/S
+BESETTING
+BESIDE/S
+BESIEGE/D/R/Z/G
+BESMIRCH/D/G/S
+BESOTTED
+BESOTTER
+BESOTTING
+BESOUGHT
+BESPEAK/S
+BESPECTACLED
+BESSEL
+BEST/D/G/S
+BESTIAL
+BESTOW/D
+BESTOWAL
+BESTSELLER/M/S
+BESTSELLING
+BET/M/S
+BETA
+BETHESDA
+BETIDE
+BETRAY/D/R/G/S
+BETRAYAL
+BETROTH/D
+BETROTHAL
+BETTER/D/G/S
+BETTERMENT/S
+BETTING
+BETWEEN
+BETWIXT
+BEVEL/D/G/S
+BEVERAGE/M/S
+BEVY
+BEWAIL/D/G/S
+BEWARE
+BEWHISKERED
+BEWILDER/D/G/S
+BEWILDERINGLY
+BEWILDERMENT
+BEWITCH/D/G/S
+BEYOND
+BEZIER
+BIANNUAL
+BIAS/D/G/S
+BIB/M/S
+BIBBED
+BIBBING
+BIBLE/M/S
+BIBLICAL/Y
+BIBLIOGRAPHIC
+BIBLIOGRAPHICAL
+BIBLIOGRAPHY/M/S
+BIBLIOPHILE
+BICAMERAL
+BICARBONATE
+BICENTENNIAL
+BICEP/M/S
+BICKER/D/G/S
+BICONCAVE
+BICONVEX
+BICYCLE/D/R/Z/G/S
+BID/M/S
+BIDDABLE
+BIDDEN
+BIDDER/M/S
+BIDDING
+BIDDY/S
+BIDE
+BIDIRECTIONAL
+BIENNIAL
+BIENNIUM
+BIFOCAL/S
+BIG/P
+BIGGER
+BIGGEST
+BIGHT/M/S
+BIGNUM
+BIGOT/D/M/S
+BIGOTRY
+BIJECTION/M/S
+BIJECTIVE/Y
+BIKE/M/G/S
+BIKINI/M/S
+BILABIAL
+BILATERAL/Y
+BILE
+BILGE/M/S
+BILINEAR
+BILINGUAL
+BILK/D/G/S
+BILL/D/R/Z/G/J/S/M
+BILLBOARD/M/S
+BILLET/D/G/S
+BILLIARD/S
+BILLION/H/S
+BILLOW/D/S
+BIMODAL
+BIMOLECULAR
+BIMONTHLY/S
+BIN/M/S
+BINARY
+BINAURAL
+BIND/R/Z/G/J/S
+BINGE/S
+BINGO
+BINOCULAR/S
+BINOMIAL
+BINUCLEAR
+BIOCHEMICAL
+BIOCHEMISTRY
+BIOFEEDBACK
+BIOGRAPHER/M/S
+BIOGRAPHIC
+BIOGRAPHICAL/Y
+BIOGRAPHY/M/S
+BIOLOGICAL/Y
+BIOLOGIST/M/S
+BIOLOGY
+BIOMEDICAL
+BIOMEDICINE
+BIOPHYSICAL
+BIOPHYSICS
+BIOPSY/S
+BIOTECHNOLOGY
+BIPARTISAN
+BIPARTITE
+BIPED/S
+BIPLANE/M/S
+BIPOLAR
+BIRACIAL
+BIRCH/N/S
+BIRD/M/S
+BIRDBATH/M
+BIRDBATHS
+BIRDIE/D/S
+BIRDLIKE
+BIREFRINGENCE
+BIREFRINGENT
+BIRMINGHAM
+BIRTH/D
+BIRTHDAY/M/S
+BIRTHPLACE/S
+BIRTHRIGHT/M/S
+BIRTHS
+BISCUIT/M/S
+BISECT/D/G/S
+BISECTION/M/S
+BISECTOR/M/S
+BISHOP/M/S
+BISMUTH
+BISON/M/S
+BISQUE/S
+BIT/M/S
+BITCH/M/S
+BITE/G/R/S/Z
+BITINGLY
+BITMAP/S
+BITMAPPED
+BITTEN
+BITTER/P/T/R/Y/S
+BITTERSWEET
+BITUMINOUS
+BITWISE
+BIVALVE/M/S
+BIVARIATE
+BIVOUAC/S
+BIWEEKLY
+BIZARRE
+BLAB/S
+BLABBED
+BLABBERMOUTH
+BLABBERMOUTHS
+BLABBING
+BLACK/P/D/T/R/G/N/X/Y/S
+BLACKBERRY/M/S
+BLACKBIRD/M/S
+BLACKBOARD/M/S
+BLACKENED
+BLACKENING
+BLACKJACK/M/S
+BLACKLIST/D/G/S
+BLACKMAIL/D/R/Z/G/S
+BLACKOUT/M/S
+BLACKSMITH
+BLACKSMITHS
+BLADDER/M/S
+BLADE/M/S
+BLAINE
+BLAMABLE
+BLAME/D/R/Z/G/S
+BLAMELESS/P
+BLANCH/D/G/S
+BLAND/P/Y
+BLANK/P/D/T/R/G/Y/S
+BLANKET/D/R/Z/G/S
+BLARE/D/G/S
+BLASE
+BLASPHEME/D/G/S
+BLASPHEMOUS/P/Y
+BLASPHEMY/S
+BLAST/D/R/Z/G/S
+BLATANT/Y
+BLAZE/D/R/Z/G/S
+BLEACH/D/R/Z/G/S
+BLEAK/P/Y
+BLEAR
+BLEARY
+BLEAT/G/S
+BLED
+BLEED/R/G/J/S
+BLEMISH/M/S
+BLEND/D/G/S
+BLESS/D/G/J
+BLEW
+BLIGHT/D
+BLIMP/M/S
+BLIND/P/D/R/Z/G/Y/S
+BLINDFOLD/D/G/S
+BLINDINGLY
+BLINK/D/R/Z/G/S
+BLIP/M/S
+BLISS
+BLISSFUL/Y
+BLISTER/D/G/S
+BLITHE/Y
+BLITZ/M/S
+BLITZKRIEG
+BLIZZARD/M/S
+BLOAT/D/R/G/S
+BLOB/M/S
+BLOC/M/S
+BLOCK'S
+BLOCK/D/R/Z/G/S
+BLOCKADE/D/G/S
+BLOCKAGE/M/S
+BLOCKHOUSE/S
+BLOKE/M/S
+BLOND/M/S
+BLONDE/M/S
+BLOOD/D/S
+BLOODHOUND/M/S
+BLOODLESS
+BLOODSHED
+BLOODSHOT
+BLOODSTAIN/D/M/S
+BLOODSTREAM
+BLOODY/D/T
+BLOOM/D/Z/G/S
+BLOSSOM/D/S
+BLOT/M/S
+BLOTTED
+BLOTTING
+BLOUSE/M/S
+BLOW/R/Z/G/S
+BLOWFISH
+BLOWN
+BLOWUP
+BLUBBER
+BLUDGEON/D/G/S
+BLUE/P/T/R/G/S
+BLUEBERRY/M/S
+BLUEBIRD/M/S
+BLUEBONNET/M/S
+BLUEFISH
+BLUEPRINT/M/S
+BLUESTOCKING
+BLUFF/G/S
+BLUISH
+BLUNDER/D/G/J/S
+BLUNT/P/D/T/R/G/Y/S
+BLUR/M/S
+BLURB
+BLURRED
+BLURRING
+BLURRY
+BLURT/D/G/S
+BLUSH/D/G/S
+BLUSTER/D/G/S
+BLUSTERY
+BOAR
+BOARD/D/R/Z/G/S
+BOARDINGHOUSE/M/S
+BOAST/D/R/Z/G/J/S
+BOASTFUL/Y
+BOAT/R/Z/G/S
+BOATHOUSE/M/S
+BOATLOAD/M/S
+BOATMAN
+BOATMEN
+BOATSMAN
+BOATSMEN
+BOATSWAIN/M/S
+BOATYARD/M/S
+BOB/M/S
+BOBBED
+BOBBIN/M/S
+BOBBING
+BOBBY
+BOBOLINK/M/S
+BOBWHITE/M/S
+BODE/S
+BODICE
+BODILY
+BODONI
+BODY/D/S
+BODYBUILDER/M/S
+BODYBUILDING
+BODYGUARD/M/S
+BODYWEIGHT
+BOG/M/S
+BOGGED
+BOGGLE/D/G/S
+BOGUS
+BOIL/D/R/Z/G/S
+BOILERPLATE
+BOISTEROUS/Y
+BOLD/P/T/R/Y
+BOLDFACE
+BOLIVIA
+BOLL
+BOLOGNA
+BOLSHEVIK/M/S
+BOLSHEVISM
+BOLSTER/D/G/S
+BOLT/D/G/S
+BOLTZMANN
+BOMB/D/R/Z/G/J/S
+BOMBARD/D/G/S
+BOMBARDMENT
+BOMBAST
+BOMBASTIC
+BOMBPROOF
+BONANZA/M/S
+BOND/D/R/Z/G/S
+BONDAGE
+BONDSMAN
+BONDSMEN
+BONE/D/R/Z/G/S
+BONFIRE/M/S
+BONG
+BONNET/D/S
+BONNY
+BONUS/M/S
+BONY
+BOO/H/S
+BOOB
+BOOBOO
+BOOBY
+BOOK/D/R/Z/G/J/S
+BOOKCASE/M/S
+BOOKIE/M/S
+BOOKISH
+BOOKKEEPER/M/S
+BOOKKEEPING
+BOOKLET/M/S
+BOOKSELLER/M/S
+BOOKSHELF/M
+BOOKSHELVES
+BOOKSTORE/M/S
+BOOLEAN
+BOOM/D/G/S
+BOOMERANG/M/S
+BOOMTOWN/M/S
+BOON
+BOOR/M/S
+BOORISH
+BOOST/D/R/G/S
+BOOT/D/G/S
+BOOTHS
+BOOTLEG/S
+BOOTLEGGED
+BOOTLEGGER/M/S
+BOOTLEGGING
+BOOTSTRAP/M/S
+BOOTSTRAPPED
+BOOTSTRAPPING
+BOOTY
+BOOZE
+BORATE/S
+BORAX
+BORDELLO/M/S
+BORDER/D/G/J/S
+BORDERLAND/M/S
+BORDERLINE
+BORE/D/R/G/S
+BOREDOM
+BORIC
+BORN
+BORNE
+BORNEO
+BORON
+BOROUGH
+BOROUGHS
+BORROW/D/R/Z/G/S
+BOSOM/M/S
+BOSS/D/S
+BOSTON
+BOSTONIAN/M/S
+BOSUN
+BOTANICAL
+BOTANIST/M/S
+BOTANY
+BOTCH/D/R/Z/G/S
+BOTH/Z
+BOTHER/D/G/S
+BOTHERSOME
+BOTSWANA
+BOTTLE/D/R/Z/G/S
+BOTTLENECK/M/S
+BOTTOM/D/G/S
+BOTTOMLESS
+BOTULINUS
+BOTULISM
+BOUFFANT
+BOUGH/M
+BOUGHS
+BOUGHT
+BOULDER/M/S
+BOULEVARD/M/S
+BOUNCE/D/R/G/S
+BOUNCY
+BOUND/D/G/N/S
+BOUNDARY/M/S
+BOUNDLESS/P
+BOUNTEOUS/Y
+BOUNTY/M/S
+BOUQUET/M/S
+BOURBON
+BOURGEOIS
+BOURGEOISIE
+BOUT/M/S
+BOVINE/S
+BOW/D/R/Z/G/S
+BOWDLERIZE/D/G/S
+BOWEL/M/S
+BOWL/D/R/Z/G/S
+BOWLINE/M/S
+BOWMAN
+BOWSTRING/M/S
+BOX/D/R/Z/G/S
+BOXCAR/M/S
+BOXTOP/M/S
+BOXWOOD
+BOY/M/S
+BOYCOTT/D/S
+BOYFRIEND/M/S
+BOYHOOD
+BOYISH/P
+BRA/M/S
+BRACE/D/G/S
+BRACELET/M/S
+BRACKET/D/G/S
+BRACKISH
+BRAD/M
+BRAE/M/S
+BRAG/S
+BRAGGED
+BRAGGER
+BRAGGING
+BRAID/D/G/S
+BRAILLE
+BRAIN/D/G/S
+BRAINCHILD/M
+BRAINSTEM/M/S
+BRAINSTORM/M/S
+BRAINWASH/D/G/S
+BRAINY
+BRAKE/D/G/S
+BRAMBLE/M/S
+BRAMBLY
+BRAN
+BRANCH/D/G/J/S
+BRAND/D/G/S
+BRANDISH/G/S
+BRANDY
+BRASH/P/Y
+BRASS/S
+BRASSIERE
+BRASSY
+BRAT/M/S
+BRAVADO
+BRAVE/P/D/T/R/G/Y/S
+BRAVERY
+BRAVO/S
+BRAVURA
+BRAWL/R/G
+BRAWN
+BRAY/D/R/G/S
+BRAZE/D/G/S
+BRAZEN/P/Y
+BRAZIER/M/S
+BRAZIL
+BRAZILIAN
+BREACH/D/R/Z/G/S
+BREAD/D/G/H/S
+BREADBOARD/M/S
+BREADBOX/M/S
+BREADWINNER/M/S
+BREAK/R/Z/G/S
+BREAKABLE/S
+BREAKAGE
+BREAKAWAY
+BREAKDOWN/M/S
+BREAKFAST/D/R/Z/G/S
+BREAKPOINT/M/S
+BREAKTHROUGH/M/S
+BREAKTHROUGHS
+BREAKUP
+BREAKWATER/M/S
+BREAST/D/S
+BREASTWORK/M/S
+BREATH
+BREATHABLE
+BREATHE/D/R/Z/G/S
+BREATHLESS/Y
+BREATHS
+BREATHTAKING/Y
+BREATHY
+BRED
+BREECH/M/S
+BREED/R/G/S
+BREEZE/M/S
+BREEZILY
+BREEZY
+BREMSSTRAHLUNG
+BRETHREN
+BREVE
+BREVET/D/G/S
+BREVITY
+BREW/D/R/Z/G/S
+BREWERY/M/S
+BRIAN/M
+BRIAR/M/S
+BRIBE/D/R/Z/G/S
+BRICK/D/R/S
+BRICKLAYER/M/S
+BRICKLAYING
+BRIDAL
+BRIDE/M/S
+BRIDEGROOM
+BRIDESMAID/M/S
+BRIDGE/D/G/S
+BRIDGEABLE
+BRIDGEHEAD/M/S
+BRIDGEWORK/M
+BRIDLE/D/G/S
+BRIEF/P/D/T/R/Y/S
+BRIEFCASE/M/S
+BRIEFING/M/S
+BRIER
+BRIG/M/S
+BRIGADE/M/S
+BRIGADIER/M/S
+BRIGANTINE
+BRIGHT/P/T/R/X/Y
+BRIGHTEN/D/R/Z/G/S
+BRILLIANCE
+BRILLIANCY
+BRILLIANT/Y
+BRIM
+BRIMFUL
+BRIMMED
+BRINDLE/D
+BRINE
+BRING/G/R/S/Z
+BRINK
+BRINKMANSHIP
+BRISK/P/R/Y
+BRISTLE/D/G/S
+BRITAIN
+BRITCHES
+BRITISH/R
+BRITON/M/S
+BRITTLE/P
+BROACH/D/G/S
+BROAD/P/T/R/X/Y
+BROADBAND
+BROADCAST/R/Z/G/J/S
+BROADEN/D/R/Z/G/J/S
+BROADSIDE
+BROCADE/D
+BROCCOLI
+BROCHURE/M/S
+BROIL/D/R/Z/G/S
+BROKE/R/Z
+BROKEN/P/Y
+BROKERAGE
+BROMIDE/M/S
+BROMINE
+BRONCHI
+BRONCHIAL
+BRONCHIOLE/M/S
+BRONCHITIS
+BRONCHUS
+BRONZE/D/S
+BROOCH/M/S
+BROOD/R/G/S
+BROOK/D/S
+BROOKHAVEN
+BROOM/M/S
+BROOMSTICK/M/S
+BROTH/R/Z
+BROTHEL/M/S
+BROTHER'S
+BROTHERHOOD
+BROTHERLY/P
+BROUGHT
+BROW/M/S
+BROWBEAT/G/N/S
+BROWN/P/D/T/R/G/S
+BROWNIE/M/S
+BROWNISH
+BROWSE/G
+BROWSER/S
+BRUCE/M
+BRUISE/D/G/S
+BRUNCH/S
+BRUNETTE
+BRUNT
+BRUSH/D/G/S
+BRUSHFIRE/M/S
+BRUSHLIKE
+BRUSHY
+BRUSQUE/Y
+BRUTAL/Y
+BRUTALITY/S
+BRUTALIZE/D/G/S
+BRUTE/M/S
+BRUTISH
+BSD
+BUBBLE/D/G/S
+BUBBLY
+BUCK/D/G/S
+BUCKBOARD/M/S
+BUCKET/M/S
+BUCKLE/D/R/G/S
+BUCKSHOT
+BUCKSKIN/S
+BUCKWHEAT
+BUCOLIC
+BUD/M/S
+BUDDED
+BUDDING
+BUDDY/M/S
+BUDGE/D/G/S
+BUDGET/D/R/Z/G/S
+BUDGETARY
+BUFF/M/S
+BUFFALO
+BUFFALOES
+BUFFER/D/M/G/S
+BUFFERER/M/S
+BUFFET/D/G/J/S
+BUFFOON/M/S
+BUG/M/S
+BUGGED
+BUGGER/M/S
+BUGGING
+BUGGY/M/S
+BUGLE/D/R/G/S
+BUILD/R/Z/G/J/S
+BUILDUP/M/S
+BUILT
+BULB/M/S
+BULGE/D/G
+BULK/D/S
+BULKHEAD/M/S
+BULKY
+BULL/D/G/S
+BULLDOG/M/S
+BULLDOZE/D/R/G/S
+BULLET/M/S
+BULLETIN/M/S
+BULLION
+BULLISH
+BULLY/D/G/S
+BULWARK
+BUM/M/S
+BUMBLE/D/R/Z/G/S
+BUMBLEBEE/M/S
+BUMMED
+BUMMING
+BUMP/D/R/Z/G/S
+BUMPTIOUS/P/Y
+BUN/M/S
+BUNCH/D/G/S
+BUNDLE/D/G/S
+BUNGALOW/M/S
+BUNGLE/D/R/Z/G/S
+BUNION/M/S
+BUNK/R/Z/S
+BUNKER'S
+BUNKERED
+BUNKHOUSE/M/S
+BUNKMATE/M/S
+BUNNY/M/S
+BUNT/D/R/Z/G/S
+BUOY/D/S
+BUOYANCY
+BUOYANT
+BURDEN/D/G/S
+BURDENSOME
+BUREAU/M/S
+BUREAUCRACY/M/S
+BUREAUCRAT/M/S
+BUREAUCRATIC
+BURGEON/D/G
+BURGESS/M/S
+BURGHER/M/S
+BURGLAR/M/S
+BURGLARIZE/D/G/S
+BURGLARPROOF/D/G/S
+BURGLARY/M/S
+BURIAL
+BURL
+BURLESQUE/S
+BURLY
+BURN/D/R/Z/G/J/S
+BURNINGLY
+BURNISH/D/G/S
+BURNT/P/Y
+BURP/D/G/S
+BURR/M/S
+BURRO/M/S
+BURROW/D/R/G/S
+BURSA
+BURSITIS
+BURST/G/S
+BURY/D/G/S
+BUS/D/G/S
+BUSBOY/M/S
+BUSH/G/S
+BUSHEL/M/S
+BUSHWHACK/D/G/S
+BUSHY
+BUSILY
+BUSINESS/M/S
+BUSINESSLIKE
+BUSINESSMAN
+BUSINESSMEN
+BUSS/D/G/S
+BUST/D/R/S
+BUSTARD/M/S
+BUSTLE/G
+BUSY/D/T/R
+BUT
+BUTANE
+BUTCHER/D/S
+BUTCHERY
+BUTLER/M/S
+BUTT/M/S
+BUTTE/D/Z/G/S
+BUTTER/D/R/Z/G
+BUTTERFAT
+BUTTERFLY/M/S
+BUTTERNUT
+BUTTOCK/M/S
+BUTTON/D/G/S
+BUTTONHOLE/M/S
+BUTTRESS/D/G/S
+BUTYL
+BUTYRATE
+BUXOM
+BUY/G/S
+BUYER/M/S
+BUZZ/D/R/G/S
+BUZZARD/M/S
+BUZZWORD/M/S
+BUZZY
+BY/R
+BYE
+BYGONE
+BYLAW/M/S
+BYLINE/M/S
+BYPASS/D/G/S
+BYPRODUCT/M/S
+BYSTANDER/M/S
+BYTE/M/S
+BYWAY/S
+BYWORD/M/S
+CAB/M/S
+CABBAGE/M/S
+CABIN/M/S
+CABINET/M/S
+CABLE/D/G/S
+CACHE/M/S/G/D
+CACKLE/D/R/G/S
+CACTI
+CACTUS
+CADENCE/D
+CADUCEUS
+CAFE/M/S
+CAGE/D/R/Z/G/S
+CAJOLE/D/G/S
+CAKE/D/G/S
+CALAMITY/M/S
+CALCIUM
+CALCULATE/D/G/N/X/V/S
+CALCULATOR/M/S
+CALCULUS
+CALENDAR/M/S
+CALF
+CALIBER/S
+CALIBRATE/D/G/N/X/S
+CALICO
+CALIFORNIA
+CALIPH
+CALIPHS
+CALL/D/R/Z/G/S
+CALLIGRAPHY
+CALLOUS/P/D/Y
+CALM/P/D/T/R/G/Y/S
+CALMINGLY
+CALORIE/M/S
+CALVES
+CAMBRIDGE
+CAME
+CAMEL/M/S
+CAMERA/M/S
+CAMOUFLAGE/D/G/S
+CAMP/D/R/Z/G/S
+CAMPAIGN/D/R/Z/G/S
+CAMPUS/M/S
+CAN'T
+CAN/M/S
+CANADA
+CANAL/M/S
+CANARY/M/S
+CANCEL/D/G/S
+CANCELLATION/M/S
+CANCER/M/S
+CANDID/P/Y
+CANDIDATE/M/S
+CANDLE/R/S
+CANDLESTICK/M/S
+CANDOR
+CANDY/D/S
+CANE/R
+CANINE
+CANKER
+CANNED
+CANNER/M/S
+CANNIBAL/M/S
+CANNIBALIZE/D/G/S
+CANNING
+CANNISTER/M/S
+CANNON/M/S
+CANNOT
+CANOE/M/S
+CANON/M/S
+CANONICAL/Y/S
+CANONICALIZATION
+CANONICALIZE/D/G/S
+CANOPY
+CANTANKEROUS/Y
+CANTO
+CANTON/M/S
+CANTOR/M/S
+CANVAS/M/S
+CANVASS/D/R/Z/G/S
+CANYON/M/S
+CAP/M/S
+CAPABILITY/M/S
+CAPABLE
+CAPABLY
+CAPACIOUS/P/Y
+CAPACITANCE/S
+CAPACITIVE
+CAPACITOR/M/S
+CAPACITY/S
+CAPE/R/Z/S
+CAPILLARY
+CAPITA
+CAPITAL/Y/S
+CAPITALISM
+CAPITALIST/M/S
+CAPITALIZATION/S
+CAPITALIZE/D/R/Z/G/S
+CAPITOL/M/S
+CAPPED
+CAPPING
+CAPRICIOUS/P/Y
+CAPTAIN/D/G/S
+CAPTION/M/S
+CAPTIVATE/D/G/N/S
+CAPTIVE/M/S
+CAPTIVITY
+CAPTOR/M/S
+CAPTURE/D/R/Z/G/S
+CAR/M/S
+CARAVAN/M/S
+CARBOHYDRATE
+CARBOLIC
+CARBON/M/S
+CARBONATE/N/S
+CARBONIC
+CARBONIZATION
+CARBONIZE/D/R/Z/G/S
+CARCASS/M/S
+CARCINOMA
+CARD/R/S
+CARDBOARD
+CARDIAC
+CARDINAL/Y/S
+CARDINALITY/M/S
+CARDIOLOGY
+CARDIOPULMONARY
+CARE/D/G/S
+CAREER/M/S
+CAREFREE
+CAREFUL/P/Y
+CARELESS/P/Y
+CARESS/D/R/G/S
+CARET
+CARGO
+CARGOES
+CARIBOU
+CARNEGIE
+CARNIVAL/M/S
+CARNIVOROUS/Y
+CAROL/M/S
+CAROLINA/M/S
+CARPENTER/M/S
+CARPET/D/G/S
+CARRIAGE/M/S
+CARROT/M/S
+CARRY/D/R/Z/G/S
+CARRYOVER/S
+CART/D/R/Z/G/S
+CARTESIAN
+CARTOGRAPHIC
+CARTOGRAPHY
+CARTON/M/S
+CARTOON/M/S
+CARTRIDGE/M/S
+CARVE/D/R/G/J/S
+CASCADE/D/G/S
+CASE/D/G/J/S
+CASEMENT/M/S
+CASH/D/R/Z/G/S
+CASHIER/M/S
+CASK/M/S
+CASKET/M/S
+CASSEROLE/M/S
+CAST/G/M/S
+CASTE/R/S/Z
+CASTLE/D/S
+CASUAL/P/Y/S
+CASUALTY/M/S
+CAT/M/S
+CATALOG/D/R/G/S
+CATALOGUE/D/S
+CATALYST/M/S
+CATARACT
+CATASTROPHE
+CATASTROPHIC
+CATCH/G/R/S/Z
+CATCHABLE
+CATEGORICAL/Y
+CATEGORIZATION
+CATEGORIZE/D/R/Z/G/S
+CATEGORY/M/S
+CATER/D/R/G/S
+CATERPILLAR/M/S
+CATHEDRAL/M/S
+CATHERINE/M
+CATHETER/S
+CATHODE/M/S
+CATHOLIC/M/S
+CATSUP
+CATTLE
+CAUGHT
+CAUSAL/Y
+CAUSALITY
+CAUSATION/M/S
+CAUSE/D/R/G/S
+CAUSEWAY/M/S
+CAUSTIC/Y/S
+CAUTION/D/R/Z/G/J/S
+CAUTIOUS/P/Y
+CAVALIER/P/Y
+CAVALRY
+CAVE/D/G/S
+CAVEAT/M/S
+CAVERN/M/S
+CAVITY/M/S
+CAW/G
+CDR
+CEASE/D/G/S
+CEASELESS/P/Y
+CEDAR
+CEILING/M/S
+CELEBRATE/D/G/N/X/S
+CELEBRITY/M/S
+CELERY
+CELESTIAL/Y
+CELL/D/S
+CELLAR/M/S
+CELLIST/M/S
+CELLULAR
+CELSIUS
+CEMENT/D/G/S
+CEMETERY/M/S
+CENSOR/D/G/S
+CENSORSHIP
+CENSURE/D/R/S
+CENSUS/M/S
+CENT/Z/S
+CENTER/D/G/S
+CENTERPIECE/M/S
+CENTIMETER/S
+CENTIPEDE/M/S
+CENTRAL/Y
+CENTRALIZATION
+CENTRALIZE/D/G/S
+CENTRIPETAL
+CENTURY/M/S
+CEREAL/M/S
+CEREBRAL
+CEREMONIAL/P/Y
+CEREMONY/M/S
+CERTAIN/Y
+CERTAINTY/S
+CERTIFIABLE
+CERTIFICATE/N/X/S
+CERTIFY/D/R/Z/G/N/S
+CESSATION/M/S
+CHAFE/R/G
+CHAFF/R/G
+CHAGRIN
+CHAIN/D/G/S
+CHAIR/D/G/S
+CHAIRMAN
+CHAIRMEN
+CHAIRPERSON/M/S
+CHALICE/M/S
+CHALK/D/G/S
+CHALLENGE/D/R/Z/G/S
+CHAMBER/D/S
+CHAMBERLAIN/M/S
+CHAMPAGNE
+CHAMPAIGN
+CHAMPION/D/G/S
+CHAMPIONSHIP/M/S
+CHANCE/D/G/S
+CHANCELLOR
+CHANDELIER/M/S
+CHANGE/D/R/Z/G/S
+CHANGEABILITY
+CHANGEABLE
+CHANGEABLY
+CHANNEL/D/G/S
+CHANNELLED
+CHANNELLER/M/S
+CHANNELLING
+CHANT/D/R/G/S
+CHANTICLEER/M/S
+CHAOS
+CHAOTIC
+CHAP/M/S
+CHAPEL/M/S
+CHAPERON/D
+CHAPLAIN/M/S
+CHAPTER/M/S
+CHAR/S
+CHARACTER/M/S
+CHARACTERISTIC/M/S
+CHARACTERISTICALLY
+CHARACTERIZABLE
+CHARACTERIZATION/M/S
+CHARACTERIZE/D/R/Z/G/S
+CHARCOAL/D
+CHARGE/D/R/Z/G/S
+CHARGEABLE
+CHARIOT/M/S
+CHARISMA
+CHARISMATIC
+CHARITABLE/P
+CHARITY/M/S
+CHARLES
+CHARM/D/R/Z/G/S
+CHARMINGLY
+CHART/D/R/Z/G/J/S
+CHARTABLE
+CHARTERED
+CHARTERING
+CHASE/D/R/Z/G/S
+CHASM/M/S
+CHASTE/P/Y
+CHASTISE/D/R/Z/G/S
+CHAT
+CHATEAU/M/S
+CHATTER/D/R/G/S/Z
+CHAUFFEUR/D
+CHEAP/P/T/R/X/Y
+CHEAPEN/D/G/S
+CHEAT/D/R/Z/G/S
+CHECK/D/R/Z/G/S
+CHECKABLE
+CHECKBOOK/M/S
+CHECKOUT
+CHECKPOINT/M/S
+CHECKSUM/M/S
+CHEEK/M/S
+CHEER/D/R/G/S
+CHEERFUL/P/Y
+CHEERILY
+CHEERLESS/P/Y
+CHEERY/P
+CHEESE/M/S
+CHEF/M/S
+CHEMICAL/Y/S
+CHEMISE
+CHEMIST/M/S
+CHEMISTRY/S
+CHERISH/D/G/S
+CHERRY/M/S
+CHERUB/M/S
+CHERUBIM
+CHESS
+CHEST/R/S
+CHESTNUT/M/S
+CHEW/D/R/Z/G/S
+CHICK/N/X/S
+CHICKADEE/M/S
+CHIDE/D/G/S
+CHIEF/Y/S
+CHIEFTAIN/M/S
+CHIFFON
+CHILD
+CHILDHOOD
+CHILDISH/P/Y
+CHILDREN
+CHILES
+CHILL/D/R/Z/G/S
+CHILLINGLY
+CHILLY/P/R
+CHIME/M/S
+CHIMNEY/M/S
+CHIN/M/S
+CHINA
+CHINESE
+CHINK/D/S
+CHINNED
+CHINNER/S
+CHINNING
+CHINTZ
+CHIP/M/S
+CHIPMUNK/M/S
+CHIRP/D/G/S
+CHISEL/D/R/S
+CHIVALROUS/P/Y
+CHIVALRY
+CHLORINE
+CHLOROPLAST/M/S
+CHOCK/M/S
+CHOCOLATE/M/S
+CHOICE/T/S
+CHOIR/M/S
+CHOKE/D/R/Z/G/S
+CHOLERA
+CHOOSE/R/Z/G/S
+CHOP/S
+CHOPPED
+CHOPPER/M/S
+CHOPPING
+CHORAL
+CHORD/M/S
+CHORE/G/S
+CHORUS/D/S
+CHOSE
+CHOSEN
+CHRIS
+CHRISTEN/D/G/S
+CHRISTIAN/M/S
+CHRISTMAS
+CHRISTOPHER/M
+CHROMOSOME
+CHRONIC
+CHRONICLE/D/R/Z/S
+CHRONOLOGICAL/Y
+CHRONOLOGY/M/S
+CHUBBY/P/T/R
+CHUCK/M/S
+CHUCKLE/D/S
+CHUM
+CHUNK/G/D/S/M
+CHURCH/Y/S
+CHURCHMAN
+CHURCHYARD/M/S
+CHURN/D/G/S
+CHUTE/M/S
+CIDER
+CIGAR/M/S
+CIGARETTE/M/S
+CINCINNATI
+CINDER/M/S
+CINNAMON
+CIPHER/M/S
+CIRCLE/D/G/S
+CIRCUIT/M/S
+CIRCUITOUS/Y
+CIRCUITRY
+CIRCULAR/Y
+CIRCULARITY/S
+CIRCULATE/D/G/N/S
+CIRCUMFERENCE
+CIRCUMFLEX
+CIRCUMLOCUTION/M/S
+CIRCUMSPECT/Y
+CIRCUMSTANCE/M/S
+CIRCUMSTANTIAL/Y
+CIRCUMVENT/D/G/S
+CIRCUMVENTABLE
+CIRCUS/M/S
+CISTERN/M/S
+CITADEL/M/S
+CITATION/M/S
+CITE/D/G/S
+CITIZEN/M/S
+CITIZENSHIP
+CITY/M/S
+CIVIC/S
+CIVIL/Y
+CIVILIAN/M/S
+CIVILITY
+CIVILIZATION/M/S
+CIVILIZE/D/G/S
+CLAD
+CLAIM/D/G/S
+CLAIMABLE
+CLAIMANT/M/S
+CLAIRVOYANT/Y
+CLAM/M/S
+CLAMBER/D/G/S
+CLAMOR/D/G/S
+CLAMOROUS
+CLAMP/D/G/S
+CLAN
+CLANG/D/G/S
+CLAP/S
+CLARA/M
+CLARIFY/D/G/N/X/S
+CLARITY
+CLASH/D/G/S
+CLASP/D/G/S
+CLASS/D/S
+CLASSIC/S
+CLASSICAL/Y
+CLASSIFIABLE
+CLASSIFY/D/R/Z/G/N/X/S
+CLASSMATE/M/S
+CLASSROOM/M/S
+CLATTER/D/G
+CLAUSE/M/S
+CLAW/D/G/S
+CLAY/M/S
+CLEAN/P/D/T/G/Y/S
+CLEANER/M/S
+CLEANLINESS
+CLEANSE/D/R/Z/G/S
+CLEAR/P/D/T/R/Y/S
+CLEARANCE/M/S
+CLEARING/M/S
+CLEAVAGE
+CLEAVE/D/R/Z/G/S
+CLEFT/M/S
+CLENCH/D/S
+CLERGY
+CLERGYMAN
+CLERICAL
+CLERK/D/G/S
+CLEVER/P/T/R/Y
+CLICHE/M/S
+CLICK/D/G/S
+CLIENT/M/S
+CLIFF/M/S
+CLIMATE/M/S
+CLIMATIC
+CLIMATICALLY
+CLIMAX/D/S
+CLIMB/D/R/Z/G/S
+CLIME/M/S
+CLINCH/D/R/S
+CLING/G/S
+CLINIC/M/S
+CLINICAL/Y
+CLINK/D/R
+CLIP/M/S
+CLIPPED
+CLIPPER/M/S
+CLIPPING/M/S
+CLIQUE/M/S
+CLOAK/M/S
+CLOBBER/D/G/S
+CLOCK/D/R/Z/G/J/S
+CLOCKWISE
+CLOCKWORK
+CLOD/M/S
+CLOG/M/S
+CLOGGED
+CLOGGING
+CLOISTER/M/S
+CLONE/D/G/S
+CLOSE/D/T/G/Y/S
+CLOSENESS/S
+CLOSER/S
+CLOSET/D/S
+CLOSURE/M/S
+CLOT
+CLOTH
+CLOTHE/D/G/S
+CLOUD/D/G/S
+CLOUDLESS
+CLOUDY/P/T/R
+CLOUT
+CLOVE/R/S
+CLOWN/G/S
+CLUB/M/S
+CLUBBED
+CLUBBING
+CLUCK/D/G/S
+CLUE/M/S
+CLUMP/D/G/S
+CLUMSILY
+CLUMSY/P
+CLUNG
+CLUSTER/D/G/J/S
+CLUTCH/D/G/S
+CLUTTER/D/G/S
+CLX
+CLYDE/M
+CMU/M
+COACH/D/R/G/S
+COACHMAN
+COAGULATION
+COAL/S
+COALESCE/D/G/S
+COALITION
+COARSE/P/T/R/Y
+COARSEN/D
+COAST/D/R/Z/G/S
+COASTAL
+COAT/D/G/J/S
+COAX/D/R/G/S
+COBBLER/M/S
+COBOL
+COBWEB/M/S
+COCK/D/G/S
+COCKATOO
+COCKTAIL/M/S
+COCOA
+COCONUT/M/S
+COCOON/M/S
+COD
+CODE/D/R/Z/G/J/S
+CODEWORD/M/S
+CODIFICATION/M/S
+CODIFIER/M/S
+CODIFY/D/G/S
+COEFFICIENT/M/S
+COERCE/D/G/N/V/S
+COEXIST/D/G/S
+COEXISTENCE
+COFFEE/M/S
+COFFER/M/S
+COFFIN/M/S
+COGENT/Y
+COGITATE/D/G/N/S
+COGNITION
+COGNITIVE/Y
+COGNIZANCE
+COGNIZANT
+COHABIT/S
+COHABITATION/S
+COHERE/D/G/S
+COHERENCE
+COHERENT/Y
+COHESION
+COHESIVE/P/Y
+COIL/D/G/S
+COIN/D/R/G/S
+COINAGE
+COINCIDE/D/G/S
+COINCIDENCE/M/S
+COINCIDENTAL
+COKE/S
+COLD/P/T/R/Y/S
+COLLABORATE/D/G/N/X/V/S
+COLLABORATOR/M/S
+COLLAPSE/D/G/S
+COLLAR/D/G/S
+COLLATERAL
+COLLEAGUE/M/S
+COLLECT/D/G/V/S
+COLLECTIBLE
+COLLECTION/M/S
+COLLECTIVE/Y/S
+COLLECTOR/M/S
+COLLEGE/M/S
+COLLEGIATE
+COLLIDE/D/G/S
+COLLIE/R/S
+COLLISION/M/S
+COLLOQUIA
+COLOGNE
+COLON/M/S
+COLONEL/M/S
+COLONIAL/Y/S
+COLONIST/M/S
+COLONIZATION
+COLONIZE/D/R/Z/G/S
+COLONY/M/S
+COLOR/D/R/Z/G/J/S
+COLORADO
+COLORFUL
+COLORLESS
+COLOSSAL
+COLT/M/S
+COLUMBUS
+COLUMN/M/S
+COLUMNAR
+COLUMNIZE/D/G/S
+COMB/D/R/Z/G/J/S
+COMBAT/D/G/V/S
+COMBATANT/M/S
+COMBINATION/M/S
+COMBINATIONAL
+COMBINATOR/M/S
+COMBINATORIAL/Y
+COMBINATORIC/S
+COMBINE/D/G/S
+COMBUSTION
+COME/R/Z/G/Y/J/S
+COMEDIAN/M/S
+COMEDIC
+COMEDY/M/S
+COMELINESS
+COMESTIBLE
+COMET/M/S
+COMFORT/D/R/Z/G/S
+COMFORTABILITY/S
+COMFORTABLE
+COMFORTABLY
+COMFORTINGLY
+COMIC/M/S
+COMICAL/Y
+COMMA/M/S
+COMMAND'S
+COMMAND/D/R/Z/G/S
+COMMANDANT/M/S
+COMMANDINGLY
+COMMANDMENT/M/S
+COMMEMORATE/D/G/N/V/S
+COMMENCE/D/G/S
+COMMENCEMENT/M/S
+COMMEND/D/G/S
+COMMENDABLE
+COMMENDATION/M/S
+COMMENSURATE
+COMMENT/D/G/S
+COMMENTARY/M/S
+COMMENTATOR/M/S
+COMMERCE
+COMMERCIAL/P/Y/S
+COMMISSION/D/R/Z/G/S
+COMMIT/S
+COMMITMENT/M/S
+COMMITTED
+COMMITTEE/M/S
+COMMITTING
+COMMODITY/M/S
+COMMODORE/M/S
+COMMON/P/T/Y/S
+COMMONALITY/S
+COMMONER/M/S
+COMMONPLACE/S
+COMMONWEALTH
+COMMONWEALTHS
+COMMOTION
+COMMUNAL/Y
+COMMUNE/N/S
+COMMUNICANT/M/S
+COMMUNICATE/D/G/N/X/V/S
+COMMUNICATOR/M/S
+COMMUNIST/M/S
+COMMUNITY/M/S
+COMMUTATIVE
+COMMUTATIVITY
+COMMUTE/D/R/Z/G/S
+COMPACT/P/D/T/R/G/Y/S
+COMPACTOR/M/S
+COMPANION/M/S
+COMPANIONABLE
+COMPANIONSHIP
+COMPANY/M/S
+COMPARABILITY
+COMPARABLE
+COMPARABLY
+COMPARATIVE/Y/S
+COMPARATOR/M/S
+COMPARE/D/G/S
+COMPARISON/M/S
+COMPARTMENT/D/S
+COMPARTMENTALIZE/D/G/S
+COMPASS
+COMPASSION
+COMPASSIONATE/Y
+COMPATIBILITY/M/S
+COMPATIBLE
+COMPATIBLY
+COMPEL/S
+COMPELLED
+COMPELLING/Y
+COMPENDIUM
+COMPENSATE/D/G/N/X/S
+COMPENSATORY
+COMPETE/D/G/S
+COMPETENCE
+COMPETENT/Y
+COMPETITION/M/S
+COMPETITIVE/Y
+COMPETITOR/M/S
+COMPILATION/M/S
+COMPILE/D/R/Z/G/S
+COMPILER'S
+COMPLAIN/D/R/Z/G/S
+COMPLAINT/M/S
+COMPLEMENT/D/R/Z/G/S
+COMPLEMENTARY
+COMPLETE/P/D/G/N/X/Y/S
+COMPLEX/Y/S
+COMPLEXION
+COMPLEXITY/S
+COMPLIANCE
+COMPLICATE/D/G/N/X/S
+COMPLICATOR/M/S
+COMPLICITY
+COMPLIMENT/D/R/Z/G/S
+COMPLIMENTARY
+COMPLY/D/G
+COMPONENT/M/S
+COMPONENTWISE
+COMPOSE/D/R/Z/G/S
+COMPOSEDLY
+COMPOSITE/N/X/S
+COMPOSITIONAL
+COMPOSURE
+COMPOUND/D/G/S
+COMPREHEND/D/G/S
+COMPREHENSIBILITY
+COMPREHENSIBLE
+COMPREHENSION
+COMPREHENSIVE/Y
+COMPRESS/D/G/V/S
+COMPRESSIBLE
+COMPRESSION
+COMPRISE/D/G/S
+COMPROMISE/D/R/Z/G/S
+COMPROMISING/Y
+COMPTROLLER/M/S
+COMPULSION/M/S
+COMPULSORY
+COMPUNCTION
+COMPUTABILITY
+COMPUTABLE
+COMPUTATION/M/S
+COMPUTATIONAL/Y
+COMPUTE/D/R/Z/G/S
+COMPUTER'S
+COMPUTERIZE/D/G/S
+COMRADE/Y/S
+COMRADESHIP
+CONCATENATE/D/G/N/X/S
+CONCEAL/D/R/Z/G/S
+CONCEALMENT
+CONCEDE/D/G/S
+CONCEIT/D/S
+CONCEIVABLE
+CONCEIVABLY
+CONCEIVE/D/G/S
+CONCENTRATE/D/G/N/X/S
+CONCENTRATOR/S
+CONCENTRIC
+CONCEPT/M/S
+CONCEPTION/M/S
+CONCEPTUAL/Y
+CONCEPTUALIZATION/M/S
+CONCEPTUALIZE/D/G/S
+CONCERN/D/G/S
+CONCERNEDLY
+CONCERT/D/S
+CONCESSION/M/S
+CONCISE/P/Y
+CONCLUDE/D/G/S
+CONCLUSION/M/S
+CONCLUSIVE/Y
+CONCOCT
+CONCOMITANT
+CONCORD
+CONCORDANCE
+CONCRETE/P/N/Y/S
+CONCUR/S
+CONCURRED
+CONCURRENCE
+CONCURRENCY/S
+CONCURRENT/Y
+CONCURRING
+CONDEMN/D/R/Z/G/S
+CONDEMNATION/S
+CONDENSATION
+CONDENSE/D/R/G/S
+CONDESCEND/G
+CONDITION/D/R/Z/G/S
+CONDITIONAL/Y/S
+CONDONE/D/G/S
+CONDUCIVE
+CONDUCT/D/G/V/S
+CONDUCTION
+CONDUCTIVITY
+CONDUCTOR/M/S
+CONE/M/S
+CONFEDERACY
+CONFEDERATE/N/X/S
+CONFER/S
+CONFERENCE/M/S
+CONFERRED
+CONFERRER/M/S
+CONFERRING
+CONFESS/D/G/S
+CONFESSION/M/S
+CONFESSOR/M/S
+CONFIDANT/M/S
+CONFIDE/D/G/S
+CONFIDENCE/S
+CONFIDENT/Y
+CONFIDENTIAL/Y
+CONFIDENTIALITY
+CONFIDINGLY
+CONFIGURABLE
+CONFIGURATION/M/S
+CONFIGURE/D/G/S
+CONFINE/D/R/G/S
+CONFINEMENT/M/S
+CONFIRM/D/G/S
+CONFIRMATION/M/S
+CONFISCATE/D/G/N/X/S
+CONFLICT/D/G/S
+CONFORM/D/G/S
+CONFORMITY
+CONFOUND/D/G/S
+CONFRONT/D/R/Z/G/S
+CONFRONTATION/M/S
+CONFUSE/D/R/Z/G/N/X/S
+CONFUSINGLY
+CONGENIAL/Y
+CONGESTED
+CONGESTION
+CONGRATULATE/D/N/X
+CONGREGATE/D/G/N/X/S
+CONGRESS/M/S
+CONGRESSIONAL/Y
+CONGRESSMAN
+CONGRUENCE
+CONGRUENT
+CONIC
+CONJECTURE/D/G/S
+CONJOINED
+CONJUNCT/D/V/S
+CONJUNCTION/M/S
+CONJUNCTIVELY
+CONJURE/D/R/G/S
+CONNECT/D/G/S
+CONNECTEDNESS
+CONNECTICUT
+CONNECTION/M/S
+CONNECTIONIST
+CONNECTIVE/M/S
+CONNECTIVITY
+CONNECTOR/M/S
+CONNOISSEUR/M/S
+CONNOTE/D/G/S
+CONQUER/D/R/Z/G/S
+CONQUERABLE
+CONQUEROR/M/S
+CONQUEST/M/S
+CONS
+CONSCIENCE/M/S
+CONSCIENTIOUS/Y
+CONSCIOUS/P/Y
+CONSECRATE/N
+CONSECUTIVE/Y
+CONSENSUS
+CONSENT/D/R/Z/G/S
+CONSEQUENCE/M/S
+CONSEQUENT/Y/S
+CONSEQUENTIAL
+CONSEQUENTIALITY/S
+CONSERVATION/M/S
+CONSERVATIONIST/M/S
+CONSERVATISM
+CONSERVATIVE/Y/S
+CONSERVE/D/G/S
+CONSIDER/D/G/S
+CONSIDERABLE
+CONSIDERABLY
+CONSIDERATE/N/X/Y
+CONSIGN/D/G/S
+CONSIST/D/G/S
+CONSISTENCY
+CONSISTENT/Y
+CONSOLABLE
+CONSOLATION/M/S
+CONSOLE/D/R/Z/G/S
+CONSOLIDATE/D/G/N/S
+CONSOLINGLY
+CONSONANT/M/S
+CONSORT/D/G/S
+CONSORTIUM
+CONSPICUOUS/Y
+CONSPIRACY/M/S
+CONSPIRATOR/M/S
+CONSPIRE/D/S
+CONSTABLE/M/S
+CONSTANCY
+CONSTANT/Y/S
+CONSTELLATION/M/S
+CONSTERNATION
+CONSTITUENCY/M/S
+CONSTITUENT/M/S
+CONSTITUTE/D/G/N/X/V/S
+CONSTITUTIONAL/Y
+CONSTITUTIONALITY
+CONSTRAIN/D/G/S
+CONSTRAINT/M/S
+CONSTRUCT/D/G/V/S
+CONSTRUCTIBILITY
+CONSTRUCTIBLE
+CONSTRUCTION/M/S
+CONSTRUCTIVELY
+CONSTRUCTOR/M/S
+CONSTRUE/D/G
+CONSUL/M/S
+CONSULATE/M/S
+CONSULT/D/G/S
+CONSULTANT/M/S
+CONSULTATION/M/S
+CONSUMABLE
+CONSUME/D/R/Z/G/S
+CONSUMER'S
+CONSUMMATE/D/N/Y
+CONSUMPTION/M/S
+CONSUMPTIVE/Y
+CONTACT/D/G/S
+CONTAGION
+CONTAGIOUS/Y
+CONTAIN/D/R/Z/G/S
+CONTAINABLE
+CONTAINMENT/M/S
+CONTAMINATE/D/G/N/S
+CONTEMPLATE/D/G/N/X/V/S
+CONTEMPORARY/P/S
+CONTEMPT
+CONTEMPTIBLE
+CONTEMPTUOUS/Y
+CONTEND/D/R/Z/G/S
+CONTENT/D/G/Y/S
+CONTENTION/M/S
+CONTENTMENT
+CONTEST/D/R/Z/G/S
+CONTESTABLE
+CONTEXT/M/S
+CONTEXTUAL/Y
+CONTIGUITY
+CONTIGUOUS/Y
+CONTINENT/M/S
+CONTINENTAL/Y
+CONTINGENCY/M/S
+CONTINGENT/M/S
+CONTINUAL/Y
+CONTINUANCE/M/S
+CONTINUATION/M/S
+CONTINUE/D/G/S
+CONTINUITY/S
+CONTINUO
+CONTINUOUS/Y
+CONTINUUM
+CONTOUR/D/M/G/S
+CONTRACT/D/G/S
+CONTRACTION/M/S
+CONTRACTOR/M/S
+CONTRACTUAL/Y
+CONTRADICT/D/G/S
+CONTRADICTION/M/S
+CONTRADICTORY
+CONTRADISTINCTION/S
+CONTRAPOSITIVE/S
+CONTRAPTION/M/S
+CONTRARY/P
+CONTRAST/D/R/Z/G/S
+CONTRASTINGLY
+CONTRIBUTE/D/G/N/X/S
+CONTRIBUTOR/M/S
+CONTRIBUTORILY
+CONTRIBUTORY
+CONTRIVANCE/M/S
+CONTRIVE/D/R/G/S
+CONTROL/M/S
+CONTROLLABILITY
+CONTROLLABLE
+CONTROLLABLY
+CONTROLLED
+CONTROLLER/M/S
+CONTROLLING
+CONTROVERSIAL
+CONTROVERSY/M/S
+CONUNDRUM/M/S
+CONVENE/D/G/S
+CONVENIENCE/M/S
+CONVENIENT/Y
+CONVENT/M/S
+CONVENTION/M/S
+CONVENTIONAL/Y
+CONVERGE/D/G/S
+CONVERGENCE
+CONVERGENT
+CONVERSANT/Y
+CONVERSATION/M/S
+CONVERSATIONAL/Y
+CONVERSE/D/G/N/X/Y/S
+CONVERT/D/R/Z/G/S
+CONVERTIBILITY
+CONVERTIBLE
+CONVEX
+CONVEY/D/R/Z/G/S
+CONVEYANCE/M/S
+CONVICT/D/G/S
+CONVICTION/M/S
+CONVINCE/D/R/Z/G/S
+CONVINCINGLY
+CONVOLUTED
+CONVOY/D/G/S
+CONVULSION/M/S
+COO/G
+COOK/D/G/S
+COOKERY
+COOKIE/M/S
+COOKY
+COOL/P/D/T/G/Y/S
+COOLER/M/S
+COOLIE/M/S
+COON/M/S
+COOP/D/R/Z/S
+COOPERATE/D/G/N/X/V/S
+COOPERATIVELY
+COOPERATIVES
+COOPERATOR/M/S
+COORDINATE/D/G/N/X/S
+COORDINATOR/M/S
+COP/M/S
+COPE/D/G/J/S
+COPIOUS/P/Y
+COPPER/M/S
+COPSE
+COPY/D/R/Z/G/S
+COPYRIGHT/M/S
+CORAL
+CORD/D/R/S
+CORDIAL/Y
+CORE/D/R/Z/G/S
+CORK/D/R/Z/G/S
+CORMORANT
+CORN/R/Z/G/S
+CORNERED
+CORNERSTONE/M/S
+CORNFIELD/M/S
+COROLLARY/M/S
+CORONARY/S
+CORONATION
+CORONET/M/S
+COROUTINE/M/S
+CORPOCRACY/S
+CORPORAL/M/S
+CORPORATE/N/X/Y
+CORPORATION'S
+CORPS
+CORPSE/M/S
+CORPUS
+CORRECT/P/D/G/Y/S
+CORRECTABLE
+CORRECTION/S
+CORRECTIVE/Y/S
+CORRECTOR
+CORRELATE/D/G/N/X/V/S
+CORRESPOND/D/G/S
+CORRESPONDENCE/M/S
+CORRESPONDENT/M/S
+CORRESPONDINGLY
+CORRIDOR/M/S
+CORROBORATE/D/G/N/X/V/S
+CORROSION
+CORRUPT/D/R/G/S
+CORRUPTION
+CORSET
+CORTEX
+CORTICAL
+COSINE/S
+COSMETIC/S
+COSMOLOGY
+COSMOPOLITAN
+COST/D/G/Y/S
+COSTUME/D/R/G/S
+COT/M/S
+COTTAGE/R/S
+COTTON/S
+COTYLEDON/M/S
+COUCH/D/G/S
+COUGH/D/G
+COUGHS
+COULD
+COULDN'T
+COUNCIL/M/S
+COUNCILLOR/M/S
+COUNSEL/D/G/S
+COUNSELLED
+COUNSELLING
+COUNSELLOR/M/S
+COUNSELOR/M/S
+COUNT/D/Z/G/S
+COUNTABLE
+COUNTABLY
+COUNTENANCE
+COUNTER/D/G/S
+COUNTERACT/D/G/V
+COUNTERCLOCKWISE
+COUNTEREXAMPLE/S
+COUNTERFEIT/D/R/G
+COUNTERMEASURE/M/S
+COUNTERPART/M/S
+COUNTERPOINT/G
+COUNTERPRODUCTIVE
+COUNTERREVOLUTION
+COUNTESS
+COUNTLESS
+COUNTRY/M/S
+COUNTRYMAN
+COUNTRYSIDE
+COUNTY/M/S
+COUPLE/D/R/Z/G/J/S
+COUPON/M/S
+COURAGE
+COURAGEOUS/Y
+COURIER/M/S
+COURSE/D/R/G/S
+COURT/D/R/Z/G/Y/S
+COURTEOUS/Y
+COURTESY/M/S
+COURTHOUSE/M/S
+COURTIER/M/S
+COURTROOM/M/S
+COURTSHIP
+COURTYARD/M/S
+COUSIN/M/S
+COVE/Z/S
+COVENANT/M/S
+COVER/D/G/J/S
+COVERABLE
+COVERAGE
+COVERLET/M/S
+COVERT/Y
+COVET/D/G/S
+COVETOUS/P
+COW/D/Z/G/S
+COWARD/Y
+COWARDICE
+COWBOY/M/S
+COWER/D/R/Z/G/S
+COWERINGLY
+COWL/G/S
+COWSLIP/M/S
+COYOTE/M/S
+COZY/P/R
+CPU
+CRAB/M/S
+CRACK/D/R/Z/G/S
+CRACKLE/D/G/S
+CRADLE/D/S
+CRAFT/D/R/G/S
+CRAFTSMAN
+CRAFTY/P
+CRAG/M/S
+CRAM/S
+CRAMP/M/S
+CRANBERRY/M/S
+CRANE/M/S
+CRANK/D/G/S
+CRANKILY
+CRANKY/T/R
+CRASH/D/R/Z/G/S
+CRATE/R/Z/S
+CRAVAT/M/S
+CRAVE/D/G/S
+CRAVEN
+CRAWL/D/R/Z/G/S
+CRAY
+CRAZE/D/G/S
+CRAZILY
+CRAZY/P/T/R
+CREAK/D/G/S
+CREAM/D/R/Z/G/S
+CREAMY
+CREASE/D/G/S
+CREATE/D/G/N/X/V/S
+CREATIVELY
+CREATIVENESS
+CREATIVITY
+CREATOR/M/S
+CREATURE/M/S
+CREDENCE
+CREDIBILITY
+CREDIBLE
+CREDIBLY
+CREDIT/D/G/S
+CREDITABLE
+CREDITABLY
+CREDITOR/M/S
+CREDULITY
+CREDULOUS/P
+CREED/M/S
+CREEK/M/S
+CREEP/R/Z/G/S
+CREMATE/D/G/N/X/S
+CREPE
+CREPT
+CRESCENT/M/S
+CREST/D/S
+CREVICE/M/S
+CREW/D/G/S
+CRIB/M/S
+CRICKET/M/S
+CRIME/M/S
+CRIMINAL/Y/S
+CRIMSON/G
+CRINGE/D/G/S
+CRIPPLE/D/G/S
+CRISES
+CRISIS
+CRISP/P/Y
+CRITERIA
+CRITERION
+CRITIC/M/S
+CRITICAL/Y
+CRITICISE/D
+CRITICISM/M/S
+CRITICIZE/D/G/S
+CRITIQUE/G/S
+CROAK/D/G/S
+CROCHET/S
+CROOK/D/S
+CROP/M/S
+CROPPED
+CROPPER/M/S
+CROPPING
+CROSS/D/R/Z/G/Y/J/S
+CROSSABLE
+CROSSBAR/M/S
+CROSSOVER/M/S
+CROSSWORD/M/S
+CROUCH/D/G
+CROW/D/G/S
+CROWD/D/R/G/S
+CROWN/D/G/S
+CRT
+CRUCIAL/Y
+CRUCIFY/D/G/S
+CRUDE/P/T/Y
+CRUEL/T/R/Y
+CRUELTY
+CRUISE/R/Z/G/S
+CRUMB/Y/S
+CRUMBLE/D/G/S
+CRUMPLE/D/G/S
+CRUNCH/D/G/S
+CRUNCHY/T/R
+CRUSADE/R/Z/G/S
+CRUSH/D/R/Z/G/S
+CRUSHABLE
+CRUSHINGLY
+CRUST/M/S
+CRUSTACEAN/M/S
+CRUTCH/M/S
+CRUX/M/S
+CRY/D/R/Z/G/S
+CRYPTANALYSIS
+CRYPTOGRAPHIC
+CRYPTOGRAPHY
+CRYPTOLOGY
+CRYSTAL/M/S
+CRYSTALLINE
+CRYSTALLIZE/D/G/S
+CS
+CSD
+CUB/M/S
+CUBE/D/S
+CUBIC
+CUCKOO/M/S
+CUCUMBER/M/S
+CUDDLE/D
+CUDGEL/M/S
+CUE/D/S
+CUFF/M/S
+CULL/D/R/G/S
+CULMINATE/D/G/N/S
+CULPRIT/M/S
+CULT/M/S
+CULTIVATE/D/G/N/X/S
+CULTIVATOR/M/S
+CULTURAL/Y
+CULTURE/D/G/S
+CUMBERSOME
+CUMULATIVE/Y
+CUNNING/Y
+CUP/M/S
+CUPBOARD/M/S
+CUPFUL
+CUPPED
+CUPPING
+CUR/Y/S
+CURABLE
+CURABLY
+CURB/G/S
+CURD
+CURE/D/G/S
+CURFEW/M/S
+CURIOSITY/M/S
+CURIOUS/T/R/Y
+CURL/D/R/Z/G/S
+CURRANT/M/S
+CURRENCY/M/S
+CURRENT/P/Y/S
+CURRICULA
+CURRICULAR
+CURRICULUM/M/S
+CURRY/D/G/S
+CURSE/D/G/V/S
+CURSOR/M/S
+CURSORILY
+CURSORY
+CURT/P/Y
+CURTAIL/D/S
+CURTAIN/D/S
+CURTATE
+CURTSY/M/S
+CURVATURE
+CURVE/D/G/S
+CUSHION/D/G/S
+CUSP/M/S
+CUSTARD
+CUSTODIAN/M/S
+CUSTODY
+CUSTOM/R/Z/S
+CUSTOMARILY
+CUSTOMARY
+CUSTOMIZABLE
+CUSTOMIZATION/M/S
+CUSTOMIZE/D/R/Z/G/S
+CUT/M/S
+CUTE/T
+CUTOFF
+CUTTER/M/S
+CUTTING/Y/S
+CYBERNETIC
+CYCLE/D/G/S
+CYCLIC
+CYCLICALLY
+CYCLOID/M/S
+CYCLOIDAL
+CYCLONE/M/S
+CYLINDER/M/S
+CYLINDRICAL
+CYMBAL/M/S
+CYNICAL/Y
+CYPRESS
+CYST/S
+CYTOLOGY
+CZAR
+DABBLE/D/R/G/S
+DAD/M/S
+DADDY
+DAEMON/M/S
+DAFFODIL/M/S
+DAGGER
+DAILY/S
+DAINTILY
+DAINTY/P
+DAIRY
+DAISY/M/S
+DALE/M/S
+DAM/M/S
+DAMAGE/D/R/Z/G/S
+DAMASK
+DAME
+DAMN/D/G/S
+DAMNATION
+DAMP/P/R/G/N/X
+DAMSEL/M/S
+DAN/M
+DANCE/D/R/Z/G/S
+DANDELION/M/S
+DANDY
+DANGER/M/S
+DANGEROUS/Y
+DANGLE/D/G/S
+DANIEL/M
+DARE/D/R/Z/G/S
+DARESAY
+DARINGLY
+DARK/P/T/R/N/Y
+DARLING/M/S
+DARN/D/R/G/S
+DARPA
+DART/D/R/G/S
+DASH/D/R/Z/G/S
+DASHING/Y
+DATA
+DATABASE/M/S
+DATE/D/R/G/V/S
+DATUM
+DAUGHTER/Y/S
+DAUNT/D
+DAUNTLESS
+DAVE/M
+DAVID/M
+DAWN/D/G/S
+DAY/M/S
+DAYBREAK
+DAYDREAM/G/S
+DAYLIGHT/M/S
+DAYTIME
+DAZE/D
+DAZZLE/D/R/G/S
+DAZZLINGLY
+DBMS
+DEACON/M/S
+DEAD/P/N/Y
+DEADLINE/M/S
+DEADLOCK/D/G/S
+DEAF/P/T/R/N
+DEAL/R/Z/G/J/S
+DEALLOCATE/D/G/N/X/S
+DEALLOCATED
+DEALLOCATION
+DEALT
+DEAN/M/S
+DEAR/P/T/R/H/Y
+DEARTHS
+DEATH/Y
+DEATHRATE/M/S
+DEATHS
+DEBATABLE
+DEBATE/D/R/Z/G/S
+DEBBIE/M
+DEBILITATE/D/G/S
+DEBRIS
+DEBT/M/S
+DEBTOR
+DEBUG/S
+DEBUGGED
+DEBUGGER/M/S
+DEBUGGING
+DECADE/M/S
+DECADENCE
+DECADENT/Y
+DECAY/D/G/S
+DECEASE/D/G/S
+DECEIT
+DECEITFUL/P/Y
+DECEIVE/D/R/Z/G/S
+DECELERATE/D/G/N/S
+DECEMBER
+DECENCY/M/S
+DECENT/Y
+DECENTRALIZATION
+DECENTRALIZED
+DECEPTION/M/S
+DECEPTIVE/Y
+DECIDABILITY
+DECIDABLE
+DECIDE/D/G/S
+DECIDEDLY
+DECIMAL/S
+DECIMATE/D/G/N/S
+DECIPHER/D/R/G/S
+DECISION/M/S
+DECISIVE/P/Y
+DECK/D/G/J/S
+DECLARATION/M/S
+DECLARATIVE/Y/S
+DECLARE/D/R/Z/G/S
+DECLINATION/M/S
+DECLINE/D/R/Z/G/S
+DECODE/D/R/Z/G/J/S
+DECOMPOSABILITY
+DECOMPOSABLE
+DECOMPOSE/D/G/S
+DECOMPOSITION/M/S
+DECOMPRESSION
+DECONSTRUCT/D/G/S
+DECONSTRUCTION
+DECORATE/D/G/N/X/V/S
+DECORUM
+DECOUPLE/D/G/S
+DECOY/M/S
+DECREASE/D/G/S
+DECREASINGLY
+DECREE/D/S
+DECREEING
+DECREMENT/D/G/S
+DEDICATE/D/G/N/S
+DEDUCE/D/R/G/S
+DEDUCIBLE
+DEDUCT/D/G/V
+DEDUCTION/M/S
+DEED/D/G/S
+DEEM/D/G/S
+DEEMPHASIZE/D/G/S
+DEEP/T/R/N/Y/S
+DEEPEN/D/G/S
+DEER
+DEFAULT/D/R/G/S
+DEFEAT/D/G/S
+DEFECT/D/G/V/S
+DEFECTION/M/S
+DEFEND/D/R/Z/G/S
+DEFENDANT/M/S
+DEFENESTRATE/D/G/N/S
+DEFENSE/V/S
+DEFENSELESS
+DEFER/S
+DEFERENCE
+DEFERMENT/M/S
+DEFERRABLE
+DEFERRED
+DEFERRER/M/S
+DEFERRING
+DEFIANCE
+DEFIANT/Y
+DEFICIENCY/S
+DEFICIENT
+DEFICIT/M/S
+DEFILE/G
+DEFINABLE
+DEFINE/D/R/G/S
+DEFINITE/P/N/X/Y
+DEFINITION/M/S
+DEFINITIONAL
+DEFINITIVE
+DEFORMATION/M/S
+DEFORMED
+DEFORMITY/M/S
+DEFTLY
+DEFY/D/G/S
+DEGENERATE/D/G/N/V/S
+DEGRADABLE
+DEGRADATION/M/S
+DEGRADE/D/G/S
+DEGREE/M/S
+DEIGN/D/G/S
+DEITY/M/S
+DEJECTED/Y
+DELAWARE
+DELAY/D/G/S
+DELEGATE/D/G/N/X/S
+DELETE/D/R/G/N/X/S
+DELIBERATE/P/D/G/N/X/Y/S
+DELIBERATIVE
+DELIBERATOR/M/S
+DELICACY/M/S
+DELICATE/Y
+DELICIOUS/Y
+DELIGHT/D/G/S
+DELIGHTEDLY
+DELIGHTFUL/Y
+DELIMIT/D/R/Z/G/S
+DELINEATE/D/G/N/S
+DELIRIOUS/Y
+DELIVER/D/R/Z/G/S
+DELIVERABLE/S
+DELIVERANCE
+DELIVERY/M/S
+DELL/M/S
+DELTA/M/S
+DELUDE/D/G/S
+DELUGE/D/S
+DELUSION/M/S
+DELVE/G/S
+DEMAND/D/R/G/S
+DEMANDINGLY
+DEMARCATE/N/D/G/S
+DEMEANOR
+DEMISE
+DEMO/S
+DEMOCRACY/M/S
+DEMOCRAT/M/S
+DEMOCRATIC
+DEMOCRATICALLY
+DEMOGRAPHIC
+DEMOLISH/D/S
+DEMOLITION
+DEMON/M/S
+DEMONSTRABLE
+DEMONSTRATE/D/G/N/X/V/S
+DEMONSTRATIVELY
+DEMONSTRATOR/M/S
+DEMORALIZE/D/G/S
+DEMUR
+DEN/M/S
+DENDRITE/S
+DENIABLE
+DENIAL/M/S
+DENIGRATE/D/G/S
+DENMARK
+DENOMINATION/M/S
+DENOMINATOR/M/S
+DENOTABLE
+DENOTATION/M/S
+DENOTATIONAL/Y
+DENOTE/D/G/S
+DENOUNCE/D/G/S
+DENSE/P/T/R/Y
+DENSITY/M/S
+DENT/D/G/S
+DENTAL/Y
+DENTIST/M/S
+DENY/D/R/G/S
+DEPART/D/G/S
+DEPARTMENT/M/S
+DEPARTMENTAL
+DEPARTURE/M/S
+DEPEND/D/G/S
+DEPENDABILITY
+DEPENDABLE
+DEPENDABLY
+DEPENDENCE
+DEPENDENCY/S
+DEPENDENT/Y/S
+DEPICT/D/G/S
+DEPLETE/D/G/N/X/S
+DEPLORABLE
+DEPLORE/D/S
+DEPLOY/D/G/S
+DEPLOYABLE
+DEPLOYMENT/M/S
+DEPORTATION
+DEPORTMENT
+DEPOSE/D/S
+DEPOSIT/D/G/S
+DEPOSITION/M/S
+DEPOSITOR/M/S
+DEPOT/M/S
+DEPRAVE/D
+DEPRECIATE/N/S
+DEPRESS/D/G/S
+DEPRESSION/M/S
+DEPRIVATION/M/S
+DEPRIVE/D/G/S
+DEPT
+DEPTH
+DEPTHS
+DEPUTY/M/S
+DEQUEUE/D/G/S
+DERAIL/D/G/S
+DERBY
+DERIDE
+DERISION
+DERIVABLE
+DERIVATION/M/S
+DERIVATIVE/M/S
+DERIVE/D/G/S
+DESCEND/D/R/Z/G/S
+DESCENDANT/M/S
+DESCENT/M/S
+DESCRIBABLE
+DESCRIBE/D/R/G/S
+DESCRIPTION/M/S
+DESCRIPTIVE/Y/S
+DESCRIPTOR/M/S
+DESCRY
+DESELECTED
+DESERT/D/R/Z/G/S
+DESERTION/S
+DESERVE/D/G/J/S
+DESERVINGLY
+DESIDERATA
+DESIDERATUM
+DESIGN/D/R/Z/G/S
+DESIGNATE/D/G/N/X/S
+DESIGNATOR/M/S
+DESIGNER'S
+DESIRABILITY
+DESIRABLE
+DESIRABLY
+DESIRE/D/G/S
+DESIROUS
+DESK/M/S
+DESOLATE/N/X/Y
+DESPAIR/D/G/S
+DESPAIRINGLY
+DESPATCH/D
+DESPERATE/N/Y
+DESPISE/D/G/S
+DESPITE
+DESPOT/M/S
+DESPOTIC
+DESSERT/M/S
+DESTINATION/M/S
+DESTINE/D
+DESTINY/M/S
+DESTITUTE/N
+DESTROY/D/G/S
+DESTROYER/M/S
+DESTRUCTION/M/S
+DESTRUCTIVE/P/Y
+DETACH/D/R/G/S
+DETACHMENT/M/S
+DETAIL/D/G/S
+DETAIN/D/G/S
+DETECT/D/G/V/S
+DETECTABLE
+DETECTABLY
+DETECTION/M/S
+DETECTIVES
+DETECTOR/M/S
+DETENTION
+DETERIORATE/D/G/N/S
+DETERMINABLE
+DETERMINACY
+DETERMINANT/M/S
+DETERMINATE/N/X/V/Y
+DETERMINE/D/R/Z/G/S
+DETERMINISM
+DETERMINISTIC
+DETERMINISTICALLY
+DETERRENT
+DETEST/D
+DETESTABLE
+DETRACT/S
+DETRACTOR/M/S
+DETRIMENT
+DETRIMENTAL
+DEVASTATE/D/G/N/S
+DEVELOP/D/R/Z/G/S
+DEVELOPMENT/M/S
+DEVELOPMENTAL
+DEVIANT/M/S
+DEVIATE/D/G/N/X/S
+DEVICE/M/S
+DEVIL/M/S
+DEVILISH/Y
+DEVISE/D/G/J/S
+DEVOID
+DEVOTE/D/G/N/X/S
+DEVOTEDLY
+DEVOTEE/M/S
+DEVOUR/D/R/S
+DEVOUT/P/Y
+DEW
+DEWDROP/M/S
+DEWY
+DEXTERITY
+DIADEM
+DIAGNOSABLE
+DIAGNOSE/D/G/S
+DIAGNOSIS
+DIAGNOSTIC/M/S
+DIAGONAL/Y/S
+DIAGRAM/M/S
+DIAGRAMMABLE
+DIAGRAMMATIC
+DIAGRAMMATICALLY
+DIAGRAMMED
+DIAGRAMMER/M/S
+DIAGRAMMING
+DIAL/D/G/S
+DIALECT/M/S
+DIALOG/M/S
+DIALOGUE/M/S
+DIAMETER/M/S
+DIAMETRICALLY
+DIAMOND/M/S
+DIAPER/M/S
+DIAPHRAGM/M/S
+DIARY/M/S
+DIATRIBE/M/S
+DICE
+DICHOTOMIZE
+DICHOTOMY
+DICKENS
+DICKY
+DICTATE/D/G/N/X/S
+DICTATOR/M/S
+DICTATORSHIP
+DICTION
+DICTIONARY/M/S
+DICTUM/M/S
+DID
+DIDN'T
+DIE/D/S
+DIEGO
+DIELECTRIC/M/S
+DIET/R/Z/S
+DIETITIAN/M/S
+DIFFER/D/G/R/S/Z
+DIFFERENCE/M/S
+DIFFERENT/Y
+DIFFERENTIAL/M/S
+DIFFERENTIATE/D/G/N/X/S
+DIFFERENTIATORS
+DIFFICULT/Y
+DIFFICULTY/M/S
+DIFFUSE/D/R/Z/G/N/X/Y/S
+DIG/S
+DIGEST/D/G/V/S
+DIGESTIBLE
+DIGESTION
+DIGGER/M/S
+DIGGING/S
+DIGIT/M/S
+DIGITAL/Y
+DIGITIZE/S/G/D
+DIGNIFY/D
+DIGNITY/S
+DIGRESS/D/G/V/S
+DIGRESSION/M/S
+DIKE/M/S
+DILATE/D/G/N/S
+DILEMMA/M/S
+DILIGENCE
+DILIGENT/Y
+DILUTE/D/G/N/S
+DIM/P/Y/S
+DIME/M/S
+DIMENSION/D/G/S
+DIMENSIONAL/Y
+DIMENSIONALITY
+DIMINISH/D/G/S
+DIMINUTION
+DIMINUTIVE
+DIMMED
+DIMMER/M/S
+DIMMEST
+DIMMING
+DIMPLE/D
+DIN
+DINE/D/R/Z/G/S
+DINGY/P
+DINNER/M/S
+DINT
+DIODE/M/S
+DIOPHANTINE
+DIOXIDE
+DIP/S
+DIPHTHERIA
+DIPLOMA/M/S
+DIPLOMACY
+DIPLOMAT/M/S
+DIPLOMATIC
+DIPPED
+DIPPER/M/S
+DIPPING/S
+DIRE
+DIRECT/P/D/G/Y/S
+DIRECTION/M/S
+DIRECTIONAL/Y
+DIRECTIONALITY
+DIRECTIVE/M/S
+DIRECTOR/M/S
+DIRECTORY/M/S
+DIRGE/M/S
+DIRT/S
+DIRTILY
+DIRTY/P/T/R
+DISABILITY/M/S
+DISABLE/D/R/Z/G/S
+DISADVANTAGE/M/S
+DISAGREE/D/S
+DISAGREEABLE
+DISAGREEING
+DISAGREEMENT/M/S
+DISALLOW/D/G/S
+DISAMBIGUATE/D/G/N/X/S
+DISAPPEAR/D/G/S
+DISAPPEARANCE/M/S
+DISAPPOINT/D/G
+DISAPPOINTMENT/M/S
+DISAPPROVAL
+DISAPPROVE/D/S
+DISARM/D/G/S
+DISARMAMENT
+DISASSEMBLE/D/G/S
+DISASTER/M/S
+DISASTROUS/Y
+DISBAND/D/G/S
+DISBURSE/D/G/S
+DISBURSEMENT/M/S
+DISC/M/S
+DISCARD/D/G/S
+DISCERN/D/G/S
+DISCERNIBILITY
+DISCERNIBLE
+DISCERNIBLY
+DISCERNINGLY
+DISCERNMENT
+DISCHARGE/D/G/S
+DISCIPLE/M/S
+DISCIPLINARY
+DISCIPLINE/D/G/S
+DISCLAIM/D/R/S
+DISCLOSE/D/G/S
+DISCLOSURE/M/S
+DISCOMFORT
+DISCONCERT
+DISCONCERTING/Y
+DISCONNECT/D/G/S
+DISCONNECTION
+DISCONTENT/D
+DISCONTINUANCE
+DISCONTINUE/D/S
+DISCONTINUITY/M/S
+DISCONTINUOUS
+DISCORD
+DISCOUNT/D/G/S
+DISCOURAGE/D/G/S
+DISCOURAGEMENT
+DISCOURSE/M/S
+DISCOVER/D/R/Z/G/S
+DISCOVERY/M/S
+DISCREDIT/D
+DISCREET/Y
+DISCREPANCY/M/S
+DISCRETE/P/N/Y
+DISCRIMINATE/D/G/N/S
+DISCRIMINATORY
+DISCUSS/D/G/S
+DISCUSSION/M/S
+DISDAIN/G/S
+DISEASE/D/S
+DISENGAGE/D/G/S
+DISFIGURE/D/G/S
+DISGORGE
+DISGRACE/D/S
+DISGRACEFUL/Y
+DISGRUNTLED
+DISGUISE/D/S
+DISGUST/D/G/S
+DISGUSTEDLY
+DISGUSTINGLY
+DISH/D/G/S
+DISHEARTEN/G
+DISHONEST/Y
+DISHONOR/D/G/S
+DISHWASHER/S
+DISHWASHING
+DISILLUSION/D/G
+DISILLUSIONMENT/M/S
+DISINTERESTED/P
+DISJOINT/P/D
+DISJUNCT/V/S
+DISJUNCTION/S
+DISJUNCTIVELY
+DISK/M/S
+DISKETTE/S
+DISLIKE/D/G/S
+DISLOCATE/D/G/N/X/S
+DISLODGE/D
+DISMAL/Y
+DISMAY/D/G
+DISMISS/D/R/Z/G/S
+DISMISSAL/M/S
+DISMOUNT/D/G/S
+DISOBEDIENCE
+DISOBEY/D/G/S
+DISORDER/D/Y/S
+DISORGANIZED
+DISORIENTED
+DISOWN/D/G/S
+DISPARATE
+DISPARITY/M/S
+DISPATCH/D/R/Z/G/S
+DISPEL/S
+DISPELLED
+DISPELLING
+DISPENSATION
+DISPENSE/D/R/Z/G/S
+DISPERSE/D/G/N/X/S
+DISPLACE/D/G/S
+DISPLACEMENT/M/S
+DISPLAY/D/G/S
+DISPLEASE/D/G/S
+DISPLEASURE
+DISPOSABLE
+DISPOSAL/M/S
+DISPOSE/D/R/G/S
+DISPOSITION/M/S
+DISPROVE/D/G/S
+DISPUTE/D/R/Z/G/S
+DISQUALIFY/D/G/N/S
+DISQUIET/G
+DISREGARD/D/G/S
+DISRUPT/D/G/V/S
+DISRUPTION/M/S
+DISSATISFACTION/M/S
+DISSATISFIED
+DISSEMINATE/D/G/N/S
+DISSENSION/M/S
+DISSENT/D/R/Z/G/S
+DISSERTATION/M/S
+DISSERVICE
+DISSIDENT/M/S
+DISSIMILAR
+DISSIMILARITY/M/S
+DISSIPATE/D/G/N/S
+DISSOCIATE/D/G/N/S
+DISSOLUTION/M/S
+DISSOLVE/D/G/S
+DISTAL/Y
+DISTANCE/S
+DISTANT/Y
+DISTASTE/S
+DISTASTEFUL/Y
+DISTEMPER
+DISTILL/D/R/Z/G/S
+DISTILLATION
+DISTINCT/P/Y
+DISTINCTION/M/S
+DISTINCTIVE/P/Y
+DISTINGUISH/D/G/S
+DISTINGUISHABLE
+DISTORT/D/G/S
+DISTORTION/M/S
+DISTRACT/D/G/S
+DISTRACTION/M/S
+DISTRAUGHT
+DISTRESS/D/G/S
+DISTRIBUTE/D/G/N/V/S
+DISTRIBUTION/M/S
+DISTRIBUTIONAL
+DISTRIBUTIVITY
+DISTRIBUTOR/M/S
+DISTRICT/M/S
+DISTRUST/D
+DISTURB/D/R/G/S
+DISTURBANCE/M/S
+DISTURBINGLY
+DITCH/M/S
+DITTO
+DIVAN/M/S
+DIVE/D/R/Z/G/S
+DIVERGE/D/G/S
+DIVERGENCE/M/S
+DIVERGENT
+DIVERSE/N/X/Y
+DIVERSIFY/D/G/N/S
+DIVERSITY/S
+DIVERT/D/G/S
+DIVEST/D/G/S
+DIVIDE/D/R/Z/G/S
+DIVIDEND/M/S
+DIVINE/R/G/Y
+DIVINITY/M/S
+DIVISION/M/S
+DIVISOR/M/S
+DIVORCE/D
+DIVULGE/D/G/S
+DIZZY/P
+DNA
+DO/R/Z/G/J
+DOCK/D/S
+DOCTOR/D/S
+DOCTORAL
+DOCTORATE/M/S
+DOCTRINE/M/S
+DOCUMENT/D/R/Z/G/S
+DOCUMENTARY/M/S
+DOCUMENTATION/M/S
+DODGE/D/R/Z/G
+DOES
+DOESN'T
+DOG/M/S
+DOGGED/P/Y
+DOGGING
+DOGMA/M/S
+DOGMATISM
+DOLE/D/S
+DOLEFUL/Y
+DOLL/M/S
+DOLLAR/S
+DOLLY/M/S
+DOLPHIN/M/S
+DOMAIN/M/S
+DOME/D/S
+DOMESTIC
+DOMESTICALLY
+DOMESTICATE/D/G/N/S
+DOMINANCE
+DOMINANT/Y
+DOMINATE/D/G/N/S
+DOMINION
+DON'T
+DON/S
+DONALD/M
+DONATE/D/G/S
+DONE
+DONKEY/M/S
+DOOM/D/G/S
+DOOR/M/S
+DOORSTEP/M/S
+DOORWAY/M/S
+DOPE/D/R/Z/G/S
+DORMANT
+DORMITORY/M/S
+DOSE/D/S
+DOT/M/S
+DOTE/D/G/S
+DOTINGLY
+DOTTED
+DOTTING
+DOUBLE/D/R/Z/G/S
+DOUBLET/M/S
+DOUBLY
+DOUBT/D/R/Z/G/S
+DOUBTABLE
+DOUBTFUL/Y
+DOUBTLESS/Y
+DOUG/M
+DOUGH
+DOUGHNUT/M/S
+DOUGLAS
+DOVE/R/S
+DOWN/D/Z/G/S
+DOWNCAST
+DOWNFALL/N
+DOWNPLAY/D/G/S
+DOWNRIGHT
+DOWNSTAIRS
+DOWNSTREAM
+DOWNTOWN/S
+DOWNWARD/S
+DOWNY
+DOZE/D/G/S
+DOZEN/H/S
+DR
+DRAB
+DRAFT/D/R/Z/G/S
+DRAFTSMAN
+DRAFTSMEN
+DRAG/S
+DRAGGED
+DRAGGING
+DRAGON/M/S
+DRAGOON/D/S
+DRAIN/D/R/G/S
+DRAINAGE
+DRAKE
+DRAMA/M/S
+DRAMATIC/S
+DRAMATICALLY
+DRAMATIST/M/S
+DRANK
+DRAPE/D/R/Z/S
+DRAPERY/M/S
+DRASTIC
+DRASTICALLY
+DRAUGHT/M/S
+DRAW/R/Z/G/J/S
+DRAWBACK/M/S
+DRAWBRIDGE/M/S
+DRAWL/D/G/S
+DRAWN/P/Y
+DREAD/D/G/S
+DREADFUL/Y
+DREAM/D/R/Z/G/S
+DREAMILY
+DREAMY
+DREARY/P
+DREGS
+DRENCH/D/G/S
+DRESS/D/R/Z/G/J/S
+DRESSMAKER/M/S
+DREW
+DRIER/M/S
+DRIFT/D/R/Z/G/S
+DRILL/D/R/G/S
+DRILY
+DRINK/R/Z/G/S
+DRINKABLE
+DRIP/M/S
+DRIVE/R/Z/G/S
+DRIVEN
+DRIVEWAY/M/S
+DRONE/M/S
+DROOP/D/G/S
+DROP/M/S
+DROPPED
+DROPPER/M/S
+DROPPING/M/S
+DROUGHT/M/S
+DROVE/R/Z/S
+DROWN/D/G/J/S
+DROWSY/P
+DRUDGERY
+DRUG/M/S
+DRUGGIST/M/S
+DRUM/M/S
+DRUMMED
+DRUMMER/M/S
+DRUMMING
+DRUNK/R/N/Y/S
+DRUNKARD/M/S
+DRUNKENNESS
+DRY/D/T/G/Y/S
+DUAL
+DUALITY/M/S
+DUANE/M
+DUB/S
+DUBBED
+DUBIOUS/P/Y
+DUCHESS/M/S
+DUCHY
+DUCK/D/G/S
+DUE/S
+DUEL/G/S
+DUG
+DUKE/M/S
+DULL/P/D/T/R/G/S
+DULLY
+DULY
+DUMB/P/T/R/Y
+DUMBBELL/M/S
+DUMMY/M/S
+DUMP/D/R/G/S
+DUMPLING
+DUNCE/M/S
+DUNE/M/S
+DUNGEON/M/S
+DUPLICATE/D/G/N/X/S
+DUPLICATOR/M/S
+DURABILITY/S
+DURABLE
+DURABLY
+DURATION/M/S
+DURING
+DUSK
+DUSKY/P
+DUST/D/R/Z/G/S
+DUSTY/T/R
+DUTIFUL/P/Y
+DUTY/M/S
+DWARF/D/S
+DWELL/D/R/Z/G/J/S
+DWINDLE/D/G
+DYE/D/R/Z/G/S
+DYEING
+DYNAMIC/S
+DYNAMICAL
+DYNAMICALLY
+DYNAMITE/D/G/S
+DYNASTY/M/S
+EACH
+EAGER/P/Y
+EAGLE/M/S
+EAR/D/H/S
+EARL/M/S
+EARLY/P/T/R
+EARMARK/D/G/J/S
+EARN/D/T/G/J/S
+EARNER/M/S
+EARNESTLY
+EARNESTNESS
+EARRING/M/S
+EARTHEN
+EARTHENWARE
+EARTHLY/P
+EARTHQUAKE/M/S
+EARTHS
+EARTHWORM/M/S
+EASE/D/G/S
+EASEMENT/M/S
+EASILY
+EAST/R
+EASTERN/R/Z
+EASTWARD/S
+EASY/P/T/R
+EAT/R/Z/G/N/J/S
+EAVES
+EAVESDROP/S
+EAVESDROPPED
+EAVESDROPPER/M/S
+EAVESDROPPING
+EBB/G/S
+EBONY
+ECCENTRIC/M/S
+ECCENTRICITY/S
+ECCLESIASTICAL
+ECHO/D/G
+ECHOES
+ECHOIC
+ECLIPSE/D/G/S
+ECOLOGY
+ECONOMIC/S
+ECONOMICAL/Y
+ECONOMIST/M/S
+ECONOMIZE/D/R/Z/G/S
+ECONOMY/M/S
+ECSTASY
+EDDY/M/S
+EDGE/D/G/S
+EDIBLE
+EDICT/M/S
+EDIFICE/M/S
+EDIT/D/G/S
+EDITION/M/S
+EDITOR/M/S
+EDITORIAL/Y/S
+EDUCATE/D/G/N/X/S
+EDUCATIONAL/Y
+EDUCATOR/M/S
+EDWARD/M
+EEL/M/S
+EERIE
+EFFECT/D/G/V/S
+EFFECTIVELY
+EFFECTIVENESS
+EFFECTOR/M/S
+EFFECTUALLY
+EFFEMINATE
+EFFICACY
+EFFICIENCY/S
+EFFICIENT/Y
+EFFIGY
+EFFORT/M/S
+EFFORTLESS/P/Y
+EGG/D/G/S
+EGO/S
+EIGENVALUE/M/S
+EIGHT/S
+EIGHTEEN/H/S
+EIGHTH/M/S
+EIGHTY/H/S
+EITHER
+EJACULATE/D/G/N/X/S
+EJECT/D/G/S
+EKE/D/S
+EL
+ELABORATE/P/D/G/N/X/Y/S
+ELABORATORS
+ELAPSE/D/G/S
+ELASTIC
+ELASTICALLY
+ELASTICITY
+ELBOW/G/S
+ELDER/Y/S
+ELDEST
+ELECT/D/G/V/S
+ELECTION/M/S
+ELECTIVES
+ELECTOR/M/S
+ELECTORAL
+ELECTRIC
+ELECTRICAL/P/Y
+ELECTRICITY
+ELECTRIFY/G/N
+ELECTROCUTE/D/G/N/X/S
+ELECTRODE/M/S
+ELECTROLYTE/M/S
+ELECTROLYTIC
+ELECTRON/M/S
+ELECTRONIC/S
+ELECTRONICALLY
+ELEGANCE
+ELEGANT/Y
+ELEGY
+ELEMENT/M/S
+ELEMENTAL/S
+ELEMENTARY
+ELEPHANT/M/S
+ELEVATE/D/N/S
+ELEVATOR/M/S
+ELEVEN/H/S
+ELF
+ELICIT/D/G/S
+ELIGIBILITY
+ELIGIBLE
+ELIMINATE/D/G/N/X/S
+ELIMINATOR/S
+ELISION
+ELK/M/S
+ELLIPSE/M/S
+ELLIPSIS
+ELLIPSOID/M/S
+ELLIPSOIDAL
+ELLIPTIC
+ELLIPTICAL/Y
+ELM/R/S
+ELOQUENCE
+ELOQUENT/Y
+ELSE
+ELSEWHERE
+ELUCIDATE/D/G/N/S
+ELUDE/D/G/S
+ELUSIVE/P/Y
+ELVES
+ELWOOD
+EMACIATED
+EMACS
+EMANATING
+EMANCIPATION
+EMBARK/D/S
+EMBARRASS/D/G/S
+EMBARRASSING/Y
+EMBARRASSMENT
+EMBASSY/M/S
+EMBED/S
+EMBEDDED
+EMBEDDING
+EMBELLISH/D/G/S
+EMBELLISHMENT/M/S
+EMBER
+EMBLEM
+EMBODIMENT/M/S
+EMBODY/D/G/S
+EMBRACE/D/G/S
+EMBROIDER/D/S
+EMBROIDERY/S
+EMBRYO/M/S
+EMBRYOLOGY
+EMERALD/M/S
+EMERGE/D/G/S
+EMERGENCE
+EMERGENCY/M/S
+EMERGENT
+EMERY
+EMIGRANT/M/S
+EMIGRATE/D/G/N/S
+EMINENCE
+EMINENT/Y
+EMIT/S
+EMITTED
+EMOTION/M/S
+EMOTIONAL/Y
+EMPATHY
+EMPEROR/M/S
+EMPHASES
+EMPHASIS
+EMPHASIZE/D/G/S
+EMPHATIC
+EMPHATICALLY
+EMPIRE/M/S
+EMPIRICAL/Y
+EMPIRICIST/M/S
+EMPLOY/D/G/S
+EMPLOYABLE
+EMPLOYEE/M/S
+EMPLOYER/M/S
+EMPLOYMENT/M/S
+EMPOWER/D/G/S
+EMPRESS
+EMPTILY
+EMPTY/P/D/T/R/G/S
+EMULATE/D/N/X/S
+EMULATOR/M/S
+ENABLE/D/R/Z/G/S
+ENACT/D/G/S
+ENACTMENT
+ENAMEL/D/G/S
+ENCAMP/D/G/S
+ENCAPSULATE/D/G/N/S
+ENCHANT/D/R/G/S
+ENCHANTMENT
+ENCIPHER/D/G/S
+ENCIRCLE/D/S
+ENCLOSE/D/G/S
+ENCLOSURE/M/S
+ENCODE/D/R/G/J/S
+ENCOMPASS/D/G/S
+ENCOUNTER/D/G/S
+ENCOURAGE/D/G/S
+ENCOURAGEMENT/S
+ENCOURAGINGLY
+ENCRYPT/D/G/S
+ENCRYPTION
+ENCUMBER/D/G/S
+ENCYCLOPEDIA/M/S
+ENCYCLOPEDIC
+END/D/R/Z/G/J/S
+ENDANGER/D/G/S
+ENDEAR/D/G/S
+ENDEAVOR/D/G/S
+ENDLESS/P/Y
+ENDORSE/D/G/S
+ENDORSEMENT
+ENDOW/D/G/S
+ENDOWMENT/M/S
+ENDPOINT/S
+ENDURABLE
+ENDURABLY
+ENDURANCE
+ENDURE/D/G/S
+ENDURINGLY
+ENEMA/M/S
+ENEMY/M/S
+ENERGETIC
+ENERGY/S
+ENFORCE/D/R/Z/G/S
+ENFORCEMENT
+ENGAGE/D/G/S
+ENGAGEMENT/M/S
+ENGAGINGLY
+ENGENDER/D/G/S
+ENGINE/M/S
+ENGINEER/D/M/G/S
+ENGLAND/R/Z
+ENGLISH
+ENGRAVE/D/R/G/J/S
+ENGROSS/D/G
+ENHANCE/D/G/S
+ENHANCEMENT/M/S
+ENIGMATIC
+ENJOIN/D/G/S
+ENJOY/D/G/S
+ENJOYABLE
+ENJOYABLY
+ENJOYMENT
+ENLARGE/D/R/Z/G/S
+ENLARGEMENT/M/S
+ENLIGHTEN/D/G
+ENLIGHTENMENT
+ENLIST/D/S
+ENLISTMENT
+ENLIVEN/D/G/S
+ENMITY/S
+ENNOBLE/D/G/S
+ENNUI
+ENORMITY/S
+ENORMOUS/Y
+ENOUGH
+ENQUEUE/D/S
+ENQUIRE/D/R/S
+ENRAGE/D/G/S
+ENRICH/D/G/S
+ENROLL/D/G/S
+ENROLLMENT/M/S
+ENSEMBLE/M/S
+ENSIGN/M/S
+ENSLAVE/D/G/S
+ENSNARE/D/G/S
+ENSUE/D/G/S
+ENSURE/D/R/Z/G/S
+ENTAIL/D/G/S
+ENTANGLE
+ENTER/D/G/S
+ENTERPRISE/G/S
+ENTERTAIN/D/R/Z/G/S
+ENTERTAININGLY
+ENTERTAINMENT/M/S
+ENTHUSIASM/S
+ENTHUSIAST/M/S
+ENTHUSIASTIC
+ENTHUSIASTICALLY
+ENTICE/D/R/Z/G/S
+ENTIRE/Y
+ENTIRETY/S
+ENTITLE/D/G/S
+ENTITY/M/S
+ENTRANCE/D/S
+ENTREAT/D
+ENTREATY
+ENTRENCH/D/G/S
+ENTREPRENEUR/M/S
+ENTROPY
+ENTRUST/D/G/S
+ENTRY/M/S
+ENUMERABLE
+ENUMERATE/D/G/N/V/S
+ENUMERATOR/S
+ENUNCIATION
+ENVELOP/S
+ENVELOPE/D/R/G/S
+ENVIOUS/P/Y
+ENVIRON/G/S
+ENVIRONMENT/M/S
+ENVIRONMENTAL
+ENVISAGE/D/S
+ENVISION/D/G/S
+ENVOY/M/S
+ENVY/D/S
+EOF
+EPAULET/M/S
+EPHEMERAL
+EPIC/M/S
+EPIDEMIC/M/S
+EPISCOPAL
+EPISODE/M/S
+EPISTEMOLOGICAL/Y
+EPISTEMOLOGY
+EPISTLE/M/S
+EPITAPH
+EPITAPHS
+EPITAXIAL/Y
+EPITHET/M/S
+EPITOMIZE/D/G/S
+EPOCH
+EPOCHS
+EPSILON
+EQUAL/D/G/Y/S
+EQUALITY/M/S
+EQUALIZE/D/R/Z/G/S
+EQUATE/D/G/N/X/S
+EQUATOR/M/S
+EQUATORIAL
+EQUILIBRIUM/S
+EQUIP/S
+EQUIPMENT
+EQUIPPED
+EQUIPPING
+EQUITABLE
+EQUITABLY
+EQUITY
+EQUIVALENCE/S
+EQUIVALENT/Y/S
+ERA/M/S
+ERADICATE/D/G/N/S
+ERASABLE
+ERASE/D/R/Z/G/S
+ERASURE
+ERE
+ERECT/D/G/S
+ERECTION/M/S
+ERECTOR/M/S
+ERGO
+ERGONOMIC/S
+ERMINE/M/S
+ERR/D/G/S
+ERRAND
+ERRATIC
+ERRINGLY
+ERRONEOUS/P/Y
+ERROR/M/S
+ERUPTION
+ESCALATE/D/G/N/S
+ESCAPABLE
+ESCAPADE/M/S
+ESCAPE/D/G/S
+ESCAPEE/M/S
+ESCHEW/D/G/S
+ESCORT/D/G/S
+ESOTERIC
+ESPECIAL/Y
+ESPERANTO
+ESPIONAGE
+ESPOUSE/D/G/S
+ESPRIT
+ESPY
+ESQUIRE/S
+ESSAY/D/S
+ESSENCE/M/S
+ESSENTIAL/Y/S
+ESTABLISH/D/G/S
+ESTABLISHMENT/M/S
+ESTATE/M/S
+ESTEEM/D/G/S
+ESTIMATE/D/G/N/X/S
+ETA
+ETC
+ETERNAL/Y
+ETERNITY/S
+ETHER/M/S
+ETHEREAL/Y
+ETHERNET
+ETHICAL/Y
+ETHICS
+ETHNIC
+ETHNOCENTRIC
+ETIQUETTE
+ETYMOLOGICAL
+ETYMOLOGY
+EUNUCH
+EUNUCHS
+EUPHEMISM/M/S
+EUPHORIA
+EUROPE
+EUROPEAN/S
+EVACUATE/D/N
+EVADE/D/G/S
+EVALUATE/D/G/N/X/V/S
+EVALUATOR/M/S
+EVAPORATE/D/G/N/V
+EVE/R
+EVEN/P/D/Y/S
+EVENHANDED/P/Y
+EVENING/M/S
+EVENT/M/S
+EVENTFUL/Y
+EVENTUAL/Y
+EVENTUALITY/S
+EVERGREEN
+EVERLASTING/Y
+EVERMORE
+EVERY
+EVERYBODY
+EVERYDAY
+EVERYONE/M
+EVERYTHING
+EVERYWHERE
+EVICT/D/G/S
+EVICTION/M/S
+EVIDENCE/D/G/S
+EVIDENT/Y
+EVIL/Y/S
+EVINCE/D/S
+EVOKE/D/G/S
+EVOLUTE/M/S
+EVOLUTION/M/S
+EVOLUTIONARY
+EVOLVE/D/G/S
+EWE/M/S
+EXACERBATE/D/G/N/X/S
+EXACT/P/D/G/Y/S
+EXACTINGLY
+EXACTION/M/S
+EXACTITUDE
+EXAGGERATE/D/G/N/X/S
+EXALT/D/G/S
+EXAM/M/S
+EXAMINATION/M/S
+EXAMINE/D/R/Z/G/S
+EXAMPLE/M/S
+EXASPERATE/D/G/N/S
+EXCAVATE/D/G/N/X/S
+EXCEED/D/G/S
+EXCEEDINGLY
+EXCEL/S
+EXCELLED
+EXCELLENCE/S
+EXCELLENCY
+EXCELLENT/Y
+EXCELLING
+EXCEPT/D/G/S
+EXCEPTION/M/S
+EXCEPTIONAL/Y
+EXCERPT/D/S
+EXCESS/V/S
+EXCESSIVELY
+EXCHANGE/D/G/S
+EXCHANGEABLE
+EXCHEQUER/M/S
+EXCISE/D/G/N/S
+EXCITABLE
+EXCITATION/M/S
+EXCITATORY
+EXCITE/D/G/S
+EXCITEDLY
+EXCITEMENT
+EXCITINGLY
+EXCLAIM/D/R/Z/G/S
+EXCLAMATION/M/S
+EXCLUDE/D/G/S
+EXCLUSION/S
+EXCLUSIVE/P/Y
+EXCLUSIVITY
+EXCOMMUNICATE/D/G/N/S
+EXCRETE/D/G/N/X/S
+EXCURSION/M/S
+EXCUSABLE
+EXCUSABLY
+EXCUSE/D/G/S
+EXECUTABLE
+EXECUTE/D/G/N/X/V/S
+EXECUTIONAL
+EXECUTIVE/M/S
+EXECUTOR/M/S
+EXEMPLAR
+EXEMPLARY
+EXEMPLIFY/D/R/Z/G/N/S
+EXEMPT/D/G/S
+EXERCISE/D/R/Z/G/S
+EXERT/D/G/S
+EXERTION/M/S
+EXHALE/D/G/S
+EXHAUST/D/G/V/S
+EXHAUSTEDLY
+EXHAUSTIBLE
+EXHAUSTION
+EXHAUSTIVELY
+EXHIBIT/D/G/S
+EXHIBITION/M/S
+EXHIBITOR/M/S
+EXHORTATION/M/S
+EXILE/D/G/S
+EXIST/D/G/S
+EXISTENCE
+EXISTENT
+EXISTENTIAL/Y
+EXISTENTIALISM
+EXISTENTIALIST/M/S
+EXIT/D/G/S
+EXORBITANT/Y
+EXOTIC
+EXPAND/D/G/S
+EXPANDABLE
+EXPANDER/M/S
+EXPANSE/N/X/V/S
+EXPANSIONISM
+EXPECT/D/G/S
+EXPECTANCY
+EXPECTANT/Y
+EXPECTATION/M/S
+EXPECTEDLY
+EXPECTINGLY
+EXPEDIENT/Y
+EXPEDITE/D/G/S
+EXPEDITION/M/S
+EXPEDITIOUS/Y
+EXPEL/S
+EXPELLED
+EXPELLING
+EXPEND/D/G/S
+EXPENDABLE
+EXPENDITURE/M/S
+EXPENSE/V/S
+EXPENSIVELY
+EXPERIENCE/D/G/S
+EXPERIMENT/D/R/Z/G/S
+EXPERIMENTAL/Y
+EXPERIMENTATION/M/S
+EXPERT/P/Y/S
+EXPERTISE
+EXPIRATION/M/S
+EXPIRE/D/S
+EXPLAIN/D/R/Z/G/S
+EXPLAINABLE
+EXPLANATION/M/S
+EXPLANATORY
+EXPLICIT/P/Y
+EXPLODE/D/G/S
+EXPLOIT/D/R/Z/G/S
+EXPLOITABLE
+EXPLOITATION/M/S
+EXPLORATION/M/S
+EXPLORATORY
+EXPLORE/D/R/Z/G/S
+EXPLOSION/M/S
+EXPLOSIVE/Y/S
+EXPONENT/M/S
+EXPONENTIAL/Y/S
+EXPONENTIATE/D/G/S
+EXPONENTIATION/M/S
+EXPORT/D/R/Z/G/S
+EXPOSE/D/R/Z/G/S
+EXPOSITION/M/S
+EXPOSITORY
+EXPOSURE/M/S
+EXPOUND/D/R/G/S
+EXPRESS/D/G/V/Y/S
+EXPRESSIBILITY
+EXPRESSIBLE
+EXPRESSIBLY
+EXPRESSION/M/S
+EXPRESSIVELY
+EXPRESSIVENESS
+EXPULSION
+EXPUNGE/D/G/S
+EXQUISITE/P/Y
+EXTANT
+EXTEND/D/G/S
+EXTENDIBLE
+EXTENSIBILITY
+EXTENSIBLE
+EXTENSION/M/S
+EXTENSIVE/Y
+EXTENT/M/S
+EXTENUATE/D/G/N
+EXTERIOR/M/S
+EXTERMINATE/D/G/N/S
+EXTERNAL/Y
+EXTINCT
+EXTINCTION
+EXTINGUISH/D/R/G/S
+EXTOL
+EXTRA/S
+EXTRACT/D/G/S
+EXTRACTION/M/S
+EXTRACTOR/M/S
+EXTRACURRICULAR
+EXTRANEOUS/P/Y
+EXTRAORDINARILY
+EXTRAORDINARY/P
+EXTRAPOLATE/D/G/N/X/S
+EXTRAVAGANCE
+EXTRAVAGANT/Y
+EXTREMAL
+EXTREME/Y/S
+EXTREMIST/M/S
+EXTREMITY/M/S
+EXTRINSIC
+EXUBERANCE
+EXULT
+EXULTATION
+EYE/D/R/Z/G/S
+EYEBROW/M/S
+EYEGLASS/S
+EYEING
+EYELID/M/S
+EYEPIECE/M/S
+EYESIGHT
+EYEWITNESS/M/S
+FABLE/D/S
+FABRIC/M/S
+FABRICATE/D/G/N/S
+FABULOUS/Y
+FACADE/D/S
+FACE/D/G/J/S
+FACET/D/S
+FACIAL
+FACILE/Y
+FACILITATE/D/G/S
+FACILITY/M/S
+FACSIMILE/M/S
+FACT/M/S
+FACTION/M/S
+FACTO
+FACTOR/D/G/S
+FACTORIAL
+FACTORIZATION/M/S
+FACTORY/M/S
+FACTUAL/Y
+FACULTY/M/S
+FADE/D/R/Z/G/S
+FAG/S
+FAHLMAN/M
+FAHRENHEIT
+FAIL/D/G/J/S
+FAILURE/M/S
+FAIN
+FAINT/P/D/T/R/G/Y/S
+FAIR/P/T/R/G/Y/S
+FAIRY/M/S
+FAIRYLAND
+FAITH
+FAITHFUL/P/Y
+FAITHLESS/P/Y
+FAITHS
+FAKE/D/R/G/S
+FALCON/R/S
+FALL/G/N/S
+FALLACIOUS
+FALLACY/M/S
+FALLIBILITY
+FALLIBLE
+FALSE/P/Y
+FALSEHOOD/M/S
+FALSIFY/D/G/N/S
+FALSITY
+FALTER/D/S
+FAME/D/S
+FAMILIAR/P/Y
+FAMILIARITY/S
+FAMILIARIZATION
+FAMILIARIZE/D/G/S
+FAMILY/M/S
+FAMINE/M/S
+FAMISH
+FAMOUS/Y
+FAN/M/S
+FANATIC/M/S
+FANCIER/M/S
+FANCIFUL/Y
+FANCILY
+FANCY/P/D/T/G/S
+FANG/M/S
+FANNED
+FANNING
+FANTASTIC
+FANTASY/M/S
+FAR
+FARADAY/M
+FARAWAY
+FARCE/M/S
+FARE/D/G/S
+FAREWELL/S
+FARM/D/R/Z/G/S
+FARMHOUSE/M/S
+FARMINGTON
+FARMYARD/M/S
+FARTHER
+FARTHEST
+FARTHING
+FASCINATE/D/G/N/S
+FASHION/D/G/S
+FASHIONABLE
+FASHIONABLY
+FAST/P/D/T/R/G/X/S
+FASTEN/D/R/Z/G/J/S
+FAT/P/S
+FATAL/Y/S
+FATALITY/M/S
+FATE/D/S
+FATHER/D/M/Y/S
+FATHERLAND
+FATHOM/D/G/S
+FATIGUE/D/G/S
+FATTEN/D/R/Z/G/S
+FATTER
+FATTEST
+FAULT/D/G/S
+FAULTLESS/Y
+FAULTY
+FAVOR/D/R/G/S
+FAVORABLE
+FAVORABLY
+FAVORITE/S
+FAWN/D/G/S
+FEAR/D/G/S
+FEARFUL/Y
+FEARLESS/P/Y
+FEASIBILITY
+FEASIBLE
+FEAST/D/G/S
+FEAT/M/S
+FEATHER/D/R/Z/G/S
+FEATHERY
+FEATURE/D/G/S
+FEBRUARY/M/S
+FED
+FEDERAL/Y/S
+FEDERATION
+FEE/S
+FEEBLE/P/T/R
+FEEBLY
+FEED/G/J/R/S/Z
+FEEDBACK
+FEEL/R/Z/G/J/S
+FEELINGLY
+FEET
+FEIGN/D/G
+FELICITY/S
+FELINE
+FELL/D/G
+FELLOW/M/S
+FELLOWSHIP/M/S
+FELT/S
+FEMALE/M/S
+FEMININE
+FEMININITY
+FEMUR/M/S
+FEN/S
+FENCE/D/R/Z/G/S
+FERMENT/D/G/S
+FERMENTATION/M/S
+FERN/M/S
+FEROCIOUS/P/Y
+FEROCITY
+FERRITE
+FERRY/D/S
+FERTILE/Y
+FERTILITY
+FERTILIZATION
+FERTILIZE/D/R/Z/G/S
+FERVENT/Y
+FERVOR/M/S
+FESTIVAL/M/S
+FESTIVE/Y
+FESTIVITY/S
+FETCH/D/G/S
+FETCHINGLY
+FETTER/D/S
+FEUD/M/S
+FEUDAL
+FEUDALISM
+FEVER/D/S
+FEVERISH/Y
+FEW/P/T/R
+FIBER/M/S
+FIBROSITY/S
+FIBROUS/Y
+FICKLE/P
+FICTION/M/S
+FICTIONAL/Y
+FICTITIOUS/Y
+FIDDLE/R/G/S
+FIDELITY
+FIELD/D/R/Z/G/S
+FIEND
+FIERCE/P/T/R/Y
+FIERY
+FIFE
+FIFO
+FIFTEEN/H/S
+FIFTH
+FIFTY/H/S
+FIG/M/S
+FIGHT/R/Z/G/S
+FIGURATIVE/Y
+FIGURE/D/G/J/S
+FILAMENT/M/S
+FILE/D/R/M/G/J/S
+FILENAME/M/S
+FILIAL
+FILL/D/R/Z/G/J/S
+FILLABLE
+FILM/D/G/S
+FILTER/D/M/G/S
+FILTH
+FILTHY/P/T/R
+FIN/M/S
+FINAL/Y/S
+FINALITY
+FINALIZATION
+FINALIZE/D/G/S
+FINANCE/D/G/S
+FINANCIAL/Y
+FINANCIER/M/S
+FIND/R/Z/G/J/S
+FINE/P/D/T/R/G/Y/S
+FINGER/D/G/J/S
+FINISH/D/R/Z/G/S
+FINITE/P/Y
+FIR
+FIRE/D/R/Z/G/J/S
+FIREARM/M/S
+FIREFLY/M/S
+FIRELIGHT
+FIREMAN
+FIREPLACE/M/S
+FIRESIDE
+FIREWOOD
+FIREWORKS
+FIRM/P/D/T/R/G/Y/S
+FIRMAMENT
+FIRMWARE
+FIRST/Y/S
+FIRSTHAND
+FISCAL/Y
+FISH/D/R/Z/G/S
+FISHERMAN
+FISHERY
+FISSURE/D
+FIST/D/S
+FIT/P/Y/S
+FITFUL/Y
+FITTED
+FITTER/M/S
+FITTING/Y/S
+FIVE/S
+FIX/D/R/Z/G/J/S
+FIXATE/D/G/N/X/S
+FIXEDLY
+FIXEDNESS
+FIXNUM
+FIXTURE/M/S
+FLAG/M/S
+FLAGGED
+FLAGGING
+FLAGRANT/Y
+FLAKE/D/G/S
+FLAME/D/R/Z/G/S
+FLAMINGO
+FLAMMABLE
+FLANK/D/R/G/S
+FLANNEL/M/S
+FLAP/M/S
+FLARE/D/G/S
+FLASH/D/R/Z/G/S
+FLASHLIGHT/M/S
+FLASK
+FLAT/P/Y/S
+FLATTEN/D/G
+FLATTER/D/R/G
+FLATTERY
+FLATTEST
+FLAUNT/D/G/S
+FLAVOR/D/G/J/S
+FLAW/D/S
+FLAWLESS/Y
+FLAX/N
+FLEA/M/S
+FLED
+FLEDGED
+FLEDGLING/M/S
+FLEE/S
+FLEECE/M/S
+FLEECY
+FLEEING
+FLEET/P/T/G/Y/S
+FLESH/D/G/Y/S
+FLESHY
+FLEW
+FLEXIBILITY/S
+FLEXIBLE
+FLEXIBLY
+FLICK/D/R/G/S
+FLICKERING
+FLIGHT/M/S
+FLINCH/D/G/S
+FLING/M/S
+FLINT
+FLIP/S
+FLIRT/D/G/S
+FLIT
+FLOAT/D/R/G/S
+FLOCK/D/G/S
+FLOOD/D/G/S
+FLOOR/D/G/J/S
+FLOP/M/S
+FLOPPILY
+FLOPPY
+FLORA
+FLORIDA
+FLORIN
+FLOSS/D/G/S
+FLOUNDER/D/G/S
+FLOUR/D
+FLOURISH/D/G/S
+FLOW/D/Z/G/S
+FLOWCHART/G/S
+FLOWER/D/G/S
+FLOWERY/P
+FLOWN
+FLUCTUATE/G/N/X/S
+FLUENT/Y
+FLUFFY/T/R
+FLUID/Y/S
+FLUIDITY
+FLUNG
+FLURRY/D
+FLUSH/D/G/S
+FLUTE/D/G
+FLUTTER/D/G/S
+FLY/R/Z/G/S
+FLYABLE
+FLYER/M/S
+FOAM/D/G/S
+FOCAL/Y
+FOCI
+FOCUS/D/G/S
+FODDER
+FOE/M/S
+FOG/M/S
+FOGGED
+FOGGILY
+FOGGING
+FOGGY/T/R
+FOIL/D/G/S
+FOLD/D/R/Z/G/S
+FOLIAGE
+FOLK/M/S
+FOLKLORE
+FOLLOW/D/R/Z/G/J/S
+FOLLY/S
+FOND/P/R/Y
+FONDLE/D/G/S
+FONT/M/S
+FOOD/M/S
+FOODSTUFF/M/S
+FOOL/D/G/S
+FOOLISH/P/Y
+FOOLPROOF
+FOOT/D/R/Z/G
+FOOTBALL/M/S
+FOOTHOLD
+FOOTMAN
+FOOTNOTE/M/S
+FOOTPRINT/M/S
+FOOTSTEP/S
+FOR/H
+FORAGE/D/G/S
+FORAY/M/S
+FORBADE
+FORBEAR/M/S
+FORBEARANCE
+FORBES
+FORBID/S
+FORBIDDEN
+FORBIDDING
+FORCE/D/R/M/G/S
+FORCEFUL/P/Y
+FORCIBLE
+FORCIBLY
+FORD/S
+FORE/T
+FOREARM/M/S
+FOREBODING
+FORECAST/D/R/Z/G/S
+FORECASTLE
+FOREFATHER/M/S
+FOREFINGER/M/S
+FOREGO/G
+FOREGOES
+FOREGONE
+FOREGROUND
+FOREHEAD/M/S
+FOREIGN/R/Z/S
+FOREMAN
+FOREMOST
+FORENOON
+FORESEE/S
+FORESEEABLE
+FORESEEN
+FORESIGHT/D
+FOREST/D/R/Z/S
+FORESTALL/D/G/S
+FORESTALLMENT
+FORETELL/G/S
+FORETOLD
+FOREVER
+FOREWARN/D/G/J/S
+FORFEIT/D
+FORGAVE
+FORGE/D/R/G/S
+FORGERY/M/S
+FORGET/S
+FORGETFUL/P
+FORGETTABLE
+FORGETTABLY
+FORGETTING
+FORGIVABLE
+FORGIVABLY
+FORGIVE/P/G/S
+FORGIVEN
+FORGIVINGLY
+FORGOT
+FORGOTTEN
+FORK/D/G/S
+FORLORN/Y
+FORM/D/R/G/S
+FORMAL/Y
+FORMALISM/M/S
+FORMALITY/S
+FORMALIZATION/M/S
+FORMALIZE/D/G/S
+FORMANT/S
+FORMAT/V/S
+FORMATION/M/S
+FORMATIVELY
+FORMATTED
+FORMATTER/M/S
+FORMATTING
+FORMERLY
+FORMIDABLE
+FORMULA/M/S
+FORMULAE
+FORMULATE/D/G/N/X/S
+FORMULATOR/M/S
+FORNICATION
+FORSAKE/G/S
+FORSAKEN
+FORT/M/S
+FORTE
+FORTHCOMING
+FORTHWITH
+FORTIFY/D/G/N/X/S
+FORTITUDE
+FORTNIGHT/Y
+FORTRAN
+FORTRESS/M/S
+FORTUITOUS/Y
+FORTUNATE/Y
+FORTUNE/M/S
+FORTY/R/H/S
+FORUM/M/S
+FORWARD/P/D/R/G/S
+FOSSIL
+FOSTER/D/G/S
+FOUGHT
+FOUL/P/D/T/G/Y/S
+FOUND/D/R/Z/G/S
+FOUNDATION/M/S
+FOUNDERED
+FOUNDRY/M/S
+FOUNT/M/S
+FOUNTAIN/M/S
+FOUR/H/S
+FOURIER
+FOURSCORE
+FOURTEEN/H/S
+FOWL/R/S
+FOX/M/S
+FRACTION/M/S
+FRACTIONAL/Y
+FRACTURE/D/G/S
+FRAGILE
+FRAGMENT/D/G/S
+FRAGMENTARY
+FRAGRANCE/M/S
+FRAGRANT/Y
+FRAIL/T
+FRAILTY
+FRAME/D/R/G/S
+FRAMEWORK/M/S
+FRANC/S
+FRANCE/M/S
+FRANCHISE/M/S
+FRANCISCO
+FRANK/P/D/T/R/G/Y/S
+FRANTIC
+FRANTICALLY
+FRATERNAL/Y
+FRATERNITY/M/S
+FRAUD/M/S
+FRAUGHT
+FRAY/D/G/S
+FREAK/M/S
+FRECKLE/D/S
+FREE/P/D/T/R/Y/S
+FREEDOM/M/S
+FREEING/S
+FREEMAN
+FREEZE/R/Z/G/S
+FREIGHT/D/R/Z/G/S
+FRENCH
+FRENZY/D
+FREQUENCY/S
+FREQUENT/D/R/Z/G/Y/S
+FRESH/P/T/R/X/Y
+FRESHEN/D/R/Z/G/S
+FRESHMAN
+FRESHMEN
+FRET
+FRETFUL/P/Y
+FRIAR/M/S
+FRICATIVE/S
+FRICTION/M/S
+FRICTIONLESS
+FRIDAY/M/S
+FRIEND/M/S
+FRIENDLESS
+FRIENDLY/P/T/R
+FRIENDSHIP/M/S
+FRIEZE/M/S
+FRIGATE/M/S
+FRIGHT/X
+FRIGHTEN/D/G/S
+FRIGHTENINGLY
+FRIGHTFUL/P/Y
+FRILL/M/S
+FRINGE/D
+FRISK/D/G/S
+FRIVOLOUS/Y
+FROCK/M/S
+FROG/M/S
+FROLIC/S
+FROM
+FRONT/D/G/S
+FRONTAL
+FRONTIER/M/S
+FROST/D/G/S
+FROSTY
+FROTH/G
+FROWN/D/G/S
+FROZE
+FROZEN/Y
+FRUGAL/Y
+FRUIT/M/S
+FRUITFUL/P/Y
+FRUITION
+FRUITLESS/Y
+FRUSTRATE/D/G/N/X/S
+FRY/D/S
+FUDGE
+FUEL/D/G/S
+FUGITIVE/M/S
+FUGUE
+FULFILL/D/G/S
+FULFILLMENT/S
+FULL/P/T/R
+FULLY
+FUMBLE/D/G
+FUME/D/G/S
+FUN
+FUNCTION/D/M/G/S
+FUNCTIONAL/Y/S
+FUNCTIONALITY/S
+FUNCTOR/M/S
+FUND/D/R/Z/G/S
+FUNDAMENTAL/Y/S
+FUNERAL/M/S
+FUNGUS
+FUNNEL/D/G/S
+FUNNILY
+FUNNY/P/T/R
+FUR/M/S
+FURIOUS/R/Y
+FURNACE/M/S
+FURNISH/D/G/J/S
+FURNITURE
+FURROW/D/S
+FURTHER/D/G/S
+FURTHERMORE
+FURTIVE/P/Y
+FURY/M/S
+FUSE/D/G/N/S
+FUSS/G
+FUTILE
+FUTILITY
+FUTURE/M/S
+FUZZY/P/R
+GABARDINE
+GABLE/D/R/S
+GAD
+GADGET/M/S
+GAG/G/S
+GAGGED
+GAGGING
+GAIETY/S
+GAILY
+GAIN/D/R/Z/G/S
+GAIT/D/R/Z
+GALAXY/M/S
+GALE
+GALL/D/G/S
+GALLANT/Y/S
+GALLANTRY
+GALLERY/D/S
+GALLEY/M/S
+GALLON/M/S
+GALLOP/D/R/G/S
+GALLOWS
+GAMBLE/D/R/Z/G/S
+GAME/P/D/G/Y/S
+GAMMA
+GANG/M/S
+GANGRENE
+GANGSTER/M/S
+GAP/M/S
+GAPE/D/G/S
+GARAGE/D/S
+GARB/D
+GARBAGE/M/S
+GARDEN/D/R/Z/G/S
+GARGLE/D/G/S
+GARLAND/D
+GARLIC
+GARMENT/M/S
+GARNER/D
+GARNET
+GARNISH
+GARRISON/D
+GARTER/M/S
+GARY/M
+GAS/M/S
+GASEOUS/Y
+GASH/M/S
+GASOLINE
+GASP/D/G/S
+GASSED
+GASSER
+GASSING/S
+GASTRIC
+GASTROINTESTINAL
+GATE/D/G/S
+GATEWAY/M/S
+GATHER/D/R/Z/G/J/S
+GAUDY/P
+GAUGE/D/S
+GAUNT/P
+GAUZE
+GAVE
+GAY/P/T/R/Y
+GAZE/D/R/Z/G/S
+GAZORCH/D/G
+GCD
+GEAR/D/G/S
+GEESE
+GEL/M/S
+GELATIN
+GELLED
+GELLING
+GEM/M/S
+GENDER/M/S
+GENE/M/S
+GENERAL/Y/S
+GENERALIST/M/S
+GENERALITY/S
+GENERALIZATION/M/S
+GENERALIZE/D/R/Z/G/S
+GENERATE/D/G/N/S/V/X
+GENERATOR/M/S
+GENERIC
+GENERICALLY
+GENEROSITY/M/S
+GENEROUS/P/Y
+GENETIC/S
+GENETICALLY
+GENEVA
+GENIAL/Y
+GENIUS/M/S
+GENRE/M/S
+GENTEEL
+GENTLE/P/T/R
+GENTLEMAN/Y
+GENTLEWOMAN
+GENTLY
+GENTRY
+GENUINE/P/Y
+GENUS
+GEOGRAPHIC
+GEOGRAPHICAL/Y
+GEOGRAPHY
+GEOLOGICAL
+GEOLOGIST/M/S
+GEOMETRIC
+GEOMETRICAL
+GEOMETRY/S
+GEORGETOWN
+GERANIUM
+GERM/M/S
+GERMAN/M/S
+GERMANE
+GERMANY
+GERMINATE/D/G/N/S
+GESTALT
+GESTURE/D/G/S
+GET/S
+GETTER/M/S
+GETTING
+GHASTLY
+GHOST/D/Y/S
+GIANT/M/S
+GIBBERISH
+GIDDY/P
+GIFT/D/S
+GIG
+GIGANTIC
+GIGGLE/D/G/S
+GILD/D/G/S
+GILL/M/S
+GILT
+GIMMICK/M/S
+GIN/M/S
+GINGER/Y
+GINGERBREAD
+GINGHAM/S
+GIPSY/M/S
+GIRAFFE/M/S
+GIRD
+GIRDER/M/S
+GIRDLE
+GIRL/M/S
+GIRT
+GIRTH
+GIVE/R/Z/G/S
+GIVEN
+GLACIAL
+GLACIER/M/S
+GLAD/P/Y
+GLADDER
+GLADDEST
+GLADE
+GLAMOROUS
+GLAMOUR
+GLANCE/D/G/S
+GLAND/M/S
+GLARE/D/G/S
+GLARINGLY
+GLASS/D/S
+GLASSY
+GLAZE/D/R/G/S
+GLEAM/D/G/S
+GLEAN/D/R/G/J/S
+GLEE/S
+GLEEFUL/Y
+GLEN/M/S
+GLIDE/D/R/Z/S
+GLIMMER/D/G/S
+GLIMPSE/D/S
+GLINT/D/G/S
+GLISTEN/D/G/S
+GLITCH/S
+GLITTER/D/G/S
+GLOBAL/Y
+GLOBE/M/S
+GLOBULAR
+GLOBULARITY
+GLOOM
+GLOOMILY
+GLOOMY
+GLORIFY/D/N/S
+GLORIOUS/Y
+GLORY/G/S
+GLOSS/D/G/S
+GLOSSARY/M/S
+GLOSSY
+GLOTTAL
+GLOVE/D/R/Z/G/S
+GLOW/D/R/Z/G/S
+GLOWINGLY
+GLUE/D/G/S
+GLYPH/S
+GNAT/M/S
+GNAW/D/G/S
+GNU
+GO/G/J
+GOAD/D
+GOAL/M/S
+GOAT/M/S
+GOATEE/M/S
+GOBBLE/D/R/Z/S
+GOBLET/M/S
+GOBLIN/M/S
+GOD/M/Y/S
+GODDESS/M/S
+GODLIKE
+GODMOTHER/M/S
+GOES
+GOLD/G/N/S
+GOLDENLY
+GOLDENNESS
+GOLDSMITH
+GOLF/R/Z/G
+GONE/R
+GONG/M/S
+GOOD/P/Y/S
+GOODY/M/S
+GOOSE
+GORDON/M
+GORE
+GORGE/G/S
+GORGEOUS/Y
+GORILLA/M/S
+GOSH
+GOSLING/M
+GOSPEL/Z/S
+GOSSIP/D/G/S
+GOT
+GOTHIC
+GOTO
+GOTTEN
+GOUGE/D/G/S
+GOURD
+GOVERN/D/G/S
+GOVERNESS
+GOVERNMENT/M/S
+GOVERNMENTAL/Y
+GOVERNOR/M/S
+GOWN/D/S
+GRAB/S
+GRABBED
+GRABBER/M/S
+GRABBING/S
+GRACE/D/G/S
+GRACEFUL/P/Y
+GRACIOUS/P/Y
+GRAD
+GRADATION/M/S
+GRADE/D/R/Z/G/J/S
+GRADIENT/M/S
+GRADUAL/Y
+GRADUATE/D/G/N/X/S
+GRAFT/D/R/G/S
+GRAHAM/M/S
+GRAIN/D/G/S
+GRAM/S
+GRAMMAR/M/S
+GRAMMATICAL/Y
+GRANARY/M/S
+GRAND/P/T/R/Y/S
+GRANDEUR
+GRANDFATHER/M/S
+GRANDIOSE
+GRANDMA
+GRANDMOTHER/M/S
+GRANDPA
+GRANDPARENT/S/M
+GRANDSON/M/S
+GRANGE
+GRANITE
+GRANNY
+GRANT/D/R/G/S
+GRANULARITY
+GRANULATE/D/G/S
+GRAPE/M/S
+GRAPH/D/M/G
+GRAPHIC/S
+GRAPHICAL/Y
+GRAPHITE
+GRAPHS
+GRAPPLE/D/G
+GRASP/D/G/S
+GRASPABLE
+GRASPING/Y
+GRASS/D/Z/S
+GRASSY/T/R
+GRATE/D/R/G/J/S
+GRATEFUL/P/Y
+GRATIFY/D/G/N
+GRATITUDE
+GRATUITOUS/P/Y
+GRATUITY/M/S
+GRAVE/P/T/R/Y/S
+GRAVEL/Y
+GRAVITATION
+GRAVITATIONAL
+GRAVITY
+GRAVY
+GRAY/P/D/T/R/G
+GRAZE/D/R/G
+GREASE/D/S
+GREASY
+GREAT/P/T/R/Y
+GREED
+GREEDILY
+GREEDY/P
+GREEK/M/S
+GREEN/P/T/R/G/Y/S
+GREENHOUSE/M/S
+GREENISH
+GREET/D/R/G/J/S
+GRENADE/M/S
+GREW
+GREY/T/G
+GRID/M/S
+GRIEF/M/S
+GRIEVANCE/M/S
+GRIEVE/D/R/Z/G/S
+GRIEVINGLY
+GRIEVOUS/Y
+GRIFFIN
+GRILL/D/G/S
+GRIM/P/D/Y
+GRIN/S
+GRIND/R/Z/G/J/S
+GRINDSTONE/M/S
+GRIP/D/G/S
+GRIPE/D/G/S
+GRIPPED
+GRIPPING/Y
+GRIT/M/S
+GRIZZLY
+GROAN/D/R/Z/G/S
+GROCER/M/S
+GROCERY/S
+GROOM/D/G/S
+GROOVE/D/S
+GROPE/D/G/S
+GROSS/P/D/T/R/G/Y/S
+GROTESQUE/Y/S
+GROTTO/M/S
+GROUND/D/R/Z/G/S
+GROUNDWORK
+GROUP/D/G/J/S
+GROUSE
+GROVE/R/Z/S
+GROVEL/D/G/S
+GROW/R/Z/G/H/S
+GROWL/D/G/S
+GROWN
+GROWNUP/M/S
+GROWTHS
+GRUB/M/S
+GRUDGE/M/S
+GRUESOME
+GRUFF/Y
+GRUMBLE/D/G/S
+GRUNT/D/G/S
+GUARANTEE/D/R/Z/S
+GUARANTEEING
+GUARANTY
+GUARD/D/G/S
+GUARDEDLY
+GUARDIAN/M/S
+GUARDIANSHIP
+GUERRILLA/M/S
+GUESS/D/G/S
+GUEST/M/S
+GUIDANCE
+GUIDE/D/G/S
+GUIDEBOOK/M/S
+GUIDELINE/M/S
+GUILD/R
+GUILE
+GUILT
+GUILTILY
+GUILTLESS/Y
+GUILTY/P/T/R
+GUINEA
+GUISE/M/S
+GUITAR/M/S
+GULCH/M/S
+GULF/M/S
+GULL/D/G/S
+GULLY/M/S
+GULP/D/S
+GUM/M/S
+GUN/M/S
+GUNFIRE
+GUNNED
+GUNNER/M/S
+GUNNING
+GUNPOWDER
+GURGLE
+GUSH/D/R/G/S
+GUST/M/S
+GUT/S
+GUTTER/D/S
+GUY/D/G/S
+GUYER/S
+GYMNASIUM/M/S
+GYMNAST/M/S
+GYMNASTIC/S
+GYPSY/M/S
+GYROSCOPE/M/S
+HA
+HABIT/M/S
+HABITAT/M/S
+HABITATION/M/S
+HABITUAL/P/Y
+HACK/D/R/Z/G/S
+HAD
+HADN'T
+HAG
+HAGGARD/Y
+HAIL/D/G/S
+HAIR/M/S
+HAIRCUT/M/S
+HAIRDRYER/M/S
+HAIRLESS
+HAIRY/P/R
+HALE/R
+HALF
+HALFTONE
+HALFWAY
+HALL/M/S
+HALLMARK/M/S
+HALLOW/D
+HALLWAY/M/S
+HALT/D/R/Z/G/S
+HALTINGLY
+HALVE/D/Z/G/S
+HAM/M/S
+HAMBURGER/M/S
+HAMLET/M/S
+HAMMER/D/G/S
+HAMMOCK/M/S
+HAMPER/D/S
+HAND/D/G/S
+HANDBAG/M/S
+HANDBOOK/M/S
+HANDCUFF/D/G/S
+HANDFUL/S
+HANDICAP/M/S
+HANDICAPPED
+HANDILY
+HANDIWORK
+HANDKERCHIEF/M/S
+HANDLE/D/R/Z/G/S
+HANDSOME/P/T/R/Y
+HANDWRITING
+HANDWRITTEN
+HANDY/P/T/R
+HANG/D/R/Z/G/S
+HANGAR/M/S
+HANGOVER/M/S
+HAP/Y
+HAPHAZARD/P/Y
+HAPLESS/P/Y
+HAPPEN/D/G/J/S
+HAPPILY
+HAPPY/P/T/R
+HARASS/D/G/S
+HARASSMENT
+HARBOR/D/G/S
+HARD/P/T/R/N/Y
+HARDCOPY
+HARDSHIP/M/S
+HARDWARE
+HARDWIRED
+HARDY/P
+HARE/M/S
+HARK/N
+HARLOT/M/S
+HARM/D/G/S
+HARMFUL/P/Y
+HARMLESS/P/Y
+HARMONIOUS/P/Y
+HARMONIZE
+HARMONY/S
+HARNESS/D/G
+HARP/R/Z/G
+HARROW/D/G/S
+HARRY/D/R
+HARSH/P/R/Y
+HART
+HARVARD
+HARVEST/D/R/G/S
+HAS
+HASH/D/R/G/S
+HASN'T
+HASTE/J
+HASTEN/D/G/S
+HASTILY
+HASTY/P
+HAT/M/S
+HATCH/D/G
+HATCHET/M/S
+HATE/D/R/G/S
+HATEFUL/P/Y
+HATRED
+HAUGHTILY
+HAUGHTY/P
+HAUL/D/R/G/S
+HAUNCH/M/S
+HAUNT/D/R/G/S
+HAVE/G/S
+HAVEN'T
+HAVEN/M/S
+HAVOC
+HAWAII
+HAWK/D/R/Z/S
+HAY/G/S
+HAZARD/M/S
+HAZARDOUS
+HAZE/M/S
+HAZEL
+HAZY/P
+HE'D
+HE'LL
+HE/D/M/V
+HEAD/D/R/Z/G/S
+HEADACHE/M/S
+HEADGEAR
+HEADING/M/S
+HEADLAND/M/S
+HEADLINE/D/G/S
+HEADLONG
+HEADQUARTERS
+HEADWAY
+HEAL/D/R/Z/G/H/S
+HEALTHFUL/P/Y
+HEALTHILY
+HEALTHY/P/T/R
+HEALY/M
+HEAP/D/G/S
+HEAR/R/Z/G/H/J/S
+HEARD
+HEARKEN
+HEARSAY
+HEART/N/S
+HEARTILY
+HEARTLESS
+HEARTY/P/T
+HEAT/D/R/Z/G/S
+HEATABLE
+HEATEDLY
+HEATH/R/N
+HEAVE/D/R/Z/G/S
+HEAVEN/Y/S
+HEAVILY
+HEAVY/P/T/R
+HEBREW
+HEDGE/D/S
+HEDGEHOG/M/S
+HEED/D/S
+HEEDLESS/P/Y
+HEEL/D/Z/G/S
+HEIDELBERG
+HEIFER
+HEIGHT/X/S
+HEIGHTEN/D/G/S
+HEINOUS/Y
+HEIR/M/S
+HEIRESS/M/S
+HELD
+HELL/M/S
+HELLO
+HELM
+HELMET/M/S
+HELP/D/R/Z/G/S
+HELPFUL/P/Y
+HELPLESS/P/Y
+HELVETICA
+HEM/M/S
+HEMISPHERE/M/S
+HEMLOCK/M/S
+HEMOSTAT/S
+HEMP/N
+HEN/M/S
+HENCE
+HENCEFORTH
+HENCHMAN
+HENCHMEN
+HER/S
+HERALD/D/G/S
+HERB/M/S
+HERBERT/M
+HERBIVORE
+HERBIVOROUS
+HERD/D/R/G/S
+HERE/M/S
+HEREABOUT/S
+HEREAFTER
+HEREBY
+HEREDITARY
+HEREDITY
+HEREIN
+HEREINAFTER
+HERESY
+HERETIC/M/S
+HERETOFORE
+HEREWITH
+HERITAGE/S
+HERMIT/M/S
+HERO
+HEROES
+HEROIC/S
+HEROICALLY
+HEROIN
+HEROINE/M/S
+HEROISM
+HERON/M/S
+HERRING/M/S
+HERSELF
+HESITANT/Y
+HESITATE/D/G/N/X/S
+HESITATINGLY
+HETEROGENEITY
+HETEROGENEOUS/P/Y
+HEURISTIC/M/S
+HEURISTICALLY
+HEW/D/R/S
+HEX
+HEXAGONAL/Y
+HEY
+HIATUS
+HICKORY
+HID
+HIDDEN
+HIDE/G/S
+HIDEOUS/P/Y
+HIDEOUT/M/S
+HIERARCHICAL/Y
+HIERARCHY/M/S
+HIGH/T/R/Y
+HIGHLAND/R/S
+HIGHLIGHT/D/G/S
+HIGHNESS/M/S
+HIGHWAY/M/S
+HIKE/D/R/G/S
+HILARIOUS/Y
+HILL/M/S
+HILLOCK
+HILLSIDE
+HILLTOP/M/S
+HILT/M/S
+HIM
+HIMSELF
+HIND/R/Z
+HINDERED
+HINDERING
+HINDRANCE/S
+HINDSIGHT
+HINGE/D/S
+HINT/D/G/S
+HIP/M/S
+HIRE/D/R/Z/G/J/S
+HIS
+HISS/D/G/S
+HISTOGRAM/M/S
+HISTORIAN/M/S
+HISTORIC
+HISTORICAL/Y
+HISTORY/M/S
+HIT/M/S
+HITCH/D/G
+HITCHHIKE/D/R/Z/G/S
+HITHER
+HITHERTO
+HITTER/M/S
+HITTING
+HOAR
+HOARD/R/G
+HOARSE/P/Y
+HOARY/P
+HOBBLE/D/G/S
+HOBBY/M/S
+HOBBYIST/M/S
+HOCKEY
+HOE/M/S
+HOG/M/S
+HOIST/D/G/S
+HOLD/R/Z/G/N/J/S
+HOLE/D/S
+HOLIDAY/M/S
+HOLISTIC
+HOLLAND
+HOLLOW/P/D/G/Y/S
+HOLLY
+HOLOCAUST
+HOLOGRAM/M/S
+HOLY/P/S
+HOMAGE
+HOME/D/R/Z/G/Y/S
+HOMELESS
+HOMEMADE
+HOMEMAKER/M/S
+HOMEOMORPHIC
+HOMEOMORPHISM/M/S
+HOMESICK/P
+HOMESPUN
+HOMESTEAD/R/Z/S
+HOMEWARD/S
+HOMEWORK
+HOMOGENEITY/M/S
+HOMOGENEOUS/P/Y
+HOMOMORPHIC
+HOMOMORPHISM/M/S
+HONE/D/T/R/G/S
+HONESTLY
+HONESTY
+HONEY
+HONEYCOMB/D
+HONEYMOON/D/R/Z/G/S
+HONEYSUCKLE
+HONG
+HONOLULU
+HONOR/D/R/G/S
+HONORABLE/P
+HONORABLY
+HONORARY/S
+HOOD/D/S
+HOODWINK/D/G/S
+HOOF/M/S
+HOOK/D/R/Z/G/S
+HOOP/R/S
+HOOT/D/R/G/S
+HOOVER/M
+HOP/S
+HOPE/D/G/S
+HOPEFUL/P/Y/S
+HOPELESS/P/Y
+HOPPER/M/S
+HORDE/M/S
+HORIZON/M/S
+HORIZONTAL/Y
+HORMONE/M/S
+HORN/D/S
+HORNET/M/S
+HORRENDOUS/Y
+HORRIBLE/P
+HORRIBLY
+HORRID/Y
+HORRIFY/D/G/S
+HORROR/M/S
+HORSE/Y/S
+HORSEBACK
+HORSEMAN
+HORSEPOWER
+HORSESHOE/R
+HOSE/M/S
+HOSPITABLE
+HOSPITABLY
+HOSPITAL/M/S
+HOSPITALITY
+HOSPITALIZE/D/G/S
+HOST/D/G/S
+HOSTAGE/M/S
+HOSTESS/M/S
+HOSTILE/Y
+HOSTILITY/S
+HOT/P/Y
+HOTEL/M/S
+HOTTER
+HOTTEST
+HOUND/D/G/S
+HOUR/Y/S
+HOUSE/D/G/S
+HOUSEFLY/M/S
+HOUSEHOLD/R/Z/S
+HOUSEKEEPER/M/S
+HOUSEKEEPING
+HOUSETOP/M/S
+HOUSEWIFE/Y
+HOUSEWORK
+HOUSTON
+HOVEL/M/S
+HOVER/D/G/S
+HOW
+HOWARD
+HOWEVER
+HOWL/D/R/G/S
+HUB/M/S
+HUBRIS
+HUDDLE/D/G
+HUDSON
+HUE/M/S
+HUG
+HUGE/P/Y
+HUH
+HULL/M/S
+HUM/S
+HUMAN/P/Y/S
+HUMANE/P/Y
+HUMANITY/M/S
+HUMBLE/P/D/T/R/G
+HUMBLY
+HUMID/Y
+HUMIDIFY/D/R/Z/G/N/S
+HUMIDITY
+HUMILIATE/D/G/N/X/S
+HUMILITY
+HUMMED
+HUMMING
+HUMOR/D/R/Z/G/S
+HUMOROUS/P/Y
+HUMP/D
+HUNCH/D/S
+HUNDRED/H/S
+HUNG/R/Z
+HUNGER/D/G
+HUNGRILY
+HUNGRY/T/R
+HUNK/M/S
+HUNT/D/R/Z/G/S
+HUNTSMAN
+HURL/D/R/Z/G
+HURRAH
+HURRICANE/M/S
+HURRIEDLY
+HURRY/D/G/S
+HURT/G/S
+HUSBAND/M/S
+HUSBANDRY
+HUSH/D/G/S
+HUSK/D/R/G/S
+HUSKY/P
+HUSTLE/D/R/G/S
+HUT/M/S
+HYACINTH
+HYATT
+HYBRID
+HYDRAULIC
+HYDRODYNAMIC/S
+HYDROGEN/M/S
+HYGIENE
+HYMN/M/S
+HYPER
+HYPERBOLIC
+HYPERCUBE/S
+HYPERMEDIA
+HYPERTEXT
+HYPERTEXTUAL
+HYPHEN/M/S
+HYPOCRISY/S
+HYPOCRITE/M/S
+HYPODERMIC/S
+HYPOTHESES
+HYPOTHESIS
+HYPOTHESIZE/D/R/G/S
+HYPOTHETICAL/Y
+HYSTERESIS
+HYSTERICAL/Y
+I'D
+I'LL
+I'M
+I'VE
+IBM
+ICE/D/G/J/S
+ICEBERG/M/S
+ICON/S
+ICONIC
+ICONOCLASTIC
+ICY/P
+IDEA/M/S
+IDEAL/Y/S
+IDEALISM
+IDEALISTIC
+IDEALIZATION/M/S
+IDEALIZE/D/G/S
+IDENTICAL/Y
+IDENTIFIABLE
+IDENTIFIABLY
+IDENTIFY/D/R/Z/G/N/X/S
+IDENTITY/M/S
+IDEOLOGICAL/Y
+IDEOLOGY/S
+IDIOM/S
+IDIOMATIC
+IDIOSYNCRASY/M/S
+IDIOSYNCRATIC
+IDIOT/M/S
+IDIOTIC
+IDLE/P/D/T/R/G/S
+IDLERS
+IDLY
+IDOL/M/S
+IDOLATRY
+IEEE
+IF
+IGNITION
+IGNOBLE
+IGNORANCE
+IGNORANT/Y
+IGNORE/D/G/S
+III
+ILL/S
+ILLEGAL/Y
+ILLEGALITY/S
+ILLICIT/Y
+ILLINOIS
+ILLITERATE
+ILLNESS/M/S
+ILLOGICAL/Y
+ILLUMINATE/D/G/N/X/S
+ILLUSION/M/S
+ILLUSIVE/Y
+ILLUSTRATE/D/G/N/X/V/S
+ILLUSTRATIVELY
+ILLUSTRATOR/M/S
+ILLUSTRIOUS/P
+ILLY
+IMAGE/G/S
+IMAGINABLE
+IMAGINABLY
+IMAGINARY
+IMAGINATION/M/S
+IMAGINATIVE/Y
+IMAGINE/D/G/J/S
+IMBALANCE/S
+IMITATE/D/G/N/X/V/S
+IMMACULATE/Y
+IMMATERIAL/Y
+IMMATURE
+IMMATURITY
+IMMEDIACY/S
+IMMEDIATE/Y
+IMMEMORIAL
+IMMENSE/Y
+IMMERSE/D/N/S
+IMMIGRANT/M/S
+IMMIGRATE/D/G/N/S
+IMMINENT/Y
+IMMORTAL/Y
+IMMORTALITY
+IMMOVABILITY
+IMMOVABLE
+IMMOVABLY
+IMMUNE
+IMMUNITY/M/S
+IMMUTABLE
+IMP
+IMPACT/D/G/S
+IMPACTION
+IMPACTOR/M/S
+IMPAIR/D/G/S
+IMPART/D/S
+IMPARTIAL/Y
+IMPASSE/V
+IMPATIENCE
+IMPATIENT/Y
+IMPEACH
+IMPEDANCE/M/S
+IMPEDE/D/G/S
+IMPEDIMENT/M/S
+IMPEL
+IMPENDING
+IMPENETRABILITY
+IMPENETRABLE
+IMPENETRABLY
+IMPERATIVE/Y/S
+IMPERFECT/Y
+IMPERFECTION/M/S
+IMPERIAL
+IMPERIALISM
+IMPERIALIST/M/S
+IMPERIL/D
+IMPERIOUS/Y
+IMPERMANENCE
+IMPERMANENT
+IMPERMISSIBLE
+IMPERSONAL/Y
+IMPERSONATE/D/G/N/X/S
+IMPERTINENT/Y
+IMPERVIOUS/Y
+IMPETUOUS/Y
+IMPETUS
+IMPINGE/D/G/S
+IMPIOUS
+IMPLANT/D/G/S
+IMPLAUSIBLE
+IMPLEMENT/D/G/S
+IMPLEMENTABLE
+IMPLEMENTATION/M/S
+IMPLEMENTOR/M/S
+IMPLICANT/M/S
+IMPLICATE/D/G/N/X/S
+IMPLICIT/P/Y
+IMPLORE/D/G
+IMPLY/D/G/N/X/S
+IMPORT/D/R/Z/G/S
+IMPORTANCE
+IMPORTANT/Y
+IMPORTATION
+IMPOSE/D/G/S
+IMPOSITION/M/S
+IMPOSSIBILITY/S
+IMPOSSIBLE
+IMPOSSIBLY
+IMPOSTOR/M/S
+IMPOTENCE
+IMPOTENT
+IMPOVERISH/D
+IMPOVERISHMENT
+IMPRACTICABLE
+IMPRACTICAL/Y
+IMPRACTICALITY
+IMPRECISE/N/Y
+IMPREGNABLE
+IMPRESS/D/R/G/V/S
+IMPRESSION/M/S
+IMPRESSIONABLE
+IMPRESSIONIST
+IMPRESSIONISTIC
+IMPRESSIVE/P/Y
+IMPRESSMENT
+IMPRINT/D/G/S
+IMPRISON/D/G/S
+IMPRISONMENT/M/S
+IMPROBABLE
+IMPROMPTU
+IMPROPER/Y
+IMPROVE/D/G/S
+IMPROVEMENT/S
+IMPROVISATION/M/S
+IMPROVISATIONAL
+IMPROVISE/D/R/Z/G/S
+IMPUDENT/Y
+IMPULSE/N/V/S
+IMPUNITY
+IMPURE
+IMPURITY/M/S
+IMPUTE/D
+IN
+INABILITY
+INACCESSIBLE
+INACCURACY/S
+INACCURATE
+INACTIVE
+INACTIVITY
+INADEQUACY/S
+INADEQUATE/P/Y
+INADMISSIBILITY
+INADVERTENT/Y
+INADVISABLE
+INANIMATE/Y
+INAPPLICABLE
+INAPPROPRIATE/P
+INASMUCH
+INAUGURAL
+INAUGURATE/D/G/N
+INC
+INCAPABLE
+INCAPACITATING
+INCARNATION/M/S
+INCENDIARY/S
+INCENSE/D/S
+INCENTIVE/M/S
+INCEPTION
+INCESSANT/Y
+INCH/D/G/S
+INCIDENCE
+INCIDENT/M/S
+INCIDENTAL/Y/S
+INCIPIENT
+INCITE/D/G/S
+INCLINATION/M/S
+INCLINE/D/G/S
+INCLOSE/D/G/S
+INCLUDE/D/G/S
+INCLUSION/M/S
+INCLUSIVE/P/Y
+INCOHERENT/Y
+INCOME/G/S
+INCOMMENSURATE
+INCOMPARABLE
+INCOMPARABLY
+INCOMPATIBILITY/M/S
+INCOMPATIBLE
+INCOMPATIBLY
+INCOMPETENCE
+INCOMPETENT/M/S
+INCOMPLETE/P/Y
+INCOMPREHENSIBILITY
+INCOMPREHENSIBLE
+INCOMPREHENSIBLY
+INCONCEIVABLE
+INCONCLUSIVE
+INCONSEQUENTIAL/Y
+INCONSIDERATE/P/Y
+INCONSISTENCY/M/S
+INCONSISTENT/Y
+INCONVENIENCE/D/G/S
+INCONVENIENT/Y
+INCORPORATE/D/G/N/S
+INCORRECT/P/Y
+INCREASE/D/G/S
+INCREASINGLY
+INCREDIBLE
+INCREDIBLY
+INCREDULOUS/Y
+INCREMENT/D/G/S
+INCREMENTAL/Y
+INCUBATE/D/G/N/S
+INCUBATOR/M/S
+INCUR/S
+INCURABLE
+INCURRED
+INCURRING
+INDEBTED/P
+INDECISION
+INDEED
+INDEFINITE/P/Y
+INDEMNITY
+INDENT/D/G/S
+INDENTATION/M/S
+INDEPENDENCE
+INDEPENDENT/Y/S
+INDESCRIBABLE
+INDETERMINACY/M/S
+INDETERMINATE/Y
+INDEX/D/G/S
+INDEXABLE
+INDIA
+INDIAN/M/S
+INDIANA
+INDICATE/D/G/N/X/V/S
+INDICATOR/M/S
+INDICES
+INDICTMENT/M/S
+INDIFFERENCE
+INDIFFERENT/Y
+INDIGENOUS/P/Y
+INDIGESTION
+INDIGNANT/Y
+INDIGNATION
+INDIGNITY/S
+INDIGO
+INDIRECT/D/G/Y/S
+INDIRECTION/S
+INDISCRIMINATE/Y
+INDISPENSABILITY
+INDISPENSABLE
+INDISPENSABLY
+INDISTINGUISHABLE
+INDIVIDUAL/M/Y/S
+INDIVIDUALISTIC
+INDIVIDUALITY
+INDIVIDUALIZE/D/G/S
+INDIVISIBILITY
+INDIVISIBLE
+INDOCTRINATE/D/G/N/S
+INDOLENT/Y
+INDOMITABLE
+INDOOR/S
+INDUCE/D/R/G/S
+INDUCEMENT/M/S
+INDUCT/D/G/S
+INDUCTANCE/S
+INDUCTION/M/S
+INDUCTIVE/Y
+INDUCTOR/M/S
+INDULGE/D/G
+INDULGENCE/M/S
+INDUSTRIAL/Y/S
+INDUSTRIALIST/M/S
+INDUSTRIALIZATION
+INDUSTRIOUS/P/Y
+INDUSTRY/M/S
+INEFFECTIVE/P/Y
+INEFFICIENCY/S
+INEFFICIENT/Y
+INELEGANT
+INEQUALITY/S
+INERT/P/Y
+INERTIA
+INESCAPABLE
+INESCAPABLY
+INESSENTIAL
+INESTIMABLE
+INEVITABILITY/S
+INEVITABLE
+INEVITABLY
+INEXACT
+INEXCUSABLE
+INEXCUSABLY
+INEXORABLE
+INEXORABLY
+INEXPENSIVE/Y
+INEXPERIENCE/D
+INEXPLICABLE
+INFALLIBILITY
+INFALLIBLE
+INFALLIBLY
+INFAMOUS/Y
+INFANCY
+INFANT/M/S
+INFANTRY
+INFEASIBLE
+INFECT/D/G/V/S
+INFECTION/M/S
+INFECTIOUS/Y
+INFER/S
+INFERENCE/M/S
+INFERENTIAL
+INFERIOR/M/S
+INFERIORITY
+INFERNAL/Y
+INFERNO/M/S
+INFERRED
+INFERRING
+INFEST/D/G/S
+INFIDEL/M/S
+INFINITE/P/Y
+INFINITESIMAL
+INFINITIVE/M/S
+INFINITUM
+INFINITY
+INFIRMITY
+INFIX
+INFLAME/D
+INFLAMMABLE
+INFLATABLE
+INFLATE/D/G/N/S
+INFLATIONARY
+INFLEXIBILITY
+INFLEXIBLE
+INFLICT/D/G/S
+INFLUENCE/D/G/S
+INFLUENTIAL/Y
+INFLUENZA
+INFO
+INFORM/D/R/Z/G/S
+INFORMAL/Y
+INFORMALITY
+INFORMANT/M/S
+INFORMATION
+INFORMATIONAL
+INFORMATIVE/Y
+INFREQUENT/Y
+INFRINGE/D/G/S
+INFRINGEMENT/M/S
+INFURIATE/D/G/N/S
+INFUSE/D/G/N/X/S
+INGENIOUS/P/Y
+INGENUITY
+INGRATITUDE
+INGREDIENT/M/S
+INGRES
+INHABIT/D/G/S
+INHABITABLE
+INHABITANCE
+INHABITANT/M/S
+INHALE/D/R/G/S
+INHERE/S
+INHERENT/Y
+INHERIT/D/G/S
+INHERITABLE
+INHERITANCE/M/S
+INHERITOR/M/S
+INHERITRESS/M/S
+INHERITRICES
+INHERITRIX
+INHIBIT/D/G/S
+INHIBITION/M/S
+INHIBITORS
+INHIBITORY
+INHOMOGENEITY/S
+INHUMAN
+INHUMANE
+INIQUITY/M/S
+INITIAL/D/G/Y/S
+INITIALIZATION/M/S
+INITIALIZE/D/R/Z/G/S
+INITIATE/D/G/N/X/V/S
+INITIATIVE/M/S
+INITIATOR/M/S
+INJECT/D/G/V/S
+INJECTION/M/S
+INJUNCTION/M/S
+INJURE/D/G/S
+INJURIOUS
+INJURY/M/S
+INJUSTICE/M/S
+INK/D/R/Z/G/J/S
+INKLING/M/S
+INLAID
+INLAND
+INLET/M/S
+INLINE
+INMATE/M/S
+INN/R/G/J/S
+INNARDS
+INNATE/Y
+INNERMOST
+INNOCENCE
+INNOCENT/Y/S
+INNOCUOUS/P/Y
+INNOVATE/N/X/V
+INNOVATION/M/S
+INNUMERABILITY
+INNUMERABLE
+INNUMERABLY
+INORDINATE/Y
+INPUT/M/S
+INQUIRE/D/R/Z/G/S
+INQUIRY/M/S
+INQUISITION/M/S
+INQUISITIVE/P/Y
+INROAD/S
+INSANE/Y
+INSANITY
+INSCRIBE/D/G/S
+INSCRIPTION/M/S
+INSECT/M/S
+INSECURE/Y
+INSENSIBLE
+INSENSITIVE/Y
+INSENSITIVITY
+INSEPARABLE
+INSERT/D/G/S
+INSERTION/M/S
+INSIDE/R/Z/S
+INSIDIOUS/P/Y
+INSIGHT/M/S
+INSIGNIA
+INSIGNIFICANCE
+INSIGNIFICANT
+INSINUATE/D/G/N/X/S
+INSIST/D/G/S
+INSISTENCE
+INSISTENT/Y
+INSOFAR
+INSOLENCE
+INSOLENT/Y
+INSOLUBLE
+INSPECT/D/G/S
+INSPECTION/M/S
+INSPECTOR/M/S
+INSPIRATION/M/S
+INSPIRE/D/R/G/S
+INSTABILITY/S
+INSTALL/D/R/Z/G/S
+INSTALLATION/M/S
+INSTALLMENT/M/S
+INSTANCE/S
+INSTANT/R/Y/S
+INSTANTANEOUS/Y
+INSTANTIATE/D/G/N/X/S
+INSTANTIATION/M/S
+INSTEAD
+INSTIGATE/D/G/S
+INSTIGATOR/M/S
+INSTINCT/M/V/S
+INSTINCTIVELY
+INSTITUTE/D/R/Z/G/N/X/S
+INSTITUTIONAL/Y
+INSTITUTIONALIZE/D/G/S
+INSTRUCT/D/G/V/S
+INSTRUCTION/M/S
+INSTRUCTIONAL
+INSTRUCTIVELY
+INSTRUCTOR/M/S
+INSTRUMENT/D/G/S
+INSTRUMENTAL/Y/S
+INSTRUMENTALIST/M/S
+INSTRUMENTATION
+INSUFFICIENT/Y
+INSULATE/D/G/N/S
+INSULATOR/M/S
+INSULT/D/G/S
+INSUPERABLE
+INSURANCE
+INSURE/D/R/Z/G/S
+INSURGENT/M/S
+INSURMOUNTABLE
+INSURRECTION/M/S
+INTACT
+INTANGIBLE/M/S
+INTEGER/M/S
+INTEGRAL/M/S
+INTEGRATE/D/G/N/X/V/S
+INTEGRITY
+INTELLECT/M/S
+INTELLECTUAL/Y/S
+INTELLIGENCE
+INTELLIGENT/Y
+INTELLIGIBILITY
+INTELLIGIBLE
+INTELLIGIBLY
+INTEND/D/G/S
+INTENSE/V/Y
+INTENSIFY/D/R/Z/G/N/S
+INTENSITY/S
+INTENSIVELY
+INTENT/P/Y/S
+INTENTION/D/S
+INTENTIONAL/Y
+INTER
+INTERACT/D/G/V/S
+INTERACTION/M/S
+INTERACTIVELY
+INTERACTIVITY
+INTERCEPT/D/G/S
+INTERCHANGE/D/G/J/S
+INTERCHANGEABILITY
+INTERCHANGEABLE
+INTERCHANGEABLY
+INTERCITY
+INTERCOMMUNICATE/D/G/N/S
+INTERCONNECT/D/G/S
+INTERCONNECTION/M/S
+INTERCOURSE
+INTERDEPENDENCE
+INTERDEPENDENCY/S
+INTERDEPENDENT
+INTERDISCIPLINARY
+INTEREST/D/G/S
+INTERESTINGLY
+INTERFACE/D/R/G/S
+INTERFERE/D/G/S
+INTERFERENCE/S
+INTERFERINGLY
+INTERIM
+INTERIOR/M/S
+INTERLACE/D/G/S
+INTERLEAVE/D/G/S
+INTERLINK/D/S
+INTERLISP
+INTERMEDIARY
+INTERMEDIATE/M/S
+INTERMINABLE
+INTERMINGLE/D/G/S
+INTERMITTENT/Y
+INTERMIXED
+INTERMODULE
+INTERN/D/S
+INTERNAL/Y/S
+INTERNALIZE/D/G/S
+INTERNATIONAL/Y
+INTERNATIONALITY
+INTERNET
+INTERNIST
+INTERPERSONAL
+INTERPLAY
+INTERPOLATE/D/G/N/X/S
+INTERPOSE/D/G/S
+INTERPRET/D/R/Z/G/V/S
+INTERPRETABLE
+INTERPRETATION/M/S
+INTERPRETIVELY
+INTERPROCESS
+INTERRELATE/D/G/N/X/S
+INTERRELATIONSHIP/M/S
+INTERROGATE/D/G/N/X/V/S
+INTERRUPT/D/G/V/S
+INTERRUPTIBLE
+INTERRUPTION/M/S
+INTERSECT/D/G/S
+INTERSECTION/M/S
+INTERSPERSE/D/G/N/S
+INTERSTAGE
+INTERSTATE
+INTERTEXUALITY
+INTERTWINE/D/G/S
+INTERVAL/M/S
+INTERVENE/D/G/S
+INTERVENTION/M/S
+INTERVIEW/D/R/Z/G/S
+INTERWOVEN
+INTESTINAL
+INTESTINE/M/S
+INTIMACY
+INTIMATE/D/G/N/X/Y
+INTIMIDATE/D/G/N/S
+INTO
+INTOLERABLE
+INTOLERABLY
+INTOLERANCE
+INTOLERANT
+INTONATION/M/S
+INTOXICATE/D/G/N
+INTRA
+INTRACTABILITY
+INTRACTABLE
+INTRACTABLY
+INTRAMURAL
+INTRANSIGENT
+INTRANSITIVE/Y
+INTRAPROCESS
+INTRICACY/S
+INTRICATE/Y
+INTRIGUE/D/G/S
+INTRINSIC
+INTRINSICALLY
+INTRODUCE/D/G/S
+INTRODUCTION/M/S
+INTRODUCTORY
+INTROSPECT/V
+INTROSPECTION/S
+INTROVERT/D
+INTRUDE/D/R/G/S
+INTRUDER/M/S
+INTRUSION/M/S
+INTRUST
+INTUBATE/D/N/S
+INTUITION/M/S
+INTUITIONIST
+INTUITIVE/Y
+INTUITIVENESS
+INVADE/D/R/Z/G/S
+INVALID/Y/S
+INVALIDATE/D/G/N/X/S
+INVALIDITY/S
+INVALUABLE
+INVARIABLE
+INVARIABLY
+INVARIANCE
+INVARIANT/Y/S
+INVASION/M/S
+INVENT/D/G/V/S
+INVENTION/M/S
+INVENTIVELY
+INVENTIVENESS
+INVENTOR/M/S
+INVENTORY/M/S
+INVERSE/N/X/Y/S
+INVERT/D/R/Z/G/S
+INVERTEBRATE/M/S
+INVERTIBLE
+INVEST/D/G/S
+INVESTIGATE/D/G/N/X/V/S
+INVESTIGATOR/M/S
+INVESTMENT/M/S
+INVESTOR/M/S
+INVINCIBLE
+INVISIBILITY
+INVISIBLE
+INVISIBLY
+INVITATION/M/S
+INVITE/D/G/S
+INVOCABLE
+INVOCATION/M/S
+INVOICE/D/G/S
+INVOKE/D/R/G/S
+INVOLUNTARILY
+INVOLUNTARY
+INVOLVE/D/G/S
+INVOLVEMENT/M/S
+INWARD/P/Y/S
+IODINE
+ION/S
+IPC
+IQ
+IRATE/P/Y
+IRE/M/S
+IRELAND/M
+IRIS
+IRK/D/G/S
+IRKSOME
+IRON/D/G/J/S
+IRONICAL/Y
+IRONY/S
+IRRATIONAL/Y/S
+IRRECOVERABLE
+IRREDUCIBLE
+IRREDUCIBLY
+IRREFLEXIVE
+IRREFUTABLE
+IRREGULAR/Y/S
+IRREGULARITY/S
+IRRELEVANCE/S
+IRRELEVANT/Y
+IRREPRESSIBLE
+IRRESISTIBLE
+IRRESPECTIVE/Y
+IRRESPONSIBLE
+IRRESPONSIBLY
+IRREVERSIBLE
+IRRIGATE/D/G/N/S
+IRRITATE/D/G/N/X/S
+IS
+ISLAND/R/Z/S
+ISLE/M/S
+ISLET/M/S
+ISN'T
+ISOLATE/D/G/N/X/S
+ISOMETRIC
+ISOMORPHIC
+ISOMORPHICALLY
+ISOMORPHISM/M/S
+ISOTOPE/M/S
+ISRAEL
+ISSUANCE
+ISSUE/D/R/Z/G/S
+ISTHMUS
+IT/M
+ITALIAN/M/S
+ITALIC/S
+ITALICIZE/D
+ITALY
+ITCH/G/S
+ITEM/M/S
+ITEMIZATION/M/S
+ITEMIZE/D/G/S
+ITERATE/D/G/N/X/V/S
+ITERATIVE/Y
+ITERATOR/M/S
+ITS
+ITSELF
+ITT
+IV
+IVORY
+IVY/M/S
+JAB/M/S
+JABBED
+JABBING
+JACK
+JACKET/D/S
+JADE/D
+JAIL/D/R/Z/G/S
+JAM/S
+JAMES
+JAMMED
+JAMMING
+JANITOR/M/S
+JANUARY/M/S
+JAPAN
+JAPANESE
+JAR/M/S
+JARGON
+JARRED
+JARRING/Y
+JASMINE/M
+JAUNDICE
+JAUNT/M/S
+JAUNTY/P
+JAVELIN/M/S
+JAW/M/S
+JAY
+JAZZ
+JEALOUS/Y
+JEALOUSY/S
+JEAN/M/S
+JEEP/M/S
+JEER/M/S
+JELLY/M/S
+JELLYFISH
+JENNY
+JEOPARDIZE/D/G/S
+JERK/D/G/J/S
+JERKY/P
+JERSEY/M/S
+JEST/D/R/G/S
+JET/M/S
+JETTED
+JETTING
+JEWEL/D/R/S
+JEWELRY/S
+JIG/M/S
+JILL
+JIM/M
+JINGLE/D/G
+JOAN/M
+JOB/M/S
+JOCUND
+JOE/M
+JOG/S
+JOHN/M
+JOIN/D/R/Z/G/S
+JOINT/M/Y/S
+JOKE/D/R/Z/G/S
+JOLLY
+JOLT/D/G/S
+JOSE/M
+JOSTLE/D/G/S
+JOT/S
+JOTTED
+JOTTING
+JOURNAL/M/S
+JOURNALISM
+JOURNALIST/M/S
+JOURNALIZE/D/G/S
+JOURNEY/D/G/J/S
+JOUST/D/G/S
+JOY/M/S
+JOYFUL/Y
+JOYOUS/P/Y
+JOYSTICK
+JR
+JUBILEE
+JUDGE/D/G/S
+JUDGMENT/M/S
+JUDICABLE
+JUDICIAL
+JUDICIARY
+JUDICIOUS/Y
+JUDY/M
+JUG/M/S
+JUGGLE/R/Z/G/S
+JUICE/M/S
+JUICY/T
+JULY/M/S
+JUMBLE/D/S
+JUMP/D/R/Z/G/S
+JUMPY
+JUNCTION/M/S
+JUNCTURE/M/S
+JUNE
+JUNGLE/M/S
+JUNIOR/M/S
+JUNIPER
+JUNK/R/Z/S
+JURISDICTION/M/S
+JUROR/M/S
+JURY/M/S
+JUST/P/Y
+JUSTICE/M/S
+JUSTIFIABLE
+JUSTIFIABLY
+JUSTIFIER'S
+JUSTIFY/D/R/Z/G/N/X/S
+JUT
+JUVENILE/M/S
+JUXTAPOSE/D/G/S
+KAISER
+KANJI
+KEEL/D/G/S
+KEEN/P/T/R/Y
+KEEP/R/Z/G/S
+KEN
+KENNEL/M/S
+KEPT
+KERCHIEF/M/S
+KERNEL/M/S
+KERNING
+KEROSENE
+KETCHUP
+KETTLE/M/S
+KEY/D/G/S
+KEYBOARD/M/S
+KEYNOTE
+KEYPAD/M/S
+KEYSTROKE/M/S
+KEYWORD/M/S
+KICK/D/R/Z/G/S
+KID/M/S
+KIDDED
+KIDDING
+KIDNAP/S/R/D/G/M
+KIDNAPPED
+KIDNAPPER/M/S
+KIDNAPPING/M/S
+KIDNEY/M/S
+KILL/D/R/Z/G/J/S
+KILLINGLY
+KILOGRAM/S
+KILOMETER/S
+KIN
+KIND/P/T/R/Y/S
+KINDERGARTEN
+KINDHEARTED
+KINDLE/D/G/S
+KINDRED
+KING/Y/S
+KINGDOM/M/S
+KINSHIP
+KINSMAN
+KISS/D/R/Z/G/S
+KIT/M/S
+KITCHEN/M/S
+KITE/D/G/S
+KITTEN/M/S
+KITTY
+KLUDGES
+KNACK
+KNAPSACK/M/S
+KNAVE/M/S
+KNEAD/S
+KNEE/D/S
+KNEEING
+KNEEL/D/G/S
+KNELL/M/S
+KNELT
+KNEW
+KNICKERBOCKER/M/S
+KNIFE/D/G/S
+KNIGHT/D/G/Y/S
+KNIGHTHOOD
+KNIT/S
+KNIVES
+KNOB/M/S
+KNOCK/D/R/Z/G/S
+KNOLL/M/S
+KNOT/M/S
+KNOTTED
+KNOTTING
+KNOW/R/G/S
+KNOWABLE
+KNOWHOW
+KNOWINGLY
+KNOWLEDGE
+KNOWLEDGEABLE
+KNOWN
+KNUCKLE/D/S
+KONG
+KYOTO
+LAB/M/S
+LABEL/S/D/R/G/M
+LABOR/D/R/Z/G/J/S
+LABORATORY/M/S
+LABORIOUS/Y
+LABYRINTH
+LABYRINTHS
+LACE/D/G/S
+LACERATE/D/G/N/X/S
+LACK/D/G/S
+LACQUER/D/S
+LAD/G/N/S
+LADDER
+LADLE
+LADY/M/S
+LAG/R/Z/S
+LAGOON/M/S
+LAGRANGIAN
+LAID
+LAIN
+LAIR/M/S
+LAKE/M/S
+LAMB/M/S
+LAMBDA
+LAME/P/D/G/Y/S
+LAMENT/D/G/S
+LAMENTABLE
+LAMENTATION/M/S
+LAMINAR
+LAMP/M/S
+LANCE/D/R/S
+LANCHESTER
+LAND/D/R/Z/G/J/S
+LANDLADY/M/S
+LANDLORD/M/S
+LANDMARK/M/S
+LANDOWNER/M/S
+LANDSCAPE/D/G/S
+LANE/M/S
+LANGUAGE/M/S
+LANGUID/P/Y
+LANGUISH/D/G/S
+LANSING
+LANTERN/M/S
+LAP/M/S
+LAPEL/M/S
+LAPIDARY
+LAPSE/D/G/S
+LARD/R
+LARGE/P/T/R/Y
+LARK/M/S
+LARVA
+LARVAE
+LAS
+LASER/M/S
+LASH/D/G/J/S
+LASS/M/S
+LAST/D/G/Y/S
+LATCH/D/G/S
+LATE/P/T/R/Y
+LATENCY
+LATENT
+LATERAL/Y
+LATITUDE/M/S
+LATRINE/M/S
+LATTER/Y
+LATTICE/M/S
+LAUGH/D/G
+LAUGHABLE
+LAUGHABLY
+LAUGHINGLY
+LAUGHS
+LAUGHTER
+LAUNCH/D/R/G/J/S
+LAUNDER/D/R/G/J/S
+LAUNDRY
+LAURA/M
+LAUREL/M/S
+LAVA
+LAVATORY/M/S
+LAVENDER
+LAVISH/D/G/Y
+LAW/M/S
+LAWFUL/Y
+LAWLESS/P
+LAWN/M/S
+LAWRENCE/M
+LAWSUIT/M/S
+LAWYER/M/S
+LAY/G/S
+LAYER/D/G/S
+LAYMAN
+LAYMEN
+LAYOFFS
+LAYOUT/M/S
+LAZED
+LAZILY
+LAZING
+LAZY/P/T/R
+LEAD/D/R/Z/G/N/J/S
+LEADERSHIP/M/S
+LEAF/D/G
+LEAFLESS
+LEAFLET/M/S
+LEAFY/T
+LEAGUE/D/R/Z/S
+LEAK/D/G/S
+LEAKAGE/M/S
+LEAN/P/D/T/R/G/S
+LEAP/D/G/S
+LEAPT
+LEARN/D/R/Z/G/S
+LEASE/D/G/S
+LEASH/M/S
+LEAST
+LEATHER/D/S
+LEATHERN
+LEAVE/D/G/J/S
+LEAVEN/D/G
+LECTURE/D/R/Z/G/S
+LED
+LEDGE/R/Z/S
+LEE/R/S
+LEECH/M/S
+LEFT
+LEFTIST/M/S
+LEFTMOST
+LEFTOVER/M/S
+LEFTWARD
+LEG/S
+LEGACY/M/S
+LEGAL/Y
+LEGALITY
+LEGALIZATION
+LEGALIZE/D/G/S
+LEGEND/M/S
+LEGENDARY
+LEGGED
+LEGGINGS
+LEGIBILITY
+LEGIBLE
+LEGIBLY
+LEGION/M/S
+LEGISLATE/D/G/N/V/S
+LEGISLATOR/M/S
+LEGISLATURE/M/S
+LEGITIMACY
+LEGITIMATE/Y
+LEGUME/S
+LEISURE/Y
+LEMMA/M/S
+LEMON/M/S
+LEMONADE
+LEND/R/Z/G/S
+LENGTH/N/Y
+LENGTHEN/D/G/S
+LENGTHS
+LENGTHWISE
+LENGTHY
+LENIENCY
+LENIENT/Y
+LENS/M/S
+LENT/N
+LENTIL/M/S
+LEOPARD/M/S
+LEPROSY
+LESS/R
+LESSEN/D/G/S
+LESSON/M/S
+LEST/R
+LET/M/S
+LETTER/D/R/G/S
+LETTING
+LETTUCE
+LEUKEMIA
+LEVEE/M/S
+LEVEL/P/D/R/G/Y/S/T
+LEVELLED
+LEVELLER
+LEVELLEST
+LEVELLING
+LEVER/M/S
+LEVERAGE
+LEVY/D/G/S
+LEWD/P/Y
+LEXIA/S
+LEXICAL/Y
+LEXICOGRAPHIC
+LEXICOGRAPHICAL/Y
+LEXICON/M/S
+LIABILITY/M/S
+LIABLE
+LIAISON/M/S
+LIAR/M/S
+LIBERAL/Y/S
+LIBERALIZE/D/G/S
+LIBERATE/D/G/N/S
+LIBERATOR/M/S
+LIBERTY/M/S
+LIBIDO
+LIBRARIAN/M/S
+LIBRARY/M/S
+LICENSE/D/G/S
+LICHEN/M/S
+LICK/D/G/S
+LID/M/S
+LIE/D/S
+LIEGE
+LIEN/M/S
+LIEU
+LIEUTENANT/M/S
+LIFE/R
+LIFELESS/P
+LIFELIKE
+LIFELONG
+LIFESTYLE/S
+LIFETIME/M/S
+LIFT/D/R/Z/G/S
+LIGHT/P/D/T/G/N/X/Y/S
+LIGHTER/M/S
+LIGHTHOUSE/M/S
+LIGHTNING/M/S
+LIGHTWEIGHT
+LIKE/D/G/S
+LIKELIHOOD/S
+LIKELY/P/T/R
+LIKEN/D/G/S
+LIKENESS/M/S
+LIKEWISE
+LILAC/M/S
+LILY/M/S
+LIMB/R/S
+LIME/M/S
+LIMESTONE
+LIMIT/D/R/Z/G/S
+LIMITABILITY
+LIMITABLY
+LIMITATION/M/S
+LIMITLESS
+LIMP/P/D/G/Y/S
+LINDA/M
+LINDEN
+LINE'S
+LINE/D/R/Z/G/J/S
+LINEAR/Y
+LINEARITY/S
+LINEARIZABLE
+LINEARIZE/D/G/S
+LINEFEED
+LINEN/M/S
+LINGER/D/G/S
+LINGUIST/M/S
+LINGUISTIC/S
+LINGUISTICALLY
+LINK/D/R/G/S
+LINKAGE/M/S
+LINOLEUM
+LINSEED
+LION/M/S
+LIONESS/M/S
+LIP/M/S
+LIPSTICK
+LIQUEFY/D/R/Z/G/S
+LIQUID/M/S
+LIQUIDATION/M/S
+LIQUIDITY
+LIQUIFY/D/R/Z/G/S
+LISBON
+LISP/D/M/G/S
+LIST/D/R/Z/G/X/S
+LISTEN/D/R/Z/G/S
+LISTING/M/S
+LIT/R/Z
+LITERACY
+LITERAL/P/Y/S
+LITERARY
+LITERATE
+LITERATURE/M/S
+LITHE
+LITTER/D/G/S
+LITTLE/P/T/R
+LIVABLE
+LIVABLY
+LIVE/P/D/R/Z/G/Y/S
+LIVELIHOOD
+LIVERY/D
+LIZARD/M/S
+LOAD/D/R/Z/G/J/S
+LOAF/D/R
+LOAN/D/G/S
+LOATH/Y
+LOATHE/D/G
+LOATHSOME
+LOAVES
+LOBBY/D/S
+LOBE/M/S
+LOBSTER/M/S
+LOCAL/Y/S
+LOCALITY/M/S
+LOCALIZATION
+LOCALIZE/D/G/S
+LOCATE/D/G/N/X/V/S
+LOCATIVES
+LOCATOR/M/S
+LOCI
+LOCK/D/R/Z/G/J/S
+LOCKOUT/M/S
+LOCKUP/M/S
+LOCOMOTION
+LOCOMOTIVE/M/S
+LOCUS
+LOCUST/M/S
+LODGE/D/R/G/J/S
+LOFT/M/S
+LOFTY/P
+LOG/M/S
+LOGARITHM/M/S
+LOGGED
+LOGGER/M/S
+LOGGING
+LOGIC/M/S
+LOGICAL/Y
+LOGICIAN/M/S
+LOGISTIC/S
+LOIN/M/S
+LOITER/D/R/G/S
+LONDON
+LONE/R/Z
+LONELY/P/T/R
+LONESOME
+LONG/D/T/R/G/J/S
+LONGITUDE/M/S
+LOOK/D/R/Z/G/S
+LOOKAHEAD
+LOOKOUT
+LOOKUP/M/S
+LOOM/D/G/S
+LOON
+LOOP/D/G/S
+LOOPHOLE/M/S
+LOOSE/P/D/T/R/G/Y/S
+LOOSEN/D/G/S
+LOOT/D/R/G/S
+LORD/Y/S
+LORDSHIP
+LORE
+LORRY
+LOSE/R/Z/G/S
+LOSS/M/S
+LOSSAGE
+LOSSY/T/R
+LOST
+LOT/M/S
+LOTTERY
+LOUD/P/T/R/Y
+LOUDSPEAKER/M/S
+LOUNGE/D/G/S
+LOUSY
+LOVABLE
+LOVABLY
+LOVE/D/R/Z/G/S
+LOVELY/P/T/R/S
+LOVINGLY
+LOW/P/T/Y/S
+LOWER/D/G/S
+LOWERCASE
+LOWLAND/S
+LOWLIEST
+LOYAL/Y
+LOYALTY/M/S
+LTD
+LUBRICANT/M
+LUBRICATION
+LUCID
+LUCK/D/S
+LUCKILY
+LUCKLESS
+LUCKY/T/R
+LUDICROUS/P/Y
+LUGGAGE
+LUKEWARM
+LULL/D/S
+LULLABY
+LUMBER/D/G
+LUMINOUS/Y
+LUMP/D/G/S
+LUNAR
+LUNATIC
+LUNCH/D/G/S
+LUNCHEON/M/S
+LUNG/D/S
+LURCH/D/G/S
+LURE/D/G/S
+LURK/D/G/S
+LUSCIOUS/P/Y
+LUST/R/S
+LUSTILY
+LUSTROUS
+LUSTY/P
+LUTE/M/S
+LUXURIANT/Y
+LUXURIOUS/Y
+LUXURY/M/S
+LYING
+LYMPH
+LYNCH/D/R/S
+LYNX/M/S
+LYRE
+LYRIC/S
+MA'AM
+MACE/D/S
+MACH
+MACHINE/D/M/G/S
+MACHINERY
+MACLACHLAN/M
+MACRO/M/S
+MACROECONOMICS
+MACROMOLECULAR
+MACROMOLECULE/M/S
+MACROSCOPIC
+MACROSTEP/S
+MACROSTRUCTURE
+MAD/P/Y
+MADAM
+MADDEN/G
+MADDER
+MADDEST
+MADE
+MADEMOISELLE
+MADISON
+MADMAN
+MADRAS
+MAGAZINE/M/S
+MAGGOT/M/S
+MAGIC
+MAGICAL/Y
+MAGICIAN/M/S
+MAGISTRATE/M/S
+MAGNESIUM
+MAGNET
+MAGNETIC
+MAGNETISM/M/S
+MAGNIFICENCE
+MAGNIFICENT/Y
+MAGNIFY/D/R/G/N/S
+MAGNITUDE/M/S
+MAHOGANY
+MAID/N/X/S
+MAIL/D/R/G/J/S
+MAILABLE
+MAILBOX/M/S
+MAIM/D/G/S
+MAIN/Y/S
+MAINE
+MAINFRAME/M/S
+MAINLAND
+MAINSTAY
+MAINSTREAM
+MAINTAIN/D/R/Z/G/S
+MAINTAINABILITY
+MAINTAINABLE
+MAINTENANCE/M/S
+MAIZE
+MAJESTIC
+MAJESTY/M/S
+MAJOR/D/S
+MAJORITY/M/S
+MAKABLE
+MAKE/R/Z/G/J/S
+MAKESHIFT
+MAKEUP/S
+MALADY/M/S
+MALARIA
+MALE/P/M/S
+MALEFACTOR/M/S
+MALFUNCTION/D/G/S
+MALICE
+MALICIOUS/P/Y
+MALIGNANT/Y
+MALLET/M/S
+MALNUTRITION
+MALT/D/S
+MAMA
+MAMMA/M/S
+MAMMAL/M/S
+MAMMOTH
+MAN/M/Y/S
+MANAGE/D/R/Z/G/S
+MANAGEABLE/P
+MANAGEMENT/M/S
+MANAGER/M/S
+MANAGERIAL
+MANDATE/D/G/S
+MANDATORY
+MANDIBLE
+MANE/M/S
+MANEUVER/D/G/S
+MANGER/M/S
+MANGLE/D/R/G/S
+MANHOOD
+MANIAC/M/S
+MANICURE/D/G/S
+MANIFEST/D/G/Y/S
+MANIFESTATION/M/S
+MANIFOLD/M/S
+MANILA
+MANIPULABILITY
+MANIPULABLE
+MANIPULATABLE
+MANIPULATE/D/G/N/X/V/S
+MANIPULATOR/M/S
+MANIPULATORY
+MANKIND
+MANNED
+MANNER/D/Y/S
+MANNING
+MANOMETER/M/S
+MANOR/M/S
+MANPOWER
+MANSION/M/S
+MANTEL/M/S
+MANTISSA/M/S
+MANTLE/M/S
+MANUAL/M/Y/S
+MANUFACTURE/D/R/Z/G/S
+MANUFACTURER/M/S
+MANURE
+MANUSCRIPT/M/S
+MANY
+MAP/M/S
+MAPLE/M/S
+MAPPABLE
+MAPPED
+MAPPING/M/S
+MAR/S
+MARBLE/G/S
+MARC/M
+MARCH/D/R/G/S
+MARE/M/S
+MARGIN/M/S
+MARGINAL/Y
+MARIGOLD
+MARIJUANA
+MARINE/R/S
+MARIO/M
+MARITAL
+MARITIME
+MARK/D/R/Z/G/J/S
+MARKABLE
+MARKEDLY
+MARKET/D/G/J/S
+MARKETABILITY
+MARKETABLE
+MARKETPLACE/M/S
+MARKOV
+MARQUIS
+MARRIAGE/M/S
+MARROW
+MARRY/D/G/S
+MARSH/M/S
+MARSHAL/D/G/S
+MART/N/S
+MARTHA/M
+MARTIAL
+MARTIN/M
+MARTYR/M/S
+MARTYRDOM
+MARVEL/D/S/G
+MARVELLED
+MARVELLING
+MARVELOUS/P/Y
+MARVIN/M
+MARY/M
+MARYLAND
+MASCULINE/Y
+MASCULINITY
+MASH/D/G/S
+MASK/D/R/G/J/S
+MASOCHIST/M/S
+MASON/M/S
+MASONRY
+MASQUERADE/R/G/S
+MASS/D/G/V/S
+MASSACHUSETTS
+MASSACRE/D/S
+MASSAGE/G/S
+MASSIVE/Y
+MAST/D/Z/S
+MASTER/D/M/G/Y/J/S
+MASTERFUL/Y
+MASTERPIECE/M/S
+MASTERY
+MASTURBATE/D/G/N/S
+MAT/M/S
+MATCH/D/R/Z/G/J/S
+MATCHABLE
+MATCHLESS
+MATE/D/R/M/G/J/S
+MATERIAL/Y/S
+MATERIALIZE/D/G/S
+MATERNAL/Y
+MATH
+MATHEMATICAL/Y
+MATHEMATICIAN/M/S
+MATHEMATICS
+MATRICES
+MATRICULATION
+MATRIMONY
+MATRIX
+MATRON/Y
+MATTED
+MATTER/D/S
+MATTRESS/M/S
+MATURATION
+MATURE/D/G/Y/S
+MATURITY/S
+MAURICE/M
+MAX
+MAXIM/M/S
+MAXIMAL/Y
+MAXIMIZE/D/R/Z/G/S
+MAXIMUM/S
+MAY
+MAYBE
+MAYHAP
+MAYHEM
+MAYONNAISE
+MAYOR/M/S
+MAYORAL
+MAZE/M/S
+MCDONALD/M
+ME
+MEAD
+MEADOW/M/S
+MEAGER/P/Y
+MEAL/M/S
+MEAN/P/T/R/Y/S
+MEANDER/D/G/S
+MEANING/M/S
+MEANINGFUL/P/Y
+MEANINGLESS/P/Y
+MEANT
+MEANTIME
+MEANWHILE
+MEASLES
+MEASURABLE
+MEASURABLY
+MEASURE/D/R/G/S
+MEASUREMENT/M/S
+MEAT/M/S
+MECHANIC/M/S
+MECHANICAL/Y
+MECHANISM/M/S
+MECHANIZATION/M/S
+MECHANIZE/D/G/S
+MEDAL/M/S
+MEDALLION/M/S
+MEDDLE/D/R/G/S
+MEDIA
+MEDIAN/M/S
+MEDIATE/D/G/N/X/S
+MEDIC/M/S
+MEDICAL/Y
+MEDICINAL/Y
+MEDICINE/M/S
+MEDIEVAL
+MEDIOCRE
+MEDITATE/D/G/N/X/V/S
+MEDIUM/M/S
+MEDUSA
+MEEK/P/T/R/Y
+MEET/G/J/S
+MELANCHOLY
+MELLON/M
+MELLOW/P/D/G/S
+MELODIOUS/P/Y
+MELODRAMA/M/S
+MELODY/M/S
+MELON/M/S
+MELT/D/G/S
+MELTINGLY
+MEMBER/M/S
+MEMBERSHIP/M/S
+MEMBRANE
+MEMO/M/S
+MEMOIR/S
+MEMORABLE/P
+MEMORANDA
+MEMORANDUM
+MEMORIAL/Y/S
+MEMORIZATION
+MEMORIZE/D/R/G/S
+MEMORY/M/S
+MEMORYLESS
+MEN/M/S
+MENACE/D/G
+MENAGERIE
+MEND/D/R/G/S
+MENIAL/S
+MENTAL/Y
+MENTALITY/S
+MENTION/D/R/Z/G/S
+MENTIONABLE
+MENTOR/M/S
+MENU/M/S
+MERCATOR
+MERCENARY/P/M/S
+MERCHANDISE/R/G
+MERCHANT/M/S
+MERCIFUL/Y
+MERCILESS/Y
+MERCURY
+MERCY
+MERE/T/Y
+MERGE/D/R/Z/G/S
+MERIDIAN
+MERIT/D/G/S
+MERITORIOUS/P/Y
+MERRILY
+MERRIMENT
+MERRY/T
+MESH
+MESS/D/G/S
+MESSAGE/M/S
+MESSENGER/M/S
+MESSIAH
+MESSIAHS
+MESSIEURS
+MESSILY
+MESSY/P/T/R
+MET/S
+META
+METACIRCULAR
+METACIRCULARITY
+METACLASS/S
+METAL/M/S
+METALANGUAGE
+METALLIC
+METALLIZATION/S
+METALLURGY
+METAMATHEMATICAL
+METAMORPHOSIS
+METAPHOR/M/S
+METAPHORICAL/Y
+METAPHYSICAL/Y
+METAPHYSICS
+METAVARIABLE
+METE/D/R/Z/G/S
+METEOR/M/S
+METEORIC
+METEOROLOGY
+METERING
+METHOD/M/S
+METHODICAL/P/Y
+METHODIST/M/S
+METHODOLOGICAL/Y
+METHODOLOGISTS
+METHODOLOGY/M/S
+METRIC/M/S
+METRICAL
+METROPOLIS
+METROPOLITAN
+MEW/D/S
+MICA
+MICE
+MICHAEL/M
+MICHIGAN
+MICRO
+MICROBICIDAL
+MICROBICIDE
+MICROBIOLOGY
+MICROCODE/D/G/S
+MICROCOMPUTER/M/S
+MICROECONOMICS
+MICROFILM/M/S
+MICROINSTRUCTION/M/S
+MICROPHONE/G/S
+MICROPROCESSING
+MICROPROCESSOR/M/S
+MICROPROGRAM/M/S
+MICROPROGRAMMED
+MICROPROGRAMMING
+MICROSCOPE/M/S
+MICROSCOPIC
+MICROSECOND/M/S
+MICROSOFT
+MICROSTEP/S
+MICROSTORE
+MICROSTRUCTURE
+MICROSYSTEM/S
+MICROWORD/S
+MID
+MIDDAY
+MIDDLE/G/S
+MIDNIGHT/S
+MIDPOINT/M/S
+MIDST/S
+MIDSUMMER
+MIDWAY
+MIDWEST
+MIDWINTER
+MIEN
+MIGHT
+MIGHTILY
+MIGHTY/P/T/R
+MIGRATE/D/G/N/X/S
+MIKE/M
+MILANO
+MILD/P/T/R/Y
+MILDEW
+MILE/M/S
+MILEAGE
+MILESTONE/M/S
+MILITANT/Y
+MILITARILY
+MILITARISM
+MILITARY
+MILITIA
+MILK/D/R/Z/G/S
+MILKMAID/M/S
+MILKY/P
+MILL/D/R/G/S
+MILLET
+MILLIMETER/S
+MILLION/H/S
+MILLIONAIRE/M/S
+MILLIPEDE/M/S
+MILLISECOND/S
+MILLSTONE/M/S
+MIMIC/S
+MIMICKED
+MIMICKING
+MINCE/D/G/S
+MIND/D/G/S
+MINDFUL/P/Y
+MINDLESS/Y
+MINE/D/R/Z/G/N/S
+MINERAL/M/S
+MINGLE/D/G/S
+MINI
+MINIATURE/M/S
+MINIATURIZATION
+MINIATURIZE/D/G/S
+MINICOMPUTER/M/S
+MINIMA
+MINIMAL/Y
+MINIMIZATION/M/S
+MINIMIZE/D/R/Z/G/S
+MINIMUM
+MINISTER/D/M/G/S
+MINISTRY/M/S
+MINK/M/S
+MINNEAPOLIS
+MINNESOTA/M
+MINNOW/M/S
+MINOR/M/S
+MINORITY/M/S
+MINSKY/M
+MINSTREL/M/S
+MINT/D/R/G/S
+MINUS
+MINUTE/P/R/Y/S
+MIRACLE/M/S
+MIRACULOUS/Y
+MIRAGE
+MIRE/D/S
+MIRROR/D/G/S
+MIRTH
+MISBEHAVING
+MISCALCULATION/M/S
+MISCELLANEOUS/P/Y
+MISCHIEF
+MISCHIEVOUS/P/Y
+MISCONCEPTION/M/S
+MISCONSTRUE/D/S
+MISER/Y/S
+MISERABLE/P
+MISERABLY
+MISERY/M/S
+MISFIT/M/S
+MISFORTUNE/M/S
+MISGIVING/S
+MISHAP/M/S
+MISINTERPRETATION
+MISJUDGMENT
+MISLEAD/G/S
+MISLED
+MISMATCH/D/G/S
+MISNOMER
+MISPLACE/D/G/S
+MISREPRESENTATION/M/S
+MISS/D/G/V/S
+MISSILE/M/S
+MISSION/R/S
+MISSIONARY/M/S
+MISSPELL/D/G/J/S
+MIST/D/R/Z/G/S
+MISTAKABLE
+MISTAKE/G/S
+MISTAKEN/Y
+MISTRESS
+MISTRUST/D
+MISTY/P
+MISTYPE/D/G/S
+MISUNDERSTAND/R/Z/G
+MISUNDERSTANDING/M/S
+MISUNDERSTOOD
+MISUSE/D/G/S
+MIT/R/M
+MITIGATE/D/G/N/V/S
+MITTEN/M/S
+MIX/D/R/Z/G/S
+MIXTURE/M/S
+MNEMONIC/M/S
+MNEMONICALLY
+MOAN/D/S
+MOAT/M/S
+MOB/M/S
+MOCCASIN/M/S
+MOCK/D/R/G/S
+MOCKERY
+MODAL/Y
+MODALITY/M/S
+MODE/T/S
+MODEL/D/G/J/S/M
+MODEM
+MODERATE/P/D/G/N/Y/S
+MODERATOR/M/S
+MODERN/P/Y/S
+MODERNISM
+MODERNITY
+MODERNIZE/D/R/G
+MODESTLY
+MODESTY
+MODIFIABILITY
+MODIFIABLE
+MODIFY/D/R/Z/G/N/X/S
+MODULAR/Y
+MODULARITY
+MODULARIZATION
+MODULARIZE/D/G/S
+MODULATE/D/G/N/X/S
+MODULATOR/M/S
+MODULE/M/S
+MODULO
+MODULUS
+MODUS
+MOHAWK
+MOIST/P/N/Y
+MOISTURE
+MOLASSES
+MOLD/D/R/G/S
+MOLE/T/S
+MOLECULAR
+MOLECULE/M/S
+MOLEST/D/G/S
+MOLTEN
+MOMENT/M/S
+MOMENTARILY
+MOMENTARY/P
+MOMENTOUS/P/Y
+MOMENTUM
+MONARCH
+MONARCHS
+MONARCHY/M/S
+MONASTERY/M/S
+MONASTIC
+MONDAY/M/S
+MONETARY
+MONEY/D/S
+MONITOR/D/G/S
+MONK/M/S
+MONKEY/D/G/S
+MONOCHROME
+MONOGRAM/M/S
+MONOGRAPH/M/S
+MONOGRAPHS
+MONOLITHIC
+MONOPOLY/M/S
+MONOTHEISM
+MONOTONE
+MONOTONIC
+MONOTONICALLY
+MONOTONICITY
+MONOTONOUS/P/Y
+MONOTONY
+MONSTER/M/S
+MONSTROUS/Y
+MONTANA/M
+MONTH/Y
+MONTHS
+MONUMENT/M/S
+MONUMENTAL/Y
+MOOD/M/S
+MOODY/P
+MOON/D/G/S
+MOONLIGHT/R/G
+MOONLIT
+MOONSHINE
+MOOR/D/G/J/S
+MOOSE
+MOOT
+MOP/D/S
+MORAL/Y/S
+MORALE
+MORALITY/S
+MORASS
+MORBID/P/Y
+MORE/S
+MOREOVER
+MORN/G/J
+MORPHISM/S
+MORPHOLOGICAL
+MORPHOLOGY
+MORROW
+MORSEL/M/S
+MORTAL/Y/S
+MORTALITY
+MORTAR/D/G/S
+MORTGAGE/M/S
+MORTIFY/D/G/N/S
+MOSAIC/M/S
+MOSQUITO/S
+MOSQUITOES
+MOSS/M/S
+MOSSY
+MOST/Y
+MOTEL/M/S
+MOTH/Z
+MOTHER'S
+MOTHER/D/R/Z/G/Y/S
+MOTIF/M/S
+MOTION/D/G/S
+MOTIONLESS/P/Y
+MOTIVATE/D/G/N/X/S
+MOTIVATIONAL
+MOTIVE/S
+MOTLEY
+MOTOR/G/S
+MOTORCAR/M/S
+MOTORCYCLE/M/S
+MOTORIST/M/S
+MOTORIZE/D/G/S
+MOTOROLA/M
+MOTTO/S
+MOTTOES
+MOULD/G
+MOUND/D/S
+MOUNT/D/R/G/J/S
+MOUNTAIN/M/S
+MOUNTAINEER/G/S
+MOUNTAINOUS/Y
+MOURN/D/R/Z/G/S
+MOURNFUL/P/Y
+MOUSE/R/S
+MOUTH/D/G
+MOUTHFUL
+MOUTHS
+MOVABLE
+MOVE/D/R/Z/G/J/S
+MOVEMENT/M/S
+MOVIE/M/S
+MOW/D/R/S
+MR
+MRS
+MS
+MUCH
+MUCK/R/G
+MUD
+MUDDLE/D/R/Z/G/S
+MUDDY/P/D
+MUFF/M/S
+MUFFIN/M/S
+MUFFLE/D/R/G/S
+MUG/M/S
+MULBERRY/M/S
+MULE/M/S
+MULTI
+MULTICELLULAR
+MULTIDIMENSIONAL
+MULTILEVEL
+MULTINATIONAL
+MULTIPLE/M/S
+MULTIPLEX/D/G/S
+MULTIPLEXOR/M/S
+MULTIPLICAND/M/S
+MULTIPLICATIVE/S
+MULTIPLICITY
+MULTIPLY/D/R/Z/G/N/X/S
+MULTIPROCESS/G
+MULTIPROCESSOR/M/S
+MULTIPROGRAM
+MULTIPROGRAMMED
+MULTIPROGRAMMING
+MULTIPURPOSE
+MULTISTAGE
+MULTITUDE/M/S
+MULTIVARIATE
+MUMBLE/D/R/Z/G/J/S
+MUMMY/M/S
+MUNCH/D/G
+MUNDANE/Y
+MUNICIPAL/Y
+MUNICIPALITY/M/S
+MUNITION/S
+MURAL
+MURDER/D/R/Z/G/S
+MURDEROUS/Y
+MURKY
+MURMUR/D/R/G/S
+MUSCLE/D/G/S
+MUSCULAR
+MUSE/D/G/J/S
+MUSEUM/M/S
+MUSHROOM/D/G/S
+MUSHY
+MUSIC
+MUSICAL/Y/S
+MUSICIAN/Y/S
+MUSK/S
+MUSKET/M/S
+MUSKRAT/M/S
+MUSLIN
+MUSSEL/M/S
+MUST/R/S
+MUSTACHE/D/S
+MUSTARD
+MUSTY/P
+MUTABILITY
+MUTABLE/P
+MUTATE/D/G/N/X/V/S
+MUTE/P/D/Y
+MUTILATE/D/G/N/S
+MUTINY/M/S
+MUTTER/D/R/Z/G/S
+MUTTON
+MUTUAL/Y
+MUZZLE/M/S
+MY
+MYRIAD
+MYRTLE
+MYSELF
+MYSTERIOUS/P/Y
+MYSTERY/M/S
+MYSTIC/M/S
+MYSTICAL
+MYTH
+MYTHICAL
+MYTHOLOGY/M/S
+NAG/M/S
+NAIL/D/G/S
+NAIVE/P/Y
+NAIVETE
+NAKED/P/Y
+NAME/D/R/Z/G/Y/S
+NAMEABLE
+NAMELESS/Y
+NAMESAKE/M/S
+NANOSECOND/S
+NAP/M/S
+NAPKIN/M/S
+NARCISSUS
+NARCOTIC/S
+NARRATIVE/M/S
+NARROW/P/D/T/R/G/Y/S
+NASAL/Y
+NASTILY
+NASTY/P/T/R
+NATHANIEL/M
+NATION/M/S
+NATIONAL/Y/S
+NATIONALIST/M/S
+NATIONALITY/M/S
+NATIONALIZATION
+NATIONALIZE/D/G/S
+NATIONWIDE
+NATIVE/Y/S
+NATIVITY
+NATURAL/P/Y/S
+NATURALISM
+NATURALIST
+NATURALIZATION
+NATURE/D/M/S
+NAUGHT
+NAUGHTY/P/R
+NAVAL/Y
+NAVIGABLE
+NAVIGATE/D/G/N/S
+NAVIGATOR/M/S
+NAVY/M/S
+NAY
+NAZI/M/S
+NEAR/P/D/T/R/G/Y/S
+NEARBY
+NEAT/P/T/R/Y
+NEBRASKA
+NEBULA
+NECESSARILY
+NECESSARY/S
+NECESSITATE/D/G/N/S
+NECESSITY/S
+NECK/G/S
+NECKLACE/M/S
+NECKTIE/M/S
+NEE
+NEED/D/G/S
+NEEDFUL
+NEEDLE/D/R/Z/G/S
+NEEDLESS/P/Y
+NEEDLEWORK
+NEEDN'T
+NEEDY
+NEGATE/D/G/N/X/V/S
+NEGATIVELY
+NEGATIVES
+NEGATOR/S
+NEGLECT/D/G/S
+NEGLIGENCE
+NEGLIGIBLE
+NEGOTIATE/D/G/N/X/S
+NEGRO
+NEGROES
+NEIGH
+NEIGHBOR/G/Y/S
+NEIGHBORHOOD/M/S
+NEITHER
+NEOPHYTE/S
+NEPAL
+NEPHEW/M/S
+NERVE/M/S
+NERVOUS/P/Y
+NEST/D/R/G/S
+NESTLE/D/G/S
+NET/M/S
+NETHER
+NETHERLANDS
+NETMAIL
+NETNEWS
+NETTED
+NETTING
+NETTLE/D
+NETWORK/D/M/G/S
+NEUMANN/M
+NEURAL
+NEUROLOGICAL
+NEUROLOGISTS
+NEURON/M/S
+NEUROPHYSIOLOGY
+NEUROSCIENCE/S
+NEUTRAL/Y
+NEUTRALITY/S
+NEUTRALIZE/D/G
+NEUTRINO/M/S
+NEVER
+NEVERTHELESS
+NEW/P/T/R/Y/S
+NEWBORN
+NEWCOMER/M/S
+NEWLINE
+NEWSMAN
+NEWSMEN
+NEWSPAPER/M/S
+NEWTONIAN
+NEXT
+NIBBLE/D/R/Z/G/S
+NICE/P/T/R/Y
+NICHE/S
+NICK/D/R/G/S
+NICKEL/M/S
+NICKNAME/D/S
+NIECE/M/S
+NIFTY
+NIGH
+NIGHT/Y/S
+NIGHTFALL
+NIGHTGOWN
+NIGHTINGALE/M/S
+NIGHTMARE/M/S
+NIL
+NIMBLE/P/R
+NIMBLY
+NINE/S
+NINETEEN/H/S
+NINETY/H/S
+NINTH
+NIP/S
+NITROGEN
+NO
+NOBILITY
+NOBLE/P/T/R/S
+NOBLEMAN
+NOBLY
+NOBODY
+NOCTURNAL/Y
+NOD/M/S
+NODDED
+NODDING
+NODE/M/S
+NOISE/S
+NOISELESS/Y
+NOISILY
+NOISY/P/R
+NOMENCLATURE
+NOMINAL/Y
+NOMINATE/D/G/N/V
+NON
+NONBLOCKING
+NONCONSERVATIVE
+NONCYCLIC
+NONDECREASING
+NONDESCRIPT/Y
+NONDESTRUCTIVELY
+NONDETERMINACY
+NONDETERMINATE/Y
+NONDETERMINISM
+NONDETERMINISTIC
+NONDETERMINISTICALLY
+NONE
+NONEMPTY
+NONETHELESS
+NONEXISTENCE
+NONEXISTENT
+NONEXTENSIBLE
+NONFUNCTIONAL
+NONINTERACTING
+NONINTERFERENCE
+NONINTUITIVE
+NONLINEAR/Y
+NONLINEARITY/M/S
+NONLOCAL
+NONNEGATIVE
+NONORTHOGONAL
+NONORTHOGONALITY
+NONPERISHABLE
+NONPROCEDURAL/Y
+NONPROGRAMMABLE
+NONPROGRAMMER
+NONSENSE
+NONSENSICAL
+NONSPECIALIST/M/S
+NONTECHNICAL
+NONTERMINAL/M/S
+NONTERMINATING
+NONTERMINATION
+NONTRIVIAL
+NONUNIFORM
+NONZERO
+NOODLE/S
+NOOK/M/S
+NOON/S
+NOONDAY
+NOONTIDE
+NOR/H
+NORM/M/S
+NORMAL/Y/S
+NORMALCY
+NORMALITY
+NORMALIZATION
+NORMALIZE/D/G/S
+NORTHEAST/R
+NORTHEASTERN
+NORTHERN/R/Z/Y
+NORTHWARD/S
+NORTHWEST
+NORTHWESTERN
+NOSE/D/G/S
+NOSTRIL/M/S
+NOT
+NOTABLE/S
+NOTABLY
+NOTARIZE/D/G/S
+NOTATION/M/S
+NOTATIONAL
+NOTCH/D/G/S
+NOTE/D/G/N/X/S
+NOTEBOOK/M/S
+NOTEWORTHY
+NOTHING/P/S
+NOTICE/D/G/S
+NOTICEABLE
+NOTICEABLY
+NOTIFY/D/R/Z/G/N/X/S
+NOTORIOUS/Y
+NOTWITHSTANDING
+NOUN/M/S
+NOURISH/D/G/S
+NOURISHMENT
+NOVEL/M/S
+NOVELIST/M/S
+NOVELTY/M/S
+NOVEMBER
+NOVICE/M/S
+NOW
+NOWADAYS
+NOWHERE
+NSF
+NUANCES
+NUCLEAR
+NUCLEOTIDE/M/S
+NUCLEUS
+NUISANCE/M/S
+NULL/D/S
+NULLARY
+NULLIFY/D/Z/G/S
+NUMB/P/D/Z/G/Y/S
+NUMBER/D/R/G/S
+NUMBERLESS
+NUMERAL/M/S
+NUMERATOR/M/S
+NUMERIC/S
+NUMERICAL/Y
+NUMEROUS
+NUN/M/S
+NUPTIAL
+NURSE/D/G/S
+NURSERY/M/S
+NURTURE/D/G/S
+NUT/M/S
+NUTRITION
+NYMPH
+NYMPHS
+O'CLOCK
+OAK/N/S
+OAR/M/S
+OASIS
+OAT/N/S
+OATH
+OATHS
+OATMEAL
+OBEDIENCE/S
+OBEDIENT/Y
+OBEY/D/G/S
+OBJECT/D/G/M/S/V
+OBJECTION/M/S
+OBJECTIONABLE
+OBJECTIVELY
+OBJECTIVES
+OBJECTOR/M/S
+OBLIGATION/M/S
+OBLIGATORY
+OBLIGE/D/G/S
+OBLIGINGLY
+OBLIQUE/P/Y
+OBLITERATE/D/G/N/S
+OBLIVION
+OBLIVIOUS/P/Y
+OBLONG
+OBSCENE
+OBSCURE/D/R/G/Y/S
+OBSCURITY/S
+OBSERVABILITY
+OBSERVABLE
+OBSERVANCE/M/S
+OBSERVANT
+OBSERVATION/M/S
+OBSERVATORY
+OBSERVE/D/R/Z/G/S
+OBSESSION/M/S
+OBSOLESCENCE
+OBSOLETE/D/G/S
+OBSTACLE/M/S
+OBSTINACY
+OBSTINATE/Y
+OBSTRUCT/D/G/V
+OBSTRUCTION/M/S
+OBTAIN/D/G/S
+OBTAINABLE
+OBTAINABLY
+OBVIATE/D/G/N/X/S
+OBVIOUS/P/Y
+OCCASION/D/G/J/S
+OCCASIONAL/Y
+OCCLUDE/D/S
+OCCLUSION/M/S
+OCCUPANCY/S
+OCCUPANT/M/S
+OCCUPATION/M/S
+OCCUPATIONAL/Y
+OCCUPY/D/R/G/S
+OCCUR/S
+OCCURRED
+OCCURRENCE/M/S
+OCCURRING
+OCEAN/M/S
+OCTAL
+OCTAVE/S
+OCTOBER
+OCTOPUS
+ODD/P/T/R/Y/S
+ODDITY/M/S
+ODE/M/S
+ODIOUS/P/Y
+ODOR/M/S
+ODOROUS/P/Y
+ODYSSEY
+OEDIPUS
+OF
+OFF/G
+OFFEND/D/R/Z/G/S
+OFFENSE/V/S
+OFFENSIVELY
+OFFENSIVENESS
+OFFER/D/R/Z/G/J/S
+OFFICE/R/Z/S
+OFFICER'S
+OFFICIAL/Y/S
+OFFICIO
+OFFICIOUS/P/Y
+OFFSET/M/S
+OFFSPRING
+OFT/N
+OFTENTIMES
+OH
+OHIO/M
+OIL/D/R/Z/G/S
+OILCLOTH
+OILY/T/R
+OINTMENT
+OK
+OKAY
+OLD/P/T/R/N
+OLIVE/M/S
+OLIVETTI
+OMEN/M/S
+OMINOUS/P/Y
+OMISSION/M/S
+OMIT/S
+OMITTED
+OMITTING
+OMNIPRESENT
+OMNISCIENT/Y
+OMNIVORE
+ON/Y
+ONANISM
+ONBOARD
+ONCE
+ONCOLOGY
+ONE/P/M/N/X/S
+ONEROUS
+ONESELF
+ONGOING
+ONLINE
+ONSET/M/S
+ONTO
+ONWARD/S
+OOZE/D
+OPACITY
+OPAL/M/S
+OPAQUE/P/Y
+OPCODE
+OPEN/P/D/R/Z/Y/S
+OPENING/M/S
+OPERA/M/S
+OPERABLE
+OPERAND/M/S
+OPERANDI
+OPERATE/D/G/N/X/V/S
+OPERATIONAL/Y
+OPERATIVES
+OPERATOR/M/S
+OPINION/M/S
+OPIUM
+OPPONENT/M/S
+OPPORTUNE/Y
+OPPORTUNISM
+OPPORTUNISTIC
+OPPORTUNITY/M/S
+OPPOSE/D/G/S
+OPPOSITE/P/N/Y/S
+OPPRESS/D/G/V/S
+OPPRESSION
+OPPRESSOR/M/S
+OPT/D/G/S
+OPTIC/S
+OPTICAL/Y
+OPTIMAL/Y
+OPTIMALITY
+OPTIMISM
+OPTIMISTIC
+OPTIMISTICALLY
+OPTIMIZATION/M/S
+OPTIMIZE/D/R/Z/G/S
+OPTIMUM
+OPTION/M/S
+OPTIONAL/Y
+OR/M/Y
+ORACLE/M/S
+ORAL/Y
+ORANGE/M/S
+ORATION/M/S
+ORATOR/M/S
+ORATORY/M/S
+ORB
+ORBIT/D/R/Z/G/S
+ORBITAL/Y
+ORCHARD/M/S
+ORCHESTRA/M/S
+ORCHID/M/S
+ORDAIN/D/G/S
+ORDEAL
+ORDER/D/G/Y/J/S
+ORDERLIES
+ORDINAL
+ORDINANCE/M/S
+ORDINARILY
+ORDINARY/P
+ORDINATE/N/S
+ORE/M/S
+ORGAN/M/S
+ORGANIC
+ORGANISM/M/S
+ORGANIST/M/S
+ORGANIZABLE
+ORGANIZATION/M/S
+ORGANIZATIONAL/Y
+ORGANIZE/D/R/Z/G/S
+ORGY/M/S
+ORIENT/D/G/S
+ORIENTAL
+ORIENTATION/M/S
+ORIFICE/M/S
+ORIGIN/M/S
+ORIGINAL/Y/S
+ORIGINALITY
+ORIGINATE/D/G/N/S
+ORIGINATOR/M/S
+ORLEANS
+ORNAMENT/D/G/S
+ORNAMENTAL/Y
+ORNAMENTATION
+ORPHAN/D/S
+ORTHODOX
+ORTHOGONAL/Y
+ORTHOGONALITY
+ORTHOGRAPHIC
+OSAKA
+OSCILLATE/D/G/N/X/S
+OSCILLATION/M/S
+OSCILLATOR/M/S
+OSCILLATORY
+OSCILLOSCOPE/M/S
+OSTRICH/M/S
+OTHER/S
+OTHERWISE
+OTTER/M/S
+OUGHT
+OUNCE/S
+OUR/S
+OURSELF
+OURSELVES
+OUT/R/G/S
+OUTBREAK/M/S
+OUTBURST/M/S
+OUTCAST/M/S
+OUTCOME/M/S
+OUTCRY/S
+OUTDOOR/S
+OUTERMOST
+OUTFIT/M/S
+OUTGOING
+OUTGREW
+OUTGROW/G/H/S
+OUTGROWN
+OUTLAST/S
+OUTLAW/D/G/S
+OUTLAY/M/S
+OUTLET/M/S
+OUTLINE/D/G/S
+OUTLIVE/D/G/S
+OUTLOOK
+OUTPERFORM/D/G/S
+OUTPOST/M/S
+OUTPUT/M/S
+OUTPUTTING
+OUTRAGE/D/S
+OUTRAGEOUS/Y
+OUTRIGHT
+OUTRUN/S
+OUTSET
+OUTSIDE/R
+OUTSIDER/M/S
+OUTSKIRTS
+OUTSTANDING/Y
+OUTSTRETCHED
+OUTSTRIP/S
+OUTSTRIPPED
+OUTSTRIPPING
+OUTVOTE/D/G/S
+OUTWARD/Y
+OUTWEIGH/D/G
+OUTWEIGHS
+OUTWIT/S
+OUTWITTED
+OUTWITTING
+OVAL/M/S
+OVARY/M/S
+OVEN/M/S
+OVER/Y
+OVERALL/M/S
+OVERBOARD
+OVERCAME
+OVERCOAT/M/S
+OVERCOME/G/S
+OVERCROWD/D/G/S
+OVERDONE
+OVERDRAFT/M/S
+OVERDUE
+OVEREMPHASIS
+OVEREMPHASIZED
+OVERESTIMATE/D/G/N/S
+OVERFLOW/D/G/S
+OVERHANG/G/S
+OVERHAUL/G
+OVERHEAD/S
+OVERHEAR/G/S
+OVERHEARD
+OVERJOY/D
+OVERLAND
+OVERLAP/M/S
+OVERLAPPED
+OVERLAPPING
+OVERLAY/G/S
+OVERLOAD/D/G/S
+OVERLOOK/D/G/S
+OVERNIGHT/R/Z
+OVERPOWER/D/G/S
+OVERPRINT/D/G/S
+OVERPRODUCTION
+OVERRIDDEN
+OVERRIDE/G/S
+OVERRODE
+OVERRULE/D/S
+OVERRUN/S
+OVERSEAS
+OVERSEE/R/Z/S
+OVERSEEING
+OVERSHADOW/D/G/S
+OVERSHOOT
+OVERSHOT
+OVERSIGHT/M/S
+OVERSIMPLIFY/D/G/S
+OVERSTATE/D/G/S
+OVERSTATEMENT/M/S
+OVERSTOCKS
+OVERT/Y
+OVERTAKE/R/Z/G/S
+OVERTAKEN
+OVERTHREW
+OVERTHROW
+OVERTHROWN
+OVERTIME
+OVERTONE/M/S
+OVERTOOK
+OVERTURE/M/S
+OVERTURN/D/G/S
+OVERUSE
+OVERVIEW/M/S
+OVERWHELM/D/G/S
+OVERWHELMINGLY
+OVERWORK/D/G/S
+OVERWRITE/G/S
+OVERWRITTEN
+OVERZEALOUS
+OWE/D/G/S
+OWL/M/S
+OWN/D/R/Z/G/S
+OWNERSHIP/S
+OX/N
+OXFORD
+OXIDE/M/S
+OXIDIZE/D
+OXYGEN
+OYSTER/M/S
+PA/H
+PACE/D/R/Z/G/S
+PACHELBEL
+PACIFIC
+PACIFY/R/N/S
+PACK/D/R/Z/G/S
+PACKAGE/D/R/Z/G/J/S
+PACKET/M/S
+PACT/M/S
+PAD/M/S
+PADDED
+PADDING
+PADDLE
+PADDY
+PAGAN/M/S
+PAGE'S
+PAGE/D/R/Z/G/S
+PAGEANT/M/S
+PAGINATE/D/G/N/S
+PAID
+PAIL/M/S
+PAIN/D/S
+PAINFUL/Y
+PAINSTAKING/Y
+PAINT/D/R/Z/G/J/S
+PAIR/D/G/J/S
+PAIRWISE
+PAJAMA/S
+PAL/M/S
+PALACE/M/S
+PALATE/M/S
+PALE/P/D/T/R/G/Y/S
+PALETTE
+PALFREY
+PALL
+PALLIATE/V
+PALLID
+PALM/D/R/G/S
+PALPATION
+PAMPHLET/M/S
+PAN/M/S
+PANACEA/M/S
+PANCAKE/M/S
+PANDEMONIUM
+PANE/M/S
+PANEL/D/G/S
+PANELIST/M/S
+PANG/M/S
+PANIC/M/S
+PANNED
+PANNING
+PANSY/M/S
+PANT/D/G/S
+PANTHER/M/S
+PANTRY/M/S
+PANTY/S
+PAPA
+PAPAL
+PAPER'S
+PAPER/D/R/Z/G/J/S
+PAPERBACK/M/S
+PAPERWORK
+PAPRIKA
+PAR/S
+PARACHUTE/M/S
+PARADE/D/G/S
+PARADIGM/M/S
+PARADISE
+PARADOX/M/S
+PARADOXICAL/Y
+PARAFFIN
+PARAGON/M/S
+PARAGRAPH/G
+PARAGRAPHS
+PARALLEL/D/G/S
+PARALLELISM
+PARALLELIZE/D/G/S
+PARALLELLED
+PARALLELLING
+PARALLELOGRAM/M/S
+PARALYSIS
+PARALYZE/D/G/S
+PARAMETER/M/S
+PARAMETERIZABLE
+PARAMETERIZATION/M/S
+PARAMETERIZE/D/G/S
+PARAMETERLESS
+PARAMETRIC
+PARAMILITARY
+PARAMOUNT
+PARANOIA
+PARANOID
+PARAPET/M/S
+PARAPHRASE/D/G/S
+PARASITE/M/S
+PARASITIC/S
+PARCEL/D/G/S
+PARCH/D
+PARCHMENT
+PARDON/D/R/Z/G/S
+PARDONABLE
+PARDONABLY
+PARE/G/J/S
+PARENT/M/S
+PARENTAGE
+PARENTAL
+PARENTHESES
+PARENTHESIS
+PARENTHESIZED
+PARENTHETICAL/Y
+PARENTHOOD
+PARISH/M/S
+PARITY
+PARK/D/R/Z/G/S
+PARLIAMENT/M/S
+PARLIAMENTARY
+PARLOR/M/S
+PAROLE/D/G/S
+PARROT/G/S
+PARRY/D
+PARSE/D/R/Z/G/J/S
+PARSIMONY
+PARSLEY
+PARSON/M/S
+PART/D/R/Z/G/Y/J/S
+PARTAKE/R/G/S
+PARTIAL/Y
+PARTIALITY
+PARTICIPANT/M/S
+PARTICIPATE/D/G/N/S
+PARTICLE/M/S
+PARTICULAR/Y/S
+PARTISAN/M/S
+PARTITION/D/G/S
+PARTNER/D/S
+PARTNERSHIP
+PARTRIDGE/M/S
+PARTY/M/S
+PASCAL
+PASS
+PASSAGE/M/S
+PASSAGEWAY
+PASSE/D/R/Z/G/N/X/S
+PASSENGER/M/S
+PASSIONATE/Y
+PASSIVE/P/Y
+PASSIVITY
+PASSPORT/M/S
+PASSWORD/M/S
+PAST/P/M/S
+PASTE/D/G/S
+PASTEBOARD
+PASTIME/M/S
+PASTOR/M/S
+PASTORAL
+PASTRY
+PASTURE/M/S
+PAT/S
+PATCH/D/G/S
+PATCHWORK
+PATENT/D/R/Z/G/Y/S
+PATENTABLE
+PATERNAL/Y
+PATHETIC
+PATHOLOGICAL
+PATHOLOGY
+PATHOS
+PATHS
+PATHWAY/M/S
+PATIENCE
+PATIENT/Y/S
+PATRIARCH
+PATRIARCHS
+PATRICIAN/M/S
+PATRIOT/M/S
+PATRIOTIC
+PATRIOTISM
+PATROL/M/S
+PATRON/M/S
+PATRONAGE
+PATRONIZE/D/G/S
+PATTER/D/G/J/S
+PATTERN/D/G/S
+PATTY/M/S
+PAUCITY
+PAUL/M
+PAUSE/D/G/S
+PAVE/D/G/S
+PAVEMENT/M/S
+PAVILION/M/S
+PAW/G/S
+PAWN/M/S
+PAY/G/S
+PAYABLE
+PAYCHECK/M/S
+PAYER/M/S
+PAYMENT/M/S
+PAYOFF/M/S
+PAYROLL
+PC
+PDP
+PEA/M/S
+PEACE
+PEACEABLE
+PEACEFUL/P/Y
+PEACH/M/S
+PEACOCK/M/S
+PEAK/D/S
+PEAL/D/G/S
+PEANUT/M/S
+PEAR/Y/S
+PEARL/M/S
+PEASANT/M/S
+PEASANTRY
+PEAT
+PEBBLE/M/S
+PECK/D/G/S
+PECULIAR/Y
+PECULIARITY/M/S
+PEDAGOGIC
+PEDAGOGICAL
+PEDANTIC
+PEDDLER/M/S
+PEDESTAL
+PEDESTRIAN/M/S
+PEDIATRIC/S
+PEEK/D/G/S
+PEEL/D/G/S
+PEEP/D/R/G/S
+PEER/D/G/S
+PEERLESS
+PEG/M/S
+PELT/G/S
+PEN
+PENALIZE/D/G/S
+PENALTY/M/S
+PENANCE
+PENCE
+PENCIL/D/S
+PEND/D/G/S
+PENDULUM/M/S
+PENETRATE/D/G/N/X/V/S
+PENETRATINGLY
+PENETRATOR/M/S
+PENGUIN/M/S
+PENINSULA/M/S
+PENITENT
+PENITENTIARY
+PENNED
+PENNILESS
+PENNING
+PENNSYLVANIA
+PENNY/M/S
+PENS/V
+PENSION/R/S
+PENT
+PENTAGON/M/S
+PEOPLE/D/M/S
+PEP
+PEPPER/D/G/S
+PER
+PERCEIVABLE
+PERCEIVABLY
+PERCEIVE/D/R/Z/G/S
+PERCENT/S
+PERCENTAGE/S
+PERCENTILE/S
+PERCEPTIBLE
+PERCEPTIBLY
+PERCEPTION/S
+PERCEPTIVE/Y
+PERCEPTRON/S
+PERCEPTUAL/Y
+PERCH/D/G/S
+PERCHANCE
+PERCUSSION
+PERCUTANEOUS
+PEREMPTORY
+PERENNIAL/Y
+PERFECT/P/D/G/Y/S
+PERFECTION
+PERFECTIONIST/M/S
+PERFORCE
+PERFORM/D/R/Z/G/S
+PERFORMANCE/M/S
+PERFUME/D/G/S
+PERHAPS
+PERIL/M/S
+PERILOUS/Y
+PERIMETER/S
+PERIOD/M/S
+PERIODIC
+PERIODICAL/Y/S
+PERIPHERAL/Y/S
+PERIPHERY/M/S
+PERISH/D/R/Z/G/S
+PERISHABLE/M/S
+PERMANENCE
+PERMANENT/Y
+PERMEATE/D/G/N/S
+PERMISSIBILITY
+PERMISSIBLE
+PERMISSIBLY
+PERMISSION/S
+PERMISSIVE/Y
+PERMIT/M/S
+PERMITTED
+PERMITTING
+PERMUTATION/M/S
+PERMUTE/D/G/S
+PERPENDICULAR/Y/S
+PERPETRATE/D/G/N/X/S
+PERPETRATOR/M/S
+PERPETUAL/Y
+PERPETUATE/D/G/N/S
+PERPLEX/D/G
+PERPLEXITY
+PERSECUTE/D/G/N/S
+PERSECUTOR/M/S
+PERSEVERANCE
+PERSEVERE/D/G/S
+PERSIST/D/G/S
+PERSISTENCE
+PERSISTENT/Y
+PERSON/M/S
+PERSONAGE/M/S
+PERSONAL/Y
+PERSONALITY/M/S
+PERSONALIZATION
+PERSONALIZE/D/G/S
+PERSONIFY/D/G/N/S
+PERSONNEL
+PERSPECTIVE/M/S
+PERSPICUOUS/Y
+PERSPIRATION
+PERSUADABLE
+PERSUADE/D/R/Z/G/S
+PERSUASION/M/S
+PERSUASIVE/P/Y
+PERTAIN/D/G/S
+PERTINENT
+PERTURB/D
+PERTURBATION/M/S
+PERUSAL
+PERUSE/D/R/Z/G/S
+PERVADE/D/G/S
+PERVASIVE/Y
+PERVERT/D/S
+PESSIMISTIC
+PEST/R/S
+PESTILENCE
+PET/R/Z/S
+PETAL/M/S
+PETITION/D/R/G/S
+PETROLEUM
+PETTED
+PETTER/M/S
+PETTICOAT/M/S
+PETTING
+PETTY/P
+PEW/M/S
+PEWTER
+PHANTOM/M/S
+PHASE/D/R/Z/G/S
+PHEASANT/M/S
+PHENOMENA
+PHENOMENAL/Y
+PHENOMENOLOGICAL/Y
+PHENOMENOLOGY/S
+PHENOMENON
+PHILADELPHIA
+PHILOSOPHER/M/S
+PHILOSOPHIC
+PHILOSOPHICAL/Y
+PHILOSOPHIZE/D/R/Z/G/S
+PHILOSOPHY/M/S
+PHONE/D/G/S
+PHONEME/M/S
+PHONEMIC
+PHONETIC/S
+PHONOGRAPH
+PHONOGRAPHS
+PHOSPHATE/M/S
+PHOSPHORIC
+PHOTO/M/S
+PHOTOCOPY/D/G/S
+PHOTOGRAPH/D/R/Z/G
+PHOTOGRAPHIC
+PHOTOGRAPHS
+PHOTOGRAPHY
+PHOTOTYPESETTER/S
+PHRASE/D/G/J/S
+PHYLA
+PHYLUM
+PHYSIC/S
+PHYSICAL/P/Y/S
+PHYSICIAN/M/S
+PHYSICIST/M/S
+PHYSIOLOGICAL/Y
+PHYSIOLOGY
+PHYSIQUE
+PI
+PIANO/M/S
+PIAZZA/M/S
+PICAYUNE
+PICK/D/R/Z/G/J/S
+PICKET/D/R/Z/G/S
+PICKLE/D/G/S
+PICKUP/M/S
+PICKY
+PICNIC/M/S
+PICTORIAL/Y
+PICTURE/D/G/S
+PICTURESQUE/P
+PIE/R/Z/S
+PIECE/D/G/S
+PIECEMEAL
+PIECEWISE
+PIERCE/D/G/S
+PIETY
+PIG/M/S
+PIGEON/M/S
+PIGMENT/D/S
+PIKE/R/S
+PILE/D/Z/G/J/S
+PILFERAGE
+PILGRIM/M/S
+PILGRIMAGE/M/S
+PILL/M/S
+PILLAGE/D
+PILLAR/D/S
+PILLOW/M/S
+PILOT/G/S
+PIN/M/S
+PINCH/D/G/S
+PINE/D/G/N/S
+PINEAPPLE/M/S
+PING
+PINK/P/T/R/Y/S
+PINNACLE/M/S
+PINNED
+PINNING/S
+PINPOINT/G/S
+PINT/M/S
+PIONEER/D/G/S
+PIOUS/Y
+PIPE/D/R/Z/G/S
+PIPELINE/D/G/S
+PIQUE
+PIRATE/M/S
+PISTIL/M/S
+PISTOL/M/S
+PISTON/M/S
+PIT/M/S
+PITCH/D/R/Z/G/S
+PITEOUS/Y
+PITFALL/M/S
+PITH/D/G/S
+PITHY/P/T/R
+PITIABLE
+PITIFUL/Y
+PITILESS/Y
+PITTED
+PITTSBURGH/M
+PITY/D/R/Z/G/S
+PITYINGLY
+PIVOT/G/S
+PIVOTAL
+PIXEL/S
+PLACARD/M/S
+PLACE/D/R/G/S
+PLACEMENT/M/S
+PLACID/Y
+PLAGUE/D/G/S
+PLAID/M/S
+PLAIN/P/T/R/Y/S
+PLAINTIFF/M/S
+PLAINTIVE/P/Y
+PLAIT/M/S
+PLAN/M/S
+PLANAR
+PLANARITY
+PLANE'S
+PLANE/D/R/Z/G/S
+PLANET/M/S
+PLANETARY
+PLANK/G/S
+PLANNED
+PLANNER/M/S
+PLANNING
+PLANT/D/R/Z/G/J/S
+PLANTATION/M/S
+PLASMA
+PLASTER/D/R/G/S
+PLASTIC/S
+PLASTICITY
+PLATE/D/G/S
+PLATEAU/M/S
+PLATELET/M/S
+PLATEN/M/S
+PLATFORM/M/S
+PLATINUM
+PLATO
+PLATTER/M/S
+PLAUSIBILITY
+PLAUSIBLE
+PLAY/D/G/S
+PLAYABLE
+PLAYER/M/S
+PLAYFUL/P/Y
+PLAYGROUND/M/S
+PLAYMATE/M/S
+PLAYTHING/M/S
+PLAYWRIGHT/M/S
+PLAZA
+PLEA/M/S
+PLEAD/D/R/G/S
+PLEASANT/P/Y
+PLEASE/D/G/S
+PLEASINGLY
+PLEASURE/S
+PLEBEIAN
+PLEBISCITE/M/S
+PLEDGE/D/S
+PLENARY
+PLENTEOUS
+PLENTIFUL/Y
+PLENTY
+PLEURISY
+PLIGHT
+PLOD
+PLOT/M/S
+PLOTTED
+PLOTTER/M/S
+PLOTTING
+PLOUGH
+PLOUGHMAN
+PLOW/D/R/G/S
+PLOWMAN
+PLOY/M/S
+PLUCK/D/G
+PLUCKY
+PLUG/M/S
+PLUGGED
+PLUGGING
+PLUM/M/S
+PLUMAGE
+PLUMB/D/M/G/S
+PLUME/D/S
+PLUMMETING
+PLUMP/P/D
+PLUNDER/D/R/Z/G/S
+PLUNGE/D/R/Z/G/S
+PLURAL/S
+PLURALITY
+PLUS
+PLUSH
+PLY/D/Z/S
+PNEUMONIA
+POACH/R/S
+POCKET/D/G/S
+POCKETBOOK/M/S
+POD/M/S
+POEM/M/S
+POET/M/S
+POETIC/S
+POETICAL/Y
+POETRY/M/S
+POINT/D/R/Z/G/S
+POINTEDLY
+POINTLESS
+POINTY
+POISE/D/S
+POISON/D/R/G/S
+POISONOUS/P
+POKE/D/R/G/S
+POLAND
+POLAR
+POLARITY/M/S
+POLE/D/G/S
+POLEMIC/S
+POLICE/D/M/G/S
+POLICEMAN
+POLICEMEN
+POLICY/M/S
+POLISH/D/R/Z/G/S
+POLITE/P/T/R/Y
+POLITIC/S
+POLITICAL/Y
+POLITICIAN/M/S
+POLL/D/G/N/S
+POLLUTANT/S
+POLLUTE/D/G/N/S
+POLO
+POLYGON/S
+POLYGONAL
+POLYHEDRA
+POLYHEDRON
+POLYLINE
+POLYMER/M/S
+POLYMORPHIC
+POLYMORPHISM
+POLYNOMIAL/M/S
+POLYTECHNIC
+POMP
+POMPOUS/P/Y
+POND/R/S
+PONDER/D/G/S
+PONDEROUS
+PONY/M/S
+POOL/D/G/S
+POOR/P/T/R/Y
+POP/M/S
+POPLAR
+POPPED
+POPPING
+POPPY/M/S
+POPULACE
+POPULAR/Y
+POPULARITY
+POPULARIZATION
+POPULARIZE/D/G/S
+POPULATE/D/G/N/X/S
+POPULOUS/P
+PORCELAIN
+PORCH/M/S
+PORCUPINE/M/S
+PORE/D/G/S
+PORK/R
+PORNOGRAPHIC
+PORRIDGE
+PORT/R/Z/Y/S/D/G
+PORTABILITY
+PORTABLE
+PORTAL/M/S
+PORTEND/D/G/S
+PORTION/M/S
+PORTRAIT/M/S
+PORTRAY/D/G/S
+PORTUGUESE
+POSE/D/R/Z/G/S
+POSIT/D/G/S
+POSITION/D/G/S
+POSITIONAL
+POSITIVE/P/Y/S
+POSSESS/D/G/V/S
+POSSESSION/M/S
+POSSESSIONAL
+POSSESSIVE/P/Y
+POSSESSOR/M/S
+POSSIBILITY/M/S
+POSSIBLE
+POSSIBLY
+POSSUM/M/S
+POST/D/R/Z/G/S
+POSTAGE
+POSTAL
+POSTCONDITION
+POSTDOCTORAL
+POSTERIOR
+POSTERITY
+POSTMAN
+POSTMASTER/M/S
+POSTMODERNISM
+POSTOFFICE/M/S
+POSTPONE/D/G
+POSTSCRIPT/M/S
+POSTSTRUCTURALISM
+POSTSTRUCTURALIST
+POSTULATE/D/G/N/X/S
+POSTURE/M/S
+POT/M/S
+POTASH
+POTASSIUM
+POTATO
+POTATOES
+POTENT
+POTENTATE/M/S
+POTENTIAL/Y/S
+POTENTIALITY/S
+POTENTIATING
+POTENTIOMETER/M/S
+POTTED
+POTTER/M/S
+POTTERY
+POTTING
+POUCH/M/S
+POUGHKEEPSIE
+POULTRY
+POUNCE/D/G/S
+POUND/D/R/Z/G/S
+POUR/D/R/Z/G/S
+POUT/D/G/S
+POVERTY
+POWDER/D/G/S
+POWER/D/G/S
+POWERFUL/P/Y
+POWERLESS/P/Y
+POWERSET/M/S
+POX
+PRACTICABLE
+PRACTICABLY
+PRACTICAL/Y
+PRACTICALITY
+PRACTICE/D/G/S
+PRACTISE/D/G
+PRACTITIONER/M/S
+PRAGMATIC/S
+PRAGMATICALLY
+PRAIRIE
+PRAISE/D/R/Z/G/S
+PRAISINGLY
+PRANCE/D/R/G
+PRANK/M/S
+PRATE
+PRAY/D/G
+PRAYER/M/S
+PRE
+PREACH/D/R/Z/G/S
+PREAMBLE
+PREASSIGN/D/G/S
+PRECARIOUS/P/Y
+PRECAUTION/M/S
+PRECEDE/D/G/S
+PRECEDENCE/M/S
+PRECEDENT/D/S
+PRECEPT/M/S
+PRECINCT/M/S
+PRECIOUS/P/Y
+PRECIPICE
+PRECIPITATE/P/D/G/N/Y/S
+PRECIPITOUS/Y
+PRECISE/P/N/X/Y
+PRECLUDE/D/G/S
+PRECOCIOUS/Y
+PRECONCEIVE/D
+PRECONCEPTION/M/S
+PRECONDITION/D/S
+PRECURSOR/M/S
+PREDATE/D/G/S
+PREDECESSOR/M/S
+PREDEFINE/D/G/S
+PREDEFINITION/M/S
+PREDETERMINE/D/G/S
+PREDICAMENT
+PREDICATE/D/G/N/X/S
+PREDICT/D/G/V/S
+PREDICTABILITY
+PREDICTABLE
+PREDICTABLY
+PREDICTION/M/S
+PREDISPOSE/D/G
+PREDOMINANT/Y
+PREDOMINATE/D/G/N/Y/S
+PREEMPT/D/G/V/S
+PREEMPTION
+PREFACE/D/G/S
+PREFER/S
+PREFERABLE
+PREFERABLY
+PREFERENCE/M/S
+PREFERENTIAL/Y
+PREFERRED
+PREFERRING
+PREFIX/D/S
+PREGNANT
+PREHISTORIC
+PREINITIALIZE/D/G/S
+PREJUDGE/D
+PREJUDICE/D/S
+PRELATE
+PRELIMINARY/S
+PRELUDE/M/S
+PREMATURE/Y
+PREMATURITY
+PREMEDITATED
+PREMIER/M/S
+PREMISE/M/S
+PREMIUM/M/S
+PREOCCUPATION
+PREOCCUPY/D/S
+PREPARATION/M/S
+PREPARATIVE/M/S
+PREPARATORY
+PREPARE/D/G/S
+PREPOSITION/M/S
+PREPOSITIONAL
+PREPOSTEROUS/Y
+PREPROCESS/D/G
+PREPRODUCTION
+PREPROGRAMMED
+PREREQUISITE/M/S
+PREROGATIVE/M/S
+PRESBYTERIAN
+PRESCRIBE/D/S
+PRESCRIPTION/M/S
+PRESCRIPTIVE
+PRESELECT/D/G/S
+PRESENCE/M/S
+PRESENT/P/D/R/G/Y/S
+PRESENTATION/M/S
+PRESERVATION/S
+PRESERVE/D/R/Z/G/S
+PRESET
+PRESIDE/D/G/S
+PRESIDENCY
+PRESIDENT/M/S
+PRESIDENTIAL
+PRESS/D/R/G/J/S
+PRESSURE/D/G/S
+PRESSURIZE/D
+PRESTIGE
+PRESTO
+PRESUMABLY
+PRESUME/D/G/S
+PRESUMPTION/M/S
+PRESUMPTUOUS/P
+PRESUPPOSE/D/G/S
+PRESYNAPTIC
+PRETEND/D/R/Z/G/S
+PRETENSE/N/X/S
+PRETENTIOUS/P/Y
+PRETEXT/M/S
+PRETTILY
+PRETTY/P/T/R
+PREVAIL/D/G/S
+PREVAILINGLY
+PREVALENCE
+PREVALENT/Y
+PREVENT/D/G/V/S
+PREVENTABLE
+PREVENTABLY
+PREVENTION
+PREVENTIVES
+PREVIEW/D/G/S
+PREVIOUS/Y
+PREY/D/G/S
+PRICE/D/R/Z/G/S
+PRICELESS
+PRICK/D/G/Y/S
+PRIDE/D/G/S
+PRIMACY
+PRIMARILY
+PRIMARY/M/S
+PRIME/P/D/R/Z/G/S
+PRIMEVAL
+PRIMITIVE/P/Y/S
+PRIMROSE
+PRINCE/Y/S
+PRINCESS/M/S
+PRINCETON
+PRINCIPAL/Y/S
+PRINCIPALITY/M/S
+PRINCIPLE/D/S
+PRINT/D/R/Z/G/S
+PRINTABLE
+PRINTABLY
+PRINTOUT
+PRIOR
+PRIORI
+PRIORITY/M/S
+PRIORY
+PRISM/M/S
+PRISON/R/Z/S
+PRISONER'S
+PRIVACY/S
+PRIVATE/N/X/Y/S
+PRIVILEGE/D/S
+PRIVY/M/S
+PRIZE/D/R/Z/G/S
+PRO/M/S
+PROBABILISTIC
+PROBABILISTICALLY
+PROBABILITY/S
+PROBABLE
+PROBABLY
+PROBATE/D/G/N/V/S
+PROBE/D/G/J/S
+PROBLEM/M/S
+PROBLEMATIC
+PROBLEMATICAL/Y
+PROCEDURAL/Y
+PROCEDURE/M/S
+PROCEED/D/G/J/S
+PROCESS/D/M/G/S
+PROCESSION
+PROCESSOR/M/S
+PROCLAIM/D/R/Z/G/S
+PROCLAMATION/M/S
+PROCLIVITY/M/S
+PROCRASTINATE/D/G/N/S
+PROCURE/D/R/Z/G/S
+PROCUREMENT/M/S
+PRODIGAL/Y
+PRODIGIOUS
+PRODIGY
+PRODUCE/D/R/Z/G/S
+PRODUCIBLE
+PRODUCT/M/V/S
+PRODUCTION/M/S
+PRODUCTIVELY
+PRODUCTIVITY
+PROFANE/Y
+PROFESS/D/G/S
+PROFESSION/M/S
+PROFESSIONAL/Y/S
+PROFESSIONALISM
+PROFESSOR/M/S
+PROFFER/D/S
+PROFICIENCY
+PROFICIENT/Y
+PROFILE/D/G/S
+PROFIT/D/G/S/R/M/Z
+PROFITABILITY
+PROFITABLE
+PROFITABLY
+PROFITEER/M/S
+PROFOUND/T/Y
+PROG
+PROGENY
+PROGRAM/M/S
+PROGRAMMABILITY
+PROGRAMMABLE
+PROGRAMMED
+PROGRAMMER/M/S
+PROGRAMMING
+PROGRESS/D/G/V/S
+PROGRESSION/M/S
+PROGRESSIVE/Y
+PROHIBIT/D/G/V/S
+PROHIBITION/M/S
+PROHIBITIVELY
+PROJECT/D/G/V/S/M
+PROJECTION/M/S
+PROJECTIVELY
+PROJECTOR/M/S
+PROLEGOMENA
+PROLETARIAT
+PROLIFERATE/D/G/N/S
+PROLIFIC
+PROLOG
+PROLOGUE
+PROLONG/D/G/S
+PROMENADE/M/S
+PROMINENCE
+PROMINENT/Y
+PROMISE/D/G/S
+PROMONTORY
+PROMOTE/D/R/Z/G/N/X/S
+PROMOTIONAL
+PROMPT/P/D/T/R/Y/S
+PROMPTING/S
+PROMULGATE/D/G/N/S
+PRONE/P
+PRONG/D/S
+PRONOUN/M/S
+PRONOUNCE/D/G/S
+PRONOUNCEABLE
+PRONOUNCEMENT/M/S
+PRONUNCIATION/M/S
+PROOF/M/S
+PROP/R/S
+PROPAGANDA
+PROPAGATE/D/G/N/X/S
+PROPEL/S
+PROPELLED
+PROPELLER/M/S
+PROPENSITY
+PROPERLY
+PROPERNESS
+PROPERTY/D/S
+PROPHECY/M/S
+PROPHESY/D/R/S
+PROPHET/M/S
+PROPHETIC
+PROPITIOUS
+PROPONENT/M/S
+PROPORTION/D/G/S
+PROPORTIONAL/Y
+PROPORTIONATELY
+PROPORTIONMENT
+PROPOSAL/M/S
+PROPOSE/D/R/G/S
+PROPOSITION/D/G/S
+PROPOSITIONAL/Y
+PROPOUND/D/G/S
+PROPRIETARY
+PROPRIETOR/M/S
+PROPRIETY
+PROPULSION/M/S
+PROSE
+PROSECUTE/D/G/N/X/S
+PROSELYTIZE/D/G/S
+PROSODIC/S
+PROSPECT/D/G/V/S
+PROSPECTION/M/S
+PROSPECTIVELY
+PROSPECTIVES
+PROSPECTOR/M/S
+PROSPECTUS
+PROSPER/D/G/S
+PROSPERITY
+PROSPEROUS
+PROSTITUTION
+PROSTRATE/N
+PROTECT/D/G/V/S
+PROTECTION/M/S
+PROTECTIVELY
+PROTECTIVENESS
+PROTECTOR/M/S
+PROTECTORATE
+PROTEGE/M/S
+PROTEIN/M/S
+PROTEST/D/G/S/R/Z/M
+PROTESTATION/S
+PROTESTER'S
+PROTESTINGLY
+PROTESTOR/M/S
+PROTOCOL/M/S
+PROTON/M/S
+PROTOPLASM
+PROTOTYPE/D/G/S
+PROTOTYPICAL/Y
+PROTRUDE/D/G/S
+PROTRUSION/M/S
+PROVABILITY
+PROVABLE
+PROVABLY
+PROVE/D/R/Z/G/S
+PROVEN
+PROVERB/M/S
+PROVIDE/D/R/Z/G/S
+PROVIDENCE
+PROVINCE/M/S
+PROVINCIAL
+PROVINCIALISM
+PROVISION/D/G/S
+PROVISIONAL/Y
+PROVOCATION
+PROVOKE/D/S
+PROW/M/S
+PROWESS
+PROWL/D/R/Z/G
+PROXIMAL
+PROXIMATE
+PROXIMITY
+PRUDENCE
+PRUDENT/Y
+PRUNE/D/R/Z/G/S
+PRY/T/G
+PSALM/M/S
+PSEUDO
+PSYCHE/M/S
+PSYCHIATRIST/M/S
+PSYCHIATRY
+PSYCHOLOGICAL/Y
+PSYCHOLOGIST/M/S
+PSYCHOLOGY
+PSYCHOMETRIC
+PSYCHOSOCIAL
+PUB/M/S
+PUBLIC/Y
+PUBLICATION/M/S
+PUBLICITY
+PUBLICIZE/D/G/S
+PUBLISH/D/R/Z/G/S
+PUCKER/D/G/S
+PUDDING/M/S
+PUDDLE/G/S
+PUFF/D/G/S
+PULL/D/R/G/J/S
+PULLEY/M/S
+PULMONARY
+PULP/G
+PULPIT/M/S
+PULSE/D/G/S
+PUMP/D/G/S
+PUMPKIN/M/S
+PUN/M/S
+PUNCH/D/R/G/S
+PUNCTUAL/Y
+PUNCTUATION
+PUNCTURE/D/M/G/S
+PUNISH/D/G/S
+PUNISHABLE
+PUNISHMENT/M/S
+PUNITIVE
+PUNT/D/G/S
+PUNY
+PUP/M/S
+PUPA
+PUPIL/M/S
+PUPPET/M/S
+PUPPY/M/S
+PURCHASABLE
+PURCHASE/D/R/Z/G/S
+PURCHASEABLE
+PURE/T/R/Y
+PURGE/D/G/S
+PURIFY/D/R/Z/G/N/X/S
+PURITY
+PURPLE/T/R
+PURPORT/D/R/Z/G/S
+PURPORTEDLY
+PURPOSE/D/V/Y/S
+PURPOSEFUL/Y
+PURR/D/G/S
+PURSE/D/R/S
+PURSUE/D/R/Z/G/S
+PURSUIT/M/S
+PURVIEW
+PUSHDOWN
+PUSS
+PUSSY
+PUT/S
+PUTRID
+PUTTER/G/S
+PUTTING
+PUZZLE/D/R/Z/G/J/S
+PUZZLEMENT
+PYGMY/M/S
+PYRAMID/M/S
+QUACK/D/S
+QUADRANT/M/S
+QUADRATIC/S
+QUADRATICAL/Y
+QUADRATURE/M/S
+QUADRUPLE/D/G/S
+QUAGMIRE/M/S
+QUAIL/M/S
+QUAINT/P/Y
+QUAKE/D/R/Z/G/S
+QUALIFY/D/R/Z/G/N/X/S
+QUALITATIVE/Y
+QUALITY/M/S
+QUANDARY/M/S
+QUANTA
+QUANTIFIABLE
+QUANTIFY/D/R/Z/G/N/X/S
+QUANTITATIVE/Y
+QUANTITY/M/S
+QUANTIZATION
+QUANTIZE/D/G/S
+QUANTUM
+QUARANTINE/M/S
+QUARREL/D/G/S
+QUARRELSOME
+QUARRY/M/S
+QUART/Z/S
+QUARTER/D/G/Y/S
+QUARTET/M/S
+QUARTZ
+QUASH/D/G/S
+QUASI
+QUAVER/D/G/S
+QUAY
+QUEEN/M/Y/S
+QUEER/P/T/R/Y
+QUELL/G
+QUENCH/D/G/S
+QUERY/D/G/S
+QUEST/D/R/Z/G/S
+QUESTION/D/R/Z/G/J/S
+QUESTIONABLE
+QUESTIONABLY
+QUESTIONINGLY
+QUESTIONNAIRE/M/S
+QUEUE/D/R/Z/G/S
+QUICK/P/T/R/N/X/Y
+QUICKENED
+QUICKENING
+QUICKSILVER
+QUIESCENT
+QUIET/P/D/T/R/G/Y/S
+QUIETUDE
+QUILL
+QUILT/D/G/S
+QUININE
+QUIT/S
+QUITE
+QUITTER/M/S
+QUITTING
+QUIVER/D/G/S
+QUIXOTE
+QUIZ
+QUIZZED
+QUIZZES
+QUIZZING
+QUO/H
+QUOTA/M/S
+QUOTATION/M/S
+QUOTE/D/G/S
+QUOTIENT
+RABBIT/M/S
+RABBLE
+RACCOON/M/S
+RACE/D/R/Z/G/S
+RACIAL/Y
+RACK/D/G/S
+RACKET/M/S
+RACKETEER/G/S
+RADAR/M/S
+RADIAL/Y
+RADIAN/S
+RADIANCE
+RADIANT/Y
+RADIATE/D/G/N/X/S
+RADIATOR/M/S
+RADICAL/Y/S
+RADII
+RADIO/D/G/S
+RADIOLOGY
+RADISH/M/S
+RADIUS
+RADIX
+RAFT/R/Z/S
+RAG/M/S
+RAGE/D/G/S
+RAGGED/P/Y
+RAID/D/R/Z/G/S
+RAIL/D/R/Z/G/S
+RAILROAD/D/R/Z/G/S
+RAILWAY/M/S
+RAIMENT
+RAIN/D/G/S
+RAINBOW
+RAINCOAT/M/S
+RAINDROP/M/S
+RAINFALL
+RAINY/T/R
+RAISE/D/R/Z/G/S
+RAISIN
+RAKE/D/G/S
+RALLY/D/G/S
+RAM/M/S
+RAMBLE/R/G/J/S
+RAMIFICATION/M/S
+RAMP/M/S
+RAMPART
+RAN
+RANCH/D/R/Z/G/S
+RANDOLPH/M
+RANDOM/P/Y
+RANDY/M
+RANG
+RANGE/D/R/Z/G/S
+RANK/P/D/T/Y/S
+RANKER/M/S
+RANKING/M/S
+RANSACK/D/G/S
+RANSOM/R/G/S
+RANT/D/R/Z/G/S
+RAP/M/S
+RAPE/D/R/G/S
+RAPID/Y/S
+RAPIDITY
+RAPT/Y
+RAPTURE/M/S
+RAPTUROUS
+RARE/P/T/R/Y
+RARITY/M/S
+RASCAL/Y/S
+RASH/P/R/Y
+RASP/D/G/S
+RASPBERRY
+RASTER
+RASTEROP
+RAT/M/S
+RATE/D/R/Z/G/N/X/J/S
+RATHER
+RATIFY/D/G/N/S
+RATIO/M/S
+RATIONAL/Y
+RATIONALE/M/S
+RATIONALITY/S
+RATIONALIZE/D/G/S
+RATTLE/D/R/Z/G/S
+RATTLESNAKE/M/S
+RAVAGE/D/R/Z/G/S
+RAVE/D/G/J/S
+RAVEN/G/S
+RAVENOUS/Y
+RAVINE/M/S
+RAW/P/T/R/Y
+RAY/M/S
+RAZOR/M/S
+RE/D/Y/J
+REABBREVIATE/D/G/S
+REACH/D/R/G/S
+REACHABLE
+REACHABLY
+REACT/D/G/V/S
+REACTION/M/S
+REACTIONARY/M/S
+REACTIVATE/D/G/N/S
+REACTIVELY
+REACTIVITY
+REACTOR/M/S
+READ/R/Z/G/J/S
+READABILITY
+READABLE
+READILY
+READJUSTED
+READJUSTMENT
+READOUT/M/S
+READY/P/D/T/R/G/S
+REAL/P/S/T/Y
+REALIGN/D/G/S
+REALISM
+REALIST/M/S
+REALISTIC
+REALISTICALLY
+REALITY/S
+REALIZABLE
+REALIZABLY
+REALIZATION/M/S
+REALIZE/D/G/S
+REALM/M/S
+REANALYZE/G/S
+REAP/D/R/G/S
+REAPPEAR/D/G/S
+REAPPRAISAL/S
+REAR/D/G/S
+REARRANGE/D/G/S
+REARRANGEABLE
+REARRANGEMENT/M/S
+REARREST/D
+REASON/D/R/G/J/S
+REASONABLE/P
+REASONABLY
+REASSEMBLE/D/G/S
+REASSESSMENT/M/S
+REASSIGN/D/G/S
+REASSIGNMENT/M/S
+REASSURE/D/G/S
+REAWAKEN/D/G/S
+REBATE/M/S
+REBEL/M/S
+REBELLION/M/S
+REBELLIOUS/P/Y
+REBOUND/D/G/S
+REBROADCAST
+REBUFF/D
+REBUILD/G/S
+REBUILT
+REBUKE/D/G/S
+REBUTTAL
+RECALCULATE/D/G/N/X/S
+RECALL/D/G/S
+RECAPITULATE/D/N/S
+RECAPTURE/D/G/S
+RECAST/G/S
+RECEDE/D/G/S
+RECEIPT/M/S
+RECEIVABLE
+RECEIVE/D/R/Z/G/S
+RECENT/P/Y
+RECEPTACLE/M/S
+RECEPTION/M/S
+RECEPTIVE/P/Y
+RECEPTIVITY
+RECESS/D/V/S
+RECESSION
+RECIPE/M/S
+RECIPIENT/M/S
+RECIPROCAL/Y
+RECIPROCATE/D/G/N/S
+RECIPROCITY
+RECIRCULATE/D/G/S
+RECITAL/M/S
+RECITATION/M/S
+RECITE/D/R/G/S
+RECKLESS/P/Y
+RECKON/D/R/G/J/S
+RECLAIM/D/R/Z/G/S
+RECLAIMABLE
+RECLAMATION/S
+RECLASSIFY/D/G/N/S
+RECLINE/G
+RECODE/D/G/S
+RECOGNITION/M/S
+RECOGNIZABILITY
+RECOGNIZABLE
+RECOGNIZABLY
+RECOGNIZE/D/R/Z/G/S
+RECOIL/D/G/S
+RECOLLECT/D/G
+RECOLLECTION/M/S
+RECOMBINE/D/G/S
+RECOMMEND/D/R/G/S
+RECOMMENDATION/M/S
+RECOMPENSE
+RECOMPILATION
+RECOMPILE/D/G
+RECOMPUTE/D/G/S
+RECONCILE/D/R/G/S
+RECONCILIATION
+RECONFIGURABLE
+RECONFIGURATION/M/S
+RECONFIGURE/D/R/G/S
+RECONNECT/D/G/S
+RECONNECTION
+RECONSIDER/D/G/S
+RECONSIDERATION
+RECONSTRUCT/D/G/S
+RECONSTRUCTION
+RECORD/D/R/Z/G/J/S
+RECOUNT/D/G/S
+RECOURSE
+RECOVER/D/G/S
+RECOVERABLE
+RECOVERY/M/S
+RECREATE/D/G/N/X/V/S
+RECREATION/S
+RECREATIONAL
+RECRUIT/D/R/M/G/S
+RECRUITMENT
+RECTA
+RECTANGLE/M/S
+RECTANGULAR
+RECTIFY
+RECTOR/M/S
+RECTUM/M/S
+RECUR/S
+RECURRENCE/M/S
+RECURRENT/Y
+RECURRING
+RECURSE/D/G/N/S
+RECURSION/M/S
+RECURSIVE/Y
+RECYCLABLE
+RECYCLE/D/G/S
+RED/P/Y/S
+REDBREAST
+REDDEN/D
+REDDER
+REDDEST
+REDDISH/P
+REDECLARE/D/G/S
+REDEEM/D/R/Z/G/S
+REDEFINE/D/G/S
+REDEFINITION/M/S
+REDEMPTION
+REDESIGN/D/G/S
+REDEVELOPMENT
+REDIRECT/D/G
+REDIRECTING
+REDIRECTION/S
+REDISPLAY/D/G/S
+REDISTRIBUTE/D/G/S
+REDONE
+REDOUBLE/D
+REDRAW/G
+REDRAWN
+REDRESS/D/G/S
+REDUCE/D/R/Z/G/S
+REDUCIBILITY
+REDUCIBLE
+REDUCIBLY
+REDUCTION/M/S
+REDUNDANCY/S
+REDUNDANT/Y
+REED/M/S
+REEDUCATION
+REEF/R/S
+REEL/D/R/G/S
+REELECT/D/G/S
+REEMPHASIZE/D/G/S
+REENFORCEMENT
+REENTER/D/G/S
+REENTRANT
+REESTABLISH/D/G/S
+REEVALUATE/D/G/N/S
+REEXAMINE/D/G/S
+REFER/S
+REFEREE/D/S
+REFEREEING
+REFERENCE/D/R/G/S
+REFERENDUM
+REFERENT/M/S
+REFERENTIAL/Y
+REFERENTIALITY
+REFERRAL/M/S
+REFERRED
+REFERRING
+REFILL/D/G/S
+REFILLABLE
+REFINE/D/R/G/S
+REFINEMENT/M/S
+REFLECT/D/G/V/S
+REFLECTION/M/S
+REFLECTIVELY
+REFLECTIVITY
+REFLECTOR/M/S
+REFLEX/M/S
+REFLEXIVE/P/Y
+REFLEXIVITY
+REFORM/D/R/Z/G/S
+REFORMABLE
+REFORMAT/S
+REFORMATION
+REFORMATTED
+REFORMATTING
+REFORMULATE/D/G/N/S
+REFRACTORY
+REFRAIN/D/G/S
+REFRESH/D/R/Z/G/S
+REFRESHINGLY
+REFRESHMENT/M/S
+REFRIGERATOR/M/S
+REFUEL/D/G/S
+REFUGE
+REFUGEE/M/S
+REFUSAL
+REFUSE/D/G/S
+REFUTABLE
+REFUTATION
+REFUTE/D/R/G/S
+REGAIN/D/G/S
+REGAL/D/Y
+REGARD/D/G/S
+REGARDLESS
+REGENERATE/D/G/N/V/S
+REGENT/M/S
+REGIME/M/S
+REGIMEN
+REGIMENT/D/S
+REGION/M/S
+REGIONAL/Y
+REGISTER/D/G/S
+REGISTRATION/M/S
+REGRESS/D/G/V/S
+REGRESSION/M/S
+REGRET/S
+REGRETFUL/Y
+REGRETTABLE
+REGRETTABLY
+REGRETTED
+REGRETTING
+REGROUP/D/G
+REGULAR/Y/S
+REGULARITY/S
+REGULATE/D/G/N/X/V/S
+REGULATOR/M/S
+REHABILITATE/D/G/N
+REHEARSAL/M/S
+REHEARSE/D/R/G/S
+REIGN/D/G/S
+REIMBURSED
+REIMBURSEMENT/M/S
+REIMPLEMENT/D/G
+REIN/D/S
+REINCARNATE/D/N
+REINDEER
+REINFORCE/D/R/G/S
+REINFORCEMENT/M/S
+REINITIALIZE/D/G
+REINSERT/D/G/S
+REINSTATE/D/G/S
+REINSTATEMENT
+REINTERPRET/D/G/S
+REINTRODUCE/D/G/S
+REINVENT/D/G/S
+REITERATE/D/G/N/S
+REJECT/D/G/S
+REJECTION/M/S
+REJECTOR/M/S
+REJOICE/D/R/G/S
+REJOIN/D/G/S
+RELABEL/S/D/G/R/Z
+RELAPSE
+RELATE/D/R/G/N/X/S
+RELATIONAL/Y
+RELATIONSHIP/M/S
+RELATIVE/P/Y/S
+RELATIVISM
+RELATIVISTIC
+RELATIVISTICALLY
+RELATIVITY
+RELAX/D/R/G/S
+RELAXATION/M/S
+RELAY/D/G/S
+RELEARN/D/G
+RELEASE/D/G/S
+RELEGATE/D/G/S
+RELENT/D/G/S
+RELENTLESS/P/Y
+RELEVANCE/S
+RELEVANT/Y
+RELIABILITY
+RELIABLE/P
+RELIABLY
+RELIANCE
+RELIC/M/S
+RELIEF
+RELIEVE/D/R/Z/G/S
+RELIGION/M/S
+RELIGIOUS/P/Y
+RELINQUISH/D/G/S
+RELISH/D/G/S
+RELIVE/G/S
+RELOAD/D/R/G/S
+RELOCATE/D/G/N/X/S
+RELUCTANCE
+RELUCTANT/Y
+RELY/D/G/S
+REMAIN/D/G/S
+REMAINDER/M/S
+REMARK/D/G/S
+REMARKABLE/P
+REMARKABLY
+REMEDIAL
+REMEDY/D/G/S
+REMEMBER/D/G/S
+REMEMBRANCE/M/S
+REMIND/D/R/Z/G/S
+REMINISCENCE/M/S
+REMINISCENT/Y
+REMITTANCE
+REMNANT/M/S
+REMODEL/D/G/S
+REMONSTRATE/D/G/N/V/S
+REMORSE
+REMOTE/P/T/Y
+REMOVABLE
+REMOVAL/M/S
+REMOVE/D/R/G/S
+RENAISSANCE
+RENAL
+RENAME/D/G/S
+REND/Z/G/S
+RENDER/D/G/J/S
+RENDEZVOUS
+RENDITION/M/S
+RENEW/D/R/G/S
+RENEWAL
+RENOUNCE/G/S
+RENOWN/D
+RENT/D/G/S
+RENTAL/M/S
+RENUMBER/G/S
+REOPEN/D/G/S
+REORDER/D/G/S
+REORGANIZATION/M/S
+REORGANIZE/D/G/S
+REPAID
+REPAIR/D/R/G/S
+REPAIRMAN
+REPARATION/M/S
+REPAST/M/S
+REPAY/G/S
+REPEAL/D/R/G/S
+REPEAT/D/R/Z/G/S
+REPEATABLE
+REPEATEDLY
+REPEL/S
+REPENT/D/G/S
+REPENTANCE
+REPERCUSSION/M/S
+REPERTOIRE
+REPETITION/M/S
+REPETITIVE/P/Y
+REPHRASE/D/G/S
+REPINE
+REPLACE/D/R/G/S
+REPLACEABLE
+REPLACEMENT/M/S
+REPLAY/D/G/S
+REPLENISH/D/G/S
+REPLETE/P/N
+REPLICA
+REPLICATE/D/G/N/S
+REPLY/D/G/N/X/S
+REPORT/D/R/Z/G/S
+REPORTEDLY
+REPOSE/D/G/S
+REPOSITION/D/G/S
+REPOSITORY/M/S
+REPRESENT/D/G/S
+REPRESENTABLE
+REPRESENTABLY
+REPRESENTATION/M/S
+REPRESENTATIONAL/Y
+REPRESENTATIVE/P/Y/S
+REPRESS/D/G/V/S
+REPRESSION/M/S
+REPRIEVE/D/G/S
+REPRINT/D/G/S
+REPRISAL/M/S
+REPROACH/D/G/S
+REPRODUCE/D/R/Z/G/S
+REPRODUCIBILITY/S
+REPRODUCIBLE
+REPRODUCIBLY
+REPRODUCTION/M/S
+REPROGRAM/S
+REPROGRAMMED
+REPROGRAMMING
+REPROOF
+REPROVE/R
+REPTILE/M/S
+REPUBLIC/M/S
+REPUBLICAN/M/S
+REPUDIATE/D/G/N/X/S
+REPULSE/D/G/N/X/V/S
+REPUTABLE
+REPUTABLY
+REPUTATION/M/S
+REPUTE/D/S
+REPUTEDLY
+REQUEST/D/R/Z/G/S
+REQUIRE/D/G/S
+REQUIREMENT/M/S
+REQUISITE/X/S
+REQUISITION/D/G/S
+REREAD
+REROUTE/D/G/S
+RESCUE/D/R/Z/G/S
+RESEARCH/D/R/Z/G/S
+RESELECT/D/G/S
+RESEMBLANCE/M/S
+RESEMBLE/D/G/S
+RESENT/D/G/S
+RESENTFUL/Y
+RESENTMENT
+RESERVATION/M/S
+RESERVE/D/R/G/S
+RESERVOIR/M/S
+RESET/S
+RESETTING/S
+RESHAPE/D/G
+RESIDE/D/G/S
+RESIDENCE/M/S
+RESIDENT/M/S
+RESIDENTIAL/Y
+RESIDUE/M/S
+RESIGN/D/G/S
+RESIGNATION/M/S
+RESIN/M/S
+RESIST/D/G/V/S
+RESISTANCE/S
+RESISTANT/Y
+RESISTIBLE
+RESISTIBLY
+RESISTIVITY
+RESISTOR/M/S
+RESIZE/D/G
+RESOLUTE/P/N/X/Y
+RESOLVABLE
+RESOLVE/D/R/Z/G/S
+RESONANCE/S
+RESONANT
+RESORT/D/G/S
+RESOUND/G/S
+RESOURCE/M/S
+RESOURCEFUL/P/Y
+RESPECT/D/R/G/V/S
+RESPECTABILITY
+RESPECTABLE
+RESPECTABLY
+RESPECTFUL/P/Y
+RESPECTIVELY
+RESPIRATION
+RESPITE
+RESPLENDENT/Y
+RESPOND/D/R/G/S
+RESPONDENT/M/S
+RESPONSE/V/S
+RESPONSIBILITY/S
+RESPONSIBLE/P
+RESPONSIBLY
+RESPONSIVELY
+RESPONSIVENESS
+REST/D/G/V/S
+RESTART/D/G/S
+RESTATE/D/G/S
+RESTATEMENT
+RESTAURANT/M/S
+RESTFUL/P/Y
+RESTLESS/P/Y
+RESTORATION/M/S
+RESTORE/D/R/Z/G/S
+RESTRAIN/D/R/Z/G/S
+RESTRAINT/M/S
+RESTRICT/D/G/V/S
+RESTRICTION/M/S
+RESTRICTIVELY
+RESTRUCTURE/D/G/S
+RESULT/D/G/S
+RESULTANT/Y/S
+RESUMABLE
+RESUME/D/G/S
+RESUMPTION/M/S
+RESURRECT/D/G/S
+RESURRECTION/M/S
+RESURRECTOR/S
+RETAIL/R/Z/G
+RETAIN/D/R/Z/G/S
+RETAINMENT
+RETALIATION
+RETARD/D/R/G
+RETENTION/S
+RETENTIVE/P/Y
+RETHINK
+RETICLE/M/S
+RETICULAR
+RETICULATE/D/G/N/Y/S
+RETINA/M/S
+RETINAL
+RETINUE
+RETIRE/D/G/S
+RETIREMENT/M/S
+RETORT/D/S
+RETRACE/D/G
+RETRACT/D/G/S
+RETRACTION/S
+RETRAIN/D/G/S
+RETRANSMISSION/M/S
+RETRANSMIT/S
+RETRANSMITTED
+RETRANSMITTING
+RETREAT/D/G/S
+RETRIEVABLE
+RETRIEVAL/M/S
+RETRIEVE/D/R/Z/G/S
+RETROACTIVE
+RETROACTIVELY
+RETROSPECT/V
+RETROSPECTION
+RETRY/D/R/Z/G/S
+RETURN/D/R/G/S
+RETURNABLE
+RETYPE/D/G/S
+REUNION/M/S
+REUNITE/D/G
+REUSABILITY
+REUSABLE
+REUSE/D/G/S
+REVAMP/D/G/S
+REVEAL/D/G/S
+REVEL/D/R/G/S
+REVELATION/M/S
+REVELRY
+REVENGE/R
+REVENUE/Z/S
+REVERE/D/G/S
+REVERENCE
+REVEREND/M/S
+REVERENTLY
+REVERIFY/D/G/S
+REVERSAL/M/S
+REVERSE/D/R/G/N/Y/S
+REVERSIBLE
+REVERT/D/G/S
+REVIEW/D/R/Z/G/S
+REVILE/D/R/G
+REVISE/D/R/G/N/X/S
+REVISION/M/S
+REVISIT/D/G/S
+REVIVAL/M/S
+REVIVE/D/R/G/S
+REVOCATION
+REVOKE/D/R/G/S
+REVOLT/D/R/G/S
+REVOLTINGLY
+REVOLUTION/M/S
+REVOLUTIONARY/M/S
+REVOLUTIONIZE/D/R
+REVOLVE/D/R/Z/G/S
+REWARD/D/G/S
+REWARDINGLY
+REWIND/G/S
+REWORK/D/G/S
+REWOUND
+REWRITE/G/S
+REWRITTEN
+RHETORIC
+RHEUMATISM
+RHEUMATOLOGY
+RHINOCEROS
+RHUBARB
+RHYME/D/G/S
+RHYTHM/M/S
+RHYTHMIC
+RHYTHMICALLY
+RIB/M/S
+RIBBED
+RIBBING
+RIBBON/M/S
+RICE
+RICH/P/T/R/Y/S
+RICHARD/M
+RICK/M
+RICKSHAW/M/S
+RID
+RIDDEN
+RIDDLE/D/G/S
+RIDE/R/Z/G/S
+RIDGE/M/S
+RIDICULE/D/G/S
+RIDICULOUS/P/Y
+RIFLE/D/R/G/S
+RIFLEMAN
+RIFT
+RIG/M/S
+RIGGING
+RIGHT/P/D/R/G/Y/S
+RIGHTEOUS/P/Y
+RIGHTFUL/P/Y
+RIGHTMOST
+RIGHTWARD
+RIGID/Y
+RIGIDITY
+RIGOR/S
+RIGOROUS/Y
+RILL
+RIM/M/S
+RIME
+RIND/M/S
+RING/D/R/Z/G/J/S
+RINGINGLY
+RINSE/D/R/G/S
+RIOT/D/R/Z/G/S
+RIOTOUS
+RIP/N/S
+RIPE/P/Y
+RIPPED
+RIPPING
+RIPPLE/D/G/S
+RISE/R/Z/G/J/S
+RISEN
+RISK/D/G/S
+RITE/M/S
+RITUAL/Y/S
+RIVAL/D/S/G
+RIVALLED
+RIVALLING
+RIVALRY/M/S
+RIVER/M/S
+RIVERSIDE
+RIVET/R/S
+RIVULET/M/S
+ROAD/M/S
+ROADSIDE
+ROADSTER/M/S
+ROADWAY/M/S
+ROAM/D/G/S
+ROAR/D/R/G/S
+ROAST/D/R/G/S
+ROB/S/M
+ROBBED
+ROBBER/M/S
+ROBBERY/M/S
+ROBBING
+ROBE/D/G/S
+ROBERT/M
+ROBIN/M/S
+ROBOT/M/S
+ROBOTIC
+ROBOTICS
+ROBUST/P/Y
+ROCK/D/R/Z/G/S
+ROCKET/D/G/S
+ROCKY/S
+ROD/M/S
+RODE
+ROE
+ROGER/M
+ROGUE/M/S
+ROLE/M/S
+ROLL/D/R/Z/G/S
+ROMAN
+ROMANCE/R/Z/G/S
+ROMANTIC/M/S
+ROMP/D/R/G/S
+ROOF/D/R/G/S
+ROOK
+ROOM/D/R/Z/G/S
+ROOST/R/Z
+ROOT/D/R/M/G/S
+ROPE/D/R/Z/G/S
+ROSE/M/S
+ROSEBUD/M/S
+ROSY/P
+ROT/S
+ROTARY
+ROTATE/D/G/N/X/S
+ROTATOR
+ROTTEN/P
+ROUGE
+ROUGH/P/D/T/R/N/Y
+ROUND/P/D/T/R/G/Y/S
+ROUNDABOUT
+ROUNDEDNESS
+ROUNDOFF
+ROUSE/D/G/S
+ROUT
+ROUTE/D/R/Z/G/J/S
+ROUTINE/Y/S
+ROVE/D/R/G/S
+ROW/D/R/G/S
+ROY/M
+ROYAL/Y
+ROYALIST/M/S
+ROYALTY/M/S
+RUB/X/S
+RUBBED
+RUBBER/M/S
+RUBBING
+RUBBISH
+RUBBLE
+RUBLE/M/S
+RUBOUT
+RUBY/M/S
+RUDDER/M/S
+RUDDY/P
+RUDE/P/Y
+RUDIMENT/M/S
+RUDIMENTARY
+RUE
+RUEFULLY
+RUFFIAN/Y/S
+RUFFLE/D/S
+RUG/M/S
+RUGGED/P/Y
+RUIN/D/G/S
+RUINATION/M/S
+RUINOUS/Y
+RULE/D/R/Z/G/J/S
+RUM/N
+RUMBLE/D/R/G/S
+RUMOR/D/S
+RUMP/Y
+RUMPLE/D
+RUN/S
+RUNAWAY
+RUNG/M/S
+RUNNER/M/S
+RUNNING
+RUNTIME
+RUPTURE/D/G/S
+RURAL/Y
+RUSH/D/R/G/S
+RUSSELL/M
+RUSSET
+RUSSIAN/M/S
+RUST/D/G/S
+RUSTIC
+RUSTICATE/D/G/N/S
+RUSTLE/D/R/Z/G
+RUSTY
+RUT/M/S
+RUTGERS
+RUTH/M
+RUTHLESS/P/Y
+RYE
+SABER/M/S
+SABLE/M/S
+SABOTAGE
+SACK/R/G/S
+SACRED/P/Y
+SACRIFICE/D/R/Z/G/S
+SACRIFICIAL/Y
+SAD/P/Y
+SADDEN/D/S
+SADDER
+SADDEST
+SADDLE/D/S
+SADISM
+SADIST/M/S
+SADISTIC
+SADISTICALLY
+SAFE/P/T/R/Y/S
+SAFEGUARD/D/G/S
+SAFETY/S
+SAG/S
+SAGACIOUS
+SAGACITY
+SAGE/Y/S
+SAID
+SAIL/D/G/S
+SAILOR/Y/S
+SAINT/D/Y/S
+SAKE/S
+SALABLE
+SALAD/M/S
+SALARY/D/S
+SALE/M/S
+SALESMAN
+SALESMEN
+SALIENT
+SALINE
+SALIVA
+SALLOW
+SALLY/G/S
+SALMON
+SALON/M/S
+SALOON/M/S
+SALT/D/R/Z/G/S
+SALTY/P/T/R
+SALUTARY
+SALUTATION/M/S
+SALUTE/D/G/S
+SALVAGE/D/R/G/S
+SALVATION
+SALVE/R/S
+SAM/M
+SAME/P
+SAMPLE/D/R/Z/G/J/S
+SAN
+SANCTIFY/D/N
+SANCTION/D/G/S
+SANCTITY
+SANCTUARY/M/S
+SAND/D/R/Z/G/S
+SANDAL/M/S
+SANDPAPER
+SANDSTONE
+SANDWICH/S
+SANDY
+SANE/T/R/Y
+SANG
+SANGUINE
+SANITARIUM
+SANITARY
+SANITATION
+SANITY
+SANK
+SANTA/M
+SAP/M/S
+SAPLING/M/S
+SAPPHIRE
+SARCASM/M/S
+SARCASTIC
+SASH
+SAT
+SATCHEL/M/S
+SATE/D/G/S
+SATELLITE/M/S
+SATIN
+SATIRE/M/S
+SATISFACTION/M/S
+SATISFACTORILY
+SATISFACTORY
+SATISFIABILITY
+SATISFIABLE
+SATISFY/D/G/S
+SATURATE/D/G/N/S
+SATURDAY/M/S
+SATYR
+SAUCE/R/Z/S
+SAUCEPAN/M/S
+SAUCY
+SAUL/M
+SAUNA
+SAUNTER
+SAUSAGE/M/S
+SAVAGE/P/D/R/Z/G/Y/S
+SAVE/D/R/Z/G/J/S
+SAVIOR/M/S
+SAVOR/D/G/S
+SAVORY
+SAW/D/G/S
+SAWMILL/M/S
+SAWTOOTH
+SAY/R/Z/G/J/S
+SCABBARD/M/S
+SCAFFOLD/G/J/S
+SCALABLE
+SCALAR/M/S
+SCALD/D/G
+SCALE/D/G/J/S
+SCALLOP/D/S
+SCALP/M/S
+SCALY
+SCAMPER/G/S
+SCAN/S
+SCANDAL/M/S
+SCANDALOUS
+SCANNED
+SCANNER/M/S
+SCANNING
+SCANT/Y
+SCANTILY
+SCANTY/P/T/R
+SCAR/M/S
+SCARCE/P/Y
+SCARCITY
+SCARE/D/G/S
+SCARF
+SCARLET
+SCARY
+SCATTER/D/G/S
+SCENARIO/M/S
+SCENE/M/S
+SCENERY
+SCENIC
+SCENT/D/S
+SCEPTER/M/S
+SCHEDULE/D/R/Z/G/S
+SCHEMA/M/S
+SCHEMATA
+SCHEMATIC/S
+SCHEMATICALLY
+SCHEME'S
+SCHEME/D/R/Z/G/S
+SCHENLEY
+SCHIZOPHRENIA
+SCHOLAR/Y/S
+SCHOLARSHIP/M/S
+SCHOLASTIC/S
+SCHOLASTICALLY
+SCHOOL/D/R/Z/G/S
+SCHOOLBOY/M/S
+SCHOOLHOUSE/M/S
+SCHOOLMASTER/M/S
+SCHOOLMATE
+SCHOOLROOM/M/S
+SCHOONER
+SCIENCE/M/S
+SCIENTIFIC
+SCIENTIFICALLY
+SCIENTIST/M/S
+SCISSOR/D/G/S
+SCOFF/D/R/G/S
+SCOLD/D/G/S
+SCOOP/D/G/S
+SCOPE/D/G/S
+SCORCH/D/R/G/S
+SCORE/D/R/Z/G/J/S
+SCORN/D/R/G/S
+SCORNFUL/Y
+SCORPION/M/S
+SCOTLAND
+SCOTT/M
+SCOUNDREL/M/S
+SCOUR/D/G/S
+SCOURGE
+SCOUT/D/G/S
+SCOW
+SCOWL/D/G/S
+SCRAMBLE/D/R/G/S
+SCRAP/M/S
+SCRAPE/D/R/Z/G/J/S
+SCRAPPED
+SCRATCH/D/R/Z/G/S
+SCRATCHPAD/M/S
+SCRAWL/D/G/S
+SCREAM/D/R/Z/G/S
+SCREECH/D/G/S
+SCREEN/D/G/J/S
+SCREW/D/G/S
+SCRIBBLE/D/R/S
+SCRIBE/G/S
+SCRIPT/M/S
+SCRIPTURE/S
+SCROLL/D/G/S
+SCRUB
+SCRUPLE
+SCRUPULOUS/Y
+SCRUTINIZE/D/G
+SCRUTINY
+SCS
+SCUFFLE/D/G/S
+SCULPT/D/S
+SCULPTOR/M/S
+SCULPTURE/D/S
+SCURRY/D
+SCUTTLE/D/G/S
+SCYTHE/M/S
+SEA/Y/S
+SEABOARD
+SEACOAST/M/S
+SEAL/D/R/G/S
+SEALEVEL
+SEAM/D/G/N/S
+SEAMAN
+SEAN/M
+SEAPORT/M/S
+SEAR/D/G/S
+SEARCH/D/R/Z/G/J/S
+SEARCHINGLY
+SEARING/Y
+SEASHORE/M/S
+SEASIDE
+SEASON/D/R/Z/G/J/S
+SEASONABLE
+SEASONABLY
+SEASONAL/Y
+SEAT/D/G/S
+SEAWARD
+SEAWEED
+SECEDE/D/G/S
+SECLUDED
+SECLUSION
+SECOND/D/R/Z/G/Y/S
+SECONDARILY
+SECONDARY
+SECONDHAND
+SECRECY
+SECRET/Y/S
+SECRETARIAL
+SECRETARY/M/S
+SECRETE/D/G/N/X/V/S
+SECRETIVELY
+SECT/M/S
+SECTION/D/G/S
+SECTIONAL
+SECTOR/M/S
+SECULAR
+SECURE/D/G/Y/J/S
+SECURITY/S
+SEDGE
+SEDIMENT/M/S
+SEDUCE/D/R/Z/G/S
+SEDUCTIVE
+SEE/R/Z/S
+SEED/D/R/Z/G/J/S
+SEEDLING/M/S
+SEEING
+SEEK/R/Z/G/S
+SEEM/D/G/Y/S
+SEEMINGLY
+SEEN
+SEEP/D/G/S
+SEETHE/D/G/S
+SEGMENT/D/G/S
+SEGMENTATION/M/S
+SEGREGATE/D/G/N/S
+SEISMIC
+SEIZE/D/G/S
+SEIZURE/M/S
+SELDOM
+SELECT/D/G/V/S
+SELECTABLE
+SELECTION/M/S
+SELECTIVE/Y
+SELECTIVITY
+SELECTOR/M/S
+SELF
+SELFISH/P/Y
+SELFSAME
+SELL/R/Z/G/S
+SELVES
+SEMANTIC/S
+SEMANTICAL/Y
+SEMANTICIST/M/S
+SEMAPHORE/M/S
+SEMBLANCE
+SEMESTER/M/S
+SEMI
+SEMIAUTOMATED
+SEMIAUTOMATIC
+SEMICOLON/M/S
+SEMICONDUCTOR/M/S
+SEMINAL
+SEMINAR/M/S
+SEMINARY/M/S
+SEMIPERMANENT/Y
+SENATE/M/S
+SENATOR/M/S
+SEND/R/Z/G/S
+SENIOR/M/S
+SENIORITY
+SENSATION/M/S
+SENSATIONAL/Y
+SENSE/D/G/S
+SENSELESS/P/Y
+SENSIBILITY/S
+SENSIBLE
+SENSIBLY
+SENSITIVE/P/Y/S
+SENSITIVITY/S
+SENSOR/M/S
+SENSORY
+SENT
+SENTENCE/D/G/S
+SENTENTIAL
+SENTIMENT/M/S
+SENTIMENTAL/Y
+SENTINEL/M/S
+SENTRY/M/S
+SEPARABLE
+SEPARATE/P/D/G/N/X/Y/S
+SEPARATOR/M/S
+SEPTEMBER
+SEPULCHER/M/S
+SEQUEL/M/S
+SEQUENCE/D/R/Z/G/J/S
+SEQUENTIAL/Y
+SEQUENTIALITY
+SEQUENTIALIZE/D/G/S
+SEQUESTER
+SERENDIPITOUS
+SERENDIPITY
+SERENE/Y
+SERENITY
+SERF/M/S
+SERGEANT/M/S
+SERIAL/Y/S
+SERIALIZATION/M/S
+SERIALIZE/D/G/S
+SERIES
+SERIOUS/P/Y
+SERMON/M/S
+SERPENT/M/S
+SERPENTINE
+SERUM/M/S
+SERVANT/M/S
+SERVE/D/R/Z/G/J/S
+SERVICE/D/G/S
+SERVICEABLE
+SERVILE
+SERVITUDE
+SESAME
+SESSION/M/S
+SET/M/S
+SETTER/M/S
+SETTING/S
+SETTLE/D/R/Z/G/S
+SETTLEMENT/M/S
+SETUP/S
+SEVEN/H/S
+SEVENTEEN/H/S
+SEVENTY/H/S
+SEVER/S
+SEVERAL/Y
+SEVERANCE
+SEVERE/D/T/R/G/Y
+SEVERITY/M/S
+SEW/D/R/Z/G/S
+SEX/D/S
+SEXUAL/Y
+SEXUALITY
+SHABBY
+SHACK/D/S
+SHACKLE/D/G/S
+SHADE/D/G/J/S
+SHADILY
+SHADOW/D/G/S
+SHADOWY
+SHADY/P/T/R
+SHAFT/M/S
+SHAGGY
+SHAKABLE
+SHAKABLY
+SHAKE/R/Z/G/S
+SHAKEN
+SHAKY/P
+SHALE
+SHALL
+SHALLOW/P/R/Y
+SHAM/M/S
+SHAMBLES
+SHAME/D/G/S
+SHAMEFUL/Y
+SHAMELESS/Y
+SHAN'T
+SHANGHAI
+SHANTY/M/S
+SHAPE/D/R/Z/G/Y/S
+SHAPELESS/P/Y
+SHARABLE
+SHARE/D/R/Z/G/S
+SHARECROPPER/M/S
+SHAREHOLDER/M/S
+SHARK/M/S
+SHARON/M
+SHARP/P/T/R/N/X/Y
+SHARPENED
+SHARPENING
+SHATTER/D/G/S
+SHAVE/D/G/J/S
+SHAVEN
+SHAWL/M/S
+SHE'LL
+SHE/M
+SHEAF
+SHEAR/D/R/G/S
+SHEATH/G
+SHEATHS
+SHEAVES
+SHED/S
+SHEEP
+SHEER/D
+SHEET/D/G/S
+SHELF
+SHELL/D/R/G/S
+SHELTER/D/G/S
+SHELVE/D/G/S
+SHEPHERD/M/S
+SHERIFF/M/S
+SHIELD/D/G/S
+SHIFT/D/R/Z/G/S
+SHIFTILY
+SHIFTY/P/T/R
+SHILLING/S
+SHIMMER/G
+SHIN
+SHINE/D/R/Z/G/S
+SHINGLE/M/S
+SHININGLY
+SHINY
+SHIP/M/S
+SHIPBOARD
+SHIPBUILDING
+SHIPMENT/M/S
+SHIPPED
+SHIPPER/M/S
+SHIPPING
+SHIPWRECK/D/S
+SHIRK/R/G/S
+SHIRT/G/S
+SHIVER/D/R/G/S
+SHOAL/M/S
+SHOCK/D/R/Z/G/S
+SHOCKINGLY
+SHOD
+SHOE/D/S
+SHOEING
+SHOEMAKER
+SHONE
+SHOOK
+SHOOT/R/Z/G/J/S
+SHOP/M/S
+SHOPKEEPER/M/S
+SHOPPED
+SHOPPER/M/S
+SHOPPING
+SHORE/M/S
+SHORN
+SHORT/P/D/T/R/G/Y/S
+SHORTAGE/M/S
+SHORTCOMING/M/S
+SHORTCUT/M/S
+SHORTEN/D/G/S
+SHORTHAND/D
+SHOT/M/S
+SHOTGUN/M/S
+SHOULD/Z
+SHOULDER/D/G/S
+SHOULDN'T
+SHOUT/D/R/Z/G/S
+SHOVE/D/G/S
+SHOVEL/D/S
+SHOW/D/R/Z/G/J/S
+SHOWER/D/G/S
+SHOWN
+SHRANK
+SHRED/M/S
+SHREW/M/S
+SHREWD/P/T/Y
+SHRIEK/D/G/S
+SHRILL/P/D/G
+SHRILLY
+SHRIMP
+SHRINE/M/S
+SHRINK/G/S
+SHRINKABLE
+SHRIVEL/D
+SHROUD/D
+SHRUB/M/S
+SHRUBBERY
+SHRUG/S
+SHRUNK/N
+SHUDDER/D/G/S
+SHUFFLE/D/G/S
+SHUN/S
+SHUT/S
+SHUTDOWN/M/S
+SHUTTER/D/S
+SHUTTING
+SHUTTLE/D/G/S
+SHY/D/Y/S
+SHYNESS
+SIBLING/M/S
+SICK/T/R/N/Y
+SICKLE
+SICKNESS/M/S
+SIDE/D/G/J/S
+SIDEBOARD/M/S
+SIDEBURN/M/S
+SIDELIGHT/M/S
+SIDEWALK/M/S
+SIDEWAYS
+SIDEWISE
+SIEGE/M/S
+SIEMENS
+SIERRA
+SIEVE/M/S
+SIFT/D/R/G
+SIGH/D/G
+SIGHS
+SIGHT/D/G/Y/J/S
+SIGMA
+SIGN/D/R/Z/G/S
+SIGNAL/D/G/Y/S/R
+SIGNALLED
+SIGNALLER
+SIGNALLING
+SIGNATURE/M/S
+SIGNET
+SIGNIFICANCE
+SIGNIFICANT/Y/S
+SIGNIFY/D/G/N/S
+SIGNOR
+SIKKIM
+SILENCE/D/R/Z/G/S
+SILENT/Y
+SILHOUETTE/D/S
+SILICON
+SILICONE
+SILK/N/S
+SILKILY
+SILKINE
+SILKY/T/R
+SILL/M/S
+SILLY/P/T
+SILT/D/G/S
+SILVER/D/G/S
+SILVERY
+SIMILAR/Y
+SIMILARITY/S
+SIMILITUDE
+SIMMER/D/G/S
+SIMON/M
+SIMPLE/P/T/R
+SIMPLEX
+SIMPLICITY/M/S
+SIMPLIFY/D/R/Z/G/N/X/S
+SIMPLISTIC
+SIMPLY
+SIMULATE/D/G/N/X/S
+SIMULATOR/M/S
+SIMULTANEITY
+SIMULTANEOUS/Y
+SIN/M/S
+SINCE
+SINCERE/T/Y
+SINCERITY
+SINE/S
+SINEW/M/S
+SINFUL/P/Y
+SING/D/R/Z/G/Y/S
+SINGABLE
+SINGAPORE
+SINGINGLY
+SINGLE/P/D/G/S
+SINGLETON/M/S
+SINGULAR/Y
+SINGULARITY/M/S
+SINISTER
+SINK/D/R/Z/G/S
+SINNED
+SINNER/M/S
+SINNING
+SINUSITIS
+SINUSOIDAL
+SINUSOIDS
+SIP/S
+SIR/N/X/S
+SIRE/D/S
+SIRUP
+SISTER/Y/S
+SIT/S
+SITE/D/G/S
+SITTER/M/S
+SITTING/S
+SITUATE/D/G/N/X/S
+SITUATIONAL/Y
+SIX/H/S
+SIXPENCE
+SIXTEEN/H/S
+SIXTY/H/S
+SIZABLE
+SIZE/D/G/J/S
+SKATE/D/R/Z/G/S
+SKELETAL
+SKELETON/M/S
+SKEPTIC/M/S
+SKEPTICAL/Y
+SKETCH/D/G/S
+SKETCHILY
+SKETCHY
+SKEW/D/R/Z/G/S
+SKI/G/S
+SKILL/D/S
+SKILLFUL/P/Y
+SKIM/M/S
+SKIMP/D/G/S
+SKIN/M/S
+SKINNED
+SKINNER/M/S
+SKINNING
+SKIP/S
+SKIPPED
+SKIPPER/M/S
+SKIPPING
+SKIRMISH/D/R/Z/G/S
+SKIRT/D/G/S
+SKULK/D/R/G/S
+SKULL/M/S
+SKUNK/M/S
+SKY/M/S
+SKYLARK/G/S
+SKYLIGHT/M/S
+SKYSCRAPER/M/S
+SLAB
+SLACK/P/R/G/N/Y/S
+SLAIN
+SLAM/S
+SLAMMED
+SLAMMING
+SLANDER/R/S
+SLANG
+SLANT/D/G/S
+SLAP/S
+SLAPPED
+SLAPPING
+SLASH/D/G/S
+SLAT/M/S
+SLATE/D/R/S
+SLAUGHTER/D/G/S
+SLAVE/R/S
+SLAVERY
+SLAY/R/Z/G/S
+SLED/M/S
+SLEDGE/M/S
+SLEEK
+SLEEP/R/Z/G/S
+SLEEPILY
+SLEEPLESS/P/Y
+SLEEPY/P
+SLEET
+SLEEVE/M/S
+SLEIGH
+SLEIGHS
+SLENDER/R
+SLEPT
+SLEW/G
+SLICE/D/R/Z/G/S
+SLICK/R/Z/S
+SLID
+SLIDE/R/Z/G/S
+SLIGHT/P/D/T/R/G/Y/S
+SLIM/Y
+SLIME/D
+SLIMY
+SLING/G/S
+SLIP/M/S
+SLIPPAGE
+SLIPPED
+SLIPPER/M/S
+SLIPPERY/P
+SLIPPING
+SLIT/M/S
+SLOGAN/M/S
+SLOP/S
+SLOPE/D/R/Z/G/S
+SLOPPED
+SLOPPING
+SLOPPY/P
+SLOT/M/S
+SLOTH
+SLOTHS
+SLOTTED
+SLOUCH/D/G/S
+SLOW/P/D/T/R/G/Y/S
+SLUG/S
+SLUGGISH/P/Y
+SLUM/M/S
+SLUMBER/D
+SLUMP/D/S
+SLUNG
+SLUR/M/S
+SLY/Y
+SMACK/D/G/S
+SMALL/P/T/R
+SMALLPOX
+SMALLTALK
+SMART/P/D/T/R/Y
+SMASH/D/R/Z/G/S
+SMASHINGLY
+SMEAR/D/G/S
+SMELL/D/G/S
+SMELLY
+SMELT/R/S
+SMILE/D/G/S
+SMILINGLY
+SMITE
+SMITH
+SMITHS
+SMITHY
+SMITTEN
+SMOCK/G/S
+SMOG
+SMOKABLE
+SMOKE/D/R/Z/G/S
+SMOKY/S
+SMOLDER/D/G/S
+SMOOTH/P/D/T/R/G/Y/S
+SMOTE
+SMOTHER/D/G/S
+SMUGGLE/D/R/Z/G/S
+SNAIL/M/S
+SNAKE/D/S
+SNAP/S
+SNAPPED
+SNAPPER/M/S
+SNAPPILY
+SNAPPING
+SNAPPY
+SNAPSHOT/M/S
+SNARE/D/G/S
+SNARL/D/G
+SNATCH/D/G/S
+SNEAK/D/R/Z/G/S
+SNEAKILY
+SNEAKY/P/T/R
+SNEER/D/G/S
+SNEEZE/D/G/S
+SNIFF/D/G/S
+SNOOP/D/G/S
+SNORE/D/G/S
+SNORT/D/G/S
+SNOUT/M/S
+SNOW/D/G/S
+SNOWILY
+SNOWMAN
+SNOWMEN
+SNOWSHOE/M/S
+SNOWY/T/R
+SNUFF/D/R/G/S
+SNUG/P/Y
+SNUGGLE/D/G/S
+SO
+SOAK/D/G/S
+SOAP/D/G/S
+SOAR/D/G/S
+SOB/R/S
+SOBER/P/D/G/Y/S
+SOCCER
+SOCIABILITY
+SOCIABLE
+SOCIABLY
+SOCIAL/Y
+SOCIALISM
+SOCIALIST/M/S
+SOCIALIZATION
+SOCIALIZE/D/G/S
+SOCIETAL
+SOCIETY/M/S
+SOCIOLOGICAL/Y
+SOCIOLOGY
+SOCK/D/G/S
+SOCKET/M/S
+SOD/M/S
+SODA
+SODIUM
+SODOMY
+SOFA/M/S
+SOFT/P/T/R/X/Y
+SOFTEN/D/G/S
+SOFTWARE/M/S
+SOIL/D/G/S
+SOJOURN/R/Z
+SOLACE/D
+SOLAR
+SOLD/R
+SOLDIER/G/Y/S
+SOLE/Y/S
+SOLEMN/P/Y
+SOLEMNITY
+SOLICIT/D/G/S
+SOLICITOR
+SOLID/P/Y/S
+SOLIDIFY/D/G/N/S
+SOLIDITY
+SOLITAIRE
+SOLITARY
+SOLITUDE/M/S
+SOLO/M/S
+SOLUBILITY
+SOLUBLE
+SOLUTION/M/S
+SOLVABLE
+SOLVE/D/R/Z/G/S
+SOLVENT/M/S
+SOMBER/Y
+SOME
+SOMEBODY
+SOMEDAY
+SOMEHOW
+SOMEONE/M
+SOMETHING
+SOMETIME/S
+SOMEWHAT
+SOMEWHERE
+SON/M/S
+SONAR
+SONG/M/S
+SONNET/M/S
+SOON/T/R
+SOOT
+SOOTH
+SOOTHE/D/R/G/S
+SOPHIE/M
+SOPHISTICATED
+SOPHISTICATION
+SOPHOMORE/M/S
+SORCERER/M/S
+SORCERY
+SORDID/P/Y
+SORE/P/T/R/Y/S
+SORROW/M/S
+SORROWFUL/Y
+SORRY/T/R
+SORT/D/R/Z/G/S
+SOUGHT
+SOUL/M/S
+SOUND/P/D/T/R/Y/S
+SOUNDING/M/S
+SOUP/M/S
+SOUR/P/D/T/R/G/Y/S
+SOURCE/M/S
+SOUTH
+SOUTHERN/R/Z
+SOVEREIGN/M/S
+SOVIET/M/S
+SOY
+SPACE/D/R/Z/G/J/S
+SPACECRAFT/S
+SPACESHIP/M/S
+SPADE/D/G/S
+SPAGHETTI
+SPAIN
+SPAN/M/S
+SPANISH
+SPANK/D/G/S
+SPANKINGLY
+SPANNED
+SPANNER/M/S
+SPANNING
+SPARE/P/D/T/R/G/Y/S
+SPARINGLY
+SPARK/D/G/S
+SPARROW/M/S
+SPARSE/P/T/R/Y
+SPAT
+SPATE/M/S
+SPATIAL/Y
+SPATTER/D
+SPAWN/D/G/S
+SPEAK/R/Z/G/S
+SPEAKABLE
+SPEAR/D/S
+SPECIAL/Y/S
+SPECIALIST/M/S
+SPECIALIZATION/M/S
+SPECIALIZE/D/G/S
+SPECIALTY/M/S
+SPECIES
+SPECIFIABLE
+SPECIFIC/S
+SPECIFICALLY
+SPECIFICITY
+SPECIFY/D/R/Z/G/N/X/S
+SPECIMEN/M/S
+SPECK/M/S
+SPECKLE/D/S
+SPECTACLE/D/S
+SPECTACULAR/Y
+SPECTATOR/M/S
+SPECTER/M/S
+SPECTRA
+SPECTROGRAM/M/S
+SPECTRUM
+SPECULATE/D/G/N/X/V/S
+SPECULATOR/M/S
+SPED
+SPEECH/M/S
+SPEECHLESS/P
+SPEED/D/R/Z/G/S
+SPEEDILY
+SPEEDUP/M/S
+SPEEDY
+SPELL/D/R/Z/G/J/S
+SPENCER
+SPEND/R/Z/G/S
+SPENT
+SPHERE/M/S
+SPHERICAL/Y
+SPICE/D/S
+SPICY/P
+SPIDER/M/S
+SPIKE/D/S
+SPILL/D/R/G/S
+SPIN/S
+SPINACH
+SPINAL/Y
+SPINDLE/G
+SPINE
+SPINNER/M/S
+SPINNING
+SPIRAL/D/G/Y
+SPIRE/M/S
+SPIRIT/D/G/S
+SPIRITEDLY
+SPIRITUAL/Y/S
+SPIT/S
+SPITE/D/G/S
+SPITEFUL/P/Y
+SPITTING
+SPLASH/D/G/S
+SPLEEN
+SPLENDID/Y
+SPLENDOR
+SPLICE/D/R/Z/G/J/S
+SPLINE/M/S
+SPLINTER/D/S
+SPLIT/M/S
+SPLITTER/M/S
+SPLITTING
+SPOIL/D/R/Z/G/S
+SPOKE/D/S
+SPOKEN
+SPOKESMAN
+SPOKESMEN
+SPONGE/D/R/Z/G/S
+SPONSOR/D/G/S
+SPONSORSHIP
+SPONTANEOUS/Y
+SPOOK
+SPOOKY
+SPOOL/D/R/G/S
+SPOON/D/G/S
+SPORE/M/S
+SPORT/D/G/V/S
+SPORTINGLY
+SPORTSMAN
+SPOT/M/S
+SPOTLESS/Y
+SPOTTED
+SPOTTER/M/S
+SPOTTING
+SPOUSE/M/S
+SPOUT/D/G/S
+SPRANG
+SPRAWL/D/G/S
+SPRAY/D/R/G/S
+SPREAD/R/Z/G/J/S
+SPREE/M/S
+SPRIG
+SPRIGHTLY
+SPRING/R/Z/G/S
+SPRINGTIME
+SPRINGY/P/T/R
+SPRINKLE/D/R/G/S
+SPRINT/D/R/Z/G/S
+SPRITE
+SPROUT/D/G
+SPRUCE/D
+SPRUNG
+SPUN
+SPUR/M/S
+SPURIOUS
+SPURN/D/G/S
+SPURT/D/G/S
+SPUTTER/D
+SPY/G/S
+SQUABBLE/D/G/S
+SQUAD/M/S
+SQUADRON/M/S
+SQUALL/M/S
+SQUARE/P/D/T/R/G/Y/S
+SQUASH/D/G
+SQUAT/S
+SQUAWK/D/G/S
+SQUEAK/D/G/S
+SQUEAL/D/G/S
+SQUEEZE/D/R/G/S
+SQUID
+SQUINT/D/G
+SQUIRE/M/S
+SQUIRM/D/S
+SQUIRREL/D/G/S
+SR
+STAB/Y/S
+STABBED
+STABBING
+STABILITY/M/S
+STABILIZE/D/R/Z/G/S
+STABLE/D/R/G/S
+STACK/D/M/G/S
+STAFF/D/R/Z/G/S
+STAG/M/S
+STAGE/D/R/Z/G/S
+STAGECOACH
+STAGGER/D/G/S
+STAGNANT
+STAID
+STAIN/D/G/S
+STAINLESS
+STAIR/M/S
+STAIRCASE/M/S
+STAIRWAY/M/S
+STAKE/D/S
+STALE
+STALK/D/G
+STALL/D/G/J/S
+STALWART/Y
+STAMEN/M/S
+STAMINA
+STAMMER/D/R/G/S
+STAMP/D/R/Z/G/S
+STAMPEDE/D/G/S
+STANCH/T
+STAND/G/J/S
+STANDARD/Y/S
+STANDARDIZATION
+STANDARDIZE/D/G/S
+STANDBY
+STANDPOINT/M/S
+STANDSTILL
+STANFORD
+STANZA/M/S
+STAPLE/R/G/S
+STAR/M/S
+STARBOARD
+STARCH/D
+STARE/D/R/G/S
+STARFISH
+STARK/Y
+STARLIGHT
+STARRED
+STARRING
+STARRY
+START/D/R/Z/G/S
+STARTLE/D/G/S
+STARTUP/M/S
+STARVATION
+STARVE/D/G/S
+STATE/D/M/G/X/Y/S
+STATEMENT/M/S
+STATESMAN
+STATIC
+STATICALLY
+STATION/D/R/G/S
+STATIONARY
+STATISTIC/S
+STATISTICAL/Y
+STATISTICIAN/M/S
+STATUE/M/S
+STATUESQUE/P/Y
+STATURE
+STATUS/S
+STATUTE/M/S
+STATUTORILY
+STATUTORY/P
+STAUNCH/T/Y
+STAVE/D/S
+STAY/D/G/S
+STEAD
+STEADFAST/P/Y
+STEADILY
+STEADY/P/D/T/R/G/S
+STEAK/M/S
+STEAL/R/G/H/S
+STEALTHILY
+STEALTHY
+STEAM/D/R/Z/G/S
+STEAMBOAT/M/S
+STEAMSHIP/M/S
+STEED
+STEEL/D/Z/G/S
+STEEP/P/D/T/R/G/Y/S
+STEEPLE/M/S
+STEER/D/G/S
+STELLAR
+STEM/M/S
+STEMMED
+STEMMING
+STENCH/M/S
+STENCIL/M/S
+STENOGRAPHER/M/S
+STEP/M/S
+STEPHEN/M
+STEPMOTHER/M/S
+STEPPED
+STEPPING
+STEPWISE
+STEREO/M/S
+STEREOGRAPHIC
+STEREOTYPE/D/S
+STEREOTYPICAL
+STERILE
+STERILIZATION/M/S
+STERILIZE/D/R/G/S
+STERLING
+STERN/P/Y/S
+STEVE/M
+STEW/D/S
+STEWARD/M/S
+STICK/G/R/S/Z
+STICKILY
+STICKY/P/T/R
+STIFF/P/T/R/N/X/Y/S
+STIFLE/D/G/S
+STIGMA
+STILE/M/S
+STILL/P/D/T/R/G/S
+STIMULANT/M/S
+STIMULATE/D/G/N/X/V/S
+STIMULI
+STIMULUS
+STING/G/S
+STINK/R/Z/G/S
+STINT
+STIPEND/M/S
+STIPULATE/D/G/N/X/S
+STIR/S
+STIRRED
+STIRRER/M/S
+STIRRING/Y/S
+STIRRUP
+STITCH/D/G/S
+STOCHASTIC
+STOCHASTICALLY
+STOCK/D/R/Z/G/J/S
+STOCKADE/M/S
+STOCKHOLDER/M/S
+STOLE/M/S
+STOLEN
+STOMACH/D/R/G/S
+STONE/D/G/S
+STONY
+STOOD
+STOOL
+STOOP/D/G/S
+STOP/S
+STOPCOCK/S
+STOPPABLE
+STOPPAGE
+STOPPED
+STOPPER/M/S
+STOPPING
+STORAGE/M/S
+STORE/D/G/S
+STOREHOUSE/M/S
+STORK/M/S
+STORM/D/G/S
+STORMY/P/T/R
+STORY/D/S
+STOUT/P/T/R/Y
+STOVE/M/S
+STOW/D
+STRAGGLE/D/R/Z/G/S
+STRAIGHT/P/T/R/N/X
+STRAIGHTFORWARD/P/Y
+STRAIGHTWAY
+STRAIN/D/R/Z/G/S
+STRAIT/N/S
+STRAND/D/G/S
+STRANGE/P/R/Z/Y
+STRANGEST
+STRANGLE/D/R/Z/G/J/S
+STRANGULATION/M/S
+STRAP/M/S
+STRATAGEM/M/S
+STRATEGIC
+STRATEGY/M/S
+STRATIFY/D/N/X/S
+STRATUM
+STRAW/M/S
+STRAWBERRY/M/S
+STRAY/D/S
+STREAK/D/S
+STREAM/D/R/Z/G/S
+STREAMLINE/D/R/G/S
+STREET/Z/S
+STREETCAR/M/S
+STRENGTH/N
+STRENGTHEN/D/R/G/S
+STRENGTHS
+STRENUOUS/Y
+STRESS/D/G/S
+STRETCH/D/R/Z/G/S
+STREW/S
+STREWN
+STRICT/P/T/R/Y
+STRIDE/R/G/S
+STRIFE
+STRIKE/R/Z/G/S
+STRIKINGLY
+STRING'S
+STRING/D/R/Z/G/S
+STRINGENT/Y
+STRINGY/P/T/R
+STRIP/M/S
+STRIPE/D/S
+STRIPPED
+STRIPPER/M/S
+STRIPPING
+STRIVE/G/J/S
+STRODE
+STROKE/D/R/Z/G/S
+STROLL/D/R/G/S
+STRONG/T/R/Y
+STRONGHOLD
+STROVE
+STRUCK
+STRUCTURAL/Y
+STRUCTURE/D/R/G/S
+STRUGGLE/D/G/S
+STRUNG
+STRUT/S
+STUB/M/S
+STUBBLE
+STUBBORN/P/Y
+STUCK
+STUD/M/S
+STUDENT/M/S
+STUDIO/M/S
+STUDIOUS/Y
+STUDY/D/G/S
+STUFF/D/G/S
+STUFFY/T/R
+STUMBLE/D/G/S
+STUMP/D/G/S
+STUN
+STUNG
+STUNNING/Y
+STUNT/M/S
+STUPEFY/G
+STUPENDOUS/Y
+STUPID/T/Y
+STUPIDITY/S
+STUPOR
+STURDY/P
+STYLE/D/R/Z/G/S
+STYLISH/P/Y
+STYLISTIC
+STYLISTICALLY
+STYLIZED
+SUB/S
+SUBATOMIC
+SUBCLASS/M/S
+SUBCOMPONENT/M/S
+SUBCOMPUTATION/M/S
+SUBCONSCIOUS/Y
+SUBCULTURE/M/S
+SUBDIVIDE/D/G/S
+SUBDIVISION/M/S
+SUBDUE/D/G/S
+SUBEXPRESSION/M/S
+SUBFIELD/M/S
+SUBFILE/M/S
+SUBGOAL/M/S
+SUBGRAPH
+SUBGRAPHS
+SUBGROUP/M/S
+SUBINTERVAL/M/S
+SUBJECT/D/G/V/S
+SUBJECTION
+SUBJECTIVELY
+SUBJECTIVITY
+SUBLIMATION/S
+SUBLIME/D
+SUBLIST/M/S
+SUBMARINE/R/Z/S
+SUBMERGE/D/G/S
+SUBMISSION/M/S
+SUBMIT/S
+SUBMITTED
+SUBMITTING
+SUBMODE/S
+SUBMODULE/M/S
+SUBNETWORK/M/S
+SUBORDINATE/D/N/S
+SUBPROBLEM/M/S
+SUBPROGRAM/M/S
+SUBPROJECT
+SUBPROOF/M/S
+SUBRANGE/M/S
+SUBROUTINE/M/S
+SUBSCHEMA/M/S
+SUBSCRIBE/D/R/Z/G/S
+SUBSCRIPT/D/G/S
+SUBSCRIPTION/M/S
+SUBSECTION/M/S
+SUBSEGMENT/M/S
+SUBSEQUENCE/M/S
+SUBSEQUENT/Y
+SUBSET/M/S
+SUBSIDE/D/G/S
+SUBSIDIARY/M/S
+SUBSIDIZE/D/G/S
+SUBSIDY/M/S
+SUBSIST/D/G/S
+SUBSISTENCE
+SUBSPACE/M/S
+SUBSTANCE/M/S
+SUBSTANTIAL/Y
+SUBSTANTIATE/D/G/N/X/S
+SUBSTANTIVE/Y
+SUBSTANTIVITY
+SUBSTITUTABILITY
+SUBSTITUTABLE
+SUBSTITUTE/D/G/N/X/S
+SUBSTRATE/M/S
+SUBSTRING/S
+SUBSTRUCTURE/M/S
+SUBSUME/D/G/S
+SUBSYSTEM/M/S
+SUBTASK/M/S
+SUBTERRANEAN
+SUBTITLE/S
+SUBTLE/P/T/R
+SUBTLETY/S
+SUBTLY
+SUBTRACT/D/G/S/R/Z
+SUBTRACTER'S
+SUBTRACTION/S
+SUBTRAHEND/M/S
+SUBTREE/M/S
+SUBTYPE/S
+SUBUNIT/M/S
+SUBURB/M/S
+SUBURBAN
+SUBVERSION
+SUBVERT/D/R/G/S
+SUBWAY/M/S
+SUCCEED/D/G/S
+SUCCESS/V/S
+SUCCESSFUL/Y
+SUCCESSION/M/S
+SUCCESSIVELY
+SUCCESSOR/M/S
+SUCCINCT/P/Y
+SUCCOR
+SUCCUMB/D/G/S
+SUCH
+SUCK/D/R/Z/G/S
+SUCKLE/G
+SUCTION
+SUDDEN/P/Y
+SUDS/G
+SUE/D/G/S
+SUFFER/D/R/Z/G/J/S
+SUFFERANCE
+SUFFICE/D/G/S
+SUFFICIENCY
+SUFFICIENT/Y
+SUFFIX/D/R/G/S
+SUFFOCATE/D/G/N/S
+SUFFRAGE
+SUGAR/D/G/J/S
+SUGGEST/D/G/V/S
+SUGGESTIBLE
+SUGGESTION/M/S
+SUGGESTIVELY
+SUICIDAL/Y
+SUICIDE/M/S
+SUIT/M/S
+SUITABILITY
+SUITABLE/P
+SUITABLY
+SUITCASE/M/S
+SUITE/D/Z/G/S
+SUITOR/M/S
+SULK/D/G/S
+SULKY/P
+SULLEN/P/Y
+SULPHATE
+SULPHUR/D
+SULPHURIC
+SULTAN/M/S
+SULTRY
+SUM/M/S
+SUMMAND/M/S
+SUMMARIZATION/M/S
+SUMMARIZE/D/G/S
+SUMMARY/M/S
+SUMMATION/M/S
+SUMMED
+SUMMER/M/S
+SUMMING
+SUMMIT
+SUMMON/D/R/Z/G/S
+SUMMONSES
+SUMPTUOUS
+SUN/M/S
+SUNBEAM/M/S
+SUNBURN
+SUNDAY/M/S
+SUNDOWN
+SUNDRY/S
+SUNG
+SUNGLASS/S
+SUNK/N
+SUNLIGHT
+SUNNED
+SUNNING
+SUNNY
+SUNNYVALE
+SUNRISE
+SUNSET
+SUNSHINE
+SUP/R
+SUPERB/Y
+SUPERCLASS/S
+SUPERCOMPUTER/M/S
+SUPERCOMPUTING
+SUPEREGO/M/S
+SUPERFICIAL/Y
+SUPERFLUITY/M/S
+SUPERFLUOUS/Y
+SUPERHUMAN/Y
+SUPERIMPOSE/D/G/S
+SUPERINTEND
+SUPERINTENDENT/M/S
+SUPERIOR/M/S
+SUPERIORITY
+SUPERLATIVE/Y/S
+SUPERMARKET/M/S
+SUPERPOSE/D/G/S
+SUPERSCRIPT/D/G/S
+SUPERSEDE/D/G/S
+SUPERSET/M/S
+SUPERSTITION/M/S
+SUPERSTITIOUS
+SUPERVISE/D/G/N/S
+SUPERVISOR/M/S
+SUPERVISORY
+SUPPER/M/S
+SUPPLANT/D/G/S
+SUPPLE/P
+SUPPLEMENT/D/G/S
+SUPPLEMENTAL
+SUPPLEMENTARY
+SUPPLY/D/R/Z/G/N/S
+SUPPORT/D/R/Z/G/V/S
+SUPPORTABLE
+SUPPORTINGLY
+SUPPORTIVELY
+SUPPOSE/D/G/S
+SUPPOSEDLY
+SUPPOSITION/M/S
+SUPPRESS/D/G/S
+SUPPRESSION
+SUPREMACY
+SUPREME/Y/P
+SURE/P/Y
+SURETY/S
+SURF
+SURFACE/P/D/G/S
+SURGE/D/G/S
+SURGEON/M/S
+SURGERY
+SURGICAL/Y
+SURLY/P
+SURMISE/D/S
+SURMOUNT/D/G/S
+SURNAME/M/S
+SURPASS/D/G/S
+SURPLUS/M/S
+SURPRISE/D/G/S
+SURPRISINGLY
+SURRENDER/D/G/S
+SURROGATE/M/S
+SURROUND/D/G/J/S
+SURVEY/D/G/S
+SURVEYOR/M/S
+SURVIVAL/S
+SURVIVE/D/G/S
+SURVIVOR/M/S
+SUSCEPTIBLE
+SUSPECT/D/G/S
+SUSPEND/D/G/S
+SUSPENDER/M/S
+SUSPENSE/N/X/S
+SUSPICION/M/S
+SUSPICIOUS/Y
+SUSTAIN/D/G/S
+SUTURE/S
+SUZANNE/M
+SWAGGER/D/G
+SWAIN/M/S
+SWALLOW/D/G/S
+SWAM
+SWAMP/D/G/S
+SWAMPY
+SWAN/M/S
+SWAP/S
+SWAPPED
+SWAPPING
+SWARM/D/G/S
+SWARTHY
+SWATTED
+SWAY/D/G
+SWEAR/R/G/S
+SWEAT/D/R/Z/G/S
+SWEEP/R/Z/G/J/S
+SWEET/P/T/R/X/Y/S
+SWEETEN/D/R/Z/G/J/S
+SWEETHEART/M/S
+SWELL/D/G/J/S
+SWEPT
+SWERVE/D/G/S
+SWIFT/P/T/R/Y
+SWIM/S
+SWIMMER/M/S
+SWIMMING/Y
+SWINE
+SWING/R/Z/G/S
+SWIRL/D/G
+SWISH/D
+SWITCH/D/R/Z/G/J/S
+SWITCHBOARD/M/S
+SWITZERLAND
+SWOLLEN
+SWOON
+SWOOP/D/G/S
+SWORD/M/S
+SWORE
+SWORN
+SWUM
+SWUNG
+SYCAMORE
+SYLLABI
+SYLLABLE/M/S
+SYLLABUS
+SYLLOGISM/M/S
+SYMBIOSIS
+SYMBIOTIC
+SYMBOL/M/S
+SYMBOLIC
+SYMBOLICALLY
+SYMBOLISM
+SYMBOLIZATION
+SYMBOLIZE/D/G/S
+SYMMETRIC
+SYMMETRICAL/Y
+SYMMETRY/M/S
+SYMPATHETIC
+SYMPATHIZE/D/R/Z/G/S
+SYMPATHIZINGLY
+SYMPATHY/M/S
+SYMPHONY/M/S
+SYMPOSIUM/S
+SYMPTOM/M/S
+SYMPTOMATIC
+SYNAPSE/M/S
+SYNCHRONIZATION
+SYNCHRONIZE/D/R/Z/G/S
+SYNCHRONOUS/Y
+SYNCHRONY
+SYNDICATE/D/N/S
+SYNDROME/M/S
+SYNERGISM
+SYNERGISTIC
+SYNONYM/M/S
+SYNONYMOUS/Y
+SYNOPSES
+SYNOPSIS
+SYNTACTIC
+SYNTACTICAL/Y
+SYNTAX
+SYNTHESIS
+SYNTHESIZE/D/R/Z/G/S
+SYNTHETIC/S
+SYRACUSE
+SYRINGE/S
+SYRUP
+SYSTEM/M/S
+SYSTEMATIC
+SYSTEMATICALLY
+SYSTEMATIZE/D/G/S
+SYSTOLIC
+TAB/S
+TABERNACLE/M/S
+TABLE/D/G/S
+TABLEAU/M/S
+TABLECLOTH
+TABLECLOTHS
+TABLESPOON/M/S
+TABLESPOONFUL/M/S
+TABLET/M/S
+TABOO/M/S
+TABULAR
+TABULATE/D/G/N/X/S
+TABULATOR/M/S
+TACHOMETER/M/S
+TACIT/Y
+TACK/D/G
+TACKLE/M/S
+TACT
+TACTICS
+TACTILE
+TAG/M/S
+TAGGED
+TAGGING
+TAIL/D/G/S
+TAILOR/D/G/S
+TAINT/D
+TAIWAN
+TAKE/R/Z/G/J/S
+TAKEN
+TALE/M/S
+TALENT/D/S
+TALK/D/R/Z/G/S
+TALKATIVE/P/Y
+TALKIE
+TALL/P/T/R
+TALLOW
+TAME/P/D/R/G/Y/S
+TAMPER/D/G/S
+TAN
+TANDEM
+TANG
+TANGENT/M/S
+TANGENTIAL
+TANGIBLE
+TANGIBLY
+TANGLE/D
+TANGY
+TANK/R/Z/S
+TANNER/M/S
+TANTALIZING/Y
+TANTAMOUNT
+TANTRUM/M/S
+TAP/M/S
+TAPE/D/R/Z/G/J/S
+TAPERED
+TAPERING
+TAPESTRY/M/S
+TAPPED
+TAPPER/M/S
+TAPPING
+TAPROOT/M/S
+TAR
+TARDY/P
+TARGET/D/G/S
+TARIFF/M/S
+TARRY
+TART/P/Y
+TASK/D/G/S
+TASSEL/M/S
+TASTE/D/R/Z/G/S
+TASTEFUL/P/Y
+TASTELESS/Y
+TASTY
+TATTER/D
+TATTOO/D/S
+TAU
+TAUGHT
+TAUNT/D/R/G/S
+TAUT/P/Y
+TAUTOLOGICAL/Y
+TAUTOLOGY/M/S
+TAVERN/M/S
+TAWNY
+TAX/D/G/S
+TAXABLE
+TAXATION
+TAXI/D/G/S
+TAXICAB/M/S
+TAXONOMIC
+TAXONOMICALLY
+TAXONOMY
+TAXPAYER/M/S
+TEA/S
+TEACH/R/Z/G/J/S
+TEACHABLE
+TEACHER'S
+TEAHOUSE
+TEAM/D/G/S
+TEAR/D/G/S
+TEARFUL/Y
+TEASE/D/G/S
+TEASPOON/M/S
+TEASPOONFUL/M/S
+TECHNICAL/Y
+TECHNICALITY/M/S
+TECHNICIAN/M/S
+TECHNIQUE/M/S
+TECHNOLOGICAL/Y
+TECHNOLOGIST/M/S
+TECHNOLOGY/S
+TEDDY/M
+TEDIOUS/P/Y
+TEDIUM
+TEEM/D/G/S
+TEEN/S
+TEENAGE/D/R/Z
+TEETH
+TEETHE/D/G/S
+TEFLON
+TELECOMMUNICATION/S
+TELEGRAM/M/S
+TELEGRAPH/D/R/Z/G
+TELEGRAPHIC
+TELEGRAPHS
+TELEOLOGICAL/Y
+TELEOLOGY
+TELEPHONE/D/R/Z/G/S
+TELEPHONIC
+TELEPHONY
+TELESCOPE/D/G/S
+TELETYPE/M/S
+TELEVISE/D/G/N/X/S
+TELEVISOR/M/S
+TELL/R/Z/G/S
+TEMPER/D/G/S
+TEMPERAMENT/S
+TEMPERAMENTAL
+TEMPERANCE
+TEMPERATE/P/Y
+TEMPERATURE/M/S
+TEMPEST
+TEMPESTUOUS/Y
+TEMPLATE/M/S
+TEMPLE/M/S
+TEMPORAL/Y
+TEMPORARILY
+TEMPORARY/S
+TEMPT/D/R/Z/G/S
+TEMPTATION/M/S
+TEMPTINGLY
+TEN/H/S
+TENACIOUS/Y
+TENANT/M/S
+TEND/D/R/Z/G/S
+TENDENCY/S
+TENDERLY
+TENDERNESS
+TENEMENT/M/S
+TENNESSEE
+TENNIS
+TENOR/M/S
+TENSE/P/D/T/R/G/N/X/Y/S
+TENSOR
+TENT/D/G/S
+TENTACLE/D/S
+TENTATIVE/Y
+TENURE
+TERM/D/G/S
+TERMINAL/M/Y/S
+TERMINATE/D/G/N/X/S
+TERMINATOR/M/S
+TERMINOLOGY/S
+TERMINUS
+TERMWISE
+TERNARY
+TERRACE/D/S
+TERRAIN/M/S
+TERRESTRIAL
+TERRIBLE
+TERRIBLY
+TERRIER/M/S
+TERRIFIC
+TERRIFY/D/G/S
+TERRITORIAL
+TERRITORY/M/S
+TERROR/M/S
+TERRORISM
+TERRORIST/M/S
+TERRORISTIC
+TERRORIZE/D/G/S
+TERSE
+TERTIARY
+TEST/D/R/Z/G/J/S
+TESTABILITY
+TESTABLE
+TESTAMENT/M/S
+TESTICLE/M/S
+TESTIFY/D/R/Z/G/S
+TESTIMONY/M/S
+TEXAS
+TEXT/M/S
+TEXTBOOK/M/S
+TEXTILE/M/S
+TEXTUAL/Y
+TEXTURE/D/S
+THAN
+THANK/D/G/S
+THANKFUL/P/Y
+THANKLESS/P/Y
+THANKSGIVING
+THAT/M/S
+THATCH/S
+THAW/D/G/S
+THE/G/J
+THEATER/M/S
+THEATRICAL/Y/S
+THEFT/M/S
+THEIR/S
+THEM
+THEMATIC
+THEME/M/S
+THEMSELVES
+THEN
+THENCE
+THENCEFORTH
+THEOLOGICAL
+THEOLOGY
+THEOREM/M/S
+THEORETIC
+THEORETICAL/Y
+THEORETICIANS
+THEORIST/M/S
+THEORIZATION/M/S
+THEORIZE/D/R/Z/G/S
+THEORY/M/S
+THERAPEUTIC
+THERAPIST/M/S
+THERAPY/M/S
+THERE/M
+THEREABOUTS
+THEREAFTER
+THEREBY
+THEREFORE
+THEREIN
+THEREOF
+THEREON
+THERETO
+THEREUPON
+THEREWITH
+THERMAL
+THERMODYNAMIC/S
+THERMOMETER/M/S
+THERMOSTAT/M/S
+THESAURI
+THESE/S
+THESIS
+THETA
+THEY
+THEY'D
+THEY'LL
+THEY'RE
+THEY'VE
+THICK/P/T/R/N/X/Y
+THICKET/M/S
+THIEF
+THIEVE/G/S
+THIGH
+THIGHS
+THIMBLE/M/S
+THIN/P/Y
+THINK/R/Z/G/S
+THINKABLE
+THINKABLY
+THINNER
+THINNEST
+THIRD/Y/S
+THIRST/D/S
+THIRSTY
+THIRTEEN/H/S
+THIRTY/H/S
+THIS
+THISTLE
+THOMAS
+THOMPSON/M
+THONG
+THORN/M/S
+THORNY
+THOROUGH/P/Y
+THOROUGHFARE/M/S
+THOSE
+THOUGH
+THOUGHT/M/S
+THOUGHTFUL/P/Y
+THOUGHTLESS/P/Y
+THOUSAND/H/S
+THRASH/D/R/G/S
+THREAD/D/R/Z/G/S
+THREAT/N/S
+THREATEN/D/G/S
+THREE/M/S
+THREESCORE
+THRESHOLD/M/S
+THREW
+THRICE
+THRIFT
+THRIFTY
+THRILL/D/R/Z/G/S
+THRILLING/Y
+THRIVE/D/G/S
+THROAT/D/S
+THROB/S
+THROBBED
+THROBBING
+THRONE/M/S
+THRONG/M/S
+THROTTLE/D/G/S
+THROUGH
+THROUGHOUT
+THROUGHPUT
+THROW/R/G/S
+THROWN
+THRUSH
+THRUST/R/Z/G/S
+THUD/S
+THUG/M/S
+THUMB/D/G/S
+THUMP/D/G
+THUNDER/D/R/Z/G/S
+THUNDERBOLT/M/S
+THUNDERSTORM/M/S
+THURSDAY/M/S
+THUS/Y
+THWART/D/G
+THYSELF
+TICK/D/R/Z/G/S
+TICKET/M/S
+TICKLE/D/G/S
+TIDAL/Y
+TIDE/D/G/J/S
+TIDY/P/D/G
+TIE/D/R/Z/S
+TIGER/M/S
+TIGHT/P/T/R/X/Y
+TIGHTEN/D/R/Z/G/J/S
+TILDE
+TILE/D/G/S
+TILL/D/R/Z/G/S
+TILLABLE
+TILT/D/G/S
+TIMBER/D/G/S
+TIME/D/R/Z/G/Y/J/S
+TIMESHARING
+TIMETABLE/M/S
+TIMID/Y
+TIMIDITY
+TIN/M/S
+TINGE/D
+TINGLE/D/G/S
+TINILY
+TINKER/D/G/S
+TINKLE/D/G/S
+TINNILY
+TINNY/P/T/R
+TINT/D/G/S
+TINY/P/T/R
+TIP/M/S
+TIPPED
+TIPPER/M/S
+TIPPING
+TIPTOE
+TIRE/D/G/S
+TIREDLY
+TIRELESS/P/Y
+TIRESOME/P/Y
+TISSUE/M/S
+TIT/R/Z/S
+TITHE/R/S
+TITLE/D/S
+TO
+TOAD/M/S
+TOAST/D/R/G/S
+TOBACCO
+TODAY
+TOE/M/S
+TOFU
+TOGETHER/P
+TOGGLE/D/G/S
+TOIL/D/R/G/S
+TOILET/M/S
+TOKEN/M/S
+TOLD
+TOLERABILITY
+TOLERABLE
+TOLERABLY
+TOLERANCE/S
+TOLERANT/Y
+TOLERATE/D/G/N/S
+TOLL/D/S
+TOM/M
+TOMAHAWK/M/S
+TOMATO
+TOMATOES
+TOMB/M/S
+TOMOGRAPHY
+TOMORROW
+TON/M/S
+TONAL
+TONE/D/R/G/S
+TONGS
+TONGUE/D/S
+TONIC/M/S
+TONIGHT
+TONNAGE
+TONSIL
+TOO/H
+TOOK
+TOOL/D/R/Z/G/S
+TOOLKIT/S
+TOOTHBRUSH/M/S
+TOOTHPICK/M/S
+TOP/R/S
+TOPIC/M/S
+TOPICAL/Y
+TOPMOST
+TOPOGRAPHIC
+TOPOGRAPHICAL
+TOPOLOGIC
+TOPOLOGICAL
+TOPOLOGY/S
+TOPPLE/D/G/S
+TORCH/M/S
+TORE
+TORMENT/D/R/Z/G
+TORN
+TORNADO/S
+TORNADOES
+TORPEDO/S
+TORPEDOES
+TORQUE
+TORRENT/M/S
+TORRID
+TORTOISE/M/S
+TORTURE/D/R/Z/G/S
+TORUS/M/S
+TOSS/D/G/S
+TOTAL/D/G/Y/S/R/Z/M
+TOTALER'S
+TOTALITY/M/S
+TOTALLED
+TOTALLER/S/M
+TOTALLING
+TOTTER/D/G/S
+TOUCH/D/G/S
+TOUCHABLE
+TOUCHILY
+TOUCHINGLY
+TOUCHY/P/T/R
+TOUGH/P/T/R/N/Y
+TOUR/D/G/S
+TOURETZKY/M
+TOURISM
+TOURIST/M/S
+TOURNAMENT/M/S
+TOW/D/Z
+TOWARD/S
+TOWEL/G/S/D/M
+TOWELLED
+TOWELLING
+TOWER/D/G/S
+TOWN/M/S
+TOWNSHIP/M/S
+TOY/D/G/S
+TRACE/D/R/Z/G/J/S
+TRACEABLE
+TRACK/D/R/Z/G/S
+TRACT/M/V/S
+TRACTABILITY
+TRACTABLE
+TRACTOR/M/S
+TRADE/D/R/Z/G/S
+TRADEMARK/M/S
+TRADESMAN
+TRADITION/M/S
+TRADITIONAL/Y
+TRAFFIC/M/S
+TRAFFICKED
+TRAFFICKER/M/S
+TRAFFICKING
+TRAGEDY/M/S
+TRAGIC
+TRAGICALLY
+TRAIL/D/R/Z/G/J/S
+TRAIN/D/R/Z/G/S
+TRAINABLE
+TRAINEE/M/S
+TRAIT/M/S
+TRAITOR/M/S
+TRAJECTORY/M/S
+TRAMP/D/G/S
+TRAMPLE/D/R/G/S
+TRANCE/M/S
+TRANQUIL/Y
+TRANQUILITY
+TRANQUILLITY
+TRANSACT
+TRANSACTION/M/S
+TRANSCEND/D/G/S
+TRANSCENDENT
+TRANSCONTINENTAL
+TRANSCRIBE/D/R/Z/G/S
+TRANSCRIPT/M/S
+TRANSCRIPTION/M/S
+TRANSFER/M/S/D/G
+TRANSFERABLE
+TRANSFERAL/M/S
+TRANSFERRAL/M/S
+TRANSFERRED
+TRANSFERRER/M/S
+TRANSFERRING
+TRANSFINITE
+TRANSFORM/D/G/S
+TRANSFORMABLE
+TRANSFORMATION/M/S
+TRANSFORMATIONAL
+TRANSGRESS/D
+TRANSGRESSION/M/S
+TRANSIENT/Y/S
+TRANSISTOR/M/S
+TRANSIT
+TRANSITION/D/S
+TRANSITIONAL
+TRANSITIVE/P/Y
+TRANSITIVITY
+TRANSITORY
+TRANSLATABILITY
+TRANSLATABLE
+TRANSLATE/D/G/N/X/S
+TRANSLATIONAL
+TRANSLATOR/M/S
+TRANSLITERATE/N/D/G
+TRANSLUCENT
+TRANSMISSION/M/S
+TRANSMIT/S
+TRANSMITTAL
+TRANSMITTED
+TRANSMITTER/M/S
+TRANSMITTING
+TRANSMOGRIFY/N
+TRANSPARENCY/M/S
+TRANSPARENT/Y
+TRANSPIRE/D/G/S
+TRANSPLANT/D/G/S
+TRANSPORT/D/R/Z/G/S
+TRANSPORTABILITY
+TRANSPORTATION
+TRANSPOSE/D/G/S
+TRANSPOSITION
+TRAP/M/S
+TRAPEZOID/M/S
+TRAPEZOIDAL
+TRAPPED
+TRAPPER/M/S
+TRAPPING/S
+TRASH
+TRAUMA
+TRAUMATIC
+TRAVAIL
+TRAVEL/D/R/Z/G/J/S
+TRAVERSAL/M/S
+TRAVERSE/D/G/S
+TRAVESTY/M/S
+TRAY/M/S
+TREACHEROUS/Y
+TREACHERY/M/S
+TREAD/G/S
+TREASON
+TREASURE/D/R/G/S
+TREASURY/M/S
+TREAT/D/G/S
+TREATISE/M/S
+TREATMENT/M/S
+TREATY/M/S
+TREBLE
+TREE/M/S
+TREETOP/M/S
+TREK/M/S
+TREMBLE/D/G/S
+TREMENDOUS/Y
+TREMOR/M/S
+TRENCH/R/S
+TREND/G/S
+TRESPASS/D/R/Z/S
+TRESS/M/S
+TRIAL/M/S
+TRIANGLE/M/S
+TRIANGULAR/Y
+TRIBAL
+TRIBE/M/S
+TRIBUNAL/M/S
+TRIBUNE/M/S
+TRIBUTARY
+TRIBUTE/M/S
+TRICHOTOMY
+TRICK/D/G/S
+TRICKLE/D/G/S
+TRICKY/P/T/R
+TRIFLE/R/G/S
+TRIGGER/D/G/S
+TRIGONOMETRIC
+TRIGONOMETRY
+TRIHEDRAL
+TRILL/D
+TRILLION/H/S
+TRIM/P/Y/S
+TRIMMED
+TRIMMER
+TRIMMEST
+TRIMMING/S
+TRINKET/M/S
+TRIP/M/S
+TRIPLE/D/G/S
+TRIPLET/M/S
+TRIUMPH/D/G
+TRIUMPHAL
+TRIUMPHANTLY
+TRIUMPHS
+TRIVIA
+TRIVIAL/Y
+TRIVIALITY/S
+TROD
+TROLL/M/S
+TROLLEY/M/S
+TROOP/R/Z/S
+TROPHY/M/S
+TROPIC/M/S
+TROPICAL
+TROT/S
+TROUBLE/D/G/S
+TROUBLEMAKER/M/S
+TROUBLESHOOT/R/Z/G/S
+TROUBLESOME/Y
+TROUGH
+TROUSER/S
+TROUT
+TROWEL/M/S
+TRUANT/M/S
+TRUCE
+TRUCK/D/R/Z/G/S
+TRUDGE/D
+TRUE/D/T/R/G/S
+TRUISM/M/S
+TRULY
+TRUMP/D/S
+TRUMPET/R
+TRUNCATE/D/G/S
+TRUNCATION/M/S
+TRUNK/M/S
+TRUST/D/G/S
+TRUSTEE/M/S
+TRUSTFUL/P/Y
+TRUSTINGLY
+TRUSTWORTHY/P
+TRUSTY
+TRUTH
+TRUTHFUL/P/Y
+TRUTHS
+TRY/D/R/Z/G/S
+TUB/M/S
+TUBE/R/Z/G/S
+TUBERCULOSIS
+TUCK/D/R/G/S
+TUESDAY/M/S
+TUFT/M/S
+TUG/S
+TUITION
+TULIP/M/S
+TUMBLE/D/R/Z/G/S
+TUMOR/S
+TUMULT/M/S
+TUMULTUOUS
+TUNABLE
+TUNE/D/R/Z/G/S
+TUNIC/M/S
+TUNNEL/D/S
+TUPLE/M/S
+TURBAN/M/S
+TURBO
+TURBULENT/Y
+TURF
+TURING
+TURKEY/M/S
+TURMOIL/M/S
+TURN/D/R/Z/G/J/S
+TURNABLE
+TURNIP/M/S
+TURNOVER
+TURPENTINE
+TURQUOISE
+TURRET/M/S
+TURTLE/M/S
+TUTOR/D/G/S
+TUTORIAL/M/S
+TV
+TWAIN
+TWANG
+TWAS
+TWEED
+TWELFTH
+TWELVE/S
+TWENTY/H/S
+TWICE
+TWIG/M/S
+TWILIGHT/M/S
+TWILL
+TWIN/M/S
+TWINE/D/R
+TWINKLE/D/R/G/S
+TWIRL/D/R/G/S
+TWIST/D/R/Z/G/S
+TWITCH/D/G
+TWITTER/D/G
+TWO/M/S
+TWOFOLD
+TYING
+TYPE/D/M/G/S
+TYPECHECK/G/S/R
+TYPEOUT
+TYPESCRIPT/S
+TYPEWRITER/M/S
+TYPHOID
+TYPICAL/P/Y
+TYPIFY/D/G/S
+TYPIST/M/S
+TYPOGRAPHICAL/Y
+TYPOGRAPHY
+TYRANNY
+TYRANT/M/S
+UBIQUITOUS/Y
+UBIQUITY
+UGH
+UGLY/P/T/R
+UIMS
+ULCER/M/S
+ULTIMATE/Y
+UMBRELLA/M/S
+UMPIRE/M/S
+UNABATED
+UNABBREVIATED
+UNABLE
+UNACCEPTABILITY
+UNACCEPTABLE
+UNACCEPTABLY
+UNACCUSTOMED
+UNACKNOWLEDGED
+UNADULTERATED
+UNAESTHETICALLY
+UNAFFECTED/P/Y
+UNAIDED
+UNALIENABILITY
+UNALIENABLE
+UNALTERABLY
+UNALTERED
+UNAMBIGUOUS/Y
+UNAMBITIOUS
+UNANALYZABLE
+UNANIMOUS/Y
+UNANSWERED
+UNANTICIPATED
+UNARMED
+UNARY
+UNASSAILABLE
+UNASSIGNED
+UNATTAINABILITY
+UNATTAINABLE
+UNATTENDED
+UNATTRACTIVE/Y
+UNAUTHORIZED
+UNAVAILABILITY
+UNAVAILABLE
+UNAVOIDABLE
+UNAVOIDABLY
+UNAWARE/P/S
+UNBALANCED
+UNBEARABLE
+UNBELIEVABLE
+UNBIASED
+UNBLOCK/D/G/S
+UNBORN
+UNBOUND/D
+UNBREAKABLE
+UNBROKEN
+UNBUFFERED
+UNCANCELED
+UNCANCELLED
+UNCANNY
+UNCAPITALIZED
+UNCAUGHT
+UNCERTAIN/Y
+UNCERTAINTY/S
+UNCHANGEABLE
+UNCHANGED
+UNCHANGING
+UNCHARTED
+UNCLAIMED
+UNCLE/M/S
+UNCLEAN/P/Y
+UNCLEAR/D
+UNCLOSED
+UNCOMFORTABLE
+UNCOMFORTABLY
+UNCOMMITTED
+UNCOMMON/Y
+UNCOMPROMISING
+UNCOMPUTABLE
+UNCONCERNED/Y
+UNCONDITIONAL/Y
+UNCONNECTED
+UNCONSCIOUS/P/Y
+UNCONSTRAINED
+UNCONTROLLABILITY
+UNCONTROLLABLE
+UNCONTROLLABLY
+UNCONTROLLED
+UNCONVENTIONAL/Y
+UNCONVINCED
+UNCONVINCING
+UNCORRECTABLE
+UNCORRECTED
+UNCOUNTABLE
+UNCOUNTABLY
+UNCOUTH
+UNCOVER/D/G/S
+UNDAUNTED/Y
+UNDECIDABLE
+UNDECIDED
+UNDECLARED
+UNDECOMPOSABLE
+UNDEFINABILITY
+UNDEFINED
+UNDELETE
+UNDELETED
+UNDENIABLY
+UNDER
+UNDERBRUSH
+UNDERDONE
+UNDERESTIMATE/D/G/N/S
+UNDERFLOW/D/G/S
+UNDERFOOT
+UNDERGO/G
+UNDERGOES
+UNDERGONE
+UNDERGRADUATE/M/S
+UNDERGROUND
+UNDERLIE/S
+UNDERLINE/D/G/J/S
+UNDERLING/M/S
+UNDERLYING
+UNDERMINE/D/G/S
+UNDERNEATH
+UNDERPINNING/S
+UNDERPLAY/D/G/S
+UNDERSCORE/D/S
+UNDERSTAND/G/J/S
+UNDERSTANDABILITY
+UNDERSTANDABLE
+UNDERSTANDABLY
+UNDERSTANDINGLY
+UNDERSTATED
+UNDERSTOOD
+UNDERTAKE/R/Z/G/J/S
+UNDERTAKEN
+UNDERTOOK
+UNDERWAY
+UNDERWEAR
+UNDERWENT
+UNDERWORLD
+UNDERWRITE/R/Z/G/S
+UNDESIRABILITY
+UNDESIRABLE
+UNDETECTABLE
+UNDETECTED
+UNDETERMINED
+UNDEVELOPED
+UNDID
+UNDIRECTED
+UNDISCIPLINED
+UNDISCOVERED
+UNDISTORTED
+UNDISTURBED
+UNDIVIDED
+UNDO/G/J
+UNDOCUMENTED
+UNDOES
+UNDONE
+UNDOUBTEDLY
+UNDRESS/D/G/S
+UNDUE
+UNDULY
+UNEASILY
+UNEASY/P
+UNECONOMICAL
+UNEMBELLISHED
+UNEMPLOYED
+UNEMPLOYMENT
+UNENDING
+UNENLIGHTENING
+UNEQUAL/D/Y
+UNEQUIVOCAL/Y
+UNESSENTIAL
+UNEVALUATED
+UNEVEN/P/Y
+UNEVENTFUL
+UNEXCUSED
+UNEXPANDED
+UNEXPECTED/Y
+UNEXPLAINED
+UNEXPLORED
+UNEXTENDED
+UNFAIR/P/Y
+UNFAITHFUL/P/Y
+UNFAMILIAR/Y
+UNFAMILIARITY
+UNFAVORABLE
+UNFETTERED
+UNFINISHED
+UNFIT/P
+UNFLAGGING
+UNFOLD/D/G/S
+UNFORESEEN
+UNFORGEABLE
+UNFORGIVING
+UNFORMATTED
+UNFORTUNATE/Y/S
+UNFOUNDED
+UNFRIENDLY/P
+UNFULFILLED
+UNGRAMMATICAL
+UNGRATEFUL/P/Y
+UNGROUNDED
+UNGUARDED
+UNGUIDED
+UNHAPPILY
+UNHAPPY/P/T/R
+UNHEALTHY
+UNHEEDED
+UNICORN/M/S
+UNIDENTIFIED
+UNIDIRECTIONAL/Y
+UNIDIRECTIONALITY
+UNIFORM/D/Y/S
+UNIFORMITY
+UNIFY/D/R/Z/G/N/X/S
+UNILATERAL
+UNILLUMINATING
+UNIMAGINABLE
+UNIMPEDED
+UNIMPLEMENTED
+UNIMPORTANT
+UNINDENTED
+UNINFORMED
+UNINITIALIZED
+UNINTELLIGIBLE
+UNINTENDED
+UNINTENTIONAL/Y
+UNINTERESTING/Y
+UNINTERPRETED
+UNINTERRUPTED/Y
+UNION/M/S
+UNIONIZATION
+UNIONIZE/D/R/Z/G/S
+UNIQUE/P/Y
+UNISON
+UNIT/M/S
+UNITE/D/G/S
+UNITY/M/S
+UNIVALVE/M/S
+UNIVERSAL/Y/S
+UNIVERSALITY
+UNIVERSE/M/S
+UNIVERSITY/M/S
+UNIX
+UNJUST/Y
+UNJUSTIFIED
+UNKIND/P/Y
+UNKNOWABLE
+UNKNOWING/Y
+UNKNOWN/S
+UNLABELED
+UNLAWFUL/Y
+UNLEASH/D/G/S
+UNLESS
+UNLIKE/P/Y
+UNLIMITED
+UNLINK/D/G/S
+UNLOAD/D/G/S
+UNLOCK/D/G/S
+UNLUCKY
+UNMANAGEABLE
+UNMANAGEABLY
+UNMANNED
+UNMARKED
+UNMARRIED
+UNMASKED
+UNMATCHED
+UNMISTAKABLE
+UNMODIFIED
+UNMOVED
+UNNAMED
+UNNATURAL/P/Y
+UNNECESSARILY
+UNNECESSARY
+UNNEEDED
+UNNOTICED
+UNOBSERVABLE
+UNOBSERVED
+UNOBTAINABLE
+UNOCCUPIED
+UNOFFICIAL/Y
+UNOPENED
+UNOPTIMIZED
+UNORDERED
+UNPACK/D/G/S
+UNPARALLELED
+UNPARSED
+UNPLANNED
+UNPLEASANT/P/Y
+UNPOPULAR
+UNPOPULARITY
+UNPRECEDENTED
+UNPREDICTABLE
+UNPRESCRIBED
+UNPRESERVED
+UNPRIMED
+UNPROFITABLE
+UNPROJECTED
+UNPROTECTED
+UNPROVABILITY
+UNPROVABLE
+UNPROVEN
+UNPUBLISHED
+UNQUALIFIED/Y
+UNQUESTIONABLY
+UNQUESTIONED
+UNQUOTED
+UNRAVEL/D/G/S
+UNREACHABLE
+UNREADABLE
+UNREAL
+UNREALISTIC
+UNREALISTICALLY
+UNREASONABLE/P
+UNREASONABLY
+UNRECOGNIZABLE
+UNRECOGNIZED
+UNRELATED
+UNRELIABILITY
+UNRELIABLE
+UNREPORTED
+UNREPRESENTABLE
+UNRESOLVED
+UNRESPONSIVE
+UNREST
+UNRESTRAINED
+UNRESTRICTED/Y
+UNRESTRICTIVE
+UNROLL/D/G/S
+UNRULY
+UNSAFE/Y
+UNSANITARY
+UNSATISFACTORY
+UNSATISFIABILITY
+UNSATISFIABLE
+UNSATISFIED
+UNSATISFYING
+UNSCRUPULOUS
+UNSEEDED
+UNSEEN
+UNSELECTED
+UNSELFISH/P/Y
+UNSENT
+UNSETTLED
+UNSETTLING
+UNSHAKEN
+UNSHARED
+UNSIGNED
+UNSKILLED
+UNSOLVABLE
+UNSOLVED
+UNSOPHISTICATED
+UNSOUND
+UNSPEAKABLE
+UNSPECIFIED
+UNSTABLE
+UNSTEADY/P
+UNSTRUCTURED
+UNSUCCESSFUL/Y
+UNSUITABLE
+UNSUITED
+UNSUPPORTED
+UNSURE
+UNSURPRISING/Y
+UNSYNCHRONIZED
+UNTAPPED
+UNTERMINATED
+UNTESTED
+UNTHINKABLE
+UNTIDY/P
+UNTIE/D/S
+UNTIL
+UNTIMELY
+UNTO
+UNTOLD
+UNTOUCHABLE/M/S
+UNTOUCHED
+UNTOWARD
+UNTRAINED
+UNTRANSLATED
+UNTREATED
+UNTRIED
+UNTRUE
+UNTRUTHFUL/P
+UNTYING
+UNUSABLE
+UNUSED
+UNUSUAL/Y
+UNVARYING
+UNVEIL/D/G/S
+UNWANTED
+UNWELCOME
+UNWHOLESOME
+UNWIELDY/P
+UNWILLING/P/Y
+UNWIND/R/Z/G/S
+UNWISE/Y
+UNWITTING/Y
+UNWORTHY/P
+UNWOUND
+UNWRITTEN
+UP
+UPBRAID
+UPDATE/D/R/G/S
+UPGRADE/D/G/S
+UPHELD
+UPHILL
+UPHOLD/R/Z/G/S
+UPHOLSTER/D/R/G/S
+UPKEEP
+UPLAND/S
+UPLIFT
+UPON
+UPPER
+UPPERMOST
+UPRIGHT/P/Y
+UPRISING/M/S
+UPROAR
+UPROOT/D/G/S
+UPSET/S
+UPSHOT/M/S
+UPSIDE
+UPSTAIRS
+UPSTREAM
+UPTURN/D/G/S
+UPWARD/S
+URBAN
+URBANA
+URCHIN/M/S
+URGE/D/G/J/S
+URGENT/Y
+URINATE/D/G/N/S
+URINE
+URN/M/S
+US
+USA
+USABILITY
+USABLE
+USABLY
+USAGE/S
+USE/D/R/Z/G/S
+USEFUL/P/Y
+USELESS/P/Y
+USENIX
+USER'S
+USHER/D/G/S
+USUAL/Y
+USURP/D/R
+UTAH
+UTENSIL/M/S
+UTILITY/M/S
+UTILIZATION/M/S
+UTILIZE/D/G/S
+UTMOST
+UTOPIAN/M/S
+UTTER/D/G/Y/S
+UTTERANCE/M/S
+UTTERMOST
+UUCP
+UZI
+VACANCY/M/S
+VACANT/Y
+VACATE/D/G/X/S
+VACATION/D/R/Z/G/S
+VACUO
+VACUOUS/Y
+VACUUM/D/G
+VAGABOND/M/S
+VAGARY/M/S
+VAGINA/M/S
+VAGRANT/Y
+VAGUE/P/T/R/Y
+VAINLY
+VALE/M/S
+VALENCE/M/S
+VALENTINE/M/S
+VALET/M/S
+VALIANT/Y
+VALID/P/Y
+VALIDATE/D/G/N/S
+VALIDITY
+VALLEY/M/S
+VALOR
+VALUABLE/S
+VALUABLY
+VALUATION/M/S
+VALUE/D/R/Z/G/S
+VALVE/M/S
+VAN/M/S
+VANCOUVER
+VANDALIZE/D/G/S
+VANE/M/S
+VANILLA
+VANISH/D/R/G/S
+VANISHINGLY
+VANITY/S
+VANQUISH/D/G/S
+VANTAGE
+VAPOR/G/S
+VARIABILITY
+VARIABLE/P/M/S
+VARIABLY
+VARIANCE/M/S
+VARIANT/Y/S
+VARIATION/M/S
+VARIETY/M/S
+VARIOUS/Y
+VARNISH/M/S
+VARY/D/G/J/S
+VASE/M/S
+VASSAL
+VAST/P/T/R/Y
+VAT/M/S
+VAUDEVILLE
+VAULT/D/R/G/S
+VAUNT/D
+VAX
+VAXEN
+VAXES
+VEAL
+VECTOR/M/S
+VECTORIZATION
+VECTORIZING
+VEE
+VEER/D/G/S
+VEGAS
+VEGETABLE/M/S
+VEGETARIAN/M/S
+VEGETATE/D/G/N/V/S
+VEHEMENCE
+VEHEMENT/Y
+VEHICLE/M/S
+VEHICULAR
+VEIL/D/G/S
+VEIN/D/G/S
+VELOCITY/M/S
+VELVET
+VENDOR/M/S
+VENERABLE
+VENGEANCE
+VENISON
+VENOM
+VENOMOUS/Y
+VENT/D/S
+VENTILATE/D/G/N/S
+VENTRICLE/M/S
+VENTURE/D/R/Z/G/J/S
+VERACITY
+VERANDA/M/S
+VERB/M/S
+VERBAL/Y
+VERBATIM
+VERBOSE
+VERBOSITY
+VERDICT
+VERDURE
+VERGE/R/S
+VERIFIABILITY
+VERIFIABLE
+VERIFY/D/R/Z/G/N/X/S
+VERILY
+VERITABLE
+VERMIN
+VERNACULAR
+VERSA
+VERSATILE
+VERSATILITY
+VERSE/D/G/N/X/S
+VERSUS
+VERTEBRATE/M/S
+VERTEX
+VERTICAL/P/Y
+VERTICES
+VERY
+VESSEL/M/S
+VEST/D/S
+VESTIGE/M/S
+VESTIGIAL
+VETERAN/M/S
+VETERINARIAN/M/S
+VETERINARY
+VETO/D/R
+VETOES
+VEX/D/G/S
+VEXATION
+VIA
+VIABILITY
+VIABLE
+VIABLY
+VIAL/M/S
+VIBRATE/D/G/N/X
+VICE/M/S
+VICEROY
+VICINITY
+VICIOUS/P/Y
+VICISSITUDE/M/S
+VICTIM/M/S
+VICTIMIZE/D/R/Z/G/S
+VICTOR/M/S
+VICTORIA
+VICTORIOUS/Y
+VICTORY/M/S
+VICTUAL/R/S
+VIDEO
+VIDEOTAPE/M/S
+VIE/D/R/S
+VIEW/D/R/Z/G/S
+VIEWABLE
+VIEWPOINT/M/S
+VIEWPORT/S
+VIGILANCE
+VIGILANT/Y
+VIGILANTE/M/S
+VIGNETTE/M/S
+VIGOR
+VIGOROUS/Y
+VILE/P/Y
+VILIFY/D/G/N/X/S
+VILLA/M/S
+VILLAGE/R/Z/S
+VILLAIN/M/S
+VILLAINOUS/P/Y
+VILLAINY
+VINDICTIVE/P/Y
+VINE/M/S
+VINEGAR
+VINEYARD/M/S
+VINTAGE
+VIOLATE/D/G/N/X/S
+VIOLATOR/M/S
+VIOLENCE
+VIOLENT/Y
+VIOLET/M/S
+VIOLIN/M/S
+VIOLINIST/M/S
+VIPER/M/S
+VIRGIN/M/S
+VIRGINIA
+VIRGINITY
+VIRTUAL/Y
+VIRTUE/M/S
+VIRTUOSO/M/S
+VIRTUOUS/Y
+VIRUS/M/S
+VISA/S
+VISAGE
+VISCOUNT/M/S
+VISCOUS
+VISIBILITY
+VISIBLE
+VISIBLY
+VISION/M/S
+VISIONARY
+VISIT/D/G/S
+VISITATION/M/S
+VISITOR/M/S
+VISOR/M/S
+VISTA/M/S
+VISUAL/Y
+VISUALIZATION
+VISUALIZE/D/R/G/S
+VITA
+VITAE
+VITAL/Y/S
+VITALITY
+VIVID/P/Y
+VIZIER
+VLSI
+VMS
+VOCABULARY/S
+VOCAL/Y/S
+VOCATION/M/S
+VOCATIONAL/Y
+VOGUE
+VOICE/D/R/Z/G/S
+VOID/D/R/G/S
+VOLATILE
+VOLATILITY/S
+VOLCANIC
+VOLCANO/M/S
+VOLLEY
+VOLLEYBALL/M/S
+VOLT/S
+VOLTAGE/S
+VOLUME/M/S
+VOLUNTARILY
+VOLUNTARY
+VOLUNTEER/D/G/S
+VOMIT/D/G/S
+VON
+VOTE/D/R/Z/G/V/S
+VOUCH/R/Z/G/S
+VOW/D/R/G/S
+VOWEL/M/S
+VOYAGE/D/R/Z/G/J/S
+VS
+VULGAR/Y
+VULNERABILITY/S
+VULNERABLE
+VULTURE/M/S
+WADE/D/R/G/S
+WAFER/M/S
+WAFFLE/M/S
+WAFT
+WAG/S
+WAGE/D/R/Z/G/S
+WAGON/R/S
+WAIL/D/G/S
+WAIST/M/S
+WAISTCOAT/M/S
+WAIT/D/R/Z/G/S
+WAITRESS/M/S
+WAIVE/D/R/G/S
+WAIVERABLE
+WAKE/D/G/S
+WAKEN/D/G
+WALK/D/R/Z/G/S
+WALL/D/G/S
+WALLET/M/S
+WALLOW/D/G/S
+WALNUT/M/S
+WALRUS/M/S
+WALTZ/D/G/S
+WAN/Y
+WAND/Z
+WANDER/D/R/Z/G/J/S
+WANE/D/G/S
+WANG
+WANT/D/G/S
+WANTON/P/Y
+WAR/M/S
+WARBLE/D/R/G/S
+WARD/R/N/X/S
+WARDROBE/M/S
+WARE/S
+WAREHOUSE/G/S
+WARFARE
+WARILY
+WARLIKE
+WARM/D/T/G/H/Y/S
+WARMER/S
+WARN/D/R/G/J/S
+WARNINGLY
+WARP/D/G/S
+WARRANT/D/G/S
+WARRANTY/M/S
+WARRED
+WARRING
+WARRIOR/M/S
+WARSHIP/M/S
+WART/M/S
+WARY/P
+WAS
+WASH/D/R/Z/G/J/S
+WASHINGTON
+WASN'T
+WASP/M/S
+WASTE/D/G/S
+WASTEFUL/P/Y
+WATCH/D/R/Z/G/J/S
+WATCHFUL/P/Y
+WATCHMAN
+WATCHWORD/M/S
+WATER/D/G/J/S
+WATERFALL/M/S
+WATERMELON
+WATERPROOF/G
+WATERWAY/M/S
+WATERY
+WAVE/D/R/Z/G/S
+WAVEFORM/M/S
+WAVEFRONT/M/S
+WAVELENGTH
+WAVELENGTHS
+WAX/D/R/Z/G/N/S
+WAXY
+WAY/M/S
+WAYSIDE
+WAYWARD
+WE'D
+WE'LL
+WE'RE
+WE'VE
+WE/T
+WEAK/T/R/N/X/Y
+WEAKEN/D/G/S
+WEAKNESS/M/S
+WEALTH
+WEALTHS
+WEALTHY/T
+WEAN/D/G
+WEAPON/M/S
+WEAR/R/G/S
+WEARABLE
+WEARILY
+WEARISOME/Y
+WEARY/P/D/T/R/G
+WEASEL/M/S
+WEATHER/D/G/S
+WEATHERCOCK/M/S
+WEAVE/R/G/S
+WEB/M/S
+WED/S
+WEDDED
+WEDDING/M/S
+WEDGE/D/G/S
+WEDNESDAY/M/S
+WEE/D
+WEEDS
+WEEK/Y/S
+WEEKEND/M/S
+WEEP/G/R/S/Z
+WEIGH/D/G/J
+WEIGHS
+WEIGHT/D/G/S
+WEIRD/Y
+WELCOME/D/G/S
+WELD/D/R/G/S
+WELFARE
+WELL/D/G/S
+WENCH/M/S
+WENT
+WEPT
+WERE
+WEREN'T
+WESLEY
+WESTERN/R/Z
+WESTWARD/S
+WET/P/Y/S
+WETTED
+WETTER
+WETTEST
+WETTING
+WHACK/D/G/S
+WHALE/R/G/S
+WHARF
+WHARVES
+WHAT/M
+WHATEVER
+WHATSOEVER
+WHEAT/N
+WHEEL/D/R/Z/G/J/S
+WHELP
+WHEN
+WHENCE
+WHENEVER
+WHERE/M
+WHEREABOUTS
+WHEREAS
+WHEREBY
+WHEREIN
+WHEREUPON
+WHEREVER
+WHETHER
+WHICH
+WHICHEVER
+WHILE
+WHIM/M/S
+WHIMPER/D/G/S
+WHIMSICAL/Y
+WHIMSY/M/S
+WHINE/D/G/S
+WHIP/M/S
+WHIPPED
+WHIPPER/M/S
+WHIPPING/M/S
+WHIRL/D/G/S
+WHIRLPOOL/M/S
+WHIRLWIND
+WHIRR/G
+WHISK/D/R/Z/G/S
+WHISKEY
+WHISPER/D/G/J/S
+WHISTLE/D/R/Z/G/S
+WHIT/X
+WHITE/P/T/R/G/Y/S
+WHITEN/D/R/Z/G/S
+WHITESPACE
+WHITEWASH/D
+WHITTLE/D/G/S
+WHIZ
+WHIZZED
+WHIZZES
+WHIZZING
+WHO/M
+WHOEVER
+WHOLE/P/S
+WHOLEHEARTED/Y
+WHOLESALE/R/Z
+WHOLESOME/P
+WHOLLY
+WHOM
+WHOMEVER
+WHOOP/D/G/S
+WHORE/M/S
+WHORL/M/S
+WHOSE
+WHY
+WICK/D/R/S
+WICKED/P/Y
+WIDE/T/R/Y
+WIDEN/D/R/G/S
+WIDESPREAD
+WIDOW/D/R/Z/S
+WIDTH
+WIDTHS
+WIELD/D/R/G/S
+WIFE/M/Y
+WIG/M/S
+WIGWAM
+WILD/P/T/R/Y
+WILDCARD/S
+WILDCAT/M/S
+WILDERNESS
+WILDLIFE
+WILE/S
+WILL/D/G/S
+WILLFUL/Y
+WILLIAM/M
+WILLINGLY
+WILLINGNESS
+WILLOW/M/S
+WILT/D/G/S
+WILY/P
+WIN/S
+WINCE/D/G/S
+WIND/D/R/Z/G/S
+WINDMILL/M/S
+WINDOW/M/S
+WINDY
+WINE/D/R/Z/G/S
+WING/D/G/S
+WINK/D/R/G/S
+WINNER/M/S
+WINNING/Y/S
+WINTER/D/G/S
+WINTRY
+WIPE/D/R/Z/G/S
+WIRE/D/G/S
+WIRELESS
+WIRETAP/M/S
+WIRY/P
+WISCONSIN
+WISDOM/S
+WISE/D/T/R/Y
+WISH/D/R/Z/G/S
+WISHFUL
+WISP/M/S
+WISTFUL/P/Y
+WIT/M/S
+WITCH/G/S
+WITCHCRAFT
+WITH/R/Z
+WITHAL
+WITHDRAW/G/S
+WITHDRAWAL/M/S
+WITHDRAWN
+WITHDREW
+WITHHELD
+WITHHOLD/R/Z/G/J/S
+WITHIN
+WITHOUT
+WITHSTAND/G/S
+WITHSTOOD
+WITNESS/D/G/S
+WITTY
+WIVES
+WIZARD/M/S
+WOE
+WOEFUL/Y
+WOKE
+WOLF
+WOLVES
+WOMAN/M/Y
+WOMANHOOD
+WOMB/M/S
+WOMEN/M
+WON
+WON'T
+WONDER/D/G/S
+WONDERFUL/P/Y
+WONDERINGLY
+WONDERMENT
+WONDROUS/Y
+WONT/D
+WOO/D/R/G/S
+WOOD/D/N/S
+WOODCHUCK/M/S
+WOODCOCK/M/S
+WOODENLY
+WOODENNESS
+WOODLAND
+WOODMAN
+WOODPECKER/M/S
+WOODWORK/G
+WOODY
+WOOF/D/R/Z/G/S
+WOOL/N/Y/S
+WORD/D/M/G/S
+WORDILY
+WORDY/P
+WORE
+WORK/D/R/Z/G/J/S
+WORKABLE
+WORKABLY
+WORKBENCH/M/S
+WORKBOOK/M/S
+WORKHORSE/M/S
+WORKINGMAN
+WORKLOAD
+WORKMAN
+WORKMANSHIP
+WORKMEN
+WORKSHOP/M/S
+WORKSTATION/S
+WORLD/M/Y/S
+WORLDLINESS
+WORLDWIDE
+WORM/D/G/S
+WORN
+WORRISOME
+WORRY/D/R/Z/G/S
+WORRYINGLY
+WORSE
+WORSHIP/D/R/G/S
+WORSHIPFUL
+WORST/D
+WORTH
+WORTHLESS/P
+WORTHS
+WORTHWHILE/P
+WORTHY/P/T
+WOULD
+WOULDN'T
+WOUND/D/G/S
+WOVE
+WOVEN
+WRANGLE/D/R
+WRAP/M/S
+WRAPPED
+WRAPPER/M/S
+WRAPPING/S
+WRATH
+WREAK/S
+WREATH/D/S
+WRECK/D/R/Z/G/S
+WRECKAGE
+WREN/M/S
+WRENCH/D/G/S
+WREST
+WRESTLE/R/G/J/S
+WRETCH/D/S
+WRETCHEDNESS
+WRIGGLE/D/R/G/S
+WRING/R/S
+WRINKLE/D/S
+WRIST/M/S
+WRISTWATCH/M/S
+WRIT/M/S
+WRITABLE
+WRITE/R/Z/G/J/S
+WRITER'S
+WRITHE/D/G/S
+WRITTEN
+WRONG/D/G/Y/S
+WROTE
+WROUGHT
+WRUNG
+XENIX
+XEROX
+YALE
+YANK/D/G/S
+YARD/M/S
+YARDSTICK/M/S
+YARN/M/S
+YAWN/R/G
+YEA/S
+YEAR/M/Y/S
+YEARN/D/G/J
+YEAST/M/S
+YELL/D/R/G
+YELLOW/P/D/T/R/G/S
+YELLOWISH
+YELP/D/G/S
+YEOMAN
+YEOMEN
+YES
+YESTERDAY
+YET
+YIELD/D/G/S
+YOKE/M/S
+YON
+YONDER
+YORK/R/Z
+YORKTOWN
+YOU'D
+YOU'LL
+YOU'RE
+YOU'VE
+YOU/H
+YOUNG/T/R/Y
+YOUNGSTER/M/S
+YOUR/S
+YOURSELF
+YOURSELVES
+YOUTHFUL/P/Y
+YOUTHS
+YUGOSLAVIA
+ZEAL
+ZEALOUS/P/Y
+ZEBRA/M/S
+ZENITH
+ZERO/D/G/H/S
+ZEROES
+ZEST
+ZIGZAG
+ZINC
+ZODIAC
+ZONAL/Y
+ZONE/D/G/S
+ZOO/M/S
+ZOOLOGICAL/Y
+ZOOM/G
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell.asd
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell.asd	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spell.asd	(revision 13309)
@@ -0,0 +1,16 @@
+;;; -*- mode: lisp -*-
+(defpackage :spell-system (:use :cl :asdf))
+(in-package :spell-system)
+
+(defsystem spell
+  :version "0.4"
+  :components ((:file "package")
+               (:file "constants" :depends-on ("package"))
+               (:file "hashing" :depends-on ("package"))
+               (:file "flags")
+               (:file "classes" :depends-on ("package"))
+               (:file "build" :depends-on ("constants" "hashing"
+                                           "flags" "classes"))
+               ;; kind of a fake dependency
+               (:file "io" :depends-on ("build"))
+               (:file "correlate" :depends-on ("build"))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spellcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spellcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spell/spellcoms.lisp	(revision 13309)
@@ -0,0 +1,822 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+(ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles and Rob Maclachlan.
+;;;
+;;; This file contains the code to implement commands using the spelling
+;;; checking/correcting stuff in Spell-Corr.Lisp and the dictionary
+;;; augmenting stuff in Spell-Augment.Lisp.
+
+(in-package "HEMLOCK")
+
+
+
+(defstruct (spell-info (:print-function print-spell-info)
+		       (:constructor make-spell-info (pathname)))
+  pathname	;Dictionary file.
+  insertions)	;Incremental insertions for this dictionary.
+
+(defun print-spell-info (obj str n)
+  (declare (ignore n))
+  (let ((pn (spell-info-pathname obj)))
+    (format str "#<Spell Info~@[ ~S~]>"
+	    (and pn (namestring pn)))))
+
+
+(defattribute "Spell Word Character"
+  "One if the character is one that is present in the spell dictionary,
+  zero otherwise.")
+
+(do-alpha-chars (c :both)
+  (setf (character-attribute :spell-word-character c) 1))
+(setf (character-attribute :spell-word-character #\') 1)
+
+
+(defvar *spelling-corrections* (make-hash-table :test #'equal)
+  "Mapping from incorrect words to their corrections.")
+
+(defvar *ignored-misspellings* (make-hash-table :test #'equal)
+  "A hashtable with true values for words that will be quietly ignored when
+  they appear.")
+
+(defhvar "Spell Ignore Uppercase"
+  "If true, then \"Check Word Spelling\" and \"Correct Buffer Spelling\" will
+  ignore unknown words that are all uppercase.  This is useful for
+  abbreviations and cryptic formatter directives."
+  :value nil)
+
+
+
+
+;;;; Basic Spelling Correction Command (Esc-$ in EMACS)
+
+(defcommand "Check Word Spelling" (p)
+  "Check the spelling of the previous word and offer possible corrections
+   if the word in unknown. To add words to the dictionary from a text file see
+   the command \"Augment Spelling Dictionary\"."
+  "Check the spelling of the previous word and offer possible correct
+   spellings if the word is known to be misspelled."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)  
+  (let* ((region (spell-previous-word (current-point) nil))
+	 (word (if region
+		   (region-to-string region)
+		   (editor-error "No previous word.")))
+	 (folded (string-upcase word)))
+    (message "Checking spelling of ~A." word)
+    (unless (check-out-word-spelling word folded)
+      (get-word-correction (region-start region) word folded))))
+
+
+
+;;;; Auto-Spell mode:
+
+(defhvar "Check Word Spelling Beep"
+  "If true, \"Auto Check Word Spelling\" will beep when an unknown word is
+   found."
+  :value t)
+
+(defhvar "Correct Unique Spelling Immediately"
+  "If true, \"Auto Check Word Spelling\" will immediately attempt to correct any
+   unknown word, automatically making the correction if there is only one
+   possible."
+  :value t)
+
+
+(defhvar "Default User Spelling Dictionary"
+  "This is the pathname of a dictionary to read the first time \"Spell\" mode
+   is entered in a given editing session.  When \"Set Buffer Spelling
+   Dictionary\" or the \"dictionary\" file option is used to specify a
+   dictionary, this default one is read also.  It defaults to nil."
+  :value nil)
+
+(defvar *default-user-dictionary-read-p* nil)
+
+(defun maybe-read-default-user-spelling-dictionary ()
+  (let ((default-dict (value default-user-spelling-dictionary)))
+    (when (and default-dict (not *default-user-dictionary-read-p*))
+      (spell:maybe-read-spell-dictionary)
+      (spell:spell-read-dictionary (truename default-dict))
+      (setf *default-user-dictionary-read-p* t))))
+
+
+(defmode "Spell"
+  :transparent-p t :precedence 1.0 :setup-function 'spell-mode-setup)
+
+(defun spell-mode-setup (buffer)
+  (defhvar "Buffer Misspelled Words"
+    "This variable holds a ring of marks pointing to misspelled words."
+    :buffer buffer  :value (make-ring 10 #'delete-mark))
+  (maybe-read-default-user-spelling-dictionary))
+
+(defcommand "Auto Spell Mode" (p)
+  "Toggle \"Spell\" mode in the current buffer.  When in \"Spell\" mode,
+  the spelling of each word is checked after it is typed."
+  "Toggle \"Spell\" mode in the current buffer."
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Spell")
+	(not (buffer-minor-mode (current-buffer) "Spell"))))
+
+
+(defcommand "Auto Check Word Spelling" (p)
+  "Check the spelling of the previous word and display a message in the echo
+   area if the word is not in the dictionary.  To add words to the dictionary
+   from a text file see the command \"Augment Spelling Dictionary\".  If a
+   replacement for an unknown word has previously been specified, then the
+   replacement will be made immediately.  If \"Correct Unique Spelling
+   Immediately\" is true, then this command will immediately correct words
+   which have a unique correction.  If there is no obvious correction, then we
+   place the word in a ring buffer for access by the \"Correct Last Misspelled
+   Word\" command.  If \"Check Word Spelling Beep\" is true, then this command
+   beeps when an unknown word is found, in addition to displaying the message."
+  "Check the spelling of the previous word, making obvious corrections, or
+  queuing the word in buffer-misspelled-words if we are at a loss."
+  (declare (ignore p))
+  (unless (eq (last-command-type) :spell-check)
+    (spell:maybe-read-spell-dictionary)
+    (let ((region (spell-previous-word (current-point) t)))
+      (when region
+	(let* ((word (nstring-upcase (region-to-string region)))
+	       (len (length word)))
+	  (declare (simple-string word))
+	  (when (and (<= 2 len spell:max-entry-length)
+		     (not (spell:spell-try-word word len)))
+	    (let ((found (gethash word *spelling-corrections*))
+		  (save (region-to-string region)))
+	      (cond (found
+		     (undoable-replace-word (region-start region) save found)
+		     (message "Corrected ~S to ~S." save found)
+		     (when (value check-word-spelling-beep) (beep)))
+		    ((and (value spell-ignore-uppercase)
+			  (every #'upper-case-p save))
+		     (unless (gethash word *ignored-misspellings*)
+		       (setf (gethash word *ignored-misspellings*) t)
+		       (message "Ignoring ~S." save)))
+		    (t
+		     (let ((close (spell:spell-collect-close-words word)))
+		       (cond ((and close
+				   (null (rest close))
+				   (value correct-unique-spelling-immediately))
+			      (let ((fix (first close)))
+				(undoable-replace-word (region-start region)
+						       save fix)
+				(message "Corrected ~S to ~S." save fix)))
+			     (t
+			      (ring-push (copy-mark (region-end region)
+						    :right-inserting)
+					 (value buffer-misspelled-words))
+			      (let ((nclose
+				     (do ((i 0 (1+ i))
+					  (words close (cdr words))
+					  (nwords () (cons (list i (car words))
+							   nwords)))
+					 ((null words) (nreverse nwords)))))
+				(message
+				 "Word ~S not found.~
+				  ~@[  Corrections:~:{ ~D=~A~}~]"
+				 save nclose)))))
+		     (when (value check-word-spelling-beep) (beep))))))))))
+  (setf (last-command-type) :spell-check))
+
+(defcommand "Correct Last Misspelled Word" (p)
+  "Fix a misspelling found by \"Auto Check Word Spelling\".  This prompts for
+   a single character command to determine which action to take to correct the
+   problem."
+  "Prompt for a single character command to determine how to fix up a
+   misspelling detected by Check-Word-Spelling-Command."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (do ((info (value spell-information)))
+      ((sub-correct-last-misspelled-word info))))
+
+(defun sub-correct-last-misspelled-word (info)
+  (let* ((missed (value buffer-misspelled-words))
+	 (region (cond ((zerop (ring-length missed))
+			(editor-error "No recently misspelled word."))
+		       ((spell-previous-word (ring-ref missed 0) t))
+		       (t (editor-error "No recently misspelled word."))))
+	 (word (region-to-string region))
+	 (folded (string-upcase word))
+	 (point (current-point))
+	 (save (copy-mark point))
+	 (res t))
+    (declare (simple-string word))
+    (unwind-protect
+      (progn
+       (when (check-out-word-spelling word folded)
+	 (delete-mark (ring-pop missed))
+	 (return-from sub-correct-last-misspelled-word t))
+       (move-mark point (region-end region))
+       (command-case (:prompt "Action: "
+		      :change-window nil
+ :help "Type a single character command to do something to the misspelled word.")
+	 (#\c "Try to find a correction for this word."
+	  (unless (get-word-correction (region-start region) word folded)
+	    (reprompt)))
+	 (#\i "Insert this word in the dictionary."
+	  (spell:spell-add-entry folded)
+	  (push folded (spell-info-insertions info))
+	  (message "~A inserted in the dictionary." word))
+	 (#\r "Prompt for a word to replace this word with."
+	  (let ((s (prompt-for-string :prompt "Replace with: "
+				      :default word
+ :help "Type a string to replace occurrences of this word with.")))
+	    (delete-region region)
+	    (insert-string point s)
+	    (setf (gethash folded *spelling-corrections*) s)))
+	 (:cancel "Ignore this word and go to the previous misspelled word."
+	  (setq res nil))
+	 (:recursive-edit
+	  "Go into a recursive edit and leave when it exits."
+	  (do-recursive-edit))
+	 ((:exit #\q) "Exit and forget about this word.")
+	 ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
+	  "Choose this numbered word as the correct spelling."
+	  (let ((num (digit-char-p (ext:key-event-char *last-key-event-typed*)))
+		(close-words (spell:spell-collect-close-words folded)))
+	    (cond ((> num (length close-words))
+		   (editor-error "Choice out of range."))
+		  (t (let ((s (nth num close-words)))
+		       (setf (gethash folded *spelling-corrections*) s)
+		       (undoable-replace-word (region-start region)
+					      word s)))))))
+       (delete-mark (ring-pop missed))
+       res)
+      (move-mark point save)
+      (delete-mark save))))
+
+(defhvar "Spelling Un-Correct Prompt for Insert"
+  "When this is set, \"Undo Last Spelling Correction\" will prompt before
+   inserting the old word into the dictionary."
+  :value nil)
+
+(defcommand "Undo Last Spelling Correction" (p)
+  "Undo the last incremental spelling correction.
+   The \"correction\" is replaced with the old word, and the old word is
+   inserted in the dictionary.  When \"Spelling Un-Correct Prompt for Insert\"
+   is set, the user is asked about inserting the old word.  Any automatic
+   replacement for the old word is eliminated."
+  "Undo the last incremental spelling correction, nuking any undesirable
+   side-effects."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'last-spelling-correction-mark)
+    (editor-error "No last spelling correction."))
+  (let ((mark (value last-spelling-correction-mark))
+	(words (value last-spelling-correction-words)))
+    (unless words
+      (editor-error "No last spelling correction."))
+    (let* ((new (car words))
+	   (old (cdr words))
+	   (folded (string-upcase old)))
+      (declare (simple-string old new folded))
+      (remhash folded *spelling-corrections*)
+      (delete-characters mark (length new))
+      (insert-string mark old)
+      (setf (value last-spelling-correction-words) nil)
+      (when (or (not (value spelling-un-correct-prompt-for-insert))
+		(prompt-for-y-or-n
+		 :prompt (list "Insert ~A into spelling dictionary? " folded)
+		 :default t
+		 :default-string "Y"))
+	(push folded (spell-info-insertions (value spell-information)))
+	(spell:maybe-read-spell-dictionary)
+	(spell:spell-add-entry folded)
+	(message "Added ~S to spelling dictionary." old)))))
+
+
+;;; Check-Out-Word-Spelling  --  Internal
+;;;
+;;;    Return Nil if Word is a candidate for correction, otherwise
+;;; return T and message as to why it isn't.
+;;;
+(defun check-out-word-spelling (word folded)
+  (declare (simple-string word))
+  (let ((len (length word)))
+      (cond ((= len 1)
+	     (message "Single character words are not in the dictionary.") t)
+	    ((> len spell:max-entry-length)
+	     (message "~A is too long for the dictionary." word) t)
+	    (t
+	     (multiple-value-bind (idx flagp) (spell:spell-try-word folded len)
+	       (when idx
+		 (message "Found it~:[~; because of ~A~]." flagp
+			  (spell:spell-root-word idx))
+		 t))))))
+
+;;; Get-Word-Correction  --  Internal
+;;;
+;;;    Find all known close words to the either unknown or incorrectly
+;;; spelled word we are checking.  Word is the unmunged word, and Folded is
+;;; the uppercased word.  Mark is a mark which points to the beginning of
+;;; the offending word.  Return True if we successfully corrected the word.
+;;;
+(defun get-word-correction (mark word folded)
+  (let ((close-words (spell:spell-collect-close-words folded)))
+    (declare (list close-words))
+    (if close-words
+	(with-pop-up-display (s :height 3)
+	  (do ((i 0 (1+ i))
+	       (words close-words (cdr words)))
+	      ((null words))
+	    (format s "~36R=~A " i (car words)))
+	  (finish-output s)
+	  (let* ((key-event (prompt-for-key-event
+			     :prompt "Correction choice: "))
+		 (num (digit-char-p (ext:key-event-char key-event) 36)))
+	    (cond ((not num) (return-from get-word-correction nil))
+		  ((> num (length close-words))
+		   (editor-error "Choice out of range."))
+		  (t
+		   (let ((s (nth num close-words)))
+		     (setf (gethash folded *spelling-corrections*) s)
+		     (undoable-replace-word mark word s)))))
+	  (return-from get-word-correction t))
+	(with-pop-up-display (s :height 1)
+	  (write-line "No corrections found." s)
+	  nil))))
+
+
+;;; Undoable-Replace-Word  --  Internal
+;;;
+;;;    Like Spell-Replace-Word, but makes annotations in buffer local variables
+;;; so that "Undo Last Spelling Correction" can undo it.
+;;;
+(defun undoable-replace-word (mark old new)
+  (unless (hemlock-bound-p 'last-spelling-correction-mark)
+    (let ((buffer (current-buffer)))
+      (defhvar "Last Spelling Correction Mark"
+	"This variable holds a park pointing to the last spelling correction."
+	:buffer buffer  :value (copy-mark (buffer-start-mark buffer)))
+      (defhvar "Last Spelling Correction Words"
+	"The replacement done for the last correction: (new . old)."
+	:buffer buffer  :value nil)))
+  (move-mark (value last-spelling-correction-mark) mark)
+  (setf (value last-spelling-correction-words) (cons new old))
+  (spell-replace-word mark old new))
+
+
+
+;;;; Buffer Correction
+
+(defvar *spell-word-characters*
+  (make-array char-code-limit :element-type 'bit  :initial-element 0)
+  "Characters that are legal in a word for spelling checking purposes.")
+
+(do-alpha-chars (c :both)
+  (setf (sbit *spell-word-characters* (char-code c)) 1))
+(setf (sbit *spell-word-characters* (char-code #\')) 1)
+
+
+(defcommand "Correct Buffer Spelling" (p)
+  "Correct spelling over whole buffer.  A log of the found misspellings is
+   kept in the buffer \"Spell Corrections\".  For each unknown word the
+   user may accept it, insert it in the dictionary, correct its spelling
+   with one of the offered possibilities, replace the word with a user
+   supplied word, or go into a recursive edit.  Words may be added to the
+   dictionary in advance from a text file (see the command \"Augment
+   Spelling Dictionary\")."
+  "Correct spelling over whole buffer."
+  (declare (ignore p))
+  (clrhash *ignored-misspellings*)
+  (let* ((buffer (current-buffer))
+	 (log (or (make-buffer "Spelling Corrections")
+		  (getstring "Spelling Corrections" *buffer-names*)))
+	 (point (buffer-end (buffer-point log)))
+	 (*standard-output* (make-hemlock-output-stream point))
+	 (window (or (car (buffer-windows log)) (make-window point))))
+    (format t "~&Starting spelling checking of buffer ~S.~2%"
+	    (buffer-name buffer))
+    (spell:maybe-read-spell-dictionary)
+    (correct-buffer-spelling buffer window)
+    (delete-window window)
+    (close *standard-output*)))
+
+;;; CORRECT-BUFFER-SPELLING scans through buffer a line at a time, grabbing the
+;;; each line's string and breaking it up into words using the
+;;; *spell-word-characters* mask.  We try the spelling of each word, and if it
+;;; is unknown, we call FIX-WORD and resynchronize when it returns.
+;;;
+(defun correct-buffer-spelling (buffer window)
+  (do ((line (mark-line (buffer-start-mark buffer)) (line-next line))
+       (info (if (hemlock-bound-p 'spell-information :buffer buffer)
+		 (variable-value 'spell-information :buffer buffer)
+		 (value spell-information)))
+       (mask *spell-word-characters*)
+       (word (make-string spell:max-entry-length)))
+      ((null line))
+    (declare (simple-bit-vector mask) (simple-string word))
+    (block line
+      (let* ((string (line-string line))
+	     (length (length string)))
+	(declare (simple-string string))
+	(do ((start 0 (or skip-apostrophes end))
+	     (skip-apostrophes nil nil)
+	     end)
+	    (nil)
+	  ;;
+	  ;; Find word start.
+	  (loop
+	    (when (= start length) (return-from line))
+	    (when (/= (bit mask (char-code (schar string start))) 0) (return))
+	    (incf start))
+	  ;;
+	  ;; Find the end.
+	  (setq end (1+ start))
+	  (loop
+	    (when (= end length) (return))
+	    (when (zerop (bit mask (char-code (schar string end)))) (return))
+	    (incf end))
+	  (multiple-value-setq (end skip-apostrophes)
+	    (correct-buffer-word-end string start end))
+	  ;;
+	  ;; Check word.
+	  (let ((word-len (- end start)))
+	    (cond
+	     ((= word-len 1))
+	     ((> word-len spell:max-entry-length)
+	      (format t "Not checking ~S -- too long for dictionary.~2%"
+		      word))
+	     (t
+	      ;;
+	      ;; Copy the word and uppercase it.
+	      (do* ((i (1- end) (1- i))
+		    (j (1- word-len) (1- j)))
+		   ((zerop j)
+		    (setf (schar word 0) (char-upcase (schar string i))))
+		(setf (schar word j) (char-upcase (schar string i))))
+	      (unless (spell:spell-try-word word word-len)
+		(move-to-position (current-point) start line)
+		(fix-word (subseq word 0 word-len) (subseq string start end)
+			  window info)
+		(let ((point (current-point)))
+		  (setq end (mark-charpos point)
+			line (mark-line point)
+			string (line-string line)
+			length (length string))))))))))))
+
+;;; CORRECT-BUFFER-WORD-END takes a line string from CORRECT-BUFFER-SPELLING, a
+;;; start, and a end.  It places end to exclude from the word apostrophes used
+;;; for quotation marks, possessives, and funny plurals (e.g., A's and AND's).
+;;; Every word potentially can be followed by "'s", and any clown can use the
+;;; `` '' Scribe ligature.  This returns the value to use for end of the word
+;;; and the value to use as the end when continuing to find the next word in
+;;; string.
+;;;
+(defun correct-buffer-word-end (string start end)
+  (cond ((and (> (- end start) 2)
+	      (char= (char-upcase (schar string (1- end))) #\S)
+	      (char= (schar string (- end 2)) #\'))
+	 ;; Use roots of possessives and funny plurals (e.g., A's and AND's).
+	 (values (- end 2) end))
+	(t
+	 ;; Maybe backup over apostrophes used for quotation marks.
+	 (do ((i (1- end) (1- i)))
+	     ((= i start) (values end end))
+	   (when (char/= (schar string i) #\')
+	     (return (values (1+ i) end)))))))
+
+;;; Fix-Word  --  Internal
+;;;
+;;;    Handles the case where the word has a known correction.  If is does
+;;; not then call Correct-Buffer-Word-Not-Found.  In either case, the
+;;; point is left at the place to resume checking.
+;;;
+(defun fix-word (word unfolded-word window info)
+  (declare (simple-string word unfolded-word))
+  (let ((correction (gethash word *spelling-corrections*))
+	(mark (current-point)))
+    (cond (correction
+	   (format t "Replacing ~S with ~S.~%" unfolded-word correction)
+	   (spell-replace-word mark unfolded-word correction))
+	  ((and (value spell-ignore-uppercase)
+		(every #'upper-case-p unfolded-word))
+	   (character-offset mark (length word))
+	   (unless (gethash word *ignored-misspellings*)
+	     (setf (gethash word *ignored-misspellings*) t)
+	     (format t "Ignoring ~S.~%" unfolded-word)))
+	  (t
+	   (correct-buffer-word-not-found word unfolded-word window info)))))
+
+(defun correct-buffer-word-not-found (word unfolded-word window info)
+  (declare (simple-string word unfolded-word))
+  (let* ((close-words (spell:spell-collect-close-words word))
+	 (close-words-len (length (the list close-words)))
+	 (mark (current-point))
+	 (wordlen (length word)))
+    (format t "Unknown word: ~A~%" word)
+    (cond (close-words
+	   (format t "~[~;A~:;Some~]~:* possible correction~[~; is~:;s are~]: "
+		   close-words-len)
+	   (if (= close-words-len 1)
+	       (write-line (car close-words))
+	       (let ((n 0))
+		 (dolist (w close-words (terpri))
+		   (format t "~36R=~A " n w)
+		   (incf n)))))
+	  (t
+	   (write-line "No correction possibilities found.")))
+    (let ((point (buffer-point (window-buffer window))))
+      (unless (displayed-p point window)
+	(center-window window point)))
+    (command-case
+       (:prompt "Action: "
+        :help "Type a single letter command, or help character for help."
+        :change-window nil)
+      (#\i "Insert unknown word into dictionary for future lookup."
+	 (spell:spell-add-entry word)
+	 (push word (spell-info-insertions info))
+	 (format t "~S added to dictionary.~2%" word))
+      (#\c "Correct the unknown word with possible correct spellings."
+	 (unless close-words
+	   (write-line "There are no possible corrections.")
+	   (reprompt))
+	 (let ((num (if (= close-words-len 1) 0
+			(digit-char-p (ext:key-event-char
+				       (prompt-for-key-event
+					:prompt "Correction choice: "))
+				      36))))
+	   (unless num (reprompt))
+	   (when (> num close-words-len)
+	     (beep)
+	     (write-line "Response out of range.")
+	     (reprompt))
+	   (let ((choice (nth num close-words)))
+	     (setf (gethash word *spelling-corrections*) choice)
+	     (spell-replace-word mark unfolded-word choice)))
+	 (terpri))
+      (#\a "Accept the word as correct (that is, ignore it)."
+	 (character-offset mark wordlen))
+      (#\r "Replace the unknown word with a supplied replacement."
+	 (let ((s (prompt-for-string
+		   :prompt "Replacement Word: "
+		   :default unfolded-word
+		   :help "String to replace the unknown word with.")))
+	   (setf (gethash word *spelling-corrections*) s)
+	   (spell-replace-word mark unfolded-word s))
+	 (terpri))
+      (:recursive-edit
+       "Go into a recursive edit and resume correction where the point is left."
+       (do-recursive-edit)))))
+
+;;; Spell-Replace-Word  --  Internal
+;;;
+;;;    Replaces Old with New, starting at Mark.  The case of Old is used
+;;; to derive the new case.
+;;;
+(defun spell-replace-word (mark old new)
+  (declare (simple-string old new))
+  (let ((res (cond ((lower-case-p (schar old 0))
+		    (string-downcase new))
+		   ((lower-case-p (schar old 1))
+		    (let ((res (string-downcase new)))
+		      (setf (char res 0) (char-upcase (char res 0)))
+		      res))
+		   (t
+		    (string-upcase new)))))
+    (with-mark ((m mark :left-inserting))
+      (delete-characters m (length old))
+      (insert-string m res))))
+
+
+
+;;;; User Spelling Dictionaries.
+
+(defvar *pathname-to-spell-info* (make-hash-table :test #'equal)
+  "This maps dictionary files to spelling information.")
+
+(defhvar "Spell Information"
+  "This is the information about a spelling dictionary and its incremental
+   insertions."
+  :value (make-spell-info nil))
+
+(define-file-option "Dictionary" (buffer file)
+  (let* ((dict (merge-pathnames
+		file
+		(make-pathname :defaults (buffer-default-pathname buffer)
+			       :type "dict")))
+	 (dictp (probe-file dict)))
+    (if dictp
+	(set-buffer-spelling-dictionary-command nil dictp buffer)
+	(loud-message "Couldn't find dictionary ~A." (namestring dict)))))
+
+;;; SAVE-DICTIONARY-ON-WRITE is on the "Write File Hook" in buffers with
+;;; the "dictionary" file option.
+;;; 
+(defun save-dictionary-on-write (buffer)
+  (when (hemlock-bound-p 'spell-information :buffer buffer)
+    (save-spelling-insertions
+     (variable-value 'spell-information :buffer buffer))))
+
+
+(defcommand "Save Incremental Spelling Insertions" (p)
+  "Append incremental spelling dictionary insertions to a file.  The file
+   is prompted for unless \"Set Buffer Spelling Dictionary\" has been
+   executed in the buffer."
+  "Append incremental spelling dictionary insertions to a file."
+  (declare (ignore p))
+  (let* ((info (value spell-information))
+	 (file (or (spell-info-pathname info)
+		   (value default-user-spelling-dictionary)
+		   (prompt-for-file
+		    :prompt "Dictionary File: "
+		    :default (dictionary-name-default)
+		    :must-exist nil
+		    :help
+ "Name of the dictionary file to append dictionary insertions to."))))
+    (save-spelling-insertions info file)
+    (let* ((ginfo (variable-value 'spell-information :global))
+	   (insertions (spell-info-insertions ginfo)))
+      (when (and insertions
+		 (prompt-for-y-or-n
+		  :prompt
+		  `("Global spelling insertions exist.~%~
+		     Save these to ~A also? "
+		    ,(namestring file)
+		  :default t
+		  :default-string "Y"))
+	(save-spelling-insertions ginfo file))))))
+
+(defun save-spelling-insertions (info &optional
+				      (name (spell-info-pathname info)))
+  (when (spell-info-insertions info)
+    (with-open-file (stream name
+			    :direction :output :element-type 'base-char
+			    :if-exists :append :if-does-not-exist :create)
+      (dolist (w (spell-info-insertions info))
+	(write-line w stream)))
+    (setf (spell-info-insertions info) ())
+    (message "Incremental spelling insertions for ~A written."
+	     (namestring name))))
+
+(defcommand "Set Buffer Spelling Dictionary" (p &optional file buffer)
+  "Prompts for the dictionary file to associate with the current buffer.
+   If this file has not been read for any other buffer, then it is read.
+   Incremental spelling insertions from this buffer can be appended to
+   this file with \"Save Incremental Spelling Insertions\"."
+  "Sets the buffer's spelling dictionary and reads it if necessary."
+  (declare (ignore p))
+  (maybe-read-default-user-spelling-dictionary)
+  (let* ((file (truename (or file
+			     (prompt-for-file
+			      :prompt "Dictionary File: "
+			      :default (dictionary-name-default)
+			      :help
+ "Name of the dictionary file to add into the current dictionary."))))
+	 (file-name (namestring file))
+	 (spell-info-p (gethash file-name *pathname-to-spell-info*))
+	 (spell-info (or spell-info-p (make-spell-info file)))
+	 (buffer (or buffer (current-buffer))))
+    (defhvar "Spell Information"
+      "This is the information about a spelling dictionary and its incremental
+       insertions."
+      :value spell-info :buffer buffer)
+    (add-hook write-file-hook 'save-dictionary-on-write)
+    (unless spell-info-p
+      (setf (gethash file-name *pathname-to-spell-info*) spell-info)
+      (read-spelling-dictionary-command nil file))))
+
+(defcommand "Read Spelling Dictionary" (p &optional file)
+  "Adds entries to the dictionary from a file in the following format:
+   
+      entry1/flag1/flag2/flag3
+      entry2
+      entry3/flag1/flag2/flag3/flag4/flag5.
+
+   The flags are single letter indicators of legal suffixes for the entry;
+   the available flags and their correct use may be found at the beginning
+   of spell-correct.lisp in the Hemlock sources.  There must be exactly one 
+   entry per line, and each line must be flushleft."
+  "Add entries to the dictionary from a text file in a specified format."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (spell:spell-read-dictionary
+   (or file
+       (prompt-for-file
+	:prompt "Dictionary File: "
+	:default (dictionary-name-default)
+	:help
+	"Name of the dictionary file to add into the current dictionary."))))
+
+(defun dictionary-name-default ()
+  (make-pathname :defaults (buffer-default-pathname (current-buffer))
+		 :type "dict"))
+
+(defcommand "Add Word to Spelling Dictionary" (p)
+  "Add the previous word to the spelling dictionary."
+  "Add the previous word to the spelling dictionary."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (let ((word (region-to-string (spell-previous-word (current-point) nil))))
+    ;;
+    ;; SPELL:SPELL-ADD-ENTRY destructively uppercases word.
+    (when (spell:spell-add-entry word)
+      (message "Word ~(~S~) added to the spelling dictionary." word)
+      (push word (spell-info-insertions (value spell-information))))))
+
+(defcommand "Remove Word from Spelling Dictionary" (p)
+  "Prompts for word to remove from the spelling dictionary."
+  "Prompts for word to remove from the spelling dictionary."
+   (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (let* ((word (prompt-for-string
+		:prompt "Word to remove from spelling dictionary: "
+		:trim t))
+	 (upword (string-upcase word)))
+    (declare (simple-string word))
+    (multiple-value-bind (index flagp)
+			 (spell:spell-try-word upword (length word))
+      (unless index
+	(editor-error "~A not in dictionary." upword))
+      (if flagp
+	  (remove-spelling-word upword)
+	  (let ((flags (spell:spell-root-flags index)))
+	    (when (or (not flags)
+		      (prompt-for-y-or-n
+		       :prompt
+ `("Deleting ~A also removes words formed from this root and these flags: ~%  ~
+    ~S.~%~
+    Delete word anyway? "
+   ,word ,flags)
+		       :default t
+		       :default-string "Y"))
+	      (remove-spelling-word upword)))))))
+
+;;; REMOVE-SPELLING-WORD removes the uppercase word word from the spelling
+;;; dictionary and from the spelling informations incremental insertions list.
+;;; 
+(defun remove-spelling-word (word)
+  (let ((info (value spell-information)))
+    (spell:spell-remove-entry word)
+    (setf (spell-info-insertions info)
+	  (delete word (spell-info-insertions info) :test #'string=))))
+
+(defcommand "List Incremental Spelling Insertions" (p)
+  "Display the incremental spelling insertions for the current buffer's
+   associated spelling dictionary file."
+  "Display the incremental spelling insertions for the current buffer's
+   associated spelling dictionary file."
+  (declare (ignore p))
+  (let* ((info (value spell-information))
+	 (file (spell-info-pathname info))
+	 (insertions (spell-info-insertions info)))
+    (declare (list insertions))
+    (with-pop-up-display (s :height (1+ (length insertions)))
+      (if file
+	  (format s "Incremental spelling insertions for dictionary ~A:~%"
+		  (namestring file))
+	  (write-line "Global incremental spelling insertions:" s))
+      (dolist (w insertions)
+	(write-line w s)))))
+
+
+
+
+;;;; Utilities for above stuff.
+
+;;; SPELL-PREVIOUS-WORD returns as a region the current or previous word, using
+;;; the spell word definition.  If there is no such word, return nil.  If end-p
+;;; is non-nil, then mark ends the word even if there is a non-delimiter
+;;; character after it.
+;;;
+;;; Actually, if mark is between the first character of a word and a
+;;; non-spell-word characer, it is considered to be in that word even though
+;;; that word is after the mark.  This is because Hemlock's cursor is always
+;;; displayed over the next character, so users tend to think of a cursor
+;;; displayed on the first character of a word as being in that word instead of
+;;; before it.
+;;;
+(defun spell-previous-word (mark end-p)
+  (with-mark ((point mark)
+	      (mark mark))
+    (cond ((or end-p
+	       (zerop (character-attribute :spell-word-character
+					   (next-character point))))
+	   (unless (reverse-find-attribute mark :spell-word-character)
+	     (return-from spell-previous-word nil))
+	   (move-mark point mark)
+	   (reverse-find-attribute point :spell-word-character #'zerop))
+	  (t
+	   (find-attribute mark :spell-word-character #'zerop)
+	   (reverse-find-attribute point :spell-word-character #'zerop)))
+    (cond ((and (> (- (mark-charpos mark) (mark-charpos point)) 2)
+		(char= (char-upcase (previous-character mark)) #\S)
+		(char= (prog1 (previous-character (mark-before mark))
+			 (mark-after mark))
+		       #\'))
+	   ;; Use roots of possessives and funny plurals (e.g., A's and AND's).
+	   (character-offset mark -2))
+	  (t
+	   ;; Maybe backup over apostrophes used for quotation marks.
+	   (loop
+	     (when (mark= point mark) (return-from spell-previous-word nil))
+	     (when (char/= (previous-character mark) #\') (return))
+	     (mark-before mark))))
+    (region point mark)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/spellcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/spellcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/spellcoms.lisp	(revision 13309)
@@ -0,0 +1,822 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles and Rob Maclachlan.
+;;;
+;;; This file contains the code to implement commands using the spelling
+;;; checking/correcting stuff in Spell-Corr.Lisp and the dictionary
+;;; augmenting stuff in Spell-Augment.Lisp.
+
+(in-package :hemlock)
+
+
+
+(defstruct (spell-info (:print-function print-spell-info)
+		       (:constructor make-spell-info (pathname)))
+  pathname	;Dictionary file.
+  insertions)	;Incremental insertions for this dictionary.
+
+(defun print-spell-info (obj str n)
+  (declare (ignore n))
+  (let ((pn (spell-info-pathname obj)))
+    (format str "#<Spell Info~@[ ~S~]>"
+	    (and pn (namestring pn)))))
+
+
+(defattribute "Spell Word Character"
+  "One if the character is one that is present in the spell dictionary,
+  zero otherwise.")
+
+(do-alpha-chars (c :both)
+  (setf (character-attribute :spell-word-character c) 1))
+(setf (character-attribute :spell-word-character #\') 1)
+
+
+(defvar *spelling-corrections* (make-hash-table :test #'equal)
+  "Mapping from incorrect words to their corrections.")
+
+(defvar *ignored-misspellings* (make-hash-table :test #'equal)
+  "A hashtable with true values for words that will be quietly ignored when
+  they appear.")
+
+(defhvar "Spell Ignore Uppercase"
+  "If true, then \"Check Word Spelling\" and \"Correct Buffer Spelling\" will
+  ignore unknown words that are all uppercase.  This is useful for
+  abbreviations and cryptic formatter directives."
+  :value nil)
+
+
+
+
+;;;; Basic Spelling Correction Command (Esc-$ in EMACS)
+
+(defcommand "Check Word Spelling" (p)
+  "Check the spelling of the previous word and offer possible corrections
+   if the word in unknown. To add words to the dictionary from a text file see
+   the command \"Augment Spelling Dictionary\"."
+  "Check the spelling of the previous word and offer possible correct
+   spellings if the word is known to be misspelled."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)  
+  (let* ((region (spell-previous-word (current-point) nil))
+	 (word (if region
+		   (region-to-string region)
+		   (editor-error "No previous word.")))
+	 (folded (string-upcase word)))
+    (message "Checking spelling of ~A." word)
+    (unless (check-out-word-spelling word folded)
+      (get-word-correction (region-start region) word folded))))
+
+
+
+;;;; Auto-Spell mode:
+
+(defhvar "Check Word Spelling Beep"
+  "If true, \"Auto Check Word Spelling\" will beep when an unknown word is
+   found."
+  :value t)
+
+(defhvar "Correct Unique Spelling Immediately"
+  "If true, \"Auto Check Word Spelling\" will immediately attempt to correct any
+   unknown word, automatically making the correction if there is only one
+   possible."
+  :value t)
+
+
+(defhvar "Default User Spelling Dictionary"
+  "This is the pathname of a dictionary to read the first time \"Spell\" mode
+   is entered in a given editing session.  When \"Set Buffer Spelling
+   Dictionary\" or the \"dictionary\" file option is used to specify a
+   dictionary, this default one is read also.  It defaults to nil."
+  :value nil)
+
+(defvar *default-user-dictionary-read-p* nil)
+
+(defun maybe-read-default-user-spelling-dictionary ()
+  (let ((default-dict (value default-user-spelling-dictionary)))
+    (when (and default-dict (not *default-user-dictionary-read-p*))
+      (spell:maybe-read-spell-dictionary)
+      (spell:spell-read-dictionary (truename default-dict))
+      (setf *default-user-dictionary-read-p* t))))
+
+
+(defmode "Spell"
+  :transparent-p t :precedence 1.0 :setup-function 'spell-mode-setup)
+
+(defun spell-mode-setup (buffer)
+  (defhvar "Buffer Misspelled Words"
+    "This variable holds a ring of marks pointing to misspelled words."
+    :buffer buffer  :value (make-ring 10 #'delete-mark))
+  (maybe-read-default-user-spelling-dictionary))
+
+(defcommand "Auto Spell Mode" (p)
+  "Toggle \"Spell\" mode in the current buffer.  When in \"Spell\" mode,
+  the spelling of each word is checked after it is typed."
+  "Toggle \"Spell\" mode in the current buffer."
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Spell")
+	(not (buffer-minor-mode (current-buffer) "Spell"))))
+
+
+(defcommand "Auto Check Word Spelling" (p)
+  "Check the spelling of the previous word and display a message in the echo
+   area if the word is not in the dictionary.  To add words to the dictionary
+   from a text file see the command \"Augment Spelling Dictionary\".  If a
+   replacement for an unknown word has previously been specified, then the
+   replacement will be made immediately.  If \"Correct Unique Spelling
+   Immediately\" is true, then this command will immediately correct words
+   which have a unique correction.  If there is no obvious correction, then we
+   place the word in a ring buffer for access by the \"Correct Last Misspelled
+   Word\" command.  If \"Check Word Spelling Beep\" is true, then this command
+   beeps when an unknown word is found, in addition to displaying the message."
+  "Check the spelling of the previous word, making obvious corrections, or
+  queuing the word in buffer-misspelled-words if we are at a loss."
+  (declare (ignore p))
+  (unless (eq (last-command-type) :spell-check)
+    (spell:maybe-read-spell-dictionary)
+    (let ((region (spell-previous-word (current-point) t)))
+      (when region
+	(let* ((word (nstring-upcase (region-to-string region)))
+	       (len (length word)))
+	  (declare (simple-string word))
+	  (when (and (<= 2 len spell:max-entry-length)
+		     (not (spell:spell-try-word word len)))
+	    (let ((found (gethash word *spelling-corrections*))
+		  (save (region-to-string region)))
+	      (cond (found
+		     (undoable-replace-word (region-start region) save found)
+		     (message "Corrected ~S to ~S." save found)
+		     (when (value check-word-spelling-beep) (beep)))
+		    ((and (value spell-ignore-uppercase)
+			  (every #'upper-case-p save))
+		     (unless (gethash word *ignored-misspellings*)
+		       (setf (gethash word *ignored-misspellings*) t)
+		       (message "Ignoring ~S." save)))
+		    (t
+		     (let ((close (spell:spell-collect-close-words word)))
+		       (cond ((and close
+				   (null (rest close))
+				   (value correct-unique-spelling-immediately))
+			      (let ((fix (first close)))
+				(undoable-replace-word (region-start region)
+						       save fix)
+				(message "Corrected ~S to ~S." save fix)))
+			     (t
+			      (ring-push (copy-mark (region-end region)
+						    :right-inserting)
+					 (value buffer-misspelled-words))
+			      (let ((nclose
+				     (do ((i 0 (1+ i))
+					  (words close (cdr words))
+					  (nwords () (cons (list i (car words))
+							   nwords)))
+					 ((null words) (nreverse nwords)))))
+				(message
+				 "Word ~S not found.~
+				  ~@[  Corrections:~:{ ~D=~A~}~]"
+				 save nclose)))))
+		     (when (value check-word-spelling-beep) (beep))))))))))
+  (setf (last-command-type) :spell-check))
+
+(defcommand "Correct Last Misspelled Word" (p)
+  "Fix a misspelling found by \"Auto Check Word Spelling\".  This prompts for
+   a single character command to determine which action to take to correct the
+   problem."
+  "Prompt for a single character command to determine how to fix up a
+   misspelling detected by Check-Word-Spelling-Command."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (do ((info (value spell-information)))
+      ((sub-correct-last-misspelled-word info))))
+
+(defun sub-correct-last-misspelled-word (info)
+  (let* ((missed (value buffer-misspelled-words))
+	 (region (cond ((zerop (ring-length missed))
+			(editor-error "No recently misspelled word."))
+		       ((spell-previous-word (ring-ref missed 0) t))
+		       (t (editor-error "No recently misspelled word."))))
+	 (word (region-to-string region))
+	 (folded (string-upcase word))
+	 (point (current-point))
+	 (save (copy-mark point))
+	 (res t))
+    (declare (simple-string word))
+    (unwind-protect
+      (progn
+       (when (check-out-word-spelling word folded)
+	 (delete-mark (ring-pop missed))
+	 (return-from sub-correct-last-misspelled-word t))
+       (move-mark point (region-end region))
+       (command-case (:prompt "Action: "
+		      :change-window nil
+ :help "Type a single character command to do something to the misspelled word.")
+	 (#\c "Try to find a correction for this word."
+	  (unless (get-word-correction (region-start region) word folded)
+	    (reprompt)))
+	 (#\i "Insert this word in the dictionary."
+	  (spell:spell-add-entry folded)
+	  (push folded (spell-info-insertions info))
+	  (message "~A inserted in the dictionary." word))
+	 (#\r "Prompt for a word to replace this word with."
+	  (let ((s (prompt-for-string :prompt "Replace with: "
+				      :default word
+ :help "Type a string to replace occurrences of this word with.")))
+	    (delete-region region)
+	    (insert-string point s)
+	    (setf (gethash folded *spelling-corrections*) s)))
+	 (:cancel "Ignore this word and go to the previous misspelled word."
+	  (setq res nil))
+	 (:recursive-edit
+	  "Go into a recursive edit and leave when it exits."
+	  (do-recursive-edit))
+	 ((:exit #\q) "Exit and forget about this word.")
+	 ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
+	  "Choose this numbered word as the correct spelling."
+	  (let ((num (digit-char-p (ext:key-event-char *last-key-event-typed*)))
+		(close-words (spell:spell-collect-close-words folded)))
+	    (cond ((> num (length close-words))
+		   (editor-error "Choice out of range."))
+		  (t (let ((s (nth num close-words)))
+		       (setf (gethash folded *spelling-corrections*) s)
+		       (undoable-replace-word (region-start region)
+					      word s)))))))
+       (delete-mark (ring-pop missed))
+       res)
+      (move-mark point save)
+      (delete-mark save))))
+
+(defhvar "Spelling Un-Correct Prompt for Insert"
+  "When this is set, \"Undo Last Spelling Correction\" will prompt before
+   inserting the old word into the dictionary."
+  :value nil)
+
+(defcommand "Undo Last Spelling Correction" (p)
+  "Undo the last incremental spelling correction.
+   The \"correction\" is replaced with the old word, and the old word is
+   inserted in the dictionary.  When \"Spelling Un-Correct Prompt for Insert\"
+   is set, the user is asked about inserting the old word.  Any automatic
+   replacement for the old word is eliminated."
+  "Undo the last incremental spelling correction, nuking any undesirable
+   side-effects."
+  (declare (ignore p))
+  (unless (hemlock-bound-p 'last-spelling-correction-mark)
+    (editor-error "No last spelling correction."))
+  (let ((mark (value last-spelling-correction-mark))
+	(words (value last-spelling-correction-words)))
+    (unless words
+      (editor-error "No last spelling correction."))
+    (let* ((new (car words))
+	   (old (cdr words))
+	   (folded (string-upcase old)))
+      (declare (simple-string old new folded))
+      (remhash folded *spelling-corrections*)
+      (delete-characters mark (length new))
+      (insert-string mark old)
+      (setf (value last-spelling-correction-words) nil)
+      (when (or (not (value spelling-un-correct-prompt-for-insert))
+		(prompt-for-y-or-n
+		 :prompt (list "Insert ~A into spelling dictionary? " folded)
+		 :default t
+		 :default-string "Y"))
+	(push folded (spell-info-insertions (value spell-information)))
+	(spell:maybe-read-spell-dictionary)
+	(spell:spell-add-entry folded)
+	(message "Added ~S to spelling dictionary." old)))))
+
+
+;;; Check-Out-Word-Spelling  --  Internal
+;;;
+;;;    Return Nil if Word is a candidate for correction, otherwise
+;;; return T and message as to why it isn't.
+;;;
+(defun check-out-word-spelling (word folded)
+  (declare (simple-string word))
+  (let ((len (length word)))
+      (cond ((= len 1)
+	     (message "Single character words are not in the dictionary.") t)
+	    ((> len spell:max-entry-length)
+	     (message "~A is too long for the dictionary." word) t)
+	    (t
+	     (multiple-value-bind (idx flagp) (spell:spell-try-word folded len)
+	       (when idx
+		 (message "Found it~:[~; because of ~A~]." flagp
+			  (spell:spell-root-word idx))
+		 t))))))
+
+;;; Get-Word-Correction  --  Internal
+;;;
+;;;    Find all known close words to the either unknown or incorrectly
+;;; spelled word we are checking.  Word is the unmunged word, and Folded is
+;;; the uppercased word.  Mark is a mark which points to the beginning of
+;;; the offending word.  Return True if we successfully corrected the word.
+;;;
+(defun get-word-correction (mark word folded)
+  (let ((close-words (spell:spell-collect-close-words folded)))
+    (declare (list close-words))
+    (if close-words
+	(with-pop-up-display (s :height 3)
+	  (do ((i 0 (1+ i))
+	       (words close-words (cdr words)))
+	      ((null words))
+	    (format s "~36R=~A " i (car words)))
+	  (finish-output s)
+	  (let* ((key-event (prompt-for-key-event
+			     :prompt "Correction choice: "))
+		 (num (digit-char-p (ext:key-event-char key-event) 36)))
+	    (cond ((not num) (return-from get-word-correction nil))
+		  ((> num (length close-words))
+		   (editor-error "Choice out of range."))
+		  (t
+		   (let ((s (nth num close-words)))
+		     (setf (gethash folded *spelling-corrections*) s)
+		     (undoable-replace-word mark word s)))))
+	  (return-from get-word-correction t))
+	(with-pop-up-display (s :height 1)
+	  (write-line "No corrections found." s)
+	  nil))))
+
+
+;;; Undoable-Replace-Word  --  Internal
+;;;
+;;;    Like Spell-Replace-Word, but makes annotations in buffer local variables
+;;; so that "Undo Last Spelling Correction" can undo it.
+;;;
+(defun undoable-replace-word (mark old new)
+  (unless (hemlock-bound-p 'last-spelling-correction-mark)
+    (let ((buffer (current-buffer)))
+      (defhvar "Last Spelling Correction Mark"
+	"This variable holds a park pointing to the last spelling correction."
+	:buffer buffer  :value (copy-mark (buffer-start-mark buffer)))
+      (defhvar "Last Spelling Correction Words"
+	"The replacement done for the last correction: (new . old)."
+	:buffer buffer  :value nil)))
+  (move-mark (value last-spelling-correction-mark) mark)
+  (setf (value last-spelling-correction-words) (cons new old))
+  (spell-replace-word mark old new))
+
+
+
+;;;; Buffer Correction
+
+(defvar *spell-word-characters*
+  (make-array char-code-limit :element-type 'bit  :initial-element 0)
+  "Characters that are legal in a word for spelling checking purposes.")
+
+(do-alpha-chars (c :both)
+  (setf (sbit *spell-word-characters* (char-code c)) 1))
+(setf (sbit *spell-word-characters* (char-code #\')) 1)
+
+
+(defcommand "Correct Buffer Spelling" (p)
+  "Correct spelling over whole buffer.  A log of the found misspellings is
+   kept in the buffer \"Spell Corrections\".  For each unknown word the
+   user may accept it, insert it in the dictionary, correct its spelling
+   with one of the offered possibilities, replace the word with a user
+   supplied word, or go into a recursive edit.  Words may be added to the
+   dictionary in advance from a text file (see the command \"Augment
+   Spelling Dictionary\")."
+  "Correct spelling over whole buffer."
+  (declare (ignore p))
+  (clrhash *ignored-misspellings*)
+  (let* ((buffer (current-buffer))
+	 (log (or (make-buffer "Spelling Corrections")
+		  (getstring "Spelling Corrections" *buffer-names*)))
+	 (point (buffer-end (buffer-point log)))
+	 (*standard-output* (make-hemlock-output-stream point))
+	 (window (or (car (buffer-windows log)) (make-window point))))
+    (format t "~&Starting spelling checking of buffer ~S.~2%"
+	    (buffer-name buffer))
+    (spell:maybe-read-spell-dictionary)
+    (correct-buffer-spelling buffer window)
+    (delete-window window)
+    (close *standard-output*)))
+
+;;; CORRECT-BUFFER-SPELLING scans through buffer a line at a time, grabbing the
+;;; each line's string and breaking it up into words using the
+;;; *spell-word-characters* mask.  We try the spelling of each word, and if it
+;;; is unknown, we call FIX-WORD and resynchronize when it returns.
+;;;
+(defun correct-buffer-spelling (buffer window)
+  (do ((line (mark-line (buffer-start-mark buffer)) (line-next line))
+       (info (if (hemlock-bound-p 'spell-information :buffer buffer)
+		 (variable-value 'spell-information :buffer buffer)
+		 (value spell-information)))
+       (mask *spell-word-characters*)
+       (word (make-string spell:max-entry-length)))
+      ((null line))
+    (declare (simple-bit-vector mask) (simple-string word))
+    (block line
+      (let* ((string (line-string line))
+	     (length (length string)))
+	(declare (simple-string string))
+	(do ((start 0 (or skip-apostrophes end))
+	     (skip-apostrophes nil nil)
+	     end)
+	    (nil)
+	  ;;
+	  ;; Find word start.
+	  (loop
+	    (when (= start length) (return-from line))
+	    (when (/= (bit mask (char-code (schar string start))) 0) (return))
+	    (incf start))
+	  ;;
+	  ;; Find the end.
+	  (setq end (1+ start))
+	  (loop
+	    (when (= end length) (return))
+	    (when (zerop (bit mask (char-code (schar string end)))) (return))
+	    (incf end))
+	  (multiple-value-setq (end skip-apostrophes)
+	    (correct-buffer-word-end string start end))
+	  ;;
+	  ;; Check word.
+	  (let ((word-len (- end start)))
+	    (cond
+	     ((= word-len 1))
+	     ((> word-len spell:max-entry-length)
+	      (format t "Not checking ~S -- too long for dictionary.~2%"
+		      word))
+	     (t
+	      ;;
+	      ;; Copy the word and uppercase it.
+	      (do* ((i (1- end) (1- i))
+		    (j (1- word-len) (1- j)))
+		   ((zerop j)
+		    (setf (schar word 0) (char-upcase (schar string i))))
+		(setf (schar word j) (char-upcase (schar string i))))
+	      (unless (spell:spell-try-word word word-len)
+		(move-to-position (current-point) start line)
+		(fix-word (subseq word 0 word-len) (subseq string start end)
+			  window info)
+		(let ((point (current-point)))
+		  (setq end (mark-charpos point)
+			line (mark-line point)
+			string (line-string line)
+			length (length string))))))))))))
+
+;;; CORRECT-BUFFER-WORD-END takes a line string from CORRECT-BUFFER-SPELLING, a
+;;; start, and a end.  It places end to exclude from the word apostrophes used
+;;; for quotation marks, possessives, and funny plurals (e.g., A's and AND's).
+;;; Every word potentially can be followed by "'s", and any clown can use the
+;;; `` '' Scribe ligature.  This returns the value to use for end of the word
+;;; and the value to use as the end when continuing to find the next word in
+;;; string.
+;;;
+(defun correct-buffer-word-end (string start end)
+  (cond ((and (> (- end start) 2)
+	      (char= (char-upcase (schar string (1- end))) #\S)
+	      (char= (schar string (- end 2)) #\'))
+	 ;; Use roots of possessives and funny plurals (e.g., A's and AND's).
+	 (values (- end 2) end))
+	(t
+	 ;; Maybe backup over apostrophes used for quotation marks.
+	 (do ((i (1- end) (1- i)))
+	     ((= i start) (values end end))
+	   (when (char/= (schar string i) #\')
+	     (return (values (1+ i) end)))))))
+
+;;; Fix-Word  --  Internal
+;;;
+;;;    Handles the case where the word has a known correction.  If is does
+;;; not then call Correct-Buffer-Word-Not-Found.  In either case, the
+;;; point is left at the place to resume checking.
+;;;
+(defun fix-word (word unfolded-word window info)
+  (declare (simple-string word unfolded-word))
+  (let ((correction (gethash word *spelling-corrections*))
+	(mark (current-point)))
+    (cond (correction
+	   (format t "Replacing ~S with ~S.~%" unfolded-word correction)
+	   (spell-replace-word mark unfolded-word correction))
+	  ((and (value spell-ignore-uppercase)
+		(every #'upper-case-p unfolded-word))
+	   (character-offset mark (length word))
+	   (unless (gethash word *ignored-misspellings*)
+	     (setf (gethash word *ignored-misspellings*) t)
+	     (format t "Ignoring ~S.~%" unfolded-word)))
+	  (t
+	   (correct-buffer-word-not-found word unfolded-word window info)))))
+
+(defun correct-buffer-word-not-found (word unfolded-word window info)
+  (declare (simple-string word unfolded-word))
+  (let* ((close-words (spell:spell-collect-close-words word))
+	 (close-words-len (length (the list close-words)))
+	 (mark (current-point))
+	 (wordlen (length word)))
+    (format t "Unknown word: ~A~%" word)
+    (cond (close-words
+	   (format t "~[~;A~:;Some~]~:* possible correction~[~; is~:;s are~]: "
+		   close-words-len)
+	   (if (= close-words-len 1)
+	       (write-line (car close-words))
+	       (let ((n 0))
+		 (dolist (w close-words (terpri))
+		   (format t "~36R=~A " n w)
+		   (incf n)))))
+	  (t
+	   (write-line "No correction possibilities found.")))
+    (let ((point (buffer-point (window-buffer window))))
+      (unless (displayed-p point window)
+	(center-window window point)))
+    (command-case
+       (:prompt "Action: "
+        :help "Type a single letter command, or help character for help."
+        :change-window nil)
+      (#\i "Insert unknown word into dictionary for future lookup."
+	 (spell:spell-add-entry word)
+	 (push word (spell-info-insertions info))
+	 (format t "~S added to dictionary.~2%" word))
+      (#\c "Correct the unknown word with possible correct spellings."
+	 (unless close-words
+	   (write-line "There are no possible corrections.")
+	   (reprompt))
+	 (let ((num (if (= close-words-len 1) 0
+			(digit-char-p (ext:key-event-char
+				       (prompt-for-key-event
+					:prompt "Correction choice: "))
+				      36))))
+	   (unless num (reprompt))
+	   (when (> num close-words-len)
+	     (beep)
+	     (write-line "Response out of range.")
+	     (reprompt))
+	   (let ((choice (nth num close-words)))
+	     (setf (gethash word *spelling-corrections*) choice)
+	     (spell-replace-word mark unfolded-word choice)))
+	 (terpri))
+      (#\a "Accept the word as correct (that is, ignore it)."
+	 (character-offset mark wordlen))
+      (#\r "Replace the unknown word with a supplied replacement."
+	 (let ((s (prompt-for-string
+		   :prompt "Replacement Word: "
+		   :default unfolded-word
+		   :help "String to replace the unknown word with.")))
+	   (setf (gethash word *spelling-corrections*) s)
+	   (spell-replace-word mark unfolded-word s))
+	 (terpri))
+      (:recursive-edit
+       "Go into a recursive edit and resume correction where the point is left."
+       (do-recursive-edit)))))
+
+;;; Spell-Replace-Word  --  Internal
+;;;
+;;;    Replaces Old with New, starting at Mark.  The case of Old is used
+;;; to derive the new case.
+;;;
+(defun spell-replace-word (mark old new)
+  (declare (simple-string old new))
+  (let ((res (cond ((lower-case-p (schar old 0))
+		    (string-downcase new))
+		   ((lower-case-p (schar old 1))
+		    (let ((res (string-downcase new)))
+		      (setf (char res 0) (char-upcase (char res 0)))
+		      res))
+		   (t
+		    (string-upcase new)))))
+    (with-mark ((m mark :left-inserting))
+      (delete-characters m (length old))
+      (insert-string m res))))
+
+
+
+;;;; User Spelling Dictionaries.
+
+(defvar *pathname-to-spell-info* (make-hash-table :test #'equal)
+  "This maps dictionary files to spelling information.")
+
+(defhvar "Spell Information"
+  "This is the information about a spelling dictionary and its incremental
+   insertions."
+  :value (make-spell-info nil))
+
+(define-file-option "Dictionary" (buffer file)
+  (let* ((dict (merge-pathnames
+		file
+		(make-pathname :defaults (buffer-default-pathname buffer)
+			       :type "dict")))
+	 (dictp (probe-file dict)))
+    (if dictp
+	(set-buffer-spelling-dictionary-command nil dictp buffer)
+	(loud-message "Couldn't find dictionary ~A." (namestring dict)))))
+
+;;; SAVE-DICTIONARY-ON-WRITE is on the "Write File Hook" in buffers with
+;;; the "dictionary" file option.
+;;; 
+(defun save-dictionary-on-write (buffer)
+  (when (hemlock-bound-p 'spell-information :buffer buffer)
+    (save-spelling-insertions
+     (variable-value 'spell-information :buffer buffer))))
+
+
+(defcommand "Save Incremental Spelling Insertions" (p)
+  "Append incremental spelling dictionary insertions to a file.  The file
+   is prompted for unless \"Set Buffer Spelling Dictionary\" has been
+   executed in the buffer."
+  "Append incremental spelling dictionary insertions to a file."
+  (declare (ignore p))
+  (let* ((info (value spell-information))
+	 (file (or (spell-info-pathname info)
+		   (value default-user-spelling-dictionary)
+		   (prompt-for-file
+		    :prompt "Dictionary File: "
+		    :default (dictionary-name-default)
+		    :must-exist nil
+		    :help
+ "Name of the dictionary file to append dictionary insertions to."))))
+    (save-spelling-insertions info file)
+    (let* ((ginfo (variable-value 'spell-information :global))
+	   (insertions (spell-info-insertions ginfo)))
+      (when (and insertions
+		 (prompt-for-y-or-n
+		  :prompt
+		  `("Global spelling insertions exist.~%~
+		     Save these to ~A also? "
+		    ,(namestring file)
+		  :default t
+		  :default-string "Y"))
+	(save-spelling-insertions ginfo file))))))
+
+(defun save-spelling-insertions (info &optional
+				      (name (spell-info-pathname info)))
+  (when (spell-info-insertions info)
+    (with-open-file (stream name
+			    :direction :output :element-type 'base-char
+			    :if-exists :append :if-does-not-exist :create)
+      (dolist (w (spell-info-insertions info))
+	(write-line w stream)))
+    (setf (spell-info-insertions info) ())
+    (message "Incremental spelling insertions for ~A written."
+	     (namestring name))))
+
+(defcommand "Set Buffer Spelling Dictionary" (p &optional file buffer)
+  "Prompts for the dictionary file to associate with the current buffer.
+   If this file has not been read for any other buffer, then it is read.
+   Incremental spelling insertions from this buffer can be appended to
+   this file with \"Save Incremental Spelling Insertions\"."
+  "Sets the buffer's spelling dictionary and reads it if necessary."
+  (declare (ignore p))
+  (maybe-read-default-user-spelling-dictionary)
+  (let* ((file (truename (or file
+			     (prompt-for-file
+			      :prompt "Dictionary File: "
+			      :default (dictionary-name-default)
+			      :help
+ "Name of the dictionary file to add into the current dictionary."))))
+	 (file-name (namestring file))
+	 (spell-info-p (gethash file-name *pathname-to-spell-info*))
+	 (spell-info (or spell-info-p (make-spell-info file)))
+	 (buffer (or buffer (current-buffer))))
+    (defhvar "Spell Information"
+      "This is the information about a spelling dictionary and its incremental
+       insertions."
+      :value spell-info :buffer buffer)
+    (add-hook write-file-hook 'save-dictionary-on-write)
+    (unless spell-info-p
+      (setf (gethash file-name *pathname-to-spell-info*) spell-info)
+      (read-spelling-dictionary-command nil file))))
+
+(defcommand "Read Spelling Dictionary" (p &optional file)
+  "Adds entries to the dictionary from a file in the following format:
+   
+      entry1/flag1/flag2/flag3
+      entry2
+      entry3/flag1/flag2/flag3/flag4/flag5.
+
+   The flags are single letter indicators of legal suffixes for the entry;
+   the available flags and their correct use may be found at the beginning
+   of spell-correct.lisp in the Hemlock sources.  There must be exactly one 
+   entry per line, and each line must be flushleft."
+  "Add entries to the dictionary from a text file in a specified format."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (spell:spell-read-dictionary
+   (or file
+       (prompt-for-file
+	:prompt "Dictionary File: "
+	:default (dictionary-name-default)
+	:help
+	"Name of the dictionary file to add into the current dictionary."))))
+
+(defun dictionary-name-default ()
+  (make-pathname :defaults (buffer-default-pathname (current-buffer))
+		 :type "dict"))
+
+(defcommand "Add Word to Spelling Dictionary" (p)
+  "Add the previous word to the spelling dictionary."
+  "Add the previous word to the spelling dictionary."
+  (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (let ((word (region-to-string (spell-previous-word (current-point) nil))))
+    ;;
+    ;; SPELL:SPELL-ADD-ENTRY destructively uppercases word.
+    (when (spell:spell-add-entry word)
+      (message "Word ~(~S~) added to the spelling dictionary." word)
+      (push word (spell-info-insertions (value spell-information))))))
+
+(defcommand "Remove Word from Spelling Dictionary" (p)
+  "Prompts for word to remove from the spelling dictionary."
+  "Prompts for word to remove from the spelling dictionary."
+   (declare (ignore p))
+  (spell:maybe-read-spell-dictionary)
+  (let* ((word (prompt-for-string
+		:prompt "Word to remove from spelling dictionary: "
+		:trim t))
+	 (upword (string-upcase word)))
+    (declare (simple-string word))
+    (multiple-value-bind (index flagp)
+			 (spell:spell-try-word upword (length word))
+      (unless index
+	(editor-error "~A not in dictionary." upword))
+      (if flagp
+	  (remove-spelling-word upword)
+	  (let ((flags (spell:spell-root-flags index)))
+	    (when (or (not flags)
+		      (prompt-for-y-or-n
+		       :prompt
+ `("Deleting ~A also removes words formed from this root and these flags: ~%  ~
+    ~S.~%~
+    Delete word anyway? "
+   ,word ,flags)
+		       :default t
+		       :default-string "Y"))
+	      (remove-spelling-word upword)))))))
+
+;;; REMOVE-SPELLING-WORD removes the uppercase word word from the spelling
+;;; dictionary and from the spelling informations incremental insertions list.
+;;; 
+(defun remove-spelling-word (word)
+  (let ((info (value spell-information)))
+    (spell:spell-remove-entry word)
+    (setf (spell-info-insertions info)
+	  (delete word (spell-info-insertions info) :test #'string=))))
+
+(defcommand "List Incremental Spelling Insertions" (p)
+  "Display the incremental spelling insertions for the current buffer's
+   associated spelling dictionary file."
+  "Display the incremental spelling insertions for the current buffer's
+   associated spelling dictionary file."
+  (declare (ignore p))
+  (let* ((info (value spell-information))
+	 (file (spell-info-pathname info))
+	 (insertions (spell-info-insertions info)))
+    (declare (list insertions))
+    (with-pop-up-display (s :height (1+ (length insertions)))
+      (if file
+	  (format s "Incremental spelling insertions for dictionary ~A:~%"
+		  (namestring file))
+	  (write-line "Global incremental spelling insertions:" s))
+      (dolist (w insertions)
+	(write-line w s)))))
+
+
+
+
+;;;; Utilities for above stuff.
+
+;;; SPELL-PREVIOUS-WORD returns as a region the current or previous word, using
+;;; the spell word definition.  If there is no such word, return nil.  If end-p
+;;; is non-nil, then mark ends the word even if there is a non-delimiter
+;;; character after it.
+;;;
+;;; Actually, if mark is between the first character of a word and a
+;;; non-spell-word characer, it is considered to be in that word even though
+;;; that word is after the mark.  This is because Hemlock's cursor is always
+;;; displayed over the next character, so users tend to think of a cursor
+;;; displayed on the first character of a word as being in that word instead of
+;;; before it.
+;;;
+(defun spell-previous-word (mark end-p)
+  (with-mark ((point mark)
+	      (mark mark))
+    (cond ((or end-p
+	       (zerop (character-attribute :spell-word-character
+					   (next-character point))))
+	   (unless (reverse-find-attribute mark :spell-word-character)
+	     (return-from spell-previous-word nil))
+	   (move-mark point mark)
+	   (reverse-find-attribute point :spell-word-character #'zerop))
+	  (t
+	   (find-attribute mark :spell-word-character #'zerop)
+	   (reverse-find-attribute point :spell-word-character #'zerop)))
+    (cond ((and (> (- (mark-charpos mark) (mark-charpos point)) 2)
+		(char= (char-upcase (previous-character mark)) #\S)
+		(char= (prog1 (previous-character (mark-before mark))
+			 (mark-after mark))
+		       #\'))
+	   ;; Use roots of possessives and funny plurals (e.g., A's and AND's).
+	   (character-offset mark -2))
+	  (t
+	   ;; Maybe backup over apostrophes used for quotation marks.
+	   (loop
+	     (when (mark= point mark) (return-from spell-previous-word nil))
+	     (when (char/= (previous-character mark) #\') (return))
+	     (mark-before mark))))
+    (region point mark)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/srccom.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/srccom.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/srccom.lisp	(revision 13309)
@@ -0,0 +1,484 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Source comparison stuff for Hemlock.
+;;;
+;;; Written by Skef Wholey and Bill Chiles.
+;;;
+
+(in-package :hemlock)
+
+(defhvar "Source Compare Ignore Extra Newlines"
+  "If T, Source Compare and Source Merge will treat all groups of newlines
+  as if they were a single newline.  The default is T."
+  :value t)
+
+(defhvar "Source Compare Ignore Case"
+  "If T, Source Compare and Source Merge will treat all letters as if they
+  were of the same case.  The default is Nil."
+  :value nil)
+
+(defhvar "Source Compare Ignore Indentation"
+  "This determines whether comparisons ignore initial whitespace on a line or
+   use the whole line."
+  :value nil)
+
+(defhvar "Source Compare Number of Lines"
+  "This variable controls the number of lines Source Compare and Source Merge
+  will compare when resyncronizing after a difference has been encountered.
+  The default is 3."
+  :value 3)
+
+(defhvar "Source Compare Default Destination"
+  "This is a sticky-default buffer name to offer when comparison commands prompt
+   for a results buffer."
+  :value "Differences")
+
+
+(defcommand "Buffer Changes" (p)
+  "Generate a comparison of the current buffer with its file on disk."
+  "Generate a comparison of the current buffer with its file on disk."
+  (declare (ignore p))
+  (let ((buffer (current-buffer)))
+    (unless (buffer-pathname buffer)
+      (editor-error "No pathname associated with buffer."))
+    (let ((other-buffer (or (getstring "Buffer Changes File" *buffer-names*)
+			    (make-buffer "Buffer Changes File")))
+	  (result-buffer (or (getstring "Buffer Changes Result" *buffer-names*)
+			     (make-buffer "Buffer Changes Result"))))
+      (visit-file-command nil (buffer-pathname buffer) other-buffer)
+      (delete-region (buffer-region result-buffer))
+      (compare-buffers-command nil buffer other-buffer result-buffer)
+      (delete-buffer other-buffer))))
+
+;;; "Compare Buffers" creates two temporary buffers when there is a prefix.
+;;; These get deleted when we're done.  Buffer-a and Buffer-b are used for
+;;; names is banners in either case.
+;;; 
+(defcommand "Compare Buffers" (p &optional buffer-a buffer-b dest-buffer)
+  "Performs a source comparison on two specified buffers.  If the prefix
+   argument is supplied, only compare the regions in the buffer."
+  "Performs a source comparison on two specified buffers, Buffer-A and
+   Buffer-B, putting the result of the comparison into the Dest-Buffer.
+   If the prefix argument is supplied, only compare the regions in the
+   buffer."
+  (srccom-choose-comparison-functions)
+  (multiple-value-bind (buffer-a buffer-b dest-point
+		        delete-buffer-a delete-buffer-b)
+		       (get-srccom-buffers "Compare buffer: " buffer-a buffer-b
+					   dest-buffer p)
+    (with-output-to-mark (log dest-point)
+      (format log "Comparison of ~A and ~A.~%~%"
+	      (buffer-name buffer-a) (buffer-name buffer-b))
+      (with-mark ((mark-a (buffer-start-mark (or delete-buffer-a buffer-a)))
+		  (mark-b (buffer-start-mark (or delete-buffer-b buffer-b))))
+	(loop
+	  (multiple-value-bind (diff-a diff-b)
+			       (srccom-find-difference mark-a mark-b)
+	    (when (null diff-a) (return nil))
+	    (format log "**** Buffer ~A:~%" (buffer-name buffer-a))
+	    (insert-region dest-point diff-a)
+	    (format log "**** Buffer ~A:~%" (buffer-name buffer-b))
+	    (insert-region dest-point diff-b)
+	    (format log "***************~%~%")
+	    (move-mark mark-a (region-end diff-a))
+	    (move-mark mark-b (region-end diff-b))
+	    (unless (line-offset mark-a 1) (return))
+	    (unless (line-offset mark-b 1) (return)))))
+	(format log "Done.~%"))
+    (when delete-buffer-a
+      (delete-buffer delete-buffer-a)
+      (delete-buffer delete-buffer-b))))
+
+
+;;; "Merge Buffers" creates two temporary buffers when there is a prefix.
+;;; These get deleted when we're done.  Buffer-a and Buffer-b are used for
+;;; names is banners in either case.
+;;; 
+(defcommand "Merge Buffers" (p &optional buffer-a buffer-b dest-buffer)
+  "Performs a source merge on two specified buffers.  If the prefix
+   argument is supplied, only compare the regions in the buffer."
+  "Performs a source merge on two specified buffers, Buffer-A and Buffer-B,
+   putting the resulting text into the Dest-Buffer.  If the prefix argument
+   is supplied, only compare the regions in the buffer."
+  (srccom-choose-comparison-functions)
+  (multiple-value-bind (buffer-a buffer-b dest-point
+		        delete-buffer-a delete-buffer-b)
+		       (get-srccom-buffers "Merge buffer: " buffer-a buffer-b
+					   dest-buffer p)
+    (with-output-to-mark (stream dest-point)
+      (let ((region-a (buffer-region (or delete-buffer-a buffer-a))))
+	(with-mark ((temp-a (region-start region-a) :right-inserting)
+		    (temp-b dest-point :right-inserting)
+		    (mark-a (region-start region-a))
+		    (mark-b (region-start
+			     (buffer-region (or delete-buffer-b buffer-b)))))
+	  (clear-echo-area)
+	  (loop
+	    (multiple-value-bind (diff-a diff-b)
+				 (srccom-find-difference mark-a mark-b)
+	      (when (null diff-a)
+		(insert-region dest-point (region temp-a (region-end region-a)))
+		(return nil))
+	      ;; Copy the part that's the same.
+	      (insert-region dest-point (region temp-a (region-start diff-a)))
+	      ;; Put both versions in the buffer, and prompt for which one to use.
+	      (move-mark temp-a dest-point)
+	      (format stream "~%**** Buffer ~A (1):~%" (buffer-name buffer-a))
+	      (insert-region dest-point diff-a)
+	      (move-mark temp-b dest-point)
+	      (format stream "~%**** Buffer ~A (2):~%" (buffer-name buffer-b))
+	      (insert-region dest-point diff-b)
+	      (command-case
+		  (:prompt "Merge Buffers: "
+		   :help "Type one of these characters to say how to merge:") 
+		(#\1 "Use the text from buffer 1."
+		     (delete-region (region temp-b dest-point))
+		     (delete-characters temp-a)
+		     (delete-region
+		      (region temp-a
+			      (line-start temp-b
+					  (line-next (mark-line temp-a))))))
+		(#\2 "Use the text from buffer 2."
+		     (delete-region (region temp-a temp-b))
+		     (delete-characters temp-b)
+		     (delete-region
+		      (region temp-b
+			      (line-start temp-a
+					  (line-next (mark-line temp-b))))))
+		(#\b "Insert both versions with **** MERGE LOSSAGE **** around them."
+		     (insert-string temp-a "
+		     **** MERGE LOSSAGE ****")
+		     (insert-string dest-point "
+		     **** END OF MERGE LOSSAGE ****"))
+		(#\a "Align window at start of difference display."
+		     (line-start
+		      (move-mark
+		       (window-display-start
+			(car (buffer-windows (line-buffer (mark-line temp-a)))))
+		       temp-a))
+		     (reprompt))
+		(:recursive-edit "Enter a recursive edit."
+				 (with-mark ((save dest-point))
+				   (do-recursive-edit)
+				   (move-mark dest-point save))
+				 (reprompt)))
+	      (redisplay)
+	      (move-mark mark-a (region-end diff-a))
+	      (move-mark mark-b (region-end diff-b))
+	      (move-mark temp-a mark-a)
+	      (unless (line-offset mark-a 1) (return))
+	      (unless (line-offset mark-b 1) (return))))))
+      (message "Done."))
+    (when delete-buffer-a
+      (delete-buffer delete-buffer-a)
+      (delete-buffer delete-buffer-b))))
+
+(defun get-srccom-buffers (first-prompt buffer-a buffer-b dest-buffer p)
+  (unless buffer-a
+    (setf buffer-a (prompt-for-buffer :prompt first-prompt
+				      :must-exist t
+				      :default (current-buffer))))
+  (unless buffer-b
+    (setf buffer-b (prompt-for-buffer :prompt "With buffer: "
+				      :must-exist t
+				      :default (previous-buffer))))
+  (unless dest-buffer
+    (setf dest-buffer
+	  (prompt-for-buffer :prompt "Putting results in buffer: "
+			     :must-exist nil
+			     :default-string
+			     (value source-compare-default-destination))))
+  (if (stringp dest-buffer)
+      (setf dest-buffer (make-buffer dest-buffer))
+      (buffer-end (buffer-point dest-buffer)))
+  (setf (value source-compare-default-destination) (buffer-name dest-buffer))
+  (change-to-buffer dest-buffer)
+  (let* ((alt-buffer-a (if p (make-buffer (prin1-to-string (gensym)))))
+	 (alt-buffer-b (if alt-buffer-a
+			   (make-buffer (prin1-to-string (gensym))))))
+    (when alt-buffer-a
+      (ninsert-region (buffer-point alt-buffer-a)
+		      (copy-region (if (mark< (buffer-point buffer-a)
+					      (buffer-mark buffer-a))
+				       (region (buffer-point buffer-a)
+					       (buffer-mark buffer-a))
+				       (region (buffer-mark buffer-a)
+					       (buffer-point buffer-a)))))
+      (ninsert-region (buffer-point alt-buffer-b)
+		      (copy-region (if (mark< (buffer-point buffer-b)
+					      (buffer-mark buffer-b))
+				       (region (buffer-point buffer-b)
+					       (buffer-mark buffer-b))
+				       (region (buffer-mark buffer-b)
+					       (buffer-point buffer-b))))))
+    (values buffer-a buffer-b (current-point) alt-buffer-a alt-buffer-b)))
+#|
+(defun get-srccom-buffers (first-prompt buffer-a buffer-b dest-buffer p)
+  (unless buffer-a
+    (setf buffer-a (prompt-for-buffer :prompt first-prompt
+				      :must-exist t
+				      :default (current-buffer))))
+  (unless buffer-b
+    (setf buffer-b (prompt-for-buffer :prompt "With buffer: "
+				      :must-exist t
+				      :default (previous-buffer))))
+  (unless dest-buffer
+    (let* ((name (value source-compare-default-destination))
+	   (temp-default (getstring name *buffer-names*))
+	   (default (or temp-default (make-buffer name))))
+      (setf dest-buffer (prompt-for-buffer :prompt "Putting results in buffer: "
+					   :must-exist nil
+					   :default default))
+      ;; Delete the default buffer if it did already exist and was not chosen.
+      (unless (or (eq dest-buffer default) temp-default)
+	(delete-buffer default))))
+  (if (stringp dest-buffer)
+      (setf dest-buffer (make-buffer dest-buffer))
+      (buffer-end (buffer-point dest-buffer)))
+  (setf (value source-compare-default-destination) (buffer-name dest-buffer))
+  (change-to-buffer dest-buffer)
+  (let* ((alt-buffer-a (if p (make-buffer (prin1-to-string (gensym)))))
+	 (alt-buffer-b (if alt-buffer-a
+			   (make-buffer (prin1-to-string (gensym))))))
+    (when alt-buffer-a
+      (ninsert-region (buffer-point alt-buffer-a)
+		      (copy-region (if (mark< (buffer-point buffer-a)
+					      (buffer-mark buffer-a))
+				       (region (buffer-point buffer-a)
+					       (buffer-mark buffer-a))
+				       (region (buffer-mark buffer-a)
+					       (buffer-point buffer-a)))))
+      (ninsert-region (buffer-point alt-buffer-b)
+		      (copy-region (if (mark< (buffer-point buffer-b)
+					      (buffer-mark buffer-b))
+				       (region (buffer-point buffer-b)
+					       (buffer-mark buffer-b))
+				       (region (buffer-mark buffer-b)
+					       (buffer-point buffer-b))))))
+    (values buffer-a buffer-b (current-point) alt-buffer-a alt-buffer-b)))
+|#
+
+
+
+;;;; Functions that find the differences between two buffers.
+
+(defun srccom-find-difference (mark-a mark-b)
+  "Returns as multiple values two regions of text that are different in the
+  lines following Mark-A and Mark-B.  If no difference is encountered, Nil
+  is returned."
+  (multiple-value-bind (diff-a diff-b)
+		       (srccom-different-lines mark-a mark-b)
+    (when diff-a
+      (multiple-value-bind (same-a same-b)
+			   (srccom-similar-lines diff-a diff-b)
+	(values (region diff-a same-a)
+		(region diff-b same-b))))))
+
+;;; These are set by SRCCOM-CHOOSE-COMPARISON-FUNCTIONS depending on something.
+;;;
+(defvar *srccom-line=* nil)
+(defvar *srccom-line-next* nil)
+
+(defun srccom-different-lines (mark-a mark-b)
+  "Returns as multiple values two marks pointing to the first different lines
+  found after Mark-A and Mark-B.  Nil is returned if no different lines are
+  found."
+  (do ((line-a (mark-line mark-a) (funcall *srccom-line-next* line-a))
+       (mark-a (copy-mark mark-a))
+       (line-b (mark-line mark-b) (funcall *srccom-line-next* line-b))
+       (mark-b (copy-mark mark-b)))
+      (())
+    (cond ((null line-a)
+	   (return (if line-b
+		       (values mark-a mark-b))))
+	  ((null line-b)
+	   (return (values mark-a mark-b))))
+    (line-start mark-a line-a)
+    (line-start mark-b line-b)
+    (unless (funcall *srccom-line=* line-a line-b)
+      (return (values mark-a mark-b)))))
+
+(defun srccom-similar-lines (mark-a mark-b)
+  "Returns as multiple values two marks pointing to the first similar lines
+  found after Mark-A and Mark-B."
+  (do ((line-a (mark-line mark-a) (funcall *srccom-line-next* line-a))
+       (cmark-a (copy-mark mark-a))
+       (line-b (mark-line mark-b) (funcall *srccom-line-next* line-b))
+       (cmark-b (copy-mark mark-b))
+       (temp)
+       (window-size (value source-compare-number-of-lines)))
+      (())
+    ;; If we hit the end of one buffer, then the difference extends to the end
+    ;; of both buffers.
+    (if (or (null line-a) (null line-b))
+	(return
+	 (values
+	  (buffer-end-mark (line-buffer (mark-line mark-a)))
+	  (buffer-end-mark (line-buffer (mark-line mark-b))))))
+    (line-start cmark-a line-a)
+    (line-start cmark-b line-b)
+    ;; Three cases:
+    ;;  1] Difference will be same length in A and B.  If so, Line-A = Line-B.
+    ;;  2] Difference will be longer in A.  If so, Line-A = something in B.
+    ;;  3] Difference will be longer in B.  If so, Line-B = something in A.
+    (cond ((and (funcall *srccom-line=* line-a line-b)
+		(srccom-check-window line-a line-b window-size))
+	   (return (values cmark-a cmark-b)))
+	  ((and (setq temp (srccom-line-in line-a mark-b cmark-b))
+		(srccom-check-window line-a temp window-size))
+	   (return (values cmark-a (line-start cmark-b temp))))
+	  ((and (setq temp (srccom-line-in line-b mark-a cmark-a))
+		(srccom-check-window temp line-b window-size))
+	   (return (values (line-start cmark-a temp) cmark-b))))))
+
+(defun srccom-line-in (line start end)
+  "Checks to see if there is a Line Srccom-Line= to the given Line in the
+  region delimited by the Start and End marks.  Returns that line if so, or
+  Nil if there is none."
+  (do ((current (mark-line start) (funcall *srccom-line-next* current))
+       (terminus (funcall *srccom-line-next* (mark-line end))))
+      ((eq current terminus) nil)
+    (if (funcall *srccom-line=* line current)
+	(return current))))
+
+(defun srccom-check-window (line-a line-b count)
+  "Verifies that the Count lines following Line-A and Line-B are Srccom-Line=.
+  If so, returns T.  Otherwise returns Nil."
+  (do ((line-a line-a (funcall *srccom-line-next* line-a))
+       (line-b line-b (funcall *srccom-line-next* line-b))
+       (index 0 (1+ index)))
+      ((= index count) t)
+    (if (not (funcall *srccom-line=* line-a line-b))
+	(return nil))))
+
+
+
+
+;;;; Functions that control the comparison of text.
+
+;;; SRCCOM-CHOOSE-COMPARISON-FUNCTIONS -- Internal.
+;;;
+;;; This initializes utility functions for comparison commands based on Hemlock
+;;; variables.
+;;;
+(defun srccom-choose-comparison-functions ()
+  (setf *srccom-line=*
+	(if (value source-compare-ignore-case)
+	    (if (value source-compare-ignore-indentation)
+		#'srccom-ignore-case-and-indentation-line=
+		#'srccom-case-insensitive-line=)
+	    (if (value source-compare-ignore-indentation)
+		#'srccom-ignore-indentation-case-sensitive-line=
+		#'srccom-case-sensitive-line=)))
+  (setf *srccom-line-next*
+	(if (value source-compare-ignore-extra-newlines)
+	    #'srccom-line-next-ignoring-extra-newlines
+	    #'line-next)))
+#|
+(defun srccom-choose-comparison-functions ()
+  "This function should be called by a ``top level'' source compare utility
+  to initialize the lower-level functions that compare text."
+  (setf *srccom-line=*
+	(if (value source-compare-ignore-case)
+	    #'srccom-case-insensitive-line=
+	    #'srccom-case-sensitive-line=))
+  (setf *srccom-line-next*
+	(if (value source-compare-ignore-extra-newlines)
+	    #'srccom-line-next-ignoring-extra-newlines
+	    #'line-next)))
+|#
+
+;;; SRCCOM-LINE-NEXT-IGNORING-EXTRA-NEWLINES -- Internal.
+;;;
+;;; This is the value of *srccom-line-next* when "Source Compare Ignore Extra
+;;; Newlines" is non-nil.
+;;;
+(defun srccom-line-next-ignoring-extra-newlines (line)
+  (if (null line) nil
+      (do ((line (line-next line) (line-next line)))
+	  ((or (null line) (not (blank-line-p line))) line))))
+
+;;; SRCCOM-IGNORE-CASE-AND-INDENTATION-LINE=	   -- Internal.
+;;; SRCCOM-CASE-INSENSITIVE-LINE=		   -- Internal.
+;;; SRCCOM-IGNORE-INDENTATION-CASE-SENSITIVE-LINE= -- Internal.
+;;; SRCCOM-CASE-SENSITIVE-LINE=			   -- Internal.
+;;;
+;;; These are the value of *srccom-line-=* depending on the orthogonal values
+;;; of "Source Compare Ignore Case" and "Source Compare Ignore Indentation".
+;;;
+(macrolet ((def-line= (name test &optional ignore-indentation)
+	     `(defun ,name (line-a line-b)
+		(or (eq line-a line-b)		; if they're both NIL
+		    (and line-a
+			 line-b
+			 (let* ((chars-a (line-string line-a))
+				(len-a (length chars-a))
+				(chars-b (line-string line-b))
+				(len-b (length chars-b)))
+			   (declare (simple-string chars-a chars-b))
+			   (cond
+			    ((and (= len-a len-b)
+				  (,test chars-a chars-b)))
+			    ,@(if ignore-indentation
+				  `((t
+				     (flet ((frob (chars len)
+					      (dotimes (i len nil)
+						(let ((char (schar chars i)))
+						  (unless
+						      (or (char= char #\space)
+							  (char= char #\tab))
+						    (return i))))))
+				       (let ((i (frob chars-a len-a))
+					     (j (frob chars-b len-b)))
+					 (if (and i j)
+					     (,test chars-a chars-b
+						    :start1 i :end1 len-a
+						    :start2 j :end2 len-b)
+					     )))))))))))))
+
+  (def-line= srccom-ignore-case-and-indentation-line= string-equal t)
+
+  (def-line= srccom-case-insensitive-line= string-equal)
+
+  (def-line= srccom-ignore-indentation-case-sensitive-line= string= t)
+
+  (def-line= srccom-case-sensitive-line= string=))
+
+#|
+;;; SRCCOM-CASE-INSENSITIVE-LINE= -- Internal.
+;;;
+;;; Returns t if line-a and line-b contain STRING-EQUAL text.
+;;;
+(defun srccom-case-insensitive-line= (line-a line-b)
+  (or (eq line-a line-b)		; if they're both NIL
+      (and line-a
+	   line-b
+	   (let ((chars-a (line-string line-a))
+		 (chars-b (line-string line-b)))
+	     (declare (simple-string chars-a chars-b))
+	     (and (= (length chars-a) (length chars-b))
+		  (string-equal chars-a chars-b))))))
+
+;;; SRCCOM-CASE-SENSITIVE-LINE= -- Internal.
+;;;
+;;; Returns t if line-a and line-b contain STRING= text.
+;;;
+(defun srccom-case-sensitive-line= (line-a line-b)
+  (or (eq line-a line-b)		; if they're both NIL
+      (and line-a
+	   line-b
+	   (let ((chars-a (line-string line-a))
+		 (chars-b (line-string line-b)))
+	     (declare (simple-string chars-a chars-b))
+	     (and (= (length chars-a) (length chars-b))
+		  (string= chars-a chars-b))))))
+|#
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/ts-buf.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/ts-buf.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/ts-buf.lisp	(revision 13309)
@@ -0,0 +1,318 @@
+;;; -*- Package: Hemlock; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+(hemlock-ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains code for processing input to and output from slaves
+;;; using typescript streams.  It maintains the stuff that hacks on the
+;;; typescript buffer and maintains its state.
+;;;
+;;; Written by William Lott.
+;;;
+
+(in-package :hemlock)
+
+
+(defhvar "Input Wait Alarm"
+  "When non-nil, the user is informed when a typescript buffer goes into
+   an input wait, and it is not visible.  Legal values are :message,
+   :loud-message (the default), and nil."
+  :value :loud-message)
+
+
+
+
+;;;; Structures.
+
+(defstruct (ts-data
+	    (:print-function
+	     (lambda (ts s d)
+	       (declare (ignore ts d))
+	       (write-string "#<TS Data>" s)))
+	    (:constructor
+	     make-ts-data (buffer
+			   &aux
+			   (fill-mark (copy-mark (buffer-end-mark buffer)
+						 :right-inserting)))))
+  buffer		      ; The buffer we are in
+  stream		      ; Stream in the slave.
+  wire			      ; Wire to slave
+  server		      ; Server info struct.
+  fill-mark		      ; Mark where output goes.  This is actually the
+			      ;   "Buffer Input Mark" which is :right-inserting,
+			      ;   and we make sure it is :left-inserting for
+			      ;   inserting output.
+  )
+
+
+
+;;;; Output routines.
+
+;;; TS-BUFFER-OUTPUT-STRING --- internal interface.
+;;;
+;;; Called by the slave to output stuff in the typescript.  Can also be called
+;;; by other random parts of hemlock when they want to output stuff to the
+;;; buffer.  Since this is called for value from the slave, we have to be
+;;; careful about what values we return, so the result can be sent back.  It is
+;;; called for value only as a synchronization thing.
+;;;
+;;; Whenever the output is gratuitous, we want it to go behind the prompt.
+;;; When it's gratuitous, and we're not at the line-start, then we can output
+;;; it normally, but we also make sure we end the output in a newline for
+;;; visibility's sake.
+;;;
+(defun ts-buffer-output-string (ts string &optional gratuitous-p)
+  "Outputs STRING to the typescript described with TS. The output is inserted
+   before the fill-mark and the current input."
+  (when (hemlock.wire:remote-object-p ts)
+    (setf ts (hemlock.wire:remote-object-value ts)))
+  (hemlock-ext:without-interrupts
+    (let ((mark (ts-data-fill-mark ts)))
+      (cond ((and gratuitous-p (not (start-line-p mark)))
+	     (with-mark ((m mark :left-inserting))
+	       (line-start m)
+	       (insert-string m string)
+	       (unless (start-line-p m)
+		 (insert-character m #\newline))))
+	    (t
+	     (setf (mark-kind mark) :left-inserting)
+	     (insert-string mark string)
+	     (when (and gratuitous-p (not (start-line-p mark)))
+	       (insert-character mark #\newline))
+	     (setf (mark-kind mark) :right-inserting)))))
+  (values))
+
+;;; TS-BUFFER-FINISH-OUTPUT --- internal interface.
+;;;
+;;; Redisplays the windows. Used by ts-stream in order to finish-output.
+;;;
+(defun ts-buffer-finish-output (ts)
+  (declare (ignore ts))
+  (redisplay)
+  nil)
+
+;;; TS-BUFFER-CHARPOS --- internal interface.
+;;;
+;;; Used by ts-stream in order to find the charpos.
+;;; 
+(defun ts-buffer-charpos (ts)
+  (mark-charpos (ts-data-fill-mark (if (hemlock.wire:remote-object-p ts)
+				       (hemlock.wire:remote-object-value ts)
+				       ts))))
+
+;;; TS-BUFFER-LINE-LENGTH --- internal interface.
+;;;
+;;; Used by ts-stream to find out the line length.  Returns the width of the
+;;; first window, or 80 if there are no windows.
+;;; 
+(defun ts-buffer-line-length (ts)
+  (let* ((ts (if (hemlock.wire:remote-object-p ts)
+		 (hemlock.wire:remote-object-value ts)
+		ts))
+	 (window (car (buffer-windows (ts-data-buffer ts)))))
+    (if window
+	(window-width window)
+	80))) ; Seems like a good number to me.
+
+
+
+;;;; Input routines
+
+(defun ts-buffer-ask-for-input (remote)
+  (let* ((ts (hemlock.wire:remote-object-value remote))
+	 (buffer (ts-data-buffer ts)))
+    (unless (buffer-windows buffer)
+      (let ((input-wait-alarm
+	     (if (hemlock-bound-p 'input-wait-alarm
+				  :buffer buffer)
+	       (variable-value 'input-wait-alarm
+			       :buffer buffer)
+	       (variable-value 'input-wait-alarm
+			       :global))))
+	(when input-wait-alarm
+	  (when (eq input-wait-alarm :loud-message)
+	    (beep))
+	  (message "Waiting for input in buffer ~A."
+		   (buffer-name buffer))))))
+  nil)
+
+(defun ts-buffer-clear-input (ts)
+  (let* ((ts (if (hemlock.wire:remote-object-p ts)
+		 (hemlock.wire:remote-object-value ts)
+		 ts))
+	 (buffer (ts-data-buffer ts))
+	 (mark (ts-data-fill-mark ts)))
+    (unless (mark= mark (buffer-end-mark buffer))
+      (with-mark ((start mark))
+	(line-start start)
+	(let ((prompt (region-to-string (region start mark)))
+	      (end (buffer-end-mark buffer)))
+	  (unless (zerop (mark-charpos end))
+	    (insert-character end #\Newline))
+	  (insert-string end "[Input Cleared]")
+	  (insert-character end #\Newline)
+	  (insert-string end prompt)
+	  (move-mark mark end)))))
+  nil)
+
+(defun ts-buffer-set-stream (ts stream)
+  (let ((ts (if (hemlock.wire:remote-object-p ts)
+		(hemlock.wire:remote-object-value ts)
+		ts)))
+    (setf (ts-data-stream ts) stream)
+    (hemlock.wire:remote (ts-data-wire ts)
+      (ts-stream-set-line-length stream (ts-buffer-line-length ts))))
+  nil)
+
+
+
+;;;; Typescript mode.
+
+(defun setup-typescript (buffer)
+  (let ((ts (make-ts-data buffer)))
+    (defhvar "Current Package"
+      "The package used for evaluation of Lisp in this buffer."
+      :buffer buffer
+      :value nil)
+
+    (defhvar "Typescript Data"
+      "The ts-data structure for this buffer"
+      :buffer buffer
+      :value ts)
+    
+    (defhvar "Buffer Input Mark"
+      "Beginning of typescript input in this buffer."
+      :value (ts-data-fill-mark ts)
+      :buffer buffer)
+    
+    (defhvar "Interactive History"
+      "A ring of the regions input to the Hemlock typescript."
+      :buffer buffer
+      :value (make-ring (value interactive-history-length)))
+    
+    (defhvar "Interactive Pointer"
+      "Pointer into the Hemlock typescript input history."
+      :buffer buffer
+      :value 0)
+    
+    (defhvar "Searching Interactive Pointer"
+      "Pointer into \"Interactive History\"."
+      :buffer buffer
+      :value 0)))
+
+(defmode "Typescript"
+  :setup-function #'setup-typescript
+  :documentation "The Typescript mode is used to interact with slave lisps.")
+
+
+;;; TYPESCRIPTIFY-BUFFER -- Internal interface.
+;;;
+;;; Buffer creation code for eval server connections calls this to setup a
+;;; typescript buffer, tie things together, and make some local Hemlock
+;;; variables.
+;;;
+(defun typescriptify-buffer (buffer server wire)
+  (setf (buffer-minor-mode buffer "Typescript") t)
+  (let ((info (variable-value 'typescript-data :buffer buffer)))
+    (setf (ts-data-server info) server)
+    (setf (ts-data-wire info) wire)
+    (defhvar "Server Info"
+      "Server-info structure for this buffer."
+      :buffer buffer :value server)
+    (defhvar "Current Eval Server"
+      "The Server-Info object for the server currently used for evaluation and
+       compilation."
+      :buffer buffer :value server)
+    info))
+
+(defun ts-buffer-wire-died (ts)
+  (setf (ts-data-stream ts) nil)
+  (setf (ts-data-wire ts) nil)
+  (buffer-end (ts-data-fill-mark ts) (ts-data-buffer ts))
+  (ts-buffer-output-string ts (format nil "~%~%Slave died!~%")))
+
+(defun unwedge-typescript-buffer ()
+  (typescript-slave-to-top-level-command nil)
+  (buffer-end (current-point) (current-buffer)))
+
+(defhvar "Unwedge Interactive Input Fun"
+  "Function to call when input is confirmed, but the point is not past the
+   input mark."
+  :value #'unwedge-typescript-buffer
+  :mode "Typescript")
+
+(defhvar "Unwedge Interactive Input String"
+  "String to add to \"Point not past input mark.  \" explaining what will
+   happen if the the user chooses to be unwedged."
+  :value "Cause the slave to throw to the top level? "
+  :mode "Typescript")
+
+;;; TYPESCRIPT-DATA-OR-LOSE -- internal
+;;;
+;;; Return the typescript-data for the current buffer, or die trying.
+;;; 
+(defun typescript-data-or-lose ()
+  (if (hemlock-bound-p 'typescript-data)
+      (let ((ts (value typescript-data)))
+	(if ts
+	    ts
+	    (editor-error "Can't find the typescript data?")))
+      (editor-error "Not in a typescript buffer.")))
+
+(defcommand "Confirm Typescript Input" (p)
+  "Send the current input to the slave typescript."
+  "Send the current input to the slave typescript."
+  (declare (ignore p))
+  (let ((ts (typescript-data-or-lose)))
+    (let ((input (get-interactive-input)))
+      (when input
+	(let ((string (region-to-string input)))
+	  (declare (simple-string string))
+	  (insert-character (current-point) #\NewLine)
+	  (hemlock.wire:remote (ts-data-wire ts)
+	    (ts-stream-accept-input (ts-data-stream ts)
+				    (concatenate 'simple-string
+						 string
+						 (string #\newline))))
+	  (hemlock.wire:wire-force-output (ts-data-wire ts))
+	  (buffer-end (ts-data-fill-mark ts)
+		      (ts-data-buffer ts)))))))
+  
+(defcommand "Typescript Slave Break" (p)
+  "Interrupt the slave Lisp process associated with this interactive buffer,
+   causing it to invoke BREAK."
+  "Interrupt the slave Lisp process associated with this interactive buffer,
+   causing it to invoke BREAK."
+  (declare (ignore p))
+  (send-oob-to-slave "B"))
+
+(defcommand "Typescript Slave to Top Level" (p)
+  "Interrupt the slave Lisp process associated with this interactive buffer,
+   causing it to throw to the top level REP loop."
+  "Interrupt the slave Lisp process associated with this interactive buffer,
+   causing it to throw to the top level REP loop."
+  (declare (ignore p))
+  (send-oob-to-slave "T"))
+
+(defcommand "Typescript Slave Status" (p)
+  "Interrupt the slave and cause it to print status information."
+  "Interrupt the slave and cause it to print status information."
+  (declare (ignore p))
+  (send-oob-to-slave "S"))
+
+#+NIL
+(defun send-oob-to-slave (string)
+  (let* ((ts (typescript-data-or-lose))
+	 (wire (ts-data-wire ts))
+	 (socket (hemlock.wire:wire-fd wire)))
+    (unless socket
+      (editor-error "The slave is no longer alive."))
+    (error "SEND-OOB-TO-SLAVE seeks an implementation.")
+    #+NIL
+    (hemlock-ext:send-character-out-of-band socket (schar string 0))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/ts-stream.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/ts-stream.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/ts-stream.lisp	(revision 13309)
@@ -0,0 +1,422 @@
+;;; -*- Package: Hemlock; Log: hemlock.log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+(hemlock-ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file implements typescript streams.
+;;;
+;;; A typescript stream is a bidirectional stream which uses remote
+;;; function calls to interact with a Hemlock typescript buffer. That
+;;; is: the code in this file is executed on the slave side.
+;;;
+;;; Written by William Lott.
+;;;
+
+(in-package :hemlock)
+
+
+
+;;;; Ts-streams.
+
+(defconstant ts-stream-output-buffer-size 512)
+
+(defclass ts-stream (hi::fundamental-character-output-stream
+                     hi::fundamental-character-input-stream)
+  ((wire
+    :initarg  :wire
+    :initform nil
+    :accessor ts-stream-wire)
+
+   (typescript
+    :initarg  :typescript
+    :initform nil
+    :accessor ts-stream-typescript)
+
+   (output-buffer
+    :initarg  :output-buffer
+    :initform (make-string ts-stream-output-buffer-size)
+    :accessor ts-stream-output-buffer
+    :type     simple-string)
+
+   (output-buffer-index
+    :initarg  :output-buffer-index
+    :initform 0
+    :accessor ts-stream-output-buffer-index
+    :type     fixnum)
+  
+   (char-pos
+    :initarg  :char-pos
+    :initform 0
+    :accessor ts-stream-char-pos
+    :type     fixnum
+    :documentation "The current output character position on the line, returned by the :CHARPOS method.")
+  
+   (line-length
+    :initarg :line-length
+    :initform 80
+    :accessor ts-stream-line-length
+    :documentation "The current length of a line of output.  Returned by STREAM-LINE-LENGTH method.")
+
+   (current-input
+    :initarg :current-input
+    :initform nil
+    :accessor ts-stream-current-input
+    :type list
+    :documentation "This is a list of strings and stream-commands whose order manifests the
+                    input provided by remote procedure calls into the slave of
+                    TS-STREAM-ACCEPT-INPUT.")
+   
+   (input-read-index
+    :initarg :input-read-index
+    :initform 0
+    :accessor ts-stream-input-read-index
+    :type fixnum)))
+
+(defun make-ts-stream (wire typescript)
+  (make-instance 'ts-stream :wire wire :typescript typescript))
+
+
+
+;;;; Conditions.
+
+(define-condition unexpected-stream-command (error)
+  ;; Context is a string to be plugged into the report text.
+  ((context :reader unexpected-stream-command-context :initarg :context))
+  (:report (lambda (condition stream)
+	     (format stream "~&Unexpected stream-command while ~A."
+		     (unexpected-stream-command-context condition)))))
+
+
+
+
+;;;; Editor remote calls into slave.
+
+;;; TS-STREAM-ACCEPT-INPUT -- Internal Interface.
+;;;
+;;; The editor calls this remotely in the slave to indicate that the user has
+;;; provided input.  Input is a string, symbol, or list.  If it is a list, the
+;;; the CAR names the command, and the CDR is the arguments.
+;;;
+(defun ts-stream-accept-input (remote input)
+  (let ((stream (hemlock.wire:remote-object-value remote)))
+    (hemlock-ext:without-interrupts
+     (hemlock-ext:without-gcing
+      (setf (ts-stream-current-input stream)
+	    (nconc (ts-stream-current-input stream)
+		   (list (etypecase input
+			   (string
+			    (let ((newline
+				   (position #\newline input :from-end t)))
+			      (setf (ts-stream-char-pos stream)
+				    (if newline
+					(- (length input) newline 1)
+					(length input)))
+			      input))
+                           #+NILGB
+			   (cons
+			    (ext:make-stream-command (car input)
+						     (cdr input)))
+                           #+NILGB
+			   (symbol
+			    (ext:make-stream-command input)))))))))
+  nil)
+
+;;; TS-STREAM-SET-LINE-LENGTH -- Internal Interface.
+;;;
+;;; This function is called by the editor to indicate that the line-length for
+;;; a TS stream should now be Length.
+;;;
+(defun ts-stream-set-line-length (remote length)
+  (let ((stream (hemlock.wire:remote-object-value remote)))
+    (setf (ts-stream-line-length stream) length)))
+
+
+
+
+;;;; Stream methods.
+
+;;; %TS-STREAM-LISTEN -- Internal.
+;;;
+;;; Determine if there is any input available.  If we don't think so, process
+;;; all pending events, and look again.
+;;;
+(defmethod hi::stream-listen ((stream ts-stream))
+  (flet ((check ()
+	   (hemlock-ext:without-interrupts
+	    (hemlock-ext:without-gcing
+	     (loop
+	       (let* ((current (ts-stream-current-input stream))
+		      (first (first current)))
+		 (cond ((null current)
+			(return nil))
+                       #+NILGB
+		       ((ext:stream-command-p first)
+			(return t))
+		       ((>= (ts-stream-input-read-index stream)
+			    (length (the simple-string first)))
+			(pop (ts-stream-current-input stream))
+			(setf (ts-stream-input-read-index stream) 0))
+		       (t
+			(return t)))))))))
+    (or (check)
+	(progn
+	  #+NILGB (system:serve-all-events 0)
+	  (check)))))
+
+;;; %TS-STREAM-IN -- Internal.
+;;;
+;;; The READ-CHAR stream method.
+;;;
+(defmethod hi::stream-read-char ((stream ts-stream))
+  (hi::stream-force-output stream)
+  (wait-for-typescript-input stream)
+  (hemlock-ext:without-interrupts
+   (hemlock-ext:without-gcing
+    (let ((first (first (ts-stream-current-input stream))))
+      (etypecase first
+	(string
+	 (prog1 (schar first (ts-stream-input-read-index stream))
+	   (incf (ts-stream-input-read-index stream))))
+        #+NILGB
+	(ext:stream-command
+	 (error 'unexpected-stream-command
+		:context "in the READ-CHAR method")))))))
+
+;;; %TS-STREAM-READ-LINE -- Internal.
+;;;
+;;; The READ-LINE stream method.  Note: here we take advantage of the fact that
+;;; newlines will only appear at the end of strings.
+;;;
+
+(defmethod stream-read-line (stream)
+  (macrolet
+      ((next-str ()
+	 '(progn
+           (wait-for-typescript-input stream)
+           (hemlock-ext:without-interrupts
+            (hemlock-ext:without-gcing
+             (let ((first (first (ts-stream-current-input stream))))
+               (etypecase first
+                 (string
+                  (prog1 (if (zerop (ts-stream-input-read-index stream))
+                             (pop (ts-stream-current-input stream))
+                             (subseq (pop (ts-stream-current-input stream))
+                                     (ts-stream-input-read-index stream)))
+                    (setf (ts-stream-input-read-index stream) 0)))
+                 #+NILGB
+                 (ext:stream-command
+                  (error 'unexpected-stream-command
+                         :context "in the READ-CHAR method")))))))))
+    (do ((result (next-str) (concatenate 'simple-string result (next-str))))
+	((char= (schar result (1- (length result))) #\newline)
+	 (values (subseq result 0 (1- (length result)))
+		 nil))
+      (declare (simple-string result)))))
+
+;;; WAIT-FOR-TYPESCRIPT-INPUT -- Internal.
+;;;
+;;; Keep calling server until some input shows up.
+;;; 
+(defun wait-for-typescript-input (stream)
+  (unless (hi::stream-listen stream)        ;for some reasons in CLISP CL:LISTEN calls STREAM-READ-CHAR :-/
+    (let ((wire (ts-stream-wire stream))
+	  (ts (ts-stream-typescript stream)))
+      (hemlock-ext:without-interrupts
+       (hemlock-ext:without-gcing
+	(hemlock.wire:remote wire (ts-buffer-ask-for-input ts))
+	(hemlock.wire:wire-force-output wire)))
+      (loop
+          #+:hemlock.serve-event (hemlock.wire::serve-all-events)
+          #-:hemlock.serve-event (hemlock.wire:wire-get-object wire)
+          #+NILGB (sleep .1)            ;###
+	(when (hi::stream-listen stream)
+	  (return))))))
+
+;;; %TS-STREAM-FLSBUF --- internal.
+;;;
+;;; Flush the output buffer associated with stream.  This should only be used
+;;; inside a without-interrupts and without-gcing.
+;;; 
+(defun %ts-stream-flsbuf (stream)
+  (when (and (ts-stream-wire stream)
+	     (ts-stream-output-buffer stream)
+	     (not (zerop (ts-stream-output-buffer-index stream))))
+    (hemlock.wire:remote (ts-stream-wire stream)
+      (ts-buffer-output-string
+       (ts-stream-typescript stream)
+       (subseq (the simple-string (ts-stream-output-buffer stream))
+	       0
+	       (ts-stream-output-buffer-index stream))))
+    (setf (ts-stream-output-buffer-index stream) 0)))
+
+;;; %TS-STREAM-OUT --- internal.
+;;;
+;;; Output a single character to stream.
+;;;
+(defmethod hi::stream-write-char ((stream ts-stream) char)
+  (declare (base-char char))
+  (hemlock-ext:without-interrupts
+   (hemlock-ext:without-gcing
+    (when (= (ts-stream-output-buffer-index stream)
+	     ts-stream-output-buffer-size)
+      (%ts-stream-flsbuf stream))
+    (setf (schar (ts-stream-output-buffer stream)
+		 (ts-stream-output-buffer-index stream))
+	  char)
+    (incf (ts-stream-output-buffer-index stream))
+    (incf (ts-stream-char-pos stream))
+    (when (= (char-code char)
+	     (char-code #\Newline))
+      (%ts-stream-flsbuf stream)
+      (setf (ts-stream-char-pos stream) 0)
+      (hemlock.wire:wire-force-output (ts-stream-wire stream)))
+    char)))
+
+;;; %TS-STREAM-SOUT --- internal.
+;;;
+;;; Output a string to stream.
+;;;
+(defmethod hi::stream-write-string ((stream ts-stream) string &optional (start 0) (end (length string)))
+  ;; This can't be true generally: --GB
+  #+NIL (declare (simple-string string))
+  (declare (fixnum start end))
+  (let ((wire (ts-stream-wire stream))
+	(newline (position #\Newline string :start start :end end :from-end t))
+	(length (- end start)))
+    (when wire
+      (hemlock-ext:without-interrupts
+       (hemlock-ext:without-gcing
+	(let ((index (ts-stream-output-buffer-index stream)))
+	  (cond ((> (+ index length)
+		    ts-stream-output-buffer-size)
+		 (%ts-stream-flsbuf stream)
+		 (hemlock.wire:remote wire
+                                      (ts-buffer-output-string (ts-stream-typescript stream)
+                                                               (subseq string start end)))
+		 (when newline
+		   (hemlock.wire:wire-force-output wire)))
+		(t
+		 (replace (the simple-string (ts-stream-output-buffer stream))
+			  string
+			  :start1 index
+			  :end1 (+ index length)
+			  :start2 start
+			  :end2 end)
+		 (incf (ts-stream-output-buffer-index stream)
+		       length)
+		 (when newline
+		   (%ts-stream-flsbuf stream)
+		   (hemlock.wire:wire-force-output wire)))))
+	(setf (ts-stream-char-pos stream)
+	      (if newline
+		  (- end newline 1)
+		  (+ (ts-stream-char-pos stream)
+		     length))))))))
+
+;;; %TS-STREAM-UNREAD -- Internal.
+;;;
+;;; Unread a single character.
+;;;
+(defmethod hi::stream-unread-char ((stream ts-stream) char)
+  (hemlock-ext:without-interrupts
+   (hemlock-ext:without-gcing
+    (let ((first (first (ts-stream-current-input stream))))
+      (cond ((and (stringp first)
+		  (> (ts-stream-input-read-index stream) 0))
+	     (setf (schar first (decf (ts-stream-input-read-index stream)))
+		   char))
+	    (t
+	     (push (string char) (ts-stream-current-input stream))
+	     (setf (ts-stream-input-read-index stream) 0)))))))
+
+;;; %TS-STREAM-CLOSE --- internal.
+;;;
+;;; Can't do much, 'cause the wire is shared.
+;;;
+(defmethod close ((stream ts-stream) &key abort)
+  (unless abort
+    (force-output stream))
+  #+NILGB (lisp::set-closed-flame stream)       ;Hugh!? what is that? --GB
+  )
+
+;;; %TS-STREAM-CLEAR-INPUT -- Internal.
+;;;
+;;; Pass the request to the editor and clear any buffered input.
+;;;
+(defmethod hi::stream-clear-input ((stream ts-stream))
+  (hemlock-ext:without-interrupts
+   (hemlock-ext:without-gcing
+    (when (ts-stream-wire stream)
+      (hemlock.wire:remote-value (ts-stream-wire stream)
+	(ts-buffer-clear-input (ts-stream-typescript stream))))
+    (setf (ts-stream-current-input stream) nil
+	  (ts-stream-input-read-index stream) 0))))
+
+(defmethod hi::stream-finish-output ((stream ts-stream))
+  (when (ts-stream-wire stream)
+    (hemlock-ext:without-interrupts
+     (hemlock-ext:without-gcing
+      (%ts-stream-flsbuf stream)
+      ;; Note: for the return value to come back,
+      ;; all pending RPCs must have completed.
+      ;; Therefore, we know it has synced.
+      (hemlock.wire:remote-value (ts-stream-wire stream)
+                         (ts-buffer-finish-output (ts-stream-typescript stream))))))
+  t)
+
+(defmethod hi::stream-force-output ((stream ts-stream))
+  (when (ts-stream-wire stream)
+    (hemlock-ext:without-interrupts
+     (hemlock-ext:without-gcing
+      (%ts-stream-flsbuf stream)
+      (hemlock.wire:wire-force-output (ts-stream-wire stream)))))
+  t)
+
+(defmethod hi::stream-line-column ((stream ts-stream))
+  (ts-stream-char-pos stream))
+
+(defmethod hi::stream-line-length ((stream ts-stream))
+  (ts-stream-line-length stream))
+
+#+NILGB ;; -- hmm.
+(defmethod interactive-stream-p ((stream ts-stream))
+  t)
+
+(defmethod hi::stream-clear-output ((stream ts-stream))
+  (setf (ts-stream-output-buffer-index stream) 0))
+
+;;; %TS-STREAM-MISC -- Internal.
+;;;
+;;; The misc stream method.
+;;;
+#+NILGB
+(defun %ts-stream-misc (stream operation &optional arg1 arg2)
+  (case operation
+    (:get-command
+     (wait-for-typescript-input stream)
+     (hemlock-ext:without-interrupts
+      (hemlock-ext:without-gcing
+       (etypecase (first (ts-stream-current-input stream))
+	 (stream-command
+	  (setf (ts-stream-input-read-index stream) 0)
+	  (pop (ts-stream-current-input stream)))
+	 (string nil)))))
+    ))
+
+;; $Log$
+;; Revision 1.1  2003/10/19 08:57:16  gb
+;; Initial revision
+;;
+;; Revision 1.1.2.1  2003/08/10 19:11:40  gb
+;; New files, imported from upstream CVS as of 03/08/09.
+;;
+;; Revision 1.3  2003/08/05 19:51:13  gilbert
+;; initial slave lisp support, still not ready for prime time.
+;;
+;;
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/termcap.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/termcap.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/termcap.lisp	(revision 13309)
@@ -0,0 +1,443 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;
+;;; Terminal Capability
+;;;
+;;; This stuff parses a Termcap file and returns a data structure suitable
+;;; for initializing a redisplay methods device.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+
+;;;; Interface for device creating code.
+
+(defun get-termcap (name)
+  "Look in TERMCAP environment variable for terminal capabilities or a
+   file to use.  If it is a file, look for name in it.  If it is a description
+   of the capabilities, use it, and don't look for name anywhere.  If TERMCAP
+   is undefined, look for name in termcap-file.  An error is signaled if it
+   cannot find the terminal capabilities."
+  (let ((termcap-env-var (get-termcap-env-var)))
+    (if termcap-env-var
+	(if (char= (schar termcap-env-var 0) #\/) ; hack for filenamep
+	    (with-open-file (s termcap-env-var)
+	      (if (find-termcap-entry name s)
+		  (parse-fields s)
+		  (error "Unknown Terminal ~S in file ~S." name termcap-env-var)))
+	    (with-input-from-string (s termcap-env-var)
+	      (skip-termcap-names s)
+	      (parse-fields s)))
+	(with-open-file (s termcap-file)
+	  (if (find-termcap-entry name s)
+	      (parse-fields s)
+	      (error "Unknown Terminal ~S in file ~S." name termcap-file))))))
+
+(declaim (inline termcap))
+(defun termcap (name termcap)
+  (cdr (assoc name termcap :test #'eq)))
+
+
+
+
+;;;; Finding the termcap entry
+
+(defun find-termcap-entry (name stream)
+  (loop
+   (let ((end-of-names (lex-termcap-name stream)))
+     (when (termcap-found-p name)
+       (unless end-of-names (skip-termcap-names stream))
+       (return t))
+     (when end-of-names
+       (unless (skip-termcap-fields stream)
+	 (return nil))))))
+
+
+;;; This buffer is used in LEX-TERMCAP-NAME and PARSE-FIELDS to
+;;; do string comparisons and build strings from interpreted termcap
+;;; characters, respectively.
+;;; 
+(defvar *termcap-string-buffer* (make-string 300))
+(defvar *termcap-string-index* 0)
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro init-termcap-string-buffer ()
+  `(setf *termcap-string-index* 0))
+
+(defmacro store-char (char)
+  `(progn
+    (setf (schar *termcap-string-buffer* *termcap-string-index*) ,char)
+    (incf *termcap-string-index*)))
+
+(defmacro termcap-string-buffer-string ()
+  `(subseq (the simple-string *termcap-string-buffer*)
+	   0 *termcap-string-index*))
+
+) ;eval-when
+
+
+;;; LEX-TERMCAP-NAME gathers characters until the next #\|, which separate
+;;; terminal names, or #\:, which terminate terminal names for an entry.
+;;; T is returned if the end of the names is reached for the entry.
+;;; If we hit and EOF, act like we found a :. 
+;;; 
+(defun lex-termcap-name (stream)
+  (init-termcap-string-buffer)
+  (loop
+   (let ((char (read-char stream nil #\:)))
+     (case char
+       (#\Linefeed (init-termcap-string-buffer))
+       (#\# (read-line stream nil))
+       (#\| (return nil))
+       (#\: (return t))
+       (t (store-char char))))))
+
+(defun termcap-found-p (name)
+  (string= name *termcap-string-buffer* :end2 *termcap-string-index*))
+
+;;; SKIP-TERMCAP-NAMES eats characters until the next #\: which terminates
+;;; terminal names for an entry.  Stop also at EOF.
+;;; 
+(defun skip-termcap-names (stream)
+  (loop
+   (when (char= (read-char stream nil #\:) #\:)
+     (return))))
+
+;;; SKIP-TERMCAP-FIELDS skips the rest of an entry, returning nil if there
+;;; are no more entries in the file.  An entry is terminated by a #\:
+;;; followed by a #\newline (possibly by eof).
+;;; 
+(defun skip-termcap-fields (stream)
+  (loop
+   (multiple-value-bind (line eofp)
+			(read-line stream nil)
+     (if eofp
+	 (return nil)
+	 (let ((len (length line)))
+	   (declare (simple-string line))
+	   (when (and (not (zerop len))
+		      (not (char= (schar line 0) #\#))
+		      (char= (schar line (1- len)) #\:))
+	     (let ((char (read-char stream nil :eof)))
+	       (if (eq char :eof)
+		   (return nil)
+		   (unread-char char stream))
+	       (return t))))))))
+
+    
+
+
+;;;; Defining known capabilities for parsing purposes.
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+(defvar *known-termcaps* ())
+) ;eval-when
+
+
+(eval-when (:compile-toplevel :execute)
+
+;;; DEFTERMCAP makes a terminal capability known for parsing purposes.
+;;; Type is one of :string, :number, or :boolean.  Cl-name is an EQ
+;;; identifier for the capability.
+;;;
+(defmacro deftermcap (name type cl-name)
+  `(progn (push (list ,name ,type ,cl-name) *known-termcaps*)))
+
+(defmacro termcap-def (name)
+  `(cdr (assoc ,name *known-termcaps* :test #'string=)))
+
+(defmacro termcap-def-type (termcap-def)
+  `(car ,termcap-def))
+
+(defmacro termcap-def-cl-name (termcap-def)
+  `(cadr ,termcap-def))
+
+) ;eval-when
+
+
+(deftermcap "is" :string :init-string)
+(deftermcap "if" :string :init-file)
+(deftermcap "ti" :string :init-cursor-motion)
+(deftermcap "te" :string :end-cursor-motion)
+(deftermcap "al" :string :open-line)
+(deftermcap "am" :boolean :auto-margins-p)
+(deftermcap "ce" :string :clear-to-eol)
+(deftermcap "cl" :string :clear-display)
+(deftermcap "cm" :string :cursor-motion)
+(deftermcap "co" :number :columns)
+(deftermcap "dc" :string :delete-char)
+(deftermcap "dm" :string :init-delete-mode)
+(deftermcap "ed" :string :end-delete-mode)
+(deftermcap "dl" :string :delete-line)
+(deftermcap "im" :string :init-insert-mode)
+(deftermcap "ic" :string :init-insert-char)
+(deftermcap "ip" :string :end-insert-char)
+(deftermcap "ei" :string :end-insert-mode)
+(deftermcap "li" :number :lines)
+(deftermcap "so" :string :init-standout-mode)
+(deftermcap "se" :string :end-standout-mode)
+(deftermcap "tc" :string :similar-terminal)
+(deftermcap "os" :boolean :overstrikes)
+(deftermcap "ul" :boolean :underlines)
+
+;;; font related stuff, added by William
+(deftermcap "ae" :string :end-alternate-char-set)
+(deftermcap "as" :string :start-alternate-char-set)
+(deftermcap "mb" :string :start-blinking-attribute)
+(deftermcap "md" :string :start-bold-attribute)
+(deftermcap "me" :string :end-all-attributes)
+(deftermcap "mh" :string :start-half-bright-attribute)
+(deftermcap "mk" :string :start-blank-attribute)
+(deftermcap "mp" :string :start-protected-attribute)
+(deftermcap "mr" :string :start-reverse-video-attribute)
+(deftermcap "ue" :string :end-underscore-mode)
+(deftermcap "us" :string :start-underscore-mode)
+
+
+
+;;;; Parsing an entry.
+
+(defvar *getchar-ungetchar-buffer* nil)
+
+(eval-when (:compile-toplevel :execute)
+
+;;; UNGETCHAR  --  Internal.
+;;;
+;;; We need this to be able to peek ahead more than one character.
+;;; This is used in PARSE-FIELDS and GET-TERMCAP-STRING-CHAR.
+;;;
+(defmacro ungetchar (char)
+  `(push ,char *getchar-ungetchar-buffer*))
+
+;;; GETCHAR  --  Internal.
+;;;
+;;; This is used in PARSE-FIELDS and GET-TERMCAP-STRING-CHAR.
+;;;
+(defmacro getchar ()
+  `(loop
+    (setf char
+	  (if *getchar-ungetchar-buffer*
+	      (pop *getchar-ungetchar-buffer*)
+	      (read-char stream nil :eof)))
+    (if (and (characterp char) (char= char #\\))
+	(let ((temp (if *getchar-ungetchar-buffer*
+			(pop *getchar-ungetchar-buffer*)
+			(read-char stream))))
+	  (when (char/= temp #\newline)
+	    (ungetchar temp)
+	    (return char)))
+	(return char))))
+
+
+;;; STORE-FIELD used in PARSE-FIELDS.
+;;; 
+(defmacro store-field (cl-name value)
+  (let ((name (gensym)))
+    `(let ((,name ,cl-name))
+       (unless (cdr (assoc ,name termcap :test #'eq))
+	 (push (cons ,name ,value) termcap)))))
+
+) ;eval-when
+
+;;; PARSE-FIELDS parses a termcap entry.  We start out in the state get-name.
+;;; Each name is looked up in *known-termcaps*, and if it is of interest, then
+;;; we dispatch to a state to pick up the value of the field; otherwise, eat
+;;; the rest of the field to get to the next name.  The name could be present
+;;; simply to have the capability negated before the entry indirects to a
+;;; similar terminal's capabilities, in which case it is followed by an #\@.
+;;; Negated fields are stored with the value :negated since we only store a
+;;; field if it does not already have a value -- this is the intent of the
+;;; sequencing built into the termcap file.  When we are done, we see if there
+;;; is a similar terminal to be parsed, and when we are really done, we replace
+;;; all the :negated's with nil's.
+;;; 
+(defun parse-fields (stream)
+  (prog ((termcap-name (make-string 2))
+	 (termcap ())
+	 char termcap-def)
+  GET-NAME
+    ;;
+    ;; This state expects char to be a #\:.
+    (case (getchar)
+      ((#\space #\tab)
+       (go GET-NAME))
+      (#\:
+       ;; This is an empty field.
+       (go GET-NAME))
+      ((#\newline :eof)
+       (go MAYBE-DONE))
+      (t
+       (setf (schar termcap-name 0) char)))
+    (setf (schar termcap-name 1) (getchar))
+    (setf termcap-def (termcap-def termcap-name))
+    (unless termcap-def (go EAT-FIELD))
+    (when (char= (getchar) #\@)
+      ;; Negation of a capability to be inherited from a similar terminal.
+      (store-field (termcap-def-cl-name termcap-def) :negated)
+      (go EAT-FIELD))
+    (case (termcap-def-type termcap-def)
+      (:number (go NUMBER))
+      (:boolean (go BOOLEAN))
+      (:string (go STRING)))
+  NUMBER
+    (unless (char= char #\#)
+      (error "Bad termcap format -- number field '#' missing."))
+    (let ((number 0)
+	  digit)
+      (loop
+       (setf digit (digit-char-p (getchar)))
+       (if digit
+	   (setf number (+ digit (* number 10)))
+	   (if (char= char #\:)
+	       (return)
+	       (error "Bad termcap format -- number field not : terminated."))))
+      (store-field (termcap-def-cl-name termcap-def) number)
+      (go GET-NAME))
+  BOOLEAN
+    (store-field (termcap-def-cl-name termcap-def) t)
+    (if (char= char #\:)
+	(go GET-NAME)
+	(error "Bad termcap format -- boolean field not : terminated."))
+  STRING
+    (unless (char= char #\=)
+      (error "Bad termcap format -- string field '=' missing."))
+    ;;
+    ;; Eat up any cost of the capability.
+    (when (digit-char-p (getchar))
+      (let ((dotp nil))
+	(loop
+	 (case (getchar)
+	   ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
+	   (#\.
+	    (when dotp (return))
+	    (setf dotp t))
+	   (t (when (char= char #\*) (getchar)) ; '*' means a per line cost
+	      (return))))))
+    ;;
+    ;; Collect the characters.
+    (let ((normal-string-p (not (eq (termcap-def-cl-name termcap-def)
+				    :cursor-motion)))
+	  xp cm-info)
+      (init-termcap-string-buffer)
+      (loop
+       (case (setf char (get-termcap-string-char stream char))
+	 (#\%
+	  (if normal-string-p
+	      (store-char #\%)
+	      (case (getchar)
+		(#\% (store-char #\%))
+		((#\d #\2 #\3)
+		 (push (if (char= char #\d) 0 (digit-char-p char))
+		       cm-info)
+		 (push (if xp :y-pad :x-pad) cm-info)
+		 (push (termcap-string-buffer-string) cm-info)
+		 (push (if xp :string2 :string1) cm-info)
+		 (init-termcap-string-buffer)
+		 (setf xp t))
+		(#\.
+		 (push (termcap-string-buffer-string) cm-info)
+		 (push (if xp :string2 :string1) cm-info)
+		 (init-termcap-string-buffer)
+		 (setf xp t))
+		(#\+
+		 (push (termcap-string-buffer-string) cm-info)
+		 (push (if xp :string2 :string1) cm-info)
+		 (push (get-termcap-string-char stream (getchar)) cm-info)
+		 (push (if xp :y-add-char :x-add-char) cm-info)
+		 (init-termcap-string-buffer)
+		 (setf xp t))
+		(#\>
+		 (push (get-termcap-string-char stream (getchar)) cm-info)
+		 (push (if xp :y-condx-char :x-condx-char) cm-info)
+		 (push (get-termcap-string-char stream (getchar)) cm-info)
+		 (push (if xp :y-condx-add-char :x-condx-add-char) cm-info))
+		(#\r
+		 (push t cm-info)
+		 (push :reversep cm-info))
+		(#\i
+		 (push t cm-info)
+		 (push :one-origin cm-info)))))
+	 (#\:
+	  (store-field (termcap-def-cl-name termcap-def)
+		       (cond (normal-string-p (termcap-string-buffer-string))
+			     (t (push (termcap-string-buffer-string) cm-info)
+				(cons :string3 cm-info))))
+	  (return))
+	 (t (store-char char)))
+       (getchar))
+      (go GET-NAME))
+  EAT-FIELD
+    (loop (when (char= (getchar) #\:) (return)))
+    (go GET-NAME)
+  MAYBE-DONE
+    (let* ((similar-terminal (assoc :similar-terminal termcap :test #'eq))
+	   (name (cdr similar-terminal)))
+      (when name
+	(file-position stream :start)
+	(setf (cdr similar-terminal) nil)
+	(if (find-termcap-entry name stream)
+	    (go GET-NAME)
+	    (error "Unknown similar terminal name -- ~S." name))))
+    (dolist (ele termcap)
+      (when (eq (cdr ele) :negated)
+	(setf (cdr ele) nil)))
+    (return termcap)))
+
+;;; GET-TERMCAP-STRING-CHAR -- Internal.
+;;;
+;;; This parses/lexes an ASCII character out of the termcap file and converts
+;;; it into the appropriate Common Lisp character.  This is a Common Lisp
+;;; character with the same CHAR-CODE code as the ASCII code, so writing the
+;;; character to the tty will have the desired effect.  If this function needs
+;;; to look ahead to determine any characters, it unreads the character.
+;;;
+(defun get-termcap-string-char (stream char)
+  (case char
+    (#\\
+     (case (getchar)
+       (#\E (code-char 27))
+       (#\n (code-char 10))
+       (#\r (code-char 13))
+       (#\t (code-char 9))
+       (#\b (code-char 8))
+       (#\f (code-char 12))
+       (#\^ #\^)
+       (#\\ #\\)
+       ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
+	(let ((result 0)
+	      (digit (digit-char-p char)))
+	  (loop (setf result (+ digit (* 8 result)))
+	    (unless (setf digit (digit-char-p (getchar)))
+	      (ungetchar char)
+	      (return (code-char (ldb (byte 7 0) result)))))))
+       (t (error "Bad termcap format -- unknown backslash character."))))
+    (#\^
+     (code-char (- (char-code (char-upcase (getchar))) 64)))
+    (t char)))
+
+
+
+;;;; Initialization file string.
+
+(defun get-init-file-string (f)
+  (unless (probe-file f)
+    (error "File containing terminal initialization string does not exist -- ~S."
+	   f))
+  (with-open-file (s f)
+    (let* ((len (file-length s))
+	   (string (make-string len)))
+      (dotimes (i len string)
+	(setf (schar string i) (read-char s))))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-disp-rt.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-disp-rt.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-disp-rt.lisp	(revision 13309)
@@ -0,0 +1,200 @@
+;;; -*- Log: hemlock.log; Package: hemlock-internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+;;;; Terminal init and exit methods.
+
+(defvar *hemlock-input-handler*)
+
+(defun init-tty-device (device)
+  (setf *hemlock-input-handler*
+	(system:add-fd-handler 0 :input #'get-editor-tty-input))
+  (standard-device-init)
+  (device-write-string (tty-device-init-string device))
+  (redisplay-all))
+
+(defun exit-tty-device (device)
+  (cursor-motion device 0 (1- (tty-device-lines device)))
+  ;; Can't call the clear-to-eol method since we don't have a hunk to
+  ;; call it on, and you can't count on the bottom hunk being the echo area.
+  ;; 
+  (if (tty-device-clear-to-eol-string device)
+      (device-write-string (tty-device-clear-to-eol-string device))
+      (dotimes (i (tty-device-columns device)
+		  (cursor-motion device 0 (1- (tty-device-lines device))))
+	(tty-write-char #\space)))
+  (device-write-string (tty-device-cm-end-string device))
+  (when (device-force-output device)
+    (funcall (device-force-output device)))
+  (when *hemlock-input-handler*
+    (system:remove-fd-handler *hemlock-input-handler*)
+    (setf *hemlock-input-handler* nil))
+  (standard-device-exit))
+
+
+
+;;;; Get terminal attributes:
+
+(defvar *terminal-baud-rate* nil)
+(declaim (type (or (unsigned-byte 24) null) *terminal-baud-rate*))
+
+;;; GET-TERMINAL-ATTRIBUTES  --  Interface
+;;;
+;;;    Get terminal attributes from Unix.  Return as values, the lines,
+;;; columns and speed.  If any value is inaccessible, return NIL for that
+;;; value.  We also sleazily cache the speed in *terminal-baud-rate*, since I
+;;; don't want to figure out how to get my hands on the TTY-DEVICE at the place
+;;; where I need it.  Currently, there really can only be one TTY anyway, since
+;;; the buffer is in a global.
+;;;
+(defun get-terminal-attributes (&optional (fd 1))
+  (alien:with-alien ((winsize (alien:struct unix:winsize))
+                     #-(or glibc2 bsd)
+		     (sgtty (alien:struct unix:sgttyb))
+                     #+bsd ; termios
+		     (tios (alien:struct unix:termios)))
+    (let ((size-win (unix:unix-ioctl fd unix:TIOCGWINSZ
+				     (alien:alien-sap winsize)))
+          #-(or glibc2 bsd)
+	  (speed-win (unix:unix-ioctl fd unix:TIOCGETP
+				      (alien:alien-sap sgtty)))
+	  #+bsd
+	  (speed-win (unix:unix-tcgetattr fd (alien:alien-sap tios))))
+      (flet ((frob (val)
+	       (if (and size-win (not (zerop val)))
+		   val
+		   nil)))
+	(values
+	 (frob (alien:slot winsize 'unix:ws-row))
+	 (frob (alien:slot winsize 'unix:ws-col))
+         #-(or glibc2 bsd)
+	 (and speed-win
+	      (setq *terminal-baud-rate*
+		    (svref unix:terminal-speeds
+			   (alien:slot sgtty 'unix:sg-ospeed))))
+	 #+bsd
+	 (and speed-win
+	      (setq *terminal-baud-rate* (unix:unix-cfgetospeed tios)))
+         #+glibc2
+         4800)))))
+
+
+
+;;;; Output routines and buffering.
+
+(defconstant redisplay-output-buffer-length 256)
+
+(defvar *redisplay-output-buffer*
+  (make-string redisplay-output-buffer-length))
+(declaim (simple-string *redisplay-output-buffer*))
+
+(defvar *redisplay-output-buffer-index* 0)
+(declaim (fixnum *redisplay-output-buffer-index*))
+
+;;; WRITE-AND-MAYBE-WAIT  --  Internal
+;;;
+;;;    Write the first Count characters in the redisplay output buffer.  If
+;;; *terminal-baud-rate* is set, then sleep for long enough to allow the
+;;; written text to be displayed.  We multiply by 10 to get the baud-per-byte
+;;; conversion, which assumes 7 character bits + 1 start bit + 2 stop bits, no
+;;; parity.
+;;;
+(defun write-and-maybe-wait (count)
+  (declare (fixnum count))
+  (unix:unix-write 1 *redisplay-output-buffer* 0 count)
+  (let ((speed *terminal-baud-rate*))
+    (when speed
+      (sleep (/ (* (float count) 10.0) (float speed))))))
+
+
+;;; TTY-WRITE-STRING blasts the string into the redisplay output buffer.
+;;; If the string overflows the buffer, then segments of the string are
+;;; blasted into the buffer, dumping the buffer, until the last piece of
+;;; the string is stored in the buffer.  The buffer is always dumped if
+;;; it is full, even if the last piece of the string just fills the buffer.
+;;; 
+(defun tty-write-string (string start length)
+  (declare (fixnum start length))
+  (let ((buffer-space (- redisplay-output-buffer-length
+			 *redisplay-output-buffer-index*)))
+    (declare (fixnum buffer-space))
+    (cond ((<= length buffer-space)
+	   (let ((dst-index (+ *redisplay-output-buffer-index* length)))
+	     (%primitive byte-blt string start *redisplay-output-buffer*
+			 *redisplay-output-buffer-index* dst-index)
+	     (cond ((= length buffer-space)
+		    (write-and-maybe-wait redisplay-output-buffer-length)
+		    (setf *redisplay-output-buffer-index* 0))
+		   (t
+		    (setf *redisplay-output-buffer-index* dst-index)))))
+	  (t
+	   (let ((remaining (- length buffer-space)))
+	     (declare (fixnum remaining))
+	     (loop
+	      (%primitive byte-blt string start *redisplay-output-buffer*
+			  *redisplay-output-buffer-index*
+			  redisplay-output-buffer-length)
+	      (write-and-maybe-wait redisplay-output-buffer-length)
+	      (when (< remaining redisplay-output-buffer-length)
+		(%primitive byte-blt string (+ start buffer-space)
+			    *redisplay-output-buffer* 0 remaining)
+		(setf *redisplay-output-buffer-index* remaining)
+		(return t))
+	      (incf start buffer-space)
+	      (setf *redisplay-output-buffer-index* 0)
+	      (setf buffer-space redisplay-output-buffer-length)
+	      (decf remaining redisplay-output-buffer-length)))))))
+
+
+;;; TTY-WRITE-CHAR stores a character in the redisplay output buffer,
+;;; dumping the buffer if it becomes full.
+;;; 
+(defun tty-write-char (char)
+  (setf (schar *redisplay-output-buffer* *redisplay-output-buffer-index*)
+	char)
+  (incf *redisplay-output-buffer-index*)
+  (when (= *redisplay-output-buffer-index* redisplay-output-buffer-length)
+    (write-and-maybe-wait redisplay-output-buffer-length)
+    (setf *redisplay-output-buffer-index* 0)))
+
+
+;;; TTY-FORCE-OUTPUT dumps the redisplay output buffer.  This is called
+;;; out of terminal device structures in multiple places -- the device
+;;; exit method, random typeout methods, out of tty-hunk-stream methods,
+;;; after calls to REDISPLAY or REDISPLAY-ALL.
+;;; 
+(defun tty-force-output ()
+  (unless (zerop *redisplay-output-buffer-index*)
+    (write-and-maybe-wait *redisplay-output-buffer-index*)
+    (setf *redisplay-output-buffer-index* 0)))
+
+
+;;; TTY-FINISH-OUTPUT simply dumps output.
+;;;
+(defun tty-finish-output (device window)
+  (declare (ignore window))
+  (let ((force-output (device-force-output device)))
+    (when force-output
+      (funcall force-output))))
+
+
+
+
+;;;; Screen image line hacks.
+
+(defmacro replace-si-line (dst-string src-string src-start dst-start dst-end)
+  `(%primitive byte-blt ,src-string ,src-start ,dst-string ,dst-start ,dst-end))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-display.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-display.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-display.lisp	(revision 13309)
@@ -0,0 +1,1303 @@
+;;; -*- Log: hemlock.log; Package: hemlock-internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles.
+;;;
+
+(in-package :hemlock-internals)
+
+(export '(redisplay redisplay-all define-tty-font))
+
+
+
+
+;;;; Macros.
+
+(eval-when (:compile-toplevel :execute)
+(defmacro tty-hunk-modeline-pos (hunk)
+  `(tty-hunk-text-height ,hunk))
+) ;eval-when
+
+
+(defvar *currently-selected-hunk* nil)
+(defvar *hunk-top-line*)
+
+(declaim (fixnum *hunk-top-line*))
+
+(eval-when (:compile-toplevel :execute)
+(defmacro select-hunk (hunk)
+  `(unless (eq ,hunk *currently-selected-hunk*)
+     (setf *currently-selected-hunk* ,hunk)
+     (setf *hunk-top-line*
+	   (the fixnum
+		(1+ (the fixnum
+			 (- (the fixnum
+				 (tty-hunk-text-position ,hunk))
+			    (the fixnum
+				 (tty-hunk-text-height ,hunk)))))))))
+) ;eval-when
+
+
+;;; Screen image lines.
+;;; 
+(defstruct (si-line (:print-function print-screen-image-line)
+		    (:constructor %make-si-line (chars)))
+  (chars nil :type simple-string)
+  (length 0)
+  (fonts nil :type list))
+
+(defun make-si-line (n)
+  (%make-si-line (make-string n)))
+
+(defun print-screen-image-line (obj str n)
+  (declare (ignore n))
+  (write-string "#<Screen Image Line \"" str)
+  (write-string (si-line-chars obj) str :end (si-line-length obj))
+  (write-string "\">" str))
+
+
+(defun find-identical-prefix (dis-line dis-line-fonts si-line)
+  (declare (type dis-line dis-line)
+	   (type list dis-line-fonts)
+	   (type si-line si-line))
+  (let* ((dl-chars (dis-line-chars dis-line))
+	 (dl-len (dis-line-length dis-line))
+	 (si-chars (si-line-chars si-line))
+	 (si-len (si-line-length si-line))
+	 (okay-until 0))
+    (declare (type simple-string dl-chars si-chars)
+	     (type (and unsigned-byte fixnum) dl-len si-len)
+	     (type (and unsigned-byte fixnum) okay-until))
+    (do ((dl-fonts dis-line-fonts (cdr dis-line-fonts))
+	 (si-fonts (si-line-fonts si-line) (cdr si-fonts)))
+	((or (null dl-fonts) (null si-fonts))
+	 (let ((next-font (car (or dl-fonts si-fonts))))
+	   (if next-font
+	       (let ((end (min dl-len si-len (cadr next-font))))
+		 (or (string/= dl-chars si-chars
+			       :start1 okay-until :start2 okay-until
+			       :end1 end :end2 end)
+		     end))
+	       (let ((end (min dl-len si-len)))
+		 (or (string/= dl-chars si-chars
+			       :start1 okay-until :start2 okay-until
+			       :end1 end :end2 end)
+		     (if (= dl-len si-len) nil end))))))
+      (let ((dl-font (caar dl-fonts))
+	    (dl-start (cadar dl-fonts))
+	    (dl-stop (cddar dl-fonts))
+	    (si-font (caar si-fonts))
+	    (si-start (cadar si-fonts))
+	    (si-stop (cddar si-fonts)))
+	(unless (and (= dl-font si-font)
+		     (= dl-start si-start))
+	  (let ((font-lossage (min dl-start si-start)))
+	    (return (or (string/= dl-chars si-chars
+				  :start1 okay-until :start2 okay-until
+				  :end1 font-lossage :end2 font-lossage)
+			font-lossage))))
+	(unless (= dl-stop si-stop)
+	  (let ((font-lossage (min dl-stop si-stop)))
+	    (return (or (string/= dl-chars si-chars
+				  :start1 okay-until :start2 okay-until
+				  :end1 font-lossage :end2 font-lossage)
+			font-lossage))))
+	(let ((mismatch (string/= dl-chars si-chars
+				  :start1 okay-until :start2 okay-until
+				  :end1 dl-stop :end2 si-stop)))
+	  (if mismatch
+	      (return mismatch)
+	      (setf okay-until dl-stop)))))))
+
+
+(defun find-identical-suffix (dis-line dis-line-fonts si-line)
+  (declare (type dis-line dis-line)
+	   (type list dis-line-fonts)
+	   (type si-line si-line))
+  (let* ((dl-chars (dis-line-chars dis-line))
+	 (dl-len (dis-line-length dis-line))
+	 (si-chars (si-line-chars si-line))
+	 (si-len (si-line-length si-line))
+	 (count (dotimes (i (min dl-len si-len) i)
+		  (when (char/= (schar dl-chars (- dl-len i 1))
+				(schar si-chars (- si-len i 1)))
+		    (return i)))))
+    (declare (type simple-string dl-chars si-chars)
+	     (type (and unsigned-byte fixnum) dl-len si-len))
+    (do ((dl-fonts (reverse dis-line-fonts) (cdr dis-line-fonts))
+	 (si-fonts (reverse (si-line-fonts si-line)) (cdr si-fonts)))
+	((or (null dl-fonts) (null si-fonts))
+	 (cond (dl-fonts
+		(min (- dl-len (cddar dl-fonts)) count))
+	       (si-fonts
+		(min (- si-len (cddar si-fonts)) count))
+	       (t
+		count)))
+      (let ((dl-font (caar dl-fonts))
+	    (dl-start (- dl-len (cadar dl-fonts)))
+	    (dl-stop (- dl-len (cddar dl-fonts)))
+	    (si-font (caar si-fonts))
+	    (si-start (- si-len (cadar si-fonts)))
+	    (si-stop (- si-len (cddar si-fonts))))
+	(unless (and (= dl-font si-font)
+		     (= dl-stop si-stop))
+	  (return (min dl-stop si-stop count)))
+	(unless (= dl-start si-start)
+	  (return (min dl-start si-start count)))
+	(when (<= count dl-start)
+	  (return count))))))
+
+
+(defmacro si-line (screen-image n)
+  `(svref ,screen-image ,n))
+
+
+
+
+;;; Font support.
+
+(defvar *tty-font-strings* (make-array font-map-size :initial-element nil)
+  "Array of (start-string . end-string) for fonts, or NIL if no such font.")
+
+(defun define-tty-font (font-id &rest stuff)
+  (unless (<= 0 font-id (1- font-map-size))
+    (error "Bogus font-id: ~S" font-id))
+  (cond ((every #'keywordp stuff)
+	 (error "Can't extract font strings from the termcap entry yet."))
+	((and (= (length stuff) 2)
+	      (stringp (car stuff))
+	      (stringp (cadr stuff)))
+	 (setf (aref *tty-font-strings* font-id)
+	       (cons (car stuff) (cadr stuff))))
+	(t
+	 (error "Bogus font spec: ~S~%Must be either a list of keywords or ~
+		 a list of the start string and end string."))))
+
+
+(defun compute-font-usages (dis-line)
+  (do ((results nil)
+       (change (dis-line-font-changes dis-line) (font-change-next change))
+       (prev nil change))
+      ((null change)
+       (when prev
+	 (let ((font (font-change-font prev)))
+	   (when (and (not (zerop font))
+		      (aref *tty-font-strings* font))
+	     (push (list* (font-change-font prev)
+			  (font-change-x prev)
+			  (dis-line-length dis-line))
+		   results))))
+       (nreverse results))
+    (when prev
+      (let ((font (font-change-font prev)))
+	(when (and (not (zerop font))
+		   (aref *tty-font-strings* font))
+	  (push (list* (font-change-font prev)
+		       (font-change-x prev)
+		       (font-change-x change))
+		results))))))
+
+
+
+;;;; Dumb window redisplay.
+
+(defmacro tty-dumb-line-redisplay (device hunk dis-line &optional y)
+  (let ((dl (gensym)) (dl-chars (gensym)) (dl-fonts (gensym)) (dl-len (gensym))
+	(dl-pos (gensym)) (screen-image-line (gensym)))
+    `(let* ((,dl ,dis-line)
+	    (,dl-chars (dis-line-chars ,dl))
+	    (,dl-fonts (compute-font-usages ,dis-line))
+	    (,dl-len (dis-line-length ,dl))
+	    (,dl-pos ,(or y `(dis-line-position ,dl))))
+       (funcall (tty-device-display-string ,device)
+		,hunk 0 ,dl-pos ,dl-chars ,dl-fonts 0 ,dl-len)
+       (setf (dis-line-flags ,dl) unaltered-bits)
+       (setf (dis-line-delta ,dl) 0)
+       (select-hunk ,hunk)
+       (let ((,screen-image-line (si-line (tty-device-screen-image ,device)
+					  (+ *hunk-top-line* ,dl-pos))))
+	 (replace-si-line (si-line-chars ,screen-image-line) ,dl-chars
+			  0 0 ,dl-len)
+	 (setf (si-line-length ,screen-image-line) ,dl-len)
+	 (setf (si-line-fonts ,screen-image-line) ,dl-fonts)))))
+
+(defun tty-dumb-window-redisplay (window)
+  (let* ((first (window-first-line window))
+	 (hunk (window-hunk window))
+	 (device (device-hunk-device hunk))
+	 (screen-image (tty-device-screen-image device)))
+    (funcall (tty-device-clear-to-eow device) hunk 0 0)
+    (do ((i 0 (1+ i))
+	 (dl (cdr first) (cdr dl)))
+	((eq dl the-sentinel)
+	 (setf (window-old-lines window) (1- i))
+	 (select-hunk hunk)
+	 (do ((last (tty-hunk-text-position hunk))
+	      (i (+ *hunk-top-line* i) (1+ i)))
+	     ((> i last))
+	   (declare (fixnum i last))
+	   (let ((si-line (si-line screen-image i)))
+	     (setf (si-line-length si-line) 0)
+	     (setf (si-line-fonts si-line) nil))))
+      (tty-dumb-line-redisplay device hunk (car dl) i))
+    (setf (window-first-changed window) the-sentinel
+	  (window-last-changed window) first)
+    (when (window-modeline-buffer window)
+      (let ((dl (window-modeline-dis-line window))
+	    (y (tty-hunk-modeline-pos hunk)))
+	(unwind-protect
+	    (progn
+	      (funcall (tty-device-standout-init device) hunk)
+	      (funcall (tty-device-clear-to-eol device) hunk 0 y)
+	      (tty-dumb-line-redisplay device hunk dl y))
+	  (funcall (tty-device-standout-end device) hunk))
+	(setf (dis-line-flags dl) unaltered-bits)))))
+
+
+
+
+;;;; Dumb redisplay top n lines of a window.
+
+(defun tty-redisplay-n-lines (window n)
+  (let* ((hunk (window-hunk window))
+	 (device (device-hunk-device hunk)))
+    (funcall (tty-device-clear-lines device) hunk 0 0 n)
+    (do ((n n (1- n))
+	 (dl (cdr (window-first-line window)) (cdr dl)))
+	((or (zerop n) (eq dl the-sentinel)))
+      (tty-dumb-line-redisplay device hunk (car dl)))))
+
+
+
+
+;;;; Semi dumb window redisplay
+
+;;; This is for terminals without opening and deleting lines.
+
+;;; TTY-SEMI-DUMB-WINDOW-REDISPLAY is a lot like TTY-SMART-WINDOW-REDISPLAY,
+;;; but it calls different line redisplay functions.
+;;; 
+(defun tty-semi-dumb-window-redisplay (window)
+  (let* ((hunk (window-hunk window))
+	 (device (device-hunk-device hunk)))
+    (let ((first-changed (window-first-changed window))
+	  (last-changed (window-last-changed window)))
+      ;; Is there anything to do?
+      (unless (eq first-changed the-sentinel)
+	(if ;; One line-changed.
+	    (and (eq first-changed last-changed)
+		 (zerop (dis-line-delta (car first-changed))))
+	    (tty-semi-dumb-line-redisplay device hunk (car first-changed))
+	    ;; More lines changed.
+	    (do-semi-dumb-line-writes first-changed last-changed hunk))
+	;; Set the bounds so we know we displayed...
+	(setf (window-first-changed window) the-sentinel
+	      (window-last-changed window) (window-first-line window))))
+    ;;
+    ;; Clear any extra lines at the end of the window.
+    (let ((pos (dis-line-position (car (window-last-line window)))))
+      (when (< pos (1- (window-height window)))
+	(tty-smart-clear-to-eow hunk (1+ pos)))
+      (setf (window-old-lines window) pos))
+    ;;
+    ;; Update the modeline if needed.
+    (when (window-modeline-buffer window)
+      (let ((dl (window-modeline-dis-line window)))
+	(when (/= (dis-line-flags dl) unaltered-bits)
+	  (unwind-protect
+	      (progn
+		(funcall (tty-device-standout-init device) hunk)
+		(tty-smart-line-redisplay device hunk dl
+					  (tty-hunk-modeline-pos hunk)))
+	    (funcall (tty-device-standout-end device) hunk)))))))
+
+;;; NEXT-DIS-LINE is used in DO-SEMI-DUMB-LINE-WRITES and
+;;; COMPUTE-TTY-CHANGES.
+;;; 
+(eval-when (:compile-toplevel :execute)
+(defmacro next-dis-line ()
+  `(progn 
+    (setf prev dl)
+    (setf dl (cdr dl))
+    (setf flags (dis-line-flags (car dl)))))
+) ;eval-when
+
+;;; DO-SEMI-DUMB-LINE-WRITES does what it says until it hits the last
+;;; changed line.  The commented out code was a gratuitous optimization,
+;;; especially if the first-changed line really is the first changes line.
+;;; Anyway, this had to be removed because of this function's use in
+;;; TTY-SMART-WINDOW-REDISPLAY, which was punting line moves due to
+;;; "Scroll Redraw Ratio".  However, these supposedly moved lines had their
+;;; bits set to unaltered bits in COMPUTE-TTY-CHANGES because it was
+;;; assuming TTY-SMART-WINDOW-REDISPLAY guaranteed to do line moves.
+;;; 
+(defun do-semi-dumb-line-writes (first-changed last-changed hunk)
+  (let* ((dl first-changed)
+	 flags ;(dis-line-flags (car dl))) flags bound for NEXT-DIS-LINE.
+	 prev)
+    ;;
+    ;; Skip old, unchanged, unmoved lines.
+    ;; (loop
+    ;;  (unless (zerop flags) (return))
+    ;;  (next-dis-line))
+    ;;
+    ;; Write every remaining line.
+    (let* ((device (device-hunk-device hunk))
+	   (force-output (device-force-output device)))
+      (loop
+       (tty-semi-dumb-line-redisplay device hunk (car dl))
+       (when force-output (funcall force-output))
+       (next-dis-line)
+       (when (eq prev last-changed) (return))))))
+
+;;; TTY-SEMI-DUMB-LINE-REDISPLAY finds the first different character
+;;; comparing the display line and the screen image line, writes out the
+;;; rest of the display line, and clears to end-of-line as necessary.
+;;; 
+(defun tty-semi-dumb-line-redisplay (device hunk dl
+				     &optional (dl-pos (dis-line-position dl)))
+  (declare (fixnum dl-pos))
+  (let* ((dl-chars (dis-line-chars dl))
+	 (dl-len (dis-line-length dl))
+	 (dl-fonts (compute-font-usages dl)))
+    (declare (fixnum dl-len) (simple-string dl-chars))
+    (when (listen-editor-input *editor-input*)
+      (throw 'redisplay-catcher :editor-input))
+    (select-hunk hunk)
+    (let* ((screen-image-line (si-line (tty-device-screen-image device)
+				       (+ *hunk-top-line* dl-pos)))
+	   (si-line-chars (si-line-chars screen-image-line))
+	   (si-line-length (si-line-length screen-image-line))
+	   (findex (find-identical-prefix dl dl-fonts screen-image-line)))
+      (declare (type (or fixnum null) findex) (simple-string si-line-chars))
+      ;;
+      ;; When the dis-line and screen chars are not string=.
+      (when findex
+	(cond
+	 ;; See if the screen shows an initial substring of the dis-line.
+	 ((= findex si-line-length)
+	  (funcall (tty-device-display-string device)
+		   hunk findex dl-pos dl-chars dl-fonts findex dl-len)
+	  (replace-si-line si-line-chars dl-chars findex findex dl-len))
+	 ;; When the dis-line is an initial substring of what's on the screen.
+	 ((= findex dl-len)
+	  (funcall (tty-device-clear-to-eol device) hunk dl-len dl-pos))
+	 ;; Otherwise, blast dl-chars and clear to eol as necessary.
+	 (t (funcall (tty-device-display-string device)
+		     hunk findex dl-pos dl-chars dl-fonts findex dl-len)
+	    (when (< dl-len si-line-length)
+	      (funcall (tty-device-clear-to-eol device) hunk dl-len dl-pos))
+	    (replace-si-line si-line-chars dl-chars findex findex dl-len)))
+	(setf (si-line-length screen-image-line) dl-len)
+	(setf (si-line-fonts screen-image-line) dl-fonts)))
+    (setf (dis-line-flags dl) unaltered-bits)
+    (setf (dis-line-delta dl) 0)))
+
+
+
+
+;;;; Smart window redisplay -- operation queues and internal screen image.
+
+;;; This is used for creating temporary smart redisplay structures.
+;;; 
+(defconstant tty-hunk-height-limit 100)
+
+
+;;; Queues for redisplay operations and access macros.
+;;; 
+(defvar *tty-line-insertions* (make-array (* 2 tty-hunk-height-limit)))
+
+(defvar *tty-line-deletions* (make-array (* 2 tty-hunk-height-limit)))
+
+(defvar *tty-line-writes* (make-array tty-hunk-height-limit))
+
+(defvar *tty-line-moves* (make-array tty-hunk-height-limit))
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro queue (value queue ptr)
+  `(progn
+    (setf (svref ,queue ,ptr) ,value)
+    (the fixnum (incf (the fixnum ,ptr)))))
+
+(defmacro dequeue (queue ptr)
+  `(prog1
+    (svref ,queue ,ptr)
+    (the fixnum (incf (the fixnum ,ptr)))))
+
+) ;eval-when
+
+;;; INSERT-LINE-COUNT is used in TTY-SMART-WINDOW-REDISPLAY.  The counting is
+;;; based on calls to QUEUE in COMPUTE-TTY-CHANGES.
+;;; 
+(defun insert-line-count (ins)
+  (do ((i 1 (+ i 2))
+       (count 0 (+ count (svref *tty-line-insertions* i))))
+      ((> i ins) count)))
+
+
+;;; Temporary storage for screen-image lines and accessing macros.
+;;; 
+(defvar *screen-image-temp* (make-array tty-hunk-height-limit))
+
+(eval-when (:compile-toplevel :execute)
+
+;;; DELETE-SI-LINES is used in DO-LINE-DELETIONS to simulate what's
+;;; happening to the screen in a device's screen-image.  At y, num
+;;; lines are deleted and saved in *screen-image-temp*; fsil is the
+;;; end of the free screen image lines saved here.  Also, we must
+;;; move lines up in the screen-image structure.  In the outer loop
+;;; we save lines in the temp storage and move lines up at the same
+;;; time.  In the termination/inner loop we move any lines that still
+;;; need to be moved up.  The screen-length is adjusted by the fsil
+;;; because any time a deletion is in progress, there are fsil bogus
+;;; lines at the bottom of the screen image from lines being moved
+;;; up previously.
+;;; 
+(defmacro delete-si-lines (screen-image y num fsil screen-length)
+  (let ((do-screen-image (gensym)) (delete-index (gensym))
+	(free-lines (gensym)) (source-index (gensym)) (target-index (gensym))
+	(n (gensym)) (do-screen-length (gensym)) (do-y (gensym)))
+    `(let ((,do-screen-image ,screen-image)
+	   (,do-screen-length (- ,screen-length fsil))
+	   (,do-y ,y))
+       (declare (fixnum ,do-screen-length ,do-y))
+       (do ((,delete-index ,do-y (1+ ,delete-index))
+	    (,free-lines ,fsil (1+ ,free-lines))
+	    (,source-index (+ ,do-y ,num) (1+ ,source-index))
+	    (,n ,num (1- ,n)))
+	   ((zerop ,n)
+	    (do ((,target-index ,delete-index (1+ ,target-index))
+		 (,source-index ,source-index (1+ ,source-index)))
+		((>= ,source-index ,do-screen-length))
+	      (declare (fixnum ,target-index ,source-index))
+	      (setf (si-line ,do-screen-image ,target-index)
+		    (si-line ,do-screen-image ,source-index))))
+	 (declare (fixnum ,delete-index ,free-lines ,source-index ,n))
+	 (setf (si-line *screen-image-temp* ,free-lines)
+	       (si-line ,do-screen-image ,delete-index))
+	 (when (< ,source-index ,do-screen-length)
+	   (setf (si-line ,do-screen-image ,delete-index)
+		 (si-line ,do-screen-image ,source-index)))))))
+
+
+;;; INSERT-SI-LINES is used in DO-LINE-INSERTIONS to simulate what's
+;;; happening to the screen in a device's screen-image.  At y, num free
+;;; lines are inserted from *screen-image-temp*; fsil is the end of the
+;;; free lines.  When copying lines down in screen-image, we must start
+;;; with the lower lines and end with the higher ones, so we don't trash
+;;; any lines.  The outer loop does all the copying, and the termination/
+;;; inner loop inserts the free screen image lines, setting their length
+;;; to zero.
+;;; 
+(defmacro insert-si-lines (screen-image y num fsil screen-length)
+  (let ((do-screen-image (gensym)) (source-index (gensym))
+	(target-index (gensym)) (target-terminus (gensym))
+	(do-screen-length (gensym)) (temp (gensym)) (do-y (gensym))
+	(insert-index (gensym)) (free-lines-index (gensym))
+	(n (gensym)))
+    `(let ((,do-screen-length ,screen-length)
+	   (,do-screen-image ,screen-image)
+	   (,do-y ,y))
+       (do ((,target-terminus (1- (+ ,do-y ,num)))	 ; (1- target-start)
+	    (,source-index (- ,do-screen-length ,fsil 1) ; (1- source-end)
+			   (1- ,source-index))
+	    (,target-index (- (+ ,do-screen-length ,num)
+			      ,fsil 1)			 ; (1- target-end)
+		(1- ,target-index)))
+	   ((= ,target-index ,target-terminus)
+	    (do ((,insert-index ,do-y (1+ ,insert-index))
+		 (,free-lines-index (1- ,fsil) (1- ,free-lines-index))
+		 (,n ,num (1- ,n)))
+		((zerop ,n))
+	      (declare (fixnum ,insert-index ,free-lines-index ,n))
+	      (let ((,temp (si-line *screen-image-temp* ,free-lines-index)))
+		(setf (si-line-length ,temp) 0)
+		(setf (si-line-fonts ,temp) nil)
+		(setf (si-line ,do-screen-image ,insert-index) ,temp)))
+	    (decf ,fsil ,num))
+	 (declare (fixnum ,target-terminus ,source-index ,target-index))
+	 (setf (si-line ,do-screen-image ,target-index)
+	       (si-line ,do-screen-image ,source-index))))))
+
+) ;eval-when
+
+
+
+
+;;;; Smart window redisplay -- the function.
+
+;;; TTY-SMART-WINDOW-REDISPLAY sees if only one line changed after
+;;; some preliminary processing.  If more than one line changed,
+;;; then we compute changes to make to the screen in the form of
+;;; line insertions, deletions, and writes.  Deletions must be done
+;;; first, so lines are not lost off the bottom of the screen by
+;;; inserting lines.
+;;; 
+(defun tty-smart-window-redisplay (window)
+  (let* ((hunk (window-hunk window))
+	 (device (device-hunk-device hunk)))
+    (let ((first-changed (window-first-changed window))
+	  (last-changed (window-last-changed window)))
+      ;; Is there anything to do?
+      (unless (eq first-changed the-sentinel)
+	(if (and (eq first-changed last-changed)
+		 (zerop (dis-line-delta (car first-changed))))
+	    ;; One line-changed.
+	    (tty-smart-line-redisplay device hunk (car first-changed))
+	    ;; More lines changed.
+	    (multiple-value-bind (ins outs writes moves)
+				 (compute-tty-changes
+				  first-changed last-changed
+				  (tty-hunk-modeline-pos hunk))
+	      (let ((ratio (variable-value 'hemlock::scroll-redraw-ratio)))
+		(cond ((and ratio
+			    (> (/ (insert-line-count ins)
+				  (tty-hunk-text-height hunk))
+			       ratio))
+		       (do-semi-dumb-line-writes first-changed last-changed
+						 hunk))
+		      (t
+		       (do-line-insertions hunk ins
+					   (do-line-deletions hunk outs))
+		       (note-line-moves moves)
+		       (do-line-writes hunk writes))))))
+	;; Set the bounds so we know we displayed...
+	(setf (window-first-changed window) the-sentinel
+	      (window-last-changed window) (window-first-line window))))
+    ;;
+    ;; Clear any extra lines at the end of the window.
+    (let ((pos (dis-line-position (car (window-last-line window)))))
+      (when (< pos (1- (window-height window)))
+	(tty-smart-clear-to-eow hunk (1+ pos)))
+      (setf (window-old-lines window) pos))
+    ;;
+    ;; Update the modeline if needed.
+    (when (window-modeline-buffer window)
+      (let ((dl (window-modeline-dis-line window)))
+	(when (/= (dis-line-flags dl) unaltered-bits)
+	  (unwind-protect
+	      (progn
+		(funcall (tty-device-standout-init device) hunk)
+		(tty-smart-line-redisplay device hunk dl
+					  (tty-hunk-modeline-pos hunk)))
+	    (funcall (tty-device-standout-end device) hunk)))))))
+
+
+
+
+;;;; Smart window redisplay -- computing changes to the display.
+
+;;; There is a lot of documentation here to help since this code is not
+;;; obviously correct.  The code is not that cryptic, but the correctness
+;;; of the algorithm is somewhat.  Most of the complexity is in handling
+;;; lines that moved on the screen which the introduction deals with.
+;;; Also, the block of documentation immediately before the function
+;;; COMPUTE-TTY-CHANGES has its largest portion dedicated to this part of
+;;; the function which is the largest block of code in the function.
+
+;;; The window image dis-lines are annotated with the difference between
+;;; their current intended locations and their previous locations in the
+;;; window.  This delta (distance moved) is negative for an upward move and
+;;; positive for a downward move.  To determine what to do with moved
+;;; groups of lines, we consider the transition (or difference in deltas)
+;;; between two adjacent groups as we look at the window's dis-lines moving
+;;; down the window image, disregarding whether they are contiguous (having
+;;; moved only by a different delta) or separated by some lines (such as
+;;; lines that are new and unmoved).
+;;;
+;;; Considering the transition between moved groups makes sense because a
+;;; given group's delta affects all the lines below it since the dis-lines
+;;; reflect the window's buffer's actual lines which are all connected in
+;;; series.  Therefore, if the previous group moved up some delta number of
+;;; lines because of line deletions, then the lines below this group (down
+;;; to the last line of the window image) moved up by the same delta too,
+;;; unless one of the following is true:
+;;;    1] The lines below the group moved up by a greater delta, possibly
+;;;       due to multiple disjoint buffer line deletions.
+;;;    2] The lines below the group moved up by a lesser delta, possibly
+;;;       due to a number (less than the previous delta) of new line
+;;;       insertions below the group that moved up.
+;;;    3] The lines below the group moved down, possibly due to a number
+;;;       (greater than the previous delta) of new line insertions below
+;;;       the group that moved up.
+;;; Similarly, if the previous group moved down some delta number of lines
+;;; because of new line insertions, then the lines below this group (down
+;;; to the last line of the window image not to fall off the window's lower
+;;; edge) moved down by the same delta too, unless one of the following is
+;;; true:
+;;;    1] The lines below the group moved down by a greater delta, possibly
+;;;       due to multiple disjoint buffer line insertions.
+;;;    2] The lines below the group moved down by a lesser delta, possibly
+;;;       due to a number (less than the previous delta) of line deletions
+;;;       below the group that moved down.
+;;;    3] The lines below the group moved up, possibly due to a number
+;;;       (greater than the previous delta) of line deletions below the
+;;;       group that moved down.
+;;;
+;;; Now we can see how the first moved group affects the window image below
+;;; it except where there is a lower group of lines that have moved a
+;;; different delta due to separate operations on the buffer's lines viewed
+;;; through a window.  We can see that this different delta is the expected
+;;; effect throughout the window image below the second group, unless
+;;; something lower down again has affected the window image.  Also, in the
+;;; case of a last group of lines that moved up, the group will never
+;;; reflect all of the lines in the window image from the first line to
+;;; move down to the bottom of the window image because somewhere down below
+;;; the group that moved up are some new lines that have just been drawn up
+;;; into the window's image.
+;;;
+
+;;; COMPUTE-TTY-CHANGES is used once in TTY-SMART-WINDOW-REDISPLAY.
+;;; It goes through all the display lines for a window recording where
+;;; lines need to be inserted, deleted, or written to make the screen
+;;; consistent with the internal image of the screen.  Pointers to
+;;; the insertions, deletions, and writes that have to be done are
+;;; returned.
+;;; 
+;;; If a line is new, then simply queue it to be written.
+;;; 
+;;; If a line is moved and/or changed, then we compute the difference
+;;; between the last block of lines that moved with the same delta and the
+;;; current block of lines that moved with the current delta.  If this
+;;; difference is positive, then some lines need to be deleted.  Since we
+;;; do all the line deletions first to prevent line insertions from
+;;; dropping lines off the bottom of the screen, we have to compute the
+;;; position of line deletions using the cumulative insertions
+;;; (cum-inserts).  Without any insertions, deletions may be done right at
+;;; the dis-line's new position.  With insertions needed above a given
+;;; deletion point combined with the fact that deletions are all done
+;;; first, the location for the deletion is higher than it would be without
+;;; the insertions being done above the deletions.  The location of the
+;;; deletion is higher by the number of insertions we have currently put
+;;; off.  When computing the position of line insertions (a negative delta
+;;; transition), we do not need to consider the cumulative insertions or
+;;; cumulative deletions since everything above the point of insertion
+;;; (both deletions and insertions) has been done.  Because of the screen
+;;; state being correct above the point of an insertion, the screen is only
+;;; off by the delta transition number of lines.  After determining the
+;;; line insertions or deletions, loop over contiguous lines with the same
+;;; delta queuing any changed ones to be written.  The delta and flag
+;;; fields are initialized according to the need to be written; since
+;;; redisplay may be interrupted by more user input after moves have been
+;;; done to the screen, we save the changed bit on, so the line will be
+;;; queued to be written after redisplay is re-entered.
+;;; 
+;;; If the line is changed or new, then queue it to be written.  Since we can
+;;; abort out of the actual dislpay at any time (due to pending input), we
+;;; don't clear the flags or delta here.  A dis-line may be groveled many times
+;;; by this function before it actually makes it to the screen, so we may have
+;;; odd combinations of bits such as both new and changed.
+;;; 
+;;; Otherwise, get the next display line, loop, and see if it's
+;;; interesting.
+;;; 
+(defun compute-tty-changes (first-changed last-changed modeline-pos)
+  (declare (fixnum modeline-pos))
+  (let* ((dl first-changed)
+	 (flags (dis-line-flags (car dl)))
+	 (ins 0) (outs 0) (writes 0) (moves 0)
+	 (prev-delta 0) (cum-deletes 0) (net-delta 0) (cum-inserts 0)
+	 prev)
+    (declare (fixnum flags ins outs writes moves prev-delta cum-deletes
+		     net-delta cum-inserts))
+    (loop
+      (cond
+       ((logtest flags new-bit)
+	(queue (car dl) *tty-line-writes* writes)
+	(next-dis-line))
+       ((logtest flags moved-bit)
+	(let* ((start-dl (car dl))
+	       (start-pos (dis-line-position start-dl))
+	       (curr-delta (dis-line-delta start-dl))
+	       (delta-delta (- prev-delta curr-delta))
+	       (car-dl start-dl))
+	  (declare (fixnum start-pos curr-delta delta-delta))
+	  (cond ((plusp delta-delta)
+		 (queue (the fixnum (- start-pos cum-inserts))
+			*tty-line-deletions* outs)
+		 (queue delta-delta *tty-line-deletions* outs)
+		 (incf cum-deletes delta-delta)
+		 (decf net-delta delta-delta))
+		((minusp delta-delta)
+		 (let ((eff-pos (the fixnum (+ start-pos delta-delta)))
+		       (num (the fixnum (- delta-delta))))
+		   (queue eff-pos *tty-line-insertions* ins)
+		   (queue num *tty-line-insertions* ins)
+		   (incf net-delta num)
+		   (incf cum-inserts num))))
+	  (loop
+	    (if (logtest flags (logior changed-bit new-bit))
+		(queue car-dl *tty-line-writes* writes)
+		(queue car-dl *tty-line-moves* moves))
+	    (next-dis-line)
+	    (setf car-dl (car dl))
+	    (when (or (eq prev last-changed)
+		      (/= (the fixnum (dis-line-delta car-dl)) curr-delta))
+	      (setf prev-delta curr-delta)
+	      (return)))))
+       ((logtest flags (logior changed-bit new-bit))
+	(queue (car dl) *tty-line-writes* writes)
+	(next-dis-line))
+       (t
+	(next-dis-line)))
+
+      (when (eq prev last-changed)
+	(unless (zerop net-delta)
+	  (cond ((plusp net-delta)
+		 (queue (the fixnum (- modeline-pos cum-deletes net-delta))
+			*tty-line-deletions* outs)
+		 (queue net-delta *tty-line-deletions* outs))
+		(t (queue (the fixnum (+ modeline-pos net-delta))
+			  *tty-line-insertions* ins)
+		   (queue (the fixnum (- net-delta))
+			  *tty-line-insertions* ins))))
+	(return (values ins outs writes moves))))))
+
+
+
+;;;; Smart window redisplay -- operation methods.
+
+;;; TTY-SMART-CLEAR-TO-EOW clears lines y through the last text line of hunk.
+;;; It takes care not to clear a line unless it really has some characters
+;;; displayed on it.  It also maintains the device's screen image lines.
+;;; 
+(defun tty-smart-clear-to-eow (hunk y)
+  (let* ((device (device-hunk-device hunk))
+	 (screen-image (tty-device-screen-image device))
+	 (clear-to-eol (tty-device-clear-to-eol device)))
+    (select-hunk hunk)
+    (do ((y y (1+ y))
+	 (si-idx (+ *hunk-top-line* y) (1+ si-idx))
+	 (last (tty-hunk-text-position hunk)))
+	((> si-idx last))
+      (declare (fixnum y si-idx last))
+      (let ((si-line (si-line screen-image si-idx)))
+	(unless (zerop (si-line-length si-line))
+	  (funcall clear-to-eol hunk 0 y)
+	  (setf (si-line-length si-line) 0)
+	  (setf (si-line-fonts si-line) nil))))))
+
+;;; NOTE-LINE-MOVES  --  Internal
+;;;
+;;;    Clear out the flags and delta of lines that have been moved.
+;;;
+(defun note-line-moves (moves)
+  (let ((i 0))
+    (loop
+      (when (= i moves) (return))
+      (let ((dl (dequeue *tty-line-moves* i)))
+	(setf (dis-line-flags dl) unaltered-bits)
+	(setf (dis-line-delta dl) 0)))))
+
+;;; DO-LINE-DELETIONS pops elements off the *tty-lines-deletions* queue,
+;;; deleting lines from hunk's area of the screen.  The internal screen
+;;; image is updated, and the total number of lines deleted is returned.
+;;; 
+(defun do-line-deletions (hunk outs)
+  (declare (fixnum outs))
+  (let* ((i 0)
+	 (device (device-hunk-device hunk))
+	 (fun (tty-device-delete-line device))
+	 (fsil 0)) ;free-screen-image-lines
+    (declare (fixnum i fsil))
+    (loop
+     (when (= i outs) (return fsil))
+     (let ((y (dequeue *tty-line-deletions* i))
+	   (num (dequeue *tty-line-deletions* i)))
+       (declare (fixnum y num))
+       (funcall fun hunk 0 y num)
+       (select-hunk hunk)
+       (delete-si-lines (tty-device-screen-image device)
+			(+ *hunk-top-line* y) num fsil
+			(tty-device-lines device))
+       (incf fsil num)))))
+
+;;; DO-LINE-INSERTIONS pops elements off the *tty-line-insertions* queue,
+;;; inserting lines into hunk's area of the screen.  The internal screen
+;;; image is updated using free screen image lines pointed to by fsil.
+;;; 
+(defun do-line-insertions (hunk ins fsil)
+  (declare (fixnum ins fsil))
+  (let* ((i 0)
+	 (device (device-hunk-device hunk))
+	 (fun (tty-device-open-line device)))
+    (declare (fixnum i))
+    (loop
+     (when (= i ins) (return))
+     (let ((y (dequeue *tty-line-insertions* i))
+	   (num (dequeue *tty-line-insertions* i)))
+       (declare (fixnum y num))
+       (funcall fun hunk 0 y num)
+       (select-hunk hunk)
+       (insert-si-lines (tty-device-screen-image device)
+			(+ *hunk-top-line* y) num fsil
+			(tty-device-lines device))))))
+
+;;; DO-LINE-WRITES pops elements off the *tty-line-writes* queue, displaying
+;;; these dis-lines with TTY-SMART-LINE-REDISPLAY.  We force output after
+;;; each line, so the user can see how far we've gotten in case he chooses
+;;; to give more editor commands which will abort redisplay until there's no
+;;; more input.
+;;; 
+(defun do-line-writes (hunk writes)
+  (declare (fixnum writes))
+  (let* ((i 0)
+	 (device (device-hunk-device hunk))
+	 (force-output (device-force-output device)))
+    (declare (fixnum i))
+    (loop
+     (when (= i writes) (return))
+     (tty-smart-line-redisplay device hunk (dequeue *tty-line-writes* i))
+     (when force-output (funcall force-output)))))
+
+;;; TTY-SMART-LINE-REDISPLAY uses an auxiliary screen image structure to
+;;; try to do minimal character shipping to the terminal.  Roughly, we find
+;;; the first different character when comparing what's on the screen and
+;;; what should be there; we will start altering the line after this same
+;;; initial substring.  Then we find, from the end, the first character
+;;; that is different, blasting out characters to the lesser of the two
+;;; indexes.  If the dis-line index is lesser, we have some characters to
+;;; delete from the screen, and if the screen index is lesser, we have some
+;;; additional dis-line characters to insert.  There are a few special
+;;; cases that allow us to punt out of the above algorithm sketch.  If the
+;;; terminal doesn't have insert mode or delete mode, we have blast out to
+;;; the end of the dis-line and possibly clear to the end of the screen's
+;;; line, as appropriate.  Sometimes we don't use insert or delete mode
+;;; because of the overhead cost in characters; it simply is cheaper to
+;;; blast out characters and clear to eol.
+;;; 
+(defun tty-smart-line-redisplay (device hunk dl
+				 &optional (dl-pos (dis-line-position dl)))
+  (declare (fixnum dl-pos))
+  (let* ((dl-chars (dis-line-chars dl))
+	 (dl-len (dis-line-length dl))
+	 (dl-fonts (compute-font-usages dl)))
+    (declare (fixnum dl-len) (simple-string dl-chars))
+    (when (listen-editor-input *editor-input*)
+      (throw 'redisplay-catcher :editor-input))
+    (select-hunk hunk)
+    (let* ((screen-image-line (si-line (tty-device-screen-image device)
+				       (+ *hunk-top-line* dl-pos)))
+	   (si-line-chars (si-line-chars screen-image-line))
+	   (si-line-length (si-line-length screen-image-line))
+	   (findex (find-identical-prefix dl dl-fonts screen-image-line)))
+      (declare (type (or fixnum null) findex) (simple-string si-line-chars))
+      ;;
+      ;; When the dis-line and screen chars are not string=.
+      (when findex
+	(block tslr-main-body
+	  ;;
+	  ;; See if the screen shows an initial substring of the dis-line.
+	  (when (= findex si-line-length)
+	    (funcall (tty-device-display-string device)
+		     hunk findex dl-pos dl-chars dl-fonts findex dl-len)
+	    (replace-si-line si-line-chars dl-chars findex findex dl-len)
+	    (return-from tslr-main-body t))
+	  ;;
+	  ;; When the dis-line is an initial substring of what's on the screen.
+	  (when (= findex dl-len)
+	    (funcall (tty-device-clear-to-eol device) hunk dl-len dl-pos)
+	    (return-from tslr-main-body t))
+	  ;;
+	  ;; Find trailing substrings that are the same.
+	  (multiple-value-bind
+	      (sindex dindex)
+	      (let ((count (find-identical-suffix dl dl-fonts
+						  screen-image-line)))
+		(values (- si-line-length count)
+			(- dl-len count)))
+	    (declare (fixnum sindex dindex))
+	    ;;
+	    ;; No trailing substrings -- blast and clear to eol.
+	    (when (= dindex dl-len)
+	      (funcall (tty-device-display-string device)
+		       hunk findex dl-pos dl-chars dl-fonts findex dl-len)
+	      (when (< dindex sindex)
+		(funcall (tty-device-clear-to-eol device)
+			 hunk dl-len dl-pos))
+	      (replace-si-line si-line-chars dl-chars findex findex dl-len)
+	      (return-from tslr-main-body t))
+	    (let ((lindex (min sindex dindex)))
+	      (cond ((< lindex findex)
+		     ;; This can happen in funny situations -- believe me!
+		     (setf lindex findex))
+		    (t
+		     (funcall (tty-device-display-string device)
+			      hunk findex dl-pos dl-chars dl-fonts
+			      findex lindex)
+		     (replace-si-line si-line-chars dl-chars
+				      findex findex lindex)))
+	      (cond
+	       ((= dindex sindex))
+	       ((< dindex sindex)
+		(let ((delete-char-num (- sindex dindex)))
+		  (cond ((and (tty-device-delete-char device)
+			      (worth-using-delete-mode
+			       device delete-char-num (- si-line-length dl-len)))
+			 (funcall (tty-device-delete-char device)
+				  hunk dindex dl-pos delete-char-num))
+			(t 
+			 (funcall (tty-device-display-string device)
+				  hunk dindex dl-pos dl-chars dl-fonts
+				  dindex dl-len)
+			 (funcall (tty-device-clear-to-eol device)
+				  hunk dl-len dl-pos)))))
+	       (t
+		(if (and (tty-device-insert-string device)
+			 (worth-using-insert-mode device (- dindex sindex)
+						  (- dl-len sindex)))
+		    (funcall (tty-device-insert-string device)
+			     hunk sindex dl-pos dl-chars sindex dindex)
+		    (funcall (tty-device-display-string device)
+			     hunk sindex dl-pos dl-chars dl-fonts
+			     sindex dl-len))))
+	      (replace-si-line si-line-chars dl-chars
+			       lindex lindex dl-len))))
+	(setf (si-line-length screen-image-line) dl-len)
+	(setf (si-line-fonts screen-image-line) dl-fonts)))
+    (setf (dis-line-flags dl) unaltered-bits)
+    (setf (dis-line-delta dl) 0)))
+
+
+
+
+;;;; Device methods
+
+;;; Initializing and exiting the device (DEVICE-INIT and DEVICE-EXIT functions).
+;;; These can be found in Tty-Display-Rt.Lisp.
+
+
+;;; Clearing the device (DEVICE-CLEAR functions).
+
+(defun clear-device (device)
+  (device-write-string (tty-device-clear-string device))
+  (cursor-motion device 0 0)
+  (setf (tty-device-cursor-x device) 0)
+  (setf (tty-device-cursor-y device) 0))
+
+
+;;; Moving the cursor around (DEVICE-PUT-CURSOR)
+
+;;; TTY-PUT-CURSOR makes sure the coordinates are mapped from the hunk's
+;;; axis to the screen's and determines the minimal cost cursor motion
+;;; sequence.  Currently, it does no cost analysis of relative motion
+;;; compared to absolute motion but simply makes sure the cursor isn't
+;;; already where we want it.
+;;;
+(defun tty-put-cursor (hunk x y)
+  (declare (fixnum x y))
+  (select-hunk hunk)
+  (let ((y (the fixnum (+ *hunk-top-line* y)))
+	(device (device-hunk-device hunk)))
+    (declare (fixnum y))
+    (unless (and (= (the fixnum (tty-device-cursor-x device)) x)
+		 (= (the fixnum (tty-device-cursor-y device)) y))
+      (cursor-motion device x y)
+      (setf (tty-device-cursor-x device) x)
+      (setf (tty-device-cursor-y device) y))))
+
+;;; UPDATE-CURSOR is used in device redisplay methods to make sure the
+;;; cursor is where it should be.
+;;; 
+(eval-when (:compile-toplevel :execute)
+  (defmacro update-cursor (hunk x y)
+    `(funcall (device-put-cursor (device-hunk-device ,hunk)) ,hunk ,x ,y))
+) ;eval-when
+
+;;; CURSOR-MOTION takes two coordinates on the screen's axis,
+;;; moving the cursor to that location.  X is the column index,
+;;; and y is the line index, but Unix and Termcap believe that
+;;; the default order of indexes is first the line and then the
+;;; column or (y,x).  Because of this, when reversep is non-nil,
+;;; we send first x and then y.
+;;; 
+(defun cursor-motion (device x y)
+  (let ((x-add-char (tty-device-cm-x-add-char device))
+	(y-add-char (tty-device-cm-y-add-char device))
+	(x-condx-add (tty-device-cm-x-condx-char device))
+	(y-condx-add (tty-device-cm-y-condx-char device))
+	(one-origin (tty-device-cm-one-origin device)))
+    (when x-add-char (incf x x-add-char))
+    (when (and x-condx-add (> x x-condx-add))
+      (incf x (tty-device-cm-x-condx-add-char device)))
+    (when y-add-char (incf y y-add-char))
+    (when (and y-condx-add (> y y-condx-add))
+      (incf y (tty-device-cm-y-condx-add-char device)))
+    (when one-origin (incf x) (incf y)))
+  (device-write-string (tty-device-cm-string1 device))
+  (let ((reversep (tty-device-cm-reversep device))
+	(x-pad (tty-device-cm-x-pad device))
+	(y-pad (tty-device-cm-y-pad device)))
+    (if reversep
+	(cm-output-coordinate x x-pad)
+	(cm-output-coordinate y y-pad))
+    (device-write-string (tty-device-cm-string2 device))
+    (if reversep
+	(cm-output-coordinate y y-pad)
+	(cm-output-coordinate x x-pad))
+    (device-write-string (tty-device-cm-string3 device))))
+
+;;; CM-OUTPUT-COORDINATE outputs the coordinate with respect to the pad.  If
+;;; there is a pad, then the coordinate needs to be sent as digit-char's (for
+;;; each digit in the coordinate), and if there is no pad, the coordinate needs
+;;; to be converted into a character.  Using CODE-CHAR here is not really
+;;; portable.  With a pad, the coordinate buffer is filled from the end as we
+;;; truncate the coordinate by 10, generating ones digits.
+;;;
+(defconstant cm-coordinate-buffer-len 5)
+(defvar *cm-coordinate-buffer* (make-string cm-coordinate-buffer-len))
+;;;
+(defun cm-output-coordinate (coordinate pad)
+  (cond (pad
+	 (let ((i (1- cm-coordinate-buffer-len)))
+	   (loop
+	     (when (= i -1) (error "Terminal has too many lines!"))
+	     (multiple-value-bind (tens ones)
+				  (truncate coordinate 10)
+	       (setf (schar *cm-coordinate-buffer* i) (digit-char ones))
+	       (when (zerop tens)
+		 (dotimes (n (- pad (- cm-coordinate-buffer-len i)))
+		   (decf i)
+		   (setf (schar *cm-coordinate-buffer* i) #\0))
+		 (device-write-string *cm-coordinate-buffer* i
+				      cm-coordinate-buffer-len)
+		 (return))
+	       (decf i)
+	       (setf coordinate tens)))))
+	(t (tty-write-char (code-char coordinate)))))
+
+
+;;; Writing strings (TTY-DEVICE-DISPLAY-STRING functions)
+
+;;; DISPLAY-STRING is used to put a string at (x,y) on the device.
+;;; 
+(defun display-string (hunk x y string font-info
+			    &optional (start 0) (end (strlen string)))
+  (declare (fixnum x y start end))
+  (update-cursor hunk x y)
+  ;; Ignore font info for chars before the start of the string.
+  (loop
+    (if (or (null font-info)
+	    (< start (cddar font-info)))
+	(return)
+	(pop font-info)))
+  (let ((posn start))
+    (dolist (next-font font-info)
+      (let ((font (car next-font))
+	    (start (cadr next-font))
+	    (stop (cddr next-font)))
+	(when (<= end start)
+	  (return))
+	(when (< posn start)
+	  (device-write-string string posn start)
+	  (setf posn start))
+	(let ((new-posn (min stop end))
+	      (font-strings (aref *tty-font-strings* font)))
+	  (unwind-protect
+	      (progn
+		(device-write-string (car font-strings))
+		(device-write-string string posn new-posn))
+	    (device-write-string (cdr font-strings)))
+	  (setf posn new-posn))))
+    (when (< posn end)
+      (device-write-string string posn end)))
+  (setf (tty-device-cursor-x (device-hunk-device hunk))
+	(the fixnum (+ x (the fixnum (- end start))))))
+
+;;; DISPLAY-STRING-CHECKING-UNDERLINES is used for terminals that special
+;;; case underlines doing an overstrike when they don't otherwise overstrike.
+;;; Note: we do not know in this code whether the terminal can backspace (or
+;;; what the sequence is), whether the terminal has insert-mode, or whether
+;;; the terminal has delete-mode.
+;;; 
+(defun display-string-checking-underlines (hunk x y string font-info
+						&optional (start 0)
+						          (end (strlen string)))
+  (declare (ignore font-info))
+  (declare (fixnum x y start end) (simple-string string))
+  (update-cursor hunk x y)
+  (let ((upos (position #\_ string :test #'char= :start start :end end))
+	(device (device-hunk-device hunk)))
+    (if upos
+	(let ((previous start)
+	      (after-pos 0))
+	  (declare (fixnum previous after-pos))
+	  (loop (device-write-string string previous upos)
+		(setf after-pos (do ((i (1+ upos) (1+ i)))
+				    ((or (= i end)
+					 (char/= (schar string i) #\_)) i)
+				  (declare (fixnum i))))
+		(let ((ulen (the fixnum (- after-pos upos)))
+		      (cursor-x (the fixnum (+ x (the fixnum
+						      (- after-pos start))))))
+		  (declare (fixnum ulen))
+		  (dotimes (i ulen) (tty-write-char #\space))
+		  (setf (tty-device-cursor-x device) cursor-x)
+		  (update-cursor hunk upos y)
+		  (dotimes (i ulen) (tty-write-char #\_))
+		  (setf (tty-device-cursor-x device) cursor-x))
+		(setf previous after-pos)
+		(setf upos (position #\_ string :test #'char=
+				     :start previous :end end))
+		(unless upos
+		  (device-write-string string previous end)
+		  (return))))
+	(device-write-string string start end))
+    (setf (tty-device-cursor-x device)
+	  (the fixnum (+ x (the fixnum (- end start)))))))
+	   
+
+;;; DEVICE-WRITE-STRING is used to shove a string at the terminal regardless
+;;; of cursor position.
+;;; 
+(defun device-write-string (string &optional (start 0) (end (strlen string)))
+  (declare (fixnum start end))
+  (unless (= start end)
+    (tty-write-string string start (the fixnum (- end start)))))
+
+
+;;; Clearing lines (TTY-DEVICE-CLEAR-TO-EOL, DEVICE-CLEAR-LINES, and
+;;; TTY-DEVICE-CLEAR-TO-EOW functions.)
+
+(defun clear-to-eol (hunk x y)
+  (update-cursor hunk x y)
+  (device-write-string
+   (tty-device-clear-to-eol-string (device-hunk-device hunk))))
+
+(defun space-to-eol (hunk x y)
+  (declare (fixnum x))
+  (update-cursor hunk x y)
+  (let* ((device (device-hunk-device hunk))
+	 (num (- (the fixnum (tty-device-columns device))
+		 x)))
+    (declare (fixnum num))
+    (dotimes (i num) (tty-write-char #\space))
+    (setf (tty-device-cursor-x device) (+ x num))))
+
+(defun clear-lines (hunk x y n)
+  (let* ((device (device-hunk-device hunk))
+	 (clear-to-eol (tty-device-clear-to-eol device)))
+    (funcall clear-to-eol hunk x y)
+    (do ((y (1+ y) (1+ y))
+	 (count (1- n) (1- count)))
+	((zerop count)
+	 (setf (tty-device-cursor-x device) 0)
+	 (setf (tty-device-cursor-y device) (1- y)))
+      (declare (fixnum count y))
+      (funcall clear-to-eol hunk 0 y))))
+
+(defun clear-to-eow (hunk x y)
+  (declare (fixnum x y))
+  (funcall (tty-device-clear-lines (device-hunk-device hunk))
+	   hunk x y
+	   (the fixnum (- (the fixnum (tty-hunk-text-height hunk)) y))))
+
+
+;;; Opening and Deleting lines (TTY-DEVICE-OPEN-LINE and TTY-DEVICE-DELETE-LINE)
+
+(defun open-tty-line (hunk x y &optional (n 1))
+  (update-cursor hunk x y)
+  (dotimes (i n)
+    (device-write-string (tty-device-open-line-string (device-hunk-device hunk)))))
+
+(defun delete-tty-line (hunk x y &optional (n 1))
+  (update-cursor hunk x y)
+  (dotimes (i n)
+    (device-write-string (tty-device-delete-line-string (device-hunk-device hunk)))))
+
+
+;;; Insert and Delete modes (TTY-DEVICE-INSERT-STRING and TTY-DEVICE-DELETE-CHAR)
+
+(defun tty-insert-string (hunk x y string
+			   &optional (start 0) (end (strlen string)))
+  (declare (fixnum x y start end))
+  (update-cursor hunk x y)
+  (let* ((device (device-hunk-device hunk))
+	 (init-string (tty-device-insert-init-string device))
+	 (char-init-string (tty-device-insert-char-init-string device))
+	 (char-end-string (tty-device-insert-char-end-string device))
+	 (end-string (tty-device-insert-end-string device)))
+    (declare (type (or simple-string null) char-init-string char-end-string))
+    (when init-string (device-write-string init-string))
+    (if char-init-string
+	(let ((cis-len (length char-init-string))
+	      (ces-len (length char-end-string)))
+	  (do ((i start (1+ i)))
+	      ((= i end))
+	    (device-write-string char-init-string 0 cis-len)
+	    (tty-write-char (schar string i))
+	    (when char-end-string
+	      (device-write-string char-end-string 0 ces-len))))
+	(device-write-string string start end))
+    (when end-string (device-write-string end-string))
+    (setf (tty-device-cursor-x device)
+	  (the fixnum (+ x (the fixnum (- end start)))))))
+
+(defun worth-using-insert-mode (device insert-char-num chars-saved)
+  (let* ((init-string (tty-device-insert-init-string device))
+	 (char-init-string (tty-device-insert-char-init-string device))
+	 (char-end-string (tty-device-insert-char-end-string device))
+	 (end-string (tty-device-insert-end-string device))
+	 (cost 0))
+    (when init-string (incf cost (length (the simple-string init-string))))
+    (when char-init-string
+      (incf cost (* insert-char-num (+ (length (the simple-string
+						    char-init-string))
+				       (if char-end-string
+					   (length (the simple-string
+							char-end-string))
+					   0)))))
+    (when end-string (incf cost (length (the simple-string end-string))))
+    (< cost chars-saved)))
+
+(defun delete-char (hunk x y &optional (n 1))
+  (declare (fixnum x y n))
+  (update-cursor hunk x y)
+  (let* ((device (device-hunk-device hunk))
+	 (init-string (tty-device-delete-init-string device))
+	 (end-string (tty-device-delete-end-string device))
+	 (delete-char-string (tty-device-delete-char-string device)))
+    (when init-string (device-write-string init-string))
+    (dotimes (i n)
+      (device-write-string delete-char-string))
+    (when end-string (device-write-string end-string))))
+
+(defun worth-using-delete-mode (device delete-char-num clear-char-num)
+  (declare (fixnum delete-char-num clear-char-num))
+  (let ((init-string (tty-device-delete-init-string device))
+	(end-string (tty-device-delete-end-string device))
+	(delete-char-string (tty-device-delete-char-string device))
+	(clear-to-eol-string (tty-device-clear-to-eol-string device))
+	(cost 0))
+    (declare (type (or simple-string null) init-string end-string
+		   delete-char-string)
+	     (fixnum cost))
+    (when init-string (incf cost (the fixnum (length init-string))))
+    (when end-string (incf cost (the fixnum (length end-string))))
+    (incf cost (the fixnum
+		    (* (the fixnum (length delete-char-string))
+		       delete-char-num)))
+    (< cost (+ delete-char-num
+	       (if clear-to-eol-string
+		   (length clear-to-eol-string)
+		   clear-char-num)))))
+
+
+;;; Standout mode (TTY-DEVICE-STANDOUT-INIT and TTY-DEVICE-STANDOUT-END)
+
+(defun standout-init (hunk)
+  (device-write-string
+   (tty-device-standout-init-string (device-hunk-device hunk))))
+
+(defun standout-end (hunk)
+  (device-write-string
+   (tty-device-standout-end-string (device-hunk-device hunk))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-screen.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-screen.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/tty/tty-screen.lisp	(revision 13309)
@@ -0,0 +1,404 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Written by Bill Chiles, except for the code that implements random typeout,
+;;; which was done by Blaine Burks and Bill Chiles.  The code for splitting
+;;; windows was rewritten by Blaine Burks to allow more than a 50/50 split.
+;;;
+;;; Terminal device screen management functions.
+;;;
+
+(in-package :hemlock-internals)
+
+
+
+
+;;;; Terminal screen initialization
+
+(declaim (special *parse-starting-mark*))
+
+(defun init-tty-screen-manager (tty-name)
+  (setf *line-wrap-char* #\!)
+  (setf *window-list* ())
+  (let* ((device (make-tty-device tty-name))
+	 (width (tty-device-columns device))
+	 (height (tty-device-lines device))
+	 (echo-height (value hemlock::echo-area-height))
+	 (main-lines (- height echo-height 1)) ;-1 for echo modeline.
+	 (main-text-lines (1- main-lines)) ;also main-modeline-pos.
+	 (last-text-line (1- main-text-lines)))
+    (setf (device-bottom-window-base device) last-text-line)
+    ;;
+    ;; Make echo area.
+    (let* ((echo-hunk (make-tty-hunk :position (1- height) :height echo-height
+				     :text-position (- height 2)
+				     :text-height echo-height :device device))
+	   (echo (internal-make-window :hunk echo-hunk)))
+      (setf *echo-area-window* echo)
+      (setf (device-hunk-window echo-hunk) echo)
+      (setup-window-image *parse-starting-mark* echo echo-height width)
+      (setup-modeline-image *echo-area-buffer* echo)
+      (setf (device-hunk-previous echo-hunk) echo-hunk
+	    (device-hunk-next echo-hunk) echo-hunk)
+      (prepare-window-for-redisplay echo))
+    ;;
+    ;; Make the main window.
+    (let* ((main-hunk (make-tty-hunk :position main-text-lines
+				     :height main-lines
+				     :text-position last-text-line
+				     :text-height main-text-lines
+				     :device device))
+	   (main (internal-make-window :hunk main-hunk)))
+      (setf (device-hunk-window main-hunk) main)
+      (setf *current-window* main)
+      (setup-window-image (buffer-point *current-buffer*)
+			  main main-text-lines width)
+      (setup-modeline-image *current-buffer* main)
+      (prepare-window-for-redisplay main)
+      (setf (device-hunk-previous main-hunk) main-hunk
+	    (device-hunk-next main-hunk) main-hunk)
+      (setf (device-hunks device) main-hunk))
+    (defhvar "Paren Pause Period"
+      "This is how long commands that deal with \"brackets\" shows the cursor at
+      the matching \"bracket\" for this number of seconds."
+      :value 0.5
+      :mode "Lisp")))
+
+
+
+
+;;;; Building devices from termcaps.
+
+;;; MAKE-TTY-DEVICE returns a device built from a termcap.  Some function
+;;; slots are set to the appropriate function even though the capability
+;;; might not exist; in this case, we simply set the control string value
+;;; to the empty string.  Some function slots are set differently depending
+;;; on available capability.
+;;;
+(defun make-tty-device (name)
+  (let ((termcap (get-termcap name))
+	(device (%make-tty-device :name name)))
+    (when (termcap :overstrikes termcap)
+      (error "Terminal sufficiently irritating -- not currently supported."))
+    ;;
+    ;; Similar device slots.
+    (setf (device-init device) #'init-tty-device)
+    (setf (device-exit device) #'exit-tty-device)
+    (setf (device-smart-redisplay device)
+	  (if (and (termcap :open-line termcap) (termcap :delete-line termcap))
+	      #'tty-smart-window-redisplay
+	      #'tty-semi-dumb-window-redisplay))
+    (setf (device-dumb-redisplay device) #'tty-dumb-window-redisplay)
+    (setf (device-clear device) #'clear-device)
+    (setf (device-put-cursor device) #'tty-put-cursor)
+    (setf (device-show-mark device) #'tty-show-mark)
+    (setf (device-next-window device) #'tty-next-window)
+    (setf (device-previous-window device) #'tty-previous-window)
+    (setf (device-make-window device) #'tty-make-window)
+    (setf (device-delete-window device) #'tty-delete-window)
+    (setf (device-random-typeout-setup device) #'tty-random-typeout-setup)
+    (setf (device-random-typeout-cleanup device) #'tty-random-typeout-cleanup)
+    (setf (device-random-typeout-full-more device) #'do-tty-full-more)
+    (setf (device-random-typeout-line-more device)
+	  #'update-tty-line-buffered-stream)
+    (setf (device-force-output device) #'tty-force-output)
+    (setf (device-finish-output device) #'tty-finish-output)
+    (setf (device-beep device) #'tty-beep)
+    ;;
+    ;; A few useful values.
+    (setf (tty-device-dumbp device)
+	  (not (and (termcap :open-line termcap)
+		    (termcap :delete-line termcap))))
+    ;;
+    ;; Get size and speed.
+    (multiple-value-bind  (lines cols speed)
+			  (get-terminal-attributes)
+      (setf (tty-device-lines device) (or lines (termcap :lines termcap)))
+      (let ((cols (or cols (termcap :columns termcap))))
+	(setf (tty-device-columns device)
+	      (if (termcap :auto-margins-p termcap)
+		  (1- cols) cols)))
+      (setf (tty-device-speed device) speed))
+    ;;
+    ;; Some function slots.
+    (setf (tty-device-display-string device)
+	  (if (termcap :underlines termcap)
+	      #'display-string-checking-underlines
+	      #'display-string))
+    (setf (tty-device-standout-init device) #'standout-init)
+    (setf (tty-device-standout-end device) #'standout-end)
+    (setf (tty-device-open-line device)
+	  (if (termcap :open-line termcap)
+	      #'open-tty-line
+	      ;; look for scrolling region stuff
+	      ))
+    (setf (tty-device-delete-line device)
+	  (if (termcap :delete-line termcap)
+	      #'delete-tty-line
+	      ;; look for reverse scrolling stuff
+	      ))
+    (setf (tty-device-clear-to-eol device)
+	  (if (termcap :clear-to-eol termcap)
+	      #'clear-to-eol
+	      #'space-to-eol))
+    (setf (tty-device-clear-lines device) #'clear-lines)
+    (setf (tty-device-clear-to-eow device) #'clear-to-eow)
+    ;;
+    ;; Insert and delete modes.
+    (let ((init-insert-mode (termcap :init-insert-mode termcap))
+	  (init-insert-char (termcap :init-insert-char termcap))
+	  (end-insert-char (termcap :end-insert-char termcap)))
+      (when (and init-insert-mode (string/= init-insert-mode ""))
+	(setf (tty-device-insert-string device) #'tty-insert-string)
+	(setf (tty-device-insert-init-string device) init-insert-mode)
+	(setf (tty-device-insert-end-string device)
+	      (termcap :end-insert-mode termcap)))
+      (when init-insert-char
+	(setf (tty-device-insert-string device) #'tty-insert-string)
+	(setf (tty-device-insert-char-init-string device) init-insert-char))
+      (when (and end-insert-char (string/= end-insert-char ""))
+	(setf (tty-device-insert-char-end-string device) end-insert-char)))
+    (let ((delete-char (termcap :delete-char termcap)))
+      (when delete-char
+	(setf (tty-device-delete-char device) #'delete-char)
+	(setf (tty-device-delete-char-string device) delete-char)
+	(setf (tty-device-delete-init-string device)
+	      (termcap :init-delete-mode termcap))
+	(setf (tty-device-delete-end-string device)
+	      (termcap :end-delete-mode termcap))))
+    ;;
+    ;; Some string slots.
+    (setf (tty-device-standout-init-string device)
+	  (or (termcap :init-standout-mode termcap) ""))
+    (setf (tty-device-standout-end-string device)
+	  (or (termcap :end-standout-mode termcap) ""))
+    (setf (tty-device-clear-to-eol-string device)
+	  (termcap :clear-to-eol termcap))
+    (let ((clear-string (termcap :clear-display termcap)))
+      (unless clear-string
+	(error "Terminal not sufficiently powerful enough to run Hemlock."))
+      (setf (tty-device-clear-string device) clear-string))
+    (setf (tty-device-open-line-string device)
+	  (termcap :open-line termcap))
+    (setf (tty-device-delete-line-string device)
+	  (termcap :delete-line termcap))
+    (let* ((init-string (termcap :init-string termcap))
+	   (init-file (termcap :init-file termcap))
+	   (init-file-string (if init-file (get-init-file-string init-file)))
+	   (init-cm-string (termcap :init-cursor-motion termcap)))
+      (setf (tty-device-init-string device)
+	    (concatenate 'simple-string (or init-string "")
+			 (or init-file-string "") (or init-cm-string ""))))
+    (setf (tty-device-cm-end-string device)
+	  (or (termcap :end-cursor-motion termcap) ""))
+    ;;
+    ;; Cursor motion slots.
+    (let ((cursor-motion (termcap :cursor-motion termcap)))
+      (unless cursor-motion
+	(error "Terminal not sufficiently powerful enough to run Hemlock."))
+      (let ((x-add-char (getf cursor-motion :x-add-char))
+	    (y-add-char (getf cursor-motion :y-add-char))
+	    (x-condx-char (getf cursor-motion :x-condx-char))
+	    (y-condx-char (getf cursor-motion :y-condx-char)))
+	(when x-add-char
+	  (setf (tty-device-cm-x-add-char device) (char-code x-add-char)))
+	(when y-add-char
+	  (setf (tty-device-cm-y-add-char device) (char-code y-add-char)))
+	(when x-condx-char
+	  (setf (tty-device-cm-x-condx-char device) (char-code x-condx-char))
+	  (setf (tty-device-cm-x-condx-add-char device)
+		(char-code (getf cursor-motion :x-condx-add-char))))
+	(when y-condx-char
+	  (setf (tty-device-cm-y-condx-char device) (char-code y-condx-char))
+	  (setf (tty-device-cm-y-condx-add-char device)
+		(char-code (getf cursor-motion :y-condx-add-char)))))
+      (setf (tty-device-cm-string1 device) (getf cursor-motion :string1))
+      (setf (tty-device-cm-string2 device) (getf cursor-motion :string2))
+      (setf (tty-device-cm-string3 device) (getf cursor-motion :string3))
+      (setf (tty-device-cm-one-origin device) (getf cursor-motion :one-origin))
+      (setf (tty-device-cm-reversep device) (getf cursor-motion :reversep))
+      (setf (tty-device-cm-x-pad device) (getf cursor-motion :x-pad))
+      (setf (tty-device-cm-y-pad device) (getf cursor-motion :y-pad)))
+    ;;
+    ;; Screen image initialization.
+    (let* ((lines (tty-device-lines device))
+	   (columns (tty-device-columns device))
+	   (screen-image (make-array lines)))
+      (dotimes (i lines)
+	(setf (svref screen-image i) (make-si-line columns)))
+      (setf (tty-device-screen-image device) screen-image))
+    device))
+
+
+
+      
+;;;; Making a window
+
+(defun tty-make-window (device start modelinep window font-family
+			       ask-user x y width height proportion)
+  (declare (ignore window font-family ask-user x y width height))
+  (let* ((old-window (current-window))
+	 (victim (window-hunk old-window))
+	 (text-height (tty-hunk-text-height victim))
+	 (availability (if modelinep (1- text-height) text-height)))
+    (when (> availability 1)
+      (let* ((new-lines (truncate (* availability proportion)))
+	     (old-lines (- availability new-lines))
+	     (pos (device-hunk-position victim))
+	     (new-height (if modelinep (1+ new-lines) new-lines))
+	     (new-text-pos (if modelinep (1- pos) pos))
+	     (new-hunk (make-tty-hunk :position pos
+				      :height new-height
+				      :text-position new-text-pos
+				      :text-height new-lines
+				      :device device))
+	     (new-window (internal-make-window :hunk new-hunk)))
+	(declare (fixnum new-lines old-lines pos new-height new-text-pos))
+	(setf (device-hunk-window new-hunk) new-window)
+	(let* ((old-text-pos-diff (- pos (tty-hunk-text-position victim)))
+	       (old-win-new-pos (- pos new-height)))
+	  (declare (fixnum old-text-pos-diff old-win-new-pos))
+	  (setf (device-hunk-height victim)
+		(- (device-hunk-height victim) new-height))
+	  (setf (tty-hunk-text-height victim) old-lines)
+	  (setf (device-hunk-position victim) old-win-new-pos)
+	  (setf (tty-hunk-text-position victim)
+		(- old-win-new-pos old-text-pos-diff)))
+	(setup-window-image start new-window new-lines
+			    (window-width old-window))
+	(prepare-window-for-redisplay new-window)
+	(when modelinep
+	  (setup-modeline-image (line-buffer (mark-line start)) new-window))
+	(change-window-image-height old-window old-lines)
+	(shiftf (device-hunk-previous new-hunk)
+		(device-hunk-previous (device-hunk-next victim))
+		new-hunk)
+	(shiftf (device-hunk-next new-hunk) (device-hunk-next victim) new-hunk)
+	(setf *currently-selected-hunk* nil)
+	(setf *screen-image-trashed* t)
+	new-window))))
+
+
+
+
+;;;; Deleting a window
+
+(defun tty-delete-window (window)
+  (let* ((hunk (window-hunk window))
+	 (prev (device-hunk-previous hunk))
+	 (next (device-hunk-next hunk))
+	 (device (device-hunk-device hunk)))
+    (setf (device-hunk-next prev) next)
+    (setf (device-hunk-previous next) prev)
+    (let ((buffer (window-buffer window)))
+      (setf (buffer-windows buffer) (delq window (buffer-windows buffer))))
+    (let ((new-lines (device-hunk-height hunk)))
+      (declare (fixnum new-lines))
+      (cond ((eq hunk (device-hunks (device-hunk-device next)))
+	     (incf (device-hunk-height next) new-lines)
+	     (incf (tty-hunk-text-height next) new-lines)
+	     (let ((w (device-hunk-window next)))
+	       (change-window-image-height w (+ new-lines (window-height w)))))
+	    (t
+	     (incf (device-hunk-height prev) new-lines)
+	     (incf (device-hunk-position prev) new-lines)
+	     (incf (tty-hunk-text-height prev) new-lines)
+	     (incf (tty-hunk-text-position prev) new-lines)
+	     (let ((w (device-hunk-window prev)))
+	       (change-window-image-height w (+ new-lines (window-height w)))))))
+    (when (eq hunk (device-hunks device))
+      (setf (device-hunks device) next)))
+  (setf *currently-selected-hunk* nil)
+  (setf *screen-image-trashed* t))
+
+
+
+
+;;;; Next and Previous window operations.
+
+(defun tty-next-window (window)
+  (device-hunk-window (device-hunk-next (window-hunk window))))
+
+(defun tty-previous-window (window)
+  (device-hunk-window (device-hunk-previous (window-hunk window))))
+
+
+
+
+;;;; Random typeout support
+
+(defun tty-random-typeout-setup (device stream height)
+  (declare (fixnum height))
+  (let* ((*more-prompt-action* :empty)
+	 (height (min (1- (device-bottom-window-base device)) height))
+	 (old-hwindow (random-typeout-stream-window stream))
+	 (new-hwindow (if old-hwindow
+			  (change-tty-random-typeout-window old-hwindow height)
+			  (setf (random-typeout-stream-window stream)
+				(make-tty-random-typeout-window
+				 device
+				 (buffer-start-mark
+				  (line-buffer
+				   (mark-line
+				    (random-typeout-stream-mark stream))))
+				 height)))))
+    (funcall (tty-device-clear-to-eow device) (window-hunk new-hwindow) 0 0)))
+
+(defun change-tty-random-typeout-window (window height)
+  (update-modeline-field (window-buffer window) window :more-prompt)
+  (let* ((height-1 (1- height))
+	 (hunk (window-hunk window)))
+    (setf (device-hunk-position hunk) height-1
+	  (device-hunk-height hunk) height
+	  (tty-hunk-text-position hunk) (1- height-1)
+	  (tty-hunk-text-height hunk) height-1)
+    (change-window-image-height window height-1)
+    window))
+
+(defun make-tty-random-typeout-window (device mark height)
+  (let* ((height-1 (1- height))
+	 (hunk (make-tty-hunk :position height-1
+			      :height height
+			      :text-position (1- height-1)
+			      :text-height height-1
+			      :device device))
+	 (window (internal-make-window :hunk hunk)))
+    (setf (device-hunk-window hunk) window)
+    (setf (device-hunk-device hunk) device)
+    (setup-window-image mark window height-1 (tty-device-columns device))
+    (setf *window-list* (delete window *window-list*))
+    (prepare-window-for-redisplay window)
+    (setup-modeline-image (line-buffer (mark-line mark)) window)
+    (update-modeline-field (window-buffer window) window :more-prompt)
+    window))
+
+(defun tty-random-typeout-cleanup (stream degree)
+  (declare (ignore degree))
+  (let* ((window (random-typeout-stream-window stream))
+	 (stream-hunk (window-hunk window))
+	 (last-line-affected (device-hunk-position stream-hunk))
+	 (device (device-hunk-device stream-hunk))
+	 (*more-prompt-action* :normal))
+    (declare (fixnum last-line-affected))
+    (update-modeline-field (window-buffer window) window :more-prompt)
+    (funcall (tty-device-clear-to-eow device) stream-hunk 0 0)
+    (do* ((hunk (device-hunks device) (device-hunk-next hunk))
+	  (window (device-hunk-window hunk) (device-hunk-window hunk))
+	  (last (device-hunk-previous hunk)))
+	 ((>= (device-hunk-position hunk) last-line-affected)
+	  (if (= (device-hunk-position hunk) last-line-affected)
+	      (redisplay-window-all window)
+	      (tty-redisplay-n-lines window
+				     (- (+ last-line-affected
+					   (tty-hunk-text-height hunk))
+					(tty-hunk-text-position hunk)))))
+      (redisplay-window-all window)
+      (when (eq hunk last) (return)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/unixcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/unixcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/unixcoms.lisp	(revision 13309)
@@ -0,0 +1,258 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;
+;;; This file contains Commands useful when running on a Unix box.  Hopefully
+;;; there are no CMU Unix dependencies though there are probably CMU Common
+;;; Lisp dependencies, such as RUN-PROGRAM.
+;;;
+;;; Written by Christopher Hoover.
+
+(in-package :hemlock)
+
+
+
+
+;;;; Region and File printing commands.
+
+(defhvar "Print Utility"
+  "UNIX(tm) program to invoke (via EXT:RUN-PROGRAM) to do printing.
+   The program should act like lpr: if a filename is given as an argument,
+   it should print that file, and if no name appears, standard input should
+   be assumed."
+  :value "lpr")
+
+(defhvar "Print Utility Switches"
+  "Switches to pass to the \"Print Utility\" program.  This should be a list
+   of strings."
+  :value ())
+
+
+;;; PRINT-SOMETHING calls RUN-PROGRAM on the utility-name and args.  Output
+;;; and error output are done to the echo area, and errors are ignored for
+;;; now.  Run-program-keys are other keywords to pass to RUN-PROGRAM in
+;;; addition to :wait, :output, and :error.
+;;; 
+(defmacro print-something (&optional (run-program-keys)
+				     (utility-name '(value print-utility))
+				     (args '(value print-utility-switches)))
+  (let ((pid (gensym))
+	(error-code (gensym)))
+    `(multiple-value-bind (,pid ,error-code)
+			  (ext:run-program ,utility-name ,args
+					   ,@run-program-keys
+					   :wait t
+					   :output *echo-area-stream*
+					   :error *echo-area-stream*)
+       (declare (ignore ,pid ,error-code))
+       (force-output *echo-area-stream*)
+       ;; Keep the echo area from being cleared at the top of the command loop.
+       (setf (buffer-modified *echo-area-buffer*) nil))))
+
+
+;;; PRINT-REGION -- Interface
+;;;
+;;; Takes a region and outputs the text to the program defined by
+;;; the hvar "Print Utility" with options form the hvar "Print
+;;; Utility Options" using PRINT-SOMETHING.
+;;; 
+(defun print-region (region)
+  (with-input-from-region (s region)
+    (print-something (:input s))))
+
+
+(defcommand "Print Buffer" (p)
+  "Prints the current buffer using the program defined by the hvar
+   \"Print Utility\" with the options from the hvar \"Print Utility
+   Options\".   Errors appear in the echo area."
+  "Prints the contents of the buffer."
+  (declare (ignore p))
+  (message "Printing buffer...~%")
+  (print-region (buffer-region (current-buffer))))
+
+(defcommand "Print Region" (p)
+  "Prints the current region using the program defined by the hvar
+   \"Print Utility\" with the options from the hvar \"Print Utility
+   Options\".  Errors appear in the echo area."
+  "Prints the current region."
+  (declare (ignore p))
+  (message "Printing region...~%")
+  (print-region (current-region)))
+
+(defcommand "Print File" (p)
+  "Prompts for a file and prints it usings the program defined by
+   the hvar \"Print Utility\" with the options from the hvar \"Print
+   Utility Options\".  Errors appear in the echo area."
+  "Prints a file."
+  (declare (ignore p))
+  (let* ((pn (prompt-for-file :prompt "File to print: "
+			      :help "Name of file to print."
+			      :default (buffer-default-pathname (current-buffer))
+			      :must-exist t))
+	 (ns (namestring (truename pn))))
+    (message "Printing file...~%")
+    (print-something () (value print-utility)
+		     (append (value print-utility-switches) (list ns)))))
+
+
+
+;;;; Scribe.
+
+(defcommand "Scribe File" (p)
+  "Scribe a file with the default directory set to the directory of the
+   specified file.  The output from running Scribe is sent to the
+   \"Scribe Warnings\" buffer.  See \"Scribe Utility\" and \"Scribe Utility
+   Switches\"."
+  "Scribe a file with the default directory set to the directory of the
+   specified file."
+  (declare (ignore p))
+  (scribe-file (prompt-for-file :prompt "Scribe file: "
+				:default
+				(buffer-default-pathname (current-buffer)))))
+
+(defhvar "Scribe Buffer File Confirm"
+  "When set, \"Scribe Buffer File\" prompts for confirmation before doing
+   anything."
+  :value t)
+
+(defcommand "Scribe Buffer File" (p)
+  "Scribe the file associated with the current buffer.  The default directory
+   set to the directory of the file.  The output from running Scribe is sent to
+   the \"Scribe Warnings\" buffer.  See \"Scribe Utility\" and \"Scribe Utility
+   Switches\".  Before doing anything the user is asked to confirm saving and
+   Scribe'ing the file.  This prompting can be inhibited by with \"Scribe Buffer
+   File Confirm\"."
+  "Scribe a file with the default directory set to the directory of the
+   specified file."
+  (declare (ignore p))
+  (let* ((buffer (current-buffer))
+	 (pathname (buffer-pathname buffer))
+	 (modified (buffer-modified buffer)))
+    (when (or (not (value scribe-buffer-file-confirm))
+	      (prompt-for-y-or-n
+	       :default t :default-string "Y"
+	       :prompt (list "~:[S~;Save and s~]cribe file ~A? "
+			     modified (namestring pathname))))
+      (when modified (write-buffer-file buffer pathname))
+      (scribe-file pathname))))
+
+(defhvar "Scribe Utility"
+  "Program name to invoke (via EXT:RUN-PROGRAM) to do text formatting."
+  :value "scribe")
+
+(defhvar "Scribe Utility Switches"
+  "Switches to pass to the \"Scribe Utility\" program.  This should be a list
+   of strings."
+  :value ())
+
+(defun scribe-file (pathname)
+  (let* ((pathname (truename pathname))
+	 (out-buffer (or (getstring "Scribe Warnings" *buffer-names*)
+			 (make-buffer "Scribe Warnings")))
+	 (out-point (buffer-end (buffer-point out-buffer)))
+	 (stream (make-hemlock-output-stream out-point :line))
+	 (orig-cwd (default-directory)))
+    (buffer-end out-point)
+    (insert-character out-point #\newline)
+    (insert-character out-point #\newline)
+    (unwind-protect
+	(progn
+	  (setf (default-directory) (directory-namestring pathname))
+	  (ext:run-program (namestring (value scribe-utility))
+			   (list* (namestring pathname)
+				  (value scribe-utility-switches))
+			   :output stream :error stream
+			   :wait nil))
+      (setf (default-directory) orig-cwd))))
+
+
+
+;;;; UNIX Filter Region
+
+(defcommand "Unix Filter Region" (p)
+  "Unix Filter Region prompts for a UNIX program and then passes the current
+  region to the program as standard input.  The standard output from the
+  program is used to replace the region.  This command is undo-able."
+  "UNIX-FILTER-REGION-COMMAND is not intended to be called from normal
+  Hemlock commands; use UNIX-FILTER-REGION instead."
+  (declare (ignore p))
+  (let* ((region (current-region))
+	 (filter-and-args (prompt-for-string
+			   :prompt "Filter: "
+			   :help "Unix program to filter the region through."))
+	 (filter-and-args-list (listify-unix-filter-string filter-and-args))
+	 (filter (car filter-and-args-list))
+	 (args (cdr filter-and-args-list))
+	 (new-region (unix-filter-region region filter args))
+	 (start (copy-mark (region-start region) :right-inserting))
+	 (end (copy-mark (region-end region) :left-inserting))
+	 (old-region (region start end))
+	 (undo-region (delete-and-save-region old-region)))
+    (ninsert-region end new-region)
+    (make-region-undo :twiddle "Unix Filter Region" old-region undo-region)))
+
+(defun unix-filter-region (region command args)
+  "Passes the region REGION as standard input to the program COMMAND
+  with arguments ARGS and returns the standard output as a freshly
+  cons'ed region."
+  (let ((new-region (make-empty-region)))
+    (with-input-from-region (input region)
+      (with-output-to-mark (output (region-end new-region) :full)
+	(ext:run-program command args
+			 :input input
+			 :output output
+			 :error output)))
+    new-region))
+
+(defun listify-unix-filter-string (str)
+  (declare (simple-string str))
+  (let ((result nil)
+	(lastpos 0))
+    (loop
+      (let ((pos (position #\Space str :start lastpos :test #'char=)))
+	(push (subseq str lastpos pos) result)
+	(unless pos
+	  (return))
+	(setf lastpos (1+ pos))))
+    (nreverse result)))
+
+
+
+
+;;;; Man pages.
+
+(defcommand "Manual Page" (p)
+  "Read the Unix manual pages in a View buffer.
+   If given an argument, this will put the man page in a Pop-up display."
+  "Read the Unix manual pages in a View buffer.
+   If given an argument, this will put the man page in a Pop-up display."
+  (let ((topic (prompt-for-string :prompt "Man topic: ")))
+    (if p
+	(with-pop-up-display (stream)
+	  (execute-man topic stream))
+	(let* ((buf-name (format nil "Man Page ~a" topic))
+	       (new-buffer (make-buffer buf-name :modes '("Fundamental" "View")))
+	       (buffer (or new-buffer (getstring buf-name *buffer-names*)))
+	       (point (buffer-point buffer)))
+	  (change-to-buffer buffer)
+	  (when new-buffer
+	    (setf (value view-return-function) #'(lambda ()))
+	    (with-writable-buffer (buffer)
+	      (with-output-to-mark (s point :full)
+		(execute-man topic s))))
+	  (buffer-start point buffer)))))
+
+(defun execute-man (topic stream)
+  (ext:run-program
+   "/bin/sh"
+   (list "-c"
+	 (format nil "man ~a| ul -t adm3" topic))
+   :output stream))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/window.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/window.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/window.lisp	(revision 13309)
@@ -0,0 +1,690 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    This file contains implementation independent code which implements
+;;; the Hemlock window primitives and most of the code which defines
+;;; other aspects of the interface to redisplay.
+;;;
+;;; Written by Bill Chiles and Rob MacLachlan.
+;;;
+
+(in-package :hemlock-internals)
+
+(defconstant unaltered-bits #b000
+  "This is the value of the dis-line-flags when a line is neither moved nor
+  changed nor new.")
+(defconstant changed-bit #b001
+  "This bit is set in the dis-line-flags when a line is found to be changed.")
+(defconstant moved-bit #b010
+  "This bit is set in the dis-line-flags when a line is found to be moved.")
+(defconstant new-bit #b100
+  "This bit is set in the dis-line-flags when a line is found to be new.")
+
+
+
+;;;; CURRENT-WINDOW.
+
+(defvar *current-window* nil "The current window object.")
+(defvar *window-list* () "A list of all window objects.")
+
+(declaim (inline current-window))
+
+(defun current-window ()
+  "Return the current window.  The current window is specially treated by
+  redisplay in several ways, the most important of which is that is does
+  recentering, ensuring that the Buffer-Point of the current window's
+  Window-Buffer is always displayed.  This may be set with Setf."
+  *current-window*)
+
+(defun %set-current-window (new-window)
+  (invoke-hook hemlock::set-window-hook new-window)
+  (move-mark (window-point *current-window*)
+	     (buffer-point (window-buffer *current-window*)))
+  (move-mark (buffer-point (window-buffer new-window))
+	     (window-point new-window))
+  (setq *current-window* new-window))
+
+
+
+
+;;;; Window structure support.
+
+(defun %print-hwindow (obj stream depth)
+  (declare (ignore depth))
+  (write-string "#<Hemlock Window \"" stream)
+  (write-string (buffer-name (window-buffer obj)) stream)
+  (write-string "\">" stream))
+
+
+(defun window-buffer (window)
+  "Return the buffer which is displayed in Window."
+  (window-%buffer window))
+
+(defun %set-window-buffer (window new-buffer)
+  (unless (bufferp new-buffer) (error "~S is not a buffer." new-buffer))
+  (unless (windowp window) (error "~S is not a window." window))
+  (unless (eq new-buffer (window-buffer window))
+    (invoke-hook hemlock::window-buffer-hook window new-buffer)
+    ;;
+    ;; Move the window's marks to the new start.
+    (let ((buffer (window-buffer window)))
+      (setf (buffer-windows buffer) (delete window (buffer-windows buffer)))
+      (move-mark (buffer-display-start buffer) (window-display-start window))
+      (push window (buffer-windows new-buffer))
+      (move-mark (window-point window) (buffer-point new-buffer))
+      (move-mark (window-display-start window) (buffer-display-start new-buffer))
+      (move-mark (window-display-end window) (buffer-display-start new-buffer)))
+    ;;
+    ;; Delete all the dis-lines, and nil out the line and chars so they get
+    ;; gc'ed.
+    (let ((first (window-first-line window))
+	  (last (window-last-line window))
+	  (free (window-spare-lines window)))
+      (unless (eq (cdr first) *the-sentinel*)
+	(shiftf (cdr last) free (cdr first) *the-sentinel*))
+      (dolist (dl free)
+	(setf (dis-line-line dl) nil  (dis-line-old-chars dl) nil))
+      (setf (window-spare-lines window) free))
+    ;;
+    ;; Set the last line and first&last changed so we know there's nothing there.
+    (setf (window-last-line window) *the-sentinel*
+	  (window-first-changed window) *the-sentinel*
+	  (window-last-changed window) *the-sentinel*)
+    ;;
+    ;; Make sure the window gets updated, and set the buffer.
+    (setf (window-tick window) -3)
+    (setf (window-%buffer window) new-buffer)))
+
+
+
+
+;;; %INIT-REDISPLAY sets up redisplay's internal data structures.  We create
+;;; initial windows, setup some hooks to cause modeline recomputation, and call
+;;; any device init necessary.  This is called from ED.
+;;;
+(defun %init-redisplay (display)
+  (%init-screen-manager display)
+  (add-hook hemlock::buffer-major-mode-hook 'queue-buffer-change)
+  (add-hook hemlock::buffer-minor-mode-hook 'queue-buffer-change)
+  (add-hook hemlock::buffer-name-hook 'queue-buffer-change)
+  (add-hook hemlock::buffer-pathname-hook 'queue-buffer-change)
+  (add-hook hemlock::buffer-modified-hook 'queue-buffer-change)
+  (add-hook hemlock::window-buffer-hook 'queue-window-change)
+  (let ((device (device-hunk-device (window-hunk (current-window)))))
+    (funcall (device-init device) device))
+  (center-window *current-window* (current-point)))
+
+
+
+
+;;;; Modelines-field structure support.
+
+(defun print-modeline-field (obj stream ignore)
+  (declare (ignore ignore))
+  (write-string "#<Hemlock Modeline-field " stream)
+  (prin1 (modeline-field-%name obj) stream)
+  (write-string ">" stream))
+
+(defun print-modeline-field-info (obj stream ignore)
+  (declare (ignore ignore))
+  (write-string "#<Hemlock Modeline-field-info " stream)
+  (prin1 (modeline-field-%name (ml-field-info-field obj)) stream)
+  (write-string ">" stream))
+
+
+(defvar *modeline-field-names* (make-hash-table))
+
+(defun make-modeline-field (&key name width function)
+  "Returns a modeline-field object."
+  (unless (or (eq width nil) (and (integerp width) (plusp width)))
+    (error "Width must be nil or a positive integer."))
+  (when (gethash name *modeline-field-names*)
+    (with-simple-restart (continue
+			  "Use the new definition for this modeline field.")
+      (error "Modeline field ~S already exists."
+	     (gethash name *modeline-field-names*))))
+  (setf (gethash name *modeline-field-names*)
+	(%make-modeline-field name function width)))
+
+(defun modeline-field (name)
+  "Returns the modeline-field object named name.  If none exists, return nil."
+  (gethash name *modeline-field-names*))
+
+
+(declaim (inline modeline-field-name modeline-field-width
+		 modeline-field-function))
+
+(defun modeline-field-name (ml-field)
+  "Returns the name of a modeline field object."
+  (modeline-field-%name ml-field))
+
+(defun %set-modeline-field-name (ml-field name)
+  (check-type ml-field modeline-field)
+  (when (gethash name *modeline-field-names*)
+    (error "Modeline field ~S already exists."
+	   (gethash name *modeline-field-names*)))
+  (remhash (modeline-field-%name ml-field) *modeline-field-names*)
+  (setf (modeline-field-%name ml-field) name)
+  (setf (gethash name *modeline-field-names*) ml-field))
+
+(defun modeline-field-width (ml-field)
+  "Returns the width of a modeline field."
+  (modeline-field-%width ml-field))
+
+(declaim (special *buffer-list*))
+
+(defun %set-modeline-field-width (ml-field width)
+  (check-type ml-field modeline-field)
+  (unless (or (eq width nil) (and (integerp width) (plusp width)))
+    (error "Width must be nil or a positive integer."))
+  (unless (eql width (modeline-field-%width ml-field))
+    (setf (modeline-field-%width ml-field) width)
+    (dolist (b *buffer-list*)
+      (when (buffer-modeline-field-p b ml-field)
+	(dolist (w (buffer-windows b))
+	  (update-modeline-fields b w)))))
+  width)
+  
+(defun modeline-field-function (ml-field)
+  "Returns the function of a modeline field object.  It returns a string."
+  (modeline-field-%function ml-field))
+
+(defun %set-modeline-field-function (ml-field function)
+  (check-type ml-field modeline-field)
+  (check-type function (or symbol function))
+  (setf (modeline-field-%function ml-field) function)
+  (dolist (b *buffer-list*)
+    (when (buffer-modeline-field-p b ml-field)
+      (dolist (w (buffer-windows b))
+	(update-modeline-field b w ml-field))))
+  function)
+
+
+
+
+;;;; Modelines maintenance.
+
+;;; Each window stores a modeline-buffer which is a string hunk-width-limit
+;;; long.  Whenever a field is updated, we must maintain a maximally long
+;;; representation of the modeline in case the window is resized.  Updating
+;;; then first gets the modeline-buffer setup, and second blasts the necessary
+;;; portion into the window's modeline-dis-line, setting the dis-line's changed
+;;; flag.
+;;;
+
+(defun update-modeline-fields (buffer window)
+  "Recompute all the fields of buffer's modeline for window, so the next
+   redisplay will reflect changes."
+  (let ((ml-buffer (window-modeline-buffer window)))
+    (declare (simple-string ml-buffer))
+    (when ml-buffer
+      (let* ((ml-buffer-len
+	      (do ((finfos (buffer-%modeline-fields buffer) (cdr finfos))
+		   (start 0 (blt-modeline-field-buffer
+			     ml-buffer (car finfos) buffer window start)))
+		  ((null finfos) start)))
+	     (dis-line (window-modeline-dis-line window))
+	     (len (min (window-width window) ml-buffer-len)))
+	(replace (the simple-string (dis-line-chars dis-line)) ml-buffer
+		 :end1 len :end2 len)
+	(setf (window-modeline-buffer-len window) ml-buffer-len)
+	(setf (dis-line-length dis-line) len)
+	(setf (dis-line-flags dis-line) changed-bit)))))
+
+;;; UPDATE-MODELINE-FIELD must replace the entire dis-line-chars with ml-buffer
+;;; after blt'ing into buffer.  Otherwise it has to do all the work
+;;; BLT-MODELINE-FIELD-BUFFER to figure out how to adjust dis-line-chars.  It
+;;; isn't worth it.  Since things could have shifted around, after calling
+;;; BLT-MODELINE-FIELD-BUFFER, we get the last field's end to know how long
+;;; the buffer is now.
+;;;
+(defun update-modeline-field (buffer window field)
+  "Recompute the field of the buffer's modeline for window, so the next
+   redisplay will reflect the change.  Field is either a modeline-field object
+   or the name of one for buffer."
+  (let ((finfo (internal-buffer-modeline-field-p buffer field)))
+    (unless finfo
+      (error "~S is not a modeline-field or the name of one for buffer ~S."
+	     field buffer))
+    (let ((ml-buffer (window-modeline-buffer window))
+	  (dis-line (window-modeline-dis-line window)))
+      (declare (simple-string ml-buffer))
+      (blt-modeline-field-buffer ml-buffer finfo buffer window
+				 (ml-field-info-start finfo) t)
+      (let* ((ml-buffer-len (ml-field-info-end
+			     (car (last (buffer-%modeline-fields buffer)))))
+	     (dis-len (min (window-width window) ml-buffer-len)))
+	(replace (the simple-string (dis-line-chars dis-line)) ml-buffer
+		 :end1 dis-len :end2 dis-len)
+	(setf (window-modeline-buffer-len window) ml-buffer-len)
+	(setf (dis-line-length dis-line) dis-len)
+	(setf (dis-line-flags dis-line) changed-bit)))))
+
+(defvar *truncated-field-char* #\!)
+
+;;; BLT-MODELINE-FIELD-BUFFER takes a Hemlock buffer, Hemlock window, the
+;;; window's modeline buffer, a modeline-field-info object, a start in the
+;;; modeline buffer, and an optional indicating whether a variable width field
+;;; should be handled carefully.  When the field is fixed-width, this is
+;;; simple.  When it is variable, we possibly have to shift all the text in the
+;;; buffer right or left before storing the new string, updating all the
+;;; finfo's after the one we're updating.  It is an error for the
+;;; modeline-field-function to return anything but a simple-string with
+;;; standard-chars.  This returns the end of the field blasted into ml-buffer.
+;;;
+(defun blt-modeline-field-buffer (ml-buffer finfo buffer window start
+					    &optional fix-other-fields-p)
+  (declare (simple-string ml-buffer))
+  (let* ((f (ml-field-info-field finfo))
+	 (width (modeline-field-width f))
+	 (string (funcall (modeline-field-function f) buffer window))
+	 (str-len (length string)))
+    (declare (simple-string string))
+    (setf (ml-field-info-start finfo) start)
+    (setf (ml-field-info-end finfo)
+	  (cond
+	   ((not width)
+	    (let ((end (min (+ start str-len) hunk-width-limit))
+		  (last-end (ml-field-info-end finfo)))
+	      (when (and fix-other-fields-p (/= end last-end))
+		(blt-ml-field-buffer-fix ml-buffer finfo buffer window
+					 end last-end))
+	      (replace ml-buffer string :start1 start :end1 end :end2 str-len)
+	      end))
+	   ((= str-len width)
+	    (let ((end (min (+ start width) hunk-width-limit)))
+	      (replace ml-buffer string :start1 start :end1 end :end2 width)
+	      end))
+	   ((> str-len width)
+	    (let* ((end (min (+ start width) hunk-width-limit))
+		   (end-1 (1- end)))
+	      (replace ml-buffer string :start1 start :end1 end-1 :end2 width)
+	      (setf (schar ml-buffer end-1) *truncated-field-char*)
+	      end))
+	   (t
+	    (let ((buf-replace-end (min (+ start str-len) hunk-width-limit))
+		  (buf-field-end (min (+ start width) hunk-width-limit)))
+	      (replace ml-buffer string
+		       :start1 start :end1 buf-replace-end :end2 str-len)
+	      (fill ml-buffer #\space :start buf-replace-end :end buf-field-end)
+	      buf-field-end))))))
+
+;;; BLT-ML-FIELD-BUFFER-FIX shifts the contents of ml-buffer in the direction
+;;; of last-end to end.  finfo is a modeline-field-info structure in buffer's
+;;; list of these.  If there are none following finfo, then we simply store the
+;;; new end of the buffer.  After blt'ing the text around, we have to update
+;;; all the finfos' starts and ends making sure nobody gets to stick out over
+;;; the ml-buffer's end.
+;;;
+(defun blt-ml-field-buffer-fix (ml-buffer finfo buffer window end last-end)
+  (declare (simple-string ml-buffer))
+  (let ((finfos (do ((f (buffer-%modeline-fields buffer) (cdr f)))
+		    ((null f) (error "This field must be here."))
+		  (if (eq (car f) finfo)
+		      (return (cdr f))))))
+    (cond
+     ((not finfos)
+      (setf (window-modeline-buffer-len window) (min end hunk-width-limit)))
+     (t
+      (let ((buffer-len (window-modeline-buffer-len window)))
+	(replace ml-buffer ml-buffer
+		 :start1 end
+		 :end1 (min (+ end (- buffer-len last-end)) hunk-width-limit)
+		 :start2 last-end :end2 buffer-len)
+	(let ((diff (- end last-end)))
+	  (macrolet ((frob (f)
+		       `(setf ,f (min (+ ,f diff) hunk-width-limit))))
+	    (dolist (f finfos)
+	      (frob (ml-field-info-start f))
+	      (frob (ml-field-info-end f)))
+	    (frob (window-modeline-buffer-len window)))))))))
+
+
+
+
+;;;; Default modeline and update hooks.
+
+(make-modeline-field :name :hemlock-literal :width 8
+		     :function #'(lambda (buffer window)
+				   "Returns \"Hemlock \"."
+				   (declare (ignore buffer window))
+				   "Hemlock "))
+
+(make-modeline-field
+ :name :package
+ :function #'(lambda (buffer window)
+	       "Returns the value of buffer's \"Current Package\" followed
+		by a colon and two spaces, or a string with one space."
+	       (declare (ignore window))
+	       (if (hemlock-bound-p 'hemlock::current-package :buffer buffer)
+		   (let ((val (variable-value 'hemlock::current-package
+					      :buffer buffer)))
+		     (if val
+			 (format nil "~A:  " val)
+			 " "))
+		   " ")))
+
+(make-modeline-field
+ :name :modes
+ :function #'(lambda (buffer window)
+	       "Returns buffer's modes followed by one space."
+	       (declare (ignore window))
+	       (format nil "~A  " (buffer-modes buffer))))
+
+(make-modeline-field
+ :name :modifiedp
+ :function #'(lambda (buffer window)
+	       "Returns \"* \" if buffer is modified, or the empty string."
+	       (declare (ignore window))
+	       (let ((modifiedp (buffer-modified buffer)))
+		 (if modifiedp
+		     "* "
+		     ""))))
+
+(make-modeline-field
+ :name :buffer-name
+ :function #'(lambda (buffer window)
+	       "Returns buffer's name followed by a colon and a space if the
+		name is not derived from the buffer's pathname, or the empty
+		string."
+	       (declare (ignore window))
+	       (let ((pn (buffer-pathname buffer))
+		     (name (buffer-name buffer)))
+		 (cond ((not pn)
+			(format nil "~A: " name))
+		       ((string/= (hemlock::pathname-to-buffer-name pn) name)
+			(format nil "~A: " name))
+		       (t "")))))
+
+
+;;; MAXIMUM-MODELINE-PATHNAME-LENGTH-HOOK is called whenever "Maximum Modeline
+;;; Pathname Length" is set.
+;;;
+(defun maximum-modeline-pathname-length-hook (name kind where new-value)
+  (declare (ignore name new-value))
+  (if (eq kind :buffer)
+      (hi::queue-buffer-change where)
+      (dolist (buffer *buffer-list*)
+	(when (and (buffer-modeline-field-p buffer :buffer-pathname)
+		   (buffer-windows buffer))
+	  (hi::queue-buffer-change buffer)))))
+
+(defun buffer-pathname-ml-field-fun (buffer window)
+  "Returns the namestring of buffer's pathname if there is one.  When
+   \"Maximum Modeline Pathname Length\" is set, and the namestring is too long,
+   return a truncated namestring chopping off leading directory specifications."
+  (declare (ignore window))
+  (let ((pn (buffer-pathname buffer)))
+    (if pn
+	(let* ((name (namestring pn))
+	       (length (length name))
+	       ;; Prefer a buffer local value over the global one.
+	       ;; Because variables don't work right, blow off looking for
+	       ;; a value in the buffer's modes.  In the future this will
+	       ;; be able to get the "current" value as if buffer were current.
+	       (max (if (hemlock-bound-p 'hemlock::maximum-modeline-pathname-length
+					  :buffer buffer)
+			 (variable-value 'hemlock::maximum-modeline-pathname-length
+					 :buffer buffer)
+			 (variable-value 'hemlock::maximum-modeline-pathname-length
+					 :global))))
+	  (declare (simple-string name))
+	  (if (or (not max) (<= length max))
+	      name
+	      (let* ((extra-chars (+ (- length max) 3))
+		     (slash (or (position #\/ name :start extra-chars)
+				;; If no slash, then file-namestring is very
+				;; long, and we should include all of it:
+				(position #\/ name :from-end t
+					  :end extra-chars))))
+		(if slash
+		    (concatenate 'simple-string "..." (subseq name slash))
+		    name))))
+	"")))
+
+(make-modeline-field
+ :name :buffer-pathname
+ :function 'buffer-pathname-ml-field-fun)
+
+
+(defvar *default-modeline-fields*
+  (list (modeline-field :hemlock-literal)
+	(modeline-field :package)
+	(modeline-field :modes)
+	(modeline-field :modifiedp)
+	(modeline-field :buffer-name)
+	(modeline-field :buffer-pathname))
+  "This is the default value for \"Default Modeline Fields\".")
+
+
+
+;;; QUEUE-BUFFER-CHANGE is used for various buffer hooks (e.g., mode changes,
+;;; name changes, etc.), so it takes some arguments to ignore.  These hooks are
+;;; invoked at a bad time to update the actual modeline-field, and user's may
+;;; have fields that change as a function of the changes this function handles.
+;;; This makes his update easier.  It doesn't cost much update the entire line
+;;; anyway.
+;;;
+(defun queue-buffer-change (buffer &optional something-else another-else)
+  (declare (ignore something-else another-else))
+  (push (list #'update-modelines-for-buffer buffer) *things-to-do-once*))
+
+(defun update-modelines-for-buffer (buffer)
+  (unless (eq buffer *echo-area-buffer*)
+    (dolist (w (buffer-windows buffer))
+      (update-modeline-fields buffer w))))
+
+
+;;; QUEUE-WINDOW-CHANGE is used for the "Window Buffer Hook".  We ignore the
+;;; argument since this hook function is invoked before any changes are made,
+;;; and the changes must be made before the fields can be set according to the
+;;; window's buffer's properties.  Therefore, we must queue the change to
+;;; happen sometime before redisplay but after the change takes effect.
+;;;
+(defun queue-window-change (window &optional something-else)
+  (declare (ignore something-else))
+  (push (list #'update-modeline-for-window window) *things-to-do-once*))
+
+(defun update-modeline-for-window (window)
+  (update-modeline-fields (window-buffer window) window))
+
+  
+
+
+;;;; Bitmap setting up new windows and modifying old.
+
+(defvar dummy-line (make-window-dis-line "")
+  "Dummy dis-line that we put at the head of window's dis-lines")
+(setf (dis-line-position dummy-line) -1)
+
+
+;;; WINDOW-FOR-HUNK makes a Hemlock window and sets up its dis-lines and marks
+;;; to display starting at start.
+;;;
+(defun window-for-hunk (hunk start modelinep)
+  (check-type start mark)
+  (setf (bitmap-hunk-changed-handler hunk) #'window-changed)
+  (let ((buffer (line-buffer (mark-line start)))
+	(first (cons dummy-line *the-sentinel*))
+	(width (bitmap-hunk-char-width hunk))
+	(height (bitmap-hunk-char-height hunk)))
+    (when (or (< height minimum-window-lines)
+	      (< width minimum-window-columns))
+      (error "Window too small."))
+    (unless buffer (error "Window start is not in a buffer."))
+    (let ((window
+	   (internal-make-window
+	    :hunk hunk
+	    :display-start (copy-mark start :right-inserting)
+	    :old-start (copy-mark start :temporary)
+	    :display-end (copy-mark start :right-inserting)
+	    :%buffer buffer
+	    :point (copy-mark (buffer-point buffer))
+	    :height height
+	    :width width
+	    :first-line first
+	    :last-line *the-sentinel*
+	    :first-changed *the-sentinel*
+	    :last-changed first
+	    :tick -1)))
+      (push window *window-list*)
+      (push window (buffer-windows buffer))
+      ;;
+      ;; Make the dis-lines.
+      (do ((i (- height) (1+ i))
+	   (res ()
+		(cons (make-window-dis-line (make-string width)) res)))
+	  ((= i height) (setf (window-spare-lines window) res)))
+      ;;
+      ;; Make the image up to date.
+      (update-window-image window)
+      (setf (bitmap-hunk-start hunk) (cdr (window-first-line window)))
+      ;;
+      ;; If there is a modeline, set it up.
+      (when modelinep
+	(setup-modeline-image buffer window)
+	(setf (bitmap-hunk-modeline-dis-line hunk)
+	      (window-modeline-dis-line window)))
+      window)))
+
+;;; SETUP-MODELINE-IMAGE sets up the modeline-dis-line for window using the
+;;; modeline-fields list.  This is used by tty redisplay too.
+;;;
+(defun setup-modeline-image (buffer window)
+  (setf (window-modeline-buffer window) (make-string hunk-width-limit))
+  (setf (window-modeline-dis-line window)
+	(make-window-dis-line (make-string (window-width window))))
+  (update-modeline-fields buffer window))
+
+;;; Window-Changed  --  Internal
+;;;
+;;;    The bitmap-hunk changed handler for windows.  This is only called if
+;;; the hunk is not locked.  We invalidate the window image and change its
+;;; size, then do a full redisplay.
+;;;
+(defun window-changed (hunk)
+  (let ((window (bitmap-hunk-window hunk)))
+    ;;
+    ;; Nuke all the lines in the window image.
+    (unless (eq (cdr (window-first-line window)) *the-sentinel*)
+      (shiftf (cdr (window-last-line window))
+	      (window-spare-lines window)
+	      (cdr (window-first-line window))
+	      *the-sentinel*))
+    (setf (bitmap-hunk-start hunk) (cdr (window-first-line window)))
+    ;;
+    ;; Add some new spare lines if needed.  If width is greater,
+    ;; reallocate the dis-line-chars.
+    (let* ((res (window-spare-lines window))
+	   (new-width (bitmap-hunk-char-width hunk))
+	   (new-height (bitmap-hunk-char-height hunk))
+	   (width (length (the simple-string (dis-line-chars (car res))))))
+      (declare (list res))
+      (when (> new-width width)
+	(setq width new-width)
+	(dolist (dl res)
+	  (setf (dis-line-chars dl) (make-string new-width))))
+      (setf (window-height window) new-height (window-width window) new-width)
+      (do ((i (- (* new-height 2) (length res)) (1- i)))
+	  ((minusp i))
+	(push (make-window-dis-line (make-string width)) res))
+      (setf (window-spare-lines window) res)
+      ;;
+      ;; Force modeline update.
+      (let ((ml-buffer (window-modeline-buffer window)))
+	(when ml-buffer
+	  (let ((dl (window-modeline-dis-line window))
+		(chars (make-string new-width))
+		(len (min new-width (window-modeline-buffer-len window))))
+	    (setf (dis-line-old-chars dl) nil)
+	    (setf (dis-line-chars dl) chars)
+	    (replace chars ml-buffer :end1 len :end2 len)
+	    (setf (dis-line-length dl) len)
+	    (setf (dis-line-flags dl) changed-bit)))))
+    ;;
+    ;; Prepare for redisplay.
+    (setf (window-tick window) (tick))
+    (update-window-image window)
+    (when (eq window *current-window*) (maybe-recenter-window window))
+    hunk))
+
+
+
+
+;;; EDITOR-FINISH-OUTPUT is used to synch output to a window with the rest of the
+;;; system.
+;;; 
+(defun editor-finish-output (window)
+  (let* ((device (device-hunk-device (window-hunk window)))
+	 (finish-output (device-finish-output device)))
+    (when finish-output
+      (funcall finish-output device window))))
+
+
+
+
+;;;; Tty setting up new windows and modifying old.
+
+;;; setup-window-image  --  Internal
+;;;
+;;;    Set up the dis-lines and marks for Window to display starting
+;;; at Start.  Height and Width are the number of lines and columns in 
+;;; the window.
+;;;
+(defun setup-window-image (start window height width)
+  (check-type start mark)
+  (let ((buffer (line-buffer (mark-line start)))
+	(first (cons dummy-line *the-sentinel*)))
+    (unless buffer (error "Window start is not in a buffer."))
+    (setf (window-display-start window) (copy-mark start :right-inserting)
+	  (window-old-start window) (copy-mark start :temporary)
+	  (window-display-end window) (copy-mark start :right-inserting)
+	  (window-%buffer window) buffer
+	  (window-point window) (copy-mark (buffer-point buffer))
+	  (window-height window) height
+	  (window-width window) width
+	  (window-first-line window) first
+	  (window-last-line window) *the-sentinel*
+	  (window-first-changed window) *the-sentinel*
+	  (window-last-changed window) first
+	  (window-tick window) -1)
+    (push window *window-list*)
+    (push window (buffer-windows buffer))
+    ;;
+    ;; Make the dis-lines.
+    (do ((i (- height) (1+ i))
+	 (res ()
+	      (cons (make-window-dis-line (make-string width)) res)))
+	((= i height) (setf (window-spare-lines window) res)))
+    ;;
+    ;; Make the image up to date.
+    (update-window-image window)))
+
+;;; change-window-image-height  --  Internal
+;;;
+;;;    Milkshake.
+;;;
+(defun change-window-image-height (window new-height)
+  ;; Nuke all the lines in the window image.
+  (unless (eq (cdr (window-first-line window)) *the-sentinel*)
+    (shiftf (cdr (window-last-line window))
+	    (window-spare-lines window)
+	    (cdr (window-first-line window))
+	    *the-sentinel*))
+  ;; Add some new spare lines if needed.
+  (let* ((res (window-spare-lines window))
+	 (width (length (the simple-string (dis-line-chars (car res))))))
+    (declare (list res))
+    (setf (window-height window) new-height)
+    (do ((i (- (* new-height 2) (length res)) (1- i)))
+	((minusp i))
+      (push (make-window-dis-line (make-string width)) res))
+    (setf (window-spare-lines window) res)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/winimage.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/winimage.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/winimage.lisp	(revision 13309)
@@ -0,0 +1,327 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Rob MacLachlan
+;;;
+;;; This file contains implementation independant functions that
+;;; build window images from the buffer structure.
+;;;
+(in-package :hemlock-internals)
+
+(defvar *the-sentinel*
+  (list (make-window-dis-line ""))
+  "This dis-line, which has several interesting properties, is used to end
+  lists of dis-lines.")
+(setf (dis-line-line (car *the-sentinel*))
+      (make-line :number most-positive-fixnum :chars ""))
+(setf (dis-line-position (car *the-sentinel*)) most-positive-fixnum)
+(setf (dis-line-old-chars (car *the-sentinel*)) :unique-thing)
+
+
+
+
+
+;;; move-lines  --  Internal
+;;;
+;;;    This function is called by Maybe-Change-Window when it believes that 
+;;; a line needs to be inserted or deleted.  When called it finishes the
+;;; image-update for the entire rest of the window.  Here and many other
+;;; places the phrase "dis-line" is often used to mean a pointer into the
+;;; window's list of dis-lines.
+;;;
+;;; Window - The window whose image needs to be updated.
+;;; Changed - True if the first-changed line has already been set, if false
+;;;  we must set it.
+;;; String - The overhang string to be added to the beginning of the first
+;;;  line image we build.  If no overhang then this is NIL.
+;;; Underhang - The number of trailing chars of String to use.
+;;; Line - The line at which we are to continue building the image.  This
+;;;  may be NIL, in which case we are at the end of the buffer.
+;;; Offset - The charpos within Line to continue at.
+;;; Current - The dis-line which caused Maybe-Change-Window to choke; it
+;;;  may be *the-sentinel*, it may not be the dummy line at head of the
+;;;  window's dis-lines.  This is the dis-line at which Maybe-Change-Window
+;;;  turns over control, it should not be one whose image it built.
+;;; Trail - This is the dis-line which immediately precedes Current in the
+;;;  dis-line list.  It may be the dummy dis-line, it may not be the sentinel.
+;;; Width - (window-width window)
+(defun move-lines (window changed string underhang line offset trail current
+			  width)
+  
+  (do* ((delta 0)
+	(cc (car current))
+	(old-line (dis-line-line cc))
+	;; Can't use current, since might be *the-sentinel*.
+	(pos (1+ (dis-line-position (car trail))))
+	;; Are we on an extension line?
+	(is-wrapped (eq line (dis-line-line (car trail))))
+	(last (window-last-line window))
+	(last-line (dis-line-line (car last)))
+	(save trail)
+	(height (window-height window))
+	(spare-lines (window-spare-lines window))
+	;; Make *the-sentinel* in this buffer so we don't delete it.
+	(buffer (setf (line-%buffer (dis-line-line (car *the-sentinel*)))
+		      (window-buffer window)))
+	(start offset) new-num)
+       ((or (= pos height) (null line))
+	;;    If we have run off the bottom or run out of lines then we are
+	;; done.  At this point Trail is the last line displayed and Current is
+	;; whatever comes after it, possibly *the-sentinel*.
+	;;    We always say that last-changed is the last line so that we
+	;; don't have to max in the old last-changed.
+	(setf (window-last-changed window) trail)
+	;; If there are extra lines at the end that need to be deleted
+	;; and haven't been already then link them into the free-list.
+	(unless (eq last trail)
+	  ;; This test works, because if the old last line was either
+	  ;; deleted or another line was inserted after it then it's
+	  ;; cdr would be something else.
+	  (when (eq (cdr last) *the-sentinel*)
+	    (shiftf (cdr last) spare-lines (cdr trail) *the-sentinel*))
+	  (setf (window-last-line window) trail))
+	(setf (window-spare-lines window) spare-lines)
+	;;    If first-changed has not been set then we set the first-changed
+	;; to the first line we looked at if it does not come after the
+	;; new position of the old first-changed.
+	(unless changed
+	  (when (> (dis-line-position (car (window-first-changed window)))
+		   (dis-line-position (car save)))
+	    (setf (window-first-changed window) (cdr save)))))
+
+    (setq new-num (line-number line))
+    ;; If a line has been deleted, it's line-%buffer is smashed; we unlink
+    ;; any dis-line which displayed such a line.
+    (cond
+     ((neq (line-%buffer old-line) buffer)
+      (do ((ptr (cdr current) (cdr ptr))
+	   (prev current ptr))
+	  ((eq (line-%buffer (dis-line-line (car ptr))) buffer)
+	   (setq delta (- pos (1+ (dis-line-position (car prev)))))
+	   (shiftf (cdr trail) (cdr prev) spare-lines current ptr)))
+      (setq cc (car current)  old-line (dis-line-line cc)))
+     ;; If the line-number of the old line is less than the line-number
+     ;; of the line we want to display then the old line must be off the top
+     ;; of the screen - delete it.  *The-Sentinel* fails this test because
+     ;; it's line-number is most-positive-fixnum.
+     ((< (line-number old-line) new-num)
+      (do ((ptr (cdr current) (cdr ptr))
+	   (prev current ptr))
+	  ((>= (line-number (dis-line-line (car ptr))) new-num)
+	   (setq delta (- pos (1+ (dis-line-position (car prev)))))
+	   (shiftf (cdr trail) (cdr prev) spare-lines current ptr)))
+      (setq cc (car current)  old-line (dis-line-line cc)))
+     ;; New line comes before old line, insert it, punting when
+     ;; we hit the bottom of the screen.
+     ((neq line old-line)
+      (do ((chars (unless is-wrapped (line-%chars line)) nil) new)
+	  (())
+	(setq new (car spare-lines))
+	(setf (dis-line-old-chars new) chars
+	      (dis-line-position new) pos
+	      (dis-line-line new) line
+	      (dis-line-delta new) 0
+	      (dis-line-flags new) new-bit)
+	(setq pos (1+ pos)  delta (1+ delta))
+	(multiple-value-setq (string underhang start)
+	  (compute-line-image string underhang line start new width))
+	(rotatef (cdr trail) spare-lines (cdr spare-lines))
+	(setq trail (cdr trail))
+	(cond ((= pos height)
+	       (return nil))
+	      ((null underhang)
+	       (setq start 0  line (line-next line))
+	       (return nil))))
+      (setq is-wrapped nil))
+     ;; The line is the same, possibly moved.  We add in the delta and
+     ;; or in the moved bit so that if redisplay punts in the middle
+     ;; the information is not lost.
+     ((eq (line-%chars line) (dis-line-old-chars cc))
+      ;; If the line is the old bottom line on the screen and it has moved and
+      ;; is full length, then mash the old-chars and quit so that the image
+      ;; will be recomputed the next time around the loop, since the line might
+      ;; have been wrapped off the bottom of the screen.
+      (cond
+       ((and (eq line last-line)
+	     (= (dis-line-length cc) width)
+	     (not (zerop delta)))
+	(setf (dis-line-old-chars cc) :another-unique-thing))
+       (t
+	(do ()
+	    ((= pos height))
+	  (unless (zerop delta)
+	    (setf (dis-line-position cc) pos)
+	    (incf (dis-line-delta cc) delta)
+	    (setf (dis-line-flags cc) (logior (dis-line-flags cc) moved-bit)))
+	  (shiftf trail current (cdr current))
+	  (setq cc (car current)  old-line (dis-line-line cc)  pos (1+ pos))
+	  (when (not (eq old-line line))
+	    (setq start 0  line (line-next line))
+	    (return nil))))))
+     ;; The line is changed, possibly moved.
+     (t
+      (do ((chars (line-%chars line) nil))
+	  (())
+	(multiple-value-setq (string underhang start)
+	  (compute-line-image string underhang line start cc width))
+	(setf (dis-line-flags cc) (logior (dis-line-flags cc) changed-bit)
+	      (dis-line-old-chars cc) chars
+	      (dis-line-position cc) pos)
+	(unless (zerop delta)
+	  (incf (dis-line-delta cc) delta)
+	  (setf (dis-line-flags cc) (logior (dis-line-flags cc) moved-bit)))
+	(shiftf trail current (cdr current))
+	(setq cc (car current)  old-line (dis-line-line cc)  pos (1+ pos))
+	(cond ((= pos height)
+	       (return nil))
+	      ((null underhang)
+	       (setq start 0  line (line-next line))
+	       (return nil))
+	      ((not (eq old-line line))
+	       (setq is-wrapped t)
+	       (return nil))))))))
+
+
+
+;;; maybe-change-window  --  Internal
+;;;
+;;;    This macro is "Called" in update-window-image whenever it finds that 
+;;; the chars of the line and the dis-line don't match.  This may happen for
+;;; several reasons:
+;;;
+;;; 1] The previous line was unchanged, but wrapped, so the dis-line-chars
+;;; are nil.  In this case we just skip over the extension lines.
+;;;
+;;; 2] A line is changed but not moved; update the line noting whether the
+;;; next line is moved because of this, and bugging out to Move-Lines if
+;;; it is.
+;;;
+;;; 3] A line is deleted, off the top of the screen, or moved.  Bug out
+;;; to Move-Lines.
+;;;
+;;;    There are two possible results, either we return NIL, and Line,
+;;; Trail and Current are updated, or we return T, in which case
+;;; Update-Window-Image should terminate immediately.  Changed is true
+;;; if a changed line changed lines has been found.
+;;;
+(eval-when (:compile-toplevel :execute)
+(defmacro maybe-change-window (window changed line offset trail current width)
+  `(let* ((cc (car ,current))
+	  (old-line (dis-line-line cc)))
+     (cond
+      ;; We have run into a continuation line, skip over any.
+      ((and (null (dis-line-old-chars cc))
+	    (eq old-line (dis-line-line (car ,trail))))
+       (do ((ptr (cdr ,current) (cdr ptr))
+	    (prev ,current ptr))
+	   ((not (eq (dis-line-line (car ptr)) old-line))
+	    (setq ,trail prev  ,current ptr) nil)))
+      ;; A line is changed.
+      ((eq old-line ,line)
+       (unless ,changed
+	 (when (< (dis-line-position cc)
+		  (dis-line-position (car (window-first-changed ,window))))
+	   (setf (window-first-changed ,window) ,current)
+	   (setq ,changed t)))
+       (do ((chars (line-%chars ,line) nil)
+	    (start ,offset) string underhang)
+	   (())
+	 (multiple-value-setq (string underhang start)
+	   (compute-line-image string underhang ,line start cc ,width))
+	 (setf (dis-line-flags cc) (logior (dis-line-flags cc) changed-bit))
+	 (setf (dis-line-old-chars cc) chars)
+	 (setq ,trail ,current  ,current (cdr ,current)  cc (car ,current))
+	 (cond
+	  ((eq (dis-line-line cc) ,line)
+	   (unless underhang
+	     (move-lines ,window t nil 0 (line-next ,line) 0 ,trail ,current
+			 ,width)
+	     (return t)))
+	  (underhang
+	   (move-lines ,window t string underhang ,line start ,trail
+		       ,current ,width)
+	   (return t))
+	  (t
+	   (setq ,line (line-next ,line))
+	   (when (> (dis-line-position (car ,trail))
+		    (dis-line-position (car (window-last-changed ,window))))
+	     (setf (window-last-changed ,window) ,trail))
+	   (return nil)))))
+      (t
+       (move-lines ,window ,changed nil 0 ,line ,offset ,trail ,current
+		   ,width)
+       t))))
+); eval-when
+
+
+;;; update-window-image  --  Internal
+;;;
+;;;    This is the function which redisplay calls when it wants to ensure that 
+;;; a window-image is up-to-date.  The main loop here is just to zoom through
+;;; the lines and dis-lines, bugging out to Maybe-Change-Window whenever
+;;; something interesting happens.
+;;;
+(defun update-window-image (window)
+  (let* ((trail (window-first-line window))
+	 (current (cdr trail))
+	 (display-start (window-display-start window))
+	 (line (mark-line display-start))
+	 (width (window-width window)) changed)
+    (cond
+     ;; If the first line or its charpos has changed then bug out.
+     ((cond ((and (eq (dis-line-old-chars (car current)) (line-%chars line))
+		  (mark= display-start (window-old-start window)))
+	     (setq trail current  current (cdr current)  line (line-next line))
+	     nil)
+	    (t
+	     ;; Force the line image to be invalid in case the start moved
+	     ;; and the line wrapped onto the screen.  If we started at the
+	     ;; beginning of the line then we don't need to.
+	     (unless (zerop (mark-charpos (window-old-start window)))
+	       (unless (eq current *the-sentinel*)
+		 (setf (dis-line-old-chars (car current)) :another-unique-thing)))
+	     (let ((start-charpos (mark-charpos display-start)))
+	       (move-mark (window-old-start window) display-start)
+	       (maybe-change-window window changed line start-charpos
+				    trail current width)))))
+     (t
+      (prog ()
+	(go TOP)
+       STEP
+	(setf (dis-line-line (car current)) line)
+	(setq trail current  current (cdr current)  line (line-next line))
+       TOP
+	(cond ((null line)
+	       (go DONE))
+	      ((eq (line-%chars line) (dis-line-old-chars (car current)))
+	       (go STEP)))
+	;;
+	;; We found a suspect line.
+	;; See if anything needs to be updated, if we bugged out, punt.
+	(when (and (eq current *the-sentinel*)
+		   (= (dis-line-position (car trail))
+		      (1- (window-height window))))
+	  (return nil))
+	(when (maybe-change-window window changed line 0 trail current width)
+	  (return nil))
+	(go TOP)
+
+       DONE
+	;;
+	;; We hit the end of the buffer. If lines need to be deleted bug out.
+	(unless (eq current *the-sentinel*)
+	  (maybe-change-window window changed line 0 trail current width))
+	(return nil))))
+    ;;
+    ;; Update the display-end mark.
+    (let ((dl (car (window-last-line window))))
+      (move-to-position (window-display-end window) (dis-line-end dl)
+			(dis-line-line dl)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/Notes
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/Notes	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/Notes	(revision 13309)
@@ -0,0 +1,21 @@
+Wire was using its own buffer management -- how useful. We did away
+with that an read/write directly from an binary stream for now.
+
+TODO
+
+- actually switch to binary streams
+- invent something for strings (say define it as unicode or something)
+
+- can we do a reasonable attempt to make symbol lookup work across
+  lisp implementations?
+
+- can we make this at least somewhat work with CLISP?
+
+- conditions.
+
+- Do away with superfluous large macros
+
+- Can we again do with a serve event kind of interface for poor Lisp
+  which do not feature multiprocessing (like say CLISP)?
+
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/package.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/package.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/package.lisp	(revision 13309)
@@ -0,0 +1,40 @@
+(defpackage :hemlock.wire
+  (:use :common-lisp)
+  (:nicknames :wire)
+  (:export
+   ;; wire.lisp
+   #:remote-object-p
+   #:remote-object
+   #:remote-object-local-p
+   #:remote-object-eq
+   #:remote-object-value
+   #:make-remote-object
+   #:forget-remote-translation
+   #:make-wire
+   #:wire-p
+   #:wire-fd
+   #:wire-listen
+   #:wire-get-byte
+   #:wire-get-number
+   #:wire-get-string
+   #:wire-get-object
+   #:wire-force-output
+   #:wire-output-byte
+   #:wire-output-number
+   #:wire-output-string
+   #:wire-output-object
+   #:wire-output-funcall
+   #:wire-error
+   #:wire-eof
+   #:wire-io-error
+   #:*current-wire*
+   #:wire-get-bignum
+   #:wire-output-bignum
+   ;; remote.lisp
+   #:remote
+   #:remote-value
+   #:remote-value-bind
+   #:create-request-server
+   #:destroy-request-server
+   #:connect-to-remote-server))
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/port.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/port.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/port.lisp	(revision 13309)
@@ -0,0 +1,182 @@
+(defpackage :hemlock.wire
+  (:use :common-lisp))
+
+(in-package :hemlock.wire)
+
+(defun ext-create-inet-listener (port)
+  #+CMU
+  (ext:create-inet-listener port)
+  #+EXCL
+  (socket:make-socket :connect :passive
+                      :local-port port
+                      :format :text)
+  #+CLISP
+  (socket:socket-server port)
+  #+SBCL
+  (let ((socket (make-instance 'sb-bsd-sockets:inet-socket
+                               :type :stream
+                               :protocol (sb-bsd-sockets:get-protocol-by-name "tcp"))))
+    (sb-bsd-sockets:socket-bind socket (sb-bsd-sockets:make-inet-address "0.0.0.0") port)
+    (sb-bsd-sockets:socket-listen socket 2)
+    socket)
+  #-(OR CMU EXCL CLISP SBCL)
+  #.(error "Configure"))
+
+(defun ext-accept-tcp-connection (socket)
+  #+CMU (ext:accept-tcp-connection socket)
+  #+EXCL
+  (values
+   (socket:accept-connection socket :wait t)
+   (socket:remote-host socket))
+  #+CLISP
+  (let ((stream (socket:socket-accept socket)))
+    #+NIL (setf (stream-element-type stream) '(unsigned-byte 8))
+    (values
+     stream
+     (multiple-value-list (socket:socket-stream-peer stream))))
+  #+SBCL
+  (multiple-value-bind (socket peer-host peer-port)
+      (sb-bsd-sockets:socket-accept socket)
+    (values (sb-bsd-sockets:socket-make-stream socket :element-type 'character :input t :output t)
+            peer-host))
+  #-(OR CMU EXCL CLISP SBCL)
+  #.(error "Configure")
+  )
+
+(defun ext-connect-to-inet-socket (host port)
+  #+CMU (ext:connect-to-inet-socket host port)
+  #+EXCL
+  (progn
+    #+(and allegro-version>= (version>= 5))
+    (socket:make-socket :remote-host host
+                        :remote-port port
+                        :format :text)
+    #-(and allegro-version>= (version>= 5))
+    (ipc:open-network-stream 
+     :host host :port port
+     :element-type 'character
+     ;; :class EXCL::BIDIRECTIONAL-BINARY-SOCKET-STREAM
+     ))
+  #+SBCL
+  (sb-bsd-sockets:socket-make-stream 
+   (let ((host (car (sb-bsd-sockets:host-ent-addresses
+		     (sb-bsd-sockets:get-host-by-name host)))))
+     (when host
+       (let ((s (make-instance 'sb-bsd-sockets:inet-socket
+                               :type :stream :protocol :tcp)))
+         (sb-bsd-sockets:socket-connect s host port)
+         s)))
+   :element-type 'character             ;(unsigned-byte 8)
+   :input t :output t)
+  #+CLISP
+  (socket:socket-connect port host)
+  #-(OR CMU EXCL CLISP SBCL)
+  #.(error "Configure"))
+
+(defun ext-close-socket (socket)
+  #+CMU   (ext:close-socket socket)
+  #+EXCL  (close socket)
+  #+CLISP (socket:socket-server-close socket)
+  #+SBCL  (sb-bsd-sockets:socket-close socket)
+  #-(OR CMU EXCL CLISP SBCL)
+  #.(error "Configure"))
+
+(defun ext-close-connection (connection)
+  #+CMU   (ext:close-socket connection)
+  #+EXCL  (close connection)
+  #+CLISP (close connection)
+  #+SBCL  (close connection)
+  #-(OR CMU EXCL CLISP SBCL)
+  #.(error "Configure"))
+
+(defun unix-gethostid ()
+  #.(or
+     #+CMU '(unix:unix-gethostid)
+     398792))
+
+(defun unix-getpid ()
+  #.(or 
+     #+CMU   '(unix:unix-getpid)
+     #+SBCL  '(sb-unix:unix-getpid)
+     #+ACL   '(excl::getpid)
+     #+CLISP '(system::program-id)))
+
+#+(OR CLISP)
+(eval-when (compile load eval)
+  (pushnew :hemlock.serve-event *features*) )
+
+#-:hemlock.serve-event
+(defun make-process (function &key name)
+  #+CMU  (mp:make-process function :name name)
+  #+EXCL (mp:process-run-function name function)
+  #+SBCL (sb-thread:make-thread function)
+  #-(OR CMU EXCL SBCL)
+  #.(error "Configure"))
+
+#+:hemlock.serve-event
+(progn
+
+  (defstruct handler
+    predicate
+    function)
+
+  (defvar *event-handlers* nil)
+
+  ;; Sigh. CLISP barfs on (typep (ext-create-inet-listener 8981) 'SOCKET:SOCKET-SERVER)
+  ;; Bad!
+  
+  (defun add-fd-handler (fd direction handler-function)
+    (let (handler)
+      (setf handler
+            (make-handler
+             :predicate
+             (cond ((eql 'socket:socket-server
+                         (type-of fd))
+                    (lambda () (socket:socket-wait fd 0)))
+                   ((typep fd 'xlib:display)
+                    (lambda ()
+                      (xlib:display-force-output fd)
+                      (xlib:event-listen fd)))
+                   (t
+                    (lambda ()
+                      (cond ((open-stream-p fd)
+                             (let ((c (read-char-no-hang fd nil :eof)))
+                               #+NIL (progn (print `(read-char-no-hang ,fd -> ,c)) (finish-output))
+                               (if (characterp c) (unread-char c fd))
+                               c))
+                            (t
+                             (setf *event-handlers* (delete handler *event-handlers*))
+                             nil)))))
+             :function
+             (lambda () (funcall handler-function fd))))
+      (push handler *event-handlers*)
+      handler))
+
+  (defun remove-fd-handler (handler)
+    (setf *event-handlers*
+          (delete handler *event-handlers*)))
+
+  (defun serve-all-events ()
+    (loop
+        (let ((handler (find-if #'funcall *event-handlers* :key #'handler-predicate)))
+          (cond (handler
+                 (funcall (handler-function handler))
+                 (return))
+                (t
+                 (sleep .01))))))
+
+  (defun serve-event (&optional timeout)
+    (let ((waited 0))
+      (loop
+          (let ((handler (find-if #'funcall *event-handlers* :key #'handler-predicate)))
+            (cond (handler
+                   (funcall (handler-function handler))
+                   (return t))
+                  ((>= waited timeout)
+                   (return nil))
+                  (t
+                   (incf waited .01)
+                   (sleep .01)))))))
+  )
+
+||#
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/remote.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/remote.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/remote.lisp	(revision 13309)
@@ -0,0 +1,403 @@
+;;; -*- Log: code.log; Package: wire -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+NIL
+(ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file implements a simple remote procedure call mechanism on top
+;;; of wire.lisp.
+;;;
+;;; Written by William Lott.
+;;;
+
+(defpackage :hemlock.wire
+  (:use :common-lisp))
+
+(in-package :hemlock.wire)
+
+(defstruct remote-wait
+  value1 value2 value3 value4 value5
+  abort
+  finished)
+
+(defvar *pending-returns* nil
+  "AList of wire . remote-wait structs")
+
+;;; MAYBE-NUKE-REMOTE-WAIT -- internal
+;;;
+;;; If the remote wait has finished, remove the external translation.
+;;; Otherwise, mark the remote wait as finished so the next call to
+;;; MAYBE-NUKE-REMOTE-WAIT will really nuke it.
+;;;
+(defun maybe-nuke-remote-wait (remote)
+  (cond ((remote-wait-finished remote)
+	 (forget-remote-translation remote)
+	 t)
+	(t
+	 (setf (remote-wait-finished remote)
+	       t)
+	 nil)))
+
+;;; REMOTE -- public
+;;;
+;;; Execute the body remotly. Subforms are executed locally in the lexical
+;;; envionment of the macro call. No values are returned.
+;;;
+(defmacro remote (wire-form &body forms)
+  "Evaluates the given forms remotly. No values are returned, as the remote
+evaluation is asyncronus."
+  (let ((wire (gensym)))
+    `(let ((,wire ,wire-form))
+       ,@(mapcar #'(lambda (form)
+		     `(wire-output-funcall ,wire
+					   ',(car form)
+					   ,@(cdr form)))
+	   forms)
+       (values))))
+
+;;; REMOTE-VALUE-BIND -- public
+;;;
+;;; Send to remote forms. First, a call to the correct dispatch routine based
+;;; on the number of args, then the actual call. The dispatch routine will get
+;;; the second funcall and fill in the correct number of arguments.
+;;; Note: if there are no arguments, we don't even wait for the function to
+;;; return, cause we can kind of guess at what the currect results would be.
+;;;
+(defmacro remote-value-bind (wire-form vars form &rest body)
+  "Bind vars to the multiple values of form (which is executed remotly). The
+forms in body are only executed if the remote function returned as apposed
+to aborting due to a throw."
+  (cond
+   ((null vars)
+    `(progn
+       (remote ,wire-form ,form)
+       ,@body))
+   (t
+    (let ((remote (gensym))
+	  (wire (gensym)))
+      `(let* ((,remote (make-remote-wait))
+	      (,wire ,wire-form)
+	      (*pending-returns* (cons (cons ,wire ,remote)
+				       *pending-returns*)))
+	 (unwind-protect
+	     (let ,vars
+	       (remote ,wire
+		 (,(case (length vars)
+		     (1 'do-1-value-call)
+		     (2 'do-2-value-call)
+		     (3 'do-3-value-call)
+		     (4 'do-4-value-call)
+		     (5 'do-5-value-call)
+		     (t 'do-n-value-call))
+		  (make-remote-object ,remote))
+		 ,form)
+	       (wire-force-output ,wire)
+	       (loop
+                 #+:hemlock.serve-event
+                 (serve-all-events)
+                 #-:hemlock.serve-event
+                 (wire-get-object ,wire)
+		 (when (remote-wait-finished ,remote)
+		   (return)))
+	       (unless (remote-wait-abort ,remote)
+		 ,(case (length vars)
+		    (1 `(setf ,(first vars) (remote-wait-value1 ,remote)))
+		    (2 `(setf ,(first vars) (remote-wait-value1 ,remote)
+			      ,(second vars) (remote-wait-value2 ,remote)))
+		    (3 `(setf ,(first vars) (remote-wait-value1 ,remote)
+			      ,(second vars) (remote-wait-value2 ,remote)
+			      ,(third vars) (remote-wait-value3 ,remote)))
+		    (4 `(setf ,(first vars) (remote-wait-value1 ,remote)
+			      ,(second vars) (remote-wait-value2 ,remote)
+			      ,(third vars) (remote-wait-value3 ,remote)
+			      ,(fourth vars) (remote-wait-value4 ,remote)))
+		    (5 `(setf ,(first vars) (remote-wait-value1 ,remote)
+			      ,(second vars) (remote-wait-value2 ,remote)
+			      ,(third vars) (remote-wait-value3 ,remote)
+			      ,(fourth vars) (remote-wait-value4 ,remote)
+			      ,(fifth vars) (remote-wait-value5 ,remote)))
+		    (t
+		     (do ((remaining-vars vars (cdr remaining-vars))
+			  (form (list 'setf)
+				(nconc form
+				       (list (car remaining-vars)
+					     `(pop values)))))
+			 ((null remaining-vars)
+			  `(let ((values (remote-wait-value1 ,remote)))
+			     ,form)))))
+		 ,@body))
+	   (maybe-nuke-remote-wait ,remote)))))))
+
+
+;;; REMOTE-VALUE -- public
+;;;
+;;; Alternate interface to getting the single return value of a remote
+;;; function. Works pretty much just the same, except the single value is
+;;; returned.
+;;;
+(defmacro remote-value (wire-form form &optional
+				  (on-server-unwind
+				   `(error "Remote server unwound")))
+  "Execute the single form remotly. The value of the form is returned.
+  The optional form on-server-unwind is only evaluated if the server unwinds
+  instead of returning."
+  (let ((remote (gensym))
+	(wire (gensym)))
+    `(let* ((,remote (make-remote-wait))
+	    (,wire ,wire-form)
+	    (*pending-returns* (cons (cons ,wire ,remote)
+				     *pending-returns*)))
+       (unwind-protect
+	   (progn
+	     (remote ,wire
+	       (do-1-value-call (make-remote-object ,remote))
+	       ,form)
+	     (wire-force-output ,wire)
+	     (loop
+               #+:hemlock.serve-event
+	       (serve-all-events)
+               #-:hemlock.serve-event
+               (wire-get-object ,wire)
+	       (when (remote-wait-finished ,remote)
+		 (return))))
+	 (maybe-nuke-remote-wait ,remote))
+       (if (remote-wait-abort ,remote)
+	 ,on-server-unwind
+	 (remote-wait-value1 ,remote)))))
+
+;;; DEFINE-FUNCTIONS -- internal
+;;;
+;;;   Defines two functions, one that the client runs in the server, and one
+;;; that the server runs in the client:
+;;;
+;;; DO-n-VALUE-CALL -- internal
+;;;
+;;;   Executed by the remote process. Reads the next object off the wire and
+;;; sends the value back. Unwind-protect is used to make sure we send something
+;;; back so the requestor doesn't hang.
+;;;
+;;; RETURN-n-VALUE -- internal
+;;;
+;;;   The remote procedure returned the given value, so fill it in the
+;;; remote-wait structure. Note, if the requestor has aborted, just throw
+;;; the value away.
+;;;
+(defmacro define-functions (values)
+  (let ((do-call (intern (format nil "~:@(do-~D-value-call~)" values)))
+	(return-values (intern (format nil "~:@(return-~D-value~:P~)" values)))
+	(vars nil))
+    (dotimes (i values)
+      (push (gensym) vars))
+    (setf vars (nreverse vars))
+    `(progn
+       (defun ,do-call (result)
+	 (let (worked ,@vars)
+	   (unwind-protect
+	       (progn
+		 (multiple-value-setq ,vars
+		   (wire-get-object *current-wire*))
+		 (setf worked t))
+	     (if worked
+	       (remote *current-wire*
+		 (,return-values result ,@vars))
+	       (remote *current-wire*
+		 (remote-return-abort result)))
+	     (wire-force-output *current-wire*))))
+       (defun ,return-values (remote ,@vars)
+	 (let ((result (remote-object-value remote)))
+	   (unless (maybe-nuke-remote-wait result)
+	     ,@(let ((setf-forms nil))
+		 (dotimes (i values)
+		   (push `(setf (,(intern (format nil
+						  "~:@(remote-wait-value~D~)"
+						  (1+ i)))
+				 result)
+				,(nth i vars))
+			 setf-forms))
+		 (nreverse setf-forms))))
+	 nil))))
+
+(define-functions 1)
+(define-functions 2)
+(define-functions 3)
+(define-functions 4)
+(define-functions 5)
+
+
+;;; DO-N-VALUE-CALL -- internal
+;;; 
+;;; For more values then 5, all the values are rolled into a list and passed
+;;; back as the first value, so we use RETURN-1-VALUE to return it.
+;;;
+(defun do-n-value-call (result)
+  (let (worked values)
+    (unwind-protect
+	(progn
+	  (setf values
+		(multiple-value-list (wire-get-object *current-wire*)))
+	  (setf worked t))
+      (if worked
+	(remote *current-wire*
+	  (return-1-values result values))
+	(remote *current-wire*
+	  (remote-return-abort result)))
+      (wire-force-output *current-wire*))))
+
+;;; REMOTE-RETURN-ABORT -- internal
+;;;
+;;; The remote call aborted instead of returned.
+;;;
+(defun remote-return-abort (result)
+  (setf result (remote-object-value result))
+  (unless (maybe-nuke-remote-wait result)
+    (setf (remote-wait-abort result) t)))
+
+#+:hemlock.serve-event
+;;; SERVE-REQUESTS -- internal
+;;;
+;;; Serve all pending requests on the given wire.
+;;;
+(defun serve-requests (wire on-death)
+  (handler-bind
+      ((wire-eof #'(lambda (condition)
+		     (declare (ignore condition))
+                     (close (wire-stream wire))
+		     #+NILGB(system:invalidate-descriptor (wire-fd wire))
+		     #+NILGB(unix:unix-close (wire-fd wire))
+		     (dolist (pending *pending-returns*)
+		       (when (eq (car pending)
+				 wire)
+			 (unless (maybe-nuke-remote-wait (cdr pending))
+			   (setf (remote-wait-abort (cdr pending))
+				 t))))
+		     (when on-death
+		       (funcall on-death))
+		     (return-from serve-requests (values))))
+       (wire-error #'(lambda (condition)
+		       (declare (ignore condition))
+                       #+NILGB
+		       (system:invalidate-descriptor (wire-fd wire)))))
+    (progn #+NILGB loop
+        #+NILGB
+        (unless (wire-listen wire)
+          (return))
+      (wire-get-object wire)))
+  (values))
+
+;;; NEW-CONNECTION -- internal
+;;;
+;;;   Maybe build a new wire and add it to the servers list of fds. If the user
+;;; Supplied a function, close the socket if it returns NIL. Otherwise, install
+;;; the wire.
+;;;
+(defun new-connection (socket addr on-connect)
+  (let ((wire (make-wire socket))
+	(on-death nil))
+    (if (or (null on-connect)
+	    (multiple-value-bind (okay death-fn)
+                (funcall on-connect wire addr)
+	      (setf on-death death-fn)
+	      okay))
+        #+:hemlock.serve-event
+        (add-fd-handler socket :input
+                        #'(lambda (socket)
+                            (declare (ignore socket))
+                            (serve-requests wire on-death)))
+        #-:hemlock.serve-event
+        (make-process (lambda ()
+                        (loop (wire-get-object wire)))
+                      :name (format nil "Wire process for ~S." wire))
+        (ext-close-connection socket))))
+
+;;; REQUEST-SERVER structure
+;;;
+;;; Just a simple handle on the socket and system:serve-event handler that make
+;;; up a request server.
+;;;
+(defstruct (request-server
+	    (:print-function %print-request-server))
+  socket
+  handler)
+
+(defun %print-request-server (rs stream depth)
+  (declare (ignore depth))
+  (print-unreadable-object (rs stream :type t)
+    (format stream "for ~D" (request-server-socket rs))))
+
+;;; CREATE-REQUEST-SERVER -- Public.
+;;;
+;;; Create a TCP/IP listener on the given port.  If anyone tries to connect to
+;;; it, call NEW-CONNECTION to do the connecting.
+;;;
+#+:hemlock.serve-event
+(defun create-request-server (port &optional on-connect)
+  "Create a request server on the given port.  Whenever anyone connects to it,
+   call the given function with the newly created wire and the address of the
+   connector.  If the function returns NIL, the connection is destroyed;
+   otherwise, it is accepted.  This returns a manifestation of the server that
+   DESTROY-REQUEST-SERVER accepts to kill the request server."
+  (let* ((socket (ext-create-inet-listener port))
+	 (handler (add-fd-handler socket :input
+                                  #'(lambda (socket)
+                                      (multiple-value-bind
+                                            (newconn addr)
+                                          (ext-accept-tcp-connection socket)
+                                        (new-connection newconn addr on-connect))))))
+    (make-request-server :socket socket
+			 :handler handler)))
+
+#-:hemlock.serve-event
+(defun create-request-server (port &optional on-connect)
+  "Create a request server on the given port.  Whenever anyone connects to it,
+   call the given function with the newly created wire and the address of the
+   connector.  If the function returns NIL, the connection is destroyed;
+   otherwise, it is accepted.  This returns a manifestation of the server that
+   DESTROY-REQUEST-SERVER accepts to kill the request server."
+  (let* ((socket (ext-create-inet-listener port))
+	 (handler (make-process
+                   (lambda ()
+                     (loop
+                         (multiple-value-bind
+                               (newconn addr)
+                             (ext-accept-tcp-connection socket)
+                           (new-connection newconn addr on-connect)))))))
+    (make-request-server :socket socket
+			 :handler handler)))
+
+;;; DESTROY-REQUEST-SERVER -- Public.
+;;;
+;;; Removes the request server from SERVER's list of file descriptors and
+;;; closes the socket behind it.
+;;;
+(defun destroy-request-server (server)
+  "Quit accepting connections to the given request server."
+  #+:hemlock.serve-event
+  (remove-fd-handler (request-server-handler server))
+  ;;
+  (ext-close-socket (request-server-socket server))
+  nil)
+
+;;; CONNECT-TO-REMOTE-SERVER -- Public.
+;;;
+;;; Just like the doc string says, connect to a remote server. A handler is
+;;; installed to handle return values, etc.
+;;; 
+#-NIL
+(defun connect-to-remote-server (hostname port &optional on-death)
+  "Connect to a remote request server addressed with the given host and port
+   pair.  This returns the created wire."
+  (let* ((socket (ext-connect-to-inet-socket hostname port))
+	 (wire (make-wire socket)))
+    #+:hemlock.serve-event
+    ;; hmm, what exactly should this accomplish?
+    (add-fd-handler socket :input
+      #'(lambda (socket)
+	  (declare (ignore socket))
+	  (serve-requests wire on-death)))
+    wire))
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/wire.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/wire.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/wire/wire.lisp	(revision 13309)
@@ -0,0 +1,563 @@
+;;; -*- Log: code.log; Package: wire -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+NIL
+(ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains an interface to internet domain sockets.
+;;;
+;;; Written by William Lott.
+;;;
+
+(defpackage :hemlock.wire
+  (:use :common-lisp)
+  (:nicknames :wire)
+  (:export
+   ;; wire.lisp
+   #:remote-object-p
+   #:remote-object
+   #:remote-object-local-p
+   #:remote-object-eq
+   #:remote-object-value
+   #:make-remote-object
+   #:forget-remote-translation
+   #:make-wire
+   #:wire-p
+   #:wire-fd
+   #:wire-listen
+   #:wire-get-byte
+   #:wire-get-number
+   #:wire-get-string
+   #:wire-get-object
+   #:wire-force-output
+   #:wire-output-byte
+   #:wire-output-number
+   #:wire-output-string
+   #:wire-output-object
+   #:wire-output-funcall
+   #:wire-error
+   #:wire-eof
+   #:wire-io-error
+   #:*current-wire*
+   #:wire-get-bignum
+   #:wire-output-bignum
+   ;; remote.lisp
+   #:remote
+   #:remote-value
+   #:remote-value-bind
+   #:create-request-server
+   #:destroy-request-server
+   #:connect-to-remote-server))
+
+(in-package :hemlock.wire)
+
+;;; Stuff that needs to be ported:
+
+(eval-when (compile load eval) ;For macros in remote.lisp.
+
+(defconstant buffer-size 2048)
+
+(defconstant initial-cache-size 16)
+
+(defconstant funcall0-op 0)
+(defconstant funcall1-op 1)
+(defconstant funcall2-op 2)
+(defconstant funcall3-op 3)
+(defconstant funcall4-op 4)
+(defconstant funcall5-op 5)
+(defconstant funcall-op 6)
+(defconstant number-op 7)
+(defconstant string-op 8)
+(defconstant symbol-op 9)
+(defconstant save-op 10)
+(defconstant lookup-op 11)
+(defconstant remote-op 12)
+(defconstant cons-op 13)
+(defconstant bignum-op 14)
+
+) ;eval-when
+
+
+(defvar *current-wire* nil
+  "The wire the form we are currently evaluating came across.")
+
+(defvar *this-host* nil
+  "Unique identifier for this host.")
+(defvar *this-pid* nil
+  "Unique identifier for this process.")
+
+(defvar *object-to-id* (make-hash-table :test 'eq)
+  "Hash table mapping local objects to the corresponding remote id.")
+(defvar *id-to-object* (make-hash-table :test 'eql)
+  "Hash table mapping remote id's to the curresponding local object.")
+(defvar *next-id* 0
+  "Next available id for remote objects.")
+
+
+(defstruct (wire
+            (:constructor make-wire (stream))
+            (:print-function
+             (lambda (wire stream depth)
+               (declare (ignore depth))
+               (format stream
+                       "#<wire ~s>"
+		       (wire-stream wire)))))
+  stream
+  (object-cache (make-array initial-cache-size))
+  (cache-index 0)
+  (object-hash (make-hash-table :test 'eq)))
+
+(defstruct (remote-object
+	    (:constructor %make-remote-object (host pid id))
+	    (:print-function
+	     (lambda (obj stream depth)
+	       (declare (ignore depth))
+	       (format stream "#<Remote Object: [~x:~a] ~s>"
+		       (remote-object-host obj)
+		       (remote-object-pid obj)
+		       (remote-object-id obj)))))
+  host
+  pid
+  id)
+
+(define-condition wire-error (error)
+  ((wire :reader wire-error-wire :initarg :wire))
+  (:report (lambda (condition stream)
+	     (format stream "There is a problem with ~A."
+		     (wire-error-wire condition)))))
+
+(define-condition wire-eof (wire-error)
+  ()
+  (:report (lambda (condition stream)
+	     (format stream "Recieved EOF on ~A."
+		     (wire-error-wire condition)))))
+
+(define-condition wire-io-error (wire-error)
+  ((when :reader wire-io-error-when :initarg :when :initform "using")
+   (msg :reader wire-io-error-msg :initarg :msg :initform "Failed."))
+  (:report (lambda (condition stream)
+	     (format stream "Error ~A ~A: ~A."
+		     (wire-io-error-when condition)
+		     (wire-error-wire condition)
+		     (wire-io-error-msg condition)))))
+
+
+
+;;; Remote Object Randomness
+
+;;; REMOTE-OBJECT-LOCAL-P -- public
+;;;
+;;;   First, make sure the *this-host* and *this-pid* are set. Then test to
+;;; see if the remote object's host and pid fields are *this-host* and
+;;; *this-pid*
+
+(defun remote-object-local-p (remote)
+  "Returns T iff the given remote object is defined locally."
+  (declare (type remote-object remote))
+  (unless *this-host*
+    (setf *this-host* (unix-gethostid))
+    (setf *this-pid* (unix-getpid)))
+  (and (eql (remote-object-host remote) *this-host*)
+       (eql (remote-object-pid remote) *this-pid*)))
+
+;;; REMOTE-OBJECT-EQ -- public
+;;;
+;;;   Remote objects are considered EQ if they refer to the same object, ie
+;;; Their host, pid, and id fields are the same (eql, cause they are all
+;;; numbers).
+
+(defun remote-object-eq (remote1 remote2)
+  "Returns T iff the two objects refer to the same (eq) object in the same
+  process."
+  (declare (type remote-object remote1 remote2))
+  (and (eql (remote-object-host remote1)
+	    (remote-object-host remote2))
+       (eql (remote-object-pid remote1)
+	    (remote-object-pid remote2))
+       (eql (remote-object-id remote1)
+	    (remote-object-id remote2))))
+
+;;; REMOTE-OBJECT-VALUE --- public
+;;;
+;;;   First assure that the remote object is defined locally. If so, look up
+;;; the id in *id-to-objects*. 
+;;; table. This will only happen if FORGET-REMOTE-TRANSLATION has been called
+;;; on the local object.
+
+(defun remote-object-value (remote)
+  "Return the associated value for the given remote object. It is an error if
+  the remote object was not created in this process or if
+  FORGET-REMOTE-TRANSLATION has been called on this remote object."
+  (declare (type remote-object remote))
+  (unless (remote-object-local-p remote)
+    (error "~S is defined is a different process." remote))
+  (multiple-value-bind
+      (value found)
+      (gethash (remote-object-id remote)
+	       *id-to-object*)
+    (unless found
+      (cerror
+       "Use the value of NIL"
+       "No value for ~S -- FORGET-REMOTE-TRANSLATION was called to early."
+       remote))
+    value))
+
+;;; MAKE-REMOTE-OBJECT --- public
+;;;
+;;;   Convert the given local object to a remote object. If the local object is
+;;; alread entered in the *object-to-id* hash table, just use the old id.
+;;; Otherwise, grab the next id and put add both mappings to the two hash
+;;; tables.
+
+(defun make-remote-object (local)
+  "Convert the given local object to a remote object."
+  (unless *this-host*
+    (setf *this-host* (unix-gethostid))
+    (setf *this-pid* (unix-getpid)))
+  (let ((id (gethash local *object-to-id*)))
+    (unless id
+      (setf id *next-id*)
+      (setf (gethash local *object-to-id*) id)
+      (setf (gethash id *id-to-object*) local)
+      (incf *next-id*))
+    (%make-remote-object *this-host* *this-pid* id)))
+
+;;; FORGET-REMOTE-TRANSLATION -- public
+;;;
+;;;   Remove any translation information about the given object. If there is
+;;; currenlt no translation for the object, don't bother doing anything.
+;;; Otherwise remove it from the *object-to-id* hashtable, and remove the id
+;;; from the *id-to-object* hashtable.
+
+(defun forget-remote-translation (local)
+  "Forget the translation from the given local to the corresponding remote
+object. Passing that remote object to remote-object-value will new return NIL."
+  (let ((id (gethash local *object-to-id*)))
+    (when id
+      (remhash local *object-to-id*)
+      (remhash id *id-to-object*)))
+  (values))
+
+
+
+;;; Wire input routeins.
+
+;;; WIRE-LISTEN -- public
+;;;
+;;;   If nothing is in the current input buffer, select on the file descriptor.
+
+(defun wire-listen (wire)
+  "Return T iff anything is in the input buffer or available on the socket."
+  (or 
+      (listen (wire-stream wire))))
+
+;;; WIRE-GET-BYTE -- public
+;;;
+;;;   Return the next byte.
+
+(defun wire-get-byte (wire)
+  "Return the next byte from the wire."
+  (let ((c (read-char (wire-stream wire) nil :eof)))
+    (cond ((eql c :eof)
+           (error 'wire-eof :wire wire))
+          (t
+           (char-int c)))))
+
+;;; WIRE-GET-NUMBER -- public
+;;;
+;;;   Just read four bytes and pack them together with normal math ops.
+
+(defun wire-get-number (wire &optional (signed t))
+  "Read a number off the wire. Numbers are 4 bytes in network order.
+The optional argument controls weather or not the number should be considered
+signed (defaults to T)."
+  (let* ((b1 (wire-get-byte wire))
+	 (b2 (wire-get-byte wire))
+	 (b3 (wire-get-byte wire))
+	 (b4 (wire-get-byte wire))
+	 (unsigned
+	  (+ b4 (* 256 (+ b3 (* 256 (+ b2 (* 256 b1))))))))
+    (if (and signed (> b1 127))
+	(logior (ash -1 32) unsigned)
+	unsigned)))
+
+;;; WIRE-GET-BIGNUM -- public
+;;;
+;;; Extracts a number, which might be a bignum.
+;;;
+(defun wire-get-bignum (wire)
+  "Reads an arbitrary integer sent by WIRE-OUTPUT-BIGNUM from the wire and
+   return it."
+  (let ((count-and-sign (wire-get-number wire)))
+    (do ((count (abs count-and-sign) (1- count))
+	 (result 0 (+ (ash result 32) (wire-get-number wire nil))))
+	((not (plusp count))
+	 (if (minusp count-and-sign)
+	     (- result)
+	     result)))))
+
+;;; WIRE-GET-STRING -- public
+;;;
+;;;   Use WIRE-GET-NUMBER to read the length, and then read the string
+;;; contents.
+
+(defun wire-get-string (wire)
+  "Reads a string from the wire. The first four bytes spec the size."
+  (let* ((length (wire-get-number wire))
+	 (result (make-string length)))
+    (declare (simple-string result)
+	     (integer length))
+    (read-sequence result (wire-stream wire))
+    result))
+    
+;;; WIRE-GET-OBJECT -- public
+;;;
+;;;   First, read a byte to determine the type of the object to read. Then,
+;;; depending on the type, call WIRE-GET-NUMBER, WIRE-GET-STRING, or whatever
+;;; to read the necessary data. Note, funcall objects are funcalled.
+
+(defun wire-get-object (wire)
+  "Reads the next object from the wire and returns it."
+  (let ((identifier (wire-get-byte wire))
+	(*current-wire* wire))
+    (declare (fixnum identifier))
+    (cond ((eql identifier lookup-op)
+	   (let ((index (wire-get-number wire))
+		 (cache (wire-object-cache wire)))
+	     (declare (integer index))
+	     (declare (simple-vector cache))
+	     (when (< index (length cache))
+	       (svref cache index))))
+	  ((eql identifier number-op)
+	   (wire-get-number wire))
+	  ((eql identifier bignum-op)
+	   (wire-get-bignum wire))
+	  ((eql identifier string-op)
+	   (wire-get-string wire))
+	  ((eql identifier symbol-op)
+	   (let* ((symbol-name (wire-get-string wire))
+		  (package-name (wire-get-string wire))
+		  (package (find-package package-name)))
+	     (unless package
+	       (error "Attempt to read symbol, ~A, of wire into non-existent ~
+		       package, ~A."
+		      symbol-name package-name))
+	     (intern symbol-name package)))
+	  ((eql identifier cons-op)
+	   (cons (wire-get-object wire)
+		 (wire-get-object wire)))
+	  ((eql identifier remote-op)
+	   (let ((host (wire-get-number wire nil))
+		 (pid (wire-get-number wire))
+		 (id (wire-get-number wire)))
+	     (%make-remote-object host pid id)))
+	  ((eql identifier save-op)
+	   (let ((index (wire-get-number wire))
+		 (cache (wire-object-cache wire)))
+	     (declare (integer index))
+	     (declare (simple-vector cache))
+	     (when (>= index (length cache))
+	       (do ((newsize (* (length cache) 2)
+			     (* newsize 2)))
+		   ((< index newsize)
+		    (let ((newcache (make-array newsize)))
+		      (declare (simple-vector newcache))
+		      (replace newcache cache)
+		      (setf cache newcache)
+		      (setf (wire-object-cache wire) cache)))))
+	     (setf (svref cache index)
+		   (wire-get-object wire))))
+	  ((eql identifier funcall0-op)
+	   (funcall (wire-get-object wire)))
+	  ((eql identifier funcall1-op)
+	   (funcall (wire-get-object wire)
+		    (wire-get-object wire)))
+	  ((eql identifier funcall2-op)
+	   (funcall (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)))
+	  ((eql identifier funcall3-op)
+	   (funcall (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)))
+	  ((eql identifier funcall4-op)
+	   (funcall (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)))
+	  ((eql identifier funcall5-op)
+	   (funcall (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)
+		    (wire-get-object wire)))
+	  ((eql identifier funcall-op)
+	   (let ((arg-count (wire-get-byte wire))
+		 (function (wire-get-object wire))
+		 (args '())
+		 (last-cons nil)
+		 (this-cons nil))
+	     (loop
+	       (when (zerop arg-count)
+		 (return nil))
+	       (setf this-cons (cons (wire-get-object wire)
+				     nil))
+	       (if (null last-cons)
+		 (setf args this-cons)
+		 (setf (cdr last-cons) this-cons))
+	       (setf last-cons this-cons)
+	       (decf arg-count))
+	     (apply function args))))))
+
+
+
+;;; Wire output routines.
+
+;;; WIRE-FORCE-OUTPUT -- internal
+;;;
+;;;   Output any stuff remaining in the output buffer.
+
+(defun wire-force-output (wire)
+  "Send any info still in the output buffer down the wire and clear it. Nothing
+harmfull will happen if called when the output buffer is empty."
+  (force-output (wire-stream wire))
+  (values))
+
+;;; WIRE-OUTPUT-BYTE -- public
+;;;
+;;;   Stick the byte in the output buffer. If there is no space, flush the
+;;; buffer using WIRE-FORCE-OUTPUT.
+
+(defun wire-output-byte (wire byte)
+  "Output the given (8-bit) byte on the wire."
+  (declare (integer byte))
+  (write-char (code-char byte) (wire-stream wire))
+  (values))
+
+;;; WIRE-OUTPUT-NUMBER -- public
+;;;
+;;;   Output the number. Note, we don't care if the number is signed or not,
+;;; because we just crank out the low 32 bits.
+;;;
+(defun wire-output-number (wire number)
+  "Output the given (32-bit) number on the wire."
+  (declare (integer number))
+  (wire-output-byte wire (+ 0 (ldb (byte 8 24) number)))
+  (wire-output-byte wire (ldb (byte 8 16) number))
+  (wire-output-byte wire (ldb (byte 8 8) number))
+  (wire-output-byte wire (ldb (byte 8 0) number))
+  (values))
+
+;;; WIRE-OUTPUT-BIGNUM -- public
+;;;
+;;; Output an arbitrary integer.
+;;; 
+(defun wire-output-bignum (wire number)
+  "Outputs an arbitrary integer, but less effeciently than WIRE-OUTPUT-NUMBER."
+  (do ((digits 0 (1+ digits))
+       (remaining (abs number) (ash remaining -32))
+       (words nil (cons (ldb (byte 32 0) remaining) words)))
+      ((zerop remaining)
+       (wire-output-number wire
+			   (if (minusp number)
+			       (- digits)
+			       digits))
+       (dolist (word words)
+	 (wire-output-number wire word)))))
+
+;;; WIRE-OUTPUT-STRING -- public
+;;;
+;;;   Output the string. Strings are represented by the length as a number,
+;;; followed by the bytes of the string.
+;;;
+(defun wire-output-string (wire string)
+  "Output the given string. First output the length using WIRE-OUTPUT-NUMBER,
+then output the bytes."
+  (declare (simple-string string))
+  (let ((length (length string)))
+    (declare (integer length))
+    (wire-output-number wire length)
+    (write-sequence string (wire-stream wire)))
+  (values))
+
+;;; WIRE-OUTPUT-OBJECT -- public
+;;;
+;;;   Output the given object. If the optional argument is non-nil, cache
+;;; the object to enhance the performance of sending it multiple times.
+;;; Caching defaults to yes for symbols, and nil for everything else.
+
+(defun wire-output-object (wire object &optional (cache-it (symbolp object)))
+  "Output the given object on the given wire. If cache-it is T, enter this
+object in the cache for future reference."
+  (let ((cache-index (gethash object
+			      (wire-object-hash wire))))
+    (cond
+     (cache-index
+      (wire-output-byte wire lookup-op)
+      (wire-output-number wire cache-index))
+     (t
+      (when cache-it
+	(wire-output-byte wire save-op)
+	(let ((index (wire-cache-index wire)))
+	  (wire-output-number wire index)
+	  (setf (gethash object (wire-object-hash wire))
+		index)
+	  (setf (wire-cache-index wire) (1+ index))))
+      (typecase object
+	(integer
+	 (cond ((typep object '(signed-byte 32))
+		(wire-output-byte wire number-op)
+		(wire-output-number wire object))
+	       (t
+		(wire-output-byte wire bignum-op)
+		(wire-output-bignum wire object))))
+	(simple-string
+	 (wire-output-byte wire string-op)
+	 (wire-output-string wire object))
+	(symbol
+	 (wire-output-byte wire symbol-op)
+	 (wire-output-string wire (symbol-name object))
+	 (wire-output-string wire (package-name (symbol-package object))))
+	(cons
+	 (wire-output-byte wire cons-op)
+	 (wire-output-object wire (car object))
+	 (wire-output-object wire (cdr object)))
+	(remote-object
+	 (wire-output-byte wire remote-op)
+	 (wire-output-number wire (remote-object-host object))
+	 (wire-output-number wire (remote-object-pid object))
+	 (wire-output-number wire (remote-object-id object)))
+	(t
+	 (error "Error: Cannot output objects of type ~s across a wire."
+		(type-of object)))))))
+  (values))
+
+;;; WIRE-OUTPUT-FUNCALL -- public
+;;;
+;;;   Send the funcall down the wire. Arguments are evaluated locally in the
+;;; lexical environment of the WIRE-OUTPUT-FUNCALL.
+
+(defmacro wire-output-funcall (wire-form function &rest args)
+  "Send the function and args down the wire as a funcall."
+  (let ((num-args (length args))
+	(wire (gensym)))
+    `(let ((,wire ,wire-form))
+       ,@(if (> num-args 5)
+	    `((wire-output-byte ,wire funcall-op)
+	      (wire-output-byte ,wire ,num-args))
+	    `((wire-output-byte ,wire ,(+ funcall0-op num-args))))
+       (wire-output-object ,wire ,function)
+       ,@(mapcar #'(lambda (arg)
+		     `(wire-output-object ,wire ,arg))
+		 args)
+       (values))))
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/archive/xcoms.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/archive/xcoms.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/archive/xcoms.lisp	(revision 13309)
@@ -0,0 +1,40 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains commands and support specifically for X related features.
+;;;
+;;; Written by Bill Chiles.
+;;;
+
+(in-package :hemlock)
+
+
+(defcommand "Region to Cut Buffer" (p)
+  "Place the current region into the X cut buffer."
+  "Place the current region into the X cut buffer."
+  (declare (ignore p))
+  (store-cut-string (hi::bitmap-device-display
+		     (hi::device-hunk-device (hi::window-hunk (current-window))))
+		    (region-to-string (current-region))))
+
+(defcommand "Insert Cut Buffer" (p)
+  "Insert the X cut buffer at current point."
+  "Insert the X cut buffer at current point.  Returns nil when it is empty."
+  (declare (ignore p))
+  (let ((str (fetch-cut-string (hi::bitmap-device-display
+				(hi::device-hunk-device
+				 (hi::window-hunk (current-window)))))))
+    (if str
+	(let ((point (current-point)))
+	  (push-buffer-mark (copy-mark point))
+	  (insert-string (current-point) str))
+	(editor-error "X cut buffer empty.")))
+  (setf (last-command-type) :ephemerally-active))
Index: /branches/new-random/cocoa-ide/hemlock/unused/bit-stream.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/bit-stream.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/bit-stream.lisp	(revision 13309)
@@ -0,0 +1,147 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Some stuff to make streams that write out on bitmap hunks.
+;;;
+;;; Written by Rob MacLachlan.
+;;; Modified by Bill Chiles to run under X on the IBM RT.
+;;;
+(in-package "HEMLOCK-INTERNALS")
+
+
+;;; These streams have an associated bitmap-hunk that is used for its
+;;; font-family, foreground and background color, and X window pointer.
+;;; The hunk need not be associated with any Hemlock window, and the low
+;;; level painting routines that use hunk dimensions are not used for
+;;; output.  Only BITMAP-HUNK-WRITE-STRING is used.  The hunk is not
+;;; registered for any event service, so resizing the associated X window
+;;; does not invoke the exposed/changed handler in Bit-Screen.Lisp; also, the
+;;; hunk's input and changed handler slots are not set.
+;;;
+(defstruct (bitmap-hunk-output-stream (:include sys:lisp-stream
+						(out #'bitmap-hunk-out)
+						(sout #'bitmap-hunk-sout)
+						(misc #'bitmap-hunk-misc))
+				      (:constructor
+				       make-bitmap-hunk-output-stream (hunk)))
+  hunk			; bitmap-hunk we display on.
+  (cursor-x 0)		; Character position of output cursor.
+  (cursor-y 0)
+  (buffer (make-string hunk-width-limit) :type simple-string)
+  (old-bottom 0))	; # of lines of scrolling before next "--More--" prompt.
+
+;;; Bitmap-Hunk-Stream-Newline  --  Internal
+;;;
+;;;    Flush the stream's output buffer and then move the cursor down
+;;; or scroll the window up if there is no room left.
+;;;
+(defun bitmap-hunk-stream-newline (stream)
+  (let* ((hunk (bitmap-hunk-output-stream-hunk stream))
+	 (height (bitmap-hunk-char-height hunk))
+	 (y (bitmap-hunk-output-stream-cursor-y stream)))
+    (when (zerop (bitmap-hunk-output-stream-old-bottom stream))
+      (hunk-write-string hunk 0 y "--More--" 0 8)
+      (let ((device (device-hunk-device hunk)))
+	(when (device-force-output device)
+	  (funcall (device-force-output device))))
+      (wait-for-more)
+      (hunk-clear-lines hunk y 1)
+      (setf (bitmap-hunk-output-stream-old-bottom stream) (1- height)))
+    (hunk-write-string hunk 0 y (bitmap-hunk-output-stream-buffer stream) 0 
+		       (bitmap-hunk-output-stream-cursor-x stream))
+    (setf (bitmap-hunk-output-stream-cursor-x stream) 0)
+    (decf (bitmap-hunk-output-stream-old-bottom stream))
+    (incf y)
+    (when (= y height)
+      (decf y)
+      (hunk-copy-lines hunk 1 0 y)
+      (hunk-clear-lines hunk y 1))
+    (setf (bitmap-hunk-output-stream-cursor-y stream) y)))
+
+;;; Bitmap-Hunk-Misc  --  Internal
+;;;
+;;;    This is the misc method for bitmap-hunk-output-streams.  It just
+;;; writes out the contents of the buffer, and does the element type.
+;;;
+(defun bitmap-hunk-misc (stream operation &optional arg1 arg2)
+  (declare (ignore arg1 arg2))
+  (case operation
+    (:charpos
+     (values (bitmap-hunk-output-stream-cursor-x stream)
+	     (bitmap-hunk-output-stream-cursor-y stream)))
+    ((:finish-output :force-output)
+     (hunk-write-string (bitmap-hunk-output-stream-hunk stream)
+			0 (bitmap-hunk-output-stream-cursor-y stream) 
+			(bitmap-hunk-output-stream-buffer stream) 0
+			(bitmap-hunk-output-stream-cursor-x stream))
+     (let ((device (device-hunk-device (bitmap-hunk-output-stream-hunk stream))))
+       (when (device-force-output device)
+	 (funcall (device-force-output device)))))
+    (:line-length
+     (bitmap-hunk-char-width (bitmap-hunk-output-stream-hunk stream)))
+    (:element-type 'base-char)))
+
+
+;;; Bitmap-Hunk-Out  --  Internal
+;;;
+;;;    Throw a character in a bitmap-hunk-stream's buffer.  If we wrap or hit a 
+;;; newline then call bitmap-hunk-stream-newline.
+;;;
+(defun bitmap-hunk-out (stream character)
+  (let ((hunk (bitmap-hunk-output-stream-hunk stream))
+	(x (bitmap-hunk-output-stream-cursor-x stream)))
+    (cond ((char= character #\newline)
+	   (bitmap-hunk-stream-newline stream)
+	   (return-from bitmap-hunk-out nil))
+	  ((= x (bitmap-hunk-char-width hunk))
+	   (setq x 0)
+	   (bitmap-hunk-stream-newline stream)))
+    (setf (schar (bitmap-hunk-output-stream-buffer stream) x) character)
+    (setf (bitmap-hunk-output-stream-cursor-x stream) (1+ x))))
+
+
+;;; Bitmap-Hunk-Sout  --  Internal
+;;;
+;;;    Write a string out to a bitmap-hunk, calling ourself recursively if the
+;;; string contains newlines.
+;;;
+(defun bitmap-hunk-sout (stream string start end)
+  (let* ((hunk (bitmap-hunk-output-stream-hunk stream))
+	 (buffer (bitmap-hunk-output-stream-buffer stream))
+	 (x (bitmap-hunk-output-stream-cursor-x stream))
+	 (dst-end (+ x (- end start)))
+	 (width (bitmap-hunk-char-width hunk)))
+    (cond ((%primitive find-character string start end #\newline)
+	   (do ((current (%primitive find-character string start end #\newline)
+			 (%primitive find-character string (1+ current)
+				     end #\newline))
+		(previous start (1+ current)))
+	       ((null current)
+		(bitmap-hunk-sout stream string previous end))
+	     (bitmap-hunk-sout stream string previous current)
+	     (bitmap-hunk-stream-newline stream)))
+	  ((> dst-end width)
+	   (let ((new-start (+ start (- width x))))
+	     (%primitive byte-blt string start buffer x width)
+	     (setf (bitmap-hunk-output-stream-cursor-x stream) width)
+	     (bitmap-hunk-stream-newline stream)
+	     (do ((idx (+ new-start width) (+ idx width))
+		  (prev new-start idx))
+		 ((>= idx end)
+		  (let ((dst-end (- end prev)))
+		    (%primitive byte-blt string prev buffer 0 dst-end)
+		    (setf (bitmap-hunk-output-stream-cursor-x stream) dst-end)))
+	       (%primitive byte-blt string prev buffer 0 width)
+	       (setf (bitmap-hunk-output-stream-cursor-x stream) width)
+	       (bitmap-hunk-stream-newline stream))))
+	  (t
+	   (%primitive byte-blt string start buffer x dst-end)
+	   (setf (bitmap-hunk-output-stream-cursor-x stream) dst-end)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/clx-ext.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/clx-ext.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/clx-ext.lisp	(revision 13309)
@@ -0,0 +1,387 @@
+;;; -*- Package: Extensions; Log: code.log; Mode: Lisp -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+(ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains code to extend CLX in the CMU Common Lisp environment.
+;;;
+;;; Written by Bill Chiles and Chris Hoover.
+;;;
+
+(in-package "EXTENSIONS")
+
+(export '(open-clx-display with-clx-event-handling enable-clx-event-handling
+	  disable-clx-event-handling object-set-event-handler
+	  default-clx-event-handler
+	  flush-display-events carefully-add-font-paths
+
+	  serve-key-press serve-key-release serve-button-press
+	  serve-button-release serve-motion-notify serve-enter-notify
+	  serve-leave-notify serve-focus-in serve-focus-out 
+	  serve-exposure serve-graphics-exposure serve-no-exposure
+	  serve-visibility-notify serve-create-notify serve-destroy-notify
+	  serve-unmap-notify serve-map-notify serve-map-request
+	  serve-reparent-notify serve-configure-notify serve-gravity-notify
+	  serve-resize-request serve-configure-request serve-circulate-notify
+	  serve-circulate-request serve-property-notify serve-selection-clear
+	  serve-selection-request serve-selection-notify serve-colormap-notify
+	  serve-client-message))
+
+
+
+
+;;;; OPEN-CLX-DISPLAY.
+
+(defun open-clx-display (&optional (string (cdr (assoc :display
+						       *environment-list*
+						       :test #'eq))))
+  "Parses a display specification including display and screen numbers.
+   This returns nil when there is no DISPLAY environment variable.  If string
+   is non-nil, and any fields are missing in the specification, this signals an
+   error.  If you specify a screen, then this sets XLIB:DISPLAY-DEFAULT-SCREEN
+   to that screen since CLX initializes this form to the first of
+   XLIB:SCREEN-ROOTS.  This returns the display and screen objects."
+  (when string
+    (let* ((string (coerce string 'simple-string))
+	   (length (length string))
+	   ;;pw-- "unix" is a signal to the connect_to_inet C code
+	   ;;     to open an AF_UNIX socket instead of an AF_INET one.
+	   ;;     This is supposed to be faster on a local server.
+	   (host-name "unix")
+	   (auth-name nil)
+	   (auth-data nil)
+	   (display-num nil)
+	   (screen-num nil))
+      (declare (simple-string string))
+      (let ((colon (position #\: string :test #'char=)))
+	(cond ((null colon)
+	       (error "Missing display number in DISPLAY environment variable."))
+	      (t
+	       (unless (zerop colon) (setf host-name (subseq string 0 colon)))
+	       (let* ((start (1+ colon))
+		      (first-dot (position #\. string
+					   :test #'char= :start start)))
+		 (cond ((= start (or first-dot length))
+			(error "Badly formed display number in DISPLAY ~
+				environment variable."))
+		       ((null first-dot)
+			(setf display-num (parse-integer string :start start)))
+		       (t
+			(setf display-num (parse-integer string :start start
+							 :end first-dot))
+			(let* ((start (1+ first-dot))
+			       (second-dot (position #\. string :test #'char=
+						     :start start)))
+			  (cond ((= start (or second-dot length))
+				 (error "Badly formed screen number in ~
+					 DISPLAY environment variable."))
+				(t
+				 (setf screen-num
+				       (parse-integer string :start start
+						      :end second-dot)))))))))))
+      (if (equal host-name "unix")
+        (multiple-value-setq (auth-name auth-data)
+          (xlib::get-best-authorization (machine-instance) display-num :tcp)))
+      (let ((display (xlib:open-display host-name
+                                      :display display-num
+                                      :authorization-name auth-name
+                                      :authorization-data auth-data)))
+	(when screen-num
+	  (let* ((screens (xlib:display-roots display))
+		 (num-screens (length screens)))
+	    (when (>= screen-num num-screens)
+	      (xlib:close-display display)
+	      (error "No such screen number (~D)." screen-num))
+	    (setf (xlib:display-default-screen display)
+		  (elt screens screen-num))))
+	(values display (xlib:display-default-screen display))))))
+
+
+
+;;;; Font Path Manipulation
+
+(defun carefully-add-font-paths (display font-pathnames
+					 &optional (operation :append))
+  "Adds the list of font pathnames, Font-Pathnames, to the font path of
+  the server Display but does so carefully by checking to make sure that
+  the font pathnames are not already on the server's font path.  If any
+  of the font pathnames are on the server's font path, they will remain
+  in their current positions.  Operation may be specified as either
+  :prepend or :append and specifies whether to add the additional font
+  pathnames to the beginning or the end of the server's original font
+  path."
+  (let ((font-path (xlib:font-path display))
+	(result ()))
+    (dolist (elt font-pathnames)
+      (enumerate-search-list (pathname elt)
+	(lisp::enumerate-matches (name pathname)
+	  (unless (member name font-path :test #'string=)
+	    (push name result)))))
+    (when result
+      (ecase operation
+	(:prepend
+	 (setf (xlib:font-path display) (revappend result font-path)))
+	(:append
+	 (setf (xlib:font-path display)
+	       (append font-path (nreverse result))))))))
+
+
+
+;;;; Enabling and disabling event handling through SYSTEM:SERVE-EVENT.
+
+(defvar *clx-fds-to-displays* (make-hash-table :test #'eql)
+  "This is a hash table that maps CLX file descriptors to CLX display
+   structures.  For every CLX file descriptor know to SYSTEM:SERVE-EVENT,
+   there must be a mapping from that file descriptor to its CLX display
+   structure when events are handled via SYSTEM:SERVE-EVENT.")
+
+(defmacro with-clx-event-handling ((display handler) &rest body)
+  "Evaluates body in a context where events are handled for the display
+   by calling handler on the display.  This destroys any previously established
+   handler for display."
+  `(unwind-protect
+       (progn
+	 (enable-clx-event-handling ,display ,handler)
+	 ,@body)
+     (disable-clx-event-handling ,display)))
+
+;;; ENABLE-CLX-EVENT-HANDLING associates the display with the handler in
+;;; *display-event-handlers*.  It also uses SYSTEM:ADD-FD-HANDLER to have
+;;; SYSTEM:SERVE-EVENT call CALL-DISPLAY-EVENT-HANDLER whenever anything shows
+;;; up from the display. Since CALL-DISPLAY-EVENT-HANDLER is called on a
+;;; file descriptor, the file descriptor is also mapped to the display in
+;;; *clx-fds-to-displays*, so the user's handler can be called on the display.
+;;;
+(defun enable-clx-event-handling (display handler)
+  "After calling this, when SYSTEM:SERVE-EVENT notices input on display's
+   connection to the X11 server, handler is called on the display.  Handler
+   is invoked in a dynamic context with an error handler bound that will
+   flush all events from the display and return.  By returning, it declines
+   to handle the error, but it will have cleared all events; thus, entering
+   the debugger will not result in infinite errors due to streams that wait
+   via SYSTEM:SERVE-EVENT for input.  Calling this repeatedly on the same
+   display establishes handler as a new handler, replacing any previous one
+   for display."
+  (check-type display xlib:display)
+  (let ((change-handler (assoc display *display-event-handlers*)))
+    (if change-handler
+	(setf (cdr change-handler) handler)
+	(let ((fd (fd-stream-fd (xlib::display-input-stream display))))
+	  (system:add-fd-handler fd :input #'call-display-event-handler)
+	  (setf (gethash fd *clx-fds-to-displays*) display)
+	  (push (cons display handler) *display-event-handlers*)))))
+
+;;; CALL-DISPLAY-EVENT-HANDLER maps the file descriptor to its display and maps
+;;; the display to its handler.  If we can't find the display, we remove the
+;;; file descriptor using SYSTEM:INVALIDATE-DESCRIPTOR and try to remove the
+;;; display from *display-event-handlers*.  This is necessary to try to keep
+;;; SYSTEM:SERVE-EVENT from repeatedly trying to handle the same event over and
+;;; over.  This is possible since many CMU Common Lisp streams loop over
+;;; SYSTEM:SERVE-EVENT, so when the debugger is entered, infinite errors are
+;;; possible.
+;;;
+(defun call-display-event-handler (file-descriptor)
+  (let ((display (gethash file-descriptor *clx-fds-to-displays*)))
+    (unless display
+      (system:invalidate-descriptor file-descriptor)
+      (setf *display-event-handlers*
+	    (delete file-descriptor *display-event-handlers*
+		    :key #'(lambda (d/h)
+			     (fd-stream-fd
+			      (xlib::display-input-stream
+			       (car d/h))))))
+      (error "File descriptor ~S not associated with any CLX display.~%~
+                It has been removed from system:serve-event's knowledge."
+	     file-descriptor))
+    (let ((handler (cdr (assoc display *display-event-handlers*))))
+      (unless handler
+	(flush-display-events display)
+	(error "Display ~S not associated with any event handler." display))
+      (handler-bind ((error #'(lambda (condx)
+				(declare (ignore condx))
+				(flush-display-events display))))
+	(funcall handler display)))))
+
+(defun disable-clx-event-handling (display)
+  "Undoes the effect of EXT:ENABLE-CLX-EVENT-HANDLING."
+  (setf *display-event-handlers*
+	(delete display *display-event-handlers* :key #'car))
+  (let ((fd (fd-stream-fd (xlib::display-input-stream display))))
+    (remhash fd *clx-fds-to-displays*)
+    (system:invalidate-descriptor fd)))
+
+
+
+
+;;;; Object set event handling.
+
+;;; This is bound by OBJECT-SET-EVENT-HANDLER, so DISPATCH-EVENT can clear
+;;; events on the display before signalling any errors.  This is necessary
+;;; since reading on certain CMU Common Lisp streams involves SERVER, and
+;;; getting an error while trying to handle an event causes repeated attempts
+;;; to handle the same event.
+;;;
+(defvar *process-clx-event-display* nil)
+
+(defvar *object-set-event-handler-print* nil)
+
+(declaim (declaration values))
+
+(defun object-set-event-handler (display)
+  "This display event handler uses object sets to map event windows cross
+   event types to handlers.  It uses XLIB:EVENT-CASE to bind all the slots
+   of each event, calling the handlers on all these values in addition to
+   the event key and send-event-p.  Describe EXT:SERVE-MUMBLE, where mumble
+   is an event keyword name for the exact order of arguments.
+   :mapping-notify and :keymap-notify events are ignored since they do not
+   occur on any particular window.  After calling a handler, each branch
+   returns t to discard the event.  While the handler is executing, all
+   errors go through a handler that flushes all the display's events and
+   returns.  This prevents infinite errors since the debug and terminal
+   streams loop over SYSTEM:SERVE-EVENT.  This function returns t if there
+   were some event to handle, nil otherwise.  It returns immediately if
+   there is no event to handle."
+  (macrolet ((dispatch (event-key &rest args)
+	       `(multiple-value-bind (object object-set)
+				     (lisp::map-xwindow event-window)
+		  (unless object
+		    (cond ((not (typep event-window 'xlib:window))
+			   (xlib:discard-current-event display)
+			   (warn "Discarding ~S event on non-window ~S."
+				 ,event-key event-window)
+			   (return-from object-set-event-handler nil))
+			  (t
+			   (flush-display-events display)
+			   (error "~S not a known X window.~%~
+			           Received event ~S."
+				  event-window ,event-key))))
+		  (handler-bind ((error #'(lambda (condx)
+					    (declare (ignore condx))
+					    (flush-display-events display))))
+		    (when *object-set-event-handler-print*
+		      (print ,event-key) (force-output))
+		    (funcall (gethash ,event-key
+				      (lisp::object-set-table object-set)
+				      (lisp::object-set-default-handler
+				       object-set))
+			     object ,event-key
+			     ,@args))
+		  (setf result t))))
+    (let ((*process-clx-event-display* display)
+	  (result nil))
+      (xlib:event-case (display :timeout 0)
+	((:KEY-PRESS :KEY-RELEASE :BUTTON-PRESS :BUTTON-RELEASE)
+	     (event-key event-window root child same-screen-p
+	      x y root-x root-y state time code send-event-p)
+	 (dispatch event-key event-window root child same-screen-p
+		   x y root-x root-y state time code send-event-p))
+	(:MOTION-NOTIFY (event-window root child same-screen-p
+			 x y root-x root-y state time hint-p send-event-p)
+	 (dispatch :motion-notify event-window root child same-screen-p
+		   x y root-x root-y state time hint-p send-event-p))
+	(:ENTER-NOTIFY (event-window root child same-screen-p
+			x y root-x root-y state time mode kind send-event-p)
+	 (dispatch :enter-notify event-window root child same-screen-p
+		   x y root-x root-y state time mode kind send-event-p))
+	(:LEAVE-NOTIFY (event-window root child same-screen-p
+			x y root-x root-y state time mode kind send-event-p)
+	 (dispatch :leave-notify event-window root child same-screen-p
+		   x y root-x root-y state time mode kind send-event-p))
+	(:EXPOSURE (event-window x y width height count send-event-p)
+	 (dispatch :exposure event-window x y width height count send-event-p))
+	(:GRAPHICS-EXPOSURE (event-window x y width height count major minor
+			     send-event-p)
+	 (dispatch :graphics-exposure event-window x y width height
+		   count major minor send-event-p))
+	(:NO-EXPOSURE (event-window major minor send-event-p)
+	 (dispatch :no-exposure event-window major minor send-event-p))
+	(:FOCUS-IN (event-window mode kind send-event-p)
+	 (dispatch :focus-in event-window mode kind send-event-p))
+	(:FOCUS-OUT (event-window mode kind send-event-p)
+	 (dispatch :focus-out event-window mode kind send-event-p))
+	(:KEYMAP-NOTIFY ()
+	 (warn "Ignoring keymap notify event.")
+	 (when *object-set-event-handler-print*
+	   (print :keymap-notify) (force-output))
+	 (setf result t))
+	(:VISIBILITY-NOTIFY (event-window state send-event-p)
+	 (dispatch :visibility-notify event-window state send-event-p))
+	(:CREATE-NOTIFY (event-window window x y width height border-width
+			 override-redirect-p send-event-p)
+	 (dispatch :create-notify event-window window x y width height
+		   border-width override-redirect-p send-event-p))
+	(:DESTROY-NOTIFY (event-window window send-event-p)
+	 (dispatch :destroy-notify event-window window send-event-p))
+	(:UNMAP-NOTIFY (event-window window configure-p send-event-p)
+	 (dispatch :unmap-notify event-window window configure-p send-event-p))
+	(:MAP-NOTIFY (event-window window override-redirect-p send-event-p)
+	 (dispatch :map-notify event-window window override-redirect-p
+		   send-event-p))
+	(:MAP-REQUEST (event-window window send-event-p)
+	 (dispatch :map-request event-window window send-event-p))
+	(:REPARENT-NOTIFY (event-window window parent x y override-redirect-p
+			   send-event-p)
+	 (dispatch :reparent-notify event-window window parent x y
+		   override-redirect-p send-event-p))
+	(:CONFIGURE-NOTIFY (event-window window x y width height border-width
+			    above-sibling override-redirect-p send-event-p)
+	 (dispatch :configure-notify event-window window x y width height
+		   border-width above-sibling override-redirect-p
+		   send-event-p))
+	(:GRAVITY-NOTIFY (event-window window x y send-event-p)
+	 (dispatch :gravity-notify event-window window x y send-event-p))
+	(:RESIZE-REQUEST (event-window width height send-event-p)
+	 (dispatch :resize-request event-window width height send-event-p))
+	(:CONFIGURE-REQUEST (event-window window x y width height border-width
+			     stack-mode above-sibling value-mask send-event-p)
+	 (dispatch :configure-request event-window window x y width height
+		   border-width stack-mode above-sibling value-mask
+		   send-event-p))
+	(:CIRCULATE-NOTIFY (event-window window place send-event-p)
+	 (dispatch :circulate-notify event-window window place send-event-p))
+	(:CIRCULATE-REQUEST (event-window window place send-event-p)
+	 (dispatch :circulate-request event-window window place send-event-p))
+	(:PROPERTY-NOTIFY (event-window atom state time send-event-p)
+	 (dispatch :property-notify event-window atom state time send-event-p))
+	(:SELECTION-CLEAR (event-window selection time send-event-p)
+	 (dispatch :selection-notify event-window selection time send-event-p))
+	(:SELECTION-REQUEST (event-window requestor selection target property
+			     time send-event-p)
+	 (dispatch :selection-request event-window requestor selection target
+		   property time send-event-p))
+	(:SELECTION-NOTIFY (event-window selection target property time
+			    send-event-p)
+	 (dispatch :selection-notify event-window selection target property time
+		   send-event-p))
+	(:COLORMAP-NOTIFY (event-window colormap new-p installed-p send-event-p)
+	 (dispatch :colormap-notify event-window colormap new-p installed-p
+		   send-event-p))
+	(:MAPPING-NOTIFY (request)
+	 (warn "Ignoring mapping notify event -- ~S." request)
+	 (when *object-set-event-handler-print*
+	   (print :mapping-notify) (force-output))
+	 (setf result t))
+	(:CLIENT-MESSAGE (event-window format data send-event-p)
+	 (dispatch :client-message event-window format data send-event-p)))
+      result)))
+
+(defun default-clx-event-handler (object event-key event-window &rest ignore)
+  (declare (ignore ignore))
+  (flush-display-events *process-clx-event-display*)
+  (error "No handler for event type ~S on ~S in ~S."
+	 event-key object (lisp::map-xwindow event-window)))
+
+(defun flush-display-events (display)
+  "Dumps all the events in display's event queue including the current one
+   in case this is called from within XLIB:EVENT-CASE, etc."
+  (xlib:discard-current-event display)
+  (xlib:event-case (display :discard-p t :timeout 0)
+    (t () nil)))
+
+
Index: /branches/new-random/cocoa-ide/hemlock/unused/cursor.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/cursor.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/cursor.lisp	(revision 13309)
@@ -0,0 +1,362 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Rob MacLachlan
+;;;
+;;; Cursor: Routines for cursor positioning and recentering
+;;;
+(in-package :hemlock-internals)
+
+
+
+;;;; Mark-To-Cursorpos
+;;;
+;;; Since performance analysis showed that HALF of the time in the editor
+;;; was being spent in this function, I threw all of the tricks in the
+;;; book at it to try and make it tenser.
+;;;
+;;; The algorithm is roughly as follows:
+;;;
+;;;    1) Eliminate the annoying boundry condition of the mark being
+;;; off the end of the window, if it is return NIL now.
+;;;    2) If the charpos is on or immediately after the last character
+;;; in the line, then find the last dis-line on which the line is
+;;; displayed.  We know that the mark is at the end of this dis-line
+;;; because it is known to be on the screen.  X position is trivially
+;;; derived from the dis-line-length.
+;;;    3) Call Real-Line-Length or Cached-Real-Line-Length to get the
+;;; X position and number of times wrapped.
+
+(declaim (special *the-sentinel*))
+
+(eval-when (:compile-toplevel :execute)
+;;; find-line
+;;;
+;;;    Find a dis-line which line is displayed on which starts before
+;;; charpos, setting ypos and dis-line to the dis-line and it's index.
+;;; Offset is expected to be the mark-charpos of the display-start for
+;;; the window initially, and is set to offset within line that
+;;; Dis-Line begins.  Charpos is the mark-charpos of the mark we want
+;;; to find.  Check if same as *redisplay-favorite-line* and then scan
+;;; if not.
+;;;
+(defmacro find-line (line offset charpos ypos dis-lines dis-line)
+  (declare (ignore charpos))
+  `(cond
+    ;; No lines at all, fail.
+    ((eq ,dis-lines *the-sentinel*) nil)
+    ;; On the first line, offset is already set, so just set dis-line and
+    ;; ypos and fall through.
+    ((eq (dis-line-line (car ,dis-lines)) ,line)
+     (setq ,dis-line ,dis-lines  ,ypos 0))
+    ;; Look farther down. 
+    ((do ((l (cdr ,dis-lines) (cdr l)))
+	 ((eq l *the-sentinel*))
+       (when (eq (dis-line-line (car l)) ,line)
+	 (setq ,dis-line l  ,ypos (dis-line-position (car l)) ,offset 0)
+	 (return t))))
+    (t
+     (error "Horrible flaming lossage, Sorry Man."))))
+
+
+;;; find-last 
+;;;
+;;;    Find the last dis-line on which line is displayed, set ypos and 
+;;; dis-line.
+;;;
+(defmacro find-last (line ypos dis-line)
+  `(do ((trail ,dis-line dl)
+	(dl (cdr ,dis-line) (cdr dl)))
+       ((not (eq (dis-line-line (car dl)) ,line))
+	(setq ,dis-line (car trail)  ,ypos (dis-line-position ,dis-line)))))
+
+;;; find-charpos
+;;;
+;;;    Special-Case mark at end of line, if not punt out to real-line-length 
+;;; function.  Return the correct values.
+;;;
+(defmacro find-charpos (line offset charpos length ypos dis-line width
+			     fun chars)
+  (declare (ignore chars))
+  `(cond
+    ((= ,charpos ,length)
+     (find-last ,line ,ypos ,dis-line)
+     (values (min (dis-line-length ,dis-line) (1- ,width)) ,ypos))
+    ((= ,charpos (1- ,length))
+     (multiple-value-bind (x dy)
+			  (,fun ,line (1- ,width) ,offset ,charpos)
+       (if (and (not (zerop dy)) (zerop x))
+	   (values (1- ,width) (1- (+ ,ypos dy)))
+	   (values x (+ ,ypos dy)))))
+    (t
+     (multiple-value-bind (x dy)
+			  (,fun ,line (1- ,width) ,offset ,charpos)
+	  (values x (+ ,ypos dy))))))
+
+); eval-when
+
+
+;;; real-line-length 
+;;;
+;;;    Return as values the X position and the number of times wrapped if
+;;; one to display the characters from Start to End of Line starting at an
+;;; X position of 0 wrapping Width wide.
+;;; %SP-Find-Character-With-Attribute is used to find charaters 
+;;; with funny representation much as in Compute-Line-Image.
+;;;
+(defun real-line-length (line width start end)
+  (declare (fixnum width start end))
+  (do ((xpos 0)
+       (ypos 0)
+       (chars (line-chars line))
+       (losing 0)
+       (dy 0))
+      ((= start end) (values xpos ypos))
+    (declare (fixnum xpos ypos dy) (simple-string chars)
+	     (type (or fixnum null) losing))
+    (setq losing (%fcwa chars start end losing-char))
+    (when (null losing)
+      (multiple-value-setq (dy xpos) (truncate (+ xpos (- end start)) width))
+      (return (values xpos (+ ypos dy))))
+    (multiple-value-setq (dy xpos) (truncate (+ xpos (- losing start)) width))
+    (setq ypos (+ ypos dy)  start losing)
+    (do ((last (or (%fcwa chars start end winning-char) end)) str)
+	((= start last))
+      (declare (fixnum last))
+      (setq str (get-rep (schar chars start)))
+      (incf start)
+      (unless (simple-string-p str) (setq str (funcall str xpos)))
+      (multiple-value-setq (dy xpos) (truncate (+ xpos (strlen str)) width))
+      (setq ypos (+ ypos dy)))))
+
+;;; cached-real-line-length
+;;;
+;;;    The same as Real-Line-Length, except does it for the cached line.
+;;; the line argument is ignored, but present to make the arglists the
+;;; same.
+;;;
+(defun cached-real-line-length (line width start end)
+  (declare (fixnum width start end) (ignore line))
+  (let ((offset (- (current-right-open-pos) (current-left-open-pos)))
+	(bound 0))
+    (declare (fixnum offset bound))
+    (cond
+     ((>= start (current-left-open-pos))
+      (setq start (+ start offset)  bound (setq end (+ end offset))))
+     ((> end (current-left-open-pos))
+      (setq bound (current-left-open-pos)  end (+ end offset)))
+     (t
+      (setq bound end)))
+    
+    (do ((xpos 0)
+	 (ypos 0)
+	 (losing 0)
+	 (dy 0))
+	(())
+      (declare (fixnum xpos ypos dy)
+	       (type (or fixnum null) losing))
+      (when (= start bound)
+	(when (= start end) (return (values xpos ypos)))
+	(setq start (current-right-open-pos)  bound end))
+      (setq losing (%fcwa (current-open-chars) start bound losing-char))
+      (cond
+       (losing
+	(multiple-value-setq (dy xpos)
+	  (truncate (+ xpos (- losing start)) width))
+	(setq ypos (+ ypos dy)  start losing)
+	(do ((last (or (%fcwa (current-open-chars) start bound winning-char) bound)) str)
+	    ((= start last))
+	  (declare (fixnum last))
+	  (setq str (get-rep (schar (current-open-chars) start)))
+	  (incf start)
+	  (unless (simple-string-p str) (setq str (funcall str xpos)))
+	  (multiple-value-setq (dy xpos)
+	    (truncate (+ xpos (strlen str)) width))
+	  (setq ypos (+ ypos dy))))
+       (t
+	(multiple-value-setq (dy xpos)
+	  (truncate (+ xpos (- bound start)) width))
+	(setq ypos (+ ypos dy)  start bound))))))
+
+
+
+;;; Dis-Line-Offset-Guess  --  Internal
+;;;
+;;;    Move Mark by Offset display lines.  The mark is assumed to be at the
+;;; beginning of a display line, and we attempt to leave it at one.  We assume
+;;; all characters print one wide.  Width is the width of the window we are
+;;; displaying in.
+;;;
+(defun dis-line-offset-guess (mark offset width)
+  (let ((w (1- width)))
+    (if (minusp offset)
+	(dotimes (i (- offset) t)
+	  (let ((pos (mark-charpos mark)))
+	    (if (>= pos w)
+		(character-offset mark (- w))
+		(let ((prev (line-previous (mark-line mark))))
+		  (unless prev (return nil))
+		  (multiple-value-bind
+		      (lines chars)
+		      (truncate (line-length prev) w)
+		    (move-to-position mark
+				      (cond ((zerop lines) 0)
+					    ((< chars 2)
+					     (* w (1- lines)))
+					    (t
+					     (* w lines)))
+				      prev))))))
+	(dotimes (i offset t)
+	  (let ((left (- (line-length (mark-line mark))
+			 (mark-charpos mark))))
+	    (if (> left width)
+		(character-offset mark w)
+		(unless (line-offset mark 1 0)
+		  (return nil))))))))
+
+;;; maybe-recenter-window  --  Internal
+;;;
+;;;     Update the dis-lines for Window and recenter if the point is off
+;;; the screen.
+;;;
+(defun maybe-recenter-window (window)
+  (unless (%displayed-p (buffer-point (window-buffer window)) window)
+    (center-window window (buffer-point (window-buffer window)))
+    t))
+
+;;; center-window  --  Public
+;;;
+;;;    Try to move the start of window so that Mark is on a line in the 
+;;; center.
+;;;
+(defun center-window (window mark)
+  "Adjust the start of Window so that Mark is displayed on the center line."
+  (let ((height (window-height window))
+	(start (window-display-start window)))
+    (move-mark start mark)
+    (unless (dis-line-offset-guess start (- (truncate height 2))
+				   (window-width window))
+      (move-mark start (buffer-start-mark (window-buffer window))))
+    (update-window-image window)
+    ;; If that doesn't work, panic and make the start the point.
+    (unless (%displayed-p mark window)
+      (move-mark start mark)
+      (update-window-image window))))
+
+
+;;; %Displayed-P  --  Internal
+;;;
+;;;    If Mark is within the displayed bounds in Window, then return true,
+;;; otherwise false.  We assume the window image is up to date.
+;;;
+(defun %displayed-p (mark window)
+  (let ((start (window-display-start window))
+	(end (window-display-end window)))
+    (not (or (mark< mark start) (mark> mark end)
+	     (if (mark= mark end)
+		 (let ((ch (next-character end)))
+		   (and ch (char/= ch #\newline)))
+		 nil)))))
+
+
+;;; Displayed-p  --  Public
+;;;
+;;;    Update the window image and then check if the mark is displayed.
+;;;
+(defun displayed-p (mark window)
+  "Return true if Mark is displayed on Window, false otherwise."
+  (maybe-update-window-image window)
+  (%displayed-p mark window))
+
+
+;;; scroll-window  --  Public
+;;;
+;;;    This is not really right, since it uses dis-line-offset-guess.
+;;; Probably if there is any screen overlap then we figure it out
+;;; exactly.
+;;;
+
+
+
+;;; Mark-Column  --  Public
+;;;
+;;;    Find the X position of a mark supposing that it were displayed
+;;; in an infinitely wide screen.
+;;;
+(defun mark-column (mark)
+  "Find the X position at which Mark would be displayed if it were on
+  an infinitely wide screen.  This takes into account tabs and control
+  characters."
+  (let ((charpos (mark-charpos mark))
+	(line (mark-line mark)))
+    (if (current-open-line-p line)
+	(values (cached-real-line-length line 10000 0 charpos))
+	(values (real-line-length line 10000 0 charpos)))))
+
+
+;;; Find-Position  --  Internal
+;;;
+;;;    Return the charpos which corresponds to the specified X position
+;;; within Line.  If there is no such position between Start and End then
+;;; rutne NIL.
+;;;
+(defun find-position (line position start end width)
+  (do* ((cached (current-open-line-p line))
+	(lo start)
+	(hi (1- end))
+	(probe (truncate (+ lo hi) 2) (truncate (+ lo hi) 2)))
+       ((> lo hi)
+	(if (= lo end) nil hi))
+    (let ((val (if cached
+		   (cached-real-line-length line width start probe)
+		   (real-line-length line width start probe))))
+      (cond ((= val position) (return probe))
+	    ((< val position) (setq lo (1+ probe)))
+	    (t (setq hi (1- probe)))))))
+
+;;; Cursorpos-To-Mark  --  Public
+;;;
+;;;    Find the right dis-line, then zero in on the correct position
+;;; using real-line-length.
+;;;
+(defun cursorpos-to-mark (x y window)
+  (check-type window window)
+  (let ((width (window-width window))
+	(first (window-first-line window)))
+    (when (>= x width)
+      (return-from cursorpos-to-mark nil))
+    (do* ((prev first dl)
+	  (dl (cdr first) (cdr dl))
+	  (ppos (mark-charpos (window-display-start window))
+		(if (eq (dis-line-line (car dl)) (dis-line-line (car prev)))
+		    (dis-line-end (car prev)) 0)))
+	((eq dl *the-sentinel*)
+	 (copy-mark (window-display-end window) :temporary))
+      (when (= (dis-line-position (car dl)) y)
+	(let* ((line (dis-line-line (car dl)))
+	       (end (dis-line-end (car dl))))
+	  (return (mark line (or (find-position line x ppos end width) end))))))))
+
+;;; Move-To-Column  --  Public
+;;;
+;;;    Just look up the charpos using find-position...
+;;;
+(defun move-to-column (mark column &optional (line (mark-line mark)))
+  "Move Mark to the specified Column on Line.  This function is analogous
+  to Move-To-Position, but it deals with the physical screen position
+  as returned by Mark-Column; the mark is moved to before the character
+  which would be displayed in Column if the line were displayed on
+  an infinitely wide screen.  If the column specified is greater than
+  the column of the last character, then Nil is returned and the mark
+  is not modified."
+  (let ((res (find-position line column 0 (line-length line) 10000)))
+    (if res
+	(move-to-position mark res line))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/ed-integrity.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/ed-integrity.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/ed-integrity.lisp	(revision 13309)
@@ -0,0 +1,165 @@
+;;; -*- Package: hemlock; Log: hemlock.log; Mode: Lisp -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This stuff can be used for testing tty redisplay.  There are four
+;;; commands that, given "Setup Tty Buffer", that test
+;;; HI::COMPUTE-TTY-CHANGES: "Two Deletes", "Two Inserts", "One Delete One
+;;; Insert", and "One Insert One Delete.  Each can be called with an
+;;; argument to generate a grand total of eight screen permutations.
+;;; "Setup Tty Buffer" numbers the lines of the main window 0 through 19
+;;; inclusively.
+;;; 
+;;; "Setup for Debugging" and "Cleanup for Debugging" were helpful in
+;;; conjunction with some alternate versions of COMPUTE-TTY-CHANGES and
+;;; TTY-SMART-WINDOW-REDISPLAY.  When something went wrong with on
+
+(in-package "ED")
+
+
+(declaim (special hemlock-internals::*debugging-tty-redisplay*
+		  hemlock-internals::*testing-delete-queue*
+		  hemlock-internals::*testing-insert-queue*
+		  hemlock-internals::*testing-moved*
+		  hemlock-internals::*testing-writes*))
+
+
+(defcommand "Setup Tty Buffer" (p)
+  "Clear buffer and insert numbering strings 0..19."
+  "Clear buffer and insert numbering strings 0..19."
+  (declare (ignore p))
+  (delete-region (buffer-region (current-buffer)))
+  (let ((point (current-point)))
+    (dotimes (i 20)
+      (insert-string point (prin1-to-string i))
+      (insert-character point #\newline))
+    (buffer-start point)))
+
+(defcommand "Setup for Debugging" (p)
+  "Set *debugging-tty-redisplay* to t, and some other stuff to nil."
+  "Set *debugging-tty-redisplay* to t, and some other stuff to nil."
+  (declare (ignore p))
+  (setf hi::*debugging-tty-redisplay* t)
+  (setf hi::*testing-delete-queue* nil)
+  (setf hi::*testing-insert-queue* nil)
+  (setf hi::*testing-moved* nil)
+  (setf hi::*testing-writes* nil))
+
+(defcommand "Cleanup for Debugging" (p)
+  "Set *debugging-tty-redisplay* to nil."
+  "Set *debugging-tty-redisplay* to nil."
+  (declare (ignore p))
+  (setf hi::*debugging-tty-redisplay* nil))
+
+;;; Given "Setup Tty Buffer", deletes lines numbered 3, 4, 5, 10, 11, 12,
+;;; 13, and 14.  With argument, 3..7 and 12..14.
+;;; 
+(defcommand "Two Deletes" (p)
+  "At line 3, delete 3 lines.  At line 3+4, delete 5 lines.
+   With an argument, switch the number deleted."
+  "At line 3, delete 3 lines.  At line 3+4, delete 5 lines.
+   With an argument, switch the number deleted."
+  (multiple-value-bind (dnum1 dnum2)
+		       (if p (values 5 3) (values 3 5))
+    (let ((point (current-point)))
+      (move-mark point (window-display-start (current-window)))
+      (line-offset point 3)
+      (with-mark ((end point :left-inserting))
+	(line-offset end dnum1)
+	(delete-region (region point end))
+ 	(line-offset point 4)
+	(line-offset (move-mark end point) dnum2)
+	(delete-region (region point end))))))
+
+
+;;; Given "Setup Tty Buffer", opens two blank lines between 2 and 3, and
+;;; opens four blank lines between 6 and 7, leaving line numbered 13 at
+;;; the bottom.  With argument, four lines between 2 and 3, two lines
+;;; between 6 and 7, and line 13 at the bottom of the window.
+;;; 
+(defcommand "Two Inserts" (p)
+  "At line 3, open 2 lines.  At line 3+2+4, open 4 lines.
+   With an argument, switch the number opened."
+  "At line 3, open 2 lines.  At line 3+2+4, open 4 lines.
+   With an argument, switch the number opened."
+  (multiple-value-bind (onum1 onum2)
+		       (if p (values 4 2) (values 2 4))
+    (let ((point (current-point)))
+      (move-mark point (window-display-start (current-window)))
+      (line-offset point 3)
+      (dotimes (i onum1)
+	(insert-character point #\newline))
+      (line-offset point 4)
+      (dotimes (i onum2)
+	(insert-character point #\newline)))))
+
+
+;;; Given "Setup Tty Buffer", deletes lines numbered 3, 4, and 5, and
+;;; opens five lines between lines numbered 9 and 10, leaving line numbered
+;;; 17 on the bottom.  With an argument, deletes lines numbered 3, 4, 5, 6,
+;;; and 7, and opens three lines between 11 and 12, creating two blank lines
+;;; at the end of the screen.
+;;; 
+(defcommand "One Delete One Insert" (p)
+  "At line 3, delete 3 lines.  At line 3+4, open 5 lines.
+   With an argument, switch the number of lines affected."
+  "At line 3, delete 3 lines.  At line 3+4, open 5 lines.
+   With an argument, switch the number of lines affected."
+  (multiple-value-bind (dnum onum)
+		       (if p (values 5 3) (values 3 5))
+    (let ((point (current-point)))
+      (move-mark point (window-display-start (current-window)))
+      (line-offset point 3)
+      (with-mark ((end point :left-inserting))
+	(line-offset end dnum)
+	(delete-region (region point end))
+ 	(line-offset point 4)
+	(dotimes (i onum)
+	  (insert-character point #\newline))))))
+
+;;; Given "Setup Tty Buffer", opens three blank lines between lines numbered
+;;; 2 and 3, and deletes lines numbered 7, 8, 9, 10, and 11, leaving two
+;;; blank lines at the bottom of the window.  With an argument, opens five
+;;; blank lines between lines numbered 2 and 3, and deletes lines 7, 8, and
+;;; 9, leaving line 17 at the bottom of the window.
+;;; 
+(defcommand "One Insert One Delete" (p)
+  "At line 3, open 3 lines.  At line 3+3+4, delete 5 lines.
+   With an argument, switch the number of lines affected."
+  "At line 3, open 3 lines.  At line 3+3+4, delete 5 lines.
+   With an argument, switch the number of lines affected."
+  (multiple-value-bind (onum dnum)
+		       (if p (values 5 3) (values 3 5))
+    (let ((point (current-point)))
+      (move-mark point (window-display-start (current-window)))
+      (line-offset point 3)
+      (dotimes (i onum)
+	(insert-character point #\newline))
+      (line-offset point 4)
+      (with-mark ((end point :left-inserting))
+	(line-offset end dnum)
+	(delete-region (region point end))))))
+
+
+;;; This could be thrown away, but I'll leave it here.  When I was testing
+;;; the problem of generating EQ screen image lines due to faulty
+;;; COMPUTE-TTY-CHANGES, this was a convenient command to get the editor
+;;; back under control.
+;;; 
+(defcommand "Fix Screen Image Lines" (p)
+  ""
+  ""
+  (declare (ignore p))
+  (let* ((device (hi::device-hunk-device (hi::window-hunk (current-window))))
+	 (lines (hi::tty-device-lines device))
+	 (columns (hi::tty-device-columns device))
+	 (screen-image (hi::tty-device-screen-image device)))
+    (dotimes (i lines)
+      (setf (svref screen-image i) (hi::make-si-line columns)))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/gosmacs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/gosmacs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/gosmacs.lisp	(revision 13309)
@@ -0,0 +1,33 @@
+;;; -*- Package: Hemlock; Log: Hemlock.Log -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Stuff in this file provides some degree of upward compatibility
+;;; for incurable Gosling Emacs users.
+;;;
+(in-package "HEMLOCK")
+
+(defcommand "Gosmacs Permute Characters" (p)
+  "Transpose the two characters before the point."
+  "Transpose the two characters before the point."
+  (declare (ignore p))
+  (with-mark ((m (current-point) :left-inserting))
+    (unless (and (mark-before m) (previous-character m))
+      (editor-error "NIB     You have addressed a character not in the buffer?"))
+    (rotatef (previous-character m) (next-character m))))
+
+(bind-key "Gosmacs Permute Characters" #k"control-t")
+(bind-key "Kill Previous Word" #k"meta-h")
+(bind-key "Replace String" #k"meta-r")
+(bind-key "Query Replace" #k"meta-q")
+(bind-key "Fill Paragraph" #k"meta-j")
+(bind-key "Visit File" #k"control-x control-r")
+(bind-key "Find File" #k"control-x control-v")
+(bind-key "Insert File" #k"control-x control-i")
Index: /branches/new-random/cocoa-ide/hemlock/unused/hacks.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/hacks.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/hacks.lisp	(revision 13309)
@@ -0,0 +1,22 @@
+(in-package "HI")
+
+(defun %sp-byte-blt (src start dest dstart end)
+  (%primitive byte-blt src start dest dstart end))
+
+(defun lisp::sap-to-fixnum (x) (sap-int x))
+(defun lisp::fixnum-to-sap (x) (int-sap x))
+(defun lisp::%sp-make-fixnum (x) (%primitive make-fixnum x))
+(defun lisp::fast-char-upcase (x) (char-upcase x))
+
+;;; prepare-window-for-redisplay  --  Internal
+;;;
+;;;    Called by make-window to do whatever redisplay wants to set up
+;;; a new window.
+;;;
+(defun prepare-window-for-redisplay (window)
+  (setf (window-old-lines window) 0))
+
+(defparameter hunk-width-limit 256)
+
+(defun reverse-video-hook-fun (&rest foo)
+  (declare (ignore foo)))
Index: /branches/new-random/cocoa-ide/hemlock/unused/hemcom.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/hemcom.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/hemcom.lisp	(revision 13309)
@@ -0,0 +1,297 @@
+;;; -*- Package: USER -*-
+;;;
+;;; **********************************************************************
+;;;
+(ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file compiles all of Hemlock.
+;;;
+
+#+bootstrap
+(progn
+  (when (ext:get-command-line-switch "slave")
+    (error "Cannot compile Hemlock in a slave due to its clobbering needed
+    typescript routines by renaming the package."))
+  
+  ;;; Blast the old packages in case they are around.  We do this solely to
+  ;;; prove Hemlock can compile cleanly without its having to exist already.
+  ;;;
+  (copy-packages '("ED" "HI")))
+
+
+;;; Stuff to set up the packages Hemlock uses.
+;;;
+(unless (find-package "HEMLOCK-INTERNALS")
+  (make-package "HEMLOCK-INTERNALS"
+		:nicknames '("HI")
+		:use '("LISP" "EXTENSIONS" "SYSTEM")))
+
+(unless (find-package "HEMLOCK")
+  (make-package "HEMLOCK"
+		:nicknames '("ED")
+		:use '("LISP" "HEMLOCK-INTERNALS" "EXTENSIONS" "SYSTEM")))
+;;;
+(export 'c::compile-from-stream (find-package "C"))
+
+
+(in-package "USER")
+
+(defvar *byte-compile* #+small t #-small :maybe)
+
+(pushnew :command-bits *features*)
+(pushnew :buffered-lines *features*)
+
+#-clx
+;;; If CLX has not been loaded, but has been compiled, then load it.
+;;;
+(when (probe-file (make-pathname :defaults "target:clx/clx-library"
+				 :type (c:backend-fasl-file-type c:*backend*)))
+  #+(and (not pcl) (not no-pcl-clx))
+  (load "target:pcl/pclload")
+  (load "target:clx/clx-library")
+  #+gencgc (gc :full t)
+  #-gencgc (ext:purify))
+  
+(with-compiler-log-file
+    ("target:compile-hemlock.log"
+     :optimize
+     '(optimize (debug #-small 2 #+small .5) 
+		(speed 2) (inhibit-warnings 2)
+		(safety #-small 1 #+small 0))
+     :optimize-interface
+     '(optimize-interface (debug .5))
+     :context-declarations
+     '(((:or :external (:match "$%SET-"))
+	(declare (optimize (safety 2))
+		 (optimize-interface (debug 1))))
+       (:macro (declare (optimize (speed 0))))))
+
+(comf "target:code/globals")
+(comf "target:code/struct")
+(comf "target:hemlock/charmacs")
+(comf "target:hemlock/key-event" :load t)
+(comf "target:hemlock/struct")
+;(comf "target:hemlock/struct-ed")
+(comf "target:hemlock/rompsite")
+;;;
+;;; This is necessary since all the #k uses in Hemlock will expand into
+;;; EXT:MAKE-KEY-EVENT calls with keysyms and bits from the compiling Lisp, not
+;;; for the Lisp new code will run in.  This destroys the compiling Lisp with
+;;; respect to running code with #k's compiled for it, but it causes the
+;;; compilation to see new keysyms, modifiers, and CLX modifier maps correctly
+;;; for the new system.
+;;;
+(ext::re-initialize-key-events)
+(comf "target:hemlock/keysym-defs")
+(comf "target:hemlock/input")
+(comf "target:hemlock/macros" :byte-compile t)
+(comf "target:hemlock/line")
+(comf "target:hemlock/ring")
+(comf "target:hemlock/table")
+(comf "target:hemlock/htext1")
+(comf "target:hemlock/htext2")
+(comf "target:hemlock/htext3")
+(comf "target:hemlock/htext4")
+(comf "target:hemlock/search1")
+(comf "target:hemlock/search2")
+(comf "target:hemlock/linimage")
+(comf "target:hemlock/cursor")
+(comf "target:hemlock/syntax")
+(comf "target:hemlock/winimage")
+#+clx (comf "target:hemlock/hunk-draw")
+;(comf "target:hemlock/bit-stream")
+(comf "target:hemlock/termcap")
+(comf "target:hemlock/display")
+#+clx (comf "target:hemlock/bit-display")
+(comf "target:hemlock/tty-disp-rt")
+(with-compilation-unit (:optimize '(optimize (safety 2) (debug 3)))
+  (comf "target:hemlock/tty-display")) ; Buggy...
+;(comf "target:hemlock/tty-stream")
+(comf "target:hemlock/pop-up-stream")
+(comf "target:hemlock/screen")
+#+clx (comf "target:hemlock/bit-screen")
+(comf "target:hemlock/tty-screen")
+(comf "target:hemlock/window")
+(comf "target:hemlock/font")
+(comf "target:hemlock/interp")
+(comf "target:hemlock/vars")
+(comf "target:hemlock/buffer")
+(comf "target:hemlock/files")
+(comf "target:hemlock/streams")
+(comf "target:hemlock/echo" :byte-compile t)
+(comf "target:hemlock/main" :byte-compile t)
+(comf "target:hemlock/echocoms" :byte-compile t)
+(comf "target:hemlock/defsyn")
+
+(comf "target:hemlock/ts-buf")
+(comf "target:hemlock/ts-stream")
+
+(with-compilation-unit
+    (:optimize
+     '(optimize (safety 2) (speed 0))
+     :context-declarations
+     '(((:match "-COMMAND$")
+	(declare (optimize (safety #+small 0 #-small 1))
+		 (optimize-interface (safety 2))))))
+
+(comf "target:hemlock/command" :byte-compile t)
+(comf "target:hemlock/morecoms" :byte-compile t)
+(comf "target:hemlock/undo" :byte-compile t)
+(comf "target:hemlock/killcoms" :byte-compile t)
+(comf "target:hemlock/searchcoms" :byte-compile t)
+(comf "target:hemlock/filecoms" :byte-compile t)
+(comf "target:hemlock/indent" :byte-compile t)
+(comf "target:hemlock/lispmode")
+(comf "target:hemlock/comments" :byte-compile t)
+(comf "target:hemlock/fill")
+(comf "target:hemlock/text" :byte-compile t)
+(comf "target:hemlock/doccoms" :byte-compile t)
+(comf "target:hemlock/srccom" :byte-compile t)
+(comf "target:hemlock/abbrev" :byte-compile t)
+(comf "target:hemlock/group" :byte-compile t)
+(comf "target:hemlock/overwrite" :byte-compile t)
+(comf "target:hemlock/gosmacs" :byte-compile t)
+(comf "target:hemlock/eval-server" :byte-compile t)
+(comf "target:hemlock/dylan" :byte-compile t)
+(comf "target:hemlock/lispbuf" :byte-compile t)
+(comf "target:hemlock/lispeval" :byte-compile t)
+(comf "target:hemlock/icom" :byte-compile t)
+(comf "target:hemlock/hi-integrity" :byte-compile t)
+(comf "target:hemlock/ed-integrity" :byte-compile t)
+(comf "target:hemlock/scribe" :byte-compile t)
+(comf "target:hemlock/pascal" :byte-compile t)
+(comf "target:hemlock/edit-defs" :byte-compile t)
+(comf "target:hemlock/auto-save" :byte-compile t)
+(comf "target:hemlock/register" :byte-compile t)
+(comf "target:hemlock/xcoms" :byte-compile t)
+(comf "target:hemlock/unixcoms" :byte-compile t)
+(comf "target:hemlock/mh")
+(comf "target:hemlock/highlight" :byte-compile t)
+(comf "target:hemlock/dired" :byte-compile t)
+(comf "target:hemlock/diredcoms" :byte-compile t)
+(comf "target:hemlock/bufed" :byte-compile t)
+(comf "target:hemlock/lisp-lib" :byte-compile t)
+(comf "target:hemlock/completion" :byte-compile t)
+(comf "target:hemlock/shell" :byte-compile t)
+(comf "target:hemlock/debug" :byte-compile t)
+(comf "target:hemlock/netnews" :byte-compile t)
+(comf "target:hemlock/rcs" :byte-compile t)
+
+) ;WITH-COMPILATION-UNIT for commands
+
+;; Stuff we want compiled native:
+
+(comf "target:hemlock/spell-rt")
+(comf "target:hemlock/spell-corr")
+(comf "target:hemlock/spell-aug")
+(comf "target:hemlock/spell-build")
+(comf "target:hemlock/spellcoms")
+(comf "target:hemlock/kbdmac")
+
+(comf "target:hemlock/bindings")
+(comf "target:hemlock/hacks")
+
+) ;WITH-COMPILER-LOG-FILE
+
+(unless (probe-file "target:hemlock/spell-dictionary.bin")
+  (load "target:hemlock/spell-rt")
+  (load "target:hemlock/spell-corr")
+  (load "target:hemlock/spell-aug")
+  (load "target:hemlock/spell-build")
+  (funcall (fdefinition (intern "BUILD-DICTIONARY" "SPELL"))
+	   "target:hemlock/spell-dictionary.text"
+	   "target:hemlock/spell-dictionary.bin"))
+
+(cat-if-anything-changed
+ "target:hemlock/hemlock-library"
+ "target:hemlock/rompsite"
+ "target:hemlock/struct"
+ ; "target:hemlock/struct-ed"
+ "target:hemlock/charmacs"
+ "target:hemlock/input"
+ "target:hemlock/line"
+ "target:hemlock/ring"
+ "target:hemlock/vars"
+ "target:hemlock/buffer"
+ "target:hemlock/macros"
+ "target:hemlock/interp"
+ "target:hemlock/syntax"
+ "target:hemlock/htext1"
+ "target:hemlock/htext2"
+ "target:hemlock/htext3"
+ "target:hemlock/htext4"
+ "target:hemlock/files"
+ "target:hemlock/search1"
+ "target:hemlock/search2"
+ "target:hemlock/table"
+ #+clx "target:hemlock/hunk-draw"
+ "target:hemlock/window"
+ "target:hemlock/screen"
+ "target:hemlock/winimage"
+ "target:hemlock/linimage"
+ "target:hemlock/display"
+ "target:hemlock/termcap"
+ #+clx "target:hemlock/bit-display"
+ "target:hemlock/tty-disp-rt"
+ "target:hemlock/tty-display"
+ "target:hemlock/pop-up-stream"
+ #+clx "target:hemlock/bit-screen"
+ "target:hemlock/tty-screen"
+ "target:hemlock/cursor"
+ "target:hemlock/font"
+ "target:hemlock/streams"
+ "target:hemlock/hacks"
+ "target:hemlock/main"
+ "target:hemlock/echo"
+ "target:hemlock/echocoms"
+ "target:hemlock/command"
+ "target:hemlock/indent"
+ "target:hemlock/comments"
+ "target:hemlock/morecoms"
+ "target:hemlock/undo"
+ "target:hemlock/killcoms"
+ "target:hemlock/searchcoms"
+ "target:hemlock/filecoms"
+ "target:hemlock/doccoms"
+ "target:hemlock/srccom"
+ "target:hemlock/group"
+ "target:hemlock/fill"
+ "target:hemlock/text"
+ "target:hemlock/lispmode"
+ "target:hemlock/ts-buf"
+ "target:hemlock/ts-stream"
+ "target:hemlock/eval-server"
+ "target:hemlock/lispbuf"
+ "target:hemlock/lispeval"
+ "target:hemlock/spell-rt"
+ "target:hemlock/spell-corr"
+ "target:hemlock/spell-aug"
+ "target:hemlock/spellcoms"
+ "target:hemlock/overwrite"
+ "target:hemlock/abbrev"
+ "target:hemlock/icom"
+ "target:hemlock/kbdmac"
+ "target:hemlock/defsyn"
+ "target:hemlock/scribe"
+ "target:hemlock/pascal"
+ "target:hemlock/dylan"
+ "target:hemlock/edit-defs"
+ "target:hemlock/auto-save"
+ "target:hemlock/register"
+ "target:hemlock/xcoms"
+ "target:hemlock/unixcoms"
+ "target:hemlock/mh"
+ "target:hemlock/highlight"
+ "target:hemlock/dired"
+ "target:hemlock/diredcoms"
+ "target:hemlock/bufed"
+ "target:hemlock/lisp-lib"
+ "target:hemlock/completion"
+ "target:hemlock/shell"
+ "target:hemlock/debug"
+ "target:hemlock/netnews"
+ "target:hemlock/rcs"
+ "target:hemlock/bindings")
Index: /branches/new-random/cocoa-ide/hemlock/unused/hi-integrity.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/hi-integrity.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/hi-integrity.lisp	(revision 13309)
@@ -0,0 +1,52 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Skef Wholey
+;;;
+;;; Hack to check a buffer's integrity.
+;;;
+(in-package "HEMLOCK-INTERNALS")
+
+(defun checkit (&optional (buffer (current-buffer)))
+  "Returns NIL if the buffer's region is OK, or a losing line if it ain't.
+  If a malformed mark is found in the mark list it is returned as the 
+  second value."
+  (do ((line (mark-line (buffer-start-mark buffer)) (line-next line))
+       (previous nil line)
+       (lines nil (cons line lines)))
+      ((null line) nil)
+    (unless (eq (line-%buffer line) buffer)
+      (format t "~%Oh, Man!  It's in the wrong buffer!~%")
+      (return line))
+    (when (member line lines)
+      (format t "~%Oh, Man!  It's circular!~%")
+      (return line))
+    (unless (eq previous (line-previous line))
+      (format t "~%Oh, Man!  A back-pointer's screwed up!~%")
+      (return line))
+    (when (and previous (>= (line-number previous) (line-number line)))
+      (format t "~%Oh, Man!  A line number is screwed up!~%")
+      (return line))
+    (let ((res
+	   (do ((m (line-marks line) (cdr m)))
+	       ((null m) nil)
+	     (unless (<= 0 (mark-charpos (car m)) (line-length line))
+	       (format t "~%Oh, Man!  A mark is pointing into hyperspace!~%")
+	       (return (car m)))
+	     (unless (member (mark-%kind (car m))
+			   '(:left-inserting :right-inserting))
+	       (format t "~%Oh, Man!  A mark's type is bogus!.~%")
+	       (return (car m)))
+	     (unless (eq (mark-line (car m)) line)
+	       (format t "~%Oh, Man!  A mark's line pointer is messed up!~%")
+	       (return (car m))))))
+      (when res
+	(return (values line res))))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/kbdmac.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/kbdmac.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/kbdmac.lisp	(revision 13309)
@@ -0,0 +1,475 @@
+;;; -*- Log: hemlock.log; Package: Hemlock -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    This file contains the implementation of keyboard macros for
+;;; Hemlock.  In itself it contains nothing particularly gross or
+;;; implementation dependant, but it uses some hooks in the stream
+;;; system and other stuff.
+;;;
+
+(in-package :hemlock)
+
+;;; We have "Keyboard Macro Transforms" that help in making a keyboard
+;;; macro.  What they do is turn the sequence of commands into equivalent
+;;; lisp code.  They operate under the following principles:
+;;;
+;;;    They are passed two arguments:
+;;; 1] The command invoked.
+;;; 2] A keyword, either :invoke, :start or :finish
+;;;
+;;;    If the keyword is :invoke, then the transform is expected to
+;;; invoke the command and do whatever is necessary to make the same
+;;; thing happen again when the macro is invoked.  The method does this
+;;; by pushing forms on the list *current-kbdmac* and characters to
+;;; simulate input of on *kbdmac-input*.  *current-kbdmac* is kept
+;;; in reverse order.  Each form must be a function call, and none
+;;; of the arguments are evaluated.  If the transform is unwound, 
+;;; presumably due to an error in the invoked command, then nothing
+;;; should be done at invocation time.
+;;;
+;;;    If the keyword is :finish, then nothing need be done.  This
+;;; is to facilitate compaction of repetitions of the same command
+;;; into one call.  The transform is called with :finish when a run
+;;; is broken.  Similarly, the transform is called with :start
+;;; before the first occurrence in a run.
+
+(defvar *kbdmac-transcript* (make-array 100  :fill-pointer 0 :adjustable t)
+  "The thing we bind *input-transcript* to during keyboard macro definition.")
+
+(defvar *kbdmac-input* (make-array 100  :fill-pointer 0  :adjustable t)
+  "Place where we stick input that will need to be simulated during keyboard
+  macro execution.")
+
+(defvar *current-kbdmac* () "Body of keyboard macro we are building.")
+
+(defvar *kbdmac-transforms* (make-hash-table :test #'eq)
+  "Hashtable of function that know how to do things.")
+
+(defvar *old-invoke-hook* () "Bound to *invoke-hook* by kbdmac-command-loop.")
+
+(defmacro define-kbdmac-transform (command function)
+  `(setf (gethash (getstring ,command *command-names*)
+		  *kbdmac-transforms*)
+	 ,function))
+
+(defmacro kbdmac-emit (form)
+  `(push ,form *current-kbdmac*))
+
+
+(defun trash-character ()
+  "Throw away a character on *editor-input*."
+  (get-key-event hi::*editor-input*))
+
+;;; Save-Kbdmac-Input  --  Internal
+;;;
+;;;    Pushes any input read within the body on *kbdmac-input* so that
+;;; it is read again at macro invocation time.  It uses the (input-waiting)
+;;; function which is a non-standard hook into the stream system.
+;;;
+(defmacro save-kbdmac-input (&body forms)
+  (let ((slen (gensym)))
+    `(let ((,slen (- (length *kbdmac-transcript*) (if (input-waiting) 1 0))))
+       (multiple-value-prog1
+	(progn ,@forms)
+	(do ((i ,slen (1+ i))
+	     (elen (length *kbdmac-transcript*)))
+	    ((= i elen)
+	     (when (input-waiting)
+	       (kbdmac-emit '(trash-character))))	 
+	  (vector-push-extend (aref *kbdmac-transcript* i)
+			      *kbdmac-input*))))))
+
+;;;; The default transform
+;;;
+;;;    This transform is called when none is defined for a command.
+;;;
+(defun default-kbdmac-transform (command key)
+  (case key
+    (:invoke
+     (let ((fun (command-function command))
+	   (arg (prefix-argument))
+	   (lastc *last-key-event-typed*))
+       (save-kbdmac-input
+	 (let ((*invoke-hook* *old-invoke-hook*))
+	   (funcall fun arg))
+	 (kbdmac-emit `(set *last-key-event-typed* ,lastc))
+	 (kbdmac-emit `(,fun ,arg)))))))
+
+
+;;;; Self insert transform:
+;;;
+;;;    For self insert we accumulate the text in a string and then
+;;; insert it all at once.
+;;;
+
+(defvar *kbdmac-text* (make-array 100 :fill-pointer 0 :adjustable t))
+
+(defun insert-string-at-point (string)
+  (insert-string (buffer-point (current-buffer)) string))
+(defun insert-character-at-point (character)
+  (insert-character (buffer-point (current-buffer)) character))
+
+(defun key-vector-to-string (key-vector)
+  (let ((string (make-array (length key-vector) :element-type 'base-char)))
+    (dotimes (i (length key-vector) string)
+      (setf (aref string i) (hemlock-ext:key-event-char (aref key-vector i))))))
+
+(defun self-insert-kbdmac-transform (command key)
+  (case key
+    (:start
+     (setf (fill-pointer *kbdmac-text*) 0))
+    (:invoke
+     (let ((p (or (prefix-argument) 1)))
+       (funcall (command-function command) p)
+       (dotimes (i p)
+	 (vector-push-extend *last-key-event-typed* *kbdmac-text*))))
+    (:finish
+     (if (> (length *kbdmac-text*) 1)
+	 (kbdmac-emit `(insert-string-at-point
+			,(key-vector-to-string *kbdmac-text*)))
+	 (kbdmac-emit `(insert-character-at-point
+			,(hemlock-ext:key-event-char (aref *kbdmac-text* 0))))))))
+;;;
+(define-kbdmac-transform "Self Insert" #'self-insert-kbdmac-transform)
+(define-kbdmac-transform "Lisp Insert )" #'self-insert-kbdmac-transform)
+
+;;;; Do-Nothing transform:
+;;;
+;;;    These are useful for prefix-argument setting commands, since they have
+;;; no semantics at macro-time.
+;;;
+(defun do-nothing-kbdmac-transform (command key)
+  (case key
+    (:invoke
+     (funcall (command-function command) (prefix-argument)))))
+;;;
+(define-kbdmac-transform "Argument Digit" #'do-nothing-kbdmac-transform)
+(define-kbdmac-transform "Negative Argument" #'do-nothing-kbdmac-transform)
+(define-kbdmac-transform "Universal Argument" #'do-nothing-kbdmac-transform)
+
+
+;;;; Multiplicative transform
+;;;
+;;;    Repititions of many commands can be turned into a call with an
+;;; argument.
+;;;
+(defvar *kbdmac-count* 0
+  "The number of occurrences we have counted of a given command.")
+
+(defun multiplicative-kbdmac-transform (command key)
+  (case key
+    (:start
+     (setq *kbdmac-count* 0))
+    (:invoke
+     (let ((p (or (prefix-argument) 1)))
+       (funcall (command-function command) p)
+       (incf *kbdmac-count* p)))
+    (:finish
+     (kbdmac-emit `(,(command-function command) ,*kbdmac-count*)))))
+;;;
+(define-kbdmac-transform "Forward Character" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Backward Character" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Forward Word" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Backward Word" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Uppercase Word" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Lowercase Word" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Capitalize Word" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Kill Next Word" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Kill Previous Word" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Forward Kill Form" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Backward Kill Form" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Forward Form" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Backward Form" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Delete Next Character"
+  #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Delete Previous Character"
+   #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Delete Previous Character Expanding Tabs"
+   #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Next Line" #'multiplicative-kbdmac-transform)
+(define-kbdmac-transform "Previous Line" #'multiplicative-kbdmac-transform)
+
+
+;;;; Vanilla transform
+;;;
+;;;    These commands neither read input nor look at random silly variables.
+;;;
+(defun vanilla-kbdmac-transform (command key)
+  (case key
+    (:invoke
+     (let ((fun (command-function command))
+	   (p (prefix-argument)))
+       (funcall fun p)
+       (kbdmac-emit `(,fun ,p))))))
+;;;
+(define-kbdmac-transform "Beginning of Line" #'vanilla-kbdmac-transform)
+(define-kbdmac-transform "End of Line" #'vanilla-kbdmac-transform)
+(define-kbdmac-transform "Beginning of Line" #'vanilla-kbdmac-transform)
+(define-kbdmac-transform "Indent for Lisp" #'vanilla-kbdmac-transform)
+(define-kbdmac-transform "Delete Horizontal Space" #'vanilla-kbdmac-transform)
+(define-kbdmac-transform "Kill Line" #'vanilla-kbdmac-transform)
+(define-kbdmac-transform "Backward Kill Line" #'vanilla-kbdmac-transform)
+(define-kbdmac-transform "Un-Kill" #'vanilla-kbdmac-transform)
+
+
+;;;; MAKE-KBDMAC, INTERACTIVE, and kbdmac command loop.
+
+;;; Kbdmac-Command-Loop  --  Internal
+;;;
+;;;    Bind *invoke-hook* to call kbdmac transforms.
+;;;
+(defun kbdmac-command-loop ()
+  (let* ((last-transform nil)
+	 (last-command nil)
+	 (last-ctype nil)
+	 (*old-invoke-hook* *invoke-hook*)
+	 (*invoke-hook*
+	  #'(lambda (res p)
+	      (declare (ignore p))
+	      (when (and (not (eq last-command res)) last-transform)
+		(funcall last-transform last-command :finish))
+	      (if (last-command-type)
+		  (setq last-ctype t)
+		  (when last-ctype
+		    (kbdmac-emit '(clear-command-type))
+		    (setq last-ctype nil)))
+	      (setq last-transform 
+		    (gethash res *kbdmac-transforms* #'default-kbdmac-transform))
+	      (unless (eq last-command res)
+		(funcall last-transform res :start))
+	      (funcall last-transform res :invoke)
+	      (setq last-command res))))
+    (declare (special *invoke-hook*))
+    (setf (last-command-type) nil)
+    (recursive-edit nil)))
+
+(defun clear-command-type ()
+  (setf (last-command-type) nil))
+
+
+(defvar *defining-a-keyboard-macro* ())
+(defvar *kbdmac-stream* #+later (make-kbdmac-stream))
+(defvar *in-a-keyboard-macro* ()
+  "True if we are currently executing a keyboard macro.")
+
+;;; Interactive  --  Public
+;;;
+;;;    See whether we are in a keyboard macro.
+;;;
+(defun interactive ()
+  "Return true if we are in a command invoked by the user.
+  This is primarily useful for commands which want to know
+  whether do something when an error happens, or just signal
+  an Editor-Error."
+  (not *in-a-keyboard-macro*))
+
+(defvar *kbdmac-done* ()
+  "Setting this causes the keyboard macro being executed to terminate
+  after the current iteration.")
+
+(defvar *kbdmac-dont-ask* ()
+  "Setting this inhibits \"Keyboard Macro Query\"'s querying.")
+
+;;; Make-Kbdmac  --  Internal
+;;;
+;;;    This guy grabs the stuff lying around in *current-kbdmac* and
+;;; whatnot and makes a lexical closure that can be used as the
+;;; definition of a command.  The prefix argument is a repitition
+;;; count.
+;;;
+(defun make-kbdmac ()
+  (let ((code (nreverse *current-kbdmac*))
+	(input (copy-seq *kbdmac-input*)))
+    (if (zerop (length input))
+	#'(lambda (p)
+	    (let ((*in-a-keyboard-macro* t)
+		  (*kbdmac-done* nil)
+		  (*kbdmac-dont-ask* nil))
+	      (setf (last-command-type) nil)
+	      (catch 'exit-kbdmac
+		(dotimes (i (or p 1))
+		  (catch 'abort-kbdmac-iteration
+		    (dolist (form code)
+		      (apply (car form) (cdr form))))
+		  (when *kbdmac-done* (return nil))))))
+	#'(lambda (p)
+	    (let* ((stream (or *kbdmac-stream* (make-kbdmac-stream)))
+		   (*kbdmac-stream* nil)
+		   (hi::*editor-input* stream)
+		   (*in-a-keyboard-macro* t)
+		   (*kbdmac-done* nil)
+		   (*kbdmac-dont-ask* nil))
+	      (setf (last-command-type) nil)
+	      (catch 'exit-kbdmac
+		(dotimes (i (or p 1))
+		  (setq stream (modify-kbdmac-stream stream input))
+		  (catch 'abort-kbdmac-iteration
+		    (dolist (form code)
+		      (apply (car form) (cdr form))))
+		  (when *kbdmac-done* (return nil)))))))))
+	    	  
+
+
+
+;;;; Commands.
+
+(defmode "Def" :major-p nil)  
+
+(defcommand "Define Keyboard Macro" (p)
+  "Define a keyboard macro."
+  "Define a keyboard macro."
+  (declare (ignore p))
+  (when *defining-a-keyboard-macro*
+    (editor-error "Already defining a keyboard macro."))
+  (define-keyboard-macro))
+
+(defhvar "Define Keyboard Macro Key Confirm"
+  "When set, \"Define Keyboard Macro Key\" asks for confirmation before
+   clobbering an existing key binding."
+  :value t)
+
+(defcommand "Define Keyboard Macro Key" (p)
+  "Prompts for a key before going into a mode for defining keyboard macros.
+   The macro definition is bound to the key.  IF the key is already bound,
+   this asks for confirmation before clobbering the binding."
+  "Prompts for a key before going into a mode for defining keyboard macros.
+   The macro definition is bound to the key.  IF the key is already bound,
+   this asks for confirmation before clobbering the binding."
+  (declare (ignore p))
+  (when *defining-a-keyboard-macro*
+    (editor-error "Already defining a keyboard macro."))
+  (multiple-value-bind (key kind where)
+		       (get-keyboard-macro-key)
+    (when key
+      (setf (buffer-minor-mode (current-buffer) "Def") t)
+      (let ((name (format nil "Keyboard Macro ~S" (gensym))))
+	(make-command name "This is a user-defined keyboard macro."
+		      (define-keyboard-macro))
+	(bind-key name key kind where)
+	(message "~A bound to ~A."
+		 (with-output-to-string (s) (hemlock-ext:print-pretty-key key s))
+		 name)))))
+
+;;; GET-KEYBOARD-MACRO-KEY gets a key from the user and confirms clobbering it
+;;; if it is already bound to a command, or it is a :prefix.  This returns nil
+;;; if the user "aborts", otherwise it returns the key and location (kind
+;;; where) of the binding.
+;;;
+(defun get-keyboard-macro-key ()
+  (let* ((key (prompt-for-key :prompt "Bind keyboard macro to key: "
+			      :must-exist nil)))
+    (multiple-value-bind (kind where)
+			 (prompt-for-place "Kind of binding: "
+					   "The kind of binding to make.")
+      (let* ((cmd (get-command key kind where)))
+	(cond ((not cmd) (values key kind where))
+	      ((commandp cmd)
+	       (if (prompt-for-y-or-n
+		    :prompt `("~A is bound to ~A.  Rebind it? "
+			      ,(with-output-to-string (s)
+				 (hemlock-ext:print-pretty-key key s))
+			      ,(command-name cmd))
+		    :default nil)
+		   (values key kind where)
+		   nil))
+	      ((eq cmd :prefix)
+	       (if (prompt-for-y-or-n
+		    :prompt `("~A is a prefix for more than one command.  ~
+			       Clobber it? "
+			      ,(with-output-to-string (s)
+				 (hemlock-ext:print-pretty-key key s)))
+		    :default nil)
+		   (values key kind where)
+		   nil)))))))
+
+;;; DEFINE-KEYBOARD-MACRO gets input from the user and clobbers the function
+;;; for the "Last Keyboard Macro" command.  This returns the new function.
+;;;
+(defun define-keyboard-macro ()
+  (setf (buffer-minor-mode (current-buffer) "Def") t)
+  (unwind-protect
+    (let* ((in *kbdmac-transcript*)
+	   (*input-transcript* in)
+	   (*defining-a-keyboard-macro* t))
+      (setf (fill-pointer in) 0)
+      (setf (fill-pointer *kbdmac-input*) 0)
+      (setq *current-kbdmac* ())
+      (catch 'punt-kbdmac
+	(kbdmac-command-loop))
+      (setf (command-function (getstring "Last Keyboard Macro" *command-names*))
+	    (make-kbdmac)))
+    (setf (buffer-minor-mode (current-buffer) "Def") nil)))
+
+
+(defcommand "End Keyboard Macro" (p)
+  "End the definition of a keyboard macro."
+  "End the definition of a keyboard macro."
+  (declare (ignore p))
+  (unless *defining-a-keyboard-macro*
+    (editor-error "Not defining a keyboard macro."))
+  (throw 'punt-kbdmac ()))
+;;;
+(define-kbdmac-transform "End Keyboard Macro" #'do-nothing-kbdmac-transform)
+
+
+(defcommand "Last Keyboard Macro" (p)
+  "Execute the last keyboard macro defined.
+  With prefix argument execute it that many times."
+  "Execute the last keyboard macro P times."
+  (declare (ignore p))
+  (editor-error "No keyboard macro defined."))
+
+(defcommand "Name Keyboard Macro" (p &optional name)
+  "Name the \"Last Keyboard Macro\".
+  The last defined keboard macro is made into a named command."
+  "Make the \"Last Keyboard Macro\" a named command."
+  (declare (ignore p))
+  (unless name
+    (setq name (prompt-for-string
+		:prompt "Macro name: "
+		:help "String name of command to make from keyboard macro.")))
+  (make-command
+    name "This is a named keyboard macro."
+   (command-function (getstring "Last Keyboard Macro" *command-names*))))
+
+(defcommand "Keyboard Macro Query" (p)
+  "Keyboard macro conditional.
+  During the execution of a keyboard macro, this command prompts for
+  a single character command, similar to those of \"Query Replace\"."
+  "Prompt for action during keyboard macro execution."
+  (declare (ignore p))
+  (unless (or (interactive) *kbdmac-dont-ask*)
+    (let ((hi::*editor-input* *real-editor-input*))
+      (command-case (:prompt "Keyboard Macro Query: "
+		     :help "Type one of these characters to say what to do:"
+		     :change-window nil
+		     :bind key-event)
+	(:exit
+	 "Exit this keyboard macro immediately."
+	 (throw 'exit-kbdmac nil))
+	(:yes
+	 "Proceed with this iteration of the keyboard macro.")
+	(:no
+       "Don't do this iteration of the keyboard macro, but continue to the next."
+	 (throw 'abort-kbdmac-iteration nil))
+	(:do-all
+	 "Do all remaining repetitions of the keyboard macro without prompting."
+	 (setq *kbdmac-dont-ask* t))
+	(:do-once
+	 "Do this iteration of the keyboard macro and then exit."
+	 (setq *kbdmac-done* t))
+	(:recursive-edit
+	 "Do a recursive edit, then ask again."
+	 (do-recursive-edit)
+	 (reprompt))
+	(t
+	 (unget-key-event key-event hi::*editor-input*)
+	 (throw 'exit-kbdmac nil))))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/keytran.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/keytran.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/keytran.lisp	(revision 13309)
@@ -0,0 +1,185 @@
+;;; -*- Log: hemlock.log; Package: extensions -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file contains a default character translation mechanism for X11
+;;; scan codes, keysyms, button codes, and modifier bits.
+;;;
+;;; Written by Bill Chiles.
+;;;
+
+(in-package "EXTENSIONS")
+
+(export '(define-keysym define-mouse-code define-keyboard-modifier
+	  translate-character translate-mouse-character))
+
+
+
+
+;;;; Keysym to character translation.
+
+;;; Hemlock uses its own keysym to character translation since this is easier
+;;; and more versatile than the CLX design.  Also, using CLX's mechanism is no
+;;; more portable than writing our own translation based on the X11 protocol
+;;; keysym specification.
+;;;
+;;; In the first table, nil indicates a non-event which is pertinent to
+;;; ignoring modifier keys being pressed prior to pressing a key to be
+;;; modified.  In the second table, nil simply indicates that there is no
+;;; special shift translation for the keysym, and that the CLX shifted keysym
+;;; should be looked up as normal (see TRANSLATE-CHARACTER).
+;;;
+;;; This mapping is initialized with DEFINE-KEYSYM in Keytrandefs.Lisp
+;;;
+(defvar *keysym-translations* (make-hash-table))
+(defvar *shifted-keysym-translations* (make-hash-table))
+
+(defun define-keysym (keysym char &optional shifted-char)
+  "Defines a keysym for Hemlock's translation.  If shifted-char is supplied,
+   it is a character to use when the :shift modifier is on for an incoming
+   keysym.  If shifted-char is not supplied, and the :shift modifier is set,
+   then XLIB:KEYCODE->KEYSYM is called with an index of 1 instead of 0.  If
+   a :lock modifier is set, it is treated as a caps-lock.  See
+   DEFINE-KEYBOARD-MODIFIER."
+  (check-type char character)
+  (setf (gethash keysym *keysym-translations*) char)
+  (when shifted-char
+    (check-type shifted-char character)
+    (setf (gethash keysym *shifted-keysym-translations*) shifted-char))
+  t)
+
+
+;;; X modifier bits translation
+;;;
+(defvar *modifier-translations* ())
+
+(defun define-keyboard-modifier (clx-mask modifier-name)
+  "Causes clx-mask to be interpreted as modifier-name which must be one of
+   :control, :meta, :super, :hyper, :shift, or :lock."
+  (let ((map (assoc clx-mask *modifier-translations*)))
+    (if map
+	(rplacd map modifier-name)
+	(push (cons clx-mask modifier-name) *modifier-translations*))))
+
+(define-keyboard-modifier (xlib:make-state-mask :control) :control)
+(define-keyboard-modifier (xlib:make-state-mask :mod-1) :meta)
+(define-keyboard-modifier (xlib:make-state-mask :shift) :shift)
+(define-keyboard-modifier (xlib:make-state-mask :lock) :lock)
+
+
+(defun translate-character (display scan-code bits)
+  "Translates scan-code and modifier bits to a Lisp character.  The scan code
+   is first mapped to a keysym with index 0 for unshifted and index 1 for
+   shifted.  If this keysym does not map to a character, and it is not a
+   modifier key (shift, ctrl, etc.), then an error is signaled.  If the keysym
+   is a modifier key, then nil is returned.  If we do have a character, and the
+   shift bit is off, and the lock bit is on, and the character is alphabetic,
+   then we get a new keysym with index 1, mapping it to a character.  If this
+   does not result in a character, an error is signaled.  If we have a
+   character, and the shift bit is on, then we look for a special shift mapping
+   for the original keysym.  This allows for distinct characters for scan
+   codes that map to the same keysym, shifted or unshifted, (e.g., number pad
+   or arrow keys)."
+  (let ((dummy #\?)
+	shiftp lockp)
+    (dolist (ele *modifier-translations*)
+      (unless (zerop (logand (car ele) bits))
+	(case (cdr ele)
+	  (:shift (setf shiftp t))
+	  (:lock (setf lockp t))
+	  (t (setf dummy (set-char-bit dummy (cdr ele) t))))))
+    (let* ((keysym (xlib:keycode->keysym display scan-code (if shiftp 1 0)))
+	   (temp-char (gethash keysym *keysym-translations*)))
+      (cond ((not temp-char)
+	     (if (<= 65505 keysym 65518) ;modifier keys.
+		 nil
+		 (error "Undefined keysym ~S, describe EXT:DEFINE-KEYSYM."
+			keysym)))
+	    ((and (not shiftp) lockp (alpha-char-p temp-char))
+	     (let* ((keysym (xlib:keycode->keysym display scan-code 1))
+		    (char (gethash keysym *keysym-translations*)))
+	       (unless char
+		 (error "Undefined keysym ~S, describe EXT:DEFINE-KEYSYM."
+			keysym))
+	       (make-char char (logior (char-bits char) (char-bits dummy)))))
+	    (shiftp
+	     (let ((char (gethash keysym *shifted-keysym-translations*)))
+	       (if char
+		   (make-char char (logior (char-bits char) (char-bits dummy)))
+		   (make-char temp-char (logior (char-bits temp-char)
+						(char-bits dummy))))))
+	    (t (make-char temp-char (logior (char-bits temp-char)
+					    (char-bits dummy))))))))
+		   
+		   
+
+
+;;;; Mouse to character translations.
+		   
+;;; Mouse codes come from the server numbered one through five.  This table is
+;;; indexed by the code to retrieve a list.  The CAR is a cons of the char and
+;;; shifted char associated with a :button-press event.  The CDR is a cons of
+;;; the char and shifted char associated with a :button-release event.  Each
+;;; of these is potentially nil (not a cons at all).
+;;;
+(defvar *mouse-translations* (make-array 6 :initial-element nil))
+;;;
+(defmacro mouse-press-chars (ele) `(car ,ele))
+(defmacro mouse-release-chars (ele) `(cadr ,ele))
+
+(defun define-mouse-code (button char shifted-char event-key)
+  "Causes X button code to be interpreted as char.  Shift and Lock modifiers
+   associated with button map to shifted-char.  For the same button code,
+   event-key may be :button-press or :button-release."
+  (check-type char character)
+  (check-type shifted-char character)
+  (check-type event-key (member :button-press :button-release))
+  (let ((stuff (svref *mouse-translations* button))
+	(trans (cons char shifted-char)))
+    (if stuff
+	(case event-key
+	  (:button-press (setf (mouse-press-chars stuff) trans))
+	  (:button-release (setf (mouse-release-chars stuff) trans)))
+	(case event-key
+	  (:button-press
+	   (setf (svref *mouse-translations* button) (list trans nil)))
+	  (:button-release
+	   (setf (svref *mouse-translations* button) (list nil trans))))))
+  t)
+
+(define-mouse-code 1 #\leftdown #\super-leftdown :button-press)
+(define-mouse-code 1 #\leftup #\super-leftup :button-release)
+
+(define-mouse-code 2 #\middledown #\super-middledown :button-press)
+(define-mouse-code 2 #\middleup #\super-middleup :button-release)
+
+(define-mouse-code 3 #\rightdown #\super-rightdown :button-press)
+(define-mouse-code 3 #\rightup #\super-rightup :button-release)
+
+(defun translate-mouse-character (scan-code bits event-key)
+  "Translates X button code, scan-code, and modifier bits, bits, for event-key
+   (either :button-press or :button-release) to a Lisp character."
+  (let ((temp (svref *mouse-translations* scan-code)))
+    (unless temp (error "Unknown mouse button -- ~S." scan-code))
+    (let ((trans (ecase event-key
+		   (:button-press (mouse-press-chars temp))
+		   (:button-release (mouse-release-chars temp)))))
+      (unless trans (error "Undefined ~S characters for mouse button ~S."
+			   event-key scan-code))
+      (let ((dummy #\?)
+	    shiftp)
+	(dolist (ele *modifier-translations*)
+	  (unless (zerop (logand (car ele) bits))
+	    (let ((bit (cdr ele)))
+	      (if (or (eq bit :shift) (eq bit :lock))
+		  (setf shiftp t)
+		  (setf dummy (set-char-bit dummy bit t))))))
+	(let ((char (if shiftp (cdr trans) (car trans))))
+	  (make-char char (logior (char-bits char) (char-bits dummy))))))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/keytrandefs.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/keytrandefs.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/keytrandefs.lisp	(revision 13309)
@@ -0,0 +1,184 @@
+;;; -*- Log: hemlock.log; Mode: Lisp; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; This file initializes character translation that would otherwise be done
+;;; in Rompsite.Slisp, but there are no good hacks for mapping X11 keysyms
+;;; to CMU Common Lisp character codes.
+;;;
+;;; Written by Bill Chiles.
+;;; 
+
+;;; The IBM RT keyboard has X11 keysyms defined for the following modifier
+;;; keys, but we leave them mapped to nil indicating that they are non-events
+;;; to be ignored:
+;;;    ctrl		65507
+;;;    meta (left)	65513
+;;;    meta (right)	65514
+;;;    shift (left)	65505
+;;;    shift (right)	65506
+;;;    lock		65509
+
+(in-package "HEMLOCK-INTERNALS")
+
+
+;;; Function keys for the RT.
+;;;
+(define-keysym 65470 #\f1 #\s-f1)
+(define-keysym 65471 #\f2 #\s-f2)
+(define-keysym 65472 #\f3 #\s-f3)
+(define-keysym 65473 #\f4 #\s-f4)
+(define-keysym 65474 #\f5 #\s-f5)
+(define-keysym 65475 #\f6 #\s-f6)
+(define-keysym 65476 #\f7 #\s-f7)
+(define-keysym 65477 #\f8 #\s-f8)
+(define-keysym 65478 #\f9 #\s-f9)
+(define-keysym 65479 #\f10 #\s-f10)
+(define-keysym 65480 #\f11 #\s-f11)
+(define-keysym 65481 #\f12 #\s-f12)
+
+;;; Function keys for the Sun (and other keyboards) -- L1-L10 and R1-R15.
+;;;
+(define-keysym 65482 #\f13 #\s-f13)
+(define-keysym 65483 #\f14 #\s-f14)
+(define-keysym 65484 #\f15 #\s-f15)
+(define-keysym 65485 #\f16 #\s-f16)
+(define-keysym 65486 #\f17 #\s-f17)
+(define-keysym 65487 #\f18 #\s-f18)
+(define-keysym 65488 #\f19 #\s-f19)
+(define-keysym 65489 #\f20 #\s-f20)
+(define-keysym 65490 #\f21 #\s-f21)
+(define-keysym 65491 #\f22 #\s-f22)
+(define-keysym 65492 #\f23 #\s-f23)
+(define-keysym 65493 #\f24 #\s-f24)
+(define-keysym 65494 #\f25 #\s-f25)
+(define-keysym 65495 #\f26 #\s-f26)
+(define-keysym 65496 #\f27 #\s-f27)
+(define-keysym 65497 #\f28 #\s-f28)
+(define-keysym 65498 #\f29 #\s-f29)
+(define-keysym 65499 #\f30 #\s-f30)
+(define-keysym 65500 #\f31 #\s-f31)
+(define-keysym 65501 #\f32 #\s-f32)
+(define-keysym 65502 #\f33 #\s-f33)
+(define-keysym 65503 #\f34 #\s-f34)
+(define-keysym 65504 #\f35 #\s-f35)
+
+;;; Upper right key bank.
+;;;
+(define-keysym 65377 #\printscreen #\s-printscreen)
+;; Couldn't type scroll lock.
+(define-keysym 65299 #\pause #\s-pause)
+
+;;; Middle right key bank.
+;;;
+(define-keysym 65379 #\insert #\s-insert)
+(define-keysym 65535 #\delete #\delete)
+(define-keysym 65360 #\home #\s-home)
+(define-keysym 65365 #\pageup #\s-pageup)
+(define-keysym 65367 #\end #\s-end)
+(define-keysym 65366 #\pagedown #\s-pagedown)
+
+;;; Arrows.
+;;;
+(define-keysym 65361 #\leftarrow #\s-leftarrow)
+(define-keysym 65362 #\uparrow #\s-uparrow)
+(define-keysym 65364 #\downarrow #\s-downarrow)
+(define-keysym 65363 #\rightarrow #\s-rightarrow)
+
+;;; Number pad.
+;;;
+(define-keysym 65407 #\numlock #\s-numlock)
+(define-keysym 65421 #\s-return #\s-return)			;num-pad-enter
+(define-keysym 65455 #\s-/ #\s-/)				;num-pad-/
+(define-keysym 65450 #\s-* #\s-*)				;num-pad-*
+(define-keysym 65453 #\s-- #\s--)				;num-pad--
+(define-keysym 65451 #\s-+ #\s-+)				;num-pad-+
+(define-keysym 65456 #\s-0 #\s-0)				;num-pad-0
+(define-keysym 65457 #\s-1 #\s-1)				;num-pad-1
+(define-keysym 65458 #\s-2 #\s-2)				;num-pad-2
+(define-keysym 65459 #\s-3 #\s-3)				;num-pad-3
+(define-keysym 65460 #\s-4 #\s-4)				;num-pad-4
+(define-keysym 65461 #\s-5 #\s-5)				;num-pad-5
+(define-keysym 65462 #\s-6 #\s-6)				;num-pad-6
+(define-keysym 65463 #\s-7 #\s-7)				;num-pad-7
+(define-keysym 65464 #\s-8 #\s-8)				;num-pad-8
+(define-keysym 65465 #\s-9 #\s-9)				;num-pad-9
+(define-keysym 65454 #\s-. #\s-.)				;num-pad-.
+
+;;; "Named" keys.
+;;;
+(define-keysym 65289 #\tab #\tab)
+(define-keysym 65307 #\escape #\escape)				;esc
+(define-keysym 65288 #\backspace #\backspace)
+(define-keysym 65293 #\return #\return)				;enter
+(define-keysym 65512 #\linefeed #\linefeed)			;action
+(define-keysym 32 #\space #\space)
+
+;;; Letters.
+;;;
+(define-keysym 97 #\a) (define-keysym 65 #\A)
+(define-keysym 98 #\b) (define-keysym 66 #\B)
+(define-keysym 99 #\c) (define-keysym 67 #\C)
+(define-keysym 100 #\d) (define-keysym 68 #\D)
+(define-keysym 101 #\e) (define-keysym 69 #\E)
+(define-keysym 102 #\f) (define-keysym 70 #\F)
+(define-keysym 103 #\g) (define-keysym 71 #\G)
+(define-keysym 104 #\h) (define-keysym 72 #\H)
+(define-keysym 105 #\i) (define-keysym 73 #\I)
+(define-keysym 106 #\j) (define-keysym 74 #\J)
+(define-keysym 107 #\k) (define-keysym 75 #\K)
+(define-keysym 108 #\l) (define-keysym 76 #\L)
+(define-keysym 109 #\m) (define-keysym 77 #\M)
+(define-keysym 110 #\n) (define-keysym 78 #\N)
+(define-keysym 111 #\o) (define-keysym 79 #\O)
+(define-keysym 112 #\p) (define-keysym 80 #\P)
+(define-keysym 113 #\q) (define-keysym 81 #\Q)
+(define-keysym 114 #\r) (define-keysym 82 #\R)
+(define-keysym 115 #\s) (define-keysym 83 #\S)
+(define-keysym 116 #\t) (define-keysym 84 #\T)
+(define-keysym 117 #\u) (define-keysym 85 #\U)
+(define-keysym 118 #\v) (define-keysym 86 #\V)
+(define-keysym 119 #\w) (define-keysym 87 #\W)
+(define-keysym 120 #\x) (define-keysym 88 #\X)
+(define-keysym 121 #\y) (define-keysym 89 #\Y)
+(define-keysym 122 #\z) (define-keysym 90 #\Z)
+
+;;; Standard number keys.
+;;;
+(define-keysym 49 #\1) (define-keysym 33 #\!)
+(define-keysym 50 #\2) (define-keysym 64 #\@)
+(define-keysym 51 #\3) (define-keysym 35 #\#)
+(define-keysym 52 #\4) (define-keysym 36 #\$)
+(define-keysym 53 #\5) (define-keysym 37 #\%)
+(define-keysym 54 #\6) (define-keysym 94 #\^)
+(define-keysym 55 #\7) (define-keysym 38 #\&)
+(define-keysym 56 #\8) (define-keysym 42 #\*)
+(define-keysym 57 #\9) (define-keysym 40 #\()
+(define-keysym 48 #\0) (define-keysym 41 #\))
+
+;;; "Standard" symbol keys.
+;;;
+(define-keysym 96 #\`) (define-keysym 126 #\~)
+(define-keysym 45 #\-) (define-keysym 95 #\_)
+(define-keysym 61 #\=) (define-keysym 43 #\+)
+(define-keysym 91 #\[) (define-keysym 123 #\{)
+(define-keysym 93 #\]) (define-keysym 125 #\})
+(define-keysym 92 #\\) (define-keysym 124 #\|)
+(define-keysym 59 #\;) (define-keysym 58 #\:)
+(define-keysym 39 #\') (define-keysym 34 #\")
+(define-keysym 44 #\,) (define-keysym 60 #\<)
+(define-keysym 46 #\.) (define-keysym 62 #\>)
+(define-keysym 47 #\/) (define-keysym 63 #\?)
+
+
+;;; Sun keyboard.
+;;;
+(define-keysym 65387 #\break #\s-break)				;alternate (Sun).
+(define-keysym 65290 #\linefeed #\s-linefeed)
Index: /branches/new-random/cocoa-ide/hemlock/unused/linimage.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/linimage.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/linimage.lisp	(revision 13309)
@@ -0,0 +1,478 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Rob MacLachlan
+;;;
+;;; This file contains functions related to building line images.
+;;;
+(in-package :hemlock-internals)
+
+;;;    The code in here is factored out in this way because it is more
+;;; or less implementation dependant.  The reason this code is 
+;;; implementation dependant is not because it is not written in 
+;;; Common Lisp per se, but because it uses this thing called 
+;;; %SP-Find-Character-With-Attribute to find any characters that
+;;; are to be displayed on the line which do not print as themselves.
+;;; This permits us to have an arbitrary string or even string-valued
+;;; function to as the representation for such a "Funny" character
+;;; with minimal penalty for the normal case.  This function can be written 
+;;; in lisp, and is included commented-out below, but if this function
+;;; is not real fast then redisplay performance will suffer.
+;;;
+;;;    Theres also code in here that special-cases "Buffered" lines,
+;;; which is not exactly Common Lisp, but if you aren't on a perq,
+;;; you won't have to worry about it.
+;;;
+;(defun %sp-find-character-with-attribute (string start end table mask)
+;  (declare (type (simple-array (mod 256) char-code-max) table))
+;  (declare (simple-string string))
+;  (declare (fixnum start end))
+;  "%SP-Find-Character-With-Attribute  String, Start, End, Table, Mask
+;  The codes of the characters of String from Start to End are used as indices
+;  into the Table, which is a U-Vector of 8-bit bytes. When the number picked
+;  up from the table bitwise ANDed with Mask is non-zero, the current
+;  index into the String is returned. The corresponds to SCANC on the Vax."
+;  (do ((index start (1+ index)))
+;      ((= index end) nil)
+;    (declare (fixnum index))
+;    (if (/= (logand (aref table (char-code (elt string index))) mask) 0)
+;	(return index))))
+;
+;(defun %sp-reverse-find-character-with-attribute (string start end table
+;							  mask)
+;  (declare (type (simple-array (mod 256) char-code-max) table))
+;  (declare (simple-string string))
+;  (declare (fixnum start end))
+;  "Like %SP-Find-Character-With-Attribute, only sdrawkcaB."
+;  (do ((index (1- end) (1- index)))
+;      ((< index start) nil)
+;    (declare (fixnum index))
+;    (if (/= (logand (aref table (char-code (elt string index))) mask) 0)
+;	(return index))))
+
+
+(defconstant winning-char #b01 "Bit for a char that prints normally")
+(defconstant losing-char #b10 "Bit for char with funny representation.")
+(defvar *losing-character-mask*
+  (make-array char-code-limit :element-type '(mod 256)
+	      :initial-element winning-char)
+  "This is a character set used by redisplay to find funny chars.")
+(defvar *print-representation-vector* nil
+  "Redisplay's handle on the :print-representation attribute")
+
+;;;  Do a find-character-with-attribute on the *losing-character-mask*.
+(defmacro %fcwa (str start end mask)
+  `(%sp-find-character-with-attribute
+    ,str ,start ,end *losing-character-mask* ,mask))
+
+;;; Get the print-representation of a character.
+(defmacro get-rep (ch)
+  `(svref *print-representation-vector* (char-code ,ch)))
+
+
+
+
+(declaim (special *character-attributes*))
+
+;;; %init-line-image  --  Internal
+;;;
+;;;    Set up the print-representations for funny chars.  We make the
+;;; attribute vector by hand and do funny stuff so that chars > 127
+;;; will have a losing print-representation, so redisplay will not
+;;; die if you visit a binary file or do something stupid like that.
+;;;
+(defun %init-line-image ()
+  (defattribute "Print Representation"
+    "The value of this attribute determines how a character is displayed
+    on the screen.  If the value is a string this string is literally
+    displayed.  If it is a function, then that function is called with
+    the current X position to get the string to display.")
+  (setq *print-representation-vector*
+	(make-array char-code-limit :initial-element nil))
+  (setf (attribute-descriptor-vector
+	 (gethash :print-representation *character-attributes*))
+	*print-representation-vector*)
+  (do ((code 128 (1+ code))
+       (str (make-string 4) (make-string 4)))
+      ((= code char-code-limit))
+    (setf (aref *losing-character-mask* code) losing-char)
+    (setf (aref *print-representation-vector* code) str)
+    (setf (schar str 0) #\<)
+    (setf (schar str 1) (char-upcase (digit-char (ash code -4) 16)))
+    (setf (schar str 2) (char-upcase (digit-char (logand code #x+F) 16)))
+    (setf (schar str 3) #\>))
+
+  (add-hook hemlock::character-attribute-hook
+	    #'redis-set-char-attribute-hook-fun)
+  (do ((i (1- (char-code #\space)) (1- i)) str)
+      ((minusp i))
+    (setq str (make-string 2))
+    (setf (elt (the simple-string str) 0) #\^)
+    (setf (elt (the simple-string str) 1)
+	  (code-char (+ i (char-code #\@))))
+    (setf (character-attribute :print-representation (code-char i)) str))
+  (setf (character-attribute :print-representation (code-char #o177)) "^?")
+  (setf (character-attribute :print-representation #\tab)
+	#'redis-tab-display-fun))
+
+
+;;; redis-set-char-attribute-hook-fun
+;;;
+;;;    Keep track of which characters have funny representations.
+;;;
+(defun redis-set-char-attribute-hook-fun (attribute char new-value)
+  (when (eq attribute :print-representation)
+    (cond
+     ((simple-string-p new-value)
+      (if (and (= (length (the simple-string new-value)) 1)
+	       (char= char (elt (the simple-string new-value) 0)))
+	  (setf (aref *losing-character-mask* (char-code char)) winning-char)
+	  (setf (aref *losing-character-mask* (char-code char))
+		losing-char)))
+     ((functionp new-value)
+      (setf (aref *losing-character-mask* (char-code char)) losing-char))
+     (t (error "Bad print representation: ~S" new-value)))))
+
+;;; redis-tab-display-fun
+;;;
+;;;    This function is initially the :print-representation for tab.
+;;;
+(defun redis-tab-display-fun (xpos)
+  (svref '#("        "
+	    "       "
+	    "      "
+	    "     "
+	    "    "
+	    "   "
+	    "  "
+	    " ")
+	 (logand xpos 7)))
+
+
+
+;;;; The actual line image computing functions.
+;;;;
+
+(eval-when (:compile-toplevel :execute)
+;;; display-some-chars  --  internal
+;;;
+;;;    Put some characters into a window.  Characters from src-start 
+;;; to src-end in src are are put in the window's dis-line's.  Lines
+;;; are wrapped as necessary.  dst is the dis-line-chars of the dis-line 
+;;; currently being written.  Dis-lines is the window's vector of dis-lines.
+;;; dis-line is the dis-line currently being written.  Line is the index
+;;; into dis-lines of the current dis-line.  dst-start is the index to
+;;; start writing chars at.  Height and width are the height and width of the 
+;;; window.  src-start, dst, dst-start, line and dis-line are updated.
+;;; Done-P indicates whether there are more characters after this sequence.
+;;;
+(defmacro display-some-chars (src src-start src-end dst dst-start width done-p)
+  `(let ((dst-end (+ ,dst-start (- ,src-end ,src-start))))
+     (declare (fixnum dst-end))
+     (cond
+      ((>= dst-end ,width)
+       (cond 
+	((and ,done-p (= dst-end ,width))
+	 (%sp-byte-blt ,src ,src-start ,dst ,dst-start dst-end)
+	 (setq ,dst-start dst-end  ,src-start ,src-end))
+	(t
+	 (let ((1-width (1- ,width)))
+	   (%sp-byte-blt ,src ,src-start ,dst ,dst-start 1-width)
+	   (setf (elt (the simple-string ,dst) 1-width) *line-wrap-char*)
+	   (setq ,src-start (+ ,src-start (- 1-width ,dst-start)))
+	   (setq ,dst-start nil)))))
+      (t (%sp-byte-blt ,src ,src-start ,dst ,dst-start dst-end)
+	 (setq ,dst-start dst-end  ,src-start ,src-end)))))
+
+;;; These macros are given as args to display-losing-chars to get the
+;;; print representation of whatever is in the data vector.
+(defmacro string-get-rep (string index)
+  `(get-rep (schar ,string ,index)))
+
+(defmacro u-vec-get-rep (u-vec index)
+  `(svref *print-representation-vector*
+	  (hemlock-ext:sap-ref-8 ,u-vec ,index)))
+
+;;; display-losing-chars  --  Internal
+;;;
+;;;    This macro is called by the compute-line-image functions to
+;;; display a group of losing characters.
+;;;
+(defmacro display-losing-chars (line-chars index end dest xpos width
+					   string underhang access-fun
+					   &optional (done-p `(= ,index ,end)))
+  `(do ((last (or (%fcwa ,line-chars ,index ,end winning-char) ,end))
+	(len 0)
+	(zero 0)
+	str)
+       (())
+     (declare (fixnum last len zero))
+     (setq str (,access-fun ,line-chars ,index))
+     (unless (simple-string-p str) (setq str (funcall str ,xpos)))
+     (setq len (strlen str)  zero 0)
+     (incf ,index)
+     (display-some-chars str zero len ,dest ,xpos ,width ,done-p)
+     (cond ((not ,xpos)
+	    ;; We wrapped in the middle of a losing char.	       
+	    (setq ,underhang zero  ,string str)
+	    (return nil))
+	   ((= ,index last)
+	    ;; No more losing chars in this bunch.
+	    (return nil)))))
+
+(defmacro update-and-punt (dis-line length string underhang end)
+  `(progn (setf (dis-line-length ,dis-line) ,length)
+	  (return (values ,string ,underhang
+			  (setf (dis-line-end ,dis-line) ,end)))))
+
+); eval-when
+
+
+;;; compute-normal-line-image  --  Internal
+;;;
+;;;    Compute the screen representation of Line starting at Start 
+;;; putting it in Dis-Line beginning at Xpos.  Width is the width of the 
+;;; window we are displaying in.  If the line will wrap then we display 
+;;; as many chars as we can then put in *line-wrap-char*.  The values 
+;;; returned are described in Compute-Line-Image, which tail-recursively 
+;;; returns them.  The length slot in Dis-Line is updated.
+;;;
+;;; We use the *losing-character-mask* to break the line to be displayed
+;;; up into chunks of characters with normal print representation and
+;;; those with funny representations.
+;;;
+(defun compute-normal-line-image (line start dis-line xpos width)
+  (declare (fixnum start width) (type (or fixnum null) xpos))
+  (do* ((index start)
+	(line-chars (line-%chars line))
+	(end (strlen line-chars))
+	(dest (dis-line-chars dis-line))
+	(losing 0)
+	underhang string)
+       (())
+    (declare (fixnum index end)
+	     (type (or fixnum null) losing)
+	     (simple-string line-chars dest))
+    (cond
+     (underhang
+      (update-and-punt dis-line width string underhang index))
+     ((null xpos)
+      (update-and-punt dis-line width nil 0 index))
+     ((= index end)
+      (update-and-punt dis-line xpos nil nil index)))
+    (setq losing (%fcwa line-chars index end losing-char))
+    (when (null losing)
+      (display-some-chars line-chars index end dest xpos width t)
+      (if (or xpos (= index end))
+	  (update-and-punt dis-line xpos nil nil index)
+	  (update-and-punt dis-line width nil 0 index)))
+    (display-some-chars line-chars index losing dest xpos width nil)
+    (cond
+     ;; Did we wrap?
+     ((null xpos)
+      (update-and-punt dis-line width nil 0 index))
+     ;; Are we about to cause the line to wrap? If so, wrap before
+     ;; it's too late.
+     ((= xpos width)
+      (setf (char dest (1- width)) *line-wrap-char*)
+      (update-and-punt dis-line width nil 0 index))
+     (t
+      (display-losing-chars line-chars index end dest xpos width string
+			    underhang string-get-rep)))))
+
+
+
+;;; compute-cached-line-image  --  Internal
+;;;
+;;;    Like compute-normal-line-image, only works on the cached line.
+;;;
+(defun compute-cached-line-image (index dis-line xpos width)
+  (declare (fixnum index width) (type (or fixnum null) xpos))
+  (prog ((gap (- (current-right-open-pos) (current-left-open-pos)))
+	 (dest (dis-line-chars dis-line))
+	 (done-p (= (current-right-open-pos) (current-line-cache-length)))
+	 (losing 0)
+	 string underhang)
+    (declare (fixnum gap) (simple-string dest)
+	     (type (or fixnum null) losing))
+   LEFT-LOOP
+    (cond
+     (underhang
+      (update-and-punt dis-line width string underhang index))
+     ((null xpos)
+      (update-and-punt dis-line width nil 0 index))
+     ((>= index (current-left-open-pos))
+      (go RIGHT-START)))
+    (setq losing (%fcwa (current-open-chars) index (current-left-open-pos) losing-char))
+    (cond
+     (losing
+      (display-some-chars (current-open-chars) index losing dest xpos width nil)
+      ;; If we we didn't wrap then display some losers...
+      (if xpos
+	  (display-losing-chars (current-open-chars) index (current-left-open-pos) dest xpos
+				width string underhang string-get-rep
+				(and done-p (= index (current-left-open-pos))))
+	  (update-and-punt dis-line width nil 0 index)))
+     (t
+      (display-some-chars (current-open-chars) index (current-left-open-pos) dest xpos width done-p)))
+    (go LEFT-LOOP)
+
+   RIGHT-START
+    (setq index (+ index gap))
+   RIGHT-LOOP
+    (cond
+     (underhang
+      (update-and-punt dis-line width string underhang (- index gap)))
+     ((null xpos)
+      (update-and-punt dis-line width nil 0 (- index gap)))
+     ((= index (current-line-cache-length))
+      (update-and-punt dis-line xpos nil nil (- index gap))))
+    (setq losing (%fcwa (current-open-chars) index (current-line-cache-length) losing-char))
+    (cond
+     (losing
+      (display-some-chars (current-open-chars) index losing dest xpos width nil)
+      (cond
+       ;; Did we wrap?
+       ((null xpos)
+	(update-and-punt dis-line width nil 0 (- index gap)))
+       (t
+	(display-losing-chars (current-open-chars) index (current-line-cache-length) dest xpos
+			      width string underhang string-get-rep))))
+     (t
+      (display-some-chars (current-open-chars) index (current-line-cache-length) dest xpos width t)))
+    (go RIGHT-LOOP))) 
+
+
+(defun make-some-font-changes ()
+  (do ((res nil (make-font-change res))
+       (i 42 (1- i)))
+      ((zerop i) res)))
+
+(defvar *free-font-changes* (make-some-font-changes)
+  "Font-Change structures that nobody's using at the moment.")
+
+(defmacro alloc-font-change (x font mark)
+  `(progn
+    (unless *free-font-changes*
+      (setq *free-font-changes* (make-some-font-changes)))
+    (let ((new-fc *free-font-changes*))
+      (setq *free-font-changes* (font-change-next new-fc))
+      (setf (font-change-x new-fc) ,x
+	    (font-change-font new-fc) ,font
+	    (font-change-next new-fc) nil
+	    (font-change-mark new-fc) ,mark)
+      new-fc)))
+		     
+;;;
+;;; compute-line-image  --  Internal
+;;;
+;;;    This function builds a full line image from some characters in
+;;; a line and from some characters which may be left over from the previous
+;;; line.
+;;;
+;;; Parameters:
+;;;    String - This is the string which contains the characters left over
+;;; from the previous line.  This is NIL if there are none.
+;;;    Underhang - Characters from here to the end of String are put at the
+;;; beginning of the line image.
+;;;    Line - This is the line to display characters from.
+;;;    Offset - This is the index of the first character to display in Line.
+;;;    Dis-Line - This is the dis-line to put the line-image in.  The only
+;;; slots affected are the chars and the length.
+;;;    Width - This is the width of the field to display in.
+;;;
+;;; Three values are returned:
+;;;    1) The new overhang string, if none this is NIL.
+;;;    2) The new underhang, if this is NIL then the entire line was
+;;; displayed.  If the entire line was not displayed, but there was no
+;;; underhang, then this is 0.
+;;;    3) The index in line after the last character displayed.
+;;;
+(defun compute-line-image (string underhang line offset dis-line width)
+  ;;
+  ;; Release any old font-changes.
+  (let ((changes (dis-line-font-changes dis-line)))
+    (when changes
+      (do ((prev changes current)
+	   (current (font-change-next changes)
+		    (font-change-next current)))
+	  ((null current)
+	   (setf (dis-line-font-changes dis-line) nil)
+	   (shiftf (font-change-next prev) *free-font-changes* changes))
+	(setf (font-change-mark current) nil))))
+  ;;
+  ;; If the line has any Font-Marks, add Font-Changes for them.
+  (let ((marks (line-marks line)))
+    (when (dolist (m marks nil)
+	    (when (fast-font-mark-p m) (return t)))
+      (let ((prev nil))
+	;;
+	;; Find the last Font-Mark with charpos less than Offset.  If there is
+	;; such a Font-Mark, then there is a font-change to this font at X = 0.
+	(let ((max -1)
+	      (max-mark nil))
+	  (dolist (m marks)
+	    (when (fast-font-mark-p m)
+	      (let ((charpos (mark-charpos m)))
+		(when (and (< charpos offset) (> charpos max))
+		  (setq max charpos  max-mark m)))))
+	  (when max-mark
+	    (setq prev (alloc-font-change 0 (font-mark-font max-mark) max-mark))
+	    (setf (dis-line-font-changes dis-line) prev)))
+	;;
+	;; Repeatedly scan through marks, adding a font-change for the
+	;; smallest Font-Mark with a charpos greater than Bound, until
+	;; we find no such mark.
+	(do ((bound (1- offset) min)
+	     (min most-positive-fixnum most-positive-fixnum)
+	     (min-mark nil nil))
+	    (())
+	  (dolist (m marks)
+	    (when (fast-font-mark-p m)
+	      (let ((charpos (mark-charpos m)))
+		(when (and (> charpos bound) (< charpos min))
+		  (setq min charpos  min-mark m)))))
+	  (unless min-mark (return nil))
+	  (let ((len (if (current-open-line-p line)
+			 (cached-real-line-length line 10000 offset min)
+			 (real-line-length line 10000 offset min))))
+	    (when (< len width)
+	      (let ((new (alloc-font-change
+			  (+ len
+			     (if string
+				 (- (length (the simple-string string)) underhang)
+				 0))
+			  (font-mark-font min-mark)
+			  min-mark)))
+		(if prev
+		    (setf (font-change-next prev) new)
+		    (setf (dis-line-font-changes dis-line) new))
+		(setq prev new))))))))
+  ;;
+  ;; Recompute the line image.
+  (cond
+   (string
+    (let ((len (strlen string))
+	  (chars (dis-line-chars dis-line))
+	  (xpos 0))
+      (declare (type (or fixnum null) xpos) (simple-string chars))
+      (display-some-chars string underhang len chars xpos width nil)
+      (cond
+       ((null xpos)
+	(values string underhang offset))	   
+       ((current-open-line-p line)
+	(compute-cached-line-image offset dis-line xpos width))
+       (t
+ 	(compute-normal-line-image line offset dis-line xpos width)))))
+   ((current-open-line-p line)
+    (compute-cached-line-image offset dis-line 0 width))
+   (t
+    (compute-normal-line-image line offset dis-line 0 width))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/spell-build.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/spell-build.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/spell-build.lisp	(revision 13309)
@@ -0,0 +1,249 @@
+;;; -*- Log: hemlock.log; Package: Spell -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;;    Written by Bill Chiles
+;;;    Designed by Bill Chiles and Rob Maclachlan
+;;;
+
+;;; This file contains code to build a new binary dictionary file from
+;;; text in system space.  This code relies on implementation dependent
+;;; code from spell-rt.lisp.  Also, it is expected that spell-corr.lisp
+;;; and spell-aug.lisp have been loaded.  In order to compile this file,
+;;; you must first compile spell-rt, spell-corr.lisp, and spell-aug.lisp.
+
+;;; The text file must be in the following format:
+;;;      entry1/flag1/flag2/flag3
+;;;      entry2
+;;;      entry3/flag1/flag2/flag3/flag4/flag5.
+;;; The flags are single letter indicators of legal suffixes for the entry;
+;;; the available flags and their correct use may be found at the beginning
+;;; of spell-corr.lisp in the Hemlock sources.  There must be exactly one 
+;;; entry per line, and each line must be flushleft.
+
+;;; The dictionary is built in system space as three distinct 
+;;; blocks of memory: the dictionary which is a hash table whose elements
+;;; are one machine word or of type '(unsigned-byte 16); a descriptors
+;;; vector which is described below; and a string table.  After all the
+;;; entries are read in from the text file, one large block of memory is
+;;; validated, and the three structures are moved into it.  Then the file
+;;; is written.  When the large block of memory is validated, enough
+;;; memory is allocated to write the three vector such that they are page
+;;; aligned.  This is important for the speed it allows in growing the
+;;; "dictionary" when augmenting it from a user's text file (see
+;;; spell-aug.lisp).
+
+
+(in-package "SPELL")
+
+
+
+
+;;;; Constants
+
+;;; This is an upper bound estimate of the number of stored entries in the
+;;; dictionary.  It should not be more than 21,845 because the dictionary
+;;; is a vector of type '(unsigned-byte 16), and the descriptors' vector
+;;; for the entries uses three '(unsigned-byte 16) elements per descriptor
+;;; unit.  See the beginning of Spell-Correct.Lisp.
+;;;
+(eval-when (compile load eval)
+
+(defconstant max-entry-count-estimate 15600)
+
+(defconstant new-dictionary-size 20011)
+
+(defconstant new-descriptors-size (1+ (* 3 max-entry-count-estimate)))
+
+(defconstant max-string-table-length (* 10 max-entry-count-estimate))
+
+); eval-when
+
+
+
+;;;; Hashing
+
+;;; These hashing macros are different from the ones in Spell-Correct.Lisp
+;;; simply because we are using separate space and global specials/constants.
+;;; Of course, they should be identical, but it doesn't seem worth cluttering
+;;; up Spell-Correct with macro generating macros for this file.
+
+(eval-when (compile eval)
+
+(defmacro new-hash2-increment (hash)
+  `(- new-dictionary-size
+      2
+      (the fixnum (rem ,hash (- new-dictionary-size 2)))))
+
+(defmacro new-hash2-loop (loc hash dictionary)
+  (let ((incr (gensym))
+	(loop-loc (gensym)))
+    `(let* ((,incr (new-hash2-increment ,hash))
+	    (,loop-loc ,loc))
+       (declare (fixnum ,incr ,loop-loc))
+       (loop (setf ,loop-loc
+		   (rem (+ ,loop-loc ,incr) new-dictionary-size))
+	     (when (zerop (the fixnum (aref ,dictionary ,loop-loc)))
+	       (return ,loop-loc))
+	     (when (= ,loop-loc ,loc) (return nil))))))
+
+(defmacro new-hash-entry (entry entry-len dictionary)
+  (let ((hash (gensym))
+	(loc (gensym)))
+    `(let* ((,hash (string-hash ,entry ,entry-len))
+	    (,loc (rem ,hash new-dictionary-size)))
+       (declare (fixnum ,loc))
+       (cond ((not (zerop (the fixnum (aref ,dictionary ,loc))))
+	      (incf *collision-count*)
+	      (new-hash2-loop ,loc ,hash ,dictionary))
+	     (t ,loc)))))
+
+) ;eval-when
+
+
+
+
+;;;; Build-Dictionary
+
+;;; An interesting value when building an initial dictionary.
+(defvar *collision-count* 0)
+
+(defvar *new-dictionary*)
+(defvar *new-descriptors*)
+(defvar *new-string-table*)
+
+(defun build-dictionary (input output &optional save-structures-p)
+  (let ((dictionary (make-array new-dictionary-size
+				:element-type '(unsigned-byte 16)))
+	(descriptors (make-array new-descriptors-size
+				:element-type '(unsigned-byte 16)))
+	(string-table (make-string max-string-table-length)))
+    (write-line "Reading dictionary ...")
+    (force-output)
+    (setf *collision-count* 0)
+    (multiple-value-bind (entry-count string-table-length)
+			 (read-initial-dictionary input dictionary
+						  descriptors string-table)
+      (write-line "Writing dictionary ...")
+      (force-output)
+      (write-dictionary output dictionary descriptors entry-count
+			string-table string-table-length)
+      (when save-structures-p
+	(setf *new-dictionary* dictionary)
+	(setf *new-descriptors* descriptors)
+	(setf *new-string-table* string-table))
+      (format t "~D entries processed with ~D collisions."
+	      entry-count *collision-count*))))
+
+(defun read-initial-dictionary (f dictionary descriptors string-table)
+  (let* ((filename (pathname f))
+	 (s (open filename :direction :input :if-does-not-exist nil)))
+    (unless s (error "File ~S does not exist." f))
+    (multiple-value-prog1
+     (let ((descriptor-ptr 1)
+	   (string-ptr 0)
+	   (entry-count 0))
+       (declare (fixnum descriptor-ptr string-ptr entry-count))
+       (loop (multiple-value-bind (line eofp) (read-line s nil nil)
+	       (declare (type (or null simple-string) line))
+	       (unless line (return (values entry-count string-ptr)))
+	       (incf entry-count)
+	       (when (> entry-count max-entry-count-estimate)
+		 (error "There are too many entries in text file!~%~
+			Please change constants in spell-build.lisp, ~
+			recompile the file, and reload it.~%~
+			Be sure to understand the constraints of permissible ~
+			values."))
+	       (let ((flags (or (position #\/ line :test #'char=) (length line))))
+		 (declare (fixnum flags))
+		 (cond ((> flags max-entry-length)
+			(format t "Entry ~s too long." (subseq line 0 flags))
+			(force-output))
+		       (t (let ((new-string-ptr (+ string-ptr flags)))
+			    (declare (fixnum new-string-ptr))
+			    (when (> new-string-ptr max-string-table-length)
+			      (error "Spell string table overflow!~%~
+				     Please change constants in ~
+				     spell-build.lisp, recompile the file, ~
+				     and reload it.~%~
+				     Be sure to understand the constraints ~
+				     of permissible values."))
+			    (spell-place-entry line flags
+					       dictionary descriptors string-table
+					       descriptor-ptr string-ptr)
+			    (incf descriptor-ptr 3)
+			    (setf string-ptr new-string-ptr)))))
+	       (when eofp (return (values entry-count string-ptr))))))
+     (close s))))
+
+(defun spell-place-entry (line word-end dictionary descriptors string-table
+			       descriptor-ptr string-ptr)
+  (declare (simple-string line string-table)
+	   (fixnum word-end descriptor-ptr string-ptr)
+	   (type (array (unsigned-byte 16) (*)) dictionary descriptors))
+  (nstring-upcase line :end word-end)
+  (let* ((hash-loc (new-hash-entry line word-end dictionary))
+	 (descriptor-ptr+1 (1+ descriptor-ptr))
+	 (descriptor-ptr+2 (1+ descriptor-ptr+1)))
+    (unless hash-loc (error "Dictionary Overflow!"))
+    (setf (aref dictionary hash-loc) descriptor-ptr)
+    (setf (aref descriptors descriptor-ptr)
+	  (dpb (the fixnum
+		    (ldb new-hash-byte (string-hash line word-end)))
+	       stored-hash-byte
+	       word-end))
+    (setf (aref descriptors descriptor-ptr+1)
+	  (ldb whole-index-low-byte string-ptr))
+    (setf (aref descriptors descriptor-ptr+2)
+	  (dpb (the fixnum (ldb whole-index-high-byte string-ptr))
+	       stored-index-high-byte
+	       0))
+    (new-add-flags descriptors descriptor-ptr+2 line word-end)
+    (replace string-table line :start1 string-ptr :end2 word-end)))
+
+(defun new-add-flags (descriptors loc line word-end)
+  (declare (simple-string line)
+	   (fixnum word-end)
+	   (type (array (unsigned-byte 16) (*)) descriptors))
+  (do ((flag (1+ word-end) (+ 2 flag))
+       (line-end (length line)))
+      ((>= flag line-end))
+    (declare (fixnum flag line-end))
+    (let ((flag-mask (flag-mask (schar line flag))))
+      (declare (fixnum flag-mask))
+      (if (zerop flag-mask)
+	  (format t "Illegal flag ~S on word ~S."
+		  (schar line flag) (subseq line 0 word-end))
+	  (setf (aref descriptors loc)
+		(logior flag-mask (aref descriptors loc)))))))
+
+(defun write-dictionary (f dictionary descriptors entry-count
+			   string-table string-table-length)
+  (declare (type (array (unsigned-byte 16) (*)) dictionary descriptors)
+	   (simple-string string-table)
+	   (fixnum string-table-length))
+  (let ((filename (ext:unix-namestring (pathname f) nil)))
+    (with-open-file (s filename :direction :output
+		       :element-type '(unsigned-byte 16)
+		       :if-exists :overwrite
+		       :if-does-not-exist :create)
+      (let ((descriptors-size (1+ (* 3 entry-count))))
+	(write-byte magic-file-id s)
+	(write-byte new-dictionary-size s)
+	(write-byte descriptors-size s)
+	(write-byte (ldb whole-index-low-byte string-table-length) s)
+	(write-byte (ldb whole-index-high-byte string-table-length) s)
+	(dotimes (i new-dictionary-size)
+	  (write-byte (aref dictionary i) s))
+	(dotimes (i descriptors-size)
+	  (write-byte (aref descriptors i) s))))
+    (with-open-file (s f :direction :output :element-type 'base-char
+		         :if-exists :append)
+      (write-string string-table s :end string-table-length))))
Index: /branches/new-random/cocoa-ide/hemlock/unused/struct-ed.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/struct-ed.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/struct-ed.lisp	(revision 13309)
@@ -0,0 +1,40 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Structures used by constucts in the HEMLOCK package.
+;;;
+
+(in-package "HEMLOCK")
+
+;;; The server-info structure holds information about the connection to a
+;;; particular eval server.  For now, we don't separate the background I/O and
+;;; random compiler output.  The Notifications port and Terminal_IO will be the
+;;; same identical object.  This separation in the interface may be just
+;;; gratuitous pseudo-generality, but it doesn't hurt.
+;;;
+(defstruct (server-info
+	    (:print-function
+	     (lambda (s stream d)
+	       (declare (ignore d))
+	       (format stream "#<Server-Info for ~A>" (server-info-name s)))))
+  name			      ; String name of this server.
+  port			      ; Port we send requests to.
+			      ;  NullPort if no connection. 
+  notifications		      ; List of notification objects for operations
+			      ;  which have not yet completed.
+  ts-info		      ; Ts-Info structure of typescript we use in
+			      ;  "background" buffer.
+  buffer		      ; Buffer "background" typescript is in.
+  slave-ts		      ; Ts-Info used in "Slave Lisp" buffer
+			      ;  (formerly the "Lisp Listener" buffer).
+  slave-buffer		      ; "Slave Lisp" buffer for slave's *terminal-io*.
+  errors		      ; List of structures describing reported errors.
+  error-mark)		      ; Pointer after last error edited. 
Index: /branches/new-random/cocoa-ide/hemlock/unused/tty-stream.lisp
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/unused/tty-stream.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/unused/tty-stream.lisp	(revision 13309)
@@ -0,0 +1,161 @@
+;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
+;;;
+;;; **********************************************************************
+;;; This code was written as part of the CMU Common Lisp project at
+;;; Carnegie Mellon University, and has been placed in the public domain.
+;;;
+#+CMU (ext:file-comment
+  "$Header$")
+;;;
+;;; **********************************************************************
+;;;
+;;; Some stuff to make streams that write out to terminal hunks.
+;;;
+;;; Written by Bill Chiles.
+;;;
+;;; This code is VERY similar to that in Pane-Stream.Lisp.  The biggest
+;;; (if only) difference is in TTY-HUNK-STREAM-NEWLINE.
+;;;
+
+(in-package "HEMLOCK-INTERNALS")
+
+
+
+
+;;;; Constants
+
+(defconstant tty-hunk-width-limit 200)
+
+
+
+
+;;;; Structures
+
+;;; Tty-Hunk streams are inherently buffered by line.
+
+(defstruct (stream-hunk (:print-function %print-device-hunk)
+			(:include tty-hunk))
+  (width 0 :type fixnum)
+  (point-x 0 :type fixnum)
+  (point-y 0 :type fixnum)
+  (buffer "" :type simple-string))
+
+(defstruct (tty-hunk-output-stream (:include sys:lisp-stream
+					     (out #'hunk-out)
+					     (sout #'hunk-sout)
+					     (misc #'hunk-misc))
+				   (:constructor
+				    make-tty-hunk-output-stream ()))
+  (hunk (make-stream-hunk :buffer (make-string tty-hunk-width-limit))))
+
+
+
+
+;;;; Tty-hunk-output-stream methods
+
+;;; HUNK-OUT puts a character into a hunk-stream buffer.  If the character
+;;; makes the current line wrap, or if the character is a newline, then
+;;; call TTY-HUNK-NEWLINE.
+;;;
+(defun hunk-out (stream character)
+  (let* ((hunk (tty-hunk-output-stream-hunk stream))
+	 (x (stream-hunk-point-x hunk)))
+    (declare (fixnum x))
+    (cond ((char= character #\newline)
+	   (tty-hunk-stream-newline hunk)
+	   (return-from hunk-out nil))
+	  ((= x (the fixnum (stream-hunk-width hunk)))
+	   (setf x 0)
+	   (tty-hunk-stream-newline hunk)))
+    (setf (schar (stream-hunk-buffer hunk) x) character)
+    (incf (stream-hunk-point-x hunk))))
+
+;;; HUNK-MISC, when finishing or forcing output, only needs to blast
+;;; out the buffer at y from 0 to x since these streams are inherently
+;;; line buffered.  Currently, these characters will be blasted out again
+;;; since there isn't a separate buffer index from point-x, and we can't
+;;; set point-x to zero since we haven't a newline.
+;;; 
+(defun hunk-misc (stream operation &optional arg1 arg2)
+  (declare (ignore arg1 arg2))
+  (case operation
+    (:charpos
+     (let ((hunk (tty-hunk-output-stream-hunk stream)))
+       (values (stream-hunk-point-x hunk) (stream-hunk-point-y hunk))))
+    ((:finish-output :force-output)
+     (let* ((hunk (tty-hunk-output-stream-hunk stream))
+	    (device (device-hunk-device hunk)))
+       (funcall (tty-device-display-string device)
+		hunk 0 (stream-hunk-point-y hunk) (stream-hunk-buffer hunk)
+		0 (stream-hunk-point-x hunk))
+       (when (device-force-output device)
+	 (funcall (device-force-output device)))))
+    (:line-length
+     (stream-hunk-width (tty-hunk-output-stream-hunk stream)))
+    (:element-type 'base-char)))
+
+;;; HUNK-SOUT writes a byte-blt's a string to a hunk-stream's buffer.
+;;; When newlines are found, recurse on the substrings delimited by start,
+;;; end, and newlines.  If the string causes line wrapping, then we break
+;;; the string up into line-at-a-time segments calling TTY-HUNK-STREAM-NEWLINE.
+;;; 
+(defun hunk-sout (stream string start end)
+  (declare (fixnum start end))
+  (let* ((hunk (tty-hunk-output-stream-hunk stream))
+	 (buffer (stream-hunk-buffer hunk))
+	 (x (stream-hunk-point-x hunk))
+	 (dst-end (+ x (- end start)))
+	 (width (stream-hunk-width hunk))
+	 (newlinep (%sp-find-character string start end #\newline)))
+    (declare (fixnum x dst-end width))
+    (cond (newlinep
+	   (let ((previous start) (current newlinep))
+	     (declare (fixnum previous))
+	     (loop (when (null current)
+		     (hunk-sout stream string previous end)
+		     (return))
+		   (hunk-sout stream string previous current)
+		   (tty-hunk-stream-newline hunk)
+		   (setf previous (the fixnum (1+ (the fixnum current))))
+		   (setf current
+			 (%sp-find-character string previous end #\newline)))))
+	  ((> dst-end width)
+	   (let ((new-start (+ start (- width x))))
+	     (declare (fixnum new-start))
+	     (%primitive byte-blt string start buffer x width)
+	     (setf (stream-hunk-point-x hunk) width)
+	     (tty-hunk-stream-newline hunk)
+	     (do ((idx (+ new-start width) (+ idx width))
+		  (prev new-start idx))
+		 ((>= idx end)
+		  (let ((dst-end (- end prev)))
+		    (%primitive byte-blt string prev buffer 0 dst-end)
+		    (setf (stream-hunk-point-x hunk) dst-end)))
+	       (declare (fixnum prev idx))
+	       (%primitive byte-blt string prev buffer 0 width)
+	       (setf (stream-hunk-point-x hunk) width)
+	       (tty-hunk-stream-newline hunk))))
+	  (t
+	   (%primitive byte-blt string start buffer x dst-end)
+	   (setf (stream-hunk-point-x hunk) dst-end)))))
+
+;;; TTY-HUNK-STREAM-NEWLINE is the only place we display lines and affect
+;;; point-y.  We also blast out the buffer in HUNK-MISC.
+;;; 
+(defun tty-hunk-stream-newline (hunk)
+  (let* ((device (device-hunk-device hunk))
+	 (force-output-fun (device-force-output device))
+	 (y (stream-hunk-point-y hunk)))
+    (declare (fixnum y))
+    (when (= y (the fixnum (device-hunk-position hunk)))
+      (funcall (tty-device-display-string device) hunk 0 y "--More--" 0 8)
+      (when force-output-fun (funcall force-output-fun))
+      (wait-for-more)
+      (funcall (tty-device-clear-to-eow device) hunk 0 0)
+      (setf (stream-hunk-point-y hunk) 0)
+      (setf y 0))
+    (funcall (tty-device-display-string device)
+	     hunk 0 y (stream-hunk-buffer hunk) 0 (stream-hunk-point-x hunk))
+    (when force-output-fun (funcall force-output-fun))
+    (setf (stream-hunk-point-x hunk) 0)
+    (incf (stream-hunk-point-y hunk))))
Index: /branches/new-random/cocoa-ide/hemlock/website/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/website/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/website/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/cocoa-ide/hemlock/website/index.html.in
===================================================================
--- /branches/new-random/cocoa-ide/hemlock/website/index.html.in	(revision 13309)
+++ /branches/new-random/cocoa-ide/hemlock/website/index.html.in	(revision 13309)
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Portable Hemlock</title>
+    <link rel='stylesheet' href='../style.css'>
+    <link rel='shortcut icon' href='../lambda.png'>
+  </head>
+
+  <body>
+    <div class=face2></div>
+    
+    <h1 align=center>Portable Hemlock</h1>
+<p>
+Hemlock is an Emacs-like editor which for a long time was a part of <a
+href='http://www.cons.org/cmucl/'>CMUCL</a>. It was believed that it
+is tied to this particular implementation of Common Lisp. But this is
+no longer true.
+
+<p>
+So, here is Portable Hemlock! An attempt to free Hemlock from its CMUCL
+prison.
+
+<p>
+The stuff that works is opening files, editing them and saving your
+work -- what you expect from an editor. Lisp mode works too. Missing
+is: tty mode operation, typescript buffers (inferior shell and
+inferior lisp), spell checking, netnews and mail.
+<p>
+Portable Hemlock was tested in:
+<ul>
+<li> <a href='http://www.cons.org/cmucl/'>CMUCL</a>
+<li> <a href='http://clisp.cons.org/'>CLISP</a>
+<li> <a href='http://openmcl.clozure.com/'>OpenMCL</a> (patches not yet received)
+<li> <a href='http://sbcl.sourceforge.net/'>SBCL</a>, patches by Daniel Barlow.
+<li> <a href='http://www.scieneer.com/scl/'>Scieneer Common Lisp</a>, patches by Douglas Crosher.
+</ul>
+
+<h2>Download</h2>
+
+<a href='http://www.stud.uni-karlsruhe.de/~unk6/export/hemlock-%%DATE%%.tar.gz'>hemlock-%%DATE%%.tar.gz</a>, have fun.
+
+<h2>CVS access</h2>
+
+    <p>
+      Anonymouns [read-only] CVS access is available. Just follow the instructions below:
+
+    <p style='margin: 1em; padding: 1em; border: 1px solid; background: rgb(100%,100%,80%);'>
+<tt>$ export CVSROOT=<b>:pserver:anonymous@bauhh.dyndns.org:/hemlock</b></tt><br>
+<tt>$ cvs login</tt><br>
+<tt>Logging in to :pserver:anonymous@bauhh.dyndns.org:2401/hemlock</tt><br>
+<tt>CVS password: <b>anonymous</b></tt><br>
+<tt>$ cvs -z9 co -P <b>hemlock</b></tt><br>
+</p>
+
+<b>non</b>-anonymous CVS write access is also awailable, just drop
+<a href="mailto:unk6@stud.uni-karlsruhe.de">me</a> a note if you want
+access.
+
+<h2>News/History</h2>
+
+<dl>
+<dt>2003-08-05
+<dd>I was a bit lazy updating the web page. Here is what happend:
+<ul>
+
+<li>Ingvar Mattsson is hacking an elisp compatibility package.
+
+<li>I am currently working on providing the "Slave Lisp"
+functionality, so that Portable Hemlock will be useful for actually
+hacking Lisp code.
+
+</ul>
+
+<dt>2003-03-06
+<dd>Bug fix: <tt>auto-save.lisp</tt> was not compiling.
+<dt>2003-03-05
+<dd>This web page was created.<p>
+    New release having the SBCL patches in.
+<dt>2003-02-07
+<dd>Portable Hemlock was announced to <a href='http://www.cliki.net/IRC'>#lisp</a>.
+<dt>2002-11-??
+<dd>I made initial attempt to port Hemlock from CMUCL. Then put it aside to work on other stuff.
+</dl>
+
+<h2>Random Notes</h2>
+
+<p>
+The source code of Hemlock showed unportability (or better its age) in
+the following areas:
+<ul>
+<li><P>
+   Buffers sometimes also serve as streams. As Hemlock was written
+   there was no universal de-facto standard interface for user defined
+   streams and thus the authors defined CMUCL streams. These days we
+   have Gray streams.
+
+<li><p>
+   File I/O was tied to both CMUCL and Unix to accommodate probably
+   slow machines. The file I/O functions called
+   <tt>unix-read</tt> and <tt>unix-write</tt> beaming data directly to
+   and fro system areas. I changed that using standard CL functions
+   doing I/O on a line-by-line basis now.
+
+<li><p>
+   The TTY interface is inherently unportable. Currently it is
+   disabled altogether. I think we could reclaim some useful code from
+   Hemlock's TTY interface and morph it into a CLIM TTY port. And
+   since my graphics card cannot even display a text console interface
+   on my monitor, this has very low priority on my list, though other
+   people might want to have it.
+
+<li><p>
+   The X11 interface uses the <tt>SERVE-EVENT</tt> facility of CMUCL,
+   which naturally is only available there. I provided a thin
+   portability layer to provide the same API using just the standard
+   CLX interface.
+</ul>
+<p>
+This already summaries pretty well the current state of Portable
+Hemlock. You can edit files using the X11 interface on an ANSI CL
+which provides for CLX.
+
+<h2>Future</h2>
+
+<p>
+The next steps I have in mind are:
+
+<ul>
+<li> <p>Port the missing files except the TTY interface.
+
+<li> <p>Hemlock has the idea that characters are 8-bit wide. We need to
+   teach it otherwise as we have Unicode strings now. This involves
+   syntax tables and probably searching.
+
+<li> <P>I want a CLIM Hemlock.
+<p>
+   How exactly to do this is still not decided. I see two
+   possibilities:
+<ul>
+<li> Hemlock already provides for a kind of device interface. We can
+     implement a new device which is just a CLIM device.
+
+<li> Or we rip this device abstraction layer and state that CLIM
+     itself is the device layer. (Making the bet that we'll have a TTY
+     CLIM in the future).
+</ul>
+</ul>
+<p>After that is done, we can talk about extending Portable Hemlock in various
+ways like syntax highlighting, color, new modes, ... you name it.
+
+
+<br>
+<br>
+    <address><a href="mailto:unk6@stud.uni-karlsruhe.de">Gilbert Baumann</a></address>
+<br>
+$Id$
+  </body>
+</html>
Index: /branches/new-random/cocoa-ide/ide-bundle.lisp
===================================================================
--- /branches/new-random/cocoa-ide/ide-bundle.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-bundle.lisp	(revision 13309)
@@ -0,0 +1,102 @@
+;;-*-Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+;;;
+
+(in-package "CCL")
+
+;;; We need to be able to point the CoreFoundation and Cocoa libraries
+;;; at some bundle very early in the process, so do that before anything
+;;; else.
+
+(defun create-ide-bundle (bundle-path &key (source "ccl:cocoa-ide;ide-contents;")
+				           (source-ignore '(".svn" "cvs" ".cvsignore"))
+					   (copy-headers *cocoa-application-copy-headers-p*)
+                                           (install-altconsole *cocoa-application-install-altconsole*)
+					   (if-exists :overwrite))
+  ;; TODO: Right now if the bundle exists, we leave alone any files that we don't replace.
+  ;; I'd like :if-exists :supersede mean to remove such files, for clean builds, but
+  ;; recursive-copy-directory doesn't support :if-exists :supersede yet...
+  (flet ((subdir (dir sub)
+	   (ensure-directory-pathname (make-pathname :name sub :defaults dir)))
+	 (ignore-test (p)
+	   (flet ((backup-p (name)
+		    (and (stringp name)
+			 (let ((len (length name)))
+			   (and (> len 0)
+				(or (eql (aref name (1- len)) #\~)
+				    (eql (aref name 0) #\#)))))))
+	     (not (or (member (car (last (pathname-directory p))) source-ignore :test #'equalp)
+		      (backup-p (file-namestring p))
+		      (member (file-namestring p) source-ignore :test #'equalp))))))
+    (let* ((source-dir (ensure-directory-pathname source))
+	   (target-dir (ensure-directory-pathname bundle-path))
+	   (contents-dir (subdir target-dir "Contents")))
+      (recursive-copy-directory source-dir contents-dir :if-exists if-exists :test #'ignore-test)
+      (when copy-headers
+	(let* ((subdirs (ccl::cdb-subdirectory-path))
+	       (ccl-headers (make-pathname :host "ccl" :directory `(:absolute ,@subdirs)))
+	       (dest-headers (make-pathname :host (pathname-host contents-dir)
+					    :directory (append (pathname-directory contents-dir)
+							       (cons "Resources" subdirs)))))
+	  (recursive-copy-directory ccl-headers dest-headers :if-exists if-exists :test #'ignore-test)))
+      (when install-altconsole
+        (install-altconsole bundle-path))
+      ;; Is this necessary?
+      ;; At one point in the past, it was necessary for the bundle to
+      ;; contain an executable file whose name matched what was specified
+      ;; in its Info.plist file.  That executable file could be practically
+      ;; anything, as long as its executable bits were set.
+      (let* ((image-name (ccl::standard-kernel-name))
+             #+ignore
+	     (ccl-image (make-pathname :name image-name :host "ccl"))
+	     (dest-image (make-pathname :name image-name
+					:defaults (subdir contents-dir #+darwin-target "MacOS" #+windows-target "Windows"))))
+	(ensure-directories-exist dest-image)
+        #+no
+	(copy-file ccl-image dest-image :if-exists :supersede :preserve-attributes t)
+        (ccl::touch dest-image)
+        )
+      #-windows-target
+      (ccl::touch target-dir))))
+
+;;; This runs "make install" to generate
+;;; "ccl:cocoa-ide;altconsole;AltConsole.app",
+;;; then copies that application bundle into the "Resources" directory
+;;; of the target bundle.  It might be simpler to just have "make install"
+;;; put things in the right place, but "the right place" is likely to
+;;; be a pathname that contains a space. Quoting such a pathname -
+;;; and figuring out how to get make to do so - is left as an exercise.
+(defun install-altconsole (bundle-path)
+  #-cocotron
+  (let* ((altconsole-path (merge-pathnames ";Contents;Resources;AltConsole.app;" bundle-path))
+         (build-directory "ccl:cocoa-ide;altconsole;")
+         (build-bundle-path "ccl:cocoa-ide;altconsole;AltConsole.app")
+         (make-output (make-string-output-stream))
+         (args `("-C" ,(native-translated-namestring build-directory) "install")))
+    (recursive-delete-directory altconsole-path :if-does-not-exist nil)
+    (unwind-protect
+         (multiple-value-bind (exit-status code)
+             (external-process-status
+              (run-program "make" args :output make-output :error make-output))
+           (unless (and (eq exit-status :exited) (zerop code))
+             (format t "~&'make install' of AltConsole.app failed:~&~a"
+                     (get-output-stream-string make-output))
+             (return-from install-altconsole nil)))
+      (close make-output))
+    ;;(ensure-directories-exist altconsole-path)
+    (recursive-copy-directory build-bundle-path altconsole-path)
+    (ccl::touch altconsole-path)
+    t)
+  #+cocotron
+  (let* ((path (probe-file "ccl:cocotron;WaltConsole;WaltConsole.exe")))
+    (when path
+      (copy-file path (merge-pathnames ";Contents;Resources;WaltConsole.exe" bundle-path)
+                 :preserve-attributes t :if-exists :supersede)
+      t))
+  )
+
+(progn
+  (require "FAKE-CFBUNDLE-PATH")
+  (create-ide-bundle *cocoa-application-path*)
+  (ccl::fake-cfbundle-path *cocoa-application-path* "ccl:cocoa-ide;Info.plist-proto" "com.clozure" *cocoa-application-bundle-suffix* *cocoa-application-frameworks* *cocoa-application-libraries* #+windows-target "ccl:cocoa-ide;ide-contents;resources;openmcl-icon.ico"))
Index: /branches/new-random/cocoa-ide/ide-contents/PkgInfo
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/PkgInfo	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/PkgInfo	(revision 13309)
@@ -0,0 +1,1 @@
+APPLOMCL
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/.cvsignore
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/.cvsignore	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.nib
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/Authenticate.nib/designable.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/Authenticate.nib/designable.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/Authenticate.nib/designable.nib	(revision 13309)
@@ -0,0 +1,494 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9C7010</string>
+		<string key="IBDocument.InterfaceBuilderVersion">667</string>
+		<string key="IBDocument.AppKitVersion">949.26</string>
+		<string key="IBDocument.HIToolboxVersion">352.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="2"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">AuthenticationWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">271</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 376}, {311, 134}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Authenticate</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="683308573">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 97}, {71, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="699062349">
+								<int key="NSCellFlags">67239488</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Username:</string>
+								<object class="NSFont" key="NSSupport" id="1051702825">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="683308573"/>
+								<object class="NSColor" key="NSBackgroundColor" id="478634459">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="320950608">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor" id="945916426">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="92683132">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 62}, {71, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="929977470">
+								<int key="NSCellFlags">67239488</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Password:</string>
+								<reference key="NSSupport" ref="1051702825"/>
+								<reference key="NSControlView" ref="92683132"/>
+								<reference key="NSBackgroundColor" ref="478634459"/>
+								<reference key="NSTextColor" ref="320950608"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="332937101">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{93, 92}, {198, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="637776574">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="1051702825"/>
+								<reference key="NSControlView" ref="332937101"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor" id="557212477">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textBackgroundColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="129191297">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textColor</string>
+									<reference key="NSColor" ref="945916426"/>
+								</object>
+							</object>
+						</object>
+						<object class="NSSecureTextField" id="52143535">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{93, 60}, {198, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSecureTextFieldCell" key="NSCell" id="721265786">
+								<int key="NSCellFlags">341966400</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="1051702825"/>
+								<reference key="NSControlView" ref="52143535"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="557212477"/>
+								<reference key="NSTextColor" ref="129191297"/>
+								<object class="NSArray" key="NSAllowedInputLocales">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSAllRomanInputSourcesLocaleIdentifier</string>
+								</object>
+							</object>
+						</object>
+						<object class="NSButton" id="558609978">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{105, 12}, {96, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="637871713">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Cancel</string>
+								<reference key="NSSupport" ref="1051702825"/>
+								<reference key="NSControlView" ref="558609978"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+						<object class="NSButton" id="455713151">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{201, 12}, {96, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="746299643">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Okay</string>
+								<reference key="NSSupport" ref="1051702825"/>
+								<reference key="NSControlView" ref="455713151"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{311, 134}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">authenticationWindow</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">17</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">usernameField</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="332937101"/>
+					</object>
+					<int key="connectionID">18</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">passwordField</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="52143535"/>
+					</object>
+					<int key="connectionID">19</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">authOkay:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="455713151"/>
+					</object>
+					<int key="connectionID">20</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">authCancel:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="558609978"/>
+					</object>
+					<int key="connectionID">21</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="683308573"/>
+							<reference ref="92683132"/>
+							<reference ref="332937101"/>
+							<reference ref="52143535"/>
+							<reference ref="455713151"/>
+							<reference ref="558609978"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="683308573"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="699062349"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="699062349"/>
+						<reference key="parent" ref="683308573"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="92683132"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="929977470"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="929977470"/>
+						<reference key="parent" ref="92683132"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="332937101"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="637776574"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="637776574"/>
+						<reference key="parent" ref="332937101"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="52143535"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="721265786"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">12</int>
+						<reference key="object" ref="721265786"/>
+						<reference key="parent" ref="52143535"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="558609978"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="637871713"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="637871713"/>
+						<reference key="parent" ref="558609978"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="455713151"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="746299643"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="746299643"/>
+						<reference key="parent" ref="455713151"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>11.IBPluginDependency</string>
+					<string>12.IBPluginDependency</string>
+					<string>13.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>5.IBPluginDependency</string>
+					<string>6.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{519, 836}, {311, 134}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{519, 836}, {311, 134}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{357, 554}, {311, 134}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">21</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">AuthenticationWindowController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>authCancel:</string>
+							<string>authOkay:</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>authenticationWindow</string>
+							<string>passwordField</string>
+							<string>usernameField</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/Credits.html
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/Credits.html	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/Credits.html	(revision 13309)
@@ -0,0 +1,28 @@
+<html>
+<head>
+<style type="text/css">
+html {
+    font-family: "Lucida Grande";
+    font-size: small;
+}
+
+.centered {
+    text-align: center;
+}
+
+</style>
+</head>
+<body>
+<p>
+This is still a very preliminary, barebones
+implementation of a Cocoa development environment for
+Clozure CL.   It's improved some over time, and
+will hopefully continue to do so.
+</p>
+<p>
+To report bugs or request enhancements, please go to the
+<a href="http://trac.clozure.com/ccl">Clozure CL Trac Site</a>
+and create a ticket.
+</p>
+</body>
+</html>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/InfoPlist.strings
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/InfoPlist.strings	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/InfoPlist.strings	(revision 13309)
@@ -0,0 +1,5 @@
+/* Localized versions of Info.plist keys */
+
+CFBundleShortVersionString = "Version 1.4-dev";
+CFBundleGetInfoString = "Clozure Common Lisp version 1.4, Copyright 2002-2009 Clozure Associates and contributors.";
+NSHumanReadableCopyright = "Copyright 2002-2009 Clozure Associates and contributors.";
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/MainMenu.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/MainMenu.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/MainMenu.nib/classes.nib	(revision 13309)
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>toggleConsole</key>
+				<string>id</string>
+				<key>toggleTypeout</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>NSApplication</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSResponder</string>
+		</dict>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>backtrace</key>
+				<string>id</string>
+				<key>compileAndLoadBuffer</key>
+				<string>id</string>
+				<key>compileBuffer</key>
+				<string>id</string>
+				<key>compileFile</key>
+				<string>id</string>
+				<key>continue</key>
+				<string>id</string>
+				<key>evalAll</key>
+				<string>id</string>
+				<key>evalSelection</key>
+				<string>id</string>
+				<key>exitBreak</key>
+				<string>id</string>
+				<key>hyperSpecLookUp</key>
+				<string>id</string>
+				<key>inspect</key>
+				<string>id</string>
+				<key>interrupt</key>
+				<string>id</string>
+				<key>loadBuffer</key>
+				<string>id</string>
+				<key>loadFile</key>
+				<string>id</string>
+				<key>newListener</key>
+				<string>id</string>
+				<key>restarts</key>
+				<string>id</string>
+				<key>showAproposWindow</key>
+				<string>id</string>
+				<key>showListener</key>
+				<string>id</string>
+				<key>showNewInspector</key>
+				<string>id</string>
+				<key>showPreferences</key>
+				<string>id</string>
+				<key>showProcessesWindow</key>
+				<string>id</string>
+				<key>showSearchFiles</key>
+				<string>id</string>
+				<key>showXaproposWindow</key>
+				<string>id</string>
+				<key>updateCCL</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>FirstResponder</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/MainMenu.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/MainMenu.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/MainMenu.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>29</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9J61</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/classes.nib	(revision 13309)
@@ -0,0 +1,32 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {
+            ACTIONS = {browserAction = id; browserDoubleAction = id; }; 
+            CLASS = InspectorBrowserDelegate; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {inspectorTableView = NSTableView; inspectorWindow = NSWindow; }; 
+            SUPERCLASS = NSObject; 
+        }, 
+        {CLASS = InspectorNSBrowser; LANGUAGE = ObjC; SUPERCLASS = NSBrowser; }, 
+        {
+            CLASS = InspectorTableViewDataSource; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {inspectorBrowser = NSBrowser; inspectorWindow = NSWindow; }; 
+            SUPERCLASS = NSObject; 
+        }, 
+        {
+            CLASS = InspectorTableViewDelegate; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {inspectorWindow = NSWindow; }; 
+            SUPERCLASS = NSObject; 
+        }, 
+        {
+            CLASS = InspectorWindowController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {inspectorBrowser = NSBrowser; }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBDocumentLocation</key>
+	<string>58 65 356 240 0 0 1280 1002 </string>
+	<key>IBFramework Version</key>
+	<string>446.1</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>21</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>8L2127</string>
+	<key>IBUsesTextArchiving</key>
+	<true/>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/keyedobjects.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/keyedobjects.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/OpenmclInspector.nib/keyedobjects.nib	(revision 13309)
@@ -0,0 +1,2299 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>$archiver</key>
+	<string>NSKeyedArchiver</string>
+	<key>$objects</key>
+	<array>
+		<string>$null</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>168</integer>
+			</dict>
+			<key>NSAccessibilityConnectors</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>165</integer>
+			</dict>
+			<key>NSAccessibilityOidsKeys</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>166</integer>
+			</dict>
+			<key>NSAccessibilityOidsValues</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>167</integer>
+			</dict>
+			<key>NSClassesKeys</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>138</integer>
+			</dict>
+			<key>NSClassesValues</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>139</integer>
+			</dict>
+			<key>NSConnections</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>9</integer>
+			</dict>
+			<key>NSFontManager</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>0</integer>
+			</dict>
+			<key>NSFramework</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>5</integer>
+			</dict>
+			<key>NSNamesKeys</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>129</integer>
+			</dict>
+			<key>NSNamesValues</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>130</integer>
+			</dict>
+			<key>NSNextOid</key>
+			<integer>276</integer>
+			<key>NSObjectsKeys</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>126</integer>
+			</dict>
+			<key>NSObjectsValues</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>128</integer>
+			</dict>
+			<key>NSOidsKeys</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>140</integer>
+			</dict>
+			<key>NSOidsValues</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>141</integer>
+			</dict>
+			<key>NSRoot</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>2</integer>
+			</dict>
+			<key>NSVisibleWindows</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>7</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>4</integer>
+			</dict>
+			<key>NSClassName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>3</integer>
+			</dict>
+		</dict>
+		<string>InspectorWindowController</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSCustomObject</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSCustomObject</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>6</integer>
+			</dict>
+			<key>NS.string</key>
+			<string>IBCocoaFramework</string>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSMutableString</string>
+				<string>NSString</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSMutableString</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>8</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array/>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSMutableSet</string>
+				<string>NSSet</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSMutableSet</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>49</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>10</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>58</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>62</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>107</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>109</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>111</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>113</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>115</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>117</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>119</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>122</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>124</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>54</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>56</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>53</integer>
+			</dict>
+			<key>NSBackgroundColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>39</integer>
+			</dict>
+			<key>NSColumnAutoresizingStyle</key>
+			<integer>4</integer>
+			<key>NSCornerView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>18</integer>
+			</dict>
+			<key>NSDraggingSourceMaskForLocal</key>
+			<integer>15</integer>
+			<key>NSDraggingSourceMaskForNonLocal</key>
+			<integer>0</integer>
+			<key>NSEnabled</key>
+			<true/>
+			<key>NSFrameSize</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>13</integer>
+			</dict>
+			<key>NSGridColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>50</integer>
+			</dict>
+			<key>NSHeaderView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>14</integer>
+			</dict>
+			<key>NSIntercellSpacingHeight</key>
+			<real>2</real>
+			<key>NSIntercellSpacingWidth</key>
+			<real>3</real>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>12</integer>
+			</dict>
+			<key>NSRowHeight</key>
+			<real>17</real>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>12</integer>
+			</dict>
+			<key>NSTableColumns</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>22</integer>
+			</dict>
+			<key>NSTvFlags</key>
+			<integer>1379926016</integer>
+			<key>NSvFlags</key>
+			<integer>256</integer>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>88</integer>
+			</dict>
+			<key>NSBGColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>85</integer>
+			</dict>
+			<key>NSDocView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>84</integer>
+			</dict>
+			<key>NSNextKeyView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSSubviews</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>83</integer>
+			</dict>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NScvFlags</key>
+			<integer>4</integer>
+			<key>NSvFlags</key>
+			<integer>2304</integer>
+		</dict>
+		<string>{525, 193}</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>17</integer>
+			</dict>
+			<key>NSFrameSize</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>16</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>15</integer>
+			</dict>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>15</integer>
+			</dict>
+			<key>NSTableView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSvFlags</key>
+			<integer>256</integer>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>88</integer>
+			</dict>
+			<key>NSBGColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>85</integer>
+			</dict>
+			<key>NSDocView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>14</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>97</integer>
+			</dict>
+			<key>NSNextKeyView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>14</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSSubviews</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>96</integer>
+			</dict>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NScvFlags</key>
+			<integer>4</integer>
+			<key>NSvFlags</key>
+			<integer>2304</integer>
+		</dict>
+		<string>{525, 17}</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSTableHeaderView</string>
+				<string>NSView</string>
+				<string>NSResponder</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSTableHeaderView</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>21</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>20</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSvFlags</key>
+			<integer>256</integer>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>99</integer>
+			</dict>
+			<key>NSContentView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>12</integer>
+			</dict>
+			<key>NSCornerView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>18</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>98</integer>
+			</dict>
+			<key>NSHScroller</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>93</integer>
+			</dict>
+			<key>NSHeaderClipView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>15</integer>
+			</dict>
+			<key>NSNextKeyView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>12</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>70</integer>
+			</dict>
+			<key>NSScrollAmts</key>
+			<data>
+			QSAAAEEgAABBmAAAQZgAAA==
+			</data>
+			<key>NSSubviews</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>82</integer>
+			</dict>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>70</integer>
+			</dict>
+			<key>NSVScroller</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>89</integer>
+			</dict>
+			<key>NSsFlags</key>
+			<integer>50</integer>
+			<key>NSvFlags</key>
+			<integer>258</integer>
+		</dict>
+		<string>{{526, 0}, {16, 17}}</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>_NSCornerView</string>
+				<string>NSView</string>
+				<string>NSResponder</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>_NSCornerView</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>49</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>23</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>44</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>43</integer>
+			</dict>
+			<key>NSDataCell</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>37</integer>
+			</dict>
+			<key>NSHeaderCell</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>25</integer>
+			</dict>
+			<key>NSIdentifier</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>24</integer>
+			</dict>
+			<key>NSIsEditable</key>
+			<true/>
+			<key>NSIsResizeable</key>
+			<true/>
+			<key>NSMaxWidth</key>
+			<real>1000</real>
+			<key>NSMinWidth</key>
+			<real>40</real>
+			<key>NSResizingMask</key>
+			<integer>3</integer>
+			<key>NSTableView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSWidth</key>
+			<real>178</real>
+		</dict>
+		<string>property</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>36</integer>
+			</dict>
+			<key>NSBackgroundColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>30</integer>
+			</dict>
+			<key>NSCellFlags</key>
+			<integer>75628032</integer>
+			<key>NSCellFlags2</key>
+			<integer>0</integer>
+			<key>NSContents</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>26</integer>
+			</dict>
+			<key>NSSupport</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>27</integer>
+			</dict>
+			<key>NSTextColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>32</integer>
+			</dict>
+		</dict>
+		<string>Property</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>29</integer>
+			</dict>
+			<key>NSName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>28</integer>
+			</dict>
+			<key>NSSize</key>
+			<real>11</real>
+			<key>NSfFlags</key>
+			<integer>16</integer>
+		</dict>
+		<string>LucidaGrande</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSFont</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSFont</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>3</integer>
+			<key>NSWhite</key>
+			<data>
+			MC4zMzMzMzMzNAA=
+			</data>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSColor</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSColor</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSCatalogName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>33</integer>
+			</dict>
+			<key>NSColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>35</integer>
+			</dict>
+			<key>NSColorName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>34</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>6</integer>
+		</dict>
+		<string>System</string>
+		<string>headerTextColor</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>3</integer>
+			<key>NSWhite</key>
+			<data>
+			MAA=
+			</data>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSTableHeaderCell</string>
+				<string>NSTextFieldCell</string>
+				<string>NSActionCell</string>
+				<string>NSCell</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSTableHeaderCell</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>42</integer>
+			</dict>
+			<key>NSBackgroundColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>39</integer>
+			</dict>
+			<key>NSCellFlags</key>
+			<integer>338820672</integer>
+			<key>NSCellFlags2</key>
+			<integer>1024</integer>
+			<key>NSControlView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSSupport</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>38</integer>
+			</dict>
+			<key>NSTextColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>40</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>29</integer>
+			</dict>
+			<key>NSName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>28</integer>
+			</dict>
+			<key>NSSize</key>
+			<real>13</real>
+			<key>NSfFlags</key>
+			<integer>1044</integer>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>3</integer>
+			<key>NSWhite</key>
+			<data>
+			MQA=
+			</data>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSCatalogName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>33</integer>
+			</dict>
+			<key>NSColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>35</integer>
+			</dict>
+			<key>NSColorName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>41</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>6</integer>
+		</dict>
+		<string>controlTextColor</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSTextFieldCell</string>
+				<string>NSActionCell</string>
+				<string>NSCell</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSTextFieldCell</string>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSTableColumn</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSTableColumn</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>43</integer>
+			</dict>
+			<key>NSDataCell</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>48</integer>
+			</dict>
+			<key>NSHeaderCell</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>46</integer>
+			</dict>
+			<key>NSIdentifier</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>45</integer>
+			</dict>
+			<key>NSIsEditable</key>
+			<true/>
+			<key>NSIsResizeable</key>
+			<true/>
+			<key>NSMaxWidth</key>
+			<real>1000</real>
+			<key>NSMinWidth</key>
+			<real>37.4010009765625</real>
+			<key>NSResizingMask</key>
+			<integer>3</integer>
+			<key>NSTableView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSWidth</key>
+			<real>341</real>
+		</dict>
+		<string>value</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>36</integer>
+			</dict>
+			<key>NSBackgroundColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>30</integer>
+			</dict>
+			<key>NSCellFlags</key>
+			<integer>75628032</integer>
+			<key>NSCellFlags2</key>
+			<integer>0</integer>
+			<key>NSContents</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>47</integer>
+			</dict>
+			<key>NSSupport</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>27</integer>
+			</dict>
+			<key>NSTextColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>32</integer>
+			</dict>
+		</dict>
+		<string>Value</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>42</integer>
+			</dict>
+			<key>NSBackgroundColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>39</integer>
+			</dict>
+			<key>NSCellFlags</key>
+			<integer>338820672</integer>
+			<key>NSCellFlags2</key>
+			<integer>1024</integer>
+			<key>NSControlView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSSupport</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>38</integer>
+			</dict>
+			<key>NSTextColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>40</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSMutableArray</string>
+				<string>NSArray</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSMutableArray</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSCatalogName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>33</integer>
+			</dict>
+			<key>NSColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>52</integer>
+			</dict>
+			<key>NSColorName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>51</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>6</integer>
+		</dict>
+		<string>gridColor</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>3</integer>
+			<key>NSWhite</key>
+			<data>
+			MC41AA==
+			</data>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSTableView</string>
+				<string>%NSTableView</string>
+				<string>NSControl</string>
+				<string>NSView</string>
+				<string>NSResponder</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSTableView</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>4</integer>
+			</dict>
+			<key>NSClassName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>55</integer>
+			</dict>
+		</dict>
+		<string>InspectorTableViewDataSource</string>
+		<string>dataSource</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSNibOutletConnector</string>
+				<string>NSNibConnector</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSNibOutletConnector</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>59</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>61</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>4</integer>
+			</dict>
+			<key>NSClassName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>60</integer>
+			</dict>
+		</dict>
+		<string>InspectorTableViewDelegate</string>
+		<string>delegate</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>65</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>106</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>63</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>4</integer>
+			</dict>
+			<key>NSClassName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>64</integer>
+			</dict>
+		</dict>
+		<string>InspectorBrowserDelegate</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>105</integer>
+			</dict>
+			<key>NSMaxSize</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>104</integer>
+			</dict>
+			<key>NSMinSize</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>103</integer>
+			</dict>
+			<key>NSScreenRect</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>102</integer>
+			</dict>
+			<key>NSViewClass</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>69</integer>
+			</dict>
+			<key>NSWTFlags</key>
+			<integer>1881669632</integer>
+			<key>NSWindowBacking</key>
+			<integer>2</integer>
+			<key>NSWindowClass</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>68</integer>
+			</dict>
+			<key>NSWindowRect</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>66</integer>
+			</dict>
+			<key>NSWindowStyleMask</key>
+			<integer>14</integer>
+			<key>NSWindowTitle</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>67</integer>
+			</dict>
+			<key>NSWindowView</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>70</integer>
+			</dict>
+		</dict>
+		<string>{{91, 144}, {582, 563}}</string>
+		<string>OpenMCL Inspector</string>
+		<string>NSWindow</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>6</integer>
+			</dict>
+			<key>NS.string</key>
+			<string>View</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>101</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>100</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>0</integer>
+			</dict>
+			<key>NSSubviews</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>71</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>49</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>72</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>19</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>81</integer>
+			</dict>
+			<key>NSBrFlags</key>
+			<integer>403783680</integer>
+			<key>NSCellPrototype</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>76</integer>
+			</dict>
+			<key>NSClassName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>73</integer>
+			</dict>
+			<key>NSColumnResizingType</key>
+			<integer>1</integer>
+			<key>NSEnabled</key>
+			<true/>
+			<key>NSFirstColumnTitle</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>80</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>75</integer>
+			</dict>
+			<key>NSMaxNumberOfVisibleColumns</key>
+			<integer>3</integer>
+			<key>NSMinColumnWidth</key>
+			<integer>1</integer>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>70</integer>
+			</dict>
+			<key>NSNumberOfVisibleColumns</key>
+			<integer>3</integer>
+			<key>NSOriginalClassName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>74</integer>
+			</dict>
+			<key>NSPathSeparator</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>79</integer>
+			</dict>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>70</integer>
+			</dict>
+			<key>NSvFlags</key>
+			<integer>274</integer>
+		</dict>
+		<string>InspectorNSBrowser</string>
+		<string>NSBrowser</string>
+		<string>{{20, 268}, {542, 275}}</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>78</integer>
+			</dict>
+			<key>NSCellFlags</key>
+			<integer>67239488</integer>
+			<key>NSCellFlags2</key>
+			<integer>1024</integer>
+			<key>NSContents</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>77</integer>
+			</dict>
+			<key>NSSupport</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>38</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>6</integer>
+			</dict>
+			<key>NS.string</key>
+			<string>BrowserItem</string>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSBrowserCell</string>
+				<string>NSCell</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSBrowserCell</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>6</integer>
+			</dict>
+			<key>NS.string</key>
+			<string>/</string>
+		</dict>
+		<string>Inspect:</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSClassSwapper</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSClassSwapper</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>49</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>12</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>89</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>93</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>15</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>18</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>49</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>11</integer>
+				</dict>
+			</array>
+		</dict>
+		<string>{{1, 17}, {525, 193}}</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSCatalogName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>33</integer>
+			</dict>
+			<key>NSColor</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>87</integer>
+			</dict>
+			<key>NSColorName</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>86</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>6</integer>
+		</dict>
+		<string>controlBackgroundColor</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>31</integer>
+			</dict>
+			<key>NSColorSpace</key>
+			<integer>3</integer>
+			<key>NSWhite</key>
+			<data>
+			MC42NjY2NjY2OQA=
+			</data>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSClipView</string>
+				<string>NSView</string>
+				<string>NSResponder</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSClipView</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>92</integer>
+			</dict>
+			<key>NSAction</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>91</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>90</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSPercent</key>
+			<real>0.95263159275054932</real>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSTarget</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSvFlags</key>
+			<integer>256</integer>
+		</dict>
+		<string>{{526, 17}, {15, 193}}</string>
+		<string>_doScroller:</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSScroller</string>
+				<string>NSControl</string>
+				<string>NSView</string>
+				<string>NSResponder</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSScroller</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>92</integer>
+			</dict>
+			<key>NSAction</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>95</integer>
+			</dict>
+			<key>NSFrame</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>94</integer>
+			</dict>
+			<key>NSNextResponder</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSPercent</key>
+			<real>0.99047619104385376</real>
+			<key>NSSuperview</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSTarget</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>19</integer>
+			</dict>
+			<key>NSsFlags</key>
+			<integer>1</integer>
+			<key>NSvFlags</key>
+			<integer>256</integer>
+		</dict>
+		<string>{{1, 210}, {525, 15}}</string>
+		<string>_doScroller:</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>49</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>14</integer>
+				</dict>
+			</array>
+		</dict>
+		<string>{{1, 0}, {525, 17}}</string>
+		<string>{{20, 20}, {542, 226}}</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSScrollView</string>
+				<string>NSView</string>
+				<string>NSResponder</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSScrollView</string>
+		</dict>
+		<string>{{1, 9}, {582, 563}}</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSView</string>
+				<string>NSResponder</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSView</string>
+		</dict>
+		<string>{{0, 0}, {1280, 1002}}</string>
+		<string>{582, 585}</string>
+		<string>{3.40282e+38, 3.40282e+38}</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSWindowTemplate</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSWindowTemplate</string>
+		</dict>
+		<string>inspectorWindow</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>65</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>108</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>54</integer>
+			</dict>
+		</dict>
+		<string>inspectorWindow</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>65</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>110</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>59</integer>
+			</dict>
+		</dict>
+		<string>inspectorWindow</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>65</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>112</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<string>window</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>2</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>114</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>65</integer>
+			</dict>
+		</dict>
+		<string>delegate</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>72</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>116</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>54</integer>
+			</dict>
+		</dict>
+		<string>inspectorBrowser</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>63</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>118</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>72</integer>
+			</dict>
+		</dict>
+		<string>delegate</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>121</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>63</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>120</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>72</integer>
+			</dict>
+		</dict>
+		<string>browserAction:</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSNibControlConnector</string>
+				<string>NSNibConnector</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSNibControlConnector</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>72</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>123</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<string>inspectorBrowser</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>57</integer>
+			</dict>
+			<key>NSDestination</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>11</integer>
+			</dict>
+			<key>NSLabel</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>125</integer>
+			</dict>
+			<key>NSSource</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>63</integer>
+			</dict>
+		</dict>
+		<string>inspectorTableView</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>63</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>44</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>70</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>54</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>11</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>59</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>65</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>23</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>19</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>72</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSArray</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSArray</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>2</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>11</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>65</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>2</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>19</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>2</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>2</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>11</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>70</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>70</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>63</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>44</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>54</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>11</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>59</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>65</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>23</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>19</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>72</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>2</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>64</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>131</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>55</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>132</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>60</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>133</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>134</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>135</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>136</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>137</integer>
+				</dict>
+			</array>
+		</dict>
+		<string>NSTableColumn1</string>
+		<string>NSTableView</string>
+		<string>Window</string>
+		<string>NSTableColumn</string>
+		<string>NSScrollView1</string>
+		<string>NSBrowser1</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>6</integer>
+			</dict>
+			<key>NS.string</key>
+			<string>File's Owner</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>72</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>73</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>58</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>122</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>72</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>70</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>109</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>62</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>115</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>63</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>107</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>113</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>54</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>19</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>11</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>111</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>65</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>10</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>117</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>119</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>44</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>23</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>59</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>124</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>2</integer>
+				</dict>
+			</array>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>142</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>143</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>144</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>145</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>146</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>147</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>148</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>149</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>150</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>151</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>152</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>153</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>154</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>155</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>156</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>157</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>158</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>159</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>160</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>161</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>162</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>163</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>164</integer>
+				</dict>
+			</array>
+		</dict>
+		<integer>254</integer>
+		<integer>274</integer>
+		<integer>234</integer>
+		<integer>2</integer>
+		<integer>257</integer>
+		<integer>255</integer>
+		<integer>264</integer>
+		<integer>249</integer>
+		<integer>256</integer>
+		<integer>263</integer>
+		<integer>250</integer>
+		<integer>238</integer>
+		<integer>236</integer>
+		<integer>262</integer>
+		<integer>21</integer>
+		<integer>253</integer>
+		<integer>265</integer>
+		<integer>272</integer>
+		<integer>237</integer>
+		<integer>235</integer>
+		<integer>251</integer>
+		<integer>275</integer>
+		<integer>1</integer>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>49</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array/>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array/>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>127</integer>
+			</dict>
+			<key>NS.objects</key>
+			<array/>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSIBObjectData</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSIBObjectData</string>
+		</dict>
+	</array>
+	<key>$top</key>
+	<dict>
+		<key>IB.objectdata</key>
+		<dict>
+			<key>CF$UID</key>
+			<integer>1</integer>
+		</dict>
+	</dict>
+	<key>$version</key>
+	<integer>100000</integer>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/ProgressWindow.nib/designable.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/ProgressWindow.nib/designable.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/ProgressWindow.nib/designable.nib	(revision 13309)
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9D34</string>
+		<string key="IBDocument.InterfaceBuilderVersion">667</string>
+		<string key="IBDocument.AppKitVersion">949.33</string>
+		<string key="IBDocument.HIToolboxVersion">352.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="2"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">ProgressWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">257</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 415}, {426, 95}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Progress</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSProgressIndicator" id="737951180">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">1292</int>
+							<object class="NSPSMatrix" key="NSDrawMatrix"/>
+							<string key="NSFrame">{{18, 16}, {390, 20}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<int key="NSpiFlags">16394</int>
+							<double key="NSMinValue">2.000000e+01</double>
+							<double key="NSMaxValue">1.000000e+02</double>
+						</object>
+						<object class="NSTextField" id="697868892">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 44}, {392, 31}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="875141224">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">4456448</int>
+								<string key="NSContents">Running a time-consuming process...</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<reference key="NSControlView" ref="697868892"/>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{426, 95}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">6</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">messageField</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="697868892"/>
+					</object>
+					<int key="connectionID">7</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">progressBar</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="737951180"/>
+					</object>
+					<int key="connectionID">8</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">progressWindow</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">9</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="697868892"/>
+							<reference ref="737951180"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="737951180"/>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="697868892"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="875141224"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="875141224"/>
+						<reference key="parent" ref="697868892"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>2.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>5.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{225, 987}, {426, 95}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{225, 987}, {426, 95}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">9</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">ProgressWindowController</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>messageField</string>
+							<string>progressBar</string>
+							<string>progressWindow</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/SearchFiles.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/SearchFiles.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/SearchFiles.nib/classes.nib	(revision 13309)
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>CLASS</key>
+			<string>NSObject</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+		</dict>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>doBrowse</key>
+				<string>id</string>
+				<key>doSearch</key>
+				<string>id</string>
+				<key>editLine</key>
+				<string>id</string>
+				<key>expandResults</key>
+				<string>id</string>
+				<key>toggleCheckbox</key>
+				<string>id</string>
+				<key>updateFileNameString</key>
+				<string>id</string>
+				<key>updateFindString</key>
+				<string>id</string>
+				<key>updateFolderString</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>SearchFilesWindowController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>browseButton</key>
+				<string>id</string>
+				<key>caseSensitiveCheckbox</key>
+				<string>id</string>
+				<key>expandResultsCheckbox</key>
+				<string>id</string>
+				<key>fileNameComboBox</key>
+				<string>id</string>
+				<key>findComboBox</key>
+				<string>id</string>
+				<key>folderComboBox</key>
+				<string>id</string>
+				<key>outlineView</key>
+				<string>id</string>
+				<key>progressIndicator</key>
+				<string>id</string>
+				<key>recursiveCheckbox</key>
+				<string>id</string>
+				<key>searchButton</key>
+				<string>id</string>
+				<key>statusField</key>
+				<string>id</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSWindowController</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/SearchFiles.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/SearchFiles.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/SearchFiles.nib/info.nib	(revision 13309)
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBLastKnownRelativeProjectPath</key>
+	<string>../SearchFiles.xcodeproj</string>
+	<key>IBOldestOS</key>
+	<integer>4</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>1</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9J61</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/apropos.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/apropos.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/apropos.nib/classes.nib	(revision 13309)
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>apropos</key>
+				<string>id</string>
+				<key>definitionForSelectedSymbol</key>
+				<string>id</string>
+				<key>inspectSelectedSymbol</key>
+				<string>id</string>
+				<key>setPackage</key>
+				<string>id</string>
+				<key>toggleShowsExternalSymbols</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>AproposWindowController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>arrayController</key>
+				<string>id</string>
+				<key>comboBox</key>
+				<string>id</string>
+				<key>externalSymbolsCheckbox</key>
+				<string>id</string>
+				<key>tableView</key>
+				<string>id</string>
+				<key>textView</key>
+				<string>id</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSWindowController</string>
+		</dict>
+		<dict>
+			<key>CLASS</key>
+			<string>PackageComboBox</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>dataSource</key>
+				<string>id</string>
+			</dict>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/apropos.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/apropos.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/apropos.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>629</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>133</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9C31</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/backtrace.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/backtrace.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/backtrace.nib/classes.nib	(revision 13309)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>CLASS</key>
+			<string>BacktraceWindowController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>outlineView</key>
+				<string>id</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSWindowController</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/backtrace.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/backtrace.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/backtrace.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBOldestOS</key>
+	<integer>4</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>5</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9J61</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/displaydoc.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/displaydoc.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/displaydoc.nib/classes.nib	(revision 13309)
@@ -0,0 +1,11 @@
+{
+    IBClasses = (
+        {
+            CLASS = DisplayDocument; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {textView = NSTextView; }; 
+            SUPERCLASS = NSDocument; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/displaydoc.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/displaydoc.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/displaydoc.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBDocumentLocation</key>
+	<string>152 222 356 240 0 0 1280 1002 </string>
+	<key>IBFramework Version</key>
+	<string>446.1</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBSystem Version</key>
+	<string>8P135</string>
+	<key>IBUsesTextArchiving</key>
+	<true/>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/inspector.nib/designable.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/inspector.nib/designable.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/inspector.nib/designable.nib	(revision 13309)
@@ -0,0 +1,1035 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.01">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9C7010</string>
+		<string key="IBDocument.InterfaceBuilderVersion">629</string>
+		<string key="IBDocument.AppKitVersion">949.26</string>
+		<string key="IBDocument.HIToolboxVersion">352.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="2"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string id="932358225">com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName" id="263787258">NinspectorWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{69, 234}, {403, 582}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Inspector</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">274</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSButton" id="1046811461">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{7, 558}, {27, 19}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="263420327">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents" id="552579010"/>
+								<object class="NSFont" key="NSSupport" id="966272341">
+									<string key="NSName" id="537056312">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="1046811461"/>
+								<int key="NSButtonFlags">-2033434369</int>
+								<int key="NSButtonFlags2">162</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName" id="521469324">NSImage</string>
+									<string key="NSResourceName">NSGoLeftTemplate</string>
+								</object>
+								<reference key="NSAlternateContents" ref="552579010"/>
+								<reference key="NSKeyEquivalent" ref="552579010"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+						</object>
+						<object class="NSButton" id="188747413">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{33, 558}, {27, 19}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="559929339">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">134217728</int>
+								<reference key="NSContents" ref="552579010"/>
+								<reference key="NSSupport" ref="966272341"/>
+								<reference key="NSControlView" ref="188747413"/>
+								<int key="NSButtonFlags">-2033434369</int>
+								<int key="NSButtonFlags2">162</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<reference key="NSClassName" ref="521469324"/>
+									<string key="NSResourceName">NSGoRightTemplate</string>
+								</object>
+								<reference key="NSAlternateContents" ref="552579010"/>
+								<reference key="NSKeyEquivalent" ref="552579010"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+						</object>
+						<object class="NSButton" id="661433680">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{64, 558}, {27, 19}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="796817393">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">134217728</int>
+								<reference key="NSContents" ref="552579010"/>
+								<reference key="NSSupport" ref="966272341"/>
+								<reference key="NSControlView" ref="661433680"/>
+								<int key="NSButtonFlags">-2033434369</int>
+								<int key="NSButtonFlags2">162</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<reference key="NSClassName" ref="521469324"/>
+									<string key="NSResourceName">NSRefreshTemplate</string>
+								</object>
+								<reference key="NSAlternateContents" ref="552579010"/>
+								<reference key="NSKeyEquivalent" ref="552579010"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+						</object>
+						<object class="NSScrollView" id="1050284761">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">274</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="33275616">
+									<reference key="NSNextResponder" ref="1050284761"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSTableView" id="699675964">
+											<reference key="NSNextResponder" ref="33275616"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{401, 533}</string>
+											<reference key="NSSuperview" ref="33275616"/>
+											<reference key="NSWindow"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSTableHeaderView" key="NSHeaderView" id="696835943">
+												<reference key="NSNextResponder" ref="626883526"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrameSize">{401, 17}</string>
+												<reference key="NSSuperview" ref="626883526"/>
+												<reference key="NSWindow"/>
+												<reference key="NSTableView" ref="699675964"/>
+											</object>
+											<object class="_NSCornerView" key="NSCornerView" id="562088563">
+												<reference key="NSNextResponder" ref="1050284761"/>
+												<int key="NSvFlags">-2147483392</int>
+												<string key="NSFrame">{{-26, 0}, {16, 17}}</string>
+												<reference key="NSSuperview" ref="1050284761"/>
+												<reference key="NSWindow"/>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="827838550">
+													<string key="NSIdentifier">property</string>
+													<double key="NSWidth">1.430000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Property</string>
+														<object class="NSFont" key="NSSupport" id="26">
+															<reference key="NSName" ref="537056312"/>
+															<double key="NSSize">1.100000e+01</double>
+															<int key="NSfFlags">3100</int>
+														</object>
+														<object class="NSColor" key="NSBackgroundColor" id="596541048">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="447086878">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName" id="396511679">System</string>
+															<string key="NSColorName">headerTextColor</string>
+															<object class="NSColor" key="NSColor" id="1045629268">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MAA</bytes>
+															</object>
+														</object>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="939744502">
+														<int key="NSCellFlags">69336641</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents" id="432928006">Text Cell</string>
+														<object class="NSFont" key="NSSupport" id="960709355">
+															<reference key="NSName" ref="537056312"/>
+															<double key="NSSize">1.100000e+01</double>
+															<int key="NSfFlags">16</int>
+														</object>
+														<reference key="NSControlView" ref="699675964"/>
+														<object class="NSColor" key="NSBackgroundColor" id="666092395">
+															<int key="NSColorSpace">6</int>
+															<reference key="NSCatalogName" ref="396511679"/>
+															<string key="NSColorName">controlBackgroundColor</string>
+															<object class="NSColor" key="NSColor" id="878022769">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+															</object>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="1059708885">
+															<int key="NSColorSpace">6</int>
+															<reference key="NSCatalogName" ref="396511679"/>
+															<string key="NSColorName">controlTextColor</string>
+															<reference key="NSColor" ref="1045629268"/>
+														</object>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="699675964"/>
+												</object>
+												<object class="NSTableColumn" id="939975622">
+													<string key="NSIdentifier">value</string>
+													<double key="NSWidth">2.520000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Value</string>
+														<reference key="NSSupport" ref="26"/>
+														<reference key="NSBackgroundColor" ref="596541048"/>
+														<reference key="NSTextColor" ref="447086878"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="745407270">
+														<int key="NSCellFlags">69336641</int>
+														<int key="NSCellFlags2">2048</int>
+														<reference key="NSContents" ref="432928006"/>
+														<reference key="NSSupport" ref="960709355"/>
+														<reference key="NSControlView" ref="699675964"/>
+														<reference key="NSBackgroundColor" ref="666092395"/>
+														<reference key="NSTextColor" ref="1059708885"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="699675964"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<object class="NSColor" key="NSBackgroundColor">
+												<int key="NSColorSpace">3</int>
+												<bytes key="NSWhite">MQA</bytes>
+											</object>
+											<object class="NSColor" key="NSGridColor">
+												<int key="NSColorSpace">6</int>
+												<reference key="NSCatalogName" ref="396511679"/>
+												<string key="NSColorName">gridColor</string>
+												<object class="NSColor" key="NSColor">
+													<int key="NSColorSpace">3</int>
+													<bytes key="NSWhite">MC41AA</bytes>
+												</object>
+											</object>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-692060160</int>
+											<int key="NSColumnAutoresizingStyle">4</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">YES</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{1, 17}, {401, 533}}</string>
+									<reference key="NSSuperview" ref="1050284761"/>
+									<reference key="NSWindow"/>
+									<reference key="NSNextKeyView" ref="699675964"/>
+									<reference key="NSDocView" ref="699675964"/>
+									<reference key="NSBGColor" ref="666092395"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="188058522">
+									<reference key="NSNextResponder" ref="1050284761"/>
+									<int key="NSvFlags">-2147483392</int>
+									<string key="NSFrame">{{558, 17}, {15, 533}}</string>
+									<reference key="NSSuperview" ref="1050284761"/>
+									<reference key="NSWindow"/>
+									<reference key="NSTarget" ref="1050284761"/>
+									<string key="NSAction" id="627650989">_doScroller:</string>
+									<double key="NSCurValue">1.000000e+00</double>
+									<double key="NSPercent">9.593810e-01</double>
+								</object>
+								<object class="NSScroller" id="166330445">
+									<reference key="NSNextResponder" ref="1050284761"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{-100, -100}, {496, 15}}</string>
+									<reference key="NSSuperview" ref="1050284761"/>
+									<reference key="NSWindow"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="1050284761"/>
+									<reference key="NSAction" ref="627650989"/>
+									<double key="NSPercent">4.444444e-01</double>
+								</object>
+								<object class="NSClipView" id="626883526">
+									<reference key="NSNextResponder" ref="1050284761"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<reference ref="696835943"/>
+									</object>
+									<string key="NSFrame">{{1, 0}, {401, 17}}</string>
+									<reference key="NSSuperview" ref="1050284761"/>
+									<reference key="NSWindow"/>
+									<reference key="NSNextKeyView" ref="696835943"/>
+									<reference key="NSDocView" ref="696835943"/>
+									<reference key="NSBGColor" ref="666092395"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<reference ref="562088563"/>
+							</object>
+							<string key="NSFrameSize">{403, 551}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="33275616"/>
+							<int key="NSsFlags">530</int>
+							<reference key="NSVScroller" ref="188058522"/>
+							<reference key="NSHScroller" ref="166330445"/>
+							<reference key="NSContentView" ref="33275616"/>
+							<reference key="NSHeaderClipView" ref="626883526"/>
+							<reference key="NSCornerView" ref="562088563"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+						<object class="NSTextField" id="92487250">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">270</int>
+							<string key="NSFrame">{{96, 559}, {567, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="327978265">
+								<int key="NSCellFlags">67239488</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Object</string>
+								<reference key="NSSupport" ref="966272341"/>
+								<reference key="NSControlView" ref="92487250"/>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<reference key="NSCatalogName" ref="396511679"/>
+									<string key="NSColorName">controlColor</string>
+									<reference key="NSColor" ref="878022769"/>
+								</object>
+								<reference key="NSTextColor" ref="1059708885"/>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{403, 582}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
+			</object>
+			<object class="NSUserDefaultsController" id="121326553">
+				<bool key="NSSharedInstance">YES</bool>
+			</object>
+			<object class="NSMenu" id="324029823">
+				<string key="NSTitle">contextual</string>
+				<object class="NSMutableArray" key="NSMenuItems">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMenuItem" id="338485557">
+						<reference key="NSMenu" ref="324029823"/>
+						<string key="NSTitle">Inspect in new window</string>
+						<reference key="NSKeyEquiv" ref="552579010"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<object class="NSCustomResource" key="NSOnImage" id="752789933">
+							<reference key="NSClassName" ref="521469324"/>
+							<string key="NSResourceName">NSMenuCheckmark</string>
+						</object>
+						<object class="NSCustomResource" key="NSMixedImage" id="720614561">
+							<reference key="NSClassName" ref="521469324"/>
+							<string key="NSResourceName">NSMenuMixedState</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="680662745">
+						<reference key="NSMenu" ref="324029823"/>
+						<string key="NSTitle">Inspect in new tab</string>
+						<reference key="NSKeyEquiv" ref="552579010"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="752789933"/>
+						<reference key="NSMixedImage" ref="720614561"/>
+					</object>
+					<object class="NSMenuItem" id="452619578">
+						<reference key="NSMenu" ref="324029823"/>
+						<string key="NSTitle">Edit source</string>
+						<reference key="NSKeyEquiv" ref="552579010"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="752789933"/>
+						<reference key="NSMixedImage" ref="720614561"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="699675964"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">125</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="876511053">propertyColumn</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="827838550"/>
+					</object>
+					<int key="connectionID">126</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="269546785">valueColumn</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="939975622"/>
+					</object>
+					<int key="connectionID">127</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="292914283">objectLabel</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="92487250"/>
+					</object>
+					<int key="connectionID">128</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="942462872">tableView</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="699675964"/>
+					</object>
+					<int key="connectionID">129</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="811034402">backButton</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1046811461"/>
+					</object>
+					<int key="connectionID">138</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="1050957050">forwardButton</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="188747413"/>
+					</object>
+					<int key="connectionID">139</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="451528378">refreshButton</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="661433680"/>
+					</object>
+					<int key="connectionID">144</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">menu</string>
+						<reference key="source" ref="1050284761"/>
+						<reference key="destination" ref="324029823"/>
+					</object>
+					<int key="connectionID">145</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="663328529">itemMenu</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="324029823"/>
+					</object>
+					<int key="connectionID">146</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="290101077">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">147</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1046811461"/>
+							<reference ref="188747413"/>
+							<reference ref="1050284761"/>
+							<reference ref="92487250"/>
+							<reference ref="661433680"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">57</int>
+						<reference key="object" ref="1046811461"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="263420327"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">58</int>
+						<reference key="object" ref="263420327"/>
+						<reference key="parent" ref="1046811461"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">59</int>
+						<reference key="object" ref="188747413"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="559929339"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">60</int>
+						<reference key="object" ref="559929339"/>
+						<reference key="parent" ref="188747413"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">112</int>
+						<reference key="object" ref="1050284761"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="188058522"/>
+							<reference ref="166330445"/>
+							<reference ref="699675964"/>
+							<reference ref="696835943"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">113</int>
+						<reference key="object" ref="188058522"/>
+						<reference key="parent" ref="1050284761"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">114</int>
+						<reference key="object" ref="166330445"/>
+						<reference key="parent" ref="1050284761"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">115</int>
+						<reference key="object" ref="699675964"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="827838550"/>
+							<reference ref="939975622"/>
+						</object>
+						<reference key="parent" ref="1050284761"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">116</int>
+						<reference key="object" ref="696835943"/>
+						<reference key="parent" ref="1050284761"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">117</int>
+						<reference key="object" ref="827838550"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="939744502"/>
+						</object>
+						<reference key="parent" ref="699675964"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">118</int>
+						<reference key="object" ref="939975622"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="745407270"/>
+						</object>
+						<reference key="parent" ref="699675964"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">119</int>
+						<reference key="object" ref="745407270"/>
+						<reference key="parent" ref="939975622"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">120</int>
+						<reference key="object" ref="939744502"/>
+						<reference key="parent" ref="827838550"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">121</int>
+						<reference key="object" ref="92487250"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="327978265"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">122</int>
+						<reference key="object" ref="327978265"/>
+						<reference key="parent" ref="92487250"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">133</int>
+						<reference key="object" ref="121326553"/>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">61</int>
+						<reference key="object" ref="661433680"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="796817393"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">62</int>
+						<reference key="object" ref="796817393"/>
+						<reference key="parent" ref="661433680"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">140</int>
+						<reference key="object" ref="324029823"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="338485557"/>
+							<reference ref="680662745"/>
+							<reference ref="452619578"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">141</int>
+						<reference key="object" ref="338485557"/>
+						<reference key="parent" ref="324029823"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">142</int>
+						<reference key="object" ref="680662745"/>
+						<reference key="parent" ref="324029823"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">143</int>
+						<reference key="object" ref="452619578"/>
+						<reference key="parent" ref="324029823"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBViewEditorWindowController.showingLayoutRectangles</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>112.IBPluginDependency</string>
+					<string>113.IBPluginDependency</string>
+					<string>114.IBPluginDependency</string>
+					<string>115.IBPluginDependency</string>
+					<string>116.IBPluginDependency</string>
+					<string>117.IBPluginDependency</string>
+					<string>118.IBPluginDependency</string>
+					<string>119.IBPluginDependency</string>
+					<string>120.IBPluginDependency</string>
+					<string>121.IBPluginDependency</string>
+					<string>122.IBPluginDependency</string>
+					<string>140.IBPluginDependency</string>
+					<string>140.editorWindowContentRectSynchronizationRect</string>
+					<string>141.IBPluginDependency</string>
+					<string>142.IBPluginDependency</string>
+					<string>143.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>57.IBPluginDependency</string>
+					<string>58.IBPluginDependency</string>
+					<string>59.IBPluginDependency</string>
+					<string>60.IBPluginDependency</string>
+					<string>61.IBPluginDependency</string>
+					<string>62.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<integer value="1" id="9"/>
+					<string>{{94, 274}, {403, 582}}</string>
+					<reference ref="9"/>
+					<string>{196, 240}</string>
+					<string>{{94, 274}, {403, 582}}</string>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<string>{{0, 599}, {223, 63}}</string>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+					<reference ref="932358225"/>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">147</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">NSButton</string>
+					<nil key="superclassName"/>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey" id="962584955">IBUserSource</string>
+						<reference key="minorKey" ref="552579010"/>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<reference key="className" ref="263787258"/>
+					<nil key="superclassName"/>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="811034402"/>
+							<reference ref="1050957050"/>
+							<reference ref="663328529"/>
+							<reference ref="292914283"/>
+							<reference ref="876511053"/>
+							<reference ref="451528378"/>
+							<reference ref="942462872"/>
+							<reference ref="269546785"/>
+							<reference ref="290101077"/>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string id="1069139689">id</string>
+							<reference ref="1069139689"/>
+							<reference ref="1069139689"/>
+							<reference ref="1069139689"/>
+							<reference ref="1069139689"/>
+							<reference ref="1069139689"/>
+							<reference ref="1069139689"/>
+							<reference ref="1069139689"/>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<reference key="majorKey" ref="962584955"/>
+						<reference key="minorKey" ref="552579010"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableData" key="IBDocument.RunnableNib">
+			<bytes key="NS.bytes">YnBsaXN0MDDUAAEAAgADAAQABQAGAAkAClgkdmVyc2lvblQkdG9wWSRhcmNoaXZlclgkb2JqZWN0cxIA
+AYag0QAHAAhdSUIub2JqZWN0ZGF0YYABXxAPTlNLZXllZEFyY2hpdmVyrxDkAAsADAAxADUANgA8AD0A
+QgBWAFcAWABZAAsAZgBuAHoAewCVAJYAngCfAKIApwCoAKkArACwALYAvgC/AMcAywDMANQA1QDdAOEA
+4gD5AQEBEAEUATMBNAE8AUYBRwFKAVEBUgFVAVoBbQFuAXYBdwF8AYEBhAGMAY0BjgGRAZUBngGfAaMB
+qAGpAawBsQGyAbQBtwG/AcABxgHHAc4B0gHVAdoB2wHeAeAB4QHkAfIB8wH0AfcCAQICAgYCBwIIAgsC
+FAIVAh4CHwIkAiUCKAALAikCKwIsAi8CMwJBAkkCSgJOAlMCVAJZAloCXwJgAmUCZgJrAmwCcQJ3AngC
+fgKNAo4CkgKTApcCmAKbAqICowKqAqsCrQKuArMCtAK5AroCvwLAAsUCxgLiAuUC5gLqAu4C8AMMAykD
+RgNHA0gDSQNKA0sDTANNA04DTwNQA1EDUgNTA1QDVQNWA1cDWANZA1oDWwNcA10DXgNfA2ADYwNmA44D
+tgO3A7gAUwO5A7oDuwO8A70DvgH8A78DwAPBA8IDwwPEA8UDxgPHA8gDyQPKA8sDzAPNA84DzwPQA9ED
+0gPTA9QD1QPWA9cD2APZA9wD3wPiVSRudWxs3xASAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAb
+ABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwVk5TUm9vdFYkY2xhc3NdTlNP
+YmplY3RzS2V5c18QD05TQ2xhc3Nlc1ZhbHVlc18QGU5TQWNjZXNzaWJpbGl0eU9pZHNWYWx1ZXNdTlND
+b25uZWN0aW9uc1tOU05hbWVzS2V5c1tOU0ZyYW1ld29ya11OU0NsYXNzZXNLZXlzWk5TT2lkc0tleXNd
+TlNOYW1lc1ZhbHVlc18QGU5TQWNjZXNzaWJpbGl0eUNvbm5lY3RvcnNdTlNGb250TWFuYWdlcl8QEE5T
+VmlzaWJsZVdpbmRvd3NfEA9OU09iamVjdHNWYWx1ZXNfEBdOU0FjY2Vzc2liaWxpdHlPaWRzS2V5c1lO
+U05leHRPaWRcTlNPaWRzVmFsdWVzgAKA44CUgLiA4oBtgJuABYC3gLmAnIDggACABoCagOEQlYC60gAO
+ADIAMwA0W05TQ2xhc3NOYW1lgASAA18QGk5pbnNwZWN0b3JXaW5kb3dDb250cm9sbGVy0gA3ADgAOQA6
+WCRjbGFzc2VzWiRjbGFzc25hbWWiADoAO15OU0N1c3RvbU9iamVjdFhOU09iamVjdF8QEElCQ29jb2FG
+cmFtZXdvcmvSAA4APgA/AEBaTlMub2JqZWN0c4BsoQBBgAfaAEMADgBEAEUARgBHAEgASQBKAEsATABN
+AE4ATwBQAFEAUgBTAFQAK1xOU1dpbmRvd1ZpZXdcTlNTY3JlZW5SZWN0XU5TV2luZG93VGl0bGVZTlNX
+VEZsYWdzXU5TV2luZG93Q2xhc3NcTlNXaW5kb3dSZWN0XxAPTlNXaW5kb3dCYWNraW5nXxARTlNXaW5k
+b3dTdHlsZU1hc2tbTlNWaWV3Q2xhc3OAC4BrgGqACRIgAAAAgAqACBACEA+AAF8QF3t7NjksIDIzNH0s
+IHs0MDMsIDU4Mn19WUluc3BlY3RvclhOU1dpbmRvd9cAWgAOAFsAXABdAFgAXgBfAGAAYQBiAGMAXwBl
+XxAPTlNOZXh0UmVzcG9uZGVyWk5TU3Vidmlld3NYTlN2RmxhZ3NbTlNGcmFtZVNpemVbTlNTdXBlcnZp
+ZXeADIBpgA0RARKAZ4AMgGjSAA4APgBnAGiATqUAaQBqAGsAbABtgA6AG4AggCWAYNgAWgAOAG8AcABc
+AHEAWABeAEwAcwB0AHUAdgB3AF8ATFdOU0ZyYW1lVk5TQ2VsbFlOU0VuYWJsZWSAC4AagA+AEBEBDAmA
+DIALXxAUe3s3LCA1NTh9LCB7MjcsIDE5fX3dAHwADgB9AH4AfwCAAIEAggCDAIQAhQCGAIcAiACJAIoA
+iwCMAI0AigCKAJAAaQCSAJMAlFtOU0NlbGxGbGFnc18QE05TQWx0ZXJuYXRlQ29udGVudHNdTlNOb3Jt
+YWxJbWFnZV8QEk5TUGVyaW9kaWNJbnRlcnZhbF5OU0J1dHRvbkZsYWdzMl8QD05TS2V5RXF1aXZhbGVu
+dFpOU0NvbnRlbnRzWU5TU3VwcG9ydF1OU0NvbnRyb2xWaWV3XxAPTlNQZXJpb2RpY0RlbGF5XE5TQ2Vs
+bEZsYWdzMl1OU0J1dHRvbkZsYWdzE/////+EAf4AgBmAEYAVEEsQooARgBGAEoAOEQGQEggAAAAT////
+/4bMQP9Q1AAOAJcAmACZAJoAmwCcAJ1WTlNTaXplVk5TTmFtZVhOU2ZGbGFnc4AUI0AqAAAAAAAAgBMR
+BBRcTHVjaWRhR3JhbmRl0gA3ADgAoAChogChADtWTlNGb2500wAOADIAowCkAKUApl5OU1Jlc291cmNl
+TmFtZYAYgBaAF1dOU0ltYWdlXxAQTlNHb0xlZnRUZW1wbGF0ZdIANwA4AKoAq6IAqwA7XxAQTlNDdXN0
+b21SZXNvdXJjZdIANwA4AK0ArqQArgCvAHAAO1xOU0J1dHRvbkNlbGxcTlNBY3Rpb25DZWxs0gA3ADgA
+sQCypQCyALMAtAC1ADtYTlNCdXR0b25ZTlNDb250cm9sVk5TVmlld1tOU1Jlc3BvbmRlctgAWgAOAG8A
+cABcAHEAWABeAEwAcwC5ALoAdgB3AF8ATIALgBqAHIAdCYAMgAtfEBV7ezMzLCA1NTh9LCB7MjcsIDE5
+fX3dAHwADgB9AH4AfwCAAIEAggCDAIQAhQCGAIcAiACJAIoAwgCMAI0AigCKAJAAagCSAJMAlIAZgBGA
+HoARgBGAEoAb0wAOADIAowCkAKUAyoAYgBaAH18QEU5TR29SaWdodFRlbXBsYXRl2ABaAA4AbwBwAFwA
+cQBYAF4ATABzAM8A0AB2AHcAXwBMgAuAGoAhgCIJgAyAC18QFXt7NjQsIDU1OH0sIHsyNywgMTl9fd0A
+fAAOAH0AfgB/AIAAgQCCAIMAhACFAIYAhwCIAIkAigDYAIwAjQCKAIoAkABrAJIAkwCUgBmAEYAjgBGA
+EYASgCDTAA4AMgCjAKQApQDggBiAFoAkXxARTlNSZWZyZXNoVGVtcGxhdGXfEA8AWgDjAA4A5ADlAOYA
+WwDnAFwAXQBYAF4A6ADpAOoATADsAO0A7gDvAPAA8QDyAGIA8wBfAEwA9gD3APdbTlNIU2Nyb2xsZXJY
+TlNzRmxhZ3NcTlNDb3JuZXJWaWV3XxAQTlNIZWFkZXJDbGlwVmlld1xOU1Njcm9sbEFtdHNbTlNWU2Ny
+b2xsZXJdTlNOZXh0S2V5Vmlld11OU0NvbnRlbnRWaWV3gAuAWoBfEQISgC+ALIAmTxAQQSAAAEEgAABB
+mAAAQZgAAIBegAyAC4BWgCeAJ9IADgA+AGcA+4BOpQD3APYA7ADwAO+AJ4BWgFqALIAv2wBaAA4AbwEC
+AFsAXAEDAFgBBABeAOkAbAEGAQcBCAEJAQoBCwBfAQ0AbAELWU5TY3ZGbGFnc1lOU0RvY1ZpZXdZTlNC
+R0NvbG9ygCWAVYBUEASAKBEJAIApgAyAQoAlgCnSAA4APgBnARKATqEBC4Ap3xAUAFoBFQAOARYBFwEY
+ARkA5QEaARsBHABcAF0AcQBYAR0BHgBeAR8BIAD3ASIBIwEkASUBJgB3AO8BKQEIASoBKwEsAHcAXwEv
+AFQA9wExATJfEB9OU0RyYWdnaW5nU291cmNlTWFza0Zvck5vbkxvY2FsWU5TVHZGbGFnc1xOU0hlYWRl
+clZpZXdfEBFOU0JhY2tncm91bmRDb2xvcl8QEk5TQWxsb3dzVHlwZVNlbGVjdF8QF05TSW50ZXJjZWxs
+U3BhY2luZ1dpZHRoXxAZTlNDb2x1bW5BdXRvcmVzaXppbmdTdHlsZV8QGE5TSW50ZXJjZWxsU3BhY2lu
+Z0hlaWdodFtOU0dyaWRDb2xvcl8QHE5TRHJhZ2dpbmdTb3VyY2VNYXNrRm9yTG9jYWxeTlNUYWJsZUNv
+bHVtbnNbTlNSb3dIZWlnaHSAJxAAgFMT/////9bAAACAK4BPCYAvI0AIAAAAAAAAI0AAAAAAAAAAEQEA
+gCoJgAyAUIAngDIjQDEAAAAAAABaezQwMSwgNTMzfdcAWgAOAFwAXQBYAF4BNQDwATcBKwE4AF8A8AEL
+W05TVGFibGVWaWV3gCyALoAtgAyALIAp2wBaAA4AbwECAFsAXAEDAFgBBABeAOkAbAEGAT8BCAFAAQoB
+JQBfAQ0AbAElgCWAVYBdgFyAK4AMgEKAJYArWXs0MDEsIDE3fdIANwA4AUgBSaQBSQC0ALUAO18QEU5T
+VGFibGVIZWFkZXJWaWV31gBaAA4AbwBcAFgAXgBsAUwBTQFOAF8AbIAlgDGAMBP/////gAABAIAMgCVf
+EBR7ey0yNiwgMH0sIHsxNiwgMTd9fdIANwA4AVMBVKQBVAC0ALUAO11fTlNDb3JuZXJWaWV30gAOAD4A
+ZwFXgE6iAVgBWYAzgEnaAVsADgFcAV0BXgFfAWABYQFiATUAdwFkAWUBZgFnAWgBaQFqAWsBC15OU0lz
+UmVzaXplYWJsZVxOU0hlYWRlckNlbGxcTlNJZGVudGlmaWVyV05TV2lkdGhaTlNEYXRhQ2VsbF5OU1Jl
+c2l6aW5nTWFza1pOU01pbldpZHRoWk5TTWF4V2lkdGgJgEiANYA0I0Bh4AAAAAAAgD8QAyNARAAAAAAA
+ACNAj0AAAAAAAIApWHByb3BlcnR51wB8AA4BGACCAIMAhgFvAXABcQFyAXMBdAEiAXVbTlNUZXh0Q29s
+b3ISBIH+AIA+gDiANoA3gDpYUHJvcGVydHnUAA4AlwCYAJkAmgF5AJwBe4AUI0AmAAAAAAAAgBMRDBzT
+AA4BfQF+AX8BaQGAXE5TQ29sb3JTcGFjZVdOU1doaXRlgDlLMC4zMzMzMzI5OQDSADcAOAGCAYOiAYMA
+O1dOU0NvbG9y1QAOAYMBfQGFAYYBfwGIAYkBigGLW05TQ29sb3JOYW1lXU5TQ2F0YWxvZ05hbWWAOYA9
+EAaAPIA7VlN5c3RlbV8QD2hlYWRlclRleHRDb2xvctMADgF9AX4BfwFpAZCAOUIwANIANwA4AZIBk6UB
+kwGUAK8AcAA7XxARTlNUYWJsZUhlYWRlckNlbGxfEA9OU1RleHRGaWVsZENlbGzYAHwADgEYAIIAgwCE
+AIYBbwGWAZcBDQGZAZoBCwGcAZ0SBCH+QYBHgEKAQIBBgCkRCACARVlUZXh0IENlbGzUAA4AlwCYAJkA
+mgF5AJwBooAUgBMQENUADgGDAX0BhQGGAX8BpQGJAaYBi4A5gESAQ4A7XxAWY29udHJvbEJhY2tncm91
+bmRDb2xvctMADgF9AX4BfwFpAauAOUswLjY2NjY2NjY5ANUADgGDAX0BhQGGAX8BiAGJAa8Bi4A5gD2A
+RoA7XxAQY29udHJvbFRleHRDb2xvctIANwA4AbMBlKQBlACvAHAAO9IANwA4AbUBtqIBtgA7XU5TVGFi
+bGVDb2x1bW7aAVsADgFcAV0BXgFfAWABYQFiATUAdwFkAboBuwG8Ab0BaQFqAWsBCwmASIBLgEojQG+A
+AAAAAACATYApVXZhbHVl1wB8AA4BGACCAIMAhgFvAXABcQFyAcMBdAEiAXWAPoA4gEyAN4A6VVZhbHVl
+2AB8AA4BGACCAIMAhACGAW8BlgGXAQ0BmQGaAQsBnAGdgEeAQoBAgEGAKYBF0gA3ADgBzwHQowHQAdEA
+O15OU011dGFibGVBcnJheVdOU0FycmF50wAOAX0BfgF/AWkB1IA5QjEA1QAOAYMBfQGFAYYBfwHXAYkB
+2AGLgDmAUoBRgDtZZ3JpZENvbG9y0wAOAX0BfgF/AWkB3YA5RDAuNQDSADcAOAHfATWlATUAswC0ALUA
+O18QFXt7MSwgMTd9LCB7NDAxLCA1MzN9fdIANwA4AeIB46QB4wC0ALUAO1pOU0NsaXBWaWV32gBaAeUA
+DgBvAFwAWAHmAF4B5wHoAGwAbAHrAewBTgBfAe4AbAHwAfFYTlNUYXJnZXRYTlNBY3Rpb25aTlNDdXJW
+YWx1ZVlOU1BlcmNlbnSAJYAlgFmAV4AMgFiAJSM/8AAAAAAAACM/7rM/wAAAAF8QFnt7NTU4LCAxN30s
+IHsxNSwgNTMzfX1cX2RvU2Nyb2xsZXI60gA3ADgB9QH2pQH2ALMAtAC1ADtaTlNTY3JvbGxlctoAWgHl
+AA4AbwDkAFwAWAHmAF4B6ABsAGwB6wH7AfwBKwBfAe4AbAIAgCWAJYBZgFsQAYAMgFiAJSM/3HHG4AAA
+AF8QGXt7LTEwMCwgLTEwMH0sIHs0OTYsIDE1fX3SAA4APgBnAgSATqEBJYArXxATe3sxLCAwfSwgezQw
+MSwgMTd9fVp7NDAzLCA1NTF90gA3ADgCCQIKpAIKALQAtQA7XE5TU2Nyb2xsVmlld9gAWgAOAG8AcABc
+AHEAWABeAEwCDQIOAg8CEAB3AF8ATIALgGaAYYBiEQEOCYAMgAtfEBZ7ezk2LCA1NTl9LCB7NTY3LCAx
+N3192AB8AA4BGACCAIMAhACGAW8CFgGXAhgCGQCQAG0CHAGdEgQB/kCAR4BkgGOAEoBgEhBABACARVZP
+YmplY3TVAA4BgwF9AYUBhgF/AaUBiQIiAYuAOYBEgGWAO1xjb250cm9sQ29sb3LSADcAOAImAielAicA
+swC0ALUAO1tOU1RleHRGaWVsZFp7NDAzLCA1ODJ90gA3ADgCKgC0owC0ALUAO18QFXt7MCwgMH0sIHsx
+NDQwLCA4Nzh9fdIANwA4Ai0CLqICLgA7XxAQTlNXaW5kb3dUZW1wbGF0ZdIANwA4AjACMaMCMQIyADtc
+TlNNdXRhYmxlU2V0VU5TU2V00gAOAD4AZwI1gE6rAjYCNwI4AjkCOgI7AjwCPQI+Aj8CQIBugHGAc4B1
+gHeAeYB7gIyAjoCQgJLUAA4CQgJDAkQCRQELAB8CSF1OU0Rlc3RpbmF0aW9uWE5TU291cmNlV05TTGFi
+ZWyAcIApgAKAb1l0YWJsZVZpZXfSADcAOAJLAkyjAkwCTQA7XxAUTlNOaWJPdXRsZXRDb25uZWN0b3Je
+TlNOaWJDb25uZWN0b3LUAA4CQgJDAkQCRQBBAB8CUoBwgAeAAoByVndpbmRvd9QADgJCAkMCRAJFAVkA
+HwJYgHCASYACgHRbdmFsdWVDb2x1bW7UAA4CQgJDAkQCRQBrAB8CXoBwgCCAAoB2XXJlZnJlc2hCdXR0
+b27UAA4CQgJDAkQCRQBtAB8CZIBwgGCAAoB4W29iamVjdExhYmVs1AAOAkICQwJEAkUAaQAfAmqAcIAO
+gAKAelpiYWNrQnV0dG9u1AAOAkICQwJEAkUCbgAfAnCAcIB8gAKAi9MADgJyAnMCdAJ1AnZXTlNUaXRs
+ZVtOU01lbnVJdGVtc4CKgH2Aflpjb250ZXh0dWFs0gAOAD4AZwJ6gE6jAnsCfAJ9gH+AhoCI2AAOAnIC
+fwKAAoECggKDAoQChQKGAocAigKJAooCiwJuXxARTlNLZXlFcXVpdk1vZE1hc2taTlNLZXlFcXVpdl1O
+U01uZW1vbmljTG9jWU5TT25JbWFnZVxOU01peGVkSW1hZ2VWTlNNZW51gIWAgBIAEAAAgBESf////4CB
+gIOAfF8QFUluc3BlY3QgaW4gbmV3IHdpbmRvd9MADgAyAKMApAClApGAGIAWgIJfEA9OU01lbnVDaGVj
+a21hcmvTAA4AMgCjAKQApQKWgBiAFoCEXxAQTlNNZW51TWl4ZWRTdGF0ZdIANwA4ApkCmqICmgA7Wk5T
+TWVudUl0ZW3YAA4CcgJ/AoACgQKCAoMChAKFAp0ChwCKAokCigKLAm6AhYCHgBGAgYCDgHxfEBJJbnNw
+ZWN0IGluIG5ldyB0YWLYAA4CcgJ/AoACgQKCAoMChAKFAqUChwCKAokCigKLAm6AhYCJgBGAgYCDgHxb
+RWRpdCBzb3VyY2XSADcAOAKsAoSiAoQAO1hpdGVtTWVuddQADgJCAkMCRAJFAB8BCwKygHCAAoApgI1a
+ZGF0YVNvdXJjZdQADgJCAkMCRAJFAm4AbAK4gHCAfIAlgI9UbWVuddQADgJCAkMCRAJFAVgAHwK+gHCA
+M4ACgJFecHJvcGVydHlDb2x1bW7UAA4CQgJDAkQCRQBqAB8CxIBwgBuAAoCTXWZvcndhcmRCdXR0b27S
+AA4APgLHAsiAma8QGQFYAOwATALMAHUBvQFoAEEAagBrAPYA0AJ9Am4CewBtAGkAugJ8AGwBWQLeAg8B
+CwElgDOAWoALgJWAEIBNgD+AB4AbgCCAVoAigIiAfIB/gGCADoAdgIaAJYBJgJeAYoApgCvSAA4AMgAz
+AuSABICWXU5TQXBwbGljYXRpb27SAA4C5wLoAHdfEBBOU1NoYXJlZEluc3RhbmNlgJgJ0gA3ADgC6wLs
+owLsAu0AO18QGE5TVXNlckRlZmF1bHRzQ29udHJvbGxlclxOU0NvbnRyb2xsZXLSADcAOALvAdGiAdEA
+O9IADgA+AscC8oCZrxAZAQsAbABBAB8AaQFZAVgAHwBMAEwAbABrAm4AHwJuAEwATABqAm4ATAELAB8A
+bQBsAGyAKYAlgAeAAoAOgEmAM4ACgAuAC4AlgCCAfIACgHyAC4ALgBuAfIALgCmAAoBggCWAJdIADgA+
+AscDDoCZrxAaAVgA7ALMAEwAdQG9AWgAQQAfAGoAawDQAPYCfQJuAnsCfABtAGkAugBsAt4BWQIPAQsB
+JYAzgFqAlYALgBCATYA/gAeAAoAbgCCAIoBWgIiAfIB/gIaAYIAOgB2AJYCXgEmAYoApgCvSAA4APgLH
+AyuAma8QGgMsAy0DLgMvAzADMQMyAzMDNAM1AzYDNwM4AzkDOgM7AzwDPQM+Az8DQANBA0IDQwNEA0WA
+nYCegJ+AoIChgKKAo4CkgKWApoCngKiAqYCqgKuArICtgK6Ar4CwgLGAsoCzgLSAtYC2XxAXVGFibGUg
+Q29sdW1uIChwcm9wZXJ0eSlfEBNIb3Jpem9udGFsIFNjcm9sbGVyW0FwcGxpY2F0aW9uXENvbnRlbnQg
+Vmlld18QHkJ1dHRvbiBDZWxsIChOU0dvTGVmdFRlbXBsYXRlKV8QHVRleHQgRmllbGQgQ2VsbCAoVGV4
+dCBDZWxsKS0xXxAbVGV4dCBGaWVsZCBDZWxsIChUZXh0IENlbGwpXxASV2luZG93IChJbnNwZWN0b3Ip
+XEZpbGUncyBPd25lcl8QGlNxdWFyZSAoTlNHb1JpZ2h0VGVtcGxhdGUpXxAaU3F1YXJlIChOU1JlZnJl
+c2hUZW1wbGF0ZSlfEB9CdXR0b24gQ2VsbCAoTlNSZWZyZXNoVGVtcGxhdGUpXxARVmVydGljYWwgU2Ny
+b2xsZXJfEBdNZW51IEl0ZW0gKEVkaXQgc291cmNlKV8QEU1lbnUgKGNvbnRleHR1YWwpXxAhTWVudSBJ
+dGVtIChJbnNwZWN0IGluIG5ldyB3aW5kb3cpXxAeTWVudSBJdGVtIChJbnNwZWN0IGluIG5ldyB0YWIp
+XxAUU3RhdGljIFRleHQgKE9iamVjdClfEBlTcXVhcmUgKE5TR29MZWZ0VGVtcGxhdGUpXxAfQnV0dG9u
+IENlbGwgKE5TR29SaWdodFRlbXBsYXRlKVtTY3JvbGwgVmlld18QH1NoYXJlZCBVc2VyIERlZmF1bHRz
+IENvbnRyb2xsZXJfEBRUYWJsZSBDb2x1bW4gKHZhbHVlKV8QGFRleHQgRmllbGQgQ2VsbCAoT2JqZWN0
+KV8QHFRhYmxlIFZpZXcgKFByb3BlcnR5LCBWYWx1ZSlfEBFUYWJsZSBIZWFkZXIgVmlld9IADgA+AscD
+YoCZoNIADgA+AscDZYCZoNIADgA+AscDaICZrxAlAVgA7ALMAEwAdQG9Aj0CQAI3AWgAQQAfAGoAawD2
+ANACfQJuAjsCNgI8Aj4CPwJ7AjoAbQBpALoCfAI4AGwCOQFZAt4CDwELASWAM4BagJWAC4AQgE2AjICS
+gHGAP4AHgAKAG4AggFaAIoCIgHyAeYBugHuAjoCQgH+Ad4BggA6AHYCGgHOAJYB1gEmAl4BigCmAK9IA
+DgA+AscDkICZrxAlA5EDkgOTA5QDlQOWA5cDmAOZA5oDmwOcA50DngOfA6ADoQOiA6MDpAOlA6YDpwOo
+A6kDqgOrA6wDrQOuA68DsAOxA7IDswO0A7WAu4C8gL2AvoC/gMCAwYDCgMOAxIDFgMaAx4DIgMmAyoDL
+gMyAzYDOgM+A0IDRgNKA04DUgNWA1oDXgNiA2YDagNuA3IDdgN6A3xB1EHIT//////////0QOhB3EH0Q
+ixCTEHgQlBA7ED0QcRA+EI8QjBCKEIEQkhCREH4QjRCAEHkQORA8EI4QfxBwEJAQdhCFEHoQcxB00gAO
+AD4AZwPbgE6g0gAOAD4CxwPegJmg0gAOAD4CxwPhgJmg0gA3ADgD4wPkogPkADteTlNJQk9iamVjdERh
+dGEACAAZACIAJwAxADoAPwBEAFIAVABmAjECNwKCAokCkAKeArACzALaAuYC8gMAAwsDGQM1A0MDVgNo
+A4IDjAOZA5sDnQOfA6EDowOlA6cDqQOrA60DrwOxA7MDtQO3A7kDuwO9A8YD0gPUA9YD8wP8BAUEEAQV
+BCQELQRABEkEVARWBFkEWwSEBJEEngSsBLYExATRBOME9wUDBQUFBwUJBQsFEAUSBRQFFgUYBRoFNAU+
+BUcFZAV2BYEFigWWBaIFpAWmBagFqwWtBa8FsQW6BbwFxwXJBcsFzQXPBdEF8gX6BgEGCwYNBg8GEQYT
+BhYGFwYZBhsGMgZnBnMGiQaXBqwGuwbNBtgG4gbwBwIHDwcdByYHKAcqBywHLgcwBzIHNAc2BzgHOwdA
+B0kHSgdbB2IHaQdyB3QHfQd/B4IHjweYB50HpAexB8AHwgfEB8YHzgfhB+oH7wgCCAsIFAghCC4INwhC
+CEsIVQhcCGgIiQiLCI0IjwiRCJIIlAiWCK4I4wjlCOcI6QjrCO0I7wjxCP4JAAkCCQQJGAk5CTsJPQk/
+CUEJQglECUYJXgmTCZUJlwmZCZsJnQmfCaEJrgmwCbIJtAnICgcKEwocCikKPApJClUKYwpxCnMKdQp3
+CnoKfAp+CoAKkwqVCpcKmQqbCp0KnwqoCqoKtQq3CrkKuwq9Cr8K7Ar2CwALCgsMCw4LEAsSCxQLFwsZ
+CxsLHQsfCyELKgssCy8LMQuEC6YLsAu9C9EL5gwADBwMNwxDDGIMcQx9DH8MgQyDDIwMjgyQDJEMkwyc
+DKUMqAyqDKsMrQyvDLEMswy8DMcM5AzwDPIM9Az2DPgM+gz8DSkNKw0tDS8NMQ0zDTUNNw05DTsNRQ1O
+DVcNaw2EDYYNiA2KDZMNlQ2XDa4Ntw3ADc4N1w3ZDd4N4A3iDgsOGg4nDjQOPA5HDlYOYQ5sDm0Obw5x
+DnMOfA5+DoAOiQ6SDpQOnQ66DsYOyw7NDs8O0Q7TDtUO3g7vDvEO+g78Dv8PDA8ZDyEPIw8vDzgPPQ9F
+D1oPZg90D3YPeA96D3wPfg+FD5cPpA+mD6kPsg+9D9EP4xAEEAkQCxANEA8QERATEBYQGBAiEDMQNRA3
+EDkQThBQEFIQVBBWEG8QfBB+EIoQnxChEKMQpRCnELoQwxDMENUQ2hDoEREREhEUERYRGBEhESMRJREr
+EUgRShFMEU4RUBFSEVgReRF7EX0RfxGBEYMRhRGOEZURpBGsEbkRuxG+EdMR1RHXEdkR2xHlEfIR9BH5
+EgISDRIlEi4SNxJCEmsSdBJ9EogSkhKUEpYSmBKaEpwSnhKgEqkSshLLEtgS4RLsEvcTIBMiEyQTJhMo
+EyoTLBMuEzATORNVE14TYBNjE2UTexOGE48TmBOlE8YTyBPKE8wTzhPRE9IT1BPWE+8UEBQVFBcUGRQb
+FB0UHxQkFCYULRRCFEQURhRIFEoUVxRgFGsUdxSCFIsUkhSqFLMUuBTLFNQU2xToFO4U9xT5FRAVEhUU
+FRYVGBUaFRwVHhUgFSIVJBUmFTcVRRVOFVYVWBVaFVwVXhVoFXEVeBWPFZ4VrxWxFbMVtRW3Fb4VzxXR
+FdMV1RXXFeMV9BX2FfgV+hX8FgoWGxYdFh8WIRYjFi8WQBZCFkQWRhZIFlMWZBZmFmgWahZsFnkWgRaN
+Fo8WkRaTFp4WpxapFrAWsha0FrYW1xbrFvYXBBcOFxsXIhckFyYXKxctFzIXNBc2FzgXUBddF18XYRdj
+F3UXgheEF4YXiBebF6QXqRe0F9UX1xfZF9sX3RffF+EX9hgXGBkYGxgdGB8YIRgjGC8YOBg9GEYYVxhZ
+GFsYXRhfGGoYexh9GH8YgRiDGIgYmRibGJ0YnxihGLAYwRjDGMUYxxjJGNcY4BjiGRcZGRkbGR0ZHxkh
+GSMZJRknGSkZKxktGS8ZMRkzGTUZNxk5GTsZPRk/GUEZQxlFGUcZSRlSGVQZVhlkGW0ZgBmCGYMZjBmT
+Ga4ZuxnEGckZ0hnUGgkaCxoNGg8aERoTGhUaFxoZGhsaHRofGiEaIxolGicaKRorGi0aLxoxGjMaNRo3
+GjkaOxpEGkYafRp/GoEagxqFGocaiRqLGo0ajxqRGpMalRqXGpkamxqdGp8aoRqjGqUapxqpGqsarRqv
+GrEauhq8GvMa9Rr3Gvka+xr9Gv8bARsDGwUbBxsJGwsbDRsPGxEbExsVGxcbGRsbGx0bHxshGyMbJRsn
+G0EbVxtjG3AbkRuxG88b5BvxHA4cKxxNHGEcexyPHLMc1BzrHQcdKR01HVcdbh2JHagdvB3FHccdyB3R
+HdMd1B3dHd8eLB4uHjAeMh40HjYeOB46HjwePh5AHkIeRB5GHkgeSh5MHk4eUB5SHlQeVh5YHloeXB5e
+HmAeYh5kHmYeaB5qHmwebh5wHnIedB52Hn8egR7OHtAe0h7UHtYe2B7aHtwe3h7gHuIe5B7mHuge6h7s
+Hu4e8B7yHvQe9h74Hvoe/B7+HwAfAh8EHwYfCB8KHwwfDh8QHxIfFB8WHxgfGh8cHyUfJx8pHysfLR8v
+HzEfMx81HzcfOR87Hz0fPx9BH0MfRR9HH0kfSx9NH08fUR9TH1UfVx9ZH1sfXR9fH2EfYx9lH24fcB9x
+H3offB99H4YfiB+JH5IflwAAAAAAAAICAAAAAAAAA+UAAAAAAAAAAAAAAAAAAB+mA</bytes>
+		</object>
+	</data>
+</archive>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/preferences.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/preferences.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/preferences.nib/classes.nib	(revision 13309)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>showFontPanel</key>
+				<string>id</string>
+				<key>startSwankListener</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>PreferencesWindowController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>appearancePrefs</key>
+				<string>id</string>
+				<key>documentationPrefs</key>
+				<string>id</string>
+				<key>editorTabViewItem</key>
+				<string>id</string>
+				<key>encodingsPrefs</key>
+				<string>id</string>
+				<key>generalPrefs</key>
+				<string>id</string>
+				<key>hyperspecURLButton</key>
+				<string>id</string>
+				<key>listenerFontName</key>
+				<string>id</string>
+				<key>listenerTabViewItem</key>
+				<string>id</string>
+				<key>swankListenerPort</key>
+				<string>id</string>
+				<key>tabView</key>
+				<string>id</string>
+				<key>window</key>
+				<string>id</string>
+			</dict>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/preferences.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/preferences.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/preferences.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBOldestOS</key>
+	<integer>4</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>1500949</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9G55</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/processes.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/processes.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/processes.nib/classes.nib	(revision 13309)
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>killSelectedProcess</key>
+				<string>id</string>
+				<key>refresh</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>ProcessesWindowController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>tableView</key>
+				<string>NSTableView</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSWindowController</string>
+		</dict>
+		<dict>
+			<key>CLASS</key>
+			<string>FirstResponder</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/processes.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/processes.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/processes.nib/info.nib	(revision 13309)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>628</string>
+	<key>IBOldestOS</key>
+	<integer>4</integer>
+	<key>IBOpenObjects</key>
+	<array/>
+	<key>IBSystem Version</key>
+	<string>9A559</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/project.nib/designable.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/project.nib/designable.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/project.nib/designable.nib	(revision 13309)
@@ -0,0 +1,1891 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">10B504</string>
+		<string key="IBDocument.InterfaceBuilderVersion">740</string>
+		<string key="IBDocument.AppKitVersion">1038.2</string>
+		<string key="IBDocument.HIToolboxVersion">437.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">740</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="79"/>
+			<integer value="172"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys" id="0">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="842755916">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="938498879">
+				<string key="NSClassName">ProjectWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="700062780">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="960468241">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="875229309">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{64, 228}, {276, 495}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Project</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
+				<string key="NSWindowContentMinSize">{145, 185}</string>
+				<object class="NSView" key="NSWindowView" id="241404708">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSSplitView" id="884315936">
+							<reference key="NSNextResponder" ref="241404708"/>
+							<int key="NSvFlags">274</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSCustomView" id="1045904718">
+									<reference key="NSNextResponder" ref="884315936"/>
+									<int key="NSvFlags">256</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSScrollView" id="728387647">
+											<reference key="NSNextResponder" ref="1045904718"/>
+											<int key="NSvFlags">274</int>
+											<object class="NSMutableArray" key="NSSubviews">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSClipView" id="356540428">
+													<reference key="NSNextResponder" ref="728387647"/>
+													<int key="NSvFlags">2304</int>
+													<object class="NSMutableArray" key="NSSubviews">
+														<bool key="EncodedWithXMLCoder">YES</bool>
+														<object class="NSTableView" id="165534007">
+															<reference key="NSNextResponder" ref="356540428"/>
+															<int key="NSvFlags">256</int>
+															<string key="NSFrameSize">{274, 157}</string>
+															<reference key="NSSuperview" ref="356540428"/>
+															<bool key="NSEnabled">YES</bool>
+															<object class="_NSCornerView" key="NSCornerView">
+																<nil key="NSNextResponder"/>
+																<int key="NSvFlags">256</int>
+																<string key="NSFrame">{{260, 0}, {16, 17}}</string>
+															</object>
+															<object class="NSMutableArray" key="NSTableColumns">
+																<bool key="EncodedWithXMLCoder">YES</bool>
+																<object class="NSTableColumn" id="677500492">
+																	<double key="NSWidth">271</double>
+																	<double key="NSMinWidth">40</double>
+																	<double key="NSMaxWidth">1000</double>
+																	<object class="NSTableHeaderCell" key="NSHeaderCell">
+																		<int key="NSCellFlags">75628096</int>
+																		<int key="NSCellFlags2">2048</int>
+																		<string key="NSContents"/>
+																		<object class="NSFont" key="NSSupport" id="26">
+																			<string key="NSName">LucidaGrande</string>
+																			<double key="NSSize">11</double>
+																			<int key="NSfFlags">3100</int>
+																		</object>
+																		<object class="NSColor" key="NSBackgroundColor">
+																			<int key="NSColorSpace">3</int>
+																			<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+																		</object>
+																		<object class="NSColor" key="NSTextColor" id="250115164">
+																			<int key="NSColorSpace">6</int>
+																			<string key="NSCatalogName">System</string>
+																			<string key="NSColorName">headerTextColor</string>
+																			<object class="NSColor" key="NSColor" id="272665718">
+																				<int key="NSColorSpace">3</int>
+																				<bytes key="NSWhite">MAA</bytes>
+																			</object>
+																		</object>
+																	</object>
+																	<object class="NSTextFieldCell" key="NSDataCell" id="554466692">
+																		<int key="NSCellFlags">337772096</int>
+																		<int key="NSCellFlags2">2048</int>
+																		<string key="NSContents">Text Cell</string>
+																		<object class="NSFont" key="NSSupport" id="419050269">
+																			<string key="NSName">LucidaGrande</string>
+																			<double key="NSSize">13</double>
+																			<int key="NSfFlags">1044</int>
+																		</object>
+																		<reference key="NSControlView" ref="165534007"/>
+																		<object class="NSColor" key="NSBackgroundColor" id="149682232">
+																			<int key="NSColorSpace">6</int>
+																			<string key="NSCatalogName">System</string>
+																			<string key="NSColorName">controlBackgroundColor</string>
+																			<object class="NSColor" key="NSColor" id="824193269">
+																				<int key="NSColorSpace">3</int>
+																				<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+																			</object>
+																		</object>
+																		<object class="NSColor" key="NSTextColor" id="714951766">
+																			<int key="NSColorSpace">6</int>
+																			<string key="NSCatalogName">System</string>
+																			<string key="NSColorName">controlTextColor</string>
+																			<reference key="NSColor" ref="272665718"/>
+																		</object>
+																	</object>
+																	<int key="NSResizingMask">3</int>
+																	<bool key="NSIsResizeable">YES</bool>
+																	<reference key="NSTableView" ref="165534007"/>
+																</object>
+															</object>
+															<double key="NSIntercellSpacingWidth">3</double>
+															<double key="NSIntercellSpacingHeight">2</double>
+															<object class="NSColor" key="NSBackgroundColor">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MQA</bytes>
+															</object>
+															<object class="NSColor" key="NSGridColor" id="400948380">
+																<int key="NSColorSpace">6</int>
+																<string key="NSCatalogName">System</string>
+																<string key="NSColorName">gridColor</string>
+																<object class="NSColor" key="NSColor">
+																	<int key="NSColorSpace">3</int>
+																	<bytes key="NSWhite">MC41AA</bytes>
+																</object>
+															</object>
+															<double key="NSRowHeight">17</double>
+															<int key="NSTvFlags">-1035993088</int>
+															<reference key="NSDelegate"/>
+															<reference key="NSDataSource"/>
+															<int key="NSColumnAutoresizingStyle">4</int>
+															<int key="NSDraggingSourceMaskForLocal">15</int>
+															<int key="NSDraggingSourceMaskForNonLocal">0</int>
+															<bool key="NSAllowsTypeSelect">YES</bool>
+															<int key="NSTableViewDraggingDestinationStyle">0</int>
+														</object>
+													</object>
+													<string key="NSFrame">{{1, 1}, {274, 157}}</string>
+													<reference key="NSSuperview" ref="728387647"/>
+													<reference key="NSNextKeyView" ref="165534007"/>
+													<reference key="NSDocView" ref="165534007"/>
+													<reference key="NSBGColor" ref="149682232"/>
+													<int key="NScvFlags">4</int>
+												</object>
+												<object class="NSScroller" id="226775687">
+													<reference key="NSNextResponder" ref="728387647"/>
+													<int key="NSvFlags">-2147483392</int>
+													<string key="NSFrame">{{260, 1}, {15, 182}}</string>
+													<reference key="NSSuperview" ref="728387647"/>
+													<reference key="NSTarget" ref="728387647"/>
+													<string key="NSAction">_doScroller:</string>
+													<double key="NSPercent">0.99456518888473511</double>
+												</object>
+												<object class="NSScroller" id="724124208">
+													<reference key="NSNextResponder" ref="728387647"/>
+													<int key="NSvFlags">-2147483392</int>
+													<string key="NSFrame">{{1, 183}, {259, 15}}</string>
+													<reference key="NSSuperview" ref="728387647"/>
+													<int key="NSsFlags">1</int>
+													<reference key="NSTarget" ref="728387647"/>
+													<string key="NSAction">_doScroller:</string>
+													<double key="NSPercent">0.99615383148193359</double>
+												</object>
+											</object>
+											<string key="NSFrameSize">{276, 159}</string>
+											<reference key="NSSuperview" ref="1045904718"/>
+											<reference key="NSNextKeyView" ref="356540428"/>
+											<int key="NSsFlags">562</int>
+											<reference key="NSVScroller" ref="226775687"/>
+											<reference key="NSHScroller" ref="724124208"/>
+											<reference key="NSContentView" ref="356540428"/>
+											<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+										</object>
+									</object>
+									<string key="NSFrameSize">{276, 159}</string>
+									<reference key="NSSuperview" ref="884315936"/>
+									<string key="NSClassName">NSView</string>
+								</object>
+								<object class="NSCustomView" id="489362485">
+									<reference key="NSNextResponder" ref="884315936"/>
+									<int key="NSvFlags">256</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSScrollView" id="797734369">
+											<reference key="NSNextResponder" ref="489362485"/>
+											<int key="NSvFlags">274</int>
+											<object class="NSMutableArray" key="NSSubviews">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSClipView" id="136896699">
+													<reference key="NSNextResponder" ref="797734369"/>
+													<int key="NSvFlags">2304</int>
+													<object class="NSMutableArray" key="NSSubviews">
+														<bool key="EncodedWithXMLCoder">YES</bool>
+														<object class="NSOutlineView" id="933218413">
+															<reference key="NSNextResponder" ref="136896699"/>
+															<int key="NSvFlags">256</int>
+															<string key="NSFrameSize">{274, 325}</string>
+															<reference key="NSSuperview" ref="136896699"/>
+															<bool key="NSEnabled">YES</bool>
+															<object class="_NSCornerView" key="NSCornerView">
+																<nil key="NSNextResponder"/>
+																<int key="NSvFlags">-2147483392</int>
+																<string key="NSFrame">{{262, 0}, {16, 17}}</string>
+															</object>
+															<object class="NSMutableArray" key="NSTableColumns">
+																<bool key="EncodedWithXMLCoder">YES</bool>
+																<object class="NSTableColumn" id="75976626">
+																	<double key="NSWidth">272</double>
+																	<double key="NSMinWidth">16</double>
+																	<double key="NSMaxWidth">1000</double>
+																	<object class="NSTableHeaderCell" key="NSHeaderCell">
+																		<int key="NSCellFlags">75628096</int>
+																		<int key="NSCellFlags2">2048</int>
+																		<string key="NSContents"/>
+																		<reference key="NSSupport" ref="26"/>
+																		<object class="NSColor" key="NSBackgroundColor">
+																			<int key="NSColorSpace">3</int>
+																			<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+																		</object>
+																		<reference key="NSTextColor" ref="250115164"/>
+																	</object>
+																	<object class="NSTextFieldCell" key="NSDataCell" id="466455816">
+																		<int key="NSCellFlags">337772096</int>
+																		<int key="NSCellFlags2">2048</int>
+																		<string key="NSContents">Text Cell</string>
+																		<reference key="NSSupport" ref="419050269"/>
+																		<reference key="NSControlView" ref="933218413"/>
+																		<reference key="NSBackgroundColor" ref="149682232"/>
+																		<reference key="NSTextColor" ref="714951766"/>
+																	</object>
+																	<int key="NSResizingMask">3</int>
+																	<bool key="NSIsResizeable">YES</bool>
+																	<reference key="NSTableView" ref="933218413"/>
+																</object>
+															</object>
+															<double key="NSIntercellSpacingWidth">2</double>
+															<double key="NSIntercellSpacingHeight">3</double>
+															<reference key="NSBackgroundColor" ref="149682232"/>
+															<reference key="NSGridColor" ref="400948380"/>
+															<double key="NSRowHeight">17</double>
+															<int key="NSTvFlags">-767557632</int>
+															<reference key="NSDelegate"/>
+															<reference key="NSDataSource"/>
+															<int key="NSColumnAutoresizingStyle">4</int>
+															<int key="NSDraggingSourceMaskForLocal">15</int>
+															<int key="NSDraggingSourceMaskForNonLocal">0</int>
+															<bool key="NSAllowsTypeSelect">YES</bool>
+															<int key="NSTableViewDraggingDestinationStyle">0</int>
+														</object>
+													</object>
+													<string key="NSFrame">{{1, 1}, {274, 325}}</string>
+													<reference key="NSSuperview" ref="797734369"/>
+													<reference key="NSNextKeyView" ref="933218413"/>
+													<reference key="NSDocView" ref="933218413"/>
+													<reference key="NSBGColor" ref="149682232"/>
+													<int key="NScvFlags">6</int>
+												</object>
+												<object class="NSScroller" id="288789385">
+													<reference key="NSNextResponder" ref="797734369"/>
+													<int key="NSvFlags">-2147483392</int>
+													<string key="NSFrame">{{262, 1}, {15, 480}}</string>
+													<reference key="NSSuperview" ref="797734369"/>
+													<reference key="NSTarget" ref="797734369"/>
+													<string key="NSAction">_doScroller:</string>
+													<double key="NSPercent">0.96969699859619141</double>
+												</object>
+												<object class="NSScroller" id="1055463008">
+													<reference key="NSNextResponder" ref="797734369"/>
+													<int key="NSvFlags">-2147483392</int>
+													<string key="NSFrame">{{1, 481}, {261, 15}}</string>
+													<reference key="NSSuperview" ref="797734369"/>
+													<int key="NSsFlags">1</int>
+													<reference key="NSTarget" ref="797734369"/>
+													<string key="NSAction">_doScroller:</string>
+													<double key="NSPercent">0.6904761791229248</double>
+												</object>
+											</object>
+											<string key="NSFrameSize">{276, 327}</string>
+											<reference key="NSSuperview" ref="489362485"/>
+											<reference key="NSNextKeyView" ref="136896699"/>
+											<int key="NSsFlags">562</int>
+											<reference key="NSVScroller" ref="288789385"/>
+											<reference key="NSHScroller" ref="1055463008"/>
+											<reference key="NSContentView" ref="136896699"/>
+											<bytes key="NSScrollAmts">QSAAAEEgAABBoAAAQaAAAA</bytes>
+										</object>
+									</object>
+									<string key="NSFrame">{{0, 168}, {276, 327}}</string>
+									<reference key="NSSuperview" ref="884315936"/>
+									<string key="NSClassName">NSView</string>
+								</object>
+							</object>
+							<string key="NSFrameSize">{276, 495}</string>
+							<reference key="NSSuperview" ref="241404708"/>
+						</object>
+					</object>
+					<string key="NSFrameSize">{276, 495}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1280, 778}}</string>
+				<string key="NSMinSize">{145, 207}</string>
+				<string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
+			</object>
+			<object class="NSMenu" id="239876997">
+				<string key="NSTitle">contextual</string>
+				<object class="NSMutableArray" key="NSMenuItems">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMenuItem" id="650272315">
+						<reference key="NSMenu" ref="239876997"/>
+						<string key="NSTitle">Open</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<object class="NSCustomResource" key="NSOnImage" id="452971550">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuCheckmark</string>
+						</object>
+						<object class="NSCustomResource" key="NSMixedImage" id="1041270430">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuMixedState</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="75799947">
+						<reference key="NSMenu" ref="239876997"/>
+						<string key="NSTitle">Compile</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="452971550"/>
+						<reference key="NSMixedImage" ref="1041270430"/>
+					</object>
+					<object class="NSMenuItem" id="227572035">
+						<reference key="NSMenu" ref="239876997"/>
+						<string key="NSTitle">Compile and Load</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="452971550"/>
+						<reference key="NSMixedImage" ref="1041270430"/>
+					</object>
+				</object>
+				<bool key="NSMenuExcludeMarkColumn">YES</bool>
+			</object>
+			<object class="NSPopUpButton" id="908486401">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">268</int>
+				<string key="NSFrameSize">{54, 25}</string>
+				<reference key="NSSuperview"/>
+				<bool key="NSEnabled">YES</bool>
+				<object class="NSPopUpButtonCell" key="NSCell" id="189252207">
+					<int key="NSCellFlags">-2076049856</int>
+					<int key="NSCellFlags2">2048</int>
+					<reference key="NSSupport" ref="419050269"/>
+					<reference key="NSControlView" ref="908486401"/>
+					<int key="NSButtonFlags">-2038415105</int>
+					<int key="NSButtonFlags2">163</int>
+					<string key="NSAlternateContents"/>
+					<string key="NSKeyEquivalent"/>
+					<int key="NSPeriodicDelay">400</int>
+					<int key="NSPeriodicInterval">75</int>
+					<object class="NSMenuItem" key="NSMenuItem" id="862699147">
+						<reference key="NSMenu" ref="928145737"/>
+						<bool key="NSIsHidden">YES</bool>
+						<string key="NSTitle"/>
+						<string key="NSKeyEquiv"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<int key="NSState">1</int>
+						<object class="NSCustomResource" key="NSImage">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSActionTemplate</string>
+						</object>
+						<reference key="NSOnImage" ref="452971550"/>
+						<reference key="NSMixedImage" ref="1041270430"/>
+						<string key="NSAction">_popUpItemAction:</string>
+						<reference key="NSTarget" ref="189252207"/>
+					</object>
+					<bool key="NSMenuItemRespectAlignment">YES</bool>
+					<object class="NSMenu" key="NSMenu" id="928145737">
+						<string key="NSTitle">project-operations</string>
+						<object class="NSMutableArray" key="NSMenuItems">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="862699147"/>
+							<object class="NSMenuItem" id="1008669135">
+								<reference key="NSMenu" ref="928145737"/>
+								<string key="NSTitle">Compile</string>
+								<string key="NSKeyEquiv"/>
+								<int key="NSMnemonicLoc">2147483647</int>
+								<reference key="NSOnImage" ref="452971550"/>
+								<reference key="NSMixedImage" ref="1041270430"/>
+								<string key="NSAction">_popUpItemAction:</string>
+								<reference key="NSTarget" ref="189252207"/>
+							</object>
+							<object class="NSMenuItem" id="64996800">
+								<reference key="NSMenu" ref="928145737"/>
+								<string key="NSTitle">Load</string>
+								<string key="NSKeyEquiv"/>
+								<int key="NSMnemonicLoc">2147483647</int>
+								<reference key="NSOnImage" ref="452971550"/>
+								<reference key="NSMixedImage" ref="1041270430"/>
+								<string key="NSAction">_popUpItemAction:</string>
+								<reference key="NSTarget" ref="189252207"/>
+							</object>
+							<object class="NSMenuItem" id="611105389">
+								<reference key="NSMenu" ref="928145737"/>
+								<string key="NSTitle">Load Source</string>
+								<string key="NSKeyEquiv"/>
+								<int key="NSMnemonicLoc">2147483647</int>
+								<reference key="NSOnImage" ref="452971550"/>
+								<reference key="NSMixedImage" ref="1041270430"/>
+								<string key="NSAction">_popUpItemAction:</string>
+								<reference key="NSTarget" ref="189252207"/>
+							</object>
+							<object class="NSMenuItem" id="331169643">
+								<reference key="NSMenu" ref="928145737"/>
+								<string key="NSTitle">Test</string>
+								<string key="NSKeyEquiv"/>
+								<int key="NSMnemonicLoc">2147483647</int>
+								<reference key="NSOnImage" ref="452971550"/>
+								<reference key="NSMixedImage" ref="1041270430"/>
+								<string key="NSAction">_popUpItemAction:</string>
+								<reference key="NSTarget" ref="189252207"/>
+							</object>
+						</object>
+						<bool key="NSMenuExcludeMarkColumn">YES</bool>
+					</object>
+					<bool key="NSPullDown">YES</bool>
+					<int key="NSPreferredEdge">1</int>
+					<bool key="NSUsesItemFromMenu">YES</bool>
+					<bool key="NSAltersState">YES</bool>
+					<int key="NSArrowPosition">2</int>
+				</object>
+			</object>
+			<object class="NSWindowTemplate" id="891704788">
+				<int key="NSWindowStyleMask">31</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 132}, {276, 378}}</string>
+				<int key="NSWTFlags">-1543503872</int>
+				<string key="NSWindowTitle">System Info</string>
+				<string key="NSWindowClass">NSPanel</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
+				<string key="NSWindowContentMinSize">{140, 200}</string>
+				<object class="NSView" key="NSWindowView" id="1073567144">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="834860042">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{53, 341}, {45, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="400721761">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Name:</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="834860042"/>
+								<object class="NSColor" key="NSBackgroundColor" id="1000393049">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<reference key="NSColor" ref="824193269"/>
+								</object>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="356363749">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{42, 316}, {56, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="432162696">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Version:</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="356363749"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="23117163">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">266</int>
+							<string key="NSFrame">{{100, 341}, {159, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="154221261">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">nameLabel</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="23117163"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="763081825">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">266</int>
+							<string key="NSFrame">{{100, 316}, {159, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="423837924">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">versionLabel</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="763081825"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="76331459">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">266</int>
+							<string key="NSFrame">{{100, 291}, {159, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="11577993">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">authorLabel</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="76331459"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="249889852">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">266</int>
+							<string key="NSFrame">{{100, 266}, {156, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="538304952">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">maintainerLabel</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="249889852"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="413462210">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">266</int>
+							<string key="NSFrame">{{100, 241}, {159, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1040536841">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">licenceLabel</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="413462210"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="565692944">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">266</int>
+							<string key="NSFrame">{{100, 216}, {159, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="421409493">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">descriptionLabel</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="565692944"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="1047623221">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 216}, {81, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="121500698">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Description:</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="1047623221"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="550357909">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 191}, {116, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="230551720">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Long Description:</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="550357909"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="815805110">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{46, 291}, {52, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="673726776">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Author:</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="815805110"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="392931666">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{23, 266}, {75, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="534961909">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Maintainer:</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="392931666"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="409834497">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{43, 241}, {55, 17}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="796241666">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Licence:</string>
+								<reference key="NSSupport" ref="419050269"/>
+								<reference key="NSControlView" ref="409834497"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="457015052">
+							<reference key="NSNextResponder" ref="1073567144"/>
+							<int key="NSvFlags">274</int>
+							<string key="NSFrame">{{19, 20}, {240, 163}}</string>
+							<reference key="NSSuperview" ref="1073567144"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="647606175">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">272629760</int>
+								<string key="NSContents">longDescriptionLabel</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">13</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<reference key="NSControlView" ref="457015052"/>
+								<reference key="NSBackgroundColor" ref="1000393049"/>
+								<reference key="NSTextColor" ref="714951766"/>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{276, 378}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1280, 778}}</string>
+				<string key="NSMinSize">{140, 216}</string>
+				<string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
+			</object>
+			<object class="NSMenu" id="698622882">
+				<string key="NSTitle">system</string>
+				<object class="NSMutableArray" key="NSMenuItems">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMenuItem" id="995317006">
+						<reference key="NSMenu" ref="698622882"/>
+						<string key="NSTitle">Operate</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="452971550"/>
+						<reference key="NSMixedImage" ref="1041270430"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="438734237">
+							<string key="NSTitle"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="360309418">
+									<reference key="NSMenu" ref="438734237"/>
+									<string key="NSTitle">Compile</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="452971550"/>
+									<reference key="NSMixedImage" ref="1041270430"/>
+								</object>
+								<object class="NSMenuItem" id="562157550">
+									<reference key="NSMenu" ref="438734237"/>
+									<string key="NSTitle">Load</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="452971550"/>
+									<reference key="NSMixedImage" ref="1041270430"/>
+								</object>
+								<object class="NSMenuItem" id="984786432">
+									<reference key="NSMenu" ref="438734237"/>
+									<string key="NSTitle">Load Source</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="452971550"/>
+									<reference key="NSMixedImage" ref="1041270430"/>
+								</object>
+								<object class="NSMenuItem" id="178270383">
+									<reference key="NSMenu" ref="438734237"/>
+									<string key="NSTitle">Test</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="452971550"/>
+									<reference key="NSMixedImage" ref="1041270430"/>
+								</object>
+							</object>
+							<bool key="NSMenuExcludeMarkColumn">YES</bool>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="760672064">
+						<reference key="NSMenu" ref="698622882"/>
+						<string key="NSTitle">Get Info</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="452971550"/>
+						<reference key="NSMixedImage" ref="1041270430"/>
+					</object>
+					<object class="NSMenuItem" id="46288552">
+						<reference key="NSMenu" ref="698622882"/>
+						<string key="NSTitle">Edit</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="452971550"/>
+						<reference key="NSMixedImage" ref="1041270430"/>
+					</object>
+				</object>
+				<bool key="NSMenuExcludeMarkColumn">YES</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="875229309"/>
+						<reference key="destination" ref="938498879"/>
+					</object>
+					<int key="connectionID">25</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="933218413"/>
+						<reference key="destination" ref="938498879"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">componentView</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="933218413"/>
+					</object>
+					<int key="connectionID">27</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="875229309"/>
+					</object>
+					<int key="connectionID">28</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">itemMenu</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="239876997"/>
+					</object>
+					<int key="connectionID">33</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">opButton</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="908486401"/>
+					</object>
+					<int key="connectionID">85</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="933218413"/>
+						<reference key="destination" ref="938498879"/>
+					</object>
+					<int key="connectionID">93</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">infoPanel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="891704788"/>
+					</object>
+					<int key="connectionID">143</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">longDescriptionLabel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="457015052"/>
+					</object>
+					<int key="connectionID">144</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">descriptionLabel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="565692944"/>
+					</object>
+					<int key="connectionID">145</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">licenceLabel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="413462210"/>
+					</object>
+					<int key="connectionID">146</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">maintainerLabel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="249889852"/>
+					</object>
+					<int key="connectionID">147</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">authorLabel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="76331459"/>
+					</object>
+					<int key="connectionID">148</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">versionLabel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="763081825"/>
+					</object>
+					<int key="connectionID">149</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">nameLabel</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="23117163"/>
+					</object>
+					<int key="connectionID">150</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="165534007"/>
+						<reference key="destination" ref="938498879"/>
+					</object>
+					<int key="connectionID">182</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="165534007"/>
+						<reference key="destination" ref="938498879"/>
+					</object>
+					<int key="connectionID">183</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">systemView</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="165534007"/>
+					</object>
+					<int key="connectionID">184</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">systemMenu</string>
+						<reference key="source" ref="938498879"/>
+						<reference key="destination" ref="698622882"/>
+					</object>
+					<int key="connectionID">235</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">menu</string>
+						<reference key="source" ref="933218413"/>
+						<reference key="destination" ref="239876997"/>
+					</object>
+					<int key="connectionID">236</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">menu</string>
+						<reference key="source" ref="165534007"/>
+						<reference key="destination" ref="698622882"/>
+					</object>
+					<int key="connectionID">237</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<reference key="object" ref="0"/>
+						<reference key="children" ref="842755916"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="938498879"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="700062780"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="960468241"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="875229309"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="241404708"/>
+						</object>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Window (System)</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="241404708"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="884315936"/>
+						</object>
+						<reference key="parent" ref="875229309"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">170</int>
+						<reference key="object" ref="884315936"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1045904718"/>
+							<reference ref="489362485"/>
+						</object>
+						<reference key="parent" ref="241404708"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">171</int>
+						<reference key="object" ref="1045904718"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="728387647"/>
+						</object>
+						<reference key="parent" ref="884315936"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">173</int>
+						<reference key="object" ref="728387647"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="165534007"/>
+							<reference ref="226775687"/>
+							<reference ref="724124208"/>
+						</object>
+						<reference key="parent" ref="1045904718"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">176</int>
+						<reference key="object" ref="165534007"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="677500492"/>
+						</object>
+						<reference key="parent" ref="728387647"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">178</int>
+						<reference key="object" ref="677500492"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="554466692"/>
+						</object>
+						<reference key="parent" ref="165534007"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">181</int>
+						<reference key="object" ref="554466692"/>
+						<reference key="parent" ref="677500492"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">172</int>
+						<reference key="object" ref="489362485"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="797734369"/>
+						</object>
+						<reference key="parent" ref="884315936"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="797734369"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="933218413"/>
+							<reference ref="288789385"/>
+							<reference ref="1055463008"/>
+						</object>
+						<reference key="parent" ref="489362485"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="933218413"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="75976626"/>
+						</object>
+						<reference key="parent" ref="797734369"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="75976626"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="466455816"/>
+						</object>
+						<reference key="parent" ref="933218413"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="466455816"/>
+						<reference key="parent" ref="75976626"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="239876997"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="650272315"/>
+							<reference ref="75799947"/>
+							<reference ref="227572035"/>
+						</object>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Menu</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="650272315"/>
+						<reference key="parent" ref="239876997"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="75799947"/>
+						<reference key="parent" ref="239876997"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="227572035"/>
+						<reference key="parent" ref="239876997"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">79</int>
+						<reference key="object" ref="908486401"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="189252207"/>
+						</object>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Round Textured Button (NSActionTemplate)</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">113</int>
+						<reference key="object" ref="891704788"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1073567144"/>
+						</object>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Panel (System Info)</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">114</int>
+						<reference key="object" ref="1073567144"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="834860042"/>
+							<reference ref="356363749"/>
+							<reference ref="23117163"/>
+							<reference ref="763081825"/>
+							<reference ref="1047623221"/>
+							<reference ref="550357909"/>
+							<reference ref="815805110"/>
+							<reference ref="392931666"/>
+							<reference ref="409834497"/>
+							<reference ref="457015052"/>
+							<reference ref="76331459"/>
+							<reference ref="249889852"/>
+							<reference ref="413462210"/>
+							<reference ref="565692944"/>
+						</object>
+						<reference key="parent" ref="891704788"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">115</int>
+						<reference key="object" ref="834860042"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="400721761"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">116</int>
+						<reference key="object" ref="356363749"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="432162696"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">117</int>
+						<reference key="object" ref="23117163"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="154221261"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">118</int>
+						<reference key="object" ref="763081825"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="423837924"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">123</int>
+						<reference key="object" ref="1047623221"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="121500698"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">125</int>
+						<reference key="object" ref="550357909"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="230551720"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">127</int>
+						<reference key="object" ref="815805110"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="673726776"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">129</int>
+						<reference key="object" ref="392931666"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="534961909"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">131</int>
+						<reference key="object" ref="409834497"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="796241666"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">133</int>
+						<reference key="object" ref="457015052"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="647606175"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">135</int>
+						<reference key="object" ref="76331459"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="11577993"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">137</int>
+						<reference key="object" ref="249889852"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="538304952"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">139</int>
+						<reference key="object" ref="413462210"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1040536841"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">141</int>
+						<reference key="object" ref="565692944"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="421409493"/>
+						</object>
+						<reference key="parent" ref="1073567144"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">205</int>
+						<reference key="object" ref="698622882"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="995317006"/>
+							<reference ref="760672064"/>
+							<reference ref="46288552"/>
+						</object>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Menu (system)</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">206</int>
+						<reference key="object" ref="995317006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="438734237"/>
+						</object>
+						<reference key="parent" ref="698622882"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">209</int>
+						<reference key="object" ref="438734237"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="360309418"/>
+							<reference ref="562157550"/>
+							<reference ref="984786432"/>
+							<reference ref="178270383"/>
+						</object>
+						<reference key="parent" ref="995317006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">210</int>
+						<reference key="object" ref="360309418"/>
+						<reference key="parent" ref="438734237"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">211</int>
+						<reference key="object" ref="562157550"/>
+						<reference key="parent" ref="438734237"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">212</int>
+						<reference key="object" ref="984786432"/>
+						<reference key="parent" ref="438734237"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">213</int>
+						<reference key="object" ref="178270383"/>
+						<reference key="parent" ref="438734237"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">207</int>
+						<reference key="object" ref="760672064"/>
+						<reference key="parent" ref="698622882"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">208</int>
+						<reference key="object" ref="46288552"/>
+						<reference key="parent" ref="698622882"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">216</int>
+						<reference key="object" ref="189252207"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="928145737"/>
+						</object>
+						<reference key="parent" ref="908486401"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">217</int>
+						<reference key="object" ref="400721761"/>
+						<reference key="parent" ref="834860042"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">218</int>
+						<reference key="object" ref="432162696"/>
+						<reference key="parent" ref="356363749"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">219</int>
+						<reference key="object" ref="154221261"/>
+						<reference key="parent" ref="23117163"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">220</int>
+						<reference key="object" ref="423837924"/>
+						<reference key="parent" ref="763081825"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">221</int>
+						<reference key="object" ref="121500698"/>
+						<reference key="parent" ref="1047623221"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">222</int>
+						<reference key="object" ref="230551720"/>
+						<reference key="parent" ref="550357909"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">223</int>
+						<reference key="object" ref="673726776"/>
+						<reference key="parent" ref="815805110"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">224</int>
+						<reference key="object" ref="534961909"/>
+						<reference key="parent" ref="392931666"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">225</int>
+						<reference key="object" ref="796241666"/>
+						<reference key="parent" ref="409834497"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">226</int>
+						<reference key="object" ref="647606175"/>
+						<reference key="parent" ref="457015052"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">227</int>
+						<reference key="object" ref="11577993"/>
+						<reference key="parent" ref="76331459"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">228</int>
+						<reference key="object" ref="538304952"/>
+						<reference key="parent" ref="249889852"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">229</int>
+						<reference key="object" ref="1040536841"/>
+						<reference key="parent" ref="413462210"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">230</int>
+						<reference key="object" ref="421409493"/>
+						<reference key="parent" ref="565692944"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">81</int>
+						<reference key="object" ref="928145737"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="331169643"/>
+							<reference ref="862699147"/>
+							<reference ref="611105389"/>
+							<reference ref="64996800"/>
+							<reference ref="1008669135"/>
+						</object>
+						<reference key="parent" ref="189252207"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">92</int>
+						<reference key="object" ref="331169643"/>
+						<reference key="parent" ref="928145737"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">82</int>
+						<reference key="object" ref="862699147"/>
+						<reference key="parent" ref="928145737"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">63</int>
+						<reference key="object" ref="611105389"/>
+						<reference key="parent" ref="928145737"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">62</int>
+						<reference key="object" ref="64996800"/>
+						<reference key="parent" ref="928145737"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">61</int>
+						<reference key="object" ref="1008669135"/>
+						<reference key="parent" ref="928145737"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">231</int>
+						<reference key="object" ref="226775687"/>
+						<reference key="parent" ref="728387647"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">232</int>
+						<reference key="object" ref="724124208"/>
+						<reference key="parent" ref="728387647"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">233</int>
+						<reference key="object" ref="288789385"/>
+						<reference key="parent" ref="797734369"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">234</int>
+						<reference key="object" ref="1055463008"/>
+						<reference key="parent" ref="797734369"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-2.IBAttributePlaceholdersKey</string>
+					<string>-3.IBPluginDependency</string>
+					<string>-3.ImportedFromIB2</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.ImportedFromIB2</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.windowTemplate.hasMinSize</string>
+					<string>1.windowTemplate.minSize</string>
+					<string>11.IBPluginDependency</string>
+					<string>11.ImportedFromIB2</string>
+					<string>113.IBEditorWindowLastContentRect</string>
+					<string>113.IBPluginDependency</string>
+					<string>113.IBWindowTemplateEditedContentRect</string>
+					<string>113.ImportedFromIB2</string>
+					<string>113.windowTemplate.hasMinSize</string>
+					<string>113.windowTemplate.minSize</string>
+					<string>114.IBPluginDependency</string>
+					<string>114.ImportedFromIB2</string>
+					<string>115.IBPluginDependency</string>
+					<string>115.ImportedFromIB2</string>
+					<string>116.IBPluginDependency</string>
+					<string>116.ImportedFromIB2</string>
+					<string>117.IBPluginDependency</string>
+					<string>117.ImportedFromIB2</string>
+					<string>118.IBPluginDependency</string>
+					<string>118.ImportedFromIB2</string>
+					<string>123.IBPluginDependency</string>
+					<string>123.ImportedFromIB2</string>
+					<string>125.IBPluginDependency</string>
+					<string>125.ImportedFromIB2</string>
+					<string>127.IBPluginDependency</string>
+					<string>127.ImportedFromIB2</string>
+					<string>129.IBPluginDependency</string>
+					<string>129.ImportedFromIB2</string>
+					<string>131.IBPluginDependency</string>
+					<string>131.ImportedFromIB2</string>
+					<string>133.IBPluginDependency</string>
+					<string>133.ImportedFromIB2</string>
+					<string>135.IBPluginDependency</string>
+					<string>135.ImportedFromIB2</string>
+					<string>137.IBPluginDependency</string>
+					<string>137.ImportedFromIB2</string>
+					<string>139.IBPluginDependency</string>
+					<string>139.ImportedFromIB2</string>
+					<string>141.IBPluginDependency</string>
+					<string>141.ImportedFromIB2</string>
+					<string>170.IBPluginDependency</string>
+					<string>170.ImportedFromIB2</string>
+					<string>171.IBPluginDependency</string>
+					<string>171.ImportedFromIB2</string>
+					<string>172.IBPluginDependency</string>
+					<string>172.ImportedFromIB2</string>
+					<string>173.IBPluginDependency</string>
+					<string>173.ImportedFromIB2</string>
+					<string>176.IBPluginDependency</string>
+					<string>176.ImportedFromIB2</string>
+					<string>178.IBPluginDependency</string>
+					<string>178.ImportedFromIB2</string>
+					<string>181.IBPluginDependency</string>
+					<string>181.ImportedFromIB2</string>
+					<string>2.IBPluginDependency</string>
+					<string>2.ImportedFromIB2</string>
+					<string>205.IBEditorWindowLastContentRect</string>
+					<string>205.IBPluginDependency</string>
+					<string>205.ImportedFromIB2</string>
+					<string>206.IBPluginDependency</string>
+					<string>206.ImportedFromIB2</string>
+					<string>207.IBPluginDependency</string>
+					<string>207.ImportedFromIB2</string>
+					<string>208.IBPluginDependency</string>
+					<string>208.ImportedFromIB2</string>
+					<string>209.IBEditorWindowLastContentRect</string>
+					<string>209.IBPluginDependency</string>
+					<string>209.ImportedFromIB2</string>
+					<string>210.IBPluginDependency</string>
+					<string>210.ImportedFromIB2</string>
+					<string>211.IBPluginDependency</string>
+					<string>211.ImportedFromIB2</string>
+					<string>212.IBPluginDependency</string>
+					<string>212.ImportedFromIB2</string>
+					<string>213.IBPluginDependency</string>
+					<string>213.ImportedFromIB2</string>
+					<string>216.IBPluginDependency</string>
+					<string>217.IBPluginDependency</string>
+					<string>218.IBPluginDependency</string>
+					<string>219.IBPluginDependency</string>
+					<string>220.IBPluginDependency</string>
+					<string>221.IBPluginDependency</string>
+					<string>222.IBPluginDependency</string>
+					<string>223.IBPluginDependency</string>
+					<string>224.IBPluginDependency</string>
+					<string>225.IBPluginDependency</string>
+					<string>226.IBPluginDependency</string>
+					<string>227.IBPluginDependency</string>
+					<string>228.IBPluginDependency</string>
+					<string>229.IBPluginDependency</string>
+					<string>230.IBPluginDependency</string>
+					<string>231.IBPluginDependency</string>
+					<string>231.IBShouldRemoveOnLegacySave</string>
+					<string>232.IBPluginDependency</string>
+					<string>232.IBShouldRemoveOnLegacySave</string>
+					<string>233.IBPluginDependency</string>
+					<string>233.IBShouldRemoveOnLegacySave</string>
+					<string>234.IBPluginDependency</string>
+					<string>234.IBShouldRemoveOnLegacySave</string>
+					<string>29.IBEditorWindowLastContentRect</string>
+					<string>29.IBPluginDependency</string>
+					<string>29.ImportedFromIB2</string>
+					<string>3.IBPluginDependency</string>
+					<string>3.ImportedFromIB2</string>
+					<string>30.IBPluginDependency</string>
+					<string>30.ImportedFromIB2</string>
+					<string>31.IBPluginDependency</string>
+					<string>31.ImportedFromIB2</string>
+					<string>32.IBPluginDependency</string>
+					<string>32.ImportedFromIB2</string>
+					<string>6.IBPluginDependency</string>
+					<string>6.ImportedFromIB2</string>
+					<string>61.IBPluginDependency</string>
+					<string>61.ImportedFromIB2</string>
+					<string>62.IBPluginDependency</string>
+					<string>62.ImportedFromIB2</string>
+					<string>63.IBPluginDependency</string>
+					<string>63.ImportedFromIB2</string>
+					<string>79.IBEditorWindowLastContentRect</string>
+					<string>79.IBPluginDependency</string>
+					<string>79.ImportedFromIB2</string>
+					<string>8.IBPluginDependency</string>
+					<string>8.ImportedFromIB2</string>
+					<string>81.IBEditorWindowLastContentRect</string>
+					<string>81.IBPluginDependency</string>
+					<string>81.ImportedFromIB2</string>
+					<string>82.IBPluginDependency</string>
+					<string>82.ImportedFromIB2</string>
+					<string>92.IBPluginDependency</string>
+					<string>92.ImportedFromIB2</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableDictionary">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<reference key="dict.sortedKeys" ref="0"/>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+					</object>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>{{311, 19}, {276, 495}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{311, 19}, {276, 495}}</string>
+					<boolean value="YES"/>
+					<boolean value="YES"/>
+					<boolean value="YES"/>
+					<string>{145, 185}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>{{35, 339}, {276, 378}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{35, 339}, {276, 378}}</string>
+					<boolean value="YES"/>
+					<boolean value="YES"/>
+					<string>{140, 200}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>{{37, 525}, {106, 63}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>{{143, 505}, {135, 83}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>{{94, 682}, {175, 63}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>{{14, 709}, {54, 25}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>{{3, 631}, {149, 103}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<boolean value="YES"/>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">237</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">ProjectWindowController</string>
+					<string key="superclassName">NSWindowController</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>authorLabel</string>
+							<string>componentView</string>
+							<string>descriptionLabel</string>
+							<string>infoPanel</string>
+							<string>itemMenu</string>
+							<string>licenceLabel</string>
+							<string>longDescriptionLabel</string>
+							<string>maintainerLabel</string>
+							<string>nameLabel</string>
+							<string>opButton</string>
+							<string>systemMenu</string>
+							<string>systemView</string>
+							<string>versionLabel</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+			<integer value="1050" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/updateCCL.nib/designable.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/updateCCL.nib/designable.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/updateCCL.nib/designable.nib	(revision 13309)
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9C7010</string>
+		<string key="IBDocument.InterfaceBuilderVersion">667</string>
+		<string key="IBDocument.AppKitVersion">949.26</string>
+		<string key="IBDocument.HIToolboxVersion">352.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="1" id="9"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">UpdateCclWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">257</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 387}, {381, 123}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Update CCL</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="380836188">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 52}, {347, 51}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="759012394">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">272891904</int>
+								<string key="NSContents">Update the CCL sources from the master Subversion repository.</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<reference key="NSControlView" ref="380836188"/>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSButton" id="653458570">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{175, 12}, {96, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="125824421">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Update</string>
+								<object class="NSFont" key="NSSupport" id="679436182">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="653458570"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+						<object class="NSButton" id="626795059">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{271, 12}, {96, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="360805428">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Cancel</string>
+								<reference key="NSSupport" ref="679436182"/>
+								<reference key="NSControlView" ref="626795059"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{381, 123}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">updateWindow</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">11</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">updateCCLCancel:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="626795059"/>
+					</object>
+					<int key="connectionID">12</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">updateCCLOkay:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="653458570"/>
+					</object>
+					<int key="connectionID">13</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="380836188"/>
+							<reference ref="626795059"/>
+							<reference ref="653458570"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="380836188"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="759012394"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="759012394"/>
+						<reference key="parent" ref="380836188"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="653458570"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="125824421"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="125824421"/>
+						<reference key="parent" ref="653458570"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="626795059"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="360805428"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">10</int>
+						<reference key="object" ref="360805428"/>
+						<reference key="parent" ref="626795059"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>10.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+					<string>9.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{323, 833}, {381, 123}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{323, 833}, {381, 123}}</string>
+					<reference ref="9"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">13</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">UpdateCclWindowController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>updateCCLCancel:</string>
+							<string>updateCCLOkay:</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">updateWindow</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xapropos.nib/classes.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xapropos.nib/classes.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xapropos.nib/classes.nib	(revision 13309)
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>inspect</key>
+				<string>id</string>
+				<key>search</key>
+				<string>id</string>
+				<key>setSearchCategory</key>
+				<string>id</string>
+				<key>source</key>
+				<string>id</string>
+				<key>toggleExternalOnly</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>XaproposWindowController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>actionMenu</key>
+				<string>id</string>
+				<key>actionPopupButton</key>
+				<string>id</string>
+				<key>allSymbolsButton</key>
+				<string>id</string>
+				<key>contextualMenu</key>
+				<string>id</string>
+				<key>externalSymbolsButton</key>
+				<string>id</string>
+				<key>searchField</key>
+				<string>id</string>
+				<key>searchFieldToolbarItem</key>
+				<string>id</string>
+				<key>tableView</key>
+				<string>id</string>
+				<key>window</key>
+				<string>id</string>
+			</dict>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xapropos.nib/info.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xapropos.nib/info.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xapropos.nib/info.nib	(revision 13309)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBOldestOS</key>
+	<integer>4</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>113</integer>
+		<integer>139</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>9J61</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xinspector.nib/designable.nib
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xinspector.nib/designable.nib	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/English.lproj/xinspector.nib/designable.nib	(revision 13309)
@@ -0,0 +1,925 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9G55</string>
+		<string key="IBDocument.InterfaceBuilderVersion">677</string>
+		<string key="IBDocument.AppKitVersion">949.43</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="1"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">XinspectorWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">4111</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 263}, {414, 247}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Inspector</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<object class="NSToolbar" key="NSViewClass" id="120420657">
+					<object class="NSMutableString" key="NSToolbarIdentifier">
+						<characters key="NS.bytes">11FF1944-C11B-41C6-A003-9585363C7826</characters>
+					</object>
+					<nil key="NSToolbarDelegate"/>
+					<bool key="NSToolbarPrefersToBeShown">YES</bool>
+					<bool key="NSToolbarShowsBaselineSeparator">YES</bool>
+					<bool key="NSToolbarAllowsUserCustomization">NO</bool>
+					<bool key="NSToolbarAutosavesConfiguration">NO</bool>
+					<int key="NSToolbarDisplayMode">2</int>
+					<int key="NSToolbarSizeMode">1</int>
+					<object class="NSMutableDictionary" key="NSToolbarIBIdentifiedItems">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>140E8E1C-26BC-428C-9CF8-CA1DDA7F3E76</string>
+							<string>9C0EEE1A-A666-4045-883D-A48E5DEAE95E</string>
+							<string>E05A681B-F0F4-4BED-857C-F96B9CC7681C</string>
+							<string>NSToolbarFlexibleSpaceItem</string>
+							<string>NSToolbarSpaceItem</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="NSToolbarItem" id="291454967">
+								<object class="NSMutableString" key="NSToolbarItemIdentifier">
+									<characters key="NS.bytes">140E8E1C-26BC-428C-9CF8-CA1DDA7F3E76</characters>
+								</object>
+								<string key="NSToolbarItemLabel">Resample</string>
+								<string key="NSToolbarItemPaletteLabel">Resample</string>
+								<nil key="NSToolbarItemToolTip"/>
+								<object class="NSButton" key="NSToolbarItemView" id="91588276">
+									<nil key="NSNextResponder"/>
+									<int key="NSvFlags">268</int>
+									<string key="NSFrame">{{16, 14}, {28, 25}}</string>
+									<bool key="NSEnabled">YES</bool>
+									<object class="NSButtonCell" key="NSCell" id="774653393">
+										<int key="NSCellFlags">-2080244224</int>
+										<int key="NSCellFlags2">134217728</int>
+										<string key="NSContents">Round Textured</string>
+										<object class="NSFont" key="NSSupport" id="314698606">
+											<string key="NSName">LucidaGrande</string>
+											<double key="NSSize">1.300000e+01</double>
+											<int key="NSfFlags">1044</int>
+										</object>
+										<reference key="NSControlView" ref="91588276"/>
+										<int key="NSButtonFlags">-2033958657</int>
+										<int key="NSButtonFlags2">163</int>
+										<object class="NSCustomResource" key="NSNormalImage" id="280890349">
+											<string key="NSClassName">NSImage</string>
+											<string key="NSResourceName">NSRefreshTemplate</string>
+										</object>
+										<string key="NSAlternateContents"/>
+										<string key="NSKeyEquivalent"/>
+										<int key="NSPeriodicDelay">400</int>
+										<int key="NSPeriodicInterval">75</int>
+									</object>
+								</object>
+								<reference key="NSToolbarItemImage" ref="280890349"/>
+								<nil key="NSToolbarItemTarget"/>
+								<nil key="NSToolbarItemAction"/>
+								<string key="NSToolbarItemMinSize">{28, 25}</string>
+								<string key="NSToolbarItemMaxSize">{28, 25}</string>
+								<bool key="NSToolbarItemEnabled">YES</bool>
+								<bool key="NSToolbarItemAutovalidates">YES</bool>
+								<int key="NSToolbarItemTag">0</int>
+								<bool key="NSToolbarIsUserRemovable">YES</bool>
+								<int key="NSToolbarItemVisibilityPriority">0</int>
+							</object>
+							<object class="NSToolbarItem" id="249745443">
+								<object class="NSMutableString" key="NSToolbarItemIdentifier">
+									<characters key="NS.bytes">9C0EEE1A-A666-4045-883D-A48E5DEAE95E</characters>
+								</object>
+								<string key="NSToolbarItemLabel">Custom View</string>
+								<string key="NSToolbarItemPaletteLabel">Custom View</string>
+								<nil key="NSToolbarItemToolTip"/>
+								<object class="NSPopUpButton" key="NSToolbarItemView" id="159161183">
+									<nil key="NSNextResponder"/>
+									<int key="NSvFlags">268</int>
+									<string key="NSFrame">{{17, 14}, {44, 25}}</string>
+									<bool key="NSEnabled">YES</bool>
+									<object class="NSPopUpButtonCell" key="NSCell" id="474393519">
+										<int key="NSCellFlags">-2076049856</int>
+										<int key="NSCellFlags2">2048</int>
+										<reference key="NSSupport" ref="314698606"/>
+										<reference key="NSControlView" ref="159161183"/>
+										<int key="NSButtonFlags">-2038415105</int>
+										<int key="NSButtonFlags2">163</int>
+										<object class="NSCustomResource" key="NSNormalImage" id="964196954">
+											<string key="NSClassName">NSImage</string>
+											<string key="NSResourceName">NSActionTemplate</string>
+										</object>
+										<string key="NSAlternateContents"/>
+										<string key="NSKeyEquivalent"/>
+										<int key="NSPeriodicDelay">400</int>
+										<int key="NSPeriodicInterval">75</int>
+										<object class="NSMenuItem" key="NSMenuItem" id="859814700">
+											<reference key="NSMenu" ref="1053546733"/>
+											<bool key="NSIsHidden">YES</bool>
+											<string key="NSTitle"/>
+											<string key="NSKeyEquiv"/>
+											<int key="NSKeyEquivModMask">1048576</int>
+											<int key="NSMnemonicLoc">2147483647</int>
+											<int key="NSState">1</int>
+											<reference key="NSImage" ref="964196954"/>
+											<object class="NSCustomResource" key="NSOnImage" id="597888505">
+												<string key="NSClassName">NSImage</string>
+												<string key="NSResourceName">NSMenuCheckmark</string>
+											</object>
+											<object class="NSCustomResource" key="NSMixedImage" id="28479342">
+												<string key="NSClassName">NSImage</string>
+												<string key="NSResourceName">NSMenuMixedState</string>
+											</object>
+											<string key="NSAction">_popUpItemAction:</string>
+											<reference key="NSTarget" ref="474393519"/>
+										</object>
+										<bool key="NSMenuItemRespectAlignment">YES</bool>
+										<object class="NSMenu" key="NSMenu" id="1053546733">
+											<string key="NSTitle">Action</string>
+											<object class="NSMutableArray" key="NSMenuItems">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<reference ref="859814700"/>
+												<object class="NSMenuItem" id="786480955">
+													<reference key="NSMenu" ref="1053546733"/>
+													<string key="NSTitle">Inspect</string>
+													<string key="NSKeyEquiv"/>
+													<int key="NSKeyEquivModMask">1048576</int>
+													<int key="NSMnemonicLoc">2147483647</int>
+													<reference key="NSOnImage" ref="597888505"/>
+													<reference key="NSMixedImage" ref="28479342"/>
+													<string key="NSAction">_popUpItemAction:</string>
+													<reference key="NSTarget" ref="474393519"/>
+												</object>
+												<object class="NSMenuItem" id="106887791">
+													<reference key="NSMenu" ref="1053546733"/>
+													<string key="NSTitle">Edit Value</string>
+													<string key="NSKeyEquiv"/>
+													<int key="NSKeyEquivModMask">1048576</int>
+													<int key="NSMnemonicLoc">2147483647</int>
+													<reference key="NSOnImage" ref="597888505"/>
+													<reference key="NSMixedImage" ref="28479342"/>
+													<string key="NSAction">_popUpItemAction:</string>
+													<reference key="NSTarget" ref="474393519"/>
+												</object>
+											</object>
+										</object>
+										<bool key="NSPullDown">YES</bool>
+										<int key="NSPreferredEdge">1</int>
+										<bool key="NSUsesItemFromMenu">YES</bool>
+										<bool key="NSAltersState">YES</bool>
+										<int key="NSArrowPosition">2</int>
+									</object>
+								</object>
+								<reference key="NSToolbarItemImage" ref="964196954"/>
+								<nil key="NSToolbarItemTarget"/>
+								<nil key="NSToolbarItemAction"/>
+								<string key="NSToolbarItemMinSize">{44, 25}</string>
+								<string key="NSToolbarItemMaxSize">{44, 25}</string>
+								<bool key="NSToolbarItemEnabled">YES</bool>
+								<bool key="NSToolbarItemAutovalidates">YES</bool>
+								<int key="NSToolbarItemTag">0</int>
+								<bool key="NSToolbarIsUserRemovable">YES</bool>
+								<int key="NSToolbarItemVisibilityPriority">0</int>
+							</object>
+							<object class="NSToolbarItem" id="129455253">
+								<object class="NSMutableString" key="NSToolbarItemIdentifier">
+									<characters key="NS.bytes">E05A681B-F0F4-4BED-857C-F96B9CC7681C</characters>
+								</object>
+								<string key="NSToolbarItemLabel">Back/Forward</string>
+								<string key="NSToolbarItemPaletteLabel">Back/Forward</string>
+								<nil key="NSToolbarItemToolTip"/>
+								<object class="NSSegmentedControl" key="NSToolbarItemView" id="391219298">
+									<nil key="NSNextResponder"/>
+									<int key="NSvFlags">268</int>
+									<string key="NSFrame">{{14, 14}, {53, 25}}</string>
+									<bool key="NSEnabled">YES</bool>
+									<object class="NSSegmentedCell" key="NSCell" id="91975892">
+										<int key="NSCellFlags">67239424</int>
+										<int key="NSCellFlags2">0</int>
+										<object class="NSFont" key="NSSupport">
+											<string key="NSName">LucidaGrande</string>
+											<double key="NSSize">1.300000e+01</double>
+											<int key="NSfFlags">16</int>
+										</object>
+										<reference key="NSControlView" ref="391219298"/>
+										<object class="NSMutableArray" key="NSSegmentImages">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSSegmentItem">
+												<double key="NSSegmentItemWidth">2.300000e+01</double>
+												<object class="NSCustomResource" key="NSSegmentItemImage">
+													<string key="NSClassName">NSImage</string>
+													<string key="NSResourceName">NSGoLeftTemplate</string>
+												</object>
+												<string key="NSSegmentItemLabel"/>
+												<int key="NSSegmentItemImageScaling">0</int>
+											</object>
+											<object class="NSSegmentItem">
+												<double key="NSSegmentItemWidth">2.300000e+01</double>
+												<object class="NSCustomResource" key="NSSegmentItemImage">
+													<string key="NSClassName">NSImage</string>
+													<string key="NSResourceName">NSGoRightTemplate</string>
+												</object>
+												<string key="NSSegmentItemLabel"/>
+												<int key="NSSegmentItemTag">1</int>
+												<int key="NSSegmentItemImageScaling">0</int>
+											</object>
+										</object>
+										<int key="NSSelectedSegment">1</int>
+										<int key="NSTrackingMode">2</int>
+										<int key="NSSegmentStyle">2</int>
+									</object>
+								</object>
+								<nil key="NSToolbarItemImage"/>
+								<nil key="NSToolbarItemTarget"/>
+								<nil key="NSToolbarItemAction"/>
+								<string key="NSToolbarItemMinSize">{53, 25}</string>
+								<string key="NSToolbarItemMaxSize">{53, 25}</string>
+								<bool key="NSToolbarItemEnabled">YES</bool>
+								<bool key="NSToolbarItemAutovalidates">YES</bool>
+								<int key="NSToolbarItemTag">0</int>
+								<bool key="NSToolbarIsUserRemovable">YES</bool>
+								<int key="NSToolbarItemVisibilityPriority">0</int>
+							</object>
+							<object class="NSToolbarFlexibleSpaceItem" id="870544756">
+								<string key="NSToolbarItemIdentifier">NSToolbarFlexibleSpaceItem</string>
+								<string key="NSToolbarItemLabel"/>
+								<string key="NSToolbarItemPaletteLabel">Flexible Space</string>
+								<nil key="NSToolbarItemToolTip"/>
+								<nil key="NSToolbarItemView"/>
+								<nil key="NSToolbarItemImage"/>
+								<nil key="NSToolbarItemTarget"/>
+								<nil key="NSToolbarItemAction"/>
+								<string key="NSToolbarItemMinSize">{1, 5}</string>
+								<string key="NSToolbarItemMaxSize">{20000, 32}</string>
+								<bool key="NSToolbarItemEnabled">YES</bool>
+								<bool key="NSToolbarItemAutovalidates">YES</bool>
+								<int key="NSToolbarItemTag">-1</int>
+								<bool key="NSToolbarIsUserRemovable">YES</bool>
+								<int key="NSToolbarItemVisibilityPriority">0</int>
+								<object class="NSMenuItem" key="NSToolbarItemMenuFormRepresentation">
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="597888505"/>
+									<reference key="NSMixedImage" ref="28479342"/>
+								</object>
+							</object>
+							<object class="NSToolbarSpaceItem" id="24890809">
+								<string key="NSToolbarItemIdentifier">NSToolbarSpaceItem</string>
+								<string key="NSToolbarItemLabel"/>
+								<string key="NSToolbarItemPaletteLabel">Space</string>
+								<nil key="NSToolbarItemToolTip"/>
+								<nil key="NSToolbarItemView"/>
+								<nil key="NSToolbarItemImage"/>
+								<nil key="NSToolbarItemTarget"/>
+								<nil key="NSToolbarItemAction"/>
+								<string key="NSToolbarItemMinSize">{32, 5}</string>
+								<string key="NSToolbarItemMaxSize">{32, 32}</string>
+								<bool key="NSToolbarItemEnabled">YES</bool>
+								<bool key="NSToolbarItemAutovalidates">YES</bool>
+								<int key="NSToolbarItemTag">-1</int>
+								<bool key="NSToolbarIsUserRemovable">YES</bool>
+								<int key="NSToolbarItemVisibilityPriority">0</int>
+								<object class="NSMenuItem" key="NSToolbarItemMenuFormRepresentation">
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="597888505"/>
+									<reference key="NSMixedImage" ref="28479342"/>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSArray" key="NSToolbarIBAllowedItems">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<reference ref="870544756"/>
+						<reference ref="129455253"/>
+						<reference ref="291454967"/>
+						<reference ref="24890809"/>
+						<reference ref="249745443"/>
+					</object>
+					<object class="NSMutableArray" key="NSToolbarIBDefaultItems">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<reference ref="129455253"/>
+						<reference ref="291454967"/>
+						<reference ref="24890809"/>
+						<reference ref="249745443"/>
+						<reference ref="870544756"/>
+					</object>
+					<object class="NSMutableArray" key="NSToolbarIBSelectableItems">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+					</object>
+				</object>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<string key="NSWindowContentMinSize">{228, 64}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSScrollView" id="958883018">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">274</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="815316034">
+									<reference key="NSNextResponder" ref="958883018"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSTableView" id="110103011">
+											<reference key="NSNextResponder" ref="815316034"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{416, 249}</string>
+											<reference key="NSSuperview" ref="815316034"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="_NSCornerView" key="NSCornerView">
+												<nil key="NSNextResponder"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrame">{{467, 0}, {16, 17}}</string>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="698277128">
+													<double key="NSWidth">4.130000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents"/>
+														<object class="NSFont" key="NSSupport">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.100000e+01</double>
+															<int key="NSfFlags">3100</int>
+														</object>
+														<object class="NSColor" key="NSBackgroundColor">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<object class="NSColor" key="NSTextColor">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">headerTextColor</string>
+															<object class="NSColor" key="NSColor" id="45479863">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MAA</bytes>
+															</object>
+														</object>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="925637923">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="314698606"/>
+														<reference key="NSControlView" ref="110103011"/>
+														<object class="NSColor" key="NSBackgroundColor" id="426750682">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlBackgroundColor</string>
+															<object class="NSColor" key="NSColor">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+															</object>
+														</object>
+														<object class="NSColor" key="NSTextColor">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlTextColor</string>
+															<reference key="NSColor" ref="45479863"/>
+														</object>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="110103011"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<object class="NSColor" key="NSBackgroundColor">
+												<int key="NSColorSpace">3</int>
+												<bytes key="NSWhite">MQA</bytes>
+											</object>
+											<object class="NSColor" key="NSGridColor">
+												<int key="NSColorSpace">6</int>
+												<string key="NSCatalogName">System</string>
+												<string key="NSColorName">gridColor</string>
+												<object class="NSColor" key="NSColor">
+													<int key="NSColorSpace">3</int>
+													<bytes key="NSWhite">MC41AA</bytes>
+												</object>
+											</object>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-700448768</int>
+											<int key="NSColumnAutoresizingStyle">4</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">YES</bool>
+										</object>
+									</object>
+									<string key="NSFrameSize">{416, 249}</string>
+									<reference key="NSSuperview" ref="958883018"/>
+									<reference key="NSNextKeyView" ref="110103011"/>
+									<reference key="NSDocView" ref="110103011"/>
+									<reference key="NSBGColor" ref="426750682"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="101125531">
+									<reference key="NSNextResponder" ref="958883018"/>
+									<int key="NSvFlags">-2147483392</int>
+									<string key="NSFrame">{{401, 0}, {15, 233}}</string>
+									<reference key="NSSuperview" ref="958883018"/>
+									<reference key="NSTarget" ref="958883018"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.961240e-01</double>
+								</object>
+								<object class="NSScroller" id="662637373">
+									<reference key="NSNextResponder" ref="958883018"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{-100, -100}, {400, 15}}</string>
+									<reference key="NSSuperview" ref="958883018"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="958883018"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.978632e-01</double>
+								</object>
+							</object>
+							<string key="NSFrame">{{-1, -1}, {416, 249}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSNextKeyView" ref="815316034"/>
+							<int key="NSsFlags">528</int>
+							<reference key="NSVScroller" ref="101125531"/>
+							<reference key="NSHScroller" ref="662637373"/>
+							<reference key="NSContentView" ref="815316034"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+					</object>
+					<string key="NSFrameSize">{414, 247}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMinSize">{228, 118}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<string key="NSFrameAutosaveName">Inspector</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">actionMenu</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1053546733"/>
+					</object>
+					<int key="connectionID">37</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">backForwardControl</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="391219298"/>
+					</object>
+					<int key="connectionID">38</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">refreshButton</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="91588276"/>
+					</object>
+					<int key="connectionID">39</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">40</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">41</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">backOrForward:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="391219298"/>
+					</object>
+					<int key="connectionID">42</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">tableView</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="110103011"/>
+					</object>
+					<int key="connectionID">52</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="110103011"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">53</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="110103011"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">54</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+							<reference ref="120420657"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="958883018"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="120420657"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="870544756"/>
+							<reference ref="129455253"/>
+							<reference ref="291454967"/>
+							<reference ref="24890809"/>
+							<reference ref="249745443"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="870544756"/>
+						<reference key="parent" ref="120420657"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="129455253"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="391219298"/>
+						</object>
+						<reference key="parent" ref="120420657"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="391219298"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="91975892"/>
+						</object>
+						<reference key="parent" ref="129455253"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">12</int>
+						<reference key="object" ref="91975892"/>
+						<reference key="parent" ref="391219298"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="291454967"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="91588276"/>
+						</object>
+						<reference key="parent" ref="120420657"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="91588276"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="774653393"/>
+						</object>
+						<reference key="parent" ref="291454967"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="774653393"/>
+						<reference key="parent" ref="91588276"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="24890809"/>
+						<reference key="parent" ref="120420657"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="249745443"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="159161183"/>
+						</object>
+						<reference key="parent" ref="120420657"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="159161183"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="474393519"/>
+						</object>
+						<reference key="parent" ref="249745443"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="474393519"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1053546733"/>
+						</object>
+						<reference key="parent" ref="159161183"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="1053546733"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="106887791"/>
+							<reference ref="786480955"/>
+							<reference ref="859814700"/>
+						</object>
+						<reference key="parent" ref="474393519"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">35</int>
+						<reference key="object" ref="106887791"/>
+						<reference key="parent" ref="1053546733"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">34</int>
+						<reference key="object" ref="786480955"/>
+						<reference key="parent" ref="1053546733"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">33</int>
+						<reference key="object" ref="859814700"/>
+						<reference key="parent" ref="1053546733"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">43</int>
+						<reference key="object" ref="958883018"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="101125531"/>
+							<reference ref="662637373"/>
+							<reference ref="110103011"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">44</int>
+						<reference key="object" ref="101125531"/>
+						<reference key="parent" ref="958883018"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">45</int>
+						<reference key="object" ref="662637373"/>
+						<reference key="parent" ref="958883018"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">46</int>
+						<reference key="object" ref="110103011"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="698277128"/>
+						</object>
+						<reference key="parent" ref="958883018"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">48</int>
+						<reference key="object" ref="698277128"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="925637923"/>
+						</object>
+						<reference key="parent" ref="110103011"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">51</int>
+						<reference key="object" ref="925637923"/>
+						<reference key="parent" ref="698277128"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>1.windowTemplate.hasMinSize</string>
+					<string>1.windowTemplate.minSize</string>
+					<string>11.IBPluginDependency</string>
+					<string>12.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>27.IBPluginDependency</string>
+					<string>3.IBEditorWindowLastContentRect</string>
+					<string>3.IBPluginDependency</string>
+					<string>30.IBPluginDependency</string>
+					<string>31.IBPluginDependency</string>
+					<string>32.IBEditorWindowLastContentRect</string>
+					<string>32.IBPluginDependency</string>
+					<string>33.IBPluginDependency</string>
+					<string>34.IBPluginDependency</string>
+					<string>35.IBPluginDependency</string>
+					<string>43.IBPluginDependency</string>
+					<string>44.IBPluginDependency</string>
+					<string>45.IBPluginDependency</string>
+					<string>46.IBPluginDependency</string>
+					<string>48.IBPluginDependency</string>
+					<string>51.IBPluginDependency</string>
+					<string>9.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{201, 186}, {414, 247}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{201, 186}, {414, 247}}</string>
+					<boolean value="NO"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<boolean value="YES"/>
+					<string>{228, 64}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{-26, 905}, {616, 0}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{319, 784}, {137, 63}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">54</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">XinspectorWindowController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">backOrForward:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>actionMenu</string>
+							<string>backForwardControl</string>
+							<string>contextualMenu</string>
+							<string>refreshButton</string>
+							<string>tableView</string>
+							<string>window</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/Help/cocoa-notes.html
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/Help/cocoa-notes.html	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/Help/cocoa-notes.html	(revision 13309)
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>The (preliminary) Cocoa-based development environment for OpenMCL</title>
+  </head>
+
+  <body>
+    <h1>The (still preliminary) Cocoa-based development environment for OpenMCL</h1>
+    <h2>General information</h2>
+    <p>
+      The OpenMCL Cocoa demo's been around for over a year; a variety
+      of things have kept it from moving forward:
+    </p>
+    <ol>
+      <li>
+	<p>
+	  It was difficult (in some cases, impossible) to get Cocoa's
+	  runtime system and OpenMCL's cooperative threads to interact
+	  reasonably.
+	</p>
+      </li>
+      <li>
+	<p>
+	  The demo code was written using a set of reader macros and
+	  other constructs that made it possible to sort of embed
+	  Objective-C like code in lisp.  (It was actually a bit worse
+	  than writing Objective-C code, since there was absolutely
+	  nothing in the way of compile-time type- or sanity-checking
+	  going on; the code was all effectively written at the lowest
+	  level of OpenMCL's ffi.
+	</p>
+	<p>
+	  The code's (almost ...) all rewritten using a Lisp-to-ObjC
+	  bridge package developed and contributed by Randall Beer.
+	  The bridge offers a lot of features that make Cocoa programming
+	  in OpenMCL saner, safer, and Lispier than it had been; it's
+	  a good thing, and seems to be an important step towards
+	  closer integration of CLOS and ObjC.
+	</p>
+      </li>
+      <li>
+	<p>
+	  There was a proof-of-concept example that showed how it was
+	  possible to save the demo IDE as a double-clickable bundled
+	  application.  A lot of the steps involved in that process
+	  had to be performed manually, and the result wasn't too
+	  usable ...
+	</p>
+      </li>
+    </ol>
+    <p>
+      These issues have been addressed to a large degree; the demo
+      IDE's still barely usable (neither the editor nor the listener
+      windows are particularly lisp-aware, a lot of development and
+      debugging tools are missing, etc.) but I think that the foundation
+      for building this stuff is significantly stronger than it was.
+    </p>
+    <p>
+      All of this is (obviously) MacOSX-specific.  The <a
+      href=http://www.gnustep.org>GNUstep Project</a> is trying to
+      provide a cross-platform, opensourced version of OPENSTEP (and
+      therefore a potentially high degree of compatibility with Cocoa.)
+      It might therefore be possible to port some of this to GNUstep
+      and Linux; I don't know how much would be involved in that.
+    </p>
+
+    <h2>Random technical issues &amp; to-do list</h2>
+
+    <h3>Lisp-awareness</h3>
+    <p>
+      The demo IDE's listener and editor windows are slightly
+      customized versions of Cocoa's NSTextView class; the underlying
+      editor buffers are accessed as "attributed strings".  There's no
+      support for lisp-syntax-aware navigation in NSTextView buffers,
+      and adding that support at the "attributed string" level would
+      seem to be a tedious, error-prone process.
+    </p>
+    <p>
+      I think that it'll be possible to effectively replace the
+      Cocoa text system's buffering mechanism with Lisp data structures
+      (e.g., PHemlock buffers), and continue to use the Cocoa text
+      system for display, scrolling, selection, and raw event handling.
+    </p>
+
+    <h3>Modularity</h3>
+    <p>
+      There's code in the demo IDE that's very specific to the IDE
+      application itself; some other code probably needs to be
+      in any (hypothetical) OpenMCL-based Cocoa application.  This
+      obviously needs to be refactored a bit.
+    </p>
+    <p>
+      The bundle directory used by the demo IDE ("ccl:OpenMCL.app")
+      is something that I originally created in ProjectBuilder a
+      long time ago.  It'd be nice (and probably not too hard)
+      if there was a simple way to create skeletal bundle hierarchys
+      that could be populated and customized to create other types
+      of applications, and if the lisp (in various ways) helped
+      to support this process.)  There are obviously lots of things
+      that could be done here ...
+    </p>
+
+    <hr>
+<!-- Created: Sun Jun  2 22:37:21 MDT 2002 -->
+<!-- hhmts start -->
+Last modified: Mon Sep  1 19:54:26 MDT 2003
+<!-- hhmts end -->
+  </body>
+</html>
Index: /branches/new-random/cocoa-ide/ide-contents/Resources/Help/index.html
===================================================================
--- /branches/new-random/cocoa-ide/ide-contents/Resources/Help/index.html	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-contents/Resources/Help/index.html	(revision 13309)
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <meta name="AppleTitle" content="OpenMCL Help"/>
+    <title>OpenMCL Help</title>
+  </head>
+
+  <body>
+    <h1>OpenMCL Help</h1>
+
+    <p>Aren't you glad you waited so long to see this window ?</p>
+    
+    <p>The OpenMCL Doc directory is available <a href=../../../../doc/HTML/index.html>here</a>.
+    </p>
+    
+    <p>Some notes about the Cocoa-based development environment are
+      available <a href=cocoa-notes.html> here</a>.
+    </p>
+
+    <hr>
+<!-- Created: Sun Jun  2 22:00:23 MDT 2002 -->
+<!-- hhmts start -->
+Last modified: Mon Jun  3 02:18:04 MDT 2002
+<!-- hhmts end -->
+  </body>
+</html>
Index: /branches/new-random/cocoa-ide/ide-self-update.lisp
===================================================================
--- /branches/new-random/cocoa-ide/ide-self-update.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/ide-self-update.lisp	(revision 13309)
@@ -0,0 +1,405 @@
+;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: cl-user -*-
+;;;; ***********************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          svn-self.lisp
+;;;; Version:       0.1
+;;;; Project:       Cocoa IDE
+;;;; Purpose:       Cocoa UI for updating the Cocoa IDE from the source repo
+;;;;
+;;;; ***********************************************************************
+
+(in-package :ccl)
+(require :sequence-utils)
+
+;;; -----------------------------------------------------------------
+;;; IDE automated self-rebuild
+;;; -----------------------------------------------------------------
+;;; normally we run the self-rebuild after an update from the
+;;; source repo. the steps are:
+;;; 1. rename Clozure CL.app to Clozure CL-last.app
+;;;    (check for older versions and rename with a numbering scheme)
+;;; 2. run an external process that starts ccl and evaluates (rebuild-ccl :full t)
+;;; 3. run an external process that starts ccl and evaluates (require :cocoa-application)
+;;; 4. quit the current IDE (with a farewell message to the effect that the IDE has been rebuilt)
+;;; 5. relaunch the IDE (?) 
+;;; (for a simple way to quit and relaunch, see http://www.cocoabuilder.com/archive/message/cocoa/2008/3/3/200352)
+
+(defun ide-self-rebuild ()
+  (let* ((ccl-dir (gui::find-ccl-directory))
+         (bundle (probe-file (merge-pathnames "Clozure CL.app" ccl-dir))))
+    (if bundle
+        ;; found the bundle; proceed with rebuilding...
+        (let* ((result-status nil)
+               (lisp (merge-pathnames (standard-kernel-name) ccl-dir)))
+          (gui::with-modal-progress-dialog "Rebuilding" "Rebuilding Clozure CL (please wait)..."
+                                           (run-program lisp `("-e" "(rebuild-ccl :full t)") 
+                                                        ::status-hook (lambda (ep) 
+                                                                        (multiple-value-bind (status status-code) 
+                                                                            (external-process-status ep)
+                                                                          (when (eql status :exited)
+                                                                            (setf result-status status-code))))))
+          (if (zerop result-status)
+              ;; rebuild succeeded; continue...
+              (let* ((old-bundle (merge-pathnames "Clozure CL-last.app" ccl-dir)))
+                ;; if there is already an old bundle, delete it
+                (when (probe-file old-bundle)
+                  (recursive-delete-directory old-bundle))
+                ;; rename the current bundle to the old-bundle
+                (rename-file bundle old-bundle)
+                ;; rebuild the IDE
+                (setf result-status nil)
+                (gui::with-modal-progress-dialog "Rebuilding" "Rebuilding the IDE (please wait)..."
+                                                 (run-program lisp `("-e" "(require :cocoa-application)") 
+                                                              ::status-hook (lambda (ep) 
+                                                                              (multiple-value-bind (status status-code) 
+                                                                                  (external-process-status ep)
+                                                                                (when (eql status :exited)
+                                                                                  (setf result-status status-code))))))
+                (if (zerop result-status)
+                    ;; inform the user that the IDE is rebuilt and we will quit
+                    (progn
+                      (gui::alert-window :title "Rebuilding IDE Succeeded"
+                                 :message (format nil 
+                                                  "Clozure CL is rebuilt; you can start the new IDE after this copy quits."))
+                      (quit))
+                    ;; warn the user that the IDE rebuild failed and we will quit
+                    (progn
+                      (gui::alert-window :title "Rebuilding IDE Failed"
+                                 :message (format nil 
+                                                  "Rebuilding the IDE failed with error code ~A. The previous IDE has been moved to ~A."
+                                                  result-status old-bundle))
+                      (quit))))
+              ;; warn the user that rebuilding failed and exit
+              (gui::alert-window :title "Rebuilding CCL Failed"
+                                 :message (format nil 
+                                                  "Clozure CL exited with error status = ~A"
+                                                  result-status))))
+        ;; else: the bundle doesn't seem to be there
+        (gui::alert-window :title "Rebuilding CCL Failed"
+                        :message (format nil 
+                                         "Can't find the application '~A'."
+                                         bundle)))))
+
+;;; -----------------------------------------------------------------
+;;; svn metadata utils
+;;; -----------------------------------------------------------------
+
+;;; VALIDATE-SVN-DATA-PATHNAME p
+;;; -----------------------------------------------------------------
+;;; returns TRUE if P is really an existing directory that appears to
+;;; contain valid Subversion metadata; NIL otherwise
+
+(defmethod validate-svn-data-pathname ((p pathname))
+  (and (probe-file p)
+       (directoryp p)
+       (string= ".svn" (first (last (pathname-directory p))))
+       ;; if we reached this point, it's an existing directory
+       ;; named ".svn". now, does it have Subversion metadata files
+       ;; in it?
+       (let ((subversion-metafiles '("dir-prop-base" "entries" "format"
+                                     "prop-base/" "props/" "text-base/")))
+         (every (lambda (f) (probe-file (merge-pathnames f p))) 
+                subversion-metafiles))))
+
+(defmethod validate-svn-data-pathname ((p string))
+  (validate-svn-data-pathname (pathname p)))
+
+;;; -----------------------------------------------------------------
+;;; url utils
+;;; -----------------------------------------------------------------
+
+;;; URL-P thing
+;;; -----------------------------------------------------------------
+;;; returns true if THING is a string that appears to contain a URL,
+;;; NIL otherwise
+
+(defmethod url-p (thing)
+  (declare (ignore thing))
+  nil)
+
+(defmethod url-p ((url string))
+  (if (find-matching-subsequence "://" url)
+      t
+      nil))
+
+;;; URL-PROTOCOL url
+;;; -----------------------------------------------------------------
+;;; returns the protocol pprtion of the URL, or NIL if none
+;;; can be identified
+
+(defmethod url-protocol ((url string))
+  (let ((index (find-matching-subsequence "://" url)))
+    (if index
+        (subseq url 0 index)
+        nil)))
+
+;;; URL-HOST url
+;;; -----------------------------------------------------------------
+;;; returns two values:
+;;; 1. the hostname of the URL
+;;; 2. the username portion of the host segment, if any, or NIL
+
+(defmethod url-host ((url string))
+  (let* ((protocol-marker "://")
+         (protocol-marker-index (find-matching-subsequence protocol-marker url)))
+    (if protocol-marker-index
+        (let* ((protocol-end-index (+ protocol-marker-index (length protocol-marker)))
+               (host-end-index (find-matching-subsequence "/" url :start protocol-end-index))
+               (host-segment (subseq url protocol-end-index host-end-index))
+               (username-terminus-index (find-matching-subsequence "@" host-segment))
+               (username (if username-terminus-index
+                             (subseq host-segment 0 username-terminus-index)
+                             nil))
+               (host (if username-terminus-index
+                         (subseq host-segment (1+ username-terminus-index))
+                         host-segment)))
+          (values host username))
+        nil)))
+
+;;; URL-PATH url
+;;; -----------------------------------------------------------------
+;;; returns the pathname portion of a URL, or NIL if none can be identified
+
+(defmethod url-path ((url string))
+  (let* ((protocol-marker "://")
+         (protocol-marker-index (find-matching-subsequence protocol-marker url)))
+    (if protocol-marker-index
+        (let* ((protocol-end-index (+ protocol-marker-index (length protocol-marker)))
+               (host-end-index (find-matching-subsequence "/" url :start protocol-end-index)))
+          (if host-end-index
+              (subseq url host-end-index)
+              nil))
+        nil)))
+
+;;; -----------------------------------------------------------------
+;;; running svn commands
+;;; -----------------------------------------------------------------
+
+(defmethod svn-info ((p string))
+  (let* ((result-status nil)
+         (info (with-output-to-string (out)
+                 (run-program *svn-program* `("info" ,p) 
+                              :output out
+                              :status-hook (lambda (ep) 
+                                             (multiple-value-bind (status status-code) 
+                                                 (external-process-status ep)
+                                               (when (eql status :exited)
+                                                 (setf result-status status-code))))))))
+    (values info result-status)))
+
+(defmethod svn-info ((p pathname))
+  (svn-info (namestring p)))
+
+(defmethod svn-update ((p string))
+  (let ((result-status nil))
+    (run-program *svn-program* `("update" ,p) 
+               :status-hook (lambda (ep) 
+                              (multiple-value-bind (status status-code) 
+                                  (external-process-status ep)
+                                (when (eql status :exited)
+                                  (setf result-status status-code)))))
+    result-status))
+
+(defmethod svn-update ((p pathname))
+  (svn-update (namestring p)))
+
+;;; -----------------------------------------------------------------
+;;; parsing info
+;;; -----------------------------------------------------------------
+
+(defmethod split-svn-info-line ((line string))
+  (let* ((split-sequence ": ")
+         (split-index (find-matching-subsequence split-sequence line :test #'char=))
+         (prefix (subseq line 0 split-index))
+         (suffix (subseq line (if split-index
+                                  (+ split-index (length split-sequence))
+                                  (length line)))))
+    (list prefix suffix)))
+
+(defmethod parse-svn-info ((info-string string))
+  (let ((info-lines (split-lines info-string)))
+    (mapcar #'split-svn-info-line info-lines)))
+
+(defun svn-revision ()
+  (svn-info-component "Revision:"))
+
+(defun check-svn ()
+  (multiple-value-bind (status exit-code)
+      (external-process-status
+       (run-program *svn-program* '("--version" "--quiet")))
+    (and (eq status :exited)
+         (eql exit-code 0))))
+
+;;; -----------------------------------------------------------------
+;;; authentication utils, for use with source control
+;;; -----------------------------------------------------------------
+;;; NOTE: currently unused, because we do not update from the GUI
+;;;       in the case that authentication is required. code left here
+;;;       for future reference
+
+(defparameter *authentication-window-controller* nil)
+
+(defclass authentication-window-controller (ns:ns-window-controller)
+    ((authentication-window :foreign-type :id :reader authentication-window)
+     (username-field :foreign-type :id :reader authentication-window-username-field)
+     (password-field :foreign-type :id :reader authentication-window-password-field))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod #/windowNibName ((self authentication-window-controller))
+  #@"Authenticate")
+
+(objc:defmethod (#/authOkay: :void) ((self authentication-window-controller) sender)
+  (declare (ignore sender))
+  (#/stopModalWithCode: (#/sharedApplication (@class ns-application)) 1)
+  (#/orderOut: (authentication-window *authentication-window-controller*) +null-ptr+))
+
+(objc:defmethod (#/authCancel: :void) ((self authentication-window-controller) sender)
+  (declare (ignore sender))
+  (#/stopModalWithCode: (#/sharedApplication (@class ns-application)) 0)
+  (#/orderOut: (authentication-window *authentication-window-controller*) +null-ptr+))
+
+(defun get-auth-window ()
+  (unless *authentication-window-controller*
+    (setf *authentication-window-controller* 
+          (make-instance 'authentication-window-controller))
+    (#/initWithWindowNibName: *authentication-window-controller* #@"Authenticate"))
+  (unless (#/isWindowLoaded *authentication-window-controller*)
+    (#/loadWindow *authentication-window-controller*))
+  (let ((window (authentication-window *authentication-window-controller*)))
+    (if (or (null window)
+            (%null-ptr-p window))
+        nil
+        window)))
+
+(defun get-svn-auth-data ()
+  (let ((auth-window (get-auth-window)))
+    (if auth-window
+        (let ((window-status (#/runModalForWindow: (#/sharedApplication (@class ns-application))
+                                                   auth-window)))
+          (if (zerop window-status)
+              nil
+              (let  ((username (lisp-string-from-nsstring (#/stringValue (authentication-window-username-field 
+                                                                          *authentication-window-controller*))))
+                     (password (lisp-string-from-nsstring (#/stringValue (authentication-window-password-field 
+                                                                          *authentication-window-controller*)))))
+                (cons username password))))
+        nil)))
+
+;;; -----------------------------------------------------------------
+;;; svn updates
+;;; -----------------------------------------------------------------
+
+(defun valid-revision-number-for-svn-update? (rev)
+  (and (stringp rev)
+       (plusp (length rev))))
+
+(defun valid-repository-for-svn-update? (url)
+  (url-p url))
+
+(defun valid-directory-for-svn-update? (dir)
+  (and dir
+       (probe-file dir)
+       (directoryp dir)
+       (validate-svn-data-pathname (merge-pathnames ".svn/" dir))))
+
+(defun svn-update-ccl (&key directory repository last-revision)
+  (cond
+    ((not (valid-directory-for-svn-update? directory)) 
+     (gui::alert-window :title "Update Failed"
+                        :message (format nil 
+                                         "Subversion update failed. CCL directory '~A' is not a valid working copy."
+                                         directory)))
+    ((not (valid-repository-for-svn-update? repository))
+     (gui::alert-window :title "Update Failed"
+                        :message (format nil "Subversion update failed. The supplied repository URL is invalid: '~A'"
+                                         repository)))
+    ((not (valid-revision-number-for-svn-update? last-revision))
+     (gui::alert-window :title "Update Failed"
+                        :message (format nil "Subversion update failed. CCL found an invalid revision number ('~A') for '~A'"
+                                         last-revision directory)))
+    (t (let ((status (svn-update directory)))
+         (if (zerop status)
+             (progn
+               ;; notify the user that the update succeeded and we'll now rebuild
+               (gui::alert-window :title "Update Succeeded"
+                        :message (format nil "Subversion updated CCL source directory '~A'. CCL needs to be rebuilt."
+                                         directory))
+               (ide-self-rebuild))
+             (gui::alert-window :title "Update Failed"
+                        :message (format nil "Subversion update of CCL directory '~A' failed with error code ~A."
+                                         directory status)))))))
+
+(defun run-svn-update-for-directory (dir)
+  (let* ((revision (svn-info-component "Revision:"))
+         (url (svn-url)))
+    (svn-update-ccl :directory dir :repository url :last-revision revision)))
+  
+(defun run-svn-update ()
+  (run-svn-update-for-directory (gui::find-ccl-directory)))
+
+(defun svn-update-available-p ()
+  (let ((ccl-dir (gui::find-ccl-directory)))
+    (if (valid-directory-for-svn-update? ccl-dir)
+        ;; compare revision number of working copy with repo
+        (let* ((local-revision (read-from-string (svn-revision)))
+               (repo (svn-repository))
+               (repo-info (parse-svn-info (svn-info repo)))
+               (repo-revision-entry (assoc "Revision" repo-info :test #'string=))
+               (repo-revision (or (and repo-revision-entry
+                                       (read-from-string (second repo-revision-entry)))
+                                  0)))
+          (< local-revision repo-revision))
+        nil)))
+
+;;; -----------------------------------------------------------------
+;;; app delegate extensions to handle self-update UI
+;;; -----------------------------------------------------------------
+
+(defparameter *update-ccl-window-controller* nil)
+
+(defclass update-ccl-window-controller (ns:ns-window-controller)
+    ((update-window :foreign-type :id :reader update-window))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod #/windowNibName ((self update-ccl-window-controller))
+  #@"updateCCL")
+
+(objc:defmethod (#/updateCCLOkay: :void) ((self update-ccl-window-controller) sender)
+  (declare (ignore sender))
+  (#/stopModalWithCode: (#/sharedApplication (@class ns-application)) 1)
+  (#/orderOut: (update-window *update-ccl-window-controller*) +null-ptr+)
+  (gui::with-modal-progress-dialog "Updating..."
+    "Getting changes from the CCL Repository..."
+   (run-svn-update))
+  (ide-self-rebuild))
+
+(objc:defmethod (#/updateCCLCancel: :void) ((self update-ccl-window-controller) sender)
+  (declare (ignore sender))
+  (#/stopModalWithCode: (#/sharedApplication (@class ns-application)) 0)
+  (#/orderOut: (update-window *update-ccl-window-controller*) +null-ptr+))
+
+(objc:defmethod (#/updateCCL: :void) ((self gui::lisp-application-delegate)
+                                      sender)
+  (declare (ignore sender))
+  (if (check-svn)
+    (if (gui::with-modal-progress-dialog "Checking for Updates..."
+        "Checking for new CCL changes..."
+       (svn-update-available-p))
+      ;; newer version in the repo; display the update window
+      (progn
+        (when (null *update-ccl-window-controller*)
+          (setf *update-ccl-window-controller*
+                (make-instance 'update-ccl-window-controller))
+          (#/initWithWindowNibName: *update-ccl-window-controller* #@"updateCCL"))
+        (unless (#/isWindowLoaded *update-ccl-window-controller*)
+          (#/loadWindow *update-ccl-window-controller*))
+        (#/runModalForWindow: (#/sharedApplication (@class ns-application)) 
+                              (update-window *update-ccl-window-controller*)))
+      ;; no newer version available; display an informative alert window
+      (gui::alert-window :title "No Update Available"
+                         :message "No update is available. Your copy of CCL is up-to-date."))
+    ;; Can't execute svn.
+    (gui::alert-window :title "Can't run svn!"
+                       :message "The \"svn\" program can't be executed. If this is because it's installed in some directory not on this program's executable search path, setting CCL:*SVN-PROGRAM* to the full pathname of your \"svn\" program may fix this.")))
+
Index: /branches/new-random/cocoa-ide/inspector.lisp
===================================================================
--- /branches/new-random/cocoa-ide/inspector.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/inspector.lisp	(revision 13309)
@@ -0,0 +1,276 @@
+(in-package "GUI")
+
+#|
+Implements inspector windows in Cocoa
+
+This builds heavily on the inspector objects defined in ccl/lib/describe.lisp.
+
+An inspector-item is an Objective-C object that contains a lisp-inspector, and a vector of child inspector-items
+that are filled in lazily as required.
+
+To Do:  
+Make scroll bars work
+Make command-left-arrow and command-right-arrow go back and forward
+Add tabs
+Set window title based on object
+Add "Inspect" menu item (Key equivalent: command-I) - and make it work in many situations
+  If an inspector is on top, inspect selection in place
+  If an editor is on top
+    If there is a selection, eval and inspect
+    If no selection look for a nearby form to eval and inspect 
+  If listener is on top and insertion point is after prompt, inspect *
+  Inspect selection of other windows, backtrace, apropos, etc.
+
+Make meta-dot edit source in many places, have menu item which is disabled when it doesn't make sense
+Handle comments, and static inspector items
+Make editing in place work in some situations
+Make command-double-click bring up new inspector window
+Make command-T inspect in a new tab
+add bookmarks for commonly inspected objects - forms to evaluate
+Add set-package widget to many places to effect printed representations and evaluation contexts
+Make a way to get inspected object to listener, possibly set *
+  (to be consistent with editor windows, make enter print it in listener setting *
+    make command-enter, do that and bring listener to the front)
+In some situations, remember and display form that was evaluated to get currently inspected object
+When form is shown, refresh re-evaluates form
+Possibly add splitter
+Possibly add linked panes
+Maybe get rid of contextual menus when main menu handles everything
+Make preferences for fonts, key commands
+|#
+
+(defvar @ nil)
+(defvar @@ nil)
+(defvar @@@ nil)
+
+(defclass ninspector-window-controller (ns:ns-window-controller)
+  ((table-view :foreign-type :id :accessor table-view) ;IBOutlet set by nib file
+   (property-column :foreign-type :id :accessor property-column) ;IBOutlet
+   (value-column :foreign-type :id :accessor value-column) ;IBOutlet
+   (object-label :foreign-type :id :accessor object-label) ;IBOutlet
+   (back-button :foreign-type :id :accessor back-button) ;IBOutlet
+   (forward-button :foreign-type :id :accessor forward-button) ;IBOutlet
+   (refresh-button :foreign-type :id :accessor refresh-button) ;IBOutlet
+   (item-menu :foreign-type :id :accessor item-menu) ;IBOutlet
+   (viewed-inspector-items :initform (make-array 10 :fill-pointer 0 :adjustable t)  :accessor viewed-inspector-items)
+   (next-index :initform 0 :accessor next-index 
+               :documentation "The index of the next inspector-item in viewed-inspector-items.
+               The index of the inspector-item currently being viewed is one less")
+   (inspector-item :initarg :inspector-item :reader inspector-item))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod #/init ((self ninspector-window-controller))
+  (#/setShouldCascadeWindows: self t)
+  (#/initWithWindowNibName: self #@"inspector"))
+
+(defmethod lisp-inspector ((wc ninspector-window-controller))
+  (lisp-inspector (inspector-item wc)))
+
+(defmethod set-current-inspector-item ((wc ninspector-window-controller) index)
+  (with-slots (next-index viewed-inspector-items) wc
+    (when (< -1 index (fill-pointer viewed-inspector-items))
+      (setf next-index (1+ index))
+      (set-enabled wc)
+      (setf (inspector-item wc) (aref viewed-inspector-items index)))))
+
+(defmethod set-enabled ((wc ninspector-window-controller))
+  "Enables or disables buttons based on current state of viewed-inspector-items and next-index"
+  (with-slots (forward-button back-button next-index viewed-inspector-items) wc
+    (#/setEnabled: back-button (> next-index 1))
+    (#/setEnabled: forward-button (< next-index (fill-pointer viewed-inspector-items)))))
+
+;;Lifted from apropos-window.lisp, not sure if it's really needed...
+(objc:defmethod (#/automaticallyNotifiesObserversForKey: :<BOOL>) ((self +ninspector-window-controller)
+                                                                  key)
+  (declare (ignore key))
+  nil)
+
+(objc:defmethod (#/awakeFromNib :void) ((self ninspector-window-controller))
+  (with-slots (table-view back-button forward-button refresh-button item-menu) self
+    (#/setTarget: back-button self)
+    (#/setAction: back-button (@selector #/goBack:))
+    (#/setTarget: forward-button self)
+    (#/setAction: forward-button (@selector #/goForward:))
+    (#/setTarget: refresh-button self)
+    (#/setAction: refresh-button (@selector #/doRefresh:))
+    (#/setTarget: table-view self)
+    (#/setDoubleAction: table-view (@selector #/inspectSelectionInPlace:))
+    (set-enabled self)
+    (let ((mi0 (#/itemAtIndex: item-menu 0)) ;Inspect in new window
+          (mi1 (#/itemAtIndex: item-menu 1)) ;Inspect in new tab
+          (mi2 (#/itemAtIndex: item-menu 2))) ;Edit Source
+      (#/setEnabled: mi0 t)
+      (#/setTarget: mi0 self)
+      (#/setAction: mi0 (@selector #/inspectSelectionInNewWindow:))
+      (#/setEnabled: mi1 nil)
+      (#/setTarget: mi1 self)
+      (#/setAction: mi1 (@selector #/inspectSelectionInNewTab:))
+      (#/setEnabled: mi2 nil) ;TODO why isn't this working?
+      (#/setTarget: mi2 self)
+      (#/setAction: mi2 (@selector #/editSelectionSource:)))
+    (#/setMenu: table-view item-menu)
+    ))
+
+(objc:defmethod (#/inspectSelectionInPlace: :void) ((wc ninspector-window-controller) sender)
+  (let* ((row (#/clickedRow sender)))
+    (unless (minusp row)
+      (with-slots (next-index viewed-inspector-items) wc
+        (let ((ii (get-child (inspector-item wc) row)))
+	  (when (lisp-inspector ii)
+	    (if (and (< next-index (fill-pointer viewed-inspector-items))
+		     (eql ii (aref viewed-inspector-items next-index)))
+		;;If the ii is the same as the next history item, then just go forward in history
+		(set-current-inspector-item wc next-index)
+		;;Otherwise forget the forward history
+		(push-inspector-item wc ii))))))))
+
+(objc:defmethod (#/inspectSelectionInNewWindow: :void) ((wc ninspector-window-controller) sender)
+  (declare (ignore sender))
+  (let* ((row (#/clickedRow (table-view wc))))
+    (unless (minusp row)
+      (with-slots (next-index viewed-inspector-items) wc
+        (let* ((ii (get-child (inspector-item wc) row))
+	       (li (lisp-inspector ii)))
+	  (when li
+	    (make-inspector-window li)))))))
+
+(objc:defmethod (#/inspectSelectionInSameWindow: :void) ((wc ninspector-window-controller) sender)
+  (declare (ignore sender)))
+
+(objc:defmethod (#/editSelectionSource: :void) ((wc ninspector-window-controller) sender)
+  (declare (ignore sender)))
+
+(objc:defmethod (#/goBack: :void) ((wc ninspector-window-controller) sender)
+  (declare (ignore sender))
+  (set-current-inspector-item wc (- (next-index wc) 2)))
+
+(objc:defmethod (#/goForward: :void) ((wc ninspector-window-controller) sender)
+  (declare (ignore sender))
+  (set-current-inspector-item wc (next-index wc)))
+
+(objc:defmethod (#/doRefresh: :void) ((wc ninspector-window-controller) sender)
+  (declare (ignore sender))
+  (let ((inspector::*inspector-disassembly* t))
+    (push-inspector-item wc (make-inspector-item (inspector::refresh-inspector (lisp-inspector wc))))))
+
+(defclass inspector-item (ns:ns-object)
+  ((lisp-inspector :accessor lisp-inspector) ;; null for non-inspectable
+   (label :accessor inspector-item-label) ;NSString
+   (ob-string :accessor inspector-item-ob-string) ;NSString
+   (children :initform nil)) ;initialized lazily
+  (:metaclass ns:+ns-object))
+
+(defmethod inspector-item-children ((ii inspector-item))
+  (or (slot-value ii 'children)
+      (setf (slot-value ii 'children)
+	    (make-array (inspector-line-count ii) :initial-element nil))))
+
+(defmethod inspector-object ((ii inspector-item))
+  (let ((li (lisp-inspector ii)))
+    (and li (inspector::inspector-object li))))
+
+(defmethod inspector-line-count ((ii inspector-item))
+  (let ((li (lisp-inspector ii)))
+    (or  (and (null li) 0)
+	 (inspector::inspector-line-count li)
+         (progn
+           (inspector::update-line-count li)
+           (inspector::inspector-line-count li)))))
+
+(defun inspector-object-nsstring (li)
+  (let ((ob (inspector::inspector-object li))
+	(*print-readably* nil)
+        (*signal-printing-errors* nil)
+        (*print-circle* t)
+        (*print-length* 20)
+        (*print-pretty* nil))
+    (%make-nsstring (prin1-to-string ob))))
+
+(defun make-inspector-item (li &optional label-string value-string)
+  (let* ((item (make-instance 'inspector-item)))
+    (setf (lisp-inspector item) li
+          (inspector-item-ob-string item) (if value-string
+					    (%make-nsstring value-string)
+					    (inspector-object-nsstring li))
+	  (inspector-item-label item) (%make-nsstring (or label-string "")))
+    item))
+  
+(defun make-inspector (ob)
+  (let ((inspector::*inspector-disassembly* t))
+    (make-inspector-window (inspector::make-inspector ob))))
+
+(defun make-inspector-window (li)
+  (let* ((wc (make-instance 'ninspector-window-controller))
+         (ii (make-inspector-item li)))
+    (push-inspector-item wc ii)
+    (#/showWindow: wc nil)
+    wc))
+
+(defmethod push-inspector-item ((wc ninspector-window-controller) (ii inspector-item))
+  (with-slots (next-index viewed-inspector-items) wc
+    (when (< next-index (fill-pointer viewed-inspector-items))
+      (setf (fill-pointer viewed-inspector-items) next-index))
+    (vector-push-extend ii viewed-inspector-items)
+    (incf next-index))
+  (set-enabled wc)
+  (setf (inspector-item wc) ii))
+
+(defmethod (setf inspector-item) ((ii inspector-item) (wc ninspector-window-controller))
+  (setf @@@ @@
+        @@ @
+        @ (inspector-object ii))
+  (setf (slot-value wc 'inspector-item) ii)
+  (let* ((w (#/window wc))
+         (title (inspector-object-nsstring (lisp-inspector ii))))
+    (#/setTitle: w (%make-nsstring (concatenate 'string  "Inspect: " 
+                                                (lisp-string-from-nsstring title))))
+    (#/setStringValue: (object-label wc) title)
+    (#/reloadData (table-view wc))))
+
+(defun ninspect (object)
+  (execute-in-gui #'(lambda () (make-inspector object))))
+
+
+#|
+The inspector-window-controller is specified in the nib file to be the data source for the NSTableView.
+In order to be a data source it must implement the NSTableDataSource protocol.
+
+The NSTableDataSource methods to get values for the NSTableView are:
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
+- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
+
+For simplicity, the latter method returns NSStrings (it could return other types that need special formatting objects)
+
+If we want the table view to support other features such as setting, sorting, or drag and drop, other
+NSTableDataSource methods can be defined.
+|#
+
+
+(objc:defmethod (#/numberOfRowsInTableView: :<NSI>nteger) ((self ninspector-window-controller) table-view)
+  (declare (ignore table-view))
+  (1- (length (inspector-item-children (inspector-item self))))) ;skip first child which just contains the object itself
+
+(objc:defmethod #/tableView:objectValueForTableColumn:row: ((self ninspector-window-controller) table-view column (row :<NSI>nteger))
+  (declare (ignore table-view))
+  (let ((child (get-child (inspector-item self) row)))
+    (cond ((eql column (property-column self)) (inspector-item-label child))
+          ((eql column (value-column self)) (inspector-item-ob-string child))
+          ((#/isEqualToString: #@"property" (#/identifier column)) (inspector-item-label child))
+          ((#/isEqualToString: #@"value" (#/identifier column)) (inspector-item-ob-string child))
+          (t (progn
+               (log-debug "col: ~s prop-col: ~s val-col: ~s" column (property-column self) (value-column self))
+               #@"*error*")))))
+
+(defmethod get-child ((ii inspector-item) index)
+  (let ((arr (inspector-item-children ii))
+        (i (1+ index)))
+    (or (svref arr i)
+	(setf (svref arr i)
+	      (let ((li (lisp-inspector ii))
+		    (inspector::*inspector-disassembly* t))
+		(multiple-value-bind (child label-string value-string) (inspector::inspector-line li i)
+		  (make-inspector-item child (or label-string "") (or value-string ""))))))))
+
+;;; Make CL:INSPECT call NINSPECT.
+(setq inspector::*default-inspector-ui-creation-function* 'ninspect)
+
Index: /branches/new-random/cocoa-ide/preferences.lisp
===================================================================
--- /branches/new-random/cocoa-ide/preferences.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/preferences.lisp	(revision 13309)
@@ -0,0 +1,277 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+;;;
+;;; How to add a new preference pane:
+;;;
+;;; 1. Open preferences.nib with IB.  Drag a Custom View instance from
+;;;    the palette.  Use the inpector to set its class to PreferencesView.
+;;; 2. Inspect File's Owner (which represents an instance of
+;;;    PreferencesWindowController).  Add an outlet for the new
+;;;    preferences view you just made.  Hook up the outlet.  You can
+;;;    add actions here too, if your preferences view will need them.
+;;; 3. Add controls to your view, binding them to the defaults controller.
+;;; 4. Save the nib file.
+;;; 5. In preferences.lisp (this file), edit the defclass form for
+;;;    preferences-window-controller and add a slot that matches the outlet
+;;;    you created in step 2.
+;;; 6. Edit the toolbar delegate methods to add a toolbar item for your
+;;;    new preference view.
+;;; 7. Implement a #/showFooPrefs: method to swap in the view when
+;;;    the toolbar item is clicked.  (See #/showGeneralPrefs: for an
+;;;    example.
+;;; 8. Implement actions, if needed.
+
+
+(in-package "GUI")
+
+;;; A view that keeps track of its initial size.
+(defclass preferences-view (ns:ns-view)
+  ((width :accessor width)
+   (height :accessor height))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/awakeFromNib :void) ((self preferences-view))
+  (let* ((frame (#/frame self)))
+    (setf (width self) (ns-width frame)
+	  (height self) (ns-height frame))))
+
+(defclass font-to-name-transformer (ns:ns-value-transformer)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/transformedValueClass :<C>lass)
+    ((self +font-to-name-transformer))
+  ns:ns-string)
+
+(objc:defmethod (#/allowsReverseTransformation :<BOOL>)
+    ((self +font-to-name-transformer))
+  nil)
+
+;;; Produce description of NSFont object, e.g., "Monaco 10"
+(objc:defmethod #/transformedValue: ((self font-to-name-transformer) value)
+  (let* ((font (#/unarchiveObjectWithData: ns:ns-unarchiver value))
+         (name (#/displayName font))
+         (size (float (#/pointSize font) 0.0d0)))
+    (#/stringWithFormat: ns:ns-string #@"%@ %.0f" :id name :double-float size)))
+
+(defclass preferences-window-controller (ns:ns-window-controller)
+  ((appearance-prefs :foreign-type :id :accessor appearance-prefs)
+   (documentation-prefs :foreign-type :id :accessor documentation-prefs)
+   (editor-tab-view-item :foreign-type :id :accessor editor-tab-view-item)
+   (encodings-prefs :foreign-type :id :accessor encodings-prefs)
+   (general-prefs :foreign-type :id :accessor general-prefs)
+   (hyperspec-path-button :foreign-type :id :accessor hyperspec-path-button)
+   (listener-tab-view-item :foreign-type :id :accessor listener-tab-view-item)
+   (swank-listener-port :foreign-type :id :accessor swank-listener-port)
+   (tab-view :foreign-type :id :accessor tab-view)
+   (toolbar :foreign-type :id :accessor toolbar))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod #/init ((self preferences-window-controller))
+  (#/setValueTransformer:forName: ns:ns-value-transformer
+				  (make-instance 'font-to-name-transformer)
+				  #@"FontToName")
+
+  (#/initWithWindowNibName: self #@"preferences")
+  (#/addObserver:selector:name:object: (#/defaultCenter ns:ns-notification-center)
+				       self
+				       (@selector #/defaultsDidChange:)
+				       #&NSUserDefaultsDidChangeNotification
+				       (#/standardUserDefaults ns:ns-user-defaults))
+
+  self)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+    (require :swank-listener))
+
+(objc:defmethod (#/windowDidLoad :void) ((self preferences-window-controller))
+  (let* ((window (#/window self))
+         (port-field (swank-listener-port self))
+         (listener-port (or (preference-swank-listener-port) *default-swank-listener-port*)))
+    (with-slots (toolbar) self
+      (setf toolbar (make-instance 'ns:ns-toolbar
+				   :with-identifier #@"preferences-window-toolbar"))
+      (#/setDelegate: toolbar self)
+      (#/setSelectedItemIdentifier: toolbar #@"appearance")
+      (#/setToolbar: window toolbar)
+      ;; for some reason, setting this in IB doesn't work on Tiger/PPC32
+      (#/setShowsToolbarButton: window nil)
+      (#/release toolbar))
+    (ccl::with-autoreleased-nsstring (port-string (format nil "~A" (or listener-port "")))
+      (#/setStringValue: port-field port-string))
+    (#/showAppearancePrefs: self +null-ptr+)))
+  
+(objc:defmethod (#/showWindow: :void) ((self preferences-window-controller)
+				       sender)
+  (#/center (#/window self))
+  (call-next-method sender))
+
+(objc:defmethod (#/defaultsDidChange: :void) ((self preferences-window-controller)
+					      notification)
+  (declare (ignore notification))
+  (update-cocoa-defaults))
+
+(defconstant editor-font-button-tag 1)
+(defconstant listener-input-font-button-tag 2)
+(defconstant listener-output-font-button-tag 2)
+
+;;; Ugh.
+(defvar *listener-or-editor* nil)
+
+(objc:defmethod (#/showFontPanel: :void) ((self preferences-window-controller)
+					 sender)
+  (let* ((tag (#/tag sender))
+	 (font-manager (#/sharedFontManager ns:ns-font-manager))
+	 (font nil)
+	 (panel (#/window self)))
+    (ecase tag
+      (1
+       (setq font *editor-font*)
+       (setq *listener-or-editor* :editor))
+      (2
+       (setq font *listener-input-font*)
+       (setq *listener-or-editor* :listener-input))
+      (3
+       (setq font *listener-output-font*)
+       (setq *listener-or-editor* :listener-output)))
+    (#/makeFirstResponder: panel panel)
+    (#/setSelectedFont:isMultiple: font-manager font nil)
+    (#/orderFrontFontPanel: font-manager self)))
+
+(objc:defmethod (#/startSwankListener: :void) ((self preferences-window-controller)
+					 sender)
+  (declare (ignore sender))
+  (unless (or *ccl-swank-active-p* 
+              (maybe-start-swank-listener :override-user-preference t))
+    (alert-window :message "Unable to start the Swank server.")))
+
+;;; This message is sent to the first responder, which is why
+;;; we do the *listener-or-editor* thing.
+(objc:defmethod (#/changeFont: :void) ((self preferences-window-controller)
+					    font-manager)
+  (let* ((defaults (#/standardUserDefaults ns:ns-user-defaults))
+	 (data nil)
+	 (font nil))
+    (ecase *listener-or-editor*
+      (:listener-input
+       (setq font (#/convertFont: font-manager *listener-input-font*))
+       (unless (%null-ptr-p font)
+	 (setq data (#/archivedDataWithRootObject: ns:ns-archiver font))
+	 (#/setObject:forKey: defaults data #@"listenerInputFont")))
+      (:listener-output
+       (setq font (#/convertFont: font-manager *listener-output-font*))
+       (unless (%null-ptr-p font)
+	 (setq data (#/archivedDataWithRootObject: ns:ns-archiver font))
+	 (#/setObject:forKey: defaults data #@"listenerOutputFont")))
+      (:editor
+       (setq font (#/convertFont: font-manager *editor-font*))
+       (unless (%null-ptr-p font)
+	 (setq data (#/archivedDataWithRootObject: ns:ns-archiver font))
+	 (#/setObject:forKey: defaults data #@"editorFont"))))))
+
+;;; toolbar delegate methods
+
+(objc:defmethod #/toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
+		((self preferences-window-controller)
+		 toolbar itemIdentifier (flag :<BOOL>))
+  (declare (ignore toolbar))
+  (let ((item +null-ptr+))
+    (cond
+     ((#/isEqualToString: itemIdentifier #@"general")
+      (setf item (make-instance 'ns:ns-toolbar-item
+				:with-item-identifier itemIdentifier))
+      (#/setLabel: item #@"General")
+      (#/setImage: item (#/imageNamed: ns:ns-image #@"General"))
+      (#/setTarget: item self)
+      (#/setAction: item (@selector #/showGeneralPrefs:)))
+     ((#/isEqualToString: itemIdentifier #@"appearance")
+      (setf item (make-instance 'ns:ns-toolbar-item
+				:with-item-identifier itemIdentifier))
+      (#/setLabel: item #@"Appearance")
+      (#/setImage: item (#/imageNamed: ns:ns-image #@"Appearance"))
+      (#/setTarget: item self)
+      (#/setAction: item (@selector #/showAppearancePrefs:)))
+     ((#/isEqualToString: itemIdentifier #@"documentation")
+      (setf item (make-instance 'ns:ns-toolbar-item
+				:with-item-identifier itemIdentifier))
+      (#/setLabel: item #@"Documentation")
+      (#/setImage: item (#/imageNamed: ns:ns-image #@"Documentation"))
+      (#/setTarget: item self)
+      (#/setAction: item (@selector #/showDocumentationPrefs:)))
+     ((#/isEqualToString: itemIdentifier #@"encodings")
+      (setf item (make-instance 'ns:ns-toolbar-item
+				:with-item-identifier itemIdentifier))
+      (#/setLabel: item #@"Encodings")
+      (#/setImage: item (#/imageNamed: ns:ns-image #@"Encodings"))
+      (#/setTarget: item self)
+      (#/setAction: item (@selector #/showEncodingsPrefs:))))
+    (#/autorelease item)))
+
+(objc:defmethod #/toolbarDefaultItemIdentifiers:
+		((self preferences-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"general"
+		       #@"appearance"
+		       #@"documentation"
+		       #@"encodings"
+		       +null-ptr+)) ; don't even think about putting nil here
+
+(objc:defmethod #/toolbarAllowedItemIdentifiers:
+		((self preferences-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"general"
+		       #@"appearance"
+		       #@"documentation"
+		       #@"encodings"
+		       +null-ptr+))
+
+(objc:defmethod #/toolbarSelectableItemIdentifiers:
+		((self preferences-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"general"
+		       #@"appearance"
+		       #@"documentation"
+		       #@"encodings"
+		       +null-ptr+))
+
+(defun switch-content-view (window view)
+  (#/setContentView: window view)
+  (let* ((frame (#/frame window))
+	 (min-size (#/minSize window))
+	 (new-frame nil)
+	 (content-rect (#/contentRectForFrameRect: window frame))
+	 (dy (- (height view)
+		(ns-height content-rect))))
+    (decf (ns:ns-rect-y content-rect) dy)
+    (incf (ns:ns-rect-height content-rect) dy)
+    (setf (ns:ns-rect-width content-rect) (max (width view)
+					       (ns:ns-size-width min-size)))
+    (setq new-frame (#/frameRectForContentRect: window content-rect))
+    (#/setFrame:display:animate: window new-frame t t)))
+
+;;; toolbar actions
+
+(objc:defmethod (#/showGeneralPrefs: :void) ((self preferences-window-controller)
+						sender)
+  (declare (ignore sender))
+  (#/setTitle: (#/window self) #@"General")
+  (switch-content-view (#/window self) (general-prefs self)))
+
+(objc:defmethod (#/showAppearancePrefs: :void) ((self preferences-window-controller)
+						sender)
+  (declare (ignore sender))
+  (#/setTitle: (#/window self) #@"Appearance")
+  (switch-content-view (#/window self) (appearance-prefs self)))
+
+(objc:defmethod (#/showDocumentationPrefs: :void) ((self preferences-window-controller)
+						sender)
+  (declare (ignore sender))
+  (#/setTitle: (#/window self) #@"Documentation")
+  (switch-content-view (#/window self) (documentation-prefs self)))
+
+(objc:defmethod (#/showEncodingsPrefs: :void) ((self preferences-window-controller)
+						sender)
+  (declare (ignore sender))
+  (#/setTitle: (#/window self) #@"Encodings")
+  (switch-content-view (#/window self) (encodings-prefs self)))
Index: /branches/new-random/cocoa-ide/processes-window.lisp
===================================================================
--- /branches/new-random/cocoa-ide/processes-window.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/processes-window.lisp	(revision 13309)
@@ -0,0 +1,150 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+;;;
+;;;   Copyright (C) 2007 Clozure Associates
+
+(in-package "GUI")
+
+(defclass processes-window-controller (ns:ns-window-controller)
+  ((table-view :foreign-type :id :reader processes-window-table-view)
+   (toolbar :foreign-type :id :accessor processes-window-toolbar)
+   (processes :accessor processes-window-processes))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod #/init ((self processes-window-controller))
+  (setf (slot-value self 'processes) (coerce (all-processes) 'vector))
+  (#/initWithWindowNibName: self #@"processes"))
+
+(objc:defmethod (#/awakeFromNib :void) ((self processes-window-controller))
+  (with-slots (toolbar table-view) self
+    (#/setDoubleAction: table-view (@selector #/inspectSelectedProcess:))
+    (setf toolbar (make-instance 'ns:ns-toolbar
+				 :with-identifier #@"processes-window-toolbar"))
+    (#/setDisplayMode: toolbar #$NSToolbarDisplayModeLabelOnly)
+    (#/setDelegate: toolbar self)
+    (#/setToolbar: (#/window self) toolbar)
+    (#/release toolbar)))
+
+
+
+;;; toolbar delegate methods
+
+(objc:defmethod #/toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
+		((self processes-window-controller)
+		 toolbar itemIdentifier (flag :<BOOL>))
+  (declare (ignore toolbar))
+  (let ((item +null-ptr+))
+    (cond
+     ((#/isEqualToString: itemIdentifier #@"kill")
+      (setf item (make-instance 'ns:ns-toolbar-item :with-item-identifier itemIdentifier))
+      (#/setLabel: item #@"Kill")
+      (#/setTarget: item self)
+      (#/setAction: item (@selector #/killSelectedProcess:)))
+     ((#/isEqualToString: itemIdentifier #@"refresh")
+      (setf item (make-instance 'ns:ns-toolbar-item :with-item-identifier itemIdentifier))
+      (#/setLabel: item #@"Refresh")
+      (#/setTarget: item self)
+      (#/setAction: item (@selector #/refresh:))))
+    (#/autorelease item)))
+
+(objc:defmethod #/toolbarDefaultItemIdentifiers:
+		((self processes-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"kill"
+		       #&NSToolbarFlexibleSpaceItemIdentifier
+		       #@"refresh"
+		       +null-ptr+)) ; don't even think about putting nil here
+
+(objc:defmethod #/toolbarAllowedItemIdentifiers:
+		((self processes-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"refresh"
+		       #&NSToolbarFlexibleSpaceItemIdentifier
+		       #@"refresh"
+		       +null-ptr+))
+
+(objc:defmethod (#/validateToolbarItem: :<BOOL>)
+		((self processes-window-controller) item)
+  (let ((enable #$NO))
+    (cond
+     ((#/isEqualToString: (#/itemIdentifier item) #@"kill")
+      (when (plusp (#/numberOfSelectedRows (processes-window-table-view self)))
+	(setf enable #$YES)))
+     ((#/isEqualToString: (#/itemIdentifier item) #@"refresh")
+      (setf enable #$YES)))
+    enable))
+
+;;; actions
+
+(objc:defmethod (#/refresh: :void) ((self processes-window-controller) sender)
+  (declare (ignore sender))
+  (setf (slot-value self 'processes)
+	(coerce (all-processes) 'vector))
+  (#/reloadData (processes-window-table-view self)))
+
+(objc:defmethod (#/killSelectedProcess: :void) ((self processes-window-controller) sender)
+  (declare (ignore sender))
+  (let ((row (#/selectedRow (processes-window-table-view self)))
+	(p nil))
+    (unless (minusp row)
+      (setq p (svref (processes-window-processes self) row))
+      (process-kill p)
+      (#/refresh: self self))))
+
+(objc:defmethod (#/inspectSelectedProcess: :void) ((self processes-window-controller) sender)
+  (declare (ignore sender))
+  (with-slots (table-view processes) self
+    (let* ((row (#/clickedRow table-view))
+	   (p nil))
+      (unless (minusp row)
+	(setq p (svref processes row))
+	(inspect p)
+	(#/refresh: self self)))))
+
+;;; table view delegate methods
+
+(objc:defmethod (#/tableViewSelectionDidChange: :void)
+		((self processes-window-controller) notification)
+  (declare (ignore notification))
+  (with-slots (toolbar) self
+    ;; Usually, we'd just update the one item in question,
+    ;; but since there aren't many items in the toolbar,
+    ;; just be lazy.
+    (#/validateVisibleItems toolbar)))
+
+;;; table view data source methods
+
+(objc:defmethod (#/numberOfRowsInTableView: :<NSI>nteger)
+		((self processes-window-controller)
+		 table-view)
+  (declare (ignore table-view))
+  (length (slot-value self 'processes)))
+
+(objc:defmethod #/tableView:objectValueForTableColumn:row:
+		((self processes-window-controller)
+		 table-view
+		 table-column
+		 (row :<NSI>nteger))
+  (declare (ignore table-view))
+  (with-slots (processes) self
+    (let ((fn nil)
+	  (p (svref processes row)))
+      (cond
+       ((#/isEqualToString: (#/identifier table-column) #@"name")
+	(setq fn #'process-name))
+       ((#/isEqualToString: (#/identifier table-column) #@"state")
+	(setq fn #'process-whostate))
+       ((#/isEqualToString: (#/identifier table-column) #@"thread")
+	(setq fn #'process-thread))
+       ((#/isEqualToString: (#/identifier table-column) #@"suspend count")
+	(setq fn #'process-suspend-count)))
+      (if (and p fn)
+	(#/autorelease (%make-nsstring (format nil "~a" (funcall fn p))))
+	+null-ptr+))))
+
+#|
+(in-package "CCL")
+(load "~rme/processes-window")
+(setf *pwc* (make-instance 'processes-window-controller))
+(#/showWindow: *pwc* *pwc*)
+
+|#
Index: /branches/new-random/cocoa-ide/project.lisp
===================================================================
--- /branches/new-random/cocoa-ide/project.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/project.lisp	(revision 13309)
@@ -0,0 +1,403 @@
+(in-package "GUI")
+
+;;; This file contains a project browser for the CCL IDE. A "project" is
+;;; just the set of ASDF systems defined in the same file.
+;;; 
+;;; To browse a project, run (gui::make-project-window :project-name). The
+;;; project name is the name of the .asd file. However, if the .asd has been
+;;; loaded, then the project browser can be opened using the name of any of the
+;;; systems defined in that file.
+;;;
+;;; Todo:
+;;; â¢ support modification without resorting to editor window
+;;; â¢ raise window if project already open
+;;; â¢ handle #-ccl sections in .asd
+;;; â¢ support arbitrary operations
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :asdf))
+
+(defclass project-window-controller (ns:ns-window-controller)
+  ((system-view :foreign-type :id :accessor system-view) ; IBOutlet
+   (component-view :foreign-type :id :accessor component-view) ; IBOutlet
+
+   ;; Info Panel fields
+   (info-panel :foreign-type :id :accessor info-panel) ; IBOutlet
+   (name-label :foreign-type :id)
+   (version-label :foreign-type :id)
+   (author-label :foreign-type :id)
+   (maintainer-label :foreign-type :id)
+   (licence-label :foreign-type :id)
+   (description-label :foreign-type :id)
+   (long-description-label :foreign-type :id)
+
+   (system-menu :foreign-type :id :accessor system-menu) ; IBOutlet set by NIB
+   (item-menu :foreign-type :id :accessor item-menu) ; IBOutlet set by NIB
+   (op-button :foreign-type :id :accessor op-button) ; IBOutlet set by NIB
+   (toolbar-items :foreign-type :id :accessor toolbar-items)
+   (project-item :initarg :project-item :reader project-item)
+   (components-field :reader components-field
+                     :initform (make-instance 'ns:ns-text-field-cell
+                                 :text-cell #@"Components"))
+   (dependencies-field :reader dependencies-field
+                       :initform (make-instance 'ns:ns-text-field-cell
+                                   :text-cell #@"Dependencies")))
+  (:metaclass ns:+ns-object))
+
+(defmethod current-system-item (controller)
+  (#/objectAtIndex: (systems (project-item controller))
+                    (#/selectedRow (system-view controller))))
+
+;;; Need to represent system in a way that the NSOutlineView likes
+
+(defclass component-item (ns:ns-object)
+  ((name :foreign-type :id :accessor name))
+  (:metaclass ns:+ns-object))
+
+(defclass module-item (component-item)
+  ((components :foreign-type :id :accessor components
+               :initform (make-instance 'ns:ns-mutable-array)))
+  (:metaclass ns:+ns-object))
+
+(defclass project-item (ns:ns-object)
+  ((name :foreign-type :id :accessor name)
+   (systems :foreign-type :id :accessor systems
+            :initform (make-instance 'ns:ns-mutable-array)))
+  (:metaclass ns:+ns-object))
+
+(defclass system-item (module-item)
+  ((system :accessor system))
+  (:metaclass ns:+ns-object))
+
+(defclass dependency-item (ns:ns-object)
+  ((name :foreign-type :id :accessor name)
+   (operations :foreign-type :id :accessor operations
+               :initform (make-instance 'ns:ns-mutable-array)))
+  (:metaclass ns:+ns-object))
+
+(defclass file-item (component-item)
+  ((location :foreign-type :id :accessor location))
+  (:metaclass ns:+ns-object))
+
+(defmethod (setf component) (component (object component-item))
+  (setf (name object) (%make-nsstring (asdf:component-name component))))
+
+(defmethod (setf component) (component (object module-item))
+  (call-next-method)
+  (setf (components object) (make-instance 'ns:ns-mutable-array))
+  (mapc (lambda (com)
+          (#/addObject: (components object)
+                        (let ((obj (make-instance
+                                       (typecase com
+                                         (asdf:system 'system-item)
+                                         (asdf:module 'module-item)
+                                         (asdf:source-file 'file-item)))))
+                          (setf (component obj) com)
+                          obj)))
+        (asdf:module-components component)))
+
+(defmethod (setf component) (component (object system-item))
+  (call-next-method)
+  (setf (system object) component))
+
+(defmethod (setf component) (component (object file-item))
+  (call-next-method)
+  (setf (location object)
+        (%make-nsstring (namestring (asdf:component-pathname component)))))
+
+(objc:defmethod #/init ((self project-window-controller))
+  (#/setShouldCascadeWindows: self t)
+  (#/initWithWindowNibName: self #@"project"))
+
+(objc:defmethod (#/awakeFromNib :void) ((self project-window-controller))
+  (with-slots (system-view component-view
+               system-menu item-menu
+               op-button toolbar-items)
+              self
+    (let ((toolbar (make-instance 'ns:ns-toolbar
+                     :with-identifier #@"projectbar")))
+      (setf (#/allowsUserCustomization toolbar) t
+            (#/delegate toolbar) self)
+      (setf toolbar-items (make-instance 'ns:ns-mutable-dictionary))
+      (let ((op-item (make-instance 'ns:ns-toolbar-item
+                       :with-item-identifier #@"operate")))
+        (setf (#/label op-item) #@"Operate"
+              (#/paletteLabel op-item) #@"Operate")
+        (let* ((op-menu (#/menu op-button)))
+          (loop for i from 1 to (1- (#/numberOfItems op-menu)) ; 0 is blank
+            do (let ((item (#/itemAtIndex: op-menu i)))
+                 (#/setTarget: item self)
+                 (#/setAction: item (@selector #/operate:)))))
+        (setf (#/view op-item) op-button
+              (#/objectForKey: toolbar-items #@"operate") op-item))
+      (let ((toolbar-item (make-instance 'ns:ns-toolbar-item
+                            :with-item-identifier #@"info")))
+        (setf (#/label toolbar-item) #@"Get Info"
+              (#/paletteLabel toolbar-item) #@"Get Info"
+              (#/image toolbar-item) (#/imageNamed: ns:ns-image #@"info")
+              (#/target toolbar-item) self
+              (#/action toolbar-item) (@selector #/showInfoPanel)
+              (#/objectForKey: toolbar-items #@"info") toolbar-item))
+      (let ((toolbar-item (make-instance 'ns:ns-toolbar-item
+                            :with-item-identifier #@"edit")))
+        (setf (#/label toolbar-item) #@"Edit"
+              (#/paletteLabel toolbar-item) #@"Edit"
+              (#/image toolbar-item) (#/imageNamed: ns:ns-image #@"font-panel")
+              (#/target toolbar-item) self
+              (#/action toolbar-item) (@selector #/openSystem:)
+              (#/objectForKey: toolbar-items #@"edit") toolbar-item))
+      (#/setToolbar: (#/window self) toolbar))
+    (let ((mi0 (#/itemAtIndex: system-menu 0)) ; Operate
+          (mi1 (#/itemAtIndex: system-menu 1)) ; Get Info
+          (mi2 (#/itemAtIndex: system-menu 2))) ; Edit
+      (let* ((op-menu (#/menu mi0)))
+        (loop for i from 0 to (1- (#/numberOfItems op-menu))
+          do (let ((item (#/itemAtIndex: op-menu i)))
+               (setf (#/enabled item) t
+                     (#/target item) self
+                     (#/action item) (@selector #/operate:)))))
+      (setf (#/enabled mi1) t
+            (#/target mi1) self
+            (#/action mi1) (@selector #/showInfoPanel))
+      (setf (#/enabled mi2) t
+            (#/target mi2) self
+            (#/action mi2) (@selector #/openSystem:)))
+    (setf (#/target system-view) self
+          (#/doubleAction system-view) (@selector #/openSystem:))
+    (let ((mi0 (#/itemAtIndex: item-menu 0)) ; Open
+          (mi1 (#/itemAtIndex: item-menu 1)) ; Compile
+          (mi2 (#/itemAtIndex: item-menu 2))) ; Compile and Load
+      (setf (#/enabled mi0) t
+            (#/target mi0) self
+            (#/action mi0) (@selector #/openComponent:))
+      (setf (#/enabled mi1) t
+            (#/target mi1) self
+            (#/action mi1) (@selector #/compileComponent:))
+      (setf (#/enabled mi2) t
+            (#/target mi2) self
+            (#/action mi2) (@selector #/compileAndLoadComponent:)))
+    (setf (#/target component-view) self
+          (#/doubleAction component-view) (@selector #/openComponent:))))
+
+(objc:defmethod (#/showInfoPanel :void) ((self project-window-controller))
+  (with-slots (info-panel name-label version-label author-label maintainer-label
+               licence-label description-label long-description-label)
+    self
+    (let ((system (system (current-system-item self))))
+      (#/makeKeyAndOrderFront: info-panel self)
+      (setf (#/stringValue name-label)
+            (%make-nsstring (asdf:component-name system))
+            (#/stringValue version-label)
+            (%make-nsstring (handler-case (asdf:component-version system)
+                              (slot-unbound () "")))
+            (#/stringValue author-label)
+            (%make-nsstring (handler-case (asdf:system-author system)
+                              (slot-unbound () "")))
+            (#/stringValue maintainer-label)
+            (%make-nsstring (handler-case (asdf:system-maintainer system)
+                              (slot-unbound () "")))
+            (#/stringValue licence-label)
+            (%make-nsstring (handler-case (asdf:system-licence system)
+                              (slot-unbound () "")))
+            (#/stringValue description-label)
+            (%make-nsstring (handler-case (asdf:system-description system)
+                              (slot-unbound () "")))
+            (#/stringValue long-description-label)
+            (%make-nsstring (handler-case
+                                (asdf:system-long-description system)
+                              (slot-unbound () "")))))))
+
+;;; NSToolbar delegate methods
+
+(objc:defmethod #/toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
+                ((self project-window-controller)
+                 toolbar itemIdentifier (flag :<BOOL>))
+  (declare (ignore toolbar))
+  (#/objectForKey: (toolbar-items self) itemIdentifier))
+
+(objc:defmethod #/toolbarAllowedItemIdentifiers:
+                ((self project-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/allKeys (toolbar-items self)))
+
+(objc:defmethod #/toolbarDefaultItemIdentifiers:
+                ((self project-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"operate" #@"info" #@"edit" +null-ptr+))
+
+(objc:defmethod (#/openSystem: :void) ((self project-window-controller) sender)
+  (declare (ignore sender))
+  (find-or-make-hemlock-view
+   (asdf:system-source-file (lisp-string-from-nsstring
+                             (name (project-item self))))))
+
+(objc:defmethod (#/openComponent: :void)
+                ((self project-window-controller) sender)
+  (declare (ignore sender))
+  (let ((row (#/clickedRow (component-view self))))
+    (unless (minusp row)
+      (let ((item (#/itemAtRow: (component-view self) row)))
+        (typecase item 
+          (file-item (find-or-make-hemlock-view
+                      (lisp-string-from-nsstring (location item))))
+          (ns:ns-string (make-project-window
+                         (make-symbol (string-upcase (lisp-string-from-nsstring
+                                                      item))))))))))
+
+(objc:defmethod (#/compileComponent: :void)
+                ((self project-window-controller) sender)
+  (declare (ignore sender))
+  (let ((row (#/clickedRow (component-view self))))
+    (unless (minusp row)
+      (let ((item (#/itemAtRow: (component-view self) row)))
+        (when (typep item 'file-item)
+          (ui-object-compile-buffer *NSApp*
+                                    (list :cl-user
+                                          (lisp-string-from-nsstring
+                                           (location item)))))))))
+
+(objc:defmethod (#/compileAndLoadComponent: :void)
+                ((self project-window-controller) sender)
+  (declare (ignore sender))
+  (let ((row (#/clickedRow (component-view self))))
+    (unless (minusp row)
+      (let ((item (#/itemAtRow: (component-view self) row)))
+        (when (typep item 'file-item)
+          (ui-object-compile-and-load-buffer
+           *NSApp*
+           (list :cl-user (lisp-string-from-nsstring (location item)))))))))
+
+(objc:defmethod (#/operate: :void) ((self project-window-controller) sender)
+  (let* ((target-listener (ui-object-choose-listener-for-selection *NSApp*
+                                                                   nil)))
+    (when target-listener
+      (let ((string (format nil "(asdf:oos 'asdf:~A-op :~A)"
+                            (substitute #\-
+                                        #\space
+                                        (lisp-string-from-nsstring
+                                         (#/title sender)))
+                            (if (= (#/compare: (#/title (#/menu sender))
+                                               #@"project-operations")
+                                   #$NSOrderedSame)
+                              (lisp-string-from-nsstring
+                               (name (project-item self)))
+                              (asdf:component-name
+                               (system (current-system-item self)))))))
+        (eval-in-listener-process target-listener string)))))
+
+(defmethod (setf project-item)
+           ((value asdf:system) (self project-window-controller))
+  (let ((proj (make-instance 'project-item))
+        (proj-name (pathname-name (asdf:system-source-file value))))
+    (setf (name proj) (%make-nsstring proj-name))
+    (setf (systems proj) (make-instance 'ns:ns-mutable-array))
+    (mapc (lambda (system)
+            (let ((component (make-instance 'system-item)))
+              (setf (component component) system)
+              (#/addObject: (systems proj) component)))
+          (find-related-systems value))
+    (setf (slot-value self 'project-item) proj)
+    (#/setTitle: (#/window self)
+                 (%make-nsstring (concatenate 'string
+                                              proj-name " â Project"))))
+  (#/reloadData (component-view self)))
+
+;;; NSTableView data source methods
+
+(objc:defmethod (#/tableView:objectValueForTableColumn:row: :id)
+                ((self project-window-controller)
+                 table-view column (row :<NSI>nteger))
+  (declare (ignore table-view column))
+  (name (#/objectAtIndex: (systems (project-item self)) row)))
+
+(objc:defmethod (#/numberOfRowsInTableView: :<NSI>nteger)
+                ((self project-window-controller) table-view)
+  (declare (ignore table-view))
+  (#/count (systems (project-item self))))
+
+(objc:defmethod (#/tableViewSelectionDidChange: :void)
+                ((self project-window-controller) sender)
+  (declare (ignore sender))
+  (#/reloadData (component-view self)))
+
+;;; NSOutlineView data source methods
+
+(objc:defmethod (#/outlineView:child:ofItem: :id)
+                ((self project-window-controller)
+                 outline-view (index :<NSI>nteger) item)
+  (declare (ignore outline-view))
+  (cond ((eql item +null-ptr+) (case index
+                                 (0 (components-field self))
+                                 (1 (dependencies-field self))))
+        ((typep item 'component-item)
+         (#/objectAtIndex: (components item) index))
+        ((eql item (components-field self))
+         (#/objectAtIndex: (components (current-system-item self)) index))
+        ((eql item (dependencies-field self))
+         (let ((dependency (nth index
+                                (remove (asdf:component-name
+                                         (system (current-system-item self)))
+                                        (reduce #'union
+                                                (asdf:component-depends-on
+                                                 'asdf:load-op
+                                                 (system (current-system-item
+                                                          self)))
+                                                :key #'cdr)))))
+           (%make-nsstring (if (consp dependency)
+                             (second dependency)
+                             dependency))))))
+
+(objc:defmethod (#/outlineView:isItemExpandable: :<BOOL>)
+                ((self project-window-controller) outline-view item)
+  (declare (ignore outline-view))
+  (not (or (typep item 'file-item) (typep item 'ns:ns-string))))
+
+(objc:defmethod (#/outlineView:numberOfChildrenOfItem: :<NSI>nteger)
+                ((self project-window-controller) outline-view item)
+  (declare (ignore outline-view))
+  (cond ((eql item +null-ptr+) 2)
+        ((typep item 'component-item) (#/count (components item)))
+        ((eql item (components-field self))
+         (#/count (components (current-system-item self))))
+        ((eql item (dependencies-field self))
+         (length (remove (asdf:component-name (system (current-system-item
+                                                       self)))
+                         (reduce #'union
+                                 (asdf:component-depends-on
+                                  'asdf:load-op
+                                  (system (current-system-item self)))
+                                 :key #'cdr))))))
+
+(objc:defmethod (#/outlineView:objectValueForTableColumn:byItem: :id)
+                ((self project-window-controller) outline-view column item)
+  (declare (ignore outline-view column))
+  (cond ((eql item +null-ptr+) (name (current-system-item self)))
+        ((typep item 'component-item) (name item))
+        (t item)))
+
+(objc:defmethod (#/outlineView:shouldSelectItem: :<BOOL>)
+                ((self project-window-controller) outline-view item)
+  (declare (ignore outline-view))
+  (not (typep item 'ns:ns-text-field-cell)))
+
+(objc:defmethod (#/outlineView:isGroupItem: :<BOOL>)
+                ((self project-window-controller) outline-view item)
+  (declare (ignore outline-view))
+  (typep item 'ns:ns-text-field-cell))
+
+(defgeneric make-project-window (obj)
+  (:method ((obj asdf:system))
+           (let ((controller (make-instance 'project-window-controller)))
+             (setf (project-item controller) obj)
+             (#/showWindow: controller nil)
+             controller))
+  (:method (obj)
+           (make-project-window (asdf:find-system obj))))
+
+(defun find-related-systems (obj)
+  "This just uses our assumption that a project is the set of systems in a
+   single .asd. It just finds all the systems with the same system-source-file."
+  (let ((system-file (asdf:system-source-file (asdf:find-system obj))))
+    (loop for system being the hash-values of asdf::*defined-systems*
+      if (equal (asdf:system-source-file (cdr system)) system-file)
+      collect (cdr system))))
Index: /branches/new-random/cocoa-ide/search-files.lisp
===================================================================
--- /branches/new-random/cocoa-ide/search-files.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/search-files.lisp	(revision 13309)
@@ -0,0 +1,441 @@
+(in-package "GUI")
+
+(defstruct search-result-file 
+  name ;A lisp string that contains the full path of the file
+  nsstr  ;An NSString that is shown in the dialog
+  lines ;A vector of search-result-lines
+  )
+
+(defstruct search-result-line 
+  file ;The search-result-file that contains this search-result-line
+  number ;An integer that is the line-number of the line
+  nsstr ;The NSString used in the dialog
+  )
+
+(defmethod print-object ((srl search-result-line) stream)
+  (print-unreadable-object (srl stream :type t)
+    (format stream "~a ~a ~s" 
+            (search-result-line-file srl)
+            (search-result-line-number srl)
+            (search-result-line-nsstr srl))))
+
+(defconstant $find-combo-box-tag 0)
+(defconstant $folder-combo-box-tag 1)
+(defconstant $file-name-combo-box-tag 2)
+
+(defparameter *search-files-history-limit* 5 "combo box history length")
+
+(defclass search-files-window-controller (ns:ns-window-controller)
+  ((find-combo-box :foreign-type :id :accessor find-combo-box)
+   (folder-combo-box :foreign-type :id :accessor folder-combo-box)
+   (file-name-combo-box :foreign-type :id :accessor file-name-combo-box)
+   (search-button :foreign-type :id :accessor search-button)
+   (browse-button :foreign-type :id :accessor browse-button)
+   (outline-view :foreign-type :id :accessor outline-view)
+   (recursive-checkbox :foreign-type :id :accessor recursive-checkbox)
+   (case-sensitive-checkbox :foreign-type :id :accessor case-sensitive-checkbox)
+   (expand-results-checkbox :foreign-type :id :accessor expand-results-checkbox)
+   (progress-indicator :foreign-type :id :accessor progress-indicator)
+   (status-field :foreign-type :id :accessor status-field)
+   (find-string-value :foreign-type :id :reader find-string-value)
+   (folder-string-value :foreign-type :id :reader folder-string-value)
+   (file-name-string-value :foreign-type :id :reader file-name-string-value)
+   (results :initform (make-array 10 :fill-pointer 0 :adjustable t)
+	    :accessor search-results) ;contains a vector of search-result-files
+   (new-results :accessor new-results)
+   (search-dir :initform "" :accessor search-dir) ;the expanded search directory
+   (search-str :initform "" :accessor search-str) ;a lisp string
+   (recursive-p :initform t :reader recursive-p)
+   (case-sensitive-p :initform nil :reader case-sensitive-p)
+   (expand-results-p :initform nil :reader expand-results-p))
+  (:metaclass ns:+ns-object))
+
+(defmacro def-copying-setter (slot-name class-name)
+  (let* ((new (gensym))
+	 (obj (gensym)))
+    `(defmethod (setf ,slot-name) (,new (,obj ,class-name))
+       (with-slots (,slot-name) ,obj
+	 (unless (eql ,slot-name ,new)
+	   (#/release ,slot-name)
+	   (setq ,slot-name (#/copy ,new)))))))
+
+(def-copying-setter find-string-value search-files-window-controller)
+(def-copying-setter folder-string-value search-files-window-controller)
+(def-copying-setter file-name-string-value search-files-window-controller)
+
+
+
+
+;;; Enable and disable the Search button according to the state of the
+;;; search files dialog.
+
+(defun can-search-p (wc)
+  (and (plusp (#/length (find-string-value wc)))
+       (folder-valid-p wc)
+       (plusp (#/length (file-name-string-value wc)))))
+
+(defmethod folder-valid-p ((wc search-files-window-controller))
+  (let* ((fm (#/defaultManager ns:ns-file-manager))
+	 (path (folder-string-value wc)))
+    (rlet ((dir-p #>BOOL))
+      (and
+       (#/fileExistsAtPath:isDirectory: fm path dir-p)
+       (plusp (%get-byte dir-p))))))
+
+(objc:defmethod (#/controlTextDidChange: :void) ((wc search-files-window-controller) notification)
+  (let* ((object (#/object notification))
+	 (info (#/userInfo notification))
+	 (field-editor (#/valueForKey: info #@"NSFieldEditor"))
+	 (string-ok (plusp (#/length (find-string-value wc))))
+	 (folder-ok (folder-valid-p wc))
+	 (file-ok (plusp (#/length (file-name-string-value wc)))))
+    (cond ((eql object (find-combo-box wc))
+	   (setf string-ok (plusp (#/length (#/string field-editor)))))
+	  ((eql object (folder-combo-box wc))
+	   (setf (folder-string-value wc) (#/string field-editor))
+	   (setf folder-ok (folder-valid-p wc)))
+	  ((eql object (file-name-combo-box wc))
+	   (setf file-ok (#/length (#/string field-editor)))))
+    (#/setEnabled: (search-button wc) (and string-ok folder-ok file-ok))))
+
+(objc:defmethod (#/comboBoxSelectionDidChange: :void) ((wc search-files-window-controller) notification)
+  (declare (ignore notification))
+  (#/setEnabled: (search-button wc) (can-search-p wc)))
+
+(objc:defmethod (#/toggleCheckbox: :void) ((wc search-files-window-controller) checkbox)
+  (with-slots (recursive-checkbox case-sensitive-checkbox expand-results-checkbox
+	       recursive-p case-sensitive-p expand-results-p) wc
+    (cond ((eql checkbox recursive-checkbox)
+	   (setf recursive-p (not recursive-p)))
+	  ((eql checkbox case-sensitive-checkbox)
+	   (setf case-sensitive-p (not case-sensitive-p)))
+	  ((eql checkbox expand-results-checkbox)
+	   (setf expand-results-p (not expand-results-p))
+	   (if expand-results-p
+	     (expand-all-results wc)
+	     (collapse-all-results wc))
+	   (#/reloadData (outline-view wc)))
+	  (t
+	   (error "Unknown checkbox ~s" checkbox)))))
+
+;;; For simple strings, it's easier to use the combo box's built-in
+;;; list than it is to mess around with a data source.
+
+(defun update-combo-box (combo-box string)
+  (check-type string ns:ns-string)
+  (unless (#/isEqualToString: string #@"")
+    (#/removeItemWithObjectValue: combo-box string)
+    (#/insertItemWithObjectValue:atIndex: combo-box string 0)
+    (when (> (#/numberOfItems combo-box) *search-files-history-limit*)
+      (#/removeItemAtIndex: combo-box *search-files-history-limit*))))
+
+(objc:defmethod (#/updateFindString: :void) ((wc search-files-window-controller)
+					     sender)
+  (setf (find-string-value wc) (#/stringValue sender))
+  (update-combo-box sender (find-string-value wc)))
+
+(objc:defmethod (#/updateFolderString: :void) ((wc search-files-window-controller) sender)
+  (setf (folder-string-value wc) (#/stringValue sender))
+  (update-combo-box sender (folder-string-value wc)))
+
+(objc:defmethod (#/updateFileNameString: :void) ((wc search-files-window-controller) sender)
+  (setf (file-name-string-value wc) (#/stringValue sender))
+  (update-combo-box sender (file-name-string-value wc)))
+
+
+
+
+(objc:defmethod #/init ((self search-files-window-controller))
+  (prog1
+      (#/initWithWindowNibName: self #@"SearchFiles")
+    (#/setShouldCascadeWindows: self nil)))
+
+(defloadvar *search-files-cascade-point* (ns:make-ns-point 0 0))
+
+(objc:defmethod (#/windowDidLoad :void) ((wc search-files-window-controller))
+  ;; Cascade window from the top left point of the topmost search files window.
+  (flet ((good-window-p (w)
+           (and (not (eql w (#/window wc)))
+                (eql (#/class (#/windowController w))
+                     (find-class 'search-files-window-controller)))))
+    (let* ((dialogs (remove-if-not #'good-window-p (gui::windows)))
+           (top-dialog (car dialogs)))
+      (if top-dialog
+        (ns:with-ns-point (zp 0 0)
+          (setq *search-files-cascade-point*
+                (#/cascadeTopLeftFromPoint: top-dialog zp))))))
+  (#/cascadeTopLeftFromPoint: (#/window wc) *search-files-cascade-point*))
+
+(objc:defmethod (#/awakeFromNib :void) ((wc search-files-window-controller))
+  (#/setStringValue: (status-field wc) #@"")
+  (with-slots (outline-view) wc
+    (#/setTarget: outline-view wc)
+    (#/setDoubleAction: outline-view (@selector #/editLine:)))
+  (setf (find-string-value wc) #@"")
+  (with-slots (file-name-combo-box) wc
+    (#/setStringValue: file-name-combo-box #@"*.lisp")
+    (#/updateFileNameString: wc file-name-combo-box))
+  (with-slots (folder-combo-box) wc
+    (let ((dir (ccl::native-translated-namestring (ccl:current-directory))))
+    (#/setStringValue: folder-combo-box
+		       (#/autorelease (%make-nsstring dir)))
+    (#/updateFolderString: wc folder-combo-box))))
+
+(defun ns-string-equal (ns1 ns2)
+  (and (typep ns1 'ns:ns-string)
+       (typep ns2 'ns:ns-string)
+       (#/isEqualToString: ns1 ns2)))
+
+(defmethod get-full-dir-string ((str string))
+  ;make sure it has a trailing slash
+  (let ((ret (ccl::native-untranslated-namestring str)))
+    (unless (eql #\/ (aref str (1- (length str))))
+      (setf ret (concatenate 'string ret "/")))
+    ret))
+
+(defmethod get-full-dir-string ((nsstring ns:ns-string))
+  (get-full-dir-string (lisp-string-from-nsstring nsstring)))
+
+(objc:defmethod (#/doSearch: :void) ((wc search-files-window-controller) sender)
+  (declare (ignore sender))
+  (set-results-string wc #@"Searching...")
+  (setf (find-string-value wc) (#/stringValue (find-combo-box wc))
+	(folder-string-value wc) (#/stringValue (folder-combo-box wc))
+	(file-name-string-value wc) (#/stringValue (file-name-combo-box wc)))
+  (let* ((find-str (lisp-string-from-nsstring (find-string-value wc)))
+	 (folder-str (lisp-string-from-nsstring (folder-string-value wc)))
+	 (file-str (lisp-string-from-nsstring (file-name-string-value wc)))
+	 (grep-args (list "-I" "-s" "-c" "-e" find-str "--include" file-str
+			  (get-full-dir-string folder-str))))
+    (when (recursive-p wc)
+      (push "-r" grep-args))
+    (unless (case-sensitive-p wc)
+      (push "-i" grep-args))
+    (setf (search-dir wc) folder-str
+	  (search-str wc) find-str)
+    (#/setEnabled: (search-button wc) nil)
+    (process-run-function "grep" 'run-grep grep-args wc)
+    (#/setTitle: (#/window wc) (#/autorelease
+				(%make-nsstring (format nil "Search Files: ~a"
+							find-str))))))
+
+(defun auto-expandable-p (results)
+  (let ((n 0))
+    (dotimes (f (length results) t)
+      (dotimes (l (length (search-result-file-lines (aref results f))))
+	(incf n)
+	(when (> n 20)
+	  (return-from auto-expandable-p nil))))))
+
+(objc:defmethod (#/updateResults: :void) ((wc search-files-window-controller)
+					  msg)
+  (let* ((old-results (search-results wc)))
+    (setf (search-results wc) (new-results wc))
+    ;; release NSString instances.  sigh.
+    (dotimes (idx (length old-results))
+      (let* ((file (aref old-results idx))
+             (lines (when file (search-result-file-lines file))))
+        (dotimes (idx (length lines))
+          (let* ((line (aref lines idx))
+                 (string (when line (search-result-line-nsstr line))))
+            (and string (#/release string))))
+        (and (search-result-file-nsstr file)
+             (#/release (search-result-file-nsstr file)))))
+    (set-results-string wc msg)
+;;     (when (or (auto-expandable-p (search-results wc))
+;;              (expand-results-p wc))
+;;       (expand-all-results wc))
+    (#/reloadData (outline-view wc))
+    (#/setEnabled: (search-button wc) t)))
+
+;;; This is run in a secondary thread.
+(defun run-grep (grep-arglist wc)
+  (with-autorelease-pool 
+      (#/performSelectorOnMainThread:withObject:waitUntilDone:
+       (progress-indicator wc) (@selector #/startAnimation:) nil t)
+    (unwind-protect
+	 (let* ((grep-output (call-grep grep-arglist)))
+	   (multiple-value-bind (results message)
+	       (results-and-message grep-output wc)
+	     ;; This assumes that only one grep can be running at
+	     ;; a time.
+	     (setf (new-results wc) results)
+	     (#/performSelectorOnMainThread:withObject:waitUntilDone:
+	      wc
+	      (@selector #/updateResults:)
+	      (#/autorelease (%make-nsstring message))
+	      t)))
+      (#/performSelectorOnMainThread:withObject:waitUntilDone:
+       (progress-indicator wc) (@selector #/stopAnimation:) nil t))))
+
+(defun results-and-message (grep-output wc)
+  (let* ((results (make-array 10 :fill-pointer 0 :adjustable t))
+	 (occurrences 0)
+	 (file-count 0)
+	 (dir-len (length (search-dir wc))))
+    (map-lines
+     grep-output
+     #'(lambda (start end)
+	 (let* ((colon-pos (position #\: grep-output :from-end t :start start
+				     :end end))
+		(count (and colon-pos
+			    (parse-integer grep-output :start (1+ colon-pos)
+					   :end end))))
+	   (when count
+	     (incf file-count)
+	     (when (> count 0)
+	       (vector-push-extend (make-search-result-file
+				    :name (subseq grep-output
+						  (+ start dir-len)
+						  colon-pos)
+				    :lines (make-array count :initial-element nil))
+				   results)
+	       (incf occurrences count))))))
+    (values results
+	    (format nil "Found ~a occurrence~:p in ~a file~:p out of ~a ~
+                         file~:p searched." occurrences (length results)
+			 file-count))))
+		   
+(defmethod expand-all-results ((wc search-files-window-controller))
+  (with-slots (outline-view) wc
+    (#/expandItem:expandChildren: outline-view +null-ptr+ t)
+    (#/reloadData outline-view)))
+
+(defmethod collapse-all-results ((wc search-files-window-controller))
+  (with-slots (outline-view) wc
+    (#/collapseItem:collapseChildren: outline-view +null-ptr+ t)
+    (#/reloadData outline-view)))
+
+(defun set-results-string (wc str)
+  (#/setStringValue: (status-field wc) str))
+	    
+(objc:defmethod (#/doBrowse: :void) ((wc search-files-window-controller) sender)
+  (declare (ignore sender))
+  (let ((pathname (cocoa-choose-directory-dialog)))
+    (when pathname
+      (ccl::with-autoreleased-nsstring
+	  (dir (native-translated-namestring pathname))
+	(with-slots (folder-combo-box) wc
+	  (#/setStringValue: folder-combo-box dir)
+	  (#/updateFolderString: wc folder-combo-box))))))
+
+(objc:defmethod (#/editLine: :void) ((wc search-files-window-controller) outline-view)
+  (let* ((item (get-selected-item outline-view))
+         (line-result (and item (nsstring-to-line-result wc item))))
+    (unless line-result
+      (let ((file-result (and item (nsstring-to-file-result wc item))))
+        (when file-result
+          (setf line-result (get-line-result wc file-result 0)))))          
+    (when line-result
+      (cocoa-edit-grep-line (concatenate 'string (search-dir wc) "/" (search-result-line-file line-result))
+                      (1- (search-result-line-number line-result))))))
+
+(defun get-selected-item (outline-view)
+  (let ((index (#/selectedRow outline-view)))
+    (when (> index -1)
+      (#/itemAtRow: outline-view (#/selectedRow outline-view)))))
+
+(defun nsstring-to-file-result (wc nsstring)
+  (find nsstring (search-results wc) :test #'ns-string-equal :key #'search-result-file-nsstr))
+
+(defun nsstring-to-line-result (wc nsstring)
+  (loop for file-result across (search-results wc)
+    do (loop for line-result across (search-result-file-lines file-result)
+         while line-result
+         do (when (ns-string-equal nsstring (search-result-line-nsstr line-result))
+              (return-from nsstring-to-line-result line-result)))))
+
+;;NSOutlineView data source protocol
+;- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
+(objc:defmethod #/outlineView:child:ofItem: ((wc search-files-window-controller) view (child :<NSI>nteger) item)
+  (declare (ignore view))
+  (with-slots (results) wc
+    (if (eql item +null-ptr+)
+      (let ((result (aref results child)))
+        (or (search-result-file-nsstr result)
+            (setf (search-result-file-nsstr result)
+                  (%make-nsstring (format nil "[~a] ~a" 
+                                          (length (search-result-file-lines result))
+                                          (search-result-file-name result))))))
+      (let* ((file-result (nsstring-to-file-result wc item))
+             (line-result (get-line-result wc file-result child)))
+        (search-result-line-nsstr line-result)))))
+
+(defun get-line-result (wc file-result index)
+  (let ((lines (search-result-file-lines file-result)))
+    (or (aref lines index)
+        (progn
+          (compute-line-results wc file-result)
+          (aref lines index)))))
+
+(defun compute-line-results (wc file-result)
+  (with-slots (search-str search-dir) wc
+    (let* ((grep-output (call-grep (nconc (unless (case-sensitive-p wc) (list "-i"))
+                                          (list "-n" "-e" search-str 
+                                                (concatenate 'string search-dir (search-result-file-name file-result))))))
+           (index -1))
+      (map-lines grep-output
+                 #'(lambda (start end)
+                     (let* ((str (subseq grep-output start end))
+                            (colon-pos (position #\: str))
+                            (num (parse-integer str :end colon-pos)))
+                       (setf (aref (search-result-file-lines file-result) (incf index))
+                             (make-search-result-line :file (search-result-file-name file-result) 
+                                                      :number num 
+                                                      :nsstr (%make-nsstring str)))))))))
+
+;- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
+(objc:defmethod (#/outlineView:isItemExpandable: :<BOOL>) ((wc search-files-window-controller) view item)
+  (declare (ignore view))
+  ;;it's expandable if it starts with #\[ (it's a file)
+  (and (typep item 'ns:ns-string)
+       (= (char-code #\[) (#/characterAtIndex: item 0))))
+
+;- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
+(objc:defmethod (#/outlineView:numberOfChildrenOfItem: :<NSI>nteger)
+                ((wc search-files-window-controller) view item)
+  (declare (ignore view))
+  (if (eql item +null-ptr+)
+    (length (search-results wc))
+    (let ((file-result (nsstring-to-file-result wc item)))
+      (if file-result
+        (length (search-result-file-lines file-result))
+        0))))
+
+;- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
+(objc:defmethod #/outlineView:objectValueForTableColumn:byItem: 
+                ((wc search-files-window-controller) outline-view table-column item)
+  (declare (ignore outline-view table-column))
+  (let ((file-result (nsstring-to-file-result wc item)))
+    (if file-result
+      (search-result-file-nsstr file-result)
+      (let ((line-result (nsstring-to-line-result wc item)))
+        (if line-result
+          (search-result-line-nsstr line-result)
+          #@"ERROR")))))
+
+(defun call-grep (args)
+  ;;Calls grep with the strings as arguments, and returns a string containing the output
+  (with-output-to-string (stream)
+    (let* ((proc (run-program "grep" args :input nil :output stream)))
+      (multiple-value-bind (status exit-code) (external-process-status proc)
+	(let ((output (get-output-stream-string stream)))
+	  (if (eq :exited status)
+	    (return-from call-grep output)
+            (error "~a returned exit status ~s" *grep-program* exit-code)))))))
+
+(defun map-lines (string fn)
+  "For each line in string, fn is called with the start and end of the line"
+  (loop with end = (length string)
+    for start = 0 then (1+ pos)
+    as pos = (or (position #\Newline string :start start :end end) end)
+    when (< start pos) do (funcall fn start pos)
+    while (< pos end)))
+
+
+#|
+(defun top-search ()
+  (#/windowController 
+   (first-window-with-controller-type 'search-files-window-controller)))
+|#
+
Index: /branches/new-random/cocoa-ide/start.lisp
===================================================================
--- /branches/new-random/cocoa-ide/start.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/start.lisp	(revision 13309)
@@ -0,0 +1,277 @@
+(in-package "GUI")
+
+(defparameter *standalone-cocoa-ide* nil)
+
+#-cocotron
+(if (< #&NSAppKitVersionNumber 824)
+    (error "This application requires features introduced in OSX 10.4."))
+
+(def-cocoa-default  *ccl-directory* :string "" nil
+                    #+no #'(lambda (old new)
+                             (when (equal new "") (setq new nil))
+                             (unless (and new (equal old new))
+                               (init-interfaces-root)
+                               (ccl::replace-base-translation
+                                "ccl:"
+                                (or new (find-ccl-directory))))))
+
+;; If there are interfaces inside the bundle, use those rather than the ones
+;; in CCL:, since they're more likely to be valid.  CCL: could be some random
+;; old sources we're just using for meta-.
+(defun init-interfaces-root ()
+  (let* ((subpath (ccl::cdb-subdirectory-path))
+         (path (pathname-directory (ccl::ccl-directory))))
+    (when (and *standalone-cocoa-ide*
+               (equalp (last path 2) '("Contents" "MacOS")))
+      (setq path (butlast path))
+      (when (or (probe-file (make-pathname :directory (append path subpath)))
+                (probe-file (make-pathname :directory (append (setq path `(,@path "Resources")) subpath))))
+        (setq ccl::*interfaces-root* (make-pathname :directory path))))))
+
+(defun find-ccl-directory ()
+  (let* ((path (ccl::ccl-directory))
+         (dir (pathname-directory path)))
+    (if (equalp (last dir 2) '("Contents" "MacOS"))
+        (make-pathname :directory (butlast dir 3))
+        path)))
+
+
+(defmethod ccl::ui-object-do-operation ((o ns:ns-application)
+                                        operation
+                                        &rest args)
+  (declare (ignore operation args))
+  ;; Do nothing.  Would it be better to warn and/or log this ?
+  )
+
+(defmethod ccl::ui-object-do-operation ((o ns:ns-application)
+                                        (operation (eql :note-current-package))
+                                        &rest args)
+  (ui-object-note-package o (car args)))
+
+(defmethod ccl::ui-object-do-operation ((o ns:ns-application)
+                                        (operation (eql :eval-selection))
+                                        &rest args)
+  (ui-object-eval-selection o (car args)))
+
+(defmethod ccl::ui-object-do-operation ((o ns:ns-application)
+                                        (operation (eql :enter-backtrace-context))
+                                        &rest args)
+  (ui-object-enter-backtrace-context o (car args)))
+
+(defmethod ccl::ui-object-do-operation ((o ns:ns-application)
+                                        (operation (eql :exit-backtrace-context))
+                                        &rest args)
+  (ui-object-exit-backtrace-context o (car args)))
+
+(defmethod ccl::ui-object-do-operation ((o ns:ns-application) (operation (eql :break-options-string)) &rest args)
+  (unless (typep ccl::*current-process* 'appkit-process)
+    (destructuring-bind (continuablep) args
+      (if continuablep
+        "~&> Type cmd-/ to continue, cmd-. to abort, cmd-\\ for a list of available restarts."
+        "~&> Type cmd-. to abort, cmd-\\ for a list of available restarts.~%"))))
+
+;;; Support for saving a stand-alone IDE
+
+
+(defclass cocoa-application (application)
+  ())
+
+(defmethod ccl::application-error ((a cocoa-application) condition error-pointer)
+  (ccl::break-loop-handle-error condition error-pointer))
+
+
+(defmethod ccl::application-init-file ((a cocoa-application))
+  '("home:ccl-init" "home:\\.ccl-init"))
+
+;;; If we're launched via the Finder, the only argument we'll
+;;; get is of the form -psnXXXXXX.  That's meaningless to us;
+;;; it's easier to pretend that we didn't get any arguments.
+;;; (If it seems like some of this needs to be thought out a
+;;; bit better ... I'd tend to agree.)
+(defmethod ccl::parse-application-arguments ((a cocoa-application))
+  (values nil nil nil nil))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+    (require :swank-listener))
+
+(defmethod toplevel-function ((a cocoa-application) init-file)
+  (declare (ignore init-file))
+  #-cocotron
+  (when (< #&NSAppKitVersionNumber 824)
+    (#_NSLog #@"This application requires features introduced in OSX 10.4.")
+    (#_ _exit -1))
+  (setq *standalone-cocoa-ide* t)
+  (maybe-start-swank-listener)
+  (with-slots  (have-interactive-terminal-io) ccl::*current-process*
+    (when (and (eql (nth-value 4 (ccl::%stat "/dev/null"))
+                    (nth-value 4 (ccl::%fstat 0)))
+             ;; Should compare st_dev, too
+             )
+      (setq have-interactive-terminal-io nil)
+      
+      ;; It's probably reasonable to do this here: it's not really IDE-specific
+      (when (try-connecting-to-altconsole)
+        (setq have-interactive-terminal-io t)))
+    ;; TODO: to avoid confusion, should now reset *cocoa-application-path* to
+    ;; actual bundle path where started up.
+    (start-cocoa-application)))
+
+
+
+
+  (defun build-ide (bundle-path)
+    (setq bundle-path (ensure-directory-pathname bundle-path))
+
+    ;; The bundle is expected to exist, we'll just add the executable into it.
+    (assert (probe-file bundle-path))
+
+    ;; Wait until we're sure that the Cocoa event loop has started.
+    (wait-on-semaphore *cocoa-application-finished-launching*)
+
+    #-cocotron                          ;needs conditionalization
+    (require :easygui)
+
+    (ccl::maybe-map-objc-classes t)
+    (let* ((missing ()))
+      (ccl::do-interface-dirs (d)
+        (ccl::cdb-enumerate-keys
+         (ccl::db-objc-classes d)
+         (lambda (name)
+           (let* ((class (ccl::lookup-objc-class name nil)))
+             (unless (ccl::objc-class-id  class) (push name missing))))))
+      (when missing
+        (break "ObjC classes ~{~&~a~} are declared but not defined." missing)))
+
+    #-cocotron
+    (ccl::touch bundle-path)
+
+    (let ((image-file (make-pathname :name (ccl::standard-kernel-name) :type nil :version nil
+                                     :defaults (merge-pathnames (format nil";Contents;~a;" #+darwin-target "MacOS" #+cocotron "Windows")  bundle-path))))
+      (format *error-output* "~2%Saving application to ~a~2%" (truename bundle-path))
+      (force-output *error-output*)
+      (ensure-directories-exist image-file)
+      (save-application image-file
+                        :prepend-kernel t
+                        :application-class 'cocoa-application
+                        #+windows-target #+windows-target
+                        :application-type :gui)))
+
+;;; If we're running as a standalone .app, try to see if a bundle named
+;;; AltConsole.app exists in our Resources directory.  If so, execute
+;;; that bundle'es executable file, with its standard input/output/error
+;;; descriptors connected to one end of a socketpair, and connect
+;;; lisp's *TERMINAL-IO* and the kernel's dbgout to the other end
+;;; of the socket.
+
+(defun try-connecting-to-altconsole ()
+  (with-autorelease-pool
+      (let* ((main-bundle (#/mainBundle ns:ns-bundle))
+             (resource-path (#/resourcePath main-bundle)))
+        (block exit
+          (when (%null-ptr-p resource-path)
+            (return-from exit nil))
+          #-windows-target
+          (let* ((altconsole-bundle
+                  (make-instance ns:ns-bundle
+                                 :with-path
+                                 (#/stringByAppendingPathComponent:
+                                  resource-path
+                                  #@"AltConsole.app"))))
+            (when (%null-ptr-p altconsole-bundle)
+              (return-from exit nil))
+            (let* ((executable-path (#/executablePath altconsole-bundle)))
+              (when (%null-ptr-p executable-path)
+                (return-from exit nil))
+              (let* ((nbytes (1+ (#/lengthOfBytesUsingEncoding:
+                                  executable-path
+                                  #$NSUTF8StringEncoding))))
+                (%stack-block ((c-executable-path nbytes))
+                  (unless (#/getCString:maxLength:encoding:
+                           executable-path
+                           c-executable-path
+                           nbytes
+                           #$NSUTF8StringEncoding)
+                    (return-from exit nil))
+                  (rletz ((argv (:array :address 2))
+                          (envp (:array :address 1))
+                          (sockets (:array :int 2)))
+                    (setf (paref argv (:array :address) 0) c-executable-path)
+                    (unless (eql 0 (#_socketpair #$AF_UNIX #$SOCK_STREAM 0 sockets))
+                      (return-from exit nil))
+                    (let* ((parent-socket (paref sockets (:array :int) 0))
+                           (child-socket (paref sockets (:array :int) 1))
+                           (pid (#_fork)))
+                      (case pid
+                        (-1
+                         ;; Fork failed
+                         (#_close parent-socket)
+                         (#_close child-socket)
+                         (return-from exit nil))
+                        (0
+                         ;; This runs in the child.
+                         (#_close parent-socket)
+                         (#_dup2 child-socket 0)
+                         (#_dup2 child-socket 1)
+                         (#_dup2 child-socket 2)
+                         (#_execve c-executable-path
+                                   argv
+                                   envp)
+                         ;; If the #_exec fails, there isn't
+                         ;; much to do or say about it.
+                         (#__exit 1))
+                        (t
+                         ;; We're the parent.
+                         (#_close child-socket)
+                         (when (eq t (ccl::check-pid pid))
+                           (flet ((set-lisp-stream-fd (stream fd)
+                                    (setf (ccl::ioblock-device (ccl::stream-ioblock stream t))
+                                          fd)))
+                             (ff-call (ccl::%kernel-import target::kernel-import-open-debug-output)
+                                      :int parent-socket
+                                      :int)
+                             (#_dup2 parent-socket 0)
+                             (set-lisp-stream-fd ccl::*stdin* parent-socket)
+                             (set-lisp-stream-fd ccl::*stdout* parent-socket))
+                           ;; Ensure that output to the stream ccl::*stdout* -
+                           ;; which is connected to fd 1 - is flushed periodically
+                           ;; by the housekeeping task.  (ccl::*stdout* is
+                           ;; typically the output side of the two-way stream
+                           ;; which is the global/static value of *TERMINAL-IO*;
+                           ;; many standard streams are synonym streams to
+                           ;; *TERMINAL-IO*.
+                           (ccl::add-auto-flush-stream ccl::*stdout*)
+                           pid)))))))))
+          #+windows-target
+          (let* ((executable-path (#/stringByAppendingPathComponent:
+                                  resource-path
+                                  #@"WaltConsole.exe")))
+            (unless (#/isExecutableFileAtPath:
+                     (#/defaultManager ns:ns-file-manager)
+                     executable-path)
+              (return-from exit nil))
+            (multiple-value-bind (child-in parent-out) (ccl::pipe)
+              (multiple-value-bind (parent-in child-out) (ccl::pipe)
+                (cond ((ccl::create-windows-process child-in child-out child-out (lisp-string-from-nsstring executable-path) nil)
+                       (#_CloseHandle (ccl::%int-to-ptr child-in))
+                       (#_CloseHandle (ccl::%int-to-ptr child-out))
+                       (let* ((in-fd (#__open_osfhandle parent-in #$_O_RDONLY))
+                              (out-fd (#__open_osfhandle parent-out 0)))
+                         (#_SetStdHandle #$STD_INPUT_HANDLE (%int-to-ptr parent-in))
+                         (#__dup2 in-fd 0) ; Thank god the namespace isn't polluted.
+                         (ff-call (ccl::%kernel-import target::kernel-import-open-debug-output)
+                                  :int out-fd
+                                  :int)                         
+                         (flet ((set-lisp-stream-handle (stream handle)
+                                    (setf (ccl::ioblock-device (ccl::stream-ioblock stream t))
+                                          handle)))
+                           (set-lisp-stream-handle ccl::*stdin* parent-in)
+                           (set-lisp-stream-handle ccl::*stdout* parent-out)
+                           (ccl::add-auto-flush-stream ccl::*stdout*)
+                           t)))))))))))
+                      
+                    
+             
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(start-cocoa-application)
Index: /branches/new-random/cocoa-ide/swank-ccl-ide.el
===================================================================
--- /branches/new-random/cocoa-ide/swank-ccl-ide.el	(revision 13309)
+++ /branches/new-random/cocoa-ide/swank-ccl-ide.el	(revision 13309)
@@ -0,0 +1,53 @@
+;;;; ***********************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          swank-ccl-ide.el
+;;;; Project:       CCL IDE
+;;;; Purpose:       swank extensions for use with the CCL IDE
+;;;;
+;;;; ***********************************************************************
+
+;;; ABOUT
+;;; ------------------------------------------------------------------------
+
+;;; this file implements an extension to SLIME that talks to CCL's
+;;; Cocoa app 
+;;; it provides utilities that:
+;;; 1. tell CCL to find and load the swank-loader currently in use by
+;;;    the running Emacs
+;;; 2.  start a swank server on a specified port.
+;;; 3. tell SLIME to connect to swank on the specified port
+
+(defun swank-loader-path () (concat slime-path "swank-loader.lisp"))
+
+(defvar *ccl-swank-listener-host* "127.0.0.1")
+(defvar *ccl-swank-listener-port* 4884)
+(defvar *ccl-swank-listener-proc* nil)
+
+(defvar *ccl-swank-output* nil)
+
+(defun slime-ccl-swank-filter (process string)
+  (let* ((status (read string))
+         (active? (plist-get status :active)))
+    (setq *ccl-swank-output* status)
+    (if active?
+        (let ((port (plist-get status :port)))
+          (slime-connect *ccl-swank-listener-host* port))
+        (error "CCL failed to start the swank server. The reason it gave was: '%s'"
+               (plist-get status :message)))))
+
+(defvar $emacs-ccl-swank-request-marker "[emacs-ccl-swank-request]")
+
+(defun request-ccl-load-swank (&optional host listener-port connection-port loader-path)
+  (let* ((host (or host *ccl-swank-listener-host*))
+         (listener-port (or listener-port *ccl-swank-listener-port*))
+         (connection-port (or connection-port slime-port))
+         (loader-path (or loader-path (swank-loader-path)))
+         (ping (concat $emacs-ccl-swank-request-marker (format "%d" connection-port) ":" loader-path "\n"))
+         (ccl-proc (open-network-stream "SLIME CCL Swank" nil host listener-port)))
+    (setq *ccl-swank-listener-proc* ccl-proc)
+    (set-process-filter ccl-proc 'slime-ccl-swank-filter)
+    ;; send ping
+    (process-send-string ccl-proc ping)
+    ccl-proc))
+
Index: /branches/new-random/cocoa-ide/swank-listener.lisp
===================================================================
--- /branches/new-random/cocoa-ide/swank-listener.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/swank-listener.lisp	(revision 13309)
@@ -0,0 +1,251 @@
+;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: cl-user -*-
+;;;; ***********************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          swank.lisp
+;;;; Project:       CCL IDE
+;;;; Purpose:       CCL's swank loader
+;;;;
+;;;; ***********************************************************************
+
+;;; ABOUT
+;;; ------------------------------------------------------------------------
+;;; implements tools used to locate and load a swank server at app startup.
+
+(in-package :GUI)
+
+(defparameter *ccl-swank-active-p* nil)
+(defparameter *default-swank-listener-port* 4884)
+(defparameter *active-gui-swank-listener-port* nil)
+(defparameter *ccl-swank-listener-active-p* nil)
+(defvar *swank-listener-process* nil)
+
+(defun swank-listener-active? ()
+  (and *swank-listener-process*
+       (typep *swank-listener-process* 'process)
+       (not (member (process-whostate *swank-listener-process*)
+                    '("Reset" "Exhausted")
+                    :test 'string-equal))))
+
+;;; preference-swank-listener-port
+;;; returns the current value of the "Swank Port" user preference
+(defun preference-swank-listener-port ()
+  (with-autorelease-pool
+    (let* ((defaults (handler-case (#/values (#/sharedUserDefaultsController ns:ns-user-defaults-controller))
+                       (serious-condition (c) 
+                         (progn (log-debug "~%ERROR: Unable to get preferences from the Shared User Defaults Controller: ~A"
+                                           c)
+                                nil))))
+           (swank-port-pref (and defaults (#/valueForKey: defaults #@"swankListenerPort"))))
+      (cond
+        ;; the user default is not initialized
+        ((or (null swank-port-pref)
+             (%null-ptr-p swank-port-pref)) nil)
+        ;; examine the user default
+        ((or (typep swank-port-pref 'ns:ns-number)
+             (typep swank-port-pref 'ns:ns-string)) 
+         (handler-case (let* ((port (#/intValue swank-port-pref)))
+                         (or port *default-swank-listener-port*))
+           ;; parsing the port number failed
+           (serious-condition (c)
+             (declare (ignore c))
+             (setf *ccl-swank-listener-active-p* nil)
+             (#_NSLog #@"\nError starting swank listener; the user preference is not a valid port number: %@\n"
+                    :id swank-port-pref)
+             nil)))
+        ;; the user default value is incomprehensible
+        (t (progn
+             (#_NSLog #@"\nERROR: Unrecognized value type in user preference 'swankListenerPort': %@"
+                    :id swank-port-pref)
+             nil))))))
+
+;;; preference-start-swank-listener?  
+;;; returns the current value of the "Start swank listener?" user
+;;; preference
+(defun preference-start-swank-listener? ()
+  (with-autorelease-pool
+   (let* ((defaults (handler-case (#/values (#/sharedUserDefaultsController ns:ns-user-defaults-controller))
+                     (serious-condition (c) 
+                       (progn (log-debug "~%ERROR: Unable to get preferences from the Shared User Defaults Controller: ~a" c)
+                              nil))))
+         (start-swank-pref (if (and defaults (not (%null-ptr-p defaults))) 
+                               (#/valueForKey: defaults #@"startSwankListener")         
+                               nil)))
+    (cond
+      ;; the user default is not initialized
+      ((or (null start-swank-pref)
+           (%null-ptr-p start-swank-pref)) nil)
+      ;; examine the user default
+      ;; intValue works on NSNumber or NSString
+      ;; BUG? if a string value is not a valid representation of an integer,
+      ;;      intValue returns 0, which means any non-numeric string will have the
+      ;;      same effect as "0"
+      ((or (typep start-swank-pref 'ns:ns-number)
+           (typep start-swank-pref 'ns:ns-string))
+       (case (#/intValue start-swank-pref)
+         ;; don't start swank listener
+         (0 nil)
+         ;; start swank listener
+         (1 t)
+         ;; the user default value is incomprehensible
+         (otherwise (progn
+                      (log-debug "~%ERROR: Unrecognized value in user preference 'startSwankServer': ~S"
+                                 start-swank-pref)
+                      nil))))
+      ;; the user default value is incomprehensible
+      (t (progn
+           (log-debug "~%ERROR: Unrecognized value type in user preference 'startSwankServer': ~S"
+                      start-swank-pref)
+           nil))))))
+
+;;; start-swank-listener
+;;; -----------------------------------------------------------------
+;;; starts up CCL's swank-listener server on the specified port
+
+;;; aux utils
+
+(defvar $emacs-ccl-swank-request-marker "[emacs-ccl-swank-request]")
+
+(defvar $last-swank-message-sent nil)
+
+(defun swank-server-running? ()
+  (and (find-package :swank)
+       (let ((active-listeners (symbol-value (intern "*LISTENER-SOCKETS*" :swank))))
+         (and (not (null active-listeners))
+              (first active-listeners)))))
+
+(defstruct (swank-status (:conc-name swank-))
+  (active? nil :read-only t)
+  (message nil :read-only t)
+  (requested-loader nil :read-only t)
+  (requested-port nil :read-only t))
+
+(defun read-swank-ping (tcp-stream) 
+  (read-line tcp-stream nil nil nil))
+
+(defun parse-swank-ping (p) 
+  (let ((sentinel-end (length $emacs-ccl-swank-request-marker)))
+    (if (typep p 'string)
+        (if (string= p $emacs-ccl-swank-request-marker :start1 0 :end1 sentinel-end)
+            (let* ((request (subseq p sentinel-end))
+                   (split-pos (position #\: request))
+                   (port-str (if split-pos
+                                 (subseq request 0 split-pos)
+                                 nil))
+                   (port (when port-str (parse-integer port-str :junk-allowed nil)))
+                   (path-str (if split-pos
+                                 (subseq request (1+ split-pos))
+                                 request)))
+              (values (string-trim '(#\space #\tab #\return #\newline) path-str) port))
+            nil)
+        nil)))
+
+
+(defun load-and-start-swank (path requested-port) 
+  (handler-case (let* ((active-swank-port (swank-server-running?))
+                       (msg (format nil "A swank server is already running on port ~A" active-swank-port)))
+                  (if active-swank-port
+                      (progn
+                        (log-debug msg)
+                        (make-swank-status :active? t :message msg :requested-loader path :requested-port requested-port))
+                      (progn
+                        (load path)
+                        (let ((swank-loader-package (find-package :swank-loader)))
+                          (if swank-loader-package
+                              ;; swank loaded. start the server
+                              (progn
+                                (funcall (intern "LOAD-SWANK" swank-loader-package))
+                                (funcall (intern "CREATE-SERVER" (find-package :swank)) :port requested-port :dont-close t)
+                                (make-swank-status :active? t :requested-loader path :requested-port requested-port))
+                              ;; swank failed to load. return failure status
+                              (make-swank-status :active? nil :message "swank load failed" :requested-loader path :requested-port requested-port))))))
+    (ccl::socket-creation-error (e) (log-debug "Unable to start a swank server on port: ~A; ~A"
+                                               requested-port e)
+                                (make-swank-status :active? nil :message "socket-creation error"
+                                                   :requested-loader path :requested-port requested-port))
+    (serious-condition (e) (log-debug "There was a problem creating the swank server on port ~A: ~A"
+                                      requested-port e)
+                       (make-swank-status :active? nil :message "error loading or starting swank"
+                                          :requested-loader path :requested-port requested-port))))
+
+(defun swank-ready? (status)
+  (swank-active? status))
+
+(defun send-swank-response (tcp-stream status)
+  (let ((response 
+         (let ((*print-case* :downcase))
+           (format nil "(:active ~S :loader ~S :message ~S :port ~D)"
+                   (swank-active? status)
+                   (swank-requested-loader status)
+                   (swank-message status)
+                   (swank-requested-port status)))))
+    (format tcp-stream response)
+    (finish-output tcp-stream)))
+
+(defun handle-swank-client (c)
+  (let* ((msg (read-swank-ping c)))
+    (multiple-value-bind (swank-path requested-port)
+        (parse-swank-ping msg)
+      (load-and-start-swank swank-path requested-port))))
+
+(defun stop-swank-listener ()
+  (process-kill *swank-listener-process*)
+  (setq *swank-listener-process* nil))
+
+;;; the real deal
+;;; if it succeeds, it returns a PROCESS object
+;;; if it fails, it returns a CONDITION object
+(defun start-swank-listener (&optional (port *default-swank-listener-port*))
+  (handler-case 
+      (if (swank-listener-active?)
+          (log-debug "in start-swank-listener: the swank listener process is already running")
+          (setq *swank-listener-process*
+                (process-run-function "Swank Listener"
+                                      #'(lambda ()
+                                          (with-open-socket (sock :type :stream :connect :passive 
+                                                                  :local-port port :reuse-address t :auto-close t)
+                                            (loop
+                                               (let* ((client-sock (accept-connection sock))
+                                                      (status (handle-swank-client client-sock)))
+                                                 (send-swank-response client-sock status))))))))
+    (ccl::socket-creation-error (c) (nslog-condition c "Unable to create a socket for the swank-listener: ") c)
+    (ccl::socket-error (c) (nslog-condition c "Swank-listener failed trying to accept a client connection: ") c)
+    (serious-condition (c) (nslog-condition c "Error starting in the swank-listener:") c)))
+
+;;; maybe-start-swank-listener
+;;; -----------------------------------------------------------------
+;;; checks whether to start the ccl swank listener, and starts it if
+;;; warranted.
+(defun maybe-start-swank-listener (&key (override-user-preference nil))
+  (unless *ccl-swank-listener-active-p*
+    ;; try to determine the user preferences concerning the
+    ;; swank-listener port number and whether the swank listener
+    ;; should be started. If the user says start it, and we can
+    ;; determine a valid port for it, start it up
+    (let* ((start-swank-listener? (or (preference-start-swank-listener?) override-user-preference))
+           (swank-listener-port (or (preference-swank-listener-port) *default-swank-listener-port*)))
+      (if (and start-swank-listener? swank-listener-port)
+          ;; try to start the swank listener
+          (handler-case (let ((swank-listener (start-swank-listener swank-listener-port)))
+                          (if (typep swank-listener 'process)
+                              (progn
+                                (setf *active-gui-swank-listener-port* swank-listener-port)
+                                (setf *ccl-swank-listener-active-p* t)
+                                swank-listener-port)
+                              (progn
+                                (setf *active-gui-swank-listener-port* nil)
+                                (setf *ccl-swank-listener-active-p* nil)
+                                nil)))
+            ;; swank listener creation failed
+            (serious-condition (c)
+              (setf *active-gui-swank-listener-port* nil)
+              (setf *ccl-swank-listener-active-p* nil)
+              (log-debug "~%Error starting swank listener: ~A~%" c)
+              nil))
+          ;; don't try to start the swank listener
+          (progn
+            (setf *active-gui-swank-listener-port* nil)
+            (setf *ccl-swank-listener-active-p* nil)
+            nil)))))
+
+(provide :swank-listener)
Index: /branches/new-random/cocoa-ide/xapropos.lisp
===================================================================
--- /branches/new-random/cocoa-ide/xapropos.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/xapropos.lisp	(revision 13309)
@@ -0,0 +1,219 @@
+(in-package "GUI")
+
+(defclass xapropos-window-controller (ns:ns-window-controller)
+  ((row-objects :foreign-type :id :reader row-objects)
+   (search-category :initform :all :accessor search-category)
+   (matched-symbols :initform (make-array 100 :fill-pointer 0 :adjustable t)
+                    :accessor matched-symbols)
+   (external-only-p :initform nil :accessor external-only-p)
+   ;; outlets
+   (action-menu :foreign-type :id :accessor action-menu)
+   (action-popup-button :foreign-type :id :accessor action-popup-button)
+   (search-field :foreign-type :id :accessor search-field)
+   (search-field-toolbar-item :foreign-type :id :accessor search-field-toolbar-item)
+   (all-symbols-button :foreign-type :id :accessor all-symbols-button)
+   (external-symbols-button :foreign-type :id :accessor external-symbols-button)
+   (table-view :foreign-type :id :accessor table-view)
+   (contextual-menu :foreign-type :id :accessor contextual-menu))
+  (:metaclass ns:+ns-object))
+
+(defclass scope-bar-view (ns:ns-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+(defconstant $scope-bar-border-width 1)
+
+;;; This should use a gradient, but we don't have NSGradient on Tiger.
+
+(objc:defmethod (#/drawRect: :void) ((self scope-bar-view) (rect #>NSRect))
+  (let* (;;(start-color (#/colorWithCalibratedWhite:alpha: ns:ns-color 0.75 1.0))
+         (end-color (#/colorWithCalibratedWhite:alpha: ns:ns-color 0.90 1.0))
+         (border-color (#/colorWithCalibratedWhite:alpha: ns:ns-color 0.69 1.0))
+         (bounds (#/bounds self)))
+    (#/set end-color)
+    (#_NSRectFill bounds)
+    (ns:with-ns-rect (r 0 0 (ns:ns-rect-width bounds) $scope-bar-border-width)
+      (#/set border-color)
+      (#_NSRectFill r))))
+
+(defconstant $all-symbols-item-tag 0)
+
+(defvar *apropos-categories*
+  '((0 . :all)
+    (1 . :function)
+    (2 . :variable)
+    (3 . :class)
+    (4 . :macro))
+  "Associates search menu item tags with keywords.")
+
+;;; action menu item tags
+(defconstant $inspect-item-tag 0)
+(defconstant $source-item-tag 1)
+
+(objc:defmethod #/init ((wc xapropos-window-controller))
+  (let ((self (#/initWithWindowNibName: wc #@"xapropos")))
+    (unless (%null-ptr-p self)
+      (setf (slot-value self 'row-objects) (make-instance 'ns:ns-mutable-array)))
+    self))
+
+(defun make-action-popup (menu)
+  (ns:with-ns-rect (r 0 0 44 23)
+    (let* ((button (make-instance 'ns:ns-pop-up-button :with-frame r :pulls-down t))
+           (item (#/itemAtIndex: menu 0))
+           (image-name (if (post-tiger-p) #@"NSActionTemplate" #@"gear")))
+      (#/setBezelStyle: button #$NSTexturedRoundedBezelStyle)
+      ;; This looks bad on Tiger: the arrow is in the bottom corner of the button.
+      #-cocotron                        ; no setArrowPosition
+      (#/setArrowPosition: (#/cell button) #$NSPopUpArrowAtBottom)
+      (#/setImage: item (#/imageNamed: ns:ns-image image-name))
+      (#/setMenu: button menu)
+      (#/synchronizeTitleAndSelectedItem button)
+      button)))
+
+(objc:defmethod (#/windowDidLoad :void) ((wc xapropos-window-controller))
+  (#/setDoubleAction: (table-view wc) (@selector #/inspect:))
+  (setf (action-popup-button wc) (make-action-popup (action-menu wc)))
+  (let* ((toolbar (make-instance 'ns:ns-toolbar :with-identifier #@"apropos toolbar")))
+    (#/setDisplayMode: toolbar #$NSToolbarDisplayModeIconOnly)
+    (#/setDelegate: toolbar wc)
+    (#/setToolbar: (#/window wc) toolbar)
+    (#/release toolbar)
+    (#/search: wc (search-field wc))
+    (#/makeFirstResponder: (#/window wc) (search-field wc))))
+
+(objc:defmethod #/toolbarAllowedItemIdentifiers: ((wc xapropos-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"action-popup-button"
+                       #&NSToolbarFlexibleSpaceItemIdentifier #@"search-field" +null-ptr+))
+
+(objc:defmethod #/toolbarDefaultItemIdentifiers: ((wc xapropos-window-controller) toolbar)
+  (declare (ignore toolbar))
+  (#/arrayWithObjects: ns:ns-array #@"action-popup-button"
+                       #&NSToolbarFlexibleSpaceItemIdentifier #@"search-field" +null-ptr+))
+
+(objc:defmethod #/toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
+                ((wc xapropos-window-controller) toolbar identifier (flag #>BOOL))
+  (declare (ignore toolbar))
+  (let* ((toolbar-item (make-instance 'ns:ns-toolbar-item :with-item-identifier identifier)))
+    (#/autorelease toolbar-item)
+    (with-slots (action-popup-button search-field) wc
+      (cond ((#/isEqualToString: identifier #@"action-popup-button")
+             (#/setMinSize: toolbar-item (pref (#/frame action-popup-button) #>NSRect.size))
+             (#/setMaxSize: toolbar-item (pref (#/frame action-popup-button) #>NSRect.size))
+             (#/setView: toolbar-item action-popup-button))
+            ((#/isEqualToString: identifier #@"search-field")
+             (#/setMinSize: toolbar-item (pref (#/frame search-field) #>NSRect.size))
+             (#/setMaxSize: toolbar-item (pref (#/frame search-field) #>NSRect.size))
+             (#/setView: toolbar-item search-field))
+          (t
+           (setq toolbar-item +null-ptr+))))
+    toolbar-item))
+
+(objc:defmethod (#/dealloc :void) ((wc xapropos-window-controller))
+  (#/release (slot-value wc 'row-objects))
+  (call-next-method))
+
+(objc:defmethod (#/search: :void) ((wc xapropos-window-controller) sender)
+  (let* ((substring (#/stringValue sender)))
+    ;;(#_NSLog #@"search for %@" :id substring)
+    (apropos-search wc (lisp-string-from-nsstring substring))))
+
+(defun apropos-search (wc substring)
+  (with-accessors ((v matched-symbols)
+                   (category search-category)
+                   (array row-objects)) wc
+    (setf (fill-pointer v) 0)
+    (flet ((maybe-include-symbol (sym)
+             (when (case category
+                     (:function (fboundp sym))
+                     (:variable (boundp sym))
+                     (:macro (macro-function sym))
+                     (:class (find-class sym nil))
+                     (t t))
+               (when (ccl::%apropos-substring-p substring (symbol-name sym))
+                 (vector-push-extend sym v)))))
+      (if (external-only-p wc)
+        (dolist (p (list-all-packages))
+          (do-external-symbols (sym p)
+            (maybe-include-symbol sym)))
+        (do-all-symbols (sym)
+          (maybe-include-symbol sym))))
+    (setf v (sort v #'string-lessp))
+    (#/removeAllObjects array)
+    (let ((n (#/null ns:ns-null)))
+      (dotimes (i (length v))
+        (#/addObject: array n))))
+  (#/reloadData (table-view wc)))
+
+(objc:defmethod (#/setSearchCategory: :void) ((wc xapropos-window-controller) sender)
+  (let* ((tag (#/tag sender))
+         (label (if (= tag $all-symbols-item-tag)
+                  #@"Search"
+                  (#/stringWithFormat: ns:ns-string #@"Search (%@)" (#/title sender))))
+         (pair (assoc tag *apropos-categories*)))
+    (when pair
+      (let* ((items (#/itemArray (#/menu sender))))
+        (dotimes (i (#/count items))
+          (#/setState: (#/objectAtIndex: items i) #$NSOffState)))
+      (#/setState: sender #$NSOnState)
+      (#/setLabel: (search-field-toolbar-item wc) label)
+      (setf (search-category wc) (cdr pair))
+      (#/search: wc (search-field wc)))))
+
+(objc:defmethod (#/toggleExternalOnly: :void) ((wc xapropos-window-controller) sender)
+  (cond ((eql sender (all-symbols-button wc))
+         (#/setState: (external-symbols-button wc) #$NSOffState)
+         (setf (external-only-p wc) nil))
+        ((eql sender (external-symbols-button wc))
+         (#/setState: (all-symbols-button wc) #$NSOffState)
+         (setf (external-only-p wc) t)))
+  (#/search: wc (search-field wc)))
+  
+(objc:defmethod (#/inspect: :void) ((wc xapropos-window-controller) sender)
+  (declare (ignore sender))
+  (let* ((row (#/selectedRow (table-view wc)))
+         (clicked-row (#/clickedRow (table-view wc))))
+    (when (/= clicked-row -1)
+      (setq row clicked-row))
+    (inspect (aref (matched-symbols wc) row))))
+
+(objc:defmethod (#/source: :void) ((wc xapropos-window-controller) sender)
+  (declare (ignore sender))
+  (let* ((row (#/selectedRow (table-view wc)))
+         (clicked-row (#/clickedRow (table-view wc))))
+    (when (/= clicked-row -1)
+      (setq row clicked-row))
+    (hemlock::edit-definition (aref (matched-symbols wc) row))))
+
+(objc:defmethod (#/validateMenuItem: #>BOOL) ((wc xapropos-window-controller) menu-item)
+  (cond ((or (eql (action-menu wc) (#/menu menu-item))
+             (eql (contextual-menu wc) (#/menu menu-item)))
+         (let ((row (#/selectedRow (table-view wc)))
+               (clicked-row (#/clickedRow (table-view wc)))
+               (tag (#/tag menu-item)))
+           (when (/= clicked-row -1)
+             (setq row clicked-row))
+           (when (/= row -1)
+             (cond ((= tag $inspect-item-tag) t)
+                   ((= tag $source-item-tag)
+                    (let ((sym (aref (matched-symbols wc) row)))
+                      (edit-definition-p sym)))
+                   (t nil)))))
+        (t t)))
+
+(objc:defmethod (#/numberOfRowsInTableView: #>NSInteger) ((wc xapropos-window-controller)
+                                                          table-view)
+  (declare (ignore table-view))
+  (length (matched-symbols wc)))
+
+(objc:defmethod #/tableView:objectValueForTableColumn:row: ((wc xapropos-window-controller)
+                                                            table-view table-column
+                                                            (row #>NSInteger))
+  (declare (ignore table-view table-column))
+  (with-accessors ((array row-objects)
+                   (syms matched-symbols)) wc
+    (when (eql (#/objectAtIndex: array row) (#/null ns:ns-null))
+      (let ((name (%make-nsstring (prin1-to-string (aref syms row)))))
+        (#/replaceObjectAtIndex:withObject: array row name)
+        (#/release name)))
+    (#/objectAtIndex: array row)))
Index: /branches/new-random/cocoa-ide/xinspector.lisp
===================================================================
--- /branches/new-random/cocoa-ide/xinspector.lisp	(revision 13309)
+++ /branches/new-random/cocoa-ide/xinspector.lisp	(revision 13309)
@@ -0,0 +1,118 @@
+(in-package "INSPECTOR")
+
+(defloadvar *inspector-cascade-point* (ns:make-ns-point 0 0))
+
+(defclass xinspector-window-controller (ns:ns-window-controller)
+  ((inspector :initarg :inspector :reader inspector)
+   ;; outlets
+   (action-menu :foreign-type :id :accessor action-menu)
+   (refresh-button :foreign-type :id :accessor refresh-button)
+   (back-forward-control :foreign-type :id :accessor back-forward-control)
+   (table-view :foreign-type :id :accessor table-view)
+   (contextual-menu :foreign-type :id :accessor contextual-menu)
+  ;; data source variables
+   (row-objects :foreign-type :id :reader row-objects))
+  (:metaclass ns:+ns-object))
+
+(defmethod (setf inspector) (new-inspector (wc xinspector-window-controller))
+  (update-line-count new-inspector)
+  (#/removeAllObjects (row-objects wc))
+  (let ((n (#/null ns:ns-null)))
+    (dotimes (i (inspector-line-count new-inspector))
+      (#/addObject: (row-objects wc) n)))
+  (setf (slot-value wc 'inspector) new-inspector))
+
+(objc:defmethod #/init ((wc xinspector-window-controller))
+  ;; Lisp slots are not set up yet when we are called.
+  (let ((self (#/initWithWindowNibName: wc #@"xinspector")))
+    (unless (%null-ptr-p self)
+      (with-slots (row-objects) wc
+        (setf row-objects (make-instance 'ns:ns-mutable-array))))
+    ;; We implement custom cascading.
+    (#/setShouldCascadeWindows: wc nil)
+    self))
+
+(defmethod initialize-instance :after ((wc xinspector-window-controller) &key inspector 
+                                       &allow-other-keys)
+  (setf (inspector wc) inspector))
+
+(objc:defmethod (#/dealloc :void) ((wc xinspector-window-controller))
+  (#/release (slot-value wc 'row-objects))
+  (call-next-method))
+
+(objc:defmethod (#/windowDidLoad :void) ((wc xinspector-window-controller))
+  (#/setDoubleAction: (table-view wc) (ccl::@selector #/inspect:))
+  ;; Cascade window from the top left point of the topmost inspector window.
+  (flet ((good-window-p (w)
+           (and (not (eql w (#/window wc)))
+                (eql (#/class (#/windowController w))
+                     (find-class 'xinspector-window-controller)))))
+    (let* ((inspectors (remove-if-not #'good-window-p (gui::windows)))
+           (top-inspector (car inspectors)))
+      (if top-inspector
+        (ns:with-ns-point (zp 0 0)
+          (setq *inspector-cascade-point*
+                (#/cascadeTopLeftFromPoint: top-inspector zp))))))
+  (#/cascadeTopLeftFromPoint: (#/window wc) *inspector-cascade-point*))
+
+
+(objc:defmethod (#/windowWillClose: :void) ((wc xinspector-window-controller) notification)
+  (declare (ignore notification))
+  (#/autorelease wc))
+
+(objc:defmethod (#/backOrForward: :void) ((wc xinspector-window-controller) sender)
+  (if (= (#/selectedSegment sender) 0)
+    (format *trace-output* "~&go back")
+    (format *trace-output* "~&go forward")))
+
+(objc:defmethod (#/inspect: :void) ((wc xinspector-window-controller) sender)
+  (declare (ignore sender))
+  (let* ((row (#/selectedRow (table-view wc)))
+         (clicked-row (#/clickedRow (table-view wc))))
+    (when (/= clicked-row -1)
+      (setq row clicked-row))
+    (inspector::cocoa-inspect (inspector::line-n (slot-value wc 'inspector) row))))
+
+;;; NSTableView data source methods
+
+(objc:defmethod (#/numberOfRowsInTableView: #>NSInteger) ((self xinspector-window-controller)
+                                                          table-view)
+  (declare (ignore table-view))
+  (#/count (row-objects self)))
+
+(objc:defmethod #/tableView:objectValueForTableColumn:row: ((self xinspector-window-controller)
+                                                            table-view table-column
+                                                            (row #>NSInteger))
+  (declare (ignore table-view table-column))
+  (with-slots (inspector row-objects) self
+    (when (eql (#/objectAtIndex: row-objects row) (#/null ns:ns-null))
+      (let* ((name (ccl::%make-nsstring (with-output-to-string (s)
+                                          (prin1-line-n inspector s row)))))
+        (#/replaceObjectAtIndex:withObject: row-objects row name)
+        (#/release name)))
+    (#/objectAtIndex: row-objects row)))
+
+(objc:defmethod (#/tableView:isGroupRow: #>BOOL) ((wc xinspector-window-controller)
+                                                  table-view
+                                                  (row #>NSInteger))
+  (declare (ignore table-view))
+  (with-accessors ((seq sequence)) wc
+    (let ((type (nth-value 2 (inspector::line-n (slot-value wc 'inspector) row))))
+      (if (consp type) (setq type (car type)))
+      (eq type :comment))))
+
+(objc:defmethod (#/tableView:shouldSelectRow: #>BOOL) ((wc xinspector-window-controller)
+                                                       table-view
+                                                       (row #>NSInteger))
+  (declare (ignore table-view))
+  (with-accessors ((seq sequence)) wc
+    (let ((type (nth-value 2 (inspector::line-n (slot-value wc 'inspector) row))))
+      (if (consp type) (setq type (car type)))
+      (neq type :comment))))
+
+(defun cocoa-inspect (thing)
+  (gui::execute-in-gui #'(lambda ()
+                           (let ((wc (make-instance 'xinspector-window-controller
+                                       :inspector (make-inspector thing))))
+                             (#/showWindow: wc nil)))))
+
Index: /branches/new-random/compiler/.cvsignore
===================================================================
--- /branches/new-random/compiler/.cvsignore	(revision 13309)
+++ /branches/new-random/compiler/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/compiler/PPC/.cvsignore
===================================================================
--- /branches/new-random/compiler/PPC/.cvsignore	(revision 13309)
+++ /branches/new-random/compiler/PPC/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/compiler/PPC/PPC32/.cvsignore
===================================================================
--- /branches/new-random/compiler/PPC/PPC32/.cvsignore	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC32/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/compiler/PPC/PPC32/ppc32-arch.lisp
===================================================================
--- /branches/new-random/compiler/PPC/PPC32/ppc32-arch.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC32/ppc32-arch.lisp	(revision 13309)
@@ -0,0 +1,944 @@
+;;;-*- Mode: Lisp; Package: (PPC32 :use CL) -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;; This file matches "ccl:pmcl;constants.h" & "ccl:pmcl;constants.s"
+
+(defpackage "PPC32"
+  (:use "CL")
+  #+ppc32-target
+  (:nicknames "TARGET"))
+
+(in-package "PPC32")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "PPC-ARCH")
+
+  
+(defmacro define-storage-layout (name origin &rest cells)
+  `(progn
+     (ccl::defenum (:start ,origin :step 4)
+       ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell)) cells))
+     (defconstant ,(ccl::form-symbol name ".SIZE") ,(* (length cells) 4))))
+ 
+(defmacro define-lisp-object (name tagname &rest cells)
+  `(define-storage-layout ,name ,(- (symbol-value tagname)) ,@cells))
+
+(defmacro define-subtag (name tag subtag)
+  `(defconstant ,(ccl::form-symbol "SUBTAG-" name) (logior ,tag (ash ,subtag ntagbits))))
+
+
+(defmacro define-imm-subtag (name subtag)
+  `(define-subtag ,name fulltag-immheader ,subtag))
+
+(defmacro define-node-subtag (name subtag)
+  `(define-subtag ,name fulltag-nodeheader ,subtag))
+
+(defmacro define-fixedsized-object (name &rest non-header-cells)
+  `(progn
+     (define-lisp-object ,name fulltag-misc header ,@non-header-cells)
+     (ccl::defenum ()
+       ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell "-CELL")) non-header-cells))
+     (defconstant ,(ccl::form-symbol name ".ELEMENT-COUNT") ,(length non-header-cells))))
+
+  
+)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defconstant rcontext 13)  
+(defconstant nbits-in-word 32)
+(defconstant least-significant-bit 31)
+(defconstant nbits-in-byte 8)
+(defconstant ntagbits 3)                ; But non-header objects only use 2
+(defconstant nlisptagbits 2)
+(defconstant nfixnumtagbits 2)          ; See ?
+(defconstant num-subtag-bits 8)         ; tag part of header is 8 bits wide
+(defconstant fixnumshift nfixnumtagbits)
+(defconstant fixnum-shift fixnumshift)          ; A pet name for it.
+(defconstant fulltagmask (1- (ash 1 ntagbits)))         ; Only needed by GC/very low-level code
+(defconstant full-tag-mask fulltagmask)
+(defconstant tagmask (1- (ash 1 nlisptagbits)))
+(defconstant tag-mask tagmask)
+(defconstant fixnummask (1- (ash 1 nfixnumtagbits)))
+(defconstant fixnum-mask fixnummask)
+(defconstant subtag-mask (1- (ash 1 num-subtag-bits)))
+(defconstant ncharcodebits 24)          ; only the low 8 bits are used, currently
+(defconstant charcode-shift (- nbits-in-word ncharcodebits))
+(defconstant word-shift 2)
+(defconstant word-size-in-bytes 4)
+(defconstant node-size 4)
+(defconstant dnode-size 8)
+(defconstant dnode-align-bits 3)
+(defconstant dnode-shift dnode-align-bits)
+(defconstant bitmap-shift 5)
+
+(defconstant target-most-negative-fixnum (ash -1 (1- (- nbits-in-word nfixnumtagbits))))
+(defconstant target-most-positive-fixnum (1- (ash 1 (1- (- nbits-in-word nfixnumtagbits)))))
+
+;; PPC-32 stuff and tags.
+
+;; Tags.
+;; There are two-bit tags and three-bit tags.
+;; A FULLTAG is the value of the low three bits of a tagged object.
+;; A TAG is the value of the low two bits of a tagged object.
+;; A TYPECODE is either a TAG or the value of a "tag-misc" object's header-byte.
+
+;; There are 4 primary TAG values.  Any object which lisp can "see" can be classified 
+;; by its TAG.  (Some headers have FULLTAGS that are congruent modulo 4 with the
+;; TAGS of other objects, but lisp can't "see" headers.)
+(ccl::defenum ()
+  tag-fixnum                            ; All fixnums, whether odd or even
+  tag-list                              ; Conses and NIL
+  tag-misc                              ; Heap-consed objects other than lists: vectors, symbols, functions, floats ...
+  tag-imm                               ; Immediate-objects: characters, UNBOUND, other markers.
+)
+
+;;; And there are 8 FULLTAG values.  Note that NIL has its own FULLTAG (congruent mod 4 to tag-list),
+;;; that FULLTAG-MISC is > 4 (so that code-vector entry-points can be branched to, since the low
+;;; two bits of the PC are ignored) and that both FULLTAG-MISC and FULLTAG-IMM have header fulltags
+;;; that share the same TAG.
+;;; Things that walk memory (and the stack) have to be careful to look at the FULLTAG of each
+;;; object that they see.
+(ccl::defenum ()
+  fulltag-even-fixnum                   ; I suppose EVENP/ODDP might care; nothing else does.
+  fulltag-cons                          ; a real (non-null) cons.  Shares TAG with fulltag-nil.
+  fulltag-nodeheader                    ; Header of heap-allocated object that contains lisp-object pointers
+  fulltag-imm                           ; a "real" immediate object.  Shares TAG with fulltag-immheader.
+  fulltag-odd-fixnum                    ; 
+  fulltag-nil                           ; NIL and nothing but.  (Note that there's still a hidden NILSYM.)
+  fulltag-misc                          ; Pointer "real" tag-misc object.  Shares TAG with fulltag-nodeheader.
+  fulltag-immheader                     ; Header of heap-allocated object that contains unboxed data.
+)
+
+(defconstant misc-header-offset (- fulltag-misc))
+(defconstant misc-subtag-offset (+ misc-header-offset 3))
+(defconstant misc-data-offset (+ misc-header-offset 4))
+(defconstant misc-dfloat-offset (+ misc-header-offset 8))
+
+
+
+
+
+
+(defconstant canonical-nil-value #x00003015)
+;;; T is almost adjacent to NIL: since NIL is a misaligned CONS, it spans
+;;; two doublewords.  The arithmetic difference between T and NIL is
+;;; such that the least-significant bit and exactly one other bit is
+;;; set in the result.
+
+(defconstant t-offset (+ 8 (- 8 fulltag-nil) fulltag-misc))
+(assert (and (logbitp 0 t-offset) (= (logcount t-offset) 2)))
+
+;;; The order in which various header values are defined is significant in several ways:
+;;; 1) Numeric subtags precede non-numeric ones; there are further orderings among numeric subtags.
+;;; 2) All subtags which denote CL arrays are preceded by those that don't,
+;;;    with a further ordering which requires that (< header-arrayH header-vectorH ,@all-other-CL-vector-types)
+;;; 3) The element-size of ivectors is determined by the ordering of ivector subtags.
+;;; 4) All subtags are >= fulltag-immheader .
+
+
+;;; Numeric subtags.
+(define-imm-subtag bignum 0)
+(defconstant min-numeric-subtag subtag-bignum)
+(define-node-subtag ratio 1)
+(defconstant max-rational-subtag subtag-ratio)
+
+(define-imm-subtag single-float 1)          ; "SINGLE" float, aka short-float in the new order.
+(define-imm-subtag double-float 2)
+(defconstant min-float-subtag subtag-single-float)
+(defconstant max-float-subtag subtag-double-float)
+(defconstant max-real-subtag subtag-double-float)
+
+(define-node-subtag complex 3)
+(defconstant max-numeric-subtag subtag-complex)
+
+;;; CL array types.  There are more immediate types than node types; all CL array subtags must be > than
+;;; all non-CL-array subtags.  So we start by defining the immediate subtags in decreasing order, starting
+;;; with that subtag whose element size isn't an integral number of bits and ending with those whose
+;;; element size - like all non-CL-array fulltag-immheader types - is 32 bits.
+(define-imm-subtag bit-vector 31)
+(define-imm-subtag double-float-vector 30)
+(define-imm-subtag s16-vector 29)
+(define-imm-subtag u16-vector 28)
+(defconstant min-16-bit-ivector-subtag subtag-u16-vector)
+(defconstant max-16-bit-ivector-subtag subtag-s16-vector)
+
+
+;;(define-imm-subtag simple-base-string 27)
+(define-imm-subtag s8-vector 26)
+(define-imm-subtag u8-vector 25)
+(defconstant min-8-bit-ivector-subtag subtag-u8-vector)
+(defconstant max-8-bit-ivector-subtag (logior fulltag-immheader (ash 27 ntagbits)))
+
+(define-imm-subtag simple-base-string 24)
+(define-imm-subtag fixnum-vector 23)
+(define-imm-subtag s32-vector 22)
+(define-imm-subtag u32-vector 21)
+(define-imm-subtag single-float-vector 20)
+(defconstant max-32-bit-ivector-subtag (logior fulltag-immheader (ash 24 ntagbits)))
+(defconstant min-cl-ivector-subtag subtag-single-float-vector)
+
+(define-node-subtag vectorH 20)
+(define-node-subtag arrayH 19)
+(assert (< subtag-arrayH subtag-vectorH min-cl-ivector-subtag))
+(define-node-subtag simple-vector 21)   ; Only one such subtag
+(assert (< subtag-arrayH subtag-vectorH subtag-simple-vector))
+(defconstant min-vector-subtag subtag-vectorH)
+(defconstant min-array-subtag subtag-arrayH)
+
+;;; So, we get the remaining subtags (n: (n > max-numeric-subtag) & (n < min-array-subtag))
+;;; for various immediate/node object types.
+
+(define-imm-subtag macptr 3)
+(defconstant min-non-numeric-imm-subtag subtag-macptr)
+(assert (> min-non-numeric-imm-subtag max-numeric-subtag))
+(define-imm-subtag dead-macptr 4)
+(define-imm-subtag code-vector 5)
+(define-imm-subtag creole-object 6)
+(define-imm-subtag xcode-vector 7)  ; code-vector for cross-development
+
+(defconstant max-non-array-imm-subtag (logior (ash 19 ntagbits) fulltag-immheader))
+
+(define-node-subtag catch-frame 4)
+(defconstant min-non-numeric-node-subtag subtag-catch-frame)
+(assert (> min-non-numeric-node-subtag max-numeric-subtag))
+(define-node-subtag function 5)
+(define-node-subtag basic-stream 6)
+(define-node-subtag symbol 7)
+(define-node-subtag lock 8)
+(define-node-subtag hash-vector 9)
+(define-node-subtag pool 10)
+(define-node-subtag weak 11)
+(define-node-subtag package 12)
+(define-node-subtag slot-vector 13)
+(define-node-subtag instance 14)
+(define-node-subtag struct 15)
+(define-node-subtag istruct 16)
+(define-node-subtag value-cell 17)
+(define-node-subtag xfunction 18)       ; Function for cross-development
+(defconstant max-non-array-node-subtag (logior (ash 18 ntagbits) fulltag-nodeheader))
+
+(define-subtag character fulltag-imm 9)
+(define-subtag vsp-protect fulltag-imm 7)
+(define-subtag slot-unbound fulltag-imm 10)
+(defconstant slot-unbound-marker subtag-slot-unbound)
+(define-subtag illegal fulltag-imm 11)
+(defconstant illegal-marker subtag-illegal)
+(define-subtag go-tag fulltag-imm 12)
+(define-subtag block-tag fulltag-imm 24)
+(define-subtag no-thread-local-binding fulltag-imm 30)
+(define-subtag unbound fulltag-imm 6)
+(defconstant unbound-marker subtag-unbound)
+(defconstant undefined unbound-marker)
+
+
+(defconstant max-64-bit-constant-index (ash (+ #x7fff ppc32::misc-dfloat-offset) -3))
+(defconstant max-32-bit-constant-index (ash (+ #x7fff ppc32::misc-data-offset) -2))
+(defconstant max-16-bit-constant-index (ash (+ #x7fff ppc32::misc-data-offset) -1))
+(defconstant max-8-bit-constant-index (+ #x7fff ppc32::misc-data-offset))
+(defconstant max-1-bit-constant-index (ash (+ #x7fff ppc32::misc-data-offset) 5))
+
+
+;;; The objects themselves look something like this:
+
+;;; Order of CAR and CDR doesn't seem to matter much - there aren't
+;;; too many tricks to be played with predecrement/preincrement addressing.
+;;; Keep them in the confusing MCL 3.0 order, to avoid confusion.
+(define-lisp-object cons tag-list 
+  cdr 
+  car)
+
+
+(define-fixedsized-object ratio
+  numer
+  denom)
+
+(define-fixedsized-object single-float
+  value)
+
+(define-fixedsized-object double-float
+  pad
+  value
+  val-low)
+
+(define-fixedsized-object complex
+  realpart
+  imagpart
+)
+
+
+;;; There are two kinds of macptr; use the length field of the header if you
+;;; need to distinguish between them
+(define-fixedsized-object macptr
+  address
+  domain
+  type
+)
+
+(define-fixedsized-object xmacptr
+  address
+  domain
+  type
+  flags
+  link
+)
+
+;;; Catch frames go on the tstack; they point to a minimal lisp-frame
+;;; on the cstack.  (The catch/unwind-protect PC is on the cstack, where
+;;; the GC expects to find it.)
+(define-fixedsized-object catch-frame
+  catch-tag                             ; #<unbound> -> unwind-protect, else catch
+  link                                  ; tagged pointer to next older catch frame
+  mvflag                                ; 0 if single-value, 1 if uwp or multiple-value
+  csp                                   ; pointer to control stack
+  db-link                               ; value of dynamic-binding link on thread entry.
+  save-save7                            ; saved registers
+  save-save6
+  save-save5
+  save-save4
+  save-save3
+  save-save2
+  save-save1
+  save-save0
+  xframe                                ; exception-frame link
+  tsp-segment                           ; mostly padding, for now.
+)
+
+(define-fixedsized-object lock
+  _value                                ;finalizable pointer to kernel object
+  kind                                  ; '0 = recursive-lock, '1 = rwlock
+  writer				;tcr of owning thread or 0
+  name
+  whostate
+  whostate-2
+  )
+
+
+
+(define-fixedsized-object symbol
+  pname
+  vcell
+  fcell
+  package-predicate
+  flags
+  plist
+  binding-index
+)
+
+
+
+(defconstant nilsym-offset (+ t-offset symbol.size))
+
+
+(define-fixedsized-object vectorH
+  logsize                               ; fillpointer if it has one, physsize otherwise
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+)
+
+(define-lisp-object arrayH fulltag-misc
+  header                                ; subtag = subtag-arrayH
+  rank                                  ; NEVER 1
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0  
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+ ;; Dimensions follow
+)
+
+(defconstant arrayH.rank-cell 0)
+(defconstant arrayH.physsize-cell 1)
+(defconstant arrayH.data-vector-cell 2)
+(defconstant arrayH.displacement-cell 3)
+(defconstant arrayH.flags-cell 4)
+(defconstant arrayH.dim0-cell 5)
+
+(defconstant arrayH.flags-cell-bits-byte (byte 8 0))
+(defconstant arrayH.flags-cell-subtag-byte (byte 8 8))
+
+
+(define-fixedsized-object value-cell
+  value)
+
+;;; The kernel uses these (rather generically named) structures
+;;; to keep track of various memory regions it (or the lisp) is
+;;; interested in.
+;;; The gc-area record definition in "ccl:interfaces;mcl-records.lisp"
+;;; matches this.
+
+(define-storage-layout area 0
+  pred                                  ; pointer to preceding area in DLL
+  succ                                  ; pointer to next area in DLL
+  low                                   ; low bound on area addresses
+  high                                  ; high bound on area addresses.
+  active                                ; low limit on stacks, high limit on heaps
+  softlimit                             ; overflow bound
+  hardlimit                             ; another one
+  code                                  ; an area-code; see below
+  markbits                              ; bit vector for GC
+  ndnodes                               ; "active" size of dynamic area or stack
+  older                                 ; in EGC sense
+  younger                               ; also for EGC
+  h                                     ; Handle or null pointer
+  softprot                              ; protected_area structure pointer
+  hardprot                              ; another one.
+  owner                                 ; fragment (library) which "owns" the area
+  refbits                               ; bitvector for intergenerational refernces
+  threshold                             ; for egc
+  gc-count                              ; generational gc count.
+  static-dnodes                         ; for honsing, etc.
+  static-used                           ; bitvector
+)
+
+
+(define-storage-layout protected-area 0
+  next
+  start                                 ; first byte (page-aligned) that might be protected
+  end                                   ; last byte (page-aligned) that could be protected
+  nprot                                 ; Might be 0
+  protsize                              ; number of bytes to protect
+  why)
+
+(defconstant tcr-bias 0)
+
+(define-storage-layout tcr (- tcr-bias)
+  prev					; in doubly-linked list 
+  next					; in doubly-linked list 
+  lisp-fpscr-high
+  lisp-fpscr-low
+  db-link				; special binding chain head 
+  catch-top				; top catch frame 
+  save-vsp				; VSP when in foreign code 
+  save-tsp				; TSP when in foreign code 
+  cs-area				; cstack area pointer 
+  vs-area				; vstack area pointer 
+  ts-area				; tstack area pointer 
+  cs-limit				; cstack overflow limit
+  total-bytes-allocated-high
+  total-bytes-allocated-low
+  log2-allocation-quantum		; unboxed
+  interrupt-pending			; fixnum
+  xframe				; exception frame linked list
+  errno-loc				; thread-private, maybe
+  ffi-exception				; fpscr bits from ff-call.
+  osid					; OS thread id 
+  valence				; odd when in foreign code 
+  foreign-exception-status
+  native-thread-info
+  native-thread-id
+  last-allocptr
+  save-allocptr
+  save-allocbase
+  reset-completion
+  activate
+  suspend-count
+  suspend-context
+  pending-exception-context
+  suspend				; semaphore for suspension notify 
+  resume				; sempahore for resumption notify
+  flags					; foreign, being reset, ...
+  gc-context
+  termination-semaphore
+  unwinding
+  tlb-limit
+  tlb-pointer
+  shutdown-count
+  safe-ref-address
+)
+
+(defconstant interrupt-level-binding-index (ash 1 fixnumshift))
+
+(define-storage-layout lockptr 0
+  avail
+  owner
+  count
+  signal
+  waiting
+  malloced-ptr
+  spinlock)
+
+(define-storage-layout rwlock 0
+  spin
+  state
+  blocked-writers
+  blocked-readers
+  writer
+  reader-signal
+  writer-signal
+  malloced-ptr
+  )
+
+;;; For the eabi port: mark this stack frame as Lisp's (since EABI
+;;; foreign frames can be the same size as a lisp frame.)
+
+
+(ppc32::define-storage-layout lisp-frame 0
+  backlink
+  savefn
+  savelr
+  savevsp
+)
+
+(ppc32::define-storage-layout c-frame 0
+  backlink
+  crsave
+  savelr
+  unused-1
+  unused-2
+  savetoc
+  param0
+  param1
+  param2
+  param3
+  param4
+  param5
+  param6
+  param7
+)
+
+(defconstant c-frame.minsize c-frame.size)
+
+;;; .SPeabi-ff-call "shrinks" this frame after loading the GPRs.
+(ppc32::define-storage-layout eabi-c-frame 0
+  backlink
+  savelr
+  param0
+  param1
+  param2
+  param3
+  param4
+  param5
+  param6
+  param7
+)
+
+(defconstant eabi-c-frame.minsize eabi-c-frame.size)
+
+(defmacro define-header (name element-count subtag)
+  `(defconstant ,name (logior (ash ,element-count num-subtag-bits) ,subtag)))
+
+(define-header single-float-header single-float.element-count subtag-single-float)
+(define-header double-float-header double-float.element-count subtag-double-float)
+(define-header one-digit-bignum-header 1 subtag-bignum)
+(define-header two-digit-bignum-header 2 subtag-bignum)
+(define-header three-digit-bignum-header 3 subtag-bignum)
+(define-header symbol-header symbol.element-count subtag-symbol)
+(define-header value-cell-header value-cell.element-count subtag-value-cell)
+(define-header macptr-header macptr.element-count subtag-macptr)
+
+(defconstant yield-syscall
+  #+darwinppc-target -60
+  #+linuxppc-target #$__NR_sched_yield)
+)
+
+
+
+
+(defun %kernel-global (sym)
+  (let* ((pos (position sym ppc::*ppc-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ fulltag-nil (* (1+ pos) 4)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+(defmacro kernel-global (sym)
+  (let* ((pos (position sym ppc::*ppc-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ fulltag-nil (* (1+ pos) 4)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+;;; The kernel imports things that are defined in various other
+;;; libraries for us.  The objects in question are generally
+;;; fixnum-tagged; the entries in the "kernel-imports" vector are 4
+;;; bytes apart.
+(ccl::defenum (:prefix "KERNEL-IMPORT-" :start 0 :step 4)
+  fd-setsize-bytes
+  do-fd-set
+  do-fd-clr
+  do-fd-is-set
+  do-fd-zero
+  MakeDataExecutable
+  GetSharedLibrary
+  FindSymbol
+  malloc
+  free
+  jvm-init
+  tcr-frame-ptr
+  register-xmacptr-dispose-function
+  open-debug-output
+  get-r-debug
+  restore-soft-stack-limit
+  egc-control
+  lisp-bug
+  NewThread
+  YieldToThread
+  DisposeThread
+  ThreadCurrentStackSpace
+  usage-exit
+  save-fp-context
+  restore-fp-context
+  put-altivec-registers
+  get-altivec-registers
+  new-semaphore
+  wait-on-semaphore
+  signal-semaphore
+  destroy-semaphore
+  new-recursive-lock
+  lock-recursive-lock
+  unlock-recursive-lock
+  destroy-recursive-lock
+  suspend-other-threads
+  resume-other-threads
+  suspend-tcr
+  resume-tcr
+  rwlock-new
+  rwlock-destroy
+  rwlock-rlock
+  rwlock-wlock
+  rwlock-unlock
+  recursive-lock-trylock
+  foreign-name-and-offset
+  lisp-read
+  lisp-write
+  lisp-open
+  lisp-fchmod
+  lisp-lseek
+  lisp-close
+  lisp-ftruncate
+  lisp-stat
+  lisp-fstat
+  lisp-futex
+  lisp-opendir
+  lisp-readdir
+  lisp-closedir
+  lisp-pipe
+  lisp-gettimeofday
+  lisp-sigexit
+)
+
+(defmacro nrs-offset (name)
+  (let* ((pos (position name ppc::*ppc-nilreg-relative-symbols* :test #'eq)))
+    (if pos (+ t-offset (* pos symbol.size)))))
+
+
+(defconstant reservation-discharge #x2004)
+
+
+
+(defmacro with-stack-short-floats (specs &body body)
+  (ccl::collect ((binds)
+		 (inits)
+		 (names))
+		(dolist (spec specs)
+		  (let ((name (first spec)))
+		    (binds `(,name (ccl::%make-sfloat)))
+		    (names name)
+		    (let ((init (second spec)))
+		      (when init
+			(inits `(ccl::%short-float ,init ,name))))))
+		`(let* ,(binds)
+		  (declare (dynamic-extent ,@(names))
+			   (short-float ,@(names)))
+		  ,@(inits)
+		  ,@body)))
+
+(defparameter *ppc32-target-uvector-subtags*
+  `((:bignum . ,subtag-bignum)
+    (:ratio . ,subtag-ratio)
+    (:single-float . ,subtag-single-float)
+    (:double-float . ,subtag-double-float)
+    (:complex . ,subtag-complex  )
+    (:symbol . ,subtag-symbol)
+    (:function . ,subtag-function )
+    (:code-vector . ,subtag-code-vector)
+    (:xcode-vector . ,subtag-xcode-vector)
+    (:macptr . ,subtag-macptr )
+    (:catch-frame . ,subtag-catch-frame)
+    (:struct . ,subtag-struct )    
+    (:istruct . ,subtag-istruct )
+    (:pool . ,subtag-pool )
+    (:population . ,subtag-weak )
+    (:hash-vector . ,subtag-hash-vector )
+    (:package . ,subtag-package )
+    (:value-cell . ,subtag-value-cell)
+    (:instance . ,subtag-instance )
+    (:lock . ,subtag-lock )
+    (:slot-vector . ,subtag-slot-vector)
+    (:basic-stream . ,subtag-basic-stream)
+    (:simple-string . ,subtag-simple-base-string )
+    (:bit-vector . ,subtag-bit-vector )
+    (:signed-8-bit-vector . ,subtag-s8-vector )
+    (:unsigned-8-bit-vector . ,subtag-u8-vector )
+    (:signed-16-bit-vector . ,subtag-s16-vector )
+    (:unsigned-16-bit-vector . ,subtag-u16-vector )
+    (:signed-32-bit-vector . ,subtag-s32-vector )
+    (:fixnum-vector . ,subtag-fixnum-vector)
+    (:unsigned-32-bit-vector . ,subtag-u32-vector )
+    (:single-float-vector . ,subtag-single-float-vector)
+    (:double-float-vector . ,subtag-double-float-vector )
+    (:simple-vector . ,subtag-simple-vector )
+    (:vector-header . ,subtag-vectorH)
+    (:array-header . ,subtag-arrayH)))
+
+
+;;; This should return NIL unless it's sure of how the indicated
+;;; type would be represented (in particular, it should return
+;;; NIL if the element type is unknown or unspecified at compile-time.
+(defun ppc32-array-type-name-from-ctype (ctype)
+  (when (typep ctype 'ccl::array-ctype)
+    (let* ((element-type (ccl::array-ctype-element-type ctype)))
+      (typecase element-type
+        (ccl::class-ctype
+         (let* ((class (ccl::class-ctype-class element-type)))
+           (if (or (eq class ccl::*character-class*)
+                   (eq class ccl::*base-char-class*)
+                   (eq class ccl::*standard-char-class*))
+             :simple-string
+             :simple-vector)))
+        (ccl::numeric-ctype
+         (if (eq (ccl::numeric-ctype-complexp element-type) :complex)
+           :simple-vector
+           (case (ccl::numeric-ctype-class element-type)
+             (integer
+              (let* ((low (ccl::numeric-ctype-low element-type))
+                     (high (ccl::numeric-ctype-high element-type)))
+                (cond ((or (null low) (null high)) :simple-vector)
+                      ((and (>= low 0) (<= high 1) :bit-vector))
+                      ((and (>= low 0) (<= high 255)) :unsigned-8-bit-vector)
+                      ((and (>= low 0) (<= high 65535)) :unsigned-16-bit-vector)
+                      ((and (>= low 0) (<= high #xffffffff) :unsigned-32-bit-vector))
+                      ((and (>= low -128) (<= high 127)) :signed-8-bit-vector)
+                      ((and (>= low -32768) (<= high 32767) :signed-16-bit-vector))
+                      ((and (>= low target-most-negative-fixnum)
+                            (<= high target-most-positive-fixnum))
+                       :fixnum-vector)
+                      ((and (>= low (ash -1 31)) (<= high (1- (ash 1 31))))
+                       :signed-32-bit-vector)
+                      (t :simple-vector))))
+             (float
+              (case (ccl::numeric-ctype-format element-type)
+                ((double-float long-float) :double-float-vector)
+                ((single-float short-float) :single-float-vector)
+                (t :simple-vector)))
+             (t :simple-vector))))
+        (ccl::unknown-ctype)
+        (ccl::named-ctype
+         (if (eq element-type ccl::*universal-type*)
+           :simple-vector))
+        (t nil)))))
+        
+(defun ppc32-misc-byte-count (subtag element-count)
+  (declare (fixnum subtag))
+  (if (or (= fulltag-nodeheader (logand subtag fulltagmask))
+          (<= subtag max-32-bit-ivector-subtag))
+    (ash element-count 2)
+    (if (<= subtag max-8-bit-ivector-subtag)
+      element-count
+      (if (<= subtag max-16-bit-ivector-subtag)
+        (ash element-count 1)
+        (if (= subtag subtag-bit-vector)
+          (ash (+ element-count 7) -3)
+          (+ 4 (ash element-count 3)))))))
+
+(defparameter *ppc32-target-arch*
+  (arch::make-target-arch :name :ppc32
+                          :lisp-node-size 4
+                          :nil-value canonical-nil-value
+                          :fixnum-shift fixnumshift
+                          :most-positive-fixnum (1- (ash 1 (1- (- 32 fixnumshift))))
+                          :most-negative-fixnum (- (ash 1 (1- (- 32 fixnumshift))))
+                          :misc-data-offset misc-data-offset
+                          :misc-dfloat-offset misc-dfloat-offset
+                          :nbits-in-word 32
+                          :ntagbits 3
+                          :nlisptagbits 2
+                          :uvector-subtags *ppc32-target-uvector-subtags*
+                          :max-64-bit-constant-index max-64-bit-constant-index
+                          :max-32-bit-constant-index max-32-bit-constant-index
+                          :max-16-bit-constant-index max-16-bit-constant-index
+                          :max-8-bit-constant-index max-8-bit-constant-index
+                          :max-1-bit-constant-index max-1-bit-constant-index
+                          :word-shift 2
+                          :code-vector-prefix ()
+                          :gvector-types '(:ratio :complex :symbol :function
+                                           :catch-frame :struct :istruct
+                                           :pool :population :hash-vector
+                                           :package :value-cell :instance
+                                           :lock :slot-vector
+                                           :simple-vector)
+                          :1-bit-ivector-types '(:bit-vector)
+                          :8-bit-ivector-types '(:signed-8-bit-vector
+                                                 :unsigned-8-bit-vector)
+                          :16-bit-ivector-types '(:signed-16-bit-vector
+                                                  :unsigned-16-bit-vector)
+                          :32-bit-ivector-types '(:signed-32-bit-vector
+                                                  :unsigned-32-bit-vector
+                                                  :single-float-vector
+                                                  :fixnum-vector
+                                                  :single-float
+                                                  :double-float
+                                                  :bignum
+                                                  :simple-string)
+                          :64-bit-ivector-types '(:double-float-vector)
+                          :array-type-name-from-ctype-function
+                          #'ppc32-array-type-name-from-ctype
+                          :package-name "PPC32"
+                          :t-offset t-offset
+                          :array-data-size-function #'ppc32-misc-byte-count
+                          :numeric-type-name-to-typecode-function
+                          #'(lambda (type-name)
+                              (ecase type-name
+                                (fixnum tag-fixnum)
+                                (bignum subtag-bignum)
+                                ((short-float single-float) subtag-single-float)
+                                ((long-float double-float) subtag-double-float)
+                                (ratio subtag-ratio)
+                                (complex subtag-complex)))
+                          :subprims-base ppc::*ppc-subprims-base*
+                          :subprims-shift ppc::*ppc-subprims-shift*
+                          :subprims-table ppc::*ppc-subprims*
+                          :primitive->subprims `(((0 . 23) . ,(ccl::%subprim-name->offset '.SPbuiltin-plus ppc::*ppc-subprims*)))
+                          :unbound-marker-value unbound-marker
+                          :slot-unbound-marker-value slot-unbound-marker
+                          :fixnum-tag tag-fixnum
+                          :single-float-tag subtag-single-float
+                          :single-float-tag-is-subtag t
+                          :double-float-tag subtag-double-float
+                          :cons-tag fulltag-cons
+                          :null-tag fulltag-nil
+                          :symbol-tag subtag-symbol
+                          :symbol-tag-is-subtag t
+                          :function-tag subtag-function
+                          :function-tag-is-subtag t
+                          :big-endian t
+                          :misc-subtag-offset misc-subtag-offset
+                          :car-offset cons.car
+                          :cdr-offset cons.cdr
+                          :subtag-char subtag-character
+                          :charcode-shift charcode-shift
+                          :fulltagmask fulltagmask
+                          :fulltag-misc fulltag-misc
+                          :char-code-limit #x110000
+                          ))
+
+;;; arch macros
+(defmacro defppc32archmacro (name lambda-list &body body)
+  `(arch::defarchmacro :ppc32 ,name ,lambda-list ,@body))
+
+(defppc32archmacro ccl::%make-sfloat ()
+  `(ccl::%alloc-misc ppc32::single-float.element-count ppc32::subtag-single-float))
+
+(defppc32archmacro ccl::%make-dfloat ()
+  `(ccl::%alloc-misc ppc32::double-float.element-count ppc32::subtag-double-float))
+
+(defppc32archmacro ccl::%numerator (x)
+  `(ccl::%svref ,x ppc32::ratio.numer-cell))
+
+(defppc32archmacro ccl::%denominator (x)
+  `(ccl::%svref ,x ppc32::ratio.denom-cell))
+
+(defppc32archmacro ccl::%realpart (x)
+  `(ccl::%svref ,x ppc32::complex.realpart-cell))
+                    
+(defppc32archmacro ccl::%imagpart (x)
+  `(ccl::%svref ,x ppc32::complex.imagpart-cell))
+
+;;;
+(defppc32archmacro ccl::%get-single-float-from-double-ptr (ptr offset)
+ `(ccl::%double-float->short-float (ccl::%get-double-float ,ptr ,offset)
+   (ccl::%alloc-misc 1 ppc32::subtag-single-float)))
+
+(defppc32archmacro ccl::codevec-header-p (word)
+  `(eql ppc32::subtag-code-vector
+    (logand ,word ppc32::subtag-mask)))
+
+(defppc32archmacro ccl::immediate-p-macro (thing)
+  (let* ((tag (gensym)))
+    `(let* ((,tag (ccl::lisptag ,thing)))
+      (declare (fixnum ,tag))
+      (or (= ,tag ppc32::tag-fixnum)
+       (= ,tag ppc32::tag-imm)))))
+
+(defppc32archmacro ccl::hashed-by-identity (thing)
+  (let* ((typecode (gensym)))
+    `(let* ((,typecode (ccl::typecode ,thing)))
+      (declare (fixnum ,typecode))
+      (or
+       (= ,typecode ppc32::tag-fixnum)
+       (= ,typecode ppc32::tag-imm)
+       (= ,typecode ppc32::subtag-symbol)
+       (= ,typecode ppc32::subtag-instance)))))
+
+;;;
+(defppc32archmacro ccl::%get-kernel-global (name)
+  `(ccl::%fixnum-ref 0 (+ ,(ccl::target-nil-value)
+                        ,(%kernel-global
+                          (if (ccl::quoted-form-p name)
+                            (cadr name)
+                            name)))))
+
+(defppc32archmacro ccl::%get-kernel-global-ptr (name dest)
+  `(ccl::%setf-macptr
+    ,dest
+    (ccl::%fixnum-ref-macptr 0 (+ ,(ccl::target-nil-value)
+                                ,(%kernel-global
+                                  (if (ccl::quoted-form-p name)
+                                    (cadr name)
+                                    name))))))
+
+(defppc32archmacro ccl::%target-kernel-global (name)
+  `(ppc32::%kernel-global ,name))
+
+(defppc32archmacro ccl::lfun-vector (fn)
+  fn)
+
+(defppc32archmacro ccl::lfun-vector-lfun (lfv)
+  lfv)
+
+(defppc32archmacro ccl::area-code ()
+  area.code)
+
+(defppc32archmacro ccl::area-succ ()
+  area.succ)
+
+(defppc32archmacro ccl::nth-immediate (f i)
+  `(ccl::%svref ,f ,i))
+
+(defppc32archmacro ccl::set-nth-immediate (f i new)
+  `(setf (ccl::%svref ,f ,i) ,new))
+
+(defppc32archmacro ccl::symptr->symvector (s)
+  s)
+
+(defppc32archmacro ccl::symvector->symptr (s)
+  s)
+
+(defppc32archmacro ccl::function-to-function-vector (f)
+  f)
+
+(defppc32archmacro ccl::function-vector-to-function (v)
+  v)
+
+(defppc32archmacro ccl::with-ffcall-results ((buf) &body body)
+  (let* ((size (+ (* 8 4) (* 31 8))))
+    `(%stack-block ((,buf ,size))
+      ,@body)))
+
+(defconstant arg-check-trap-pc-limit 8)
+
+(provide "PPC32-ARCH")
Index: /branches/new-random/compiler/PPC/PPC32/ppc32-backend.lisp
===================================================================
--- /branches/new-random/compiler/PPC/PPC32/ppc32-backend.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC32/ppc32-backend.lisp	(revision 13309)
@@ -0,0 +1,155 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+(in-package "CCL")
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "NXENV")
+  (require "PPCENV")
+  (require "PPC32-ARCH"))
+
+
+
+
+
+(defvar *ppc32-vinsn-templates* (make-hash-table :test #'eq))
+
+
+
+
+(defvar *known-ppc32-backends* ())
+
+
+#+linuxppc-target
+(defvar *linuxppc32-backend*
+  (make-backend :lookup-opcode #'lookup-ppc-opcode
+		:lookup-macro #'ppc::ppc-macro-function
+		:lap-opcodes ppc::*ppc-opcodes*
+                :define-vinsn 'define-ppc-vinsn
+                :platform-syscall-mask (logior platform-os-linux platform-cpu-ppc)
+		:p2-dispatch *ppc2-specials*
+		:p2-vinsn-templates *ppc32-vinsn-templates*
+		:p2-template-hash-name '*ppc32-vinsn-templates*
+		:p2-compile 'ppc2-compile
+		:target-specific-features
+		'(:powerpc :ppc-target :eabi-target :linux-target :linuxppc-target :ppc32-target :32-bit-target :big-endian-target)
+		:target-fasl-pathname (make-pathname :type "pfsl")
+		:target-platform (logior platform-word-size-32
+                                         platform-cpu-ppc
+                                         platform-os-linux)
+		:target-os :linuxppc
+		:name :linuxppc32
+		:target-arch-name :ppc32
+		:target-foreign-type-data nil
+                :target-arch ppc32::*ppc32-target-arch*))
+
+
+#+darwinppc-target
+(defvar *darwinppc32-backend*
+  (make-backend :lookup-opcode #'lookup-ppc-opcode
+		:lookup-macro #'ppc::ppc-macro-function
+		:lap-opcodes ppc::*ppc-opcodes*
+                :define-vinsn 'define-ppc-vinsn
+                :platform-syscall-mask (logior platform-os-darwin platform-cpu-ppc)                
+		:p2-dispatch *ppc2-specials*
+		:p2-vinsn-templates *ppc32-vinsn-templates*
+		:p2-template-hash-name '*ppc32-vinsn-templates*
+		:p2-compile 'ppc2-compile
+		:target-specific-features
+		'(:powerpc :ppc-target :darwin-target :darwinppc-target :ppc32-target :32-bit-target :big-endian-target)
+		:target-fasl-pathname (make-pathname :type "dfsl")
+		:target-platform (logior platform-word-size-32
+                                         platform-cpu-ppc
+                                         platform-os-darwin)
+		:target-os :darwinppc
+		:name :darwinppc32
+		:target-arch-name :ppc32
+		:target-foreign-type-data nil
+                :target-arch ppc32::*ppc32-target-arch*))
+
+#+linuxppc-target
+(pushnew *linuxppc32-backend* *known-ppc32-backends* :key #'backend-name)
+
+
+#+darwinppc-target
+(pushnew *darwinppc32-backend* *known-ppc32-backends* :key #'backend-name)
+
+(defvar *ppc32-backend* (car *known-ppc32-backends*))
+
+(defun fixup-ppc32-backend ()
+  (dolist (b *known-ppc32-backends*)
+    (setf (backend-lap-opcodes b) ppc::*ppc-opcodes*
+	  (backend-p2-dispatch b) *ppc2-specials*
+	  (backend-p2-vinsn-templates b)  *ppc32-vinsn-templates*)
+    (or (backend-lap-macros b) (setf (backend-lap-macros b)
+                                     (make-hash-table :test #'equalp)))))
+
+
+
+(fixup-ppc32-backend)
+
+#+ppc32-target
+(setq *host-backend* *ppc32-backend* *target-backend* *ppc32-backend*)
+#-ppc32-target
+(unless (backend-target-foreign-type-data *ppc32-backend*)
+  (let* ((ftd (make-ftd
+               :interface-db-directory
+               #+darwinppc-target "ccl:darwin-headers;"
+               #+linuxppc-target "ccl:headers;"
+               :interface-package-name
+               #+darwinppc-target "DARWIN32"
+               #+linuxppc-target "LINUX32"
+               :attributes
+               #+darwinppc-target
+               '(:signed-char t
+                 :struct-by-value t
+                 :prepend-underscores t
+                 :bits-per-word  32
+                 :poweropen-alignment t)
+               #+linuxppc-target
+               '(:bits-per-word 32)
+               :ff-call-expand-function
+               #+linuxppc-target
+               'linux32::expand-ff-call
+               #+darwinppc-target
+               'darwin32::expand-ff-call
+               :ff-call-struct-return-by-implicit-arg-function
+               #+linuxppc-target
+               linux32::record-type-returns-structure-as-first-arg
+               #+darwinppc-target
+               darwin32::record-type-returns-structure-as-first-arg
+               :callback-bindings-function
+               #+linuxppc-target
+               linux32::generate-callback-bindings
+               #+darwinppc-target
+               darwin32::generate-callback-bindings
+               :callback-return-value-function
+               #+linuxppc-target
+               linux32::generate-callback-return-value
+               #+darwinppc-target
+               darwin32::generate-callback-return-value
+               )))
+    (install-standard-foreign-types ftd)
+    (use-interface-dir :libc ftd)
+    (setf (backend-target-foreign-type-data *ppc32-backend*) ftd)))
+
+(pushnew *ppc32-backend* *known-backends* :key #'backend-name)
+
+#+ppc32-target
+(require "PPC32-VINSNS")
+(provide "PPC32-BACKEND")
Index: /branches/new-random/compiler/PPC/PPC32/ppc32-vinsns.lisp
===================================================================
--- /branches/new-random/compiler/PPC/PPC32/ppc32-vinsns.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC32/ppc32-vinsns.lisp	(revision 13309)
@@ -0,0 +1,4036 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "VINSN")
+  (require "PPC32-BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "PPCENV"))
+
+(defmacro define-ppc32-vinsn (vinsn-name (results args &optional temps) &body body)
+  (%define-vinsn *ppc32-backend* vinsn-name results args temps body))
+
+
+;;; Index "scaling" and constant-offset misc-ref vinsns.
+
+(define-ppc32-vinsn scale-node-misc-index (((dest :u32))
+                                            ((idx :imm) ; A fixnum
+                                             )
+                                            ())
+  (addi dest idx ppc32::misc-data-offset))
+
+(define-ppc32-vinsn scale-32bit-misc-index (((dest :u32))
+                                            ((idx :imm) ; A fixnum
+                                             )
+                                            ())
+  (addi dest idx ppc32::misc-data-offset))
+
+(define-ppc32-vinsn scale-16bit-misc-index (((dest :u32))
+                                            ((idx :imm) ; A fixnum
+                                             )
+                                            ())
+  (srwi dest idx 1)
+  (addi dest dest ppc32::misc-data-offset))
+
+(define-ppc32-vinsn scale-8bit-misc-index (((dest :u32))
+                                           ((idx :imm) ; A fixnum
+                                            )
+                                           ())
+  (srwi dest idx 2)
+  (addi dest dest ppc32::misc-data-offset))
+
+(define-ppc32-vinsn scale-64bit-misc-index (((dest :u32))
+					    ((idx :imm) ; A fixnum
+					     )
+					    ())
+  (slwi dest idx 1)
+  (addi dest dest ppc32::misc-dfloat-offset))
+
+(define-ppc32-vinsn scale-1bit-misc-index (((word-index :u32)
+					    (bitnum :u8)) ; (unsigned-byte 5)
+					   ((idx :imm) ; A fixnum
+					    )
+					   )
+                                        ; Logically, we want to:
+                                        ; 1) Unbox the index by shifting it right 2 bits.
+                                        ; 2) Shift (1) right 5 bits
+                                        ; 3) Scale (2) by shifting it left 2 bits.
+                                        ; We get to do all of this with one instruction
+  (rlwinm word-index idx (- ppc32::nbits-in-word 5) 5 (- ppc32::least-significant-bit ppc32::fixnum-shift))
+  (addi word-index word-index ppc32::misc-data-offset) ; Hmmm. Also one instruction, but less impressive somehow.
+  (extrwi bitnum idx 5 (- ppc32::nbits-in-word (+ ppc32::fixnum-shift 5))))
+
+
+
+(define-ppc32-vinsn misc-ref-u32  (((dest :u32))
+                                   ((v :lisp)
+                                    (scaled-idx :u32))
+                                   ())
+  (lwzx dest v scaled-idx))
+
+
+(define-ppc32-vinsn misc-ref-c-u32  (((dest :u32))
+                                     ((v :lisp)
+                                      (idx :u32const))
+                                     ())
+  (lwz dest (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc32-vinsn misc-ref-s32 (((dest :s32))
+                                  ((v :lisp)
+                                   (scaled-idx :u32))
+                                  ())
+  (lwzx dest v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-c-s32  (((dest :s32))
+                                     ((v :lisp)
+                                      (idx :u32const))
+                                     ())
+  (lwz dest (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+
+(define-ppc32-vinsn misc-set-c-u32 (()
+                                    ((val :u32)
+                                     (v :lisp)
+                                     (idx :u32const)))
+  (stw val (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc32-vinsn misc-set-c-s32 (()
+                                    ((val :s32)
+                                     (v :lisp)
+                                     (idx :u32const)))
+  (stw val (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc32-vinsn misc-set-u32 (()
+                                  ((val :u32)
+                                   (v :lisp)
+                                   (scaled-idx :u32)))
+  (stwx val v scaled-idx))
+
+(define-ppc32-vinsn misc-set-s32 (()
+                                  ((val :s32)
+                                   (v :lisp)
+                                   (scaled-idx :u32)))
+  (stwx val v scaled-idx))
+
+                              
+(define-ppc32-vinsn misc-ref-single-float  (((dest :single-float))
+					    ((v :lisp)
+					     (scaled-idx :u32))
+					    ())
+  (lfsx dest v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-c-single-float  (((dest :single-float))
+					      ((v :lisp)
+					       (idx :u32const))
+					      ())
+  (lfs dest (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc32-vinsn misc-ref-double-float  (((dest :double-float))
+					    ((v :lisp)
+					     (scaled-idx :u32))
+					    ())
+  (lfdx dest v scaled-idx))
+
+
+(define-ppc32-vinsn misc-ref-c-double-float  (((dest :double-float))
+					      ((v :lisp)
+					       (idx :u32const))
+					      ())
+  (lfd dest (:apply + ppc32::misc-dfloat-offset (:apply ash idx 3)) v))
+
+(define-ppc32-vinsn misc-set-c-double-float (((val :double-float))
+					     ((v :lisp)
+					      (idx :u32const)))
+  (stfd val (:apply + ppc32::misc-dfloat-offset (:apply ash idx 3)) v))
+
+(define-ppc32-vinsn misc-set-double-float (()
+					   ((val :double-float)
+					    (v :lisp)
+					    (scaled-idx :u32)))
+  (stfdx val v scaled-idx))
+
+(define-ppc32-vinsn misc-set-c-single-float (((val :single-float))
+					     ((v :lisp)
+					      (idx :u32const)))
+  (stfs val (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc32-vinsn misc-set-single-float (()
+					   ((val :single-float)
+					    (v :lisp)
+					    (scaled-idx :u32)))
+  (stfsx val v scaled-idx))
+
+
+(define-ppc32-vinsn misc-ref-u16  (((dest :u16))
+                                   ((v :lisp)
+                                    (scaled-idx :u32))
+                                   ())
+  (lhzx dest v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-c-u16  (((dest :u16))
+                                     ((v :lisp)
+                                      (idx :u32const))
+                                     ())
+  (lhz dest (:apply + ppc32::misc-data-offset (:apply ash idx 1)) v))
+
+(define-ppc32-vinsn misc-set-c-u16  (((val :u16))
+                                     ((v :lisp)
+                                      (idx :u32const))
+                                     ())
+  (sth val (:apply + ppc32::misc-data-offset (:apply ash idx 1)) v))
+
+(define-ppc32-vinsn misc-set-u16 (((val :u16))
+                                  ((v :lisp)
+                                   (scaled-idx :s32)))
+  (sthx val v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-s16  (((dest :s16))
+                                   ((v :lisp)
+                                    (scaled-idx :u32))
+                                   ())
+  (lhax dest v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-c-s16  (((dest :s16))
+                                     ((v :lisp)
+                                      (idx :u32const))
+                                     ())
+  (lha dest (:apply + ppc32::misc-data-offset (:apply ash idx 1)) v))
+
+
+(define-ppc32-vinsn misc-set-c-s16  (((val :s16))
+                                     ((v :lisp)
+                                      (idx :u32const))
+                                     ())
+  (sth val (:apply + ppc32::misc-data-offset (:apply ash idx 1)) v))
+
+(define-ppc32-vinsn misc-set-s16 (((val :s16))
+                                  ((v :lisp)
+                                   (scaled-idx :s32)))
+  (sthx val v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-u8  (((dest :u8))
+                                  ((v :lisp)
+                                   (scaled-idx :u32))
+                                  ())
+  (lbzx dest v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-c-u8  (((dest :u8))
+                                    ((v :lisp)
+                                     (idx :u32const))
+                                    ())
+  (lbz dest (:apply + ppc32::misc-data-offset idx) v))
+
+(define-ppc32-vinsn misc-set-c-u8  (((val :u8))
+                                    ((v :lisp)
+                                     (idx :u32const))
+                                    ())
+  (stb val (:apply + ppc32::misc-data-offset idx) v))
+
+(define-ppc32-vinsn misc-set-u8  (((val :u8))
+                                  ((v :lisp)
+                                   (scaled-idx :u32))
+                                  ())
+  (stbx val v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-s8  (((dest :s8))
+                                  ((v :lisp)
+                                   (scaled-idx :u32))
+                                  ())
+  (lbzx dest v scaled-idx)
+  (extsb dest dest))
+
+(define-ppc32-vinsn misc-ref-c-s8  (((dest :s8))
+                                    ((v :lisp)
+                                     (idx :u32const))
+                                    ())
+  (lbz dest (:apply + ppc32::misc-data-offset idx) v)
+  (extsb dest dest))
+
+(define-ppc32-vinsn misc-set-c-s8  (((val :s8))
+                                    ((v :lisp)
+                                     (idx :u32const))
+                                    ())
+  (stb val (:apply + ppc32::misc-data-offset idx) v))
+
+(define-ppc32-vinsn misc-set-s8  (((val :s8))
+                                  ((v :lisp)
+                                   (scaled-idx :u32))
+                                  ())
+  (stbx val v scaled-idx))
+
+(define-ppc32-vinsn misc-ref-c-bit (((dest :u8))
+                                    ((v :lisp)
+                                     (idx :u32const))
+                                    ())
+  (lwz dest (:apply + ppc32::misc-data-offset (:apply ash idx -5)) v)
+  (rlwinm dest dest (:apply 1+ (:apply logand idx #x1f)) 31 31))
+
+(define-ppc32-vinsn misc-ref-c-bit-fixnum (((dest :imm))
+                                           ((v :lisp)
+                                            (idx :u32const))
+                                           ((temp :u32)))
+  (lwz temp (:apply + ppc32::misc-data-offset (:apply ash idx -5)) v)
+  (rlwinm dest 
+          temp
+          (:apply + 1 ppc32::fixnumshift (:apply logand idx #x1f)) 
+          (- ppc32::least-significant-bit ppc32::fixnumshift)
+          (- ppc32::least-significant-bit ppc32::fixnumshift)))
+
+
+(define-ppc32-vinsn misc-ref-node  (((dest :lisp))
+                                    ((v :lisp)
+                                     (scaled-idx :s32))
+                                    ())
+  (lwzx dest v scaled-idx))
+
+
+
+
+(define-ppc32-vinsn misc-ref-c-node (((dest :lisp))
+                                     ((v :lisp)
+                                      (idx :s16const))
+                                     ())
+  (lwz dest (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc32-vinsn misc-set-node (()
+                                  ((val :lisp)
+                                   (v :lisp)
+                                   (scaled-idx :u32)))
+  (stwx val v scaled-idx))
+
+;;; This should only be used for initialization (when the value being
+;;; stored is known to be older than the vector V.)
+(define-ppc32-vinsn misc-set-c-node (()
+                                     ((val :lisp)
+                                      (v :lisp)
+                                      (idx :s16const))
+                                     ())
+  (stw val (:apply + ppc32::misc-data-offset (:apply ash idx 2)) v))
+
+
+(define-ppc32-vinsn misc-element-count-fixnum (((dest :imm))
+                                               ((v :lisp))
+                                               ((temp :u32)))
+  (lwz temp ppc32::misc-header-offset v)
+  (rlwinm dest 
+          temp 
+          (- ppc32::nbits-in-word (- ppc32::num-subtag-bits ppc32::fixnumshift))
+          (- ppc32::num-subtag-bits ppc32::fixnumshift) 
+          (- ppc32::least-significant-bit ppc32::fixnumshift)))
+
+(define-ppc32-vinsn check-misc-bound (()
+                                      ((idx :imm)
+                                       (v :lisp))
+                                      ((temp :u32)))
+  (lwz temp ppc32::misc-header-offset v)
+  (rlwinm temp 
+          temp 
+          (- ppc32::nbits-in-word (- ppc32::num-subtag-bits ppc32::fixnumshift))
+          (- ppc32::num-subtag-bits ppc32::fixnumshift) 
+          (- ppc32::least-significant-bit ppc32::fixnumshift))
+  (twlge idx temp))
+
+(define-ppc32-vinsn 2d-unscaled-index (((dest :imm)
+                                        (dim1 :u32))
+				       ((dim1 :u32)
+                                        (i :imm)
+					(j :imm)))
+  (mullw dim1 i dim1)
+  (add dest dim1 j))
+
+;; dest <- (+ (* i dim1 dim2) (* j dim2) k)
+(define-ppc32-vinsn 3d-unscaled-index (((dest :imm)
+                                        (dim1 :u32)
+                                        (dim2 :u32))
+				       ((dim1 :u32)
+                                        (dim2 :u32)
+                                        (i :imm)
+					(j :imm)
+                                        (k :imm)))
+  (mullw dim1 dim1 dim2)
+  (mullw dim2 j dim2)
+  (mullw dim1 i dim1)
+  (add dim2 dim1 dim2)
+  (add dest dim2 k))
+
+
+(define-ppc32-vinsn 2d-dim1 (((dest :u32))
+                             ((header :lisp)))
+  (lwz dest (+ ppc32::misc-data-offset (* 4 (1+ ppc32::arrayH.dim0-cell))) header)
+  (srawi dest dest ppc32::fixnumshift))
+
+(define-ppc32-vinsn 3d-dims (((dim1 :u32)
+                              (dim2 :u32))
+                             ((header :lisp)))
+  (lwz dim1 (+ ppc32::misc-data-offset (* 4 (1+ ppc32::arrayH.dim0-cell))) header)
+  (lwz dim2 (+ ppc32::misc-data-offset (* 4 (+ 2 ppc32::arrayH.dim0-cell))) header)
+  (srawi dim1 dim1 ppc32::fixnumshift)
+  (srawi dim2 dim2 ppc32::fixnumshift))
+
+;; Return dim1 (unboxed)
+(define-ppc32-vinsn check-2d-bound (((dim :u32))
+                                    ((i :imm)
+                                     (j :imm)
+                                     (header :lisp)))
+  (lwz dim (+ ppc32::misc-data-offset (* 4 ppc32::arrayH.dim0-cell)) header)
+  (twlge i dim)
+  (lwz dim (+ ppc32::misc-data-offset (* 4 (1+ ppc32::arrayH.dim0-cell))) header)
+  (twlge j dim)
+  (srawi dim dim ppc32::fixnumshift))
+
+(define-ppc32-vinsn check-3d-bound (((dim1 :u32)
+                                     (dim2 :u32))
+                                    ((i :imm)
+                                     (j :imm)
+                                     (k :imm)
+                                     (header :lisp)))
+  (lwz dim1 (+ ppc32::misc-data-offset (* 4 ppc32::arrayH.dim0-cell)) header)
+  (twlge i dim1)
+  (lwz dim1 (+ ppc32::misc-data-offset (* 4 (1+ ppc32::arrayH.dim0-cell))) header)
+  (twlge j dim1)
+  (lwz dim2 (+ ppc32::misc-data-offset (* 4 (+ 2 ppc32::arrayH.dim0-cell))) header)
+  (twlge k dim2)
+  (srawi dim1 dim1 ppc32::fixnumshift)
+  (srawi dim2 dim2 ppc32::fixnumshift))
+
+(define-ppc32-vinsn array-data-vector-ref (((dest :lisp))
+                                           ((header :lisp)))
+  (lwz dest ppc32::arrayH.data-vector header))
+  
+
+(define-ppc32-vinsn check-arrayH-rank (()
+                                       ((header :lisp)
+                                        (expected :u32const))
+                                       ((rank :imm)))
+  (lwz rank ppc32::arrayH.rank header)
+  (twi 27 rank (:apply ash expected ppc32::fixnumshift)))
+
+(define-ppc32-vinsn check-arrayH-flags (()
+                                        ((header :lisp)
+                                         (expected :u16const))
+                                        ((flags :imm)
+                                         (xreg :u32)))
+  (lis xreg (:apply ldb (byte 16 16) (:apply ash expected ppc32::fixnumshift)))
+  (ori xreg xreg (:apply ldb (byte 16 0) (:apply ash expected ppc32::fixnumshift)))
+  (lwz flags ppc32::arrayH.flags header)
+  (tw 27 flags xreg))
+
+  
+
+
+  
+(define-ppc32-vinsn node-slot-ref  (((dest :lisp))
+                                    ((node :lisp)
+                                     (cellno :u32const)))
+  (lwz dest (:apply + ppc32::misc-data-offset (:apply ash cellno 2)) node))
+
+
+
+(define-ppc32-vinsn  %slot-ref (((dest :lisp))
+                                ((instance (:lisp (:ne dest)))
+                                 (index :lisp))
+                                ((scaled :u32)))
+  (la scaled ppc32::misc-data-offset index)
+  (lwzx dest instance scaled)
+  (tweqi dest ppc32::slot-unbound-marker))
+
+
+;;; Untagged memory reference & assignment.
+
+(define-ppc32-vinsn mem-ref-c-fullword (((dest :u32))
+                                        ((src :address)
+                                         (index :s16const)))
+  (lwz dest index src))
+
+
+(define-ppc32-vinsn mem-ref-c-signed-fullword (((dest :s32))
+                                               ((src :address)
+                                                (index :s16const)))
+  (lwz dest index src))
+
+(define-ppc32-vinsn mem-ref-c-natural (((dest :u32))
+                                       ((src :address)
+                                        (index :s16const)))
+  (lwz dest index src))
+  
+
+(define-ppc32-vinsn mem-ref-fullword (((dest :u32))
+                                      ((src :address)
+                                       (index :s32)))
+  (lwzx dest src index))
+
+(define-ppc32-vinsn mem-ref-signed-fullword (((dest :u32))
+                                             ((src :address)
+                                              (index :s32)))
+  (lwzx dest src index))
+
+(define-ppc32-vinsn mem-ref-natural (((dest :u32))
+                                     ((src :address)
+                                      (index :s32)))
+  (lwzx dest src index))
+
+
+(define-ppc32-vinsn mem-ref-c-u16 (((dest :u16))
+                                   ((src :address)
+                                    (index :s16const)))
+  (lhz dest index src))
+
+
+(define-ppc32-vinsn mem-ref-u16 (((dest :u16))
+                                 ((src :address)
+                                  (index :s32)))
+  (lhzx dest src index))
+
+
+
+(define-ppc32-vinsn mem-ref-c-s16 (((dest :s16))
+                                   ((src :address)
+                                    (index :s16const)))
+  (lha dest index src))
+
+(define-ppc32-vinsn mem-ref-s16 (((dest :s16))
+                                 ((src :address)
+                                  (index :s32)))
+  (lhax dest src index))
+
+(define-ppc32-vinsn mem-ref-c-u8 (((dest :u8))
+                                  ((src :address)
+                                   (index :s16const)))
+  (lbz dest index src))
+
+(define-ppc32-vinsn mem-ref-u8 (((dest :u8))
+                                ((src :address)
+                                 (index :s32)))
+  (lbzx dest src index))
+
+(define-ppc32-vinsn mem-ref-c-s8 (((dest :s8))
+                                  ((src :address)
+                                   (index :s16const)))
+  (lbz dest index src)
+  (extsb dest dest))
+
+(define-ppc32-vinsn mem-ref-s8 (((dest :s8))
+                                ((src :address)
+                                 (index :s32)))
+  (lbzx dest src index)
+  (extsb dest dest))
+
+(define-ppc32-vinsn mem-ref-c-bit (((dest :u8))
+                                   ((src :address)
+                                    (byte-index :s16const)
+                                    (bit-shift :u8const)))
+  (lbz dest byte-index src)
+  (rlwinm dest dest bit-shift 31 31))
+
+(define-ppc32-vinsn mem-ref-c-bit-fixnum (((dest :lisp))
+                                          ((src :address)
+                                           (byte-index :s16const)
+                                           (bit-shift :u8const))
+                                          ((byteval :u8)))
+  (lbz byteval byte-index src)
+  (rlwinm dest byteval bit-shift 29 29))
+
+(define-ppc32-vinsn mem-ref-bit (((dest :u8))
+                                 ((src :address)
+                                  (bit-index :lisp))
+                                 ((byte-index :s16)
+                                  (bit-shift :u8)))
+  (srwi byte-index bit-index (+ ppc32::fixnumshift 3))
+  (extrwi bit-shift bit-index 3 27)
+  (addi bit-shift bit-shift 29)
+  (lbzx dest src byte-index)
+  (rlwnm dest dest bit-shift 31 31))
+
+
+(define-ppc32-vinsn mem-ref-bit-fixnum (((dest :lisp))
+                                        ((src :address)
+                                         (bit-index :lisp))
+                                        ((byte-index :s16)
+                                         (bit-shift :u8)))
+  (srwi byte-index bit-index (+ ppc32::fixnumshift 3))
+  (extrwi bit-shift bit-index 3 27)
+  (addi bit-shift bit-shift 27)
+  (lbzx byte-index src byte-index)
+  (rlwnm dest
+         byte-index
+         bit-shift
+         (- ppc32::least-significant-bit ppc32::fixnum-shift)
+         (- ppc32::least-significant-bit ppc32::fixnum-shift)))
+
+(define-ppc32-vinsn mem-ref-c-double-float (((dest :double-float))
+					    ((src :address)
+					     (index :s16const)))
+  (lfd dest index src))
+
+(define-ppc32-vinsn mem-ref-double-float (((dest :double-float))
+					  ((src :address)
+					   (index :s32)))
+  (lfdx dest src index))
+
+(define-ppc32-vinsn mem-set-c-double-float (()
+					    ((val :double-float)
+					     (src :address)
+					     (index :s16const)))
+  (stfd val index src))
+
+(define-ppc32-vinsn mem-set-double-float (()
+					  ((val :double-float)
+					   (src :address)
+					   (index :s32)))
+  (stfdx val src index))
+
+(define-ppc32-vinsn mem-ref-c-single-float (((dest :single-float))
+					    ((src :address)
+					     (index :s16const)))
+  (lfs dest index src))
+
+(define-ppc32-vinsn mem-ref-single-float (((dest :single-float))
+					  ((src :address)
+					   (index :s32)))
+  (lfsx dest src index))
+
+(define-ppc32-vinsn mem-set-c-single-float (()
+					    ((val :single-float)
+					     (src :address)
+					     (index :s16const)))
+  (stfs val index src))
+
+(define-ppc32-vinsn mem-set-single-float (()
+					  ((val :single-float)
+					   (src :address)
+					   (index :s32)))
+  (stfsx val src index))
+
+
+(define-ppc32-vinsn mem-set-c-address (()
+                                       ((val :address)
+                                        (src :address)
+                                        (index :s16const)))
+  (stw val index src))
+
+(define-ppc32-vinsn mem-set-address (()
+                                     ((val :address)
+                                      (src :address)
+                                      (index :s32)))
+  (stwx val src index))
+
+(define-ppc32-vinsn mem-set-c-fullword (()
+					((val :u32)
+					 (src :address)
+					 (index :s16const)))
+  (stw val index src))
+
+(define-ppc32-vinsn mem-set-fullword (()
+				      ((val :u32)
+				       (src :address)
+				       (index :s32)))
+  (stwx val src index))
+
+(define-ppc32-vinsn mem-set-c-halfword (()
+					((val :u16)
+					 (src :address)
+					 (index :s16const)))
+  (sth val index src))
+
+(define-ppc32-vinsn mem-set-halfword (()
+				      ((val :u16)
+				       (src :address)
+				       (index :s32)))
+  (sthx val src index))
+
+(define-ppc32-vinsn mem-set-c-byte (()
+				    ((val :u16)
+				     (src :address)
+				     (index :s16const)))
+  (stb val index src))
+
+(define-ppc32-vinsn mem-set-byte (()
+				  ((val :u8)
+				   (src :address)
+				   (index :s32)))
+  (stbx val src index))
+
+(define-ppc32-vinsn mem-set-c-bit-0 (()
+				     ((src :address)
+				      (byte-index :s16const)
+				      (mask-begin :u8const)
+				      (mask-end :u8const))
+				     ((val :u8)))
+  (lbz val byte-index src)
+  (rlwinm val val 0 mask-begin mask-end)
+  (stb val byte-index src))
+
+(define-ppc32-vinsn mem-set-c-bit-1 (()
+				     ((src :address)
+				      (byte-index :s16const)
+				      (mask :u8const))
+				     ((val :u8)))
+  (lbz val byte-index src)
+  (ori val val mask)
+  (stb val byte-index src))
+
+(define-ppc32-vinsn mem-set-c-bit (()
+				   ((src :address)
+				    (byte-index :s16const)
+				    (bit-index :u8const)
+				    (val :imm))
+				   ((byteval :u8)))
+  (lbz byteval byte-index src)
+  (rlwimi byteval val (:apply logand 31 (:apply - 29 bit-index)) bit-index bit-index)
+  (stb byteval byte-index src))
+
+;;; Hey, they should be happy that it even works.  Who cares how big it is or how
+;;; long it takes ...
+(define-ppc32-vinsn mem-set-bit (()
+				 ((src :address)
+				  (bit-index :lisp)
+				  (val :lisp))
+				 ((bit-shift :u32)
+				  (mask :u32)
+				  (byte-index :u32)
+				  (crf :crf)))
+  (cmplwi crf val (ash 1 ppc32::fixnumshift))
+  (extrwi bit-shift bit-index 3 27)
+  (li mask #x80)
+  (srw mask mask bit-shift)
+  (ble+ crf :got-it)
+  (uuo_interr arch::error-object-not-bit src)
+  :got-it
+  (srwi bit-shift bit-index (+ 3 ppc32::fixnumshift))
+  (lbzx bit-shift src bit-shift)
+  (beq crf :set)
+  (andc mask bit-shift mask)
+  (b :done)
+  :set
+  (or mask bit-shift mask)
+  :done
+  (srwi bit-shift bit-index (+ 3 ppc32::fixnumshift))
+  (stbx mask src bit-shift))
+     
+;;; Tag and subtag extraction, comparison, checking, trapping ...
+
+(define-ppc32-vinsn extract-tag (((tag :u8)) 
+				 ((object :lisp)) 
+				 ())
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits)))
+
+(define-ppc32-vinsn extract-tag-fixnum (((tag :imm))
+                                        ((object :lisp)))
+  (rlwinm tag 
+          object 
+          ppc32::fixnum-shift 
+          (- ppc32::nbits-in-word 
+             (+ ppc32::nlisptagbits ppc32::fixnum-shift)) 
+          (- ppc32::least-significant-bit ppc32::fixnum-shift)))
+
+(define-ppc32-vinsn extract-fulltag (((tag :u8))
+                                     ((object :lisp))
+                                     ())
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::ntagbits)))
+
+
+(define-ppc32-vinsn extract-fulltag-fixnum (((tag :imm))
+                                            ((object :lisp)))
+  (rlwinm tag 
+          object 
+          ppc32::fixnum-shift 
+          (- ppc32::nbits-in-word 
+             (+ ppc32::ntagbits ppc32::fixnum-shift)) 
+          (- ppc32::least-significant-bit ppc32::fixnum-shift)))
+
+(define-ppc32-vinsn extract-typecode (((code :u8))
+                                      ((object :lisp))
+                                      ((crf :crf)))
+  (clrlwi code object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf code ppc32::tag-misc)
+  (bne crf :not-misc)
+  (lbz code ppc32::misc-subtag-offset object)
+  :not-misc)
+
+(define-ppc32-vinsn extract-typecode-fixnum (((code :imm))
+                                             ((object (:lisp (:ne code))))
+                                             ((crf :crf) (subtag :u8)))
+  (rlwinm code 
+          object 
+          ppc32::fixnum-shift 
+          (- ppc32::nbits-in-word 
+             (+ ppc32::nlisptagbits ppc32::fixnum-shift)) 
+          (- ppc32::least-significant-bit ppc32::fixnum-shift))
+  (cmpwi crf code (ash ppc32::tag-misc ppc32::fixnum-shift))
+  (bne crf :not-misc)
+  (lbz subtag ppc32::misc-subtag-offset object)
+  (slwi code subtag ppc32::fixnum-shift)
+  :not-misc)
+
+
+(define-ppc32-vinsn require-fixnum (()
+                                    ((object :lisp))
+                                    ((crf0 (:crf 0))
+                                     (tag :u8)))
+  :again
+  (clrlwi. tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (beq+ crf0 :got-it)
+  (uuo_intcerr arch::error-object-not-fixnum object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-integer (()
+                                     ((object :lisp))
+                                     ((crf0 (:crf 0))
+                                      (tag :u8)))
+  :again
+  (clrlwi. tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (beq+ crf0 :got-it)
+  (cmpwi crf0 tag ppc32::tag-misc)
+  (bne crf0 :no-got)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmpwi crf0 tag ppc32::subtag-bignum)
+  (beq+ crf0 :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-integer object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-simple-vector (()
+                                           ((object :lisp))
+                                           ((tag :u8)
+                                            (crf :crf)))
+  :again
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :no-got)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmpwi crf tag ppc32::subtag-simple-vector)
+  (beq+ crf :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-simple-vector object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-simple-string (()
+                                           ((object :lisp))
+                                           ((tag :u8)
+                                            (crf :crf)
+                                            (crf2 :crf)))
+  :again
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :no-got)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmpwi crf tag ppc32::subtag-simple-base-string)
+  (beq+ crf :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-simple-string object)
+  (b :again)
+  :got-it)
+
+  
+(define-ppc32-vinsn require-real (()
+                                  ((object :lisp))
+                                  ((crf0 (:crf 0))
+                                   (tag :u8)))
+  :again
+  (clrlwi. tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (beq+ crf0 :got-it)
+  (cmpwi crf0 tag ppc32::tag-misc)
+  (bne crf0 :no-got)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmplwi crf0 tag ppc32::max-real-subtag)
+  (ble+ crf0 :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-real object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-number (()
+                                    ((object :lisp))
+                                    ((crf0 (:crf 0))
+                                     (tag :u8)))
+  :again
+  (clrlwi. tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (beq+ crf0 :got-it)
+  (cmpwi crf0 tag ppc32::tag-misc)
+  (bne crf0 :no-got)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmplwi crf0 tag ppc32::max-numeric-subtag)
+  (ble+ crf0 :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-number object)
+  (b :again)
+  :got-it)
+
+
+(define-ppc32-vinsn require-list (()
+                                  ((object :lisp))
+                                  ((tag :u8)
+                                   (crf :crf)))
+  :again
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-list)
+  (beq+ crf :got-it)
+  (uuo_intcerr arch::error-object-not-list object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-symbol (()
+                                    ((object :lisp))
+                                    ((tag :u8)
+                                     (crf :crf)))
+  :again
+  (cmpwi crf object (:apply target-nil-value))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (beq crf :got-it)
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :no-got)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmpwi crf tag ppc32::subtag-symbol)
+  (beq+ crf :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-symbol object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-character (()
+                                       ((object :lisp))
+                                       ((tag :u8)
+                                        (crf :crf)))
+  :again
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::num-subtag-bits))
+  (cmpwi crf tag ppc32::subtag-character)
+  (beq+ crf :got-it)
+  (uuo_intcerr arch::error-object-not-character object)
+  (b :again)
+  :got-it)
+
+
+(define-ppc32-vinsn require-s8 (()
+                                ((object :lisp))
+                                ((crf :crf)
+                                 (tag :u32)))
+  :again
+  (slwi tag object (- ppc32::nbits-in-word (+ 8 ppc32::fixnumshift)))
+  (srawi tag tag (- ppc32::nbits-in-word 8 ))
+  (slwi tag tag ppc32::fixnumshift)
+  (cmpw crf tag object)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-8 object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-u8 (()
+                                ((object :lisp))
+                                ((crf0 (:crf 0))
+                                 (tag :u32)))
+  :again
+  ;; The bottom ppc32::fixnumshift bits and the top (- 32 (+
+  ;; ppc32::fixnumshift 8)) must all be zero.
+  (rlwinm. tag object 0 (- ppc32::nbits-in-word ppc32::fixnumshift) (- ppc32::least-significant-bit (+ ppc32::fixnumshift 8)))
+  (beq+ crf0 :got-it)
+  (uuo_intcerr arch::error-object-not-unsigned-byte-8 object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-s16 (()
+                                ((object :lisp))
+                                ((crf :crf)
+                                 (tag :u32)))
+  :again
+  (slwi tag object (- ppc32::nbits-in-word (+ 16 ppc32::fixnumshift)))
+  (srawi tag tag (- ppc32::nbits-in-word 16))
+  (slwi tag tag ppc32::fixnumshift)
+  (cmpw crf tag object)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-16 object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-u16 (()
+                                ((object :lisp))
+                                ((crf0 (:crf 0))
+                                 (tag :u32)))
+  :again
+  ;; The bottom ppc32::fixnumshift bits and the top (- 32 (+
+  ;; ppc32::fixnumshift 16)) must all be zero.
+  (rlwinm. tag object 0 (- ppc32::nbits-in-word ppc32::fixnumshift) (- ppc32::least-significant-bit (+ ppc32::fixnumshift 16)))
+  (beq+ crf0 :got-it)
+  (uuo_intcerr arch::error-object-not-unsigned-byte-16 object)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-s32 (()
+                                 ((src :lisp))
+                                 ((crfx :crf)
+                                  (crfy :crf)
+                                  (tag :u32)))
+  :again
+  (clrlwi tag src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crfx tag ppc32::tag-fixnum)
+  (cmpwi crfy tag ppc32::tag-misc)
+  (beq+ crfx :got-it)
+  (bne- crfy :bad)
+  (lwz tag ppc32::misc-header-offset src)
+  (cmpwi crfx tag ppc32::one-digit-bignum-header)
+  (beq+ crfx :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-32 src)
+  (b :again)
+  :got-it)
+
+
+(define-ppc32-vinsn require-u32 (()
+                                 ((src :lisp))
+                                 ((crf0 (:crf 0))
+                                  (crf1 :crf)
+                                  (temp :u32)))
+  :again
+  (rlwinm. temp src 0 (- ppc32::nbits-in-word ppc32::fixnumshift) 0)
+  (beq+ crf0 :got-it)
+  (clrlwi temp src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf0 temp ppc32::tag-misc)
+  (bne- crf0 :bad)
+  (lwz temp ppc32::misc-header-offset src)
+  (cmpwi crf1 temp ppc32::two-digit-bignum-header)
+  (cmpwi crf0 temp ppc32::one-digit-bignum-header)
+  (lwz temp ppc32::misc-data-offset src)
+  (beq crf1 :two)
+  (bne crf0 :bad)
+  (cmpwi crf0 temp 0)
+  (bgt+ crf0 :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-unsigned-byte-32 src)
+  (b :again)
+  :two
+  (lwz temp (+ ppc32::misc-data-offset 4) src)
+  (cmpwi crf0 temp 0)
+  (bne- crf0 :bad)
+  :got-it)
+
+(define-ppc32-vinsn require-s64 (()
+                                 ((src :lisp))
+                                 ((crfx :crf)
+                                  (crfy :crf)
+                                  (tag :u32)))
+  :again
+  (clrlwi tag src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crfx tag ppc32::tag-fixnum)
+  (cmpwi crfy tag ppc32::tag-misc)
+  (beq+ crfx :got-it)
+  (bne- crfy :bad)
+  (lwz tag ppc32::misc-header-offset src)
+  (cmpwi crfx tag ppc32::one-digit-bignum-header)
+  (cmpwi crfy tag ppc32::two-digit-bignum-header)
+  (lwz tag ppc32::misc-data-offset src)
+  (beq+ crfx :got-it)
+  (beq+ crfy :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-64 src)
+  (b :again)
+  :got-it)
+
+(define-ppc32-vinsn require-u64 (()
+                                 ((src :lisp))
+                                 ((crf0 (:crf 0))
+                                  (crf1 :crf)
+                                  (crf2 :crf)
+                                  (temp :u32)))
+  :again
+  (rlwinm. temp src 0 (- ppc32::nbits-in-word ppc32::fixnumshift) 0)
+  (beq+ crf0 :got-it)
+  (clrlwi temp src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf0 temp ppc32::tag-misc)
+  (bne- crf0 :bad)
+  (lwz temp ppc32::misc-header-offset src)
+  (cmpwi crf2 temp ppc32::three-digit-bignum-header)
+  (cmpwi crf1 temp ppc32::two-digit-bignum-header)
+  (cmpwi crf0 temp ppc32::one-digit-bignum-header)
+  (lwz temp ppc32::misc-data-offset src)
+  (beq crf2 :three)
+  (beq crf1 :two)
+  (bne crf0 :bad)
+  (cmpwi crf0 temp 0)
+  (bgt+ crf0 :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-unsigned-byte-64 src)
+  (b :again)
+  :three
+  (lwz temp (+ ppc32::misc-data-offset 8) src)
+  (cmpwi crf0 temp 0)
+  (beq+ crf0 :got-it)
+  (b :bad)
+  :two
+  (lwz temp (+ ppc32::misc-data-offset 4) src)
+  (cmpwi crf0 temp 0)
+  (blt- crf0 :bad)
+  :got-it)
+
+
+
+(define-ppc32-vinsn require-char-code (()
+                                       ((object :lisp))
+                                       ((crf0 (:crf 0))
+                                        (crf1 :crf)
+                                        (tag :u32)))
+  :again
+  (clrlwi. tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (lis tag (ash (ash #x110000 ppc32::fixnumshift) -16))
+  (cmplw crf1 object tag)
+  (bne crf0 :bad)
+  (blt+ crf1 :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-mod-char-code-limit object)
+  (b :again)
+  :got-it)
+
+
+(define-ppc32-vinsn box-fixnum (((dest :imm))
+                                ((src :s32)))
+  (slwi dest src ppc32::fixnumshift))
+
+(define-ppc32-vinsn fixnum->signed-natural (((dest :s32))
+                                            ((src :imm)))
+  (srawi dest src ppc32::fixnumshift))
+
+(define-ppc32-vinsn fixnum->unsigned-natural (((dest :u32))
+                                              ((src :imm)))
+  (srwi dest src ppc32::fixnumshift))
+
+;;; An object is of type (UNSIGNED-BYTE 32) iff
+;;;  a) it's of type (UNSIGNED-BYTE 30) (e.g., an unsigned fixnum)
+;;;  b) it's a bignum of length 1 and the 0'th digit is positive
+;;;  c) it's a bignum of length 2 and the sign-digit is 0.
+
+(define-ppc32-vinsn unbox-u32 (((dest :u32))
+                               ((src :lisp))
+                               ((crf0 (:crf 0))
+                                (crf1 :crf)))
+  (rlwinm. dest src 0 (- ppc32::nbits-in-word ppc32::fixnumshift) 0)
+  (srwi dest src ppc32::fixnumshift)
+  (beq+ crf0 :got-it)
+  (clrlwi dest src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf0 dest ppc32::tag-misc)
+  (bne- crf0 :bad)
+  (lwz dest ppc32::misc-header-offset src)
+  (cmpwi crf1 dest ppc32::two-digit-bignum-header)
+  (cmpwi crf0 dest ppc32::one-digit-bignum-header)
+  (lwz dest ppc32::misc-data-offset src)
+  (beq crf1 :two)
+  (bne crf0 :bad)
+  (cmpwi crf0 dest 0)
+  (bgt+ crf0 :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-unsigned-byte-32 src)
+  :two
+  (lwz dest (+ ppc32::misc-data-offset 4) src)
+  (cmpwi crf0 dest 0)
+  (bne- crf0 :bad)
+  (lwz dest ppc32::misc-data-offset src)
+  :got-it)
+
+;;; an object is of type (SIGNED-BYTE 32) iff
+;;; a) it's a fixnum
+;;; b) it's a bignum with exactly one digit.
+
+(define-ppc32-vinsn unbox-s32 (((dest :s32))
+                               ((src :lisp))
+                               ((crfx :crf)
+                                (crfy :crf)
+                                (tag :u32)))
+  (clrlwi tag src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crfx tag ppc32::tag-fixnum)
+  (cmpwi crfy tag ppc32::tag-misc)
+  (srawi dest src ppc32::fixnumshift)
+  (beq+ crfx :got-it)
+  (bne- crfy :bad)
+  (lwz tag ppc32::misc-header-offset src)
+  (cmpwi crfx tag ppc32::one-digit-bignum-header)
+  (lwz dest ppc32::misc-data-offset src)
+  (beq+ crfx :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-32 src)
+  :got-it)
+
+;;; For the sake of argument, "dest" is u32.
+;;; Return dest if src is either (signed-byte 32) or (unsigned-byte 32).
+;;; Say that it's not (signed-byte 32) if neither.
+(define-ppc32-vinsn unbox-x32 (((dest :u32))
+                               ((src :lisp))
+                               ((crfx :crf)
+                                (crfy :crf)
+                                (tag :u32)))
+  (clrlwi tag src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crfx tag ppc32::tag-fixnum)
+  (cmpwi crfy tag ppc32::tag-misc)
+  (srawi dest src ppc32::fixnumshift)
+  (beq+ crfx :got-it)
+  (bne- crfy :bad)
+  (lwz tag ppc32::misc-header-offset src)
+  (cmpwi crfx tag (logior (ash 1 ppc32::num-subtag-bits) ppc32::subtag-bignum))
+  (cmpwi crfy tag (logior (ash 2 ppc32::num-subtag-bits) ppc32::subtag-bignum))
+  (lwz dest ppc32::misc-data-offset src)
+  (beq crfx :got-it)
+  (lwz tag (+ 4 ppc32::misc-data-offset) src)
+  (cmpwi crfx tag 0)
+  (bne crfy :bad)
+  (beq+ crfx :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-32 src)
+  :got-it)
+
+(define-ppc32-vinsn unbox-u16 (((dest :u16))
+                               ((src :lisp))
+                               ((crf0 (:crf 0))))
+                                        ; The bottom ppc32::fixnumshift bits and the top (- 31 (+ ppc32::fixnumshift 16)) must all be zero.
+  (rlwinm. dest src 0 (- ppc32::nbits-in-word ppc32::fixnumshift) (- ppc32::least-significant-bit (+ ppc32::fixnumshift 16)))
+  (rlwinm dest src (- 32 ppc32::fixnumshift) 16 31)
+  (beq+ crf0 :got-it)
+  (uuo_interr arch::error-object-not-unsigned-byte-16 src)
+  :got-it)
+
+(define-ppc32-vinsn unbox-s16 (((dest :s16))
+                               ((src :lisp))
+                               ((crf :crf)))
+  (slwi dest src (- ppc32::nbits-in-word (+ 16 ppc32::fixnumshift)))
+  (srawi dest dest (- ppc32::nbits-in-word 16))
+  (slwi dest dest ppc32::fixnumshift)
+  (cmpw crf dest src)
+  (srawi dest src ppc32::fixnumshift)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-16 src)
+  :got-it)
+
+  
+  
+(define-ppc32-vinsn unbox-u8 (((dest :u8))
+                              ((src :lisp))
+                              ((crf0 (:crf 0))))
+  ;; The bottom ppc32::fixnumshift bits and the top (- 31 (+
+  ;; ppc32::fixnumshift 8)) must all be zero.
+  (rlwinm. dest src 0 (- ppc32::nbits-in-word ppc32::fixnumshift) (- ppc32::least-significant-bit (+ ppc32::fixnumshift 8)))
+  (rlwinm dest src (- 32 ppc32::fixnumshift) 24 31)
+  (beq+ crf0 :got-it)
+  (uuo_interr arch::error-object-not-unsigned-byte-8 src)
+  :got-it)
+
+(define-ppc32-vinsn %unbox-u8 (((dest :u8))
+                              ((src :lisp))
+)
+  (rlwinm dest src (- 32 ppc32::fixnumshift) 24 31))
+
+(define-ppc32-vinsn unbox-s8 (((dest :s8))
+                              ((src :lisp))
+                              ((crf :crf)))
+  (slwi dest src (- ppc32::nbits-in-word (+ 8 ppc32::fixnumshift)))
+  (srawi dest dest (- ppc32::nbits-in-word 8))
+  (slwi dest dest ppc32::fixnumshift)
+  (cmpw crf dest src)
+  (srawi dest src ppc32::fixnumshift)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-8 src)
+  :got-it)
+
+(define-ppc32-vinsn unbox-base-char (((dest :u32))
+                                     ((src :lisp))
+                                     ((crf :crf)))
+  (rlwinm dest src 0 24 31)
+  (cmpwi crf dest ppc32::subtag-character)
+  (srwi dest src ppc32::charcode-shift)
+  (beq+ crf :got-it)
+  (uuo_interr arch::error-object-not-base-char src)
+  :got-it)
+
+
+(define-ppc32-vinsn unbox-bit (((dest :u32))
+                               ((src :lisp))
+                               ((crf :crf)))
+  (cmplwi crf src (ash 1 ppc32::fixnumshift))
+  (srawi dest src ppc32::fixnumshift)
+  (ble+ crf :got-it)
+  (uuo_interr arch::error-object-not-bit src)
+  :got-it)
+
+(define-ppc32-vinsn unbox-bit-bit0 (((dest :u32))
+                                    ((src :lisp))
+                                    ((crf :crf)))
+  (cmplwi crf src (ash 1 ppc32::fixnumshift))
+  (rlwinm dest src (- 32 (1+ ppc32::fixnumshift)) 0 0)
+  (ble+ crf :got-it)
+  (uuo_interr arch::error-object-not-bit src)
+  :got-it)
+
+(define-ppc32-vinsn fixnum->fpr (((dest :double-float))
+                                 ((src :lisp))
+                                 ((imm :s32)))
+  (stfd ppc::fp-s32conv -8 ppc::sp)
+  (srawi imm src ppc32::fixnumshift)
+  (xoris imm imm #x8000)
+  (stw imm -4 ppc::sp)
+  (lfd dest -8 ppc::sp)
+  (fsub dest dest ppc::fp-s32conv))
+
+
+(define-ppc32-vinsn shift-right-variable-word (((dest :u32))
+                                               ((src :u32)
+                                                (sh :u32)))
+  (srw dest src sh))
+
+(define-ppc32-vinsn u32logandc2 (((dest :u32))
+                                 ((x :u32)
+                                  (y :u32)))
+  (andc dest x y))
+
+(define-ppc32-vinsn u32logior (((dest :u32))
+                               ((x :u32)
+                                (y :u32)))
+  (or dest x y))
+
+(define-ppc32-vinsn rotate-left-variable-word (((dest :u32))
+                                               ((src :u32)
+                                                (rot :u32)))
+  (rlwnm dest src rot 0 31))
+
+(define-ppc32-vinsn complement-shift-count (((dest :u32))
+                                            ((src :u32)))
+  (subfic dest src 32))
+
+(define-ppc32-vinsn extract-lowbyte (((dest :u32))
+                                     ((src :lisp)))
+  (clrlwi dest src (- ppc32::nbits-in-word ppc32::num-subtag-bits)))
+
+;;; Set DEST to the difference between the low byte of SRC and BYTEVAL.
+(define-ppc32-vinsn extract-compare-lowbyte (((dest :u32))
+                                             ((src :lisp)
+                                              (byteval :u8const)))
+  (clrlwi dest src (- ppc32::nbits-in-word ppc32::num-subtag-bits))
+  (subi dest dest byteval))
+
+
+;;; Set the "EQ" bit in condition-register field CRF if object is
+;;; a fixnum.  Leave the object's tag in TAG.
+;;; This is a little easier if CRF is CR0.
+(define-ppc32-vinsn eq-if-fixnum (((crf :crf)
+                                   (tag :u8))
+                                  ((object :lisp))
+                                  ())
+  ((:eq crf 0)
+   (clrlwi. tag object (- ppc32::nbits-in-word ppc32::nlisptagbits)))
+  ((:not (:eq crf 0))
+   (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+   (cmpwi crf tag ppc32::tag-fixnum)))
+
+
+
+(define-ppc32-vinsn trap-unless-fixnum (()
+					((object :lisp))
+					((tag :u8)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (twnei tag ppc32::tag-fixnum))
+
+(define-ppc32-vinsn trap-unless-list (()
+                                      ((object :lisp))
+                                      ((tag :u8)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (twnei tag ppc32::tag-list))
+
+(define-ppc32-vinsn trap-unless-single-float (()
+                                              ((object :lisp))
+                                              ((tag :u8)
+                                               (crf :crf)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc32::misc-subtag-offset object)
+  :do-trap
+  (twnei tag ppc32::subtag-single-float))
+
+(define-ppc32-vinsn trap-unless-double-float (()
+                                              ((object :lisp))
+                                              ((tag :u8)
+                                               (crf :crf)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc32::misc-subtag-offset object)
+  :do-trap
+  (twnei tag ppc32::subtag-double-float))
+
+
+(define-ppc32-vinsn trap-unless-array-header (()
+                                              ((object :lisp))
+                                              ((tag :u8)
+                                               (crf :crf)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc32::misc-subtag-offset object)
+  :do-trap
+  (twnei tag ppc32::subtag-arrayH))
+
+(define-ppc32-vinsn trap-unless-macptr (()
+                                        ((object :lisp))
+                                        ((tag :u8)
+                                         (crf :crf)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc32::misc-subtag-offset object)
+  :do-trap
+  (twnei tag ppc32::subtag-macptr))
+
+
+
+(define-ppc32-vinsn trap-unless-uvector (()
+					 ((object :lisp))
+                                         ((tag :u8)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (twnei tag ppc32::tag-misc))
+
+(define-ppc32-vinsn trap-unless-fulltag= (()
+                                          ((object :lisp)
+                                           (tagval :u16const))
+                                          ((tag :u8)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::ntagbits))
+  (twnei tag tagval))
+
+(define-ppc32-vinsn trap-unless-lowbyte= (()
+                                          ((object :lisp)
+                                           (tagval :u16const))
+                                          ((tag :u8)))
+  (clrlwi tag object (- ppc32::nbits-in-word 8))
+  (twnei tag tagval))
+
+(define-ppc32-vinsn trap-unless-character (()
+                                           ((object :lisp))
+                                           ((tag :u8)))
+  (clrlwi tag object (- ppc32::nbits-in-word 8))
+  (twnei tag ppc32::subtag-character))
+
+(define-ppc32-vinsn trap-unless-cons (()
+                                      ((object :lisp))
+                                      ((tag :u8)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::ntagbits))
+  (twnei tag ppc32::fulltag-cons))
+
+(define-ppc32-vinsn trap-unless-typecode= (()
+                                           ((object :lisp)
+                                            (tagval :u16const))
+                                           ((tag :u8)
+                                            (crf :crf)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc32::misc-subtag-offset object)
+  :do-trap
+  (twnei tag tagval))
+  
+(define-ppc32-vinsn subtract-constant (((dest :imm))
+                                       ((src :imm)
+                                        (const :s16const)))
+  (subi dest src const))
+
+(define-ppc32-vinsn trap-unless-numeric-type (()
+                                              ((object :lisp)
+                                               (maxtype :u16const))
+                                              ((crf0 (:crf 0))
+                                               (tag :u8)
+                                               (crfX :crf)))
+  (clrlwi. tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi tag ppc32::tag-misc)
+  (beq+ crf0 :fixnum)
+  (bne crfX :scale-tag)
+  (lbz tag ppc32::misc-subtag-offset object)
+  :scale-tag
+  (subi tag tag ppc32::min-numeric-subtag)
+  (twlgti tag (:apply - maxtype ppc32::min-numeric-subtag))
+  :fixnum)
+
+
+;; Bit-extraction & boolean operations
+
+(eval-when (:compile-toplevel :execute)
+  (assert (= ppc32::t-offset #b10001))) ; PPC-bits 31 and 27 set
+
+;; For some mind-numbing reason, IBM decided to call the most significant
+;; bit in a 32-bit word "bit 0" and the least significant bit "bit 31"
+;; (this despite the fact that it's essentially a big-endian architecture
+;; (it was exclusively big-endian when this decision was made.))
+;; We'll probably be least confused if we consistently use this backwards
+;; bit ordering (letting things that have a "sane" bit-number worry about
+;; it at compile-time or run-time (subtracting the "sane" bit number from
+;; 31.))
+
+(define-ppc32-vinsn extract-variable-bit (((dest :u8))
+                                          ((src :u32)
+                                           (bitnum :u8))
+                                          ())
+  (rotlw dest src bitnum)
+  (extrwi dest dest 1 0))
+
+
+(define-ppc32-vinsn extract-variable-bit-fixnum (((dest :imm))
+                                                 ((src :u32)
+                                                  (bitnum :u8))
+                                                 ((temp :u32)))
+  (rotlw temp src bitnum)
+  (rlwinm dest
+          temp 
+          (1+ ppc32::fixnumshift) 
+          (- ppc32::least-significant-bit ppc32::fixnumshift)
+          (- ppc32::least-significant-bit ppc32::fixnumshift)))
+
+
+;; Sometimes we try to extract a single bit from some source register
+;; into a destination bit (typically 31, sometimes fixnum bit 0 = 29).
+;; If we copy bit 0 (whoops, I mean "bit 31") to bit 4 (aka 27) in a
+;; given register, we get a value that's either 17 (the arithmetic difference
+;; between T and NIL) or 0.
+
+(define-ppc32-vinsn lowbit->truth (((dest :lisp)
+                                    (bits :u32))
+                                   ((bits :u32))
+                                   ())
+  (rlwimi bits bits (- ppc32::least-significant-bit 27) 27 27) ; bits = 0000...X000X
+  (addi dest bits (:apply target-nil-value)))
+
+(define-ppc32-vinsn invert-lowbit (((bits :u32))
+                                   ((bits :u32))
+                                   ())
+  (xori bits bits 1))
+
+                           
+
+;; Some of the obscure-looking instruction sequences - which map some relation
+;; to PPC bit 31 of some register - were found by the GNU SuperOptimizer.
+;; Some of them use extended-precision instructions (which may cause interlocks
+;; on some superscalar PPCs, if I remember correctly.)  In general, sequences
+;; that GSO found that -don't- do extended precision are longer and/or use
+;; more temporaries.
+;; On the 604, the penalty for using an instruction that uses the CA bit is
+;; "at least" one cycle: it can't complete execution until all "older" instructions
+;; have.  That's not horrible, especially given that the alternative is usually
+;; to use more instructions (and, more importantly, more temporaries) to avoid
+;; using extended-precision.
+
+
+(define-ppc32-vinsn eq0->bit31 (((bits :u32))
+                                ((src (t (:ne bits)))))
+  (cntlzw bits src)
+  (srwi bits bits 5))                   ; bits = 0000...000X
+
+(define-ppc32-vinsn ne0->bit31 (((bits :u32))
+                                ((src (t (:ne bits)))))
+  (cntlzw bits src)
+  (slw bits src bits)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn lt0->bit31 (((bits :u32))
+                                ((src (t (:ne bits)))))
+  (srwi bits src 31))                   ; bits = 0000...000X
+
+
+(define-ppc32-vinsn ge0->bit31 (((bits :u32))
+                                ((src (t (:ne bits)))))
+  (srwi bits src 31)       
+  (xori bits bits 1))                   ; bits = 0000...000X
+
+
+(define-ppc32-vinsn le0->bit31 (((bits :u32))
+                                ((src (t (:ne bits)))))
+  (neg bits src)
+  (orc bits bits src)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn gt0->bit31 (((bits :u32))
+                                ((src (t (:ne bits)))))
+  (subi bits src 1)       
+  (nor bits bits src)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn ne->bit31 (((bits :u32))
+                               ((x t)
+                                (y t))
+                               ((temp :u32)))
+  (subf temp x y)
+  (cntlzw bits temp)
+  (slw bits temp bits)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn fulltag->bit31 (((bits :u32))
+                                    ((lispobj :lisp)
+                                     (tagval :u8const))
+                                    ())
+  (clrlwi bits lispobj (- ppc32::nbits-in-word ppc32::ntagbits))
+  (subi bits bits tagval)
+  (cntlzw bits bits)
+  (srwi bits bits 5))
+
+
+(define-ppc32-vinsn eq->bit31 (((bits :u32))
+                               ((x t)
+                                (y t)))
+  (subf bits x y)
+  (cntlzw bits bits)
+  (srwi bits bits 5))                   ; bits = 0000...000X
+
+(define-ppc32-vinsn eqnil->bit31 (((bits :u32))
+                                  ((x t)))
+  (subi bits x (:apply target-nil-value))
+  (cntlzw bits bits)
+  (srwi bits bits 5))
+
+(define-ppc32-vinsn ne->bit31 (((bits :u32))
+                               ((x t)
+                                (y t)))
+  (subf bits x y)
+  (cntlzw bits bits)
+  (srwi bits bits 5)
+  (xori bits bits 1))
+
+(define-ppc32-vinsn nenil->bit31 (((bits :u32))
+                                  ((x t)))
+  (subi bits x (:apply target-nil-value))
+  (cntlzw bits bits)
+  (srwi bits bits 5)
+  (xori bits bits 1))
+
+(define-ppc32-vinsn lt->bit31 (((bits :u32))
+                               ((x (t (:ne bits)))
+                                (y (t (:ne bits)))))
+
+  (xor bits x y)
+  (srawi bits bits 31)
+  (or bits bits x)
+  (subf bits y bits)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn ltu->bit31 (((bits :u32))
+                                ((x :u32)
+                                 (y :u32)))
+  (subfc bits y x)
+  (subfe bits bits bits)
+  (neg bits bits))
+
+(define-ppc32-vinsn le->bit31 (((bits :u32))
+                               ((x (t (:ne bits)))
+                                (y (t (:ne bits)))))
+
+  (xor bits x y)
+  (srawi bits bits 31)
+  (nor bits bits y)
+  (add bits bits x)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn leu->bit31  (((bits :u32))
+                                 ((x :u32)
+                                  (y :u32)))
+  (subfc bits x y)
+  (addze bits ppc::rzero))
+
+(define-ppc32-vinsn gt->bit31 (((bits :u32))
+                               ((x (t (:ne bits)))
+                                (y (t (:ne bits)))))
+
+  (eqv bits x y)
+  (srawi bits bits 31)
+  (and bits bits x)
+  (subf bits bits y)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn gtu->bit31 (((bits :u32))
+                                ((x :u32)
+                                 (y :u32)))
+  (subfc bits x y)
+  (subfe bits bits bits)
+  (neg bits bits))
+
+(define-ppc32-vinsn ge->bit31 (((bits :u32))
+                               ((x (t (:ne bits)))
+                                (y (t (:ne bits)))))
+  (eqv bits x y)
+  (srawi bits bits 31)
+  (andc bits bits x)
+  (add bits bits y)
+  (srwi bits bits 31))                  ; bits = 0000...000X
+
+(define-ppc32-vinsn geu->bit31 (((bits :u32))
+                                ((x :u32)
+                                 (y :u32)))
+  (subfc bits y x)
+  (addze bits ppc::rzero))
+
+
+;;; there are big-time latencies associated with MFCR on more heavily
+;;; pipelined processors; that implies that we should avoid this like
+;;; the plague.
+;;; GSO can't find anything much quicker for LT or GT, even though
+;;; MFCR takes three cycles and waits for previous instructions to complete.
+;;; Of course, using a CR field costs us something as well.
+(define-ppc32-vinsn crbit->bit31 (((bits :u32))
+                                  ((crf :crf)
+                                   (bitnum :crbit))
+                                  ())
+  (mfcr bits)                           ; Suffer.
+  (rlwinm bits bits (:apply + 1  bitnum (:apply ash crf 2)) 31 31)) ; bits = 0000...000X
+
+
+(define-ppc32-vinsn compare (((crf :crf))
+                             ((arg0 t)
+                              (arg1 t))
+                             ())
+  (cmpw crf arg0 arg1))
+
+(define-ppc32-vinsn compare-to-nil (((crf :crf))
+                                    ((arg0 t)))
+  (cmpwi crf arg0 (:apply target-nil-value)))
+
+(define-ppc32-vinsn compare-logical (((crf :crf))
+                                     ((arg0 t)
+                                      (arg1 t))
+                                     ())
+  (cmplw crf arg0 arg1))
+
+(define-ppc32-vinsn double-float-compare (((crf :crf))
+                                          ((arg0 :double-float)
+                                           (arg1 :double-float))
+                                          ())
+  (fcmpo crf arg0 arg1))
+              
+
+(define-ppc32-vinsn double-float+-2 (((result :double-float))
+                                     ((x :double-float)
+                                      (y :double-float))
+                                     ((crf (:crf 4))))
+  (fadd result x y))
+
+(define-ppc32-vinsn double-float--2 (((result :double-float))
+                                     ((x :double-float)
+                                      (y :double-float))
+                                     ((crf (:crf 4))))
+  (fsub result x y))
+
+(define-ppc32-vinsn double-float*-2 (((result :double-float))
+                                     ((x :double-float)
+                                      (y :double-float))
+                                     ((crf (:crf 4))))
+  (fmul result x y))
+
+(define-ppc32-vinsn double-float/-2 (((result :double-float))
+                                     ((x :double-float)
+                                      (y :double-float))
+                                     ((crf (:crf 4))))
+  (fdiv result x y))
+
+(define-ppc32-vinsn single-float+-2 (((result :single-float))
+                                     ((x :single-float)
+                                      (y :single-float))
+                                     ((crf (:crf 4))))
+  (fadds result x y))
+
+(define-ppc32-vinsn single-float--2 (((result :single-float))
+                                     ((x :single-float)
+                                      (y :single-float))
+                                     ((crf (:crf 4))))
+  (fsubs result x y))
+
+(define-ppc32-vinsn single-float*-2 (((result :single-float))
+                                     ((x :single-float)
+                                      (y :single-float))
+                                     ((crf (:crf 4))))
+  (fmuls result x y))
+
+(define-ppc32-vinsn single-float/-2 (((result :single-float))
+                                     ((x :single-float)
+                                      (y :single-float))
+                                     ((crf (:crf 4))))
+  (fdivs result x y))
+
+
+
+
+
+(define-ppc32-vinsn compare-unsigned (((crf :crf))
+                                      ((arg0 :imm)
+                                       (arg1 :imm))
+                                      ())
+  (cmplw crf arg0 arg1))
+
+(define-ppc32-vinsn compare-signed-s16const (((crf :crf))
+                                             ((arg0 :imm)
+                                              (imm :s16const))
+                                             ())
+  (cmpwi crf arg0 imm))
+
+(define-ppc32-vinsn compare-unsigned-u16const (((crf :crf))
+                                               ((arg0 :u32)
+                                                (imm :u16const))
+                                               ())
+  (cmplwi crf arg0 imm))
+
+
+
+;; Extract a constant bit (0-31) from src; make it be bit 31 of dest.
+;; Bitnum is treated mod 32.
+(define-ppc32-vinsn extract-constant-ppc-bit (((dest :u32))
+                                              ((src :imm)
+                                               (bitnum :u16const))
+                                              ())
+  (rlwinm dest src (:apply + 1 bitnum) 31 31))
+
+
+(define-ppc32-vinsn set-constant-ppc-bit-to-variable-value (((dest :u32))
+                                                            ((src :u32)
+                                                             (bitval :u32) ; 0 or 1
+                                                             (bitnum :u8const)))
+  (rlwimi dest bitval (:apply - 32 bitnum) bitnum bitnum))
+
+(define-ppc32-vinsn set-constant-ppc-bit-to-1 (((dest :u32))
+                                               ((src :u32)
+                                                (bitnum :u8const)))
+  ((:pred < bitnum 16)
+   (oris dest src (:apply ash #x8000 (:apply - bitnum))))
+  ((:pred >= bitnum 16)
+   (ori dest src (:apply ash #x8000 (:apply - (:apply - bitnum 16))))))
+
+(define-ppc32-vinsn set-constant-ppc-bit-to-0 (((dest :u32))
+                                               ((src :u32)
+                                                (bitnum :u8const)))
+  (rlwinm dest src 0 (:apply logand #x1f (:apply 1+ bitnum)) (:apply logand #x1f (:apply 1- bitnum))))
+
+  
+(define-ppc32-vinsn insert-bit-0 (((dest :u32))
+                                  ((src :u32)
+                                   (val :u32)))
+  (rlwimi dest val 0 0 0))
+  
+;;; The bit number is boxed and wants to think of the least-significant bit as 0.
+;;; Imagine that.
+;;; To turn the boxed, lsb-0 bitnumber into an unboxed, msb-0 rotate count,
+;;; we (conceptually) unbox it, add ppc32::fixnumshift to it, subtract it from
+;;; 31, and add one.  This can also be done as "unbox and subtract from 28",
+;;; I think ...
+;;; Actually, it'd be "unbox, then subtract from 30".
+(define-ppc32-vinsn extract-variable-non-insane-bit (((dest :u32))
+                                                     ((src :imm)
+                                                      (bit :imm))
+                                                     ((temp :u32)))
+  (srwi temp bit ppc32::fixnumshift)
+  (subfic temp temp (- 32 ppc32::fixnumshift))
+  (rlwnm dest src temp 31 31))
+                                               
+;;; Operations on lists and cons cells
+
+(define-ppc32-vinsn %cdr (((dest :lisp))
+                          ((src :lisp)))
+  (lwz dest ppc32::cons.cdr src))
+
+(define-ppc32-vinsn %car (((dest :lisp))
+                          ((src :lisp)))
+  (lwz dest ppc32::cons.car src))
+
+(define-ppc32-vinsn %set-car (()
+                              ((cell :lisp)
+                               (new :lisp)))
+  (stw new ppc32::cons.car cell))
+
+(define-ppc32-vinsn %set-cdr (()
+                              ((cell :lisp)
+                               (new :lisp)))
+  (stw new ppc32::cons.cdr cell))
+
+(define-ppc32-vinsn load-adl (()
+                              ((n :u32const)))
+  (lis ppc::nargs (:apply ldb (byte 16 16) n))
+  (ori ppc::nargs ppc::nargs (:apply ldb (byte 16 0) n)))
+                            
+(define-ppc32-vinsn set-nargs (()
+                               ((n :s16const)))
+  (li ppc::nargs (:apply ash n ppc32::word-shift)))
+
+(define-ppc32-vinsn scale-nargs (()
+                                 ((nfixed :s16const)))
+  ((:pred > nfixed 0)
+   (la ppc::nargs (:apply - (:apply ash nfixed ppc32::word-shift)) ppc::nargs)))
+                           
+
+
+(define-ppc32-vinsn (vpush-register :push :node :vsp)
+    (()
+     ((reg :lisp)))
+  (stwu reg -4 ppc::vsp))
+
+(define-ppc32-vinsn (vpush-register-arg :push :node :vsp :outgoing-argument)
+    (()
+     ((reg :lisp)))
+  (stwu reg -4 ppc::vsp))
+
+(define-ppc32-vinsn (vpop-register :pop :node :vsp)
+    (((dest :lisp))
+     ())
+  (lwz dest 0 ppc::vsp)
+  (la ppc::vsp 4 ppc::vsp))
+
+
+(define-ppc32-vinsn copy-node-gpr (((dest :lisp))
+                                   ((src :lisp)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (mr dest src)))
+
+(define-ppc32-vinsn copy-gpr (((dest t))
+			      ((src t)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (mr dest src)))
+
+
+(define-ppc32-vinsn copy-fpr (((dest :double-float))
+			      ((src :double-float)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (fmr dest src)))
+
+(define-ppc32-vinsn vcell-ref (((dest :lisp))
+			       ((vcell :lisp)))
+  (lwz dest ppc32::misc-data-offset vcell))
+
+
+(define-ppc32-vinsn make-vcell (((dest :lisp))
+                                ((closed (:lisp :ne dest)))
+                                ((header :u32)))
+  (li header ppc32::value-cell-header)
+  (la ppc::allocptr (- ppc32::fulltag-misc ppc32::value-cell.size) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw closed ppc32::value-cell.value dest))
+
+(define-ppc32-vinsn make-tsp-vcell (((dest :lisp))
+                                    ((closed :lisp))
+                                    ((header :u32)))
+  (li header ppc32::value-cell-header)
+  (stwu ppc::tsp -16 ppc::tsp)
+  (stw ppc::tsp 4 ppc::tsp)
+  (stfd ppc::fp-zero 8 ppc::tsp)
+  (stw ppc::rzero 4 ppc::tsp)
+  (stw header (+ 8 ppc32::fulltag-misc ppc32::value-cell.header) ppc::tsp)
+  (stw closed (+ 8 ppc32::fulltag-misc ppc32::value-cell.value) ppc::tsp)
+  (la dest (+ 8 ppc32::fulltag-misc) ppc::tsp))
+
+(define-ppc32-vinsn make-tsp-cons (((dest :lisp))
+                                   ((car :lisp) (cdr :lisp))
+                                   ())
+  (stwu ppc::tsp -16 ppc::tsp)
+  (stw ppc::tsp 4 ppc::tsp)
+  (stfd ppc::fp-zero 8 ppc::tsp)
+  (stw ppc::rzero 4 ppc::tsp)
+  (stw car (+ 8 ppc32::fulltag-cons ppc32::cons.car) ppc::tsp)
+  (stw cdr (+ 8 ppc32::fulltag-cons ppc32::cons.cdr) ppc::tsp)
+  (la dest (+ 8 ppc32::fulltag-cons) ppc::tsp))
+
+
+(define-ppc32-vinsn %closure-code% (((dest :lisp))
+                                    ())
+  (lwz dest (:apply + ppc32::symbol.vcell (ppc32::nrs-offset %closure-code%) (:apply target-nil-value)) 0))
+
+
+(define-ppc32-vinsn single-float-bits (((dest :u32))
+                                       ((src :lisp)))
+  (lwz dest ppc32::single-float.value src))
+
+(define-ppc32-vinsn (call-subprim :call :subprim-call) (()
+                                                        ((spno :s32const)))
+  (bla spno))
+
+(define-ppc32-vinsn (jump-subprim :jumpLR) (()
+                                            ((spno :s32const)))
+  (ba spno))
+
+;;; Same as "call-subprim", but gives us a place to 
+;;; track args, results, etc.
+(define-ppc32-vinsn (call-subprim-0 :call :subprim-call) (((dest t))
+                                                          ((spno :s32const)))
+  (bla spno))
+
+(define-ppc32-vinsn (call-subprim-1 :call :subprim-call) (((dest t))
+                                                          ((spno :s32const)
+                                                           (z t)))
+  (bla spno))
+  
+(define-ppc32-vinsn (call-subprim-2 :call :subprim-call) (((dest t))
+                                                          ((spno :s32const)
+                                                           (y t)
+                                                           (z t)))
+  (bla spno))
+
+(define-ppc32-vinsn (call-subprim-3 :call :subprim-call) (((dest t))
+                                                          ((spno :s32const)
+                                                           (x t)
+                                                           (y t)
+                                                           (z t)))
+  (bla spno))
+
+(define-ppc32-vinsn event-poll (()
+				()
+                                ((crf :crf)))
+  (lwz ppc::nargs ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (lwz ppc::nargs ppc32::interrupt-level-binding-index ppc::nargs)
+  (cmpwi crf ppc::nargs 0)
+  (blt crf :done)
+  (bgt crf :trap)
+  (lwz ppc::nargs ppc32::tcr.interrupt-pending ppc32::rcontext)
+  :trap
+  (twgti ppc::nargs 0)
+  :done)
+
+(define-ppc32-vinsn ref-interrupt-level (((dest :imm))
+                                         ()
+                                         ((temp :u32)))
+  (lwz temp ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (lwz dest ppc32::INTERRUPT-LEVEL-BINDING-INDEX temp))
+
+                         
+;;; Unconditional (pc-relative) branch
+(define-ppc32-vinsn (jump :jump) (()
+                                  ((label :label)))
+  (b label))
+
+(define-ppc32-vinsn (call-label :call) (()
+                                        ((label :label)))
+  (bl label))
+
+;;; just like JUMP, only (implicitly) asserts that the following 
+;;; code is somehow reachable.
+(define-ppc32-vinsn (non-barrier-jump :xref) (()
+                                              ((label :label)))
+  (b label))
+
+
+(define-ppc32-vinsn (cbranch-true :branch) (()
+                                            ((label :label)
+                                             (crf :crf)
+                                             (crbit :u8const)))
+  (bt (:apply + crf crbit) label))
+
+(define-ppc32-vinsn (cbranch-false :branch) (()
+                                             ((label :label)
+                                              (crf :crf)
+                                              (crbit :u8const)))
+  (bf (:apply + crf crbit) label))
+
+(define-ppc32-vinsn check-trap-error (()
+                                      ())
+  (beq+ 0 :no-error)
+  (uuo_interr arch::error-reg-regnum ppc::arg_z)
+  :no-error)
+
+
+(define-ppc32-vinsn lisp-word-ref (((dest t))
+                                   ((base t)
+                                    (offset t)))
+  (lwzx dest base offset))
+
+(define-ppc32-vinsn lisp-word-ref-c (((dest t))
+                                     ((base t)
+                                      (offset :s16const)))
+  (lwz dest offset base))
+
+  
+
+;; Load an unsigned, 32-bit constant into a destination register.
+(define-ppc32-vinsn (lri :constant-ref) (((dest :imm))
+                                         ((intval :u32const))
+                                         ())
+  ((:or (:pred = (:apply ash intval -15) #x1ffff)
+        (:pred = (:apply ash intval -15) #x0))
+   (li dest (:apply %word-to-int (:apply logand #xffff intval))))
+  ((:not                                ; that's :else to you, bub.
+    (:or (:pred = (:apply ash intval -15) #x1ffff)
+         (:pred = (:apply ash intval -15) #x0)))
+   ((:pred = (:apply ash intval -15) 1)
+    (ori dest ppc::rzero (:apply logand intval #xffff)))
+   ((:not (:pred = (:apply ash intval -15) 1))
+    (lis dest (:apply ash intval -16))
+    ((:not (:pred = 0 (:apply logand intval #xffff)))
+     (ori dest dest (:apply logand intval #xffff))))))
+
+
+(define-ppc32-vinsn (discard-temp-frame :tsp :pop :discard) (()
+                                                             ())
+  (lwz ppc::tsp 0 ppc::tsp))
+
+
+;;; Somewhere, deep inside the "OS_X_PPC_RuntimeConventions.pdf"
+;;; document, they bother to document the fact that SP should
+;;; maintain 16-byte alignment on OSX.  (The example prologue
+;;; code in that document incorrectly assumes 8-byte alignment.
+;;; Or something.  It's wrong in a number of other ways.)
+;;; The caller always has to reserve a 24-byte linkage area
+;;; (large chunks of which are unused).
+(define-ppc32-vinsn alloc-c-frame (()
+                                   ((n-c-args :u16const)))
+  ;; Always reserve space for at least 8 args and space for a lisp
+  ;; frame (for the kernel) underneath it.
+  ;; Zero the c-frame's savelr field, not that the GC cares ..
+  ((:pred <= n-c-args 10)
+   (stwu ppc::sp (- (+ 8 ppc32::c-frame.size ppc32::lisp-frame.size)) ppc::sp))
+  ((:pred > n-c-args 10)
+   ;; A normal C frame has room for 10 args (when padded out to
+   ;; 16-byte alignment. Add enough double words to accomodate the
+   ;; remaining args, in multiples of 4.
+   (stwu ppc::sp (:apply - (:apply +
+                                   8
+                                   (+ ppc32::c-frame.size ppc32::lisp-frame.size)
+                                   (:apply ash
+                                           (:apply logand
+                                                   (lognot 3)
+                                                   (:apply
+                                                    +
+                                                    3
+                                                    (:apply - n-c-args 10)))
+                                           2)))
+         ppc::sp))
+  (stw ppc::rzero ppc32::c-frame.savelr ppc::sp))
+
+(define-ppc32-vinsn alloc-variable-c-frame (()
+                                            ((n-c-args :lisp))
+                                            ((crf :crf)
+                                             (size :s32)))
+  (cmpwi crf n-c-args (ash 10 ppc32::fixnumshift))
+  (subi size n-c-args (ash 10 ppc32::fixnumshift))
+  (bgt :variable)
+  ;; Always reserve space for at least 8 args and space for a lisp
+  ;; frame (for the kernel) underneath it.
+  (stwu ppc::sp (- (+ 8 ppc32::c-frame.size ppc32::lisp-frame.size)) ppc::sp)
+  (b :done)
+  :variable
+  (addi size size (+  (+ 8 ppc32::c-frame.size ppc32::lisp-frame.size) (ash 3 ppc32::fixnumshift)))
+  (clrrwi size size 3)
+  (neg size size)
+  (stwux ppc::sp ppc::sp size)
+  :done
+  (stw ppc::rzero ppc32::c-frame.savelr ppc::sp))
+
+(define-ppc32-vinsn alloc-eabi-c-frame (()
+                                        ((n-c-args :u16const)))
+  ;; Always reserve space for at least 8 args and space for a lisp
+  ;; frame (for the kernel) underneath it.  Store NIL inthe c-frame's
+  ;; savelr field, so that the kernel doesn't mistake this for a lisp
+  ;; frame.
+  ((:pred <= n-c-args 8)
+   (stwu ppc::sp (- (+ ppc32::eabi-c-frame.size ppc32::lisp-frame.size)) ppc::sp))
+  ((:pred > n-c-args 8)
+   ;; A normal C frame has room for 8 args. Add enough double words to
+   ;; accomodate the remaining args
+   (stwu ppc::sp (:apply - (:apply + 
+                                   (+ ppc32::eabi-c-frame.size ppc32::lisp-frame.size)
+                                   (:apply ash
+                                           (:apply logand
+                                                   (lognot 1)
+                                                   (:apply
+                                                    1+
+                                                    (:apply - n-c-args 8)))
+                                           2)))
+         ppc::sp))
+  (stw ppc::sp ppc32::eabi-c-frame.savelr ppc::sp))
+
+(define-ppc32-vinsn alloc-variable-eabi-c-frame (()
+                                                 ((n-c-args :lisp))
+                                                 ((crf :crf)
+                                                  (size :s32)))
+  (cmpwi crf n-c-args (ash 8 ppc32::fixnumshift))
+  (subi size n-c-args (ash 8 ppc32::fixnumshift))
+  (bgt :variable)
+  ;; Always reserve space for at least 8 args and space for a lisp
+  ;; frame (for the kernel) underneath it.
+  (stwu ppc::sp (- (+ ppc32::eabi-c-frame.size ppc32::lisp-frame.size)) ppc::sp)
+  (b :done)
+  :variable
+  (addi size size (+  (+ ppc32::eabi-c-frame.size ppc32::lisp-frame.size) (ash 1 ppc32::fixnumshift)))
+  (clrrwi size size 2)
+  (neg size size)
+  (stwux ppc::sp ppc::sp size)
+  :done
+  (stw ppc::rzero ppc32::c-frame.savelr ppc::sp))
+
+
+
+;;; We should rarely have to do this.  It's easier to just generate code
+;;; to do the memory reference than it would be to keep track of the size
+;;; of each frame.
+(define-ppc32-vinsn (discard-c-frame :csp :pop :discard) (()
+                                                          ())
+  (lwz ppc::sp 0 ppc::sp))
+
+
+
+
+(define-ppc32-vinsn set-c-arg (()
+                               ((argval :u32)
+                                (argnum :u16const)))
+  (stw argval (:apply + ppc32::c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn set-single-c-arg (()
+                                      ((argval :single-float)
+                                       (argnum :u16const)))
+  (stfs argval (:apply + ppc32::c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn set-double-c-arg (()
+                                      ((argval :double-float)
+                                       (argnum :u16const)))
+  (stfd argval (:apply + ppc32::c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn reload-single-c-arg (((argval :single-float))
+                                         ((argnum :u16const)))
+  (lfs argval (:apply + ppc32::c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn reload-double-c-arg (((argval :double-float))
+                                         ((argnum :u16const)))
+  (lfd argval (:apply + ppc32::c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn set-eabi-c-arg (()
+                                    ((argval :u32)
+                                     (argnum :u16const)))
+  (stw argval (:apply + ppc32::eabi-c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn set-single-eabi-c-arg (()
+                                           ((argval :single-float)
+                                            (argnum :u16const)))
+  (stfs argval (:apply + ppc32::eabi-c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn set-double-eabi-c-arg (()
+                                           ((argval :double-float)
+                                            (argnum :u16const)))
+  (stfd argval (:apply + ppc32::eabi-c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn reload-single-eabi-c-arg (((argval :single-float))
+                                              ((argnum :u16const)))
+  (lfs argval (:apply + ppc32::eabi-c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn reload-double-eabi-c-arg (((argval :double-float))
+                                              ((argnum :u16const)))
+  (lfd argval (:apply + ppc32::eabi-c-frame.param0 (:apply ash argnum ppc32::word-shift)) ppc::sp))
+
+(define-ppc32-vinsn (load-nil :constant-ref) (((dest t))
+                                              ())
+  (li dest (:apply target-nil-value)))
+
+(define-ppc32-vinsn (load-t :constant-ref) (((dest t))
+                                            ())
+  (li dest (:apply + ppc32::t-offset (:apply target-nil-value))))
+
+(define-ppc32-vinsn set-eq-bit (((dest :crf))
+                                ())
+  (creqv (:apply + ppc::ppc-eq-bit dest)
+	 (:apply + ppc::ppc-eq-bit dest)
+	 (:apply + ppc::ppc-eq-bit dest)))
+
+(define-ppc32-vinsn (ref-constant :constant-ref) (((dest :lisp))
+                                                  ((src :s16const)))
+  (lwz dest (:apply + ppc32::misc-data-offset (:apply ash (:apply 1+ src) 2)) ppc::fn))
+
+(define-ppc32-vinsn ref-indexed-constant (((dest :lisp))
+                                          ((idxreg :s32)))
+  (lwzx dest ppc::fn idxreg))
+
+
+(define-ppc32-vinsn cons (((dest :lisp))
+                          ((newcar :lisp)
+                           (newcdr :lisp)))
+  (la ppc::allocptr (- ppc32::fulltag-cons ppc32::cons.size) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw newcdr ppc32::cons.cdr ppc::allocptr)
+  (stw newcar ppc32::cons.car ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits))
+
+
+
+;; subtag had better be a PPC-NODE-SUBTAG of some sort!
+(define-ppc32-vinsn %ppc-gvector (((dest :lisp))
+                                  ((Rheader :u32) 
+                                   (nbytes :u32const))
+                                  ((immtemp0 :u32)
+                                   (nodetemp :lisp)
+                                   (crf :crf)))
+  (la ppc::allocptr (:apply - ppc32::fulltag-misc
+                            (:apply logand (lognot 7)
+                                    (:apply + (+ 7 4) nbytes)))
+      ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw Rheader ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  ((:not (:pred = nbytes 0))
+   (li immtemp0 (:apply + ppc32::misc-data-offset nbytes))
+   :loop
+   (subi immtemp0 immtemp0 4)
+   (cmpwi crf immtemp0 ppc32::misc-data-offset)
+   (lwz nodetemp 0 ppc::vsp)
+   (la ppc::vsp 4 ppc::vsp)   
+   (stwx nodetemp dest immtemp0)
+   (bne crf :loop)))
+
+;; allocate a small (phys size <= 32K bytes) misc obj of known size/subtag
+(define-ppc32-vinsn %alloc-misc-fixed (((dest :lisp))
+                                       ((Rheader :u32)
+                                        (nbytes :u32const)))
+  (la ppc::allocptr (:apply - ppc32::fulltag-misc
+                            (:apply logand (lognot 7)
+                                    (:apply + (+ 7 4) nbytes)))
+      ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw Rheader ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits))
+
+(define-ppc32-vinsn (vstack-discard :vsp :pop :discard) (()
+                                                         ((nwords :u32const)))
+  ((:not (:pred = nwords 0))
+   (la ppc::vsp (:apply ash nwords ppc32::word-shift) ppc::vsp)))
+
+
+(define-ppc32-vinsn lcell-load (((dest :lisp))
+                                ((cell :lcell)
+                                 (top :lcell)))
+  (lwz dest (:apply - 
+                    (:apply - (:apply calc-lcell-depth top) 4)
+                    (:apply calc-lcell-offset cell)) ppc::vsp))
+
+(define-ppc32-vinsn vframe-load (((dest :lisp))
+                                 ((frame-offset :u16const)
+                                  (cur-vsp :u16const)))
+  (lwz dest (:apply - (:apply - cur-vsp 4) frame-offset) ppc::vsp))
+
+(define-ppc32-vinsn lcell-store (()
+                                 ((src :lisp)
+                                  (cell :lcell)
+                                  (top :lcell)))
+  (stw src (:apply - 
+                   (:apply - (:apply calc-lcell-depth top) 4)
+                   (:apply calc-lcell-offset cell)) ppc::vsp))
+
+(define-ppc32-vinsn vframe-store (()
+                                  ((src :lisp)
+                                   (frame-offset :u16const)
+                                   (cur-vsp :u16const)))
+  (stw src (:apply - (:apply - cur-vsp 4) frame-offset) ppc::vsp))
+
+(define-ppc32-vinsn load-vframe-address (((dest :imm))
+                                         ((offset :s16const)))
+  (la dest offset ppc::vsp))
+
+(define-ppc32-vinsn copy-lexpr-argument (()
+                                         ()
+                                         ((temp :lisp)))
+  (lwzx temp ppc::vsp ppc::nargs)
+  (stwu temp -4 ppc::vsp))
+
+;;; Boxing/unboxing of integers.
+
+;;; Treat the low 8 bits of VAL as an unsigned integer; set RESULT to the equivalent fixnum.
+(define-ppc32-vinsn u8->fixnum (((result :imm)) 
+                                ((val :u8)) 
+                                ())
+  (rlwinm result val ppc32::fixnumshift (- ppc32::nbits-in-word (+ 8 ppc32::fixnumshift)) (- ppc32::least-significant-bit ppc32::fixnumshift)))
+
+;;; Treat the low 8 bits of VAL as a signed integer; set RESULT to the equivalent fixnum.
+(define-ppc32-vinsn s8->fixnum (((result :imm)) 
+                                ((val :s8)) 
+                                ())
+  (extlwi result val 8 (- ppc32::nbits-in-word 8))
+  (srawi result result (- (- ppc32::nbits-in-word 8) ppc32::fixnumshift)))
+
+
+;;; Treat the low 16 bits of VAL as an unsigned integer; set RESULT to the equivalent fixnum.
+(define-ppc32-vinsn u16->fixnum (((result :imm)) 
+                                 ((val :u16)) 
+                                 ())
+  (rlwinm result val ppc32::fixnumshift (- ppc32::nbits-in-word (+ 16 ppc32::fixnumshift)) (- ppc32::least-significant-bit ppc32::fixnumshift)))
+
+;;; Treat the low 16 bits of VAL as a signed integer; set RESULT to the equivalent fixnum.
+(define-ppc32-vinsn s16->fixnum (((result :imm)) 
+                                 ((val :s16)) 
+                                 ())
+  (extlwi result val 16 (- ppc32::nbits-in-word 16))
+  (srawi result result (- (- ppc32::nbits-in-word 16) ppc32::fixnumshift)))
+
+(define-ppc32-vinsn fixnum->s16 (((result :s16))
+                                 ((src :imm)))
+  (srawi result src ppc32::fixnumshift))
+
+;;; A signed 32-bit untagged value can be at worst a 1-digit bignum.
+;;; There should be something very much like this that takes a stack-consed
+;;; bignum result ...
+(define-ppc32-vinsn s32->integer (((result :lisp))
+                                  ((src :s32))
+                                  ((crf (:crf 0)) ; a casualty
+                                   (temp :s32)))        
+  (addo temp src src)
+  (addo. result temp temp)
+  (bns+ :done)
+  (mtxer ppc::rzero)
+  (li temp ppc32::one-digit-bignum-header)
+  (la ppc::allocptr (- ppc32::fulltag-misc 8) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw temp ppc32::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw src ppc32::misc-data-offset result)
+  :done)
+
+
+;;; An unsigned 32-bit untagged value can be either a 1 or a 2-digit bignum.
+(define-ppc32-vinsn u32->integer (((result :lisp))
+                                  ((src :u32))
+                                  ((crf (:crf 0)) ; a casualty
+                                   (temp :s32)
+                                   (size :u32)))
+  (clrrwi. temp src (- ppc32::least-significant-bit ppc32::nfixnumtagbits))
+  (slwi result src ppc32::fixnumshift)
+  (beq+ crf :done)
+  (cmpwi src 0)
+  (li temp ppc32::one-digit-bignum-header)
+  (li size (- 8 ppc32::fulltag-misc))
+  (bgt :common)
+  (li temp ppc32::two-digit-bignum-header)
+  (li size (- 16 ppc32::fulltag-misc))
+  :common
+  (sub ppc::allocptr ppc::allocptr size)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw temp ppc32::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw src ppc32::misc-data-offset result)
+  :done)
+
+(define-ppc32-vinsn u16->u32 (((dest :u32))
+                              ((src :u16)))
+  (clrlwi dest src 16))
+
+(define-ppc32-vinsn u8->u32 (((dest :u32))
+                             ((src :u8)))
+  (clrlwi dest src 24))
+
+
+(define-ppc32-vinsn s16->s32 (((dest :s32))
+                              ((src :s16)))
+  (extsh dest src))
+
+(define-ppc32-vinsn s8->s32 (((dest :s32))
+                             ((src :s8)))
+  (extsb dest src))
+
+
+;;; ... of floats ...
+
+;;; Heap-cons a double-float to store contents of FPREG.  Hope that we don't do
+;;; this blindly.
+(define-ppc32-vinsn double->heap (((result :lisp)) ; tagged as a double-float
+                                  ((fpreg :double-float)) 
+                                  ((header-temp :u32)))
+  (li header-temp (arch::make-vheader ppc32::double-float.element-count ppc32::subtag-double-float))
+  (la ppc::allocptr (- ppc32::fulltag-misc ppc32::double-float.size) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header-temp ppc32::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stfd fpreg ppc32::double-float.value result)  )
+
+
+;;; This is about as bad as heap-consing a double-float.  (In terms of
+;;; verbosity).  Wouldn't kill us to do either/both out-of-line, but
+;;; need to make visible to compiler so unnecessary heap-consing can
+;;; be elided.
+(define-ppc32-vinsn single->node (((result :lisp)) ; tagged as a single-float
+				  ((fpreg :single-float))
+				  ((header-temp :u32)))
+  (li header-temp (arch::make-vheader ppc32::single-float.element-count ppc32::subtag-single-float))
+  (la ppc::allocptr (- ppc32::fulltag-misc ppc32::single-float.size) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header-temp ppc32::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stfs fpreg ppc32::single-float.value result))
+
+
+;;; "dest" is preallocated, presumably on a stack somewhere.
+(define-ppc32-vinsn store-double (()
+                                  ((dest :lisp)
+                                   (source :double-float))
+                                  ())
+  (stfd source ppc32::double-float.value dest))
+
+(define-ppc32-vinsn get-double (((target :double-float))
+                                ((source :lisp))
+                                ())
+  (lfd target ppc32::double-float.value source))
+
+;;; Extract a double-float value, typechecking in the process.
+;;; IWBNI we could simply call the "trap-unless-typecode=" vinsn here,
+;;; instead of replicating it ..
+
+(define-ppc32-vinsn get-double? (((target :double-float))
+                                 ((source :lisp))
+                                 ((tag :u8)
+                                  (crf :crf)))
+  (clrlwi tag source (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc32::misc-subtag-offset source)
+  :do-trap
+  (twnei tag ppc32::subtag-double-float)
+  (lfd target ppc32::double-float.value source))
+  
+
+(define-ppc32-vinsn double-to-single (((result :single-float))
+                                       ((arg :double-float)))
+  (frsp result arg))
+
+(define-ppc32-vinsn store-single (()
+                                  ((dest :lisp)
+                                   (source :single-float))
+                                  ())
+  (stfs source ppc32::single-float.value dest))
+
+(define-ppc32-vinsn get-single (((target :single-float))
+                                ((source :lisp))
+                                ())
+  (lfs target ppc32::single-float.value source))
+
+;;; ... of characters ...
+
+
+(define-ppc32-vinsn character->fixnum (((dest :lisp))
+                                       ((src :lisp))
+                                       ())
+  (rlwinm dest
+          src
+          (- ppc32::nbits-in-word (- ppc32::charcode-shift ppc32::fixnumshift))
+          (- ppc32::nbits-in-word (+ ppc32::ncharcodebits ppc32::fixnumshift)) 
+          (- ppc32::least-significant-bit ppc32::fixnumshift)))
+
+(define-ppc32-vinsn character->code (((dest :u32))
+                                     ((src :lisp)))
+  (srwi dest src ppc32::charcode-shift))
+
+
+(define-ppc32-vinsn fixnum->char (((dest :lisp))
+                                  ((src :imm))
+                                  ((temp :u32)
+                                   (crf0 (:crf 0))))
+  (srwi temp src (+ ppc32::fixnumshift 1))
+  (cmplwi temp (ash #xffff -1))
+  (srwi temp src (+ ppc32::fixnumshift 11))
+  (beq :bad)
+  (cmpwi temp 27)
+  (slwi dest src (- ppc32::charcode-shift ppc32::fixnumshift))
+  (bne+ :ok)
+  :bad
+  (li dest (:apply target-nil-value))
+  (b :done)
+  :ok
+  (addi dest dest ppc32::subtag-character)
+  :done)
+
+;;; src is known to be a code for which CODE-CHAR returns non-nil.
+(define-ppc32-vinsn code-char->char (((dest :lisp))
+				     ((src :imm))
+				     ())
+  (slwi dest src (- ppc32::charcode-shift ppc32::fixnum-shift))
+  (addi dest dest ppc32::subtag-character))
+
+(define-ppc32-vinsn u32->char (((dest :lisp))
+                              ((src :u32))
+                              ())
+  (slwi dest src ppc32::charcode-shift)
+  (addi dest dest ppc32::subtag-character))
+
+;; ... Macptrs ...
+
+(define-ppc32-vinsn deref-macptr (((addr :address))
+                                  ((src :lisp))
+                                  ())
+  (lwz addr ppc32::macptr.address src))
+
+(define-ppc32-vinsn set-macptr-address (()
+                                        ((addr :address)
+                                         (src :lisp))
+                                        ())
+  (stw addr ppc32::macptr.address src))
+
+
+(define-ppc32-vinsn macptr->heap (((dest :lisp))
+                                  ((address :address))
+                                  ((header :u32)))
+  (li header (logior (ash ppc32::macptr.element-count ppc32::num-subtag-bits) ppc32::subtag-macptr))
+  (la ppc::allocptr (- ppc32::fulltag-misc ppc32::macptr.size) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  ;; It's not necessary to zero out the domain/type fields, since newly
+  ;; heap-allocated memory's guaranteed to be 0-filled.
+  (stw address ppc32::macptr.address dest))
+
+(define-ppc32-vinsn macptr->stack (((dest :lisp))
+                                   ((address :address))
+                                   ((header :u32)))
+  (li header ppc32::macptr-header)
+  (stwu ppc::tsp (- (+ 8 ppc32::macptr.size)) ppc::tsp)
+  (stw ppc::tsp 4 ppc::tsp)
+  (stw header (+ 8 ppc32::fulltag-misc ppc32::macptr.header) ppc::tsp)
+  (stw address (+ 8 ppc32::fulltag-misc ppc32::macptr.address) ppc::tsp)
+  ;; It -is- necessary to zero out the domain/type fields here, since
+  ;; stack-allocated memory isn't guaranteed to be 0-filled.
+  (stfd ppc::fp-zero (+ 8 ppc32::fulltag-misc ppc32::macptr.domain) ppc::tsp)
+  (la dest (+ 8 ppc32::fulltag-misc) ppc::tsp))
+
+  
+(define-ppc32-vinsn adjust-stack-register (()
+                                           ((reg t)
+                                            (amount :s16const)))
+  (la reg amount reg))
+
+(define-ppc32-vinsn adjust-vsp (()
+                                ((amount :s16const)))
+  (la ppc::vsp amount ppc::vsp))
+
+(define-ppc32-vinsn adjust-sp (()
+                               ((amount :s16const)))
+  (la ppc::sp amount ppc::sp))
+
+;; Arithmetic on fixnums & unboxed numbers
+
+(define-ppc32-vinsn u32-lognot (((dest :u32))
+                                ((src :u32))
+                                ())
+  (not dest src))
+
+(define-ppc32-vinsn fixnum-lognot (((dest :imm))
+                                   ((src :imm))
+                                   ((temp :u32)))
+  (not temp src)
+  (clrrwi dest temp ppc32::nfixnumtagbits))
+
+
+(define-ppc32-vinsn negate-fixnum-overflow-inline (((dest :lisp))
+                                                   ((src :imm))
+                                                   ((unboxed :s32)
+                                                    (header :u32)))
+  (nego. dest src)
+  (bns+ :done)
+  (mtxer ppc::rzero)
+  (srawi unboxed dest ppc32::fixnumshift)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc32::fixnumshift))))
+  (li header ppc32::one-digit-bignum-header)
+  (la ppc::allocptr (- ppc32::fulltag-misc 8) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw unboxed ppc32::misc-data-offset dest)
+  :done)
+
+(define-ppc32-vinsn negate-fixnum-overflow-ool (()
+                                                ((src :imm))
+                                                )
+  (nego. ppc::arg_z src)
+  (bsola- .SPfix-overflow)
+  :done)
+  
+                                                  
+                                       
+(define-ppc32-vinsn negate-fixnum-no-ovf (((dest :lisp))
+                                          ((src :imm)))
+  
+  (neg dest src))
+  
+
+(define-ppc32-vinsn logior-high (((dest :imm))
+                                 ((src :imm)
+                                  (high :u16const)))
+  (oris dest src high))
+
+(define-ppc32-vinsn logior-low (((dest :imm))
+                                ((src :imm)
+                                 (low :u16const)))
+  (ori dest src low))
+
+                           
+                           
+(define-ppc32-vinsn %logior2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm))
+                              ())
+  (or dest x y))
+
+(define-ppc32-vinsn logand-high (((dest :imm))
+                                 ((src :imm)
+                                  (high :u16const))
+                                 ((crf0 (:crf 0))))
+  (andis. dest src high))
+
+(define-ppc32-vinsn logand-low (((dest :imm))
+                                ((src :imm)
+                                 (low :u16const))
+                                ((crf0 (:crf 0))))
+  (andi. dest src low))
+
+
+(define-ppc32-vinsn %logand2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm))
+                              ())
+  (and dest x y))
+
+(define-ppc32-vinsn clear-left (((dest :imm))
+                                ((src :imm)
+                                 (nbits :s8const)))
+  (rlwinm dest src 0 (:apply 1+ nbits) 31))
+
+(define-ppc32-vinsn clear-right (((dest :imm))
+                                 ((src :imm)
+                                  (nbits :s8const)))
+  (rlwinm dest src 0 0 (:apply - 31 nbits)))
+
+                               
+(define-ppc32-vinsn logxor-high (((dest :imm))
+                                 ((src :imm)
+                                  (high :u16const)))
+  (xoris dest src high))
+
+(define-ppc32-vinsn logxor-low (((dest :imm))
+                                ((src :imm)
+                                 (low :u16const)))
+  (xori dest src low))
+
+                           
+
+(define-ppc32-vinsn %logxor2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm))
+                              ())
+  (xor dest x y))
+
+(define-ppc32-vinsn %ilsl (((dest :imm))
+                           ((count :imm)
+                            (src :imm))
+                           ((temp :u32)
+                            (crx :crf)))
+  (cmpwi crx count (ash 31 ppc32::fixnumshift))
+  (srwi temp count ppc32::fixnumshift)
+  (slw dest src temp)
+  (ble+ crx :foo)
+  (li dest 0)
+  :foo)
+
+(define-ppc32-vinsn %ilsl-c (((dest :imm))
+                             ((count :u8const)
+                              (src :imm)))
+                                        ; Hard to use ppcmacroinstructions that expand into expressions involving variables.
+  (rlwinm dest src count 0 (:apply - ppc32::least-significant-bit count)))
+
+
+(define-ppc32-vinsn %ilsr-c (((dest :imm))
+                             ((count :u8const)
+                              (src :imm)))
+  (rlwinm dest src (:apply - ppc32::nbits-in-word count) count (- ppc32::least-significant-bit
+                                                                  ppc32::fixnumshift)))
+
+
+
+;;; 68k did the right thing for counts < 64 - fixnumshift but not if greater
+;;; so load-byte fails in 3.0 also
+
+
+(define-ppc32-vinsn %iasr (((dest :imm))
+                           ((count :imm)
+                            (src :imm))
+                           ((temp :s32)
+                            (crx :crf)))
+  (cmpwi crx count (ash 31 ppc32::fixnumshift))
+  (srawi temp count ppc32::fixnumshift)
+  (sraw temp src temp)
+  (ble+ crx :foo)
+  (srawi temp src 31)
+  :foo
+  (clrrwi dest temp ppc32::fixnumshift))
+
+(define-ppc32-vinsn %iasr-c (((dest :imm))
+                             ((count :u8const)
+                              (src :imm))
+                             ((temp :s32)))
+  (srawi temp src count)
+  (clrrwi dest temp ppc32::fixnumshift))
+
+(define-ppc32-vinsn %ilsr (((dest :imm))
+                           ((count :imm)
+                            (src :imm))
+                           ((temp :s32)
+                            (crx :crf)))
+  (cmpwi crx count (ash 31 ppc32::fixnumshift))
+  (srwi temp count ppc32::fixnumshift)
+  (srw temp src temp)
+  (clrrwi dest temp ppc32::fixnumshift)
+  (ble+ crx :foo)
+  (li dest 0)
+  :foo  
+  )
+
+#+maybe
+(define-ppc32-vinsn %ilsr-c (((dest :imm))
+                             ((count :u8const)
+                              (src :imm))
+                             ((temp :s32)))
+  (rlwinm temp src (:apply - 32 count) count 31)
+  (clrrwi dest temp ppc32::fixnumshift))
+
+(define-ppc32-vinsn natural-shift-left (((dest :u32))
+                                        ((src :u32)
+                                         (count :u8const)))
+  (rlwinm dest src count 0 (:apply - 31 count)))
+
+(define-ppc32-vinsn natural-shift-right (((dest :u32))
+                                         ((src :u32)
+                                          (count :u8const)))
+  (rlwinm dest src (:apply - 32 count) count 31))
+
+
+(define-ppc32-vinsn trap-unless-simple-array-2 (()
+                                                ((object :lisp)
+                                                 (expected-flags :u32const)
+                                                 (type-error :u8const))
+                                                ((tag :u8)
+                                                 (flags :u32)
+                                                 (crf :crf)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :bad)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmpwi crf tag ppc32::subtag-arrayH)
+  (bne crf :bad) 
+  (lwz tag ppc32::arrayH.rank object)
+  (cmpwi crf tag (ash 2 ppc32::fixnumshift))
+  (lis tag (:apply ldb (byte 16 16) (:apply ash expected-flags ppc32::fixnumshift)))
+       
+  (lwz flags ppc32::arrayH.flags object)
+  (ori tag tag (:apply ldb (byte 16 0) (:apply ash expected-flags ppc32::fixnumshift)))
+  (bne crf :bad)
+  (cmpw crf tag flags)
+  (beq crf :good)
+  :bad
+  (uuo_interr type-error object)
+  :good)
+
+(define-ppc32-vinsn trap-unless-simple-array-3 (()
+                                                ((object :lisp)
+                                                 (expected-flags :u32const)
+                                                 (type-error :u8const))
+                                                ((tag :u8)
+                                                 (flags :u32)
+                                                 (crf :crf)))
+  (clrlwi tag object (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne crf :bad)
+  (lbz tag ppc32::misc-subtag-offset object)
+  (cmpwi crf tag ppc32::subtag-arrayH)
+  (bne crf :bad) 
+  (lwz tag ppc32::arrayH.rank object)
+  (cmpwi crf tag (ash 3 ppc32::fixnumshift))
+  (lis tag (:apply ldb (byte 16 16) (:apply ash expected-flags ppc32::fixnumshift)))
+       
+  (lwz flags ppc32::arrayH.flags object)
+  (ori tag tag (:apply ldb (byte 16 0) (:apply ash expected-flags ppc32::fixnumshift)))
+  (bne crf :bad)
+  (cmpw crf tag flags)
+  (beq crf :good)
+  :bad
+  (uuo_interr type-error object)
+  :good)
+  
+  
+  
+  
+(define-ppc32-vinsn sign-extend-halfword (((dest :imm))
+                                          ((src :imm)))
+  (slwi dest src (- 16 ppc32::fixnumshift))
+  (srawi dest dest (- 16 ppc32::fixnumshift)))
+
+(define-ppc32-vinsn s32-highword (((dest :imm))
+                                  ((src :s32))
+                                  ((temp :s32)))
+  (srawi temp src 16)
+  (slwi dest temp ppc32::fixnumshift))
+
+                            
+
+(define-ppc32-vinsn fixnum-add (((dest t))
+                                ((x t)
+                                 (y t)))
+  (add dest x y))
+
+
+(define-ppc32-vinsn fixnum-add-overflow-ool (()
+                                             ((x :imm)
+                                              (y :imm))
+                                             ((cr0 (:crf 0))))
+  (addo. ppc::arg_z x y)
+  (bsola- .SPfix-overflow))
+
+(define-ppc32-vinsn fixnum-add-overflow-inline (((dest :lisp))
+                                                ((x :imm)
+                                                 (y :imm))
+                                                ((cr0 (:crf 0))
+                                                 (unboxed :s32)
+                                                 (header :u32)))
+  (addo. dest x y)
+  (bns+ cr0 :done)
+  (mtxer ppc::rzero)
+  (srawi unboxed dest ppc32::fixnumshift)
+  (li header ppc32::one-digit-bignum-header)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc32::fixnumshift))))
+  (la ppc::allocptr (- ppc32::fulltag-misc 8) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw unboxed ppc32::misc-data-offset dest)
+  :done)
+
+(define-ppc32-vinsn fixnum-add-overflow-inline-skip (((dest :lisp))
+                                                ((x :imm)
+                                                 (y :imm)
+                                                 (target :label))
+                                                ((cr0 (:crf 0))
+                                                 (unboxed :s32)
+                                                 (header :u32)))
+  (addo. dest x y)
+  (bns+ cr0 target)
+  (mtxer ppc::rzero)
+  (srawi unboxed dest ppc32::fixnumshift)
+  (li header ppc32::one-digit-bignum-header)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc32::fixnumshift))))
+  (la ppc::allocptr (- ppc32::fulltag-misc 8) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw unboxed ppc32::misc-data-offset dest)
+  (b target))
+  
+
+  
+
+;;;  (setq dest (- x y))
+(define-ppc32-vinsn fixnum-sub (((dest t))
+                                ((x t)
+                                 (y t)))
+  (subf dest y x))
+
+(define-ppc32-vinsn fixnum-sub-from-constant (((dest :imm))
+                                              ((x :s16const)
+                                               (y :imm)))
+  (subfic dest y (:apply ash x ppc32::fixnumshift)))
+
+
+
+
+(define-ppc32-vinsn fixnum-sub-overflow-ool (()
+                                             ((x :imm)
+                                              (y :imm)))
+  (subo. ppc::arg_z x y)
+  (bsola- .SPfix-overflow))
+
+(define-ppc32-vinsn fixnum-sub-overflow-inline (((dest :lisp))
+                                                ((x :imm)
+                                                 (y :imm))
+                                                ((cr0 (:crf 0))
+                                                 (unboxed :s32)
+                                                 (header :u32)))
+  (subo. dest x y)
+  (bns+ cr0 :done)
+  (mtxer ppc::rzero)
+  (srawi unboxed dest ppc32::fixnumshift)
+  (li header ppc32::one-digit-bignum-header)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc32::fixnumshift))))
+  (la ppc::allocptr (- ppc32::fulltag-misc 8) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw unboxed ppc32::misc-data-offset dest)
+  :done)
+
+(define-ppc32-vinsn fixnum-sub-overflow-inline-skip (((dest :lisp))
+                                                     ((x :imm)
+                                                      (y :imm)
+                                                      (target :label))
+                                                     ((cr0 (:crf 0))
+                                                      (unboxed :s32)
+                                                      (header :u32)))
+  (subo. dest x y)
+  (bns+ cr0 target)
+  (mtxer ppc::rzero)
+  (srawi unboxed dest ppc32::fixnumshift)
+  (li header ppc32::one-digit-bignum-header)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc32::fixnumshift))))
+  (la ppc::allocptr (- ppc32::fulltag-misc 8) ppc::allocptr)
+  (twllt ppc::allocptr ppc::allocbase)
+  (stw header ppc32::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrwi ppc::allocptr ppc::allocptr ppc32::ntagbits)
+  (stw unboxed ppc32::misc-data-offset dest)
+  (b target))
+
+;;; This is, of course, also "subtract-immediate."
+(define-ppc32-vinsn add-immediate (((dest t))
+                                   ((src t)
+                                    (upper :u32const)
+                                    (lower :u32const)))
+  ((:not (:pred = upper 0))
+   (addis dest src upper)
+   ((:not (:pred = lower 0))
+    (addi dest dest lower)))
+  ((:and (:pred = upper 0) (:not (:pred = lower 0)))
+   (addi dest src lower)))
+
+;This must unbox one reg, but hard to tell which is better.
+;(The one with the smaller absolute value might be)
+(define-ppc32-vinsn multiply-fixnums (((dest :imm))
+                                      ((a :imm)
+                                       (b :imm))
+                                      ((unboxed :s32)))
+  (srawi unboxed b ppc32::fixnumshift)
+  (mullw dest a unboxed))
+
+(define-ppc32-vinsn multiply-immediate (((dest :imm))
+                                        ((boxed :imm)
+                                         (const :s16const)))
+  (mulli dest boxed const))
+
+;;; Mask out the code field of a base character; the result
+;;; should be EXACTLY = to subtag-base-char
+(define-ppc32-vinsn mask-base-char (((dest :u32))
+                                    ((src :imm)))
+  (clrlwi dest src (- ppc32::nbits-in-word ppc32::charcode-shift)))
+
+;;; Set dest (of type :s32!) to 0 iff VAL is an istruct of type TYPE
+(define-ppc32-vinsn istruct-typep (((dest :s32))
+                                   ((val :lisp)
+                                    (type :lisp))
+                                   ((crf :crf)
+                                    (temp :lisp)))
+  (clrlwi dest val (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf dest ppc32::tag-misc)
+  (li dest -1)
+  (bne crf :done)
+  (lbz dest ppc32::misc-subtag-offset val)
+  (cmpwi crf dest ppc32::subtag-istruct)
+  (bne crf :done)
+  (lwz temp ppc32::misc-data-offset val)
+  (subf dest type temp)
+  :done)
+  
+  
+;; Boundp, fboundp stuff.
+(define-ppc32-vinsn (ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val)))))
+  (bla .SPspecrefcheck))
+
+(define-ppc32-vinsn ref-symbol-value-inline (((dest :lisp))
+                                              ((src (:lisp (:ne dest))))
+                                              ((table :imm)
+                                               (idx :imm)))
+  (lwz idx ppc32::symbol.binding-index src)
+  (lwz table ppc32::tcr.tlb-limit ppc32::rcontext)
+  (cmpw idx table)
+  (lwz table ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (bge :symbol)
+  (lwzx dest table idx)
+  (cmpwi dest ppc32::subtag-no-thread-local-binding)
+  (bne :done)
+  :symbol
+  (lwz dest ppc32::symbol.vcell src)
+  :done
+  (tweqi dest ppc32::unbound-marker))
+
+(define-ppc32-vinsn (%ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val)))))
+  (bla .SPspecref))
+
+(define-ppc32-vinsn %ref-symbol-value-inline (((dest :lisp))
+                                              ((src (:lisp (:ne dest))))
+                                              ((table :imm)
+                                               (idx :imm)))
+  (lwz idx ppc32::symbol.binding-index src)
+  (lwz table ppc32::tcr.tlb-limit ppc32::rcontext)
+  (cmpw idx table)
+  (lwz table ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (bge :symbol)
+  (lwzx dest table idx)
+  (cmpwi dest ppc32::subtag-no-thread-local-binding)
+  (bne :done)
+  :symbol
+  (lwz dest ppc32::symbol.vcell src)
+  :done
+  )
+
+(define-ppc32-vinsn (setq-special :call :subprim-call)
+    (()
+     ((sym :lisp)
+      (val :lisp)))
+  (bla .SPspecset))
+
+
+(define-ppc32-vinsn symbol-function (((val :lisp))
+                                     ((sym (:lisp (:ne val))))
+                                     ((crf :crf)
+                                      (tag :u32)))
+  (lwz val ppc32::symbol.fcell sym)
+  (clrlwi tag val (- 32 ppc32::nlisptagbits))
+  (cmpwi crf tag ppc32::tag-misc)
+  (bne- crf :bad)
+  (lbz tag ppc32::misc-subtag-offset val)
+  (cmpwi crf tag ppc32::subtag-function)
+  (beq+ crf :good)
+  :bad 
+  (uuo_interr arch::error-udf sym)
+  :good)
+
+(define-ppc32-vinsn (temp-push-unboxed-word :push :word :tsp)
+    (()
+     ((w :u32)))
+  (stwu ppc::tsp -16 ppc::tsp)
+  (stw ppc::tsp 4 ppc::tsp)
+  (stw w 8 ppc::tsp))
+
+(define-ppc32-vinsn (temp-pop-unboxed-word :pop :word :tsp)
+    (((w :u32))
+     ())
+  (lwz w 8 ppc::tsp)
+  (la ppc::tsp 16 ppc::tsp))
+
+(define-ppc32-vinsn (temp-push-double-float :push :doubleword :tsp)
+    (((d :double-float))
+     ())
+  (stwu ppc::tsp -16 ppc::tsp)
+  (stw ppc::tsp 4 ppc::tsp)
+  (stfd d 8 ppc::tsp))
+
+(define-ppc32-vinsn (temp-pop-double-float :pop :doubleword :tsp)
+    (()
+     ((d :double-float)))
+  (lfd d 8 ppc::tsp)
+  (la ppc::tsp 16 ppc::tsp))
+
+(define-ppc32-vinsn (temp-push-single-float :push :word :tsp)
+    (((s :single-float))
+     ())
+  (stwu ppc::tsp -16 ppc::tsp)
+  (stw ppc::tsp 4 ppc::tsp)
+  (stfs s 8 ppc::tsp))
+
+(define-ppc32-vinsn (temp-pop-single-float :pop :word :tsp)
+    (()
+     ((s :single-float)))
+  (lfs s 8 ppc::tsp)
+  (la ppc::tsp 16 ppc::tsp))
+
+
+(define-ppc32-vinsn (save-nvrs-individually :push :node :vsp :multiple)
+    (()
+     ((first :u8const)))
+  (stwu ppc::save0 -4 ppc::vsp)  
+  ((:pred <= first ppc::save1)
+   (stwu ppc::save1 -4 ppc::vsp)
+   ((:pred <= first ppc::save2)
+    (stwu ppc::save2 -4 ppc::vsp)
+    ((:pred <= first ppc::save3)
+     (stwu ppc::save3 -4 ppc::vsp)
+     ((:pred <= first ppc::save4)
+      (stwu ppc::save4 -4 ppc::vsp)
+      ((:pred <= first ppc::save5)
+       (stwu ppc::save5 -4 ppc::vsp)
+       ((:pred <= first ppc::save6)
+        (stwu ppc::save6 -4 ppc::vsp)
+        ((:pred = first ppc::save7)
+         (stwu ppc::save7 -4 ppc::vsp)))))))))
+
+(define-ppc32-vinsn (save-nvrs :push :node :vsp :multiple)
+    (()
+     ((first :u8const)))
+  ((:pred <= first ppc::save3)
+   (subi ppc::vsp ppc::vsp (:apply * 4 (:apply - 32 first)))   
+   (stmw first 0 ppc::vsp))
+  ((:pred >= first ppc::save2)
+   (stwu ppc::save0 -4 ppc::vsp)
+   ((:pred <= first ppc::save1)
+    (stwu ppc::save1 -4 ppc::vsp)
+    ((:pred = first ppc::save2)
+     (stwu ppc::save2 -4 ppc::vsp)))))
+
+
+(define-ppc32-vinsn (restore-nvrs :pop :node :vsp :multiple)
+    (()
+     ((firstreg :u8const)
+      (basereg :imm)
+      (offset :s16const)))
+  ((:pred <= firstreg ppc::save3)
+   (lmw firstreg offset basereg))
+  ((:pred = firstreg ppc::save2)
+   (lwz ppc::save2 offset basereg)
+   (lwz ppc::save1 (:apply + offset 4) basereg)
+   (lwz ppc::save0 (:apply + offset 8) basereg))
+  ((:pred = firstreg ppc::save1)
+   (lwz ppc::save1 offset basereg)
+   (lwz ppc::save0 (:apply + offset 4) basereg))
+  ((:pred = firstreg ppc::save0)
+   (lwz ppc::save0 offset basereg)))
+
+(define-ppc32-vinsn %current-frame-ptr (((dest :imm))
+                                        ())
+  (mr dest ppc::sp))
+
+(define-ppc32-vinsn %current-tcr (((dest :imm))
+                                  ())
+  (mr dest ppc32::rcontext))
+
+(define-ppc32-vinsn (dpayback :call :subprim-call) (()
+                                                    ((n :s16const))
+                                                    ((temp (:u32 #.ppc::imm0))))
+  ((:pred > n 1)
+   (li temp n)
+   (bla .SPunbind-n))
+  ((:pred = n 1)
+   (bla .SPunbind)))
+
+(define-ppc32-vinsn zero-double-float-register 
+    (((dest :double-float))
+     ())
+  (fmr dest ppc::fp-zero))
+
+(define-ppc32-vinsn zero-single-float-register 
+    (((dest :single-float))
+     ())
+  (fmr dest ppc::fp-zero))
+
+(define-ppc32-vinsn load-double-float-constant
+    (((dest :double-float))
+     ((high t)
+      (low t)))
+  (stw high -8 ppc::sp)
+  (stw low -4 ppc::sp)
+  (lfd dest -8 ppc::sp ))
+
+(define-ppc32-vinsn load-single-float-constant
+    (((dest :single-float))
+     ((src t)))
+  (stw src -4 ppc::sp)
+  (lfs dest -4 ppc::sp))
+
+(define-ppc32-vinsn load-indexed-node (((node :lisp))
+                                       ((base :lisp)
+                                        (offset :s16const)))
+  (lwz node offset base))
+
+(define-ppc32-vinsn check-exact-nargs (()
+                                       ((n :u16const)))
+  (twnei ppc::nargs (:apply ash n 2)))
+
+(define-ppc32-vinsn check-min-nargs (()
+                                     ((min :u16const)))
+  (twllti ppc::nargs (:apply ash min 2)))
+
+(define-ppc32-vinsn check-max-nargs (()
+                                     ((max :u16const)))
+  (twlgti ppc::nargs (:apply ash max 2)))
+
+;;; Save context and establish FN.  The current VSP is the the
+;;; same as the caller's, e.g., no arguments were vpushed.
+(define-ppc32-vinsn save-lisp-context-vsp (()
+                                           ()
+                                           ((imm :u32)))
+  (lwz imm ppc32::tcr.cs-limit ppc32::rcontext)
+  (stwu ppc::sp (- ppc32::lisp-frame.size) ppc::sp)
+  (stw ppc::fn ppc32::lisp-frame.savefn ppc::sp)
+  (stw ppc::loc-pc ppc32::lisp-frame.savelr ppc::sp)
+  (stw ppc::vsp ppc32::lisp-frame.savevsp ppc::sp)
+  (mr ppc::fn ppc::nfn)
+  ;; Do a stack-probe ...
+  (twllt ppc::sp imm))
+
+;;; Do the same thing via a subprim call.
+(define-ppc32-vinsn (save-lisp-context-vsp-ool :call :subprim-call)
+    (()
+     ()
+     ((imm (:u32 #.ppc::imm0))))
+  (bla .SPsavecontextvsp))
+
+(define-ppc32-vinsn save-lisp-context-offset (()
+                                              ((nbytes-vpushed :u16const))
+                                              ((imm :u32)))
+  (la imm nbytes-vpushed ppc::vsp)
+  (stwu ppc::sp (- ppc32::lisp-frame.size) ppc::sp)
+  (stw ppc::fn ppc32::lisp-frame.savefn ppc::sp)
+  (stw ppc::loc-pc ppc32::lisp-frame.savelr ppc::sp)
+  (stw imm ppc32::lisp-frame.savevsp ppc::sp)
+  (mr ppc::fn ppc::nfn)
+  ;; Do a stack-probe ...
+  (lwz imm ppc32::tcr.cs-limit ppc32::rcontext)
+  (twllt ppc::sp imm))
+
+(define-ppc32-vinsn save-lisp-context-offset-ool (()
+                                                  ((nbytes-vpushed :u16const))
+                                                  ((imm (:u32 #.ppc::imm0))))
+  (li imm nbytes-vpushed)
+  (bla .SPsavecontext0))
+
+
+(define-ppc32-vinsn save-lisp-context-lexpr (()
+                                             ()
+                                             ((imm :u32)))
+  (stwu ppc::sp (- ppc32::lisp-frame.size) ppc::sp)
+  (stw ppc::rzero ppc32::lisp-frame.savefn ppc::sp)
+  (stw ppc::loc-pc ppc32::lisp-frame.savelr ppc::sp)
+  (stw ppc::vsp ppc32::lisp-frame.savevsp ppc::sp)
+  (mr ppc::fn ppc::nfn)
+  ;; Do a stack-probe ...
+  (lwz imm ppc32::tcr.cs-limit ppc32::rcontext)
+  (twllt ppc::sp imm))
+  
+(define-ppc32-vinsn save-cleanup-context (()
+                                          ())
+  ;; SP was this deep just a second ago, so no need to do a stack-probe.
+  (mflr ppc::loc-pc)
+  (stwu ppc::sp (- ppc32::lisp-frame.size) ppc::sp)
+  (stw ppc::rzero ppc32::lisp-frame.savefn ppc::sp)
+  (stw ppc::loc-pc ppc32::lisp-frame.savelr ppc::sp)
+  (stw ppc::vsp ppc32::lisp-frame.savevsp ppc::sp))
+
+;; Vpush the argument registers.  We got at least "min-fixed" args;
+;; that knowledge may help us generate better code.
+(define-ppc32-vinsn (save-lexpr-argregs :call :subprim-call)
+    (()
+     ((min-fixed :u16const))
+     ((crfx :crf)
+      (crfy :crf)
+      (entry-vsp (:u32 #.ppc::imm0))
+      (arg-temp :u32)))
+  ((:pred >= min-fixed $numppcargregs)
+   (stwu ppc::arg_x -4 ppc::vsp)   
+   (stwu ppc::arg_y -4 ppc::vsp)   
+   (stwu ppc::arg_z -4 ppc::vsp))
+  ((:pred = min-fixed 2)                ; at least 2 args
+   (cmplwi crfx ppc::nargs (ash 2 ppc32::word-shift))
+   (beq crfx :yz2)                      ; skip arg_x if exactly 2
+   (stwu ppc::arg_x -4 ppc::vsp)
+   :yz2
+   (stwu ppc::arg_y -4 ppc::vsp)
+   (stwu ppc::arg_z -4 ppc::vsp))
+  ((:pred = min-fixed 1)                ; at least one arg
+   (cmplwi crfx ppc::nargs (ash 2 ppc32::word-shift))
+   (blt crfx :z1)                       ; branch if exactly one
+   (beq crfx :yz1)                      ; branch if exactly two
+   (stwu ppc::arg_x -4 ppc::vsp)
+   :yz1
+   (stwu ppc::arg_y -4 ppc::vsp)   
+   :z1
+   (stwu ppc::arg_z -4 ppc::vsp))
+  ((:pred = min-fixed 0)
+   (cmplwi crfx ppc::nargs (ash 2 ppc32::word-shift))
+   (cmplwi crfy ppc::nargs 0)
+   (beq crfx :yz0)                      ; exactly two
+   (beq crfy :none)                     ; exactly zero
+   (blt crfx :z0)                       ; one
+                                        ; Three or more ...
+   (stwu ppc::arg_x -4 ppc::vsp)
+   :yz0
+   (stwu ppc::arg_y -4 ppc::vsp)
+   :z0
+   (stwu ppc::arg_z -4 ppc::vsp)
+   :none
+   )
+  ((:pred = min-fixed 0)
+   (stwu ppc::nargs -4 ppc::vsp))
+  ((:not (:pred = min-fixed 0))
+   (subi arg-temp ppc::nargs (:apply ash min-fixed ppc32::word-shift))
+   (stwu arg-temp -4 ppc::vsp))
+  (add entry-vsp ppc::vsp ppc::nargs)
+  (la entry-vsp 4 entry-vsp)
+  (bla .SPlexpr-entry))
+
+
+(define-ppc32-vinsn (jump-return-pc :jumpLR)
+    (()
+     ())
+  (blr))
+
+(define-ppc32-vinsn (restore-full-lisp-context :lispcontext :pop :csp :lrRestore)
+    (()
+     ())
+  (lwz ppc::loc-pc ppc32::lisp-frame.savelr ppc::sp)
+  (lwz ppc::vsp ppc32::lisp-frame.savevsp ppc::sp)  
+  (lwz ppc::fn ppc32::lisp-frame.savefn ppc::sp)
+  (mtlr ppc::loc-pc)
+  (la ppc::sp ppc32::lisp-frame.size ppc::sp))
+
+
+
+(define-ppc32-vinsn (restore-full-lisp-context-ool :lispcontext :pop :csp :lrRestore)
+    (()
+     ())
+  (bla .SPrestorecontext)
+  (mtlr ppc::loc-pc))
+
+(define-ppc32-vinsn (popj :lispcontext :pop :csp :lrRestore :jumpLR)
+    (() 
+     ())
+  (ba .SPpopj))
+
+;;; Exiting from an UNWIND-PROTECT cleanup is similar to
+;;; (and a little simpler than) returning from a function.
+(define-ppc32-vinsn restore-cleanup-context (()
+                                             ())
+  (lwz ppc::loc-pc ppc32::lisp-frame.savelr ppc::sp)
+  (mtlr ppc::loc-pc)
+  (la ppc::sp ppc32::lisp-frame.size ppc::sp))
+
+
+
+(define-ppc32-vinsn default-1-arg (()
+                                   ((min :u16const))
+                                   ((crf :crf)))
+  (cmplwi crf ppc::nargs (:apply ash min 2))
+  (bne crf :done)
+  ((:pred >= min 3)
+   (stwu ppc::arg_x -4 ppc::vsp))
+  ((:pred >= min 2)
+   (mr ppc::arg_x ppc::arg_y))
+  ((:pred >= min 1)
+   (mr ppc::arg_y ppc::arg_z))
+  (li ppc::arg_z (:apply target-nil-value))
+  :done)
+
+(define-ppc32-vinsn default-2-args (()
+                                    ((min :u16const))
+                                    ((crf :crf)))
+  (cmplwi crf ppc::nargs (:apply ash (:apply 1+ min) 2))
+  (bgt crf :done)
+  (beq crf :one)
+                                        ; We got "min" args; arg_y & arg_z default to nil
+  ((:pred >= min 3)
+   (stwu ppc::arg_x -4 ppc::vsp))   
+  ((:pred >= min 2)
+   (stwu ppc::arg_y -4 ppc::vsp))
+  ((:pred >= min 1)
+   (mr ppc::arg_x ppc::arg_z))
+  (li ppc::arg_y (:apply target-nil-value))
+  (b :last)
+  :one
+                                        ; We got min+1 args: arg_y was supplied, arg_z defaults to nil.
+  ((:pred >= min 2)
+   (stwu ppc::arg_x -4 ppc::vsp))
+  ((:pred >= min 1)
+   (mr ppc::arg_x ppc::arg_y))
+  (mr ppc::arg_y ppc::arg_z)
+  :last
+  (li ppc::arg_z (:apply target-nil-value))
+  :done)
+
+(define-ppc32-vinsn default-3-args (()
+                                    ((min :u16const))
+                                    ((crfx :crf)
+                                     (crfy :crf)))
+  (cmplwi crfx ppc::nargs (:apply ash (:apply + 2 min) 2))
+  (cmplwi crfy ppc::nargs (:apply ash min 2))
+  (bgt crfx :done)
+  (beq crfx :two)
+  (beq crfy :none)
+                                        ; The first (of three) &optional args was supplied.
+  ((:pred >= min 2)
+   (stwu ppc::arg_x -4 ppc::vsp))
+  ((:pred >= min 1)
+   (stwu ppc::arg_y -4 ppc::vsp))
+  (mr ppc::arg_x ppc::arg_z)
+  (b :last-2)
+  :two
+                                        ; The first two (of three) &optional args were supplied.
+  ((:pred >= min 1)
+   (stwu ppc::arg_x -4 ppc::vsp))
+  (mr ppc::arg_x ppc::arg_y)
+  (mr ppc::arg_y ppc::arg_z)
+  (b :last-1)
+                                        ; None of the three &optional args was provided.
+  :none
+  ((:pred >= min 3)
+   (stwu ppc::arg_x -4 ppc::vsp))
+  ((:pred >= min 2)
+   (stwu ppc::arg_y -4 ppc::vsp))
+  ((:pred >= min 1)
+   (stwu ppc::arg_z -4 ppc::vsp))
+  (li ppc::arg_x (:apply target-nil-value))
+  :last-2
+  (li ppc::arg_y (:apply target-nil-value))
+  :last-1
+  (li ppc::arg_z (:apply target-nil-value))
+  :done)
+
+(define-ppc32-vinsn save-lr (()
+                             ())
+  (mflr ppc::loc-pc))
+
+;;; "n" is the sum of the number of required args + 
+;;; the number of &optionals.  
+(define-ppc32-vinsn (default-optionals :call :subprim-call) (()
+                                                             ((n :u16const)))
+  (li ppc::imm0 (:apply ash n 2))
+  (bla .SPdefault-optional-args))
+
+;;; fname contains a known symbol
+(define-ppc32-vinsn (call-known-symbol :call) (((result (:lisp ppc::arg_z)))
+                                               ())
+  (lwz ppc::nfn ppc32::symbol.fcell ppc::fname)
+  (lwz ppc::temp0 ppc32::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctrl))
+
+(define-ppc32-vinsn (jump-known-symbol :jumplr) (()
+                                                 ())
+  (lwz ppc::nfn ppc32::symbol.fcell ppc::fname)
+  (lwz ppc::temp0 ppc32::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctr))
+
+(define-ppc32-vinsn (call-known-function :call) (()
+                                                 ())
+  (lwz ppc::temp0 ppc32::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctrl))
+
+(define-ppc32-vinsn (jump-known-function :jumplr) (()
+                                                   ())
+  (lwz ppc::temp0 ppc32::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctr))
+
+(define-ppc32-vinsn %schar8 (((char :imm))
+                            ((str :lisp)
+                             (idx :imm))
+                            ((imm :u32)))
+  (srwi imm idx ppc32::fixnumshift)
+  (addi imm imm ppc32::misc-data-offset)
+  (lbzx imm str imm)
+  (slwi imm imm ppc32::charcode-shift)
+  (addi char imm ppc32::subtag-character))
+
+(define-ppc32-vinsn %schar32 (((char :imm))
+                              ((str :lisp)
+                               (idx :imm))
+                              ((imm :u32)))
+  (addi imm idx ppc32::misc-data-offset)
+  (lwzx imm str imm)
+  (slwi imm imm ppc32::charcode-shift)
+  (addi char imm ppc32::subtag-character))
+
+
+(define-ppc32-vinsn %set-schar8 (()
+                                ((str :lisp)
+                                 (idx :imm)
+                                 (char :imm))
+                                ((imm :u32)
+                                 (imm1 :u32)
+                                 (cr0 (:crf 0))))
+  (srwi imm idx ppc32::fixnumshift)
+  (addi imm imm ppc32::misc-data-offset)
+  (srwi imm1 char ppc32::charcode-shift)
+  (stbx imm1 str imm)
+  )
+
+(define-ppc32-vinsn %set-schar32 (()
+                                  ((str :lisp)
+                                   (idx :imm)
+                                   (char :imm))
+                                  ((imm :u32)
+                                   (imm1 :u32)
+                                   (cr0 (:crf 0))))
+  (addi imm idx ppc32::misc-data-offset)
+  (srwi imm1 char ppc32::charcode-shift)
+  (stwx imm1 str imm)
+  )
+
+(define-ppc32-vinsn %set-scharcode8 (()
+                                    ((str :lisp)
+                                     (idx :imm)
+                                     (code :imm))
+                                    ((imm :u32)
+                                     (imm1 :u32)
+                                     (cr0 (:crf 0))))
+  (srwi imm idx ppc32::fixnumshift)
+  (addi imm imm ppc32::misc-data-offset)
+  (srwi imm1 code ppc32::fixnumshift)
+  (stbx imm1 str imm)
+  )
+
+
+(define-ppc32-vinsn %set-scharcode32 (()
+                                    ((str :lisp)
+                                     (idx :imm)
+                                     (code :imm))
+                                    ((imm :u32)
+                                     (imm1 :u32)))
+  (addi imm idx ppc32::misc-data-offset)
+  (srwi imm1 code ppc32::fixnumshift)
+  (stwx imm1 str imm)
+  )
+
+(define-ppc32-vinsn %scharcode8 (((code :imm))
+                                 ((str :lisp)
+                                  (idx :imm))
+                                 ((imm :u32)
+                                  (cr0 (:crf 0))))
+  (srwi imm idx ppc32::fixnumshift)
+  (addi imm imm ppc32::misc-data-offset)
+  (lbzx imm str imm)
+  (slwi code imm ppc32::fixnumshift))
+
+(define-ppc32-vinsn %scharcode32 (((code :imm))
+                                 ((str :lisp)
+                                  (idx :imm))
+                                 ((imm :u32)
+                                  (cr0 (:crf 0))))
+  (addi imm idx ppc32::misc-data-offset)
+  (lwzx imm str imm)
+  (slwi code imm ppc32::fixnumshift))
+
+;;; Clobbers LR
+(define-ppc32-vinsn (%debug-trap :call :subprim-call) (()
+                                                       ())
+  (bla .SPbreakpoint)
+  )
+
+
+(define-ppc32-vinsn eep.address (((dest t))
+                                 ((src (:lisp (:ne dest )))))
+  (lwz dest (+ (ash 1 2) ppc32::misc-data-offset) src)
+  (tweqi dest (:apply target-nil-value)))
+                 
+(define-ppc32-vinsn %natural+ (((dest :u32))
+                               ((x :u32) (y :u32)))
+  (add dest x y))
+
+(define-ppc32-vinsn %natural+-c (((dest :u32))
+                                 ((x :u32) (y :u16const)))
+  (addi dest x y))
+
+(define-ppc32-vinsn %natural- (((dest :u32))
+                               ((x :u32) (y :u32)))
+  (sub dest x y))
+
+(define-ppc32-vinsn %natural--c (((dest :u32))
+                                 ((x :u32) (y :u16const)))
+  (subi dest x y))
+
+(define-ppc32-vinsn %natural-logior (((dest :u32))
+                                     ((x :u32) (y :u32)))
+  (or dest x y))
+
+(define-ppc32-vinsn %natural-logior-c (((dest :u32))
+                                       ((x :u32) (high :u16const) (low :u16const)))
+  ((:not (:pred = high 0))
+   (oris dest x high))
+  ((:not (:pred = low 0))
+   (ori dest x low)))
+
+(define-ppc32-vinsn %natural-logxor (((dest :u32))
+                                     ((x :u32) (y :u32)))
+  (xor dest x y))
+
+(define-ppc32-vinsn %natural-logxor-c (((dest :u32))
+                                       ((x :u32) (high :u16const) (low :u16const)))
+  ((:not (:pred = high 0))
+   (xoris dest x high))
+  ((:not (:pred = low 0))
+   (xori dest x low)))
+
+(define-ppc32-vinsn %natural-logand (((dest :u32))
+                                     ((x :u32) (y :u32)))
+  (and dest x y))
+
+(define-ppc32-vinsn %natural-logand-high-c (((dest :u32))
+                                            ((x :u32) (high :u16const))
+                                            ((cr0 (:crf 0))))
+  (andis. dest x high))
+
+(define-ppc32-vinsn %natural-logand-low-c (((dest :u64))
+                                           ((x :u64) (low :u16const))
+                                           ((cr0 (:crf 0))))
+  (andi. dest x low))
+
+(define-ppc32-vinsn %natural-logand-mask-c (((dest :u32))
+                                            ((x :u32)
+                                             (start :u8const)
+                                             (end :u8const)))
+  (rlwinm dest x 0 start end))
+
+(define-ppc32-vinsn disable-interrupts (((dest :lisp))
+                                        ()
+                                        ((temp :imm)
+                                         (temp2 :imm)))
+  (lwz temp2 ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (li temp -4)
+  (lwz dest ppc32::interrupt-level-binding-index temp2)
+  (stw temp ppc32::interrupt-level-binding-index temp2))
+
+(define-ppc32-vinsn load-character-constant (((dest :lisp))
+                                             ((code :u32const)))
+  (ori dest ppc::rzero (:apply logior (:apply ash (:apply logand #xff code) ppc32::charcode-shift) ppc32::subtag-character))
+  ((:not (:pred = 0 (:apply ldb (byte 16 8) code)))
+   (oris dest dest (:apply ldb (byte 16 8) code))))
+
+
+(define-ppc32-vinsn %symbol->symptr (((dest :lisp))
+                                     ((src :lisp))
+                                     ((tag :u8)
+                                      (crf0 :crf)
+                                      (crf1 :crf)))
+  (clrlwi tag src (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (cmpwi crf0 src (:apply target-nil-value))
+  (cmpwi crf1 tag ppc32::tag-misc)
+  (beq crf0 :nilsym)
+  (bne crf1 :do-trap)
+  (lbz tag ppc32::misc-subtag-offset src)
+  :do-trap
+  (twnei tag ppc32::subtag-symbol)
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (mr dest src))
+  (b :done)
+  :nilsym
+  (li dest (:apply + ppc32::nilsym-offset (:apply target-nil-value)))
+  :done)
+
+;;; Subprim calls.  Done this way for the benefit of VINSN-OPTIMIZE.
+(defmacro define-ppc32-subprim-call-vinsn ((name &rest other-attrs) spno)
+  `(define-ppc32-vinsn (,name :call :subprim-call ,@other-attrs) (() ())
+    (bla ,spno)))
+
+(defmacro define-ppc32-subprim-jump-vinsn ((name &rest other-attrs) spno)
+  `(define-ppc32-vinsn (,name  :jumpLR ,@other-attrs) (() ())
+    (ba ,spno)))
+
+(define-ppc32-subprim-jump-vinsn (restore-interrupt-level) .SPrestoreintlevel)
+
+(define-ppc32-subprim-call-vinsn (save-values) .SPsave-values)
+
+(define-ppc32-subprim-call-vinsn (recover-values)  .SPrecover-values)
+
+(define-ppc32-subprim-call-vinsn (add-values) .SPadd-values)
+
+(define-ppc32-subprim-jump-vinsn (jump-known-symbol-ool) .SPjmpsym)
+
+(define-ppc32-subprim-call-vinsn (call-known-symbol-ool)  .SPjmpsym)
+
+(define-ppc32-subprim-call-vinsn (pass-multiple-values)  .SPmvpass)
+
+(define-ppc32-subprim-call-vinsn (pass-multiple-values-symbol) .SPmvpasssym)
+
+(define-ppc32-subprim-jump-vinsn (tail-call-sym-gen) .SPtcallsymgen)
+
+(define-ppc32-subprim-jump-vinsn (tail-call-fn-gen) .SPtcallnfngen)
+
+(define-ppc32-subprim-jump-vinsn (tail-call-sym-slide) .SPtcallsymslide)
+
+(define-ppc32-subprim-jump-vinsn (tail-call-fn-slide) .SPtcallnfnslide)
+
+(define-ppc32-subprim-jump-vinsn (tail-call-sym-vsp) .SPtcallsymvsp)
+
+(define-ppc32-subprim-jump-vinsn (tail-call-fn-vsp) .SPtcallnfnvsp)
+
+(define-ppc32-subprim-call-vinsn (funcall)  .SPfuncall)
+
+(define-ppc32-subprim-jump-vinsn (tail-funcall-gen) .SPtfuncallgen)
+
+(define-ppc32-subprim-jump-vinsn (tail-funcall-slide) .SPtfuncallslide)
+
+(define-ppc32-subprim-jump-vinsn (tail-funcall-vsp) .SPtfuncallvsp)
+
+(define-ppc32-subprim-call-vinsn (spread-lexpr)  .SPspread-lexpr-z)
+
+(define-ppc32-subprim-call-vinsn (spread-list)  .SPspreadargz)
+
+(define-ppc32-subprim-call-vinsn (pop-argument-registers)  .SPvpopargregs)
+
+(define-ppc32-subprim-call-vinsn (getu32) .SPgetu32)
+
+(define-ppc32-subprim-call-vinsn (gets32) .SPgets32)
+
+(define-ppc32-subprim-call-vinsn (getxlong)  .SPgetXlong)
+
+(define-ppc32-subprim-call-vinsn (stack-cons-list)  .SPstkconslist)
+
+(define-ppc32-subprim-call-vinsn (list) .SPconslist)
+
+(define-ppc32-subprim-call-vinsn (stack-cons-list*)  .SPstkconslist-star)
+
+(define-ppc32-subprim-call-vinsn (list*) .SPconslist-star)
+
+(define-ppc32-subprim-call-vinsn (make-stack-block)  .SPmakestackblock)
+
+(define-ppc32-subprim-call-vinsn (make-stack-block0)  .Spmakestackblock0)
+
+(define-ppc32-subprim-call-vinsn (make-stack-list)  .Spmakestacklist)
+
+(define-ppc32-subprim-call-vinsn (make-stack-vector)  .SPmkstackv)
+
+(define-ppc32-subprim-call-vinsn (make-stack-gvector)  .SPstkgvector)
+
+(define-ppc32-subprim-call-vinsn (stack-misc-alloc)  .SPstack-misc-alloc)
+
+(define-ppc32-subprim-call-vinsn (stack-misc-alloc-init)  .SPstack-misc-alloc-init)
+
+(define-ppc32-subprim-call-vinsn (bind-nil)  .SPbind-nil)
+
+(define-ppc32-subprim-call-vinsn (bind-self)  .SPbind-self)
+
+(define-ppc32-subprim-call-vinsn (bind-self-boundp-check)  .SPbind-self-boundp-check)
+
+(define-ppc32-subprim-call-vinsn (bind)  .SPbind)
+
+(define-ppc32-subprim-jump-vinsn (nvalret :jumpLR) .SPnvalret)
+
+(define-ppc32-subprim-call-vinsn (nthrowvalues) .SPnthrowvalues)
+
+(define-ppc32-subprim-call-vinsn (nthrow1value) .SPnthrow1value)
+
+(define-ppc32-subprim-call-vinsn (slide-values) .SPmvslide)
+
+(define-ppc32-subprim-call-vinsn (macro-bind) .SPmacro-bind)
+
+(define-ppc32-subprim-call-vinsn (destructuring-bind-inner) .SPdestructuring-bind-inner)
+
+(define-ppc32-subprim-call-vinsn (destructuring-bind) .SPdestructuring-bind)
+
+(define-ppc32-subprim-call-vinsn (simple-keywords) .SPsimple-keywords)
+
+(define-ppc32-subprim-call-vinsn (keyword-args) .SPkeyword-args)
+
+(define-ppc32-subprim-call-vinsn (keyword-bind) .SPkeyword-bind)
+
+(define-ppc32-subprim-call-vinsn (stack-rest-arg) .SPstack-rest-arg)
+
+(define-ppc32-subprim-call-vinsn (req-stack-rest-arg) .SPreq-stack-rest-arg)
+
+(define-ppc32-subprim-call-vinsn (stack-cons-rest-arg) .SPstack-cons-rest-arg)
+
+(define-ppc32-subprim-call-vinsn (heap-rest-arg) .SPheap-rest-arg)
+
+(define-ppc32-subprim-call-vinsn (req-heap-rest-arg) .SPreq-heap-rest-arg)
+
+(define-ppc32-subprim-call-vinsn (heap-cons-rest-arg) .SPheap-cons-rest-arg)
+
+(define-ppc32-subprim-call-vinsn (opt-supplied-p) .SPopt-supplied-p)
+
+(define-ppc32-subprim-call-vinsn (gvector) .SPgvector)
+
+(define-ppc32-vinsn (nth-value :call :subprim-call) (((result :lisp))
+                                                     ())
+  (bla .SPnthvalue))
+
+(define-ppc32-subprim-call-vinsn (fitvals) .SPfitvals)
+
+(define-ppc32-subprim-call-vinsn (misc-alloc) .SPmisc-alloc)
+
+(define-ppc32-subprim-call-vinsn (misc-alloc-init) .SPmisc-alloc-init)
+
+(define-ppc32-subprim-call-vinsn (integer-sign) .SPinteger-sign)
+
+;;; Even though it's implemented by calling a subprim, THROW is really
+;;; a JUMP (to a possibly unknown destination).  If the destination's
+;;; really known, it should probably be inlined (stack-cleanup, value
+;;; transfer & jump ...)
+(define-ppc32-vinsn (throw :jump-unknown) (()
+                                                 ())
+  (bla .SPthrow))
+
+(define-ppc32-subprim-call-vinsn (mkcatchmv) .SPmkcatchmv)
+
+(define-ppc32-subprim-call-vinsn (mkcatch1v) .SPmkcatch1v)
+
+(define-ppc32-subprim-call-vinsn (setqsym) .SPsetqsym)
+
+(define-ppc32-subprim-call-vinsn (ksignalerr) .SPksignalerr)
+
+(define-ppc32-subprim-call-vinsn (subtag-misc-ref) .SPsubtag-misc-ref)
+
+(define-ppc32-subprim-call-vinsn (subtag-misc-set) .SPsubtag-misc-set)
+
+(define-ppc32-subprim-call-vinsn (mkunwind) .SPmkunwind)
+(define-ppc32-subprim-call-vinsn (nmkunwind) .SPnmkunwind)
+
+
+(define-ppc32-subprim-call-vinsn (progvsave) .SPprogvsave)
+
+(define-ppc32-subprim-jump-vinsn (progvrestore) .SPprogvrestore)
+
+(define-ppc32-subprim-call-vinsn (eabi-syscall) .SPeabi-syscall)
+
+(define-ppc32-subprim-call-vinsn (misc-ref) .SPmisc-ref)
+
+(define-ppc32-subprim-call-vinsn (misc-set) .SPmisc-set)
+
+(define-ppc32-subprim-call-vinsn (gets64) .SPgets64)
+
+(define-ppc32-subprim-call-vinsn (getu64) .SPgetu64)
+
+(define-ppc32-subprim-call-vinsn (makeu64) .SPmakeu64)
+
+(define-ppc32-subprim-call-vinsn (makes64) .SPmakes64)
+
+(define-ppc32-vinsn (poweropen-syscall :call :subprim-call) (()
+                                                          ())
+  (stw ppc::rzero ppc32::c-frame.crsave ppc::sp)
+  (bla .SPpoweropen-syscall))
+
+(define-ppc32-vinsn (poweropen-syscall-s64 :call :subprim-call) (()
+                                                              ())
+  (stw ppc::sp ppc32::c-frame.crsave ppc::sp)
+  (bla .SPpoweropen-syscall))
+
+(define-ppc32-subprim-call-vinsn (eabi-ff-call) .SPeabi-ff-call)
+
+(define-ppc32-subprim-call-vinsn (poweropen-ff-call) .SPpoweropen-ffcall)
+
+(define-ppc32-subprim-call-vinsn (poweropen-ff-callX) .SPpoweropen-ffcallX)
+
+(define-ppc32-subprim-call-vinsn (bind-interrupt-level-0) .SPbind-interrupt-level-0)
+
+(define-ppc32-vinsn bind-interrupt-level-0-inline (()
+                                                   ()
+                                                   ((tlb :imm)
+                                                    (value :imm)
+                                                    (link :imm)
+                                                    (temp :imm)))
+  (lwz tlb ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (lwz value ppc32::interrupt-level-binding-index tlb)
+  (lwz link ppc32::tcr.db-link ppc32::rcontext)
+  (cmpwi value 0)
+  (li temp ppc32::interrupt-level-binding-index)
+  (stwu value -4 ppc::vsp)
+  (stwu temp -4 ppc::vsp)
+  (stwu link -4 ppc::vsp)
+  (stw ppc::rzero ppc32::interrupt-level-binding-index tlb)
+  (stw ppc::vsp  ppc32::tcr.db-link ppc32::rcontext)
+  (beq+ :done)
+  (mr ppc::nargs value)
+  (bgt :do-trap)
+  (lwz ppc::nargs ppc32::tcr.interrupt-pending ppc32::rcontext)
+  :do-trap
+  (twgti ppc::nargs 0)
+  :done)
+                                                    
+  
+                                                   
+(define-ppc32-subprim-call-vinsn (bind-interrupt-level-m1) .SPbind-interrupt-level-m1)
+
+(define-ppc32-vinsn bind-interrupt-level-m1-inline (()
+                                                   ()
+                                                   ((tlb :imm)
+                                                    (oldvalue :imm)
+                                                    (link :imm)
+                                                    (newvalue :imm)
+                                                    (idx :imm)))
+  (li newvalue (ash -1 ppc32::fixnumshift))
+  (li idx ppc32::interrupt-level-binding-index)
+  (lwz tlb ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (lwz oldvalue ppc32::interrupt-level-binding-index tlb)
+  (lwz link ppc32::tcr.db-link ppc32::rcontext)
+  (stwu oldvalue -4 ppc::vsp)
+  (stwu idx -4 ppc::vsp)
+  (stwu link -4 ppc::vsp)
+  (stw newvalue ppc32::interrupt-level-binding-index tlb)
+  (stw ppc::vsp  ppc32::tcr.db-link ppc32::rcontext)
+  :done)
+
+(define-ppc32-subprim-call-vinsn (bind-interrupt-level) .SPbind-interrupt-level)
+
+(define-ppc32-subprim-call-vinsn (unbind-interrupt-level) .SPunbind-interrupt-level)
+
+(define-ppc32-vinsn unbind-interrupt-level-inline (()
+                                                   ()
+                                                   ((tlb :imm)
+                                                    (link :imm)
+                                                    (value :imm)
+                                                    (save-nargs :u32)
+                                                    (crf0 :crf)
+                                                    (crf1 :crf)))
+  (lwz tlb ppc32::tcr.tlb-pointer ppc32::rcontext)
+  (lwz value ppc32::interrupt-level-binding-index tlb)
+  (lwz link ppc32::tcr.db-link ppc32::rcontext)
+  (cmpwi crf1 value 0)
+  (lwz value 8 link)
+  (lwz link 0 link)
+  (cmpwi crf0 value 0)
+  (stw value ppc32::interrupt-level-binding-index tlb)
+  (stw link ppc32::tcr.db-link ppc32::rcontext)
+  (bge crf1 :done)
+  (blt crf0 :done)
+  (mr save-nargs ppc::nargs)
+  (lwz ppc::nargs ppc32::tcr.interrupt-pending ppc32::rcontext)
+  (twgti ppc::nargs 0)
+  (mr ppc::nargs save-nargs)
+  :done)
+  
+
+
+(define-ppc32-vinsn branch-unless-arg-fixnum (()
+                                              ((arg :lisp)
+                                               (lab :label))
+                                              ((cr0 (:crf 0))
+                                               (tag :u8)))
+  (clrlwi. tag arg (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (bne cr0 lab))
+
+(define-ppc32-vinsn branch-unless-both-args-fixnums (()
+                                              ((arg0 :lisp)
+                                               (arg1 :lisp)
+                                               (lab :label))
+                                              ((cr0 (:crf 0))
+                                               (tag :u8)))
+  (clrlwi tag arg0 (- ppc32::nbits-in-word ppc32::nlisptagbits))
+  (rlwimi. tag arg1 ppc32::nlisptagbits 28 29)
+  (bne cr0 lab))
+
+;;; In case ppc32::*ppc-opcodes* was changed since this file was compiled.
+(queue-fixup
+ (fixup-vinsn-templates *ppc32-vinsn-templates* ppc::*ppc-opcode-numbers*))
+
+(provide "PPC32-VINSNS")
+
Index: /branches/new-random/compiler/PPC/PPC64/.cvsignore
===================================================================
--- /branches/new-random/compiler/PPC/PPC64/.cvsignore	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC64/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/compiler/PPC/PPC64/ppc64-arch.lisp
===================================================================
--- /branches/new-random/compiler/PPC/PPC64/ppc64-arch.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC64/ppc64-arch.lisp	(revision 13309)
@@ -0,0 +1,1012 @@
+;;;-*- Mode: Lisp; Package: (PPC64 :use CL) -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; This file matches "ccl:lisp-kernel;constants64.h" &
+;;; "ccl:lisp-kernel;constants64.s"
+
+(defpackage "PPC64"
+  (:use "CL")
+  #+ppc64-target
+  (:nicknames "TARGET"))
+
+
+(in-package "PPC64")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defconstant rcontext 2)                ;sigh.  Could use r13+bias on Linux,
+                                        ; but Apple hasn't invented tls yet.
+(defconstant nbits-in-word 64)
+(defconstant least-significant-bit 63)
+(defconstant nbits-in-byte 8)
+(defconstant ntagbits 4)
+(defconstant nlisptagbits 3)
+(defconstant nfixnumtagbits 3)          ; See ?
+(defconstant nlowtagbits 2)
+(defconstant num-subtag-bits 8)         ; tag part of header is 8 bits wide
+(defconstant fixnumshift nfixnumtagbits)
+(defconstant fixnum-shift fixnumshift)          ; A pet name for it.
+(defconstant fulltagmask (1- (ash 1 ntagbits)))         ; Only needed by GC/very low-level code
+(defconstant full-tag-mask fulltagmask)
+(defconstant tagmask (1- (ash 1 nlisptagbits)))
+(defconstant tag-mask tagmask)
+(defconstant fixnummask (1- (ash 1 nfixnumtagbits)))
+(defconstant fixnum-mask fixnummask)
+(defconstant subtag-mask (1- (ash 1 num-subtag-bits)))
+(defconstant ncharcodebits 8)           ;24
+(defconstant charcode-shift 8)
+(defconstant word-shift 3)
+(defconstant word-size-in-bytes 8)
+(defconstant node-size word-size-in-bytes)
+(defconstant dnode-size 16)
+(defconstant dnode-align-bits 4)
+(defconstant dnode-shift dnode-align-bits)
+(defconstant bitmap-shift 6)
+
+(defconstant target-most-negative-fixnum (ash -1 (1- (- nbits-in-word nfixnumtagbits))))
+(defconstant target-most-positive-fixnum (1- (ash 1 (1- (- nbits-in-word nfixnumtagbits)))))
+(defmacro define-subtag (name tag value)
+  `(defconstant ,(ccl::form-symbol "SUBTAG-" name) (logior ,tag (ash ,value ntagbits))))
+
+;;; PPC64 stuff and tags.
+
+;;; There are several ways to look at the 4 tag bits of any object or
+;;; header.  Looking at the low 2 bits, we can classify things as
+;;; follows (I'm not sure if we'd ever want to do this) :
+;;;
+;;;  #b00   a "primary" object: fixnum, cons, uvector
+;;;  #b01   an immediate
+;;;  #b10   the header on an immediate uvector
+;;;  #b11   the header on a node (pointer-containing) uvector
+;;
+;;;  Note that the ppc64's LD and STD instructions require that the low
+;;;  two bits of the constant displacement be #b00.  If we want to use constant
+;;;  offsets to access CONS and UVECTOR fields, we're pretty much obligated
+;;;  to ensure that CONS and UVECTOR have tags that also end in #b00, and
+;;;  fixnum addition and subtraction work better when fixnum tags are all 0.
+;;;  We generally have to look at all 4 tag bits before we really know what
+;;;  class of "potentially primary" object we're looking at.
+;;;  If we look at 3 tag bits, we can see:
+;;;
+;;;  #b000  fixnum
+;;;  #b001  immediate
+;;;  #b010  immedate-header
+;;;  #b011  node-header
+;;;  #b100  CONS or UVECTOR
+;;;  #b101  immediate
+;;;  #b110  immediate-header
+;;;  #b111  node-header
+;;;
+
+(defconstant tag-fixnum 0)
+(defconstant tag-imm-0 1)
+(defconstant tag-immheader-0 2)
+(defconstant tag-nodeheader-0 3)
+(defconstant tag-memory 4)
+(defconstant tag-imm-2 5)
+(defconstant tag-immheader2 6)
+(defconstant tag-nodeheader2 7)
+
+
+;;;  Note how we're already winding up with lots of header and immediate
+;;;  "classes".  That might actually be useful.
+;;
+;;;  When we move to 4 bits, we wind up (obviously) with 4 tags of the form
+;;;  #bxx00.  There are two partitionings that make (some) sense: we can either
+;;;  use 2 of these for (even and odd) fixnums, or we can give NIL a tag
+;;;  that's congruent (mod 16) with CONS.  There seem to be a lot of tradeoffs
+;;;  involved, but it ultimately seems best to be able to treat 64-bit
+;;;  aligned addresses as fixnums: we don't want the VSP to look like a
+;;;  vector.   That basically requires that NIL really be a symbol (good
+;;;  bye, nilsym) and that we ensure that there are NILs where its CAR and
+;;;  CDR would be (-4, 4 bytes from the tagged pointer.)  That means that
+;;;  CONS is 4 and UVECTOR is 12, and we have even more immediate/header types.
+
+(defconstant fulltag-even-fixnum    #b0000)
+(defconstant fulltag-imm-0          #b0001)
+(defconstant fulltag-immheader-0    #b0010)
+(defconstant fulltag-nodeheader-0   #b0011)
+(defconstant fulltag-cons           #b0100)
+(defconstant fulltag-imm-1          #b0101)
+(defconstant fulltag-immheader-1    #b0110)
+(defconstant fulltag-nodeheader-1   #b0111)
+(defconstant fulltag-odd-fixnum     #b1000)
+(defconstant fulltag-imm-2          #b1001)
+(defconstant fulltag-immheader-2    #b1010)
+(defconstant fulltag-nodeheader-2   #b1011)
+(defconstant fulltag-misc           #b1100)
+(defconstant fulltag-imm-3          #b1101)
+(defconstant fulltag-immheader-3    #b1110)
+(defconstant fulltag-nodeheader-3   #b1111)
+
+(defconstant lowtagmask (1- (ash 1 nlowtagbits)))
+(defconstant lowtag-mask lowtagmask)
+(defconstant lowtag-primary 0)
+(defconstant lowtag-imm 1)
+(defconstant lowtag-immheader 2)
+(defconstant lowtag-nodeheader 3)
+
+;;; The general algorithm for determining the (primary) type of an
+;;; object is something like:
+;;; (clrldi tag node 60)
+;;; (cmpwi tag fulltag-misc)
+;;; (clrldi tag tag 61)
+;;; (bne @done)
+;;; (lbz tag misc-subtag-offset node)
+;;; @done
+;;
+;;; That's good enough to identify FIXNUM, "generally immediate", cons,
+;;; or a header tag from a UVECTOR.  In some cases, we may need to hold
+;;; on to the full 4-bit tag.
+;;; In no specific order:
+;;; - it's important to be able to quickly recognize fixnums; that's
+;;;    simple
+;;; - it's important to be able to quickly recognize lists (for CAR/CDR)
+;;;   and somewhat important to be able to quickly recognize conses.
+;;;   Also simple, though we have to special-case NIL.
+;;; - it's desirable to be able to do VECTORP, ARRAYP, and specific-array-type-
+;;;   p.  We need at least 12 immediate CL vector types (SIGNED/UNSIGNED-BYTE
+;;;   8/16/32/64, SINGLE-FLOAT, DOUBLE-FLOAT, BIT, and at least one CHARACTER;
+;;;   we need SIMPLE-ARRAY, VECTOR-HEADER, and ARRAY-HEADER as node
+;;;   array types.  That's suspciciously close to 16
+;;; - it's desirable to be able (in FUNCALL) to quickly recognize
+;;;   functions/symbols/other, and probably desirable to trap on other.
+;;;   Pretty much have to do a memory reference and at least one comparison
+;;;   here.
+;;; - it's sometimes desirable to recognize numbers and distinct numeric
+;;;   types (other than FIXNUM) quickly.
+;;; - The GC (especially) needs to be able to determine the size of
+;;;   ivectors (ivector elements) fairly cheaply.  Most ivectors are CL
+;;;   arrays, but code-vectors are fairly common (and have 32-bit elements,
+;;;   naturally.)
+;;; - We have a fairly large number of non-array gvector types, and it's
+;;;   always desirable to have room for expansion.
+;;; - we basically have 8 classes of header subtags, each of which has
+;;;   16 possible values.  If we stole the high bit of the subtag to
+;;;   indicate CL-array-ness, we'd still have 6 bits to encode non-CL
+;;;   array types.  
+
+(defconstant cl-array-subtag-bit 7)
+(defconstant cl-array-subtag-mask (ash 1 cl-array-subtag-bit))
+(defmacro define-cl-array-subtag (name tag value)
+  `(defconstant ,(ccl::form-symbol "SUBTAG-" name)
+    (logior cl-array-subtag-mask (logior ,tag (ash ,value ntagbits)))))
+
+(define-cl-array-subtag arrayH  fulltag-nodeheader-1 0)
+(define-cl-array-subtag vectorH fulltag-nodeheader-2 0)
+(define-cl-array-subtag simple-vector fulltag-nodeheader-3 0)
+(defconstant min-array-subtag subtag-arrayH)
+(defconstant min-vector-subtag subtag-vectorH)
+
+;;;  bits:                         64             32       16    8     1
+;;;  CL-array ivector types    DOUBLE-FLOAT     SINGLE    s16   CHAR  BIT
+;;;                               s64             s32     u16    s8
+;;;                               u64             u32            u8
+;;;  Other ivector types       MACPTR           CODE-VECTOR
+;;;                            DEAD-MACPTR     XCODE-VECTOR
+;;;                                            BIGNUM
+;;;                                            DOUBLE-FLOAT
+;;; There might possibly be ivectors with 128-bit (VMX/AltiVec) elements
+;;; someday, and there might be multiple character sizes (16/32 bits).
+;;; That sort of suggests that we use the four immheader classes to
+;;; encode the ivector size (64, 32, 8, other) and make BIT an easily-
+;;; detected case of OTHER.
+
+(defconstant ivector-class-64-bit fulltag-immheader-3)
+(defconstant ivector-class-32-bit fulltag-immheader-2)
+(defconstant ivector-class-other-bit fulltag-immheader-1)
+(defconstant ivector-class-8-bit fulltag-immheader-0)
+
+(define-cl-array-subtag s64-vector ivector-class-64-bit 1)
+(define-cl-array-subtag u64-vector ivector-class-64-bit 2)
+(define-cl-array-subtag fixnum-vector ivector-class-64-bit 3)
+(define-cl-array-subtag double-float-vector ivector-class-64-bit 4)
+(define-cl-array-subtag s32-vector ivector-class-32-bit 1)
+(define-cl-array-subtag u32-vector ivector-class-32-bit 2)
+(define-cl-array-subtag single-float-vector ivector-class-32-bit 3)
+(define-cl-array-subtag simple-base-string ivector-class-32-bit 5)
+(define-cl-array-subtag s16-vector ivector-class-other-bit 1)
+(define-cl-array-subtag u16-vector ivector-class-other-bit 2)
+(define-cl-array-subtag bit-vector ivector-class-other-bit 7)
+(define-cl-array-subtag s8-vector ivector-class-8-bit 1)
+(define-cl-array-subtag u8-vector ivector-class-8-bit 2)
+
+;;; There's some room for expansion in non-array ivector space.
+(define-subtag macptr ivector-class-64-bit 1)
+(define-subtag dead-macptr ivector-class-64-bit 2)
+
+(define-subtag code-vector ivector-class-32-bit 0)
+(define-subtag xcode-vector ivector-class-32-bit 1)
+(define-subtag bignum ivector-class-32-bit 2)
+(define-subtag double-float ivector-class-32-bit 3)
+
+;;; Size doesn't matter for non-CL-array gvectors; I can't think of a good
+;;; reason to classify them in any particular way.  Let's put funcallable
+;;; things in the first slice by themselves, though it's not clear that
+;;; that helps FUNCALL much.
+(defconstant gvector-funcallable fulltag-nodeheader-0)
+(define-subtag function gvector-funcallable 0)
+(define-subtag symbol gvector-funcallable 1)
+
+(define-subtag catch-frame fulltag-nodeheader-1 0)
+(define-subtag basic-stream fulltag-nodeheader-1 1)
+(define-subtag lock fulltag-nodeheader-1 2)
+(define-subtag hash-vector fulltag-nodeheader-1 3)
+(define-subtag pool fulltag-nodeheader-1 4)
+(define-subtag weak fulltag-nodeheader-1 5)
+(define-subtag package fulltag-nodeheader-1 6)
+(define-subtag slot-vector fulltag-nodeheader-2 0)
+(define-subtag instance fulltag-nodeheader-2 1)
+(define-subtag struct fulltag-nodeheader-2  2)
+(define-subtag istruct fulltag-nodeheader-2  3)
+(define-subtag value-cell fulltag-nodeheader-2  4)
+(define-subtag xfunction fulltag-nodeheader-2 5)
+
+(define-subtag ratio fulltag-nodeheader-3 0)
+(define-subtag complex fulltag-nodeheader-3 1)
+
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "PPC-ARCH")
+  (defmacro define-storage-layout (name origin &rest cells)
+  `(progn
+     (ccl::defenum (:start ,origin :step 8)
+       ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell)) cells))
+     (defconstant ,(ccl::form-symbol name ".SIZE") ,(* (length cells)
+						       8))))
+ 
+(defmacro define-lisp-object (name tagname &rest cells)
+  `(define-storage-layout ,name ,(- (symbol-value tagname)) ,@cells))
+
+
+
+(defmacro define-fixedsized-object (name &rest non-header-cells)
+  `(progn
+     (define-lisp-object ,name fulltag-misc header ,@non-header-cells)
+     (ccl::defenum ()
+       ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell "-CELL")) non-header-cells))
+     (defconstant ,(ccl::form-symbol name ".ELEMENT-COUNT") ,(length non-header-cells))))
+
+
+
+
+
+
+
+(defconstant misc-header-offset (- fulltag-misc))
+(defconstant misc-subtag-offset (+ misc-header-offset 7 ))
+(defconstant misc-data-offset (+ misc-header-offset 8))
+(defconstant misc-dfloat-offset (+ misc-header-offset 8))
+
+
+
+(define-subtag single-float fulltag-imm-0 0)
+
+(define-subtag character fulltag-imm-1 0)
+
+;;; FULLTAG-IMM-2 is unused, so the only type with lisptag (3-bit tag)
+;;; TAG-IMM-0 should be SINGLE-FLOAT.
+
+(define-subtag unbound fulltag-imm-3 0)
+(defconstant unbound-marker subtag-unbound)
+(defconstant undefined unbound-marker)
+(define-subtag slot-unbound fulltag-imm-3 1)
+(defconstant slot-unbound-marker subtag-slot-unbound)
+(define-subtag illegal fulltag-imm-3 2)
+(defconstant illegal-marker subtag-illegal)
+
+(define-subtag no-thread-local-binding fulltag-imm-3 3)
+(define-subtag forward-marker fulltag-imm-3 7)
+
+
+(defconstant max-64-bit-constant-index (ash (+ #x7fff ppc64::misc-dfloat-offset) -3))
+(defconstant max-32-bit-constant-index (ash (+ #x7fff ppc64::misc-data-offset) -2))
+(defconstant max-16-bit-constant-index (ash (+ #x7fff ppc64::misc-data-offset) -1))
+(defconstant max-8-bit-constant-index (+ #x7fff ppc64::misc-data-offset))
+(defconstant max-1-bit-constant-index (ash (+ #x7fff ppc64::misc-data-offset) 5))
+
+
+; The objects themselves look something like this:
+
+; Order of CAR and CDR doesn't seem to matter much - there aren't
+; too many tricks to be played with predecrement/preincrement addressing.
+; Keep them in the confusing MCL 3.0 order, to avoid confusion.
+(define-lisp-object cons fulltag-cons 
+  cdr 
+  car)
+
+
+(define-fixedsized-object ratio
+  numer
+  denom)
+
+;;; It's slightly easier (for bootstrapping reasons)
+;;; to view a DOUBLE-FLOAT as being UVECTOR with 2 32-bit elements
+;;; (rather than 1 64-bit element).
+
+(defconstant double-float.value misc-data-offset)
+(defconstant double-float.value-cell 0)
+(defconstant double-float.val-high double-float.value)
+(defconstant double-float.val-high-cell double-float.value-cell)
+(defconstant double-float.val-low (+ double-float.value 4))
+(defconstant double-float.val-low-cell 1)
+(defconstant double-float.element-count 2)
+(defconstant double-float.size 16)
+
+(define-fixedsized-object complex
+  realpart
+  imagpart
+)
+
+
+; There are two kinds of macptr; use the length field of the header if you
+; need to distinguish between them
+(define-fixedsized-object macptr
+  address
+  domain
+  type
+)
+
+(define-fixedsized-object xmacptr
+  address
+  domain
+  type
+  flags
+  link
+)
+
+; Catch frames go on the tstack; they point to a minimal lisp-frame
+; on the cstack.  (The catch/unwind-protect PC is on the cstack, where
+; the GC expects to find it.)
+(define-fixedsized-object catch-frame
+  catch-tag                             ; #<unbound> -> unwind-protect, else catch
+  link                                  ; tagged pointer to next older catch frame
+  mvflag                                ; 0 if single-value, 1 if uwp or multiple-value
+  csp                                   ; pointer to control stack
+  db-link                               ; value of dynamic-binding link on thread entry.
+  save-save7                            ; saved registers
+  save-save6
+  save-save5
+  save-save4
+  save-save3
+  save-save2
+  save-save1
+  save-save0
+  xframe                                ; exception-frame link
+  tsp-segment                           ; mostly padding, for now.
+)
+
+(define-fixedsized-object lock
+  _value                                ;finalizable pointer to kernel object
+  kind                                  ; '0 = recursive-lock, '1 = rwlock
+  writer				;tcr of owning thread or 0
+  name
+  whostate
+  whostate-2
+  )
+
+
+
+(define-fixedsized-object symbol
+  pname
+  vcell
+  fcell
+  package-predicate
+  flags
+  plist
+  binding-index
+)
+
+
+(defconstant t-offset (- symbol.size))
+
+
+
+
+(define-fixedsized-object vectorH
+  logsize                               ; fillpointer if it has one, physsize otherwise
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+)
+
+(define-lisp-object arrayH fulltag-misc
+  header                                ; subtag = subtag-arrayH
+  rank                                  ; NEVER 1
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0  
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+ ;; Dimensions follow
+)
+
+(defconstant arrayH.rank-cell 0)
+(defconstant arrayH.physsize-cell 1)
+(defconstant arrayH.data-vector-cell 2)
+(defconstant arrayH.displacement-cell 3)
+(defconstant arrayH.flags-cell 4)
+(defconstant arrayH.dim0-cell 5)
+
+(defconstant arrayH.flags-cell-bits-byte (byte 8 0))
+(defconstant arrayH.flags-cell-subtag-byte (byte 8 8))
+
+
+(define-fixedsized-object value-cell
+  value)
+
+
+;;; The kernel uses these (rather generically named) structures
+;;; to keep track of various memory regions it (or the lisp) is
+;;; interested in.
+
+
+(define-storage-layout area 0
+  pred                                  ; pointer to preceding area in DLL
+  succ                                  ; pointer to next area in DLL
+  low                                   ; low bound on area addresses
+  high                                  ; high bound on area addresses.
+  active                                ; low limit on stacks, high limit on heaps
+  softlimit                             ; overflow bound
+  hardlimit                             ; another one
+  code                                  ; an area-code; see below
+  markbits                              ; bit vector for GC
+  ndnodes                               ; "active" size of dynamic area or stack
+  older                                 ; in EGC sense
+  younger                               ; also for EGC
+  h                                     ; Handle or null pointer
+  softprot                              ; protected_area structure pointer
+  hardprot                              ; another one.
+  owner                                 ; fragment (library) which "owns" the area
+  refbits                               ; bitvector for intergenerational refernces
+  threshold                             ; for egc
+  gc-count                              ; generational gc count.
+  static-dnodes                         ; for honsing. etc
+  static-used                           ; bitvector
+)
+
+
+
+
+
+(define-storage-layout protected-area 0
+  next
+  start                                 ; first byte (page-aligned) that might be protected
+  end                                   ; last byte (page-aligned) that could be protected
+  nprot                                 ; Might be 0
+  protsize                              ; number of bytes to protect
+  why)
+
+(defconstant tcr-bias 0)
+
+(define-storage-layout tcr (- tcr-bias)
+  prev					; in doubly-linked list 
+  next					; in doubly-linked list
+  single-float-convert			; per-thread scratch space.
+  lisp-fpscr-high
+  db-link				; special binding chain head 
+  catch-top				; top catch frame 
+  save-vsp				; VSP when in foreign code 
+  save-tsp				; TSP when in foreign code 
+  cs-area				; cstack area pointer 
+  vs-area				; vstack area pointer 
+  ts-area				; tstack area pointer 
+  cs-limit				; cstack overflow limit
+  total-bytes-allocated-high
+  log2-allocation-quantum		; unboxed
+  interrupt-pending			; fixnum
+  xframe				; exception frame linked list
+  errno-loc				; thread-private, maybe
+  ffi-exception				; fpscr bits from ff-call.
+  osid					; OS thread id 
+  valence				; odd when in foreign code 
+  foreign-exception-status
+  native-thread-info
+  native-thread-id
+  last-allocptr
+  save-allocptr
+  save-allocbase
+  reset-completion
+  activate
+  suspend-count
+  suspend-context
+  pending-exception-context
+  suspend				; semaphore for suspension notify 
+  resume				; sempahore for resumption notify
+  flags					; foreign, being reset, ...
+  gc-context
+  termination-semaphore
+  unwinding
+  tlb-limit
+  tlb-pointer
+  shutdown-count
+  safe-ref-address
+)
+
+(defconstant interrupt-level-binding-index (ash 1 fixnumshift))
+
+(defconstant tcr.lisp-fpscr-low (+ tcr.lisp-fpscr-high 4))
+(defconstant tcr.total-bytes-allocated-low (+ tcr.total-bytes-allocated-high 4))
+
+(define-storage-layout lockptr 0
+  avail
+  owner
+  count
+  signal
+  waiting
+  malloced-ptr
+  spinlock)
+
+(define-storage-layout rwlock 0
+  spin
+  state
+  blocked-writers
+  blocked-readers
+  writer
+  reader-signal
+  writer-signal
+  malloced-ptr
+  )
+
+;;; For the eabi port: mark this stack frame as Lisp's (since EABI
+;;; foreign frames can be the same size as a lisp frame.)
+
+
+(ppc64::define-storage-layout lisp-frame 0
+  backlink
+  savefn
+  savelr
+  savevsp
+)
+
+(ppc64::define-storage-layout c-frame 0
+  backlink
+  crsave
+  savelr
+  unused-1
+  unused-2
+  savetoc
+  param0
+  param1
+  param2
+  param3
+  param4
+  param5
+  param6
+  param7
+)
+
+(defconstant c-frame.minsize c-frame.size)
+
+(defmacro define-header (name element-count subtag)
+  `(defconstant ,name (logior (ash ,element-count num-subtag-bits) ,subtag)))
+
+(define-header double-float-header double-float.element-count subtag-double-float)
+;;; We could possibly have a one-digit bignum header when dealing
+;;; with "small bignums" in some bignum code.  Like other cases of
+;;; non-normalized bignums, they should never escape from the lab.
+(define-header one-digit-bignum-header 1 subtag-bignum)
+(define-header two-digit-bignum-header 2 subtag-bignum)
+(define-header three-digit-bignum-header 3 subtag-bignum)
+(define-header four-digit-bignum-header 4 subtag-bignum)
+(define-header five-digit-bignum-header 5 subtag-bignum)
+(define-header symbol-header symbol.element-count subtag-symbol)
+(define-header value-cell-header value-cell.element-count subtag-value-cell)
+(define-header macptr-header macptr.element-count subtag-macptr)
+
+
+(defconstant yield-syscall
+  #+darwinppc-target -60
+  #+linuxppc-target #$__NR_sched_yield)
+)
+)
+
+
+
+
+
+
+(defun %kernel-global (sym)
+  (let* ((pos (position sym ppc::*ppc-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ symbol.size fulltag-misc (* (1+ pos) word-size-in-bytes)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+(defmacro kernel-global (sym)
+  (let* ((pos (position sym ppc::*ppc-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ symbol.size fulltag-misc (* (1+ pos) word-size-in-bytes)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+;;; The kernel imports things that are defined in various other
+;;; libraries for us.  The objects in question are generally
+;;; fixnum-tagged; the entries in the "kernel-imports" vector are 8
+;;; bytes apart.
+(ccl::defenum (:prefix "KERNEL-IMPORT-" :start 0 :step word-size-in-bytes)
+  fd-setsize-bytes
+  do-fd-set
+  do-fd-clr
+  do-fd-is-set
+  do-fd-zero
+  MakeDataExecutable
+  GetSharedLibrary
+  FindSymbol
+  malloc
+  free
+  jvm-init
+  tcr-frame-ptr
+  register-xmacptr-dispose-function
+  open-debug-output
+  get-r-debug
+  restore-soft-stack-limit
+  egc-control
+  lisp-bug
+  NewThread
+  YieldToThread
+  DisposeThread
+  ThreadCurrentStackSpace
+  usage-exit
+  save-fp-context
+  restore-fp-context
+  put-altivec-registers
+  get-altivec-registers
+  new-semaphore
+  wait-on-semaphore
+  signal-semaphore
+  destroy-semaphore
+  new-recursive-lock
+  lock-recursive-lock
+  unlock-recursive-lock
+  destroy-recursive-lock
+  suspend-other-threads
+  resume-other-threads
+  suspend-tcr
+  resume-tcr
+  rwlock-new
+  rwlock-destroy
+  rwlock-rlock
+  rwlock-wlock
+  rwlock-unlock
+  recursive-lock-trylock
+  foreign-name-and-offset
+  lisp-read
+  lisp-write
+  lisp-open
+  lisp-fchmod
+  lisp-lseek
+  lisp-close
+  lisp-ftruncate
+  lisp-stat
+  lisp-fstat
+  lisp-futex
+  lisp-opendir
+  lisp-readdir
+  lisp-closedir
+  lisp-pipe
+  lisp-gettimeofday
+  lisp-sigexit
+)
+
+(defmacro nrs-offset (name)
+  (let* ((pos (position name ppc::*ppc-nilreg-relative-symbols* :test #'eq)))
+    (if pos (* (1- pos) symbol.size))))
+
+(defconstant canonical-nil-value (+ #x3000 symbol.size fulltag-misc))
+
+
+(defconstant reservation-discharge #x2008)
+
+(defparameter *ppc64-target-uvector-subtags*
+  `((:bignum . ,subtag-bignum)
+    (:ratio . ,subtag-ratio)
+    (:single-float . ,subtag-single-float)
+    (:double-float . ,subtag-double-float)
+    (:complex . ,subtag-complex  )
+    (:symbol . ,subtag-symbol)
+    (:function . ,subtag-function )
+    (:code-vector . ,subtag-code-vector)
+    (:xcode-vector . ,subtag-xcode-vector)
+    (:macptr . ,subtag-macptr )
+    (:catch-frame . ,subtag-catch-frame)
+    (:struct . ,subtag-struct )    
+    (:istruct . ,subtag-istruct )
+    (:pool . ,subtag-pool )
+    (:population . ,subtag-weak )
+    (:hash-vector . ,subtag-hash-vector )
+    (:package . ,subtag-package )
+    (:value-cell . ,subtag-value-cell)
+    (:instance . ,subtag-instance )
+    (:lock . ,subtag-lock )
+    (:basic-stream . ,subtag-basic-stream)
+    (:slot-vector . ,subtag-slot-vector)
+    (:simple-string . ,subtag-simple-base-string )
+    (:bit-vector . ,subtag-bit-vector )
+    (:signed-8-bit-vector . ,subtag-s8-vector )
+    (:unsigned-8-bit-vector . ,subtag-u8-vector )
+    (:signed-16-bit-vector . ,subtag-s16-vector )
+    (:unsigned-16-bit-vector . ,subtag-u16-vector )
+    (:signed-32-bit-vector . ,subtag-s32-vector )
+    (:unsigned-32-bit-vector . ,subtag-u32-vector )
+    (:fixnum-vector . ,subtag-fixnum-vector)
+    (:signed-64-bit-vector . ,subtag-s64-vector)
+    (:unsigned-64-bit-vector . ,subtag-u64-vector)    
+    (:single-float-vector . ,subtag-single-float-vector)
+    (:double-float-vector . ,subtag-double-float-vector )
+    (:simple-vector . ,subtag-simple-vector )
+    (:vector-header . ,subtag-vectorH)
+    (:array-header . ,subtag-arrayH)))
+
+;;; This should return NIL unless it's sure of how the indicated
+;;; type would be represented (in particular, it should return
+;;; NIL if the element type is unknown or unspecified at compile-time.
+(defun ppc64-array-type-name-from-ctype (ctype)
+  (when (typep ctype 'ccl::array-ctype)
+    (let* ((element-type (ccl::array-ctype-element-type ctype)))
+      (typecase element-type
+        (ccl::class-ctype
+         (let* ((class (ccl::class-ctype-class element-type)))
+           (if (or (eq class ccl::*character-class*)
+                   (eq class ccl::*base-char-class*)
+                   (eq class ccl::*standard-char-class*))
+             :simple-string
+             :simple-vector)))
+        (ccl::numeric-ctype
+         (if (eq (ccl::numeric-ctype-complexp element-type) :complex)
+           :simple-vector
+           (case (ccl::numeric-ctype-class element-type)
+             (integer
+              (let* ((low (ccl::numeric-ctype-low element-type))
+                     (high (ccl::numeric-ctype-high element-type)))
+                (cond ((or (null low) (null high))
+                       :simple-vector)
+                      ((and (>= low 0) (<= high 1))
+                       :bit-vector)
+                      ((and (>= low 0) (<= high 255))
+                       :unsigned-8-bit-vector)
+                      ((and (>= low 0) (<= high 65535))
+                       :unsigned-16-bit-vector)
+                      ((and (>= low 0) (<= high #xffffffff))
+                       :unsigned-32-bit-vector)
+                      ((and (>= low 0) (<= high #xffffffffffffffff))
+                       :unsigned-64-bit-vector)
+                      ((and (>= low -128) (<= high 127))
+                       :signed-8-bit-vector)
+                      ((and (>= low -32768) (<= high 32767))
+                       :signed-16-bit-vector)
+                      ((and (>= low (ash -1 31)) (<= high (1- (ash 1 31))))
+                       :signed-32-bit-vector)
+                      ((and (>= low target-most-negative-fixnum)
+                            (<= high target-most-positive-fixnum))
+                       :fixnum-vector)
+                      ((and (>= low (ash -1 63)) (<= high (1- (ash 1 63))))
+                       :signed-64-bit-vector)
+                      (t :simple-vector))))
+             (float
+              (case (ccl::numeric-ctype-format element-type)
+                ((double-float long-float) :double-float-vector)
+                ((single-float short-float) :single-float-vector)
+                (t :simple-vector)))
+             (t :simple-vector))))
+        (ccl::unknown-ctype)
+        (ccl::named-ctype
+         (if (eq element-type ccl::*universal-type*)
+           :simple-vector))
+        (t)))))
+
+(defun ppc64-misc-byte-count (subtag element-count)
+  (declare (fixnum subtag))
+  (if (= lowtag-nodeheader (logand subtag lowtagmask))
+    (ash element-count 3)
+    (case (logand subtag fulltagmask)
+      (#.ivector-class-64-bit (ash element-count 3))
+      (#.ivector-class-32-bit (ash element-count 2))
+      (#.ivector-class-8-bit element-count)
+      (t
+       (if (= subtag subtag-bit-vector)
+         (ash (+ 7 element-count) -3)
+         (ash element-count 1))))))
+
+(defparameter *ppc64-target-arch*
+  (arch::make-target-arch :name :ppc64
+                          :lisp-node-size 8
+                          :nil-value canonical-nil-value
+                          :fixnum-shift fixnumshift
+                          :most-positive-fixnum (1- (ash 1 (1- (- 64 fixnumshift))))
+                          :most-negative-fixnum (- (ash 1 (1- (- 64 fixnumshift))))
+                          :misc-data-offset misc-data-offset
+                          :misc-dfloat-offset misc-dfloat-offset
+                          :nbits-in-word 64
+                          :ntagbits 4
+                          :nlisptagbits 3
+                          :uvector-subtags *ppc64-target-uvector-subtags*
+                          :max-64-bit-constant-index max-64-bit-constant-index
+                          :max-32-bit-constant-index max-32-bit-constant-index
+                          :max-16-bit-constant-index max-16-bit-constant-index
+                          :max-8-bit-constant-index max-8-bit-constant-index
+                          :max-1-bit-constant-index max-1-bit-constant-index
+                          :word-shift 3
+                          :code-vector-prefix '(#$"CODE")
+                          :gvector-types '(:ratio :complex :symbol :function
+                                           :catch-frame :struct :istruct
+                                           :pool :population :hash-vector
+                                           :package :value-cell :instance
+                                           :lock :slot-vector
+                                           :simple-vector)
+                          :1-bit-ivector-types '(:bit-vector)
+                          :8-bit-ivector-types '(:signed-8-bit-vector
+                                                 :unsigned-8-bit-vector)
+                          :16-bit-ivector-types '(:signed-16-bit-vector
+                                                  :unsigned-16-bit-vector)
+                          :32-bit-ivector-types '(:signed-32-bit-vector
+                                                  :unsigned-32-bit-vector
+                                                  :single-float-vector
+                                                  :double-float
+                                                  :bignum
+                                                  :simple-string)
+                          :64-bit-ivector-types '(:double-float-vector
+                                                  :unsigned-64-bit-vector
+                                                  :signed-64-bit-vector
+                                                  :fixnum-vector)
+                          :array-type-name-from-ctype-function
+                          #'ppc64-array-type-name-from-ctype
+                          :package-name "PPC64"
+                          :t-offset t-offset
+                          :array-data-size-function #'ppc64-misc-byte-count
+                          :numeric-type-name-to-typecode-function
+                          #'(lambda (type-name)
+                              (ecase type-name
+                                (fixnum tag-fixnum)
+                                (bignum subtag-bignum)
+                                ((short-float single-float) subtag-single-float)
+                                ((long-float double-float) subtag-double-float)
+                                (ratio subtag-ratio)
+                                (complex subtag-complex)))
+                                                    :subprims-base ppc::*ppc-subprims-base*
+                          :subprims-shift ppc::*ppc-subprims-shift*
+                          :subprims-table ppc::*ppc-subprims*
+                          :primitive->subprims `(((0 . 23) . ,(ccl::%subprim-name->offset '.SPbuiltin-plus ppc::*ppc-subprims*)))
+                          :unbound-marker-value unbound-marker
+                          :slot-unbound-marker-value slot-unbound-marker
+                          :fixnum-tag tag-fixnum
+                          :single-float-tag subtag-single-float
+                          :single-float-tag-is-subtag nil
+                          :double-float-tag subtag-double-float
+                          :cons-tag fulltag-cons
+                          :null-tag subtag-symbol
+                          :symbol-tag subtag-symbol
+                          :symbol-tag-is-subtag t
+                          :function-tag subtag-function
+                          :function-tag-is-subtag t
+                          :big-endian t
+                          :misc-subtag-offset misc-subtag-offset
+                          :car-offset cons.car
+                          :cdr-offset cons.cdr
+                          :subtag-char subtag-character
+                          :charcode-shift charcode-shift
+                          :fulltagmask fulltagmask
+                          :fulltag-misc fulltag-misc
+                          :char-code-limit #x110000
+                          ))
+
+;;; arch macros
+(defmacro defppc64archmacro (name lambda-list &body body)
+  `(arch::defarchmacro :ppc64 ,name ,lambda-list ,@body))
+
+(defppc64archmacro ccl::%make-sfloat ()
+  (error "~s shouldn't be used in code targeting :PPC64" 'ccl::%make-sfloat))
+
+(defppc64archmacro ccl::%make-dfloat ()
+  `(ccl::%alloc-misc ppc64::double-float.element-count ppc64::subtag-double-float))
+
+(defppc64archmacro ccl::%numerator (x)
+  `(ccl::%svref ,x ppc64::ratio.numer-cell))
+
+(defppc64archmacro ccl::%denominator (x)
+  `(ccl::%svref ,x ppc64::ratio.denom-cell))
+
+(defppc64archmacro ccl::%realpart (x)
+  `(ccl::%svref ,x ppc64::complex.realpart-cell))
+                    
+(defppc64archmacro ccl::%imagpart (x)
+  `(ccl::%svref ,x ppc64::complex.imagpart-cell))
+
+;;;
+(defppc64archmacro ccl::%get-single-float-from-double-ptr (ptr offset)
+ `(ccl::%double-float->short-float (ccl::%get-double-float ,ptr ,offset)))
+
+(defppc64archmacro ccl::codevec-header-p (word)
+  `(eql ,word #$"CODE"))
+
+;;;
+
+(defppc64archmacro ccl::immediate-p-macro (thing)
+  (let* ((tag (gensym)))
+    `(let* ((,tag (ccl::lisptag ,thing)))
+      (declare (fixnum ,tag))
+      (or (= ,tag ppc64::tag-fixnum)
+       (= (logand ,tag ppc64::lowtagmask) ppc64::lowtag-imm)))))
+
+(defppc64archmacro ccl::hashed-by-identity (thing)
+  (let* ((typecode (gensym)))
+    `(let* ((,typecode (ccl::typecode ,thing)))
+      (declare (fixnum ,typecode))
+      (or
+       (= ,typecode ppc64::tag-fixnum)
+       (= (logand ,typecode ppc64::lowtagmask) ppc64::lowtag-imm)
+       (= ,typecode ppc64::subtag-symbol)
+       (= ,typecode ppc64::subtag-instance)))))
+
+;;;
+(defppc64archmacro ccl::%get-kernel-global (name)
+  `(ccl::%fixnum-ref 0 (+ ,(ccl::target-nil-value)
+                        ,(%kernel-global
+                          (if (ccl::quoted-form-p name)
+                            (cadr name)
+                            name)))))
+
+(defppc64archmacro ccl::%get-kernel-global-ptr (name dest)
+  `(ccl::%setf-macptr
+    ,dest
+    (ccl::%fixnum-ref-macptr 0 (+ ,(ccl::target-nil-value)
+                                ,(%kernel-global
+                                  (if (ccl::quoted-form-p name)
+                                    (cadr name)
+                                    name))))))
+
+(defppc64archmacro ccl::%target-kernel-global (name)
+  `(ppc64::%kernel-global ,name))
+
+(defppc64archmacro ccl::lfun-vector (fn)
+  fn)
+
+(defppc64archmacro ccl::lfun-vector-lfun (lfv)
+  lfv)
+
+(defppc64archmacro ccl::area-code ()
+  area.code)
+
+(defppc64archmacro ccl::area-succ ()
+  area.succ)
+
+
+(defppc64archmacro ccl::nth-immediate (f i)
+  `(ccl::%svref ,f ,i))
+
+(defppc64archmacro ccl::set-nth-immediate (f i new)
+  `(setf (ccl::%svref ,f ,i) ,new))
+
+
+(defppc64archmacro ccl::symptr->symvector (s)
+  s)
+
+(defppc64archmacro ccl::symvector->symptr (s)
+  s)
+
+(defppc64archmacro ccl::function-to-function-vector (f)
+  f)
+
+(defppc64archmacro ccl::function-vector-to-function (v)
+  v)
+
+(defppc64archmacro ccl::with-ffcall-results ((buf) &body body)
+  (let* ((size (+ (* 8 8) (* 13 8))))
+    `(ccl::%stack-block ((,buf ,size))
+      ,@body)))
+
+(defconstant arg-check-trap-pc-limit 8)
+                              
+(provide "PPC64-ARCH")
Index: /branches/new-random/compiler/PPC/PPC64/ppc64-backend.lisp
===================================================================
--- /branches/new-random/compiler/PPC/PPC64/ppc64-backend.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC64/ppc64-backend.lisp	(revision 13309)
@@ -0,0 +1,309 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 2004, 2005 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "NXENV")
+  (require "PPCENV"))
+
+
+;;; Callbacks.  Both LinuxPPC64 and DarwinPPC64 follow something
+;;; close to the PowerOpen ABI.  LinuxPPC uses transition vectors
+;;; and a TOC, but it's not clear that we need to care about that
+;;; here.
+(defun define-ppc64-poweropen-callback (name args body env)
+  (let* ((stack-word (gensym))
+         (stack-ptr (gensym))
+         (fp-arg-regs (gensym))
+         (fp-arg-num 0)
+         (arg-names ())
+         (arg-types ())
+         (return-type :void)
+         (args args)
+         (woi nil)
+	 (monitor nil)
+         (dynamic-extent-names ())
+         (error-return nil))
+    (loop
+      (when (null args) (return))
+      (when (null (cdr args))
+        (setq return-type (car args))
+        (return))
+      (if (eq (car args) :without-interrupts)
+        (setq woi (cadr args) args (cddr args))
+	(if (eq (car args) :monitor-exception-ports)
+	  (setq monitor (cadr args) args (cddr args))
+          (if (eq (car args) :error-return)
+            (setq error-return
+                  (cadr args)                  
+                  args (cddr args))
+            (progn
+              (push (foreign-type-to-representation-type (pop args)) arg-types)
+              (push (pop args) arg-names))))))
+    (setq arg-names (nreverse arg-names)
+          arg-types (nreverse arg-types))
+    (setq return-type (foreign-type-to-representation-type return-type))
+    (when (eq return-type :void)
+      (setq return-type nil))
+    (let* ((offset 0)
+           (need-stack-pointer (or arg-names return-type error-return))
+           (lets
+             (mapcar
+	      #'(lambda (name type)
+		  (let* ((delta 8)
+			 (bias 0)
+                         (use-fp-args nil))
+		    (prog1
+			(list name
+			      `(,
+				(if (typep type 'unsigned-byte)
+				  (progn (setq delta (* 8 type)) '%inc-ptr)
+				  (ecase type
+				    (:single-float
+                                     (if (< (incf fp-arg-num) 14)
+                                       (progn
+                                         (setq use-fp-args t)
+                                         '%get-single-float-from-double-ptr)
+                                       (progn
+                                         (setq bias 4)
+                                         '%get-single-float)))
+				    (:double-float
+                                     (setq delta 8)
+                                     (if (< (incf fp-arg-num) 14)
+                                       (setq use-fp-args t))
+                                     '%get-double-float)
+				    (:signed-doubleword (setq delta 8) '%%get-signed-longlong)
+				    (:signed-fullword
+                                     (setq bias 4)
+                                     '%get-signed-long)
+				    (:signed-halfword (setq bias 6)
+                                                      '%get-signed-word)
+				    (:signed-byte (setq bias 7)
+                                                  '%get-signed-byte)
+				    (:unsigned-doubleword (setq delta 8) '%%get-unsigned-longlong)
+				    (:unsigned-fullword
+                                     (setq bias 4)
+                                     '%get-unsigned-long)
+				    (:unsigned-halfword
+                                     (setq bias 6)
+                                     '%get-unsigned-word)
+				    (:unsigned-byte
+                                     (setq bias 7)
+                                     '%get-unsigned-byte)
+				    (:address '%get-ptr)))
+				,(if use-fp-args fp-arg-regs stack-ptr)
+				,(if use-fp-args (* 8 (1- fp-arg-num))
+                                     `(+ ,offset ,bias))))
+		      (when (or (eq type :address)
+				(typep type 'unsigned-byte))
+			(push name dynamic-extent-names))
+		      (incf offset delta))))
+	      arg-names arg-types)))
+      (multiple-value-bind (body decls doc) (parse-body body env t)
+        `(progn
+           (declaim (special ,name))
+           (define-callback-function
+             (nfunction ,name
+                        (lambda (,stack-word)
+                          (declare (ignorable ,stack-word))
+                          (block ,name
+                            (with-macptrs (,@(and need-stack-pointer (list `(,stack-ptr))))
+                              ,(when need-stack-pointer
+                                 `(%setf-macptr-to-object ,stack-ptr ,stack-word))
+                              ,(defcallback-body  stack-ptr lets dynamic-extent-names
+                                                 decls body return-type error-return
+                                                 (- ppc64::c-frame.savelr ppc64::c-frame.param0)
+                                                 fp-arg-regs
+                                                 )))))
+             ,doc
+             ,woi
+	     ,monitor))))))
+
+(defun defcallback-body-ppc64-poweropen (stack-ptr lets dynamic-extent-names decls body return-type error-return error-delta  fp-arg-ptr)
+  (let* ((result (gensym))
+         (result-ptr (case return-type
+                   ((:single-float :double-float) fp-arg-ptr)
+                   (t stack-ptr)))
+         (condition-name (if (atom error-return) 'error (car error-return)))
+         (error-return-function (if (atom error-return) error-return (cadr error-return)))
+         (body
+   	  `(with-macptrs ((,fp-arg-ptr (%get-ptr ,stack-ptr (- ppc64::c-frame.unused-1 ppc64::c-frame.param0))))
+            (declare (ignorable ,fp-arg-ptr))
+            (let ,lets
+              (declare (dynamic-extent ,@dynamic-extent-names))
+              ,@decls
+
+              (let ((,result (progn ,@body)))
+                (declare (ignorable ,result))
+                ,@(progn
+                   ;; Coerce SINGLE-FLOAT result to DOUBLE-FLOAT
+                   (when (eq return-type :single-float)
+                     (setq result `(float ,result 0.0d0)))
+                   nil)
+
+                ,(when return-type
+                       `(setf (,
+                               (case return-type
+                                 (:address '%get-ptr)
+                                 (:signed-doubleword '%%get-signed-longlong)
+                                 (:unsigned-doubleword '%%get-unsigned-longlong)
+                                 ((:double-float :single-float) '%get-double-float)
+                                 (t '%%get-signed-longlong )) ,result-ptr 0) ,result)))))))
+    (if error-return
+      (let* ((cond (gensym)))
+        `(handler-case ,body
+          (,condition-name (,cond) (,error-return-function ,cond ,stack-ptr (%inc-ptr ,stack-ptr ,error-delta)))))
+      body)))
+
+(defvar *ppc64-vinsn-templates* (make-hash-table :test #'eq))
+
+
+
+(defvar *known-ppc64-backends* ())
+
+
+#+linuxppc-target
+(defvar *linuxppc64-backend*
+  (make-backend :lookup-opcode #'lookup-ppc-opcode
+		:lookup-macro #'ppc::ppc-macro-function
+		:lap-opcodes ppc::*ppc-opcodes*
+                :define-vinsn 'define-ppc-vinsn
+                :platform-syscall-mask (logior platform-os-linux platform-cpu-ppc)                
+                
+		:p2-dispatch *ppc2-specials*
+		:p2-vinsn-templates *ppc64-vinsn-templates*
+		:p2-template-hash-name '*ppc64-vinsn-templates*
+		:p2-compile 'ppc2-compile
+		:target-specific-features
+		'(:powerpc :ppc-target :poweropen-target :linux-target :linuxppc-target :ppc64-target :64-bit-target :big-endian-target)
+		:target-fasl-pathname (make-pathname :type "p64fsl")
+		:target-platform (logior platform-cpu-ppc
+                                         platform-os-linux
+                                         platform-word-size-64)
+		:target-os :linuxppc
+		:name :linuxppc64
+		:target-arch-name :ppc64
+		:target-foreign-type-data nil
+                :target-arch ppc64::*ppc64-target-arch*
+                :define-callback 'define-ppc64-poweropen-callback
+                :defcallback-body 'defcallback-body-ppc64-poweropen
+                ))
+
+
+#+darwinppc-target
+(defvar *darwinppc64-backend*
+  (make-backend :lookup-opcode #'lookup-ppc-opcode
+		:lookup-macro #'ppc::ppc-macro-function
+		:lap-opcodes ppc::*ppc-opcodes*
+                :define-vinsn 'define-ppc-vinsn
+                :platform-syscall-mask (logior platform-os-darwin platform-cpu-ppc)                
+                
+		:p2-dispatch *ppc2-specials*
+		:p2-vinsn-templates *ppc64-vinsn-templates*
+		:p2-template-hash-name '*ppc64-vinsn-templates*
+		:p2-compile 'ppc2-compile
+		:target-specific-features
+		'(:powerpc :ppc-target :darwin-target :darwinppc-target :ppc64-target :64-bit-target :big-endian-target)
+		:target-fasl-pathname (make-pathname :type "d64fsl")
+		:target-platform (logior platform-cpu-ppc
+                                         platform-os-darwin
+                                         platform-word-size-64)
+		:target-os :darwinppc
+		:name :darwinppc64
+		:target-arch-name :ppc64
+		:target-foreign-type-data nil
+                :target-arch ppc64::*ppc64-target-arch*
+                :define-callback 'define-ppc64-poweropen-callback
+                :defcallback-body 'defcallback-body-ppc64-poweropen))
+
+#+linuxppc-target
+(pushnew *linuxppc64-backend* *known-ppc64-backends* :key #'backend-name)
+
+
+#+darwinppc-target
+(pushnew *darwinppc64-backend* *known-ppc64-backends* :key #'backend-name)
+
+(defvar *ppc64-backend* (car *known-ppc64-backends*))
+
+(defun fixup-ppc64-backend ()
+  (dolist (b *known-ppc64-backends*)
+    (setf (backend-lap-opcodes b) ppc::*ppc-opcodes*
+	  (backend-p2-dispatch b) *ppc2-specials*
+	  (backend-p2-vinsn-templates b)  *ppc64-vinsn-templates*)
+    (or (backend-lap-macros b) (setf (backend-lap-macros b)
+                                     (make-hash-table :test #'equalp)))))
+
+
+
+(fixup-ppc64-backend)
+
+#+ppc64-target
+(setq *host-backend* *ppc64-backend* *target-backend* *ppc64-backend*)
+#-ppc64-target
+(unless (backend-target-foreign-type-data *ppc64-backend*)
+  (let* ((ftd (make-ftd
+               :interface-db-directory
+               #+darwinppc-target "ccl:darwin-headers64;"
+               #+linuxppc-target "ccl:headers64;"
+               :interface-package-name
+               #+darwinppc-target "DARWIN64"
+               #+linuxppc-target "LINUX64"
+               :attributes
+               #+darwinppc-target
+               '(:signed-char t
+                 :struct-by-value t
+                 :struct-return-in-registers t
+                 :struct-return-explicit t
+                 :struct-by-value-by-field t
+                 :prepend-underscores t
+                 :bits-per-word  64)
+               #+linuxppc-target
+               '(:bits-per-word  64)
+               :ff-call-expand-function
+               #+linuxppc-target
+               'linux64::expand-ff-call
+               #+darwinppc-target
+               'darwin64::expand-ff-call
+               :ff-call-struct-return-by-implicit-arg-function
+               #+linuxppc-target
+               linux64::record-type-returns-structure-as-first-arg
+               #+darwinppc-target
+               darwin64::record-type-returns-structure-as-first-arg
+               :callback-bindings-function
+               #+linuxppc-target
+               linux64::generate-callback-bindings
+               #+darwinppc-target
+               darwin64::generate-callback-bindings
+               :callback-return-value-function
+               #+linuxppc-target
+               linux64::generate-callback-return-value
+               #+darwinppc-target
+               darwin64::generate-callback-return-value
+               )))
+    (install-standard-foreign-types ftd)
+    (use-interface-dir :libc ftd)
+    (setf (backend-target-foreign-type-data *ppc64-backend*) ftd)))
+  
+(pushnew *ppc64-backend* *known-backends* :key #'backend-name)
+
+#+ppc64-target
+(require "PPC64-VINSNS")
+
+(provide "PPC64-BACKEND")
Index: /branches/new-random/compiler/PPC/PPC64/ppc64-vinsns.lisp
===================================================================
--- /branches/new-random/compiler/PPC/PPC64/ppc64-vinsns.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/PPC64/ppc64-vinsns.lisp	(revision 13309)
@@ -0,0 +1,4032 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 2004-2005, Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "VINSN")
+  (require "PPC64-BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "PPCENV"))
+
+(defmacro define-ppc64-vinsn (vinsn-name (results args &optional temps) &body body)
+  (%define-vinsn *ppc64-backend* vinsn-name results args temps body))
+
+
+;;; Index "scaling" and constant-offset misc-ref vinsns.
+
+
+(define-ppc64-vinsn scale-node-misc-index (((dest :u64))
+                                           ((idx :imm)	; A fixnum
+                                            )
+                                           ())
+  (addi dest idx ppc64::misc-data-offset))
+
+(define-ppc64-vinsn scale-32bit-misc-index (((dest :u64))
+					    ((idx :imm)	; A fixnum
+					     )
+					    ())
+  (srdi dest idx 1)
+  (addi dest dest ppc64::misc-data-offset))
+
+(define-ppc64-vinsn scale-16bit-misc-index (((dest :u64))
+					    ((idx :imm)	; A fixnum
+					     )
+					    ())
+  (srdi dest idx 2)
+  (addi dest dest ppc64::misc-data-offset))
+
+(define-ppc64-vinsn scale-8bit-misc-index (((dest :u64))
+					   ((idx :imm) ; A fixnum
+					    )
+					   ())
+  (srdi dest idx ppc64::word-shift)
+  (addi dest dest ppc64::misc-data-offset))
+
+
+(define-ppc64-vinsn scale-64bit-misc-index (((dest :u64))
+					    ((idx :imm) ; A fixnum
+					     )
+					    ())
+  (addi dest idx ppc64::misc-data-offset))
+
+(define-ppc64-vinsn scale-1bit-misc-index (((word-index :s64)
+					    (bitnum :u8)) ; (unsigned-byte 5)
+					   ((idx :imm) ; A fixnum
+					    )
+					   )
+  (srdi word-index idx  (+ 5 ppc64::fixnum-shift))
+  (sldi word-index word-index 2)
+  (addi word-index word-index ppc64::misc-data-offset) ; Hmmm. Also one instruction, but less impressive somehow.
+  (extrwi bitnum idx 5 (- 32 (+ ppc64::fixnum-shift 5))))
+
+
+
+(define-ppc64-vinsn misc-ref-u64  (((dest :u64))
+				   ((v :lisp)
+				    (scaled-idx :u64))
+				   ())
+  (ldx dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-s64  (((dest :s64))
+				   ((v :lisp)
+				    (scaled-idx :u64))
+				   ())
+  (ldx dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-u64  (((dest :u64))
+				     ((v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (ld dest (:apply + ppc64::misc-data-offset (:apply ash idx ppc64::word-shift)) v))
+
+(define-ppc64-vinsn misc-ref-c-s64  (((dest :s64))
+				     ((v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (ld dest (:apply + ppc64::misc-data-offset (:apply ash idx ppc64::word-shift)) v))
+
+  
+(define-ppc64-vinsn misc-set-u64 (()
+                                  ((val :u64)
+                                   (v :lisp)
+                                   (scaled-idx :u64)))
+  (stdx val v scaled-idx))
+
+(define-ppc64-vinsn misc-set-c-u64 (()
+				    ((val :u64)
+				     (v :lisp)
+				     (idx :u32const)))
+  (std val (:apply + ppc64::misc-data-offset (:apply ash idx 3)) v))
+
+(define-ppc64-vinsn misc-set-s64 (()
+                                  ((val :s64)
+                                   (v :lisp)
+                                   (scaled-idx :u64)))
+  (stdx val v scaled-idx))
+
+
+(define-ppc64-vinsn misc-set-c-s64 (()
+				    ((val :s64)
+				     (v :lisp)
+				     (idx :u32const)))
+  (std val (:apply + ppc64::misc-data-offset (:apply ash idx 3)) v))
+
+(define-ppc64-vinsn misc-ref-u32  (((dest :u32))
+				   ((v :lisp)
+				    (scaled-idx :u64))
+				   ())
+  (lwzx dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-u32  (((dest :u32))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (lwz dest (:apply + ppc64::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc64-vinsn misc-ref-s32  (((dest :s32))
+				   ((v :lisp)
+				    (scaled-idx :u64))
+				   ())
+  (lwax dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-s32  (((dest :s32))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (lwa dest (:apply + ppc64::misc-data-offset (:apply ash idx 2)) v))
+
+
+(define-ppc64-vinsn misc-set-c-u32 (()
+				    ((val :u32)
+				     (v :lisp)
+				     (idx :u32const)))
+  (stw val (:apply + ppc64::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc64-vinsn misc-set-u32 (()
+				  ((val :u32)
+				   (v :lisp)
+				   (scaled-idx :u64)))
+  (stwx val v scaled-idx))
+
+(define-ppc64-vinsn misc-set-c-s32 (()
+				    ((val :s32)
+				     (v :lisp)
+				     (idx :u32const)))
+  (stw val (:apply + ppc64::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc64-vinsn misc-set-s32 (()
+				  ((val :s32)
+				   (v :lisp)
+				   (scaled-idx :u64)))
+  (stwx val v scaled-idx))
+                              
+(define-ppc64-vinsn misc-ref-single-float  (((dest :single-float))
+					    ((v :lisp)
+					     (scaled-idx :u64))
+					    ())
+  (lfsx dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-single-float  (((dest :single-float))
+					      ((v :lisp)
+					       (idx :u32const))
+					      ())
+  (lfs dest (:apply + ppc64::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc64-vinsn misc-ref-double-float  (((dest :double-float))
+					    ((v :lisp)
+					     (scaled-idx :u32))
+					    ())
+  (lfdx dest v scaled-idx))
+
+
+(define-ppc64-vinsn misc-ref-c-double-float  (((dest :double-float))
+					      ((v :lisp)
+					       (idx :u32const))
+					      ())
+  (lfd dest (:apply + ppc64::misc-dfloat-offset (:apply ash idx 3)) v))
+
+(define-ppc64-vinsn misc-set-c-double-float (((val :double-float))
+					     ((v :lisp)
+					      (idx :u32const)))
+  (stfd val (:apply + ppc64::misc-dfloat-offset (:apply ash idx 3)) v))
+
+(define-ppc64-vinsn misc-set-double-float (()
+					   ((val :double-float)
+					    (v :lisp)
+					    (scaled-idx :u32)))
+  (stfdx val v scaled-idx))
+
+(define-ppc64-vinsn misc-set-c-single-float (((val :single-float))
+					     ((v :lisp)
+					      (idx :u32const)))
+  (stfs val (:apply + ppc64::misc-data-offset (:apply ash idx 2)) v))
+
+(define-ppc64-vinsn misc-set-single-float (()
+					   ((val :single-float)
+					    (v :lisp)
+					    (scaled-idx :u32)))
+  (stfsx val v scaled-idx))
+
+
+(define-ppc64-vinsn misc-ref-u16  (((dest :u16))
+				   ((v :lisp)
+				    (scaled-idx :u64))
+				   ())
+  (lhzx dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-u16  (((dest :u16))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (lhz dest (:apply + ppc64::misc-data-offset (:apply ash idx 1)) v))
+
+(define-ppc64-vinsn misc-set-c-u16  (((val :u16))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (sth val (:apply + ppc64::misc-data-offset (:apply ash idx 1)) v))
+
+(define-ppc64-vinsn misc-set-u16 (((val :u16))
+				  ((v :lisp)
+				   (scaled-idx :s64)))
+  (sthx val v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-s16  (((dest :s16))
+				   ((v :lisp)
+				    (scaled-idx :s64))
+				   ())
+  (lhax dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-s16  (((dest :s16))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (lha dest (:apply + ppc64::misc-data-offset (:apply ash idx 1)) v))
+
+(define-ppc64-vinsn misc-set-c-s16  (((val :s16))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (sth val (:apply + ppc64::misc-data-offset (:apply ash idx 1)) v))
+
+(define-ppc64-vinsn misc-set-s16 (((val :s16))
+				  ((v :lisp)
+				   (scaled-idx :s64)))
+  (sthx val v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-u8  (((dest :u8))
+				  ((v :lisp)
+				   (scaled-idx :u64))
+				  ())
+  (lbzx dest v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-u8  (((dest :u8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (lbz dest (:apply + ppc64::misc-data-offset idx) v))
+
+(define-ppc64-vinsn misc-set-c-u8  (((val :u8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (stb val (:apply + ppc64::misc-data-offset idx) v))
+
+(define-ppc64-vinsn misc-set-u8  (((val :u8))
+				  ((v :lisp)
+				   (scaled-idx :u64))
+				  ())
+  (stbx val v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-s8  (((dest :s8))
+				  ((v :lisp)
+				   (scaled-idx :u64))
+				  ())
+  (lbzx dest v scaled-idx)
+  (extsb dest dest))
+
+(define-ppc64-vinsn misc-ref-c-s8  (((dest :s8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (lbz dest (:apply + ppc64::misc-data-offset idx) v)
+  (extsb dest dest))
+
+(define-ppc64-vinsn misc-set-c-s8  (((val :s8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (stb val (:apply + ppc64::misc-data-offset idx) v))
+
+(define-ppc64-vinsn misc-set-s8  (((val :s8))
+				  ((v :lisp)
+				   (scaled-idx :u64))
+				  ())
+  (stbx val v scaled-idx))
+
+(define-ppc64-vinsn misc-ref-c-bit (((dest :u8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (lwz dest (:apply + ppc64::misc-data-offset (:apply ash idx -5)) v)
+  (rlwinm dest dest (:apply 1+ (:apply logand idx #x1f)) 31 31))
+
+(define-ppc64-vinsn misc-ref-c-bit-fixnum (((dest :imm))
+					   ((v :lisp)
+					    (idx :u32const))
+					   ((temp :u32)))
+  (lwz temp (:apply + ppc64::misc-data-offset (:apply ash idx -5)) v)
+  (rlwinm dest 
+	  temp
+	  (:apply + 1 ppc64::fixnumshift (:apply logand idx #x1f)) 
+	  (- ppc64::least-significant-bit ppc64::fixnumshift)
+	  (- ppc64::least-significant-bit ppc64::fixnumshift)))
+
+
+(define-ppc64-vinsn misc-ref-node  (((dest :lisp))
+				    ((v :lisp)
+				     (scaled-idx :s64))
+				    ())
+  (ldx dest v scaled-idx))
+
+(define-ppc64-vinsn misc-set-node (()
+				   ((val :lisp)
+				    (v :lisp)
+				    (scaled-idx :s64))
+				   ())
+  (stdx val v scaled-idx))
+
+
+
+
+(define-ppc64-vinsn misc-ref-c-node (((dest :lisp))
+				     ((v :lisp)
+				      (idx :s16const))
+				     ())
+  (ld dest (:apply + ppc64::misc-data-offset (:apply ash idx 3)) v))
+
+(define-ppc64-vinsn misc-set-c-node (()
+				     ((val :lisp)
+				      (v :lisp)
+				      (idx :s16const))
+				     ())
+  (std val (:apply + ppc64::misc-data-offset (:apply ash idx 3)) v))
+
+
+(define-ppc64-vinsn misc-element-count-fixnum (((dest :imm))
+					       ((v :lisp))
+					       ((temp :u64)))
+  (ld temp ppc64::misc-header-offset v)
+  (srdi temp temp ppc64::num-subtag-bits)
+  (sldi dest temp ppc64::fixnumshift))
+
+(define-ppc64-vinsn check-misc-bound (()
+				      ((idx :imm)
+				       (v :lisp))
+				      ((temp :u64)))
+  (ld temp ppc64::misc-header-offset v)
+  (srdi temp temp ppc64::num-subtag-bits)
+  (sldi temp temp ppc64::fixnumshift)
+  (tdlge idx temp))
+
+(define-ppc64-vinsn 2d-unscaled-index (((dest :imm)
+                                        (dim1 :u32))
+				       ((dim1 :u32)
+                                        (i :imm)
+					(j :imm)))
+  (mulld dim1 i dim1)
+  (add dest dim1 j))
+
+
+;; dest <- (+ (* i dim1 dim2) (* j dim2) k)
+(define-ppc64-vinsn 3d-unscaled-index (((dest :imm)
+                                        (dim1 :u64)
+                                        (dim2 :u64))
+				       ((dim1 :u64)
+                                        (dim2 :u64)
+                                        (i :imm)
+					(j :imm)
+                                        (k :imm)))
+  (mulld dim1 dim1 dim2)
+  (mulld dim2 j dim2)
+  (mulld dim1 i dim1)
+  (add dim2 dim1 dim2)
+  (add dest dim2 k))
+
+
+(define-ppc64-vinsn 2d-32-scaled-index (((dest :u64))
+					((array :lisp)
+					 (i :imm)
+					 (j :imm)
+					 (dim1 :u32)))
+  (mulld dest i dim1)
+  (add dest dest j)
+  (la dest ppc64::misc-data-offset dest))
+
+(define-ppc64-vinsn 2d-dim1 (((dest :u64))
+			     ((header :lisp)))
+  (ld dest (+ ppc64::misc-data-offset (* 8 (1+ ppc64::arrayH.dim0-cell))) header)
+  (sradi dest dest ppc64::fixnumshift))
+
+(define-ppc64-vinsn 3d-dims (((dim1 :u64)
+                              (dim2 :u64))
+                             ((header :lisp)))
+  (ld dim1 (+ ppc64::misc-data-offset (* 8 (1+ ppc64::arrayH.dim0-cell))) header)
+  (ld dim2 (+ ppc64::misc-data-offset (* 8 (+ 2 ppc64::arrayH.dim0-cell))) header)
+  (sradi dim1 dim1 ppc64::fixnumshift)
+  (sradi dim2 dim2 ppc64::fixnumshift))
+
+;;; Return dim1 (unboxed)
+(define-ppc64-vinsn check-2d-bound (((dim :u64))
+				    ((i :imm)
+				     (j :imm)
+				     (header :lisp)))
+  (ld dim (+ ppc64::misc-data-offset (* 8 ppc64::arrayH.dim0-cell)) header)
+  (tdlge i dim)
+  (ld dim (+ ppc64::misc-data-offset (* 8 (1+ ppc64::arrayH.dim0-cell))) header)
+  (tdlge j dim)
+  (sradi dim dim ppc64::fixnumshift))
+
+(define-ppc64-vinsn check-3d-bound (((dim1 :u64)
+                                     (dim2 :u64))
+                                    ((i :imm)
+                                     (j :imm)
+                                     (k :imm)
+                                     (header :lisp)))
+  (ld dim1 (+ ppc64::misc-data-offset (* 8 ppc64::arrayH.dim0-cell)) header)
+  (tdlge i dim1)
+  (ld dim1 (+ ppc64::misc-data-offset (* 8 (1+ ppc64::arrayH.dim0-cell))) header)
+  (tdlge j dim1)
+  (ld dim2 (+ ppc64::misc-data-offset (* 8 (+ 2 ppc64::arrayH.dim0-cell))) header)
+  (tdlge k dim2)
+  (sradi dim1 dim1 ppc64::fixnumshift)
+  (sradi dim2 dim2 ppc64::fixnumshift))
+
+(define-ppc64-vinsn array-data-vector-ref (((dest :lisp))
+					   ((header :lisp)))
+  (ld dest ppc64::arrayH.data-vector header))
+  
+
+(define-ppc64-vinsn check-arrayH-rank (()
+				       ((header :lisp)
+					(expected :u32const))
+				       ((rank :imm)))
+  (ld rank ppc64::arrayH.rank header)
+  (tdi 27 rank (:apply ash expected ppc64::fixnumshift)))
+
+(define-ppc64-vinsn check-arrayH-flags (()
+					((header :lisp)
+					 (expected :u16const))
+					((flags :imm)
+					 (xreg :u32)))
+  (lis xreg (:apply ldb (byte 16 16) (:apply ash expected ppc64::fixnumshift)))
+  (ori xreg xreg (:apply ldb (byte 16 0) (:apply ash expected ppc64::fixnumshift)))
+  (ld flags ppc64::arrayH.flags header)
+  (td 27 flags xreg))
+
+
+(define-ppc64-vinsn trap-unless-simple-array-2 (()
+                                               ((object :lisp)
+                                                (expected-flags :u64const)
+                                                (type-error :u8const))
+                                               ((tag :u8)
+                                                (flags :u64)
+                                                (crf :crf)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :bad)
+  (lbz tag ppc64::misc-subtag-offset object)
+  (cmpdi crf tag ppc64::subtag-arrayH)
+  (bne crf :bad) 
+  (ld tag ppc64::arrayH.rank object)
+  (cmpdi crf tag (ash 2 ppc64::fixnumshift))
+  (lis tag (:apply ldb (byte 16 16) (:apply ash expected-flags ppc64::fixnumshift)))
+  (ld flags ppc64::arrayH.flags object)
+  (ori tag tag (:apply ldb (byte 16 0) (:apply ash expected-flags ppc64::fixnumshift)))
+  (bne crf :bad)
+  (cmpd crf tag flags)
+  (beq crf :good)
+  :bad
+  (uuo_interr type-error object)
+  :good)
+
+(define-ppc64-vinsn trap-unless-simple-array-3 (()
+                                               ((object :lisp)
+                                                (expected-flags :u64const)
+                                                (type-error :u8const))
+                                               ((tag :u8)
+                                                (flags :u64)
+                                                (crf :crf)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :bad)
+  (lbz tag ppc64::misc-subtag-offset object)
+  (cmpdi crf tag ppc64::subtag-arrayH)
+  (bne crf :bad) 
+  (ld tag ppc64::arrayH.rank object)
+  (cmpdi crf tag (ash 3 ppc64::fixnumshift))
+  (lis tag (:apply ldb (byte 16 16) (:apply ash expected-flags ppc64::fixnumshift)))
+  (ld flags ppc64::arrayH.flags object)
+  (ori tag tag (:apply ldb (byte 16 0) (:apply ash expected-flags ppc64::fixnumshift)))
+  (bne crf :bad)
+  (cmpd crf tag flags)
+  (beq crf :good)
+  :bad
+  (uuo_interr type-error object)
+  :good)
+
+  
+(define-ppc64-vinsn node-slot-ref  (((dest :lisp))
+				    ((node :lisp)
+				     (cellno :u32const)))
+  (ld dest (:apply + ppc64::misc-data-offset (:apply ash cellno 3)) node))
+
+
+
+(define-ppc64-vinsn  %slot-ref (((dest :lisp))
+				((instance (:lisp (:ne dest)))
+				 (index :lisp))
+				((scaled :s64)))
+  (la scaled ppc64::misc-data-offset index)
+  (ldx dest instance scaled)
+  (tdeqi dest ppc64::slot-unbound-marker))
+
+
+;;; Untagged memory reference & assignment.
+
+(define-ppc64-vinsn mem-ref-c-fullword (((dest :u32))
+					((src :address)
+					 (index :s16const)))
+  (lwz dest index src))
+
+(define-ppc64-vinsn mem-ref-c-signed-fullword (((dest :s32))
+                                               ((src :address)
+                                                (index :s16const)))
+  (lwa dest index src))
+
+(define-ppc64-vinsn mem-ref-c-doubleword (((dest :u64))
+                                          ((src :address)
+                                           (index :s16const)))
+  (ld dest index src))
+
+(define-ppc64-vinsn mem-ref-c-signed-doubleword (((dest :s64))
+                                                 ((src :address)
+                                                  (index :s16const)))
+  (ld dest index src))
+
+(define-ppc64-vinsn mem-ref-c-natural (((dest :u64))
+                                       ((src :address)
+                                        (index :s16const)))
+  (ld dest index src))
+
+(define-ppc64-vinsn mem-ref-fullword (((dest :u32))
+				      ((src :address)
+				       (index :s64)))
+  (lwzx dest src index))
+
+(define-ppc64-vinsn mem-ref-signed-fullword (((dest :s32))
+                                             ((src :address)
+                                              (index :s64)))
+  (lwax dest src index))
+
+(define-ppc64-vinsn mem-ref-doubleword (((dest :u64))
+                                        ((src :address)
+                                         (index :s64)))
+  (ldx dest src index))
+
+(define-ppc64-vinsn mem-ref-natural (((dest :u64))
+                                        ((src :address)
+                                         (index :s64)))
+  (ldx dest src index))
+
+(define-ppc64-vinsn mem-ref-signed-doubleword (((dest :s64))
+                                               ((src :address)
+                                                (index :s64)))
+  (ldx dest src index))
+
+(define-ppc64-vinsn mem-ref-c-u16 (((dest :u16))
+				   ((src :address)
+				    (index :s16const)))
+  (lhz dest index src))
+
+(define-ppc64-vinsn mem-ref-u16 (((dest :u16))
+				 ((src :address)
+				  (index :s32)))
+  (lhzx dest src index))
+
+
+(define-ppc64-vinsn mem-ref-c-s16 (((dest :s16))
+				   ((src :address)
+				    (index :s16const)))
+  (lha dest index src))
+
+(define-ppc64-vinsn mem-ref-s16 (((dest :s16))
+				 ((src :address)
+				  (index :s32)))
+  (lhax dest src index))
+
+(define-ppc64-vinsn mem-ref-c-u8 (((dest :u8))
+				  ((src :address)
+				   (index :s16const)))
+  (lbz dest index src))
+
+(define-ppc64-vinsn mem-ref-u8 (((dest :u8))
+				((src :address)
+				 (index :s32)))
+  (lbzx dest src index))
+
+(define-ppc64-vinsn mem-ref-c-s8 (((dest :s8))
+				  ((src :address)
+				   (index :s16const)))
+  (lbz dest index src)
+  (extsb dest dest))
+
+(define-ppc64-vinsn mem-ref-s8 (((dest :s8))
+				((src :address)
+				 (index :s32)))
+  (lbzx dest src index)
+  (extsb dest dest))
+
+(define-ppc64-vinsn mem-ref-c-bit (((dest :u8))
+				   ((src :address)
+				    (byte-index :s16const)
+				    (bit-shift :u8const)))
+  (lbz dest byte-index src)
+  (rlwinm dest dest bit-shift 31 31))
+
+(define-ppc64-vinsn mem-ref-c-bit-fixnum (((dest :lisp))
+					  ((src :address)
+					   (byte-index :s16const)
+					   (bit-shift :u8const))
+					  ((byteval :u8)))
+  (lbz byteval byte-index src)
+  (rlwinm dest byteval bit-shift 29 29))
+
+(define-ppc64-vinsn mem-ref-bit (((dest :u8))
+				 ((src :address)
+				  (bit-index :lisp))
+				 ((byte-index :s16)
+				  (bit-shift :u8)))
+  (srwi byte-index bit-index (+ ppc64::fixnumshift 3))
+  (extrwi bit-shift bit-index 3 27)
+  (addi bit-shift bit-shift 29)
+  (lbzx dest src byte-index)
+  (rlwnm dest dest bit-shift 31 31))
+
+
+(define-ppc64-vinsn mem-ref-bit-fixnum (((dest :lisp))
+					((src :address)
+					 (bit-index :lisp))
+					((byte-index :s16)
+					 (bit-shift :u8)))
+  (srwi byte-index bit-index (+ ppc64::fixnumshift 3))
+  (extrwi bit-shift bit-index 3 27)
+  (addi bit-shift bit-shift 27)
+  (lbzx byte-index src byte-index)
+  (rlwnm dest
+         byte-index
+         bit-shift
+         (- ppc64::least-significant-bit ppc64::fixnum-shift)
+         (- ppc64::least-significant-bit ppc64::fixnum-shift)))
+
+(define-ppc64-vinsn mem-ref-c-double-float (((dest :double-float))
+					    ((src :address)
+					     (index :s16const)))
+  (lfd dest index src))
+
+(define-ppc64-vinsn mem-ref-double-float (((dest :double-float))
+					  ((src :address)
+					   (index :s32)))
+  (lfdx dest src index))
+
+(define-ppc64-vinsn mem-set-c-double-float (()
+					    ((val :double-float)
+					     (src :address)
+					     (index :s16const)))
+  (stfd val index src))
+
+(define-ppc64-vinsn mem-set-double-float (()
+					  ((val :double-float)
+					   (src :address)
+					   (index :s32)))
+  (stfdx val src index))
+
+(define-ppc64-vinsn mem-ref-c-single-float (((dest :single-float))
+					    ((src :address)
+					     (index :s16const)))
+  (lfs dest index src))
+
+(define-ppc64-vinsn mem-ref-single-float (((dest :single-float))
+					  ((src :address)
+					   (index :s32)))
+  (lfsx dest src index))
+
+(define-ppc64-vinsn mem-set-c-single-float (()
+					    ((val :single-float)
+					     (src :address)
+					     (index :s16const)))
+  (stfs val index src))
+
+(define-ppc64-vinsn mem-set-single-float (()
+					  ((val :single-float)
+					   (src :address)
+					   (index :s32)))
+  (stfsx val src index))
+
+
+(define-ppc64-vinsn mem-set-c-doubleword (()
+                                          ((val :u64)
+                                           (src :address)
+                                           (index :s16const)))
+  (std val index src))
+
+(define-ppc64-vinsn mem-set-doubleword (()
+                                        ((val :u64)
+                                         (src :address)
+                                         (index :s64)))
+  (stdx val index src))
+
+(define-ppc64-vinsn mem-set-c-address (()
+                                       ((val :address)
+                                        (src :address)
+                                        (index :s16const)))
+  (std val index src))
+
+(define-ppc64-vinsn mem-set-address (()
+                                     ((val :address)
+                                      (src :address)
+                                      (index :s64)))
+  (stdx val src index))
+
+(define-ppc64-vinsn mem-set-c-fullword (()
+					((val :u32)
+					 (src :address)
+					 (index :s16const)))
+  (stw val index src))
+
+(define-ppc64-vinsn mem-set-fullword (()
+				      ((val :u32)
+				       (src :address)
+				       (index :s32)))
+  (stwx val src index))
+
+(define-ppc64-vinsn mem-set-c-halfword (()
+					((val :u16)
+					 (src :address)
+					 (index :s16const)))
+  (sth val index src))
+
+(define-ppc64-vinsn mem-set-halfword (()
+				      ((val :u16)
+				       (src :address)
+				       (index :s32)))
+  (sthx val src index))
+
+(define-ppc64-vinsn mem-set-c-byte (()
+				    ((val :u16)
+				     (src :address)
+				     (index :s16const)))
+  (stb val index src))
+
+(define-ppc64-vinsn mem-set-byte (()
+				  ((val :u8)
+				   (src :address)
+				   (index :s32)))
+  (stbx val src index))
+
+(define-ppc64-vinsn mem-set-c-bit-0 (()
+				     ((src :address)
+				      (byte-index :s16const)
+				      (mask-begin :u8const)
+				      (mask-end :u8const))
+				     ((val :u8)))
+  (lbz val byte-index src)
+  (rlwinm val val 0 mask-begin mask-end)
+  (stb val byte-index src))
+
+(define-ppc64-vinsn mem-set-c-bit-1 (()
+				     ((src :address)
+				      (byte-index :s16const)
+				      (mask :u8const))
+				     ((val :u8)))
+  (lbz val byte-index src)
+  (ori val val mask)
+  (stb val byte-index src))
+
+(define-ppc64-vinsn mem-set-c-bit (()
+				   ((src :address)
+				    (byte-index :s16const)
+				    (bit-index :u8const)
+				    (val :imm))
+				   ((byteval :u8)))
+  (lbz byteval byte-index src)
+  (rlwimi byteval val (:apply logand 31 (:apply - 29 bit-index)) bit-index bit-index)
+  (stb byteval byte-index src))
+
+
+(define-ppc64-vinsn mem-set-bit (()
+				 ((src :address)
+				  (bit-index :lisp)
+				  (val :lisp))
+				 ((bit-shift :u32)
+				  (mask :u32)
+				  (byte-index :u32)
+				  (crf :crf)))
+  (cmplwi crf val (ash 1 ppc64::fixnumshift))
+  (extrwi bit-shift bit-index 3 27)
+  (li mask #x80)
+  (srw mask mask bit-shift)
+  (ble+ crf :got-it)
+  (uuo_interr arch::error-object-not-bit src)
+  :got-it
+  (srwi bit-shift bit-index (+ 3 ppc64::fixnumshift))
+  (lbzx bit-shift src bit-shift)
+  (beq crf :set)
+  (andc mask bit-shift mask)
+  (b :done)
+  :set
+  (or mask bit-shift mask)
+  :done
+  (srwi bit-shift bit-index (+ 3 ppc64::fixnumshift))
+  (stbx mask src bit-shift))
+     
+;;; Tag and subtag extraction, comparison, checking, trapping ...
+
+(define-ppc64-vinsn extract-tag (((tag :u8)) 
+				 ((object :lisp)) 
+				 ())
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::nlisptagbits)))
+
+(define-ppc64-vinsn extract-tag-fixnum (((tag :imm))
+					((object :lisp)))
+  (clrlsldi tag object (- ppc64::nbits-in-word ppc64::nlisptagbits) ppc64::fixnum-shift))
+
+(define-ppc64-vinsn extract-fulltag (((tag :u8))
+				     ((object :lisp))
+				     ())
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits)))
+
+
+(define-ppc64-vinsn extract-fulltag-fixnum (((tag :imm))
+					    ((object :lisp)))
+  (clrlsldi tag object (- ppc64::nbits-in-word ppc64::ntagbits) ppc64::fixnum-shift))
+
+
+(define-ppc64-vinsn extract-typecode (((code :u8))
+				      ((object :lisp))
+				      ((crf :crf)))
+  (clrldi code object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf code ppc64::fulltag-misc)
+  (clrldi code code (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (bne crf :not-misc)
+  (lbz code ppc64::misc-subtag-offset object)
+  :not-misc)
+
+(define-ppc64-vinsn extract-typecode-fixnum (((code :imm))
+					     ((object (:lisp (:ne code))))
+					     ((crf :crf) (subtag :u8)))
+  (clrldi subtag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf subtag ppc64::fulltag-misc)
+  (clrldi subtag object (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (bne crf :not-misc)
+  (lbz subtag ppc64::misc-subtag-offset object)
+  :not-misc
+  (sldi code subtag ppc64::fixnum-shift))
+
+
+(define-ppc64-vinsn require-fixnum (()
+				    ((object :lisp))
+				    ((crf0 (:crf 0))
+				     (tag :u8)))
+  :again
+  (clrldi. tag object (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (beq+ crf0 :got-it)
+  (uuo_intcerr arch::error-object-not-fixnum object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-integer (()
+				     ((object :lisp))
+				     ((crf0 (:crf 0))
+				      (tag :u8)))
+  :again
+  (clrldi. tag object (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (beq+ crf0 :got-it)
+  (cmpdi crf0 tag ppc64::fulltag-misc)
+  (bne crf0 :no-got)
+  (lbz tag ppc64::misc-subtag-offset object)
+  (cmpdi crf0 tag ppc64::subtag-bignum)
+  (beq+ crf0 :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-integer object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-simple-vector (()
+					   ((object :lisp))
+					   ((tag :u8)
+					    (crf :crf)))
+  :again
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :no-got)
+  (lbz tag ppc64::misc-subtag-offset object)
+  (cmpdi crf tag ppc64::subtag-simple-vector)
+  (beq+ crf :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-simple-vector object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-simple-string (()
+					   ((object :lisp))
+					   ((tag :u8)
+					    (crf :crf)))
+  :again
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :no-got)
+  (lbz tag ppc64::misc-subtag-offset object)
+  (cmpdi crf tag ppc64::subtag-simple-base-string)
+  (beq+ crf :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-simple-string object)
+  (b :again)
+  :got-it)
+
+
+(define-ppc64-vinsn require-real (()
+                                  ((object :lisp))
+                                  ((crf0 (:crf 0))
+                                   (crf1 :crf)
+                                   (tag :u8)
+                                   (mask :u64)))
+  :again
+  (lis mask (ash 1 (- ppc64::subtag-double-float (+ 32 16))))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (ori mask mask (ash 1 (- ppc64::subtag-bignum 32)))
+  (cmpdi crf0 tag ppc64::fulltag-misc)
+  (sldi mask mask 32)
+  (bne crf0 :have-typecode)
+  (lbz tag ppc64::misc-subtag-offset object)
+  :have-typecode
+  (ori mask mask (logior (ash 1 ppc64::subtag-ratio)
+                         (ash 1 ppc64::fulltag-odd-fixnum)
+                         (ash 1 ppc64::subtag-single-float)
+                         (ash 1 ppc64::fulltag-even-fixnum)))
+  (cmpdi crf1 tag ppc64::subtag-double-float)
+  (srd mask mask tag)
+  (clrldi. mask mask 63)
+  (bgt crf1 :no-got)
+  (bne+ :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-real object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-number (()
+                                    ((object :lisp))
+                                    ((crf0 (:crf 0))
+                                     (crf1 :crf)
+                                     (tag :u8)
+                                     (mask :u64)))
+  :again
+  (lis mask (ash 1 (- ppc64::subtag-double-float (+ 32 16))))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (ori mask mask (ash 1 (- ppc64::subtag-bignum 32)))
+  (cmpdi crf0 tag ppc64::fulltag-misc)
+  (sldi mask mask 32)
+  (bne crf0 :have-typecode)
+  (lbz tag ppc64::misc-subtag-offset object)
+  :have-typecode
+  (ori mask mask (logior (ash 1 ppc64::subtag-ratio)
+                         (ash 1 ppc64::fulltag-odd-fixnum)
+                         (ash 1 ppc64::subtag-single-float)
+                         (ash 1 ppc64::fulltag-even-fixnum)))
+  (cmpdi crf1 tag ppc64::subtag-double-float)
+  (oris mask mask (ash 1 (- ppc64::subtag-complex 16)))
+  (srd mask mask tag)
+  (clrldi. mask mask 63)
+  (bgt crf1 :no-got)
+  (bne+ :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-number object)
+  (b :again)
+  :got-it)
+
+
+(define-ppc64-vinsn require-list (()
+				  ((object :lisp))
+				  ((tag :u8)
+				   (crfx :crf)
+				   (crfy :crf)))
+  :again
+  (cmpdi crfx object (:apply target-nil-value))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crfy tag ppc64::fulltag-cons)
+  (beq crfx :got-it)
+  (beq+ crfy :got-it)
+  (uuo_intcerr arch::error-object-not-list object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-symbol (()
+				    ((object :lisp))
+				    ((tag :u8)
+				     (crf :crf)))
+  :again
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :no-got)
+  (lbz tag ppc64::misc-subtag-offset object)
+  (cmpdi crf tag ppc64::subtag-symbol)
+  (beq+ crf :got-it)
+  :no-got
+  (uuo_intcerr arch::error-object-not-symbol object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-character (()
+				       ((object :lisp))
+				       ((tag :u8)
+					(crf :crf)))
+  :again
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::num-subtag-bits))
+  (cmpdi crf tag ppc64::subtag-character)
+  (beq+ crf :got-it)
+  (uuo_intcerr arch::error-object-not-character object)
+  (b :again)
+  :got-it)
+
+
+(define-ppc64-vinsn require-s8 (()
+				((object :lisp))
+				((crf :crf)
+				 (tag :s64)))
+  :again
+  (sldi tag object (- ppc64::nbits-in-word (+ 8 ppc64::fixnumshift)))
+  (sradi tag tag (- ppc64::nbits-in-word 8))
+  (sldi tag tag ppc64::fixnumshift)
+  (cmpd crf tag object)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-8 object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-u8 (()
+				((object :lisp))
+				((crf0 (:crf 0))
+				 (tag :u32)))
+  :again
+  ;; The bottom ppc64::fixnumshift bits and the top (- 64 (+
+  ;; ppc64::fixnumshift 8)) must all be zero.
+  (rldicr. tag object (- 64 ppc64::fixnumshift) 55)
+  (beq+ crf0 :got-it)
+  (uuo_intcerr arch::error-object-not-unsigned-byte-8 object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-s16 (()
+                                 ((object :lisp))
+                                 ((crf :crf)
+                                  (tag :s64)))
+  :again
+  (sldi tag object (- ppc64::nbits-in-word (+ 16 ppc64::fixnumshift)))
+  (sradi tag tag (- ppc64::nbits-in-word 16))
+  (sldi tag tag ppc64::fixnumshift)
+  (cmpd crf tag object)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-16 object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-u16 (()
+				((object :lisp))
+				((crf0 (:crf 0))
+				 (tag :s64)))
+  :again
+  ;; The bottom ppc64::fixnumshift bits and the top (- 64 (+
+  ;; ppc64::fixnumshift 8)) must all be zero.
+  (rldicr. tag object (- 64 ppc64::fixnumshift) 47)
+  (beq+ crf0 :got-it)
+  (uuo_intcerr arch::error-object-not-unsigned-byte-16 object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-s32 (()
+                                 ((object :lisp))
+                                 ((crf :crf)
+                                  (tag :s64)))
+  :again
+  (sldi tag object (- ppc64::nbits-in-word (+ 32 ppc64::fixnumshift)))
+  (sradi tag tag (- ppc64::nbits-in-word 32))
+  (sldi tag tag ppc64::fixnumshift)
+  (cmpd crf tag object)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-32 object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-u32 (()
+				((object :lisp))
+				((crf0 (:crf 0))
+				 (tag :s64)))
+  :again
+  ;; The bottom ppc64::fixnumshift bits and the top (- 64 (+
+  ;; ppc64::fixnumshift 32)) must all be zero.
+  (rldicr. tag object (- 64 ppc64::fixnumshift) 31)
+  (beq+ crf0 :got-it)
+  (uuo_intcerr arch::error-object-not-unsigned-byte-32 object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-s64 (()
+                                 ((object :lisp))
+                                 ((crf0 (:crf 0))
+                                  (crf1 :crf)
+                                  (tag :s64)))
+  :again
+  (clrldi. tag object (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (beq+ crf0 :got-it)
+  (cmpdi crf1 tag ppc64::fulltag-misc)
+  (bne- crf1 :bad)
+  (ld tag ppc64::misc-header-offset object)
+  (cmpdi crf0 tag ppc64::two-digit-bignum-header)
+  (beq+ crf0 :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-signed-byte-64 object)
+  (b :again)
+  :got-it)
+
+(define-ppc64-vinsn require-u64 (()
+                                 ((object :lisp))
+                                 ((crf0 (:crf 0))
+                                  (crf1 :crf)
+                                  (crf2 :crf)
+                                  (temp :u64)))
+  (clrldi. temp object (- ppc64::nbits-in-word ppc64::fixnumshift))
+  (clrldi temp object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf1 temp ppc64::fulltag-misc)
+  (sradi temp object ppc64::fixnumshift)
+  (beq crf0 :good-if-positive)
+  (bne crf1 :bad)
+  (ld temp ppc64::misc-header-offset object)
+  (cmpdi crf0 temp  ppc64::three-digit-bignum-header)
+  (cmpdi crf2 temp ppc64::two-digit-bignum-header)
+  (beq crf0 :three-digit)
+  (bne crf2 :bad)
+  ;; two-digit case.  Must be positive.
+  (ld temp ppc64::misc-data-offset object)
+  (rotldi temp temp 32)
+  :good-if-positive
+  (cmpdi crf1 temp 0)
+  (bge crf1 :good)
+  :bad
+  (uuo_interr arch::error-object-not-unsigned-byte-64 object)
+  :three-digit
+  (lwz temp (+ ppc64::misc-data-offset 8) object)
+  (cmpwi crf1 temp 0)
+  (bne crf1 :bad)
+  :good
+  )
+
+
+(define-ppc64-vinsn require-char-code (()
+                                       ((object :lisp))
+                                       ((crf0 (:crf 0))
+                                        (crf1 :crf)
+                                        (tag :u32)))
+  :again
+  (clrldi. tag object (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (lis tag (ash (ash #x110000 ppc64::fixnumshift) -16))
+  (cmpld crf1 object tag)
+  (bne crf0 :bad)
+  (blt+ crf1 :got-it)
+  :bad
+  (uuo_intcerr arch::error-object-not-mod-char-code-limit object)
+  (b :again)
+  :got-it)
+
+
+(define-ppc64-vinsn box-fixnum (((dest :imm))
+				((src :s64)))
+  (sldi dest src ppc64::fixnumshift))
+
+(define-ppc64-vinsn fixnum->signed-natural (((dest :s64))
+                                            ((src :imm)))
+  (sradi dest src ppc64::fixnumshift))
+
+(define-ppc64-vinsn fixnum->unsigned-natural (((dest :u64))
+                                              ((src :imm)))
+  (srdi dest src ppc64::fixnumshift))
+
+
+
+(define-ppc64-vinsn unbox-u64 (((dest :u64))
+                               ((src :lisp))
+                               ((crf0 (:crf 0))
+                                (crf1 :crf)
+                                (crf2 :crf)))
+  (clrldi. dest src (- ppc64::nbits-in-word ppc64::fixnumshift))
+  (clrldi dest src (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf1 dest ppc64::fulltag-misc)
+  (sradi dest src ppc64::fixnumshift)
+  (beq crf0 :good-if-positive)
+  (bne crf1 :bad)
+  (ld dest ppc64::misc-header-offset src)
+  (cmpdi crf0 dest  ppc64::three-digit-bignum-header)
+  (cmpdi crf2 dest ppc64::two-digit-bignum-header)
+  (beq crf0 :three-digit)
+  (bne crf2 :bad)
+  ;; two-digit case.  Must be positive.
+  (ld dest ppc64::misc-data-offset src)
+  (rotldi dest dest 32)
+  :good-if-positive
+  (cmpdi crf1 dest 0)
+  (bge crf1 :good)
+  :bad
+  (uuo_interr arch::error-object-not-unsigned-byte-64 src)
+  :three-digit
+  (lwz dest (+ ppc64::misc-data-offset 8) src)
+  (cmpwi crf1 dest 0)
+  (ld dest ppc64::misc-data-offset src)
+  (rotldi dest dest 32)
+  (bne crf1 :bad)
+  :good
+  )
+
+(define-ppc64-vinsn unbox-s64 (((dest :s64))
+                               ((src :lisp))
+                               ((crf0 :crf)
+                                (crf1 :crf)
+                                (tag :u64)))
+  
+  (clrldi. tag src (- ppc64::nbits-in-word ppc64::fixnumshift))
+  (clrldi tag src (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf1 tag ppc64::fulltag-misc)
+  (sradi dest src ppc64::fixnumshift)
+  (beq+ crf0 :good)
+  (beq+ crf1 :bignum)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-64 src)
+  :bignum
+  (ld tag ppc64::misc-header-offset src)
+  (ld dest ppc64::misc-data-offset src)
+  (cmpdi crf0 tag ppc64::two-digit-bignum-header)
+  (rotldi dest dest 32)
+  (bne- crf0 :bad)
+  :good
+  )
+
+;;; An object is of type (UNSIGNED-BYTE 32) iff
+;;;  a) it's of type (UNSIGNED-BYTE 32)
+;;; That pretty much narrows it down.
+  
+(define-ppc64-vinsn unbox-u32 (((dest :u32))
+			       ((src :lisp))
+			       ((crf0 (:crf 0))))
+  (rldicr. dest src (- 64 ppc64::fixnumshift) 31)
+  (srdi dest src ppc64::fixnumshift)
+  (beq crf0 :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-unsigned-byte-32 src)
+  :got-it)
+
+(define-ppc64-vinsn %unbox-u32 (((dest :u32))
+				((src :lisp)))
+  (rldicl dest src (- 64 ppc64::fixnumshift) 32))
+
+;;; an object is of type (SIGNED-BYTE 32) iff
+;;; a) it's of type (SIGNED-BYTE 32)
+;;; b) see (a).
+
+
+(define-ppc64-vinsn unbox-s32 (((dest :s32))
+			       ((src :lisp))
+			       ((crf :crf)))
+  (sldi dest src (- ppc64::nbits-in-word (+ 32 ppc64::fixnumshift)))
+  (sradi dest dest (- ppc64::nbits-in-word 32))
+  (sldi dest dest ppc64::fixnumshift)
+  (cmpd crf dest src)
+  (sradi dest src ppc64::fixnumshift)
+  (beq crf :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-32 src)
+  :got-it)
+
+
+(define-ppc64-vinsn unbox-u16 (((dest :u16))
+			       ((src :lisp))
+			       ((crf0 (:crf 0))))
+  ;; The bottom ppc64::fixnumshift bits and the top (- 31 (+
+  ;; ppc64::fixnumshift 16)) must all be zero.
+  (rldicr. dest src (- 64 ppc64::fixnumshift) 47)
+  (srdi dest src ppc64::fixnumshift)
+  (beq+ crf0 :got-it)
+  (uuo_interr arch::error-object-not-unsigned-byte-16 src)
+  :got-it)
+
+(define-ppc64-vinsn unbox-s16 (((dest :s16))
+			       ((src :lisp))
+			       ((crf :crf)))
+  (sldi dest src (- ppc64::nbits-in-word (+ 16 ppc64::fixnumshift)))
+  (sradi dest dest (- ppc64::nbits-in-word 16))
+  (sldi dest dest ppc64::fixnumshift)
+  (cmpd crf dest src)
+  (sradi dest src ppc64::fixnumshift)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-16 src)
+  :got-it)
+
+  
+  
+(define-ppc64-vinsn unbox-u8 (((dest :u8))
+			      ((src :lisp))
+			      ((crf0 (:crf 0))))
+  ;; The bottom ppc64::fixnumshift bits and the top (- 63 (+
+  ;; ppc64::fixnumshift 8)) must all be zero.
+  (rldicr. dest src (- 64 ppc64::fixnumshift) 55)
+  (srdi dest src ppc64::fixnumshift)
+  (beq+ crf0 :got-it)
+  (uuo_interr arch::error-object-not-unsigned-byte-8 src)
+  :got-it)
+
+(define-ppc64-vinsn %unbox-u8 (((dest :u8))
+			      ((src :lisp)))
+  ;; The bottom ppc64::fixnumshift bits and the top (- 63 (+
+  ;; ppc64::fixnumshift 8)) must all be zero.
+  (rldicl dest src (- 64 ppc64::fixnumshift) 56))
+
+(define-ppc64-vinsn unbox-s8 (((dest :s8))
+			      ((src :lisp))
+			      ((crf :crf)))
+  (sldi dest src (- ppc64::nbits-in-word (+ 8 ppc64::fixnumshift)))
+  (sradi dest dest (- ppc64::nbits-in-word 8))
+  (sldi dest dest ppc64::fixnumshift)
+  (cmpd crf dest src)
+  (sradi dest src ppc64::fixnumshift)
+  (beq+ crf :got-it)
+  :bad
+  (uuo_interr arch::error-object-not-signed-byte-16 src)
+  :got-it)
+
+(define-ppc64-vinsn unbox-base-char (((dest :u32))
+				     ((src :lisp))
+				     ((crf :crf)))
+  (clrldi dest src (- 64 ppc64::num-subtag-bits))
+  (cmpdi crf dest ppc64::subtag-character)
+  (srdi dest src ppc64::charcode-shift)
+  (beq+ crf :got-it)
+  (uuo_interr arch::error-object-not-character src)
+  :got-it)
+
+(define-ppc64-vinsn unbox-bit (((dest :u32))
+			       ((src :lisp))
+			       ((crf :crf)))
+  (cmplwi crf src (ash 1 ppc64::fixnumshift))
+  (srawi dest src ppc64::fixnumshift)
+  (ble+ crf :got-it)
+  (uuo_interr arch::error-object-not-bit src)
+  :got-it)
+
+(define-ppc64-vinsn unbox-bit-bit0 (((dest :u32))
+				    ((src :lisp))
+				    ((crf :crf)))
+  (cmplwi crf src (ash 1 ppc64::fixnumshift))
+  (rlwinm dest src (- 32 (1+ ppc64::fixnumshift)) 0 0)
+  (ble+ crf :got-it)
+  (uuo_interr arch::error-object-not-bit src)
+  :got-it)
+
+
+
+
+(define-ppc64-vinsn shift-right-variable-word (((dest :u32))
+					       ((src :u32)
+						(sh :u32)))
+  (srw dest src sh))
+
+;;; These vinsns are used in bit extraction operations, which
+;;; currently do 32-bit memory references on both platforms.
+(define-ppc64-vinsn u32logandc2 (((dest :u32))
+				 ((x :u32)
+				  (y :u32)))
+  (andc dest x y))
+
+(define-ppc64-vinsn u32logior (((dest :u32))
+			       ((x :u32)
+				(y :u32)))
+  (or dest x y))
+
+
+(define-ppc64-vinsn trap-unless-fixnum (()
+					((object :lisp))
+					((tag :u8)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (tdnei tag ppc64::tag-fixnum))
+
+(define-ppc64-vinsn trap-unless-character (()
+                                           ((object :lisp))
+                                           ((tag :u8)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::num-subtag-bits))
+  (tdnei tag ppc64::subtag-character))
+
+
+(define-ppc64-vinsn trap-unless-cons (()
+					((object :lisp))
+					((tag :u8)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (tdnei tag ppc64::fulltag-cons))
+
+(define-ppc64-vinsn trap-unless-list (()
+				      ((object :lisp))
+				      ((tag :u8)
+				       (crf :crf)))
+  (cmpldi crf object (:apply target-nil-value))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (beq crf :ok)
+  (tdi 3 tag ppc64::fulltag-cons)
+  :ok)
+
+(define-ppc64-vinsn trap-unless-uvector (()
+					 ((object :lisp))
+                                         ((tag :u8)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (tdnei tag ppc64::fulltag-misc))
+
+(define-ppc64-vinsn trap-unless-single-float (()
+                                              ((object :lisp))
+                                              ((tag :u8)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (tdnei tag ppc64::subtag-single-float))
+
+(define-ppc64-vinsn trap-unless-double-float (()
+                                              ((object :lisp))
+                                              ((tag :u8)
+                                               (crf :crf)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc64::misc-subtag-offset object)
+  :do-trap
+  (tdnei tag ppc64::subtag-double-float))
+
+(define-ppc64-vinsn trap-unless-array-header (()
+                                              ((object :lisp))
+                                              ((tag :u8)
+                                               (crf :crf)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc64::misc-subtag-offset object)
+  :do-trap
+  (tdnei tag ppc64::subtag-arrayH))
+
+(define-ppc64-vinsn trap-unless-macptr (()
+                                        ((object :lisp))
+                                        ((tag :u8)
+                                         (crf :crf)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc64::misc-subtag-offset object)
+  :do-trap
+  (tdnei tag ppc64::subtag-macptr))
+
+
+(define-ppc64-vinsn trap-unless-typecode= (()
+					   ((object :lisp)
+					    (tagval :u16const))
+					   ((tag :u8)
+					    (crf :crf)))
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (clrldi tag object (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (bne crf :do-trap)
+  (lbz tag ppc64::misc-subtag-offset object)
+  :do-trap
+  (tdnei tag tagval))
+  
+(define-ppc64-vinsn subtract-constant (((dest :imm))
+				       ((src :imm)
+					(const :s16const)))
+  (subi dest src const))
+
+
+
+
+;;; Bit-extraction & boolean operations
+
+
+;;; For some mind-numbing reason, IBM decided to call the most significant
+;;; bit in a 32-bit word "bit 0" and the least significant bit "bit 31"
+;;; (this despite the fact that it's essentially a big-endian architecture
+;;; (it was exclusively big-endian when this decision was made.))
+;;; We'll probably be least confused if we consistently use this backwards
+;;; bit ordering (letting things that have a "sane" bit-number worry about
+;;; it at compile-time or run-time (subtracting the "sane" bit number from
+;;; 31.))
+
+(define-ppc64-vinsn extract-variable-bit (((dest :u8))
+					  ((src :u32)
+					   (bitnum :u8))
+					  ())
+  (rotlw dest src bitnum)
+  (extrwi dest dest 1 0))
+
+
+(define-ppc64-vinsn extract-variable-bit-fixnum (((dest :imm))
+						 ((src :u32)
+						  (bitnum :u8))
+						 ((temp :u32)))
+  (rotlw temp src bitnum)
+  (rlwinm dest
+          temp 
+          (1+ ppc64::fixnumshift) 
+          (- ppc64::least-significant-bit ppc64::fixnumshift)
+          (- ppc64::least-significant-bit ppc64::fixnumshift)))
+
+
+(define-ppc64-vinsn lowbit->truth (((dest :lisp)
+                                    (bits :u64))
+                                   ((bits :u64))
+                                   ())
+  (mulli bits bits ppc64::t-offset)
+  (addi dest bits (:apply target-nil-value)))
+
+(define-ppc64-vinsn invert-lowbit (((bits :u64))
+                                   ((bits :u64))
+                                   ())
+  (xori bits bits 1))
+
+                           
+
+;;; Some of the obscure-looking instruction sequences - which map some
+;;; relation to PPC bit 31 of some register - were found by the GNU
+;;; SuperOptimizer.  Some of them use extended-precision instructions
+;;; (which may cause interlocks on some superscalar PPCs, if I
+;;; remember correctly.)  In general, sequences that GSO found that
+;;; -don't- do extended precision are longer and/or use more
+;;; temporaries.  On the 604, the penalty for using an instruction
+;;; that uses the CA bit is "at least" one cycle: it can't complete
+;;; execution until all "older" instructions have.  That's not
+;;; horrible, especially given that the alternative is usually to use
+;;; more instructions (and, more importantly, more temporaries) to
+;;; avoid using extended-precision.
+
+
+(define-ppc64-vinsn eq0->bit31 (((bits :u64))
+				((src (t (:ne bits)))))
+  (cntlzd bits src)
+  (srdi bits bits 6))			; bits = 0000...000X
+
+(define-ppc64-vinsn ne0->bit31 (((bits :u64))
+				((src (t (:ne bits)))))
+  (cntlzd bits src)
+  (sld bits src bits)
+  (srdi bits bits 63))			; bits = 0000...000X
+
+(define-ppc64-vinsn lt0->bit31 (((bits :u64))
+				((src (t (:ne bits)))))
+  (srdi bits src 63))                   ; bits = 0000...000X
+
+
+(define-ppc64-vinsn ge0->bit31 (((bits :u64))
+				((src (t (:ne bits)))))
+  (srdi bits src 63)       
+  (xori bits bits 1))                   ; bits = 0000...000X
+
+
+(define-ppc64-vinsn le0->bit31 (((bits :u64))
+				((src (t (:ne bits)))))
+  (neg bits src)
+  (orc bits bits src)
+  (srdi bits bits 63))                  ; bits = 0000...000X
+
+(define-ppc64-vinsn gt0->bit31 (((bits :u64))
+				((src (t (:ne bits)))))
+  (subi bits src 1)       
+  (nor bits bits src)
+  (srdi bits bits 63))                  ; bits = 0000...000X
+
+(define-ppc64-vinsn ne->bit31 (((bits :u64))
+			       ((x t)
+				(y t))
+			       ((temp :u64)))
+  (subf temp x y)
+  (cntlzd bits temp)
+  (sld bits temp bits)
+  (srdi bits bits 63))			; bits = 0000...000X
+
+(define-ppc64-vinsn fulltag->bit31 (((bits :u64))
+				    ((lispobj :lisp)
+				     (tagval :u8const))
+				    ())
+  (clrldi bits lispobj (- ppc64::nbits-in-word ppc64::ntagbits))
+  (subi bits bits tagval)
+  (cntlzd bits bits)
+  (srdi bits bits 6))
+
+
+(define-ppc64-vinsn eq->bit31 (((bits :u64))
+			       ((x t)
+				(y t)))
+  (subf bits x y)
+  (cntlzd bits bits)
+  (srdi bits bits 6))			; bits = 0000...000X
+
+(define-ppc64-vinsn eqnil->bit31 (((bits :u64))
+				  ((x t)))
+  (subi bits x (:apply target-nil-value))
+  (cntlzd bits bits)
+  (srdi bits bits 6))
+
+(define-ppc64-vinsn ne->bit31 (((bits :u64))
+			       ((x t)
+				(y t)))
+  (subf bits x y)
+  (cntlzd bits bits)
+  (srdi bits bits 6)
+  (xori bits bits 1))
+
+(define-ppc64-vinsn nenil->bit31 (((bits :u64))
+				  ((x t)))
+  (subi bits x (:apply target-nil-value))
+  (cntlzd bits bits)
+  (srdi bits bits 6)
+  (xori bits bits 1))
+
+(define-ppc64-vinsn lt->bit31 (((bits :u64))
+			       ((x (t (:ne bits)))
+				(y (t (:ne bits)))))
+
+  (xor bits x y)
+  (sradi bits bits 63)
+  (or bits bits x)
+  (subf bits y bits)
+  (srdi bits bits 63))			; bits = 0000...000X
+
+(define-ppc64-vinsn ltu->bit31 (((bits :u64))
+				((x :u64)
+				 (y :u64)))
+  (subfc bits y x)
+  (subfe bits bits bits)
+  (neg bits bits))
+
+(define-ppc64-vinsn le->bit31 (((bits :u64))
+			       ((x (t (:ne bits)))
+				(y (t (:ne bits)))))
+
+  (xor bits x y)
+  (sradi bits bits 63)
+  (nor bits bits y)
+  (add bits bits x)
+  (srdi bits bits 63))			; bits = 0000...000X
+
+(define-ppc64-vinsn leu->bit31  (((bits :u32))
+				 ((x :u32)
+				  (y :u32)))
+  (subfc bits x y)
+  (addze bits ppc::rzero))
+
+(define-ppc64-vinsn gt->bit31 (((bits :u32))
+			       ((x (t (:ne bits)))
+				(y (t (:ne bits)))))
+
+  (eqv bits x y)
+  (sradi bits bits 63)
+  (and bits bits x)
+  (subf bits bits y)
+  (srdi bits bits 63))			; bits = 0000...000X
+
+(define-ppc64-vinsn gtu->bit31 (((bits :u64))
+				((x :u64)
+				 (y :u64)))
+  (subfc bits x y)
+  (subfe bits bits bits)
+  (neg bits bits))
+
+(define-ppc64-vinsn ge->bit31 (((bits :u64))
+			       ((x (t (:ne bits)))
+				(y (t (:ne bits)))))
+  (eqv bits x y)
+  (sradi bits bits 63)
+  (andc bits bits x)
+  (add bits bits y)
+  (srdi bits bits 63))			; bits = 0000...000X
+
+(define-ppc64-vinsn geu->bit31 (((bits :u64))
+				((x :u64)
+				 (y :u64)))
+  (subfc bits y x)
+  (addze bits ppc::rzero))
+
+
+;;; there are big-time latencies associated with MFCR on more heavily
+;;; pipelined processors; that implies that we should avoid this like
+;;; the plague.
+;;; GSO can't find anything much quicker for LT or GT, even though
+;;; MFCR takes three cycles and waits for previous instructions to complete.
+;;; Of course, using a CR field costs us something as well.
+(define-ppc64-vinsn crbit->bit31 (((bits :u64))
+				  ((crf :crf)
+				   (bitnum :crbit))
+				  ())
+  (mfcr bits)                           ; Suffer.
+  (rlwinm bits bits (:apply + 1  bitnum (:apply ash crf 2)) 31 31)) ; bits = 0000...000X
+
+
+(define-ppc64-vinsn compare (((crf :crf))
+			     ((arg0 t)
+			      (arg1 t))
+			     ())
+  (cmpd crf arg0 arg1))
+
+(define-ppc64-vinsn compare-to-nil (((crf :crf))
+				    ((arg0 t)))
+  (cmpdi crf arg0 (:apply target-nil-value)))
+
+(define-ppc64-vinsn compare-logical (((crf :crf))
+				     ((arg0 t)
+				      (arg1 t))
+				     ())
+  (cmpld crf arg0 arg1))
+
+(define-ppc64-vinsn double-float-compare (((crf :crf))
+					  ((arg0 :double-float)
+					   (arg1 :double-float))
+					  ())
+  (fcmpo crf arg0 arg1))
+              
+
+(define-ppc64-vinsn double-float+-2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float))
+				     ((crf (:crf 4))))
+  (fadd result x y))
+
+(define-ppc64-vinsn double-float--2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float))
+				     ((crf (:crf 4))))
+  (fsub result x y))
+
+(define-ppc64-vinsn double-float*-2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float))
+				     ((crf (:crf 4))))
+  (fmul result x y))
+
+(define-ppc64-vinsn double-float/-2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float))
+				     ((crf (:crf 4))))
+  (fdiv result x y))
+
+(define-ppc64-vinsn single-float+-2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float))
+				     ((crf (:crf 4))))
+  (fadds result x y))
+
+(define-ppc64-vinsn single-float--2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float))
+				     ((crf (:crf 4))))
+  (fsubs result x y))
+
+(define-ppc64-vinsn single-float*-2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float))
+				     ((crf (:crf 4))))
+  (fmuls result x y))
+
+(define-ppc64-vinsn single-float/-2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float))
+				     ((crf (:crf 4))))
+  (fdivs result x y))
+
+
+
+(define-ppc64-vinsn compare-signed-s16const (((crf :crf))
+					     ((arg0 :imm)
+					      (imm :s16const))
+					     ())
+  (cmpdi crf arg0 imm))
+
+(define-ppc64-vinsn compare-unsigned-u16const (((crf :crf))
+					       ((arg0 :u32)
+						(imm :u16const))
+					       ())
+  (cmpldi crf arg0 imm))
+
+
+
+;;; Extract a constant bit (0-63) from src; make it be bit 63 of dest.
+;;; Bitnum is treated mod 64. (This is used in LOGBITP).
+(define-ppc64-vinsn extract-constant-ppc-bit (((dest :u64))
+					      ((src :imm)
+					       (bitnum :u16const))
+					      ())
+  (rldicl dest src (:apply + 1 bitnum) 63))
+
+
+(define-ppc64-vinsn set-constant-ppc-bit-to-variable-value (((dest :u32))
+							    ((src :u32)
+							     (bitval :u32) ; 0 or 1
+							     (bitnum :u8const)))
+  (rlwimi dest bitval (:apply - 32 bitnum) bitnum bitnum))
+
+(define-ppc64-vinsn set-constant-ppc-bit-to-1 (((dest :u32))
+					       ((src :u32)
+						(bitnum :u8const)))
+  ((:pred < bitnum 16)
+   (oris dest src (:apply ash #x8000 (:apply - bitnum))))
+  ((:pred >= bitnum 16)
+   (ori dest src (:apply ash #x8000 (:apply - (:apply - bitnum 16))))))
+
+(define-ppc64-vinsn set-constant-ppc-bit-to-0 (((dest :u32))
+					       ((src :u32)
+						(bitnum :u8const)))
+  (rlwinm dest src 0 (:apply logand #x1f (:apply 1+ bitnum)) (:apply logand #x1f (:apply 1- bitnum))))
+
+  
+(define-ppc64-vinsn insert-bit-0 (((dest :u32))
+				  ((src :u32)
+				   (val :u32)))
+  (rlwimi dest val 0 0 0))
+  
+;;; The bit number is boxed and wants to think of the
+;;; least-significant bit as 0.  Imagine that.  To turn the boxed,
+;;; lsb-0 bitnumber into an unboxed, msb-0 rotate count, we
+;;; (conceptually) unbox it, add ppc64::fixnumshift to it, subtract it
+;;; from 31, and add one.  This can also be done as "unbox and
+;;; subtract from 28", I think ...  Actually, it'd be "unbox, then
+;;; subtract from 30".
+(define-ppc64-vinsn extract-variable-non-insane-bit (((dest :u64))
+						     ((src :imm)
+						      (bit :imm))
+						     ((temp :u64)))
+  (srdi temp bit ppc64::fixnumshift)
+  (subfic temp temp (- 64 ppc64::fixnumshift))
+  (rldcl dest src temp 63))
+                                               
+;;; Operations on lists and cons cells
+
+(define-ppc64-vinsn %cdr (((dest :lisp))
+			  ((src :lisp)))
+  (ld dest ppc64::cons.cdr src))
+
+(define-ppc64-vinsn %car (((dest :lisp))
+			  ((src :lisp)))
+  (ld dest ppc64::cons.car src))
+
+(define-ppc64-vinsn %set-car (()
+			      ((cell :lisp)
+			       (new :lisp)))
+  (std new ppc64::cons.car cell))
+
+(define-ppc64-vinsn %set-cdr (()
+			      ((cell :lisp)
+			       (new :lisp)))
+  (std new ppc64::cons.cdr cell))
+
+(define-ppc64-vinsn load-adl (()
+			      ((n :u32const)))
+  (lis ppc::nargs (:apply ldb (byte 16 16) n))
+  (ori ppc::nargs ppc::nargs (:apply ldb (byte 16 0) n)))
+                            
+(define-ppc64-vinsn set-nargs (()
+			       ((n :s16const)))
+  (li ppc::nargs (:apply ash n ppc64::word-shift)))
+
+(define-ppc64-vinsn scale-nargs (()
+				 ((nfixed :s16const)))
+  ((:pred > nfixed 0)
+   (la ppc::nargs (:apply - (:apply ash nfixed ppc64::word-shift)) ppc::nargs)))
+                           
+
+
+(define-ppc64-vinsn (vpush-register :push :node :vsp)
+    (()
+     ((reg :lisp)))
+  (stdu reg -8 ppc::vsp))
+
+(define-ppc64-vinsn (vpush-register-arg :push :node :vsp :outgoing-argument)
+    (()
+     ((reg :lisp)))
+  (stdu reg -8 ppc::vsp))
+
+(define-ppc64-vinsn (vpop-register :pop :node :vsp)
+    (((dest :lisp))
+     ())
+  (ld dest 0 ppc::vsp)
+  (la ppc::vsp ppc64::word-size-in-bytes ppc::vsp))
+
+
+(define-ppc64-vinsn copy-node-gpr (((dest :lisp))
+				   ((src :lisp)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (mr dest src)))
+
+(define-ppc64-vinsn copy-gpr (((dest t))
+			      ((src t)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (mr dest src)))
+
+
+(define-ppc64-vinsn copy-fpr (((dest :double-float))
+			      ((src :double-float)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (fmr dest src)))
+
+(define-ppc64-vinsn vcell-ref (((dest :lisp))
+			       ((vcell :lisp)))
+  (ld dest ppc64::misc-data-offset vcell))
+
+(define-ppc64-vinsn vcell-set (()
+			       ((vcell :lisp)
+				(value :lisp)))
+  (std value ppc64::misc-data-offset vcell))
+
+
+(define-ppc64-vinsn make-vcell (((dest :lisp))
+				((closed (:lisp :ne dest)))
+				((header :u64)))
+  (li header ppc64::value-cell-header)
+  (la ppc::allocptr (- ppc64::fulltag-misc ppc64::value-cell.size) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits))
+  (std closed ppc64::value-cell.value dest))
+
+(define-ppc64-vinsn make-tsp-vcell (((dest :lisp))
+				    ((closed :lisp))
+				    ((header :u64)))
+  (li header ppc64::value-cell-header)
+  (stdu ppc::tsp -32 ppc::tsp)
+  (std ppc::tsp 8 ppc::tsp)
+  (stfd ppc::fp-zero 16 ppc::tsp)
+  (stfd ppc::fp-zero 24 ppc::tsp)
+  (std ppc::rzero 8 ppc::tsp)
+  (std header (+ 16 ppc64::fulltag-misc ppc64::value-cell.header) ppc::tsp)
+  (std closed (+ 16 ppc64::fulltag-misc ppc64::value-cell.value) ppc::tsp)
+  (la dest (+ 16 ppc64::fulltag-misc) ppc::tsp))
+
+(define-ppc64-vinsn make-tsp-cons (((dest :lisp))
+				   ((car :lisp) (cdr :lisp))
+				   ())
+  (stdu ppc::tsp -32 ppc::tsp)
+  (std ppc::tsp 8 ppc::tsp)
+  (stfd ppc::fp-zero 16 ppc::tsp)
+  (stfd ppc::fp-zero 24 ppc::tsp)
+  (std ppc::rzero 8 ppc::tsp)
+  (std car (+ 16 ppc64::fulltag-cons ppc64::cons.car) ppc::tsp)
+  (std cdr (+ 16 ppc64::fulltag-cons ppc64::cons.cdr) ppc::tsp)
+  (la dest (+ 16 ppc64::fulltag-cons) ppc::tsp))
+
+
+(define-ppc64-vinsn %closure-code% (((dest :lisp))
+				    ())
+  (ld dest (:apply + ppc64::symbol.vcell (ppc64::nrs-offset %closure-code%) (:apply target-nil-value)) 0))
+
+(define-ppc64-vinsn single-float-bits (((dest :u32))
+                                       ((src :lisp)))
+  (srdi dest  src 32))
+
+(define-ppc64-vinsn (call-subprim :call :subprim-call) (()
+							((spno :s32const)))
+  (bla spno))
+
+(define-ppc64-vinsn (jump-subprim :jumpLR) (()
+					    ((spno :s32const)))
+  (ba spno))
+
+;;; Same as "call-subprim", but gives us a place to 
+;;; track args, results, etc.
+(define-ppc64-vinsn (call-subprim-0 :call :subprim-call) (((dest t))
+							  ((spno :s32const)))
+  (bla spno))
+
+(define-ppc64-vinsn (call-subprim-1 :call :subprim-call) (((dest t))
+							  ((spno :s32const)
+							   (z t)))
+  (bla spno))
+  
+(define-ppc64-vinsn (call-subprim-2 :call :subprim-call) (((dest t))
+							  ((spno :s32const)
+							   (y t)
+							   (z t)))
+  (bla spno))
+
+(define-ppc64-vinsn (call-subprim-3 :call :subprim-call) (((dest t))
+							  ((spno :s32const)
+							   (x t)
+							   (y t)
+							   (z t)))
+  (bla spno))
+
+(define-ppc64-vinsn event-poll (()
+				()
+                                ((crf :crf)))
+  (ld ppc::nargs ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (ld ppc::nargs ppc64::interrupt-level-binding-index ppc::nargs)
+  (cmpdi crf ppc::nargs 0)
+  (blt crf :done)
+  (bgt crf :trap)
+  (ld ppc::nargs ppc64::tcr.interrupt-pending ppc64::rcontext)
+  :trap
+  (tdgti ppc::nargs 0)
+  :done)
+
+(define-ppc64-vinsn ref-interrupt-level (((dest :imm))
+                                         ()
+                                         ((temp :u64)))
+  (ld temp ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (ld dest ppc64::INTERRUPT-LEVEL-BINDING-INDEX temp))
+                         
+;;; Unconditional (pc-relative) branch
+(define-ppc64-vinsn (jump :jump)
+    (()
+     ((label :label)))
+  (b label))
+
+(define-ppc64-vinsn (call-label :call) (()
+					((label :label)))
+  (bl label))
+
+;;; just like JUMP, only (implicitly) asserts that the following 
+;;; code is somehow reachable.
+(define-ppc64-vinsn (non-barrier-jump :xref) (()
+					      ((label :label)))
+  (b label))
+
+
+(define-ppc64-vinsn (cbranch-true :branch) (()
+					    ((label :label)
+					     (crf :crf)
+					     (crbit :u8const)))
+  (bt (:apply + crf crbit) label))
+
+(define-ppc64-vinsn (cbranch-false :branch) (()
+					     ((label :label)
+					      (crf :crf)
+					      (crbit :u8const)))
+  (bf (:apply + crf crbit) label))
+
+(define-ppc64-vinsn check-trap-error (()
+				      ())
+  (beq+ 0 :no-error)
+  (uuo_interr arch::error-reg-regnum ppc::arg_z)
+  :no-error)
+
+
+(define-ppc64-vinsn lisp-word-ref (((dest t))
+				   ((base t)
+				    (offset t)))
+  (ldx dest base offset))
+
+(define-ppc64-vinsn lisp-word-ref-c (((dest t))
+				     ((base t)
+				      (offset :s16const)))
+  (ld dest offset base))
+
+
+(define-ppc64-vinsn (lri :constant-ref) (((dest :imm))
+                                         ((intval :u64const))
+                                         ())
+  ((:or (:pred = (:apply ash intval -15) #x1FFFFFFFFFFFF)
+        (:pred = (:apply ash intval -15) 0))
+   (li dest (:apply %word-to-int (:apply logand #xffff intval))))
+  ((:not
+    (:or (:pred = (:apply ash intval -15) #x1FFFFFFFFFFFF)
+         (:pred = (:apply ash intval -15) 0)))
+   ((:or (:pred = (:apply ash intval -31) 0)
+         (:pred = (:apply ash intval -31) #x1ffffffff))
+    (lis dest (:apply %word-to-int (:apply ldb (:apply byte 16 16) intval)))
+    ((:not (:pred = (:apply ldb (:apply byte 16 0) intval) 0))
+     (ori dest dest (:apply ldb (:apply byte 16 0) intval))))
+   ((:not (:or (:pred = (:apply ash intval -31) 0)
+               (:pred = (:apply ash intval -31) #x1ffffffff)))
+    ((:pred = (:apply ash intval -32) 0)
+     (oris dest ppc::rzero (:apply ldb (:apply byte 16 16) intval))
+     ((:not (:pred = (:apply ldb (:apply byte 16 0) intval) 0))
+      (ori dest dest (:apply ldb (:apply byte 16 0) intval))))
+    ((:not (:pred = (:apply ash intval -32) 0))
+     ;; This is the general case, where all halfwords are significant.
+     ;; Hopefully, something above catches lots of other cases.
+     (lis dest (:apply %word-to-int (:apply ldb (:apply byte 16 48) intval)))
+     ((:not (:pred = (:apply ldb (:apply byte 16 32) intval) 0))
+      (ori dest dest (:apply ldb (:apply byte 16 32) intval)))
+     (sldi dest dest 32)
+     ((:not (:pred = (:apply ldb (:apply byte 16 16) intval) 0))
+      (oris dest dest (:apply ldb (:apply byte 16 16) intval)))
+     ((:not (:pred = (:apply ldb (:apply byte 16 0) intval) 0))
+      (ori dest dest (:apply ldb (:apply byte 16 0) intval)))))))
+
+
+(define-ppc64-vinsn (discard-temp-frame :tsp :pop :discard) (()
+                                                             ())
+  (ld ppc::tsp 0 ppc::tsp))
+
+
+;;; Somewhere, deep inside the "OS_X_PPC_RuntimeConventions.pdf"
+;;; document, they bother to document the fact that SP should
+;;; maintain 32-byte alignment on OSX.  (The example prologue
+;;; code in that document incorrectly assumes 8-byte alignment.
+;;; Or something.  It's wrong in a number of other ways.)
+;;; The caller always has to reserve a 24-byte linkage area
+;;; (large chunks of which are unused).
+(define-ppc64-vinsn alloc-c-frame (()
+				   ((n-c-args :u16const)))
+  ;; Always reserve space for at least 8 args and space for a lisp
+  ;; frame (for the kernel) underneath it.
+  ;; Zero the c-frame's savelr field, not that the GC cares ..
+  ((:pred <= n-c-args 10)
+   (stdu ppc::sp (- (+ 16 ppc64::c-frame.size ppc64::lisp-frame.size)) ppc::sp))
+  ((:pred > n-c-args 10)
+   ;; A normal C frame has room for 10 args (when padded out to
+   ;; 32-byte alignment. Add enough double words to accomodate the
+   ;; remaining args, in multiples of 4.
+   (stdu ppc::sp (:apply - (:apply +
+                                   16
+                                   (+ ppc64::c-frame.size ppc64::lisp-frame.size)
+                                   (:apply ash
+                                           (:apply logand
+                                                   (lognot 7)
+                                                   (:apply
+                                                    +
+                                                    7
+                                                    (:apply - n-c-args 10)))
+                                           3)))
+         ppc::sp))
+  (std ppc::rzero ppc64::c-frame.savelr ppc::sp))
+
+
+(define-ppc64-vinsn alloc-variable-c-frame (()
+                                            ((n-c-args :lisp))
+                                            ((crf :crf)
+                                             (size :s64)))
+  (cmpdi crf n-c-args (ash 10 ppc64::fixnumshift))
+  (subi size n-c-args (ash 10 ppc64::fixnumshift))
+  (bgt :variable)
+  ;; Always reserve space for at least 8 args and space for a lisp
+  ;; frame (for the kernel) underneath it.
+  (stdu ppc::sp (- (+ 16 ppc64::c-frame.size ppc64::lisp-frame.size)) ppc::sp)
+  (b :done)
+  :variable
+  (addi size size (+  (+ 16 ppc64::c-frame.size ppc64::lisp-frame.size) (ash 3 ppc64::fixnumshift)))
+  (clrrdi size size 4)
+  (neg size size)
+  (stdux ppc::sp ppc::sp size)
+  :done
+  (stw ppc::rzero ppc64::c-frame.savelr ppc::sp))
+
+;;; We should rarely have to do this.  It's easier to just generate code
+;;; to do the memory reference than it would be to keep track of the size
+;;; of each frame.
+(define-ppc64-vinsn (discard-c-frame :csp :pop :discard) (()
+				     ())
+  (ld ppc::sp 0 ppc::sp))
+
+
+
+
+(define-ppc64-vinsn set-c-arg (()
+			       ((argval :u32)
+				(argnum :u16const)))
+  (std argval (:apply + ppc64::c-frame.param0 (:apply ash argnum ppc64::word-shift)) ppc::sp))
+
+(define-ppc64-vinsn set-single-c-arg (()
+				      ((argval :single-float)
+				       (argnum :u16const)))
+  (stfs argval (:apply + ppc64::c-frame.param0 4 (:apply ash argnum ppc64::word-shift)) ppc::sp))
+
+(define-ppc64-vinsn set-double-c-arg (()
+				      ((argval :double-float)
+				       (argnum :u16const)))
+  (stfd argval (:apply + ppc64::c-frame.param0 (:apply ash argnum ppc64::word-shift)) ppc::sp))
+
+(define-ppc64-vinsn reload-single-c-arg (((argval :single-float))
+					 ((argnum :u16const)))
+  (lfs argval (:apply + ppc64::c-frame.param0 4 (:apply ash argnum ppc64::word-shift)) ppc::sp))
+
+(define-ppc64-vinsn reload-single-c-arg-high (((argval :single-float))
+                                              ((argnum :u16const)))
+  (lfs argval (:apply + ppc64::c-frame.param0 (:apply ash argnum ppc64::word-shift)) ppc::sp))
+
+(define-ppc64-vinsn reload-double-c-arg (((argval :double-float))
+					 ((argnum :u16const)))
+  (lfd argval (:apply + ppc64::c-frame.param0 (:apply ash argnum ppc64::word-shift)) ppc::sp))
+
+(define-ppc64-vinsn (load-nil :constant-ref) (((dest t))
+					      ())
+  (li dest (:apply target-nil-value)))
+
+
+(define-ppc64-vinsn (load-t :constant-ref) (((dest t))
+					    ())
+  (li dest (:apply + ppc64::t-offset (:apply target-nil-value))))
+
+(define-ppc64-vinsn set-eq-bit (((dest :crf))
+				())
+  (creqv (:apply + ppc::ppc-eq-bit dest)
+	 (:apply + ppc::ppc-eq-bit dest)
+	 (:apply + ppc::ppc-eq-bit dest)))
+
+(define-ppc64-vinsn (ref-constant :constant-ref) (((dest :lisp))
+						  ((src :s16const)))
+  (ld dest (:apply + ppc64::misc-data-offset (:apply ash (:apply 1+ src) 3)) ppc::fn))
+
+(define-ppc64-vinsn ref-indexed-constant (((dest :lisp))
+					  ((idxreg :s64)))
+  (ldx dest ppc::fn idxreg))
+
+
+(define-ppc64-vinsn cons (((dest :lisp))
+			  ((newcar :lisp)
+			   (newcdr :lisp)))
+  (la ppc::allocptr (- ppc64::fulltag-cons ppc64::cons.size) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std newcdr ppc64::cons.cdr ppc::allocptr)
+  (std newcar ppc64::cons.car ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits)))
+
+
+
+;;; subtag had better be a PPC-NODE-SUBTAG of some sort!
+(define-ppc64-vinsn %ppc-gvector (((dest :lisp))
+				  ((Rheader :u32) 
+				   (nbytes :u32const))
+				  ((immtemp0 :u32)
+				   (nodetemp :lisp)
+				   (crf :crf)))
+  (la ppc::allocptr (:apply - ppc64::fulltag-misc
+                            (:apply logand (lognot 15)
+                                    (:apply + (+ 15 8) nbytes)))
+      ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std Rheader ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits))
+  ((:not (:pred = nbytes 0))
+   (li immtemp0 (:apply + ppc64::misc-data-offset nbytes))
+   :loop
+   (subi immtemp0 immtemp0 8)
+   (cmpdi crf immtemp0 ppc64::misc-data-offset)
+   (ld nodetemp 0 ppc::vsp)
+   (la ppc::vsp 8 ppc::vsp)
+   (stdx nodetemp dest immtemp0)
+   (bne crf :loop)))
+
+;;; allocate a small (phys size <= 32K bytes) misc obj of known size/subtag
+(define-ppc64-vinsn %alloc-misc-fixed (((dest :lisp))
+				       ((Rheader :u64)
+					(nbytes :u32const)))
+  (la ppc::allocptr (:apply - ppc64::fulltag-misc
+                            (:apply logand (lognot 15)
+                                    (:apply + (+ 15 8) nbytes)))
+      ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std Rheader ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits)))
+
+(define-ppc64-vinsn (vstack-discard :vsp :pop :discard) (()
+				    ((nwords :u32const)))
+  ((:not (:pred = nwords 0))
+   (la ppc::vsp (:apply ash nwords ppc64::word-shift) ppc::vsp)))
+
+
+(define-ppc64-vinsn lcell-load (((dest :lisp))
+				((cell :lcell)
+				 (top :lcell)))
+  (ld dest (:apply - 
+		   (:apply - (:apply calc-lcell-depth top) ppc64::word-size-in-bytes)
+		   (:apply calc-lcell-offset cell)) ppc::vsp))
+
+(define-ppc64-vinsn vframe-load (((dest :lisp))
+				 ((frame-offset :u16const)
+				  (cur-vsp :u16const)))
+  (ld dest (:apply - (:apply - cur-vsp ppc64::word-size-in-bytes) frame-offset) ppc::vsp))
+
+(define-ppc64-vinsn lcell-store (()
+				 ((src :lisp)
+				  (cell :lcell)
+				  (top :lcell)))
+  (stw src (:apply - 
+                   (:apply - (:apply calc-lcell-depth top) 4)
+                   (:apply calc-lcell-offset cell)) ppc::vsp))
+
+(define-ppc64-vinsn vframe-store (()
+				  ((src :lisp)
+				   (frame-offset :u16const)
+				   (cur-vsp :u16const)))
+  (std src (:apply - (:apply - cur-vsp 8) frame-offset) ppc::vsp))
+
+(define-ppc64-vinsn load-vframe-address (((dest :imm))
+					 ((offset :s16const)))
+  (la dest offset ppc::vsp))
+
+(define-ppc64-vinsn copy-lexpr-argument (()
+					 ()
+					 ((temp :lisp)))
+  (ldx temp ppc::vsp ppc::nargs)
+  (stdu temp -8 ppc::vsp))
+
+;;; Boxing/unboxing of integers.
+
+;;; Treat the low 8 bits of VAL as an unsigned integer; set RESULT to
+;;; the equivalent fixnum.
+(define-ppc64-vinsn u8->fixnum (((result :imm)) 
+				((val :u8)) 
+				())
+  (clrlsldi result val (- ppc64::nbits-in-word 8) ppc64::fixnumshift))
+
+;;; Treat the low 8 bits of VAL as a signed integer; set RESULT to the
+;;; equivalent fixnum.
+(define-ppc64-vinsn s8->fixnum (((result :imm)) 
+				((val :s8)) 
+				())
+  (sldi result val (- ppc64::nbits-in-word 8))
+  (sradi result result (- (- ppc64::nbits-in-word 8) ppc64::fixnumshift)))
+
+
+;;; Treat the low 16 bits of VAL as an unsigned integer; set RESULT to
+;;; the equivalent fixnum.
+(define-ppc64-vinsn u16->fixnum (((result :imm)) 
+				 ((val :u16)) 
+				 ())
+  (clrlsldi result val (- ppc64::nbits-in-word 16) ppc64::fixnumshift))
+
+;;; Treat the low 16 bits of VAL as a signed integer; set RESULT to
+;;; the equivalent fixnum.
+(define-ppc64-vinsn s16->fixnum (((result :imm)) 
+				 ((val :s16)) 
+				 ())
+  (sldi result val (- ppc64::nbits-in-word 16))
+  (sradi result result (- (- ppc64::nbits-in-word 16) ppc64::fixnumshift)))
+
+(define-ppc64-vinsn fixnum->s16 (((result :s16))
+				 ((src :imm)))
+  (sradi result src ppc64::fixnumshift))
+
+(define-ppc64-vinsn s32->integer (((result :lisp))
+                                  ((src :s32))
+                                  ((temp :s64)))
+  (extsw temp src)
+  (sldi result temp ppc64::fixnumshift))
+
+
+;;; A signed 64-bit untagged value can be at worst a 2-digit
+;;; (minimal-sized) bignum.  There should be something very much like
+;;; this that takes a stack-consed bignum result ...
+(define-ppc64-vinsn s64->integer (((result :lisp))
+				  ((src :s64))
+				  ((crf (:crf 0)) ; a casualty
+				   (temp :s64)
+                                   (header :s64)))
+  (addo temp src src)
+  (addo temp temp temp)
+  (addo. result temp temp)
+  (rotldi temp src 32)
+  (bns+ :done)
+  (mtxer ppc::rzero)
+  (li header ppc64::two-digit-bignum-header)
+  (la ppc::allocptr (- ppc64::fulltag-misc 16) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits))
+  (std temp ppc64::misc-data-offset result)
+  :done)
+
+
+;;; An unsigned 32-bit untagged value is a fixnum.
+(define-ppc64-vinsn u32->integer (((result :lisp))
+				  ((src :u32)))
+  (sldi result src ppc64::fixnumshift))
+
+;;; An unsigned 64-bit untagged value is either a fixnum, a 2 (32-bit)
+;;; digit bignum, or a 3 (32-bit) digit bignum.
+(define-ppc64-vinsn u64->integer (((result :lisp))
+                                  ((src :u64))
+                                  ((temp :u64)
+                                   (header :u64)
+                                   (crf0 (:crf 0))
+                                   (crf1 :crf)))
+  (clrrdi. temp src (- 63 ppc64::nfixnumtagbits))
+  (cmpdi crf1 src 0)
+  (sldi result src ppc64::fixnumshift)
+  (beq crf0 :done)
+  (rotldi temp src 32)
+  (li header ppc64::two-digit-bignum-header)
+  (blt crf1 :three)
+  (la ppc::allocptr (- ppc64::fulltag-misc 16) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits))
+  (b :store)
+  :three
+  (la ppc::allocptr (- ppc64::fulltag-misc 32) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits))
+  :store
+  (std temp ppc64::misc-data-offset result)
+  :done)
+
+(define-ppc64-vinsn u16->u32 (((dest :u32))
+			      ((src :u16)))
+  (clrlwi dest src 16))
+
+(define-ppc64-vinsn u8->u32 (((dest :u32))
+			     ((src :u8)))
+  (clrlwi dest src 24))
+
+
+(define-ppc64-vinsn s16->s32 (((dest :s32))
+			      ((src :s16)))
+  (extsh dest src))
+
+(define-ppc64-vinsn s8->s32 (((dest :s32))
+			     ((src :s8)))
+  (extsb dest src))
+
+
+;;; ... of floats ...
+
+;;; Heap-cons a double-float to store contents of FPREG.  Hope that we
+;;; don't do this blindly.
+(define-ppc64-vinsn double->heap (((result :lisp)) ; tagged as a double-float
+				  ((fpreg :double-float)) 
+				  ((header-temp :u32)))
+  (li header-temp (arch::make-vheader ppc64::double-float.element-count ppc64::subtag-double-float))
+  (la ppc::allocptr (- ppc64::fulltag-misc ppc64::double-float.size) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header-temp ppc64::misc-header-offset ppc::allocptr)
+  (mr result ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits))
+  (stfd fpreg ppc64::double-float.value result)  )
+
+
+(define-ppc64-vinsn single->node (((result :lisp)) ; tagged as a single-float
+				  ((fpreg :single-float)))
+  (stfs fpreg ppc64::tcr.single-float-convert ppc64::rcontext)
+  (ld result  ppc64::tcr.single-float-convert ppc64::rcontext))
+
+
+;;; "dest" is preallocated, presumably on a stack somewhere.
+(define-ppc64-vinsn store-double (()
+				  ((dest :lisp)
+				   (source :double-float))
+				  ())
+  (stfd source ppc64::double-float.value dest))
+
+(define-ppc64-vinsn get-double (((target :double-float))
+				((source :lisp))
+				())
+  (lfd target ppc64::double-float.value source))
+
+;;; Extract a double-float value, typechecking in the process.
+;;; IWBNI we could simply call the "trap-unless-typecode=" vinsn here,
+;;; instead of replicating it ..
+
+(define-ppc64-vinsn get-double? (((target :double-float))
+				 ((source :lisp))
+				 ((tag :u8)
+				  (crf :crf)))
+  (clrldi tag source (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne crf :do-trap)
+  (lbz tag ppc64::misc-subtag-offset source)
+  :do-trap
+  (tdnei tag ppc64::subtag-double-float)
+  (lfd target ppc64::double-float.value source))
+
+(define-ppc64-vinsn double-to-single (((result :single-float))
+                                       ((arg :double-float)))
+  (frsp result arg))
+
+
+(define-ppc64-vinsn store-single (()
+				  ((dest :lisp)
+				   (source :single-float))
+				  ())
+  (stfs source ppc64::tcr.single-float-convert ppc64::rcontext)
+  (ld dest ppc64::tcr.single-float-convert ppc64::rcontext))
+
+(define-ppc64-vinsn get-single (((target :single-float))
+				((source :lisp)))
+  (std source ppc64::tcr.single-float-convert ppc64::rcontext)
+  (lfs target ppc64::tcr.single-float-convert ppc64::rcontext))
+
+;;; ... of characters ...
+(define-ppc64-vinsn charcode->u16 (((dest :u16))
+				   ((src :imm))
+				   ())
+  (srdi dest src ppc64::charcode-shift))
+
+(define-ppc64-vinsn character->fixnum (((dest :lisp))
+				       ((src :lisp))
+				       ())
+  (srdi dest src (- ppc64::charcode-shift ppc64::fixnumshift)))
+
+(define-ppc64-vinsn character->code (((dest :u32))
+				     ((src :lisp)))
+  (srdi dest src ppc64::charcode-shift))
+
+
+(define-ppc64-vinsn fixnum->char (((dest :lisp))
+				  ((src :imm))
+				  ((temp :u64)
+                                   (crf0 (:crf 0))))
+  (srdi temp src (+ ppc64::fixnumshift 1))
+  (cmpldi temp (ash #xffff -1))
+  (srdi temp src (+ ppc64::fixnumshift 11))
+  (beq :bad)
+  (cmpdi temp 27)
+  (sldi dest src (- ppc64::charcode-shift ppc64::fixnumshift))
+  (bne+ :ok)
+  :bad
+  (li dest (:apply target-nil-value))
+  (b :done)
+  :ok
+  (addi dest dest ppc64::subtag-character)
+  :done)
+
+(define-ppc64-vinsn code-char->char (((dest :lisp))
+				     ((src :imm))
+                               ())
+  (sldi dest src (- ppc64::charcode-shift ppc64::fixnumshift))
+  (ori dest dest ppc64::subtag-character))
+
+
+(define-ppc64-vinsn u32->char (((dest :lisp))
+			      ((src :u32))
+                               ())
+  (sldi dest src ppc64::charcode-shift)
+  (ori dest dest ppc64::subtag-character))
+
+;;; ... Macptrs ...
+
+(define-ppc64-vinsn deref-macptr (((addr :address))
+				  ((src :lisp))
+				  ())
+  (ld addr ppc64::macptr.address src))
+
+(define-ppc64-vinsn set-macptr-address (()
+					((addr :address)
+					 (src :lisp))
+					())
+  (std addr ppc64::macptr.address src))
+
+
+(define-ppc64-vinsn macptr->heap (((dest :lisp))
+				  ((address :address))
+				  ((header :u64)))
+  (li header (logior (ash ppc64::macptr.element-count ppc64::num-subtag-bits) ppc64::subtag-macptr))
+  (la ppc::allocptr (- ppc64::fulltag-misc ppc64::macptr.size) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (rldicr ppc::allocptr ppc::allocptr 0 (- 63 ppc64::ntagbits))
+  ;; It's not necessary to zero out the domain/type fields, since newly
+  ;; heap-allocated memory's guaranteed to be 0-filled.
+  (std address ppc64::macptr.address dest))
+
+(define-ppc64-vinsn macptr->stack (((dest :lisp))
+				   ((address :address))
+				   ((header :u64)))
+  (li header ppc64::macptr-header)
+  (stdu ppc::tsp (- (+ 16 ppc64::macptr.size)) ppc::tsp)
+  (std ppc::tsp 8 ppc::tsp)
+  (std header (+ 16 ppc64::fulltag-misc ppc64::macptr.header) ppc::tsp)
+  (std address (+ 16 ppc64::fulltag-misc ppc64::macptr.address) ppc::tsp)
+  ;; It -is- necessary to zero out the domain/type fields here, since
+  ;; stack-allocated memory isn't guaranteed to be 0-filled.
+  (std ppc::rzero (+ 16 ppc64::fulltag-misc ppc64::macptr.domain) ppc::tsp)
+  (std ppc::rzero (+ 16 ppc64::fulltag-misc ppc64::macptr.type) ppc::tsp)
+  (la dest (+ 16 ppc64::fulltag-misc) ppc::tsp))
+
+  
+(define-ppc64-vinsn adjust-stack-register (()
+					   ((reg t)
+					    (amount :s16const)))
+  (la reg amount reg))
+
+(define-ppc64-vinsn adjust-vsp (()
+				((amount :s16const)))
+  (la ppc::vsp amount ppc::vsp))
+
+(define-ppc64-vinsn adjust-sp (()
+                               ((amount :s16const)))
+  (la ppc::sp amount ppc::sp))
+
+;;; Arithmetic on fixnums & unboxed numbers
+
+(define-ppc64-vinsn u64-lognot (((dest :u64))
+				((src :u64))
+				())
+  (not dest src))
+
+(define-ppc64-vinsn fixnum-lognot (((dest :imm))
+				   ((src :imm))
+				   ((temp :u64)))
+  (not temp src)
+  (rldicr dest temp 0 (- 63 ppc64::nfixnumtagbits)))
+
+
+(define-ppc64-vinsn negate-fixnum-overflow-inline (((dest :lisp))
+						   ((src :imm))
+						   ((unboxed :s64)
+						    (header :u64)))
+  (nego. dest src)
+  (bns+ :done)
+  (mtxer ppc::rzero)
+  (sradi unboxed dest ppc64::fixnumshift)
+  (li header ppc64::two-digit-bignum-header)
+  (rotldi unboxed unboxed 32)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc64::fixnumshift))))
+  (la ppc::allocptr (- ppc64::fulltag-misc 16) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrdi ppc::allocptr ppc::allocptr ppc64::ntagbits)
+  (std unboxed ppc64::misc-data-offset dest)
+  :done)
+
+(define-ppc64-vinsn negate-fixnum-overflow-ool (()
+						((src :imm))
+						)
+  (nego. ppc::arg_z src)
+  (bsola- .SPfix-overflow)
+  :done)
+  
+                                                  
+                                       
+(define-ppc64-vinsn negate-fixnum-no-ovf (((dest :lisp))
+					  ((src :imm)))
+  
+  (neg dest src))
+  
+
+(define-ppc64-vinsn logior-high (((dest :imm))
+				 ((src :imm)
+				  (high :u16const)))
+  (oris dest src high))
+
+(define-ppc64-vinsn logior-low (((dest :imm))
+				((src :imm)
+				 (low :u16const)))
+  (ori dest src low))
+
+                           
+                           
+(define-ppc64-vinsn %logior2 (((dest :imm))
+			      ((x :imm)
+			       (y :imm))
+			      ())
+  (or dest x y))
+
+(define-ppc64-vinsn logand-high (((dest :imm))
+				 ((src :imm)
+				  (high :u16const))
+				 ((crf0 (:crf 0))))
+  (andis. dest src high))
+
+(define-ppc64-vinsn logand-low (((dest :imm))
+				((src :imm)
+				 (low :u16const))
+				((crf0 (:crf 0))))
+  (andi. dest src low))
+
+
+(define-ppc64-vinsn %logand2 (((dest :imm))
+			      ((x :imm)
+			       (y :imm))
+			      ())
+  (and dest x y))
+
+(define-ppc64-vinsn clear-left (((dest :imm))
+                                ((src :imm)
+                                 (nbits :s8const)))
+  (rldicl dest src 0 (:apply 1+ nbits)))
+
+(define-ppc64-vinsn clear-right (((dest :imm))
+                                 ((src :imm)
+                                  (nbits :s8const)))
+  (rldicr dest src 0 (:apply - 63 nbits)))
+
+(define-ppc64-vinsn logxor-high (((dest :imm))
+				 ((src :imm)
+				  (high :u16const)))
+  (xoris dest src high))
+
+(define-ppc64-vinsn logxor-low (((dest :imm))
+				((src :imm)
+				 (low :u16const)))
+  (xori dest src low))
+
+                           
+
+(define-ppc64-vinsn %logxor2 (((dest :imm))
+			      ((x :imm)
+			       (y :imm))
+			      ())
+  (xor dest x y))
+
+(define-ppc64-vinsn %ilsl (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :u32)
+			    (crx :crf)))
+  (cmpdi crx count (ash 63 ppc64::fixnumshift))
+  (srdi temp count ppc64::fixnumshift)
+  (sld dest src temp)
+  (ble+ crx :foo)
+  (li dest 0)
+  :foo)
+
+(define-ppc64-vinsn %ilsl-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm)))
+  ;; Hard to use ppcmacroinstructions that expand into expressions
+  ;; involving variables.
+  (rldicr dest src count (:apply - ppc64::least-significant-bit count)))
+
+
+(define-ppc64-vinsn %ilsr-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm))
+                             ((temp :s64)))
+  (rldicl temp src (:apply - 64 count) count)
+  (rldicr dest temp 0 (- 63 ppc64::fixnumshift)))
+
+
+
+;;; 68k did the right thing for counts < 64 - fixnumshift but not if greater
+;;; so load-byte fails in 3.0 also
+
+
+(define-ppc64-vinsn %iasr (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :s32)
+			    (crx :crf)))
+  (cmpdi crx count (ash 63 ppc64::fixnumshift))
+  (sradi temp count ppc64::fixnumshift)
+  (srad temp src temp)
+  (ble+ crx :foo)
+  (sradi temp src 63)
+  :foo
+  (rldicr dest temp 0 (- 63 ppc64::fixnumshift)))
+
+(define-ppc64-vinsn %iasr-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm))
+			     ((temp :s32)))
+  (sradi temp src count)
+  (rldicr dest temp 0 (- 63 ppc64::fixnumshift)))
+
+(define-ppc64-vinsn %ilsr (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :s32)
+			    (crx :crf)))
+  (cmpdi crx count (ash 63 ppc64::fixnumshift))
+  (srdi temp count ppc64::fixnumshift)
+  (srd temp src temp)
+  (rldicr dest temp 0 (- 63 ppc64::fixnumshift))
+  (ble+ crx :foo)
+  (li dest 0)
+  :foo  
+  )
+
+(define-ppc64-vinsn natural-shift-left (((dest :u64))
+                                        ((src :u64)
+                                         (count :u8const)))
+  (rldicr dest src count  (:apply - 63 count)))
+
+(define-ppc64-vinsn natural-shift-right (((dest :u64))
+                                         ((src :u64)
+                                          (count :u8const)))
+  (rldicr dest src (:apply - 64 count) count))
+
+(define-ppc64-vinsn sign-extend-halfword (((dest :imm))
+					  ((src :imm)))
+  (sldi dest src (- 48 ppc64::fixnumshift))
+  (sradi dest dest (- 48 ppc64::fixnumshift)))
+
+
+
+(define-ppc64-vinsn fixnum-add (((dest t))
+				((x t)
+				 (y t)))
+  (add dest x y))
+
+
+(define-ppc64-vinsn fixnum-add-overflow-ool (()
+					     ((x :imm)
+					      (y :imm))
+					     ((cr0 (:crf 0))))
+  (addo. ppc::arg_z x y)
+  (bsola- .SPfix-overflow))
+
+(define-ppc64-vinsn fixnum-add-overflow-inline (((dest :lisp))
+						((x :imm)
+						 (y :imm))
+						((cr0 (:crf 0))
+						 (unboxed :s64)
+						 (header :u64)))
+  (addo. dest x y)
+  (bns+ cr0 :done)
+  (mtxer ppc::rzero)
+  (sradi unboxed dest ppc64::fixnumshift)
+  (li header ppc64::two-digit-bignum-header)
+  (rotldi unboxed unboxed 32)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc64::fixnumshift))))
+  (la ppc::allocptr (- ppc64::fulltag-misc 16) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrdi ppc::allocptr ppc::allocptr ppc64::ntagbits)
+  (std unboxed ppc64::misc-data-offset dest)
+  :done)
+
+(define-ppc64-vinsn fixnum-add-overflow-inline-skip (((dest :lisp))
+                                                     ((x :imm)
+                                                      (y :imm)
+                                                      (done :label))
+                                                     ((cr0 (:crf 0))
+                                                      (unboxed :s64)
+                                                      (header :u64)))
+  (addo. dest x y)
+  (bns+ cr0 done)
+  (mtxer ppc::rzero)
+  (sradi unboxed dest ppc64::fixnumshift)
+  (li header ppc64::two-digit-bignum-header)
+  (rotldi unboxed unboxed 32)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc64::fixnumshift))))
+  (la ppc::allocptr (- ppc64::fulltag-misc 16) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrdi ppc::allocptr ppc::allocptr ppc64::ntagbits)
+  (std unboxed ppc64::misc-data-offset dest)
+  (b done))
+  
+
+  
+
+;;;  (setq dest (- x y))
+(define-ppc64-vinsn fixnum-sub (((dest t))
+				((x t)
+				 (y t)))
+  (subf dest y x))
+
+(define-ppc64-vinsn fixnum-sub-from-constant (((dest :imm))
+					      ((x :s16const)
+					       (y :imm)))
+  (subfic dest y (:apply ash x ppc64::fixnumshift)))
+
+
+
+
+(define-ppc64-vinsn fixnum-sub-overflow-ool (()
+					     ((x :imm)
+					      (y :imm)))
+  (subo. ppc::arg_z x y)
+  (bsola- .SPfix-overflow))
+
+(define-ppc64-vinsn fixnum-sub-overflow-inline (((dest :lisp))
+						((x :imm)
+						 (y :imm))
+						((cr0 (:crf 0))
+						 (unboxed :s64)
+						 (header :u64)))
+  (subo. dest x y)
+  (bns+ cr0 :done)
+  (mtxer ppc::rzero)
+  (sradi unboxed dest ppc64::fixnumshift)
+  (li header ppc64::two-digit-bignum-header)
+  (rotldi unboxed unboxed 32)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc64::fixnumshift))))
+  (la ppc::allocptr (- ppc64::fulltag-misc 16) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrdi ppc::allocptr ppc::allocptr ppc64::ntagbits)
+  (std unboxed ppc64::misc-data-offset dest)
+  :done)
+
+(define-ppc64-vinsn fixnum-sub-overflow-inline-skip (((dest :lisp))
+                                                     ((x :imm)
+                                                      (y :imm)
+                                                      (done :label))
+                                                     ((cr0 (:crf 0))
+                                                      (unboxed :s64)
+                                                      (header :u64)))
+  (subo. dest x y)
+  (bns+ cr0 done)
+  (mtxer ppc::rzero)
+  (sradi unboxed dest ppc64::fixnumshift)
+  (li header ppc64::two-digit-bignum-header)
+  (rotldi unboxed unboxed 32)
+  (xoris unboxed unboxed (logand #xffff (ash #xffff (- 32 16 ppc64::fixnumshift))))
+  (la ppc::allocptr (- ppc64::fulltag-misc 16) ppc::allocptr)
+  (tdlt ppc::allocptr ppc::allocbase)
+  (std header ppc64::misc-header-offset ppc::allocptr)
+  (mr dest ppc::allocptr)
+  (clrrdi ppc::allocptr ppc::allocptr ppc64::ntagbits)
+  (std unboxed ppc64::misc-data-offset dest)
+  (b done))
+
+;;; This is, of course, also "subtract-immediate."
+(define-ppc64-vinsn add-immediate (((dest t))
+				   ((src t)
+				    (upper :u32const)
+				    (lower :u32const)))
+  ((:not (:pred = upper 0))
+   (addis dest src upper)
+   ((:not (:pred = lower 0))
+    (addi dest dest lower)))
+  ((:and (:pred = upper 0) (:not (:pred = lower 0)))
+   (addi dest src lower)))
+
+;This must unbox one reg, but hard to tell which is better.
+;(The one with the smaller absolute value might be)
+(define-ppc64-vinsn multiply-fixnums (((dest :imm))
+				      ((a :imm)
+				       (b :imm))
+				      ((unboxed :s32)))
+  (sradi unboxed b ppc64::fixnumshift)
+  (mulld dest a unboxed))
+
+(define-ppc64-vinsn multiply-immediate (((dest :imm))
+					((boxed :imm)
+					 (const :s16const)))
+  (mulli dest boxed const))
+
+;;; Mask out the code field of a base character; the result
+;;; should be EXACTLY = to subtag-base-char
+(define-ppc64-vinsn mask-base-char (((dest :u32))
+				    ((src :imm)))
+  (clrldi dest src (- ppc64::nbits-in-word ppc64::num-subtag-bits)))
+
+;;; Set dest (of type :s64!) to 0 iff VAL is an istruct of type TYPE
+(define-ppc64-vinsn istruct-typep (((dest :s64))
+                                   ((val :lisp)
+                                    (type :lisp))
+                                   ((crf :crf)
+                                    (temp :lisp)))
+  (clrldi dest val (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf dest ppc64::fulltag-misc)
+  (li dest -1)
+  (bne crf :done)
+  (lbz dest ppc64::misc-subtag-offset val)
+  (cmpdi crf dest ppc64::subtag-istruct)
+  (bne crf :done)
+  (ld temp ppc64::misc-data-offset val)
+  (subf dest type temp)
+  :done)
+                             
+;;; Boundp, fboundp stuff.
+(define-ppc64-vinsn (ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val)))))
+  (bla .SPspecrefcheck))
+
+(define-ppc64-vinsn ref-symbol-value-inline (((dest :lisp))
+                                              ((src (:lisp (:ne dest))))
+                                              ((table :imm)
+                                               (idx :imm)))
+  (ld idx ppc64::symbol.binding-index src)
+  (ld table ppc64::tcr.tlb-limit ppc64::rcontext)
+  (cmpd idx table)
+  (ld table ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (bge :symbol)
+  (ldx dest table idx)
+  (cmpdi dest ppc64::subtag-no-thread-local-binding)
+  (bne :done)
+  :symbol
+  (ld dest ppc64::symbol.vcell src)
+  :done
+  (tdeqi dest ppc64::unbound-marker))
+
+(define-ppc64-vinsn (%ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val)))))
+  (bla .SPspecref))
+
+(define-ppc64-vinsn %ref-symbol-value-inline (((dest :lisp))
+                                              ((src (:lisp (:ne dest))))
+                                              ((table :imm)
+                                               (idx :imm)))
+  (ld idx ppc64::symbol.binding-index src)
+  (ld table ppc64::tcr.tlb-limit ppc64::rcontext)
+  (cmpd idx table)
+  (ld table ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (bge :symbol)
+  (ldx dest table idx)
+  (cmpdi dest ppc64::subtag-no-thread-local-binding)
+  (bne :done)
+  :symbol
+  (ld dest ppc64::symbol.vcell src)
+  :done
+  )
+
+(define-ppc64-vinsn (setq-special :call :subprim-call)
+    (()
+     ((sym :lisp)
+      (val :lisp)))
+  (bla .SPspecset))
+
+
+(define-ppc64-vinsn symbol-function (((val :lisp))
+				     ((sym (:lisp (:ne val))))
+				     ((crf :crf)
+				      (tag :u32)))
+  (ld val ppc64::symbol.fcell sym)
+  (clrldi tag val (- 64 ppc64::ntagbits))
+  (cmpdi crf tag ppc64::fulltag-misc)
+  (bne- crf :bad)
+  (lbz tag ppc64::misc-subtag-offset val)
+  (cmpdi crf tag ppc64::subtag-function)
+  (beq+ crf :good)
+  :bad 
+  (uuo_interr arch::error-udf sym)
+  :good)
+
+(define-ppc64-vinsn (temp-push-unboxed-word :push :word :tsp)
+    (()
+     ((w :u64)))
+  (stdu ppc::tsp -32 ppc::tsp)
+  (std ppc::tsp 8 ppc::tsp)
+  (std w 16 ppc::tsp))
+
+(define-ppc64-vinsn (temp-pop-unboxed-word :pop :word :tsp)
+    (((w :u64))
+     ())
+  (ld w 16 ppc::tsp)
+  (la ppc::tsp 32 ppc::tsp))
+
+(define-ppc64-vinsn (temp-push-double-float :push :doubleword :tsp)
+    (((d :double-float))
+     ())
+  (stdu ppc::tsp -32 ppc::tsp)
+  (std ppc::tsp 8 ppc::tsp)
+  (stfd d 16 ppc::tsp))
+
+(define-ppc64-vinsn (temp-pop-double-float :pop :doubleword :tsp)
+    (()
+     ((d :double-float)))
+  (lfd d 16 ppc::tsp)
+  (la ppc::tsp 32 ppc::tsp))
+
+(define-ppc64-vinsn (temp-push-single-float :push :word :tsp)
+    (((s :single-float))
+     ())
+  (stdu ppc::tsp -32 ppc::tsp)
+  (std ppc::tsp 8 ppc::tsp)
+  (stfs s 16 ppc::tsp))
+
+(define-ppc64-vinsn (temp-pop-single-float :pop :word :tsp)
+    (()
+     ((s :single-float)))
+  (lfs s 16 ppc::tsp)
+  (la ppc::tsp 32 ppc::tsp))
+
+
+(define-ppc64-vinsn (save-nvrs-individually :push :node :vsp :multiple)
+    (()
+     ((first :u8const)))
+  (stdu ppc::save0 -8 ppc::vsp)
+  ((:pred <= first ppc::save1)
+   (stdu ppc::save1 -8 ppc::vsp)
+   ((:pred <= first ppc::save2)
+    (stdu ppc::save2 -8 ppc::vsp)
+    ((:pred <= first ppc::save3)
+     (stdu ppc::save3 -8 ppc::vsp)
+     ((:pred <= first ppc::save4)
+      (stdu ppc::save4 -8 ppc::vsp)
+      ((:pred <= first ppc::save5)
+       (stdu ppc::save5 -8 ppc::vsp)
+       ((:pred <= first ppc::save6)
+	(stdu ppc::save6 -8 ppc::vsp)
+	((:pred = first ppc::save7)
+	 (stdu ppc::save7 -8 ppc::vsp)))))))))
+
+(define-ppc64-vinsn (save-nvrs :push :node :vsp :multiple)
+    (()
+     ((first :u8const)))
+  ;; There's no "stmd" instruction.
+  (stdu ppc::save0 -8 ppc::vsp)
+  ((:pred <= first ppc::save1)
+   (stdu ppc::save1 -8 ppc::vsp)
+   ((:pred <= first ppc::save2)
+    (stdu ppc::save2 -8 ppc::vsp)
+    ((:pred <= first ppc::save3)
+     (stdu ppc::save3 -8 ppc::vsp)
+     ((:pred <= first ppc::save4)
+      (stdu ppc::save4 -8 ppc::vsp)
+      ((:pred <= first ppc::save5)
+       (stdu ppc::save5 -8 ppc::vsp)
+       ((:pred <= first ppc::save6)
+	(stdu ppc::save6 -8 ppc::vsp)
+	((:pred = first ppc::save7)
+	 (stdu ppc::save7 -8 ppc::vsp)))))))))
+
+
+(define-ppc64-vinsn (restore-nvrs :pop :node :vsp :multiple)
+    (()
+     ((firstreg :u8const)
+      (basereg :imm)
+      (offset :s16const)))
+  ((:pred = firstreg ppc::save7)
+   (ld ppc::save7 offset basereg)
+   (ld ppc::save6 (:apply + offset 8) basereg)
+   (ld ppc::save5 (:apply + offset 16) basereg)
+   (ld ppc::save4 (:apply + offset 24) basereg)
+   (ld ppc::save3 (:apply + offset 32) basereg)
+   (ld ppc::save2 (:apply + offset 40) basereg)
+   (ld ppc::save1 (:apply + offset 48) basereg)
+   (ld ppc::save0 (:apply + offset 56) basereg))
+  ((:pred = firstreg ppc::save6)
+   (ld ppc::save6 offset basereg)
+   (ld ppc::save5 (:apply + offset 8) basereg)
+   (ld ppc::save4 (:apply + offset 16) basereg)
+   (ld ppc::save3 (:apply + offset 24) basereg)
+   (ld ppc::save2 (:apply + offset 32) basereg)
+   (ld ppc::save1 (:apply + offset 40) basereg)
+   (ld ppc::save0 (:apply + offset 48) basereg))
+  ((:pred = firstreg ppc::save5)
+   (ld ppc::save5 offset basereg)
+   (ld ppc::save4 (:apply + offset 8) basereg)
+   (ld ppc::save3 (:apply + offset 16) basereg)
+   (ld ppc::save2 (:apply + offset 24) basereg)
+   (ld ppc::save1 (:apply + offset 32) basereg)
+   (ld ppc::save0 (:apply + offset 40) basereg))
+  ((:pred = firstreg ppc::save4)
+   (ld ppc::save4 offset basereg)
+   (ld ppc::save3 (:apply + offset 8) basereg)
+   (ld ppc::save2 (:apply + offset 16) basereg)
+   (ld ppc::save1 (:apply + offset 24) basereg)
+   (ld ppc::save0 (:apply + offset 32) basereg))
+  ((:pred = firstreg ppc::save3)
+   (ld ppc::save3 offset basereg)
+   (ld ppc::save2 (:apply + offset 8) basereg)
+   (ld ppc::save1 (:apply + offset 16) basereg)
+   (ld ppc::save0 (:apply + offset 24) basereg))
+  ((:pred = firstreg ppc::save2)
+   (ld ppc::save2 offset basereg)
+   (ld ppc::save1 (:apply + offset 8) basereg)
+   (ld ppc::save0 (:apply + offset 16) basereg))
+  ((:pred = firstreg ppc::save1)
+   (ld ppc::save1 offset basereg)
+   (ld ppc::save0 (:apply + offset 8) basereg))
+  ((:pred = firstreg ppc::save0)
+   (ld ppc::save0 offset basereg)))
+
+(define-ppc64-vinsn %current-frame-ptr (((dest :imm))
+					())
+  (mr dest ppc::sp))
+
+(define-ppc64-vinsn %current-tcr (((dest :imm))
+				  ())
+  (mr dest ppc64::rcontext))
+
+(define-ppc64-vinsn (dpayback :call :subprim-call) (()
+                                                    ((n :s16const))
+                                                    ((temp (:u32 #.ppc::imm0))))
+  ((:pred > n 1)
+   (li temp n)
+   (bla .SPunbind-n))
+  ((:pred = n 1)
+   (bla .SPunbind)))
+
+(define-ppc64-vinsn zero-double-float-register 
+    (((dest :double-float))
+     ())
+  (fmr dest ppc::fp-zero))
+
+(define-ppc64-vinsn zero-single-float-register 
+    (((dest :single-float))
+     ())
+  (fmr dest ppc::fp-zero))
+
+(define-ppc64-vinsn load-double-float-constant
+    (((dest :double-float))
+     ((high :u32)
+      (low :u32)))
+  (stw high -8 ppc::sp)
+  (stw low -4 ppc::sp)
+  (lfd dest -8 ppc::sp))
+
+(define-ppc64-vinsn load-single-float-constant
+    (((dest :single-float))
+     ((src t)))
+  (stw src -4 ppc::sp)
+  (lfs dest -4 ppc::sp))
+
+(define-ppc64-vinsn load-indexed-node (((node :lisp))
+				       ((base :lisp)
+					(offset :s16const)))
+  (ld node offset base))
+
+(define-ppc64-vinsn recover-saved-vsp (((dest :imm))
+				       ())
+  (ld dest ppc64::lisp-frame.savevsp ppc::sp))
+
+
+(define-ppc64-vinsn check-exact-nargs (()
+				       ((n :u16const)))
+  (tdnei ppc::nargs (:apply ash n ppc64::word-shift)))
+
+(define-ppc64-vinsn check-min-nargs (()
+				     ((min :u16const)))
+  (tdllti ppc::nargs (:apply ash min ppc64::word-shift)))
+
+(define-ppc64-vinsn check-max-nargs (()
+				     ((max :u16const)))
+  (tdlgti ppc::nargs (:apply ash max ppc64::word-shift)))
+
+;;; Save context and establish FN.  The current VSP is the the
+;;; same as the caller's, e.g., no arguments were vpushed.
+(define-ppc64-vinsn save-lisp-context-vsp (()
+					   ()
+					   ((imm :u64)))
+  (stdu ppc::sp (- ppc64::lisp-frame.size) ppc::sp)
+  (std ppc::fn ppc64::lisp-frame.savefn ppc::sp)
+  (std ppc::loc-pc ppc64::lisp-frame.savelr ppc::sp)
+  (std ppc::vsp ppc64::lisp-frame.savevsp ppc::sp)
+  (mr ppc::fn ppc::nfn)
+  ;; Do a stack-probe ...
+  (ld imm ppc64::tcr.cs-limit ppc64::rcontext)
+  (tdllt ppc::sp imm))
+
+;;; Do the same thing via a subprim call.
+(define-ppc64-vinsn (save-lisp-context-vsp-ool :call :subprim-call)
+    (()
+     ()
+     ((imm (:u64 #.ppc::imm0))))
+  (bla .SPsavecontextvsp))
+
+(define-ppc64-vinsn save-lisp-context-offset (()
+					      ((nbytes-vpushed :u16const))
+					      ((imm :u64)))
+  (la imm nbytes-vpushed ppc::vsp)
+  (stdu ppc::sp (- ppc64::lisp-frame.size) ppc::sp)
+  (std ppc::fn ppc64::lisp-frame.savefn ppc::sp)
+  (std ppc::loc-pc ppc64::lisp-frame.savelr ppc::sp)
+  (std imm ppc64::lisp-frame.savevsp ppc::sp)
+  (mr ppc::fn ppc::nfn)
+  ;; Do a stack-probe ...
+  (ld imm ppc64::tcr.cs-limit ppc64::rcontext)
+  (tdllt ppc::sp imm))
+
+(define-ppc64-vinsn save-lisp-context-offset-ool (()
+						  ((nbytes-vpushed :u16const))
+						  ((imm (:u64 #.ppc::imm0))))
+  (li imm nbytes-vpushed)
+  (bla .SPsavecontext0))
+
+
+(define-ppc64-vinsn save-lisp-context-lexpr (()
+					     ()
+					     ((imm :u64)))
+  (stdu ppc::sp (- ppc64::lisp-frame.size) ppc::sp)
+  (std ppc::rzero ppc64::lisp-frame.savefn ppc::sp)
+  (std ppc::loc-pc ppc64::lisp-frame.savelr ppc::sp)
+  (std ppc::vsp ppc64::lisp-frame.savevsp ppc::sp)
+  (mr ppc::fn ppc::nfn)
+  ;; Do a stack-probe ...
+  (ld imm ppc64::tcr.cs-limit ppc64::rcontext)
+  (tdllt ppc::sp imm))
+  
+(define-ppc64-vinsn save-cleanup-context (()
+					  ())
+  ;; SP was this deep just a second ago, so no need to do a stack-probe.
+  (mflr ppc::loc-pc)
+  (stdu ppc::sp (- ppc64::lisp-frame.size) ppc::sp)
+  (std ppc::rzero ppc64::lisp-frame.savefn ppc::sp)
+  (std ppc::loc-pc ppc64::lisp-frame.savelr ppc::sp)
+  (std ppc::vsp ppc64::lisp-frame.savevsp ppc::sp))
+
+;;; Vpush the argument registers.  We got at least "min-fixed" args;
+;;; that knowledge may help us generate better code.
+(define-ppc64-vinsn (save-lexpr-argregs :call :subprim-call)
+    (()
+     ((min-fixed :u16const))
+     ((crfx :crf)
+      (crfy :crf)
+      (entry-vsp (:u64 #.ppc::imm0))
+      (arg-temp :u64)))
+  ((:pred >= min-fixed $numppcargregs)
+   (stdu ppc::arg_x -8 ppc::vsp)
+   (stdu ppc::arg_y -8 ppc::vsp)
+   (stdu ppc::arg_z -8 ppc::vsp))
+  ((:pred = min-fixed 2)                ; at least 2 args
+   (cmpldi crfx ppc::nargs (ash 2 ppc64::word-shift))
+   (beq crfx :yz2)                      ; skip arg_x if exactly 2
+   (stdu ppc::arg_x -8 ppc::vsp)
+   :yz2
+   (stdu ppc::arg_y -8 ppc::vsp)
+   (stdu ppc::arg_z -8 ppc::vsp))
+  ((:pred = min-fixed 1)                ; at least one arg
+   (cmpldi crfx ppc::nargs (ash 2 ppc64::word-shift))
+   (blt crfx :z1)                       ; branch if exactly one
+   (beq crfx :yz1)                      ; branch if exactly two
+   (stdu ppc::arg_x -8 ppc::vsp)
+   :yz1
+   (stdu ppc::arg_y -8 ppc::vsp)
+   :z1
+   (stdu ppc::arg_z -8 ppc::vsp))
+  ((:pred = min-fixed 0)
+   (cmpldi crfx ppc::nargs (ash 2 ppc64::word-shift))
+   (cmpldi crfy ppc::nargs 0)
+   (beq crfx :yz0)                      ; exactly two
+   (beq crfy :none)                     ; exactly zero
+   (blt crfx :z0)                       ; one
+                                        ; Three or more ...
+   (stdu ppc::arg_x -8 ppc::vsp)
+   :yz0
+   (stdu ppc::arg_y -8 ppc::vsp)
+   :z0
+   (stdu ppc::arg_z -8 ppc::vsp)
+   :none
+   )
+  ((:pred = min-fixed 0)
+   (stdu ppc::nargs -8 ppc::vsp))
+  ((:not (:pred = min-fixed 0))
+   (subi arg-temp ppc::nargs (:apply ash min-fixed ppc64::word-shift))
+   (stdu arg-temp -8 ppc::vsp))
+  (add entry-vsp ppc::vsp ppc::nargs)
+  (la entry-vsp 8 entry-vsp)
+  (bla .SPlexpr-entry))
+
+
+(define-ppc64-vinsn (jump-return-pc :jumpLR)
+    (()
+     ())
+  (blr))
+
+(define-ppc64-vinsn (restore-full-lisp-context :lispcontext :pop :csp :lrRestore)
+    (()
+     ())
+  (ld ppc::loc-pc ppc64::lisp-frame.savelr ppc::sp)
+  (ld ppc::vsp ppc64::lisp-frame.savevsp ppc::sp)
+  (ld ppc::fn ppc64::lisp-frame.savefn ppc::sp)
+  (mtlr ppc::loc-pc)
+  (la ppc::sp ppc64::lisp-frame.size ppc::sp))
+
+(define-ppc64-vinsn (restore-full-lisp-context-ool :lispcontext :pop :csp :lrRestore)
+    (()
+     ())
+  (bla .SPrestorecontext)
+  (mtlr ppc::loc-pc))
+
+(define-ppc64-vinsn (popj :lispcontext :pop :csp :lrRestore :jumpLR)
+    (() 
+     ())
+  (ba .SPpopj))
+
+;;; Exiting from an UNWIND-PROTECT cleanup is similar to
+;;; (and a little simpler than) returning from a function.
+(define-ppc64-vinsn restore-cleanup-context (()
+					     ())
+  (ld ppc::loc-pc ppc64::lisp-frame.savelr ppc::sp)
+  (mtlr ppc::loc-pc)
+  (la ppc::sp ppc64::lisp-frame.size ppc::sp))
+
+
+
+(define-ppc64-vinsn default-1-arg (()
+				   ((min :u16const))
+				   ((crf :crf)))
+  (cmpldi crf ppc::nargs (:apply ash min ppc64::word-shift))
+  (bne crf :done)
+  ((:pred >= min 3)
+   (stdu ppc::arg_x -8 ppc::vsp))
+  ((:pred >= min 2)
+   (mr ppc::arg_x ppc::arg_y))
+  ((:pred >= min 1)
+   (mr ppc::arg_y ppc::arg_z))
+  (li ppc::arg_z (:apply target-nil-value))
+  :done)
+
+(define-ppc64-vinsn default-2-args (()
+				    ((min :u16const))
+				    ((crf :crf)))
+  (cmpldi crf ppc::nargs (:apply ash (:apply 1+ min) ppc64::word-shift))
+  (bgt crf :done)
+  (beq crf :one)
+  ;; We got "min" args; arg_y & arg_z default to nil
+  ((:pred >= min 3)
+   (stdu ppc::arg_x -8 ppc::vsp))   
+  ((:pred >= min 2)
+   (stdu ppc::arg_y -8 ppc::vsp))
+  ((:pred >= min 1)
+   (mr ppc::arg_x ppc::arg_z))
+  (li ppc::arg_y (:apply target-nil-value))
+  (b :last)
+  :one
+  ;; We got min+1 args: arg_y was supplied, arg_z defaults to nil.
+  ((:pred >= min 2)
+   (stdu ppc::arg_x -8 ppc::vsp))
+  ((:pred >= min 1)
+   (mr ppc::arg_x ppc::arg_y))
+  (mr ppc::arg_y ppc::arg_z)
+  :last
+  (li ppc::arg_z (:apply target-nil-value))
+  :done)
+
+(define-ppc64-vinsn default-3-args (()
+				    ((min :u16const))
+				    ((crfx :crf)
+				     (crfy :crf)))
+  (cmpldi crfx ppc::nargs (:apply ash (:apply + 2 min) ppc64::word-shift))
+  (cmpldi crfy ppc::nargs (:apply ash min ppc64::word-shift))
+  (bgt crfx :done)
+  (beq crfx :two)
+  (beq crfy :none)
+  ;; The first (of three) &optional args was supplied.
+  ((:pred >= min 2)
+   (stdu ppc::arg_x -8 ppc::vsp))
+  ((:pred >= min 1)
+   (stdu ppc::arg_y -8 ppc::vsp))
+  (mr ppc::arg_x ppc::arg_z)
+  (b :last-2)
+  :two
+  ;; The first two (of three) &optional args were supplied.
+  ((:pred >= min 1)
+   (stdu ppc::arg_x -8 ppc::vsp))
+  (mr ppc::arg_x ppc::arg_y)
+  (mr ppc::arg_y ppc::arg_z)
+  (b :last-1)
+  ;; None of the three &optional args was provided.
+  :none
+  ((:pred >= min 3)
+   (stdu ppc::arg_x -8 ppc::vsp))
+  ((:pred >= min 2)
+   (stdu ppc::arg_y -8 ppc::vsp))
+  ((:pred >= min 1)
+   (stdu ppc::arg_z -8 ppc::vsp))
+  (li ppc::arg_x (:apply target-nil-value))
+  :last-2
+  (li ppc::arg_y (:apply target-nil-value))
+  :last-1
+  (li ppc::arg_z (:apply target-nil-value))
+  :done)
+
+(define-ppc64-vinsn save-lr (()
+			     ())
+  (mflr ppc::loc-pc))
+
+;;; "n" is the sum of the number of required args + 
+;;; the number of &optionals.  
+(define-ppc64-vinsn (default-optionals :call :subprim-call) (()
+							     ((n :u16const)))
+  (li ppc::imm0 (:apply ash n ppc64::word-shift))
+  (bla .SPdefault-optional-args))
+
+;;; fname contains a known symbol
+(define-ppc64-vinsn (call-known-symbol :call) (((result (:lisp ppc::arg_z)))
+					       ())
+  (ld ppc::nfn ppc64::symbol.fcell ppc::fname)
+  (ld ppc::temp0 ppc64::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctrl))
+
+(define-ppc64-vinsn (jump-known-symbol :jumplr) (()
+						 ())
+  (ld ppc::nfn ppc64::symbol.fcell ppc::fname)
+  (ld ppc::temp0 ppc64::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctr))
+
+(define-ppc64-vinsn (call-known-function :call) (()
+						 ())
+  (ld ppc::temp0 ppc64::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctrl))
+
+(define-ppc64-vinsn (jump-known-function :jumplr) (()
+						   ())
+  (ld ppc::temp0 ppc64::misc-data-offset ppc::nfn)
+  (mtctr ppc::temp0)
+  (bctr))
+
+(define-ppc64-vinsn %schar8 (((char :imm))
+                             ((str :lisp)
+                              (idx :imm))
+                             ((imm :u32)
+                              (cr0 (:crf 0))))
+  (srdi imm idx ppc64::fixnumshift)
+  (addi imm imm ppc64::misc-data-offset)
+  (lbzx imm str imm)
+  (rldicr imm imm ppc64::charcode-shift (- 63 ppc64::charcode-shift))
+  (ori char imm ppc64::subtag-character))
+
+(define-ppc64-vinsn %schar32 (((char :imm))
+                              ((str :lisp)
+                               (idx :imm))
+                              ((imm :u32)
+                               (cr0 (:crf 0))))
+  (srdi imm idx 1)
+  (addi imm imm ppc64::misc-data-offset)
+  (lwzx imm str imm)
+  (rldicr imm imm ppc64::charcode-shift (- 63 ppc64::charcode-shift))
+  (ori char imm ppc64::subtag-character))
+
+(define-ppc64-vinsn %set-schar8 (()
+				((str :lisp)
+				 (idx :imm)
+				 (char :imm))
+				((imm :u64)
+				 (imm1 :u64)
+				 (cr0 (:crf 0))))
+  (srdi imm idx ppc64::fixnumshift)
+  (addi imm imm ppc64::misc-data-offset)
+  (srdi imm1 char ppc64::charcode-shift)
+  (stbx imm1 str imm)
+  )
+
+(define-ppc64-vinsn %set-schar32 (()
+				((str :lisp)
+				 (idx :imm)
+				 (char :imm))
+				((imm :u64)
+				 (imm1 :u64)
+				 (cr0 (:crf 0))))
+  (srdi imm idx 1)
+  (addi imm imm ppc64::misc-data-offset)
+  (srdi imm1 char ppc64::charcode-shift)
+  (stwx imm1 str imm)
+  )
+
+(define-ppc64-vinsn %set-scharcode8 (()
+                                     ((str :lisp)
+                                      (idx :imm)
+                                      (code :imm))
+                                     ((imm :u64)
+                                      (imm1 :u64)
+                                      (cr0 (:crf 0))))
+  (srdi imm idx ppc64::fixnumshift)
+  (addi imm imm ppc64::misc-data-offset)
+  (srdi imm1 code ppc64::fixnumshift)
+  (stbx imm1 str imm)
+  )
+
+(define-ppc64-vinsn %set-scharcode32 (()
+                                      ((str :lisp)
+                                       (idx :imm)
+                                       (code :imm))
+                                      ((imm :u64)
+                                       (imm1 :u64)
+                                       (cr0 (:crf 0))))
+  (srdi imm idx 1)
+  (addi imm imm ppc64::misc-data-offset)
+  (srdi imm1 code ppc64::fixnumshift)
+  (stwx imm1 str imm)
+  )
+
+
+(define-ppc64-vinsn %scharcode8 (((code :imm))
+                                 ((str :lisp)
+                                  (idx :imm))
+                                 ((imm :u64)
+                                  (cr0 (:crf 0))))
+  (srdi imm idx ppc64::fixnumshift)
+  (addi imm imm ppc64::misc-data-offset)
+  (lbzx imm str imm)
+  (sldi code imm ppc64::fixnumshift))
+
+(define-ppc64-vinsn %scharcode32 (((code :imm))
+                                  ((str :lisp)
+                                   (idx :imm))
+                                  ((imm :u64)
+                                   (cr0 (:crf 0))))
+  (srdi imm idx 1)
+  (addi imm imm ppc64::misc-data-offset)
+  (lwzx imm str imm)
+  (sldi code imm ppc64::fixnumshift))
+
+;;; Clobbers LR
+(define-ppc64-vinsn (%debug-trap :call :subprim-call) (()
+						       ())
+  (bla .SPbreakpoint)
+  )
+
+
+(define-ppc64-vinsn eep.address (((dest t))
+				 ((src (:lisp (:ne dest )))))
+  (ld dest (+ (ash 1 ppc64::word-shift) ppc64::misc-data-offset) src)
+  (tdeqi dest (:apply target-nil-value)))
+
+(define-ppc64-vinsn %natural+ (((dest :u64))
+                               ((x :u64) (y :u64)))
+  (add dest x y))
+
+(define-ppc64-vinsn %natural+-c (((dest :u64))
+                                 ((x :u64) (y :u16const)))
+  (addi dest x y))
+
+(define-ppc64-vinsn %natural- (((dest :u64))
+                               ((x :u64) (y :u64)))
+  (sub dest x y))
+
+(define-ppc64-vinsn %natural--c (((dest :u64))
+                                 ((x :u64) (y :u16const)))
+  (subi dest x y))
+
+(define-ppc64-vinsn %natural-logior (((dest :u64))
+                                     ((x :u64) (y :u64)))
+  (or dest x y))
+
+(define-ppc64-vinsn %natural-logior-c (((dest :u64))
+				   ((x :u64) (high :u16const) (low :u16const)))
+  ((:not (:pred = high 0))
+   (oris dest x high))
+  ((:not (:pred = low 0))
+   (ori dest x low)))
+
+(define-ppc64-vinsn %natural-logxor (((dest :u64))
+                                     ((x :u64) (y :u64)))
+  (xor dest x y))
+
+(define-ppc64-vinsn %natural-logxor-c (((dest :u64))
+                                       ((x :u64) (high :u16const) (low :u16const)))
+  ((:not (:pred = high 0))
+   (xoris dest x high))
+  ((:not (:pred = low 0))
+   (xori dest x low)))
+
+(define-ppc64-vinsn %natural-logand (((dest :u64))
+                                     ((x :u64) (y :u64)))
+  (and dest x y))
+
+(define-ppc64-vinsn %natural-logand-high-c (((dest :u64))
+                                            ((x :u64) (high :u16const))
+                                            ((cr0 (:crf 0))))
+  (andis. dest x high))
+
+(define-ppc64-vinsn %natural-logand-low-c (((dest :u64))
+                                           ((x :u64) (low :u16const))
+                                           ((cr0 (:crf 0))))
+  (andi. dest x low))
+
+(define-ppc64-vinsn %natural-logand-mask-c (((dest :u32))
+                                            ((x :u32)
+                                             (start :u8const)
+                                             (end :u8const)))
+  (rlwinm dest x 0 start end))
+
+(define-ppc64-vinsn disable-interrupts (((dest :lisp))
+					()
+					((temp :imm)
+                                         (temp2 :imm)))
+  (ld temp2 ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (li temp -8)
+  (ld dest ppc64::interrupt-level-binding-index temp2)
+  (std temp ppc64::interrupt-level-binding-index temp2))
+
+(define-ppc64-vinsn load-character-constant (((dest :lisp))
+                                             ((code :u32const))
+                                             ())
+  (ori dest ppc::rzero (:apply logior (:apply ash (:apply logand #xff code) 8) ppc64::subtag-character))
+  ((:not (:pred = 0 (:apply ldb (byte 16 8) code)))
+   (oris dest dest (:apply ldb (byte 16 8) code))))
+
+
+(define-ppc64-vinsn %symbol->symptr (((dest :lisp))
+                                     ((src :lisp))
+                                     ((tag :u8)
+                                      (crf0 :crf)))
+  (clrldi tag src (- ppc64::nbits-in-word ppc64::ntagbits))
+  (cmpdi crf0 tag ppc64::fulltag-misc)
+  (bne crf0 :do-trap)
+  (lbz tag ppc64::misc-subtag-offset src)
+  :do-trap
+  (tdnei tag ppc64::subtag-symbol)
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (mr dest src)))
+
+
+
+;;; Subprim calls.  Done this way for the benefit of VINSN-OPTIMIZE.
+(defmacro define-ppc64-subprim-call-vinsn ((name &rest other-attrs) spno)
+  `(define-ppc64-vinsn (,name :call :subprim-call ,@other-attrs) (() ())
+    (bla ,spno)))
+
+(defmacro define-ppc64-subprim-jump-vinsn ((name &rest other-attrs) spno)
+  `(define-ppc64-vinsn (,name :jumpLR ,@other-attrs) (() ())
+    (ba ,spno)))
+
+(define-ppc64-subprim-jump-vinsn (restore-interrupt-level) .SPrestoreintlevel)
+
+(define-ppc64-subprim-call-vinsn (save-values) .SPsave-values)
+
+(define-ppc64-subprim-call-vinsn (recover-values)  .SPrecover-values)
+
+(define-ppc64-subprim-call-vinsn (add-values) .SPadd-values)
+
+(define-ppc64-subprim-jump-vinsn (jump-known-symbol-ool) .SPjmpsym)
+
+(define-ppc64-subprim-call-vinsn (call-known-symbol-ool)  .SPjmpsym)
+
+(define-ppc64-subprim-call-vinsn (pass-multiple-values)  .SPmvpass)
+
+(define-ppc64-subprim-call-vinsn (pass-multiple-values-symbol) .SPmvpasssym)
+
+(define-ppc64-subprim-jump-vinsn (tail-call-sym-gen) .SPtcallsymgen)
+
+(define-ppc64-subprim-jump-vinsn (tail-call-fn-gen) .SPtcallnfngen)
+
+(define-ppc64-subprim-jump-vinsn (tail-call-sym-slide) .SPtcallsymslide)
+
+(define-ppc64-subprim-jump-vinsn (tail-call-fn-slide) .SPtcallnfnslide)
+
+(define-ppc64-subprim-jump-vinsn (tail-call-sym-vsp) .SPtcallsymvsp)
+
+(define-ppc64-subprim-jump-vinsn (tail-call-fn-vsp) .SPtcallnfnvsp)
+
+(define-ppc64-subprim-call-vinsn (funcall)  .SPfuncall)
+
+(define-ppc64-subprim-jump-vinsn (tail-funcall-gen) .SPtfuncallgen)
+
+(define-ppc64-subprim-jump-vinsn (tail-funcall-slide) .SPtfuncallslide)
+
+(define-ppc64-subprim-jump-vinsn (tail-funcall-vsp) .SPtfuncallvsp)
+
+(define-ppc64-subprim-call-vinsn (spread-lexpr)  .SPspread-lexpr-z)
+
+(define-ppc64-subprim-call-vinsn (spread-list)  .SPspreadargz)
+
+(define-ppc64-subprim-call-vinsn (pop-argument-registers)  .SPvpopargregs)
+
+(define-ppc64-subprim-call-vinsn (getxlong)  .SPgetXlong)
+
+(define-ppc64-subprim-call-vinsn (stack-cons-list)  .SPstkconslist)
+
+(define-ppc64-subprim-call-vinsn (list) .SPconslist)
+
+(define-ppc64-subprim-call-vinsn (stack-cons-list*)  .SPstkconslist-star)
+
+(define-ppc64-subprim-call-vinsn (list*) .SPconslist-star)
+
+(define-ppc64-subprim-call-vinsn (make-stack-block)  .SPmakestackblock)
+
+(define-ppc64-subprim-call-vinsn (make-stack-block0)  .Spmakestackblock0)
+
+(define-ppc64-subprim-call-vinsn (make-stack-list)  .Spmakestacklist)
+
+(define-ppc64-subprim-call-vinsn (make-stack-vector)  .SPmkstackv)
+
+(define-ppc64-subprim-call-vinsn (make-stack-gvector)  .SPstkgvector)
+
+(define-ppc64-subprim-call-vinsn (stack-misc-alloc)  .SPstack-misc-alloc)
+
+(define-ppc64-subprim-call-vinsn (stack-misc-alloc-init)  .SPstack-misc-alloc-init)
+
+(define-ppc64-subprim-call-vinsn (bind-nil)  .SPbind-nil)
+
+(define-ppc64-subprim-call-vinsn (bind-self)  .SPbind-self)
+
+(define-ppc64-subprim-call-vinsn (bind-self-boundp-check)  .SPbind-self-boundp-check)
+
+(define-ppc64-subprim-call-vinsn (bind)  .SPbind)
+
+(define-ppc64-subprim-jump-vinsn (nvalret :jumpLR) .SPnvalret)
+
+(define-ppc64-subprim-call-vinsn (nthrowvalues) .SPnthrowvalues)
+
+(define-ppc64-subprim-call-vinsn (nthrow1value) .SPnthrow1value)
+
+(define-ppc64-subprim-call-vinsn (slide-values) .SPmvslide)
+
+(define-ppc64-subprim-call-vinsn (macro-bind) .SPmacro-bind)
+
+(define-ppc64-subprim-call-vinsn (destructuring-bind-inner) .SPdestructuring-bind-inner)
+
+(define-ppc64-subprim-call-vinsn (destructuring-bind) .SPdestructuring-bind)
+
+(define-ppc64-subprim-call-vinsn (simple-keywords) .SPsimple-keywords)
+
+(define-ppc64-subprim-call-vinsn (keyword-args) .SPkeyword-args)
+
+(define-ppc64-subprim-call-vinsn (keyword-bind) .SPkeyword-bind)
+
+(define-ppc64-subprim-call-vinsn (stack-rest-arg) .SPstack-rest-arg)
+
+(define-ppc64-subprim-call-vinsn (req-stack-rest-arg) .SPreq-stack-rest-arg)
+
+(define-ppc64-subprim-call-vinsn (stack-cons-rest-arg) .SPstack-cons-rest-arg)
+
+(define-ppc64-subprim-call-vinsn (heap-rest-arg) .SPheap-rest-arg)
+
+(define-ppc64-subprim-call-vinsn (req-heap-rest-arg) .SPreq-heap-rest-arg)
+
+(define-ppc64-subprim-call-vinsn (heap-cons-rest-arg) .SPheap-cons-rest-arg)
+
+(define-ppc64-subprim-call-vinsn (opt-supplied-p) .SPopt-supplied-p)
+
+(define-ppc64-subprim-call-vinsn (gvector) .SPgvector)
+
+(define-ppc64-vinsn (nth-value :call :subprim-call) (((result :lisp))
+						     ())
+  (bla .SPnthvalue))
+
+(define-ppc64-subprim-call-vinsn (fitvals) .SPfitvals)
+
+(define-ppc64-subprim-call-vinsn (misc-alloc) .SPmisc-alloc)
+
+(define-ppc64-subprim-call-vinsn (misc-alloc-init) .SPmisc-alloc-init)
+
+(define-ppc64-subprim-call-vinsn (integer-sign) .SPinteger-sign)
+
+;;; Even though it's implemented by calling a subprim, THROW is really
+;;; a JUMP (to a possibly unknown destination).  If the destination's
+;;; really known, it should probably be inlined (stack-cleanup, value
+;;; transfer & jump ...)
+(define-ppc64-vinsn (throw :jump-unknown) (()
+						 ())
+  (bla .SPthrow))
+
+(define-ppc64-subprim-call-vinsn (mkcatchmv) .SPmkcatchmv)
+
+(define-ppc64-subprim-call-vinsn (mkcatch1v) .SPmkcatch1v)
+
+(define-ppc64-subprim-call-vinsn (setqsym) .SPsetqsym)
+
+(define-ppc64-subprim-call-vinsn (ksignalerr) .SPksignalerr)
+
+(define-ppc64-subprim-call-vinsn (subtag-misc-ref) .SPsubtag-misc-ref)
+
+(define-ppc64-subprim-call-vinsn (subtag-misc-set) .SPsubtag-misc-set)
+
+(define-ppc64-subprim-call-vinsn (mkunwind) .SPmkunwind)
+(define-ppc64-subprim-call-vinsn (nmkunwind) .SPnmkunwind)
+
+(define-ppc64-subprim-call-vinsn (progvsave) .SPprogvsave)
+
+(define-ppc64-subprim-jump-vinsn (progvrestore) .SPprogvrestore)
+
+(define-ppc64-subprim-call-vinsn (eabi-syscall) .SPeabi-syscall)
+
+(define-ppc64-subprim-call-vinsn (misc-ref) .SPmisc-ref)
+
+(define-ppc64-subprim-call-vinsn (misc-set) .SPmisc-set)
+
+(define-ppc64-subprim-call-vinsn (gets64) .SPgets64)
+
+(define-ppc64-subprim-call-vinsn (getu64) .SPgetu64)
+
+(define-ppc64-subprim-call-vinsn (makeu64) .SPmakeu64)
+
+(define-ppc64-subprim-call-vinsn (makes64) .SPmakes64)
+
+(define-ppc64-vinsn (poweropen-syscall :call :subprim-call) (()
+							  ())
+  (stw ppc::rzero ppc64::c-frame.crsave ppc::sp)
+  (bla .SPpoweropen-syscall))
+
+(define-ppc64-vinsn (poweropen-syscall-s64 :call :subprim-call) (()
+							      ())
+  (std ppc::sp ppc64::c-frame.crsave ppc::sp)
+  (bla .SPpoweropen-syscall))
+
+(define-ppc64-subprim-call-vinsn (eabi-ff-call) .SPeabi-ff-call)
+
+(define-ppc64-subprim-call-vinsn (poweropen-ff-call) .SPpoweropen-ffcall)
+
+(define-ppc64-subprim-call-vinsn (poweropen-ff-call-regs) .SPpoweropen-ffcall-return-registers)
+
+(define-ppc64-subprim-call-vinsn (poweropen-ff-callX) .SPpoweropen-ffcallX)
+
+(define-ppc64-subprim-call-vinsn (bind-interrupt-level-0) .SPbind-interrupt-level-0)
+
+(define-ppc64-vinsn bind-interrupt-level-0-inline (()
+                                                   ()
+                                                   ((tlb :imm)
+                                                    (value :imm)
+                                                    (link :imm)
+                                                    (temp :imm)))
+  (ld tlb ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (ld value ppc64::interrupt-level-binding-index tlb)
+  (ld link ppc64::tcr.db-link ppc64::rcontext)
+  (cmpdi value 0)
+  (li temp ppc64::interrupt-level-binding-index)
+  (stdu value -8 ppc::vsp)
+  (stdu temp -8 ppc::vsp)
+  (stdu link -8 ppc::vsp)
+  (std ppc::rzero ppc64::interrupt-level-binding-index tlb)
+  (std ppc::vsp  ppc64::tcr.db-link ppc64::rcontext)
+  (beq+ :done)
+  (mr ppc::nargs value)
+  (bgt :do-trap)
+  (ld ppc::nargs ppc64::tcr.interrupt-pending ppc64::rcontext)
+  :do-trap
+  (tdgti ppc::nargs 0)
+  :done)
+
+(define-ppc64-subprim-call-vinsn (bind-interrupt-level-m1) .SPbind-interrupt-level-m1)
+
+(define-ppc64-vinsn bind-interrupt-level-m1-inline (()
+                                                   ()
+                                                   ((tlb :imm)
+                                                    (oldvalue :imm)
+                                                    (link :imm)
+                                                    (newvalue :imm)
+                                                    (idx :imm)))
+  (li newvalue (ash -1 ppc64::fixnumshift))
+  (li idx ppc64::interrupt-level-binding-index)
+  (ld tlb ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (ld oldvalue ppc64::interrupt-level-binding-index tlb)
+  (ld link ppc64::tcr.db-link ppc64::rcontext)
+  (stdu oldvalue -8 ppc::vsp)
+  (stdu idx -8 ppc::vsp)
+  (stdu link -8 ppc::vsp)
+  (std newvalue ppc64::interrupt-level-binding-index tlb)
+  (std ppc::vsp  ppc64::tcr.db-link ppc64::rcontext)
+  :done)
+
+(define-ppc64-subprim-call-vinsn (bind-interrupt-level) .SPbind-interrupt-level)
+
+(define-ppc64-subprim-call-vinsn (unbind-interrupt-level) .SPunbind-interrupt-level)
+
+(define-ppc64-vinsn unbind-interrupt-level-inline (()
+                                                   ()
+                                                   ((tlb :imm)
+                                                    (link :imm)
+                                                    (value :imm)
+                                                    (save-nargs :u32)
+                                                    (crf0 :crf)
+                                                    (crf1 :crf)))
+  (ld tlb ppc64::tcr.tlb-pointer ppc64::rcontext)
+  (ld value ppc64::interrupt-level-binding-index tlb)
+  (ld link ppc64::tcr.db-link ppc64::rcontext)
+  (cmpdi crf1 value 0)
+  (ld value 16 link)
+  (ld link 0 link)
+  (cmpdi crf0 value 0)
+  (std value ppc64::interrupt-level-binding-index tlb)
+  (std link ppc64::tcr.db-link ppc64::rcontext)
+  (bge crf1 :done)
+  (blt crf0 :done)
+  (mr save-nargs ppc::nargs)
+  (ld ppc::nargs ppc64::tcr.interrupt-pending ppc64::rcontext)
+  (tdgti ppc::nargs 0)
+  (mr ppc::nargs save-nargs)
+  :done)
+
+(define-ppc64-vinsn fixnum->fpr (((f :double-float))
+                                          ((fixnum :imm))
+                                          ((imm :s64)))
+  (srawi imm fixnum ppc64::fixnumshift)
+  (std imm -8 ppc::sp)
+  (lfd f -8 ppc::sp)
+  (fcfid f f))
+
+(define-ppc64-vinsn branch-unless-arg-fixnum (()
+                                              ((arg :lisp)
+                                               (lab :label))
+                                              ((cr0 (:crf 0))
+                                               (tag :u8)))
+  (clrldi. tag arg (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (bne cr0 lab))
+
+(define-ppc64-vinsn branch-unless-both-args-fixnums (()
+                                              ((arg0 :lisp)
+                                               (arg1 :lisp)
+                                               (lab :label))
+                                              ((cr0 (:crf 0))
+                                               (tag :u8)))
+  (clrldi tag arg0 (- ppc64::nbits-in-word ppc64::nlisptagbits))
+  (rldimi. tag arg1 ppc64::nlisptagbits 58)
+  (bne cr0 lab))
+  
+                                              
+                                           
+
+;;; In case ppc64::*ppc-opcodes* was changed since this file was compiled.
+(queue-fixup
+ (fixup-vinsn-templates *ppc64-vinsn-templates* ppc::*ppc-opcode-numbers*))
+
+(provide "PPC64-VINSNS")
Index: /branches/new-random/compiler/PPC/ppc-arch.lisp
===================================================================
--- /branches/new-random/compiler/PPC/ppc-arch.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/ppc-arch.lisp	(revision 13309)
@@ -0,0 +1,499 @@
+;;;-*- Mode: Lisp; Package: (PPC :use CL) -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(defpackage "PPC"
+  (:use "CL"))
+
+(require "ARCH")
+
+(in-package "PPC")
+;;; Lisp registers.
+(eval-when (:compile-toplevel :execute)
+  (defmacro defregs (&body regs)
+    `(progn
+       (ccl::defenum () ,@regs)
+       (defparameter *gpr-register-names* ,(coerce (mapcar #'string regs) 'vector))))
+  (defmacro deffpregs (&body regs)
+    `(progn
+       (ccl::defenum () ,@regs)
+       (defparameter *fpr-register-names* ,(coerce (mapcar #'string regs) 'vector))))
+  (defmacro defvregs (&body regs)
+    `(progn
+      (ccl::defenum () ,@regs)
+      (defparameter *vector-register-names* ,(coerce (mapcar #'string regs) 'vector))
+      )))
+
+(defregs
+  rzero                                 ; Always contains 0; not as handy as it sounds.
+  sp					; The control stack.  Aligned on 16-byte boundary.
+  target-1                              ; volatile reg on Darwin, tp or TOC on Linux.
+  imm0                                  ; Unboxed, volatile registers.
+  imm1 
+  imm2 
+  imm3 
+  imm4
+  imm5
+  allocptr
+  allocbase
+  nargs                                 ; Volatile.  SHOULDN'T be used for tag extraction. (TWI handler confusion.)
+  tsp                                   ; Temp-stack pointer.
+  target-2
+  loc-pc                                ; for return PC only.
+  vsp                                   ; Value stack pointer; grows towards 0.
+  fn                                    ; Current function (constants vector).
+  temp3                                 ; Boxed, volatile registers.  Some
+					; may be defined on function entry.
+  temp2 
+  temp1 
+  temp0 
+  arg_x                                 ; Next-to-next-to-last function arg.
+  arg_y                                 ; Next-to-last function argument.
+  arg_z                                 ; Last function argument.
+  save7                                 ; Boxed, nonvolatile registers.
+  save6
+  save5
+  save4 
+  save3 
+  save2 
+  save1 
+  save0
+  )
+
+(deffpregs 
+  fp0
+  fp1
+  fp2
+  fp3
+  fp4
+  fp5
+  fp6
+  fp7
+  fp8
+  fp9
+  fp10
+  fp11
+  fp12
+  fp13
+  fp14
+  fp15
+  fp16
+  fp17
+  fp18
+  fp19
+  fp20
+  fp21
+  fp22
+  fp23
+  fp24
+  fp25
+  fp26
+  fp27
+  fp28
+  fp29
+  fp30
+  fp31)
+
+(defvregs
+  vr0					; General temp vector register
+  vr1					; Most-significant quadword when word-aligning
+  vr2					; Least-significant quadword when word-aligning
+  vr3					; Operand A resulting from word-aligning
+  vr4					; Operand B resulting from word-aligning
+  vr5					; Result from operations on A and B
+  vr6
+  vr7
+  vr8
+  vr9
+  vr10
+  vr11
+  vr12
+  vr13
+  vr14
+  vr15
+  vr16
+  vr17
+  vr18
+  vr19
+  ;;By convention, registers after this point are considered non-volatile. Callee should save.
+  vr20
+  vr21
+  vr22
+  vr23
+  vr24
+  vr25
+  vr26
+  vr27					; Permutation control register A for loads
+  vr28					; Permutation control register B for stores
+  vr29					; mask register
+  vr30					; All zeros
+  vr31					; All ones
+  )
+
+
+
+;;; Calling sequence may pass additional arguments in temp registers.
+;;; "nfn" (new function) is always passed; it's the new value of "fn".
+(defconstant nfn temp2)
+
+;;; CLOS may pass the context for, e.g.., CALL-NEXT-METHOD in 
+;;;; the "next-method-context" register.
+(defconstant next-method-context temp1)
+
+
+;;; It's handy to have 0.0 in an fpr.
+(defconstant fp-zero fp31)
+
+; Also handy to have #x4330000080000000 in an fpr, for s32->float conversion.
+(defconstant fp-s32conv fp30)
+
+(defconstant fname temp3)
+
+;;; Calling sequence may pass additional arguments in temp registers.
+;;; "nfn" (new function) is always passed; it's the new value of "fn".
+(defconstant nfn temp2)
+
+;;; CLOS may pass the context for, e.g.., CALL-NEXT-METHOD in 
+;;;; the "next-method-context" register.
+(defconstant next-method-context temp1)
+
+
+;;; It's handy to have 0.0 in an fpr.
+(defconstant fp-zero fp31)
+
+; Also handy to have #x4330000080000000 in an fpr, for s32->float conversion.
+(defconstant fp-s32conv fp30)
+
+(ccl::defenum (:prefix "FPSCR-" :suffix "-BIT")
+  fx
+  fex
+  vx
+  ox
+  ux
+  zx
+  xx
+  vxsnan
+  vxisi
+  vxidi
+  vxzdz
+  vximz
+  vxvc
+  fr
+  fi
+  fprfc
+  fl
+  fg
+  fe
+  fu
+  nil
+  vxsoft
+  vxsqrt
+  vxcvi
+  ve
+  oe
+  ue
+  ze
+  xe
+  ni
+  rn0
+  rn1
+)
+
+(ccl::defenum (:prefix "PPC-" :suffix "-BIT")
+  lt
+  gt
+  eq
+  so
+)
+
+;;; Kernel globals are allocated "below" nil.  This list (used to map
+;;; symbolic names to rnil-relative offsets) must (of course) exactly
+;;; match the kernel's notion of where things are.
+;;; The order here matches "ccl:lisp-kernel;lisp_globals.h" & the
+;;; lisp_globals record in "ccl:lisp-kernel;*constants*.s"
+(defparameter *ppc-kernel-globals*
+  '(get-tcr				; callback to obtain (real) tcr
+    tcr-count
+    interrupt-signal			; used by PROCESS-INTERRUPT
+    kernel-imports                      ; some things we need to have imported for us.
+    objc-2-personality
+    savetoc                  ; used to save TOC on some platforms
+    saver13                             ; used to save r13 on some platforms
+    subprims-base                       ; start of dynamic subprims jump table
+    ret1valaddr                         ; magic multiple-values return address.
+    tcr-key                             ; tsd key for thread's tcr
+    area-lock                           ; serialize access to gc
+    exception-lock			; serialize exception handling
+    static-conses                       ; when FREEZE is in effect
+    default-allocation-quantum          ; log2_heap_segment_size, as a fixnum.
+    intflag				; interrupt-pending flag
+    gc-inhibit-count                    ; for gc locking
+    refbits                             ; oldspace refbits
+    oldspace-dnode-count                ; number of dnodes in dynamic space that are older than
+                                        ; youngest generation
+    altivec-present                     ; non-zero if cpu supports AltiVec 
+    fwdnum                              ; fixnum: GC "forwarder" call count.
+    gc-count                            ; fixnum: GC call count.
+    gcable-pointers                     ; linked-list of weak macptrs.
+    heap-start                          ; start of lisp heap
+    heap-end                            ; end of lisp heap
+    statically-linked                   ; true if the lisp kernel is statically linked
+    stack-size                          ; value of --stack-size arg
+    objc-2-begin-catch                  ; objc_begin_catch
+    kernel-path
+    all-areas                           ; doubly-linked area list
+    lexpr-return                        ; multiple-value lexpr return address
+    lexpr-return1v                      ; single-value lexpr return address
+    in-gc                               ; non-zero when GC-ish thing active
+    free-static-conses                  ; fixnum
+    objc-2-end-catch                    ; _objc_end_catch
+    short-float-zero                    ; low half of 1.0d0
+    double-float-one                    ; high half of 1.0d0
+    static-cons-area                    ; 
+    exception-saved-registers           ; saved registers from exception frame
+    oldest-ephemeral                    ; doublenode address of oldest ephemeral object or 0
+    tenured-area                        ; the tenured_area.
+    errno                               ; address of C lib errno
+    argv                                ; address of C lib argv
+    host-platform                       ; 0 on MacOS, 1 on PPC Linux, 2 on VxWorks ...
+    batch-flag				; non-zero if --batch specified
+    unwind-resume			; _Unwind_Resume
+    weak-gc-method                      ; weak gc algorithm.
+    image-name				; current image name
+    initial-tcr                         ; initial thread's context record
+    ))
+
+;;; The order here matches "ccl:lisp-kernel;lisp_globals.h" and the nrs record
+;;; in "ccl:lisp-kernel;constants.s".
+(defparameter *ppc-nil-relative-symbols*
+  '(t
+    nil
+    ccl::%err-disp
+    ccl::cmain
+    eval
+    ccl::apply-evaluated-function
+    error    
+    ccl::%defun
+    ccl::%defvar
+    ccl::%defconstant
+    ccl::%macro
+    ccl::%kernel-restart
+    *package*
+    ccl::*total-bytes-freed*
+    :allow-other-keys    
+    ccl::%toplevel-catch%
+    ccl::%toplevel-function%
+    ccl::%pascal-functions%    
+    ccl::*all-metered-functions*
+    ccl::*total-gc-microseconds*
+    ccl::%builtin-functions%
+    ccl::%unbound-function%
+    ccl::%init-misc
+    ccl::%macro-code%
+    ccl::%closure-code%
+    ccl::%new-gcable-ptr
+    ccl::*gc-event-status-bits*
+    ccl::*post-gc-hook*
+    ccl::%handlers%
+    ccl::%all-packages%
+    ccl::*keyword-package* 
+    ccl::%finalization-alist%
+    ccl::%foreign-thread-control
+    ))
+
+;;; Old (and slightly confusing) name; NIL used to be in a register.
+(defparameter *ppc-nilreg-relative-symbols* *ppc-nil-relative-symbols*)
+
+
+
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defparameter *ppc-subprims-shift* 2)
+(defparameter *ppc-subprims-base* (ash 5 12) )
+)
+
+;;; For now, nothing's nailed down and we don't say anything about
+;;; registers clobbered.
+;;; These are shared between ppc32 and ppc64.
+(let* ((origin *ppc-subprims-base*)
+       (step (ash 1 *ppc-subprims-shift*)))
+  (flet ((define-ppc-subprim (name)
+             (ccl::make-subprimitive-info :name (string name)
+                                          :offset (prog1 origin
+                                                    (incf origin step)))))
+    (macrolet ((defppcsubprim (name)
+                   `(define-ppc-subprim ',name)))
+      (defparameter *ppc-subprims*
+        (vector
+         (defppcsubprim .SPjmpsym)
+         (defppcsubprim .SPjmpnfn)
+         (defppcsubprim .SPfuncall)
+         (defppcsubprim .SPmkcatch1v)
+         (defppcsubprim .SPmkunwind)
+         (defppcsubprim .SPmkcatchmv)
+         (defppcsubprim .SPthrow)
+         (defppcsubprim .SPnthrowvalues)
+         (defppcsubprim .SPnthrow1value)
+         (defppcsubprim .SPbind)
+         (defppcsubprim .SPbind-self)
+         (defppcsubprim .SPbind-nil)
+         (defppcsubprim .SPbind-self-boundp-check)
+         (defppcsubprim .SPrplaca)
+         (defppcsubprim .SPrplacd)
+         (defppcsubprim .SPconslist)
+         (defppcsubprim .SPconslist-star)
+         (defppcsubprim .SPstkconslist)
+         (defppcsubprim .SPstkconslist-star)
+         (defppcsubprim .SPmkstackv)
+         (defppcsubprim .SPsubtag-misc-ref)
+         (defppcsubprim .SPsetqsym)
+         (defppcsubprim .SPprogvsave)
+         (defppcsubprim .SPstack-misc-alloc)
+         (defppcsubprim .SPgvector)
+         (defppcsubprim .SPnvalret)
+         (defppcsubprim .SPmvpass)
+         (defppcsubprim .SPfitvals)
+         (defppcsubprim .SPnthvalue)
+         (defppcsubprim .SPvalues)
+         (defppcsubprim .SPdefault-optional-args)
+         (defppcsubprim .SPopt-supplied-p)
+         (defppcsubprim .SPheap-rest-arg)
+         (defppcsubprim .SPreq-heap-rest-arg)
+         (defppcsubprim .SPheap-cons-rest-arg)
+         (defppcsubprim .SPsimple-keywords)
+         (defppcsubprim .SPkeyword-args)
+         (defppcsubprim .SPkeyword-bind)
+         (defppcsubprim .SPpoweropen-ffcall)
+         (defppcsubprim .SParef2)
+         (defppcsubprim .SPksignalerr)
+         (defppcsubprim .SPstack-rest-arg)
+         (defppcsubprim .SPreq-stack-rest-arg)
+         (defppcsubprim .SPstack-cons-rest-arg)
+         (defppcsubprim .SPpoweropen-callbackX)
+         (defppcsubprim .SPcall-closure)
+         (defppcsubprim .SPgetXlong)
+         (defppcsubprim .SPspreadargz)
+         (defppcsubprim .SPtfuncallgen)
+         (defppcsubprim .SPtfuncallslide)
+         (defppcsubprim .SPtfuncallvsp)
+         (defppcsubprim .SPtcallsymgen)
+         (defppcsubprim .SPtcallsymslide)
+         (defppcsubprim .SPtcallsymvsp)
+         (defppcsubprim .SPtcallnfngen)
+         (defppcsubprim .SPtcallnfnslide)
+         (defppcsubprim .SPtcallnfnvsp)
+         (defppcsubprim .SPmisc-ref)
+         (defppcsubprim .SPmisc-set)
+         (defppcsubprim .SPstkconsyz)
+         (defppcsubprim .SPstkvcell0)
+         (defppcsubprim .SPstkvcellvsp)
+         (defppcsubprim .SPmakestackblock)
+         (defppcsubprim .SPmakestackblock0)
+         (defppcsubprim .SPmakestacklist)
+         (defppcsubprim .SPstkgvector)
+         (defppcsubprim .SPmisc-alloc)
+         (defppcsubprim .SPpoweropen-ffcallX)
+         (defppcsubprim .SPgvset)
+         (defppcsubprim .SPmacro-bind)
+         (defppcsubprim .SPdestructuring-bind)
+         (defppcsubprim .SPdestructuring-bind-inner)
+         (defppcsubprim .SPrecover-values)
+         (defppcsubprim .SPvpopargregs)
+         (defppcsubprim .SPinteger-sign)
+         (defppcsubprim .SPsubtag-misc-set)
+         (defppcsubprim .SPspread-lexpr-z)
+         (defppcsubprim .SPstore-node-conditional)
+         (defppcsubprim .SPreset)
+         (defppcsubprim .SPmvslide)
+         (defppcsubprim .SPsave-values)
+         (defppcsubprim .SPadd-values)
+         (defppcsubprim .SPpoweropen-callback)
+         (defppcsubprim .SPmisc-alloc-init)
+         (defppcsubprim .SPstack-misc-alloc-init)
+         (defppcsubprim .SPset-hash-key)
+         (defppcsubprim .SPaset2)
+         (defppcsubprim .SPcallbuiltin)
+         (defppcsubprim .SPcallbuiltin0)
+         (defppcsubprim .SPcallbuiltin1)
+         (defppcsubprim .SPcallbuiltin2)
+         (defppcsubprim .SPcallbuiltin3)
+         (defppcsubprim .SPpopj)
+         (defppcsubprim .SPrestorefullcontext)
+         (defppcsubprim .SPsavecontextvsp)
+         (defppcsubprim .SPsavecontext0)
+         (defppcsubprim .SPrestorecontext)
+         (defppcsubprim .SPlexpr-entry)
+         (defppcsubprim .SPpoweropen-syscall)
+         (defppcsubprim .SPbuiltin-plus)
+         (defppcsubprim .SPbuiltin-minus)
+         (defppcsubprim .SPbuiltin-times)
+         (defppcsubprim .SPbuiltin-div)
+         (defppcsubprim .SPbuiltin-eq)
+         (defppcsubprim .SPbuiltin-ne)
+         (defppcsubprim .SPbuiltin-gt)
+         (defppcsubprim .SPbuiltin-ge)
+         (defppcsubprim .SPbuiltin-lt)
+         (defppcsubprim .SPbuiltin-le)
+         (defppcsubprim .SPbuiltin-eql)
+         (defppcsubprim .SPbuiltin-length)
+         (defppcsubprim .SPbuiltin-seqtype)
+         (defppcsubprim .SPbuiltin-assq)
+         (defppcsubprim .SPbuiltin-memq)
+         (defppcsubprim .SPbuiltin-logbitp)
+         (defppcsubprim .SPbuiltin-logior)
+         (defppcsubprim .SPbuiltin-logand)
+         (defppcsubprim .SPbuiltin-ash)
+         (defppcsubprim .SPbuiltin-negate)
+         (defppcsubprim .SPbuiltin-logxor)
+         (defppcsubprim .SPbuiltin-aref1)
+         (defppcsubprim .SPbuiltin-aset1)
+         (defppcsubprim .SPbreakpoint)
+         (defppcsubprim .SPeabi-ff-call)
+         (defppcsubprim .SPeabi-callback)
+         (defppcsubprim .SPeabi-syscall)
+         (defppcsubprim .SPgetu64)
+         (defppcsubprim .SPgets64)
+         (defppcsubprim .SPmakeu64)
+         (defppcsubprim .SPmakes64)
+         (defppcsubprim .SPspecref)
+         (defppcsubprim .SPspecset)
+         (defppcsubprim .SPspecrefcheck)
+         (defppcsubprim .SPrestoreintlevel)
+         (defppcsubprim .SPmakes32)
+         (defppcsubprim .SPmakeu32)
+         (defppcsubprim .SPgets32)
+         (defppcsubprim .SPgetu32)
+         (defppcsubprim .SPfix-overflow)
+         (defppcsubprim .SPmvpasssym)
+         (defppcsubprim .SParef3)
+         (defppcsubprim .SPaset3)
+         (defppcsubprim .SPpoweropen-ffcall-return-registers)
+         (defppcsubprim .SPnmkunwind)
+         (defppcsubprim .SPset-hash-key-conditional)
+         (defppcsubprim .SPunbind-interrupt-level)
+         (defppcsubprim .SPunbind)
+         (defppcsubprim .SPunbind-n)
+         (defppcsubprim .SPunbind-to)
+         (defppcsubprim .SPbind-interrupt-level-m1)
+         (defppcsubprim .SPbind-interrupt-level)
+         (defppcsubprim .SPbind-interrupt-level-0)
+         (defppcsubprim .SPprogvrestore)
+         )))))
+
+
+  
+(provide "PPC-ARCH")
Index: /branches/new-random/compiler/PPC/ppc-asm.lisp
===================================================================
--- /branches/new-random/compiler/PPC/ppc-asm.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/ppc-asm.lisp	(revision 13309)
@@ -0,0 +1,2442 @@
+;;;-*- Mode: Lisp; Package: (PPC :use CL) -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(cl:eval-when (:compile-toplevel :execute)
+  (require "PPC-ARCH"))
+
+(in-package "PPC")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "RISC-LAP")
+(ccl::defenum ()
+  $ppc-operand-signed                    ; This operand takes signed values.
+  $ppc-operand-signopt                   ; This operand takes signed or positive values.
+  $ppc-operand-cr                        ; This operand uses symbolic names for CR fields
+  $ppc-operand-gpr                       ; This operand is a GPR.
+  $ppc-operand-fpr                       ; This operand is an FPR.
+  $ppc-operand-relative                  ; This operand is a relative branch offset.
+  $ppc-operand-absolute                  ; This operand is an absolute address.
+  $ppc-operand-optional                  ; This operand is optional, defaulting to 0.
+  $ppc-operand-next                      ; A brutal hack to make some rotate instructions work.
+  $ppc-operand-negative                  ; This operand should be treated as negative wrt overflow checking.
+  $ppc-operand-fake                      ; Used to signify operands whose value is that of another operand.
+  $ppc-operand-parens                    ; Operand should be enclosed in parens in traditional as syntax.
+  $ppc-operand-source                    ; Operand value is read by the instruction
+  $ppc-operand-dest                      ; Operand value is written by the instruction
+  $ppc-operand-vr			; Operand is an Altivec vector register
+  )
+
+(ccl::defenum ()
+  $ppc                                  ; Opcode is defined for the PowerPC architecture.
+  $b32                                  ; Opcode is only defined on 32 bit architectures.
+  $b64                                  ; Opcode is only defined on 64 bit architectures.
+)
+
+                                        ;;; A macro to extract the major opcode from an instruction.
+(defmacro major-opcode (i) `(ldb (byte 6 26) ,i))
+
+;; Operand class indices.
+(ccl::defenum ()
+  $unused
+  $ba                                   ; the BA field in an XL form instruction.
+  $bat                                  ; The BA field in an XL form instruction when it 
+                                        ;  must be the same as the BT field in the same instruction.
+  $bb                                   ; The BB field in an XL form instruction.
+  $bba                                  ; The BB field in an XL form instruction when it must be 
+                                        ;  the same as the BA field in the same instruction. 
+  $bd                                   ; The BD field in a B form instruction.  The lower two
+                                        ; bits are forced to zero.
+  $bda                                  ; The BD field in a B form instruction when absolute 
+                                        ;  addressing is used.
+  $bdm                                  ; The BD field in a B form instruction when the - modifier 
+                                        ;  is used. This sets the y bit of the BO field appropriately.
+  $bdma                                 ; The BD field in a B form instruction when the - modifier is used       
+                                        ;  and absolute addressing is used.   
+  $bdp                                  ; The BD field in a B form instruction when the + modifier 
+                                        ;  is used. This sets the y bit of the BO field appropriately.
+  $bdpa                                 ; The BD field in a B form instruction when the + modifier is used       
+                                        ;  and absolute addressing is used.   
+  $bf                                   ; The BF field in an X or XL form instruction.
+  $obf                                  ; An optional BF field.  This is used for comparison instructions,
+                                        ;  in which an omitted BF field is taken as zero.
+  $bfa                                  ; The BFA field in an X or XL form instruction.
+  $bi                                   ; The BI field in a B form or XL form instruction.
+  $bo                                   ; The BO field in a B form instruction.  Certain values are illegal.
+  $boe                                  ; The BO field in a B form instruction when the + or - modifier is         
+                                        ; used.  This is like the BO field, but it must be even.
+  $bt                                   ; The BT field in an X or XL form instruction.  
+  $cr                                   ; The condition register number portion of the BI field in a B form
+                                        ;  or XL form instruction.  This is used for the extended
+                                        ;  conditional branch mnemonics, which set the lower two bits of the
+                                        ;  BI field.  This field is optional.         
+  $d                                    ; The D field in a D form instruction.  This is a displacement off
+                                        ;  a register, and implies that the next operand is a register in     
+                                        ;  parentheses. 
+  $ds                                   ; The DS field in a DS form instruction.  This is like D, but the
+                                        ;  lower two bits are forced to zero.  
+  $flm                                  ; The FLM field in an XFL form instruction.  
+  $fra                                  ; The FRA field in an X or A form instruction.  
+  $frb                                  ; The FRB field in an X or A form instruction.  
+  $frc                                  ; The FRC field in an A form instruction.  
+  $frs                                  ; The FRS field in an X form instruction
+  $frt                                  ; The FRT field in a D, X or A form instruction.  
+  $fxm                                  ; The FXM field in an XFX instruction.  
+  $l                                    ; The L field in a D or X form instruction.  
+  $li                                   ; The LI field in an I form instruction.  The lower two bits are
+                                        ;  forced to zero.  
+  $lia                                  ; The LI field in an I form instruction when used as an absolute
+                                        ;  address.
+  $mb                                   ; The MB field in an M form instruction.  
+  $me                                   ; The ME field in an M form instruction.  
+  $mbe                                  ; The MB and ME fields in an M form instruction expressed a single
+                                        ;  operand which is a bitmask indicating which bits to select.  This
+                                        ;  is a two operand form using $PPC-OPERAND-NEXT.  See the
+                                        ;  description of $PPC-OPERAND-NEXT. for what this means.
+  $mbe-aux                              ; A placeholder for the second MBE operand.
+  $mb6                                  ; The MB or ME field in an MD or MDS form instruction.  The high
+                                        ;  bit is wrapped to the low end.  
+  $nb                                   ; The NB field in an X form instruction.  The value 32 is stored as 0.  
+  $nsi                                  ; The NSI field in a D form instruction.  This is the same as the
+                                        ;  SI field, only negated.  
+  $ra                                   ; The RA field in an D, DS, X, XO, M, or MDS form instruction.    
+  $ral                                  ; The RA field in a D or X form instruction which is an updating
+                                        ;  load, which means that the RA field may not be zero and may not
+                                        ;  equal the RT field.  
+  $ram                                  ; The RA field in an lmw instruction, which has special value
+                                        ;  restrictions.  
+  $ras                                  ; The RA field in a D or X form instruction which is an updating
+                                        ;  store or an updating floating point load, which means that the RA
+                                        ;  field may not be zero.  
+  $rTa                                  ; The RA field in an D, DS, X, XO, M, or MDS form instruction, when
+                                        ;  used as a destination.
+  $rb                                   ; The RB field in an X, XO, M, or MDS form instruction.    
+  $rbs                                  ; The RB field in an X form instruction when it must be the same as
+                                        ;  the RS field in the instruction.  This is used for extended
+                                        ;  mnemonics like mr.  
+  $rs                                   ; The RS field in a D, DS, X, XFX, XS, M, MD or MDS form   
+                                        ;  instruction. 
+  $rt                                   ; The RT field in a D, DS, X, XFX or XO form instruction.  
+  $sh                                   ; The SH field in an X or M form instruction.  
+  $sh6                                  ; The SH field in an MD form instruction.  This is split.  
+  $si                                   ; The SI field in a D form instruction.  
+  $sisignopt                            ; The SI field in a D form instruction when we accept a wide range
+                                        ;  of positive values.  
+  $spr                                  ; The SPR or TBR field in an XFX form instruction.  This is
+                                        ;  flipped--the lower 5 bits are stored in the upper 5 and vice-
+                                        ;  versa.  
+  $sr                                   ; The SR field in an X form instruction.  
+  $to                                   ; The TO field in a D or X form instruction.  
+  $u                                    ; The U field in an X form instruction.  
+  $ui                                   ; The UI field in a D form instruction.
+  $uuo-code                             ; UUO extended-operation code.
+  $uuo-errnum
+  $uuo-small-errnum
+  $va               ; The vA field in a vector instruction
+  $vb               ; The vB field in a vector instruction
+  $vc               ; the vC field in a vector VA form instruction
+  $vd               ; the vD field in a vector instruction
+  $vs               ; the vS field in a vector instruction
+  $vsh              ; the SH field in a vector instruction
+  $all/transient    ; the all/transient bit in a vector data stream instruction
+  $strm             ; the strm field in a vector data stream instruction
+  $vsimm            ; a 5-bit signed immediate that goes in the vA field
+  $vuimm            ; a 5-bit unsigned immediate that goes in the vA field
+  $ls               ; The LS field in an X (sync) form instruction
+
+  )
+
+(defconstant $me6 $mb6)
+(defconstant $tbr $spr)
+
+(defmacro defopmask (name width offset)
+  `(defconstant ,name (mask-field (byte ,width ,offset) -1)))
+
+(defopmask $ba-mask 5 16)
+(defopmask $bb-mask 5 11)
+(defopmask $bi-mask 5 16)
+(defopmask $bo-mask 5 21)
+(defopmask $fra-mask 5 16)
+(defopmask $frb-mask 5 11)
+(defopmask $frc-mask 5 6)
+(defopmask $mb-mask 5 6)
+(defopmask $me-mask 5 1)
+(defopmask $mb6-mask 6 5)
+(defopmask $ra-mask 5 16)
+(defopmask $rb-mask 5 11)
+(defopmask $rt-mask 5 21)
+(defopmask $sh-mask 5 11)
+(defconstant $sh6-mask (logior (mask-field (byte 1 1) -1) (mask-field (byte 5 11) -1)))
+(defopmask $spr-mask 10 11)
+(defopmask $to-mask 5 21)
+(defopmask $uuo-code-mask 7 4)
+(defopmask $uuo-interr-mask 10 16)
+(defopmask $uuo-small-interr-mask 5 21)
+(defopmask $vsimm-mask 5 16)
+(defopmask $vuimm-mask 5 16)
+
+)
+
+
+
+
+(eval-when (:compile-toplevel :execute)
+  (defmacro ppc-op (index width offset &optional insert-function extract-function &rest flags)
+    `(ccl::make-operand :index ,index
+      :width ,width 
+      :offset ,offset 
+      :insert-function ',insert-function
+      :extract-function ',extract-function
+      :flags (logior ,@(mapcar #'(lambda (f) `(ash 1 ,f)) flags)))))
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defparameter *ppc-operands*
+  (vector
+   (ppc-op $unused 0 0)
+   (ppc-op $ba 5 16 nil nil $ppc-operand-cr)
+   (ppc-op $bat 5 16 insert-bat extract-bat ccl::operand-fake)
+   (ppc-op $bb 5 11 nil nil $ppc-operand-cr)
+   (ppc-op $bba 5 11 insert-bba extract-bba ccl::operand-fake)
+   (ppc-op $bd 16 0 insert-bd extract-bd $ppc-operand-relative $ppc-operand-signed)
+   (ppc-op $bda 16 0 insert-bd extract-bd $ppc-operand-absolute $ppc-operand-signed)
+   (ppc-op $bdm 16 0 insert-bdm extract-bdm $ppc-operand-relative $ppc-operand-signed)
+   (ppc-op $bdma 16 0 insert-bdm extract-bdm $ppc-operand-absolute $ppc-operand-signed)
+   (ppc-op $bdp 16 0 insert-bdp extract-bdp $ppc-operand-relative $ppc-operand-signed)
+   (ppc-op $bdpa 16 0 insert-bdp extract-bdp $ppc-operand-absolute $ppc-operand-signed)
+   (ppc-op $bf 3 23 insert-bf extract-bf $ppc-operand-cr)
+   (ppc-op $obf 3 23 insert-bf extract-bf $ppc-operand-cr ccl::operand-optional)
+   (ppc-op $bfa 3 18 insert-cr extract-cr $ppc-operand-cr)
+   (ppc-op $bi 5 16 nil nil $ppc-operand-cr)
+   (ppc-op $bo 5 21 insert-bo extract-bo)
+   (ppc-op $boe 5 21 insert-boe extract-boe)
+   (ppc-op $bt 5 21 nil nil $ppc-operand-cr)
+   (ppc-op $cr 5 16 insert-cr extract-cr $ppc-operand-cr ccl::operand-optional)
+   (ppc-op $d 16 0 nil nil $ppc-operand-parens $ppc-operand-signed)
+   (ppc-op $ds 16 0 insert-ds extract-ds $ppc-operand-parens $ppc-operand-signed)
+   (ppc-op $flm 8 17)
+   (ppc-op $fra 5 16 nil nil $ppc-operand-fpr $ppc-operand-source)
+   (ppc-op $frb 5 11 nil nil $ppc-operand-fpr $ppc-operand-source)
+   (ppc-op $frc 5 6 nil nil $ppc-operand-fpr $ppc-operand-source)
+   (ppc-op $frs 5 21 nil nil $ppc-operand-fpr $ppc-operand-source)
+   (ppc-op $frt 5 21 nil nil $ppc-operand-fpr $ppc-operand-dest)
+   (ppc-op $fxm 8 12)
+   (ppc-op $l 1 21 nil nil ccl::operand-optional)
+   (ppc-op $li 26 0 insert-li extract-li $ppc-operand-relative $ppc-operand-signed)
+   (ppc-op $lia 26 0 insert-li extract-li $ppc-operand-absolute $ppc-operand-signed)
+   (ppc-op $mb 5 6)
+   (ppc-op $me 5 1 )
+   (ppc-op $mbe 5 6 nil nil ccl::operand-optional $ppc-operand-next)
+   (ppc-op $mbe-aux 10 1 insert-mbe extract-mbe)
+   (ppc-op $mb6 6 5 insert-mb6 extract-mb6)
+   (ppc-op $nb 6 11 insert-nb extract-nb)
+   (ppc-op $nsi 16 0 insert-nsi extract-nsi $ppc-operand-negative $ppc-operand-signed)
+   (ppc-op $ra 5 16 nil nil $ppc-operand-gpr $ppc-operand-source)
+   (ppc-op $ral 5 16 insert-ral nil $ppc-operand-gpr $ppc-operand-source)
+   (ppc-op $ram 5 16 insert-ram nil $ppc-operand-gpr $ppc-operand-source)
+   (ppc-op $ras 5 16 insert-ras nil $ppc-operand-gpr $ppc-operand-source)
+   (ppc-op $rTa 5 16 nil nil $ppc-operand-gpr $ppc-operand-dest)
+   (ppc-op $rb 5 11 nil nil $ppc-operand-gpr $ppc-operand-source)
+   (ppc-op $rbs 5 11 insert-rbs extract-rbs ccl::operand-fake)
+   (ppc-op $rs 5 21 nil nil $ppc-operand-gpr $ppc-operand-source)
+   (ppc-op $rt 5 21 nil nil $ppc-operand-gpr $ppc-operand-dest)
+   (ppc-op $sh 5 11)
+   (ppc-op $sh6 6 1 insert-sh6 extract-sh6)
+   (ppc-op $si 16 0 nil nil $ppc-operand-signed)
+   (ppc-op $sisignopt 16 0 nil nil $ppc-operand-signed $ppc-operand-signopt)
+   (ppc-op $spr 10 11 insert-spr extract-spr)
+   (ppc-op $sr 4 16)
+   (ppc-op $to 5 21)
+   (ppc-op $u 4 12)
+   (ppc-op $ui 16 0)
+   (ppc-op $uuo-code 7 4)
+   (ppc-op $uuo-errnum 10 16)
+   (ppc-op $uuo-small-errnum 5 21)
+   (ppc-op $va 5 16 nil nil $ppc-operand-vr $ppc-operand-source)
+   (ppc-op $vb 5 11 nil nil $ppc-operand-vr $ppc-operand-source)
+   (ppc-op $vc 5 6  nil nil $ppc-operand-vr $ppc-operand-source)
+   (ppc-op $vd 5 21 nil nil $ppc-operand-vr $ppc-operand-dest)
+   (ppc-op $vs 5 21 nil nil $ppc-operand-vr $ppc-operand-source)
+   (ppc-op $vsh 4 6 nil nil)
+   (ppc-op $all/transient 1 25 nil nil)
+   (ppc-op $strm 2 21 nil nil)
+   (ppc-op $vsimm 5 16 nil nil $ppc-operand-signed)
+   (ppc-op $vuimm 5 16 nil nil)
+   (ppc-op $ls 21 2 nil nil ccl::operand-optional)
+
+   ))
+
+
+(eval-when (:load-toplevel :execute)
+  (dotimes (i (length *ppc-operands*))
+    (unless (= i (ccl::operand-index (svref *ppc-operands* i)))
+      (break "Operand table out-of-synch at ~d : ~s. " i (svref *ppc-operands* i)))))
+
+)
+
+(eval-when (:compile-toplevel :execute)
+;; The main opcode of an instruction.
+(defmacro op (x &optional (base 0)) `(dpb ,x (byte 6 26) ,base))
+(defconstant $op-mask (mask-field (byte 6 26) -1))
+
+;; The main opcode combined with a trap code in the TO field
+;; of a D form instruction.  Used for extended mnemonics for
+;; the trap instructions.
+(defmacro opto (x to) `(op ,x (dpb ,to (byte 5 21) 0)))
+(defconstant $opto-mask (opto -1 -1))
+
+;; The main opcode combined with a comparison size bit in the L field
+;; of a D form or X form instruction.  Used for extended mnemonics for
+;; the comparison instructions.
+(defmacro opl (x l) `(op ,x (dpb ,l (byte 1 21) 0)))
+(defconstant $opl-mask (opl -1 -1))
+
+;; An A form instruction.
+(defmacro a (op xop rc) `(op ,op (dpb ,xop (byte 5 1) (logand ,rc 1))))
+(defconstant $a-mask (a -1 -1 -1))
+
+;; An A-MASK with the FRB field fixed.  
+(defconstant $afrb-mask (logior $a-mask $frb-mask))
+
+;; An A-MASK with the FRC field fixed.  
+(defconstant $afrc-mask (logior $a-mask $frc-mask))
+
+;; An A-MASK with the FRA and FRC fields fixed.  
+(defconstant $afrafrc-mask (logior $a-mask $fra-mask $frc-mask))
+
+;; A B form instruction.  
+(defmacro b (op aa lk) `(op ,op (dpb ,aa (byte 1 1) (logand ,lk 1))))
+(defconstant $b-mask (b -1 -1 -1))
+
+;; A B form instruction setting the BO field.  
+(defmacro bbo (op bo aa lk) 
+  `(op ,op (dpb ,bo (byte 5 21) (dpb ,aa (byte 1 1) (logand ,lk 1)))))
+(defconstant $bbo-mask (bbo -1 -1 -1 -1))
+
+;; A BBO-MASK with the y bit of the BO field removed.  This permits
+;; matching a conditional branch regardless of the setting of the y
+;; bit.  
+(defconstant $y-mask (dpb 1 (byte 1 21) 0))
+(defconstant $bboy-mask (logandc2 $bbo-mask $y-mask))
+
+;; A B form instruction setting the BO field and the condition bits of
+;; the BI field.  
+(defmacro bbocb (op bo cb  aa lk)
+  `(op ,op (dpb ,bo (byte 5 21) (dpb ,cb (byte 2 16) (dpb ,aa (byte 1 1) (logand ,lk 1))))))
+(defconstant $bbocb-mask (bbocb -1 -1 -1 -1 -1))
+
+;; A BBOCB-MASK with the y bit of the BO field removed.  
+(defconstant $bboycb-mask (logandc2 $bbocb-mask $y-mask))
+
+;; A BBOYCB-MASK in which the BI field is fixed.  
+(defconstant $bboybi-mask (logior $bboycb-mask $bi-mask))
+
+;; The main opcode mask with the RA field clear.  
+(defconstant $DRA-MASK (logior $op-mask $ra-mask))
+
+;; A DS form instruction.  
+(defmacro dso (op xop) `(op ,op  (logand ,xop #x3)))
+(defconstant $ds-mask (dso -1 -1))
+
+;; An M form instruction.  
+(defmacro m (op &optional (rc 0)) `(op ,op (logand ,rc 1)))
+(defconstant $m-mask (m -1 -1))
+
+;; An M form instruction with the ME field specified.  
+(defmacro mme (op me &optional (rc 0)) `(op ,op (dpb ,me (byte 5 1) (logand ,rc 1))))
+
+;; An M-MASK with the MB and ME fields fixed.  
+(defconstant $mmbme-mask (logior $m-mask $mb-mask $me-mask))
+
+;; An M-MASK with the SH and ME fields fixed.  
+(defconstant $mshme-mask (logior $m-mask $sh-mask $me-mask))
+
+;; An MD form instruction.  
+(defmacro md (op xop &optional (rc 0)) `(op ,op (dpb ,xop (byte 3 2) (logand ,rc 1))))
+(defconstant $md-mask (md -1 -1 -1))
+
+;; An MD-MASK with the MB field fixed.  
+(defconstant $mdmb-mask (logior $md-mask $mb6-mask))
+
+;; An MD-MASK with the SH field fixed.  
+(defconstant $mdsh-mask (logior $md-mask $sh6-mask))
+
+;; An MDS form instruction. 
+(defmacro mds (op xop &optional (rc 0)) `(op ,op (dpb ,xop (byte 4 1) (logand ,rc 1))))
+(defconstant $mds-mask (mds -1 -1 -1))
+
+;; An MDS-MASK with the MB field fixed.  
+(defconstant $mdsmb-mask (logior $mds-mask $mb6-mask))
+
+;; An SC form instruction. 
+(defmacro sc (op sa lk) `(op ,op (dpb ,sa (byte 1 1) (logand ,lk 1))))
+(defconstant $sc-mask (sc -1 -1 -1))
+
+;; A UUO is an unimplemented instruction that the exception handler
+;; decodes and emulates. The major opcode and low three bits are clear;
+;; bit 3 is set.
+
+(defmacro uuo (xop) `(op 0 (dpb ,xop (byte 7 4) (logior (ash 1 3) ppc32::fulltag-imm))))
+(defconstant $uuo-mask (logior $op-mask (uuo -1)))
+(defconstant $uuorb-mask (logior $uuo-mask $rb-mask))
+
+;; An X form instruction.  
+(defmacro x (op xop &optional (base 0)) `(op ,op (dpb ,xop (byte 10 1) ,base)))
+
+;; An X form instruction with the RC bit specified.
+(defmacro xrc (op xop &optional (rc 0)) `(op ,op (dpb ,xop (byte 10 1) (logand ,rc 1))))
+
+;; The mask for an X form instruction. 
+(defconstant $x-mask (xrc -1 -1 -1))
+
+;; An X-MASK with the RA field fixed.  
+(defconstant $xra-mask (logior $x-mask $ra-mask))
+
+;; An X-MASK with the RB field fixed.  
+(defconstant $xrb-mask (logior $x-mask $rb-mask))
+
+;; An X-MASK with the RT field fixed.  
+(defconstant $xrt-mask (logior $x-mask $rt-mask))
+
+;; An X-MASK with the RA and RB fields fixed.  
+(defconstant $xrarb-mask (logior $x-mask $ra-mask $rb-mask))
+
+;; An X-MASK with the RT and RA fields fixed.  
+(defconstant $xrtra-mask (logior $x-mask $rt-mask $ra-mask))
+
+;; An X form comparison instruction.  
+(defmacro xcmpl (op xop l)
+  `(x ,op ,xop (dpb ,l (byte 1 21) 0)))
+
+;; The mask for an X form comparison instruction.  
+(defconstant $xcmp-mask (logior $x-mask (ash 1  22)))
+
+;; The mask for an X form comparison instruction with the L field
+;; fixed.  
+(defconstant $xcmpl-mask (logior $xcmp-mask (ash 1 21)))
+
+(defmacro xsync (op xop l) `(x ,op ,xop (dpb ,l (byte 3 21) 0)))
+(defconstant $xsync-mask #xff9fffff)
+
+;; An X form trap instruction with the TO field specified.  
+(defmacro xto (op xop to) `(x ,op ,xop (dpb ,to (byte 5 21) 0)))
+(defconstant $xto-mask (xto -1 -1 -1))
+
+;; An XFL form instruction.  
+(defmacro xfl (op xop &optional (rc 0)) `(op ,op (dpb ,xop (byte 10 1) (logand ,rc 1))))
+(defconstant $xfl-mask (logior (xfl -1 -1 -1) (ash 1 25) (ash 1 16)))
+
+;; An XL form instruction with the LK field set to 0. 
+(defmacro xl (op xop &optional (base 0)) `(op ,op (dpb ,xop (byte 10 1) ,base)))
+
+;; An XL form instruction which uses the LK field.  
+(defmacro xllk (op xop &optional (lk 0)) `(xl ,op ,xop (logand ,lk 1)))
+
+;; The mask for an XL form instruction.  
+(defconstant $xl-mask (xllk -1 -1 -1))
+
+;; An XL form instruction which explicitly sets the BO field. 
+(defmacro xlo (op bo xop &optional (lk 0))
+  `(xl ,op ,xop (dpb ,bo (byte 5 21) (logand ,lk 1))))
+(defconstant $xlo-mask (logior $xl-mask $bo-mask))
+
+;; An XL form instruction which explicitly sets the y bit of the BO
+;; field.  
+(defmacro xlylk (op xop y &optional (lk 0)) `(xl ,op ,xop (dpb ,y (byte 1 21) (logand ,lk 1))))
+(defconstant $xlylk-mask (logior $xl-mask $y-mask))
+
+;; An XL form instruction which sets the BO field and the condition
+;; bits of the BI field.  
+(defmacro xlocb (op bo cb xop &optional (lk 0))
+  `(x ,op ,xop (dpb ,bo (byte 5 21) (dpb ,cb (byte 2 16) (logand ,lk 1)))))
+(defconstant $xlocb-mask (xlocb -1 -1 -1 -1 -1))
+
+;; An XL-MASK or XLYLK-MASK or XLOCB-MASK with the BB field fixed.  
+(defconstant $xlbb-mask (logior $xl-mask $bb-mask))
+(defconstant $xlybb-mask (logior $xlylk-mask $bb-mask))
+(defconstant $xlbocbbb-mask (logior $xlocb-mask $bb-mask))
+
+;; An XL-MASK with the BO and BB fields fixed.  
+(defconstant $xlbobb-mask (logior $xl-mask $bo-mask $bb-mask))
+
+;; An XL-MASK with the BO, BI and BB fields fixed.  
+(defconstant $xlbobibb-mask (logior $xl-mask $bo-mask $bi-mask $bb-mask))
+
+;; An XO form instruction. 
+(defmacro xo (op xop oe rc)
+  `(op ,op (dpb ,xop (byte 9 1) (dpb ,oe (byte 1 10) (logand ,rc 1)))))
+(defconstant $xo-mask (xo -1 -1 -1 -1))
+
+;; An XO-MASK with the RB field fixed.  
+(defconstant $xorb-mask (logior $xo-mask $rb-mask))
+
+;; An XS form instruction.  
+(defmacro xs (op xop &optional (rc 0)) 
+  `(op ,op (dpb ,xop (byte 9 2) (logand ,rc 1))))
+(defconstant $xs-mask (xs -1 -1 -1))
+
+;; An XFX form instruction with the SPR field filled in.  
+(defmacro xspr (op xop spr) `(x ,op ,xop (dpb ,spr (byte 5 16) (ash (logand ,spr #x3e0) 6))))
+(defconstant $xspr-mask (logior $x-mask $spr-mask))
+
+;; A VX form instruction.
+(defmacro vx (op xop) `(op ,op (dpb ,xop (byte 11 0) 0)))
+(defconstant $vx-mask (vx -1 -1))
+
+;; A VXR form instruction.
+(defmacro vxr (op xop rc) `(op ,op (dpb ,xop (byte 10 0) (ash (logand ,rc 1) 10))))
+(defconstant $vxr-mask (vxr -1 -1 1))
+  
+;; A VXA form instruction.
+(defmacro vxa (op xop &optional (base 0)) `(op ,op (dpb ,xop (byte 6 0) ,base)))
+(defconstant $vxa-mask (vxa -1 -1))
+(defconstant $vash-mask (logior $vxa-mask (ash 1 10)))
+
+
+
+
+
+;; The BO encodings used in extended conditional branch mnemonics.  
+(defconstant $bodnzf #x0)
+(defconstant $bodnzfp #x1)
+(defconstant $bodzf #x2)
+(defconstant $bodzfp #x3)
+(defconstant $bof #x4)
+(defconstant $bofp #x5)
+(defconstant $bodnzt #x8)
+(defconstant $bodnztp #x9)
+(defconstant $bodzt #xa)
+(defconstant $bodztp #xb)
+(defconstant $bot #xc)
+(defconstant $botp #xd)
+(defconstant $bodnz #x10)
+(defconstant $bodnzp #x11)
+(defconstant $bodz #x12)
+(defconstant $bodzp #x13)
+(defconstant $bou #x14)
+ 
+;; The BI condition bit encodings used in extended conditional branch
+;;   mnemonics. 
+(defconstant $cblt 0)
+(defconstant $cbgt 1)
+(defconstant $cbeq 2)
+(defconstant $cbso 3)
+
+;; The TO encodings used in extended trap mnemonics.
+(defconstant $tolgt #x1)
+(defconstant $tollt #x2)
+(defconstant $toeq #x4)
+(defconstant $tolge #x5)
+(defconstant $tolnl #x5)
+(defconstant $tolle #x6)
+(defconstant $tolng #x6)
+(defconstant $togt #x8)
+(defconstant $toge #xc)
+(defconstant $tonl #xc)
+(defconstant $tolt #x10)
+(defconstant $tole #x14)
+(defconstant $tong #x14)
+(defconstant $tone #x18)
+(defconstant $tou #x1f)
+
+
+)
+
+
+
+(eval-when (:compile-toplevel :execute)
+(defun max-operand-count (opnums)
+  (let* ((max 0))
+    (declare (fixnum max))
+    (dolist (i opnums max)
+      (unless 
+        (logbitp ccl::operand-fake (ccl::operand-flags (svref *ppc-operands* i)))
+        (incf max)))))
+
+(defun min-operand-count (opnums)
+  (let* ((min 0))
+    (declare (fixnum min))
+    (dolist (i opnums min)
+      (let* ((flags (ccl::operand-flags (svref *ppc-operands* i))))
+        (declare (fixnum flags))
+        (unless (or (logbitp ccl::operand-fake flags)
+                    (logbitp ccl::operand-optional flags))
+          (incf min))))))
+
+(defmacro ppc-opcode (name opcode mask (&rest flags) &rest operands)
+  `(ccl::make-opcode
+    :name (string ',name)
+    :opcode ,opcode
+    :majorop (major-opcode ,opcode)
+    :mask ,mask
+    :flags (logior ,@(mapcar #'(lambda (f) `(ash 1 ,f)) flags))
+    :min-args (min-operand-count (list ,@operands))
+    :max-args (max-operand-count (list ,@operands))
+    :operands (mapcar #'(lambda (i) (svref *ppc-operands* i)) (list ,@operands))))
+)
+
+
+; The #.s are a necesary evil here (to keep the function vector size < 32K) in MCL 3.0.
+
+; If you change this, you need to evaluate (initialize-ppc-opcode-numbers)
+(defparameter *ppc-opcodes*
+  (vector
+   #.(ppc-opcode uuo_interr (uuo 11) $uuo-mask ($ppc) $uuo-errnum $rb)
+   #.(ppc-opcode uuo_intcerr (uuo 12) $uuo-mask ($ppc) $uuo-errnum $rb)
+   #.(ppc-opcode uuo_interr2 (uuo 13) $uuo-mask ($ppc) $uuo-small-errnum $ra $rb)
+   #.(ppc-opcode uuo_intcerr2 (uuo 14) $uuo-mask ($ppc) $uuo-small-errnum $ra $rb)
+   ;; We'll clearly need more; add a few "anonymous" ones for now so that
+   ;; other opcode's opcode numbers stay constant.
+   #.(ppc-opcode uuo_fpuXbinop (uuo 22) $uuo-mask ($ppc) $frt $fra $frb)
+
+   #.(ppc-opcode tdlgti (opto 2 $tolgt) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdllti (opto 2 $tollt) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdeqi (opto 2 $toeq) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdlgei (opto 2 $tolge) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdlnli (opto 2 $tolnl) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdllei (opto 2 $tolle) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdlngi (opto 2 $tolng) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdgti (opto 2 $togt) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdgei (opto 2 $toge) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdnli (opto 2 $tonl) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdlti (opto 2 $tolt) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdlei (opto 2 $tole) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdngi (opto 2 $tong) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdnei (opto 2 $tone) $opto-mask ($ppc $b64) $ra $si)
+   #.(ppc-opcode tdi (op 2) $op-mask ($ppc $b64) $to $ra $si)
+
+   #.(ppc-opcode twlgti (opto 3 $tolgt) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twllti (opto 3 $tollt) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode tweqi (opto 3 $toeq) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twlgei (opto 3 $tolge) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twlnli (opto 3 $tolnl) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twllei (opto 3 $tolle) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twlngi (opto 3 $tolng) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twgti (opto 3 $togt) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twgei (opto 3 $toge) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twnli (opto 3 $tonl) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twlti (opto 3 $tolt) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twlei (opto 3 $tole) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twngi (opto 3 $tong) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twnei (opto 3 $tone) $opto-mask ($ppc) $ra $si)
+   #.(ppc-opcode twi (op 3) $op-mask ($ppc) $to $ra $si)
+
+   #.(ppc-opcode mfvscr (vx 4 1540) $vx-mask ($ppc) $vd )
+   #.(ppc-opcode mtvscr (vx 4 1604) $vx-mask ($ppc) $vd )
+   #.(ppc-opcode vaddcuw (vx 4 384) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vaddfp (vx 4 10) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vaddsbs (vx 4 768) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vaddshs (vx 4 832) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vaddsws (vx 4 896) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vaddubm (vx 4 0) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vaddubs (vx 4 512) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vadduhm (vx 4 64) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vadduhs (vx 4 576) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vadduwm (vx 4 128) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vadduws (vx 4 640) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vand (vx 4 1028) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vandc (vx 4 1092) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vavgsb (vx 4 1282) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vavgsh (vx 4 1346) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vavgsw (vx 4 1410) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vavgub (vx 4 1026) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vavguh (vx 4 1090) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vavguw (vx 4 1154) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcfsx (vx 4 842) $vx-mask ($ppc) $vd $vb $vuimm )
+   #.(ppc-opcode vcfux (vx 4 778) $vx-mask ($ppc) $vd $vb $vuimm )
+   #.(ppc-opcode vcmpbfp (vxr 4 966 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpbfp. (vxr 4 966 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpeqfp (vxr 4 198 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpeqfp. (vxr 4 198 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpequb (vxr 4 6 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpequb. (vxr 4 6 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpequh (vxr 4 70 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpequh. (vxr 4 70 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpequw (vxr 4 134 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpequw. (vxr 4 134 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgefp (vxr 4 454 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgefp. (vxr 4 454 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtfp (vxr 4 710 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtfp. (vxr 4 710 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtsb (vxr 4 774 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtsb. (vxr 4 774 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtsh (vxr 4 838 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtsh. (vxr 4 838 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtsw (vxr 4 902 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtsw. (vxr 4 902 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtub (vxr 4 518 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtub. (vxr 4 518 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtuh (vxr 4 582 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtuh. (vxr 4 582 1) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtuw (vxr 4 646 0) $vxr-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vcmpgtuw. (vxr 4 646 1) $vxr-mask  ($ppc) $vd $va $vb )
+   #.(ppc-opcode vctsxs (vx 4 970) $vx-mask ($ppc) $vd $vb $vuimm )
+   #.(ppc-opcode vctuxs (vx 4 906) $vx-mask ($ppc) $vd $vb $vuimm )
+   #.(ppc-opcode vexptefp (vx 4 394) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vlogefp (vx 4 458) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vmaddfp (vxa 4 46) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmaxfp (vx 4 1034) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmaxsb (vx 4 258) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmaxsh (vx 4 322) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmaxsw (vx 4 386) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmaxub (vx 4 2) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmaxuh (vx 4 66) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmaxuw (vx 4 130) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmhaddshs (vxa 4 32) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmhraddshs (vxa 4 33) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vminfp (vx 4 1098) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vminsb (vx 4 770) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vminsh (vx 4 834) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vminsw (vx 4 898) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vminub (vx 4 514) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vminuh (vx 4 578) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vminuw (vx 4 642) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmladduhm (vxa 4 34) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmrghb (vx 4 12) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmrghh (vx 4 76) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmrghw (vx 4 140) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmrglb (vx 4 268) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmrglh (vx 4 332) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmrglw (vx 4 396) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmsummbm (vxa 4 37) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmsumshm (vxa 4 40) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmsumshs (vxa 4 41) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmsumubm (vxa 4 36) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmsumuhm (vxa 4 38) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmsumuhs (vxa 4 39) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vmulesb (vx 4 776) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmulesh (vx 4 840) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmuleub (vx 4 520) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmuleuh (vx 4 584) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmulosb (vx 4 264) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmulosh (vx 4 328) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmuloub (vx 4 8) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vmulouh (vx 4 72) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vnmsubfp (vxa 4 47) $vxa-mask ($ppc) $vd $va $vc $vb )
+   #.(ppc-opcode vnor (vx 4 1284) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vor (vx 4 1156) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vperm (vxa 4 43) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vpkpx (vx 4 782) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkshss (vx 4 398) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkshus (vx 4 270) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkswss (vx 4 462) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkswus (vx 4 334) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkuhum (vx 4 14) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkuhus (vx 4 142) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkuwum (vx 4 78) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vpkuwus (vx 4 206) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vrefp (vx 4 266) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vrfim (vx 4 714) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vrfin (vx 4 522) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vrfip (vx 4 650) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vrfiz (vx 4 586) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vrlb (vx 4 4) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vrlh (vx 4 68) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vrlw (vx 4 132) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vrsqrtefp (vx 4 330) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vsel (vxa 4 42) $vxa-mask ($ppc) $vd $va $vb $vc )
+   #.(ppc-opcode vsl (vx 4 452) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vslb (vx 4 260) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsldoi (vxa 4 44) $vxa-mask ($ppc) $vd $va $vb $vsh)
+   #.(ppc-opcode vslh (vx 4 324) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vslo (vx 4 1036) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vslw (vx 4 388) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vspltb (vx 4 524) $vx-mask ($ppc) $vd $vb $vuimm )
+   #.(ppc-opcode vsplth (vx 4 588) $vx-mask ($ppc) $vd $vb $vuimm )
+   #.(ppc-opcode vspltisb (vx 4 780) $vx-mask ($ppc) $vd $vsimm )
+   #.(ppc-opcode vspltish (vx 4 844) $vx-mask ($ppc) $vd $vsimm )
+   #.(ppc-opcode vspltisw (vx 4 908) $vx-mask ($ppc) $vd $vsimm )
+   #.(ppc-opcode vspltw (vx 4 652) $vx-mask ($ppc) $vd $vb $vuimm )
+   #.(ppc-opcode vsr (vx 4 708) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsrab (vx 4 772) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsrah (vx 4 836) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsraw (vx 4 900) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsrb (vx 4 516) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsrh (vx 4 580) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsro (vx 4 1100) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsrw (vx 4 644) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubcuw (vx 4 1408) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubfp (vx 4 74) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubsbs (vx 4 1792) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubshs (vx 4 1856) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubsws (vx 4 1920) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsububm (vx 4 1024) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsububs (vx 4 1536) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubuhm (vx 4 1088) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubuhs (vx 4 1600) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubuwm (vx 4 1152) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsubuws (vx 4 1664) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsumsws (vx 4 1928) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsum2sws (vx 4 1672) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsum4sbs (vx 4 1800) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsum4shs (vx 4 1608) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vsum4ubs (vx 4 1544) $vx-mask ($ppc) $vd $va $vb )
+   #.(ppc-opcode vupkhpx (vx 4 846) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vupkhsb (vx 4 526) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vupkhsh (vx 4 590) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vupklpx (vx 4 974) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vupklsb (vx 4 654) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vupklsh (vx 4 718) $vx-mask ($ppc) $vd $vb )
+   #.(ppc-opcode vxor (vx 4 1220) $vx-mask ($ppc) $vd $va $vb  )
+
+   #.(ppc-opcode mulli (op 7) $op-mask ($ppc) $rt $ra $si)
+   
+   #.(ppc-opcode subfic (op 8) $op-mask ($ppc) $rt $ra $si)
+   
+   #.(ppc-opcode cmplwi (opl 10 0) $opl-mask ($ppc) $obf $ra $ui)
+
+   #.(ppc-opcode cmpldi (opl 10 1) $opl-mask ($ppc $b64) $obf $ra $ui)
+
+   #.(ppc-opcode cmpli (op 10) $op-mask ($ppc) $bf $l $ra $ui)
+
+   #.(ppc-opcode cmpwi (opl 11 0) $opl-mask ($ppc) $obf $ra $si)
+
+   #.(ppc-opcode cmpdi (opl 11 1) $opl-mask ($ppc $b64) $obf $ra $si)
+
+   #.(ppc-opcode cmpi (op 11) $op-mask ($ppc) $bf $l $ra $si)
+
+   #.(ppc-opcode addic (op 12) $op-mask ($ppc) $rt $ra $si)
+   #.(ppc-opcode subic (op 12) $op-mask ($ppc) $rt $ra $nsi)
+
+   #.(ppc-opcode addic. (op 13) $op-mask ($ppc) $rt $ra $si)
+   #.(ppc-opcode subic. (op 13) $op-mask ($ppc) $rt $ra $nsi)
+
+   #.(ppc-opcode li (op 14) $dra-mask ($ppc) $rt $si)
+   #.(ppc-opcode addi (op 14) $op-mask ($ppc) $rt $ra $si)
+   #.(ppc-opcode subi (op 14) $op-mask ($ppc) $rt $ra $nsi)
+   #.(ppc-opcode la (op 14) $op-mask ($ppc) $rt $d $ra)
+
+   #.(ppc-opcode lis (op 15) $dra-mask ($ppc) $rt $sisignopt)
+   #.(ppc-opcode addis (op 15) $op-mask ($ppc) $rt $ra $sisignopt)
+   #.(ppc-opcode subis (op 15) $op-mask ($ppc) $rt $ra $nsi)
+
+   #.(ppc-opcode bdnz- (bbo 16 $bodnz 0 0) $bboybi-mask ($ppc) $bdm)
+   #.(ppc-opcode bdnz+ (bbo 16 $bodnz 0 0) $bboybi-mask ($ppc) $bdp)
+   #.(ppc-opcode bdnz (bbo 16 $bodnz 0 0) $bboybi-mask ($ppc) $bd)
+   #.(ppc-opcode bdnzl- (bbo 16 $bodnz 0 1) $bboybi-mask ($ppc) $bdm)
+   #.(ppc-opcode bdnzl+ (bbo 16 $bodnz 0 1) $bboybi-mask ($ppc) $bdp)
+   #.(ppc-opcode bdnzl (bbo 16 $bodnz 0 1) $bboybi-mask ($ppc) $bd)
+   #.(ppc-opcode bdnza- (bbo 16 $bodnz 1 0) $bboybi-mask ($ppc) $bdma)
+   #.(ppc-opcode bdnza+ (bbo 16 $bodnz 1 0) $bboybi-mask ($ppc) $bdpa)
+   #.(ppc-opcode bdnza (bbo 16 $bodnz 1 0) $bboybi-mask ($ppc) $bda)
+   #.(ppc-opcode bdnzla- (bbo 16 $bodnz 1 1) $bboybi-mask ($ppc) $bdma)
+   #.(ppc-opcode bdnzla+ (bbo 16 $bodnz 1 1) $bboybi-mask ($ppc) $bdpa)
+   #.(ppc-opcode bdnzla (bbo 16 $bodnz 1 1) $bboybi-mask ($ppc) $bda)
+   #.(ppc-opcode bdz- (bbo 16 $bodz 0 0) $bboybi-mask ($ppc) $bdm)
+   #.(ppc-opcode bdz+ (bbo 16 $bodz 0 0) $bboybi-mask ($ppc) $bdp)
+   #.(ppc-opcode bdz (bbo 16 $bodz 0 0) $bboybi-mask ($ppc) $bd)
+   #.(ppc-opcode bdzl- (bbo 16 $bodz 0 1) $bboybi-mask ($ppc) $bdm)
+   #.(ppc-opcode bdzl+ (bbo 16 $bodz 0 1) $bboybi-mask ($ppc) $bdp)
+   #.(ppc-opcode bdzl (bbo 16 $bodz 0 1) $bboybi-mask ($ppc) $bd)
+   #.(ppc-opcode bdza- (bbo 16 $bodz 1 0) $bboybi-mask ($ppc) $bdma)
+   #.(ppc-opcode bdza+ (bbo 16 $bodz 1 0) $bboybi-mask ($ppc) $bdpa)
+   #.(ppc-opcode bdza (bbo 16 $bodz 1 0) $bboybi-mask ($ppc) $bda)
+   #.(ppc-opcode bdzla- (bbo 16 $bodz 1 1) $bboybi-mask ($ppc) $bdma)
+   #.(ppc-opcode bdzla+ (bbo 16 $bodz 1 1) $bboybi-mask ($ppc) $bdpa)
+   #.(ppc-opcode bdzla (bbo 16 $bodz 1 1) $bboybi-mask ($ppc) $bda)
+   #.(ppc-opcode blt- (bbocb 16 $bot $cblt 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode blt+ (bbocb 16 $bot $cblt 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode blt (bbocb 16 $bot $cblt 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bltl- (bbocb 16 $bot $cblt 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bltl+ (bbocb 16 $bot $cblt 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bltl (bbocb 16 $bot $cblt 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode blta- (bbocb 16 $bot $cblt 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode blta+ (bbocb 16 $bot $cblt 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode blta (bbocb 16 $bot $cblt 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bltla- (bbocb 16 $bot $cblt 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bltla+ (bbocb 16 $bot $cblt 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bltla (bbocb 16 $bot $cblt 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bgt- (bbocb 16 $bot $cbgt 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bgt+ (bbocb 16 $bot $cbgt 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bgt (bbocb 16 $bot $cbgt 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bgtl- (bbocb 16 $bot $cbgt 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bgtl+ (bbocb 16 $bot $cbgt 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bgtl (bbocb 16 $bot $cbgt 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bgta- (bbocb 16 $bot $cbgt 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bgta+ (bbocb 16 $bot $cbgt 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bgta (bbocb 16 $bot $cbgt 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bgtla- (bbocb 16 $bot $cbgt 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bgtla+ (bbocb 16 $bot $cbgt 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bgtla (bbocb 16 $bot $cbgt 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode beq- (bbocb 16 $bot $cbeq 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode beq+ (bbocb 16 $bot $cbeq 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode beq (bbocb 16 $bot $cbeq 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode beql- (bbocb 16 $bot $cbeq 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode beql+ (bbocb 16 $bot $cbeq 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode beql (bbocb 16 $bot $cbeq 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode beqa- (bbocb 16 $bot $cbeq 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode beqa+ (bbocb 16 $bot $cbeq 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode beqa (bbocb 16 $bot $cbeq 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode beqla- (bbocb 16 $bot $cbeq 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode beqla+ (bbocb 16 $bot $cbeq 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode beqla (bbocb 16 $bot $cbeq 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bso- (bbocb 16 $bot $cbso 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bso+ (bbocb 16 $bot $cbso 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bso (bbocb 16 $bot $cbso 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bsol- (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bsol+ (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bsol (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bsoa- (bbocb 16 $bot $cbso 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bsoa+ (bbocb 16 $bot $cbso 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bsoa (bbocb 16 $bot $cbso 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bsola- (bbocb 16 $bot $cbso 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bsola+ (bbocb 16 $bot $cbso 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bsola (bbocb 16 $bot $cbso 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bun- (bbocb 16 $bot $cbso 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bun+ (bbocb 16 $bot $cbso 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bun (bbocb 16 $bot $cbso 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bunl- (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bunl+ (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bunl (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode buna- (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode buna+ (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode buna (bbocb 16 $bot $cbso 0 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bunla- (bbocb 16 $bot $cbso 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bunla+ (bbocb 16 $bot $cbso 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bunla (bbocb 16 $bot $cbso 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bge- (bbocb 16 $bof $cblt 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bge+ (bbocb 16 $bof $cblt 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bge (bbocb 16 $bof $cblt 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bgel- (bbocb 16 $bof $cblt 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bgel+ (bbocb 16 $bof $cblt 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bgel (bbocb 16 $bof $cblt 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bgea- (bbocb 16 $bof $cblt 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bgea+ (bbocb 16 $bof $cblt 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bgea (bbocb 16 $bof $cblt 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bgela- (bbocb 16 $bof $cblt 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bgela+ (bbocb 16 $bof $cblt 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bgela (bbocb 16 $bof $cblt 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bnl- (bbocb 16 $bof $cblt  0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bnl+ (bbocb 16 $bof $cblt  0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bnl (bbocb 16 $bof $cblt 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnll- (bbocb 16 $bof $cblt 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bnll+ (bbocb 16 $bof $cblt 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bnll (bbocb 16 $bof $cblt 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnla- (bbocb 16 $bof $cblt 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnla+ (bbocb 16 $bof $cblt 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnla (bbocb 16 $bof $cblt 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bnlla- (bbocb 16 $bof $cblt 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnlla+ (bbocb 16 $bof $cblt 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnlla (bbocb 16 $bof $cblt 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode ble- (bbocb 16 $bof $cbgt 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode ble+ (bbocb 16 $bof $cbgt 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode ble (bbocb 16 $bof $cbgt 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode blel- (bbocb 16 $bof $cbgt 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode blel+ (bbocb 16 $bof $cbgt 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode blel (bbocb 16 $bof $cbgt 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode blea- (bbocb 16 $bof $cbgt 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode blea+ (bbocb 16 $bof $cbgt 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode blea (bbocb 16 $bof $cbgt 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode blela- (bbocb 16 $bof $cbgt 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode blela+ (bbocb 16 $bof $cbgt 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode blela (bbocb 16 $bof $cbgt 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bng- (bbocb 16 $bof $cbgt 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bng+ (bbocb 16 $bof $cbgt 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bng (bbocb 16 $bof $cbgt 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bngl- (bbocb 16 $bof $cbgt 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bngl+ (bbocb 16 $bof $cbgt 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bngl (bbocb 16 $bof $cbgt 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnga- (bbocb 16 $bof $cbgt 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnga+ (bbocb 16 $bof $cbgt 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnga (bbocb 16 $bof $cbgt 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bngla- (bbocb 16 $bof $cbgt 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bngla+ (bbocb 16 $bof $cbgt 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bngla (bbocb 16 $bof $cbgt 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bne- (bbocb 16 $bof $cbeq 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bne+ (bbocb 16 $bof $cbeq 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bne (bbocb 16 $bof $cbeq 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnel- (bbocb 16 $bof $cbeq 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bnel+ (bbocb 16 $bof $cbeq 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bnel (bbocb 16 $bof $cbeq 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnea- (bbocb 16 $bof $cbeq 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnea+ (bbocb 16 $bof $cbeq 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnea (bbocb 16 $bof $cbeq 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bnela- (bbocb 16 $bof $cbeq 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnela+ (bbocb 16 $bof $cbeq 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnela (bbocb 16 $bof $cbeq 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bns- (bbocb 16 $bof $cbso 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bns+ (bbocb 16 $bof $cbso 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bns (bbocb 16 $bof $cbso 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnsl- (bbocb 16 $bof $cbso 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bnsl+ (bbocb 16 $bof $cbso 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bnsl (bbocb 16 $bof $cbso 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnsa- (bbocb 16 $bof $cbso 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnsa+ (bbocb 16 $bof $cbso 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnsa (bbocb 16 $bof $cbso 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bnsla- (bbocb 16 $bof $cbso 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnsla+ (bbocb 16 $bof $cbso 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnsla (bbocb 16 $bof $cbso 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bnu- (bbocb 16 $bof $cbso 0 0) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bnu+ (bbocb 16 $bof $cbso 0 0) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bnu (bbocb 16 $bof $cbso 0 0) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnul- (bbocb 16 $bof $cbso 0 1) $bboycb-mask ($ppc) $cr $bdm)
+   #.(ppc-opcode bnul+ (bbocb 16 $bof $cbso 0 1) $bboycb-mask ($ppc) $cr $bdp)
+   #.(ppc-opcode bnul (bbocb 16 $bof $cbso 0 1) $bboycb-mask ($ppc) $cr $bd)
+   #.(ppc-opcode bnua- (bbocb 16 $bof $cbso 1 0) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnua+ (bbocb 16 $bof $cbso 1 0) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnua (bbocb 16 $bof $cbso 1 0) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bnula- (bbocb 16 $bof $cbso 1 1) $bboycb-mask ($ppc) $cr $bdma)
+   #.(ppc-opcode bnula+ (bbocb 16 $bof $cbso 1 1) $bboycb-mask ($ppc) $cr $bdpa)
+   #.(ppc-opcode bnula (bbocb 16 $bof $cbso 1 1) $bboycb-mask ($ppc) $cr $bda)
+   #.(ppc-opcode bdnzt- (bbo 16 $bodnzt 0 0) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdnzt+ (bbo 16 $bodnzt 0 0) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdnzt (bbo 16 $bodnzt 0 0) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdnztl- (bbo 16 $bodnzt 0 1) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdnztl+ (bbo 16 $bodnzt 0 1) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdnztl (bbo 16 $bodnzt 0 1) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdnzta- (bbo 16 $bodnzt 1 0) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdnzta+ (bbo 16 $bodnzt 1 0) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdnzta (bbo 16 $bodnzt 1 0) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bdnztla- (bbo 16 $bodnzt 1 1) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdnztla+ (bbo 16 $bodnzt 1 1) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdnztla (bbo 16 $bodnzt 1 1) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bdnzf- (bbo 16 $bodnzf 0 0) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdnzf+ (bbo 16 $bodnzf 0 0) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdnzf (bbo 16 $bodnzf 0 0) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdnzfl- (bbo 16 $bodnzf 0 1) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdnzfl+ (bbo 16 $bodnzf 0 1) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdnzfl (bbo 16 $bodnzf 0 1) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdnzfa- (bbo 16 $bodnzf 1 0) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdnzfa+ (bbo 16 $bodnzf 1 0) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdnzfa (bbo 16 $bodnzf 1 0) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bdnzfla- (bbo 16 $bodnzf 1 1) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdnzfla+ (bbo 16 $bodnzf 1 1) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdnzfla (bbo 16 $bodnzf 1 1) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bt- (bbo 16 $bot 0 0) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bt+ (bbo 16 $bot 0 0) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bt (bbo 16 $bot 0 0) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode btl- (bbo 16 $bot 0 1) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode btl+ (bbo 16 $bot 0 1) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode btl (bbo 16 $bot 0 1) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bta- (bbo 16 $bot 1 0) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bta+ (bbo 16 $bot 1 0) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bta (bbo 16 $bot 1 0) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode btla- (bbo 16 $bot 1 1) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode btla+ (bbo 16 $bot 1 1) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode btla (bbo 16 $bot 1 1) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bf- (bbo 16 $bof 0 0) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bf+ (bbo 16 $bof 0 0) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bf (bbo 16 $bof 0 0) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bfl- (bbo 16 $bof 0 1) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bfl+ (bbo 16 $bof 0 1) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bfl (bbo 16 $bof 0 1) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bfa- (bbo 16 $bof 1 0) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bfa+ (bbo 16 $bof 1 0) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bfa (bbo 16 $bof 1 0) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bfla- (bbo 16 $bof 1 1) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bfla+ (bbo 16 $bof 1 1) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bfla (bbo 16 $bof 1 1) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bdzt- (bbo 16 $bodzt 0 0) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdzt+ (bbo 16 $bodzt 0 0) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdzt (bbo 16 $bodzt 0 0) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdztl- (bbo 16 $bodzt 0 1) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdztl+ (bbo 16 $bodzt 0 1) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdztl (bbo 16 $bodzt 0 1) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdzta- (bbo 16 $bodzt 1 0) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdzta+ (bbo 16 $bodzt 1 0) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdzta (bbo 16 $bodzt 1 0) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bdztla- (bbo 16 $bodzt 1 1) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdztla+ (bbo 16 $bodzt 1 1) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdztla (bbo 16 $bodzt 1 1) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bdzf- (bbo 16 $bodzf 0 0) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdzf+ (bbo 16 $bodzf 0 0) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdzf (bbo 16 $bodzf 0 0) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdzfl- (bbo 16 $bodzf 0 1) $bboy-mask ($ppc) $bi $bdm)
+   #.(ppc-opcode bdzfl+ (bbo 16 $bodzf 0 1) $bboy-mask ($ppc) $bi $bdp)
+   #.(ppc-opcode bdzfl (bbo 16 $bodzf 0 1) $bboy-mask ($ppc) $bi $bd)
+   #.(ppc-opcode bdzfa- (bbo 16 $bodzf 1 0) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdzfa+ (bbo 16 $bodzf 1 0) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdzfa (bbo 16 $bodzf 1 0) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bdzfla- (bbo 16 $bodzf 1 1) $bboy-mask ($ppc) $bi $bdma)
+   #.(ppc-opcode bdzfla+ (bbo 16 $bodzf 1 1) $bboy-mask ($ppc) $bi $bdpa)
+   #.(ppc-opcode bdzfla (bbo 16 $bodzf 1 1) $bboy-mask ($ppc) $bi $bda)
+   #.(ppc-opcode bc- (b 16 0 0) $b-mask ($ppc) $boe $bi $bdm)
+   #.(ppc-opcode bc+ (b 16 0 0) $b-mask ($ppc) $boe $bi $bdp)
+   #.(ppc-opcode bc (b 16 0 0) $b-mask ($ppc) $bo $bi $bd)
+   #.(ppc-opcode bcl- (b 16 0 1) $b-mask ($ppc) $boe $bi $bdm)
+   #.(ppc-opcode bcl+ (b 16 0 1) $b-mask ($ppc) $boe $bi $bdp)
+   #.(ppc-opcode bcl (b 16 0 1) $b-mask ($ppc) $bo $bi $bd)
+   #.(ppc-opcode bca- (b 16 1 0) $b-mask ($ppc) $boe $bi $bdma)
+   #.(ppc-opcode bca+ (b 16 1 0) $b-mask ($ppc) $boe $bi $bdpa)
+   #.(ppc-opcode bca (b 16 1 0) $b-mask ($ppc) $bo $bi $bda)
+   #.(ppc-opcode bcla- (b 16 1 1) $b-mask ($ppc) $boe $bi $bdma)
+   #.(ppc-opcode bcla+ (b 16 1 1) $b-mask ($ppc) $boe $bi $bdpa)
+   #.(ppc-opcode bcla (b 16 1 1) $b-mask ($ppc) $bo $bi $bda)
+
+   #.(ppc-opcode sc (sc 17 1 0) #xffffffff ($ppc))
+
+   #.(ppc-opcode b (b 18 0 0) $b-mask ($ppc) $li)
+   #.(ppc-opcode bl (b 18 0 1) $b-mask ($ppc) $li)
+   #.(ppc-opcode ba (b 18 1 0) $b-mask ($ppc) $lia)
+   #.(ppc-opcode bla (b 18 1 1) $b-mask ($ppc) $lia)
+
+   #.(ppc-opcode mcrf (xl 19 0) (logior $xlbb-mask (ash 3 21) (ash 3 16)) ($ppc) $bf $bfa)
+
+   #.(ppc-opcode blr (xlo 19 $bou 16 0) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode blrl (xlo 19 $bou 16 1) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdnzlr (xlo 19 $bodnz 16 0) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdnzlr- (xlo 19 $bodnz 16 0) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdnzlr+ (xlo 19 $bodnzp 16 0) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdnzlrl (xlo 19 $bodnz 16 1) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdnzlrl- (xlo 19 $bodnz 16 1) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdnzlrl+ (xlo 19 $bodnzp 16 1) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdzlr (xlo 19 $bodz 16 0) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdzlr- (xlo 19 $bodz 16 0) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdzlr+ (xlo 19 $bodzp 16 0) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdzlrl (xlo 19 $bodz 16 1) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdzlrl- (xlo 19 $bodz 16 1) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bdzlrl+ (xlo 19 $bodzp 16 1) $xlbobibb-mask ($ppc))
+   #.(ppc-opcode bltlr (xlocb 19 $bot $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltlr- (xlocb 19 $bot $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltlr+ (xlocb 19 $botp $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltlrl (xlocb 19 $bot $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltlrl- (xlocb 19 $bot $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltlrl+ (xlocb 19 $botp $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtlr (xlocb 19 $bot $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtlr- (xlocb 19 $bot $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtlr+ (xlocb 19 $botp $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtlrl (xlocb 19 $bot $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtlrl- (xlocb 19 $bot $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtlrl+ (xlocb 19 $botp $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqlr (xlocb 19 $bot $cbeq 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqlr- (xlocb 19 $bot $cbeq 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqlr+ (xlocb 19 $botp $cbeq 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqlrl (xlocb 19 $bot $cbeq 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqlrl- (xlocb 19 $bot $cbeq 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqlrl+ (xlocb 19 $botp $cbeq 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsolr (xlocb 19 $bot $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsolr- (xlocb 19 $bot $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsolr+ (xlocb 19 $botp $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsolrl (xlocb 19 $bot $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsolrl- (xlocb 19 $bot $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsolrl+ (xlocb 19 $botp $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunlr (xlocb 19 $bot $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunlr- (xlocb 19 $bot $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunlr+ (xlocb 19 $botp $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunlrl (xlocb 19 $bot $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunlrl- (xlocb 19 $bot $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunlrl+ (xlocb 19 $botp $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgelr (xlocb 19 $bof $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgelr- (xlocb 19 $bof $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgelr+ (xlocb 19 $bofp $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgelrl (xlocb 19 $bof $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgelrl- (xlocb 19 $bof $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgelrl+ (xlocb 19 $bofp $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnllr (xlocb 19 $bof $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnllr- (xlocb 19 $bof $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnllr+ (xlocb 19 $bofp $cblt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnllrl (xlocb 19 $bof $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnllrl- (xlocb 19 $bof $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnllrl+ (xlocb 19 $bofp $cblt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blelr (xlocb 19 $bof $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blelr- (xlocb 19 $bof $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blelr+ (xlocb 19 $bofp $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blelrl (xlocb 19 $bof $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blelrl- (xlocb 19 $bof $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blelrl+ (xlocb 19 $bofp $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnglr (xlocb 19 $bof $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnglr- (xlocb 19 $bof $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnglr+ (xlocb 19 $bofp $cbgt 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnglrl (xlocb 19 $bof $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnglrl- (xlocb 19 $bof $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnglrl+ (xlocb 19 $bofp $cbgt 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnelr (xlocb 19 $bof $cbeq 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnelr- (xlocb 19 $bof $cbeq 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnelr+ (xlocb 19 $bofp $cbeq 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnelrl (xlocb 19 $bof $cbeq 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnelrl- (xlocb 19 $bof $cbeq 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnelrl+ (xlocb 19 $bofp $cbeq 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnslr (xlocb 19 $bof $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnslr- (xlocb 19 $bof $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnslr+ (xlocb 19 $bofp $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnslrl (xlocb 19 $bof $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnslrl- (xlocb 19 $bof $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnslrl+ (xlocb 19 $bofp $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnulr (xlocb 19 $bof $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnulr- (xlocb 19 $bof $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnulr+ (xlocb 19 $bofp $cbso 16) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnulrl (xlocb 19 $bof $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnulrl- (xlocb 19 $bof $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnulrl+ (xlocb 19 $bofp $cbso 16 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode btlr (xlo 19 $bot 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btlr- (xlo 19 $bot 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btlr+ (xlo 19 $botp 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btlrl (xlo 19 $bot 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btlrl- (xlo 19 $bot 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btlrl+ (xlo 19 $botp 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bflr (xlo 19 $bof 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bflr- (xlo 19 $bof 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bflr+ (xlo 19 $bofp 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bflrl (xlo 19 $bof 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bflrl- (xlo 19 $bof 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bflrl+ (xlo 19 $bofp 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnztlr (xlo 19 $bodnzt 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnztlr- (xlo 19 $bodnzt 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnztlr+ (xlo 19 $bodnztp 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnztlrl (xlo 19 $bodnzt 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnztlrl- (xlo 19 $bodnzt 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnztlrl+ (xlo 19 $bodnztp 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnzflr (xlo 19 $bodnzf 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnzflr- (xlo 19 $bodnzf 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnzflr+ (xlo 19 $bodnzfp 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnzflrl (xlo 19 $bodnzf 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnzflrl- (xlo 19 $bodnzf 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdnzflrl+ (xlo 19 $bodnzfp 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdztlr (xlo 19 $bodzt 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdztlr- (xlo 19 $bodzt 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdztlr+ (xlo 19 $bodztp 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdztlrl (xlo 19 $bodzt 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdztlrl- (xlo 19 $bodzt 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdztlrl+ (xlo 19 $bodztp 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdzflr (xlo 19 $bodzf 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdzflr- (xlo 19 $bodzf 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdzflr+ (xlo 19 $bodzfp 16) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdzflrl (xlo 19 $bodzf 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdzflrl- (xlo 19 $bodzf 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bdzflrl+ (xlo 19 $bodzfp 16 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bclr (xllk 19 16) $xlybb-mask ($ppc) $bo $bi)
+   #.(ppc-opcode bclrl (xllk 19 16 1) $xlybb-mask ($ppc) $bo $bi)
+   #.(ppc-opcode bclr+ (xlylk 19 16 1) $xlybb-mask ($ppc) $boe $bi)
+   #.(ppc-opcode bclrl+ (xlylk 19 16 1 1) $xlybb-mask ($ppc) $boe $bi)
+   #.(ppc-opcode bclr- (xlylk 19 16 0) $xlybb-mask ($ppc) $boe $bi)
+   #.(ppc-opcode bclrl- (xlylk 19 16 1) $xlybb-mask ($ppc) $boe $bi)
+
+   #.(ppc-opcode crnot (xl 19 33) $xl-mask ($ppc) $bt $ba $bba)
+   #.(ppc-opcode crnor (xl 19 33) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode rfi (xl 19 50) #xffffffff ($ppc) )
+
+
+   #.(ppc-opcode crandc (xl 19 129) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode isync (xl 19 150) #xffffffff ($ppc))
+
+   #.(ppc-opcode crclr (xl 19 193) $xl-mask ($ppc) $bt $bat $bba)
+   #.(ppc-opcode crxor (xl 19 193) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode crnand (xl 19 225) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode crand (xl 19 257) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode crset (xl 19 289) $xl-mask ($ppc) $bt $bat $bba)
+   #.(ppc-opcode creqv (xl 19 289) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode crorc (xl 19 417) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode crmove (xl 19 449) $xl-mask ($ppc) $bt $ba $bba)
+   #.(ppc-opcode cror (xl 19 449) $xl-mask ($ppc) $bt $ba $bb)
+
+   #.(ppc-opcode bctr (xlo 19 $bou 528) $xlbobibb-mask ($ppc) )
+   #.(ppc-opcode bctrl (xlo 19 $bou 528 1) $xlbobibb-mask ($ppc) )
+   #.(ppc-opcode bltctr (xlocb 19 $bot $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltctr- (xlocb 19 $bot $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltctr+ (xlocb 19 $botp $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltctrl (xlocb 19 $bot $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltctrl- (xlocb 19 $bot $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bltctrl+ (xlocb 19 $botp $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtctr (xlocb 19 $bot $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtctr- (xlocb 19 $bot $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtctr+ (xlocb 19 $botp $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtctrl (xlocb 19 $bot $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtctrl- (xlocb 19 $bot $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgtctrl+ (xlocb 19 $botp $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqctr (xlocb 19 $bot $cbeq 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqctr- (xlocb 19 $bot $cbeq 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqctr+ (xlocb 19 $botp $cbeq 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqctrl (xlocb 19 $bot $cbeq 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqctrl- (xlocb 19 $bot $cbeq 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode beqctrl+ (xlocb 19 $botp $cbeq 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsoctr (xlocb 19 $bot $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsoctr- (xlocb 19 $bot $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsoctr+ (xlocb 19 $botp $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsoctrl (xlocb 19 $bot $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsoctrl- (xlocb 19 $bot $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bsoctrl+ (xlocb 19 $botp $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunctr (xlocb 19 $bot $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunctr- (xlocb 19 $bot $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunctr+ (xlocb 19 $botp $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunctrl (xlocb 19 $bot $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunctrl- (xlocb 19 $bot $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bunctrl+ (xlocb 19 $botp $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgectr (xlocb 19 $bof $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgectr- (xlocb 19 $bof $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgectr+ (xlocb 19 $bofp $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgectrl (xlocb 19 $bof $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgectrl- (xlocb 19 $bof $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bgectrl+ (xlocb 19 $bofp $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnlctr (xlocb 19 $bof $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnlctr- (xlocb 19 $bof $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnlctr+ (xlocb 19 $bofp $cblt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnlctrl (xlocb 19 $bof $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnlctrl- (xlocb 19 $bof $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnlctrl+ (xlocb 19 $bofp $cblt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blectr (xlocb 19 $bof $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blectr- (xlocb 19 $bof $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blectr+ (xlocb 19 $bofp $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blectrl (xlocb 19 $bof $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blectrl- (xlocb 19 $bof $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode blectrl+ (xlocb 19 $bofp $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bngctr (xlocb 19 $bof $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bngctr- (xlocb 19 $bof $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bngctr+ (xlocb 19 $bofp $cbgt 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bngctrl (xlocb 19 $bof $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bngctrl- (xlocb 19 $bof $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bngctrl+ (xlocb 19 $bofp $cbgt 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnectr (xlocb 19 $bof $cbeq 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnectr- (xlocb 19 $bof $cbeq 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnectr+ (xlocb 19 $bofp $cbeq 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnectrl (xlocb 19 $bof $cbeq 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnectrl- (xlocb 19 $bof $cbeq 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnectrl+ (xlocb 19 $bofp $cbeq 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnsctr (xlocb 19 $bof $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnsctr- (xlocb 19 $bof $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnsctr+ (xlocb 19 $bofp $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnsctrl (xlocb 19 $bof $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnsctrl- (xlocb 19 $bof $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnsctrl+ (xlocb 19 $bofp $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnuctr (xlocb 19 $bof $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnuctr- (xlocb 19 $bof $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnuctr+ (xlocb 19 $bofp $cbso 528) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnuctrl (xlocb 19 $bof $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnuctrl- (xlocb 19 $bof $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode bnuctrl+ (xlocb 19 $bofp $cbso 528 1) $xlbocbbb-mask ($ppc) $cr)
+   #.(ppc-opcode btctr (xlo 19 $bot 528) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btctr- (xlo 19 $bot 528) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btctr+ (xlo 19 $botp 528) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btctrl (xlo 19 $bot 528 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btctrl- (xlo 19 $bot 528 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode btctrl+ (xlo 19 $botp 528 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bfctr (xlo 19 $bof 528) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bfctr- (xlo 19 $bof 528) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bfctr+ (xlo 19 $bofp 528) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bfctrl (xlo 19 $bof 528 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bfctrl- (xlo 19 $bof 528 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bfctrl+ (xlo 19 $bofp 528 1) $xlbobb-mask ($ppc) $bi)
+   #.(ppc-opcode bcctr (xllk 19 528) $xlybb-mask ($ppc) $bo $bi)
+   #.(ppc-opcode bcctr- (xlylk 19 528 0) $xlybb-mask ($ppc) $boe $bi)
+   #.(ppc-opcode bcctr+ (xlylk 19 528 1) $xlybb-mask ($ppc) $boe $bi)
+   #.(ppc-opcode bcctrl (xllk 19 528 1) $xlybb-mask ($ppc) $bo $bi)
+   #.(ppc-opcode bcctrl- (xlylk 19 528 1) $xlybb-mask ($ppc) $boe $bi)
+   #.(ppc-opcode bcctrl+ (xlylk 19 528 1 1) $xlybb-mask ($ppc) $boe $bi)
+
+   #.(ppc-opcode rlwimi (m 20) $m-mask ($ppc) $rta $rs $sh $mb $me)
+
+   #.(ppc-opcode rlwimi. (m 20 1) $m-mask ($ppc) $rta $rs $sh $mb $me)
+
+   #.(ppc-opcode rotlwi (mme 21 31) $mmbme-mask ($ppc) $rta $rs $sh)
+   #.(ppc-opcode clrlwi (mme 21 31) $mshme-mask ($ppc) $rta $rs $mb)
+   #.(ppc-opcode rlwinm (m 21) $m-mask ($ppc) $rta $rs $sh $mb $me)
+   #.(ppc-opcode rotlwi. (mme 21 31 1) $mmbme-mask ($ppc) $rta $rs $sh)
+   #.(ppc-opcode clrlwi. (mme 21 31 1) $mshme-mask ($ppc) $rta $rs $mb)
+   #.(ppc-opcode rlwinm. (m 21 1) $m-mask ($ppc) $rta $rs $sh $mb $me)
+
+   #.(ppc-opcode rotlw (mme 23 31) $mmbme-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode rlwnm (m 23) $m-mask ($ppc) $rta $rs $rb $mb $me)
+   #.(ppc-opcode rotlw. (mme 23 31 1) $mmbme-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode rlwnm. (m 23 1) $m-mask ($ppc) $rta $rs $rb $mb $me)
+
+   #.(ppc-opcode nop (op 24) #xffffffff ($ppc))
+   #.(ppc-opcode ori (op 24) $op-mask ($ppc) $rta $rs $ui)
+
+   #.(ppc-opcode oris (op 25) $op-mask ($ppc) $rta $rs $ui)
+
+   #.(ppc-opcode xori (op 26) $op-mask ($ppc) $rta $rs $ui)
+
+   #.(ppc-opcode xoris (op 27) $op-mask ($ppc) $rta $rs $ui)
+
+   #.(ppc-opcode andi. (op 28) $op-mask ($ppc) $rta $rs $ui)
+
+   #.(ppc-opcode andis. (op 29) $op-mask ($ppc) $rta $rs $ui)
+
+   #.(ppc-opcode rotldi (md 30 0 0) $mdmb-mask ($ppc $b64) $rta $rs $sh6)
+   #.(ppc-opcode clrldi (md 30 0 0) $mdsh-mask ($ppc $b64) $rta $rs $mb6)
+   #.(ppc-opcode rldicl (md 30 0 0) $md-mask ($ppc $b64) $rta $rs $sh6 $mb6)
+   #.(ppc-opcode rotldi. (md 30 0 1) $mdmb-mask ($ppc $b64) $rta $rs $sh6)
+   #.(ppc-opcode clrldi. (md 30 0 1) $mdsh-mask ($ppc $b64) $rta $rs $mb6)
+   #.(ppc-opcode rldicl. (md 30 0 1) $md-mask ($ppc $b64) $rta $rs $sh6 $mb6)
+
+   #.(ppc-opcode rldicr (md 30 1 0) $md-mask ($ppc $b64) $rta $rs $sh6 $me6)
+   #.(ppc-opcode rldicr. (md 30 1 1) $md-mask ($ppc $b64) $rta $rs $sh6 $me6)
+
+   #.(ppc-opcode rldic (md 30 2 0) $md-mask ($ppc $b64) $rta $rs $sh6 $mb6)
+   #.(ppc-opcode rldic. (md 30 2 1) $md-mask ($ppc $b64) $rta $rs $sh6 $mb6)
+
+   #.(ppc-opcode rldimi (md 30 3 0) $md-mask ($ppc $b64) $rta $rs $sh6 $mb6)
+   #.(ppc-opcode rldimi. (md 30 3 1) $md-mask ($ppc $b64) $rta $rs $sh6 $mb6)
+
+   #.(ppc-opcode rotld (mds 30 8 0) $mdsmb-mask ($ppc $b64) $rta $rs $rb)
+   #.(ppc-opcode rldcl (mds 30 8 0) $mds-mask ($ppc $b64) $rta $rs $rb $mb6)
+   #.(ppc-opcode rotld. (mds 30 8 1) $mdsmb-mask ($ppc $b64) $rta $rs $rb)
+   #.(ppc-opcode rldcl. (mds 30 8 1) $mds-mask ($ppc $b64) $rta $rs $rb $mb6)
+
+   #.(ppc-opcode rldcr (mds 30 9 0) $mds-mask ($ppc $b64) $rta $rs $rb $me6)
+   #.(ppc-opcode rldcr. (mds 30 9 1) $mds-mask ($ppc $b64) $rta $rs $rb $me6)
+
+   #.(ppc-opcode cmpw (xcmpl 31 0 0) $xcmpl-mask ($ppc) $obf $ra $rb)
+
+   #.(ppc-opcode cmpd (xcmpl 31 0 1) $xcmpl-mask ($ppc $b64) $obf $ra $rb)
+
+
+   #.(ppc-opcode cmp (x 31 0) $xcmp-mask ($ppc) $bf $l $ra $rb)
+
+   #.(ppc-opcode twlgt (xto 31 4 $tolgt) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twllt (xto 31 4 $tollt) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode tweq (xto 31 4 $toeq) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twlge (xto 31 4 $tolge) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twlnl (xto 31 4 $tolnl) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twlle (xto 31 4 $tolle) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twlng (xto 31 4 $tolng) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twgt (xto 31 4 $togt) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twge (xto 31 4 $toge) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twnl (xto 31 4 $tonl) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twlt (xto 31 4 $tolt) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twle (xto 31 4 $tole) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twng (xto 31 4 $tong) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode twne (xto 31 4 $tone) $xto-mask ($ppc) $ra $rb)
+   #.(ppc-opcode trap (xto 31 4 $tou) #xffffffff ($ppc))
+   #.(ppc-opcode tw (x 31 4) $x-mask ($ppc) $to $ra $rb)
+
+   #.(ppc-opcode subfc (xo 31 8 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subc (xo 31 8 0 0) $xo-mask ($ppc) $rt $rb $ra)
+   #.(ppc-opcode subfc. (xo 31 8 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subc. (xo 31 8 0 1) $xo-mask ($ppc) $rt $rb $ra)
+   #.(ppc-opcode subfco (xo 31 8 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subco (xo 31 8 1 0) $xo-mask ($ppc) $rt $rb $ra)
+   #.(ppc-opcode subfco. (xo 31 8 1 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subco. (xo 31 8 1 1) $xo-mask ($ppc) $rt $rb $ra)
+
+
+   #.(ppc-opcode mulhdu (xo 31 9 0 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode mulhdu. (xo 31 9 0 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+
+
+   #.(ppc-opcode addc (xo 31 10 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode addc. (xo 31 10 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode addco (xo 31 10 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode addco. (xo 31 10 1 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode mulhwu (xo 31 11 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode mulhwu. (xo 31 11 0 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode mfcr (x 31 19) $xrarb-mask ($ppc) $rt)
+
+   #.(ppc-opcode lwarx (x 31 20) $x-mask ($ppc) $rt $ra $rb)
+
+
+   #.(ppc-opcode ldx (x 31 21) $x-mask ($ppc $b64) $rt $ra $rb)
+
+
+   #.(ppc-opcode lwzx (x 31 23) $x-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode slw (xrc 31 24) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode slw. (xrc 31 24 1) $x-mask ($ppc) $rta $rs $rb)
+
+   #.(ppc-opcode cntlzw (xrc 31 26) $xrb-mask ($ppc) $rta $rs)
+   #.(ppc-opcode cntlzw. (xrc 31 26 1) $xrb-mask ($ppc) $rta $rs)
+
+
+   #.(ppc-opcode sld (xrc 31 27) $x-mask ($ppc $b64) $rta $rs $rb)
+   #.(ppc-opcode sld. (xrc 31 27 1) $x-mask ($ppc $b64) $rta $rs $rb)
+
+
+   #.(ppc-opcode and (xrc 31 28) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode and. (xrc 31 28 1) $x-mask ($ppc) $rta $rs $rb)
+
+   #.(ppc-opcode cmplw (xcmpl 31 32 0) $xcmpl-mask ($ppc) $obf $ra $rb)
+
+   #.(ppc-opcode cmpld (xcmpl 31 32 1) $xcmpl-mask ($ppc $b64) $obf $ra $rb)
+
+   #.(ppc-opcode cmpl (x 31 32) $xcmp-mask ($ppc) $bf $l $ra $rb)
+
+   #.(ppc-opcode subf (xo 31 40 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode sub (xo 31 40 0 0) $xo-mask ($ppc) $rt $rb $ra)
+   #.(ppc-opcode subf. (xo 31 40 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode sub. (xo 31 40 0 1) $xo-mask ($ppc) $rt $rb $ra)
+   #.(ppc-opcode subfo (xo 31 40 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subo (xo 31 40 1 0) $xo-mask ($ppc) $rt $rb $ra)
+   #.(ppc-opcode subfo. (xo 31 40 1 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subo. (xo 31 40 1 1) $xo-mask ($ppc) $rt $rb $ra)
+
+
+   #.(ppc-opcode ldux (x 31 53) $x-mask ($ppc $b64) $rt $ral $rb)
+
+
+   #.(ppc-opcode dcbst (x 31 54) $xrt-mask ($ppc) $ra $rb)
+
+   #.(ppc-opcode lwzux (x 31 55) $x-mask ($ppc) $rt $ral $rb)
+
+
+   #.(ppc-opcode cntlzd (xrc 31 58) $xrb-mask ($ppc $b64) $rta $rs)
+   #.(ppc-opcode cntlzd. (xrc 31 58 1) $xrb-mask ($ppc $b64) $rta $rs)
+
+
+   #.(ppc-opcode andc (xrc 31 60) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode andc. (xrc 31 60 1) $x-mask ($ppc) $rta $rs $rb)
+
+
+   #.(ppc-opcode tdlgt (xto 31 68 $tolgt) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdllt (xto 31 68 $tollt) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdeq (xto 31 68 $toeq) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdlge (xto 31 68 $tolge) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdlnl (xto 31 68 $tolnl) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdlle (xto 31 68 $tolle) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdlng (xto 31 68 $tolng) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdgt (xto 31 68 $togt) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdge (xto 31 68 $toge) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdnl (xto 31 68 $tonl) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdlt (xto 31 68 $tolt) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdle (xto 31 68 $tole) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdng (xto 31 68 $tong) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode tdne (xto 31 68 $tone) $xto-mask ($ppc $b64) $ra $rb)
+   #.(ppc-opcode td (x 31 68) $x-mask ($ppc $b64) $to $ra $rb)
+
+   #.(ppc-opcode mulhd (xo 31 73 0 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode mulhd. (xo 31 73 0 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+
+
+   #.(ppc-opcode mulhw (xo 31 75 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode mulhw. (xo 31 75 0 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode mfmsr (x 31 83) $xrarb-mask ($ppc) $rt)
+
+
+   #.(ppc-opcode ldarx (x 31 84) $x-mask ($ppc $b64) $rt $ra $rb)
+
+
+   #.(ppc-opcode dcbf (x 31 86) $xrt-mask ($ppc) $ra $rb)
+
+   #.(ppc-opcode lbzx (x 31 87) $x-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode neg (xo 31 104 0 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode neg. (xo 31 104 0 1) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode nego (xo 31 104 1 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode nego. (xo 31 104 1 1) $xorb-mask ($ppc) $rt $ra)
+
+   #.(ppc-opcode lbzux (x 31 119) $x-mask ($ppc) $rt $ral $rb)
+
+   #.(ppc-opcode not (xrc 31 124) $x-mask ($ppc) $rta $rs $rbs)
+   #.(ppc-opcode nor (xrc 31 124) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode not. (xrc 31 124 1) $x-mask ($ppc) $rta $rs $rbs)
+   #.(ppc-opcode nor. (xrc 31 124 1) $x-mask ($ppc) $rta $rs $rb)
+
+   #.(ppc-opcode subfe (xo 31 136 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subfe. (xo 31 136 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subfeo (xo 31 136 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode subfeo. (xo 31 136 1 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode adde (xo 31 138 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode adde. (xo 31 138 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode addeo (xo 31 138 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode addeo. (xo 31 138 1 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode mtcrf (x 31 144) (logior $x-mask (ash 1 20) (ash 1 11)) ($ppc) $fxm $rs)
+
+   #.(ppc-opcode mtmsr (x 31 146) $xrarb-mask ($ppc) $rs)
+
+
+   #.(ppc-opcode stdx (x 31 149) $x-mask ($ppc $b64) $rs $ra $rb)
+
+
+   #.(ppc-opcode stwcx. (xrc 31 150 1) $x-mask ($ppc) $rs $ra $rb)
+
+   #.(ppc-opcode stwx (x 31 151) $x-mask ($ppc) $rs $ra $rb)
+
+   #.(ppc-opcode stdux (x 31 181) $x-mask ($ppc $b64) $rs $ras $rb)
+
+   #.(ppc-opcode stwux (x 31 183) $x-mask ($ppc) $rs $ras $rb)
+
+   #.(ppc-opcode subfze (xo 31 200 0 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode subfze. (xo 31 200 0 1) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode subfzeo (xo 31 200 1 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode subfzeo. (xo 31 200 1 1) $xorb-mask ($ppc) $rt $ra)
+
+   #.(ppc-opcode addze (xo 31 202 0 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode addze. (xo 31 202 0 1) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode addzeo (xo 31 202 1 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode addzeo. (xo 31 202 1 1) $xorb-mask ($ppc) $rt $ra)
+
+   #.(ppc-opcode mtsr (x 31 210) (logior $xrb-mask (ash 1 20)) ($ppc $b32) $sr $rs)
+
+   #.(ppc-opcode stdcx. (xrc 31 214 1) $x-mask ($ppc $b64) $rs $ra $rb)
+
+   #.(ppc-opcode stbx (x 31 215) $x-mask ($ppc) $rs $ra $rb)
+
+   #.(ppc-opcode subfme (xo 31 232 0 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode subfme. (xo 31 232 0 1) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode subfmeo (xo 31 232 1 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode subfmeo. (xo 31 232 1 1) $xorb-mask ($ppc) $rt $ra)
+
+
+   #.(ppc-opcode mulld (xo 31 233 0 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode mulld. (xo 31 233 0 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode mulldo (xo 31 233 1 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode mulldo. (xo 31 233 1 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+
+
+   #.(ppc-opcode addme (xo 31 234 0 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode addme. (xo 31 234 0 1) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode addmeo (xo 31 234 1 0) $xorb-mask ($ppc) $rt $ra)
+   #.(ppc-opcode addmeo. (xo 31 234 1 1) $xorb-mask ($ppc) $rt $ra)
+
+   #.(ppc-opcode mullw (xo 31 235 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode mullw. (xo 31 235 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode mullwo (xo 31 235 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode mullwo. (xo 31 235 1 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode mtsrin (x 31 242) $xra-mask ($ppc $b32) $rs $rb)
+
+   #.(ppc-opcode dcbtst (x 31 246) $xrt-mask ($ppc) $ra $rb)
+
+   #.(ppc-opcode stbux (x 31 247) $x-mask ($ppc) $rs $ras $rb)
+
+   #.(ppc-opcode add (xo 31 266 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode add. (xo 31 266 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode addo (xo 31 266 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode addo. (xo 31 266 1 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode dcbt (x 31 278) $xrt-mask ($ppc) $ra $rb)
+
+   #.(ppc-opcode lhzx (x 31 279) $x-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode eqv (xrc 31 284) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode eqv. (xrc 31 284 1) $x-mask ($ppc) $rta $rs $rb)
+
+   #.(ppc-opcode tlbie (x 31 306) $xrtra-mask ($ppc) $rb)
+
+   #.(ppc-opcode eciwx (x 31 310) $x-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode lhzux (x 31 311) $x-mask ($ppc) $rt $ral $rb)
+
+   #.(ppc-opcode xor (xrc 31 316) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode xor. (xrc 31 316 1) $x-mask ($ppc) $rta $rs $rb)
+
+   #.(ppc-opcode mfxer (xspr 31 339 1) $xspr-mask ($ppc) $rt)
+   #.(ppc-opcode mflr (xspr 31 339 8) $xspr-mask ($ppc) $rt)
+   #.(ppc-opcode mfctr (xspr 31 339 9) $xspr-mask ($ppc) $rt)
+   #.(ppc-opcode mfspr (x 31 339) $x-mask ($ppc) $rt $spr)
+
+
+   #.(ppc-opcode lwax (x 31 341) $x-mask ($ppc $b64) $rt $ra $rb)
+
+   #.(ppc-opcode lhax (x 31 343) $x-mask ($ppc) $rt $ra $rb)
+
+
+   #.(ppc-opcode tlbia (x 31 370) #xffffffff ($ppc))
+
+   #.(ppc-opcode mftb (x 31 371) $x-mask ($ppc) $rt $tbr)
+
+
+   #.(ppc-opcode lwaux (x 31 373) $x-mask ($ppc $b64) $rt $ral $rb)
+
+   #.(ppc-opcode lhaux (x 31 375) $x-mask ($ppc) $rt $ral $rb)
+
+   #.(ppc-opcode sthx (x 31 407) $x-mask ($ppc) $rs $ra $rb)
+   #.(ppc-opcode orc (xrc 31 412) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode orc. (xrc 31 412 1) $x-mask ($ppc) $rta $rs $rb)
+
+   #.(ppc-opcode sradi (xs 31 413) $xs-mask ($ppc $b64) $rta $rs $sh6)
+   #.(ppc-opcode sradi. (xs 31 413 1) $xs-mask ($ppc $b64) $rta $rs $sh6)
+
+   #.(ppc-opcode slbie (x 31 434) $xrtra-mask ($ppc $b64) $rb)
+
+
+   #.(ppc-opcode ecowx (x 31 438) $x-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode sthux (x 31 439) $x-mask ($ppc) $rs $ras $rb)
+
+   #.(ppc-opcode mr (xrc 31 444) $x-mask ($ppc) $rta $rs $rbs)
+   #.(ppc-opcode or (xrc 31 444) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode mr. (xrc 31 444 1) $x-mask ($ppc) $rta $rs $rbs)
+   #.(ppc-opcode or. (xrc 31 444 1) $x-mask ($ppc) $rta $rs $rb)
+
+
+   #.(ppc-opcode divdu (xo 31 457 0 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode divdu. (xo 31 457 0 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode divduo (xo 31 457 1 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode divduo. (xo 31 457 1 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+
+
+   #.(ppc-opcode divwu (xo 31 459 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode divwu. (xo 31 459 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode divwuo (xo 31 459 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode divwuo. (xo 31 459 1 1) $xo-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode mtxer (xspr 31 467 1) $xspr-mask ($ppc) $rs)
+   #.(ppc-opcode mtlr (xspr 31 467 8) $xspr-mask ($ppc) $rs)
+   #.(ppc-opcode mtctr (xspr 31 467 9) $xspr-mask ($ppc) $rs)
+   #.(ppc-opcode mtspr (x 31 467) $x-mask ($ppc) $spr $rs)
+
+   #.(ppc-opcode dcbi (x 31 470) $xrt-mask ($ppc) $ra $rb)
+
+   #.(ppc-opcode nand (xrc 31 476) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode nand. (xrc 31 476 1) $x-mask ($ppc) $rta $rs $rb)
+
+
+   #.(ppc-opcode divd (xo 31 489 0 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode divd. (xo 31 489 0 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode divdo (xo 31 489 1 0) $xo-mask ($ppc $b64) $rt $ra $rb)
+   #.(ppc-opcode divdo. (xo 31 489 1 1) $xo-mask ($ppc $b64) $rt $ra $rb)
+
+   #.(ppc-opcode divw (xo 31 491 0 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode divw. (xo 31 491 0 1) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode divwo (xo 31 491 1 0) $xo-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode divwo. (xo 31 491 1 1) $xo-mask ($ppc) $rt $ra $rb)
+
+
+   #.(ppc-opcode slbia (x 31 498) #xffffffff ($ppc $b64))
+
+
+
+   #.(ppc-opcode mcrxr (x 31 512) (logior $xrarb-mask (ash 3 21)) ($ppc) $bf)
+
+   #.(ppc-opcode lswx (x 31 533) $x-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode lwbrx (x 31 534) $x-mask ($ppc) $rt $ra $rb)
+
+   #.(ppc-opcode lfsx (x 31 535) $x-mask ($ppc) $frt $ra $rb)
+
+   #.(ppc-opcode srw (xrc 31 536) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode srw. (xrc 31 536 1) $x-mask ($ppc) $rta $rs $rb)
+
+
+
+   #.(ppc-opcode srd (xrc 31 539) $x-mask ($ppc $b64) $rta $rs $rb)
+   #.(ppc-opcode srd. (xrc 31 539 1) $x-mask ($ppc $b64) $rta $rs $rb)
+
+
+   #.(ppc-opcode tlbsync (x 31 566) #xffffffff ($ppc))
+
+   #.(ppc-opcode lfsux (x 31 567) $x-mask ($ppc) $frt $ras $rb)
+
+   #.(ppc-opcode mfsr (x 31 595) (logior $xrb-mask (ash 1 20)) ($ppc $b32) $rt $sr)
+
+   #.(ppc-opcode lswi (x 31 597) $x-mask ($ppc) $rt $ra $nb)
+
+   #.(ppc-opcode lwsync (xsync 31 598 1) #xffffffff ($ppc))
+   #.(ppc-opcode sync (x 31 598) $xsync-mask ($ppc))
+
+   #.(ppc-opcode lfdx (x 31 599) $x-mask ($ppc) $frt $ra $rb)
+   #.(ppc-opcode lfdux (x 31 631) $x-mask ($ppc) $frt $ras $rb)
+
+   #.(ppc-opcode mfsrin (x 31 659) $xra-mask ($ppc $b32) $rt $rb)
+
+   #.(ppc-opcode stswx (x 31 661) $x-mask ($ppc) $rs $ra $rb)
+
+   #.(ppc-opcode stwbrx (x 31 662) $x-mask ($ppc) $rs $ra $rb)
+
+   #.(ppc-opcode stfsx (x 31 663) $x-mask ($ppc) $frs $ra $rb)
+   #.(ppc-opcode stfsux (x 31 695) $x-mask ($ppc) $frs $ras $rb)
+   #.(ppc-opcode stswi (x 31 725) $x-mask ($ppc) $rs $ra $nb)
+   #.(ppc-opcode stfdx (x 31 727) $x-mask ($ppc) $frs $ra $rb)
+   #.(ppc-opcode stfdux (x 31 759) $x-mask ($ppc) $frs $ras $rb)
+   #.(ppc-opcode lhbrx (x 31 790) $x-mask ($ppc) $rt $ra $rb)
+   #.(ppc-opcode sraw (xrc 31 792) $x-mask ($ppc) $rta $rs $rb)
+   #.(ppc-opcode sraw. (xrc 31 792 1) $x-mask ($ppc) $rta $rs $rb)
+
+
+   #.(ppc-opcode srad (xrc 31 794) $x-mask ($ppc $b64) $rta $rs $rb)
+   #.(ppc-opcode srad. (xrc 31 794 1) $x-mask ($ppc $b64) $rta $rs $rb)
+
+
+   #.(ppc-opcode srawi (xrc 31 824) $x-mask ($ppc) $rta $rs $sh)
+   #.(ppc-opcode srawi. (xrc 31 824 1) $x-mask ($ppc) $rta $rs $sh)
+
+   #.(ppc-opcode eieio (x 31 854) #xffffffff ($ppc))
+
+   #.(ppc-opcode sthbrx (x 31 918) $x-mask ($ppc) $rs $ra $rb)
+
+   #.(ppc-opcode extsh (xrc 31 922) $xrb-mask ($ppc) $rta $rs)
+   #.(ppc-opcode extsh. (xrc 31 922 1) $xrb-mask ($ppc) $rta $rs)
+
+   #.(ppc-opcode extsb (xrc 31 954) $xrb-mask ($ppc) $rta $rs)
+   #.(ppc-opcode extsb. (xrc 31 954 1) $xrb-mask ($ppc) $rta $rs)
+
+   #.(ppc-opcode icbi (x 31 982) $xrt-mask ($ppc) $ra $rb)
+
+   #.(ppc-opcode stfiwx (x 31 983) $x-mask ($ppc) $frs $ra $rb)
+
+   #.(ppc-opcode extsw (xrc 31 986) $xrb-mask ($ppc) $rta $rs)
+   #.(ppc-opcode extsw. (xrc 31 986 1) $xrb-mask ($ppc) $rta $rs)
+
+   #.(ppc-opcode dcbz (x 31 1014) $xrt-mask ($ppc) $ra $rb)
+   #.(ppc-opcode dclz (x 31 1014) $xrt-mask ($ppc) $ra $rb)
+
+   #.(ppc-opcode lvebx (x 31 7) $x-mask ($ppc) $vd $ra $rb)
+   #.(ppc-opcode lvehx (x 31 39) $x-mask ($ppc) $vd $ra $rb)
+   #.(ppc-opcode lvewx (x 31 71) $x-mask ($ppc) $vd $ra $rb)
+   #.(ppc-opcode lvsl (x 31 6) $x-mask ($ppc) $vd $ra $rb)
+   #.(ppc-opcode lvsr (x 31 38) $x-mask ($ppc) $vd $ra $rb)
+   #.(ppc-opcode lvx (x 31 103) $x-mask ($ppc) $vd $ra $rb)
+   #.(ppc-opcode lvxl (x 31 359) $x-mask ($ppc) $vd $ra $rb)
+   #.(ppc-opcode stvebx (x 31 135) $x-mask ($ppc) $vs $ra $rb)
+   #.(ppc-opcode stvehx (x 31 167) $x-mask ($ppc) $vs $ra $rb)
+   #.(ppc-opcode stvewx (x 31 199) $x-mask ($ppc) $vs $ra $rb)
+   #.(ppc-opcode stvx (x 31 231) $x-mask ($ppc) $vs $ra $rb)
+   #.(ppc-opcode stvxl (x 31 487) $x-mask ($ppc) $vs $ra $rb)
+
+   #.(ppc-opcode dss (x 31 822) $x-mask ($ppc) $strm $all/transient)
+   #.(ppc-opcode dst (x 31 342) $x-mask ($ppc) $ra $rb $strm $all/transient)
+   #.(ppc-opcode dstst (x 31 374) $x-mask ($ppc) $ra $rb $strm $all/transient)
+	 
+   #.(ppc-opcode lwz (op 32) $op-mask ($ppc) $rt $d $ra)
+
+   #.(ppc-opcode lwzu (op 33) $op-mask ($ppc) $rt $d $ral)
+
+   #.(ppc-opcode lbz (op 34) $op-mask ($ppc) $rt $d $ra)
+
+   #.(ppc-opcode lbzu (op 35) $op-mask ($ppc) $rt $d $ral)
+
+   #.(ppc-opcode stw (op 36) $op-mask ($ppc) $rs $d $ra)
+
+   #.(ppc-opcode stwu (op 37) $op-mask ($ppc) $rs $d $ras)
+
+   #.(ppc-opcode stb (op 38) $op-mask ($ppc) $rs $d $ra)
+
+   #.(ppc-opcode stbu (op 39) $op-mask ($ppc) $rs $d $ras)
+
+   #.(ppc-opcode lhz (op 40) $op-mask ($ppc) $rt $d $ra)
+
+   #.(ppc-opcode lhzu (op 41) $op-mask ($ppc) $rt $d $ral)
+
+   #.(ppc-opcode lha (op 42) $op-mask ($ppc) $rt $d $ra)
+
+   #.(ppc-opcode lhau (op 43) $op-mask ($ppc) $rt $d $ral)
+
+   #.(ppc-opcode sth (op 44) $op-mask ($ppc) $rs $d $ra)
+
+   #.(ppc-opcode sthu (op 45) $op-mask ($ppc) $rs $d $ras)
+
+   #.(ppc-opcode lmw (op 46) $op-mask ($ppc) $rt $d $ram)
+
+   #.(ppc-opcode stmw (op 47) $op-mask ($ppc) $rs $d $ra)
+
+   #.(ppc-opcode lfs (op 48) $op-mask ($ppc) $frt $d $ra)
+
+   #.(ppc-opcode lfsu (op 49) $op-mask ($ppc) $frt $d $ras)
+
+   #.(ppc-opcode lfd (op 50) $op-mask ($ppc) $frt $d $ra)
+
+   #.(ppc-opcode lfdu (op 51) $op-mask ($ppc) $frt $d $ras)
+
+   #.(ppc-opcode stfs (op 52) $op-mask ($ppc) $frs $d $ra)
+
+   #.(ppc-opcode stfsu (op 53) $op-mask ($ppc) $frs $d $ras)
+
+   #.(ppc-opcode stfd (op 54) $op-mask ($ppc) $frs $d $ra)
+
+   #.(ppc-opcode stfdu (op 55) $op-mask ($ppc) $frs $d $ras)
+
+
+
+
+   #.(ppc-opcode ld (dso 58 0) $ds-mask ($ppc $b64) $rt $ds $ra)
+
+   #.(ppc-opcode ldu (dso 58 1) $ds-mask ($ppc $b64) $rt $ds $ral)
+
+   #.(ppc-opcode lwa (dso 58 2) $ds-mask ($ppc $b64) $rt $ds $ra)
+
+
+   #.(ppc-opcode fdivs (a 59 18 0) $afrc-mask ($ppc) $frt $fra $frb)
+   #.(ppc-opcode fdivs. (a 59 18 1) $afrc-mask ($ppc) $frt $fra $frb)
+
+   #.(ppc-opcode fsubs (a 59 20 0) $afrc-mask ($ppc) $frt $fra $frb)
+   #.(ppc-opcode fsubs. (a 59 20 1) $afrc-mask ($ppc) $frt $fra $frb)
+
+   #.(ppc-opcode fadds (a 59 21 0) $afrc-mask ($ppc) $frt $fra $frb)
+   #.(ppc-opcode fadds. (a 59 21 1) $afrc-mask ($ppc) $frt $fra $frb)
+
+   #.(ppc-opcode fsqrts (a 59 22 0) $afrafrc-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fsqrts. (a 59 22 1) $afrafrc-mask ($ppc) $frt $frb)
+
+   #.(ppc-opcode fres (a 59 24 0) $afrafrc-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fres. (a 59 24 1) $afrafrc-mask ($ppc) $frt $frb)
+
+   #.(ppc-opcode fmuls (a 59 25 0) $afrb-mask ($ppc) $frt $fra $frc)
+   #.(ppc-opcode fmuls. (a 59 25 1) $afrb-mask ($ppc) $frt $fra $frc)
+
+   #.(ppc-opcode fmsubs (a 59 28 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fmsubs. (a 59 28 1) $a-mask ($ppc) $frt $fra $frc $frb)
+
+   #.(ppc-opcode fmadds (a 59 29 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fmadds. (a 59 29 1) $a-mask ($ppc) $frt $fra $frc $frb)
+
+   #.(ppc-opcode fnmsubs (a 59 30 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fnmsubs. (a 59 30 1) $a-mask ($ppc) $frt $fra $frc $frb)
+
+   #.(ppc-opcode fnmadds (a 59 31 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fnmadds. (a 59 31 1) $a-mask ($ppc) $frt $fra $frc $frb)
+
+
+
+
+   #.(ppc-opcode std (dso 62 0) $ds-mask ($ppc $b64) $rs $ds $ra)
+
+   #.(ppc-opcode stdu (dso 62 1) $ds-mask ($ppc $b64) $rs $ds $ras)
+
+
+   #.(ppc-opcode fcmpu (x 63 0) (logior $x-mask (ash 3 21)) ($ppc) $bf $fra $frb)
+
+   #.(ppc-opcode frsp (xrc 63 12) $xra-mask ($ppc) $frt $frb)
+   #.(ppc-opcode frsp. (xrc 63 12 1) $xra-mask ($ppc) $frt $frb)
+
+   #.(ppc-opcode fctiw (xrc 63 14) $xra-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fctiw. (xrc 63 14 1) $xra-mask ($ppc) $frt $frb)
+   
+   #.(ppc-opcode fctiwz (xrc 63 15) $xra-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fctiwz. (xrc 63 15 1) $xra-mask ($ppc) $frt $frb)
+   
+   #.(ppc-opcode fdiv (a 63 18 0) $afrc-mask ($ppc) $frt $fra $frb)
+   #.(ppc-opcode fdiv. (a 63 18 1) $afrc-mask ($ppc) $frt $fra $frb)
+   
+   #.(ppc-opcode fsub (a 63 20 0) $afrc-mask ($ppc) $frt $fra $frb)
+   #.(ppc-opcode fsub. (a 63 20 1) $afrc-mask ($ppc) $frt $fra $frb)
+   
+   #.(ppc-opcode fadd (a 63 21 0) $afrc-mask ($ppc) $frt $fra $frb)
+   #.(ppc-opcode fadd. (a 63 21 1) $afrc-mask ($ppc) $frt $fra $frb)
+
+   #.(ppc-opcode fsqrt (a 63 22 0) $afrafrc-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fsqrt. (a 63 22 1) $afrafrc-mask ($ppc) $frt $frb)
+   
+   #.(ppc-opcode fsel (a 63 23 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fsel. (a 63 23 1) $a-mask ($ppc) $frt $fra $frc $frb)
+
+   #.(ppc-opcode fmul (a 63 25 0) $afrb-mask ($ppc) $frt $fra $frc)
+   #.(ppc-opcode fmul. (a 63 25 1) $afrb-mask ($ppc) $frt $fra $frc)
+      
+   #.(ppc-opcode fmsub (a 63 28 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fmsub. (a 63 28 1) $a-mask ($ppc) $frt $fra $frc $frb)
+
+   #.(ppc-opcode fmadd (a 63 29 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fmadd. (a 63 29 1) $a-mask ($ppc) $frt $fra $frc $frb)
+
+   #.(ppc-opcode fnmsub (a 63 30 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fnmsub. (a 63 30 1) $a-mask ($ppc) $frt $fra $frc $frb)
+   
+   #.(ppc-opcode fnmadd (a 63 31 0) $a-mask ($ppc) $frt $fra $frc $frb)
+   #.(ppc-opcode fnmadd. (a 63 31 1) $a-mask ($ppc) $frt $fra $frc $frb)
+   
+   #.(ppc-opcode fcmpo (x 63 32) (logior $x-mask (ash 3 21)) ($ppc) $bf $fra $frb)
+
+   #.(ppc-opcode mtfsb1 (xrc 63 38) $xrarb-mask ($ppc) $bt)
+   #.(ppc-opcode mtfsb1. (xrc 63 38 1) $xrarb-mask ($ppc) $bt)
+
+   #.(ppc-opcode fneg (xrc 63 40) $xra-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fneg. (xrc 63 40 1) $xra-mask ($ppc) $frt $frb)
+
+   #.(ppc-opcode mcrfs (x 63 64) (logior $xrb-mask (ash 3 21) (ash 3 16)) ($ppc) $bf $bfa)
+
+   #.(ppc-opcode mtfsb0 (xrc 63 70) $xrarb-mask ($ppc) $bt)
+   #.(ppc-opcode mtfsb0. (xrc 63 70 1) $xrarb-mask ($ppc) $bt)
+
+   #.(ppc-opcode fmr (xrc 63 72) $xra-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fmr. (xrc 63 72 1) $xra-mask ($ppc) $frt $frb)
+
+   #.(ppc-opcode mtfsfi (xrc 63 134) (logior $xra-mask (ash 3 21) (ash 1 11)) ($ppc) $bf $u)
+   #.(ppc-opcode mtfsfi. (xrc 63 134 1) (logior $xra-mask (ash 3 21) (ash 1 11)) ($ppc) $bf $u)
+
+   #.(ppc-opcode fnabs (xrc 63 136) $xra-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fnabs. (xrc 63 136 1) $xra-mask ($ppc) $frt $frb)
+
+   #.(ppc-opcode fabs (xrc 63 264) $xra-mask ($ppc) $frt $frb)
+   #.(ppc-opcode fabs. (xrc 63 264 1) $xra-mask ($ppc) $frt $frb)
+
+   #.(ppc-opcode mffs (xrc 63 583) $xrarb-mask ($ppc) $frt)
+   #.(ppc-opcode mffs. (xrc 63 583 1) $xrarb-mask ($ppc) $frt)
+
+   #.(ppc-opcode mtfsf (xfl 63 711) $xfl-mask ($ppc) $flm $frb)
+   #.(ppc-opcode mtfsf. (xfl 63 711 1) $xfl-mask ($ppc) $flm $frb)
+
+   #.(ppc-opcode fctid (xrc 63 814) $xra-mask ($ppc $b64) $frt $frb)
+   #.(ppc-opcode fctid. (xrc 63 814 1) $xra-mask ($ppc $b64) $frt $frb)
+
+   #.(ppc-opcode fctidz (xrc 63 815) $xra-mask ($ppc $b64) $frt $frb)
+   #.(ppc-opcode fctidz. (xrc 63 815 1) $xra-mask ($ppc $b64) $frt $frb)
+
+   #.(ppc-opcode fcfid (xrc 63 846) $xra-mask ($ppc $b64) $frt $frb)
+   #.(ppc-opcode fcfid. (xrc 63 846 1) $xra-mask ($ppc $b64) $frt $frb)
+
+))
+
+(defvar *ppc-opcode-indices* (make-array 64 :initial-element -1))
+(defvar *ppc-opcode-counts* (make-array 64 :initial-element 0))
+(defvar *ppc-opcode-numbers* (make-hash-table :test #'equalp))
+(defvar *ppc-instruction-macros* (make-hash-table :test #'equalp))
+
+(defun initialize-ppc-opcode-numbers ()
+  (clrhash *ppc-opcode-numbers*)
+  (dotimes (i 64) 
+    (setf (svref *ppc-opcode-indices* i) -1
+          (svref *ppc-opcode-counts* i) 0))
+  (dotimes (i (length *ppc-opcodes*))
+    (let* ((code (svref *ppc-opcodes* i))
+    (opcode (ccl::opcode-opcode code))
+    (mask (ccl::opcode-mask code)))
+      (setf (gethash (string (ccl::opcode-name code))  *ppc-opcode-numbers*) i)
+      (setf (ccl::opcode-op-high code) (ldb (byte 16 16) opcode)
+     (ccl::opcode-op-low code) (ldb (byte 16 0) opcode)
+     (ccl::opcode-mask-high code) (ldb (byte 16 16) mask)
+     (ccl::opcode-mask-low code) (ldb (byte 16 0) mask))
+      (setf (ccl::opcode-vinsn-operands code) (ccl::opcode-operands code)
+     (ccl::opcode-min-vinsn-args code) (ccl::opcode-min-args code)
+     (ccl::opcode-max-vinsn-args code) (ccl::opcode-max-args code))
+      (let* ((op (ccl::opcode-majorop code)))
+          (if (= -1 (svref *ppc-opcode-indices* op))
+            (setf (svref *ppc-opcode-indices* op) i
+                  (svref *ppc-opcode-counts* op) 1)
+            (incf (svref *ppc-opcode-counts* op))))))
+  (when (fboundp 'ccl::fixup-vinsn-templates)   ; not defined yet at bootstrap time
+    (ccl::fixup-vinsn-templates (ccl::backend-p2-vinsn-templates ccl::*target-backend*) *ppc-opcode-numbers* ))
+  (when (fboundp 'ccl::fixup-ppc-backend)
+    (ccl::fixup-ppc-backend)))
+
+(initialize-ppc-opcode-numbers)
+
+
+(defmacro defppcmacro (name arglist &body body)
+  `(setf (ppc-macro-function ',(string name))
+         #',(ccl:parse-macro name arglist body)))
+
+(defun ppc-macro-function (name)
+  (gethash (string name) *ppc-instruction-macros*))
+
+(defun (setf ppc-macro-function) (new-function name)
+  (if (gethash name *ppc-opcode-numbers*)
+    (error "~s is already defined as an assembler instruction" name))
+  (setf (gethash name *ppc-instruction-macros*) new-function))
+
+(defppcmacro extlwi (ra rs n b)
+  `(rlwinm ,ra ,rs ,b 0 (1- ,n)))
+
+(defppcmacro extlwi. (ra rs n b)
+  `(rlwinm. ,ra ,rs ,b 0 (1- ,n)))
+
+(defppcmacro extrwi (ra rs n b)
+  `(rlwinm ,ra ,rs (+ ,b ,n) (- 32 ,n) 31))
+
+(defppcmacro extrwi. (ra rs n b)
+  `(rlwinm. ,ra ,rs (+ ,b ,n) (- 32 ,n) 31))
+
+(defppcmacro inslwi (ra rs n b)
+  `(rlwimi ,ra ,rs (- 32 ,b) ,b (1- (+ ,b ,n))))
+
+(defppcmacro inslwi. (ra rs n b)
+  `(rlwimi. ,ra ,rs (- 32 ,b) ,b (1- (+ ,b ,n))))
+
+(defppcmacro insrwi (ra rs n b)
+  `(rlwimi ,ra ,rs (- 32 (+ ,b ,n)) ,b (1- (+ ,b ,n))))
+
+(defppcmacro insrwi. (ra rs n b)
+  `(rlwimi. ,ra ,rs (- 32 (+ ,b ,n)) ,b (1- (+ ,b ,n))))
+
+(defppcmacro rotrwi (ra rs n)
+  `(rlwinm ,ra ,rs (- 32 ,n) 0 31))
+
+(defppcmacro rotrwi. (ra rs n)
+  `(rlwinm. ,ra ,rs (- 32 ,n) 0 31))
+
+(defppcmacro slwi (ra rs n)
+  `(rlwinm ,ra ,rs ,n 0 (- 31 ,n)))
+
+(defppcmacro slwi. (ra rs n)
+  `(rlwinm. ,ra ,rs ,n 0 (- 31 ,n)))
+
+(defppcmacro srwi (ra rs n)
+  `(rlwinm ,ra ,rs (- 32 ,n) ,n 31))
+
+(defppcmacro srwi. (ra rs n)
+  `(rlwinm. ,ra ,rs (- 32 ,n) ,n 31))
+
+(defppcmacro clrrwi (ra rs n)
+  `(rlwinm ,ra ,rs 0 0 (- 31 ,n)))
+
+(defppcmacro clrrwi. (ra rs n)
+  `(rlwinm. ,ra ,rs 0 0 (- 31 ,n)))
+
+(defppcmacro clrlslwi (ra rs b n)
+  `(rlwinm ,ra ,rs ,n (- ,b ,n) (- 31 ,n)))
+
+(defppcmacro clrlslwi. (ra rs b n)
+  `(rlwinm. ,ra ,rs ,n (- ,b ,n) (- 31 ,n)))
+
+(defppcmacro extldi (ra rs n b)
+  `(rldicr ,ra ,rs ,b ,n))
+
+(defppcmacro extldi. (ra rs n b)
+  `(rldicr. ,ra ,rs ,b ,n))
+
+(defppcmacro extrdi (ra rs n b)
+  `(rldicl ,ra ,rs (+ ,b ,n) (- 64 ,n)))
+
+(defppcmacro extrdi. (ra rs n b)
+  `(rldicl. ,ra ,rs (+ ,b ,n) (- 64 ,n)))
+
+(defppcmacro insrdi (ra rs n b)
+  `(rldimi ,ra ,rs (- 64 (+ ,b ,n)) ,b))
+
+(defppcmacro insrdi. (ra rs n b)
+  `(rldimi. ,ra ,rs (- 64 (+ ,b ,n)) ,b))
+
+(defppcmacro rotrdi (ra rs n)
+  `(rldicl ,ra ,rs (- 64 ,n) 0))
+
+(defppcmacro rotrdi. (ra rs n)
+  `(rldicl. ,ra ,rs (- 64 ,n) 0))
+
+(defppcmacro sldi (ra rs n)
+  `(rldicr ,ra ,rs ,n (- 63 ,n)))
+
+(defppcmacro sldi. (ra rs n)
+  `(rldicr. ,ra ,rs ,n (- 63 ,n)))
+
+(defppcmacro srdi (ra rs n)
+  `(rldicl ,ra ,rs (- 64 ,n) ,n))
+
+(defppcmacro srdi. (ra rs n)
+  `(rldicl. ,ra ,rs (- 64 ,n) ,n))
+
+(defppcmacro clrrdi (ra rs n)
+  `(rldicr ,ra ,rs 0 (- 63 ,n)))
+
+(defppcmacro clrrdi. (ra rs n)
+  `(rldicr. ,ra ,rs 0 (- 63 ,n)))
+
+(defppcmacro clrlsldi (ra rs b sh)
+  `(rldic ,ra ,rs ,sh (- ,b ,sh)))
+
+(defppcmacro clrlsldi. (ra rs b sh)
+  `(rldic. ,ra ,rs ,sh (- ,b ,sh)))
+
+
+;; Vector unit macros
+(defppcmacro dssall ()
+  ;;Data stream stop all
+  `(dss 0 1))
+
+(defppcmacro dstt (a b strm)
+  `(dst ,a ,b ,strm 1))
+
+(defppcmacro dststt (a b strm)
+  `(dstst ,a ,b ,strm 1))
+
+(defppcmacro vmr (vd vs)
+  ;;Analogous to mr for GP registers. Moves contents of vs to vd
+  `(vor ,vd ,vs ,vs))
+
+
+
+
+;; The BA field in an XL form instruction when it must be the same as
+;; the BT field in the same instruction.  This operand is marked FAKE.
+;; The insertion function just copies the BT field into the BA field,
+;; and the extraction function just checks that the fields are the
+;; same. 
+
+(defun insert-bat (high low val)
+  (declare (ignore val))
+  (values  (dpb (ldb (byte 5 (- 21 16)) high) (byte 5 (- 16 16)) high) low))
+
+(defun extract-bat (instr)
+  (if (= (ldb (byte 5 21) instr) (ldb (byte 5 16) instr))
+    0))
+
+;; The BB field in an XL form instruction when it must be the same as
+;; the BA field in the same instruction.  This operand is marked FAKE.
+;; The insertion function just copies the BA field into the BB field,
+;; and the extraction function just checks that the fields are the
+;; same. 
+
+(defun insert-bba (high low val)
+  (declare (ignore val))
+  (values high (dpb (ldb (byte 5 (- 21 16)) high) (byte 5 11) low)))
+
+(defun extract-bba (instr)
+  (if (= (ldb (byte 5 16) instr) (ldb (byte 5 11) instr))
+    0))
+
+;; The BD field in a B form instruction.  The lower two bits are
+;; forced to zero.
+
+(defun insert-bd (high low val)
+  (values high (logior (logand val #xfffc) (logand low 3))))
+
+(defun extract-bd (instr)
+  (- (logand instr #xfffc)
+     (if (logbitp 15 instr)                ; negative branch displacement
+       #x10000
+       0)))
+
+;; The BD field in a B form instruction when the - modifier is used.
+;; This modifier means that the branch is not expected to be taken.
+;; We must set the y bit of the BO field to 1 if the offset is
+;; negative.  When extracting, we require that the y bit be 1 and that
+;; the offset be positive, since if the y bit is 0 we just want to
+;; print the normal form of the instruction. 
+
+(defun insert-bdm (high low val)
+  (values
+   (if (logbitp 15 val) (logior high (ash 1 (- 21 16))) high)
+   (logior (logand val #xfffc) (logand low 3))))
+
+(defun extract-bdm (instr)
+  ;; Recognize this if both the "y" (branch predict false) bit
+  ;;  is set and the displacement is negative.
+  (if (and (logbitp 15 instr)           ; branch disp is negative
+           (logbitp 21 instr))          ; prediction inverted
+    (extract-bd instr)))                ; return the displacement
+
+;; The BD field in a B form instruction when the + modifier is used.
+;; This is like BDM, above, except that the branch is expected to be
+;; taken.
+
+(defun insert-bdp (high low val)
+  (values
+   (if (logbitp 15 val) high (logior high (ash 1 (- 21 16))))
+   (logior (logand val #xfffc) (logand low 3))))
+
+(defun extract-bdp (instr)
+  ;; Recognize this if both the "y" (branch predict false) bit
+  ;;  is set and the displacement is non-negative.
+  (if (and (not (logbitp 15 instr))     ; branch disp is non-negative
+           (logbitp 21 instr))          ; prediction inverted
+    (extract-bd instr)))                ; return the displacement
+
+;; return nil if val isn't a valid bo field i.e. if it has any reserved bits set.
+(defun valid-bo (val)
+  (and (= val (ldb (byte 5 0) val))
+       (case (logand val #x14)
+             (4 (not (logbitp 1 val)))
+             (#x10 (not (logbitp 3 val)))
+             (#x14 (= val #x14))
+             (t t))))
+ 
+;; The BO field in a B form instruction.  Fail on attempts to set
+;; the field to an illegal value.
+(defun insert-bo (high low val)
+  (if (valid-bo val)
+    (values (dpb val (byte 5 (- 21 16)) high) low)))
+
+(defun extract-bo (instr)
+  (let* ((val (ldb (byte 5 21) instr)))
+    (and (valid-bo val) val)))
+
+;; The BO field in a B form instruction when the + or - modifier is
+;; used.  This is like the BO field, but it must be even.  When
+;; extracting it, we force it to be even.
+
+(defun insert-boe (high low val)
+  (unless (logbitp 0 val) (insert-bo high low val)))
+
+(defun extract-boe (instr)
+  (let* ((val (extract-bo instr)))
+    (if val (logandc2 val 1))))
+
+;; The condition register number portion of the BI field in a B form
+;; or XL form instruction.  This is used for the extended conditional
+;; branch mnemonics, which set the lower two bits of the BI field.  It
+;; is the BI field with the lower two bits ignored.
+
+(defun insert-cr (high low val)
+  (values (dpb (ash val -2) (byte 3 (- 18 16)) high) low))
+
+(defun extract-cr (instr)
+  (logandc2 (ldb (byte 5 16) instr) 3))
+
+(defun insert-bf (high low val)
+  (values (dpb (ash val -2) (byte 3 (- 23 16)) high) low))
+
+(defun extract-bf (instr)
+  (logandc2 (ldb (byte 5 21) instr) 3))
+
+
+;; The DS field in a DS form instruction.  This is like D, but the
+;; lower two bits are forced to zero.
+(defun insert-ds (high low val)
+  (when (logtest #b11 val)
+    (warn "low two bits of operand #x~8,'0x must be zero - clearing."
+	  val))
+  (values high (logior low (logand val #xfffc))))
+
+(defun extract-ds (instr)
+  (- (logand instr #xfffc) (if (logbitp 15 instr) #x10000 0)))
+
+;; The LI field in an I form instruction.  The lower two bits are
+;; forced to zero.
+
+(defun insert-li (high low val)
+  (values (dpb (ash val -16) (byte 10 (- 16 16)) high) (logior (logand val #xfffc) (logand low 3))))
+
+(defun extract-li (instr)
+  (- (logand instr #x3fffffc) (if (logbitp 25 instr) #x4000000 0)))
+
+;; The MB and ME fields in an M form instruction expressed as a single
+;; operand which is itself a bitmask.  The extraction function always
+;; marks it as invalid, since we never want to recognize an
+;; instruction which uses a field of this type.
+
+#|
+(defun insert-mbe (instr val)
+  (let* ((uval val)
+         (me 31))
+    (declare (integer uval)
+             (fixnum me))
+    (when (/= uval 0)
+      (do ()
+          ((logbitp 0 uval))
+        (setq uval (ash uval -1))
+        (decf me))
+      (let* ((nbits (logcount uval))
+             (mb (- (1+ me) nbits)))
+        (declare (fixnum nbits mb))
+        (when (= nbits (integer-length uval))
+          (dpb me (byte 5 1) (dpb mb (byte 5 6) instr)))))))
+
+
+(defun extract-mbe (instr)
+  (declare (ignore instr)))
+
+;; The MB or ME field in an MD or MDS form instruction.  The high bit
+;; is wrapped to the low end.
+
+
+|#
+
+;; The NB field in an X form instruction.  The value 32 is stored as
+;; 0.
+
+(defun insert-nb (high low val)
+  (if (<= 0 val 32)
+    (values high (dpb val (byte 5 11) low))))
+
+(defun extract-nb (instr)
+  (let* ((val (ldb (byte 5 11) instr)))
+    (declare (fixnum val))
+    (if (= val 0) 32 val)))
+
+;; The NSI field in a D form instruction.  This is the same as the SI
+;; field, only negated.  The extraction function always marks it as
+;; invalid, since we never want to recognize an instruction which uses
+;; a field of this type.
+(defun insert-nsi (high low val)
+  (declare (ignore low))
+  (values high (logand (- val) #xffff)))
+
+(defun extract-nsi (instr)
+  (declare (ignore instr)))
+
+;; The RA field in a D or X form instruction which is an updating
+;; load, which means that the RA field may not be zero and may not
+;; equal the RT field.
+
+(defun insert-ral (high low val)
+  (and (/= val 0)
+       (/= val (ldb (byte 5 (- 21 16)) high))
+       (values (dpb val (byte 5 (- 16 16)) high) low)))
+
+;; The RA field in an lmw instruction, which has special value
+;; restrictions.
+(defun insert-ram (high low val)
+  (if (< val (ldb (byte 5 (- 21 16)) high))
+    (values (dpb val (byte 5 (- 16 16)) high) low)))
+
+;; The RA field in a D or X form instruction which is an updating
+;; store or an updating floating point load, which means that the RA
+;; field may not be zero. 
+
+(defun insert-ras (high low val)
+  (unless (= val 0)
+    (values (dpb val (byte 5 (- 16 16)) high) low)))
+ 
+;; The RB field in an X form instruction when it must be the same as
+;; the RS field in the instruction.  This is used for extended
+;; mnemonics like mr.  This operand is marked FAKE.  The insertion
+;; function just copies the BT field into the BA field, and the
+;; extraction function just checks that the fields are the same.
+
+(defun insert-rbs (high low val)
+  (declare (ignore val))
+  (values high (dpb (ldb (byte 5 (- 21 16)) high) (byte 5 11) low)))
+
+(defun extract-rbs (instr)
+  (if (= (ldb (byte 5 21) instr) (ldb (byte 5 11) instr))
+    0))
+
+;; The SH field in an MD form instruction.  This is split.
+(defun insert-sh6 (high low val)
+  (values high
+          (dpb (ldb (byte 5 0) val) (byte 5 11)
+               (dpb (ldb (byte 1 5) val) (byte 1 1) low))))
+
+(defun extract-sh6 (instr)
+  (logior (ldb (byte 5 11) instr) (ash (ldb (byte 1 1) instr) 5)))
+
+
+(defun insert-mb6 (high low val)
+  (values high
+          (dpb (ldb (byte 1 5) val)
+               (byte 1 5)
+               (dpb val (byte 5 6) low))))
+
+(defun extract-mb6 (instr)
+  (dpb (ldb (byte 1 5) instr)
+       (byte 1 5)
+       (ldb (byte 5 6) instr)))
+
+
+;; The SPR or TBR field in an XFX form instruction.  This is
+;; flipped--the lower 5 bits are stored in the upper 5 and vice-
+;; versa.
+(defun insert-spr (high low val)
+  (values (dpb val (byte 5 (- 16 16)) high)
+          (logior low (ash (logand val #x3e0) 6))))
+
+
+(defun extract-spr (instr)
+  (logior (ldb (byte 5 16) instr) (logand #x3e0 (ash instr -6))))
+
+(defun insert-default (operand high low val)
+  (let* ((width (ccl::operand-width operand))
+         (offset (ccl::operand-offset operand))
+         (msbit (1- (+ width offset))))
+    (declare (fixnum width offset msbit))
+    (if (>= offset 16)
+      (values (dpb val (byte width (- offset 16)) high) low)
+      (if (< msbit 16)
+        (values high (dpb val (byte width offset) low))
+        (let* ((lowbits (- 16 offset)))
+          (values
+           (dpb (the fixnum (ash val (the fixnum (- lowbits))))
+                (byte  (the fixnum (- width lowbits)) 0) 
+                high)
+           (dpb val (byte lowbits offset) low)))))))
+
+
+(defun extract-default (operand instr)
+  (let* ((width (ccl::operand-width operand))
+           (op (ldb (byte width (ccl::operand-offset operand)) instr)))
+    (if (and (logbitp $ppc-operand-signed (ccl::operand-flags operand))
+                (logbitp (1- width) op))
+         (- op (ash 1 width))
+       op)))
+
+
+
+
+
+(defun ccl::lookup-ppc-opcode (name)
+  (gethash (string name) ppc::*ppc-opcode-numbers*))
+
+(provide "PPC-ASM")
Index: /branches/new-random/compiler/PPC/ppc-backend.lisp
===================================================================
--- /branches/new-random/compiler/PPC/ppc-backend.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/ppc-backend.lisp	(revision 13309)
@@ -0,0 +1,239 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(next-nx-defops)
+(defvar *ppc2-specials* nil)
+(let* ((newsize (%i+ (next-nx-num-ops) 10))
+       (old *ppc2-specials*)
+       (oldsize (length old)))
+  (declare (fixnum newsize oldsize))
+  (unless (>= oldsize newsize)
+    (let* ((v (make-array newsize :initial-element nil)))
+      (dotimes (i oldsize (setq *ppc2-specials* v))
+        (setf (svref v i) (svref old i))))))
+
+;;; This defines a template.  All expressions in the body must be
+;;; evaluable at macroexpansion time.
+(defun define-ppc-vinsn (backend vinsn-name results args temps body)
+  (let* ((opcode-vector (backend-lap-opcodes backend))
+	 (opcode-lookup (backend-lookup-opcode backend))
+	 (opcode-expander (backend-lookup-macro backend))
+	 (backend-name (backend-name backend))
+         (arch-name (backend-target-arch-name backend))
+	 (template-hash (backend-p2-template-hash-name backend))
+	 (name-list ())
+	 (attrs 0)
+         (nhybrids 0)
+         (local-labels ())
+         (referenced-labels ())
+	 (source-indicator (form-symbol arch-name "-VINSN"))
+         (opcode-alist ()))
+    (flet ((valid-spec-name (x)
+	     (or (and (consp x) 
+		      (consp (cdr x)) 
+		      (null (cddr x)) 
+		      (atom (car x))
+		      (or (assoc (cadr x) *vreg-specifier-constant-constraints* :test #'eq)
+			  (assoc (cadr x) *spec-class-storage-class-alist* :test #'eq)
+			  (eq (cadr x) :label)
+			  (and (consp (cadr x))
+			       (or 
+				(assoc (caadr x) *vreg-specifier-constant-constraints* :test #'eq)
+				(assoc (caadr x) *spec-class-storage-class-alist* :test #'eq))))
+		      (car x))
+		 (error "Invalid vreg spec: ~s" x)))
+           (add-spec-name (vname) 
+             (if (member vname name-list :test #'eq)
+               (error "Duplicate name ~s in vinsn ~s" vname vinsn-name)
+               (push vname name-list))))
+      (declare (dynamic-extent #'valid-spec-name #'add-spec-name))
+      (when (consp vinsn-name)
+        (setq attrs (encode-vinsn-attributes (cdr vinsn-name))
+              vinsn-name (car vinsn-name)))
+      (unless (and (symbolp vinsn-name) (eq *CCL-PACKAGE* (symbol-package vinsn-name)))
+        (setq vinsn-name (intern (string vinsn-name) *CCL-PACKAGE*)))
+      (dolist (n (append args temps))
+        (add-spec-name (valid-spec-name n)))
+      (dolist (form body)
+        (if (atom form)
+          (add-spec-name form)))
+      (setq name-list (nreverse name-list))
+      ;; We now know that "args" is an alist; we don't know if
+      ;; "results" is.  First, make sure that there are no duplicate
+      ;; result names (and validate "results".)
+      (do* ((res results tail)
+            (tail (cdr res) (cdr tail)))
+           ((null res))
+        (let* ((name (valid-spec-name (car res))))
+          (if (assoc name tail :test #'eq)
+            (error "Duplicate result name ~s in ~s." name results))))
+      (let* ((non-hybrid-results ()) 
+             (match-args args))
+        (dolist (res results)
+          (let* ((res-name (car res)))
+            (if (not (assoc res-name args :test #'eq))
+              (if (not (= nhybrids 0))
+                (error "result ~s should also name an argument. " res-name)
+                (push res-name non-hybrid-results))
+              (if (eq res-name (caar match-args))
+                (setf nhybrids (1+ nhybrids)
+                      match-args (cdr match-args))
+                (error "~S - hybrid results should appear in same order as arguments." res-name)))))
+        (dolist (name non-hybrid-results)
+          (add-spec-name name)))
+      (let* ((k -1))
+        (declare (fixnum k))
+        (let* ((name-alist (mapcar #'(lambda (n) (cons n (list (incf k)))) name-list)))
+          (flet ((find-name (n)
+                   (let* ((pair (assoc n name-alist :test #'eq)))
+                     (declare (list pair))
+                     (if pair
+                       (cdr pair)
+                       (or (subprim-name->offset n backend)
+                           (error "Unknown name ~s" n))))))
+            (labels ((simplify-operand (op)
+                       (if (atom op)
+                         (if (typep op 'fixnum)
+                           op
+                           (if (constantp op)
+                             (progn
+                               (if (keywordp op)
+                                 (pushnew op referenced-labels))
+                               (eval op))
+                             (find-name op)))
+                         (if (eq (car op) :apply)
+                           `(,(cadr op) ,@(mapcar #'simplify-operand (cddr op)))
+                           (simplify-operand (eval op)))))) ; Handler-case this?         
+              (labels ((simplify-constraint (guard)
+                         ;; A constraint is one of
+
+                         ;; (:eq|:lt|:gt vreg-name constant)
+
+                         ;; value" of vreg relop constant
+
+                         ;; (:pred <function-name> <operand>* ;
+                         ;; <function-name> unquoted, each <operand>
+                         ;; is a vreg-name or constant expression.
+
+                         ;; (:type vreg-name typeval) ; vreg is of
+                         ;; "type" typeval
+                         ;;
+                         ;;(:not <constraint>) ; constraint is false
+                         ;; (:and <constraint> ...)        ;  conjuntion
+                         ;; (:or <constraint> ...)         ;  disjunction
+                         ;; There's no "else"; we'll see how ugly it
+                         ;; is without one.
+                         (destructuring-bind (guardname &rest others) guard
+                           (ecase guardname
+                             (:not 
+                              (destructuring-bind (negation) others
+                                `(:not ,(simplify-constraint negation))))
+                             (:pred
+                              (destructuring-bind (predicate &rest operands) others
+                                `(:pred ,predicate ,@(mapcar #'simplify-operand operands))))
+                             ((:eq :lt :gt :type)
+                              (destructuring-bind (vreg constant) others
+                                (unless (constantp constant)
+                                  (error "~S : not constant in constraint ~s ." constant guard))
+                                `(,guardname ,(find-name vreg) ,(eval constant))))
+                             ((:or :and)
+                              (unless others (error "Missing constraint list in ~s ." guard))
+                              `(,guardname ,(mapcar #'simplify-constraint others))))))
+                       (simplify-form (form)
+                         (if (atom form)
+                           (progn 
+                             (if (keywordp form) (push form local-labels) )
+                             form)
+                           (destructuring-bind (&whole w opname &rest opvals) form
+                             (if (consp opname) ; A constraint, we presume ...
+                               (cons (simplify-constraint opname)
+                                     (mapcar #'simplify-form opvals))
+                               (if (keywordp opname)
+                                 form
+                                 (let* ((name (string opname))
+                                        (opnum (funcall opcode-lookup name)))
+                                   (if (and (not opnum) opcode-expander)
+                                     (let* ((expander (funcall opcode-expander name)))
+                                       (if expander
+                                         (simplify-form (funcall expander form nil))
+                                         (error "Unknown ~A instruction in ~s" backend-name form)))
+                                     (let* ((opcode (if (< -1 opnum (length opcode-vector))
+                                                      (svref opcode-vector opnum)
+                                                      (error "~& Invalid ~A opcode: ~s" backend-name name)))
+                                            (opvals (mapcar #'simplify-operand opvals)))
+                                       (setf (assq opnum opcode-alist) name)
+                                       (let* ((operands (opcode-vinsn-operands opcode))
+                                              (nmin (opcode-min-vinsn-args opcode))
+                                              (nmax (opcode-max-vinsn-args opcode))
+                                              (nhave (length opvals)))
+                                         (declare (fixnum nmin nmax nhave))
+                                         (if (= nhave nmax)
+                                           `(,opnum ,@opvals)
+                                           (if (> nhave nmax)
+                                             (error "Too many operands in ~s (~a accepts at most ~d)"
+                                                    (cdr w) name nmax)
+                                             (if (= nhave nmin)
+                                               (let* ((newops ()))
+                                                 (dolist (op operands `(,opnum ,@(nreverse newops)))
+                                                   (let* ((flags (operand-flags op)))
+                                                     (unless (logbitp operand-fake flags)
+                                                       (push (if (logbitp operand-optional flags)
+                                                               0
+                                                               (pop opvals))
+                                                             newops)))))
+                                               (error "Too few operands in ~s : (~a requires at least ~d)"
+                                                      (cdr w) name nmin))))))))))))))
+                (let* ((template (make-vinsn-template
+                                  :name vinsn-name
+                                  :result-vreg-specs results
+                                  :argument-vreg-specs args
+                                  :temp-vreg-specs temps
+                                  :nhybrids nhybrids
+                                  :results&args (append results (nthcdr nhybrids args))
+                                  :nvp (- (+ (length results) (length args) (length temps))
+                                          nhybrids)
+                                  :body (prog1 (mapcar #'simplify-form body)
+                                          (dolist (ref referenced-labels)
+                                            (unless (memq ref local-labels)
+                                              (error 
+                                               "local label ~S was referenced but never defined in VINSN-TEMPLATE definition for ~s" ref vinsn-name))))
+                                  :local-labels local-labels :attributes attrs :opcode-alist
+                                  opcode-alist)))
+                  `(progn (set-vinsn-template ',vinsn-name ,template
+                           ,template-hash) (record-source-file ',vinsn-name ',source-indicator)
+                    ',vinsn-name))))))))))
+
+#+ppc32-target
+(require "PPC32-BACKEND")
+#+ppc64-target
+(require "PPC64-BACKEND")
+
+(defparameter *ppc-backend*
+  #+ppc32-target *ppc32-backend*
+  #+ppc64-target *ppc64-backend*
+  #-(or ppc32-target ppc64-target)
+  nil)
+
+
+	      
+(defun fixup-ppc-backend (&rest args)
+  #+ppc32-target (apply #'fixup-ppc32-backend args)
+  #+ppc64-target (apply #'fixup-ppc64-backend args))
+
+  
Index: /branches/new-random/compiler/PPC/ppc-disassemble.lisp
===================================================================
--- /branches/new-random/compiler/PPC/ppc-disassemble.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/ppc-disassemble.lisp	(revision 13309)
@@ -0,0 +1,484 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "NXENV")
+  (require "DLL-NODE")
+  (require "PPC-ASM")
+  (require "PPC-LAP"))
+
+(defparameter *ppc-disassembly-backend* *host-backend*)
+(defparameter *ppc-disassemble-raw-instructions* nil)
+
+(eval-when (:compile-toplevel :execute)
+  (require "PPCENV"))
+
+(defun ppc-gpr (r)
+  (or
+   (case (backend-target-arch-name *ppc-disassembly-backend*)
+     (:ppc32 (and (eql r ppc32::rcontext) 'ppc32::rcontext))
+     (:ppc64 (and (eql r ppc64::rcontext) 'ppc64::rcontext)))
+   (svref ppc::*gpr-register-names* r)))
+
+(defun ppc-fpr (r)
+  (svref ppc::*fpr-register-names* r))
+
+(defun ppc-vr (r)
+    (svref ppc::*vector-register-names* r))
+
+;;; To "unmacroexpand" something is to undo the effects of
+;;; some sort of macroexpansion, returning some presumably
+;;; more meaningful equivalent form.  Some cases of this
+;;; are trivial (e.g., turning (stwu rX -4 vsp) into (vpush rX);
+;;; some would depend on surrounding context and are still
+;;; heuristic.  A few cases can probably benefit from state
+;;; maintained by preceding instructions, e.g., (twnei rX 1)
+;;; is presumably looking at the low 2 or three bits of rX; we
+;;; have to know what set rX to know which.
+
+;;; For now, just try to handle a few simple cases.
+;;; Return a new form (new-opcode-name &rest new-operands) or NIL.
+;;;
+
+(defparameter *ppc-unmacroexpanders* (make-hash-table :test #'equalp))
+
+(defun ppc-unmacroexpand-function (name)
+  (let* ((pname (string name))
+         (opnum (gethash pname ppc::*ppc-opcode-numbers*)))
+    (unless opnum (error "Unknown ppc opcode name ~s." name))
+    (values (gethash pname *ppc-unmacroexpanders*))))
+
+(defun (setf ppc-unmacroexpand-function) (def name)
+  (let* ((pname (string name))
+         (opnum (gethash pname ppc::*ppc-opcode-numbers*)))
+    (unless opnum (error "Unknown ppc opcode name ~s." name))
+    (setf (gethash pname *ppc-unmacroexpanders*) def)))
+
+(defmacro def-ppc-unmacroexpand (name insn-var lambda-list &body body)
+  `(setf (ppc-unmacroexpand-function ',name)
+         #'(lambda (,insn-var)
+             (destructuring-bind ,lambda-list (lap-instruction-parsed-operands ,insn-var)
+               ,@body))))
+
+(def-ppc-unmacroexpand stwu insn (rs d ra)
+  (case (backend-target-arch-name *ppc-disassembly-backend*)
+    (:ppc32
+     (if (and (= ra ppc::vsp) (= d -4))
+       `(vpush ,(ppc-gpr rs))))))
+
+(def-ppc-unmacroexpand stdu insn (rs d ra)
+  (case (backend-target-arch-name *ppc-disassembly-backend*)
+    (:ppc64
+     (if (and (= ra ppc::vsp) (= d -8))
+       `(vpush ,(ppc-gpr rs))))))
+
+(def-ppc-unmacroexpand rlwinm insn (rt ra b mb &optional (me mb me-p))
+  (if (not me-p)
+    (setq mb 0))                        ; That's what's happening now to fake operands.
+  (if (and (= me 31) (= (+ b mb) 32))
+    `(srwi ,(ppc-gpr rt) ,(ppc-gpr ra) ,mb)
+    (if (and (= mb 0) (= (+ b me) 31))
+      (if (and (case (backend-target-arch-name *ppc-disassembly-backend*)
+                 (:ppc32 t))
+             (logbitp rt ppc-node-regs)
+             (not (logbitp ra ppc-node-regs))
+             (= b (arch::target-fixnum-shift (backend-target-arch
+                                               *ppc-disassembly-backend*))))
+        `(box-fixnum ,(ppc-gpr rt) ,(ppc-gpr ra))
+        `(slwi ,(ppc-gpr rt) ,(ppc-gpr ra) ,b)))))
+
+(def-ppc-unmacroexpand rldicr insn (rt ra sh me)
+  (if (= (+ sh me) 63)
+    (if (and (case (backend-target-arch-name *ppc-disassembly-backend*)
+               (:ppc64 t))
+             (logbitp rt ppc-node-regs)
+             (not (logbitp ra ppc-node-regs))
+             (= sh (arch::target-fixnum-shift (backend-target-arch
+                                               *ppc-disassembly-backend*))))
+      `(box-fixnum ,(ppc-gpr rt) ,(ppc-gpr ra))
+      `(sldi ,(ppc-gpr rt) ,(ppc-gpr ra) ,sh))))
+
+(def-ppc-unmacroexpand rldicl insn (rt ra sh mb)
+  (if (= (+ sh mb) 64)
+    `(srdi ,(ppc-gpr rt) ,(ppc-gpr ra) ,mb)))
+
+(def-ppc-unmacroexpand srawi insn (rt ra sh)
+  (if (and (case (backend-target-arch-name *ppc-disassembly-backend*)
+             (:ppc32 t))
+           (not (logbitp rt ppc-node-regs))
+           (logbitp ra ppc-node-regs)
+           (= sh (arch::target-fixnum-shift (backend-target-arch
+                                             *ppc-disassembly-backend*))))
+    `(unbox-fixnum ,(ppc-gpr rt) ,(ppc-gpr ra))))
+
+(def-ppc-unmacroexpand sradi insn (rt ra sh)
+  (if (and (case (backend-target-arch-name *ppc-disassembly-backend*)
+             (:ppc64 t))
+           (not (logbitp rt ppc-node-regs))
+           (logbitp ra ppc-node-regs)
+           (= sh (arch::target-fixnum-shift (backend-target-arch
+                                             *ppc-disassembly-backend*))))
+    `(unbox-fixnum ,(ppc-gpr rt) ,(ppc-gpr ra))))
+
+(def-ppc-unmacroexpand li insn (rt imm)
+  (let* ((fixnumshift (arch::target-fixnum-shift (backend-target-arch *ppc-disassembly-backend*))))
+    (if (not (logtest (1- (ash 1 fixnumshift)) imm))
+      (if (logbitp rt ppc-node-regs)
+        `(li ,(ppc-gpr rt) ',(ash imm (- fixnumshift)))
+        (if (eql rt ppc::nargs)
+          `(set-nargs ,(ash imm (- fixnumshift))))))))
+
+
+
+(def-ppc-unmacroexpand cmpwi insn (crf ra simm)
+  (let* ((fixnumshift (arch::target-fixnum-shift (backend-target-arch *ppc-disassembly-backend*))))
+    (if (and (not (logtest (1- (ash 1 fixnumshift)) simm))
+             (logbitp ra ppc-node-regs))
+      `(cmpwi ,@(unless (eql 0 crf) `(,(aref *ppc-cr-names* (ash crf -2))))
+	,(ppc-gpr ra)
+	',(ash simm (- fixnumshift))))))
+
+(def-ppc-unmacroexpand cmpdi insn (crf ra simm)
+  (let* ((fixnumshift (arch::target-fixnum-shift (backend-target-arch *ppc-disassembly-backend*))))
+    (if (and (not (logtest (1- (ash 1 fixnumshift)) simm))
+             (logbitp ra ppc-node-regs))
+      `(cmpdi ,@(unless (eql 0 crf) `(,(aref *ppc-cr-names* (ash crf -2))))
+	,(ppc-gpr ra)
+	',(ash simm (- fixnumshift))))))
+
+(def-ppc-unmacroexpand addi insn (rd ra simm)
+  (let* ((fixnumshift (arch::target-fixnum-shift (backend-target-arch *ppc-disassembly-backend*)))
+         (disp-d (ppc-gpr rd))
+	 (disp-a (ppc-gpr ra)))
+    (if (or (eql ra ppc::sp)
+            (eql ra ppc::tsp)
+	    (eql ra ppc::vsp))
+	`(la ,disp-d ,simm ,disp-a)
+	(let* ((opcode 'addi)
+	       (val (abs simm)))
+	  (if (< simm 0)
+	      (setq opcode 'subi))
+	  (if (and (not (logtest (1- (ash 1 fixnumshift)) simm))
+		   (logbitp rd ppc-node-regs)
+		   (logbitp ra ppc-node-regs))
+	    `(,opcode ,disp-d ,disp-a ',(ash val (- fixnumshift)))
+	    `(,opcode ,disp-d ,disp-a ,(if (eq val
+                                               (arch::target-nil-value (backend-target-arch *ppc-disassembly-backend*))) nil val)))))))
+
+(defun ppc-unmacroexpand (insn)
+  (unless *ppc-disassemble-raw-instructions*
+    (let* ((expander (ppc-unmacroexpand-function (opcode-name (lap-instruction-opcode insn))))
+           (expansion (if expander (funcall expander insn))))
+      (when expansion
+        (setf (lap-instruction-opcode insn) (car expansion)
+              (lap-instruction-parsed-operands insn) (cdr expansion))
+        expansion))))
+
+
+(defun find-ppc-opcode (i)
+  (let* ((op (ldb (byte 6 26) i))
+         (k (svref ppc::*ppc-opcode-indices* op)))
+    (declare (type (unsigned-byte 12) k)
+             (type (unsigned-byte 6) op))
+    (unless (= k -1)
+      (dotimes (j (svref ppc::*ppc-opcode-counts* op))
+        (declare (type (unsigned-byte 10) j))
+        (let* ((code (svref ppc::*ppc-opcodes* (+ k j))))
+          (if (= (logand (opcode-mask code) i)
+                 (opcode-opcode code))
+            (if (dolist (op (opcode-operands code) t)
+                  (let* ((xfun (operand-extract-function op)))
+                    (unless (or (null xfun)
+                                (funcall xfun i))
+                      (return nil))))
+              (return code))))))))
+
+(defun ppc-disasm-1 (i pc header)
+  (let* ((opcode (find-ppc-opcode i)))
+    (if (null opcode)
+      (error "Unknown PPC instruction : #x~8,'0x" i)    ; should handle somehow
+      (let* ((vals ()))
+        (dolist (operand (opcode-operands opcode))
+          (unless (logbitp operand-fake (operand-flags operand))
+            (let* ((extract-fn (operand-extract-function operand)))
+              (push (if extract-fn
+                      (funcall extract-fn i)
+                      (ppc::extract-default operand i))
+                    vals))))
+        (let* ((insn (%make-lap-instruction opcode)))
+          (setf (lap-instruction-parsed-operands insn)
+                (nreverse vals))
+          (setf (lap-instruction-address insn)
+                pc)
+          (append-dll-node insn header))))))
+                
+
+(defvar *disassembled-ppc-instructions* ())
+(defvar *disassembled-ppc-labels* ())
+
+
+
+(defun ppc-label-at-address (address)
+  (dolist (l *disassembled-ppc-labels* 
+             (let* ((label (%make-lap-label (intern (format nil "L~d" address)))))
+               (setf (lap-label-address label) address)
+               (push label *disassembled-ppc-labels*)
+               label))
+    (when (= address (lap-label-address l))
+      (return l))))
+
+(defun insert-ppc-label (l instructions)
+  (let* ((labaddr (lap-label-address l)))
+   (do-dll-nodes (insn instructions (append-dll-node l instructions))
+     (when (>= (lap-instruction-address insn) labaddr)
+       (return (insert-dll-node-after l (lap-instruction-pred insn)))))))
+
+(defun ppc-disassemble-cr (val operand-spec)
+  (declare (type (mod 32) val))
+  (let* ((width (operand-width operand-spec))
+         (crnum (ash val -2))
+         (ccnum (logand val 3)))
+    (declare (fixnum width crnum ccnum))
+    (if (= width 3)
+      (unless (= crnum 0) (aref *ppc-cr-names* crnum))
+      (if (= ccnum 0)
+        (unless (= crnum 0) (aref *ppc-cr-names* crnum))
+        (list (aref *ppc-cr-field-names* crnum) (aref *ppc-cc-bit-names* ccnum))))))
+
+(defun ppc-analyze-operands (instructions constants)
+  (let* ((pc 0)
+         (regsave-pseudo nil)
+         (arch (backend-target-arch *ppc-disassembly-backend*))
+         (nil-value (arch::target-nil-value arch))
+         (misc-data-offset (arch::target-misc-data-offset arch))
+         (word-shift (arch::target-word-shift arch))
+         (align-mask (1- (ash 1 word-shift))))
+    (declare (fixnum pc))
+    (let* ((last (dll-header-last instructions)))
+      (when (eq (lap-instruction-opcode last) *ppc-lwz-instruction*)
+        (remove-dll-node last)
+        (setq regsave-pseudo last)))
+    (do-dll-nodes (insn instructions)
+      (unless (ppc-unmacroexpand insn)
+        (let* ((opcode (lap-instruction-opcode insn))
+               (opvalues (lap-instruction-parsed-operands insn)))
+          (do* ((operands (opcode-operands opcode) (cdr operands))
+                (operand (car operands) (car operands))
+                (header (cons nil opvalues))
+                (tail header))
+               ((null operands) (setf (lap-instruction-parsed-operands insn) (cdr header)))
+            (declare (dynamic-extent header))
+            (let* ((flags (operand-flags operand))
+		   (opidx (operand-index operand))
+                   (val (cadr tail)))
+              (declare (fixnum flags))
+              (if (and (logbitp operand-optional flags)
+                       (eql 0 val))
+                (rplacd tail (cddr tail))
+                (progn
+		  (if (and (or (eq opidx ppc::$si)
+			       (eq opidx ppc::$nsi)
+			       (eq opidx ppc::$ui))
+			   (eql val nil-value))
+		    (setf (cadr tail) nil)
+		    (if (logbitp ppc::$ppc-operand-relative flags)
+		      (let* ((label (ppc-label-at-address (+ pc val))))
+			(setf (cadr tail) (lap-label-name label)))
+		      (if (logbitp ppc::$ppc-operand-cr flags)
+			(let* ((cr (ppc-disassemble-cr val operand)))
+			  (when cr (setf (cadr tail) cr)))
+			(if (logbitp ppc::$ppc-operand-absolute flags)
+			  (let* ((info (find val ppc::*ppc-subprims* :key #'subprimitive-info-offset)))
+			    (when info (setf (cadr tail) (subprimitive-info-name info))))
+			  (if (logbitp ppc::$ppc-operand-fpr flags)
+			    (setf (cadr tail) (ppc-fpr val))
+			    (if (logbitp ppc::$ppc-operand-vr flags) ; SVS
+			      (setf (cadr tail) (ppc-vr val))
+			      (when (logbitp ppc::$ppc-operand-gpr flags)
+				(setf (cadr tail) (ppc-gpr val))
+				(when (eq val ppc::fn)
+				  (let* ((disp (car tail)))
+				    (when (and disp (typep disp 'fixnum))
+				      (let* ((unscaled (+ (- misc-data-offset) disp)))
+					(unless (logtest align-mask unscaled)
+					  (let* ((idx (ash unscaled (- word-shift))))
+					    (if (< idx (uvsize constants))
+					      (rplaca tail (list 'quote (uvref constants idx)))))))))))))))))
+		  (setq tail (cdr tail))))))))
+      (incf pc 4))
+    (dolist (l *disassembled-ppc-labels*) (insert-ppc-label l instructions))
+    (when regsave-pseudo
+      (destructuring-bind (reg offset pc) (lap-instruction-parsed-operands regsave-pseudo)
+        (declare (fixnum reg offset pc))
+        (let* ((nregs (- 32 reg)))
+          (declare (fixnum nregs))
+          (setq pc (ash (the fixnum (dpb (ldb (byte 2 0) offset) (byte 2 5) pc)) 2)
+                offset (- (logand (lognot 3) (- offset)) (ash nregs target::word-shift))))
+        (setf (lap-instruction-opcode regsave-pseudo) :regsave
+              (lap-instruction-parsed-operands regsave-pseudo)
+              (list (ppc-gpr reg) offset)
+              (lap-instruction-address regsave-pseudo) pc)
+        (do-dll-nodes (node instructions)
+          (when (>= (lap-instruction-address node) pc)
+            (insert-dll-node-after regsave-pseudo (dll-node-pred node))
+            (return)))))))
+              
+      
+; This returns a doubly-linked list of INSTRUCTION-ELEMENTs; the caller (disassemble, INSPECT)
+; can format the contents however it wants.
+(defun disassemble-ppc-function (code-vector constants-vector &optional (start-word 0))
+  (let* ((*disassembled-ppc-labels* nil)
+         (header (make-dll-header)))
+    (let* ((n (uvsize code-vector)))
+      (declare (fixnum n))
+      (do* ((i start-word (1+ i))
+            (pc 0 (+ pc 4)))
+           ((= i n))
+        (declare (fixnum i))
+        (let* ((opcode (uvref code-vector i)))
+          (declare (integer opcode))
+          (if (= opcode 0)
+            (return)
+            (ppc-disasm-1 opcode pc header))))
+      (ppc-analyze-operands header constants-vector))
+    header))
+
+(defun print-ppc-instruction (stream tabcount opcode parsed-operands)
+  (let* ((name (if (symbolp opcode) opcode (opcode-name opcode))))
+    (if (keywordp name)
+      (format stream "~&~V,t(~s" tabcount name)
+      (format stream "~&~V,t(~a" tabcount name))
+    (dolist (op parsed-operands (format stream ")"))
+      (format stream (if (and (consp op) (eq (car op) 'quote)) " ~s" " ~a") op))))
+
+(defun print-ppc-instructions (stream function instructions &optional for-lap backend)
+  (declare (ignorable backend))
+  (let* ((tab (if for-lap 6 2))
+         (previous-source-note nil))
+
+    (let ((source-note (function-source-note function)))
+      (when source-note
+        (format t ";; Source: ~S:~D-~D"
+                (source-note-filename source-note)
+                (source-note-start-pos source-note)
+                (source-note-end-pos source-note))
+        ;; Fetch text from file if don't already have it
+        (ensure-source-note-text source-note)))
+
+    (when for-lap 
+      (let* ((lap-function-name (car for-lap)))
+        (format stream "~&(~S ~S ~&  (~S (~s) ~&    (~s ~s ()" 
+                'nfunction lap-function-name 'lambda '&lap 'ppc-lap-function lap-function-name)))
+
+    (do-dll-nodes (i instructions)
+      (let ((source-note (find-source-note-at-pc function (instruction-element-address i))))
+        (unless (eql (source-note-file-range source-note)
+                     (source-note-file-range previous-source-note))
+          (setf previous-source-note source-note)
+          (let* ((source-text (source-note-text source-note))
+                 (text (if source-text
+                         (string-sans-most-whitespace source-text 100)
+                         "#<no source text>")))
+            (format stream "~&~%;;; ~A" text))))
+      (etypecase i
+        (lap-label (format stream "~&~a " (lap-label-name i)))
+        (lap-instruction 
+         (print-ppc-instruction stream tab (lap-instruction-opcode i) (lap-instruction-parsed-operands i)))))
+    (when for-lap (format stream ")))~&"))))
+
+
+(defun ppc-Xdisassemble (fn-vector &key (for-lap nil) (stream *standard-output*) target ((:raw *ppc-disassemble-raw-instructions*) nil))
+  (let* ((backend (if target (find-backend target) *host-backend*))
+         (prefix-length (length (arch::target-code-vector-prefix (backend-target-arch backend))))
+         (*ppc-disassembly-backend* backend))
+    (print-ppc-instructions stream fn-vector
+                            (function-to-dll-header fn-vector prefix-length)
+                            (if for-lap (list (uvref fn-vector (- (uvsize fn-vector) 2)))))
+    (values)))
+
+(defun function-to-dll-header (fn-vector &optional (prefix #+ppc32-target 0 #+ppc64-target 1))
+  (let* ((codev (uvref fn-vector 0)))
+    (disassemble-ppc-function codev fn-vector prefix)))
+
+
+(defun disassemble-list (thing)
+  (let ((dll (function-to-dll-header (function-for-disassembly thing)))
+        (address 0)
+        (label-p nil)
+        (res nil))
+    (do-dll-nodes (i dll)
+      (setq address (instruction-element-address i))
+      (etypecase i
+        (lap-label
+         (setq label-p (lap-label-name i)))
+        (lap-instruction
+         (let ((opcode (lap-instruction-opcode i))
+               (operands (lap-instruction-parsed-operands i)))
+           (push (list* (if label-p `(label ,address) address)
+                        (if (symbolp opcode) opcode (opcode-name opcode))
+                        operands)
+                 res)
+           (setq label-p nil)))))
+    (nreverse res)))
+
+(defun disassemble-lines (thing)
+  (let ((dll (function-to-dll-header (function-for-disassembly thing)))
+        (address 0)
+        (label-p nil)
+        (lines (make-array 20 :adjustable t :fill-pointer 0)))
+    (do-dll-nodes (i dll)
+      (setq address (instruction-element-address i))
+      (etypecase i
+        (lap-label
+         (setq label-p (lap-label-name i)))
+        (lap-instruction
+         (let* ((opcode (lap-instruction-opcode i))
+		(operands (lap-instruction-parsed-operands i))
+		(imms (loop for op in operands
+			 when (and (consp op)
+				   (consp (cdr op))
+				   (null (cddr op))
+				   (or (eq (%car op) 'quote) (eq (%car op) 'function)))
+			 collect op)))
+	   (vector-push-extend (list (if (cdr imms) (coerce imms 'vector) (car imms))
+				     (if label-p `(:label address) address)
+				     (with-output-to-string (s)
+				       (format s "(~a" (if (symbolp opcode) opcode (opcode-name opcode)))
+				       (loop for op in operands
+					  do (princ " " s)
+					  do (disasm-prin1 op s))
+				       (format s ")")))
+			       lines)
+           (setq label-p nil)))))
+    lines))
+
+#+ppc-target
+(defun disasm-prin1 (thing stream)
+  (if (and (consp thing) (consp (cdr thing)) (null (cddr thing)))
+    (cond ((eq (%car thing) 'quote)
+           (prin1 thing stream))
+          ((eq (%car thing) 'function)
+           (format stream "#'~S" (cadr thing)))
+          ((eq (%car thing) 16)
+             (format stream "#x~X" (cadr thing)))
+          ((eq (%car thing) 'label)
+           (let ((*print-radix* nil))
+             (princ (cadr thing) stream)))
+          (t (princ thing stream)))
+    (princ thing stream)))
+
+
Index: /branches/new-random/compiler/PPC/ppc-lap.lisp
===================================================================
--- /branches/new-random/compiler/PPC/ppc-lap.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/ppc-lap.lisp	(revision 13309)
@@ -0,0 +1,681 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "PPC32-ARCH")
+  (require "PPC64-ARCH")
+  (require "RISC-LAP")
+  (require "DLL-NODE")
+  (require "PPC-ASM")
+  (require "SUBPRIMS"))
+
+
+(defun ppc-lap-macro-function (name)
+  (gethash (string name) (backend-lap-macros *ppc-backend*)))
+
+(defun (setf ppc-lap-macro-function) (def name)
+  (let* ((s (string name)))
+    (when (gethash s ppc::*ppc-opcode-numbers*)
+      (error "~s already defines a PowerPC instruction . " name))
+    (when (ppc::ppc-macro-function s)
+      (error "~s already defines a PowerPC macro instruction . " name))
+    (setf (gethash s (backend-lap-macros *ppc-backend*)) def)))
+
+(defmacro defppclapmacro (name arglist &body body)
+  `(progn
+     (setf (ppc-lap-macro-function ',name)
+           (nfunction (ppc-lap-macro ,name) ,(parse-macro name arglist body)))
+     (record-source-file ',name 'ppc-lap)
+     ',name))
+
+(defvar *ppc-lap-constants* ())
+(defvar *ppc-lap-regsave-reg* ())
+(defvar *ppc-lap-regsave-addr* ())
+(defvar *ppc-lap-regsave-label* ())
+(defparameter *ppc-lwz-instruction* (svref ppc::*ppc-opcodes* (gethash "LWZ" ppc::*ppc-opcode-numbers*)))
+(defvar *ppc-lap-lfun-bits* 0)
+
+
+
+
+
+(defun ppc-lap-macroexpand-1 (form)
+  (unless (and (consp form) (atom (car form)))
+    (values form nil))
+  (let* ((expander (ppc-lap-macro-function (car form))))
+    (if expander
+      (values (funcall expander form nil) t)
+      (values form nil))))
+
+
+
+(defun ppc-lap-encode-regsave-info (maxpc)
+  (declare (fixnum maxpc))
+  (if *ppc-lap-regsave-label*
+    (let* ((regsave-pc (ash (the fixnum (lap-label-address *ppc-lap-regsave-label*)) -2)))
+      (declare (fixnum regsave-pc))
+      (if (< regsave-pc #x80)
+        (let* ((instr (ppc-emit-lap-instruction *ppc-lwz-instruction*
+                                                (list *ppc-lap-regsave-reg*
+                                                      (dpb (ldb (byte 2 5) regsave-pc) 
+                                                           (byte 2 0) 
+                                                           *ppc-lap-regsave-addr*)
+                                                      (ldb (byte 5 0) regsave-pc)))))
+          (setf (lap-instruction-address instr) maxpc)
+          (incf maxpc 4))
+        (warn "Can't encode register save information."))))
+  maxpc)
+
+(defun %define-ppc-lap-function (name body &optional (bits 0))
+  (with-dll-node-freelist (*lap-instructions* *lap-instruction-freelist*)
+      (let* ((*lap-labels* ())
+             (*ppc-lap-regsave-label* ())
+             (*ppc-lap-regsave-reg* ())
+             (*ppc-lap-regsave-addr* ())
+             (*ppc-lap-constants* ())
+             (*ppc-lap-lfun-bits* bits))
+        (dolist (form body)
+          (ppc-lap-form form))
+        #+ppc-lap-scheduler (ppc-schedule-instuctions)       ; before resolving branch targets
+        (ppc-lap-generate-code name (ppc-lap-encode-regsave-info (ppc-lap-do-labels)) *ppc-lap-lfun-bits*))))
+
+;;; Any conditional branch that the compiler generates is currently just of the form
+;;; BT or BF, but it'd be nice to recognize all of the other extended branch mnemonics
+;;; as well.
+;;; A conditional branch is "conditional" if bit 2 of the BO field is set.
+(defun ppc-lap-conditional-branch-p (insn)
+  (let* ((opcode (lap-instruction-opcode insn)))
+    (if (= (the fixnum (opcode-majorop opcode)) 16)    ; it's a BC instruction ...
+      (unless (logbitp 1 (the fixnum (opcode-op-low opcode)))          ; not absolute
+        (let* ((bo-field (if (= #xf (ldb (byte 4 6) (the fixnum (opcode-mask-high opcode))))
+                           (ldb (byte 5 5) (the fixnum (opcode-op-high opcode)))
+                           (svref (lap-instruction-parsed-operands insn) 0))))
+          (declare (fixnum bo-field))
+          (if (logbitp 2 bo-field)
+            bo-field))))))
+
+;;; Turn an instruction that's of the form 
+;;;   (bc[l] bo bi label) 
+;;; into the sequence
+;;;   (bc (invert bo) bi @new)
+;;;   (b[l] label)
+;;; @new
+;;; Do so only if the instruction's a conditional branch
+;;; and the label is more than 16 bits away from the instruction.
+;;; Return true if we do this, false otherwise.
+(defun ppc-lap-invert-conditional-branch (insn label)
+  (if (ppc-lap-conditional-branch-p insn)      
+    (let* ((diff (- (lap-label-address label) (lap-instruction-address insn))))
+      (declare (fixnum diff))
+      (if (or (< diff #x-8000) (> diff #x7ffc))
+        ; Too far away, will have to invert.
+        ; It's necessary to "partially assemble" the BC instruction in order to 
+        ; get explicit values for the BO and BI fields of the instruction.
+        (let* ((original-opcode (lap-instruction-opcode insn))
+               (vals (lap-instruction-parsed-operands insn))
+               (high (opcode-op-high original-opcode))
+               (low (opcode-op-low original-opcode))
+               (link-p (logbitp 0 low))
+               (new-label (make-lap-label (gensym)))
+               (idx -1))
+          (declare (fixnum high low))
+          ; Assemble all operands but the last
+          (do* ((ops (opcode-operands original-opcode) next)
+                (next (cdr ops) (cdr next)))
+               ((null next))
+            (declare (list ops next))
+            (let* ((operand (car ops))
+                   (val (if (logbitp operand-fake (operand-flags operand))
+                    0
+                    (svref vals (incf idx))))
+                   (insert-function (operand-insert-function operand)))
+              (setq high (if insert-function
+                           (funcall insert-function high low val)
+                           (ppc::insert-default operand high low val)))))
+          ;; "high" now contains the major opcode, BO, and BI fields
+          ;; of the original branch instruction.  Generate a (BC
+          ;; (invert BO) BI new-label) instruction, and insert it
+          ;; before the original instruction.
+          (let* ((bc-opcode (svref ppc::*ppc-opcodes* (gethash "BC" ppc::*ppc-opcode-numbers*)))
+                 (bo (logxor #b1000 (the fixnum (ldb (byte 5 5) high))))
+                 (bi (ldb (byte 5 0) high))
+                 (new-instruction (make-lap-instruction bc-opcode))
+                 (opvect (alloc-lap-operand-vector)))
+            (setf (lap-instruction-parsed-operands new-instruction) opvect
+                  (svref opvect 0) bo
+                  (svref opvect 1) bi
+                  (svref opvect 2) new-label)
+            (push new-instruction (lap-label-refs new-label))
+            (insert-dll-node-after new-instruction (dll-node-pred insn))
+            (insert-dll-node-after new-label insn))
+          ;; Now, change INSN's opcode to B or BL, and make sure that
+          ;; it references nothing but the old label.
+          (let* ((long-branch (svref ppc::*ppc-opcodes* (gethash (if link-p "BL" "B") ppc::*ppc-opcode-numbers*)))
+                 (opvect (alloc-lap-operand-vector)))
+            (setf (svref opvect 0) label
+                  (lap-instruction-opcode insn) long-branch
+                  (lap-instruction-parsed-operands insn) opvect)
+            ;; We're finally done.  Return t.
+            t))))))
+            
+
+; Build & return list of all labels that are targets of conditional branches.
+(defun ppc-lap-conditional-branch-targets ()
+  (let* ((branch-target-labels ()))
+    (do-lap-labels (lab branch-target-labels)
+      (dolist (insn (lap-label-refs lab))
+        (when (ppc-lap-conditional-branch-p insn)
+          (push lab branch-target-labels))))))
+
+(defun ppc-lap-assign-addresses (delete-labels-p)
+  (let* ((pc 0))
+    (declare (fixnum pc))
+    (do-dll-nodes (node *lap-instructions*)
+      (setf (instruction-element-address node) pc)
+      (if (typep node 'lap-label)
+        (if delete-labels-p (remove-dll-node node))
+        (incf pc 4)))
+    ;; Don't bother checking code-vector size yet.
+    pc))
+
+;;; The function's big enough that we might have generated conditional
+;;; branches that are too far away from their targets.  Find the set
+;;; of all labels that are the target of conditional branches, then
+;;; repeatedly assign (tentative) addresses to all instructions and
+;;; labels and iterate over the set of conditional branch targets,
+;;; "lengthening" any condtional branches that are too far away from
+;;; the target label.  Since lengthening a branch instruction can
+;;; cause a spanning branch to become a candidate for lengthening, we
+;;; have to repeat the process until all labels are the targets of
+;;; valid (short enough or unconditional) branch instructions.
+(defun ppc-lap-remove-long-branches ()
+  (let* ((branch-target-labels (ppc-lap-conditional-branch-targets)))
+    (do* ((done nil))
+         (done (ppc-lap-assign-addresses t))
+      (setq done t)
+      (ppc-lap-assign-addresses nil)
+      (dolist (lab branch-target-labels)
+        (dolist (insn (lap-label-refs lab))
+          (when (ppc-lap-invert-conditional-branch insn lab)
+            (setq done nil)))))))
+
+(defun ppc-lap-do-labels ()
+  (do-lap-labels (lab)
+    (if (and (lap-label-refs lab) (not (lap-label-emitted-p lab)))
+      (error "Label ~S was referenced but never defined. " 
+             (lap-label-name lab)))
+    ;; Repeatedly iterate through label's refs, until none of them is
+    ;; the preceding instruction.  This eliminates
+    ;; (b @next)
+    ;;@next
+    ;;
+    ;; but can probably be fooled by hairier nonsense.
+    (loop
+      (when (dolist (ref (lap-label-refs lab) t)
+              (when (eq lab (lap-instruction-succ ref))
+                (remove-dll-node ref)
+                (setf (lap-label-refs lab) (delete ref (lap-label-refs lab)))
+                (return)))
+        (return))))
+  ;; Assign pc to emitted labels, splice them out of the list.
+  
+  (if (> (the fixnum (dll-header-length *lap-instructions*)) 8191)
+    ;; -Might- have some conditional branches that are too long.
+    ;; Definitely don't  otherwise, so only bother to check in this case
+    (ppc-lap-remove-long-branches)
+    (ppc-lap-assign-addresses t)))
+
+;;; Replace each label with the difference between the label's address
+;;; and the referencing instruction's address.
+(defun ppc-lap-resolve-labels ()
+  (do-lap-labels (label)
+    (let* ((label-address (lap-label-address label)))
+      (declare (fixnum label-address))          ; had BETTER be ...
+      (dolist (insn (lap-label-refs label))
+        (let* ((diff (- label-address (lap-instruction-address insn))))
+          (declare (fixnum diff))
+          (let* ((opvals (lap-instruction-parsed-operands insn))
+                 (pos (position label opvals)))
+            (unless pos
+              (error "Bug: label ~s should be referenced by instruction ~s, but isn't." label insn))
+            (setf (svref opvals pos) diff)))))))
+
+(defun ppc-lap-generate-instruction (code-vector index insn)
+  (let* ((op (lap-instruction-opcode insn))
+         (vals (lap-instruction-parsed-operands insn))
+         (high (opcode-op-high op))
+         (low (opcode-op-low op))
+         (idx -1))
+    (dolist (operand (opcode-operands op))
+      (let* ((val (if (logbitp operand-fake (operand-flags operand))
+                    0
+                    (svref vals (incf idx))))
+             (insert-function (operand-insert-function operand)))
+        (multiple-value-setq (high low)
+          (if insert-function
+            (funcall insert-function high low val)
+            (ppc::insert-default operand high low val)))
+        (if (null high)
+          (error "Invalid operand for ~s instruction: ~d" (opcode-name op) val))))
+    (setf (lap-instruction-parsed-operands insn) nil)
+    (free-lap-operand-vector vals)
+    (locally (declare (type (simple-array (unsigned-byte 16) (*)) code-vector)
+                      (optimize (speed 3) (safety 0)))
+      (setf (aref code-vector (+ index index)) high
+            (aref code-vector (+ index index 1)) low)
+     nil)))
+
+(defparameter *use-traceback-tables* nil)
+
+(defun traceback-fullwords (pname)
+  (if (and *use-traceback-tables* pname (typep pname 'simple-base-string))
+    (ceiling (+ 22 (length pname)) 4)
+    0))
+
+(defun add-traceback-table (code-vector start pname)
+  (flet ((out-byte (v i8 b)
+            (declare (type (simple-array (unsigned-byte 8) (*)) v)
+                    (optimize (speed 3) (safety 0))
+                    (fixnum i8))
+            (setf (aref v i8) b)))          
+    (flet ((out-bytes (v i32 b0 b1 b2 b3)
+           (declare (type (simple-array (unsigned-byte 8) (*)) v)
+                    (optimize (speed 3) (safety 0))
+                    (fixnum i32))
+           (let* ((i8 (ash i32 2)))
+             (declare (fixnum i8))
+             (setf (aref v i8) b0
+                   (aref v (%i+ i8 1)) b1
+                   (aref v (%i+ i8 2)) b2
+                   (aref v (%i+ i8 3)) b3))))
+      (setf (uvref code-vector start) 0)
+      (out-bytes code-vector (1+ start)
+                 0                          ; traceback table version
+                 0                          ; language id 7 - try 0 instead (means C) or 9 means C++
+                 #x20                       ; ???
+                 #x41)                      ; ???
+      (out-bytes code-vector (+ start 2)
+                 #x80 #x06 #x01 #x00)       ; ??? ??? ??? ???
+      (setf (uvref code-vector (+ start 3)) #x0)
+      (setf (uvref code-vector (+ start 4)) (ash start 2))
+      (let* ((namelen (length pname))
+             (pos (ash (the fixnum (+ start 5)) 2)))
+        (declare (fixnum namelen pos))
+        (out-byte code-vector pos (ldb (byte 8 8) namelen))
+        (incf pos)
+        (out-byte code-vector pos (ldb (byte 8 0) namelen))
+        (incf pos)
+        (dotimes (i namelen) 
+          (out-byte code-vector pos (char-code (schar pname i)))
+          (incf pos))))))
+
+(defun ppc-lap-generate-code (name maxpc bits &optional (traceback nil))
+  (declare (fixnum maxpc))
+  (let* ((target-backend *target-backend*)
+         (cross-compiling (not (eq *host-backend* target-backend)))
+	 (traceback-size
+	  (traceback-fullwords (and traceback
+				    name
+				    (setq traceback (symbol-name name)))))
+         (prefix (arch::target-code-vector-prefix (backend-target-arch *target-backend*)))
+         (prefix-size (length prefix))
+         (code-vector-size (+ (ash maxpc -2) traceback-size prefix-size))
+
+         (constants-size (+ 3 (length *ppc-lap-constants*)))
+         (constants-vector (%alloc-misc
+                            constants-size
+			    (if cross-compiling
+			      target::subtag-xfunction
+			      target::subtag-function)))
+         (i prefix-size))
+    (declare (fixnum i constants-size))
+    #+ppc32-target
+    (if (>= code-vector-size (ash 1 19)) (compiler-function-overflow))
+    (let* ((code-vector (%alloc-misc
+                         code-vector-size
+                         (if cross-compiling
+                           target::subtag-xcode-vector
+                           target::subtag-code-vector))))
+      (dotimes (j prefix-size)
+        (setf (uvref code-vector j) (pop prefix)))
+      (ppc-lap-resolve-labels)          ; all operands fully evaluated now.
+      (do-dll-nodes (insn *lap-instructions*)
+        (ppc-lap-generate-instruction code-vector i insn)
+        (incf i))
+      (unless (eql 0 traceback-size)
+        (add-traceback-table code-vector i traceback))
+      (dolist (immpair *ppc-lap-constants*)
+        (let* ((imm (car immpair))
+               (k (cdr immpair)))
+          (declare (fixnum k))
+          (setf (uvref constants-vector
+                       (ash
+                        (- k (arch::target-misc-data-offset (backend-target-arch target-backend)))
+                        (- (arch::target-word-shift (backend-target-arch target-backend)))))
+                imm)))
+      (setf (uvref constants-vector (1- constants-size)) bits ; lfun-bits
+            (uvref constants-vector (- constants-size 2)) name
+            (uvref constants-vector 0) code-vector)
+      #+ppc-target (%make-code-executable code-vector)
+      constants-vector)))
+
+(defun ppc-lap-pseudo-op (form)
+  (case (car form)
+    (:regsave
+     (if *ppc-lap-regsave-label*
+       (warn "Duplicate :regsave form not handled (yet ?) : ~s" form)
+       (destructuring-bind (reg addr) (cdr form)
+         (let* ((regno (ppc-register-name-or-expression reg)))
+           (if (not (<= ppc::save7 regno ppc::save0))
+             (warn "Not a save register: ~s.  ~s ignored." reg form)
+             (let* ((addrexp (ppc-register-name-or-expression addr)))   ; parses 'fixnum
+               (if (not (and (typep addrexp 'fixnum)
+                             (<= 0 addrexp #x7ffc)      ; not really right
+                             (not (logtest 3 addrexp))))
+                 (warn "Invalid logical VSP: ~s.  ~s ignored." addr form)
+                 (setq *ppc-lap-regsave-label* (emit-lap-label (gensym))
+                       *ppc-lap-regsave-reg* regno
+                       *ppc-lap-regsave-addr* (- (+ addrexp)
+                                                 (* 4 (1+ (- ppc::save0 regno))))))))))))
+    (:arglist (setq *ppc-lap-lfun-bits* (encode-lambda-list (cadr form))))))
+
+       
+(defun ppc-lap-form (form)
+  (if (and form (symbolp form))
+    (emit-lap-label form)
+    (if (or (atom form) (not (symbolp (car form))))
+      (error "~& unknown PPC-LAP form: ~S ." form)
+      (multiple-value-bind (expansion expanded)
+                           (ppc-lap-macroexpand-1 form)
+        (if expanded
+          (ppc-lap-form expansion)
+          (let* ((name (car form)))
+            (if (keywordp name)
+              (ppc-lap-pseudo-op form)
+              (case name
+                ((progn) (dolist (f (cdr form)) (ppc-lap-form f)))
+                ((let) (ppc-lap-equate-form (cadr form) (cddr form)))
+                (t
+                 ; instruction macros expand into instruction forms
+                 ; (with some operands reordered/defaulted.)
+                 (let* ((expander (ppc::ppc-macro-function name)))
+                   (if expander
+                     (ppc-lap-form (funcall expander form nil))
+                     (ppc-lap-instruction name (cdr form)))))))))))))
+
+;;; (let ((name val) ...) &body body)
+;;; each "val" gets a chance to be treated as a PPC register name
+;;; before being evaluated.
+(defun ppc-lap-equate-form (eqlist body) 
+  (let* ((symbols (mapcar #'(lambda (x)
+                              (let* ((name (car x)))
+                                (or
+                                 (and name 
+                                      (symbolp name)
+                                      (not (constant-symbol-p name))
+                                      name)
+                                 (error 
+                                  "~S is not a bindable symbol name ." name))))
+                          eqlist))
+         (values (mapcar #'(lambda (x) (or (ppc-vr-name-p (cadr x))
+					   (ppc-fpr-name-p (cadr x))
+					   (ppc-register-name-or-expression
+					    (cadr x))))
+                         eqlist)))
+    (progv symbols values
+                   (dolist (form body)
+                     (ppc-lap-form form)))))
+
+(defun ppc-lap-constant-offset (x)
+  (or (cdr (assoc x *ppc-lap-constants* :test #'equal))
+      (let* ((target-backend *target-backend*)
+             (n (+ (arch::target-misc-data-offset (backend-target-arch target-backend))
+                   (ash (1+ (length *ppc-lap-constants*))
+                        (arch::target-word-shift (backend-target-arch target-backend))))))
+        (push (cons x n) *ppc-lap-constants*)
+        n)))
+
+; Evaluate an arbitrary expression; warn if the result isn't a fixnum.
+(defun ppc-lap-evaluated-expression (x)
+  (if (typep x 'fixnum)
+    x
+    (if (null x)
+      (arch::target-nil-value (backend-target-arch *target-backend*))
+      (if (eq x t)
+        (+ (arch::target-nil-value (backend-target-arch *target-backend*))
+           (arch::target-t-offset  (backend-target-arch *target-backend*)))
+        (let* ((val (handler-case (eval x) ; Look! Expression evaluation!
+                      (error (condition) (error "~&Evaluation of ~S signalled assembly-time error ~& ~A ."
+                                                x condition)))))
+          (unless (typep val 'fixnum)
+            (warn "assembly-time evaluation of ~S returned ~S, which may not have been intended ."
+                  x val))
+          val)))))
+
+(defparameter *ppc-lap-register-aliases*
+  `((nfn . ,ppc::nfn)
+    (fname . ,ppc::fname)))
+
+(defparameter *ppc-lap-fp-register-aliases*
+  ())
+
+(defparameter *ppc-lap-vector-register-aliases*
+  ())
+
+(defun ppc-gpr-name-p (x)
+  (and (or (symbolp x) (stringp x))
+           (or
+            (position (string x) ppc::*gpr-register-names* :test #'string-equal)
+            (cdr (assoc x *ppc-lap-register-aliases* :test #'string-equal)))))
+
+(defun ppc-register-name-or-expression (x)
+  (if x
+    (or (ppc-gpr-name-p x)
+        (if (and (consp x) (eq (car x) 'quote))
+          (let* ((quoted-form (cadr x)))
+            (if (null quoted-form)
+              (arch::target-nil-value (backend-target-arch *target-backend*))
+              (if (eq quoted-form t)
+                (+ (arch::target-nil-value (backend-target-arch *target-backend*))
+                   (arch::target-t-offset (backend-target-arch *target-backend*)))
+                (if (typep quoted-form 'fixnum)
+                  (ash quoted-form (arch::target-fixnum-shift (backend-target-arch *target-backend*)))
+                  (ppc-lap-constant-offset quoted-form)))))
+          (ppc-lap-evaluated-expression x)))
+    (arch::target-nil-value (backend-target-arch *target-backend*))))
+
+(defun ppc-fpr-name-p (x)
+  (and (or (symbolp x) (stringp x))
+                   (or
+                    (position (string x) ppc::*fpr-register-names* :test #'string-equal)
+                    (cdr (assoc x *ppc-lap-fp-register-aliases* :test #'string-equal)))))
+
+(defun ppc-fp-register-name-or-expression (x)
+  (or (ppc-fpr-name-p x)
+      (ppc-lap-evaluated-expression x)))
+
+(defun ppc-vr-name-p (x)
+  (and (or (symbolp x) (stringp x))
+	     (or
+	      (position (string x) ppc::*vector-register-names* :test #'string-equal)
+	      (cdr (assoc x *ppc-lap-vector-register-aliases* :test #'string-equal)))))
+
+(defun ppc-vector-register-name-or-expression (x)
+  (or (ppc-vr-name-p x)
+      (ppc-lap-evaluated-expression x)))
+
+
+(defparameter *ppc-cr-field-names* #(:crf0 :crf1 :crf2 :crf3 :crf4 :crf5 :crf6 :crf7))
+(defparameter *ppc-cr-names* #(:cr0 :cr1 :cr2 :cr3 :cr4 :cr5 :cr6 :cr7))
+(defparameter *ppc-cc-bit-names* #(:lt :gt :eq :so :un))
+(defparameter *ppc-cc-bit-inverse-names* #(:ge :le :ne :ns :nu))
+
+; This wants a :CC, a negated :CC, or either (:CRn :CC) or (:CRn :~CC).
+; Returns the fully-qualified CR bit and an indication of whether or not the CC was 
+; negated.
+(defun ppc-lap-parse-test (x)
+  (if (or (symbolp x) (stringp x))
+    (let* ((pos (position x *ppc-cc-bit-names* :test #'string-equal)))
+      (if pos
+        (values (min pos 3) nil)
+        (if (setq pos (position x *ppc-cc-bit-inverse-names* :test #'string-equal))
+          (values (min pos 3) t)
+          (error "Unknown PPC lap condition form : ~s" x))))
+    (if (and (consp x) (keywordp (car x)) (consp (cdr x)) (keywordp (cadr x)))
+      (let* ((field (position (car x) *ppc-cr-names*)))
+        (unless field (error "Unknown CR field name : ~s" (car x)))
+        (let* ((bit (position (cadr x) *ppc-cc-bit-names*)))
+          (if bit 
+            (values (logior (ash field 2) (min bit 3)) nil)
+            (if (setq bit (position (cadr x) *ppc-cc-bit-inverse-names*))
+              (values (logior (ash field 2) (min bit 3)) t)
+              (error "Unknown condition name : ~s" (cadr x))))))
+      (error "Unknown PPC lap condition form : ~s" x))))
+
+; Accept either :CRn, :CC,  or (:CRFn :CC), or evaluate an expression.
+(defun ppc-lap-cr-field-expression (x)
+  (if (or (symbolp x) (stringp x))
+    (let* ((pos (position x *ppc-cr-names* :test #'string-equal)))
+      (if pos 
+        (ash pos 2)
+        (let* ((cc-pos (position x *ppc-cc-bit-names* :test #'string-equal)))
+          (if cc-pos 
+            (min cc-pos 3)
+            (ppc-lap-evaluated-expression x)))))
+    (if (and (consp x) (keywordp (car x)) (consp (cdr x)) (keywordp (cadr x)))
+      (let* ((field (position (car x) *ppc-cr-field-names*))
+             (bit (position (cadr x) *ppc-cc-bit-names*)))
+        (if (and field bit)
+          (logior (min bit 3) (ash field 2))
+          (error "Bad ppc-cr-field-expression: ~s" x)))
+      (ppc-lap-evaluated-expression x))))
+  
+(defun ppc-lap-instruction (name opvals)
+  (let* ((opnum (gethash (string name) ppc::*ppc-opcode-numbers*))
+         (opcode (and opnum 
+                          (< -1 opnum (length ppc::*ppc-opcodes*))
+                          (svref ppc::*ppc-opcodes* opnum))))
+    (unless opcode
+          (error "Unknown PPC opcode: ~a" name))
+    ;; Unless either
+    ;;  a) The number of operand values in the macro call exactly
+    ;;      matches the number of operands accepted by the instruction or
+    ;;  b) The number of operand values is one less, and the instuction
+    ;;     takes an optional operand
+    ;;  we've got a wrong-number-of-args error.
+    ;;  In case (b), there's at most one optional argument per instruction;
+    ;;   provide 0 for the missing value.
+    (let* ((operands (opcode-operands opcode))
+           (nmin (opcode-min-args opcode))
+           (nmax (opcode-max-args opcode))
+           (nhave (length opvals)))
+      (declare (fixnum nmin nmax nhave))
+      (if (= nhave nmax)
+        (ppc-emit-lap-instruction opcode opvals)
+        (if (> nhave nmax)
+          (error "Too many operands in ~s (~a accepts at most ~d)"
+                 opvals name nmax)
+          (if (= nhave nmin)
+            (let* ((newops ()))
+              (dolist (op operands (ppc-emit-lap-instruction opcode (nreverse newops)))
+                (let* ((flags (operand-flags op)))
+                  (unless (logbitp operand-fake flags)
+                    (push (if (logbitp operand-optional flags)
+                            0
+                            (pop opvals))
+                          newops)))))
+            (error "Too few operands in ~s : (~a requires at least ~d)"
+                   opvals name nmin)))))))
+
+; This is pretty rudimentary: if the operand has the "ppc::$ppc-operand-relative" bit
+; set, we demand a label name and note the fact that we reference the label in question.
+; Otherwise, we use the "register-name-or-expression" thing.
+; Like most PPC assemblers, this lets you treat everything as an expression, even if
+; you've got the order of some arguments wrong ...
+
+(defun ppc-parse-lap-operand (opvalx operand insn)
+  (let* ((flags (operand-flags operand)))
+    (declare (fixnum flags))
+    (if (logbitp ppc::$ppc-operand-relative flags)
+      (lap-note-label-reference opvalx insn)
+      (if (logbitp ppc::$ppc-operand-cr flags)
+        (ppc-lap-cr-field-expression opvalx)
+        (if (logbitp ppc::$ppc-operand-absolute flags)
+          (ppc-subprimitive-address opvalx)
+          (if (logbitp ppc::$ppc-operand-fpr flags)
+            (ppc-fp-register-name-or-expression opvalx)
+	    (if (logbitp ppc::$ppc-operand-vr flags) ; SVS
+	      (ppc-vector-register-name-or-expression opvalx)
+	      (ppc-register-name-or-expression opvalx))))))))
+
+(defun ppc-subprimitive-address (x)
+  (if (and x (or (symbolp x) (stringp x)))
+    (let* ((info (find x ppc::*ppc-subprims* :test #'string-equal :key #'subprimitive-info-name)))
+      (when info (return-from ppc-subprimitive-address
+                   (subprimitive-info-offset info)))))
+  (ppc-lap-evaluated-expression x))
+
+
+;;; We've checked that the number of operand values match the number
+;;; expected (and have set "fake" operand values to 0.)  Labels - and
+;;; some constructs that might someday do arithmetic on them - are
+;;; about the only class of forward references we need to deal with.
+;;; This whole two-pass scheme seems overly general, but if/when we
+;;; ever do instruction scheduling it'll probably make it simpler.
+(defun ppc-emit-lap-instruction (opcode opvals)
+  (let* ((operands (opcode-operands opcode))
+         (parsed-values (alloc-lap-operand-vector))
+         (insn (make-lap-instruction opcode))
+         (idx -1))
+    (declare (fixnum idx))
+    (dolist (op operands)
+      (let* ((flags (operand-flags op))
+             (val (if (logbitp operand-fake flags)
+                    0
+                    (ppc-parse-lap-operand (pop opvals) op insn))))
+        (declare (fixnum flags))
+        (setf (svref parsed-values (incf idx)) val)))
+    (setf (lap-instruction-parsed-operands insn) parsed-values)
+    (append-dll-node insn *lap-instructions*)))
+
+
+
+(defmacro defppclapfunction (&environment env name arglist &body body
+                             &aux doc)
+  (if (not (endp body))
+      (and (stringp (car body))
+           (cdr body)
+           (setq doc (car body))
+           (setq body (cdr body))))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (note-function-info ',name t ,env))
+     #-ppc-target
+     (progn
+       (eval-when (:load-toplevel)
+         (%defun (nfunction ,name (lambda (&lap 0) (ppc-lap-function ,name ,arglist ,@body))) ,doc))
+       (eval-when (:execute)
+         (%define-ppc-lap-function ',name '((let ,arglist ,@body)))))
+     #+ppc-target	; just shorthand for defun
+     (%defun (nfunction ,name (lambda (&lap 0) (ppc-lap-function ,name ,arglist ,@body))) ,doc)))
+ 
+
+
+(provide "PPC-LAP")
Index: /branches/new-random/compiler/PPC/ppc-lapmacros.lisp
===================================================================
--- /branches/new-random/compiler/PPC/ppc-lapmacros.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/ppc-lapmacros.lisp	(revision 13309)
@@ -0,0 +1,1079 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "PPC-LAP"))
+  
+
+(defppclapmacro clrrri (&rest args)
+  (target-arch-case
+   (:ppc32 `(clrrwi ,@args))
+   (:ppc64 `(clrrdi ,@args))))
+
+(defppclapmacro clrlri (&rest args)
+  (target-arch-case
+   (:ppc32 `(clrlwi ,@args))
+   (:ppc64 `(clrldi ,@args))))
+
+(defppclapmacro clrlri. (&rest args)
+  (target-arch-case
+   (:ppc32 `(clrlwi. ,@args))
+   (:ppc64 `(clrldi. ,@args))))
+
+(defppclapmacro ldr (&rest args)
+  (target-arch-case
+   (:ppc32 `(lwz ,@args))
+   (:ppc64 `(ld ,@args))))
+
+(defppclapmacro ldrx (&rest args)
+  (target-arch-case
+   (:ppc32 `(lwzx ,@args))
+   (:ppc64 `(ldx ,@args))))
+
+(defppclapmacro ldru (&rest args)
+  (target-arch-case
+   (:ppc32 `(lwzu ,@args))
+   (:ppc64 `(ldu ,@args))))
+
+(defppclapmacro str (&rest args)
+  (target-arch-case
+   (:ppc32 `(stw ,@args))
+   (:ppc64 `(std ,@args))))
+
+(defppclapmacro strx (&rest args)
+  (target-arch-case
+   (:ppc32 `(stwx ,@args))
+   (:ppc64 `(stdx ,@args))))
+
+(defppclapmacro stru (&rest args)
+  (target-arch-case
+   (:ppc32 `(stwu ,@args))
+   (:ppc64 `(stdu ,@args))))
+
+(defppclapmacro strux (&rest args)
+  (target-arch-case
+   (:ppc32 `(stwux ,@args))
+   (:ppc64 `(stdux ,@args))))
+
+(defppclapmacro lrarx (&rest args)
+  (target-arch-case
+   (:ppc32 `(lwarx ,@args))
+   (:ppc64 `(ldarx ,@args))))
+
+(defppclapmacro strcx. (&rest args)
+  (target-arch-case
+   (:ppc32 `(stwcx. ,@args))
+   (:ppc64 `(stdcx. ,@args))))
+  
+(defppclapmacro cmpr (&rest args)
+  (target-arch-case
+   (:ppc32 `(cmpw ,@args))
+   (:ppc64 `(cmpd ,@args))))
+
+(defppclapmacro cmpri (&rest args)
+  (target-arch-case
+   (:ppc32 `(cmpwi ,@args))
+   (:ppc64 `(cmpdi ,@args))))
+
+(defppclapmacro cmplr (&rest args)
+  (target-arch-case
+   (:ppc32 `(cmplw ,@args))
+   (:ppc64 `(cmpld ,@args))))
+
+(defppclapmacro cmplri (&rest args)
+  (target-arch-case
+   (:ppc32 `(cmplwi ,@args))
+   (:ppc64 `(cmpldi ,@args))))
+
+(defppclapmacro trlge (&rest args)
+  (target-arch-case
+   (:ppc32 `(twlge ,@args))
+   (:ppc64 `(tdlge ,@args))))
+
+(defppclapmacro trlgei (&rest args)
+  (target-arch-case
+   (:ppc32 `(twlgei ,@args))
+   (:ppc64 `(tdlgei ,@args))))
+
+(defppclapmacro trllt (&rest args)
+  (target-arch-case
+   (:ppc32 `(twllt ,@args))
+   (:ppc64 `(tdllt ,@args))))
+
+(defppclapmacro trllti (&rest args)
+  (target-arch-case
+   (:ppc32 `(twllti ,@args))
+   (:ppc64 `(tdllti ,@args))))
+
+(defppclapmacro trlgti (&rest args)
+  (target-arch-case
+   (:ppc32 `(twlgti ,@args))
+   (:ppc64 `(tdlgti ,@args))))
+
+(defppclapmacro trlti (&rest args)
+  (target-arch-case
+   (:ppc32 `(twlti ,@args))
+   (:ppc64 `(tdlti ,@args))))
+
+(defppclapmacro trlle (&rest args)
+  (target-arch-case
+   (:ppc32 `(twlle ,@args))
+   (:ppc64 `(tdlle ,@args))))
+
+(defppclapmacro treqi (&rest args)
+  (target-arch-case
+   (:ppc32 `(tweqi ,@args))
+   (:ppc64 `(tdeqi ,@args))))
+
+(defppclapmacro trnei (&rest args)
+  (target-arch-case
+   (:ppc32 `(twnei ,@args))
+   (:ppc64 `(tdnei ,@args))))
+
+(defppclapmacro trgti (&rest args)
+  (target-arch-case
+   (:ppc32 `(twgti ,@args))
+   (:ppc64 `(tdgti ,@args))))
+
+
+(defppclapmacro srari (&rest args)
+  (target-arch-case
+   (:ppc32 `(srawi ,@args))
+   (:ppc64 `(sradi ,@args))))
+
+(defppclapmacro srar (&rest args)
+  (target-arch-case
+   (:ppc32 `(sraw ,@args))
+   (:ppc64 `(srad ,@args))))
+
+(defppclapmacro slr (&rest args)
+  (target-arch-case
+   (:ppc32 `(slw ,@args))
+   (:ppc64 `(sld ,@args))))
+
+(defppclapmacro srri (&rest args)
+  (target-arch-case
+   (:ppc32 `(srwi ,@args))
+   (:ppc64 `(srdi ,@args))))
+
+(defppclapmacro slri (&rest args)
+  (target-arch-case
+   (:ppc32 `(slwi ,@args))
+   (:ppc64 `(sldi ,@args))))
+
+(defppclapmacro slri. (&rest args)
+  (target-arch-case
+   (:ppc32 `(slwi. ,@args))
+   (:ppc64 `(sldi. ,@args))))
+
+(defppclapmacro srr (&rest args)
+  (target-arch-case
+   (:ppc32 `(srw ,@args))
+   (:ppc64 `(srd ,@args))))
+
+(defppclapmacro bkpt ()
+  `(tweq rzero rzero))
+
+(defppclapmacro dbg (&optional save-lr?)
+  (if save-lr?
+    `(progn
+       (mflr loc-pc)
+       (str imm0 -40 sp) ; better than clobbering imm0
+       (bla .SPbreakpoint)
+       (ldr imm0 -40 sp)
+       (mtlr loc-pc))
+    `(bla .SPbreakpoint)))
+
+(defppclapmacro lwi (dest n)
+  (setq n (logand n #xffffffff))
+  (let* ((mask #xffff8000)
+         (masked (logand n mask))
+         (high (ash n -16))
+         (low (logand #xffff n)))
+    (if (or (= 0 masked) (= mask masked))
+      `(li ,dest ,low)
+      (if (= low 0)
+        `(lis ,dest ,high)
+        `(progn
+           (lis ,dest ,high)
+           (ori ,dest ,dest ,low))))))
+
+(defppclapmacro set-nargs (n)
+  (check-type n (unsigned-byte 13))
+  `(li nargs ',n))
+
+(defppclapmacro check-nargs (min &optional (max min))
+  (if (eq max min)
+    `(trnei nargs ',min)
+    (if (null max)
+      (unless (= min 0)
+        `(trllti nargs ',min))
+      (if (= min 0)
+        `(trlgti nargs ',max)
+        `(progn
+           (trllti nargs ',min)
+           (trlgti nargs ',max))))))
+
+;; Event-polling involves checking to see if the value of the current
+;; thread's interrupt-level is > 0.  For now, use nargs; this may
+;; change to "any register BUT nargs".  (Note that most number-of-args
+;; traps use unsigned comparisons.)
+(defppclapmacro event-poll ()
+  (target-arch-case
+   (:ppc32
+    '(progn
+      (lwz nargs ppc32::tcr.tlb-pointer ppc32::rcontext)
+      (lwz nargs ppc32::interrupt-level-binding-index nargs)
+      (twgti nargs 0)))
+   (:ppc64
+    '(progn     
+      (ld nargs ppc64::tcr.tlb-pointer ppc64::rcontext)
+      (ld nargs ppc64::interrupt-level-binding-index nargs)
+      (tdgti nargs 0)))))
+    
+
+;;; There's no "else"; learn to say "(progn ...)".
+;;; Note also that the condition is a CR bit specification (or a "negated" one).
+;;; Whatever affected that bit (hopefully) happened earlier in the pipeline.
+(defppclapmacro if (test then &optional (else nil else-p))
+  (multiple-value-bind (bitform negated) (ppc-lap-parse-test test)
+    (let* ((false-label (gensym)))
+      (if (not else-p)
+      `(progn
+         (,(if negated 'bt 'bf) ,bitform ,false-label)
+         ,then
+         ,false-label)
+      (let* ((cont-label (gensym)))
+        `(progn
+          (,(if negated 'bt 'bf) ,bitform ,false-label)
+          ,then
+          (b ,cont-label)
+          ,false-label
+          ,else
+          ,cont-label))))))
+
+(defppclapmacro save-pc ()
+  `(mflr loc-pc))
+
+;;; This needs to be done if we aren't a leaf function (e.g., if we
+;;; clobber our return address or need to reference any constants.  Note
+;;; that it's not atomic wrt a preemptive scheduler, but we need to
+;;; pretend that it will be.)  The VSP to be saved is the value of the
+;;; VSP before any of this function's arguments were vpushed by its
+;;; caller; that's not the same as the VSP register if any non-register
+;;; arguments were received, but is usually easy to compute.
+
+(defppclapmacro save-lisp-context (&optional (vsp 'vsp) (save-pc t))
+  (target-arch-case
+   (:ppc32
+    `(progn
+      ,@(if save-pc 
+            '((save-pc)))
+      (stwu sp (- ppc32::lisp-frame.size) sp)
+      (stw fn ppc32::lisp-frame.savefn sp)
+      (stw loc-pc ppc32::lisp-frame.savelr sp)
+      (stw ,vsp ppc32::lisp-frame.savevsp sp)
+      (mr fn nfn)))
+   (:ppc64
+    `(progn
+      ,@(if save-pc 
+            '((save-pc)))
+      (stdu sp (- ppc64::lisp-frame.size) sp)
+      (std fn ppc64::lisp-frame.savefn sp)
+      (std loc-pc ppc64::lisp-frame.savelr sp)
+      (std ,vsp ppc64::lisp-frame.savevsp sp)
+      (mr fn nfn)))))
+
+;;; There are a few cases to deal with when restoring: whether or not
+;;; to restore the vsp, whether we need to saved LR back in the LR or
+;;; whether it only needs to get as far as loc-pc, etc.  This fully
+;;; restores everything (letting the caller specify some register
+;;; other than the VSP, if that's useful.)  Note that, since FN gets
+;;; restored, it's no longer possible to use it to address the current
+;;; function's constants.
+(defppclapmacro restore-full-lisp-context (&optional (vsp 'vsp))
+  (target-arch-case
+   (:ppc32
+    `(progn
+      (lwz loc-pc ppc32::lisp-frame.savelr sp)
+      (lwz ,vsp ppc32::lisp-frame.savevsp sp)
+      (mtlr loc-pc)
+      (lwz fn ppc32::lisp-frame.savefn sp)
+      (la sp ppc32::lisp-frame.size sp)))
+   (:ppc64
+    `(progn
+      (ld loc-pc ppc64::lisp-frame.savelr sp)
+      (ld ,vsp ppc64::lisp-frame.savevsp sp)
+      (mtlr loc-pc)
+      (ld fn ppc64::lisp-frame.savefn sp)
+      (la sp ppc64::lisp-frame.size sp)))))
+
+(defppclapmacro restore-pc ()
+  `(mtlr loc-pc))
+
+(defppclapmacro push (src stack)
+  `(stru ,src ,(- (arch::target-lisp-node-size (backend-target-arch *target-backend*))) ,stack))
+
+(defppclapmacro vpush (src)
+  `(push ,src vsp))
+
+;;; You typically don't want to do this to pop a single register (it's better to
+;;; do a sequence of loads, and then adjust the stack pointer.)
+
+(defppclapmacro pop (dest stack)
+  `(progn
+     (ldr ,dest 0 ,stack)
+     (la ,stack ,(arch::target-lisp-node-size (backend-target-arch *target-backend*)) ,stack)))
+
+(defppclapmacro vpop (dest)
+  `(pop ,dest vsp))
+
+(defppclapmacro %cdr (dest node)
+  (target-arch-case
+   (:ppc32 `(lwz ,dest ppc32::cons.cdr ,node))
+   (:ppc64 `(ld ,dest ppc64::cons.cdr ,node))))
+
+(defppclapmacro %car (dest node)
+  (target-arch-case
+   (:ppc32 `(lwz ,dest ppc32::cons.car ,node))
+   (:ppc64 `(ld ,dest ppc64::cons.car ,node))))
+
+(defppclapmacro extract-lisptag (dest node)
+  (let* ((tb *target-backend*))
+    `(clrlri ,dest ,node (- ,(arch::target-nbits-in-word (backend-target-arch tb))
+                          ,(arch::target-nlisptagbits (backend-target-arch tb))))))
+
+(defppclapmacro extract-fulltag (dest node)
+  (let* ((tb *target-backend*))
+  `(clrlri ,dest ,node (- ,(arch::target-nbits-in-word (backend-target-arch tb))
+                        ,(arch::target-ntagbits (backend-target-arch tb))))))
+
+(defppclapmacro extract-lowtag (dest node)
+  (target-arch-case
+   (:ppc32
+    (error "EXTRACT-LOWTAG lapmacro makes no sense on PPC32."))
+   (:ppc64
+    `(clrldi ,dest ,node (- 64 ppc64::nlowtagbits)))))
+
+
+(defppclapmacro extract-subtag (dest node)
+  (target-arch-case
+   (:ppc32
+    `(lbz ,dest ppc32::misc-subtag-offset ,node))
+   (:ppc64
+    `(lbz ,dest ppc64::misc-subtag-offset ,node))))
+
+(defppclapmacro extract-typecode (dest node &optional (crf :cr0))
+  (target-arch-case
+   (:ppc32
+    `(progn
+      (extract-lisptag ,dest ,node)
+      (cmpwi ,crf ,dest ppc32::tag-misc)
+      (if (,crf :eq)
+        (extract-subtag ,dest ,node))))
+   (:ppc64
+    `(progn
+      (extract-fulltag ,dest ,node)
+      (cmpdi ,crf ,dest ppc64::fulltag-misc)
+      (extract-lisptag ,dest ,dest)
+      (if (,crf :eq)
+        (extract-subtag ,dest ,node))))))
+
+(defppclapmacro trap-unless-lisptag= (node tag &optional (immreg ppc::imm0))
+  `(progn
+     (extract-lisptag ,immreg ,node)
+     (trnei ,immreg ,tag)))
+
+(defppclapmacro trap-unless-fulltag= (node tag &optional (immreg ppc::imm0))
+  `(progn
+     (extract-fulltag ,immreg ,node)
+     (trnei ,immreg ,tag)))
+
+
+(defppclapmacro trap-unless-typecode= (node tag &optional (immreg ppc::imm0) (crf :cr0))
+  `(progn
+     (extract-typecode ,immreg ,node ,crf)
+     (trnei ,immreg ,tag)))
+
+
+(defppclapmacro load-constant (dest constant)
+  `(ldr ,dest ',constant fn))
+
+;;; This is about as hard on the pipeline as anything I can think of.
+(defppclapmacro call-symbol (function-name)
+  (target-arch-case
+   (:ppc32
+    `(progn
+      (load-constant fname ,function-name)
+      (lwz nfn ppc32::symbol.fcell fname)
+      (lwz loc-pc ppc32::misc-data-offset nfn)
+      (mtctr loc-pc)
+      (bctrl)))
+   (:ppc64
+    `(progn
+      (load-constant fname ,function-name)
+      (ld nfn ppc64::symbol.fcell fname)
+      (ld loc-pc ppc64::misc-data-offset nfn)
+      (mtctr loc-pc)
+      (bctrl)))))
+
+(defppclapmacro sp-call-symbol (function-name)
+  `(progn
+     (load-constant fname ,function-name)
+     (bla .SPjmpsym)))
+
+(defppclapmacro getvheader (dest src)
+  (target-arch-case
+   (:ppc32
+    `(lwz ,dest ppc32::misc-header-offset ,src))
+   (:ppc64
+    `(ld ,dest ppc64::misc-header-offset ,src))))
+
+;;; "Size" is unboxed element-count.
+(defppclapmacro header-size (dest vheader)
+  (target-arch-case
+   (:ppc32
+    `(srwi ,dest ,vheader ppc32::num-subtag-bits))
+   (:ppc64
+    `(srdi ,dest ,vheader ppc64::num-subtag-bits))))
+
+
+;;; "Length" is fixnum element-count.
+(defppclapmacro header-length (dest vheader)
+  (target-arch-case
+   (:ppc32
+    `(rlwinm ,dest 
+      ,vheader 
+      (- ppc32::nbits-in-word (- ppc32::num-subtag-bits ppc32::nfixnumtagbits))
+      (- ppc32::num-subtag-bits ppc32::nfixnumtagbits)
+      (- ppc32::least-significant-bit ppc32::nfixnumtagbits)))
+   (:ppc64
+    `(progn
+      (rldicr ,dest
+       ,vheader
+       (- 64 (- ppc64::num-subtag-bits ppc64::fixnumshift))
+       (- 63 ppc64::fixnumshift))
+      (clrldi ,dest ,dest (- ppc64::num-subtag-bits ppc64::fixnumshift))))))
+  
+
+(defppclapmacro header-subtag[fixnum] (dest vheader)
+  (target-arch-case
+   (:ppc32
+    `(rlwinm ,dest
+           ,vheader
+           ppc32::fixnumshift
+           (- ppc32::nbits-in-word (+ ppc32::num-subtag-bits ppc32::nfixnumtagbits))
+           (- ppc32::least-significant-bit ppc32::nfixnumtagbits)))
+   (:ppc64
+    `(clrlsldi ,dest
+      ,vheader (- ppc64::nbits-in-word ppc64::num-subtag-bits)
+      ppc64::fixnumshift))))
+
+
+(defppclapmacro vector-size (dest v vheader)
+  `(progn
+     (getvheader ,vheader ,v)
+     (header-size ,dest ,vheader)))
+
+(defppclapmacro vector-length (dest v vheader)
+  `(progn
+     (getvheader ,vheader ,v)
+     (header-length ,dest ,vheader)))
+
+
+;;; Reference a 32-bit miscobj entry at a variable index.
+;;; Make the caller explicitly designate a scratch register
+;;; to use for the scaled index.
+
+(defppclapmacro vref32 (dest miscobj index scaled-idx)
+  `(progn
+     (la ,scaled-idx ppc32::misc-data-offset ,index)
+     (lwzx ,dest ,miscobj ,scaled-idx)))
+
+;; The simple (no-memoization) case.
+(defppclapmacro vset32 (src miscobj index scaled-idx)
+  `(progn
+     (la ,scaled-idx ppc32::misc-data-offset ,index)
+     (stwx ,src ,miscobj ,scaled-idx)))
+
+(defppclapmacro extract-lowbyte (dest src)
+  (target-arch-case
+   (:ppc32 `(clrlwi ,dest ,src (- 32 8)))
+   (:ppc64 `(clrldi ,dest ,src (- 64 8)))))
+
+(defppclapmacro unbox-fixnum (dest src)
+  (target-arch-case
+   (:ppc32
+    `(srawi ,dest ,src ppc32::fixnumshift))
+   (:ppc64
+    `(sradi ,dest ,src ppc64::fixnumshift))))
+
+(defppclapmacro box-fixnum (dest src)
+  (target-arch-case
+   (:ppc32
+    `(slwi ,dest ,src ppc32::fixnumshift))
+   (:ppc64
+    `(sldi ,dest ,src ppc64::fixnumshift))))
+
+
+
+;;; If crf is specified, type checks src
+(defppclapmacro unbox-base-char (dest src &optional crf)
+  (if (null crf)
+    (target-arch-case
+     (:ppc32 `(srwi ,dest ,src ppc32::charcode-shift))
+     (:ppc64 `(srdi ,dest ,src ppc64::charcode-shift)))
+    (let ((label (gensym)))
+      (target-arch-case
+       (:ppc32 `(progn
+                 (clrlwi ,dest ,src (- ppc32::nbits-in-word ppc32::charcode-shift))
+                 (cmpwi ,crf ,dest ppc32::subtag-character)
+                 (srwi ,dest ,src ppc32::charcode-shift)
+                 (beq+ ,crf ,label)
+                 (uuo_interr arch::error-object-not-base-char ,src)
+                 ,label))
+       (:ppc64
+        `(progn
+          (clrldi ,dest ,src (- ppc64::nbits-in-word ppc64::num-subtag-bits))
+          (cmpdi ,crf ,dest ppc64::subtag-character)
+          (srdi ,dest ,src ppc64::charcode-shift)
+          (beq+ ,crf ,label)
+          (uuo_interr arch::error-object-not-base-char ,src)
+          ,label))))))
+
+
+
+
+(defppclapmacro ref-global (reg sym)
+  (target-arch-case
+   (:ppc32
+    (let* ((offset (ppc32::%kernel-global sym)))
+      `(lwz ,reg (+ ,offset (target-nil-value)) 0)))
+   (:ppc64
+    (let* ((offset (ppc64::%kernel-global sym)))
+      `(ld ,reg (+ ,offset (target-nil-value)) 0)))))
+
+(defppclapmacro set-global (reg sym)
+  (target-arch-case
+   (:ppc32
+    (let* ((offset (ppc32::%kernel-global sym)))
+      `(stw ,reg (+ ,offset (target-nil-value)) 0)))
+   (:ppc64
+    (let* ((offset (ppc64::%kernel-global sym)))
+      `(std ,reg (+ ,offset (target-nil-value)) 0)))))
+
+;;; Set "dest" to those bits in "src" that are other than those that
+;;; would be set if "src" is a fixnum and of type (unsigned-byte
+;;; "width").  If no bits are set in "dest", then "src" is indeed of
+;;; type (unsigned-byte "width").  Set (:CR0 :EQ) according to the
+;;; result.
+(defppclapmacro extract-unsigned-byte-bits. (dest src width)
+  (target-arch-case
+   (:ppc32
+    `(rlwinm. ,dest ,src 0 (- 32 ppc32::fixnumshift) (- 31 (+ ,width ppc32::fixnumshift))))
+   (:ppc64
+    `(rldicr. ,dest ,src (- 64 ppc64::fixnumshift) (- 63 ,width)))))
+
+
+
+;;; You generally don't want to have to say "mfcr": it crosses functional
+;;; units and forces synchronization (all preceding insns must complete,
+;;; no subsequent insns may start.)
+;;; There are often algebraic ways of computing ppc32::t-offset:
+
+;;; Src has all but the least significant bit clear.  Map low bit to T/NIL.
+(defppclapmacro bit0->boolean (dest src temp)
+  (target-arch-case
+   (:ppc32
+    `(progn
+      (rlwimi ,temp ,src 4 27 27)
+      (addi ,dest ,temp (target-nil-value))))
+   (:ppc64
+    `(progn
+      (mulli ,temp ,src ppc64::t-offset) ; temp = ppc64::t-offset, or 0
+      (addi ,dest ,temp (target-nil-value)))))) ; dest = (src == 1), lisp-wise
+
+(defppclapmacro eq0->boolean (dest src temp)
+  (target-arch-case
+   (:ppc32
+    `(progn
+      (cntlzw ,temp ,src)                ; 32 leading zeros if (src == 0)
+      (srwi ,temp ,temp 5)               ; temp = (src == 0), C-wise
+      (bit0->boolean ,dest ,temp ,temp)))
+   (:ppc64
+    `(progn
+      (cntlzd ,temp ,src)               ; 64 leading zeros if (src == 0)
+      (srdi ,temp ,temp 6)              ; temp = (src == 0), C-wise
+      (bit0->boolean ,dest ,temp ,temp)))))
+
+(defppclapmacro ne0->boolean (dest src temp)
+  (target-arch-case
+   (:ppc32
+    `(progn
+      (cntlzw ,temp ,src)                
+      (slw ,temp ,src ,temp)
+      (srwi ,temp ,temp 31)
+      (bit0->boolean ,dest ,temp ,temp)))
+   (:ppc64
+    `(progn
+      (cntlzd ,temp ,src)
+      (sld ,temp ,src ,temp)
+      (srdi ,temp ,temp 63) 
+      (bit0->boolean ,dest ,temp ,temp)))))
+
+(defppclapmacro eq->boolean (dest rx ry temp)
+  `(progn
+     (sub ,temp ,rx ,ry)
+     (eq0->boolean ,dest ,temp ,temp)))
+
+
+(defppclapmacro repeat (n inst)
+  (let* ((insts ()))
+    (dotimes (i n `(progn ,@(nreverse insts)))
+      (push inst insts))))
+
+(defppclapmacro get-single-float (dest node)
+  (target-arch-case
+   (:ppc32
+    `(lfs ,dest ppc32::single-float.value ,node))
+   (:ppc64
+    `(progn
+      (std ,node ppc64::tcr.single-float-convert ppc64::rcontext)
+      (lfs ,dest ppc64::tcr.single-float-convert ppc64::rcontext)))))
+
+(defppclapmacro get-double-float (dest node)
+  (target-arch-case
+   (:ppc32
+    `(lfd ,dest ppc32::double-float.value ,node))
+   (:ppc64
+    `(lfd ,dest ppc64::double-float.value ,node))))
+  
+
+(defppclapmacro put-single-float (src node)
+  (target-arch-case
+   (:ppc32
+    `(stfs ,src ppc32::single-float.value ,node))
+   (:ppc64
+    `(progn
+      (stfs ,src ppc64::tcr.single-float-convert ppc64::rcontext)
+      (ld ,node ppc64::tcr.single-float-convert ppc64::rcontext)))))
+
+(defppclapmacro put-double-float (src node)
+  (target-arch-case
+   (:ppc32
+    `(stfd ,src ppc32::double-float.value ,node))
+   (:ppc64
+    `(stfd ,src ppc64::double-float.value ,node))))
+
+(defppclapmacro clear-fpu-exceptions ()
+  `(mtfsf #xfc #.ppc::fp-zero))
+
+
+
+;;; from ppc-bignum.lisp
+(defppclapmacro digit-h (dest src)
+  (target-arch-case
+   (:ppc32
+    `(rlwinm ,dest ,src (+ 16 ppc32::fixnumshift) (- 16 ppc32::fixnumshift) (- 31 ppc32::fixnumshift)))
+   (:ppc64
+    (error "DIGIT-H on PPC64 ?"))))
+
+;;; from ppc-bignum.lisp
+(defppclapmacro digit-l (dest src)
+  (target-arch-case
+   (:ppc32
+    `(clrlslwi ,dest ,src 16 ppc32::fixnumshift))
+   (:ppc64
+    (error "DIGIT-L on PPC64 ?"))))
+  
+;;; from ppc-bignum.lisp
+(defppclapmacro compose-digit (dest high low)
+  (target-arch-case
+   (:ppc32
+    `(progn
+      (rlwinm ,dest ,low (- ppc32::nbits-in-word ppc32::fixnumshift) 16 31)
+      (rlwimi ,dest ,high (- 16 ppc32::fixnumshift) 0 15)))
+   (:ppc64
+    (error "COMPOSE-DIGIT on PPC64 ?"))))
+
+(defppclapmacro macptr-ptr (dest macptr)
+  (target-arch-case
+   (:ppc32
+    `(lwz ,dest ppc32::macptr.address ,macptr))
+   (:ppc64
+    `(ld ,dest ppc64::macptr.address ,macptr))))
+
+(defppclapmacro svref (dest index vector)
+  (target-arch-case
+   (:ppc32
+    `(lwz ,dest (+ (* 4 ,index) ppc32::misc-data-offset) ,vector))
+   (:ppc64
+    `(ld ,dest (+ (* 8 ,index) ppc64::misc-data-offset) ,vector))))
+
+;;; This evals its args in the wrong order.
+;;; Can't imagine any code will care.
+(defppclapmacro svset (new-value index vector)
+  (target-arch-case
+   (:ppc32
+    `(stw ,new-value (+ (* 4 ,index) ppc32::misc-data-offset) ,vector))
+   (:ppc64
+    `(std ,new-value (+ (* 8 ,index) ppc64::misc-data-offset) ,vector))))
+
+(defppclapmacro vpush-argregs ()
+  (let* ((none (gensym))
+         (two (gensym))
+         (one (gensym)))
+  `(progn
+     (cmpri cr1 nargs '2)
+     (cmpri cr0 nargs 0)
+     (beq cr1 ,two)
+     (beq cr0 ,none)
+     (blt cr1 ,one)
+     (vpush arg_x)
+     ,two
+     (vpush arg_y)
+     ,one
+     (vpush arg_z)
+     ,none)))
+
+
+
+
+;;; Saving and restoring AltiVec registers.
+
+;;; Note that under the EABI (to which PPCLinux conforms), the OS
+;;; doesn't attach any special significance to the value of the VRSAVE
+;;; register (spr 256).  Under some other ABIs, VRSAVE is a bitmask
+;;; which indicates which vector registers are live at context switch
+;;; time.  These macros contain code to maintain VRSAVE when the
+;;; variable *ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P* is true at
+;;; macroexpand time; that variable is initialized to true if and only
+;;; if :EABI-TARGET is not on *FEATURES*.  Making this behavior
+;;; optional is supposed to help make code which uses these macros
+;;; easier to port to other platforms.
+
+;;; From what I can tell, a function that takes incoming arguments in
+;;; vector registers (vr2 ... vr13) (and doesn't use any other vector
+;;; registers) doesn't need to assert that it uses any vector
+;;; registers (even on platforms that maintain VRSAVE.)  A function
+;;; that uses vector registers that were not incoming arguments has to
+;;; assert that it uses those registers on platforms that maintain
+;;; VRSAVE.  On all platforms, a function that uses any non-volatile
+;;; vector registers (vr20 ... vr31) has to assert that it uses these
+;;; registers and save and restore the caller's value of these registers
+;;; around that usage.
+
+(defparameter *altivec-lapmacros-maintain-vrsave-p*
+  #-eabi-target t
+  #+eabi-target nil
+  "Control the expansion of certain lap macros. Initialized to NIL on
+LinuxPPC; initialized to T on platforms (such as MacOS X/Darwin) that
+require that the VRSAVE SPR contain a bitmask of active vector registers
+at all times.")
+
+(defun %vr-register-mask (reglist)
+  (let* ((mask 0))
+    (dolist (reg reglist mask)
+      (let* ((regval (ppc-vector-register-name-or-expression reg)))
+        (unless (typep regval '(mod 32))
+          (error "Bad AltiVec register - ~s" reg))
+        (setq mask (logior mask (ash #x80000000 (- regval))))))))
+
+
+
+;;; Build a frame on the temp stack large enough to hold N 128-bit vector
+;;; registers and the saved value of the VRSAVE spr.  That frame will look
+;;; like:
+;;; #x??????I0   backpointer to previous tstack frame
+;;; #x??????I4   non-zero marker: frame doesn't contain tagged lisp data
+;;; #x??????I8   saved VRSAVE
+;;; #x??????IC   pad word for alignment
+;;; #x??????J0   first saved vector register
+;;; #x??????K0   second saved vector register
+;;;   ...
+;;; #x??????X0   last saved vector register
+;;; #x??????Y0   (possibly) 8 bytes wasted for alignment.
+;;; #x????????   UNKNOWN; not necessarily the previous tstack frame
+;;;
+;;;  Use the specified immediate register to build the frame.
+;;;  Save the caller's VRSAVE in the frame.
+
+(defppclapmacro %build-vrsave-frame (n tempreg)
+  (if (or (> n 0) *altivec-lapmacros-maintain-vrsave-p*)
+    (if (zerop n)
+      ;; Just make room for vrsave; no need to align to 16-byte boundary.
+      `(progn
+	(stwu tsp -16 tsp)
+	(stw tsp 4 tsp))
+      `(progn
+	(la ,tempreg ,(- (ash (1+ n) 4)) ppc::tsp)
+	(clrrwi ,tempreg ,tempreg 4)	; align to 16-byte boundary
+	(sub ,tempreg ,tempreg ppc32::tsp) ; calculate (aligned) frame size.
+	(stwux ppc::tsp ppc::tsp ,tempreg)
+	(stw ppc::tsp 4 ppc::tsp)))	; non-zero: non-lisp
+    `(progn)))
+
+;;; Save the current value of the VRSAVE spr in the newly-created
+;;; tstack frame.
+
+(defppclapmacro %save-vrsave (tempreg)
+  (if *altivec-lapmacros-maintain-vrsave-p*
+    `(progn
+      (mfspr ,tempreg 256)		; SPR 256 = vrsave
+      (stw ,tempreg 8 tsp))
+    `(progn)))
+
+
+
+;;; When this is expanded, "tempreg" should contain the caller's vrsave.
+(defppclapmacro %update-vrsave (tempreg mask)
+  (let* ((mask-high (ldb (byte 16 16) mask))
+         (mask-low (ldb (byte 16 0) mask)))
+    `(progn
+       ,@(unless (zerop mask-high) `((oris ,tempreg ,tempreg ,mask-high)))
+       ,@(unless (zerop mask-low) `((ori ,tempreg ,tempreg ,mask-low)))
+       (mtspr 256 ,tempreg))))
+
+;;; Save each of the vector regs in "nvrs" into the current tstack 
+;;; frame, starting at offset 16
+(defppclapmacro %save-vector-regs (nvrs tempreg)
+  (let* ((insts ()))
+    (do* ((offset 16 (+ 16 offset))
+          (regs nvrs (cdr regs)))
+         ((null regs) `(progn ,@(nreverse insts)))
+      (declare (fixnum offset))
+      (push `(la ,tempreg ,offset ppc::tsp) insts)
+      (push `(stvx ,(car regs) ppc::rzero ,tempreg) insts))))
+
+
+;;; Pretty much the same idea, only we restore VRSAVE first and
+;;; discard the tstack frame after we've reloaded the vector regs.
+(defppclapmacro %restore-vector-regs (nvrs tempreg)
+  (let* ((loads ()))
+    (do* ((offset 16 (+ 16 offset))
+          (regs nvrs (cdr regs)))
+         ((null regs) `(progn
+			,@ (when *altivec-lapmacros-maintain-vrsave-p*
+			     `((progn
+				 (lwz ,tempreg 8 ppc::tsp)
+				 (mtspr 256 ,tempreg))))
+			,@(nreverse loads)
+			(lwz ppc::tsp 0 ppc::tsp)))
+      (declare (fixnum offset))
+      (push `(la ,tempreg ,offset ppc::tsp) loads)
+      (push `(lvx ,(car regs) ppc::rzero ,tempreg) loads))))
+
+
+(defun %extract-non-volatile-vector-registers (vector-reg-list)
+  (let* ((nvrs ()))
+    (dolist (reg vector-reg-list (nreverse nvrs))
+      (let* ((regval (ppc-vector-register-name-or-expression reg)))
+        (unless (typep regval '(mod 32))
+          (error "Bad AltiVec register - ~s" reg))
+        (when (>= regval 20)
+          (pushnew regval nvrs))))))
+
+
+;;; One could imagine something more elaborate:
+;;; 1) Binding a global bitmask that represents the assembly-time notion
+;;;    of VRSAVE's contents; #'ppc-vector-register-name-or-expression
+;;;    could then warn if a vector register wasn't marked as active.
+;;;    Maybe a good idea, but PPC-LAP would have to bind that special
+;;;    variable to 0 to make things reentrant.
+;;; 2) Binding a user-specified variable to the list of NVRs that need
+;;;    to be restored, so that it'd be more convenient to insert one's
+;;;    own calls to %RESTORE-VECTOR-REGS at appropriate points.
+;;; Ad infinitum.  As is, this allows one to execute a "flat" body of code
+;;;   that's bracketed by the stuff needed to keep VRSAVE in sync and
+;;;   to save and restore any non-volatile vector registers specified.
+;;;   That body of code is "flat" in the sense that it doesn't return,
+;;;   tail-call, establish a catch or unwind-protect frame, etc.
+;;;   It -can- contain lisp or foreign function calls.
+
+(defppclapmacro %with-altivec-registers ((&key (immreg 'ppc::imm0)) reglist &body body)
+  (let* ((mask (%vr-register-mask reglist))
+         (nvrs (%extract-non-volatile-vector-registers reglist))
+         (num-nvrs (length nvrs)))
+    (if (or *altivec-lapmacros-maintain-vrsave-p* nvrs)
+      `(progn
+	(%build-vrsave-frame ,num-nvrs ,immreg)
+	(%save-vrsave ,immreg)
+	,@ (if *altivec-lapmacros-maintain-vrsave-p*
+	     `((%update-vrsave ,immreg ,mask)))
+	(%save-vector-regs ,nvrs ,immreg)
+	(progn ,@body)
+	(%restore-vector-regs ,nvrs ,immreg))
+      `(progn ,@body))))
+
+
+(defppclapmacro with-altivec-registers (reglist &body body)
+  "Specify the set of AltiVec registers used in body. If
+*altivec-lapmacros-maintain-vrsave-p* is true when the macro is expanded,
+generates code to save the VRSAVE SPR and updates VRSAVE to incude a
+bitmask generated from the specified register list. Generates code which
+saves any non-volatile vector registers which appear in the register list,
+executes body, and restores the saved non-volatile vector registers (and,
+if *altivec-lapmacros-maintain-vrsave-p* is true, restores VRSAVE as well.
+Uses the IMM0 register (r3) as a temporary."
+  `(%with-altivec-registers () ,reglist ,@body))
+
+
+;;; Create an aligned buffer on the temp stack, large enough for N vector
+;;; registers.  Make base be a pointer to this buffer (base can be
+;;; any available GPR, since the buffer will be fixnum-tagged.) N should
+;;; be a constant.
+;;; The intent here is that the register 'base' can be used in subsequent
+;;; stvx/lvx instructions.  Any vector registers involved in such instructions
+;;; must have their corresponding bits saved in VRSAVE on platforms where
+;;; that matters.
+
+(defppclapmacro allocate-vector-buffer (base n)
+  `(progn
+    (stwux tsp (- (ash (1+ ,n) 4)))	; allocate a frame on temp stack
+    (stw tsp 4 tsp)			; temp frame contains immediate data
+    (la ,base (+ 8 8) tsp)		; skip header, round up
+    (clrrwi ,base ,base 4)))		; align (round down)
+
+;;; Execute the specified body of code; on entry to that body, BASE
+;;; will point to the lowest address of a vector-aligned buffer with
+;;; room for N vector registers.  On exit, the buffer will be
+;;; deallocated.  The body should preserve the value of BASE as long
+;;; as it needs to reference the buffer.
+
+(defppclapmacro with-vector-buffer (base n &body body)
+  "Generate code which allocates a 16-byte aligned buffer large enough
+to contain N vector registers; the GPR base points to the lowest address
+of this buffer. After processing body, the buffer will be deallocated.
+The body should preserve the value of base as long as it needs to
+reference the buffer. It's intended that base be used as a base register
+in stvx and lvx instructions within the body."
+  `(progn
+    (allocate-vector-buffer ,base ,n)
+    (progn
+      (progn ,@body)
+      (unlink tsp))))
+
+#|
+
+;;; This is just intended to test the macros; I can't test whether or not the code works.
+
+(defppclapfunction load-array ((n arg_z))
+  (check-nargs 1)
+  (with-altivec-registers (vr1 vr2 vr3 vr27) ; Clobbers imm0
+    (li imm0 ppc32::misc-data-offset)
+    (lvx vr1 arg_z imm0)		; load MSQ
+    (lvsl vr27 arg_z imm0)		; set the permute vector
+    (addi imm0 imm0 16)			; address of LSQ
+    (lvx vr2 arg_z imm0)		; load LSQ
+    (vperm vr3 vr1 vr2 vr27)		; aligned result appears in VR3
+    (dbg t))				; Look at result in some debugger
+  (blr))
+|#
+
+;;; see "Optimizing PowerPC Code" p. 156
+;;; Note that the constant #x4330000080000000 is now in fp-s32conv
+
+(defppclapmacro int-to-freg (int freg imm)
+  (target-arch-case
+   (:ppc32
+    `(let ((temp 8)
+           (temp.h 8)
+           (temp.l 12))
+      (stwu tsp -16 tsp)
+      (stw tsp 4 tsp)
+      (stfd ppc::fp-s32conv temp tsp)
+      (unbox-fixnum ,imm ,int)
+      (xoris ,imm ,imm #x8000)       ; invert sign of unboxed fixnum
+      (stw ,imm temp.l tsp)
+      (lfd ,freg temp tsp)
+      (lwz tsp 0 tsp)
+      (fsub ,freg ,freg ppc::fp-s32conv)))
+   (:ppc64
+    `(progn
+      (unbox-fixnum ,imm ,int)
+      (std ,imm -8 sp)
+      (lfd ,freg -8 sp)
+      (fcfid ,freg ,freg)))))
+
+;;; Set the most significant bit in DEST, clear all other bits.
+(defppclapmacro load-highbit (dest)
+  (target-arch-case
+   (:ppc32
+    `(lis ,dest #x8000))
+   (:ppc64
+    `(progn
+      (lis ,dest #x8000)
+      (sldi ,dest ,dest 32)))))
+
+(defppclapmacro extract-bit-shift-count (dest src)
+  (target-arch-case
+   (:ppc32 `(clrlwi ,dest ,src (- 32 ppc32::bitmap-shift)))
+   (:ppc64 `(clrldi ,dest ,src (- 64 ppc64::bitmap-shift)))))
+
+;;; "index" is the result of subtracting a base address from some
+;;; possibly tagged pointer.  "bitwords" is the address of the first
+;;; word of an (untagged) bitvector.
+(defppclapmacro set-bit-at-index (bitwords index &optional (mask ppc::imm3) (count ppc::imm4) (was ppc::imm1))
+  (let* ((done (gensym))
+         (again (gensym)))
+    `(progn
+      (load-highbit ,mask)
+      (srri ,index ,index ,(target-arch-case
+                            (:ppc32 ppc32::dnode-shift)
+                            (:ppc64 ppc64::dnode-shift)))
+      (extract-bit-shift-count ,count ,index)
+      (srr ,mask ,mask ,count)
+      (srri ,index ,index ,(target-arch-case
+                            (:ppc32 ppc32::bitmap-shift)
+                            (:ppc64 ppc64::bitmap-shift)))
+      (slri ,index ,index  ,(target-arch-case
+                            (:ppc32 ppc32::word-shift)
+                            (:ppc64 ppc64::word-shift)))
+      (ldrx ,was ,bitwords ,index)
+      (and. ,was ,was ,mask)
+      (bne ,done)
+      ,again
+      (lrarx ,was ,bitwords ,index)
+      (or ,was ,was ,mask)
+      (strcx. ,was ,bitwords ,index)
+      (bne ,again)
+      ,done)))
+
+;;; Like SET-BIT-AT-INDEX, but sets CR0[EQ] iff the index'th bit
+;;; is set.
+(defppclapmacro test-bit-at-index (bitwords index &optional (mask ppc::imm3) (count ppc::imm4) (was ppc::imm1))
+  `(progn
+    (load-highbit ,mask)
+    (srri ,index ,index ,(target-arch-case
+                          (:ppc32 ppc32::dnode-shift)
+                          (:ppc64 ppc64::dnode-shift)))
+    (extract-bit-shift-count ,count ,index)
+    (srr ,mask ,mask ,count)
+    (srri ,index ,index ,(target-arch-case
+                          (:ppc32 ppc32::bitmap-shift)
+                          (:ppc64 ppc64::bitmap-shift)))
+    (slri ,index ,index  ,(target-arch-case
+                           (:ppc32 ppc32::word-shift)
+                           (:ppc64 ppc64::word-shift)))
+    (ldrx ,was ,bitwords ,index)
+    (and. ,mask ,was ,mask)))
+                                           
+
+(provide "PPC-LAPMACROS")
+
+;;; end of ppc-lapmacros.lisp
Index: /branches/new-random/compiler/PPC/ppc2.lisp
===================================================================
--- /branches/new-random/compiler/PPC/ppc2.lisp	(revision 13309)
+++ /branches/new-random/compiler/PPC/ppc2.lisp	(revision 13309)
@@ -0,0 +1,9202 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NXENV")
+  (require "PPCENV"))
+
+(eval-when (:load-toplevel :execute :compile-toplevel)
+  (require "PPC-BACKEND"))
+
+(defparameter *ppc2-debug-mask* 0)
+(defconstant ppc2-debug-verbose-bit 0)
+(defconstant ppc2-debug-vinsns-bit 1)
+(defconstant ppc2-debug-lcells-bit 2)
+(defparameter *ppc2-target-lcell-size* 0)
+(defparameter *ppc2-target-node-size* 0)
+(defparameter *ppc2-target-fixnum-shift* 0)
+(defparameter *ppc2-target-node-shift* 0)
+(defparameter *ppc2-target-bits-in-word* 0)
+(defparameter *ppc2-ppc32-half-fixnum-type* '(signed-byte 29))
+(defparameter *ppc2-ppc64-half-fixnum-type* `(signed-byte 60))
+(defparameter *ppc2-target-half-fixnum-type* nil)
+
+
+
+  
+
+(defmacro with-ppc-p2-declarations (declsform &body body)
+  `(let* ((*ppc2-tail-allow* *ppc2-tail-allow*)
+          (*ppc2-reckless* *ppc2-reckless*)
+          (*ppc2-open-code-inline* *ppc2-open-code-inline*)
+          (*ppc2-trust-declarations* *ppc2-trust-declarations*)
+	  (*ppc2-full-safety* *ppc2-full-safety*))
+     (ppc2-decls ,declsform)
+     ,@body))
+
+
+(defmacro with-ppc-local-vinsn-macros ((segvar &optional vreg-var xfer-var) &body body)
+  (declare (ignorable xfer-var))
+  (let* ((template-name-var (gensym))
+         (template-temp (gensym))
+         (args-var (gensym))
+         (labelnum-var (gensym))
+         (retvreg-var (gensym))
+         (label-var (gensym)))
+    `(macrolet ((! (,template-name-var &rest ,args-var)
+                  (let* ((,template-temp (get-vinsn-template-cell ,template-name-var (backend-p2-vinsn-templates *target-backend*))))
+                    (unless ,template-temp
+                      (warn "VINSN \"~A\" not defined" ,template-name-var))
+                    `(%emit-vinsn ,',segvar ',,template-name-var (backend-p2-vinsn-templates *target-backend*) ,@,args-var))))
+       (macrolet ((<- (,retvreg-var)
+                    `(ppc2-copy-register ,',segvar ,',vreg-var ,,retvreg-var))
+                  (@  (,labelnum-var)
+                    `(backend-gen-label ,',segvar ,,labelnum-var))
+                  (-> (,label-var)
+                    `(! jump (aref *backend-labels* ,,label-var)))
+                  (^ (&rest branch-args)
+                    `(ppc2-branch ,',segvar ,',xfer-var ,',vreg-var ,@branch-args))
+                  (? (&key (class :gpr)
+                          (mode :lisp))
+                   (let* ((class-val
+                           (ecase class
+                             (:gpr hard-reg-class-gpr)
+                             (:fpr hard-reg-class-fpr)
+                             (:crf hard-reg-class-crf)))
+                          (mode-val
+                           (if (eq class :gpr)
+                             (gpr-mode-name-value mode)
+                             (if (eq class :fpr)
+                               (if (eq mode :single-float)
+                                 hard-reg-class-fpr-mode-single
+                                 hard-reg-class-fpr-mode-double)
+                               0))))
+                     `(make-unwired-lreg nil
+                       :class ,class-val
+                       :mode ,mode-val)))
+                  ($ (reg &key (class :gpr) (mode :lisp))
+                   (let* ((class-val
+                           (ecase class
+                             (:gpr hard-reg-class-gpr)
+                             (:fpr hard-reg-class-fpr)
+                             (:crf hard-reg-class-crf)))
+                          (mode-val
+                           (if (eq class :gpr)
+                             (gpr-mode-name-value mode)
+                             (if (eq class :fpr)
+                               (if (eq mode :single-float)
+                                 hard-reg-class-fpr-mode-single
+                                 hard-reg-class-fpr-mode-double)
+                               0))))
+                     `(make-wired-lreg ,reg
+                       :class ,class-val
+                       :mode ,mode-val))))
+         ,@body))))
+
+
+
+
+
+
+
+
+
+
+
+
+(defvar *ppc-current-context-annotation* nil)
+(defvar *ppc2-woi* nil)
+(defvar *ppc2-open-code-inline* nil)
+(defvar *ppc2-register-restore-count* 0)
+(defvar *ppc2-register-restore-ea* nil)
+(defvar *ppc2-compiler-register-save-label* nil)
+(defvar *ppc2-valid-register-annotations* 0)
+(defvar *ppc2-register-annotation-types* nil)
+(defvar *ppc2-register-ea-annotations* nil)
+
+(defparameter *ppc2-tail-call-aliases*
+  ()
+  #| '((%call-next-method . (%tail-call-next-method . 1))) |#
+  
+)
+
+(defvar *ppc2-popreg-labels* nil)
+(defvar *ppc2-popj-labels* nil)
+(defvar *ppc2-valret-labels* nil)
+(defvar *ppc2-nilret-labels* nil)
+
+(defvar *ppc2-icode* nil)
+(defvar *ppc2-undo-stack* nil)
+(defvar *ppc2-undo-because* nil)
+
+
+(defvar *ppc2-cur-afunc* nil)
+(defvar *ppc2-vstack* 0)
+(defvar *ppc2-cstack* 0)
+(defvar *ppc2-undo-count* 0)
+(defvar *ppc2-returning-values* nil)
+(defvar *ppc2-vcells* nil)
+(defvar *ppc2-fcells* nil)
+(defvar *ppc2-entry-vsp-saved-p* nil)
+
+(defvar *ppc2-entry-label* nil)
+(defvar *ppc2-tail-label* nil)
+(defvar *ppc2-tail-vsp* nil)
+(defvar *ppc2-tail-nargs* nil)
+(defvar *ppc2-tail-allow* t)
+(defvar *ppc2-reckless* nil)
+(defvar *ppc2-full-safety* nil)
+(defvar *ppc2-trust-declarations* nil)
+(defvar *ppc2-entry-vstack* nil)
+(defvar *ppc2-fixed-nargs* nil)
+(defvar *ppc2-need-nargs* t)
+
+(defparameter *ppc2-inhibit-register-allocation* nil)
+(defvar *ppc2-record-symbols* nil)
+(defvar *ppc2-recorded-symbols* nil)
+(defvar *ppc2-emitted-source-notes* nil)
+
+(defvar *ppc2-result-reg* ppc::arg_z)
+
+(defvar *ppc2-nvrs* `(,ppc::save0 ,ppc::save1 ,ppc::save2 ,ppc::save3
+                      ,ppc::save4 ,ppc::save5 ,ppc::save6 ,ppc::save7))
+
+
+
+
+
+(declaim (fixnum *ppc2-vstack* *ppc2-cstack*))
+
+ 
+
+
+;;; Before any defppc2's, make the *ppc2-specials* vector.
+
+(defvar *ppc2-all-lcells* ())
+
+
+
+
+     
+(defun ppc2-free-lcells ()
+  (without-interrupts 
+   (let* ((prev (pool.data *lcell-freelist*)))
+     (dolist (r *ppc2-all-lcells*)
+       (setf (lcell-kind r) prev
+             prev r))
+     (setf (pool.data *lcell-freelist*) prev)
+     (setq *ppc2-all-lcells* nil))))
+
+(defun ppc2-note-lcell (c)
+  (push c *ppc2-all-lcells*)
+  c)
+
+(defvar *ppc2-top-vstack-lcell* ())
+(defvar *ppc2-bottom-vstack-lcell* ())
+
+(defun ppc2-new-lcell (kind parent width attributes info)
+  (ppc2-note-lcell (make-lcell kind parent width attributes info)))
+
+(defun ppc2-new-vstack-lcell (kind width attributes info)
+  (setq *ppc2-top-vstack-lcell* (ppc2-new-lcell kind *ppc2-top-vstack-lcell* width attributes info)))
+
+(defun ppc2-reserve-vstack-lcells (n)
+  (dotimes (i n) (ppc2-new-vstack-lcell :reserved *ppc2-target-lcell-size* 0 nil)))
+
+(defun ppc2-vstack-mark-top ()
+  (ppc2-new-lcell :tos *ppc2-top-vstack-lcell* 0 0 nil))
+
+;;; Alist mapping VARs to lcells/lregs
+(defvar *ppc2-var-cells* ())
+
+(defun ppc2-note-var-cell (var cell)
+  ;(format t "~& ~s -> ~s" (var-name var) cell)
+  (push (cons var cell) *ppc2-var-cells*))
+
+(defun ppc2-note-top-cell (var)
+  (ppc2-note-var-cell var *ppc2-top-vstack-lcell*))
+
+(defun ppc2-lookup-var-cell (var)
+  (or (cdr (assq var *ppc2-var-cells*))
+      (and nil (warn "Cell not found for ~s" (var-name var)))))
+
+(defun ppc2-collect-lcells (kind &optional (bottom *ppc2-bottom-vstack-lcell*) (top *ppc2-top-vstack-lcell*))
+  (do* ((res ())
+        (cell top (lcell-parent cell)))
+       ((eq cell bottom) res)
+    (if (null cell)
+      (compiler-bug "Horrible compiler bug.")
+      (if (eq (lcell-kind cell) kind)
+        (push cell res)))))
+
+
+
+  
+;;; ensure that lcell's offset matches what we expect it to.
+;;; For bootstrapping.
+
+(defun ppc2-ensure-lcell-offset (c expected)
+  (if c (= (calc-lcell-offset c) expected) (zerop expected)))
+
+(defun ppc2-check-lcell-depth (&optional (context "wherever"))
+  (when (logbitp ppc2-debug-verbose-bit *ppc2-debug-mask*)
+    (let* ((depth (calc-lcell-depth *ppc2-top-vstack-lcell*)))
+      (or (= depth *ppc2-vstack*)
+          (warn "~a: lcell depth = ~d, vstack = ~d" context depth *ppc2-vstack*)))))
+
+(defun ppc2-do-lexical-reference (seg vreg ea)
+  (when vreg
+    (with-ppc-local-vinsn-macros (seg vreg) 
+      (if (memory-spec-p ea)
+        (ensuring-node-target (target vreg)
+          (progn
+            (ppc2-stack-to-register seg ea target)
+            (if (addrspec-vcell-p ea)
+              (! vcell-ref target target))))
+        (<- ea)))))
+
+(defun ppc2-do-lexical-setq (seg vreg ea valreg)
+  (with-ppc-local-vinsn-macros (seg vreg)
+    (cond ((typep ea 'lreg)
+            (ppc2-copy-register seg ea valreg))
+          ((addrspec-vcell-p ea)     ; closed-over vcell
+           (ppc2-copy-register seg ppc::arg_z valreg)
+           (ppc2-stack-to-register seg ea ppc::arg_x)
+           (ppc2-copy-register seg ppc::arg_y ppc::rzero)
+           (! call-subprim-3 ppc::arg_z (subprim-name->offset '.SPgvset) ppc::arg_x ppc::arg_y ppc::arg_z))
+          ((memory-spec-p ea)    ; vstack slot
+           (ppc2-register-to-stack seg valreg ea))
+          (t
+           (ppc2-copy-register seg ea valreg)))
+    (when vreg
+      (<- valreg))))
+
+;;; ensure that next-method-var is heap-consed (if it's closed over.)
+;;; it isn't ever setqed, is it ?
+(defun ppc2-heap-cons-next-method-var (seg var)
+  (with-ppc-local-vinsn-macros (seg)
+    (when (eq (ash 1 $vbitclosed)
+              (logand (logior (ash 1 $vbitclosed)
+                              (ash 1 $vbitcloseddownward))
+                      (the fixnum (nx-var-bits var))))
+      (let* ((ea (var-ea var))
+             (arg ($ ppc::arg_z))
+             (result ($ ppc::arg_z)))
+        (ppc2-do-lexical-reference seg arg ea)
+        (ppc2-set-nargs seg 1)
+        (! ref-constant ($ ppc::fname) (backend-immediate-index (ppc2-symbol-entry-locative '%cons-magic-next-method-arg)))
+        (! call-known-symbol arg)
+        (ppc2-do-lexical-setq seg nil ea result)))))
+
+(defun ppc2-reverse-cc (cc)
+  ;                NE  NE  EQ  EQ   LE   GE   LT   GT   GE   LE   GT   LT    MI   PL   PL   MI
+  (%cdr (assq cc '((6 . 6) (7 . 7) (15 . 12) (13 . 14) (12 . 15) (14 . 13)  (11 . 10) (10 . 11)))))
+
+  ;                NE  NE  EQ  EQ   LE   GE   LT   GT   GE   LE   GT   LT    MI   PL   PL   MI
+(defun ppc2-reverse-condition-keyword (k)
+  (cdr (assq k '((:ne . :ne) (:eq . :eq) (:le . :ge) (:lt . :gt) (:ge . :le) (:gt . :lt)))))
+
+
+
+
+(defun acode-condition-to-ppc-cr-bit (cond)
+  (condition-to-ppc-cr-bit (cadr cond)))
+
+(defun condition-to-ppc-cr-bit (cond)
+  (case cond
+    (:EQ (values ppc::ppc-eq-bit t))
+    (:NE (values ppc::ppc-eq-bit nil))
+    (:GT (values ppc::ppc-gt-bit t))
+    (:LE (values ppc::ppc-gt-bit nil))
+    (:LT (values ppc::ppc-lt-bit t))
+    (:GE (values ppc::ppc-lt-bit nil))))
+
+;;; Generate the start and end bits for a RLWINM instruction that
+;;; would be equivalent to to LOGANDing the constant with some value.
+;;; Return (VALUES NIL NIL) if the constant contains more than one
+;;; sequence of consecutive 1-bits, else bit indices.
+;;; The caller generally wants to treat the constant as an (UNSIGNED-BYTE 32);
+;;; since this uses LOGCOUNT and INTEGER-LENGTH to find the significant
+;;; bits, it ensures that the constant is a (SIGNED-BYTE 32) that has
+;;; the same least-significant 32 bits.
+(defun ppc2-mask-bits (constant)
+  (if (< constant 0) (setq constant (logand #xffffffff constant)))
+  (if (= constant #xffffffff)
+    (values 0 31)
+    (if (zerop constant)
+      (values nil nil)
+      (let* ((signed (if (and (logbitp 31 constant)
+                              (> constant 0))
+                       (- constant (ash 1 32))
+                       constant))
+             (count (logcount signed))
+             (len (integer-length signed))
+             (highbit (logbitp (the fixnum (1- len)) constant)))
+        (declare (fixnum count len))
+        (do* ((i 1 (1+ i))
+              (pos (- len 2) (1- pos)))
+             ((= i count)
+              (let* ((start (- 32 len))
+                     (end (+ count start)))
+                (declare (fixnum start end))
+                (if highbit
+                  (values start (the fixnum (1- end)))
+                  (values (logand 31 end)
+                          (the fixnum (1- start))))))
+          (declare (fixnum i pos))
+          (unless (eq (logbitp pos constant) highbit)
+            (return (values nil nil))))))))
+    
+
+(defun ppc2-ensure-binding-indices-for-vcells (vcells)
+  (dolist (cell vcells)
+    (ensure-binding-index (car cell)))
+  vcells)
+
+(defun ppc2-compile (afunc &optional lambda-form *ppc2-record-symbols*)
+  (progn
+    (dolist (a  (afunc-inner-functions afunc))
+      (unless (afunc-lfun a)
+        (ppc2-compile a 
+                      (if lambda-form 
+                        (afunc-lambdaform a)) 
+                      *ppc2-record-symbols*))) ; always compile inner guys
+    (let* ((*ppc2-cur-afunc* afunc)
+           (*ppc2-returning-values* nil)
+           (*ppc-current-context-annotation* nil)
+           (*ppc2-woi* nil)
+           (*next-lcell-id* -1)
+           (*ppc2-open-code-inline* nil)
+           (*ppc2-register-restore-count* nil)
+           (*ppc2-compiler-register-save-label* nil)
+           (*ppc2-valid-register-annotations* 0)
+           (*ppc2-register-ea-annotations* (ppc2-make-stack 16))
+           (*ppc2-register-restore-ea* nil)
+           (*ppc2-vstack* 0)
+           (*ppc2-cstack* 0)
+	   (*ppc2-target-lcell-size* (arch::target-lisp-node-size (backend-target-arch *target-backend*)))
+           (*ppc2-target-fixnum-shift* (arch::target-fixnum-shift (backend-target-arch *target-backend*)))
+           (*ppc2-target-node-shift* (arch::target-word-shift  (backend-target-arch *target-backend*)))
+           (*ppc2-target-bits-in-word* (arch::target-nbits-in-word (backend-target-arch *target-backend*)))
+	   (*ppc2-target-node-size* *ppc2-target-lcell-size*)
+           (*ppc2-target-half-fixnum-type* (target-word-size-case
+                                            (32 *ppc2-ppc32-half-fixnum-type*)
+                                            (64 *ppc2-ppc64-half-fixnum-type*)))
+           (*ppc2-all-lcells* ())
+           (*ppc2-top-vstack-lcell* nil)
+           (*ppc2-bottom-vstack-lcell* (ppc2-new-vstack-lcell :bottom 0 0 nil))
+           (*ppc2-var-cells* nil)
+           (*backend-vinsns* (backend-p2-vinsn-templates *target-backend*))
+           (*backend-node-regs* ppc-node-regs)
+           (*backend-node-temps* ppc-temp-node-regs)
+           (*available-backend-node-temps* ppc-temp-node-regs)
+           (*backend-imm-temps* ppc-imm-regs)
+           (*available-backend-imm-temps* ppc-imm-regs)
+           (*backend-crf-temps* ppc-cr-fields)
+           (*available-backend-crf-temps* ppc-cr-fields)
+           (*backend-fp-temps* ppc-temp-fp-regs)
+           (*available-backend-fp-temps* ppc-temp-fp-regs)
+           (bits 0)
+           (*logical-register-counter* -1)
+           (*backend-all-lregs* ())
+           (*ppc2-popj-labels* nil)
+           (*ppc2-popreg-labels* nil)
+           (*ppc2-valret-labels* nil)
+           (*ppc2-nilret-labels* nil)
+           (*ppc2-undo-count* 0)
+           (*backend-labels* (ppc2-make-stack 64 target::subtag-simple-vector))
+           (*ppc2-undo-stack* (ppc2-make-stack 64  target::subtag-simple-vector))
+           (*ppc2-undo-because* (ppc2-make-stack 64))
+           (*backend-immediates* (ppc2-make-stack 64  target::subtag-simple-vector))
+           (*ppc2-entry-label* nil)
+           (*ppc2-tail-label* nil)
+           (*ppc2-tail-vsp* nil)
+           (*ppc2-tail-nargs* nil)
+           (*ppc2-inhibit-register-allocation* nil)
+           (*ppc2-tail-allow* t)
+           (*ppc2-reckless* nil)
+	   (*ppc2-full-safety* nil)
+           (*ppc2-trust-declarations* t)
+           (*ppc2-entry-vstack* nil)
+           (*ppc2-fixed-nargs* nil)
+           (*ppc2-need-nargs* t)
+           (fname (afunc-name afunc))
+           (*ppc2-entry-vsp-saved-p* nil)
+           (*ppc2-vcells* (ppc2-ensure-binding-indices-for-vcells (afunc-vcells afunc)))
+           (*ppc2-fcells* (afunc-fcells afunc))
+           *ppc2-recorded-symbols*
+           (*ppc2-emitted-source-notes* '()))
+      (set-fill-pointer
+       *backend-labels*
+       (set-fill-pointer
+        *ppc2-undo-stack*
+        (set-fill-pointer 
+         *ppc2-undo-because*
+         (set-fill-pointer
+          *backend-immediates* 0))))
+      (backend-get-next-label)          ; start @ label 1, 0 is confused with NIL in compound cd
+      (with-dll-node-freelist (vinsns *vinsn-freelist*)
+        (unwind-protect
+             (progn
+               (setq bits (ppc2-toplevel-form vinsns (make-wired-lreg *ppc2-result-reg*) $backend-return (afunc-acode afunc)))
+               (dotimes (i (length *backend-immediates*))
+                 (let ((imm (aref *backend-immediates* i)))
+                   (when (ppc2-symbol-locative-p imm) (aset *backend-immediates* i (car imm)))))
+               (optimize-vinsns vinsns)
+               (when (logbitp ppc2-debug-vinsns-bit *ppc2-debug-mask*)
+                 (format t "~% vinsns for ~s (after generation)" (afunc-name afunc))
+                 (do-dll-nodes (v vinsns) (format t "~&~s" v))
+                 (format t "~%~%"))
+            
+            
+               (with-dll-node-freelist (*lap-instructions* *lap-instruction-freelist*)
+                 (let* ((*lap-labels* nil)
+                        debug-info)
+                   (ppc2-expand-vinsns vinsns) 
+                   (if (logbitp $fbitnonnullenv (the fixnum (afunc-bits afunc)))
+                     (setq bits (+ bits (ash 1 $lfbits-nonnullenv-bit))))
+                   (setq debug-info (afunc-lfun-info afunc))
+                   (when lambda-form
+                     (setq debug-info (list* 'function-lambda-expression lambda-form debug-info)))
+                   (when *ppc2-recorded-symbols*
+                     (setq debug-info (list* 'function-symbol-map *ppc2-recorded-symbols* debug-info)))
+                   (when (and (getf debug-info '%function-source-note) *ppc2-emitted-source-notes*)
+                     (setq debug-info (list* 'pc-source-map *ppc2-emitted-source-notes* debug-info)))
+                   (when debug-info
+                     (setq bits (logior (ash 1 $lfbits-info-bit) bits))
+                     (backend-new-immediate debug-info))
+                   (if (or fname lambda-form *ppc2-recorded-symbols*)
+                     (backend-new-immediate fname)
+                     (setq bits (logior (ash -1 $lfbits-noname-bit) bits)))
+
+                   (unless (afunc-parent afunc)
+                     (ppc2-fixup-fwd-refs afunc))
+                   (setf (afunc-all-vars afunc) nil)
+                   (setf (afunc-argsword afunc) bits)
+                   (let* ((regsave-label (if (typep *ppc2-compiler-register-save-label* 'vinsn-note)
+                                           (vinsn-label-info (vinsn-note-label *ppc2-compiler-register-save-label*))))
+                          (regsave-reg (if regsave-label (- 32 *ppc2-register-restore-count*)))
+                          (regsave-addr (if regsave-label (- *ppc2-register-restore-ea*))))
+                     (setf (afunc-lfun afunc)
+                           (ppc2-xmake-function
+                            *lap-instructions*
+                            *lap-labels*
+                            *backend-immediates*
+                            bits
+                            regsave-label
+                            regsave-reg
+                            regsave-addr
+                            (if (and fname (symbolp fname)) (symbol-name fname)))))
+                   (when (getf debug-info 'pc-source-map)
+                     (setf (getf debug-info 'pc-source-map) (ppc2-generate-pc-source-map debug-info)))
+                   (when (getf debug-info 'function-symbol-map)
+                     (setf (getf debug-info 'function-symbol-map) (ppc2-digest-symbols))))))
+          (backend-remove-labels))))
+    afunc))
+
+(defun ppc2-xmake-function (codeheader labels imms bits *ppc-lap-regsave-label* *ppc-lap-regsave-reg* *ppc-lap-regsave-addr* &optional traceback-string)
+  (let* ((*lap-instructions* codeheader)
+         (*lap-labels* labels)
+         (cross-compiling (not (eq *host-backend* *target-backend*)))
+         (numimms (length imms))
+         (function (%alloc-misc (+ numimms 2)
+                                (if cross-compiling
+                                  target::subtag-xfunction
+                                  target::subtag-function))))
+    (dotimes (i numimms)
+      (setf (uvref function (1+ i)) (aref imms i)))
+    (setf (uvref function (+ numimms 1)) bits)
+    (let* ((maxpc (ppc-lap-encode-regsave-info (ppc-lap-do-labels)))
+	   (traceback-size (traceback-fullwords traceback-string))
+           (prefix (arch::target-code-vector-prefix (backend-target-arch *target-backend*)))
+           (prefix-size (length prefix))
+           (code-vector-size (+ traceback-size (ash maxpc -2) prefix-size)))
+      #+ppc32-target
+      (if (>= code-vector-size (ash 1 19)) (compiler-function-overflow))
+      (let* ((code-vector (%alloc-misc code-vector-size
+                                     (if cross-compiling
+                                       target::subtag-xcode-vector
+                                       target::subtag-code-vector)))
+             (i prefix-size))
+        (dotimes (i prefix-size)
+          (setf (uvref code-vector i) (pop prefix)))
+        (ppc-lap-resolve-labels)
+        (do-dll-nodes (insn *lap-instructions*)
+          (ppc-lap-generate-instruction code-vector i insn)
+          (incf i))
+        (unless (eql 0 traceback-size)
+          (add-traceback-table code-vector i traceback-string))
+        (setf (uvref function 0) code-vector)
+        (%make-code-executable code-vector)
+        function))))
+      
+    
+(defun ppc2-make-stack (size &optional (subtype target::subtag-s16-vector))
+  (make-uarray-1 subtype size t 0 nil nil nil nil t nil))
+
+(defun ppc2-fixup-fwd-refs (afunc)
+  (dolist (f (afunc-inner-functions afunc))
+    (ppc2-fixup-fwd-refs f))
+  (let ((fwd-refs (afunc-fwd-refs afunc)))
+    (when fwd-refs
+      (let* ((v (afunc-lfun afunc))
+             (vlen (uvsize v)))
+        (declare (fixnum vlen))
+        (dolist (ref fwd-refs)
+          (let* ((ref-fun (afunc-lfun ref)))
+            (do* ((i 1 (1+ i)))
+                 ((= i vlen))
+              (declare (fixnum i))
+              (if (eq (%svref v i) ref)
+                (setf (%svref v i) ref-fun)))))))))
+
+(defun ppc2-generate-pc-source-map (debug-info)
+  (let* ((definition-source-note (getf debug-info '%function-source-note))
+         (emitted-source-notes (getf debug-info 'pc-source-map))
+         (def-start (source-note-start-pos definition-source-note))
+         (n (length emitted-source-notes))
+         (nvalid 0)
+         (max 0)
+         (pc-starts (make-array n))
+         (pc-ends (make-array n))
+         (text-starts (make-array n))
+         (text-ends (make-array n)))
+    (declare (fixnum n nvalid)
+             (dynamic-extent pc-starts pc-ends text-starts text-ends))
+    (dolist (start emitted-source-notes)
+      (let* ((pc-start (ppc2-vinsn-note-label-address start t))
+             (pc-end (ppc2-vinsn-note-label-address (vinsn-note-peer start) nil))
+             (source-note (aref (vinsn-note-info start) 0))
+             (text-start (- (source-note-start-pos source-note) def-start))
+             (text-end (- (source-note-end-pos source-note) def-start)))
+        (declare (fixnum pc-start pc-end text-start text-end))
+        (when (and (plusp pc-start)
+                   (plusp pc-end)
+                   (plusp text-start)
+                   (plusp text-end))
+          (if (> pc-start max) (setq max pc-start))
+          (if (> pc-end max) (setq max pc-end))
+          (if (> text-start max) (setq max text-start))
+          (if (> text-end max) (setq max text-end))
+          (setf (svref pc-starts nvalid) pc-start
+                (svref pc-ends nvalid) pc-end
+                (svref text-starts nvalid) text-start
+                (svref text-ends nvalid) text-end)
+          (incf nvalid))))
+    (let* ((nentries (* nvalid 4))
+           (vec (cond ((< max #x100) (make-array nentries :element-type '(unsigned-byte 8)))
+                      ((< max #x10000) (make-array nentries :element-type '(unsigned-byte 16)))
+                      (t (make-array nentries :element-type '(unsigned-byte 32))))))
+      (declare (fixnum nentries))
+      (do* ((i 0 (+ i 4))
+            (j 1 (+ j 4))
+            (k 2 (+ k 4))
+            (l 3 (+ l 4))
+            (idx 0 (1+ idx)))
+          ((= i nentries) vec)
+        (declare (fixnum i j k l idx))
+        (setf (aref vec i) (svref pc-starts idx)
+              (aref vec j) (svref pc-ends idx)
+              (aref vec k) (svref text-starts idx)
+              (aref vec l) (svref text-ends idx))))))
+
+(defun ppc2-vinsn-note-label-address (note &optional start-p sym)
+  (let* ((label (vinsn-note-label note))
+         (lap-label (if label (vinsn-label-info label))))
+    (if lap-label
+      (lap-label-address lap-label)
+      (compiler-bug "Missing or bad ~s label: ~s" 
+                    (if start-p 'start 'end) sym))))
+
+(defun ppc2-digest-symbols ()
+  (when *ppc2-recorded-symbols*
+    (setq *ppc2-recorded-symbols* (nx2-recorded-symbols-in-arglist-order *ppc2-recorded-symbols* *ppc2-cur-afunc*))
+ (let* ((symlist *ppc2-recorded-symbols*)
+           (len (length symlist))
+           (syms (make-array len))
+           (ptrs (make-array (%i+  (%i+ len len) len)))
+           (i -1)
+           (j -1))
+      (declare (fixnum i j))
+      (dolist (info symlist (progn (%rplaca symlist syms)
+                                   (%rplacd symlist ptrs)))
+        (destructuring-bind (var sym startlab endlab) info
+          (let* ((ea (var-ea var))
+                 (ea-val (ldb (byte 16 0) ea)))
+            (setf (aref ptrs (incf i)) (if (memory-spec-p ea)
+                                         (logior (ash ea-val 6) #o77)
+                                         ea-val)))
+          (setf (aref syms (incf j)) sym)
+          (setf (aref ptrs (incf i)) (ppc2-vinsn-note-label-address startlab t sym))
+          (setf (aref ptrs (incf i)) (ppc2-vinsn-note-label-address endlab nil sym))))
+      *ppc2-recorded-symbols*)))
+
+(defun ppc2-decls (decls)
+  (if (fixnump decls)
+    (locally (declare (fixnum decls))
+      (setq *ppc2-tail-allow* (neq 0 (%ilogand2 $decl_tailcalls decls))
+            *ppc2-open-code-inline* (neq 0 (%ilogand2 $decl_opencodeinline decls))
+	    *ppc2-full-safety* (neq 0 (%ilogand2 $decl_full_safety decls))
+            *ppc2-reckless* (neq 0 (%ilogand2 $decl_unsafe decls))
+            *ppc2-trust-declarations* (neq 0 (%ilogand2 $decl_trustdecls decls))))))
+
+
+
+
+
+          
+    
+;;; Vpush the last N non-volatile-registers.
+;;; Could use a STM here, especially if N is largish or optimizing for space.
+(defun ppc2-save-nvrs (seg n)
+  (declare (fixnum n))
+  (when (> n 0)
+    (setq *ppc2-compiler-register-save-label* (ppc2-emit-note seg :regsave))
+    (with-ppc-local-vinsn-macros (seg)
+      (if *ppc2-open-code-inline*
+	(! save-nvrs-individually (- 32 n))
+	(! save-nvrs (- 32 n))))
+    (dotimes (i n)
+      (ppc2-new-vstack-lcell :regsave *ppc2-target-lcell-size* 0 (- ppc::save0 i)))
+    (incf *ppc2-vstack* (the fixnum (* n *ppc2-target-node-size*)))
+    (setq *ppc2-register-restore-ea* *ppc2-vstack*
+          *ppc2-register-restore-count* n)))
+
+
+;;; If there are an indefinite number of args/values on the vstack,
+;;; we have to restore from a register that matches the compiler's
+;;; notion of the vstack depth.  This can be computed by the caller 
+;;; (sum of vsp & nargs, or copy of vsp  before indefinite number of 
+;;; args pushed, etc.)
+;;; We DON'T try to compute this from the saved context, since the
+;;; saved vsp may belong to a different stack segment.  (It's cheaper
+;;; to compute/copy than to load it, anyway.)
+
+(defun ppc2-restore-nvrs (seg ea nregs &optional from-fp)
+  (when (null from-fp)
+    (setq from-fp ppc::vsp))
+  (when (and ea nregs)
+    (with-ppc-local-vinsn-macros (seg)
+      (let* ((first (- 32 nregs)))
+        (declare (fixnum first))
+        (! restore-nvrs first from-fp (- *ppc2-vstack* ea))))))
+
+
+
+(defun ppc2-bind-lambda (seg lcells req opt rest keys auxen optsupvloc passed-in-regs lexpr &optional inherited
+                             &aux (vloc 0) (numopt (list-length (%car opt)))
+                             (nkeys (list-length (%cadr keys))) 
+                             reg)
+  (declare (fixnum vloc))
+  (ppc2-check-lcell-depth)
+  (dolist (arg inherited)
+    (if (memq arg passed-in-regs)
+      (ppc2-set-var-ea seg arg (var-ea arg))
+      (let* ((lcell (pop lcells)))
+        (if (setq reg (nx2-assign-register-var arg))
+          (ppc2-init-regvar seg arg reg (ppc2-vloc-ea vloc))
+          (ppc2-bind-var seg arg vloc lcell))
+        (setq vloc (%i+ vloc *ppc2-target-node-size*)))))
+  (dolist (arg req)
+    (if (memq arg passed-in-regs)
+      (ppc2-set-var-ea seg arg (var-ea arg))
+      (let* ((lcell (pop lcells)))
+        (if (setq reg (nx2-assign-register-var arg))
+          (ppc2-init-regvar seg arg reg (ppc2-vloc-ea vloc))
+          (ppc2-bind-var seg arg vloc lcell))
+        (setq vloc (%i+ vloc *ppc2-target-node-size*)))))
+  (when opt
+    (if (ppc2-hard-opt-p opt)
+      (setq vloc (apply #'ppc2-initopt seg vloc optsupvloc lcells (nthcdr (- (length lcells) numopt) lcells) opt)
+            lcells (nthcdr numopt lcells))
+
+      (dolist (var (%car opt))
+        (if (memq var passed-in-regs)
+          (ppc2-set-var-ea seg var (var-ea var))
+          (let* ((lcell (pop lcells)))
+            (if (setq reg (nx2-assign-register-var var))
+              (ppc2-init-regvar seg var reg (ppc2-vloc-ea vloc))
+              (ppc2-bind-var seg var vloc lcell))
+            (setq vloc (+ vloc *ppc2-target-node-size*)))))))
+  (when rest
+    (if lexpr
+      (progn
+        (if (setq reg (nx2-assign-register-var rest))
+          (progn
+            (ppc2-load-lexpr-address seg reg)
+            (ppc2-set-var-ea seg rest reg))
+          (with-imm-temps () ((nargs-cell :natural))
+            (ppc2-load-lexpr-address seg nargs-cell)
+            (let* ((loc *ppc2-vstack*))
+              (ppc2-vpush-register seg nargs-cell :reserved)
+              (ppc2-note-top-cell rest)
+              (ppc2-bind-var seg rest loc *ppc2-top-vstack-lcell*)))))
+      (let* ((rvloc (+ vloc (* 2 *ppc2-target-node-size* nkeys))))
+        (if (setq reg (nx2-assign-register-var rest))
+          (ppc2-init-regvar seg rest reg (ppc2-vloc-ea rvloc))
+          (ppc2-bind-var seg rest rvloc (pop lcells))))))
+  (when keys
+    (apply #'ppc2-init-keys seg vloc lcells keys))  
+  (ppc2-seq-bind seg (%car auxen) (%cadr auxen)))
+
+(defun ppc2-initopt (seg vloc spvloc lcells splcells vars inits spvars)
+  (with-ppc-local-vinsn-macros (seg)
+    (dolist (var vars vloc)
+      (let* ((initform (pop inits))
+             (spvar (pop spvars))
+             (lcell (pop lcells))
+             (splcell (pop splcells))
+             (reg (nx2-assign-register-var var))
+             (sp-reg ($ ppc::arg_z))
+             (regloadedlabel (if reg (backend-get-next-label))))
+        (unless (nx-null initform)
+          (ppc2-stack-to-register seg (ppc2-vloc-ea spvloc) sp-reg)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (ppc2-compare-register-to-nil seg crf (ppc2-make-compound-cd 0 skipinitlabel) sp-reg  ppc::ppc-eq-bit t))
+            (if reg
+              (ppc2-form seg reg regloadedlabel initform)
+              (ppc2-register-to-stack seg (ppc2-one-untargeted-reg-form seg initform ($ ppc::arg_z)) (ppc2-vloc-ea vloc)))
+            (@ skipinitlabel)))
+        (if reg
+          (progn
+            (ppc2-init-regvar seg var reg (ppc2-vloc-ea vloc))
+            (@ regloadedlabel))
+          (ppc2-bind-var seg var vloc lcell))
+        (when spvar
+          (if (setq reg (nx2-assign-register-var spvar))
+            (ppc2-init-regvar seg spvar reg (ppc2-vloc-ea spvloc))
+            (ppc2-bind-var seg spvar spvloc splcell))))
+      (setq vloc (%i+ vloc *ppc2-target-node-size*))
+      (if spvloc (setq spvloc (%i+ spvloc *ppc2-target-node-size*))))))
+
+(defun ppc2-init-keys (seg vloc lcells allow-others keyvars keysupp keyinits keykeys)
+  (declare (ignore keykeys allow-others))
+  (with-ppc-local-vinsn-macros (seg)
+    (dolist (var keyvars)
+      (let* ((spvar (pop keysupp))
+             (initform (pop keyinits))
+             (reg (nx2-assign-register-var var))
+             (regloadedlabel (if reg (backend-get-next-label)))
+             (var-lcell (pop lcells))
+             (sp-lcell (pop lcells))
+             (sp-reg ($ ppc::arg_z))
+             (sploc (%i+ vloc *ppc2-target-node-size*)))
+        (unless (nx-null initform)
+          (ppc2-stack-to-register seg (ppc2-vloc-ea sploc) sp-reg)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (ppc2-compare-register-to-nil seg crf (ppc2-make-compound-cd 0 skipinitlabel) sp-reg  ppc::ppc-eq-bit t))
+            (if reg
+              (ppc2-form seg reg regloadedlabel initform)
+              (ppc2-register-to-stack seg (ppc2-one-untargeted-reg-form seg initform ($ ppc::arg_z)) (ppc2-vloc-ea vloc)))
+            (@ skipinitlabel)))
+        (if reg
+          (progn
+            (ppc2-init-regvar seg var reg (ppc2-vloc-ea vloc))
+            (@ regloadedlabel))
+          (ppc2-bind-var seg var vloc var-lcell))
+        (when spvar
+          (if (setq reg (nx2-assign-register-var spvar))
+            (ppc2-init-regvar seg spvar reg (ppc2-vloc-ea sploc))
+            (ppc2-bind-var seg spvar sploc sp-lcell))))
+      (setq vloc (%i+ vloc (* 2 *ppc2-target-node-size*))))))
+
+;;; Vpush register r, unless var gets a globally-assigned register.
+;;; Return NIL if register was vpushed, else var.
+(defun ppc2-vpush-arg-register (seg reg var)
+  (when var
+    (if (var-nvr var)
+      var
+      (progn 
+        (ppc2-vpush-register seg reg :reserved)
+        nil))))
+
+
+;;; nargs has been validated, arguments defaulted and canonicalized.
+;;; Save caller's context, then vpush any argument registers that
+;;; didn't get global registers assigned to their variables.
+;;; Return a list of vars/nils for each argument register 
+;;;  (nil if vpushed, var if still in arg_reg).
+(defun ppc2-argregs-entry (seg revargs)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((nargs (length revargs))
+           (reg-vars ()))
+      (declare (type (unsigned-byte 16) nargs))
+      (! save-lr)
+      (if (<= nargs $numppcargregs)       ; caller didn't vpush anything
+        (if *ppc2-open-code-inline*
+          (! save-lisp-context-vsp)
+          (! save-lisp-context-vsp-ool))
+        (let* ((offset (* (the fixnum (- nargs $numppcargregs)) *ppc2-target-node-size*)))
+          (declare (fixnum offset))
+          (if *ppc2-open-code-inline*
+            (! save-lisp-context-offset offset)
+            (! save-lisp-context-offset-ool offset))))
+      (destructuring-bind (&optional zvar yvar xvar &rest stack-args) revargs
+        (let* ((nstackargs (length stack-args)))
+          (ppc2-set-vstack (* nstackargs *ppc2-target-node-size*))
+          (dotimes (i nstackargs)
+            (ppc2-new-vstack-lcell :reserved *ppc2-target-lcell-size* 0 nil))
+          (if (>= nargs 3)
+            (push (ppc2-vpush-arg-register seg ($ ppc::arg_x) xvar) reg-vars))
+          (if (>= nargs 2)
+            (push (ppc2-vpush-arg-register seg ($ ppc::arg_y) yvar) reg-vars))
+          (if (>= nargs 1)
+            (push (ppc2-vpush-arg-register seg ($ ppc::arg_z) zvar) reg-vars))))
+      reg-vars)))
+
+;;; Just required args.
+;;; Since this is just a stupid bootstrapping port, always save 
+;;; lisp context.
+(defun ppc2-req-nargs-entry (seg rev-fixed-args)
+  (let* ((nargs (length rev-fixed-args)))
+    (declare (type (unsigned-byte 16) nargs))
+    (with-ppc-local-vinsn-macros (seg)
+      (unless *ppc2-reckless*
+        (! check-exact-nargs nargs))
+      (ppc2-argregs-entry seg rev-fixed-args))))
+
+;;; No more than three &optional args; all default to NIL and none have
+;;; supplied-p vars.  No &key/&rest.
+(defun ppc2-simple-opt-entry (seg rev-opt-args rev-req-args)
+  (let* ((min (length rev-req-args))
+         (nopt (length rev-opt-args))
+         (max (+ min nopt)))
+    (declare (type (unsigned-byte 16) min nopt max))
+    (with-ppc-local-vinsn-macros (seg)
+      (unless *ppc2-reckless*
+        (when rev-req-args
+          (! check-min-nargs min))
+        (! check-max-nargs max))
+      (if (= nopt 1)
+        (! default-1-arg min)
+        (if (= nopt 2)
+          (! default-2-args min)
+          (! default-3-args min)))
+      (ppc2-argregs-entry seg (append rev-opt-args rev-req-args)))))
+
+;;; if "num-fixed" is > 0, we've already ensured that at least that many args
+;;; were provided; that may enable us to generate better code for saving the
+;;; argument registers.
+;;; We're responsible for computing the caller's VSP and saving
+;;; caller's state.
+(defun ppc2-lexpr-entry (seg num-fixed)
+  (with-ppc-local-vinsn-macros (seg)
+    (! save-lexpr-argregs num-fixed)
+    (dotimes (i num-fixed)
+      (! copy-lexpr-argument))
+    (! save-lisp-context-lexpr)))
+
+(defun ppc2-load-lexpr-address (seg dest)
+  (with-ppc-local-vinsn-macros (seg)
+    (! load-vframe-address dest *ppc2-vstack*)))
+
+
+(defun ppc2-structured-initopt (seg lcells vloc context vars inits spvars)
+  (with-ppc-local-vinsn-macros (seg)
+    (dolist (var vars vloc)
+      (let* ((initform (pop inits))
+             (spvar (pop spvars))
+             (spvloc (%i+ vloc *ppc2-target-node-size*))
+             (var-lcell (pop lcells))
+             (sp-reg ($ ppc::arg_z))
+             (sp-lcell (pop lcells)))
+        (unless (nx-null initform)
+          (ppc2-stack-to-register seg (ppc2-vloc-ea spvloc) sp-reg)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (ppc2-compare-register-to-nil seg crf (ppc2-make-compound-cd 0 skipinitlabel) sp-reg ppc::ppc-eq-bit t))
+            (ppc2-register-to-stack seg (ppc2-one-untargeted-reg-form seg initform ($ ppc::arg_z)) (ppc2-vloc-ea vloc))
+            (@ skipinitlabel)))
+        (ppc2-bind-structured-var seg var vloc var-lcell context)
+        (when spvar
+          (ppc2-bind-var seg spvar spvloc sp-lcell)))
+      (setq vloc (%i+ vloc (* 2 *ppc2-target-node-size*))))))
+
+
+
+(defun ppc2-structured-init-keys (seg lcells vloc context allow-others keyvars keysupp keyinits keykeys)
+  (declare (ignore keykeys allow-others))
+  (with-ppc-local-vinsn-macros (seg)
+    (dolist (var keyvars)
+      (let* ((spvar (pop keysupp))
+             (initform (pop keyinits))
+             (sploc (%i+ vloc *ppc2-target-node-size*))
+             (var-lcell (pop lcells))
+             (sp-reg ($ ppc::arg_z))
+             (sp-lcell (pop lcells)))
+        (unless (nx-null initform)
+          (ppc2-stack-to-register seg (ppc2-vloc-ea sploc) sp-reg)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (ppc2-compare-register-to-nil seg crf (ppc2-make-compound-cd 0 skipinitlabel) sp-reg ppc::ppc-eq-bit t))
+            (ppc2-register-to-stack seg (ppc2-one-untargeted-reg-form seg initform ($ ppc::arg_z)) (ppc2-vloc-ea vloc))
+            (@ skipinitlabel)))
+        (ppc2-bind-structured-var seg var vloc var-lcell context)
+        (when spvar
+          (ppc2-bind-var seg spvar sploc sp-lcell)))
+      (setq vloc (%i+ vloc (* 2 *ppc2-target-node-size*))))))
+
+(defun ppc2-vloc-ea (n &optional vcell-p)
+  (setq n (make-memory-spec (dpb memspec-frame-address memspec-type-byte n)))
+  (if vcell-p
+    (make-vcell-memory-spec n)
+    n))
+
+
+(defun ppc2-acode-operator-function (form)
+  (or (and (acode-p form)
+           (svref *ppc2-specials* (%ilogand #.operator-id-mask (acode-operator form))))
+      (compiler-bug "ppc2-form ? ~s" form)))
+
+(defmacro with-note ((form-var seg-var &rest other-vars) &body body)
+  (let* ((note (gensym "NOTE"))
+         (code-note (gensym "CODE-NOTE"))
+         (source-note (gensym "SOURCE-NOTE"))
+         (start (gensym "START"))
+         (end (gensym "END"))
+         (with-note-body (gensym "WITH-NOTE-BODY")))
+    `(flet ((,with-note-body (,form-var ,seg-var ,@other-vars) ,@body))
+       (let ((,note (acode-note ,form-var)))
+         (if ,note
+           (let* ((,code-note (and (code-note-p ,note) ,note))
+                  (,source-note (if ,code-note
+                                  (code-note-source-note ,note)
+                                  ,note))
+                  (,start (and ,source-note
+                               (ppc2-emit-note ,seg-var :source-location-begin ,source-note))))
+             (prog2
+                 (when ,code-note
+                   (with-ppc-local-vinsn-macros (,seg-var)
+                     (ppc2-store-immediate ,seg-var ,code-note ppc::temp0)
+                     (! misc-set-c-node ($ ppc::rzero) ($ ppc::temp0) 1)))
+                 (,with-note-body ,form-var ,seg-var ,@other-vars)
+               (when ,source-note
+                 (let ((,end (ppc2-emit-note ,seg-var :source-location-end)))
+                   (setf (vinsn-note-peer ,start) ,end
+                         (vinsn-note-peer ,end) ,start)
+                   (push ,start *ppc2-emitted-source-notes*)))))
+           (,with-note-body ,form-var ,seg-var ,@other-vars))))))
+
+(defun ppc2-toplevel-form (seg vreg xfer form)
+  (let* ((code-note (acode-note form))
+         (args (if code-note `(,@(%cdr form) ,code-note) (%cdr form))))
+    (apply (ppc2-acode-operator-function form) seg vreg xfer args)))
+
+(defun ppc2-form (seg vreg xfer form)
+  (with-note (form seg vreg xfer)
+    (if (nx-null form)
+      (ppc2-nil seg vreg xfer)
+      (if (nx-t form)
+        (ppc2-t seg vreg xfer)
+        (let ((fn (ppc2-acode-operator-function form))
+              (op (acode-operator form)))
+          (if (and (null vreg)
+                   (%ilogbitp operator-acode-subforms-bit op)
+                   (%ilogbitp operator-assignment-free-bit op))
+            (dolist (f (%cdr form) (ppc2-branch seg xfer nil))
+              (ppc2-form seg nil nil f ))
+            (apply fn seg vreg xfer (%cdr form))))))))
+
+;;; dest is a float reg - form is acode
+(defun ppc2-form-float (seg freg xfer form)
+  (declare (ignore xfer))
+  (with-note (form seg freg)
+    (when (or (nx-null form)(nx-t form))(compiler-bug "ppc2-form to freg ~s" form))
+    (when (and (= (get-regspec-mode freg) hard-reg-class-fpr-mode-double)
+               (ppc2-form-typep form 'double-float))
+                                        ; kind of screwy - encoding the source type in the dest register spec
+      (set-node-regspec-type-modes freg hard-reg-class-fpr-type-double))
+    (let* ((fn (ppc2-acode-operator-function form)))
+      (apply fn seg freg nil (%cdr form)))))
+
+
+
+(defun ppc2-form-typep (form type)
+  (acode-form-typep form type *ppc2-trust-declarations*)
+)
+
+(defun ppc2-form-type (form)
+  (acode-form-type form *ppc2-trust-declarations*))
+  
+(defun ppc2-use-operator (op seg vreg xfer &rest forms)
+  (declare (dynamic-extent forms))
+  (apply (svref *ppc2-specials* (%ilogand operator-id-mask op)) seg vreg xfer forms))
+
+;;; Returns true iff lexical variable VAR isn't setq'ed in FORM.
+;;; Punts a lot ...
+(defun ppc2-var-not-set-by-form-p (var form)
+  (or (not (%ilogbitp $vbitsetq (nx-var-bits var)))
+      (ppc2-setqed-var-not-set-by-form-p var form)))
+
+(defun ppc2-setqed-var-not-set-by-form-p (var form)
+  (setq form (acode-unwrapped-form form))
+  (or (atom form)
+      (ppc-constant-form-p form)
+      (ppc2-lexical-reference-p form)
+      (let ((op (acode-operator form))
+            (subforms nil))
+        (if (eq op (%nx1-operator setq-lexical))
+          (and (neq var (cadr form))
+               (ppc2-setqed-var-not-set-by-form-p var (caddr form)))
+          (and (%ilogbitp operator-side-effect-free-bit op)
+               (flet ((not-set-in-formlist (formlist)
+                        (dolist (subform formlist t)
+                          (unless (ppc2-setqed-var-not-set-by-form-p var subform) (return)))))
+                 (if
+                   (cond ((%ilogbitp operator-acode-subforms-bit op) (setq subforms (%cdr form)))
+                         ((%ilogbitp operator-acode-list-bit op) (setq subforms (cadr form))))
+                   (not-set-in-formlist subforms)
+                   (and (or (eq op (%nx1-operator call))
+                            (eq op (%nx1-operator lexical-function-call)))
+                        (ppc2-setqed-var-not-set-by-form-p var (cadr form))
+                        (setq subforms (caddr form))
+                        (not-set-in-formlist (car subforms))
+                        (not-set-in-formlist (cadr subforms))))))))))
+  
+(defun ppc2-nil (seg vreg xfer)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if (ppc2-for-value-p vreg)
+      (ensuring-node-target (target vreg)
+        (! load-nil target)))
+    (ppc2-branch seg (ppc2-cd-false xfer) vreg)))
+
+(defun ppc2-t (seg vreg xfer)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if (ppc2-for-value-p vreg)
+      (ensuring-node-target (target vreg)
+        (! load-t target)))
+    (ppc2-branch seg (ppc2-cd-true xfer) vreg)))
+
+(defun ppc2-for-value-p (vreg)
+  (and vreg (not (backend-crf-p vreg))))
+
+(defun ppc2-mvpass (seg form &optional xfer)
+  (with-ppc-local-vinsn-macros (seg)
+    (ppc2-form seg  ($ ppc::arg_z) (logior (or xfer 0) $backend-mvpass-mask) form)))
+
+(defun ppc2-adjust-vstack (delta)
+  (ppc2-set-vstack (%i+ *ppc2-vstack* delta)))
+
+(defun ppc2-set-vstack (new)
+  (setq *ppc2-vstack* new))
+
+
+;;; Emit a note at the end of the segment.
+(defun ppc2-emit-note (seg class &rest info)
+  (declare (dynamic-extent info))
+  (let* ((note (make-vinsn-note class info)))
+    (append-dll-node (vinsn-note-label note) seg)
+    note))
+
+;;; Emit a note immediately before the target vinsn.
+(defun ppc-prepend-note (vinsn class &rest info)
+  (declare (dynamic-extent info))
+  (let* ((note (make-vinsn-note class info)))
+    (insert-dll-node-before (vinsn-note-label note) vinsn)
+    note))
+
+(defun ppc2-close-note (seg note)
+  (let* ((end (close-vinsn-note note)))
+    (append-dll-node (vinsn-note-label end) seg)
+    end))
+
+
+
+
+
+
+(defun ppc2-stack-to-register (seg memspec reg)
+  (with-ppc-local-vinsn-macros (seg)
+    (! vframe-load reg (memspec-frame-address-offset memspec) *ppc2-vstack*)))
+
+(defun ppc2-lcell-to-register (seg lcell reg)
+  (with-ppc-local-vinsn-macros (seg)
+    (! lcell-load reg lcell (ppc2-vstack-mark-top))))
+
+(defun ppc2-register-to-lcell (seg reg lcell)
+  (with-ppc-local-vinsn-macros (seg)
+    (! lcell-store reg lcell (ppc2-vstack-mark-top))))
+
+(defun ppc2-register-to-stack (seg reg memspec)
+  (with-ppc-local-vinsn-macros (seg)
+    (! vframe-store reg (memspec-frame-address-offset memspec) *ppc2-vstack*)))
+
+
+(defun ppc2-ea-open (ea)
+  (if (and ea (not (typep ea 'lreg)) (addrspec-vcell-p ea))
+    (make-memory-spec (memspec-frame-address-offset ea))
+    ea))
+
+(defun ppc2-set-NARGS (seg n)
+  (if (> n call-arguments-limit)
+    (compiler-bug "~s exceeded." call-arguments-limit)
+    (with-ppc-local-vinsn-macros (seg)
+      (! set-nargs n))))
+
+(defun ppc2-single-float-bits (the-sf)
+  (single-float-bits the-sf))
+
+(defun ppc2-double-float-bits (the-df)
+  (double-float-bits the-df))
+
+(defun ppc2-immediate (seg vreg xfer form)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+               (or (and (typep form 'double-float) (= (get-regspec-mode vreg) hard-reg-class-fpr-mode-double))
+                   (and (typep form 'short-float)(= (get-regspec-mode vreg) hard-reg-class-fpr-mode-single))))
+        (if (zerop form)
+          (if (eql form 0.0d0)
+            (! zero-double-float-register vreg)
+            (! zero-single-float-register vreg))
+          (if (typep form 'short-float)
+            (let* ((bits (ppc2-single-float-bits form)))
+              (with-imm-temps () ((bitsreg :u32))
+                (! lri bitsreg bits)
+                (! load-single-float-constant vreg bitsreg)))
+            (multiple-value-bind (high low) (ppc2-double-float-bits form)
+              (declare (integer high low))
+              (with-imm-temps () ((highreg :u32) (lowreg :u32))
+                (if (zerop high)
+                  (setq highreg ($ ppc::rzero))
+                  (! lri highreg high))
+                (if (zerop low)
+                  (setq lowreg ($ ppc::rzero))
+                  (! lri lowreg low))
+                (! load-double-float-constant vreg highreg lowreg)))))
+        (if (and (typep form '(unsigned-byte 32))
+                 (= (hard-regspec-class vreg) hard-reg-class-gpr)
+                 (= (get-regspec-mode vreg)
+                    hard-reg-class-gpr-mode-u32))
+          (ppc2-lri seg vreg form)
+          (ensuring-node-target
+           (target vreg)
+           (if (characterp form)
+             (! load-character-constant target (char-code form))
+             (ppc2-store-immediate seg form target)))))
+      (if (and (listp form) *load-time-eval-token* (eq (car form) *load-time-eval-token*))
+        (ppc2-store-immediate seg form ($ ppc::temp0))))
+    (^)))
+
+(defun ppc2-register-constant-p (form)
+  (and (consp form)
+           (or (memq form *ppc2-vcells*)
+               (memq form *ppc2-fcells*))
+           (%cdr form)))
+
+(defun ppc2-store-immediate (seg imm dest)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((reg (ppc2-register-constant-p imm)))
+      (if reg
+        (ppc2-copy-register seg dest reg)
+        (let* ((idx (backend-immediate-index imm)))
+          (target-arch-case
+           (:ppc32
+            (if (< idx 8192)
+              (! ref-constant dest idx)
+              (with-imm-target () (idxreg :s32)
+                (ppc2-lri seg idxreg (+ ppc32::misc-data-offset (ash (1+ idx) 2)))
+                (! ref-indexed-constant dest idxreg))))
+           (:ppc64
+            (if (< idx 4096)
+              (! ref-constant dest idx)
+              (with-imm-target () (idxreg :s64)
+                (ppc2-lri seg idxreg (+ ppc64::misc-data-offset (ash (1+ idx) 3)))
+                (! ref-indexed-constant dest idxreg)))))))
+      dest)))
+
+
+;;; Returns label iff form is (local-go <tag>) and can go without adjusting stack.
+(defun ppc2-go-label (form)
+  (let ((current-stack (ppc2-encode-stack)))
+    (while (and (acode-p form) (or (eq (acode-operator form) (%nx1-operator progn))
+                                   (eq (acode-operator form) (%nx1-operator local-tagbody))))
+      (setq form (caadr form)))
+    (when (acode-p form)
+      (let ((op (acode-operator form)))
+        (if (and (eq op (%nx1-operator local-go))
+                 (ppc2-equal-encodings-p (%caddr (%cadr form)) current-stack))
+          (%cadr (%cadr form))
+          (if (and (eq op (%nx1-operator local-return-from))
+                   (nx-null (caddr form)))
+            (let ((tagdata (car (cadr form))))
+              (and (ppc2-equal-encodings-p (cdr tagdata) current-stack)
+                   (null (caar tagdata))
+                   (< 0 (cdar tagdata) $backend-mvpass)
+                   (cdar tagdata)))))))))
+
+(defun ppc2-single-valued-form-p (form)
+  (setq form (acode-unwrapped-form-value form))
+  (or (nx-null form)
+      (nx-t form)
+      (if (acode-p form)
+        (let ((op (acode-operator form)))
+          (or (%ilogbitp operator-single-valued-bit op)
+              (and (eql op (%nx1-operator values))
+                   (let ((values (cadr form)))
+                     (and values (null (cdr values)))))
+              nil                       ; Learn about functions someday
+              )))))
+
+
+(defun ppc2-box-s32 (seg node-dest s32-src)
+  (with-ppc-local-vinsn-macros (seg)
+    (if (target-arch-case
+         (:ppc32 *ppc2-open-code-inline*)
+         (:ppc64 t))
+      (! s32->integer node-dest s32-src)
+      (let* ((arg_z ($ ppc::arg_z))
+             (imm0 ($ ppc::imm0 :mode :s32)))
+        (ppc2-copy-register seg imm0 s32-src)
+        (! call-subprim (subprim-name->offset '.SPmakes32))
+        (ppc2-copy-register seg node-dest arg_z)))))
+
+(defun ppc2-box-s64 (seg node-dest s64-src)
+  (with-ppc-local-vinsn-macros (seg)
+    (if (target-arch-case
+         (:ppc32 (compiler-bug "Bug!"))
+         (:ppc64 *ppc2-open-code-inline*))
+      (! s64->integer node-dest s64-src)
+      (let* ((arg_z ($ ppc::arg_z))
+             (imm0 ($ ppc::imm0 :mode :s64)))
+        (ppc2-copy-register seg imm0 s64-src)
+        (! call-subprim (subprim-name->offset '.SPmakes64))
+        (ppc2-copy-register seg node-dest arg_z)))))
+
+(defun ppc2-box-u32 (seg node-dest u32-src)
+  (with-ppc-local-vinsn-macros (seg)
+    (if (target-arch-case
+         (:ppc32 *ppc2-open-code-inline*)
+         (:ppc64 t))
+      (! u32->integer node-dest u32-src)
+      (let* ((arg_z ($ ppc::arg_z))
+             (imm0 ($ ppc::imm0 :mode :u32)))
+        (ppc2-copy-register seg imm0 u32-src)
+        (! call-subprim (subprim-name->offset '.SPmakeu32))
+        (ppc2-copy-register seg node-dest arg_z)))))
+
+(defun ppc2-box-u64 (seg node-dest u64-src)
+  (with-ppc-local-vinsn-macros (seg)
+    (if (target-arch-case
+         (:ppc32 (compiler-bug "Bug!"))
+         (:ppc64 *ppc2-open-code-inline*))
+      (! u64->integer node-dest u64-src)
+      (let* ((arg_z ($ ppc::arg_z))
+             (imm0 ($ ppc::imm0 :mode :u64)))
+        (ppc2-copy-register seg imm0 u64-src)
+        (! call-subprim (subprim-name->offset '.SPmakeu64))
+        (ppc2-copy-register seg node-dest arg_z)))))
+
+(defun ppc2-vref1 (seg vreg xfer type-keyword src unscaled-idx index-known-fixnum)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (let* ((arch (backend-target-arch *target-backend*))
+             (is-node (member type-keyword (arch::target-gvector-types arch)))
+             (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
+
+             (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+             (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+             (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+             (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+             (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
+             (vreg-class (hard-regspec-class vreg))
+             (vreg-mode
+              (if (or (eql vreg-class hard-reg-class-gpr)
+                      (eql vreg-class hard-reg-class-fpr))
+                (get-regspec-mode vreg)
+                hard-reg-class-gpr-mode-invalid))
+             (temp-is-vreg nil))
+        (cond
+          (is-node
+           (ensuring-node-target (target vreg)
+             (if (and index-known-fixnum (<= index-known-fixnum
+                                             (target-word-size-case
+                                              (32 (arch::target-max-32-bit-constant-index arch))
+                                              (64 (arch::target-max-64-bit-constant-index arch)))))
+               (! misc-ref-c-node target src index-known-fixnum)
+               (with-imm-target () (idx-reg :u64)
+                 (if index-known-fixnum
+                   (ppc2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum *ppc2-target-node-shift*)))
+                   (! scale-node-misc-index idx-reg unscaled-idx))
+                 (! misc-ref-node target src idx-reg)))))
+          (is-32-bit
+           (with-imm-target () (temp :u32)
+             (with-fp-target () (fp-val :single-float)
+               (if (eql vreg-class hard-reg-class-gpr)
+                 (if
+                   (if is-signed
+                     (or (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                         (eql vreg-mode hard-reg-class-gpr-mode-s64))
+                     (or (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                         (eql vreg-mode hard-reg-class-gpr-mode-u64)))
+                   (setq temp vreg temp-is-vreg t)
+                   (if is-signed
+                     (set-regspec-mode temp hard-reg-class-gpr-mode-s32)))
+                 (if (and (eql vreg-class hard-reg-class-fpr)
+                          (eql vreg-mode hard-reg-class-fpr-mode-single))
+                   (setf fp-val vreg temp-is-vreg t)))
+               (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-32-bit-constant-index arch)))
+                 (cond ((eq type-keyword :single-float-vector)
+                        (! misc-ref-c-single-float fp-val src index-known-fixnum))
+                       (t
+                        (if is-signed
+                          (! misc-ref-c-s32 temp src index-known-fixnum)
+                          (! misc-ref-c-u32 temp src index-known-fixnum)))))
+               (with-imm-target () idx-reg
+                 (if index-known-fixnum
+                   (ppc2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 2)))
+                   (! scale-32bit-misc-index idx-reg unscaled-idx))
+                 (cond ((eq type-keyword :single-float-vector)
+                        (! misc-ref-single-float fp-val src idx-reg))
+                       (t
+                        (if is-signed
+                          (! misc-ref-s32 temp src idx-reg)
+                          (! misc-ref-u32 temp src idx-reg)))))
+               (case type-keyword
+                 (:single-float-vector
+                  (if (eq vreg-class hard-reg-class-fpr)
+                    (<- fp-val)
+                    (ensuring-node-target (target vreg)
+                      (! single->node target fp-val))))
+                 (:signed-32-bit-vector
+                  (unless temp-is-vreg
+                    (ensuring-node-target (target vreg)
+                      (ppc2-box-s32 seg target temp))))
+                 (:fixnum-vector
+                  (unless temp-is-vreg
+                    (ensuring-node-target (target vreg)
+                      (! box-fixnum target temp))))
+                 (:simple-string
+                  (ensuring-node-target (target vreg)
+                    (! u32->char target temp)))
+                 (t
+                  (unless temp-is-vreg
+                    (ensuring-node-target (target vreg)
+                      (ppc2-box-u32 seg target temp))))))))
+          (is-8-bit
+           (with-imm-target () (temp :u8)
+             (if (and (eql vreg-class hard-reg-class-gpr)
+                      (or
+                       (and is-signed
+                            (or (eql vreg-mode hard-reg-class-gpr-mode-s8)
+                                (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                (eql vreg-mode hard-reg-class-gpr-mode-s64)))
+                       (and (not is-signed)
+                            (or (eql vreg-mode hard-reg-class-gpr-mode-u8)
+                                (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                (eql vreg-mode hard-reg-class-gpr-mode-u16)
+                                (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                                (eql vreg-mode hard-reg-class-gpr-mode-s64)
+                                (eql vreg-mode hard-reg-class-gpr-mode-u64)))))
+               (setq temp vreg temp-is-vreg t)
+               (if is-signed
+                 (set-regspec-mode temp hard-reg-class-gpr-mode-s8)))
+             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-8-bit-constant-index arch)))
+               (if is-signed
+                 (! misc-ref-c-s8 temp src index-known-fixnum)
+                 (! misc-ref-c-u8 temp src index-known-fixnum))
+               (with-imm-target () idx-reg
+                 (if index-known-fixnum
+                   (ppc2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) index-known-fixnum))
+                   (! scale-8bit-misc-index idx-reg unscaled-idx))
+                 (if is-signed
+                   (! misc-ref-s8 temp src idx-reg)
+                   (! misc-ref-u8 temp src idx-reg))))
+             (ecase type-keyword
+               (:unsigned-8-bit-vector
+                (unless temp-is-vreg
+                  (ensuring-node-target (target vreg)
+                    (! box-fixnum target temp))))
+               (:signed-8-bit-vector
+                (unless temp-is-vreg
+                  (ensuring-node-target (target vreg)
+                    (! box-fixnum target temp))))
+               (:simple-string
+                (ensuring-node-target (target vreg)
+                  (! u32->char target temp))))))
+          (is-16-bit
+           (ensuring-node-target (target vreg)
+             (with-imm-target () temp
+               (if (and index-known-fixnum
+                        (<= index-known-fixnum (arch::target-max-16-bit-constant-index arch)))
+                 (if is-signed
+                   (! misc-ref-c-s16 temp src index-known-fixnum)
+                   (! misc-ref-c-u16 temp src index-known-fixnum))
+                 (with-imm-target () idx-reg
+                   (if index-known-fixnum
+                     (ppc2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 1)))
+                     (! scale-16bit-misc-index idx-reg unscaled-idx))
+                   (if is-signed
+                     (! misc-ref-s16 temp src idx-reg)
+                     (! misc-ref-u16 temp src idx-reg))))
+               (! box-fixnum target temp))))
+          (is-64-bit
+           (with-fp-target () (fp-val :double-float)
+             (with-imm-target () (temp :u64)
+               (if (and (eql vreg-class hard-reg-class-fpr)
+                        (eql vreg-mode hard-reg-class-fpr-mode-double))
+                 (setq fp-val vreg)
+                 (if (eql vreg-class hard-reg-class-gpr)
+                   (if (or (and is-signed
+                                (eql vreg-mode hard-reg-class-gpr-mode-s64))
+                           (and (not is-signed)
+                                (eql vreg-mode hard-reg-class-gpr-mode-u64)))
+                     (setf temp vreg temp-is-vreg t)
+                     (if is-signed
+                       (set-regspec-mode temp hard-reg-class-gpr-mode-s64)))))
+               (case type-keyword
+                 (:double-float-vector
+                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+                    (! misc-ref-c-double-float fp-val src index-known-fixnum)
+                    (with-imm-target () idx-reg
+                      (if index-known-fixnum
+                        (ppc2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3)))
+                        (! scale-64bit-misc-index idx-reg unscaled-idx))
+                      (! misc-ref-double-float fp-val src idx-reg)))
+                  (if (eq vreg-class hard-reg-class-fpr)
+                    (<- fp-val)
+                    (ensuring-node-target (target vreg)
+                      (! double->heap target fp-val))))
+                 ((:signed-64-bit-vector :fixnum-vector)
+                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+                    (! misc-ref-c-s64 temp src index-known-fixnum)
+                    (with-imm-target () idx-reg
+                      (if index-known-fixnum
+                        (ppc2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3)))
+                        (! scale-64bit-misc-index idx-reg unscaled-idx))
+                      (! misc-ref-s64 temp src idx-reg)))
+                  (if (eq type-keyword :fixnum-vector)
+                    (ensuring-node-target (target vreg)
+                      (! box-fixnum target temp))
+                    (unless temp-is-vreg
+                      (ensuring-node-target (target vreg)
+                        (! s64->integer target temp)))))
+                 (t
+                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+                    (! misc-ref-c-u64 temp src index-known-fixnum)
+                    (with-imm-target () idx-reg
+                      (if index-known-fixnum
+                        (ppc2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3)))
+                        (! scale-64bit-misc-index idx-reg unscaled-idx))
+                      (! misc-ref-u64  temp src idx-reg)))
+                  (unless temp-is-vreg
+                    (ensuring-node-target (target vreg)
+                      (! u64->integer target temp))))))))
+          (t
+           (unless is-1-bit
+             (nx-error "~& unsupported vector type: ~s"
+                       type-keyword))
+           (ensuring-node-target (target vreg)
+             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-1-bit-constant-index arch)))
+               (! misc-ref-c-bit-fixnum target src index-known-fixnum)
+               (with-imm-temps
+                   () (word-index bitnum dest)
+                 (if index-known-fixnum
+                   (progn
+                     (ppc2-lri seg word-index (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum -5)))
+                     (ppc2-lri seg bitnum (logand index-known-fixnum #x1f)))
+                   (! scale-1bit-misc-index word-index bitnum unscaled-idx))
+                 (! misc-ref-u32 dest src word-index)
+                 (! extract-variable-bit-fixnum target dest bitnum))))))))
+    (^)))
+             
+    
+
+;;; safe = T means assume "vector" is miscobj, do bounds check.
+;;; safe = fixnum means check that subtag of vector = "safe" and do
+;;;        bounds check.
+;;; safe = nil means crash&burn.
+;;; This mostly knows how to reference the elements of an immediate miscobj.
+(defun ppc2-vref (seg vreg xfer type-keyword vector index safe)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((index-known-fixnum (acode-fixnum-form-p index))
+           (unscaled-idx nil)
+           (src nil))
+      (if (or safe (not index-known-fixnum))
+        (multiple-value-setq (src unscaled-idx)
+          (ppc2-two-untargeted-reg-forms seg vector ppc::arg_y index ppc::arg_z))
+        (setq src (ppc2-one-untargeted-reg-form seg vector ppc::arg_z)))
+      (when safe
+        (if (typep safe 'fixnum)
+          (! trap-unless-typecode= src safe))
+        (unless index-known-fixnum
+          (! trap-unless-fixnum unscaled-idx))
+        (! check-misc-bound unscaled-idx src))
+      (ppc2-vref1 seg vreg xfer type-keyword src unscaled-idx index-known-fixnum))))
+
+
+
+(defun ppc2-aset2 (seg vreg xfer  array i j new safe type-keyword dim0 dim1)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (constval (ppc2-constant-value-ok-for-type-keyword type-keyword new))
+           (needs-memoization (and is-node (ppc2-acode-needs-memoization new)))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (val-reg (ppc2-target-reg-for-aset vreg type-keyword))
+           (constidx
+            (and dim0 dim1 i-known-fixnum j-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (+ (* i-known-fixnum dim1) j-known-fixnum))))
+      (progn
+        (if constidx
+          (multiple-value-setq (src val-reg)
+            (ppc2-two-targeted-reg-forms seg array ($ ppc::temp0) new val-reg))
+          (multiple-value-setq (src unscaled-i unscaled-j val-reg)
+            (if needs-memoization
+              (progn
+                (ppc2-four-targeted-reg-forms seg
+                                                array ($ ppc::temp0)
+                                                i ($ ppc::arg_x)
+                                                j ($ ppc::arg_y)
+                                                new val-reg)
+                (values ($ ppc::temp0) ($ ppc::arg_x) ($ ppc::arg_y) ($ ppc::arg_z)))
+            (ppc2-four-untargeted-reg-forms seg
+                                            array ($ ppc::temp0)
+                                            i ($ ppc::arg_x)
+                                            j ($ ppc::arg_y)
+                                            new val-reg))))
+        (let* ((*available-backend-imm-temps* *available-backend-imm-temps*))
+          (when (and (= (hard-regspec-class val-reg) hard-reg-class-gpr)
+                     (logbitp (hard-regspec-value val-reg)
+                              *backend-imm-temps*))
+            (use-imm-temp (hard-regspec-value val-reg)))
+          (when safe      
+            (when (typep safe 'fixnum)
+              (! trap-unless-simple-array-2
+                 src
+                 (dpb safe target::arrayH.flags-cell-subtag-byte
+                      (ash 1 $arh_simple_bit))
+                 (nx-error-for-simple-2d-array-type type-keyword)))
+            (unless i-known-fixnum
+              (! trap-unless-fixnum unscaled-i))
+            (unless j-known-fixnum
+              (! trap-unless-fixnum unscaled-j)))
+          (with-imm-target () dim1
+            (let* ((idx-reg ($ ppc::arg_y)))
+              (unless constidx
+                (if safe                  
+                  (! check-2d-bound dim1 unscaled-i unscaled-j src)
+                  (! 2d-dim1 dim1 src))
+                (! 2d-unscaled-index idx-reg dim1 unscaled-i unscaled-j))
+              (let* ((v ($ ppc::arg_x)))
+                (! array-data-vector-ref v src)
+                (ppc2-vset1 seg vreg xfer type-keyword v idx-reg constidx val-reg (ppc2-unboxed-reg-for-aset seg type-keyword val-reg safe constval) constval needs-memoization)))))))))
+
+
+(defun ppc2-aset3 (seg vreg xfer  array i j k new safe type-keyword  dim0 dim1 dim2)
+  (with-ppc-local-vinsn-macros (seg target)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (k-known-fixnum (acode-fixnum-form-p k))
+           (arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (constval (ppc2-constant-value-ok-for-type-keyword type-keyword new))
+           (needs-memoization (and is-node (ppc2-acode-needs-memoization new)))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (unscaled-k)
+           (val-reg (ppc2-target-reg-for-aset vreg type-keyword))
+           (constidx
+            (and dim0 dim1 dim2 i-known-fixnum j-known-fixnum k-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (>= k-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (< k-known-fixnum dim2)
+                 (+ (* i-known-fixnum dim1 dim2)
+                    (* j-known-fixnum dim2)
+                    k-known-fixnum))))
+      (progn
+        (if constidx
+          (multiple-value-setq (src val-reg)
+            (ppc2-two-targeted-reg-forms seg array ($ ppc::temp0) new val-reg))
+          (progn
+            (setq src ($ ppc::temp1)
+                  unscaled-i ($ ppc::temp0)
+                  unscaled-j ($ ppc::arg_x)
+                  unscaled-k ($ ppc::arg_y))
+            (ppc2-push-register
+             seg
+             (ppc2-one-untargeted-reg-form seg array ($ ppc::arg_z)))
+            (ppc2-four-targeted-reg-forms seg
+                                          i ($ ppc::temp0)
+                                          j ($ ppc::arg_x)
+                                          k ($ ppc::arg_y)
+                                          new val-reg)
+            (ppc2-pop-register seg src)))
+        (let* ((*available-backend-imm-temps* *available-backend-imm-temps*))
+          (when (and (= (hard-regspec-class val-reg) hard-reg-class-gpr)
+                     (logbitp (hard-regspec-value val-reg)
+                              *backend-imm-temps*))
+            (use-imm-temp (hard-regspec-value val-reg)))
+
+          (when safe      
+            (when (typep safe 'fixnum)
+              (! trap-unless-simple-array-3
+                 src
+                 (dpb safe target::arrayH.flags-cell-subtag-byte
+                      (ash 1 $arh_simple_bit))
+                 (nx-error-for-simple-3d-array-type type-keyword)))
+            (unless i-known-fixnum
+              (! trap-unless-fixnum unscaled-i))
+            (unless j-known-fixnum
+              (! trap-unless-fixnum unscaled-j))
+            (unless k-known-fixnum
+              (! trap-unless-fixnum unscaled-k)))
+          (with-imm-target () dim1
+            (with-imm-target (dim1) dim2
+              (let* ((idx-reg ($ ppc::arg_y)))
+                (unless constidx
+                  (if safe                  
+                    (! check-3d-bound dim1 dim2 unscaled-i unscaled-j unscaled-k src)
+                    (! 3d-dims dim1 dim2 src))
+                  (! 3d-unscaled-index idx-reg dim1 dim2 unscaled-i unscaled-j unscaled-k))
+                (let* ((v ($ ppc::arg_x)))
+                  (! array-data-vector-ref v src)
+                  (ppc2-vset1 seg vreg xfer type-keyword v idx-reg constidx val-reg (ppc2-unboxed-reg-for-aset seg type-keyword val-reg safe constval) constval needs-memoization))))))))))
+
+(defun ppc2-aref2 (seg vreg xfer array i j safe typekeyword &optional dim0 dim1)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (constidx
+            (and dim0 dim1 i-known-fixnum j-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (+ (* i-known-fixnum dim1) j-known-fixnum))))
+      (if constidx
+        (setq src (ppc2-one-targeted-reg-form seg array ($ ppc::arg_z)))
+        (multiple-value-setq (src unscaled-i unscaled-j)
+          (ppc2-three-untargeted-reg-forms seg
+                                           array ppc::arg_x
+                                           i ppc::arg_y
+                                           j ppc::arg_z)))
+      (when safe        
+        (when (typep safe 'fixnum)
+          (! trap-unless-simple-array-2
+             src
+             (dpb safe target::arrayH.flags-cell-subtag-byte
+                  (ash 1 $arh_simple_bit))
+             (nx-error-for-simple-2d-array-type typekeyword)))
+        (unless i-known-fixnum
+          (! trap-unless-fixnum unscaled-i))
+        (unless j-known-fixnum
+          (! trap-unless-fixnum unscaled-j)))
+      (with-node-target (src) idx-reg
+        (with-imm-target () dim1
+          (unless constidx
+            (if safe                    
+              (! check-2d-bound dim1 unscaled-i unscaled-j src)
+              (! 2d-dim1 dim1 src))
+            (! 2d-unscaled-index idx-reg dim1 unscaled-i unscaled-j))
+          (with-node-target (idx-reg) v
+            (! array-data-vector-ref v src)
+            (ppc2-vref1 seg vreg xfer typekeyword v idx-reg constidx)))))))
+
+
+
+(defun ppc2-aref3 (seg vreg xfer array i j k safe typekeyword &optional dim0 dim1 dim2)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (k-known-fixnum (acode-fixnum-form-p k))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (unscaled-k)
+           (constidx
+            (and dim0 dim1 i-known-fixnum j-known-fixnum k-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (>= k-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (< k-known-fixnum dim2)
+                 (+ (* i-known-fixnum dim1 dim2)
+                    (* j-known-fixnum dim2)
+                    k-known-fixnum))))
+      (if constidx
+        (setq src (ppc2-one-targeted-reg-form seg array ($ ppc::arg_z)))
+        (multiple-value-setq (src unscaled-i unscaled-j unscaled-k)
+          (ppc2-four-untargeted-reg-forms seg
+                                           array ppc::temp0
+                                           i ppc::arg_x
+                                           j ppc::arg_y
+                                           k ppc::arg_z)))
+      (when safe        
+        (when (typep safe 'fixnum)
+          (! trap-unless-simple-array-3
+             src
+             (dpb safe target::arrayH.flags-cell-subtag-byte
+                  (ash 1 $arh_simple_bit))
+             (nx-error-for-simple-3d-array-type typekeyword)))
+        (unless i-known-fixnum
+          (! trap-unless-fixnum unscaled-i))
+        (unless j-known-fixnum
+          (! trap-unless-fixnum unscaled-j))
+        (unless k-known-fixnum
+          (! trap-unless-fixnum unscaled-k)))
+      (with-node-target (src) idx-reg
+        (with-imm-target () dim1
+          (with-imm-target (dim1) dim2
+            (unless constidx
+              (if safe                    
+                (! check-3d-bound dim1 dim2 unscaled-i unscaled-j unscaled-k src)
+                (! 3d-dims dim1 dim2 src))
+              (! 3d-unscaled-index idx-reg dim1 dim2 unscaled-i unscaled-j unscaled-k))))
+        (with-node-target (idx-reg) v
+          (! array-data-vector-ref v src)
+          (ppc2-vref1 seg vreg xfer typekeyword v idx-reg constidx))))))
+
+
+(defun ppc2-constant-value-ok-for-type-keyword (type-keyword form)
+  (if (and (acode-p (setq form (acode-unwrapped-form form)))
+           (or (eq (acode-operator form) (%nx1-operator immediate))
+               (eq (acode-operator form) (%nx1-operator fixnum))))
+    (let* ((val (%cadr form))
+           (typep (cond ((eq type-keyword :signed-32-bit-vector)
+                         (typep val '(signed-byte 32)))
+                        ((eq type-keyword :single-float-vector)
+                         (typep val 'short-float))
+                        ((eq type-keyword :double-float-vector)
+                         (typep val 'double-float))
+                        ((eq type-keyword :simple-string)
+                         (typep val 'base-char))
+                        ((eq type-keyword :signed-8-bit-vector)
+                         (typep val '(signed-byte 8)))
+                        ((eq type-keyword :unsigned-8-bit-vector)
+                         (typep val '(unsigned-byte 8)))
+                        ((eq type-keyword :signed-16-bit-vector) 
+                         (typep val '(signed-byte 16)))
+                        ((eq type-keyword :unsigned-16-bit-vector)
+                         (typep val '(unsigned-byte 16)))
+                        ((eq type-keyword :bit-vector)
+                         (typep val 'bit)))))
+      (if typep val))))
+
+(defun ppc2-target-reg-for-aset (vreg type-keyword)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (is-node (member type-keyword (arch::target-gvector-types arch)))
+         (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
+         (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+         (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+         (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+         (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+         (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
+         (vreg-class (if vreg (hard-regspec-class vreg)))
+         (vreg-mode (if (or (eql vreg-class hard-reg-class-gpr)
+                            (eql vreg-class hard-reg-class-fpr))
+                      (get-regspec-mode vreg)))
+         (next-imm-target (available-imm-temp  *available-backend-imm-temps*))
+         (next-fp-target (available-fp-temp *available-backend-fp-temps*))
+         (acc (make-wired-lreg ppc::arg_z)))
+    (cond ((or is-node
+               is-1-bit
+               (eq type-keyword :simple-string)
+               (eq type-keyword :fixnum-vector)
+               (and (eql vreg-class hard-reg-class-gpr)
+                    (eql vreg-mode hard-reg-class-gpr-mode-node)))
+           acc)
+          ;; If there's no vreg - if we're setting for effect only, and
+          ;; not for value - we can target an unboxed register directly.
+          ;; Usually.
+          ((null vreg)
+           (cond (is-64-bit
+                  (if (eq type-keyword :double-float-vector)
+                    (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-double)
+                    (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s64 hard-reg-class-gpr-mode-u64))))
+                 (is-32-bit
+                  (if (eq type-keyword :single-float-vector)
+                    (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-single)
+                    (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s32 hard-reg-class-gpr-mode-u32))))
+                 (is-16-bit
+                  (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s16 hard-reg-class-gpr-mode-u16)))
+                 (is-8-bit
+                  (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s8 hard-reg-class-gpr-mode-u8)))
+                 (t "Bug: can't determine operand size for ~s" type-keyword)))
+          ;; Vreg is non-null.  We might be able to use it directly.
+          (t
+           (let* ((lreg (if vreg-mode
+                          (make-unwired-lreg (lreg-value vreg)))))
+             (if 
+               (cond
+                 (is-64-bit
+                  (if (eq type-keyword :double-float-vector)
+                    (and (eql vreg-class hard-reg-class-fpr)
+                         (eql vreg-mode hard-reg-class-fpr-mode-double))
+                      (if is-signed
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (eql vreg-mode hard-reg-class-gpr-mode-s64))
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (eql vreg-mode hard-reg-class-gpr-mode-u64)))))
+                   (is-32-bit
+                    (if (eq type-keyword :single-float-vector)
+                      (and (eql vreg-class hard-reg-class-fpr)
+                               (eql vreg-mode hard-reg-class-fpr-mode-single))
+                      (if is-signed
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (or (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                     (eql vreg-mode hard-reg-class-gpr-mode-s64)))
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (or (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                                     (eql vreg-mode hard-reg-class-gpr-mode-u64)
+                                     (eql vreg-mode hard-reg-class-gpr-mode-s64))))))
+                   (is-16-bit
+                    (if is-signed
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-u16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u64)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))))
+                   (t
+                    (if is-signed
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-s8)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-u8)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u64)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64))))))
+               lreg
+               acc))))))
+
+(defun ppc2-unboxed-reg-for-aset (seg type-keyword result-reg safe constval)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+           (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+           (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+           (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+           (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
+           (result-is-node-gpr (and (eql (hard-regspec-class result-reg)
+                                         hard-reg-class-gpr)
+                                    (eql (get-regspec-mode result-reg)
+                                         hard-reg-class-gpr-mode-node)))
+           (next-imm-target (available-imm-temp *available-backend-imm-temps*))
+           (next-fp-target (available-fp-temp *available-backend-fp-temps*)))
+      (if (or is-node (not result-is-node-gpr))
+        result-reg
+        (cond (is-64-bit
+               (if (eq type-keyword :double-float-vector)
+                 (let* ((reg (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-double)))
+                   (if safe
+                     (! get-double? reg result-reg)
+                     (! get-double reg result-reg))
+                   reg)
+                 (if is-signed
+                   (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s64)))
+                     (if (eq type-keyword :fixnum-vector)
+                       (progn
+                         (when safe
+                           (! trap-unless-fixnum result-reg))
+                         (! fixnum->signed-natural reg result-reg))
+                       (! unbox-s64 reg result-reg))
+                     reg)
+                   (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u64)))
+                     (! unbox-u64 reg result-reg)
+                     reg))))
+              (is-32-bit
+               ;; Generally better to use a GPR for the :SINGLE-FLOAT-VECTOR
+               ;; case here.
+               (if is-signed             
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s32)))
+                   (if (eq type-keyword :fixnum-vector)
+                     (progn
+                       (when safe
+                         (! trap-unless-fixnum result-reg))
+                       (! fixnum->signed-natural reg result-reg))
+                     (! unbox-s32 reg result-reg))
+                   reg)
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u32)))
+                   (cond ((eq type-keyword :simple-string)
+                          (if (characterp constval)
+                            (ppc2-lri seg reg (char-code constval))
+                            (! unbox-base-char reg result-reg)))
+                         ((eq type-keyword :single-float-vector)
+                          (if (typep constval 'single-float)
+                            (ppc2-lri seg reg (single-float-bits constval))
+                            (progn
+                              (when safe
+                                (! trap-unless-single-float result-reg))
+                              (! single-float-bits reg result-reg))))
+                         (t
+                          (if (typep constval '(unsigned-byte 32))
+                            (ppc2-lri seg reg constval)
+			    (if *ppc2-reckless*
+			      (target-arch-case
+			       (:ppc32 (! unbox-u32 reg result-reg))
+			       (:ppc64 (! %unbox-u32 reg result-reg)))
+			      (! unbox-u32 reg result-reg)))))
+                   reg)))
+              (is-16-bit
+               (if is-signed
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s16)))
+                   (if (typep constval '(signed-byte 16))
+                     (ppc2-lri seg reg constval)
+                     (! unbox-s16 reg result-reg))
+                   reg)
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u16)))
+                   (if (typep constval '(unsigned-byte 16))
+                     (ppc2-lri seg reg constval)
+                     (! unbox-u16 reg result-reg))
+                   reg)))
+              (is-8-bit
+               (if is-signed
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s8)))
+                   (if (typep constval '(signed-byte 8))
+                     (ppc2-lri seg reg constval)
+                     (! unbox-s8 reg result-reg))
+                   reg)
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u8)))
+                   (if (typep constval '(unsigned-byte 8))
+                     (ppc2-lri seg reg constval)
+                     (! unbox-u8 reg result-reg))
+                   reg)))
+              (t
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u8)))
+                   (unless (typep constval 'bit)
+                     (! unbox-bit-bit0 reg result-reg))
+                   reg)))))))
+                   
+      
+;;; "val-reg" might be boxed, if the vreg requires it to be.
+(defun ppc2-vset1 (seg vreg xfer type-keyword src  unscaled-idx index-known-fixnum val-reg unboxed-val-reg constval &optional (node-value-needs-memoization t))
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
+           (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+           (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+           (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+           (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+           (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector))))
+      (cond ((and is-node node-value-needs-memoization)
+             (unless (and (eql (hard-regspec-value src) ppc::arg_x)
+                          (eql (hard-regspec-value unscaled-idx) ppc::arg_y)
+                          (eql (hard-regspec-value val-reg) ppc::arg_z))
+               (compiler-bug "Bug: invalid register targeting for gvset: ~s" (list src unscaled-idx val-reg)))
+             (! call-subprim-3 val-reg (subprim-name->offset '.SPgvset) src unscaled-idx val-reg))
+            (is-node
+             (if (and index-known-fixnum (<= index-known-fixnum
+                                             (target-word-size-case
+                                              (32 (arch::target-max-32-bit-constant-index arch))
+                                              (64 (arch::target-max-64-bit-constant-index arch)))))
+               (! misc-set-c-node val-reg src index-known-fixnum)
+               (with-imm-target () scaled-idx
+
+                 (if index-known-fixnum
+                   (ppc2-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum *ppc2-target-node-shift*)))
+                   (! scale-node-misc-index scaled-idx unscaled-idx))
+                 (! misc-set-node val-reg src scaled-idx))))
+            (t
+             (with-imm-target (unboxed-val-reg) scaled-idx
+               (cond
+                 (is-64-bit
+                  (if (and index-known-fixnum
+                           (<= index-known-fixnum
+                               (arch::target-max-64-bit-constant-index arch)))
+                    (if (eq type-keyword :double-float-vector)
+                      (! misc-set-c-double-float unboxed-val-reg src index-known-fixnum)
+                      (if is-signed
+                        (! misc-set-c-s64 unboxed-val-reg src index-known-fixnum)
+                        (! misc-set-c-u64 unboxed-val-reg src index-known-fixnum)))
+                    (progn
+                      (if index-known-fixnum
+                        (ppc2-absolute-natural seg scaled-idx nil (+ (arch::target-misc-dfloat-offset arch) (ash index-known-fixnum 3)))
+                        (! scale-64bit-misc-index scaled-idx unscaled-idx))
+                      (if (eq type-keyword :double-float-vector)
+                        (! misc-set-double-float unboxed-val-reg src scaled-idx)
+                        (if is-signed
+                          (! misc-set-s64 unboxed-val-reg src scaled-idx)
+                          (! misc-set-u64 unboxed-val-reg src scaled-idx))))))
+                 (is-32-bit
+                  (if (and index-known-fixnum
+                           (<= index-known-fixnum
+                               (arch::target-max-32-bit-constant-index arch)))
+                    (if (eq type-keyword :single-float-vector)
+                      (if (eq (hard-regspec-class unboxed-val-reg)
+                              hard-reg-class-fpr)
+                        (! misc-set-c-single-float unboxed-val-reg src index-known-fixnum)
+                        (! misc-set-c-u32 unboxed-val-reg src index-known-fixnum))
+                      (if is-signed
+                        (! misc-set-c-s32 unboxed-val-reg src index-known-fixnum)
+                        (! misc-set-c-u32 unboxed-val-reg src index-known-fixnum)))
+                    (progn
+                      (if index-known-fixnum
+                        (ppc2-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 2)))
+                        (! scale-32bit-misc-index scaled-idx unscaled-idx))
+                      (if (and (eq type-keyword :single-float-vector)
+                               (eql (hard-regspec-class unboxed-val-reg)
+                                    hard-reg-class-fpr))
+                        (! misc-set-single-float unboxed-val-reg src scaled-idx)
+                        (if is-signed
+                          (! misc-set-s32 unboxed-val-reg src scaled-idx)
+                          (! misc-set-u32 unboxed-val-reg src scaled-idx))))))
+                 (is-16-bit
+                  (if (and index-known-fixnum
+                           (<= index-known-fixnum
+                               (arch::target-max-16-bit-constant-index arch)))
+                    (if is-signed
+                      (! misc-set-c-s16 unboxed-val-reg src index-known-fixnum)
+                      (! misc-set-c-u16 unboxed-val-reg src index-known-fixnum))
+                    (progn
+                      (if index-known-fixnum
+                        (ppc2-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 1)))
+                        (! scale-16bit-misc-index scaled-idx unscaled-idx))
+                      (if is-signed
+                        (! misc-set-s16 unboxed-val-reg src scaled-idx)
+                        (! misc-set-u16 unboxed-val-reg src scaled-idx)))))
+                 (is-8-bit
+                  (if (and index-known-fixnum
+                           (<= index-known-fixnum
+                               (arch::target-max-8-bit-constant-index arch)))
+                    (if is-signed
+                      (! misc-set-c-s8 unboxed-val-reg src index-known-fixnum)
+                      (! misc-set-c-u8  unboxed-val-reg src index-known-fixnum))
+                    (progn
+                      (if index-known-fixnum
+                        (ppc2-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) index-known-fixnum))
+                        (! scale-8bit-misc-index scaled-idx unscaled-idx))
+                      (if is-signed
+                        (! misc-set-s8 unboxed-val-reg src scaled-idx)
+                        (! misc-set-u8 unboxed-val-reg src scaled-idx)))))
+                 (t
+                  (unless is-1-bit
+                    (nx-error "~& unsupported vector type: ~s"
+                              type-keyword))
+                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-1-bit-constant-index arch)))
+                    (with-imm-target (unboxed-val-reg) word
+                      (let* ((word-index (ash index-known-fixnum -5))
+                             (bit-number (logand index-known-fixnum #x1f)))
+                        (! misc-ref-c-u32 word src word-index)
+                        (if constval
+                          (if (zerop constval)
+                            (! set-constant-ppc-bit-to-0 word word bit-number)
+                            (! set-constant-ppc-bit-to-1 word word bit-number))
+                          (! set-constant-ppc-bit-to-variable-value word word unboxed-val-reg bit-number))
+                        (! misc-set-c-u32 word src word-index)))
+                    (with-imm-temps (unboxed-val-reg) (word-index bit-number temp)
+                      (! scale-1bit-misc-index word-index bit-number unscaled-idx)
+                      (if constval
+                        (progn
+                          (! lri temp #x80000000)
+                          (! shift-right-variable-word bit-number temp bit-number)
+                          (! misc-ref-u32 temp src word-index)
+                          (if (zerop constval)
+                            (! u32logandc2 temp temp bit-number)
+                            (! u32logior temp temp bit-number)))
+                        (with-imm-temps () (bitval)
+                          (! shift-right-variable-word bitval unboxed-val-reg bit-number)
+                          (! lri temp #x80000000)
+                          (! shift-right-variable-word bit-number temp bit-number)
+                          (! misc-ref-u32 temp src word-index)
+                          (! u32logandc2 temp temp bit-number)
+                          (! u32logior temp temp bitval)))
+                      (! misc-set-u32 temp src word-index))))))))
+      (when (and vreg val-reg) (<- val-reg))
+      (^))))
+                    
+
+(defun ppc2-code-coverage-entry (seg note)
+  (let* ((afunc *ppc2-cur-afunc*))
+    (setf (afunc-bits afunc) (%ilogior (afunc-bits afunc) (ash 1 $fbitccoverage)))
+    (with-ppc-local-vinsn-macros (seg)
+      (let* ((ccreg ($ ppc::temp0)))
+        (ppc2-store-immediate seg note ccreg)
+        (! misc-set-c-node ($ ppc::rzero) ccreg 1)))))
+
+(defun ppc2-vset (seg vreg xfer type-keyword vector index value safe)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (constval (ppc2-constant-value-ok-for-type-keyword type-keyword value))
+           (needs-memoization (and is-node (ppc2-acode-needs-memoization value)))
+           (index-known-fixnum (acode-fixnum-form-p index)))
+      (let* ((src ($ ppc::arg_x))
+             (unscaled-idx ($ ppc::arg_y))
+             (result-reg ($ ppc::arg_z)))
+        (cond (needs-memoization
+               (ppc2-three-targeted-reg-forms seg
+                                              vector src
+                                              index unscaled-idx
+                                              value result-reg))
+              (t
+               (multiple-value-setq (src unscaled-idx result-reg)
+                 (ppc2-three-untargeted-reg-forms seg
+                                              vector src
+                                              index unscaled-idx
+                                              value (ppc2-target-reg-for-aset vreg type-keyword)))))
+        (when safe
+          (let* ((*available-backend-imm-temps* *available-backend-imm-temps*)
+                 (value (if (eql (hard-regspec-class result-reg)
+                                 hard-reg-class-gpr)
+                          (hard-regspec-value result-reg))))
+            (when (and value (logbitp value *available-backend-imm-temps*))
+              (setq *available-backend-imm-temps* (bitclr value *available-backend-imm-temps*)))
+            (if (typep safe 'fixnum)
+              (! trap-unless-typecode= src safe))
+            (unless index-known-fixnum
+              (! trap-unless-fixnum unscaled-idx))
+            (! check-misc-bound unscaled-idx src)))
+        (ppc2-vset1 seg vreg xfer type-keyword src unscaled-idx index-known-fixnum result-reg (ppc2-unboxed-reg-for-aset seg type-keyword result-reg safe constval) constval needs-memoization)))))
+
+
+(defun ppc2-tail-call-alias (immref sym &optional arglist)
+  (let ((alias (cdr (assq sym *ppc2-tail-call-aliases*))))
+    (if (and alias (or (null arglist) (eq (+ (length (car arglist)) (length (cadr arglist))) (cdr alias))))
+      (make-acode (%nx1-operator immediate) (car alias))
+      immref)))
+
+;;; If BODY is essentially an APPLY involving an &rest arg, try to avoid
+;;; consing it.
+(defun ppc2-eliminate-&rest (body rest key-p auxen rest-values)
+  (when (and rest (not key-p) (not (cadr auxen)) rest-values)
+    (when (eq (logand (the fixnum (nx-var-bits rest))
+                      (logior $vsetqmask (ash -1 $vbitspecial)
+                              (ash 1 $vbitclosed) (ash 1 $vbitsetq) (ash 1 $vbitcloseddownward)))
+              0)               ; Nothing but simple references
+      (do* ()
+           ((not (acode-p body)))
+        (let* ((op (acode-operator body)))
+          (if (or (eq op (%nx1-operator lexical-function-call))
+                  (eq op (%nx1-operator call)))
+            (destructuring-bind (fn-form (stack-args reg-args) &optional spread-p) (%cdr body)
+               (unless (and (eq spread-p t)
+                           (eq (ppc2-lexical-reference-p (%car reg-args)) rest))
+                (return nil))
+              (flet ((independent-of-all-values (form)        
+                       (setq form (acode-unwrapped-form-value form))
+                       (or (ppc-constant-form-p form)
+                           (let* ((lexref (ppc2-lexical-reference-p form)))
+                             (and lexref 
+                                  (neq lexref rest)
+                                  (dolist (val rest-values t)
+                                    (unless (ppc2-var-not-set-by-form-p lexref val)
+                                      (return))))))))
+                (unless (or (eq op (%nx1-operator lexical-function-call))
+                            (independent-of-all-values fn-form))
+                  (return nil))
+                (if (dolist (s stack-args t)
+                          (unless (independent-of-all-values s)
+                            (return nil)))
+                  (let* ((arglist (append stack-args rest-values)))
+                    (return
+                     (make-acode op 
+                                 fn-form 
+                                 (if (<= (length arglist) $numppcargregs)
+                                   (list nil (reverse arglist))
+                                   (list (butlast arglist $numppcargregs)
+                                         (reverse (last arglist $numppcargregs))))
+                                 nil)))
+                  (return nil))))
+            (if (eq op (%nx1-operator local-block))
+              (setq body (%cadr body))
+              (if (and (eq op (%nx1-operator if))
+                       (eq (ppc2-lexical-reference-p (%cadr body)) rest))
+                (setq body (%caddr body))
+                (return nil)))))))))
+
+(defun ppc2-call-fn (seg vreg xfer fn arglist spread-p)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (when spread-p
+      (destructuring-bind (stack-args reg-args) arglist
+        (when (and (null (cdr reg-args))
+                   (nx-null (acode-unwrapped-form-value (car reg-args))))
+          (setq spread-p nil)
+          (let* ((nargs (length stack-args)))
+            (declare (fixnum nargs))
+            (if (<= nargs $numppcargregs)
+              (setq arglist (list nil (reverse stack-args)))
+              (setq arglist (list (butlast stack-args $numppcargregs) (reverse (last stack-args $numppcargregs)))))))))
+    (let* ((lexref (ppc2-lexical-reference-p fn))
+           (simple-case (or (fixnump fn)
+                            (typep fn 'lreg)
+                            (ppc2-immediate-function-p fn)
+                            (and 
+                             lexref
+                             (not spread-p)
+                             (flet ((all-simple (args)
+                                      (dolist (arg args t)
+                                        (when (and arg (not (ppc2-var-not-set-by-form-p lexref arg)))
+                                          (return)))))
+                               (and (all-simple (car arglist))
+                                    (all-simple (cadr arglist))
+                                    (setq fn (var-ea lexref)))))))
+           (cstack *ppc2-cstack*)
+           (top *ppc2-top-vstack-lcell*)
+           (vstack *ppc2-vstack*))
+      (setq xfer (or xfer 0))
+      (when (and (eq xfer $backend-return)
+                 (eq 0 *ppc2-undo-count*)
+                 (acode-p fn)
+                 (eq (acode-operator fn) (%nx1-operator immediate))
+                 (symbolp (cadr fn)))
+        (setq fn (ppc2-tail-call-alias fn (%cadr fn) arglist)))
+      
+      (if (and (eq xfer $backend-return) (not (ppc2-tailcallok xfer)))
+        (progn
+          (ppc2-call-fn seg vreg $backend-mvpass fn arglist spread-p)
+          (ppc2-set-vstack (%i+ (if simple-case 0 *ppc2-target-node-size*) vstack))
+          (setq  *ppc2-cstack* cstack)
+          (let ((*ppc2-returning-values* t)) (ppc2-do-return seg)))
+        (let* ((mv-p (ppc2-mv-p xfer)))
+          (unless simple-case
+            (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg fn ppc::arg_z))
+            (setq fn (ppc2-vloc-ea vstack)))
+          (ppc2-invoke-fn seg fn (ppc2-arglist seg arglist) spread-p xfer)
+          (if (and (logbitp $backend-mvpass-bit xfer)
+                   (not simple-case))
+            (progn
+              (! save-values)
+              (! vstack-discard 1)
+              (ppc2-set-nargs seg 0)
+              (! recover-values))
+            (unless (or mv-p simple-case)
+              (! vstack-discard 1)))
+          (ppc2-set-vstack vstack)
+          (setq *ppc2-top-vstack-lcell* top)
+          (setq *ppc2-cstack* cstack)
+          (when (or (logbitp $backend-mvpass-bit xfer) (not mv-p))
+            (<- ppc::arg_z)
+            (ppc2-branch seg (logand (lognot $backend-mvpass-mask) xfer) vreg))))
+      nil)))
+
+(defun ppc2-restore-full-lisp-context (seg)
+  (with-ppc-local-vinsn-macros (seg)
+    (if *ppc2-open-code-inline*
+      (! restore-full-lisp-context)
+      (! restore-full-lisp-context-ool))))
+
+(defun ppc2-call-symbol (seg jump-p)
+  ; fname contains a symbol; we can either call it via
+  ; a call to .SPjmpsym or expand the instructions inline.
+  ; Since the branches are unconditional, the call doesn't
+  ; cost much, but doing the instructions inline would give
+  ; an instruction scheduler some opportunities to improve
+  ; performance, so this isn't a strict time/speed tradeoff.
+  ; This should probably dispatch on something other than
+  ; *ppc2-open-code-inline*, since that does imply a time/speed
+  ; tradeoff.
+  (with-ppc-local-vinsn-macros (seg)
+    (if *ppc2-open-code-inline*
+      (if jump-p
+        (! jump-known-symbol)
+        (! call-known-symbol ppc::arg_z))
+      (if jump-p
+        (! jump-known-symbol-ool)
+        (! call-known-symbol-ool)))))
+
+;;; Nargs = nil -> multiple-value case.
+(defun ppc2-invoke-fn (seg fn nargs spread-p xfer)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((f-op (acode-unwrapped-form-value fn))
+           (immp (and (consp f-op)
+                      (eq (%car f-op) (%nx1-operator immediate))))
+           (symp (and immp (symbolp (%cadr f-op))))
+           (label-p (and (fixnump fn) 
+                         (locally (declare (fixnum fn))
+                           (and (= fn -1) (- fn)))))
+           (tail-p (eq xfer $backend-return))
+           (func (if (consp f-op) (%cadr f-op)))
+           (a-reg nil)
+           (lfunp (and (acode-p f-op) 
+                       (eq (acode-operator f-op) (%nx1-operator simple-function))))
+           (expression-p (or (typep fn 'lreg) (and (fixnump fn) (not label-p))))
+           (callable (or symp lfunp label-p))
+           (destreg (if symp ($ ppc::fname) (if lfunp ($ ppc::nfn) (unless label-p ($ ppc::temp0)))))
+           (alternate-tail-call
+            (and tail-p label-p *ppc2-tail-label* (eql nargs *ppc2-tail-nargs*) (not spread-p)))
+           )
+      (when expression-p
+                                        ;Have to do this before spread args, since might be vsp-relative.
+        (if nargs
+          (ppc2-do-lexical-reference seg destreg fn)
+          (ppc2-copy-register seg destreg fn)))
+      (if (or symp lfunp)
+        (setq func (if symp (ppc2-symbol-entry-locative func)
+                     (ppc2-afunc-lfun-ref func))
+              a-reg (ppc2-register-constant-p func)))
+      (when tail-p
+        #-no-compiler-bugs
+        (unless (or immp symp lfunp (typep fn 'lreg) (fixnump fn)) (compiler-bug "Well, well, well.  How could this have happened ?"))
+        (when a-reg
+          (ppc2-copy-register seg destreg a-reg))
+        (unless spread-p
+          (unless alternate-tail-call
+            (if nargs
+              (ppc2-restore-nvrs seg *ppc2-register-restore-ea* *ppc2-register-restore-count*)
+              (when *ppc2-register-restore-count*
+                (with-imm-temps () (vsp0)
+                  (! fixnum-add vsp0 ppc::vsp ppc::nargs)
+                  (ppc2-restore-nvrs seg *ppc2-register-restore-ea* *ppc2-register-restore-count* vsp0)))))))
+      (if spread-p
+        (progn
+          (ppc2-set-nargs seg (%i- nargs 1))
+          (when (and tail-p *ppc2-register-restore-count*)
+            (! copy-gpr ppc::temp1 ppc::vsp)) ; .SPspread-lexpr-z & .SPspreadargz preserve temp1
+          (if (eq spread-p 0)
+            (! spread-lexpr)
+            (! spread-list))
+          (when (and tail-p *ppc2-register-restore-count*)
+            (ppc2-restore-nvrs seg *ppc2-register-restore-ea* *ppc2-register-restore-count* ppc::temp1)))
+        (if nargs
+          (unless alternate-tail-call (ppc2-set-nargs seg nargs))
+          (! pop-argument-registers)))
+      (if callable
+        (if (not tail-p)
+          (if (ppc2-mvpass-p xfer)
+            (let* ((call-reg (if symp ($ ppc::fname) ($ ppc::temp0))))
+              (if label-p
+                (ppc2-copy-register seg call-reg ($ ppc::fn))
+                (if a-reg
+                  (ppc2-copy-register seg call-reg  a-reg)
+                  (ppc2-store-immediate seg func call-reg)))
+              (if symp
+                (! pass-multiple-values-symbol)
+                (! pass-multiple-values)))
+            (progn 
+              (if label-p
+                (progn
+                  (ppc2-copy-register seg ($ ppc::nfn) ($  ppc::fn))
+                  (! call-label (aref *backend-labels* 1)))
+                (progn
+                  (if a-reg
+                    (ppc2-copy-register seg destreg a-reg)
+                    (ppc2-store-immediate seg func destreg))
+                  (if symp
+                    (ppc2-call-symbol seg nil)
+                    (! call-known-function))))))
+          (if alternate-tail-call
+            (progn
+              (ppc2-unwind-stack seg xfer 0 0 *ppc2-tail-vsp*)
+              (! jump (aref *backend-labels* *ppc2-tail-label*)))
+            (progn
+              (ppc2-unwind-stack seg xfer 0 0 #x7fffff)
+              (if (and (not spread-p) nargs (%i<= nargs $numppcargregs))
+                (progn
+                  (if label-p
+                    (ppc2-copy-register seg ppc::nfn ppc::fn))
+                  (unless (or label-p a-reg) (ppc2-store-immediate seg func destreg))
+                  (ppc2-restore-full-lisp-context seg)
+                  (if label-p
+                    (! jump (aref *backend-labels* 1))
+                    (progn
+                      (if symp
+                        (ppc2-call-symbol seg t)
+                        (! jump-known-function)))))
+                (progn
+                  (if label-p
+                    (ppc2-copy-register seg ppc::nfn ppc::fn)
+                    (unless a-reg (ppc2-store-immediate seg func destreg)))
+                  (cond ((or spread-p (null nargs))
+                         (if symp
+                           (! tail-call-sym-gen)
+                           (! tail-call-fn-gen)))
+                        ((%i> nargs $numppcargregs)
+                         (if symp
+                           (! tail-call-sym-slide)
+                           (! tail-call-fn-slide)))
+                        (t
+                         (if symp
+                           (! tail-call-sym-vsp)
+                           (! tail-call-fn-vsp)))))))))
+        ;; The general (funcall) case: we don't know (at compile-time)
+        ;; for sure whether we've got a symbol or a (local, constant)
+        ;; function.
+        (progn
+          (unless (or (fixnump fn) (typep fn 'lreg))
+            (ppc2-one-targeted-reg-form seg fn destreg))
+          (if (not tail-p)
+            (if (ppc2-mvpass-p xfer)
+              (! pass-multiple-values)
+              (! funcall))                  
+            (cond ((or (null nargs) spread-p)
+                   (! tail-funcall-gen))
+                  ((%i> nargs $numppcargregs)
+                   (! tail-funcall-slide))
+                  (t
+                   (! tail-funcall-vsp)))))))
+    nil))
+
+(defun ppc2-seq-fbind (seg vreg xfer vars afuncs body p2decls)
+  (let* ((old-stack (ppc2-encode-stack))
+         (copy afuncs)
+         (func nil))
+    (with-ppc-p2-declarations p2decls 
+      (dolist (var vars) 
+        (when (neq 0 (afunc-fn-refcount (setq func (pop afuncs))))
+          (ppc2-seq-bind-var seg var (nx1-afunc-ref func))))
+      (ppc2-undo-body seg vreg xfer body old-stack)
+      (dolist (var vars)
+        (when (neq 0 (afunc-fn-refcount (setq func (pop copy))))
+          (ppc2-close-var seg var))))))
+
+(defun ppc2-make-closure (seg afunc downward-p)
+  (with-ppc-local-vinsn-macros (seg)
+    (flet ((var-to-reg (var target)
+             (let* ((ea (var-ea (var-bits var))))
+               (if ea
+                 (ppc2-addrspec-to-reg seg (ppc2-ea-open ea) target)
+                 (! load-nil target))
+               target))
+           (set-some-cells (dest cellno c0 c1 c2 c3)
+             (declare (fixnum cellno))
+             (! misc-set-c-node c0 dest cellno)
+             (incf cellno)
+             (when c1
+               (! misc-set-c-node c1 dest cellno)
+               (incf cellno)
+               (when c2
+                 (! misc-set-c-node c2 dest cellno)
+                 (incf cellno)
+                 (when c3
+                   (! misc-set-c-node c3 dest cellno)
+                   (incf cellno))))
+             cellno))
+      (let* ((inherited-vars (afunc-inherited-vars afunc))
+             (arch (backend-target-arch *target-backend*))
+             (dest ($ ppc::arg_z))
+             (vsize (+ (length inherited-vars) 
+                       2                ; %closure-code%, afunc
+                       2)))             ; name, lfun-bits
+        (declare (list inherited-vars))
+        (if downward-p
+          (progn
+            (let* ((*ppc2-vstack* *ppc2-vstack*)
+                   (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+              (ppc2-lri seg ppc::arg_x (ash (nx-lookup-target-uvector-subtag :function) *ppc2-target-fixnum-shift*))
+              (! %closure-code% ppc::arg_y)
+              (ppc2-store-immediate seg (ppc2-afunc-lfun-ref afunc) ppc::arg_z)
+              (ppc2-vpush-register-arg seg ppc::arg_x)
+              (ppc2-vpush-register-arg seg ppc::arg_y)
+              (ppc2-vpush-register-arg seg ppc::arg_z)
+                                        ; Could be smarter about memory traffic here.
+              (dolist (v inherited-vars)
+                (ppc2-vpush-register-arg seg (var-to-reg v ppc::arg_z)))
+              (! load-nil ppc::arg_z)
+              (ppc2-vpush-register-arg seg ppc::arg_z)
+              (ppc2-lri seg ppc::arg_z (ash (ash 1 $lfbits-trampoline-bit) *ppc2-target-fixnum-shift*))
+              (ppc2-vpush-register-arg seg ppc::arg_z)
+              (ppc2-set-nargs seg (1+ vsize)) ; account for subtag
+              (! make-stack-gvector))
+            (ppc2-open-undo $undostkblk))
+          (let* ((cell 0))
+            (declare (fixnum cell))
+            (progn
+              (ppc2-lri seg
+                        ppc::imm0
+                        (arch::make-vheader vsize (nx-lookup-target-uvector-subtag :function)))
+              (! %alloc-misc-fixed dest ppc::imm0 (ash vsize (arch::target-word-shift arch)))
+              )       
+            (! %closure-code% ppc::arg_x)
+            (ppc2-store-immediate seg (ppc2-afunc-lfun-ref afunc) ppc::arg_y)
+            (with-node-temps (ppc::arg_z) (t0 t1 t2 t3)
+              (do* ((ccode ppc::arg_x nil)
+                    (func ppc::arg_y nil))
+                   ((null inherited-vars))
+                (let* ((t0r (or ccode (if inherited-vars (var-to-reg (pop inherited-vars) t0))))
+                       (t1r (or func (if inherited-vars (var-to-reg (pop inherited-vars) t1))))
+                       (t2r (if inherited-vars (var-to-reg (pop inherited-vars) t2)))
+                       (t3r (if inherited-vars (var-to-reg (pop inherited-vars) t3))))
+                  (setq cell (set-some-cells dest cell t0r t1r t2r t3r)))))
+            (ppc2-lri seg ppc::arg_y (ash (ash 1 $lfbits-trampoline-bit) *ppc2-target-fixnum-shift*))
+            (! load-nil ppc::arg_x)
+            (! misc-set-c-node ppc::arg_x dest cell)
+            (! misc-set-c-node ppc::arg_y dest (1+ cell))))
+        dest))))
+        
+(defun ppc2-symbol-entry-locative (sym)
+  (setq sym (require-type sym 'symbol))
+  (when (eq sym '%call-next-method-with-args)
+    (setf (afunc-bits *ppc2-cur-afunc*)
+          (%ilogior (%ilsl $fbitnextmethargsp 1) (afunc-bits *ppc2-cur-afunc*))))
+  (or (assq sym *ppc2-fcells*)
+      (let ((new (list sym)))
+        (push new *ppc2-fcells*)
+        new)))
+
+(defun ppc2-symbol-value-cell (sym)
+  (setq sym (require-type sym 'symbol))
+  (or (assq sym *ppc2-vcells*)
+      (let ((new (list sym)))
+        (push new *ppc2-vcells*)
+        (ensure-binding-index sym)
+        new)))
+
+
+(defun ppc2-symbol-locative-p (imm)
+  (and (consp imm)
+       (or (memq imm *ppc2-vcells*)
+           (memq imm *ppc2-fcells*))))
+
+
+
+
+(defun ppc2-immediate-function-p (f)
+  (setq f (acode-unwrapped-form-value f))
+  (and (acode-p f)
+       (or (eq (%car f) (%nx1-operator immediate))
+           (eq (%car f) (%nx1-operator simple-function)))))
+
+(defun ppc-constant-form-p (form)
+  (setq form (nx-untyped-form form))
+  (if form
+    (or (nx-null form)
+        (nx-t form)
+        (and (consp form)
+             (or (eq (acode-operator form) (%nx1-operator immediate))
+                 (eq (acode-operator form) (%nx1-operator fixnum))
+                 (eq (acode-operator form) (%nx1-operator simple-function)))))))
+
+
+  
+(defun ppc2-integer-constant-p (form mode)
+  (let* ((val 
+         (or (acode-fixnum-form-p (setq form (acode-unwrapped-form form)))
+             (and (acode-p form)
+                  (eq (acode-operator form) (%nx1-operator immediate))
+                  (setq form (%cadr form))
+                  (if (typep form 'integer)
+                    form)))))
+    (and val (%typep val (mode-specifier-type mode)) val)))
+
+
+(defun ppc-side-effect-free-form-p (form)
+  (when (consp (setq form (acode-unwrapped-form-value form)))
+    (or (ppc-constant-form-p form)
+        ;(eq (acode-operator form) (%nx1-operator bound-special-ref))
+        (if (eq (acode-operator form) (%nx1-operator lexical-reference))
+          (not (%ilogbitp $vbitsetq (nx-var-bits (%cadr form))))))))
+
+(defun ppc2-formlist (seg stkargs &optional revregargs)
+  (with-ppc-local-vinsn-macros (seg)  
+    (let* ((nregs (length revregargs))
+           (n nregs))
+      (declare (fixnum n))
+      (dolist (arg stkargs)
+        (let* ((reg (ppc2-one-untargeted-reg-form seg arg ppc::arg_z)))
+          (ppc2-vpush-register-arg seg reg)
+          (incf n)))
+      (when revregargs
+        (let* ((zform (%car revregargs))
+               (yform (%cadr revregargs))
+               (xform (%caddr revregargs)))
+          (if (eq 3 nregs)
+            (ppc2-three-targeted-reg-forms seg xform ($ ppc::arg_x) yform ($ ppc::arg_y) zform ($ ppc::arg_z))
+            (if (eq 2 nregs)
+              (ppc2-two-targeted-reg-forms seg yform ($ ppc::arg_y) zform ($ ppc::arg_z))
+              (ppc2-one-targeted-reg-form seg zform ($ ppc::arg_z))))))
+      n)))
+
+(defun ppc2-arglist (seg args)
+  (ppc2-formlist seg (car args) (cadr args)))
+
+
+
+
+
+(defun ppc2-unboxed-integer-arg-to-reg (seg form immreg &optional ffi-arg-type)
+  (let* ((mode (case ffi-arg-type
+                 ((nil) :natural)
+                 (:signed-byte :s8)
+                 (:unsigned-byte :u8)
+                 (:signed-halfword :s16)
+                 (:unsigned-halfword :u16)
+                 (:signed-fullword :s32)
+                 (:unsigned-fullword :u32)
+                 (:unsigned-doubleword :u64)
+                 (:signed-doubleword :s64)))
+         (modeval (gpr-mode-name-value mode)))
+    (with-ppc-local-vinsn-macros (seg)
+      (let* ((value (ppc2-integer-constant-p form mode)))
+        (if value
+          (if (eql value 0)
+            (make-wired-lreg ppc::rzero :mode modeval)
+            (progn
+              (unless (typep immreg 'lreg)
+                (setq immreg (make-unwired-lreg immreg :mode modeval)))
+              (ppc2-lri seg immreg value)
+              immreg))
+          (progn 
+            (ppc2-one-targeted-reg-form seg form (make-wired-lreg ppc::imm0 :mode modeval))))))))
+
+
+(defun ppc2-macptr-arg-to-reg (seg form address-reg)  
+  (ppc2-one-targeted-reg-form seg
+                              form 
+                              address-reg))
+
+
+(defun ppc2-one-lreg-form (seg form lreg)
+  (let ((is-float (= (hard-regspec-class lreg) hard-reg-class-fpr)))
+    (if is-float
+      (ppc2-form-float seg lreg nil form)
+      (ppc2-form seg lreg nil form))
+    lreg))
+
+(defun ppc2-one-targeted-reg-form (seg form reg)
+  (ppc2-one-lreg-form seg form reg))
+
+(defun ppc2-one-untargeted-lreg-form (seg form reg)
+  (ppc2-one-lreg-form seg form (if (typep reg 'lreg) reg (make-unwired-lreg reg))))
+
+(defun ppc2-one-untargeted-reg-form (seg form suggested)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((gpr-p (= (hard-regspec-class suggested) hard-reg-class-gpr))
+           (node-p (if gpr-p (= (get-regspec-mode suggested) hard-reg-class-gpr-mode-node))))
+      (if node-p
+        (let* ((ref (ppc2-lexical-reference-ea form))
+               (reg (backend-ea-physical-reg ref hard-reg-class-gpr)))
+          (if reg
+            ref
+            (if (nx-null form)
+              (progn
+                (! load-nil suggested)
+                suggested)
+              (if (eql 0 (acode-fixnum-form-p form))
+                ($ ppc::rzero)
+                (if (and (acode-p form) 
+                         (eq (acode-operator form) (%nx1-operator immediate)) 
+                         (setq reg (ppc2-register-constant-p (cadr form))))
+                  reg
+                  (if (and (acode-p form)
+                           (eq (acode-operator form) (%nx1-operator %current-tcr)))
+                    (target-arch-case
+                     (:ppc32 ($ ppc32::rcontext))
+                     (:ppc64 ($ ppc64::rcontext)))
+                    (ppc2-one-untargeted-lreg-form seg form suggested)))))))
+        (ppc2-one-untargeted-lreg-form seg form suggested)))))
+             
+
+(defun ppc2-push-register (seg areg)
+  (let* ((a-float (= (hard-regspec-class areg) hard-reg-class-fpr))
+         (a-double (if a-float (= (get-regspec-mode areg) hard-reg-class-fpr-mode-double)))
+         (a-node (unless a-float (= (get-regspec-mode areg) hard-reg-class-gpr-mode-node)))
+         vinsn)
+    (with-ppc-local-vinsn-macros (seg)
+      (if a-node
+        (setq vinsn (ppc2-vpush-register seg areg :node-temp))
+        (progn
+          (setq vinsn
+                (if a-float
+                  (if a-double
+                    (! temp-push-double-float areg)
+                    (! temp-push-single-float areg))
+                  (! temp-push-unboxed-word areg)))
+          (ppc2-open-undo $undostkblk)))
+      vinsn)))
+
+(defun ppc2-pop-register (seg areg)
+  (let* ((a-float (= (hard-regspec-class areg) hard-reg-class-fpr))
+         (a-double (if a-float (= (get-regspec-mode areg) hard-reg-class-fpr-mode-double)))
+         (a-node (unless a-float (= (get-regspec-mode areg) hard-reg-class-gpr-mode-node)))
+         vinsn)
+    (with-ppc-local-vinsn-macros (seg)
+      (if a-node
+        (setq vinsn (ppc2-vpop-register seg areg))
+        (progn
+          (setq vinsn
+                (if a-float
+                  (if a-double
+                    (! temp-pop-double-float areg)
+                    (! temp-pop-single-float areg))
+                  (! temp-pop-unboxed-word areg)))
+          (ppc2-close-undo)))
+      vinsn)))
+
+(defun ppc2-acc-reg-for (reg)
+  (with-ppc-local-vinsn-macros (seg)
+    (if (and (eql (hard-regspec-class reg) hard-reg-class-gpr)
+             (eql (get-regspec-mode reg) hard-reg-class-gpr-mode-node))
+      ($ ppc::arg_z)
+      reg)))
+
+;;; The compiler often generates superfluous pushes & pops.  Try to
+;;; eliminate them.
+;;; It's easier to elide pushes and pops to the TSP.
+(defun ppc2-elide-pushes (seg push-vinsn pop-vinsn)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((pushed-reg (svref (vinsn-variable-parts push-vinsn) 0))
+           (popped-reg (svref (vinsn-variable-parts pop-vinsn) 0))
+           (same-reg (eq (hard-regspec-value pushed-reg)
+                         (hard-regspec-value popped-reg)))
+           (tsp-p (vinsn-attribute-p push-vinsn :tsp)))
+      (when (and tsp-p t)               ; vsp case is harder.
+        (unless (vinsn-sequence-has-attribute-p push-vinsn pop-vinsn :tsp :discard)
+          (let* ((pushed-reg-is-set (vinsn-sequence-sets-reg-p
+                                     push-vinsn pop-vinsn pushed-reg))
+                 (popped-reg-is-set (if same-reg
+                                      pushed-reg-is-set
+                                      (vinsn-sequence-sets-reg-p
+                                       push-vinsn pop-vinsn popped-reg))))
+            (unless (and pushed-reg-is-set popped-reg-is-set)
+              (unless same-reg
+                (let* ((copy (if (eq (hard-regspec-class pushed-reg)
+                                     hard-reg-class-fpr)
+                               (! copy-fpr popped-reg pushed-reg)
+                               (! copy-gpr popped-reg pushed-reg))))
+                  (remove-dll-node copy)
+                  (if pushed-reg-is-set
+                    (insert-dll-node-after copy push-vinsn)
+                    (insert-dll-node-before copy push-vinsn))))
+              (elide-vinsn push-vinsn)
+              (elide-vinsn pop-vinsn))))))))
+                
+        
+;;; we never leave the first form pushed (the 68K compiler had some subprims that
+;;; would vpop the first argument out of line.)
+(defun ppc2-two-targeted-reg-forms (seg aform areg bform breg)
+  (let* ((avar (ppc2-lexical-reference-p aform))
+         (atriv (and (ppc2-trivial-p bform) (nx2-node-gpr-p breg)))
+         (aconst (and (not atriv) (or (ppc-side-effect-free-form-p aform)
+                                      (if avar (ppc2-var-not-set-by-form-p avar bform)))))
+         (apushed (not (or atriv aconst))))
+    (progn
+      (unless aconst
+        (if atriv
+          (ppc2-one-targeted-reg-form seg aform areg)
+          (setq apushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg aform (ppc2-acc-reg-for areg))))))
+      (ppc2-one-targeted-reg-form seg bform breg)
+      (if aconst
+        (ppc2-one-targeted-reg-form seg aform areg)
+        (if apushed
+          (ppc2-elide-pushes seg apushed (ppc2-pop-register seg areg)))))
+    (values areg breg)))
+
+
+(defun ppc2-two-untargeted-reg-forms (seg aform areg bform breg)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((avar (ppc2-lexical-reference-p aform))
+           (adest areg)
+           (bdest breg)
+           (atriv (and (ppc2-trivial-p bform) (nx2-node-gpr-p breg)))
+           (aconst (and (not atriv) (or (ppc-side-effect-free-form-p aform)
+                                        (if avar (ppc2-var-not-set-by-form-p avar bform)))))
+           (apushed (not (or atriv aconst))))
+      (progn
+        (unless aconst
+          (if atriv
+            (setq adest (ppc2-one-untargeted-reg-form seg aform areg))
+            (setq apushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg aform (ppc2-acc-reg-for areg))))))
+        (setq bdest (ppc2-one-untargeted-reg-form seg bform breg))
+        (if aconst
+          (setq adest (ppc2-one-untargeted-reg-form seg aform areg))
+          (if apushed
+            (ppc2-elide-pushes seg apushed (ppc2-pop-register seg areg)))))
+      (values adest bdest))))
+
+
+(defun ppc2-four-targeted-reg-forms (seg aform areg bform breg cform creg dform dreg)
+  (let* ((bnode (nx2-node-gpr-p breg))
+         (cnode (nx2-node-gpr-p creg))
+         (dnode (nx2-node-gpr-p dreg))
+         (atriv (or (null aform) 
+                    (and (ppc2-trivial-p bform)
+                         (ppc2-trivial-p cform)
+                         (ppc2-trivial-p dform)
+                         bnode
+                         cnode
+                         dnode)))
+         (btriv (or (null bform)
+                    (and (ppc2-trivial-p cform)
+                         (ppc2-trivial-p dform)
+                         cnode
+                         dnode)))
+         (ctriv (or (null cform)
+                    (and (ppc2-trivial-p dform) dnode)))
+          
+         (aconst (and (not atriv) 
+                      (or (ppc-side-effect-free-form-p aform)
+                          (let ((avar (ppc2-lexical-reference-p aform)))
+                            (and avar 
+                                 (ppc2-var-not-set-by-form-p avar bform)
+                                 (ppc2-var-not-set-by-form-p avar cform)
+                                 (ppc2-var-not-set-by-form-p avar dform))))))
+         (bconst (and (not btriv)
+                      (or (ppc-side-effect-free-form-p bform)
+                          (let ((bvar (ppc2-lexical-reference-p bform)))
+                            (and bvar
+                                 (ppc2-var-not-set-by-form-p bvar cform)
+                                 (ppc2-var-not-set-by-form-p bvar dform))))))
+         (cconst (and (not ctriv)
+                      (or (ppc-side-effect-free-form-p cform)
+                          (let ((cvar (ppc2-lexical-reference-p cform)))
+                            (and cvar
+                                 (ppc2-var-not-set-by-form-p cvar dform))))))
+         (apushed nil)
+         (bpushed nil)
+         (cpushed nil))
+    (if (and aform (not aconst))
+      (if atriv
+        (ppc2-one-targeted-reg-form seg aform areg)
+        (setq apushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg aform (ppc2-acc-reg-for areg))))))
+    (if (and bform (not bconst))
+      (if btriv
+        (ppc2-one-targeted-reg-form seg bform breg)
+        (setq bpushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg bform (ppc2-acc-reg-for breg))))))
+    (if (and cform (not cconst))
+      (if ctriv
+        (ppc2-one-targeted-reg-form seg cform creg)
+        (setq cpushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg cform (ppc2-acc-reg-for creg))))))
+    (ppc2-one-targeted-reg-form seg dform dreg)
+    (unless ctriv
+      (if cconst
+        (ppc2-one-targeted-reg-form seg cform creg)
+        (ppc2-elide-pushes seg cpushed (ppc2-pop-register seg creg))))
+    (unless btriv 
+      (if bconst
+        (ppc2-one-targeted-reg-form seg bform breg)
+        (ppc2-elide-pushes seg bpushed (ppc2-pop-register seg breg))))
+    (unless atriv
+      (if aconst
+        (ppc2-one-targeted-reg-form seg aform areg)
+        (ppc2-elide-pushes seg apushed (ppc2-pop-register seg areg))))
+    (values areg breg creg dreg)))
+
+(defun ppc2-three-targeted-reg-forms (seg aform areg bform breg cform creg)
+  (let* ((bnode (nx2-node-gpr-p breg))
+         (cnode (nx2-node-gpr-p creg))
+         (atriv (or (null aform) 
+                    (and (ppc2-trivial-p bform)
+                         (ppc2-trivial-p cform)
+                         bnode
+                         cnode)))
+         (btriv (or (null bform)
+                    (and (ppc2-trivial-p cform)
+                         cnode)))
+         (aconst (and (not atriv) 
+                      (or (ppc-side-effect-free-form-p aform)
+                          (let ((avar (ppc2-lexical-reference-p aform)))
+                            (and avar 
+                                 (ppc2-var-not-set-by-form-p avar bform)
+                                 (ppc2-var-not-set-by-form-p avar cform))))))
+         (bconst (and (not btriv)
+                      (or
+                       (ppc-side-effect-free-form-p bform)
+                       (let ((bvar (ppc2-lexical-reference-p bform)))
+                         (and bvar (ppc2-var-not-set-by-form-p bvar cform))))))
+         (apushed nil)
+         (bpushed nil))
+    (if (and aform (not aconst))
+      (if atriv
+        (ppc2-one-targeted-reg-form seg aform areg)
+        (setq apushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg aform (ppc2-acc-reg-for areg))))))
+    (if (and bform (not bconst))
+      (if btriv
+        (ppc2-one-targeted-reg-form seg bform breg)
+        (setq bpushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg bform (ppc2-acc-reg-for breg))))))
+    (ppc2-one-targeted-reg-form seg cform creg)
+    (unless btriv 
+      (if bconst
+        (ppc2-one-targeted-reg-form seg bform breg)
+        (ppc2-elide-pushes seg bpushed (ppc2-pop-register seg breg))))
+    (unless atriv
+      (if aconst
+        (ppc2-one-targeted-reg-form seg aform areg)
+        (ppc2-elide-pushes seg apushed (ppc2-pop-register seg areg))))
+    (values areg breg creg)))
+
+(defun ppc2-three-untargeted-reg-forms (seg aform areg bform breg cform creg)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((bnode (nx2-node-gpr-p breg))
+           (cnode (nx2-node-gpr-p creg))
+           (atriv (or (null aform) 
+                      (and (ppc2-trivial-p bform)
+                           (ppc2-trivial-p cform)
+                           bnode
+                           cnode)))
+           (btriv (or (null bform)
+                      (and (ppc2-trivial-p cform)
+                           cnode)))
+           (aconst (and (not atriv) 
+                        (or (ppc-side-effect-free-form-p aform)
+                            (let ((avar (ppc2-lexical-reference-p aform)))
+                              (and avar 
+                                   (ppc2-var-not-set-by-form-p avar bform)
+                                   (ppc2-var-not-set-by-form-p avar cform))))))
+           (bconst (and (not btriv)
+                        (or
+                         (ppc-side-effect-free-form-p bform)
+                         (let ((bvar (ppc2-lexical-reference-p bform)))
+                           (and bvar (ppc2-var-not-set-by-form-p bvar cform))))))
+           (adest areg)
+           (bdest breg)
+           (cdest creg)
+           (apushed nil)
+           (bpushed nil))
+      (if (and aform (not aconst))
+        (if atriv
+          (setq adest (ppc2-one-untargeted-reg-form seg aform ($ areg)))
+          (setq apushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg aform (ppc2-acc-reg-for areg))))))
+      (if (and bform (not bconst))
+        (if btriv
+          (setq bdest (ppc2-one-untargeted-reg-form seg bform ($ breg)))
+          (setq bpushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg bform (ppc2-acc-reg-for breg))))))
+      (setq cdest (ppc2-one-untargeted-reg-form seg cform creg))
+      (unless btriv 
+        (if bconst
+          (setq bdest (ppc2-one-untargeted-reg-form seg bform breg))
+          (ppc2-elide-pushes seg bpushed (ppc2-pop-register seg breg))))
+      (unless atriv
+        (if aconst
+          (setq adest (ppc2-one-untargeted-reg-form seg aform areg))
+          (ppc2-elide-pushes seg apushed (ppc2-pop-register seg areg))))
+      (values adest bdest cdest))))
+
+(defun ppc2-four-untargeted-reg-forms (seg aform areg bform breg cform creg dform dreg)
+  (let* ((bnode (nx2-node-gpr-p breg))
+         (cnode (nx2-node-gpr-p creg))
+         (dnode (nx2-node-gpr-p dreg))
+         (atriv (or (null aform) 
+                    (and (ppc2-trivial-p bform)
+                         (ppc2-trivial-p cform)
+                         (ppc2-trivial-p dform)
+                         bnode
+                         cnode
+                         dnode)))
+         (btriv (or (null bform)
+                    (and (ppc2-trivial-p cform)
+                         (ppc2-trivial-p dform)
+                         cnode
+                         dnode)))
+         (ctriv (or (null cform)
+                    (and (ppc2-trivial-p dform) dnode)))
+         (aconst (and (not atriv) 
+                      (or (ppc-side-effect-free-form-p aform)
+                          (let ((avar (ppc2-lexical-reference-p aform)))
+                            (and avar 
+                                 (ppc2-var-not-set-by-form-p avar bform)
+                                 (ppc2-var-not-set-by-form-p avar cform)
+                                 (ppc2-var-not-set-by-form-p avar dform))))))
+         (bconst (and (not btriv)
+                      (or
+                       (ppc-side-effect-free-form-p bform)
+                       (let ((bvar (ppc2-lexical-reference-p bform)))
+                         (and bvar
+                              (ppc2-var-not-set-by-form-p bvar cform)
+                              (ppc2-var-not-set-by-form-p bvar dform))))))
+         (cconst (and (not ctriv)
+                      (or
+                       (ppc-side-effect-free-form-p cform)
+                       (let ((cvar (ppc2-lexical-reference-p cform)))
+                         (and cvar
+                              (ppc2-var-not-set-by-form-p cvar dform))))))
+         (adest areg)
+         (bdest breg)
+         (cdest creg)
+         (ddest dreg)
+         (apushed nil)
+         (bpushed nil)
+         (cpushed nil))
+    (if (and aform (not aconst))
+      (if atriv
+        (setq adest (ppc2-one-targeted-reg-form seg aform areg))
+        (setq apushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg aform (ppc2-acc-reg-for areg))))))
+    (if (and bform (not bconst))
+      (if btriv
+        (setq bdest (ppc2-one-untargeted-reg-form seg bform breg))
+        (setq bpushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg bform (ppc2-acc-reg-for breg))))))
+    (if (and cform (not cconst))
+      (if ctriv
+        (setq cdest (ppc2-one-untargeted-reg-form seg cform creg))
+        (setq cpushed (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg cform (ppc2-acc-reg-for creg))))))
+    (setq ddest (ppc2-one-untargeted-reg-form seg dform dreg))
+    (unless ctriv 
+      (if cconst
+        (setq cdest (ppc2-one-untargeted-reg-form seg cform creg))
+        (ppc2-elide-pushes seg cpushed (ppc2-pop-register seg creg))))
+    (unless btriv 
+      (if bconst
+        (setq bdest (ppc2-one-untargeted-reg-form seg bform breg))
+        (ppc2-elide-pushes seg bpushed (ppc2-pop-register seg breg))))
+    (unless atriv
+      (if aconst
+        (setq adest (ppc2-one-untargeted-reg-form seg aform areg))
+        (ppc2-elide-pushes seg apushed (ppc2-pop-register seg areg))))
+    (values adest bdest cdest ddest)))
+
+(defun ppc2-lri (seg reg value)
+  (with-ppc-local-vinsn-macros (seg)
+    (if (>= value 0)
+      (! lri reg value)
+      (target-arch-case
+       (:ppc32 (! lri reg (logand value #xffffffff)))
+       (:ppc64 (! lri reg (logand value #xffffffffffffffff)))))))
+
+
+(defun ppc2-multiple-value-body (seg form)
+  (let* ((lab (backend-get-next-label))
+         (*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+         (old-stack (ppc2-encode-stack)))
+    (with-ppc-local-vinsn-macros (seg)
+      (ppc2-open-undo $undomvexpect)
+      (ppc2-undo-body seg nil (logior $backend-mvpass-mask lab) form old-stack)
+      (@ lab))))
+
+(defun ppc2-afunc-lfun-ref (afunc)
+  (or
+   (afunc-lfun afunc)
+   (progn (pushnew afunc (afunc-fwd-refs *ppc2-cur-afunc*) :test #'eq)
+          afunc)))
+
+(defun ppc2-augment-arglist (afunc arglist &optional (maxregs $numppcargregs))
+  (let ((inherited-args (afunc-inherited-vars afunc)))
+    (when inherited-args
+      (let* ((current-afunc *ppc2-cur-afunc*)
+             (stkargs (car arglist))
+             (regargs (cadr arglist))
+             (inhforms nil)
+             (numregs (length regargs))
+             (own-inhvars (afunc-inherited-vars current-afunc)))
+        (dolist (var inherited-args)
+          (let* ((root-var (nx-root-var var))
+                 (other-guy 
+                  (dolist (v own-inhvars #|(compiler-bug "other guy not found")|# root-var)
+                    (when (eq root-var (nx-root-var v)) (return v)))))
+            (push (make-acode (%nx1-operator inherited-arg) other-guy) inhforms)))
+        (dolist (form inhforms)
+          (if (%i< numregs maxregs)
+            (progn
+              (setq regargs (nconc regargs (list form)))
+              (setq numregs (%i+ numregs 1)))
+            (push form stkargs)))
+        (%rplaca (%cdr arglist) regargs) ; might have started out NIL.
+        (%rplaca arglist stkargs)))) 
+  arglist)
+
+
+
+;;; There are other cases involving constants that are worth exploiting.
+(defun ppc2-compare (seg vreg xfer i j cr-bit true-p)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((js16 (acode-s16-constant-p j))
+           (is16 (acode-s16-constant-p i))
+           (boolean (backend-crf-p vreg)))
+      (if (and boolean (or js16 is16))
+        (let* ((reg (ppc2-one-untargeted-reg-form seg (if js16 i j) ppc::arg_z)))
+          (! compare-signed-s16const vreg reg (or js16 is16))
+          (unless (or js16 (eq cr-bit ppc::ppc-eq-bit))
+            (setq cr-bit (- 1 cr-bit)))
+          (^ cr-bit true-p))
+        (if (and (eq cr-bit ppc::ppc-eq-bit) 
+                 (or js16 is16))
+          (ppc2-test-reg-%izerop 
+           seg 
+           vreg 
+           xfer 
+           (ppc2-one-untargeted-reg-form 
+            seg 
+            (if js16 i j) 
+            ppc::arg_z) 
+           cr-bit 
+           true-p 
+           (or js16 is16))
+          (multiple-value-bind (ireg jreg) (ppc2-two-untargeted-reg-forms seg i ppc::arg_y j ppc::arg_z)
+            (ppc2-compare-registers seg vreg xfer ireg jreg cr-bit true-p)))))))
+
+(defun ppc2-natural-compare (seg vreg xfer i j cr-bit true-p)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((jconstant (acode-fixnum-form-p j))
+           (ju16 (typep jconstant '(unsigned-byte 16)))
+           (iconstant (acode-fixnum-form-p i))
+           (iu16 (typep iconstant '(unsigned-byte 16)))
+           (boolean (backend-crf-p vreg)))
+      (if (and boolean (or ju16 iu16))
+        (with-imm-target
+            () (reg :natural)
+            (ppc2-one-targeted-reg-form seg (if ju16 i j) reg)
+            (! compare-unsigned-u16const vreg reg (if ju16 jconstant iconstant))
+            (unless (or ju16 (eq cr-bit ppc::ppc-eq-bit)) 
+              (setq cr-bit (- 1 cr-bit)))
+            (^ cr-bit true-p))
+        (with-imm-target ()
+          (ireg :natural)
+            (with-imm-target 
+                (ireg) (jreg :natural)
+                (ppc2-two-targeted-reg-forms seg i ireg j jreg)
+                (ppc2-compare-natural-registers seg vreg xfer ireg jreg cr-bit true-p)))))))
+
+(defun ppc2-compare-natural-registers (seg vreg xfer ireg jreg cr-bit true-p)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (progn
+         (! compare-logical dest ireg jreg)
+         (^ cr-bit true-p))
+       (with-imm-temps () ((b31-reg :natural))
+         (ecase cr-bit
+           (#. ppc::ppc-eq-bit 
+            (if true-p
+              (! eq->bit31 b31-reg ireg jreg)
+              (! ne->bit31 b31-reg ireg jreg)))
+           (#. ppc::ppc-lt-bit
+            (if true-p
+              (! ltu->bit31 b31-reg ireg jreg)
+              (! geu->bit31 b31-reg ireg jreg)))
+           (#. ppc::ppc-gt-bit
+            (if true-p
+              (! gtu->bit31 b31-reg ireg jreg)
+              (! leu->bit31 b31-reg ireg jreg))))
+         (ensuring-node-target (target dest)
+           (! lowbit->truth target b31-reg))
+         (^)))
+      (^))))
+
+(defun ppc2-compare-registers (seg vreg xfer ireg jreg cr-bit true-p)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (progn
+         (! compare dest ireg jreg)
+         (^ cr-bit true-p))
+       (with-imm-temps () ((b31-reg :natural))
+         (ecase cr-bit
+           (#. ppc::ppc-eq-bit 
+            (if true-p
+              (! eq->bit31 b31-reg ireg jreg)
+              (! ne->bit31 b31-reg ireg jreg)))
+           (#. ppc::ppc-lt-bit
+            (if true-p
+              (! lt->bit31 b31-reg ireg jreg)
+              (! ge->bit31 b31-reg ireg jreg)))
+           (#. ppc::ppc-gt-bit
+            (if true-p
+              (! gt->bit31 b31-reg ireg jreg)
+              (! le->bit31 b31-reg ireg jreg))))
+         (ensuring-node-target (target dest)
+           (! lowbit->truth target b31-reg))
+         (^)))
+      (^))))
+
+(defun ppc2-compare-register-to-nil (seg vreg xfer ireg cr-bit true-p)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (progn
+         (! compare-to-nil dest ireg)
+         (^ cr-bit true-p))
+       (with-imm-temps () ((b31-reg :natural))
+         (ecase cr-bit
+           (#. ppc::ppc-eq-bit 
+            (if true-p
+              (! eqnil->bit31 b31-reg ireg)
+              (! nenil->bit31 b31-reg ireg))))
+         (ensuring-node-target (target dest)
+           (! lowbit->truth target b31-reg))
+         (^)))
+      (^))))
+
+;;; Have to extract a bit out of the CR when a boolean result needed.
+(defun ppc2-compare-double-float-registers (seg vreg xfer ireg jreg cr-bit true-p)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (progn
+         (! double-float-compare dest ireg jreg)
+         (^ cr-bit true-p))
+       (with-imm-temps () ((lowbit-reg :natural))
+         (with-crf-target () flags
+           (! double-float-compare flags ireg jreg)
+           (! crbit->bit31 lowbit-reg flags cr-bit))
+         (unless true-p
+           (! invert-lowbit lowbit-reg))
+         (ensuring-node-target (target dest)
+           (! lowbit->truth target lowbit-reg))
+         (^)))
+      (^))))
+
+
+(defun ppc2-immediate-form-p (form)
+  (if (and (consp form)
+           (or (eq (%car form) (%nx1-operator immediate))
+               (eq (%car form) (%nx1-operator simple-function))))
+    t))
+
+(defun ppc2-test-%izerop (seg vreg xfer form cr-bit true-p)
+  (ppc2-test-reg-%izerop seg vreg xfer (ppc2-one-untargeted-reg-form seg form ppc::arg_z) cr-bit true-p 0))
+
+(defun ppc2-test-reg-%izerop (seg vreg xfer reg cr-bit true-p  zero)
+  (declare (fixnum reg zero))
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (regspec-crf-gpr-case 
+     (vreg dest)
+     (progn
+       (! compare-signed-s16const dest reg zero)
+       (^ cr-bit true-p))
+     (with-imm-temps (reg) (b31-reg scaled)
+       (if (zerop zero)
+         (setq scaled reg)
+         (! subtract-constant scaled reg zero))
+       (ecase cr-bit
+         (#. ppc::ppc-eq-bit 
+          (if true-p
+            (! eq0->bit31 b31-reg scaled)
+            (! ne0->bit31 b31-reg scaled)))
+         (#. ppc::ppc-lt-bit
+          (if true-p
+            (! lt0->bit31 b31-reg scaled)
+            (! ge0->bit31 b31-reg scaled)))
+         (#. ppc::ppc-gt-bit
+          (if true-p
+            (! gt0->bit31 b31-reg scaled)
+            (! le0->bit31 b31-reg scaled))))
+          (ensuring-node-target (target dest)
+            (! lowbit->truth target b31-reg))
+       (^)))))
+
+(defun ppc2-lexical-reference-ea (form &optional (no-closed-p t))
+  (when (acode-p (setq form (acode-unwrapped-form-value form)))
+    (if (eq (acode-operator form) (%nx1-operator lexical-reference))
+      (let* ((addr (var-ea (%cadr form))))
+        (if (typep addr 'lreg)
+          addr
+          (unless (and no-closed-p (addrspec-vcell-p addr ))
+            addr))))))
+
+
+(defun ppc2-vpush-register (seg src &optional why info attr)
+  (with-ppc-local-vinsn-macros (seg)
+    (prog1
+      (! vpush-register src)
+      (ppc2-new-vstack-lcell (or why :node) *ppc2-target-lcell-size* (or attr 0) info)
+      (ppc2-adjust-vstack *ppc2-target-node-size*))))
+
+(defun ppc2-vpush-register-arg (seg src)
+  (ppc2-vpush-register seg src :outgoing-argument))
+
+
+(defun ppc2-vpop-register (seg dest)
+  (with-ppc-local-vinsn-macros (seg)
+    (prog1
+      (! vpop-register dest)
+      (setq *ppc2-top-vstack-lcell* (lcell-parent *ppc2-top-vstack-lcell*))
+      (ppc2-adjust-vstack (- *ppc2-target-node-size*)))))
+
+(defun ppc2-copy-register (seg dest src)
+  (with-ppc-local-vinsn-macros (seg)
+    (when dest
+      (let* ((dest-gpr (backend-ea-physical-reg dest hard-reg-class-gpr))
+             (src-gpr (if src (backend-ea-physical-reg src hard-reg-class-gpr)))
+             (dest-fpr (backend-ea-physical-reg dest hard-reg-class-fpr))
+             (src-fpr (if src (backend-ea-physical-reg src hard-reg-class-fpr)))
+             (src-mode (if src (get-regspec-mode src)))
+             (dest-mode (get-regspec-mode dest))
+             (dest-crf (backend-ea-physical-reg dest hard-reg-class-crf)))
+        (if (and dest-gpr (eql dest-gpr ppc::rzero))
+          (compiler-bug "Bad destination register: ~s" dest-gpr))
+        (if (null src)
+          (if dest-gpr
+            (! load-nil dest-gpr)
+            (if dest-crf
+              (! set-eq-bit dest-crf)))
+          (if (and dest-crf src-gpr)
+            ;; "Copying" a GPR to a CR field means comparing it to rnil
+            (! compare-to-nil dest src)
+            (if (and dest-gpr src-gpr)
+              (if (eql src-gpr ppc::rzero)        
+                ;; Rzero always contains 0, so we can
+                ;; save ourselves some trouble.
+                ;; This assumes that (LI dest-gpr 0) is easier
+                ;; on the register-renaming pipeline nonsense than
+                ;; (MR dest-gpr rzero) would be.
+                (! lri dest-gpr 0)
+                ;; This is the "GPR <- GPR" case.  There are
+                ;; word-size dependencies, but there's also
+                ;; lots of redundancy here.
+                (target-word-size-case
+                 (32
+                  (case dest-mode
+                    (#.hard-reg-class-gpr-mode-node ; boxed result.
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u32
+                        (ppc2-box-u32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-s32
+                        (ppc2-box-s32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-address
+                        (! macptr->heap dest src))))
+                    ((#.hard-reg-class-gpr-mode-u32
+                      #.hard-reg-class-gpr-mode-address)
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (let* ((src-type (get-node-regspec-type-modes src)))
+                          (declare (fixnum src-type))
+                          (case dest-mode
+                            (#.hard-reg-class-gpr-mode-u32
+                             (! unbox-u32 dest src))
+                            (#.hard-reg-class-gpr-mode-address
+                             (unless (or (logbitp #.hard-reg-class-gpr-mode-address src-type)
+                                         *ppc2-reckless*)
+                               (! trap-unless-macptr src))
+                             (! deref-macptr dest src)))))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       ((#.hard-reg-class-gpr-mode-u16
+                         #.hard-reg-class-gpr-mode-s16)
+                        (! u16->u32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! u8->u32 dest src))))
+                    (#.hard-reg-class-gpr-mode-s32
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->u32 dest src))                 
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))))
+                    (#.hard-reg-class-gpr-mode-u16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-u16 dest src))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s16 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-u8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (if *ppc2-reckless*
+                          (! %unbox-u8 dest src)
+                          (! unbox-u8 dest src)))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s8 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))))
+                 (64
+                  (case dest-mode
+                    (#.hard-reg-class-gpr-mode-node ; boxed result.
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u64
+                        (ppc2-box-u64 seg dest src))
+                       (#.hard-reg-class-gpr-mode-s64
+                        (ppc2-box-s64 seg dest src))
+                       (#.hard-reg-class-gpr-mode-u32
+                        (ppc2-box-u32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-s32
+                        (ppc2-box-s32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-address
+                        (! macptr->heap dest src))))
+                    ((#.hard-reg-class-gpr-mode-u64
+                      #.hard-reg-class-gpr-mode-address)
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (let* ((src-type (get-node-regspec-type-modes src)))
+                          (declare (fixnum src-type))
+                          (case dest-mode
+                            (#.hard-reg-class-gpr-mode-u64
+                             (! unbox-u64 dest src))
+                            (#.hard-reg-class-gpr-mode-address
+                             (unless (or (logbitp #.hard-reg-class-gpr-mode-address src-type)
+                                         *ppc2-reckless*)
+                               (! trap-unless-macptr src))
+                             (! deref-macptr dest src)))))
+                       ((#.hard-reg-class-gpr-mode-u64
+                         #.hard-reg-class-gpr-mode-s64
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       ((#.hard-reg-class-gpr-mode-u16
+                         #.hard-reg-class-gpr-mode-s16)
+                        (! u16->u32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! u8->u32 dest src))))
+                    (#.hard-reg-class-gpr-mode-s32
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->u32 dest src))                 
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))))
+                    (#.hard-reg-class-gpr-mode-u32
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+			(if *ppc2-reckless*
+			  (! %unbox-u32 dest src)
+			  (! unbox-u32 dest src)))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->u32 dest src))                 
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))))
+                    (#.hard-reg-class-gpr-mode-u16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-u16 dest src))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s16 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-u8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (if *ppc2-reckless*
+                          (! %unbox-u8 dest src)
+                          (! unbox-u8 dest src)))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s8 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))))))
+              (if src-gpr
+                (if dest-fpr
+                  (progn
+                    (case src-mode
+                      (#.hard-reg-class-gpr-mode-node
+                       (case dest-mode
+                         (#.hard-reg-class-fpr-mode-double
+                          (unless (or (logbitp hard-reg-class-fpr-type-double 
+                                           (get-node-regspec-type-modes src))
+                                      *ppc2-reckless*)
+                            (! trap-unless-double-float src))
+                          (! get-double dest src))
+                         (#.hard-reg-class-fpr-mode-single
+                          (unless *ppc2-reckless*
+                            (! trap-unless-single-float src))
+                          (! get-single dest src)))))))
+                (if dest-gpr
+                  (case dest-mode
+                    (#.hard-reg-class-gpr-mode-node
+                     (case src-mode
+                       (#.hard-reg-class-fpr-mode-double
+                        (! double->heap dest src))
+                       (#.hard-reg-class-fpr-mode-single
+                        (! single->node dest src)))))
+                  (if (and src-fpr dest-fpr)
+                    (unless (eql dest-fpr src-fpr)
+                      (! copy-fpr dest src))))))))))))
+  
+(defun ppc2-unreachable-store (&optional vreg)
+  ;; I don't think that anything needs to be done here,
+  ;; but leave this guy around until we're sure.
+  ;; (PPC2-VPUSH-REGISTER will always vpush something, even
+  ;; if code to -load- that "something" never gets generated.
+  ;; If I'm right about this, that means that the compile-time
+  ;; stack-discipline problem that this is supposed to deal
+  ;; with can't happen.)
+  (declare (ignore vreg))
+  nil)
+
+;;; bind vars to initforms, as per let*, &aux.
+(defun ppc2-seq-bind (seg vars initforms)
+  (dolist (var vars)
+    (ppc2-seq-bind-var seg var (pop initforms))))
+
+(defun ppc2-dynamic-extent-form (seg curstack val &aux (form val))
+  (when (acode-p form)
+    (with-note (form seg curstack) ; note this rebinds form/seg/curstack so can't setq
+      (with-ppc-local-vinsn-macros (seg)
+	(let* ((op (acode-operator form)))
+	  (cond ((eq op (%nx1-operator list))
+		 (let* ((*ppc2-vstack* *ppc2-vstack*)
+			(*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+		   (ppc2-set-nargs seg (ppc2-formlist seg (%cadr form) nil))
+		   (ppc2-open-undo $undostkblk curstack)
+		   (! stack-cons-list))
+		 (setq val ppc::arg_z))
+		((eq op (%nx1-operator list*))
+		 (let* ((arglist (%cadr form)))                   
+		   (let* ((*ppc2-vstack* *ppc2-vstack*)
+			  (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+		     (ppc2-arglist seg arglist))
+		   (when (car arglist)
+		     (ppc2-set-nargs seg (length (%car arglist)))
+		     (! stack-cons-list*)
+		     (ppc2-open-undo $undostkblk curstack))
+		   (setq val ppc::arg_z)))
+		((eq op (%nx1-operator multiple-value-list))
+		 (ppc2-multiple-value-body seg (%cadr form))
+		 (ppc2-open-undo $undostkblk curstack)
+		 (! stack-cons-list)
+		 (setq val ppc::arg_z))
+		((eq op (%nx1-operator cons))
+		 (let* ((y ($ ppc::arg_y))
+			(z ($ ppc::arg_z))
+			(result ($ ppc::arg_z)))
+		   (ppc2-two-targeted-reg-forms seg (%cadr form) y (%caddr form) z)
+		   (ppc2-open-undo $undostkblk )
+		   (! make-tsp-cons result y z) 
+		   (setq val result)))
+		((eq op (%nx1-operator %consmacptr%))
+		 (with-imm-target () (address :address)
+		   (ppc2-one-targeted-reg-form seg form address)
+		   (with-node-temps () (node)
+		     (! macptr->stack node address)
+		     (ppc2-open-undo $undostkblk)
+		     (setq val node))))
+		((eq op (%nx1-operator %new-ptr))
+		 (let* ((clear-form (caddr form))
+			(cval (nx2-constant-form-value clear-form)))
+		   (if cval
+		       (progn 
+			 (ppc2-one-targeted-reg-form seg (%cadr form) ($ ppc::arg_z))
+			 (if (nx-null cval)
+			     (! make-stack-block)
+			     (! make-stack-block0)))
+		       (with-crf-target () crf
+			 (let ((stack-block-0-label (backend-get-next-label))
+			       (done-label (backend-get-next-label))
+			       (rval ($ ppc::arg_z))
+			       (rclear ($ ppc::arg_y)))
+			   (ppc2-two-targeted-reg-forms seg (%cadr form) rval clear-form rclear)
+			   (! compare-to-nil crf rclear)
+			   (! cbranch-false (aref *backend-labels* stack-block-0-label) crf ppc::ppc-eq-bit)
+			   (! make-stack-block)
+			   (-> done-label)
+			   (@ stack-block-0-label)
+			   (! make-stack-block0)
+			   (@ done-label)))))
+		 (ppc2-open-undo $undostkblk)
+		 (setq val ($ ppc::arg_z)))
+		((eq op (%nx1-operator make-list))
+		 (ppc2-two-targeted-reg-forms seg (%cadr form) ($ ppc::arg_y) (%caddr form) ($ ppc::arg_z))
+		 (ppc2-open-undo $undostkblk curstack)
+		 (! make-stack-list)
+		 (setq val ppc::arg_z))       
+		((eq op (%nx1-operator vector))
+		 (let* ((*ppc2-vstack* *ppc2-vstack*)
+			(*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+		   (ppc2-set-nargs seg (ppc2-formlist seg (%cadr form) nil))
+		   (! make-stack-vector))
+		 (ppc2-open-undo $undostkblk)
+		 (setq val ppc::arg_z))
+		((eq op (%nx1-operator %gvector))
+		 (let* ((*ppc2-vstack* *ppc2-vstack*)
+			(*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+			(arglist (%cadr form)))
+		   (ppc2-set-nargs seg (ppc2-formlist seg (append (car arglist) (reverse (cadr arglist))) nil))
+		   (! make-stack-gvector))
+		 (ppc2-open-undo $undostkblk)
+		 (setq val ppc::arg_z)) 
+		((eq op (%nx1-operator closed-function)) 
+		 (setq val (ppc2-make-closure seg (cadr form) t))) ; can't error
+		((eq op (%nx1-operator %make-uvector))
+		 (destructuring-bind (element-count subtag &optional (init 0 init-p)) (%cdr form)
+		   (if init-p
+		       (progn
+			 (ppc2-three-targeted-reg-forms seg element-count ($ ppc::arg_x) subtag ($ ppc::arg_y) init ($ ppc::arg_z))
+			 (! stack-misc-alloc-init))
+		       (progn
+			 (ppc2-two-targeted-reg-forms seg element-count ($ ppc::arg_y)  subtag ($ ppc::arg_z))
+			 (! stack-misc-alloc)))
+		   (ppc2-open-undo $undostkblk)
+		   (setq val ($ ppc::arg_z)))))))))
+  val)
+
+(defun ppc2-addrspec-to-reg (seg addrspec reg)
+  (if (memory-spec-p addrspec)
+    (ppc2-stack-to-register seg addrspec reg)
+    (ppc2-copy-register seg reg addrspec)))
+  
+(defun ppc2-seq-bind-var (seg var val)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((sym (var-name var))
+           (bits (nx-var-bits var))
+           (closed-p (and (%ilogbitp $vbitclosed bits)
+                          (%ilogbitp $vbitsetq bits)))
+           (curstack (ppc2-encode-stack))
+           (make-vcell (and closed-p (eq bits (var-bits var))))
+           (closed-downward (and closed-p (%ilogbitp $vbitcloseddownward bits))))
+      (unless (fixnump val)
+        (setq val (nx-untyped-form val))
+        (when (and (%ilogbitp $vbitdynamicextent bits) (acode-p val))
+          (setq val (ppc2-dynamic-extent-form seg curstack val))))
+      (if (%ilogbitp $vbitspecial bits)
+        (progn
+          (ppc2-dbind seg val sym)
+          (ppc2-set-var-ea seg var (ppc2-vloc-ea (- *ppc2-vstack* *ppc2-target-node-size*))))
+        (let ((puntval nil))
+          (flet ((ppc2-puntable-binding-p (var initform)
+                   ; The value returned is acode.
+                   (let* ((bits (nx-var-bits var)))
+                     (if (%ilogbitp $vbitpuntable bits)
+                       initform))))
+            (declare (inline ppc2-puntable-binding-p))
+            (if (and (not (ppc2-load-ea-p val))
+                     (setq puntval (ppc2-puntable-binding-p var val)))
+              (progn
+                (nx-set-var-bits var (%ilogior (%ilsl $vbitpunted 1) bits))
+                (nx2-replace-var-refs var puntval)
+                (ppc2-set-var-ea seg var puntval))
+              (progn
+                (let* ((vloc *ppc2-vstack*)
+                       (reg (let* ((r (nx2-assign-register-var var)))
+                              (if r ($ r)))))
+                  (if (ppc2-load-ea-p val)
+                    (if reg
+                      (ppc2-addrspec-to-reg seg val reg)
+                      (if (memory-spec-p val)
+                        (with-node-temps () (temp)
+                          (ppc2-addrspec-to-reg seg val temp)
+                          (ppc2-vpush-register seg temp :node var bits))
+                        (ppc2-vpush-register seg val :node var bits)))
+                    (if reg
+                      (ppc2-one-targeted-reg-form seg val reg)
+                      (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg val ppc::arg_z) :node var bits)))
+                  (ppc2-set-var-ea seg var (or reg (ppc2-vloc-ea vloc closed-p)))
+                  (if reg
+                    (ppc2-note-var-cell var reg)
+                    (ppc2-note-top-cell var))
+                  (when make-vcell
+                    (with-node-temps () (vcell closed)
+                        (ppc2-stack-to-register seg vloc closed)
+                        (if closed-downward
+                          (progn
+                            (! make-tsp-vcell vcell closed)
+                            (ppc2-open-undo $undostkblk))
+                          (! make-vcell vcell closed))
+                        (ppc2-register-to-stack seg vcell vloc))))))))))))
+
+
+
+;;; Never make a vcell if this is an inherited var.
+;;; If the var's inherited, its bits won't be a fixnum (and will
+;;; therefore be different from what NX-VAR-BITS returns.)
+(defun ppc2-bind-var (seg var vloc &optional lcell &aux 
+                          (bits (nx-var-bits var)) 
+                          (closed-p (and (%ilogbitp $vbitclosed bits) (%ilogbitp $vbitsetq bits)))
+                          (closed-downward (if closed-p (%ilogbitp $vbitcloseddownward bits)))
+                          (make-vcell (and closed-p (eq bits (var-bits var))))
+                          (addr (ppc2-vloc-ea vloc)))
+  (with-ppc-local-vinsn-macros (seg)
+    (if (%ilogbitp $vbitspecial bits)
+      (progn
+        (ppc2-dbind seg addr (var-name var))
+        (ppc2-set-var-ea seg var (ppc2-vloc-ea (- *ppc2-vstack* *ppc2-target-node-size*)))
+        t)
+      (progn
+        (when (%ilogbitp $vbitpunted bits)
+          (compiler-bug "bind-var: var ~s was punted" var))
+        (when make-vcell
+          (with-node-temps () (vcell closed)
+            (ppc2-stack-to-register seg vloc closed)
+            (if closed-downward
+              (progn
+                (! make-tsp-vcell vcell closed)
+                (ppc2-open-undo $undostkblk))
+              (! make-vcell vcell closed))
+            (ppc2-register-to-stack seg vcell vloc)))
+        (when lcell
+          (setf (lcell-kind lcell) :node
+                (lcell-attributes lcell) bits
+                (lcell-info lcell) var)
+          (ppc2-note-var-cell var lcell))          
+        (ppc2-set-var-ea seg var (ppc2-vloc-ea vloc closed-p))        
+        closed-downward))))
+
+(defun ppc2-set-var-ea (seg var ea)
+  (setf (var-ea var) ea)
+  (when (and *ppc2-record-symbols* (or (typep ea 'lreg) (typep ea 'fixnum)))
+    (let* ((start (ppc2-emit-note seg :begin-variable-scope)))
+      (push (list var (var-name var) start (close-vinsn-note start))
+            *ppc2-recorded-symbols*)))
+  ea)
+
+(defun ppc2-close-var (seg var)
+  (let ((bits (nx-var-bits var)))
+    (when (and *ppc2-record-symbols*
+               (or (logbitp $vbitspecial bits)
+                   (not (logbitp $vbitpunted bits))))
+      (let ((endnote (%car (%cdddr (assq var *ppc2-recorded-symbols*)))))
+        (unless endnote (compiler-bug "ppc2-close-var for ~s ?" (var-name var)))
+        (setf (vinsn-note-class endnote) :end-variable-scope)
+        (append-dll-node (vinsn-note-label endnote) seg)))))
+
+(defun ppc2-load-ea-p (ea)
+  (or (typep ea 'fixnum)
+      (typep ea 'lreg)
+      (typep ea 'lcell)))
+
+(defun ppc2-dbind (seg value sym)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((ea-p (ppc2-load-ea-p value))
+           (nil-p (unless ea-p (nx-null (setq value (nx-untyped-form value)))))
+           (self-p (unless ea-p (and (or
+                                      (eq (acode-operator value) (%nx1-operator bound-special-ref))
+                                      (eq (acode-operator value) (%nx1-operator special-ref)))
+                                     (eq (cadr value) sym)))))
+      (cond ((eq sym '*interrupt-level*)
+             (let* ((fixval (acode-fixnum-form-p value)))
+               (cond ((eql fixval 0) (if *ppc2-open-code-inline*
+                                       (! bind-interrupt-level-0-inline)
+                                       (! bind-interrupt-level-0)))
+                     ((eql fixval -1) (if *ppc2-open-code-inline*
+                                        (! bind-interrupt-level-m1-inline)
+                                        (! bind-interrupt-level-m1)))
+                     (t
+                      (if ea-p 
+                        (ppc2-store-ea seg value ppc::arg_z)
+                        (ppc2-one-targeted-reg-form seg value ($ ppc::arg_z)))
+                      (! bind-interrupt-level))))
+             (ppc2-open-undo $undointerruptlevel))
+            (t
+             (if (or nil-p self-p)
+               (progn
+                 (ppc2-store-immediate seg (ppc2-symbol-value-cell sym) ppc::arg_z)
+                 (if nil-p
+                   (! bind-nil)
+                   (if (or *ppc2-reckless* (eq (acode-operator value) (%nx1-operator special-ref)))
+                     (! bind-self)
+                     (! bind-self-boundp-check))))
+               (progn
+                 (if ea-p 
+                   (ppc2-store-ea seg value ppc::arg_z)
+                   (ppc2-one-targeted-reg-form seg value ($ ppc::arg_z)))
+                 (ppc2-store-immediate seg (ppc2-symbol-value-cell sym) ($ ppc::arg_y))
+                 (! bind)))
+             (ppc2-open-undo $undospecial)))
+      (ppc2-new-vstack-lcell :special-value *ppc2-target-lcell-size* 0 sym)
+      (ppc2-new-vstack-lcell :special *ppc2-target-lcell-size* (ash 1 $vbitspecial) sym)
+      (ppc2-new-vstack-lcell :special-link *ppc2-target-lcell-size* 0 sym)
+      (ppc2-adjust-vstack (* 3 *ppc2-target-node-size*)))))
+
+;;; Store the contents of EA - which denotes either a vframe location
+;;; or a hard register - in reg.
+
+(defun ppc2-store-ea (seg ea reg)
+  (if (typep ea 'fixnum)
+    (if (memory-spec-p ea)
+      (ppc2-stack-to-register seg ea reg)
+      (ppc2-copy-register seg reg ea))
+    (if (typep ea 'lreg)
+      (ppc2-copy-register seg reg ea)
+      (if (typep ea 'lcell)
+        (ppc2-lcell-to-register seg ea reg)))))
+
+
+      
+
+;;; Callers should really be sure that this is what they want to use.
+(defun ppc2-absolute-natural (seg vreg xfer value)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (ppc2-lri seg vreg value))
+    (^)))
+
+
+
+(defun ppc2-store-macptr (seg vreg address-reg)
+  (with-ppc-local-vinsn-macros (seg vreg)
+    (when (ppc2-for-value-p vreg)
+      (if (logbitp vreg ppc-imm-regs)
+        (<- address-reg)
+        (! macptr->heap vreg address-reg)))))
+
+(defun ppc2-store-signed-longword (seg vreg imm-reg)
+  (with-ppc-local-vinsn-macros (seg vreg)
+    (when (ppc2-for-value-p vreg)
+      (if (logbitp vreg ppc-imm-regs)
+        (<- imm-reg)
+        (ppc2-box-s32 seg vreg imm-reg)))))
+
+(defun ppc2-store-signed-halfword (seg vreg imm-reg)
+  (with-ppc-local-vinsn-macros (seg vreg)
+    (when (ppc2-for-value-p vreg)
+      (if (logbitp vreg ppc-imm-regs)
+        (<- imm-reg)
+        (! s16->fixnum vreg imm-reg)))))
+
+
+(defun ppc2-store-unsigned-halfword (seg vreg imm-reg)
+  (with-ppc-local-vinsn-macros (seg vreg)
+    (when (ppc2-for-value-p vreg)
+      (if (logbitp vreg ppc-imm-regs)
+        (<- imm-reg)
+        (! u16->fixnum vreg imm-reg)))))
+
+
+
+;;; If "value-first-p" is true and both "offset" and "val" need to be 
+;;; evaluated, evaluate "val" before evaluating "offset".
+(defun ppc2-%immediate-set-ptr (seg vreg xfer  ptr offset val)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((intval (acode-absolute-ptr-p val))
+           (offval (acode-fixnum-form-p offset))
+           (absptr (and offval (acode-absolute-ptr-p ptr)))
+           (for-value (ppc2-for-value-p vreg)))
+      (flet ((address-and-node-regs ()
+               (if for-value
+                 (progn
+                   (ppc2-one-targeted-reg-form seg val ($ ppc::arg_z))
+                   (if (eq intval 0)
+                     (values ppc::rzero ppc::arg_z)
+                     (progn
+                       (if intval
+                         (ppc2-lri seg ppc::imm0 intval)
+                         (! deref-macptr ppc::imm0 ppc::arg_z))
+                       (values ppc::imm0 ppc::arg_z))))
+                 (if (eq intval 0)
+                   (values ppc::rzero nil)
+                   (values (ppc2-macptr-arg-to-reg seg val ($ ppc::imm0 :mode :address)) nil)))))
+        (if (and absptr offval)
+          (setq absptr (+ absptr offval) offval 0)
+          (setq absptr nil))
+        (and offval (%i> (integer-length offval) 15) (setq offval nil))
+        (and absptr (%i> (integer-length absptr) 15) (setq absptr nil))
+        (target-arch-case
+         (:ppc32 (progn))
+         (:ppc64 (progn
+                   (and offval (logtest 3 offval) (setq offval nil))
+                   (and absptr (logtest 3 absptr) (setq absptr nil)))))
+        (if absptr
+          (multiple-value-bind (address node) (address-and-node-regs)
+            (! mem-set-c-address address ppc::rzero absptr)
+            (if for-value
+              (<- node)))
+          ; No absolute ptr (which is presumably a rare case anyway.)
+          (if offval
+            ; Easier: need one less register than in the general case.
+            (with-imm-target () (ptr-reg :address)
+              (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+              (if intval
+                (with-imm-target (ptr-reg) (val-target :address)
+                  (if (eql intval 0)
+                    (setq val-target ppc::rzero)
+                    (ppc2-lri seg val-target intval))
+                  (! mem-set-c-address val-target ptr-reg offval)
+                  (if for-value
+                    (<- (set-regspec-mode val-target (gpr-mode-name-value :address)))))
+                (progn
+                  (! temp-push-unboxed-word ptr-reg)
+                  (ppc2-open-undo $undostkblk)
+                  (multiple-value-bind (address node) (address-and-node-regs)
+                    (with-imm-target (address) (ptr-reg :address)
+                      (! temp-pop-unboxed-word ptr-reg)
+                      (ppc2-close-undo)
+                      (! mem-set-c-address address ptr-reg offval)
+                      (if for-value
+                        (<- node)))))))
+            ;; No (16-bit) constant offset.  Might still have a 32-bit
+            ;; constant offset; might have a constant value.  Might
+            ;; not.  Might not.  Easiest to special-case the
+            ;; constant-value case first ...
+            (let* ((xptr-reg nil)
+                   (xoff-reg nil)
+                   (xval-reg nil)
+                   (node-arg_z nil)
+                   (constant-offset (acode-fixnum-form-p offset)))
+              (if intval
+                (if constant-offset
+                  (with-imm-target () (ptr-reg :address)
+                    (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+                    (with-imm-target (ptr-reg) (off-reg :signed-natural)
+                      (ppc2-lri seg off-reg constant-offset)
+                      (with-imm-target (ptr-reg off-reg) (val-reg :address)
+                        (if (eql intval 0)
+                          (setq val-reg ppc::rzero)
+                          (ppc2-lri seg val-reg intval))
+                        (setq xptr-reg ptr-reg
+                              xoff-reg off-reg
+                              xval-reg val-reg))))
+                  ; Offset's non-constant.  Temp-push the pointer, evaluate
+                  ; and unbox the offset, load the value, pop the pointer.
+                  (progn
+                    (with-imm-target () (ptr-reg :address)
+                      (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+                      (! temp-push-unboxed-word ptr-reg)
+                      (ppc2-open-undo $undostkblk))
+                    (with-imm-target () (off-reg :signed-natural)
+                      (! fixnum->signed-natural off-reg (ppc2-one-targeted-reg-form seg offset ($ ppc::arg_z)))
+                      (with-imm-target (off-reg) (val-reg :signed-natural)
+                        (if (eql intval 0)
+                          (setq val-reg ppc::rzero)
+                          (ppc2-lri seg val-reg intval))
+                        (with-imm-target (off-reg val-reg) (ptr-reg :address)
+                          (! temp-pop-unboxed-word ptr-reg)
+                          (ppc2-close-undo)
+                          (setq xptr-reg ptr-reg
+                                xoff-reg off-reg
+                                xval-reg val-reg))))))
+                ;; No intval; maybe constant-offset.
+                (with-imm-target () (ptr-reg :address)
+                  (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+                  (! temp-push-unboxed-word ptr-reg)
+                  (ppc2-open-undo $undostkblk)
+                  (progn
+                    (if (not constant-offset)
+                      (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z)))
+                    (multiple-value-bind (address node) (address-and-node-regs)
+                      (with-imm-target (address) (off-reg :s32)
+                                       (if constant-offset
+                                         (ppc2-lri seg off-reg constant-offset)
+                                         (with-node-temps (ppc::arg_z) (temp)
+                                           (ppc2-vpop-register seg temp)
+                                           (! fixnum->signed-natural off-reg temp)))
+                                       (with-imm-target (ppc::imm0 off-reg) (ptr-reg :address)
+                                                        (! temp-pop-unboxed-word ptr-reg)
+                                                        (ppc2-close-undo)
+                            (setq xptr-reg ptr-reg
+                                  xoff-reg off-reg
+                                  xval-reg address
+                                  node-arg_z node)))))))
+              (! mem-set-address xval-reg xptr-reg xoff-reg)
+              (when for-value
+                (if node-arg_z
+                  (<- node-arg_z)
+                  (<- (set-regspec-mode 
+                       xval-reg
+                       (gpr-mode-name-value :address))))))))
+        (^)))))
+  
+(defun ppc2-memory-store-displaced (seg valreg basereg displacement size)
+  (with-ppc-local-vinsn-macros (seg)
+    (case size
+      (8 (! mem-set-c-doubleword valreg basereg displacement))
+      (4 (! mem-set-c-fullword valreg basereg displacement))
+      (2 (! mem-set-c-halfword valreg basereg displacement))
+      (1 (! mem-set-c-byte valreg basereg displacement)))))
+
+(defun ppc2-memory-store-indexed (seg valreg basereg idxreg size)
+  (with-ppc-local-vinsn-macros (seg)
+    (case size
+      (8 (! mem-set-doubleword valreg basereg idxreg))
+      (4 (! mem-set-fullword valreg basereg idxreg))
+      (2 (! mem-set-halfword valreg basereg idxreg))
+      (1 (! mem-set-byte valreg basereg idxreg)))))
+      
+(defun ppc2-%immediate-store  (seg vreg xfer bits ptr offset val)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if (eql 0 (%ilogand #xf bits))
+      (ppc2-%immediate-set-ptr seg vreg xfer  ptr offset val)
+      (let* ((size (logand #xf bits))
+             (nbits (ash size 3))
+             (signed (not (logbitp 5 bits)))
+             (intval (acode-integer-constant-p val nbits))
+             (offval (acode-fixnum-form-p offset))
+             (absptr (and offval (acode-absolute-ptr-p ptr)))
+             (for-value (ppc2-for-value-p vreg)))
+        (declare (fixnum size))
+        (flet ((val-to-argz-and-imm0 ()
+                 (ppc2-one-targeted-reg-form seg val ($ ppc::arg_z))
+                 (if (eq size 8)
+                   (if signed
+                     (! gets64)
+                     (! getu64))
+                   (if (and (eq size 4)
+                            (target-arch-case
+                             (:ppc32 t)
+                             (:ppc64 nil)))
+                     (if signed
+                       (! gets32)
+                       (! getu32))
+                     (! fixnum->signed-natural ppc::imm0 ppc::arg_z)))))
+          (if (and absptr offval)
+            (setq absptr (+ absptr offval) offval 0)
+            (setq absptr nil))
+          (and offval (%i> (integer-length offval) 15) (setq offval nil))
+          (and absptr (%i> (integer-length absptr) 15) (setq absptr nil))
+          (target-arch-case
+           (:ppc32 (progn))
+           (:ppc64 (when (eql size 8)
+                     (and offval (logtest 3 offval) (setq offval nil))
+                     (and absptr (logtest 3 absptr) (setq absptr nil)))))
+          (if absptr
+            (if intval
+              (with-imm-target () (val-target :s32)
+                (if (eql intval 0)
+                  (setq val-target ppc::rzero)
+                  (ppc2-lri seg val-target intval))
+                (ppc2-memory-store-displaced seg val-target ppc::rzero absptr size)
+                (if for-value
+                  (<- (set-regspec-mode 
+                       val-target 
+                       (gpr-mode-name-value
+                        (case size
+                          (8 (if signed :s64 :u64))
+                          (4 (if signed :s32 :u32))
+                          (2 (if signed :s16 :u16))
+                          (1 (if signed :s8 :u8))))))))
+              (progn
+                (val-to-argz-and-imm0)
+                (ppc2-memory-store-displaced seg ppc::imm0 ppc::rzero absptr size)
+                (<- ppc::arg_z)))
+            ; No absolute ptr (which is presumably a rare case anyway.)
+            (if offval
+              ; Easier: need one less register than in the general case.
+              (with-imm-target () (ptr-reg :address)
+                (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+                (if intval
+                  (with-imm-target (ptr-reg) (val-target :s32)                    
+                    (if (eql intval 0)
+                      (setq val-target ppc::rzero)
+                      (ppc2-lri seg val-target intval))
+                    (ppc2-memory-store-displaced seg val-target ptr-reg offval size)
+                    (if for-value
+                      (<- (set-regspec-mode 
+                           val-target 
+                           (gpr-mode-name-value
+                            (case size
+                              (8 (if signed :s64 :u64))
+                              (4 (if signed :s32 :u32))
+                              (2 (if signed :s16 :u16))
+                              (1 (if signed :s8 :u8))))))))
+                  (progn
+                    (! temp-push-unboxed-word ptr-reg)
+                    (ppc2-open-undo $undostkblk)
+                    (val-to-argz-and-imm0)                  
+                    (with-imm-target (ppc::imm0) (ptr-reg :address)
+                      (! temp-pop-unboxed-word ptr-reg)
+                      (ppc2-close-undo)
+                      (ppc2-memory-store-displaced seg ppc::imm0 ptr-reg offval size)                    
+                      (if for-value
+                        (<- ppc::arg_z))))))
+              ;; No (16-bit) constant offset.  Might still have a 32-bit constant offset;
+              ;; might have a constant value.  Might not.  Might not.
+              ;; Easiest to special-case the constant-value case first ...
+              (let* ((xptr-reg nil)
+                     (xoff-reg nil)
+                     (xval-reg nil)
+                     (node-arg_z nil)
+                     (constant-offset (acode-fixnum-form-p offset)))
+                (if intval
+                  (if constant-offset
+                    (with-imm-target () (ptr-reg :address)
+                      (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+                      (with-imm-target (ptr-reg) (off-reg :s32)
+                        (ppc2-lri seg off-reg constant-offset)
+                        (with-imm-target (ptr-reg off-reg) (val-reg :s32)
+                          (if (eql intval 0)
+                            (setq val-reg ppc::rzero)
+                            (ppc2-lri seg val-reg intval))
+                          (setq xptr-reg ptr-reg
+                                xoff-reg off-reg
+                                xval-reg val-reg))))
+                    ; Offset's non-constant.  Temp-push the pointer, evaluate
+                    ; and unbox the offset, load the value, pop the pointer.
+                    (progn
+                      (with-imm-target () (ptr-reg :address)
+                        (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+                        (! temp-push-unboxed-word ptr-reg)
+                        (ppc2-open-undo $undostkblk))
+                      (with-imm-target () (off-reg :s32)
+                        (! fixnum->signed-natural off-reg (ppc2-one-targeted-reg-form seg offset ($ ppc::arg_z)))
+                        (with-imm-target (off-reg) (val-reg :s32)
+                          (if (eql intval 0)
+                            (setq val-reg ppc::rzero)
+                            (ppc2-lri seg val-reg intval))
+                          (with-imm-target (off-reg val-reg) (ptr-reg :address)
+                            (! temp-pop-unboxed-word ptr-reg)
+                            (ppc2-close-undo)
+                            (setq xptr-reg ptr-reg
+                                  xoff-reg off-reg
+                                  xval-reg val-reg))))))
+                  ;; No intval; maybe constant-offset.
+                  (with-imm-target () (ptr-reg :address)
+                    (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+                    (! temp-push-unboxed-word ptr-reg)
+                    (ppc2-open-undo $undostkblk)
+                    (progn
+                        (if (not constant-offset)
+                          (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z)))
+                        (val-to-argz-and-imm0)
+                        (with-imm-target (ppc::imm0) (off-reg :signed-natural)
+                          (if constant-offset
+                            (ppc2-lri seg off-reg constant-offset)
+                            (with-node-temps (ppc::arg_z) (temp)
+                              (ppc2-vpop-register seg temp)
+                              (! fixnum->signed-natural off-reg temp)))
+                          (with-imm-target (ppc::imm0 off-reg) (ptr-reg :address)
+                            (! temp-pop-unboxed-word ptr-reg)
+                            (ppc2-close-undo)
+                            (setq xptr-reg ptr-reg
+                                  xoff-reg off-reg
+                                  xval-reg ppc::imm0
+                                  node-arg_z t))))))
+                (ppc2-memory-store-indexed seg xval-reg xptr-reg xoff-reg size)
+                (when for-value
+                  (if node-arg_z
+                    (<- ppc::arg_z)
+                    (<- (set-regspec-mode 
+                         xval-reg
+                         (gpr-mode-name-value
+                          (case size
+                            (8 (if signed :s64 :u64))
+                            (4 (if signed :s32 :u32))
+                            (2 (if signed :s16 :u16))
+                            (1 (if signed :s8 :u8)))))))))))
+          (^))))))
+
+
+
+
+
+(defun ppc2-encoding-undo-count (encoding)
+ (svref encoding 0))
+
+(defun ppc2-encoding-cstack-depth (encoding)    ; hardly ever interesting
+  (svref encoding 1))
+
+(defun ppc2-encoding-vstack-depth (encoding)
+  (svref encoding 2))
+
+(defun ppc2-encoding-vstack-top (encoding)
+  (svref encoding 3))
+
+(defun ppc2-encode-stack ()
+  (vector *ppc2-undo-count* *ppc2-cstack* *ppc2-vstack* *ppc2-top-vstack-lcell*))
+
+(defun ppc2-decode-stack (encoding)
+  (values (ppc2-encoding-undo-count encoding)
+          (ppc2-encoding-cstack-depth encoding)
+          (ppc2-encoding-vstack-depth encoding)
+          (ppc2-encoding-vstack-top encoding)))
+
+(defun ppc2-equal-encodings-p (a b)
+  (dotimes (i 3 t)
+    (unless (eq (svref a i) (svref b i)) (return))))
+
+(defun ppc2-open-undo (&optional (reason $undocatch) (curstack (ppc2-encode-stack)))
+  (set-fill-pointer 
+   *ppc2-undo-stack*
+   (set-fill-pointer *ppc2-undo-because* *ppc2-undo-count*))
+  (vector-push-extend curstack *ppc2-undo-stack*)
+  (vector-push-extend reason *ppc2-undo-because*)
+  (setq *ppc2-undo-count* (%i+ *ppc2-undo-count* 1)))
+
+(defun ppc2-close-undo (&aux
+                        (new-count (%i- *ppc2-undo-count* 1))
+                        (i (aref *ppc2-undo-stack* new-count)))
+  (multiple-value-setq (*ppc2-undo-count* *ppc2-cstack* *ppc2-vstack* *ppc2-top-vstack-lcell*)
+    (ppc2-decode-stack i))
+  (set-fill-pointer 
+   *ppc2-undo-stack*
+   (set-fill-pointer *ppc2-undo-because* new-count)))
+
+
+
+
+
+;;; "Trivial" means can be evaluated without allocating or modifying registers.
+;;; Interim definition, which will probably stay here forever.
+(defun ppc2-trivial-p (form &aux op bits)
+  (setq form (nx-untyped-form form))
+  (and
+   (consp form)
+   (not (eq (setq op (%car form)) (%nx1-operator call)))
+   (or
+    (nx-null form)
+    (nx-t form)
+    (eq op (%nx1-operator simple-function))
+    (eq op (%nx1-operator fixnum))
+    (eq op (%nx1-operator immediate))
+    #+nil
+    (eq op (%nx1-operator bound-special-ref))
+    (and (or (eq op (%nx1-operator inherited-arg)) 
+             (eq op (%nx1-operator lexical-reference)))
+         (or (%ilogbitp $vbitpunted (setq bits (nx-var-bits (cadr form))))
+             (neq (%ilogior (%ilsl $vbitclosed 1) (%ilsl $vbitsetq 1))
+                  (%ilogand (%ilogior (%ilsl $vbitclosed 1) (%ilsl $vbitsetq 1)) bits)))))))
+
+(defun ppc2-lexical-reference-p (form)
+  (when (acode-p form)
+    (let ((op (acode-operator (setq form (acode-unwrapped-form-value form)))))
+      (when (or (eq op (%nx1-operator lexical-reference))
+                (eq op (%nx1-operator inherited-arg)))
+        (%cadr form)))))
+
+
+
+(defun ppc2-ref-symbol-value (seg vreg xfer sym check-boundp)
+  (declare (ignorable check-boundp))
+  (setq check-boundp (not *ppc2-reckless*))
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (when (or check-boundp vreg)
+      (unless vreg (setq vreg ($ ppc::arg_z)))
+      (if (eq sym '*interrupt-level*)
+          (ensuring-node-target (target vreg)
+            (! ref-interrupt-level target))
+          (if *ppc2-open-code-inline*
+            (ensuring-node-target (target vreg)
+              (with-node-target (target) src
+                (let* ((vcell (ppc2-symbol-value-cell sym))
+                       (reg (ppc2-register-constant-p vcell)))
+                  (if reg
+                    (setq src reg)
+                    (ppc2-store-immediate seg vcell src)))
+                (if check-boundp
+                  (! ref-symbol-value-inline target src)
+                  (! %ref-symbol-value-inline target src))))
+            (let* ((src ($ ppc::arg_z))
+                   (dest ($ ppc::arg_z)))
+              (ppc2-store-immediate seg (ppc2-symbol-value-cell sym) src)
+              (if check-boundp
+                (! ref-symbol-value dest src)
+                (! %ref-symbol-value dest src))
+              (<- dest)))))
+    (^)))
+
+#|
+(defun ppc2-ref-symbol-value (seg vreg xfer sym check-boundp)  
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (if (eq sym '*interrupt-level*)
+        (ensuring-node-target (target vreg)
+          (! ref-interrupt-level target))
+        (let* ((src ($ ppc::arg_z))
+               (dest ($ ppc::arg_z)))
+          (ppc2-store-immediate seg (ppc2-symbol-value-cell sym) src)
+          (if check-boundp
+            (! ref-symbol-value dest src)
+            (! %ref-symbol-value dest src))
+          (<- dest))))
+    (^)))
+||#
+
+;;; Should be less eager to box result
+(defun ppc2-extract-charcode (seg vreg xfer char safe)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((src (ppc2-one-untargeted-reg-form seg char ppc::arg_z)))
+      (when safe
+        (! trap-unless-character src))
+      (if vreg
+        (ensuring-node-target (target vreg)
+          (! character->fixnum target src)))
+      (^))))
+  
+
+(defun ppc2-reference-list (seg vreg xfer listform safe refcdr)
+  (if (ppc2-form-typep listform 'list)
+    (setq safe nil))                    ; May also have been passed as NIL.
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((src (ppc2-one-untargeted-reg-form seg listform ppc::arg_z)))
+      (when safe
+        (! trap-unless-list src))
+      (if vreg
+        (ensuring-node-target (target vreg)
+          (if refcdr
+            (! %cdr target src)
+            (! %car target src))))
+      (^))))
+
+
+
+
+
+
+
+(defun ppc2-misc-byte-count (subtag element-count)
+  (funcall (arch::target-array-data-size-function
+            (backend-target-arch *target-backend*))
+           subtag element-count))
+
+
+;;; The naive approach is to vpush all of the initforms, allocate the
+;;; miscobj, then sit in a loop vpopping the values into the vector.
+;;; That's "naive" when most of the initforms in question are
+;;; "side-effect-free" (constant references or references to un-SETQed
+;;; lexicals), in which case it makes more sense to just store the
+;;; things into the vector cells, vpushing/ vpopping only those things
+;;; that aren't side-effect-free.  (It's necessary to evaluate any
+;;; non-trivial forms before allocating the miscobj, since that
+;;; ensures that the initforms are older (in the EGC sense) than it
+;;; is.)  The break-even point space-wise is when there are around 3
+;;; non-trivial initforms to worry about.
+
+
+(defun ppc2-allocate-initialized-gvector (seg vreg xfer subtag initforms)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if (null vreg)
+      (dolist (f initforms) (ppc2-form seg nil nil f))
+      (let* ((*ppc2-vstack* *ppc2-vstack*)
+             (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+             (arch (backend-target-arch *target-backend*))
+             (n (length initforms))
+             (nntriv (let* ((count 0)) 
+                       (declare (fixnum count))
+                       (dolist (f initforms count) 
+                         (unless (ppc-side-effect-free-form-p f)
+                           (incf count)))))
+             (header (arch::make-vheader n subtag)))
+        (declare (fixnum n nntriv))
+        (cond ( (or *ppc2-open-code-inline* (> nntriv 3))
+               (ppc2-formlist seg initforms nil)
+               (ppc2-lri seg ppc::imm0 header)
+               (! %ppc-gvector vreg ppc::imm0 (ash n (arch::target-word-shift arch))))
+              (t
+               (let* ((pending ())
+                      (vstack *ppc2-vstack*))
+                 (declare (fixnum vstack))
+                 (dolist (form initforms)
+                   (if (ppc-side-effect-free-form-p form)
+                     (push form pending)
+                     (progn
+                       (push nil pending)
+                       (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg form ppc::arg_z)))))
+                 (ppc2-lri seg ppc::imm0 header)
+                 (ensuring-node-target (target vreg)
+                   (! %alloc-misc-fixed target ppc::imm0 (ash n (arch::target-word-shift arch)))
+                   (with-node-temps (target) (nodetemp)
+                     (do* ((forms pending (cdr forms))
+                           (index (1- n) (1- index))
+                           (pushed-cell (+ vstack (the fixnum (ash nntriv (arch::target-word-shift arch))))))
+                          ((null forms))
+                       (declare (list forms) (fixnum pushed-cell))
+                       (let* ((form (car forms))
+                              (reg nodetemp))
+                         (if form
+                           (setq reg (ppc2-one-untargeted-reg-form seg form nodetemp))
+                           (progn
+                             (decf pushed-cell *ppc2-target-node-size*)
+                             (ppc2-stack-to-register seg (ppc2-vloc-ea pushed-cell) nodetemp)))
+                         (! misc-set-c-node reg target index)))))
+                 (! vstack-discard nntriv))
+               ))))
+     (^)))
+
+;;; Heap-allocated constants -might- need memoization: they might be newly-created,
+;;; as in the case of synthesized toplevel functions in .pfsl files.
+(defun ppc2-acode-needs-memoization (valform)
+  (if (ppc2-form-typep valform 'fixnum)
+    nil
+    (let* ((val (acode-unwrapped-form-value valform)))
+      (if (or (nx-t val)
+              (nx-null val)
+              (and (acode-p val)
+                   (let* ((op (acode-operator val)))
+                     (or (eq op (%nx1-operator fixnum)) #|(eq op (%nx1-operator immediate))|#))))
+        nil
+        t))))
+
+(defun ppc2-modify-cons (seg vreg xfer ptrform valform safe setcdr returnptr)
+  (if (ppc2-form-typep ptrform 'cons)
+    (setq safe nil))                    ; May also have been passed as NIL.
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (multiple-value-bind (ptr-vreg val-vreg) (ppc2-two-targeted-reg-forms seg ptrform ($ ppc::arg_y) valform ($ ppc::arg_z))
+      (when safe
+        (! trap-unless-cons ptr-vreg))
+      (if setcdr
+        (! call-subprim-2 ($ ppc::arg_z) (subprim-name->offset '.SPrplacd) ptr-vreg val-vreg)
+        (! call-subprim-2 ($ ppc::arg_z) (subprim-name->offset '.SPrplaca) ptr-vreg val-vreg))
+      (if returnptr
+        (<- ptr-vreg)
+        (<- val-vreg))
+      (^))))
+
+
+
+(defun ppc2-find-nilret-label ()
+  (dolist (l *ppc2-nilret-labels*)
+    (destructuring-bind (label vsp csp register-restore-count register-restore-ea &rest agenda) l
+      (and (or (and (eql 0 register-restore-count)
+                    (or (not (eql 0 vsp))
+                        (eq vsp *ppc2-vstack*)))
+                (and 
+                 (eq register-restore-count *ppc2-register-restore-count*)
+                 (eq vsp *ppc2-vstack*)))
+           (or agenda (eq csp *ppc2-cstack*))
+           (eq register-restore-ea *ppc2-register-restore-ea*)
+           (eq (%ilsr 1 (length agenda)) *ppc2-undo-count*)
+           (dotimes (i (the fixnum *ppc2-undo-count*) t) 
+             (unless (and (eq (pop agenda) (aref *ppc2-undo-because* i))
+                          (eq (pop agenda) (aref *ppc2-undo-stack* i)))
+               (return)))
+           (return label)))))
+
+(defun ppc2-record-nilret-label ()
+  (let* ((lab (backend-get-next-label))
+         (info nil))
+    (dotimes (i (the fixnum *ppc2-undo-count*))
+      (push (aref *ppc2-undo-because* i) info)
+      (push (aref *ppc2-undo-stack* i) info))
+    (push (cons
+                 lab 
+                 (cons
+                  *ppc2-vstack*
+                  (cons 
+                   *ppc2-cstack*
+                   (cons
+                    *ppc2-register-restore-count*
+                    (cons
+                     *ppc2-register-restore-ea*
+                     (nreverse info))))))
+          *ppc2-nilret-labels*)
+    lab))
+
+;;; If we know that the form is something that sets a CR bit,
+;;; allocate a CR field and evaluate the form in such a way
+;;; as to set that bit.
+;;; If it's a compile-time constant, branch accordingly and
+;;; let the dead code die.
+;;; Otherwise, evaluate it to some handy register and compare
+;;; that register to RNIL.
+;;; "XFER" is a compound destination.
+(defun ppc2-conditional-form (seg xfer form)
+  (let* ((uwf (acode-unwrapped-form-value form)))
+    (if (nx-null uwf)
+      (ppc2-branch seg (ppc2-cd-false xfer) nil)
+      (if (ppc-constant-form-p uwf)
+        (ppc2-branch seg (ppc2-cd-true xfer) nil)
+        (with-crf-target () crf
+          (ppc2-form seg crf xfer form))))))
+
+      
+(defun ppc2-branch (seg xfer crf &optional cr-bit true-p)
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+    (with-ppc-local-vinsn-macros (seg)
+      (setq xfer (or xfer 0))
+      (when (logbitp $backend-mvpass-bit xfer) ;(ppc2-mvpass-p cd)
+        (setq xfer (logand (lognot $backend-mvpass-mask) xfer))
+        (unless *ppc2-returning-values*
+          (ppc2-vpush-register seg ppc::arg_z)
+          (ppc2-set-nargs seg 1)))
+      (if (neq 0 xfer)
+        (if (eq xfer $backend-return)    ;; xfer : RETURN ==> popj
+          (ppc2-do-return seg)
+          (if (not (ppc2-cd-compound-p xfer))
+            (-> xfer)  ;; xfer : label# ==> BRA label#
+            ;; cd is compound : (<true> / <false>)
+            (let* ((truebranch (ppc2-cd-true xfer))
+                   (falsebranch (ppc2-cd-false xfer))
+                   (tbranch (if true-p truebranch falsebranch))
+                   (nbranch (if true-p falsebranch truebranch))
+                   (tn0 (neq 0 tbranch))
+                   (tnret (neq $backend-return tbranch))
+                   (nn0 (neq 0 nbranch))
+                   (nnret (neq $backend-return nbranch))
+                   (tlabel (if (and tnret tn0) (aref *backend-labels* tbranch)))
+                   (nlabel (if (and nnret nn0) (aref *backend-labels* nbranch))))
+              (unless cr-bit (setq cr-bit ppc::ppc-eq-bit))
+              (if (and tn0 tnret nn0 nnret)
+                (progn
+                  (! cbranch-true tlabel crf cr-bit )    ;; (label# /  label#)
+                  (-> nbranch)))
+                (if (and nnret tnret)
+                  (if nn0
+                    (! cbranch-false nlabel crf cr-bit)
+                    (! cbranch-true tlabel crf cr-bit))
+                  (let* ((aux-label (backend-get-next-label))
+                         (auxl (aref *backend-labels* aux-label)))
+                    (if tn0
+                      (! cbranch-true auxl crf cr-bit)
+                      (! cbranch-false auxl crf cr-bit))
+                    (ppc2-do-return seg)
+                    (@ aux-label))))))))))
+
+(defun ppc2-cd-merge (cd label)
+  (setq cd (or cd 0))
+  (let ((mvpass (logbitp $backend-mvpass-bit cd)))
+    (if (neq 0 (logand (lognot $backend-mvpass-mask) cd))
+      (if (ppc2-cd-compound-p cd)
+        (ppc2-make-compound-cd
+         (ppc2-cd-merge (ppc2-cd-true cd) label)
+         (ppc2-cd-merge (ppc2-cd-false cd) label)
+         mvpass)
+        cd)
+      (if mvpass 
+        (logior $backend-mvpass-mask label)
+        label))))
+
+(defun ppc2-mvpass-p (xfer)
+  (if xfer (or (logbitp $backend-mvpass-bit xfer) (eq xfer $backend-mvpass))))
+
+(defun ppc2-cd-compound-p (xfer)
+  (if xfer (logbitp $backend-compound-branch-target-bit xfer)))
+
+(defun ppc2-cd-true (xfer)
+ (if (ppc2-cd-compound-p xfer)
+   (ldb  $backend-compound-branch-true-byte xfer)
+  xfer))
+
+(defun ppc2-cd-false (xfer)
+ (if (ppc2-cd-compound-p xfer)
+   (ldb  $backend-compound-branch-false-byte xfer)
+   xfer))
+
+(defun ppc2-make-compound-cd (tpart npart &optional mvpass-p)
+  (dpb (or npart 0) $backend-compound-branch-false-byte
+       (dpb (or tpart 0) $backend-compound-branch-true-byte
+            (logior (if mvpass-p $backend-mvpass-mask 0) $backend-compound-branch-target-mask))))
+
+(defun ppc2-invert-cd (cd)
+  (if (ppc2-cd-compound-p cd)
+    (ppc2-make-compound-cd (ppc2-cd-false cd) (ppc2-cd-true cd) (logbitp $backend-mvpass-bit cd))
+    cd))
+
+
+
+;;; execute body, cleanup afterwards (if need to)
+(defun ppc2-undo-body (seg vreg xfer body old-stack)
+  (let* ((current-stack (ppc2-encode-stack))
+         (numundo (%i- *ppc2-undo-count* (ppc2-encoding-undo-count old-stack))))
+    (declare (fixnum numundo))
+    (with-ppc-local-vinsn-macros (seg vreg xfer)
+      (if (eq current-stack old-stack)
+        (ppc2-form seg vreg xfer body)
+        (if (eq xfer $backend-return)
+          (progn
+            (ppc2-form seg vreg xfer body)
+            (dotimes (i numundo) (ppc2-close-undo)))
+          (if (ppc2-mvpass-p xfer)
+            (progn
+              (ppc2-mvpass seg body) ; presumed to be ok
+              (let* ((*ppc2-returning-values* :pass))
+                (ppc2-nlexit seg xfer numundo)
+                (^))
+              (dotimes (i numundo) (ppc2-close-undo)))
+            (progn
+              ;; There are some cases where storing thru ppc::arg_z
+              ;; can be avoided (stores to vlocs, specials, etc.) and
+              ;; some other case where it can't ($test, $vpush.)  The
+              ;; case of a null vd can certainly avoid it; the check
+              ;; of numundo is to keep $acc boxed in case of nthrow.
+              (ppc2-form  seg (if (or vreg (not (%izerop numundo))) ppc::arg_z) nil body)
+              (ppc2-unwind-set seg xfer old-stack)
+              (when vreg (<- ppc::arg_z))
+              (^))))))))
+
+
+(defun ppc2-unwind-set (seg xfer encoding)
+  (multiple-value-bind (target-catch target-cstack target-vstack target-vstack-lcell)
+                       (ppc2-decode-stack encoding)
+    (ppc2-unwind-stack seg xfer target-catch target-cstack target-vstack)
+    (setq *ppc2-undo-count* target-catch 
+          *ppc2-cstack* target-cstack
+          *ppc2-vstack* target-vstack
+          *ppc2-top-vstack-lcell* target-vstack-lcell)))
+
+(defun ppc2-unwind-stack (seg xfer target-catch target-cstack target-vstack)
+  (let* ((current-catch *ppc2-undo-count*)
+         (current-cstack *ppc2-cstack*)
+         (current-vstack *ppc2-vstack*)
+         (diff (%i- current-catch target-catch))
+         target
+         (exit-vstack current-vstack))
+    (declare (ignore-if-unused target))
+    (when (neq 0 diff)
+      (setq exit-vstack (ppc2-nlexit seg xfer diff))
+      (multiple-value-setq (target current-cstack current-vstack)
+                           (ppc2-decode-stack (aref *ppc2-undo-stack* target-catch))))
+    (if (%i< 0 (setq diff (%i- current-cstack target-cstack)))
+      (with-ppc-local-vinsn-macros (seg)
+        (! adjust-sp diff)))
+    (if (%i< 0 (setq diff (%i- current-vstack target-vstack)))
+      (with-ppc-local-vinsn-macros (seg)
+        (! vstack-discard (ash diff (- *ppc2-target-fixnum-shift*)))))
+    exit-vstack))
+
+;;; We can sometimes combine unwinding the catch stack with returning from the function
+;;; by jumping to a subprim that knows how to do this.  If catch frames were distinguished
+;;; from unwind-protect frames, we might be able to do this even when saved registers
+;;; are involved (but the subprims restore them from the last catch frame.)
+;;; *** there are currently only subprims to handle the "1 frame" case; add more ***
+(defun ppc2-do-return (seg)
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+         (mask *ppc2-register-restore-count*)
+         (ea *ppc2-register-restore-ea*)
+         (label nil)
+         (vstack nil)
+         (foldp (not *ppc2-open-code-inline*)))
+    (if (%izerop mask) (setq mask nil))
+    (with-ppc-local-vinsn-macros (seg)
+      (progn
+        (setq vstack (ppc2-set-vstack (ppc2-unwind-stack seg $backend-return 0 0 #x7fffff)))
+        (if *ppc2-returning-values*
+          (cond ((and mask foldp (setq label (%cdr (assq vstack *ppc2-valret-labels*))))
+                 (-> label))
+                (t
+                 (@ (setq label (backend-get-next-label)))
+                 (push (cons vstack label) *ppc2-valret-labels*)
+                 (when mask
+                   (with-imm-temps () (vsp0)
+                     (! fixnum-add vsp0 ppc::vsp ppc::nargs)
+                     (ppc2-restore-nvrs seg ea mask vsp0)))
+                 (! nvalret)))
+          (if (null mask)
+            (if *ppc2-open-code-inline*
+              (progn
+                (! restore-full-lisp-context)
+                (! jump-return-pc))
+              (! popj))
+            (if (and foldp (setq label (assq *ppc2-vstack* *ppc2-popreg-labels*)))
+              (-> (cdr label))
+              (let* ((new-label (backend-get-next-label)))
+                (@ new-label)
+                (push (cons *ppc2-vstack* new-label) *ppc2-popreg-labels*)
+                (ppc2-set-vstack (ppc2-restore-nvrs seg ea mask))
+                (if *ppc2-open-code-inline*
+                  (progn
+                    (! restore-full-lisp-context)
+                    (! jump-return-pc))
+                  (! popj))))))))
+    nil))
+
+
+
+(defun ppc2-mvcall (seg vreg xfer fn arglist &optional recursive-p)
+  (let* ((cstack *ppc2-cstack*)
+         (vstack *ppc2-vstack*))
+    (with-ppc-local-vinsn-macros (seg vreg xfer)
+      (if (and (eq xfer $backend-return) (not (ppc2-tailcallok xfer)))
+        (progn
+          (ppc2-mvcall seg vreg $backend-mvpass fn arglist t)
+          (ppc2-set-vstack (%i+ (if arglist *ppc2-target-node-size* 0) vstack))
+          (setq *ppc2-cstack* cstack)
+          (let* ((*ppc2-returning-values* t)) (^)))
+        (let* ((mv-p (ppc2-mv-p xfer)))
+          (if (null arglist)
+            (ppc2-call-fn seg vreg xfer fn arglist nil)
+            (progn
+              (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg fn ppc::arg_z))
+              (ppc2-multiple-value-body seg (pop arglist))
+              (when arglist
+                (ppc2-open-undo $undostkblk)
+                (! save-values)
+                (dolist (form arglist)
+                  (ppc2-multiple-value-body seg form)
+                  (! add-values))
+                (ppc2-set-nargs seg 0)
+                (! recover-values)
+                (ppc2-close-undo))
+              (! lisp-word-ref ppc::temp0 ppc::vsp ppc::nargs)
+              (ppc2-invoke-fn seg ppc::temp0 nil nil xfer)))
+          (unless recursive-p
+            (if mv-p
+              (unless (eq xfer $backend-return)
+                (let* ((*ppc2-returning-values* t))
+                  (^)))
+              (progn 
+                (ppc2-adjust-vstack (- *ppc2-target-node-size*)) ; discard function
+                (! vstack-discard 1)
+                (<- ppc::arg_z)
+                (^)))))))))
+
+
+(defun ppc2-hard-opt-p (opts)
+  (or
+   (dolist (x (%cadr opts))
+     (unless (nx-null x) (return t)))
+   (dolist (x (%caddr opts))
+     (when x (return t)))))
+
+(defun ppc2-close-lambda (seg req opt rest keys auxen)
+  (dolist (var req)
+    (ppc2-close-var seg var))
+  (dolist (var (%car opt))
+    (ppc2-close-var seg var))
+  (dolist (var (%caddr opt))
+    (when var
+      (ppc2-close-var seg var)))
+  (if rest
+    (ppc2-close-var seg rest))
+  (dolist (var (%cadr keys))
+    (ppc2-close-var seg var))
+  (dolist (var (%caddr keys))
+    (if var (ppc2-close-var seg var)))
+  (dolist (var (%car auxen))
+    (ppc2-close-var seg var)))
+
+(defun ppc2-close-structured-var (seg var)
+  (if (ppc2-structured-var-p var)
+    (apply #'ppc2-close-structured-lambda seg (cdr var))
+    (ppc2-close-var seg var)))
+
+(defun ppc2-close-structured-lambda (seg whole req opt rest keys auxen)
+  (if whole
+    (ppc2-close-var seg whole))
+  (dolist (var req)
+    (ppc2-close-structured-var seg var))
+  (dolist (var (%car opt))
+    (ppc2-close-structured-var seg var))
+  (dolist (var (%caddr opt))
+    (when var
+      (ppc2-close-var seg var)))
+  (if rest
+    (ppc2-close-structured-var seg rest))
+  (dolist (var (%cadr keys))
+    (ppc2-close-structured-var seg var))
+  (dolist (var (%caddr keys))
+    (if var (ppc2-close-var seg var)))
+  (dolist (var (%car auxen))
+    (ppc2-close-var seg var)))
+
+
+(defun ppc2-init-regvar (seg var reg addr)
+  (with-ppc-local-vinsn-macros (seg)
+    (ppc2-stack-to-register seg addr reg)
+    (ppc2-set-var-ea seg var ($ reg))))
+
+(defun ppc2-bind-structured-var (seg var vloc lcell &optional context)
+  (if (not (ppc2-structured-var-p var))
+    (let* ((reg (nx2-assign-register-var var)))
+      (if reg
+        (ppc2-init-regvar seg var reg (ppc2-vloc-ea vloc))
+        (ppc2-bind-var seg var vloc lcell)))
+    (let* ((v2 (%cdr var))
+           (v v2)
+           (vstack *ppc2-vstack*)
+           (whole (pop v))
+           (req (pop v))
+           (opt (pop v))
+           (rest (pop v))
+           (keys (pop v)))
+      
+      (apply #'ppc2-bind-structured-lambda seg 
+             (ppc2-spread-lambda-list seg (ppc2-vloc-ea vloc) whole req opt rest keys context)
+             vstack context v2))))
+
+(defun ppc2-bind-structured-lambda (seg lcells vloc context whole req opt rest keys auxen
+                        &aux (nkeys (list-length (%cadr keys))))
+  (declare (fixnum vloc))
+  (when whole
+    (ppc2-bind-structured-var seg whole vloc (pop lcells))
+    (incf vloc *ppc2-target-node-size*))
+  (dolist (arg req)
+    (ppc2-bind-structured-var seg arg vloc (pop lcells) context)
+    (incf vloc *ppc2-target-node-size*))
+  (when opt
+   (if (ppc2-hard-opt-p opt)
+     (setq vloc (apply #'ppc2-structured-initopt seg lcells vloc context opt)
+           lcells (nthcdr (ash (length (car opt)) 1) lcells))
+     (dolist (var (%car opt))
+       (ppc2-bind-structured-var seg var vloc (pop lcells) context)
+       (incf vloc *ppc2-target-node-size*))))
+  (when rest
+    (ppc2-bind-structured-var seg rest vloc (pop lcells) context)
+    (incf vloc *ppc2-target-node-size*))
+  (when keys
+    (apply #'ppc2-structured-init-keys seg lcells vloc context keys)
+    (setq vloc (%i+ vloc (* *ppc2-target-node-size* (+ nkeys nkeys)))))
+  (ppc2-seq-bind seg (%car auxen) (%cadr auxen)))
+
+(defun ppc2-structured-var-p (var)
+  (and (consp var) (or (eq (%car var) *nx-lambdalist*)
+                       (eq (%car var) (%nx1-operator lambda-list)))))
+
+(defun ppc2-simple-var (var &aux (bits (cadr var)))
+  (if (or (%ilogbitp $vbitclosed bits)
+          (%ilogbitp $vbitspecial bits))
+    (nx-error "Non-simple-variable ~S" (%car var))
+    var))
+
+(defun ppc2-nlexit (seg xfer &optional (nlevels 0))
+  (let* ((numnthrow 0)
+         (n *ppc2-undo-count*)
+         (cstack *ppc2-cstack*)
+         (vstack *ppc2-vstack*)
+         (target-cstack)
+         (target-vstack)
+         (lastcatch n)
+         (i nil)
+         (returning (eq xfer $backend-return))
+         (junk1 nil)
+         (unbind ())
+         (dest (%i- n nlevels))
+         (retval *ppc2-returning-values*)
+         reason)
+    (declare (ignorable junk1))
+    (with-ppc-local-vinsn-macros (seg)
+      (when (neq 0 nlevels)
+        (let* ((numnlispareas 0))
+          (declare (fixnum numnlispareas))
+          (flet ((popnlispareas ()
+                   (dotimes (i numnlispareas)
+                     (! discard-temp-frame)))
+                 (throw-through-numnthrow-catch-frames ()
+                   (when (neq 0 numnthrow)
+                     (ppc2-lri seg ppc::imm0 (ash numnthrow *ppc2-target-fixnum-shift*))
+                     (if retval
+                       (! nthrowvalues)
+                       (! nthrow1value))
+                     (setq numnthrow 0)
+                     (multiple-value-setq (junk1 cstack vstack)
+                       (ppc2-decode-stack (aref *ppc2-undo-stack* lastcatch))))))
+            (while (%i> n dest)
+              (cond ((eql $undocatch (setq reason (aref *ppc2-undo-because* (setq n (%i- n 1)))))
+                     (popnlispareas)
+                     (setq numnthrow (%i+ numnthrow 1) lastcatch n))
+                    ((eql $undostkblk reason)
+                     (throw-through-numnthrow-catch-frames)
+                     (incf numnlispareas))
+                    ((eql $undo-ppc-c-frame reason)
+                     (! discard-c-frame))))
+            (throw-through-numnthrow-catch-frames)
+            (setq i lastcatch)
+            (while (%i> i dest)
+              (let ((reason (aref *ppc2-undo-because* (setq i (%i- i 1)))))
+                (if (or (eql reason $undospecial)
+                        (eql reason $undointerruptlevel))
+                  (push reason unbind))))
+            (if unbind
+              (ppc2-dpayback-list seg (nreverse unbind)))
+            (when (and (neq lastcatch dest)
+                       (%i>
+                        vstack
+                        (setq target-vstack 
+                              (nth-value 2 (ppc2-decode-stack (aref *ppc2-undo-stack* dest)))))
+                       (neq retval t))
+              (unless returning
+                (let ((vdiff (%i- vstack target-vstack)))
+                  (if retval
+                    (progn
+                      (ppc2-lri seg ppc::imm0 vdiff)
+                      (! slide-values))
+                    (! adjust-vsp vdiff)))))
+            (setq numnlispareas 0)
+            (while (%i> lastcatch dest)
+              (let ((reason (aref *ppc2-undo-because* (setq lastcatch (%i- lastcatch 1)))))
+                (setq target-cstack (nth-value 1
+                                               (ppc2-decode-stack (aref *ppc2-undo-stack* lastcatch))))
+                (if (eq reason $undostkblk)
+                  (incf numnlispareas))
+                (if (%i> cstack target-cstack)
+                  (with-ppc-local-vinsn-macros (seg)
+                    (! adjust-sp (%i- cstack target-cstack))))
+                ; else what's going on? $sp-stkcons, for one thing
+                (setq cstack target-cstack)))
+            (popnlispareas)))
+        vstack))))
+
+
+;;; Restore the most recent dynamic bindings.  Bindings
+;;; of *INTERRUPT-LEVEL* get special treatment.
+(defun ppc2-dpayback-list (seg reasons)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((n 0))
+      (declare (fixnum n))
+      (dolist (r reasons (if (> n 0) (! dpayback n)))
+        (if (eql r $undospecial)
+          (incf n)
+          (if (eql r $undointerruptlevel)
+            (progn
+              (when (> n 0)
+                (! dpayback n)
+                (setq n 0))
+              (if *ppc2-open-code-inline*
+                (! unbind-interrupt-level-inline)
+                (! unbind-interrupt-level)))
+            (compiler-bug "unknown payback token ~s" r)))))))
+
+(defun ppc2-spread-lambda-list (seg listform whole req opt rest keys 
+                                    &optional enclosing-ea cdr-p)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((numopt (length (%car opt)))
+           (nkeys (length (%cadr keys)))
+           (numreq (length req))
+           (vtotal numreq)
+           (old-top *ppc2-top-vstack-lcell*)
+           (listreg ($ ppc::temp3))
+           (doadlword (dpb nkeys (byte 8 16) (dpb numopt (byte 8 8) (dpb numreq (byte 8 0) 0 )))))
+      (declare (fixnum numopt nkeys numreq vtotal doadlword))
+      (when (or (> numreq 255) (> numopt 255) (> nkeys 255))
+        (compiler-bug "A lambda list can contain a maximum of 255 required, 255 optional, and 255 keywords args"))
+      (if (fixnump listform)
+        (ppc2-store-ea seg listform listreg)
+        (ppc2-one-targeted-reg-form seg listform listreg))
+      (when whole
+        (ppc2-vpush-register seg listreg :reserved))
+      (when keys
+        (setq doadlword (%ilogior2 (ash #x80000000 -6) doadlword))
+        (incf  vtotal (%ilsl 1 nkeys))
+        (if (%car keys)                 ; &allow-other-keys
+          (setq doadlword (%ilogior doadlword (ash #x80000000 -5))))
+        (ppc2-store-immediate seg (%car (%cdr (%cdr (%cdr (%cdr keys))))) ppc::temp2))
+      (when opt
+        (setq vtotal (%i+ vtotal numopt))
+        (when (ppc2-hard-opt-p opt)
+          (setq doadlword (%ilogior2 doadlword (ash #x80000000 -7)))
+          (setq vtotal (%i+ vtotal numopt))))
+      (when rest
+        (setq doadlword (%ilogior2 (ash #x80000000 -4) doadlword) vtotal (%i+ vtotal 1)))
+      (ppc2-reserve-vstack-lcells vtotal)
+      (! load-adl doadlword)
+      (if cdr-p
+        (! macro-bind)
+        (if enclosing-ea
+          (progn
+            (ppc2-store-ea seg enclosing-ea ppc::arg_z)
+            (! destructuring-bind-inner))
+          (! destructuring-bind)))
+      (ppc2-set-vstack (%i+ *ppc2-vstack* (* *ppc2-target-node-size* vtotal)))
+      (ppc2-collect-lcells :reserved old-top))))
+
+
+(defun ppc2-tailcallok (xfer)
+  (and (eq xfer $backend-return)
+       *ppc2-tail-allow*
+       (eq 0 *ppc2-undo-count*)))
+
+(defun ppc2-mv-p (cd)
+  (or (eq cd $backend-return) (ppc2-mvpass-p cd)))
+
+(defun ppc2-expand-note (note)
+  (let* ((lab (vinsn-note-label note)))
+    (case (vinsn-note-class note)
+      ((:regsave :begin-variable-scope :end-variable-scope
+        :source-location-begin :source-location-end)
+       (setf (vinsn-label-info lab) (emit-lap-label lab))))))
+
+(defun ppc2-expand-vinsns (header)
+  (do-dll-nodes (v header)
+    (if (%vinsn-label-p v)
+      (let* ((id (vinsn-label-id v)))
+        (if (or (typep id 'fixnum) (null id))
+          (when (or t (vinsn-label-refs v) (null id))
+            (setf (vinsn-label-info v) (emit-lap-label v)))
+          (ppc2-expand-note id)))
+      (ppc2-expand-vinsn v)))
+  ;;; This doesn't have too much to do with anything else that's
+  ;;; going on here, but it needs to happen before the lregs
+  ;;; are freed.  There really shouldn't be such a thing as a
+  ;;; var-ea, of course ...
+  (dolist (s *ppc2-recorded-symbols*)
+    (let* ((var (car s))
+           (ea (var-ea var)))
+      (when (typep ea 'lreg)
+        (setf (var-ea var) (lreg-value ea)))))
+  (free-logical-registers)
+  (ppc2-free-lcells))
+
+;;; It's not clear whether or not predicates, etc. want to look
+;;; at an lreg or just at its value slot.
+;;; It's clear that the assembler just wants the value, and that
+;;; the value had better be assigned by the time we start generating
+;;; machine code.
+;;; For now, we replace lregs in the operand vector with their values
+;;; on entry, but it might be reasonable to make PARSE-OPERAND-FORM
+;;; deal with lregs ...
+(defun ppc2-expand-vinsn (vinsn)
+  (let* ((template (vinsn-template vinsn))
+         (vp (vinsn-variable-parts vinsn))
+         (nvp (vinsn-template-nvp template))
+         (unique-labels ()))
+    (declare (fixnum nvp))
+    (dotimes (i nvp)
+      (let* ((val (svref vp i)))
+        (when (typep val 'lreg)
+          (setf (svref vp i) (lreg-value val)))))                       
+    (dolist (name (vinsn-template-local-labels template))
+      (let* ((unique (cons name nil)))
+        (push unique unique-labels)
+        (make-lap-label unique)))
+    (labels ((parse-operand-form (valform)
+               (cond ((typep valform 'keyword)
+                      (or (assq valform unique-labels)
+                          (compiler-bug "unknown vinsn label ~s" valform)))
+                     ((atom valform) valform)
+                     ((and (atom (cdr valform))
+                           (typep (car valform) 'fixnum))
+                      (svref vp (car valform)))
+                     (t (let* ((op-vals (cdr valform))
+                               (parsed-ops (make-list (length op-vals)))
+                               (tail parsed-ops))
+                          (declare (dynamic-extent parsed-ops)
+                                   (cons parsed-ops tail))
+                          (dolist (op op-vals (apply (car valform) parsed-ops))
+                            (setq tail (cdr (rplaca tail (parse-operand-form op)))))))))
+             (expand-insn-form (f)
+               (let* ((operands (cdr f))
+                      (head (make-list (length operands)))
+                      (tail head))
+                 (declare (dynamic-extent head)
+                          (cons head tail))
+                 (dolist (op operands)
+                   (rplaca tail (parse-operand-form op))
+                   (setq tail (cdr tail)))
+                 (ppc-emit-lap-instruction (svref ppc::*ppc-opcodes* (car f)) 
+                                           head)))
+             (eval-predicate (f)
+               (case (car f)
+                 (:pred (let* ((op-vals (cddr f))
+                               (parsed-ops (make-list (length op-vals)))
+                               (tail parsed-ops))
+                          (declare (dynamic-extent parsed-ops)
+                                   (cons parsed-ops tail))
+                          (dolist (op op-vals (apply (cadr f) parsed-ops))
+                            (setq tail (cdr (rplaca tail (parse-operand-form op)))))))
+                 (:not (not (eval-predicate (cadr f))))
+                 (:or (dolist (pred (cadr f))
+                        (when (eval-predicate pred)
+                          (return t))))
+                 (:and (dolist (pred (cadr f) t)
+                         (unless (eval-predicate pred)
+                           (return nil))))
+                 (t (compiler-bug "Unknown predicate: ~s" f))))
+             (expand-form (f)
+               (if (keywordp f)
+                 (emit-lap-label (assq f unique-labels))
+                 (if (atom f)
+                   (compiler-bug "Invalid form in vinsn body: ~s" f)
+                   (if (atom (car f))
+                     (expand-insn-form f)
+                     (if (eval-predicate (car f))
+                       (dolist (subform (cdr f))
+                         (expand-form subform))))))))
+      (declare (dynamic-extent #'expand-form #'parse-operand-form #'expand-insn-form #'eval-predicate))
+      ;(format t "~& vinsn = ~s" vinsn)
+      (dolist (form (vinsn-template-body template))
+        (expand-form form ))
+      (setf (vinsn-variable-parts vinsn) nil)
+      (when vp
+        (free-varparts-vector vp)))))
+
+
+
+
+
+(defun ppc2-builtin-index-subprim (idx)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (table (arch::target-primitive->subprims  arch))
+         (shift (arch::target-subprims-shift arch)))
+    (dolist (cell table)
+      (destructuring-bind ((low . high) . base) cell
+        (if (and (>= idx low)
+                 (< idx high))
+          (return (+ base (ash (- idx low) shift))))))))
+
+(defun ppc2-fixed-call-builtin (seg vreg xfer name subprim)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((index (arch::builtin-function-name-offset name))
+           (idx-subprim (if index (ppc2-builtin-index-subprim index)))
+           (tail-p (ppc2-tailcallok xfer)))
+      (when tail-p
+        (ppc2-restore-nvrs seg *ppc2-register-restore-ea* *ppc2-register-restore-count*)
+        (ppc2-restore-full-lisp-context seg))
+      (if idx-subprim
+        (setq subprim idx-subprim)
+        (if index (! lri ($ ppc::imm0) (ash index *ppc2-target-fixnum-shift*))))
+      (if tail-p
+        (! jump-subprim subprim)
+        (progn
+          (! call-subprim subprim)
+          (<- ($ ppc::arg_z))
+          (^))))))
+
+(defun ppc2-unary-builtin (seg vreg xfer name form)
+  (with-ppc-local-vinsn-macros (seg)
+    (ppc2-one-targeted-reg-form seg form ($ ppc::arg_z))
+    (ppc2-fixed-call-builtin seg vreg xfer name (subprim-name->offset '.SPcallbuiltin1))))
+
+(defun ppc2-binary-builtin (seg vreg xfer name form1 form2)
+  (with-ppc-local-vinsn-macros (seg)
+    (ppc2-two-targeted-reg-forms seg form1 ($ ppc::arg_y) form2 ($ ppc::arg_z))
+    (ppc2-fixed-call-builtin seg vreg xfer name (subprim-name->offset '.SPcallbuiltin2))))
+
+(defun ppc2-ternary-builtin (seg vreg xfer name form1 form2 form3)
+  (with-ppc-local-vinsn-macros (seg)
+    (ppc2-three-targeted-reg-forms seg form1 ($ ppc::arg_x) form2 ($ ppc::arg_y) form3 ($ ppc::arg_z))
+    (ppc2-fixed-call-builtin seg vreg xfer name (subprim-name->offset '.SPcallbuiltin3))))
+
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+
+
+(defmacro defppc2 (name locative arglist &body forms)
+  (multiple-value-bind (body decls)
+                       (parse-body forms nil t)
+    (destructuring-bind (vcode-block dest control &rest other-args) arglist
+      (let* ((fun `(nfunction ,name 
+                              (lambda (,vcode-block ,dest ,control ,@other-args) ,@decls 
+                                      (block ,name (with-ppc-local-vinsn-macros (,vcode-block ,dest ,control) ,@body))))))
+        `(progn
+           (record-source-file ',name 'function)
+           (svset *ppc2-specials* (%ilogand #.operator-id-mask (%nx1-operator ,locative)) ,fun))))))
+)
+  
+(defppc2 ppc2-lambda lambda-list (seg vreg xfer req opt rest keys auxen body p2decls &optional code-note)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((stack-consed-rest nil)
+           (lexprp (if (consp rest) (progn (setq rest (car rest)) t)))
+           (rest-var-bits (and rest (nx-var-bits rest)))
+           (rest-ignored-p (and rest (not lexprp) (%ilogbitp $vbitignore rest-var-bits)))
+           (want-stack-consed-rest (or rest-ignored-p
+                                       (and rest (not lexprp) (%ilogbitp $vbitdynamicextent rest-var-bits))))
+           (afunc *ppc2-cur-afunc*)
+           (inherited-vars (afunc-inherited-vars afunc))
+           (fbits (afunc-bits afunc))
+           (methodp (%ilogbitp $fbitmethodp fbits))
+           (method-var (if methodp (pop req)))
+           (next-method-p (%ilogbitp $fbitnextmethp fbits))
+           (allow-other-keys-p (%car keys))
+           (hardopt (ppc2-hard-opt-p opt))
+           (lap-p (when (and (consp (%car req)) (eq (%caar req) '&lap))
+                    (prog1 (%cdar req) (setq req nil))))
+           (num-inh (length inherited-vars))
+           (num-req (length req))
+           (num-opt (length (%car opt)))
+           (no-regs nil)
+           (arg-regs nil)
+           optsupvloc
+           reglocatives
+           pregs
+           (reserved-lcells nil)
+           (*ppc2-vstack* 0))
+      (declare (type (unsigned-byte 16) num-req num-opt num-inh))
+      (with-ppc-p2-declarations p2decls
+        (setq *ppc2-inhibit-register-allocation*
+              (setq no-regs (%ilogbitp $fbitnoregs fbits)))
+        (multiple-value-setq (pregs reglocatives) 
+          (nx2-allocate-global-registers *ppc2-fcells* *ppc2-vcells* (afunc-all-vars afunc) inherited-vars (unless no-regs *ppc2-nvrs*)))
+        (@ (backend-get-next-label)) ; generic self-reference label, should be label #1
+        (when keys ;; Ensure keyvect is the first immediate
+          (backend-immediate-index (%cadr (%cdddr keys))))
+        (when code-note
+          (ppc2-code-coverage-entry seg code-note))
+        (unless next-method-p
+          (setq method-var nil))
+        
+        (let* ((rev-req (reverse req))
+               (rev-fixed (if inherited-vars (reverse (append inherited-vars req)) rev-req))
+               (num-fixed (length rev-fixed))
+               (rev-opt (reverse (car opt))))
+          (if (not (or opt rest keys))
+            (setq arg-regs (ppc2-req-nargs-entry seg rev-fixed))
+            (if (and (not (or hardopt rest keys))
+                     (<= num-opt $numppcargregs))
+              (setq arg-regs (ppc2-simple-opt-entry seg rev-opt rev-fixed))
+              (progn
+                ; If the minumum acceptable number of args is non-zero, ensure
+                ; that at least that many were received.  If there's an upper bound,
+                ; enforce it.
+                
+                (when rev-fixed
+                  (ppc2-reserve-vstack-lcells num-fixed)                    
+                  (! check-min-nargs num-fixed))
+                (unless (or rest keys)
+                  (! check-max-nargs (+ num-fixed num-opt)))
+                ;; Going to have to call one or more subprims.  First save
+                ;; the LR in LOC-PC.
+                (! save-lr)
+                ;; If there were &optional args, initialize their values
+                ;; to NIL.  All of the argregs get vpushed as a result of this.
+                (when opt
+                  (ppc2-reserve-vstack-lcells num-opt)
+                  (! default-optionals (+ num-fixed num-opt)))
+                (when keys
+                  (let* ((keyvect (%car (%cdr (%cdr (%cdr (%cdr keys))))))
+                         (flags (the fixnum (logior (the fixnum (if rest 4 0)) 
+                                                    (the fixnum (if (or methodp allow-other-keys-p) 1 0)))))
+                         (nkeys (length keyvect))
+                         (nprev (+ num-fixed num-opt)))
+                    (declare (fixnum flags nkeys nprev))
+                    (dotimes (i (the fixnum (+ nkeys nkeys)))
+                      (ppc2-new-vstack-lcell :reserved *ppc2-target-lcell-size* 0 nil))
+                    (! misc-ref-c-node ppc::temp3 ppc::nfn (1+ (backend-immediate-index keyvect)))
+                    (ppc2-lri seg ppc::imm2 (ash flags *ppc2-target-fixnum-shift*))
+                    (ppc2-lri seg ppc::imm3 (ash nkeys *ppc2-target-fixnum-shift*))
+                    (unless (= nprev 0)
+                      (ppc2-lri seg ppc::imm0 (ash nprev *ppc2-target-fixnum-shift*)))
+                    (if (= 0 nprev)
+                      (! simple-keywords)
+                      (if (= 0 num-opt)
+                        (! keyword-args)
+                        (! keyword-bind)))))
+                (when rest
+                  ;; If any keyword-binding's happened, the key/value
+                  ;; pairs have been slid to the top-of-stack for us.
+                  ;; There'll be an even number of them (nargs - the
+                  ;; "previous" (required/&optional) count.)
+                  (if lexprp
+                    (ppc2-lexpr-entry seg num-fixed)
+                    (progn
+                      (if want-stack-consed-rest
+                        (setq stack-consed-rest t))
+                      (let* ((nprev (+ num-fixed num-opt))
+                             (simple (and (not keys) (= 0 nprev))))
+                        (declare (fixnum nprev))
+                        (unless simple
+                          (ppc2-lri seg ppc::imm0 (ash nprev *ppc2-target-fixnum-shift*)))
+                        (if stack-consed-rest
+                          (if simple
+                            (! stack-rest-arg)
+                            (if (and (not keys) (= 0 num-opt))
+                              (! req-stack-rest-arg)
+                              (! stack-cons-rest-arg)))
+                          (if simple
+                            (! heap-rest-arg)
+                            (if (and (not keys) (= 0 num-opt))
+                              (! req-heap-rest-arg)
+                              (! heap-cons-rest-arg)))))
+                      ; Make an lcell for the &rest arg
+                      (ppc2-reserve-vstack-lcells 1))))
+                (when hardopt
+                  (ppc2-reserve-vstack-lcells num-opt)
+                  (ppc2-lri seg ppc::imm0 (ash num-opt *ppc2-target-fixnum-shift*))
+
+                  ;; .SPopt-supplied-p wants nargs to contain the
+                  ;; actual arg-count minus the number of "fixed"
+                  ;; (required, inherited) args.
+
+                  (unless (= 0 num-fixed)
+                    (! scale-nargs num-fixed))
+                  (! opt-supplied-p))
+                (let* ((nwords-vpushed (+ num-fixed 
+                                          num-opt 
+                                          (if hardopt num-opt 0) 
+                                          (if lexprp 0 (if rest 1 0))
+                                          (ash (length (%cadr keys)) 1)))
+                       (nbytes-vpushed (* nwords-vpushed *ppc2-target-node-size*)))
+                  (declare (fixnum nwords-vpushed nbytes-vpushed))
+                  (unless (or lexprp keys) 
+                    (if *ppc2-open-code-inline*
+                      (! save-lisp-context-offset nbytes-vpushed)
+                      (! save-lisp-context-offset-ool nbytes-vpushed)))
+                  (ppc2-set-vstack nbytes-vpushed)
+                  (setq optsupvloc (- *ppc2-vstack* (* num-opt *ppc2-target-node-size*)))))))
+          ;; Caller's context is saved; *ppc2-vstack* is valid.  Might still have method-var
+          ;; to worry about.
+          (unless (= 0 pregs)
+            ;; Save NVRs; load constants into any that get constants.
+            (ppc2-save-nvrs seg pregs)
+
+            (dolist (pair reglocatives)
+              (declare (cons pair))
+              (let* ((constant (car pair))
+                     (reg (cdr pair)))
+                (declare (cons constant))
+                (rplacd constant reg)
+                (! ref-constant reg (backend-immediate-index (car constant))))))
+          (when (and (not (or opt rest keys))
+                     (<= num-fixed $numppcargregs)
+                     (not (some #'null arg-regs)))
+            (setq *ppc2-tail-vsp* *ppc2-vstack*
+                  *ppc2-tail-nargs* num-fixed)
+            (@ (setq *ppc2-tail-label* (backend-get-next-label))))
+          (when method-var
+            (ppc2-seq-bind-var seg method-var ppc::next-method-context))
+          ;; If any arguments are still in arg_x, arg_y, arg_z, that's
+          ;; because they weren't vpushed in a "simple" entry case and
+          ;; belong in some NVR.  Put them in their NVRs, so that we
+          ;; can handle arbitrary expression evaluation (special
+          ;; binding, value-cell consing, etc.) without clobbering the
+          ;; argument registers.
+          (when arg-regs
+            (do* ((vars arg-regs (cdr vars))
+                  (arg-reg-num ppc::arg_z (1- arg-reg-num)))
+                 ((null vars))
+              (declare (list vars) (fixnum arg-reg-num))
+              (let* ((var (car vars)))
+                (when var
+                  (let* ((reg (nx2-assign-register-var var)))
+                    (ppc2-copy-register seg reg arg-reg-num)
+                    (setf (var-ea var) reg))))))
+          (setq *ppc2-entry-vsp-saved-p* t)
+#|
+          (when stack-consed-rest
+            (if rest-ignored-p
+              (if nil (ppc2-jsrA5 $sp-popnlisparea))
+              (progn
+                (ppc2-open-undo $undostkblk))))
+|#
+          (when stack-consed-rest
+            (ppc2-open-undo $undostkblk))
+          (setq *ppc2-entry-vstack* *ppc2-vstack*)
+          (setq reserved-lcells (ppc2-collect-lcells :reserved))
+          (ppc2-bind-lambda seg reserved-lcells req opt rest keys auxen optsupvloc arg-regs lexprp inherited-vars))
+        (when method-var (ppc2-heap-cons-next-method-var seg method-var))
+        (ppc2-form seg vreg xfer body)
+        (ppc2-close-lambda seg req opt rest keys auxen)
+        (dolist (v inherited-vars)
+          (ppc2-close-var seg v))
+        (when method-var
+          (ppc2-close-var seg method-var))
+        (let* ((bits 0))
+          (when (%i> num-inh (ldb $lfbits-numinh -1))
+            (setq num-inh (ldb $lfbits-numinh -1)))
+          (setq bits (dpb num-inh $lfbits-numinh bits))
+          (unless lap-p
+            (when (%i> num-req (ldb $lfbits-numreq -1))
+              (setq num-req (ldb $lfbits-numreq -1)))
+            (setq bits (dpb num-req $lfbits-numreq bits))
+            (when (%i> num-opt (ldb $lfbits-numopt -1))
+              (setq num-opt (ldb $lfbits-numopt -1)))
+            (setq bits (dpb num-opt $lfbits-numopt bits))
+            (when hardopt (setq bits (%ilogior (%ilsl $lfbits-optinit-bit 1) bits)))
+            (when rest (setq bits (%ilogior (if lexprp (%ilsl $lfbits-restv-bit 1) (%ilsl $lfbits-rest-bit 1)) bits)))
+            (when keys (setq bits (%ilogior (%ilsl $lfbits-keys-bit 1) bits)))
+            (when allow-other-keys-p (setq bits (%ilogior (%ilsl $lfbits-aok-bit 1) bits)))
+            (when (%ilogbitp $fbitnextmethargsp (afunc-bits afunc))
+              (if methodp
+                (setq bits (%ilogior (%ilsl $lfbits-nextmeth-with-args-bit 1) bits))
+                (let ((parent (afunc-parent afunc)))
+                  (when parent
+                    (setf (afunc-bits parent) (bitset $fbitnextmethargsp (afunc-bits parent)))))))
+            (when methodp
+              (setq bits (logior (ash 1 $lfbits-method-bit) bits))
+              (when next-method-p
+                (setq bits (logior (%ilsl $lfbits-nextmeth-bit 1) bits))))) 
+          bits)))))
+
+
+(defppc2 ppc2-progn progn (seg vreg xfer forms)
+  (declare (list forms))
+  (if (null forms)
+    (ppc2-nil seg vreg xfer)
+    (loop
+      (let* ((form (pop forms)))
+        (if forms
+          (ppc2-form seg nil nil form)
+          (return (ppc2-form seg vreg xfer form)))))))
+
+
+
+(defppc2 ppc2-prog1 prog1 (seg vreg xfer forms)
+  (if (eq (list-length forms) 1)
+    (ppc2-use-operator (%nx1-operator values) seg vreg xfer forms)
+    (if (null vreg)
+      (ppc2-use-operator (%nx1-operator progn) seg vreg xfer forms)
+      (let* ((float-p (= (hard-regspec-class vreg) hard-reg-class-fpr))
+             (crf-p (= (hard-regspec-class vreg) hard-reg-class-crf))
+             (node-p (unless (or float-p crf-p)
+                       (= (get-regspec-mode vreg) hard-reg-class-gpr-mode-node)))
+             (first (pop forms)))
+        (ppc2-push-register seg 
+                            (if (or node-p crf-p)
+                              (ppc2-one-untargeted-reg-form seg first ppc::arg_z)
+                              (ppc2-one-targeted-reg-form seg first vreg)))
+        (dolist (form forms)
+          (ppc2-form seg nil nil form))
+        (if crf-p
+          (progn
+            (ppc2-vpop-register seg ppc::arg_z)
+            (<- ppc::arg_z))
+          (ppc2-pop-register seg vreg))
+        (^)))))
+
+(defppc2 ppc2-free-reference free-reference (seg vreg xfer sym)
+  (ppc2-ref-symbol-value seg vreg xfer sym t))
+
+(defppc2 ppc2-special-ref special-ref (seg vreg xfer sym)
+  (ppc2-ref-symbol-value seg vreg xfer sym t))
+
+(defppc2 ppc2-bound-special-ref bound-special-ref (seg vreg xfer sym)
+  (ppc2-ref-symbol-value seg vreg xfer sym nil))
+
+(defppc2 ppc2-%slot-ref %slot-ref (seg vreg xfer instance idx)
+  (ensuring-node-target (target (or vreg ($ ppc::arg_z)))
+    (multiple-value-bind (v i)
+        (ppc2-two-untargeted-reg-forms seg instance ppc::arg_y idx ppc::arg_z)
+      (unless *ppc2-reckless*
+        (! check-misc-bound i v))
+      (with-node-temps (v) (temp)
+        (! %slot-ref temp v i)
+        (ppc2-copy-register seg target temp))))
+  (^))
+  
+(defppc2 ppc2-%svref %svref (seg vreg xfer vector index)
+  (ppc2-vref seg vreg xfer :simple-vector vector index nil))
+
+(defppc2 ppc2-svref svref (seg vreg xfer vector index)
+  (ppc2-vref seg vreg xfer :simple-vector  vector index (unless *ppc2-reckless* (nx-lookup-target-uvector-subtag :simple-vector))))
+
+;;; It'd be nice if this didn't box the result.  Worse things happen ...
+;;;  Once there's a robust mechanism, adding a CHARCODE storage class shouldn't be hard.
+(defppc2 ppc2-%sbchar %sbchar (seg vreg xfer string index)
+  (ppc2-vref seg vreg xfer :simple-string string index (unless *ppc2-reckless* (nx-lookup-target-uvector-subtag :simple-string))))
+
+
+(defppc2 ppc2-%svset %svset (seg vreg xfer vector index value)
+  (ppc2-vset seg vreg xfer :simple-vector vector index value nil))
+
+(defppc2 ppc2-svset svset (seg vreg xfer vector index value)
+  (ppc2-vset seg vreg xfer :simple-vector  vector index value (nx-lookup-target-uvector-subtag :simple-vector)))
+
+(defppc2 ppc2-typed-form typed-form (seg vreg xfer typespec form &optional check)
+  (if check
+    (ppc2-typechecked-form seg vreg xfer typespec form)
+    (ppc2-form seg vreg xfer form)))
+
+(defppc2 ppc2-type-asserted-form type-asserted-form (seg vreg xfer typespec form &optional check)
+  (declare (ignore typespec check))
+  (ppc2-form seg vreg xfer form))
+
+
+(defppc2 ppc2-%primitive %primitive (seg vreg xfer &rest ignore)
+  (declare (ignore seg vreg xfer ignore))
+  (compiler-bug "You're probably losing big: using %primitive ..."))
+
+(defppc2 ppc2-consp consp (seg vreg xfer cc form)
+  (if (null vreg)
+    (ppc2-form seg vreg xfer form)
+    (let* ((tagreg ppc::imm0))
+      (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+        (! extract-fulltag tagreg (ppc2-one-untargeted-reg-form seg form ppc::arg_z))
+        (ppc2-test-reg-%izerop seg vreg xfer tagreg cr-bit true-p
+                               (target-arch-case
+                                (:ppc32 ppc32::fulltag-cons)
+                                (:ppc64 ppc64::fulltag-cons)))))))
+      
+(defppc2 ppc2-cons cons (seg vreg xfer y z)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil y)
+      (ppc2-form seg nil xfer z))
+    (multiple-value-bind (yreg zreg) (ppc2-two-untargeted-reg-forms seg y ppc::arg_y z ppc::arg_z)
+      (ensuring-node-target (target vreg)
+        (! cons target yreg zreg))
+      (^))))
+
+
+
+(defppc2 ppc2-%rplaca %rplaca (seg vreg xfer ptr val)
+  (ppc2-modify-cons seg vreg xfer ptr val nil nil t))
+
+(defppc2 ppc2-%rplacd %rplacd (seg vreg xfer ptr val)
+  (ppc2-modify-cons seg vreg xfer ptr val nil t t))
+
+(defppc2 ppc2-rplaca rplaca (seg vreg xfer ptr val)
+  (ppc2-modify-cons seg vreg xfer ptr val t nil t))
+
+(defppc2 ppc2-set-car set-car (seg vreg xfer ptr val)
+  (ppc2-modify-cons seg vreg xfer ptr val t nil nil))
+
+(defppc2 ppc2-rplacd rplacd (seg vreg xfer ptr val)
+  (ppc2-modify-cons seg vreg xfer ptr val t t t))
+
+(defppc2 ppc2-set-cdr set-cdr (seg vreg xfer ptr val)
+  (ppc2-modify-cons seg vreg xfer ptr val t t nil))
+
+(defppc2 ppc2-%car %car (seg vreg xfer form)
+  (ppc2-reference-list seg vreg xfer form nil nil))
+
+(defppc2 ppc2-%cdr %cdr (seg vreg xfer form)
+  (ppc2-reference-list seg vreg xfer form nil t))
+
+(defppc2 ppc2-car car (seg vreg xfer form)
+  (ppc2-reference-list seg vreg xfer form t nil))
+
+(defppc2 ppc2-cdr cdr (seg vreg xfer form)
+  (ppc2-reference-list seg vreg xfer form t t))
+
+
+(defppc2 ppc2-vector vector (seg vreg xfer arglist)
+  (ppc2-allocate-initialized-gvector seg vreg xfer
+                                     (nx-lookup-target-uvector-subtag
+                                      :simple-vector) arglist))
+
+(defppc2 ppc2-%gvector %gvector (seg vreg xfer arglist)
+  (let* ((all-on-stack (append (car arglist) (reverse (cadr arglist))))
+         (subtag-form (car all-on-stack))
+         (subtag (acode-fixnum-form-p subtag-form)))
+    (if (null vreg)
+      (dolist (form all-on-stack (^)) (ppc2-form seg nil nil form))
+      (if (null subtag)
+        (progn                            ; Vpush everything and call subprim
+          (let* ((*ppc2-vstack* *ppc2-vstack*)
+                 (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+            (ppc2-set-nargs seg (ppc2-formlist seg all-on-stack nil))
+            (! gvector))
+          (<- ppc::arg_z)
+          (^))
+        (ppc2-allocate-initialized-gvector seg vreg xfer subtag (cdr all-on-stack))))))
+
+;;; Should be less eager to box result
+(defppc2 ppc2-%char-code %char-code (seg vreg xfer c)
+  (ppc2-extract-charcode seg vreg xfer c nil))
+
+(defppc2 ppc2-char-code char-code (seg vreg xfer c)
+  (ppc2-extract-charcode seg vreg xfer c (not (ppc2-form-typep c 'character))))
+
+(defppc2 ppc2-%ilogior2 %ilogior2 (seg vreg xfer form1 form2)
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2)))
+    (if (and fix1 fix2)
+      (ppc2-use-operator (%nx1-operator fixnum) seg vreg xfer (logior fix1 fix2)))
+    (let* ((fixval (or fix1 fix2))
+           (unboxed-fixval (if fixval (ash fixval *ppc2-target-fixnum-shift*)))
+           (high (if fixval (if (= unboxed-fixval (logand #xffff0000 unboxed-fixval)) (ash unboxed-fixval -16))))
+           (low (if fixval (unless high (if (= unboxed-fixval (logand #x0000ffff unboxed-fixval)) unboxed-fixval))))
+           (otherform (if (or high low) (if fix1 form2 form1))))
+      (if otherform
+        (let* ((other-reg (ppc2-one-untargeted-reg-form seg otherform ppc::arg_z)))
+          (when vreg
+            (ensuring-node-target (target vreg) 
+              (if high
+                (! logior-high target other-reg high)
+                (! logior-low target other-reg low)))))
+        (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form1 ppc::arg_y form2 ppc::arg_z)
+          (if vreg (ensuring-node-target (target vreg) (! %logior2 target r1 r2)))))   
+      (^))))
+
+;;; in a lot of (typical ?) cases, it might be possible to use a
+;;; rotate-and-mask instead of andi./andis.
+
+(defppc2 ppc2-%ilogand2 %ilogand2 (seg vreg xfer form1 form2)
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2)))
+    (if (and fix1 fix2)
+      (ppc2-use-operator (%nx1-operator fixnum) seg vreg xfer (logand fix1 fix2))
+      (let* ((fixval (or fix1 fix2))
+             (fixlen (if fixval (integer-length fixval)))
+             (unboxed-fixval (if fixval (ash fixval *ppc2-target-fixnum-shift*)))
+             (high (if fixval (if (= unboxed-fixval (logand #xffff0000 unboxed-fixval)) (ash unboxed-fixval -16))))
+             (low (if fixval (unless high (if (= unboxed-fixval (logand #x0000ffff unboxed-fixval)) unboxed-fixval))))
+             (otherform (if (or high low) (if fix1 form2 form1))))
+        (if otherform
+          (let* ((other-reg (ppc2-one-untargeted-reg-form seg otherform ppc::arg_z)))
+            (when vreg
+              (ensuring-node-target (target vreg) 
+                (if high
+                  (! logand-high target other-reg high)
+                  (! logand-low target other-reg low)))))
+          (if (and fixval (= fixlen (logcount fixval)))
+            (let* ((nbits (- *ppc2-target-bits-in-word*
+                             (1+ (+ *ppc2-target-fixnum-shift* fixlen))))
+                   (otherreg (ppc2-one-untargeted-reg-form seg (if fix1 form2 form1) ppc::arg_z)))
+            
+              (if vreg (ensuring-node-target (target vreg)
+                         (if (> fixval 0)
+                           (! clear-left target otherreg nbits)
+                           (! clear-right target otherreg (+ fixlen
+                                                             *ppc2-target-fixnum-shift*))))))
+          
+            (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form1 ppc::arg_y form2 ppc::arg_z)
+              (if vreg (ensuring-node-target (target vreg) (! %logand2 target r1 r2))))))
+        (^)))))
+
+(defppc2 ppc2-%ilogxor2 %ilogxor2 (seg vreg xfer form1 form2)
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2)))
+    (if (and fix1 fix2)
+      (ppc2-use-operator (%nx1-operator fixnum) seg vreg xfer (logxor fix1 fix2)))
+    (let* ((fixval (or fix1 fix2))
+           (unboxed-fixval (if fixval (ash fixval *ppc2-target-fixnum-shift*)))
+           (high (if fixval (if (= unboxed-fixval (logand #xffff0000 unboxed-fixval)) (ash unboxed-fixval -16))))
+           (low (if fixval (unless high (if (= unboxed-fixval (logand #x0000ffff unboxed-fixval)) unboxed-fixval))))
+           (otherform (if (or high low) (if fix1 form2 form1))))
+      (if otherform
+        (let* ((other-reg (ppc2-one-untargeted-reg-form seg otherform ppc::arg_z)))
+          (when vreg
+            (ensuring-node-target (target vreg) 
+              (if high
+                (! logxor-high target other-reg high)
+                (! logxor-low target other-reg low)))))
+        (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form1 ppc::arg_y form2 ppc::arg_z)
+          (if vreg (ensuring-node-target (target vreg) (! %logxor2 vreg r1 r2)))))
+      (^))))
+
+(defppc2 ppc2-%ineg %ineg (seg vreg xfer n)
+  (let* ((src (ppc2-one-untargeted-reg-form seg n ppc::arg_z)))
+    (when vreg
+      (ensuring-node-target (target vreg)
+        (if *ppc2-open-code-inline*
+          (! negate-fixnum-overflow-inline target src)
+          (progn
+            (! negate-fixnum-overflow-ool src)
+            (ppc2-copy-register seg target ($ ppc::arg_z))))))
+    (^)))
+
+(defppc2 ppc2-%%ineg %%ineg (seg vreg xfer n)
+  (let* ((src (ppc2-one-untargeted-reg-form seg n ppc::arg_z)))
+    (when vreg
+      (ensuring-node-target (target vreg) 
+        (! negate-fixnum-no-ovf target src)))
+    (^)))
+
+(defppc2 ppc2-characterp characterp (seg vreg xfer cc form)
+  (ppc2-char-p seg vreg xfer cc form))
+
+(defppc2 ppc2-struct-ref struct-ref (seg vreg xfer struct offset)
+  (ppc2-vref seg vreg xfer :struct struct offset (unless *ppc2-reckless* (nx-lookup-target-uvector-subtag :struct))))
+
+(defppc2 ppc2-struct-set struct-set (seg vreg xfer struct offset value)
+  (ppc2-vset seg vreg xfer :struct  struct offset value (unless *ppc2-reckless* (nx-lookup-target-uvector-subtag :struct))))
+
+(defppc2 ppc2-istruct-typep istruct-typep (seg vreg xfer cc form type)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form ppc::arg_y type ppc::arg_z)
+      (with-imm-target  () (target :signed-natural)
+        (! istruct-typep target r1 r2)
+        (ppc2-test-reg-%izerop seg vreg xfer target cr-bit true-p 0)))))
+
+
+(defppc2 ppc2-lisptag lisptag (seg vreg xfer node)
+  (if (null vreg)
+    (ppc2-form seg vreg xfer node)
+    (progn
+      (ensuring-node-target (target vreg) 
+        (! extract-tag-fixnum target (ppc2-one-untargeted-reg-form seg node ppc::arg_z)))
+      (^))))
+
+(defppc2 ppc2-fulltag fulltag (seg vreg xfer node)
+  (if (null vreg)
+    (ppc2-form seg vreg xfer node)
+    (progn
+      (ensuring-node-target (target vreg) 
+        (! extract-fulltag-fixnum target (ppc2-one-untargeted-reg-form seg node ppc::arg_z)))
+      (^))))
+
+(defppc2 ppc2-typecode typecode (seg vreg xfer node)
+  (if (null vreg)
+    (ppc2-form seg vreg xfer node)
+    (let* ((reg (ppc2-one-untargeted-reg-form seg node (if (eq (hard-regspec-value vreg) ppc::arg_z) 
+                                                         ppc::arg_y ppc::arg_z))))
+      (ensuring-node-target (target vreg) 
+        (! extract-typecode-fixnum target reg ))
+      (^))))
+
+(defppc2 ppc2-setq-special setq-special (seg vreg xfer sym val)
+  (let* ((symreg ($ ppc::arg_y))
+         (valreg ($ ppc::arg_z)))
+    (ppc2-one-targeted-reg-form seg val valreg)
+    (ppc2-store-immediate seg (ppc2-symbol-value-cell sym) symreg)
+    (! setq-special symreg valreg)
+    (<- valreg))
+  (^))
+
+
+(defppc2 ppc2-local-go local-go (seg vreg xfer tag)
+  (declare (ignorable xfer))
+  (let* ((curstack (ppc2-encode-stack))
+         (label (cadr tag))
+         (deststack (caddr tag)))
+    (if (not (ppc2-equal-encodings-p curstack deststack))
+      (multiple-value-bind (catch cstack vstack)
+                           (ppc2-decode-stack deststack)
+        (ppc2-unwind-stack seg nil catch cstack vstack)))
+    (-> label)
+    (ppc2-unreachable-store vreg)))
+
+(defppc2 ppc2-local-block local-block (seg vreg xfer blocktag body)
+  (let* ((curstack (ppc2-encode-stack))
+         (compound (ppc2-cd-compound-p xfer))
+         (mvpass-p (ppc2-mvpass-p xfer))
+         (need-label (if xfer (or compound mvpass-p) t))
+         end-of-block
+         last-cd
+         (dest (if (backend-crf-p vreg) ppc::arg_z vreg)))
+    (if need-label
+      (setq end-of-block (backend-get-next-label)))
+    (setq last-cd (if need-label (%ilogior2 (if mvpass-p $backend-mvpass-mask 0) end-of-block) xfer))
+    (%rplaca blocktag (cons (cons dest last-cd) curstack))
+    (if mvpass-p
+      (ppc2-multiple-value-body seg body)
+      (ppc2-form seg dest (if xfer last-cd) body))
+    (when need-label
+      (@ end-of-block)
+      (if compound
+        (<- dest))
+      (ppc2-branch seg (logand (lognot $backend-mvpass-mask) (or xfer 0)) vreg))))
+
+(defppc2 ppc2-%izerop %izerop (seg vreg xfer cc form)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (ppc2-test-%izerop seg vreg xfer form cr-bit true-p)))
+
+
+(defppc2 ppc2-uvsize uvsize (seg vreg xfer v)
+  (let* ((misc-reg (ppc2-one-untargeted-reg-form seg v ppc::arg_z)))
+    (unless *ppc2-reckless* (! trap-unless-uvector misc-reg))
+    (if vreg 
+      (ensuring-node-target (target vreg)
+        (! misc-element-count-fixnum target misc-reg)))
+    (^)))
+
+(defppc2 ppc2-%ilsl %ilsl (seg vreg xfer form1 form2)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil form1)
+      (ppc2-form seg nil xfer form2))
+    (let* ((const (acode-fixnum-form-p form1))
+           (max (target-arch-case (:ppc32 31) (:ppc64 63))))
+      (ensuring-node-target (target vreg)
+        (if const
+          (let* ((src (ppc2-one-untargeted-reg-form seg form2 ppc::arg_z)))
+            (if (<= const max)
+              (! %ilsl-c target const src)
+              (!  lri target 0)))
+          (multiple-value-bind (count src) (ppc2-two-untargeted-reg-forms seg form1 ppc::arg_y form2 ppc::arg_z)
+            (! %ilsl target count src))))
+      (^))))
+
+(defppc2 ppc2-endp endp (seg vreg xfer cc form)
+  (let* ((formreg (ppc2-one-untargeted-reg-form seg form ppc::arg_z)))
+    (! trap-unless-list formreg)
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+      (ppc2-compare-register-to-nil seg vreg xfer formreg  cr-bit true-p))))
+
+
+
+(defppc2 ppc2-%code-char %code-char (seg vreg xfer c)
+  (if (null vreg)
+    (ppc2-form seg nil xfer c)
+    (progn
+      (ensuring-node-target (target vreg)
+        (with-imm-target () (dest :u8)
+          (! u32->char target (ppc2-one-untargeted-reg-form seg c dest))))
+      (^))))
+
+(defppc2 ppc2-%schar %schar (seg vreg xfer str idx)
+  (multiple-value-bind (src unscaled-idx)
+                       (ppc2-two-untargeted-reg-forms seg str ppc::arg_y idx ppc::arg_z)
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+          (256 (! %schar8 target src unscaled-idx))
+          (t (! %schar32 target src unscaled-idx)))))
+    (^)))
+
+(defppc2 ppc2-%set-schar %set-schar (seg vreg xfer str idx char)
+  (multiple-value-bind (src unscaled-idx char)
+                       (ppc2-three-untargeted-reg-forms seg
+                                                        str ppc::arg_x
+                                                        idx ppc::arg_y
+                                                        char ppc::arg_z)
+    (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+      (256 (! %set-schar8 src unscaled-idx char))
+      (t (! %set-schar32 src unscaled-idx char)))
+    (when vreg (<- char)) 
+    (^)))
+
+(defppc2 ppc2-%set-scharcode %set-scharcode (seg vreg xfer str idx char)
+  (multiple-value-bind (src unscaled-idx char)
+                       (ppc2-three-untargeted-reg-forms seg str ppc::arg_x idx ppc::arg_y
+                                                        char ppc::arg_z)
+    (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+      (256 (! %set-scharcode8 src unscaled-idx char))
+      (t (! %set-scharcode32 src unscaled-idx char)))
+    (when vreg (<- char)) 
+    (^)))
+
+(defppc2 ppc2-%scharcode %scharcode (seg vreg xfer str idx)
+  (multiple-value-bind (src unscaled-idx)
+      (ppc2-two-untargeted-reg-forms seg str ppc::arg_y idx ppc::arg_z)
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+          (256 (! %scharcode8 target src unscaled-idx))
+          (t (! %scharcode32 target src unscaled-idx)))))
+    (^)))
+
+      
+
+(defppc2 ppc2-code-char code-char (seg vreg xfer c)
+  (let* ((reg (ppc2-one-untargeted-reg-form seg c ppc::arg_z)))
+    ;; Typecheck even if result unused.
+    (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+      (256 (! require-u8 reg))
+      (t (! require-char-code reg)))
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (! fixnum->char target reg)))
+    (^)))
+
+(defppc2 ppc2-%valid-code-char %valid-code-char (seg vreg xfer c)
+  (let* ((reg (ppc2-one-untargeted-reg-form seg c ppc::arg_z)))
+    (when *ppc2-full-safety* (! require-char-code reg))
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (! code-char->char target reg)))
+    (^)))
+
+(defppc2 ppc2-eq eq (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (ppc2-compare seg vreg xfer form1 form2 cr-bit true-p)))
+
+(defppc2 ppc2-neq neq (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (ppc2-compare seg vreg xfer form1 form2 cr-bit true-p)))
+
+(defppc2 ppc2-numcmp numcmp (seg vreg xfer cc form1 form2)
+  (let* ((name (ecase (cadr cc)
+                 (:eq '=-2)
+                 (:ne '/=-2)
+                 (:lt '<-2)
+                 (:le '<=-2)
+                 (:gt '>-2)
+                 (:ge '>=-2))))
+    (if (or (ppc2-explicit-non-fixnum-type-p form1)
+            (ppc2-explicit-non-fixnum-type-p form2))
+      (ppc2-binary-builtin seg vreg xfer name form1 form2)
+      (ppc2-inline-numcmp seg vreg xfer cc name form1 form2))))
+
+(defun ppc2-inline-numcmp (seg vreg xfer cc name form1 form2)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+      (let* ((otherform (and (eql cr-bit ppc::ppc-eq-bit)
+                             (if (eql (acode-fixnum-form-p form2) 0)
+                               form1
+                               (if (eql (acode-fixnum-form-p form1) 0)
+                                 form2)))))
+        (if otherform
+          (ppc2-one-targeted-reg-form seg otherform ($ ppc::arg_z))
+          (ppc2-two-targeted-reg-forms seg  form1 ($ ppc::arg_y) form2 ($ ppc::arg_z)))
+        (let* ((out-of-line (backend-get-next-label))
+               (done (backend-get-next-label)))
+          (if otherform
+            (unless (acode-fixnum-form-p otherform)
+              (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line)))
+            (if (acode-fixnum-form-p form1)
+              (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line))
+              (if (acode-fixnum-form-p form2)
+                (! branch-unless-arg-fixnum ($ ppc::arg_y) (aref *backend-labels* out-of-line))  
+                (! branch-unless-both-args-fixnums ($ ppc::arg_y) ($ ppc::arg_z) (aref *backend-labels* out-of-line)))))
+          (with-imm-target () (b31-reg :natural)
+            (if otherform
+              (if true-p
+                (! eq0->bit31 b31-reg ($ ppc::arg_z))
+                (! ne0->bit31 b31-reg ($ ppc::arg_z)))
+              (ecase cr-bit 
+                (#. ppc::ppc-eq-bit 
+                    (if true-p
+                      (! eq->bit31 b31-reg ($ ppc::arg_y) ($ ppc::arg_z))
+                      (! ne->bit31 b31-reg ($ ppc::arg_y) ($ ppc::arg_z))))
+                (#. ppc::ppc-lt-bit
+                    (if true-p
+                      (! lt->bit31 b31-reg ($ ppc::arg_y) ($ ppc::arg_z))
+                      (! ge->bit31 b31-reg ($ ppc::arg_y) ($ ppc::arg_z))))
+                (#. ppc::ppc-gt-bit
+                    (if true-p
+                      (! gt->bit31 b31-reg ($ ppc::arg_y) ($ ppc::arg_z))
+                      (! le->bit31 b31-reg ($ ppc::arg_y) ($ ppc::arg_z))))))
+            (! lowbit->truth ($ ppc::arg_z) b31-reg)
+            (-> done)
+            (@ out-of-line)
+            (if otherform
+              (ppc2-lri seg ($ ppc::arg_y) 0))
+            (let* ((index (arch::builtin-function-name-offset name))
+                   (idx-subprim (ppc2-builtin-index-subprim index)))
+              (! call-subprim-2 ($ ppc::arg_z) idx-subprim ($ ppc::arg_y) ($ ppc::arg_z)))
+            (@ done)
+            (<- ($ ppc::arg_z))
+            (^)))))))
+    
+(defppc2 ppc2-%word-to-int %word-to-int (seg vreg xfer form)
+  (if (null vreg)
+    (ppc2-form seg nil xfer form)
+    (progn
+      (ensuring-node-target (target vreg)
+        (! sign-extend-halfword target (ppc2-one-untargeted-reg-form seg form ppc::arg_z)))
+      (^))))
+
+(defppc2 ppc2-multiple-value-list multiple-value-list (seg vreg xfer form)
+  (ppc2-multiple-value-body seg form)
+  (! list)
+  (when vreg
+    (<- ppc::arg_z))
+  (^))
+
+(defppc2 ppc2-immform immediate (seg vreg xfer form)
+  (ppc2-immediate seg vreg xfer form))
+
+(defppc2 ppc2-lexical-reference lexical-reference (seg vreg xfer varnode)
+  (let* ((ea-or-form (var-ea varnode)))
+    (if (and (acode-punted-var-p varnode) (not (fixnump ea-or-form)))
+      (ppc2-form seg vreg xfer ea-or-form)
+      (let* ((cell (ppc2-lookup-var-cell varnode)))
+        (if (and cell (typep cell 'lcell))
+          (if (ppc2-ensure-lcell-offset cell (logand ea-or-form #xffff))
+            (and nil (format t "~& could use cell ~s for var ~s" cell (var-name varnode)))
+            (if (logbitp ppc2-debug-verbose-bit *ppc2-debug-mask*)
+              (compiler-bug "wrong ea for lcell for var ~s: got ~d, expected ~d" 
+                     (var-name varnode) (calc-lcell-offset cell) (logand ea-or-form #xffff))))
+          (if (not cell)
+            (when (memory-spec-p ea-or-form)
+              (if (logbitp ppc2-debug-verbose-bit *ppc2-debug-mask*)
+                (format t "~& no lcell for ~s." (var-name varnode))))))
+        
+        (unless (or (typep ea-or-form 'lreg) (fixnump ea-or-form))
+          (compiler-bug "bogus ref to var ~s (~s) : ~s " varnode (var-name varnode) ea-or-form))
+        (ppc2-do-lexical-reference seg vreg ea-or-form)
+        (^)))))
+
+(defppc2 ppc2-setq-lexical setq-lexical (seg vreg xfer varspec form)
+  (let* ((ea (var-ea varspec)))
+    ;(unless (fixnump ea) (compiler-bug "setq lexical is losing BIG"))
+    (let* ((valreg (ppc2-one-untargeted-reg-form seg form (if (and (register-spec-p ea) 
+                                                                   (or (null vreg) (eq ea vreg)))
+                                                            ea
+                                                            ppc::arg_z))))
+      (ppc2-do-lexical-setq seg vreg ea valreg))
+    (^)))
+
+(defppc2 ppc2-fixnum fixnum (seg vreg xfer value)
+  (if (null vreg)
+    (^)
+    (let* ((class (hard-regspec-class vreg))
+           (mode (get-regspec-mode vreg))
+           (unboxed (if (= class hard-reg-class-gpr)
+                      (not (or (= hard-reg-class-gpr-mode-node mode)
+                               (= hard-reg-class-gpr-mode-address mode))))))
+      (if unboxed
+        (ppc2-absolute-natural seg vreg xfer value)
+        (if (= class hard-reg-class-crf)
+          (progn
+            ;(compiler-bug "Would have clobbered a GPR!")
+            (ppc2-branch seg (ppc2-cd-true xfer) nil))
+          (progn
+            (ensuring-node-target (target vreg)
+              (ppc2-absolute-natural seg target nil (ash value *ppc2-target-fixnum-shift*)))
+            (^)))))))
+
+(defppc2 ppc2-%ilogbitp %ilogbitp (seg vreg xfer cc bitnum form)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil bitnum)
+      (ppc2-form seg vreg xfer form))
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+      (let* ((fixbit (acode-fixnum-form-p bitnum)))
+        (if fixbit
+          (let* ((reg (ppc2-one-untargeted-reg-form seg form ppc::arg_z))
+                 (ppc-bit (- (1- *ppc2-target-bits-in-word*) (max (min (+ fixbit *ppc2-target-fixnum-shift*) (1- *ppc2-target-bits-in-word*)) *ppc2-target-fixnum-shift*))))
+            (with-imm-temps () (bitreg)
+              (! extract-constant-ppc-bit bitreg reg ppc-bit)
+              (regspec-crf-gpr-case 
+               (vreg dest)
+               (progn
+                 (! compare-signed-s16const dest bitreg 0)
+                 (^ cr-bit true-p))
+               (progn
+                 (if true-p
+                   (! invert-lowbit bitreg))
+                 (ensuring-node-target (target dest)
+                   (! lowbit->truth target bitreg))
+                 (^)))))
+          (multiple-value-bind (rbit rform) (ppc2-two-untargeted-reg-forms seg bitnum ppc::arg_y form ppc::arg_z)
+             (with-imm-temps () (bitreg)
+               (! extract-variable-non-insane-bit bitreg rform rbit)
+               (regspec-crf-gpr-case 
+               (vreg dest)
+               (progn
+                 (! compare-signed-s16const dest bitreg 0)
+                 (^ cr-bit true-p))
+               (progn
+                 (if true-p
+                   (! invert-lowbit bitreg))
+                 (ensuring-node-target (target dest)
+                   (! lowbit->truth target bitreg))
+                 (^))))))))))
+
+(defppc2 ppc2-uvref uvref (seg vreg xfer vector index)
+  (ppc2-two-targeted-reg-forms seg vector ($ ppc::arg_y) index ($ ppc::arg_z))
+  (! misc-ref)
+  (<- ($ ppc::arg_z))
+  (^))
+
+(defppc2 ppc2-uvset uvset (seg vreg xfer vector index value)
+  (ppc2-three-targeted-reg-forms seg vector ($ ppc::arg_x) index ($ ppc::arg_y) value ($ ppc::arg_z))
+  (! misc-set)
+  (<- ($ ppc::arg_z))
+  (^))
+
+(defppc2 ppc2-%decls-body %decls-body (seg vreg xfer form p2decls)
+  (with-ppc-p2-declarations p2decls
+    (ppc2-form seg vreg xfer form)))
+
+
+
+(defppc2 ppc2-%err-disp %err-disp (seg vreg xfer arglist)
+  (ppc2-set-nargs seg (ppc2-arglist seg arglist))
+  (! ksignalerr)
+  (ppc2-nil seg vreg xfer))
+
+
+(defppc2 ppc2-local-tagbody local-tagbody (seg vreg xfer taglist body)
+  (let* ((encstack (ppc2-encode-stack))
+         (tagop (%nx1-operator tag-label)))
+    (dolist (tag taglist)
+      (rplacd tag (cons (backend-get-next-label) (cons encstack (cadr (cddr (cddr tag)))))))
+    (dolist (form body)
+      (if (eq (acode-operator form) tagop)
+        (let ((tag (cddr form)))
+          (@ (car tag)))
+        (ppc2-form seg nil nil form)))
+    (ppc2-nil seg vreg xfer)))
+
+(defppc2 ppc2-call call (seg vreg xfer fn arglist &optional spread-p)
+  (when (and (null vreg)
+             (acode-p fn)
+             (eq (acode-operator fn) (%nx1-operator immediate)))
+    (let* ((name (cadr fn)))
+      (when (memq name *warn-if-function-result-ignored*)
+        (p2-whine *ppc2-cur-afunc*  :result-ignored name))))
+  (ppc2-call-fn seg vreg xfer fn arglist spread-p))
+
+(defppc2 ppc2-self-call self-call (seg vreg xfer arglist &optional spread-p)
+  (setq arglist (ppc2-augment-arglist *ppc2-cur-afunc* arglist (if spread-p 1 $numppcargregs)))
+  (ppc2-call-fn seg vreg xfer -1 arglist spread-p))
+
+
+(defppc2 ppc2-lexical-function-call lexical-function-call (seg vreg xfer afunc arglist &optional spread-p)
+  (ppc2-call-fn seg vreg xfer (list (%nx1-operator simple-function) afunc)
+                (ppc2-augment-arglist afunc arglist (if spread-p 1 $numppcargregs))
+                spread-p))
+
+(defppc2 ppc2-builtin-call builtin-call (seg vreg xfer index arglist)
+  (let* ((nargs (ppc2-arglist seg arglist))
+         (tail-p (and (ppc2-tailcallok xfer) (<= nargs $numppcargregs)))
+         (idx (acode-fixnum-form-p index))
+         (idx-subprim (ppc2-builtin-index-subprim idx))
+         (subprim
+          (or idx-subprim
+              (case nargs
+                (0 (subprim-name->offset '.SPcallbuiltin0))
+                (1 (subprim-name->offset '.SPcallbuiltin1))
+                (2 (subprim-name->offset '.SPcallbuiltin2))
+                (3 (subprim-name->offset '.SPcallbuiltin3))
+                (t (subprim-name->offset '.SPcallbuiltin))))))
+    (when tail-p
+      (ppc2-restore-nvrs seg *ppc2-register-restore-ea* *ppc2-register-restore-count*)
+      (ppc2-restore-full-lisp-context seg))
+    (unless idx-subprim
+      (! lri ppc::imm0 (ash idx *ppc2-target-fixnum-shift*))
+      (when (eql subprim (subprim-name->offset '.SPcallbuiltin))
+        (ppc2-set-nargs seg nargs)))
+    (if tail-p
+      (! jump-subprim subprim)
+      (progn
+        (! call-subprim subprim)
+        (<- ppc::arg_z)
+        (^)))))
+      
+
+(defppc2 ppc2-if if (seg vreg xfer testform true false &aux test-val)
+  (if (setq test-val (nx2-constant-form-value (acode-unwrapped-form-value testform)))
+    (ppc2-form seg vreg xfer (if (nx-null test-val) false true))
+    (let* ((cstack *ppc2-cstack*)
+           (vstack *ppc2-vstack*)
+           (top-lcell *ppc2-top-vstack-lcell*)
+           (entry-stack (ppc2-encode-stack))
+           (true-stack nil)
+           (false-stack nil)
+           (true-cleanup-label nil)
+           (same-stack-effects nil)
+           (true-is-goto (ppc2-go-label true))
+           (false-is-goto (and (not true-is-goto) (ppc2-go-label false)))
+           (endlabel (backend-get-next-label))
+           (falselabel (backend-get-next-label))
+           (need-else (unless false-is-goto (or (not (nx-null false)) (ppc2-for-value-p vreg))))
+           (both-single-valued (and (not *ppc2-open-code-inline*)
+                                    (eq xfer $backend-return)
+                                    (ppc2-for-value-p vreg)
+                                    need-else
+                                    (ppc2-single-valued-form-p true) 
+                                    (ppc2-single-valued-form-p false))))
+      (if (eq 0 xfer) 
+        (setq xfer nil))
+      (if both-single-valued            ; it's implied that we're returning
+        (let* ((result ppc::arg_z))
+          (let ((merge-else-branch-label (if (nx-null false) (ppc2-find-nilret-label))))
+            (ppc2-conditional-form seg (ppc2-make-compound-cd 0 falselabel) testform)
+            (ppc2-form seg result endlabel true)
+            (if (and merge-else-branch-label (neq -1 (aref *backend-labels* merge-else-branch-label)))
+              (backend-copy-label merge-else-branch-label falselabel)
+              (progn
+                (@ falselabel)
+                (if (nx-null false) (@ (ppc2-record-nilret-label)))
+                (ppc2-form seg result nil false)))
+            (@ endlabel)
+            (<- result)
+            (^)))
+        (progn
+          (if (and need-else (ppc2-mvpass-p xfer))
+            (setq true-cleanup-label (backend-get-next-label)))         
+          (ppc2-conditional-form 
+           seg
+           (ppc2-make-compound-cd 
+            (or true-is-goto 0)
+            (or false-is-goto 
+                (if need-else 
+                  (if true-is-goto 0 falselabel) 
+                  (if true-is-goto xfer (ppc2-cd-merge xfer falselabel))))) 
+           testform)  
+          (if true-is-goto
+            (ppc2-unreachable-store)
+            (if true-cleanup-label
+              (progn
+                (ppc2-open-undo $undomvexpect)
+                (ppc2-form seg vreg (logior $backend-mvpass-mask true-cleanup-label) true))
+              (ppc2-form seg vreg (if need-else (ppc2-cd-merge xfer endlabel) xfer) true)))
+          (setq true-stack (ppc2-encode-stack))
+          (setq *ppc2-cstack* cstack)
+          (ppc2-set-vstack vstack)
+          (setq *ppc2-top-vstack-lcell* top-lcell)
+          (if false-is-goto (ppc2-unreachable-store))
+          (let ((merge-else-branch-label (if (and (nx-null false) (eq xfer $backend-return)) (ppc2-find-nilret-label))))
+            (if (and merge-else-branch-label (neq -1 (aref *backend-labels* merge-else-branch-label)))
+              (backend-copy-label merge-else-branch-label falselabel)
+              (progn
+                (@ falselabel)
+                (when need-else
+                  (if true-cleanup-label
+                    (ppc2-mvpass seg false)
+                    (ppc2-form seg vreg xfer false))
+                  (setq false-stack (ppc2-encode-stack))))))
+          (when true-cleanup-label
+            (if (setq same-stack-effects (ppc2-equal-encodings-p true-stack false-stack)) ; can share cleanup code
+              (@ true-cleanup-label))
+            (let* ((*ppc2-returning-values* :pass))
+              (ppc2-nlexit seg xfer 1)
+              (ppc2-branch seg (if (and xfer (neq xfer $backend-mvpass-mask)) xfer (if (not same-stack-effects) endlabel)) vreg))
+            (unless same-stack-effects
+              (@ true-cleanup-label)
+              (multiple-value-setq (true *ppc2-cstack* *ppc2-vstack* *ppc2-top-vstack-lcell*)
+                (ppc2-decode-stack true-stack))
+              (let* ((*ppc2-returning-values* :pass))
+                (ppc2-nlexit seg xfer 1)
+                (^)))
+            (ppc2-close-undo)
+            (multiple-value-setq (*ppc2-undo-count* *ppc2-cstack* *ppc2-vstack* *ppc2-top-vstack-lcell*) 
+              (ppc2-decode-stack entry-stack)))
+          (@ endlabel))))))
+
+(defppc2 ppc2-or or (seg vreg xfer forms)
+  (let* ((mvpass (ppc2-mvpass-p xfer))
+         (tag1 (backend-get-next-label))
+         (tag2 (backend-get-next-label))
+         (vstack *ppc2-vstack*)
+         (cstack *ppc2-cstack*)
+         (dest (if (backend-crf-p vreg) vreg (if vreg ppc::arg_z (available-crf-temp *available-backend-crf-temps*))))
+         (cd1 (ppc2-make-compound-cd 
+               (if (eq dest ppc::arg_z) tag1 (ppc2-cd-merge (ppc2-cd-true xfer) tag1)) 0)))
+    (while (cdr forms)
+      (ppc2-form seg dest (if (eq dest ppc::arg_z) nil cd1) (car forms))
+      (when (eq dest ppc::arg_z)
+        (with-crf-target () val-crf
+          (ppc2-copy-register seg val-crf dest)
+          (ppc2-branch seg cd1 val-crf)))
+      (setq forms (%cdr forms)))
+    (if mvpass
+      (progn (ppc2-multiple-value-body seg (car forms)) 
+             (let* ((*ppc2-returning-values* t)) (ppc2-branch seg (ppc2-cd-merge xfer tag2) vreg)))
+      (ppc2-form seg  vreg (if (eq dest ppc::arg_z) (ppc2-cd-merge xfer tag2) xfer) (car forms)))
+    (setq *ppc2-vstack* vstack *ppc2-cstack* cstack)
+    (@ tag1)
+    (when (eq dest ppc::arg_z)
+      (<- ppc::arg_z)
+      (^))
+    (@ tag2)))
+
+(defppc2 ppc2-simple-function simple-function (seg vreg xfer afunc)
+  (ppc2-immediate seg vreg xfer (ppc2-afunc-lfun-ref afunc)))
+
+(defppc2 ppc2-list list (seg vreg xfer arglist)
+  (if (null vreg)
+    (dolist (form arglist)
+      (ppc2-form seg vreg nil form)) 
+    (let* ((*ppc2-vstack* *ppc2-vstack*)
+           (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+           (nargs (ppc2-formlist seg arglist nil)))
+      (ppc2-set-nargs seg nargs)
+      (! list)
+      (<- ppc::arg_z)))
+  (^))
+
+(defppc2 ppc2-list* list* (seg vreg xfer arglist)
+  (if (null vreg)
+    (dolist (arg (apply #'append arglist))
+      (ppc2-form seg nil nil arg))
+    (let* ((*ppc2-vstack* *ppc2-vstack*)
+           (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+           (nargs (ppc2-arglist seg arglist)))
+      (declare (fixnum nargs))
+      (when (> nargs 1)
+        (ppc2-set-nargs seg (1- nargs))
+        (! list*))
+      (<- ppc::arg_z)))
+  (^))
+
+(defppc2 ppc2-minus1 minus1 (seg vreg xfer form)
+  (ppc2-unary-builtin seg vreg xfer '%negate form))
+
+(defun ppc2-inline-add2 (seg vreg xfer form1 form2)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (ppc2-two-targeted-reg-forms seg form1 ($ ppc::arg_y) form2 ($ ppc::arg_z))
+    (let* ((out-of-line (backend-get-next-label))
+           (done (backend-get-next-label)))
+      (ensuring-node-target (target vreg)
+        (if (acode-fixnum-form-p form1)
+          (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line))
+          (if (acode-fixnum-form-p form2)
+            (! branch-unless-arg-fixnum ($ ppc::arg_y) (aref *backend-labels* out-of-line))  
+            (! branch-unless-both-args-fixnums ($ ppc::arg_y) ($ ppc::arg_z) (aref *backend-labels* out-of-line))))
+        (if *ppc2-open-code-inline*
+          (! fixnum-add-overflow-inline-skip ($ ppc::arg_z) ($ ppc::arg_y) ($ ppc::arg_z) (aref *backend-labels* done))
+          (progn
+            (! fixnum-add-overflow-ool ($ ppc::arg_y) ($ ppc::arg_z))
+            (-> done)))
+        (@ out-of-line)
+        (! call-subprim-2 ($ ppc::arg_z) (subprim-name->offset '.SPbuiltin-plus) ($ ppc::arg_y) ($ ppc::arg_z))
+        (@ done)
+        (ppc2-copy-register seg target ($ ppc::arg_z)))
+      (^))))
+
+(defun ppc2-inline-sub2 (seg vreg xfer form1 form2)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (ppc2-two-targeted-reg-forms seg form1 ($ ppc::arg_y) form2 ($ ppc::arg_z))
+    (let* ((out-of-line (backend-get-next-label))
+           (done (backend-get-next-label)))
+      (ensuring-node-target (target vreg)
+        (if (acode-fixnum-form-p form1)
+          (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line))
+          (if (acode-fixnum-form-p form2)
+            (! branch-unless-arg-fixnum ($ ppc::arg_y) (aref *backend-labels* out-of-line))  
+            (! branch-unless-both-args-fixnums ($ ppc::arg_y) ($ ppc::arg_z) (aref *backend-labels* out-of-line))))
+        (if *ppc2-open-code-inline*
+          (! fixnum-sub-overflow-inline-skip ($ ppc::arg_z) ($ ppc::arg_y) ($ ppc::arg_z) (aref *backend-labels* done))
+          (progn
+            (! fixnum-sub-overflow-ool ($ ppc::arg_y) ($ ppc::arg_z))
+            (-> done)))
+        (@ out-of-line)
+        (! call-subprim-2 ($ ppc::arg_z) (subprim-name->offset '.SPbuiltin-minus) ($ ppc::arg_y) ($ ppc::arg_z))
+        (@ done)
+        (ppc2-copy-register seg target ($ ppc::arg_z)))
+      (^))))
+
+;;; Return T if form is declared to be something that couldn't be a fixnum.
+(defun ppc2-explicit-non-fixnum-type-p (form)
+  (let* ((type (ppc2-form-type form))
+         (target-fixnum-type (nx-target-type 'fixnum)))
+    (and (not (subtypep type target-fixnum-type))
+         (not (subtypep target-fixnum-type type)))))
+
+
+    
+
+(defppc2 ppc2-add2 add2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *ppc2-trust-declarations*)
+    (if (and (ppc2-form-typep form1 'double-float)
+             (ppc2-form-typep form2 'double-float))
+      (ppc2-use-operator (%nx1-operator %double-float+-2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (ppc2-form-typep form1 'single-float)
+               (ppc2-form-typep form2 'single-float))
+        (ppc2-use-operator (%nx1-operator %short-float+-2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+        (if (and (ppc2-form-typep form1 'fixnum)
+                 (ppc2-form-typep form2 'fixnum))
+          (ppc2-use-operator (%nx1-operator %i+)
+                             seg
+                             vreg
+                             xfer
+                             form1
+                             form2
+                             t)
+          (if (or (ppc2-explicit-non-fixnum-type-p form1)
+                  (ppc2-explicit-non-fixnum-type-p form2))
+            (ppc2-binary-builtin seg vreg xfer '+-2 form1 form2)
+            (ppc2-inline-add2 seg vreg xfer form1 form2)))))))
+
+(defppc2 ppc2-sub2 sub2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *ppc2-trust-declarations*)
+    (if (and (ppc2-form-typep form1 'double-float)
+             (ppc2-form-typep form2 'double-float))
+      (ppc2-use-operator (%nx1-operator %double-float--2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (ppc2-form-typep form1 'single-float)
+               (ppc2-form-typep form2 'single-float))
+        (ppc2-use-operator (%nx1-operator %short-float--2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+        (if (and (ppc2-form-typep form1 'fixnum)
+                 (ppc2-form-typep form2 'fixnum))
+          (ppc2-use-operator (%nx1-operator %i-)
+                             seg
+                             vreg
+                             xfer
+                             form1
+                             form2
+                             t)
+          (if (or (ppc2-explicit-non-fixnum-type-p form1)
+                  (ppc2-explicit-non-fixnum-type-p form2))
+            (ppc2-binary-builtin seg vreg xfer '--2 form1 form2)
+            (ppc2-inline-sub2 seg vreg xfer form1 form2)))))))
+
+(defppc2 ppc2-mul2 mul2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *ppc2-trust-declarations*)
+    (if (and (ppc2-form-typep form1 'double-float)
+             (ppc2-form-typep form2 'double-float))
+      (ppc2-use-operator (%nx1-operator %double-float*-2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (ppc2-form-typep form1 'single-float)
+               (ppc2-form-typep form2 'single-float))
+        (ppc2-use-operator (%nx1-operator %short-float*-2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+        (ppc2-binary-builtin seg vreg xfer '*-2 form1 form2)))))
+
+
+(defppc2 ppc2-div2 div2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *ppc2-trust-declarations*)
+    (if (and (ppc2-form-typep form1 'double-float)
+             (ppc2-form-typep form2 'double-float))
+      (ppc2-use-operator (%nx1-operator %double-float/-2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (ppc2-form-typep form1 'single-float)
+               (ppc2-form-typep form2 'single-float))
+        (ppc2-use-operator (%nx1-operator %short-float/-2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+        (let* ((f2 (acode-fixnum-form-p form2))
+               (unwrapped (acode-unwrapped-form form1))
+               (f1 nil)
+               (f1/f2 nil))
+          (if (and f2
+                   (not (zerop f2))
+                   (acode-p unwrapped)
+                   (or (eq (acode-operator unwrapped) (%nx1-operator mul2))
+                       (eq (acode-operator unwrapped) (%nx1-operator %i*)))
+                   (setq f1 (acode-fixnum-form-p (cadr unwrapped)))
+                   (typep (setq f1/f2 (/ f1 f2)) 'fixnum))
+            (ppc2-use-operator (%nx1-operator mul2)
+                               seg
+                               vreg
+                               xfer
+                               (make-acode (%nx1-operator fixnum) f1/f2)
+                               (caddr unwrapped))
+            (ppc2-binary-builtin seg vreg xfer '/-2 form1 form2)))))))
+
+(defppc2 ppc2-logbitp logbitp (seg vreg xfer bitnum int)
+  (ppc2-binary-builtin seg vreg xfer 'logbitp bitnum int))
+
+
+(defun ppc2-inline-logior2 (seg vreg xfer form1 form2)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((fix1 (acode-fixnum-form-p form1))
+           (fix2 (acode-fixnum-form-p form2)))
+      (if (and fix1 fix2)
+        (ppc2-use-operator (%nx1-operator fixnum) seg vreg xfer (logior fix1 fix2))
+        (let* ((fixval (or fix1 fix2))
+               (unboxed-fixval (if fixval (ash fixval *ppc2-target-fixnum-shift*)))
+               (high (if fixval (if (= unboxed-fixval (logand #xffff0000 unboxed-fixval)) (ash unboxed-fixval -16))))
+               (low (if fixval (unless high (if (= unboxed-fixval (logand #x0000ffff unboxed-fixval)) unboxed-fixval))))
+               (otherform (if (or high low) (if fix1 form2 form1)))
+               (out-of-line (backend-get-next-label))
+               (done (backend-get-next-label)))
+
+          (if otherform
+            (ppc2-one-targeted-reg-form seg otherform ($ ppc::arg_z))
+            (ppc2-two-targeted-reg-forms seg form1 ($ ppc::arg_y) form2 ($ ppc::arg_z)))
+          (ensuring-node-target (target vreg)
+            (if otherform
+              (unless (acode-fixnum-form-p otherform)
+                (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line)))
+              (if (acode-fixnum-form-p form1)
+                (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line))
+                (if (acode-fixnum-form-p form2)
+                  (! branch-unless-arg-fixnum ($ ppc::arg_y) (aref *backend-labels* out-of-line))  
+                  (! branch-unless-both-args-fixnums ($ ppc::arg_y) ($ ppc::arg_z) (aref *backend-labels* out-of-line)))))
+            (if otherform
+              (if high
+                (! logior-high ($ ppc::arg_z) ($ ppc::arg_z) high)
+                (! logior-low ($ ppc::arg_z) ($ ppc::arg_z) low))
+              (! %logior2 ($ ppc::arg_z) ($ ppc::arg_z) ($ ppc::arg_y)))
+            (-> done)
+            (@ out-of-line)
+            (if otherform
+              (ppc2-lri seg ($ ppc::arg_y) (ash fixval *ppc2-target-fixnum-shift*)))
+            (! call-subprim-2 ($ ppc::arg_z) (subprim-name->offset '.SPbuiltin-logior) ($ ppc::arg_y) ($ ppc::arg_z))
+            (@ done)
+            (ppc2-copy-register seg target ($ ppc::arg_z)))
+          (^))))))
+
+(defppc2 ppc2-logior2 logior2 (seg vreg xfer form1 form2)
+  (if (or (ppc2-explicit-non-fixnum-type-p form1)
+          (ppc2-explicit-non-fixnum-type-p form2))
+    (ppc2-binary-builtin seg vreg xfer 'logior-2 form1 form2)
+    (ppc2-inline-logior2 seg vreg xfer form1 form2)))
+
+(defppc2 ppc2-logxor2 logxor2 (seg vreg xfer form1 form2)
+  (ppc2-binary-builtin seg vreg xfer 'logxor-2 form1 form2))
+
+(defun ppc2-inline-logand2 (seg vreg xfer form1 form2)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2)))
+    (if (and fix1 fix2)
+      (ppc2-use-operator (%nx1-operator fixnum) seg vreg xfer (logand fix1 fix2))
+      (let* ((fixval (or fix1 fix2))
+             (fixlen (if fixval (integer-length fixval)))
+             (unboxed-fixval (if fixval (ash fixval *ppc2-target-fixnum-shift*)))
+             (high (if fixval (if (= unboxed-fixval (logand #xffff0000 unboxed-fixval)) (ash unboxed-fixval -16))))
+             (low (if fixval (unless high (if (= unboxed-fixval (logand #x0000ffff unboxed-fixval)) unboxed-fixval))))
+             (maskable (and fixval (= fixlen (logcount fixval))))
+             (otherform (if (or high low maskable) (if fix1 form2 form1)))
+             (out-of-line (backend-get-next-label))
+             (done (backend-get-next-label)))
+        (if otherform
+          (ppc2-one-targeted-reg-form seg otherform ($ ppc::arg_z))
+          (ppc2-two-targeted-reg-forms  seg form1 ($ ppc::arg_y) form2 ($ ppc::arg_z)))
+        (ensuring-node-target (target vreg)
+          (if otherform
+            (unless (acode-fixnum-form-p otherform)
+              (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line)))
+            (if (acode-fixnum-form-p form1)
+              (! branch-unless-arg-fixnum ($ ppc::arg_z) (aref *backend-labels* out-of-line))
+              (if (acode-fixnum-form-p form2)
+                (! branch-unless-arg-fixnum ($ ppc::arg_y) (aref *backend-labels* out-of-line))  
+                (! branch-unless-both-args-fixnums ($ ppc::arg_y) ($ ppc::arg_z) (aref *backend-labels* out-of-line)))))
+          (if otherform
+            (if (or high low)
+              (if high
+                (! logand-high ($ ppc::arg_z) ($ ppc::arg_z) high)
+                (! logand-low ($ ppc::arg_z) ($ ppc::arg_z) low))
+              (let* ((nbits (- *ppc2-target-bits-in-word*
+                             (1+ (+ *ppc2-target-fixnum-shift* fixlen)))))
+                (if (> fixval 0)
+                  (! clear-left ($ ppc::arg_z) ($ ppc::arg_z)  nbits)
+                  (! clear-right ($ ppc::arg_z) ($ ppc::arg_z) (+ fixlen
+                                                                  *ppc2-target-fixnum-shift*)))))
+            (! %logand2 ($ ppc::arg_z) ($ ppc::arg_z) ($ ppc::arg_y)))
+          (-> done)
+          (@ out-of-line)
+          (if otherform
+            (ppc2-lri seg ($ ppc::arg_y) (ash fixval *ppc2-target-fixnum-shift*)))
+            (! call-subprim-2 ($ ppc::arg_z) (subprim-name->offset '.SPbuiltin-logand) ($ ppc::arg_y) ($ ppc::arg_z))          
+            (@ done)
+            (ppc2-copy-register seg target ($ ppc::arg_z)))
+        (^))))))
+
+(defppc2 ppc2-logand2 logand2 (seg vreg xfer form1 form2)
+  (if (or (ppc2-explicit-non-fixnum-type-p form1)
+          (ppc2-explicit-non-fixnum-type-p form2))
+    (ppc2-binary-builtin seg vreg xfer 'logand-2 form1 form2)
+    (ppc2-inline-logand2 seg vreg xfer form1 form2)))
+
+
+
+(defppc2 ppc2-%aref1 %aref1 (seg vreg xfer v i)
+  (let* ((vtype (acode-form-type v t))
+         (atype (if vtype (specifier-type vtype)))
+         (keyword (if (and atype
+                           (let* ((dims (array-ctype-dimensions atype)))
+                             (or (eq dims '*)
+                                 (and (not (atom dims))
+                                      (= (length dims) 1))))
+                           (not (array-ctype-complexp atype)))
+                    (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (if keyword
+      (ppc2-vref  seg vreg xfer keyword v i (not *ppc2-reckless*))
+      (ppc2-binary-builtin seg vreg xfer '%aref1 v i))))
+
+(defppc2 ppc2-%aset1 aset1 (seg vreg xfer v i n)
+  (let* ((vtype (acode-form-type v t))
+         (atype (if vtype (specifier-type vtype)))
+         (keyword (if (and atype
+                           (let* ((dims (array-ctype-dimensions atype)))
+                             (or (eq dims '*)
+                                 (and (not (atom dims))
+                                      (= (length dims) 1))))
+                           (not (array-ctype-complexp atype)))
+                    (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (if keyword
+      (ppc2-vset seg vreg xfer keyword v i n (not *ppc2-reckless*))
+      (ppc2-ternary-builtin seg vreg xfer '%aset1 v i n))))
+
+(defppc2 ppc2-%i+ %i+ (seg vreg xfer form1 form2 &optional overflow)
+  (when overflow
+    (let* ((type *ppc2-target-half-fixnum-type*))
+      (when (and (ppc2-form-typep form1 type)
+                 (ppc2-form-typep form2 type))
+        (setq overflow nil))))
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2))
+         (sum (and fix1 fix2 (if overflow (+ fix1 fix2) (%i+ fix1 fix2)))))
+    (cond ((null vreg) 
+           (ppc2-form seg nil nil form1) 
+           (ppc2-form seg nil xfer form2))
+          (sum
+           (if (nx1-target-fixnump sum)
+             (ppc2-use-operator (%nx1-operator fixnum) seg vreg xfer sum)
+             (ppc2-use-operator (%nx1-operator immediate) seg vreg xfer sum)))
+          (overflow
+           (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form1 ppc::arg_y form2 ppc::arg_z)
+             (ensuring-node-target (target vreg)
+               (if *ppc2-open-code-inline*
+                 (! fixnum-add-overflow-inline target r1 r2)
+                 (progn
+                   (! fixnum-add-overflow-ool r1 r2)
+                   (ppc2-copy-register seg target ($ ppc::arg_z)))))
+             (^)))
+          (t                              
+           ;; There isn't any "addi" that checks for overflow, which is
+           ;; why we didn't bother.
+           (let* ((other (if (and fix1
+                                  (typep (ash fix1 *ppc2-target-fixnum-shift*)
+                                         '(signed-byte 32)))
+                           form2
+                           (if (and fix2
+                                    (typep (ash fix2 *ppc2-target-fixnum-shift*)
+                                           '(signed-byte 32)))
+                             form1))))
+             (if (and fix1 fix2)
+               (ppc2-lri seg vreg (ash (+ fix1 fix2) *ppc2-target-fixnum-shift*))
+               (if other
+                 (let* ((constant (ash (or fix1 fix2) *ppc2-target-fixnum-shift*))
+                        (reg (ppc2-one-untargeted-reg-form seg other ppc::arg_z))
+                        (high (ldb (byte 16 16) constant))
+                        (low (ldb (byte 16 0) constant)))
+                   (declare (fixnum high low))
+                   (if (zerop constant)
+                     (<- reg)
+                     (progn
+                       (if (logbitp 15 low) (setq high (ldb (byte 16 0) (1+ high))))
+                       (if (and (eq vreg reg) (not (zerop high)))
+                         (with-node-temps (vreg) (temp)
+                           (! add-immediate temp reg high low)
+                           (<- temp))
+                         (ensuring-node-target (target vreg)
+                           (! add-immediate target reg high low))))))
+                 (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form1 ppc::arg_y form2 ppc::arg_z)
+                   (ensuring-node-target (target vreg)
+                     (! fixnum-add target r1 r2)))))
+             (^))))))
+
+(defppc2 ppc2-%i- %i- (seg vreg xfer num1 num2 &optional overflow)
+  (when overflow
+    (let* ((type *ppc2-target-half-fixnum-type*))
+      (when (and (ppc2-form-typep num1 type)
+                 (ppc2-form-typep num2 type))
+        (setq overflow nil))))
+  (let* ((v1 (acode-fixnum-form-p num1))
+         (v2 (acode-fixnum-form-p num2))
+         (diff (and v1 v2 (if overflow (- v1 v2) (%i- v1 v2)))))
+    (if diff
+      (if (nx1-target-fixnump diff)
+        (ppc2-use-operator (%nx1-operator fixnum) seg vreg xfer diff)
+        (ppc2-use-operator (%nx1-operator immediate) seg vreg xfer diff))
+      (if (and v2 (neq v2 most-negative-fixnum))
+        (ppc2-use-operator (%nx1-operator %i+) seg vreg xfer num1 (make-acode (%nx1-operator fixnum) (- v2)) overflow) 
+        (if (eq v2 0)
+          (ppc2-form seg vreg xfer num1)
+          (cond
+           ((null vreg)
+            (ppc2-form seg nil nil num1)
+            (ppc2-form seg nil xfer num2))
+           (overflow
+            (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg num1 ppc::arg_y num2 ppc::arg_z)
+               (ensuring-node-target (target vreg)
+                 (if *ppc2-open-code-inline*
+                   (! fixnum-sub-overflow-inline target r1 r2)
+                   (progn
+                     (! fixnum-sub-overflow-ool r1 r2)
+                     (ppc2-copy-register seg target ($ ppc::arg_z)))))
+              (^)))
+           ((and v1 (<= (integer-length v1) (- 15 *ppc2-target-fixnum-shift*)))
+            (ensuring-node-target (target vreg)
+              (! fixnum-sub-from-constant target v1 (ppc2-one-untargeted-reg-form seg num2 ppc::arg_z)))
+            (^))
+           (t
+            (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg num1 ppc::arg_y num2 ppc::arg_z)
+              (ensuring-node-target (target vreg)
+                (! fixnum-sub target r1 r2))
+              (^)))))))))
+
+(defppc2 ppc2-%i* %i* (seg vreg xfer num1 num2)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil num1)
+      (ppc2-form seg nil xfer num2))  
+    (let* ((fix1 (acode-fixnum-form-p num1))
+           (fix2 (acode-fixnum-form-p num2))
+           (other (if (typep fix1 '(signed-byte 16)) num2 (if (typep fix2 '(signed-byte 16)) num1))))
+      (if (and fix1 fix2)
+        (ppc2-lri seg vreg (ash (* fix1 fix2) *ppc2-target-fixnum-shift*))
+        (if other
+          (! multiply-immediate vreg (ppc2-one-untargeted-reg-form seg other ppc::arg_z) (or fix1 fix2))
+          (multiple-value-bind (rx ry) (ppc2-two-untargeted-reg-forms seg num1 ppc::arg_y num2 ppc::arg_z)
+            (ensuring-node-target (target vreg)
+              (! multiply-fixnums target rx ry)))))
+      (^))))
+
+(defppc2 ppc2-nth-value nth-value (seg vreg xfer n form)
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+    (let* ((nreg (ppc2-one-untargeted-reg-form seg n ppc::arg_z)))
+      (unless (acode-fixnum-form-p n)
+        (! trap-unless-fixnum nreg))
+      (ppc2-vpush-register seg nreg))
+     (ppc2-multiple-value-body seg form) ; sets nargs
+    (! nth-value ppc::arg_z))
+  (<- ppc::arg_z)
+  (^))
+
+(defppc2 ppc2-values values (seg vreg xfer forms)
+  (if (eq (list-length forms) 1)
+    (if (ppc2-cd-compound-p xfer)
+      (ppc2-form seg vreg xfer (%car forms))
+      (progn
+        (ppc2-form seg vreg nil (%car forms))
+        (^)))
+    (if (not (ppc2-mv-p xfer))
+      (if forms
+        (ppc2-use-operator (%nx1-operator prog1) seg vreg xfer forms)
+        (ppc2-nil seg vreg xfer))
+      (progn
+        (let* ((*ppc2-vstack* *ppc2-vstack*)
+               (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+          (ppc2-set-nargs seg (ppc2-formlist seg forms nil)))
+        (let* ((*ppc2-returning-values* t))
+          (^))))))
+
+(defppc2 ppc2-base-char-p base-char-p (seg vreg xfer cc form)
+  (ppc2-char-p seg vreg xfer cc form))
+
+(defun ppc2-char-p (seg vreg xfer cc form)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+      (! mask-base-char ppc::imm0 (ppc2-one-untargeted-reg-form seg form ppc::arg_z))
+      (ppc2-test-reg-%izerop seg vreg xfer ppc::imm0 cr-bit true-p
+                             (target-arch-case
+                              (:ppc32 ppc32::subtag-character)
+                              (:ppc64 ppc64::subtag-character))))))
+
+
+(defppc2 ppc2-let* let* (seg vreg xfer vars vals body p2decls &aux
+                             (old-stack (ppc2-encode-stack)))
+  (ppc2-check-lcell-depth)
+  (with-ppc-p2-declarations p2decls
+    (ppc2-seq-bind seg vars vals)
+    (ppc2-undo-body seg vreg xfer body old-stack))
+  (dolist (v vars) (ppc2-close-var seg v)))
+
+(defppc2 ppc2-multiple-value-bind multiple-value-bind (seg vreg xfer vars valform body p2decls)
+  (let* ((n (list-length vars))
+         (vloc *ppc2-vstack*)
+         (nbytes (* n *ppc2-target-node-size*))
+         (old-stack (ppc2-encode-stack)))
+    (with-ppc-p2-declarations p2decls
+      (ppc2-multiple-value-body seg valform)
+      (ppc2-lri seg ppc::imm0 nbytes)
+      (! fitvals)
+      (ppc2-set-vstack (%i+ vloc nbytes))
+      (let* ((old-top *ppc2-top-vstack-lcell*)
+             (lcells (progn (ppc2-reserve-vstack-lcells n) (ppc2-collect-lcells :reserved old-top))))
+        (dolist (var vars)
+          (let* ((lcell (pop lcells))
+                 (reg (nx2-assign-register-var var)))
+            (if reg
+              (ppc2-init-regvar seg var reg (ppc2-vloc-ea vloc))
+              (ppc2-bind-var seg var vloc lcell))          
+            (setq vloc (%i+ vloc *ppc2-target-node-size*)))))
+      (ppc2-undo-body seg vreg xfer body old-stack)
+      (dolist (var vars)
+        (ppc2-close-var seg var)))))
+
+(defppc2 ppc2-debind debind (seg vreg xfer lambda-list bindform req opt rest keys auxen whole body p2decls cdr-p)
+  (declare (ignore lambda-list))
+  (let* ((old-stack (ppc2-encode-stack))
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+         (vloc *ppc2-vstack*))
+    (with-ppc-p2-declarations p2decls      
+      (ppc2-bind-structured-lambda
+       seg 
+       (ppc2-spread-lambda-list seg bindform whole req opt rest keys nil cdr-p)
+       vloc (ppc2-vloc-ea vloc) whole req opt rest keys auxen)
+      (ppc2-undo-body seg vreg xfer body old-stack)
+      (ppc2-close-structured-lambda seg whole req opt rest keys auxen))))
+
+(defppc2 ppc2-multiple-value-prog1 multiple-value-prog1 (seg vreg xfer forms)
+  (if (or (not (ppc2-mv-p xfer)) (ppc2-single-valued-form-p (%car forms)))
+    (ppc2-use-operator (%nx1-operator prog1) seg vreg xfer forms)
+    (if (null (cdr forms))
+      (ppc2-form seg vreg xfer(car forms))
+      (progn
+        (let* ((*ppc2-vstack* *ppc2-vstack*)
+               (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+          (ppc2-multiple-value-body seg (%car forms))
+          (ppc2-open-undo $undostkblk)
+          (! save-values))
+        (dolist (form (cdr forms))
+          (ppc2-form seg nil nil form))
+        (ppc2-set-nargs seg 0)
+        (! recover-values)
+        (ppc2-close-undo)
+        (let* ((*ppc2-returning-values* t))
+          (^))))))
+
+(defppc2 ppc2-not not (seg vreg xfer cc form)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+  (ppc2-compare-register-to-nil
+   seg 
+   vreg 
+   xfer
+   (ppc2-one-untargeted-reg-form seg form ppc::arg_z) 
+   cr-bit
+   true-p)))
+
+
+(defppc2 ppc2-%alloc-misc %make-uvector (seg vreg xfer element-count st &optional initval)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil element-count)
+      (ppc2-form seg nil xfer st))
+    (let* ((subtag (acode-fixnum-form-p st))
+           (nelements (acode-fixnum-form-p element-count))         
+           (nbytes (if (and subtag nelements) (ppc2-misc-byte-count subtag nelements))))
+      (if (and  nbytes (null initval)
+                (< (logand
+                    (lognot (1- (* 2 *ppc2-target-node-size*)))
+                    (+ nbytes *ppc2-target-node-size*
+                       (1- (* 2 *ppc2-target-node-size*)))) #x8000))
+        (with-imm-temps () (header)
+          (ppc2-lri seg header (arch::make-vheader nelements subtag))
+          (ensuring-node-target (target vreg)
+            (! %alloc-misc-fixed target header nbytes)))
+        (progn
+          (if initval
+            (progn
+              (ppc2-three-targeted-reg-forms seg element-count ($ ppc::arg_x) st ($ ppc::arg_y) initval ($ ppc::arg_z))
+              (! misc-alloc-init)
+              (<- ($ ppc::arg_z)))
+            (progn
+              (ppc2-two-targeted-reg-forms seg element-count ($ ppc::arg_y) st ($ ppc::arg_z))
+              (! misc-alloc)
+              (<- ($ ppc::arg_z))))))
+        (^))))
+
+(defppc2 ppc2-%iasr %iasr (seg vreg xfer form1 form2)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil form1)
+      (ppc2-form seg vreg xfer form2))
+    (let* ((count (acode-fixnum-form-p form1))
+           (max (target-arch-case (:ppc32 31) (:ppc64 63))))
+      (declare (fixnum max))
+      (ensuring-node-target (target vreg)
+        (if count
+          (! %iasr-c target (if (> count max) max count)
+             (ppc2-one-untargeted-reg-form seg form2 ppc::arg_z))
+          (multiple-value-bind (cnt src) (ppc2-two-targeted-reg-forms seg form1 ($ ppc::arg_y) form2 ($ ppc::arg_z))
+            (! %iasr target cnt src))))
+      (^))))
+
+(defppc2 ppc2-%ilsr %ilsr (seg vreg xfer form1 form2)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil form1)
+      (ppc2-form seg vreg xfer form2))
+    (let* ((count (acode-fixnum-form-p form1)))
+      (ensuring-node-target (target vreg)
+        (if count
+          (let ((src (ppc2-one-untargeted-reg-form seg form2 ($ ppc::arg_z))))
+            (if (<= count 31)
+              (! %ilsr-c target count src)
+              (!  lri target 0)))
+          (multiple-value-bind (cnt src) (ppc2-two-targeted-reg-forms seg form1 ($ ppc::arg_y) form2 ($ ppc::arg_z))
+            (! %ilsr target cnt src))))
+      (^))))
+
+
+(defppc2 ppc2-%i<> %i<> (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (ppc2-compare seg vreg xfer form1 form2 cr-bit true-p)))
+
+(defppc2 ppc2-%natural<> %natural<> (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (ppc2-natural-compare seg vreg xfer form1 form2 cr-bit true-p)))
+
+(defppc2 ppc2-double-float-compare double-float-compare (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (with-fp-target () (r1 :double-float)
+      (with-fp-target (r1) (r2 :double-float)
+        (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form1 r1 form2 r2)
+          (ppc2-compare-double-float-registers seg vreg xfer r1 r2 cr-bit true-p))))))
+
+(defppc2 ppc2-short-float-compare short-float-compare (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (with-fp-target () (r1 :single-float)
+      (with-fp-target (r1) (r2 :single-float)
+        (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg form1 r1 form2 r2)
+          (ppc2-compare-double-float-registers seg vreg xfer r1 r2 cr-bit true-p))))))
+ 
+(eval-when (:compile-toplevel :execute)
+  (defmacro defppc2-df-op (fname opname vinsn)
+    `(defppc2 ,fname ,opname (seg vreg xfer f0 f1)
+       (if (null vreg)
+         (progn
+           (ppc2-form seg nil nil f0)
+           (ppc2-form seg vreg xfer f1))
+         (with-fp-target () (r1 :double-float)
+           (with-fp-target (r1) (r2 :double-float)
+             (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg f0 r1 f1 r2)
+               (if (= (hard-regspec-class vreg) hard-reg-class-fpr)
+                 (! ,vinsn vreg r1 r2)
+                 (with-fp-target (r1 r2) (result :double-float)
+                   (! ,vinsn result r1 r2)
+                   (ensuring-node-target (target vreg)
+                     (ppc2-copy-register seg target result))))
+               (^)))))))
+  
+  (defmacro defppc2-sf-op (fname opname vinsn)
+    `(defppc2 ,fname ,opname (seg vreg xfer f0 f1)
+       (if (null vreg)
+         (progn
+           (ppc2-form seg nil nil f0)
+           (ppc2-form seg vreg xfer f1))
+         (with-fp-target () (r1 :single-float)
+           (with-fp-target (r1) (r2 :single-float)
+             (multiple-value-bind (r1 r2) (ppc2-two-untargeted-reg-forms seg f0 r1 f1 r2)
+               (if (= (hard-regspec-class vreg) hard-reg-class-fpr)
+		 (! ,vinsn vreg r1 r2)
+                 (with-fp-target (r1 r2) (result :single-float)
+                   (! ,vinsn result r1 r2)
+                   (ensuring-node-target (target vreg)
+                     (ppc2-copy-register seg target result))))
+               (^)))))))
+)
+
+(defppc2-df-op ppc2-%double-float+-2 %double-float+-2 double-float+-2)
+(defppc2-df-op ppc2-%double-float--2 %double-float--2 double-float--2)
+(defppc2-df-op ppc2-%double-float*-2 %double-float*-2 double-float*-2)
+(defppc2-df-op ppc2-%double-float/-2 %double-float/-2 double-float/-2)
+
+(defppc2-sf-op ppc2-%short-float+-2 %short-float+-2 single-float+-2)
+(defppc2-sf-op ppc2-%short-float--2 %short-float--2 single-float--2)
+(defppc2-sf-op ppc2-%short-float*-2 %short-float*-2 single-float*-2)
+(defppc2-sf-op ppc2-%short-float/-2 %short-float/-2 single-float/-2)
+
+(defun ppc2-get-float (seg vreg xfer ptr offset double-p fp-reg)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (cond ((null vreg)
+           (ppc2-form seg nil nil ptr)
+           (ppc2-form seg nil xfer offset))
+          (t
+           (let* ((fixoffset (acode-fixnum-form-p offset)))
+             (if (typep fixoffset '(unsigned-byte 15))
+               (with-imm-target () (ptrreg :address)
+                 (ppc2-form seg ptrreg nil ptr)
+                 (if double-p
+                   (! mem-ref-c-double-float fp-reg ptrreg fixoffset)
+                   (! mem-ref-c-single-float fp-reg ptrreg fixoffset)))
+               (with-imm-target () (ptrreg :address)
+                 (with-imm-target (ptrreg) (offsetreg :s32)
+                   (ppc2-two-targeted-reg-forms seg
+                                                ptr ptrreg
+                                                offset ($ ppc::arg_z))
+                   (! fixnum->signed-natural offsetreg ppc::arg_z)
+                   (if double-p
+                     (! mem-ref-double-float fp-reg ptrreg offsetreg)
+                     (! mem-ref-single-float fp-reg ptrreg offsetreg)))))
+             (<- fp-reg))
+           (^)))))
+    
+
+(defppc2 ppc2-%get-double-float %get-double-float (seg vreg xfer ptr offset)
+  (with-fp-target () (fp-reg :double-float)
+    (ppc2-get-float seg vreg xfer ptr offset t fp-reg)))
+
+(defppc2 ppc2-%get-single-float %get-single-float (seg vreg xfer ptr offset)
+  (with-fp-target () (fp-reg :single-float)
+    (ppc2-get-float seg vreg xfer ptr offset nil fp-reg)))
+
+(defun ppc2-set-float (seg vreg xfer ptr offset newval double-p fp-reg)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((fixoffset (acode-fixnum-form-p offset))
+           (immoffset (typep fixoffset '(unsigned-byte 15))))
+      (with-imm-target () (ptr-reg :address) 
+        (cond ((or (null vreg)
+                   (= (hard-regspec-class vreg) hard-reg-class-fpr))
+               (cond (immoffset
+                      (ppc2-push-register
+                       seg
+                       (ppc2-one-untargeted-reg-form seg
+                                                     ptr
+                                                     ptr-reg))
+                      (ppc2-one-targeted-reg-form seg newval fp-reg)
+                      (ppc2-pop-register seg ptr-reg)
+                      (if double-p
+                        (! mem-set-c-double-float fp-reg ptr-reg fixoffset)
+                        (! mem-set-c-single-float fp-reg ptr-reg fixoffset)))
+                     (t
+                      (with-imm-target (ptr-reg) (offset-reg :s32)
+                        (ppc2-push-register
+                         seg
+                         (ppc2-one-untargeted-reg-form seg
+                                                       ptr
+                                                       ptr-reg))
+                        (ppc2-push-register
+                         seg
+                         (ppc2-one-untargeted-reg-form seg
+                                                       offset
+                                                       ppc::arg_z))
+                        (ppc2-one-targeted-reg-form seg newval fp-reg)
+                        (ppc2-pop-register seg ppc::arg_z)
+                        (ppc2-pop-register seg ptr-reg)
+                        (! fixnum->signed-natural offset-reg ppc::arg_z)
+                        (if double-p
+                          (! mem-set-double-float fp-reg ptr-reg offset-reg)
+                          (! mem-set-single-float fp-reg ptr-reg offset-reg)))))
+               (<- fp-reg))
+              (t
+               (cond (immoffset
+                      (let* ((rnew ($ ppc::arg_z)))
+                        (ppc2-push-register
+                         seg
+                         (ppc2-one-untargeted-reg-form seg
+                                                       ptr
+                                                       ptr-reg))
+                        (ppc2-one-targeted-reg-form seg newval rnew)
+                        (ppc2-pop-register seg ptr-reg)
+                        (with-imm-temps (ptr-reg) ()
+                          (ppc2-copy-register seg fp-reg rnew)
+                          (if double-p
+                            (! mem-set-c-double-float fp-reg ptr-reg fixoffset)
+                            (! mem-set-c-single-float fp-reg ptr-reg fixoffset)))))
+                     (t
+                      (let* ((roffset ($ ppc::arg_y))
+                             (rnew ($ ppc::arg_z)))
+                        (ppc2-push-register
+                         seg
+                         (ppc2-one-untargeted-reg-form
+                          seg
+                          ptr ptr-reg))
+                        (ppc2-two-targeted-reg-forms seg
+                                                   offset roffset
+                                                   newval rnew)
+                        (ppc2-pop-register seg ptr-reg)
+                        (with-imm-target (ptr-reg) (offset-reg :s32)
+                          (with-imm-temps (ptr-reg offset-reg) ()
+                            (! fixnum->signed-natural offset-reg roffset)
+                            (ppc2-copy-register seg fp-reg rnew))
+                        (if double-p
+                          (! mem-set-double-float fp-reg ptr-reg offset-reg)
+                          (! mem-set-single-float fp-reg ptr-reg offset-reg))))))
+               (<- ppc::arg_z)))
+        (^)))))
+
+(defppc2 ppc2-%set-double-float %set-double-float (seg vreg xfer ptr offset newval)
+  (with-fp-target () (fp-reg :double-float)
+    (ppc2-set-float seg vreg xfer ptr offset newval t fp-reg)))
+      
+(defppc2 ppc2-%set-single-float %set-single-float (seg vreg xfer ptr offset newval)
+  (with-fp-target () (fp-reg :single-float)
+    (ppc2-set-float seg vreg xfer ptr offset newval nil fp-reg)))
+
+(defppc2 ppc2-immediate-get-ptr immediate-get-ptr (seg vreg xfer ptr offset)
+  (let* ((absptr (acode-absolute-ptr-p ptr))
+         (triv-p (ppc2-trivial-p offset))
+         (dest vreg)
+         (offval (acode-fixnum-form-p offset)))
+    (cond ((not vreg)
+           (ppc2-form seg nil nil ptr)
+           (ppc2-form seg nil xfer offset))
+          (t
+           (if (and absptr offval) 
+             (setq absptr (+ absptr offval) offval 0)
+             (setq absptr nil))
+           (and offval (%i> (integer-length offval) 15) (setq offval nil))
+           (and absptr (%i> (integer-length absptr) 15) (setq absptr nil))
+           (target-arch-case
+            (:ppc32 (progn))
+            (:ppc64 (progn
+                      (and offval (logtest 3 offval) (setq offval nil))
+                      (and absptr (logtest 3 absptr) (setq absptr nil)))))
+           (if absptr
+             (! mem-ref-c-natural dest ppc::rzero absptr)
+             (if offval
+               (let* ((src (ppc2-macptr-arg-to-reg seg ptr ($ ppc::imm0 :mode :address))))
+                 (! mem-ref-c-natural dest src offval))
+               (let* ((src (ppc2-macptr-arg-to-reg seg ptr ($ ppc::imm0 :mode :address))))
+                 (if triv-p
+                   (with-imm-temps (src) (x)
+                     (if (acode-fixnum-form-p offset)
+                       (ppc2-lri seg x (acode-fixnum-form-p offset))
+                       (! fixnum->signed-natural x (ppc2-one-untargeted-reg-form seg offset ppc::arg_z)))
+                     (! mem-ref-natural dest src x))
+                   (progn
+                     (! temp-push-unboxed-word src)
+                     (ppc2-open-undo $undostkblk)
+                     (let* ((oreg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z)))
+                       (with-imm-temps () (src x)
+                         (! temp-pop-unboxed-word src)
+                         (ppc2-close-undo)
+                         (! fixnum->signed-natural x oreg)
+                         (! mem-ref-natural dest src x)))))))) 
+           (^)))))
+
+(defppc2 ppc2-get-bit %get-bit (seg vreg xfer ptr offset)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil ptr)
+      (ppc2-form seg nil ptr nil))
+    (let* ((offval (acode-fixnum-form-p offset))
+           (byte-index (if offval (ash offval -3)))
+           (bit-shift (if (and byte-index (< byte-index #x8000))
+                        (logand 31 (+ 25 (logand offval 7))))))
+      (if bit-shift
+        (with-imm-target ()
+          (src-reg :address)
+          (ppc2-one-targeted-reg-form seg ptr src-reg)
+          (if (node-reg-p vreg)
+            (! mem-ref-c-bit-fixnum vreg src-reg byte-index (logand 31 (+ bit-shift
+                                                                           *ppc2-target-fixnum-shift*)))
+            (with-imm-target ()           ;OK if src-reg & dest overlap
+              (dest :u8)
+              (! mem-ref-c-bit dest src-reg  byte-index bit-shift)
+              (<- dest))))
+        (let* ((triv-p (ppc2-trivial-p offset))
+               (offset-reg nil))
+          (with-imm-target ()
+            (src-reg :address)
+            (ppc2-one-targeted-reg-form seg ptr src-reg)
+            (unless triv-p
+              (! temp-push-unboxed-word src-reg)
+              (ppc2-open-undo $undostkblk))
+            (setq offset-reg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z))
+            (unless triv-p
+              (! temp-pop-unboxed-word src-reg)
+              (ppc2-close-undo))
+            (if (node-reg-p vreg)
+              (! mem-ref-bit-fixnum vreg src-reg offset-reg)
+              (with-imm-target ()
+                (dest :u8)
+                (! mem-ref-bit dest src-reg offset-reg)
+                (<- dest))))))))
+  (^))
+    
+      
+                                      
+;;; This returns an unboxed object, unless the caller wants to box it.
+(defppc2 ppc2-immediate-get-xxx immediate-get-xxx (seg vreg xfer bits ptr offset)
+  (declare (fixnum bits))
+  (let* ((fixnump (logbitp 6 bits))
+         (signed (logbitp 5 bits))
+         (size (logand 15 bits))
+         (absptr (acode-absolute-ptr-p ptr))
+         (triv-p (ppc2-trivial-p offset))
+         (offval (acode-fixnum-form-p offset)))
+    (declare (fixnum size))
+    (cond ((null vreg)
+           (ppc2-form seg nil nil ptr)
+           (ppc2-form seg nil xfer offset))
+          (t 
+           (if (and absptr offval) 
+             (setq absptr (+ absptr offval) offval 0)
+             (setq absptr nil))
+           (and offval (%i> (integer-length offval) 15) (setq offval nil))
+           (and absptr (%i> (integer-length absptr) 15) (setq absptr nil))
+           (target-arch-case
+            (:ppc32 (progn))
+            (:ppc64 (when (or fixnump (eql size 8) (and (eql size 8) signed))
+                      (and offval (logtest 3 offval) (setq offval nil))
+                      (and absptr (logtest 3 absptr) (setq absptr nil))))) 
+           (cond
+             (fixnump
+              (with-imm-target () (dest :signed-natural)
+                (cond
+                  (absptr                              
+                   (target-arch-case
+                    (:ppc32 (! mem-ref-c-fullword dest ppc::rzero absptr))
+                    (:ppc64 (! mem-ref-c-doubleword dest ppc::rzero absptr))))
+                  (offval
+                    (with-imm-target () (src-reg :address)
+                      (ppc2-one-targeted-reg-form seg ptr src-reg)
+                      (target-arch-case
+                       (:ppc32 (! mem-ref-c-fullword dest src-reg offval))
+                       (:ppc64 (! mem-ref-c-doubleword dest src-reg offval)))))
+                  (t
+                   (with-imm-target () (src-reg :address)
+                     (with-imm-target (src-reg) (offset-reg :signed-natural)
+                       (ppc2-one-targeted-reg-form seg ptr src-reg)
+                       (if triv-p
+                         (if (acode-fixnum-form-p offset)
+                           (ppc2-lri seg offset-reg (acode-fixnum-form-p offset))
+                           (! fixnum->signed-natural offset-reg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z)))
+                         (progn
+                           (! temp-push-unboxed-word src-reg)
+                           (ppc2-open-undo $undostkblk)
+                           (! fixnum->signed-natural offset-reg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z))
+                           (! temp-pop-unboxed-word src-reg)
+                           (ppc2-close-undo)))
+                       (target-arch-case
+                        (:ppc32 (! mem-ref-fullword dest src-reg offset-reg))
+                        (:ppc64 (! mem-ref-doubleword dest src-reg offset-reg)))))))
+                (if (node-reg-p vreg)
+                  (! box-fixnum vreg dest)
+                  (<- dest))))
+             (signed
+              (with-imm-target () (dest :signed-natural)
+               (cond
+                 (absptr
+                  (case size
+                    (8 (! mem-ref-c-signed-doubleword dest ppc::rzero absptr))
+                    (4 (! mem-ref-c-signed-fullword dest ppc::rzero absptr))
+                    (2 (! mem-ref-c-s16 dest ppc::rzero absptr))
+                    (1 (! mem-ref-c-s8 dest ppc::rzero absptr))))
+                 (offval
+                  (with-imm-target (dest) (src-reg :address)
+                   (ppc2-one-targeted-reg-form seg ptr src-reg)
+                     (case size
+                       (8 (! mem-ref-c-signed-doubleword dest src-reg offval))
+                       (4 (! mem-ref-c-signed-fullword dest src-reg offval))
+                       (2 (! mem-ref-c-s16 dest src-reg offval))
+                       (1 (! mem-ref-c-s8 dest src-reg offval)))))
+                 (t
+                  (with-imm-target () (src-reg :address)
+                    (with-imm-target (src-reg) (offset-reg :signed-natural)
+                     (ppc2-one-targeted-reg-form seg ptr src-reg)
+                     (if triv-p
+                       (if (acode-fixnum-form-p offset)
+                         (ppc2-lri seg offset-reg (acode-fixnum-form-p offset))
+                         (! fixnum->signed-natural offset-reg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z)))
+                       (progn
+                         (! temp-push-unboxed-word src-reg)
+                         (ppc2-open-undo $undostkblk)
+                         (! fixnum->signed-natural offset-reg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z))
+                         (! temp-pop-unboxed-word src-reg)
+                         (ppc2-close-undo)))
+                  (case size
+                    (8 (! mem-ref-signed-doubleword dest src-reg offset-reg))
+                    (4 (! mem-ref-signed-fullword dest src-reg offset-reg))
+                    (2 (! mem-ref-s16 dest src-reg offset-reg))
+                    (1 (! mem-ref-s8 dest src-reg offset-reg)))))))
+               (if (node-reg-p vreg)
+                 (case size
+                   ((1 2) (! box-fixnum vreg dest))
+                   (4 (target-arch-case
+                       (:ppc32
+                        (<- dest))
+                       (:ppc64 (! box-fixnum vreg dest))))
+                   (8 (<- dest)))
+                 (<- dest))))
+             (t
+              (with-imm-target () (dest :natural)
+               (cond
+                 (absptr
+                  (case size
+                    (8 (! mem-ref-c-doubleword dest ppc::rzero absptr))
+                    (4 (! mem-ref-c-fullword dest ppc::rzero absptr))
+                    (2 (! mem-ref-c-u16 dest ppc::rzero absptr))
+                    (1 (! mem-ref-c-u8 dest ppc::rzero absptr))))
+                 (offval
+                  (with-imm-target (dest) (src-reg :address)
+                    (ppc2-one-targeted-reg-form seg ptr src-reg)
+                    (case size
+                      (8 (! mem-ref-c-doubleword dest src-reg offval))
+                      (4 (! mem-ref-c-fullword dest src-reg offval))
+                      (2 (! mem-ref-c-u16 dest src-reg offval))
+                      (1 (! mem-ref-c-u8 dest src-reg offval)))))
+                 (t
+                  (with-imm-target () (src-reg :address)
+                    (with-imm-target (src-reg) (offset-reg :signed-natural)
+                     (ppc2-one-targeted-reg-form seg ptr src-reg)
+                     (if triv-p
+                       (if (acode-fixnum-form-p offset)
+                         (ppc2-lri seg offset-reg (acode-fixnum-form-p offset))
+                         (! fixnum->signed-natural offset-reg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z)))
+                       (progn
+                         (! temp-push-unboxed-word src-reg)
+                         (ppc2-open-undo $undostkblk)
+                         (! fixnum->signed-natural offset-reg (ppc2-one-untargeted-reg-form seg offset ppc::arg_z))
+                         (! temp-pop-unboxed-word src-reg)
+                         (ppc2-close-undo)))
+                  (case size
+                    (8 (! mem-ref-doubleword dest src-reg offset-reg))
+                    (4 (! mem-ref-fullword dest src-reg offset-reg))
+                    (2 (! mem-ref-u16 dest src-reg offset-reg))
+                    (1 (! mem-ref-u8 dest src-reg offset-reg)))))))
+                  (<- (set-regspec-mode 
+                       dest 
+                       (gpr-mode-name-value
+                        (case size
+                          (8 :u64)
+                          (4 :u32)
+                          (2 :u16)
+                          (1 :u8))))))))
+           (^)))))
+
+(defppc2 ppc2-let let (seg vreg xfer vars vals body p2decls)
+  (let* ((old-stack (ppc2-encode-stack))
+         (val nil)
+         (bits nil)
+         (valcopy vals))
+    (with-ppc-p2-declarations p2decls
+      (dolist (var vars)
+        (setq val (%car valcopy))
+        (cond ((or (%ilogbitp $vbitspecial (setq bits (nx-var-bits var)))
+                   (and (var-nvr var)
+                        (dolist (val (%cdr valcopy))
+                          (unless (ppc2-trivial-p val) (return t)))))
+               (let* ((pair (cons (ppc2-vloc-ea *ppc2-vstack*) nil)))
+                 (%rplaca valcopy pair)
+                 (if (and (%ilogbitp $vbitdynamicextent bits)
+                          (progn
+                            (setq val 
+                                  (ppc2-dynamic-extent-form seg (ppc2-encode-stack) val))
+                            (ppc2-load-ea-p val)))
+                   (progn
+                     (%rplaca pair (ppc2-vloc-ea *ppc2-vstack*))
+                     (ppc2-vpush-register seg val :reserved))
+                 (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg val ppc::arg_z) :reserved))
+                 (%rplacd pair *ppc2-top-vstack-lcell*)))
+              (t (ppc2-seq-bind-var seg var val)
+                 (%rplaca valcopy nil)))
+        (setq valcopy (%cdr valcopy)))
+      (dolist (var vars)
+        (declare (list val))
+        (when (setq val (pop vals))
+          (if (%ilogbitp $vbitspecial (nx-var-bits var))
+            (progn
+              (ppc2-dbind seg (car val) (var-name var))
+              (ppc2-set-var-ea seg var (ppc2-vloc-ea (- *ppc2-vstack* *ppc2-target-node-size*))))
+            (ppc2-seq-bind-var seg var (car val)))))
+      (ppc2-undo-body seg vreg xfer body old-stack)
+      (dolist (var vars)
+        (ppc2-close-var seg var)))))
+
+(defppc2 ppc2-closed-function closed-function (seg vreg xfer afunc)
+  (ppc2-make-closure seg afunc nil)
+  (when vreg (<- ppc::arg_z))
+  (^))
+
+(defppc2 ppc2-flet flet (seg vreg xfer vars afuncs body p2decls)
+  (if (dolist (afunc afuncs)
+        (unless (eql 0 (afunc-fn-refcount afunc))
+          (return t)))
+    (ppc2-seq-fbind seg vreg xfer vars afuncs body p2decls)
+    (with-ppc-p2-declarations p2decls
+      (ppc2-form seg vreg xfer body))))
+
+(defppc2 ppc2-labels labels (seg vreg xfer vars afuncs body p2decls)
+  (let* ((fwd-refs nil)
+         (func nil)
+         (togo vars)
+         (real-vars ())
+         (real-funcs ())
+         (funs afuncs))
+    (dolist (v vars)
+      (when (neq 0 (afunc-fn-refcount (setq func (pop funs))))
+        (push v real-vars)
+        (push func real-funcs)
+        (let* ((i 2)
+               (our-var nil)
+               (item nil))
+          (declare (fixnum i))
+          (dolist (ref (afunc-inherited-vars func))
+            (when (memq (setq our-var (var-bits ref)) togo)
+              (setq item (cons i our-var))
+              (let* ((refs (assq v fwd-refs)))
+                (if refs
+                  (push item (cdr refs))
+                  (push (list v item) fwd-refs))))
+            (incf i)))
+        (setq togo (%cdr togo))))       
+    (if (null fwd-refs)
+      (ppc2-seq-fbind seg vreg xfer (nreverse real-vars) (nreverse real-funcs) body p2decls)
+      (let* ((old-stack (ppc2-encode-stack)))
+        (setq real-vars (nreverse real-vars) real-funcs (nreverse real-funcs))
+        (with-ppc-p2-declarations p2decls
+          (dolist (var real-vars)
+            (ppc2-seq-bind-var seg var (nx1-afunc-ref (pop real-funcs))))
+          (dolist (ref fwd-refs)
+            (let ((ea (var-ea (pop ref))))
+              (ppc2-addrspec-to-reg seg ea ppc::temp0)
+              (dolist (r ref)
+                (let* ((v-ea (var-ea (cdr r))))
+                  (let* ((val-reg (if (eq v-ea ea)
+                                    ppc::temp0
+                                    (progn
+                                      (ppc2-addrspec-to-reg seg v-ea ppc::temp1)
+                                      ppc::temp1))))
+                    (! misc-set-c-node val-reg ppc::temp0 (car r)))))))
+          (ppc2-undo-body seg vreg xfer body old-stack)
+          (dolist (var real-vars)
+            (ppc2-close-var seg var)))))))
+
+;;; Make a function call (e.g., to mapcar) with some of the toplevel arguments
+;;; stack-consed (downward) closures.  Bind temporaries to these closures so
+;;; that tail-recursion/non-local exits work right.
+;;; (all of the closures are distinct: FLET and LABELS establish dynamic extent themselves.)
+(defppc2 ppc2-with-downward-closures with-downward-closures (seg vreg xfer tempvars closures callform)
+  (let* ((old-stack (ppc2-encode-stack)))
+    (ppc2-seq-bind seg tempvars closures)
+    (ppc2-undo-body seg vreg xfer callform old-stack)
+    (dolist (v tempvars) (ppc2-close-var seg v))))
+
+
+(defppc2 ppc2-local-return-from local-return-from (seg vreg xfer blocktag value)
+  (declare (ignorable vreg xfer))
+  (let* ((*ppc2-undo-count* *ppc2-undo-count*)
+         (tagdata (car blocktag))
+         (cur-stack (ppc2-encode-stack))
+         (dest-vd (caar tagdata))
+         (dest-cd (cdar tagdata))
+         (mv-p (ppc2-mvpass-p dest-cd))
+         (dest-stack  (cdr tagdata))
+         (need-break (neq cur-stack dest-stack)))
+    (let* ((*ppc2-vstack* *ppc2-vstack*)
+           (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+           (*ppc2-cstack* *ppc2-cstack*))
+      (if 
+        (or
+         (eq dest-cd $backend-return)
+         (and mv-p 
+              (eq (ppc2-encoding-undo-count cur-stack)
+                  (ppc2-encoding-undo-count dest-stack)) 
+              (eq (ppc2-encoding-cstack-depth cur-stack)
+                  (ppc2-encoding-cstack-depth dest-stack))))
+        (ppc2-form seg dest-vd dest-cd value)
+        (if mv-p
+          (progn
+            (ppc2-multiple-value-body seg value)
+            (let* ((*ppc2-returning-values* :pass))
+              (ppc2-nlexit seg dest-cd (%i- *ppc2-undo-count* (ppc2-encoding-undo-count dest-stack)))
+              (ppc2-branch seg dest-cd vreg)))
+          (progn
+            (ppc2-form 
+             seg
+             (if need-break (if dest-vd ppc::arg_z) dest-vd) 
+             (if need-break nil dest-cd)
+             value)
+            (when need-break
+              (ppc2-unwind-set seg dest-cd dest-stack)
+              (when dest-vd (ppc2-copy-register seg dest-vd ppc::arg_z))
+              (ppc2-branch seg dest-cd dest-vd))))))
+    (ppc2-unreachable-store)))
+
+(defppc2 ppc2-inherited-arg inherited-arg (seg vreg xfer arg)
+  (when vreg
+    (ppc2-addrspec-to-reg seg (ppc2-ea-open (var-ea arg)) vreg))
+  (^))
+
+
+(defppc2 ppc2-%lisp-word-ref %lisp-word-ref (seg vreg xfer base offset)
+  (let* ((fixoffset (acode-fixnum-form-p offset)))
+    (cond ((null vreg)
+           (ppc2-form seg nil nil base)
+           (ppc2-form seg nil xfer offset))
+          ((target-arch-case
+            (:ppc32 (typep fixoffset '(signed-byte 14)))
+            (:ppc64 (typep fixoffset '(signed-byte 13))))
+           (ensuring-node-target (target vreg)
+             (! lisp-word-ref-c target 
+                (ppc2-one-untargeted-reg-form seg base ppc::arg_z) 
+                (ash fixoffset *ppc2-target-fixnum-shift*)))
+           (^))
+          (t (multiple-value-bind (breg oreg)
+                                  (ppc2-two-untargeted-reg-forms seg base ppc::arg_y offset ppc::arg_z)
+               (ensuring-node-target (target vreg)
+                 (! lisp-word-ref target breg oreg))
+               (^))))))
+
+(defppc2 ppc2-%fixnum-ref %fixnum-ref (seg vreg xfer base offset)
+  (let* ((fixoffset (acode-fixnum-form-p offset)))
+    (cond ((null vreg)
+           (ppc2-form seg nil nil base)
+           (ppc2-form seg nil xfer offset))
+          ((typep fixoffset '(signed-byte 16))
+           (ensuring-node-target (target vreg)
+             (! lisp-word-ref-c target 
+                (ppc2-one-untargeted-reg-form seg base ppc::arg_z) 
+                fixoffset))
+           (^))
+          (t (multiple-value-bind (breg oreg)
+                                  (ppc2-two-untargeted-reg-forms seg base ppc::arg_y offset ppc::arg_z)
+               (with-imm-target () (otemp :s32)
+                 (! fixnum->signed-natural otemp oreg)
+                 (ensuring-node-target (target vreg)
+                   (! lisp-word-ref target breg otemp)))
+               (^))))))
+
+(defppc2 ppc2-%fixnum-ref-natural %fixnum-ref-natural (seg vreg xfer base offset)
+  (let* ((fixoffset (acode-fixnum-form-p offset)))
+    (cond ((null vreg)
+           (ppc2-form seg nil nil base)
+           (ppc2-form seg nil xfer offset))
+          ((typep fixoffset '(signed-byte 16))
+           (with-imm-target () (val :natural)
+             (! lisp-word-ref-c val
+                (ppc2-one-untargeted-reg-form seg base ppc::arg_z) 
+                fixoffset)
+             (<- val))
+           (^))
+          (t (multiple-value-bind (breg oreg)
+		 (ppc2-two-untargeted-reg-forms seg base ppc::arg_y offset ppc::arg_z)
+               (with-imm-target () (otemp :s32)
+                 (! fixnum->signed-natural otemp oreg)
+                 (with-imm-target () (val :natural)
+                   (! lisp-word-ref val breg otemp)
+                   (<- val)))
+               (^))))))
+
+(defppc2 ppc2-int>0-p int>0-p (seg vreg xfer cc form)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+    (ppc2-one-targeted-reg-form seg form ($ ppc::arg_z))
+    (! integer-sign)
+    (ppc2-test-reg-%izerop seg vreg xfer ppc::imm0 cr-bit true-p 0)))
+
+
+(defppc2 ppc2-throw throw (seg vreg xfer tag valform )
+  (declare (ignorable vreg xfer))
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*))
+    (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg tag ppc::arg_z))
+    (if (ppc2-trivial-p valform)
+      (progn
+        (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg valform ppc::arg_z))
+        (ppc2-set-nargs seg 1))
+      (ppc2-multiple-value-body seg valform))
+    (! throw)))
+
+;;; This (and unwind-protect and things like that) are a little funky in that
+;;; they have no good way of specifying the exit-point.  The bad way is to
+;;; follow the call to the catch-frame-creating subprim with a branch to that
+;;; exit-point; the subprim returns to the following instruction.
+;;; If the compiler ever gets smart about eliminating dead code, it has to
+;;; be careful not to consider the block following the jump to be dead.
+;;; Use a vinsn other than JUMP to reference the label.
+(defppc2 ppc2-catch catch (seg vreg xfer tag valform)
+  (let* ((tag-label (backend-get-next-label))
+         (mv-pass (ppc2-mv-p xfer)))
+    (ppc2-one-targeted-reg-form seg tag ($ ppc::arg_z))
+    (if mv-pass
+      (! mkcatchmv)
+      (! mkcatch1v))
+    (! non-barrier-jump (aref *backend-labels* tag-label))
+    (ppc2-open-undo)
+    (if mv-pass
+      (ppc2-multiple-value-body seg valform)  
+      (ppc2-one-targeted-reg-form seg valform ($ ppc::arg_z)))
+    (ppc2-lri seg ppc::imm0 (ash 1 *ppc2-target-fixnum-shift*))
+    (if mv-pass
+      (! nthrowvalues)
+      (! nthrow1value))
+    (ppc2-close-undo)
+    (@ tag-label)
+    (unless mv-pass (if vreg (<- ppc::arg_z)))
+    (let* ((*ppc2-returning-values* mv-pass)) ; nlexit keeps values on stack
+      (^))))
+
+
+(defppc2 ppc2-fixnum-overflow fixnum-overflow (seg vreg xfer form)
+  (destructuring-bind (op n0 n1) (acode-unwrapped-form form)
+    (ppc2-use-operator op seg vreg xfer n0 n1 *nx-t*)))
+
+
+
+(defppc2 ppc2-%aref2 simple-typed-aref2 (seg vreg xfer typename arr i j &optional dim0 dim1)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil arr)
+      (ppc2-form seg nil nil i)
+      (ppc2-form seg nil xfer j))
+    (let* ((type-keyword (acode-immediate-operand typename))
+           (fixtype (nx-lookup-target-uvector-subtag type-keyword ))
+           (safe (unless *ppc2-reckless* fixtype))
+           (dim0 (acode-fixnum-form-p dim0))
+           (dim1 (acode-fixnum-form-p dim1)))
+      (ppc2-aref2 seg vreg xfer arr i j safe type-keyword dim0 dim1))))
+
+
+(defppc2 ppc2-general-aref2 general-aref2 (seg vreg xfer arr i j)
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+	 (keyword (and atype
+		       (or (eq dims '*)
+			   (and (typep dims 'list)
+				(= 2 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims)))
+             (ppc2-aref2 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         (if *ppc2-reckless*
+                           *nx-nil*
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword        ;(make-acode (%nx1-operator immediate) )
+                         (if (typep dim0 'fixnum) dim0) (if (typep dim1 'fixnum) dim1))))
+          (t
+           (ppc2-three-targeted-reg-forms seg
+                                          arr ($ ppc::arg_x)
+                                          i ($ ppc::arg_y)
+                                          j ($ ppc::arg_z))
+           (ppc2-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SParef2)))))  )
+
+
+(defppc2 ppc2-%aref3 simple-typed-aref3 (seg vreg xfer typename arr i j k &optional dim0 dim1 dim2)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil arr)
+      (ppc2-form seg nil nil i)
+      (ppc2-form seg nil nil j)
+      (ppc2-form seg nil xfer k)))
+  (let* ((type-keyword (acode-immediate-operand typename))
+         (fixtype (nx-lookup-target-uvector-subtag type-keyword ))
+         (safe (unless *ppc2-reckless* fixtype))
+         (dim0 (acode-fixnum-form-p dim0))
+         (dim1 (acode-fixnum-form-p dim1))
+         (dim2 (acode-fixnum-form-p dim2)))
+    (ppc2-aref3 seg vreg xfer arr i j k safe type-keyword dim0 dim1 dim2)))
+
+(defppc2 ppc2-general-aref3 general-aref3 (seg vreg xfer arr i j k)
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+         (keyword (and atype
+		       (or (eq dims '*)
+			   (and (typep dims 'list)
+				(= 3 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims))
+                  (dim2 (caddr dims)))
+             (ppc2-aref3 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         k
+                         (if *ppc2-reckless*
+                           *nx-nil*
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword ;(make-acode (%nx1-operator immediate) )
+                         (if (typep dim0 'fixnum) dim0)
+                         (if (typep dim1 'fixnum) dim1)
+                         (if (typep dim2 'fixnum) dim2))))
+          (t
+           (ppc2-four-targeted-reg-forms seg
+                                         arr ($ ppc::temp0)
+                                         i ($ ppc::arg_x)
+                                         j ($ ppc::arg_y)
+                                         k ($ ppc::arg_z))
+           (ppc2-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SParef3))))))
+
+(defppc2 ppc2-%aset2 simple-typed-aset2 (seg vreg xfer typename arr i j new &optional dim0 dim1)
+  (let* ((type-keyword (acode-immediate-operand typename))
+         (fixtype (nx-lookup-target-uvector-subtag type-keyword ))
+         (safe (unless *ppc2-reckless* fixtype))
+         (dim0 (acode-fixnum-form-p dim0))
+         (dim1 (acode-fixnum-form-p dim1)))
+    (ppc2-aset2 seg vreg xfer arr i j new safe type-keyword dim0 dim1))
+)
+
+(defppc2 ppc2-general-aset2 general-aset2 (seg vreg xfer arr i j new)
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+         (keyword (and atype
+		       (or (eq dims '*)
+			   (and (typep dims 'list)
+				(= 2 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims)))
+             (ppc2-aset2 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         new
+                         (unless *ppc2-reckless*
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword
+                         (if (typep dim0 'fixnum) dim0)
+                         (if (typep dim1 'fixnum) dim1))))
+          (t
+           (ppc2-four-targeted-reg-forms seg
+                                         arr ($ ppc::temp0)
+                                         i ($ ppc::arg_x)
+                                         j ($ ppc::arg_y)
+                                         new ($ ppc::arg_z))
+           (ppc2-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SPaset2))))))
+
+
+(defppc2 ppc2-general-aset3 general-aset3 (seg vreg xfer arr i j k new)
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+         (keyword (and atype
+		       (or (eq dims '*)
+			   (unless (atom dims)
+			     (= 3 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims))
+                  (dim2 (caddr dims)))
+             (ppc2-aset3 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         k
+                         new
+                         (unless *ppc2-reckless*
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword
+                         (if (typep dim0 'fixnum) dim0)
+                         (if (typep dim1 'fixnum) dim1)
+                         (if (typep dim2 'fixnum) dim2))))
+          (t
+           (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg arr ($ ppc::arg_z)))
+           (ppc2-four-targeted-reg-forms seg
+                                         i ($ ppc::temp0)
+                                         j ($ ppc::arg_x)
+                                         k ($ ppc::arg_y)
+                                         new ($ ppc::arg_z))
+           (ppc2-pop-register seg ($ ppc::temp1))
+           (ppc2-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SPaset3))))))
+
+(defppc2 ppc2-%aset3 simple-typed-aset3 (seg vreg xfer typename arr i j k new &optional dim0 dim1 dim2)
+  (let* ((type-keyword (acode-immediate-operand typename))
+         (fixtype (nx-lookup-target-uvector-subtag type-keyword))
+         (safe (unless *ppc2-reckless* fixtype))
+         (dim0 (acode-fixnum-form-p dim0))
+         (dim1 (acode-fixnum-form-p dim1))
+         (dim2 (acode-fixnum-form-p dim2)))
+    (ppc2-aset3 seg vreg xfer arr i j k new safe type-keyword dim0 dim1 dim2)))
+
+
+
+(defppc2 ppc2-%typed-uvref %typed-uvref (seg vreg xfer subtag uvector index)
+  (let* ((type-keyword
+          (let* ((fixtype (acode-fixnum-form-p subtag)))
+            (if fixtype
+              (nx-target-uvector-subtag-name fixtype)
+              (acode-immediate-operand subtag)))))
+    (if type-keyword
+      (ppc2-vref seg vreg xfer type-keyword uvector index (unless *ppc2-reckless* (nx-lookup-target-uvector-subtag type-keyword)))
+      (progn
+        (ppc2-three-targeted-reg-forms seg subtag ($ ppc::arg_x) uvector ($ ppc::arg_y) index ($ ppc::arg_z))
+        (! subtag-misc-ref)
+        (when vreg (<- ($ ppc::arg_z)))
+        (^)) )))
+
+(defppc2 ppc2-%typed-uvset %typed-uvset (seg vreg xfer subtag uvector index newval)
+  (let* ((type-keyword
+          (let* ((fixtype (acode-fixnum-form-p subtag)))
+            (if fixtype
+              (nx-target-uvector-subtag-name fixtype)
+              (acode-immediate-operand subtag)))))
+    (if type-keyword
+      (ppc2-vset seg vreg xfer type-keyword uvector index newval (unless *ppc2-reckless* (nx-lookup-target-uvector-subtag type-keyword)))
+      (progn
+        (ppc2-four-targeted-reg-forms seg
+                                      subtag ($ ppc::temp0)
+                                      uvector ($ ppc::arg_x)
+                                      index ($ ppc::arg_y)
+                                      newval ($ ppc::arg_z))
+
+        (! subtag-misc-set)
+        (when vreg (<- ($ ppc::arg_z)))
+        (^)))))
+
+(defppc2 ppc2-%macptrptr% %macptrptr% (seg vreg xfer form)
+  (with-imm-target () (target :address)
+    (ppc2-one-targeted-reg-form seg form (or vreg target)))
+  (^))
+           
+
+;;; cons a macptr, unless "vreg" is an immediate register of mode :address.
+(defppc2 ppc2-%consmacptr% %consmacptr% (seg vreg xfer form)
+  (cond ((null vreg) (ppc2-form seg nil xfer form))
+        ((eql (get-regspec-mode vreg) hard-reg-class-gpr-mode-address)
+         (ppc2-form seg vreg xfer form))
+        (t         
+         (with-imm-target () (temp :address)
+           (<- (ppc2-one-targeted-reg-form seg form temp))
+           (^)))))
+
+(defppc2 ppc2-%immediate-ptr-to-int %immediate-ptr-to-int (seg vreg xfer form)
+  (if (null vreg)
+    (ppc2-form seg nil xfer form)
+    (with-imm-target () (address-reg :address)
+      (ppc2-form seg address-reg nil form)
+      (<- (set-regspec-mode address-reg (gpr-mode-name-value :natural)))
+      (^))))
+
+(defppc2 ppc2-%immediate-int-to-ptr %immediate-int-to-ptr (seg vreg xfer form)
+  (if (null vreg)
+    (ppc2-form seg nil xfer form)
+    (progn
+      (unless (logbitp (hard-regspec-value vreg) ppc-imm-regs)
+        (compiler-bug "I give up.  When will I get this right ?"))
+      (let* ((natural-reg (ppc2-one-targeted-reg-form seg 
+                                                      form
+                                                      ($ vreg :mode :natural))))
+        (<- natural-reg)
+        (^)))))
+
+
+(defppc2 ppc2-%function %function (seg vreg xfer sym)
+  (when vreg
+    (let* ((symreg (ppc2-one-untargeted-reg-form seg (make-acode (%nx1-operator immediate)
+                                                                 (ppc2-symbol-entry-locative sym)) ppc::arg_z)))
+      (with-node-temps (vreg symreg) (val)
+        (! symbol-function val symreg)
+        (<- val))))
+  (^))
+
+(defppc2 ppc2-%unbound-marker %unbound-marker (seg vreg xfer)
+  (when vreg       
+    (ensuring-node-target (target vreg)
+      (ppc2-lri seg target (target-arch-case
+                            (:ppc32 ppc32::unbound-marker)
+                            (:ppc64 ppc64::unbound-marker)))))
+  (^))
+
+(defppc2 ppc2-slot-unbound-marker %slot-unbound-marker (seg vreg xfer)
+  (when vreg    
+    (ensuring-node-target (target vreg)
+      (ppc2-lri seg target (target-arch-case
+                            (:ppc32 ppc32::slot-unbound-marker)
+                            (:ppc64 ppc64::slot-unbound-marker)))))
+  (^))
+
+(defppc2 ppc2-illegal-marker %illegal-marker (seg vreg xfer)
+  (when vreg    
+    (ensuring-node-target (target vreg)
+      (ppc2-lri seg target (target-arch-case
+                            (:ppc32 ppc32::illegal-marker)
+                            (:ppc64 ppc64::illegal-marker)))))
+  (^))
+
+(defppc2 ppc2-lambda-bind lambda-bind (seg vreg xfer vals req rest keys-p auxen body p2decls)
+  (let* ((old-stack (ppc2-encode-stack))
+         (nreq (list-length req))
+         (rest-arg (nthcdr nreq vals))
+         (apply-body (ppc2-eliminate-&rest body rest keys-p auxen rest-arg)))
+    (ppc2-seq-bind seg req vals)
+    (when apply-body (setq rest nil body apply-body))
+    (let*
+      ((vloc *ppc2-vstack*)
+       (restloc vloc)
+       (nvloc (progn (if (or rest keys-p) (ppc2-formlist seg rest-arg)) *ppc2-vstack*)))
+      (with-ppc-p2-declarations p2decls
+        (when rest
+          (when keys-p
+            (until (eq restloc nvloc)
+              (with-node-temps () (temp)
+                (ppc2-stack-to-register seg (ppc2-vloc-ea restloc) temp)
+                (ppc2-vpush-register seg temp))
+              (setq restloc (%i+ restloc *ppc2-target-node-size*))))
+          (ppc2-set-nargs seg (length rest-arg))
+          (ppc2-set-vstack restloc)
+          (if (%ilogbitp $vbitdynamicextent (nx-var-bits rest))
+            (progn
+              (! stack-cons-list)
+              (ppc2-open-undo $undostkblk))
+            (! list))
+          (ppc2-vpush-register seg ppc::arg_z))
+        (when rest (ppc2-bind-var seg rest restloc))
+        (destructuring-bind (vars inits) auxen
+          (while vars
+            (let ((val (%car inits))) 
+              (if (fixnump val)
+                (progn
+                  (when rest (setq val (%i+ (%i+ val val) 1)))
+                  (ppc2-bind-var seg (%car vars) (%i+ vloc (* val *ppc2-target-node-size*))))
+                (ppc2-seq-bind-var seg (%car vars) val)))
+            (setq vars (%cdr vars) inits (%cdr inits))))
+        (ppc2-undo-body seg vreg xfer body old-stack)
+        (dolist (var req) (ppc2-close-var seg var))
+        (when rest (ppc2-close-var seg rest))
+        (dolist (var (%car auxen)) (ppc2-close-var seg var))))))
+
+(macrolet 
+  ((def-ppc2-require (function op &optional (vinsn op))
+     `(defppc2 ,function ,op (seg vreg xfer val)
+        (let* ((val-reg (ppc2-one-untargeted-reg-form 
+                         seg 
+                         val 
+                         (if (eq vreg ppc::arg_z) ppc::arg_y ppc::arg_z))))
+          (! ,vinsn val-reg)
+          (when vreg (<- val-reg))
+          (^)))))
+  (def-ppc2-require ppc2-require-simple-vector require-simple-vector)
+  (def-ppc2-require ppc2-require-simple-string require-simple-string)
+  (def-ppc2-require ppc2-require-integer require-integer)
+  (def-ppc2-require ppc2-require-fixnum require-fixnum)
+  (def-ppc2-require ppc2-require-real require-real)
+  (def-ppc2-require ppc2-require-list require-list)
+  (def-ppc2-require ppc2-require-character require-character)
+  (def-ppc2-require ppc2-require-number require-number)
+  (def-ppc2-require ppc2-require-symbol require-symbol)
+  (def-ppc2-require ppc2-require-s8 require-s8)
+  (def-ppc2-require ppc2-require-s8 require-u8)
+  (def-ppc2-require ppc2-require-s8 require-s16)
+  (def-ppc2-require ppc2-require-s8 require-u16)
+  (def-ppc2-require ppc2-require-s8 require-s32)
+  (def-ppc2-require ppc2-require-s8 require-u32)
+  (def-ppc2-require ppc2-require-s8 require-s64)
+  (def-ppc2-require ppc2-require-s8 require-u64))
+
+(defun ppc2-typechecked-form (seg vreg xfer typespec form)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (let* ((op
+            (cond ((eq typespec 'fixnum) (%nx1-operator require-fixnum))
+                  ((eq typespec 'integer) (%nx1-operator require-integer))
+                  ((memq typespec '(base-char character))
+                   (%nx1-operator require-character))
+                  ((eq typespec 'symbol) (%nx1-operator require-symbol))
+                  ((eq typespec 'list) (%nx1-operator require-list))
+                  ((eq typespec 'real) (%nx1-operator require-real))
+                  ((memq typespec '(simple-base-string simple-string))
+                   (%nx1-operator require-simple-string))
+                  ((eq typespec 'number) (%nx1-operator require-number))
+                  ((eq typespec 'simple-vector) (%nx1-operator require-simple-vector))
+                  (t
+                   (let* ((ctype (specifier-type typespec)))
+                     (cond ((type= ctype (load-time-value (specifier-type '(signed-byte 8))))
+                            (%nx1-operator require-s8))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 8))))
+                            (%nx1-operator require-u8))
+                           ((type= ctype (load-time-value (specifier-type '(signed-byte 16))))
+                            (%nx1-operator require-s16))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 16))))
+                            (%nx1-operator require-u16))
+                           ((type= ctype (load-time-value (specifier-type '(signed-byte 32))))                            
+                            (%nx1-operator require-s32))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 32))))
+                            (%nx1-operator require-u32))
+                           ((type= ctype (load-time-value (specifier-type '(signed-byte 64))))
+                            (%nx1-operator require-s64))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 64))))
+                            (%nx1-operator require-u64))))))))
+      (if op
+        (ppc2-use-operator op seg vreg xfer form)
+        (if (or (eq typespec t)
+                (eq typespec '*))
+          (ppc2-form seg vreg xfer form)
+          (let* ((ok (backend-get-next-label)))
+            (ppc2-one-targeted-reg-form seg form ($ ppc::arg_y))
+            (ppc2-store-immediate seg typespec ($ ppc::arg_z))
+            (ppc2-store-immediate seg 'typep ($ ppc::fname))
+            (ppc2-set-nargs seg 2)
+            (ppc2-vpush-register seg ($ ppc::arg_y))
+            (! call-known-symbol ($ ppc::arg_z))
+	    (with-crf-target () crf
+               (! compare-to-nil crf ($ ppc::arg_z))
+	       (ppc2-vpop-register seg ($ ppc::arg_y))
+	       (! cbranch-false (aref *backend-labels* ok) crf ppc::ppc-eq-bit))
+            (ppc2-lri seg ($ ppc::arg_x) (ash $XWRONGTYPE *ppc2-target-fixnum-shift*))
+            (ppc2-store-immediate seg typespec ($ ppc::arg_z))
+            (ppc2-set-nargs seg 3)
+            (! ksignalerr)
+            (@ ok)
+            (<- ($ ppc::arg_y))
+            (^)))))))
+
+(defppc2 ppc2-%badarg2 %badarg2 (seg vreg xfer badthing goodthing)
+  (ppc2-two-targeted-reg-forms seg badthing ($ ppc::arg_y) goodthing ($ ppc::arg_z))
+  (ppc2-lri seg ($ ppc::arg_x) (ash $XWRONGTYPE *ppc2-target-fixnum-shift*))
+  (ppc2-set-nargs seg 3)
+  (! ksignalerr)
+  (<- nil)
+  (^))  
+          
+(defppc2 ppc2-%set-sbchar %set-sbchar (seg vreg xfer string index value)
+  (ppc2-vset 
+   seg 
+   vreg 
+   xfer 
+   :simple-string 
+   string 
+   index
+   value 
+   (unless *ppc2-reckless* (nx-lookup-target-uvector-subtag :simple-string))))
+
+
+;;; If we didn't use this for stack consing, turn it into a call.  Ugh.
+
+(defppc2 ppc2-make-list make-list (seg vreg xfer size initial-element)
+  (ppc2-form seg vreg xfer (make-acode (%nx1-operator call)
+                                       (make-acode (%nx1-operator immediate) 'make-list)
+                                       (list nil
+                                             (list initial-element 
+                                                   (make-acode (%nx1-operator immediate)
+                                                               :initial-element)
+                                                   size)))))
+
+
+(defppc2 ppc2-setq-free setq-free (seg vreg xfer sym val)
+  (let* ((rsym ($ ppc::arg_y))
+         (rval ($ ppc::arg_z)))
+    (ppc2-one-targeted-reg-form seg val rval)
+    (ppc2-immediate seg rsym nil (ppc2-symbol-value-cell sym))
+    (! setqsym)
+    (<- rval)
+    (^)))
+
+(defppc2 ppc2-%setf-macptr %setf-macptr (seg vreg xfer x y)
+  (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg x ppc::arg_z))
+  (with-imm-target () (src-reg :address)
+    (ppc2-one-targeted-reg-form seg y src-reg)
+    (ppc2-vpop-register seg ppc::arg_z)
+    (unless (or *ppc2-reckless* (ppc2-form-typep x 'macptr))
+      (with-imm-temps (src-reg) ()
+        (! trap-unless-macptr ppc::arg_z)))
+    (! set-macptr-address src-reg ppc::arg_z)
+    (<- ppc::arg_z)
+    (^)))
+
+(defppc2 ppc2-%setf-double-float %setf-double-float (seg vref xfer fnode fval)
+  (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg fnode ppc::arg_z))
+  (let* ((target ($ ppc::fp1 :class :fpr :mode :double-float))
+         (node ($ ppc::arg_z)))
+    (ppc2-one-targeted-reg-form seg fval target)
+    (ppc2-vpop-register seg node)
+    (unless (or *ppc2-reckless* (ppc2-form-typep fnode 'double-float))
+      (! trap-unless-double-float node))
+    (! store-double node target)
+    (<- node)
+    (^)))
+
+(defppc2 ppc2-%setf-short-float %setf-short-float (seg vreg xfer fnode fval)
+  (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg fnode ppc::arg_z))
+  (let* ((target ($ ppc::fp1 :class :fpr :mode :single-float))
+         (freg ($ ppc::arg_z)))
+    (ppc2-one-targeted-reg-form seg fval target)
+    (ppc2-vpop-register seg freg)
+    (unless (or *ppc2-reckless* (ppc2-form-typep fnode 'short-float))
+      (! trap-unless-single-float freg))
+    (! store-single freg target)
+    (<- freg)
+    (^)))
+
+    
+
+(defppc2 ppc2-unwind-protect unwind-protect (seg vreg xfer protected-form cleanup-form)
+  (let* ((cleanup-label (backend-get-next-label))
+         (protform-label (backend-get-next-label))
+         (old-stack (ppc2-encode-stack))
+         (ilevel '*interrupt-level*))
+    (! nmkunwind)
+    (ppc2-open-undo $undointerruptlevel)
+    (ppc2-new-vstack-lcell :special-value *ppc2-target-lcell-size* 0 ilevel)
+    (ppc2-new-vstack-lcell :special *ppc2-target-lcell-size* (ash 1 $vbitspecial) ilevel)
+    (ppc2-new-vstack-lcell :special-link *ppc2-target-lcell-size* 0 ilevel)
+    (ppc2-adjust-vstack (* 3 *ppc2-target-node-size*))    
+    (! non-barrier-jump (aref *backend-labels* cleanup-label))
+    (-> protform-label)
+    (@ cleanup-label)
+    (let* ((*ppc2-vstack* *ppc2-vstack*)
+           (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+           (*ppc2-cstack* (%i+ *ppc2-cstack* (target-arch-case
+                                              (:ppc32 ppc32::lisp-frame.size)
+                                              (:ppc64 ppc64::lisp-frame.size)))))
+      (ppc2-open-undo $undostkblk)      ; tsp frame created by nthrow.
+      (! save-cleanup-context)
+      (setq *ppc2-cstack* (%i+ *ppc2-cstack*
+                               (target-arch-case
+                                (:ppc32 ppc32::lisp-frame.size)
+                                (:ppc64 ppc64::lisp-frame.size))))       ; the frame we just pushed
+      (ppc2-form seg nil nil cleanup-form)
+      (ppc2-close-undo)
+      (! restore-cleanup-context)
+      (! jump-return-pc)) ; blr
+    (ppc2-open-undo)
+    (@ protform-label)
+    (ppc2-new-vstack-lcell :special-value *ppc2-target-lcell-size* 0 ilevel)
+    (ppc2-new-vstack-lcell :special *ppc2-target-lcell-size* (ash 1 $vbitspecial) ilevel)
+    (ppc2-new-vstack-lcell :special-link *ppc2-target-lcell-size* 0 ilevel)
+    (ppc2-adjust-vstack (* 3 *ppc2-target-node-size*))
+
+    (ppc2-undo-body seg vreg xfer protected-form old-stack)))
+
+(defppc2 ppc2-progv progv (seg vreg xfer symbols values body)
+  (let* ((cleanup-label (backend-get-next-label))
+         (protform-label (backend-get-next-label))
+         (old-stack (ppc2-encode-stack)))
+    (ppc2-two-targeted-reg-forms seg symbols ($ ppc::arg_y) values ($ ppc::arg_z))
+    (! progvsave)
+    (ppc2-open-undo $undostkblk)
+    (! mkunwind)
+    (! non-barrier-jump (aref *backend-labels* cleanup-label))
+    (-> protform-label)
+    (@ cleanup-label)
+    (! progvrestore)
+    (ppc2-open-undo)
+    (@ protform-label)
+    (ppc2-undo-body seg vreg xfer body old-stack)))
+
+(defppc2 ppc2-%ptr-eql %ptr-eql (seg vreg xfer cc x y )
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil x)
+      (ppc2-form seg nil xfer y))
+    (let* ((x-abs (acode-absolute-ptr-p x t))
+           (y-abs (acode-absolute-ptr-p y t))
+           (abs (or x-abs y-abs))
+           (other (if abs (if x-abs y x))))
+      (multiple-value-bind (cr-bit true-p) (acode-condition-to-ppc-cr-bit cc)
+        (if other
+          (with-imm-target () (other-target :address)
+            (ppc2-one-targeted-reg-form seg other other-target)
+            (if (typep abs '(signed-byte 16))              
+              (ppc2-test-reg-%izerop seg vreg xfer other-target cr-bit true-p abs)
+              (with-imm-temps (other-target) ((abs-target :address))
+                (use-imm-temp other-target)
+                (ppc2-lri seg abs-target abs)
+                (ppc2-compare-registers seg vreg xfer other-target abs-target cr-bit true-p))))
+          ; Neither expression is obviously a constant-valued macptr.
+          (with-imm-target () (target-a :address)
+            (ppc2-one-targeted-reg-form seg x target-a)
+            (! temp-push-unboxed-word target-a)
+            (ppc2-open-undo $undostkblk)
+            (ppc2-one-targeted-reg-form seg y target-a)
+            (with-imm-target (target-a) (target-b :address)
+              (! temp-pop-unboxed-word target-b)
+              (ppc2-close-undo)
+              (ppc2-compare-registers seg vreg xfer target-b target-a cr-bit true-p))))))))
+
+(defppc2 ppc2-set-bit %set-bit (seg vreg xfer ptr offset newval)
+  (let* ((offval (acode-fixnum-form-p offset))
+         (byte-index (if offval (ash offval -3)))
+         (bit-index (if (and byte-index (< byte-index #x8000))
+                      (logand offval #x7)))
+         (triv-offset (ppc2-trivial-p offset))
+         (triv-val (ppc2-trivial-p newval)))
+    (with-imm-target ()
+      (src :address)
+      (ppc2-one-targeted-reg-form seg ptr src)
+      (if bit-index
+        (let* ((mask-start (logand 31 (+ bit-index 25)))
+               (mask-end (logand 31 (+ bit-index 23)))
+               (mask (ash #x80 (- bit-index)))
+               (constval (acode-fixnum-form-p newval)))
+          (if constval
+            (progn
+              (if (eql constval 0)
+                (! mem-set-c-bit-0 src byte-index mask-start mask-end)
+                (! mem-set-c-bit-1 src byte-index mask))
+              (when vreg
+                (ppc2-form seg vreg nil newval)))
+            (progn
+              (unless triv-val
+                (! temp-push-unboxed-word src)
+                (ppc2-open-undo $undostkblk))
+              (let* ((target (ppc2-one-untargeted-reg-form seg newval ppc::arg_z)))
+                (unless triv-val
+                  (! temp-pop-unboxed-word src)
+                  (ppc2-close-undo))
+                (! mem-set-c-bit src byte-index (+ 24 bit-index) target)
+                (<- target)))))
+        (progn
+          (unless (and triv-val triv-offset)
+            (! temp-push-unboxed-word src)
+            (ppc2-open-undo $undostkblk))
+          (multiple-value-bind (idx-reg val-reg)
+              (ppc2-two-untargeted-reg-forms seg offset ppc::arg_y newval ppc::arg_z)
+            (unless (and triv-val triv-offset)
+              (! temp-pop-unboxed-word src)
+              (ppc2-close-undo ))
+            (! mem-set-bit src idx-reg val-reg)
+            (<- val-reg)))))
+    (^)))
+
+(defppc2 ppc2-%immediate-set-xxx %immediate-set-xxx (seg vreg xfer bits ptr offset val)
+  (ppc2-%immediate-store seg vreg xfer bits ptr offset val))
+
+
+
+(defppc2 ppc2-%immediate-inc-ptr %immediate-inc-ptr (seg vreg xfer ptr by)
+  (let* ((triv-by (ppc2-trivial-p by))
+         (fixnum-by (acode-fixnum-form-p by)))
+    (if (and fixnum-by (eql 0 fixnum-by))
+      (ppc2-form seg vreg xfer ptr)
+      (with-imm-target (vreg) (ptr-reg :address)
+        (ppc2-one-targeted-reg-form seg ptr ptr-reg)
+        (if fixnum-by
+          (with-imm-target (vreg ptr-reg) (result :address)
+            (let* ((high (ldb (byte 16 16) fixnum-by))
+                   (low (ldb (byte 16 0) fixnum-by)))
+              (declare (type (unsigned-byte 16) high low))
+              (if (logbitp 15 low) (incf high))
+              (! add-immediate result ptr-reg high low)
+              (<- result)))
+          (progn
+            (unless triv-by
+              (! temp-push-unboxed-word ptr-reg)
+              (ppc2-open-undo $undostkblk))
+            (with-imm-target (vreg ptr-reg) (by-reg :s32)
+              (ppc2-one-targeted-reg-form seg by by-reg)
+              (unless triv-by
+                (! temp-pop-unboxed-word ptr-reg)
+                (ppc2-close-undo))
+              (with-imm-target (vreg ptr-reg by-reg) (result :address)
+                (! fixnum-add result ptr-reg by-reg)
+                (<- result)))))
+        (^)))))
+
+
+
+(defppc2 ppc2-multiple-value-call multiple-value-call (seg vreg xfer fn arglist)
+  (ppc2-mvcall seg vreg xfer fn arglist))
+
+
+
+(defppc2 ppc2-eabi-syscall eabi-syscall (seg vreg xfer idx argspecs argvals resultspec &optional monitor-exception-ports)
+  (declare (ignore monitor-exception-ports))
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+         (*ppc2-cstack* *ppc2-cstack*)
+         (nextarg 0))
+    (declare (fixnum nextarg))
+    (! alloc-eabi-c-frame (the fixnum (length argvals)))
+    (ppc2-open-undo $undo-ppc-c-frame)
+    ;; Evaluate each form into the C frame, according to the matching argspec.
+    (do* ((specs argspecs (cdr specs))
+          (vals argvals (cdr vals)))
+         ((null specs))
+      (declare (list specs vals))
+      (let* ((valform (car vals))
+             (spec (car specs))
+             (absptr (acode-absolute-ptr-p valform)))
+        (case spec
+          (:address
+           (with-imm-target ()
+             (ptr :address)
+             (if absptr
+               (ppc2-lri seg ptr absptr)
+               (ppc2-one-targeted-reg-form seg valform ptr))
+             (! set-eabi-c-arg ptr nextarg)))
+          (t
+           (! set-eabi-c-arg
+              (with-imm-target ()
+                (valreg :natural)
+                (ppc2-unboxed-integer-arg-to-reg seg valform valreg spec))
+              nextarg)))
+        (incf nextarg)))
+    (ppc2-form seg ppc::arg_z nil idx)
+    (! eabi-syscall) 
+    (ppc2-close-undo)
+    (when vreg
+      (if (eq resultspec :void)
+        (<- nil)
+        (<- (set-regspec-mode ppc::imm0 (gpr-mode-name-value
+                                         (case resultspec
+                                           (:address :address)
+                                           (:signed-byte :s8)
+                                           (:unsigned-byte :u8)
+                                           (:signed-halfword :s16)
+                                           (:unsigned-halfword :u16)
+                                           (:signed-fullword :s32)
+                                           (t :u32)))))))
+    (^)))
+
+
+;;; Caller has allocated poweropen stack frame.
+(defun ppc2-poweropen-foreign-args (seg argspecs argvals)
+  (with-ppc-local-vinsn-macros (seg)
+    (let* ((fp-loads ())
+           (nextarg 0)
+           (return-registers nil))
+      ;; Evaluate each form into the C frame, according to the matching
+      ;; argspec.  Remember type and arg offset of any FP args, since FP
+      ;; regs will have to be loaded later.
+      (do* ((specs argspecs (cdr specs))
+            (vals argvals (cdr vals)))
+           ((null specs) (if return-registers (ppc2-pop-register seg ($ ppc::arg_y))))
+        (declare (list specs vals))
+        (let* ((valform (car vals))
+               (spec (car specs))
+               (absptr (acode-absolute-ptr-p valform)))
+          (case spec
+            (:registers
+             (setq return-registers t)
+             (ppc2-push-register seg (ppc2-one-untargeted-reg-form seg valform ppc::arg_z)))
+            ((:signed-doubleword :unsigned-doubleword :hybrid-int-float :hybrid-float-float :hybrid-float-int)
+                                 
+             (ppc2-one-targeted-reg-form seg valform ($ ppc::arg_z))
+             (if (eq spec :signed-doubleword)
+               (! gets64)
+               (! getu64))
+             (! set-c-arg ($ ppc::imm0) nextarg)
+             (target-arch-case
+              (:ppc32
+               (incf nextarg)
+               (! set-c-arg ($ ppc::imm1) nextarg))
+              (:ppc64
+               (case spec
+                 (:hybrid-int-float (push (cons :single-float nextarg) fp-loads))
+                 (:hybrid-float-int (push (cons :single-float-high nextarg) fp-loads))
+                 (:hybrid-float-float
+                  (push (cons :single-float-high nextarg) fp-loads)
+                  (push (cons :single-float nextarg) fp-loads))))))
+            (:double-float
+             (let* ((df ($ ppc::fp1 :class :fpr :mode :double-float)))
+               (ppc2-one-targeted-reg-form seg valform df)
+               (! set-double-c-arg df nextarg)            
+               (push (cons :double-float nextarg) fp-loads)
+               (target-word-size-case
+                (32 (incf nextarg))
+                (64))))
+            (:single-float
+             (let* ((sf ($ ppc::fp1 :class :fpr :mode :single-float)))
+               (ppc2-one-targeted-reg-form seg valform sf)
+               (! set-single-c-arg sf nextarg)
+               (push (cons :single-float nextarg) fp-loads)))
+            (:address
+             (with-imm-target ()
+                 (ptr :address)
+               (if absptr
+                 (ppc2-lri seg ptr absptr)
+                 (ppc2-one-targeted-reg-form seg valform ptr))
+               (! set-c-arg ptr nextarg)))
+            (t
+             (if (typep spec 'unsigned-byte)
+               (progn
+                 (with-imm-target () (ptr :address)
+                   (ppc2-one-targeted-reg-form seg valform ptr)
+                   (with-imm-temps (ptr) (r)
+                     (dotimes (i spec)
+                       (target-arch-case
+                        (:ppc32
+                         (! mem-ref-c-fullword r ptr (ash i ppc32::word-shift)))
+                        (:ppc64
+                         (! mem-ref-c-doubleword r ptr (ash i ppc64::word-shift))))
+                       (! set-c-arg r nextarg)
+                       (incf nextarg))))
+                 (decf nextarg))
+               (with-imm-target ()
+                   (valreg :natural)
+                 (let* ((reg valreg))
+                   (setq reg (ppc2-unboxed-integer-arg-to-reg seg valform valreg spec))
+                   (! set-c-arg reg nextarg))))))
+          (unless (eq spec :registers)(incf nextarg))))
+      (do* ((fpreg ppc::fp1 (1+ fpreg))
+            (reloads (nreverse fp-loads) (cdr reloads)))
+           ((or (null reloads) (= fpreg ppc::fp14)))
+        (declare (list reloads) (fixnum fpreg))
+        (let* ((reload (car reloads))
+               (size (car reload))
+               (from (cdr reload)))
+          (if (eq size :double-float)
+            (! reload-double-c-arg fpreg from)
+            (if (eq size :single-float-high)
+              (! reload-single-c-arg-high fpreg from)
+              (! reload-single-c-arg fpreg from)))))
+      return-registers)))
+
+(defun ppc2-poweropen-foreign-return (seg vreg xfer resultspec)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (cond ((eq resultspec :void) (<- nil))
+            ((eq resultspec :double-float)
+             (<- ($ ppc::fp1 :class :fpr :mode :double-float)))
+            ((eq resultspec :single-float)
+             (<- ($ ppc::fp1 :class :fpr :mode :single-float)))
+            ((eq resultspec :unsigned-doubleword)
+             (ensuring-node-target
+              (target vreg)
+              (! makeu64)
+              (ppc2-copy-register seg target ppc::arg_z)))
+            ((eq resultspec :signed-doubleword)
+             (ensuring-node-target
+              (target vreg)
+              (! makes64)
+              (ppc2-copy-register seg target ppc::arg_z)))
+            (t
+             (<- (make-wired-lreg ppc::imm0
+                                  :mode
+                                  (gpr-mode-name-value
+                                   (case resultspec
+                                     (:address :address)
+                                     (:signed-byte :s8)
+                                     (:unsigned-byte :u8)
+                                     (:signed-halfword :s16)
+                                     (:unsigned-halfword :u16)
+                                     (:signed-fullword :s32)
+                                     (t :u32))))))))
+
+    (^)))
+
+(defppc2 ppc2-poweropen-syscall poweropen-syscall (seg vreg xfer idx argspecs argvals resultspec &optional monitor-exception-ports)
+  (declare (ignore monitor-exception-ports))
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+         (*ppc2-cstack* *ppc2-cstack*))
+    (! alloc-c-frame (the fixnum
+                       (+ (the fixnum (length argvals))
+                          (the fixnum
+                            (let* ((n 0))
+                              (declare (fixnum n))
+                              (dolist (spec argspecs n)
+                                (if (typep spec 'unsigned-byte)
+                                  (incf n (the fixnum
+                                            (1- (the fixnum spec))))))))
+                          (the fixnum
+                            (count-if
+                             #'(lambda (x)
+                                 (member x
+                                         '(:double-float
+                                           :unsigned-doubleword
+                                           :signed-doubleword)))
+                             argspecs)))))
+    (ppc2-open-undo $undo-ppc-c-frame)
+    (ppc2-poweropen-foreign-args seg argspecs argvals)
+    (ppc2-form seg ppc::arg_z nil idx)
+    (if (eq resultspec :signed-doubleword)
+      (! poweropen-syscall-s64)
+      (! poweropen-syscall))
+    (ppc2-close-undo)
+    (ppc2-poweropen-foreign-return seg vreg xfer resultspec)))
+
+(defun ppc2-identity (seg vreg xfer arg)
+  (with-ppc-local-vinsn-macros (seg vreg xfer)
+    (if (null vreg)
+      (ppc2-form seg vreg xfer arg)
+      (progn
+        (ensuring-node-target (target vreg)
+          (ppc2-one-targeted-reg-form seg arg target))
+      (^)))))
+
+;;; Outgoing C stack frame will look like:
+;;;  backptr
+;;;  NIL  ; marker to keep GC happy, make GDB unhappy.
+;;;  8 words of GPR arg vals - will be loaded & popped by subprim
+;;;  N words of "other" (overflow) arguments
+;;;  F words of single-float values, to be loaded into FPR before subprim call
+;;;  D aligned doublewords of double-float values, to be loaded into FPR before call.
+(defppc2 ppc2-eabi-ff-call eabi-ff-call (seg vreg xfer address argspecs argvals resultspec &optional monitor)
+  (declare (ignore monitor))
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+         (*ppc2-cstack* *ppc2-cstack*)
+         (gpr-offset 0)
+         (other-offset 8)
+         (single-float-offset 8)
+         (double-float-offset 8)
+         (nsingle-floats 0)              ; F
+         (ndouble-floats 0)             ; D
+         (nother-words 0)
+         (nfpr-args 0)
+         (ngpr-args 0)
+         (fp-loads ()))
+      (declare (fixnum  nsingle-floats ndouble-floats nfpr-args ngpr-args nother-words
+                        gpr-offset other-offset single-float-offset double-float-offset))
+      (dolist (argspec argspecs)
+        (case argspec
+          (:double-float (incf nfpr-args)
+                         (if (<= nfpr-args 8)
+                           (incf ndouble-floats)
+                           (progn
+                             (if (oddp nother-words)
+                               (incf nother-words))
+                             (incf nother-words 2))))
+          (:single-float (incf nfpr-args)
+                         (if (<= nfpr-args 8)
+                           (incf nsingle-floats)
+                           (progn
+                             (if (oddp nother-words)
+                               (incf nother-words))
+                             (incf nother-words 2))))
+          ((:unsigned-doubleword :signed-doubleword)
+           (setq ngpr-args (logior 1 ngpr-args))
+           (incf ngpr-args 2)
+           (when (> ngpr-args 9)
+             (if (oddp nother-words)
+               (incf nother-words))
+             (incf nother-words 2)))
+          (t (incf ngpr-args)
+             (if (> ngpr-args 8)
+               (incf nother-words)))))
+      (let* ((single-words (+ 8 nother-words nsingle-floats))
+             (total-words (if (zerop ndouble-floats)
+                            single-words
+                            (+ (the fixnum (+ ndouble-floats ndouble-floats))
+                               (the fixnum (logand (lognot 1) (the fixnum (1+ single-words))))))))
+           
+        (! alloc-eabi-c-frame total-words))
+      (setq single-float-offset (+ other-offset nother-words))
+      (setq double-float-offset
+            (logand (lognot 1)
+                    (the fixnum (1+ (the fixnum (+ single-float-offset nsingle-floats))))))
+      (setq ngpr-args 0 nfpr-args 0)
+      (ppc2-open-undo $undo-ppc-c-frame)
+      (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg address ppc::arg_z))
+      ;; Evaluate each form into the C frame, according to the
+      ;; matching argspec.
+      ;; Remember type and arg offset of any FP args, since FP regs
+      ;; will have to be loaded later.
+      (do* ((specs argspecs (cdr specs))
+            (vals argvals (cdr vals)))
+           ((null specs))
+        (declare (list specs vals))
+        (let* ((valform (car vals))
+               (spec (car specs))
+               (absptr (acode-absolute-ptr-p valform)))
+          (case spec
+            (:double-float
+             (let* ((df ($ ppc::fp1 :class :fpr :mode :double-float)))
+               (incf nfpr-args)
+               (ppc2-one-targeted-reg-form seg valform df )
+               (cond ((<= nfpr-args 8)
+                      (! set-double-eabi-c-arg df double-float-offset)
+                      (push (cons :double-float double-float-offset) fp-loads)
+                      (incf double-float-offset 2))
+                     (t
+                      (setq other-offset (logand (lognot 1) (the fixnum (1+ other-offset))))
+                      (! set-double-eabi-c-arg df other-offset)
+                      (incf other-offset 2)))))
+            (:single-float
+             (let* ((sf ($ ppc::fp1 :class :fpr :mode :single-float)))
+               (incf nfpr-args)
+               (ppc2-one-targeted-reg-form
+                seg valform sf)
+               (cond ((<= nfpr-args 8)
+                      (! set-single-eabi-c-arg sf single-float-offset)
+                      (push (cons :single-float single-float-offset) fp-loads)
+                      (incf single-float-offset))
+                     (t
+                      (setq other-offset (logand (lognot 1) (the fixnum (1+ other-offset))))
+                      (! set-double-eabi-c-arg sf other-offset)
+                      (incf other-offset 2)))))
+            ((:signed-doubleword :unsigned-doubleword)
+             (ppc2-one-targeted-reg-form seg valform ($ ppc::arg_z))
+             (if (eq spec :signed-doubleword)
+               (! gets64)
+               (! getu64))
+             (if (oddp ngpr-args)
+               (incf ngpr-args))
+             (incf ngpr-args 2)
+             (if (oddp gpr-offset)
+               (incf gpr-offset))
+             (cond ((<= ngpr-args 8)
+                    (! set-eabi-c-arg ($ ppc::imm0) gpr-offset)
+                    (incf gpr-offset)
+                    (! set-eabi-c-arg ($ ppc::imm1) gpr-offset)
+                    (incf gpr-offset))
+                   (t
+                    (if (oddp other-offset)
+                      (incf other-offset))
+                    (! set-eabi-c-arg ($ ppc::imm0) other-offset)
+                    (incf other-offset)
+                    (! set-eabi-c-arg ($ ppc::imm1) other-offset)
+                    (incf other-offset))))
+            (:address
+             (with-imm-target () (ptr :address)
+               (if absptr
+                 (ppc2-lri seg ptr absptr)
+                 (ppc2-form seg ptr nil valform))
+               (incf ngpr-args)
+               (cond ((<= ngpr-args 8)
+                      (! set-eabi-c-arg ptr gpr-offset)
+                      (incf gpr-offset))
+                     (t
+                      (! set-eabi-c-arg ptr other-offset)
+                      (incf other-offset)))))
+            (t
+             (with-imm-target () (valreg :natural)
+                (let* ((reg (ppc2-unboxed-integer-arg-to-reg seg valform valreg spec)))
+                  (incf ngpr-args)
+                  (cond ((<= ngpr-args 8)
+                         (! set-eabi-c-arg reg gpr-offset)
+                         (incf gpr-offset))
+                        (t
+                         (! set-eabi-c-arg reg other-offset)
+                         (incf other-offset)))))))))
+      (do* ((fpreg ppc::fp1 (1+ fpreg))
+            (reloads (nreverse fp-loads) (cdr reloads)))
+           ((or (null reloads) (= fpreg ppc::fp14)))
+        (declare (list reloads) (fixnum fpreg))
+        (let* ((reload (car reloads))
+               (size (car reload))
+               (from (cdr reload)))
+          (if (eq size :double-float)
+            (! reload-double-eabi-c-arg ($ fpreg :class :fpr :mode :double-float) from)
+            (! reload-single-eabi-c-arg ($ fpreg :class :fpr :mode :single-float) from))))
+      (ppc2-vpop-register seg ($ ppc::arg_z))
+      (! eabi-ff-call) 
+      (ppc2-close-undo)
+      (when vreg
+        (cond ((eq resultspec :void) (<- nil))
+              ((eq resultspec :double-float)
+               (<- ($  ppc::fp1 :class :fpr :mode :double-float)))
+              ((eq resultspec :single-float)
+               (<- ($ ppc::fp1 :class :fpr :mode :single-float)))
+              ((eq resultspec :unsigned-doubleword)
+               (ensuring-node-target (target vreg)
+                 (! makeu64)
+                 (ppc2-copy-register seg target ppc::arg_z)))
+              ((eq resultspec :signed-doubleword)
+               (ensuring-node-target (target vreg)
+                 (! makes64)
+                 (ppc2-copy-register seg target ppc::arg_z)))
+              (t
+               (<- (make-wired-lreg ppc::imm0
+                                    :mode
+                                    (gpr-mode-name-value
+                                     (case resultspec
+                                       (:address :address)
+                                       (:signed-byte :s8)
+                                       (:unsigned-byte :u8)
+                                       (:signed-halfword :s16)
+                                       (:unsigned-halfword :u16)
+                                       (:signed-fullword :s32)
+                                       (t :u32))))))))
+      (^)))
+
+(defppc2 ppc2-poweropen-ff-call poweropen-ff-call (seg vreg xfer address argspecs argvals resultspec &optional monitor-exception-ports)
+  (declare (ignore monitor-exception-ports))
+  (let* ((*ppc2-vstack* *ppc2-vstack*)
+         (*ppc2-top-vstack-lcell* *ppc2-top-vstack-lcell*)
+         (*ppc2-cstack* *ppc2-cstack*)
+         (return-registers nil))
+    (! alloc-c-frame (the fixnum
+                       (+ (the fixnum (length argvals)) 
+                          (the fixnum
+                            (let* ((n 0))
+                              (declare (fixnum n))
+                              (dolist (spec argspecs n)
+                                (if (typep spec 'unsigned-byte)
+                                  (incf n (the fixnum
+                                            (1- (the fixnum spec))))))))
+                          (the fixnum
+                            (count-if
+                             #'(lambda (x)
+                                 (member x
+                                         '(:double-float
+                                           :unsigned-doubleword
+                                           :signed-doubleword)))
+                             argspecs)))))
+    (ppc2-open-undo $undo-ppc-c-frame)
+    (ppc2-vpush-register seg (ppc2-one-untargeted-reg-form seg address ppc::arg_z))
+    (setq return-registers (ppc2-poweropen-foreign-args seg argspecs argvals))
+    (ppc2-vpop-register seg ppc::arg_z)
+    (if return-registers
+      (! poweropen-ff-call-regs)
+      (! poweropen-ff-call))
+    (ppc2-close-undo)
+    (when vreg
+      (cond ((eq resultspec :void) (<- nil))
+            ((eq resultspec :double-float)
+             (<- (make-hard-fp-reg ppc::fp1 hard-reg-class-fpr-mode-double)))
+            ((eq resultspec :single-float)
+             (<- (make-hard-fp-reg ppc::fp1 hard-reg-class-fpr-mode-single)))
+            ((eq resultspec :unsigned-doubleword)
+             (ensuring-node-target
+              (target vreg)
+              (! makeu64)
+              (ppc2-copy-register seg target ppc::arg_z)))
+            ((eq resultspec :signed-doubleword)
+             (ensuring-node-target
+              (target vreg)
+              (! makes64)
+              (ppc2-copy-register seg target ppc::arg_z)))
+            (t
+             (<- (set-regspec-mode ppc::imm0 (gpr-mode-name-value
+                                              (case resultspec
+                                                (:address :address)
+                                                (:signed-byte :s8)
+                                                (:unsigned-byte :u8)
+                                                (:signed-halfword :s16)
+                                                (:unsigned-halfword :u16)
+                                                (:signed-fullword :s32)
+                                                (t :u32))))))))
+      (^)))
+
+
+
+             
+(defppc2 ppc2-%temp-list %temp-list (seg vreg xfer arglist)
+  (ppc2-use-operator (%nx1-operator list) seg vreg xfer arglist))
+
+(defppc2 ppc2-%temp-cons %temp-cons (seg vreg xfer car cdr)
+  (ppc2-use-operator (%nx1-operator cons) seg vreg xfer car cdr))
+
+
+;;; Under MacsBug 5.3 (and some others ?), this'll do a low-level user
+;;; break.  If the debugger doesn't recognize the trap instruction,
+;;; you'll have to manually advance the PC past it.  "arg" winds up in the
+;;; arg_z register; whatever's in arg_z on return is returned by
+;;; the %debug-trap construct.
+
+(defppc2 ppc2-%debug-trap %debug-trap (seg vreg xfer arg)
+  (ppc2-one-targeted-reg-form seg arg ($ ppc::arg_z))
+  (! %debug-trap)
+  (<- ($ ppc::arg_z))
+  (^))
+
+(defppc2 ppc2-%reference-external-entry-point %reference-external-entry-point
+  (seg vreg xfer arg)
+  (ensuring-node-target (target vreg)
+    (let* ((reg (if (eq (hard-regspec-value target) ppc::arg_z) ($ ppc::arg_y) ($ ppc::arg_z))))
+      (ppc2-one-targeted-reg-form seg arg reg)
+      (! eep.address target reg)))
+  (^))
+
+(defppc2 ppc2-%natural+ %natural+ (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil x)
+      (ppc2-form seg nil xfer y))
+    (let* ((fix-x (acode-fixnum-form-p x))
+           (fix-y (acode-fixnum-form-p y)))
+      (if (and fix-x fix-y)
+        (ppc2-absolute-natural seg vreg xfer (+ fix-x fix-y))
+        (let* ((u15x (and (typep fix-x '(unsigned-byte 15)) fix-x))
+               (u15y (and (typep fix-y '(unsigned-byte 15)) fix-y)))
+          (if (not (or u15x u15y))
+            (with-imm-target () (xreg :natural)
+              (with-imm-target (xreg) (yreg :natural)
+                (ppc2-two-targeted-reg-forms seg x xreg y yreg)
+                (! %natural+ xreg xreg yreg))
+              (<- xreg))
+            (let* ((other (if u15x y x)))
+              (with-imm-target () (other-reg :natural)
+                (ppc2-one-targeted-reg-form seg other other-reg)
+                (! %natural+-c other-reg other-reg (or u15x u15y))
+                (<- other-reg))))
+          (^))))))
+
+(defppc2 ppc2-%natural- %natural- (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil x)
+      (ppc2-form seg nil xfer y))
+    (let* ((fix-x (acode-fixnum-form-p x))
+           (fix-y (acode-fixnum-form-p y)))
+      (if (and fix-x fix-y)
+        (ppc2-absolute-natural seg vreg xfer (- fix-x fix-y))
+        (let* ((u15y (and (typep fix-y '(unsigned-byte 15)) fix-y)))
+          (if (not u15y)
+            (with-imm-target () (xreg :natural)
+              (with-imm-target (xreg) (yreg :natural)
+                (ppc2-two-targeted-reg-forms seg x xreg y yreg)
+                (! %natural- xreg xreg yreg))
+              (<- xreg))
+            (progn
+              (with-imm-target () (xreg :natural)
+                (ppc2-one-targeted-reg-form seg x xreg)
+                (! %natural--c xreg xreg u15y)
+                (<- xreg))))
+          (^))))))
+
+(defppc2 ppc2-%natural-logior %natural-logior (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil x)
+      (ppc2-form seg nil xfer y))
+    (let* ((naturalx (nx-natural-constant-p x))
+           (naturaly (nx-natural-constant-p y)))
+      (if (and naturalx naturaly) 
+        (ppc2-absolute-natural seg vreg xfer (logior naturalx naturaly))
+        (let* ((u32x (nx-u32-constant-p x))
+               (u32y (nx-u32-constant-p y))
+               (constant (or u32x u32y)))
+          (if (not constant)
+            (with-imm-target () (xreg :natural)
+              (with-imm-target (xreg) (yreg :natural)
+                (ppc2-two-targeted-reg-forms seg x xreg y yreg)
+                (! %natural-logior xreg xreg yreg))
+              (<- xreg))
+            (let* ((other (if u32x y x))
+                   (high (ldb (byte 16 16) constant))
+                   (low (ldb (byte 16 0) constant)))
+              (with-imm-target () (other-reg :natural)
+                (ppc2-one-targeted-reg-form seg other other-reg)
+                (! %natural-logior-c other-reg other-reg high low)
+                (<- other-reg))))
+          (^))))))
+
+(defppc2 ppc2-%natural-logxor %natural-logxor (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil x)
+      (ppc2-form seg nil xfer y))
+    (let* ((naturalx (nx-natural-constant-p x))
+           (naturaly (nx-natural-constant-p y)))
+      (if (and naturalx naturaly) 
+        (ppc2-absolute-natural seg vreg xfer (logxor naturalx naturaly))
+        (let* ((u32x (nx-u32-constant-p x))
+               (u32y (nx-u32-constant-p y))
+               (constant (or u32x u32y)))
+          (if (not constant)
+            (with-imm-target () (xreg :natural)
+              (with-imm-target (xreg) (yreg :natural)
+                (ppc2-two-targeted-reg-forms seg x xreg y yreg)
+                (! %natural-logxor xreg xreg yreg))
+              (<- xreg))
+            (let* ((other (if u32x y x))
+                   (high (ldb (byte 16 16) constant))
+                   (low (ldb (byte 16 0) constant)))
+              (with-imm-target () (other-reg :natural)
+                (ppc2-one-targeted-reg-form seg other other-reg)
+                (! %natural-logxor-c other-reg other-reg high low)
+                (<- other-reg))))
+          (^))))))
+
+(defppc2 ppc2-%natural-logand %natural-logand (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (ppc2-form seg nil nil x)
+      (ppc2-form seg nil xfer y))
+    (let* ((naturalx (nx-natural-constant-p x))
+           (naturaly (nx-natural-constant-p y)))
+      (if (and naturalx naturaly) 
+        (ppc2-absolute-natural seg vreg xfer (logand naturalx naturaly))
+        (let* ((u32x (nx-u32-constant-p x))
+               (u32y (nx-u32-constant-p y))
+               (constant (or u32x u32y)))
+          (if (not constant)
+            (with-imm-target () (xreg :natural)
+              (with-imm-target (xreg) (yreg :natural)
+                (ppc2-two-targeted-reg-forms seg x xreg y yreg)
+                (! %natural-logand xreg xreg yreg))
+              (<- xreg))
+            (let* ((other (if u32x y x)))
+              (with-imm-target () (other-reg :natural)
+                (ppc2-one-targeted-reg-form seg other other-reg)
+                (multiple-value-bind (start-bit stop-bit)
+                    (ppc2-mask-bits constant)
+                  (if start-bit
+                    (! %natural-logand-mask-c other-reg other-reg start-bit stop-bit)
+                    (let* ((high (ldb (byte 16 16) constant))
+                           (low (ldb (byte 16 0) constant)))
+                      (declare (type (unsigned-byte 16) high low))
+                      (unless (and (= high #xffff)
+                                   (= low high))
+                        (if (= low 0)
+                          (! %natural-logand-high-c other-reg other-reg high)
+                          (if (= high 0)
+                            (! %natural-logand-low-c other-reg other-reg low)
+                            (with-imm-target (other-reg) (const-reg :natural)
+                              (ppc2-absolute-natural seg const-reg nil constant)
+                              (! %natural-logand other-reg other-reg const-reg))))))))
+                (<- other-reg))))
+          (^))))))
+
+(defppc2 ppc2-natural-shift-right natural-shift-right (seg vreg xfer num amt)
+  (with-imm-target () (dest :natural)
+    (ppc2-one-targeted-reg-form seg num dest)
+    (! natural-shift-right dest dest (acode-fixnum-form-p amt))
+    (<- dest)
+    (^)))
+
+(defppc2 ppc2-natural-shift-left natural-shift-left (seg vreg xfer num amt)
+  (with-imm-target () (dest :natural)
+    (ppc2-one-targeted-reg-form seg num dest)
+    (! natural-shift-left dest dest (acode-fixnum-form-p amt))
+    (<- dest)
+    (^)))
+
+;;; This assumes that "global" variables are always boundp.
+(defppc2 ppc2-global-ref global-ref (seg vreg xfer sym)
+  (when vreg
+    (ensuring-node-target (target vreg)
+      (with-node-temps () (symreg)
+        (setq symreg (or (ppc2-register-constant-p sym)
+                         (ppc2-store-immediate seg sym symreg)))
+        (! node-slot-ref target symreg (target-arch-case
+                                        (:ppc32 ppc32::symbol.vcell-cell)
+                                        (:ppc64 ppc64::symbol.vcell-cell))))))
+  (^))
+
+(defppc2 ppc2-global-setq global-setq (seg vreg xfer sym val)
+  (ppc2-vset seg
+             vreg
+             xfer
+             :symbol
+             (make-acode (%nx1-operator immediate) sym)
+             (make-acode (%nx1-operator fixnum)
+                         (target-arch-case (:ppc32 ppc32::symbol.vcell-cell)
+                                           (:ppc64 ppc64::symbol.vcell-cell)))
+             val
+             nil))
+
+(defppc2 ppc2-%current-frame-ptr %current-frame-ptr (seg vreg xfer)
+  (cond ((ppc2-tailcallok xfer)
+	 (ppc2-restore-nvrs seg *ppc2-register-restore-ea* *ppc2-register-restore-count*)
+	 (ppc2-restore-full-lisp-context seg)
+	 (! %current-frame-ptr ($ ppc::arg_z))
+	 (! jump-return-pc))
+	(t
+	 (when vreg
+	   (ensuring-node-target (target vreg)
+				 (! %current-frame-ptr target)))
+	 (^))))
+
+(defppc2 ppc2-%foreign-stack-pointer %foreign-stack-pointer (seg vreg xfer)
+  (when vreg
+    (ensuring-node-target (target vreg)
+      (! %current-frame-ptr target)))
+  (^))
+
+(defppc2 ppc2-%current-tcr %current-tcr (seg vreg xfer)
+  (when vreg
+    (ensuring-node-target (target vreg)
+      (! %current-tcr target)))
+  (^))
+
+
+
+(defppc2 ppc2-%interrupt-poll %interrupt-poll (seg vreg xfer)
+  (! event-poll)
+  (ppc2-nil seg vreg xfer))
+
+
+(defppc2 ppc2-with-c-frame with-c-frame (seg vreg xfer body &aux
+                                             (old-stack (ppc2-encode-stack)))
+  (ecase (backend-name *target-backend*)
+    (:linuxppc32 (! alloc-eabi-c-frame 0))
+    ((:darwinppc32 :darwinppc64 :linuxppc64) (! alloc-c-frame 0)))
+  (ppc2-open-undo $undo-ppc-c-frame)
+  (ppc2-undo-body seg vreg xfer body old-stack))
+
+(defppc2 ppc2-with-variable-c-frame with-variable-c-frame (seg vreg xfer size body &aux
+                                                               (old-stack (ppc2-encode-stack)))
+  (let* ((reg (ppc2-one-untargeted-reg-form seg size ppc::arg_z)))
+    (ecase (backend-name *target-backend*)
+      (:linuxppc32 (! alloc-variable-eabi-c-frame reg))
+      ((:darwinppc32 :darwinppc64 :linuxppc64) (! alloc-variable-c-frame reg)))
+    (ppc2-open-undo $undo-ppc-c-frame)
+    (ppc2-undo-body seg vreg xfer body old-stack)))
+
+(defppc2 ppc2-%symbol->symptr %symbol->symptr (seg vreg xfer sym)
+  (let* ((src (ppc2-one-untargeted-reg-form seg sym ppc::arg_z)))
+    (ensuring-node-target (target vreg)
+      (! %symbol->symptr target src))
+    (^)))
+
+(defppc2 ppc2-%double-to-single %double-to-single (seg vreg xfer arg)
+  (if (null vreg)
+    (ppc2-form seg vreg xfer arg)
+    (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+             (= (get-regspec-mode vreg) hard-reg-class-fpr-mode-single))
+      (let* ((dreg (ppc2-one-untargeted-reg-form 
+                    seg arg
+                    (make-wired-lreg (hard-regspec-value vreg)
+                                     :class hard-reg-class-fpr
+                                     :mode hard-reg-class-fpr-mode-double))))
+        (! double-to-single vreg dreg)
+        (^))
+      (with-fp-target () (argreg :double-float)
+        (ppc2-one-targeted-reg-form seg arg argreg)
+        (with-fp-target ()  (sreg :single-float)
+          (! double-to-single sreg argreg)
+          (<- sreg)
+          (^))))))
+
+(defppc2 ppc2-%single-to-double %single-to-double (seg vreg xfer arg)
+  (if (null vreg)
+    (ppc2-form seg vreg xfer arg)
+    (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+             (= (get-regspec-mode vreg) hard-reg-class-fpr-mode-double))
+      (progn
+        (ppc2-one-untargeted-reg-form 
+         seg arg
+         (make-wired-lreg (hard-regspec-value vreg)
+                          :class hard-reg-class-fpr
+                          :mode hard-reg-class-fpr-mode-single))
+        (^))
+      (with-fp-target () (sreg :single-float)
+        (ppc2-one-targeted-reg-form seg arg sreg)
+        (<- (set-regspec-mode sreg hard-reg-class-fpr-mode-double))
+        (^)))))
+
+(defppc2 ppc2-%symptr->symvector %symptr->symvector (seg vreg xfer arg)
+  (ppc2-identity seg vreg xfer arg))
+
+(defppc2 ppc2-%symvector->symptr %symvector->symptr (seg vreg xfer arg)
+  (ppc2-identity seg vreg xfer arg))
+
+(defppc2 ppc2-%fixnum-to-double %fixnum-to-double (seg vreg xfer arg)
+  (with-fp-target () (dreg :double-float)
+    (let* ((r (ppc2-one-untargeted-reg-form seg arg ppc::arg_z)))
+      (unless (or (acode-fixnum-form-p arg)
+                  *ppc2-reckless*)
+        (! trap-unless-fixnum r))
+      (! fixnum->fpr dreg r)
+      (<- dreg)
+      (^))))
+
+(defppc2 ppc2-%fixnum-to-single %fixnum-to-single (seg vreg xfer arg)
+  (with-fp-target () (dreg :double-float)
+    (let* ((r (ppc2-one-untargeted-reg-form seg arg ppc::arg_z)))
+      (unless (or (acode-fixnum-form-p arg)
+                  *ppc2-reckless*)
+        (! trap-unless-fixnum r))
+      (! fixnum->fpr dreg r)
+      (if (single-float-reg-p vreg)
+	(! double-to-single vreg dreg)
+	(with-fp-target (dreg) (sreg :single-float)
+	  (! double-to-single sreg dreg)
+	  (<- sreg)))
+      (^))))
+
+(defppc2 ppc2-%double-float %double-float (seg vreg xfer arg)
+  (let* ((real (or (acode-fixnum-form-p arg)
+                   (let* ((form (acode-unwrapped-form-value arg)))
+                     (if (and (acode-p form)
+                              (eq (acode-operator form)
+                                  (%nx1-operator immediate))
+                              (typep (cadr form) 'real))
+                       (cadr form)))))
+         (dconst (and real (ignore-errors (float real 0.0d0)))))
+    (if dconst
+      (ppc2-immediate seg vreg xfer dconst)
+      (if (ppc2-form-typep arg 'single-float)
+        (ppc2-use-operator (%nx1-operator %single-to-double)
+                           seg
+                           vreg
+                           xfer
+                           arg)
+        (if (ppc2-form-typep arg 'fixnum)
+          (ppc2-use-operator (%nx1-operator %fixnum-to-double)
+                             seg
+                             vreg
+                             xfer
+                             arg)
+          (ppc2-use-operator (%nx1-operator call)
+                             seg
+                             vreg
+                             xfer
+                             (make-acode (%nx1-operator immediate)
+                                         '%double-float)
+                             (list nil (list arg))))))))
+
+(defppc2 ppc2-%single-float %single-float (seg vreg xfer arg)
+  (let* ((real (or (acode-fixnum-form-p arg)
+                   (let* ((form (acode-unwrapped-form-value arg)))
+                     (if (and (acode-p form)
+                              (eq (acode-operator form)
+                                  (%nx1-operator immediate))
+                              (typep (cadr form) 'real))
+                       (cadr form)))))
+         (sconst (and real (ignore-errors (float real 0.0f0)))))
+    (if sconst
+      (ppc2-immediate seg vreg xfer sconst)
+      (if (ppc2-form-typep arg 'double-float)
+        (ppc2-use-operator (%nx1-operator %double-to-single)
+                           seg
+                           vreg
+                           xfer
+                           arg)
+        (if (ppc2-form-typep arg 'fixnum)
+          (ppc2-use-operator (%nx1-operator %fixnum-to-single)
+                             seg
+                             vreg
+                             xfer
+                             arg)
+          (ppc2-use-operator (%nx1-operator call)
+                             seg
+                             vreg
+                             xfer
+                             (make-acode (%nx1-operator immediate)
+                                         '%short-float)
+                             (list nil (list arg))))))))
+
+(defun show-function-constants (f)
+  (cond ((typep f 'function)
+	 (do* ((i 0 j)
+	       (n (uvsize f))
+	       (j 1 (1+ j)))
+	      ((= j n))
+	   (format t "~&~d: ~s" i (uvref f j))))
+	(t (report-bad-arg f 'function))))
+
+	
+;------
+
+
+;;;Make a gcable macptr.
+(defppc2 ppc2-%new-ptr %new-ptr (seg vreg xfer size clear-p )
+  (ppc2-call-fn seg
+                vreg
+                xfer
+                (make-acode (%nx1-operator immediate)
+                            '%new-gcable-ptr)
+                (list nil (list clear-p size))
+                nil))
+
Index: /branches/new-random/compiler/X86/.cvsignore
===================================================================
--- /branches/new-random/compiler/X86/.cvsignore	(revision 13309)
+++ /branches/new-random/compiler/X86/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/compiler/X86/X8632/x8632-arch.lisp
===================================================================
--- /branches/new-random/compiler/X86/X8632/x8632-arch.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/X8632/x8632-arch.lisp	(revision 13309)
@@ -0,0 +1,1262 @@
+;;;-*- Mode: Lisp; Package: (X8632 :use CL) -*-
+
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+;;; This stuff has to match lisp-kernel/x86-constants32.[hs]
+
+(defpackage "X8632"
+  (:use "CL")
+  #+x8632-target
+  (:nicknames "TARGET"))
+
+(in-package "X8632")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "X86-ARCH")
+  (require "X86-LAP")
+
+(defparameter *x8632-symbolic-register-names*
+  (make-hash-table :test #'equal)
+  "For the disassembler, mostly.")
+
+;;; Define integer constants which map to indices in the
+;;; X86::*X8632-REGISTER-ENTRIES* array.
+(ccl::defenum ()
+  ;; 32-bit registers
+  eax
+  ecx
+  edx
+  ebx
+  esp
+  ebp
+  esi
+  edi
+  ;; 16-bit-registers
+  ax
+  cx
+  dx
+  bx
+  sp
+  bp
+  si
+  di
+  ;; 8-bit registers
+  al
+  cl
+  dl
+  bl
+  ah
+  ch
+  dh
+  bh
+  ;; xmm registers
+  xmm0
+  xmm1
+  xmm2
+  xmm3
+  xmm4
+  xmm5
+  xmm6
+  xmm7
+  ;; MMX registers
+  mm0
+  mm1
+  mm2
+  mm3
+  mm4
+  mm5
+  mm6
+  mm7
+  ;; x87 FP regs
+  st[0]
+  st[1]
+  st[2]
+  st[3]
+  st[4]
+  st[5]
+  st[6]
+  st[7]
+  ;; Segment registers
+  cs
+  ds
+  ss
+  es
+  fs
+  gs
+  )
+
+(defmacro defx86reg (alias known)
+  (let* ((known-entry (gensym)))
+    `(let* ((,known-entry (gethash ,(string known) x86::*x8632-registers*)))
+       (unless ,known-entry
+	 (error "register ~a not defined" ',known))
+       (setf (gethash ,(string alias) x86::*x8632-registers*) ,known-entry)
+       (unless (gethash ,(string-downcase (string known)) *x8632-symbolic-register-names*)
+	 (setf (gethash ,(string-downcase (string known)) *x8632-symbolic-register-names*)
+	       (string-downcase ,(string alias))))
+       (defconstant ,alias ,known))))
+
+;;; The limited number of registers that we have may make it
+;;; impossible to statically partition the register file into
+;;; immediate and tagged sets.
+;;;
+;;; As a baseline, we will use the scheme defined below.  This
+;;; partitioning will be in effect any time a function is entered
+;;; (and therefore at the time of a function call).
+;;;
+;;; This partitioning can be altered by setting or clearing bits in
+;;; thread-private memory which indicate whether a register is an
+;;; immmediate or a node.  The GC will look at these flag bits to
+;;; decide how to treat the registers.
+;;;
+;;; "Lispy" register names might be therefore be confusing at times.
+;;; 
+
+(defx86reg imm0 eax)
+(defx86reg imm0.w ax)
+(defx86reg imm0.b al)
+(defx86reg imm0.bh ah)
+
+(defx86reg temp0 ecx)
+(defx86reg temp0.w cx)
+(defx86reg temp0.b cl)
+(defx86reg temp0.bh ch)
+(defx86reg shift cl)
+
+(defx86reg temp1 edx)
+(defx86reg temp1.w dx)
+(defx86reg temp1.b dl)
+(defx86reg temp1.bh dh)
+(defx86reg nargs edx)
+
+(defx86reg arg_z ebx)
+(defx86reg arg_z.w bx)
+(defx86reg arg_z.b bl)
+(defx86reg arg_z.bh bh)
+
+(defx86reg arg_y esi)
+(defx86reg arg_y.w si)
+
+(defx86reg fn edi)
+
+;; Callee-saved non-volatile registers are probably a non-starter on
+;; IA-32.
+
+;;; Use xmm regs for floating-point.  (They can also hold integer values.)
+(defx86reg fp0 xmm0)
+(defx86reg fp1 xmm1)
+(defx86reg fp2 xmm2)
+(defx86reg fp3 xmm3)
+(defx86reg fp4 xmm4)
+(defx86reg fp5 xmm5)
+(defx86reg fp6 xmm6)
+(defx86reg fp7 xmm7)
+
+(defx86reg fpzero fp7)
+
+;;; The 8 MMX registers overlap the x87 FPU.
+;;; (so when/if we use the x87 FPU, we need to be careful with this)
+(defx86reg stack-temp mm7)
+
+(defx86reg fname temp0)
+
+(defx86reg allocptr temp0)
+
+(defx86reg ra0 temp0)
+
+;;; We rely one at least one of %ra0/%fn pointing to the current function
+;;; (or to a TRA that references the function) at all times.  When we
+;;; tail call something, we want %RA0 to point to our caller's TRA and
+;;; %FN to point to the new function.  Unless we go out of line to
+;;; do tail calls, we need some register not involved in the calling
+;;; sequence to hold the current function, since it might get GCed otherwise.
+;;; (The odds of this happening are low, but non-zero.)
+;;; xxx
+(defx86reg xfn temp1)
+
+(defx86reg next-method-context temp0)
+
+;;; This follows the ppc32 scheme pretty closely.
+
+(defconstant nbits-in-word 32)
+(defconstant nbits-in-byte 8)
+(defconstant ntagbits 3)
+(defconstant nlisptagbits 2)
+(defconstant nfixnumtagbits 2)
+(defconstant num-subtag-bits 8)
+(defconstant subtagmask 255)
+(defconstant fixnumshift 2)
+(defconstant fixnum-shift 2)
+(defconstant fulltagmask 7)
+(defconstant tagmask 3)
+(defconstant fixnummask 3)
+(defconstant ncharcodebits 8)
+(defconstant charcode-shift 8)
+(defconstant word-shift 2)
+(defconstant word-size-in-bytes 4)
+(defconstant node-size word-size-in-bytes)
+(defconstant dnode-size 8)
+(defconstant dnode-align-bits 3)
+(defconstant dnode-shift dnode-align-bits)
+(defconstant bitmap-shift 5)
+
+(defconstant fixnumone (ash 1 fixnumshift))
+(defconstant fixnum-one fixnumone)
+(defconstant fixnum1 fixnumone)
+
+(defconstant target-most-negative-fixnum (ash -1 (1- (- nbits-in-word nfixnumtagbits))))
+(defconstant target-most-positive-fixnum (1- (ash 1 (1- (- nbits-in-word nfixnumtagbits)))))
+
+;;; bits correspond to reg encoding used in instructions
+;;;  7   6   5   4   3   2   1   0
+;;; edi esi ebp esp ebx edx ecx eax
+
+(defconstant default-node-regs-mask #b11001110)
+
+;;; 2-bit "lisptag" values
+(defconstant tag-fixnum 0)
+(defconstant tag-list 1)		;a misnomer now
+(defconstant tag-misc 2)
+(defconstant tag-imm 3)
+
+;;; 3-bit "fulltag" values
+(defconstant fulltag-even-fixnum 0)
+(defconstant fulltag-cons 1)
+(defconstant fulltag-nodeheader 2)
+(defconstant fulltag-imm 3)
+(defconstant fulltag-odd-fixnum 4)
+(defconstant fulltag-tra 5)		;was for nil on PPC32
+(defconstant fulltag-misc 6)
+(defconstant fulltag-immheader 7)
+
+(defmacro define-subtag (name tag subtag)
+  `(defconstant ,(ccl::form-symbol "SUBTAG-" name) (logior ,tag (ash ,subtag ntagbits))))
+
+(defmacro define-imm-subtag (name subtag)
+  `(define-subtag ,name fulltag-immheader ,subtag))
+
+(defmacro define-node-subtag (name subtag)
+  `(define-subtag ,name fulltag-nodeheader ,subtag))
+
+;;; The order in which various header values are defined is
+;;; significant in several ways:
+;;; 1) Numeric subtags precede non-numeric ones; there are further
+;;;    orderings among numeric subtags.
+;;; 2) All subtags which denote CL arrays are preceded by those that
+;;;    don't, with a further ordering which requires that
+;;;    (< header-arrayH header-vectorH ,@all-other-CL-vector-types)
+;;; 3) The element-size of ivectors is determined by the ordering of
+;;;    ivector subtags.
+;;; 4) All subtags are >= fulltag-immheader.
+
+;;; Numeric subtags
+(define-imm-subtag bignum 0)
+(defconstant min-numeric-subtag subtag-bignum)
+(define-node-subtag ratio 1)
+(defconstant max-rational-subtag subtag-ratio)
+
+(define-imm-subtag single-float 1)
+(define-imm-subtag double-float 2)
+(defconstant min-float-subtag subtag-single-float)
+(defconstant max-float-subtag subtag-double-float)
+(defconstant max-real-subtag subtag-double-float)
+
+(define-node-subtag complex 3)
+(defconstant max-numeric-subtag subtag-complex)
+
+;;; CL array types.  There are more immediate types than node types;
+;;; all CL array subtags must be > than all non-CL-array subtags.  So
+;;; we start by defining the immediate subtags in decreasing order,
+;;; starting with that subtag whose element size isn't an integral
+;;; number of bits and ending with those whose element size - like all
+;;; non-CL-array fulltag-immheader types - is 32 bits.
+
+(define-imm-subtag bit-vector 31)
+(define-imm-subtag double-float-vector 30)
+(define-imm-subtag s16-vector 29)
+(define-imm-subtag u16-vector 28)
+(defconstant min-16-bit-ivector-subtag subtag-u16-vector)
+(defconstant max-16-bit-ivector-subtag subtag-s16-vector)
+
+;imm-subtag 27 unused
+
+(define-imm-subtag s8-vector 26)
+(define-imm-subtag u8-vector 25)
+(defconstant min-8-bit-ivector-subtag subtag-u8-vector)
+(defconstant max-8-bit-ivector-subtag (logior fulltag-immheader (ash 27 ntagbits)))
+
+(define-imm-subtag simple-base-string 24)
+(define-imm-subtag fixnum-vector 23)
+(define-imm-subtag s32-vector 22)
+(define-imm-subtag u32-vector 21)
+(define-imm-subtag single-float-vector 20)
+(defconstant max-32-bit-ivector-subtag (logior fulltag-immheader (ash 24 ntagbits)))
+(defconstant min-cl-ivector-subtag subtag-single-float-vector)
+
+(define-node-subtag arrayH 19)
+(define-node-subtag vectorH 20)
+(assert (< subtag-arrayH subtag-vectorH min-cl-ivector-subtag))
+(define-node-subtag simple-vector 21)   ; Only one such subtag
+(assert (< subtag-arrayH subtag-vectorH subtag-simple-vector))
+(defconstant min-vector-subtag subtag-vectorH)
+(defconstant min-array-subtag subtag-arrayH)
+
+(define-imm-subtag macptr 3)
+(defconstant min-non-numeric-imm-subtag subtag-macptr)
+(assert (> min-non-numeric-imm-subtag max-numeric-subtag))
+(define-imm-subtag dead-macptr 4)
+;;(define-imm-subtag unused 5)		;was creole-object
+;;(define-imm-subtag unused 6)		;was code-vector
+(define-imm-subtag xcode-vector 7)
+
+;;; immediate subtags
+(define-subtag unbound fulltag-imm 6)
+(defconstant unbound-marker subtag-unbound)
+(defconstant undefined unbound-marker)
+(define-subtag character fulltag-imm 9)
+(define-subtag slot-unbound fulltag-imm 10)
+(defconstant slot-unbound-marker subtag-slot-unbound)
+(define-subtag illegal fulltag-imm 11)
+(defconstant illegal-marker subtag-illegal)
+(define-subtag forward-marker fulltag-imm 28)
+(define-subtag reserved-frame fulltag-imm 29)
+(defconstant reserved-frame-marker subtag-reserved-frame)
+(define-subtag no-thread-local-binding fulltag-imm 30)
+
+;;; This has two functions: it tells the link-inverting marker where
+;;; the code ends and the self-reference table and constants start, and it
+;;; ensures that the 0th constant will never be in the same memozized
+;;; dnode as some (unboxed) word of machine code.  I'm not sure if
+;;; there's a better way to do either of those things.
+;;;
+;;; Depending on how you look at it, we either lose 8 bytes per
+;;; function, or gain 7 bytes of otherwise unused space for debugging
+;;; info.
+;;; xxx -- comments above not right for x8632
+(define-subtag function-boundary-marker fulltag-imm 31)
+(defconstant function-boundary-marker subtag-function-boundary-marker)
+(defconstant max-non-array-imm-subtag (logior (ash 19 ntagbits) fulltag-immheader))
+
+(define-node-subtag catch-frame 4)
+(defconstant min-non-numeric-node-subtag subtag-catch-frame)
+(assert (> min-non-numeric-node-subtag max-numeric-subtag))
+(define-node-subtag function 5)
+(define-node-subtag basic-stream 6)
+(define-node-subtag symbol 7)
+(define-node-subtag lock 8)
+(define-node-subtag hash-vector 9)
+(define-node-subtag pool 10)
+(define-node-subtag weak 11)
+(define-node-subtag package 12)
+(define-node-subtag slot-vector 13)
+(define-node-subtag instance 14)
+(define-node-subtag struct 15)
+(define-node-subtag istruct 16)
+(define-node-subtag value-cell 17)
+(define-node-subtag xfunction 18)       ; Function for cross-development
+
+(defconstant max-non-array-node-subtag (logior (ash 18 ntagbits) fulltag-nodeheader))
+
+(defconstant misc-header-offset (- fulltag-misc))
+(defconstant misc-subtag-offset misc-header-offset)
+(defconstant misc-data-offset (+ misc-header-offset node-size))
+(defconstant misc-dfloat-offset ( + misc-header-offset 8))
+
+(defconstant max-64-bit-constant-index (ash 1 24))
+(defconstant max-32-bit-constant-index (ash 1 24))
+(defconstant max-16-bit-constant-index (ash 1 24))
+(defconstant max-8-bit-constant-index (ash 1 24))
+(defconstant max-1-bit-constant-index (ash 1 24))
+
+)  ;eval-when
+
+;;; On IA-32, the tag which was used for nil on ppc32 is now used for
+;;; tagged return addresses.  We therefore make nil a distinguished
+;;; CONS.  This way, CAR and CDR can just check the tag, and
+;;; CONSP/RPLACA/RPLACD can check the tag and complain if the argument
+;;; is NIL.
+(defconstant canonical-nil-value (+ #x13000 fulltag-cons))
+(defconstant canonical-t-value (+ #x13008 fulltag-misc))
+(defconstant t-offset (- canonical-t-value canonical-nil-value))
+
+(defconstant misc-bias fulltag-misc)
+(defconstant cons-bias fulltag-cons)
+
+
+(defmacro define-storage-layout (name origin &rest cells)
+  `(progn
+     (ccl::defenum (:start ,origin :step 4)
+	 ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell)) cells))
+     (defconstant ,(ccl::form-symbol name ".SIZE") ,(* (length cells) 4))))
+
+(defmacro define-lisp-object (name tagname &rest cells)
+  `(define-storage-layout ,name ,(- (symbol-value tagname)) ,@cells))
+
+(defmacro define-fixedsized-object (name &rest non-header-cells)
+  `(progn
+     (define-lisp-object ,name fulltag-misc header ,@non-header-cells)
+     (ccl::defenum ()
+	 ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell "-CELL")) non-header-cells))
+     (defconstant ,(ccl::form-symbol name ".ELEMENT-COUNT") ,(length non-header-cells))))
+
+(define-lisp-object cons tag-list 
+  cdr 
+  car)
+
+(define-fixedsized-object ratio
+  numer
+  denom)
+
+(define-fixedsized-object single-float
+  value)
+
+(define-fixedsized-object double-float
+  pad
+  value
+  val-high)
+
+(define-fixedsized-object complex
+  realpart
+  imagpart)
+
+;;; There are two kinds of macptr; use the length field of the header if you
+;;; need to distinguish between them
+(define-fixedsized-object macptr
+  address
+  domain
+  type
+)
+
+(define-fixedsized-object xmacptr
+  address
+  domain
+  type
+  flags
+  link
+)
+
+;;; Need to think about catch frames on x8632, too.
+(define-fixedsized-object catch-frame
+  catch-tag                             ; #<unbound> -> unwind-protect, else catch
+  link                                  ; tagged pointer to next older catch frame
+  mvflag                                ; 0 if single-value, 1 if uwp or multiple-value
+  esp                                   ;
+  ebp
+  foreign-sp
+  db-link                               ; value of dynamic-binding link on thread entry.
+  xframe                                ; exception-frame link
+  pc                                    ; tra of catch exit/unwind cleanup
+)
+
+(define-fixedsized-object lock
+  _value                                ;finalizable pointer to kernel object
+  kind                                  ; '0 = recursive-lock, '1 = rwlock
+  writer                                ;tcr of owning thread or 0
+  name
+  whostate
+  whostate-2
+  )
+
+
+
+(define-fixedsized-object symbol
+  pname
+  vcell
+  fcell
+  package-predicate
+  flags
+  plist
+  binding-index
+)
+
+(defconstant nilsym-offset (+ t-offset symbol.size))
+
+(define-fixedsized-object vectorH
+  logsize                               ; fillpointer if it has one, physsize otherwise
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+)
+
+(define-lisp-object arrayH fulltag-misc
+  header                                ; subtag = subtag-arrayH
+  rank                                  ; NEVER 1
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0  
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+ ;; Dimensions follow
+)
+
+(defconstant arrayH.rank-cell 0)
+(defconstant arrayH.physsize-cell 1)
+(defconstant arrayH.data-vector-cell 2)
+(defconstant arrayH.displacement-cell 3)
+(defconstant arrayH.flags-cell 4)
+(defconstant arrayH.dim0-cell 5)
+
+(defconstant arrayH.flags-cell-bits-byte (byte 8 0))
+(defconstant arrayH.flags-cell-subtag-byte (byte 8 8))
+
+
+(define-fixedsized-object value-cell
+  value)
+
+(define-storage-layout lisp-frame 0
+  backptr
+  return-address
+  xtra)
+
+(define-storage-layout tsp-frame 0
+  backptr
+  ebp)
+
+(define-storage-layout csp-frame 0
+  backptr
+  ebp)
+
+(define-storage-layout xcf 0            ;"exception callback frame"
+  backptr
+  return-address                        ; always 0
+  nominal-function
+  relative-pc
+  containing-object
+  xp
+  ra0
+  foreign-sp				;value of tcr.foreign_sp
+  prev-xframe				;tcr.xframe before exception
+  )					;(last 2 needed by apply-in-frame)
+
+;;; The kernel uses these (rather generically named) structures
+;;; to keep track of various memory regions it (or the lisp) is
+;;; interested in.
+
+(define-storage-layout area 0
+  pred                                  ; pointer to preceding area in DLL
+  succ                                  ; pointer to next area in DLL
+  low                                   ; low bound on area addresses
+  high                                  ; high bound on area addresses.
+  active                                ; low limit on stacks, high limit on heaps
+  softlimit                             ; overflow bound
+  hardlimit                             ; another one
+  code                                  ; an area-code; see below
+  markbits                              ; bit vector for GC
+  ndnodes                               ; "active" size of dynamic area or stack
+  older                                 ; in EGC sense
+  younger                               ; also for EGC
+  h                                     ; Handle or null pointer
+  softprot                              ; protected_area structure pointer
+  hardprot                              ; another one.
+  owner                                 ; fragment (library) which "owns" the area
+  refbits                               ; bitvector for intergenerational refernces
+  threshold                             ; for egc
+  gc-count                              ; generational gc count.
+  static-dnodes                         ; for honsing, etc.
+  static-used                           ; bitvector
+)
+
+(define-storage-layout protected-area 0
+  next
+  start                                 ; first byte (page-aligned) that might be protected
+  end                                   ; last byte (page-aligned) that could be protected
+  nprot                                 ; Might be 0
+  protsize                              ; number of bytes to protect
+  why)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defconstant tcr-bias 0))
+
+(define-storage-layout tcr (- tcr-bias)
+  next					; in doubly-linked list
+  prev					; in doubly-linked list 
+  node-regs-mask			; bit set means corresponding reg contains node
+  linear
+  ;; save0 *must* be aligned on a 16-byte boundary!
+  save0					;spill area for node registers
+  save1					; (caller saved)
+  save2					; probably saved/restored in
+  save3					; callout/trap handlers
+  save-ebp                              ; lisp frame ptr for foreign code
+  lisp-mxcsr
+  foreign-mxcsr
+  db-link				; special binding chain head 
+  catch-top				; top catch frame 
+  save-vsp				; SP when in foreign code 
+  save-tsp				; TSP, at all times
+  foreign-sp                            ; SP when in lisp code
+  cs-area				; cstack area pointer 
+  vs-area				; vstack area pointer 
+  ts-area				; tstack area pointer 
+  cs-limit				; cstack overflow limit
+  total-bytes-allocated-low
+  total-bytes-allocated-high
+  log2-allocation-quantum		; unboxed
+  interrupt-pending			; fixnum
+  xframe				; exception frame linked list
+  errno-loc				; thread-private, maybe
+  ffi-exception				; fpscr bits from ff-call.
+  osid					; OS thread id 
+  valence				; odd when in foreign code 
+  foreign-exception-status
+  native-thread-info
+  native-thread-id
+  last-allocptr
+  save-allocptr
+  save-allocbase
+  reset-completion
+  activate
+  suspend-count
+  suspend-context
+  pending-exception-context
+  suspend				; semaphore for suspension notify 
+  resume				; sempahore for resumption notify
+  flags					; foreign, being reset, ...
+  gc-context
+  termination-semaphore
+  unwinding
+  tlb-limit
+  tlb-pointer
+  shutdown-count
+  next-tsp
+  safe-ref-address
+  ldt-selector
+  scratch-mxcsr				;used for reading/writing mxcsr
+  unboxed0				;unboxed scratch locations
+  unboxed1
+  next-method-context			;used in lieu of register
+  save-eflags
+  allocated                             ;maybe unaligned TCR pointer
+  pending-io-info
+  io-datum                              ;for windows overlapped I/O
+)
+
+(defconstant interrupt-level-binding-index (ash 1 fixnumshift))
+
+(define-storage-layout lockptr 0
+  avail
+  owner
+  count
+  signal
+  waiting
+  malloced-ptr
+  spinlock)
+
+(define-storage-layout rwlock 0
+  spin
+  state
+  blocked-writers
+  blocked-readers
+  writer
+  reader-signal
+  writer-signal
+  malloced-ptr
+  )
+
+(defmacro define-header (name element-count subtag)
+  `(defconstant ,name (logior (ash ,element-count num-subtag-bits) ,subtag)))
+
+(define-header single-float-header single-float.element-count subtag-single-float)
+(define-header double-float-header double-float.element-count subtag-double-float)
+
+;;; We could possibly have a one-digit bignum header when dealing
+;;; with "small bignums" in some bignum code.  Like other cases of
+;;; non-normalized bignums, they should never escape from the lab.
+(define-header one-digit-bignum-header 1 subtag-bignum)
+(define-header two-digit-bignum-header 2 subtag-bignum)
+(define-header three-digit-bignum-header 3 subtag-bignum)
+(define-header symbol-header symbol.element-count subtag-symbol)
+(define-header value-cell-header value-cell.element-count subtag-value-cell)
+(define-header macptr-header macptr.element-count subtag-macptr)
+
+;;; see x86-clos.lisp
+(defconstant gf-code-size 30)
+
+(defun %kernel-global (sym)
+  (let* ((pos (position sym x86::*x86-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ fulltag-cons (* (1+ pos) node-size)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+(defmacro kernel-global (sym)
+  (let* ((pos (position sym x86::*x86-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ fulltag-cons (* (1+ pos) node-size)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+(ccl::defenum (:prefix "KERNEL-IMPORT-" :start 0 :step node-size)
+  fd-setsize-bytes
+  do-fd-set
+  do-fd-clr
+  do-fd-is-set
+  do-fd-zero
+  MakeDataExecutable
+  GetSharedLibrary
+  FindSymbol
+  malloc
+  free
+  jvm-init
+  tcr-frame-ptr
+  register-xmacptr-dispose-function
+  open-debug-output
+  get-r-debug
+  restore-soft-stack-limit
+  egc-control
+  lisp-bug
+  NewThread
+  cooperative-thread-startup
+  DisposeThread
+  ThreadCurrentStackSpace
+  usage-exit
+  save-fp-context
+  restore-fp-context
+  put-altivec-registers			;is there any
+  get-altivec-registers			;point to these on x86?
+  new-semaphore
+  wait-on-semaphore
+  signal-semaphore
+  destroy-semaphore
+  new-recursive-lock
+  lock-recursive-lock
+  unlock-recursive-lock
+  destroy-recursive-lock
+  suspend-other-threads
+  resume-other-threads
+  suspend-tcr
+  resume-tcr
+  rwlock-new
+  rwlock-destroy
+  rwlock-rlock
+  rwlock-wlock
+  rwlock-unlock
+  recursive-lock-trylock
+  foreign-name-and-offset
+  lisp-read
+  lisp-write
+  lisp-open
+  lisp-fchmod
+  lisp-lseek
+  lisp-close
+  lisp-ftruncate
+  lisp-stat
+  lisp-fstat
+  lisp-futex
+  lisp-opendir
+  lisp-readdir
+  lisp-closedir
+  lisp-pipe
+  lisp-gettimeofday
+  lisp-sigexit
+)
+
+(defmacro nrs-offset (name)
+  (let* ((pos (position name x86::*x86-nilreg-relative-symbols* :test #'eq)))
+    (if pos (* (1- pos) symbol.size))))
+
+(defmacro with-stack-short-floats (specs &body body)
+  (ccl::collect ((binds)
+                 (inits)
+                 (names))
+                (dolist (spec specs)
+                  (let ((name (first spec)))
+                    (binds `(,name (ccl::%make-sfloat)))
+                    (names name)
+                    (let ((init (second spec)))
+                      (when init
+                        (inits `(ccl::%short-float ,init ,name))))))
+                `(let* ,(binds)
+                  (declare (dynamic-extent ,@(names))
+                           (short-float ,@(names)))
+                  ,@(inits)
+                  ,@body)))
+
+(defparameter *x8632-target-uvector-subtags*
+  `((:bignum . ,subtag-bignum)
+    (:ratio . ,subtag-ratio)
+    (:single-float . ,subtag-single-float)
+    (:double-float . ,subtag-double-float)
+    (:complex . ,subtag-complex  )
+    (:symbol . ,subtag-symbol)
+    (:function . ,subtag-function )
+    (:xcode-vector . ,subtag-xcode-vector)
+    (:macptr . ,subtag-macptr )
+    (:catch-frame . ,subtag-catch-frame)
+    (:struct . ,subtag-struct )    
+    (:istruct . ,subtag-istruct )
+    (:pool . ,subtag-pool )
+    (:population . ,subtag-weak )
+    (:hash-vector . ,subtag-hash-vector )
+    (:package . ,subtag-package )
+    (:value-cell . ,subtag-value-cell)
+    (:instance . ,subtag-instance )
+    (:lock . ,subtag-lock )
+    (:slot-vector . ,subtag-slot-vector)
+    (:basic-stream . ,subtag-basic-stream)
+    (:simple-string . ,subtag-simple-base-string )
+    (:bit-vector . ,subtag-bit-vector )
+    (:signed-8-bit-vector . ,subtag-s8-vector )
+    (:unsigned-8-bit-vector . ,subtag-u8-vector )
+    (:signed-16-bit-vector . ,subtag-s16-vector )
+    (:unsigned-16-bit-vector . ,subtag-u16-vector )
+    (:signed-32-bit-vector . ,subtag-s32-vector )
+    (:fixnum-vector . ,subtag-fixnum-vector)
+    (:unsigned-32-bit-vector . ,subtag-u32-vector )
+    (:single-float-vector . ,subtag-single-float-vector)
+    (:double-float-vector . ,subtag-double-float-vector )
+    (:simple-vector . ,subtag-simple-vector )
+    (:vector-header . ,subtag-vectorH)
+    (:array-header . ,subtag-arrayH)))
+
+;;; This should return NIL unless it's sure of how the indicated
+;;; type would be represented (in particular, it should return
+;;; NIL if the element type is unknown or unspecified at compile-time.
+(defun x8632-array-type-name-from-ctype (ctype)
+  (when (typep ctype 'ccl::array-ctype)
+    (let* ((element-type (ccl::array-ctype-element-type ctype)))
+      (typecase element-type
+        (ccl::class-ctype
+         (let* ((class (ccl::class-ctype-class element-type)))
+           (if (or (eq class ccl::*character-class*)
+                   (eq class ccl::*base-char-class*)
+                   (eq class ccl::*standard-char-class*))
+             :simple-string
+             :simple-vector)))
+        (ccl::numeric-ctype
+         (if (eq (ccl::numeric-ctype-complexp element-type) :complex)
+           :simple-vector
+           (case (ccl::numeric-ctype-class element-type)
+             (integer
+              (let* ((low (ccl::numeric-ctype-low element-type))
+                     (high (ccl::numeric-ctype-high element-type)))
+                (cond ((or (null low) (null high)) :simple-vector)
+                      ((and (>= low 0) (<= high 1) :bit-vector))
+                      ((and (>= low 0) (<= high 255)) :unsigned-8-bit-vector)
+                      ((and (>= low 0) (<= high 65535)) :unsigned-16-bit-vector)
+                      ((and (>= low 0) (<= high #xffffffff) :unsigned-32-bit-vector))
+                      ((and (>= low -128) (<= high 127)) :signed-8-bit-vector)
+                      ((and (>= low -32768) (<= high 32767) :signed-16-bit-vector))
+                      ((and (>= low target-most-negative-fixnum)
+                            (<= high target-most-positive-fixnum))
+                       :fixnum-vector)
+                      ((and (>= low (ash -1 31)) (<= high (1- (ash 1 31))))
+                       :signed-32-bit-vector)
+                      (t :simple-vector))))
+             (float
+              (case (ccl::numeric-ctype-format element-type)
+                ((double-float long-float) :double-float-vector)
+                ((single-float short-float) :single-float-vector)
+                (t :simple-vector)))
+             (t :simple-vector))))
+        (ccl::unknown-ctype)
+        (ccl::named-ctype
+         (if (eq element-type ccl::*universal-type*)
+           :simple-vector))
+        (t nil)))))
+
+(defun x8632-misc-byte-count (subtag element-count)
+  (declare (fixnum subtag))
+  (if (or (= fulltag-nodeheader (logand subtag fulltagmask))
+          (<= subtag max-32-bit-ivector-subtag))
+    (ash element-count 2)
+    (if (<= subtag max-8-bit-ivector-subtag)
+      element-count
+      (if (<= subtag max-16-bit-ivector-subtag)
+        (ash element-count 1)
+        (if (= subtag subtag-bit-vector)
+          (ash (+ element-count 7) -3)
+          (+ 4 (ash element-count 3)))))))
+
+(defparameter *x8632-subprims-shift* 2)
+(defconstant x8632-subprims-base #x15000)
+
+(declaim (special *x8632-subprims*))
+
+(let* ((origin x8632-subprims-base)
+       (step (ash 1 *x8632-subprims-shift*)))
+  (flet ((define-x8632-subprim (name)
+	   (ccl::make-subprimitive-info :name (string name)
+					:offset (prog1 origin
+						  (incf origin step)))))
+    (macrolet ((defx8632subprim (name)
+		 `(define-x8632-subprim ',name)))
+      (defparameter *x8632-subprims*
+	(vector
+         (defx8632subprim .SPjmpsym)
+         (defx8632subprim .SPjmpnfn)
+         (defx8632subprim .SPfuncall)
+         (defx8632subprim .SPmkcatch1v)
+         (defx8632subprim .SPmkunwind)
+         (defx8632subprim .SPmkcatchmv)
+         (defx8632subprim .SPthrow)
+         (defx8632subprim .SPnthrowvalues)
+         (defx8632subprim .SPnthrow1value)
+         (defx8632subprim .SPbind)
+         (defx8632subprim .SPbind-self)
+         (defx8632subprim .SPbind-nil)
+         (defx8632subprim .SPbind-self-boundp-check)
+         (defx8632subprim .SPrplaca)
+         (defx8632subprim .SPrplacd)
+         (defx8632subprim .SPconslist)
+         (defx8632subprim .SPconslist-star)
+         (defx8632subprim .SPstkconslist)
+         (defx8632subprim .SPstkconslist-star)
+         (defx8632subprim .SPmkstackv)
+         (defx8632subprim .SPsubtag-misc-ref)
+         (defx8632subprim .SPsetqsym)
+         (defx8632subprim .SPprogvsave)
+         (defx8632subprim .SPstack-misc-alloc)
+         (defx8632subprim .SPgvector)
+         (defx8632subprim .SPnvalret)
+         (defx8632subprim .SPmvpass)
+         (defx8632subprim .SPrecover-values-for-mvcall)
+         (defx8632subprim .SPnthvalue)
+         (defx8632subprim .SPvalues)
+         (defx8632subprim .SPdefault-optional-args)
+         (defx8632subprim .SPopt-supplied-p)
+         (defx8632subprim .SPheap-rest-arg)
+         (defx8632subprim .SPreq-heap-rest-arg)
+         (defx8632subprim .SPheap-cons-rest-arg)
+         (defx8632subprim .SPsimple-keywords)
+         (defx8632subprim .SPkeyword-args)
+         (defx8632subprim .SPkeyword-bind)
+         (defx8632subprim .SPffcall)
+         (defx8632subprim .SParef2)
+         (defx8632subprim .SPksignalerr)
+         (defx8632subprim .SPstack-rest-arg)
+         (defx8632subprim .SPreq-stack-rest-arg)
+         (defx8632subprim .SPstack-cons-rest-arg)
+         (defx8632subprim .SPpoweropen-callbackX) ;needed on x86?
+         (defx8632subprim .SPcall-closure)
+         (defx8632subprim .SPgetXlong)
+         (defx8632subprim .SPspreadargz)
+         (defx8632subprim .SPtfuncallgen)
+         (defx8632subprim .SPtfuncallslide)
+         (defx8632subprim .SPtfuncallvsp)
+         (defx8632subprim .SPtcallsymgen)
+         (defx8632subprim .SPtcallsymslide)
+         (defx8632subprim .SPtcallsymvsp)
+         (defx8632subprim .SPtcallnfngen)
+         (defx8632subprim .SPtcallnfnslide)
+         (defx8632subprim .SPtcallnfnvsp)
+         (defx8632subprim .SPmisc-ref)
+         (defx8632subprim .SPmisc-set)
+         (defx8632subprim .SPstkconsyz)
+         (defx8632subprim .SPstkvcell0)
+         (defx8632subprim .SPstkvcellvsp)
+         (defx8632subprim .SPmakestackblock)
+         (defx8632subprim .SPmakestackblock0)
+         (defx8632subprim .SPmakestacklist)
+         (defx8632subprim .SPstkgvector)
+         (defx8632subprim .SPmisc-alloc)
+         (defx8632subprim .SPpoweropen-ffcallX)	;needed on x86?
+         (defx8632subprim .SPgvset)
+         (defx8632subprim .SPmacro-bind)
+         (defx8632subprim .SPdestructuring-bind)
+         (defx8632subprim .SPdestructuring-bind-inner)
+         (defx8632subprim .SPrecover-values)
+         (defx8632subprim .SPvpopargregs)
+         (defx8632subprim .SPinteger-sign)
+         (defx8632subprim .SPsubtag-misc-set)
+         (defx8632subprim .SPspread-lexpr-z)
+         (defx8632subprim .SPstore-node-conditional)
+         (defx8632subprim .SPreset)
+         (defx8632subprim .SPmvslide)
+         (defx8632subprim .SPsave-values)
+         (defx8632subprim .SPadd-values)
+         (defx8632subprim .SPcallback)
+         (defx8632subprim .SPmisc-alloc-init)
+         (defx8632subprim .SPstack-misc-alloc-init)
+         (defx8632subprim .SPset-hash-key)
+         (defx8632subprim .SPaset2)
+         (defx8632subprim .SPcallbuiltin)
+         (defx8632subprim .SPcallbuiltin0)
+         (defx8632subprim .SPcallbuiltin1)
+         (defx8632subprim .SPcallbuiltin2)
+         (defx8632subprim .SPcallbuiltin3)
+         (defx8632subprim .SPpopj)
+         (defx8632subprim .SPrestorefullcontext)
+         (defx8632subprim .SPsavecontextvsp)
+         (defx8632subprim .SPsavecontext0)
+         (defx8632subprim .SPrestorecontext)
+         (defx8632subprim .SPlexpr-entry)
+         (defx8632subprim .SPsyscall2)
+         (defx8632subprim .SPbuiltin-plus)
+         (defx8632subprim .SPbuiltin-minus)
+         (defx8632subprim .SPbuiltin-times)
+         (defx8632subprim .SPbuiltin-div)
+         (defx8632subprim .SPbuiltin-eq)
+         (defx8632subprim .SPbuiltin-ne)
+         (defx8632subprim .SPbuiltin-gt)
+         (defx8632subprim .SPbuiltin-ge)
+         (defx8632subprim .SPbuiltin-lt)
+         (defx8632subprim .SPbuiltin-le)
+         (defx8632subprim .SPbuiltin-eql)
+         (defx8632subprim .SPbuiltin-length)
+         (defx8632subprim .SPbuiltin-seqtype)
+         (defx8632subprim .SPbuiltin-assq)
+         (defx8632subprim .SPbuiltin-memq)
+         (defx8632subprim .SPbuiltin-logbitp)
+         (defx8632subprim .SPbuiltin-logior)
+         (defx8632subprim .SPbuiltin-logand)
+         (defx8632subprim .SPbuiltin-ash)
+         (defx8632subprim .SPbuiltin-negate)
+         (defx8632subprim .SPbuiltin-logxor)
+         (defx8632subprim .SPbuiltin-aref1)
+         (defx8632subprim .SPbuiltin-aset1)
+         (defx8632subprim .SPbreakpoint)
+         (defx8632subprim .SPeabi-ff-call)
+         (defx8632subprim .SPeabi-callback)
+         (defx8632subprim .SPsyscall)
+         (defx8632subprim .SPgetu64)
+         (defx8632subprim .SPgets64)
+         (defx8632subprim .SPmakeu64)
+         (defx8632subprim .SPmakes64)
+         (defx8632subprim .SPspecref)
+         (defx8632subprim .SPspecset)
+         (defx8632subprim .SPspecrefcheck)
+         (defx8632subprim .SPrestoreintlevel)
+         (defx8632subprim .SPmakes32)
+         (defx8632subprim .SPmakeu32)
+         (defx8632subprim .SPgets32)
+         (defx8632subprim .SPgetu32)
+         (defx8632subprim .SPfix-overflow)
+         (defx8632subprim .SPmvpasssym)
+         (defx8632subprim .SParef3)
+         (defx8632subprim .SPaset3)
+         (defx8632subprim .SPffcall-return-registers)
+         (defx8632subprim .SPaset1)
+         (defx8632subprim .SPset-hash-key-conditional)
+         (defx8632subprim .SPunbind-interrupt-level)
+         (defx8632subprim .SPunbind)
+         (defx8632subprim .SPunbind-n)
+         (defx8632subprim .SPunbind-to)
+         (defx8632subprim .SPbind-interrupt-level-m1)
+         (defx8632subprim .SPbind-interrupt-level)
+         (defx8632subprim .SPbind-interrupt-level-0)
+         (defx8632subprim .SPprogvrestore)
+	 (defx8632subprim .SPnmkunwind)
+         )))))
+
+
+
+(defparameter *x8632-target-arch*
+  (arch::make-target-arch :name :x8632
+                          :lisp-node-size node-size
+                          :nil-value canonical-nil-value
+                          :fixnum-shift fixnumshift
+                          :most-positive-fixnum target-most-positive-fixnum
+                          :most-negative-fixnum target-most-negative-fixnum
+                          :misc-data-offset misc-data-offset
+                          :misc-dfloat-offset misc-dfloat-offset
+                          :nbits-in-word nbits-in-word
+                          :ntagbits ntagbits
+                          :nlisptagbits nlisptagbits
+                          :uvector-subtags *x8632-target-uvector-subtags*
+                          :max-64-bit-constant-index max-64-bit-constant-index
+                          :max-32-bit-constant-index max-32-bit-constant-index
+                          :max-16-bit-constant-index max-16-bit-constant-index
+                          :max-8-bit-constant-index max-8-bit-constant-index
+                          :max-1-bit-constant-index max-1-bit-constant-index
+                          :word-shift word-shift
+                          :code-vector-prefix ()
+                          :gvector-types '(:ratio :complex :symbol :function
+                                           :catch-frame :struct :istruct
+                                           :pool :population :hash-vector
+                                           :package :value-cell :instance
+                                           :lock :slot-vector
+                                           :simple-vector)
+                          :1-bit-ivector-types '(:bit-vector)
+                          :8-bit-ivector-types '(:signed-8-bit-vector
+                                                 :unsigned-8-bit-vector)
+                          :16-bit-ivector-types '(:signed-16-bit-vector
+                                                  :unsigned-16-bit-vector)
+                          :32-bit-ivector-types '(:signed-32-bit-vector
+                                                  :unsigned-32-bit-vector
+                                                  :single-float-vector
+                                                  :fixnum-vector
+                                                  :single-float
+                                                  :double-float
+                                                  :bignum
+                                                  :simple-string)
+                          :64-bit-ivector-types '(:double-float-vector)
+                          :array-type-name-from-ctype-function
+                          #'x8632-array-type-name-from-ctype
+                          :package-name "X8632"
+                          :t-offset t-offset
+                          :array-data-size-function #'x8632-misc-byte-count
+                          :numeric-type-name-to-typecode-function
+                          #'(lambda (type-name)
+                              (ecase type-name
+                                (fixnum tag-fixnum)
+                                (bignum subtag-bignum)
+                                ((short-float single-float) subtag-single-float)
+                                ((long-float double-float) subtag-double-float)
+                                (ratio subtag-ratio)
+                                (complex subtag-complex)))
+                          :subprims-base x8632-subprims-base
+                          :subprims-shift x8632::*x8632-subprims-shift*
+                          :subprims-table x8632::*x8632-subprims*
+                          :primitive->subprims `(((0 . 23) . ,(ccl::%subprim-name->offset '.SPbuiltin-plus x8632::*x8632-subprims*)))
+                          :unbound-marker-value unbound-marker
+                          :slot-unbound-marker-value slot-unbound-marker
+                          :fixnum-tag tag-fixnum
+                          :single-float-tag subtag-single-float
+                          :single-float-tag-is-subtag t
+                          :double-float-tag subtag-double-float
+                          :cons-tag fulltag-cons
+                          :null-tag fulltag-cons
+                          :symbol-tag subtag-symbol
+                          :symbol-tag-is-subtag t
+                          :function-tag subtag-function
+                          :function-tag-is-subtag t
+                          :big-endian nil
+                          :misc-subtag-offset misc-subtag-offset
+                          :car-offset cons.car
+                          :cdr-offset cons.cdr
+                          :subtag-char subtag-character
+                          :charcode-shift charcode-shift
+                          :fulltagmask fulltagmask
+                          :fulltag-misc fulltag-misc
+                          :char-code-limit #x110000
+                          ))
+
+;; arch macros
+
+(defmacro defx8632archmacro (name lambda-list &body body)
+  `(arch::defarchmacro :x8632 ,name ,lambda-list ,@body))
+
+(defx8632archmacro ccl::%make-sfloat ()
+  `(ccl::%alloc-misc x8632::single-float.element-count x8632::subtag-single-float))
+
+(defx8632archmacro ccl::%make-dfloat ()
+  `(ccl::%alloc-misc x8632::double-float.element-count x8632::subtag-double-float))
+
+(defx8632archmacro ccl::%numerator (x)
+  `(ccl::%svref ,x x8632::ratio.numer-cell))
+
+(defx8632archmacro ccl::%denominator (x)
+  `(ccl::%svref ,x x8632::ratio.denom-cell))
+
+(defx8632archmacro ccl::%realpart (x)
+  `(ccl::%svref ,x x8632::complex.realpart-cell))
+                    
+(defx8632archmacro ccl::%imagpart (x)
+  `(ccl::%svref ,x x8632::complex.imagpart-cell))
+
+;;;
+(defx8632archmacro ccl::%get-single-float-from-double-ptr (ptr offset)
+ `(ccl::%double-float->short-float (ccl::%get-double-float ,ptr ,offset)
+   (ccl::%alloc-misc 1 x8632::subtag-single-float)))
+
+(defx8632archmacro ccl::codevec-header-p (word)
+  (declare (ignore word))
+  (error "~s makes no sense on :X8632" 'ccl::codevec-header-p))
+
+(defx8632archmacro ccl::immediate-p-macro (thing)
+  (let* ((tag (gensym)))
+    `(let* ((,tag (ccl::lisptag ,thing)))
+       (declare (fixnum ,tag))
+       (or (= ,tag x8632::tag-fixnum)
+	   (= ,tag x8632::tag-imm)))))
+
+(defx8632archmacro ccl::hashed-by-identity (thing)
+  (let* ((typecode (gensym)))
+    `(let* ((,typecode (ccl::typecode ,thing)))
+       (declare (fixnum ,typecode))
+       (or
+	(= ,typecode x8632::tag-fixnum)
+	(= ,typecode x8632::tag-imm)
+	(= ,typecode x8632::subtag-symbol)
+	(= ,typecode x8632::subtag-instance)))))
+
+;;;
+(defx8632archmacro ccl::%get-kernel-global (name)
+  `(ccl::%fixnum-ref 0 (+ ,(ccl::target-nil-value)
+                        ,(%kernel-global
+                          (if (ccl::quoted-form-p name)
+                            (cadr name)
+                            name)))))
+
+(defx8632archmacro ccl::%get-kernel-global-ptr (name dest)
+  `(ccl::%setf-macptr
+    ,dest
+    (ccl::%fixnum-ref-macptr 0 (+ ,(ccl::target-nil-value)
+				  ,(%kernel-global
+				    (if (ccl::quoted-form-p name)
+				      (cadr name)
+				      name))))))
+
+(defx8632archmacro ccl::%target-kernel-global (name)
+  `(x8632::%kernel-global ,name))
+
+(defx8632archmacro ccl::lfun-vector (fun)
+  fun)
+
+(defx8632archmacro ccl::lfun-vector-lfun (lfv)
+  lfv)
+
+(defx8632archmacro ccl::area-code ()
+  area.code)
+
+(defx8632archmacro ccl::area-succ ()
+  area.succ)
+
+(defx8632archmacro ccl::nth-immediate (f i)
+  `(ccl::%nth-immediate ,f (the fixnum (- (the fixnum ,i) 1))))
+
+(defx8632archmacro ccl::set-nth-immediate (f i new)
+  `(ccl::%set-nth-immediate ,f (the fixnum (- (the fixnum ,i) 1)) ,new))
+
+(defx8632archmacro ccl::symptr->symvector (s)
+  s)
+
+(defx8632archmacro ccl::symvector->symptr (s)
+  s)
+
+(defx8632archmacro ccl::function-to-function-vector (f)
+  f)
+
+(defx8632archmacro ccl::function-vector-to-function (v)
+  v)
+
+(defx8632archmacro ccl::with-ffcall-results ((buf) &body body)
+  ;; Reserve space for eax,edx,st0 only.
+  (let* ((size (+ (* 2 4) (* 1 8))))
+    `(ccl::%stack-block ((,buf ,size :clear t))
+      ,@body)))
+
+;;; When found at a tagged return address, the instruction
+;;; (movl ($ imm32) (% fn))
+;;; lets the runtime easily map a return address to the containing
+;;; function.
+;;;
+;;; The notation ($ :self) is used in the assembler to mean "a 32-bit
+;;; immediate whose offset will be remembered in a table at the end of
+;;; the function object."
+;;;
+;;; Before the function is made executable (or when the GC moves the
+;;; function), these :self immediates are filled in with the actual
+;;; address of the function.
+
+(defconstant recover-fn-opcode-byte #b10111111) ;when %fn is %edi
+(defconstant recover-fn-address-offset 1)
+
+;;; For backtrace: the relative PC of an argument-check trap
+;;; must be less than or equal to this value.  (Because of
+;;; the way that we do "anchored" UUOs, it should always be =.)
+;;; (maybe not = on x8632)
+(defconstant arg-check-trap-pc-limit 7)
+
+(provide "X8632-ARCH")
Index: /branches/new-random/compiler/X86/X8632/x8632-backend.lisp
===================================================================
--- /branches/new-random/compiler/X86/X8632/x8632-backend.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/X8632/x8632-backend.lisp	(revision 13309)
@@ -0,0 +1,497 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "NXENV")
+  (require "X8632ENV"))
+
+(defvar *x8632-vinsn-templates* (make-hash-table :test #'eq))
+
+(defvar *known-x8632-backends* ())
+
+#+darwinx86-target
+(defvar *darwinx8632-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+                :lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+                :p2-dispatch *x862-specials*
+                :p2-vinsn-templates *x8632-vinsn-templates*
+                :p2-template-hash-name '*x8632-vinsn-templates*
+                :p2-compile 'x862-compile
+                :platform-syscall-mask (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) 
+                :target-specific-features
+                '(:x8632 :x86-target :darwin-target :darwinx86-target :x8632-target
+                  :darwinx8632-target
+                  :little-endian-target
+                  :32-bit-target)
+                :target-fasl-pathname (make-pathname :type "dx32fsl")
+                :target-platform (logior platform-cpu-x86
+                                         platform-os-darwin
+                                         platform-word-size-32)
+                :target-os :darwinx86
+                :name :darwinx8632
+                :target-arch-name :x8632
+                :target-foreign-type-data nil
+                :target-arch x8632::*x8632-target-arch*
+                :lisp-context-register x8632::fs
+		:num-arg-regs 2
+                ))
+
+
+#+darwinx86-target
+(pushnew *darwinx8632-backend* *known-x8632-backends* :key #'backend-name)
+
+#+linuxx86-target
+(defvar *linuxx8632-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+                :lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+                :p2-dispatch *x862-specials*
+                :p2-vinsn-templates *x8632-vinsn-templates*
+                :p2-template-hash-name '*x8632-vinsn-templates*
+                :p2-compile 'x862-compile
+                :platform-syscall-mask (logior platform-os-linux platform-cpu-x86 platform-word-size-32) 
+                :target-specific-features
+                '(:x8632 :x86-target :linux-target :linuxx86-target :x8632-target
+                  :linuxx8632-target
+                  :little-endian-target
+                  :32-bit-target)
+                :target-fasl-pathname (make-pathname :type "lx32fsl")
+                :target-platform (logior platform-cpu-x86
+                                         platform-os-linux
+                                         platform-word-size-32)
+                :target-os :linuxx86
+                :name :linuxx8632
+                :target-arch-name :x8632
+                :target-foreign-type-data nil
+                :target-arch x8632::*x8632-target-arch*
+                :lisp-context-register x8632::fs
+		:num-arg-regs 2
+                ))
+
+#+linuxx86-target
+(pushnew *linuxx8632-backend* *known-x8632-backends* :key #'backend-name)
+
+#+windows-target
+(defvar *win32-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+                :lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+                :p2-dispatch *x862-specials*
+                :p2-vinsn-templates *x8632-vinsn-templates*
+                :p2-template-hash-name '*x8632-vinsn-templates*
+                :p2-compile 'x862-compile
+                :platform-syscall-mask (logior platform-os-windows platform-cpu-x86 platform-word-size-32) 
+                :target-specific-features
+                '(:x8632 :x86-target :windows-target :win32-target :x8632-target
+                  :windowsx8632-target
+                  :little-endian-target
+                  :32-bit-target)
+                :target-fasl-pathname (make-pathname :type "wx32fsl")
+                :target-platform (logior platform-cpu-x86
+                                         platform-os-windows
+                                         platform-word-size-32)
+                :target-os :win32
+                :name :win32
+                :target-arch-name :x8632
+                :target-foreign-type-data nil
+                :target-arch x8632::*x8632-target-arch*
+                :lisp-context-register x8632::es
+		:num-arg-regs 2
+                ))
+
+#+windows-target
+(pushnew *win32-backend* *known-x8632-backends* :key #'backend-name)
+
+#+solaris-target
+(defvar *solaris-x8632-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+                :lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+                :p2-dispatch *x862-specials*
+                :p2-vinsn-templates *x8632-vinsn-templates*
+                :p2-template-hash-name '*x8632-vinsn-templates*
+                :p2-compile 'x862-compile
+                :platform-syscall-mask (logior platform-os-solaris platform-cpu-x86 platform-word-size-32) 
+                :target-specific-features
+                '(:x8632 :x86-target :solaris-target :x8632-target
+                  :solarisx8632-target
+                  :little-endian-target
+                  :32-bit-target)
+                :target-fasl-pathname (make-pathname :type "sx32fsl")
+                :target-platform (logior platform-cpu-x86
+                                         platform-os-solaris
+                                         platform-word-size-32)
+                :target-os :solarisx8632
+                :name :solarisx8632
+                :target-arch-name :x8632
+                :target-foreign-type-data nil
+                :target-arch x8632::*x8632-target-arch*
+                :lisp-context-register x8632::fs
+		:num-arg-regs 2
+                ))
+#+solaris-target
+(pushnew *solaris-x8632-backend* *known-x8632-backends* :key #'backend-name)
+
+#+freebsd-target
+(defvar *freebsd-x8632-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+                :lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+                :p2-dispatch *x862-specials*
+                :p2-vinsn-templates *x8632-vinsn-templates*
+                :p2-template-hash-name '*x8632-vinsn-templates*
+                :p2-compile 'x862-compile
+                :platform-syscall-mask (logior platform-os-freebsd platform-cpu-x86 platform-word-size-32) 
+                :target-specific-features
+                '(:x8632 :x86-target :freebsd-target :x8632-target
+                  :freebsdsx8632-target
+                  :little-endian-target
+                  :32-bit-target)
+                :target-fasl-pathname (make-pathname :type "fx32fsl")
+                :target-platform (logior platform-cpu-x86
+                                         platform-os-freebsd
+                                         platform-word-size-32)
+                :target-os :freebsdx8632
+                :name :freebsdx8632
+                :target-arch-name :x8632
+                :target-foreign-type-data nil
+                :target-arch x8632::*x8632-target-arch*
+                :lisp-context-register x8632::fs
+		:num-arg-regs 2
+                ))
+
+#+freebsd-target
+(pushnew *freebsd-x8632-backend* *known-x8632-backends* :key #'backend-name)
+
+(defvar *x8632-backend* (car *known-x8632-backends*))
+
+(defun fixup-x8632-backend ()
+  (dolist (b *known-x8632-backends*)
+    (setf #| (backend-lap-opcodes b) x86::*x86-opcodes* |#
+          (backend-p2-dispatch b) *x862-specials*
+          (backend-p2-vinsn-templates b)  *x8632-vinsn-templates*)
+    (or (backend-lap-macros b) (setf (backend-lap-macros b)
+                                     (make-hash-table :test #'equalp)))))
+
+
+(fixup-x8632-backend)
+
+#+x8632-target
+(setq *host-backend* *x8632-backend* *target-backend* *x8632-backend*)
+
+
+(defun setup-x8632-ftd (backend)
+  (or (backend-target-foreign-type-data backend)
+      (let* ((name (backend-name backend))
+             (ftd
+              (case name
+                (:darwinx8632
+                 (make-ftd :interface-db-directory "ccl:darwin-x86-headers;"
+			   :interface-package-name "X86-DARWIN32"
+                           :attributes '(:bits-per-word  32
+                                         :signed-char t
+                                         :struct-by-value t
+                                         :prepend-underscore t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-DARWIN32")
+			   :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-DARWIN32")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-DARWIN32")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-DARWIN32")))
+                (:linuxx8632
+                 (make-ftd :interface-db-directory "ccl:x86-headers;"
+			   :interface-package-name "X86-LINUX32"
+                           :attributes '(:bits-per-word  32
+                                         :signed-char nil
+                                         :struct-by-value t
+                                         :float-results-in-x87 t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-LINUX32")
+			   :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-LINUX32")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-LINUX32")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-LINUX32")))
+                (:win32
+                 (make-ftd :interface-db-directory "ccl:win32-headers;"
+			   :interface-package-name "WIN32"
+                           :attributes '(:bits-per-word  32
+                                         :signed-char nil
+                                         :struct-by-value t
+                                         :float-results-in-x87 t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "WIN32")
+			   :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "WIN32")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "WIN32")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "WIN32")))
+                (:solarisx8632
+                 (make-ftd :interface-db-directory "ccl:solarisx86-headers;"
+			   :interface-package-name "X86-SOLARIS32"
+                           :attributes '(:bits-per-word  32
+                                         :signed-char nil
+                                         :struct-by-value t
+                                         :float-results-in-x87 t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-SOLARIS32")
+			   :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-SOLARIS32")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-SOLARIS32")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-SOLARIS32")))
+                (:freebsdx8632
+                 (make-ftd :interface-db-directory "ccl:freebsd-headers;"
+			   :interface-package-name "X86-FREEBSD32"
+                           :attributes '(:bits-per-word  32
+                                         :signed-char nil
+                                         :struct-by-value t
+                                         :float-results-in-x87 t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-FREEBSD32")
+			   :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-FREEBSD32")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-FREEBSD32")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-FREEBSD32")))
+                )))
+        (install-standard-foreign-types ftd)
+        (use-interface-dir :libc ftd)
+        (setf (backend-target-foreign-type-data backend) ftd))))
+
+#-x8632-target
+(setup-x8632-ftd *x8632-backend*)
+
+(pushnew *x8632-backend* *known-backends* :key #'backend-name)
+
+;;; FFI stuff.  The vanilla i386 ABI always returns structures as a
+;;; hidden first argument.  Some systems (Darwin, FreeBSD) use a
+;;; variant that returns small (<= 64 bit) structures in registers.
+
+;;; A returned structure is passed as a hidden first argument.
+(defun x8632::record-type-returns-structure-as-first-arg (rtype)
+  (declare (ignore rtype))
+  t)
+
+;;; All arguments are passed on the stack.
+(defun x8632::expand-ff-call (callform args
+			      &key (arg-coerce #'null-coerce-foreign-arg)
+			      (result-coerce #'null-coerce-foreign-result))
+  (let* ((result-type-spec (or (car (last args)) :void))
+	 (struct-by-value-p nil)
+	 (result-op nil)
+	 (result-temp nil)
+	 (result-form nil))
+    (multiple-value-bind (result-type error)
+	(ignore-errors (parse-foreign-type result-type-spec))
+      (if error
+	(setq result-type-spec :void result-type *void-foreign-type*)
+	(setq args (butlast args)))
+      (collect ((argforms))
+	(when (typep result-type 'foreign-record-type)
+	  (setq result-form (pop args))
+	  (if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function
+			*target-ftd*) result-type)
+	    (progn
+	      (setq result-type *void-foreign-type*
+		    result-type-spec :void)
+	      (argforms :address)
+	      (argforms result-form))
+	    (progn
+	      (ecase (foreign-type-bits result-type)
+		(8 (setq result-type-spec :unsigned-byte
+			 result-op '%get-unsigned-byte))
+		(16 (setq result-type-spec :unsigned-halfword
+			  result-op '%get-unsigned-word))
+		(32 (setq result-type-spec :unsigned-fullword
+			  result-op '%get-unsigned-long))
+		(64 (setq result-type-spec :unsigned-doubleword
+			  result-op '%%get-unsigned-longlong)))
+	      (setq result-type (parse-foreign-type result-type-spec))
+	      (setq result-temp (gensym))
+	      (setq struct-by-value-p t))))
+	(unless (evenp (length args))
+	  (error "~s should be an even-length list of alternating foreign types and values" args))
+	(do* ((args args (cddr args)))
+	     ((null args))
+	  (let* ((arg-type-spec (car args))
+		 (arg-value-form (cadr args)))
+	    (if (or (member arg-type-spec *foreign-representation-type-keywords*
+			    :test #'eq)
+		    (typep arg-type-spec 'unsigned-byte))
+	      (progn
+		(argforms arg-type-spec)
+		(argforms arg-value-form))
+	      (let* ((ftype (parse-foreign-type arg-type-spec))
+                     (bits (ensure-foreign-type-bits ftype)))
+		(when (and (typep ftype 'foreign-record-type)
+			   (eq (foreign-record-type-kind ftype)
+			       :transparent-union))
+		  (ensure-foreign-type-bits ftype)
+		  (setq ftype (foreign-record-field-type
+			       (car (foreign-record-type-fields ftype)))
+			arg-type-spec (foreign-type-to-representation-type
+				       ftype)
+			bits (ensure-foreign-type-bits ftype)))
+		(if (typep ftype 'foreign-record-type)
+		  (argforms (ceiling bits 32))
+		  (argforms (foreign-type-to-representation-type ftype)))
+		(argforms (funcall arg-coerce arg-type-spec arg-value-form))))))
+	(argforms (foreign-type-to-representation-type result-type))
+	(let* ((call (funcall result-coerce result-type-spec
+			      `(,@callform ,@(argforms)))))
+	  (if struct-by-value-p
+	    `(let* ((,result-temp (%null-ptr)))
+	       (declare (dynamic-extent ,result-temp)
+			(type macptr ,result-temp))
+	       (%setf-macptr ,result-temp ,result-form)
+	       (setf (,result-op ,result-temp 0)
+		     ,call))
+	    call))))))
+
+;;; Return 8 values:
+;;; A list of RLET bindings
+;;; A list of LET* bindings
+;;; A list of DYNAMIC-EXTENT declarations for the LET* bindings
+;;; A list of initializaton forms for (some) structure args (not used on x8632)
+;;; A FOREIGN-TYPE representing the "actual" return type.
+;;; A form which can be used to initialize FP-ARGS-PTR, relative
+;;;  to STACK-PTR.  (not used on x8632)
+;;; The byte offset of the foreign return address, relative to STACK-PTR
+;;; The number of argument bytes pushed on the stack by the caller, or NIL
+;;;  if this can't be determined. (Only meaningful on Windows.)
+
+(defun x8632::generate-callback-bindings (stack-ptr fp-args-ptr argvars
+                                                    argspecs result-spec
+                                                    struct-result-name)
+  (declare (ignore fp-args-ptr))
+  (collect ((lets)
+	    (rlets)
+	    (dynamic-extent-names))
+    (let* ((rtype (parse-foreign-type result-spec)))
+      (when (typep rtype 'foreign-record-type)
+	(if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function
+		      *target-ftd*) rtype)
+	  (setq argvars (cons struct-result-name argvars)
+		argspecs (cons :address argspecs)
+		rtype *void-foreign-type*)
+	  (rlets (list struct-result-name (foreign-record-type-name rtype)))))
+      (do* ((argvars argvars (cdr argvars))
+	    (argspecs argspecs (cdr argspecs))
+	    (offset 8))
+	   ((null argvars)
+	    (values (rlets) (lets) (dynamic-extent-names) nil rtype nil 4
+		    (- offset 8)))
+	(let* ((name (car argvars))
+	       (spec (car argspecs))
+	       (argtype (parse-foreign-type spec))
+	       (bits (require-foreign-type-bits argtype))
+	       (double nil))
+	  (if (typep argtype 'foreign-record-type)
+            (let* ((form `(%inc-ptr ,stack-ptr
+                           ,(prog1 offset
+                                   (incf offset
+                                         (* 4 (ceiling bits 32)))))))
+              (when name (lets (list name form))))
+	    (let* ((form `(,
+                           (ecase (foreign-type-to-representation-type argtype)
+                             (:single-float '%get-single-float)
+                             (:double-float (setq double t) '%get-double-float)
+                             (:signed-doubleword (setq double t)
+                                                 '%%get-signed-longlong)
+                             (:signed-fullword '%get-signed-long)
+                             (:signed-halfword '%get-signed-word)
+                             (:signed-byte '%get-signed-byte)
+                             (:unsigned-doubleword (setq double t)
+                                                   '%%get-unsigned-longlong)
+                             (:unsigned-fullword '%get-unsigned-long)
+                             (:unsigned-halfword '%get-unsigned-word)
+                             (:unsigned-byte '%get-unsigned-byte)
+                             (:address '%get-ptr))
+                           ,stack-ptr
+                           ,offset)))
+	      (when name (lets (list name form)))
+	      (incf offset 4)
+	      (when double (incf offset 4)))))))))
+
+(defun x8632::generate-callback-return-value (stack-ptr fp-args-ptr result
+					      return-type struct-return-arg)
+  (declare (ignore fp-args-ptr))
+  (unless (eq return-type *void-foreign-type*)
+    (if (typep return-type 'foreign-record-type)
+      ;; If the struct result is returned via a hidden argument, the
+      ;; return type would have been mapped to :VOID.  On some
+      ;; systems, small (<= 64 bits) structs are returned by value,
+      ;; which we arrange to retrieve here.
+      (ecase (ensure-foreign-type-bits return-type)
+	(8 `(setf (%get-unsigned-byte ,stack-ptr -8)
+		  (%get-unsigned-byte ,struct-return-arg 0)))
+	(16 `(setf (%get-unsigned-word ,stack-ptr -8)
+		   (%get-unsigned-word ,struct-return-arg 0)))
+	(32 `(setf (%get-unsigned-long ,stack-ptr -8)
+		   (%get-unsigned-long ,struct-return-arg 0)))
+	(64 `(setf (%%get-unsigned-longlong ,stack-ptr -8)
+	       (%%get-unsigned-longlong ,struct-return-arg 0))))
+      (let* ((return-type-keyword (foreign-type-to-representation-type
+				   return-type)))
+        (collect ((forms))
+          (forms 'progn)
+          (case return-type-keyword
+            (:single-float
+             (forms `(setf (%get-unsigned-byte ,stack-ptr -16) 1)))
+            (:double-float
+             (forms `(setf (%get-unsigned-byte ,stack-ptr -16) 2))))
+          (forms
+           `(setf (,
+                   (case return-type-keyword
+                     (:address '%get-ptr)
+                     (:signed-doubleword '%%get-signed-longlong)
+                     (:unsigned-doubleword '%%get-unsigned-longlong)
+                     (:double-float '%get-double-float)
+                     (:single-float '%get-single-float)
+                     (:unsigned-fullword '%get-unsigned-long)
+                     (t '%get-signed-long)
+                     ) ,stack-ptr -8) ,result))
+          (forms))))))
+
+
+
+#+x8632-target
+(require "X8632-VINSNS")
+
+(provide "X8632-BACKEND")
+
Index: /branches/new-random/compiler/X86/X8632/x8632-vinsns.lisp
===================================================================
--- /branches/new-random/compiler/X86/X8632/x8632-vinsns.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/X8632/x8632-vinsns.lisp	(revision 13309)
@@ -0,0 +1,4153 @@
+;;;-*- Mode: Lisp; Package: (CCL :use CL) -*-
+
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "VINSN")
+  (require "X8632-BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "X8632ENV"))
+
+(defun unsigned-to-signed (u nbits)
+  (if (logbitp (1- nbits) u)
+    (- u (ash 1 nbits))
+    u))
+
+(defmacro define-x8632-vinsn (vinsn-name (results args &optional temps) &body body)
+  (%define-vinsn *x8632-backend* vinsn-name results args temps body))
+
+(define-x8632-vinsn scale-32bit-misc-index (((dest :u32))
+					    ((idx :imm)	; A fixnum
+					     )
+					    ())
+  (movl (:%l idx) (:%l dest)))
+
+(define-x8632-vinsn scale-16bit-misc-index (((dest :u32))
+					    ((idx :imm))) ; A fixnum
+  (movl (:%l idx) (:%l dest))
+  (shrl (:$ub 1) (:%l dest)))
+
+(define-x8632-vinsn scale-8bit-misc-index (((dest :u32))
+					    ((idx :imm))) ; A fixnum
+  (movl (:%l idx) (:%l dest))
+  (shrl (:$ub 2) (:%l dest)))
+
+;;; same as above, but looks better in bit vector contexts
+(define-x8632-vinsn scale-1bit-misc-index (((dest :u32))
+					    ((idx :imm))) ; A fixnum
+  (movl (:%l idx) (:%l dest))
+  (shrl (:$ub 2) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-u32 (((dest :u32))
+				  ((v :lisp)
+				   (scaled-idx :u32)))
+  (movl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-double-float  (((dest :double-float))
+                                            ((v :lisp)
+                                             (scaled-idx :imm)))
+  (movsd (:@ x8632::misc-dfloat-offset (:%l v) (:%l scaled-idx) 2) (:%xmm dest)))
+
+(define-x8632-vinsn misc-ref-c-double-float  (((dest :double-float))
+                                              ((v :lisp)
+					       (idx :s32const)))
+  (movsd (:@ (:apply + x8632::misc-dfloat-offset (:apply ash idx 3)) (:%l v)) (:%xmm dest)))
+
+(define-x8632-vinsn misc-ref-node  (((dest :lisp))
+                                    ((v :lisp)
+                                     (scaled-idx :imm)))
+  (movl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn (push-misc-ref-node :push :node :vsp) (()
+							   ((v :lisp)
+							    (scaled-idx :imm)))
+  (pushl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn misc-set-node (()
+				   ((val :lisp)
+				    (v :lisp)
+				    (unscaled-idx :imm))
+				   ())
+  (movl (:%l val) (:@ x8632::misc-data-offset (:%l v) (:%l unscaled-idx))))
+
+(define-x8632-vinsn misc-set-immediate-node (()
+                                             ((val :s32const)
+                                              (v :lisp)
+                                              (unscaled-idx :imm))
+                                             ())
+  (movl (:$l val) (:@ x8632::misc-data-offset (:%l v) (:%l unscaled-idx))))
+
+(define-x8632-vinsn misc-set-single-float (()
+					   ((val :single-float)
+					    (v :lisp)
+					    (scaled-idx :u32))
+					   ())
+  (movss (:%xmm val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn misc-set-double-float (()
+				   ((val :double-float)
+				    (v :lisp)
+				    (unscaled-idx :imm))
+				   ())
+  (movsd (:%xmm val) (:@ x8632::misc-dfloat-offset (:%l v) (:%l unscaled-idx) 2)))
+
+(define-x8632-vinsn misc-ref-u8 (((dest :u8))
+                                 ((v :lisp)
+                                  (scaled-idx :s32)))
+  (movzbl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-s8 (((dest :s8))
+                                 ((v :lisp)
+                                  (scaled-idx :s32)))
+  (movsbl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-c-u16 (((dest :u16))
+				    ((v :lisp)
+				     (idx :u32const)))
+  (movzwl (:@ (:apply + x8632::misc-data-offset (:apply ash idx 1)) (:%l v)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-c-s16 (((dest :s16))
+				    ((v :lisp)
+				     (idx :u32const)))
+  (movswl (:@ (:apply + x8632::misc-data-offset (:apply ash idx 1)) (:%l v)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-u16 (((dest :u16))
+                                  ((v :lisp)
+                                   (scaled-idx :s32)))
+  (movzwl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-u32 (((dest :u32))
+                                  ((v :lisp)
+                                   (scaled-idx :s32)))
+  (movl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-single-float (((dest :single-float))
+                                           ((v :lisp)
+                                            (scaled-idx :s32)))
+  (movss (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%xmm dest)))
+
+(define-x8632-vinsn misc-ref-s32 (((dest :s32))
+                                  ((v :lisp)
+                                   (scaled-idx :s32)))
+  (movl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-s16 (((dest :s16))
+                                  ((v :lisp)
+                                   (scaled-idx :s32)))
+  (movswl (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-c-node  (((dest :lisp))
+				     ((v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movl (:@ (:apply + x8632::misc-data-offset (:apply ash idx x8632::word-shift)) (:%l v)) (:%l dest)))
+
+(define-x8632-vinsn (push-misc-ref-c-node :push :node :vsp)
+    (()
+     ((v :lisp)
+      (idx :u32const)) ; sic
+     ())
+  (pushl (:@ (:apply + x8632::misc-data-offset (:apply ash idx x8632::word-shift)) (:%l v))))
+
+(define-x8632-vinsn misc-ref-c-u32  (((dest :u32))
+				     ((v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  ;; xxx - should the 2 be x8632::word-shift?
+  (movl (:@ (:apply + x8632::misc-data-offset (:apply ash idx 2)) (:%l v)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-c-s32  (((dest :s32))
+				     ((v :lisp)
+				      (idx :s32const)) ; sic
+				     ())
+  (movl (:@ (:apply + x8632::misc-data-offset (:apply ash idx x8632::word-shift)) (:%l v)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-c-single-float  (((dest :single-float))
+                                              ((v :lisp)
+                                               (idx :s32const)) ; sic
+                                              ())
+  (movss (:@ (:apply + x8632::misc-data-offset (:apply ash idx x8632::word-shift)) (:%l v)) (:%xmm dest)))
+
+(define-x8632-vinsn misc-ref-c-u8  (((dest :u32))
+				     ((v :lisp)
+				      (idx :s32const)) ; sic
+				     ())
+  (movzbl (:@ (:apply + x8632::misc-data-offset idx) (:%l v)) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-c-s8  (((dest :s32))
+				     ((v :lisp)
+				      (idx :s32const)) ; sic
+				     ())
+  (movsbl (:@ (:apply + x8632::misc-data-offset idx) (:%l v)) (:%l dest)))
+
+(define-x8632-vinsn misc-set-c-s8  (((val :s8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (movb (:%b val) (:@ (:apply + x8632::misc-data-offset idx) (:%l v))))
+
+(define-x8632-vinsn misc-set-s8  (((val :s8))
+				  ((v :lisp)
+				   (scaled-idx :s32))
+				  ())
+  (movb (:%b val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn mem-ref-s8 (((dest :s8))
+				((src :address)
+				 (index :s32)))
+  (movsbl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn misc-set-c-node (()
+				     ((val :lisp)
+				      (v :lisp)
+				     (idx :s32const)))
+  (movl (:%l val) (:@ (:apply + x8632::misc-data-offset (:apply ash idx 2)) (:%l v))))
+
+(define-x8632-vinsn misc-set-immediate-c-node (()
+                                               ((val :s32const)
+                                                (v :lisp)
+                                                (idx :s32const)))
+  (movl (:$l val) (:@ (:apply + x8632::misc-data-offset (:apply ash idx 2)) (:%l v))))
+
+;;; xxx don't know if this is right
+(define-x8632-vinsn set-closure-forward-reference (()
+                                                   ((val :lisp)
+                                                    (closure :lisp)
+                                                    (idx :s32const)))
+  (movl (:%l val) (:@ (:apply + x8632::misc-data-offset (:apply ash idx x8632::word-shift)) (:%l closure))))
+
+(define-x8632-vinsn misc-set-c-double-float (()
+				    ((val :double-float)
+				     (v :lisp)
+				     (idx :s32const)))
+  (movsd (:%xmm val) (:@ (:apply + x8632::misc-dfloat-offset (:apply ash idx 3)) (:%l v))))
+
+(define-x8632-vinsn (call-known-symbol :call) (((result (:lisp x8632::arg_z)))
+                                               ()
+					       ((entry (:label 1))))
+  (:talign x8632::fulltag-tra)
+  (call (:@ x8632::symbol.fcell (:% x8632::fname)))
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn (jump-known-symbol :jumplr) (()
+                                                 ())
+
+  (jmp (:@ x8632::symbol.fcell (:% x8632::fname))))
+
+(define-x8632-vinsn set-nargs (()
+			       ((n :u16const)))
+  ((:pred = n 0)
+   (xorl (:%l x8632::nargs) (:%l x8632::nargs)))
+  ((:not (:pred = n 0))
+   (movl (:$l (:apply ash n x8632::fixnumshift)) (:%l x8632::nargs))))
+
+(define-x8632-vinsn check-exact-nargs (()
+                                       ((n :u16const)))
+  :resume
+  ((:pred = n 0)
+   (testl (:%l x8632::nargs) (:%l x8632::nargs)))
+  ((:and (:pred > n 0) (:pred < n 32))
+   (cmpl (:$b (:apply ash n x8632::fixnumshift)) (:%l x8632::nargs)))
+  ((:pred >= n 32)
+   (cmpl (:$l (:apply ash n x8632::fixnumshift)) (:%l x8632::nargs)))
+  (jne :bad)
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-wrong-number-of-args)))
+
+(define-x8632-vinsn check-min-nargs (()
+				     ((min :u16const)))
+  :resume
+  ((:pred = min 1)
+   (testl (:%l x8632::nargs) (:%l x8632::nargs))
+   (je :toofew))
+  ((:not (:pred = min 1))
+   ((:and (:pred > min 1) (:pred < min 32))
+    (rcmpl (:%l x8632::nargs) (:$b (:apply ash min x8632::fixnumshift))))
+   ((:pred >= min 32)
+    (rcmpl (:%l x8632::nargs) (:$l (:apply ash min x8632::fixnumshift))))
+   (jb :toofew))
+  (:anchored-uuo-section :resume)
+  :toofew
+  (:anchored-uuo (uuo-error-too-few-args)))
+
+(define-x8632-vinsn check-max-nargs (()
+				     ((n :u16const)))
+  :resume
+  ((:pred < n 32)
+   (rcmpl (:%l x8632::nargs) (:$b (:apply ash n x8632::fixnumshift))))
+  ((:pred >= n 32)
+   (rcmpl (:%l x8632::nargs) (:$l (:apply ash n x8632::fixnumshift))))
+  (ja :bad)
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-too-many-args)))
+
+(define-x8632-vinsn check-min-max-nargs (()
+                                         ((min :u16const)
+                                          (max :u16)))
+  :resume
+  ((:pred = min 1)
+   (testl (:%l x8632::nargs) (:%l x8632::nargs))
+   (je :toofew))
+  ((:not (:pred = min 1))
+   ((:pred < min 32)
+    (rcmpl (:%l x8632::nargs) (:$b (:apply ash min x8632::word-shift))))
+   ((:pred >= min 32)
+    (rcmpl (:%l x8632::nargs) (:$l (:apply ash min x8632::word-shift))))
+   (jb :toofew))
+  ((:pred < max 32)
+   (rcmpl (:%l x8632::nargs) (:$b (:apply ash max x8632::word-shift))))
+  ((:pred >= max 32)
+   (rcmpl (:%l x8632::nargs) (:$l (:apply ash max x8632::word-shift))))
+  (ja :toomany)
+  
+  (:anchored-uuo-section :resume)
+  :toofew
+  (:anchored-uuo (uuo-error-too-few-args))
+  (:anchored-uuo-section :resume)
+  :toomany
+  (:anchored-uuo (uuo-error-too-many-args)))
+
+(define-x8632-vinsn default-1-arg (()
+                                   ((min :u16const)))
+  ((:pred < min 32)
+   (rcmpl (:%l x8632::nargs) (:$b (:apply ash min x8632::fixnumshift))))
+  ((:pred >= min 32)
+   (rcmpl (:%l x8632::nargs) (:$l (:apply ash min x8632::fixnumshift))))
+  (jne :done)
+  ((:pred >= min 2)
+   (pushl (:%l x8632::arg_y)))
+  ((:pred >= min 1)
+   (movl (:%l x8632::arg_z) (:%l x8632::arg_y)))
+  (movl (:$l (:apply target-nil-value)) (:%l x8632::arg_z))
+  :done)
+
+(define-x8632-vinsn default-2-args (()
+				    ((min :u16const)))
+  ((:pred < (:apply 1+ min) 32)
+   (rcmpl (:%l x8632::nargs) (:$b (:apply ash (:apply 1+ min) x8632::fixnumshift))))
+  ((:pred >= (:apply 1+ min) 32)
+   (rcmpl (:%l x8632::nargs) (:$l (:apply ash (:apply 1+ min) x8632::fixnumshift))))
+  (ja :done)
+  (je :one)
+  ;; We got "min" args; arg_y & arg_z default to nil
+  ((:pred >= min 2)
+   (pushl (:%l x8632::arg_y)))
+  ((:pred >= min 1)
+   (pushl (:%l x8632::arg_z)))
+  (movl (:$l (:apply target-nil-value)) (:%l x8632::arg_y))
+  (jmp :last)
+  :one
+  ;; We got min+1 args: arg_y was supplied, arg_z defaults to nil.
+  ((:pred >= min 1)
+   (pushl (:%l x8632::arg_y)))
+  (movl (:%l x8632::arg_z) (:%l x8632::arg_y))
+  :last
+  (movl (:$l (:apply target-nil-value)) (:%l x8632::arg_z))
+  :done)
+
+(define-x8632-vinsn default-optionals (()
+                                       ((n :u16const))
+                                       ((temp :u32)
+					(nargs (:lisp #.x8632::nargs))))
+  (movl (:%l x8632::nargs) (:%l temp))
+  ((:pred < n 32)
+   (rcmpl (:%l x8632::nargs) (:$b (:apply ash n x8632::fixnumshift))))
+  ((:pred >= n 32)
+   (rcmpl (:%l x8632::nargs) (:$l (:apply ash n x8632::fixnumshift))))
+  (jae :done)
+  :loop
+  (addl (:$b x8632::fixnumone) (:%l temp))
+  (pushl (:$l (:apply target-nil-value)))
+  ((:pred < n 32)
+   (cmpl (:$b (:apply ash n x8632::fixnumshift)) (:%l temp)))
+  ((:pred >= n 32)
+   (cmpl (:$l (:apply ash n x8632::fixnumshift)) (:%l temp)))
+  (jne :loop)
+  :done)
+
+(define-x8632-vinsn save-lisp-context-no-stack-args (()
+                                                     ())
+  (pushl (:%l x8632::ebp))
+  (movl (:%l x8632::esp) (:%l x8632::ebp)))
+
+(define-x8632-vinsn save-lisp-context-offset (()
+					      ((nbytes-pushed :s32const)))
+  (movl (:%l x8632::ebp) (:@ (:apply + nbytes-pushed x8632::node-size) (:%l x8632::esp)))
+  (leal (:@ (:apply + nbytes-pushed x8632::node-size) (:%l x8632::esp)) (:%l x8632::ebp))
+  (popl  (:@ x8632::node-size (:%l x8632::ebp))))
+
+(define-x8632-vinsn save-lisp-context-variable-arg-count (()
+                                                          ()
+                                                          ((temp :u32)
+							   (nargs (:lisp #.x8632::nargs))))
+  (movl (:%l x8632::nargs) (:%l temp))
+  (subl (:$b (* $numx8632argregs x8632::node-size)) (:%l temp))
+  (jle :push)
+  (movl (:%l x8632::ebp) (:@ x8632::node-size (:%l x8632::esp) (:%l temp)))
+  (leal (:@ x8632::node-size (:%l x8632::esp) (:%l temp)) (:%l x8632::ebp))
+  (popl (:@ x8632::node-size (:%l x8632::ebp)))
+  (jmp :done)
+  :push
+  (pushl (:%l x8632::ebp))
+  (movl (:%l x8632::esp) (:%l x8632::ebp))
+  :done)
+
+;;; We know that some args were pushed, but don't know how many were
+;;; passed.
+(define-x8632-vinsn save-lisp-context-in-frame (()
+                                                ()
+                                                ((temp :u32)
+						 (nargs (:lisp #.x8632::nargs))))
+  (movl (:%l x8632::nargs) (:%l temp))
+  (subl (:$b (* $numx8632argregs x8632::node-size)) (:%l temp))
+  (movl (:%l x8632::ebp) (:@ x8632::node-size (:%l x8632::esp) (:%l temp)))
+  (leal (:@ x8632::node-size (:%l x8632::esp) (:%l temp)) (:%l x8632::ebp))
+  (popl  (:@ x8632::node-size (:%l x8632::ebp))))
+
+(define-x8632-vinsn (vpush-register :push :node :vsp)
+    (()
+     ((reg :lisp)))
+  (pushl (:% reg)))
+
+(define-x8632-vinsn (vpush-fixnum :push :node :vsp)
+    (()
+     ((const :s32const)))
+  ((:and  (:pred < const 128) (:pred >= const -128))
+   (pushl (:$b const)))
+  ((:not (:and  (:pred < const 128) (:pred >= const -128)))
+   (pushl (:$l const))))
+
+(define-x8632-vinsn vframe-load (((dest :lisp))
+				 ((frame-offset :u16const)
+				  (cur-vsp :u16const)))
+  (movl (:@ (:apply - (:apply + frame-offset x8632::word-size-in-bytes)) (:%l x8632::ebp)) (:%l dest)))
+
+(define-x8632-vinsn compare-vframe-offset-to-nil (()
+                                                  ((frame-offset :u16const)
+                                                   (cur-vsp :u16const)))
+  (cmpl (:$l (:apply target-nil-value)) (:@ (:apply - (:apply + frame-offset x8632::word-size-in-bytes)) (:%l x8632::ebp))))
+
+(define-x8632-vinsn compare-value-cell-to-nil (()
+                                               ((vcell :lisp)))
+  (cmpl (:$l (:apply target-nil-value)) (:@ x8632::value-cell.value (:%l vcell))))
+
+(define-x8632-vinsn lcell-load (((dest :lisp))
+				((cell :lcell)
+				 (top :lcell)))
+  (movl (:@ (:apply - (:apply + (:apply calc-lcell-offset cell) x8632::word-size-in-bytes)) (:%l x8632::ebp)) (:%l dest)))
+
+(define-x8632-vinsn (vframe-push :push :node :vsp)
+    (()
+     ((frame-offset :u16const)
+      (cur-vsp :u16const)))
+  (pushl (:@ (:apply - (:apply + frame-offset x8632::word-size-in-bytes)) (:%l x8632::ebp))))
+
+(define-x8632-vinsn vframe-store (()
+				  ((src :lisp)
+				   (frame-offset :u16const)
+				   (cur-vsp :u16const)))
+  (movl (:%l src) (:@ (:apply - (:apply + frame-offset x8632::word-size-in-bytes)) (:%l x8632::ebp))))
+
+(define-x8632-vinsn lcell-store (()
+				 ((src :lisp)
+				  (cell :lcell)
+				  (top :lcell)))
+  (movl (:%l src) (:@ (:apply - (:apply + (:apply calc-lcell-offset cell) x8632::word-size-in-bytes)) (:%l x8632::ebp))))
+        
+(define-x8632-vinsn (popj :lispcontext :pop :csp :lrRestore :jumpLR)
+    (()
+     ())
+  (leave)
+  (ret))
+
+(define-x8632-vinsn (restore-full-lisp-context :lispcontext :pop :vsp )
+    (()
+     ())
+  (leave))
+
+(define-x8632-vinsn compare-to-nil (()
+                                    ((arg0 t)))
+  (cmpl (:$l (:apply target-nil-value)) (:%l arg0)))
+
+(define-x8632-vinsn compare-to-t (()
+				  ((arg0 t)))
+  (cmpl (:$l (:apply target-t-value)) (:%l arg0)))
+
+(define-x8632-vinsn ref-constant (((dest :lisp))
+                                  ((lab :label)))
+  (movl (:@ (:^ lab) (:%l x8632::fn)) (:%l dest)))
+
+(define-x8632-vinsn compare-constant-to-register (()
+                                                  ((lab :label)
+                                                   (reg :lisp)))
+  (cmpl (:@ (:^ lab) (:%l x8632::fn)) (:%l reg)))
+
+(define-x8632-vinsn (vpush-constant :push :node :vsp) (()
+                                                       ((lab :label)))
+  (pushl (:@ (:^ lab) (:%l x8632::fn))))
+
+(define-x8632-vinsn (jump :jump)
+    (()
+     ((label :label)))
+  (jmp label))
+
+(define-x8632-vinsn (cbranch-true :branch) (()
+					    ((label :label)
+					     (crbit :u8const)))
+  (jcc (:$ub crbit) label))
+
+(define-x8632-vinsn (cbranch-false :branch) (()
+					     ((label :label)
+					      (crbit :u8const)))
+  (jcc (:$ub (:apply logxor 1 crbit)) label))
+
+(define-x8632-vinsn (lri :constant-ref) (((dest :imm))
+                                         ((intval :s32const))
+                                         ())
+  ((:pred = intval 0)
+   (xorl (:%l dest) (:%l dest)))
+  ((:not (:pred = intval 0))
+   (movl (:$l intval) (:%l dest))))
+
+(define-x8632-vinsn (lriu :constant-ref) (((dest :imm))
+                                         ((intval :u32const))
+                                         ())
+  ((:pred = intval 0)
+   (xorl (:%l dest) (:%l dest)))
+  ((:not (:pred = intval 0))
+   (movl (:$l intval) (:%l dest))))
+
+;;; In the following trap/branch-unless vinsns, it might be worth
+;;; trying to use byte instructions when the args are known to be
+;;; accessible as byte regs.  It also might be possible to
+;;; special-case eax/ax/al.
+
+(define-x8632-vinsn trap-unless-bit (()
+                                     ((value :lisp)))
+  :resume
+  (testl (:$l (lognot x8632::fixnumone)) (:%l value))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l value) (:$ub arch::error-object-not-bit))))
+
+;;; note that NIL is just a distinguished CONS.
+;;; the tag formerly known as fulltag-nil is now
+;;; for tagged return addresses.
+(define-x8632-vinsn trap-unless-list (()
+				      ((object :lisp))
+				      ((tag :u8)))
+  :resume
+  (movl (:% object) (:% tag))
+  (andl (:$b x8632::fulltagmask) (:% tag))
+  (cmpl (:$b x8632::fulltag-cons) (:% tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad  
+  (:anchored-uuo (uuo-error-reg-not-list (:%l object))))
+
+(define-x8632-vinsn trap-unless-cons (()
+				      ((object :lisp))
+				      ((tag :u8)))
+  ;; special check for NIL (which is a distinguished CONS on x8632)
+  :resume
+  (cmpl (:$l (:apply target-nil-value)) (:%l object))
+  (je :bad)
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::fulltagmask) (:%l tag))
+  (cmpl (:$b x8632::fulltag-cons) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%l object) (:$ub x8632::fulltag-cons))))
+
+(define-x8632-vinsn set-z-flag-if-consp (()
+					 ((object :lisp))
+					 ((tag (:u32 #.x8632::imm0))))
+  (movl (:%l object) (:%accl tag))
+  (andl (:$b x8632::fulltagmask) (:%accl tag))
+  (cmpb (:$b x8632::fulltag-cons) (:%accb tag))
+  (setne (:%b x8632::ah))
+  (cmpl (:$l (:apply target-nil-value)) (:% object))
+  (sete (:%b x8632::al))
+  (orb (:%b x8632::ah) (:%b x8632::al)))
+
+(define-x8632-vinsn trap-unless-uvector (()
+                                         ((object :lisp))
+                                         ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%l object) (:$ub x8632::tag-misc))))
+
+(define-x8632-vinsn trap-unless-character (()
+					   ((object :lisp))
+					   ((tag :u8)))
+  ;; xxx can't be sure that object will be in a byte-accessible register
+  :resume
+  (movl (:%l object) (:%l tag))
+  (cmpb (:$b x8632::subtag-character) (:%b tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo(uuo-error-reg-not-tag (:%l object) (:$ub x8632::subtag-character))))
+
+(define-x8632-vinsn trap-unless-fixnum (()
+                                        ((object :lisp))
+                                        ())
+  :resume
+  (testl (:$l x8632::tagmask) (:%l object))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-fixnum (:%l object))))
+
+(define-x8632-vinsn set-flags-from-lisptag (()
+                                            ((reg :lisp)))
+  (testl (:$l x8632::tagmask) (:%l reg)))
+
+(define-x8632-vinsn trap-unless-typecode= (()
+					   ((object :lisp)
+					    (tagval :u8const))
+					   ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  ((:pred = (:apply %hard-regspec-value tag) x8632::eax)
+   ;; accumulator
+   (andl (:$b x8632::tagmask) (:%accl tag))
+   (cmpl (:$b x8632::tag-misc) (:%accl tag)))
+  ((:pred > (:apply %hard-regspec-value tag) x8632::eax)
+   (andl (:$b x8632::tagmask) (:%l tag))
+   (cmpl (:$b x8632::tag-misc) (:%l tag)))
+  (jne :have-tag)
+  ;; This needs to be a sign-extending mov, since the cmpl below
+  ;; will sign-extend the 8-bit constant operand.
+  (movsbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l tag))
+  :have-tag
+  (cmpl (:$b tagval) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%l object) (:$ub tagval))))
+
+(define-x8632-vinsn trap-unless-single-float (()
+                                              ((object :lisp))
+                                              ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l tag))
+  (cmpl (:$b x8632::subtag-single-float) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%l object) (:$ub x8632::subtag-single-float))))
+
+(define-x8632-vinsn trap-unless-double-float (()
+                                              ((object :lisp))
+                                              ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l tag))
+  (cmpl (:$b x8632::subtag-double-float) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%l object) (:$ub x8632::subtag-double-float))))
+
+(define-x8632-vinsn trap-unless-macptr (()
+                                        ((object :lisp))
+                                        ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l tag))
+  :have-tag
+  (cmpl (:$b x8632::subtag-macptr) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%l object) (:$ub x8632::subtag-macptr))))
+
+(define-x8632-vinsn check-misc-bound (()
+				      ((idx :imm)
+				       (v :lisp))
+				      ((temp :u32)))
+  :resume
+  (movl (:@ x8632::misc-header-offset (:%l v)) (:%l temp))
+  ((:and (:pred >= (:apply %hard-regspec-value temp) x8632::eax)
+	 (:pred <= (:apply %hard-regspec-value temp) x8632::ebx))
+   (xorb (:%b temp) (:%b temp))
+   (shrl (:$ub (- x8632::num-subtag-bits x8632::fixnumshift)) (:%l temp)))
+  ((:pred > (:apply %hard-regspec-value temp) x8632::ebx)
+   (shrl (:$ub x8632::num-subtag-bits) (:%l temp))
+   (shll (:$ub x8632::fixnumshift) (:%l temp)))
+  (rcmpl (:%l idx) (:%l temp))
+  (jae :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-vector-bounds (:%l idx) (:%l v))))
+
+(define-x8632-vinsn %cdr (((dest :lisp))
+			  ((src :lisp)))
+  (movl (:@ x8632::cons.cdr (:%l src)) (:%l dest)))
+
+(define-x8632-vinsn (%vpush-cdr :push :node :vsp)
+    (()
+     ((src :lisp)))
+  (pushl (:@ x8632::cons.cdr (:%l src))))
+
+(define-x8632-vinsn %car (((dest :lisp))
+			  ((src :lisp)))
+  (movl (:@ x8632::cons.car (:%l src)) (:%l dest)))
+
+(define-x8632-vinsn (%vpush-car :push :node :vsp)
+    (()
+     ((src :lisp)))
+  (pushl (:@ x8632::cons.car (:%l src))))
+
+(define-x8632-vinsn u32->char (((dest :lisp)
+                               (src :u8))
+			      ((src :u8))
+			      ())
+  (shll (:$ub x8632::charcode-shift) (:%l src))
+  (leal (:@ x8632::subtag-character (:%l src)) (:%l dest)))
+
+(define-x8632-vinsn (load-nil :constant-ref) (((dest t))
+					      ())
+  (movl (:$l (:apply target-nil-value)) (:%l dest)))
+
+
+(define-x8632-vinsn (load-t :constant-ref) (((dest t))
+					    ())
+  (movl (:$l (:apply target-t-value)) (:%l dest)))
+
+(define-x8632-vinsn extract-tag (((tag :u8))
+                                 ((object :lisp)))
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag)))
+
+(define-x8632-vinsn extract-tag-fixnum (((tag :imm))
+					((object :lisp)))
+  (leal (:@ (:%l object) 4) (:%l tag))
+  (andl (:$b (ash x8632::tagmask x8632::fixnumshift)) (:%l tag)))
+
+(define-x8632-vinsn extract-fulltag (((tag :u8))
+                                 ((object :lisp)))
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::fulltagmask) (:%l tag)))
+
+(define-x8632-vinsn extract-fulltag-fixnum (((tag :imm))
+                                            ((object :lisp)))
+  ((:pred =
+	  (:apply %hard-regspec-value tag)
+	  (:apply %hard-regspec-value object))
+   (shll (:$ub x8632::fixnumshift) (:%l object)))
+  ((:not (:pred =
+		(:apply %hard-regspec-value tag)
+		(:apply %hard-regspec-value object)))
+   (imull (:$b x8632::fixnumone) (:%l object) (:%l tag)))
+  (andl (:$b (ash x8632::fulltagmask x8632::fixnumshift)) (:%l tag)))
+
+(define-x8632-vinsn extract-typecode (((tag :u32))
+                                      ((object :lisp)))
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l tag))
+  :have-tag)
+
+(define-x8632-vinsn extract-typecode-fixnum (((tag :imm))
+                                             ((object :lisp))
+                                             ((temp :u32)))
+  (movl (:%l object) (:%l temp))
+  (andl (:$b x8632::tagmask) (:%l temp))
+  (cmpl (:$b x8632::tag-misc) (:%l temp))
+  (jne :have-tag)
+  (movzbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l temp))
+  :have-tag
+  (leal (:@ (:%l temp) 4) (:%l tag)))
+
+(define-x8632-vinsn compare-reg-to-zero (()
+                                         ((reg :imm)))
+  (testl (:%l reg) (:%l reg)))
+
+;;; life will be sad if reg isn't byte accessible
+(define-x8632-vinsn compare-u8-reg-to-zero (()
+                                            ((reg :u8)))
+  (testb (:%b reg) (:%b reg)))
+
+(define-x8632-vinsn cr-bit->boolean (((dest :lisp))
+                                     ((crbit :u8const))
+                                     ((temp :u32)))
+  (movl (:$l (:apply target-t-value)) (:%l temp))
+  (leal (:@ (- x8632::t-offset) (:%l temp)) (:%l dest))
+  (cmovccl (:$ub crbit) (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn compare-s32-constant (()
+                                            ((val :imm)
+                                             (const :s32const)))
+  ((:or  (:pred < const -128) (:pred > const 127))
+   (rcmpl (:%l val) (:$l const)))
+  ((:not (:or  (:pred < const -128) (:pred > const 127)))
+   (rcmpl (:%l val) (:$b const))))
+
+(define-x8632-vinsn compare-u31-constant (()
+                                          ((val :u32)
+                                           (const :u32const)))
+  ((:pred > const 127)
+   (rcmpl (:%l val) (:$l const)))
+  ((:not (:pred > const 127))
+   (rcmpl (:%l val) (:$b const))))
+
+(define-x8632-vinsn compare-u8-constant (()
+                                         ((val :u8)
+                                          (const :u8const)))
+  ((:pred = (:apply %hard-regspec-value val) x8632::eax)
+   (rcmpb (:%accb val) (:$b const)))
+  ((:and (:pred > (:apply %hard-regspec-value val) x8632::eax)
+	 (:pred <= (:apply %hard-regspec-value val) x8632::ebx))
+   (rcmpb (:%b val) (:$b const)))
+  ((:pred > (:apply %hard-regspec-value val) x8632::ebx)
+   (rcmpl (:%l val) (:$l const)))
+  )
+
+(define-x8632-vinsn cons (((dest :lisp))
+                          ((car :lisp)
+                           (cdr :lisp))
+			  ((allocptr (:lisp #.x8632::allocptr))))
+  (subl (:$b (- x8632::cons.size x8632::fulltag-cons)) (:@ (:%seg :rcontext) x8632::tcr.save-allocptr))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.save-allocptr) (:%l x8632::allocptr))
+  (rcmpl (:%l x8632::allocptr) (:@ (:%seg :rcontext) x8632::tcr.save-allocbase))
+  (ja :no-trap)
+  (uuo-alloc)
+  :no-trap
+  (andb (:$b (lognot x8632::fulltagmask)) (:@ (:%seg :rcontext) x8632::tcr.save-allocptr))
+  (movl (:%l car) (:@ x8632::cons.car (:%l x8632::allocptr)))
+  (movl (:%l cdr) (:@ x8632::cons.cdr (:%l x8632::allocptr)))
+  (movl (:%l x8632::allocptr) (:%l dest)))
+
+(define-x8632-vinsn unbox-u8 (((dest :u8))
+			      ((src :lisp)))
+  :resume
+  (movl (:$l (lognot (ash #xff x8632::fixnumshift))) (:%l dest))
+  (andl (:% src) (:% dest))
+  (jne :bad)
+  (movl (:%l src) (:%l dest))
+  (shrl (:$ub x8632::fixnumshift) (:%l dest))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l src) (:$ub arch::error-object-not-unsigned-byte-8))))
+
+(define-x8632-vinsn %unbox-u8 (((dest :u8))
+			      ((src :lisp)))
+  (movl (:%l src) (:%l dest))
+  (shrl (:$ub x8632::fixnumshift) (:%l dest))
+  (andl (:$l #xff) (:%l dest)))
+
+(define-x8632-vinsn unbox-s8 (((dest :s8))
+			      ((src :lisp)))
+  :resume
+  (movl (:%l src) (:%l dest))
+  (shll (:$ub (- x8632::nbits-in-word (+ 8 x8632::fixnumshift))) (:%l dest))
+  (sarl (:$ub (- x8632::nbits-in-word (+ 8 x8632::fixnumshift))) (:%l dest))
+  (cmpl (:%l src) (:%l dest))
+  (jne :bad)
+  (testl (:$l x8632::fixnummask) (:%l dest))
+  (jne :bad)
+  (sarl (:$ub x8632::fixnumshift) (:%l dest))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l src) (:$ub arch::error-object-not-signed-byte-8))))
+
+(define-x8632-vinsn unbox-u16 (((dest :u16))
+			      ((src :lisp)))
+  :resume
+  (testl (:$l (lognot (ash #xffff x8632::fixnumshift))) (:% src))
+  (movl (:%l src) (:%l dest))
+  (jne :bad)
+  (shrl (:$ub x8632::fixnumshift) (:%l dest))
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l src) (:$ub arch::error-object-not-unsigned-byte-16))))
+
+(define-x8632-vinsn %unbox-u16 (((dest :u16))
+			      ((src :lisp)))
+  (movl (:%l src) (:%l dest))
+  (shrl (:$ub x8632::fixnumshift) (:%l dest)))
+
+(define-x8632-vinsn unbox-s16 (((dest :s16))
+			      ((src :lisp)))
+  :resume
+  (movl (:%l src) (:%l dest))
+  (shll (:$ub (- x8632::nbits-in-word (+ 16 x8632::fixnumshift))) (:%l dest))
+  (sarl (:$ub (- x8632::nbits-in-word (+ 16 x8632::fixnumshift))) (:%l dest))
+  (cmpl (:%l src) (:%l dest))
+  (jne :bad)
+  (testl (:$l x8632::fixnummask) (:%l dest))
+  (jne :bad)
+  (sarl (:$ub x8632::fixnumshift) (:%l dest))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l src) (:$ub arch::error-object-not-signed-byte-16))))
+
+(define-x8632-vinsn %unbox-s16 (((dest :s16))
+                                ((src :lisp)))
+  (movl (:%l src) (:%l dest))
+  (sarl (:$ub x8632::fixnumshift) (:%l dest)))
+
+;;; An object is of type (UNSIGNED-BYTE 32) iff
+;;;  a) it's of type (UNSIGNED-BYTE 30) (e.g., an unsigned fixnum)
+;;;  b) it's a bignum of length 1 and the 0'th digit is positive
+;;;  c) it's a bignum of length 2 and the sign-digit is 0.
+(define-x8632-vinsn unbox-u32 (((dest :u32))
+                               ((src :lisp)))
+  :resume
+  (movl (:$l (lognot (ash x8632::target-most-positive-fixnum x8632::fixnumshift))) (:%l dest))
+  (testl (:%l dest) (:%l src))
+  (movl (:%l src) (:%l dest))
+  (jnz :maybe-bignum)
+  (sarl (:$ub x8632::fixnumshift) (:%l dest))
+  (jmp :done)
+  :maybe-bignum
+  (andl (:$b x8632::tagmask) (:%l dest))
+  (cmpl (:$b x8632::tag-misc) (:%l dest))
+  (jne :bad)
+  (movl (:@ x8632::misc-header-offset (:%l src)) (:%l dest))
+  (cmpl (:$l x8632::two-digit-bignum-header) (:%l dest))
+  (je :two)
+  (cmpl (:$l x8632::one-digit-bignum-header) (:%l dest))
+  (jne :bad)
+  (movl (:@ x8632::misc-data-offset (:%l src)) (:%l dest))
+  (testl (:%l dest) (:%l dest))
+  (js :bad)
+  (jmp :done)
+  :two
+  (movl (:@ (+ 4 x8632::misc-data-offset) (:%l src)) (:%l dest))
+  (testl (:%l dest) (:%l dest))
+  (jne :bad)
+  (movl (:@ x8632::misc-data-offset (:%l src)) (:%l dest))
+  :done
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l src) (:$ub arch::error-object-not-unsigned-byte-32))))
+
+;;; an object is of type (SIGNED-BYTE 32) iff
+;;; a) it's a fixnum
+;;; b) it's a bignum with exactly one digit.
+(define-x8632-vinsn unbox-s32 (((dest :s32))
+                               ((src :lisp)))
+  :resume
+  (movl (:%l src) (:%l dest))
+  (sarl (:$ub x8632::fixnumshift) (:%l dest))
+  ;; Was it a fixnum ?
+  (testl (:$l x8632::fixnummask) (:%l src))
+  (je :done)
+  ;; May be a 1-digit bignum
+  (movl (:%l src) (:%l dest))
+  (andl (:$b x8632::tagmask) (:%l dest))
+  (cmpl (:$b x8632::tag-misc) (:%l dest))
+  (jne :bad)
+  (cmpl (:$l x8632::one-digit-bignum-header) (:@ x8632::misc-header-offset (:%l src)))
+  (movl (:@ x8632::misc-data-offset (:%l src)) (:%l dest))
+  (jne :bad)
+  :done
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l src) (:$ub arch::error-object-not-signed-byte-32))))
+
+(define-x8632-vinsn sign-extend-s8 (((dest :s32))
+                                    ((src :s8)))
+  (movsbl (:%b src) (:%l dest)))
+
+(define-x8632-vinsn sign-extend-s16 (((dest :s32))
+                                     ((src :s16)))
+  (movswl (:%w src) (:%l dest)))
+
+(define-x8632-vinsn zero-extend-u8 (((dest :s32))
+                                    ((src :u8)))
+  (movzbl (:%b src) (:%l dest)))
+
+(define-x8632-vinsn zero-extend-u16 (((dest :s32))
+                                     ((src :u16)))
+  (movzwl (:%w src) (:%l dest)))
+
+(define-x8632-vinsn (jump-subprim :jumpLR) (()
+					    ((spno :s32const)))
+  (jmp (:@ spno)))
+
+;;; Call a subprimitive using a tail-aligned CALL instruction.
+(define-x8632-vinsn (call-subprim :call)  (()
+                                           ((spno :s32const))
+                                           ((entry (:label 1))))
+  (:talign x8632::fulltag-tra)
+  (call (:@ spno))
+  (movl (:$self 0) (:% x8632::fn)))
+
+(define-x8632-vinsn fixnum-subtract-from (((dest t)
+                                           (y t))
+                                          ((y t)
+                                           (x t)))
+  (subl (:%l y) (:%l x)))
+
+(define-x8632-vinsn %logand-c (((dest t)
+                                (val t))
+                               ((val t)
+                                (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (andl (:$b const) (:%l val)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (andl (:$l const) (:%l val))))
+
+(define-x8632-vinsn %logior-c (((dest t)
+                                (val t))
+                               ((val t)
+                                (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (orl (:$b const) (:%l val)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (orl (:$l const) (:%l val))))
+
+(define-x8632-vinsn %logxor-c (((dest t)
+                                (val t))
+                               ((val t)
+                                (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (xorl (:$b const) (:%l val)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (xorl (:$l const) (:%l val))))
+
+(define-x8632-vinsn character->fixnum (((dest :lisp))
+				       ((src :lisp))
+				       ())
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movl (:%l src) (:%l dest)))
+
+  ((:pred <= (:apply %hard-regspec-value dest) x8632::ebx)
+   (xorb (:%b dest) (:%b dest)))
+  ((:pred > (:apply %hard-regspec-value dest) x8632::ebx)
+   (andl (:$l -256) (:%l dest)))
+  (shrl (:$ub (- x8632::charcode-shift x8632::fixnumshift)) (:%l dest)))
+
+(define-x8632-vinsn compare (()
+                             ((x t)
+                              (y t)))
+  (rcmpl (:%l x) (:%l y)))
+
+(define-x8632-vinsn negate-fixnum (((val :lisp))
+                                   ((val :imm)))
+  (negl (:% val)))
+
+;;; This handles the 1-bit overflow from addition/subtraction/unary negation
+(define-x8632-vinsn set-bigits-and-header-for-fixnum-overflow
+    (()
+     ((val :lisp)
+      (no-overflow
+       :label))
+     ((imm (:u32 #.x8632::imm0))))
+  (jno no-overflow)
+  (movl (:%l val) (:%l imm))
+  (sarl (:$ub x8632::fixnumshift) (:%l imm))
+  (xorl (:$l #xc0000000) (:%l imm))
+  ;; stash bignum digit
+  (movd (:%l imm) (:%mmx x8632::mm1))
+  ;; set header
+  (movl (:$l x8632::one-digit-bignum-header) (:%l imm))
+  (movd (:%l imm) (:%mmx x8632::mm0))
+  ;; need 8 bytes of aligned memory for 1 digit bignum
+  (movl (:$l (- 8 x8632::fulltag-misc)) (:%l imm)))
+
+(define-x8632-vinsn handle-fixnum-overflow-inline
+    (()
+     ((val :lisp)
+      (no-overflow
+       :label))
+     ((imm (:u32 #.x8632::imm0))
+      (freeptr (:lisp #.x8632::allocptr))))
+  (jo :overflow)
+  (:uuo-section)
+  :overflow
+  (movl (:%l val) (:%l imm))
+  (sarl (:$ub x8632::fixnumshift) (:%l imm))
+  (xorl (:$l #xc0000000) (:%l imm))
+  ;; stash bignum digit
+  (movd (:%l imm) (:%mmx x8632::mm1))
+  ;; set header
+  (movl (:$l x8632::one-digit-bignum-header) (:%l imm))
+  (movd (:%l imm) (:%mmx x8632::mm0))
+  ;; need 8 bytes of aligned memory for 1 digit bignum
+  (movl (:$l (- 8 x8632::fulltag-misc)) (:%l imm))
+  (subl (:%l imm) (:@ (:%seg :rcontext) x8632::tcr.save-allocptr))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.save-allocptr) (:%l freeptr))
+  (rcmpl (:%l freeptr) (:@ (:%seg :rcontext) x8632::tcr.save-allocbase))
+  (ja :no-trap)
+  (uuo-alloc)
+  :no-trap
+  (movd (:%mmx x8632::mm0) (:@ x8632::misc-header-offset (:%l freeptr)))
+  (andb (:$b (lognot x8632::fulltagmask)) (:@ (:%seg :rcontext) x8632::tcr.save-allocptr))
+  ((:not (:pred = freeptr
+		(:apply %hard-regspec-value val)))
+   (movl (:%l freeptr) (:%l val)))
+  (movd (:%mmx x8632::mm1) (:@ x8632::misc-data-offset (:%l val)))
+  (jmp no-overflow))
+
+  
+(define-x8632-vinsn set-bigits-after-fixnum-overflow (()
+                                                      ((bignum :lisp)))
+  (movd (:%mmx x8632::mm1) (:@ x8632::misc-data-offset (:%l bignum))))  
+
+
+(define-x8632-vinsn %set-z-flag-if-s32-fits-in-fixnum (((dest :imm))
+						       ((src :s32))
+						       ((temp :s32)))
+  (movl (:%l src) (:%l temp))
+  (shll (:$ub x8632::fixnumshift) (:%l temp))
+  (movl (:%l temp) (:%l dest))          ; tagged as a fixnum
+  (sarl (:$ub x8632::fixnumshift) (:%l temp))
+  (cmpl (:%l src) (:%l temp)))
+
+(define-x8632-vinsn %set-z-flag-if-u32-fits-in-fixnum (((dest :imm))
+                                                       ((src :u32))
+                                                       ((temp :u32)))
+  (movl (:%l src) (:%l temp))
+  (shll (:$ub (1+ x8632::fixnumshift)) (:%l temp))
+  (movl (:%l temp) (:%l dest))          ; tagged as an even fixnum
+  (shrl (:$ub (1+ x8632::fixnumshift)) (:%l temp))
+  (shrl (:%l dest))
+  (cmpl (:%l src) (:%l temp))
+  :done)
+
+;;; setup-bignum-alloc-for-s32-overflow
+;;; setup-bignum-alloc-for-u32-overflow
+
+(define-x8632-vinsn setup-uvector-allocation (()
+					      ((header :imm)))
+  (movd (:%l header) (:%mmx x8632::mm0)))
+
+;;; The code that runs in response to the uuo-alloc
+;;; expects a header in mm0, and a size in imm0.
+;;; mm0 is an implicit arg (it contains the uvector header)
+;;; size is actually an arg, not a temporary,
+;;; but it appears that there's isn't a way to enforce
+;;; register usage on vinsn args.
+(define-x8632-vinsn %allocate-uvector (((dest :lisp))
+				       ()
+				       ((size (:u32 #.x8632::imm0))
+					(freeptr (:lisp #.x8632::allocptr))))
+  (subl (:%l size) (:@ (:%seg :rcontext) x8632::tcr.save-allocptr))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.save-allocptr) (:%l freeptr))
+  (rcmpl (:%l freeptr) (:@ (:%seg :rcontext) x8632::tcr.save-allocbase))
+  (ja :no-trap)
+  (uuo-alloc)
+  :no-trap
+  (movd (:%mmx x8632::mm0) (:@ x8632::misc-header-offset (:%l freeptr)))
+  (andb (:$b (lognot x8632::fulltagmask)) (:@ (:%seg :rcontext) x8632::tcr.save-allocptr))
+  ((:not (:pred = freeptr
+		(:apply %hard-regspec-value dest)))
+   (movl (:%l freeptr) (:%l dest))))
+
+(define-x8632-vinsn box-fixnum (((dest :imm))
+                                ((src :s32)))
+  ;;(imull (:$b x8632::fixnumone) (:%l src) (:%l dest))
+  (leal (:@ (:%l src) x8632::fixnumone) (:%l dest)))
+
+(define-x8632-vinsn (fix-fixnum-overflow-ool :call)
+    (((val :lisp))
+     ((val :lisp))
+     ((unboxed (:s32 #.x8632::imm0))
+      ;; we use %mm0 for header in subprim
+      (entry (:label 1))))
+  (jno :done)
+  ((:not (:pred = x8632::arg_z
+                (:apply %hard-regspec-value val)))
+   (movl (:%l val) (:%l x8632::arg_z)))
+  (:talign 5)
+  (call (:@ .SPfix-overflow))
+  (movl (:$self 0) (:%l x8632::fn))
+  ((:not (:pred = x8632::arg_z
+                (:apply %hard-regspec-value val)))
+   (movl (:%l x8632::arg_z) (:%l val)))
+  :done)
+
+(define-x8632-vinsn (fix-fixnum-overflow-ool-and-branch :call)
+    (((val :lisp))
+     ((val :lisp)
+      (lab :label))
+     ((unboxed (:s32 #.x8632::imm0))
+      ;; we use %mm0 for header in subprim
+      (entry (:label 1))))
+  (jno lab)
+  ((:not (:pred = x8632::arg_z
+                (:apply %hard-regspec-value val)))
+   (movl (:%l val) (:%l x8632::arg_z)))
+  (:talign 5)
+  (call (:@ .SPfix-overflow))
+  (movl (:$self 0) (:%l x8632::fn))
+  ((:not (:pred = x8632::arg_z
+                (:apply %hard-regspec-value val)))
+   (movl (:%l x8632::arg_z) (:%l val)))
+  (jmp lab))
+
+
+(define-x8632-vinsn add-constant (((dest :imm))
+                                  ((dest :imm)
+                                   (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (addl (:$b const) (:%l dest)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (addl (:$l const) (:%l dest))))
+
+(define-x8632-vinsn add-constant3 (((dest :imm))
+                                   ((src :imm)
+                                    (const :s32const)))
+  ((:pred = (:apply %hard-regspec-value dest)
+          (:apply %hard-regspec-value src))
+   ((:and (:pred >= const -128) (:pred <= const 127))
+    (addl (:$b const) (:%l dest)))
+   ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+    (addl (:$l const) (:%l dest))))
+  ((:not (:pred = (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (leal (:@ const (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn fixnum-add2  (((dest :imm))
+                                  ((dest :imm)
+                                   (other :imm)))
+  (addl (:%l other) (:%l dest)))
+
+(define-x8632-vinsn fixnum-sub2  (((dest :imm))
+                                  ((x :imm)
+                                   (y :imm))
+                                  ((temp :imm)))
+  (movl (:%l x) (:%l temp))
+  (subl (:%l y) (:%l temp))
+  (movl (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn fixnum-add3 (((dest :imm))
+                                 ((x :imm)
+                                  (y :imm)))
+  
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (addl (:%l y) (:%l dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (addl (:%l x) (:%l dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (leal (:@ (:%l x) (:%l y)) (:%l dest)))))
+
+(define-x8632-vinsn copy-gpr (((dest t))
+			      ((src t)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movl (:%l src) (:%l dest))))
+
+(define-x8632-vinsn (vpop-register :pop :node :vsp)
+    (((dest :lisp))
+     ())
+  (popl (:%l dest)))
+
+(define-x8632-vinsn (push-argregs :push :node :vsp) (()
+						     ())
+  (rcmpl (:%l x8632::nargs) (:$b (* 1 x8632::node-size)))
+  (jb :done)
+  (je :one)
+  (pushl (:%l x8632::arg_y))
+  :one
+  (pushl (:%l x8632::arg_z))
+  :done)
+
+(define-x8632-vinsn (push-max-argregs :push :node :vsp) (()
+                                                         ((max :u32const)))
+  ((:pred >= max 2)
+   (rcmpl (:%l x8632::nargs) (:$b (* 1 x8632::node-size)))
+   (jb :done)
+   (je :one)
+   (pushl (:%l x8632::arg_y))
+   :one
+   (pushl (:%l x8632::arg_z))
+   :done)
+  ((:pred = max 1)
+   (testl (:%l x8632::nargs) (:%l x8632::nargs))
+   (je :done)
+   (pushl (:%l x8632::arg_z))
+   :done))
+
+(define-x8632-vinsn (call-label :call) (()
+					((label :label))
+                                        ((entry (:label 1))))
+  (:talign 5)
+  (call label)
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn double-float-compare (()
+					  ((arg0 :double-float)
+					   (arg1 :double-float)))
+  (comisd (:%xmm arg1) (:%xmm arg0)))
+
+(define-x8632-vinsn single-float-compare (()
+					  ((arg0 :single-float)
+					   (arg1 :single-float)))
+  (comiss (:%xmm arg1) (:%xmm arg0)))
+
+(define-x8632-vinsn double-float+-2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float)))
+  ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (addsd (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (addsd (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movsd (:%xmm x) (:%xmm result))
+   (addsd (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8632-vinsn double-float--2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movsd (:%xmm x) (:%xmm result)))
+  (subsd (:%xmm y) (:%xmm result)))
+
+(define-x8632-vinsn double-float*-2 (((result :double-float))
+				     ((x :double-float)
+                                      (y :double-float)))
+  ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (mulsd (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (mulsd (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movsd (:%xmm x) (:%xmm result))
+   (mulsd (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8632-vinsn double-float/-2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movsd (:%xmm x) (:%xmm result)))
+  (divsd (:%xmm y) (:%xmm result)))
+
+(define-x8632-vinsn single-float+-2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float)))
+  ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (addss (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (addss (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movss (:%xmm x) (:%xmm result))
+   (addss (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8632-vinsn single-float--2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movss (:%xmm x) (:%xmm result)))
+  (subss (:%xmm y) (:%xmm result)))
+
+(define-x8632-vinsn single-float*-2 (((result :single-float))
+				     ((x :single-float)
+                                      (y :single-float)))
+    ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (mulss (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (mulss (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movss (:%xmm x) (:%xmm result))
+   (mulss (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8632-vinsn single-float/-2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movss (:%xmm x) (:%xmm result)))
+  (divss (:%xmm y) (:%xmm result)))
+
+(define-x8632-vinsn get-single (((result :single-float))
+                                ((source :lisp)))
+  (movss (:@ x8632::single-float.value (:%l source)) (:%xmm result)))
+
+(define-x8632-vinsn get-double (((result :double-float))
+                                ((source :lisp)))
+  (movsd (:@ x8632::double-float.value (:%l source)) (:%xmm result)))
+
+;;; Extract a double-float value, typechecking in the process.
+;;; IWBNI we could simply call the "trap-unless-typecode=" vinsn here,
+;;; instead of replicating it ..
+(define-x8632-vinsn get-double? (((target :double-float))
+				 ((source :lisp))
+				 ((tag :u8)))
+  :resume
+  (movl (:%l source) (:%l tag))
+  ((:pred = (:apply %hard-regspec-value tag) x8632::eax)
+   (andl (:$b x8632::tagmask) (:%accl tag))
+   (cmpl (:$b x8632::tag-misc) (:%accl tag)))
+  ((:pred > (:apply %hard-regspec-value tag) x8632::eax)
+   (andl (:$b x8632::tagmask) (:%l tag))
+   (cmpl (:$b x8632::tag-misc) (:%l tag)))
+  (jne :have-tag)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l source)) (:%l tag))
+  :have-tag
+  (cmpl (:$b x8632::subtag-double-float) (:%l tag))
+  (jne :bad)
+  (movsd (:@  x8632::double-float.value (:%l source)) (:%xmm target))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q source) (:$ub x8632::subtag-double-float))))
+
+(define-x8632-vinsn copy-double-float (((dest :double-float))
+                                       ((src :double-float)))
+  (movsd (:%xmm src) (:%xmm dest)))
+
+(define-x8632-vinsn copy-single-float (((dest :single-float))
+                                       ((src :single-float)))
+  (movss (:%xmm src) (:%xmm dest)))
+
+(define-x8632-vinsn copy-single-to-double (((dest :double-float))
+                                           ((src :single-float)))
+  (cvtss2sd (:%xmm src) (:%xmm dest)))
+
+(define-x8632-vinsn copy-double-to-single (((dest :single-float))
+                                           ((src :double-float)))
+  (cvtsd2ss (:%xmm src) (:%xmm dest)))
+
+;;; these two clobber unboxed0, unboxed1 in tcr
+;;; (There's no way to move a value from the x87 stack to an xmm register,
+;;; so we have to go through memory.)
+(define-x8632-vinsn fp-stack-to-single (((dest :single-float))
+					())
+  (fstps (:@ (:%seg :rcontext) x8632::tcr.unboxed0))
+  (movss (:@ (:%seg :rcontext) x8632::tcr.unboxed0) (:%xmm dest)))
+
+(define-x8632-vinsn fp-stack-to-double (((dest :double-float))
+					())
+  (fstpl (:@ (:%seg :rcontext) x8632::tcr.unboxed0))
+  (movsd (:@ (:%seg :rcontext) x8632::tcr.unboxed0) (:%xmm dest)))
+
+(define-x8632-vinsn fitvals (()
+                             ((n :u16const))
+                             ((imm :u32)))
+  ((:pred = n 0)
+   (xorl (:%l imm) (:%l imm)))
+  ((:not (:pred = n 0))
+   (movl (:$l (:apply ash n x8632::fixnumshift)) (:%l imm)))
+  (subl (:%l x8632::nargs) (:%l imm))
+  (jae :push-more)
+  (subl (:%l imm) (:%l x8632::esp))
+  (jmp :done)
+  :push-loop
+  (pushl (:$l (:apply target-nil-value)))
+  (addl (:$b x8632::node-size) (:%l x8632::nargs))
+  (subl (:$b x8632::node-size) (:%l imm))
+  :push-more
+  (jne :push-loop)
+  :done)
+
+(define-x8632-vinsn (nvalret :jumpLR) (()
+                                       ())
+  (jmp (:@ .SPnvalret)))
+
+(define-x8632-vinsn lisp-word-ref (((dest t))
+				   ((base t)
+				    (offset t)))
+  (movl (:@ (:%l base) (:%l offset)) (:%l  dest)))
+
+(define-x8632-vinsn lisp-word-ref-c (((dest t))
+				     ((base t)
+				      (offset :s32const)))
+  ((:pred = offset 0)
+   (movl (:@ (:%l base)) (:%l dest)))
+  ((:not (:pred = offset 0))
+   (movl (:@ offset (:%l base)) (:%l dest))))
+
+;; start-mv-call
+
+(define-x8632-vinsn (vpush-label :push :node :vsp) (()
+						    ((label :label))
+						    ((temp :lisp)))
+  (leal (:@ (:^ label) (:%l x8632::fn)) (:%l temp))
+  (pushl (:%l temp)))
+
+(define-x8632-vinsn emit-aligned-label (()
+                                        ((label :label)))
+  ;; We don't care about label.
+  ;; We just want the label following this stuff to be tra-tagged.
+  (:align 3)
+  (nop) (nop) (nop) (nop) (nop))
+
+;; pass-multiple-values-symbol
+;;; %ra0 is pointing into %fn, so no need to copy %fn here.
+(define-x8632-vinsn pass-multiple-values-symbol (()
+                                                 ())
+  (pushl (:@ (:apply + (:apply target-nil-value) (x8632::%kernel-global 'x86::ret1valaddr)))) 
+  (jmp (:@ x8632::symbol.fcell (:% x8632::fname))))
+
+
+;;; It'd be good to have a variant that deals with a known function
+;;; as well as this. 
+(define-x8632-vinsn pass-multiple-values (()
+                                          ()
+                                          ((tag :u8)))
+  :resume
+  (movl (:%l x8632::temp0) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l x8632::temp0)) (:%l tag))
+  (cmpl (:$b x8632::subtag-function) (:%l tag))
+  (cmovel (:%l x8632::temp0) (:%l x8632::fn))
+  (je :go)
+  (cmpl (:$b x8632::subtag-symbol) (:%l tag))
+  (cmovel (:@ x8632::symbol.fcell (:%l x8632::fname)) (:%l x8632::fn))
+  (jne :bad)
+  :go
+  (pushl (:@ (:apply + (:apply target-nil-value) (x8632::%kernel-global 'x86::ret1valaddr))))
+  (jmp (:%l x8632::fn))
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-not-callable))
+)
+
+
+(define-x8632-vinsn reserve-outgoing-frame (()
+                                            ())
+  (pushl (:$b x8632::reserved-frame-marker))
+  (pushl (:$b x8632::reserved-frame-marker)))
+
+;; implicit temp0 arg
+(define-x8632-vinsn (call-known-function :call) (()
+						 ()
+                                                 ((entry (:label 1))))
+  (:talign 5)
+  (call (:%l x8632::temp0))
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn (jump-known-function :jumplr) (()
+                                                   ())
+  (jmp (:%l x8632::temp0)))
+
+(define-x8632-vinsn (list :call) (()
+                                  ()
+				  ((entry (:label 1))
+				   (temp (:lisp #.x8632::temp0))))
+  (leal (:@ (:^ :back) (:%l x8632::fn)) (:%l x8632::temp0))
+  (:talign 5)
+  (jmp (:@ .SPconslist))
+  :back
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn make-fixed-stack-gvector (((dest :lisp))
+                                              ((aligned-size :u32const)
+                                               (header :s32const))
+                                              ((tempa :imm)
+                                               (tempb :imm)))
+  ((:and (:pred >= (:apply + aligned-size x8632::dnode-size) -128)
+         (:pred <= (:apply + aligned-size x8632::dnode-size) 127))
+   (subl (:$b (:apply + aligned-size x8632::dnode-size))
+         (:@ (:%seg :rcontext) x8632::tcr.next-tsp)))
+  ((:not (:and (:pred >= (:apply + aligned-size x8632::dnode-size) -128)
+               (:pred <= (:apply + aligned-size x8632::dnode-size) 127)))
+   (subl (:$l (:apply + aligned-size x8632::dnode-size))
+         (:@ (:%seg :rcontext) x8632::tcr.next-tsp)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.save-tsp) (:%l tempb))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.next-tsp) (:%l tempa))
+  (movd (:%l tempb) (:%mmx x8632::stack-temp))
+  :loop
+  (movsd (:%xmm x8632::fpzero) (:@ -8 (:%l tempb)))
+  (subl (:$b x8632::dnode-size) (:%l tempb))
+  (cmpl (:%l tempa) (:%l tempb))
+  (jnz :loop)
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l tempa)))
+  (movl (:%l tempa) (:@ (:%seg :rcontext) x8632::tcr.save-tsp))
+  (movl (:$l header) (:@ x8632::dnode-size (:%l tempa)))
+  (leal (:@ (+ x8632::dnode-size x8632::fulltag-misc) (:%l tempa)) (:%l dest)))
+
+
+
+
+(define-x8632-vinsn make-tsp-vcell (((dest :lisp))
+				    ((closed :lisp))
+				    ((temp :imm)))
+  (subl (:$b (+ x8632::value-cell.size x8632::dnode-size)) (:@ (:%seg :rcontext) x8632::tcr.next-tsp))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.save-tsp) (:%mmx x8632::stack-temp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.next-tsp) (:%l temp))
+  (movsd (:%xmm x8632::fpzero) (:@ (:%l temp)))
+  (movsd (:%xmm x8632::fpzero) (:@ x8632::dnode-size (:%l temp)))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp))) 
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.save-tsp))  
+  (movl (:$l x8632::value-cell-header) (:@ x8632::dnode-size (:%l temp)))
+  (movl (:%l closed) (:@ (+ x8632::dnode-size x8632::node-size) (:%l temp)))
+  (leal (:@ (+ x8632::dnode-size x8632::fulltag-misc) (:%l temp)) (:%l dest)))
+
+(define-x8632-vinsn make-tsp-cons (((dest :lisp))
+				   ((car :lisp) (cdr :lisp))
+				   ((temp :imm)))
+  (subl (:$b (+ x8632::cons.size x8632::dnode-size)) (:@ (:%seg :rcontext) x8632::tcr.next-tsp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.next-tsp) (:%l temp))
+  (movq (:%xmm x8632::fpzero) (:@ (:%l temp)))
+  (movq (:%xmm x8632::fpzero) (:@ 8 (:%l temp)))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.save-tsp) (:%mmx x8632::stack-temp))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.save-tsp))
+  (leal (:@ (+ x8632::dnode-size x8632::fulltag-cons) (:%l temp)) (:%l temp))
+  (movl (:%l car) (:@ x8632::cons.car (:%l temp)))
+  (movl (:%l cdr) (:@ x8632::cons.cdr (:%l temp)))
+  (movl (:%l temp) (:%l dest)))
+
+
+;; make-fixed-stack-gvector
+
+(define-x8632-vinsn (discard-temp-frame :tsp :pop :discard) (()
+                                                             ()
+                                                             ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.save-tsp) (:%l temp))
+  (movl (:@ (:%l temp)) (:%l temp))
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.save-tsp))
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.next-tsp))
+  )
+
+(define-x8632-vinsn (discard-c-frame :csp :pop :discard) (()
+                                                          ()
+                                                          ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movl (:@ (:%l temp)) (:%l temp))
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp)))
+
+  
+(define-x8632-vinsn (vstack-discard :vsp :pop :discard) (()
+				    ((nwords :u32const)))
+  ((:not (:pred = nwords 0))
+   ((:pred < nwords 16)
+    (addl (:$b (:apply ash nwords x8632::word-shift)) (:%l x8632::esp)))
+   ((:not (:pred < nwords 16))
+    (addl (:$l (:apply ash nwords x8632::word-shift)) (:%l x8632::esp)))))
+
+(defmacro define-x8632-subprim-lea-jmp-vinsn ((name &rest other-attrs) spno)
+  `(define-x8632-vinsn (,name :call :subprim-call ,@other-attrs) (()
+								  ()
+								  ((entry (:label 1))
+								   (ra (:lisp #.x8632::ra0))))
+    (leal (:@ (:^ :back) (:%l x8632::fn)) (:%l ra))
+    (:talign 5)
+    (jmp (:@ ,spno))
+    :back
+    (movl (:$self 0) (:%l x8632::fn))))
+
+(defmacro define-x8632-subprim-call-vinsn ((name &rest other-attrs) spno)
+  `(define-x8632-vinsn (,name :call :subprim-call ,@other-attrs) (() () ((entry (:label 1))))
+    (:talign 5)
+    (call (:@ ,spno))
+    :back
+    (movl (:$self 0) (:%l x8632::fn))))
+
+(defmacro define-x8632-subprim-jump-vinsn ((name &rest other-attrs) spno)
+  `(define-x8632-vinsn (,name :jumpLR ,@other-attrs) (() ())
+    (jmp (:@ ,spno))))
+
+(define-x8632-vinsn (nthrowvalues :call :subprim-call) (()
+                                                        ((lab :label))
+							((ra (:lisp #.x8632::ra0))))
+  (leal (:@ (:^ lab) (:%l x8632::fn)) (:%l ra))
+  (jmp (:@ .SPnthrowvalues)))
+
+(define-x8632-vinsn (nthrow1value :call :subprim-call) (()
+                                                        ((lab :label))
+							((ra (:lisp #.x8632::ra0))))
+  (leal (:@ (:^ lab) (:%l x8632::fn)) (:%l ra))
+  (jmp (:@ .SPnthrow1value)))
+
+(define-x8632-vinsn set-single-c-arg (()
+                                      ((arg :single-float)
+                                       (offset :u32const))
+				      ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movss (:%xmm arg) (:@ (:apply + 8 (:apply ash offset 2)) (:%l temp))))
+
+(define-x8632-vinsn reload-single-c-arg (((arg :single-float))
+                                         ((offset :u32const))
+					 ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movss (:@ (:apply + 8 (:apply ash offset 2)) (:%l temp)) (:%xmm arg)))
+
+(define-x8632-vinsn set-double-c-arg (()
+                                      ((arg :double-float)
+                                       (offset :u32const))
+				      ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movsd (:%xmm arg) (:@ (:apply + 8 (:apply ash offset 2)) (:%l temp))))
+
+(define-x8632-vinsn reload-double-c-arg (((arg :double-float))
+                                         ((offset :u32const))
+					 ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movsd (:@ (:apply + 8 (:apply ash offset 2)) (:%l temp)) (:%xmm arg)))
+
+;;; .SPffcall has stored %edx in tcr.unboxed1.  Load %mm0 with a 
+;;; 64-bit value composed from %edx:%eax.
+(define-x8632-vinsn get-64-bit-ffcall-result (()
+                                              ())
+  (movl (:%l x8632::eax) (:@ (:%seg :rcontext) x8632::tcr.unboxed0))
+  (movq (:@ (:%seg :rcontext) x8632::tcr.unboxed0) (:%mmx x8632::mm0)))
+
+(define-x8632-subprim-call-vinsn (ff-call)  .SPffcall)
+
+(define-x8632-subprim-call-vinsn (syscall)  .SPsyscall)
+
+(define-x8632-subprim-call-vinsn (syscall2)  .SPsyscall2)
+
+(define-x8632-subprim-call-vinsn (setqsym) .SPsetqsym)
+
+(define-x8632-subprim-call-vinsn (gets32) .SPgets32)
+
+(define-x8632-subprim-call-vinsn (getu32) .SPgetu32)
+
+(define-x8632-subprim-call-vinsn (gets64) .SPgets64)
+
+(define-x8632-subprim-call-vinsn (getu64) .SPgetu64)
+
+(define-x8632-subprim-call-vinsn (makes64) .SPmakes64)
+
+(define-x8632-subprim-call-vinsn (makeu64) .SPmakeu64)
+
+(define-x8632-subprim-lea-jmp-vinsn (stack-cons-list*)  .SPstkconslist-star)
+
+(define-x8632-subprim-lea-jmp-vinsn (list*) .SPconslist-star)
+
+(define-x8632-subprim-lea-jmp-vinsn (bind-interrupt-level-0) .SPbind-interrupt-level-0)
+
+(define-x8632-vinsn bind-interrupt-level-0-inline (()
+                                                   ()
+                                                   ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.tlb-pointer) (:%l temp))
+  (cmpl (:$b 0) (:@ x8632::interrupt-level-binding-index (:%l temp)))
+  (pushl (:@ x8632::interrupt-level-binding-index (:%l temp)))
+  (pushl (:$b x8632::interrupt-level-binding-index))
+  (pushl (:@ (:%seg :rcontext) x8632::tcr.db-link))
+  (movl (:$l 0) (:@ x8632::interrupt-level-binding-index (:%l temp)))
+  (movl (:%l x8632::esp) (:@ (:%seg :rcontext) x8632::tcr.db-link))
+  (jns :done)
+  (btrl (:$ub 31) (:@ (:%seg :rcontext) x8632::tcr.interrupt-pending))
+  (jae :done)
+  (ud2a)
+  (:byte 2)
+  :done)
+
+(define-x8632-vinsn bind-interrupt-level-m1-inline (()
+						    ()
+						    ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.tlb-pointer) (:%l temp))
+  (pushl (:@ x8632::interrupt-level-binding-index (:%l temp)))
+  (pushl (:$b x8632::interrupt-level-binding-index))
+  (pushl (:@ (:%seg :rcontext) x8632::tcr.db-link))
+  (movl (:$l (ash -1 x8632::fixnumshift)) (:@ x8632::interrupt-level-binding-index (:%l temp)))
+  (movl (:%l x8632::esp) (:@ (:%seg :rcontext) x8632::tcr.db-link)))
+
+(define-x8632-subprim-lea-jmp-vinsn (bind-interrupt-level-m1) .SPbind-interrupt-level-m1)
+
+(define-x8632-subprim-lea-jmp-vinsn (bind-interrupt-level) .SPbind-interrupt-level)
+
+(define-x8632-subprim-call-vinsn (unbind-interrupt-level) .SPunbind-interrupt-level)
+
+#||
+(define-x8632-vinsn unbind-interrupt-level-inline (()
+                                                   ()
+                                                   ((link :imm)
+                                                    (curval :imm)
+                                                    (oldval :imm)
+                                                    (tlb :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.tlb-pointer) (:%l tlb))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.db-link) (:%l link))
+  (movl (:@ x8632::interrupt-level-binding-index (:%l tlb)) (:%l curval))
+  (testl (:%l curval) (:%l curval))
+  (movl (:@ 8 #|binding.val|# (:%l link)) (:%l oldval))
+  (movl (:@ #|binding.link|# (:%l link)) (:%l link))
+  (movl (:%l oldval) (:@ x8632::interrupt-level-binding-index (:%l tlb)))
+  (movl (:%l link) (:@ (:%seg :rcontext) x8632::tcr.db-link))
+  (jns :done)
+  (testl (:%l oldval) (:%l oldval))
+  (js :done)
+  (btrl (:$ub 31) (:@ (:%seg :rcontext) x8632::tcr.interrupt-pending))
+  (jae :done)
+  (ud2a)
+  (:byte 2)
+  :done)
+||#
+
+(define-x8632-vinsn (jump-return-pc :jumpLR) (()
+					      ())
+  (ret))
+
+;;; xxx
+(define-x8632-vinsn (nmkcatchmv :call :subprim-call) (()
+						      ((lab :label))
+						      ((entry (:label 1))
+						       (xfn (:lisp #.x8632::xfn))))
+  (leal (:@ (:^ lab)  (:%l x8632::fn)) (:%l xfn))
+  (:talign 5)
+  (call (:@ .SPmkcatchmv))
+  :back
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn (nmkcatch1v :call :subprim-call) (()
+                                                     ((lab :label))
+                                                     ((entry (:label 1))
+						      (xfn (:lisp #.x8632::xfn))))
+  (leal (:@ (:^ lab)  (:%l x8632::fn)) (:%l x8632::xfn))
+  (:talign 5)
+  (call (:@ .SPmkcatch1v))
+  :back
+  (movl (:$self 0) (:%l x8632::fn)))
+
+
+(define-x8632-vinsn (make-simple-unwind :call :subprim-call) (()
+                                                     ((protform-lab :label)
+                                                      (cleanup-lab :label)))
+  (leal (:@ (:^ protform-lab) (:%l x8632::fn)) (:%l x8632::ra0))
+  (leal (:@ (:^ cleanup-lab)  (:%l x8632::fn)) (:%l x8632::xfn))
+  (jmp (:@ .SPmkunwind)))
+
+(define-x8632-vinsn (nmkunwind :call :subprim-call) (()
+                                                     ((protform-lab :label)
+                                                      (cleanup-lab :label)))
+  (leal (:@ (:^ protform-lab) (:%l x8632::fn)) (:%l x8632::ra0))
+  (leal (:@ (:^ cleanup-lab)  (:%l x8632::fn)) (:%l x8632::xfn))
+  (jmp (:@ .SPnmkunwind)))
+
+(define-x8632-vinsn u16->u32 (((dest :u32))
+			      ((src :u16)))
+  (movzwl (:%w src) (:%l dest)))
+
+(define-x8632-vinsn u8->u32 (((dest :u32))
+			     ((src :u8)))
+  (movzbl (:%b src) (:%l dest)))
+
+(define-x8632-vinsn s16->s32 (((dest :s32))
+			      ((src :s16)))
+  (movswl (:%w src) (:%l dest)))
+
+(define-x8632-vinsn s8->s32 (((dest :s32))
+			     ((src :s8)))
+  (movsbl (:%b src) (:%l dest)))
+
+(define-x8632-subprim-jump-vinsn (tail-call-fn-gen) .SPtcallnfngen)
+
+(define-x8632-subprim-jump-vinsn (tail-call-fn-vsp) .SPtcallnfnvsp)
+
+(define-x8632-vinsn set-eq-bit (()
+                                ())
+  (testb (:%b x8632::arg_z) (:%b x8632::arg_z)))
+
+;;; %schar8
+;;; %schar32
+;;; %set-schar8
+;;; %set-schar32
+
+(define-x8632-vinsn misc-set-c-single-float (((val :single-float))
+					     ((v :lisp)
+					      (idx :u32const)))
+  (movss (:%xmm val) (:@ (:apply + x8632::misc-data-offset (:apply ash idx 2)) (:%l v))))
+
+(define-x8632-vinsn array-data-vector-ref (((dest :lisp))
+					   ((header :lisp)))
+  (movl (:@ x8632::arrayH.data-vector (:%l header)) (:%l dest)))
+
+(define-x8632-vinsn set-z-flag-if-istruct-typep (()
+                                                 ((val :lisp)
+                                                  (type :lisp))
+                                                 ((tag :u8)
+                                                  (valtype :lisp)))
+  (xorl (:%l valtype) (:%l valtype))
+  (movl (:%l val) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l val)) (:%l tag))
+  :have-tag
+  (cmpl (:$b x8632::subtag-istruct) (:%l tag))
+  (jne :do-compare)
+  (movl (:@ x8632::misc-data-offset (:%l val)) (:%l valtype))
+  :do-compare
+  (cmpl (:%l valtype) (:%l type)))
+
+(define-x8632-subprim-call-vinsn (subtag-misc-ref) .SPsubtag-misc-ref)
+
+(define-x8632-subprim-call-vinsn (subtag-misc-set) .SPsubtag-misc-set)
+
+(define-x8632-vinsn mem-set-c-constant-fullword (()
+                                                 ((val :s32const)
+                                                  (dest :address)
+                                                  (offset :s32const)))
+  ((:pred = offset 0)
+   (movl (:$l val) (:@ (:%l dest))))
+  ((:not (:pred = offset 0))
+   (movl (:$l val) (:@ offset (:%l dest)))))
+
+(define-x8632-vinsn mem-set-c-halfword (()
+					((val :u16)
+					 (dest :address)
+					 (offset :s32const)))
+  ((:pred = offset 0)
+   (movw (:%w val) (:@ (:%l dest))))
+  ((:not (:pred = offset 0))
+   (movw (:%w val) (:@ offset (:%l dest)))))
+
+(define-x8632-vinsn mem-set-c-constant-halfword (()
+                                                 ((val :s16const)
+                                                  (dest :address)
+                                                  (offset :s32const)))
+  ((:pred = offset 0)
+   (movw (:$w val) (:@ (:%l dest))))
+  ((:not (:pred = offset 0))
+   (movw (:$w val) (:@ offset (:%l dest)))))
+
+(define-x8632-vinsn mem-set-c-constant-byte (()
+                                                 ((val :s8const)
+                                                  (dest :address)
+                                                  (offset :s32const)))
+  ((:pred = offset 0)
+   (movb (:$b val) (:@ (:%l dest))))
+  ((:not (:pred = offset 0))
+   (movb (:$b val) (:@ offset (:%l dest)))))
+
+(define-x8632-vinsn mem-set-c-byte (()
+				    ((val :u8)
+				     (dest :address)
+				     (offset :s32const)))
+  ((:pred = offset 0)
+   (movb (:%b val) (:@ (:%l dest))))
+  ((:not (:pred = offset 0))
+   (movb (:%b val) (:@ offset (:%l dest)))))
+
+(define-x8632-vinsn mem-ref-c-absolute-u8 (((dest :u8))
+                                           ((addr :s32const)))
+  (movzbl (:@ addr) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-absolute-s8 (((dest :s8))
+                                           ((addr :s32const)))
+  (movsbl (:@ addr) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-absolute-u16 (((dest :u16))
+                                           ((addr :s32const)))
+  (movzwl (:@ addr) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-absolute-s16 (((dest :s16))
+                                           ((addr :s32const)))
+  (movswl (:@ addr) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-absolute-fullword (((dest :u32))
+                                                 ((addr :s32const)))
+  (movl (:@ addr) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-absolute-signed-fullword (((dest :s32))
+                                                        ((addr :s32const)))
+  (movl (:@ addr) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-absolute-natural (((dest :u32))
+                                                   ((addr :s32const)))
+  (movl (:@ addr) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-u8 (((dest :u8))
+				((src :address)
+				 (index :s32)))
+  (movzbl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-u16 (((dest :u16))
+				   ((src :address)
+				    (index :s32const)))
+  ((:pred = index 0)  
+   (movzwl (:@ (:%l src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movzwl (:@ index (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn mem-ref-u16 (((dest :u16))
+				 ((src :address)
+				  (index :s32)))
+  (movzwl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-s16 (((dest :s16))
+				   ((src :address)
+				    (index :s32const)))
+  ((:pred = index 0)
+   (movswl (:@ (:%l src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movswl (:@ index (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn mem-ref-s16 (((dest :s16))
+				 ((src :address)
+				  (index :s32)))
+  (movswl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-u8 (((dest :u8))
+				  ((src :address)
+				   (index :s16const)))
+  ((:pred = index 0)
+   (movzbl (:@  (:%l src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movzbl (:@ index (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn mem-ref-u8 (((dest :u8))
+				((src :address)
+				 (index :s32)))
+  (movzbl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-s8 (((dest :s8))
+				  ((src :address)
+				   (index :s16const)))
+  ((:pred = index 0)
+   (movsbl (:@ (:%l src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movsbl (:@ index (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn misc-set-c-s8  (((val :s8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (movb (:%b val) (:@ (:apply + x8632::misc-data-offset idx) (:%l v))))
+
+(define-x8632-vinsn misc-set-s8  (((val :s8))
+				  ((v :lisp)
+				   (scaled-idx :s32))
+				  ())
+  (movb (:%b val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn mem-ref-s8 (((dest :s8))
+				((src :address)
+				 (index :s32)))
+  (movsbl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn mem-set-constant-fullword (()
+                                               ((val :s32const)
+                                                (ptr :address)
+                                                (offset :s32)))
+  (movl (:$l val) (:@ (:%l ptr) (:%l offset))))
+
+
+(define-x8632-vinsn mem-set-constant-halfword (()
+                                               ((val :s16const)
+                                                (ptr :address)
+                                                (offset :s32)))
+  (movw (:$w val) (:@ (:%l ptr) (:%l offset))))
+
+(define-x8632-vinsn mem-set-constant-byte (()
+                                           ((val :s8const)
+                                            (ptr :address)
+                                            (offset :s32)))
+  (movb (:$b val) (:@ (:%l ptr) (:%l offset))))
+
+(define-x8632-vinsn misc-set-c-u8  (((val :u8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (movb (:%b val) (:@ (:apply + x8632::misc-data-offset idx) (:%l v))))
+
+(define-x8632-vinsn misc-set-u8  (((val :u8))
+				  ((v :lisp)
+				   (scaled-idx :s32))
+				  ())
+  (movb (:%b val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn misc-set-c-u16  (()
+                                    ((val :u16)
+                                     (v :lisp)
+                                     (idx :s32const))
+                                    ())
+  (movw (:%w val) (:@ (:apply + x8632::misc-data-offset (:apply * 2 idx)) (:%l v))))
+
+(define-x8632-vinsn misc-set-u16  (()
+                                   ((val :u16)
+                                    (v :lisp)
+                                    (scaled-idx :s32))
+                                   ())
+  (movw (:%w val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn misc-set-c-s16  (()
+                                    ((val :s16)
+                                     (v :lisp)
+                                     (idx :s32const))
+                                    ())
+  (movw (:%w val) (:@ (:apply + x8632::misc-data-offset (:apply * 2 idx)) (:%l v))))
+
+(define-x8632-vinsn misc-set-s16  (()
+                                   ((val :s16)
+                                    (v :lisp)
+                                    (scaled-idx :s32))
+                                   ())
+  (movw (:%w val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn misc-set-c-u32  (()
+				     ((val :u32)
+                                      (v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movl (:%l val) (:@ (:apply + x8632::misc-data-offset (:apply ash idx 2)) (:%l v))))
+
+(define-x8632-vinsn misc-set-u32  (()
+                                   ((val :u32)
+                                    (v :lisp)
+                                    (scaled-idx :s32))
+                                   ())
+  (movl (:%l val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn misc-set-c-s32  (()
+				     ((val :s32)
+                                      (v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movl (:%l val) (:@ (:apply + x8632::misc-data-offset (:apply ash idx 2)) (:%l v))))
+
+(define-x8632-vinsn misc-set-s32  (()
+                                   ((val :s32)
+                                    (v :lisp)
+                                    (scaled-idx :s32))
+                                   ())
+  (movl (:%l val) (:@ x8632::misc-data-offset (:%l v) (:%l scaled-idx))))
+
+(define-x8632-vinsn %iasr (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :s32)
+                            (shiftcount (:s32 #.x8632::ecx))))
+  (movl (:%l count) (:%l temp))
+  (sarl (:$ub x8632::fixnumshift) (:%l temp))
+  (rcmpl (:%l temp) (:$l 31))
+  (cmovbw (:%w temp) (:%w shiftcount))
+  (movl (:%l src) (:%l temp))
+  (jae :shift-max)
+  (sarl (:%shift x8632::cl) (:%l temp))
+  (jmp :done)
+  :shift-max
+  (sarl (:$ub 31) (:%l temp))
+  :done
+  (andl (:$l (lognot x8632::fixnummask)) (:%l temp))
+  (movl (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn %ilsr (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :s32)
+                            (shiftcount (:s32 #.x8632::ecx))))
+  (movl (:%l count) (:%l temp))
+  (sarl (:$ub x8632::fixnumshift) (:%l temp))
+  (rcmpl (:%l temp) (:$l 31))
+  (cmovbw (:%w temp) (:%w shiftcount))
+  (movl (:%l src) (:%l temp))
+  (jae :shift-max)
+  (shrl (:%shift x8632::cl) (:%l temp))
+  (jmp :done)
+  :shift-max
+  (shrl (:$ub 31) (:%l temp))
+  :done
+  (andb (:$b (lognot x8632::fixnummask)) (:%b temp))
+  (movl (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn %iasr-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm))
+			     ((temp :s32)))
+  (movl (:%l src) (:%l temp))
+  (sarl (:$ub count) (:%l temp))
+  (andb (:$b (lognot x8632::fixnummask)) (:%b temp))
+  (movl (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn %ilsr-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm))
+			     ((temp :s32)))
+  (movl (:%l src) (:%l temp))
+  (shrl (:$ub count) (:%l temp))
+  ;; xxx --- use :%acc
+  (andb (:$b (lognot x8632::fixnummask)) (:%b temp))
+  (movl (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn %ilsl (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp (:s32 #.x8632::eax))
+                            (shiftcount (:s32 #.x8632::ecx))))
+  (movl (:%l count) (:%l temp))
+  (sarl (:$ub x8632::fixnumshift) (:%l temp))
+  (rcmpl (:%l temp) (:$l 31))
+  (cmovbw (:%w temp) (:%w shiftcount))
+  (movl (:%l src) (:%l temp))
+  (jae :shift-max)
+  (shll (:%shift x8632::cl) (:%l temp))
+  (jmp :done)
+  :shift-max
+  (xorl (:%l temp) (:%l temp))
+  :done
+  (movl (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn %ilsl-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value src)
+                (:apply %hard-regspec-value dest)))
+   (movl (:%l src) (:%l dest)))
+  (shll (:$ub count) (:%l dest)))
+
+;;; In safe code, something else has ensured that the value is of type
+;;; BIT.
+(define-x8632-vinsn set-variable-bit-to-variable-value (()
+                                                        ((vec :lisp)
+                                                         (word-index :s32)
+                                                         (bitnum :u8)
+                                                         (value :lisp)))
+  (testl (:%l value) (:%l value))
+  (je :clr)
+  (btsl (:%l bitnum) (:@ x8632::misc-data-offset (:%l vec) (:%l word-index) 4))
+  (jmp :done)
+  :clr
+  (btrl (:%l bitnum) (:@ x8632::misc-data-offset (:%l vec) (:%l word-index) 4))
+  :done)
+
+;;; In safe code, something else has ensured that the value is of type
+;;; BIT.
+(define-x8632-vinsn nset-variable-bit-to-variable-value (()
+							 ((vec :lisp)
+							  (index :s32)
+							  (value :lisp)))
+  (testl (:%l value) (:%l value))
+  (je :clr)
+  (btsl (:%l index) (:@ x8632::misc-data-offset (:%l vec)))
+  (jmp :done)
+  :clr
+  (btrl (:%l index) (:@ x8632::misc-data-offset (:%l vec)))
+  :done)
+
+(define-x8632-vinsn nset-variable-bit-to-zero (()
+                                              ((vec :lisp)
+                                               (index :s32)))
+  (btrl (:%l index) (:@ x8632::misc-data-offset (:%l vec))))
+
+(define-x8632-vinsn nset-variable-bit-to-one (()
+					     ((vec :lisp)
+					      (index :s32)))
+  (btsl (:%l index) (:@ x8632::misc-data-offset (:%l vec))))
+
+(define-x8632-vinsn set-variable-bit-to-zero (()
+                                              ((vec :lisp)
+                                               (word-index :s32)
+                                               (bitnum :u8)))
+  (btrl (:%l bitnum) (:@ x8632::misc-data-offset (:%l vec) (:%l word-index) 4)))
+
+(define-x8632-vinsn set-variable-bit-to-one (()
+					     ((vec :lisp)
+					      (word-index :s32)
+					      (bitnum :u8)))
+  (btsl (:%l bitnum) (:@ x8632::misc-data-offset (:%l vec) (:%l word-index) 4)))
+
+(define-x8632-vinsn set-constant-bit-to-zero (()
+                                              ((src :lisp)
+                                               (idx :u32const)))
+  (btrl (:$ub (:apply logand 31 idx))
+        (:@ (:apply + x8632::misc-data-offset (:apply ash (:apply ash idx -5) x8632::word-shift)) (:%l src))))
+
+(define-x8632-vinsn set-constant-bit-to-one (()
+                                             ((src :lisp)
+                                              (idx :u32const)))
+  (btsl (:$ub (:apply logand 31 idx))
+        (:@ (:apply + x8632::misc-data-offset (:apply ash (:apply ash idx -5) x8632::word-shift)) (:%l src))))
+
+(define-x8632-vinsn set-constant-bit-to-variable-value (()
+                                                        ((src :lisp)
+                                                         (idx :u32const)
+                                                         (value :lisp)))
+  (testl (:%l value) (:%l value))
+  (je :clr)
+  (btsl (:$ub (:apply logand 31 idx))
+        (:@ (:apply + x8632::misc-data-offset (:apply ash (:apply ash idx -5) x8632::word-shift)) (:%l src)))
+  (jmp :done)
+  :clr
+  (btrl (:$ub (:apply logand 31 idx))
+        (:@ (:apply + x8632::misc-data-offset (:apply ash (:apply ash idx -5) x8632::word-shift)) (:%l src)))
+  :done)
+
+(define-x8632-vinsn require-fixnum (()
+                                    ((object :lisp)))
+  :again
+  ((:and (:pred > (:apply %hard-regspec-value object) x8632::eax)
+	 (:pred <= (:apply %hard-regspec-value object) x8632::ebx))
+   (testb (:$b x8632::fixnummask) (:%b object)))
+  ((:pred > (:apply %hard-regspec-value object) x8632::ebx)
+   (testl (:$l x8632::fixnummask) (:%l object)))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-fixnum))))
+
+(define-x8632-vinsn require-integer (()
+                                     ((object :lisp))
+                                     ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  ((:pred = (:apply %hard-regspec-value tag) x8632::eax)
+   (andb (:$b x8632::fixnummask) (:%accb tag)))
+  ((:and (:pred > (:apply %hard-regspec-value tag) x8632::eax)
+	 (:pred <= (:apply %hard-regspec-value tag) x8632::ebx))
+   (andb (:$b x8632::fixnummask) (:%b tag)))
+  ((:pred > (:apply %hard-regspec-value object) x8632::ebx)
+   (andl (:$l x8632::fixnummask) (:%l tag)))
+  (je :got-it)
+  ((:pred = (:apply %hard-regspec-value tag) x8632::eax)
+   (cmpb (:$b x8632::tag-misc) (:%accb tag)))
+  ((:and (:pred > (:apply %hard-regspec-value tag) x8632::eax)
+	 (:pred <= (:apply %hard-regspec-value tag) x8632::ebx))
+   (cmpb (:$b x8632::tag-misc) (:%b tag)))
+  ((:pred > (:apply %hard-regspec-value object) x8632::ebx)
+   (cmpl (:$l x8632::tag-misc) (:%l tag)))
+  (jne :bad)
+  (cmpb (:$b x8632::subtag-bignum) (:@ x8632::misc-subtag-offset (:%l object)))
+  (jne :bad)
+  :got-it
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-integer))))
+
+(define-x8632-vinsn require-simple-vector (()
+                                           ((object :lisp))
+                                           ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::fixnummask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8632::subtag-simple-vector) (:@ x8632::misc-subtag-offset (:%l object)))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-simple-vector))))
+
+(define-x8632-vinsn require-simple-string (()
+                                           ((object :lisp))
+                                           ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::fixnummask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8632::subtag-simple-base-string) (:@ x8632::misc-subtag-offset (:%l object)))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-simple-string))))
+
+
+;;; naive
+(define-x8632-vinsn require-real (()
+                                    ((object :lisp))
+                                    ((tag :u8)
+                                     (mask :lisp)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l tag))
+  :have-tag
+  (cmpl (:$b (1- (- x8632::nbits-in-word x8632::fixnumshift))) (:%l tag))
+  (movl (:$l (ash (logior (ash 1 x8632::tag-fixnum)
+                          (ash 1 x8632::subtag-single-float)
+                          (ash 1 x8632::subtag-double-float)
+                          (ash 1 x8632::subtag-bignum)
+                          (ash 1 x8632::subtag-ratio))
+                  x8632::fixnumshift)) (:%l mask))
+  (ja :bad)
+  (addl (:$b x8632::fixnumshift) (:%l tag))
+  (btl (:%l tag) (:%l mask))
+  (jnc :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-real))))
+
+;;; naive
+(define-x8632-vinsn require-number (()
+                                    ((object :lisp))
+                                    ((tag :u8)
+                                     (mask :lisp)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8632::misc-subtag-offset (:%l object)) (:%l tag))
+  :have-tag
+  (cmpl (:$b (1- (- x8632::nbits-in-word x8632::fixnumshift))) (:%l tag))
+  (movl (:$l (ash (logior (ash 1 x8632::tag-fixnum)
+                          (ash 1 x8632::subtag-single-float)
+                          (ash 1 x8632::subtag-double-float)
+                          (ash 1 x8632::subtag-bignum)
+                          (ash 1 x8632::subtag-ratio)
+                          (ash 1 x8632::subtag-complex))
+                  x8632::fixnumshift)) (:%l mask))
+  (ja :bad)
+  (addl (:$b x8632::fixnumshift) (:%l tag))
+  (btl (:%l tag) (:%l mask))
+  (jnc :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-number))))
+
+(define-x8632-vinsn require-list (()
+                                  ((object :lisp))
+                                  ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::fulltagmask) (:%l tag))
+  (cmpl (:$b x8632::fulltag-cons) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-list))))
+
+(define-x8632-vinsn require-symbol (()
+                                    ((object :lisp))
+                                    ((tag :u8)))
+  :again
+  (cmpl (:$l (:apply target-nil-value)) (:%l object))
+  (je :got-it)
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8632::subtag-symbol) (:@ x8632::misc-subtag-offset (:%l object)))
+  (jne :bad)
+  :got-it
+  
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-symbol)))
+)
+
+(define-x8632-vinsn require-character (()
+				       ((object :lisp)))
+  :again
+  (cmpb (:$b x8632::subtag-character) (:%b object))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-character))))
+
+(define-x8632-vinsn require-s8 (()
+				((object :lisp))
+				((tag :u32)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (shll (:$ub (- x8632::nbits-in-word (+ 8 x8632::fixnumshift))) (:%l tag))
+  (sarl (:$ub (- x8632::nbits-in-word 8)) (:%l tag))
+  (shll (:$ub x8632::fixnumshift) (:%l tag))
+  (cmpl (:%l object) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-signed-byte-8))))
+
+(define-x8632-vinsn require-u8 (()
+				((object :lisp))
+				((tag :u32)))
+  :again
+  (movl (:$l (lognot (ash #xff x8632::fixnumshift))) (:%l tag))
+  (andl (:%l object) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-unsigned-byte-8))))
+
+(define-x8632-vinsn require-s16 (()
+				((object :lisp))
+				((tag :s32)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (shll (:$ub (- x8632::nbits-in-word (+ 16 x8632::fixnumshift))) (:%l tag))
+  (sarl (:$ub (- x8632::nbits-in-word 16)) (:%l tag))
+  (shll (:$ub x8632::fixnumshift) (:%l tag))
+  (cmpl (:%l object) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-signed-byte-16))))
+
+(define-x8632-vinsn require-u16 (()
+				((object :lisp))
+				((tag :u32)))
+  :again
+  (movl (:$l (lognot (ash #xffff x8632::fixnumshift))) (:%l tag))
+  (andl (:%l object) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-unsigned-byte-16))))
+
+(define-x8632-vinsn require-s32 (()
+				 ((object :lisp))
+				 ((tag :s32)))
+  :again
+  (testl (:$l x8632::fixnummask) (:%l object))
+  (movl (:%l object) (:%l tag))
+  (je :ok)
+  (andl (:$l x8632::fulltagmask) (:%l tag))
+  (cmpl (:$l x8632::fulltag-misc) (:%l tag))
+  (jne :bad)
+  (cmpl (:$l x8632::one-digit-bignum-header) (:@ x8632::misc-header-offset (:%l object)))
+  (jne :bad)
+  :ok
+  
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-signed-byte-32))))
+
+(define-x8632-vinsn require-u32 (()
+				 ((object :lisp))
+				 ((tag :s32)))
+  :again
+  (testl (:$l x8632::fixnummask) (:%l object))
+  (movl (:%l object) (:%l tag))
+  (je :ok-if-non-negative)
+  (andl (:$l x8632::fulltagmask) (:%l tag))
+  (cmpl (:$l x8632::fulltag-misc) (:%l tag))
+  (jne :bad)
+  (cmpl (:$l x8632::one-digit-bignum-header) (:@ x8632::misc-header-offset (:%l object)))
+  (je :one)
+  (cmpl (:$l x8632::two-digit-bignum-header) (:@ x8632::misc-header-offset (:%l object)))
+  (jne :bad)
+  (cmpl (:$b 0) (:@ (+ x8632::misc-data-offset 4) (:%l object)))
+  (je :ok)
+  :bad
+  (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-unsigned-byte-32))
+  (jmp :again)
+  :one
+  (movl (:@ x8632::misc-data-offset (:%l object)) (:%l tag))
+  :ok-if-non-negative
+  (testl (:%l tag) (:%l tag))
+  (js :bad)
+  :ok)
+
+(define-x8632-vinsn require-s64 (()
+				 ((object :lisp))
+				 ((tag :s32)))
+  :again
+  (testl (:$l x8632::fixnummask) (:%l object))
+  (movl (:%l object) (:%l tag))
+  (je :ok)
+  (andl (:$l x8632::fulltagmask) (:%l tag))
+  (cmpl (:$l x8632::fulltag-misc) (:%l tag))
+  (jne :bad)
+  (cmpl (:$l x8632::two-digit-bignum-header) (:@ x8632::misc-header-offset (:%l object)))
+  (jne :bad)
+  :ok
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-signed-byte-64))))
+
+(define-x8632-vinsn require-u64 (()
+				 ((object :lisp))
+				 ((tag :s32)))
+  :again
+  (testl (:$l x8632::fixnummask) (:%l object))
+  (movl (:%l object) (:%l tag))
+  (je :ok-if-non-negative)
+  (andl (:$l x8632::fulltagmask) (:%l tag))
+  (cmpl (:$l x8632::fulltag-misc) (:%l tag))
+  (jne :bad)
+  (cmpl (:$l x8632::two-digit-bignum-header) (:@ x8632::misc-header-offset (:%l object)))
+  (je :two)
+  (cmpl (:$l x8632::three-digit-bignum-header) (:@ x8632::misc-header-offset (:%l object)))
+  (jne :bad)
+  (cmpl (:$b 0) (:@ (+ x8632::misc-data-offset 8) (:%l object)))
+  (je :ok)
+  :bad
+  (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-unsigned-byte-64))
+  (jmp :again)
+  :two
+  (movl (:@ x8632::misc-data-offset (:%l object)) (:%l tag))
+  :ok-if-non-negative
+  (testl (:%l tag) (:%l tag))
+  (js :bad)
+  :ok)
+
+(define-x8632-vinsn require-char-code (()
+                                       ((object :lisp))
+                                       ((tag :u32)))
+  :again
+  (testb (:$b x8632::fixnummask) (:%b object))
+  (jne :bad)
+  (cmpl (:$l (ash #x110000 x8632::fixnumshift)) (:%l object))
+  (jae :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%l object) (:$ub arch::error-object-not-mod-char-code-limit))))
+
+(define-x8632-vinsn mask-base-char (((dest :u8))
+                                    ((src :lisp)))
+  (movzbl (:%b src) (:%l dest)))
+
+(define-x8632-vinsn event-poll (()
+                                ())
+  (btrl (:$ub 31) (:@ (:%seg :rcontext) x8632::tcr.interrupt-pending))
+  (jae :no-interrupt)
+  (ud2a)
+  (:byte 2)
+  :no-interrupt)
+
+;;; check-2d-bound
+;;; check-3d-bound
+
+(define-x8632-vinsn 2d-dim1 (((dest :u32))
+			     ((header :lisp)))
+  (movl (:@ (+ x8632::misc-data-offset (* 4 (1+ x8632::arrayH.dim0-cell)))
+	    (:%l header)) (:%l dest))
+  (sarl (:$ub x8632::fixnumshift) (:%l dest)))
+
+;;; 3d-dims
+
+;;; xxx
+(define-x8632-vinsn 2d-unscaled-index (((dest :imm)
+                                        (dim1 :u32))
+				       ((dim1 :u32)
+                                        (i :imm)
+					(j :imm)))
+
+  (imull (:%l i) (:%l dim1))
+  (leal (:@ (:%l j) (:%l dim1)) (:%l dest)))
+
+;;; 3d-unscaled-index
+
+(define-x8632-vinsn branch-unless-both-args-fixnums (()
+                                                     ((a :lisp)
+                                                      (b :lisp)
+                                                      (dest :label))
+                                                     ((tag :u8)))
+  (movl (:%l a) (:%l tag))
+  (orl (:%l b) (:%l tag))
+  ((:pred = (:apply %hard-regspec-value tag) x8632::eax)
+   (testb (:$b x8632::fixnummask) (:%accb tag)))
+  ((:and (:pred > (:apply %hard-regspec-value tag) x8632::eax)
+	 (:pred <= (:apply %hard-regspec-value tag) x8632::ebx))
+   (testb (:$b x8632::fixnummask) (:%b tag)))
+  ((:pred > (:apply %hard-regspec-value tag) x8632::ebx)
+   (testl (:$l x8632::fixnummask) (:%l tag)))
+  (jne dest))
+
+(define-x8632-vinsn branch-unless-arg-fixnum (()
+                                              ((a :lisp)
+                                               (dest :label)))
+  ((:pred <= (:apply %hard-regspec-value a) x8632::ebx)
+   (testb (:$b x8632::fixnummask) (:%b a)))
+  ((:pred > (:apply %hard-regspec-value a) x8632::ebx)
+   (testl (:$l x8632::fixnummask) (:%l a)))
+  (jne dest))
+
+(define-x8632-vinsn fixnum->single-float (((f :single-float))
+                                          ((arg :lisp))
+                                          ((unboxed :s32)))
+  (movl (:%l arg) (:%l unboxed))
+  (sarl (:$ub x8632::fixnumshift) (:%l unboxed))
+  (cvtsi2ssl (:%l unboxed) (:%xmm f)))
+
+(define-x8632-vinsn fixnum->double-float (((f :double-float))
+                                          ((arg :lisp))
+                                          ((unboxed :s32)))
+  (movl (:%l arg) (:%l unboxed))
+  (sarl (:$ub x8632::fixnumshift) (:%l unboxed))
+  (cvtsi2sdl (:%l unboxed) (:%xmm f)))
+
+(define-x8632-vinsn xchg-registers (()
+                                    ((a t)
+                                     (b t)))
+  (xchgl (:%l a) (:%l b)))
+
+(define-x8632-vinsn establish-fn (()
+                                  ())
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn %scharcode32 (((code :imm))
+				  ((str :lisp)
+				   (idx :imm))
+				  ((imm :u32)))
+  (movl (:@ x8632::misc-data-offset (:%l str) (:%l idx)) (:%l imm))
+  (imull (:$b x8632::fixnumone) (:%l imm) (:%l code)))
+
+(define-x8632-vinsn %set-scharcode32 (()
+				      ((str :lisp)
+				       (idx :imm)
+				       (code :imm))
+				      ((imm :u32)))
+  (movl (:%l code) (:%l imm))
+  (shrl (:$ub x8632::fixnumshift) (:%l imm))
+  (movl (:%l imm) (:@ x8632::misc-data-offset (:%l str) (:%l idx))))
+
+
+(define-x8632-subprim-jump-vinsn (tail-call-sym-slide) .SPtcallsymslide)
+
+(define-x8632-subprim-jump-vinsn (tail-call-sym-vsp) .SPtcallsymvsp)
+
+
+(define-x8632-vinsn character->code (((dest :u32))
+				     ((src :lisp)))
+  (movl (:%l src) (:%l dest))
+  (sarl (:$ub x8632::charcode-shift) (:%l dest)))
+
+(define-x8632-vinsn adjust-vsp (()
+				((amount :s32const)))
+  ((:and (:pred >= amount -128) (:pred <= amount 127))
+   (addl (:$b amount) (:%l x8632::esp)))
+  ((:not (:and (:pred >= amount -128) (:pred <= amount 127)))
+   (addl (:$l amount) (:%l x8632::esp))))
+
+
+(define-x8632-vinsn (call-subprim-2 :call :subprim-call) (((dest t))
+							  ((spno :s32const)
+							   (y t)
+							   (z t))
+                                                          ((entry (:label 1))))
+  (:talign 5)
+  (call (:@ spno))
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn %symbol->symptr (((dest :lisp))
+                                     ((src :lisp))
+                                     ((tag :u8)))
+  :resume
+  (cmpl (:$l (:apply target-nil-value)) (:%l src))
+  (je :nilsym)
+  (movl (:%l src) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l src)) (:%l tag))
+  (cmpl (:$b x8632::subtag-symbol) (:%l tag))
+  (jne :bad)
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movl (:% src) (:% dest)))
+  (jmp :ok)
+  :nilsym
+  (movl (:$l (:apply + (:apply target-nil-value) x8632::nilsym-offset)) (:%l dest))
+  :ok
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%l src) (:$ub x8632::subtag-symbol))))
+
+(define-x8632-vinsn single-float-bits (((dest :u32))
+				       ((src :lisp)))
+  (movl (:@ x8632::misc-data-offset (:%l src)) (:%l dest)))
+
+(define-x8632-vinsn zero-double-float-register (((dest :double-float))
+                                                ())
+  (movsd (:%xmm x8632::fpzero) (:%xmm dest)))
+
+(define-x8632-vinsn zero-single-float-register (((dest :single-float))
+                                                ())
+  (movss (:%xmm x8632::fpzero) (:%xmm dest)))
+
+(define-x8632-subprim-lea-jmp-vinsn (heap-rest-arg) .SPheap-rest-arg)
+(define-x8632-subprim-lea-jmp-vinsn (stack-rest-arg) .SPstack-rest-arg)
+(define-x8632-subprim-lea-jmp-vinsn (req-stack-rest-arg) .SPreq-stack-rest-arg)
+
+
+(define-x8632-subprim-call-vinsn (stack-misc-alloc) .SPstack-misc-alloc)
+
+(define-x8632-vinsn misc-element-count-fixnum (((dest :imm))
+                                               ((src :lisp))
+                                               ((temp :u32)))
+  (movl (:@ x8632::misc-header-offset (:%l src)) (:%l temp))
+  (shrl (:$ub x8632::num-subtag-bits) (:%l temp))
+  (leal (:@ (:%l temp) 4) (:%l dest)))
+
+(define-x8632-vinsn %logior2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (orl (:%l y) (:%l dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (orl (:%l x) (:%l dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (movl (:%l x) (:%l dest))
+    (orl (:%l y) (:%l dest)))))
+
+(define-x8632-vinsn %logand2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (andl (:%l y) (:%l dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (andl (:%l x) (:%l dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (movl (:%l x) (:%l dest))
+    (andl (:%l y) (:%l dest)))))
+
+(define-x8632-vinsn %logxor2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (xorl (:%l y) (:%l dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (xorl (:%l x) (:%l dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (movl (:%l x) (:%l dest))
+    (xorl (:%l y) (:%l dest)))))
+
+
+(define-x8632-subprim-call-vinsn (integer-sign) .SPinteger-sign)
+
+(define-x8632-subprim-call-vinsn (misc-ref) .SPmisc-ref)
+
+(define-x8632-subprim-call-vinsn (ksignalerr) .SPksignalerr)
+
+(define-x8632-subprim-call-vinsn (misc-alloc-init) .SPmisc-alloc-init)
+
+(define-x8632-subprim-call-vinsn (misc-alloc) .SPmisc-alloc)
+
+(define-x8632-subprim-lea-jmp-vinsn (make-stack-gvector)  .SPstkgvector)
+
+(define-x8632-vinsn load-character-constant (((dest :lisp))
+                                             ((code :u32const))
+                                             ())
+  (movl (:$l (:apply logior (:apply ash code 8) x8632::subtag-character))
+        (:%l dest)))
+
+
+(define-x8632-vinsn setup-single-float-allocation (()
+						   ())
+  (movl (:$l (arch::make-vheader x8632::single-float.element-count x8632::subtag-single-float)) (:%l x8632::imm0))
+  (movd (:%l x8632::imm0) (:%mmx x8632::mm0))
+  (movl (:$l (- x8632::single-float.size x8632::fulltag-misc)) (:%l x8632::imm0)))
+  
+(define-x8632-vinsn setup-double-float-allocation (()
+                                                   ())
+  (movl (:$l (arch::make-vheader x8632::double-float.element-count x8632::subtag-double-float)) (:%l x8632::imm0))
+  (movd (:%l x8632::imm0) (:%mmx x8632::mm0))
+  (movl (:$l (- x8632::double-float.size x8632::fulltag-misc)) (:%l x8632::imm0)))
+
+(define-x8632-vinsn set-single-float-value (()
+                                            ((node :lisp)
+                                             (val :single-float)))
+  (movss (:%xmm val) (:@ x8632::single-float.value (:%l node))))
+
+(define-x8632-vinsn set-double-float-value (()
+                                            ((node :lisp)
+                                             (val :double-float)))
+  (movsd (:%xmm val) (:@ x8632::double-float.value (:%l node))))
+
+(define-x8632-vinsn word-index-and-bitnum-from-index (((word-index :u32)
+                                                       (bitnum :u8))
+                                                      ((index :imm)))
+  (movl (:%l index) (:%l word-index))
+  (shrl (:$ub x8632::fixnumshift) (:%l word-index))
+  (movl (:$l 31) (:%l bitnum))
+  (andl (:%l word-index) (:%l bitnum))
+  (shrl (:$ub 5) (:%l word-index)))
+
+(define-x8632-vinsn ref-bit-vector-fixnum (((dest :imm)
+                                            (bitnum :u8))
+                                           ((bitnum :u8)
+                                            (bitvector :lisp)
+                                            (word-index :u32)))
+  (btl (:%l bitnum) (:@ x8632::misc-data-offset (:%l bitvector) (:%l word-index) 4))
+  (setb (:%b bitnum))
+  (negb (:%b bitnum))
+  (andl (:$l x8632::fixnumone) (:%l bitnum))
+  (movl (:%l bitnum) (:%l dest)))
+
+(define-x8632-vinsn nref-bit-vector-fixnum (((dest :imm)
+					     (bitnum :s32))
+					    ((bitnum :s32)
+					     (bitvector :lisp))
+					    ())
+  (btl (:%l bitnum) (:@ x8632::misc-data-offset (:%l bitvector)))
+  (setc (:%b bitnum))
+  (movzbl (:%b bitnum) (:%l bitnum))
+  (imull (:$b x8632::fixnumone) (:%l bitnum) (:%l dest)))
+
+(define-x8632-vinsn nref-bit-vector-flags (()
+					   ((bitnum :s32)
+					    (bitvector :lisp))
+					   ())
+  (btl (:%l bitnum) (:@ x8632::misc-data-offset (:%l bitvector))))
+
+(define-x8632-vinsn misc-ref-c-bit-fixnum (((dest :imm))
+                                           ((src :lisp)
+                                            (idx :u32const))
+                                           ((temp :u8)))
+  (btl (:$ub (:apply logand 31 idx))
+       (:@ (:apply + x8632::misc-data-offset (:apply ash (:apply ash idx -5) x8632::word-shift)) (:%l src)))
+  (setc (:%b temp))
+  (movzbl (:%b temp) (:%l temp))
+  (imull (:$b x8632::fixnumone) (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn misc-ref-c-bit-flags (()
+					  ((src :lisp)
+					   (idx :u64const)))
+  (btl (:$ub (:apply logand 31 idx))
+       (:@ (:apply + x8632::misc-data-offset (:apply ash (:apply ash idx -5) x8632::word-shift)) (:%l src))))
+
+(define-x8632-vinsn set-macptr-address (()
+					((addr :address)
+					 (src :lisp))
+					())
+  (movl (:%l addr) (:@ x8632::macptr.address (:%l src))))
+
+(define-x8632-vinsn deref-macptr (((addr :address))
+				  ((src :lisp))
+				  ())
+  (movl (:@ x8632::macptr.address (:%l src)) (:%l addr)))
+
+(define-x8632-vinsn setup-macptr-allocation (()
+                                             ((src :address)))
+  (movd (:%l src) (:%mmx x8632::mm1))	;see %set-new-macptr-value, below
+  (movl (:$l x8632::macptr-header) (:%l x8632::imm0))
+  (movd (:%l x8632::imm0) (:%mmx x8632::mm0))
+  (movl (:$l (- x8632::macptr.size x8632::fulltag-misc)) (:%l x8632::imm0)))
+
+(define-x8632-vinsn %set-new-macptr-value (()
+                                           ((ptr :lisp)))
+  (movd (:%mmx x8632::mm1) (:@ x8632::macptr.address (:%l ptr))))
+
+(define-x8632-vinsn mem-ref-natural (((dest :u32))
+				     ((src :address)
+				      (index :s32)))
+  (movl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-fullword (((dest :u32))
+					((src :address)
+					 (index :s32const)))
+  ((:pred = index 0)
+   (movl (:@ (:%l src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movl (:@ index (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn mem-ref-c-signed-fullword (((dest :s32))
+                                               ((src :address)
+                                                (index :s32const)))
+  ((:pred = index 0)
+   (movl (:@ (:%l src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movl (:@ index (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn mem-ref-c-single-float (((dest :single-float))
+					    ((src :address)
+					     (index :s32const)))
+  ((:pred = index 0)
+   (movss (:@ (:%l src)) (:%xmm dest)))
+  ((:not (:pred = index 0))
+   (movss (:@ index (:%l src)) (:%xmm dest))))
+
+(define-x8632-vinsn mem-set-c-single-float (()
+					    ((val :single-float)
+					     (src :address)
+					     (index :s16const)))
+  ((:pred = index 0)
+   (movss (:%xmm val) (:@ (:%l src))))
+  ((:not (:pred = index 0))
+   (movss (:%xmm val) (:@ index (:%l src)))))
+
+(define-x8632-vinsn mem-ref-c-natural (((dest :u32))
+                                       ((src :address)
+                                        (index :s32const)))
+  ((:pred = index 0)
+   (movl (:@ (:%l src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movl (:@ index (:%l src)) (:%l dest))))
+
+(define-x8632-vinsn mem-ref-c-double-float (((dest :double-float))
+                                            ((src :address)
+                                             (index :s32const)))
+  ((:pred = index 0)
+   (movsd (:@ (:%l src)) (:%xmm dest)))
+  ((:not (:pred = index 0))
+   (movsd (:@ index (:%l src)) (:%xmm dest))))
+
+(define-x8632-vinsn mem-set-c-double-float (()
+					    ((val :double-float)
+					     (src :address)
+					     (index :s32const)))
+  ((:pred = index 0)
+   (movsd (:%xmm val) (:@ (:%l src))))
+  ((:not (:pred = index 0))
+   (movsd (:%xmm val) (:@ index (:%l src)))))
+
+(define-x8632-vinsn mem-ref-fullword (((dest :u32))
+				      ((src :address)
+				       (index :s32)))
+  (movl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-signed-fullword (((dest :s32))
+                                             ((src :address)
+                                              (index :s32)))
+  (movl (:@ (:%l src) (:%l index)) (:%l dest)))
+
+(define-x8632-vinsn macptr->stack (((dest :lisp))
+                                   ((ptr :address))
+				   ((temp :imm)))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%mmx x8632::stack-temp))
+  (subl (:$b (+ 8 x8632::macptr.size)) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:%l x8632::ebp) (:@ 4 (:%l temp)))
+  (leal (:@ (+ 8 x8632::fulltag-misc) (:%l  temp)) (:%l dest))
+  (movl (:$l x8632::macptr-header) (:@ x8632::macptr.header (:%l dest)))
+  (movl (:%l ptr) (:@ x8632::macptr.address (:%l dest)))
+  (movsd (:%xmm x8632::fpzero)  (:@ x8632::macptr.domain (:%l dest))))
+
+(define-x8632-vinsn fixnum->signed-natural (((dest :s32))
+                                            ((src :imm)))
+  (movl (:%l src) (:%l dest))
+  (sarl (:$ub x8632::fixnumshift) (:%l dest)))
+
+(define-x8632-vinsn fixnum->unsigned-natural (((dest :u32))
+                                              ((src :imm)))
+  (movl (:%l src) (:%l dest))
+  (shrl (:$ub x8632::fixnumshift) (:%l dest)))
+
+(define-x8632-vinsn mem-set-double-float (()
+					  ((val :double-float)
+					   (src :address)
+					   (index :s32)))
+  (movsd (:%xmm val) (:@ (:%l src) (:%l index))))
+
+(define-x8632-vinsn mem-set-single-float (()
+					  ((val :single-float)
+					   (src :address)
+					   (index :s32)))
+  (movss (:%xmm val) (:@ (:%l src) (:%l index))))
+
+(define-x8632-vinsn mem-set-c-fullword (()
+                                          ((val :u32)
+                                           (dest :address)
+                                           (offset :s32const)))
+  ((:pred = offset 0)
+   (movl (:%l val) (:@ (:%l dest))))
+  ((:not (:pred = offset 0))
+   (movl (:%l val) (:@ offset (:%l dest)))))
+
+(define-x8632-vinsn mem-set-bit-variable-value (((src :address))
+                                                ((src :address)
+                                                 (offset :lisp)
+                                                 (value :lisp))
+                                                ((temp :lisp)))
+  ;; (mark-as-imm temp)
+  (btrl (:$ub (:apply %hard-regspec-value temp))
+	(:@ (:%seg :rcontext) x8632::tcr.node-regs-mask))
+  (movl (:%l offset) (:%l temp))
+  (shrl (:$ub (+ 5 x8632::fixnumshift)) (:%l temp))
+  (leal (:@ (:%l src) (:%l temp) 4) (:%l src))
+  (movl (:%l offset) (:%l temp))
+  (shrl (:$ub x8632::fixnumshift) (:%l temp))
+  (andl (:$l 31) (:%l temp))
+  (testl (:%l value) (:%l value))
+  (jne :set)
+  (btrl (:%l temp) (:@ (:%l src)))
+  (jmp :done)
+  :set
+  (btsl (:%l temp) (:@ (:%l src)))
+  :done
+  ;; (mark-as-node temp)
+  (xorl (:%l temp) (:%l temp))
+  (btsl (:$ub (:apply %hard-regspec-value temp))
+	(:@ (:%seg :rcontext) x8632::tcr.node-regs-mask)))
+
+
+(define-x8632-vinsn mem-set-c-bit-variable-value (()
+                                                  ((src :address)
+                                                   (offset :s32const)
+                                                   (value :lisp)))
+  (testl (:%l value) (:%l value))
+  (jne :set)
+  ((:pred = 0 (:apply ash offset -5))
+   (btrl (:$ub (:apply logand 31 offset))
+        (:@  (:%l src))))
+  ((:not (:pred = 0 (:apply ash offset -5)))
+   (btrl (:$ub (:apply logand 31 offset))
+         (:@ (:apply ash (:apply ash offset -5) 4) (:%l src))))
+  (jmp :done)
+  :set
+  ((:pred = 0 (:apply ash offset -5))
+   (btsl (:$ub (:apply logand 31 offset))
+         (:@  (:%l src))))
+  ((:not (:pred = 0 (:apply ash offset -5)))
+   (btsl (:$ub (:apply logand 31 offset))
+         (:@ (:apply ash (:apply ash offset -5) 2) (:%l src))))
+  :done)
+
+(define-x8632-vinsn %natural+  (((result :u32))
+                               ((result :u32)
+                                (other :u32)))
+  (addl (:%l other) (:%l result)))
+
+(define-x8632-vinsn %natural+-c (((result :u32))
+                                ((result :u32)
+                                 (constant :u32const)))
+  (addl (:$l (:apply unsigned-to-signed constant 32)) (:%l result)))
+
+(define-x8632-vinsn %natural-  (((result :u32))
+				((result :u32)
+				 (other :u32)))
+  (subl (:%l other) (:%l result)))
+
+(define-x8632-vinsn %natural--c (((result :u32))
+                                ((result :u32)
+                                 (constant :u32const)))
+  (subl (:$l (:apply unsigned-to-signed constant 32)) (:%l result)))
+
+(define-x8632-vinsn %natural-logior (((result :u32))
+                                    ((result :u32)
+                                     (other :u32)))
+  (orl (:%l other) (:%l result)))
+
+(define-x8632-vinsn %natural-logior-c (((result :u32))
+                                      ((result :u32)
+                                       (constant :u32const)))
+  (orl (:$l (:apply unsigned-to-signed constant 32)) (:%l result)))
+
+(define-x8632-vinsn %natural-logand (((result :u32))
+                                    ((result :u32)
+                                     (other :u32)))
+  (andl (:%l other) (:%l result)))
+
+(define-x8632-vinsn %natural-logand-c (((result :u32))
+                                      ((result :u32)
+                                       (constant :u32const)))
+  (andl (:$l (:apply unsigned-to-signed constant 32)) (:%l result)))
+
+(define-x8632-vinsn %natural-logxor (((result :u32))
+                                    ((result :u32)
+                                     (other :u32)))
+  (xorl (:%l other) (:%l result)))
+
+(define-x8632-vinsn %natural-logxor-c (((result :u32))
+                                       ((result :u32)
+                                        (constant :u32const)))
+  (xorl (:$l (:apply unsigned-to-signed constant 32)) (:%l result)))
+
+(define-x8632-vinsn natural-shift-left (((dest :u32))
+                                        ((dest :u32)
+                                         (amt :u8const)))
+  (shll (:$ub amt) (:%l dest)))
+
+(define-x8632-vinsn natural-shift-right (((dest :u32))
+                                         ((dest :u32)
+                                          (amt :u8const)))
+  (shrl (:$ub amt) (:%l dest)))
+
+(define-x8632-vinsn recover-fn (()
+				())
+  (movl (:$self 0) (:%l x8632::fn)))
+
+;;; xxx probably wrong
+(define-x8632-vinsn (call-subprim-3 :call :subprim-call) (((dest t))
+							  ((spno :s32const)
+							   (x t)
+							   (y t)
+							   (z t))
+                                                          ((entry (:label 1))))
+  (:talign 5)
+  (call (:@ spno))
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn vcell-ref (((dest :lisp))
+			       ((vcell :lisp)))
+  (movl (:@ x8632::misc-data-offset (:%l vcell)) (:%l dest)))
+
+(define-x8632-vinsn setup-vcell-allocation (()
+                                            ())
+  (movl (:$l x8632::value-cell-header) (:%l x8632::imm0))
+  (movd (:%l x8632::imm0) (:%mmx x8632::mm0))
+  (movl (:$l (- x8632::value-cell.size x8632::fulltag-misc)) (:%l x8632::imm0)))
+
+(define-x8632-vinsn %init-vcell (()
+                                 ((vcell :lisp)
+                                  (closed :lisp)))
+  (movl (:%l closed) (:@ x8632::value-cell.value (:%l vcell))))
+
+;;; "old" mkunwind.  Used by PROGV, since the binding of *interrupt-level*
+;;; on entry to the new mkunwind confuses the issue.
+
+(define-x8632-vinsn (mkunwind :call :subprim-call) (()
+                                                     ((protform-lab :label)
+                                                      (cleanup-lab :label)))
+  (leal (:@ (:^ protform-lab) (:%l x8632::fn)) (:%l x8632::ra0))
+  (leal (:@ (:^ cleanup-lab)  (:%l x8632::fn)) (:%l x8632::xfn))
+  (jmp (:@ .SPmkunwind)))
+
+;;; Funcall the function or symbol in temp0 and obtain the single
+;;; value that it returns.
+(define-x8632-subprim-call-vinsn (funcall) .SPfuncall)
+
+(define-x8632-vinsn tail-funcall (()
+                                  ()
+                                  ((tag :u8)))
+  :resume
+  (movl (:%l x8632::temp0) (:%l tag))
+  ((:pred = (:apply %hard-regspec-value tag) x8632::eax)
+   (andl (:$b x8632::tagmask) (:%accl tag))
+   (cmpl (:$b x8632::tag-misc) (:%accl tag)))
+  ((:pred > (:apply %hard-regspec-value tag) x8632::eax)
+   (andl (:$b x8632::tagmask) (:%l tag))
+   (cmpl (:$b x8632::tag-misc) (:%l tag)))
+  (jne :bad)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l x8632::temp0)) (:%l tag))
+  (cmpl (:$b x8632::subtag-function) (:%l tag))
+  (je :go)
+  (cmpl (:$b x8632::subtag-symbol) (:%l tag))
+  (cmovel (:@ x8632::symbol.fcell (:%l x8632::temp0)) (:%l x8632::temp0))
+  (jne :bad)
+  :go
+  (jmp (:%l x8632::temp0))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-not-callable)))
+
+;;; Magic numbers in here include the address of .SPcall-closure.
+
+;;; movl $self, %fn
+;;; jmp *20660 (.SPcall-closure)
+(define-x8632-vinsn init-nclosure (()
+                                   ((closure :lisp)))
+  (movb (:$b 6) (:@ x8632::misc-data-offset (:%l closure))) ;imm word count
+  (movb (:$b #xbf) (:@ (+ x8632::misc-data-offset 2) (:%l closure))) ;movl $self, %fn
+  (movl (:%l closure) (:@ (+ x8632::misc-data-offset 3) (:%l closure)))
+  (movb (:$b #xff) (:@ (+ x8632::misc-data-offset 7) (:%l closure))) ;jmp
+  (movl (:$l #x0150b425) (:@ (+ x8632::misc-data-offset 8) (:%l closure))) ;.SPcall-closure
+  ;; already aligned
+  ;; (movl ($ 0) (:@ (+ x8632::misc-data-offset 12))) ;"end" of self-references
+  (movb (:$b 7) (:@ (+ x8632::misc-data-offset 16) (:%l closure))) ;self-reference offset
+  (movb (:$b x8632::function-boundary-marker) (:@ (+ x8632::misc-data-offset 20) (:%l closure))))
+
+(define-x8632-vinsn finalize-closure (((closure :lisp))
+                                      ((closure :lisp)))
+  (nop))
+
+
+(define-x8632-vinsn (ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val)))))
+  (:talign 5)
+  (call (:@ .SPspecrefcheck))
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn ref-symbol-value-inline (((dest :lisp))
+					     ((src (:lisp (:ne dest))))
+					     ((table :imm)
+					      (idx :imm)))
+  :resume
+  (movl (:@ x8632::symbol.binding-index (:%l src)) (:%l idx))
+  (rcmpl (:%l idx) (:@ (:%seg :rcontext) x8632::tcr.tlb-limit))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.tlb-pointer) (:%l table))
+  (jae :symbol)
+  (movl (:@ (:%l table) (:%l idx)) (:%l dest))
+  (cmpl (:$l x8632::subtag-no-thread-local-binding) (:%l dest))
+  (jne :test)
+  :symbol
+  (movl (:@ x8632::symbol.vcell (:%l src)) (:%l dest))
+  :test
+  (cmpl (:$l x8632::unbound-marker) (:%l dest))
+  (je :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-unbound (:%l src))))
+
+(define-x8632-vinsn (%ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val)))))
+  (:talign 5)
+  (call (:@ .SPspecref))
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn %ref-symbol-value-inline (((dest :lisp))
+                                              ((src (:lisp (:ne dest))))
+                                              ((table :imm)
+                                               (idx :imm)))
+  (movl (:@ x8632::symbol.binding-index (:%l src)) (:%l idx))
+  (rcmpl (:%l idx) (:@ (:%seg :rcontext) x8632::tcr.tlb-limit))
+  (jae :symbol)
+  (addl (:@ (:%seg :rcontext) x8632::tcr.tlb-pointer) (:%l idx))
+  (movl (:@ (:%l idx)) (:%l dest))
+  (cmpl (:$l x8632::subtag-no-thread-local-binding) (:%l dest))
+  (jne :done)
+  :symbol
+  (movl (:@ x8632::symbol.vcell (:%l src)) (:%l dest))
+  :done)
+
+(define-x8632-vinsn ref-interrupt-level (((dest :imm))
+                                         ()
+                                         ((temp :u32)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.tlb-pointer) (:%l temp))
+  (movl (:@ x8632::interrupt-level-binding-index (:%l temp)) (:%l dest)))
+
+(define-x8632-subprim-lea-jmp-vinsn (bind-nil)  .SPbind-nil)
+
+(define-x8632-subprim-lea-jmp-vinsn (bind-self)  .SPbind-self)
+
+(define-x8632-subprim-lea-jmp-vinsn (bind-self-boundp-check)  .SPbind-self-boundp-check)
+
+(define-x8632-subprim-lea-jmp-vinsn (bind)  .SPbind)
+
+(define-x8632-vinsn (dpayback :call :subprim-call) (()
+                                                    ((n :s16const))
+                                                    ((temp (:u32 #.x8632::imm0))
+                                                     (entry (:label 1))))
+  ((:pred > n 0)
+   ((:pred > n 1)
+    (movl (:$l n) (:%l temp))
+    (:talign 5)
+    (call (:@ .SPunbind-n)))
+   ((:pred = n 1)
+    (:talign 5)
+    (call (:@ .SPunbind)))
+   (movl (:$self 0) (:%l x8632::fn))))
+
+(define-x8632-subprim-jump-vinsn (tail-call-sym-gen) .SPtcallsymgen)
+
+(define-x8632-subprim-call-vinsn (make-stack-list)  .Spmakestacklist)
+
+(define-x8632-vinsn node-slot-ref  (((dest :lisp))
+				    ((node :lisp)
+				     (cellno :u32const)))
+  (movl (:@ (:apply + x8632::misc-data-offset (:apply ash cellno 2))
+            (:%l node)) (:%l dest)))
+
+(define-x8632-subprim-lea-jmp-vinsn (stack-cons-list)  .SPstkconslist)
+
+(define-x8632-vinsn save-lexpr-argregs (()
+                                        ((min-fixed :u16const)))
+  ((:pred >= min-fixed $numx8632argregs)
+   (pushl (:%l x8632::arg_y))
+   (pushl (:%l x8632::arg_z)))
+  ((:pred = min-fixed 1)                ; at least one arg
+   (rcmpl (:%l x8632::nargs) (:$b (ash 1 x8632::word-shift)))
+   (je :z1)				;skip arg_y if exactly 1
+   (pushl (:%l x8632::arg_y))
+   :z1
+   (pushl (:%l x8632::arg_z)))
+  ((:pred = min-fixed 0)
+   (rcmpl (:%l x8632::nargs) (:$b (ash 1 x8632::word-shift)))
+   (je :z0)				;exactly one
+   (jl :none)				;none
+                                        ;two or more...
+   (pushl (:%l x8632::arg_y))
+   :z0
+   (pushl (:%l x8632::arg_z))
+   :none
+   )
+  ((:not (:pred = min-fixed 0))
+   (leal (:@ (:apply - (:apply ash min-fixed x8632::word-shift)) (:%l x8632::nargs))
+         (:%l x8632::nargs)))
+  (pushl (:%l x8632::nargs))
+  (movl (:%l x8632::esp) (:%l x8632::arg_z)))
+
+;;; The frame that was built (by SAVE-LISP-CONTEXT-VARIABLE-ARG-COUNT
+;;; and SAVE-LEXPR-ARGREGS) contains an unknown number of arguments
+;;; followed by the count of non-required arguments; the count is on
+;;; top of the stack and its address is in %arg_z.  We need to build a
+;;; frame so that the function can address its arguments (copies of
+;;; the required arguments and the lexpr) and locals; when the
+;;; function returns, it should one or more values (depending on how
+;;; it was called) and discard the hidden lexpr frame.  At this point,
+;;; %ra0 still contains the "real" return address. If it's not the
+;;; magic multiple-value address, we can make the function return to
+;;; something that does a single-value return (.SPpopj); otherwise, we
+;;; need to make it return multiple values to the real caller. (Unlike
+;;; the PPC, this case only involves creating one frame here, but that
+;;; frame has two return addresses.)
+(define-x8632-vinsn build-lexpr-frame (()
+                                       ()
+                                       ((temp :imm)
+					(ra0 (:lisp #.x8632::ra0))))
+  (movl (:@ (:apply + (:apply target-nil-value) (x8632::%kernel-global 'x86::ret1valaddr)))
+        (:%l temp))
+  (cmpl (:%l temp) (:%l ra0))
+  (je :multiple)
+  (pushl (:@ (:apply + (:apply target-nil-value) (x8632::%kernel-global 'x86::lexpr-return1v))))
+  (jmp :finish)
+  :multiple
+  (pushl (:@ (:apply + (:apply target-nil-value) (x8632::%kernel-global 'x86::lexpr-return))))
+  (pushl (:%l temp))
+  :finish
+  (pushl (:%l x8632::ebp))
+  (movl (:%l x8632::esp) (:%l x8632::ebp)))
+
+(define-x8632-vinsn copy-lexpr-argument (()
+					 ((n :u16const))
+					 ((temp :imm)))
+  (movl (:@ (:%l x8632::arg_z)) (:%l temp))
+  (pushl (:@ (:apply ash n x8632::word-shift) (:%l x8632::arg_z) (:%l temp))))
+
+(define-x8632-vinsn %current-tcr (((dest :lisp))
+                                 ())
+  (movl (:@ (:%seg :rcontext) x8632::tcr.linear) (:%l dest)))
+
+(define-x8632-vinsn (setq-special :call :subprim-call)
+    (()
+     ((sym :lisp)
+      (val :lisp))
+     ((entry (:label 1))))
+  (:talign 5)
+  (call (:@ .SPspecset))
+  (movl (:$self 0) (:%l x8632::fn)))
+
+(define-x8632-vinsn pop-argument-registers (()
+                                            ())
+  (testl (:%l x8632::nargs) (:%l x8632::nargs))
+  (je :done)
+  (rcmpl (:%l x8632::nargs) (:$l (ash 1 x8632::word-shift)))
+  (popl (:%l x8632::arg_z))
+  (je :done)
+  (popl (:%l x8632::arg_y))
+  :done)
+
+(define-x8632-vinsn %symptr->symvector (((target :lisp))
+                                        ((target :lisp)))
+  (nop))
+
+(define-x8632-vinsn %symvector->symptr (((target :lisp))
+                                        ((target :lisp)))
+  (nop))
+
+(define-x8632-subprim-lea-jmp-vinsn (spread-lexpr)  .SPspread-lexpr-z)
+
+(define-x8632-vinsn mem-ref-double-float (((dest :double-float))
+					  ((src :address)
+					   (index :s32)))
+  (movsd (:@ (:%l src) (:%l index)) (:%xmm dest)))
+
+(define-x8632-vinsn mem-ref-single-float (((dest :single-float))
+					  ((src :address)
+					   (index :s32)))
+  (movss (:@ (:%l src) (:%l index)) (:%xmm dest)))
+
+;;; This would normally be put in %nargs, but we need an
+;;; extra node register for passing stuff into
+;;; SPdestructuring_bind and friends.
+(define-x8632-vinsn load-adl (()
+			      ((n :u32const)))
+  (movl (:$l n) (:%l x8632::imm0)))
+
+(define-x8632-subprim-lea-jmp-vinsn (macro-bind) .SPmacro-bind)
+
+(define-x8632-subprim-lea-jmp-vinsn (destructuring-bind-inner) .SPdestructuring-bind-inner)
+
+(define-x8632-subprim-lea-jmp-vinsn  (destructuring-bind) .SPdestructuring-bind)
+
+
+(define-x8632-vinsn symbol-function (((val :lisp))
+                                     ((sym (:lisp (:ne val))))
+                                     ((tag :u8)))
+  :resume
+  (movl (:@ x8632::symbol.fcell (:%l sym)) (:%l val))
+  (movl (:%l val) (:%l tag))
+  (andl (:$b x8632::tagmask) (:%l tag))
+  (cmpl (:$b x8632::tag-misc) (:%l tag))
+  (jne :bad)
+  (movsbl (:@ x8632::misc-subtag-offset (:%l val)) (:%l tag))
+  (cmpl (:$b x8632::subtag-function) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-udf (:%l sym))))
+
+(define-x8632-subprim-jump-vinsn (tail-call-fn-slide) .SPtcallnfnslide)
+
+(define-x8632-vinsn load-double-float-constant (((dest :double-float))
+                                                ((lab :label)))
+  (movsd (:@ (:^ lab) (:%l x8632::fn)) (:%xmm dest)))
+
+(define-x8632-vinsn load-single-float-constant (((dest :single-float))
+                                                ((lab :label)))
+  (movss (:@ (:^ lab) (:%l x8632::fn)) (:%xmm dest)))
+
+(define-x8632-subprim-call-vinsn (misc-set) .SPmisc-set)
+
+(define-x8632-subprim-lea-jmp-vinsn (slide-values) .SPmvslide)
+
+(define-x8632-subprim-lea-jmp-vinsn (spread-list)  .SPspreadargz)
+
+;;; Even though it's implemented by calling a subprim, THROW is really
+;;; a JUMP (to a possibly unknown destination).  If the destination's
+;;; really known, it should probably be inlined (stack-cleanup, value
+;;; transfer & jump ...)
+(define-x8632-vinsn (throw :jump-unknown) (()
+						 ()
+                                                 ((entry (:label 1))
+						  (ra (:lisp #.x8632::ra0))))
+  (leal (:@ (:^ :back) (:%l x8632::fn)) (:%l ra))
+  (:talign 5)
+  (jmp (:@ .SPthrow))
+  :back
+  (movl (:$self 0) (:%l x8632::fn))
+  (uuo-error-reg-not-tag (:%l x8632::temp0) (:$ub x8632::subtag-catch-frame)))
+
+(define-x8632-vinsn unbox-base-char (((dest :u32))
+				     ((src :lisp)))
+  (movl (:%l src) (:%l dest))
+  ((:pred = (:apply %hard-regspec-value dest) x8632::eax)
+   (cmpb (:$b x8632::subtag-character) (:%accb dest)))
+  ((:and (:pred > (:apply %hard-regspec-value dest) x8632::eax)
+	 (:pred <= (:apply %hard-regspec-value dest) x8632::ebx))
+   (cmpb (:$b x8632::subtag-character) (:%b dest)))
+  ((:pred > (:apply %hard-regspec-value dest) x8632::ebx)
+   ;; very rare case, if even possible...
+   (andl (:$l #xff) (:%l dest))
+   (cmpl (:$b x8632::subtag-character) (:%l dest))
+   (cmovel (:%l src) (:%l dest)))
+  (je ::got-it)
+  (uuo-error-reg-not-tag (:%l src) (:$ub x8632::subtag-character))
+  :got-it
+  (shrl (:$ub x8632::charcode-shift) (:%l dest)))
+
+(define-x8632-subprim-lea-jmp-vinsn (save-values) .SPsave-values)
+
+(define-x8632-subprim-lea-jmp-vinsn (recover-values)  .SPrecover-values)
+
+(define-x8632-subprim-lea-jmp-vinsn (recover-values-for-mvcall) .SPrecover-values-for-mvcall)
+
+(define-x8632-subprim-lea-jmp-vinsn (add-values) .SPadd-values)
+
+(define-x8632-subprim-call-vinsn (make-stack-block)  .SPmakestackblock)
+
+(define-x8632-subprim-call-vinsn (make-stack-block0)  .Spmakestackblock0)
+
+;;; "dest" is preallocated, presumably on a stack somewhere.
+(define-x8632-vinsn store-single (()
+				  ((dest :lisp)
+				   (source :single-float))
+				  ())
+  (movss (:%xmm source) (:@  x8632::single-float.value (:%l dest))))
+
+;;; "dest" is preallocated, presumably on a stack somewhere.
+(define-x8632-vinsn store-double (()
+				  ((dest :lisp)
+				   (source :double-float))
+				  ())
+  (movsd (:%xmm source) (:@  x8632::double-float.value (:%l dest))))
+
+(define-x8632-vinsn fixnum->char (((dest :lisp))
+				  ((src :imm))
+				  ((temp :u32)))
+  (movl (:%l src) (:%l temp))
+  (sarl (:$ub (+ x8632::fixnumshift 1)) (:%l temp))
+  (cmpl (:$l (ash #xfffe -1)) (:%l temp))
+  (je :bad-if-eq)
+  (sarl (:$ub (- 11 1)) (:%l temp))
+  (cmpl (:$b (ash #xd800 -11))(:%l temp))
+  :bad-if-eq
+  (movl (:$l (:apply target-nil-value)) (:%l temp))
+  (cmovel (:%l temp) (:%l dest))
+  (je :done)
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movl (:%l src) (:%l dest)))
+  (shll (:$ub (- x8632::charcode-shift x8632::fixnumshift)) (:%l dest))
+  (addl (:$b x8632::subtag-character) (:%l dest))
+  :done)
+
+;;; src is known to be a code for which CODE-CHAR returns non-nil.
+(define-x8632-vinsn code-char->char (((dest :lisp))
+				     ((src :imm))
+				     ())
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movl (:%l src) (:%l dest)))
+  (shll (:$ub (- x8632::charcode-shift x8632::fixnumshift)) (:%l dest))
+  (addl (:$b x8632::subtag-character) (:%l dest))
+  :done)
+
+(define-x8632-vinsn sign-extend-halfword (((dest :imm))
+					  ((src :imm)))
+  (movl (:%l src ) (:%l dest))
+  (shll (:$ub (- 16 x8632::fixnumshift)) (:%l dest))
+  (sarl (:$ub (- 16 x8632::fixnumshift)) (:%l dest)))
+
+(define-x8632-subprim-jump-vinsn (tail-funcall-gen) .SPtfuncallgen)
+
+(define-x8632-vinsn %init-gvector (()
+                                   ((v :lisp)
+                                    (nbytes :u32const))
+                                   ((count :imm)))
+  (movl (:$l nbytes) (:%l count))
+  (jmp :test)
+  :loop
+  (popl (:@ x8632::misc-data-offset (:%l v) (:%l count)))
+  :test
+  (subl (:$b x8632::node-size) (:%l count))
+  (jge :loop))
+
+(define-x8632-subprim-jump-vinsn (tail-funcall-slide) .SPtfuncallslide)
+
+(define-x8632-vinsn nth-value (((result :lisp))
+                               ()
+                               ((temp :u32)
+				(nargs (:lisp #.x8632::nargs))))
+  (leal (:@ (:%l x8632::esp) (:%l x8632::nargs)) (:%l temp))
+  (subl (:@ (:%l temp)) (:%l x8632::nargs))
+  (movl (:$l (:apply target-nil-value)) (:%l result))
+  (jle :done)
+  ;; I -think- that a CMOV would be safe here, assuming that N wasn't
+  ;; extremely large.  Don't know if we can assume that.
+  (movl (:@ (- x8632::node-size) (:%l x8632::esp) (:%l x8632::nargs)) (:%l result))
+  :done
+  (leal (:@ x8632::node-size (:%l temp)) (:%l x8632::esp)))
+
+
+(define-x8632-subprim-lea-jmp-vinsn (req-heap-rest-arg) .SPreq-heap-rest-arg)
+
+(define-x8632-subprim-call-vinsn (stack-misc-alloc-init)  .SPstack-misc-alloc-init)
+
+(define-x8632-vinsn %debug-trap (()
+                                 ())
+  (uuo-error-debug-trap))
+
+(define-x8632-vinsn double-to-single (((result :single-float))
+                                      ((arg :double-float)))
+  (cvtsd2ss (:%xmm arg) (:%xmm result)))
+
+(define-x8632-vinsn single-to-double (((result :double-float))
+                                      ((arg :single-float)))
+  (cvtss2sd (:%xmm arg) (:%xmm result)))
+
+(define-x8632-vinsn alloc-c-frame (()
+                                   ((nwords :u32const))
+				   ((temp :imm)))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%mmx x8632::stack-temp))
+  ;; Work around Apple bug number 6386516 (open stub may clobber stack)
+  ;; by leaving an extra word of space in the parameter area.
+  (subl (:$l (:apply ash (:apply 1+ nwords) x8632::word-shift))
+	(:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  ;; align stack to 16-byte boundary
+  (andb (:$b -16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (subl (:$b (* 2 x8632::node-size)) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:% x8632::ebp) (:@ 4 (:%l temp))))
+
+(define-x8632-vinsn alloc-variable-c-frame (()
+                                            ((nwords :imm))
+                                            ((temp :imm)))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%mmx x8632::stack-temp))
+  ;; Work around Apple bug number 6386516 (open stub may clobber stack)
+  ;; by leaving an extra word of space in the parameter area.
+  ;; Note that nwords is a fixnum.
+  (leal (:@ 4 (:%l nwords)) (:%l temp))
+  (subl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  ;; align stack to 16-byte boundary
+  (andb (:$b -16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (subl (:$b (* 2 x8632::node-size)) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:% x8632::ebp) (:@ 4 (:%l temp))))
+
+(define-x8632-vinsn set-c-arg (()
+                               ((arg :u32)
+                                (offset :u32const))
+			       ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movl (:%l arg) (:@ (:apply + 8 (:apply ash offset 2)) (:%l temp))))
+
+;;; This is a pretty big crock.
+(define-x8632-vinsn set-c-arg-from-mm0 (()
+					((offset :u32const))
+					((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movq (:%mmx x8632::mm0) (:@ (:apply + 8 (:apply ash offset 2)) (:%l temp))))
+
+(define-x8632-vinsn eep.address (((dest t))
+				 ((src (:lisp (:ne dest )))))
+  :resume
+  (movl (:@ (+ (ash 1 x8632::word-shift) x8632::misc-data-offset) (:%l src))
+        (:%l dest))
+  (cmpl (:$l (:apply target-nil-value)) (:%l dest))
+  (je :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-eep-unresolved (:%l src) (:%l dest))))
+
+(define-x8632-subprim-lea-jmp-vinsn (heap-cons-rest-arg) .SPheap-cons-rest-arg)
+
+(define-x8632-subprim-lea-jmp-vinsn (stack-cons-rest-arg) .SPstack-cons-rest-arg)
+
+(define-x8632-subprim-lea-jmp-vinsn (make-stack-vector)  .SPmkstackv)
+
+(define-x8632-vinsn %current-frame-ptr (((dest :imm))
+					())
+  (movl (:%l x8632::ebp) (:%l dest)))
+
+(define-x8632-vinsn %foreign-stack-pointer (((dest :imm))
+                                            ())
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l dest)))
+
+
+(define-x8632-vinsn  %slot-ref (((dest :lisp))
+				((instance (:lisp (:ne dest)))
+				 (index :lisp)))
+  (movl (:@ x8632::misc-data-offset (:%l instance) (:%l index)) (:%l dest))
+  (cmpl (:$l x8632::slot-unbound-marker) (:%l dest))
+  (je :bad)
+  :resume
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-slot-unbound (:%l dest) (:%l instance) (:%l index))))
+
+
+
+(define-x8632-vinsn symbol-ref (((dest :lisp))
+                                ((src :lisp)
+                                 (cellno :u32const)))
+  (movl (:@ (:apply + (- x8632::node-size x8632::fulltag-misc)
+                    (:apply ash cellno 2))
+              (:%l src)) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-c-bit-fixnum (((dest :lisp))
+                                          ((src :address)
+                                           (offset :s32const))
+                                          ((temp :imm)))
+  ((:pred = 0 (:apply ash offset -5))
+   (btl (:$ub (:apply logand 31 offset))
+        (:@  (:%l src))))
+  ((:not (:pred = 0 (:apply ash offset -5)))
+   (btl (:$ub (:apply logand 31 offset))
+        (:@ (:apply ash (:apply ash offset -5) 2) (:%l src))))
+  (movl (:$l x8632::fixnumone) (:%l temp))
+  (movl (:$l 0) (:%l dest))
+  (cmovbl (:%l temp) (:%l dest)))
+
+(define-x8632-vinsn mem-ref-bit-fixnum (((dest :lisp)
+                                         (src :address))
+                                        ((src :address)
+                                         (offset :lisp))
+                                        ((temp :lisp)))
+  ;; (mark-as-imm temp)
+  (btrl (:$ub (:apply %hard-regspec-value temp))
+	(:@ (:%seg :rcontext) x8632::tcr.node-regs-mask))
+  (movl (:%l offset) (:%l temp))
+  (shrl (:$ub (+ 5 x8632::fixnumshift)) (:%l temp))
+  (leal (:@ (:%l src) (:%l temp) 4) (:%l src))
+  (movl (:%l offset) (:%l temp))
+  (shrl (:$ub x8632::fixnumshift) (:%l temp))
+  (andl (:$l 31) (:%l temp))
+  (btl (:%l temp) (:@ (:%l src)))
+  (movl (:$l x8632::fixnumone) (:%l temp))
+  (leal (:@ (- x8632::fixnumone) (:%l temp)) (:%l dest))
+  (cmovbl (:%l temp) (:%l dest))
+  ;; (mark-as-node temp)
+  (xorl (:%l temp) (:%l temp))
+  (btsl (:$ub (:apply %hard-regspec-value temp))
+	(:@ (:%seg :rcontext) x8632::tcr.node-regs-mask)))
+
+(define-x8632-subprim-call-vinsn (progvsave) .SPprogvsave)
+
+(define-x8632-subprim-jump-vinsn (progvrestore) .SPprogvrestore)
+
+(define-x8632-subprim-lea-jmp-vinsn (simple-keywords) .SPsimple-keywords)
+
+(define-x8632-subprim-lea-jmp-vinsn (keyword-args) .SPkeyword-args)
+
+(define-x8632-subprim-lea-jmp-vinsn (keyword-bind) .SPkeyword-bind)
+
+(define-x8632-vinsn set-high-halfword (()
+				       ((dest :imm)
+					(n :s16const)))
+  (orl (:$l (:apply ash n 16)) (:%l dest)))
+
+(define-x8632-vinsn scale-nargs (()
+				 ((nfixed :s16const)))
+  ((:pred > nfixed 0)
+   ((:pred < nfixed 32)
+    (subl (:$b (:apply ash nfixed x8632::word-shift)) (:%l x8632::nargs)))
+   ((:pred >= nfixed 32)
+    (subl (:$l (:apply ash nfixed x8632::word-shift)) (:%l x8632::nargs)))))
+
+(define-x8632-vinsn opt-supplied-p (()
+                                    ((num-opt :u16const))
+                                    ((nargs (:u32 #.x8632::nargs))
+                                     (imm :imm)))
+  (xorl (:%l imm) (:%l imm))
+  (movl (:$l (:apply target-nil-value)) (:%l x8632::arg_y))
+  :loop
+  (rcmpl (:%l imm) (:%l nargs))
+  (movl (:%l x8632::arg_y) (:%l x8632::arg_z))
+  (cmovll (:@ (+ x8632::t-offset x8632::symbol.vcell) (:%l x8632::arg_y)) (:%l  x8632::arg_z))
+  (addl (:$b x8632::node-size) (:%l imm))
+  (rcmpl (:%l imm) (:$l (:apply ash num-opt x8632::fixnumshift)))
+  (pushl (:%l x8632::arg_z))
+  (jne :loop))
+
+(define-x8632-vinsn one-opt-supplied-p (()
+                                        ()
+					((temp :u32)))
+  (testl (:%l x8632::nargs) (:%l x8632::nargs))
+  (setne (:%b temp))
+  (negb (:%b temp))
+  (andl (:$b x8632::t-offset) (:%l temp))
+  (addl (:$l (:apply target-nil-value)) (:%l temp))
+  (pushl (:%l temp)))
+
+;; needs some love
+(define-x8632-vinsn two-opt-supplied-p (()
+                                        ())
+  (rcmpl (:%l x8632::nargs) (:$b (:apply ash 2 x8632::word-shift)))
+  (jge :two)
+  (rcmpl (:%l x8632::nargs) (:$b (:apply ash 1 x8632::word-shift)))
+  (je :one)
+  ;; none
+  (pushl (:$l (:apply target-nil-value)))
+  (pushl (:$l (:apply target-nil-value)))
+  (jmp :done)
+  :one
+  (pushl (:$l (:apply target-t-value)))
+  (pushl (:$l (:apply target-nil-value)))
+  (jmp :done)
+  :two
+  (pushl (:$l (:apply target-t-value)))
+  (pushl (:$l (:apply target-t-value)))
+  :done)
+
+(define-x8632-vinsn set-c-flag-if-constant-logbitp (()
+                                                    ((bit :u8const)
+                                                     (int :imm)))
+  (btl (:$ub bit) (:%l int)))
+
+(define-x8632-vinsn set-c-flag-if-variable-logbitp (()
+                                                    ((bit :imm)
+                                                     (int :imm))
+						    ((temp :u32)))
+  (movl (:%l bit) (:%l temp))
+  (sarl (:$ub x8632::fixnumshift) (:%l temp))
+  (addl (:$b x8632::fixnumshift) (:%l temp))
+  ;; Would be nice to use a cmov here, but the branch is probably
+  ;; cheaper than trying to scare up an additional unboxed temporary.
+  (cmpb (:$ub 31) (:%b temp))
+  (jbe :test)
+  (movl (:$l 31) (:%l temp))
+  :test
+  (btl (:%l temp) (:%l int)))
+
+(define-x8632-vinsn multiply-immediate (((dest :imm))
+                                        ((src :imm)
+                                         (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (imull (:$b const) (:%l src) (:%l dest)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (imull (:$l const) (:%l src) (:%l dest))))
+
+(define-x8632-vinsn multiply-fixnums (((dest :imm))
+                                      ((x :imm)
+                                       (y :imm))
+                                      ((unboxed :s32)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (movl (:%l y) (:%l unboxed))
+   (sarl (:$ub x8632::fixnumshift) (:%l unboxed))
+   (imull (:%l unboxed) (:%l dest)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value x)
+                      (:apply %hard-regspec-value dest)))
+         (:pred =
+                (:apply %hard-regspec-value y)
+                (:apply %hard-regspec-value dest)))
+   (movl (:%l x) (:%l unboxed))
+   (sarl (:$ub x8632::fixnumshift) (:%l unboxed))
+   (imull (:%l unboxed) (:%l dest)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value x)
+                      (:apply %hard-regspec-value dest)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value y)
+                      (:apply %hard-regspec-value dest))))
+   (movl (:%l y) (:%l dest))
+   (movl (:%l x) (:%l unboxed))
+   (sarl (:$ub x8632::fixnumshift) (:%l unboxed))
+   (imull (:%l unboxed) (:%l dest))))
+
+
+(define-x8632-vinsn mark-as-imm (()
+				 ((reg :imm)))
+  (btrl (:$ub (:apply %hard-regspec-value reg)) (:@ (:%seg :rcontext) x8632::tcr.node-regs-mask)))
+
+(define-x8632-vinsn mark-as-node (()
+				  ((reg :imm)))
+  (xorl (:%l reg) (:%l reg))
+  (btsl (:$ub (:apply %hard-regspec-value reg)) (:@ (:%seg :rcontext) x8632::tcr.node-regs-mask)))
+
+(define-x8632-vinsn mark-temp1-as-node-preserving-flags (()
+                                                        ()
+                                                        ((reg (:u32 #.x8632::temp1))))
+  (movl (:$l 0) (:%l reg))              ;not xorl!
+  (cld))                                ;well, preserving most flags.
+
+  
+
+  
+(define-x8632-vinsn (temp-push-unboxed-word :push :word :csp)
+    (()
+     ((w :u32))
+     ((temp :imm)))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%mmx x8632::stack-temp))
+  (subl (:$b 16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:%l x8632::ebp) (:@ 4 (:%l temp)))
+  (movl (:%l w) (:@ 8 (:%l temp))))
+
+(define-x8632-vinsn (temp-pop-unboxed-word :pop :word :csp)
+    (((w :u32))
+     ())
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l w))
+  (movl (:@ 8 (:%l w)) (:%l w))
+  (addl (:$b 16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp)))
+
+(define-x8632-vinsn (temp-pop-temp1-as-unboxed-word :pop :word :csp)
+    (()
+     ()
+     ((w (:u32 #.x8632::temp1))))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l w))
+  (std)
+  (movl (:@ 8 (:%l w)) (:%l w))
+  (addl (:$b 16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp)))
+
+(define-x8632-vinsn (temp-push-node :push :word :tsp)
+    (()
+     ((w :lisp))
+     ((temp :imm)))
+  (subl (:$b (* 2 x8632::dnode-size)) (:@ (:%seg :rcontext) x8632::tcr.next-tsp))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.save-tsp) (:%mmx x8632::stack-temp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.next-tsp) (:%l temp))
+  (movsd (:%xmm x8632::fpzero) (:@ (:%l temp)))
+  (movsd (:%xmm x8632::fpzero) (:@ x8632::dnode-size (:%l temp)))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.save-tsp))
+  (movl (:%l w) (:@ x8632::dnode-size (:%l temp))))
+
+(define-x8632-vinsn (temp-pop-node :pop :word :tsp)
+    (((w :lisp))
+     ()
+     ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.save-tsp) (:%l temp))
+  (movl (:@ x8632::dnode-size (:%l temp)) (:%l w))
+  (movl (:@ (:%l temp)) (:%l temp))
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.save-tsp))  
+  (movl (:%l temp) (:@ (:%seg :rcontext) x8632::tcr.next-tsp)))
+
+(define-x8632-vinsn (temp-push-single-float :push :word :csp)
+    (()
+     ((f :single-float))
+     ((temp :imm)))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%mmx x8632::stack-temp))
+  (subl (:$b 16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:%l x8632::ebp) (:@ 4 (:%l temp)))
+  (movss (:%xmm f) (:@ 8 (:%l temp))))
+
+(define-x8632-vinsn (temp-pop-single-float :pop :word :csp)
+    (((f :single-float))
+     ()
+     ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movss (:@ 8 (:%l temp)) (:%xmm f))
+  (addl (:$b 16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp)))
+
+(define-x8632-vinsn (temp-push-double-float :push :word :csp)
+    (()
+     ((f :double-float))
+     ((temp :imm)))
+  (movd (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%mmx x8632::stack-temp))
+  (subl (:$b 16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movd (:%mmx x8632::stack-temp) (:@ (:%l temp)))
+  (movl (:%l x8632::ebp) (:@ 4 (:%l temp)))
+  (movsd (:%xmm f) (:@ 8 (:%l temp))))
+
+(define-x8632-vinsn (temp-pop-double-float :pop :word :csp)
+    (((f :double-float))
+     ()
+     ((temp :imm)))
+  (movl (:@ (:%seg :rcontext) x8632::tcr.foreign-sp) (:%l temp))
+  (movsd (:@ 8 (:%l temp)) (:%xmm f))
+  (addl (:$b 16) (:@ (:%seg :rcontext) x8632::tcr.foreign-sp)))
+
+(define-x8632-vinsn load-next-method-context (((dest :lisp))
+					      ())
+  (movl (:@ (:%seg :rcontext) x8632::tcr.next-method-context) (:%l dest))
+  (movl (:$l 0) (:@ (:%seg :rcontext) x8632::tcr.next-method-context)))
+
+(define-x8632-vinsn save-node-register-to-spill-area (()
+					 ((src :lisp)))
+  ;; maybe add constant to index slot 0--3
+  (movl (:%l src) (:@ (:%seg :rcontext) x8632::tcr.save3)))
+
+(define-x8632-vinsn load-node-register-from-spill-area (((dest :lisp))
+							())
+  (movl (:@ (:%seg :rcontext) x8632::tcr.save3) (:%l dest))
+  (movss (:%xmm x8632::fpzero) (:@ (:%seg :rcontext) x8632::tcr.save3)))
+
+(define-x8632-vinsn align-loop-head (()
+				     ())
+)
+
+(queue-fixup
+ (fixup-x86-vinsn-templates
+  *x8632-vinsn-templates*
+  x86::*x86-opcode-template-lists* *x8632-backend*))
+
+(provide "X8632-VINSNS")
Index: /branches/new-random/compiler/X86/X8664/x8664-arch.lisp
===================================================================
--- /branches/new-random/compiler/X86/X8664/x8664-arch.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/X8664/x8664-arch.lisp	(revision 13309)
@@ -0,0 +1,1348 @@
+;;;-*- Mode: Lisp; Package: (X8664 :use CL) -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(defpackage "X8664"
+  (:use "CL")
+  #+x8664-target
+  (:nicknames "TARGET"))
+
+(in-package "X8664")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "X86-ARCH")
+  (require "X86-LAP")
+  
+(defparameter *x8664-symbolic-register-names*
+  (make-hash-table :test #'equal)
+  "For the disassembler, mostly")
+
+;;; define integer constants which map to
+;;; indices in the X86::*X8664-REGISTER-ENTRIES* array.
+(ccl::defenum ()
+  rax
+  rcx
+  rdx
+  rbx
+  rsp
+  rbp
+  rsi
+  rdi
+  r8
+  r9
+  r10
+  r11
+  r12
+  r13
+  r14
+  r15
+  ;; 32-bit registers
+  eax
+  ecx
+  edx
+  ebx
+  esp
+  ebp
+  esi
+  edi
+  r8d
+  r9d
+  r10d
+  r11d
+  r12d
+  r13d
+  r14d
+  r15d
+  ;; 16-bit-registers
+  ax
+  cx
+  dx
+  bx
+  sp
+  bp
+  si
+  di
+  r8w
+  r9w
+  r10w
+  r11w
+  r12w
+  r13w
+  r14w
+  r15w
+  ;; 8-bit registers
+  al
+  cl
+  dl
+  bl
+  spl
+  bpl
+  sil
+  dil
+  r8b
+  r9b
+  r10b
+  r11b
+  r12b
+  r13b
+  r14b
+  r15b
+       ;;; xmm registers
+  xmm0
+  xmm1
+  xmm2
+  xmm3
+  xmm4
+  xmm5
+  xmm6
+  xmm7
+  xmm8
+  xmm9
+  xmm10
+  xmm11
+  xmm12
+  xmm13
+  xmm14
+  xmm15
+  ;; MMX registers
+  mm0
+  mm1
+  mm2
+  mm3
+  mm4
+  mm5
+  mm6
+  mm7
+  ;; x87 FP regs.  May or may not be useful.
+  st[0]
+  st[1]
+  st[2]
+  st[3]
+  st[4]
+  st[5]
+  st[6]
+  st[7]
+  ;; Segment registers
+  cs
+  ds
+  ss
+  es
+  fs
+  gs
+  rip
+  )
+
+(defmacro defx86reg (alias known)
+  (let* ((known-entry (gensym)))
+    `(let* ((,known-entry (gethash ,(string known) x86::*x8664-registers*)))
+      (unless ,known-entry
+        (error "register ~a not defined" ',known))
+      (setf (gethash ,(string alias) x86::*x8664-registers*) ,known-entry)
+      (unless (gethash ,(string-downcase (string known)) *x8664-symbolic-register-names*)
+        (setf (gethash ,(string-downcase (string known)) *x8664-symbolic-register-names*)
+              (string-downcase ,(string alias))))
+      (defconstant ,alias ,known))))
+
+(defx86reg imm0 rax)
+(defx86reg imm0.l eax)
+(defx86reg imm0.w ax)
+(defx86reg imm0.b al)
+
+(defx86reg temp0 rbx)
+(defx86reg temp0.l ebx)
+(defx86reg temp0.w bx)
+(defx86reg temp0.b bl)
+
+(defx86reg imm2 rcx)
+(defx86reg nargs ecx)
+(defx86reg imm2.l ecx)
+(defx86reg nargs.w cx)
+(defx86reg nargs.q rcx)
+(defx86reg imm2.w cx)
+(defx86reg imm2.b cl)
+(defx86reg shift cl)
+
+(defx86reg imm1 rdx)
+(defx86reg imm1.l edx)
+(defx86reg imm1.w dx)
+(defx86reg imm1.b dl)
+
+(defx86reg arg_z rsi)
+(defx86reg arg_z.l esi)
+(defx86reg arg_z.w si)
+(defx86reg arg_z.b sil)
+
+(defx86reg arg_y rdi)
+(defx86reg arg_y.l edi)
+(defx86reg arg_y.w di)
+(defx86reg arg_y.b dil)
+
+(defx86reg arg_x r8)
+(defx86reg arg_x.l r8d)
+(defx86reg arg_x.w r8w)
+(defx86reg arg_x.b r8b)
+
+(defx86reg temp1 r9)
+(defx86reg temp1.l r9d)
+(defx86reg temp1.w r9w)
+(defx86reg temp1.b r9b)
+
+(defx86reg ra0 r10)
+(defx86reg ra0.l r10d)
+(defx86reg ra0.w r10w)
+(defx86reg ra0.b r10b)
+
+(defx86reg temp2 r10)
+(defx86reg temp2.l r10d)
+(defx86reg temp2.w r10w)
+(defx86reg temp2.b r10b)
+
+
+(defx86reg save3 r11)
+(defx86reg save3.l r11d)
+(defx86reg save3.w r11w)
+(defx86reg save3.b r11b)
+
+(defx86reg save2 r12)
+(defx86reg save2.l r12d)
+(defx86reg save2.w r12w)
+(defx86reg save2.b r12b)
+
+(defx86reg fn r13)
+(defx86reg fn.l r13d)
+(defx86reg fn.w r13w)
+(defx86reg fn.b r13b)
+
+(defx86reg save1 r14)
+(defx86reg save1.l r14d)
+(defx86reg save1.w r14w)
+(defx86reg save1.b r14b)
+
+(defx86reg save0 r15)
+(defx86reg save0.l r15d)
+(defx86reg save0.w r15w)
+(defx86reg save0.b r15b)
+
+;;; Use xmm regs for floating-point.  (They can also hold integer values.)
+(defx86reg fp0 xmm0)
+(defx86reg fp1 xmm1)
+(defx86reg fp2 xmm2)
+(defx86reg fp3 xmm3)
+(defx86reg fp4 xmm4)
+(defx86reg fp5 xmm5)
+(defx86reg fp6 xmm6)
+(defx86reg fp7 xmm7)
+(defx86reg fp8 xmm8)
+(defx86reg fp9 xmm9)
+(defx86reg fp10 xmm10)
+(defx86reg fp11 xmm11)
+(defx86reg fp12 xmm12)
+(defx86reg fp13 xmm13)
+(defx86reg fp14 xmm14)
+(defx86reg fpzero xmm15)
+(defx86reg fp15 xmm15)
+
+;;; There are only 8 mmx registers, and they overlap the x87 FPU.
+(defx86reg stack-temp mm7)
+
+
+;;; NEXT-METHOD-CONTEXT is passed from gf-dispatch code to the method
+;;; functions that it funcalls.  FNAME is only meaningful when calling
+;;; globally named functions through the function cell of a symbol.
+;;; It appears that they're never live at the same time.
+;;; (We can also consider passing next-method context on the stack.)
+
+(defx86reg fname temp0)
+(defx86reg next-method-context temp0)
+;;; We rely one at least one of %ra0/%fn pointing to the current function
+;;; (or to a TRA that references the function) at all times.  When we
+;;; tail call something, we want %RA0 to point to our caller's TRA and
+;;; %FN to point to the new function.  Unless we go out of line to
+;;; do tail calls, we need some register not involved in the calling
+;;; sequence to hold the current function, since it might get GCed otherwise.
+;;; (The odds of this happening are low, but non-zero.)
+(defx86reg xfn temp1)
+
+(defx86reg ra1 fn)
+
+(defx86reg allocptr temp0)
+
+    
+(defconstant nbits-in-word 64)
+(defconstant nbits-in-byte 8)
+(defconstant ntagbits 4)
+(defconstant nlisptagbits 3)
+(defconstant nfixnumtagbits 3)
+(defconstant num-subtag-bits 8)
+(defconstant fixnumshift 3)
+(defconstant fixnum-shift 3)
+(defconstant fulltagmask 15)
+(defconstant tagmask 7)
+(defconstant fixnummask 7)
+(defconstant ncharcodebits 8)
+(defconstant charcode-shift 8)
+(defconstant word-shift 3)
+(defconstant word-size-in-bytes 8)
+(defconstant node-size word-size-in-bytes)
+(defconstant dnode-size 16)
+(defconstant dnode-align-bits 4)
+(defconstant dnode-shift dnode-align-bits)
+(defconstant bitmap-shift 6)
+
+(defconstant fixnumone (ash 1 fixnumshift))
+(defconstant fixnum-one fixnumone)
+(defconstant fixnum1 fixnumone)
+
+(defconstant target-most-negative-fixnum (ash -1 (1- (- nbits-in-word nfixnumtagbits))))
+(defconstant target-most-positive-fixnum (1- (ash 1 (1- (- nbits-in-word nfixnumtagbits)))))
+
+;;; 3-bit "lisptag" values
+
+(defconstant tag-fixnum 0)
+(defconstant tag-imm-0 1)               ;subtag-single-float ONLY
+(defconstant tag-imm-1 2)               ;subtag-character, internal markers
+(defconstant tag-list 3)                ;fulltag-cons or NIL
+(defconstant tag-tra 4)                 ;tagged return-address
+(defconstant tag-misc 5)                ;random uvector
+(defconstant tag-symbol 6)              ;non-null symbol
+(defconstant tag-function 7)            ;function entry point
+
+(defconstant tag-single-float tag-imm-0)
+
+;;; 4-bit "fulltag" values
+(defconstant fulltag-even-fixnum 0)
+(defconstant fulltag-imm-0 1)           ;subtag-single-float ONLY
+(defconstant fulltag-imm-1 2)           ;characters, markers
+(defconstant fulltag-cons 3)
+(defconstant fulltag-tra-0 4)           ;tagged return address
+(defconstant fulltag-nodeheader-0 5)
+(defconstant fulltag-nodeheader-1 6)
+(defconstant fulltag-immheader-0 7)
+(defconstant fulltag-odd-fixnum 8)
+(defconstant fulltag-immheader-1 9)
+(defconstant fulltag-immheader-2 10)
+(defconstant fulltag-nil 11)
+(defconstant fulltag-tra-1 12)
+(defconstant fulltag-misc 13)
+(defconstant fulltag-symbol 14)
+(defconstant fulltag-function 15)
+
+(defconstant fulltag-single-float fulltag-imm-0)
+
+(defmacro define-subtag (name tag value)
+  `(defconstant ,(ccl::form-symbol "SUBTAG-" name) (logior ,tag (ash ,value ntagbits))))
+
+
+(define-subtag arrayH fulltag-nodeheader-0 10)
+(define-subtag vectorH fulltag-nodeheader-1 10)
+(define-subtag simple-vector fulltag-nodeheader-1 11)
+(defconstant min-vector-subtag  subtag-vectorH)
+(defconstant min-array-subtag  subtag-arrayH)
+
+(defconstant ivector-class-64-bit  fulltag-immheader-2)
+(defconstant ivector-class-32-bit  fulltag-immheader-1)
+(defconstant ivector-class-other-bit  fulltag-immheader-0)
+
+(define-subtag fixnum-vector ivector-class-64-bit 12)
+(define-subtag s64-vector ivector-class-64-bit 13)
+(define-subtag u64-vector ivector-class-64-bit 14)
+(define-subtag double-float-vector ivector-class-64-bit 15)
+
+(define-subtag simple-base-string ivector-class-32-bit 12)
+(define-subtag s32-vector ivector-class-32-bit 13)
+(define-subtag u32-vector ivector-class-32-bit 14)
+(define-subtag single-float-vector ivector-class-32-bit 15)
+	
+(define-subtag s16-vector ivector-class-other-bit 10)
+(define-subtag u16-vector ivector-class-other-bit 11)
+
+(define-subtag s8-vector ivector-class-other-bit 13)
+(define-subtag u8-vector ivector-class-other-bit 14)
+(defconstant min-8-bit-ivector-subtag subtag-s8-vector)
+(defconstant max-8-bit-ivector-subtag subtag-u8-vector)
+(define-subtag bit-vector ivector-class-other-bit 15)
+
+
+;;; There's some room for expansion in non-array ivector space.
+(define-subtag macptr ivector-class-64-bit 1)
+(define-subtag dead-macptr ivector-class-64-bit 2)
+(define-subtag bignum ivector-class-32-bit 1)
+(define-subtag double-float ivector-class-32-bit 2)
+(define-subtag xcode-vector ivector-class-32-bit 3)
+
+
+        
+;;; Note the difference between (e.g) fulltag-function - which
+;;; defines what the low 4 bytes of a function pointer look like -
+;;; and subtag-function - which describes what the subtag byte
+;;; in a function header looks like.  (Likewise for fulltag-symbol
+;;; and subtag-symbol)
+
+;;; don't use nodheader/0, since that would conflict with tag-misc
+(define-subtag symbol fulltag-nodeheader-0 1)
+(define-subtag catch-frame fulltag-nodeheader-0 2)
+(define-subtag hash-vector fulltag-nodeheader-0 3)
+(define-subtag pool fulltag-nodeheader-0 4)
+(define-subtag weak fulltag-nodeheader-0 5)
+(define-subtag package fulltag-nodeheader-0 6)
+(define-subtag slot-vector fulltag-nodeheader-0 7)
+(define-subtag basic-stream fulltag-nodeheader-0 8)
+(define-subtag function fulltag-nodeheader-0 9)
+
+(define-subtag ratio fulltag-nodeheader-1 1)
+(define-subtag complex fulltag-nodeheader-1 2)
+(define-subtag struct fulltag-nodeheader-1 3)
+(define-subtag istruct fulltag-nodeheader-1 4)
+(define-subtag value-cell fulltag-nodeheader-1 5)
+(define-subtag xfunction fulltag-nodeheader-1 6)
+(define-subtag lock fulltag-nodeheader-1 7)
+(define-subtag instance fulltag-nodeheader-1 8)
+
+	
+(defconstant canonical-nil-value (+ #x13000 fulltag-nil))
+(defconstant canonical-t-value (+ #x13020 fulltag-symbol))
+(defconstant misc-bias fulltag-misc)
+(defconstant cons-bias fulltag-cons)
+(defconstant t-offset (- canonical-t-value canonical-nil-value))
+
+
+(defconstant misc-header-offset (- fulltag-misc))
+(defconstant misc-data-offset (+ misc-header-offset node-size))
+(defconstant misc-subtag-offset misc-header-offset)
+(defconstant misc-dfloat-offset misc-data-offset)
+(defconstant misc-symbol-offset (- node-size fulltag-symbol))
+(defconstant misc-function-offset (- node-size fulltag-function))
+  
+(define-subtag single-float fulltag-imm-0 0)
+
+(define-subtag character fulltag-imm-1 0)
+
+(define-subtag unbound fulltag-imm-1 1)
+(defconstant unbound-marker subtag-unbound)
+(defconstant undefined unbound-marker)
+(define-subtag slot-unbound fulltag-imm-1 2)
+(defconstant slot-unbound-marker subtag-slot-unbound)
+(define-subtag illegal fulltag-imm-1 3)
+(defconstant illegal-marker subtag-illegal)
+(define-subtag no-thread-local-binding fulltag-imm-1 4)
+(defconstant no-thread-local-binding-marker subtag-no-thread-local-binding)
+(define-subtag reserved-frame fulltag-imm-1 5)
+(defconstant reserved-frame-marker subtag-reserved-frame)
+
+;;; This has two functions: it tells the link-inverting marker where the
+;;; code ends and the constants start, and it ensures that the 0th constant
+;;; will never be in the same memozized dnode as some (unboxed) word of
+;;; machine code.  I'm not sure if there's a better way to do either of those
+;;; things.
+;;; Depending on how you look at it, we either lose 8 bytes per function, or gain
+;;; 7 bytes of otherwise unused space for debugging info.
+(define-subtag function-boundary-marker fulltag-imm-1 15)
+(defconstant function-boundary-marker subtag-function-boundary-marker)
+
+(defconstant max-64-bit-constant-index (ash (+ #x7fffffff x8664::misc-dfloat-offset) -3))
+(defconstant max-32-bit-constant-index (ash (+ #x7fffffff x8664::misc-data-offset) -2))
+(defconstant max-16-bit-constant-index (ash (+ #x7fffffff x8664::misc-data-offset) -1))
+(defconstant max-8-bit-constant-index (+ #x7fffffff x8664::misc-data-offset))
+(defconstant max-1-bit-constant-index (ash (+ #x7fffffff x8664::misc-data-offset) 5))
+
+)
+(defmacro define-storage-layout (name origin &rest cells)
+  `(progn
+    (ccl::defenum (:start ,origin :step 8)
+        ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell)) cells))
+    (defconstant ,(ccl::form-symbol name ".SIZE") ,(* (length cells)
+                                                      8))))
+
+(defmacro define-lisp-object (name tagname &rest cells)
+  `(define-storage-layout ,name ,(- (symbol-value tagname)) ,@cells))
+
+(defmacro define-fixedsized-object (name (&optional (fulltag 'fulltag-misc))
+                                         &rest non-header-cells)
+  `(progn
+     (define-lisp-object ,name ,fulltag header ,@non-header-cells)
+     (ccl::defenum ()
+       ,@(mapcar #'(lambda (cell) (ccl::form-symbol name "." cell "-CELL")) non-header-cells))
+     (defconstant ,(ccl::form-symbol name ".ELEMENT-COUNT") ,(length non-header-cells))))
+
+;;; Order of CAR and CDR doesn't seem to matter much - there aren't
+;;; too many tricks to be played with predecrement/preincrement addressing.
+;;; Keep them in the confusing MCL 3.0 order, to avoid confusion.
+(define-lisp-object cons fulltag-cons 
+  cdr 
+  car)
+
+(define-fixedsized-object ratio ()
+  numer
+  denom)
+
+;;; It's slightly easier (for bootstrapping reasons)
+;;; to view a DOUBLE-FLOAT as being UVECTOR with 2 32-bit elements
+;;; (rather than 1 64-bit element).
+
+(defconstant double-float.value misc-data-offset)
+(defconstant double-float.value-cell 0)
+(defconstant double-float.val-low double-float.value)
+(defconstant double-float.val-low-cell 0)
+(defconstant double-float.val-high (+ double-float.value 4))
+(defconstant double-float.val-high-cell 1)
+(defconstant double-float.element-count 2)
+(defconstant double-float.size 16)
+
+(define-fixedsized-object complex ()
+  realpart
+  imagpart
+)
+
+;;; There are two kinds of macptr; use the length field of the header if you
+;;; need to distinguish between them
+(define-fixedsized-object macptr ()
+  address
+  domain
+  type
+)
+
+(define-fixedsized-object xmacptr ()
+  address
+  domain
+  type
+  flags
+  link
+)
+
+
+;;; Need to think about catch frames on x8664.
+(define-fixedsized-object catch-frame ()
+  catch-tag                             ; #<unbound> -> unwind-protect, else catch
+  link                                  ; tagged pointer to next older catch frame
+  mvflag                                ; 0 if single-value, 1 if uwp or multiple-value
+  rsp                                   ;
+  rbp
+  foreign-sp
+  db-link                               ; value of dynamic-binding link on thread entry.
+  save-save3                            ; saved nvrs
+  save-save2
+  save-save1
+  save-save0
+  xframe                                ; exception-frame link
+  pc                                    ; tra of catch exit/unwind cleanup
+)
+
+(define-fixedsized-object lock ()
+  _value                                ;finalizable pointer to kernel object
+  kind                                  ; '0 = recursive-lock, '1 = rwlock
+  writer				;tcr of owning thread or 0
+  name
+  whostate
+  whostate-2
+  )
+
+
+
+;;; If we're pointing at the "symbol-vector", we can use these
+(define-fixedsized-object symptr ()
+  pname
+  vcell
+  fcell
+  package-predicate
+  flags
+  plist
+  binding-index
+)
+
+(define-fixedsized-object symbol (fulltag-symbol)
+  pname
+  vcell
+  fcell
+  package-predicate
+  flags
+  plist
+  binding-index
+)
+
+(defconstant nilsym-offset (+ t-offset symbol.size))
+
+
+(define-fixedsized-object vectorH ()
+  logsize                               ; fillpointer if it has one, physsize otherwise
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+)
+
+(define-lisp-object arrayH fulltag-misc
+  header                                ; subtag = subtag-arrayH
+  rank                                  ; NEVER 1
+  physsize                              ; total size of (possibly displaced) data vector
+  data-vector                           ; object this header describes
+  displacement                          ; true displacement or 0  
+  flags                                 ; has-fill-pointer,displaced-to,adjustable bits; subtype of underlying simple vector.
+ ;; Dimensions follow
+)
+
+(defconstant arrayH.rank-cell 0)
+(defconstant arrayH.physsize-cell 1)
+(defconstant arrayH.data-vector-cell 2)
+(defconstant arrayH.displacement-cell 3)
+(defconstant arrayH.flags-cell 4)
+(defconstant arrayH.dim0-cell 5)
+
+(defconstant arrayH.flags-cell-bits-byte (byte 8 0))
+(defconstant arrayH.flags-cell-subtag-byte (byte 8 8))
+
+(define-fixedsized-object value-cell ()
+  value)
+
+
+(define-storage-layout lisp-frame 0
+  backptr
+  return-address
+  xtra)
+
+(define-storage-layout tsp-frame 0
+  backptr
+  rbp)
+
+(define-storage-layout csp-frame 0
+  backptr
+  rbp)
+
+
+(define-storage-layout xcf 0            ;"exception callback frame"
+  backptr
+  return-address                        ; always 0
+  nominal-function
+  relative-pc
+  containing-object
+  xp
+  ra0
+  foreign-sp                            ; value of tcr.foreign_sp
+  prev-xframe                           ; tcr.xframe before exception
+                                        ; (last 2 needed by apply-in-frame)
+  )
+
+;;; The kernel uses these (rather generically named) structures
+;;; to keep track of various memory regions it (or the lisp) is
+;;; interested in.
+
+
+(define-storage-layout area 0
+  pred                                  ; pointer to preceding area in DLL
+  succ                                  ; pointer to next area in DLL
+  low                                   ; low bound on area addresses
+  high                                  ; high bound on area addresses.
+  active                                ; low limit on stacks, high limit on heaps
+  softlimit                             ; overflow bound
+  hardlimit                             ; another one
+  code                                  ; an area-code; see below
+  markbits                              ; bit vector for GC
+  ndnodes                               ; "active" size of dynamic area or stack
+  older                                 ; in EGC sense
+  younger                               ; also for EGC
+  h                                     ; Handle or null pointer
+  softprot                              ; protected_area structure pointer
+  hardprot                              ; another one.
+  owner                                 ; fragment (library) which "owns" the area
+  refbits                               ; bitvector for intergenerational refernces
+  threshold                             ; for egc
+  gc-count                              ; generational gc count.
+  static-dnodes                         ; for honsing. etc
+  static-used                           ; bitvector
+)
+
+
+(define-storage-layout protected-area 0
+  next
+  start                                 ; first byte (page-aligned) that might be protected
+  end                                   ; last byte (page-aligned) that could be protected
+  nprot                                 ; Might be 0
+  protsize                              ; number of bytes to protect
+  why)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defconstant tcr-bias 0)
+)
+
+(define-storage-layout tcr (- tcr-bias)
+  prev					; in doubly-linked list 
+  next					; in doubly-linked list
+  single-float-convert                  ; faster to box/unbox through memory
+  linear
+  save-rbp                              ; lisp frame ptr for foreign code
+  lisp-fpscr-high
+  db-link				; special binding chain head 
+  catch-top				; top catch frame 
+  save-vsp				; SP when in foreign code 
+  save-tsp				; TSP, at all times
+  foreign-sp                            ; SP when in lisp code
+  cs-area				; cstack area pointer 
+  vs-area				; vstack area pointer 
+  ts-area				; tstack area pointer 
+  cs-limit				; cstack overflow limit
+  total-bytes-allocated
+  log2-allocation-quantum		; unboxed
+  interrupt-pending			; fixnum
+  xframe				; exception frame linked list
+  errno-loc				; thread-private, maybe
+  ffi-exception				; fpscr bits from ff-call.
+  osid					; OS thread id 
+  valence				; odd when in foreign code 
+  foreign-exception-status
+  native-thread-info
+  native-thread-id
+  last-allocptr
+  save-allocptr
+  save-allocbase
+  reset-completion
+  activate
+  suspend-count
+  suspend-context
+  pending-exception-context
+  suspend				; semaphore for suspension notify 
+  resume				; sempahore for resumption notify
+  flags					; foreign, being reset, ...
+  gc-context
+  termination-semaphore
+  unwinding
+  tlb-limit
+  tlb-pointer
+  shutdown-count
+  next-tsp
+  safe-ref-address
+  pending-io-info
+  io-datum
+)
+
+(defconstant tcr.single-float-convert.value (+ 4 tcr.single-float-convert))
+
+
+(defconstant interrupt-level-binding-index (ash 1 fixnumshift))
+
+(define-storage-layout lockptr 0
+  avail
+  owner
+  count
+  signal
+  waiting
+  malloced-ptr
+  spinlock)
+
+(define-storage-layout rwlock 0
+  spin
+  state
+  blocked-writers
+  blocked-readers
+  writer
+  reader-signal
+  writer-signal
+  malloced-ptr
+  )
+
+(defmacro define-header (name element-count subtag)
+  `(defconstant ,name (logior (ash ,element-count num-subtag-bits) ,subtag)))
+
+(define-header double-float-header double-float.element-count subtag-double-float)
+
+;;; We could possibly have a one-digit bignum header when dealing
+;;; with "small bignums" in some bignum code.  Like other cases of
+;;; non-normalized bignums, they should never escape from the lab.
+(define-header one-digit-bignum-header 1 subtag-bignum)
+(define-header two-digit-bignum-header 2 subtag-bignum)
+(define-header three-digit-bignum-header 3 subtag-bignum)
+(define-header four-digit-bignum-header 4 subtag-bignum)
+(define-header five-digit-bignum-header 5 subtag-bignum)
+(define-header symbol-header symbol.element-count subtag-symbol)
+(define-header value-cell-header value-cell.element-count subtag-value-cell)
+(define-header macptr-header macptr.element-count subtag-macptr)
+
+
+(defconstant gf-code-size 18)
+
+(defun %kernel-global (sym)
+  (let* ((pos (position sym x86::*x86-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ fulltag-nil (* (1+ pos) node-size)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+(defmacro kernel-global (sym)
+  (let* ((pos (position sym x86::*x86-kernel-globals* :test #'string=)))
+    (if pos
+      (- (+ fulltag-nil (* (1+ pos) node-size)))
+      (error "Unknown kernel global : ~s ." sym))))
+
+(ccl::defenum (:prefix "KERNEL-IMPORT-" :start 0 :step node-size)
+  fd-setsize-bytes
+  do-fd-set
+  do-fd-clr
+  do-fd-is-set
+  do-fd-zero
+  MakeDataExecutable
+  GetSharedLibrary
+  FindSymbol
+  malloc
+  free
+  jvm-init
+  tcr-frame-ptr
+  register-xmacptr-dispose-function
+  open-debug-output
+  get-r-debug
+  restore-soft-stack-limit
+  egc-control
+  lisp-bug
+  NewThread
+  YieldToThread
+  DisposeThread
+  ThreadCurrentStackSpace
+  usage-exit
+  save-fp-context
+  restore-fp-context
+  put-altivec-registers
+  get-altivec-registers
+  new-semaphore
+  wait-on-semaphore
+  signal-semaphore
+  destroy-semaphore
+  new-recursive-lock
+  lock-recursive-lock
+  unlock-recursive-lock
+  destroy-recursive-lock
+  suspend-other-threads
+  resume-other-threads
+  suspend-tcr
+  resume-tcr
+  rwlock-new
+  rwlock-destroy
+  rwlock-rlock
+  rwlock-wlock
+  rwlock-unlock
+  recursive-lock-trylock
+  foreign-name-and-offset
+  lisp-read
+  lisp-write
+  lisp-open
+  lisp-fchmod
+  lisp-lseek
+  lisp-close
+  lisp-ftruncate
+  lisp-stat
+  lisp-fstat
+  lisp-futex
+  lisp-opendir
+  lisp-readdir
+  lisp-closedir
+  lisp-pipe
+  lisp-gettimeofday
+  lisp-sigexit
+)
+
+(defmacro nrs-offset (name)
+  (let* ((pos (position name x86::*x86-nilreg-relative-symbols* :test #'eq)))
+    (if pos (* (1- pos) symbol.size))))
+
+(defparameter *x8664-target-uvector-subtags*
+  `((:bignum . ,subtag-bignum)
+    (:ratio . ,subtag-ratio)
+    (:single-float . ,subtag-single-float)
+    (:double-float . ,subtag-double-float)
+    (:complex . ,subtag-complex  )
+    (:symbol . ,subtag-symbol)
+    (:function . ,subtag-function )
+    (:xcode-vector . ,subtag-xcode-vector)
+    (:macptr . ,subtag-macptr )
+    (:catch-frame . ,subtag-catch-frame)
+    (:struct . ,subtag-struct )    
+    (:istruct . ,subtag-istruct )
+    (:pool . ,subtag-pool )
+    (:population . ,subtag-weak )
+    (:hash-vector . ,subtag-hash-vector )
+    (:package . ,subtag-package )
+    (:value-cell . ,subtag-value-cell)
+    (:instance . ,subtag-instance )
+    (:lock . ,subtag-lock )
+    (:basic-stream . ,subtag-basic-stream)
+    (:slot-vector . ,subtag-slot-vector)
+    (:simple-string . ,subtag-simple-base-string )
+    (:bit-vector . ,subtag-bit-vector )
+    (:signed-8-bit-vector . ,subtag-s8-vector )
+    (:unsigned-8-bit-vector . ,subtag-u8-vector )
+    (:signed-16-bit-vector . ,subtag-s16-vector )
+    (:unsigned-16-bit-vector . ,subtag-u16-vector )
+    (:signed-32-bit-vector . ,subtag-s32-vector )
+    (:unsigned-32-bit-vector . ,subtag-u32-vector )
+    (:signed-64-bit-vector . ,subtag-s64-vector)
+    (:fixnum-vector . ,subtag-fixnum-vector)
+    (:unsigned-64-bit-vector . ,subtag-u64-vector)    
+    (:single-float-vector . ,subtag-single-float-vector)
+    (:double-float-vector . ,subtag-double-float-vector )
+    (:simple-vector . ,subtag-simple-vector )
+    (:vector-header . ,subtag-vectorH)
+    (:array-header . ,subtag-arrayH)))
+
+;;; This should return NIL unless it's sure of how the indicated
+;;; type would be represented (in particular, it should return
+;;; NIL if the element type is unknown or unspecified at compile-time.
+(defun x8664-array-type-name-from-ctype (ctype)
+  (when (typep ctype 'ccl::array-ctype)
+    (let* ((element-type (ccl::array-ctype-element-type ctype)))
+      (typecase element-type
+        (ccl::class-ctype
+         (let* ((class (ccl::class-ctype-class element-type)))
+           (if (or (eq class ccl::*character-class*)
+                   (eq class ccl::*base-char-class*)
+                   (eq class ccl::*standard-char-class*))
+             :simple-string
+             :simple-vector)))
+        (ccl::numeric-ctype
+         (if (eq (ccl::numeric-ctype-complexp element-type) :complex)
+           :simple-vector
+           (case (ccl::numeric-ctype-class element-type)
+             (integer
+              (let* ((low (ccl::numeric-ctype-low element-type))
+                     (high (ccl::numeric-ctype-high element-type)))
+                (cond ((or (null low) (null high))
+                       :simple-vector)
+                      ((and (>= low 0) (<= high 1))
+                       :bit-vector)
+                      ((and (>= low 0) (<= high 255))
+                       :unsigned-8-bit-vector)
+                      ((and (>= low 0) (<= high 65535))
+                       :unsigned-16-bit-vector)
+                      ((and (>= low 0) (<= high #xffffffff))
+                       :unsigned-32-bit-vector)
+                      ((and (>= low 0) (<= high #xffffffffffffffff))
+                       :unsigned-64-bit-vector)
+                      ((and (>= low -128) (<= high 127))
+                       :signed-8-bit-vector)
+                      ((and (>= low -32768) (<= high 32767))
+                       :signed-16-bit-vector)
+                      ((and (>= low (ash -1 31)) (<= high (1- (ash 1 31))))
+                       :signed-32-bit-vector)
+                      ((and (>= low target-most-negative-fixnum)
+                            (<= high target-most-positive-fixnum))
+                       :fixnum-vector)
+                      ((and (>= low (ash -1 63)) (<= high (1- (ash 1 63))))
+                       :signed-64-bit-vector)
+                      (t :simple-vector))))
+             (float
+              (case (ccl::numeric-ctype-format element-type)
+                ((double-float long-float) :double-float-vector)
+                ((single-float short-float) :single-float-vector)
+                (t :simple-vector)))
+             (t :simple-vector))))
+        (ccl::unknown-ctype)
+        (ccl::named-ctype
+         (if (eq element-type ccl::*universal-type*)
+           :simple-vector))
+        (t)))))
+
+(defun x8664-misc-byte-count (subtag element-count)
+  (declare (fixnum subtag))
+  (if (logbitp (logand subtag fulltagmask)
+               (logior (ash 1 fulltag-nodeheader-0)
+                       (ash 1 fulltag-nodeheader-1)))
+    (ash element-count 3)
+    (case (logand subtag fulltagmask)
+      (#.ivector-class-64-bit (ash element-count 3))
+      (#.ivector-class-32-bit (ash element-count 2))
+      (t
+       (if (= subtag subtag-bit-vector)
+         (ash (+ 7 element-count) -3)
+         (if (>= subtag min-8-bit-ivector-subtag)
+           element-count
+           (ash element-count 1)))))))
+
+(defparameter *x8664-subprims-shift* 3)
+(defconstant x8664-subprims-base #x15000)
+
+
+(declaim (special *x8664-subprims*))
+
+;;; For now, nothing's nailed down and we don't say anything about
+;;; registers clobbered.
+(let* ((origin x8664-subprims-base)
+       (step (ash 1 *x8664-subprims-shift*)))
+  (flet ((define-x8664-subprim (name)
+             (ccl::make-subprimitive-info :name (string name)
+                                          :offset (prog1 origin
+                                                    (incf origin step)))))
+    (macrolet ((defx8664subprim (name)
+                   `(define-x8664-subprim ',name)))
+      (defparameter *x8664-subprims*
+        (vector
+         (defx8664subprim .SPjmpsym)
+         (defx8664subprim .SPjmpnfn)
+         (defx8664subprim .SPfuncall)
+         (defx8664subprim .SPmkcatch1v)
+         (defx8664subprim .SPmkunwind)
+         (defx8664subprim .SPmkcatchmv)
+         (defx8664subprim .SPthrow)
+         (defx8664subprim .SPnthrowvalues)
+         (defx8664subprim .SPnthrow1value)
+         (defx8664subprim .SPbind)
+         (defx8664subprim .SPbind-self)
+         (defx8664subprim .SPbind-nil)
+         (defx8664subprim .SPbind-self-boundp-check)
+         (defx8664subprim .SPrplaca)
+         (defx8664subprim .SPrplacd)
+         (defx8664subprim .SPconslist)
+         (defx8664subprim .SPconslist-star)
+         (defx8664subprim .SPstkconslist)
+         (defx8664subprim .SPstkconslist-star)
+         (defx8664subprim .SPmkstackv)
+         (defx8664subprim .SPsubtag-misc-ref)
+         (defx8664subprim .SPsetqsym)
+         (defx8664subprim .SPprogvsave)
+         (defx8664subprim .SPstack-misc-alloc)
+         (defx8664subprim .SPgvector)
+         (defx8664subprim .SPnvalret)
+         (defx8664subprim .SPmvpass)
+         (defx8664subprim .SPrecover-values-for-mvcall)
+         (defx8664subprim .SPnthvalue)
+         (defx8664subprim .SPvalues)
+         (defx8664subprim .SPdefault-optional-args)
+         (defx8664subprim .SPopt-supplied-p)
+         (defx8664subprim .SPheap-rest-arg)
+         (defx8664subprim .SPreq-heap-rest-arg)
+         (defx8664subprim .SPheap-cons-rest-arg)
+         (defx8664subprim .SPsimple-keywords)
+         (defx8664subprim .SPkeyword-args)
+         (defx8664subprim .SPkeyword-bind)
+         (defx8664subprim .SPffcall)
+         (defx8664subprim .SParef2)
+         (defx8664subprim .SPksignalerr)
+         (defx8664subprim .SPstack-rest-arg)
+         (defx8664subprim .SPreq-stack-rest-arg)
+         (defx8664subprim .SPstack-cons-rest-arg)
+         (defx8664subprim .SPpoweropen-callbackX)
+         (defx8664subprim .SPcall-closure)
+         (defx8664subprim .SPgetXlong)
+         (defx8664subprim .SPspreadargz)
+         (defx8664subprim .SPtfuncallgen)
+         (defx8664subprim .SPtfuncallslide)
+         (defx8664subprim .SPtfuncallvsp)
+         (defx8664subprim .SPtcallsymgen)
+         (defx8664subprim .SPtcallsymslide)
+         (defx8664subprim .SPtcallsymvsp)
+         (defx8664subprim .SPtcallnfngen)
+         (defx8664subprim .SPtcallnfnslide)
+         (defx8664subprim .SPtcallnfnvsp)
+         (defx8664subprim .SPmisc-ref)
+         (defx8664subprim .SPmisc-set)
+         (defx8664subprim .SPstkconsyz)
+         (defx8664subprim .SPstkvcell0)
+         (defx8664subprim .SPstkvcellvsp)
+         (defx8664subprim .SPmakestackblock)
+         (defx8664subprim .SPmakestackblock0)
+         (defx8664subprim .SPmakestacklist)
+         (defx8664subprim .SPstkgvector)
+         (defx8664subprim .SPmisc-alloc)
+         (defx8664subprim .SPpoweropen-ffcallX)
+         (defx8664subprim .SPgvset)
+         (defx8664subprim .SPmacro-bind)
+         (defx8664subprim .SPdestructuring-bind)
+         (defx8664subprim .SPdestructuring-bind-inner)
+         (defx8664subprim .SPrecover-values)
+         (defx8664subprim .SPvpopargregs)
+         (defx8664subprim .SPinteger-sign)
+         (defx8664subprim .SPsubtag-misc-set)
+         (defx8664subprim .SPspread-lexpr-z)
+         (defx8664subprim .SPstore-node-conditional)
+         (defx8664subprim .SPreset)
+         (defx8664subprim .SPmvslide)
+         (defx8664subprim .SPsave-values)
+         (defx8664subprim .SPadd-values)
+         (defx8664subprim .SPcallback)
+         (defx8664subprim .SPmisc-alloc-init)
+         (defx8664subprim .SPstack-misc-alloc-init)
+         (defx8664subprim .SPset-hash-key)
+         (defx8664subprim .SPaset2)
+         (defx8664subprim .SPcallbuiltin)
+         (defx8664subprim .SPcallbuiltin0)
+         (defx8664subprim .SPcallbuiltin1)
+         (defx8664subprim .SPcallbuiltin2)
+         (defx8664subprim .SPcallbuiltin3)
+         (defx8664subprim .SPpopj)
+         (defx8664subprim .SPrestorefullcontext)
+         (defx8664subprim .SPsavecontextvsp)
+         (defx8664subprim .SPsavecontext0)
+         (defx8664subprim .SPrestorecontext)
+         (defx8664subprim .SPlexpr-entry)
+         (defx8664subprim .SPpoweropen-syscall)
+         (defx8664subprim .SPbuiltin-plus)
+         (defx8664subprim .SPbuiltin-minus)
+         (defx8664subprim .SPbuiltin-times)
+         (defx8664subprim .SPbuiltin-div)
+         (defx8664subprim .SPbuiltin-eq)
+         (defx8664subprim .SPbuiltin-ne)
+         (defx8664subprim .SPbuiltin-gt)
+         (defx8664subprim .SPbuiltin-ge)
+         (defx8664subprim .SPbuiltin-lt)
+         (defx8664subprim .SPbuiltin-le)
+         (defx8664subprim .SPbuiltin-eql)
+         (defx8664subprim .SPbuiltin-length)
+         (defx8664subprim .SPbuiltin-seqtype)
+         (defx8664subprim .SPbuiltin-assq)
+         (defx8664subprim .SPbuiltin-memq)
+         (defx8664subprim .SPbuiltin-logbitp)
+         (defx8664subprim .SPbuiltin-logior)
+         (defx8664subprim .SPbuiltin-logand)
+         (defx8664subprim .SPbuiltin-ash)
+         (defx8664subprim .SPbuiltin-negate)
+         (defx8664subprim .SPbuiltin-logxor)
+         (defx8664subprim .SPbuiltin-aref1)
+         (defx8664subprim .SPbuiltin-aset1)
+         (defx8664subprim .SPbreakpoint)
+         (defx8664subprim .SPeabi-ff-call)
+         (defx8664subprim .SPeabi-callback)
+         (defx8664subprim .SPsyscall)
+         (defx8664subprim .SPgetu64)
+         (defx8664subprim .SPgets64)
+         (defx8664subprim .SPmakeu64)
+         (defx8664subprim .SPmakes64)
+         (defx8664subprim .SPspecref)
+         (defx8664subprim .SPspecset)
+         (defx8664subprim .SPspecrefcheck)
+         (defx8664subprim .SPrestoreintlevel)
+         (defx8664subprim .SPmakes32)
+         (defx8664subprim .SPmakeu32)
+         (defx8664subprim .SPgets32)
+         (defx8664subprim .SPgetu32)
+         (defx8664subprim .SPfix-overflow)
+         (defx8664subprim .SPmvpasssym)
+         (defx8664subprim .SParef3)
+         (defx8664subprim .SPaset3)
+         (defx8664subprim .SPffcall-return-registers)
+         (defx8664subprim .SPunused-5)
+         (defx8664subprim .SPset-hash-key-conditional)
+         (defx8664subprim .SPunbind-interrupt-level)
+         (defx8664subprim .SPunbind)
+         (defx8664subprim .SPunbind-n)
+         (defx8664subprim .SPunbind-to)
+         (defx8664subprim .SPbind-interrupt-level-m1)
+         (defx8664subprim .SPbind-interrupt-level)
+         (defx8664subprim .SPbind-interrupt-level-0)
+         (defx8664subprim .SPprogvrestore)
+         (defx8664subprim .SPnmkunwind)
+         
+         )))))
+
+(defparameter *x8664-target-arch*
+  (arch::make-target-arch :name :x8664
+                          :lisp-node-size 8
+                          :nil-value canonical-nil-value
+                          :fixnum-shift fixnumshift
+                          :most-positive-fixnum (1- (ash 1 (1- (- 64 fixnumshift))))
+                          :most-negative-fixnum (- (ash 1 (1- (- 64 fixnumshift))))
+                          :misc-data-offset misc-data-offset
+                          :misc-dfloat-offset misc-dfloat-offset
+                          :nbits-in-word 64
+                          :ntagbits 4
+                          :nlisptagbits 3
+                          :uvector-subtags *x8664-target-uvector-subtags*
+                          :max-64-bit-constant-index max-64-bit-constant-index
+                          :max-32-bit-constant-index max-32-bit-constant-index
+                          :max-16-bit-constant-index max-16-bit-constant-index
+                          :max-8-bit-constant-index max-8-bit-constant-index
+                          :max-1-bit-constant-index max-1-bit-constant-index
+                          :word-shift 3
+                          :code-vector-prefix nil
+                          :gvector-types '(:ratio :complex :symbol :function
+                                           :catch-frame :struct :istruct
+                                           :pool :population :hash-vector
+                                           :package :value-cell :instance
+                                           :lock :slot-vector
+                                           :simple-vector)
+                          :1-bit-ivector-types '(:bit-vector)
+                          :8-bit-ivector-types '(:signed-8-bit-vector
+                                                 :unsigned-8-bit-vector)
+                          :16-bit-ivector-types '(:signed-16-bit-vector
+                                                  :unsigned-16-bit-vector)
+                          :32-bit-ivector-types '(:signed-32-bit-vector
+                                                  :unsigned-32-bit-vector
+                                                  :single-float-vector
+                                                  :double-float
+                                                  :bignum
+                                                  :simple-string)
+                          :64-bit-ivector-types '(:double-float-vector
+                                                  :unsigned-64-bit-vector
+                                                  :signed-64-bit-vector
+                                                  :fixnum-vector)
+                          :array-type-name-from-ctype-function
+                          #'x8664-array-type-name-from-ctype
+                          :package-name "X8664"
+                          :t-offset t-offset
+                          :array-data-size-function #'x8664-misc-byte-count
+                          :numeric-type-name-to-typecode-function
+                          #'(lambda (type-name)
+                              (ecase type-name
+                                (fixnum tag-fixnum)
+                                (bignum subtag-bignum)
+                                ((short-float single-float) subtag-single-float)
+                                ((long-float double-float) subtag-double-float)
+                                (ratio subtag-ratio)
+                                (complex subtag-complex)))
+                          :subprims-base x8664-subprims-base
+                          :subprims-shift x8664::*x8664-subprims-shift*
+                          :subprims-table x8664::*x8664-subprims*
+                          :primitive->subprims `(((0 . 23) . ,(ccl::%subprim-name->offset '.SPbuiltin-plus x8664::*x8664-subprims*)))
+                          :unbound-marker-value unbound-marker
+                          :slot-unbound-marker-value slot-unbound-marker
+                          :fixnum-tag tag-fixnum
+                          :single-float-tag subtag-single-float
+                          :single-float-tag-is-subtag nil
+                          :double-float-tag subtag-double-float
+                          :cons-tag fulltag-cons
+                          :null-tag fulltag-nil
+                          :symbol-tag fulltag-symbol
+                          :symbol-tag-is-subtag nil
+                          :function-tag fulltag-function
+                          :function-tag-is-subtag nil
+                          :big-endian nil
+                          :misc-subtag-offset misc-subtag-offset
+                          :car-offset cons.car
+                          :cdr-offset cons.cdr
+                          :subtag-char subtag-character
+                          :charcode-shift charcode-shift
+                          :fulltagmask fulltagmask
+                          :fulltag-misc fulltag-misc
+                          :char-code-limit #x110000
+                          ))
+
+;;; arch macros
+(defmacro defx8664archmacro (name lambda-list &body body)
+  `(arch::defarchmacro :x8664 ,name ,lambda-list ,@body))
+
+(defx8664archmacro ccl::%make-sfloat ()
+  (error "~s shouldn't be used in code targeting :X8664" 'ccl::%make-sfloat))
+
+(defx8664archmacro ccl::%make-dfloat ()
+  `(ccl::%alloc-misc x8664::double-float.element-count x8664::subtag-double-float))
+
+(defx8664archmacro ccl::%numerator (x)
+  `(ccl::%svref ,x x8664::ratio.numer-cell))
+
+(defx8664archmacro ccl::%denominator (x)
+  `(ccl::%svref ,x x8664::ratio.denom-cell))
+
+(defx8664archmacro ccl::%realpart (x)
+  `(ccl::%svref ,x x8664::complex.realpart-cell))
+                    
+(defx8664archmacro ccl::%imagpart (x)
+  `(ccl::%svref ,x x8664::complex.imagpart-cell))
+
+;;;
+(defx8664archmacro ccl::%get-single-float-from-double-ptr (ptr offset)
+ `(ccl::%double-float->short-float (ccl::%get-double-float ,ptr ,offset)))
+
+(defx8664archmacro ccl::codevec-header-p (word)
+  (declare (ignore word))
+  (error "~s makes no sense on :X8664" 'ccl::codevec-header-p))
+
+;;;
+
+(defx8664archmacro ccl::immediate-p-macro (thing)
+  (let* ((tag (gensym)))
+    `(let* ((,tag (ccl::lisptag ,thing)))
+      (declare (type (unsigned-byte 3) ,tag))
+      (logbitp ,tag (logior (ash 1 x8664::tag-fixnum)
+                    (ash 1 x8664::tag-imm-0)
+                    (ash 1 x8664::tag-imm-1))))))
+
+(defx8664archmacro ccl::hashed-by-identity (thing)
+  (let* ((typecode (gensym)))
+    `(let* ((,typecode (ccl::typecode ,thing)))
+      (declare (fixnum ,typecode))
+      (or (= ,typecode  x8664::subtag-instance)
+       (and (<= ,typecode x8664::fulltag-symbol)
+        (logbitp (the (integer 0 #.x8664::fulltag-symbol) ,typecode)
+                 (logior (ash 1 x8664::tag-fixnum)
+                         (ash 1 x8664::tag-imm-0)
+                         (ash 1 x8664::tag-imm-1)
+                         (ash 1 x8664::fulltag-symbol))))))))
+
+;;;
+(defx8664archmacro ccl::%get-kernel-global (name)
+  `(ccl::%fixnum-ref 0 (+ ,(ccl::target-nil-value)
+                        ,(%kernel-global
+                         (if (ccl::quoted-form-p name)
+                           (cadr name)
+                           name)))))
+
+(defx8664archmacro ccl::%get-kernel-global-ptr (name dest)
+  `(ccl::%setf-macptr
+    ,dest
+    (ccl::%int-to-ptr (ccl::%fixnum-ref-natural 0 (+ ,(ccl::target-nil-value)
+                                 ,(%kernel-global
+                                   (if (ccl::quoted-form-p name)
+                                     (cadr name)
+                                     name)))))))
+
+(defx8664archmacro ccl::%target-kernel-global (name)
+  `(x8664::%kernel-global ,name))
+
+(defx8664archmacro ccl::lfun-vector (fun)
+  `(ccl::%function-to-function-vector ,fun))
+
+(defx8664archmacro ccl::lfun-vector-lfun (lfv)
+  `(ccl::%function-vector-to-function ,lfv))
+
+(defx8664archmacro ccl::area-code ()
+  area.code)
+
+(defx8664archmacro ccl::area-succ ()
+  area.succ)
+
+(defx8664archmacro ccl::nth-immediate (f i)
+  `(ccl::%nth-immediate ,f (the fixnum (- (the fixnum ,i) 1))))
+
+(defx8664archmacro ccl::set-nth-immediate (f i new)
+  `(ccl::%set-nth-immediate ,f (the fixnum (- (the fixnum ,i) 1)) ,new))
+
+(defx8664archmacro ccl::symptr->symvector (s)
+  `(ccl::%symptr->symvector ,s))
+
+(defx8664archmacro ccl::symvector->symptr (s)
+  `(ccl::%symvector->symptr ,s))
+
+(defx8664archmacro ccl::function-to-function-vector (f)
+  `(ccl::%function-to-function-vector ,f))
+
+(defx8664archmacro ccl::function-vector-to-function (v)
+  `(ccl::%function-vector-to-function ,v))
+
+(defx8664archmacro ccl::with-ffcall-results ((buf) &body body)
+  ;; Reserve space for rax,rdx,xmm0,xmm1 only.
+  (let* ((size (+ (* 2 8) (* 2 8))))
+    `(ccl::%stack-block ((,buf ,size :clear t))
+      ,@body)))
+
+;;; an (lea (@ disp (% rip)) (% fn)) instruction following a tagged
+;;; return address helps the runtime map from the return address to
+;;; the containing function.  That instuction is 7 bytes long: 3
+;;; bytes of code followed by 4 bytes of displacement.  The constant
+;;; part of that - assuming that FN is R13 - looks like #x4c #x8d #x2d.
+
+(defconstant recover-fn-from-rip-length 7)
+(defconstant recover-fn-from-rip-disp-offset 3)
+(defconstant recover-fn-from-rip-word0 #x8d4c)
+(defconstant recover-fn-from-rip-byte2 #x2d)
+
+;;; For backtrace: the relative PC of an argument-check trap
+;;; must be less than or equal to this value.  (Because of
+;;; the way that we do "anchored" UUOs, it should always be =.)
+
+(defconstant arg-check-trap-pc-limit 7)
+
+(provide "X8664-ARCH")
Index: /branches/new-random/compiler/X86/X8664/x8664-backend.lisp
===================================================================
--- /branches/new-random/compiler/X86/X8664/x8664-backend.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/X8664/x8664-backend.lisp	(revision 13309)
@@ -0,0 +1,664 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "NXENV")
+  (require "X8664ENV"))
+
+
+(defvar *x8664-vinsn-templates* (make-hash-table :test #'eq))
+
+
+
+(defvar *known-x8664-backends* ())
+
+
+#+(or linuxx86-target (not x86-target))
+(defvar *linuxx8664-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+                :lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+                :platform-syscall-mask (logior platform-os-linux platform-cpu-x86 platform-word-size-64) 
+		:p2-dispatch *x862-specials*
+		:p2-vinsn-templates *x8664-vinsn-templates*
+		:p2-template-hash-name '*x8664-vinsn-templates*
+		:p2-compile 'x862-compile
+		:target-specific-features
+		'(:x8664 :x86-target :linux-target :linuxx86-target :x8664-target
+                  :linuxx8664-target
+                  :little-endian-target
+                  :64-bit-target)
+		:target-fasl-pathname (make-pathname :type "lx64fsl")
+		:target-platform (logior platform-cpu-x86
+                                         platform-os-linux
+                                         platform-word-size-64)
+		:target-os :linuxx86
+		:name :linuxx8664
+		:target-arch-name :x8664
+		:target-foreign-type-data nil
+
+
+                :target-arch x8664::*x8664-target-arch*
+                :lisp-context-register x8664::gs
+                ))
+
+
+#+darwinx86-target
+(defvar *darwinx8664-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+		:lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+		:p2-dispatch *x862-specials*
+		:p2-vinsn-templates *x8664-vinsn-templates*
+		:p2-template-hash-name '*x8664-vinsn-templates*
+		:p2-compile 'x862-compile
+                :platform-syscall-mask (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) 
+		:target-specific-features
+		'(:x8664 :x86-target :darwin-target :darwinx86-target :x8664-target
+                  :darwinx8664-target
+                  :little-endian-target
+                  :64-bit-target)
+		:target-fasl-pathname (make-pathname :type "dx64fsl")
+		:target-platform (logior platform-cpu-x86
+                                         platform-os-darwin
+                                         platform-word-size-64)
+		:target-os :darwinx86
+		:name :darwinx8664
+		:target-arch-name :x8664
+		:target-foreign-type-data nil
+                :target-arch x8664::*x8664-target-arch*
+                ;; Overload %gs until Apple straightens things out.
+                ;; Whoops; they never did.
+                :lisp-context-register x8664::r11
+                ))
+
+#+freebsdx86-target
+(defvar *freebsdx8664-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+		:lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+		:p2-dispatch *x862-specials*
+		:p2-vinsn-templates *x8664-vinsn-templates*
+		:p2-template-hash-name '*x8664-vinsn-templates*
+		:p2-compile 'x862-compile
+		:target-specific-features
+		'(:x8664 :x86-target :freebsd-target :freebsdx86-target :x8664-target
+                  :freebsdx8664-target                  
+                  :little-endian-target
+                  :64-bit-target)
+		:target-fasl-pathname (make-pathname :type "fx64fsl")
+		:target-platform (logior platform-cpu-x86
+                                         platform-os-freebsd
+                                         platform-word-size-64)
+		:target-os :freebsdx86
+		:name :freebsdx8664
+		:target-arch-name :x8664
+		:target-foreign-type-data nil
+                :target-arch x8664::*x8664-target-arch*
+                :platform-syscall-mask (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)
+                :lisp-context-register x8664::gs
+                ))
+
+#+solarisx86-target
+(defvar *solarisx8664-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+		:lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+		:p2-dispatch *x862-specials*
+		:p2-vinsn-templates *x8664-vinsn-templates*
+		:p2-template-hash-name '*x8664-vinsn-templates*
+		:p2-compile 'x862-compile
+		:target-specific-features
+		'(:x8664 :x86-target :solaris-target :solarisx86-target :x8664-target
+                  :solarisx8664-target
+                  :solarisx64-target
+                  :little-endian-target
+                  :64-bit-target)
+		:target-fasl-pathname (make-pathname :type "sx64fsl")
+		:target-platform (logior platform-cpu-x86
+                                         platform-os-solaris
+                                         platform-word-size-64)
+		:target-os :solarisx86
+		:name :solarisx8664
+		:target-arch-name :x8664
+		:target-foreign-type-data nil
+                :target-arch x8664::*x8664-target-arch*
+                :platform-syscall-mask (logior platform-os-solaris platform-cpu-x86 platform-word-size-64)
+                :lisp-context-register x8664::gs
+                ))
+
+#+win64-target
+(defvar *win64-backend*
+  (make-backend :lookup-opcode 'lookup-x86-opcode
+		:lookup-macro #'false
+                :lap-opcodes x86::*x86-opcode-templates*
+                :define-vinsn 'define-x86-vinsn
+		:p2-dispatch *x862-specials*
+		:p2-vinsn-templates *x8664-vinsn-templates*
+		:p2-template-hash-name '*x8664-vinsn-templates*
+		:p2-compile 'x862-compile
+		:target-specific-features
+		'(:x8664 :x86-target :win64-target :windows-target :x8664-target
+                  :winx64-target                  
+                  :little-endian-target
+                  :64-bit-target)
+		:target-fasl-pathname (make-pathname :type "wx64fsl")
+		:target-platform (logior platform-cpu-x86
+                                         platform-os-windows
+                                         platform-word-size-64)
+		:target-os :win64
+		:name :win64
+		:target-arch-name :x8664
+		:target-foreign-type-data nil
+                :target-arch x8664::*x8664-target-arch*
+                :platform-syscall-mask (logior platform-os-windows platform-cpu-x86 platform-word-size-64)
+                :lisp-context-register x8664::r11
+                ))
+
+#+(or linuxx86-target (not x86-target))
+(pushnew *linuxx8664-backend* *known-x8664-backends* :key #'backend-name)
+
+
+#+darwinx86-target
+(pushnew *darwinx8664-backend* *known-x8664-backends* :key #'backend-name)
+
+#+freebsdx86-target
+(pushnew *freebsdx8664-backend* *known-x8664-backends* :key #'backend-name)
+
+#+solarisx86-target
+(pushnew *solarisx8664-backend* *known-x8664-backends* :key #'backend-name)
+
+#+win64-target
+(pushnew *win64-backend* *known-x8664-backends* :key #'backend-name)
+
+(defvar *x8664-backend* (car *known-x8664-backends*))
+
+(defun fixup-x8664-backend ()
+  (dolist (b *known-x8664-backends*)
+    (setf #| (backend-lap-opcodes b) x86::*x86-opcodes* |#
+	  (backend-p2-dispatch b) *x862-specials*
+	  (backend-p2-vinsn-templates b)  *x8664-vinsn-templates*)
+    (or (backend-lap-macros b) (setf (backend-lap-macros b)
+                                     (make-hash-table :test #'equalp)))))
+
+
+
+(fixup-x8664-backend)
+
+#+x8664-target
+(setq *host-backend* *x8664-backend* *target-backend* *x8664-backend*)
+
+(defun setup-x8664-ftd (backend)
+  (or (backend-target-foreign-type-data backend)
+      (let* ((name (backend-name backend))
+             (ftd
+              (case name
+                (:linuxx8664
+                 (make-ftd :interface-db-directory
+                           (if (eq backend *host-backend*)
+                             "ccl:x86-headers64;"
+                             "ccl:cross-x86-headers64;")
+                           :interface-package-name "X86-LINUX64"
+                           :attributes '(:bits-per-word  64
+                                         :struct-by-value t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-LINUX64")
+                           :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-LINUX64")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-LINUX64")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-LINUX64")))
+                (:darwinx8664
+                 (make-ftd :interface-db-directory
+                           (if (eq backend *host-backend*)
+                             "ccl:darwin-x86-headers64;"
+                             "ccl:cross-darwin-x86-headers64;")
+                           :interface-package-name "X86-DARWIN64"
+                           :attributes '(:bits-per-word  64
+                                         :signed-char t
+                                         :struct-by-value t
+                                         :prepend-underscore t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-DARWIN64")
+                           :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-DARWIN64")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-DARWIN64")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-DARWIN64")))
+                (:freebsdx8664
+                 (make-ftd :interface-db-directory
+                           (if (eq backend *host-backend*)
+                             "ccl:freebsd-headers64;"
+                             "ccl:cross-freebsd-headers64;")
+                           :interface-package-name "X86-FREEBSD64"
+                           :attributes '(:bits-per-word  64
+                                         :struct-by-value t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-FREEBSD64")
+                           :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-FREEBSD64")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-FREEBSD64")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-FREEBSD64")))
+                (:solarisx8664
+                 (make-ftd :interface-db-directory
+                           (if (eq backend *host-backend*)
+                             "ccl:solarisx64-headers;"
+                             "ccl:cross-solarisx64-headers;")
+                           :interface-package-name "X86-SOLARIS64"
+                           :attributes '(:bits-per-word  64
+                                         :struct-by-value t)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "X86-SOLARIS64")
+                           :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "X86-SOLARIS64")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "X86-SOLARIS64")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "X86-SOLARIS64")))
+                (:win64
+                 (make-ftd :interface-db-directory
+                           (if (eq backend *host-backend*)
+                             "ccl:win64-headers;"
+                             "ccl:cross-win64-headers;")
+                           :interface-package-name "WIN64"
+                           :attributes '(:bits-per-word  64
+                                         :struct-by-value t
+                                         :bits-per-long 32)
+                           :ff-call-expand-function
+                           (intern "EXPAND-FF-CALL" "WIN64")
+                           :ff-call-struct-return-by-implicit-arg-function
+                           (intern "RECORD-TYPE-RETURNS-STRUCTURE-AS-FIRST-ARG"
+                                   "WIN64")
+                           :callback-bindings-function
+                           (intern "GENERATE-CALLBACK-BINDINGS" "WIN64")
+                           :callback-return-value-function
+                           (intern "GENERATE-CALLBACK-RETURN-VALUE" "WIN64"))))))
+        (install-standard-foreign-types ftd)
+        (use-interface-dir :libc ftd)
+        (setf (backend-target-foreign-type-data backend) ftd))))
+
+#-x8664-target
+(setup-x8664-ftd *x8664-backend*)
+
+(pushnew *x8664-backend* *known-backends* :key #'backend-name)
+
+;;; FFI stuff.  Seems to be shared by Darwin/Linux/FreeBSD.
+
+;;; A returned structure is passed as an invisible first argument if
+;;; it's more than 2 doublewords long or if it contains unaligned fields.
+;;; Not clear how the latter case can happen, so this just checks for
+;;; the first.
+(defun x8664::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+             (not (typep rtype 'unsigned-byte))
+             (not (member rtype *foreign-representation-type-keywords*
+                          :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+                    rtype
+                    (parse-foreign-type rtype))))
+      (> (ensure-foreign-type-bits ftype) 128))))
+
+;;; On x8664, structures can be passed by value:
+;;;  a) in memory, if they're more than 128 bits in size or if there aren't
+;;;     enough of the right kind of register to pass them entirely in registers.
+;;;  b) as a series of 64-bit chunks, passed in GPRs if any component of the
+;;;     chunk is a non FLOAT or in FPRs otherwise.
+;;; Note that this means that a chunk consisting of two SINGLE-FLOATs would
+;;; be passed in the low 64 bit of an SSE (xmm) register.
+
+(defun x8664::field-is-of-class-integer (field)
+  ;; Return true if field is of "class" integer or if it's a record
+  ;; type of class integer.  (See the System V AMD64 ABI document for
+  ;; a convoluted definition of field "classes".)
+  (let* ((ftype (foreign-record-field-type field)))
+    (typecase ftype
+      ((or foreign-integer-type foreign-pointer-type) t)
+      (foreign-record-type (dolist (f (foreign-record-type-fields ftype))
+                             (when (x8664::field-is-of-class-integer f)
+                               (return t))))
+      (otherwise nil))))
+
+(defun x8664::classify-8byte (field-list bit-limit)
+  ;; CDR down the fields in FIELD-LIST until we find a field of class integer,
+  ;; hit the end of the list, or find a field whose offset is >= BIT-LIMIT.
+  ;; In the first case, return :INTEGER.  In other cases, return :FLOAT.
+  (dolist (field field-list :float)
+    (if (<= bit-limit (foreign-record-field-offset field))
+      (return :float)
+      (if (x8664::field-is-of-class-integer field)
+        (return :integer)))))
+
+;;; Return a first value :memory, :integer, or::float and a second
+;;; value of NIL, :integer, or :float according to how the structure
+;;; RTYPE should ideally be passed or returned.  Note that the caller
+;;; may decide to turn this to :memory if there aren't enough
+;;; available registers of the right class when passing an instance of
+;;; this structure type.
+(defun x8664::classify-record-type (rtype)
+  (let* ((nbits (ensure-foreign-type-bits rtype))
+         (fields (foreign-record-type-fields rtype)))
+    (cond ((> nbits 128) (values :memory nil))
+          ((<= nbits 64) (values (x8664::classify-8byte fields 64) nil))
+          (t (values (x8664::classify-8byte fields 64)
+               (do* ()
+                    ((>= (foreign-record-field-offset (car fields)) 64)
+                     (x8664::classify-8byte fields 128))
+                 (setq fields (cdr fields))))))))
+
+(defun x8664::struct-from-regbuf-values (r rtype regbuf)
+  (multiple-value-bind (first second)
+      (x8664::classify-record-type rtype)
+    (let* ((gpr-offset 0)
+           (fpr-offset 16))
+      ;; Do this 32 bits at a time, to avoid consing.
+      (collect ((forms))
+        (case first
+          (:integer (forms `(setf (%get-unsigned-long ,r 0)
+                             (%get-unsigned-long ,regbuf 0)))
+                    (forms `(setf (%get-unsigned-long ,r 4)
+                             (%get-unsigned-long ,regbuf 4)))
+                    (setq gpr-offset 8))
+          (:float (forms `(setf (%get-unsigned-long ,r 0)
+                             (%get-unsigned-long ,regbuf 16)))
+                  (forms `(setf (%get-unsigned-long ,r 4)
+                             (%get-unsigned-long ,regbuf 20)))
+                  (setf fpr-offset 24)))
+        (case second
+          (:integer (forms `(setf (%get-unsigned-long ,r 8)
+                             (%get-unsigned-long ,regbuf ,gpr-offset)))
+                    (forms `(setf (%get-unsigned-long ,r 12)
+                             (%get-unsigned-long ,regbuf ,(+ gpr-offset 4)))))
+          (:float (forms `(setf (%get-unsigned-long ,r 8)
+                             (%get-unsigned-long ,regbuf ,fpr-offset)))
+                  (forms `(setf (%get-unsigned-long ,r 12)
+                             (%get-unsigned-long ,regbuf ,(+ fpr-offset 4))))))
+        `(progn ,@(forms))))))
+
+(defun x8664::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (let* ((result-type-spec (or (car (last args)) :void))
+         (regbuf nil)
+         (result-temp nil)
+         (result-form nil)
+         (struct-result-type nil)
+         (structure-arg-temp nil))
+    (multiple-value-bind (result-type error)
+        (ignore-errors (parse-foreign-type result-type-spec))
+      (if error
+        (setq result-type-spec :void result-type *void-foreign-type*)
+        (setq args (butlast args)))
+      (collect ((argforms))
+        (when (eq (car args) :monitor-exception-ports)
+          (argforms (pop args)))
+        (when (typep result-type 'foreign-record-type)
+          (setq result-form (pop args)
+                struct-result-type result-type
+                result-type *void-foreign-type*
+                result-type-spec :void)
+          (if (x8664::record-type-returns-structure-as-first-arg struct-result-type)
+            (progn
+              (argforms :address)
+              (argforms result-form))
+            (progn
+              (setq regbuf (gensym)
+                    result-temp (gensym))
+              (argforms :registers)
+              (argforms regbuf))))
+        (let* ((valform nil))
+                      (unless (evenp (length args))
+              (error "~s should be an even-length list of alternating foreign types and values" args))
+            (do* ((args args (cddr args))
+                  (remaining-gprs 6)
+                  (remaining-fprs 8))
+                 ((null args))
+              (let* ((arg-type-spec (car args))
+                     (arg-value-form (cadr args)))
+                (if (or (member arg-type-spec *foreign-representation-type-keywords*
+                                :test #'eq)
+                        (typep arg-type-spec 'unsigned-byte))
+                  (progn
+                    (if (or (eq arg-type-spec :double-float)
+                            (eq arg-type-spec :single-float))
+                      (decf remaining-fprs)
+                      (unless (typep arg-type-spec 'unsigned-byte)
+                        (decf remaining-gprs)))
+                    (argforms arg-type-spec)
+                    (argforms arg-value-form))
+                  (let* ((ftype (parse-foreign-type arg-type-spec)))
+                    (when (and (typep ftype 'foreign-record-type)
+                             (eq (foreign-record-type-kind ftype) :transparent-union))
+                      (ensure-foreign-type-bits ftype)
+                      (setq ftype (foreign-record-field-type
+                                   (car (foreign-record-type-fields ftype)))
+                            arg-type-spec (foreign-type-to-representation-type ftype)))
+                    (if (typep ftype 'foreign-record-type)
+                      (multiple-value-bind (first8 second8)
+                          (x8664::classify-record-type ftype)
+                        (let* ((gprs remaining-gprs)
+                               (fprs remaining-fprs))
+                          (case first8
+                            (:integer (if (< (decf gprs) 0) (setq first8 :memory)))
+                            (:float (if (< (decf fprs) 0) (setq first8 :memory))))
+                          (case second8
+                            (:integer (if (< (decf gprs) 0) (setq first8 :memory)))
+                            (:float (if (< (decf fprs) 0) (setq first8 :memory)))))
+                        (if (eq first8 :memory)
+                          (progn
+                            (argforms (ceiling (foreign-record-type-bits ftype) 64))
+                            (argforms arg-value-form))
+                          (progn
+                            (if second8
+                              (progn
+                                (unless structure-arg-temp
+                                  (setq structure-arg-temp (gensym)))
+                                (setq valform `(%setf-macptr ,structure-arg-temp ,arg-value-form)))
+                              (setq valform arg-value-form))
+                            (if (eq first8 :float)
+                              (progn
+                                (decf remaining-fprs)
+                                (argforms :double-float)
+                                (argforms `(%get-double-float ,valform 0)))
+                              (progn
+                                (decf remaining-gprs)
+                                (argforms :unsigned-doubleword)
+                                (argforms `(%%get-unsigned-longlong ,valform 0))))
+                            (when second8
+                              (setq valform structure-arg-temp)
+                              (if (eq second8 :float)
+                                (progn
+                                (decf remaining-fprs)
+                                (argforms :double-float)
+                                (argforms `(%get-double-float ,valform 8)))
+                              (progn
+                                (decf remaining-gprs)
+                                (argforms :unsigned-doubleword)
+                                (argforms `(%%get-unsigned-longlong ,valform 8))))))))
+                      (let* ((rtype (foreign-type-to-representation-type ftype)))
+                        (if (or (eq rtype :singlefloat) (eq rtype :double-float))
+                          (decf remaining-fprs)
+                          (decf remaining-gprs))
+                        (argforms rtype)
+                        (argforms (funcall arg-coerce arg-type-spec arg-value-form))))))))
+            (argforms (foreign-type-to-representation-type result-type))
+            (let* ((call (funcall result-coerce result-type-spec `(,@callform ,@(argforms)))))
+              (when structure-arg-temp
+                (setq call `(let* ((,structure-arg-temp (%null-ptr)))
+                             (declare (dynamic-extent ,structure-arg-temp)
+                                      (type macptr ,structure-arg-temp))
+                             ,call)))
+              (if regbuf
+                `(let* ((,result-temp (%null-ptr)))
+                  (declare (dynamic-extent ,result-temp)
+                           (type macptr ,result-temp))
+                  (%setf-macptr ,result-temp ,result-form)
+                  (%stack-block ((,regbuf (+ (* 2 8) (* 2 8))))
+                    ,call
+                    ,(x8664::struct-from-regbuf-values result-temp struct-result-type regbuf)))
+                call)))))))
+
+
+;;; Return 7 values:
+;;; A list of RLET bindings
+;;; A list of LET* bindings
+;;; A list of DYNAMIC-EXTENT declarations for the LET* bindings
+;;; A list of initializaton forms for (some) structure args
+;;; A FOREIGN-TYPE representing the "actual" return type.
+;;; A form which can be used to initialize FP-ARGS-PTR, relative
+;;;  to STACK-PTR.  (This is unused on linuxppc32.)
+;;; The byte offset of the foreign return address, relative to STACK-PTR
+
+(defun x8664::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (declare (ignore fp-args-ptr))
+  (collect ((lets)
+            (rlets)
+            (inits)
+            (dynamic-extent-names))
+    (let* ((rtype (parse-foreign-type result-spec)))
+      (when (typep rtype 'foreign-record-type)
+        (if (x8664::record-type-returns-structure-as-first-arg rtype)
+          (setq argvars (cons struct-result-name argvars)
+                argspecs (cons :address argspecs)
+                rtype *void-foreign-type*)
+          (rlets (list struct-result-name (foreign-record-type-name rtype)))))
+      (do* ((argvars argvars (cdr argvars))
+            (argspecs argspecs (cdr argspecs))
+            (gpr-arg-num 0)
+            (gpr-arg-offset -8)
+            (fpr-arg-num 0)
+            (fpr-arg-offset -56)
+            (memory-arg-offset 16)
+            (fp nil nil))
+           ((null argvars)
+            (values (rlets) (lets) (dynamic-extent-names) (inits) rtype nil 8))
+        (flet ((next-gpr ()
+                 (if (<= (incf gpr-arg-num) 6)
+                   (prog1
+                       gpr-arg-offset
+                     (decf gpr-arg-offset 8))
+                   (prog1
+                       memory-arg-offset
+                     (incf memory-arg-offset 8))))
+               (next-fpr ()
+                 (if (<= (incf fpr-arg-num) 8)
+                   (prog1
+                       fpr-arg-offset
+                     (decf fpr-arg-offset 8))
+                   (prog1
+                       memory-arg-offset
+                     (incf memory-arg-offset 8)))))
+          (let* ((name (car argvars))
+                 (spec (car argspecs))
+                 (argtype (parse-foreign-type spec))
+                 (bits (require-foreign-type-bits argtype)))
+            (if (typep argtype 'foreign-record-type)
+              (multiple-value-bind (first8 second8)
+                  (x8664::classify-record-type argtype)
+                (let* ((gprs (- 6 gpr-arg-num))
+                       (fprs (- 8 fpr-arg-num)))
+                  (case first8
+                    (:integer (if (< (decf gprs) 0) (setq first8 :memory)))
+                    (:float (if (< (decf fprs) 0) (setq first8 :memory))))
+                  (case second8
+                    (:integer (if (< (decf gprs) 0) (setq first8 :memory)))
+                    (:float (if (< (decf fprs) 0) (setq first8 :memory)))))
+                (if (eq first8 :memory)
+                  (let* ((form `(%inc-ptr ,stack-ptr ,(prog1 memory-arg-offset
+                                                                   (incf memory-arg-offset (* 8 (ceiling bits 64)))))))
+                    (when name
+                      (lets (list name form))
+                      (dynamic-extent-names name)))
+                  (progn
+                    (when name (rlets (list name (foreign-record-type-name argtype))))
+                    (let* ((init1 `(setf (%%get-unsigned-longlong ,name 0)
+                             (%%get-unsigned-longlong ,stack-ptr ,(if (eq first8 :integer) (next-gpr) (next-fpr))))))
+                      (when name (inits init1)))
+                    (if second8
+                      (let* ((init2 `(setf (%%get-unsigned-longlong ,name 8)
+                               (%%get-unsigned-longlong ,stack-ptr ,(if (eq second8 :integer) (next-gpr) (next-fpr))))))
+                        (when name (inits init2 )))))))
+              (let* ((form`(,
+                            (ecase (foreign-type-to-representation-type argtype)
+                              (:single-float (setq fp t) '%get-single-float)
+                              (:double-float (setq fp t) '%get-double-float)
+                              (:signed-doubleword  '%%get-signed-longlong)
+                              (:signed-fullword '%get-signed-long)
+                              (:signed-halfword '%get-signed-word)
+                              (:signed-byte '%get-signed-byte)
+                              (:unsigned-doubleword '%%get-unsigned-longlong)
+                              (:unsigned-fullword '%get-unsigned-long)
+                              (:unsigned-halfword '%get-unsigned-word)
+                              (:unsigned-byte '%get-unsigned-byte)
+                              (:address
+                               #+nil
+                               (when name (dynamic-extent-names name))
+                               '%get-ptr))
+                            ,stack-ptr
+                            ,(if fp (next-fpr) (next-gpr)))))                
+                (if name (lets (list name form )))))))))))
+
+(defun x8664::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (declare (ignore fp-args-ptr))
+  (unless (eq return-type *void-foreign-type*)
+    (let* ((gpr-offset -8)
+           (fpr-offset -24))
+      (if (typep return-type 'foreign-record-type)
+      ;;; Would have been mapped to :VOID unless record-type was <= 128 bits.
+        (collect ((forms))
+          (multiple-value-bind (first8 second8)
+              (x8664::classify-record-type return-type)
+            (forms `(setf (%%get-signed-longlong ,stack-ptr ,(if (eq first8 :integer) gpr-offset fpr-offset))
+                     (%%get-signed-longlong ,struct-return-arg 0)))
+            (when second8
+              (if (eq first8 :integer) (decf gpr-offset 8) (decf fpr-offset 8))
+              (forms `(setf (%%get-signed-longlong ,stack-ptr ,(if (eq first8 :integer) gpr-offset fpr-offset))
+                       (%%get-signed-longlong ,struct-return-arg 8))))
+            `(progn ,@(forms))))
+        (let* ((return-type-keyword (foreign-type-to-representation-type return-type))
+               (offset (case return-type-keyword
+                         ((:single-float :double-float) fpr-offset)
+                         (t gpr-offset))))
+          `(setf (,
+                  (case return-type-keyword
+                    (:address '%get-ptr)
+                    (:signed-doubleword '%%get-signed-longlong)
+                    (:unsigned-doubleword '%%get-unsigned-longlong)
+                    (:double-float '%get-double-float)
+                    (:single-float '%get-single-float)
+                    (:unsigned-fullword '%get-unsigned-long)
+                    (t '%%get-signed-longlong )
+                    ) ,stack-ptr ,offset) ,result))))))
+
+
+
+#+x8664-target
+(require "X8664-VINSNS")
+
+(provide "X8664-BACKEND")
Index: /branches/new-random/compiler/X86/X8664/x8664-vinsns.lisp
===================================================================
--- /branches/new-random/compiler/X86/X8664/x8664-vinsns.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/X8664/x8664-vinsns.lisp	(revision 13309)
@@ -0,0 +1,4577 @@
+;;;-*- Mode: Lisp; Package: (X86 :use CL) -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License   known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict  the preamble takes precedence.
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "VINSN")
+  (require "X8664-BACKEND"))
+
+(eval-when (:compile-toplevel :execute)
+  (require "X8664ENV"))
+
+(defmacro define-x8664-vinsn (vinsn-name (results args &optional temps) &body body)
+  (%define-vinsn *x8664-backend* vinsn-name results args temps body))
+
+
+
+(define-x8664-vinsn scale-32bit-misc-index (((dest :u64))
+					    ((idx :imm)	; A fixnum
+					     )
+					    ())
+  (movq (:%q idx) (:%q dest))
+  (shrq (:$1 1) (:%q dest)))
+
+(define-x8664-vinsn scale-16bit-misc-index (((dest :u64))
+					    ((idx :imm)	; A fixnum
+					     )
+					    ())
+  (movq (:%q idx) (:%q dest))
+  (shrq (:$ub 2) (:%q dest)))
+
+(define-x8664-vinsn scale-8bit-misc-index (((dest :u64))
+					    ((idx :imm)	; A fixnum
+					     )
+					    ())
+  (movq (:%q idx) (:%q dest))
+  (shrq (:$ub 3) (:%q dest)))
+
+;;; same as above, but looks better in bit vector contexts
+(define-x8664-vinsn scale-1bit-misc-index (((dest :u64))
+					    ((idx :imm)	; A fixnum
+					     )
+					    ())
+  (movq (:%q idx) (:%q dest))
+  (shrq (:$ub 3) (:%q dest)))
+
+(define-x8664-vinsn misc-ref-u64  (((dest :u64))
+                                  ((v :lisp)
+                                   (scaled-idx :imm)))
+  (movq (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%q dest)))
+
+(define-x8664-vinsn misc-ref-double-float  (((dest :double-float))
+                                            ((v :lisp)
+                                             (scaled-idx :imm)))
+  (movsd (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%xmm dest)))
+
+(define-x8664-vinsn misc-ref-c-double-float  (((dest :double-float))
+                                              ((v :lisp)
+                                             (idx :s32const)))
+  (movsd (:@ (:apply + x8664::misc-data-offset (:apply ash idx x8664::word-shift)) (:%q v)) (:%xmm dest)))
+
+
+(define-x8664-vinsn misc-ref-node  (((dest :lisp))
+                                    ((v :lisp)
+                                     (scaled-idx :imm)))
+  (movq (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%q dest)))
+
+(define-x8664-vinsn (push-misc-ref-node :push :node :vsp)  (()
+                                                            ((v :lisp)
+                                                             (scaled-idx :imm)))
+  (pushq (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn misc-set-node (()
+				   ((val :lisp)
+				    (v :lisp)
+				    (unscaled-idx :imm))
+				   ())
+  (movq (:%q val) (:@ x8664::misc-data-offset (:%q  v) (:%q unscaled-idx))))
+
+(define-x8664-vinsn misc-set-immediate-node (()
+                                             ((val :s32const)
+                                              (v :lisp)
+                                              (unscaled-idx :imm))
+                                             ())
+  (movq (:$l val) (:@ x8664::misc-data-offset (:%q  v) (:%q unscaled-idx))))
+
+
+(define-x8664-vinsn misc-set-double-float (()
+				   ((val :double-float)
+				    (v :lisp)
+				    (unscaled-idx :imm))
+				   ())
+  (movsd (:%xmm val) (:@ x8664::misc-data-offset (:%q  v) (:%q unscaled-idx))))
+
+(define-x8664-vinsn misc-ref-u8 (((dest :u8))
+                                 ((v :lisp)
+                                  (scaled-idx :s64)))
+  (movzbl (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%l dest)))
+
+(define-x8664-vinsn misc-ref-s8 (((dest :s8))
+                                 ((v :lisp)
+                                  (scaled-idx :s64)))
+  (movsbq (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%q dest)))
+
+(define-x8664-vinsn misc-ref-u16 (((dest :u16))
+                                  ((v :lisp)
+                                   (scaled-idx :s64)))
+  (movzwl (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%l dest)))
+
+(define-x8664-vinsn misc-ref-u32 (((dest :u32))
+                                  ((v :lisp)
+                                   (scaled-idx :s64)))
+  (movl (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%l dest)))
+
+
+(define-x8664-vinsn misc-ref-single-float (((dest :single-float))
+                                           ((v :lisp)
+                                            (scaled-idx :s64)))
+  (movss(:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%xmm dest)))
+
+(define-x8664-vinsn misc-ref-s32 (((dest :s32))
+                                  ((v :lisp)
+                                   (scaled-idx :s64)))
+  (movslq (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%q dest)))
+
+(define-x8664-vinsn misc-ref-s16 (((dest :s16))
+                                  ((v :lisp)
+                                   (scaled-idx :s64)))
+  (movswq (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%q dest)))
+
+(define-x8664-vinsn misc-ref-s64  (((dest :s64))
+                                  ((v :lisp)
+                                   (scaled-idx :imm)))
+  (movq (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx)) (:%q dest)))
+
+
+(define-x8664-vinsn misc-ref-c-node  (((dest :lisp))
+				     ((v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movq (:@ (:apply + x8664::misc-data-offset (:apply ash idx x8664::word-shift)) (:%q v)) (:%q dest)))
+
+
+(define-x8664-vinsn (push-misc-ref-c-node :push :node :vsp)
+    (()
+     ((v :lisp)
+      (idx :u32const)) ; sic
+     ())
+  (pushq (:@ (:apply + x8664::misc-data-offset (:apply ash idx x8664::word-shift)) (:%q v))))
+
+(define-x8664-vinsn misc-ref-c-u64  (((dest :u64))
+				     ((v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movq (:@ (:apply + x8664::misc-data-offset (:apply ash idx x8664::word-shift)) (:%q v)) (:%q dest)))
+
+
+(define-x8664-vinsn misc-ref-c-s64  (((dest :s64))
+				     ((v :lisp)
+				      (idx :s32const)) ; sic
+				     ())
+  (movq (:@ (:apply + x8664::misc-data-offset (:apply ash idx x8664::word-shift)) (:%q v)) (:%q dest)))
+
+
+(define-x8664-vinsn misc-ref-c-u32  (((dest :u32))
+				     ((v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movl (:@ (:apply + x8664::misc-data-offset (:apply ash idx 2)) (:%q v)) (:%l dest)))
+
+(define-x8664-vinsn misc-ref-c-s32  (((dest :s32))
+				     ((v :lisp)
+				      (idx :s32const)) ; sic
+				     ())
+  (movslq (:@ (:apply + x8664::misc-data-offset (:apply ash idx x8664::word-shift)) (:%q v)) (:%q dest)))
+
+(define-x8664-vinsn misc-ref-c-single-float  (((dest :single-float))
+                                              ((v :lisp)
+                                               (idx :s32const)) ; sic
+                                              ())
+  (movss (:@ (:apply + x8664::misc-data-offset (:apply ash idx 2)) (:%q v)) (:%xmm dest)))
+
+(define-x8664-vinsn misc-ref-c-u8  (((dest :u64))
+				     ((v :lisp)
+				      (idx :s32const)) ; sic
+				     ())
+  (movzbl (:@ (:apply + x8664::misc-data-offset idx) (:%q v)) (:%l dest)))
+
+(define-x8664-vinsn misc-ref-c-s8  (((dest :s64))
+				     ((v :lisp)
+				      (idx :s32const)) ; sic
+				     ())
+  (movsbq (:@ (:apply + x8664::misc-data-offset idx) (:%q v)) (:%q dest)))
+
+(define-x8664-vinsn misc-set-u64 (()
+                                  ((val :u64)
+                                   (v :lisp)
+                                   (idx :u64)))
+  (movq (:%q val) (:@ x8664::misc-data-offset (:%q v) (:%q idx))))
+
+(define-x8664-vinsn misc-set-immediate-u64 (()
+                                            ((val :u32const)
+                                             (v :lisp)
+                                             (idx :u64)))
+  (movq (:$l val) (:@ x8664::misc-data-offset (:%q v) (:%q idx))))
+
+(define-x8664-vinsn misc-set-c-u64 (()
+				    ((val :u64)
+				     (v :lisp)
+				     (idx :u32const)))
+  (movq (:%q val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 3)) (:%q v))))
+
+(define-x8664-vinsn misc-set-immediate-c-u64 (()
+                                              ((val :u32const)
+                                               (v :lisp)
+                                               (idx :u32const)))
+  (movq (:$l val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 3)) (:%q v))))
+
+(define-x8664-vinsn misc-set-s64 (()
+                                  ((val :s64)
+                                   (v :lisp)
+                                   (scaled-idx :imm)))
+  (movq (:%q val) (:@ x8664::misc-data-offset  (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn misc-set-immediate-s64 (()
+                                            ((val :s32const)
+                                             (v :lisp)
+                                             (scaled-idx :imm)))
+  (movq (:$l val) (:@ x8664::misc-data-offset  (:%q v) (:%q scaled-idx))))
+
+
+(define-x8664-vinsn misc-set-c-s64 (()
+				    ((val :s64)
+				     (v :lisp)
+				     (idx :s32const)))
+  (movq (:%q val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 3)) (:%q v))))
+
+(define-x8664-vinsn misc-set-immediate-c-s64 (()
+                                              ((val :s32const)
+                                               (v :lisp)
+                                               (idx :s32const)))
+  (movq (:$l val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 3)) (:%q v))))
+
+
+(define-x8664-vinsn misc-set-c-node (()
+				    ((val :lisp)
+				     (v :lisp)
+				     (idx :s32const)))
+  (movq (:%q val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 3)) (:%q v))))
+
+(define-x8664-vinsn misc-set-immediate-c-node (()
+                                               ((val :s32const)
+                                                (v :lisp)
+                                                (idx :s32const)))
+  (movq (:$l val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 3)) (:%q v))))
+
+(define-x8664-vinsn set-closure-forward-reference (()
+                                                   ((val :lisp)
+                                                    (closure :lisp)
+                                                    (idx :s32const)))
+  (movq (:%q val) (:@ (:apply + x8664::misc-function-offset (:apply ash idx x8664::word-shift)) (:%q closure))))
+
+
+(define-x8664-vinsn misc-set-c-double-float (()
+				    ((val :double-float)
+				     (v :lisp)
+				     (idx :s32const)))
+  (movsd (:%xmm val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 3)) (:%q v))))
+
+
+
+(define-x8664-vinsn (call-known-symbol :call) (((result (:lisp x8664::arg_z)))
+                                               ()
+					       ((entry (:label 1))))
+  (:talign 4)
+  (call (:@ x8664::symbol.fcell (:% x8664::fname)))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+
+(define-x8664-vinsn (jump-known-symbol :jumplr) (()
+                                                 ())
+
+  (jmp (:@ x8664::symbol.fcell (:% x8664::fname))))
+
+(define-x8664-vinsn set-nargs (()
+			       ((n :s16const)))
+  ((:pred = n 0)
+   (xorl (:%l x8664::nargs ) (:%l x8664::nargs )))
+  ((:not (:pred = n 0))
+   (movl (:$l (:apply ash n x8664::word-shift)) (:%l x8664::nargs ))))
+
+(define-x8664-vinsn check-exact-nargs (()
+                                       ((n :u16const)))
+  :resume
+  ((:pred = n 0)
+   (testl (:%l x8664::nargs) (:%l x8664::nargs)))
+  ((:not (:pred = n 0))
+   ((:pred < n 16)
+   (cmpl (:$b (:apply ash n x8664::word-shift)) (:%l x8664::nargs)))
+   ((:pred >= n 16)
+    (cmpl (:$l (:apply ash n x8664::word-shift)) (:%l x8664::nargs))))
+  (jne :bad)
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-wrong-number-of-args)))
+
+(define-x8664-vinsn check-min-nargs (()
+                                       ((min :u16const)))
+  :resume
+  ((:pred = min 1)
+   (testl (:%l x8664::nargs) (:%l x8664::nargs))
+   (je :toofew))
+  ((:not (:pred = min 1))
+   ((:pred < min 16)
+    (rcmpl (:%l x8664::nargs) (:$b (:apply ash min x8664::word-shift))))
+   ((:pred >= min 16)
+    (rcmpl (:%l x8664::nargs) (:$l (:apply ash min x8664::word-shift))))
+   (jb :toofew))  
+  
+  (:anchored-uuo-section :resume)
+  :toofew
+  (:anchored-uuo (uuo-error-too-few-args)))
+
+(define-x8664-vinsn check-max-nargs (()
+                                       ((n :u16const)))
+  :resume
+  ((:pred < n 16)
+   (rcmpl (:%l x8664::nargs) (:$b (:apply ash n x8664::word-shift))))
+  ((:pred >= n 16)
+   (rcmpl (:%l x8664::nargs) (:$l (:apply ash n x8664::word-shift))))
+  (ja :bad)
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-too-many-args)))
+
+
+(define-x8664-vinsn check-min-max-nargs (()
+                                         ((min :u16const)
+                                          (max :u16)))
+  :resume
+  ((:pred = min 1)
+   (testl (:%l x8664::nargs) (:%l x8664::nargs))
+   (je :toofew))
+  ((:not (:pred = min 1))
+   ((:pred < min 16)
+    (rcmpl (:%l x8664::nargs) (:$b (:apply ash min x8664::word-shift))))
+   ((:pred >= min 16)
+    (rcmpl (:%l x8664::nargs) (:$l (:apply ash min x8664::word-shift))))
+   (jb :toofew))
+  ((:pred < max 16)
+   (rcmpl (:%l x8664::nargs) (:$b (:apply ash max x8664::word-shift))))
+  ((:pred >= max 16)
+   (rcmpl (:%l x8664::nargs) (:$l (:apply ash max x8664::word-shift))))
+  (ja :toomany)
+  
+  (:anchored-uuo-section :resume)
+  :toofew
+  (:anchored-uuo (uuo-error-too-few-args))
+  (:anchored-uuo-section :resume)
+  :toomany
+  (:anchored-uuo (uuo-error-too-many-args)))
+
+
+(define-x8664-vinsn default-1-arg (()
+                                   ((min :u16const)))
+  ((:pred < min 16)
+   (rcmpl (:%l x8664::nargs) (:$b (:apply ash min x8664::word-shift))))
+  ((:pred >= min 16)
+   (rcmpl (:%l x8664::nargs) (:$l (:apply ash min x8664::word-shift))))
+  (jne :done)
+  ((:pred >= min 3)
+   (pushq (:%q x8664::arg_x)))
+  ((:pred >= min 2)
+   (movq (:%q x8664::arg_y) (:%q x8664::arg_x)))
+  ((:pred >= min 1)
+   (movq (:%q x8664::arg_z) (:%q x8664::arg_y)))
+  (movq (:$l (:apply target-nil-value)) (:%q x8664::arg_z))
+  :done)
+
+
+(define-x8664-vinsn default-2-args (()
+				    ((min :u16const)))
+  ((:pred < (:apply 1+ min) 16)
+   (rcmpl (:%l x8664::nargs ) (:$b (:apply ash (:apply 1+ min) x8664::word-shift))))
+  ((:pred >= (:apply 1+ min) 16)
+   (rcmpl (:%l x8664::nargs ) (:$l (:apply ash (:apply 1+ min) x8664::word-shift))))
+  (ja :done)
+  (je :one)
+  ;; We got "min" args; arg_y & arg_z default to nil
+  ((:pred >= min 3)
+   (pushq (:%q x8664::arg_x)))   
+  ((:pred >= min 2)
+   (pushq (:%q x8664::arg_y)))
+  ((:pred >= min 1)
+   (movq (:%q x8664::arg_z) (:%q x8664::arg_x)))
+  (movl (:$l (:apply target-nil-value)) (:%l x8664::arg_y))
+  (jmp :last)
+  :one
+  ;; We got min+1 args: arg_y was supplied, arg_z defaults to nil.
+  ((:pred >= min 2)
+   (pushq (:%q x8664::arg_x)))
+  ((:pred >= min 1)
+   (movq (:%q x8664::arg_y) (:%q x8664::arg_x)))
+  (movq (:%q x8664::arg_z) (:%q x8664::arg_y))
+  :last
+  (movq (:$l (:apply target-nil-value)) (:%q x8664::arg_z))
+  :done)
+
+(define-x8664-vinsn default-3-args (()
+				    ((min :u16const)))
+  ((:pred < (:apply + 2 min) 16)
+   (rcmpl (:%l x8664::nargs ) (:$b (:apply ash (:apply + 2 min) x8664::word-shift))))
+  ((:pred >= (:apply + 2 min) 16)
+   (rcmpl (:%l x8664::nargs ) (:$l (:apply ash (:apply + 2 min) x8664::word-shift))))
+  (ja :done)
+  (je :two)
+  ((:pred < min 16)
+   (rcmpl (:%l x8664::nargs ) (:$b (:apply ash min x8664::word-shift))))
+  ((:pred >= min 16)
+   (rcmpl (:%l x8664::nargs ) (:$l (:apply ash min x8664::word-shift))))
+  (je :none)
+  ;; The first (of three) &optional args was supplied.
+  ((:pred >= min 2)
+   (pushq (:%q x8664::arg_x)))
+  ((:pred >= min 1)
+   (pushq (:%q x8664::arg_y)))
+  (movq (:%q x8664::arg_z) (:%q x8664::arg_x))
+  (jmp :last-2)
+  :two
+  ;; The first two (of three) &optional args were supplied.
+  ((:pred >= min 1)
+   (pushq (:%q x8664::arg_x)))
+  (movq (:%q x8664::arg_y) (:%q x8664::arg_x))
+  (movq (:%q x8664::arg_z) (:%q x8664::arg_y))
+  (jmp :last-1)
+  ;; None of the three &optional args was provided.
+  :none
+  ((:pred >= min 3)
+   (pushq (:%q x8664::arg_x)))
+  ((:pred >= min 2)
+   (pushq (:%q x8664::arg_y)))
+  ((:pred >= min 1)
+   (pushq (:%q x8664::arg_z)))
+  (movl (:$l (:apply target-nil-value)) (:%l x8664::arg_x))
+  :last-2
+  (movl (:$l (:apply target-nil-value)) (:%l x8664::arg_y))
+  :last-1
+  (movl (:$l (:apply target-nil-value)) (:%l x8664::arg_z))
+  :done)
+
+
+(define-x8664-vinsn default-optionals (()
+                                       ((n :u16const))
+                                       ((temp :u64)))
+  ((:pred < n 16)
+   (rcmpl (:%l x8664::nargs) (:$b (:apply ash n x8664::word-shift))))
+  ((:pred >= n 16)
+   (rcmpl (:%l x8664::nargs) (:$l (:apply ash n x8664::word-shift))))
+  (movl (:%l x8664::nargs) (:%l temp))
+  (jae :done)
+  :loop
+  (addl (:$b x8664::fixnumone) (:%l temp))
+  ((:pred < n 16)
+   (cmpl (:$b (:apply ash n x8664::word-shift)) (:%l temp)))
+  ((:pred >= n 16)
+   (cmpl (:$l (:apply ash n x8664::word-shift)) (:%l temp)))  
+  (pushq (:$l (:apply target-nil-value)))
+  (jne :loop)
+  :done)
+  
+
+(define-x8664-vinsn save-lisp-context-no-stack-args (()
+                                                     ())
+  (pushq (:%q x8664::rbp))
+  (movq (:%q x8664::rsp) (:%q x8664::rbp)))
+
+
+(define-x8664-vinsn save-lisp-context-offset (()
+					      ((nbytes-pushed :s32const)))
+  (movq (:%q x8664::rbp) (:@ (:apply + nbytes-pushed x8664::node-size) (:%q x8664::rsp)))
+  (leaq (:@ (:apply + nbytes-pushed x8664::node-size) (:%q x8664::rsp)) (:%q x8664::rbp))
+  (popq  (:@ x8664::node-size (:%q x8664::rbp))))
+
+(define-x8664-vinsn save-lisp-context-variable-arg-count (()
+                                                          ()
+                                                          ((temp :u64)))
+  (movl (:%l x8664::nargs) (:%l temp))
+  (subq (:$b (* $numx8664argregs x8664::node-size)) (:%q temp))
+  (jle :push)
+  (movq (:%q x8664::rbp) (:@ x8664::node-size (:%q x8664::rsp) (:%q temp)))
+  (leaq (:@ x8664::node-size (:%q x8664::rsp) (:%q temp)) (:%q x8664::rbp))
+  (popq  (:@ 8 (:%q x8664::rbp)))
+  (jmp :done)
+  :push
+  (pushq (:%q x8664::rbp))
+  (movq (:%q x8664::rsp) (:%q x8664::rbp))
+  :done)
+
+;;; We know that some args were pushed, but don't know how many were
+;;; passed.
+(define-x8664-vinsn save-lisp-context-in-frame (()
+                                                ()
+                                                ((temp :u64)))
+  (movl (:%l x8664::nargs) (:%l temp))
+  (subq (:$b (* $numx8664argregs x8664::node-size)) (:%q temp))
+  (movq (:%q x8664::rbp) (:@ x8664::node-size (:%q x8664::rsp) (:%q temp)))
+  (leaq (:@ x8664::node-size (:%q x8664::rsp) (:%q temp)) (:%q x8664::rbp))
+  (popq  (:@ x8664::node-size (:%q x8664::rbp))))
+
+
+(define-x8664-vinsn (vpush-register :push :node :vsp)
+    (()
+     ((reg :lisp)))
+  (pushq (:% reg)))
+
+(define-x8664-vinsn (vpush-fixnum :push :node :vsp)
+    (()
+     ((const :s32const)))
+  ((:and  (:pred < const 128) (:pred >= const -128))
+   (pushq (:$b const)))
+  ((:not (:and  (:pred < const 128) (:pred >= const -128)))
+   (pushq (:$l const))))
+
+
+
+(define-x8664-vinsn vframe-load (((dest :lisp))
+				 ((frame-offset :u16const)
+				  (cur-vsp :u16const)))
+  (movq (:@ (:apply - (:apply + frame-offset x8664::word-size-in-bytes)) (:%q x8664::rbp)) (:%q dest)))
+
+(define-x8664-vinsn compare-vframe-offset-to-nil (()
+                                                  ((frame-offset :u16const)
+                                                   (cur-vsp :u16const)))
+  (cmpb (:$b x8664::fulltag-nil) (:@ (:apply - (:apply + frame-offset x8664::word-size-in-bytes)) (:%q x8664::rbp))))
+
+
+(define-x8664-vinsn compare-value-cell-to-nil (()
+                                               ((vcell :lisp)))
+  (cmpb (:$b x8664::fulltag-nil) (:@ x8664::value-cell.value (:%q vcell))))
+
+(define-x8664-vinsn lcell-load (((dest :lisp))
+				((cell :lcell)
+				 (top :lcell)))
+  (movq (:@ (:apply - (:apply + (:apply calc-lcell-offset cell) x8664::word-size-in-bytes)) (:%q x8664::rbp)) (:%q dest)))
+
+(define-x8664-vinsn (vframe-push :push :node :vsp)
+    (()
+     ((frame-offset :u16const)
+      (cur-vsp :u16const)))
+  (pushq (:@ (:apply - (:apply + frame-offset x8664::word-size-in-bytes)) (:%q x8664::rbp))))
+
+(define-x8664-vinsn vframe-store (()
+				 ((src :lisp)
+                                  (frame-offset :u16const)
+				  (cur-vsp :u16const)))
+  (movq (:%q src) (:@ (:apply - (:apply + frame-offset x8664::word-size-in-bytes)) (:%q x8664::rbp))))
+
+(define-x8664-vinsn lcell-store (()
+				 ((src :lisp)
+				  (cell :lcell)
+				  (top :lcell)))
+  (movq (:%q src) (:@ (:apply - (:apply + (:apply calc-lcell-offset cell) x8664::word-size-in-bytes)) (:%q x8664::rbp))))
+        
+(define-x8664-vinsn (popj :lispcontext :pop :csp :lrRestore :jumpLR)
+    (() 
+     ())
+  (leave)
+  (ret))
+
+(define-x8664-vinsn (restore-full-lisp-context :lispcontext :pop :vsp )
+    (()
+     ())
+  (leave))
+
+(define-x8664-vinsn compare-to-nil (()
+                                    ((arg0 t)))
+  (cmpb (:$b x8664::fulltag-nil) (:%b arg0)))
+
+(define-x8664-vinsn compare-to-t (()
+                                    ((arg0 t)))
+  (cmpq (:$l (:apply target-t-value)) (:%q arg0)))
+
+(define-x8664-vinsn ref-constant (((dest :lisp))
+                                  ((lab :label)))
+  (movq (:@ (:^ lab) (:%q x8664::fn)) (:%q dest)))
+
+(define-x8664-vinsn compare-constant-to-register (()
+                                                  ((lab :label)
+                                                   (reg :lisp)))
+  (cmpq (:@ (:^ lab) (:%q x8664::fn)) (:%q reg)))
+
+
+(define-x8664-vinsn (vpush-constant :push :node :vsp) (()
+                                                       ((lab :label)))
+  (pushq (:@ (:^ lab) (:%q x8664::fn))))
+
+  
+(define-x8664-vinsn (jump :jump)
+    (()
+     ((label :label)))
+  (jmp label))
+
+(define-x8664-vinsn (cbranch-true :branch) (()
+					    ((label :label)
+					     (crbit :u8const)))
+  (jcc (:$ub crbit) label))
+
+(define-x8664-vinsn (cbranch-false :branch) (()
+					     ((label :label)
+					      (crbit :u8const)))
+  (jcc (:$ub (:apply logxor 1 crbit)) label))
+
+
+(define-x8664-vinsn (lri :constant-ref) (((dest :imm))
+                                         ((intval :s64const))
+                                         ())
+  ((:pred = intval 0)
+   (xorl (:%l dest) (:%l dest)))
+  ((:and (:pred /= intval 0)
+         (:pred >= intval  -2147483648)
+         (:pred <= intval 2147483647))
+   (movq (:$l intval) (:%q dest)))
+  ((:or (:pred < intval  -2147483648)
+        (:pred > intval 2147483647))
+   (movq (:$q (:apply logand #xffffffffffffffff intval)) (:%q dest))))
+
+(define-x8664-vinsn (lriu :constant-ref) (((dest :imm))
+                                         ((intval :u64const))
+                                         ())
+  ((:pred = intval 0)
+   (xorl (:%l dest) (:%l dest)))
+  ((:and (:pred /= intval 0)
+         (:pred >= intval  -2147483648)
+         (:pred <= intval 2147483647))
+   (movq (:$l intval) (:%q dest)))
+  ((:or (:pred < intval  -2147483648)
+        (:pred > intval 2147483647))
+   (movq (:$q (:apply logand #xffffffffffffffff intval)) (:%q dest))))
+
+(define-x8664-vinsn trap-unless-bit (()
+                                     ((value :lisp)))
+  :resume
+  (testq (:$l (lognot x8664::fixnumone)) (:%q value))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q value) (:$ub arch::error-object-not-bit)))
+  )
+
+(define-x8664-vinsn trap-unless-list (()
+				      ((object :lisp))
+				      ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-list) (:%l tag))
+  (jne :bad)
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-list (:%q object))))
+
+
+
+(define-x8664-vinsn trap-unless-cons (()
+                                         ((object :lisp))
+                                         ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::fulltagmask) (:%l tag))
+  (cmpl (:$b x8664::fulltag-cons) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub x8664::fulltag-cons))))
+
+(define-x8664-vinsn set-z-flag-if-consp (()
+                                         ((object :lisp))
+                                         ((tag :u8)))
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::fulltagmask) (:%l tag))
+  (cmpl (:$b x8664::fulltag-cons) (:%l tag)))
+
+(define-x8664-vinsn trap-unless-uvector (()
+                                         ((object :lisp))
+                                         ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub x8664::tag-misc))))
+  
+(define-x8664-vinsn trap-unless-single-float (()
+                                              ((object :lisp)))
+  :resume
+  (cmpb (:$b x8664::tag-single-float) (:%b object))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub x8664::tag-single-float))))
+
+(define-x8664-vinsn trap-unless-character (()
+                                              ((object :lisp)))
+  :resume
+  (cmpb (:$b x8664::subtag-character) (:%b object))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub x8664::subtag-character))))
+
+(define-x8664-vinsn trap-unless-fixnum (()
+                                        ((object :lisp))
+                                        ())
+  :resume
+  (testb (:$b x8664::tagmask) (:%b object))
+  (jne :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-fixnum (:%q object))))
+
+(define-x8664-vinsn set-flags-from-lisptag (()
+                                            ((reg :lisp)))
+  (testb (:$b x8664::tagmask) (:%b reg)))
+                                            
+
+(define-x8664-vinsn trap-unless-typecode= (()
+					   ((object :lisp)
+					    (tagval :u16const))
+					   ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  ;; This needs to be a sign-extending mov, since the cmpl below
+  ;; will sign-extend the 8-bit constant operand.
+  (movsbl (:@ x8664::misc-subtag-offset (:%q object)) (:%l tag))
+  :have-tag
+  (cmpl (:$b tagval) (:%l tag))
+  (jne :bad)
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub tagval))))
+
+(define-x8664-vinsn trap-unless-double-float (()
+                                              ((object :lisp))
+                                              ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movsbl (:@ x8664::misc-subtag-offset (:%q object)) (:%l tag))
+  :have-tag
+  (cmpl (:$b x8664::subtag-double-float) (:%l tag))
+  (jne :bad)
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub x8664::subtag-double-float))))
+
+(define-x8664-vinsn trap-unless-macptr (()
+                                        ((object :lisp))
+                                        ((tag :u8)))
+  :resume
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8664::misc-subtag-offset (:%q object)) (:%l tag))
+  :have-tag
+  (cmpb (:$b x8664::subtag-macptr) (:%b tag))
+  (jne :bad)
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub x8664::subtag-macptr))))
+
+
+(define-x8664-vinsn check-misc-bound (()
+				      ((idx :imm)
+				       (v :lisp))
+				      ((temp :u64)))
+  :resume
+  (movq (:@ x8664::misc-header-offset (:%q v)) (:%q temp))
+  (shrq (:$ub x8664::num-subtag-bits) (:%q temp))
+  (shlq (:$ub x8664::fixnumshift) (:%q temp))
+  (rcmpq (:%q idx) (:%q temp))
+  (jae :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-vector-bounds (:%q idx) (:%q v))))
+
+
+
+(define-x8664-vinsn %cdr (((dest :lisp))
+			  ((src :lisp)))
+  (movq (:@ x8664::cons.cdr (:%q src)) (:%q dest)))
+
+(define-x8664-vinsn (%vpush-cdr :push :node :vsp)
+    (()
+     ((src :lisp)))
+  (pushq (:@ x8664::cons.cdr (:%q src))))
+
+(define-x8664-vinsn %car (((dest :lisp))
+			  ((src :lisp)))
+  (movq (:@ x8664::cons.car (:%q src)) (:%q dest)))
+
+(define-x8664-vinsn (%vpush-car :push :node :vsp)
+    (()
+     ((src :lisp)))
+  (pushq (:@ x8664::cons.car (:%q src))))
+
+
+(define-x8664-vinsn u32->char (((dest :lisp)
+                               (src :u8))
+			      ((src :u8))
+			      ())
+  (shll (:$ub x8664::charcode-shift) (:%l src))
+  (leaq  (:@ x8664::subtag-character (:%q src)) (:%q dest)))
+
+
+(define-x8664-vinsn (load-nil :constant-ref) (((dest t))
+					      ())
+  (movl (:$l (:apply target-nil-value)) (:%l dest)))
+
+
+(define-x8664-vinsn (load-t :constant-ref) (((dest t))
+					    ())
+  (movl(:$l (:apply target-t-value)) (:%l dest)))
+
+
+(define-x8664-vinsn extract-tag (((tag :u8))
+                                 ((object :lisp)))
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag)))
+
+(define-x8664-vinsn extract-tag-fixnum (((tag :imm))
+					((object :lisp)))
+  ((:pred =
+          (:apply %hard-regspec-value tag)
+          (:apply %hard-regspec-value object))
+   (shll (:$ub x8664::fixnumshift) (:%l object)))
+  ((:not (:pred =
+          (:apply %hard-regspec-value tag)
+          (:apply %hard-regspec-value object)))
+   (imull (:$b x8664::fixnumone) (:%l object) (:%l tag)))
+  (andl (:$b (ash x8664::tagmask x8664::fixnumshift)) (:%l tag)))
+
+(define-x8664-vinsn extract-fulltag (((tag :u8))
+                                 ((object :lisp)))
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::fulltagmask) (:%l tag)))
+
+(define-x8664-vinsn extract-fulltag-fixnum (((tag :imm))
+                                            ((object :lisp)))
+  ((:pred =
+          (:apply %hard-regspec-value tag)
+          (:apply %hard-regspec-value object))
+   (shll (:$ub x8664::fixnumshift) (:%l object)))
+  ((:not (:pred =
+          (:apply %hard-regspec-value tag)
+          (:apply %hard-regspec-value object)))
+   (imull (:$b x8664::fixnumone) (:%l object) (:%l tag)))
+  (andl (:$b (ash x8664::fulltagmask x8664::fixnumshift)) (:%l tag)))
+
+(define-x8664-vinsn extract-typecode (((tag :u32))
+                                      ((object :lisp)))
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8664::misc-subtag-offset (:%q object)) (:%l tag))
+  :have-tag)
+
+(define-x8664-vinsn extract-typecode-fixnum (((tag :imm))
+                                             ((object :lisp))
+                                             ((temp :u32)))
+  (movl (:%l object) (:%l temp))
+  (andl (:$b x8664::tagmask) (:%l temp))
+  (cmpl (:$b x8664::tag-misc) (:%l temp))
+  (jne :have-tag)
+  (movzbl (:@ x8664::misc-subtag-offset (:%q object)) (:%l temp))
+  :have-tag
+  (imulq (:$b x8664::fixnumone) (:%q temp) (:%q tag)))
+
+
+(define-x8664-vinsn compare-reg-to-zero (()
+                                         ((reg :imm)))
+  (testq (:%q reg) (:%q reg)))
+
+(define-x8664-vinsn compare-u8-reg-to-zero (()
+                                            ((reg :u8)))
+  (testb (:%b reg) (:%b reg)))
+
+(define-x8664-vinsn cr-bit->boolean (((dest :lisp))
+                                     ((crbit :u8const)))
+  (movl (:$l (:apply target-nil-value)) (:%l dest))
+  (cmovccl (:$ub crbit) (:@ (+ x8664::t-offset x8664::symbol.vcell) (:%l dest)) (:%l dest)))
+
+
+
+
+
+(define-x8664-vinsn compare-s32-constant (()
+                                            ((val :imm)
+                                             (const :s32const)))
+  ((:or  (:pred < const -128) (:pred > const 127))
+   (rcmpq (:%q val) (:$l const)))
+  ((:not (:or  (:pred < const -128) (:pred > const 127)))
+   (rcmpq (:%q val) (:$b const))))
+
+(define-x8664-vinsn compare-u31-constant (()
+                                          ((val :u64)
+                                           (const :u32const)))
+  ((:pred > const 127)
+   (rcmpq (:%q val) (:$l const)))
+  ((:not (:pred > const 127))
+   (rcmpq (:%q val) (:$b const))))
+
+(define-x8664-vinsn compare-u8-constant (()
+                                         ((val :u8)
+                                          (const :u8const)))
+  #|
+  ((:pred logbitp 7 const)
+   (movzbl (:%b val) (:%l val))
+   (rcmpw (:%w val) (:$w const)))
+  ((:not (:pred logbitp 7 const))
+   (rcmpb (:%b val) (:$b const)))
+  ||#
+  (rcmpb (:%b val) (:$b const))
+  )
+
+
+(define-x8664-vinsn cons (((dest :lisp))
+                          ((car :lisp)
+                           (cdr :lisp)))
+  (subq (:$b (- x8664::cons.size x8664::fulltag-cons)) (:rcontext x8664::tcr.save-allocptr))
+  (movq (:rcontext x8664::tcr.save-allocptr) (:%q x8664::allocptr))
+  (rcmpq (:%q x8664::allocptr) (:rcontext x8664::tcr.save-allocbase))
+  (:byte #x77) (:byte #x02) ;(ja :no-trap)
+  (uuo-alloc)
+  :no-trap
+  (andb (:$b (lognot x8664::fulltagmask)) (:rcontext x8664::tcr.save-allocptr))
+  (movq (:%q car) (:@ x8664::cons.car (:%q x8664::allocptr)))
+  (movq (:%q cdr) (:@ x8664::cons.cdr (:%q x8664::allocptr)))
+  (movq (:%q x8664::allocptr) (:%q dest)))
+
+(define-x8664-vinsn unbox-u8 (((dest :u8))
+			      ((src :lisp)))
+  :resume
+  (movq (:$l (lognot (ash #xff x8664::fixnumshift))) (:%q dest))
+  (andq (:% src) (:% dest))
+  (jne :bad)
+  (movq (:%q src) (:%q dest))
+  (shrq (:$ub x8664::fixnumshift) (:%q dest))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-unsigned-byte-8))))
+
+(define-x8664-vinsn %unbox-u8 (((dest :u8))
+			      ((src :lisp)))
+  (movl (:%l src) (:%l dest))
+  (shrl (:$ub x8664::fixnumshift) (:%l dest))
+  (movzbl (:%b dest) (:%l dest)))
+
+(define-x8664-vinsn unbox-s8 (((dest :s8))
+			      ((src :lisp)))
+  :resume
+  (movq (:%q src) (:%q dest))
+  (shlq (:$ub (- x8664::nbits-in-word (+ 8 x8664::fixnumshift))) (:%q dest))
+  (sarq (:$ub (- x8664::nbits-in-word (+ 8 x8664::fixnumshift))) (:%q dest))
+  (cmpq (:%q src) (:%q dest))
+  (jne :bad)
+  (testb (:$b x8664::fixnummask) (:%b dest))
+  (jne :bad)
+  (sarq (:$ub x8664::fixnumshift) (:%q dest))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-signed-byte-8))))
+
+(define-x8664-vinsn unbox-u16 (((dest :u16))
+			      ((src :lisp)))
+  :resume
+  (testq (:$l (lognot (ash #xffff x8664::fixnumshift))) (:% src))
+  (movq (:%q src) (:%q dest))
+  (jne :bad)
+  (shrq (:$ub x8664::fixnumshift) (:%q dest))
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-unsigned-byte-16))))
+
+(define-x8664-vinsn %unbox-u16 (((dest :u16))
+			      ((src :lisp)))
+  (movq (:%q src) (:%q dest))
+  (shrq (:$ub x8664::fixnumshift) (:%q dest)))
+
+(define-x8664-vinsn unbox-s16 (((dest :s16))
+			      ((src :lisp)))
+  :resume
+  (movq (:%q src) (:%q dest))
+  (shlq (:$ub (- x8664::nbits-in-word (+ 16 x8664::fixnumshift))) (:%q dest))
+  (sarq (:$ub (- x8664::nbits-in-word (+ 16 x8664::fixnumshift))) (:%q dest))
+  (cmpq (:%q src) (:%q dest))
+  (jne :bad)
+  (testb (:$b x8664::fixnummask) (:%b dest))
+  (jne :bad)
+  (sarq (:$ub x8664::fixnumshift) (:%q dest))
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-signed-byte-16))))
+
+(define-x8664-vinsn %unbox-s16 (((dest :s16))
+                                ((src :lisp)))
+  (movq (:%q src) (:%q dest))
+  (sarq (:$ub x8664::fixnumshift) (:%q dest)))
+
+(define-x8664-vinsn unbox-u32 (((dest :u32))
+			      ((src :lisp)))
+  :resume
+  (movq (:$q (lognot (ash #xffffffff x8664::fixnumshift))) (:%q dest))
+  (testq (:% src) (:% dest))
+  (jne :bad)
+  (movq (:%q src) (:%q dest))
+  (shrq (:$ub x8664::fixnumshift) (:%q dest))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-unsigned-byte-32))))
+
+(define-x8664-vinsn %unbox-u32 (((dest :u32))
+			      ((src :lisp)))
+
+  (movq (:%q src) (:%q dest))
+  (shrq (:$ub x8664::fixnumshift) (:%q dest)))
+
+(define-x8664-vinsn unbox-s32 (((dest :s32))
+                               ((src :lisp)))
+  :resume
+  (movq (:%q src) (:%q dest))
+  (shlq (:$ub (- x8664::nbits-in-word (+ 32 x8664::fixnumshift))) (:%q dest))
+  (sarq (:$ub (- x8664::nbits-in-word (+ 32 x8664::fixnumshift))) (:%q dest))
+  (cmpq (:%q src) (:%q dest))
+  (jne :bad)
+  (testb (:$b x8664::fixnummask) (:%b dest))
+  (jne :bad)
+  (sarq (:$ub x8664::fixnumshift) (:%q dest))
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-signed-byte-32))))
+
+(define-x8664-vinsn %unbox-s32 (((dest :s32))
+                               ((src :lisp)))
+  (movq (:%q src) (:%q dest))
+  (sarq (:$ub x8664::fixnumshift) (:%q dest)))
+
+
+(define-x8664-vinsn unbox-u64 (((dest :u64))
+                               ((src :lisp)))
+  :resume
+  (movq (:$q (lognot (ash x8664::target-most-positive-fixnum x8664::fixnumshift))) (:%q dest))
+  (testq (:%q dest) (:%q src))
+  (movq (:%q src) (:%q dest))
+  (jnz :maybe-bignum)
+  (sarq (:$ub x8664::fixnumshift) (:%q dest))
+  (jmp :done)
+  :maybe-bignum
+  (andl (:$b x8664::tagmask) (:%l dest))
+  (cmpl (:$b x8664::tag-misc) (:%l dest))
+  (jne :have-tag)
+  (movzbl (:@ x8664::misc-subtag-offset (:%q src)) (:%l dest))
+  :have-tag
+  (cmpl (:$b x8664::subtag-bignum) (:%l dest))
+  (jne :bad)
+  (movq (:@ x8664::misc-header-offset (:%q src)) (:%q dest))
+  (cmpq (:$l x8664::three-digit-bignum-header) (:%q dest))
+  (je :three)
+  (cmpq (:$l x8664::two-digit-bignum-header) (:%q dest))
+  (jne :bad)
+  (movq (:@ x8664::misc-data-offset (:%q src)) (:%q dest))
+  (testq (:%q dest) (:%q dest))
+  (js :bad)
+  (jmp :done)
+
+  :three
+  (movl (:@ (+ 8 x8664::misc-data-offset) (:%q src)) (:%l dest))
+  (testl (:%l dest) (:%l dest))
+  (movq (:@ x8664::misc-data-offset (:%q src)) (:%q dest))
+  (jne :bad)
+  :done
+  
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-unsigned-byte-64))))
+
+(define-x8664-vinsn unbox-s64 (((dest :s64))
+                               ((src :lisp)))
+  :resume
+  (movq (:%q src) (:%q dest))
+  (sarq (:$ub x8664::fixnumshift) (:%q dest))
+  ;; Was it a fixnum ?
+  (testb (:$b x8664::fixnummask) (:%b src))
+  (je :done)
+  ;; May be a 2-digit bignum
+  (movl (:%l src) (:%l dest))
+  (andl (:$b x8664::tagmask) (:%l dest))
+  (cmpl (:$b x8664::tag-misc) (:%l dest))
+  (jne :bad)
+  (cmpq (:$l x8664::two-digit-bignum-header) (:@ x8664::misc-header-offset (:%q src)))
+  (movq (:@ x8664::misc-data-offset (:%q src)) (:%q dest))
+  (jne :bad)
+  :done
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q src) (:$ub arch::error-object-not-signed-byte-64))))
+
+(define-x8664-vinsn sign-extend-s8 (((dest :s64))
+                                    ((src :s8)))
+  (movsbq (:%b src) (:%q dest)))
+
+(define-x8664-vinsn sign-extend-s16 (((dest :s64))
+                                     ((src :s16)))
+  (movswq (:%w src) (:%q dest)))
+
+(define-x8664-vinsn sign-extend-s32 (((dest :s64))
+                                     ((src :s32)))
+  (movslq (:%l src) (:%q dest)))
+
+
+(define-x8664-vinsn zero-extend-u8 (((dest :s64))
+                                    ((src :u8)))
+  (movzbl (:%b src) (:%l dest)))
+
+(define-x8664-vinsn zero-extend-u16 (((dest :s64))
+                                     ((src :u16)))
+  (movzwl (:%w src) (:%l dest)))
+
+(define-x8664-vinsn zero-extend-u32 (((dest :s64))
+                                     ((src :u32)))
+  (movl (:%l src) (:%l dest)))
+
+(define-x8664-vinsn (jump-subprim :jumpLR) (()
+					    ((spno :s32const)))
+  (jmp (:@ spno)))
+
+;;; "call" a subprimitive that manipulates the stack in some way,
+;;; using an lea/jmp calling convention.
+(define-x8664-vinsn (lea-jmp-subprim :call)  (()
+                                              ((spno :s32const))
+                                              ((entry (:label 1))))
+  (leaq (:@ (:^ :back) (:%q x8664::fn)) (:%q x8664::ra0))
+  (:talign 4)
+  (jmp (:@ spno))
+  :back
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+;;; Call a subprimitive using a tail-aligned CALL instruction.
+(define-x8664-vinsn (call-subprim :call)  (()
+                                           ((spno :s32const))
+                                           ((entry (:label 1))))
+  (:talign 4)
+  (call (:@ spno))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn fixnum-subtract-from (((dest t)
+                                           (y t))
+                                          ((y t)
+                                           (x t)))
+  (subq (:%q y) (:%q x)))
+
+(define-x8664-vinsn %logand-c (((dest t)
+                                (val t))
+                               ((val t)
+                                (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (andq (:$b const) (:%q val)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (andq (:$l const) (:%q val))))
+
+(define-x8664-vinsn %logior-c (((dest t)
+                                (val t))
+                               ((val t)
+                                (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (orq (:$b const) (:%q val)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (orq (:$l const) (:%q val))))
+
+(define-x8664-vinsn %logxor-c (((dest t)
+                                (val t))
+                               ((val t)
+                                (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (xorq (:$b const) (:%q val)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (xorq (:$l const) (:%q val))))
+
+(define-x8664-vinsn character->fixnum (((dest :lisp))
+				       ((src :lisp))
+				       ())
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movq (:%q src) (:%q dest)))
+  (shrq (:$ub (- x8664::charcode-shift x8664::fixnumshift)) (:%q dest)))
+
+(define-x8664-vinsn compare (()
+                             ((x t)
+                              (y t)))
+  (rcmpq (:%q x) (:%q y)))
+
+(define-x8664-vinsn negate-fixnum (((val :lisp))
+                                   ((val :imm)))
+  (negq (:% val)))
+
+(define-x8664-vinsn handle-fixnum-overflow-inline
+    (()
+     ((val :lisp)
+      (no-overflow :label))
+     ((header (:u64 #.x8664::imm0))
+      (scaled-size (:u64 #.x8664::imm1))
+      (freeptr (:lisp #.x8664::allocptr))))
+  (jo :overflow)
+  (:uuo-section)
+  :overflow
+  (movq (:%q val) (:%q scaled-size))
+  (btcq (:$ub 63) (:%q scaled-size))
+  (sarq (:$ub x8664::fixnumshift) (:%q scaled-size))
+  (btcq (:$ub 60) (:%q scaled-size))
+  (movd (:%q scaled-size) (:%mmx x8664::mm0))
+  (movq (:$l x8664::two-digit-bignum-header) (:%q header))
+  (movq (:$l (- 16 x8664::fulltag-misc)) (:%q scaled-size))
+  (subq (:%q scaled-size) (:rcontext x8664::tcr.save-allocptr))
+  (movq (:rcontext x8664::tcr.save-allocptr) (:%q freeptr))
+  (rcmpq (:%q freeptr) (:rcontext x8664::tcr.save-allocbase))
+  (:byte #x77) (:byte #x02)             ;(ja :no-trap)
+  (uuo-alloc)
+  :no-trap
+  (movq (:%q header) (:@ x8664::misc-header-offset (:%q freeptr)))
+  (andb (:$b (lognot x8664::fulltagmask)) (:rcontext x8664::tcr.save-allocptr))
+  ((:not (:pred = freeptr
+                (:apply %hard-regspec-value val)))
+   (movq (:%q freeptr) (:%q val)))
+  (movq (:%mmx x8664::mm0) (:@ x8664::misc-data-offset (:%q val)))
+  (jmp no-overflow))
+
+    
+;;; This handles the 1-bit overflow from addition/subtraction/unary negation
+(define-x8664-vinsn set-bigits-and-header-for-fixnum-overflow
+    (()
+     ((val :lisp)
+      (no-overflow
+       :label))
+     ((header (:u64 #.x8664::imm0))
+      (scaled-size (:u64 #.x8664::imm1))))
+  (jno no-overflow)
+  (movq (:%q val) (:%q scaled-size))
+  (sarq (:$ub x8664::fixnumshift) (:%q scaled-size))
+  (movq (:$q #xe000000000000000) (:%q header))
+  (xorq (:%q header) (:%q scaled-size))
+  (movd (:%q scaled-size) (:%mmx x8664::mm0))
+  (movq (:$l x8664::two-digit-bignum-header) (:%q header))
+  (movq (:$l (- 16 x8664::fulltag-misc)) (:%q scaled-size)))
+
+(define-x8664-vinsn %set-z-flag-if-s64-fits-in-fixnum (((dest :imm))
+                                                       ((src :s64))
+                                                       ((temp :s64)))
+  (movq (:%q src) (:%q temp))
+  (shlq (:$ub x8664::fixnumshift) (:%q temp))
+  (movq (:%q temp) (:%q dest))          ; tagged as a fixnum
+  (sarq (:$ub x8664::fixnumshift) (:%q temp))
+  (cmpq (:%q src) (:%q temp)))
+
+(define-x8664-vinsn %set-z-flag-if-u64-fits-in-fixnum (((dest :imm))
+                                                       ((src :u64))
+                                                       ((temp :u64)))
+  (movq (:%q src) (:%q temp))
+  (shlq (:$ub (1+ x8664::fixnumshift)) (:%q temp))
+  (movq (:%q temp) (:%q dest))          ; tagged as an even fixnum
+  (shrq (:$ub (1+ x8664::fixnumshift)) (:%q temp))
+  (shrq (:%q dest))
+  (cmpq (:%q src) (:%q temp))
+  :done)
+
+
+(define-x8664-vinsn setup-bignum-alloc-for-s64-overflow (()
+                                                         ((src :s64)))
+  (movd (:%q src) (:%mmx x8664::mm0))
+  (movl (:$l x8664::two-digit-bignum-header) (:%l x8664::imm0.l))
+  (movl (:$l (- 16 x8664::fulltag-misc)) (:%l x8664::imm1.l)))
+
+
+;;; If the sign bit is set in SRC, need to make a 3-digit bignum
+;;; that requires 32 bytes of aligned memory
+(define-x8664-vinsn setup-bignum-alloc-for-u64-overflow (()
+                                                         ((src :s64)))
+  (testq (:%q src) (:%q src))
+  (movd (:%q src) (:%mmx x8664::mm0))
+  (movl (:$l x8664::two-digit-bignum-header) (:%l x8664::imm0.l))
+  (movl (:$l (- 16 x8664::fulltag-misc)) (:%l x8664::imm1.l))
+  (jns :done)
+  (movl (:$l x8664::three-digit-bignum-header) (:%l x8664::imm0.l))
+  (movl (:$l (- 32 x8664::fulltag-misc)) (:%l x8664::imm1.l))
+  :done)
+  
+  
+
+(define-x8664-vinsn %allocate-uvector (((dest :lisp))
+                                       ()
+                                       ((header (:u64 #.x8664::imm0))
+                                        (freeptr (:lisp #.x8664::allocptr))))
+  (subq (:%q x8664::imm1) (:rcontext x8664::tcr.save-allocptr))
+  (movq (:rcontext x8664::tcr.save-allocptr) (:%q freeptr))
+  (rcmpq (:%q freeptr) (:rcontext x8664::tcr.save-allocbase))
+  (:byte #x77) (:byte #x02) ;(ja :no-trap)
+  (uuo-alloc)
+  :no-trap
+  (movq (:%q header) (:@ x8664::misc-header-offset (:%q freeptr)))
+  (andb (:$b (lognot x8664::fulltagmask)) (:rcontext x8664::tcr.save-allocptr))
+  ((:not (:pred = freeptr
+                (:apply %hard-regspec-value dest)))
+   (movq (:%q freeptr) (:%q dest))))
+
+(define-x8664-vinsn set-bigits-after-fixnum-overflow (()
+                                                      ((bignum :lisp)))
+  (movq (:%mmx x8664::mm0) (:@ x8664::misc-data-offset (:%q bignum))))
+  
+                                                       
+(define-x8664-vinsn box-fixnum (((dest :imm))
+                                ((src :s8)))
+  (imulq (:$b x8664::fixnumone) (:%q src)(:%q dest)))
+
+
+(define-x8664-vinsn (fix-fixnum-overflow-ool :call)
+    (((val :lisp))
+     ((val :lisp))
+     ((unboxed (:s64 #.x8664::imm1))
+      (header (:u64 #.x8664::imm0))
+      (entry (:label 1))))
+  (jo :overflow)
+  :done
+  (:uuo-section)
+  ((:not (:pred = x8664::arg_z
+                (:apply %hard-regspec-value val)))
+   :overflow
+   (movq (:%q val) (:%q x8664::arg_z)))
+  (:talign 4)
+  ((:pred = x8664::arg_z
+          (:apply %hard-regspec-value val))
+   :overflow)
+  (call (:@ .SPfix-overflow))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn))
+  ((:not (:pred = x8664::arg_z
+                (:apply %hard-regspec-value val)))
+   (movq (:%q x8664::arg_z) (:%q val)))
+  (jmp :done))
+
+(define-x8664-vinsn (fix-fixnum-overflow-ool-and-branch :call)
+    (((val :lisp))
+     ((val :lisp)
+      (lab :label))
+     ((unboxed (:s64 #.x8664::imm1))
+      (header (:u64 #.x8664::imm0))
+      (entry (:label 1))))
+  (jo :overflow)
+  (jmp lab)
+  (:uuo-section)
+  ((:not (:pred = x8664::arg_z
+                (:apply %hard-regspec-value val)))
+     :overflow
+   (movq (:%q val) (:%q x8664::arg_z)))
+  (:talign 4)
+  ((:pred = x8664::arg_z
+          (:apply %hard-regspec-value val))
+   :overflow)
+  (call (:@ .SPfix-overflow))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn))
+  ((:not (:pred = x8664::arg_z
+                (:apply %hard-regspec-value val)))
+   (movq (:%q x8664::arg_z) (:%q val)))
+  (jmp lab))
+
+(define-x8664-vinsn add-constant (((dest :imm))
+                                  ((dest :imm)
+                                   (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (addq (:$b const) (:%q dest)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (addq (:$l const) (:%q dest))))
+
+(define-x8664-vinsn add-constant3 (((dest :imm))
+                                   ((src :imm)
+                                    (const :s32const)))
+  ((:pred = (:apply %hard-regspec-value dest)
+          (:apply %hard-regspec-value src))
+   ((:and (:pred >= const -128) (:pred <= const 127))
+    (addq (:$b const) (:%q dest)))
+   ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+    (addq (:$l const) (:%q dest))))
+  ((:not (:pred = (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (leaq (:@ const (:%q src)) (:%q dest))))
+
+  
+
+(define-x8664-vinsn fixnum-add2  (((dest :imm))
+                                  ((dest :imm)
+                                   (other :imm)))
+  (addq (:%q other) (:%q dest)))
+
+(define-x8664-vinsn fixnum-sub2  (((dest :imm))
+                                  ((x :imm)
+                                   (y :imm))
+                                  ((temp :imm)))
+  (movq (:%q x) (:%q temp))
+  (subq (:%q y) (:%q temp))
+  (movq (:%q temp) (:%q dest)))
+
+
+
+(define-x8664-vinsn fixnum-add3 (((dest :imm))
+                                 ((x :imm)
+                                  (y :imm)))
+  
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (addq (:%q y) (:%q dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (addq (:%q x) (:%q dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (leaq (:@ (:%q x) (:%q y)) (:%q dest)))))
+   
+(define-x8664-vinsn copy-gpr (((dest t))
+			      ((src t)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movq (:%q src) (:%q dest))))
+
+(define-x8664-vinsn (vpop-register :pop :node :vsp)
+    (((dest :lisp))
+     ())
+  (popq (:%q dest)))
+
+                                           
+(define-x8664-vinsn (push-argregs :push :node :vsp) (()
+                                                      ())
+  (testl (:%l x8664::nargs) (:%l x8664::nargs))
+  (jz :done)
+  (rcmpl (:%l x8664::nargs) (:$b (* 2 x8664::node-size)))
+  (jb :one)
+  (je :two)
+  (pushq (:%q x8664::arg_x))
+  :two
+  (pushq (:%q x8664::arg_y))
+  :one
+  (pushq (:%q x8664::arg_z))
+  :done)
+
+(define-x8664-vinsn (push-max-argregs :push :node :vsp) (()
+                                                         ((max :u32const)))
+  ((:pred >= max 3)
+   (testl (:%l x8664::nargs) (:%l x8664::nargs))
+   (jz :done)
+   (rcmpl (:%l x8664::nargs) (:$b (* 2 x8664::node-size)))
+   (jb :one)
+   (je :two)
+   (pushq (:%q x8664::arg_x))
+   :two
+   (pushq (:%q x8664::arg_y))
+   :one
+   (pushq (:%q x8664::arg_z))
+   :done)
+  ((:pred = max 2)
+   (rcmpl (:%l x8664::nargs) (:$b (* 1 x8664::node-size)))
+   (jb :done)
+   (je :one)
+   (pushq (:%q x8664::arg_y))
+   :one
+   (pushq (:%q x8664::arg_z))
+   :done)
+  ((:pred = max 1)
+   (testl (:%l x8664::nargs) (:%l x8664::nargs))
+   (je :done)
+   (pushq (:%q x8664::arg_z))
+   :done))
+
+(define-x8664-vinsn (call-label :call) (()
+					((label :label))
+                                        ((entry (:label 1))))
+  (:talign 4)
+  (call label)
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn double-float-compare (()
+					  ((arg0 :double-float)
+					   (arg1 :double-float)))
+  (comisd (:%xmm arg1) (:%xmm arg0)))
+
+(define-x8664-vinsn single-float-compare (()
+					  ((arg0 :single-float)
+					   (arg1 :single-float)))
+  (comiss (:%xmm arg1) (:%xmm arg0)))
+              
+
+(define-x8664-vinsn double-float+-2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float)))
+  ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (addsd (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (addsd (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movsd (:%xmm x) (:%xmm result))
+   (addsd (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8664-vinsn double-float--2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movsd (:%xmm x) (:%xmm result)))
+  (subsd (:%xmm y) (:%xmm result)))
+
+(define-x8664-vinsn double-float*-2 (((result :double-float))
+				     ((x :double-float)
+                                      (y :double-float)))
+  ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (mulsd (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (mulsd (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movsd (:%xmm x) (:%xmm result))
+   (mulsd (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8664-vinsn double-float/-2 (((result :double-float))
+				     ((x :double-float)
+				      (y :double-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movsd (:%xmm x) (:%xmm result)))
+  (divsd (:%xmm y) (:%xmm result)))
+
+(define-x8664-vinsn single-float+-2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float)))
+  ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (addss (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (addss (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movss (:%xmm x) (:%xmm result))
+   (addss (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8664-vinsn single-float--2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movss (:%xmm x) (:%xmm result)))
+  (subss (:%xmm y) (:%xmm result)))
+
+(define-x8664-vinsn single-float*-2 (((result :single-float))
+				     ((x :single-float)
+                                      (y :single-float)))
+    ((:pred =
+          (:apply %hard-regspec-value result)
+          (:apply %hard-regspec-value x))
+   (mulss (:%xmm y) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:pred =
+                (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value y)))
+   (mulss (:%xmm x) (:%xmm result)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value x)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value result)
+                      (:apply %hard-regspec-value y))))
+   (movss (:%xmm x) (:%xmm result))
+   (mulss (:%xmm y) (:%xmm result))))
+
+;;; Caller guarantees (not (eq y result))
+(define-x8664-vinsn single-float/-2 (((result :single-float))
+				     ((x :single-float)
+				      (y :single-float)))
+  ((:not (:pred = (:apply %hard-regspec-value result)
+                (:apply %hard-regspec-value x)))
+   (movss (:%xmm x) (:%xmm result)))
+  (divss (:%xmm y) (:%xmm result)))
+
+(define-x8664-vinsn get-single (((result :single-float))
+                                ((source :lisp)))
+  (movd (:%q source) (:%xmm result))
+  (psrlq (:$ub 32) (:%xmm result)))
+
+(define-x8664-vinsn get-double (((result :double-float))
+                                ((source :lisp)))
+  (movsd (:@  x8664::double-float.value (:%q source)) (:%xmm result)))
+
+;;; Extract a double-float value, typechecking in the process.
+;;; IWBNI we could simply call the "trap-unless-typecode=" vinsn here,
+;;; instead of replicating it ..
+
+(define-x8664-vinsn get-double? (((target :double-float))
+				 ((source :lisp))
+				 ((tag :u8)))
+  :resume
+  (movl (:%l source) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movsbl (:@ x8664::misc-subtag-offset (:%q source)) (:%l tag))
+  :have-tag
+  (cmpl (:$b x8664::subtag-double-float) (:%l tag))
+  (jne :bad)
+  (movsd (:@  x8664::double-float.value (:%q source)) (:%xmm target))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q source) (:$ub x8664::subtag-double-float))))
+
+(define-x8664-vinsn single->node (((result :lisp)
+                                   (source :single-float))
+                                  ((source :single-float)))
+  (psllq (:$ub 32) (:%xmm source))
+  (movd (:%xmm source) (:%q result))
+  (movb (:$b x8664::tag-single-float) (:%b result)))
+
+(define-x8664-vinsn copy-double-float (((dest :double-float))
+                                       ((src :double-float)))
+  (movsd (:%xmm src) (:%xmm dest)))
+
+(define-x8664-vinsn copy-single-float (((dest :single-float))
+                                       ((src :single-float)))
+  (movss (:%xmm src) (:%xmm dest)))
+
+
+(define-x8664-vinsn copy-single-to-double (((dest :double-float))
+                                           ((src :single-float)))
+  (cvtss2sd (:%xmm src) (:%xmm dest)))
+
+(define-x8664-vinsn copy-double-to-single (((dest :single-float))
+                                           ((src :double-float)))
+  (cvtsd2ss (:%xmm src) (:%xmm dest)))
+
+(define-x8664-vinsn u8->fixnum (((result :imm)) 
+				((val :u8)) 
+				())
+  (leaq (:@ (:%q val) 8) (:%q result)))
+
+(define-x8664-vinsn fitvals (()
+                             ((n :u16const))
+                             ((imm :u16)))
+  ((:pred = n 0)
+   (xorl (:%l imm) (:%l imm)))
+  ((:not (:pred = n 0))
+   (movl (:$l (:apply ash n x8664::fixnumshift)) (:%l imm)))
+  (subl (:%l x8664::nargs) (:%l imm))
+  (jae :push-more)
+  (movslq (:%l imm) (:%q imm))
+  (subq (:%q imm) (:%q x8664::rsp))
+  (jmp :done)
+  :push-loop
+  (pushq (:$l (:apply target-nil-value)))
+  (addl (:$b x8664::node-size) (:%l x8664::nargs))
+  (subl (:$b x8664::node-size) (:%l imm))
+  :push-more
+  (jne :push-loop)
+  :done)
+  
+(define-x8664-vinsn (nvalret :jumpLR) (()
+                                       ())
+  
+  (jmp (:@ .SPnvalret)))
+
+
+(define-x8664-vinsn lisp-word-ref (((dest t))
+				   ((base t)
+				    (offset t)))
+  (movq (:@ (:%q base) (:%q offset)) (:%q  dest)))
+
+
+(define-x8664-vinsn lisp-word-ref-c (((dest t))
+				     ((base t)
+				      (offset :s32const)))
+  ((:pred = offset 0)
+   (movq (:@ (:%q base)) (:%q dest)))
+  ((:not (:pred = offset 0))
+   (movq (:@ offset (:%q base)) (:%q dest))))
+
+
+(define-x8664-vinsn (vpush-label :push :node :vsp) (()
+                                                 ((label :label)))
+  (leaq (:@ (:^ label) (:%q x8664::fn)) (:%q x8664::ra0))
+  (pushq (:%q x8664::ra0)))
+
+;; ????
+(define-x8664-vinsn emit-aligned-label (()
+                                        ((label :label)))
+  (:align 3)
+  (:long (:^ label)))
+
+;;; %ra0 is pointing into %fn, so no need to copy %fn here.
+(define-x8664-vinsn pass-multiple-values-symbol (()
+                                                 ())
+  (pushq (:@ (:apply + (:apply target-nil-value) (x8664::%kernel-global 'x86::ret1valaddr)))) 
+  (jmp (:@ x8664::symbol.fcell (:% x8664::fname))))
+
+;;; It'd be good to have a variant that deals with a known function
+;;; as well as this. 
+(define-x8664-vinsn pass-multiple-values (()
+                                          ()
+                                          ((tag :u8)))
+  :resume
+  (movl (:%l x8664::temp0) (:%l tag))
+  (andl (:$b x8664::fulltagmask) (:%l tag))
+  (cmpl (:$b x8664::fulltag-symbol) (:%l tag))
+  (cmovgq (:%q x8664::temp0) (:%q x8664::fn))
+  (jl :bad)
+  (cmoveq (:@ x8664::symbol.fcell (:%q x8664::fname)) (:%q x8664::fn))
+  (pushq (:@ (:apply + (:apply target-nil-value) (x8664::%kernel-global 'x86::ret1valaddr))))
+  (jmp (:%q x8664::fn))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-not-callable)))
+
+
+
+(define-x8664-vinsn reserve-outgoing-frame (()
+                                            ())
+  (pushq (:$b x8664::reserved-frame-marker))
+  (pushq (:$b x8664::reserved-frame-marker)))
+
+
+(define-x8664-vinsn (call-known-function :call) (()
+						 ()
+                                                 ((entry (:label 1))))
+  (:talign 4)
+  (call (:%q x8664::temp0))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn (jump-known-function :jumplr) (()
+                                                   ())
+  (movq (:%q x8664::fn) (:%q x8664::xfn))
+  (movq (:%q x8664::temp0)  (:%q x8664::fn))
+  (jmp (:%q x8664::fn)))
+
+(define-x8664-vinsn (list :call) (()
+                                  ()
+                                  ((entry (:label 1))))
+  (leaq (:@ (:^ :back) (:%q x8664::fn)) (:%q x8664::ra0))
+  (:talign 4)
+  (jmp (:@ .SPconslist))
+  :back
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+
+(define-x8664-vinsn make-tsp-cons (((dest :lisp))
+				   ((car :lisp) (cdr :lisp))
+				   ((temp :imm)))
+  (subq (:$b (+ x8664::cons.size x8664::dnode-size)) (:rcontext x8664::tcr.next-tsp))
+  (movq (:rcontext x8664::tcr.next-tsp) (:%q temp))
+  (movapd (:%xmm x8664::fpzero) (:@ (:%q temp)))
+  (movapd (:%xmm x8664::fpzero) (:@ 16 (:%q temp)))
+  (movq (:rcontext x8664::tcr.save-tsp) (:%mmx x8664::stack-temp))
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q temp)))
+  (movq (:% x8664::rbp) (:@ x8664::tsp-frame.rbp (:%q temp)))
+  (movq (:%q temp) (:rcontext x8664::tcr.save-tsp))
+  (leaq (:@ (+ x8664::dnode-size x8664::fulltag-cons) (:%q temp)) (:%q temp))
+  (movq (:%q car) (:@ x8664::cons.car (:%q temp)))
+  (movq (:%q cdr) (:@ x8664::cons.cdr (:%q temp)))
+  (movq (:%q temp) (:%q dest)))
+
+(define-x8664-vinsn make-fixed-stack-gvector (((dest :lisp))
+                                              ((aligned-size :u32const)
+                                               (header :s32const))
+                                              ((tempa :imm)
+                                               (tempb :imm)))
+  ((:and (:pred >= (:apply + aligned-size x8664::dnode-size) -128)
+         (:pred <= (:apply + aligned-size x8664::dnode-size) 127))
+   (subq (:$b (:apply + aligned-size x8664::dnode-size))
+         (:rcontext x8664::tcr.next-tsp)))
+  ((:not (:and (:pred >= (:apply + aligned-size x8664::dnode-size) -128)
+               (:pred <= (:apply + aligned-size x8664::dnode-size) 127)))
+   (subq (:$l (:apply + aligned-size x8664::dnode-size))
+         (:rcontext x8664::tcr.next-tsp)))
+  (movq (:rcontext x8664::tcr.save-tsp) (:%q tempb))
+  (movq (:rcontext x8664::tcr.next-tsp) (:%q tempa))
+  (movd (:%q tempb) (:%mmx x8664::stack-temp))
+  :loop
+  (movapd (:%xmm x8664::fpzero) (:@ -16 (:%q tempb)))
+  (subq (:$b x8664::dnode-size) (:%q tempb))
+  (cmpq (:%q tempa) (:%q tempb))
+  (jnz :loop)
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q tempa)))
+  (movq (:% x8664::rbp) (:@ x8664::tsp-frame.rbp (:%q tempa)))
+  (movq (:%q tempa) (:rcontext x8664::tcr.save-tsp))
+  (movl (:$l header) (:@ x8664::dnode-size (:%q tempa)))
+  (leaq (:@ (+ x8664::dnode-size x8664::fulltag-misc) (:%q tempa)) (:%q dest)))
+
+
+(define-x8664-vinsn (discard-temp-frame :tsp :pop :discard) (()
+					()
+                                        ((temp :imm)))
+  (movq (:rcontext x8664::tcr.save-tsp) (:%q temp))
+  (movq (:@ (:%q temp)) (:%q temp))
+  (movq (:%q temp) (:rcontext x8664::tcr.save-tsp))
+  (movq (:%q temp) (:rcontext x8664::tcr.next-tsp))
+  )
+
+(define-x8664-vinsn (discard-c-frame :csp :pop :discard) (()
+                                     ()
+                                     ((temp :imm)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q temp))
+  (movq (:@ (:%q temp)) (:%q temp))
+  (movq (:%q temp) (:rcontext x8664::tcr.foreign-sp)))
+
+  
+(define-x8664-vinsn (vstack-discard :vsp :pop :discard) (()
+				    ((nwords :u32const)))
+  ((:not (:pred = nwords 0))
+   ((:pred < nwords 16)
+    (addq (:$b (:apply ash nwords x8664::word-shift)) (:%q x8664::rsp)))
+   ((:not (:pred < nwords 16))
+    (addq (:$l (:apply ash nwords x8664::word-shift)) (:%q x8664::rsp)))))
+
+
+(defmacro define-x8664-subprim-lea-jmp-vinsn ((name &rest other-attrs) spno)
+  `(define-x8664-vinsn (,name :call :subprim-call ,@other-attrs) (() () ((entry (:label 1))))
+    (leaq (:@ (:^ :back) (:%q x8664::fn)) (:%q x8664::ra0))
+    (:talign 4)
+    (jmp (:@ ,spno))
+    :back
+    (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn))))
+
+(defmacro define-x8664-subprim-call-vinsn ((name &rest other-attrs) spno)
+  `(define-x8664-vinsn (,name :call :subprim-call ,@other-attrs) (() () ((entry (:label 1))))
+    (:talign 4)
+    (call (:@ ,spno))
+    :back
+    (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn))))
+
+(defmacro define-x8664-subprim-jump-vinsn ((name &rest other-attrs) spno)
+  `(define-x8664-vinsn (,name :jumpLR ,@other-attrs) (() ())
+    (jmp (:@ ,spno))))
+
+(define-x8664-vinsn (nthrowvalues :call :subprim-call) (()
+                                                        ((lab :label)))
+  (leaq (:@ (:^ lab) (:%q x8664::fn)) (:%q x8664::ra0))
+  (jmp (:@ .SPnthrowvalues)))
+
+(define-x8664-vinsn (nthrow1value :call :subprim-call) (()
+                                                        ((lab :label)))
+  (leaq (:@ (:^ lab) (:%q x8664::fn)) (:%q x8664::ra0))
+  (jmp (:@ .SPnthrow1value)))
+
+
+(define-x8664-subprim-lea-jmp-vinsn (bind-interrupt-level-0) .SPbind-interrupt-level-0)
+
+(define-x8664-vinsn bind-interrupt-level-0-inline (()
+                                                   ()
+                                                   ((temp :imm)))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (:%q temp))
+  (cmpq (:$b 0) (:@ x8664::interrupt-level-binding-index (:%q temp)))
+  (pushq (:@ x8664::interrupt-level-binding-index (:%q temp)))
+  (pushq (:$b x8664::interrupt-level-binding-index))
+  (pushq (:rcontext x8664::tcr.db-link))
+  (movq (:$l 0) (:@ x8664::interrupt-level-binding-index (:%q temp)))
+  (movq (:%q x8664::rsp) (:rcontext x8664::tcr.db-link))
+  (jns :done)
+  (btrq (:$ub 63) (:rcontext x8664::tcr.interrupt-pending))
+  (jae :done)
+  (ud2a)
+  (:byte 2)
+  :done)
+  
+  
+
+(define-x8664-subprim-lea-jmp-vinsn (bind-interrupt-level-m1) .SPbind-interrupt-level-m1)
+
+(define-x8664-vinsn bind-interrupt-level-m1-inline (()
+                                                   ()
+                                                   ((temp :imm)))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (:%q temp))
+  (pushq (:@ x8664::interrupt-level-binding-index (:%q temp)))
+  (pushq (:$b x8664::interrupt-level-binding-index))
+  (pushq (:rcontext x8664::tcr.db-link))
+  (movq (:$l (ash -1 x8664::fixnumshift)) (:@ x8664::interrupt-level-binding-index (:%q temp)))
+  (movq (:%q x8664::rsp) (:rcontext x8664::tcr.db-link)))
+
+(define-x8664-subprim-lea-jmp-vinsn (bind-interrupt-level) .SPbind-interrupt-level)
+
+(define-x8664-subprim-call-vinsn (unbind-interrupt-level) .SPunbind-interrupt-level)
+
+(define-x8664-vinsn unbind-interrupt-level-inline (()
+                                                   ()
+                                                   ((link :imm)
+                                                    (curval :imm)
+                                                    (oldval :imm)
+                                                    (tlb :imm)))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (:%q tlb))
+  (movq (:rcontext x8664::tcr.db-link) (:%q link))
+  (movq (:@ x8664::interrupt-level-binding-index (:%q tlb)) (:%q curval))
+  (testq (:%q curval) (:%q curval))
+  (movq (:@ 16 #|binding.val|# (:%q link)) (:%q oldval))
+  (movq (:@ #|binding.link|# (:%q link)) (:%q link))
+  (movq (:%q oldval) (:@ x8664::interrupt-level-binding-index (:%q tlb)))
+  (movq (:%q link) (:rcontext x8664::tcr.db-link))
+  (jns :done)
+  (testq (:%q oldval) (:%q oldval))
+  (js :done)
+  (btrq (:$ub 63) (:rcontext x8664::tcr.interrupt-pending))
+  (jae :done)
+  (ud2a)
+  (:byte 2)
+  :done)  
+
+(define-x8664-vinsn (jump-return-pc :jumpLR)
+    (()
+     ())
+  (ret))
+
+(define-x8664-vinsn (nmkcatchmv :call :subprim-call) (()
+                                                     ((lab :label))
+                                                     ((entry (:label 1))))
+  (leaq (:@ (:^ lab)  (:%q x8664::fn)) (:%q x8664::xfn))
+  (:talign 4)
+  (call (:@ .SPmkcatchmv))
+  :back
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn (nmkcatch1v :call :subprim-call) (()
+                                                     ((lab :label))
+                                                     ((entry (:label 1))))
+  (leaq (:@ (:^ lab)  (:%q x8664::fn)) (:%q x8664::xfn))
+  (:talign 4)
+  (call (:@ .SPmkcatch1v))
+  :back
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+
+(define-x8664-vinsn (make-simple-unwind :call :subprim-call) (()
+                                                     ((protform-lab :label)
+                                                      (cleanup-lab :label)))
+  (leaq (:@ (:^ protform-lab) (:%q x8664::fn)) (:%q x8664::ra0))
+  (leaq (:@ (:^ cleanup-lab)  (:%q x8664::fn)) (:%q x8664::xfn))
+  (jmp (:@ .SPmkunwind)))
+
+(define-x8664-vinsn (nmkunwind :call :subprim-call) (()
+                                                     ((protform-lab :label)
+                                                      (cleanup-lab :label)))
+  (leaq (:@ (:^ protform-lab) (:%q x8664::fn)) (:%q x8664::ra0))
+  (leaq (:@ (:^ cleanup-lab)  (:%q x8664::fn)) (:%q x8664::xfn))
+  (jmp (:@ .SPnmkunwind)))
+
+;;; "old" mkunwind.  Used by PROGV, since the binding of *interrupt-level*
+;;; on entry to the new mkunwind confuses the issue.
+
+(define-x8664-vinsn (mkunwind :call :subprim-call) (()
+                                                     ((protform-lab :label)
+                                                      (cleanup-lab :label)))
+  (leaq (:@ (:^ protform-lab) (:%q x8664::fn)) (:%q x8664::ra0))
+  (leaq (:@ (:^ cleanup-lab)  (:%q x8664::fn)) (:%q x8664::xfn))
+  (jmp (:@ .SPmkunwind)))
+
+(define-x8664-subprim-lea-jmp-vinsn (gvector) .SPgvector)
+
+(define-x8664-subprim-call-vinsn (getu64) .SPgetu64)
+
+;;; Call something callable and obtain the single value that it
+;;; returns.
+(define-x8664-vinsn funcall (()
+                             ()
+                             ((tag :u8)
+                              (entry (:label 1))))
+  :resume
+  (movl (:%l x8664::temp0) (:%l tag))
+  (andl (:$b x8664::fulltagmask) (:%l tag))
+  (cmpl (:$b x8664::fulltag-symbol) (:%l tag))
+  (cmovgq (:%q x8664::temp0) (:%q x8664::xfn))
+  (jl :bad)
+  (cmoveq (:@ x8664::symbol.fcell (:%q x8664::fname)) (:%q x8664::xfn))
+  (:talign 4)
+  (call (:%q x8664::xfn))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn))
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-not-callable)))
+
+(define-x8664-vinsn tail-funcall (()
+                                  ()
+                                  ((tag (:u8 #.x8664::imm0))))
+  :resume
+  (movl (:%l x8664::temp0) (:%l tag))
+  (andl (:$b x8664::fulltagmask) (:%l tag))
+  (cmpl (:$b x8664::fulltag-symbol) (:%l tag))
+  (cmovgq (:%q x8664::temp0) (:%q x8664::xfn))
+  (jl :bad)
+  (cmoveq (:@ x8664::symbol.fcell (:%q x8664::fname)) (:%q x8664::xfn))
+  (jmp (:%q x8664::xfn))
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-not-callable)))
+                             
+
+
+;;; Magic numbers in here include the address of .SPcall-closure.
+(define-x8664-vinsn init-nclosure (()
+                                   ((closure :lisp))
+                                   ((imm0 :u64)))
+  (movq (:$q #x24fffffffff92d8d) (:%q imm0))
+  (movb (:$b 4) (:@ x8664::misc-data-offset (:%q closure))) ; code word count
+  (movb (:$b #x4c) (:@ (+ x8664::misc-data-offset 7) (:%q closure))) ; 1st byte of lea
+  (movq (:%q imm0) (:@ (+ x8664::misc-data-offset 8) (:%q closure))) ; rest of lea, start of jmp
+  (movl (:$l #x01516825) (:@ (+ x8664::misc-data-offset 16) (:%q closure)))
+  (movb (:$b x8664::function-boundary-marker) (:@ (+ x8664::misc-data-offset 24)  (:%q closure))))
+
+
+(define-x8664-vinsn finalize-closure (((closure :lisp))
+                                      ((closure :lisp)))
+  (addq (:$b (- x8664::fulltag-function x8664::fulltag-misc)) (:%q closure)))
+
+
+(define-x8664-vinsn (ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val))))
+     ((entry (:label 1))))
+  (:talign 4)
+  (call (:@ .SPspecrefcheck))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)) )
+
+(define-x8664-vinsn ref-symbol-value-inline (((dest :lisp))
+                                              ((src (:lisp (:ne dest))))
+                                              ((table :imm)
+                                               (idx :imm)))
+  :resume
+  (movq (:@ x8664::symbol.binding-index (:%q src)) (:%q idx))
+  (rcmpq (:%q idx) (:rcontext x8664::tcr.tlb-limit))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (:%q table))
+  (jae :symbol)
+  (movq (:@ (:%q table) (:%q idx)) (:%q dest))
+  (cmpl (:$b x8664::subtag-no-thread-local-binding) (:%l dest))
+  (jne :test)
+  :symbol
+  (movq (:@ x8664::symbol.vcell (:%q src)) (:%q dest))
+  :test
+  (cmpl (:$b x8664::unbound-marker) (:%l dest))
+  (je :bad)
+
+  (:anchored-uuo-section :resume)
+  :bad
+  (:anchored-uuo (uuo-error-unbound (:%q src))))
+
+
+(define-x8664-vinsn (%ref-symbol-value :call :subprim-call)
+    (((val :lisp))
+     ((sym (:lisp (:ne val))))
+     ((entry (:label 1))))
+  (:talign 4)
+  (call (:@ .SPspecref))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn %ref-symbol-value-inline (((dest :lisp))
+                                              ((src (:lisp (:ne dest))))
+                                              ((table :imm)
+                                               (idx :imm)))
+  (movq (:@ x8664::symbol.binding-index (:%q src)) (:%q idx))
+  (rcmpq (:%q idx) (:rcontext x8664::tcr.tlb-limit))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (:%q table))
+  (jae :symbol)
+  (movq (:@ (:%q table) (:%q idx)) (:%q dest))
+  (cmpb (:$b x8664::subtag-no-thread-local-binding) (:%b dest))
+  (jne :done)
+  :symbol
+  (movq (:@ x8664::symbol.vcell (:%q src)) (:%q dest))
+  :done)
+
+(define-x8664-vinsn ref-interrupt-level (((dest :imm))
+                                         ()
+                                         ((temp :u64)))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (:%q temp))
+  (movq (:@ x8664::INTERRUPT-LEVEL-BINDING-INDEX (:%q temp)) (:%q dest)))
+
+
+
+
+(define-x8664-vinsn setup-double-float-allocation (()
+                                                   ())
+  (movl (:$l (arch::make-vheader x8664::double-float.element-count x8664::subtag-double-float)) (:%l x8664::imm0.l))
+  (movl (:$l (- x8664::double-float.size x8664::fulltag-misc)) (:%l x8664::imm1.l)))
+
+(define-x8664-vinsn set-double-float-value (()
+                                            ((node :lisp)
+                                             (val :double-float)))
+  (movsd (:%xmm val) (:@ x8664::double-float.value (:%q node))))
+
+(define-x8664-vinsn word-index-and-bitnum-from-index (((word-index :u64)
+                                                       (bitnum :u8))
+                                                      ((index :imm)))
+  (movq (:%q index) (:%q word-index))
+  (shrq (:$ub x8664::fixnumshift) (:%q word-index))
+  (movl (:$l 63) (:%l bitnum))
+  (andl (:%l word-index) (:%l bitnum))
+  (shrq (:$ub 6) (:%q word-index)))
+
+(define-x8664-vinsn ref-bit-vector-fixnum (((dest :imm)
+                                            (bitnum :u8))
+                                           ((bitnum :u8)
+                                            (bitvector :lisp)
+                                            (word-index :u64)))
+  (btq (:%q bitnum) (:@ x8664::misc-data-offset (:%q bitvector) (:%q word-index) 8))
+  (setb (:%b bitnum))
+  (negb (:%b bitnum))
+  (andl (:$l x8664::fixnumone) (:%l bitnum))
+  (movl (:%l bitnum) (:%l dest)))
+
+(define-x8664-vinsn nref-bit-vector-fixnum (((dest :imm)
+					     (bitnum :s64))
+					    ((bitnum :s64)
+					     (bitvector :lisp))
+					    ())
+  (btq (:%q bitnum) (:@ x8664::misc-data-offset (:%q bitvector)))
+  (setc (:%b bitnum))
+  (movzbl (:%b bitnum) (:%l bitnum))
+  (imull (:$b x8664::fixnumone) (:%l bitnum) (:%l dest)))
+
+
+(define-x8664-vinsn nref-bit-vector-flags (()
+					    ((bitnum :s64)
+					     (bitvector :lisp))
+					    ())
+  (btq (:%q bitnum) (:@ x8664::misc-data-offset (:%q bitvector))))
+
+(define-x8664-vinsn misc-ref-c-bit-fixnum (((dest :imm))
+                                           ((src :lisp)
+                                            (idx :u64const))
+                                           ((temp :u8)))
+  (btq (:$ub (:apply logand 63 idx))
+       (:@ (:apply + x8664::misc-data-offset (:apply ash (:apply ash idx -6) x8664::word-shift)) (:%q src)))
+  (setc (:%b temp))
+  (movzbl (:%b temp) (:%l temp))
+  (imull (:$b x8664::fixnumone) (:%l temp) (:%l dest)))
+
+
+(define-x8664-vinsn misc-ref-c-bit-flags (()
+                                           ((src :lisp)
+                                            (idx :u64const))
+                                          )
+  (btq (:$ub (:apply logand 63 idx))
+       (:@ (:apply + x8664::misc-data-offset (:apply ash (:apply ash idx -6) x8664::word-shift)) (:%q src))))
+
+(define-x8664-vinsn deref-macptr (((addr :address))
+				  ((src :lisp))
+				  ())
+  (movq (:@ x8664::macptr.address (:%q src)) (:%q addr)))
+
+(define-x8664-vinsn (temp-push-unboxed-word :push :word :csp)
+    (()
+     ((w :u64)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%mmx x8664::stack-temp))  
+  (subq (:$b (* 2 x8664::dnode-size)) (:rcontext x8664::tcr.foreign-sp))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q x8664::ra0)))
+  (movq (:% x8664::rbp) (:@ x8664::csp-frame.rbp (:%q x8664::ra0)))
+  (movq (:%q w) (:@ x8664::dnode-size (:%q x8664::ra0))))
+
+
+(define-x8664-vinsn (temp-push-node :push :word :tsp)
+        (()
+         ((w :lisp))
+         ((temp :imm)))
+  (subq (:$b (* 2 x8664::dnode-size)) (:rcontext x8664::tcr.next-tsp))
+  (movq (:rcontext x8664::tcr.save-tsp) (:%mmx x8664::stack-temp))
+  (movq (:rcontext x8664::tcr.next-tsp) (:%q temp))
+  (movapd (:%xmm x8664::fpzero) (:@ (:%q temp)))
+  (movapd (:%xmm x8664::fpzero) (:@ 16 (:%q temp)))
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q temp)))
+  (movq (:% x8664::rbp) (:@ x8664::tsp-frame.rbp (:%q temp)))  
+  (movq (:%q temp) (:rcontext x8664::tcr.save-tsp))
+  (movq (:%q w) (:@ x8664::dnode-size (:%q temp))))
+
+(define-x8664-vinsn (temp-push-double-float :push :word :csp)
+    (()
+     ((f :double-float)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%mmx x8664::stack-temp))  
+  (subq (:$b (* 2 x8664::dnode-size)) (:rcontext x8664::tcr.foreign-sp))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))  
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q x8664::ra0)))
+  (movq (:% x8664::rbp) (:@ x8664::csp-frame.rbp (:%q x8664::ra0)))
+  (movapd (:%xmm f) (:@ x8664::dnode-size (:%q x8664::ra0))))
+
+
+(define-x8664-vinsn (vpush-single-float :push :word :vsp)
+    (()
+     ((f :single-float)))
+  (pushq (:$b x8664::tag-single-float))
+  (movss (:%xmm f) (:@ 4 (:%q x8664::rsp))))
+
+(define-x8664-vinsn (vpop-single-float :pop :word :vsp)
+    (()
+     ((f :single-float)))
+  (movss (:@ 4 (:%q x8664::rsp)) (:%xmm f))
+  (addq (:$b x8664::node-size) (:%q x8664::rsp)))
+
+(define-x8664-vinsn (temp-pop-unboxed-word :pop :word :csp)
+    (((w :u64))
+     ())
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movq (:@ x8664::dnode-size (:%q x8664::ra0)) (:%q w))
+  (addq (:$b (* 2 x8664::dnode-size)) (:rcontext x8664::tcr.foreign-sp)))
+
+
+(define-x8664-vinsn (temp-pop-node :pop :word :tsp)
+        (((w :lisp))
+         ()
+         ((temp :imm)))
+  (movq (:rcontext x8664::tcr.save-tsp) (:%q temp))
+  (movq (:@ x8664::dnode-size (:%q temp)) (:%q w))
+  (movq (:@ (:%q temp)) (:%q temp))
+  (movq (:%q temp) (:rcontext x8664::tcr.save-tsp))  
+  (movq (:%q temp) (:rcontext x8664::tcr.next-tsp)))
+
+(define-x8664-vinsn (temp-pop-double-float :pop :word :csp)
+    (((f :double-float))
+     ())
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movapd (:@ x8664::dnode-size (:%q x8664::ra0)) (:%xmm f))
+  (addq (:$b (* 2 x8664::dnode-size)) (:rcontext x8664::tcr.foreign-sp)))
+
+
+
+(define-x8664-vinsn macptr->stack (((dest :lisp))
+                                   ((ptr :address)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%mmx x8664::stack-temp))
+  (subq (:$b (+ x8664::dnode-size x8664::macptr.size)) (:rcontext x8664::tcr.foreign-sp))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q x8664::ra0)))
+  (movq (:% x8664::rbp) (:@ x8664::csp-frame.rbp (:%q x8664::ra0)))
+  (leaq (:@ (+ x8664::dnode-size x8664::fulltag-misc) (:%q  x8664::ra0)) (:%q dest))
+  (movq (:$l x8664::macptr-header) (:@ x8664::macptr.header (:%q dest)))
+  (movq (:%q ptr) (:@ x8664::macptr.address (:%q dest)))
+  (movapd (:%xmm x8664::fpzero)  (:@ x8664::macptr.domain (:%q dest))))
+
+(define-x8664-vinsn fixnum->signed-natural (((dest :s64))
+                                            ((src :imm)))
+  (movq (:%q src) (:%q dest))
+  (sarq (:$ub x8664::fixnumshift) (:%q dest)))
+
+(define-x8664-vinsn mem-set-double-float (()
+					  ((val :double-float)
+					   (src :address)
+					   (index :s64)))
+  (movsd (:%xmm val) (:@ (:%q src) (:%q  index))))
+
+(define-x8664-vinsn mem-set-single-float (()
+					  ((val :single-float)
+					   (src :address)
+					   (index :s64)))
+  (movss (:%xmm val) (:@ (:%q src) (:%q  index))))
+
+
+
+(define-x8664-vinsn mem-set-c-doubleword (()
+                                          ((val :u64)
+                                           (dest :address)
+                                           (offset :s32const)))
+  ((:pred = offset 0)
+   (movq (:%q val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movq (:%q val) (:@ offset (:%q dest)))))
+
+(define-x8664-vinsn mem-set-c-fullword (()
+                                          ((val :u32)
+                                           (dest :address)
+                                           (offset :s32const)))
+  ((:pred = offset 0)
+   (movl (:%l val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movl (:%l val) (:@ offset (:%q dest)))))
+
+(define-x8664-vinsn mem-set-c-halfword (()
+                                          ((val :u16)
+                                           (dest :address)
+                                           (offset :s32const)))
+  ((:pred = offset 0)
+   (movw (:%w val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movw (:%w val) (:@ offset (:%q dest)))))
+
+(define-x8664-vinsn mem-set-c-byte (()
+                                          ((val :u8)
+                                           (dest :address)
+                                           (offset :s32const)))
+  ((:pred = offset 0)
+   (movb (:%b val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movb (:%b val) (:@ offset (:%q dest)))))
+
+(define-x8664-vinsn mem-set-c-constant-doubleword (()
+                                                   ((val :s32const)
+                                                    (dest :address)
+                                                    (offset :s32const)))
+  ((:pred = offset 0)
+   (movq (:$l val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movq (:$l val) (:@ offset (:%q dest)))))
+
+(define-x8664-vinsn mem-set-c-constant-fullword (()
+                                                 ((val :s32const)
+                                                  (dest :address)
+                                                  (offset :s32const)))
+  ((:pred = offset 0)
+   (movl (:$l val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movl (:$l val) (:@ offset (:%q dest)))))
+
+(define-x8664-vinsn mem-set-c-constant-halfword (()
+                                                 ((val :s16const)
+                                                  (dest :address)
+                                                  (offset :s32const)))
+  ((:pred = offset 0)
+   (movw (:$w val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movw (:$w val) (:@ offset (:%q dest)))))
+
+(define-x8664-vinsn mem-set-c-constant-byte (()
+                                                 ((val :s8const)
+                                                  (dest :address)
+                                                  (offset :s32const)))
+  ((:pred = offset 0)
+   (movb (:$b val) (:@ (:%q dest))))
+  ((:not (:pred = offset 0))
+   (movb (:$b val) (:@ offset (:%q dest)))))
+
+
+
+
+
+
+(define-x8664-vinsn mem-ref-natural (((dest :u64))
+                                        ((src :address)
+                                         (index :s64)))
+  (movq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn setup-macptr-allocation (()
+                                             ((src :address)))
+  (movd (:%q src) (:%mmx x8664::mm0))
+  (movl (:$l x8664::macptr-header) (:%l x8664::imm0.l))
+  (movl (:$l (- x8664::macptr.size x8664::fulltag-misc)) (:%l x8664::imm1.l)))
+
+(define-x8664-vinsn %set-new-macptr-value (()
+                                           ((ptr :lisp)))
+  (movq (:%mmx x8664::mm0) (:@ x8664::macptr.address (:%q ptr))))
+
+(define-x8664-vinsn mem-ref-c-fullword (((dest :u32))
+					((src :address)
+					 (index :s32const)))
+  ((:pred = index 0)
+   (movl (:@ (:%q src)) (:%l dest)))
+  ((:not (:pred = index 0))
+   (movl (:@ index (:%q src)) (:%l dest))))
+
+(define-x8664-vinsn mem-ref-c-signed-fullword (((dest :s32))
+                                               ((src :address)
+                                                (index :s32const)))
+  ((:pred = index 0)
+   (movslq (:@ (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movslq (:@ index (:%q src)) (:%q dest))))
+
+
+(define-x8664-vinsn mem-ref-c-single-float (((dest :single-float))
+                                           ((src :address)
+                                            (index :s32const)))
+  ((:pred = index 0)
+   (movss (:@ (:%q src)) (:%xmm dest)))
+  ((:not (:pred = index 0))
+   (movss (:@ index (:%q src)) (:%xmm dest))))
+
+(define-x8664-vinsn mem-set-c-single-float (()
+					    ((val :single-float)
+					     (src :address)
+					     (index :s16const)))
+  ((:pred = index 0)
+   (movss (:%xmm val) (:@ (:%q src))))
+  ((:not (:pred = index 0))
+   (movss (:%xmm val) (:@ index (:%q src)))))
+
+(define-x8664-vinsn mem-ref-c-doubleword (((dest :u64))
+                                          ((src :address)
+                                           (index :s32const)))
+  ((:pred = index 0)
+   (movq (:@ (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movq (:@ index (:%q src)) (:%q dest))))
+
+(define-x8664-vinsn mem-ref-c-signed-doubleword (((dest :s64))
+                                                 ((src :address)
+                                                  (index :s32const)))
+  ((:pred = index 0)
+   (movq (:@ (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movq (:@ index (:%q src)) (:%q dest))))
+
+(define-x8664-vinsn mem-ref-c-natural (((dest :u64))
+                                       ((src :address)
+                                        (index :s32const)))
+  ((:pred = index 0)
+   (movq (:@ (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movq (:@ index (:%q src)) (:%q dest))))
+
+(define-x8664-vinsn mem-ref-c-double-float (((dest :double-float))
+                                            ((src :address)
+                                             (index :s32const)))
+  ((:pred = index 0)
+   (movsd (:@ (:%q src)) (:%xmm dest)))
+  ((:not (:pred = index 0))
+   (movsd (:@ index (:%q src)) (:%xmm dest))))
+
+(define-x8664-vinsn mem-set-c-double-float (()
+					    ((val :double-float)
+					     (src :address)
+					     (index :s16const)))
+  ((:pred = index 0)
+   (movsd (:%xmm val) (:@ (:%q src))))
+  ((:not (:pred = index 0))
+   (movsd (:%xmm val) (:@ index (:%q src)))))
+
+(define-x8664-vinsn mem-ref-fullword (((dest :u32))
+				      ((src :address)
+				       (index :s64)))
+  (movl (:@ (:%q src) (:%q index)) (:%l dest)))
+
+(define-x8664-vinsn mem-ref-signed-fullword (((dest :s32))
+                                             ((src :address)
+                                              (index :s64)))
+  (movslq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-doubleword (((dest :u64))
+                                        ((src :address)
+                                         (index :s64)))
+  (movq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-natural (((dest :u64))
+                                        ((src :address)
+                                         (index :s64)))
+  (movq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-signed-doubleword (((dest :s64))
+                                               ((src :address)
+                                                (index :s64)))
+  (movq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-u16 (((dest :u16))
+				   ((src :address)
+				    (index :s32const)))
+  ((:pred = index 0)  
+   (movzwq (:@ (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movzwq (:@ index (:%q src)) (:%q dest))))
+
+(define-x8664-vinsn mem-ref-u16 (((dest :u16))
+				 ((src :address)
+				  (index :s64)))
+  (movzwq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+
+(define-x8664-vinsn mem-ref-c-s16 (((dest :s16))
+				   ((src :address)
+				    (index :s32const)))
+  ((:pred = index 0)
+   (movswq (:@ (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movswq (:@ index (:%q src)) (:%q dest))))
+
+(define-x8664-vinsn mem-ref-s16 (((dest :s16))
+				 ((src :address)
+				  (index :s32)))
+  (movswq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-u8 (((dest :u8))
+				  ((src :address)
+				   (index :s16const)))
+  ((:pred = index 0)
+   (movzbq (:@  (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movzbq (:@ index (:%q src)) (:%q dest))))
+
+(define-x8664-vinsn mem-ref-u8 (((dest :u8))
+				((src :address)
+				 (index :s32)))
+  (movzbq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-s8 (((dest :s8))
+				  ((src :address)
+				   (index :s16const)))
+  ((:pred = index 0)
+   (movsbq (:@ (:%q src)) (:%q dest)))
+  ((:not (:pred = index 0))
+   (movsbq (:@ index (:%q src)) (:%q dest))))
+
+(define-x8664-vinsn misc-set-c-s8  (((val :s8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (movb (:%b val) (:@ (:apply + x8664::misc-data-offset idx) (:%q v))))
+
+(define-x8664-vinsn misc-set-s8  (((val :s8))
+				  ((v :lisp)
+				   (scaled-idx :s64))
+				  ())
+  (movb (:%b val) (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn mem-ref-s8 (((dest :s8))
+				((src :address)
+				 (index :s32)))
+  (movsbq (:@ (:%q src) (:%q index)) (:%q dest)))
+
+(define-x8664-vinsn mem-set-constant-doubleword (()
+                                                 ((val :s32const)
+                                                  (ptr :address)
+                                                  (offset :s64)))
+  (movq (:$l val) (:@ (:%q ptr) (:%q offset))))
+
+(define-x8664-vinsn mem-set-constant-fullword (()
+                                               ((val :s32const)
+                                                (ptr :address)
+                                                (offset :s64)))
+  (movl (:$l val) (:@ (:%q ptr) (:%q offset))))
+
+
+(define-x8664-vinsn mem-set-constant-halfword (()
+                                               ((val :s16const)
+                                                (ptr :address)
+                                                (offset :s64)))
+  (movw (:$w val) (:@ (:%q ptr) (:%q offset))))
+
+(define-x8664-vinsn mem-set-constant-byte (()
+                                           ((val :s8const)
+                                            (ptr :address)
+                                            (offset :s64)))
+  (movb (:$b val) (:@ (:%q ptr) (:%q offset))))
+
+(define-x8664-vinsn misc-set-c-u8  (((val :u8))
+				    ((v :lisp)
+				     (idx :u32const))
+				    ())
+  (movb (:%b val) (:@ (:apply + x8664::misc-data-offset idx) (:%q v))))
+
+(define-x8664-vinsn misc-set-u8  (((val :u8))
+				  ((v :lisp)
+				   (scaled-idx :s64))
+				  ())
+  (movb (:%b val) (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn misc-set-c-u8  (((val :u8))
+                                    ((v :lisp)
+                                     (idx :s32const))
+                                    ())
+  (movb (:%b val) (:@ (:apply + x8664::misc-data-offset idx) (:%q v))))
+
+(define-x8664-vinsn misc-set-u8  (()
+				  ((val :u8)
+                                   (v :lisp)
+				   (scaled-idx :s64))
+				  ())
+  (movb (:%b val) (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn misc-set-c-u16  (()
+                                    ((val :u16)
+                                     (v :lisp)
+                                     (idx :s32const))
+                                    ())
+  (movw (:%w val) (:@ (:apply + x8664::misc-data-offset (:apply * 2 idx)) (:%q v))))
+
+
+(define-x8664-vinsn misc-set-u16  (()
+                                   ((val :u16)
+                                    (v :lisp)
+                                    (scaled-idx :s64))
+                                   ())
+  (movw (:%w val) (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn misc-set-c-s16  (()
+                                    ((val :s16)
+                                     (v :lisp)
+                                     (idx :s32const))
+                                    ())
+  (movw (:%w val) (:@ (:apply + x8664::misc-data-offset (:apply * 2 idx)) (:%q v))))
+
+
+(define-x8664-vinsn misc-set-s16  (()
+                                   ((val :s16)
+                                    (v :lisp)
+                                    (scaled-idx :s64))
+                                   ())
+  (movw (:%w val) (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn misc-set-c-u32  (()
+				     ((val :u32)
+                                      (v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movl (:%l val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 2)) (:%q v))))
+
+(define-x8664-vinsn misc-set-u32  (()
+                                   ((val :u32)
+                                    (v :lisp)
+                                    (scaled-idx :s64))
+                                   ())
+  (movl (:%l val) (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn misc-set-c-s32  (()
+				     ((val :s32)
+                                      (v :lisp)
+				      (idx :u32const)) ; sic
+				     ())
+  (movl (:%l val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 2)) (:%q v))))
+
+(define-x8664-vinsn misc-set-s32  (()
+                                   ((val :s32)
+                                    (v :lisp)
+                                    (scaled-idx :s64))
+                                   ())
+  (movl (:%l val) (:@ x8664::misc-data-offset (:%q v) (:%q scaled-idx))))
+
+(define-x8664-vinsn %iasr (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :s64)
+                            (shiftcount (:s64 #.x8664::rcx))))
+  (movq (:%q count) (:%q temp))
+  (sarq (:$ub x8664::fixnumshift) (:%q temp))
+  (rcmpq (:%q temp) (:$l 63))
+  (cmovbw (:%w temp) (:%w shiftcount))
+  (movq (:%q src) (:%q temp))
+  (jae :shift-max)
+  (sarq (:%shift x8664::cl) (:%q temp))
+  (jmp :done)
+  :shift-max
+  (sarq (:$ub 63) (:%q temp))
+  :done
+  (andb (:$b (lognot x8664::fixnummask)) (:%b temp))
+  (movq (:%q temp) (:%q dest)))
+
+(define-x8664-vinsn %ilsr (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :s64)
+                            (shiftcount (:s64 #.x8664::rcx))))
+  (movq (:%q count) (:%q temp))
+  (sarq (:$ub x8664::fixnumshift) (:%q temp))
+  (rcmpq (:%q temp) (:$l 63))
+  (cmovbw (:%w temp) (:%w shiftcount))
+  (movq (:%q src) (:%q temp))
+  (jae :shift-max)
+  (shrq (:%shift x8664::cl) (:%q temp))
+  (jmp :done)
+  :shift-max
+  (shrq (:$ub 63) (:%q temp))
+  :done
+  (andb (:$b (lognot x8664::fixnummask)) (:%b temp))
+  (movq (:%q temp) (:%q dest)))
+
+(define-x8664-vinsn %iasr-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm))
+			     ((temp :s64)))
+  (movq (:%q src) (:%q temp))
+  (sarq (:$ub count) (:%q temp))
+  (andq (:$b (lognot x8664::fixnummask)) (:%q temp))
+  (movq (:%q temp) (:%q dest)))
+
+(define-x8664-vinsn %ilsr-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm))
+			     ((temp :s64)))
+  (movq (:%q src) (:%q temp))
+  (shrq (:$ub count) (:%q temp))
+  (andb (:$b (lognot x8664::fixnummask)) (:%b temp))
+  (movq (:%q temp) (:%q dest)))
+
+(define-x8664-vinsn %ilsl (((dest :imm))
+			   ((count :imm)
+			    (src :imm))
+			   ((temp :s64)
+                            (shiftcount (:s64 #.x8664::rcx))))
+  (movq (:%q count) (:%q temp))
+  (sarq (:$ub x8664::fixnumshift) (:%q temp))
+  (rcmpq (:%q temp) (:$l 63))
+  (cmovbw (:%w temp) (:%w shiftcount))
+  (movq (:%q src) (:%q temp))
+  (jae :shift-max)
+  (shlq (:%shift x8664::cl) (:%q temp))
+  (jmp :done)
+  :shift-max
+  (xorq (:%q temp) (:%q temp))
+  :done
+  (movq (:%q temp) (:%q dest)))
+
+(define-x8664-vinsn %ilsl-c (((dest :imm))
+			     ((count :u8const)
+			      (src :imm)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value src)
+                (:apply %hard-regspec-value dest)))
+   (movq (:%q src) (:%q dest)))
+  (shlq (:$ub count) (:%q dest)))
+
+;;; In safe code, something else has ensured that the value is of type
+;;; BIT.
+(define-x8664-vinsn set-variable-bit-to-variable-value (()
+                                                        ((vec :lisp)
+                                                         (word-index :s64)
+                                                         (bitnum :u8)
+                                                         (value :lisp)))
+  (testb (:%b value) (:%b value))
+  (je :clr)
+  (btsq (:%q bitnum) (:@ x8664::misc-data-offset (:%q vec) (:%q word-index) 8))
+  (jmp :done)
+  :clr
+  (btrq (:%q bitnum) (:@ x8664::misc-data-offset (:%q vec) (:%q word-index) 8))
+  :done)
+
+(define-x8664-vinsn set-variable-bit-to-zero (()
+                                              ((vec :lisp)
+                                               (word-index :s64)
+                                               (bitnum :u8)))
+  (btrq (:%q bitnum) (:@ x8664::misc-data-offset (:%q vec) (:%q word-index) 8)))
+
+(define-x8664-vinsn set-variable-bit-to-one (()
+                                              ((vec :lisp)
+                                               (word-index :s64)
+                                               (bitnum :u8)))
+  (btsq (:%q bitnum) (:@ x8664::misc-data-offset (:%q vec) (:%q word-index) 8)))
+
+;;; In safe code, something else has ensured that the value is of type
+;;; BIT.
+(define-x8664-vinsn nset-variable-bit-to-variable-value (()
+                                                        ((vec :lisp)
+                                                         (index :s64)
+                                                         (value :lisp)))
+  (testb (:%b value) (:%b value))
+  (je :clr)
+  (btsq (:%q index) (:@ x8664::misc-data-offset (:%q vec)))
+  (jmp :done)
+  :clr
+  (btrq (:%q index) (:@ x8664::misc-data-offset (:%q vec)))
+  :done)
+
+(define-x8664-vinsn nset-variable-bit-to-zero (()
+                                              ((vec :lisp)
+                                               (index :s64)))
+  (btrq (:%q index) (:@ x8664::misc-data-offset (:%q vec))))
+
+(define-x8664-vinsn nset-variable-bit-to-one (()
+                                              ((vec :lisp)
+                                               (index :s64)))
+  (btsq (:%q index) (:@ x8664::misc-data-offset (:%q vec))))
+
+(define-x8664-vinsn set-constant-bit-to-zero (()
+                                              ((src :lisp)
+                                               (idx :u64const)))
+  (btrq (:$ub (:apply logand 63 idx))
+        (:@ (:apply + x8664::misc-data-offset (:apply ash (:apply ash idx -6) x8664::word-shift)) (:%q src))))
+
+(define-x8664-vinsn set-constant-bit-to-one (()
+                                             ((src :lisp)
+                                              (idx :u64const)))
+  (btsq (:$ub (:apply logand 63 idx))
+        (:@ (:apply + x8664::misc-data-offset (:apply ash (:apply ash idx -6) x8664::word-shift)) (:%q src))))
+
+(define-x8664-vinsn set-constant-bit-to-variable-value (()
+                                                        ((src :lisp)
+                                                         (idx :u64const)
+                                                         (value :lisp)))
+  (testb (:%b value) (:%b value))
+  (je :clr)
+  (btsq (:$ub (:apply logand 63 idx))
+        (:@ (:apply + x8664::misc-data-offset (:apply ash (:apply ash idx -6) x8664::word-shift)) (:%q src)))
+  (jmp :done)
+  :clr
+  (btrq (:$ub (:apply logand 63 idx))
+        (:@ (:apply + x8664::misc-data-offset (:apply ash (:apply ash idx -6) x8664::word-shift)) (:%q src)))
+  :done)
+
+
+(define-x8664-vinsn require-fixnum (()
+                                    ((object :lisp)))
+  :again
+  (testl (:$l x8664::fixnummask) (:%l object))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-fixnum))))
+
+(define-x8664-vinsn require-integer (()
+                                     ((object :lisp))
+                                     ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::fixnummask) (:%l tag))
+  (je :got-it)
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8664::subtag-bignum) (:@ x8664::misc-subtag-offset (:%q object)))
+  (jne :bad)
+  :got-it
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-integer))))
+
+(define-x8664-vinsn require-simple-vector (()
+                                           ((object :lisp))
+                                           ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::fixnummask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8664::subtag-simple-vector) (:@ x8664::misc-subtag-offset (:%q object)))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-simple-vector))))
+
+(define-x8664-vinsn require-simple-string (()
+                                           ((object :lisp))
+                                           ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::fixnummask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8664::subtag-simple-base-string) (:@ x8664::misc-subtag-offset (:%q object)))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-simple-string))))
+                                    
+(define-x8664-vinsn require-real (()
+                                    ((object :lisp))
+                                    ((tag :u8)
+                                     (mask :u64)))
+  (movq (:$q (logior (ash 1 x8664::tag-fixnum)
+                     (ash 1 x8664::tag-single-float)
+                     (ash 1 x8664::subtag-double-float)
+                     (ash 1 x8664::subtag-bignum)
+                     (ash 1 x8664::subtag-ratio)))
+        (:%q mask))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8664::misc-subtag-offset (:%q object)) (:%l tag))
+  :have-tag
+  (rcmpl (:%l tag) (:$b 64))
+  (jae :bad)
+  (btq (:%q tag) (:%q mask))
+  (jae :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-real))))
+
+(define-x8664-vinsn require-number (()
+                                    ((object :lisp))
+                                    ((tag :u8)
+                                     (mask :u64)))
+  (movq (:$q (logior (ash 1 x8664::tag-fixnum)
+                     (ash 1 x8664::tag-single-float)
+                     (ash 1 x8664::subtag-double-float)
+                     (ash 1 x8664::subtag-bignum)
+                     (ash 1 x8664::subtag-ratio)
+                     (ash 1 x8664::subtag-complex)))
+        (:%q mask))
+  :again
+  (movl (:%l object) (:%l tag))  
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8664::misc-subtag-offset (:%q object)) (:%l tag))
+  :have-tag
+  (rcmpl (:%l tag) (:$b 64))
+  (jae :bad)
+  (btq (:%q tag) (:%q mask))
+  (jae :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-number))))
+
+(define-x8664-vinsn require-list (()
+                                  ((object :lisp))
+                                  ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-list) (:%l tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-list))))
+
+(define-x8664-vinsn require-symbol (()
+                                    ((object :lisp))
+                                    ((tag :u8)))
+  :again
+  (movzbl (:%b object) (:%l tag))
+  (cmpl (:$b x8664::fulltag-nil) (:%l tag))
+  (je :good)
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-symbol) (:%l tag))
+  (jne :bad)
+  :good
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-symbol))))
+
+(define-x8664-vinsn require-character (()
+				((object :lisp)))
+  :again
+  (cmpb (:$b x8664::subtag-character) (:%b object))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-character))))
+
+(define-x8664-vinsn require-s8 (()
+				((object :lisp))
+				((tag :u32)))
+  :again
+  (movq (:%q object) (:%q tag))
+  (shlq (:$ub (- x8664::nbits-in-word (+ 8 x8664::fixnumshift))) (:%q tag))
+  (sarq (:$ub (- x8664::nbits-in-word 8)) (:%q tag))
+  (shlq (:$ub x8664::fixnumshift) (:%q tag))
+  (cmpq (:%q object) (:%q tag))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-signed-byte-8))))
+
+(define-x8664-vinsn require-u8 (()
+				((object :lisp))
+				((tag :u32)))
+  :again
+  (movq (:$l (lognot (ash #xff x8664::fixnumshift))) (:%q tag))
+  (andq (:% object) (:% tag))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-unsigned-byte-8))))
+
+(define-x8664-vinsn require-s16 (()
+				((object :lisp))
+				((tag :s64)))
+  :again
+  (movq (:%q object) (:%q tag))
+  (shlq (:$ub (- x8664::nbits-in-word (+ 16 x8664::fixnumshift))) (:%q tag))
+  (sarq (:$ub (- x8664::nbits-in-word 16)) (:%q tag))
+  (shlq (:$ub x8664::fixnumshift) (:%q tag))
+  (cmpq (:%q object) (:%q tag))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-signed-byte-16))))
+
+(define-x8664-vinsn require-u16 (()
+				((object :lisp))
+				((tag :u32)))
+  :again
+  (movq (:$l (lognot (ash #xffff x8664::fixnumshift))) (:%q tag))
+  (andq (:% object) (:% tag))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-unsigned-byte-16))))
+
+(define-x8664-vinsn require-s32 (()
+				((object :lisp))
+				((tag :s64)))
+  :again
+  (movq (:%q object) (:%q tag))
+  (shlq (:$ub (- x8664::nbits-in-word (+ 32 x8664::fixnumshift))) (:%q tag))
+  (sarq (:$ub (- x8664::nbits-in-word 32)) (:%q tag))
+  (shlq (:$ub x8664::fixnumshift) (:%q tag))
+  (cmpq (:%q object) (:%q tag))
+  (jne :bad)
+  (testl (:$l x8664::fixnummask) (:%l object))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-signed-byte-32))))
+
+(define-x8664-vinsn require-u32 (()
+                                 ((object :lisp))
+                                 ((tag :u32)))
+  :again
+  (movq (:$q (lognot (ash #xffffffff x8664::fixnumshift))) (:%q tag))
+  (andq (:% object) (:% tag))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-unsigned-byte-32))))
+
+(define-x8664-vinsn require-s64 (()
+				((object :lisp))
+				((tag :s64)))
+  :again
+  (testl (:$l x8664::fixnummask) (:%l object))
+  (movl (:%l object) (:%l tag))
+  (je :ok)
+  (andl (:$b x8664::fulltagmask) (:%l tag))
+  (cmpl (:$b x8664::fulltag-misc) (:%l tag))
+  (jne :bad)
+  (cmpq (:$l x8664::two-digit-bignum-header) (:@ x8664::misc-header-offset (:%q object)))
+  (jne :bad)
+  :ok
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-signed-byte-64))))
+
+(define-x8664-vinsn require-u64 (()
+				((object :lisp))
+				((tag :s64)))
+  :again
+  (testl (:$l x8664::fixnummask) (:%l object))
+  (movq (:%q object) (:%q tag))
+  (je :ok-if-non-negative)
+  (andl (:$b x8664::fulltagmask) (:%l tag))
+  (cmpl (:$b x8664::fulltag-misc) (:%l tag))
+  (jne :bad)
+  (cmpq (:$l x8664::two-digit-bignum-header) (:@ x8664::misc-header-offset (:%q object)))
+  (je :two)
+  (cmpq (:$l x8664::three-digit-bignum-header) (:@ x8664::misc-header-offset (:%q object)))
+  (jne :bad)
+  (cmpl (:$b 0) (:@ (+ x8664::misc-data-offset 8) (:%q object)))
+  (je :ok)
+  (jmp :bad)
+  :two
+  (movq (:@ x8664::misc-data-offset (:%q object)) (:%q tag))
+  :ok-if-non-negative
+  (testq (:%q tag) (:%q tag))
+  (js :bad)
+  :ok
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-unsigned-byte-64))))
+
+(define-x8664-vinsn require-char-code (()
+                                       ((object :lisp))
+                                       ((tag :u32)))
+  :again
+  (testl (:$l x8664::fixnummask) (:%l object))
+  (jne :bad)
+  (cmpq (:$l (ash #x110000 x8664::fixnumshift)) (:%q object))
+  (jae :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub arch::error-object-not-mod-char-code-limit))))
+
+
+;;; set DEST to 
+(define-x8664-vinsn mask-base-char (((dest :u8))
+                                    ((src :lisp)))
+  (movzbl (:%b src) (:%l dest))) 
+
+(define-x8664-vinsn single-float-bits (((dest :u32))
+                                       ((src :lisp)))
+  (movq (:%q src) (:%q dest))
+  (shrq (:$ub 32) (:%q dest)))
+
+(define-x8664-vinsn zero-double-float-register (((dest :double-float))
+                                                ())
+  (movsd (:%xmm x8664::fpzero) (:%xmm dest)))
+
+(define-x8664-vinsn zero-single-float-register (((dest :single-float))
+                                                ())
+  (movss (:%xmm x8664::fpzero) (:%xmm dest)))
+
+(define-x8664-subprim-lea-jmp-vinsn (heap-rest-arg) .SPheap-rest-arg)
+(define-x8664-subprim-lea-jmp-vinsn (stack-rest-arg) .SPstack-rest-arg)
+(define-x8664-subprim-lea-jmp-vinsn (req-stack-rest-arg) .SPreq-stack-rest-arg)
+
+(define-x8664-subprim-call-vinsn (stack-misc-alloc) .SPstack-misc-alloc)
+
+(define-x8664-vinsn misc-element-count-fixnum (((dest :imm))
+                                               ((src :lisp))
+                                               ((temp :u64)))
+  (movq (:@ x8664::misc-header-offset (:%q src)) (:%q temp))
+  (shrq (:$ub x8664::num-subtag-bits) (:%q temp))
+  (imulq (:$b x8664::fixnumone) (:%q temp)(:%q dest)))
+
+(define-x8664-vinsn %logior2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (orq (:%q y) (:%q dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (orq (:%q x) (:%q dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (movq (:%q x) (:%q dest))
+    (orq (:%q y) (:%q dest)))))
+
+(define-x8664-vinsn %logand2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (andq (:%q y) (:%q dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (andq (:%q x) (:%q dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (movq (:%q x) (:%q dest))
+    (andq (:%q y) (:%q dest)))))
+
+(define-x8664-vinsn %logxor2 (((dest :imm))
+                              ((x :imm)
+                               (y :imm)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (xorq (:%q y) (:%q dest)))
+  ((:not (:pred =
+                (:apply %hard-regspec-value x)
+                (:apply %hard-regspec-value dest)))
+   ((:pred =
+           (:apply %hard-regspec-value y)
+           (:apply %hard-regspec-value dest))
+    (xorq (:%q x) (:%q dest)))
+   ((:not (:pred =
+                 (:apply %hard-regspec-value y)
+                 (:apply %hard-regspec-value dest)))
+    (movq (:%q x) (:%q dest))
+    (xorq (:%q y) (:%q dest)))))
+
+(define-x8664-subprim-call-vinsn (integer-sign) .SPinteger-sign)
+
+(define-x8664-vinsn vcell-ref (((dest :lisp))
+			       ((vcell :lisp)))
+  (movq (:@ x8664::misc-data-offset (:%q vcell)) (:%q dest)))
+
+(define-x8664-vinsn (call-subprim-3 :call :subprim-call) (((dest t))
+							  ((spno :s32const)
+							   (x t)
+							   (y t)
+							   (z t))
+                                                          ((entry (:label 1))))
+  (:talign 4)
+  (call (:@ spno))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn setup-vcell-allocation (()
+                                            ())
+  (movl (:$l x8664::value-cell-header) (:%l x8664::imm0))
+  (movl (:$l (- x8664::value-cell.size x8664::fulltag-misc)) (:%l x8664::imm1)))
+
+(define-x8664-vinsn %init-vcell (()
+                                 ((vcell :lisp)
+                                  (closed :lisp)))
+  (movq (:%q closed) (:@ x8664::value-cell.value (:%q vcell))))
+
+(define-x8664-subprim-call-vinsn (progvsave) .SPprogvsave)
+
+(define-x8664-subprim-jump-vinsn (progvrestore) .SPprogvrestore)
+
+(define-x8664-subprim-lea-jmp-vinsn (simple-keywords) .SPsimple-keywords)
+
+(define-x8664-subprim-lea-jmp-vinsn (keyword-args) .SPkeyword-args)
+
+(define-x8664-subprim-lea-jmp-vinsn (keyword-bind) .SPkeyword-bind)
+
+(define-x8664-vinsn scale-nargs (()
+				 ((nfixed :s16const)))
+  ((:pred > nfixed 0)
+   ((:pred < nfixed 16)
+    (subl (:$b (:apply ash nfixed x8664::word-shift)) (:%l x8664::nargs)))
+   ((:pred >= nfixed 16)
+    (subl (:$l (:apply ash nfixed x8664::word-shift)) (:%l x8664::nargs)))))
+
+(define-x8664-vinsn opt-supplied-p (()
+                                    ((num-opt :u16const))
+                                    ((nargs (:u64 #.x8664::nargs))
+                                     (imm :imm)))
+  (xorl (:%l imm) (:%l imm))
+  (movl (:$l (:apply target-nil-value)) (:%l x8664::arg_y))
+  :loop
+  (rcmpl (:%l imm) (:%l nargs))
+  (movl (:%l x8664::arg_y) (:%l x8664::arg_z))
+  (cmovll (:@ (+ x8664::t-offset x8664::symbol.vcell) (:%l x8664::arg_y)) (:%l  x8664::arg_z))
+  (addl (:$b x8664::node-size) (:%l imm))
+  (rcmpl (:%l imm) (:$l (:apply ash num-opt x8664::fixnumshift)))
+  (pushq (:%q x8664::arg_z))
+  (jne :loop))
+
+(define-x8664-vinsn one-opt-supplied-p (()
+                                        ()
+                                        ((temp :u64)))
+  (testl (:%l x8664::nargs) (:%l x8664::nargs))
+  (movl (:$l (:apply target-nil-value)) (:%l temp))
+  (cmovnel (:@ (+ x8664::t-offset x8664::symbol.vcell) (:%l temp)) (:%l temp))
+  (pushq (:%q temp)))
+
+(define-x8664-vinsn two-opt-supplied-p (()
+                                        ()
+                                        ((temp0 :u64)
+                                         (temp1 :u64)))
+  (rcmpl (:%l x8664::nargs) (:$b x8664::node-size))
+  (movl (:$l (:apply target-nil-value)) (:%l temp0))
+  (movl (:%l temp0) (:%l temp1))
+  (cmovael (:@ (+ x8664::t-offset x8664::symbol.vcell) (:%l temp0)) (:%l temp0))
+  (cmoval (:@ (+ x8664::t-offset x8664::symbol.vcell) (:%l temp1)) (:%l temp1))
+  (pushq (:%q temp0))
+  (pushq (:%q temp1)))
+
+
+(define-x8664-vinsn set-c-flag-if-constant-logbitp (()
+                                                    ((bit :u8const)
+                                                     (int :imm)))
+  (btq (:$ub bit) (:%q int)))
+
+(define-x8664-vinsn set-c-flag-if-variable-logbitp (()
+                                                    ((bit :imm)
+                                                     (int :imm))
+                                                    ((temp0 :u8)
+                                                     (temp1 :u8)))
+  (movl (:$l 63) (:%l temp1))
+  (movq (:%q bit) (:%q temp0))
+  (sarq (:$ub x8664::fixnumshift) (:%q temp0))
+  (addq (:$b x8664::fixnumshift) (:%q temp0))
+  (rcmpq (:%q temp0) (:%q temp1))
+  (cmoval (:%l temp1) (:%l temp0))
+  (btq (:%q temp0) (:%q int)))
+
+(define-x8664-vinsn multiply-immediate (((dest :imm))
+                                        ((src :imm)
+                                         (const :s32const)))
+  ((:and (:pred >= const -128) (:pred <= const 127))
+   (imulq (:$b const) (:%q src) (:%q dest)))
+  ((:not (:and (:pred >= const -128) (:pred <= const 127)))
+   (imulq (:$l const) (:%q src) (:%q dest))))
+
+(define-x8664-vinsn multiply-fixnums (((dest :imm))
+                                      ((x :imm)
+                                       (y :imm))
+                                      ((unboxed :s64)))
+  ((:pred =
+          (:apply %hard-regspec-value x)
+          (:apply %hard-regspec-value dest))
+   (movq (:%q y) (:%q unboxed))
+   (sarq (:$ub x8664::fixnumshift) (:%q unboxed))
+   (imulq (:%q unboxed) (:%q dest)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value x)
+                      (:apply %hard-regspec-value dest)))
+         (:pred =
+                (:apply %hard-regspec-value y)
+                (:apply %hard-regspec-value dest)))
+   (movq (:%q x) (:%q unboxed))
+   (sarq (:$ub x8664::fixnumshift) (:%q unboxed))
+   (imulq (:%q unboxed) (:%q dest)))
+  ((:and (:not (:pred =
+                      (:apply %hard-regspec-value x)
+                      (:apply %hard-regspec-value dest)))
+         (:not (:pred =
+                      (:apply %hard-regspec-value y)
+                      (:apply %hard-regspec-value dest))))
+   (movq (:%q y) (:%q dest))
+   (movq (:%q x) (:%q unboxed))
+   (sarq (:$ub x8664::fixnumshift) (:%q unboxed))
+   (imulq (:%q unboxed) (:%q dest))))
+
+   
+(define-x8664-vinsn save-lexpr-argregs (()
+                                        ((min-fixed :u16const)))
+  ((:pred >= min-fixed $numx8664argregs)
+   (pushq (:%q x8664::arg_x))
+   (pushq (:%q x8664::arg_y))
+   (pushq (:%q x8664::arg_z)))
+  ((:pred = min-fixed 2)                ; at least 2 args
+   (cmpl (:$b (ash 2 x8664::word-shift)) (:%l x8664::nargs))
+   (je :yz2)                      ; skip arg_x if exactly 2
+   (pushq (:%q x8664::arg_x))
+   :yz2
+   (pushq (:%q x8664::arg_y))
+   (pushq (:%q x8664::arg_z)))
+  ((:pred = min-fixed 1)                ; at least one arg
+   (rcmpl (:%l x8664::nargs) (:$b  (ash 2 x8664::word-shift)))
+   (jl :z1)                       ; branch if exactly one
+   (je :yz1)                      ; branch if exactly two
+   (pushq (:%q x8664::arg_x))
+   :yz1
+   (pushq (:%q x8664::arg_y))
+   :z1
+   (pushq (:%q x8664::arg_z)))
+  ((:pred = min-fixed 0)
+   (testl (:%l x8664::nargs) (:%l x8664::nargs))
+   (je  :none)                     ; exactly zero
+   (rcmpl (:%l x8664::nargs) (:$b (ash 2 x8664::word-shift)))
+   (je :yz0)                      ; exactly two
+   (jl :z0)                       ; one
+                                        ; Three or more ...
+   (pushq (:%q x8664::arg_x))
+   :yz0
+   (pushq (:%q x8664::arg_y))
+   :z0
+   (pushq (:%q x8664::arg_z))
+   :none
+   )
+  ((:not (:pred = min-fixed 0))
+   (leaq (:@ (:apply - (:apply ash min-fixed x8664::word-shift)) (:%q x8664::nargs))
+         (:%q x8664::nargs)))
+  (pushq (:%q x8664::nargs))
+  (movq (:%q x8664::rsp) (:%q x8664::arg_z)))
+
+
+
+
+;;; The frame that was built (by SAVE-LISP-CONTEXT-VARIABLE-ARG-COUNT
+;;; and SAVE-LEXPR-ARGREGS) contains an unknown number of arguments
+;;; followed by the count of non-required arguments; the count is on
+;;; top of the stack and its address is in %arg_z.  We need to build a
+;;; frame so that the function can address its arguments (copies of
+;;; the required arguments and the lexpr) and locals; when the
+;;; function returns, it should one or more values (depending on how
+;;; it was called) and discard the hidden lexpr frame.  At this point,
+;;; %ra0 still contains the "real" return address. If it's not the
+;;; magic multiple-value address, we can make the function return to
+;;; something that does a single-value return (.SPpopj); otherwise, we
+;;; need to make it return multiple values to the real caller. (Unlike
+;;; the PPC, this case only involves creating one frame here, but that
+;;; frame has two return addresses.)
+(define-x8664-vinsn build-lexpr-frame (()
+                                       ()
+                                       ((temp :imm)))
+  (movq (:@ (:apply + (:apply target-nil-value) (x8664::%kernel-global 'x86::ret1valaddr)))
+        (:%q temp))
+  (cmpq (:%q temp)
+        (:%q x8664::ra0))
+  (je :multiple)
+  (pushq (:@ (:apply + (:apply target-nil-value) (x8664::%kernel-global 'x86::lexpr-return1v))))
+  (jmp :finish)
+  :multiple
+  (pushq (:@ (:apply + (:apply target-nil-value) (x8664::%kernel-global 'x86::lexpr-return))))
+  (pushq (:%q temp))
+  :finish
+  (pushq (:%q x8664::rbp))
+  (movq (:%q x8664::rsp) (:%q x8664::rbp)))
+
+
+(define-x8664-vinsn copy-lexpr-argument (()
+					 ((n :u16const))
+					 ((temp :imm)))
+  (movq (:@ (:%q x8664::arg_z)) (:%q temp))
+  (pushq (:@ (:apply ash n x8664::word-shift) (:%q x8664::arg_z) (:%q temp))))
+
+
+(define-x8664-vinsn %current-tcr (((dest :lisp))
+                                 ())
+  (movq (:rcontext x8664::tcr.linear) (:%q dest)))
+
+(define-x8664-vinsn (setq-special :call :subprim-call)
+    (()
+     ((sym :lisp)
+      (val :lisp))
+     ((entry (:label 1))))
+  (:talign 4)
+  (call (:@ .SPspecset))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn set-z-flag-if-istruct-typep (()
+                                                 ((val :lisp)
+                                                  (type :lisp))
+                                                 ((tag :u8)
+                                                  (valtype :lisp)))
+  (xorl (:%l valtype) (:%l valtype))
+  (movl (:%l val) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :have-tag)
+  (movzbl (:@ x8664::misc-subtag-offset (:%q val)) (:%l tag))
+  :have-tag
+  (cmpl (:$b x8664::subtag-istruct) (:%l tag))
+  (jne :do-compare)
+  (movq (:@ x8664::misc-data-offset (:%q val)) (:%q valtype))
+  :do-compare
+  (cmpq (:%q valtype) (:%q type)))
+
+(define-x8664-subprim-call-vinsn (misc-ref) .SPmisc-ref)
+
+(define-x8664-subprim-call-vinsn (ksignalerr) .SPksignalerr)
+
+(define-x8664-subprim-call-vinsn (misc-alloc-init) .SPmisc-alloc-init)
+
+(define-x8664-subprim-call-vinsn (misc-alloc) .SPmisc-alloc) 
+
+(define-x8664-subprim-lea-jmp-vinsn (make-stack-gvector)  .SPstkgvector)
+
+(define-x8664-vinsn load-character-constant (((dest :lisp))
+                                             ((code :u32const))
+                                             ())
+  (movl (:$l (:apply logior (:apply ash code 8) x8664::subtag-character))
+        (:%l dest)))
+
+(define-x8664-vinsn %scharcode8 (((code :imm))
+				((str :lisp)
+				 (idx :imm))
+				((imm :u64)))
+  (movq (:%q idx) (:%q imm))
+  (sarq (:$ub x8664::fixnumshift) (:%q imm))
+  (movzbl (:@ x8664::misc-data-offset (:%q str) (:%q imm)) (:%l imm))
+  (imulq (:$b x8664::fixnumone) (:%q imm)(:%q code)))
+
+(define-x8664-vinsn %scharcode32 (((code :imm))
+				((str :lisp)
+				 (idx :imm))
+				((imm :u64)))
+  (movq (:%q idx) (:%q imm))
+  (sarq (:$ub 1) (:%q imm))
+  (movl (:@ x8664::misc-data-offset (:%q str) (:%q imm)) (:%l imm))
+  (imulq (:$b x8664::fixnumone) (:%q imm)(:%q code)))
+
+(define-x8664-subprim-jump-vinsn (tail-call-sym-slide) .SPtcallsymslide)
+
+(define-x8664-subprim-jump-vinsn (tail-call-sym-vsp) .SPtcallsymvsp)
+
+
+(define-x8664-vinsn character->code (((dest :u32))
+				     ((src :lisp)))
+  (movq (:%q src) (:%q dest))
+  (sarq (:$ub x8664::charcode-shift) (:%q  dest)))
+
+(define-x8664-vinsn adjust-vsp (()
+				((amount :s32const)))
+  ((:and (:pred >= amount -128) (:pred <= amount 127))
+   (addq (:$b amount) (:%q x8664::rsp)))
+  ((:not (:and (:pred >= amount -128) (:pred <= amount 127)))
+   (addq (:$l amount) (:%q x8664::rsp))))
+
+(define-x8664-vinsn (call-subprim-2 :call :subprim-call) (((dest t))
+							  ((spno :s32const)
+							   (y t)
+							   (z t))
+                                                          ((entry (:label 1))))
+  (:talign 4)
+  (call (:@ spno))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+
+
+(define-x8664-vinsn set-macptr-address (()
+					((addr :address)
+					 (src :lisp))
+					())
+  (movq (:%q addr) (:@ x8664::macptr.address (:%q src))))
+
+(define-x8664-vinsn %symbol->symptr (((dest :lisp))
+                                     ((src :lisp))
+                                     ((tag :u8)))
+  :begin
+  (movl (:$l (:apply + (:apply target-nil-value) x8664::nilsym-offset)) (:%l tag))
+  (cmpb (:$b x8664::fulltag-nil) (:%b src))
+  (cmoveq (:%q tag) (:%q dest))
+  (movl (:%l src) (:%l tag))
+  (je :ok)
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-symbol) (:%l tag))
+  (jne :bad)
+
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movq (:% src) (:% dest)))
+  :ok
+  (:anchored-uuo-section :begin)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q src) (:$ub x8664::fulltag-symbol))))
+
+(define-x8664-vinsn symbol-function (((val :lisp))
+                                     ((sym (:lisp (:ne val))))
+                                     ((tag :u8)))
+  :anchor
+  (movq (:@ x8664::symbol.fcell (:%q sym)) (:%q val))
+  (movl (:%l val) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-function) (:%l tag))
+  (jne :bad)
+  
+  (:anchored-uuo-section :anchor)
+  :bad
+  (:anchored-uuo (uuo-error-udf (:%q sym))))
+
+(define-x8664-subprim-jump-vinsn (tail-call-fn-slide) .SPtcallnfnslide)
+
+(define-x8664-vinsn load-double-float-constant (((dest :double-float))
+                                                ((lab :label)
+))
+  (movsd (:@ (:^ lab) (:%q x8664::fn)) (:%xmm dest)))
+
+(define-x8664-vinsn load-single-float-constant (((dest :single-float))
+                                                ((lab :label)
+))
+  (movss (:@ (:^ lab) (:%q x8664::fn)) (:%xmm dest)))
+
+(define-x8664-subprim-call-vinsn (misc-set) .SPmisc-set)
+
+(define-x8664-subprim-lea-jmp-vinsn (slide-values) .SPmvslide)
+
+(define-x8664-subprim-lea-jmp-vinsn (spread-list)  .SPspreadargz)
+
+;;; Even though it's implemented by calling a subprim, THROW is really
+;;; a JUMP (to a possibly unknown destination).  If the destination's
+;;; really known, it should probably be inlined (stack-cleanup, value
+;;; transfer & jump ...)
+(define-x8664-vinsn (throw :jump-unknown) (()
+                                           ()
+                                           ((entry (:label 1))))
+  (leaq (:@ (:^ :back) (:%q x8664::fn)) (:%q x8664::ra0))
+  (:talign 4)
+  (jmp (:@ .SPthrow))
+  :back
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn))
+  (uuo-error-reg-not-tag (:%q x8664::temp0) (:$ub x8664::subtag-catch-frame)))
+
+
+
+(define-x8664-vinsn unbox-base-char (((dest :u64))
+				     ((src :lisp)))
+  :anchor
+  (movq (:%q src) (:%q dest))
+  (shrq (:$ub x8664::charcode-shift) (:%q dest))
+  (cmpb (:$b x8664::subtag-character) (:%b src))
+  (jne :bad)
+  (:anchored-uuo-section :anchor)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q src) (:$ub x8664::subtag-character))))
+
+(define-x8664-subprim-lea-jmp-vinsn (save-values) .SPsave-values)
+
+(define-x8664-subprim-lea-jmp-vinsn (recover-values)  .SPrecover-values)
+
+(define-x8664-subprim-lea-jmp-vinsn (recover-values-for-mvcall) .SPrecover-values-for-mvcall)
+
+(define-x8664-subprim-lea-jmp-vinsn (add-values) .SPadd-values)
+
+(define-x8664-subprim-call-vinsn (make-stack-block)  .SPmakestackblock)
+
+(define-x8664-subprim-call-vinsn (make-stack-block0)  .Spmakestackblock0)
+
+;;; "dest" is preallocated, presumably on a stack somewhere.
+(define-x8664-vinsn store-double (()
+				  ((dest :lisp)
+				   (source :double-float))
+				  ())
+  (movsd (:%xmm source) (:@  x8664::double-float.value (:%q dest))))
+
+(define-x8664-vinsn fixnum->char (((dest :lisp))
+				  ((src :imm))
+				  ((temp :u32)))
+  (movl (:%l src) (:%l temp))
+  (sarl (:$ub (+ x8664::fixnumshift 1)) (:%l temp))
+  (cmpl (:$l (ash #xfffe -1)) (:%l temp))
+  (je :bad-if-eq)
+  (sarl (:$ub (- 11 1)) (:%l temp))
+  (cmpl (:$b (ash #xd800 -11))(:%l temp))
+  :bad-if-eq
+  (movl (:$l (:apply target-nil-value)) (:%l temp))
+  (cmovel (:%l temp) (:%l dest))
+  (je :done)
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movl (:%l src) (:%l dest)))
+  (shll (:$ub (- x8664::charcode-shift x8664::fixnumshift)) (:%l dest))
+  (addl (:$b x8664::subtag-character) (:%l dest))
+  :done)
+
+;;; src is known to be a code for which CODE-CHAR returns non-nil.
+(define-x8664-vinsn code-char->char (((dest :lisp))
+				  ((src :imm))
+				  ())
+  ((:not (:pred =
+                (:apply %hard-regspec-value dest)
+                (:apply %hard-regspec-value src)))
+   (movl (:%l src) (:%l dest)))
+  (shll (:$ub (- x8664::charcode-shift x8664::fixnumshift)) (:%l dest))
+  (addl (:$b x8664::subtag-character) (:%l dest))
+  :done)
+
+
+(define-x8664-vinsn sign-extend-halfword (((dest :imm))
+					  ((src :imm)))
+  (movq (:%q src ) (:%q dest))
+  (shlq (:$ub (- 48 x8664::fixnumshift)) (:%q dest))
+  (sarq (:$ub (- 48 x8664::fixnumshift)) (:%q dest)))
+
+(define-x8664-subprim-jump-vinsn (tail-funcall-gen) .SPtfuncallgen)
+
+(define-x8664-subprim-call-vinsn (gets64) .SPgets64)
+
+(define-x8664-subprim-call-vinsn (getu64) .SPgetu64)
+
+(define-x8664-vinsn %init-gvector (()
+                                   ((v :lisp)
+                                    (nbytes :u32const))
+                                   ((count :imm)))
+  (movl (:$l nbytes) (:%l count))
+  (jmp :test)
+  :loop
+  (popq (:@ x8664::misc-data-offset (:%q v) (:%q count)))
+  :test
+  (subq (:$b x8664::node-size) (:%q count))
+  (jge :loop))
+
+(define-x8664-subprim-jump-vinsn (tail-funcall-slide) .SPtfuncallslide)
+
+(define-x8664-vinsn nth-value (((result :lisp))
+                               ()
+                               ((imm0 :u64)))
+  (leaq (:@ (:%q x8664::rsp) (:%q x8664::nargs)) (:%q imm0))
+  (subq (:@ (:%q imm0)) (:%q x8664::nargs))
+  (movl (:$l (:apply target-nil-value)) (:%l result))
+  (jle :done)
+  ;; I -think- that a CMOV would be safe here, assuming that N wasn't
+  ;; extremely large.  Don't know if we can assume that.
+  (movq (:@ (- x8664::node-size) (:%q x8664::rsp) (:%q x8664::nargs)) (:%q result))
+  :done
+  (leaq (:@ x8664::node-size (:%q imm0)) (:%q x8664::rsp)))
+
+
+(define-x8664-subprim-lea-jmp-vinsn (req-heap-rest-arg) .SPreq-heap-rest-arg)
+
+(define-x8664-subprim-call-vinsn (stack-misc-alloc-init)  .SPstack-misc-alloc-init)
+
+(define-x8664-vinsn fixnum->unsigned-natural (((dest :u64))
+                                              ((src :imm)))
+  (movq (:%q src) (:%q dest))
+  (shrq (:$ub x8664::fixnumshift) (:%q dest)))
+
+(define-x8664-vinsn %debug-trap (()
+                                 ())
+  (uuo-error-debug-trap))
+
+(define-x8664-vinsn double-to-single (((result :single-float))
+                                      ((arg :double-float)))
+  (cvtsd2ss (:%xmm arg) (:%xmm result)))
+
+(define-x8664-vinsn single-to-double (((result :double-float))
+                                      ((arg :single-float)))
+  (cvtss2sd (:%xmm arg) (:%xmm result)))
+
+
+(define-x8664-vinsn alloc-c-frame (()
+                                   ((nwords :u32const)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%mmx x8664::stack-temp))
+  ((:pred < (:apply ash (:apply logandc2 (:apply + nwords 9) 1) x8664::word-shift) 128)
+   (subq (:$b (:apply ash (:apply logandc2 (:apply + nwords 9) 1) x8664::word-shift)) (:rcontext x8664::tcr.foreign-sp)))
+  ((:not (:pred < (:apply ash (:apply logandc2 (:apply + nwords 9) 1) x8664::word-shift) 128))
+   (subq (:$l (:apply ash (:apply logandc2 (:apply + nwords 9) 1) x8664::word-shift)) (:rcontext x8664::tcr.foreign-sp)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q x8664::ra0)))
+  (movq (:% x8664::rbp) (:@ x8664::csp-frame.rbp (:%q x8664::ra0))))
+
+(define-x8664-vinsn alloc-variable-c-frame (()
+                                            ((nwords :imm))
+                                            ((size :s64)))
+  (leaq (:@ (* 9 x8664::node-size) (:%q nwords)) (:%q size))
+  (andb (:$b (lognot x8664::fulltagmask)) (:%b size))
+
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%mmx x8664::stack-temp))
+  (subq (:%q size) (:rcontext x8664::tcr.foreign-sp))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q x8664::ra0)))
+  (movq (:% x8664::rbp) (:@ x8664::csp-frame.rbp (:%q x8664::ra0))))
+
+(define-x8664-vinsn set-c-arg (()
+                               ((arg :u64)
+                                (offset :u32const)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movq (:%q arg) (:@ (:apply + 16 (:apply ash offset 3)) (:%q x8664::ra0))))
+
+(define-x8664-vinsn set-single-c-arg (()
+                                      ((arg :single-float)
+                                       (offset :u32const)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movss (:%xmm arg) (:@ (:apply + 16 (:apply ash offset 3)) (:%q x8664::ra0))))
+
+(define-x8664-vinsn reload-single-c-arg (((arg :single-float))
+                                         ((offset :u32const)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movss (:@ (:apply + 16 (:apply ash offset 3)) (:%q x8664::ra0)) (:%xmm arg)))
+
+(define-x8664-vinsn set-double-c-arg (()
+                                      ((arg :double-float)
+                                       (offset :u32const)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movsd (:%xmm arg) (:@ (:apply + 16 (:apply ash offset 3)) (:%q x8664::ra0))))
+
+(define-x8664-vinsn reload-double-c-arg (((arg :double-float))
+                                         ((offset :u32const)))
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q x8664::ra0))
+  (movsd (:@ (:apply + 16 (:apply ash offset 3)) (:%q x8664::ra0)) (:%xmm arg)))
+
+(define-x8664-subprim-call-vinsn (ff-call)  .SPffcall)
+
+(define-x8664-subprim-call-vinsn (ff-call-return-registers)  .SPffcall-return-registers)
+
+(define-x8664-subprim-call-vinsn (syscall)  .SPsyscall)
+
+(define-x8664-subprim-call-vinsn (setqsym) .SPsetqsym)
+
+(define-x8664-vinsn recover-fn-from-rip (()
+                                         ())
+  (leaq (:@ (:apply - (:^ :disp)) (:%q x8664::rip)) (:%q x8664::fn))
+  :disp)
+
+
+
+(define-x8664-subprim-call-vinsn (makeu64) .SPmakeu64)
+
+(define-x8664-subprim-call-vinsn (makes64) .SPmakes64)
+
+(define-x8664-subprim-lea-jmp-vinsn (stack-cons-list*)  .SPstkconslist-star)
+
+(define-x8664-subprim-lea-jmp-vinsn (list*) .SPconslist-star)
+
+(define-x8664-vinsn make-tsp-vcell (((dest :lisp))
+				    ((closed :lisp))
+				    ((temp :imm)))
+  (subq (:$b (+ x8664::value-cell.size x8664::dnode-size)) (:rcontext x8664::tcr.next-tsp))
+  (movq (:rcontext x8664::tcr.save-tsp) (:%mmx x8664::stack-temp))
+  (movq (:rcontext x8664::tcr.next-tsp) (:%q temp))
+  (movapd (:%xmm x8664::fpzero) (:@ (:%q temp)))
+  (movapd (:%xmm x8664::fpzero) (:@ x8664::dnode-size (:%q temp)))
+  (movq (:%mmx x8664::stack-temp) (:@ (:%q temp)))
+  (movq (:% x8664::rbp) (:@ x8664::tsp-frame.rbp (:%q temp)))  
+  (movq (:%q temp) (:rcontext x8664::tcr.save-tsp))  
+  (movq (:$l x8664::value-cell-header) (:@ x8664::dnode-size (:%q temp)))
+  (movq (:%q closed) (:@ (+ x8664::dnode-size x8664::node-size) (:%q temp)))
+  (leaq (:@ (+ x8664::dnode-size x8664::fulltag-misc) (:%q temp)) (:%q dest)))
+
+(define-x8664-subprim-lea-jmp-vinsn (bind-nil)  .SPbind-nil)
+
+(define-x8664-subprim-lea-jmp-vinsn (bind-self)  .SPbind-self)
+
+(define-x8664-subprim-lea-jmp-vinsn (bind-self-boundp-check)  .SPbind-self-boundp-check)
+
+(define-x8664-subprim-lea-jmp-vinsn (bind)  .SPbind)
+
+(define-x8664-vinsn (dpayback :call :subprim-call) (()
+                                                    ((n :s16const))
+                                                    ((temp (:u32 #.x8664::imm0))
+                                                     (entry (:label 1))))
+  ((:pred > n 0)
+   ((:pred > n 1)
+    (movl (:$l n) (:%l temp))
+    (:talign 4)
+    (call (:@ .SPunbind-n)))
+   ((:pred = n 1)
+    (:talign 4)
+    (call (:@ .SPunbind)))
+   (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn))))  
+
+(define-x8664-subprim-jump-vinsn (tail-call-sym-gen) .SPtcallsymgen)
+
+(define-x8664-subprim-call-vinsn (make-stack-list)  .Spmakestacklist)
+
+(define-x8664-vinsn node-slot-ref  (((dest :lisp))
+				    ((node :lisp)
+				     (cellno :u32const)))
+  (movq (:@ (:apply + x8664::misc-data-offset (:apply ash cellno 3))
+            (:%q node)) (:%q dest)))
+
+(define-x8664-subprim-lea-jmp-vinsn (stack-cons-list)  .SPstkconslist)
+
+
+(define-x8664-vinsn  %slot-ref (((dest :lisp))
+				((instance (:lisp (:ne dest)))
+				 (index :lisp)))
+  (movq (:@ x8664::misc-data-offset (:%q instance) (:%q index)) (:%q dest))
+  (cmpl (:$b x8664::slot-unbound-marker) (:%l dest))
+  (je :bad)
+  :ok
+  (:anchored-uuo-section :ok)
+  :bad
+  (:anchored-uuo (uuo-error-slot-unbound (:%q dest) (:%q instance) (:%q index))))
+
+(define-x8664-vinsn eep.address (((dest t))
+				 ((src (:lisp (:ne dest )))))
+  (movq (:@ (+ (ash 1 x8664::word-shift) x8664::misc-data-offset) (:%q src))
+        (:%q dest))
+  (cmpb (:$b x8664::fulltag-nil) (:%b dest))
+  (je :bad)
+  :ok
+  (:anchored-uuo-section :ok)
+  :bad
+  (:anchored-uuo (uuo-error-eep-unresolved (:%q src) (:%q dest))))
+
+
+(define-x8664-subprim-lea-jmp-vinsn (heap-cons-rest-arg) .SPheap-cons-rest-arg)
+
+(define-x8664-subprim-lea-jmp-vinsn (stack-cons-rest-arg) .SPstack-cons-rest-arg)
+
+(define-x8664-subprim-lea-jmp-vinsn (make-stack-vector)  .SPmkstackv)
+
+(define-x8664-vinsn %current-frame-ptr (((dest :imm))
+					())
+  (movq (:%q x8664::rbp) (:%q dest)))
+
+(define-x8664-vinsn %foreign-stack-pointer (((dest :imm))
+                                            ())
+  (movq (:rcontext x8664::tcr.foreign-sp) (:%q dest)))
+
+
+(define-x8664-vinsn %set-scharcode8 (()
+				    ((str :lisp)
+				     (idx :imm)
+				     (code :imm))
+				    ((imm :u64)
+				     (imm1 :u64)))
+  (movq (:%q code) (:%q imm1))
+  (movq (:%q idx) (:%q imm))
+  (shrq (:$ub x8664::fixnumshift) (:%q imm1))
+  (shrq (:$ub x8664::word-shift) (:%q imm))
+  (movb (:%b imm1) (:@ x8664::misc-data-offset (:%q str) (:%q imm))))
+
+
+(define-x8664-vinsn %set-scharcode32 (()
+				    ((str :lisp)
+				     (idx :imm)
+				     (code :imm))
+				    ((imm :u64)
+				     (imm1 :u64)))
+  (movq (:%q code) (:%q imm1))
+  (movq (:%q idx) (:%q imm))
+  (shrq (:$ub x8664::fixnumshift) (:%q imm1))
+  (shrq (:$ub 1) (:%q imm))
+  (movl (:%l imm1) (:@ x8664::misc-data-offset (:%q str) (:%q imm))))
+
+
+
+
+(define-x8664-vinsn pop-argument-registers (()
+                                            ())
+  (testl (:%l x8664::nargs) (:%l x8664::nargs))
+  (je :done)
+  (rcmpl (:%l x8664::nargs) (:$b (ash 2 x8664::word-shift)))
+  (popq (:%q x8664::arg_z))
+  (jb :done)
+  (popq (:%q x8664::arg_y))
+  (je :done)
+  (popq (:%q x8664::arg_x))
+  :done)
+
+(define-x8664-vinsn %symptr->symvector (((target :lisp))
+                                        ((target :lisp)))
+  (subb (:$b (- x8664::fulltag-symbol x8664::fulltag-misc)) (:%b target)))
+
+(define-x8664-vinsn %symvector->symptr (((target :lisp))
+                                        ((target :lisp)))
+  (addb (:$b (- x8664::fulltag-symbol x8664::fulltag-misc)) (:%b target)))
+
+
+(define-x8664-subprim-lea-jmp-vinsn (spread-lexpr)  .SPspread-lexpr-z)
+
+(define-x8664-vinsn mem-ref-double-float (((dest :double-float))
+                                           ((src :address)
+                                            (index :s64)))
+  (movsd (:@ (:%q src) (:%q index)) (:%xmm dest)))
+
+(define-x8664-vinsn mem-ref-single-float (((dest :single-float))
+                                           ((src :address)
+                                            (index :s64)))
+  (movss (:@ (:%q src) (:%q index)) (:%xmm dest)))
+
+(define-x8664-vinsn zero-extend-nargs (()
+                                       ())
+  (movzwl (:%w x8664::nargs) (:%l x8664::nargs)))
+
+(define-x8664-vinsn load-adl (()
+			      ((n :u32const)))
+  (movl (:$l n) (:%l x8664::nargs)))
+
+(define-x8664-subprim-lea-jmp-vinsn (macro-bind) .SPmacro-bind)
+
+(define-x8664-subprim-lea-jmp-vinsn (destructuring-bind-inner) .SPdestructuring-bind-inner)
+
+(define-x8664-subprim-lea-jmp-vinsn  (destructuring-bind) .SPdestructuring-bind)
+
+(define-x8664-vinsn symbol-ref (((dest :lisp))
+                                ((src :lisp)
+                                 (cellno :u32const)))
+  (movq (:@ (:apply + (- x8664::node-size x8664::fulltag-symbol)
+                    (:apply ash cellno 3))
+              (:%q src)) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-bit-fixnum (((dest :lisp))
+                                          ((src :address)
+                                           (offset :s32const))
+                                          ((temp :u32)))
+  ((:pred = 0 (:apply ash offset -6))
+   (btq (:$ub (:apply logand 63 offset))
+        (:@  (:%q src))))
+  ((:not (:pred = 0 (:apply ash offset -6)))
+   (btq (:$ub (:apply logand 63 offset))
+        (:@ (:apply ash (:apply ash offset -6) 3) (:%q src))))
+  (movl (:$l x8664::fixnumone) (:%l temp))
+  (leaq (:@ (- x8664::fixnumone) (:%q temp)) (:%q dest))
+  (cmovbl (:%l temp) (:%l dest)))
+
+(define-x8664-vinsn mem-ref-c-bit (((dest :lisp))
+                                   ((src :address)
+                                    (offset :s32const))
+                                   ((temp :u32)))
+  ((:pred = 0 (:apply ash offset -6))
+   (btq (:$ub (:apply logand 63 offset))
+        (:@  (:%q src))))
+  ((:not (:pred = 0 (:apply ash offset -6)))
+   (btq (:$ub (:apply logand 63 offset))
+        (:@ (:apply ash (:apply ash offset -6) 3) (:%q src))))
+  (setb (:%b temp))
+  (movzbl (:%b temp) (:%l dest)))
+
+(define-x8664-vinsn mem-ref-bit-fixnum (((dest :lisp)
+                                         (src :address))
+                                        ((src :address)
+                                         (offset :lisp))
+                                        ((temp :u32)))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub (+ 6 x8664::fixnumshift)) (:%q temp))
+  (leaq (:@ (:%q src) (:%q temp) 8) (:%q src))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub x8664::fixnumshift) (:%q temp))
+  (andl (:$l 63) (:%l temp))
+  (btq (:%q temp) (:@ (:%q src)))
+  (movl (:$l x8664::fixnumone) (:%l temp))
+  (leaq (:@ (- x8664::fixnumone) (:%q temp)) (:%q dest))
+  (cmovbl (:%l temp) (:%l dest)))
+
+(define-x8664-vinsn mem-ref-bit (((dest :lisp)
+                                  (src :address))
+                                 ((src :address)
+                                  (offset :lisp))
+                                 ((temp :u32)))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub (+ 6 x8664::fixnumshift)) (:%q temp))
+  (leaq (:@ (:%q src) (:%q temp) 8) (:%q src))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub x8664::fixnumshift) (:%q temp))
+  (andl (:$l 63) (:%l temp))
+  (btq (:%q temp) (:@ (:%q src)))
+  (setb (:%b temp))
+  (movzbl (:%b temp) (:%l dest)))
+
+  
+(define-x8664-vinsn mem-set-c-bit-0 (()
+				     ((src :address)
+                                      (offset :s32const)))
+  
+  ((:pred = 0 (:apply ash offset -6))
+   (btrq (:$ub (:apply logand 63 offset))
+        (:@  (:%q src))))
+  ((:not (:pred = 0 (:apply ash offset -6)))
+   (btrq (:$ub (:apply logand 63 offset))
+         (:@ (:apply ash (:apply ash offset -6) 3) (:%q src)))))
+
+(define-x8664-vinsn mem-set-c-bit-1 (()
+				     ((src :address)
+                                      (offset :s32const)))
+  
+  ((:pred = 0 (:apply ash offset -6))
+   (btsq (:$ub (:apply logand 63 offset))
+         (:@  (:%q src))))
+  ((:not (:pred = 0 (:apply ash offset -6)))
+   (btsq (:$ub (:apply logand 63 offset))
+         (:@ (:apply ash (:apply ash offset -6) 3) (:%q src)))))
+
+(define-x8664-vinsn mem-set-c-bit-variable-value (()
+                                                  ((src :address)
+                                                   (offset :s32const)
+                                                   (value :lisp)))
+  (testq (:%q value) (:%q value))
+  (jne :set)
+  ((:pred = 0 (:apply ash offset -6))
+   (btrq (:$ub (:apply logand 63 offset))
+        (:@  (:%q src))))
+  ((:not (:pred = 0 (:apply ash offset -6)))
+   (btrq (:$ub (:apply logand 63 offset))
+         (:@ (:apply ash (:apply ash offset -6) 3) (:%q src))))
+  (jmp :done)
+  :set
+  ((:pred = 0 (:apply ash offset -6))
+   (btsq (:$ub (:apply logand 63 offset))
+         (:@  (:%q src))))
+  ((:not (:pred = 0 (:apply ash offset -6)))
+   (btsq (:$ub (:apply logand 63 offset))
+         (:@ (:apply ash (:apply ash offset -6) 3) (:%q src))))
+  :done)
+
+
+(define-x8664-vinsn mem-set-bit-0 (((src :address))
+                                   ((src :address)
+                                    (offset :lisp))
+                                   ((temp :u32)))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub (+ 6 x8664::fixnumshift)) (:%q temp))
+  (leaq (:@ (:%q src) (:%q temp) 8) (:%q src))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub x8664::fixnumshift) (:%q temp))
+  (andl (:$l 63) (:%l temp))
+  (btrq (:%q temp) (:@ (:%q src))))
+
+(define-x8664-vinsn mem-set-bit-1 (((src :address))
+                                   ((src :address)
+                                    (offset :lisp))
+                                   ((temp :u32)))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub (+ 6 x8664::fixnumshift)) (:%q temp))
+  (leaq (:@ (:%q src) (:%q temp) 8) (:%q src))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub x8664::fixnumshift) (:%q temp))
+  (andl (:$l 63) (:%l temp))
+  (btsq (:%q temp) (:@ (:%q src))))
+
+
+(define-x8664-vinsn mem-set-bit-variable-value (((src :address))
+                                                ((src :address)
+                                                 (offset :lisp)
+                                                 (value :lisp))
+                                                ((temp :u32)))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub (+ 6 x8664::fixnumshift)) (:%q temp))
+  (leaq (:@ (:%q src) (:%q temp) 8) (:%q src))
+  (movq (:%q offset) (:%q temp))
+  (shrq (:$ub x8664::fixnumshift) (:%q temp))
+  (andl (:$l 63) (:%l temp))
+  (testq (:%q value) (:%q value))
+  (jne :set)
+  (btrq (:%q temp) (:@ (:%q src)))
+  (jmp :done)
+  :set
+  (btsq (:%q temp) (:@ (:%q src)))
+  :done)
+
+(define-x8664-vinsn %natural+  (((result :u64))
+                               ((result :u64)
+                                (other :u64)))
+  (addq (:%q other) (:%q result)))
+
+(define-x8664-vinsn %natural+-c (((result :u64))
+                                ((result :u64)
+                                 (constant :s32const)))
+  (addq (:$l constant) (:%q result)))
+
+(define-x8664-vinsn %natural-  (((result :u64))
+                                ((result :u64)
+                                 (other :u64)))
+  (subq (:%q other) (:%q result)))
+
+(define-x8664-vinsn %natural--c (((result :u64))
+                                ((result :u64)
+                                 (constant :s32const)))
+  (subq (:$l constant) (:%q result)))
+
+(define-x8664-vinsn %natural-logior (((result :u64))
+                                    ((result :u64)
+                                     (other :u64)))
+  (orq (:%q other) (:%q result)))
+
+(define-x8664-vinsn %natural-logior-c (((result :u64))
+                                      ((result :u64)
+                                       (constant :s32const)))
+  (orq (:$l constant) (:%q result)))
+
+(define-x8664-vinsn %natural-logand (((result :u64))
+                                    ((result :u64)
+                                     (other :u64)))
+  (andq (:%q other) (:%q result)))
+
+(define-x8664-vinsn %natural-logand-c (((result :u64))
+                                      ((result :u64)
+                                       (constant :s32const)))
+  (andq (:$l constant) (:%q result)))
+
+(define-x8664-vinsn %natural-logxor (((result :u64))
+                                    ((result :u64)
+                                     (other :u64)))
+  (xorq (:%q other) (:%q result)))
+
+(define-x8664-vinsn %natural-logxor-c (((result :u64))
+                                       ((result :u64)
+                                        (constant :s32const)))
+  (xorq (:$l constant) (:%q result)))
+
+(define-x8664-vinsn natural-shift-left (((dest :u64))
+                                        ((dest :u64)
+                                         (amt :u8const)))
+  (shlq (:$ub amt) (:%q dest)))
+
+(define-x8664-vinsn natural-shift-right (((dest :u64))
+                                         ((dest :u64)
+                                          (amt :u8const)))
+  (shrq (:$ub amt) (:%q dest)))
+
+(define-x8664-vinsn trap-unless-simple-array-2 (()
+                                                ((object :lisp)
+                                                 (expected-flags :u32const)
+                                                 (type-error :u8const))
+                                                ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8664::subtag-arrayH) (:@ x8664::misc-subtag-offset (:%q object)))
+  (jne :bad)
+  (cmpq (:$b (ash 2 x8664::fixnumshift)) (:@ x8664::arrayH.rank (:%q object)))
+  (jne :bad)
+  (cmpq (:$l (:apply ash expected-flags x8664::fixnumshift)) (:@ x8664::arrayH.flags (:%q object)))
+  (jne :bad)
+
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub type-error))))
+
+(define-x8664-vinsn trap-unless-simple-array-3 (()
+                                                ((object :lisp)
+                                                 (expected-flags :u32const)
+                                                 (type-error :u8const))
+                                                ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :bad)
+  (cmpb (:$b x8664::subtag-arrayH) (:@ x8664::misc-subtag-offset (:%q object)))
+  (jne :bad)
+  (cmpq (:$b (ash 3 x8664::fixnumshift)) (:@ x8664::arrayH.rank (:%q object)))
+  (jne :bad)
+  (cmpq (:$l (:apply ash expected-flags x8664::fixnumshift)) (:@ x8664::arrayH.flags (:%q object)))
+  (jne :bad)
+  (:anchored-uuo-section :again)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q object) (:$ub type-error))))
+  
+(define-x8664-vinsn trap-unless-array-header (()
+                                              ((object :lisp))
+                                              ((tag :u8)))
+  :again
+  (movl (:%l object) (:%l tag))
+  (andl (:$b x8664::tagmask) (:%l tag))
+  (cmpl (:$b x8664::tag-misc) (:%l tag))
+  (jne :trap)
+  (cmpb (:$b x8664::subtag-arrayH) (:@ x8664::misc-subtag-offset (:%q object)))
+  (jne :trap)
+
+  (:anchored-uuo-section :again)
+  :trap
+  (:anchored-uuo (uuo-error-reg-not-tag (:%q object) (:$ub x8664::subtag-arrayH))))
+
+(define-x8664-vinsn check-arrayH-rank (()
+                                       ((header :lisp)
+                                        (expected :u32const))
+                                       ((rank :imm)))
+  :anchor
+  (movl (:$l (:apply ash expected x8664::fixnumshift)) (:%l rank))
+  (cmpq (:@ x8664::arrayH.rank (:%q header)) (:%q rank))
+  (jne :bad)
+  (:anchored-uuo-section :anchor)
+  :bad
+  (:anchored-uuo (uuo-error-array-rank (:%q header) (:%q rank))))
+
+(define-x8664-vinsn check-arrayH-flags (()
+                                       ((header :lisp)
+                                        (expected :u32const)
+                                        (type-error :u8const)))
+  :anchor
+  (cmpq (:$l (:apply ash expected x8664::fixnumshift))
+        (:@ x8664::arrayH.flags (:%q header)))
+  (jne :bad)
+  (:anchored-uuo-section :anchor)
+  :bad
+  (:anchored-uuo (uuo-error-reg-not-type (:%q header) (:$ub type-error))))
+
+(define-x8664-vinsn misc-ref-c-u16  (((dest :u16))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (movzwl (:@ (:apply + x8664::misc-data-offset (:apply ash idx 1)) (:%q v)) (:%l dest)))
+
+(define-x8664-vinsn misc-ref-c-s16  (((dest :s16))
+				     ((v :lisp)
+				      (idx :u32const))
+				     ())
+  (movswq (:@ (:apply + x8664::misc-data-offset (:apply ash idx 1)) (:%q v)) (:%q dest)))
+
+(define-x8664-vinsn misc-set-single-float (()
+					   ((val :single-float)
+					    (v :lisp)
+					    (scaled-idx :u32)))
+  (movss (:%xmm val) (:@ x8664::misc-data-offset (:% v) (:% scaled-idx))))
+
+(define-x8664-vinsn u16->u32 (((dest :u32))
+			      ((src :u16)))
+  (movzwl (:%w src) (:%l dest)))
+
+(define-x8664-vinsn u8->u32 (((dest :u32))
+			     ((src :u8)))
+  (movzbl (:%b src) (:%l dest)))
+
+
+(define-x8664-vinsn s16->s32 (((dest :s32))
+			      ((src :s16)))
+  (movswl (:%w src) (:%l dest)))
+
+(define-x8664-vinsn s8->s32 (((dest :s32))
+			     ((src :s8)))
+  (movsbl (:%b src) (:%l dest)))
+
+(define-x8664-subprim-jump-vinsn (tail-call-fn-gen) .SPtcallnfngen)
+
+(define-x8664-subprim-jump-vinsn (tail-call-fn-vsp) .SPtcallnfnvsp)
+
+(define-x8664-vinsn set-eq-bit (()
+                                ())
+  (testb (:%b x8664::arg_z) (:%b x8664::arg_z)))
+
+(define-x8664-vinsn %schar8 (((char :imm))
+			    ((str :lisp)
+			     (idx :imm))
+			    ((imm :u32)))
+  (movq (:%q idx) (:%q imm))
+  (shrq (:$ub x8664::fixnumshift) (:%q imm))
+  (movzbl (:@ x8664::misc-data-offset (:%q str) (:%q imm)) (:%l imm))
+  (shll (:$ub x8664::charcode-shift) (:%l imm))
+  (leaq (:@ x8664::subtag-character (:%q imm)) (:%q char)))
+
+(define-x8664-vinsn %schar32 (((char :imm))
+                              ((str :lisp)
+                               (idx :imm))
+                              ((imm :u32)))
+  (movq (:%q idx) (:%q imm))
+  (shrq (:$ub 1) (:%q imm))
+  (movl (:@ x8664::misc-data-offset (:%q str) (:%q imm)) (:%l imm))
+  (shll (:$ub x8664::charcode-shift) (:%l imm))
+  (leaq (:@ x8664::subtag-character (:%q imm)) (:%q char)))
+
+
+(define-x8664-vinsn %set-schar8 (()
+                                 ((str :lisp)
+                                  (idx :imm)
+                                  (char :imm))
+                                 ((imm0 :u64)
+                                  (imm1 :u64)))
+  (movq (:%q idx) (:%q imm0))
+  (movl (:%l char) (:%l imm1))
+  (shrq (:$ub x8664::fixnumshift) (:%q imm0))
+  (shrl (:$ub x8664::charcode-shift) (:%l imm1))
+  (movb (:%b imm1) (:@ x8664::misc-data-offset (:%q str) (:%q imm0))))
+
+(define-x8664-vinsn %set-schar32 (()
+                                 ((str :lisp)
+                                  (idx :imm)
+                                  (char :imm))
+                                 ((imm0 :u64)
+                                  (imm1 :u64)))
+  (movq (:%q idx) (:%q imm0))
+  (movl (:%l char) (:%l imm1))
+  (shrq (:$ub 1) (:%q imm0))
+  (shrl (:$ub x8664::charcode-shift) (:%l imm1))
+  (movl (:%l imm1) (:@ x8664::misc-data-offset (:%q str) (:%q imm0))))
+
+(define-x8664-vinsn misc-set-c-single-float (((val :single-float))
+					     ((v :lisp)
+					      (idx :u32const)))
+  (movss (:%xmm val) (:@ (:apply + x8664::misc-data-offset (:apply ash idx 2)) (:%q v))))
+
+(define-x8664-vinsn array-data-vector-ref (((dest :lisp))
+					   ((header :lisp)))
+  (movq (:@ x8664::arrayH.data-vector (:%q header)) (:%q dest)))
+
+(define-x8664-subprim-call-vinsn (subtag-misc-ref) .SPsubtag-misc-ref)
+
+(define-x8664-subprim-call-vinsn (subtag-misc-set) .SPsubtag-misc-set)
+
+(define-x8664-vinsn mem-ref-c-absolute-u8 (((dest :u8))
+                                           ((addr :s32const)))
+  (movzbl (:@ addr) (:%l dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-s8 (((dest :s8))
+                                           ((addr :s32const)))
+  (movsbq (:@ addr) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-u16 (((dest :u16))
+                                           ((addr :s32const)))
+  (movzwl (:@ addr) (:%l dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-s16 (((dest :s16))
+                                           ((addr :s32const)))
+  (movswq (:@ addr) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-fullword (((dest :u32))
+                                                 ((addr :s32const)))
+  (movl (:@ addr) (:%l dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-signed-fullword (((dest :s32))
+                                                        ((addr :s32const)))
+  (movslq (:@ addr) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-doubleword (((dest :s64))
+                                                   ((addr :s32const)))
+  (movq (:@ addr) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-signed-doubleword (((dest :s64))
+                                                          ((addr :s32const)))
+  (movq (:@ addr) (:%q dest)))
+
+(define-x8664-vinsn mem-ref-c-absolute-natural (((dest :u64))
+                                                   ((addr :s32const)))
+  (movq (:@ addr) (:%q dest)))
+
+(define-x8664-vinsn event-poll (()
+                                ())
+  (btrq (:$ub 63) (:rcontext x8664::tcr.interrupt-pending))
+  (jae :no-interrupt)
+  (ud2a)
+  (:byte 2)
+  :no-interrupt)
+
+;;; Return dim1 (unboxed)
+(define-x8664-vinsn check-2d-bound (((dim :u64))
+				    ((i :imm)
+				     (j :imm)
+				     (header :lisp)))
+  :anchor
+  (cmpq (:@ (+ x8664::misc-data-offset (* 8 x8664::arrayH.dim0-cell)) (:%q header)) (:%q i))
+  (jae :bad-i)
+  (movq (:@ (+ x8664::misc-data-offset (* 8 (1+ x8664::arrayH.dim0-cell))) (:%q header))
+        (:%q dim))
+  (cmpq (:%q dim) (:%q j))
+  (jae :bad-j)
+  (sarq (:$ub x8664::fixnumshift) (:%q dim))
+  (:anchored-uuo-section :anchor)
+  :bad-i
+  (:anchored-uuo (uuo-error-array-bounds (:%q i) (:%q header)))
+  (:anchored-uuo-section :anchor)
+  :bad-j
+  (:anchored-uuo (uuo-error-array-bounds (:%q j) (:%q header))))
+
+;;; Return dim1, dim2 (unboxed)
+(define-x8664-vinsn check-3d-bound (((dim1 :u64)
+                                     (dim2 :u64))
+				    ((i :imm)
+				     (j :imm)
+                                     (k :imm)
+				     (header :lisp)))
+  :anchor
+  (cmpq (:@ (+ x8664::misc-data-offset (* 8 x8664::arrayH.dim0-cell)) (:%q header)) (:%q i))
+  (jae :bad-i)
+  (movq (:@ (+ x8664::misc-data-offset (* 8 (1+ x8664::arrayH.dim0-cell))) (:%q header)) (:%q dim1))
+  (cmpq (:%q dim1) (:%q j))
+  (jae :bad-j)
+  (sarq (:$ub x8664::fixnumshift) (:%q dim1))
+  (movq (:@ (+ x8664::misc-data-offset (* 8 (+ 2 x8664::arrayH.dim0-cell))) (:%q header)) (:%q dim2))
+  (cmpq (:%q dim2) (:%q k))
+  (jae :bad-k)
+  (sarq (:$ub x8664::fixnumshift) (:%q dim2))
+  (:anchored-uuo-section :anchor)
+  :bad-i
+  (:anchored-uuo (uuo-error-array-bounds (:%q i) (:%q header)))
+  (:anchored-uuo-section :anchor)
+  :bad-j
+  (:anchored-uuo (uuo-error-array-bounds (:%q j) (:%q header)))
+  (:anchored-uuo-section :anchor)
+  :bad-k
+  (:anchored-uuo (uuo-error-array-bounds (:%q k) (:%q header)))
+  )
+
+
+(define-x8664-vinsn 2d-dim1 (((dest :u64))
+			     ((header :lisp)))
+  (movq (:@ (+ x8664::misc-data-offset (* 8 (1+ x8664::arrayH.dim0-cell))) (:%q header))
+        (:%q dest))
+  (sarq (:$ub x8664::fixnumshift) (:%q dest)))
+
+
+(define-x8664-vinsn 3d-dims (((dim1 :u64)
+                              (dim2 :u64))
+			     ((header :lisp)))
+  (movq (:@ (+ x8664::misc-data-offset (* 8 (1+ x8664::arrayH.dim0-cell))) (:%q header)) (:%q dim1))
+  (movq (:@ (+ x8664::misc-data-offset (* 8 (+ 2 x8664::arrayH.dim0-cell))) (:%q header)) (:%q dim2))
+  (sarq (:$ub x8664::fixnumshift) (:%q dim1))
+  (sarq (:$ub x8664::fixnumshift) (:%q dim2)))
+
+(define-x8664-vinsn 2d-unscaled-index (((dest :imm)
+                                        (dim1 :u64))
+				       ((dim1 :u64)
+                                        (i :imm)
+					(j :imm)))
+
+  (imulq (:%q i) (:%q dim1))
+  (leaq (:@ (:%q j) (:%q dim1)) (:%q dest)))
+
+
+;; dest <- (+ (* i dim1 dim2) (* j dim2) k)
+(define-x8664-vinsn 3d-unscaled-index (((dest :imm)
+                                        (dim1 :u64)
+                                        (dim2 :u64))
+				       ((dim1 :u64)
+                                        (dim2 :u64)
+                                        (i :imm)
+					(j :imm)
+                                        (k :imm)))
+  (imulq (:%q dim2) (:%q dim1))
+  (imulq (:%q j) (:%q dim2))
+  (imulq (:%q i) (:%q dim1))
+  (addq (:%q dim1) (:%q dim2))
+  (leaq (:@ (:%q k) (:%q dim2)) (:%q dest)))
+
+(define-x8664-vinsn branch-unless-both-args-fixnums (()
+                                                     ((a :lisp)
+                                                      (b :lisp)
+                                                      (dest :label))
+                                                     ((tag :u8)))
+  (movl (:%l a) (:%l tag))
+  (orl (:%l b) (:%l tag))
+  (testb (:$b x8664::fixnummask) (:%b tag))
+  (jne dest))
+
+(define-x8664-vinsn branch-unless-arg-fixnum (()
+                                              ((a :lisp)
+                                               (dest :label)))
+  (testb (:$b x8664::fixnummask) (:%b a))
+  (jne dest))
+
+(define-x8664-vinsn fixnum->single-float (((f :single-float))
+                                          ((arg :lisp))
+                                          ((unboxed :s64)))
+  (movq (:%q arg) (:%q unboxed))
+  (sarq (:$ub x8664::fixnumshift) (:%q unboxed))
+  (cvtsi2ssq (:%q unboxed) (:%xmm f)))
+
+(define-x8664-vinsn fixnum->double-float (((f :double-float))
+                                          ((arg :lisp))
+                                          ((unboxed :s64)))
+  (movq (:%q arg) (:%q unboxed))
+  (sarq (:$ub x8664::fixnumshift) (:%q unboxed))
+  (cvtsi2sdq (:%q unboxed) (:%xmm f)))
+
+
+(define-x8664-vinsn xchg-registers (()
+                                    ((a t)
+                                     (b t)))
+  (xchgq (:%q a) (:%q b)))
+
+(define-x8664-vinsn establish-fn (()
+                                  ()
+                                  ((entry (:label 1))))
+  (leaq (:@ (:^ entry) (:% x8664::rip)) (:%q x8664::fn)))
+
+(define-x8664-vinsn align-loop-head (()
+                                     ()
+                                     ()))
+
+(queue-fixup
+ (fixup-x86-vinsn-templates
+  *x8664-vinsn-templates*
+  x86::*x86-opcode-template-lists* *x8664-backend*))
+
+(provide "X8664-VINSNS")
+
Index: /branches/new-random/compiler/X86/x86-arch.lisp
===================================================================
--- /branches/new-random/compiler/X86/x86-arch.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/x86-arch.lisp	(revision 13309)
@@ -0,0 +1,202 @@
+;;;-*- Mode: Lisp; Package: (X86 :use CL) -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(defpackage "X86"
+  (:use "CL"))
+
+(in-package "X86")
+
+(require "ARCH")
+
+;;; Kernel globals are allocated "below" nil.  This list (used to map
+;;; symbolic names to rnil-relative offsets) must (of course) exactly
+;;; match the kernel's notion of where things are.
+;;; The order here matches "ccl:lisp-kernel;lisp_globals.h" & the
+;;; lisp_globals record in "ccl:lisp-kernel;constants.s"
+(defparameter *x86-kernel-globals*
+  '(get-tcr				; callback to obtain (real) tcr
+    tcr-count
+    interrupt-signal			; used by PROCESS-INTERRUPT
+    kernel-imports                      ; some things we need to have imported for us.
+    objc-2-personality
+    savetoc                  ; used to save TOC on some platforms
+    saver13                             ; used to save r13 on some platforms
+    subprims-base                       ; start of dynamic subprims jump table
+    ret1valaddr                         ; magic multiple-values return address.
+    tcr-key                             ; tsd key for thread's tcr
+    area-lock                           ; serialize access to gc
+    exception-lock			; serialize exception handling
+    static-conses                       ; when FREEZE is in effect
+    default-allocation-quantum          ; log2_heap_segment_size, as a fixnum.
+    intflag				; interrupt-pending flag
+    gc-inhibit-count                    ; for gc locking
+    refbits                             ; oldspace refbits
+    oldspace-dnode-count                ; number of dnodes in dynamic space that are older than
+                                        ; youngest generation
+    altivec-present                     ; non-zero if cpu supports AltiVec 
+    fwdnum                              ; fixnum: GC "forwarder" call count.
+    gc-count                            ; fixnum: GC call count.
+    gcable-pointers                     ; linked-list of weak macptrs.
+    heap-start                          ; start of lisp heap
+    heap-end                            ; end of lisp heap
+    statically-linked                   ; true if the lisp kernel is statically linked
+    stack-size                          ; value of --stack-size arg
+    objc-2-begin-catch                  ; objc_begin_catch
+    kernel-path
+    all-areas                           ; doubly-linked area list
+    lexpr-return                        ; multiple-value lexpr return address
+    lexpr-return1v                      ; single-value lexpr return address
+    in-gc                               ; non-zero when GC-ish thing active
+    free-static-conses                  ; fixnum
+    objc-2-end-catch                    ; _objc_end_catch
+    short-float-zero                    ; low half of 1.0d0
+    double-float-one                    ; high half of 1.0d0
+    static-cons-area                    ; 
+    exception-saved-registers           ; saved registers from exception frame
+    oldest-ephemeral                    ; doublenode address of oldest ephemeral object or 0
+    tenured-area                        ; the tenured_area.
+    errno                               ; address of C lib errno
+    argv                                ; address of C lib argv
+    host-platform                       ; 0 on MacOS, 1 on PPC Linux, 2 on VxWorks ...
+    batch-flag				; non-zero if --batch specified
+    unwind-resume			; _Unwind_Resume
+    weak-gc-method                      ; weak gc algorithm.
+    image-name				; current image name
+    initial-tcr                         ; initial thread's context record
+    ))
+
+;;; The order here matches "ccl:lisp-kernel;lisp_globals.h" and the nrs record
+;;; in "ccl:lisp-kernel;constants.s".
+(defparameter *x86-nil-relative-symbols*
+  '(t
+    nil
+    ccl::%err-disp
+    ccl::cmain
+    eval
+    ccl::apply-evaluated-function
+    error    
+    ccl::%defun
+    ccl::%defvar
+    ccl::%defconstant
+    ccl::%macro
+    ccl::%kernel-restart
+    *package*
+    ccl::*total-bytes-freed*
+    :allow-other-keys    
+    ccl::%toplevel-catch%
+    ccl::%toplevel-function%
+    ccl::%pascal-functions%    
+    ccl::*all-metered-functions*
+    ccl::*total-gc-microseconds*
+    ccl::%builtin-functions%
+    ccl::%unbound-function%
+    ccl::%init-misc
+    ccl::%macro-code%
+    ccl::%closure-code%
+    ccl::%new-gcable-ptr
+    ccl::*gc-event-status-bits*
+    ccl::*post-gc-hook*
+    ccl::%handlers%
+    ccl::%all-packages%
+    ccl::*keyword-package* 
+    ccl::%finalization-alist%
+    ccl::%foreign-thread-control
+    ))
+
+;;; Old (and slightly confusing) name; NIL used to be in a register.
+(defparameter *x86-nilreg-relative-symbols* *x86-nil-relative-symbols*)
+
+
+;;; mxcsr bits.  (Unlike the convention used on the PPC, bit 0 is the
+;;; least significant bit of the containing byte/word.)
+
+(ccl::defenum (:prefix "MXCSR-" :suffix "-BIT")
+  ie                                    ;invalid exception
+  de                                    ;denormal exception
+  ze                                    ;divide-by-zero exception
+  oe                                    ;overflow exception
+  ue                                    ;underflow exception
+  pe                                    ;precision exception
+  daz                                   ;denorms-are-zeros (not-IEEE)
+  im                                    ;invalid masked
+  dm                                    ;denormals masked
+  zm                                    ;divide-by-zero masked
+  om                                    ;overflow masked
+  um                                    ;underflow masked
+  pm                                    ;precision masked
+  rc0                                   ;rounding control bit 0
+  rc1                                   ;rounding control bit 1
+  fz                                    ;flush-to-zero (not-IEEE)
+)
+
+(defconstant mxcsr-status-mask
+  (logior (ash 1 mxcsr-ie-bit)
+          (ash 1 mxcsr-de-bit)
+          (ash 1 mxcsr-ze-bit)
+          (ash 1 mxcsr-oe-bit)
+          (ash 1 mxcsr-ue-bit)
+          (ash 1 mxcsr-pe-bit)))
+
+(defconstant mxcsr-control-and-rounding-mask
+  (logior (ash 1 mxcsr-im-bit)
+          (ash 1 mxcsr-dm-bit)
+          (ash 1 mxcsr-zm-bit)
+          (ash 1 mxcsr-om-bit)
+          (ash 1 mxcsr-um-bit)
+          (ash 1 mxcsr-pm-bit)
+          (ash 1 mxcsr-rc0-bit)
+          (ash 1 mxcsr-rc1-bit)))
+
+;;; There's a fairly hairy method of determining which MXCSR bits are
+;;; available on a given proccessor version.  In practice, the bits
+;;; that might not be supported are bits that select non-IEE754-compliant
+;;; behavior (DenormsAreZeros and FlushtoZerop), and we don't really
+;;; want to activate either of those things, anyway.
+
+(defconstant mxcsr-write-mask (lognot (logior (ash 1 mxcsr-daz-bit)
+                                              (ash 1 mxcsr-fz-bit))))
+
+
+
+;;; Condition bitfields, used in jcc, cmovcc, setcc.
+(defconstant x86-o-bits #x0)
+(defconstant x86-no-bit #x1)
+(defconstant x86-b-bits #x2)
+(defconstant x86-ae-bits #x3)
+(defconstant x86-e-bits #x4)
+(defconstant x86-ne-bits #x5)
+(defconstant x86-be-bits #x6)
+(defconstant x86-a-bits #x7)
+(defconstant x86-s-bits #x8)
+(defconstant x86-ns-bits #x9)
+(defconstant x86-pe-bits #xa)
+(defconstant x86-po-bits #xb)
+(defconstant x86-l-bits #xc)
+(defconstant x86-ge-bits #xd)
+(defconstant x86-le-bits #xe)
+(defconstant x86-g-bits #xf)
+
+;;; Bits in the xFLAGS register
+(defconstant x86-carry-flag-bit 0)
+(defconstant x86-parity-flag-bit 2)
+(defconstant x86-aux-carry-flag-bit 4)
+(defconstant x86-zero-flag-bit 6)
+(defconstant x86-sign-flag-bit 7)
+(defconstant x86-direction-flag-bit 10)
+(defconstant x86-overflow-flag-bit 11)
+
+
+(provide "X86-ARCH")
Index: /branches/new-random/compiler/X86/x86-asm.lisp
===================================================================
--- /branches/new-random/compiler/X86/x86-asm.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/x86-asm.lisp	(revision 13309)
@@ -0,0 +1,4832 @@
+;;;-*- Mode: Lisp; Package: (X86 :use CL) -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License   known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict  the preamble takes precedence.
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(require "X86-ARCH")
+)
+
+(in-package "X86")
+
+(defconstant +MAX-OPERANDS+ 3) ; max operands per insn
+(defconstant +MAX-IMMEDIATE-OPERANDS+ 2) ; max immediates per insn (lcall  ljmp)
+(defconstant +MAX-MEMORY-OPERANDS+ 2) ; max memory refs per insn (string ops)
+
+;;; Prefixes will be emitted in the order defined below.
+;;; WAIT-PREFIX must be the first prefix since FWAIT is really is an
+;;; instruction  and so must come before any prefixes.
+
+(defconstant +WAIT-PREFIX+ 0)
+(defconstant +LOCKREP-PREFIX+ 1)
+(defconstant +ADDR-PREFIX+ 2)
+(defconstant +DATA-PREFIX+ 3)
+(defconstant +SEG-PREFIX+ 4)
+(defconstant +REX-PREFIX+ 5) ; must come last.
+(defconstant +MAX-PREFIXES+ 6) ; max prefixes per opcode
+
+;;; we define the syntax here (modulo base index scale syntax)
+(defconstant +REGISTER-PREFIX+ #\%)
+(defconstant +IMMEDIATE-PREFIX+ #\$)
+(defconstant +ABSOLUTE-PREFIX+ #\*)
+
+(defconstant +TWO-BYTE-OPCODE-ESCAPE+ #x0f)
+(defconstant +NOP-OPCODE+ #x90)
+
+;;; register numbers
+(defconstant +EBP-REG-NUM+ 5)
+(defconstant +ESP-REG-NUM+ 4)
+
+;;; modrm-byte.regmem for twobyte escape
+(defconstant +ESCAPE-TO-TWO-BYTE-ADDRESSING+ +ESP-REG-NUM+)
+;;; index-base-byte.index for no index register addressing
+(defconstant +NO-INDEX-REGISTER+ +ESP-REG-NUM+)
+;;; index-base-byte.base for no base register addressing
+(defconstant +NO-BASE-REGISTER+ +EBP-REG-NUM+)
+(defconstant +NO-BASE-REGISTER-16+ 6)
+
+;;; these are the instruction mnemonic suffixes.
+(defconstant +WORD-MNEM-SUFFIX+ #\w)
+(defconstant +BYTE-MNEM-SUFFIX+ #\b)
+(defconstant +SHORT-MNEM-SUFFIX+ #\s)
+(defconstant +LONG-MNEM-SUFFIX+ #\l)
+(defconstant +QWORD-MNEM-SUFFIX+ #\q)
+(defconstant +LONG-DOUBLE-MNEM-SUFFIX+ #\x)
+
+;;; modrm.mode = REGMEM-FIELD-HAS-REG when a register is in there
+(defconstant +REGMEM-FIELD-HAS-REG+ #x3) ; always = #x3
+(defconstant +REGMEM-FIELD-HAS-MEM+ (lognot +REGMEM-FIELD-HAS-REG+))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+;;; By default, this returns NIL if the modifier can't be encoded.
+;;; That's an error, but the caller can provide better error context.
+
+;;; first 16 bits for opcode modifier flags, rest for cpu
+;;; features. 
+(defparameter *opcode-flags*            
+  `((:jump . ,(ash 1 0))                ;special case for jump insns
+    (:CpuNo64 . ,(ash 1 16))            ;not supported in 64 bit mode
+    (:Cpu64 . ,(ash 1 17))              ;64 bit mode required
+    (:CpuSSE . ,(ash 1 18))             ;SSE extensions required
+    (:CpuSSE2 . ,(ash 1 19))            ;SSE2 extensions required
+    (:CpuSSE3 . ,(ash 1 20))            ;SSE3 extensions required
+))
+
+(defun %encode-opcode-flags (flags &optional errorp)
+  (flet ((encode-atomic-flag (f)
+           (if f
+             (cdr (assoc f *opcode-flags*))
+             0)))
+    (or
+     (if (atom flags)
+       (encode-atomic-flag flags)
+       (let* ((k 0))
+         (dolist (f flags k)
+           (let* ((k0 (encode-atomic-flag f)))
+             (if k0
+               (setq k (logior k0 k))
+               (return))))))
+     (if errorp (error "Unknown x86 opcode flags: ~s" flags)))))
+
+)
+
+(defmacro encode-opcode-flags (&rest flags)
+  (%encode-opcode-flags flags t))
+
+;;; operand-types[i] bits
+;;; register
+(defconstant +operand-type-Reg8+ #x1) ; 8 bit reg
+(defconstant +operand-type-Reg16+ #x2) ; 16 bit reg
+(defconstant +operand-type-Reg32+ #x4) ; 32 bit reg
+(defconstant +operand-type-Reg64+ #x8) ; 64 bit reg
+;;; immediate
+(defconstant +operand-type-Imm8+ #x10) ; 8 bit immediate
+(defconstant +operand-type-Imm8S+ #x20) ; 8 bit immediate sign extended
+(defconstant +operand-type-Imm16+ #x40) ; 16 bit immediate
+(defconstant +operand-type-Imm32+ #x80) ; 32 bit immediate
+(defconstant +operand-type-Imm32S+ #x100) ; 32 bit immediate sign extended
+(defconstant +operand-type-Imm64+ #x200) ; 64 bit immediate
+(defconstant +operand-type-Imm1+ #x400) ; 1 bit immediate
+;;; memory
+(defconstant +operand-type-BaseIndex+ #x800)
+;;; Disp8 16 32 are used in different ways  depending on the
+;;; instruction.  For jumps  they specify the size of the PC relative
+;;; displacement  for baseindex type instructions  they specify the
+;;; size of the offset relative to the base register  and for memory
+;;; offset instructions such as `mov 1234 %al' they specify the size of
+;;; the offset relative to the segment base.
+(defconstant +operand-type-Disp8+ #x1000) ; 8 bit displacement
+(defconstant +operand-type-Disp16+ #x2000) ; 16 bit displacement
+(defconstant +operand-type-Disp32+ #x4000) ; 32 bit displacement
+(defconstant +operand-type-Disp32S+ #x8000) ; 32 bit signed displacement
+(defconstant +operand-type-Disp64+ #x10000) ; 64 bit displacement
+;;; specials
+(defconstant +operand-type-InOutPortReg+ #x20000) ; register to hold in/out port addr = dx
+(defconstant +operand-type-ShiftCount+ #x40000) ; register to hold shift cound = cl
+(defconstant +operand-type-Control+ #x80000) ; Control register
+(defconstant +operand-type-Debug+ #x100000) ; Debug register
+(defconstant +operand-type-Test+ #x200000) ; Test register
+(defconstant +operand-type-FloatReg+ #x400000) ; Float register
+(defconstant +operand-type-FloatAcc+ #x800000) ; Float stack top %st(0)
+(defconstant +operand-type-SReg2+ #x1000000) ; 2 bit segment register
+(defconstant +operand-type-SReg3+ #x2000000) ; 3 bit segment register
+(defconstant +operand-type-Acc+ #x4000000) ; Accumulator %al or %ax or %eax
+(defconstant +operand-type-JumpAbsolute+ #x8000000)
+(defconstant +operand-type-RegMMX+ #x10000000) ; MMX register
+(defconstant +operand-type-RegXMM+ #x20000000) ; XMM registers in PIII
+(defconstant +operand-type-EsSeg+ #x40000000) ; String insn operand with fixed es segment
+
+;;; InvMem is for instructions with a modrm byte that only allow a
+;;; general register encoding in the i.tm.mode and i.tm.regmem fields
+;;; eg. control reg moves.  They really ought to support a memory form
+;;; but don't  so we add an InvMem flag to the register operand to
+;;; indicate that it should be encoded in the i.tm.regmem field.
+(defconstant +operand-type-InvMem+ #x80000000)
+(defconstant +operand-type-Label+ #x100000000)
+
+;;; 4 bytes and a :reloc; otherwise just like a 32-bit immediate
+(defconstant +operand-type-Self+ #x200000000)
+
+(defconstant +operand-type-Reg+ (logior +operand-type-Reg8+ +operand-type-Reg16+ +operand-type-Reg32+ +operand-type-Reg64+)) ; gen'l register
+(defconstant +operand-type-WordReg+ (logior +operand-type-Reg16+ +operand-type-Reg32+ +operand-type-Reg64+))
+(defconstant +operand-type-ImplicitRegister+ (logior +operand-type-InOutPortReg+ +operand-type-ShiftCount+ +operand-type-Acc+ +operand-type-FloatAcc+))
+(defconstant +operand-type-Imm+ (logior +operand-type-Imm8+ +operand-type-Imm8S+ +operand-type-Imm16+ +operand-type-Imm32S+ +operand-type-Imm32+ +operand-type-Imm64+)) ; gen'l immediate
+(defconstant +operand-type-EncImm+ (logior +operand-type-Imm8+ +operand-type-Imm16+ +operand-type-Imm32+ +operand-type-Imm32S+)) ; Encodable gen'l immediate
+(defconstant +operand-type-Disp+ (logior +operand-type-Disp8+ +operand-type-Disp16+ +operand-type-Disp32+ +operand-type-Disp32S+ +operand-type-Disp64+)) ; General displacement
+(defconstant +operand-type-AnyMem+ (logior +operand-type-Disp8+ +operand-type-Disp16+ +operand-type-Disp32+ +operand-type-Disp32S+ +operand-type-BaseIndex+ +operand-type-InvMem+)) ; General memory
+;;; The following aliases are defined because the opcode table
+;;; carefully specifies the allowed memory types for each instruction.
+;;; At the moment we can only tell a memory reference size by the
+;;; instruction suffix  so there's not much point in defining Mem8
+;;; Mem16  Mem32 and Mem64 opcode modifiers - We might as well just use
+;;; the suffix directly to check memory operands.
+(defconstant +operand-type-LLongMem+ +operand-type-AnyMem+); 64 bits (or more)
+(defconstant +operand-type-LongMem+  +operand-type-AnyMem+) ; 32 bit memory ref
+(defconstant +operand-type-ShortMem+ +operand-type-AnyMem+) ; 16 bit memory ref
+(defconstant +operand-type-WordMem+ +operand-type-AnyMem+) ; 16 or 32 bit memory ref
+(defconstant +operand-type-ByteMem+ +operand-type-AnyMem+) ; 8 bit memory ref
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+(defparameter *x86-operand-type-names*
+  `((:Reg8 . ,+operand-type-Reg8+)
+    (:Reg16 . ,+operand-type-Reg16+)
+    (:Reg32 . ,+operand-type-Reg32+)
+    (:Reg64 . ,+operand-type-Reg64+)
+    (:Imm8 . ,+operand-type-Imm8+)
+    (:Imm8S . ,+operand-type-Imm8S+)
+    (:Imm16 . ,+operand-type-Imm16+)
+    (:Imm32 . ,+operand-type-Imm32+)
+    (:Imm32S . ,+operand-type-Imm32S+)
+    (:Imm64 . ,+operand-type-Imm64+)
+    (:Imm1 . ,+operand-type-Imm1+)
+    (:BaseIndex . ,+operand-type-BaseIndex+)
+    (:Disp8 . ,+operand-type-Disp8+)
+    (:Disp16 . ,+operand-type-Disp16+)
+    (:Disp32 . ,+operand-type-Disp32+)
+    (:Disp32S . ,+operand-type-Disp32S+)
+    (:Disp64 . ,+operand-type-Disp64+)
+    (:InOutPortReg . ,+operand-type-InOutPortReg+)
+    (:ShiftCount . ,+operand-type-ShiftCount+)
+    (:Control . ,+operand-type-Control+)
+    (:Debug . ,+operand-type-Debug+)
+    (:Test . ,+operand-type-Test+)
+    (:FloatReg . ,+operand-type-FloatReg+)
+    (:FloatAcc . ,+operand-type-FloatAcc+)
+    (:SReg2 . ,+operand-type-SReg2+)
+    (:SReg3 . ,+operand-type-SReg3+)
+    (:Acc . ,+operand-type-Acc+)
+    (:JumpAbsolute . ,+operand-type-JumpAbsolute+)
+    (:RegMMX . ,+operand-type-RegMMX+)
+    (:RegXMM . ,+operand-type-RegXMM+)
+    (:EsSeg . ,+operand-type-EsSeg+)
+    (:InvMem . ,+operand-type-InvMem+)
+    (:Reg . ,+operand-type-Reg+)
+    (:WordReg . ,+operand-type-WordReg+)
+    (:ImplicitRegister . ,+operand-type-ImplicitRegister+)
+    (:Imm . ,+operand-type-Imm+)
+    (:EncImm . ,+operand-type-EncImm+)
+    (:Disp . ,+operand-type-Disp+)
+    (:AnyMem . ,+operand-type-AnyMem+)
+    (:LLongMem . ,+operand-type-LLongMem+)
+    (:LongMem . ,+operand-type-LongMem+)
+    (:ShortMem . ,+operand-type-ShortMem+)
+    (:WordMem . ,+operand-type-WordMem+)
+    (:ByteMem . ,+operand-type-ByteMem+)
+    (:Label . ,+operand-type-Label+)
+    (:Self . ,+operand-type-Self+)
+  ))
+
+(defun %encode-operand-type (optype &optional errorp)
+  (flet ((encode-atomic-operand-type (op)
+           (if op
+             (cdr (assoc op *x86-operand-type-names* :test #'eq))
+             0)))
+    (or
+     (if (atom optype)
+       (encode-atomic-operand-type optype)
+       (let* ((k 0))
+         (dolist (op optype k)
+           (let* ((k0 (encode-atomic-operand-type op)))
+             (if k0
+               (setq k (logior k k0))
+               (return))))))
+     (if errorp (error "Unknown x86 operand type ~s" optype)))))
+)
+
+(defmacro encode-operand-type (&rest op)
+  (%encode-operand-type op t))
+
+
+
+
+
+(defconstant +RegRex+ #x1) ; Extended register.
+(defconstant +RegRex64+ #x2) ; Extended 8 bit register.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+;;; these are for register name --> number & type hash lookup
+(defstruct reg-entry
+  reg-name
+  reg-type
+  reg-flags
+  reg-num                               ; for encoding in instruction fields
+  ordinal64                             ; canonical, ordinal register number
+  ordinal32
+)
+
+(defmethod make-load-form ((r reg-entry) &optional env)
+  (declare (ignore env))
+  (make-load-form-saving-slots r))
+
+(defstruct seg-entry
+  seg-name
+  seg-prefix
+)
+
+)
+
+
+(defstruct modrm-byte
+  regmem ; codes register or memory operand
+  reg ; codes register operand (or extended opcode)
+  mode ; how to interpret regmem & reg
+)
+
+;;; x86-64 extension prefix.
+;; typedef int rex-byte
+(defconstant +REX-OPCODE+ #x40)
+
+;;; Indicates 64 bit operand size.
+(defconstant +REX-MODE64+ 8)
+;;; High extension to reg field of modrm byte.
+(defconstant +REX-EXTX+ 4)
+;;; High extension to SIB index field.
+(defconstant +REX-EXTY+ 2)
+;;; High extension to base field of modrm or SIB  or reg field of opcode.
+(defconstant +REX-EXTZ+ 1)
+
+;;; 386 opcode byte to code indirect addressing.
+(defstruct sib-byte
+  base
+  index
+  scale
+)
+
+
+;;; x86 arch names and features
+(defstruct arch-entry
+  name  ; arch name
+  flags ; cpu feature flags
+)
+
+
+;;; The SystemV/386 SVR3.2 assembler  and probably all AT&T derived
+;;; ix86 Unix assemblers  generate floating point instructions with
+;;; reversed source and destination registers in certain cases.
+;;; Unfortunately  gcc and possibly many other programs use this
+;;; reversed syntax  so we're stuck with it.
+;;;
+;;; eg. `fsub %st(3) %st' results in st = st - st(3) as expected  but
+;;;`fsub %st %st(3)' results in st(3) = st - st(3)  rather than
+;;; the expected st(3) = st(3) - st
+;;;
+;;; This happens with all the non-commutative arithmetic floating point
+;;; operations with two register operands  where the source register is
+;;; %st  and destination register is %st(i).  See FloatDR below.
+;;;
+;;; The affected opcode map is dceX  dcfX  deeX  defX.
+
+(defconstant +MOV-AX-DISP32+ #xa0)
+(defconstant +POP-SEG-SHORT+ #x07)
+(defconstant +JUMP-PC-RELATIVE+ #xe9)
+(defconstant +INT-OPCODE+  #xcd)
+(defconstant +INT3-OPCODE+ #xcc)
+(defconstant +FWAIT-OPCODE+ #x9b)
+(defconstant +ADDR-PREFIX-OPCODE+ #x67)
+(defconstant +DATA-PREFIX-OPCODE+ #x66)
+(defconstant +LOCK-PREFIX-OPCODE+ #xf0)
+(defconstant +CS-PREFIX-OPCODE+ #x2e)
+(defconstant +DS-PREFIX-OPCODE+ #x3e)
+(defconstant +ES-PREFIX-OPCODE+ #x26)
+(defconstant +FS-PREFIX-OPCODE+ #x64)
+(defconstant +GS-PREFIX-OPCODE+ #x65)
+(defconstant +SS-PREFIX-OPCODE+ #x36)
+(defconstant +REPNE-PREFIX-OPCODE+ #xf2)
+(defconstant +REPE-PREFIX-OPCODE+  #xf3)
+
+
+(defstruct (x86-opcode-template (:constructor %make-x86-opcode-template))
+  mnemonic               ; fully qualified, includes suffix if applicable
+  flags                  ; opcode modifier and cpu type flags
+  ordinal                ; unique id
+  operand-types          ; as specific as possible
+  operand-classes        ; describe how to insert operands in base op, modrm
+  prefixes               ; list of 0 or more explicit prefixes
+  base-opcode            ; 1-3 bytes
+  rex-prefix             ; initial REX value
+  modrm-byte             ; initial modrm vale, may be nil if no modrm byte
+  )
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defun parse-x86-opcode-operand-types (types&classes)
+  (ccl::collect ((types))
+    (dolist (t&c types&classes (apply #'vector (types)))
+      (destructuring-bind (type class) t&c
+        (declare (ignore class))
+        (types (%encode-operand-type type t))))))
+
+(defparameter *x86-operand-insert-function-keywords*
+  #(:insert-nothing
+    :insert-modrm-reg
+    :insert-modrm-rm
+    :insert-memory
+    :insert-opcode-reg
+    :insert-opcode-reg4
+    :insert-cc
+    :insert-label
+    :insert-imm8-for-int
+    :insert-extra
+    :insert-imm8
+    :insert-imm8s
+    :insert-imm16
+    :insert-imm32s
+    :insert-imm32
+    :insert-imm64
+    :insert-mmx-reg
+    :insert-mmx-rm
+    :insert-xmm-reg
+    :insert-xmm-rm
+    :insert-reg4-pseudo-rm-high
+    :insert-reg4-pseudo-rm-low
+    :insert-self
+    ))
+
+(defun parse-x86-opcode-operand-classes (types&classes)
+  (ccl::collect ((classes))
+    (dolist (t&c types&classes (apply #'vector (classes)))
+      (destructuring-bind (type class) t&c
+        (declare (ignore type))
+        (classes (or (position class *x86-operand-insert-function-keywords*)
+		     (error "Unknown operand class: ~s" class)))))))
+
+(defun parse-x86-opcode-name (name&flags)
+  (string-downcase (if (atom name&flags) name&flags (car name&flags))))
+
+
+(defun parse-x86-opcode-flags (name&flags)
+  (if (atom name&flags)
+    0
+    (%encode-opcode-flags (cdr name&flags))))
+
+)
+
+;;; Any instruction with no operands.
+(defstruct x86-instruction
+  opcode-template
+  rex-prefix                            ; ignored in 32-bit assembly
+  base-opcode
+  modrm-byte
+  sib-byte
+  seg-prefix
+  disp
+  imm
+  extra
+  )
+
+(defun need-modrm-byte (instruction)
+  (or (x86-instruction-modrm-byte instruction)
+      (error "Bug: no modrm byte in ~s" instruction)))
+
+(defun need-rex-prefix (instruction)
+  (or (x86-instruction-rex-prefix instruction)
+      (error "Bug: no REX prefix in ~s" instruction)))
+
+
+
+
+(defconstant modrm-mod-byte (byte 2 6))
+(defconstant modrm-reg-byte (byte 3 3))
+(defconstant modrm-rm-byte (byte 3 0))
+
+(defconstant sib-scale-byte (byte 2 6))
+(defconstant sib-index-byte (byte 3 3))
+(defconstant sib-base-byte (byte 3 0))
+
+(defun mode-from-disp-size (type)
+  (cond ((logtest type (x86::encode-operand-type :disp8)) 1)
+        ((logtest type (x86::encode-operand-type :disp16 :disp32 :disp32S)) 2)
+        (t 0)))
+
+
+(defun insert-memory-operand-values (instruction
+                                     explicit-seg
+                                     disp
+                                     base
+                                     index
+                                     scale
+                                     memtype)
+  (declare (special *ds-segment-register* *ss-segment-register*)) ;fwd refs
+  (let* ((rm-byte (x86-instruction-modrm-byte instruction))
+         (sib 0)
+         (default-seg *ds-segment-register*))
+    (cond ((null base)
+           (setf (ldb modrm-mod-byte rm-byte) 0
+                 (ldb modrm-rm-byte rm-byte) +escape-to-two-byte-addressing+
+                 (ldb sib-base-byte sib) +no-base-register+
+                 memtype (encode-operand-type :disp32s))
+           (cond ((null index)
+                  ;; Just a displacement.
+                  (setf (ldb sib-index-byte sib) +no-index-register+))
+                 (t
+                  ;; No base, but index
+                  (let* ((index-reg (reg-entry-reg-num index)))
+                    (setf (ldb sib-index-byte sib) index-reg
+                          (ldb sib-scale-byte sib) (or scale 0))
+                    (when (logtest (reg-entry-reg-flags index) +RegRex+)
+                      (setf (x86-instruction-rex-prefix instruction)
+                            (logior +rex-exty+ (need-rex-prefix instruction))))))))
+          ((= (reg-entry-reg-type base) (encode-operand-type :baseIndex))
+           ;; RIP-relative.  Need a displacement if we don't already
+           ;; have one.
+           (setf (ldb modrm-rm-byte rm-byte) +no-base-register+)
+           (setq memtype
+                 (logior (encode-operand-type :disp32s)
+                         (encode-operand-type :label)
+                         (logandc2 memtype (encode-operand-type :disp)))))
+          (t
+           ;; have a real base register (not just %rip).  Maybe an
+           ;; index register, too.
+           (let* ((baseregnum (reg-entry-reg-num base)))
+             (setf (ldb modrm-rm-byte rm-byte) baseregnum)
+             (when (logtest (reg-entry-reg-flags base) +RegRex+)
+               (setf (x86-instruction-rex-prefix instruction)
+                     (logior 1 (need-rex-prefix instruction))))
+             (setf (ldb sib-base-byte sib) baseregnum)
+             (cond ((= (logand baseregnum 7) +ebp-reg-num+)
+                    (setq default-seg *ss-segment-register*)
+                    (unless disp
+                      (setf memtype (logior memtype (encode-operand-type :disp8)))))
+                   ((= baseregnum x86::+esp-reg-num+)
+                    (setq default-seg x86::*ss-segment-register*)))
+             (setf (ldb sib-scale-byte sib) (or scale 0))
+             (if (null index)
+               (setf (ldb sib-index-byte sib) +no-index-register+)
+               (progn
+                 (setf (ldb sib-index-byte sib)
+                       (reg-entry-reg-num index)
+                       (ldb modrm-rm-byte rm-byte) +escape-to-two-byte-addressing+)
+                 (when (logtest (reg-entry-reg-flags index) +RegRex+)
+                   (setf (x86-instruction-rex-prefix instruction)
+                         (logior +rex-exty+
+                                 (need-rex-prefix instruction)))))))
+               (setf (ldb modrm-mod-byte rm-byte) (mode-from-disp-size memtype))))
+    (setf (x86-instruction-modrm-byte instruction) rm-byte)
+    (when (= (ldb modrm-rm-byte rm-byte) +escape-to-two-byte-addressing+)
+      (setf (x86-instruction-sib-byte instruction) sib))
+    (when (logtest memtype (encode-operand-type :disp))
+      (unless disp (setq disp 0))
+      (setf (x86-instruction-disp instruction) disp
+            (x86-instruction-extra instruction) memtype))
+    (when (and explicit-seg
+               (not (eq explicit-seg default-seg)))
+      (setf (x86-instruction-seg-prefix instruction)
+            (seg-entry-seg-prefix explicit-seg)))))
+
+(defun insert-memory (instruction operand)
+  (insert-memory-operand-values instruction
+                                (x86-memory-operand-seg operand)
+                                (x86-memory-operand-disp operand)
+                                (x86-memory-operand-base operand)
+                                (x86-memory-operand-index operand)
+                                (x86-memory-operand-scale operand)
+                                (x86-memory-operand-type operand)))
+
+
+(defmacro def-x86-opcode (name&flags types-and-classes base-opcode
+			  modrm-byte rex-prefix &rest prefixes)
+  `(%make-x86-opcode-template
+    :mnemonic ,(parse-x86-opcode-name name&flags)
+    :flags ,(parse-x86-opcode-flags name&flags)
+    :operand-types ,(parse-x86-opcode-operand-types types-and-classes)
+    :operand-classes ,(parse-x86-opcode-operand-classes types-and-classes)
+    :base-opcode ,base-opcode
+    :prefixes ',prefixes
+    :rex-prefix ,rex-prefix
+    :modrm-byte ,modrm-byte))
+
+(defparameter *x86-opcode-templates*
+  (vector
+   ;; adc
+   (def-x86-opcode (adcq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x11 #o300 #x48)
+   (def-x86-opcode (adcq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x13 #o000 #x48)
+   (def-x86-opcode (adcq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x11 #x00 #x48)
+   (def-x86-opcode (adcq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o320 #x48)
+   (def-x86-opcode (adcq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x15 nil #x48)
+   (def-x86-opcode (adcq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o320 #x48)
+   (def-x86-opcode (adcq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o020 #x48)
+   (def-x86-opcode (adcq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o020 #x48)
+
+   (def-x86-opcode adcl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x11 #o300 #x00)
+   (def-x86-opcode adcl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x13 #o000 #x00)
+   (def-x86-opcode adcl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x11 #x00 #x00)
+   (def-x86-opcode adcl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o320 #x00)
+   (def-x86-opcode adcl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x15 nil nil)
+   (def-x86-opcode adcl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o320 #x00)
+   (def-x86-opcode adcl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o020 #x00)
+   (def-x86-opcode adcl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o020 #x00)
+
+   (def-x86-opcode adcw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x11 #o300 #x00 #x66)
+   (def-x86-opcode adcw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x13 #o000 #x00 #x66)
+   (def-x86-opcode adcw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x11 #x00 #x00 #x66)
+   (def-x86-opcode adcw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o320 #x00 #x66)
+   (def-x86-opcode adcw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x15 nil nil #x66)
+   (def-x86-opcode adcw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o320 #x00 #x66)
+   (def-x86-opcode adcw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o020 #x00 #x66)
+   (def-x86-opcode adcw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o020 #x00 #x66)
+
+   (def-x86-opcode adcb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x10 #o300 #x00)
+   (def-x86-opcode adcb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x12 #o000 #x00)
+   (def-x86-opcode adcb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x10 #x00 #x00)
+   (def-x86-opcode adcb ((:imm8 :insert-imm8) (:acc :insert-nothing))
+     #x14 nil nil)
+   (def-x86-opcode adcb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #x80 #o320 #x00)
+   (def-x86-opcode adcb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #x80 #o320 #x00)
+   (def-x86-opcode adcb ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x80 #o020 #x00)
+
+   ;; add
+   (def-x86-opcode (addq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x01 #o300 #x48)
+   (def-x86-opcode (addq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x03 #o000 #x48)
+   (def-x86-opcode (addq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x01 #x00 #x48)
+   (def-x86-opcode (addq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o300 #x48)
+   (def-x86-opcode (addq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x05 nil #x48)
+   (def-x86-opcode (addq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o300 #x48)
+   (def-x86-opcode (addq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o000 #x48)
+   (def-x86-opcode (addq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o000 #x48)
+
+   (def-x86-opcode addl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x01 #o300 #x00)
+   (def-x86-opcode addl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x03 #o000 #x00)
+   (def-x86-opcode addl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x01 #x00 #x00)
+   (def-x86-opcode addl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o300 #x00)
+   (def-x86-opcode addl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x05 nil nil)
+   (def-x86-opcode addl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o300 #x00)
+   (def-x86-opcode addl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o000 #x00)
+   (def-x86-opcode addl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o000 #x00)
+
+   (def-x86-opcode addw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x01 #o300 #x00 #x66)
+   (def-x86-opcode addw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x03 #o000 #x00 #x66)
+   (def-x86-opcode addw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x01 #x00 #x00 #x66)
+   (def-x86-opcode addw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o300 #x00 #x66)
+   (def-x86-opcode addw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x05 nil nil #x66)
+   (def-x86-opcode addw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o300 #x00 #x66)
+   (def-x86-opcode addw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o000 #x00 #x66)
+   (def-x86-opcode addw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o000 #x00 #x66)
+
+   (def-x86-opcode addb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x00 #o300 #x00)
+   (def-x86-opcode addb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x02 #o000 #x00)
+   (def-x86-opcode addb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x00 #x00 #x00)
+   (def-x86-opcode addb ((:imm8s :insert-imm8s) (:acc :insert-nothing))
+     #x04 nil nil)
+   (def-x86-opcode addb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o300 #x00)
+   (def-x86-opcode addb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x80 #o000 #x00)
+
+   ;; and
+   (def-x86-opcode (andq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x21 #o300 #x48)
+   (def-x86-opcode (andq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x23 #o000 #x48)
+   (def-x86-opcode (andq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x21 #x00 #x48)
+   (def-x86-opcode (andq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o340 #x48)
+   (def-x86-opcode (andq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x25 nil #x48)
+   (def-x86-opcode (andq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o340 #x48)
+   (def-x86-opcode (andq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o040 #x48)
+   (def-x86-opcode (andq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o040 #x48)
+
+   (def-x86-opcode andl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x21 #o300 #x00)
+   (def-x86-opcode andl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x23 #o000 #x00)
+   (def-x86-opcode andl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x21 #x00 #x00)
+   (def-x86-opcode andl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o340 #x00)
+   (def-x86-opcode andl (((:imm32s :imm32) :insert-imm32s) (:acc :insert-nothing))
+     #x25 nil nil)
+   (def-x86-opcode andl (((:imm32s :imm32) :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o340 #x00)
+   (def-x86-opcode andl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o040 #x00)
+   (def-x86-opcode andl (((:imm32s :imm32) :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o040 #x00)
+
+   (def-x86-opcode andw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x21 #o300 #x00 #x66)
+   (def-x86-opcode andw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x23 #o000 #x00 #x66)
+   (def-x86-opcode andw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x21 #x00 #x00 #x66)
+   (def-x86-opcode andw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o340 #x00 #x66)
+   (def-x86-opcode andw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x25 nil nil #x66)
+   (def-x86-opcode andw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o340 #x00 #x66)
+   (def-x86-opcode andw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o040 #x00 #x66)
+   (def-x86-opcode andw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o040 #x00 #x66)
+
+   (def-x86-opcode andb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x20 #o300 #x00)
+   (def-x86-opcode andb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x22 #o000 #x00)
+   (def-x86-opcode andb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x20 #o000 #x00)
+   (def-x86-opcode andb ((:imm8s :insert-imm8s) (:acc :insert-nothing))
+     #x24 nil nil)
+   (def-x86-opcode andb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o340 #x00)
+   (def-x86-opcode andb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x80 #o040 #x00)
+
+   ;; bsf
+   (def-x86-opcode (bsfq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0fbc #o300 #x48)
+   (def-x86-opcode (bsfq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0fbc #o000 #x48)
+
+   (def-x86-opcode bsfl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0fbc #o300 #x00)
+   (def-x86-opcode bsfl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0fbc #o000 #x00)
+
+   (def-x86-opcode bsfw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0fbc #o300 #x00 #x66)
+   (def-x86-opcode bsfw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0fbc #o000 #x00 #x66)
+
+   ;; bsr
+   (def-x86-opcode (bsrq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0fbd #o300 #x48)
+   (def-x86-opcode (bsrq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0fbd #o000 #x48)
+
+   (def-x86-opcode bsrl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0fbd #o300 #x00)
+   (def-x86-opcode bsrl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0fbd #o000 #x00)
+
+   (def-x86-opcode bsrw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0fbd #o300 #x00 #x66)
+   (def-x86-opcode bsrw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0fbd #o000 #x00 #x66)
+
+   ;; bswap
+   (def-x86-opcode (bswapq :cpu64) ((:reg64 :insert-opcode-reg))
+     #x0fc8 nil #x48)
+
+   (def-x86-opcode bswapl ((:reg32 :insert-opcode-reg))
+     #x0fc8 nil #x00)
+
+   ;; bt
+   (def-x86-opcode (btq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #x0fba #o340 #x48)
+   (def-x86-opcode (btq :cpu64) ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o040 #x48)
+   (def-x86-opcode (btq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fa3 #o300 #x48)
+   (def-x86-opcode (btq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa3 #o000 #x48)
+
+   (def-x86-opcode btl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #x0fba #o340 #x00)
+   (def-x86-opcode btl ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o040 #x00)
+   (def-x86-opcode btl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fa3 #o300 #x00)
+   (def-x86-opcode btl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa3 #o000 #x00)
+
+   (def-x86-opcode btw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #x0fba #o340 #x00 #x66)
+   (def-x86-opcode btw ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o040 #x00 #x66)
+   (def-x86-opcode btw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fa3 #o300 #x00 #x66)
+   (def-x86-opcode btw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa3 #o000 #x00 #x66)
+
+   ;; btc
+   (def-x86-opcode (btcq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #x0fba #o370 #x48)
+   (def-x86-opcode (btcq :cpu64) ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o070 #x48)
+   (def-x86-opcode (btcq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fbb #o300 #x48)
+   (def-x86-opcode (btcq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fbb #o000 #x48)
+
+   (def-x86-opcode btcl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #x0fba #o370 #x00)
+   (def-x86-opcode btcl ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o070 #x00)
+   (def-x86-opcode btcl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fbb #o300 #x00)
+   (def-x86-opcode btcl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fbb #o000 #x00)
+
+   (def-x86-opcode btcw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #x0fba #o370 #x00 #x66)
+   (def-x86-opcode btcw ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o070 #x00 #x66)
+   (def-x86-opcode btcw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fbb #o300 #x00 #x66)
+   (def-x86-opcode btcw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fbb #o000 #x00 #x66)
+
+   ;; btr
+   (def-x86-opcode (btrq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #x0fba #o360 #x48)
+   (def-x86-opcode (btrq :cpu64) ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o060 #x48)
+   (def-x86-opcode (btrq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fb3 #o300 #x48)
+   (def-x86-opcode (btrq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fb3 #o000 #x48)
+
+   (def-x86-opcode btrl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #x0fba #o360 #x00)
+   (def-x86-opcode btrl ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o060 #x00)
+   (def-x86-opcode btrl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fb3 #o300 #x00)
+   (def-x86-opcode btrl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fb3 #o000 #x00)
+
+   (def-x86-opcode btrw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #x0fba #o360  #x00 #x66)
+   (def-x86-opcode btrw ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o060 #x00 #x66)
+   (def-x86-opcode btrw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fb3 #o300 #x00 #x66)
+   (def-x86-opcode btrw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fb3 #o000 #x00 #x66)
+
+   ;; bts
+   (def-x86-opcode (btsq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #x0fba #o350 #x48)
+   (def-x86-opcode (btsq :cpu64) ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o050 #x48)
+   (def-x86-opcode (btsq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fab #o300 #x48)
+   (def-x86-opcode (btsq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fab #o000 #x48)
+
+   (def-x86-opcode btsl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #x0fba #o350 #x00)
+   (def-x86-opcode btsl ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o050 #x00)
+   (def-x86-opcode btsl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fab #o300 #x00)
+   (def-x86-opcode btsl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fab #o000 #x00)
+
+   (def-x86-opcode btsw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #x0fba #o350  #x00 #x66)
+   (def-x86-opcode btsw ((:imm8 :insert-imm8) (:anymem :insert-memory))
+     #x0fba #o050 #x00 #x66)
+   (def-x86-opcode btsw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fab #o300 #x00 #x66)
+   (def-x86-opcode btsw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fab #o000 #x00 #x66)
+
+   ;; call
+   ;; Probably need to align CALL instructions within the containing function,
+   ;; so that return addresses are tagged appropriately.
+   (def-x86-opcode call ((:label :insert-label))
+     #xe8 nil nil)
+
+   (def-x86-opcode (call :cpu64) ((:reg64 :insert-modrm-rm))
+     #xff #o320 #x0)
+   (def-x86-opcode (call :cpuno64) ((:reg32 :insert-modrm-rm))
+     #xff #o320 #x0)
+
+   (def-x86-opcode call ((:anymem :insert-memory))
+     #xff #o020 #x0)
+
+   ;; cbtw
+   (def-x86-opcode cbtw ()
+     #x98 nil nil #x66)
+
+   ;; clc
+   (def-x86-opcode clc ()
+     #xf8 nil nil)
+
+   ;; cld
+   (def-x86-opcode cld ()
+     #xfc nil nil)
+
+   ;; cltd
+   (def-x86-opcode cltd ()
+     #x99 nil nil)
+
+  
+   ;; cltq
+   (def-x86-opcode (cltq :cpu64) ()
+     #x98 nil #x48)
+
+   ;; cmc
+   (def-x86-opcode cmc ()
+     #xf5 nil nil)
+
+   ;; cmovCC
+   (def-x86-opcode (cmovccq :cpu64)
+       ((:imm8 :insert-cc) (:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f40 #o300 #x48)
+   (def-x86-opcode (cmovccq :cpu64)
+       ((:imm8 :insert-cc) (:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f40 #o000 #x48)
+   (def-x86-opcode cmovccl
+       ((:imm8 :insert-cc) (:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f40 #o300 #x00)
+   (def-x86-opcode cmovccl
+       ((:imm8 :insert-cc) (:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f40 #o000 #x00)
+   (def-x86-opcode cmovccw
+       ((:imm8 :insert-cc) (:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f40 #o300 #x00 #x66)
+   (def-x86-opcode cmovccw
+       ((:imm8 :insert-cc) (:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f40 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovoq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f40 #o300 #x48)
+   (def-x86-opcode (cmovoq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f40 #o000 #x48)
+   (def-x86-opcode cmovol ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f40 #o300 #x00)
+   (def-x86-opcode cmovol ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f40 #o000 #x00)
+   (def-x86-opcode cmovow ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f40 #o300 #x00 #x66)
+   (def-x86-opcode cmovow ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f40 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovnoq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f41 #o300 #x48)
+   (def-x86-opcode (cmovnoq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f41 #o000 #x48)
+   (def-x86-opcode cmovnol ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f41 #o300 #x00)
+   (def-x86-opcode cmovnol ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f41 #o000 #x00)
+   (def-x86-opcode cmovnow ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f41 #o300 #x00 #x66)
+   (def-x86-opcode cmovnow ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f41 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovbq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f42 #o300 #x48)
+   (def-x86-opcode (cmovbq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f42 #o000 #x48)
+   (def-x86-opcode cmovbl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f42 #o300 #x00)
+   (def-x86-opcode cmovbl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f42 #o000 #x00)
+   (def-x86-opcode cmovbw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f42 #o300 #x00 #x66)
+   (def-x86-opcode cmovbw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f42 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovcq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f42 #o300 #x48)
+   (def-x86-opcode (cmovcq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f42 #o000 #x48)
+   (def-x86-opcode cmovcl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f42 #o300 #x00)
+   (def-x86-opcode cmovcl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f42 #o000 #x00)
+   (def-x86-opcode cmovcw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f42 #o300 #x00 #x66)
+   (def-x86-opcode cmovcw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f42 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovaeq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f43 #o300 #x48)
+   (def-x86-opcode (cmovaeq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f43 #o000 #x48)
+   (def-x86-opcode cmovael ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f43 #o300 #x00)
+   (def-x86-opcode cmovael ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f43 #o000 #x00)
+   (def-x86-opcode cmovaew ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f43 #o300 #x00 #x66)
+   (def-x86-opcode cmovaew ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f43 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovncq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f43 #o300 #x48)
+   (def-x86-opcode (cmovncq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f43 #o000 #x48)
+   (def-x86-opcode cmovncl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f43 #o300 #x00)
+   (def-x86-opcode cmovncl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f43 #o000 #x00)
+   (def-x86-opcode cmovncw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f43 #o300 #x00 #x66)
+   (def-x86-opcode cmovncw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f43 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmoveq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f44 #o300 #x48)
+   (def-x86-opcode (cmoveq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f44 #o000 #x48)
+   (def-x86-opcode cmovel ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f44 #o300 #x00)
+   (def-x86-opcode cmovel ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f44 #o000 #x00)
+   (def-x86-opcode cmovew ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f44 #o300 #x00 #x66)
+   (def-x86-opcode cmovew ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f44 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovzq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f44 #o300 #x48)
+   (def-x86-opcode (cmovzq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f44 #o000 #x48)
+   (def-x86-opcode cmovzl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f44 #o300 #x00)
+   (def-x86-opcode cmovzl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f44 #o000 #x00)
+   (def-x86-opcode cmovzw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f44 #o300 #x00 #x66)
+   (def-x86-opcode cmovzw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f44 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovneq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f45 #o300 #x48)
+   (def-x86-opcode (cmovneq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f45 #o000 #x48)
+   (def-x86-opcode cmovnel ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f45 #o300 #x00)
+   (def-x86-opcode cmovnel ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f45 #o000 #x00)
+   (def-x86-opcode cmovnew ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f45 #o300 #x00 #x66)
+   (def-x86-opcode cmovnew ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f45 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovnzq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f45 #o300 #x48)
+   (def-x86-opcode (cmovnzq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f45 #o000 #x48)
+   (def-x86-opcode cmovnzl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f45 #o300 #x00)
+   (def-x86-opcode cmovnzl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f45 #o000 #x00)
+   (def-x86-opcode cmovnzw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f45 #o300 #x00 #x66)
+   (def-x86-opcode cmovnzw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f45 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovbeq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f46 #o300 #x48)
+   (def-x86-opcode (cmovbeq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f46 #o000 #x48)
+   (def-x86-opcode cmovbel ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-reg))
+     #x0f46 #o300 #x00)
+   (def-x86-opcode cmovbel ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f46 #o000 #x00)
+   (def-x86-opcode cmovbew ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f46 #o300 #x00 #x66)
+   (def-x86-opcode cmovbew ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f46 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovaq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f47 #o300 #x48)
+   (def-x86-opcode (cmovaq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f47 #o000 #x48)
+   (def-x86-opcode cmoval ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f47 #o300 #x00)
+   (def-x86-opcode cmoval ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f47 #o000 #x00)
+   (def-x86-opcode cmovaw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f47 #o300 #x00 #x66)
+   (def-x86-opcode cmovaw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f47 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovsq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f48 #o300 #x48)
+   (def-x86-opcode (cmovsq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f48 #o000 #x48)
+   (def-x86-opcode cmovsl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f48 #o300 #x00)
+   (def-x86-opcode cmovsl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f48 #o000 #x00)
+   (def-x86-opcode cmovsw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f48 #o300 #x00 #x66)
+   (def-x86-opcode cmovsw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f48 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovnsq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f49 #o300 #x48)
+   (def-x86-opcode (cmovnsq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f49 #o000 #x48)
+   (def-x86-opcode cmovnsl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f49 #o300 #x00)
+   (def-x86-opcode cmovnsl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f49 #o000 #x00)
+   (def-x86-opcode cmovnsw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f49 #o300 #x00 #x66)
+   (def-x86-opcode cmovnsw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f49 #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovpeq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f4a #o300 #x48)
+   (def-x86-opcode (cmovpeq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f4a #o000 #x48)
+   (def-x86-opcode cmovpel ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f4a #o300 #x00)
+   (def-x86-opcode cmovpel ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f4a #o000 #x00)
+   (def-x86-opcode cmovpew ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f4a #o300 #x00 #x66)
+   (def-x86-opcode cmovpew ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f4a #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovpoq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f4b #o300 #x48)
+   (def-x86-opcode (cmovpoq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f4b #o000 #x48)
+   (def-x86-opcode cmovpol ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f4b #o300 #x00)
+   (def-x86-opcode cmovpol ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f4b #o000 #x00)
+   (def-x86-opcode cmovpow ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f4b #o300 #x00 #x66)
+   (def-x86-opcode cmovpow ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f4b #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovlq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f4c #o300 #x48)
+   (def-x86-opcode (cmovlq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f4c #o000 #x48)
+   (def-x86-opcode cmovll ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f4c #o300 #x00)
+   (def-x86-opcode cmovll ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f4c #o000 #x00)
+   (def-x86-opcode cmovlw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f4c #o300 #x00 #x66)
+   (def-x86-opcode cmovlw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f4c #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovgeq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f4d #o300 #x48)
+   (def-x86-opcode (cmovgeq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f4d #o000 #x48)
+   (def-x86-opcode cmovgel ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f4d #o300 #x00)
+   (def-x86-opcode cmovgel ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f4d #o000 #x00)
+   (def-x86-opcode cmovgew ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f4d #o300 #x00 #x66)
+   (def-x86-opcode cmovgew ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f4d #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovleq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f4e #o300 #x48)
+   (def-x86-opcode (cmovleq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f4e #o000 #x48)
+   (def-x86-opcode cmovlel ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f4e #o300 #x00)
+   (def-x86-opcode cmovlel ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f4e #o000 #x00)
+   (def-x86-opcode cmovlew ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f4e #o300 #x00 #x66)
+   (def-x86-opcode cmovlew ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f4e #o000 #x00 #x66)
+
+   (def-x86-opcode (cmovgq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0f4f #o300 #x48)
+   (def-x86-opcode (cmovgq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f4f #o000 #x48)
+   (def-x86-opcode cmovgl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0f4f #o300 #x00)
+   (def-x86-opcode cmovgl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f4f #o000 #x00)
+   (def-x86-opcode cmovgw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0f4f #o300 #x00 #x66)
+   (def-x86-opcode cmovgw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0f4f #o000 #x00 #x66)
+
+
+   ;; cmp
+
+   (def-x86-opcode (cmpq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x39 #o300 #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x39 #o300 #x48)
+   (def-x86-opcode (cmpq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x3b #o000 #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x3b #o000 #x48)   
+   (def-x86-opcode (cmpq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x39 #x00 #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x39 #x00 #x48)
+   (def-x86-opcode (cmpq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o370 #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:reg64 :insert-modrm-rm) (:imm8s :insert-imm8s))
+     #x83 #o370 #x48)
+   (def-x86-opcode (cmpq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x3d nil #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x3d nil #x48)
+   (def-x86-opcode (cmpq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o370 #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:reg64 :insert-modrm-rm) (:imm32s :insert-imm32s))
+     #x81 #o370 #x48)   
+   (def-x86-opcode (cmpq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o070 #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:anymem :insert-memory) (:imm8s :insert-imm8s))
+     #x83 #o070 #x48)
+   (def-x86-opcode (cmpq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o070 #x48)
+   (def-x86-opcode (rcmpq :cpu64) ((:anymem :insert-memory) (:imm32s :insert-imm32s))
+     #x81 #o070 #x48)
+
+   (def-x86-opcode cmpl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x39 #o300 #x00)
+   (def-x86-opcode rcmpl ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x39 #o300 #x00)   
+   (def-x86-opcode cmpl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x3b #o000 #x00)
+   (def-x86-opcode rcmpl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x3b #o000 #x00)   
+   (def-x86-opcode cmpl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x39 #x00 #x00)
+   (def-x86-opcode rcmpl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x39 #x00 #x00)   
+   (def-x86-opcode cmpl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o370 #x00)
+   (def-x86-opcode rcmpl ((:reg32 :insert-modrm-rm) (:imm8s :insert-imm8s))
+     #x83 #o370 #x00)   
+   (def-x86-opcode cmpl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x3d nil nil)
+   (def-x86-opcode rcmpl ((:acc :insert-nothing) (:imm32s :insert-imm32s))
+     #x3d nil nil)   
+   (def-x86-opcode cmpl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o370 #x00)
+   (def-x86-opcode rcmpl ((:reg32 :insert-modrm-rm) (:imm32s :insert-imm32s))
+     #x81 #o370 #x00)   
+   (def-x86-opcode cmpl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o070 #x00)
+   (def-x86-opcode rcmpl ((:anymem :insert-memory) (:imm8s :insert-imm8s))
+     #x83 #o070 #x00)   
+   (def-x86-opcode cmpl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o070 #x00)
+   (def-x86-opcode rcmpl ((:anymem :insert-memory) (:imm32s :insert-imm32s))
+     #x81 #o070 #x00)   
+
+   (def-x86-opcode cmpw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x39 #o300 #x00 #x66)
+   (def-x86-opcode rcmpw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x39 #o300 #x00 #x66)   
+   (def-x86-opcode cmpw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x3b #o000 #x00 #x66)
+   (def-x86-opcode rcmpw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x3b #o000 #x00 #x66)   
+   (def-x86-opcode cmpw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x39 #x00 #x00 #x66)
+   (def-x86-opcode rcmpw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x39 #x00 #x00 #x66)   
+   (def-x86-opcode cmpw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o370 #x00 #x66)
+   (def-x86-opcode rcmpw ((:reg16 :insert-modrm-rm) (:imm8s :insert-imm8s))
+     #x83 #o370 #x00 #x66)   
+   (def-x86-opcode cmpw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x3d nil nil #x66)
+   (def-x86-opcode rcmpw ((:acc :insert-nothing) (:imm16 :insert-imm16))
+     #x3d nil nil #x66)   
+   (def-x86-opcode cmpw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o370 #x00 #x66)
+   (def-x86-opcode rcmpw ((:reg16 :insert-modrm-rm) (:imm16 :insert-imm16))
+     #x81 #o370 #x00 #x66)   
+   (def-x86-opcode cmpw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o070 #x00 #x66)
+   (def-x86-opcode rcmpw ((:anymem :insert-memory) (:imm8s :insert-imm8s))
+     #x83 #o070 #x00 #x66)   
+   (def-x86-opcode cmpw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o070 #x00 #x66)
+   (def-x86-opcode rcmpw ((:anymem :insert-memory) (:imm16 :insert-imm16))
+     #x81 #o070 #x00 #x66)   
+
+   (def-x86-opcode cmpb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x38 #o300 #x00)
+   (def-x86-opcode rcmpb ((:reg8 :insert-modrm-rm) (:reg8 :insert-modrm-reg))
+     #x38 #o300 #x00)
+   (def-x86-opcode cmpb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x3a #o000 #x00)
+   (def-x86-opcode rcmpb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x3a #o000 #x00)
+   (def-x86-opcode cmpb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x38 #x00 #x00)
+   (def-x86-opcode rcmpb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x38 #x00 #x00)   
+   (def-x86-opcode cmpb (((:imm8s :imm8) :insert-imm8s) (:acc :insert-nothing))
+     #x3c nil nil)
+   (def-x86-opcode rcmpb ((:acc :insert-nothing) ((:imm8s :imm8) :insert-imm8s))
+     #x3c nil nil)
+   (def-x86-opcode cmpb (((:imm8s :imm8) :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o370 #x00)
+   (def-x86-opcode rcmpb ((:reg8 :insert-modrm-rm) ((:imm8s :imm8) :insert-imm8s))
+     #x80 #o370 #x00)
+   (def-x86-opcode cmpb (((:imm8s :imm8) :insert-imm8s) (:anymem :insert-memory))
+     #x80 #o070 #x00)
+   (def-x86-opcode rcmpb ((:anymem :insert-memory) ((:imm8s :imm8) :insert-imm8s))
+     #x80 #o070 #x00)
+
+   ;; cmps
+   (def-x86-opcode (cmpsq :cpu64) ()
+     #xa7 nil #x48)
+
+   (def-x86-opcode cmpsl ()
+     #xa7 nil nil)
+
+   (def-x86-opcode cmpsw ()
+     #xa7 nil nil #x66)
+
+   (def-x86-opcode cmpsb ()
+     #xa6 nil nil)
+
+   ;; cmpxchg
+   (def-x86-opcode (cmpxchgq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fb1 #o300 #x48)
+   (def-x86-opcode (cmpxchgq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fb1 #o000 #x48)
+
+   (def-x86-opcode cmpxchgl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fb1 #o300 #x00)
+   (def-x86-opcode cmpxchgl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fb1 #o000 #x00)
+
+   (def-x86-opcode cmpxchgw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fb1 #o300 #x00 #x66)
+   (def-x86-opcode cmpxchgw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fb1 #o000 #x00 #x66)
+
+   (def-x86-opcode cmpxchgb ((:reg8 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fb0 #o300 #x00)
+   (def-x86-opcode cmpxchgb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fb0 #o000 #x00)
+
+   ;; cpuid
+   (def-x86-opcode cpuid ()
+     #x0fa2 nil nil)
+
+   ;; cqto
+   (def-x86-opcode (cqto :cpu64) ()
+     #x99 nil #x48)
+
+   ;; cwtd
+   (def-x86-opcode cwtd ()
+     #x99 nil nil #x66)
+
+   ;; cwtl
+   (def-x86-opcode cwtl ()
+     #x98 nil nil)
+
+   ;; dec (not the 1-byte form).  This exists on x8664, but gas doesn't
+   ;; know that.
+   (def-x86-opcode (decq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xff #o310 #x48)
+   (def-x86-opcode (decq :cpu64) ((:anymem :insert-memory))
+     #xff #o010 #x48)
+
+   (def-x86-opcode (decl :cpuno64) ((:reg32 :insert-opcode-reg))
+     #x48 nil nil)
+   ;; This is valid in 32 bit too, but use it only on x86-64
+   (def-x86-opcode (decl :cpu64) ((:reg32 :insert-modrm-rm))
+     #xff #o310 #x00)
+   (def-x86-opcode decl ((:anymem :insert-memory))
+     #xff #o010 #x00)
+
+   (def-x86-opcode (decw :cpuno64) ((:reg16 :insert-opcode-reg))
+     #x48 nil nil #x66)
+   ;; This is valud in 32 bit too, but use it only on x86-64
+   (def-x86-opcode (decw :cpu64) ((:reg16 :insert-modrm-rm))
+     #xff #o310 #x00 #x66)
+   (def-x86-opcode decw ((:anymem :insert-memory))
+     #xff #o010 #x00 #x66)
+
+   (def-x86-opcode decb ((:reg8 :insert-modrm-rm))
+     #xfe #o310 #x00)
+   (def-x86-opcode decb ((:anymem :insert-memory))
+     #xfe #o010 #x00)
+
+   ;; div
+   (def-x86-opcode (divq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xf7 #o360 #x48)
+   (def-x86-opcode (divq :cpu64) ((:anymem :insert-memory))
+     #xf7 #o060 #x48)
+
+   (def-x86-opcode divl ((:reg32 :insert-modrm-rm))
+     #xf7 #o360 #x00)
+   (def-x86-opcode divl ((:anymem :insert-memory))
+     #xf7 #o060 #x00)
+
+   (def-x86-opcode divw ((:reg16 :insert-modrm-rm))
+     #xf7 #o360 #x00 #x66)
+   (def-x86-opcode divw ((:anymem :insert-memory))
+     #xf7 #o060 #x00 #x66)
+
+   (def-x86-opcode divb ((:reg8 :insert-modrm-rm))
+     #xf6 #o360 #x00)
+   (def-x86-opcode divl ((:anymem :insert-memory))
+     #xf6 #o060 #x00)
+
+   ;; enter.
+
+   (def-x86-opcode enter ((:imm16 :insert-imm16) (:imm8 :insert-extra))
+     #xc8 nil nil)
+
+   ;; hlt
+   (def-x86-opcode hlt ()
+     #xf4 nil nil)
+
+   ;; idiv.  Note that GAS doesn't know about newer(?) idiv forms
+   (def-x86-opcode (idivq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xf7 #o370 #x48)
+   (def-x86-opcode (idivq :cpu64) ((:anymem :insert-memory))
+     #xf7 #o070 #x48)
+
+   (def-x86-opcode idivl ((:reg32 :insert-modrm-rm))
+     #xf7 #o370 #x00)
+   (def-x86-opcode idivl ((:anymem :insert-memory))
+     #xf7 #o070 #x00)
+
+   (def-x86-opcode idivw ((:reg16 :insert-modrm-rm))
+     #xf7 #o370 #x00 #x66)
+   (def-x86-opcode idivw ((:anymem :insert-memory))
+     #xf7 #o070 #x00 #x66)
+
+   (def-x86-opcode idivb ((:reg8 :insert-modrm-rm))
+     #xf6 #o370 #x00)
+   (def-x86-opcode idivl ((:anymem :insert-memory))
+     #xf6 #o070 #x00)
+
+   ;; imul
+   (def-x86-opcode (imulq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xf7 #o350 #x48)
+   (def-x86-opcode (imulq :cpu64) ((:anymem :insert-memory))
+     #xf7 #o050 #x48)
+
+   (def-x86-opcode (imulq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x6b #o300 #x48)
+   (def-x86-opcode (imulq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x6b #o000 #x48)
+   (def-x86-opcode (imulq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x69 #o300 #x48)
+   (def-x86-opcode (imulq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x69 #o000 #x48)
+   (def-x86-opcode (imulq :cpu64) ((:reg64 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0faf #o300 #x48)
+   (def-x86-opcode (imulq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0faf #o000 #x48)   
+
+   
+   (def-x86-opcode imull ((:reg32 :insert-modrm-rm))
+     #xf7 #o350 #x00)
+   (def-x86-opcode imull ((:anymem :insert-memory))
+     #xf7 #o050 #x00)
+
+   (def-x86-opcode imull ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x6b #o300 #x00)
+   (def-x86-opcode imull ((:imm8s :insert-imm8s) (:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x6b #o000 #x00)
+   (def-x86-opcode imull ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x69 #o300 #x00)
+   (def-x86-opcode imull ((:imm32s :insert-imm32s) (:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x69 #o000 #x00)
+   (def-x86-opcode imull ((:reg32 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0faf #o300 #x00)
+   (def-x86-opcode imull ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0faf #o000 #x00)   
+   
+   (def-x86-opcode imulw ((:reg16 :insert-modrm-rm))
+     #xf7 #o350 #x00 #x66)
+   (def-x86-opcode imulw ((:anymem :insert-memory))
+     #xf7 #o050 #x00 #x66)
+
+   (def-x86-opcode imulw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x6b #o300 #x00 #x66)
+   (def-x86-opcode imulw ((:imm8s :insert-imm8s) (:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x6b #o000 #x00 #x66)
+   (def-x86-opcode imulw ((:imm32s :insert-imm32s) (:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x69 #o300 #x00 #x66)
+   (def-x86-opcode imulw ((:imm32s :insert-imm32s) (:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x69 #o000 #x00 #x66)
+   (def-x86-opcode imulw ((:reg16 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0faf #o300 #x00 #x66)
+   (def-x86-opcode imulw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0faf #o000 #x00 #x66)   
+
+   (def-x86-opcode imulb ((:reg8 :insert-modrm-rm))
+     #xf6 #o350 #x00)
+   (def-x86-opcode imulb ((:anymem :insert-memory))
+     #xf6 #o050 #x00)
+
+   ;; inc (but not the one-byte form) is available on x86-64.
+   (def-x86-opcode (incq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xff #o300 #x48)
+   (def-x86-opcode (incq :cpu64) ((:anymem :insert-memory))
+     #xff #o000 #x48)
+
+   (def-x86-opcode (incl :cpuno64) ((:reg32 :insert-opcode-reg))
+     #x40 nil nil)
+   ;; This is valid in 32-bit too, but use it only on x86-64
+   (def-x86-opcode (incl :cpu64) ((:reg32 :insert-modrm-rm))
+     #xff #o300 #x00)
+   (def-x86-opcode incl ((:anymem :insert-memory))
+     #xff #o000 #x00)
+
+   (def-x86-opcode (incw :cpuno64) ((:reg16 :insert-opcode-reg))
+     #x40 nil nil #x66)
+   ;; This is valid in 32-bit too, but use it only on x86-64
+   (def-x86-opcode (incw :cpu64) ((:reg16 :insert-modrm-rm))
+     #xff #o300 #x00 #x66)
+   (def-x86-opcode incw ((:anymem :insert-memory))
+     #xff #o000 #x00 #x66)
+
+   (def-x86-opcode incb ((:reg8 :insert-modrm-rm))
+     #xfe #o300 #x00)
+   (def-x86-opcode incb ((:anymem :insert-memory))
+     #xfe #o000 #x00)
+
+   ;; int.  See also UUOs.
+   (def-x86-opcode int ((:imm8 :insert-imm8-for-int))
+     #xcd nil nil)
+
+   ;; Jcc.  Generate the short form here; maybe relax later.
+   (def-x86-opcode (jcc :jump) ((:imm8 :insert-cc) (:label :insert-label))
+     #x70 nil nil)
+   (def-x86-opcode (jcc.pt :jump) ((:imm8 :insert-cc) (:label :insert-label))
+     #x70 nil nil #x3e)
+   (def-x86-opcode (jcc.pn :jump) ((:imm8 :insert-cc) (:label :insert-label))
+     #x70 nil nil #x2e)
+
+   (def-x86-opcode (jo :jump) ((:label :insert-label))
+     #x70 nil nil)
+   (def-x86-opcode (jo.pt :jump) ((:label :insert-label))
+     #x70 nil nil #x3e)
+   (def-x86-opcode (jo.pn :jump) ((:label :insert-label))
+     #x70 nil nil #x2e)
+   (def-x86-opcode (jno :jump) ((:label :insert-label))
+     #x71 nil nil)
+   (def-x86-opcode (jno.pt :jump) ((:label :insert-label))
+     #x71 nil nil #x3e)
+   (def-x86-opcode (jno.pn :jump) ((:label :insert-label))
+     #x71 nil nil #x2e)
+   (def-x86-opcode (jb :jump) ((:label :insert-label))
+     #x72 nil nil)
+   (def-x86-opcode (jb.pt :jump) ((:label :insert-label))
+     #x72 nil nil #x3e)
+   (def-x86-opcode (jb.pn :jump) ((:label :insert-label))
+     #x72 nil nil #x2e)
+   (def-x86-opcode (jc :jump) ((:label :insert-label))
+     #x72 nil nil)
+   (def-x86-opcode (jc.pt :jump) ((:label :insert-label))
+     #x72 nil nil #x3e)
+   (def-x86-opcode (jc.pn :jump) ((:label :insert-label))
+     #x72 nil nil #x2e)
+   (def-x86-opcode (jae :jump) ((:label :insert-label))
+     #x73 nil nil)
+   (def-x86-opcode (jae.pt :jump) ((:label :insert-label))
+     #x73 nil nil #x3e)
+   (def-x86-opcode (jae.pn :jump) ((:label :insert-label))
+     #x73 nil nil #x2e)
+   (def-x86-opcode (jnc :jump) ((:label :insert-label))
+     #x73 nil nil)
+   (def-x86-opcode (jnc.pt :jump) ((:label :insert-label))
+     #x73 nil nil #x3e)
+   (def-x86-opcode (jnc.pn :jump) ((:label :insert-label))
+     #x73 nil nil #x2e)
+   (def-x86-opcode (je :jump) ((:label :insert-label))
+     #x74 nil nil)
+   (def-x86-opcode (je.pt :jump) ((:label :insert-label))
+     #x74 nil nil #x3e)
+   (def-x86-opcode (je.pn :jump) ((:label :insert-label))
+     #x74 nil nil #x2e)
+   (def-x86-opcode (jz :jump) ((:label :insert-label))
+     #x74 nil nil)
+   (def-x86-opcode (jz.pt :jump) ((:label :insert-label))
+     #x74 nil nil #x3e)
+   (def-x86-opcode (jz.pn :jump) ((:label :insert-label))
+     #x74 nil nil #x2e)
+   (def-x86-opcode (jne :jump) ((:label :insert-label))
+     #x75 nil nil)
+   (def-x86-opcode (jne.pt :jump) ((:label :insert-label))
+     #x75 nil nil #x3e)
+   (def-x86-opcode (jne.pn :jump) ((:label :insert-label))
+     #x75 nil nil #x2e)
+   (def-x86-opcode (jnz :jump) ((:label :insert-label))
+     #x75 nil nil)
+   (def-x86-opcode (jnz.pt :jump) ((:label :insert-label))
+     #x75 nil nil #x3e)
+   (def-x86-opcode (jnz.pn :jump) ((:label :insert-label))
+     #x75 nil nil #x2e)
+   (def-x86-opcode (jbe :jump) ((:label :insert-label))
+     #x76 nil nil)
+   (def-x86-opcode (jbe.pt :jump) ((:label :insert-label))
+     #x76 nil nil #x3e)
+   (def-x86-opcode (jbe.pn :jump) ((:label :insert-label))
+     #x76 nil nil #x2e)
+   (def-x86-opcode (ja :jump) ((:label :insert-label))
+     #x77 nil nil)
+   (def-x86-opcode (ja.pt :jump) ((:label :insert-label))
+     #x77 nil nil #x3e)
+   (def-x86-opcode (ja.pn :jump) ((:label :insert-label))
+     #x77 nil nil #x2e)
+   (def-x86-opcode (js :jump) ((:label :insert-label))
+     #x78 nil nil)
+   (def-x86-opcode (js.pt :jump) ((:label :insert-label))
+     #x78 nil nil #x3e)
+   (def-x86-opcode (js.pn :jump) ((:label :insert-label))
+     #x78 nil nil #x2e)
+   (def-x86-opcode (jns :jump) ((:label :insert-label))
+     #x79 nil nil)
+   (def-x86-opcode (jns.pt :jump) ((:label :insert-label))
+     #x79 nil nil #x3e)
+   (def-x86-opcode (jns.pn :jump) ((:label :insert-label))
+     #x79 nil nil #x2e)
+   (def-x86-opcode (jpe :jump) ((:label :insert-label))
+     #x7a nil nil)
+   (def-x86-opcode (jpe.pt :jump) ((:label :insert-label))
+     #x7a nil nil #x3e)
+   (def-x86-opcode (jpe.pn :jump) ((:label :insert-label))
+     #x7a nil nil #x2e)
+   (def-x86-opcode (jpo :jump) ((:label :insert-label))
+     #x7b nil nil)
+   (def-x86-opcode (jpo.pt :jump) ((:label :insert-label))
+     #x7b nil nil #x3e)
+   (def-x86-opcode (jpo.pn :jump) ((:label :insert-label))
+     #x7b nil nil #x2e)
+   (def-x86-opcode (jl :jump) ((:label :insert-label))
+     #x7c nil nil)
+   (def-x86-opcode (jl.pt :jump) ((:label :insert-label))
+     #x7c nil nil #x3e)
+   (def-x86-opcode (jl.pn :jump) ((:label :insert-label))
+     #x7c nil nil #x2e)
+   (def-x86-opcode (jge :jump) ((:label :insert-label))
+     #x7d nil nil)
+   (def-x86-opcode (jge.pt :jump) ((:label :insert-label))
+     #x7d nil nil #x3e)
+   (def-x86-opcode (jge.pn :jump) ((:label :insert-label))
+     #x7d nil nil #x2e)
+   (def-x86-opcode (jle :jump) ((:label :insert-label))
+     #x7e nil nil)
+   (def-x86-opcode (jle.pt :jump) ((:label :insert-label))
+     #x7e nil nil #x3e)
+   (def-x86-opcode (jle.pn :jump) ((:label :insert-label))
+     #x7e nil nil #x2e)
+   (def-x86-opcode (jg :jump) ((:label :insert-label))
+     #x7f nil nil)
+   (def-x86-opcode (jg.pt :jump) ((:label :insert-label))
+     #x7f nil nil #x3e)
+   (def-x86-opcode (jg.pn :jump) ((:label :insert-label))
+     #x7f nil nil #x2e)
+
+   ;; jmp .  Translating the 8-bit pc-relative version to the 32-bit
+   ;;        pc-relative version happens during relaxation.
+   ;; On 32-bit, I think it's possible to use 16-bit pc-relative
+   ;; displacements---this would save a byte in instances where
+   ;; the displacement fit in 16 bits.
+   (def-x86-opcode (jmp :jump) ((:label :insert-label))
+     #xeb nil nil)
+
+   (def-x86-opcode (jmp :cpu64) ((:reg64 :insert-modrm-rm))
+     #xff #o340 #x0)
+   (def-x86-opcode (jmp :cpuno64) ((:reg32 :insert-modrm-rm))
+     #xff #o340 nil)
+
+   (def-x86-opcode jmp ((:anymem :insert-memory))
+     #xff #o040 #x0)
+
+   ;; lea
+   (def-x86-opcode (leaq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x8d 0 #x48)
+
+   (def-x86-opcode leal ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x8d 0 #x00)
+
+   (def-x86-opcode leaw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x8d 0 #x00 #x66)
+
+   ;; leave
+   (def-x86-opcode leave ()
+     #xc9 nil nil)
+
+   ;; lock
+   (def-x86-opcode lock ()
+     #xf0 nil nil)
+
+   ;; lods
+   (def-x86-opcode lodsq ()
+     #xac nil #x48)
+
+   (def-x86-opcode lodsl ()
+     #xac nil nil)
+
+   ;; loop
+   (def-x86-opcode (loopq :cpu64) ((:label :insert-label))
+     #xe2 nil #x48)
+
+   (def-x86-opcode loopl ((:label :insert-label))
+     #xe2 nil nil)
+
+   (def-x86-opcode (loopzq :cpu64) ((:label :insert-label))
+     #xe1 nil #x48)
+
+   (def-x86-opcode loopzl ((:label :insert-label))
+     #xe1 nil nil)
+
+   (def-x86-opcode (loopnzq :cpu64) ((:label :insert-label))
+     #xe0 nil #x48)
+
+   (def-x86-opcode loopnzl ((:label :insert-label))
+     #xe0 nil nil)
+
+   ;; mov, including the MMX/XMM variants.
+   (def-x86-opcode movq ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0f6f #o300 0)
+   (def-x86-opcode movq ((:regmmx :insert-mmx-reg) (:anymem :insert-memory))
+     #x0f7f #o0 0)
+   (def-x86-opcode movq ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0f6f #o0 0)
+   (def-x86-opcode movq ((:regxmm :insert-xmm-reg) (:regxmm :insert-xmm-rm))
+     #x0f7e #o300 0 #xf3)
+   (def-x86-opcode movq ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f7e #o000 0 #xf3)
+   (def-x86-opcode movq ((:regxmm :insert-xmm-reg) (:anymem :insert-memory))
+     #x0fd6 #o000 0 #x66)
+
+   (def-x86-opcode (movq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x89 #o300 #x48)
+   (def-x86-opcode (movq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x8b #o0 #x48)
+   (def-x86-opcode (movq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x89 #o0 #x48)
+   (def-x86-opcode (movq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #xc7 #o300 #x48)
+   (def-x86-opcode (movq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #xc7 #o000 #x48)
+   (def-x86-opcode (movq :cpu64) ((:imm64 :insert-imm64) (:reg64 :insert-opcode-reg))
+     #xb8 nil #x48)
+
+   (def-x86-opcode movl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x89 #o300 #x00)
+   (def-x86-opcode movl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x8b #o0 #x00)
+   (def-x86-opcode movl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x89 #o0 #x00)
+   (def-x86-opcode movl ((:imm32s :insert-imm32s) (:reg32 :insert-opcode-reg))
+     #xb8 nil #x00)
+   (def-x86-opcode movl ((:self :insert-self) (:reg32 :insert-opcode-reg))
+     #xb8 nil #x00)
+   (def-x86-opcode movl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #xc7 #o000 #x00)
+
+
+   (def-x86-opcode movw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x89 #o300 #x00 #x66)
+   (def-x86-opcode movw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x8b #o0 #x00  #x66)
+   (def-x86-opcode movw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x89 #o0 #x00 #x66)
+   (def-x86-opcode movw ((:imm16 :insert-imm16) (:reg16 :insert-opcode-reg))
+     #xb8 nil #x00 #x66)
+   (def-x86-opcode movw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #xc7 #o000 #x00 #x66)
+
+   (def-x86-opcode movb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x88 #o300 0)
+   (def-x86-opcode movb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x8a #o0 0)
+   (def-x86-opcode movb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x88 #o0 0)
+   (def-x86-opcode movb ((:imm8s :insert-imm8s) (:reg8 :insert-opcode-reg))
+     #xb0 nil 0)
+   (def-x86-opcode movb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #xc6 #o000 0)
+  
+   ;; movd
+   (def-x86-opcode (movd :cpu64) ((:reg64 :insert-modrm-rm) (:regmmx :insert-mmx-reg))
+     #x0f6e #o300 #x48)
+   (def-x86-opcode movd ((:reg32 :insert-modrm-rm) (:regmmx :insert-mmx-reg))
+     #x0f6e #o300 0)
+   (def-x86-opcode movd ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0f6e #o000 0)
+   (def-x86-opcode movd ((:regmmx :insert-mmx-reg) (:reg64 :insert-modrm-rm))
+     #x0f7e #o300 #x48)
+   (def-x86-opcode movd ((:regmmx :insert-mmx-reg) (:reg32 :insert-modrm-rm))
+     #x0f7e #o300 #x0)
+   (def-x86-opcode movd ((:regmmx :insert-mmx-reg) (:anymem :insert-memory))
+     #x0f7e #o000 #x0)
+
+   (def-x86-opcode (movd :cpu64) ((:reg64 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f6e #o300 #x48 #x66)
+   (def-x86-opcode movd ((:reg32 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f6e #o300 0 #x66)
+   (def-x86-opcode movd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f6e #o000 0 #x66)
+   (def-x86-opcode (movd :cpu64) ((:regxmm :insert-xmm-reg) (:reg64 :insert-modrm-rm))
+     #x0f7e #o300 #x48 #x66)
+   (def-x86-opcode movd ((:regxmm :insert-xmm-reg) (:reg32 :insert-modrm-rm))
+     #x0f7e #o300 #x0 #x66)
+   (def-x86-opcode movd ((:regxmm :insert-xmm-reg) (:anymem :insert-memory))
+     #x0f7e #o000 #x0 #x66)
+
+   ;; sign-extending mov
+   (def-x86-opcode movsbl ((:reg8 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0fbe #o300 0)
+   (def-x86-opcode movsbl ((:anymem :insert-memory)  (:reg32 :insert-modrm-reg))
+     #x0fbe #o000 0)
+   (def-x86-opcode movsbw ((:reg8 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fbe #o300 0 #x66)
+   (def-x86-opcode movsbw ((:anymem :insert-memory) (:reg16 :insert-modrm-rm))
+     #x0fbe #o300 0 #x66)
+   (def-x86-opcode (movsbq :cpu64) ((:reg8 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0fbe #o300 #x48)
+   (def-x86-opcode (movsbq :cpu64) ((:anymem :insert-memory)  (:reg64 :insert-modrm-reg))
+     #x0fbe #o000 #x48)
+   (def-x86-opcode movswl ((:reg16 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0fbf #o300 0)
+   (def-x86-opcode movswl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0fbf #o000 0)
+   (def-x86-opcode (movswq :cpu64) ((:reg16 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0fbf #o300 #x48)
+   (def-x86-opcode (movswq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0fbf #o000 #x48)
+   (def-x86-opcode (movslq :cpu64) ((:reg32 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x63 #o300 #x48)
+   (def-x86-opcode (movslq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x63 #o000 #x48)
+
+   ;; zero-extending MOVs
+   (def-x86-opcode movzbl ((:reg8 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0fb6 #o300 0)
+   (def-x86-opcode movzbl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0fb6 #o000 0)
+   (def-x86-opcode movzbw ((:reg8 :insert-modrm-rm) (:reg16 :insert-modrm-reg))
+     #x0fb6 #o300 0 #x66)
+   (def-x86-opcode movzbw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0fb6 #o300 0 #x66)
+   (def-x86-opcode movzwl ((:reg16 :insert-modrm-rm) (:reg32 :insert-modrm-reg))
+     #x0fb7 #o300 0)
+   (def-x86-opcode movzwl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0fb7 #o000 0)
+   (def-x86-opcode (movzbq :cpu64) ((:reg8 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0fb6 #o300 #x48)
+   (def-x86-opcode (movzbq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0fb6 #o000 #x48)
+   (def-x86-opcode (movzwq :cpu64) ((:reg16 :insert-modrm-rm) (:reg64 :insert-modrm-reg))
+     #x0fb7 #o300 #x48)
+   (def-x86-opcode (movzwq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0fb7 #o000 #x48)
+
+   ;; mul
+   (def-x86-opcode (mulq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xf7 #o340 #x48)
+   (def-x86-opcode (mulq :cpu64) ((:anymem :insert-memory))
+     #xf7 #o040 #x48)
+
+   (def-x86-opcode mull ((:reg32 :insert-modrm-rm))
+     #xf7 #o340 #x00)
+   (def-x86-opcode mull ((:anymem :insert-memory))
+     #xf7 #o040 #x00)
+
+   (def-x86-opcode mulw ((:reg16 :insert-modrm-rm))
+     #xf7 #o340 #x00 #x66)
+   (def-x86-opcode mulw ((:anymem :insert-memory))
+     #xf7 #o040 #x00 #x66)
+
+   (def-x86-opcode mulb ((:reg8 :insert-modrm-rm))
+     #xf6 #o340 #x00)
+   (def-x86-opcode mull ((:anymem :insert-memory))
+     #xf6 #o040 #x00)
+
+   ;; neg
+   (def-x86-opcode (negq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xf7 #o330 #x48)
+   (def-x86-opcode (negq :cpu64) ((:anymem :insert-memory))
+     #xf7 #o030 #x48)
+
+   (def-x86-opcode negl ((:reg32 :insert-modrm-rm))
+     #xf7 #o330 #x00)
+   (def-x86-opcode negl ((:anymem :insert-memory))
+     #xf7 #o030 #x00)
+
+   (def-x86-opcode negw ((:reg16 :insert-modrm-rm))
+     #xf7 #o330 #x00 #x66)
+   (def-x86-opcode negw ((:anymem :insert-memory))
+     #xf7 #o030 #x00 #x66)
+
+   (def-x86-opcode negb ((:reg8 :insert-modrm-rm))
+     #xf6 #o330 #x00)
+   (def-x86-opcode negb ((:anymem :insert-memory))
+     #xf6 #o030 #x00)
+
+   ;; nop
+   (def-x86-opcode nop ()
+     #x90 nil nil)
+
+   ;; not
+   (def-x86-opcode (notq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xf7 #o320 #x48)
+   (def-x86-opcode (notq :cpu64) ((:anymem :insert-memory))
+     #xf7 #o020 #x48)
+   (def-x86-opcode notl ((:reg32 :insert-modrm-rm))
+     #xf7 #o320 #x0)
+   (def-x86-opcode notl ((:anymem :insert-memory))
+     #xf7 #o020 #x0)
+   (def-x86-opcode notw ((:reg16 :insert-modrm-rm))
+     #xf7 #o320 #x0 #x66)
+   (def-x86-opcode notw ((:anymem :insert-memory))
+     #xf7 #o020 #x0 #x66)
+   (def-x86-opcode notb ((:reg8 :insert-modrm-rm))
+     #xf6 #o320 #x0)
+   (def-x86-opcode notb ((:anymem :insert-memory))
+     #xf6 #o020 #x0)
+
+   ;; or
+   (def-x86-opcode (orq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x09 #o300 #x48)
+   (def-x86-opcode (orq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0b #o000 #x48)
+   (def-x86-opcode (orq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x09 #x00 #x48)
+   (def-x86-opcode (orq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o310 #x48)
+   (def-x86-opcode (orq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x0d nil #x48)
+   (def-x86-opcode (orq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o310 #x48)
+   (def-x86-opcode (orq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o010 #x48)
+   (def-x86-opcode (orq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o010 #x48)
+
+   (def-x86-opcode orl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x09 #o300 #x00)
+   (def-x86-opcode orl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0b #o000 #x00)
+   (def-x86-opcode orl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x09 #x00 #x00)
+   (def-x86-opcode orl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o310 #x00)
+   (def-x86-opcode orl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x0d nil nil)
+   (def-x86-opcode orl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o310 #x00)
+   (def-x86-opcode orl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o010 #x00)
+   (def-x86-opcode orl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o010 #x00)
+
+   (def-x86-opcode orw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x09 #o300 #x00 #x66)
+   (def-x86-opcode orw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x0b #o000 #x00 #x66)
+   (def-x86-opcode orw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x09 #x00 #x00 #x66)
+   (def-x86-opcode orw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o310 #x00 #x66)
+   (def-x86-opcode orw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x0d nil nil #x66)
+   (def-x86-opcode orw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o310 #x00 #x66)
+   (def-x86-opcode orw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o010 #x00 #x66)
+   (def-x86-opcode orw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o010 #x00 #x66)
+
+   (def-x86-opcode orb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x08 #o300 #x00)
+   (def-x86-opcode orb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x0a #o000 #x00)
+   (def-x86-opcode orb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x08 #x00 #x00)
+   (def-x86-opcode orb ((:imm8s :insert-imm8s) (:acc :insert-nothing))
+     #x0c nil nil)
+   (def-x86-opcode orb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o310 #x00)
+   (def-x86-opcode orb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o310 #x00)
+   (def-x86-opcode orb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x80 #o010 #x00)
+
+   ;; pop
+   (def-x86-opcode (popq :cpu64) ((:reg64 :insert-opcode-reg))
+     #x58 nil #x0)
+   (def-x86-opcode (popq :cpu64) ((:anymem :insert-memory))
+     #x8f #o000 #x0)
+
+   (def-x86-opcode (popl :cpuno64) ((:reg32 :insert-opcode-reg))
+     #x58 nil nil)
+   (def-x86-opcode (popl :cpuno64) ((:anymem :insert-memory))
+     #x8f #o000 nil)
+
+   (def-x86-opcode popw ((:reg16 :insert-opcode-reg))
+     #x58 nil #x0 #x66)
+   (def-x86-opcode popw ((:anymem :insert-memory))
+     #x8f #o000 #x0 #x66)
+
+   ;; popf
+   (def-x86-opcode (popfq :cpu64) ()
+     #x9d nil #x48)
+   (def-x86-opcode popfl ()
+     #x9d nil nil)
+
+   ;; push .  It's not clear how "pushw $imm16" is encoded.
+   (def-x86-opcode (pushq :cpu64) ((:reg64 :insert-opcode-reg))
+     #x50 nil #x0)
+   (def-x86-opcode (pushq :cpu64) ((:anymem :insert-memory))
+     #xff #o060 #x0)
+   (def-x86-opcode (pushq :cpu64) ((:imm8s :insert-imm8s))
+     #x6a nil nil)
+   (def-x86-opcode (pushq :cpu64) ((:imm32s :insert-imm32s))
+     #x68 nil nil)
+
+   (def-x86-opcode (pushl :cpuno64) ((:reg32 :insert-opcode-reg))
+     #x50 nil nil)
+   (def-x86-opcode (pushl :cpuno64) ((:anymem :insert-memory))
+     #xff #o060 nil)
+   (def-x86-opcode (pushl :cpuno64) ((:imm8s :insert-imm8s))
+     #x6a nil nil)
+   (def-x86-opcode (pushl :cpuno64) ((:imm32s :insert-imm32s))
+     #x68 nil nil)
+
+   (def-x86-opcode pushw ((:reg16 :insert-opcode-reg))
+     #x50 nil 0 #x66)
+   (def-x86-opcode pushw ((:anymem :insert-memory))
+     #xff #o060 #x0 #x66)
+
+   ;; pushf
+   (def-x86-opcode (pushfq :cpu64) ()
+     #x9c nil nil)
+   (def-x86-opcode (pushfl :cpuno64) ()
+     #x9c nil nil)
+   (def-x86-opcode pushfw ()
+     #x9c nil nil #x66)
+
+   ;; rcl.  Note that the :ShiftCount operand type only matches %cl.
+   (def-x86-opcode (rclq :cpu64) ((:imm1 :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd1 #o320 #x48)
+   (def-x86-opcode (rclq :cpu64) ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o020 #x48)
+   (def-x86-opcode (rclq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xd1 #o320 #x48)
+   (def-x86-opcode (rclq :cpu64) ((:anymem :insert-memory))
+     #xd1 #o020 #x48)
+   (def-x86-opcode (rclq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #xc1 #o320 #x48)
+   (def-x86-opcode (rclq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd3 #o320 #x48)
+  
+   (def-x86-opcode rcll ((:imm1 :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd1 #o320 #x0)
+   (def-x86-opcode rcll ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o020 #x0)
+   (def-x86-opcode rcll ((:reg32 :insert-modrm-rm))
+     #xd1 #o320 #x0)
+   (def-x86-opcode rcll ((:anymem :insert-memory))
+     #xd1 #o020 #x0)
+   (def-x86-opcode rcll ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #xc1 #o320 #x0)
+   (def-x86-opcode rcll ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd3 #o320 #x0)
+
+   (def-x86-opcode rclw ((:imm1 :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd1 #o320 #x0 #x66)
+   (def-x86-opcode rclw ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o020 #x0 #x66)
+   (def-x86-opcode rclw ((:reg16 :insert-modrm-rm))
+     #xd1 #o320 #x0 #x66)
+   (def-x86-opcode rclw ((:anymem :insert-memory))
+     #xd1 #o020 #x0 #x66)
+   (def-x86-opcode rclw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #xc1 #o320 #x0 #x66)
+   (def-x86-opcode rclw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd3 #o320 #x0 #x66)
+
+   (def-x86-opcode rclb ((:imm1 :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd0 #o320 #x0)
+   (def-x86-opcode rclb ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd0 #o020 #x0)
+   (def-x86-opcode rclb ((:reg8 :insert-modrm-rm))
+     #xd0 #o320 #x0)
+   (def-x86-opcode rclb ((:anymem :insert-memory))
+     #xd0 #o020 #x0)
+   (def-x86-opcode rclb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #xc0 #o320 #x0)
+   (def-x86-opcode rclb ((:shiftcount :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd2 #o320 #x0)
+
+   ;; rcr
+   (def-x86-opcode (rcrq :cpu64) ((:imm1 :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd1 #o330 #x48)
+   (def-x86-opcode (rcrq :cpu64) ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o030 #x48)
+   (def-x86-opcode (rcrq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xd1 #o330 #x48)
+   (def-x86-opcode (rcrq :cpu64) ((:anymem :insert-memory))
+     #xd1 #o030 #x48)
+   (def-x86-opcode (rcrq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #xc1 #o330 #x48)
+   (def-x86-opcode (rcrq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd3 #o330 #x48)
+  
+   (def-x86-opcode rcrl ((:imm1 :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd1 #o330 #x0)
+   (def-x86-opcode rcrl ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o030 #x0)
+   (def-x86-opcode rcrl ((:reg32 :insert-modrm-rm))
+     #xd1 #o330 #x0)
+   (def-x86-opcode rcrl ((:anymem :insert-memory))
+     #xd1 #o030 #x0)
+   (def-x86-opcode rcrl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #xc1 #o330 #x0)
+   (def-x86-opcode rcrl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd3 #o330 #x0)
+
+   (def-x86-opcode rcrw ((:imm1 :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd1 #o330 #x0 #x66)
+   (def-x86-opcode rcrw ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o030 #x0 #x66)
+   (def-x86-opcode rcrw ((:reg16 :insert-modrm-rm))
+     #xd1 #o330 #x0 #x66)
+   (def-x86-opcode rcrw ((:anymem :insert-memory))
+     #xd1 #o030 #x0 #x66)
+   (def-x86-opcode rcrw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #xc1 #o330 #x0 #x66)
+   (def-x86-opcode rcrw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd3 #o330 #x0 #x66)
+
+   (def-x86-opcode rcrb ((:imm1 :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd0 #o330 #x0)
+   (def-x86-opcode rcrb ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd0 #o030 #x0)
+   (def-x86-opcode rcrb ((:reg8 :insert-modrm-rm))
+     #xd0 #o330 #x0)
+   (def-x86-opcode rcrb ((:anymem :insert-memory))
+     #xd0 #o030 #x0)
+   (def-x86-opcode rcrb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #xc0 #o330 #x0)
+   (def-x86-opcode rcrb ((:shiftcount :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd2 #o330 #x0)
+
+   ;; repe, repne.  These are really prefixes, that should
+   ;; only be used before string instructions.
+   (def-x86-opcode repe ()
+     #xf3 nil nil)
+
+   (def-x86-opcode repne ()
+     #xf2 nil nil)
+
+   ;; ret
+   (def-x86-opcode ret ()
+     #xc3 nil nil)
+
+   (def-x86-opcode ret ((:imm16 :insert-imm16))
+     #xc2 nil nil)
+
+   ;; rol
+   (def-x86-opcode (rolq :cpu64) ((:imm1 :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd1 #o300 #x48)
+   (def-x86-opcode (rolq :cpu64) ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o000 #x48)
+   (def-x86-opcode (rolq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xd1 #o300 #x48)
+   (def-x86-opcode (rolq :cpu64) ((:anymem :insert-memory))
+     #xd1 #o000 #x48)
+   (def-x86-opcode (rolq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #xc1 #o300 #x48)
+   (def-x86-opcode (rolq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd3 #o300 #x48)
+  
+   (def-x86-opcode roll ((:imm1 :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd1 #o300 #x0)
+   (def-x86-opcode roll ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o000 #x0)
+   (def-x86-opcode roll ((:reg32 :insert-modrm-rm))
+     #xd1 #o300 #x0)
+   (def-x86-opcode roll ((:anymem :insert-memory))
+     #xd1 #o000 #x0)
+   (def-x86-opcode roll ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #xc1 #o300 #x0)
+   (def-x86-opcode roll ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd3 #o300 #x0)
+
+   (def-x86-opcode rolw ((:imm1 :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd1 #o300 #x0 #x66)
+   (def-x86-opcode rolw ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o000 #x0 #x66)
+   (def-x86-opcode rolw ((:reg16 :insert-modrm-rm))
+     #xd1 #o300 #x0 #x66)
+   (def-x86-opcode rolw ((:anymem :insert-memory))
+     #xd1 #o000 #x0 #x66)
+   (def-x86-opcode rolw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #xc1 #o300 #x0 #x66)
+   (def-x86-opcode rolw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd3 #o300 #x0 #x66)
+
+   (def-x86-opcode rolb ((:imm1 :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd0 #o300 #x0)
+   (def-x86-opcode rolb ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd0 #o000 #x0)
+   (def-x86-opcode rolb ((:reg8 :insert-modrm-rm))
+     #xd0 #o300 #x0)
+   (def-x86-opcode rolb ((:anymem :insert-memory))
+     #xd0 #o000 #x0)
+   (def-x86-opcode rolb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #xc0 #o300 #x0)
+   (def-x86-opcode rolb ((:shiftcount :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd2 #o300 #x0)
+
+   ;; ror
+   (def-x86-opcode (rorq :cpu64) ((:imm1 :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd1 #o310 #x48)
+   (def-x86-opcode (rorq :cpu64) ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o010 #x48)
+   (def-x86-opcode (rorq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xd1 #o310 #x48)
+   (def-x86-opcode (rorq :cpu64) ((:anymem :insert-memory))
+     #xd1 #o010 #x48)
+   (def-x86-opcode (rorq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #xc1 #o310 #x48)
+   (def-x86-opcode (rorq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd3 #o310 #x48)
+  
+   (def-x86-opcode rorl ((:imm1 :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd1 #o310 #x0)
+   (def-x86-opcode rorl ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o010 #x0)
+   (def-x86-opcode rorl ((:reg32 :insert-modrm-rm))
+     #xd1 #o310 #x0)
+   (def-x86-opcode rorl ((:anymem :insert-memory))
+     #xd1 #o010 #x0)
+   (def-x86-opcode rorl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #xc1 #o310 #x0)
+   (def-x86-opcode rorl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd3 #o310 #x0)
+
+   (def-x86-opcode rorw ((:imm1 :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd1 #o310 #x0 #x66)
+   (def-x86-opcode rorw ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o010 #x0 #x66)
+   (def-x86-opcode rorw ((:reg16 :insert-modrm-rm))
+     #xd1 #o310 #x0 #x66)
+   (def-x86-opcode rorw ((:anymem :insert-memory))
+     #xd1 #o010 #x0 #x66)
+   (def-x86-opcode rorw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #xc1 #o310 #x0 #x66)
+   (def-x86-opcode rorw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd3 #o310 #x0 #x66)
+
+   (def-x86-opcode rorb ((:imm1 :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd0 #o310 #x0)
+   (def-x86-opcode rorb ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd0 #o010 #x0)
+   (def-x86-opcode rorb ((:reg8 :insert-modrm-rm))
+     #xd0 #o310 #x0)
+   (def-x86-opcode rorb ((:anymem :insert-memory))
+     #xd0 #o010 #x0)
+   (def-x86-opcode rorb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #xc0 #o310 #x0)
+   (def-x86-opcode rorb ((:shiftcount :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd2 #o310 #x0)
+
+   ;; sar
+   (def-x86-opcode (sarq :cpu64) ((:imm1 :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd1 #o370 #x48)
+   (def-x86-opcode (sarq :cpu64) ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o070 #x48)
+   (def-x86-opcode (sarq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xd1 #o370 #x48)
+   (def-x86-opcode (sarq :cpu64) ((:anymem :insert-memory))
+     #xd1 #o070 #x48)
+   (def-x86-opcode (sarq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #xc1 #o370 #x48)
+   (def-x86-opcode (sarq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd3 #o370 #x48)
+  
+   (def-x86-opcode sarl ((:imm1 :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd1 #o370 #x0)
+   (def-x86-opcode sarl ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o070 #x0)
+   (def-x86-opcode sarl ((:reg32 :insert-modrm-rm))
+     #xd1 #o370 #x0)
+   (def-x86-opcode sarl ((:anymem :insert-memory))
+     #xd1 #o070 #x0)
+   (def-x86-opcode sarl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #xc1 #o370 #x0)
+   (def-x86-opcode sarl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd3 #o370 #x0)
+
+   (def-x86-opcode sarw ((:imm1 :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd1 #o370 #x0 #x66)
+   (def-x86-opcode sarw ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o070 #x0 #x66)
+   (def-x86-opcode sarw ((:reg16 :insert-modrm-rm))
+     #xd1 #o370 #x0 #x66)
+   (def-x86-opcode sarw ((:anymem :insert-memory))
+     #xd1 #o070 #x0 #x66)
+   (def-x86-opcode sarw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #xc1 #o370 #x0 #x66)
+   (def-x86-opcode sarw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd3 #o370 #x0 #x66)
+
+   (def-x86-opcode sarb ((:imm1 :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd0 #o370 #x0)
+   (def-x86-opcode sarb ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd0 #o070 #x0)
+   (def-x86-opcode sarb ((:reg8 :insert-modrm-rm))
+     #xd0 #o370 #x0)
+   (def-x86-opcode sarb ((:anymem :insert-memory))
+     #xd0 #o070 #x0)
+   (def-x86-opcode sarb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #xc0 #o370 #x0)
+   (def-x86-opcode sarb ((:shiftcount :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd2 #o370 #x0)
+
+   ;; sbb
+   (def-x86-opcode (sbbq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x19 #o300 #x48)
+   (def-x86-opcode (sbbq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x1b #o000 #x48)
+   (def-x86-opcode (sbbq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x19 #x00 #x48)
+   (def-x86-opcode (sbbq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o330 #x48)
+   (def-x86-opcode (sbbq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x1d nil #x48)
+   (def-x86-opcode (sbbq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o330 #x48)
+   (def-x86-opcode (sbbq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o030 #x48)
+   (def-x86-opcode (sbbq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o030 #x48)
+
+   (def-x86-opcode sbbl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x19 #o300 #x00)
+   (def-x86-opcode sbbl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x1b #o000 #x00)
+   (def-x86-opcode sbbl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x19 #x00 #x00)
+   (def-x86-opcode sbbl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o330 #x00)
+   (def-x86-opcode sbbl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x1d nil nil)
+   (def-x86-opcode sbbl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o330 #x00)
+   (def-x86-opcode sbbl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o030 #x00)
+   (def-x86-opcode sbbl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o030 #x00)
+
+   (def-x86-opcode sbbw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x19 #o300 #x00 #x66)
+   (def-x86-opcode sbbw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x1b #o000 #x00 #x66)
+   (def-x86-opcode sbbw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x19 #x00 #x00 #x66)
+   (def-x86-opcode sbbw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o330 #x00 #x66)
+   (def-x86-opcode sbbw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x1d nil nil #x66)
+   (def-x86-opcode sbbw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o330 #x00 #x66)
+   (def-x86-opcode sbbw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o030 #x00 #x66)
+   (def-x86-opcode sbbw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o030 #x00 #x66)
+
+   (def-x86-opcode sbbb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x18 #o300 #x00)
+   (def-x86-opcode sbbb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x1a #o000 #x00)
+   (def-x86-opcode sbbb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x18 #x00 #x00)
+   (def-x86-opcode sbbb ((:imm8 :insert-imm8) (:acc :insert-nothing))
+     #x1c nil nil)
+   (def-x86-opcode sbbb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o330 #x00)
+   (def-x86-opcode sbbb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o330 #x00)
+   (def-x86-opcode sbbb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x80 #o030 #x00)
+
+   ;; scas
+   (def-x86-opcode (scasq :cpu64) ()
+     #xaf nil #x48)
+   (def-x86-opcode scasl ()
+     #xaf nil nil)
+   (def-x86-opcode scasw ()
+     #xaf nil nil #x66)
+   (def-x86-opcode scasb ()
+     #xae nil nil)
+
+
+   ;; setcc
+   (def-x86-opcode setcc ((:imm8 :insert-cc) (:reg8 :insert-modrm-rm))
+     #x0f90 #o300 0)     
+   (def-x86-opcode seto ((:reg8 :insert-modrm-rm))
+     #x0f90 #o300 0)
+   (def-x86-opcode seto ((:anymem :insert-memory))
+     #x0f90 #o000 0)
+   (def-x86-opcode setno ((:reg8 :insert-modrm-rm))
+     #x0f91 #o300 0)
+   (def-x86-opcode setno ((:anymem :insert-memory))
+     #x0f91 #o000 0)
+   (def-x86-opcode setb ((:reg8 :insert-modrm-rm))
+     #x0f92 #o300 0)
+   (def-x86-opcode setb ((:anymem :insert-memory))
+     #x0f92 #o000 0)
+   (def-x86-opcode setc ((:reg8 :insert-modrm-rm))
+     #x0f92 #o300 0)
+   (def-x86-opcode setc ((:anymem :insert-memory))
+     #x0f92 #o000 0)
+   (def-x86-opcode setae ((:reg8 :insert-modrm-rm))
+     #x0f93 #o300 0)
+   (def-x86-opcode setae ((:anymem :insert-memory))
+     #x0f93 #o000 0)
+   (def-x86-opcode sete ((:reg8 :insert-modrm-rm))
+     #x0f94 #o300 0)
+   (def-x86-opcode sete ((:anymem :insert-memory))
+     #x0f94 #o000 0)
+   (def-x86-opcode setne ((:reg8 :insert-modrm-rm))
+     #x0f95 #o300 0)
+   (def-x86-opcode setne ((:anymem :insert-memory))
+     #x0f95 #o000 0)
+   (def-x86-opcode setbe ((:reg8 :insert-modrm-rm))
+     #x0f96 #o300 0)
+   (def-x86-opcode setbe ((:anymem :insert-memory))
+     #x0f96 #o000 0)
+   (def-x86-opcode seta ((:reg8 :insert-modrm-rm))
+     #x0f97 #o300 0)
+   (def-x86-opcode seta ((:anymem :insert-memory))
+     #x0f97 #o000 0)
+   (def-x86-opcode sets ((:reg8 :insert-modrm-rm))
+     #x0f98 #o300 0)
+   (def-x86-opcode sets ((:anymem :insert-memory))
+     #x0f98 #o000 0)
+   (def-x86-opcode setns ((:reg8 :insert-modrm-rm))
+     #x0f99 #o300 0)
+   (def-x86-opcode setns ((:anymem :insert-memory))
+     #x0f99 #o000 0)
+   (def-x86-opcode setpe ((:reg8 :insert-modrm-rm))
+     #x0f9a #o300 0)
+   (def-x86-opcode setpe ((:anymem :insert-memory))
+     #x0f9a #o000 0)
+   (def-x86-opcode setpo ((:reg8 :insert-modrm-rm))
+     #x0f9b #o300 0)
+   (def-x86-opcode setpo ((:anymem :insert-memory))
+     #x0f9b #o000 0)
+   (def-x86-opcode setl ((:reg8 :insert-modrm-rm))
+     #x0f9c #o300 0)
+   (def-x86-opcode setl ((:anymem :insert-memory))
+     #x0f9c #o000 0)
+   (def-x86-opcode setge ((:reg8 :insert-modrm-rm))
+     #x0f9d #o300 0)
+   (def-x86-opcode setge ((:anymem :insert-memory))
+     #x0f9d #o000 0)
+   (def-x86-opcode setle ((:reg8 :insert-modrm-rm))
+     #x0f9e #o300 0)
+   (def-x86-opcode setle ((:anymem :insert-memory))
+     #x0f9e #o000 0)
+   (def-x86-opcode setg ((:reg8 :insert-modrm-rm))
+     #x0f9f #o300 0)
+   (def-x86-opcode setg ((:anymem :insert-memory))
+     #x0f9f #o000 0)
+
+   ;; shl
+   (def-x86-opcode (shlq :cpu64) ((:imm1 :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd1 #o340 #x48)
+   (def-x86-opcode (shlq :cpu64) ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o040 #x48)
+   (def-x86-opcode (shlq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xd1 #o340 #x48)
+   (def-x86-opcode (shlq :cpu64) ((:anymem :insert-memory))
+     #xd1 #o040 #x48)
+   (def-x86-opcode (shlq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #xc1 #o340 #x48)
+   (def-x86-opcode (shlq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd3 #o340 #x48)
+  
+   (def-x86-opcode shll ((:imm1 :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd1 #o340 #x0)
+   (def-x86-opcode shll ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o040 #x0)
+   (def-x86-opcode shll ((:reg32 :insert-modrm-rm))
+     #xd1 #o340 #x0)
+   (def-x86-opcode shll ((:anymem :insert-memory))
+     #xd1 #o040 #x0)
+   (def-x86-opcode shll ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #xc1 #o340 #x0)
+   (def-x86-opcode shll ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd3 #o340 #x0)
+
+   (def-x86-opcode shlw ((:imm1 :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd1 #o340 #x0 #x66)
+   (def-x86-opcode shlw ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o040 #x0 #x66)
+   (def-x86-opcode shlw ((:reg16 :insert-modrm-rm))
+     #xd1 #o340 #x0 #x66)
+   (def-x86-opcode shlw ((:anymem :insert-memory))
+     #xd1 #o040 #x0 #x66)
+   (def-x86-opcode shlw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #xc1 #o340 #x0 #x66)
+   (def-x86-opcode shlw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd3 #o340 #x0 #x66)
+
+   (def-x86-opcode shlb ((:imm1 :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd0 #o340 #x0)
+   (def-x86-opcode shlb ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd0 #o040 #x0)
+   (def-x86-opcode shlb ((:reg8 :insert-modrm-rm))
+     #xd0 #o340 #x0)
+   (def-x86-opcode shlb ((:anymem :insert-memory))
+     #xd0 #o040 #x0)
+   (def-x86-opcode shlb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #xc0 #o340 #x0)
+   (def-x86-opcode shlb ((:shiftcount :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd2 #o340 #x0)
+
+   ;; shld
+   (def-x86-opcode (shldq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fa4 #o300 #x48)
+   (def-x86-opcode (shldq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa4 #o000 #x48)
+   (def-x86-opcode (shldq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fa5 #o300 #x48)
+   (def-x86-opcode (shldq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa5 #o000 #x48)
+   (def-x86-opcode (shldq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fa5 #o300 #x48)
+   (def-x86-opcode (shldq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa5 #o000 #x48)
+
+   (def-x86-opcode shldl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fa4 #o300 #x0)
+   (def-x86-opcode shldl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa4 #o000 #x0)
+   (def-x86-opcode shldl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fa5 #o300 #x0)
+   (def-x86-opcode shldl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa5 #o000 #x0)
+   (def-x86-opcode shldl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fa5 #o300 #x0)
+   (def-x86-opcode shldl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa5 #o000 #x0)
+
+   (def-x86-opcode shldw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fa4 #o300 #x0 #x66)
+   (def-x86-opcode shldw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa4 #o000 #x0 #x66)
+   (def-x86-opcode shldw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fa5 #o300 #x0 #x66)
+   (def-x86-opcode shldw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa5 #o000 #x0 #x66)
+   (def-x86-opcode shldw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fa5 #o300 #x0 #x66)
+   (def-x86-opcode shldw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fa5 #o000 #x0 #x66)
+
+   ;; shr
+   (def-x86-opcode (shrq :cpu64) ((:imm1 :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd1 #o350 #x48)
+   (def-x86-opcode (shrq :cpu64) ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o050 #x48)
+   (def-x86-opcode (shrq :cpu64) ((:reg64 :insert-modrm-rm))
+     #xd1 #o350 #x48)
+   (def-x86-opcode (shrq :cpu64) ((:anymem :insert-memory))
+     #xd1 #o050 #x48)
+   (def-x86-opcode (shrq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-rm))
+     #xc1 #o350 #x48)
+   (def-x86-opcode (shrq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-rm))
+     #xd3 #o350 #x48)
+  
+   (def-x86-opcode shrl ((:imm1 :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd1 #o350 #x0)
+   (def-x86-opcode shrl ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o050 #x0)
+   (def-x86-opcode shrl ((:reg32 :insert-modrm-rm))
+     #xd1 #o350 #x0)
+   (def-x86-opcode shrl ((:anymem :insert-memory))
+     #xd1 #o050 #x0)
+   (def-x86-opcode shrl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-rm))
+     #xc1 #o350 #x0)
+   (def-x86-opcode shrl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-rm))
+     #xd3 #o350 #x0)
+
+   (def-x86-opcode shrw ((:imm1 :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd1 #o350 #x0 #x66)
+   (def-x86-opcode shrw ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd1 #o050 #x0 #x66)
+   (def-x86-opcode shrw ((:reg16 :insert-modrm-rm))
+     #xd1 #o350 #x0 #x66)
+   (def-x86-opcode shrw ((:anymem :insert-memory))
+     #xd1 #o050 #x0 #x66)
+   (def-x86-opcode shrw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-rm))
+     #xc1 #o350 #x0 #x66)
+   (def-x86-opcode shrw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-rm))
+     #xd3 #o350 #x0 #x66)
+
+   (def-x86-opcode shrb ((:imm1 :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd0 #o350 #x0)
+   (def-x86-opcode shrb ((:imm1 :insert-nothing) (:anymem :insert-memory))
+     #xd0 #o050 #x0)
+   (def-x86-opcode shrb ((:reg8 :insert-modrm-rm))
+     #xd0 #o350 #x0)
+   (def-x86-opcode shrb ((:anymem :insert-memory))
+     #xd0 #o050 #x0)
+   (def-x86-opcode shrb ((:imm8 :insert-imm8) (:reg8 :insert-modrm-rm))
+     #xc0 #o350 #x0)
+   (def-x86-opcode shrb ((:shiftcount :insert-nothing) (:reg8 :insert-modrm-rm))
+     #xd2 #o350 #x0)
+
+   ;; shrd
+   (def-x86-opcode (shrdq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fac #o300 #x48)
+   (def-x86-opcode (shrdq :cpu64) ((:imm8 :insert-imm8) (:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fac #o000 #x48)
+   (def-x86-opcode (shrdq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fad #o300 #x48)
+   (def-x86-opcode (shrdq :cpu64) ((:shiftcount :insert-nothing) (:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fad #o000 #x48)
+   (def-x86-opcode (shrdq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fad #o300 #x48)
+   (def-x86-opcode (shrdq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fad #o000 #x48)
+
+   (def-x86-opcode shrdl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fac #o300 #x0)
+   (def-x86-opcode shrdl ((:imm8 :insert-imm8) (:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fac #o000 #x0)
+   (def-x86-opcode shrdl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fad #o300 #x0)
+   (def-x86-opcode shrdl ((:shiftcount :insert-nothing) (:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fad #o000 #x0)
+   (def-x86-opcode shrdl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fad #o300 #x0)
+   (def-x86-opcode shrdl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fad #o000 #x0)
+
+   (def-x86-opcode shrdw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fac #o300 #x0 #x66)
+   (def-x86-opcode shrdw ((:imm8 :insert-imm8) (:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fac #o000 #x0 #x66)
+   (def-x86-opcode shrdw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fad #o300 #x0 #x66)
+   (def-x86-opcode shrdw ((:shiftcount :insert-nothing) (:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fad #o000 #x0 #x66)
+   (def-x86-opcode shrdw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fad #o300 #x0 #x66)
+   (def-x86-opcode shrdw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fad #o000 #x0 #x66)
+
+   ;; stc
+   (def-x86-opcode stc ()
+     #xf9 nil nil)
+
+   ;; std
+   (def-x86-opcode std ()
+     #xfd nil nil)
+
+   ;; sub
+   (def-x86-opcode (subq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x29 #o300 #x48)
+   (def-x86-opcode (subq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x2b #o000 #x48)
+   (def-x86-opcode (subq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x29 #x00 #x48)
+   (def-x86-opcode (subq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o350 #x48)
+   (def-x86-opcode (subq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x2d nil #x48)
+   (def-x86-opcode (subq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o350 #x48)
+   (def-x86-opcode (subq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o050 #x48)
+   (def-x86-opcode (subq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o050 #x48)
+
+   (def-x86-opcode subl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x29 #o300 #x00)
+   (def-x86-opcode subl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x2b #o000 #x00)
+   (def-x86-opcode subl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x29 #x00 #x00)
+   (def-x86-opcode subl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o350 #x00)
+   (def-x86-opcode subl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x2d nil nil)
+   (def-x86-opcode subl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o350 #x00)
+   (def-x86-opcode subl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o050 #x00)
+   (def-x86-opcode subl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o050 #x00)
+
+   (def-x86-opcode subw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x29 #o300 #x00 #x66)
+   (def-x86-opcode subw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x2b #o000 #x00 #x66)
+   (def-x86-opcode subw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x29 #x00 #x00 #x66)
+   (def-x86-opcode subw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o350 #x00 #x66)
+   (def-x86-opcode subw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x2d nil nil #x66)
+   (def-x86-opcode subw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o350 #x00 #x66)
+   (def-x86-opcode subw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o050 #x00 #x66)
+   (def-x86-opcode subw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o050 #x00 #x66)
+
+   (def-x86-opcode subb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x28 #o300 #x00)
+   (def-x86-opcode subb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x2a #o000 #x00)
+   (def-x86-opcode subb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x2a #x00 #x00)
+   (def-x86-opcode subb ((:imm8s :insert-imm8s) (:acc :insert-nothing))
+     #x2c nil nil)
+   (def-x86-opcode subb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o350 #x00)
+   (def-x86-opcode subb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o350 #x00)
+   (def-x86-opcode subb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x80 #o050 #x00)
+
+   ;; syscall
+   (def-x86-opcode (syscall :cpu64) ()
+     #x0f0f nil nil)
+
+   ;; test
+   (def-x86-opcode (testq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x85 #o300 #x48)
+   (def-x86-opcode (testq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x85 #o000 #x48)
+   (def-x86-opcode (testq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x85 #o000 #x48)
+   (def-x86-opcode (testq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #xa9 nil #x48)
+   (def-x86-opcode (testq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #xf7 #o300 #x48)
+   (def-x86-opcode (testq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #xf7 #o000 #x48)
+
+   (def-x86-opcode testl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x85 #o300 #x00)
+   (def-x86-opcode testl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x85 #o000 #x00)
+   (def-x86-opcode testl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x85 #o000 #x00)
+   (def-x86-opcode testl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #xa9 nil #x00)
+   (def-x86-opcode testl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #xf7 #o300 #x00)
+   (def-x86-opcode testl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #xf7 #o000 #x00)
+
+
+   (def-x86-opcode testw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x85 #o300 #x00 #x66)
+   (def-x86-opcode testw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x85 #o000 #x00 #x66)
+   (def-x86-opcode testw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x85 #o000 #x00 #x66)
+   (def-x86-opcode testw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #xa9 nil #x00 #x66)
+   (def-x86-opcode testw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #xf7 #o300 #x00 #x66)
+   (def-x86-opcode testw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #xf7 #o000 #x00 #x66)
+
+
+   (def-x86-opcode testb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x84 #o300 #x00)
+   (def-x86-opcode testb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x84 #o000 #x00)
+   (def-x86-opcode testb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x84 #o000 #x00)
+   (def-x86-opcode testb ((:imm8s :insert-imm8s) (:acc :insert-nothing))
+     #xa8 nil #x00)
+   (def-x86-opcode testb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #xf6 #o300 #x00)
+   (def-x86-opcode testb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #xf6 #o000 #x00)
+
+   ;; ud2a (not to be confused with all of the other undefined/accidental
+   ;; instructions) is "officially undefined".
+   (def-x86-opcode ud2a ()
+     #x0f0b nil nil)
+
+   (def-x86-opcode ud2b ()
+     #x0fb9 nil nil)
+
+   ;; xadd
+   (def-x86-opcode (xaddq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x0fc1 #o300 #x48)
+   (def-x86-opcode (xaddq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fc1 #o000 #x48)
+
+   (def-x86-opcode xaddl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x0fc1 #o300 #x00)
+   (def-x86-opcode xaddl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fc1 #o000 #x00)
+
+   (def-x86-opcode xaddw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x0fc1 #o300 #x00 #x66)
+   (def-x86-opcode xaddw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fc1 #o000 #x00 #x66)
+
+   (def-x86-opcode xaddb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x0fc0 #o300 #x00)
+   (def-x86-opcode xaddb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x0fc0 #o000 #x00)
+
+   ;; xchg
+   ;; Allegedly, using the opcode #x9x to implement "(xchg (% eax) (% eax))"
+   ;; doesn't zero-extend eax to rax on x86-64.  (So don't special-case
+   ;; :acc as source or destination, and use #x86 and a modrm byte in all cases.)
+   (def-x86-opcode (xchgq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x87 #o300 #x48)
+   (def-x86-opcode (xchgq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x87 #o000 #x48)
+   (def-x86-opcode (xchgq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x87 #o000 #x48)
+
+   (def-x86-opcode xchgl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x87 #o300 #x00)
+   (def-x86-opcode xchgl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x87 #o000 #x00)
+   (def-x86-opcode xchgl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x87 #o000 #x00)
+
+   (def-x86-opcode xchgw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x87 #o300 #x00 #x66)
+   (def-x86-opcode xchgw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x87 #o000 #x00 #x66)
+   (def-x86-opcode xchgw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x87 #o000 #x00 #x66)
+
+   (def-x86-opcode xchgb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x86 #o300 #x00)
+   (def-x86-opcode xchgb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x86 #o000 #x00)
+   (def-x86-opcode xchgb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x86 #o000 #x00)
+
+   ;; xlat
+
+   (def-x86-opcode xlatb ()
+     #xd7 nil nil)
+
+   ;; xor
+   (def-x86-opcode (xorq :cpu64) ((:reg64 :insert-modrm-reg) (:reg64 :insert-modrm-rm))
+     #x31 #o300 #x48)
+   (def-x86-opcode (xorq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x33 #o000 #x48)
+   (def-x86-opcode (xorq :cpu64) ((:reg64 :insert-modrm-reg) (:anymem :insert-memory))
+     #x31 #x00 #x48)
+   (def-x86-opcode (xorq :cpu64) ((:imm8s :insert-imm8s) (:reg64 :insert-modrm-rm))
+     #x83 #o360 #x48)
+   (def-x86-opcode (xorq :cpu64) ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x35 nil #x48)
+   (def-x86-opcode (xorq :cpu64) ((:imm32s :insert-imm32s) (:reg64 :insert-modrm-rm))
+     #x81 #o360 #x48)
+   (def-x86-opcode (xorq :cpu64) ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o060 #x48)
+   (def-x86-opcode (xorq :cpu64) ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o060 #x48)
+
+   (def-x86-opcode xorl ((:reg32 :insert-modrm-reg) (:reg32 :insert-modrm-rm))
+     #x31 #o300 #x00)
+   (def-x86-opcode xorl ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x33 #o000 #x00)
+   (def-x86-opcode xorl ((:reg32 :insert-modrm-reg) (:anymem :insert-memory))
+     #x31 #x00 #x00)
+   (def-x86-opcode xorl ((:imm8s :insert-imm8s) (:reg32 :insert-modrm-rm))
+     #x83 #o360 #x00)
+   (def-x86-opcode xorl ((:imm32s :insert-imm32s) (:acc :insert-nothing))
+     #x35 nil nil)
+   (def-x86-opcode xorl ((:imm32s :insert-imm32s) (:reg32 :insert-modrm-rm))
+     #x81 #o360 #x00)
+   (def-x86-opcode xorl ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o060 #x00)
+   (def-x86-opcode xorl ((:imm32s :insert-imm32s) (:anymem :insert-memory))
+     #x81 #o060 #x00)
+
+   (def-x86-opcode xorw ((:reg16 :insert-modrm-reg) (:reg16 :insert-modrm-rm))
+     #x31 #o300 #x00 #x66)
+   (def-x86-opcode xorw ((:anymem :insert-memory) (:reg16 :insert-modrm-reg))
+     #x33 #o000 #x00 #x66)
+   (def-x86-opcode xorw ((:reg16 :insert-modrm-reg) (:anymem :insert-memory))
+     #x31 #x00 #x00 #x66)
+   (def-x86-opcode xorw ((:imm8s :insert-imm8s) (:reg16 :insert-modrm-rm))
+     #x83 #o360 #x00 #x66)
+   (def-x86-opcode xorw ((:imm16 :insert-imm16) (:acc :insert-nothing))
+     #x35 nil nil #x66)
+   (def-x86-opcode xorw ((:imm16 :insert-imm16) (:reg16 :insert-modrm-rm))
+     #x81 #o360 #x00 #x66)
+   (def-x86-opcode xorw ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x83 #o060 #x00 #x66)
+   (def-x86-opcode xorw ((:imm16 :insert-imm16) (:anymem :insert-memory))
+     #x81 #o060 #x00 #x66)
+
+   (def-x86-opcode xorb ((:reg8 :insert-modrm-reg) (:reg8 :insert-modrm-rm))
+     #x30 #o300 #x00)
+   (def-x86-opcode xorb ((:anymem :insert-memory) (:reg8 :insert-modrm-reg))
+     #x32 #o000 #x00)
+   (def-x86-opcode xorb ((:reg8 :insert-modrm-reg) (:anymem :insert-memory))
+     #x30 #x00 #x00)
+   (def-x86-opcode xorb ((:imm8s :insert-imm8s) (:acc :insert-nothing))
+     #x34 nil nil)
+   (def-x86-opcode xorb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o360 #x00)
+   (def-x86-opcode xorb ((:imm8s :insert-imm8s) (:reg8 :insert-modrm-rm))
+     #x80 #o360 #x00)
+   (def-x86-opcode xorb ((:imm8s :insert-imm8s) (:anymem :insert-memory))
+     #x80 #o060 #x00)
+
+   ;; fxsave
+   (def-x86-opcode fxsaveq ((:anymem :insert-memory))
+     #x0fae #o000 0)
+
+   ;; fxrstor
+   (def-x86-opcode fxrstor ((:anymem :insert-memory))
+     #x0fae #o010 0)
+
+   ;; clflush
+   (def-x86-opcode clflush ((:anymem :insert-memory))
+     #x0fae #o070 0)
+
+   ;; lfence
+   (def-x86-opcode lfence ()
+     #x0fae #xe8 nil)
+
+   ;; mfence
+   (def-x86-opcode mfence ()
+     #x0fae #xf0 nil)
+   
+   ;; pause
+   (def-x86-opcode pause ()
+     #xf390 nil nil)
+
+   ;; I don't want to have to define all mmx/sse/sse2 instructions at the
+   ;; moment, but it wouldn't hurt to define those that the lisp is
+   ;; likely to use.
+
+   ;; Useful mmx/sse2 instructions, other than movd/movq:
+
+   ;; emms
+   (def-x86-opcode emms ()
+     #x0f77 nil nil)
+
+   ;; addsd
+   (def-x86-opcode addsd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f58 #o000 #x0 #xf2)
+   (def-x86-opcode addsd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f58 #o300 #x0 #xf2)
+   
+   ;; addss
+   (def-x86-opcode addss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f58 #o000 #x0 #xf3)
+   (def-x86-opcode addss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f58 #o300 #x0 #xf3)
+
+   ;; subsd
+   (def-x86-opcode subsd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f5c #o000 #x0 #xf2)
+   (def-x86-opcode subsd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f5c #o300 #x0 #xf2)
+
+   ;; subss
+   (def-x86-opcode subss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f5c #o000 #x0 #xf3)
+   (def-x86-opcode subss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f5c #o300 #x0 #xf3)
+
+   ;; movapd
+   (def-x86-opcode movapd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f28 #o300 #x0 #x66)
+   (def-x86-opcode movapd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f28 #o000 #x0 #x66)
+   (def-x86-opcode movapd ((:regxmm :insert-xmm-reg) (:anymem :insert-memory))
+     #x0f29 #o000 #x0 #x66)
+   
+   ;; mulsd
+   (def-x86-opcode mulsd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f59 #o000 #x0 #xf2)
+   (def-x86-opcode mulsd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f59 #o300 #x0 #xf2)
+
+   ;; mulss
+   (def-x86-opcode mulss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f59 #o000 #x0 #xf3)
+   (def-x86-opcode mulss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f59 #o300 #x0 #xf3)
+
+   ;; divsd
+   (def-x86-opcode divsd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f5e #o000 #x0 #xf2)
+   (def-x86-opcode divsd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f5e #o300 #x0 #xf2)
+
+   ;; divss
+   (def-x86-opcode divss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f5e #o000 #x0 #xf3)
+   (def-x86-opcode divss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f5e #o300 #x0 #xf3)
+
+
+   ;; sqrtsd
+   (def-x86-opcode sqrtsd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f51 #o000 #x0 #xf2)
+   (def-x86-opcode sqrtsd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f51 #o300 #x0 #xf2)
+
+   ;; sqrtss
+   (def-x86-opcode sqrtss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f51 #o000 #x0 #xf3)
+   (def-x86-opcode sqrtss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f51 #o300 #x0 #xf3)
+   
+   ;; comisd
+   (def-x86-opcode comisd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2f #o000 #x0 #x66)
+   (def-x86-opcode comisd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2f #o300 #x0 #x66)
+
+   ;; ucomisd
+   (def-x86-opcode ucomisd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2e #o000 #x0 #x66)
+   (def-x86-opcode ucomisd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2e #o300 #x0 #x66)
+
+   ;; comiss
+   (def-x86-opcode comiss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2f #o000 #x0)
+   (def-x86-opcode comiss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2f #o300 #x0)
+
+   ;; ucomiss
+   (def-x86-opcode ucomiss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2e #o000 #x0)
+   (def-x86-opcode ucomiss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2e #o300 #x0)
+
+   ;; movsd
+   (def-x86-opcode movsd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f10 #o300 #x0 #xf2)
+   (def-x86-opcode movsd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f10 #o300 #x0 #xf2)
+   (def-x86-opcode movsd ((:regxmm :insert-xmm-reg) (:anymem :insert-memory))
+     #x0f11 #o000 #x0 #xf2)
+
+   
+
+   ;; movss
+   (def-x86-opcode movss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f10 #o300 #x0 #xf3)
+   (def-x86-opcode movss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f10 #o300 #x0 #xf3)
+   (def-x86-opcode movss ((:regxmm :insert-xmm-reg) (:anymem :insert-memory))
+     #x0f11 #o000 #x0 #xf3)
+
+   
+;;; cvtsd2si.  This does rounding (as opposed to truncation).
+   (def-x86-opcode (cvtsd2siq :cpu64) ((:regxmm :insert-xmm-rm) (:reg64 :insert-modrm-reg))
+     #x0f2d #o300 #x48 #xf2)
+   (def-x86-opcode (cvtsd2siq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f2d #o000 #x48 #xf2)
+   (def-x86-opcode cvtsd2sil ((:regxmm :insert-xmm-rm) (:reg32 :insert-modrm-reg))
+     #x0f2d #o300 #x00 #xf2)
+   (def-x86-opcode cvtsd2sil ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f2d #o000 #x00 #xf2)
+
+;;; cvtss2si.  This does rounding (as opposed to truncation).
+   (def-x86-opcode (cvtss2siq :cpu64) ((:regxmm :insert-xmm-rm) (:reg64 :insert-modrm-reg))
+     #x0f2d #o300 #x48 #xf3)
+   (def-x86-opcode (cvtss2siq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f2d #o000 #x48 #xf3)
+   (def-x86-opcode cvtss2sil ((:regxmm :insert-xmm-rm) (:reg32 :insert-modrm-reg))
+     #x0f2d #o300 #x00 #xf3)
+   (def-x86-opcode cvtss2sil ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f2d #o000 #x00 #xf3)
+   
+;;; cvttsd2si.  This does truncation (as opposed to rounding).
+   (def-x86-opcode (cvttsd2siq :cpu64) ((:regxmm :insert-xmm-rm) (:reg64 :insert-modrm-reg))
+     #x0f2c #o300 #x48 #xf2)
+   (def-x86-opcode (cvttsd2siq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f2c #o000 #x48 #xf2)
+   (def-x86-opcode cvttsd2sil ((:regxmm :insert-xmm-rm) (:reg32 :insert-modrm-reg))
+     #x0f2c #o300 #x00 #xf2)
+   (def-x86-opcode cvtsd2sil ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f2c #o000 #x00 #xf2)
+
+;;; cvttss2si.  This does truncation (as opposed to rounding).
+   (def-x86-opcode (cvttss2siq :cpu64) ((:regxmm :insert-xmm-rm) (:reg64 :insert-modrm-reg))
+     #x0f2c #o300 #x48 #xf3)
+   (def-x86-opcode (cvttss2siq :cpu64) ((:anymem :insert-memory) (:reg64 :insert-modrm-reg))
+     #x0f2c #o000 #x48 #xf3)
+   (def-x86-opcode cvttss2sil ((:regxmm :insert-xmm-rm) (:reg32 :insert-modrm-reg))
+     #x0f2c #o300 #x00 #xf3)
+   (def-x86-opcode cvttss2sil ((:anymem :insert-memory) (:reg32 :insert-modrm-reg))
+     #x0f2c #o000 #x00 #xf3)
+
+   ;; cvtsi2sd
+   (def-x86-opcode (cvtsi2sdq :cpu64) ((:reg64 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2a #o300 #x48 #xf2)
+   (def-x86-opcode (cvtsi2sdq :cpu64) ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2a #o000 #x48 #xf2)
+   (def-x86-opcode cvtsi2sdl ((:reg32 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2a #o300 #x00 #xf2)
+   (def-x86-opcode cvtsi2sdl ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2a #o000 #x00 #xf2)
+   
+   ;; cvtsd2ss
+   (def-x86-opcode cvtsd2ss ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f5a #o300 #x0 #xf2)
+   (def-x86-opcode cvtsd2ss ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f5a #o000 #x0 #xf2)
+
+   ;; cvtsi2sd
+   (def-x86-opcode (cvtsi2sdq :cpu64) ((:reg64 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2a #o300 #x48 #xf2)
+   (def-x86-opcode (cvtsi2sdq :cpu64) ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2a #o000 #x48 #xf2)
+   (def-x86-opcode cvtsi2sdl ((:reg32 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2a #o300 #x00 #xf2)
+   (def-x86-opcode cvtsi2sdl ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2a #o000 #x00 #xf2)
+
+   ;; cvtsi2ss
+   (def-x86-opcode (cvtsi2ssq :cpu64) ((:reg64 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2a #o300 #x48 #xf3)
+   (def-x86-opcode (cvtsi2ssq :cpu64) ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2a #o000 #x48 #xf3)
+   (def-x86-opcode cvtsi2ssl ((:reg32 :insert-modrm-rm) (:regxmm :insert-xmm-reg))
+     #x0f2a #o300 #x00 #xf3)
+   (def-x86-opcode cvtsi2ssl ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f2a #o000 #x00 #xf3)
+
+;;; cvtss2sd
+   (def-x86-opcode cvtss2sd ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0f5a #o300 #x0 #xf3)
+   (def-x86-opcode cvtss2sd ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0f5a #o000 #x0 #xf3)
+   
+   ;; pand
+   (def-x86-opcode pand ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0fdb #o300 #x0)
+   (def-x86-opcode pand ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0fdb #o000 #x0)
+   (def-x86-opcode pand ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0fef #o300 #x0 #x66)
+   (def-x86-opcode pand ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0fdb #o000 #x0 #x66)
+   
+   ;; pandn
+   (def-x86-opcode pandn ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0fdf #o300 #x0)
+   (def-x86-opcode pandn ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0fdf #o000 #x0)
+   (def-x86-opcode pandn ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0fdf #o300 #x0 #x66)
+   (def-x86-opcode pandn ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0fdf #o000 #x0 #x66)
+
+   ;; por
+   (def-x86-opcode por ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0feb #o300 #x0)
+   (def-x86-opcode por ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0feb #o000 #x0)
+   (def-x86-opcode por ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0feb #o300 #x0 #x66)
+   (def-x86-opcode por ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0feb #o000 #x0 #x66)
+
+   ;; pxor
+   (def-x86-opcode pxor ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0fef #o300 #x0)
+   (def-x86-opcode pxor ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0fef #o000 #x0)
+   (def-x86-opcode pxor ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0fef #o300 #x0 #x66)
+   (def-x86-opcode pxor ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0fef #o000 #x0 #x66)
+
+   ;; psllq 
+   (def-x86-opcode psllq ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0ff3 #o300 #x0)
+   (def-x86-opcode psllq ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0ff3 #o000 #x0)
+   (def-x86-opcode psllq ((:imm8 :insert-imm8) (:regmmx :insert-mmx-rm))
+     #x0f73 #o360 #o0)
+   (def-x86-opcode psllq ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0ff3 #o300 #x0 #x66)
+   (def-x86-opcode psllq ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0ff3 #o000 #x0 #x66)
+   (def-x86-opcode psllq ((:imm8 :insert-imm8) (:regxmm :insert-xmm-rm))
+     #x0f73 #o360 #o0 #x66)
+
+   ;; psllw
+   
+   ;; pslld
+   (def-x86-opcode pslld ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0ff2 #o300 #x0)
+   (def-x86-opcode pslld ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0ff2 #o000 #x0)
+   (def-x86-opcode pslld ((:imm8 :insert-imm8) (:regmmx :insert-mmx-rm))
+     #x0f72 #o360 #o0)
+   (def-x86-opcode pslld ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0ff2 #o300 #x0 #x66)
+   (def-x86-opcode pslld ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0ff2 #o000 #x0 #x66)
+   (def-x86-opcode pslld ((:imm8 :insert-imm8) (:regxmm :insert-xmm-rm))
+     #x0f72 #o360 #o0 #x66)
+
+   ;; pslldq
+   (def-x86-opcode pslldq ((:imm8 :insert-imm8) (:regxmm :insert-xmm-rm))
+     #x0f73 #o370 #x0 #x66)
+   
+   ;; psrlq 
+   (def-x86-opcode psrlq ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0fd3 #o300 #x0)
+   (def-x86-opcode psrlq ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0fd3 #o000 #x0)
+   (def-x86-opcode psrlq ((:imm8 :insert-imm8) (:regmmx :insert-mmx-rm))
+     #x0f73 #o320 #o0)
+   (def-x86-opcode psrlq ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0fd3 #o300 #x0 #x66)
+   (def-x86-opcode psrlq ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0fd3 #o000 #x0 #x66)
+   (def-x86-opcode psrlq ((:imm8 :insert-imm8) (:regxmm :insert-xmm-rm))
+     #x0f73 #o320 #o0 #x66)
+
+   ;; psrld
+   (def-x86-opcode psrld ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0fd2 #o300 #x0)
+   (def-x86-opcode psrld ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0fd2 #o000 #x0)
+   (def-x86-opcode psrld ((:imm8 :insert-imm8) (:regmmx :insert-mmx-rm))
+     #x0f72 #o320 #o0)
+   (def-x86-opcode psrld ((:regxmm :insert-modrm-rm) (:regxmm :insert-modrm-reg))
+     #x0fd2 #o300 #x0 #x66)
+   (def-x86-opcode psrld ((:anymem :insert-memory) (:regxmm :insert-modrm-reg))
+     #x0fd2 #o000 #x0 #x66)
+   (def-x86-opcode psrld ((:imm8 :insert-imm8) (:regxmm :insert-xmm-rm))
+     #x0f72 #o320 #o0 #x66)
+
+   ;; psrldq
+   (def-x86-opcode psrldq ((:imm8 :insert-imm8) (:regxmm :insert-xmm-rm))
+     #x0f73 #o330 #x0 #x66)
+   
+   ;; psrlw
+
+   ;; pmuludq
+   (def-x86-opcode pmuludq ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0ff4 #o300 #x0)
+   (def-x86-opcode pmuludq ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0ff4 #o000 #x0)
+   (def-x86-opcode pmuludq ((:regxmm :insert-xmm-rm) (:regxmm :insert-xmm-reg))
+     #x0ff4 #o300 #x0 #x66)
+   (def-x86-opcode pmuludq ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0ff4 #o000 #x0 #x66)
+
+   ;; paddq
+   (def-x86-opcode paddq ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0fd4 #o300 #x0)
+   (def-x86-opcode paddq ((:anymem :insert-memory) (:regmmx :insert-mmx-reg))
+     #x0fd4 #o000 #x0)
+   (def-x86-opcode paddq ((:regxmm :insert-xmm-reg) (:regxmm :insert-xmm-reg))
+     #x0fd4 #o300 #x0 #x66)
+   (def-x86-opcode paddq ((:anymem :insert-memory) (:regxmm :insert-xmm-reg))
+     #x0fd4 #o000 #x0 #x66)
+
+   ;; psrad
+   (def-x86-opcode psrad ((:regmmx :insert-mmx-rm) (:regmmx :insert-mmx-reg))
+     #x0fe2 #o300 #x0)
+
+;;; End of list of useful mmx instructions
+
+;;; x87 fpu instructions
+
+   ;; fstp
+   (def-x86-opcode fstps ((:anymem :insert-memory))
+     #xd9 #o030 nil)
+   (def-x86-opcode fstpl ((:anymem :insert-memory))
+     #xdd #o030 nil)
+
+;;; end of x87 fpu instructions
+
+   (def-x86-opcode ldmxcsr ((:anymem :insert-memory))
+     #x0fae #o020 nil)
+
+   (def-x86-opcode stmxcsr ((:anymem :insert-memory))
+     #x0fae #o030 nil)
+
+   ;; UUOs.  Expect lots more, some of which may take pseudo-operands.
+   (def-x86-opcode uuo-error-slot-unbound ((:reg :insert-opcode-reg4)
+					   (:reg :insert-reg4-pseudo-rm-high)
+					   (:reg :insert-reg4-pseudo-rm-low))
+     #xcd70 0 nil)
+
+;;; DON'T use #xcd8x: doing so will make Mach angry and confused.
+   
+   (def-x86-opcode uuo-error-unbound ((:reg :insert-opcode-reg4))
+     #xcd90 nil 0)
+
+   (def-x86-opcode uuo-error-udf ((:reg :insert-opcode-reg4))
+     #xcda0 nil 0)
+   
+   (def-x86-opcode uuo-error-reg-not-type ((:reg :insert-opcode-reg4) (:imm8 :insert-imm8))
+     #xcdb0 nil 0)
+   
+   (def-x86-opcode uuo-error-too-few-args ()
+     #xcdc0 nil nil)
+   (def-x86-opcode uuo-error-too-many-args ()
+     #xcdc1 nil nil)
+   (def-x86-opcode uuo-error-wrong-number-of-args ()
+     #xcdc2 nil nil)
+   (def-x86-opcode uuo-error-array-rank ((:reg :insert-reg4-pseudo-rm-high)
+					 (:reg :insert-reg4-pseudo-rm-low))
+     #xcdc3 0 nil)
+
+   (def-x86-opcode uuo-gc-trap ()
+     #xcdc4 nil nil)
+   (def-x86-opcode uuo-alloc ()
+     #xcdc5 nil nil)
+   (def-x86-opcode uuo-error-not-callable ()
+     #xcdc6 nil nil)
+   (def-x86-opcode uuo-error-udf-call ()
+     #xcdc7 nil nil)
+
+   (def-x86-opcode uuo-error-vector-bounds ((:reg :insert-reg4-pseudo-rm-high) (:reg :insert-reg4-pseudo-rm-low))
+     #xcdc8 0 nil)
+
+   (def-x86-opcode uuo-error-call-macro-or-special-operator ()
+     #xcdc9 nil nil)
+
+   (def-x86-opcode uuo-error-debug-trap ()
+     #xcdca nil nil)
+
+   (def-x86-opcode uuo-error-array-bounds ((:reg :insert-reg4-pseudo-rm-high) (:reg :insert-reg4-pseudo-rm-low))
+     #xcdcb 0 nil)
+
+   (def-x86-opcode uuo-error-eep-unresolved ((:reg :insert-reg4-pseudo-rm-high)
+					     (:reg :insert-reg4-pseudo-rm-low))
+     #xcdcc 0 nil)
+
+   (def-x86-opcode uuo-error-debug-trap-with-string ()
+     #xcdcd nil nil)
+
+   (def-x86-opcode uuo-watch-trap ()
+     #xcdce nil nil)
+   
+   (def-x86-opcode uuo-error-reg-not-tag ((:reg :insert-opcode-reg4) (:imm8 :insert-imm8))
+     #xcdd0 nil 0)
+   (def-x86-opcode uuo-error-reg-not-list ((:reg :insert-opcode-reg4))
+     #xcde0 nil 0)
+   (def-x86-opcode uuo-error-reg-not-fixnum ((:reg :insert-opcode-reg4))
+     #xcdf0 nil 0)
+
+   ))
+
+
+(dotimes (i (length *x86-opcode-templates*))
+  (setf (x86-opcode-template-ordinal (svref *x86-opcode-templates* i)) i))
+  
+
+
+(defparameter *x86-opcode-template-lists*
+  (make-hash-table :test #'equalp))
+
+
+(defun initialize-x86-opcode-templates ()
+  (flet ((setup-templates-hash (hash templates)
+           (clrhash hash)
+           (do* ((i (1- (length templates)) (1- i)))
+                ((< i 0) hash)
+             (declare (fixnum i))
+             (let* ((template (svref templates i))
+                    (name (x86-opcode-template-mnemonic template)))
+               (push template (gethash name hash))))))
+    (setup-templates-hash *x86-opcode-template-lists* *x86-opcode-templates*)
+    (when (fboundp 'ccl::fixup-x86-vinsn-templates)
+      (ccl::fixup-x86-vinsn-templates
+       (ccl::backend-p2-vinsn-templates ccl::*target-backend*)
+       *x86-opcode-template-lists*))
+    t))
+
+(defvar *x8632-registers* (make-hash-table :test #'equalp))
+(defvar *x8664-registers* (make-hash-table :test #'equalp))
+(defvar *x86-registers* nil)
+
+(defparameter *x86-operand-insert-functions*
+  #(insert-nothing
+    insert-modrm-reg
+    insert-modrm-rm
+    insert-memory
+    insert-opcode-reg
+    insert-opcode-reg4
+    insert-cc
+    insert-label
+    insert-imm8-for-int
+    insert-extra
+    insert-imm8
+    insert-imm8s
+    insert-imm16
+    insert-imm32s
+    insert-imm32
+    insert-imm64
+    insert-mmx-reg
+    insert-mmx-rm
+    insert-xmm-reg
+    insert-xmm-rm
+    insert-reg4-pseudo-rm-high
+    insert-reg4-pseudo-rm-low
+    insert-self
+))
+
+(initialize-x86-opcode-templates)
+
+
+
+
+
+;;; 386 register table.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+(defconstant +REGNAM-AL+ 1) ; Entry in i386-regtab.
+(defconstant +REGNAM-AX+ 25)
+(defconstant +REGNAM-EAX+ 41)
+
+(defvar *x86-regtab*
+  (vector
+   ;; Make %st first as we test for it.
+   (make-reg-entry :reg-name "st"
+                   :reg-type (encode-operand-type :FloatReg :floatacc)
+                   :reg-flags 0
+                   :reg-num 0 )
+   ;; 8 bit regs
+   (make-reg-entry :reg-name "al"
+                   :reg-type (encode-operand-type :Reg8 :Acc)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "cl"
+                   :reg-type (encode-operand-type :Reg8 :ShiftCount)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "dl"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "bl"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "ah"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "ch"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "dh"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "bh"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "axl"
+                   :reg-type (encode-operand-type :Reg8 :Acc)
+                   :reg-flags +RegRex64+
+                   :reg-num 0 ) ; Must be in the "al + 8" slot.
+   (make-reg-entry :reg-name "cxl"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags +RegRex64+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "dxl"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags +RegRex64+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "bxl"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags +RegRex64+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "spl"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags +RegRex64+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "bpl"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags +RegRex64+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "sil"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags +RegRex64+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "dil"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags +RegRex64+
+                   :reg-num 7)
+   (make-reg-entry :reg-name "r8b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "r9b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 1)
+   (make-reg-entry :reg-name "r10b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 2)
+   (make-reg-entry :reg-name "r11b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 3)
+   (make-reg-entry :reg-name "r12b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 4)
+   (make-reg-entry :reg-name "r13b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 5)
+   (make-reg-entry :reg-name "r14b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 6)
+   (make-reg-entry :reg-name "r15b"
+                   :reg-type (encode-operand-type :Reg8)
+                   :reg-flags (logior +RegRex64+ +RegRex+)
+                   :reg-num 7)
+   ;; 16 bit regs
+   (make-reg-entry :reg-name "ax"
+                   :reg-type (encode-operand-type :Reg16 :Acc)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "cx"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "dx"
+                   :reg-type (encode-operand-type :Reg16 :InOutPortReg)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "bx"
+                   :reg-type (encode-operand-type :Reg16 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "sp"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "bp"
+                   :reg-type (encode-operand-type :Reg16 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "si"
+                   :reg-type (encode-operand-type :Reg16 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "di"
+                   :reg-type (encode-operand-type :Reg16 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "r8w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "r9w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "r10w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "r11w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "r12w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "r13w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "r14w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "r15w"
+                   :reg-type (encode-operand-type :Reg16)
+                   :reg-flags +RegRex+
+                   :reg-num 7)
+        ; 32 bit regs
+   (make-reg-entry :reg-name "eax"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex :Acc)
+                   :reg-flags 0
+                   :reg-num 0 ) ; Must be in ax + 16 slot.
+   (make-reg-entry :reg-name "ecx"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "edx"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "ebx"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "esp"
+                   :reg-type (encode-operand-type :Reg32)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "ebp"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "esi"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "edi"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "r8d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "r9d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "r10d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "r11d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "r12d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "r13d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "r14d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "r15d"
+                   :reg-type (encode-operand-type :Reg32 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 7)
+   (make-reg-entry :reg-name "rax"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex :Acc)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "rcx"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "rdx"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "rbx"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "rsp"
+                   :reg-type (encode-operand-type :Reg64)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "rbp"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "rsi"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "rdi"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "r8"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "r9"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "r10"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "r11"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "r12"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "r13"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "r14"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "r15"
+                   :reg-type (encode-operand-type :Reg64 :BaseIndex)
+                   :reg-flags +RegRex+
+                   :reg-num 7)
+        ; Segment registers.
+   (make-reg-entry :reg-name "es"
+                   :reg-type (encode-operand-type :SReg2)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "cs"
+                   :reg-type (encode-operand-type :SReg2)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "ss"
+                   :reg-type (encode-operand-type :SReg2)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "ds"
+                   :reg-type (encode-operand-type :SReg2)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "fs"
+                   :reg-type (encode-operand-type :SReg3)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "gs"
+                   :reg-type (encode-operand-type :SReg3)
+                   :reg-flags 0
+                   :reg-num 5)
+   ;; Control registers.
+   (make-reg-entry :reg-name "cr0"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "cr1"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "cr2"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "cr3"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "cr4"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "cr5"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "cr6"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "cr7"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "cr8"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "cr9"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "cr10"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "cr11"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "cr12"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "cr13"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "cr14"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "cr15"
+                   :reg-type (encode-operand-type :Control)
+                   :reg-flags +RegRex+
+                   :reg-num 7)
+   ;; Debug registers.
+   (make-reg-entry :reg-name "db0"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "db1"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "db2"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "db3"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "db4"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "db5"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "db6"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "db7"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "db8"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "db9"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "db10"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "db11"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "db12"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "db13"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "db14"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "db15"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 7)
+   (make-reg-entry :reg-name "dr0"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "dr1"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "dr2"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "dr3"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "dr4"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "dr5"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "dr6"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "dr7"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "dr8"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "dr9"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "dr10"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "dr11"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "dr12"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "dr13"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "dr14"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "dr15"
+                   :reg-type (encode-operand-type :Debug)
+                   :reg-flags +RegRex+
+                   :reg-num 7)
+   ;; Test registers.
+   (make-reg-entry :reg-name "tr0"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "tr1"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "tr2"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "tr3"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "tr4"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "tr5"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "tr6"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "tr7"
+                   :reg-type (encode-operand-type :Test)
+                   :reg-flags 0
+                   :reg-num 7)
+   ;; MMX and simd registers.
+   (make-reg-entry :reg-name "mm0"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "mm1"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "mm2"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "mm3"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "mm4"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "mm5"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "mm6"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "mm7"
+                   :reg-type (encode-operand-type :RegMMX)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "xmm0"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "xmm1"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "xmm2"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "xmm3"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "xmm4"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "xmm5"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "xmm6"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "xmm7"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags 0
+                   :reg-num 7)
+   (make-reg-entry :reg-name "xmm8"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 0 )
+   (make-reg-entry :reg-name "xmm9"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 1)
+   (make-reg-entry :reg-name "xmm10"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 2)
+   (make-reg-entry :reg-name "xmm11"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 3)
+   (make-reg-entry :reg-name "xmm12"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 4)
+   (make-reg-entry :reg-name "xmm13"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 5)
+   (make-reg-entry :reg-name "xmm14"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 6)
+   (make-reg-entry :reg-name "xmm15"
+                   :reg-type (encode-operand-type :RegXMM)
+                   :reg-flags +RegRex+
+                   :reg-num 7)
+   ;; No type will make this register rejected for all purposes except
+   ;; for addressing. This saves creating one extra type for RIP.
+   (make-reg-entry :reg-name "rip"
+                   :reg-type (encode-operand-type :BaseIndex)
+                   :reg-flags 0
+                   :reg-num 0 )
+   ))
+
+(defvar *x86-float-regs*
+  (vector
+   (make-reg-entry :reg-name "st[0]"
+                   :reg-type (encode-operand-type :FloatReg :FloatAcc)
+                   :reg-flags 0
+                   :reg-num 0)
+   (make-reg-entry :reg-name "st[1]"
+                   :reg-type (encode-operand-type :FloatReg)
+                   :reg-flags 0
+                   :reg-num 1)
+   (make-reg-entry :reg-name "st[2]"
+                   :reg-type (encode-operand-type :FloatReg)
+                   :reg-flags 0
+                   :reg-num 2)
+   (make-reg-entry :reg-name "st[3]"
+                   :reg-type (encode-operand-type :FloatReg)
+                   :reg-flags 0
+                   :reg-num 3)
+   (make-reg-entry :reg-name "st[4]"
+                   :reg-type (encode-operand-type :FloatReg)
+                   :reg-flags 0
+                   :reg-num 4)
+   (make-reg-entry :reg-name "st[5]"
+                   :reg-type (encode-operand-type :FloatReg)
+                   :reg-flags 0
+                   :reg-num 5)
+   (make-reg-entry :reg-name "st[6]"
+                   :reg-type (encode-operand-type :FloatReg)
+                   :reg-flags 0
+                   :reg-num 6)
+   (make-reg-entry :reg-name "st[7]"
+                   :reg-type (encode-operand-type :FloatReg)
+                   :reg-flags 0
+                   :reg-num 7)))
+
+
+;;; Segment stuff.
+(defvar *cs-segment-register* (make-seg-entry :seg-name "cs" :seg-prefix #x23))
+(defvar *ds-segment-register* (make-seg-entry :seg-name "ds" :seg-prefix #x3e))
+(defvar *ss-segment-register* (make-seg-entry :seg-name "ss" :seg-prefix #x36))
+(defvar *es-segment-register* (make-seg-entry :seg-name "es" :seg-prefix #x26))
+(defvar *fs-segment-register* (make-seg-entry :seg-name "fs" :seg-prefix #x64))
+(defvar *gs-segment-register* (make-seg-entry :seg-name "gs" :seg-prefix #x65))
+
+(defvar *x86-seg-entries*
+  (vector *es-segment-register*
+          *cs-segment-register*
+          *ss-segment-register*
+          *ds-segment-register*
+          *fs-segment-register*
+          *gs-segment-register*))
+
+
+
+
+
+(defun init-x86-registers ()
+  (labels ((ia32-p (entry)
+	     (not (or (logtest (reg-entry-reg-flags entry)
+			       (logior +regrex+ +regrex64+))
+		      (logtest (reg-entry-reg-type entry)
+			       (encode-operand-type :reg64))
+		      ;; As a special case, exclude RIP, whose type is
+		      ;; *exactly* :BaseIndex
+		      (eql (reg-entry-reg-type entry)
+			   (encode-operand-type :BaseIndex)))))
+	   (hash-registers (vector hash 64p)
+	     (dotimes (i (length vector))
+	       (let* ((entry (svref vector i)))
+		 (if (or 64p (ia32-p entry))
+		   (setf (gethash (reg-entry-reg-name entry) hash) entry))))))
+    (hash-registers *x86-regtab* *x8632-registers* nil)
+    (hash-registers *x86-float-regs* *x8632-registers* nil)
+    (hash-registers *x86-regtab* *x8664-registers* t)
+    (hash-registers *x86-float-regs* *x8664-registers* t)))
+
+)
+
+(init-x86-registers)
+
+
+
+(defstruct x86-operand
+  (type ))
+
+(defstruct (x86-immediate-operand (:include x86-operand))
+  ;; The "value" of an immediate operand may be an expression (that we
+  ;; have to do some sort of delayed evaluation on.)  It could just be
+  ;; a lisp form (that we call EVAL on), but there might be scoping or
+  ;; similar issues in that case.
+  value)
+
+(defstruct (x86-register-operand (:include x86-operand))
+  entry                                 ;the reg-entry
+)
+
+(defstruct (x86-label-operand (:include x86-operand))
+  label)
+
+
+(defstruct (x86-memory-operand (:include x86-operand))
+  ;; Any of these fields can be null.  Some combinations of fields -
+  ;; like a segment register or scale factor by itself - make no
+  ;; sense.
+  seg                                   ; a segment register
+  disp                                  ; a signed displacement added to base
+  base                                  ; a GPR
+  index                                 ; another GPR
+  scale                                 ; scale factor, multiplied with index
+  )
+
+
+(defun insert-nothing (instruction operand)
+  (declare (ignore instruction operand)))
+
+;;; Insert a 3-bit register value derived from OPERAND in INSN's modrm.reg
+;;; field.  If the register requires REX addressing, set the REX.R bit
+;;; in the instruction's rex-prefix.  If either the modrm or rex-prefix
+;;; fields of the instruction are NIL, we're very confused; check for
+;;; that explicitly until this code matures a bit.
+
+(defun insert-modrm-reg-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry))
+         (flags (reg-entry-reg-flags entry))
+         (need-rex.r (logtest +regrex+ flags)))
+    (setf (x86-instruction-modrm-byte instruction)
+          (dpb reg-num (byte 3 3)
+               (need-modrm-byte instruction)))
+    (when need-rex.r
+      (setf (x86-instruction-rex-prefix instruction)
+            (logior +rex-extx+ (need-rex-prefix instruction))))
+    (when (logtest +regrex64+ flags)
+      (setf (x86-instruction-rex-prefix instruction)
+            (logior #x80 (need-rex-prefix instruction))))))
+
+
+
+(defun insert-modrm-reg (instruction operand)
+  (insert-modrm-reg-entry instruction (x86-register-operand-entry operand)))
+
+(defun insert-mmx-reg-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry)))
+    (setf (x86-instruction-modrm-byte instruction)
+          (dpb reg-num (byte 3 3)
+               (need-modrm-byte instruction)))))
+
+(defun insert-mmx-reg (instruction operand)
+  (insert-mmx-reg-entry instruction (x86-register-operand-entry operand)))
+
+(defun insert-xmm-reg (instruction operand)
+  (insert-modrm-reg instruction operand))
+
+(defun insert-xmm-rm (instruction operand)
+  (insert-modrm-rm instruction operand))
+
+(defun insert-opcode-reg-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry))
+         (flags (reg-entry-reg-flags entry))
+         (need-rex.b (logtest +regrex+ flags)))
+    (setf (x86-instruction-base-opcode instruction)
+          (dpb reg-num (byte 3 0)
+               (x86-instruction-base-opcode instruction)))
+    (when need-rex.b
+      (setf (x86-instruction-rex-prefix instruction)
+            (logior +rex-extz+ (need-rex-prefix instruction))))
+    (when (logtest +regrex64+ flags)
+      (setf (x86-instruction-rex-prefix instruction)
+            (logior #x80 (need-rex-prefix instruction))))))
+
+(defun insert-opcode-reg (instruction operand)
+  (insert-opcode-reg-entry instruction (x86-register-operand-entry operand)))
+
+;;; Insert a 4-bit register number in the low 4 bits of the opcode.
+;;; (This is only used in synthetic instructions, like some UUOs.)
+
+(defun insert-opcode-reg4-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry))
+         (xreg-num (logior reg-num
+                           (if
+                             (ccl::target-arch-case
+                              (:x8664
+                               (logtest +regrex+ (reg-entry-reg-flags entry)))
+                              (:x8632 t))
+                             #x08
+                             #x00))))
+    (setf (x86-instruction-base-opcode instruction)
+          (dpb xreg-num (byte 4 0)
+               (x86-instruction-base-opcode instruction)))))
+
+(defun insert-opcode-reg4 (instruction operand)
+  (insert-opcode-reg4-entry instruction (x86-register-operand-entry operand)))
+
+
+(defun insert-reg4-pseudo-rm-high-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry))
+         (xreg-num (logior reg-num
+                           (if (logtest +regrex+ (reg-entry-reg-flags entry))
+                             #x08
+                             #x00))))
+    (setf (x86-instruction-modrm-byte instruction)
+          (dpb xreg-num (byte 4 4)
+               (x86-instruction-modrm-byte instruction)))))
+
+(defun insert-reg4-pseudo-rm-high (instruction operand)
+  (insert-reg4-pseudo-rm-high-entry instruction (x86-register-operand-entry operand)))
+
+
+(defun insert-reg4-pseudo-rm-low-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry))
+         (xreg-num (logior reg-num
+                           (if (logtest +regrex+ (reg-entry-reg-flags entry))
+                             #x08
+                             #x00))))
+    (setf (x86-instruction-modrm-byte instruction)
+          (dpb xreg-num (byte 4 0)
+               (x86-instruction-modrm-byte instruction)))))
+
+(defun insert-reg4-pseudo-rm-low (instruction operand)
+  (insert-reg4-pseudo-rm-low-entry instruction (x86-register-operand-entry operand)))
+
+;;; Insert a 3-bit register value derived from OPERAND in INSN's modrm.rm
+;;; field.  If the register requires REX addressing, set the REX.B bit
+;;; in the instruction's rex-prefix.  If either the modrm or rex-prefix
+;;; fields of the instruction are NIL, we're very confused; check for
+;;; that explicitly until this code matures a bit.
+
+(defun insert-modrm-rm-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry))
+         (flags (reg-entry-reg-flags entry))
+         (need-rex.b (logtest +regrex+ flags)))
+    (setf (x86-instruction-modrm-byte instruction)
+          (dpb reg-num (byte 3 0) (need-modrm-byte instruction)))
+    (when need-rex.b
+      (setf (x86-instruction-rex-prefix instruction)
+            (logior +rex-extz+ (need-rex-prefix instruction))))
+    (when (logtest +regrex64+ flags)
+      (setf (x86-instruction-rex-prefix instruction)
+            (logior #x80 (need-rex-prefix instruction))))))
+
+(defun insert-modrm-rm (instruction operand)
+  (insert-modrm-rm-entry instruction (x86-register-operand-entry operand)))
+
+(defun insert-mmx-rm-entry (instruction entry)
+  (let* ((reg-num (reg-entry-reg-num entry)))
+    (setf (x86-instruction-modrm-byte instruction)
+          (dpb reg-num (byte 3 0) (need-modrm-byte instruction)))))
+
+(defun insert-mmx-rm (instruction operand)
+  (insert-mmx-rm-entry instruction (x86-register-operand-entry operand)))
+
+(defun insert-imm64 (instruction operand)
+  (setf (x86-immediate-operand-type operand)
+        (encode-operand-type :imm64))
+  (setf (x86-instruction-imm instruction) operand))
+
+(defun insert-imm32s (instruction operand)
+  (setf (x86-immediate-operand-type operand)
+        (encode-operand-type :imm32s))
+  (setf (x86-instruction-imm instruction) operand))
+
+(defun insert-imm32 (instruction operand)
+  (setf (x86-immediate-operand-type operand)
+        (encode-operand-type :imm32))
+  (setf (x86-instruction-imm instruction) operand))
+
+(defun insert-imm16 (instruction operand)
+  (setf (x86-immediate-operand-type operand)
+        (encode-operand-type :imm16))
+  (setf (x86-instruction-imm instruction) operand))
+
+(defun insert-imm8 (instruction operand)
+  (setf (x86-immediate-operand-type operand)
+        (encode-operand-type :imm8))
+  (setf (x86-instruction-imm instruction) operand))
+
+(defun insert-imm8s (instruction operand)
+  (setf (x86-immediate-operand-type operand)
+        (encode-operand-type :imm8s))
+  (setf (x86-instruction-imm instruction) operand))
+
+(defun insert-imm8-for-int (instruction operand)
+  (declare (ftype (function (t) t) ccl::early-x86-lap-expression-value))
+  (let* ((expr (x86-immediate-operand-value operand))
+         (value (ccl::early-x86-lap-expression-value expr)))
+    (if (eql value 3)
+      (setf (x86-instruction-base-opcode instruction)
+            +int3-opcode+)
+      (insert-imm8 instruction operand))))
+
+(defun insert-label (instruction operand)
+  (setf (x86-instruction-extra instruction)
+        (x86::x86-label-operand-label operand)))
+
+(defun insert-self (instruction operand)
+  (setf (x86-immediate-operand-type operand)
+	(encode-operand-type :self))
+  (setf (x86-instruction-imm instruction) operand))
+
+(defparameter *x8632-register-entries*
+  (flet ((register-entry (name)
+           (let* ((r (gethash name *x8632-registers*)))
+             (unless r (error "unknown register ~s" name))
+             r)))
+    (vector
+     ;; 32-bit registers
+     (register-entry "eax")
+     (register-entry "ecx")
+     (register-entry "edx")
+     (register-entry "ebx")
+     (register-entry "esp")
+     (register-entry "ebp")
+     (register-entry "esi")
+     (register-entry "edi")
+     ;; 16-bit-registers
+     (register-entry "ax")
+     (register-entry "cx")
+     (register-entry "dx")
+     (register-entry "bx")
+     (register-entry "sp")
+     (register-entry "bp")
+     (register-entry "si")
+     (register-entry "di")
+     ;; 8-bit registers
+     (register-entry "al")
+     (register-entry "cl")
+     (register-entry "dl")
+     (register-entry "bl")
+     (register-entry "ah")
+     (register-entry "ch")
+     (register-entry "dh")
+     (register-entry "bh")
+       ;;; xmm registers
+     (register-entry "xmm0")
+     (register-entry "xmm1")
+     (register-entry "xmm2")
+     (register-entry "xmm3")
+     (register-entry "xmm4")
+     (register-entry "xmm5")
+     (register-entry "xmm6")
+     (register-entry "xmm7")
+     ;; MMX registers
+     (register-entry "mm0")
+     (register-entry "mm1")
+     (register-entry "mm2")
+     (register-entry "mm3")
+     (register-entry "mm4")
+     (register-entry "mm5")
+     (register-entry "mm6")
+     (register-entry "mm7")
+     ;; x87 FP regs.  May or may not be useful.
+     (register-entry "st[0]")
+     (register-entry "st[1]")
+     (register-entry "st[2]")
+     (register-entry "st[3]")
+     (register-entry "st[4]")
+     (register-entry "st[5]")
+     (register-entry "st[6]")
+     (register-entry "st[7]")
+     ;; Our friends, the segment registers
+     (register-entry "cs")
+     (register-entry "ds")
+     (register-entry "ss")
+     (register-entry "es")
+     (register-entry "fs")
+     (register-entry "gs")
+     )))
+
+(dotimes (i (length *x8632-register-entries*))
+  (let* ((entry (svref *x8632-register-entries* i)))
+    (when entry
+      (setf (reg-entry-ordinal32 entry) i))))
+
+(defconstant +x8632-32-bit-register+ #x0)
+(defconstant +x8632-16-bit-register+ #x8)
+(defconstant +x8632-8-bit-register+ #x10)
+(defconstant +x8632-xmm-register-offset+ #x18)
+(defconstant +x8632-mmx-register-offset+ #x20)
+(defconstant +x8632-fpu-register-offset+ #x28)
+(defconstant +x8632-segment-register-offset+ #x30)
+
+(defparameter *x8664-register-entries*
+  (flet ((register-entry (name)
+           (let* ((r (gethash name *x8664-registers*)))
+             (unless r (error "unknown register ~s" name))
+             r)))
+    (vector
+     ;; 64-bit general-purpose registers
+     (register-entry "rax")
+     (register-entry "rcx")
+     (register-entry "rdx")
+     (register-entry "rbx")
+     (register-entry "rsp")
+     (register-entry "rbp")
+     (register-entry "rsi")
+     (register-entry "rdi")
+     (register-entry "r8")
+     (register-entry "r9")
+     (register-entry "r10")
+     (register-entry "r11")
+     (register-entry "r12")
+     (register-entry "r13")
+     (register-entry "r14")
+     (register-entry "r15")
+     ;; 32-bit registers
+     (register-entry "eax")
+     (register-entry "ecx")
+     (register-entry "edx")
+     (register-entry "ebx")
+     (register-entry "esp")
+     (register-entry "ebp")
+     (register-entry "esi")
+     (register-entry "edi")
+     (register-entry "r8d")
+     (register-entry "r9d")
+     (register-entry "r10d")
+     (register-entry "r11d")
+     (register-entry "r12d")
+     (register-entry "r13d")
+     (register-entry "r14d")
+     (register-entry "r15d")
+     ;; 16-bit-registers
+     (register-entry "ax")
+     (register-entry "cx")
+     (register-entry "dx")
+     (register-entry "bx")
+     (register-entry "sp")
+     (register-entry "bp")
+     (register-entry "si")
+     (register-entry "di")
+     (register-entry "r8w")
+     (register-entry "r9w")
+     (register-entry "r10w")
+     (register-entry "r11w")
+     (register-entry "r12w")
+     (register-entry "r13w")
+     (register-entry "r14w")
+     (register-entry "r15w")
+     ;; 8-bit registers
+     (register-entry "al")
+     (register-entry "cl")
+     (register-entry "dl")
+     (register-entry "bl")
+     (register-entry "spl")
+     (register-entry "bpl")
+     (register-entry "sil")
+     (register-entry "dil")
+     (register-entry "r8b")
+     (register-entry "r9b")
+     (register-entry "r10b")
+     (register-entry "r11b")
+     (register-entry "r12b")
+     (register-entry "r13b")
+     (register-entry "r14b")
+     (register-entry "r15b")
+       ;;; xmm registers
+     (register-entry "xmm0")
+     (register-entry "xmm1")
+     (register-entry "xmm2")
+     (register-entry "xmm3")
+     (register-entry "xmm4")
+     (register-entry "xmm5")
+     (register-entry "xmm6")
+     (register-entry "xmm7")
+     (register-entry "xmm8")
+     (register-entry "xmm9")
+     (register-entry "xmm10")
+     (register-entry "xmm11")
+     (register-entry "xmm12")
+     (register-entry "xmm13")
+     (register-entry "xmm14")
+     (register-entry "xmm15")
+     ;; MMX registers
+     (register-entry "mm0")
+     (register-entry "mm1")
+     (register-entry "mm2")
+     (register-entry "mm3")
+     (register-entry "mm4")
+     (register-entry "mm5")
+     (register-entry "mm6")
+     (register-entry "mm7")
+     ;; x87 FP regs.  May or may not be useful.
+     (register-entry "st[0]")
+     (register-entry "st[1]")
+     (register-entry "st[2]")
+     (register-entry "st[3]")
+     (register-entry "st[4]")
+     (register-entry "st[5]")
+     (register-entry "st[6]")
+     (register-entry "st[7]")
+     ;; Our friends, the segment registers
+     (register-entry "cs")
+     (register-entry "ds")
+     (register-entry "ss")
+     (register-entry "es")
+     (register-entry "fs")
+     (register-entry "gs")
+     (register-entry "rip")
+     )))
+
+(dotimes (i (length *x8664-register-entries*))
+  (let* ((entry (svref *x8664-register-entries* i)))
+    (when entry
+      (setf (reg-entry-ordinal64 entry) i))))
+
+(defconstant +x8664-64-bit-register+ #x00)
+(defconstant +x8664-32-bit-register+ #x10)
+(defconstant +x8664-16-bit-register+ #x20)
+(defconstant +x8664-8-bit-register+ #x30)
+(defconstant +x8664-xmm-register-offset+ #x40)
+(defconstant +x8664-mmx-register-offset+ #x50)
+(defconstant +x8664-fpu-register-offset+ #x58)
+(defconstant +x8664-segment-register-offset+ #x60)
+
+(defun x86-segment-register (i)
+  (if (and (typep i 'unsigned-byte)
+           (< i 6))
+      (ccl::target-arch-case
+       (:x8632
+	(svref *x8632-register-entries* (+ +x8632-segment-register-offset+ i)))
+       (:x8664
+	(svref *x8664-register-entries* (+ +x8664-segment-register-offset+ i))))))
+
+(defun x86-xmm-register (i)
+  (ccl::target-arch-case
+   (:x8632
+    (if (typep i '(mod 8))
+	(svref *x8632-register-entries* (+ +x8632-xmm-register-offset+ i))))
+   (:x8664
+    (if (typep i '(mod 16))
+	(svref *x8664-register-entries* (+ +x8664-xmm-register-offset+ i))))))
+
+(defun x86-mmx-register (i)
+  (if (typep i '(mod 8))
+      (ccl::target-arch-case
+       (:x8632
+	(svref *x8632-register-entries* (+ +x8632-mmx-register-offset+ i)))
+       (:x8664
+	(svref *x8664-register-entries* (+ +x8664-mmx-register-offset+ i))))))
+    
+
+(defun gpr-ordinal (r)
+  (ccl::target-arch-case
+   (:x8632
+    (or
+     (etypecase r
+       ((mod 24) r)
+       ((or string symbol)
+	(let* ((entry (gethash r *x8632-registers*)))
+	  (if entry
+	    (reg-entry-ordinal32 entry))))
+       (reg-entry (reg-entry-ordinal32 r))
+       (x86-register-operand
+	(reg-entry-ordinal32 (x86-register-operand-entry r))))
+     (error "Can't determine register ordinal of ~s" r)))
+   (:x8664
+    (or
+     (etypecase r
+       ((mod 64) r)
+       ((or string symbol)
+	(let* ((entry (gethash r *x8664-registers*)))
+	  (if entry
+	    (reg-entry-ordinal64 entry))))
+       (reg-entry (reg-entry-ordinal64 r))
+       (x86-register-operand
+	(reg-entry-ordinal64 (x86-register-operand-entry r))))
+     (error "Can't determine register ordinal of ~s" r)))))
+   
+
+(defun x86-reg8 (r)
+  (ccl::target-arch-case
+   (:x8632
+    (svref *x8632-register-entries* (dpb (gpr-ordinal r)
+					 (byte 3 0)
+					 +x8632-8-bit-register+)))
+   (:x8664
+    (svref *x8664-register-entries* (dpb (gpr-ordinal r)
+					 (byte 4 0)
+					 +x8664-8-bit-register+)))))
+
+(defun x86-reg16 (r)
+  (ccl::target-arch-case
+   (:x8632
+    (svref *x8632-register-entries* (dpb (gpr-ordinal r)
+					 (byte 3 0)
+					 +x8632-16-bit-register+)))
+   (:x8664
+    (svref *x8664-register-entries* (dpb (gpr-ordinal r)
+					 (byte 4 0)
+					 +x8664-16-bit-register+)))))
+
+(defun x86-reg32 (r)
+  (ccl::target-arch-case
+   (:x8632
+    (svref *x8632-register-entries* (dpb (gpr-ordinal r)
+					 (byte 3 0)
+					 +x8632-32-bit-register+)))
+   (:x8664
+    (svref *x8664-register-entries* (dpb (gpr-ordinal r)
+					 (byte 4 0)
+					 +x8664-32-bit-register+)))))
+
+(defun x86-reg64 (r)
+  (ccl::target-arch-case
+   (:x8632
+    (error "x8632 doesn't have 64 bit register ~s" r))
+   (:x8664
+    (svref *x8664-register-entries* (dpb (gpr-ordinal r)
+					 (byte 4 0)
+					 +x8664-64-bit-register+)))))
+
+;;; This returns true if the template's operand types "match" the
+;;; types of the actual operands.
+(defun match-template-types (template type0 type1 type2 &optional (backend ccl::*target-backend*))
+  #+debug
+  (format t "~& template = ~s, operand types = ~s" template (list type0 type1 type2))
+  (case (ccl::backend-target-arch-name backend)
+   (:x8632
+    (if (logtest (encode-opcode-flags :cpu64) (x86-opcode-template-flags template))
+      (return-from match-template-types nil)))
+   (:x8664
+    (if (logtest (encode-opcode-flags :cpuno64) (x86-opcode-template-flags template))
+      (return-from match-template-types nil))))
+  (flet ((match (overlap given)
+           (and
+            (not (zerop (logandc2 overlap (encode-operand-type :jumpabsolute))))
+            (= (logand given (encode-operand-type :baseindex :jumpabsolute))
+               (logand overlap (encode-operand-type :baseindex :jumpabsolute)))))
+         (consistent-register-match (m0 g0 t0 m1 g1 t1)
+           (let* ((g0&reg (logand g0 (encode-operand-type :reg)))
+                  (g1&reg (logand g1 (encode-operand-type :reg))))
+             (or (zerop g0&reg)
+                 (zerop g1&reg)
+                 (= g0&reg g1&reg)
+                 (not
+                  (logtest
+                   (if (logtest m0 (encode-operand-type :acc))
+                     (encode-operand-type :reg)
+                     t0)
+                   (if (logtest m1 (encode-operand-type :acc))
+                     (encode-operand-type :reg)
+                     t1)))))))
+    (let* ((nops (if type2 3 (if type1 2 (if type0 1 0)))))
+      (declare (fixnum nops))
+      (let* ((template-types
+              (x86-opcode-template-operand-types template)))
+        (when (= nops (the fixnum (length template-types)))
+          (or (zerop nops)
+              (let* ((template-type0 (svref template-types 0))
+                     (overlap0
+                      (logand type0 template-type0))
+                     (match0 (match overlap0 type0)))
+                (if match0
+                  (or (= nops 1)
+                      ;; 2 or 3 operands.
+                      (let* ((template-type1 (svref template-types 1))
+                             (overlap1 (logand type1 template-type1))
+                             (match1 (match overlap1 type1)))
+                        (if (and
+                             match1
+                             (consistent-register-match
+                              overlap0
+                              type0
+                              template-type0
+                              overlap1
+                              type1
+                              template-type1))
+                          (or (= nops 2)
+                              ;; 3 operands
+                              (let* ((template-type2 (svref template-types 2))
+                                     (overlap2 (logand type2 template-type2)))
+                                (and (match overlap2 type2)
+                                     (consistent-register-match
+                                      overlap1
+                                      type1
+                                      template-type1
+                                      overlap2
+                                      type2
+                                      template-type2)))))))))))))))
+
+;;; the format of operands in lap and in vinsns differs
+;;; #'x86-encode-vinsn-operand-type is for vinsns
+;;; #'x86-operand-type is for lap
+(defun match-template (template parsed-operands)
+  (let* ((flags (x86-opcode-template-flags template))
+	 (operand-types (mapcar #'x86-operand-type parsed-operands))
+	 (type0 (pop operand-types))
+	 (type1 (pop operand-types))
+	 (type2 (car operand-types)))
+    #+debug
+    (format t "~& template = ~s, operand types = ~s" template operand-types)
+    (ccl::target-arch-case
+     (:x8632
+      (if (not (logtest (encode-opcode-flags :cpu64) flags))
+	(match-template-types template type0 type1 type2)))
+     (:x8664
+      (if (not (logtest (encode-opcode-flags :cpuno64) flags))
+	(match-template-types template type0 type1 type2))))))
+
+
+(provide "X86-ASM")
Index: /branches/new-random/compiler/X86/x86-backend.lisp
===================================================================
--- /branches/new-random/compiler/X86/x86-backend.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/x86-backend.lisp	(revision 13309)
@@ -0,0 +1,392 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(next-nx-defops)
+(defvar *x862-specials* nil)
+(let* ((newsize (%i+ (next-nx-num-ops) 10))
+       (old *x862-specials*)
+       (oldsize (length old)))
+  (declare (fixnum newsize oldsize))
+  (unless (>= oldsize newsize)
+    (let* ((v (make-array newsize :initial-element nil)))
+      (dotimes (i oldsize (setq *x862-specials* v))
+        (setf (svref v i) (svref old i))))))
+
+(defun x86-encode-vinsn-operand-type (thing backend)
+  (when thing
+    (if (atom thing)
+      (x86::encode-operand-type :label)
+      (ecase (car thing)
+        (:% (ecase (arch::target-lisp-node-size (backend-target-arch backend))
+              (8 (x86::encode-operand-type :reg64))
+              (4 (x86::encode-operand-type :reg32))))
+	(:%acc (ecase (arch::target-lisp-node-size (backend-target-arch backend))
+              (8 (x86::encode-operand-type :reg64 :acc))
+              (4 (x86::encode-operand-type :reg32 :acc))))
+        (:%q (x86::encode-operand-type :reg64))
+        (:%accq (x86::encode-operand-type :reg64 :acc))
+        (:%l (x86::encode-operand-type :reg32))
+        (:%accl (x86::encode-operand-type :reg32 :acc))
+        (:%w (x86::encode-operand-type :reg16))
+        (:%accw (x86::encode-operand-type :reg16 :acc))
+        (:%b (x86::encode-operand-type :reg8))
+        (:%accb (x86::encode-operand-type :reg8 :acc))
+        (:%xmm (x86::encode-operand-type :regxmm))
+        (:%mmx (x86::encode-operand-type :regmmx))
+        (:@ (x86::encode-operand-type :anymem))
+        (:rcontext (x86::encode-operand-type :anymem))
+        (:$1 (x86::encode-operand-type :imm1) )
+        (:$b (x86::encode-operand-type :imm8s ))
+        (:$ub (x86::encode-operand-type :imm8))
+        (:$w (x86::encode-operand-type :imm16))
+        (:$l (x86::encode-operand-type :imm32s))
+        (:$ul  (x86::encode-operand-type :imm32))
+        (:$q (x86::encode-operand-type :imm64))
+        (:%shift (x86::encode-operand-type :shiftcount :reg8))
+	(:$self (x86::encode-operand-type :self))))))
+
+(defun lookup-x86-opcode (form backend)
+  (when (consp form)
+    (let* ((name (string (car form)))
+           (templates (gethash name x86::*x86-opcode-template-lists*)))
+      (when templates
+        (flet ((optype (thing)
+                 (x86-encode-vinsn-operand-type thing backend)))
+          (let* ((operands (cdr form))
+                 (type0 (optype (pop operands)))
+                 (type1 (optype (pop operands)))
+                 (type2 (optype (car operands))))
+            (dolist (template templates)
+              (when (x86::match-template-types template type0 type1 type2 backend)
+                (collect ((types))
+                  (if type0 (types type0))
+                  (if type1 (types type1))
+                  (if type2 (types type2))
+                  (return (values (x86::x86-opcode-template-ordinal template)
+                                  (types))))))))))))
+
+(defun fixup-opcode-ordinals (vinsn-template opcode-templates &optional (backend *target-backend*))
+  (let* ((changed ()))
+    (dolist (vinsn-opcode (vinsn-template-opcode-alist vinsn-template))
+      (destructuring-bind (old-ordinal name &optional type0 type1 type2) vinsn-opcode
+        (let* ((opcode-templates (gethash name opcode-templates)))
+          (unless opcode-templates
+            (error "Unknown X86 instruction - ~a.  Odd, because it was once a known instruction." name))
+        (let* ((new-ordinal (dolist (template opcode-templates)
+                              (when (x86::match-template-types template type0 type1 type2 backend)
+                                (return (x86::x86-opcode-template-ordinal template))))))
+          (unless new-ordinal
+            (error "No match for opcode ~s in ~s" vinsn-opcode vinsn-template))
+          (unless (eql old-ordinal new-ordinal)
+            (setf (car vinsn-opcode) new-ordinal)
+            (push (cons old-ordinal new-ordinal) changed))))))
+    (when changed
+      ;;(format t "~& opcode ordinals changed in ~s: ~s" vinsn-template changed)
+      (flet ((update-instruction (i)
+               (when (consp i)
+                 ;; An :ANCHORED-UUO directive contains a real
+                 ;; (vinsn-encoded) instruction (typically a UUO) in
+                 ;; its cadr.  Other directives won't contain embedded
+                 ;; instructions and whatever's in their CARs won't
+                 ;; match in the assoc below.
+                 (when (eq (car i) :anchored-uuo)
+                   (setq i (cadr i)))
+                 (let* ((pair (assoc (car i) changed :test #'eq)))
+                   (when pair
+                     (setf (car i) (cdr pair)))))))
+        (labels ((fixup-form (form)
+                   (unless (atom form)
+                     (if (atom (car form))
+                       (update-instruction form)
+                       (dolist (f (cdr form))
+                         (fixup-form f))))))
+          (dolist (form (vinsn-template-body vinsn-template))
+            (fixup-form form)))))))
+
+(defparameter *report-missing-vinsns* nil)
+
+(defun fixup-x86-vinsn-templates (template-hash opcode-templates &optional (backend *target-backend*))
+  (maphash #'(lambda (name vinsn-template)
+               (if (not (cdr vinsn-template))
+                 (when *report-missing-vinsns*
+                   (warn "Reference to undefined vinsn ~s" name))
+                 (fixup-opcode-ordinals (cdr vinsn-template) opcode-templates backend)))
+           template-hash))
+
+
+
+;;; This defines a template.  All expressions in the body must be
+;;; evaluable at macroexpansion time.
+(defun define-x86-vinsn (backend vinsn-name results args temps body)
+  (let* ((opcode-lookup (backend-lookup-opcode backend))
+	 (backend-name (backend-name backend))
+         (arch-name (backend-target-arch-name backend))
+	 (template-hash (backend-p2-template-hash-name backend))
+	 (name-list ())
+	 (attrs 0)
+         (nhybrids 0)
+         (local-labels ())
+         (referenced-labels ())
+	 (source-indicator (form-symbol arch-name "-VINSN"))
+         (opcode-alist ()))
+    (flet ((valid-spec-name (x)
+	     (or (and (consp x) 
+		      (consp (cdr x)) 
+		      (null (cddr x)) 
+		      (atom (car x))
+		      (or (assoc (cadr x) *vreg-specifier-constant-constraints* :test #'eq)
+			  (assoc (cadr x) *spec-class-storage-class-alist* :test #'eq)
+			  (eq (cadr x) :label)
+                          (and (consp (cadr x)) (eq (caadr x) :label) (consp (cdadr x)) (null (cddadr x)))
+			  (and (consp (cadr x))
+			       (or 
+				(assoc (caadr x) *vreg-specifier-constant-constraints* :test #'eq)
+				(assoc (caadr x) *spec-class-storage-class-alist* :test #'eq))))
+		      (car x))
+		 (error "Invalid vreg spec: ~s" x)))
+           (add-spec-name (vname) 
+             (if (member vname name-list :test #'eq)
+               (error "Duplicate name ~s in vinsn ~s" vname vinsn-name)
+               (push vname name-list))))
+      (declare (dynamic-extent #'valid-spec-name #'add-spec-name))
+      (when (consp vinsn-name)
+        (setq attrs (encode-vinsn-attributes (cdr vinsn-name))
+              vinsn-name (car vinsn-name)))
+      (unless (and (symbolp vinsn-name) (eq *CCL-PACKAGE* (symbol-package vinsn-name)))
+        (setq vinsn-name (intern (string vinsn-name) *CCL-PACKAGE*)))
+      (dolist (n (append args temps))
+        (add-spec-name (valid-spec-name n)))
+      (dolist (form body)
+        (if (atom form)
+          (add-spec-name form)))
+      (setq name-list (nreverse name-list))
+      ;; We now know that "args" is an alist; we don't know if
+      ;; "results" is.  First, make sure that there are no duplicate
+      ;; result names (and validate "results".)
+      (do* ((res results tail)
+            (tail (cdr res) (cdr tail)))
+           ((null res))
+        (let* ((name (valid-spec-name (car res))))
+          (if (assoc name tail :test #'eq)
+            (error "Duplicate result name ~s in ~s." name results))))
+      (let* ((non-hybrid-results ()) 
+             (match-args args))
+        (dolist (res results)
+          (let* ((res-name (car res)))
+            (if (not (assoc res-name args :test #'eq))
+              (if (not (= nhybrids 0))
+                (error "result ~s should also name an argument. " res-name)
+                (push res-name non-hybrid-results))
+              (if (eq res-name (caar match-args))
+                (setf nhybrids (1+ nhybrids)
+                      match-args (cdr match-args))
+                (error "~S - hybrid results should appear in same order as arguments." res-name)))))
+        (dolist (name non-hybrid-results)
+          (add-spec-name name)))
+      (let* ((k -1))
+        (declare (fixnum k))
+        (let* ((name-alist (mapcar #'(lambda (n) (cons n (list (incf k)))) name-list)))
+          (flet ((find-name (n)
+                   (let* ((pair (assoc n name-alist :test #'eq)))
+                     (declare (list pair))
+                     (if pair
+                       (cdr pair)
+                       (or (subprim-name->offset n backend)
+                           (error "Unknown name ~s" n))))))
+            (labels ((simplify-simple-operand (op)
+                       (if (atom op)
+                         (if (typep op 'fixnum)
+                           op
+                           (if (eq op :rcontext)
+                             op
+                             (if (constantp op)
+                               (progn
+                                 (if (keywordp op)
+                                   (pushnew op referenced-labels))
+                                 (eval op))
+                               (find-name op))))
+                         (if (eq (car op) :^)
+                           (list :^ (simplify-simple-operand (cadr op)))
+                           (if (eq (car op) :apply)
+                             `(,(cadr op) ,@(mapcar #'simplify-operand (cddr op)))
+                             (if (member (car op)
+                                         '(:tra :align :byte :word :long :quad :talign))
+                               `(,(car op) ,(simplify-operand (cadr op)))
+                               (simplify-operand (eval op))))))) ; Handler-case this?
+                     (simplify-memory-operand (op)
+                       ;; This happens to be the only place that
+                       ;; we allow segment registers.
+                       (let* ((seg nil)
+                              (disp nil)
+                              (base nil)
+                              (index nil)
+                              (scale nil))
+                         (do* ((form op (cdr form)))
+                              ((null form) (list seg disp base index scale))
+                           (let* ((head (car form)))
+                             (if (consp head)
+                               (case (car head)
+                                 (:%seg
+                                  (if (eq form op)
+                                    (setq seg (simplify-operand (cadr head)))
+                                    (error "Bad :%seg in ~s" op)))
+                                 ((:%q :% :%l)
+                                  (let* ((r (simplify-operand head)))
+                                    (if base
+                                      (if index
+                                        (error "Extra register ~s in ~s"
+                                               head op)
+                                        (setq index r))
+                                      (setq base r))))
+                                 (t
+                                  (if (and (null (cdr form))
+                                           (or disp base index))
+                                    (progn
+                                      (setq scale (simplify-simple-operand head))
+                                      (if (and base (not index))
+                                        (setq index base base nil)))
+                                    (if (not (or disp base index))
+                                      (setq disp (simplify-simple-operand head))
+                                      (error "~s not expected in ~s" head op)))))
+                               (if (and (null (cdr form))
+                                        (or disp base index))
+                                 (progn
+                                   (setq scale (simplify-simple-operand head))
+                                   (if (and base (not index))
+                                     (setq index base base nil)))
+                                 (if (not (or disp base index))
+                                   (setq disp (simplify-simple-operand head))
+                                   (error "~s not expected in ~s" head op))))))))
+                     (simplify-operand (op)
+                       (cond ((atom op)
+                              (simplify-simple-operand op))
+                             ((eq (car op) :@)
+                              (cons :@
+                                    (simplify-memory-operand (cdr op))))
+                             ((eq (car op) :rcontext)
+                              (list :rcontext
+                                    (simplify-simple-operand (cadr op))))
+                             ((member (car op)
+                                      '(:% :%q :%l :%w :%b
+					:%acc :%accq :%accl :%accw :%accb
+					:$ :$1 :$b :$ub :$w :$l
+                                        :$ul :$q :%mmx :%xmm :%shift :$self))
+                              (simplify-simple-operand (cadr op)))
+                             (t
+                              (simplify-simple-operand op)))))
+              (labels ((simplify-constraint (guard)
+                         ;; A constraint is one of
+
+                         ;; (:eq|:lt|:gt vreg-name constant) ; "value"
+                         ;; of vreg relop constant
+
+                         ;; (:pred <function-name> <operand>* ;
+                         ;; <function-name> unquoted, each <operand>
+                         ;; is a vreg-name or constant expression.
+
+                         ;; (:type vreg-name typeval) ; vreg is of
+                         ;; "type" typeval
+                         ;;
+                         ;;(:not <constraint>) ; constraint is false
+                         ;; (:and <constraint> ...)        ;  conjuntion
+                         ;; (:or <constraint> ...)         ;  disjunction
+                         ;; There's no "else"; we'll see how ugly it
+                         ;; is without one.
+                         (destructuring-bind (guardname &rest others) guard
+                           (ecase guardname
+                             (:not 
+                              (destructuring-bind (negation) others
+                                `(:not ,(simplify-constraint negation))))
+                             (:pred
+                              (destructuring-bind (predicate &rest operands) others
+                                `(:pred ,predicate ,@(mapcar #'simplify-operand operands))))
+                             ((:eq :lt :gt :type)
+                              (destructuring-bind (vreg constant) others
+                                (unless (constantp constant)
+                                  (error "~S : not constant in constraint ~s ." constant guard))
+                                `(,guardname ,(find-name vreg) ,(eval constant))))
+                             ((:or :and)
+                              (unless others (error "Missing constraint list in ~s ." guard))
+                              `(,guardname ,(mapcar #'simplify-constraint others))))))
+                       (simplify-form (form)
+                         (if (atom form)
+                           (progn 
+                             (if (keywordp form) (push form local-labels) )
+                             form)
+                           (destructuring-bind (&whole w opname &rest opvals) form
+                             (if (consp opname) ; A constraint, we presume ...
+                               (cons (simplify-constraint opname)
+                                     (mapcar #'simplify-form opvals))
+                               (if (keywordp opname)
+                                 (progn
+                                   (list opname
+                                         (if (eq opname :anchored-uuo)
+                                           (simplify-form (car opvals))
+                                           (simplify-operand (car opvals)))))
+                                 (let* ((name (string opname)))
+                                   (multiple-value-bind (opnum types)
+                                       (funcall opcode-lookup form backend)
+                                     (if (not opnum)
+                                       (error "Unknown ~A instruction in ~s" backend-name form)
+                                       (let* ((opvals (mapcar #'simplify-operand opvals)))
+                                         (setf (assq opnum opcode-alist) (cons name types))
+                                         `(,opnum ,@opvals)))))))))))
+                (let* ((template (make-vinsn-template :name vinsn-name
+                                                      :result-vreg-specs results
+                                                      :argument-vreg-specs args
+                                                      :temp-vreg-specs temps
+                                                      :nhybrids nhybrids
+                                                      :results&args (append results (nthcdr nhybrids args))
+                                                      :nvp (- (+ (length results) (length args) (length temps))
+                                                              nhybrids)
+                                                      :body (prog1 (mapcar #'simplify-form body)
+                                                              (dolist (ref referenced-labels)
+                                                                (unless (memq ref local-labels)
+                                                                  (error 
+                                                                   "local-label ~S was referenced but ~
+                                                                    never defined in VINSN-TEMPLATE definition for ~s"
+                                                                   ref vinsn-name))))
+                                                      :local-labels local-labels
+                                                      :attributes attrs
+                                                      :opcode-alist opcode-alist)))
+                  
+                  `(progn
+                    (set-vinsn-template ',vinsn-name ,template ,template-hash)
+                    (record-source-file ',vinsn-name ',source-indicator)
+                    ',vinsn-name))))))))))
+
+
+
+#+x8632-target
+(require "X8632-BACKEND")
+#+x8664-target
+(require "X8664-BACKEND")
+
+(defparameter *x86-backend*
+  #+x8632-target *x8632-backend*
+  #+x8664-target *x8664-backend*
+  #-x86-target nil)
+
+	      
+(defun fixup-x86-backend (&rest args)
+  #+x8632-target (apply #'fixup-x8632-backend args)
+  #+x8664-target (apply #'fixup-x8664-backend args)
+  #-x86-target (declare (ignore args))
+  )
+
+(provide "X86-BACKEND")
Index: /branches/new-random/compiler/X86/x86-disassemble.lisp
===================================================================
--- /branches/new-random/compiler/X86/x86-disassemble.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/x86-disassemble.lisp	(revision 13309)
@@ -0,0 +1,2982 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "NXENV")
+  (require "DLL-NODE")
+  (require "X86-ASM")
+  (require "X86-LAP"))
+
+(defstruct (x86-disassembled-instruction (:include dll-node)
+                                         (:conc-name x86-di-))
+  address
+  labeled
+  prefixes                              ;explicit prefixes
+  mnemonic
+  op0
+  op1
+  op2
+  )
+
+(defmethod print-object ((xdi x86-disassembled-instruction) stream)
+  (print-unreadable-object (xdi stream :type t :identity t)
+    (dolist (p (x86-di-prefixes xdi))
+      (format stream "(~a) " p))
+    (format stream "(~a" (x86-di-mnemonic xdi))
+    (let* ((op0 (x86-di-op0 xdi))
+	   (op1 (x86-di-op1 xdi))
+	   (op2 (x86-di-op2 xdi))
+	   (ds (make-x86-disassembly-state :mode-64 #+x8664-target t
+					            #+x8632-target nil
+					   :code-vector nil
+					   :code-pointer 0)))
+      (when op0
+	(write-x86-lap-operand stream op0 ds)
+	(when op1
+	  (write-x86-lap-operand stream op1 ds)
+	  (when op2
+	    (write-x86-lap-operand stream op2 ds)))))
+    (format stream ")")))
+
+(defstruct (x86-disassembly-state (:conc-name x86-ds-))
+  (mode-64 t)
+  (prefixes 0)
+  (used-prefixes 0)
+  (rex 0)
+  (rex-used 0)
+  (need-modrm nil)
+  (mod 0)
+  (reg 0)
+  (rm 0)
+  (blocks (make-dll-header))
+  (insn-start 0)                        ; offset of first prefix byte
+  (opcode-start 0)                      ; offset of first opcode byte
+  code-vector
+  code-pointer
+  code-limit
+  constants-vector
+  pending-labels
+  (entry-point 0)
+  current-instruction
+  (string-buffer (make-array 16 :element-type 'character
+                             :fill-pointer 0
+                             :adjustable t))
+  (symbolic-names ())
+)
+
+(defun badop (ds)
+  (setf (x86-ds-code-pointer ds) (1+ (x86-ds-opcode-start ds)))
+  ;;; Do more here.
+  )
+
+(defun x86-ds-peek-u8 (ds)
+  (aref (x86-ds-code-vector ds) (x86-ds-code-pointer ds)))
+
+(defun x86-ds-skip (ds &optional (n 1))
+  (incf (x86-ds-code-pointer ds) n))
+
+(defun x86-ds-next-u8 (ds)
+  (let* ((idx (x86-ds-code-pointer ds)))
+    (incf (x86-ds-code-pointer ds))
+    (aref (x86-ds-code-vector ds) idx)))
+
+(defun x86-ds-next-s8 (ds)
+  (let* ((u8 (x86-ds-next-u8 ds)))
+    (if (logbitp 7 u8)
+      (- u8 #x100)
+      u8)))
+
+(defun x86-ds-next-u16 (ds)
+  (let* ((low (x86-ds-next-u8 ds))
+         (high (x86-ds-next-u8 ds)))
+    (declare (type (unsigned-byte 8) low high))
+    (logior (the fixnum (ash high 8)) low)))
+
+(defun x86-ds-next-s16 (ds)
+  (let* ((low (x86-ds-next-u8 ds))
+         (high (x86-ds-next-s8 ds)))
+    (declare (type (unsigned-byte 8) low)
+             (type (signed-byte 8) high))
+    (logior (the fixnum (ash high 8)) low)))
+
+(defun x86-ds-next-u32 (ds)
+  (let* ((low (x86-ds-next-u16 ds))
+         (high (x86-ds-next-u16 ds)))
+    (declare (type (unsigned-byte 16) low high))
+    (logior (ash high 16) low)))
+
+(defun x86-ds-next-s32 (ds)
+  (let* ((low (x86-ds-next-u16 ds))
+         (high (x86-ds-next-s16 ds)))
+    (declare (type (unsigned-byte 16) low)
+             (type (signed-byte 16) high))
+    (logior (ash high 16) low)))
+
+(defun x86-ds-next-u64 (ds)
+  (let* ((low (x86-ds-next-u32 ds))
+         (high (x86-ds-next-u32 ds)))
+    (logior (ash high 32) low)))
+
+(defun x86-ds-next-s64 (ds)
+  (let* ((low (x86-ds-next-u32 ds))
+         (high (x86-ds-next-s32 ds)))
+    (logior (ash high 32) low)))
+
+(defun used-rex (ds value)
+  (if (not (zerop value))
+    (setf (x86-ds-rex-used ds)
+          (logior (x86-ds-rex-used ds)
+                  (if (logtest (x86-ds-rex ds) value)
+                    #x40
+                    0)))
+    (setf (x86-ds-rex-used ds)
+          (logior (x86-ds-rex-used ds) #x40))))
+
+(defun used-prefix (ds mask)
+  (setf (x86-ds-used-prefixes ds)
+        (logior (x86-ds-used-prefixes ds)
+                (logand (x86-ds-prefixes ds) mask))))
+
+
+
+;;; An x86-disassembly-block is -something- like a basic block in a
+;;; compiler flow graph; it ends with an unconditional jump and it's
+;;; either the entry node in that graph or it's reachable via a jump
+;;; or branch from some other reachable block.  There may, however, be
+;;; internal labels that are referenced from within the block's
+;;; instructions, from some other block, or both.  Each disassembled
+;;; instruction within a block keeps track of its address and whether
+;;; or not it's a label (a branch or jump target or a tagged return
+;;; address.)  The first instruction in each block is a label; others
+;;; (initally) aren't.  Whenever we encounter a branch or jmp
+;;; instruction (or a manipulation of a tagged return address, which
+;;; is a kind of jmp) and determine the address of the label, we add
+;;; that address to the disassembly-state's PENDING-LABELS set.  When
+;;; we're through processing the block (having encountered an
+;;; unconditional jmp), we remove a pending label from that set.  If
+;;; it's within a block that's already been processed, we ensure that
+;;; the instruction at that address is marked as a label; otherwise,
+;;; we process the new block which starts at that address.
+;;; Eventually, this'll terminate with all reachable code having been
+;;; processed.  There's embedded data and alignment padding in Clozure CL
+;;; x86 functions and this approach means that we won't try to
+;;; disassemble any of that; if the compiler generates any unreachable
+;;; code, we won't see that, either.
+
+;;; There might be a large number of blocks, in which case
+;;; keeping them in a search tree might be a better idea.
+(defstruct (x86-dis-block (:include dll-node))
+  start-address
+  end-address
+  (instructions (make-dll-header))
+)
+
+;;; Insert the block before the first existing block whose
+;;; start address is greater than or equal to this block's
+;;; end address.  (Yes, they can be equal; no, there should
+;;; never be any overlap.)
+(defun insert-x86-block (block blocks)
+  (let* ((this-end (x86-dis-block-end-address block)))
+    (declare (fixnum this-end))
+    (do-dll-nodes (other blocks (append-dll-node block blocks))
+      (when (>= (the fixnum (x86-dis-block-start-address other))
+                this-end)
+        (return (insert-dll-node-before block other))))))
+
+(defun x86-dis-find-label (address blocks)
+  (declare (fixnum address))
+  (do-dll-nodes (block blocks)
+    (when (and (>= address (the fixnum (x86-dis-block-start-address block)))
+               (< address (the fixnum (x86-dis-block-end-address block))))
+      (let* ((instruction
+              (do-dll-nodes (i (x86-dis-block-instructions block))
+                (when (= (x86-di-address i) address)
+                  (return i)))))
+        (unless instruction
+          (error "Bug: no instruction at address #x~x" address))
+        (return (or (x86-di-labeled instruction)
+                    (setf (x86-di-labeled instruction) t)))))))
+
+
+;;; Flags stored in PREFIXES
+(defconstant +PREFIX-REPZ+ 1)
+(defconstant +PREFIX-REPNZ+ 2)
+(defconstant +PREFIX-LOCK+ 4)
+(defconstant +PREFIX-CS+ 8)
+(defconstant +PREFIX-SS+ #x10)
+(defconstant +PREFIX-DS+ #x20)
+(defconstant +PREFIX-ES+ #x40)
+(defconstant +PREFIX-FS+ #x80)
+(defconstant +PREFIX-GS+ #x100)
+(defconstant +PREFIX-DATA+ #x200)
+(defconstant +PREFIX-ADDR+ #x400)
+(defconstant +PREFIX-FWAIT+ #x800)
+
+
+
+                              
+(defstruct (x86-dis (:constructor %make-x86-dis))
+  mnemonic                              ; may be nil
+  flags                                 ; extra info
+  op1                                   ; function to obtain 1st operand
+  bytemode1                             ; flags associated with operand1
+  op2                                   ; function for second operand
+  bytemode2                             ; flags for operand2
+  op3                                   ; function,
+  bytemode3                             ; flags for operand3
+  )
+
+(defconstant +SUFFIX-ALWAYS+ 4)
+(defconstant +AFLAG+ 2)
+(defconstant +DFLAG+ 1)
+
+(defconstant +b-mode+ 1)                ; byte operand
+(defconstant +v-mode+ 2)                ; operand size depends on prefixes
+(defconstant +w-mode+ 3)                ; word operand
+(defconstant +d-mode+ 4)                ; double word operand
+(defconstant +q-mode+ 5)                ; quad word operand
+(defconstant +t-mode+ 6)                ; ten-byte operand
+(defconstant +x-mode+ 7)                ; 16-byte XMM operand
+(defconstant +m-mode+ 8)                ; d-mode in 32bit, q-mode in 64bit mode.
+(defconstant +cond-jump-mode+ 9)
+(defconstant +loop-jcxz-mode+ 10)
+(defconstant +dq-mode+ 11)              ; operand size depends on REX prefixes.
+(defconstant +dqw-mode+ 12)             ; registers like dq-mode, memory like w-mode.
+(defconstant +f-mode+ 13)               ; 4- or 6-byte pointer operand
+(defconstant +const-1-mode+ 14)
+
+(defconstant +es-reg+ 100)
+(defconstant +cs-reg+ 101)
+(defconstant +ss-reg+ 102)
+(defconstant +ds-reg+ 103)
+(defconstant +fs-reg+ 104)
+(defconstant +gs-reg+ 105)
+
+(defconstant +eAX-reg+ 108)
+(defconstant +eCX-reg+ 109)
+(defconstant +eDX-reg+ 110)
+(defconstant +eBX-reg+ 111)
+(defconstant +eSP-reg+ 112)
+(defconstant +eBP-reg+ 113)
+(defconstant +eSI-reg+ 114)
+(defconstant +eDI-reg+ 115)
+
+(defconstant +al-reg+ 116)
+(defconstant +cl-reg+ 117)
+(defconstant +dl-reg+ 118)
+(defconstant +bl-reg+ 119)
+(defconstant +ah-reg+ 120)
+(defconstant +ch-reg+ 121)
+(defconstant +dh-reg+ 122)
+(defconstant +bh-reg+ 123)
+
+(defconstant +ax-reg+ 124)
+(defconstant +cx-reg+ 125)
+(defconstant +dx-reg+ 126)
+(defconstant +bx-reg+ 127)
+(defconstant +sp-reg+ 128)
+(defconstant +bp-reg+ 129)
+(defconstant +si-reg+ 130)
+(defconstant +di-reg+ 131)
+
+(defconstant +rAX-reg+ 132)
+(defconstant +rCX-reg+ 133)
+(defconstant +rDX-reg+ 134)
+(defconstant +rBX-reg+ 135)
+(defconstant +rSP-reg+ 136)
+(defconstant +rBP-reg+ 137)
+(defconstant +rSI-reg+ 138)
+(defconstant +rDI-reg+ 139)
+
+(defconstant +indir-dx-reg+ 150)
+
+(defconstant +FLOATCODE+ 1)
+(defconstant +USE-GROUPS+ 2)
+(defconstant +USE-PREFIX-USER-TABLE+ 3)
+(defconstant +X86-64-SPECIAL+ 4)
+(defconstant +UUOCODE+ 5)
+
+(defconstant +REX-MODE64+ 8)
+(defconstant +REX-EXTX+ 4)
+(defconstant +REX-EXTY+ 2)
+(defconstant +REX-EXTZ+ 1)
+
+(defparameter *x86-segment-prefix-alist*
+  `((,+prefix-cs+ . "cs")
+    (,+prefix-ds+ . "ds")
+    (,+prefix-ss+ . "ss")
+    (,+prefix-es+ . "es")
+    (,+prefix-fs+ . "fs")
+    (,+prefix-gs+ . "gs")))
+
+
+(defun segment-register-from-prefixes (ds)
+  (let* ((prefixes (x86-ds-prefixes ds)))
+    (dolist (pair *x86-segment-prefix-alist*)
+      (when (logtest (car pair) prefixes)
+        (setf (x86-ds-used-prefixes ds)
+              (logior (x86-ds-used-prefixes ds)
+                      (car pair)))
+        (return (parse-x86-register-operand (cdr pair) :%))))))
+
+(defun x86-dis-make-reg-operand (r)
+  (x86::make-x86-register-operand
+   :type (logandc2 (x86::reg-entry-reg-type r)
+                   (x86::encode-operand-type :baseIndex))
+   :entry r))
+
+(defun op-st (ds bytemode sizeflag)
+  (declare (ignore ds bytemode sizeflag))
+  (parse-x86-register-operand "st" :%))
+
+(defun op-sti (ds bytemode sizeflag)
+  (declare (ignore bytemode sizeflag))
+  (x86-dis-make-reg-operand (svref x86::*x86-float-regs* (x86-ds-rm ds))))
+
+(defun op-indire (ds bytemode sizeflag)
+  (when (and (x86-ds-mode-64 ds)
+	     (zerop (x86-ds-prefixes ds)))
+    (setf (x86-ds-rex ds) (logior #x48 (x86-ds-rex ds))))
+  (op-e ds bytemode sizeflag))
+
+
+(defun op-e (ds bytemode sizeflag)
+  (let* ((add 0)
+         (riprel nil))
+    (used-rex ds +rex-extz+)
+    (if (logtest (x86-ds-rex ds) +rex-extz+)
+      (setq add 8))
+    (x86-ds-skip ds)                    ;skip MODRM byte
+    (cond ((eql (x86-ds-mod ds) 3)      ; EA is just a register
+           (cond ((eql bytemode +b-mode+)
+                  (used-rex ds 0)
+                  ;; This is wrong: if we don't have an REX prefix,
+                  ;; we should use the old byte register names
+                  ;; (dh, ah, ...) instead of the new ones (bpl, sil ...)
+                  ;; That'll matter if Lisp code ever needs to
+                  ;; access the #xff00 byte, but that seems unlikely
+                  (x86-dis-make-reg-operand (x86::x86-reg8 (+ (x86-ds-rm ds)
+                                                              add))))
+                 ((eql bytemode +w-mode+)
+                  (x86-dis-make-reg-operand (x86::x86-reg16 (+ (x86-ds-rm ds)
+                                                              add))))
+                 ((eql bytemode +d-mode+)
+                  (x86-dis-make-reg-operand (x86::x86-reg32 (+ (x86-ds-rm ds)
+                                                              add))))
+                 ((eql bytemode +q-mode+)
+                  (x86-dis-make-reg-operand (x86::x86-reg64 (+ (x86-ds-rm ds)
+                                                              add))))
+                 ((eql bytemode +m-mode+)
+                  (if (x86-ds-mode-64 ds)
+                    (x86-dis-make-reg-operand (x86::x86-reg64 (+ (x86-ds-rm ds)
+                                                              add)))
+                    (x86-dis-make-reg-operand (x86::x86-reg32 (+ (x86-ds-rm ds)
+                                                              add)))))
+                 ((or (eql bytemode +v-mode+)
+                      (eql bytemode +dq-mode+)
+                      (eql bytemode +dqw-mode+))
+                  (used-rex ds +rex-mode64+)
+                  (used-prefix ds +prefix-data+)
+                  (cond ((logtest (x86-ds-rex ds) +rex-mode64+)
+                         (x86-dis-make-reg-operand (x86::x86-reg64 (+ (x86-ds-rm ds)
+                                                              add))))
+                        ((or (logtest sizeflag +dflag+)
+                             (not (eql bytemode +v-mode+)))
+                         (x86-dis-make-reg-operand (x86::x86-reg32 (+ (x86-ds-rm ds)
+                                                              add))))
+                        (t
+                         (x86-dis-make-reg-operand (x86::x86-reg16 (+ (x86-ds-rm ds)
+                                                              add))))))
+                 ((eql bytemode 0) nil)
+                 (t (error "Disassembly error"))))
+          (t                            ; memory operand
+           (let* ((disp nil)
+                  (base (x86-ds-rm ds))
+                  (index nil)
+                  (scale nil)
+                  (have-base t)
+                  (have-sib nil)
+                  (memop (x86::make-x86-memory-operand)))
+             (setf (x86::x86-memory-operand-seg memop)
+                   (segment-register-from-prefixes ds))
+             (when (= base 4)
+               (setq have-sib t)
+               (let* ((sib (x86-ds-next-u8 ds)))
+                 (setq index (ldb (byte 3 3) sib))
+                 (if (or (x86-ds-mode-64 ds)
+                         (not (eql index 4)))
+                   (setq scale (ldb (byte 2 6) sib)))
+                 (setq base (ldb (byte 3 0) sib))
+                 (used-rex ds +rex-exty+)
+                 (used-rex ds +rex-extz+)
+                 (when (logtest (x86-ds-rex ds) +rex-exty+)
+                   (incf index 8))
+                 (when (logtest  (x86-ds-rex ds) +rex-extz+)
+                   (incf base 8))))
+             (case (x86-ds-mod ds)
+               (0
+                (when (= 5 (logand base 7))
+                  (setq have-base nil)
+                  (if (and (x86-ds-mode-64 ds) (not have-sib))
+                    (setq riprel t))
+                  (setq disp (x86-ds-next-s32 ds))))
+               (1
+                (setq disp (x86-ds-next-s8 ds)))
+               (2
+                (setq disp (x86-ds-next-s32 ds))))
+             (when (or (not (eql (x86-ds-mod ds) 0))
+                       (eql 5 (logand base 7)))
+               (setf (x86::x86-memory-operand-disp memop)
+                     (parse-x86-lap-expression disp))
+               (when riprel
+                 (setf (x86::x86-memory-operand-base memop)
+                       (parse-x86-register-operand "rip" :%))))
+             (when (or have-base
+                       (and have-sib
+                            (or (not (eql index 4))
+                                (not (eql scale 0)))))
+               (used-rex ds +rex-extz+)
+               (if (and (not have-sib)
+                        (logtest (x86-ds-rex ds) +rex-extz+))
+                 (incf base 8))
+               (if have-base
+                 (setf (x86::x86-memory-operand-base memop)
+                       (if (and (x86-ds-mode-64 ds)
+                                (logtest sizeflag +aflag+))
+                         (x86-dis-make-reg-operand (x86::x86-reg64 base))
+                         (x86-dis-make-reg-operand (x86::x86-reg32 base)))))
+               (when have-sib
+                 (unless (= index 4)
+                   (setf (x86::x86-memory-operand-index memop)
+                    (if (and (x86-ds-mode-64 ds)
+                             (logtest sizeflag +aflag+))
+                      (x86-dis-make-reg-operand (x86::x86-reg64 index))
+                      (x86-dis-make-reg-operand (x86::x86-reg32 index)))))
+                 (unless scale
+                   (setq scale 0))
+                 (when (or (not (eql scale 0))
+                           (not (eql index 4)))
+                   (setf (x86::x86-memory-operand-scale memop) scale))))
+             memop)))))
+
+
+(defun op-g (ds bytemode sizeflag)
+  (let* ((add 0)
+         (reg (x86-ds-reg ds)))
+    (used-rex ds +rex-extx+)
+    (if (logtest (x86-ds-rex ds) +rex-extx+)
+      (setq add 8))
+    (cond ((eql bytemode +b-mode+)
+           (used-rex ds 0)
+           ;; This is wrong: if we don't have an REX prefix,
+           ;; we should use the old byte register names
+           ;; (dh, ah, ...) instead of the new ones (bpl, sil ...)
+           ;; That'll matter if Lisp code ever needs to
+           ;; access the #xff00 byte, but that seems unlikely
+           (x86-dis-make-reg-operand (x86::x86-reg8 (+ reg add))))
+          ((eql bytemode +w-mode+)
+           (x86-dis-make-reg-operand (x86::x86-reg16 (+ reg add))))
+          ((eql bytemode +d-mode+)
+           (x86-dis-make-reg-operand (x86::x86-reg32 (+ reg add))))
+          ((eql bytemode +q-mode+)
+           (x86-dis-make-reg-operand (x86::x86-reg64 (+ reg add))))
+          ((eql bytemode +m-mode+)
+           (if (x86-ds-mode-64 ds)
+             (x86-dis-make-reg-operand (x86::x86-reg64 (+ reg add)))
+             (x86-dis-make-reg-operand (x86::x86-reg32 (+ reg add)))))
+          ((or (eql bytemode +v-mode+)
+               (eql bytemode +dq-mode+)
+               (eql bytemode +dqw-mode+))
+           (used-rex ds +rex-mode64+)
+           (used-prefix ds +prefix-data+)
+           (cond ((logtest (x86-ds-rex ds) +rex-mode64+)
+                  (x86-dis-make-reg-operand (x86::x86-reg64 (+ reg add))))
+                 ((or (logtest sizeflag +dflag+)
+                      (not (eql bytemode +v-mode+)))
+                  (x86-dis-make-reg-operand (x86::x86-reg32 (+ reg add))))
+                 (t
+                  (x86-dis-make-reg-operand (x86::x86-reg16 (+ reg add))))))
+          ((eql bytemode 0) nil)
+          (t (error "Disassembly error")))))
+
+(defun op-reg (ds code sizeflag)
+  (declare (fixnum code))
+  (let* ((add 0))
+    (used-rex ds +rex-extz+)
+    (if (logtest (x86-ds-rex ds) +rex-extz+)
+      (setq add 8))
+    (cond ((= code +indir-dx-reg+)
+           (x86::make-x86-memory-operand
+            :base (parse-x86-register-operand "dx" :%)))
+          (t
+           (let* ((r (cond ((and (>= code +ax-reg+)
+                                 (<= code +di-reg+))
+                            (x86::x86-reg16 (+ (- code +ax-reg+) add)))
+                           ((= code +es-reg+) (lookup-x86-register "es" :%))
+                           ((= code +cs-reg+) (lookup-x86-register "cs" :%))
+                           ((= code +ds-reg+) (lookup-x86-register "ds" :%))
+                           ((= code +ss-reg+) (lookup-x86-register "ss" :%))
+                           ((= code +fs-reg+) (lookup-x86-register "fs" :%))
+                           ((= code +gs-reg+) (lookup-x86-register "gs" :%))
+                           ((and (>= code +al-reg+)
+                                 (<= code +dh-reg+))
+                            ;; Again, this is wrong if there's no REX
+                            ;; prefix.
+                            (used-rex ds 0)
+                            (x86::x86-reg8 (+ add (- code +al-reg+))))
+                           ((and (>= code +rax-reg+)
+                                 (<= code +rdi-reg+)
+                                 (or (x86-ds-mode-64 ds)
+                                     (progn
+                                       (setq code (+ code (- +eax-reg+ +rax-reg+)))
+                                       nil)))
+                            (x86::x86-reg64 (+ add (- code +rax-reg+))))
+                           ((and (>= code +eax-reg+)
+                                 (<= code +edi-reg+))
+                            (used-rex ds +rex-mode64+)
+                            (used-prefix ds +prefix-data+)
+                            (if (logtest (x86-ds-rex ds) +rex-mode64+)
+                              (x86::x86-reg64 (+ add (- code +eax-reg+)))
+                              (if (logtest sizeflag +dflag+)
+                                (x86::x86-reg32 (+ add (- code +eax-reg+)))
+                                (x86::x86-reg16 (+ add (- code +eax-reg+))))))
+                           ((and (>= code +al-reg+)
+                                 (<= code +bh-reg+))
+                            (x86::x86-reg8 (+ add (- code +al-reg+))))
+                           (t (error "Disassembly error: code = ~s" code)))))
+             (x86-dis-make-reg-operand r))))))
+
+;;; Like OP-REG, but doesn't deal with extended 64-bit registers.
+(defun op-imreg (ds code sizeflag)
+  (declare (fixnum code))
+  (cond ((= code +indir-dx-reg+)
+         (x86::make-x86-memory-operand
+          :base (parse-x86-register-operand "dx" :%)))
+        (t
+         (let* ((r (cond ((and (>= code +ax-reg+)
+                               (<= code +di-reg+))
+                          (x86::x86-reg16 (- code +ax-reg+)))
+                         ((= code +es-reg+) (lookup-x86-register "es" :%))
+                         ((= code +cs-reg+) (lookup-x86-register "cs" :%))
+                         ((= code +ds-reg+) (lookup-x86-register "ds" :%))
+                         ((= code +ss-reg+) (lookup-x86-register "ss" :%))
+                         ((= code +fs-reg+) (lookup-x86-register "fs" :%))
+                         ((= code +gs-reg+) (lookup-x86-register "gs" :%))
+                         ((and (>= code +al-reg+)
+                               (<= code +dh-reg+))
+                          ;; Again, this is wrong if there's no REX
+                          ;; prefix.
+                          (used-rex ds 0)
+                          (x86::x86-reg8 (- code +al-reg+)))
+
+                         ((and (>= code +eax-reg+)
+                                 (<= code +edi-reg+))
+                          (used-rex ds +rex-mode64+)
+                          (used-prefix ds +prefix-data+)
+                          (if (logtest (x86-ds-rex ds) +rex-mode64+)
+                            (x86::x86-reg64 (- code +eax-reg+))
+                            (if (logtest sizeflag +dflag+)
+                              (x86::x86-reg32 (- code +eax-reg+))
+                              (x86::x86-reg16 (- code +eax-reg+)))))
+                         (t (error "Disassembly error")))))
+           (x86-dis-make-reg-operand r)))))
+
+;;; A (possibly unsigned) immediate.
+(defun op-i (ds bytemode sizeflag)
+  (let* ((mask -1)
+         (op (cond ((= bytemode +b-mode+)
+                    (setq mask #xff)
+                    (x86-ds-next-u8 ds))
+                   ((and (= bytemode +q-mode+)
+                         (x86-ds-mode-64 ds))
+                    (x86-ds-next-s32 ds))
+                   ((or (= bytemode +q-mode+)
+                        (= bytemode +v-mode+))
+                    (used-rex ds +rex-mode64+)
+                    (used-prefix ds +prefix-data+)
+                    (if (logtest (x86-ds-rex ds) +rex-mode64+)
+                      (x86-ds-next-s32 ds)
+                      (if (logtest sizeflag +dflag+)
+                        (progn
+                          (setq mask #xffffffff)
+                          (x86-ds-next-u32 ds))
+                        (progn
+                          (setq mask #xfffff)
+                          (x86-ds-next-u16 ds)))))
+                   ((= bytemode +w-mode+)
+                    (setq mask #xfffff)
+                    (x86-ds-next-u16 ds))
+                   ((= bytemode +const-1-mode+)
+                    nil))))
+    (when op
+      (setq op (logand op mask))
+      (x86::make-x86-immediate-operand :value (parse-x86-lap-expression op)))))
+
+(defun op-i64 (ds bytemode sizeflag)
+  (if (not (x86-ds-mode-64 ds))
+    (op-i ds bytemode sizeflag)
+    (let* ((op (cond ((= bytemode +b-mode+)
+                      (x86-ds-next-u8 ds))
+                     ((= bytemode +v-mode+)
+                      (used-rex ds +rex-mode64+)
+                      (used-prefix ds +prefix-data+)
+                      (if (logtest (x86-ds-rex ds) +rex-mode64+)
+                        (x86-ds-next-u64 ds)
+                        (if (logtest sizeflag +dflag+)
+                          (x86-ds-next-u32 ds)
+                          (x86-ds-next-u16 ds))))
+                     ((= bytemode +w-mode+)
+                      (x86-ds-next-u16 ds))
+                     (t (error "Disassembly error")))))
+      (when op
+        (x86::make-x86-immediate-operand :value (parse-x86-lap-expression op))))))
+
+(defun op-si (ds bytemode sizeflag)
+  (let* ((op
+          (cond ((= bytemode +b-mode+)
+                 (x86-ds-next-s8 ds))
+                ((= bytemode +v-mode+)
+                 (used-rex ds +rex-mode64+)
+                 (used-prefix ds +prefix-data+)
+                 (if (logtest (x86-ds-rex ds) +rex-mode64+)
+                   (x86-ds-next-s32 ds)
+                   (if (logtest sizeflag +dflag+)
+                     (x86-ds-next-s32 ds)
+                     (x86-ds-next-s16 ds))))
+                ((= bytemode +w-mode+)
+                 (x86-ds-next-s16 ds))
+                (t (error "Disassembly error")))))
+    (x86::make-x86-immediate-operand :value (parse-x86-lap-expression op))))
+
+(defun op-j (ds bytemode sizeflag)
+  (let* ((mask -1)
+         (disp (cond ((= bytemode +b-mode+)
+                      (x86-ds-next-s8 ds))
+                     ((= bytemode +v-mode+)
+                      (if (logtest sizeflag +dflag+)
+                        (x86-ds-next-s32 ds)
+                        (progn
+                          (setq mask #xffff)
+                          (x86-ds-next-u16 ds))))
+                     (t (error "Disassembly error"))))
+         (label-address (logand (+ (x86-ds-code-pointer ds) disp)
+                                mask)))
+    (push label-address (x86-ds-pending-labels ds))
+    (x86::make-x86-label-operand :label label-address)))
+
+(defun op-seg (ds x y)
+  (declare (ignore x y))
+  (x86-dis-make-reg-operand (x86::x86-segment-register (x86-ds-reg ds))))
+
+(defun op-dir (ds x sizeflag)
+  (declare (ignore x))
+  (let* ((offset (if (logtest sizeflag +dflag+)
+                   (x86-ds-next-u32 ds)
+                   (x86-ds-next-u16 ds)))
+         (seg (x86-ds-next-u16 ds)))
+    (list (x86::make-x86-immediate-operand :value (parse-x86-lap-expression seg))
+          (x86::make-x86-memory-operand :disp (parse-x86-lap-expression offset)))))
+
+(defun op-off (ds x sizeflag)
+  (declare (ignore x))
+  (x86::make-x86-memory-operand
+   :seg (segment-register-from-prefixes ds)
+   :disp (parse-x86-lap-expression (cond ((or (x86-ds-mode-64 ds)
+                                              (logtest sizeflag +aflag+))
+                                          (x86-ds-next-u32 ds))
+                                         (t (x86-ds-next-u16 ds))))))
+
+
+(defun op-off64 (ds bytemode sizeflag)
+  (if (not (x86-ds-mode-64 ds))
+    (op-off ds bytemode sizeflag)
+    (x86::make-x86-memory-operand
+     :seg (segment-register-from-prefixes ds)
+     :disp (parse-x86-lap-expression (x86-ds-next-u64 ds)))))
+       
+
+(defun %ptr-reg (ds code sizeflag)
+  (used-prefix ds +prefix-addr+)
+  (let* ((idx (- code +eax-reg+))
+         (r (if (x86-ds-mode-64 ds)
+              (if (not (logtest sizeflag +aflag+))
+                (x86::x86-reg32 idx)
+                (x86::x86-reg64 idx))
+              (if (logtest sizeflag +aflag+)
+                (x86::x86-reg32 idx)
+                (x86::x86-reg16 idx)))))
+    (x86-dis-make-reg-operand r)))
+
+(defun op-esreg (ds code sizeflag)
+  (x86::make-x86-memory-operand
+   :seg (parse-x86-register-operand "es" :%)
+   :base (%ptr-reg ds code sizeflag)))
+     
+(defun op-dsreg (ds code sizeflag)
+  (unless (logtest (x86-ds-prefixes ds)
+                   (logior +prefix-cs+
+                           +prefix-ds+
+                           +prefix-ss+
+                           +prefix-es+
+                           +prefix-fs+
+                           +prefix-gs+))
+    (setf (x86-ds-prefixes ds)
+          (logior (x86-ds-prefixes ds) +prefix-ds+)))
+  (x86::make-x86-memory-operand
+   :seg (segment-register-from-prefixes ds)
+   :base (%ptr-reg ds code sizeflag)))
+
+;;; Control-register reference.
+(defun op-c (ds x sizeflag)
+  (declare (ignore x sizeflag))
+  (let* ((add (cond ((logtest (x86-ds-rex ds) +rex-extx+)
+                     (used-rex ds +rex-extx+)
+                     8)
+                    ((and (not (x86-ds-mode-64 ds))
+                          (logtest (x86-ds-prefixes ds) +prefix-lock+))
+                     (setf (x86-ds-used-prefixes ds)
+                           (logior (x86-ds-used-prefixes ds) +prefix-lock+))
+                     8)
+                    (t 0)))
+         (regname (format nil "cr~d" (+ (x86-ds-reg ds) add))))
+    (parse-x86-register-operand regname :%)))
+  
+;;; Debug-register reference.
+(defun op-d (ds x sizeflag)
+  (declare (ignore x sizeflag))
+  (used-rex ds +rex-extx+)
+  (let* ((add (if (logtest (x86-ds-rex ds) +rex-extx+)
+                8
+                0))
+         (regname (format nil "db~d" (+ (x86-ds-reg ds) add))))
+    (parse-x86-register-operand regname :%)))
+
+;;; Test-register.  There are only 8 of them, even on x86-64.
+(defun op-t (ds x y)
+  (declare (ignore x y))
+  (parse-x86-register-operand (format nil "tr~d" (x86-ds-reg ds)) :%))
+
+(defun op-rd (ds bytemode sizeflag)
+  (if (= (x86-ds-mod ds) 3)
+    (op-e ds bytemode sizeflag)
+    (badop ds)))
+
+
+;;; A data prefix causes a reference to an xmm register instead of
+;;; the (default) case of referencing an mmx register.
+(defun op-mmx (ds x sizeflag)
+  (declare (ignore x sizeflag))
+  (let* ((prefixes (x86-ds-prefixes ds)))
+    (used-prefix ds +prefix-data+)
+    (if (logtest prefixes +prefix-data+)
+      (let* ((add (progn (used-rex ds +rex-extx+)
+                         (if (logtest (x86-ds-rex ds) +rex-extx+)
+                           8
+                           0))))
+        (x86-dis-make-reg-operand (x86::x86-xmm-register (+ (x86-ds-reg ds) add))))
+      (x86-dis-make-reg-operand (x86::x86-mmx-register (x86-ds-reg ds))))))
+
+
+(defun op-xmm (ds bytemode sizeflag)
+  (declare (ignore bytemode sizeflag))
+  (used-rex ds +rex-extx+)
+  (let* ((add (if (logtest (x86-ds-rex ds) +rex-extx+) 8 0)))
+    (x86-dis-make-reg-operand (x86::x86-xmm-register (+ (x86-ds-reg ds) add)))))
+
+(defun op-em (ds bytemode sizeflag)
+  (if (not (eql (x86-ds-mod ds) 3))
+    (op-e ds bytemode sizeflag)
+    (let* ((prefixes (x86-ds-prefixes ds)))
+      (x86-ds-skip ds)                  ; skip modrm
+      (used-prefix ds +prefix-data+)
+      (cond ((logtest prefixes +prefix-data+)
+             (used-rex ds +rex-extz+)
+             (let* ((add (if (logtest (x86-ds-rex ds) +rex-extz+)
+                           8
+                           0)))
+               (x86-dis-make-reg-operand
+                (x86::x86-xmm-register (+ (x86-ds-rm ds) add)))))
+            (t
+             (x86-dis-make-reg-operand
+              (x86::x86-mmx-register (x86-ds-rm ds))))))))
+
+(defun op-ex (ds bytemode sizeflag)
+  (if (not (eql (x86-ds-mod ds) 3))
+    (op-e ds bytemode sizeflag)
+    (let* ((add (if (logtest (x86-ds-rex ds) +rex-extz+) 8 0)))
+      (used-rex ds +rex-extz+)
+      (x86-ds-skip ds)                  ; skip modrm
+      (x86-dis-make-reg-operand (x86::x86-xmm-register (+ (x86-ds-rm ds) add))))))
+           
+(defun op-ms (ds bytemode sizeflag)
+  (if (eql (x86-ds-mod ds) 3)
+    (op-em ds bytemode sizeflag)
+    (badop ds)))
+
+(defun op-xs (ds bytemode sizeflag)
+  (if (eql (x86-ds-mod ds) 3)
+    (op-ex ds bytemode sizeflag)
+    (badop ds)))
+
+(defun op-m (ds bytemode sizeflag)
+  (if (eql (x86-ds-mod ds) 3)
+    (badop ds)
+    (op-e ds bytemode sizeflag)))
+
+(defun op-0f07 (ds bytemode sizeflag)
+  (if (or (not (eql (x86-ds-mod ds) 3))
+          (not (eql (x86-ds-rm ds) 0)))
+    (badop ds)
+    (op-e ds bytemode sizeflag)))
+
+(defun nop-fixup (ds bytemode sizeflag)
+  (declare (ignore bytemode sizeflag)
+           (ignorable ds))
+  #+nothing
+  (if (logtest (x86-ds-prefixes ds) +prefix-repz+)
+    (break "should be PAUSE")))
+
+;;;             
+
+(defun make-x86-dis (opstring &optional
+                             op1-fun
+                             (op1-byte 0)
+                             op2-fun
+                             (op2-byte 0)
+                             op3-fun
+                             (op3-byte 0))
+  (let* ((flags nil))
+    (if (consp opstring)
+      (setq flags (cdr opstring) opstring (car opstring)))
+    (%make-x86-dis :mnemonic opstring
+                   :flags flags
+                   :op1 op1-fun
+                   :bytemode1 op1-byte
+                   :op2 op2-fun
+                   :bytemode2 op2-byte
+                   :op3 op3-fun
+                   :bytemode3 op3-byte)))
+                         
+
+;;; The root of all evil, unless the first byte of the opcode
+;;; is #xf
+(defparameter *disx86*
+  (vector
+   ;; #x00
+   (make-x86-dis "addB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "addS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "addB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "addS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "addB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "addS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis '(("pushT" . "(bad)")) 'op-reg +es-reg+)
+   (make-x86-dis '(("popT" . "(bad)")) 'op-reg +es-reg+)
+   ;; #x08
+   (make-x86-dis "orB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "orS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "orB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "orS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "orB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "orS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis '(("pushT" . "(bad)")) 'op-reg +cs-reg+)
+   (make-x86-dis "(bad)")               ; #x0f extended opcode escape
+   ;; #x10
+   (make-x86-dis "adcB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "adcS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "adcB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "adcS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "adcB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "adcS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis '(("pushT" . "(bad)")) 'op-reg +ss-reg+)
+   (make-x86-dis '(("popT" . "(bad)")) 'op-reg +ss-reg+)
+   ;; #x18
+   (make-x86-dis "sbbB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "sbbS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "sbbB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "sbbS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "sbbB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "sbbS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis '(("pushT" . "(bad)")) 'op-reg +ds-reg+)
+   (make-x86-dis '(("popT" . "(bad)")) 'op-reg +ds-reg+)
+   ;; #x20
+   (make-x86-dis "andB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "andS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "andB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "andS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "andB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "andS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis "(bad)")               ; SEG ES prefix
+   (make-x86-dis '(("daa" . "(bad)")))
+   ;; #x28
+   (make-x86-dis "subB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "subS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "subB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "subS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "subB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "subS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis "(bad)")               ; SEG CS prefix
+   (make-x86-dis '(("das" . "(bad)")))
+   ;; #x30
+   (make-x86-dis "xorB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "xorS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "xorB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "xorS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "xorB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "xorS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis "(bad)")               ; SEG SS prefix
+   (make-x86-dis '(("aaa" . "(bad)")))
+   ;; #x38
+   (make-x86-dis "cmpB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "cmpS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "cmpB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "cmpS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmpB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "cmpS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis "(bad)")               ; SEG DS prefix
+   (make-x86-dis '(("aas" . "(bad)")))
+   ;; #x40
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +eax-reg+)
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +ecx-reg+)
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +edx-reg+)
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +ebx-reg+)
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +esp-reg+)
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +ebp-reg+)
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +esi-reg+)
+   (make-x86-dis '(("incS" . "(bad)")) 'op-reg +edi-reg+)
+   ;; #x48
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +eax-reg+)
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +ecx-reg+)
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +edx-reg+)
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +ebx-reg+)
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +esp-reg+)
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +ebp-reg+)
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +esi-reg+)
+   (make-x86-dis '(("decS" . "(bad)")) 'op-reg +edi-reg+)
+   ;; #x50
+   (make-x86-dis "pushT" 'op-reg +rax-reg+)
+   (make-x86-dis "pushT" 'op-reg +rcx-reg+)
+   (make-x86-dis "pushT" 'op-reg +rdx-reg+)
+   (make-x86-dis "pushT" 'op-reg +rbx-reg+)
+   (make-x86-dis "pushT" 'op-reg +rsp-reg+)
+   (make-x86-dis "pushT" 'op-reg +rbp-reg+)
+   (make-x86-dis "pushT" 'op-reg +rsi-reg+)
+   (make-x86-dis "pushT" 'op-reg +rdi-reg+)
+   ;; #x58
+   (make-x86-dis "popT" 'op-reg +rax-reg+)
+   (make-x86-dis "popT" 'op-reg +rcx-reg+)
+   (make-x86-dis "popT" 'op-reg +rdx-reg+)
+   (make-x86-dis "popT" 'op-reg +rbx-reg+)
+   (make-x86-dis "popT" 'op-reg +rsp-reg+)
+   (make-x86-dis "popT" 'op-reg +rbp-reg+)
+   (make-x86-dis "popT" 'op-reg +rsi-reg+)
+   (make-x86-dis "popT" 'op-reg +rdi-reg+)
+   ;; #x60
+   (make-x86-dis '(("pushaP" . "(bad)")))
+   (make-x86-dis '(("popaP" . "(bad)")))
+   (make-x86-dis '(("boundS" . "(bad)")) 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis nil nil +x86-64-special+)
+   (make-x86-dis "(bad)")               ; seg fs
+   (make-x86-dis "(bad)")               ; seg gs
+   (make-x86-dis "(bad)")               ; op size prefix
+   (make-x86-dis "(bad)")               ; adr size prefix
+   ;; #x68
+   (make-x86-dis "pushT" 'op-i +q-mode+)
+   (make-x86-dis "imulS" 'op-g +v-mode+ 'op-e +v-mode+ 'op-i +v-mode+ )
+   (make-x86-dis "pushT" 'op-si +b-mode+)
+   (make-x86-dis "imulS" 'op-g +v-mode+ 'op-e +v-mode+ 'op-si +b-mode+ )
+   (make-x86-dis "insb" 'op-dsreg +esi-reg+ 'op-imreg +indir-dx-reg+)
+   (make-x86-dis "insR" 'op-esreg +edi-reg+ 'op-imreg +indir-dx-reg+)
+   (make-x86-dis "outsb" 'op-imreg +indir-dx-reg+ 'op-dsreg +esi-reg+)
+   (make-x86-dis "outsR" 'op-imreg +indir-dx-reg+ 'op-dsreg +esi-reg+)
+   ;; #x70
+   (make-x86-dis "joH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jnoH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jbH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jaeH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jeH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jneH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jbeH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jaH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   ;; #x78
+   (make-x86-dis "jsH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jnsH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jpH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jnpH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jlH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jgeH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jleH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   (make-x86-dis "jgH" 'op-j +b-mode+ nil +cond-jump-mode+ )
+   ;; #x80
+   (make-x86-dis nil nil +use-groups+ nil 0)
+   (make-x86-dis nil nil +use-groups+ nil 1)
+   (make-x86-dis "(bad)")
+   (make-x86-dis nil nil +use-groups+ nil 2 )
+   (make-x86-dis "testB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "testS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "xchgB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "xchgS" 'op-e +v-mode+ 'op-g +v-mode+)
+   ;; #x88
+   (make-x86-dis "movB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "movS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "movB" 'op-g +b-mode+ 'op-e +b-mode+)
+   (make-x86-dis "movS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "movQ" 'op-e +v-mode+ 'op-seg +w-mode+)
+   (make-x86-dis '("leaS" . :lea) 'op-g +v-mode+ 'op-m 0)
+   (make-x86-dis "movQ" 'op-seg +w-mode+ 'op-e +v-mode+)
+   (make-x86-dis "popU" 'op-e +v-mode+)
+   ;; #x90
+   (make-x86-dis "nop" 'nop-fixup 0)
+   (make-x86-dis "xchgS" 'op-reg +ecx-reg+ 'op-imreg +eax-reg+)
+   (make-x86-dis "xchgS" 'op-reg +edx-reg+ 'op-imreg +eax-reg+)
+   (make-x86-dis "xchgS" 'op-reg +ebx-reg+ 'op-imreg +eax-reg+)
+   (make-x86-dis "xchgS" 'op-reg +esp-reg+ 'op-imreg +eax-reg+)
+   (make-x86-dis "xchgS" 'op-reg +ebp-reg+ 'op-imreg +eax-reg+)
+   (make-x86-dis "xchgS" 'op-reg +esi-reg+ 'op-imreg +eax-reg+)
+   (make-x86-dis "xchgS" 'op-reg +edi-reg+ 'op-imreg +eax-reg+)
+   ;; #x98
+   (make-x86-dis "cWtR")
+   (make-x86-dis "cRtO")
+   (make-x86-dis '(("JcallT" . "(bad)")) 'op-dir 0)
+   (make-x86-dis "(bad)")               ; fwait
+   (make-x86-dis "pushfT")
+   (make-x86-dis "popfT")
+   ;; "sahf" and "lahf" are unimplemented on some Intel EM64T
+   ;; steppings, allegedly because an early AMD64 manual
+   ;; accidentally omitted them.  It makes sense to disassemble
+   ;; them in 64-bit mode, but it may require some thought
+   ;; before using them in compiled code.
+   (make-x86-dis "sahf")
+   (make-x86-dis "lahf")
+   ;; #xa0
+   (make-x86-dis "movB" 'op-imreg +al-reg+ 'op-off64 +b-mode+)
+   (make-x86-dis "movS" 'op-imreg +eax-reg+ 'op-off64 +v-mode+)
+   (make-x86-dis "movB" 'op-off64 +b-mode+  'op-imreg +al-reg+)
+   (make-x86-dis "movS" 'op-off64 +v-mode+ 'op-imreg +eax-reg+)
+   (make-x86-dis "movsb" 'op-dsreg +esi-reg+ 'op-dsreg +esi-reg+)
+   (make-x86-dis "movsR" 'op-esreg +edi-reg+ 'op-dsreg +esi-reg+)
+   (make-x86-dis "cmpsb" 'op-dsreg +esi-reg+ 'op-dsreg +esi-reg+)
+   (make-x86-dis "cmpsR" 'op-dsreg +esi-reg+ 'op-esreg +edi-reg+)
+   ;; #xa8
+   (make-x86-dis "testB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "testS" 'op-imreg +eax-reg+ 'op-i +v-mode+)
+   (make-x86-dis "stosB" 'op-dsreg +esi-reg+ 'op-imreg +al-reg+)
+   (make-x86-dis "stosS" 'op-esreg +edi-reg+ 'op-imreg +eax-reg+)
+   (make-x86-dis "lodsB" 'op-imreg +al-reg+ 'op-dsreg +esi-reg+)
+   (make-x86-dis "lodsS" 'op-imreg +eax-reg+ 'op-dsreg +esi-reg+)
+   (make-x86-dis "scasB" 'op-imreg +al-reg+ 'op-dsreg +esi-reg+)
+   (make-x86-dis "scasS" 'op-imreg +eax-reg+ 'op-esreg +edi-reg+)
+   ;; #xb0
+   (make-x86-dis "movB" 'op-reg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "movB" 'op-reg +cl-reg+ 'op-i +b-mode+)
+   (make-x86-dis "movB" 'op-reg +dl-reg+ 'op-i +b-mode+)
+   (make-x86-dis "movB" 'op-reg +bl-reg+ 'op-i +b-mode+)
+   (make-x86-dis "movB" 'op-reg +ah-reg+ 'op-i +b-mode+)
+   (make-x86-dis "movB" 'op-reg +ch-reg+ 'op-i +b-mode+)
+   (make-x86-dis "movB" 'op-reg +dh-reg+ 'op-i +b-mode+)
+   (make-x86-dis "movB" 'op-reg +bh-reg+ 'op-i +b-mode+)
+   ;; #xb8
+   (make-x86-dis "movS" 'op-reg +eax-reg+ 'op-i64 +v-mode+)
+   (make-x86-dis "movS" 'op-reg +ecx-reg+ 'op-i64 +v-mode+)
+   (make-x86-dis "movS" 'op-reg +edx-reg+ 'op-i64 +v-mode+)
+   (make-x86-dis "movS" 'op-reg +ebx-reg+ 'op-i64 +v-mode+)
+   (make-x86-dis "movS" 'op-reg +esp-reg+ 'op-i64 +v-mode+)
+   (make-x86-dis "movS" 'op-reg +ebp-reg+ 'op-i64 +v-mode+)
+   (make-x86-dis "movS" 'op-reg +esi-reg+ 'op-i64 +v-mode+)
+   (make-x86-dis "movS" 'op-reg +edi-reg+ 'op-i64 +v-mode+)
+   ;; #xc0
+   (make-x86-dis nil nil +use-groups+ nil 3)
+   (make-x86-dis nil nil +use-groups+ nil 4)
+   (make-x86-dis '("retT" . :jump) 'op-i +w-mode+)
+   (make-x86-dis '("retT" . :jump))
+   (make-x86-dis '(("lesS" . "(bad)")) 'op-g +v-mode+ 'op-m +f-mode+)
+   (make-x86-dis "ldsS" 'op-g +v-mode+ 'op-m +f-mode+)
+   (make-x86-dis "movA" 'op-e +b-mode+ 'op-i +b-mode+)
+   (make-x86-dis "movQ" 'op-e +v-mode+ 'op-i +v-mode+)
+   ;; #xc8
+   (make-x86-dis "enterT" 'op-i +w-mode+ 'op-i +b-mode+)
+   (make-x86-dis "leaveT")
+   (make-x86-dis "lretP" 'op-i +w-mode+)
+   (make-x86-dis "lretP")
+   (make-x86-dis "int3")
+   (make-x86-dis nil nil +uuocode+)
+   (make-x86-dis '(("into" . "(bad)")))
+   (make-x86-dis "iretP")
+   ;; #xd0
+   (make-x86-dis nil nil +use-groups+ nil 5)
+   (make-x86-dis nil nil +use-groups+ nil 6)
+   (make-x86-dis nil nil +use-groups+ nil 7)
+   (make-x86-dis nil nil +use-groups+ nil 8)
+   (make-x86-dis '(("aam" . "(bad)")) 'op-si +b-mode+)
+   (make-x86-dis '(("aad" . "(bad)")) 'op-si +b-mode+)
+   (make-x86-dis "(bad)")
+   (make-x86-dis "xlat" 'op-dsreg +ebx-reg+)
+   ;; #xd8
+   (make-x86-dis nil nil +floatcode+)
+   (make-x86-dis nil nil +floatcode+)
+   (make-x86-dis nil nil +floatcode+)
+   (make-x86-dis nil nil +floatcode+)
+   (make-x86-dis nil nil +floatcode+)
+   (make-x86-dis nil nil +floatcode+)
+   (make-x86-dis nil nil +floatcode+)
+   (make-x86-dis nil nil +floatcode+)
+   ;; #xe0
+   (make-x86-dis "loopneFH" 'op-j +b-mode+ nil +loop-jcxz-mode+ )
+   (make-x86-dis "loopeFH" 'op-j +b-mode+ nil +loop-jcxz-mode+ )
+   (make-x86-dis "loopFH" 'op-j +b-mode+ nil +loop-jcxz-mode+ )
+   (make-x86-dis "jEcxzH" 'op-j +b-mode+ nil +loop-jcxz-mode+ )
+   (make-x86-dis "inB" 'op-imreg +al-reg+ 'op-i +b-mode+)
+   (make-x86-dis "inS" 'op-imreg +eax-reg+ 'op-i +b-mode+)
+   (make-x86-dis "outB" 'op-i +b-mode+ 'op-imreg +al-reg+)
+   (make-x86-dis "outS" 'op-i +b-mode+ 'op-imreg +eax-reg+)
+   ;; #xe8
+   (make-x86-dis '("callT" . :call) 'op-j +v-mode+)
+   (make-x86-dis '("jmpT" . :jump) 'op-j +v-mode+)
+   (make-x86-dis '(("JjmpT" . "(bad)") . :jump) 'op-dir 0)
+   (make-x86-dis '("jmp" . :jump)  'op-j +b-mode+)
+   (make-x86-dis "inB" 'op-imreg +al-reg+ 'op-imreg +indir-dx-reg+)
+   (make-x86-dis "inS" 'op-imreg +eax-reg+ 'op-imreg +indir-dx-reg+)
+   (make-x86-dis "outB" 'op-imreg +indir-dx-reg+ 'op-imreg +al-reg+)
+   (make-x86-dis "outS" 'op-imreg +indir-dx-reg+ 'op-imreg +eax-reg+)
+   ;; #xf0
+   (make-x86-dis "(bad)")               ; lock prefix
+   (make-x86-dis "icebp")
+   (make-x86-dis "(bad)")               ; repne
+   (make-x86-dis "(bad)")               ; repz
+   (make-x86-dis "hlt")
+   (make-x86-dis "cmc")
+   (make-x86-dis nil nil +use-groups+ nil 9)
+   (make-x86-dis nil nil +use-groups+ nil 10)
+   ;; #xf8
+   (make-x86-dis "clc")
+   (make-x86-dis "stc")
+   (make-x86-dis "cli")
+   (make-x86-dis "sti")
+   (make-x86-dis "cld")
+   (make-x86-dis "std")
+   (make-x86-dis nil nil +use-groups+ nil 11)
+   (make-x86-dis nil nil +use-groups+ nil 12)
+   ))
+
+(defparameter *disx86-twobyte*
+  (vector
+   ;; #x00
+   (make-x86-dis nil nil +use-groups+ nil 13)
+   (make-x86-dis nil nil +use-groups+ nil 14)
+   (make-x86-dis "larS" 'op-g +v-mode+ 'op-e +w-mode+)
+   (make-x86-dis "lslS" 'op-g +v-mode+ 'op-e +w-mode+)
+   (make-x86-dis "(bad)")
+   (make-x86-dis "syscall")
+   (make-x86-dis "clts")
+   (make-x86-dis "sysretP")
+   ;; #x08
+   (make-x86-dis "invd")
+   (make-x86-dis "wbinvd")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "ud2a" 'op-i +b-mode+)
+   (make-x86-dis "(bad)")
+   (make-x86-dis nil nil +use-groups+ nil 22)
+   (make-x86-dis "femms")
+   (make-x86-dis "" 'op-mmx 0 'op-em +v-mode+ 'op-3dnowsuffix 0) ; See OP-3DNowSuffix.
+   ;; #x10
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 8)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 9)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 30)
+   (make-x86-dis "movlpX" 'op-ex +v-mode+ 'op-xmm 0 'SIMD-Fixup #\h)
+   (make-x86-dis "unpcklpX" 'op-xmm 0 'op-ex +v-mode+)
+   (make-x86-dis "unpckhpX" 'op-xmm 0 'op-ex +v-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 31)
+   (make-x86-dis "movhpX" 'op-ex +v-mode+ 'op-xmm 0 'SIMD-Fixup #\l)
+   ;; #x18
+   (make-x86-dis nil nil +use-groups+ nil 21)
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   ;; #x20
+   (make-x86-dis "movL" 'op-rd +m-mode+ 'op-c +m-mode+)
+   (make-x86-dis "movL" 'op-rd +m-mode+ 'op-d +m-mode+)
+   (make-x86-dis "movL" 'op-c +m-mode+ 'op-rd +m-mode+)
+   (make-x86-dis "movL" 'op-d +m-mode+ 'op-rd +m-mode+)
+   (make-x86-dis "movL" 'op-rd +d-mode+ 'op-t +d-mode+)
+   (make-x86-dis "(bad)")
+   (make-x86-dis "movL" 'op-t +d-mode+ 'op-rd +d-mode+)
+   (make-x86-dis "(bad)")
+   ;; #x28
+   (make-x86-dis "movapX" 'op-xmm 0 'op-ex +v-mode+)
+   (make-x86-dis "movapX" 'op-ex +v-mode+ 'op-xmm 0)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 2)
+   (make-x86-dis "movntpX" 'op-e +v-mode+ 'op-xmm 0)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 4)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 3)
+   (make-x86-dis "ucomisX" 'op-xmm 0 'op-ex +v-mode+)
+   (make-x86-dis "comisX" 'op-xmm 0 'op-ex +v-mode+)
+   ;; #x30
+   (make-x86-dis "wrmsr")
+   (make-x86-dis "rdtsc")
+   (make-x86-dis "rdmsr")
+   (make-x86-dis "rdpmc")
+   (make-x86-dis "sysenter")
+   (make-x86-dis "sysexit")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   ;; #x38
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   ;; #x40
+   (make-x86-dis "cmovoS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovnoS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovbS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovaeS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmoveS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovneS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovbeS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovaS" 'op-g +v-mode+ 'op-e +v-mode+)
+   ;; #x48
+   (make-x86-dis "cmovsS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovnsS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovpS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovnpS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovlS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovgeS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovleS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "cmovgS" 'op-g +v-mode+ 'op-e +v-mode+)
+   ;; #x50
+   (make-x86-dis "movmskpX" 'op-g +dq-mode+ 'op-xs +v-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 13)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 12)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 11)
+   (make-x86-dis "andpX" 'op-xmm 0 'op-ex +v-mode+)
+   (make-x86-dis "andnpX" 'op-xmm 0 'op-ex +v-mode+)
+   (make-x86-dis "orpX" 'op-xmm 0 'op-ex +v-mode+)
+   (make-x86-dis "xorpX" 'op-xmm 0 'op-ex +v-mode+)
+   ;; #x58
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 0)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 10)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 17)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 16)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 14)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 7)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 5)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 6)
+   ;; #x60
+   (make-x86-dis "punpcklbw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "punpcklwd" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "punpckldq" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "packsswb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pcmpgtb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pcmpgtw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pcmpgtd" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "packuswb" 'op-mmx 0 'op-em +v-mode+)
+   ;; #x68
+   (make-x86-dis "punpckhbw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "punpckhwd" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "punpckhdq" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "packssdw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 26)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 24)
+   (make-x86-dis "movd" 'op-mmx 0 'op-e +dq-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 19)
+   ;; #x70
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 22)
+   (make-x86-dis nil nil +use-groups+ nil 17)
+   (make-x86-dis nil nil +use-groups+ nil 18)
+   (make-x86-dis nil nil +use-groups+ nil 19)
+   (make-x86-dis "pcmpeqb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pcmpeqw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pcmpeqd" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "emms")
+   ;; #x78
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis "(bad)")
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 28)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 29)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 23)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 20)
+   ;; #x80
+   (make-x86-dis "joH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jnoH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jbH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jaeH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jeH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jneH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jbeH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jaH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   ;; #x88
+   (make-x86-dis "jsH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jnsH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jpH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jnpH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jlH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jgeH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jleH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   (make-x86-dis "jgH" 'op-j +v-mode+ nil +cond-jump-mode+)
+   ;; #x90
+   (make-x86-dis "seto" 'op-e +b-mode+)
+   (make-x86-dis "setno" 'op-e +b-mode+)
+   (make-x86-dis "setb" 'op-e +b-mode+)
+   (make-x86-dis "setae" 'op-e +b-mode+)
+   (make-x86-dis "sete" 'op-e +b-mode+)
+   (make-x86-dis "setne" 'op-e +b-mode+)
+   (make-x86-dis "setbe" 'op-e +b-mode+)
+   (make-x86-dis "seta" 'op-e +b-mode+)
+   ;; #x98
+   (make-x86-dis "sets" 'op-e +b-mode+)
+   (make-x86-dis "setns" 'op-e +b-mode+)
+   (make-x86-dis "setp" 'op-e +b-mode+)
+   (make-x86-dis "setnp" 'op-e +b-mode+)
+   (make-x86-dis "setl" 'op-e +b-mode+)
+   (make-x86-dis "setge" 'op-e +b-mode+)
+   (make-x86-dis "setle" 'op-e +b-mode+)
+   (make-x86-dis "setg" 'op-e +b-mode+)
+   ;; #xa0
+   (make-x86-dis "pushT" 'op-reg +fs-reg+)
+   (make-x86-dis "popT" 'op-reg +fs-reg+)
+   (make-x86-dis "cpuid")
+   (make-x86-dis "btS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "shldS" 'op-e +v-mode+ 'op-g +v-mode+ 'op-i +b-mode+)
+   (make-x86-dis "shldS" 'op-e +v-mode+ 'op-g +v-mode+ 'op-imreg +cl-reg+)
+   (make-x86-dis nil nil +use-groups+ nil 24)
+   (make-x86-dis nil nil +use-groups+ nil 23)
+   ;; #xa8
+   (make-x86-dis "pushT" 'op-reg +gs-reg+)
+   (make-x86-dis "popT" 'op-reg +gs-reg+)
+   (make-x86-dis "rsm")
+   (make-x86-dis "btsS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "shrdS" 'op-e +v-mode+ 'op-g +v-mode+ 'op-i +b-mode+)
+   (make-x86-dis "shrdS" 'op-e +v-mode+ 'op-g +v-mode+ 'op-imreg +cl-reg+)
+   (make-x86-dis nil nil +use-groups+ nil 20)
+   (make-x86-dis "imulS" 'op-g +v-mode+ 'op-e +v-mode+)
+   ;; #xb0
+   (make-x86-dis "cmpxchgB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "cmpxchgS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "lssS" 'op-g +v-mode+ 'op-m +f-mode+)
+   (make-x86-dis "btrS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "lfsS" 'op-g +v-mode+ 'op-m +f-mode+)
+   (make-x86-dis "lgsS" 'op-g +v-mode+ 'op-m +f-mode+)
+   (make-x86-dis "movzbR" 'op-g +v-mode+ 'op-e +b-mode+)
+   (make-x86-dis "movzwR" 'op-g +v-mode+ 'op-e +w-mode+) ; yes there really is movzww !
+   ;; #xb8
+   (make-x86-dis "(bad)")
+   (make-x86-dis "ud2b")
+   (make-x86-dis nil nil +use-groups+ nil 15)
+   (make-x86-dis "btcS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "bsfS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "bsrS" 'op-g +v-mode+ 'op-e +v-mode+)
+   (make-x86-dis "movsbR" 'op-g +v-mode+ 'op-e +b-mode+)
+   (make-x86-dis "movswR" 'op-g +v-mode+ 'op-e +w-mode+) ; yes there really is movsww !
+   ;; #xc0
+   (make-x86-dis "xaddB" 'op-e +b-mode+ 'op-g +b-mode+)
+   (make-x86-dis "xaddS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 1)
+   (make-x86-dis "movntiS" 'op-e +v-mode+ 'op-g +v-mode+)
+   (make-x86-dis "pinsrw" 'op-mmx 0 'op-e +dqw-mode+ 'op-i +b-mode+)
+   (make-x86-dis "pextrw" 'op-g +dq-mode+ 'op-ms +v-mode+ 'op-i +b-mode+)
+   (make-x86-dis "shufpX" 'op-xmm 0 'op-ex +v-mode+ 'op-i +b-mode+)
+   (make-x86-dis nil nil +use-groups+ nil 16)
+   ;; #xc8
+   (make-x86-dis "bswap" 'op-reg +eax-reg+)
+   (make-x86-dis "bswap" 'op-reg +ecx-reg+)
+   (make-x86-dis "bswap" 'op-reg +edx-reg+)
+   (make-x86-dis "bswap" 'op-reg +ebx-reg+)
+   (make-x86-dis "bswap" 'op-reg +esp-reg+)
+   (make-x86-dis "bswap" 'op-reg +ebp-reg+)
+   (make-x86-dis "bswap" 'op-reg +esi-reg+)
+   (make-x86-dis "bswap" 'op-reg +edi-reg+)
+   ;; #xd0
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 27)
+   (make-x86-dis "psrlw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psrld" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psrlq" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddq" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pmullw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 21)
+   (make-x86-dis "pmovmskb" 'op-g +dq-mode+ 'op-ms +v-mode+)
+   ;; #xd8
+   (make-x86-dis "psubusb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psubusw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pminub" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pand" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddusb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddusw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pmaxub" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pandn" 'op-mmx 0 'op-em +v-mode+)
+   ;; #xe0
+   (make-x86-dis "pavgb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psraw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psrad" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pavgw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pmulhuw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pmulhw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 15)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 25)
+   ;; #xe8
+   (make-x86-dis "psubsb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psubsw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pminsw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "por" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddsb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddsw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pmaxsw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pxor" 'op-mmx 0 'op-em +v-mode+)
+   ;; #xf0
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 32)
+   (make-x86-dis "psllw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pslld" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psllq" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pmuludq" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "pmaddwd" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psadbw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis nil nil +use-prefix-user-table+ nil 18)
+   ;; #xf8
+   (make-x86-dis "psubb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psubw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psubd" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "psubq" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddb" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddw" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "paddd" 'op-mmx 0 'op-em +v-mode+)
+   (make-x86-dis "(bad)")
+   ))
+
+(defparameter *onebyte-has-modrm*
+  (make-array 256 :element-type 'bit
+              :initial-contents '(
+  #|       0 1 2 3 4 5 6 7 8 9 a b c d e f        |#
+  #|       -------------------------------        |#
+  #| 00 |# 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0  #| 00 |#
+  #| 10 |# 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0  #| 10 |#
+  #| 20 |# 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0  #| 20 |#
+  #| 30 |# 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0  #| 30 |#
+  #| 40 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 40 |#
+  #| 50 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 50 |#
+  #| 60 |# 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0  #| 60 |#
+  #| 70 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 70 |#
+  #| 80 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  #| 80 |#
+  #| 90 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 90 |#
+  #| a0 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| a0 |#
+  #| b0 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| b0 |#
+  #| c0 |# 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0  #| c0 |#
+  #| d0 |# 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1  #| d0 |#
+  #| e0 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| e0 |#
+  #| f0 |# 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1  #| f0 |#
+  #|       -------------------------------        |#
+  #|       0 1 2 3 4 5 6 7 8 9 a b c d e f        |#
+)))
+
+
+(defparameter *twobyte-has-modrm*
+  (make-array 256 :element-type 'bit
+              :initial-contents '(
+  #|       0 1 2 3 4 5 6 7 8 9 a b c d e f        |#
+  #|       -------------------------------        |#
+  #| 00 |# 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1  #| 0f |#
+  #| 10 |# 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0  #| 1f |#
+  #| 20 |# 1 1 1 1 1 0 1 0 1 1 1 1 1 1 1 1  #| 2f |#
+  #| 30 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 3f |#
+  #| 40 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  #| 4f |#
+  #| 50 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  #| 5f |#
+  #| 60 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  #| 6f |#
+  #| 70 |# 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1  #| 7f |#
+  #| 80 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 8f |#
+  #| 90 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  #| 9f |#
+  #| a0 |# 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1  #| af |#
+  #| b0 |# 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1  #| bf |#
+  #| c0 |# 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0  #| cf |#
+  #| d0 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  #| df |#
+  #| e0 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  #| ef |#
+  #| f0 |# 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0  #| ff |#
+  #|       -------------------------------        |#
+  #|       0 1 2 3 4 5 6 7 8 9 a b c d e f        |#
+)))
+
+(defparameter *twobyte-uses-sse-prefix*
+  (make-array 256 :element-type 'bit
+              :initial-contents '(
+  #|       0 1 2 3 4 5 6 7 8 9 a b c d e f        |#
+  #|       -------------------------------        |#
+  #| 00 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 0f |#
+  #| 10 |# 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0  #| 1f |#
+  #| 20 |# 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0  #| 2f |#
+  #| 30 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 3f |#
+  #| 40 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 4f |#
+  #| 50 |# 0 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1  #| 5f |#
+  #| 60 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1  #| 6f |#
+  #| 70 |# 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1  #| 7f |#
+  #| 80 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 8f |#
+  #| 90 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| 9f |#
+  #| a0 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| af |#
+  #| b0 |# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  #| bf |#
+  #| c0 |# 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0  #| cf |#
+  #| d0 |# 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0  #| df |#
+  #| e0 |# 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0  #| ef |#
+  #| f0 |# 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0  #| ff |#
+  #|       -------------------------------        |#
+  #|       0 1 2 3 4 5 6 7 8 9 a b c d e f        |#
+)))
+
+
+
+(defparameter *grps*
+  (vector
+   ;; GRP1b
+   (vector
+    (make-x86-dis "addA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "orA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "adcA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "sbbA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "andA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "subA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "xorA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "cmpA" 'op-e +b-mode+ 'op-i +b-mode+))
+   ;; GRP1S
+   (vector
+    (make-x86-dis '("addQ" . :addi32) 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis "orQ" 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis "adcQ" 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis "sbbQ" 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis "andQ" 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis '("subQ" . :subi32) 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis "xorQ" 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis "cmpQ" 'op-e +v-mode+ 'op-i +v-mode+))
+   ;; GRP1Ss
+   (vector
+    (make-x86-dis '("addQ" . :addi64) 'op-e +v-mode+ 'op-si +b-mode+)
+    (make-x86-dis "orQ" 'op-e +v-mode+ 'op-si +b-mode+)
+    (make-x86-dis "adcQ" 'op-e +v-mode+ 'op-si +b-mode+)
+    (make-x86-dis "sbbQ" 'op-e +v-mode+ 'op-si +b-mode+)
+    (make-x86-dis "andQ" 'op-e +v-mode+ 'op-si +b-mode+)
+    (make-x86-dis '("subQ" . :subi64) 'op-e +v-mode+ 'op-si +b-mode+)
+    (make-x86-dis "xorQ" 'op-e +v-mode+ 'op-si +b-mode+)
+    (make-x86-dis "cmpQ" 'op-e +v-mode+ 'op-si +b-mode+))
+   ;; GRP2b
+   (vector
+    (make-x86-dis "rolA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "rorA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "rclA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "rcrA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "shlA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "shrA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "sarA" 'op-e +b-mode+ 'op-i +b-mode+))
+   ;; GRP2S
+   (vector
+    (make-x86-dis "rolQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "rorQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "rclQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "rcrQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "shlQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "shrQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "sarQ" 'op-e +v-mode+ 'op-i +b-mode+))
+   ;; GRP2b-one
+   (vector
+    (make-x86-dis "rolA" 'op-e +b-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "rorA" 'op-e +b-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "rclA" 'op-e +b-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "rcrA" 'op-e +b-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "shlA" 'op-e +b-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "shrA" 'op-e +b-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "sarA" 'op-e +b-mode+ 'op-i +const-1-mode+))
+   ;; GRP2S-one
+   (vector
+    (make-x86-dis "rolQ" 'op-e +v-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "rorQ" 'op-e +v-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "rclQ" 'op-e +v-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "rcrQ" 'op-e +v-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "shlQ" 'op-e +v-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "shrQ" 'op-e +v-mode+ 'op-i +const-1-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "sarQ" 'op-e +v-mode+ 'op-i +const-1-mode+))
+   ;; GRP2b-cl
+   (vector
+    (make-x86-dis "rolA" 'op-e +b-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "rorA" 'op-e +b-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "rclA" 'op-e +b-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "rcrA" 'op-e +b-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "shlA" 'op-e +b-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "shrA" 'op-e +b-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "sarA" 'op-e +b-mode+ 'op-imreg +cl-reg+))
+   ;; GRP2S-cl
+   (vector
+    (make-x86-dis "rolQ" 'op-e +v-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "rorQ" 'op-e +v-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "rclQ" 'op-e +v-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "rcrQ" 'op-e +v-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "shlQ" 'op-e +v-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "shrQ" 'op-e +v-mode+ 'op-imreg +cl-reg+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "sarQ" 'op-e +v-mode+ 'op-imreg +cl-reg+))
+   ;; GRP3b
+   (vector
+    (make-x86-dis "testA" 'op-e +b-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)" 'op-e +b-mode+)
+    (make-x86-dis "notA" 'op-e +b-mode+)
+    (make-x86-dis "negA" 'op-e +b-mode+)
+    (make-x86-dis "mulA" 'op-e +b-mode+)            ; Don't print the implicit %al register
+    (make-x86-dis "imulA" 'op-e +b-mode+)           ; to distinguish these opcodes from other
+    (make-x86-dis "divA" 'op-e +b-mode+)            ; mul/imul opcodes. Do the same for div
+    (make-x86-dis "idivA" 'op-e +b-mode+)           ; and idiv for consistency.
+    )
+   ;; GRP3S
+   (vector
+    (make-x86-dis "testQ" 'op-e +v-mode+ 'op-i +v-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "notQ" 'op-e +v-mode+)
+    (make-x86-dis "negQ" 'op-e +v-mode+)
+    (make-x86-dis "mulQ" 'op-e +v-mode+)            ; Don't print the implicit register.
+    (make-x86-dis "imulQ" 'op-e +v-mode+)
+    (make-x86-dis "divQ" 'op-e +v-mode+)
+    (make-x86-dis "idivQ" 'op-e +v-mode+))
+   ;; GRP4
+   (vector
+    (make-x86-dis "incA" 'op-e +b-mode+)
+    (make-x86-dis "decA" 'op-e +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)"))
+   ;; GRP5
+   (vector
+    (make-x86-dis "incQ" 'op-e +v-mode+)
+    (make-x86-dis "decQ" 'op-e +v-mode+)
+    (make-x86-dis '("callT" . :call) 'op-indire +v-mode+)
+    (make-x86-dis '("JcallT" . :call) 'op-indire +f-mode+)
+    (make-x86-dis '("jmpT" . :jump) 'op-indire +v-mode+)
+    (make-x86-dis '("JjmpT" . :jump) 'op-indire +f-mode+)
+    (make-x86-dis "pushU" 'op-e +v-mode+)
+    (make-x86-dis "(bad)"))
+   ;; GRP6
+   (vector
+    (make-x86-dis "sldtQ" 'op-e +v-mode+)
+    (make-x86-dis "strQ" 'op-e +v-mode+)
+    (make-x86-dis "lldt" 'op-e +w-mode+)
+    (make-x86-dis "ltr" 'op-e +w-mode+)
+    (make-x86-dis "verr" 'op-e +w-mode+)
+    (make-x86-dis "verw" 'op-e +w-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)"))
+   ;; GRP7
+   (vector
+    (make-x86-dis "sgdtQ" 'op-m 0)
+    (make-x86-dis "sidtQ" 'pni-fixup 0)
+    (make-x86-dis '(("lgdtQ" . "lgdt")) 'op-m 0)
+    (make-x86-dis '(("lidtQ" . "lidt")) 'op-m 0)
+    (make-x86-dis "smswQ" 'op-e +v-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "lmsw" 'op-e +w-mode+)
+    (make-x86-dis "invlpg" 'INVLPG-Fixup +w-mode+))
+   ;; GRP8
+   (vector
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "btQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "btsQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "btrQ" 'op-e +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "btcQ" 'op-e +v-mode+ 'op-i +b-mode+))
+   ;; GRP9
+   (vector
+    (make-x86-dis "(bad)")
+    (make-x86-dis "cmpxchg8b" 'op-e +q-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)"))
+   ;; GRP10
+   (vector
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "psrlw" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "psraw" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "psllw" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)"))
+   ;; GRP11
+   (vector
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "psrld" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "psrad" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "pslld" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)"))
+   ;; GRP12
+   (vector
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "psrlq" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "psrldq" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "psllq" 'op-ms +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "pslldq" 'op-ms +v-mode+ 'op-i +b-mode+))
+   ;; GRP13
+   (vector
+    (make-x86-dis "fxsave" 'op-e +v-mode+)
+    (make-x86-dis "fxrstor" 'op-e +v-mode+)
+    (make-x86-dis "ldmxcsr" 'op-e +v-mode+)
+    (make-x86-dis "stmxcsr" 'op-e +v-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "lfence" 'OP-0fae 0)
+    (make-x86-dis "mfence" 'OP-0fae 0)
+    (make-x86-dis "clflush" 'OP-0fae 0))
+   ;; GRP14
+   (vector
+    (make-x86-dis "prefetchnta" 'op-e +v-mode+)
+    (make-x86-dis "prefetcht0" 'op-e +v-mode+)
+    (make-x86-dis "prefetcht1" 'op-e +v-mode+)
+    (make-x86-dis "prefetcht2" 'op-e +v-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)"))
+   ;; GRPAMD
+   (vector
+    (make-x86-dis "prefetch" 'op-e +b-mode+)
+    (make-x86-dis "prefetchw" 'op-e +b-mode+)
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)")
+    (make-x86-dis "(bad)"))
+   ;; GRPPADLCK1
+   (vector
+    (make-x86-dis "xstorerng" 'op-0f07 0)
+    (make-x86-dis "xcryptecb" 'op-0f07 0)
+    (make-x86-dis "xcryptcbc" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0)
+    (make-x86-dis "xcryptcfb" 'op-0f07 0)
+    (make-x86-dis "xcryptofb" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0))
+   ;; GRPPADLCK2
+   (vector
+    (make-x86-dis "montmul" 'op-0f07 0)
+    (make-x86-dis "xsha1" 'op-0f07 0)
+    (make-x86-dis "xsha256" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0)
+    (make-x86-dis "(bad)" 'op-0f07 0))))
+
+(defparameter *prefix-user-table*
+  (vector
+   ;; PREGRP0
+   (vector
+    (make-x86-dis "addps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "addss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "addpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "addsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP1
+   (vector
+    (make-x86-dis "" 'op-xmm 0 'op-ex +v-mode+ 'op-simd-suffix 0);; See OP-SIMD-SUFFIX.
+    (make-x86-dis "" 'op-xmm 0 'op-ex +v-mode+ 'op-simd-suffix 0)
+    (make-x86-dis "" 'op-xmm 0 'op-ex +v-mode+ 'op-simd-suffix 0)
+    (make-x86-dis "" 'op-xmm 0 'op-ex +v-mode+ 'op-simd-suffix 0))
+   ;; PREGRP2
+   (vector
+    (make-x86-dis "cvtpi2ps" 'op-xmm 0 'op-em +v-mode+)
+    (make-x86-dis "cvtsi2ssY" 'op-xmm 0 'op-e +v-mode+)
+    (make-x86-dis "cvtpi2pd" 'op-xmm 0 'op-em +v-mode+)
+    (make-x86-dis "cvtsi2sdY" 'op-xmm 0 'op-e +v-mode+))
+   ;; PREGRP3
+   (vector
+    (make-x86-dis "cvtps2pi" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtss2siY" 'op-g +v-mode+ 'op-ex +v-mode+)
+    (make-x86-dis "cvtpd2pi" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtsd2siY" 'op-g +v-mode+ 'op-ex +v-mode+))
+   ;; PREGRP4
+   (vector
+    (make-x86-dis "cvttps2pi" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "cvttss2siY" 'op-g +v-mode+ 'op-ex +v-mode+)
+    (make-x86-dis "cvttpd2pi" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "cvttsd2siY" 'op-g +v-mode+ 'op-ex +v-mode+))
+   ;; PREGRP5
+   (vector
+    (make-x86-dis "divps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "divss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "divpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "divsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP6
+   (vector
+    (make-x86-dis "maxps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "maxss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "maxpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "maxsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP7
+   (vector
+    (make-x86-dis "minps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "minss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "minpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "minsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP8
+   (vector
+    (make-x86-dis "movups" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movupd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP9
+   (vector
+    (make-x86-dis "movups" 'op-ex +v-mode+ 'op-xmm 0)
+    (make-x86-dis "movss" 'op-ex +v-mode+ 'op-xmm 0)
+    (make-x86-dis "movupd" 'op-ex +v-mode+ 'op-xmm 0)
+    (make-x86-dis "movsd" 'op-ex +v-mode+ 'op-xmm 0))
+   ;; PREGRP10
+   (vector
+    (make-x86-dis "mulps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "mulss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "mulpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "mulsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP11
+   (vector
+    (make-x86-dis "rcpps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "rcpss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP12
+   (vector
+    (make-x86-dis "rsqrtps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "rsqrtss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP13
+   (vector
+    (make-x86-dis "sqrtps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "sqrtss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "sqrtpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "sqrtsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP14
+   (vector
+    (make-x86-dis "subps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "subss" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "subpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "subsd" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP15
+   (vector
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtdq2pd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvttpd2dq" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtpd2dq" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP16
+   (vector
+    (make-x86-dis "cvtdq2ps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvttps2dq" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtps2dq" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP17
+   (vector
+    (make-x86-dis "cvtps2pd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtss2sd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtpd2ps" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "cvtsd2ss" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP18
+   (vector
+    (make-x86-dis "maskmovq" 'op-mmx 0 'op-s +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "maskmovdqu" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP19
+   (vector
+    (make-x86-dis "movq" 'op-mmx 0 'op-em +v-mode+)
+    (make-x86-dis "movdqu" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movdqa" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP20
+   (vector
+    (make-x86-dis "movq" 'op-em +v-mode+ 'op-mmx 0)
+    (make-x86-dis "movdqu" 'op-ex +v-mode+ 'op-xmm 0)
+    (make-x86-dis "movdqa" 'op-ex +v-mode+ 'op-xmm 0)
+    (make-x86-dis "(bad)" 'op-ex +v-mode+ 'op-xmm 0))
+   ;; PREGRP21
+   (vector
+    (make-x86-dis "(bad)" 'op-ex +v-mode+ 'op-xmm 0)
+    (make-x86-dis "movq2dq" 'op-xmm 0 'op-s +v-mode+)
+    (make-x86-dis "movq" 'op-ex +v-mode+ 'op-xmm 0)
+    (make-x86-dis "movdq2q" 'op-mmx 0 'op-xs +v-mode+))
+   ;; PREGRP22
+   (vector
+    (make-x86-dis "pshufw" 'op-mmx 0 'op-em +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "pshufhw" 'op-xmm 0 'op-ex +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "pshufd" 'op-xmm 0 'op-ex +v-mode+ 'op-i +b-mode+)
+    (make-x86-dis "pshuflw" 'op-xmm 0 'op-ex +v-mode+ 'op-i +b-mode+))
+   ;; PREGRP23
+   (vector
+    (make-x86-dis "movd" 'op-e +dq-mode+ 'op-mmx 0)
+    (make-x86-dis "movq" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movd" 'op-e +dq-mode+ 'op-xmm 0)
+    (make-x86-dis "(bad)" 'op-e +d-mode+ 'op-xmm 0))
+   ;; PREGRP24
+   (vector
+    (make-x86-dis "(bad)" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "punpckhqdq" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP25
+   (vector
+    (make-x86-dis "movntq" 'op-em +v-mode+ 'op-mmx 0)
+    (make-x86-dis "(bad)" 'op-em +v-mode+ 'op-xmm 0)
+    (make-x86-dis "movntdq" 'op-em +v-mode+ 'op-xmm 0)
+    (make-x86-dis "(bad)" 'op-em +v-mode+ 'op-xmm 0))
+   ;; PREGRP26
+   (vector
+    (make-x86-dis "(bad)" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "punpcklqdq" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP27
+   (vector
+    (make-x86-dis "(bad)" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "addsubpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "addsubps" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP28
+   (vector
+    (make-x86-dis "(bad)" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "haddpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "haddps" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP29
+   (vector
+    (make-x86-dis "(bad)" 'op-mmx 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "hsubpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "hsubps" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP30
+   (vector
+    (make-x86-dis "movlpX" 'op-xmm 0 'op-ex +v-mode+ 'SIMD-Fixup #\h);; really only 2 operands
+    (make-x86-dis "movsldup" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movlpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movddup" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP31
+   (vector
+    (make-x86-dis "movhpX" 'op-xmm 0 'op-ex +v-mode+ 'SIMD-Fixup #\l)
+    (make-x86-dis "movshdup" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "movhpd" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+))
+   ;; PREGRP32
+   (vector
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "(bad)" 'op-xmm 0 'op-ex +v-mode+)
+    (make-x86-dis "lddqu" 'op-xmm 0 'op-m 0))))
+
+(defparameter *x86-64-table*
+    (vector
+     (vector
+      (make-x86-dis "arpl" 'op-e +w-mode+ 'op-g +w-mode+)
+      (make-x86-dis "movslq" 'op-g +v-mode+ 'op-e +d-mode+))))
+
+
+(defun prefix-name (ds b sizeflag)
+  (case b
+    (#x40 "rex")
+    (#x41 "rexZ")
+    (#x42 "rexY")
+    (#x43 "rexYZ")
+    (#x44 "rexX")
+    (#x45 "rexXZ")
+    (#x46 "rexYZ")
+    (#x47 "rexXYZ")
+    (#x48 "rex64")
+    (#x49 "rex64Z")
+    (#x4a "rex64Y")
+    (#x4b "rex64YZ")
+    (#x4c "rex64X")
+    (#x4d "rex64XZ")
+    (#x4e "rex64XY")
+    (#x4f "rex64XYZ")
+    (#xf3 "repz")
+    (#xf2 "repnz")
+    (#xf0 "lock")
+    (#x2e "cs")
+    (#x36 "ss")
+    (#x3e "ds")
+    (#x26 "es")
+    (#x64 "fs")
+    (#x65 "gs")
+    (#x66 (if (logtest sizeflag +dflag+) "data16" "data32"))
+    (#x67 (if (x86-ds-mode-64 ds)
+            (if (logtest sizeflag +aflag+) "addr32" "addr64")
+            (if (logtest sizeflag +aflag+) "addr16" "addr32")))
+
+    (#x9b "fwait")))
+
+(defun scan-prefixes (ds instruction)
+  (setf (x86-ds-prefixes ds) 0
+        (x86-ds-used-prefixes ds) 0
+        (x86-ds-rex ds) 0
+        (x86-ds-rex-used ds) 0)
+  (let* ((newrex 0)
+         (prefixes 0))
+    (declare (fixnum prefixes))
+    (do* ((b (x86-ds-peek-u8 ds)
+             (progn (x86-ds-skip ds)
+                    (x86-ds-peek-u8 ds))))
+         ()
+      (declare (type (unsigned-byte 8) b))
+      (setq newrex 0)
+      (cond ((and (>= b #x40)
+                  (<= b #x4f))
+             (if (x86-ds-mode-64 ds)
+               (setq newrex b)
+               (return)))
+            ((= b #xf3)
+             (setq prefixes (logior prefixes +prefix-repz+)))
+            ((= b #xf2)
+             (setq prefixes (logior prefixes +prefix-repnz+)))
+            ((= b #xf0)
+             (setq prefixes (logior prefixes +prefix-lock+)))
+            ((= b #x2e)
+             (setq prefixes (logior prefixes +prefix-cs+)))
+            ((= b #x36)
+             (setq prefixes (logior prefixes +prefix-ss+)))
+            ((= b #x3e)
+             (setq prefixes (logior prefixes +prefix-ds+)))
+            ((= b #x26)
+             (setq prefixes (logior prefixes +prefix-es+)))
+            ((= b #x64)
+             (setq prefixes (logior prefixes +prefix-fs+)))
+            ((= b #x65)
+             (setq prefixes (logior prefixes +prefix-gs+)))
+            ((= b #x66)
+             (setq prefixes (logior prefixes +prefix-data+)))
+            ((= b #x67)
+             (setq prefixes (logior prefixes +prefix-addr+)))
+            ((= b #x9b)
+             ;; FWAIT. If there are already some prefixes,
+             ;; we've found the opcode.
+             (if (= prefixes 0)
+               (progn
+                 (setq prefixes +prefix-fwait+)
+                 (return))
+               (setq prefixes (logior prefixes +prefix-fwait+))))
+            (t (return)))
+      (unless (zerop (x86-ds-rex ds))
+        (let* ((prefix-name (prefix-name ds (x86-ds-rex ds) 0)))
+          (when prefix-name
+            (push prefix-name
+                  (x86-di-prefixes instruction)))))
+      (setf (x86-ds-rex ds) newrex))
+    (setf (x86-ds-prefixes ds) prefixes)))
+
+
+(defun x86-putop (ds template sizeflag instruction)
+  (let* ((ok t))
+    (when (consp template)
+      (if (x86-ds-mode-64 ds)
+      (setq template (cdr template))
+      (setq template (car template))))
+  (if (dotimes (i (length template) t)
+          (unless (lower-case-p (schar template i))
+            (return nil)))
+      (setf (x86-di-mnemonic instruction) template)
+      (let* ((string-buffer (x86-ds-string-buffer ds))
+             (mod (x86-ds-mod ds))
+             (rex (x86-ds-rex ds))
+             (prefixes (x86-ds-prefixes ds))
+             (mode64 (x86-ds-mode-64 ds)))
+        (declare (fixnum rex prefixes))
+        (setf (fill-pointer string-buffer) 0)
+        (dotimes (i (length template))
+          (let* ((c (schar template i))
+                 (b 
+                  (case c
+                    (#\) (setq ok nil))
+                    (#\A (if (or (not (eql mod 3))
+                                 (logtest sizeflag +suffix-always+))
+                           #\b))
+                    (#\B (if (logtest sizeflag +suffix-always+)
+                           #\b))
+                    (#\C (when (or (logtest prefixes +prefix-data+)
+                                   (logtest sizeflag +suffix-always+))
+                           (used-prefix ds +prefix-data+)
+                           (if (logtest sizeflag +dflag+)
+                             #\l
+                             #\s)))
+                    (#\E (used-prefix ds +prefix-addr+)
+                         (if mode64
+                           (if (logtest sizeflag +aflag+)
+                             #\r
+                             #\e)
+                           (if (logtest sizeflag +aflag+)
+                             #\e)))
+                    (#\F (when (or (logtest prefixes +prefix-addr+)
+                                   (logtest sizeflag +suffix-always+))
+                           (used-prefix ds +prefix-addr+)
+                           (if (logtest sizeflag +aflag+)
+                             (if mode64 #\q #\l)
+                             (if mode64 #\l #\w))))
+                    (#\H (let* ((ds-or-cs
+                                 (logand prefixes
+                                         (logior +prefix-ds+ +prefix-ds+)))
+                                (ds-only (= ds-or-cs +prefix-ds+))
+                                (cs-only (= ds-or-cs +prefix-cs+)))
+                           (when (or ds-only cs-only)
+                             (setf (x86-ds-used-prefixes ds)
+                                   (logior (x86-ds-used-prefixes ds)
+                                           ds-or-cs))
+                             (if ds-only ".pt" ".pn"))))
+                    (#\J #\l)
+                    (#\L (if (logtest sizeflag +suffix-always+) #\l))
+                    (#\N (if (logtest prefixes +prefix-fwait+)
+                           (setf (x86-ds-used-prefixes ds)
+                                 (logior (x86-ds-used-prefixes ds)
+                                         +prefix-fwait+))
+                           #\n))
+                    (#\O (used-rex ds +rex-mode64+)
+                         (if (logtest rex +rex-mode64+)
+                           #\o
+                           #\d))
+                    ((#\T #\P)
+                     (if (and (eql c #\T) mode64)
+                       #\q
+                       (when (or (logtest prefixes +prefix-data+)
+                                 (logtest rex +rex-mode64+)
+                                 (logtest sizeflag +suffix-always+))
+                         (used-rex ds +rex-mode64+)
+                         (if (logtest rex +rex-mode64+)
+                           #\q
+                           (progn
+                             (used-prefix ds +prefix-data+)
+                             (if (logtest sizeflag +dflag+)
+                               #\l
+                               #\w))))))
+                    ((#\U #\Q)
+                     (if (and (eql c #\U) mode64)
+                       #\q
+                       (progn
+                         (used-rex ds +rex-mode64+)
+                         (when (or (not (eql mod 3))
+                                   (logtest sizeflag +suffix-always+))
+                           (if (logtest rex +rex-mode64+)
+                             #\q
+                             (progn
+                               (used-prefix ds +prefix-data+)
+                               (if (logtest sizeflag +dflag+)
+                                 #\l
+                                 #\w)))))))
+                    (#\R
+                     (used-rex ds +rex-mode64+)
+                     (if (logtest rex +rex-mode64+)
+                       #\q
+                       (if (logtest sizeflag +dflag+)
+                         #\l
+                         #\w)))
+                    (#\S
+                     (when (logtest sizeflag +suffix-always+)
+                       (if (logtest rex +rex-mode64+)
+                         #\q
+                         (progn
+                           (used-prefix ds +prefix-data+)
+                           (if (logtest sizeflag +dflag+)
+                             #\l
+                             #\w)))))
+                    (#\X
+                     (used-prefix ds +prefix-data+)
+                     (if (logtest prefixes +prefix-data+)
+                       #\d
+                       #\s))
+                    (#\Y
+                     (when (logtest rex +rex-mode64+)
+                       (used-rex ds +rex-mode64+)
+                       #\q))
+                    (#\W
+                     (used-rex ds 0)
+                     (if (not (eql rex 0))
+                       #\l
+                       (progn
+                         (used-prefix ds +prefix-data+)
+                         (if (logtest sizeflag +dflag+)
+                           #\w
+                           #\b))))
+                    (t c))))
+            (if b
+              (if (typep b 'character)
+                (vector-push-extend b string-buffer)
+                (dotimes (i (length b))
+                  (vector-push-extend (schar b i) string-buffer))))))
+        (setf (x86-di-mnemonic instruction) (subseq string-buffer 0))))
+  ok))
+
+(defparameter *x86-dissassemble-always-print-suffix* t)
+
+(defun x86-dis-do-float (ds instruction floatop sizeflag)
+  (declare (ignore floatop sizeflag))
+  ;; Later; we want to make minimal use of the x87 fpu.
+  (setf (x86-di-mnemonic instruction) "x87-fpu-op")
+  (x86-ds-skip ds))
+
+(defun x86-dis-do-uuo (ds instruction intop)
+  (declare (type (unsigned-byte 8) intop))
+  (let* ((stop t)
+         (regmask (if (x86-ds-mode-64 ds) #xf #x7)))
+    (cond ((and (>= intop #x70) (< intop #x80))
+           (let* ((pseudo-modrm-byte (x86-ds-next-u8 ds)))
+             (setf (x86-di-mnemonic instruction)
+                   "uuo-error-slot-unbound"
+                   (x86-di-op0 instruction)
+                   (x86-dis-make-reg-operand (lookup-x86-register (logand intop regmask) :%))                     
+                   (x86-di-op1 instruction)
+                   (x86-dis-make-reg-operand (lookup-x86-register (ldb (byte 4 4)
+                                                                       pseudo-modrm-byte) :%))
+                   (x86-di-op2 instruction)
+                   (x86-dis-make-reg-operand (lookup-x86-register (ldb (byte 4 0)
+                                                                       pseudo-modrm-byte) :%)))))
+          ((< intop #x90)
+           (setf (x86-di-mnemonic instruction) "int"
+                 (x86-di-op0 instruction)
+                 (x86::make-x86-immediate-operand :value (parse-x86-lap-expression intop))))
+          ((< intop #xa0)
+           (setf (x86-di-mnemonic instruction)
+                 "uuo-error-unbound"
+                 (x86-di-op0 instruction)
+                 (x86-dis-make-reg-operand (lookup-x86-register (logand intop regmask) :%))))
+          ((< intop #xb0)
+           (setf (x86-di-mnemonic instruction)
+                 "uuo-error-udf"
+                 (x86-di-op0 instruction)
+                 (x86-dis-make-reg-operand (lookup-x86-register (logand intop regmask) :%))))
+         
+          ((< intop #xc0)
+           (setf (x86-di-mnemonic instruction)
+                 "uuo-error-reg-not-type"
+                 (x86-di-op0 instruction)
+                 (x86-dis-make-reg-operand (lookup-x86-register (logand intop regmask) :%))
+                 (x86-di-op1 instruction)
+                 (x86::make-x86-immediate-operand :value (parse-x86-lap-expression (x86-ds-next-u8 ds)))))
+          ((< intop #xc8)
+           (if (= intop #xc3)
+             (let* ((pseudo-modrm-byte (x86-ds-next-u8 ds)))
+               (setf (x86-di-mnemonic instruction)
+                     "uuo-error-array-rank"
+                     (x86-di-op0 instruction)
+                     (x86-dis-make-reg-operand (lookup-x86-register (ldb (byte 4 4)
+                                                                         pseudo-modrm-byte) :%))
+                     (x86-di-op1 instruction)
+                     (x86-dis-make-reg-operand (lookup-x86-register (ldb (byte 4 0)
+                                                                         pseudo-modrm-byte) :%))))
+                   
+           (setf (x86-di-mnemonic instruction)
+                 (case intop
+                   (#xc0 "uuo-error-too-few-args")
+                   (#xc1 "uuo-error-too-many-args")
+                   (#xc2 "uuo-error-wrong-number-of-args")
+                   (#xc4 (progn (setq stop nil) "uuo-gc-trap"))
+                   (#xc5 "uuo-alloc")
+                   (#xc6 "uuo-error-not-callable")
+                   (#xc7 "uuo-udf-call")
+                   (t "unknown-UUO")))))
+          ((= intop #xc8)
+           (let* ((pseudo-modrm-byte (x86-ds-next-u8 ds)))
+             (declare (type (unsigned-byte 8) pseudo-modrm-byte))
+             (setf (x86-di-op0 instruction)
+                 (x86-dis-make-reg-operand
+                  (lookup-x86-register (ldb (byte 4 4) pseudo-modrm-byte) :%))
+                 (x86-di-op1 instruction)
+                 (x86-dis-make-reg-operand
+                  (lookup-x86-register (ldb (byte 4 0) pseudo-modrm-byte) :%))
+                 (x86-di-mnemonic instruction) "uuo-error-vector-bounds")))
+          ((< intop #xd0)
+           (cond ((= intop #xcb)
+                  (let* ((pseudo-modrm-byte (x86-ds-next-u8 ds)))
+                    (setf (x86-di-mnemonic instruction)
+                          "uuo-error-array-bounds"
+                          (x86-di-op0 instruction)
+                          (x86-dis-make-reg-operand
+                           (lookup-x86-register (ldb (byte 4 4)
+                                                     pseudo-modrm-byte) :%))
+                          (x86-di-op1 instruction)
+                          (x86-dis-make-reg-operand
+                           (lookup-x86-register (ldb (byte 4 0)
+                                                     pseudo-modrm-byte) :%)))))
+                 ((= intop #xcc)
+                  (let* ((pseudo-modrm-byte (x86-ds-next-u8 ds)))
+                    (setf (x86-di-mnemonic instruction)
+                          "uuo-error-eep-unresolved"
+                          (x86-di-op0 instruction)
+                          (x86-dis-make-reg-operand
+                           (lookup-x86-register (ldb (byte 4 4)
+                                                     pseudo-modrm-byte) :%))
+                          (x86-di-op1 instruction)
+                          (x86-dis-make-reg-operand
+                           (lookup-x86-register (ldb (byte 4 0)
+                                                     pseudo-modrm-byte) :%)))))
+                 (t (setf (x86-di-mnemonic instruction)
+                          (case intop
+                            (#xc9 "uuo-error-call-macro-or-special-operator")
+                            (#xca (setq stop nil) "uuo-error-debug-trap")
+                            (#xcd (setq stop nil) "uuo-error-debug-trap-with-string")
+                            (t "unknown-UUO"))))))
+          ((< intop #xe0)
+           (setf (x86-di-mnemonic instruction)
+                 "uuo-error-reg-not-tag"
+                 (x86-di-op0 instruction)
+                 (x86-dis-make-reg-operand (lookup-x86-register (logand intop regmask) :%))
+                 (x86-di-op1 instruction)
+                 (x86::make-x86-immediate-operand :value (parse-x86-lap-expression (x86-ds-next-u8 ds)))))
+          ((< intop #xf0)
+           (setf (x86-di-mnemonic instruction)
+                 "uuo-error-reg-not-list"
+                 (x86-di-op0 instruction)
+                 (x86-dis-make-reg-operand (lookup-x86-register (logand intop regmask) :%))))
+          (t
+           (setf (x86-di-mnemonic instruction)
+                 "uuo-error-reg-not-fixnum"
+                 (x86-di-op0 instruction)
+                 (x86-dis-make-reg-operand (lookup-x86-register (logand intop regmask) :%)))))
+    stop))
+
+
+
+(defun x86-dis-analyze-operands (ds instruction flag)
+  ;; If instruction is adding a positive displacement to the FN
+  ;; register, note the effective address as a label reference
+  ;; and modify the operand(s).
+  ;; If the instruction is a MOV or PUSH whose source operand
+  ;; is relative to the FN register, generate a constant reference.
+  ;; If the instruction is adding a displacement to RIP, note
+  ;; the effective address as a label reference.
+  ;; On ia32, if op0 is a 32-bit immediate and op1 is (% fn),
+  ;; treat the immediate as :self.
+  (let* ((op0 (x86-di-op0 instruction))
+         (op1 (x86-di-op1 instruction))
+         (entry-ea (x86-ds-entry-point ds)))
+    (flet ((is-fn (thing)
+             (if (typep thing 'x86::x86-register-operand)
+               (let* ((entry (x86::x86-register-operand-entry thing)))
+                 (eq entry (if (x86-ds-mode-64 ds)
+                             (x86::x86-reg64 13)
+                             (x86::x86-reg32 x8632::fn))))))
+           (is-rip (thing)
+             (if (and (typep thing 'x86::x86-register-operand)
+                      (x86-ds-mode-64 ds))
+               (let* ((entry (x86::x86-register-operand-entry thing)))
+                 (eq entry (svref x86::*x8664-register-entries* 102)))))
+           (is-ra0 (thing)
+             (if (typep thing 'x86::x86-register-operand)
+               (let* ((entry (x86::x86-register-operand-entry thing)))
+                 (eq entry (if (x86-ds-mode-64 ds)
+                             (x86::x86-reg64 10)
+                             (x86::x86-reg32 7))))))
+           (is-disp-only (thing)
+             (and (typep thing 'x86::x86-memory-operand)
+                  (null (x86::x86-memory-operand-base thing))
+                  (null (x86::x86-memory-operand-index thing))
+                  (x86::x86-memory-operand-disp thing))))
+      (flet ((is-fn-ea (thing)
+               (and (typep thing 'x86::x86-memory-operand)
+                    (is-fn (x86::x86-memory-operand-base thing))
+                    (null (x86::x86-memory-operand-index thing))
+                    (let* ((scale (x86::x86-memory-operand-scale thing)))
+                      (or (null scale) (eql 0 scale)))
+                    (let* ((disp (x86::x86-memory-operand-disp thing)))
+                      (and disp (early-x86-lap-expression-value disp)))))
+             (is-ra0-ea (thing)
+               (and (typep thing 'x86::x86-memory-operand)
+                    (is-ra0 (x86::x86-memory-operand-base thing))
+                    (null (x86::x86-memory-operand-index thing))
+                    (let* ((scale (x86::x86-memory-operand-scale thing)))
+                      (or (null scale) (eql 0 scale)))
+                    (let* ((disp (x86::x86-memory-operand-disp thing)))
+                      (and disp (early-x86-lap-expression-value disp)))))
+             (is-rip-ea (thing)
+               (and (typep thing 'x86::x86-memory-operand)
+                    (is-rip (x86::x86-memory-operand-base thing))
+                    (null (x86::x86-memory-operand-index thing))
+                    (let* ((scale (x86::x86-memory-operand-scale thing)))
+                      (or (null scale) (eql 0 scale)))
+                    (let* ((disp (x86::x86-memory-operand-disp thing)))
+                      (and disp (early-x86-lap-expression-value disp))))))
+        (case flag
+          ;; Should also check alignment here, and check
+          
+          (:lea
+           (let* ((disp ))
+             (if (or (and (setq disp (is-fn-ea op0)) (> disp 0))
+                       (and (setq disp (is-ra0-ea op0)) (< disp 0) (is-fn op1)))
+               (let* ((label-ea (+ entry-ea (abs disp))))
+                 (when (< label-ea (x86-ds-code-limit ds))
+                   (setf (x86::x86-memory-operand-disp op0)
+                         (parse-x86-lap-expression
+                          (if (< disp 0)
+                            `(- (:^ ,label-ea))
+                            `(:^ ,label-ea))))
+                   (push label-ea (x86-ds-pending-labels ds))))
+               (if (and (setq disp (is-rip-ea op0)) (< disp 0) (is-fn op1))
+                 (progn
+                   (setf (x86::x86-memory-operand-disp op0)
+                         (parse-x86-lap-expression `(:^ ,entry-ea)))
+                   (push entry-ea (x86-ds-pending-labels ds)))))))
+          ((:jump :call)
+           (let* ((disp (is-disp-only op0)))
+             (when disp
+               (let* ((info (find (early-x86-lap-expression-value disp)
+				  (if (x86-ds-mode-64 ds)
+				    x8664::*x8664-subprims*
+				    x8632::*x8632-subprims*)
+                                  :key #'subprimitive-info-offset)))
+                 (when info (setf (x86::x86-memory-operand-disp op0)
+                                  (subprimitive-info-name info)))))))
+          (t
+           (unless (x86-ds-mode-64 ds)
+             (when (and (is-fn op1)
+                        (typep op0 'x86::x86-immediate-operand)
+                        ;; Not sure what else would have an
+                        ;; immediate source and %fn as destination,
+                        ;; but check for this.
+                        (equal (x86-di-mnemonic instruction) "movl"))
+               (setf (x86-di-mnemonic instruction) "recover-fn"
+                     (x86-di-op0 instruction) nil
+                     (x86-di-op0 instruction) nil))))
+
+          )))
+    instruction))
+
+(defun x86-disassemble-instruction (ds labeled)
+  (let* ((addr (x86-ds-code-pointer ds))
+         (sizeflag (logior +aflag+ +dflag+
+                           (if *x86-dissassemble-always-print-suffix*
+                             +suffix-always+
+                             0)))
+         (instruction (make-x86-disassembled-instruction :address addr
+                                                         :labeled labeled))
+         (stop nil))
+    (setf (x86-ds-insn-start ds) addr
+          (x86-ds-current-instruction ds) instruction)
+    (scan-prefixes ds instruction)
+    (setf (x86-ds-opcode-start ds) (x86-ds-code-pointer ds))
+    (let* ((primary-opcode (x86-ds-next-u8 ds))
+           (two-source-ops (or (= primary-opcode #x62)
+                               (= primary-opcode #xc8)))
+           (prefixes (x86-ds-prefixes ds))
+           (need-modrm nil)
+           (uses-sse-prefix nil)
+           (uses-lock-prefix nil)
+           (dp nil))
+      (declare (type (unsigned-byte 8) primary-opcode)
+               (fixnum prefixes))
+      (if (= primary-opcode #x0f)       ;two-byte opcode
+        (setq primary-opcode (x86-ds-next-u8 ds)
+              dp (svref *disx86-twobyte* primary-opcode)
+              need-modrm (eql 1 (sbit *twobyte-has-modrm* primary-opcode))
+              uses-sse-prefix (eql 1 (sbit *twobyte-uses-sse-prefix* primary-opcode))
+              uses-lock-prefix (= #x20 (logandc2 primary-opcode 2)))
+        (setq dp (svref *disx86* primary-opcode)
+              need-modrm (eql 1 (sbit *onebyte-has-modrm* primary-opcode))))
+      (when (and (not uses-sse-prefix) 
+                 (logtest prefixes +prefix-repz+))
+        (push "repz" (x86-di-prefixes instruction))
+        (setf (x86-ds-used-prefixes ds)
+              (logior (x86-ds-used-prefixes ds) +prefix-repz+)))
+      (when (and (not uses-sse-prefix) 
+                 (logtest prefixes +prefix-repnz+))
+        (push "repnz" (x86-di-prefixes instruction))
+        (setf (x86-ds-used-prefixes ds)
+              (logior (x86-ds-used-prefixes ds) +prefix-repnz+)))
+      (when (and (not uses-lock-prefix)
+                 (logtest prefixes +prefix-lock+))
+        (push "lock" (x86-di-prefixes instruction))
+        (setf (x86-ds-used-prefixes ds)
+              (logior (x86-ds-used-prefixes ds) +prefix-lock+)))
+      (when (logtest prefixes +prefix-addr+)
+        (setq sizeflag (logxor sizeflag +aflag+))
+        (unless (= (x86-dis-bytemode3 dp) +loop-jcxz-mode+)
+          (if (or (x86-ds-mode-64 ds)
+                  (logtest sizeflag +aflag+))
+            (push "addr32" (x86-di-prefixes instruction))
+            (push "addr16" (x86-di-prefixes instruction)))
+          (setf (x86-ds-used-prefixes ds)
+                (logior (x86-ds-used-prefixes ds) +prefix-addr+))))
+      (when (and (not uses-sse-prefix)
+                 (logtest prefixes +prefix-data+))
+        (setq sizeflag (logxor sizeflag +dflag+))
+        (when (and (= (x86-dis-bytemode3 dp) +cond-jump-mode+)
+                   (= (x86-dis-bytemode1 dp) +v-mode+))
+          (if (logtest sizeflag +dflag+)
+            (push "data32" (x86-di-prefixes instruction))
+            (push "data16" (x86-di-prefixes instruction)))
+          (setf (x86-ds-used-prefixes ds)
+                (logior (x86-ds-used-prefixes ds) +prefix-data+))))
+      (when need-modrm
+        (let* ((modrm-byte (x86-ds-peek-u8 ds)))
+          (declare (type (unsigned-byte 8) modrm-byte))
+          (setf (x86-ds-mod ds) (ldb (byte 2 6) modrm-byte)
+                (x86-ds-reg ds) (ldb (byte 3 3) modrm-byte)
+                (x86-ds-rm ds) (ldb (byte 3 0) modrm-byte))))
+      (if (and (null (x86-dis-mnemonic dp))
+               (eql (x86-dis-bytemode1 dp) +floatcode+))
+        (x86-dis-do-float ds instruction primary-opcode sizeflag)
+        (if (and (null (x86-dis-mnemonic dp))
+                 (eql (x86-dis-bytemode1 dp) +uuocode+))
+          (progn
+            (setq stop
+                  (x86-dis-do-uuo ds instruction (x86-ds-next-u8 ds))))
+          (progn
+            (when (null (x86-dis-mnemonic dp))
+              (let* ((bytemode1 (x86-dis-bytemode1 dp)))
+                (declare (fixnum bytemode1))
+                (cond ((= bytemode1 +use-groups+)
+                       (setq dp (svref (svref *grps* (x86-dis-bytemode2 dp))
+                                       (x86-ds-reg ds))))
+                      ((= bytemode1 +use-prefix-user-table+)
+                       (let* ((index 0))
+                         (used-prefix ds +prefix-repz+)
+                         (if (logtest prefixes +prefix-repz+)
+                           (setq index 1)
+                           (progn
+                             (used-prefix ds +prefix-data+)
+                             (if (logtest prefixes +prefix-data+)
+                               (setq index 2)
+                               (progn
+                                 (used-prefix ds +prefix-repnz+)
+                                 (if (logtest prefixes +prefix-repnz+)
+                                   (setq index 3))))))
+                         (setq dp (svref (svref *prefix-user-table*
+                                                (x86-dis-bytemode2 dp))
+                                         index))))
+                      ((= bytemode1 +x86-64-special+)
+                       (setq dp (svref (svref *x86-64-table*
+                                              (x86-dis-bytemode2 dp))
+                                       (if (x86-ds-mode-64 ds) 1 0))))
+                    (t (error "Disassembly error")))))
+          (when (x86-putop ds (x86-dis-mnemonic dp) sizeflag instruction)
+            (let* ((operands ())
+                   (op1 (x86-dis-op1 dp))
+                   (op2 (x86-dis-op2 dp))
+                   (op3 (x86-dis-op3 dp))
+                   (operand nil))
+              (when op1
+                ;(format t "~& op1 = ~s" op1)
+                (setq operand (funcall op1 ds (x86-dis-bytemode1 dp) sizeflag))
+                (if operand
+                  (push operand operands)))
+              (when op2
+                ;(format t "~& op2 = ~s" op2)
+                (setq operand (funcall op2 ds (x86-dis-bytemode2 dp) sizeflag))
+                (if operand
+                  (push operand operands)))
+              (when op3
+                ;(format t "~& op3 = ~s" op3)
+                (setq operand (funcall op3 ds (x86-dis-bytemode3 dp) sizeflag))
+                (if operand
+                  (push operand operands)))
+              (if two-source-ops
+                (setf (x86-di-op1 instruction) (pop operands)
+                      (x86-di-op0 instruction) (pop operands))
+                (setf (x86-di-op0 instruction) (pop operands)
+                      (x86-di-op1 instruction) (pop operands)
+                      (x86-di-op2 instruction) (pop operands))))))))
+      (values (x86-dis-analyze-operands ds instruction (x86-dis-flags dp))
+              (or stop (eq (x86-dis-flags dp) :jump))))))
+
+(defun x86-disassemble-new-block (ds addr)
+  (setf (x86-ds-code-pointer ds) addr)
+  (let* ((limit (do-dll-nodes (b (x86-ds-blocks ds) (x86-ds-code-limit ds))
+                  (when (> (x86-dis-block-start-address b) addr)
+                    (return (x86-dis-block-start-address b)))))
+         (block (make-x86-dis-block :start-address addr))
+         (instructions (x86-dis-block-instructions block))
+         (labeled (not (eql addr (x86-ds-entry-point ds)))))
+    (loop
+      (multiple-value-bind (instruction stop)
+          (x86-disassemble-instruction ds labeled)
+        (setq labeled nil)
+        (append-dll-node instruction instructions)
+        (if stop (return))
+        (if (>= (x86-ds-code-pointer ds) limit)
+          (if (= (x86-ds-code-pointer ds) limit)
+            (return)
+            (error "Internal disassembly error")))))
+    (setf (x86-dis-block-end-address block) (x86-ds-code-pointer ds))
+    (insert-x86-block block (x86-ds-blocks ds))))
+
+(defmethod unparse-x86-lap-expression ((exp t)
+                                       ds)
+  (declare (ignore ds))
+  exp)
+
+(defmethod unparse-x86-lap-expression ((exp constant-x86-lap-expression)
+                                       ds)
+  (declare (ignore ds))
+  (constant-x86-lap-expression-value exp))
+
+(defmethod unparse-x86-lap-expression ((exp label-x86-lap-expression)
+                                       ds)
+  (let* ((label (label-x86-lap-expression-label exp))
+         (name (x86-lap-label-name label))
+         (entry (x86-ds-entry-point ds)))
+    `(":^" , (if (typep name 'fixnum)
+            (format nil "L~d" (- name entry))
+            name))))
+
+(defmethod unparse-x86-lap-expression ((exp unary-x86-lap-expression)
+                                       ds)
+  `(,(unary-x86-lap-expression-operator exp)
+    ,(unparse-x86-lap-expression (unary-x86-lap-expression-operand exp) ds)))
+
+(defmethod unparse-x86-lap-expression ((exp binary-x86-lap-expression)
+                                       ds)
+  `(,(binary-x86-lap-expression-operator exp)
+    ,(unparse-x86-lap-expression (binary-x86-lap-expression-operand0 exp) ds)
+    ,(unparse-x86-lap-expression (binary-x86-lap-expression-operand1 exp) ds)))
+
+(defmethod unparse-x86-lap-expression ((exp n-ary-x86-lap-expression)
+                                       ds)
+  `(,(n-ary-x86-lap-expression-operator exp)
+    ,@(mapcar #'(lambda (x)
+                  (unparse-x86-lap-expression x ds))
+              (n-ary-x86-lap-expression-operands exp))))
+
+(defmethod unparse-x86-lap-operand ((op x86::x86-register-operand)
+                                    ds)
+  (let* ((r (x86::x86-register-operand-entry op))
+         (symbolic-names (x86-ds-symbolic-names ds))
+         (reg-name (x86::reg-entry-reg-name r))
+         (name (or (if symbolic-names
+                     (gethash reg-name symbolic-names))
+                     reg-name)))
+    `(% ,name)))
+
+(defmethod unparse-x86-lap-operand ((op x86::x86-immediate-operand)
+                                    ds)
+  `($ ,(unparse-x86-lap-expression (x86::x86-immediate-operand-value op)
+                                   ds)))
+
+(defmethod unparse-x86-lap-operand ((op x86::x86-label-operand)
+                                    ds)
+  (let* ((addr (x86::x86-label-operand-label op))
+         (entrypoint (x86-ds-entry-point ds)))
+    (format nil "L~d" (- addr entrypoint))))
+
+
+(defmethod x86-lap-operand-constant-offset (op ds)
+  (declare (ignore op ds))
+  nil)
+
+(defmethod x86-lap-operand-constant-offset ((op x86::x86-memory-operand) ds)
+  (let* ((disp (x86::x86-memory-operand-disp op)) 
+         (base (x86::x86-memory-operand-base op))
+         (index (x86::x86-memory-operand-index op))
+         (scale (x86::x86-memory-operand-scale op))
+         (code-limit (x86-ds-code-limit ds))
+         (val (and base
+                   (eq (x86::x86-register-operand-entry base)
+                       (if (x86-ds-mode-64 ds)
+                         (x86::x86-reg64 13)
+                         (x86::x86-reg32 x8632::fn)))
+                   (null index)
+                   (or (eql scale 0) (null scale))
+                   (typecase disp
+                     (constant-x86-lap-expression
+                      (+ (x86-ds-entry-point ds)
+                         (constant-x86-lap-expression-value disp)))
+                     (integer
+                      (+ (x86-ds-entry-point ds) disp))
+                     (t nil)))))
+    (when (and val (>= val code-limit))
+      (- val code-limit))))
+
+(defun x86-lap-operand-constant (op ds)
+  (let ((diff (x86-lap-operand-constant-offset op ds)))
+    (when diff
+      (values (uvref (x86-ds-constants-vector ds)
+                     (1+ (ash diff (if (x86-ds-mode-64 ds)
+                                     (- x8664::word-shift)
+                                     (- x8632::word-shift)))))
+              t))))
+
+
+(defmethod unparse-x86-lap-operand ((x x86::x86-memory-operand) ds)
+  (multiple-value-bind (constant foundp) (x86-lap-operand-constant x ds)
+    (if foundp
+      `(@ ',constant ,(unparse-x86-lap-operand (x86::x86-memory-operand-base x) ds))
+      (let* ((seg (x86::x86-memory-operand-seg x))
+             (disp (x86::x86-memory-operand-disp x)) 
+             (base (x86::x86-memory-operand-base x))
+             (index (x86::x86-memory-operand-index x))
+             (scale (x86::x86-memory-operand-scale x)))
+        (collect ((subforms))
+          (subforms '@)
+          (if seg
+            (subforms (unparse-x86-lap-operand seg ds)))
+          (if disp
+            (subforms (unparse-x86-lap-expression disp ds)))
+          (if base
+            (subforms (unparse-x86-lap-operand base ds)))
+          (if index
+            (subforms (unparse-x86-lap-operand index ds)))
+          (if (and scale (not (eql scale 0)))
+            (subforms (ash 1 scale)))
+          (subforms))))))
+    
+(defmethod unparse-x86-lap-operand :around ((op x86::x86-operand)
+                                            ds)
+  (declare (ignore ds))
+  (let* ((usual (call-next-method))
+         (type (or (x86::x86-operand-type op) 0)))
+    (if (logtest (x86::encode-operand-type :jumpabsolute) type)
+      `(* ,usual)
+      usual)))
+
+(defun write-x86-lap-operand (stream op ds)
+  ;; Basically, have to princ because some parts are already stringified,
+  ;; plus don't want package prefixes on assembler syntax.  But want to
+  ;; prin1 immediates. 
+  (let ((expr (unparse-x86-lap-operand op ds)))
+    (format stream " ")
+    (labels ((out (stream expr)
+               (cond ((atom expr)
+                      (format stream "~a" expr))
+                     ((quoted-form-p expr)
+                      (format stream "'~s" (cadr expr)))
+                     (t
+                      (loop for item in expr as pre = "(" then " "
+                        do (format stream pre)
+                        do (out stream item))
+                      (format stream ")")))))
+      (out stream expr))))
+
+(defvar *previous-source-note*)
+
+(defun x86-print-disassembled-instruction (ds instruction seq function)
+  (let* ((addr (x86-di-address instruction))
+         (entry (x86-ds-entry-point ds))
+         (pc (- addr entry)))
+    (let ((source-note (find-source-note-at-pc function pc)))
+      (unless (eql (source-note-file-range source-note)
+                   (source-note-file-range *previous-source-note*))
+        (setf *previous-source-note* source-note)
+        (let* ((source-text (source-note-text source-note))
+               (text (if source-text
+                       (string-sans-most-whitespace source-text 100)
+                       "#<no source text>")))
+          (format t "~&~%;;; ~A" text))))
+    (when (x86-di-labeled instruction)
+      (format t "~&L~d~%" pc)
+      (setq seq 0))
+    (format t "~&  [~D]~8T" pc)
+    (dolist (p (x86-di-prefixes instruction))
+      (format t "~&  (~a)~%" p))
+    (format t "  (~a" (x86-di-mnemonic instruction))
+    (let* ((op0 (x86-di-op0 instruction))
+	   (op1 (x86-di-op1 instruction))
+	   (op2 (x86-di-op2 instruction)))
+      (when op0
+	(write-x86-lap-operand t op0 ds)
+	(when op1
+	  (write-x86-lap-operand t op1 ds)
+	  (when op2
+	    (write-x86-lap-operand t op2 ds)))))
+    (format t ")")
+    (format t "~%")
+    (1+ seq)))
+
+(defun x86-print-disassembled-function-header (function xfunction)
+  (declare (ignore xfunction))
+  (let ((source-note (function-source-note function)))
+    (when source-note
+      (ensure-source-note-text source-note)
+      (if (source-note-filename source-note)
+	(format t ";; ~S:~D-~D"
+		(source-note-filename source-note)
+		(source-note-start-pos source-note)
+		(source-note-end-pos source-note))
+	  (let* ((source-text (source-note-text source-note)))
+	    (when source-text
+	      (format t ";;; ~A" (string-sans-most-whitespace source-text 100))))))))
+
+(defun x86-disassemble-xfunction (function xfunction
+                                  &key (symbolic-names #+x8664-target target::*x8664-symbolic-register-names*
+                                                       #+x8632-target target::*x8632-symbolic-register-names*)
+                                       (collect-function #'x86-print-disassembled-instruction)
+                                       (header-function #'x86-print-disassembled-function-header))
+  (check-type xfunction xfunction)
+  (check-type (uvref xfunction 0) (simple-array (unsigned-byte 8) (*)))
+  (let* ((entry-point  #+x8664-target 7  #+x8632-target 2)
+         (ds (make-x86-disassembly-state
+              :mode-64 #+x8664-target t #+x8632-target nil
+              :code-vector (uvref xfunction 0)
+              :constants-vector xfunction
+              :entry-point entry-point
+              :code-pointer 0           ; for next-u32/next-u16 below
+              :symbolic-names symbolic-names
+              :pending-labels (list entry-point)))
+         (blocks (x86-ds-blocks ds)))
+    (setf (x86-ds-code-limit ds)
+          #+x8664-target (ash (x86-ds-next-u32 ds) 3)
+          #+x8632-target (ash (x86-ds-next-u16 ds) 2))
+    (do* ()
+         ((null (x86-ds-pending-labels ds)))
+      (let* ((lab (pop (x86-ds-pending-labels ds))))
+        (or (x86-dis-find-label lab blocks)
+            (x86-disassemble-new-block ds lab))))
+    (when (and header-function
+               blocks
+               (let ((something-to-disassemble nil))
+                 (do-dll-nodes (block blocks)
+                   (do-dll-nodes (instruction (x86-dis-block-instructions block))
+                     (setf something-to-disassemble t)))
+                 something-to-disassemble))
+      (funcall header-function function xfunction))
+    (let* ((seq 0)
+           (*previous-source-note* nil))
+      (declare (special *previous-source-note*))
+      (do-dll-nodes (block blocks)
+        (do-dll-nodes (instruction (x86-dis-block-instructions block))
+          (setq seq (funcall collect-function ds instruction seq function)))))))
+
+(defun x86-xdisassemble (function
+                         &optional (collect-function #'x86-print-disassembled-instruction)
+                                   (header-function #'x86-print-disassembled-function-header))
+  (let* ((fv (function-to-function-vector function))
+         (function-size-in-words (uvsize fv))
+         (code-words (%function-code-words function))
+         (ncode-bytes (ash function-size-in-words target::word-shift))
+         (code-bytes (make-array ncode-bytes
+                                 :element-type '(unsigned-byte 8)))
+         (numimms (- function-size-in-words code-words))
+         (xfunction (%alloc-misc (the fixnum (1+ numimms)) target::subtag-xfunction)))
+    (declare (fixnum code-words ncode-bytes numimms))
+    (%copy-ivector-to-ivector fv 0 code-bytes 0 ncode-bytes)
+    (setf (uvref xfunction 0) code-bytes)
+    (do* ((k code-words (1+ k))
+          (j 1 (1+ j)))
+         ((= k function-size-in-words)
+          (x86-disassemble-xfunction function xfunction
+                                     :collect-function collect-function
+                                     :header-function header-function))
+      (declare (fixnum j k))
+      (setf (uvref xfunction j) (uvref fv k)))))
+
+(defun disassemble-list (function)
+  (collect ((instructions))
+    (x86-xdisassemble
+     function
+     #'(lambda (ds instruction seq function)
+         (declare (ignore function))
+         (collect ((insn))
+           (let* ((addr (x86-di-address instruction))
+                  (entry (x86-ds-entry-point ds))
+                  (rpc (- addr entry)))
+             (if (x86-di-labeled instruction)
+               (progn
+                 (insn `(label ,rpc))
+                 (setq seq 0))
+               (insn rpc))
+             (dolist (p (x86-di-prefixes instruction))
+               (insn p))
+             (insn (x86-di-mnemonic instruction))
+             (let* ((op0 (x86-di-op0 instruction))
+                    (op1 (x86-di-op1 instruction))
+                    (op2 (x86-di-op2 instruction)))
+               (when op0
+                 (insn (unparse-x86-lap-operand op0 ds))
+                 (when op1
+                   (insn (unparse-x86-lap-operand op1 ds))
+                   (when op2
+                     (insn (unparse-x86-lap-operand op2 ds))  ))))
+             (instructions (insn))
+             (1+ seq))))
+     nil)
+    (instructions)))
+
+(defun x86-disassembled-instruction-line (ds instruction function &optional string-stream)
+  (if (null string-stream)
+    (with-output-to-string (stream)
+      (return-from x86-disassembled-instruction-line
+                   (x86-disassembled-instruction-line ds instruction function stream)))
+    (let* ((addr (x86-di-address instruction))
+           (entry (x86-ds-entry-point ds))
+           (pc (- addr entry))
+           (op0 (x86-di-op0 instruction))
+           (op1 (x86-di-op1 instruction))
+           (op2 (x86-di-op2 instruction))
+           (label (if (x86-di-labeled instruction) (list :label pc) pc))
+           (instr (progn
+                    (dolist (p (x86-di-prefixes instruction))
+                      (format string-stream "(~a) " p))
+                    (format string-stream "(~a" (x86-di-mnemonic instruction))
+                    (when op0 (write-x86-lap-operand string-stream op0 ds))
+                    (when op1 (write-x86-lap-operand string-stream op1 ds))
+                    (when op2 (write-x86-lap-operand string-stream op2 ds))
+                    (format string-stream ")")
+                    (get-output-stream-string string-stream)))
+           (comment (let ((source-note (find-source-note-at-pc function pc)))
+                      (unless (eql (source-note-file-range source-note)
+                                   (source-note-file-range *previous-source-note*))
+                        (setf *previous-source-note* source-note)
+                        (let* ((source-text (source-note-text source-note))
+                               (text (if source-text
+                                       (string-sans-most-whitespace source-text 100)
+                                       "#<no source text>")))
+                          (format string-stream ";;; ~A" text)
+                          (get-output-stream-string string-stream)))))
+           (imms (let ((imms nil))
+                   (multiple-value-bind (imm foundp) (x86-lap-operand-constant op2 ds)
+                     (when foundp (push imm imms)))
+                   (multiple-value-bind (imm foundp) (x86-lap-operand-constant op1 ds)
+                     (when foundp (push imm imms)))
+                   (multiple-value-bind (imm foundp) (x86-lap-operand-constant op0 ds)
+                     (when foundp (push imm imms)))
+                   imms)))
+      ;; Subtle difference between no imms and a single NIL imm, so if anybody ever
+      ;; cares for some reason, they could distinguish the two cases.
+      (if imms
+        (values comment label instr (if (cdr imms) (coerce imms 'vector) (car imms)))
+        (values comment label instr)))))
+
+(defun disassemble-lines (function)
+  (let ((source-note (function-source-note function)))
+    (when source-note
+      ;; Fetch source from file if don't already have it.
+      (ensure-source-note-text source-note)))
+  (let ((lines (make-array 20 :adjustable t :fill-pointer 0)))
+    (with-output-to-string (stream)
+      (x86-xdisassemble
+       function
+       #'(lambda (ds instruction seq function)
+           (declare (ignore seq))
+           (multiple-value-bind (comment label instr object)
+                                (x86-disassembled-instruction-line ds instruction function stream)
+             (when comment
+               (vector-push-extend comment lines))
+             (vector-push-extend (list object label instr) lines)))
+       nil))
+    (coerce lines 'simple-vector)))
Index: /branches/new-random/compiler/X86/x86-lap.lisp
===================================================================
--- /branches/new-random/compiler/X86/x86-lap.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/x86-lap.lisp	(revision 13309)
@@ -0,0 +1,1665 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(require "X86-ASM")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "DLL-NODE"))
+
+(def-standard-initial-binding *x86-lap-label-freelist* (make-dll-node-freelist))
+
+(def-standard-initial-binding *x86-lap-frag-vector-freelist* (%cons-pool))
+
+(defun %allocate-vector-list-segment ()
+  (without-interrupts
+   (let* ((data (pool.data *x86-lap-frag-vector-freelist*)))
+     (if data
+       (progn
+         (when (null (list-length data))
+           (compiler-bug "frag-vector freelist is circular"))
+         (setf (pool.data *x86-lap-frag-vector-freelist*) (cdr data))
+         (rplacd data nil))
+       (cons (make-array 24 :element-type '(unsigned-byte 8)) nil)))))
+
+(defun %free-vector-list-segment (segment)
+  (without-interrupts
+   (setf (pool.data *x86-lap-frag-vector-freelist*)
+         (nconc segment (pool.data *x86-lap-frag-vector-freelist*)))))
+
+(defun %vector-list-ref (vector-list index)
+  (do* ((i index (- i len))
+        (vl vector-list (cdr vl))
+        (v (car vl) (car vl))
+        (len (length v) (length v)))
+       ((null vl) (error "Index ~s is out of bounds for ~s" index vector-list))
+    (if (< i len)
+      (return (aref v i)))))
+
+(defun (setf %vector-list-ref) (new vector-list index)
+  (do* ((i index (- i len))
+        (vl vector-list (cdr vl))
+        (v (car vl) (car vl))
+        (len (length v) (length v)))
+       ((< i len) (setf (aref v i) new))
+    (when (null (cdr vl))
+      (setf (cdr vl) (%allocate-vector-list-segment)))))
+
+(defun %truncate-vector-list (vector-list newlen)
+  (do* ((vl vector-list (cdr vl))
+        (v (car vl) (car vl))
+        (len (length v) (length v))
+        (total len (+ total len)))
+       ((null (cdr vl)))
+    (when (> total newlen)
+      (%free-vector-list-segment (cdr vl))
+      (return (setf (cdr vl) nil)))))
+        
+  
+
+
+
+(eval-when (:execute :load-toplevel)
+
+  (defstruct (x86-lap-note (:include ccl::dll-node))
+    peer
+    id)
+
+  (defstruct (x86-lap-note-begin (:include x86-lap-note)))
+  (defstruct (x86-lap-note-end (:include x86-lap-note)))
+    
+  (defstruct (x86-lap-label (:constructor %%make-x86-lap-label (name)))
+    name
+    frag
+    offset
+    )
+
+  (defstruct (frag (:include ccl::dll-node)
+                   (:constructor %make-frag))
+    address
+    last-address                        ; address may change during relax
+    type                                ; nil, or (:TYPE &rest args)
+    relocs                              ; relocations against this frag
+    (position 0)                        ; position in code-buffer
+    (code-buffer (%allocate-vector-list-segment))     ; a VECTOR-LIST
+    labels                              ; labels defined in this frag
+    ))
+
+(def-standard-initial-binding *frag-freelist* (make-dll-node-freelist))
+
+
+(defun frag-push-byte (frag b)
+  (let* ((pos (frag-position frag)))
+    (setf (%vector-list-ref (frag-code-buffer frag) pos) b
+          (frag-position frag) (1+ pos))
+    b))
+
+(defun frag-ref (frag index)
+  (%vector-list-ref (frag-code-buffer frag) index))
+
+(defun (setf frag-ref) (new frag index)
+  (setf (%vector-list-ref (frag-code-buffer frag) index) new))
+
+;;; get/set little-endian 32 bit word in frag at index
+(defun frag-ref-32 (frag index)
+  (let ((result 0))
+    (setf (ldb (byte 8 0) result) (frag-ref frag index)
+	  (ldb (byte 8 8) result) (frag-ref frag (+ index 1))
+	  (ldb (byte 8 16) result) (frag-ref frag (+ index 2))
+	  (ldb (byte 8 24) result) (frag-ref frag (+ index 3)))
+    result))
+
+(defun (setf frag-ref-32) (new frag index)
+  (setf (frag-ref frag index) (ldb (byte 8 0) new)
+	(frag-ref frag (+ index 1)) (ldb (byte 8 8) new)
+	(frag-ref frag (+ index 2)) (ldb (byte 8 16) new)
+	(frag-ref frag (+ index 3)) (ldb (byte 8 24) new)))
+
+(defun frag-length (frag)
+  (frag-position frag))
+
+(defun (setf frag-length) (new frag)
+  (%truncate-vector-list (frag-code-buffer frag) new)
+  (setf (frag-position frag) new))
+
+
+;;; Push 1, 2, 4, or 8 bytes onto the frag-list's current-frag's buffer.
+;;; (If pushing more than one byte, do so in little-endian order.)
+(defun frag-list-push-byte (frag-list b)
+  (frag-push-byte (frag-list-current frag-list) b))
+
+(defun frag-list-push-16 (frag-list w)
+  (let* ((frag (frag-list-current frag-list)))
+    (frag-push-byte frag (ldb (byte 8 0) w))
+    (frag-push-byte frag (ldb (byte 8 8) w))))
+
+(defun frag-list-push-32 (frag-list w)
+  (let* ((frag (frag-list-current frag-list)))
+    (frag-push-byte frag (ldb (byte 8 0) w))
+    (frag-push-byte frag (ldb (byte 8 8) w))
+    (frag-push-byte frag (ldb (byte 8 16) w))
+    (frag-push-byte frag (ldb (byte 8 24) w))
+    w))
+
+(defun frag-list-push-64 (frag-list w)
+  (let* ((frag (frag-list-current frag-list)))
+    (frag-push-byte frag (ldb (byte 8 0) w))
+    (frag-push-byte frag (ldb (byte 8 8) w))
+    (frag-push-byte frag (ldb (byte 8 16) w))
+    (frag-push-byte frag (ldb (byte 8 24) w))
+    (frag-push-byte frag (ldb (byte 8 32) w))
+    (frag-push-byte frag (ldb (byte 8 40) w))
+    (frag-push-byte frag (ldb (byte 8 48) w))
+    (frag-push-byte frag (ldb (byte 8 56) w))
+    w))
+
+;;; Returns the length of the current frag
+(defun frag-list-position (frag-list)
+  (frag-length (frag-list-current frag-list)))
+
+(defun frag-output-bytes (frag target target-offset)
+  (let* ((buffer (frag-code-buffer frag))
+         (n (frag-length frag))
+         (remain n))
+    (loop
+      (when (zerop remain) (return n))
+      (let* ((v (pop buffer))
+             (len (length v))
+             (nout (min remain len)))
+        (%copy-ivector-to-ivector v
+                                  0
+                                  target
+                                  target-offset
+                                  nout)
+        (incf target-offset nout)
+        (decf remain nout)))))
+
+(defun make-frag ()
+  (let* ((frag (alloc-dll-node *frag-freelist*)))
+    (if frag
+      (let* ((buffer (frag-code-buffer frag)))
+        (when buffer
+          (setf (frag-length frag) 0))
+        (setf (frag-address frag) nil
+              (frag-last-address frag) nil
+              (frag-type frag) nil
+              (frag-relocs frag) nil
+              (frag-labels frag) nil)
+        frag)
+      (%make-frag))))
+  
+
+;;; Intentionally very similar to RISC-LAP, but with some extensions
+;;; to deal with alignment and with variable-length and/or span-
+;;; dependent instructions.
+
+(defvar *x86-lap-labels* ())
+(defvar *x86-lap-constants* ())
+(defparameter *x86-lap-entry-offset* nil)
+(defparameter *x86-lap-fixed-code-words* nil)
+(defvar *x86-lap-lfun-bits* 0)
+
+(defun x86-lap-macro-function (name)
+  (gethash (string name) (backend-lap-macros *target-backend*)))
+
+(defun (setf x86-lap-macro-function) (def name)
+  (let* ((s (string name)))
+    (when (gethash s x86::*x86-opcode-template-lists*)
+      (error "~s already defines an x86 instruction." name))
+    (setf (gethash s (backend-lap-macros *target-backend*)) def)))
+
+(defmacro defx86lapmacro (name arglist &body body)
+  `(progn
+     (setf (x86-lap-macro-function ',name)
+           (nfunction (x86-lap-macro ,name) ,(ccl::parse-macro name arglist body)))
+     (record-source-file ',name 'x86-lap)
+     ',name))
+
+(defun x86-lap-macroexpand-1 (form)
+  (unless (and (consp form) (atom (car form)))
+    (values form nil))
+  (let* ((expander (x86-lap-macro-function (car form))))
+    (if expander
+      (values (funcall expander form nil) t)
+      (values form nil))))
+
+
+(defmethod print-object ((l x86-lap-label) stream)
+  (print-unreadable-object (l stream :type t)
+    (format stream "~a" (x86-lap-label-name l))))
+
+;;; Labels
+
+(defun %make-x86-lap-label (name)
+  (let* ((lab (alloc-dll-node *x86-lap-label-freelist*)))
+    (if lab
+      (progn
+        (setf (x86-lap-label-frag lab) nil
+              (x86-lap-label-offset lab) nil
+              (x86-lap-label-name lab) name)
+        lab)
+      (%%make-x86-lap-label name))))
+  
+(defun make-x86-lap-label (name)
+  (let* ((lab (%make-x86-lap-label name)))
+    (if (typep *x86-lap-labels* 'hash-table)
+      (setf (gethash name *x86-lap-labels*) lab)
+      (progn
+        (push lab *x86-lap-labels*)
+        (if (> (length *x86-lap-labels*) 255)
+          (let* ((hash (make-hash-table :size 512 :test #'eq)))
+            (dolist (l *x86-lap-labels* (setq *x86-lap-labels* hash))
+              (setf (gethash (x86-lap-label-name l) hash) l))))))
+    lab))
+
+(defun find-x86-lap-label (name)
+  (if (typep *x86-lap-labels* 'hash-table)
+    (gethash name *x86-lap-labels*)
+    (car (member name *x86-lap-labels* :test #'eq :key #'x86-lap-label-name))))
+
+(defun find-or-create-x86-lap-label (name)
+  (or (find-x86-lap-label name)
+      (make-x86-lap-label name)))
+
+
+;;; A label can only be emitted once.  Once it's been emitted, its frag
+;;; slot will be non-nil.
+
+(defun x86-lap-label-emitted-p (lab)
+  (not (null (x86-lap-label-frag lab))))
+
+(defun emit-x86-lap-label (frag-list name)
+  (let* ((lab (find-or-create-x86-lap-label name))
+         (current (frag-list-current frag-list)))
+    (when (x86-lap-label-emitted-p lab)
+      (error "Label ~s: multiply defined." name))
+    (setf (x86-lap-label-frag lab) current
+          (x86-lap-label-offset lab) (frag-list-position frag-list))
+    (push lab (frag-labels current))
+    lab))
+
+
+
+
+
+(defstruct reloc
+  type                                  ; a keyword
+  arg                                   ; a label-operand or an expression, etc.
+  frag                                  ; the (redundant) containing frag
+  pos                                   ; octet position withing frag
+  )
+
+
+
+
+(defstruct (frag-list (:include ccl::dll-header) (:constructor nil)))
+
+;;; ccl::dll-header-last is unit-time
+(defun frag-list-current (frag-list)
+  (ccl::dll-header-last frag-list))
+
+;;; Add a new (empty) frag to the end of FRAG-LIST and make the new frag
+;;; current
+(defun new-frag (frag-list)
+  (ccl::append-dll-node (make-frag) frag-list))
+
+;;; Make a frag list, and make an empty frag be its current frag.
+(defun make-frag-list ()
+  (let* ((header (ccl::make-dll-header)))         
+    (new-frag header)
+    header))
+
+
+
+;;; Finish the current frag, marking it as containing a PC-relative
+;;; branch to the indicated label, with a one-byte opcode and
+;;; one byte of displacement.
+(defun finish-frag-for-branch (frag-list opcode label)
+  (let* ((frag (frag-list-current frag-list)))
+    (frag-push-byte frag opcode)
+    (let* ((pos (frag-length frag))
+           (reloc (make-reloc :type :branch8
+                              :arg label
+                              :pos pos)))
+      (push reloc (frag-relocs frag))
+      (frag-push-byte frag 0)
+      (setf (frag-type frag) (list (if (eql opcode #xeb)
+                                     :assumed-short-branch
+                                     :assumed-short-conditional-branch)
+                                   label
+                                   pos
+                                   reloc))
+      (new-frag frag-list))))
+
+;;; Mark the current frag as -ending- with an align directive.
+;;; p2align is the power of 2 at which code in the next frag
+;;; should be aligned.
+;;; Start a new frag.
+(defun finish-frag-for-align (frag-list p2align)
+  (let* ((frag (frag-list-current frag-list)))
+    (setf (frag-type frag) (list :align p2align))
+    (new-frag frag-list)))
+
+;;; Make the current frag be of type :talign; set that frag-type's
+;;; argument to NIL initially.  Start a new frag of type :pending-talign;
+;;; that frag will contain at most one instruction.  When an
+;;; instuction is ouput in the pending-talign frag, adjust the preceding
+;;; :talign frag's argument and set the type of the :pending-talign
+;;; frag to NIL.  (The :talign frag will have 0-7 NOPs of some form
+;;; appended to it, so the first instruction in the successor will end
+;;; on an address that matches the argument below.)
+;;; That instruction can not be a relaxable branch.
+(defun finish-frag-for-talign (frag-list arg)
+  (let* ((current (frag-list-current frag-list))
+         (new (new-frag frag-list)))
+    (setf (frag-type current) (list :talign nil))
+    (setf (frag-type new) (list :pending-talign arg))))
+
+;;; Having generated an instruction in a :pending-talign frag, set the
+;;; frag-type argument of the preceding :talign frag to the :pendint-talign
+;;; frag's argument - the length of the pending-talign's first instruction
+;;; mod 8, and clear the type of the "pending" frag.
+;;; cadr of the frag-type 
+(defun finish-pending-talign-frag (frag-list)
+  (let* ((frag (frag-list-current frag-list))
+         (pred (frag-pred frag))
+         (arg (cadr (frag-type frag)))
+         (pred-arg (frag-type pred)))
+    (setf (cadr pred-arg) (logand 7 (- arg (frag-length frag)))
+          (frag-type frag) nil)
+    (new-frag frag-list)))
+
+(defun finish-frag-for-org (frag-list org)
+  (let* ((frag (frag-list-current frag-list)))
+    (setf (frag-type frag) (list :org org))
+    (new-frag frag-list)))
+
+
+(defun lookup-x86-register (regname designator)
+  (let* ((registers (target-arch-case (:x8632 x86::*x8632-registers*)
+				      (:x8664 x86::*x8664-registers*)))
+	 (register-entries (target-arch-case (:x8632 x86::*x8632-register-entries*)
+					     (:x8664 x86::*x8664-register-entries*)))
+	 (r (typecase regname
+              (symbol (or (gethash (string regname) registers)
+                          (if (eq regname :rcontext)
+                            (svref register-entries
+                                   (ccl::backend-lisp-context-register *target-backend*)))
+                          (and (boundp regname)
+                               (let* ((val (symbol-value regname)))
+                                 (and (typep val 'fixnum)
+                                      (>= val 0)
+                                      (< val (length register-entries))
+                                      (svref register-entries val))))))
+              (string (gethash regname registers))
+              (fixnum (if (and (typep regname 'fixnum)
+                                      (>= regname 0)
+                                      (< regname (length register-entries)))
+                        (svref register-entries regname))))))
+                               
+    (when r
+      (if (eq designator :%)
+        r
+        (let* ((regtype (x86::reg-entry-reg-type r))
+	       (oktypes (target-arch-case
+			(:x8632 (x86::encode-operand-type :reg8 :reg16 :reg32))
+			(:x8664 (x86::encode-operand-type :reg8 :reg16 :reg32 :reg64)))))
+          (unless (logtest regtype oktypes)
+            (error "Designator ~a can't be used with register ~a"
+                   designator (x86::reg-entry-reg-name r)))
+          (case designator
+            (:%b (if (x86-byte-reg-p (x86::reg-entry-reg-name r))
+		   (x86::x86-reg8 r)
+		   (error "Designator ~a can't be used with register ~a"
+			  designator (x86::reg-entry-reg-name r))))
+            (:%w (x86::x86-reg16 r))
+            (:%l (x86::x86-reg32 r))
+            (:%q (x86::x86-reg64 r))))))))
+
+(defun x86-register-ordinal-or-expression (form)
+  (let* ((r (if (typep form 'symbol)
+              (lookup-x86-register form :%))))
+    (if r
+      (target-arch-case (:x8632 (x86::reg-entry-ordinal32 r))
+			(:x8664 (x86::reg-entry-ordinal64 r)))
+      (multiple-value-bind (val condition)
+          (ignore-errors (eval form))
+        (if condition
+          (error "Condition ~a signaled during assembly-time evalation of ~s."
+                 condition form)
+          val)))))
+
+(defun x86-acc-reg-p (regname)
+  (let ((r (lookup-x86-register regname :%)))
+    (if r
+      (logtest (x86::encode-operand-type :acc) (x86::reg-entry-reg-type r)))))
+
+(defun x86-byte-reg-p (regname)
+  (let ((r (lookup-x86-register regname :%)))
+    (if r
+      (target-arch-case
+       (:x8632
+	(or (<= (x86::reg-entry-reg-num r) x8632::ebx)
+	    (member (x86::reg-entry-reg-name r) '("ah" "ch" "dh" "bh") :test #'string=)))
+       (:x8664 t)))))
+      
+;;; It may seem strange to have an expression language in a lisp-based
+;;; assembler, since lisp is itself a fairly reasonable expression
+;;; language and EVAL is (in this context, at least) an adequate evaluation
+;;; mechanism.  This may indeed be overkill, but there are reasons for
+;;; wanting something beyond EVAL.
+;;; This assumes that any expression that doesn't involve label addresses
+;;; will always evaluate to the same value (in "the same" execution context).
+;;; Expressions that do involve label references might only be evaluable
+;;; after all labels are defined, and the value of such an expression may
+;;; change (as label addresses are adjusted.)
+
+;;; A "label address expression" looks like (:^ lab), syntactically.  Tree-walk
+;;; FORM, and return T if it contains a label address expression.
+
+(defun label-address-expression-p (form)
+  (and (consp form)
+       (eq (car form) :^)
+       (consp (cdr form))
+       (null (cddr form))))
+
+(defun contains-label-address-expression (form)
+  (cond ((label-address-expression-p form) t)
+        ((typep form 'application-x86-lap-expression) t)
+        ((atom form) nil)
+        (t (dolist (sub (cdr form))
+              (when (contains-label-address-expression sub)
+                (return t))))))
+
+(defstruct x86-lap-expression
+  )
+
+
+(defstruct (label-x86-lap-expression (:include x86-lap-expression))
+  label)
+
+
+;;; Represents a constant
+(defstruct (constant-x86-lap-expression (:include x86-lap-expression))
+  value)
+
+
+
+;;; Also support 0, 1, 2, and many args, where at least one of those args
+;;; is or contains a label reference.
+(defstruct (application-x86-lap-expression (:include x86-lap-expression))
+  operator)
+
+
+(defstruct (unary-x86-lap-expression (:include application-x86-lap-expression))
+  operand)
+
+
+(defstruct (binary-x86-lap-expression (:include application-x86-lap-expression))
+  operand0
+  operand1)
+
+(defstruct (n-ary-x86-lap-expression (:include application-x86-lap-expression))
+  operands)
+
+;;; Looks like a job for DEFMETHOD.
+(defun x86-lap-expression-value (exp)
+  (typecase exp
+    (label-x86-lap-expression (- (x86-lap-label-address (label-x86-lap-expression-label exp)) *x86-lap-entry-offset*))
+    (unary-x86-lap-expression (funcall (unary-x86-lap-expression-operator exp)
+                                       (x86-lap-expression-value (unary-x86-lap-expression-operand exp))))
+    (binary-x86-lap-expression (funcall (binary-x86-lap-expression-operator exp) 
+                                        (x86-lap-expression-value (binary-x86-lap-expression-operand0 exp))
+                                        (x86-lap-expression-value (binary-x86-lap-expression-operand1 exp))))
+    (n-ary-x86-lap-expression (apply (n-ary-x86-lap-expression-operator exp)
+                                     (mapcar #'x86-lap-expression-value (n-ary-x86-lap-expression-operands exp))))
+    (constant-x86-lap-expression (constant-x86-lap-expression-value exp))
+    (t exp)))
+
+;;; Expression might contain unresolved labels.  Return nil if so (even
+;;; if everything -could- be resolved.)
+(defun early-x86-lap-expression-value (expression)
+  (typecase expression
+    (constant-x86-lap-expression (constant-x86-lap-expression-value expression))
+    (x86-lap-expression nil)
+    (t expression)))
+
+(define-condition undefined-x86-lap-label (simple-program-error)
+  ((label-name :initarg :label-name))
+  (:report (lambda (c s)
+             (format s "Label ~s was referenced but not defined."
+                     (slot-value c 'label-name)))))
+
+(defun x86-lap-label-address (lab)
+  (let* ((frag (or (x86-lap-label-frag lab)
+                   (error 'undefined-x86-lap-label :label-name (x86-lap-label-name lab)))))
+    (+ (frag-address frag)
+       (x86-lap-label-offset lab))))
+
+
+(defun ensure-x86-lap-constant-label (val)
+  (or (cdr (assoc val *x86-lap-constants*
+                  :test #'eq))
+      (let* ((label (make-x86-lap-label
+                     (gensym)))
+             (pair (cons val label)))
+        (push pair *x86-lap-constants*)
+        label)))
+
+(defun parse-x86-lap-expression (form)
+  (if (typep form 'x86-lap-expression)
+    form
+    (progn
+      (when (quoted-form-p form)
+        (let* ((val (cadr form)))
+          (if (typep val 'fixnum)
+	    (setq form (ash val (arch::target-fixnum-shift (backend-target-arch *target-backend*))))
+            (let* ((constant-label (ensure-x86-lap-constant-label val )))
+              (setq form `(:^ ,(x86-lap-label-name constant-label)))))))
+      (if (null form)
+        (setq form (arch::target-nil-value (backend-target-arch *target-backend*)))
+        (if (eq form t)
+          (setq form
+                (+ (arch::target-nil-value (backend-target-arch *target-backend*))
+                   (arch::target-t-offset  (backend-target-arch *target-backend*))))))
+      
+      (if (label-address-expression-p form)
+        (make-label-x86-lap-expression :label (find-or-create-x86-lap-label (cadr form)))
+        (if (contains-label-address-expression form)
+          (destructuring-bind (op &rest args) form
+            (case (length args)
+              (1 (make-unary-x86-lap-expression :operator op :operand (parse-x86-lap-expression (car args))))
+              (2 (make-binary-x86-lap-expression :operator op :operand0 (parse-x86-lap-expression (car args))
+                                                 :operand1 (parse-x86-lap-expression (cadr args))))
+              (t (make-n-ary-x86-lap-expression :operator op :operands (mapcar #'parse-x86-lap-expression args)))))
+          (multiple-value-bind (value condition)
+              (ignore-errors
+                (eval (if (atom form)
+                        form
+                        (cons (car form)
+                            (mapcar #'(lambda (x)
+                                        (if (typep x 'constant-x86-lap-expression)
+                                          (constant-x86-lap-expression-value
+                                           x)
+                                          x))
+                                    (cdr form))))))
+            (if condition
+              (error "~a signaled during assembly-time evaluation of form ~s" condition form)
+              value #|(make-constant-x86-lap-expression :value value)|#)))))))
+
+(defun parse-x86-register-operand (regname designator)
+  (let* ((r (lookup-x86-register regname designator)))
+    (if r
+      (x86::make-x86-register-operand :type (logandc2 (x86::reg-entry-reg-type r)
+                                                      (x86::encode-operand-type :baseIndex))
+                                 :entry r)
+      (error "Unknown X86 register ~s" regname))))
+
+(defun parse-x86-label-reference (name)
+  (let* ((lab (find-or-create-x86-lap-label name)))
+    (x86::make-x86-label-operand :type (x86::encode-operand-type :label)
+                                 :label lab)))
+
+
+
+(defun x86-register-designator (form)
+  (when (and (consp form)
+             (symbolp (car form)))
+    (let* ((sym (car form)))
+      (cond ((string= sym '%) :%)
+            ((string= sym '%b) :%b)
+            ((string= sym '%w) :%w)
+            ((string= sym '%l) :%l)
+            ((string= sym '%q) :%q)))))
+
+
+;;; Syntax is:
+;;; ([seg] [disp] [base] [index] [scale])
+;;; A [seg] by itself isn't too meaningful; the same is true
+;;; of a few other combinations.
+(defun parse-x86-memory-operand (form)
+  (flet ((register-operand-p (form)
+           (let* ((designator (x86-register-designator form)))
+             (when designator
+               (destructuring-bind (regname) (cdr form)
+                 (or (lookup-x86-register regname designator)
+                     (error "Unknown register ~s" regname)))))))
+  (let* ((seg nil)
+         (disp nil)
+         (base nil)
+         (index nil)
+         (scale nil))
+    (do* ((f form (cdr f)))
+         ((null f)
+          (if (or disp base index)
+            (progn
+              ;;(check-base-and-index-regs instruction base index)
+              (x86::make-x86-memory-operand 
+               :type (if (or base index)
+                       (if disp
+                         (logior (optimize-displacement-type disp)
+                                 (x86::encode-operand-type  :baseindex))
+                         (x86::encode-operand-type :baseindex))
+                       (optimize-displacement-type disp))
+               :seg seg
+               :disp disp
+               :base base
+               :index index
+               :scale scale))
+            (error "No displacement, base,  or index in ~s" form)))
+      (let* ((head (car f))
+             (r (register-operand-p head)))
+        (if r
+          (if (logtest (x86::reg-entry-reg-type r)
+                       (x86::encode-operand-type :sreg2 :sreg3))
+            ;; A segment register - if present - must be first
+            (if (eq f form)
+              (setq seg (svref x86::*x86-seg-entries* (x86::reg-entry-reg-num r))) 
+              (error "Segment register ~s not valid in ~s" head form))
+            ;; Some other register.  Assume base if this is the
+            ;; first gpr.  If we find only one gpr and a significant
+            ;; scale factor, make that single gpr be the index.
+            (if base
+              (if index
+                (error "Extra register ~s in memory address ~s" head form)
+                (setq index r))
+              (setq base r)))
+          ;; Not a register, so head is either a displacement or
+          ;; a scale factor.
+          (if (and (null (cdr f))
+                   (or disp base index))
+            (let* ((exp (parse-x86-lap-expression head))
+                   (val (if (or (typep exp 'constant-x86-lap-expression)
+                                (not (x86-lap-expression-p exp)))
+                          (x86-lap-expression-value exp))))
+              (case val
+                ((1 2 4 8)
+                 (if (and base (not index))
+                   (setq index base base nil))
+                 (setq scale (1- (integer-length val))))
+                (t
+                 (error "Invalid scale factor ~s in ~s" head form))))
+            (if (not (or disp base index))
+              (setq disp (parse-x86-lap-expression head))
+              (error "~&~s not expected in ~s" head form)))))))))
+
+     
+    
+
+;;; Operand syntax:
+;;; (% x) -> register
+;;; ($ x) -> immediate
+;;; (@ x) -> memory operand
+;;; (:rcontext x) -> memory operand, using segment register or gpr
+;;; (:self fn) -> self-reference
+;;; x -> labelref
+(defun parse-x86-operand (form)
+  (if (consp form)
+    (let* ((head (car form))
+           (designator nil))
+      (if (symbolp head)
+        (cond ((string= head '$)
+               (destructuring-bind (immval) (cdr form)
+                 (let* ((expr (parse-x86-lap-expression immval))
+                        (val (early-x86-lap-expression-value expr))
+                        (type (if val
+                                (smallest-imm-type val)
+                                (x86::encode-operand-type :imm32s))))
+		   ;; special case
+		   (when (eq val :self)
+		     (setq type (x86::encode-operand-type :self)))
+                   (x86::make-x86-immediate-operand :type type
+                                                    :value expr))))
+              ((eq head :rcontext)
+               (if (>= (backend-lisp-context-register *target-backend*)
+                       (target-arch-case
+                        (:x8632 x86::+x8632-segment-register-offset+)
+                        (:x8664 x86::+x8664-segment-register-offset+)))
+                 (parse-x86-memory-operand `((% :rcontext) ,(cadr form)))
+                 (parse-x86-memory-operand `(,(cadr form) (% :rcontext)))))
+              ((setq designator (x86-register-designator form))
+               (destructuring-bind (reg) (cdr form)
+                 (parse-x86-register-operand reg designator)))
+              ((string= head '@)
+               (parse-x86-memory-operand  (cdr form)))
+              (t (error "unknown X86 operand: ~s" form)))
+        (error "unknown X86 operand: ~s" form)))
+    ;; Treat an atom as a label.
+    (parse-x86-label-reference form)))
+
+
+
+
+;;; Initialize some fields in the instruction from the template;
+;;; set other fields (which depend on operand values) to NIL.
+(defun set-x86-instruction-template (i template)
+  (setf (x86::x86-instruction-opcode-template i) template
+        (x86::x86-instruction-base-opcode i) (x86::x86-opcode-template-base-opcode template)
+        (x86::x86-instruction-modrm-byte i) (x86::x86-opcode-template-modrm-byte template)
+        (x86::x86-instruction-rex-prefix i) (target-arch-case
+					     (:x8632 nil)
+					     (:x8664
+					      (x86::x86-opcode-template-rex-prefix template)))
+        (x86::x86-instruction-sib-byte i) nil
+        (x86::x86-instruction-seg-prefix i) nil
+        (x86::x86-instruction-disp i) nil
+        (x86::x86-instruction-imm i) nil
+        (x86::x86-instruction-extra i) nil))
+
+
+(defun init-x86-instruction (instruction template parsed-operands)
+  (set-x86-instruction-template instruction template)
+  (let* ((insert-classes (x86::x86-opcode-template-operand-classes template))
+         (insert-functions x86::*x86-operand-insert-functions*))
+    (dotimes (i (length parsed-operands) instruction)
+      (funcall (svref insert-functions (svref insert-classes i))
+               instruction
+               (pop parsed-operands)))))
+
+
+
+(defun smallest-imm-type (val)
+  (if (eql val 1)
+    (x86::encode-operand-type :Imm1 :Imm8 :Imm8S :Imm16 :Imm32 :Imm32S :Imm64)
+    (typecase val
+      ((signed-byte 8)
+       (x86::encode-operand-type :Imm8S :imm8 :Imm16 :Imm32 :Imm32S :Imm64))
+      ((unsigned-byte 8)
+       (x86::encode-operand-type  :imm8 :Imm16 :Imm32 :Imm32S :Imm64))
+      ((signed-byte 16)
+       (x86::encode-operand-type  :Imm16 :Imm32 :Imm32S :Imm64))
+      ((unsigned-byte 16)
+       (x86::encode-operand-type  :Imm16 :Imm32 :Imm32S :Imm64))
+      ((signed-byte 32)
+       (x86::encode-operand-type :Imm32 :Imm32S :Imm64))
+      ((unsigned-byte 32)
+       (x86::encode-operand-type :Imm32 :Imm64))
+      (t (x86::encode-operand-type :Imm64)))))
+
+    
+(defun x86-optimize-imm (operands suffix)
+  (unless suffix
+    ;; See if we can determine an implied suffix from operands.
+    (do* ((i (1- (length operands)) (1- i)))
+         ((< i 0))
+      (declare (fixnum i))
+      (let* ((op (svref operands i))
+             (optype (x86::x86-operand-type op)))
+        (when (logtest optype (x86::encode-operand-type :reg))
+          (cond ((logtest optype (x86::encode-operand-type :reg8))
+                 (setq suffix #\b))
+                ((logtest optype (x86::encode-operand-type :reg16))
+                 (setq suffix #\w))
+                ((logtest optype (x86::encode-operand-type :reg32))
+                 (setq suffix #\l))
+                ((logtest optype (x86::encode-operand-type :reg64))
+                 (setq suffix #\q)))
+          (return)))))
+  (dotimes (i (length operands))
+    (let* ((op (svref operands i))
+           (optype (x86::x86-operand-type op)))
+      (when (logtest optype (x86::encode-operand-type :imm))
+        (let* ((val (x86::x86-immediate-operand-value op)))
+          (cond ((typep val 'constant-x86-lap-expression)
+                 (case suffix
+                   (#\l (setf (x86::x86-operand-type op)
+                              (logior optype (x86::encode-operand-type
+                                              :imm32 :imm64))))
+                   (#\w (setf (x86::x86-operand-type op)
+                              (logior optype (x86::encode-operand-type
+                                              :imm16 :imm32S  :imm32 :imm64))))
+                   (#\b (setf (x86::x86-operand-type op)
+                              (logior optype (x86::encode-operand-type
+                                              :imm8 :imm16 :imm32S  :imm32 :imm64)))))
+                 (setf (x86::x86-operand-type op)
+                       (logior (x86::x86-operand-type op)
+                               (smallest-imm-type (x86-lap-expression-value val))))
+                 (when (eql suffix #\q)
+                   (setf (x86::x86-operand-type op)
+                         (logandc2 (x86::x86-operand-type op)
+                                   (x86::encode-operand-type :imm32)))))
+                (t ; immediate value not constant
+                 (case suffix
+                   (#\q (setf (x86::x86-operand-type op)
+                              (logior optype
+                                      (x86::encode-operand-type :imm64 :imm32S))))
+                   (#\l (setf (x86::x86-operand-type op)
+                              (logior optype
+                                      (x86::encode-operand-type :imm32))))
+                   (#\w (setf (x86::x86-operand-type op)
+                              (logior optype
+                                      (x86::encode-operand-type :imm16))))
+                   (#\b  (setf (x86::x86-operand-type op)
+                              (logior optype
+                                      (x86::encode-operand-type :imm8))))))))))))
+
+(defun get-x86-opcode-templates (form)
+  (let* ((name (string (car form))))
+    (or
+     (gethash name x86::*x86-opcode-template-lists*)
+     ;; Try to determine a suffix, based on the size of the last
+     ;; register argument (if any.)  If that can be determined,
+     ;; tack it on to the end of NAME and try again.
+     (let* ((suffix nil))
+       (dolist (arg (cdr form))
+         (let* ((designator (x86-register-designator arg)))
+           (when designator
+             (destructuring-bind (regname) (cdr arg)
+               (let* ((reg (lookup-x86-register regname designator)))
+                 (when reg
+                   (let* ((type (x86::reg-entry-reg-type reg)))
+                     (cond ((logtest type (x86::encode-operand-type :reg8))
+                            (setq suffix #\b))
+                           ((logtest type (x86::encode-operand-type :reg16))
+                            (setq suffix #\w))
+                           ((logtest type (x86::encode-operand-type :reg32))
+                            (setq suffix #\l))
+                           ((logtest type (x86::encode-operand-type :reg64))
+                            (setq suffix #\q))))))))))
+       (when suffix
+         (let* ((n (length name))
+                (m (1+ n))
+                (s (make-string m)))
+           (declare (fixnum n m) (dynamic-extent s))
+           (dotimes (i n) (setf (schar s i) (char name i)))
+           (setf (schar s n) suffix)
+           (gethash s x86::*x86-opcode-template-lists*)))))))
+         
+                
+         
+     
+  
+;;; FORM is a list; its car doesn't name a macro or pseudo op.  If we
+;;; can find a matching opcode template, initialize the
+;;; x86-instruction with that template and these operands.
+;;; Note that this doesn't handle "prefix" instructions at all.
+;;; Things that would change the operand or address size are
+;;; of limited utility, as are REP* prefixes on string instructions
+;;; (because of the way that the lisp used %[E|R]DI and %[E|R]SI).
+;;; LOCK can be used in the preceding instruction.
+(defun parse-x86-instruction (form instruction)
+    (let* ((templates (or
+                       (get-x86-opcode-templates form)
+                       (error "Unknown X86 instruction ~s" form)))
+           (operands (cdr form)))
+      (let* ((parsed-operands (if operands
+                                (mapcar #'parse-x86-operand operands)))
+             (operand-types (mapcar #'x86::x86-operand-type parsed-operands))
+             (type0 (pop operand-types))
+             (type1 (pop operand-types))
+             (type2 (car operand-types)))
+
+        ;; (x86-optimize-imm parsed-operands suffix)
+        (dolist (template templates (error "Operands or suffix invalid in ~s" form))
+          (when (x86::match-template-types template type0 type1 type2)
+            (init-x86-instruction instruction template parsed-operands)
+            ;(check-suffix instruction form)
+            ;(x86-finalize-operand-types instruction)
+            (return instruction))))))
+
+
+
+
+              
+;;; xxx - might want to omit disp64 when doing 32 bit code
+(defun optimize-displacement-type (disp)
+  (if disp
+    (let* ((value (early-x86-lap-expression-value disp)))
+      (if value
+        (if (typep value '(signed-byte 8))
+          (x86::encode-operand-type :disp8 :disp32 :disp32s :disp64)
+          (if (typep value '(signed-byte 32))
+            (x86::encode-operand-type :disp32s :disp64)
+            (if (typep value '(unsigned-byte 32))
+              (x86::encode-operand-type :disp32 :disp64)
+              (x86::encode-operand-type :disp64))))
+        (x86::encode-operand-type :disp32s :disp64)))
+    0))
+
+(defun optimize-displacements (operands)
+  (dotimes (i (length operands))
+    (let* ((op (svref operands i)))
+      (when (typep op 'x86::x86-memory-operand)
+        (let* ((disp (x86::x86-memory-operand-disp op))
+               (val (if disp (early-x86-lap-expression-value disp))))
+          (if (typep val '(signed-byte 32))
+            (setf (x86::x86-operand-type op)
+                  (logior (x86::x86-operand-type op) (x86::encode-operand-type :disp32s))))
+          (if (typep val '(unsigned-byte 32))
+            (setf (x86::x86-operand-type op)
+                  (logior (x86::x86-operand-type op) (x86::encode-operand-type :disp32))))
+          (if (and (logtest (x86::x86-operand-type op)
+                            (x86::encode-operand-type :disp32 :disp32S :disp16))
+                   (typep val '(signed-byte 8)))
+            (setf (x86::x86-operand-type op)
+                  (logior (x86::x86-operand-type op) (x86::encode-operand-type :disp8)))))))))
+
+(defun x86-output-branch (frag-list insn)
+  (dolist (b (x86::x86-opcode-template-prefixes
+              (x86::x86-instruction-opcode-template insn)))
+    (when (or (= b x86::+data-prefix-opcode+)
+              (= b x86::+cs-prefix-opcode+)
+              (= b x86::+ds-prefix-opcode+))
+      (frag-list-push-byte frag-list b)))
+  (finish-frag-for-branch frag-list
+                          (x86::x86-instruction-base-opcode insn)
+                          (x86::x86-instruction-extra insn)))
+
+(defun x86-generate-instruction-code (frag-list insn)
+  (let* ((template (x86::x86-instruction-opcode-template insn))
+         (flags (x86::x86-opcode-template-flags template))
+         (prefixes (x86::x86-opcode-template-prefixes template)))
+    (let* ((explicit-seg-prefix (x86::x86-instruction-seg-prefix insn)))
+      (when explicit-seg-prefix
+        (push explicit-seg-prefix prefixes)))
+    (cond
+      ((logtest (x86::encode-opcode-flags :jump) flags)
+       ;; a variable-length pc-relative branch, possibly preceded
+       ;; by prefixes (used for branch prediction, mostly.)
+       (x86-output-branch frag-list insn))
+      (t
+       (let* ((base-opcode (x86::x86-instruction-base-opcode insn)))
+         (declare (fixnum base-opcode))
+         (dolist (b prefixes)
+           (frag-list-push-byte frag-list b))
+         (let* ((rex-bits (logand #x8f
+                                  (or (x86::x86-instruction-rex-prefix insn)
+                                      0))))
+           (declare (fixnum rex-bits))
+           (unless (= 0 rex-bits)
+             (frag-list-push-byte frag-list (logior #x40 (logand rex-bits #xf)))))
+         (when (logtest base-opcode #xff00)
+           (frag-list-push-byte frag-list (ldb (byte 8 8) base-opcode)))
+         (frag-list-push-byte frag-list (ldb (byte 8 0) base-opcode)))
+       (let* ((modrm (x86::x86-instruction-modrm-byte insn)))
+         (when modrm
+           (frag-list-push-byte frag-list modrm)
+           (let* ((sib (x86::x86-instruction-sib-byte insn)))
+             (when sib
+               (frag-list-push-byte frag-list sib)))))
+       (let* ((operands (x86::x86-opcode-template-operand-types template)))
+         (if (and (= (length operands) 1)
+                  (= (x86::encode-operand-type :label) (aref operands 0)))
+           (let* ((label (x86::x86-instruction-extra insn))
+                  (frag (frag-list-current frag-list))
+                  (pos (frag-list-position frag-list)))
+             (push (make-reloc :type :branch32
+                               :arg label
+                               :frag frag
+                               :pos pos)
+                   (frag-relocs frag))
+             (frag-list-push-32 frag-list 0))
+           (let* ((disp (x86::x86-instruction-disp insn)))
+             (when disp
+               (let* ((optype (x86::x86-instruction-extra insn))
+                      (pcrel (and (logtest (x86::encode-operand-type :label) optype)
+                              (typep disp 'label-x86-lap-expression)))
+                  (val (unless pcrel (early-x86-lap-expression-value disp))))
+             (if (null val)
+               ;; We can do better job here, but (for now)
+               ;; generate a 32-bit relocation
+               (let* ((frag (frag-list-current frag-list))
+                      (pos (frag-list-position frag-list)))
+                 (push (make-reloc :type (if pcrel :branch32 :expr32)
+                                   :arg (if pcrel (label-x86-lap-expression-label disp) disp)
+                                   :frag frag
+                                   :pos pos)
+                       (frag-relocs frag))
+                 (frag-list-push-32 frag-list 0))
+               (if (logtest optype (x86::encode-operand-type :disp8))
+                 (frag-list-push-byte frag-list (logand val #xff))
+                 (if (logtest optype (x86::encode-operand-type :disp32 :disp32s))
+                   (frag-list-push-32 frag-list val)
+                   (frag-list-push-64 frag-list val)))))))))
+       ;; Emit immediate operand(s).
+       (let* ((op (x86::x86-instruction-imm insn)))
+         (when op
+           (let* ((optype (x86::x86-operand-type op))
+                  (expr (x86::x86-immediate-operand-value op))
+                  (val (early-x86-lap-expression-value expr)))
+             (if (null val)
+               (let* ((frag (frag-list-current frag-list))
+                      (pos (frag-list-position frag-list))
+                      (size 4)
+                      (reloctype :expr32))
+                 (when (logtest optype
+                                (x86::encode-operand-type
+                                 :imm8 :imm8S :imm16 :imm64))
+                   (setq size 2 reloctype :expr16)
+                   (if (logtest optype (x86::encode-operand-type
+                                        :imm8 :imm8s))
+                     (setq size 1 reloctype :expr8)
+                     (if (logtest optype (x86::encode-operand-type :imm64))
+                       (setq size 8 reloctype :expr64))))
+                 (push (make-reloc :type reloctype
+                                   :arg expr
+                                   :frag frag
+                                   :pos pos)
+                       (frag-relocs frag))
+                 (dotimes (b size)
+                   (frag-list-push-byte frag-list 0)))
+               (if (logtest optype (x86::encode-operand-type :imm8 :imm8s))
+                 (frag-list-push-byte frag-list (logand val #xff))
+                 (if (logtest optype (x86::encode-operand-type :imm16))
+                   (frag-list-push-16 frag-list (logand val #xffff))
+                   (if (logtest optype (x86::encode-operand-type :imm64))
+                     (frag-list-push-64 frag-list val)
+		     ;; magic value denoting function object's
+		     ;; actual runtime address
+		     (if (logtest optype (x86::encode-operand-type :self))
+		       (let* ((frag (frag-list-current frag-list))
+			      (pos (frag-list-position frag-list)))
+			 (frag-list-push-32 frag-list 0)
+			 (push (make-reloc :type :self
+					   :arg 0
+					   :frag frag
+					   :pos pos)
+			       (frag-relocs frag)))
+		       (frag-list-push-32 frag-list val)))))))))))
+    (let* ((frag (frag-list-current frag-list)))
+      (if (eq (car (frag-type frag)) :pending-talign)
+        (finish-pending-talign-frag frag-list)))))
+
+;;; Returns the active frag list after processing directive(s).
+(defun x86-lap-directive (frag-list directive arg &optional main-frag-list exception-frag-list)
+  (declare (ignorable main-frag-list exception-frag-list))
+  (case directive
+    (:tra
+     (finish-frag-for-align frag-list 3)
+     (x86-lap-directive frag-list :long `(:^ ,arg))
+     (emit-x86-lap-label frag-list arg))
+    (:fixed-constants
+     (dolist (constant arg)
+       (ensure-x86-lap-constant-label constant)))
+    (:arglist (setq *x86-lap-lfun-bits* (encode-lambda-list arg)))
+    ((:uuo :uuo-section)
+     (if exception-frag-list
+       (progn
+         (setq frag-list exception-frag-list)
+         (finish-frag-for-align frag-list 2))))
+    ((:main :main-section)
+     (when main-frag-list (setq frag-list main-frag-list)))
+    (:anchored-uuo-section
+     (setq frag-list (x86-lap-directive frag-list :uuo-section nil main-frag-list exception-frag-list))
+     (setq frag-list (x86-lap-directive frag-list :long `(:^ ,arg) main-frag-list exception-frag-list)))
+    (t (let* ((exp (parse-x86-lap-expression arg))
+              (constantp (or (constant-x86-lap-expression-p exp)
+                             (not (x86-lap-expression-p exp)))))
+         
+         (if constantp
+           (let* ((val (x86-lap-expression-value exp)))
+             (ecase directive
+               (:code-size
+                (if *x86-lap-fixed-code-words*
+                  (error "Duplicate :CODE-SIZE directive")
+                  (setq *x86-lap-fixed-code-words* val)))
+               (:byte (frag-list-push-byte frag-list val))
+               (:short (frag-list-push-16 frag-list val))
+               (:long (frag-list-push-32 frag-list val))
+               (:quad (frag-list-push-64 frag-list val))
+               (:align (finish-frag-for-align frag-list val))
+               (:talign (finish-frag-for-talign frag-list val))
+               (:org (finish-frag-for-org frag-list val))))
+           (let* ((pos (frag-list-position frag-list))
+                  (frag (frag-list-current frag-list))
+                  (reloctype nil))
+             (ecase directive
+               (:byte (frag-list-push-byte frag-list 0)
+                      (setq reloctype :expr8))
+               (:short (frag-list-push-16 frag-list 0)
+                       (setq reloctype :expr16))
+               (:long (frag-list-push-32 frag-list 0)
+                      (setq reloctype :expr32))
+               (:quad (frag-list-push-64 frag-list 0)
+                      (setq reloctype :expr64))
+               (:align (error ":align expression ~s not constant" arg))
+               (:talign (error ":talign expression ~s not constant" arg)))
+             (when reloctype
+               (push
+                (make-reloc :type reloctype
+                            :arg exp
+                            :pos pos
+                            :frag frag)
+                (frag-relocs frag))))))))
+  frag-list)
+
+
+(defun x862-lap-process-regsave-info (frag-list regsave-label regsave-mask regsave-addr)
+  (when regsave-label
+    (let* ((label-diff (min (- (x86-lap-label-address regsave-label)
+                               *x86-lap-entry-offset*)
+                            255))
+           (first-frag (frag-list-succ frag-list)))
+      (setf (frag-ref first-frag 4) label-diff
+            (frag-ref first-frag 5) regsave-addr
+            (frag-ref first-frag 6) regsave-mask))
+    t))
+                       
+         
+
+(defun x86-lap-form (form frag-list instruction  main-frag-list exception-frag-list)
+  (if (and form (symbolp form))
+    (emit-x86-lap-label frag-list form)
+    (if (or (atom form) (not (symbolp (car form))))
+      (error "Unknown X86-LAP form ~s ." form)
+      (multiple-value-bind (expansion expanded)
+          (x86-lap-macroexpand-1 form)
+        (if expanded
+          (x86-lap-form expansion frag-list instruction main-frag-list exception-frag-list)
+          (if (typep (car form) 'keyword)
+            (destructuring-bind (op &optional arg) form
+              (setq frag-list (x86-lap-directive frag-list op arg main-frag-list exception-frag-list)))
+            (case (car form)
+              (progn
+                (dolist (f (cdr form))
+                  (setq frag-list (x86-lap-form f frag-list instruction main-frag-list exception-frag-list))))
+              (let
+                  (destructuring-bind (equates &body body)
+                      (cdr form)
+                    (setq frag-list (x86-lap-equate-form equates frag-list instruction body main-frag-list exception-frag-list))))
+              (t
+               (parse-x86-instruction form instruction)
+               (x86-generate-instruction-code frag-list instruction))))))))
+  frag-list)
+
+(defun relax-align (address bits)
+  (let* ((mask (1- (ash 1 bits))))
+    (- (logandc2 (+ address mask) mask) address)))
+
+(defun relax-talign (address mask)
+  (do* ((i 0 (1+ i)))
+       ((= (logand address 7) mask) i)
+    (incf address)))
+
+
+(defun relax-frag-list (frag-list)
+  ;; First, assign tentative addresses to all frags, assuming that
+  ;; span-dependent instructions have short displacements.
+  ;; While doing that, find branches to the next instruction and
+  ;; remove them.  In some cases, that'll cause the containing
+  ;; frag to become empty; that could introduce branches to the
+  ;; next instruction, so we repeat this process until we can
+  ;; make it all the way through the frag-list.
+  (loop
+    (let* ((address (target-arch-case (:x8632 4) (:x8664 8)))) ;after header
+      (declare (fixnum address))
+      (when (do-dll-nodes (frag frag-list t)
+              (setf (frag-address frag) address)
+              (incf address (frag-length frag))
+              (case (car (frag-type frag))
+                (:org
+                 ;; Do nothing, for now
+                 )
+                (:align
+                 (incf address (relax-align address (cadr (frag-type frag)))))
+                (:talign
+                 (let* ((arg (cadr (frag-type frag))))
+                   (if (null arg)
+                     ;;; Never generated code in :pending-talign frag
+                     (setf (frag-type frag) nil)
+                     (incf address (relax-talign address arg)))))
+                ((:assumed-short-branch :assumed-short-conditional-branch)
+                 (destructuring-bind (label pos reloc) (cdr (frag-type frag))
+                   (let* ((next (frag-succ frag)))
+                     (when (and (eq (x86-lap-label-frag label) next)
+                                (eql (x86-lap-label-offset label) 0))
+                       ;; Delete the reloc associated with this branch.
+                       (setf (frag-relocs frag)
+                             (delete reloc (frag-relocs frag)))
+                       ;; This will be a "normal" frag
+                       (setf (frag-type frag) nil)
+                       ;; Remove the (short) branch, and remove the frag
+                       ;; if it becomes empty.  If the frag does become
+                       ;; empty, migrate any labels to the next frag.
+                       (when (zerop (setf (frag-length frag)
+                                        (1- pos)))
+
+                         (do* ((labels (frag-labels frag)))
+                              ((null labels))
+                           (let* ((lab (pop labels)))
+                             (setf (x86-lap-label-frag lab) next
+                                   (x86-lap-label-offset lab) 0)
+                             (push lab (frag-labels next))))
+                         (remove-dll-node frag))
+                       (return nil)))))))
+        (return))))
+  ;; Repeatedly "stretch" frags containing span-dependent instructions
+  ;; until nothing's stretched.  It may take several iterations to
+  ;; converge; is convergence guaranteed ?
+  (loop
+    (let* ((stretch 0)                  ;cumulative growth in frag sizes
+           (stretched nil))             ;any change on this pass ?
+      (do-dll-nodes (frag frag-list)
+        (let* ((growth 0)
+               (fragtype (frag-type frag))
+               (was-address (frag-address frag))
+               (address (incf (frag-address frag) stretch)))
+          (case (car fragtype)
+            (:org
+             (let* ((target (cadr (frag-type frag)))
+                    (next-address (frag-address (frag-succ frag))))
+               (setq growth (- target next-address))
+               (if (< growth 0)
+                 (error "Code size exceeds :CODE-SIZE constraint ~s"
+                        (ash target -3))
+                 (decf growth stretch))))
+            (:align
+             (let* ((bits (cadr fragtype))
+                    (len (frag-length frag))
+                    (oldoff (relax-align (+ was-address len) bits))
+                    (newoff (relax-align (+ address len) bits)))
+               (setq growth (- newoff oldoff))))
+            (:talign
+             (let* ((arg (cadr fragtype))
+                    (len (frag-length frag))
+                    (oldoff (relax-talign (+ was-address len) arg))
+                    (newoff (relax-talign (+ address len) arg)))
+               (setq growth (- newoff oldoff))))
+            ;; If we discover - on any iteration - that a short
+            ;; branch doesn't fit, we change the type (and the reloc)
+            ;; destructively to a wide branch indicator and will
+            ;; never change our minds about that, so we only have
+            ;; to look here at conditional branches that may still
+            ;; be able to use a 1-byte displacement.
+            ((:assumed-short-branch :assumed-short-conditional-branch)
+             (destructuring-bind (label pos reloc) (cdr (frag-type frag))
+               (declare (fixnum pos))
+               (let* ((label-address (x86-lap-label-address label))
+                      (branch-pos (+ address (1+ pos)))
+                      (diff (- label-address branch-pos)))
+                 (unless (typep diff '(signed-byte 8))
+                   (cond ((eq (car fragtype) :assumed-short-branch)
+                          ;; replace the opcode byte
+                          (setf (frag-ref frag (the fixnum (1- pos)))
+                                x86::+jump-pc-relative+)
+                          (frag-push-byte frag 0)
+                          (frag-push-byte frag 0)
+                          (frag-push-byte frag 0)
+                          (setf (reloc-type reloc) :branch32)
+                          (setf (car fragtype) :long-branch)
+                          (setq growth 3))
+                         (t
+                          ;; Conditional branch: must change
+                          ;; 1-byte opcode to 2 bytes, add 4-byte
+                          ;; displacement
+                          (let* ((old-opcode (frag-ref frag (1- pos))))
+                            (setf (frag-ref frag (1- pos)) #x0f
+                                  (frag-ref frag pos) (+ old-opcode #x10))
+                            (frag-push-byte frag 0)
+                            (frag-push-byte frag 0)
+                            (frag-push-byte frag 0)
+                            (frag-push-byte frag 0)
+                            (setf (reloc-type reloc) :branch32
+                                  (reloc-pos reloc) (1+ pos))
+                            (setf (car fragtype) :long-conditional-branch
+                                  (caddr fragtype) (1+ pos))
+                            (setq growth 4)))))))))
+          (unless (eql 0 growth)
+            (incf stretch growth)
+            (setq stretched t))))
+      (unless stretched (return)))))
+
+(defun apply-relocs (frag-list)
+  (flet ((emit-byte (frag pos b)
+           (setf (frag-ref frag pos) (logand b #xff))))
+    (flet ((emit-short (frag pos s)
+             (setf (frag-ref frag pos) (ldb (byte 8 0) s)
+                   (frag-ref frag (1+ pos)) (ldb (byte 8 8) s))))
+      (flet ((emit-long (frag pos l)
+               (emit-short frag pos (ldb (byte 16 0) l))
+               (emit-short frag (+ pos 2) (ldb (byte 16 16) l))))
+        (flet ((emit-quad (frag pos q)
+                 (emit-long frag pos (ldb (byte 32 0) q))
+                 (emit-long frag (+ pos 4) (ldb (byte 32 32) q))))
+          (do-dll-nodes (frag frag-list)
+            (let* ((address (frag-address frag)))
+              (dolist (reloc (frag-relocs frag))
+                (let* ((pos (reloc-pos reloc))
+                       (arg (reloc-arg reloc)))
+                  (ecase (reloc-type reloc)
+                    (:branch8 (let* ((target (x86-lap-label-address arg))
+                                     (refpos (+ address (1+ pos))))
+                                (emit-byte frag pos (- target refpos))))
+                    (:branch32 (let* ((target (x86-lap-label-address arg))
+                                     (refpos (+ address pos 4)))
+                                (emit-long frag pos (- target refpos))))
+                    (:expr8 (emit-byte frag pos  (x86-lap-expression-value arg)))
+                    (:expr16 (emit-short frag pos (x86-lap-expression-value arg)))
+                    (:expr32 (emit-long frag pos (x86-lap-expression-value arg)))
+                    (:expr64 (emit-quad frag pos (x86-lap-expression-value arg)))
+		    (:self (emit-long frag pos (x86-lap-expression-value arg)))))))))))))
+
+(defstatic *x86-32-bit-lap-nops*
+  #(
+    #()
+    #(#x90)                             ; nop                  
+    #(#x89 #xf6)                        ; movl %esi,%esi       
+    #(#x8d #x76 #x00)                   ; leal 0(%esi),%esi    
+    #(#x8d #x74 #x26 #x00)              ; leal 0(%esi,1),%esi  
+    #(#x90 #x8d #x74 #x26 #x00)         ; nop ; leal 0(%esi,1),%esi  
+    #(#x8d #xb6 #x00 #x00 #x00 #x00)    ; leal 0L(%esi),%esi   
+    #(#x8d #xb4 #x26 #x00 #x00 #x00 #x00) ; leal 0L(%esi,1),%esi 
+  )
+  "Allegedly, many implementations recognize these instructions and
+execute them very quickly.")
+
+(defstatic *x86-32-bit-lap-nops-8*
+  #(#x90 #x8d #xb4 #x26 #x00 #x00 #x00 #x00))
+
+(defun frag-emit-nops (frag count)
+  (target-word-size-case
+   (32
+    (do* ((c count (- c 8)))
+         ((< c 8)
+          (let* ((v (svref *x86-32-bit-lap-nops* c)))
+            (dotimes (i c)
+              (frag-push-byte frag (svref v i)))))
+      (dotimes (i 8)
+        (frag-push-byte frag (svref *x86-32-bit-lap-nops-8* i)))))
+   (64
+    (let* ((nnops (ash (+ count 3) -2))
+           (len (floor count nnops))
+           (remains (- count (* nnops len))))
+      (dotimes (i remains)
+        (dotimes (k len) (frag-push-byte frag #x66))
+        (frag-push-byte frag #x90))
+      (do* ((i remains (1+ i)))
+           ((= i nnops))
+        (dotimes (k (1- len)) (frag-push-byte frag #x66))
+        (frag-push-byte frag #x90))))))
+  
+(defun fill-for-alignment (frag-list)
+  (ccl::do-dll-nodes (frag frag-list)
+    (let* ((next (ccl::dll-node-succ frag)))
+      (unless (eq next frag-list)
+        (let* ((addr (frag-address frag))
+               (nextaddr (frag-address next))
+               (pad (- nextaddr (+ addr (frag-length frag)))))
+          (unless (eql 0 pad)
+            (frag-emit-nops frag pad)))))))
+
+(defun show-frag-bytes (frag-list)
+  (ccl::do-dll-nodes (frag frag-list)
+    (format t "~& frag at #x~x" (frag-address frag))
+    (dotimes (i (frag-length frag))
+      (unless (logtest 15 i)
+        (format t "~&"))
+      (format t "~2,'0x " (frag-ref frag i)))))
+
+(defun x86-lap-equate-form (eqlist fraglist instruction  body main-frag exception-frag) 
+  (let* ((symbols (mapcar #'(lambda (x)
+                              (let* ((name (car x)))
+                                (or
+                                 (and name 
+                                      (symbolp name)
+                                      (not (constant-symbol-p name))
+                                      (or (not (gethash (string name)
+							(target-arch-case
+							 (:x8632 x86::*x8632-registers*)
+							 (:x8664 x86::*x8664-registers*))))
+                                          (error "Symbol ~s already names an x86 register" name))
+                                      name)
+                                 (error 
+                                  "~S is not a bindable symbol name ." name))))
+                          eqlist))
+         (values (mapcar #'(lambda (x) (x86-register-ordinal-or-expression
+                                        (cadr x)))
+                         eqlist)))
+    (progv symbols values
+      (dolist (form body fraglist)
+        (setq fraglist (x86-lap-form form fraglist instruction main-frag exception-frag))))))
+                
+(defun cross-create-x86-function (name frag-list constants bits debug-info)
+  (let* ((constants-vector (%alloc-misc (+ (length constants)
+                                           (+ 2
+                                              (if name 1 0)
+                                              (if debug-info 1 0)))
+                                        target::subtag-xfunction)))
+    (unless name (setq bits (logior bits (ash -1 $lfbits-noname-bit))))
+    (let* ((last (1- (uvsize constants-vector))))
+      (declare (fixnum last))
+      (setf (uvref constants-vector last) bits)
+      (when name
+        (setf (uvref constants-vector (decf last)) name))
+      (when debug-info
+        (setf (uvref constants-vector (decf last)) debug-info))
+      (dolist (c constants)
+        (setf (uvref constants-vector (decf last)) (car c)))
+      (let* ((nbytes 0))
+        (do-dll-nodes (frag frag-list)
+          (incf nbytes (frag-length frag)))
+	#+x8632-target
+	(when (>= nbytes (ash 1 18)) (compiler-function-overflow))
+        (let* ((code-vector (make-array nbytes
+                                        :element-type '(unsigned-byte 8)))
+               (target-offset 0))
+          (declare (fixnum target-offset))
+          (setf (uvref constants-vector 0) code-vector)
+          (do-dll-nodes (frag frag-list)
+            (incf target-offset (frag-output-bytes frag code-vector target-offset)))
+          constants-vector)))))
+
+#+x86-target
+(defun create-x86-function (name frag-list constants bits debug-info)
+  (unless name (setq bits (logior bits (ash -1 $lfbits-noname-bit))))
+  (let* ((code-bytes (let* ((nbytes 0))
+                       (do-dll-nodes (frag frag-list nbytes)
+                         (incf nbytes (frag-length frag)))))
+         (code-words (ash code-bytes (- target::word-shift)))
+         (function-vector (allocate-typed-vector :function code-words))
+	 (nconstants (length constants)))
+    (declare (fixnum code-bytes code-words))
+    (when name (incf nconstants))
+    (when debug-info (incf nconstants))
+    (incf nconstants)
+
+    #+x8632-target
+    (let* ((ncode (- code-words nconstants)))
+      (when (>= ncode #x8000)
+        (if (>= nconstants #x8000)
+          (compiler-function-overflow)
+          (let* ((buf (car (frag-code-buffer (dll-header-first frag-list))))
+                 (new-word (logior #x8000 nconstants)))
+            (setf (aref buf 0) (ldb (byte 8 0) new-word)
+                  (aref buf 1) (ldb (byte 8 8) new-word))))))
+    (let* ((target-offset 0))
+      (declare (fixnum target-offset))
+      (do-dll-nodes (frag frag-list)
+        (incf target-offset (frag-output-bytes frag function-vector target-offset))))
+    (let* ((last (1- (uvsize function-vector))))
+      (declare (fixnum last))
+      (setf (uvref function-vector last) bits)
+      (when name
+        (setf (uvref function-vector (decf last)) name))
+      (when debug-info
+        (setf (uvref function-vector (decf last)) debug-info))
+      (dolist (c constants)
+        (setf (uvref function-vector (decf last)) (car c)))
+      #+x8632-target
+      (%update-self-references function-vector)
+      (function-vector-to-function function-vector))))
+
+(defun %define-x86-lap-function (name forms &optional (bits 0))
+  (target-arch-case
+   (:x8632
+    (%define-x8632-lap-function name forms bits))
+   (:x8664
+    (%define-x8664-lap-function name forms bits))))
+
+(defun %define-x8664-lap-function (name forms &optional (bits 0))
+  (let* ((*x86-lap-labels* ())
+         (*x86-lap-constants* ())
+	 (*x86-lap-entry-offset* x8664::fulltag-function)
+         (*x86-lap-fixed-code-words* nil)
+         (*x86-lap-lfun-bits* bits)
+         (end-code-tag (gensym))
+         (entry-code-tag (gensym))
+         (instruction (x86::make-x86-instruction))
+         (main-frag-list (make-frag-list))
+         (exception-frag-list (make-frag-list))
+         (frag-list main-frag-list))
+    (make-x86-lap-label end-code-tag)
+    (make-x86-lap-label entry-code-tag)
+    (x86-lap-directive frag-list :long `(ash (+ (- (:^ ,end-code-tag ) 8)
+                                              *x86-lap-entry-offset*) -3))
+    (x86-lap-directive frag-list :byte 0) ;regsave pc
+    (x86-lap-directive frag-list :byte 0) ;regsave ea
+    (x86-lap-directive frag-list :byte 0) ;regsave mask
+    (emit-x86-lap-label frag-list entry-code-tag)
+
+    (x86-lap-form `(lea (@ (:^ ,entry-code-tag) (% rip)) (% fn)) frag-list instruction main-frag-list exception-frag-list)
+    (dolist (f forms)
+      (setq frag-list (x86-lap-form f frag-list instruction main-frag-list exception-frag-list)))
+    (setq frag-list main-frag-list)
+    (merge-dll-nodes frag-list exception-frag-list)
+    (x86-lap-directive frag-list :align 3)
+    (when *x86-lap-fixed-code-words*
+      (x86-lap-directive frag-list :org (ash *x86-lap-fixed-code-words* 3)))
+    (x86-lap-directive frag-list :quad x8664::function-boundary-marker)
+    (emit-x86-lap-label frag-list end-code-tag)
+    (dolist (c (reverse *x86-lap-constants*))
+      (emit-x86-lap-label frag-list (x86-lap-label-name (cdr c)))
+      (x86-lap-directive frag-list :quad 0))
+    (when name
+      (x86-lap-directive frag-list :quad 0))
+    ;; room for lfun-bits
+    (x86-lap-directive frag-list :quad 0)
+    (relax-frag-list frag-list)
+    (apply-relocs frag-list)
+    (fill-for-alignment frag-list)
+    ;;(show-frag-bytes frag-list)
+    (funcall #-x86-target #'cross-create-x86-function
+             #+x86-target (if (eq *target-backend* *host-backend*)
+                            #'create-x86-function
+                            #'cross-create-x86-function)
+             name frag-list *x86-lap-constants* *x86-lap-lfun-bits* nil)))
+
+(defun %define-x8632-lap-function (name forms &optional (bits 0))
+  (let* ((*x86-lap-labels* ())
+         (*x86-lap-constants* ())
+	 (*x86-lap-entry-offset* x8632::fulltag-misc)
+         (*x86-lap-fixed-code-words* nil)
+         (*x86-lap-lfun-bits* bits)
+	 (srt-tag (gensym))
+         (end-code-tag (gensym))
+         (entry-code-tag (gensym))
+         (instruction (x86::make-x86-instruction))
+         (main-frag-list (make-frag-list))
+         (exception-frag-list (make-frag-list))
+         (frag-list main-frag-list))
+    (make-x86-lap-label entry-code-tag)
+    (make-x86-lap-label srt-tag)
+    (make-x86-lap-label end-code-tag)
+    ;; count of 32-bit words from header to function boundary
+    ;; marker, inclusive.
+    (x86-lap-directive frag-list :short `(ash (+ (- (:^ ,end-code-tag) 4)
+						 *x86-lap-entry-offset*) -2))
+    (emit-x86-lap-label frag-list entry-code-tag)
+    (x86-lap-form '(movl ($ :self) (% x8632::fn)) frag-list instruction main-frag-list exception-frag-list)
+    (dolist (f forms)
+      (setq frag-list (x86-lap-form f frag-list instruction main-frag-list exception-frag-list)))
+    (setq frag-list main-frag-list)
+    (merge-dll-nodes frag-list exception-frag-list)
+    (x86-lap-directive frag-list :align 2)
+    (when *x86-lap-fixed-code-words*
+      ;; We have a code-size that we're trying to get to.  We need to
+      ;; include the self-reference table in the code-size, so decrement
+      ;; the size of the padding we would otherwise insert by the srt size.
+      (let ((srt-words 1))		;for zero between end of code and srt
+	(do-dll-nodes (frag frag-list)
+	  (dolist (reloc (frag-relocs frag))
+	    (when (eq (reloc-type reloc) :self)
+	      (incf srt-words))))
+	(decf *x86-lap-fixed-code-words* srt-words)
+	(if (plusp *x86-lap-fixed-code-words*)
+	  (x86-lap-directive frag-list :org (ash *x86-lap-fixed-code-words* 2)))))
+    ;; self reference table
+    (x86-lap-directive frag-list :long 0)
+    (emit-x86-lap-label frag-list srt-tag)
+    ;; reserve space for self-reference offsets
+    (do-dll-nodes (frag frag-list)
+      (dolist (reloc (frag-relocs frag))
+	(when (eq (reloc-type reloc) :self)
+	  (x86-lap-directive frag-list :long 0))))
+    (x86-lap-directive frag-list :long x8632::function-boundary-marker)
+    (emit-x86-lap-label frag-list end-code-tag)
+    (dolist (c (reverse *x86-lap-constants*))
+      (emit-x86-lap-label frag-list (x86-lap-label-name (cdr c)))
+      (x86-lap-directive frag-list :long 0))
+    (when name
+      (x86-lap-directive frag-list :long 0))
+    ;; room for lfun-bits
+    (x86-lap-directive frag-list :long 0)
+    (relax-frag-list frag-list)
+    (apply-relocs frag-list)
+    (fill-for-alignment frag-list)
+    ;; determine start of self-reference-table
+    (let* ((label (find srt-tag *x86-lap-labels* :test #'eq
+						 :key #'x86-lap-label-name))
+	   (srt-frag (x86-lap-label-frag label))
+	   (srt-index (x86-lap-label-offset label)))
+      ;; fill in self-reference offsets
+      (do-dll-nodes (frag frag-list)
+	(dolist (reloc (frag-relocs frag))
+	  (when (eq (reloc-type reloc) :self)
+	    (setf (frag-ref-32 srt-frag srt-index)
+		  (+ (frag-address frag) (reloc-pos reloc)))
+	    (incf srt-index 4)))))
+    ;;(show-frag-bytes frag-list)
+    (funcall #-x8632-target #'cross-create-x86-function
+             #+x8632-target (if (eq *target-backend* *host-backend*)
+			      #'create-x86-function
+			      #'cross-create-x86-function)
+             name frag-list *x86-lap-constants* *x86-lap-lfun-bits* nil)))
+
+(defmacro defx86lapfunction (&environment env name arglist &body body
+                             &aux doc)
+  (if (not (endp body))
+      (and (stringp (car body))
+           (cdr body)
+           (setq doc (car body))
+           (setq body (cdr body))))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (note-function-info ',name t ,env))
+     #-x8664-target
+     (progn
+       (eval-when (:load-toplevel)
+         (%defun (nfunction ,name (lambda (&lap 0) (x86-lap-function ,name ,arglist ,@body))) ,doc))
+       (eval-when (:execute)
+         (%define-x86-lap-function ',name '((let ,arglist ,@body)))))
+     #+x8664-target	; just shorthand for defun
+     (%defun (nfunction ,name (lambda (&lap 0) (x86-lap-function ,name ,arglist ,@body))) ,doc)))
+
+(defmacro defx8632lapfunction (&environment env name arglist &body body
+                             &aux doc)
+  (if (not (endp body))
+      (and (stringp (car body))
+           (cdr body)
+           (setq doc (car body))
+           (setq body (cdr body))))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (note-function-info ',name t ,env))
+     #-x8632-target
+     (progn
+       (eval-when (:load-toplevel)
+         (%defun (nfunction ,name (lambda (&lap 0) (x86-lap-function ,name ,arglist ,@body))) ,doc))
+       (eval-when (:execute)
+         (%define-x8632-lap-function ',name '((let ,arglist ,@body)))))
+     #+x8632-target
+     (%defun (nfunction ,name (lambda (&lap 0) (x86-lap-function ,name ,arglist ,@body))) ,doc)))
Index: /branches/new-random/compiler/X86/x86-lapmacros.lisp
===================================================================
--- /branches/new-random/compiler/X86/x86-lapmacros.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/x86-lapmacros.lisp	(revision 13309)
@@ -0,0 +1,649 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Comparisons make more sense if arg order is "dest, src", instead
+;;; of the gas/ATT arg order.
+
+(defx86lapmacro rcmp (src dest)
+  `(cmp ,dest ,src))
+
+(defx86lapmacro clrl (reg)
+  `(xorl (% ,reg) (% ,reg)))
+
+(defx86lapmacro clrq (reg)
+  `(xorq (% ,reg) (% ,reg)))
+
+(defx86lapmacro set-nargs (n)
+  (cond ((= n 0) `(xorl (% nargs) (% nargs)))
+        (t `(movl ($ ',n) (% nargs)))))
+
+(defx86lapmacro anchored-uuo (form)
+  `(progn
+    ,form
+    (:byte 0)))
+
+(defx86lapmacro check-nargs (min &optional (max min))
+  (let* ((anchor (gensym))
+         (bad (gensym)))
+    (if (and max (= max min))
+      `(progn
+        ,anchor
+        ,(if (eql min 0)
+             `(testl (% nargs) (% nargs))
+             `(rcmp (% nargs) ($ ',min)))
+        (jne ,bad)
+        (:anchored-uuo-section ,anchor)
+        ,bad
+        (anchored-uuo (uuo-error-wrong-number-of-args))
+        (:main-section nil))
+      (if (null max)
+        (unless (zerop min)
+          `(progn
+            ,anchor
+            (rcmp (% nargs) ($ ',min))
+            (jb ,bad)
+            (:anchored-uuo-section ,anchor)
+            ,bad
+            (anchored-uuo (uuo-error-too-few-args))
+            (:main-section nil)))
+        (if (zerop min)
+          `(progn
+            ,anchor
+            (rcmp (% nargs) ($ ',max))
+            (ja ,bad)
+            (:anchored-uuo-section ,anchor)
+            ,bad
+            (anchored-uuo (uuo-error-too-many-args))
+            (:main-section nil))
+          (let* ((toofew (gensym))
+                 (toomany (gensym)))
+            `(progn
+              ,anchor
+              (rcmp (% nargs) ($ ',min))
+              (jb ,toofew)
+              (rcmp (% nargs) ($ ',max))
+              (ja ,toomany)
+              (:anchored-uuo-section ,anchor)
+              ,toofew
+              (anchored-uuo (uuo-error-too-few-args))
+              (:anchored-uuo-section ,anchor)
+              ,toomany
+              (anchored-uuo (uuo-error-too-many-args)))))))))
+
+
+(defx86lapmacro extract-lisptag (node dest)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (movl ($ x8632::tagmask) (% ,dest))
+       (andl (%l ,node) (%l ,dest))))
+   (:x8664
+    `(progn
+       (movb ($ x8664::tagmask) (%b ,dest))
+       (andb (%b ,node) (%b ,dest))))))
+
+(defx86lapmacro extract-fulltag (node dest)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (movl ($ x8632::fulltagmask) (%l ,dest))
+       (andl (%l ,node) (%l ,dest))))
+   (:x8664
+    `(progn
+       (movb ($ x8664::fulltagmask) (%b ,dest))
+       (andb (%b ,node) (%b ,dest))))))
+
+(defx86lapmacro extract-subtag (node dest)
+  (target-arch-case
+   (:x8632
+    `(movb (@ x8632::misc-subtag-offset (% ,node)) (%b ,dest)))
+   (:x8664
+    `(movb (@ x8664::misc-subtag-offset (% ,node)) (%b ,dest)))))
+
+(defx86lapmacro extract-typecode (node dest)
+  ;;; In general, these things are only defined to affect the low
+  ;;; byte of the destination register.  This can also affect
+  ;;; the #xff00 byte.
+  (let* ((done (gensym)))
+    (target-arch-case
+     (:x8632
+      `(progn
+	 (extract-lisptag ,node ,dest)
+	 (rcmp (%b ,dest) ($ x8632::tag-misc))
+	 (jne ,done)
+	 (movb (@  x8632::misc-subtag-offset (% ,node)) (%b ,dest))
+	 ,done))
+     (:x8664
+      `(progn
+	 (extract-lisptag ,node ,dest)
+	 (rcmp (%b ,dest) ($ x8664::tag-misc))
+	 (jne ,done)
+	 (movb (@  x8664::misc-subtag-offset (% ,node)) (%b ,dest))
+	 ,done)))))
+
+(defx86lapmacro trap-unless-typecode= (node tag &optional (immreg 'imm0))
+  (let* ((bad (gensym))
+         (anchor (gensym)))
+    `(progn
+      ,anchor
+      (extract-typecode ,node ,immreg)
+      (cmpb ($ ,tag) (%b ,immreg))
+      (jne ,bad)
+      (:anchored-uuo-section ,anchor)
+      ,bad
+      (:anchored-uuo (uuo-error-reg-not-tag (% ,node) ($ ,tag)))
+      (:main-section nil))))
+
+(defx86lapmacro trap-unless-fulltag= (node tag &optional (immreg 'imm0))
+  (let* ((ok (gensym)))
+    `(progn
+      (extract-fulltag ,node ,immreg)
+      (cmpb ($ ,tag) (%b ,immreg))
+      (je.pt ,ok)
+      (uuo-error-reg-not-tag (% ,node) ($ ,tag))
+      ,ok)))
+
+(defx86lapmacro trap-unless-lisptag= (node tag &optional (immreg 'imm0))
+  (let* ((ok (gensym)))
+    `(progn
+      (extract-lisptag ,node ,immreg)
+      (cmpb ($ ,tag) (%b ,immreg))
+      (je.pt ,ok)
+      (uuo-error-reg-not-tag (% ,node) ($ ,tag))
+      ,ok)))
+
+(defx86lapmacro trap-unless-fixnum (node)
+  (let* ((ok (gensym)))
+    (target-arch-case
+     (:x8632
+      `(progn
+	 (test ($ x8632::tagmask) (% ,node))
+	 (je.pt ,ok)
+	 (uuo-error-reg-not-fixnum (% ,node))
+	 ,ok))
+     (:x8664
+      `(progn
+	 (testb ($ x8664::tagmask) (%b ,node))
+	 (je.pt ,ok)
+	 (uuo-error-reg-not-fixnum (% ,node))
+	 ,ok)))))
+
+;;; On x8664, NIL has its own tag, so no other lisp object can
+;;; have the same low byte as NIL.  On x8632, NIL is a just
+;;; a distiguished CONS.
+(defx86lapmacro cmp-reg-to-nil (reg)
+  (target-arch-case
+   (:x8632
+    `(cmpl ($ (target-nil-value)) (%l ,reg)))
+   (:x8664
+    `(cmpb ($ (logand #xff (target-nil-value))) (%b ,reg)))))
+
+(defx86lapmacro unbox-fixnum (src dest)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (mov (% ,src) (% ,dest))
+       (sar ($ x8632::fixnumshift) (% ,dest))))
+   (:x8664
+    `(progn
+       (mov (% ,src) (% ,dest))
+       (sar ($ x8664::fixnumshift) (% ,dest))))))
+
+(defx86lapmacro box-fixnum (src dest)
+  (target-arch-case
+   (:x8632
+    `(imull ($ x8632::fixnumone) (% ,src) (% ,dest)))
+   (:x8664
+    `(imulq ($ x8664::fixnumone) (% ,src) (% ,dest)))))
+
+(defx86lapmacro get-single-float (node dest)
+  (target-arch-case
+   (:x8632
+    `(movss (@ x8632::single-float.value (% ,node)) (% ,dest)))
+   (:x8664
+    `(progn
+       (movd (% ,node) (% ,dest))
+       (psrlq ($ 32) (% ,dest))))))
+
+;;; Note that this modifies the src argument in the x8664 case.
+(defx86lapmacro put-single-float (src node)
+  (target-arch-case
+   (:x8632
+    `(movss (% ,src) (@ x8632::single-float.value (% ,node))))
+   (:x8664
+    `(progn
+       (psllq ($ 32) (% ,src))
+       (movd (% ,src) (% ,node))
+       (movb ($ x8664::tag-single-float) (%b ,node))))))
+
+(defx86lapmacro get-double-float (src fpreg)
+  (target-arch-case
+   (:x8632
+    `(movsd (@ x8632::double-float.value (% ,src)) (% ,fpreg)))
+   (:x8664
+    `(movsd (@ x8664::double-float.value (% ,src)) (% ,fpreg)))))
+
+(defx86lapmacro put-double-float (fpreg dest)
+  (target-arch-case
+   (:x8632
+    `(movsd (% ,fpreg) (@ x8632::double-float.value (% ,dest))))
+   (:x8664
+    `(movsd (% ,fpreg) (@ x8664::double-float.value (% ,dest))))))
+ 
+(defx86lapmacro getvheader (src dest)
+  (target-arch-case
+   (:x8632
+    `(movl (@ x8632::misc-header-offset (% ,src)) (% ,dest)))
+   (:x8664
+    `(movq (@ x8664::misc-header-offset (% ,src)) (% ,dest)))))
+
+;;; "Size" is unboxed element-count.  vheader and dest should
+;;; both be immediate registers
+(defx86lapmacro header-size (vheader dest)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (mov (% ,vheader) (% ,dest))
+       (shr ($ x8632::num-subtag-bits) (% ,dest))))
+   (:x8664
+    `(progn
+       (mov (% ,vheader) (% ,dest))
+       (shr ($ x8664::num-subtag-bits) (% ,dest))))))
+
+;;; "Length" is fixnum element-count.
+(defx86lapmacro header-length (vheader dest)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (movl ($ (lognot 255)) (% ,dest))
+       (andl (% ,vheader) (% ,dest))
+       (shr ($ (- x8632::num-subtag-bits x8632::fixnumshift)) (% ,dest))))
+   (:x8664
+    `(progn
+       (movq ($ (lognot 255)) (% ,dest))
+       (andq (% ,vheader) (% ,dest))
+       (shr ($ (- x8664::num-subtag-bits x8664::fixnumshift)) (% ,dest))))))
+
+(defx86lapmacro header-subtag[fixnum] (vheader dest)
+  `(progn
+    (lea (@ (% ,vheader) 8) (% ,dest))
+    (andl ($ '255) (%l ,dest))))
+
+(defx86lapmacro vector-size (vector vheader dest)
+  `(progn
+    (getvheader ,vector ,vheader)
+    (header-size ,vheader ,dest)))
+
+(defx86lapmacro vector-length (vector dest)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (movl ($ (lognot 255)) (% ,dest))
+       (andl (@ x8632::misc-header-offset (% ,vector)) (% ,dest))
+       (shr ($ (- x8632::num-subtag-bits x8632::fixnumshift)) (% ,dest))))
+   (:x8664
+    `(progn
+       (movq ($ (lognot 255)) (% ,dest))
+       (andq (@ x8664::misc-header-offset (% ,vector)) (% ,dest))
+       (shr ($ (- x8664::num-subtag-bits x8664::fixnumshift)) (% ,dest))))))
+
+(defx86lapmacro int-to-double (int temp double)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (unbox-fixnum  ,int ,temp)
+       (cvtsi2sdl (% ,temp) (% ,double))))
+   (:x8664
+    `(progn
+       (unbox-fixnum  ,int ,temp)
+       (cvtsi2sdq (% ,temp) (% ,double))))))
+
+(defx86lapmacro int-to-single (int temp single)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (unbox-fixnum ,int ,temp)
+       (cvtsi2ssl (% ,temp) (% ,single))))
+   (:x8664
+    `(progn
+       (unbox-fixnum ,int ,temp)
+       (cvtsi2ssq (% ,temp) (% ,single))))))
+
+(defx86lapmacro ref-global (global reg)
+  (target-arch-case
+   (:x8632
+    `(movl (@ (+ (target-nil-value) ,(x8632::%kernel-global global))) (% ,reg)))
+   (:x8664
+    `(movq (@ (+ (target-nil-value) ,(x8664::%kernel-global global))) (% ,reg)))))
+
+(defx86lapmacro ref-global.l (global reg)
+  (target-arch-case
+   (:x8632
+    `(movl (@ (+ (target-nil-value) ,(x8632::%kernel-global global))) (%l ,reg)))
+   (:x8664
+    `(movl (@ (+ (target-nil-value) ,(x8664::%kernel-global global))) (%l ,reg)))))
+
+(defx86lapmacro set-global (reg global)
+  (target-arch-case
+   (:x8632
+    `(movl (% ,reg) (@ (+ (target-nil-value) ,(x8632::%kernel-global global)))))
+   (:x8664
+    `(movq (% ,reg) (@ (+ (target-nil-value) ,(x8664::%kernel-global global)))))))
+
+(defx86lapmacro macptr-ptr (src dest)
+  (target-arch-case
+   (:x8632
+    `(movl (@ x8632::macptr.address (% ,src)) (% ,dest)))
+   (:x8664
+    `(movq (@ x8664::macptr.address (% ,src)) (% ,dest)))))
+
+;;; CODE is unboxed char-code (in low 8 bits); CHAR needs to be boxed.
+(defx86lapmacro box-character (code char)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (box-fixnum ,code ,char)
+       (shl ($ (- x8632::charcode-shift x8632::fixnumshift)) (% ,char))
+       (movb ($ x8632::subtag-character) (%b ,char))))
+   (:x8664
+    `(progn
+       (box-fixnum ,code ,char)
+       (shl ($ (- x8664::charcode-shift x8664::fixnumshift)) (% ,char))
+       (movb ($ x8664::subtag-character) (%b ,char))))))
+  
+;;; index is a constant
+(defx86lapmacro svref (vector index dest)
+  (target-arch-case
+   (:x8632
+    `(movl (@ (+ x8632::misc-data-offset (* ,index 4)) (% ,vector)) (% ,dest)))
+   (:x8664
+    `(movq (@ (+ x8664::misc-data-offset (* ,index 8)) (% ,vector)) (% ,dest)))))
+
+;;; Index is still a constant
+(defx86lapmacro svset (vector index new)
+  (target-arch-case
+   (:x8632
+    `(movl (% ,new) (@ (+ x8632::misc-data-offset (* ,index 4)) (% ,vector))))
+   (:x8664
+    `(movq (% ,new) (@ (+ x8664::misc-data-offset (* ,index 8)) (% ,vector))))))
+
+
+;;; Frames, function entry and exit.
+
+
+;;; Simple frame, since the caller didn't reserve space for it.
+(defx86lapmacro save-simple-frame ()
+  (target-arch-case
+   (:x8632
+    `(progn
+       (pushl (% ebp))
+       (movl (% esp) (% ebp))))
+   (:x8664
+    `(progn
+       (pushq (% rbp))
+       (movq (% rsp) (% rbp))))))
+
+(defx86lapmacro save-stackargs-frame (nstackargs)
+  (target-arch-case
+   (:x8632
+    `(progn
+      (movl (% ebp) (@ ,(* (1+ nstackargs) x8632::node-size) (% esp)))
+      (leal (@ ,(* (1+ nstackargs) x8632::node-size) (% esp)) (% ebp))
+      (popl (@ x8632::node-size (% ebp)))))
+   (:x8664
+    `(progn
+      (movq (% rbp) (@ ,(* (1+ nstackargs) x8664::node-size) (% rsp)))
+      (leaq (@ ,(* (1+ nstackargs) x8664::node-size) (% rsp)) (% rbp))
+      (popq (@ x8632::node-size (% rbp)))))))
+
+(defx86lapmacro save-frame-variable-arg-count ()
+  (let* ((push (gensym))
+         (done (gensym)))
+    (target-arch-case
+     (:x8632
+      `(progn
+	 (movl (% nargs) (% imm0))
+	 (subl ($ (* $numx8632argregs x8632::node-size)) (% imm0))
+	 (jle ,push)
+	 (movl (% ebp) (@ 4 (% esp) (% imm0)))
+	 (leal (@ 4 (% esp) (% imm0)) (% ebp))
+	 (popl (@ 4 (% ebp)))
+	 (jmp ,done)
+	 ,push
+	 (save-simple-frame)
+	 ,done))
+     (:x8664
+      `(progn
+	 (movl (% nargs) (%l imm0))
+	 (subq ($ (* $numx8664argregs x8664::node-size)) (% imm0))
+	 (jle ,push)
+	 (movq (% rbp) (@ 8 (% rsp) (% imm0)))
+	 (leaq (@ 8 (% rsp) (% imm0)) (% rbp))
+	 (popq (@ 8 (% rbp)))
+	 (jmp ,done)
+	 ,push
+	 (save-simple-frame)
+	 ,done)))))
+
+
+(defx86lapmacro restore-simple-frame ()
+  `(progn
+    (leave)))
+
+(defx86lapmacro discard-reserved-frame ()
+  (target-arch-case
+   (:x8632
+    `(add ($ '2) (% esp)))
+   (:x8664
+    `(add ($ '2) (% rsp)))))
+
+;;; Return to caller.
+(defx86lapmacro single-value-return (&optional (words-to-discard 0))
+  (target-arch-case
+   (:x8632
+    (if (zerop words-to-discard)
+	`(ret)
+	`(ret ($ ,(* x8632::node-size words-to-discard)))))
+   (:x8664
+    (if (zerop words-to-discard)
+	`(ret)
+	`(ret ($ ,(* x8664::node-size words-to-discard)))))))
+
+(defun x86-subprim-offset (name)
+  (let* ((info (find name (arch::target-subprims-table (backend-target-arch *target-backend*)) :test #'string-equal :key #'subprimitive-info-name))
+         (offset (when info 
+                   (subprimitive-info-offset info))))
+    (or offset      
+	(error "Unknown subprim: ~s" name))))
+
+(defx86lapmacro jmp-subprim (name)
+  `(jmp (@ ,(x86-subprim-offset name))))
+
+(defx86lapmacro recover-fn ()
+  `(movl ($ :self) (% fn)))
+
+(defx86lapmacro call-subprim (name)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (:talign x8632::fulltag-tra)
+       (call (@ ,(x86-subprim-offset name)))
+       (recover-fn)))
+   (:x8664
+    `(progn
+       (:talign 4)
+       (call (@ ,(x86-subprim-offset name)))
+       (recover-fn-from-rip)))))
+
+ (defx86lapmacro %car (src dest)
+  (target-arch-case
+   (:x8632
+    `(movl (@ x8632::cons.car (% ,src)) (% ,dest)))
+   (:x8664
+    `(movq (@ x8664::cons.car (% ,src)) (% ,dest)))))
+
+(defx86lapmacro %cdr (src dest)
+  (target-arch-case
+   (:x8632
+    `(movl (@ x8632::cons.cdr (% ,src)) (% ,dest)))
+   (:x8664
+    `(movq (@ x8664::cons.cdr (% ,src)) (% ,dest)))))
+
+(defx86lapmacro stack-probe ()
+  (target-arch-case
+   (:x8632
+    (let* ((ok (gensym)))
+      `(progn
+	 (rcmp (% esp) (@ (% rcontext) x8632::tcr.cs-limit))
+	 (jae.pt ,ok)
+	 (uuo-stack-overflow)
+	 ,ok)))
+   (:x8664
+    (let* ((ok (gensym)))
+      `(progn
+	 (rcmp (% rsp) (@ (% rcontext) x8664::tcr.cs-limit))
+	 (jae.pt ,ok)
+	 (uuo-stack-overflow)
+	 ,ok)))))
+
+(defx86lapmacro load-constant (constant dest &optional (fn 'fn))
+  (target-arch-case
+   (:x8632
+    `(movl (@ ',constant (% ,fn)) (% ,dest)))
+   (:x8664
+    `(movq (@ ',constant (% ,fn)) (% ,dest)))))
+
+(defx86lapmacro recover-fn-from-rip ()
+  (let* ((next (gensym)))
+    `(progn
+      (lea (@ (- (:^ ,next)) (% rip)) (% fn))
+      ,next)))
+
+;;; call symbol named NAME, setting nargs to NARGS.  Do the TRA
+;;; hair.   Args should already be in arg regs, and we expect
+;;; to return a single value.
+(defx86lapmacro call-symbol (name nargs)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (load-constant ,name fname)
+       (set-nargs ,nargs)
+       (:talign 5)
+       (call (@ x8632::symbol.fcell (% fname)))
+       (recover-fn)))
+   (:x8664
+    `(progn
+       (load-constant ,name fname)
+       (set-nargs ,nargs)
+       (:talign 4)
+       (call (@ x8664::symbol.fcell (% fname)))
+       (recover-fn-from-rip)))))
+
+
+;;;  tail call the function named by NAME with nargs NARGS.  %FN is
+;;;  the caller, which will be in %FN on entry to the callee.  For the
+;;;  couple of instructions where neither %RA0 or %FN point to the
+;;;  current function, ensure that %XFN does; this is necessary to
+;;;  prevent the current function from being GCed halfway through
+;;;  those couple of instructions.
+
+(defx86lapmacro jump-symbol (name nargs)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (load-constant ,name fname)
+       (set-nargs ,nargs)
+       (jmp (@ x8632::symbol.fcell (% fname)))))
+   (:x8664
+    `(progn
+       (load-constant ,name fname)
+       (set-nargs ,nargs)
+       (jmp (@ x8664::symbol.fcell (% fname)))))))
+
+(defx86lapmacro push-argregs ()
+  (let* ((done (gensym))
+         (yz (gensym))
+         (z (gensym)))
+    (target-arch-case
+     (:x8632
+      `(progn
+	 (testl (% nargs) (% nargs))
+	 (je ,done)
+	 (cmpl ($ '1) (% nargs))
+	 (je ,z)
+	 (push (% arg_y))
+	 ,z
+	 (push (% arg_z))
+	 ,done))
+     (:x8664
+      `(progn
+	 (testl (% nargs) (% nargs))
+	 (je ,done)
+	 (cmpl ($ '2) (% nargs))
+	 (je ,yz)
+	 (jb ,z)
+	 (push (% arg_x))
+	 ,yz
+	 (push (% arg_y))
+	 ,z
+	 (push (% arg_z))
+	 ,done)))))
+
+;;; clears reg
+(defx86lapmacro mark-as-node (reg)
+  (let* ((regnum (logand #x7 (x86::gpr-ordinal (string reg))))
+	 (bit (ash 1 regnum)))
+    `(progn
+       (xorl (% ,reg) (% ,reg))
+       (orb ($ ,bit) (@ (% :rcontext) x8632::tcr.node-regs-mask)))))
+
+(defx86lapmacro mark-as-imm (reg)
+  (let* ((regnum (logand #x7 (x86::gpr-ordinal (string reg))))
+	 (bit (ash 1 regnum)))
+    `(progn
+       (andb ($ (lognot ,bit)) (@ (% :rcontext) x8632::tcr.node-regs-mask)))))
+
+(defx86lapmacro compose-digit (high low dest)
+  (target-arch-case
+   (:x8632
+    `(progn
+       (unbox-fixnum ,low ,dest)
+       (andl ($ #xffff) (% ,dest))
+       (shll ($ (- 16 x8632::fixnumshift)) (% ,high))
+       (orl (% ,high) (% ,dest))))
+   (:x8664
+    (error "compose-digit on x8664?"))))
+
+(defx86lapmacro imm-word-count (fn imm dest)
+  `(progn
+     (movzwl (@ x8632::misc-data-offset (% ,fn)) (% ,imm))
+     (btr ($ 15) (% ,imm))
+     (vector-length ,fn ,dest)
+     (box-fixnum ,imm ,imm)
+     (subl (% ,imm) (% ,dest))))
+
+(defx86lapmacro double-constant (name value)
+  (multiple-value-bind (high low)
+      (double-float-bits (float value 1.0d0))
+    `(progn
+       (:uuo-section)
+       (:align 3)
+       ,name
+       (:long ,low)
+       (:long ,high)
+       (:main-section))))
Index: /branches/new-random/compiler/X86/x862.lisp
===================================================================
--- /branches/new-random/compiler/X86/x862.lisp	(revision 13309)
+++ /branches/new-random/compiler/X86/x862.lisp	(revision 13309)
@@ -0,0 +1,10179 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NXENV")
+  (require "X8632ENV")
+  (require "X8664ENV"))
+
+(eval-when (:load-toplevel :execute :compile-toplevel)
+  (require "X86-BACKEND"))
+
+(defparameter *x862-debug-mask* 0)
+(defconstant x862-debug-verbose-bit 0)
+(defconstant x862-debug-vinsns-bit 1)
+(defconstant x862-debug-lcells-bit 2)
+(defparameter *x862-target-lcell-size* 0)
+(defparameter *x862-target-node-size* 0)
+(defparameter *x862-target-dnode-size* 0)
+(defparameter *x862-target-fixnum-shift* 0)
+(defparameter *x862-target-node-shift* 0)
+(defparameter *x862-target-bits-in-word* 0)
+(defparameter *x862-target-num-arg-regs* 0)
+(defparameter *x862-target-num-save-regs* 0)
+(defparameter *x862-target-half-fixnum-type* nil)
+
+(defparameter *x862-operator-supports-u8-target* ())
+(defparameter *x862-operator-supports-push* ())
+(defparameter *x862-tos-reg* ())
+
+;; probably should be elsewhere
+
+(defmacro with-additional-imm-reg ((&rest reserved) &body body)
+  (let ((node (gensym))
+	(bit (gensym)))
+    `(target-arch-case
+      (:x8632
+       (with-node-target (,@reserved) ,node
+	 (let* ((,bit (ash 1 (hard-regspec-value ,node)))
+		(*backend-node-temps* (logandc2 *backend-node-temps* ,bit))
+		(*available-backend-node-temps* (logandc2 *available-backend-node-temps* ,bit))
+		(*backend-imm-temps* (logior *backend-imm-temps* ,bit))
+		(*available-backend-imm-temps* (logior *available-backend-imm-temps* ,bit)))
+	   (! mark-as-imm ,node)
+	   ,@body
+	   (! mark-as-node ,node))))
+      (:x8664
+       (progn
+	 ,@body)))))
+
+
+
+(defmacro with-x86-p2-declarations (declsform &body body)
+  `(let* ((*x862-tail-allow* *x862-tail-allow*)
+          (*x862-reckless* *x862-reckless*)
+          (*x862-open-code-inline* *x862-open-code-inline*)
+          (*x862-trust-declarations* *x862-trust-declarations*)
+          (*x862-full-safety* *x862-full-safety*))
+     (x862-decls ,declsform)
+     ,@body))
+
+
+(defmacro with-x86-local-vinsn-macros ((segvar &optional vreg-var xfer-var) &body body)
+  (declare (ignorable xfer-var))
+  (let* ((template-name-var (gensym))
+         (template-temp (gensym))
+         (args-var (gensym))
+         (labelnum-var (gensym))
+         (retvreg-var (gensym))
+         (label-var (gensym)))
+    `(macrolet ((! (,template-name-var &rest ,args-var)                 
+                  (let* ((,template-temp (get-vinsn-template-cell ,template-name-var (backend-p2-vinsn-templates *target-backend*))))
+                    (unless ,template-temp
+                      (warn "VINSN \"~A\" not defined" ,template-name-var))
+                    `(prog1
+                      (%emit-vinsn ,',segvar ',,template-name-var (backend-p2-vinsn-templates *target-backend*) ,@,args-var)
+                      (setq *x862-tos-reg* nil)))))
+       (macrolet ((<- (,retvreg-var)
+                    `(x862-copy-register ,',segvar ,',vreg-var ,,retvreg-var))
+                  (@  (,labelnum-var)
+                    `(backend-gen-label ,',segvar ,,labelnum-var))
+                  (@= (,labelnum-var)
+                    `(x862-emit-aligned-label ,',segvar ,,labelnum-var))
+                  (-> (,label-var)
+                    `(! jump (aref *backend-labels* ,,label-var)))
+                  (^ (&rest branch-args)
+                    `(x862-branch ,',segvar ,',xfer-var ,@branch-args))
+                  (? (&key (class :gpr)
+                          (mode :lisp))
+                   (let* ((class-val
+                           (ecase class
+                             (:gpr hard-reg-class-gpr)
+                             (:fpr hard-reg-class-fpr)
+                             (:crf hard-reg-class-crf)))
+                          (mode-val-or-form
+                           (if (eq class :gpr)
+			     (if (member mode '(:natural :signed-natural))
+			       `(gpr-mode-name-value ,mode)
+			       (gpr-mode-name-value mode))
+                             (if (eq class :fpr)
+                               (if (eq mode :single-float)
+                                 hard-reg-class-fpr-mode-single
+                                 hard-reg-class-fpr-mode-double)
+                               0))))
+                     `(make-unwired-lreg nil
+                       :class ,class-val
+                       :mode ,mode-val-or-form)))
+                  ($ (reg &key (class :gpr) (mode :lisp))
+                   (let* ((class-val
+                           (ecase class
+                             (:gpr hard-reg-class-gpr)
+                             (:fpr hard-reg-class-fpr)
+                             (:crf hard-reg-class-crf)))
+                          (mode-val-or-form
+                           (if (eq class :gpr)
+			     (if (member mode '(:natural :signed-natural))
+			       `(gpr-mode-name-value ,mode)
+			       (gpr-mode-name-value mode))
+                             (if (eq class :fpr)
+                               (if (eq mode :single-float)
+                                 hard-reg-class-fpr-mode-single
+                                 hard-reg-class-fpr-mode-double)
+                               0))))
+                     `(make-wired-lreg ,reg
+                       :class ,class-val
+                       :mode ,mode-val-or-form))))
+         ,@body))))
+
+
+
+(defvar *x86-current-context-annotation* nil)
+(defvar *x862-woi* nil)
+(defvar *x862-open-code-inline* nil)
+(defvar *x862-register-restore-count* 0)
+(defvar *x862-register-restore-ea* nil)
+(defvar *x862-compiler-register-save-label* nil)
+(defvar *x862-valid-register-annotations* 0)
+(defvar *x862-register-annotation-types* nil)
+(defvar *x862-register-ea-annotations* nil)
+(defvar *x862-constant-alist* nil)
+(defvar *x862-double-float-constant-alist* nil)
+(defvar *x862-single-float-constant-alist* nil)
+
+(defparameter *x862-tail-call-aliases*
+  ()
+  #| '((%call-next-method . (%tail-call-next-method . 1))) |#
+  
+)
+
+(defvar *x862-popreg-labels* nil)
+(defvar *x862-popj-labels* nil)
+(defvar *x862-valret-labels* nil)
+(defvar *x862-nilret-labels* nil)
+
+(defvar *x862-icode* nil)
+(defvar *x862-undo-stack* nil)
+(defvar *x862-undo-because* nil)
+
+
+(defvar *x862-cur-afunc* nil)
+(defvar *x862-vstack* 0)
+(defvar *x862-cstack* 0)
+(defvar *x862-undo-count* 0)
+(defvar *x862-returning-values* nil)
+(defvar *x862-vcells* nil)
+(defvar *x862-fcells* nil)
+(defvar *x862-entry-vsp-saved-p* nil)
+
+(defvar *x862-entry-label* nil)
+(defvar *x862-tail-label* nil)
+(defvar *x862-tail-vsp* nil)
+(defvar *x862-tail-nargs* nil)
+(defvar *x862-tail-allow* t)
+(defvar *x862-reckless* nil)
+(defvar *x862-full-safety* nil)
+(defvar *x862-trust-declarations* nil)
+(defvar *x862-entry-vstack* nil)
+(defvar *x862-fixed-nargs* nil)
+(defvar *x862-need-nargs* t)
+
+(defparameter *x862-inhibit-register-allocation* nil)
+(defvar *x862-record-symbols* nil)
+(defvar *x862-recorded-symbols* nil)
+(defvar *x862-emitted-source-notes* nil)
+
+(defvar *x862-result-reg* x8664::arg_z)
+
+(defvar *x8664-nvrs*
+  `(,x8664::save0 ,x8664::save1 ,x8664::save2 ,x8664::save3))
+
+(defvar *reduced-x8664-nvrs*
+  `(,x8664::save0 ,x8664::save1 ,x8664::save2))
+
+(defvar *x8632-nvrs* ())
+
+
+(defvar *x862-arg-z* nil)
+(defvar *x862-arg-y* nil)
+(defvar *x862-imm0* nil)
+(defvar *x862-temp0* nil)
+(defvar *x862-temp1* nil)
+(defvar *x862-fn* nil)
+(defvar *x862-fname* nil)
+(defvar *x862-ra0* nil)
+(defvar *x862-codecoverage-reg* nil)
+
+(defvar *x862-allocptr* nil)
+
+(defvar *x862-fp0* nil)
+(defvar *x862-fp1* nil)
+
+(declaim (fixnum *x862-vstack* *x862-cstack*))
+
+
+
+
+
+(defvar *x862-all-lcells* ())
+
+(defun x86-immediate-label (imm)
+  (or (cdr (assoc imm *x862-constant-alist* :test #'eq))
+      (let* ((lab (aref *backend-labels* (backend-get-next-label))))
+        (push (cons imm lab) *x862-constant-alist*)
+        lab)))
+
+(defun x86-double-float-constant-label (imm)
+  (or (cdr (assoc imm *x862-double-float-constant-alist*))
+      (let* ((lab (aref *backend-labels* (backend-get-next-label))))
+        (push (cons imm lab) *x862-double-float-constant-alist*)
+        lab)))
+
+(defun x86-single-float-constant-label (imm)
+  (or (cdr (assoc imm *x862-single-float-constant-alist*))
+      (let* ((lab (aref *backend-labels* (backend-get-next-label))))
+        (push (cons imm lab) *x862-single-float-constant-alist*)
+        lab)))
+
+
+(defun x862-free-lcells ()
+  (without-interrupts 
+   (let* ((prev (pool.data *lcell-freelist*)))
+     (dolist (r *x862-all-lcells*)
+       (setf (lcell-kind r) prev
+             prev r))
+     (setf (pool.data *lcell-freelist*) prev)
+     (setq *x862-all-lcells* nil))))
+
+(defun x862-note-lcell (c)
+  (push c *x862-all-lcells*)
+  c)
+
+(defvar *x862-top-vstack-lcell* ())
+(defvar *x862-bottom-vstack-lcell* ())
+
+(defun x862-new-lcell (kind parent width attributes info)
+  (x862-note-lcell (make-lcell kind parent width attributes info)))
+
+(defun x862-new-vstack-lcell (kind width attributes info)
+  (setq *x862-top-vstack-lcell* (x862-new-lcell kind *x862-top-vstack-lcell* width attributes info)))
+
+(defun x862-reserve-vstack-lcells (n)
+  (dotimes (i n) (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil)))
+
+(defun x862-vstack-mark-top ()
+  (x862-new-lcell :tos *x862-top-vstack-lcell* 0 0 nil))
+
+;;; Alist mapping VARs to lcells/lregs
+(defvar *x862-var-cells* ())
+
+(defun x862-note-var-cell (var cell)
+  ;(format t "~& ~s -> ~s" (var-name var) cell)
+  (push (cons var cell) *x862-var-cells*))
+
+(defun x862-note-top-cell (var)
+  (x862-note-var-cell var *x862-top-vstack-lcell*))
+
+(defun x862-lookup-var-cell (var)
+  (or (cdr (assq var *x862-var-cells*))
+      (and nil (warn "Cell not found for ~s" (var-name var)))))
+
+(defun x862-collect-lcells (kind &optional (bottom *x862-bottom-vstack-lcell*) (top *x862-top-vstack-lcell*))
+  (do* ((res ())
+        (cell top (lcell-parent cell)))
+       ((eq cell bottom) res)
+    (if (null cell)
+      (compiler-bug "Horrible compiler bug.")
+      (if (eq (lcell-kind cell) kind)
+        (push cell res)))))
+
+
+  
+;;; ensure that lcell's offset matches what we expect it to.
+;;; For bootstrapping.
+
+(defun x862-ensure-lcell-offset (c expected)
+  (if c (= (calc-lcell-offset c) expected) (zerop expected)))
+
+(defun x862-check-lcell-depth (&optional (context "wherever"))
+  (when (logbitp x862-debug-verbose-bit *x862-debug-mask*)
+    (let* ((depth (calc-lcell-depth *x862-top-vstack-lcell*)))
+      (or (= depth *x862-vstack*)
+          (warn "~a: lcell depth = ~d, vstack = ~d" context depth *x862-vstack*)))))
+
+(defun x862-do-lexical-reference (seg vreg ea)
+  (when vreg
+    (with-x86-local-vinsn-macros (seg vreg)
+      (if (eq vreg :push)
+        (if (memory-spec-p ea)
+          (if (addrspec-vcell-p ea)
+            (with-node-target () target
+              (x862-stack-to-register seg ea target)
+              (! vcell-ref target target)
+              (! vpush-register target))
+            (! vframe-push (memspec-frame-address-offset ea) *x862-vstack*))
+          (! vpush-register ea))
+        (if (memory-spec-p ea)
+          (ensuring-node-target (target vreg)
+            (progn
+              (x862-stack-to-register seg ea target)
+              (if (addrspec-vcell-p ea)
+                (! vcell-ref target target))))
+          (<- ea))))))
+
+(defun x862-do-lexical-setq (seg vreg ea valreg)
+  (with-x86-local-vinsn-macros (seg vreg)
+    (cond ((typep ea 'lreg)
+            (x862-copy-register seg ea valreg))
+          ((addrspec-vcell-p ea)     ; closed-over vcell
+           (x862-copy-register seg *x862-arg-z* valreg)
+	   (let* ((gvector (target-arch-case (:x8632 x8632::temp0)
+					     (:x8664 x8664::arg_x))))
+	     (x862-stack-to-register seg ea gvector)
+	     (x862-lri seg *x862-arg-y* 0)
+	     (! call-subprim-3 *x862-arg-z* (subprim-name->offset '.SPgvset) gvector *x862-arg-y* *x862-arg-z*)))
+          ((memory-spec-p ea)    ; vstack slot
+           (x862-register-to-stack seg valreg ea))
+          (t
+           (x862-copy-register seg ea valreg)))
+    (when vreg
+      (<- valreg))))
+
+;;; ensure that next-method-var is heap-consed (if it's closed over.)
+;;; it isn't ever setqed, is it ?
+(defun x862-heap-cons-next-method-var (seg var)
+  (with-x86-local-vinsn-macros (seg)
+    (when (eq (ash 1 $vbitclosed)
+              (logand (logior (ash 1 $vbitclosed)
+                              (ash 1 $vbitcloseddownward))
+                      (the fixnum (nx-var-bits var))))
+      (let* ((ea (var-ea var))
+             (arg ($ *x862-arg-z*))
+             (result ($ *x862-arg-z*)))
+        (x862-do-lexical-reference seg arg ea)
+        (x862-set-nargs seg 1)
+        (! ref-constant ($ *x862-fname*) (x86-immediate-label (x862-symbol-entry-locative '%cons-magic-next-method-arg)))
+        (! call-known-symbol arg)
+        (x862-do-lexical-setq seg nil ea result)))))
+
+;;; If we change the order of operands in a binary comparison operation,
+;;; what should the operation change to ? (eg., (< X Y) means the same
+;;; thing as (> Y X)).
+(defparameter *x862-reversed-cr-bits*
+  (vector
+   nil                                  ;o ?
+   nil                                  ;no ?
+   x86::x86-a-bits                      ;b -> a
+   x86::x86-be-bits                     ;ae -> be
+   x86::x86-e-bits                      ;e->e
+   x86::x86-ne-bits                     ;ne->ne
+   x86::x86-ae-bits                     ;be->ae
+   x86::x86-b-bits                      ;a->b
+   nil                                  ;s ?
+   nil                                  ;ns ?
+   nil                                  ;pe ?
+   nil                                  ;po ?
+   x86::x86-g-bits                      ;l->g
+   x86::x86-le-bits                     ;ge->le
+   x86::x86-ge-bits                     ;le->ge
+   x86::x86-l-bits                      ;g->l
+   ))
+
+(defun x862-reverse-cr-bit (cr-bit)
+  (or (svref *x862-reversed-cr-bits* cr-bit)
+      (compiler-bug "Can't reverse CR bit ~d" cr-bit)))
+
+
+(defun acode-condition-to-x86-cr-bit (cond)
+  (condition-to-x86-cr-bit (cadr cond)))
+
+(defun condition-to-x86-cr-bit (cond)
+  (case cond
+    (:EQ (values x86::x86-e-bits t))
+    (:NE (values x86::x86-e-bits nil))
+    (:GT (values x86::x86-le-bits nil))
+    (:LE (values x86::x86-le-bits t))
+    (:LT (values x86::x86-l-bits t))
+    (:GE (values x86::x86-l-bits nil))))
+
+;;; Generate the start and end bits for a RLWINM instruction that
+;;; would be equivalent to to LOGANDing the constant with some value.
+;;; Return (VALUES NIL NIL) if the constant contains more than one
+;;; sequence of consecutive 1-bits, else bit indices.
+;;; The caller generally wants to treat the constant as an (UNSIGNED-BYTE 32);
+;;; since this uses LOGCOUNT and INTEGER-LENGTH to find the significant
+;;; bits, it ensures that the constant is a (SIGNED-BYTE 32) that has
+;;; the same least-significant 32 bits.
+(defun x862-mask-bits (constant)
+  (if (< constant 0) (setq constant (logand #xffffffff constant)))
+  (if (= constant #xffffffff)
+    (values 0 31)
+    (if (zerop constant)
+      (values nil nil)
+      (let* ((signed (if (and (logbitp 31 constant)
+                              (> constant 0))
+                       (- constant (ash 1 32))
+                       constant))
+             (count (logcount signed))
+             (len (integer-length signed))
+             (highbit (logbitp (the fixnum (1- len)) constant)))
+        (declare (fixnum count len))
+        (do* ((i 1 (1+ i))
+              (pos (- len 2) (1- pos)))
+             ((= i count)
+              (let* ((start (- 32 len))
+                     (end (+ count start)))
+                (declare (fixnum start end))
+                (if highbit
+                  (values start (the fixnum (1- end)))
+                  (values (logand 31 end)
+                          (the fixnum (1- start))))))
+          (declare (fixnum i pos))
+          (unless (eq (logbitp pos constant) highbit)
+            (return (values nil nil))))))))
+    
+
+(defun x862-ensure-binding-indices-for-vcells (vcells)
+  (dolist (cell vcells)
+    (ensure-binding-index (car cell)))
+  vcells)
+
+(defun x862-register-mask-byte (count)
+  (if (> count 0)
+    (logior
+     (ash 1 (- x8664::save0 8))
+     (if (> count 1)
+       (logior
+        (ash 1 (- x8664::save1 8))
+        (if (> count 2)
+          (logior
+           (ash 1 (- x8664::save2 8))
+           (if (> count 3)
+             (ash 1 (- x8664::save3 8))
+             0))
+          0))
+       0))
+    0))
+
+(defun x862-encode-register-save-ea (ea count)
+  (if (zerop count)
+    0 
+    (min (- (ash ea (- *x862-target-node-shift*)) count) #xff)))
+
+
+(defun x862-compile (afunc &optional lambda-form *x862-record-symbols*)
+  (progn
+    (dolist (a  (afunc-inner-functions afunc))
+      (unless (afunc-lfun a)
+        (x862-compile a 
+                      (if lambda-form (afunc-lambdaform a))
+                      *x862-record-symbols*))) ; always compile inner guys
+    (let* ((*x862-cur-afunc* afunc)
+           (*x862-returning-values* nil)
+           (*x86-current-context-annotation* nil)
+           (*x862-woi* nil)
+           (*next-lcell-id* -1)
+           (*x862-open-code-inline* nil)
+           (*x862-register-restore-count* nil)
+           (*x862-compiler-register-save-label* nil)
+           (*x862-valid-register-annotations* 0)
+           (*x862-register-ea-annotations* (x862-make-stack 16))
+           (*x862-register-restore-ea* nil)
+           (*x862-constant-alist* nil)
+           (*x862-double-float-constant-alist* nil)
+           (*x862-single-float-constant-alist* nil)
+           (*x862-vstack* 0)
+           (*x862-cstack* 0)
+	   (*x86-lap-entry-offset* (target-arch-case
+				    (:x8632 x8632::fulltag-misc)
+				    (:x8664 x8664::fulltag-function)))
+	   (*x862-result-reg* (target-arch-case
+			       (:x8632 x8632::arg_z)
+			       (:x8664 x8664::arg_z)))
+	   (*x862-imm0* (target-arch-case (:x8632 x8632::imm0)
+					  (:x8664 x8664::imm0)))
+	   (*x862-arg-z* (target-arch-case (:x8632 x8632::arg_z)
+					   (:x8664 x8664::arg_z)))
+	   (*x862-arg-y* (target-arch-case (:x8632 x8632::arg_y)
+					   (:x8664 x8664::arg_y)))
+	   (*x862-temp0* (target-arch-case (:x8632 x8632::temp0)
+					   (:x8664 x8664::temp0)))
+           (*x862-codecoverage-reg* *x862-temp0*)
+	   (*x862-temp1* (target-arch-case (:x8632 x8632::temp1)
+					   (:x8664 x8664::temp1)))
+	   (*x862-fn* (target-arch-case (:x8632 x8632::fn)
+					(:x8664 x8664::fn)))
+	   (*x862-fname* (target-arch-case (:x8632 x8632::fname)
+					   (:x8664 x8664::fname)))
+	   (*x862-ra0* (target-arch-case (:x8632 x8632::ra0)
+					 (:x8664 x8664::ra0)))
+	   (*x862-allocptr* (target-arch-case (:x8632 x8632::allocptr)
+					      (:x8664 x8664::allocptr)))
+	   (*x862-fp0* (target-arch-case (:x8632 x8632::fp0)
+					 (:x8664 x8664::fp0)))
+	   (*x862-fp1* (target-arch-case (:x8632 x8632::fp1)
+					 (:x8664 x8664::fp1)))
+           (*x862-target-num-arg-regs* (target-arch-case
+					(:x8632 $numx8632argregs)
+					(:x8664  $numx8664argregs)))
+           (*x862-target-num-save-regs* (target-arch-case
+					 (:x8632 $numx8632saveregs)
+					 (:x8664  $numx8664saveregs)))
+	   (*x862-target-lcell-size* (arch::target-lisp-node-size (backend-target-arch *target-backend*)))
+           (*x862-target-fixnum-shift* (arch::target-fixnum-shift (backend-target-arch *target-backend*)))
+           (*x862-target-node-shift* (arch::target-word-shift  (backend-target-arch *target-backend*)))
+           (*x862-target-bits-in-word* (arch::target-nbits-in-word (backend-target-arch *target-backend*)))
+	   (*x862-target-node-size* *x862-target-lcell-size*)
+           (*x862-target-half-fixnum-type* `(signed-byte ,(- *x862-target-bits-in-word*
+                                                            (1+ *x862-target-fixnum-shift*))))
+           (*x862-target-dnode-size* (* 2 *x862-target-lcell-size*))
+           (*x862-tos-reg* nil)
+           (*x862-all-lcells* ())
+           (*x862-top-vstack-lcell* nil)
+           (*x862-bottom-vstack-lcell* (x862-new-vstack-lcell :bottom 0 0 nil))
+           (*x862-var-cells* nil)
+           (*backend-vinsns* (backend-p2-vinsn-templates *target-backend*))
+           (*backend-node-regs* (target-arch-case
+				 (:x8632 x8632-node-regs)
+				 (:x8664 x8664-node-regs)))
+           (*backend-node-temps* (target-arch-case
+				  (:x8632 x8632-temp-node-regs)
+				  (:x8664 x8664-temp-node-regs)))
+           (*available-backend-node-temps* (target-arch-case
+					    (:x8632 x8632-temp-node-regs)
+					    (:x8664 x8664-temp-node-regs)))
+           (*backend-imm-temps* (target-arch-case
+				 (:x8632 x8632-imm-regs)
+				 (:x8664 x8664-imm-regs)))
+           (*available-backend-imm-temps* (target-arch-case
+					   (:x8632 x8632-imm-regs)
+					   (:x8664 x8664-imm-regs)))
+           (*backend-crf-temps* (target-arch-case
+				 (:x8632 x8632-cr-fields)
+				 (:x8664 x8664-cr-fields)))
+           (*available-backend-crf-temps* (target-arch-case
+					   (:x8632 x8632-cr-fields)
+					   (:x8664 x8664-cr-fields)))
+           (*backend-fp-temps* (target-arch-case
+				(:x8632 x8632-temp-fp-regs)
+				(:x8664 x8664-temp-fp-regs)))
+           (*available-backend-fp-temps* (target-arch-case
+					  (:x8632 x8632-temp-fp-regs)
+					  (:x8664 x8664-temp-fp-regs)))
+           (bits 0)
+           (*logical-register-counter* -1)
+           (*backend-all-lregs* ())
+           (*x862-popj-labels* nil)
+           (*x862-popreg-labels* nil)
+           (*x862-valret-labels* nil)
+           (*x862-nilret-labels* nil)
+           (*x862-undo-count* 0)
+           (*backend-labels* (x862-make-stack 64 target::subtag-simple-vector))
+           (*x862-undo-stack* (x862-make-stack 64  target::subtag-simple-vector))
+           (*x862-undo-because* (x862-make-stack 64))
+           (*x862-entry-label* nil)
+           (*x862-tail-label* nil)
+           (*x862-tail-vsp* nil)
+           (*x862-tail-nargs* nil)
+           (*x862-inhibit-register-allocation* nil)
+           (*x862-tail-allow* t)
+           (*x862-reckless* nil)
+           (*x862-full-safety* nil)
+           (*x862-trust-declarations* t)
+           (*x862-entry-vstack* nil)
+           (*x862-fixed-nargs* nil)
+           (*x862-need-nargs* t)
+           (fname (afunc-name afunc))
+           (*x862-entry-vsp-saved-p* nil)
+           (*x862-vcells* (x862-ensure-binding-indices-for-vcells (afunc-vcells afunc)))
+           (*x862-fcells* (afunc-fcells afunc))
+           *x862-recorded-symbols*
+           (*x862-emitted-source-notes* '()))
+      (set-fill-pointer
+       *backend-labels*
+       (set-fill-pointer
+        *x862-undo-stack*
+        (set-fill-pointer 
+         *x862-undo-because*
+         0)))
+      (backend-get-next-label)          ; start @ label 1, 0 is confused with NIL in compound cd
+      (with-dll-node-freelist (vinsns *vinsn-freelist*)
+        (unwind-protect
+             (progn
+               (setq bits (x862-toplevel-form vinsns (make-wired-lreg *x862-result-reg*)
+                                              $backend-return (afunc-acode afunc)))
+               (do* ((constants *x862-constant-alist* (cdr constants)))
+                    ((null constants))
+                 (let* ((imm (caar constants)))
+                   (when (x862-symbol-locative-p imm)
+                     (setf (caar constants) (car imm)))))
+               (optimize-vinsns vinsns)
+               (when (logbitp x862-debug-vinsns-bit *x862-debug-mask*)
+                 (format t "~% vinsns for ~s (after generation)" (afunc-name afunc))
+                 (do-dll-nodes (v vinsns) (format t "~&~s" v))
+                 (format t "~%~%"))
+            
+               (with-dll-node-freelist ((frag-list make-frag-list) *frag-freelist*)
+                 (with-dll-node-freelist ((uuo-frag-list make-frag-list) *frag-freelist*)
+                 (let* ((*x86-lap-labels* nil)
+                        (instruction (x86::make-x86-instruction))
+                        (end-code-tag (gensym))
+			(start-tag (gensym))
+			(srt-tag (gensym))
+                        debug-info)
+                   (make-x86-lap-label end-code-tag)
+		   (target-arch-case
+		    (:x8664
+		     (x86-lap-directive frag-list :long `(ash (+ (- (:^ ,end-code-tag ) 8)
+								 *x86-lap-entry-offset*) -3))
+		     (x86-lap-directive frag-list :byte 0) ;regsave PC 
+		     (x86-lap-directive frag-list :byte 0) ;regsave ea
+		     (x86-lap-directive frag-list :byte 0)) ;regsave mask
+		    (:x8632
+		     (make-x86-lap-label start-tag)
+		     (make-x86-lap-label srt-tag)
+		     (x86-lap-directive frag-list :short `(ash (+ (- (:^ ,end-code-tag) 4)
+								  *x86-lap-entry-offset*) -2))
+		     (emit-x86-lap-label frag-list start-tag)))
+                   (x862-expand-vinsns vinsns frag-list instruction uuo-frag-list)
+                   (when (or *x862-double-float-constant-alist*
+                             *x862-single-float-constant-alist*)
+                     (x86-lap-directive frag-list :align 3)
+                     (dolist (double-pair *x862-double-float-constant-alist*)
+                       (destructuring-bind (dfloat . lab) double-pair
+                         (setf (vinsn-label-info lab) (emit-x86-lap-label frag-list lab))
+                         (multiple-value-bind (high low)
+                             (x862-double-float-bits dfloat)
+                           (x86-lap-directive frag-list :long low)
+                           (x86-lap-directive frag-list :long high))))
+                     (dolist (single-pair *x862-single-float-constant-alist*)
+                       (destructuring-bind (sfloat . lab) single-pair
+                         (setf (vinsn-label-info lab) (emit-x86-lap-label frag-list lab))
+                         (let* ((val (single-float-bits sfloat)))
+                           (x86-lap-directive frag-list :long val)))))
+                   (target-arch-case
+		    (:x8632
+		     (x86-lap-directive frag-list :align 2)
+		     ;; start of self reference table
+		     (x86-lap-directive frag-list :long 0)
+		     (emit-x86-lap-label frag-list srt-tag)
+		     ;; make space for self-reference offsets
+		     (do-dll-nodes (frag frag-list)
+		       (dolist (reloc (frag-relocs frag))
+			 (when (eq (reloc-type reloc) :self)
+			   (x86-lap-directive frag-list :long 0))))
+		     (x86-lap-directive frag-list :long x8632::function-boundary-marker))
+		    (:x8664
+		     (x86-lap-directive frag-list :align 3)
+		     (x86-lap-directive frag-list :quad x8664::function-boundary-marker)))
+
+                   (emit-x86-lap-label frag-list end-code-tag)
+		   
+                   (dolist (c (reverse *x862-constant-alist*))
+                     (let* ((vinsn-label (cdr c)))
+                       (or (vinsn-label-info vinsn-label)
+                           (setf (vinsn-label-info vinsn-label)
+                                 (find-or-create-x86-lap-label
+                                  vinsn-label)))
+                       (emit-x86-lap-label frag-list vinsn-label)
+		       (target-arch-case
+			(:x8632
+			 (x86-lap-directive frag-list :long 0))
+			(:x8664
+			 (x86-lap-directive frag-list :quad 0)))))
+
+                   (if (logbitp $fbitnonnullenv (the fixnum (afunc-bits afunc)))
+                     (setq bits (+ bits (ash 1 $lfbits-nonnullenv-bit))))
+                   (setq debug-info (afunc-lfun-info afunc))
+                   (when (logbitp $fbitccoverage (the fixnum (afunc-bits afunc)))
+                     (setq bits (+ bits (ash 1 $lfbits-code-coverage-bit))))
+                   (when lambda-form
+                     (setq debug-info
+                           (list* 'function-lambda-expression lambda-form debug-info)))
+                   (when *x862-recorded-symbols*
+                     (setq debug-info
+                           (list* 'function-symbol-map *x862-recorded-symbols* debug-info)))
+                   (when (and (getf debug-info '%function-source-note) *x862-emitted-source-notes*)
+                     (setq debug-info                     ;; Compressed below
+                           (list* 'pc-source-map *x862-emitted-source-notes* debug-info)))
+                   (when debug-info
+                     (setq bits (logior (ash 1 $lfbits-info-bit) bits)))
+                   (unless (or fname lambda-form *x862-recorded-symbols*)
+                     (setq bits (logior (ash 1 $lfbits-noname-bit) bits)))
+                   (unless (afunc-parent afunc)
+                     (x862-fixup-fwd-refs afunc))
+                   (setf (afunc-all-vars afunc) nil)
+                   (setf (afunc-argsword afunc) bits)
+                   (let* ((regsave-label (if (typep *x862-compiler-register-save-label* 'vinsn-note)
+                                           (vinsn-label-info (vinsn-note-label *x862-compiler-register-save-label*))))
+                          (regsave-mask (if regsave-label (x862-register-mask-byte
+                                                           *x862-register-restore-count*)))
+                          (regsave-addr (if regsave-label (x862-encode-register-save-ea
+                                                           *x862-register-restore-ea*
+                                                           *x862-register-restore-count*))))
+		     (target-arch-case
+		      (:x8632
+		       (when debug-info
+			 (x86-lap-directive frag-list :long 0))
+		       (when fname
+			 (x86-lap-directive frag-list :long 0))
+		       (x86-lap-directive frag-list :long 0))
+		      (:x8664
+		       (when debug-info
+			 (x86-lap-directive frag-list :quad 0))
+		       (when fname
+			 (x86-lap-directive frag-list :quad 0))
+		       (x86-lap-directive frag-list :quad 0)))
+
+                     (relax-frag-list frag-list)
+                     (apply-relocs frag-list)
+                     (fill-for-alignment frag-list)
+		     (target-arch-case
+		      (:x8632
+		       (let* ((label (find-x86-lap-label srt-tag))
+			      (srt-frag (x86-lap-label-frag label))
+			      (srt-index (x86-lap-label-offset label)))
+			 ;; fill in self-reference offsets
+			 (do-dll-nodes (frag frag-list)
+			   (dolist (reloc (frag-relocs frag))
+			     (when (eq (reloc-type reloc) :self)
+			       (setf (frag-ref-32 srt-frag srt-index)
+				     (+ (frag-address frag) (reloc-pos reloc)))
+			       (incf srt-index 4)))))
+		       ;;(show-frag-bytes frag-list)
+		       ))
+
+                     (x862-lap-process-regsave-info frag-list regsave-label regsave-mask regsave-addr)
+
+                     (when (getf debug-info 'pc-source-map)
+                       (setf (getf debug-info 'pc-source-map) (x862-generate-pc-source-map debug-info)))
+                     (when (getf debug-info 'function-symbol-map)
+                       (setf (getf debug-info 'function-symbol-map) (x862-digest-symbols)))
+
+                     (setf (afunc-lfun afunc)
+                           #+x86-target
+                           (if (eq *host-backend* *target-backend*)
+                             (create-x86-function fname frag-list *x862-constant-alist* bits debug-info)
+                             (cross-create-x86-function fname frag-list *x862-constant-alist* bits debug-info))
+                           #-x86-target
+                           (cross-create-x86-function fname frag-list *x862-constant-alist* bits debug-info)))))))
+          (backend-remove-labels))))
+    afunc))
+
+
+      
+    
+(defun x862-make-stack (size &optional (subtype target::subtag-s16-vector))
+  (make-uarray-1 subtype size t 0 nil nil nil nil t nil))
+
+(defun x862-fixup-fwd-refs (afunc)
+  (dolist (f (afunc-inner-functions afunc))
+    (x862-fixup-fwd-refs f))
+  (let ((fwd-refs (afunc-fwd-refs afunc)))
+    (when fwd-refs
+      (let* ((native-x86-functions #-x86-target nil
+                                   #+x86-target (eq *target-backend*
+                                                    *host-backend*))
+             (v (if native-x86-functions
+                  (function-to-function-vector (afunc-lfun afunc))
+                  (afunc-lfun afunc)))
+             (vlen (uvsize v)))
+        (declare (fixnum vlen))
+        (dolist (ref fwd-refs)
+          (let* ((ref-fun (afunc-lfun ref)))
+            (do* ((i (if native-x86-functions
+                       (%function-code-words
+                        (function-vector-to-function v))
+                       1)
+                     (1+ i)))
+                 ((= i vlen))
+              (declare (fixnum i))
+              (if (eq (%svref v i) ref)
+                (setf (%svref v i) ref-fun)))))))))
+
+(defun x862-generate-pc-source-map (debug-info)
+  (let* ((definition-source-note (getf debug-info '%function-source-note))
+         (emitted-source-notes (getf debug-info 'pc-source-map))
+         (def-start (source-note-start-pos definition-source-note))
+         (n (length emitted-source-notes))
+         (nvalid 0)
+         (max 0)
+         (pc-starts (make-array n))
+         (pc-ends (make-array n))
+         (text-starts (make-array n))
+         (text-ends (make-array n)))
+    (declare (fixnum n nvalid)
+             (dynamic-extent pc-starts pc-ends text-starts text-ends))
+    (dolist (start emitted-source-notes)
+      (let* ((pc-start (x862-vinsn-note-label-address start t))
+             (pc-end (x862-vinsn-note-label-address (vinsn-note-peer start) nil))
+             (source-note (aref (vinsn-note-info start) 0))
+             (text-start (- (source-note-start-pos source-note) def-start))
+             (text-end (- (source-note-end-pos source-note) def-start)))
+        (declare (fixnum pc-start pc-end text-start text-end))
+        (when (and (plusp pc-start)
+                   (plusp pc-end)
+                   (plusp text-start)
+                   (plusp text-end))
+          (if (> pc-start max) (setq max pc-start))
+          (if (> pc-end max) (setq max pc-end))
+          (if (> text-start max) (setq max text-start))
+          (if (> text-end max) (setq max text-end))
+          (setf (svref pc-starts nvalid) pc-start
+                (svref pc-ends nvalid) pc-end
+                (svref text-starts nvalid) text-start
+                (svref text-ends nvalid) text-end)
+          (incf nvalid))))
+    (let* ((nentries (* nvalid 4))
+           (vec (cond ((< max #x100) (make-array nentries :element-type '(unsigned-byte 8)))
+                      ((< max #x10000) (make-array nentries :element-type '(unsigned-byte 16)))
+                      (t (make-array nentries :element-type '(unsigned-byte 32))))))
+      (declare (fixnum nentries))
+      (do* ((i 0 (+ i 4))
+            (j 1 (+ j 4))
+            (k 2 (+ k 4))
+            (l 3 (+ l 4))
+            (idx 0 (1+ idx)))
+          ((= i nentries) vec)
+        (declare (fixnum i j k l idx))
+        (setf (aref vec i) (svref pc-starts idx)
+              (aref vec j) (svref pc-ends idx)
+              (aref vec k) (svref text-starts idx)
+              (aref vec l) (svref text-ends idx))))))
+
+(defun x862-vinsn-note-label-address (note &optional start-p sym)
+  (-
+   (let* ((label (vinsn-note-label note))
+          (lap-label (if label (vinsn-label-info label))))
+     (if lap-label
+       (x86-lap-label-address lap-label)
+       (compiler-bug "Missing or bad ~s label~@[: ~s~]"
+                     (if start-p 'start 'end)
+                     sym)))
+   (target-arch-case
+    (:x8632 x8632::fulltag-misc)        ;xxx?
+    (:x8664 x8664::fulltag-function))))
+
+(defun x862-digest-symbols ()
+  (when *x862-recorded-symbols*
+    (setq *x862-recorded-symbols* (nx2-recorded-symbols-in-arglist-order *x862-recorded-symbols* *x862-cur-afunc*))
+    (let* ((symlist *x862-recorded-symbols*)
+           (len (length symlist))
+           (syms (make-array len))
+           (ptrs (make-array (%i+  (%i+ len len) len)))
+           (i -1)
+           (j -1))
+      (declare (fixnum i j))
+      (dolist (info symlist (progn (%rplaca symlist syms)
+                                   (%rplacd symlist ptrs)))
+        (destructuring-bind (var sym startlab endlab) info
+          (let* ((ea (var-ea var))
+                 (ea-val (ldb (byte 16 0) ea)))
+            (setf (aref ptrs (incf i)) (if (memory-spec-p ea)
+                                         (logior (ash ea-val 6) #o77)
+                                         ea-val)))
+          (setf (aref syms (incf j)) sym)
+          (setf (aref ptrs (incf i)) (x862-vinsn-note-label-address startlab t sym))
+          (setf (aref ptrs (incf i)) (x862-vinsn-note-label-address endlab nil sym))))
+      *x862-recorded-symbols*)))
+
+(defun x862-decls (decls)
+  (if (fixnump decls)
+    (locally (declare (fixnum decls))
+      (setq *x862-tail-allow* (neq 0 (%ilogand2 $decl_tailcalls decls))
+            *x862-open-code-inline* (neq 0 (%ilogand2 $decl_opencodeinline decls))
+            *x862-full-safety* (neq 0 (%ilogand2 $decl_full_safety decls))
+            *x862-reckless* (neq 0 (%ilogand2 $decl_unsafe decls))
+            *x862-trust-declarations* (neq 0 (%ilogand2 $decl_trustdecls decls))))))
+
+
+    
+;;; Vpush the last N non-volatile-registers.
+(defun x862-save-nvrs (seg n)
+  (declare (fixnum n))
+  (target-arch-case
+   ;; no nvrs on x8632
+   (:x8664
+    (when (> n 0)
+      (setq *x862-compiler-register-save-label* (x862-emit-note seg :regsave))
+      (with-x86-local-vinsn-macros (seg)
+	(let* ((mask x8664-nonvolatile-node-regs))
+	  (dotimes (i n)
+	    (let* ((reg (1- (integer-length mask))))
+	      (x862-vpush-register seg reg :regsave reg 0)
+	      (setq mask (logandc2 mask (ash 1 reg)))))))
+      (setq *x862-register-restore-ea* *x862-vstack*
+	    *x862-register-restore-count* n)))))
+
+
+;;; If there are an indefinite number of args/values on the vstack,
+;;; we have to restore from a register that matches the compiler's
+;;; notion of the vstack depth.  This can be computed by the caller 
+;;; (sum of vsp & nargs, or copy of vsp  before indefinite number of 
+;;; args pushed, etc.)
+
+
+(defun x862-restore-nvrs (seg ea nregs &optional (can-pop t))
+  (target-arch-case
+   ;; no nvrs on x8632
+   (:x8664
+    (when (and ea nregs)
+      (with-x86-local-vinsn-macros (seg)
+	(let* ((mask x8664-nonvolatile-node-regs)
+	       (regs ()))
+	  (dotimes (i nregs)
+	    (let* ((reg (1- (integer-length mask))))
+	      (push reg regs)
+	      (setq mask (logandc2 mask (ash 1 reg)))))
+	  (cond (can-pop
+		 (let* ((diff-in-bytes (- *x862-vstack* ea)))
+		   (unless (zerop diff-in-bytes)
+		     (x862-adjust-vstack diff-in-bytes)
+		     (! vstack-discard (floor diff-in-bytes *x862-target-node-size*)))
+		   (dolist (reg regs)
+		     (! vpop-register reg))))
+		(t
+		 (dolist (reg regs)
+		   (! vframe-load reg (- ea *x862-target-node-size*) ea)
+		   (decf ea *x862-target-node-size*))))))))))
+
+
+(defun x862-bind-lambda (seg lcells req opt rest keys auxen optsupvloc passed-in-regs lexpr &optional inherited
+                             &aux (vloc 0) (numopt (list-length (%car opt)))
+                             (nkeys (list-length (%cadr keys))) 
+                             reg)
+  (declare (fixnum vloc))
+  (x862-check-lcell-depth)
+  (dolist (arg inherited)
+    (if (memq arg passed-in-regs)
+      (x862-set-var-ea seg arg (var-ea arg))
+      (let* ((lcell (pop lcells)))
+        (if (setq reg (nx2-assign-register-var arg))
+          (x862-init-regvar seg arg reg (x862-vloc-ea vloc))
+          (x862-bind-var seg arg vloc lcell))
+        (setq vloc (%i+ vloc *x862-target-node-size*)))))
+  (dolist (arg req)
+    (if (memq arg passed-in-regs)
+      (x862-set-var-ea seg arg (var-ea arg))
+      (let* ((lcell (pop lcells)))
+        (if (setq reg (nx2-assign-register-var arg))
+          (x862-init-regvar seg arg reg (x862-vloc-ea vloc))
+          (x862-bind-var seg arg vloc lcell))
+        (setq vloc (%i+ vloc *x862-target-node-size*)))))
+  (when opt
+    (if (x862-hard-opt-p opt)
+      (setq vloc (apply #'x862-initopt seg vloc optsupvloc lcells (nthcdr (- (length lcells) numopt) lcells) opt)
+            lcells (nthcdr numopt lcells))
+
+      (dolist (var (%car opt))
+        (if (memq var passed-in-regs)
+          (x862-set-var-ea seg var (var-ea var))
+          (let* ((lcell (pop lcells)))
+            (if (setq reg (nx2-assign-register-var var))
+              (x862-init-regvar seg var reg (x862-vloc-ea vloc))
+              (x862-bind-var seg var vloc lcell))
+            (setq vloc (+ vloc *x862-target-node-size*)))))))
+
+  (when rest
+    (if lexpr
+      (progn
+        (if (setq reg (nx2-assign-register-var rest))
+          (progn
+            (x862-copy-register seg reg *x862-arg-z*)
+            (x862-set-var-ea seg rest reg))
+            (let* ((loc *x862-vstack*))
+              (x862-vpush-register seg *x862-arg-z* :reserved)
+              (x862-note-top-cell rest)
+              (x862-bind-var seg rest loc *x862-top-vstack-lcell*))))
+      (let* ((rvloc (+ vloc (* 2 *x862-target-node-size* nkeys))))
+        (if (setq reg (nx2-assign-register-var rest))
+          (x862-init-regvar seg rest reg (x862-vloc-ea rvloc))
+          (x862-bind-var seg rest rvloc (pop lcells))))))
+    (when keys
+      (apply #'x862-init-keys seg vloc lcells keys))
+  (x862-seq-bind seg (%car auxen) (%cadr auxen)))
+
+
+(defun x862-initopt (seg vloc spvloc lcells splcells vars inits spvars)
+  (with-x86-local-vinsn-macros (seg)
+    (dolist (var vars vloc)
+      (let* ((initform (pop inits))
+             (spvar (pop spvars))
+             (lcell (pop lcells))
+             (splcell (pop splcells))
+             (reg (nx2-assign-register-var var))
+             (regloadedlabel (if reg (backend-get-next-label))))
+        (unless (nx-null initform)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (x862-compare-ea-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) (x862-vloc-ea spvloc)  x86::x86-e-bits t))
+            (if reg
+              (x862-form seg reg regloadedlabel initform)
+              (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc)))
+            (@ skipinitlabel)))
+        (if reg
+          (progn
+            (x862-init-regvar seg var reg (x862-vloc-ea vloc))
+            (@ regloadedlabel))
+          (x862-bind-var seg var vloc lcell))
+        (when spvar
+          (if (setq reg (nx2-assign-register-var spvar))
+            (x862-init-regvar seg spvar reg (x862-vloc-ea spvloc))
+            (x862-bind-var seg spvar spvloc splcell))))
+      (setq vloc (%i+ vloc *x862-target-node-size*))
+      (if spvloc (setq spvloc (%i+ spvloc *x862-target-node-size*))))))
+
+(defun x862-init-keys (seg vloc lcells allow-others keyvars keysupp keyinits keykeys)
+  (declare (ignore keykeys allow-others))
+  (with-x86-local-vinsn-macros (seg)
+    (dolist (var keyvars)
+      (let* ((spvar (pop keysupp))
+             (initform (pop keyinits))
+             (reg (nx2-assign-register-var var))
+             (regloadedlabel (if reg (backend-get-next-label)))
+             (var-lcell (pop lcells))
+             (sp-lcell (pop lcells))
+             (sploc (%i+ vloc *x862-target-node-size*)))
+        (unless (nx-null initform)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (x862-compare-ea-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) (x862-vloc-ea sploc)  x86::x86-e-bits t))
+            (if reg
+              (x862-form seg reg regloadedlabel initform)
+              (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc)))
+            (@ skipinitlabel)))
+        (if reg
+          (progn
+            (x862-init-regvar seg var reg (x862-vloc-ea vloc))
+            (@ regloadedlabel))
+          (x862-bind-var seg var vloc var-lcell))
+        (when spvar
+          (if (setq reg (nx2-assign-register-var spvar))
+            (x862-init-regvar seg spvar reg (x862-vloc-ea sploc))
+            (x862-bind-var seg spvar sploc sp-lcell))))
+      (setq vloc (%i+ vloc (* 2 *x862-target-node-size*))))))
+
+;;; Vpush register r, unless var gets a globally-assigned register.
+;;; Return NIL if register was vpushed, else var.
+(defun x862-vpush-arg-register (seg reg var)
+  (when var
+    (if (var-nvr var)
+      var
+      (progn 
+        (x862-vpush-register seg reg :reserved)
+        nil))))
+
+
+;;; nargs has been validated, arguments defaulted and canonicalized.
+;;; Save caller's context, then vpush any argument registers that
+;;; didn't get global registers assigned to their variables.
+;;; Return a list of vars/nils for each argument register 
+;;;  (nil if vpushed, var if still in arg_reg).
+(defun x862-argregs-entry (seg revargs &optional variable-args-entry)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((nargs (length revargs))
+           (reg-vars ()))
+      (declare (type (unsigned-byte 16) nargs))
+      (unless variable-args-entry
+        (if (<= nargs *x862-target-num-arg-regs*) ; caller didn't vpush anything
+          (! save-lisp-context-no-stack-args)
+          (let* ((offset (* (the fixnum (- nargs *x862-target-num-arg-regs*)) *x862-target-node-size*)))
+            (declare (fixnum offset))
+            (! save-lisp-context-offset offset))))
+      (target-arch-case
+       (:x8632
+	(destructuring-bind (&optional zvar yvar &rest stack-args) revargs
+	  (let* ((nstackargs (length stack-args)))
+	    (x862-set-vstack (* nstackargs *x862-target-node-size*))
+	    (dotimes (i nstackargs)
+	      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil))
+	    (if (>= nargs 2)
+	      (push (x862-vpush-arg-register seg ($ *x862-arg-y*) yvar) reg-vars))
+	    (if (>= nargs 1)
+	      (push (x862-vpush-arg-register seg ($ *x862-arg-z*) zvar) reg-vars)))))
+       (:x8664
+	(destructuring-bind (&optional zvar yvar xvar &rest stack-args) revargs
+	  (let* ((nstackargs (length stack-args)))
+	    (x862-set-vstack (* nstackargs *x862-target-node-size*))
+	    (dotimes (i nstackargs)
+	      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil))
+	    (if (>= nargs 3)
+	      (push (x862-vpush-arg-register seg ($ x8664::arg_x) xvar) reg-vars))
+	    (if (>= nargs 2)
+	      (push (x862-vpush-arg-register seg ($ *x862-arg-y*) yvar) reg-vars))
+	    (if (>= nargs 1)
+	      (push (x862-vpush-arg-register seg ($ *x862-arg-z*) zvar) reg-vars))))))
+      reg-vars)))
+
+;;; Just required args.
+;;; Since this is just a stupid bootstrapping port, always save 
+;;; lisp context.
+(defun x862-req-nargs-entry (seg rev-fixed-args)
+  (let* ((nargs (length rev-fixed-args)))
+    (declare (type (unsigned-byte 16) nargs))
+    (with-x86-local-vinsn-macros (seg)
+      (unless *x862-reckless*
+        (! check-exact-nargs nargs))
+      (x862-argregs-entry seg rev-fixed-args))))
+
+;;; No more &optional args than register args; all &optionals default
+;;; to NIL and none have supplied-p vars.  No &key/&rest.
+(defun x862-simple-opt-entry (seg rev-opt-args rev-req-args)
+  (let* ((min (length rev-req-args))
+         (nopt (length rev-opt-args))
+         (max (+ min nopt)))
+    (declare (type (unsigned-byte 16) min nopt max))
+    (with-x86-local-vinsn-macros (seg)
+      (unless *x862-reckless*
+        (if rev-req-args
+          (! check-min-max-nargs min max)
+          (! check-max-nargs max)))
+      (if (> min *x862-target-num-arg-regs*)
+        (! save-lisp-context-in-frame)
+        (if (<= max *x862-target-num-arg-regs*)
+          (! save-lisp-context-no-stack-args)
+          (! save-lisp-context-variable-arg-count)))
+      (if (= nopt 1)
+        (! default-1-arg min)
+        (if (= nopt 2)
+          (! default-2-args min)
+          (! default-3-args min)))
+      (x862-argregs-entry seg (append rev-opt-args rev-req-args) t))))
+
+;;; if "num-fixed" is > 0, we've already ensured that at least that many args
+;;; were provided; that may enable us to generate better code for saving the
+;;; argument registers.
+;;; We're responsible for computing the caller's VSP and saving
+;;; caller's state.
+(defun x862-lexpr-entry (seg num-fixed)
+  (with-x86-local-vinsn-macros (seg)
+    (! save-lexpr-argregs num-fixed)
+    ;; The "lexpr" (address of saved nargs register, basically
+    ;; is now in arg_z
+    (! build-lexpr-frame)
+    (dotimes (i num-fixed)
+      (! copy-lexpr-argument (- num-fixed i)))))
+
+
+(defun x862-structured-initopt (seg lcells vloc context vars inits spvars)
+  (with-x86-local-vinsn-macros (seg)
+    (dolist (var vars vloc)
+      (let* ((initform (pop inits))
+             (spvar (pop spvars))
+             (spvloc (%i+ vloc *x862-target-node-size*))
+             (var-lcell (pop lcells))
+             (sp-lcell (pop lcells)))
+        (unless (nx-null initform)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (x862-compare-ea-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) (x862-vloc-ea spvloc) x86::x86-e-bits t))
+            (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc))
+            (@ skipinitlabel)))
+        (x862-bind-structured-var seg var vloc var-lcell context)
+        (when spvar
+          (x862-bind-var seg spvar spvloc sp-lcell)))
+      (setq vloc (%i+ vloc (* 2 *x862-target-node-size*))))))
+
+
+
+(defun x862-structured-init-keys (seg lcells vloc context allow-others keyvars keysupp keyinits keykeys)
+  (declare (ignore keykeys allow-others))
+  (with-x86-local-vinsn-macros (seg)
+    (dolist (var keyvars)
+      (let* ((spvar (pop keysupp))
+             (initform (pop keyinits))
+             (sploc (%i+ vloc *x862-target-node-size*))
+             (var-lcell (pop lcells))
+             (sp-reg ($ *x862-arg-z*))
+             (sp-lcell (pop lcells)))
+        (unless (nx-null initform)
+          (x862-stack-to-register seg (x862-vloc-ea sploc) sp-reg)
+          (let ((skipinitlabel (backend-get-next-label)))
+            (with-crf-target () crf
+              (x862-compare-register-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) sp-reg x86::x86-e-bits t))
+            (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc))
+            (@ skipinitlabel)))
+        (x862-bind-structured-var seg var vloc var-lcell context)
+        (when spvar
+          (x862-bind-var seg spvar sploc sp-lcell)))
+      (setq vloc (%i+ vloc (* 2 *x862-target-node-size*))))))
+
+(defun x862-vloc-ea (n &optional vcell-p)
+  (setq n (make-memory-spec (dpb memspec-frame-address memspec-type-byte n)))
+  (if vcell-p
+    (make-vcell-memory-spec n)
+    n))
+
+
+(defun x862-acode-operator-function (form)
+  (or (and (acode-p form)
+           (svref *x862-specials* (%ilogand #.operator-id-mask (acode-operator form))))
+      (compiler-bug "x862-form ? ~s" form)))
+
+(defmacro with-note ((form-var seg-var) &body body)
+  (let* ((note (gensym "NOTE"))
+         (code-note (gensym "CODE-NOTE"))
+         (source-note (gensym "SOURCE-NOTE"))
+         (start (gensym "START"))
+         (end (gensym "END")))
+    `(let* ((,note (acode-note ,form-var))
+            (,code-note (and (code-note-p ,note) ,note))
+            (,source-note (if ,code-note
+                            (code-note-source-note ,note)
+                            ,note))
+            (,start (and ,source-note
+                         (x862-emit-note ,seg-var :source-location-begin ,source-note))))
+      #+debug-code-notes (require-type ,note '(or null code-note source-note))
+      (when ,code-note
+        (with-x86-local-vinsn-macros (,seg-var)
+          (x862-store-immediate ,seg-var ,code-note *x862-codecoverage-reg*)
+          (! misc-set-immediate-c-node 0 *x862-codecoverage-reg* 1)))
+      (prog1
+          (progn
+            ,@body)
+        (when ,source-note
+          (let ((,end (x862-emit-note ,seg-var :source-location-end)))
+            (setf (vinsn-note-peer ,start) ,end
+                  (vinsn-note-peer ,end) ,start)
+            (push ,start *x862-emitted-source-notes*)))))))
+
+(defun x862-toplevel-form (seg vreg xfer form)
+  (let* ((code-note (acode-note form))
+         (args (if code-note `(,@(%cdr form) ,code-note) (%cdr form))))
+    (apply (x862-acode-operator-function form) seg vreg xfer args)))
+
+(defun x862-form (seg vreg xfer form)
+  (with-note (form seg)
+    (if (nx-null form)
+      (x862-nil seg vreg xfer)
+      (if (nx-t form)
+        (x862-t seg vreg xfer)
+        (let* ((fn (x862-acode-operator-function form)) ;; also typechecks
+               (op (acode-operator form)))
+          (if (and (null vreg)
+                   (%ilogbitp operator-acode-subforms-bit op)
+                   (%ilogbitp operator-assignment-free-bit op))
+            (dolist (f (%cdr form) (x862-branch seg xfer))
+              (x862-form seg nil nil f ))
+            (apply fn seg vreg xfer (%cdr form))))))))
+
+;;; dest is a float reg - form is acode
+(defun x862-form-float (seg freg xfer form)
+  (declare (ignore xfer))
+  (with-note (form seg)
+    (when (or (nx-null form)(nx-t form))(compiler-bug "x862-form to freg ~s" form))
+    (when (and (= (get-regspec-mode freg) hard-reg-class-fpr-mode-double)
+               (x862-form-typep form 'double-float))
+      ;; kind of screwy - encoding the source type in the dest register spec
+      (set-node-regspec-type-modes freg hard-reg-class-fpr-type-double))
+    (let* ((fn (x862-acode-operator-function form)))
+      (apply fn seg freg nil (%cdr form)))))
+
+
+(defun x862-form-typep (form type)
+  (acode-form-typep form type *x862-trust-declarations*)
+)
+
+(defun x862-form-type (form)
+  (acode-form-type form *x862-trust-declarations*))
+  
+(defun x862-use-operator (op seg vreg xfer &rest forms)
+  (declare (dynamic-extent forms))
+  (apply (svref *x862-specials* (%ilogand operator-id-mask op)) seg vreg xfer forms))
+
+
+(defun x862-check-fixnum-overflow (seg target &optional labelno)
+  (with-x86-local-vinsn-macros (seg)
+    (if *x862-open-code-inline*
+      (let* ((no-overflow (backend-get-next-label)))
+        (! handle-fixnum-overflow-inline target (aref *backend-labels* (or labelno no-overflow)))
+        (when labelno (-> labelno))
+        (@ no-overflow))
+      (if labelno
+        (! fix-fixnum-overflow-ool-and-branch target (aref *backend-labels* labelno))
+        (! fix-fixnum-overflow-ool target)))))
+
+(defun x862-nil (seg vreg xfer)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if (eq vreg :push)
+      (progn
+        (! vpush-fixnum (target-nil-value))
+        (^))
+      (progn
+        (if (x862-for-value-p vreg)
+          (ensuring-node-target (target vreg)
+            (! load-nil target)))
+        (x862-branch seg (x862-cd-false xfer))))))
+
+(defun x862-t (seg vreg xfer)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if (eq vreg :push)
+      (progn
+        (! vpush-fixnum (target-t-value))
+        (^))
+      (progn
+        (if (x862-for-value-p vreg)
+          (ensuring-node-target (target vreg)
+            (! load-t target)))
+        (x862-branch seg (x862-cd-true xfer))))))
+
+(defun x862-for-value-p (vreg)
+  (and vreg (not (backend-crf-p vreg))))
+
+(defun x862-mvpass (seg form &optional xfer)
+  (with-x86-local-vinsn-macros (seg)
+    (x862-form seg  ($ *x862-arg-z*) (logior (or xfer 0) $backend-mvpass-mask) form)))
+
+(defun x862-adjust-vstack (delta)
+  (x862-set-vstack (%i+ *x862-vstack* delta)))
+
+(defun x862-set-vstack (new)
+  (setq *x862-vstack* (or new 0)))
+
+
+;;; Emit a note at the end of the segment.
+(defun x862-emit-note (seg class &rest info)
+  (declare (dynamic-extent info))
+  (let* ((note (make-vinsn-note class info)))
+    (append-dll-node (vinsn-note-label note) seg)
+    note))
+
+;;; Emit a note immediately before the target vinsn.
+(defun x86-prepend-note (vinsn class &rest info)
+  (declare (dynamic-extent info))
+  (let* ((note (make-vinsn-note class info)))
+    (insert-dll-node-before (vinsn-note-label note) vinsn)
+    note))
+
+(defun x862-close-note (seg note)
+  (let* ((end (close-vinsn-note note)))
+    (append-dll-node (vinsn-note-label end) seg)
+    end))
+
+
+
+
+
+
+(defun x862-stack-to-register (seg memspec reg)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((offset (memspec-frame-address-offset memspec)))
+      (if (and *x862-tos-reg*
+               (= offset (- *x862-vstack* *x862-target-node-size*)))
+        (x862-copy-register seg reg *x862-tos-reg*)
+        (! vframe-load reg offset  *x862-vstack*)))))
+
+(defun x862-lcell-to-register (seg lcell reg)
+  (with-x86-local-vinsn-macros (seg)
+    (! lcell-load reg lcell (x862-vstack-mark-top))))
+
+(defun x862-register-to-lcell (seg reg lcell)
+  (with-x86-local-vinsn-macros (seg)
+    (! lcell-store reg lcell (x862-vstack-mark-top))))
+
+(defun x862-register-to-stack (seg reg memspec)
+  (with-x86-local-vinsn-macros (seg)
+    (! vframe-store reg (memspec-frame-address-offset memspec) *x862-vstack*)))
+
+
+(defun x862-ea-open (ea)
+  (if (and ea (not (typep ea 'lreg)) (addrspec-vcell-p ea))
+    (make-memory-spec (memspec-frame-address-offset ea))
+    ea))
+
+(defun x862-set-NARGS (seg n)
+  (if (> n call-arguments-limit)
+    (error "~s exceeded." call-arguments-limit)
+    (with-x86-local-vinsn-macros (seg)
+      (! set-nargs n))))
+
+
+
+(defun x862-single-float-bits (the-sf)
+  (single-float-bits the-sf))
+
+(defun x862-double-float-bits (the-df)
+  (double-float-bits the-df))
+
+(defun x862-push-immediate (seg xfer form)
+  (with-x86-local-vinsn-macros (seg)
+    (if (typep form 'character)
+      (! vpush-fixnum (logior (ash (char-code form) 8)
+			      (arch::target-subtag-char (backend-target-arch *target-backend*))))
+      (let* ((reg (x862-register-constant-p form)))
+        (if reg
+          (! vpush-register reg)
+          (let* ((lab (x86-immediate-label form)))
+            (! vpush-constant lab)))))
+    (x862-branch seg xfer)))
+
+      
+(pushnew (%nx1-operator immediate) *x862-operator-supports-push*)  
+(defun x862-immediate (seg vreg xfer form)
+  (if (eq vreg :push)
+    (x862-push-immediate seg xfer form)
+    (with-x86-local-vinsn-macros (seg vreg xfer)
+      (if vreg
+        (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+                 (or (and (typep form 'double-float) (= (get-regspec-mode vreg) hard-reg-class-fpr-mode-double))
+                     (and (typep form 'short-float)(= (get-regspec-mode vreg) hard-reg-class-fpr-mode-single))))
+          (if (zerop form)
+            (if (eql form 0.0d0)
+              (! zero-double-float-register vreg)
+              (! zero-single-float-register vreg))
+            (if (typep form 'short-float)
+              (let* ((lab (x86-single-float-constant-label form)))
+                (! load-single-float-constant vreg lab))
+              (let* ((lab (x86-double-float-constant-label form)))
+                (! load-double-float-constant vreg lab))))
+	  (target-arch-case
+	   (:x8632
+	    (if (and (= (hard-regspec-class vreg) hard-reg-class-gpr)
+		     (member (get-regspec-mode vreg)
+			     '(hard-reg-class-gpr-mode-u32
+			       hard-reg-class-gpr-mode-s32
+			       hard-reg-class-gpr-mode-address))
+		     (or (typep form '(unsigned-byte 32))
+			 (typep form '(signed-byte 32))))
+	      ;; The bits fit.  Get them in the register somehow.
+	      (if (typep form '(signed-byte 32))
+		(x862-lri seg vreg form)
+		(x862-lriu seg vreg form))
+	      (ensuring-node-target (target vreg)
+		(if (characterp form)
+		  (! load-character-constant target (char-code form))
+		  (x862-store-immediate seg form target)))))
+	   (:x8664
+	    (if (and (typep form '(unsigned-byte 32))
+		     (= (hard-regspec-class vreg) hard-reg-class-gpr)
+		     (= (get-regspec-mode vreg)
+			hard-reg-class-gpr-mode-u32))
+	      (x862-lri seg vreg form)
+	      (ensuring-node-target
+		  (target vreg)
+		(if (characterp form)
+		  (! load-character-constant target (char-code form))
+		  (x862-store-immediate seg form target)))))))
+        (if (and (listp form) *load-time-eval-token* (eq (car form) *load-time-eval-token*))
+          (x862-store-immediate seg form ($ *x862-temp0*))))
+      (^))))
+
+(defun x862-register-constant-p (form)
+  (and (consp form)
+           (or (memq form *x862-vcells*)
+               (memq form *x862-fcells*))
+           (%cdr form)))
+
+(defun x862-store-immediate (seg imm dest)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((reg (x862-register-constant-p imm)))
+      (if reg
+        (x862-copy-register seg dest reg)
+        (let* ((lab (x86-immediate-label imm)))
+          (! ref-constant dest lab)))
+      dest)))
+
+
+;;; Returns label iff form is (local-go <tag>) and can go without adjusting stack.
+(defun x862-go-label (form)
+  (let ((current-stack (x862-encode-stack)))
+    (while (and (acode-p form) (or (eq (acode-operator form) (%nx1-operator progn))
+                                   (eq (acode-operator form) (%nx1-operator local-tagbody))))
+      (setq form (caadr form)))
+    (when (acode-p form)
+      (let ((op (acode-operator form)))
+        (if (and (eq op (%nx1-operator local-go))
+                 (x862-equal-encodings-p (%caddr (%cadr form)) current-stack))
+          (%cadr (%cadr form))
+          (if (and (eq op (%nx1-operator local-return-from))
+                   (nx-null (caddr form)))
+            (let ((tagdata (car (cadr form))))
+              (and (x862-equal-encodings-p (cdr tagdata) current-stack)
+                   (null (caar tagdata))
+                   (< 0 (cdar tagdata) $backend-mvpass)
+                   (cdar tagdata)))))))))
+
+(defun x862-single-valued-form-p (form)
+  (setq form (acode-unwrapped-form-value form))
+  (or (nx-null form)
+      (nx-t form)
+      (if (acode-p form)
+        (let ((op (acode-operator form)))
+          (or (%ilogbitp operator-single-valued-bit op)
+              (and (eql op (%nx1-operator values))
+                   (let ((values (cadr form)))
+                     (and values (null (cdr values)))))
+              nil                       ; Learn about functions someday
+              )))))
+
+(defun x862-box-s32 (seg node-dest s32-src)
+  (with-x86-local-vinsn-macros (seg)
+    (if (target-arch-case
+         (:x8632 nil)
+         (:x8664 t))
+      (! box-fixnum node-dest s32-src)
+      (let* ((arg_z ($ *x862-arg-z*))
+             (imm0 ($ *x862-imm0* :mode :s32)))
+        (x862-copy-register seg imm0 s32-src)
+        (! call-subprim (subprim-name->offset '.SPmakes32))
+        (x862-copy-register seg node-dest arg_z)))))
+
+(defun x862-box-s64 (seg node-dest s64-src)
+  (with-x86-local-vinsn-macros (seg)
+    (if (target-arch-case
+	 (:x8632 (error "bug"))
+         (:x8664 *x862-open-code-inline*))
+      (let* ((no-overflow (backend-get-next-label)))
+        (! %set-z-flag-if-s64-fits-in-fixnum node-dest s64-src)
+        (! cbranch-true (aref *backend-labels* no-overflow) x86::x86-e-bits)
+        (! setup-bignum-alloc-for-s64-overflow s64-src)
+        (! %allocate-uvector node-dest)
+        (! set-bigits-after-fixnum-overflow node-dest)
+        (@ no-overflow))
+      (let* ((arg_z ($ *x862-arg-z*))
+             (imm0 (make-wired-lreg *x862-imm0* :mode (get-regspec-mode s64-src))))
+        (x862-copy-register seg imm0 s64-src)
+        (! call-subprim (subprim-name->offset '.SPmakes64))
+        (x862-copy-register seg node-dest arg_z)))))
+
+(defun x862-box-u32 (seg node-dest u32-src)
+  (with-x86-local-vinsn-macros (seg)
+    (target-arch-case
+     (:x8632
+      (let* ((arg_z ($ *x862-arg-z*))
+	     (imm0 ($ *x862-imm0* :mode :u32)))
+	(x862-copy-register seg imm0 u32-src)
+	(! call-subprim (subprim-name->offset '.SPmakeu32))
+	(x862-copy-register seg node-dest arg_z)))
+     (:x8664
+      (! box-fixnum node-dest u32-src)))))
+
+(defun x862-box-u64 (seg node-dest u64-src)
+  (with-x86-local-vinsn-macros (seg)
+    (if (target-arch-case
+         (:x8632 (error "bug"))
+         (:x8664 *x862-open-code-inline*))
+      (let* ((no-overflow (backend-get-next-label)))
+        (! %set-z-flag-if-u64-fits-in-fixnum node-dest u64-src)
+        (! cbranch-true (aref *backend-labels* no-overflow) x86::x86-e-bits)
+        (! setup-bignum-alloc-for-u64-overflow u64-src)
+        (! %allocate-uvector node-dest)
+        (! set-bigits-after-fixnum-overflow node-dest)
+        (@ no-overflow))
+      (let* ((arg_z ($ *x862-arg-z*))
+             (imm0 ($ *x862-imm0* :mode :u64)))
+        (x862-copy-register seg imm0 u64-src)
+        (! call-subprim (subprim-name->offset '.SPmakeu64))
+        (x862-copy-register seg node-dest arg_z)))))
+
+(defun x862-single->heap (seg dest src)
+  (with-x86-local-vinsn-macros (seg)
+    (! setup-single-float-allocation)
+    (! %allocate-uvector dest)
+    (! set-single-float-value dest src)))
+
+(defun x862-double->heap (seg dest src)
+  (with-x86-local-vinsn-macros (seg)
+    (! setup-double-float-allocation)
+    (! %allocate-uvector dest)
+    (! set-double-float-value dest src)))
+
+
+(defun x862-vref1 (seg vreg xfer type-keyword src unscaled-idx index-known-fixnum)  
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (let* ((arch (backend-target-arch *target-backend*))
+             (is-node (member type-keyword (arch::target-gvector-types arch)))
+             (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
+
+             (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+             (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+             (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+             (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+             (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
+             (vreg-class (and (not (eq vreg :push)) (hard-regspec-class vreg)))
+             (vreg-mode
+              (if (or (eql vreg-class hard-reg-class-gpr)
+                      (eql vreg-class hard-reg-class-fpr))
+                (get-regspec-mode vreg)
+                hard-reg-class-gpr-mode-invalid)))
+        (cond
+          (is-node
+           (if (eq vreg :push)
+             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+               (! push-misc-ref-c-node  src index-known-fixnum)
+               (! push-misc-ref-node src unscaled-idx))
+             (ensuring-node-target (target vreg)
+               (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+                 (! misc-ref-c-node target src index-known-fixnum)
+                 (if unscaled-idx
+                   (! misc-ref-node target src unscaled-idx)
+                   (with-node-target (src) unscaled-idx
+                     (x862-absolute-natural seg unscaled-idx  nil (ash index-known-fixnum *x862-target-fixnum-shift*))
+                     (! misc-ref-node target src unscaled-idx)))))))
+          (is-32-bit
+           (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-32-bit-constant-index arch)))
+             (cond ((eq type-keyword :single-float-vector)
+                    (with-fp-target () (fp-val :single-float)
+                      (if (and (eql vreg-class hard-reg-class-fpr)
+                               (eql vreg-mode hard-reg-class-fpr-mode-single))
+                        (setq fp-val vreg))
+                      (! misc-ref-c-single-float fp-val src index-known-fixnum)
+                      (if (eql vreg-class hard-reg-class-fpr)
+                        (<- fp-val)
+                        (ensuring-node-target (target vreg)
+			  (target-arch-case
+			   (:x8632 (x862-single->heap seg target fp-val))
+			   (:x8664 (! single->node target fp-val)))))))
+                   (t
+		    (with-additional-imm-reg ()
+		      (with-imm-target () temp
+			(if is-signed
+			  (! misc-ref-c-s32 temp src index-known-fixnum)
+			  (! misc-ref-c-u32 temp src index-known-fixnum))
+			(ensuring-node-target (target vreg)
+			  (if (eq type-keyword :simple-string)
+			    (! u32->char target temp)
+			    (target-arch-case
+			     (:x8632
+			      (if is-signed
+				(x862-box-s32 seg target temp)
+				(x862-box-u32 seg target temp)))
+			     (:x8664
+			      (! box-fixnum target temp)))))))))
+             (with-imm-target () idx-reg
+               (if index-known-fixnum
+		 (x862-absolute-natural seg idx-reg nil (ash index-known-fixnum 2))
+		 (! scale-32bit-misc-index idx-reg unscaled-idx))
+	       (cond ((eq type-keyword :single-float-vector)
+		      (with-fp-target () (fp-val :single-float)
+			(if (and (eql vreg-class hard-reg-class-fpr)
+				 (eql vreg-mode hard-reg-class-fpr-mode-single))
+			  (setq fp-val vreg))
+			(! misc-ref-single-float fp-val src idx-reg)
+			(if (eq vreg-class hard-reg-class-fpr)
+			  (<- fp-val)
+			  (ensuring-node-target (target vreg)
+			    (target-arch-case
+			     (:x8632 (x862-single->heap seg target fp-val))
+			     (:x8664 (! single->node target fp-val)))))))
+		     (t
+		      (with-imm-target () temp
+			(if is-signed
+			  (! misc-ref-s32 temp src idx-reg)
+			  (! misc-ref-u32 temp src idx-reg))
+			(ensuring-node-target (target vreg)
+			  (if (eq type-keyword :simple-string)
+			    (! u32->char target temp)
+			    (target-arch-case
+			     (:x8632 (if is-signed
+				       (x862-box-s32 seg target temp)
+				       (x862-box-u32 seg target temp)))
+			     (:x8664 (! box-fixnum target temp)))))))))))
+          (is-8-bit
+           (with-imm-target () temp
+             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-8-bit-constant-index arch)))
+               (if is-signed
+                 (! misc-ref-c-s8 temp src index-known-fixnum)
+                 (! misc-ref-c-u8 temp src index-known-fixnum))
+	       (with-additional-imm-reg ()
+		 (with-imm-target () idx-reg
+		   (if index-known-fixnum
+		     (x862-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) index-known-fixnum))
+		     (! scale-8bit-misc-index idx-reg unscaled-idx))
+		   (if is-signed
+		     (! misc-ref-s8 temp src idx-reg)
+		     (! misc-ref-u8 temp src idx-reg)))))
+             (if (eq type-keyword :simple-string)
+               (ensuring-node-target (target vreg)
+                 (! u32->char target temp))
+               (if (and (= vreg-mode hard-reg-class-gpr-mode-u8)
+                        (eq type-keyword :unsigned-8-bit-vector))
+                 (x862-copy-register seg vreg temp)
+                 (ensuring-node-target (target vreg)
+                   (! box-fixnum target temp))))))
+          (is-16-bit
+           (with-imm-target () temp
+             (ensuring-node-target (target vreg)
+               (if (and index-known-fixnum
+                        (<= index-known-fixnum (arch::target-max-16-bit-constant-index arch)))
+                 (if is-signed
+                   (! misc-ref-c-s16 temp src index-known-fixnum)
+                   (! misc-ref-c-u16 temp src index-known-fixnum))
+		 (with-imm-target () idx-reg
+		   (if index-known-fixnum
+		     (x862-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 1)))
+		     (! scale-16bit-misc-index idx-reg unscaled-idx))
+		   (if is-signed
+		     (! misc-ref-s16 temp src idx-reg)
+		     (! misc-ref-u16 temp src idx-reg))))
+               (! box-fixnum target temp))))
+          ;; Down to the dregs.
+          (is-64-bit
+           (with-node-target (src) extra
+             (unless unscaled-idx (setq unscaled-idx extra)))
+           (case type-keyword
+             (:double-float-vector
+              (with-fp-target () (fp-val :double-float)
+                (if (and (eql vreg-class hard-reg-class-fpr)
+                         (eql vreg-mode hard-reg-class-fpr-mode-double))
+                  (setq fp-val vreg))
+                (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+                  (! misc-ref-c-double-float fp-val src index-known-fixnum)
+                  (progn
+                    (if index-known-fixnum
+                      (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
+                    (! misc-ref-double-float fp-val src unscaled-idx)))
+                (if (eq vreg-class hard-reg-class-fpr)
+                  (<- fp-val)
+                  (ensuring-node-target (target vreg)
+                    (x862-double->heap seg target fp-val)))))
+             ((:signed-64-bit-vector :fixnum-vector)
+              (ensuring-node-target (target vreg)
+
+                (with-imm-target () (s64-reg :s64)
+                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+                    (! misc-ref-c-s64 s64-reg src index-known-fixnum)
+                    (progn
+                      (if index-known-fixnum
+                        (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
+                      (! misc-ref-s64 s64-reg src unscaled-idx)))
+                  (if (eq type-keyword :fixnum-vector)
+                    (! box-fixnum target s64-reg)
+                    (x862-box-s64 seg target s64-reg)))))
+             (t
+                (with-imm-target () (u64-reg :u64)
+                  (if (eql vreg-mode hard-reg-class-gpr-mode-u64)
+                    (setq u64-reg vreg))
+                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+                    (! misc-ref-c-u64 u64-reg src index-known-fixnum)
+                    (progn
+                      (if index-known-fixnum
+                        (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
+                      (! misc-ref-u64 u64-reg src unscaled-idx)))
+                  (unless (eq u64-reg vreg)
+                    (ensuring-node-target (target vreg)
+                      (x862-box-u64 seg target u64-reg)))))))
+          (t
+           (unless is-1-bit
+             (nx-error "~& unsupported vector type: ~s"
+                       type-keyword))
+           (ensuring-node-target (target vreg)
+             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-1-bit-constant-index arch)))
+               (! misc-ref-c-bit-fixnum target src index-known-fixnum)
+	       (with-imm-target () bitnum
+		 (if index-known-fixnum
+		   (x862-lri seg bitnum index-known-fixnum)
+		   (! scale-1bit-misc-index bitnum unscaled-idx))
+                 (! nref-bit-vector-fixnum target bitnum src))))))))
+    (^)))
+
+
+
+;;; safe = T means assume "vector" is miscobj, do bounds check.
+;;; safe = fixnum means check that subtag of vector = "safe" and do
+;;;        bounds check.
+;;; safe = nil means crash&burn.
+;;; This mostly knows how to reference the elements of an immediate miscobj.
+(defun x862-vref (seg vreg xfer type-keyword vector index safe)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (when *x862-full-safety*
+      (unless vreg (setq vreg *x862-arg-z*)))
+    (if (null vreg)
+      (progn
+        (x862-form seg nil nil vector)
+        (x862-form seg nil xfer index))
+      (let* ((index-known-fixnum (acode-fixnum-form-p index))
+             (unscaled-idx nil)
+             (src nil))
+        (if (or safe (not index-known-fixnum))
+          (multiple-value-setq (src unscaled-idx)
+            (x862-two-untargeted-reg-forms seg vector *x862-arg-y* index *x862-arg-z*))
+          (setq src (x862-one-untargeted-reg-form seg vector *x862-arg-z*)))
+        (when safe
+          (if (typep safe 'fixnum)
+            (! trap-unless-typecode= src safe))
+          (unless index-known-fixnum
+            (! trap-unless-fixnum unscaled-idx))
+          (! check-misc-bound unscaled-idx src))
+        (x862-vref1 seg vreg xfer type-keyword src unscaled-idx index-known-fixnum)))))
+
+
+
+(defun x862-aset2 (seg vreg xfer  array i j new safe type-keyword  dim0 dim1)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (with-x86-local-vinsn-macros (seg target)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (constval (x862-constant-value-ok-for-type-keyword type-keyword new))
+           (needs-memoization (and is-node (x862-acode-needs-memoization new)))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (val-reg (x862-target-reg-for-aset vreg type-keyword))
+           (constidx
+            (and dim0 dim1 i-known-fixnum j-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (+ (* i-known-fixnum dim1) j-known-fixnum))))
+      (progn
+        (if constidx
+          (multiple-value-setq (src val-reg)
+            (x862-two-targeted-reg-forms seg array ($ *x862-temp0*) new val-reg))
+          (multiple-value-setq (src unscaled-i unscaled-j val-reg)
+            (if needs-memoization
+              (progn
+                (x862-four-targeted-reg-forms seg
+                                              array ($ *x862-temp0*)
+                                              i ($ x8664::arg_x)
+                                              j ($ *x862-arg-y*)
+                                              new val-reg)
+                (values ($ *x862-temp0*) ($ x8664::arg_x) ($ *x862-arg-y*) ($ *x862-arg-z*)))
+              (x862-four-untargeted-reg-forms seg
+                                              array ($ *x862-temp0*)
+                                              i ($ x8664::arg_x)
+                                              j ($ *x862-arg-y*)
+                                              new val-reg))))
+        (let* ((*available-backend-imm-temps* *available-backend-imm-temps*))
+          (when (and (= (hard-regspec-class val-reg) hard-reg-class-gpr)
+                     (logbitp (hard-regspec-value val-reg)
+                              *backend-imm-temps*))
+            (use-imm-temp (hard-regspec-value val-reg)))
+          (when safe      
+            (when (typep safe 'fixnum)
+              (! trap-unless-simple-array-2
+                 src
+                 (dpb safe target::arrayH.flags-cell-subtag-byte
+                      (ash 1 $arh_simple_bit))
+                 (nx-error-for-simple-2d-array-type type-keyword)))
+            (unless i-known-fixnum
+              (! trap-unless-fixnum unscaled-i))
+            (unless j-known-fixnum
+              (! trap-unless-fixnum unscaled-j)))
+          (with-imm-target () dim1
+            (let* ((idx-reg ($ *x862-arg-y*)))
+              (if constidx
+                (if needs-memoization
+                  (x862-lri seg *x862-arg-y* (ash constidx *x862-target-fixnum-shift*)))
+                (progn
+                  (if safe                  
+                    (! check-2d-bound dim1 unscaled-i unscaled-j src)
+                    (! 2d-dim1 dim1 src))
+                  (! 2d-unscaled-index idx-reg dim1 unscaled-i unscaled-j)))
+              (let* ((v ($ x8664::arg_x)))
+                (! array-data-vector-ref v src)
+                (x862-vset1 seg vreg xfer type-keyword v idx-reg constidx val-reg (x862-unboxed-reg-for-aset seg type-keyword val-reg safe constval) constval needs-memoization)))))))))
+
+
+(defun x862-aset3 (seg vreg xfer  array i j k new safe type-keyword  dim0 dim1 dim2)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (with-x86-local-vinsn-macros (seg target)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (k-known-fixnum (acode-fixnum-form-p k))
+           (arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (constval (x862-constant-value-ok-for-type-keyword type-keyword new))
+           (needs-memoization (and is-node (x862-acode-needs-memoization new)))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (unscaled-k)
+           (val-reg (x862-target-reg-for-aset vreg type-keyword))
+           (constidx
+            (and dim0 dim1 dim2 i-known-fixnum j-known-fixnum k-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (>= k-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (< k-known-fixnum dim2)
+                 (+ (* i-known-fixnum dim1 dim2)
+                    (* j-known-fixnum dim2)
+                    k-known-fixnum))))
+      (progn
+        (if constidx
+          (multiple-value-setq (src val-reg)
+            (x862-two-targeted-reg-forms seg array ($ *x862-temp0*) new val-reg))
+          (progn
+            (setq src ($ x8664::temp1)
+                  unscaled-i ($ *x862-temp0*)
+                  unscaled-j ($ x8664::arg_x)
+                  unscaled-k ($ *x862-arg-y*))
+            (x862-push-register
+             seg
+             (x862-one-untargeted-reg-form seg array ($ *x862-arg-z*)))
+            (x862-four-targeted-reg-forms seg
+                                          i ($ *x862-temp0*)
+                                          j ($ x8664::arg_x)
+                                          k ($ *x862-arg-y*)
+                                          new val-reg)
+            (x862-pop-register seg src)))
+        (let* ((*available-backend-imm-temps* *available-backend-imm-temps*))
+          (when (and (= (hard-regspec-class val-reg) hard-reg-class-gpr)
+                     (logbitp (hard-regspec-value val-reg)
+                              *backend-imm-temps*))
+            (use-imm-temp (hard-regspec-value val-reg)))
+        
+          (when safe      
+            (when (typep safe 'fixnum)
+              (! trap-unless-simple-array-3
+                 src
+                 (dpb safe target::arrayH.flags-cell-subtag-byte
+                      (ash 1 $arh_simple_bit))
+                 (nx-error-for-simple-3d-array-type type-keyword)))
+            (unless i-known-fixnum
+              (! trap-unless-fixnum unscaled-i))
+            (unless j-known-fixnum
+              (! trap-unless-fixnum unscaled-j))
+            (unless k-known-fixnum
+              (! trap-unless-fixnum unscaled-k)))
+          (with-imm-target () dim1
+            (with-imm-target (dim1) dim2
+              (let* ((idx-reg ($ *x862-arg-y*)))
+                (if constidx
+                  (when needs-memoization
+                    (x862-lri seg idx-reg (ash constidx *x862-target-fixnum-shift*)))
+                  (progn
+                    (if safe                  
+                      (! check-3d-bound dim1 dim2 unscaled-i unscaled-j unscaled-k src)
+                      (! 3d-dims dim1 dim2 src))
+                    (! 3d-unscaled-index idx-reg dim1 dim2 unscaled-i unscaled-j unscaled-k)))
+                (let* ((v ($ x8664::arg_x)))
+                  (! array-data-vector-ref v src)
+                  (x862-vset1 seg vreg xfer type-keyword v idx-reg constidx val-reg (x862-unboxed-reg-for-aset seg type-keyword val-reg safe constval) constval needs-memoization))))))))))
+
+
+(defun x862-aref2 (seg vreg xfer array i j safe typekeyword &optional dim0 dim1)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (constidx
+            (and dim0 dim1 i-known-fixnum j-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (+ (* i-known-fixnum dim1) j-known-fixnum))))
+      (if constidx
+        (setq src (x862-one-targeted-reg-form seg array ($ *x862-arg-z*)))
+        (multiple-value-setq (src unscaled-i unscaled-j)
+          (x862-three-untargeted-reg-forms seg
+                                           array x8664::arg_x
+                                           i *x862-arg-y*
+                                           j *x862-arg-z*)))
+      (when safe        
+        (when (typep safe 'fixnum)
+          (! trap-unless-simple-array-2
+             src
+             (dpb safe target::arrayH.flags-cell-subtag-byte
+                  (ash 1 $arh_simple_bit))
+             (nx-error-for-simple-2d-array-type typekeyword)))
+        (unless i-known-fixnum
+          (! trap-unless-fixnum unscaled-i))
+        (unless j-known-fixnum
+          (! trap-unless-fixnum unscaled-j)))
+      (with-node-target (src) idx-reg
+        (with-imm-target () dim1
+          (unless constidx
+            (if safe                    
+              (! check-2d-bound dim1 unscaled-i unscaled-j src)
+              (! 2d-dim1 dim1 src))
+            (! 2d-unscaled-index idx-reg dim1 unscaled-i unscaled-j))
+          (with-node-target (idx-reg) v
+            (! array-data-vector-ref v src)
+            (x862-vref1 seg vreg xfer typekeyword v idx-reg constidx)))))))
+
+(defun x862-aref3 (seg vreg xfer array i j k safe typekeyword &optional dim0 dim1 dim2)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((i-known-fixnum (acode-fixnum-form-p i))
+           (j-known-fixnum (acode-fixnum-form-p j))
+           (k-known-fixnum (acode-fixnum-form-p k))
+           (src)
+           (unscaled-i)
+           (unscaled-j)
+           (unscaled-k)
+           (constidx
+            (and dim0 dim1 i-known-fixnum j-known-fixnum k-known-fixnum
+                 (>= i-known-fixnum 0)
+                 (>= j-known-fixnum 0)
+                 (>= k-known-fixnum 0)
+                 (< i-known-fixnum dim0)
+                 (< j-known-fixnum dim1)
+                 (< k-known-fixnum dim2)
+                 (+ (* i-known-fixnum dim1 dim2)
+                    (* j-known-fixnum dim2)
+                    k-known-fixnum))))
+      (if constidx
+        (setq src (x862-one-targeted-reg-form seg array ($ *x862-arg-z*)))
+        (multiple-value-setq (src unscaled-i unscaled-j unscaled-k)
+          (x862-four-untargeted-reg-forms seg
+                                           array *x862-temp0*
+                                           i x8664::arg_x
+                                           j *x862-arg-y*
+                                           k *x862-arg-z*)))
+      (when safe        
+        (when (typep safe 'fixnum)
+          (! trap-unless-simple-array-3
+             src
+             (dpb safe target::arrayH.flags-cell-subtag-byte
+                  (ash 1 $arh_simple_bit))
+             (nx-error-for-simple-3d-array-type typekeyword)))
+        (unless i-known-fixnum
+          (! trap-unless-fixnum unscaled-i))
+        (unless j-known-fixnum
+          (! trap-unless-fixnum unscaled-j))
+        (unless k-known-fixnum
+          (! trap-unless-fixnum unscaled-k)))
+      (with-node-target (src) idx-reg
+        (with-imm-target () dim1
+          (with-imm-target (dim1) dim2
+            (unless constidx
+              (if safe                    
+                (! check-3d-bound dim1 dim2 unscaled-i unscaled-j unscaled-k src)
+                (! 3d-dims dim1 dim2 src))
+              (! 3d-unscaled-index idx-reg dim1 dim2 unscaled-i unscaled-j unscaled-k))))
+        (with-node-target (idx-reg) v
+          (! array-data-vector-ref v src)
+          (x862-vref1 seg vreg xfer typekeyword v idx-reg constidx))))))
+
+
+
+(defun x862-natural-vset (seg vreg xfer vector index value safe)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((index-known-fixnum (acode-fixnum-form-p index))
+           (arch (backend-target-arch *target-backend*))
+           (src nil)
+           (unscaled-idx nil))
+      (with-imm-target () (target :natural)
+        (if (or safe (not index-known-fixnum))
+          (multiple-value-setq (src unscaled-idx target)
+            (x862-three-untargeted-reg-forms seg vector *x862-arg-y* index *x862-arg-z* value (or vreg target)))
+          (multiple-value-setq (src target)
+            (x862-two-untargeted-reg-forms seg vector *x862-arg-y* value (or vreg target))))
+        (when safe
+          (with-imm-temps (target) ()   ; Don't use target in type/bounds check
+            (if (typep safe 'fixnum)
+              (! trap-unless-typecode= src safe))
+            (unless index-known-fixnum
+              (! trap-unless-fixnum unscaled-idx))
+            (! check-misc-bound unscaled-idx src)))
+        (target-arch-case
+         
+         (:x8664
+          (if (and index-known-fixnum
+                   (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
+            (! misc-set-c-u64 target src index-known-fixnum)
+            (progn
+              (if index-known-fixnum
+                (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
+              (! misc-set-u64 target src unscaled-idx)))))
+        (<- target)                     ; should be a no-op in this case
+        (^)))))
+
+
+(defun x862-constant-value-ok-for-type-keyword (type-keyword form)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (is-node  (member type-keyword (arch::target-gvector-types arch))))
+    (if is-node
+      (cond ((nx-null form)
+             (target-nil-value))
+            ((nx-t form)
+             (+ (target-nil-value) (arch::target-t-offset arch)))
+            (t
+             (let* ((fixval (acode-fixnum-form-p form)))
+               (if fixval
+                 (ash fixval (arch::target-fixnum-shift arch))))))
+      (if (and (acode-p form)
+               (or (eq (acode-operator form) (%nx1-operator immediate))
+                   (eq (acode-operator form) (%nx1-operator fixnum))))
+        (let* ((val (%cadr form))
+
+               (typep (cond ((eq type-keyword :signed-32-bit-vector)
+                             (typep val '(signed-byte 32)))
+                            ((eq type-keyword :single-float-vector)
+                             (typep val 'short-float))
+                            ((eq type-keyword :double-float-vector)
+                             (typep val 'double-float))
+                            ((eq type-keyword :simple-string)
+                             (typep val 'base-char))
+                            ((eq type-keyword :signed-8-bit-vector)
+                             (typep val '(signed-byte 8)))
+                            ((eq type-keyword :unsigned-8-bit-vector)
+                             (typep val '(unsigned-byte 8)))
+                            ((eq type-keyword :signed-16-bit-vector) 
+                             (typep val '(signed-byte 16)))
+                            ((eq type-keyword :unsigned-16-bit-vector)
+                             (typep val '(unsigned-byte 16)))
+                            ((eq type-keyword :bit-vector)
+                             (typep val 'bit)))))
+          (if typep val))))))
+
+(defun x862-target-reg-for-aset (vreg type-keyword)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (is-node (member type-keyword (arch::target-gvector-types arch)))
+         (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
+         (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+         (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+         (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+         (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+         (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
+         (vreg-class (if (and vreg (not (eq vreg :push))) (hard-regspec-class vreg)))
+         (vreg-mode (if (or (eql vreg-class hard-reg-class-gpr)
+                            (eql vreg-class hard-reg-class-fpr))
+                      (get-regspec-mode vreg)))
+         (next-imm-target (available-imm-temp  *available-backend-imm-temps*))
+         (next-fp-target (available-fp-temp *available-backend-fp-temps*))
+         (acc (make-wired-lreg *x862-arg-z*)))
+    (cond ((or is-node
+               (eq vreg :push)
+               is-1-bit
+               (eq type-keyword :simple-string)
+               (eq type-keyword :fixnum-vector)
+               (and (eql vreg-class hard-reg-class-gpr)
+                    (eql vreg-mode hard-reg-class-gpr-mode-node)))
+           acc)
+          ;; If there's no vreg - if we're setting for effect only, and
+          ;; not for value - we can target an unboxed register directly.
+          ;; Usually.
+          ((null vreg)
+           (cond (is-64-bit
+                  (if (eq type-keyword :double-float-vector)
+                    (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-double)
+                    (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s64 hard-reg-class-gpr-mode-u64))))
+                 (is-32-bit
+                  (if (eq type-keyword :single-float-vector)
+                    (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-single)
+                    (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s32 hard-reg-class-gpr-mode-u32))))
+                 (is-16-bit
+                  (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s16 hard-reg-class-gpr-mode-u16)))
+                 (is-8-bit
+                  (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s8 hard-reg-class-gpr-mode-u8)))
+                 (t "Bug: can't determine operand size for ~s" type-keyword)))
+          ;; Vreg is non-null.  We might be able to use it directly.
+          (t
+           (let* ((lreg (if vreg-mode
+                          (make-unwired-lreg (lreg-value vreg)))))
+             (if 
+               (cond
+                 (is-64-bit
+                  (if (eq type-keyword :double-float-vector)
+                    (and (eql vreg-class hard-reg-class-fpr)
+                         (eql vreg-mode hard-reg-class-fpr-mode-double))
+                      (if is-signed
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (eql vreg-mode hard-reg-class-gpr-mode-s64))
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (eql vreg-mode hard-reg-class-gpr-mode-u64)))))
+                   (is-32-bit
+                    (if (eq type-keyword :single-float-vector)
+                      (and (eql vreg-class hard-reg-class-fpr)
+                               (eql vreg-mode hard-reg-class-fpr-mode-single))
+                      (if is-signed
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (or (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                     (eql vreg-mode hard-reg-class-gpr-mode-s64)))
+                        (and (eql vreg-class hard-reg-class-gpr)
+                                 (or (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                                     (eql vreg-mode hard-reg-class-gpr-mode-u64)
+                                     (eql vreg-mode hard-reg-class-gpr-mode-s64))))))
+                   (is-16-bit
+                    (if is-signed
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-u16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u64)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))))
+                   (t
+                    (if is-signed
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-s8)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))
+                      (and (eql vreg-class hard-reg-class-gpr)
+                               (or (eql vreg-mode hard-reg-class-gpr-mode-u8)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-u64)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s16)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
+                                   (eql vreg-mode hard-reg-class-gpr-mode-s64))))))
+               lreg
+               acc))))))
+
+(defun x862-unboxed-reg-for-aset (seg type-keyword result-reg safe constval)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+           (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+           (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+           (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+           (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
+           (result-is-node-gpr (and (eql (hard-regspec-class result-reg)
+                                         hard-reg-class-gpr)
+                                    (eql (get-regspec-mode result-reg)
+                                         hard-reg-class-gpr-mode-node)))
+           (next-imm-target (available-imm-temp *available-backend-imm-temps*))
+           (next-fp-target (available-fp-temp *available-backend-fp-temps*)))
+      (if (or is-node (not result-is-node-gpr))
+        result-reg
+        (cond (is-64-bit
+               (if (eq type-keyword :double-float-vector)
+                 (let* ((reg (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-double)))
+                   (if safe
+                     (! get-double? reg result-reg)
+                     (! get-double reg result-reg))
+                   reg)
+                 (if is-signed
+                   (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s64)))
+                     (if (eq type-keyword :fixnum-vector)
+                       (progn
+                         (when safe
+                           (! trap-unless-fixnum result-reg))
+                         (! fixnum->signed-natural reg result-reg))
+                       (! unbox-s64 reg result-reg))
+                     reg)
+                   (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u64)))
+                     (! unbox-u64 reg result-reg)
+                     reg))))
+              (is-32-bit
+               ;; Generally better to use a GPR for the :SINGLE-FLOAT-VECTOR
+               ;; case here.
+               (if is-signed             
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s32)))
+                   (if (eq type-keyword :fixnum-vector)
+                     (progn
+                       (when safe
+                         (! trap-unless-fixnum result-reg))
+                       (! fixnum->signed-natural reg result-reg))
+                     (! unbox-s32 reg result-reg))
+                   reg)
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u32)))
+                   (cond ((eq type-keyword :simple-string)
+                          (if (characterp constval)
+                            (x862-lri seg reg (char-code constval))
+                            (! unbox-base-char reg result-reg)))
+                         ((eq type-keyword :single-float-vector)
+                          (if (typep constval 'single-float)
+                            (x862-lri seg reg (single-float-bits constval))
+                            (progn
+                              (when safe
+                                (! trap-unless-single-float result-reg))
+                              (! single-float-bits reg result-reg))))
+                         (t
+                          (if (typep constval '(unsigned-byte 32))
+                            (x862-lri seg reg constval)
+                            (if *x862-reckless*
+			      (target-arch-case
+			       (:x8632 (! unbox-u32 reg result-reg))
+			       (:x8664 (! %unbox-u32 reg result-reg)))
+                              (! unbox-u32 reg result-reg)))))
+                   reg)))
+              (is-16-bit
+               (if is-signed
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s16)))
+                   (if (typep constval '(signed-byte 16))
+                     (x862-lri seg reg constval)
+                     (if *x862-reckless*
+                       (! %unbox-s16 reg result-reg)
+                       (! unbox-s16 reg result-reg)))
+                   reg)
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u16)))
+                   (if (typep constval '(unsigned-byte 16))
+                     (x862-lri seg reg constval)
+                     (if *x862-reckless*
+                       (! %unbox-u16 reg result-reg)
+                       (! unbox-u16 reg result-reg)))
+                   reg)))
+              (is-8-bit
+               (if is-signed
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s8)))
+                   (if (typep constval '(signed-byte 8))
+                     (x862-lri seg reg constval)
+                     (if *x862-reckless*
+                       (! %unbox-s8 reg result-reg)
+                       (! unbox-s8 reg result-reg)))
+                   reg)
+                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u8)))
+                   (if (typep constval '(unsigned-byte 8))
+                     (x862-lri seg reg constval)
+                     (if *x862-reckless*
+                       (! %unbox-u8 reg result-reg)
+                       (! unbox-u8 reg result-reg)))
+                   reg)))
+              (t
+                 (let* ((reg result-reg))
+                   (unless (typep constval 'bit)
+                     (when safe
+                       (! trap-unless-bit reg )))
+                   reg)))))))
+
+
+;;; xxx
+(defun x862-vset1 (seg vreg xfer type-keyword src unscaled-idx index-known-fixnum val-reg unboxed-val-reg constval node-value-needs-memoization)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
+           (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
+           (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
+           (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
+           (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
+           (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector))))
+      (cond ((and is-node node-value-needs-memoization)
+             (unless (and (eql (hard-regspec-value src) (target-arch-case
+							 (:x8632 x8632::temp0)
+							 (:x8664 x8664::arg_x)))
+                          (eql (hard-regspec-value unscaled-idx) *x862-arg-y*)
+                          (eql (hard-regspec-value val-reg) *x862-arg-z*))
+               (compiler-bug "Bug: invalid register targeting for gvset: ~s" (list src unscaled-idx val-reg)))
+             (! call-subprim-3 val-reg (subprim-name->offset '.SPgvset) src unscaled-idx val-reg))
+            (is-node
+             (if (and index-known-fixnum (<= index-known-fixnum
+                                             (target-word-size-case
+                                              (32 (arch::target-max-32-bit-constant-index arch))
+                                              (64 (arch::target-max-64-bit-constant-index arch)))))
+               (if (typep constval '(signed-byte 32))
+                 (! misc-set-immediate-c-node constval src index-known-fixnum)
+                 (! misc-set-c-node val-reg src index-known-fixnum))
+               (progn
+                 (if index-known-fixnum
+                   (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum *x862-target-node-shift*))))
+                 (if (typep constval '(signed-byte 32))
+                   (! misc-set-immediate-node constval src unscaled-idx)
+                   (! misc-set-node val-reg src unscaled-idx)))))
+            (t
+	     (with-additional-imm-reg (src unscaled-idx val-reg)
+	       (with-imm-target (unboxed-val-reg) scaled-idx
+		 (cond
+		   (is-64-bit
+		    (if (and index-known-fixnum
+			     (<= index-known-fixnum
+				 (arch::target-max-64-bit-constant-index arch)))
+		      (if (eq type-keyword :double-float-vector)
+			(! misc-set-c-double-float unboxed-val-reg src index-known-fixnum)
+			(if is-signed
+			  (! misc-set-c-s64 unboxed-val-reg src index-known-fixnum)
+			  (! misc-set-c-u64 unboxed-val-reg src index-known-fixnum)))
+		      (progn
+			(if index-known-fixnum
+			  (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-dfloat-offset arch) (ash index-known-fixnum 3))))
+			(if (eq type-keyword :double-float-vector)
+			  (! misc-set-double-float unboxed-val-reg src unscaled-idx)
+			  (if is-signed
+			    (! misc-set-s64 unboxed-val-reg src unscaled-idx)
+			    (! misc-set-u64 unboxed-val-reg src unscaled-idx))))))
+		   (is-32-bit
+		    (if (and index-known-fixnum
+			     (<= index-known-fixnum
+				 (arch::target-max-32-bit-constant-index arch)))
+		      (if (eq type-keyword :single-float-vector)
+			(if (eq (hard-regspec-class unboxed-val-reg)
+				hard-reg-class-fpr)
+			  (! misc-set-c-single-float unboxed-val-reg src index-known-fixnum)
+			  (! misc-set-c-u32 unboxed-val-reg src index-known-fixnum))
+			(if is-signed
+			  (! misc-set-c-s32 unboxed-val-reg src index-known-fixnum)
+			  (! misc-set-c-u32 unboxed-val-reg src index-known-fixnum)))
+		      (progn
+			(if index-known-fixnum
+			  (x862-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 2)))
+			  (! scale-32bit-misc-index scaled-idx unscaled-idx))
+			(if (and (eq type-keyword :single-float-vector)
+				 (eql (hard-regspec-class unboxed-val-reg)
+				      hard-reg-class-fpr))
+			  (! misc-set-single-float unboxed-val-reg src scaled-idx)
+			  (if is-signed
+			    (! misc-set-s32 unboxed-val-reg src scaled-idx)
+			    (! misc-set-u32 unboxed-val-reg src scaled-idx))))))
+		   (is-16-bit
+		    (if (and index-known-fixnum
+			     (<= index-known-fixnum
+				 (arch::target-max-16-bit-constant-index arch)))
+		      (if is-signed
+			(! misc-set-c-s16 unboxed-val-reg src index-known-fixnum)
+			(! misc-set-c-u16 unboxed-val-reg src index-known-fixnum))
+		      (progn
+			(if index-known-fixnum
+			  (x862-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 1)))
+			  (! scale-16bit-misc-index scaled-idx unscaled-idx))
+			(if is-signed
+			  (! misc-set-s16 unboxed-val-reg src scaled-idx)
+			  (! misc-set-u16 unboxed-val-reg src scaled-idx)))))
+		   (is-8-bit
+		    (if (and index-known-fixnum
+			     (<= index-known-fixnum
+				 (arch::target-max-8-bit-constant-index arch)))
+		      (if is-signed
+			(! misc-set-c-s8 unboxed-val-reg src index-known-fixnum)
+			(! misc-set-c-u8  unboxed-val-reg src index-known-fixnum))
+		      (progn
+			(if index-known-fixnum
+			  (x862-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) index-known-fixnum))
+			  (! scale-8bit-misc-index scaled-idx unscaled-idx))
+			(if is-signed
+			  (! misc-set-s8 unboxed-val-reg src scaled-idx)
+			  (! misc-set-u8 unboxed-val-reg src scaled-idx)))))
+		   (is-1-bit
+		    (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-1-bit-constant-index arch)))
+		      (if constval
+			(if (zerop constval)
+			  (! set-constant-bit-to-zero src index-known-fixnum)
+			  (! set-constant-bit-to-one src index-known-fixnum))
+			(progn
+			  (! set-constant-bit-to-variable-value src index-known-fixnum val-reg)))
+		      (progn
+			(if index-known-fixnum
+			  (x862-lri seg scaled-idx index-known-fixnum)
+			  (! scale-1bit-misc-index scaled-idx unscaled-idx))
+			(if constval
+			  (if (zerop constval)
+			    (! nset-variable-bit-to-zero src scaled-idx)
+			    (! nset-variable-bit-to-one src scaled-idx))
+			  (progn
+			    (! nset-variable-bit-to-variable-value src scaled-idx val-reg)))))))))))
+      (when (and vreg val-reg) (<- val-reg))
+      (^))))
+
+
+(defun x862-code-coverage-entry (seg note)
+ (let* ((afunc *x862-cur-afunc*))
+   (setf (afunc-bits afunc) (%ilogior (afunc-bits afunc) (ash 1 $fbitccoverage)))
+   (with-x86-local-vinsn-macros (seg)
+     (let* ((ccreg ($ x8664::arg_x)))
+       (! vpush-register ccreg)
+       (! ref-constant ccreg (x86-immediate-label note))
+       (! misc-set-immediate-c-node 0 ccreg 1)
+       (! vpop-register ccreg)))))
+
+(defun x862-vset (seg vreg xfer type-keyword vector index value safe)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((arch (backend-target-arch *target-backend*))
+           (is-node (member type-keyword (arch::target-gvector-types arch)))
+           (constval (x862-constant-value-ok-for-type-keyword type-keyword value))
+           (needs-memoization (and is-node (x862-acode-needs-memoization value)))
+           (index-known-fixnum (acode-fixnum-form-p index)))
+      (let* ((src (target-arch-case
+		   (:x8632 ($ x8632::temp0))
+		   (:x8664 ($ x8664::arg_x))))
+             (unscaled-idx ($ *x862-arg-y*))
+             (result-reg ($ *x862-arg-z*)))
+        (cond (needs-memoization
+               (x862-three-targeted-reg-forms seg
+                                              vector src
+                                              index unscaled-idx
+                                              value result-reg))
+              (t
+               (setq result-reg (x862-target-reg-for-aset vreg type-keyword))
+	       (target-arch-case
+		(:x8632
+		 (with-node-temps (src) ()
+		   (x862-three-targeted-reg-forms seg
+						  vector src
+						  index unscaled-idx
+						  value result-reg)))
+		(:x8664
+                 (if (and index-known-fixnum
+                          (not safe)
+                          (nx2-constant-index-ok-for-type-keyword index-known-fixnum type-keyword))
+                   (multiple-value-setq (src result-reg unscaled-idx)
+                     (x862-two-untargeted-reg-forms seg
+                                                  vector src
+                                                  value result-reg))
+                   (multiple-value-setq (src unscaled-idx result-reg)
+                     (x862-three-untargeted-reg-forms seg
+                                                      vector src
+                                                      index unscaled-idx
+                                                      value result-reg)))))))
+        (when safe
+	  (let* ((*available-backend-imm-temps* *available-backend-imm-temps*)
+		 (value (if (eql (hard-regspec-class result-reg)
+				 hard-reg-class-gpr)
+			  (hard-regspec-value result-reg)))
+		 (result-is-imm nil))
+	    (when (and value (logbitp value *available-backend-imm-temps*))
+	      (setq *available-backend-imm-temps* (bitclr value *available-backend-imm-temps*))
+	      (setq result-is-imm t))
+	    (if (typep safe 'fixnum)
+	      (if result-is-imm
+		(with-additional-imm-reg (src safe)
+		  (! trap-unless-typecode= src safe))
+		(! trap-unless-typecode= src safe)))
+	    (unless index-known-fixnum
+	      (! trap-unless-fixnum unscaled-idx))
+	    (if result-is-imm
+	      (with-additional-imm-reg (unscaled-idx src)
+		(! check-misc-bound unscaled-idx src))
+	      (! check-misc-bound unscaled-idx src))))
+        (x862-vset1 seg vreg xfer type-keyword src unscaled-idx index-known-fixnum result-reg (x862-unboxed-reg-for-aset seg type-keyword result-reg safe constval) constval needs-memoization)))))
+
+
+
+(defun x862-tail-call-alias (immref sym &optional arglist)
+  (let ((alias (cdr (assq sym *x862-tail-call-aliases*))))
+    (if (and alias (or (null arglist) (eq (+ (length (car arglist)) (length (cadr arglist))) (cdr alias))))
+      (make-acode (%nx1-operator immediate) (car alias))
+      immref)))
+
+;;; If BODY is essentially an APPLY involving an &rest arg, try to avoid
+;;; consing it.
+(defun x862-eliminate-&rest (body rest key-p auxen rest-values)
+  (when (and rest (not key-p) (not (cadr auxen)) rest-values)
+    (when (eq (logand (the fixnum (nx-var-bits rest))
+                      (logior $vsetqmask (ash -1 $vbitspecial)
+                              (ash 1 $vbitclosed) (ash 1 $vbitsetq) (ash 1 $vbitcloseddownward)))
+              0)               ; Nothing but simple references
+      (do* ()
+           ((not (acode-p body)))
+        (let* ((op (acode-operator body)))
+          (if (or (eq op (%nx1-operator lexical-function-call))
+                  (eq op (%nx1-operator call)))
+            (destructuring-bind (fn-form (stack-args reg-args) &optional spread-p) (%cdr body)
+               (unless (and (eq spread-p t)
+                           (eq (nx2-lexical-reference-p (%car reg-args)) rest))
+                (return nil))
+              (flet ((independent-of-all-values (form)        
+                       (setq form (acode-unwrapped-form-value form))
+                       (or (x86-constant-form-p form)
+                           (let* ((lexref (nx2-lexical-reference-p form)))
+                             (and lexref 
+                                  (neq lexref rest)
+                                  (dolist (val rest-values t)
+                                    (unless (nx2-var-not-set-by-form-p lexref val)
+                                      (return))))))))
+                (unless (or (eq op (%nx1-operator lexical-function-call))
+                            (independent-of-all-values fn-form))
+                  (return nil))
+                (if (dolist (s stack-args t)
+                          (unless (independent-of-all-values s)
+                            (return nil)))
+                  (let* ((arglist (append stack-args rest-values)))
+                    (return
+                     (make-acode op 
+                                 fn-form 
+                                 (if (<= (length arglist) *x862-target-num-arg-regs*)
+                                   (list nil (reverse arglist))
+                                   (list (butlast arglist *x862-target-num-arg-regs*)
+                                         (reverse (last arglist *x862-target-num-arg-regs*))))
+                                 nil)))
+                  (return nil))))
+            (if (eq op (%nx1-operator local-block))
+              (setq body (%cadr body))
+              (if (and (eq op (%nx1-operator if))
+                       (eq (nx2-lexical-reference-p (%cadr body)) rest))
+                (setq body (%caddr body))
+                (return nil)))))))))
+
+(defun x862-call-fn (seg vreg xfer fn arglist spread-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (when spread-p
+      (destructuring-bind (stack-args reg-args) arglist
+        (when (and (null (cdr reg-args))
+                   (nx-null (acode-unwrapped-form-value (car reg-args))))
+          (setq spread-p nil)
+          (let* ((nargs (length stack-args)))
+            (declare (fixnum nargs))
+            (if (<= nargs *x862-target-num-arg-regs*)
+              (setq arglist (list nil (reverse stack-args)))
+              (setq arglist (list (butlast stack-args *x862-target-num-arg-regs*) (reverse (last stack-args *x862-target-num-arg-regs*)))))))))
+    (let* ((lexref (nx2-lexical-reference-p fn))
+           (simple-case (or (fixnump fn)
+                            (typep fn 'lreg)
+                            (x862-immediate-function-p fn)
+                            (and 
+                             lexref
+                             (not spread-p)
+                             (flet ((all-simple (args)
+                                      (dolist (arg args t)
+                                        (when (and arg (not (nx2-var-not-set-by-form-p lexref arg)))
+                                          (return)))))
+                               (and (all-simple (car arglist))
+                                    (all-simple (cadr arglist))
+                                    (setq fn (var-ea lexref)))))))
+           (cstack *x862-cstack*)
+           (top *x862-top-vstack-lcell*)
+           (vstack *x862-vstack*))
+      (setq xfer (or xfer 0))
+      (when (and (eq xfer $backend-return)
+                 (eq 0 *x862-undo-count*)
+                 (acode-p fn)
+                 (eq (acode-operator fn) (%nx1-operator immediate))
+                 (symbolp (cadr fn)))
+        (setq fn (x862-tail-call-alias fn (%cadr fn) arglist)))
+      
+      (if (and (eq xfer $backend-return) (not (x862-tailcallok xfer)))
+        (progn
+          (x862-call-fn seg vreg $backend-mvpass fn arglist spread-p)
+          (x862-set-vstack (%i+ (if simple-case 0 *x862-target-node-size*) vstack))
+          (setq  *x862-cstack* cstack)
+          (let ((*x862-returning-values* t)) (x862-do-return seg)))
+        (let* ((mv-p (x862-mv-p xfer))
+               (mv-return-label (if (and mv-p
+                                         (not (x862-tailcallok xfer)))
+                                  (backend-get-next-label))))
+          (unless simple-case
+            (x862-vpush-register seg (x862-one-untargeted-reg-form seg fn *x862-arg-z*))
+            (setq fn (x862-vloc-ea vstack)))
+          (x862-invoke-fn seg fn (x862-arglist seg arglist mv-return-label) spread-p xfer mv-return-label)
+          (if (and (logbitp $backend-mvpass-bit xfer)
+                   (not simple-case))
+            (progn
+              (! save-values)
+              (! vstack-discard 1)
+              (x862-set-nargs seg 0)
+              (! recover-values))
+            (unless (or mv-p simple-case)
+              (! vstack-discard 1)))
+          (x862-set-vstack vstack)
+          (setq *x862-top-vstack-lcell* top)
+          (setq *x862-cstack* cstack)
+          (when (or (logbitp $backend-mvpass-bit xfer) (not mv-p))
+            (<- *x862-arg-z*)
+            (x862-branch seg (logand (lognot $backend-mvpass-mask) xfer)))))
+      nil)))
+
+(defun x862-restore-full-lisp-context (seg)
+  (with-x86-local-vinsn-macros (seg)
+    (! restore-full-lisp-context)))
+
+(defun x862-emit-aligned-label (seg labelnum)
+  (with-x86-local-vinsn-macros (seg)
+    (! emit-aligned-label (aref *backend-labels* labelnum))
+    (@ labelnum)
+    (target-arch-case
+     (:x8632
+      (! recover-fn))
+     (:x8664
+      (! recover-fn-from-rip)))))
+
+  
+(defun x862-call-symbol (seg jump-p)
+  (with-x86-local-vinsn-macros (seg)
+    (if jump-p
+      (! jump-known-symbol)
+      (! call-known-symbol *x862-arg-z*))))
+
+;;; Nargs = nil -> multiple-value case.
+(defun x862-invoke-fn (seg fn nargs spread-p xfer &optional mvpass-label)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((f-op (acode-unwrapped-form-value fn))
+           (immp (and (consp f-op)
+                      (eq (%car f-op) (%nx1-operator immediate))))
+           (symp (and immp (symbolp (%cadr f-op))))
+           (label-p (and (fixnump fn) 
+                         (locally (declare (fixnum fn))
+                           (and (= fn -2) (- fn)))))
+           (tail-p (eq xfer $backend-return))
+           (func (if (consp f-op) (%cadr f-op)))
+           (a-reg nil)
+           (lfunp (and (acode-p f-op) 
+                       (eq (acode-operator f-op) (%nx1-operator simple-function))))
+           (expression-p (or (typep fn 'lreg) (and (fixnump fn) (not label-p))))
+           (callable (or symp lfunp label-p))
+           (destreg (if symp ($ *x862-fname*) (unless label-p ($ *x862-temp0*))))
+           (alternate-tail-call
+            (and tail-p label-p *x862-tail-label* (eql nargs *x862-tail-nargs*) (not spread-p))))
+      (when expression-p
+        ;;Have to do this before spread args, since might be vsp-relative.
+        (if nargs
+          (x862-do-lexical-reference seg destreg fn)
+          (x862-copy-register seg destreg fn)))
+      (if (or symp lfunp)
+        (setq func (if symp
+                     (x862-symbol-entry-locative func)
+                     (x862-afunc-lfun-ref func))
+              a-reg (x862-register-constant-p func)))
+      (when tail-p
+        #-no-compiler-bugs
+        (unless (or immp symp lfunp (typep fn 'lreg) (fixnump fn)) (compiler-bug "Well, well, well.  How could this have happened ?"))
+        (when a-reg
+          (x862-copy-register seg destreg a-reg))
+        (unless spread-p
+          (unless alternate-tail-call
+            (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* (and nargs (<= nargs *x862-target-num-arg-regs*))))))
+      (if spread-p
+        (progn
+          (x862-set-nargs seg (%i- nargs 1))
+                                        ; .SPspread-lexpr-z & .SPspreadargz preserve temp1
+	  (target-arch-case
+	   (:x8632
+	    (! save-node-register-to-spill-area *x862-temp0*)))
+          (if (eq spread-p 0)
+	    (! spread-lexpr)
+            (! spread-list))
+	  (target-arch-case
+	   (:x8632
+	    (! load-node-register-from-spill-area *x862-temp0*)))
+
+          (when (and tail-p *x862-register-restore-count*)
+            (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* nil)))
+        (if nargs
+          (unless alternate-tail-call (x862-set-nargs seg nargs))
+          (! pop-argument-registers)))
+      (if callable
+        (if (not tail-p)
+          (if (x862-mvpass-p xfer)
+            (let* ((call-reg (if symp ($ *x862-fname*) ($ *x862-temp0*))))
+              (unless mvpass-label (compiler-bug "no label for mvpass"))
+              (if label-p
+                (x862-copy-register seg call-reg ($ *x862-fn*))
+                (if a-reg
+                  (x862-copy-register seg call-reg  a-reg)
+                  (x862-store-immediate seg func call-reg)))
+              (if symp
+                (! pass-multiple-values-symbol)
+                (! pass-multiple-values))
+              (when mvpass-label
+                (@= mvpass-label)))
+            (progn 
+              (if label-p
+                (progn
+                  (! call-label (aref *backend-labels* 2)))
+                (progn
+                  (if a-reg
+                    (x862-copy-register seg destreg a-reg)
+                    (x862-store-immediate seg func destreg))
+                  (if symp
+                    (x862-call-symbol seg nil)
+                    (! call-known-function))))))
+          (if alternate-tail-call
+            (progn
+              (x862-unwind-stack seg xfer 0 0 *x862-tail-vsp*)
+              (! jump (aref *backend-labels* *x862-tail-label*)))
+            (progn
+              (x862-unwind-stack seg xfer 0 0 #x7fffff)
+              (if (and (not spread-p) nargs (%i<= nargs *x862-target-num-arg-regs*))
+                (progn
+                  (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
+                  (x862-restore-full-lisp-context seg)
+                  (if label-p
+                    (! jump (aref *backend-labels* 1))
+                    (progn
+                      (if symp
+                        (x862-call-symbol seg t)
+                        (! jump-known-function)))))
+                (progn
+                  (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
+                  (when label-p
+                    (x862-copy-register seg *x862-temp0* *x862-fn*))
+
+                  (cond ((or spread-p (null nargs))
+                         (if symp
+                           (! tail-call-sym-gen)
+                           (! tail-call-fn-gen)))
+                        ((%i> nargs *x862-target-num-arg-regs*)
+                         (if symp
+                           (! tail-call-sym-slide)
+                           (! tail-call-fn-slide)))
+                        (t
+                         (if symp
+                           (! tail-call-sym-vsp)
+                           (! tail-call-fn-vsp)))))))))
+        ;; The general (funcall) case: we don't know (at compile-time)
+        ;; for sure whether we've got a symbol or a (local, constant)
+        ;; function.
+        (progn
+          (unless (or (fixnump fn) (typep fn 'lreg))
+            (x862-one-targeted-reg-form seg fn destreg))
+          (if (not tail-p)
+            (if (x862-mvpass-p xfer)
+              (progn (! pass-multiple-values)
+                     (when mvpass-label
+                       (@= mvpass-label)))
+              (! funcall))                  
+            (cond ((or (null nargs) spread-p)
+                   (! tail-funcall-gen))
+                  ((%i> nargs *x862-target-num-arg-regs*)
+                   (! tail-funcall-slide))
+                  (t
+                   (! restore-full-lisp-context)
+                   (! tail-funcall)))))))
+    nil))
+
+(defun x862-seq-fbind (seg vreg xfer vars afuncs body p2decls)
+  (let* ((old-stack (x862-encode-stack))
+         (copy afuncs)
+         (func nil))
+    (with-x86-p2-declarations p2decls 
+      (dolist (var vars) 
+        (when (neq 0 (afunc-fn-refcount (setq func (pop afuncs))))
+          (x862-seq-bind-var seg var (nx1-afunc-ref func))))
+      (x862-undo-body seg vreg xfer body old-stack)
+      (dolist (var vars)
+        (when (neq 0 (afunc-fn-refcount (setq func (pop copy))))
+          (x862-close-var seg var))))))
+
+(defun x862-make-closure (seg afunc downward-p)
+  (with-x86-local-vinsn-macros (seg)
+    (flet ((var-to-reg (var target)
+             (let* ((ea (var-ea (var-bits var))))
+               (if ea
+                 (x862-addrspec-to-reg seg (x862-ea-open ea) target)
+                 (! load-nil target))
+               target))
+           (set-some-cells (dest cellno c0 c1 c2 c3)
+             (declare (fixnum cellno))
+             (! misc-set-c-node c0 dest cellno)
+             (incf cellno)
+             (when c1
+               (! misc-set-c-node c1 dest cellno)
+               (incf cellno)
+               (when c2
+                 (! misc-set-c-node c2 dest cellno)
+                 (incf cellno)
+                 (when c3
+                   (! misc-set-c-node c3 dest cellno)
+                   (incf cellno))))
+             cellno))
+      (let* ((inherited-vars (afunc-inherited-vars afunc))
+             (arch (backend-target-arch *target-backend*))
+             (dest ($ *x862-arg-z*))
+             (vsize (+ (length inherited-vars)
+		       (target-arch-case
+			(:x8632 7)
+			(:x8664 5))	; %closure-code%, afunc
+                       1)))             ; lfun-bits
+        (declare (list inherited-vars))
+        (let* ((cell (target-arch-case (:x8632 6)
+				       (:x8664 4))))
+          (declare (fixnum cell))
+          (if downward-p
+            (progn
+              (! make-fixed-stack-gvector
+                 dest
+                 (ash (logandc2 (+ vsize 2) 1) (arch::target-word-shift arch))
+                 (arch::make-vheader vsize (nx-lookup-target-uvector-subtag :function)))
+              (x862-open-undo $undostkblk))
+            (progn
+              (x862-lri seg
+                        *x862-imm0*
+                        (arch::make-vheader vsize (nx-lookup-target-uvector-subtag :function)))
+	      (target-arch-case
+	       (:x8632
+		(! setup-uvector-allocation *x862-imm0*)
+		(x862-lri seg *x862-imm0* (- (ash (logandc2 (+ vsize 2) 1) (arch::target-word-shift arch)) x8632::fulltag-misc)))
+	       (:x8664
+		(x862-lri seg x8664::imm1 (- (ash (logandc2 (+ vsize 2) 1) (arch::target-word-shift arch)) x8664::fulltag-misc))))
+              (! %allocate-uvector dest)))
+          (! init-nclosure *x862-arg-z*)
+	  ;;; xxx --- x8632 likely to have register conflicts with *x862-ra0*
+          (x862-store-immediate seg (x862-afunc-lfun-ref afunc) *x862-ra0*)
+	  (target-arch-case
+	   (:x8632
+	    (with-node-temps (*x862-arg-z*) (t0)
+	      (do* ((func *x862-ra0* nil))
+		   ((null inherited-vars))
+		(let* ((t0r (or func (if inherited-vars
+				       (var-to-reg (pop inherited-vars) t0)))))
+		  (! misc-set-c-node t0r dest cell)
+		  (incf cell)))))
+	   (:x8664
+	    (with-node-temps (*x862-arg-z*) (t0 t1 t2 t3)
+	      (do* ((func *x862-ra0* nil))
+		   ((null inherited-vars))
+		(let* ((t0r (or func (if inherited-vars (var-to-reg (pop inherited-vars) t0))))
+		       (t1r (if inherited-vars (var-to-reg (pop inherited-vars) t1)))
+		       (t2r (if inherited-vars (var-to-reg (pop inherited-vars) t2)))
+		       (t3r (if inherited-vars (var-to-reg (pop inherited-vars) t3))))
+		  (setq cell (set-some-cells dest cell t0r t1r t2r t3r)))))))
+	  (x862-lri seg *x862-arg-y* (ash (logior (ash -1 $lfbits-noname-bit) (ash 1 $lfbits-trampoline-bit)) *x862-target-fixnum-shift*))
+          (! misc-set-c-node *x862-arg-y* dest cell))
+        (! finalize-closure dest)
+        dest))))
+        
+(defun x862-symbol-entry-locative (sym)
+  (setq sym (require-type sym 'symbol))
+  (when (eq sym '%call-next-method-with-args)
+    (setf (afunc-bits *x862-cur-afunc*)
+          (%ilogior (%ilsl $fbitnextmethargsp 1) (afunc-bits *x862-cur-afunc*))))
+  (or (assq sym *x862-fcells*)
+      (let ((new (list sym)))
+        (push new *x862-fcells*)
+        new)))
+
+(defun x862-symbol-value-cell (sym)
+  (setq sym (require-type sym 'symbol))
+  (or (assq sym *x862-vcells*)
+      (let ((new (list sym)))
+        (push new *x862-vcells*)
+        (ensure-binding-index sym)
+        new)))
+
+
+(defun x862-symbol-locative-p (imm)
+  (and (consp imm)
+       (or (memq imm *x862-vcells*)
+           (memq imm *x862-fcells*))))
+
+
+
+
+(defun x862-immediate-function-p (f)
+  (setq f (acode-unwrapped-form-value f))
+  (and (acode-p f)
+       (or (eq (%car f) (%nx1-operator immediate))
+           (eq (%car f) (%nx1-operator simple-function)))))
+
+(defun x86-constant-form-p (form)
+  (setq form (nx-untyped-form form))
+  (if form
+    (or (nx-null form)
+        (nx-t form)
+        (and (consp form)
+             (or (eq (acode-operator form) (%nx1-operator immediate))
+                 (eq (acode-operator form) (%nx1-operator fixnum))
+                 (eq (acode-operator form) (%nx1-operator simple-function)))))))
+
+
+  
+(defun x862-integer-constant-p (form mode)
+  (let* ((val 
+         (or (acode-fixnum-form-p (setq form (acode-unwrapped-form form)))
+             (and (acode-p form)
+                  (eq (acode-operator form) (%nx1-operator immediate))
+                  (setq form (%cadr form))
+                  (if (typep form 'integer)
+                    form)))))
+    (when val
+      (let* ((type (mode-specifier-type mode))
+             (high (numeric-ctype-high type))
+             (low (numeric-ctype-low type)))
+        (if (and (>= val low)
+                 (<= val high))
+          val
+          (if (<= (integer-length val) (integer-length (- high low)))
+            (if (eql 0 low)             ; type is unsigned, value is negative
+              (logand high val)
+              (- val (1+ (- high low))))))))))
+
+         
+
+
+(defun x86-side-effect-free-form-p (form)
+  (when (consp (setq form (acode-unwrapped-form-value form)))
+    (or (x86-constant-form-p form)
+        ;(eq (acode-operator form) (%nx1-operator bound-special-ref))
+        (and (eq (acode-operator form) (%nx1-operator %svref))
+             (destructuring-bind (v i) (acode-operands form)
+               (let* ((idx (acode-fixnum-form-p i)))
+                 (and idx
+                      (nx2-constant-index-ok-for-type-keyword idx :simple-vector)
+                      (consp (setq v (acode-unwrapped-form-value v)))
+                      (eq (acode-operator v) (%nx1-operator lexical-reference))
+                      (let* ((var (cadr v)))
+                        (unless (%ilogbitp $vbitsetq (nx-var-bits var))
+                          (var-nvr var)))))))
+        (if (eq (acode-operator form) (%nx1-operator lexical-reference))
+          (not (%ilogbitp $vbitsetq (nx-var-bits (%cadr form))))))))
+
+(defun x862-formlist (seg stkargs &optional revregargs)
+  (with-x86-local-vinsn-macros (seg)  
+    (let* ((nregs (length revregargs))
+           (n nregs))
+      (declare (fixnum n))
+      (dolist (arg stkargs)
+        (let* ((pushform (x862-acode-operator-supports-push arg)))
+          (if pushform
+            (progn
+              (x862-form seg :push nil pushform)
+              (x862-new-vstack-lcell :outgoing-argument *x862-target-lcell-size* 0 nil)
+              (x862-adjust-vstack *x862-target-node-size*))
+              
+            (let* ((reg (x862-one-untargeted-reg-form seg arg *x862-arg-z*)))
+              (x862-vpush-register-arg seg reg)))
+          (incf n)))
+      (when revregargs
+        (let* ((zform (%car revregargs))
+               (yform (%cadr revregargs))
+               (xform (%caddr revregargs)))
+	  (if (eq 3 nregs)
+	    (progn
+	      (target-arch-case (:x8632 (compiler-bug "3 reg args on x8632?")))
+	      (x862-three-targeted-reg-forms seg xform ($ x8664::arg_x)
+					     yform ($ *x862-arg-y*)
+					     zform ($ *x862-arg-z*)))
+	    (if (eq 2 nregs)
+	      (x862-two-targeted-reg-forms seg yform ($ *x862-arg-y*) zform ($ *x862-arg-z*))
+	      (x862-one-targeted-reg-form seg zform ($ *x862-arg-z*))))))
+      n)))
+
+(defun x862-arglist (seg args &optional mv-label)
+  (with-x86-local-vinsn-macros (seg)
+    (when mv-label
+      (x862-vpush-label seg (aref *backend-labels* mv-label)))
+    (when (car args)
+      (! reserve-outgoing-frame)
+      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil)
+      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil)
+      (setq *x862-vstack* (+  *x862-vstack* (* 2 *x862-target-node-size*))))
+    (x862-formlist seg (car args) (cadr args))))
+
+
+(defun x862-unboxed-integer-arg-to-reg (seg form immreg &optional ffi-arg-type)
+  (let* ((mode (ecase ffi-arg-type
+                 ((nil) :natural)
+                 (:signed-byte :s8)
+                 (:unsigned-byte :u8)
+                 (:signed-halfword :s16)
+                 (:unsigned-halfword :u16)
+                 (:signed-fullword :s32)
+                 (:unsigned-fullword :u32)
+                 (:unsigned-doubleword :u64)
+                 (:signed-doubleword :s64)))
+         (modeval (gpr-mode-name-value mode)))
+    (with-x86-local-vinsn-macros (seg)
+      (let* ((value (x862-integer-constant-p form mode)))
+        (if value
+          (progn
+            (unless (typep immreg 'lreg)
+              (setq immreg (make-unwired-lreg immreg :mode modeval)))
+            (if (< value 0)
+              (x862-lri seg immreg value)
+              (x862-lriu seg immreg value))
+            immreg)
+          (progn 
+            (x862-one-targeted-reg-form seg form (make-wired-lreg *x862-imm0* :mode modeval))))))))
+
+
+(defun x862-macptr-arg-to-reg (seg form address-reg)  
+  (x862-one-targeted-reg-form seg
+                              form 
+                              address-reg))
+
+
+(defun x862-one-lreg-form (seg form lreg)
+  (let ((is-float (= (hard-regspec-class lreg) hard-reg-class-fpr)))
+    (if is-float
+      (x862-form-float seg lreg nil form)
+      (x862-form seg lreg nil form))
+    lreg))
+
+(defun x862-one-targeted-reg-form (seg form reg)
+  (x862-one-lreg-form seg form reg))
+
+(defun x862-one-untargeted-lreg-form (seg form reg)
+  (x862-one-lreg-form seg form (if (typep reg 'lreg) reg (make-unwired-lreg reg))))
+
+(defun x862-one-untargeted-reg-form (seg form suggested)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((gpr-p (= (hard-regspec-class suggested) hard-reg-class-gpr))
+           (node-p (if gpr-p (= (get-regspec-mode suggested) hard-reg-class-gpr-mode-node))))
+      (if node-p
+        (let* ((ref (x862-lexical-reference-ea form))
+               (reg (backend-ea-physical-reg ref hard-reg-class-gpr)))
+          (if reg
+            ref
+            (if (nx-null form)
+              (progn
+                (! load-nil suggested)
+                suggested)
+              (if (and (acode-p form) 
+                       (eq (acode-operator form) (%nx1-operator immediate)) 
+                       (setq reg (x862-register-constant-p (cadr form))))
+                reg
+                (x862-one-untargeted-lreg-form seg form suggested)))))
+        (x862-one-untargeted-lreg-form seg form suggested)))))
+             
+
+
+
+(defun x862-push-register (seg areg)
+  (let* ((a-float (= (hard-regspec-class areg) hard-reg-class-fpr))
+         (a-single (if a-float (= (get-regspec-mode areg) hard-reg-class-fpr-mode-single)))
+         (a-node (unless a-float (= (get-regspec-mode areg) hard-reg-class-gpr-mode-node)))
+         vinsn)
+    (with-x86-local-vinsn-macros (seg)
+      (if a-node
+        (setq vinsn (x862-vpush-register seg areg :node-temp))
+        (if a-single
+	  (target-arch-case
+	   (:x8632
+	    (setq vinsn (! temp-push-single-float areg))
+            (x862-open-undo $undo-x86-c-frame))
+	   (:x8664
+	    (setq vinsn (! vpush-single-float areg))
+	    (x862-new-vstack-lcell :single-float *x862-target-lcell-size* 0 nil)
+	    (x862-adjust-vstack *x862-target-node-size*)))
+	  (target-arch-case
+	   (:x8632
+	    (if a-float
+	      (progn
+		(setq vinsn (! temp-push-double-float areg))
+                (x862-open-undo $undo-x86-c-frame))
+	      (progn
+		(setq vinsn (! temp-push-unboxed-word areg))
+		(x862-open-undo $undo-x86-c-frame))))
+	   (:x8664
+            (setq vinsn
+                  (if a-float
+                    (! temp-push-double-float areg)
+                    (! temp-push-unboxed-word areg)))
+            (x862-open-undo $undo-x86-c-frame)))))
+      vinsn)))
+
+
+
+(defun x862-pop-register (seg areg)
+  (let* ((a-float (= (hard-regspec-class areg) hard-reg-class-fpr))
+         (a-single (if a-float (= (get-regspec-mode areg) hard-reg-class-fpr-mode-single)))
+         (a-node (unless a-float (= (get-regspec-mode areg) hard-reg-class-gpr-mode-node)))
+         vinsn)
+    (with-x86-local-vinsn-macros (seg)
+      (if a-node
+        (setq vinsn (x862-vpop-register seg areg))
+        (if a-single
+          (target-arch-case
+	   (:x8632
+	    (setq vinsn (! temp-pop-single-float areg))
+            (x862-close-undo))
+	   (:x8664
+            (setq vinsn (! vpop-single-float areg))
+            (setq *x862-top-vstack-lcell* (lcell-parent *x862-top-vstack-lcell*))
+            (x862-adjust-vstack (- *x862-target-node-size*))))
+          (target-arch-case
+	   (:x8632
+	    (if a-float
+	      (progn
+		(setq vinsn (! temp-pop-double-float areg))
+		(x862-close-undo))
+	      (progn
+		(setq vinsn (! temp-pop-unboxed-word areg))
+		(x862-close-undo))))
+	   (:x8664
+            (setq vinsn
+                  (if a-float
+                    (! temp-pop-double-float areg)
+                    (! temp-pop-unboxed-word areg)))
+            (x862-close-undo)))))
+      vinsn)))
+
+;;; If reg is a GPR and of mode node, use arg_z, otherwise, just return
+;;; reg.
+(defun x862-acc-reg-for (reg)
+  (with-x86-local-vinsn-macros (seg)
+    (if (and (eql (hard-regspec-class reg) hard-reg-class-gpr)
+           (eql (get-regspec-mode reg) hard-reg-class-gpr-mode-node))
+      ($ *x862-arg-z*)
+      reg)))
+
+;;; The compiler often generates superfluous pushes & pops.  Try to
+;;; eliminate them.
+(defun x862-elide-pushes (seg push-vinsn pop-vinsn)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((pushed-reg (svref (vinsn-variable-parts push-vinsn) 0))
+           (popped-reg (svref (vinsn-variable-parts pop-vinsn) 0))
+           (same-reg (eq (hard-regspec-value pushed-reg)
+                         (hard-regspec-value popped-reg)))
+           (csp-p (vinsn-attribute-p push-vinsn :csp)))
+      (when csp-p                       ; vsp case is harder.
+        (unless (vinsn-sequence-has-attribute-p push-vinsn pop-vinsn :csp :discard)
+          (let* ((pushed-reg-is-set (vinsn-sequence-sets-reg-p
+                                     push-vinsn pop-vinsn pushed-reg))
+                 (popped-reg-is-set (if same-reg
+                                      pushed-reg-is-set
+                                      (vinsn-sequence-sets-reg-p
+                                       push-vinsn pop-vinsn popped-reg))))
+            (unless (and pushed-reg-is-set popped-reg-is-set)
+              (unless same-reg
+                (let* ((copy (if (eq (hard-regspec-class pushed-reg)
+                                     hard-reg-class-fpr)
+                               (if (= (get-regspec-mode pushed-reg)
+                                      hard-reg-class-fpr-mode-double)
+                                 (! copy-double-float popped-reg pushed-reg)
+                                 (! copy-single-float popped-reg pushed-reg))
+                               (! copy-gpr popped-reg pushed-reg))))
+                  (remove-dll-node copy)
+                  (if pushed-reg-is-set
+                    (insert-dll-node-after copy push-vinsn)
+                    (insert-dll-node-before copy push-vinsn))))
+              (elide-vinsn push-vinsn)
+              (elide-vinsn pop-vinsn))))))))
+                
+        
+;;; we never leave the first form pushed (the 68K compiler had some subprims that
+;;; would vpop the first argument out of line.)
+(defun x862-two-targeted-reg-forms (seg aform areg bform breg)
+  (let* ((avar (nx2-lexical-reference-p aform))
+         (atriv (and (x862-trivial-p bform areg) (nx2-node-gpr-p breg)))
+         (aconst (and (not atriv) (or (x86-side-effect-free-form-p aform)
+                                      (if avar (nx2-var-not-set-by-form-p avar bform)))))
+         apushed)
+    (progn
+      (unless aconst
+        (if atriv
+          (x862-one-targeted-reg-form seg aform areg)
+          (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
+      (x862-one-targeted-reg-form seg bform breg)
+      (if aconst
+        (x862-one-targeted-reg-form seg aform areg)
+        (if apushed
+          (x862-elide-pushes seg apushed (x862-pop-register seg areg)))))
+    (values areg breg)))
+
+
+(defun x862-two-untargeted-reg-forms (seg aform areg bform breg)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((avar (nx2-lexical-reference-p aform))
+           (adest areg)
+           (bdest breg)
+           (atriv (and (x862-trivial-p bform) (nx2-node-gpr-p breg)))
+           (aconst (and (not atriv) (or (x86-side-effect-free-form-p aform)
+                                        (if avar (nx2-var-not-set-by-form-p avar bform)))))
+           (apushed (not (or atriv aconst))))
+      (progn
+        (unless aconst
+          (if atriv
+            (setq adest (x862-one-untargeted-reg-form seg aform areg))
+            (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
+        (setq bdest (x862-one-untargeted-reg-form seg bform breg))
+        (if aconst
+          (setq adest (x862-one-untargeted-reg-form seg aform areg))
+          (if apushed
+            (x862-elide-pushes seg apushed (x862-pop-register seg areg)))))
+      (values adest bdest))))
+
+
+(defun x862-three-targeted-reg-forms (seg aform areg bform breg cform creg)
+  (let* ((bnode (nx2-node-gpr-p breg))
+         (cnode (nx2-node-gpr-p creg))
+         (atriv (or (null aform) 
+                    (and (x862-trivial-p bform areg)
+                         (x862-trivial-p cform areg)
+                         bnode
+                         cnode)))
+         (btriv (or (null bform)
+                    (and (x862-trivial-p cform breg)
+                         cnode)))
+         (aconst (and (not atriv) 
+                      (or (x86-side-effect-free-form-p aform)
+                          (let ((avar (nx2-lexical-reference-p aform)))
+                            (and avar 
+                                 (nx2-var-not-set-by-form-p avar bform)
+                                 (nx2-var-not-set-by-form-p avar cform))))))
+         (bconst (and (not btriv)
+                      (or
+                       (x86-side-effect-free-form-p bform)
+                       (let ((bvar (nx2-lexical-reference-p bform)))
+                         (and bvar (nx2-var-not-set-by-form-p bvar cform))))))
+         (apushed nil)
+         (bpushed nil))
+    (if (and aform (not aconst))
+      (if atriv
+        (x862-one-targeted-reg-form seg aform areg)
+        (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
+    (if (and bform (not bconst))
+      (if btriv
+        (x862-one-targeted-reg-form seg bform breg)
+        (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
+    (x862-one-targeted-reg-form seg cform creg)
+    (unless btriv 
+      (if bconst
+        (x862-one-targeted-reg-form seg bform breg)
+        (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
+    (unless atriv
+      (if aconst
+        (x862-one-targeted-reg-form seg aform areg)
+        (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
+    (values areg breg creg)))
+
+(defun x862-four-targeted-reg-forms (seg aform areg bform breg cform creg dform dreg)
+  (let* ((bnode (nx2-node-gpr-p breg))
+         (cnode (nx2-node-gpr-p creg))
+         (dnode (nx2-node-gpr-p dreg))
+         (atriv (or (null aform) 
+                    (and (x862-trivial-p bform areg)
+                         (x862-trivial-p cform areg)
+                         (x862-trivial-p dform areg)
+                         bnode
+                         cnode
+                         dnode)))
+         (btriv (or (null bform)
+                    (and (x862-trivial-p cform breg)
+                         (x862-trivial-p dform breg)
+                         cnode
+                         dnode)))
+         (ctriv (or (null cform)
+                    (and (x862-trivial-p dform creg)
+                         dnode)))
+         (aconst (and (not atriv) 
+                      (or (x86-side-effect-free-form-p aform)
+                          (let ((avar (nx2-lexical-reference-p aform)))
+                            (and avar 
+                                 (nx2-var-not-set-by-form-p avar bform)
+                                 (nx2-var-not-set-by-form-p avar cform)
+                                 (nx2-var-not-set-by-form-p avar dform))))))
+         (bconst (and (not btriv)
+                      (or
+                       (x86-side-effect-free-form-p bform)
+                       (let ((bvar (nx2-lexical-reference-p bform)))
+                         (and bvar
+                              (nx2-var-not-set-by-form-p bvar cform)
+                              (nx2-var-not-set-by-form-p bvar dform))))))
+         (cconst (and (not ctriv)
+                      (or
+                       (x86-side-effect-free-form-p cform)
+                       (let ((cvar (nx2-lexical-reference-p cform)))
+                         (and cvar (nx2-var-not-set-by-form-p cvar dform))))))
+         (apushed nil)
+         (bpushed nil)
+         (cpushed nil))
+    (if (and aform (not aconst))
+      (if atriv
+        (x862-one-targeted-reg-form seg aform areg)
+        (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
+    (if (and bform (not bconst))
+      (if btriv
+        (x862-one-targeted-reg-form seg bform breg)
+        (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
+    (if (and cform (not cconst))
+      (if ctriv
+        (x862-one-targeted-reg-form seg cform creg)
+        (setq cpushed (x862-push-register seg (x862-one-untargeted-reg-form seg cform (x862-acc-reg-for creg))))))
+    (x862-one-targeted-reg-form seg dform dreg)
+    (unless ctriv
+      (if cconst
+        (x862-one-targeted-reg-form seg cform creg)
+        (x862-elide-pushes seg cpushed (x862-pop-register seg creg))))
+    (unless btriv 
+      (if bconst
+        (x862-one-targeted-reg-form seg bform breg)
+        (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
+    (unless atriv
+      (if aconst
+        (x862-one-targeted-reg-form seg aform areg)
+        (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
+    (values areg breg creg dreg)))
+
+(defun x862-three-untargeted-reg-forms (seg aform areg bform breg cform creg)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((bnode (nx2-node-gpr-p breg))
+           (cnode (nx2-node-gpr-p creg))
+           (atriv (or (null aform) 
+                      (and (x862-trivial-p bform)
+                           (x862-trivial-p cform)
+                           bnode
+                           cnode)))
+           (btriv (or (null bform)
+                      (and (x862-trivial-p cform)
+                           cnode)))
+           (aconst (and (not atriv) 
+                        (or (x86-side-effect-free-form-p aform)
+                            (let ((avar (nx2-lexical-reference-p aform)))
+                              (and avar 
+                                   (nx2-var-not-set-by-form-p avar bform)
+                                   (nx2-var-not-set-by-form-p avar cform))))))
+           (bconst (and (not btriv)
+                        (or
+                         (x86-side-effect-free-form-p bform)
+                         (let ((bvar (nx2-lexical-reference-p bform)))
+                           (and bvar (nx2-var-not-set-by-form-p bvar cform))))))
+           (adest areg)
+           (bdest breg)
+           (cdest creg)
+           (apushed nil)
+           (bpushed nil))
+      (if (and aform (not aconst))
+        (if atriv
+          (setq adest (x862-one-untargeted-reg-form seg aform ($ areg)))
+          (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
+      (if (and bform (not bconst))
+        (if btriv
+          (setq bdest (x862-one-untargeted-reg-form seg bform ($ breg)))
+          (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
+      (setq cdest (x862-one-untargeted-reg-form seg cform creg))
+      (unless btriv 
+        (if bconst
+          (setq bdest (x862-one-untargeted-reg-form seg bform breg))
+          (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
+      (unless atriv
+        (if aconst
+          (setq adest (x862-one-untargeted-reg-form seg aform areg))
+          (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
+      (values adest bdest cdest))))
+
+(defun x862-four-untargeted-reg-forms (seg aform areg bform breg cform creg dform dreg)
+  (let* ((bnode (nx2-node-gpr-p breg))
+         (cnode (nx2-node-gpr-p creg))
+         (dnode (nx2-node-gpr-p dreg))
+         (atriv (or (null aform) 
+                    (and (x862-trivial-p bform)
+                         (x862-trivial-p cform)
+                         (x862-trivial-p dform)
+                         bnode
+                         cnode
+                         dnode)))
+         (btriv (or (null bform)
+                    (and (x862-trivial-p cform)
+                         (x862-trivial-p dform)
+                         cnode
+                         dnode)))
+         (ctriv (or (null cform)
+                    (x862-trivial-p dform)))
+         (aconst (and (not atriv) 
+                      (or (x86-side-effect-free-form-p aform)
+                          (let ((avar (nx2-lexical-reference-p aform)))
+                            (and avar 
+                                 (nx2-var-not-set-by-form-p avar bform)
+                                 (nx2-var-not-set-by-form-p avar cform)
+                                 (nx2-var-not-set-by-form-p avar dform))))))
+         (bconst (and (not btriv)
+                      (or
+                       (x86-side-effect-free-form-p bform)
+                       (let ((bvar (nx2-lexical-reference-p bform)))
+                         (and bvar
+                              (nx2-var-not-set-by-form-p bvar cform)
+                              (nx2-var-not-set-by-form-p bvar dform))))))
+         (cconst (and (not ctriv)
+                      (or
+                       (x86-side-effect-free-form-p cform)
+                       (let ((cvar (nx2-lexical-reference-p cform)))
+                         (and cvar
+                              (nx2-var-not-set-by-form-p cvar dform))))))
+         (adest areg)
+         (bdest breg)
+         (cdest creg)
+         (ddest dreg)
+         (apushed nil)
+         (bpushed nil)
+         (cpushed nil))
+    (if (and aform (not aconst))
+      (if atriv
+        (setq adest (x862-one-targeted-reg-form seg aform areg))
+        (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
+    (if (and bform (not bconst))
+      (if btriv
+        (setq bdest (x862-one-untargeted-reg-form seg bform breg))
+        (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
+    (if (and cform (not cconst))
+      (if ctriv
+        (setq cdest (x862-one-untargeted-reg-form seg cform creg))
+        (setq cpushed (x862-push-register seg (x862-one-untargeted-reg-form seg cform (x862-acc-reg-for creg))))))
+    (setq ddest (x862-one-untargeted-reg-form seg dform dreg))
+    (unless ctriv 
+      (if cconst
+        (setq cdest (x862-one-untargeted-reg-form seg cform creg))
+        (x862-elide-pushes seg cpushed (x862-pop-register seg creg))))
+    (unless btriv 
+      (if bconst
+        (setq bdest (x862-one-untargeted-reg-form seg bform breg))
+        (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
+    (unless atriv
+      (if aconst
+        (setq adest (x862-one-untargeted-reg-form seg aform areg))
+        (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
+    (values adest bdest cdest ddest)))
+
+(defun x862-lri (seg reg value)
+  (with-x86-local-vinsn-macros (seg)
+    (! lri reg value)))
+
+;;; unsigned variant
+(defun x862-lriu (seg reg value)
+  (with-x86-local-vinsn-macros (seg)
+    (! lriu reg value)))
+
+(defun x862-multiple-value-body (seg form)
+  (let* ((lab (backend-get-next-label))
+         (*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+         (old-stack (x862-encode-stack)))
+    (with-x86-local-vinsn-macros (seg)
+      (x862-open-undo $undomvexpect)
+      (x862-undo-body seg nil (logior $backend-mvpass-mask lab) form old-stack)
+      (@ lab))))
+
+(defun x862-afunc-lfun-ref (afunc)
+  (or
+   (afunc-lfun afunc)
+   (progn (pushnew afunc (afunc-fwd-refs *x862-cur-afunc*) :test #'eq)
+          afunc)))
+
+(defun x862-augment-arglist (afunc arglist &optional (maxregs *x862-target-num-arg-regs*))
+  (let ((inherited-args (afunc-inherited-vars afunc)))
+    (when inherited-args
+      (let* ((current-afunc *x862-cur-afunc*)
+             (stkargs (car arglist))
+             (regargs (cadr arglist))
+             (inhforms nil)
+             (numregs (length regargs))
+             (own-inhvars (afunc-inherited-vars current-afunc)))
+        (dolist (var inherited-args)
+          (let* ((root-var (nx-root-var var))
+                 (other-guy 
+                  (dolist (v own-inhvars #|(error "other guy not found")|# root-var)
+                    (when (eq root-var (nx-root-var v)) (return v)))))
+            (push (make-acode (%nx1-operator inherited-arg) other-guy) inhforms)))
+        (dolist (form inhforms)
+          (if (%i< numregs maxregs)
+            (progn
+              (setq regargs (nconc regargs (list form)))
+              (setq numregs (%i+ numregs 1)))
+            (push form stkargs)))
+        (%rplaca (%cdr arglist) regargs) ; might have started out NIL.
+        (%rplaca arglist stkargs)))) 
+  arglist)
+
+(defun x862-acode-operator-supports-u8 (form)
+  (setq form (acode-unwrapped-form-value form))
+  (when (acode-p form)
+    (let* ((operator (acode-operator form)))
+      (if (member operator *x862-operator-supports-u8-target*)
+        (values operator (acode-operand 1 form))))))
+
+(defun x862-acode-operator-supports-push (form)
+  (let ((value (acode-unwrapped-form-value form)))
+    (when (acode-p value)
+      (if (or (nx-t value)
+              (nx-null value)
+              (let* ((operator (acode-operator value)))
+                (member operator *x862-operator-supports-push*)))
+        value))))
+
+(defun x862-compare-u8 (seg vreg xfer form u8constant cr-bit true-p u8-operator)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (with-imm-target () (u8 :u8)
+      (if (and (eql u8-operator (%nx1-operator lisptag))
+               (eql 0 u8constant))
+        (let* ((formreg (x862-one-untargeted-reg-form seg form *x862-arg-z*)))
+          
+          (! set-flags-from-lisptag formreg))
+        (progn
+          (x862-use-operator u8-operator seg u8 nil form)
+          (if (zerop u8constant)
+            (! compare-u8-reg-to-zero u8)
+            (! compare-u8-constant u8 u8constant))))
+      ;; Flags set.  Branch or return a boolean value ?
+      (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (^ cr-bit true-p)
+       (progn
+         (ensuring-node-target (target dest)
+           (if (not true-p)
+             (setq cr-bit (logxor 1 cr-bit)))
+           (! cr-bit->boolean target cr-bit))
+         (^))))))
+
+;;; There are other cases involving constants that are worth exploiting.
+(defun x862-compare (seg vreg xfer i j cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((iu8 (let* ((i-fixnum (acode-fixnum-form-p i)))
+                  (if (typep i-fixnum '(unsigned-byte 8))
+                    i-fixnum)))
+           (ju8 (let* ((j-fixnum (acode-fixnum-form-p j)))
+                  (if (typep j-fixnum '(unsigned-byte 8))
+                    j-fixnum)))
+           (u8 (or iu8 ju8))
+           (other-u8 (if iu8 j (if ju8 i)))
+           (js32 (acode-s32-constant-p j))
+           (is32 (acode-s32-constant-p i))
+           (boolean (backend-crf-p vreg)))
+      (multiple-value-bind (u8-operator u8-operand) (if other-u8 (x862-acode-operator-supports-u8 other-u8))
+        (if u8-operator
+          (x862-compare-u8 seg vreg xfer u8-operand u8 (if (and iu8 (not (eq cr-bit x86::x86-e-bits))) (logxor 1 cr-bit) cr-bit) true-p u8-operator)
+          (if (and boolean (or js32 is32))
+            (let* ((reg (x862-one-untargeted-reg-form seg (if js32 i j) *x862-arg-z*))
+                   (constant (or js32 is32)))
+              (if (zerop constant)
+                (! compare-reg-to-zero reg)
+                (! compare-s32-constant reg (or js32 is32)))
+              (unless (or js32 (eq cr-bit x86::x86-e-bits))
+                (setq cr-bit (x862-reverse-cr-bit cr-bit)))
+              (^ cr-bit true-p))
+            (if (and ;(eq cr-bit x86::x86-e-bits) 
+                     (or js32 is32))
+              (progn
+                (unless (or js32 (eq cr-bit x86::x86-e-bits))
+                  (setq cr-bit (x862-reverse-cr-bit cr-bit)))
+              (x862-test-reg-%izerop
+               seg 
+               vreg 
+               xfer 
+               (x862-one-untargeted-reg-form 
+                seg 
+                (if js32 i j) 
+                *x862-arg-z*) 
+               cr-bit 
+               true-p 
+               (or js32 is32)))
+              (multiple-value-bind (ireg jreg) (x862-two-untargeted-reg-forms seg i *x862-arg-y* j *x862-arg-z*)
+                (x862-compare-registers seg vreg xfer ireg jreg cr-bit true-p)))))))))
+
+(defun x862-natural-compare (seg vreg xfer i j cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((jconstant (acode-fixnum-form-p j))
+           (ju31 (typep jconstant '(unsigned-byte 31)))
+           (iconstant (acode-fixnum-form-p i))
+           (iu31 (typep iconstant '(unsigned-byte 31)))
+           (boolean (backend-crf-p vreg)))
+      (if (and boolean (or ju31 iu31))
+        (with-imm-target
+            () (reg :natural)
+            (x862-one-targeted-reg-form seg (if ju31 i j) reg)
+            (! compare-u31-constant reg (if ju31 jconstant iconstant))
+            (unless (or ju31 (eq cr-bit x86::x86-e-bits)) 
+              (setq cr-bit (x862-reverse-cr-bit cr-bit)))
+            (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
+            (^ cr-bit true-p))
+        (target-arch-case
+         (:x8664
+          (with-imm-target () (ireg :natural)
+            (with-imm-target (ireg) (jreg :natural)
+              (x862-two-targeted-reg-forms seg i ireg j jreg)
+              (x862-compare-natural-registers seg vreg xfer ireg jreg cr-bit true-p))))
+         (:x8632
+          (with-imm-target () (jreg :natural) 
+            (x862-one-targeted-reg-form seg i jreg)
+            (x862-push-register seg jreg)
+            (x862-one-targeted-reg-form seg j jreg)
+            (! temp-pop-temp1-as-unboxed-word)
+            (x862-close-undo)
+            (x862-compare-natural-registers seg vreg xfer ($ x8632::temp1) jreg cr-bit true-p))))))))
+
+
+
+                 
+(defun x862-compare-natural-registers (seg vreg xfer ireg jreg cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (progn
+        (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
+        (! compare ireg jreg)
+        (target-arch-case
+         (:x8664)
+         (:x8632 (! mark-temp1-as-node-preserving-flags)))
+        (regspec-crf-gpr-case 
+         (vreg dest)
+         (^ cr-bit true-p)
+         (progn
+           (ensuring-node-target (target dest)
+             (if (not true-p)
+               (setq cr-bit (logxor 1 cr-bit)))
+             (! cr-bit->boolean target cr-bit))
+           (^))))
+      (^))))
+
+
+(defun x862-compare-registers (seg vreg xfer ireg jreg cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (progn
+        (! compare ireg jreg)
+        (regspec-crf-gpr-case 
+         (vreg dest)
+         (^ cr-bit true-p)
+         (progn
+           (ensuring-node-target (target dest)
+             (if (not true-p)
+               (setq cr-bit (logxor 1 cr-bit)))
+             (! cr-bit->boolean target cr-bit))
+           (^))))
+      (^))))
+
+(defun x862-compare-register-to-constant (seg vreg xfer ireg cr-bit true-p constant)
+  (cond ((nx-null constant)
+         (x862-compare-register-to-nil seg vreg xfer ireg cr-bit true-p))
+        (t
+         (with-x86-local-vinsn-macros (seg vreg xfer)
+           (when vreg
+             (if (nx-t constant)
+               (! compare-to-t ireg)
+               (let* ((imm (acode-immediate-operand constant))
+                      (reg (x862-register-constant-p imm))) 
+                 (if reg
+                   (! compare-registers reg ireg)
+                   (! compare-constant-to-register (x86-immediate-label imm) ireg))))
+             (regspec-crf-gpr-case 
+              (vreg dest)
+              (^ cr-bit true-p)
+              (progn
+                (ensuring-node-target (target dest)
+                  (if (not true-p)
+                    (setq cr-bit (logxor 1 cr-bit)))
+                  (! cr-bit->boolean target cr-bit))
+                (^))))))))
+         
+(defun x862-compare-register-to-nil (seg vreg xfer ireg cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (! compare-to-nil ireg)
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (^ cr-bit true-p)
+       (progn
+       (ensuring-node-target (target dest)
+         (if (not true-p)
+           (setq cr-bit (logxor 1 cr-bit)))
+         (! cr-bit->boolean target cr-bit))
+       (^))))))
+
+(defun x862-compare-ea-to-nil (seg vreg xfer ea cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (if (addrspec-vcell-p ea)
+        (with-node-target () temp
+          (x862-stack-to-register seg ea temp)
+          (! compare-value-cell-to-nil temp))
+        (! compare-vframe-offset-to-nil (memspec-frame-address-offset ea) *x862-vstack*))
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (^ cr-bit true-p)
+       (progn
+       (ensuring-node-target (target dest)
+         (if (not true-p)
+           (setq cr-bit (logxor 1 cr-bit)))
+         (! cr-bit->boolean target cr-bit))
+       (^))))))
+
+(defun x862-cr-bit-for-unsigned-comparison (cr-bit)
+  (ecase cr-bit
+    (#.x86::x86-e-bits #.x86::x86-e-bits)
+    (#.x86::x86-ne-bits #.x86::x86-ne-bits)
+    (#.x86::x86-l-bits #.x86::x86-b-bits)
+    (#.x86::x86-le-bits #.x86::x86-be-bits)
+    (#.x86::x86-ge-bits #.x86::x86-ae-bits)
+    (#.x86::x86-g-bits #.x86::x86-a-bits)))
+
+
+(defun x862-compare-double-float-registers (seg vreg xfer ireg jreg cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (progn
+        (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
+        (regspec-crf-gpr-case 
+         (vreg dest)
+         (progn
+           (! double-float-compare ireg jreg)
+           (^ cr-bit true-p))
+         (progn
+           (! double-float-compare ireg jreg)
+           (ensuring-node-target (target dest)
+             (if (not true-p)
+               (setq cr-bit (logxor 1 cr-bit)))
+             (! cr-bit->boolean target cr-bit))
+           (^))))
+      (^))))
+
+(defun x862-compare-single-float-registers (seg vreg xfer ireg jreg cr-bit true-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if vreg
+      (progn
+        (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
+        (regspec-crf-gpr-case 
+         (vreg dest)
+         (progn
+           (! single-float-compare ireg jreg)
+           (^ cr-bit true-p))
+         (progn
+           (! single-float-compare ireg jreg)
+           (ensuring-node-target (target dest)
+             (if (not true-p)
+               (setq cr-bit (logxor 1 cr-bit)))
+             (! cr-bit->boolean target cr-bit))
+         (^))))
+      (^))))
+
+
+(defun x862-immediate-form-p (form)
+  (if (and (consp form)
+           (or (eq (%car form) (%nx1-operator immediate))
+               (eq (%car form) (%nx1-operator simple-function))))
+    t))
+
+(defun x862-test-%izerop (seg vreg xfer form cr-bit true-p)
+  (x862-test-reg-%izerop seg vreg xfer (x862-one-untargeted-reg-form seg form *x862-arg-z*) cr-bit true-p 0))
+
+(defun x862-test-reg-%izerop (seg vreg xfer reg cr-bit true-p  zero)
+  (declare (fixnum zero))
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if (zerop zero)
+      (! compare-reg-to-zero reg)
+      (! compare-s32-constant reg zero))
+    (regspec-crf-gpr-case 
+     (vreg dest)
+     (^ cr-bit true-p)
+     (progn
+       (ensuring-node-target (target dest)
+         (if (not true-p)
+           (setq cr-bit (logxor 1 cr-bit)))
+         (! cr-bit->boolean target cr-bit))
+       (^)))))
+
+(defun x862-lexical-reference-ea (form &optional (no-closed-p t))
+  (when (acode-p (setq form (acode-unwrapped-form-value form)))
+    (if (eq (acode-operator form) (%nx1-operator lexical-reference))
+      (let* ((addr (var-ea (%cadr form))))
+        (if (typep addr 'lreg)
+          addr
+          (unless (and no-closed-p (addrspec-vcell-p addr ))
+            addr))))))
+
+
+(defun x862-vpush-register (seg src &optional why info attr)
+  (with-x86-local-vinsn-macros (seg)
+    (prog1
+      (! vpush-register src)
+      (setq *x862-tos-reg* src)
+      (x862-new-vstack-lcell (or why :node) *x862-target-lcell-size* (or attr 0) info)
+      (x862-adjust-vstack *x862-target-node-size*))))
+
+
+;;; Need to track stack usage when pushing label for mv-call.
+(defun x862-vpush-label (seg label)
+  (with-x86-local-vinsn-macros (seg)
+    (prog1
+      (! vpush-label label)
+      (x862-new-vstack-lcell :label *x862-target-lcell-size* 0 nil)
+      (x862-adjust-vstack *x862-target-node-size*))))
+
+(defun x862-temp-push-node (seg reg)
+  (with-x86-local-vinsn-macros (seg)
+    (! temp-push-node reg)
+    (x862-open-undo $undostkblk)))
+
+(defun x862-temp-pop-node (seg reg)
+  (with-x86-local-vinsn-macros (seg)
+    (! temp-pop-node reg)
+    (x862-close-undo)))
+
+(defun x862-vpush-register-arg (seg src)
+  (x862-vpush-register seg src :outgoing-argument))
+
+
+(defun x862-vpop-register (seg dest)
+  (with-x86-local-vinsn-macros (seg)
+    (prog1
+      (! vpop-register dest)
+      (setq *x862-top-vstack-lcell* (lcell-parent *x862-top-vstack-lcell*))
+      (x862-adjust-vstack (- *x862-target-node-size*)))))
+
+(defun x862-macptr->heap (seg dest src)
+  (with-x86-local-vinsn-macros (seg)
+    (! setup-macptr-allocation src)
+    (! %allocate-uvector dest)
+    (! %set-new-macptr-value dest)))
+
+(defun x862-copy-register (seg dest src)
+  (with-x86-local-vinsn-macros (seg)
+    (when dest
+      (let* ((dest-gpr (backend-ea-physical-reg dest hard-reg-class-gpr))
+             (src-gpr (if src (backend-ea-physical-reg src hard-reg-class-gpr)))
+             (dest-fpr (backend-ea-physical-reg dest hard-reg-class-fpr))
+             (src-fpr (if src (backend-ea-physical-reg src hard-reg-class-fpr)))
+             (src-mode (if src (get-regspec-mode src)))
+             (dest-mode (get-regspec-mode dest))
+             (dest-crf (backend-ea-physical-reg dest hard-reg-class-crf)))
+        (if (null src)
+          (if dest-gpr
+            (! load-nil dest-gpr)
+            (if dest-crf
+              (! set-eq-bit)))
+          (if (and dest-crf src-gpr)
+            ;; "Copying" a GPR to a CR field means comparing it to rnil
+            (! compare-to-nil src)
+            (if (and dest-gpr src-gpr)
+              (if (eq src-mode dest-mode)
+                (unless (eq src-gpr dest-gpr)
+                  (! copy-gpr dest src))
+                ;; This is the "GPR <- GPR" case.  There are
+                ;; word-size dependencies, but there's also
+                ;; lots of redundancy here.
+                (target-arch-case
+		 (:x8632
+		  (ecase dest-mode
+		    (#.hard-reg-class-gpr-mode-node ; boxed result.
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u32
+                        (x862-box-u32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-s32
+                        (x862-box-s32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-address
+                        (x862-macptr->heap seg dest src))))
+		    ((#.hard-reg-class-gpr-mode-u32
+                      #.hard-reg-class-gpr-mode-address)
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (let* ((src-type (get-node-regspec-type-modes src)))
+                          (declare (fixnum src-type))
+                          (case dest-mode
+                            (#.hard-reg-class-gpr-mode-u32
+                             (! unbox-u32 dest src))
+                            (#.hard-reg-class-gpr-mode-address
+                             (unless (or (logbitp #.hard-reg-class-gpr-mode-address src-type)
+                                         *x862-reckless*)
+                               (! trap-unless-macptr src))
+                             (! deref-macptr dest src)))))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->u32 dest src))                 
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))))
+                    (#.hard-reg-class-gpr-mode-s32
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->u32 dest src))                 
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))))
+		    (#.hard-reg-class-gpr-mode-u16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-u16 dest src))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s16 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-u8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (if *x862-reckless*
+                          (! %unbox-u8 dest src)
+                          (! unbox-u8 dest src)))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s8 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))))
+                 (:x8664
+                  (ecase dest-mode
+                    (#.hard-reg-class-gpr-mode-node ; boxed result.
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u64
+                        (x862-box-u64 seg dest src))
+                       (#.hard-reg-class-gpr-mode-s64
+                        (x862-box-s64 seg dest src))
+                       (#.hard-reg-class-gpr-mode-u32
+                        (x862-box-u32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-s32
+                        (x862-box-s32 seg dest src))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! box-fixnum dest src))
+                       (#.hard-reg-class-gpr-mode-address
+                        (x862-macptr->heap seg dest src))))
+                    ((#.hard-reg-class-gpr-mode-u64
+                      #.hard-reg-class-gpr-mode-address)
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (let* ((src-type (get-node-regspec-type-modes src)))
+                          (declare (fixnum src-type))
+                          (case dest-mode
+                            (#.hard-reg-class-gpr-mode-u64
+                             (! unbox-u64 dest src))
+                            (#.hard-reg-class-gpr-mode-address
+                             (unless (or (logbitp #.hard-reg-class-gpr-mode-address src-type)
+                                         *x862-reckless*)
+                               (! trap-unless-macptr src))
+                             (! deref-macptr dest src)))))
+                       ((#.hard-reg-class-gpr-mode-u64
+                         #.hard-reg-class-gpr-mode-s64
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       ((#.hard-reg-class-gpr-mode-u16
+                         #.hard-reg-class-gpr-mode-s16)
+                        (! u16->u32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! u8->u32 dest src))))
+                    (#.hard-reg-class-gpr-mode-s64
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s64 dest src))
+                       ((#.hard-reg-class-gpr-mode-u64
+                         #.hard-reg-class-gpr-mode-s64
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       ((#.hard-reg-class-gpr-mode-u16
+                         #.hard-reg-class-gpr-mode-s16)
+                        (! s16->s32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! s8->s32 dest src))))
+                    (#.hard-reg-class-gpr-mode-s32
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s32 dest src))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32
+                         #.hard-reg-class-gpr-mode-address)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->u32 dest src))                 
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))))
+                    (#.hard-reg-class-gpr-mode-u32
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (if *x862-reckless*
+                          (! %unbox-u32 dest src)
+                          (! unbox-u32 dest src)))
+                       ((#.hard-reg-class-gpr-mode-u32
+                         #.hard-reg-class-gpr-mode-s32)
+                        (unless (eql  dest-gpr src-gpr)
+                          (! copy-gpr dest src)))
+                       (#.hard-reg-class-gpr-mode-u16
+                        (! u16->u32 dest src))                 
+                       (#.hard-reg-class-gpr-mode-s16
+                        (! s16->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))))
+                    (#.hard-reg-class-gpr-mode-u16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (if *x862-reckless*
+                          (! %unbox-u16 dest src)
+                          (! unbox-u16 dest src)))
+                       ((#.hard-reg-class-gpr-mode-u8
+                         #.hard-reg-class-gpr-mode-s8)
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s16
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s16 dest src))
+                       (#.hard-reg-class-gpr-mode-s8
+                        (! s8->s32 dest src))
+                       (#.hard-reg-class-gpr-mode-u8
+                        (! u8->u32 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-u8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (if *x862-reckless*
+                          (! %unbox-u8 dest src)
+                          (! unbox-u8 dest src)))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))
+                    (#.hard-reg-class-gpr-mode-s8
+                     (case src-mode
+                       (#.hard-reg-class-gpr-mode-node
+                        (! unbox-s8 dest src))
+                       (t
+                        (unless (eql dest-gpr src-gpr)
+                          (! copy-gpr dest src)))))))))
+              (if src-gpr
+                (if dest-fpr
+                  (progn
+                    (case src-mode
+                      (#.hard-reg-class-gpr-mode-node
+                       (case dest-mode
+                         (#.hard-reg-class-fpr-mode-double
+                          (unless (or (logbitp hard-reg-class-fpr-type-double 
+                                           (get-node-regspec-type-modes src))
+                                      *x862-reckless*)
+                            (! trap-unless-double-float src))
+                          (! get-double dest src))
+                         (#.hard-reg-class-fpr-mode-single
+                          (unless *x862-reckless* (! trap-unless-single-float src))
+                          (! get-single dest src)))))))
+                (if dest-gpr
+                  (case dest-mode
+                    (#.hard-reg-class-gpr-mode-node
+                     (case src-mode
+                       (#.hard-reg-class-fpr-mode-double
+                        (x862-double->heap seg dest src))
+                       (#.hard-reg-class-fpr-mode-single
+			(target-arch-case
+			 (:x8632
+			  (x862-single->heap seg dest src))
+			 (:x8664
+			  (! single->node dest src)))))))
+                  (if (and src-fpr dest-fpr)
+                    (unless (eql dest-fpr src-fpr)
+                      (if (= src-mode hard-reg-class-fpr-mode-double)
+                        (if (= dest-mode hard-reg-class-fpr-mode-double)
+                          (! copy-double-float dest src)
+                          (! copy-double-to-single dest src))
+                        (if (= dest-mode hard-reg-class-fpr-mode-double)
+                          (! copy-single-to-double dest src)
+                          (! copy-single-float dest src))))))))))))))
+  
+(defun x862-unreachable-store (&optional vreg)
+  ;; I don't think that anything needs to be done here,
+  ;; but leave this guy around until we're sure.
+  ;; (X862-VPUSH-REGISTER will always vpush something, even
+  ;; if code to -load- that "something" never gets generated.
+  ;; If I'm right about this, that means that the compile-time
+  ;; stack-discipline problem that this is supposed to deal
+  ;; with can't happen.)
+  (declare (ignore vreg))
+  nil)
+
+;;; bind vars to initforms, as per let*, &aux.
+(defun x862-seq-bind (seg vars initforms)
+  (dolist (var vars)
+    (x862-seq-bind-var seg var (pop initforms))))
+
+(defun x862-target-is-imm-subtag (subtag)
+  (when subtag
+    (target-arch-case
+     (:x8632
+      (let* ((masked (logand subtag x8632::fulltagmask)))
+	(declare (fixnum masked))
+	(= masked x8632::fulltag-immheader)))
+     (:x8664
+      (let* ((masked (logand subtag x8664::fulltagmask)))
+        (declare (fixnum masked))
+        (or (= masked x8664::fulltag-immheader-0)
+            (= masked x8664::fulltag-immheader-1)
+            (= masked x8664::fulltag-immheader-2)))))))
+
+(defun x862-target-is-node-subtag (subtag)
+  (when subtag
+    (target-arch-case
+     (:x8632
+      (let* ((masked (logand subtag x8632::fulltagmask)))
+	(declare (fixnum masked))
+	(= masked x8632::fulltag-nodeheader)))
+     (:x8664
+      (let* ((masked (logand subtag x8664::fulltagmask)))
+        (declare (fixnum masked))
+        (or (= masked x8664::fulltag-nodeheader-0)
+            (= masked x8664::fulltag-nodeheader-1)))))))
+
+(defun x862-dynamic-extent-form (seg curstack val &aux (form val))
+  (when (acode-p val)
+    ;; this will do source note processing even if don't emit anything here,
+    ;; which is a bit wasteful but not incorrect.
+    (with-note (form seg)
+      (with-x86-local-vinsn-macros (seg)
+        (let* ((op (acode-operator form)))
+          (cond ((eq op (%nx1-operator list))
+                 (let* ((*x862-vstack* *x862-vstack*)
+                        (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+                   (x862-set-nargs seg (x862-formlist seg (%cadr form) nil))
+                   (x862-open-undo $undostkblk curstack)
+                   (! stack-cons-list))
+                 (setq val *x862-arg-z*))
+                ((eq op (%nx1-operator list*))
+                 (let* ((arglist (%cadr form)))
+                   (let* ((*x862-vstack* *x862-vstack*)
+                          (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+                     (x862-formlist seg (car arglist) (cadr arglist)))
+                   (when (car arglist)
+                     (x862-set-nargs seg (length (%car arglist)))
+                     (! stack-cons-list*)
+                     (x862-open-undo $undostkblk curstack))
+                   (setq val *x862-arg-z*)))
+                ((eq op (%nx1-operator multiple-value-list))
+                 (x862-multiple-value-body seg (%cadr form))
+                 (x862-open-undo $undostkblk curstack)
+                 (! stack-cons-list)
+                 (setq val *x862-arg-z*))
+                ((eq op (%nx1-operator cons))
+                 (let* ((y ($ *x862-arg-y*))
+                        (z ($ *x862-arg-z*))
+                        (result ($ *x862-arg-z*)))
+                   (x862-two-targeted-reg-forms seg (%cadr val) y (%caddr val) z)
+                   (x862-open-undo $undostkblk )
+                   (! make-tsp-cons result y z)
+                   (setq val result)))
+                ((eq op (%nx1-operator %consmacptr%))
+                 (with-imm-target () (address :address)
+                   (x862-one-targeted-reg-form seg form address)
+                   (with-node-target () node
+                     (! macptr->stack node address)
+                     (x862-open-undo $undo-x86-c-frame)
+                     (setq val node))))
+                ((eq op (%nx1-operator %new-ptr))
+                 (let* ((clear-form (caddr form))
+                        (cval (nx2-constant-form-value clear-form)))
+                   (if cval
+                     (progn 
+                       (x862-one-targeted-reg-form seg (%cadr form) ($ *x862-arg-z*))
+                       (if (nx-null cval)
+                         (! make-stack-block)
+                         (! make-stack-block0)))
+                     (with-crf-target () crf
+                       (let ((stack-block-0-label (backend-get-next-label))
+                             (done-label (backend-get-next-label))
+                             (rval ($ *x862-arg-z*))
+                             (rclear ($ *x862-arg-y*)))
+                         (x862-two-targeted-reg-forms seg (%cadr form) rval clear-form rclear)
+                         (! compare-to-nil crf rclear)
+                         (! cbranch-false (aref *backend-labels* stack-block-0-label) crf x86::x86-e-bits)
+                         (! make-stack-block)
+                         (-> done-label)
+                         (@ stack-block-0-label)
+                         (! make-stack-block0)
+                         (@ done-label)))))
+                 (x862-open-undo $undo-x86-c-frame)
+                 (setq val ($ *x862-arg-z*)))
+                ((eq op (%nx1-operator make-list))
+                 (x862-two-targeted-reg-forms seg (%cadr form) ($ *x862-arg-y*) (%caddr form) ($ *x862-arg-z*))
+                 (x862-open-undo $undostkblk curstack)
+                 (! make-stack-list)
+                 (setq val *x862-arg-z*))       
+                ((eq op (%nx1-operator vector))
+                 (let* ((*x862-vstack* *x862-vstack*)
+                        (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+                   (x862-set-nargs seg (x862-formlist seg (%cadr form) nil))
+                   (! make-stack-vector))
+                 (x862-open-undo $undostkblk)
+                 (setq val *x862-arg-z*))
+                ((eq op (%nx1-operator %gvector))
+                 (let* ((*x862-vstack* *x862-vstack*)
+                        (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+                        (arglist (%cadr form)))
+                   (x862-set-nargs seg (x862-formlist seg (append (car arglist) (reverse (cadr arglist))) nil))
+                   (! make-stack-gvector))
+                 (x862-open-undo $undostkblk)
+                 (setq val *x862-arg-z*)) 
+                ((eq op (%nx1-operator closed-function)) 
+                 (setq val (x862-make-closure seg (cadr form) t))) ; can't error
+                ((eq op (%nx1-operator %make-uvector))
+                 (destructuring-bind (element-count subtag &optional (init 0 init-p)) (%cdr form)
+                   (let* ((fix-subtag (acode-fixnum-form-p subtag))
+                          (is-node (x862-target-is-node-subtag fix-subtag))
+                          (is-imm  (x862-target-is-imm-subtag fix-subtag)))
+                     (when (or is-node is-imm)
+                       (if init-p
+                         (progn
+                           (x862-three-targeted-reg-forms seg element-count
+                                                          (target-arch-case
+                                                           (:x8632
+                                                            ($ x8632::temp1))
+                                                           (:x8664
+                                                            ($ x8664::arg_x)))
+                                                          subtag ($ *x862-arg-y*)
+                                                          init ($ *x862-arg-z*))
+                           (! stack-misc-alloc-init))
+                         (progn
+                           (x862-two-targeted-reg-forms seg element-count ($ *x862-arg-y*)  subtag ($ *x862-arg-z*))
+                           (! stack-misc-alloc)))
+                       (if is-node
+                         (x862-open-undo $undostkblk)
+                         (x862-open-undo $undo-x86-c-frame))
+                       (setq val ($ *x862-arg-z*))))))))))
+    val))
+
+(defun x862-addrspec-to-reg (seg addrspec reg)
+  (if (memory-spec-p addrspec)
+    (x862-stack-to-register seg addrspec reg)
+    (x862-copy-register seg reg addrspec)))
+  
+(defun x862-seq-bind-var (seg var val)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((sym (var-name var))
+           (bits (nx-var-bits var))
+           (closed-p (and (%ilogbitp $vbitclosed bits)
+                          (%ilogbitp $vbitsetq bits)))
+           (curstack (x862-encode-stack))
+           (make-vcell (and closed-p (eq bits (var-bits var))))
+           (closed-downward (and closed-p (%ilogbitp $vbitcloseddownward bits))))
+      (unless (fixnump val)
+        (setq val (nx-untyped-form val))
+        (when (and (%ilogbitp $vbitdynamicextent bits) (acode-p val))
+          (setq val (x862-dynamic-extent-form seg curstack val))))
+      (if (%ilogbitp $vbitspecial bits)
+        (progn
+          (x862-dbind seg val sym)
+          (x862-set-var-ea seg var (x862-vloc-ea (- *x862-vstack* *x862-target-node-size*))))
+        (let ((puntval nil))
+          (flet ((x862-puntable-binding-p (var initform)
+                   ;; The value returned is acode.
+                   (let* ((bits (nx-var-bits var)))
+                     (if (%ilogbitp $vbitpuntable bits)
+                       initform))))
+            (declare (inline x862-puntable-binding-p))
+            (if (and (not (x862-load-ea-p val))
+                     (setq puntval (x862-puntable-binding-p var val)))
+              (progn
+                (nx-set-var-bits var (%ilogior (%ilsl $vbitpunted 1) bits))
+                (let* ((vtype (var-inittype var)))
+                  (when (and vtype (not (eq t vtype)))
+                    (setq puntval (make-acode (%nx1-operator typed-form)
+                                              vtype
+                                              puntval
+                                              nil))))
+                (nx2-replace-var-refs var puntval)
+                (x862-set-var-ea seg var puntval))
+              (progn
+                (let* ((vloc *x862-vstack*)
+                       (reg (let* ((r (nx2-assign-register-var var)))
+                              (if r ($ r)))))
+                  (if (x862-load-ea-p val)
+                    (if reg
+                      (x862-addrspec-to-reg seg val reg)
+                      (if (memory-spec-p val)
+                        (with-node-temps () (temp)
+                          (x862-addrspec-to-reg seg val temp)
+                          (x862-vpush-register seg temp :node var bits))
+                        (x862-vpush-register seg val :node var bits)))
+                    (if reg
+                      (x862-one-targeted-reg-form seg val reg)
+                      (let* ((pushform (x862-acode-operator-supports-push val)))
+                        (if pushform
+                          (progn
+                            (x862-form seg :push nil pushform)
+                            (x862-new-vstack-lcell :node *x862-target-lcell-size* bits var)
+                            (x862-adjust-vstack *x862-target-node-size*))
+                          (x862-vpush-register seg (x862-one-untargeted-reg-form seg val *x862-arg-z*) :node var bits)))))
+                  (x862-set-var-ea seg var (or reg (x862-vloc-ea vloc closed-p)))
+                  (if reg
+                    (x862-note-var-cell var reg)
+                    (x862-note-top-cell var))
+                  (when make-vcell
+                    (with-node-target (*x862-allocptr*) closed
+                      (with-node-target (*x862-allocptr* closed) vcell
+                        (x862-stack-to-register seg vloc closed)
+                        (if closed-downward
+                          (progn
+                            (! make-tsp-vcell vcell closed)
+                            (x862-open-undo $undostkblk))
+                          (progn
+                            (! setup-vcell-allocation)
+                            (! %allocate-uvector vcell)
+                            (! %init-vcell vcell closed)))
+                        (x862-register-to-stack seg vcell vloc)))))))))))))
+
+
+
+;;; Never make a vcell if this is an inherited var.
+;;; If the var's inherited, its bits won't be a fixnum (and will
+;;; therefore be different from what NX-VAR-BITS returns.)
+(defun x862-bind-var (seg var vloc &optional lcell &aux 
+                          (bits (nx-var-bits var)) 
+                          (closed-p (and (%ilogbitp $vbitclosed bits) (%ilogbitp $vbitsetq bits)))
+                          (closed-downward (if closed-p (%ilogbitp $vbitcloseddownward bits)))
+                          (make-vcell (and closed-p (eq bits (var-bits var))))
+                          (addr (x862-vloc-ea vloc)))
+  (with-x86-local-vinsn-macros (seg)
+    (if (%ilogbitp $vbitspecial bits)
+      (progn
+        (x862-dbind seg addr (var-name var))
+        (x862-set-var-ea seg var (x862-vloc-ea (- *x862-vstack* *x862-target-node-size*)))
+        t)
+      (progn
+        (when (%ilogbitp $vbitpunted bits)
+          (compiler-bug "bind-var: var ~s was punted" var))
+        (when make-vcell
+          (with-node-target (*x862-allocptr*) closed
+            (with-node-target (*x862-allocptr* closed) vcell
+              (x862-stack-to-register seg vloc closed)
+              (if closed-downward
+                (progn
+                  (! make-tsp-vcell vcell closed)
+                  (x862-open-undo $undostkblk))
+                (progn
+                  (! setup-vcell-allocation)
+                  (! %allocate-uvector vcell)
+                  (! %init-vcell vcell closed)))
+              (x862-register-to-stack seg vcell vloc))))
+        (when lcell
+          (setf (lcell-kind lcell) :node
+                (lcell-attributes lcell) bits
+                (lcell-info lcell) var)
+          (x862-note-var-cell var lcell))          
+        (x862-set-var-ea seg var (x862-vloc-ea vloc closed-p))        
+        closed-downward))))
+
+(defun x862-set-var-ea (seg var ea)
+  (setf (var-ea var) ea)
+  (when (and *x862-record-symbols* (or (typep ea 'lreg) (typep ea 'fixnum)))
+    (let* ((start (x862-emit-note seg :begin-variable-scope)))
+      (push (list var (var-name var) start (close-vinsn-note start))
+            *x862-recorded-symbols*)))
+  ea)
+
+(defun x862-close-var (seg var)
+  (let ((bits (nx-var-bits var)))
+    (when (and *x862-record-symbols*
+               (or (logbitp $vbitspecial bits)
+                   (not (logbitp $vbitpunted bits))))
+      (let ((endnote (%car (%cdddr (assq var *x862-recorded-symbols*)))))
+        (unless endnote (compiler-bug "x862-close-var for ~s" (var-name var)))
+        (setf (vinsn-note-class endnote) :end-variable-scope)
+        (append-dll-node (vinsn-note-label endnote) seg)))))
+
+(defun x862-load-ea-p (ea)
+  (or (typep ea 'fixnum)
+      (typep ea 'lreg)
+      (typep ea 'lcell)))
+
+(defun x862-dbind (seg value sym)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((ea-p (x862-load-ea-p value))
+           (nil-p (unless ea-p (nx-null (setq value (nx-untyped-form value)))))
+           (self-p (unless ea-p (and (or
+                                      (eq (acode-operator value) (%nx1-operator bound-special-ref))
+                                      (eq (acode-operator value) (%nx1-operator special-ref)))
+                                     (eq (cadr value) sym)))))
+      (cond ((eq sym '*interrupt-level*)
+             (let* ((fixval (acode-fixnum-form-p value)))
+               (cond ((eql fixval 0)
+                      (if *x862-open-code-inline*
+                        (! bind-interrupt-level-0-inline)
+                        (! bind-interrupt-level-0)))
+                     ((eql fixval -1)
+                      (if *x862-open-code-inline*
+                        (! bind-interrupt-level-m1-inline)
+                        (! bind-interrupt-level-m1)))
+                     (t
+                      (if ea-p 
+                        (x862-store-ea seg value *x862-arg-z*)
+                        (x862-one-targeted-reg-form seg value ($ *x862-arg-z*)))
+                      (! bind-interrupt-level))))
+             (x862-open-undo $undointerruptlevel))
+            (t
+             (if (or nil-p self-p)
+               (progn
+                 (x862-store-immediate seg (x862-symbol-value-cell sym) *x862-arg-z*)
+                 (if nil-p
+                   (! bind-nil)
+                   (if (or *x862-reckless* (eq (acode-operator value) (%nx1-operator special-ref)))
+                     (! bind-self)
+                     (! bind-self-boundp-check))))
+               (progn
+                 (if ea-p 
+                   (x862-store-ea seg value *x862-arg-z*)
+                   (x862-one-targeted-reg-form seg value ($ *x862-arg-z*)))
+                 (x862-store-immediate seg (x862-symbol-value-cell sym) ($ *x862-arg-y*))
+                 (! bind)))
+             (x862-open-undo $undospecial)))
+      (x862-new-vstack-lcell :special-value *x862-target-lcell-size* 0 sym)
+      (x862-new-vstack-lcell :special *x862-target-lcell-size* (ash 1 $vbitspecial) sym)
+      (x862-new-vstack-lcell :special-link *x862-target-lcell-size* 0 sym)
+      (x862-adjust-vstack (* 3 *x862-target-node-size*)))))
+
+;;; Store the contents of EA - which denotes either a vframe location
+;;; or a hard register - in reg.
+
+(defun x862-store-ea (seg ea reg)
+  (if (typep ea 'fixnum)
+    (if (memory-spec-p ea)
+      (x862-stack-to-register seg ea reg)
+      (x862-copy-register seg reg ea))
+    (if (typep ea 'lreg)
+      (x862-copy-register seg reg ea)
+      (if (typep ea 'lcell)
+        (x862-lcell-to-register seg ea reg)))))
+
+
+      
+
+;;; Callers should really be sure that this is what they want to use.
+(defun x862-absolute-natural (seg vreg xfer value)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (when vreg
+      (x862-lri seg vreg value))
+    (^)))
+
+
+
+(defun x862-store-macptr (seg vreg address-reg)
+  (with-x86-local-vinsn-macros (seg vreg)
+    (when (x862-for-value-p vreg)
+      (if (logbitp vreg *backend-imm-temps*)
+        (<- address-reg)
+        (x862-macptr->heap seg vreg address-reg)))))
+
+(defun x862-store-signed-longword (seg vreg imm-reg)
+  (with-x86-local-vinsn-macros (seg vreg)
+    (when (x862-for-value-p vreg)
+      (if (logbitp vreg *backend-imm-temps*)
+        (<- imm-reg)
+        (x862-box-s32 seg vreg imm-reg)))))
+
+
+
+;; xxx imm regs
+(defun x862-%immediate-set-ptr (seg vreg xfer  ptr offset val)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((intval (acode-absolute-ptr-p val t))
+           (offval (acode-fixnum-form-p offset))
+           (for-value (x862-for-value-p vreg)))
+      (flet ((address-and-node-regs ()
+               (if for-value
+                 (progn
+                   (x862-one-targeted-reg-form seg val ($ *x862-arg-z*))
+                   (progn
+                       (if intval
+                         (x862-lri seg *x862-imm0* intval)
+                         (! deref-macptr *x862-imm0* *x862-arg-z*))
+                       (values *x862-imm0* *x862-arg-z*)))
+                 (values (x862-macptr-arg-to-reg seg val ($ *x862-imm0* :mode :address)) nil))))
+        (unless (typep offval '(signed-byte 32))
+          (setq offval nil))
+        (unless (typep intval '(signed-byte 32))
+          (setq intval nil))
+        (cond (intval
+               (cond (offval
+                      (with-imm-target () (ptr-reg :address)
+                        (let* ((ptr-reg (x862-one-untargeted-reg-form seg
+                                                                      ptr
+                                                                      ptr-reg)))
+			  (target-word-size-case
+			   (32
+			    (! mem-set-c-constant-fullword intval ptr-reg offval))
+			   (64
+			    (! mem-set-c-constant-doubleword intval ptr-reg offval))))))
+                     (t
+		      (with-additional-imm-reg ()
+			(with-imm-target () (ptr-reg :address)
+			  (with-imm-target (ptr-reg) (offsetreg :signed-natural)
+			    (x862-two-targeted-reg-forms seg ptr ptr-reg offset ($ *x862-arg-z*))
+			    (! fixnum->signed-natural offsetreg *x862-arg-z*)
+			    (target-word-size-case
+			     (32 (! mem-set-constant-fullword intval ptr-reg offsetreg))
+			     (64 (! mem-set-constant-doubleword intval ptr-reg offsetreg))))))))
+               (if for-value
+                 (with-imm-target () (val-reg (target-word-size-case (32 :s32) (64 :s64)))
+                   (x862-lri seg val-reg intval)
+                   (<- (set-regspec-mode val-reg (gpr-mode-name-value :address))))))
+              (offval
+               ;; Still simpler than the general case
+               (with-imm-target () (ptr-reg :address)
+                 (x862-push-register seg
+                                     (x862-one-untargeted-reg-form seg ptr ptr-reg)))
+               (multiple-value-bind (address node)
+                   (address-and-node-regs)
+		 (with-additional-imm-reg ()
+		   (with-imm-target (address) (ptr-reg :address)
+		     (x862-pop-register seg ptr-reg)
+		     (target-word-size-case
+		      (32 (! mem-set-c-fullword address ptr-reg offval))
+		      (64 (! mem-set-c-doubleword address ptr-reg offval)))))
+                 (if for-value
+                   (<- node))))
+              (t
+               (with-imm-target () (ptr-reg :address)
+		 (with-additional-imm-reg ()
+		   (with-imm-target (ptr-reg) (offset-reg :address)
+		     (x862-two-targeted-reg-forms seg ptr ptr-reg offset ($ *x862-arg-z*))
+		     (! fixnum->signed-natural offset-reg *x862-arg-z*)
+		     (! fixnum-add2 ptr-reg offset-reg)
+		     (x862-push-register seg ptr-reg))))
+               (multiple-value-bind (address node)
+                   (address-and-node-regs)
+		 (with-additional-imm-reg ()
+		   (with-imm-target (address) (ptr-reg :address)
+		     (x862-pop-register seg ptr-reg)
+		     (target-word-size-case
+		      (32 (! mem-set-c-fullword address ptr-reg 0))
+		      (64 (! mem-set-c-doubleword address ptr-reg 0)))))
+                 (if for-value
+                   (<- node))))))
+      (^))))
+                     
+  
+
+      
+(defun x862-%immediate-store  (seg vreg xfer bits ptr offset val)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if (eql 0 (%ilogand #xf bits))
+      (x862-%immediate-set-ptr seg vreg xfer  ptr offset val)
+      (let* ((size (logand #xf bits))
+             (signed (not (logbitp 5 bits)))
+             (nbits (ash size 3))
+             (intval (acode-integer-constant-p val nbits))
+             (ncbits (if (eql nbits 64) 32 nbits))
+             (signed-intval (or (and intval
+                                     (> intval 0)
+                                     (logbitp (1- ncbits) intval)
+                                     (- intval (ash 1 ncbits)))
+                                intval))
+             (offval (acode-fixnum-form-p offset))
+             (for-value (x862-for-value-p vreg)))
+        (declare (fixnum size))
+        (flet ((val-to-argz-and-imm0 ()
+                 (x862-one-targeted-reg-form seg val ($ *x862-arg-z*))
+                 (if (eq size 8)
+                   (if signed
+                     (! gets64)
+                     (! getu64))
+		   (if (and (eq size 4)
+			    (target-arch-case
+			     (:x8632 t)
+			     (:x8664 nil)))
+		     (if signed
+		       (! gets32)
+		       (! getu32))
+		     (! fixnum->signed-natural *x862-imm0* *x862-arg-z*)))))
+
+          (and offval (%i> (integer-length offval) 31) (setq offval nil))
+          (and intval (%i> (integer-length intval) 31) (setq intval nil))
+          (and intval
+               (case size
+                 (2
+                  (if (>= intval 32768) (setq intval (- intval 65536))))
+                 (1
+                  (if (>= intval 128) (setq intval (- intval 256))))))
+	  (cond (intval
+		 (cond (offval
+			(with-imm-target () (ptr-reg :address)
+			  (let* ((ptr-reg (x862-one-untargeted-reg-form seg
+									ptr
+									ptr-reg)))
+			    (case size
+			      (8 (! mem-set-c-constant-doubleword signed-intval ptr-reg offval))
+			      (4 (! mem-set-c-constant-fullword signed-intval ptr-reg offval))
+			      (2 (! mem-set-c-constant-halfword signed-intval ptr-reg offval))
+			      (1 (! mem-set-c-constant-byte signed-intval ptr-reg offval))))))
+		       (t
+			(with-imm-target () (ptr-reg :address)
+			  (with-additional-imm-reg (*x862-arg-z*)
+			    (with-imm-target (ptr-reg) (offsetreg :signed-natural)
+			      (x862-two-targeted-reg-forms seg ptr ptr-reg offset ($ *x862-arg-z*))
+			      (! fixnum->signed-natural offsetreg *x862-arg-z*)
+			      (case size
+				(8 (! mem-set-constant-doubleword intval ptr-reg offsetreg))
+				(4 (! mem-set-constant-fullword intval ptr-reg offsetreg))
+				(2 (! mem-set-constant-halfword intval ptr-reg offsetreg))
+				(1 (! mem-set-constant-byte intval ptr-reg offsetreg))))))))
+		 (if for-value
+		   (ensuring-node-target (target vreg)
+		     (x862-lri seg vreg (ash intval *x862-target-fixnum-shift*)))))
+		(offval
+		 ;; simpler than the general case
+		 (with-imm-target () (ptr-reg :address)
+		   (x862-push-register seg
+				       (x862-one-untargeted-reg-form seg ptr ptr-reg)))
+		 (val-to-argz-and-imm0)
+		 (target-arch-case
+		  (:x8632
+		   (with-additional-imm-reg (*x862-arg-z*)
+		     (with-imm-temps (x8632::imm0) (ptr-reg)
+		       (x862-pop-register seg ptr-reg)
+		       (case size
+			 (8 (! mem-set-c-doubleword *x862-imm0* ptr-reg offval))
+			 (4 (! mem-set-c-fullword *x862-imm0* ptr-reg offval))
+			 (2 (! mem-set-c-halfword *x862-imm0* ptr-reg offval))
+			 (1 (! mem-set-c-byte *x862-imm0* ptr-reg offval))))))
+		  (:x8664
+		   (with-imm-target (x8664::imm0) (ptr-reg :address)
+		     (x862-pop-register seg ptr-reg)
+		     (case size
+		       (8 (! mem-set-c-doubleword *x862-imm0* ptr-reg offval))
+		       (4 (! mem-set-c-fullword *x862-imm0* ptr-reg offval))
+		       (2 (! mem-set-c-halfword *x862-imm0* ptr-reg offval))
+		       (1 (! mem-set-c-byte *x862-imm0* ptr-reg offval))))))
+		 (if for-value
+		   (<- *x862-arg-z*)))
+		(t
+		 (with-imm-target () (ptr-reg :address)
+		   (with-additional-imm-reg (*x862-arg-z* ptr-reg)
+		     (with-imm-target (ptr-reg) (offset-reg :address)
+		       (x862-two-targeted-reg-forms seg ptr ptr-reg offset ($ *x862-arg-z*))
+		       (! fixnum->signed-natural offset-reg *x862-arg-z*)
+		       (! fixnum-add2 ptr-reg offset-reg)
+		       (x862-push-register seg ptr-reg))))
+		 (val-to-argz-and-imm0)
+		 (target-arch-case
+		  (:x8632
+		     ;; Ensure imm0 is marked as in use so that some
+		     ;; vinsn doesn't decide to use it a temp.
+		     (with-additional-imm-reg ()
+		       (with-imm-temps (x8632::imm0) (ptr-reg)
+			 (x862-pop-register seg ptr-reg)
+			 (case size
+			   (8 (! mem-set-c-doubleword *x862-imm0* ptr-reg 0))
+			   (4 (! mem-set-c-fullword *x862-imm0* ptr-reg 0))
+			   (2 (! mem-set-c-halfword *x862-imm0* ptr-reg 0))
+			   (1 (! mem-set-c-byte *x862-imm0* ptr-reg 0))))))
+		  (:x8664
+		   (with-imm-target (x8664::imm0) (ptr-reg :address)
+		     (x862-pop-register seg ptr-reg)
+		     (case size
+		       (8 (! mem-set-c-doubleword *x862-imm0* ptr-reg 0))
+		       (4 (! mem-set-c-fullword *x862-imm0* ptr-reg 0))
+		       (2 (! mem-set-c-halfword *x862-imm0* ptr-reg 0))
+		       (1 (! mem-set-c-byte *x862-imm0* ptr-reg 0))))))
+		 (if for-value
+		   (< *x862-arg-z*))))
+
+          (^))))))
+
+
+
+
+
+(defun x862-encoding-undo-count (encoding)
+ (svref encoding 0))
+
+(defun x862-encoding-cstack-depth (encoding)    ; hardly ever interesting
+  (svref encoding 1))
+
+(defun x862-encoding-vstack-depth (encoding)
+  (svref encoding 2))
+
+(defun x862-encoding-vstack-top (encoding)
+  (svref encoding 3))
+
+(defun x862-encode-stack ()
+  (vector *x862-undo-count* *x862-cstack* *x862-vstack* *x862-top-vstack-lcell*))
+
+(defun x862-decode-stack (encoding)
+  (values (x862-encoding-undo-count encoding)
+          (x862-encoding-cstack-depth encoding)
+          (x862-encoding-vstack-depth encoding)
+          (x862-encoding-vstack-top encoding)))
+
+(defun x862-equal-encodings-p (a b)
+  (dotimes (i 3 t)
+    (unless (eq (svref a i) (svref b i)) (return))))
+
+(defun x862-open-undo (&optional (reason $undocatch) (curstack (x862-encode-stack)))
+  (set-fill-pointer 
+   *x862-undo-stack*
+   (set-fill-pointer *x862-undo-because* *x862-undo-count*))
+  (vector-push-extend curstack *x862-undo-stack*)
+  (vector-push-extend reason *x862-undo-because*)
+  (setq *x862-undo-count* (%i+ *x862-undo-count* 1)))
+
+(defun x862-close-undo (&aux
+                        (new-count (%i- *x862-undo-count* 1))
+                        (i (aref *x862-undo-stack* new-count)))
+  (multiple-value-setq (*x862-undo-count* *x862-cstack* *x862-vstack* *x862-top-vstack-lcell*)
+    (x862-decode-stack i))
+  (set-fill-pointer 
+   *x862-undo-stack*
+   (set-fill-pointer *x862-undo-because* new-count)))
+
+
+
+
+
+;;; "Trivial" means can be evaluated without allocating or modifying registers.
+;;; Interim definition, which will probably stay here forever.
+(defun x862-trivial-p (form &optional reg &aux untyped-form op bits)
+  (setq untyped-form (nx-untyped-form form))
+  (and
+   (consp untyped-form)
+   (not (eq (setq op (%car untyped-form)) (%nx1-operator call)))
+   (or
+    (nx-null untyped-form)
+    (nx-t untyped-form)
+    (eq op (%nx1-operator simple-function))
+    (eq op (%nx1-operator fixnum))
+    (eq op (%nx1-operator immediate))
+    #+nil
+    (eq op (%nx1-operator bound-special-ref))
+    (and (or (eq op (%nx1-operator inherited-arg)) 
+             (eq op (%nx1-operator lexical-reference)))
+         (or (%ilogbitp $vbitpunted (setq bits (nx-var-bits (cadr untyped-form))))
+             (neq (%ilogior (%ilsl $vbitclosed 1) (%ilsl $vbitsetq 1))
+                  (%ilogand (%ilogior (%ilsl $vbitclosed 1) (%ilsl $vbitsetq 1)) bits)))))
+   (or (and reg (neq (hard-regspec-value reg) *x862-codecoverage-reg*))
+       (not (code-note-p (acode-note form))))))
+
+
+
+(defun x862-ref-symbol-value (seg vreg xfer sym check-boundp)
+  (declare (ignorable check-boundp))
+  (setq check-boundp (not *x862-reckless*))
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (when (or check-boundp vreg)
+      (unless vreg (setq vreg ($ *x862-arg-z*)))
+      (if (eq sym '*interrupt-level*)
+          (ensuring-node-target (target vreg)
+            (! ref-interrupt-level target))
+          (if *x862-open-code-inline*
+            (ensuring-node-target (target vreg)
+              (with-node-target (target) src
+                (let* ((vcell (x862-symbol-value-cell sym))
+                       (reg (x862-register-constant-p vcell)))
+                  (if reg
+                    (setq src reg)
+                    (x862-store-immediate seg vcell src)))
+                (if check-boundp
+                  (! ref-symbol-value-inline target src)
+                  (! %ref-symbol-value-inline target src))))
+            (let* ((src ($ *x862-arg-z*))
+                   (dest ($ *x862-arg-z*)))
+              (x862-store-immediate seg (x862-symbol-value-cell sym) src)
+              (if check-boundp
+                (! ref-symbol-value dest src)
+                (! %ref-symbol-value dest src))
+              (<- dest)))))
+    (^)))
+
+;;; Should be less eager to box result
+(defun x862-extract-charcode (seg vreg xfer char safe)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((src (x862-one-untargeted-reg-form seg char *x862-arg-z*)))
+      (when safe
+        (! trap-unless-character src))
+      (if vreg
+        (ensuring-node-target (target vreg)
+          (! character->fixnum target src)))
+      (^))))
+  
+
+(defun x862-reference-list (seg vreg xfer listform safe refcdr)
+  (if (x862-form-typep listform 'list)
+    (setq safe nil))                    ; May also have been passed as NIL.
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((src (x862-one-untargeted-reg-form seg listform *x862-arg-z*)))
+      (when safe
+        (! trap-unless-list src))
+      (if vreg
+        (if (eq vreg :push)
+          (if refcdr
+            (! %vpush-cdr src)
+            (! %vpush-car src))
+          (ensuring-node-target (target vreg)
+            (if refcdr
+              (! %cdr target src)
+              (! %car target src)))))
+      (^))))
+
+
+
+(defun x862-misc-byte-count (subtag element-count)
+  (funcall (arch::target-array-data-size-function
+            (backend-target-arch *target-backend*))
+           subtag element-count))
+
+
+;;; The naive approach is to vpush all of the initforms, allocate the
+;;; miscobj, then sit in a loop vpopping the values into the vector.
+;;; That's "naive" when most of the initforms in question are
+;;; "side-effect-free" (constant references or references to un-SETQed
+;;; lexicals), in which case it makes more sense to just store the
+;;; things into the vector cells, vpushing/ vpopping only those things
+;;; that aren't side-effect-free.  (It's necessary to evaluate any
+;;; non-trivial forms before allocating the miscobj, since that
+;;; ensures that the initforms are older (in the EGC sense) than it
+;;; is.)  The break-even point space-wise is when there are around 3
+;;; non-trivial initforms to worry about.
+
+
+(defun x862-allocate-initialized-gvector (seg vreg xfer subtag initforms)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if (null vreg)
+      (dolist (f initforms) (x862-form seg nil nil f))
+      (let* ((*x862-vstack* *x862-vstack*)
+             (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+             (arch (backend-target-arch *target-backend*))
+             (n (length initforms))
+             (nntriv (let* ((count 0)) 
+                       (declare (fixnum count))
+                       (dolist (f initforms count) 
+                         (unless (x86-side-effect-free-form-p f)
+                           (incf count)))))
+             (header (arch::make-vheader n subtag)))
+        (declare (fixnum n nntriv))
+        (cond ((or *x862-open-code-inline* (> nntriv 3))
+               (x862-formlist seg initforms nil)
+	       (target-arch-case
+		(:x8632
+		 (x862-lri seg *x862-imm0* header)
+		 (! setup-uvector-allocation *x862-imm0*)
+		 (x862-lri seg *x862-imm0* (- (ash (logandc2 (+ n 2) 1) (arch::target-word-shift arch)) x8632::fulltag-misc)))
+		(:x8664
+		 (x862-lri seg *x862-imm0* header)
+		 (x862-lri seg x8664::imm1 (- (ash (logandc2 (+ n 2) 1) (arch::target-word-shift arch)) x8664::fulltag-misc))))
+               (! %allocate-uvector vreg)
+               (unless (eql n 0)
+                 (! %init-gvector vreg  (ash n (arch::target-word-shift arch)))))
+              (t
+               (let* ((pending ())
+                      (vstack *x862-vstack*))
+                 (declare (fixnum vstack))
+                 (dolist (form initforms)
+                   (if (x86-side-effect-free-form-p form)
+                     (push form pending)
+                     (progn
+                       (push nil pending)
+                       (x862-vpush-register seg (x862-one-untargeted-reg-form seg form *x862-arg-z*)))))
+		 (target-arch-case
+		  (:x8632
+		   (x862-lri seg *x862-imm0* header)
+		   (! setup-uvector-allocation *x862-imm0*)
+		   (x862-lri seg *x862-imm0* (- (ash (logandc2 (+ n 2) 1) (arch::target-word-shift arch)) x8632::fulltag-misc)))
+		  (:x8664
+		   (x862-lri seg *x862-imm0* header)
+		   (x862-lri seg x8664::imm1 (- (ash (logandc2 (+ n 2) 1) (arch::target-word-shift arch)) x8664::fulltag-misc))))
+                 (ensuring-node-target (target vreg)
+                   (! %allocate-uvector target)
+                   (with-node-temps (target) (nodetemp)
+                     (do* ((forms pending (cdr forms))
+                           (index (1- n) (1- index))
+                           (pushed-cell (+ vstack (the fixnum (ash nntriv (arch::target-word-shift arch))))))
+                          ((null forms))
+                       (declare (list forms) (fixnum pushed-cell))
+                       (let* ((form (car forms))
+                              (reg nodetemp))
+                         (if form
+                           (setq reg (x862-one-untargeted-reg-form seg form nodetemp))
+                           (progn
+                             (decf pushed-cell *x862-target-node-size*)
+                             (x862-stack-to-register seg (x862-vloc-ea pushed-cell) nodetemp)))
+                         (! misc-set-c-node reg target index)))))
+                 (! vstack-discard nntriv))
+               ))))
+     (^)))
+
+;;; Heap-allocated constants -might- need memoization: they might be newly-created,
+;;; as in the case of synthesized toplevel functions in .pfsl files.
+(defun x862-acode-needs-memoization (valform)
+  (if (x862-form-typep valform 'fixnum)
+    nil
+    (let* ((val (acode-unwrapped-form-value valform)))
+      (if (or (nx-t val)
+              (nx-null val)
+              (and (acode-p val)
+                   (let* ((op (acode-operator val)))
+                     (or (eq op (%nx1-operator fixnum)) #|(eq op (%nx1-operator immediate))|#))))
+        nil
+        t))))
+
+(defun x862-modify-cons (seg vreg xfer ptrform valform safe setcdr returnptr)
+  (if (x862-form-typep ptrform 'cons)
+    (setq safe nil))                    ; May also have been passed as NIL.
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (multiple-value-bind (ptr-vreg val-vreg) (x862-two-targeted-reg-forms seg ptrform ($ *x862-arg-y*) valform ($ *x862-arg-z*))
+      (when safe
+        (! trap-unless-cons ptr-vreg))
+      (if setcdr
+        (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPrplacd) ptr-vreg val-vreg)
+        (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPrplaca) ptr-vreg val-vreg))
+      (if returnptr
+        (<- ptr-vreg)
+        (<- val-vreg))
+      (^))))
+
+
+
+(defun x862-find-nilret-label ()
+  (dolist (l *x862-nilret-labels*)
+    (destructuring-bind (label vsp csp register-restore-count register-restore-ea &rest agenda) l
+      (and (or (and (eql 0 register-restore-count)
+                    (or (not (eql 0 vsp))
+                        (eq vsp *x862-vstack*)))
+                (and 
+                 (eq register-restore-count *x862-register-restore-count*)
+                 (eq vsp *x862-vstack*)))
+           (or agenda (eq csp *x862-cstack*))
+           (eq register-restore-ea *x862-register-restore-ea*)
+           (eq (%ilsr 1 (length agenda)) *x862-undo-count*)
+           (dotimes (i (the fixnum *x862-undo-count*) t) 
+             (unless (and (eq (pop agenda) (aref *x862-undo-because* i))
+                          (eq (pop agenda) (aref *x862-undo-stack* i)))
+               (return)))
+           (return label)))))
+
+(defun x862-record-nilret-label ()
+  (let* ((lab (backend-get-next-label))
+         (info nil))
+    (dotimes (i (the fixnum *x862-undo-count*))
+      (push (aref *x862-undo-because* i) info)
+      (push (aref *x862-undo-stack* i) info))
+    (push (cons
+                 lab 
+                 (cons
+                  *x862-vstack*
+                  (cons 
+                   *x862-cstack*
+                   (cons
+                    *x862-register-restore-count*
+                    (cons
+                     *x862-register-restore-ea*
+                     (nreverse info))))))
+          *x862-nilret-labels*)
+    lab))
+
+;;; If we know that the form is something that sets a CR bit,
+;;; allocate a CR field and evaluate the form in such a way
+;;; as to set that bit.
+;;; If it's a compile-time constant, branch accordingly and
+;;; let the dead code die.
+;;; Otherwise, evaluate it to some handy register and compare
+;;; that register to RNIL.
+;;; "XFER" is a compound destination.
+(defun x862-conditional-form (seg xfer form)
+  (let* ((uwf (acode-unwrapped-form-value form)))
+    (if (x86-constant-form-p uwf)
+      (with-note (form seg)
+        (if (nx-null uwf)
+          (x862-branch seg (x862-cd-false xfer))
+          (x862-branch seg (x862-cd-true xfer))))
+      (with-crf-target () crf
+        (let* ((ea (x862-lexical-reference-ea form nil)))
+          (if (and ea (memory-spec-p ea))
+            (with-note (form seg)
+              (x862-compare-ea-to-nil seg crf xfer ea x86::x86-e-bits nil))
+            (x862-form seg crf xfer form)))))))
+
+      
+(defun x862-branch (seg xfer &optional cr-bit true-p)
+  (let* ((*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+    (with-x86-local-vinsn-macros (seg)
+      (setq xfer (or xfer 0))
+      (when (logbitp $backend-mvpass-bit xfer) ;(x862-mvpass-p cd)
+        (setq xfer (logand (lognot $backend-mvpass-mask) xfer))
+        (unless *x862-returning-values*
+          (x862-vpush-register seg *x862-arg-z*)
+          (x862-set-nargs seg 1)))
+      (if (neq 0 xfer)
+        (if (eq xfer $backend-return)    ;; xfer : RETURN ==> popj
+          (x862-do-return seg)
+          (if (not (x862-cd-compound-p xfer))
+            (-> xfer)  ;; xfer : label# ==> jmp label#
+            ;; cd is compound : (<true> / <false>)
+            (let* ((truebranch (x862-cd-true xfer))
+                   (falsebranch (x862-cd-false xfer))
+                   (tbranch (if true-p truebranch falsebranch))
+                   (nbranch (if true-p falsebranch truebranch))
+                   (tn0 (neq 0 tbranch))
+                   (tnret (neq $backend-return tbranch))
+                   (nn0 (neq 0 nbranch))
+                   (nnret (neq $backend-return nbranch))
+                   (tlabel (if (and tnret tn0) (aref *backend-labels* tbranch)))
+                   (nlabel (if (and nnret nn0) (aref *backend-labels* nbranch))))
+              (unless cr-bit (setq cr-bit x86::x86-e-bits))
+              (if (and tn0 tnret nn0 nnret)
+                (progn
+                  (! cbranch-true tlabel cr-bit )    ;; (label# /  label#)
+                  (-> nbranch)))
+                (if (and nnret tnret)
+                  (if nn0
+                    (! cbranch-false nlabel cr-bit)
+                    (! cbranch-true tlabel cr-bit))
+                  (let* ((aux-label (backend-get-next-label))
+                         (auxl (aref *backend-labels* aux-label)))
+                    (if tn0
+                      (! cbranch-true auxl cr-bit)
+                      (! cbranch-false auxl cr-bit) )
+                    (x862-do-return seg)
+                    (@ aux-label))))))))))
+
+(defun x862-cd-merge (cd label)
+  (setq cd (or cd 0))
+  (let ((mvpass (logbitp $backend-mvpass-bit cd)))
+    (if (neq 0 (logand (lognot $backend-mvpass-mask) cd))
+      (if (x862-cd-compound-p cd)
+        (x862-make-compound-cd
+         (x862-cd-merge (x862-cd-true cd) label)
+         (x862-cd-merge (x862-cd-false cd) label)
+         mvpass)
+        cd)
+      (if mvpass 
+        (logior $backend-mvpass-mask label)
+        label))))
+
+(defun x862-mvpass-p (xfer)
+  (if xfer (or (logbitp $backend-mvpass-bit xfer) (eq xfer $backend-mvpass))))
+
+(defun x862-cd-compound-p (xfer)
+  (if xfer (logbitp $backend-compound-branch-target-bit xfer)))
+
+(defun x862-cd-true (xfer)
+ (if (x862-cd-compound-p xfer)
+   (ldb  $backend-compound-branch-true-byte xfer)
+  xfer))
+
+(defun x862-cd-false (xfer)
+ (if (x862-cd-compound-p xfer)
+   (ldb  $backend-compound-branch-false-byte xfer)
+   xfer))
+
+(defun x862-make-compound-cd (tpart npart &optional mvpass-p)
+  (dpb (or npart 0) $backend-compound-branch-false-byte
+       (dpb (or tpart 0) $backend-compound-branch-true-byte
+            (logior (if mvpass-p $backend-mvpass-mask 0) $backend-compound-branch-target-mask))))
+
+(defun x862-invert-cd (cd)
+  (if (x862-cd-compound-p cd)
+    (x862-make-compound-cd (x862-cd-false cd) (x862-cd-true cd) (logbitp $backend-mvpass-bit cd))
+    cd))
+
+
+
+;;; execute body, cleanup afterwards (if need to)
+(defun x862-undo-body (seg vreg xfer body old-stack)
+  (let* ((current-stack (x862-encode-stack))
+         (numundo (%i- *x862-undo-count* (x862-encoding-undo-count old-stack))))
+    (declare (fixnum numundo))
+    (with-x86-local-vinsn-macros (seg vreg xfer)
+      (if (eq current-stack old-stack)
+        (x862-form seg vreg xfer body)
+        (if (eq xfer $backend-return)
+          (progn
+            (x862-form seg vreg xfer body)
+            (dotimes (i numundo) (x862-close-undo)))
+          (if (x862-mvpass-p xfer)
+            (progn
+              (x862-mvpass seg body) ; presumed to be ok
+              (let* ((*x862-returning-values* :pass))
+                (x862-nlexit seg xfer numundo)
+                (^))
+              (dotimes (i numundo) (x862-close-undo)))
+            (progn
+              ;; There are some cases where storing thru *x862-arg-z*
+              ;; can be avoided (stores to vlocs, specials, etc.) and
+              ;; some other case where it can't ($test, $vpush.)  The
+              ;; case of a null vd can certainly avoid it; the check
+              ;; of numundo is to keep $acc boxed in case of nthrow.
+              (x862-form  seg (if (or vreg (not (%izerop numundo))) *x862-arg-z*) nil body)
+              (x862-unwind-set seg xfer old-stack)
+              (when vreg (<- *x862-arg-z*))
+              (^))))))))
+
+
+(defun x862-unwind-set (seg xfer encoding)
+  (multiple-value-bind (target-catch target-cstack target-vstack target-vstack-lcell)
+                       (x862-decode-stack encoding)
+    (x862-unwind-stack seg xfer target-catch target-cstack target-vstack)
+    (setq *x862-undo-count* target-catch 
+          *x862-cstack* target-cstack
+          *x862-vstack* target-vstack
+          *x862-top-vstack-lcell* target-vstack-lcell)))
+
+(defun x862-unwind-stack (seg xfer target-catch target-cstack target-vstack)
+  (let* ((current-catch *x862-undo-count*)
+         (current-cstack *x862-cstack*)
+         (current-vstack *x862-vstack*)
+         (diff (%i- current-catch target-catch))
+         target
+         (exit-vstack current-vstack))
+    (declare (ignorable target))
+    (when (neq 0 diff)
+      (setq exit-vstack (x862-nlexit seg xfer diff))
+      (multiple-value-setq (target current-cstack current-vstack)
+                           (x862-decode-stack (aref *x862-undo-stack* target-catch))))
+    (if (%i< 0 (setq diff (%i- current-cstack target-cstack)))
+      (compiler-bug "Bug: adjust foreign stack ?"))
+    (if (%i< 0 (setq diff (%i- current-vstack target-vstack)))
+      (with-x86-local-vinsn-macros (seg)
+        (! vstack-discard (ash diff (- *x862-target-fixnum-shift*)))))
+    exit-vstack))
+
+;;; We can sometimes combine unwinding the catch stack with returning
+;;; from the function by jumping to a subprim that knows how to do
+;;; this.  If catch frames were distinguished from unwind-protect
+;;; frames, we might be able to do this even when saved registers are
+;;; involved (but the subprims restore them from the last catch
+;;; frame.)  *** there are currently only subprims to handle the "1
+;;; frame" case; add more ***
+(defun x862-do-return (seg)
+  (let* ((*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+         (mask *x862-register-restore-count*)
+         (ea *x862-register-restore-ea*)
+         (label nil)
+         (vstack nil)
+         (foldp (not *x862-open-code-inline*)))
+    (if (%izerop mask) (setq mask nil))
+    (with-x86-local-vinsn-macros (seg)
+      (progn
+        (setq vstack (x862-set-vstack (x862-unwind-stack seg $backend-return 0 0 #x7fffff)))
+        (if *x862-returning-values*
+          (cond ((and mask foldp (setq label (%cdr (assq vstack *x862-valret-labels*))))
+                 (-> label))
+                (t
+                 (@ (setq label (backend-get-next-label)))
+                 (push (cons vstack label) *x862-valret-labels*)
+                 (x862-restore-nvrs seg ea mask nil)
+                 (! nvalret)))
+          (if (null mask)
+            (! popj)
+            (if (and foldp (setq label (assq *x862-vstack* *x862-popreg-labels*)))
+              (-> (cdr label))
+              (let* ((new-label (backend-get-next-label)))
+                (@ new-label)
+                (push (cons *x862-vstack* new-label) *x862-popreg-labels*)
+                (x862-set-vstack (x862-restore-nvrs seg ea mask))
+                (! popj)))))))
+    nil))
+
+
+(defun x862-mvcall (seg vreg xfer fn arglist &optional recursive-p)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (if (and (eq xfer $backend-return) (not (x862-tailcallok xfer)))
+      (progn
+        (x862-mvcall seg vreg $backend-mvpass fn arglist t)
+        (let* ((*x862-returning-values* t)) (^)))
+      (let* ((mv-p (x862-mv-p xfer)))
+        (if (null arglist)
+          (x862-call-fn seg vreg xfer fn arglist nil)
+          (let* ((label (when (or recursive-p (x862-mvpass-p xfer)) (backend-get-next-label))))
+            (when label
+              (x862-vpush-label seg (aref *backend-labels* label)))
+            (x862-temp-push-node seg (x862-one-untargeted-reg-form seg fn *x862-arg-z*))
+            (x862-multiple-value-body seg (pop arglist))
+            (x862-open-undo $undostkblk)
+            (! save-values)
+            (dolist (form arglist)
+              (x862-multiple-value-body seg form)
+              (! add-values))
+            (! recover-values-for-mvcall)
+            (x862-close-undo)
+            (x862-temp-pop-node seg *x862-temp0*)
+            (x862-invoke-fn seg *x862-temp0* nil nil xfer label)
+            (when label
+              ;; Pushed a label earlier, then returned to it.
+              (setq *x862-top-vstack-lcell* (lcell-parent *x862-top-vstack-lcell*))
+              (x862-adjust-vstack (- *x862-target-node-size*)))))
+        (unless recursive-p
+          (if mv-p
+            (unless (eq xfer $backend-return)
+              (let* ((*x862-returning-values* t))
+                (^)))
+            (progn 
+              (<- *x862-arg-z*)
+              (^))))))))
+
+
+
+
+(defun x862-hard-opt-p (opts)
+  (or
+   (dolist (x (%cadr opts))
+     (unless (nx-null x) (return t)))
+   (dolist (x (%caddr opts))
+     (when x (return t)))))
+
+(defun x862-close-lambda (seg req opt rest keys auxen)
+  (dolist (var req)
+    (x862-close-var seg var))
+  (dolist (var (%car opt))
+    (x862-close-var seg var))
+  (dolist (var (%caddr opt))
+    (when var
+      (x862-close-var seg var)))
+  (if rest
+    (x862-close-var seg rest))
+  (dolist (var (%cadr keys))
+    (x862-close-var seg var))
+  (dolist (var (%caddr keys))
+    (if var (x862-close-var seg var)))
+  (dolist (var (%car auxen))
+    (x862-close-var seg var)))
+
+(defun x862-close-structured-var (seg var)
+  (if (x862-structured-var-p var)
+    (apply #'x862-close-structured-lambda seg (cdr var))
+    (x862-close-var seg var)))
+
+(defun x862-close-structured-lambda (seg whole req opt rest keys auxen)
+  (if whole
+    (x862-close-var seg whole))
+  (dolist (var req)
+    (x862-close-structured-var seg var))
+  (dolist (var (%car opt))
+    (x862-close-structured-var seg var))
+  (dolist (var (%caddr opt))
+    (when var
+      (x862-close-var seg var)))
+  (if rest
+    (x862-close-structured-var seg rest))
+  (dolist (var (%cadr keys))
+    (x862-close-structured-var seg var))
+  (dolist (var (%caddr keys))
+    (if var (x862-close-var seg var)))
+  (dolist (var (%car auxen))
+    (x862-close-var seg var)))
+
+
+(defun x862-init-regvar (seg var reg addr)
+  (with-x86-local-vinsn-macros (seg)
+    (x862-stack-to-register seg addr reg)
+    (x862-set-var-ea seg var ($ reg))))
+
+(defun x862-bind-structured-var (seg var vloc lcell &optional context)
+  (if (not (x862-structured-var-p var))
+    (let* ((reg (nx2-assign-register-var var)))
+      (if reg
+        (x862-init-regvar seg var reg (x862-vloc-ea vloc))
+        (x862-bind-var seg var vloc lcell)))
+    (let* ((v2 (%cdr var))
+           (v v2)
+           (vstack *x862-vstack*)
+           (whole (pop v))
+           (req (pop v))
+           (opt (pop v))
+           (rest (pop v))
+           (keys (pop v)))
+      
+      (apply #'x862-bind-structured-lambda seg 
+             (x862-spread-lambda-list seg (x862-vloc-ea vloc) whole req opt rest keys context)
+             vstack context v2))))
+
+(defun x862-bind-structured-lambda (seg lcells vloc context whole req opt rest keys auxen
+                        &aux (nkeys (list-length (%cadr keys))))
+  (declare (fixnum vloc))
+  (when whole
+    (x862-bind-structured-var seg whole vloc (pop lcells))
+    (incf vloc *x862-target-node-size*))
+  (dolist (arg req)
+    (x862-bind-structured-var seg arg vloc (pop lcells) context)
+    (incf vloc *x862-target-node-size*))
+  (when opt
+   (if (x862-hard-opt-p opt)
+     (setq vloc (apply #'x862-structured-initopt seg lcells vloc context opt)
+           lcells (nthcdr (ash (length (car opt)) 1) lcells))
+     (dolist (var (%car opt))
+       (x862-bind-structured-var seg var vloc (pop lcells) context)
+       (incf vloc *x862-target-node-size*))))
+  (when rest
+    (x862-bind-structured-var seg rest vloc (pop lcells) context)
+    (incf vloc *x862-target-node-size*))
+  (when keys
+    (apply #'x862-structured-init-keys seg lcells vloc context keys)
+    (setq vloc (%i+ vloc (* *x862-target-node-size* (+ nkeys nkeys)))))
+  (x862-seq-bind seg (%car auxen) (%cadr auxen)))
+
+(defun x862-structured-var-p (var)
+  (and (consp var) (or (eq (%car var) *nx-lambdalist*)
+                       (eq (%car var) (%nx1-operator lambda-list)))))
+
+(defun x862-simple-var (var &aux (bits (cadr var)))
+  (if (or (%ilogbitp $vbitclosed bits)
+          (%ilogbitp $vbitspecial bits))
+    (nx-error "Non-simple-variable ~S" (%car var))
+    var))
+
+(defun x862-nlexit (seg xfer &optional (nlevels 0))
+  (let* ((numnthrow 0)
+         (n *x862-undo-count*)
+         (cstack *x862-cstack*)
+         (vstack *x862-vstack*)
+         (target-vstack)
+         (lastcatch n)
+         (returning (eq xfer $backend-return))
+         (junk1 nil)
+         (unbind ())
+         (dest (%i- n nlevels))
+         (retval *x862-returning-values*)
+         reason)
+    (declare (ignorable junk1))
+    (with-x86-local-vinsn-macros (seg)
+      (when (neq 0 nlevels)
+        (let* ((num-temp-frames 0)
+               (num-c-frames 0))
+          (declare (fixnum num-temp-frames num-c-frames))
+          (flet ((pop-temp-frames ()
+                   (dotimes (i num-temp-frames)
+                     (! discard-temp-frame)))
+                 (pop-c-frames ()
+                   (dotimes (i num-c-frames)
+                     (! discard-c-frame)))
+                 (throw-through-numnthrow-catch-frames ()
+                   (when (neq 0 numnthrow)
+                     (let* ((tag-label (backend-get-next-label))
+                            (tag-label-value (aref *backend-labels* tag-label)))
+                       (x862-lri seg *x862-imm0* (ash numnthrow *x862-target-fixnum-shift*))
+                       (if retval
+                         (! nthrowvalues tag-label-value)
+                         (! nthrow1value tag-label-value))
+                       (@= tag-label))
+                     (setq numnthrow 0)
+                     (multiple-value-setq (junk1 cstack vstack)
+                       (x862-decode-stack (aref *x862-undo-stack* lastcatch)))))
+                 (find-last-catch ()
+                   (do* ((n n)
+                         (reasons *x862-undo-because*))
+                        ((= n dest))
+                     (declare (fixnum n))
+                     (when (eql $undocatch (aref reasons (decf n)))
+                       (incf numnthrow)
+                       (setq lastcatch n)))))
+                            
+            (find-last-catch)
+            (throw-through-numnthrow-catch-frames)
+            (setq n lastcatch)
+            (while (%i> n dest)
+              (setq reason (aref *x862-undo-because* (setq n (%i- n 1))))
+              (cond ((eql $undostkblk reason)
+                     (incf num-temp-frames))
+                    ((eql $undo-x86-c-frame reason)
+                     (incf num-c-frames))
+                    ((or (eql reason $undospecial)
+                        (eql reason $undointerruptlevel))
+                  (push reason unbind))))
+            (if unbind
+	      (target-arch-case
+	       (:x8632
+		(let* ((*available-backend-node-temps* *available-backend-node-temps*))
+		  (when retval (use-node-temp x8632::nargs))
+		  (x862-dpayback-list seg (nreverse unbind))))
+	       (:x8664
+		(let* ((*available-backend-imm-temps* *available-backend-imm-temps*))
+		  (when retval (use-imm-temp x8664::nargs.q))
+		  (x862-dpayback-list seg (nreverse unbind))))))
+            (when (and (neq lastcatch dest)
+                       (%i>
+                        vstack
+                        (setq target-vstack 
+                              (nth-value 2 (x862-decode-stack (aref *x862-undo-stack* dest)))))
+                       (neq retval t))
+              (unless returning
+                (let ((vdiff (%i- vstack target-vstack)))
+                  (if retval
+                    (progn
+                      (x862-lri seg *x862-imm0* vdiff)
+                      (! slide-values))
+                    (! adjust-vsp vdiff)))))
+            (pop-temp-frames)
+            (pop-c-frames)))
+        vstack))))
+
+
+;;; Restore the most recent dynamic bindings.  Bindings
+;;; of *INTERRUPT-LEVEL* get special treatment.
+(defun x862-dpayback-list (seg reasons)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((n 0))
+      (declare (fixnum n))
+      (dolist (r reasons (if (> n 0) (! dpayback n)))
+        (if (eql r $undospecial)
+          (incf n)
+          (if (eql r $undointerruptlevel)
+            (progn
+              (when (> n 0)
+                (! dpayback n)
+                (setq n 0))
+              (if (and *x862-open-code-inline*
+		       (target-arch-case
+			(:x8632 nil)
+			(:x8664 t)))
+                (let* ((*available-backend-node-temps* (bitclr *x862-arg-z* (bitclr x8664::rcx *available-backend-node-temps*))))
+                  (! unbind-interrupt-level-inline))
+                (! unbind-interrupt-level)))
+            (compiler-bug "unknown payback token ~s" r)))))))
+
+(defun x862-spread-lambda-list (seg listform whole req opt rest keys 
+                                    &optional enclosing-ea cdr-p)
+  (with-x86-local-vinsn-macros (seg)
+    (let* ((numopt (length (%car opt)))
+           (nkeys (length (%cadr keys)))
+           (numreq (length req))
+           (vtotal numreq)
+           (old-top *x862-top-vstack-lcell*)
+           (argreg ($ (target-arch-case
+		       (:x8632 ($ x8632::temp1))
+		       (:x8664 ($ x8664::temp0)))))
+           (keyvectreg (target-arch-case
+			(:x8632 ($ x8632::arg_y))
+			(:x8664 ($ x8664::arg_x))))
+           (doadlword (dpb nkeys (byte 8 16) (dpb numopt (byte 8 8) (dpb numreq (byte 8 0) 0 )))))
+      (declare (fixnum numopt nkeys numreq vtotal doadlword))
+      (when (or (> numreq 255) (> numopt 255) (> nkeys 255))
+        (compiler-bug "A lambda list can contain a maximum of 255 required, 255 optional, and 255 keywords args"))
+      (if (fixnump listform)
+        (x862-store-ea seg listform argreg)
+        (x862-one-targeted-reg-form seg listform argreg))
+      (when whole
+        (x862-vpush-register seg argreg :reserved))
+      (when keys
+        (setq doadlword (%ilogior2 (ash #x80000000 -6) doadlword))
+        (incf  vtotal (%ilsl 1 nkeys))
+        (if (%car keys)                 ; &allow-other-keys
+          (setq doadlword (%ilogior doadlword (ash #x80000000 -5))))
+        (x862-store-immediate seg (%car (%cdr (%cdr (%cdr (%cdr keys))))) keyvectreg))
+      (when opt
+        (setq vtotal (%i+ vtotal numopt))
+        (when (x862-hard-opt-p opt)
+          (setq doadlword (%ilogior2 doadlword (ash #x80000000 -7)))
+          (setq vtotal (%i+ vtotal numopt))))
+      (when rest
+        (setq doadlword (%ilogior2 (ash #x80000000 -4) doadlword) vtotal (%i+ vtotal 1)))
+      (x862-reserve-vstack-lcells vtotal)
+      (! load-adl doadlword)
+      (if cdr-p
+        (! macro-bind)
+        (if enclosing-ea
+          (progn
+            (x862-store-ea seg enclosing-ea *x862-arg-z*)
+            (! destructuring-bind-inner))
+          (! destructuring-bind)))
+      (x862-set-vstack (%i+ *x862-vstack* (* *x862-target-node-size* vtotal)))
+      (x862-collect-lcells :reserved old-top))))
+
+
+(defun x862-tailcallok (xfer)
+  (and (eq xfer $backend-return)
+       *x862-tail-allow*
+       (eq 0 *x862-undo-count*)))
+
+(defun x862-mv-p (cd)
+  (or (eq cd $backend-return) (x862-mvpass-p cd)))
+
+(defun x862-expand-note (frag-list note)
+  (let* ((lab (vinsn-note-label note)))
+    (case (vinsn-note-class note)
+      ((:regsave :begin-variable-scope :end-variable-scope
+        :source-location-begin :source-location-end)
+       (setf (vinsn-label-info lab) (emit-x86-lap-label frag-list lab))))))
+
+(defun x86-emit-instruction-from-vinsn (opcode-template
+                                        form
+                                        frag-list
+                                        instruction
+                                        immediate-operand)
+  #+debug
+  (format t "~&~a" (cons (x86::x86-opcode-template-mnemonic opcode-template)
+                         form))
+  (set-x86-instruction-template instruction opcode-template)
+  (let* ((operand-classes (x86::x86-opcode-template-operand-classes
+                           opcode-template))
+         (operand-types  (x86::x86-opcode-template-operand-types
+                          opcode-template))
+         (register-table (target-arch-case
+			  (:x8632 x86::*x8632-register-entries*)
+                          (:x8664 x86::*x8664-register-entries*))))
+    (dotimes (i (length operand-classes))
+      (let* ((operand (pop form))
+             (insert-function (svref operand-classes i))
+             (type (svref operand-types i))
+             (insert-keyword (svref x86::*x86-operand-insert-function-keywords*
+				    insert-function)))
+        #+debug
+        (format t "~& insert-function = ~s, operand = ~s"
+                insert-keyword
+                operand)
+        (ecase insert-keyword
+          (:insert-nothing )
+          ((:insert-modrm-reg :insert-xmm-reg)
+           (x86::insert-modrm-reg-entry instruction
+                                        (if (logtest (x86::encode-operand-type
+                                                      :reg8)
+                                                     type)
+                                          (x86::x86-reg8 operand)
+                                          (svref register-table operand))))
+          ((:insert-modrm-rm :insert-xmm-rm)
+           (x86::insert-modrm-rm-entry instruction
+                                       (if (logtest (x86::encode-operand-type
+                                                     :reg8)
+                                                    type)
+                                         (x86::x86-reg8 operand)
+                                         (svref register-table operand))))
+          (:insert-memory
+           (destructuring-bind (seg disp base index scale) operand
+             (when seg (setq seg
+                             (svref x86::*x86-seg-entries* (x86::reg-entry-reg-num (svref register-table seg)))))
+             ;; Optimize things like this later; almost all
+             ;; displacements will be constants at this point.
+             (when disp  (setq disp (parse-x86-lap-expression disp)))
+             (when base (setq base (svref register-table base)))
+             (when index (setq index (svref register-table index)))
+             (when scale (setq scale (1- (integer-length scale))))
+             (x86::insert-memory-operand-values
+              instruction
+              seg
+              disp
+              base
+              index
+              scale
+              (if (or base index)
+                (if disp
+                  (logior (optimize-displacement-type disp)
+                          (x86::encode-operand-type  :baseindex))
+                  (x86::encode-operand-type :baseindex))
+                (optimize-displacement-type disp)))))          
+          (:insert-opcode-reg
+           (x86::insert-opcode-reg-entry instruction
+                                         (if (logtest (x86::encode-operand-type
+                                                       :reg8)
+                                                      type)
+                                           (x86::x86-reg8 operand)
+                                           (svref register-table operand))))
+          (:insert-opcode-reg4
+           (x86::insert-opcode-reg4-entry instruction
+                                          (if (logtest (x86::encode-operand-type
+                                                        :reg8)
+                                                       type)
+                                            (x86::x86-reg8 operand)
+                                            (svref register-table operand))))
+          (:insert-reg4-pseudo-rm-high
+           (x86::insert-reg4-pseudo-rm-high-entry instruction
+                                                  (svref register-table operand)))
+          (:insert-reg4-pseudo-rm-low
+           (x86::insert-reg4-pseudo-rm-low-entry instruction
+                                                  (svref register-table operand)))
+          (:insert-cc
+           (unless (typep operand 'x86-lap-expression)
+             (setq operand (parse-x86-lap-expression operand)))
+           (setf (ldb (byte 4 0)
+                      (x86::x86-instruction-base-opcode instruction))
+                 (x86-lap-expression-value operand)))
+          (:insert-label
+           (setf (x86::x86-instruction-extra instruction)
+                 (find-or-create-x86-lap-label operand)))
+          (:insert-imm8-for-int
+           )
+          (:insert-extra
+           )
+          (:insert-imm8
+           (setf (x86::x86-immediate-operand-type immediate-operand)
+                 (x86::encode-operand-type :imm8)
+                 (x86::x86-immediate-operand-value immediate-operand)
+                 (parse-x86-lap-expression operand)
+                 (x86::x86-instruction-imm instruction)
+                 immediate-operand))
+          (:insert-imm8s
+           (setf (x86::x86-immediate-operand-type immediate-operand)
+                 (x86::encode-operand-type :imm8s)
+                 (x86::x86-immediate-operand-value immediate-operand)
+                 (parse-x86-lap-expression operand)
+                 (x86::x86-instruction-imm instruction)
+                 immediate-operand))
+          (:insert-imm16
+           (setf (x86::x86-immediate-operand-type immediate-operand)
+                 (x86::encode-operand-type :imm16)
+                 (x86::x86-immediate-operand-value immediate-operand)
+                 (parse-x86-lap-expression operand)
+                 (x86::x86-instruction-imm instruction)
+                 immediate-operand))
+          (:insert-imm32s
+           (setf (x86::x86-immediate-operand-type immediate-operand)
+                 (x86::encode-operand-type :imm32s)
+                 (x86::x86-immediate-operand-value immediate-operand)
+                 (parse-x86-lap-expression operand)
+                 (x86::x86-instruction-imm instruction)
+                 immediate-operand))
+          (:insert-imm32
+           (setf (x86::x86-immediate-operand-type immediate-operand)
+                 (x86::encode-operand-type :imm32)
+                 (x86::x86-immediate-operand-value immediate-operand)
+                 (parse-x86-lap-expression operand)
+                 (x86::x86-instruction-imm instruction)
+                 immediate-operand))
+          (:insert-imm64
+           (setf (x86::x86-immediate-operand-type immediate-operand)
+                 (x86::encode-operand-type :imm64)
+                 (x86::x86-immediate-operand-value immediate-operand)
+                 (parse-x86-lap-expression operand)
+                 (x86::x86-instruction-imm instruction)
+                 immediate-operand))
+          (:insert-mmx-reg
+           (x86::insert-mmx-reg-entry instruction
+                                      (svref register-table operand)))
+          (:insert-mmx-rm
+           (x86::insert-mmx-rm-entry instruction
+                                     (svref register-table operand)))
+	  (:insert-self
+	   (setf (x86::x86-immediate-operand-type immediate-operand)
+		 (x86::encode-operand-type :self)
+		 (x86::x86-immediate-operand-value immediate-operand)
+		 (parse-x86-lap-expression operand)
+		 (x86::x86-instruction-imm instruction)
+		 immediate-operand)))))
+    (x86-generate-instruction-code frag-list instruction)))
+          
+    
+(defun x862-expand-vinsns (header frag-list instruction &optional uuo-frag-list)
+  (let* ((immediate-operand (x86::make-x86-immediate-operand)))
+    (do-dll-nodes (v header)
+      (if (%vinsn-label-p v)
+        (let* ((id (vinsn-label-id v)))
+          (if (or (typep id 'fixnum) (null id))
+            (when (or t (vinsn-label-refs v) (null id))
+              (setf (vinsn-label-info v) (emit-x86-lap-label frag-list v)))
+            (x862-expand-note frag-list id)))
+        (x862-expand-vinsn v frag-list instruction immediate-operand uuo-frag-list)))
+    (when uuo-frag-list
+      (merge-dll-nodes frag-list uuo-frag-list)))
+  ;;; This doesn't have too much to do with anything else that's
+  ;;; going on here, but it needs to happen before the lregs
+  ;;; are freed.  There really shouldn't be such a thing as a
+  ;;; var-ea, of course ...
+  (dolist (s *x862-recorded-symbols*)
+    (let* ((var (car s))
+           (ea (var-ea var)))
+      (when (typep ea 'lreg)
+        (setf (var-ea var) (lreg-value ea)))))
+  (free-logical-registers)
+  (x862-free-lcells))
+
+;;; It's not clear whether or not predicates, etc. want to look
+;;; at an lreg or just at its value slot.
+;;; It's clear that the assembler just wants the value, and that
+;;; the value had better be assigned by the time we start generating
+;;; machine code.
+;;; For now, we replace lregs in the operand vector with their values
+;;; on entry, but it might be reasonable to make PARSE-OPERAND-FORM
+;;; deal with lregs ...
+(defun x862-expand-vinsn (vinsn frag-list instruction immediate-operand &optional uuo-frag-list)
+  (let* ((template (vinsn-template vinsn))
+         (main-frag-list frag-list)
+         (vp (vinsn-variable-parts vinsn))
+         (nvp (vinsn-template-nvp template))
+         (unique-labels ()))
+    (declare (fixnum nvp))
+    (dotimes (i nvp)
+      (let* ((val (svref vp i)))
+        (when (typep val 'lreg)
+          (setf (svref vp i) (lreg-value val)))))                       
+    (dolist (name (vinsn-template-local-labels template))
+      (let* ((unique (cons name nil)))
+        (push unique unique-labels)
+        (make-x86-lap-label unique)))
+    (labels ((parse-operand-form (valform &optional for-pred)
+               (cond ((typep valform 'keyword)
+                      (if (eq valform :rcontext)
+                        (backend-lisp-context-register *target-backend*)
+                        (or (assq valform unique-labels)
+                            (compiler-bug
+                             "unknown vinsn label ~s" valform))))
+                     ((atom valform) valform)
+                     ((eq (car valform) :rcontext)
+                      (if (>= (backend-lisp-context-register *target-backend*)
+                              (target-arch-case
+                               (:x8632 x86::+x8632-segment-register-offset+)
+                               (:x8664 x86::+x8664-segment-register-offset+)))
+                        (mapcar #'parse-operand-form `(:rcontext ,(cadr valform) nil nil nil))
+                        (mapcar #'parse-operand-form `(nil ,(cadr valform) :rcontext nil nil))))
+                     ((and (atom (cdr valform))
+                           (typep (car valform) 'fixnum))
+                      (svref vp (car valform)))
+                     ((eq (car valform) :@)
+                      (mapcar #'parse-operand-form (cdr valform)))
+                     ((eq (car valform) :^)
+                      (list :^ (parse-operand-form (cadr valform))))
+                     (t (let* ((op-vals (cdr valform))
+                               (parsed-ops (make-list (length op-vals)))
+                               (tail parsed-ops))
+                          (declare (dynamic-extent parsed-ops)
+                                   (list parsed-ops tail))
+                          (dolist (op op-vals
+                                   (if for-pred
+                                     (apply (car valform) parsed-ops)
+                                     (parse-x86-lap-expression (cons (car valform) parsed-ops))))
+                            (setq tail (cdr (rplaca tail (parse-operand-form op)))))))))
+             (expand-insn-form (f)
+               (let* ((operands (cdr f))
+                      (head (make-list (length operands)))
+                      (tail head))
+                 (declare (dynamic-extent head)
+                          (cons head tail))
+                 (dolist (op operands)
+                   (rplaca tail (parse-operand-form op))
+                   (setq tail (cdr tail)))
+                 (x86-emit-instruction-from-vinsn
+                  (svref x86::*x86-opcode-templates* (car f))
+                  head
+                  frag-list
+                  instruction
+                  immediate-operand)))
+             (eval-predicate (f)
+               (case (car f)
+                 (:pred (let* ((op-vals (cddr f))
+                               (parsed-ops (make-list (length op-vals)))
+                               (tail parsed-ops))
+                          (declare (dynamic-extent parsed-ops)
+                                   (list parsed-ops tail))
+                          (dolist (op op-vals (apply (cadr f) parsed-ops))
+                            (setq tail (cdr (rplaca tail (parse-operand-form op t)))))))
+                 (:not (not (eval-predicate (cadr f))))
+                 (:or (dolist (pred (cadr f))
+                        (when (eval-predicate pred)
+                          (return t))))
+                 (:and (dolist (pred (cadr f) t)
+                         (unless (eval-predicate pred)
+                           (return nil))))
+                 (t (compiler-bug "Unknown predicate: ~s" f))))
+             (expand-pseudo-op (f)
+               (case (car f)
+                 (:anchored-uuo-section
+                  (expand-form '(:uuo-section))
+                  (expand-form `(:long (:^ ,(cadr f)))))
+                 (:anchored-uuo
+                  (expand-form (cadr f))
+                  ;; add a trailing 0 byte after the uu0
+                  (frag-list-push-byte frag-list 0))
+                 ((:uuo :uuo-section)
+                      (if uuo-frag-list
+                        (progn
+                          (setq frag-list uuo-frag-list)
+                          (finish-frag-for-align frag-list 2))
+                        (compiler-bug "No frag-list for :uuo")))
+                 ((:main :main-section)
+                  (setq frag-list main-frag-list))
+                 (t
+                  (destructuring-bind (directive arg) f
+                     (setq arg (parse-operand-form arg))
+                     (let* ((exp (parse-x86-lap-expression arg))
+                            (constantp (or (not (x86-lap-expression-p exp))
+                                           (constant-x86-lap-expression-p exp))))
+                       (if constantp
+                         (let* ((val (x86-lap-expression-value exp)))
+                           (ecase directive
+                             (:byte (frag-list-push-byte frag-list val))
+                             (:short (frag-list-push-16 frag-list val))
+                             (:long (frag-list-push-32 frag-list val))
+                             (:quad (frag-list-push-64 frag-list val))
+                             (:align (finish-frag-for-align frag-list val))
+                             (:talign (finish-frag-for-talign frag-list val))))
+                         (let* ((pos (frag-list-position frag-list))
+                                (frag (frag-list-current frag-list))
+                                (reloctype nil))
+                           (ecase directive
+                             (:byte (frag-list-push-byte frag-list 0)
+                                    (setq reloctype :expr8))
+                             (:short (frag-list-push-16 frag-list 0)
+                                     (setq reloctype :expr16))
+                             (:long (frag-list-push-32 frag-list 0)
+                                    (setq reloctype :expr32))
+                             (:quad (frag-list-push-64 frag-list 0)
+                                    (setq reloctype :expr64))
+                             ((:align :talign) (compiler-bug "~s expression ~s not constant" directive arg)))
+                           (when reloctype
+                             (push
+                              (make-reloc :type reloctype
+                                          :arg exp
+                                          :pos pos
+                                          :frag frag)
+                              (frag-relocs frag))))))))))
+                   
+             (expand-form (f)
+               (if (keywordp f)
+                 (emit-x86-lap-label frag-list (assq f unique-labels))
+                 (if (atom f)
+                   (compiler-bug "Invalid form in vinsn body: ~s" f)
+                   (if (atom (car f))
+                     (if (keywordp (car f))
+                       (expand-pseudo-op f)
+                       (expand-insn-form f))
+                     (if (eval-predicate (car f))
+                       (dolist (subform (cdr f))
+                         (expand-form subform))))))))
+      (declare (dynamic-extent #'expand-form #'parse-operand-form #'expand-insn-form #'eval-predicate))
+      ;;(format t "~& vinsn = ~s" vinsn)
+      (dolist (form (vinsn-template-body template))
+	;;(format t "~&form = ~s" form)
+        (expand-form form ))
+      (setf (vinsn-variable-parts vinsn) nil)
+      (when vp
+        (free-varparts-vector vp)))))
+
+
+
+
+
+(defun x862-builtin-index-subprim (idx)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (table (arch::target-primitive->subprims  arch))
+         (shift (arch::target-subprims-shift arch)))
+    (dolist (cell table)
+      (destructuring-bind ((low . high) . base) cell
+        (if (and (>= idx low)
+                 (< idx high))
+          (return (+ base (ash (- idx low) shift))))))))
+
+(defun x862-fixed-call-builtin (seg vreg xfer name subprim)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((index (arch::builtin-function-name-offset name))
+           (idx-subprim (if index (x862-builtin-index-subprim index)))
+           (tail-p (x862-tailcallok xfer)))
+      (when tail-p
+        (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count*)
+        (x862-restore-full-lisp-context seg))
+      (if idx-subprim
+        (setq subprim idx-subprim)
+        (if index (! lri ($ *x862-imm0*) (ash index *x862-target-fixnum-shift*))))
+      (if tail-p
+        (! jump-subprim subprim)
+        (progn
+          (! call-subprim subprim)
+          (<- ($ *x862-arg-z*))
+          (^))))))
+
+(defun x862-unary-builtin (seg vreg xfer name form)
+  (with-x86-local-vinsn-macros (seg)
+    (x862-one-targeted-reg-form seg form ($ *x862-arg-z*))
+    (x862-fixed-call-builtin seg vreg xfer name (subprim-name->offset '.SPcallbuiltin1))))
+
+(defun x862-binary-builtin (seg vreg xfer name form1 form2)
+  (with-x86-local-vinsn-macros (seg)
+    (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*))
+    (x862-fixed-call-builtin seg vreg xfer name (subprim-name->offset '.SPcallbuiltin2))))
+
+(defun x862-ternary-builtin (seg vreg xfer name form1 form2 form3)
+  (with-x86-local-vinsn-macros (seg)
+    (x862-three-targeted-reg-forms seg form1 (target-arch-case
+					      (:x8632 ($ x8632::temp0))
+					      (:x8664 ($ x8664::arg_x)))
+				   form2 ($ *x862-arg-y*)
+				   form3 ($ *x862-arg-z*))
+    (x862-fixed-call-builtin seg vreg xfer name (subprim-name->offset '.SPcallbuiltin3))))
+
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+
+
+(defmacro defx862 (name locative arglist &body forms)
+  (multiple-value-bind (body decls)
+                       (parse-body forms nil t)
+    (destructuring-bind (vcode-block dest control &rest other-args) arglist
+      (let* ((fun `(nfunction ,name 
+                              (lambda (,vcode-block ,dest ,control ,@other-args) ,@decls 
+                                      (block ,name (with-x86-local-vinsn-macros (,vcode-block ,dest ,control) ,@body))))))
+        `(progn
+           (record-source-file ',name 'function)
+           (svset *x862-specials* (%ilogand #.operator-id-mask (%nx1-operator ,locative)) ,fun))))))
+)
+  
+(defx862 x862-lambda lambda-list (seg vreg xfer req opt rest keys auxen body p2decls &optional code-note)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((stack-consed-rest nil)
+           (next-method-var-scope-info nil)
+           (lexprp (if (consp rest) (progn (setq rest (car rest)) t)))
+           (rest-var-bits (and rest (nx-var-bits rest)))
+           (rest-ignored-p (and rest (not lexprp) (%ilogbitp $vbitignore rest-var-bits)))
+           (want-stack-consed-rest (or rest-ignored-p
+                                       (and rest (not lexprp) (%ilogbitp $vbitdynamicextent rest-var-bits))))
+           (afunc *x862-cur-afunc*)
+           (inherited-vars (afunc-inherited-vars afunc))
+           (fbits (afunc-bits afunc))
+           (methodp (%ilogbitp $fbitmethodp fbits))
+           (method-var (if methodp (pop req)))
+           (next-method-p (%ilogbitp $fbitnextmethp fbits))
+           (allow-other-keys-p (%car keys))
+           (hardopt (x862-hard-opt-p opt))
+           (lap-p (when (and (consp (%car req)) (eq (%caar req) '&lap))
+                    (prog1 (%cdar req) (setq req nil))))
+           (num-inh (length inherited-vars))
+           (num-req (length req))
+           (num-opt (length (%car opt)))
+           (no-regs nil)
+           (arg-regs nil)
+           optsupvloc
+           reglocatives
+           pregs
+           (reserved-lcells nil)
+           (*x862-vstack* 0))
+      (declare (type (unsigned-byte 16) num-req num-opt num-inh))
+      (with-x86-p2-declarations p2decls
+        (setq *x862-inhibit-register-allocation*
+              (setq no-regs (%ilogbitp $fbitnoregs fbits)))
+        (multiple-value-setq (pregs reglocatives) 
+          (nx2-allocate-global-registers
+           *x862-fcells*
+           *x862-vcells*
+           (afunc-all-vars afunc)
+           inherited-vars
+           (unless no-regs
+             (target-arch-case
+              (:x8664
+               (if (= (backend-lisp-context-register *target-backend*) x8664::save3)
+                 *reduced-x8664-nvrs*
+                 *x8664-nvrs*))
+              (:x8632
+               *x8632-nvrs*)))))
+        (@ (backend-get-next-label)) ; generic self-reference label, should be label #1
+        (! establish-fn)
+        (@ (backend-get-next-label))    ; self-call label
+	(when keys ;; Ensure keyvect is the first immediate
+	  (x86-immediate-label (%cadr (%cdddr keys))))
+        (when code-note
+	  (x862-code-coverage-entry seg code-note))
+        (unless next-method-p
+          (setq method-var nil))
+        
+        (let* ((rev-req (reverse req))
+               (rev-fixed (if inherited-vars (reverse (append inherited-vars req)) rev-req))
+               (num-fixed (length rev-fixed))
+               (rev-opt (reverse (car opt)))
+               (max-args (unless (or rest keys) (+ num-fixed num-opt))))
+          (if (not (or opt rest keys))
+            (setq arg-regs (x862-req-nargs-entry seg rev-fixed))
+            (if (and (not (or hardopt rest keys))
+                     (<= num-opt *x862-target-num-arg-regs*))
+              (setq arg-regs (x862-simple-opt-entry seg rev-opt rev-fixed))
+              (progn
+                ;; If the minumum acceptable number of args is
+                ;; non-zero, ensure that at least that many were
+                ;; received.  If there's an upper bound, enforce it.
+                
+                (cond (rev-fixed
+                       (x862-reserve-vstack-lcells num-fixed)
+                       (if max-args
+                         (! check-min-max-nargs num-fixed max-args)
+                         (! check-min-nargs num-fixed)))
+                      (max-args
+                       (! check-max-nargs max-args)))
+                (if (not (or rest keys))
+                  (if (<= (+ num-fixed num-opt) *x862-target-num-arg-regs*)
+                    (! save-lisp-context-no-stack-args)
+                    (! save-lisp-context-variable-arg-count))
+                  (! save-lisp-context-variable-arg-count))
+                ;; If there were &optional args, initialize their values
+                ;; to NIL.  All of the argregs get vpushed as a result of this.
+                (when opt
+                  (x862-reserve-vstack-lcells num-opt)
+                  (if max-args
+                    (! push-max-argregs max-args)
+                    (! push-argregs))
+                  (! default-optionals (+ num-fixed num-opt)))
+                (when keys
+                  (let* ((keyvect (%car (%cdr (%cdr (%cdr (%cdr keys))))))
+                         (flags (the fixnum (logior (the fixnum (if rest 4 0)) 
+                                                    (the fixnum (if (or methodp allow-other-keys-p) 1 0)))))
+                         (nkeys (length keyvect))
+                         (nprev (+ num-fixed num-opt)))
+                    (declare (fixnum flags nkeys nprev))
+                    (dotimes (i (the fixnum (+ nkeys nkeys)))
+                      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil))
+		    (target-arch-case
+		     ;; xxx hack alert (see SPkeyword_bind in x86-spentry32.s)
+		     (:x8632
+		      (! set-high-halfword *x862-temp1* flags))
+		     (:x8664
+		      (x862-lri seg *x862-temp1* (ash flags *x862-target-fixnum-shift*))))
+                    (unless (= nprev 0)
+                      (x862-lri seg *x862-imm0* (ash nprev *x862-target-fixnum-shift*)))
+                    (x86-immediate-label keyvect)
+                    (if (= 0 nprev)
+                      (! simple-keywords)
+                      (if (= 0 num-opt)
+                        (! keyword-args)
+                        (! keyword-bind)))))
+                (when rest
+                  ;; If any keyword-binding's happened, the key/value
+                  ;; pairs have been slid to the top-of-stack for us.
+                  ;; There'll be an even number of them (nargs - the
+                  ;; "previous" (required/&optional) count.)
+                  (if lexprp
+                    (x862-lexpr-entry seg num-fixed)
+                    (progn
+                      (if want-stack-consed-rest
+                        (setq stack-consed-rest t))
+                      (let* ((nprev (+ num-fixed num-opt))
+                             (simple (and (not keys) (= 0 nprev))))
+                        (declare (fixnum nprev))
+                        (unless simple
+                          (x862-lri seg *x862-imm0* (ash nprev *x862-target-fixnum-shift*)))
+                        (if stack-consed-rest
+                          (if simple
+                            (! stack-rest-arg)
+                            (if (and (not keys) (= 0 num-opt))
+                              (! req-stack-rest-arg)
+                              (! stack-cons-rest-arg)))
+                          (if simple
+                            (! heap-rest-arg)
+                            (if (and (not keys) (= 0 num-opt))
+                              (! req-heap-rest-arg)
+                              (! heap-cons-rest-arg)))))
+                      ;; Make an lcell for the &rest arg
+                      (x862-reserve-vstack-lcells 1))))
+                (when hardopt
+                  (x862-reserve-vstack-lcells num-opt)
+                  
+
+                  ;; ! opt-supplied-p wants nargs to contain the
+                  ;; actual arg-count minus the number of "fixed"
+                  ;; (required, inherited) args.
+
+                  (unless (= 0 num-fixed)
+                    (! scale-nargs num-fixed))
+                  (cond ((= 1 num-opt)
+                         (! one-opt-supplied-p))
+                        ((= 2 num-opt)
+                         (! two-opt-supplied-p))
+                        (t
+                         (! opt-supplied-p num-opt))))
+                (let* ((nwords-vpushed (+ num-fixed 
+                                          num-opt 
+                                          (if hardopt num-opt 0) 
+                                          (if lexprp 0 (if rest 1 0))
+                                          (ash (length (%cadr keys)) 1)))
+                       (nbytes-vpushed (* nwords-vpushed *x862-target-node-size*)))
+                  (declare (fixnum nwords-vpushed nbytes-vpushed))
+                  (x862-set-vstack nbytes-vpushed)
+                  (setq optsupvloc (- *x862-vstack* (* num-opt *x862-target-node-size*)))))))
+          ;; Caller's context is saved; *x862-vstack* is valid.  Might
+          ;; still have method-var to worry about.
+          (unless (= 0 pregs)
+            ;; Save NVRs; load constants into any that get constants.
+            (x862-save-nvrs seg pregs)
+            (dolist (pair reglocatives)
+              (let* ((pair pair)
+                     (constant (car pair))
+                     (reg (cdr pair)))
+                (declare (cons pair constant))
+                (rplacd constant reg)
+                (! ref-constant reg (x86-immediate-label (car constant))))))
+          (when (and (not (or opt rest keys))
+                     (<= max-args *x862-target-num-arg-regs*)
+                     (not (some #'null arg-regs)))
+            (setq *x862-tail-vsp* *x862-vstack*
+                  *x862-tail-nargs* max-args)
+            (@ (setq *x862-tail-label* (backend-get-next-label))))
+          (when method-var
+	    (target-arch-case
+	     (:x8632
+	      (with-node-target () next-method-context
+		(! load-next-method-context next-method-context)
+		(x862-seq-bind-var seg method-var next-method-context)))
+	     (:x8664
+	      (x862-seq-bind-var seg method-var x8664::next-method-context)))
+	    (when *x862-recorded-symbols*
+              (setq next-method-var-scope-info (pop *x862-recorded-symbols*))))
+
+          ;; If any arguments are still in arg_x, arg_y, arg_z, that's
+          ;; because they weren't vpushed in a "simple" entry case and
+          ;; belong in some NVR.  Put them in their NVRs, so that we
+          ;; can handle arbitrary expression evaluation (special
+          ;; binding, value-cell consing, etc.) without clobbering the
+          ;; argument registers.
+          (when arg-regs
+            (do* ((vars arg-regs (cdr vars))
+                  (arg-reg-numbers (target-arch-case
+				    (:x8632 (list *x862-arg-z* *x862-arg-y*))
+                                    (:x8664 (list *x862-arg-z* *x862-arg-y* x8664::arg_x))))
+                  (arg-reg-num (pop arg-reg-numbers) (pop arg-reg-numbers)))
+                 ((null vars))
+              (declare (list vars))
+              (let* ((var (car vars)))
+                (when var
+                  (let* ((reg (nx2-assign-register-var var)))
+                    (x862-copy-register seg reg arg-reg-num)
+                    (setf (var-ea var) reg))))))
+          (setq *x862-entry-vsp-saved-p* t)
+          (when stack-consed-rest
+            (x862-open-undo $undostkblk))
+          (setq *x862-entry-vstack* *x862-vstack*)
+          (setq reserved-lcells (x862-collect-lcells :reserved))
+          (x862-bind-lambda seg reserved-lcells req opt rest keys auxen optsupvloc arg-regs lexprp inherited-vars)
+          (when next-method-var-scope-info
+            (push next-method-var-scope-info *x862-recorded-symbols*)))
+        (when method-var (x862-heap-cons-next-method-var seg method-var))
+        (x862-form seg vreg xfer body)
+        (x862-close-lambda seg req opt rest keys auxen)
+        (dolist (v inherited-vars)
+          (x862-close-var seg v))
+        (when method-var
+          (x862-close-var seg method-var))
+        (let* ((bits 0))
+          (when (%i> num-inh (ldb $lfbits-numinh -1))
+            (setq num-inh (ldb $lfbits-numinh -1)))
+          (setq bits (dpb num-inh $lfbits-numinh bits))
+          (unless lap-p
+            (when (%i> num-req (ldb $lfbits-numreq -1))
+              (setq num-req (ldb $lfbits-numreq -1)))
+            (setq bits (dpb num-req $lfbits-numreq bits))
+            (when (%i> num-opt (ldb $lfbits-numopt -1))
+              (setq num-opt (ldb $lfbits-numopt -1)))
+            (setq bits (dpb num-opt $lfbits-numopt bits))
+            (when hardopt (setq bits (%ilogior (%ilsl $lfbits-optinit-bit 1) bits)))
+            (when rest (setq bits (%ilogior (if lexprp (%ilsl $lfbits-restv-bit 1) (%ilsl $lfbits-rest-bit 1)) bits)))
+            (when keys (setq bits (%ilogior (%ilsl $lfbits-keys-bit 1) bits)))
+            (when allow-other-keys-p (setq bits (%ilogior (%ilsl $lfbits-aok-bit 1) bits)))
+            (when (%ilogbitp $fbitnextmethargsp (afunc-bits afunc))
+              (if methodp
+                (setq bits (%ilogior (%ilsl $lfbits-nextmeth-with-args-bit 1) bits))
+                (let ((parent (afunc-parent afunc)))
+                  (when parent
+                    (setf (afunc-bits parent) (bitset $fbitnextmethargsp (afunc-bits parent)))))))
+            (when methodp
+              (setq bits (logior (ash 1 $lfbits-method-bit) bits))
+              (when next-method-p
+                (setq bits (logior (%ilsl $lfbits-nextmeth-bit 1) bits)))))
+          bits)))))
+
+
+(defx862 x862-progn progn (seg vreg xfer forms)
+  (declare (list forms))
+  (if (null forms)
+    (x862-nil seg vreg xfer)
+    (loop
+      (let* ((form (pop forms)))
+        (if forms
+          (x862-form seg nil nil form)
+          (return (x862-form seg vreg xfer form)))))))
+
+
+
+(defx862 x862-prog1 prog1 (seg vreg xfer forms)
+  (if (eq (list-length forms) 1)
+    (x862-use-operator (%nx1-operator values) seg vreg xfer forms)
+    (if (null vreg)
+      (x862-use-operator (%nx1-operator progn) seg vreg xfer forms)
+      (let* ((float-p (= (hard-regspec-class vreg) hard-reg-class-fpr))
+             (crf-p (= (hard-regspec-class vreg) hard-reg-class-crf))
+             (node-p (unless (or float-p crf-p)
+                       (= (get-regspec-mode vreg) hard-reg-class-gpr-mode-node)))
+             (first (pop forms)))
+        (if (and node-p
+                 (nx-null (car forms))
+                 (null (cdr forms)))
+          (x862-form seg vreg xfer first)
+          (progn
+            (x862-push-register seg 
+                                (if (or node-p crf-p)
+                                  (x862-one-untargeted-reg-form seg first *x862-arg-z*)
+                                  (x862-one-targeted-reg-form seg first vreg)))
+            (dolist (form forms)
+              (x862-form seg nil nil form))
+            (if crf-p
+              (progn
+                (x862-vpop-register seg *x862-arg-z*)
+                (<- *x862-arg-z*))
+              (x862-pop-register seg vreg))
+            (^)))))))
+
+(defx862 x862-free-reference free-reference (seg vreg xfer sym)
+  (x862-ref-symbol-value seg vreg xfer sym t))
+
+(defx862 x862-special-ref special-ref (seg vreg xfer sym)
+  (x862-ref-symbol-value seg vreg xfer sym t))
+
+(defx862 x862-bound-special-ref bound-special-ref (seg vreg xfer sym)
+  (x862-ref-symbol-value seg vreg xfer sym t))
+
+(defx862 x862-%slot-ref %slot-ref (seg vreg xfer instance idx)
+  (ensuring-node-target (target (or vreg ($ *x862-arg-z*)))
+    (multiple-value-bind (v i)
+        (x862-two-untargeted-reg-forms seg instance *x862-arg-y* idx *x862-arg-z*)
+      (unless *x862-reckless*
+        (! check-misc-bound i v))
+      (with-node-temps (v) (temp)
+        (! %slot-ref temp v i)
+        (x862-copy-register seg target temp))))
+  (^))
+
+(pushnew (%nx1-operator %svref) *x862-operator-supports-push*)
+(defx862 x862-%svref %svref (seg vreg xfer vector index)
+  (x862-vref seg vreg xfer :simple-vector vector index nil))
+
+(pushnew (%nx1-operator svref) *x862-operator-supports-push*)
+(defx862 x862-svref svref (seg vreg xfer vector index)
+  (x862-vref seg vreg xfer :simple-vector vector index (unless *x862-reckless* (nx-lookup-target-uvector-subtag :simple-vector))))
+
+;;; It'd be nice if this didn't box the result.  Worse things happen ...
+;;;  Once there's a robust mechanism, adding a CHARCODE storage class shouldn't be hard.
+(defx862 x862-%sbchar %sbchar (seg vreg xfer string index)
+  (x862-vref seg vreg xfer :simple-string string index (unless *x862-reckless* (nx-lookup-target-uvector-subtag :simple-string))))
+
+
+(defx862 x862-%svset %svset (seg vreg xfer vector index value)
+  (x862-vset seg vreg xfer :simple-vector vector index value nil))
+
+(defx862 x862-svset svset (seg vreg xfer vector index value)
+   (x862-vset seg vreg xfer :simple-vector vector  index value (nx-lookup-target-uvector-subtag :simple-vector)))
+
+(defx862 x862-typed-form typed-form (seg vreg xfer typespec form &optional check)
+  (if check
+    (x862-typechecked-form seg vreg xfer typespec form)
+    (x862-form seg vreg xfer form)))
+
+(defx862 x862-type-asserted-form type-asserted-form (seg vreg xfer typespec form &optional check)
+  (declare (ignore typespec check))
+  (x862-form seg vreg xfer form))
+
+(defx862 x862-%primitive %primitive (seg vreg xfer &rest ignore)
+  (declare (ignore seg vreg xfer ignore))
+  (compiler-bug "You're probably losing big: using %primitive ..."))
+
+(defx862 x862-consp consp (seg vreg xfer cc form)
+  (if (null vreg)
+    (x862-form seg vreg xfer form)
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+      (! set-z-flag-if-consp (x862-one-untargeted-reg-form seg form *x862-arg-z*))
+      (regspec-crf-gpr-case
+       (vreg dest)
+       (^ cr-bit true-p)
+       (progn
+	 (ensuring-node-target (target dest)
+	   (if (not true-p)
+	     (setq cr-bit (logxor 1 cr-bit)))
+	   (! cr-bit->boolean target cr-bit))
+	 (^))))))
+      
+(defx862 x862-cons cons (seg vreg xfer y z)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil y)
+      (x862-form seg nil xfer z))
+    (multiple-value-bind (yreg zreg) (x862-two-untargeted-reg-forms seg y *x862-arg-y* z *x862-arg-z*)
+      (ensuring-node-target (target vreg)
+        (! cons target yreg zreg))
+      (^))))
+
+
+
+(defx862 x862-%rplaca %rplaca (seg vreg xfer ptr val)
+  (x862-modify-cons seg vreg xfer ptr val nil nil t))
+
+(defx862 x862-%rplacd %rplacd (seg vreg xfer ptr val)
+  (x862-modify-cons seg vreg xfer ptr val nil t t))
+
+(defx862 x862-rplaca rplaca (seg vreg xfer ptr val)
+  (x862-modify-cons seg vreg xfer ptr val t nil t))
+
+(defx862 x862-set-car set-car (seg vreg xfer ptr val)
+  (x862-modify-cons seg vreg xfer ptr val t nil nil))
+
+(defx862 x862-rplacd rplacd (seg vreg xfer ptr val)
+  (x862-modify-cons seg vreg xfer ptr val t t t))
+
+(defx862 x862-set-cdr set-cdr (seg vreg xfer ptr val)
+  (x862-modify-cons seg vreg xfer ptr val t t nil))
+
+(pushnew (%nx1-operator %car) *x862-operator-supports-push*)
+(defx862 x862-%car %car (seg vreg xfer form)
+  (x862-reference-list seg vreg xfer form nil nil))
+
+(pushnew (%nx1-operator %cdr) *x862-operator-supports-push*)
+(defx862 x862-%cdr %cdr (seg vreg xfer form)
+  (x862-reference-list seg vreg xfer form nil t))
+
+(pushnew (%nx1-operator car) *x862-operator-supports-push*)
+(defx862 x862-car car (seg vreg xfer form)
+  (x862-reference-list seg vreg xfer form t nil))
+
+(pushnew (%nx1-operator cdr) *x862-operator-supports-push*)
+(defx862 x862-cdr cdr (seg vreg xfer form)
+  (x862-reference-list seg vreg xfer form t t))
+
+(defx862 x862-vector vector (seg vreg xfer arglist)
+  (x862-allocate-initialized-gvector seg vreg xfer
+                                     (nx-lookup-target-uvector-subtag
+                                      :simple-vector) arglist))
+
+(defx862 x862-%gvector %gvector (seg vreg xfer arglist)
+  (let* ((all-on-stack (append (car arglist) (reverse (cadr arglist))))
+         (subtag-form (car all-on-stack))
+         (subtag (acode-fixnum-form-p subtag-form)))
+    (if (null vreg)
+      (dolist (form all-on-stack (^)) (x862-form seg nil nil form))
+      (if (null subtag)
+        (progn                            ; Vpush everything and call subprim
+          (let* ((*x862-vstack* *x862-vstack*)
+                 (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+            (x862-set-nargs seg (x862-formlist seg all-on-stack nil))
+            (! gvector))
+          (<- *x862-arg-z*)
+          (^))
+        (x862-allocate-initialized-gvector seg vreg xfer subtag (cdr all-on-stack))))))
+
+;;; Should be less eager to box result
+(defx862 x862-%char-code %char-code (seg vreg xfer c)
+  (x862-extract-charcode seg vreg xfer c nil))
+
+(defx862 x862-char-code char-code (seg vreg xfer c)
+  (x862-extract-charcode seg vreg xfer c (not (x862-form-typep c 'character))))
+
+(defx862 x862-%ilogior2 %ilogior2 (seg vreg xfer form1 form2)
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2)))
+    (if (and fix1 fix2)
+      (x862-use-operator (%nx1-operator fixnum) seg vreg xfer (logior fix1 fix2)))
+    (let* ((fixval (or fix1 fix2))
+           (fiximm (if fixval (<= (integer-length fixval)
+                                  (- 31 *x862-target-fixnum-shift*))))
+           (otherform (when fiximm (if fix1 form2 form1))))
+      (if otherform
+        (if (null vreg)
+          (x862-form seg nil xfer otherform)
+          (ensuring-node-target (target vreg)
+            (x862-one-targeted-reg-form seg otherform target)
+            (! %logior-c target target (ash fixval *x862-target-fixnum-shift*))))
+         (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form1 *x862-arg-y* form2 *x862-arg-z*)
+            (if vreg (ensuring-node-target (target vreg) (! %logior2 target r1 r2)))))
+      (^))))
+
+;;; in a lot of (typical ?) cases, it might be possible to use a
+;;; rotate-and-mask instead of andi./andis.
+
+(defx862 x862-%ilogand2 %ilogand2 (seg vreg xfer form1 form2)
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2)))
+    (if (and fix1 fix2)
+      (x862-use-operator (%nx1-operator fixnum) seg vreg xfer (logand fix1 fix2)))
+    (let* ((fixval (or fix1 fix2))
+           (fiximm (if fixval (<= (integer-length fixval)
+                                  (- 31 *x862-target-fixnum-shift*))))
+           (otherform (when fiximm (if fix1 form2 form1))))
+      (if otherform
+        (if (null vreg)
+          (x862-form seg nil xfer otherform)
+          (ensuring-node-target (target vreg)
+            (x862-one-targeted-reg-form seg otherform target)
+            (! %logand-c target target (ash fixval *x862-target-fixnum-shift*))))
+         (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form1 *x862-arg-y* form2 *x862-arg-z*)
+            (if vreg (ensuring-node-target (target vreg) (! %logand2 target r1 r2)))))
+      (^))))
+
+(defx862 x862-%ilogxor2 %ilogxor2 (seg vreg xfer form1 form2)
+  (let* ((fix1 (acode-fixnum-form-p form1))
+         (fix2 (acode-fixnum-form-p form2)))
+    (if (and fix1 fix2)
+      (x862-use-operator (%nx1-operator fixnum) seg vreg xfer (logxor fix1 fix2)))
+    (let* ((fixval (or fix1 fix2))
+           (fiximm (if fixval (<= (integer-length fixval)
+                                  (- 31 *x862-target-fixnum-shift*))))
+           (otherform (when fiximm (if fix1 form2 form1))))
+      (if otherform
+        (if (null vreg)
+          (x862-form seg nil xfer otherform)
+          (ensuring-node-target (target vreg)
+            (x862-one-targeted-reg-form seg otherform target)
+            (! %logxor-c target target (ash fixval *x862-target-fixnum-shift*))))
+         (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form1 *x862-arg-y* form2 *x862-arg-z*)
+            (if vreg (ensuring-node-target (target vreg) (! %logxor2 target r1 r2)))))
+      (^))))
+
+(defx862 x862-%ineg %ineg (seg vreg xfer n)
+  (if (null vreg)
+    (x862-form seg vreg xfer n)
+    (progn
+      (ensuring-node-target (target vreg)
+        (x862-one-targeted-reg-form seg n target)
+        (! negate-fixnum target)
+        (x862-check-fixnum-overflow seg target))
+      (^ ))))
+
+(defx862 x862-%%ineg %%ineg (seg vreg xfer n)
+  (if (null vreg)
+    (x862-form seg vreg xfer n)
+    (progn
+      (ensuring-node-target (target vreg)
+        (x862-one-targeted-reg-form seg n target)
+        (when vreg
+          (! negate-fixnum target)))
+      (^))))
+
+(defx862 x862-characterp characterp (seg vreg xfer cc form)
+  (x862-char-p seg vreg xfer cc form))
+
+(pushnew (%nx1-operator struct-ref) *x862-operator-supports-push*)
+(defx862 x862-struct-ref struct-ref (seg vreg xfer struct offset)
+  (x862-vref seg vreg xfer :struct struct offset (unless *x862-reckless* (nx-lookup-target-uvector-subtag :struct))))
+
+(defx862 x862-struct-set struct-set (seg vreg xfer struct offset value)
+  (x862-vset seg vreg xfer :struct struct offset value (unless *x862-reckless* (nx-lookup-target-uvector-subtag :struct))))
+
+(defx862 x862-istruct-typep istruct-typep (seg vreg xfer cc form type)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form *x862-arg-y* type *x862-arg-z*)
+      (! set-z-flag-if-istruct-typep r1 r2)
+      (regspec-crf-gpr-case 
+       (vreg dest)
+       (^ cr-bit true-p)
+       (progn
+         (ensuring-node-target (target dest)
+           (if (not true-p)
+             (setq cr-bit (logxor 1 cr-bit)))
+           (! cr-bit->boolean target cr-bit))
+         (^))))))
+
+
+(pushnew (%nx1-operator lisptag) *x862-operator-supports-u8-target*)
+(defx862 x862-lisptag lisptag (seg vreg xfer node)
+  (if (null vreg)
+    (x862-form seg vreg xfer node)
+    (progn
+      (unboxed-other-case (vreg :u8)
+        (! extract-tag vreg (x862-one-untargeted-reg-form seg node *x862-arg-z*))
+        (ensuring-node-target (target vreg) 
+         (! extract-tag-fixnum target (x862-one-untargeted-reg-form seg node *x862-arg-z*))))
+      (^))))
+
+(pushnew (%nx1-operator fulltag) *x862-operator-supports-u8-target*)
+(defx862 x862-fulltag fulltag (seg vreg xfer node)
+  (if (null vreg)
+    (x862-form seg vreg xfer node)
+    (progn
+      (unboxed-other-case (vreg :u8)
+        (! extract-fulltag vreg (x862-one-untargeted-reg-form seg node *x862-arg-z*))
+        (ensuring-node-target (target vreg) 
+          (! extract-fulltag-fixnum target (x862-one-untargeted-reg-form seg node *x862-arg-z*))))
+      (^))))
+
+(pushnew (%nx1-operator typecode) *x862-operator-supports-u8-target*)
+(defx862 x862-typecode typecode (seg vreg xfer node)
+  (if (null vreg)
+    (x862-form seg vreg xfer node)
+    (progn
+      (unboxed-other-case (vreg :u8)
+         (! extract-typecode vreg (x862-one-untargeted-reg-form seg node *x862-arg-z*))
+         (let* ((reg (x862-one-untargeted-reg-form seg node (if (eq (hard-regspec-value vreg) *x862-arg-z*) 
+                                                              *x862-arg-y* *x862-arg-z*))))
+           (ensuring-node-target (target vreg) 
+             (! extract-typecode-fixnum target reg ))))
+      (^))))
+
+(defx862 x862-setq-special setq-special (seg vreg xfer sym val)
+  (let* ((symreg ($ *x862-arg-y*))
+         (valreg ($ *x862-arg-z*)))
+    (x862-one-targeted-reg-form seg val valreg)
+    (x862-store-immediate seg (x862-symbol-value-cell sym) symreg)
+    (! setq-special symreg valreg)
+    (<- valreg))
+  (^))
+
+
+(defx862 x862-local-go local-go (seg vreg xfer tag)
+  (declare (ignorable xfer))
+  (let* ((curstack (x862-encode-stack))
+         (label (cadr tag))
+         (deststack (caddr tag)))
+    (if (not (x862-equal-encodings-p curstack deststack))
+      (multiple-value-bind (catch cstack vstack)
+                           (x862-decode-stack deststack)
+        (x862-unwind-stack seg nil catch cstack vstack)))
+    (-> label)
+    (x862-unreachable-store vreg)))
+
+(defx862 x862-local-block local-block (seg vreg xfer blocktag body)
+  (let* ((curstack (x862-encode-stack))
+         (compound (x862-cd-compound-p xfer))
+         (mvpass-p (x862-mvpass-p xfer))
+         (need-label (if xfer (or compound mvpass-p) t))
+         end-of-block
+         last-cd
+         (dest (if (backend-crf-p vreg) *x862-arg-z* vreg)))
+    (if need-label
+      (setq end-of-block (backend-get-next-label)))
+    (setq last-cd (if need-label (%ilogior2 (if mvpass-p $backend-mvpass-mask 0) end-of-block) xfer))
+    (%rplaca blocktag (cons (cons dest last-cd) curstack))
+    (if mvpass-p
+      (x862-multiple-value-body seg body)
+      (x862-form seg dest (if xfer last-cd) body))
+    (when need-label
+      (@ end-of-block)
+      (if compound
+        (<- dest))
+      (x862-branch seg (logand (lognot $backend-mvpass-mask) (or xfer 0))))))
+
+(defx862 x862-%izerop %izerop (seg vreg xfer cc form)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (x862-test-%izerop seg vreg xfer form cr-bit true-p)))
+
+
+(defx862 x862-uvsize uvsize (seg vreg xfer v)
+  (let* ((misc-reg (x862-one-untargeted-reg-form seg v *x862-arg-z*)))
+    (unless *x862-reckless* (! trap-unless-uvector misc-reg))
+    (if vreg 
+      (ensuring-node-target (target vreg)
+        (! misc-element-count-fixnum target misc-reg)))
+    (^)))
+
+(defx862 x862-%ilsl %ilsl (seg vreg xfer form1 form2)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil form1)
+      (x862-form seg nil xfer form2))
+    (let* ((const (acode-fixnum-form-p form1))
+           (max (target-arch-case (:x8632 31) (:x8664 63))))
+      (ensuring-node-target (target vreg)
+        (if const
+          (let* ((src (x862-one-untargeted-reg-form seg form2 *x862-arg-z*)))
+            (if (<= const max)
+              (! %ilsl-c target const src)
+              (!  lri target 0)))
+          (multiple-value-bind (count src) (x862-two-untargeted-reg-forms seg form1 *x862-arg-y* form2 *x862-arg-z*)
+            (! %ilsl target count src))))
+      (^))))
+
+(defx862 x862-endp endp (seg vreg xfer cc form)
+  (let* ((formreg (x862-one-untargeted-reg-form seg form *x862-arg-z*)))
+    (! trap-unless-list formreg)
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+      (x862-compare-register-to-nil seg vreg xfer formreg  cr-bit true-p))))
+
+
+
+(defx862 x862-%code-char %code-char (seg vreg xfer c)
+  (if (null vreg)
+    (x862-form seg nil xfer c)
+    (progn
+      (ensuring-node-target (target vreg)
+        (with-imm-target () (dest :u8)
+          (! u32->char target (x862-one-untargeted-reg-form seg c dest))))
+      (^))))
+
+(defx862 x862-%schar %schar (seg vreg xfer str idx)
+  (multiple-value-bind (src unscaled-idx)
+      (x862-two-untargeted-reg-forms seg str *x862-arg-y* idx *x862-arg-z*)
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+          (256 (! %schar8 target src unscaled-idx))
+          (t (! %schar32 target src unscaled-idx)))))
+    (^)))
+
+(defx862 x862-%set-schar %set-schar (seg vreg xfer str idx char)
+  (multiple-value-bind (src unscaled-idx char)
+      (x862-three-untargeted-reg-forms seg
+                                       str (target-arch-case
+					    (:x8632 x8632::temp0)
+					    (:x8664 x8664::arg_x))
+                                       idx *x862-arg-y*
+                                       char *x862-arg-z*)
+    (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+      (256 (! %set-schar8 src unscaled-idx char))
+      (t (! %set-schar32 src unscaled-idx char)))
+    (when vreg (<- char)) 
+    (^)))
+
+(defx862 x862-%set-scharcode %set-scharcode (seg vreg xfer str idx char)
+  (multiple-value-bind (src unscaled-idx char)
+      (x862-three-untargeted-reg-forms seg str (target-arch-case
+						(:x8632 x8632::temp0)
+						(:x8664 x8664::arg_x))
+				       idx *x862-arg-y*
+                                       char *x862-arg-z*)
+    (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+      (256
+       (! %set-scharcode8 src unscaled-idx char))
+      (t 
+       (! %set-scharcode32 src unscaled-idx char)))
+    (when vreg (<- char)) 
+    (^)))
+
+(defx862 x862-%scharcode %scharcode (seg vreg xfer str idx)
+  (multiple-value-bind (src unscaled-idx)
+      (x862-two-untargeted-reg-forms seg str *x862-arg-y* idx *x862-arg-z*)
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (case (arch::target-char-code-limit (backend-target-arch *target-backend*))
+          (256 (! %scharcode8 target src unscaled-idx))
+          (t (! %scharcode32 target src unscaled-idx)))))
+    (^)))
+
+      
+
+(defx862 x862-code-char code-char (seg vreg xfer c)
+  (let* ((reg (x862-one-untargeted-reg-form seg c *x862-arg-z*)))
+    ;; Typecheck even if result unused.
+    (! require-char-code reg)
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (! fixnum->char target reg)))
+    (^)))
+
+(defx862 x862-%valid-code-char %valid-code-char (seg vreg xfer c)
+  (let* ((reg (x862-one-untargeted-reg-form seg c *x862-arg-z*)))
+    (when *x862-full-safety* (! require-char-code reg))
+    (if vreg
+      (ensuring-node-target (target vreg)
+        (! code-char->char target reg)))
+    (^)))
+
+(defun x862-eq-test (seg vreg xfer cc form1 form2)
+  (with-x86-local-vinsn-macros (seg)
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+      (let* ((f1 (acode-unwrapped-form form1))
+             (f2 (acode-unwrapped-form form2)))
+        (cond ((or (nx-null f1 )
+                   (nx-t f1)
+                   (and (acode-p f1)
+                        (eq (acode-operator f1) (%nx1-operator immediate))))
+               (x862-compare-register-to-constant seg vreg xfer (x862-one-untargeted-reg-form seg form2 ($ *x862-arg-z*)) cr-bit true-p f1))
+              ((or (nx-null f2)
+                   (nx-t f2)
+                   (and (acode-p f2)
+                        (eq (acode-operator f2) (%nx1-operator immediate))))
+               (x862-compare-register-to-constant seg vreg xfer
+                                                  (x862-one-untargeted-reg-form seg form1 ($ *x862-arg-z*))
+                                                  cr-bit true-p f2))
+              (t (x862-compare seg vreg xfer form1 form2 cr-bit true-p)))))))
+
+(defx862 x862-eq eq (seg vreg xfer cc form1 form2)
+  (x862-eq-test seg vreg xfer cc form1 form2))
+
+(defx862 x862-neq neq (seg vreg xfer cc form1 form2)
+  (x862-eq-test seg vreg xfer cc form1 form2))
+
+(defx862 x862-numcmp numcmp (seg vreg xfer cc form1 form2)
+  (let* ((name (ecase (cadr cc)
+                 (:eq '=-2)
+                 (:ne '/=-2)
+                 (:lt '<-2)
+                 (:le '<=-2)
+                 (:gt '>-2)
+                 (:ge '>=-2))))
+    (if (or (x862-explicit-non-fixnum-type-p form1)
+            (x862-explicit-non-fixnum-type-p form2))
+      (x862-binary-builtin seg vreg xfer name form1 form2)
+      (let* ((fix1 (acode-fixnum-form-p form1))
+             (fix2 (acode-fixnum-form-p form2)))
+        (if (and fix1 fix2)
+          (if (funcall name fix1 fix2)
+            (x862-t seg vreg xfer)
+            (x862-nil seg vreg xfer))
+          (x862-inline-numcmp seg vreg xfer cc name form1 form2))))))
+
+(defun x862-inline-numcmp (seg vreg xfer cc name form1 form2)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((fix1 (acode-fixnum-form-p form1))
+           (fix2 (acode-fixnum-form-p form2))
+           (fixval (or fix1 fix2))
+           (fiximm (if fixval (<= (integer-length fixval)
+                                  (- 31 *x862-target-fixnum-shift*))))
+           (otherform (when fiximm (if fix1 form2 form1)))
+           (out-of-line (backend-get-next-label))
+           (done (backend-get-next-label)))
+      (if otherform
+        (x862-one-targeted-reg-form seg otherform ($ *x862-arg-y*))
+        (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*)))
+      (if otherform
+        (unless (acode-fixnum-form-p otherform)
+          (! branch-unless-arg-fixnum ($ *x862-arg-y*) (aref *backend-labels* out-of-line)))
+        (if (acode-fixnum-form-p form1)
+          (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line))
+          (if (acode-fixnum-form-p form2)
+            (! branch-unless-arg-fixnum ($ *x862-arg-y*) (aref *backend-labels* out-of-line))  
+            (! branch-unless-both-args-fixnums ($ *x862-arg-y*) ($ *x862-arg-z*) (aref *backend-labels* out-of-line)))))
+      (if otherform
+        (if (zerop fixval)
+          (! compare-reg-to-zero ($ *x862-arg-y*))
+          (! compare-s32-constant ($ *x862-arg-y*) (ash fixval *x862-target-fixnum-shift*)))
+        (! compare ($ *x862-arg-y*) ($ *x862-arg-z*)))
+      (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+        (when otherform
+          (unless (or (and fix2 (not fix1)) (eq cr-bit x86::x86-e-bits))
+            (setq cr-bit (x862-reverse-cr-bit cr-bit))))
+        (if (not true-p)
+          (setq cr-bit (logxor 1 cr-bit)))
+        (! cr-bit->boolean ($ *x862-arg-z*) cr-bit)
+        (-> done)
+        (@ out-of-line)
+        (when otherform
+          (x862-lri seg ($ *x862-arg-z*) (ash fixval *x862-target-fixnum-shift*))
+          (unless (or fix2 (eq cr-bit x86::x86-e-bits))
+            (! xchg-registers ($ *x862-arg-z*) ($ *x862-arg-y*))))
+        (let* ((index (arch::builtin-function-name-offset name))
+               (idx-subprim (x862-builtin-index-subprim index)))
+          (! call-subprim-2 ($ *x862-arg-z*) idx-subprim ($ *x862-arg-y*) ($ *x862-arg-z*)))
+        (@ done)
+        (<- ($ *x862-arg-z*))
+        (^)))))
+         
+        
+    
+
+(defx862 x862-%word-to-int %word-to-int (seg vreg xfer form)
+  (if (null vreg)
+    (x862-form seg nil xfer form)
+    (progn
+      (ensuring-node-target (target vreg)
+        (! sign-extend-halfword target (x862-one-untargeted-reg-form seg form *x862-arg-z*)))
+      (^))))
+
+(defx862 x862-multiple-value-list multiple-value-list (seg vreg xfer form)
+  (x862-multiple-value-body seg form)
+  (! list)
+  (when vreg
+    (<- *x862-arg-z*))
+  (^))
+
+(defx862 x862-immform immediate (seg vreg xfer form)
+  (x862-immediate seg vreg xfer form))
+
+(pushnew (%nx1-operator lexical-reference) *x862-operator-supports-push*)
+(defx862 x862-lexical-reference lexical-reference (seg vreg xfer varnode)
+  (let* ((ea-or-form (var-ea varnode)))
+    (if (and (acode-punted-var-p varnode) (not (fixnump ea-or-form)))
+      (if (or (not (eq vreg :push))
+              (x862-acode-operator-supports-push ea-or-form))
+        (x862-form seg vreg xfer ea-or-form)
+        (ensuring-node-target (target vreg)
+          (x862-form seg target xfer ea-or-form)
+          (! vpush-register target)))
+      (let* ((cell (x862-lookup-var-cell varnode)))
+        (if (and cell (typep cell 'lcell))
+          (if (x862-ensure-lcell-offset cell (logand ea-or-form #xffff))
+            (and nil (format t "~& could use cell ~s for var ~s" cell (var-name varnode)))
+            (if (logbitp x862-debug-verbose-bit *x862-debug-mask*)
+              (compiler-bug "wrong ea for lcell for var ~s: got ~d, expected ~d" 
+                            (var-name varnode) (calc-lcell-offset cell) (logand ea-or-form #xffff))))
+          (if (not cell)
+            (when (memory-spec-p ea-or-form)
+              (if (logbitp x862-debug-verbose-bit *x862-debug-mask*)
+                (compiler-bug "no lcell for ~s." (var-name varnode))))))
+        (unless (or (typep ea-or-form 'lreg) (fixnump ea-or-form))
+          (compiler-bug "bogus ref to var ~s (~s) : ~s " varnode (var-name varnode) ea-or-form))
+        (x862-do-lexical-reference seg vreg ea-or-form)
+        (^)))))
+
+(defx862 x862-setq-lexical setq-lexical (seg vreg xfer varspec form)
+  (let* ((ea (var-ea varspec)))
+    ;(unless (fixnump ea) compiler-bug "setq lexical is losing BIG"))
+    (let* ((valreg (x862-one-untargeted-reg-form seg form (if (and (register-spec-p ea) 
+                                                                   (or (null vreg) (eq ea vreg)))
+                                                            ea
+                                                            *x862-arg-z*))))
+      (x862-do-lexical-setq seg vreg ea valreg))
+    (^)))
+
+
+
+(pushnew (%nx1-operator fixnum) *x862-operator-supports-push*)
+(defx862 x862-fixnum fixnum (seg vreg xfer value)
+  (if (null vreg)
+    (^)
+    (if (eq vreg :push)
+      (let* ((boxed (ash value *x862-target-fixnum-shift*)))
+        (if (typep boxed '(signed-byte 32))
+          (! vpush-fixnum boxed)
+          (with-node-target () target
+            (x862-absolute-natural seg target nil boxed)
+            (! vpush-register target)))
+        (^))
+      (let* ((class (hard-regspec-class vreg))
+             (mode (get-regspec-mode vreg))
+             (unboxed (if (= class hard-reg-class-gpr)
+                        (not (or (= hard-reg-class-gpr-mode-node mode)
+                                 (= hard-reg-class-gpr-mode-address mode))))))
+        (if unboxed
+          (x862-absolute-natural seg vreg xfer value)
+          (if (= class hard-reg-class-crf)
+            (progn
+                                        ;compiler-bug "Would have clobbered a GPR!")
+              (x862-branch seg (x862-cd-true xfer)))
+            (progn
+              (ensuring-node-target (target vreg)
+                (x862-absolute-natural seg target nil (ash value *x862-target-fixnum-shift*)))
+              (^))))))))
+
+(defx862 x862-%ilogbitp %ilogbitp (seg vreg xfer cc bitnum form)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil bitnum)
+      (x862-form seg vreg xfer form))
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+      (unless (eq cr-bit x86::x86-e-bits)
+        (bug "bad cr-bit"))
+      (setq cr-bit x86::x86-b-bits true-p (not true-p))
+      (let* ((fixbit (acode-fixnum-form-p bitnum)))
+        (if fixbit
+          (let* ((reg (x862-one-untargeted-reg-form seg form *x862-arg-z*))
+                 (x86-bit (min (+ fixbit *x862-target-fixnum-shift*) (1- *x862-target-bits-in-word*))))
+            (! set-c-flag-if-constant-logbitp x86-bit reg))
+          (multiple-value-bind (rbit rform) (x862-two-untargeted-reg-forms seg bitnum *x862-arg-y* form *x862-arg-z*)
+            (! set-c-flag-if-variable-logbitp rbit rform)))
+        (regspec-crf-gpr-case 
+         (vreg dest)
+         (^ cr-bit true-p)
+         (progn
+           (ensuring-node-target (target dest)
+             (if (not true-p)
+               (setq cr-bit (logxor 1 cr-bit)))
+             (! cr-bit->boolean target cr-bit))
+           (^)))))))
+
+
+(defx862 x862-uvref uvref (seg vreg xfer vector index)
+  (x862-two-targeted-reg-forms seg vector ($ *x862-arg-y*) index ($ *x862-arg-z*))
+  (! misc-ref)
+  (<- ($ *x862-arg-z*))
+  (^))
+
+(defx862 x862-uvset uvset (seg vreg xfer vector index value)
+  (x862-three-targeted-reg-forms seg
+				 vector (target-arch-case
+					 (:x8632 ($ x8632::temp0))
+					 (:x8664 ($ x8664::arg_x)))
+				 index ($ *x862-arg-y*)
+				 value ($ *x862-arg-z*))
+  (! misc-set)
+  (<- ($ *x862-arg-z*))
+  (^))
+
+(defx862 x862-%decls-body %decls-body (seg vreg xfer form p2decls)
+  (with-x86-p2-declarations p2decls
+    (x862-form seg vreg xfer form)))
+
+
+
+(defx862 x862-%err-disp %err-disp (seg vreg xfer arglist)
+  (let* ((*x862-vstack* *x862-vstack*))
+    (x862-set-nargs seg (x862-arglist seg arglist))
+    (! ksignalerr))
+  (x862-nil seg vreg xfer))
+
+
+(defx862 x862-local-tagbody local-tagbody (seg vreg xfer taglist body)
+  (let* ((encstack (x862-encode-stack))
+         (tagop (%nx1-operator tag-label)))
+    (dolist (tag taglist)
+      (rplacd tag (cons (backend-get-next-label) (cons encstack (cadr (cddr (cddr tag)))))))
+    (dolist (form body)
+      (if (eq (acode-operator form) tagop)
+        (let ((tag (cddr form)))
+          (when (cddr tag) (! align-loop-head))
+          (@ (car tag)))
+        (x862-form seg nil nil form)))
+    (x862-nil seg vreg xfer)))
+
+(defx862 x862-call call (seg vreg xfer fn arglist &optional spread-p)
+  (when (and (null vreg)
+             (acode-p fn)
+             (eq (acode-operator fn) (%nx1-operator immediate)))
+    (let* ((name (cadr fn)))
+      (when (memq name *warn-if-function-result-ignored*)
+        (p2-whine *x862-cur-afunc*  :result-ignored name))))
+  (x862-call-fn seg vreg xfer fn arglist spread-p))
+
+(defx862 x862-self-call self-call (seg vreg xfer arglist &optional spread-p)
+  (setq arglist (x862-augment-arglist *x862-cur-afunc* arglist (if spread-p 1 *x862-target-num-arg-regs*)))
+  (x862-call-fn seg vreg xfer -2 arglist spread-p))
+
+
+(defx862 x862-lexical-function-call lexical-function-call (seg vreg xfer afunc arglist &optional spread-p)
+  (x862-call-fn seg vreg xfer (list (%nx1-operator simple-function) afunc)
+                (x862-augment-arglist afunc arglist (if spread-p 1 *x862-target-num-arg-regs*))
+                spread-p))
+
+(defx862 x862-builtin-call builtin-call (seg vreg xfer index arglist)
+  (let* ((nargs (x862-arglist seg arglist))
+         (tail-p (and (x862-tailcallok xfer) (<= nargs *x862-target-num-arg-regs*)))
+         (idx (acode-fixnum-form-p index))
+         (idx-subprim (x862-builtin-index-subprim idx))
+         (subprim
+          (or idx-subprim
+              (case nargs
+                (0 (subprim-name->offset '.SPcallbuiltin0))
+                (1 (subprim-name->offset '.SPcallbuiltin1))
+                (2 (subprim-name->offset '.SPcallbuiltin2))
+                (3 (subprim-name->offset '.SPcallbuiltin3))
+                (t (subprim-name->offset '.SPcallbuiltin))))))
+    (when tail-p
+      (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count*)
+      (x862-restore-full-lisp-context seg))
+    (unless idx-subprim
+      (! lri *x862-imm0* (ash idx *x862-target-fixnum-shift*))
+      (when (eql subprim (subprim-name->offset '.SPcallbuiltin))
+        (x862-set-nargs seg nargs)))
+    (if tail-p
+      (! jump-subprim subprim)
+      (progn
+        (! call-subprim subprim)
+        (<- *x862-arg-z*)
+        (^)))))
+      
+
+(defx862 x862-if if (seg vreg xfer testform true false &aux test-val)
+  (if (setq test-val (nx2-constant-form-value (acode-unwrapped-form-value testform)))
+    (x862-form seg vreg xfer (if (nx-null test-val) false true))
+    (let* ((cstack *x862-cstack*)
+           (vstack *x862-vstack*)
+           (top-lcell *x862-top-vstack-lcell*)
+           (entry-stack (x862-encode-stack))
+           (true-stack nil)
+           (false-stack nil)
+           (true-cleanup-label nil)
+           (same-stack-effects nil)
+           (true-is-goto (x862-go-label true))
+           (false-is-goto (and (not true-is-goto) (x862-go-label false)))
+           (endlabel (backend-get-next-label))
+           (falselabel (backend-get-next-label))
+           (need-else (unless false-is-goto (or (not (nx-null false)) (x862-for-value-p vreg))))
+           (both-single-valued (and (not *x862-open-code-inline*)
+                                    (eq xfer $backend-return)
+                                    (x862-for-value-p vreg)
+                                    need-else
+                                    (x862-single-valued-form-p true) 
+                                    (x862-single-valued-form-p false))))
+      (if (eq 0 xfer) 
+        (setq xfer nil))
+      (if both-single-valued            ; it's implied that we're returning
+        (let* ((result *x862-arg-z*))
+          (let ((merge-else-branch-label (if (nx-null false) (x862-find-nilret-label))))
+            (x862-conditional-form seg (x862-make-compound-cd 0 falselabel) testform)
+            (x862-form seg result endlabel true)
+            (if (and merge-else-branch-label (neq -1 (aref *backend-labels* merge-else-branch-label)))
+              (backend-copy-label merge-else-branch-label falselabel)
+              (progn
+                (@ falselabel)
+                (if (nx-null false) (@ (x862-record-nilret-label)))
+                (x862-form seg result nil false)))
+            (@ endlabel)
+            (<- result)
+            (^)))
+        (progn
+          (if (and need-else (x862-mvpass-p xfer))
+            (setq true-cleanup-label (backend-get-next-label)))         
+          (x862-conditional-form 
+           seg
+           (x862-make-compound-cd 
+            (or true-is-goto 0)
+            (or false-is-goto 
+                (if need-else 
+                  (if true-is-goto 0 falselabel) 
+                  (if true-is-goto xfer (x862-cd-merge xfer falselabel))))) 
+           testform)  
+          (if true-is-goto
+            (x862-unreachable-store)
+            (if true-cleanup-label
+              (progn
+                (x862-open-undo $undomvexpect)
+                (x862-form seg vreg (logior $backend-mvpass-mask true-cleanup-label) true))
+              (x862-form seg vreg (if need-else (x862-cd-merge xfer endlabel) xfer) true)))
+          (setq true-stack (x862-encode-stack))
+          (setq *x862-cstack* cstack)
+          (x862-set-vstack vstack)
+          (setq *x862-top-vstack-lcell* top-lcell)
+          (if false-is-goto (x862-unreachable-store))
+          (let ((merge-else-branch-label (if (and (nx-null false) (eq xfer $backend-return)) (x862-find-nilret-label))))
+            (if (and merge-else-branch-label (neq -1 (aref *backend-labels* merge-else-branch-label)))
+              (backend-copy-label merge-else-branch-label falselabel)
+              (progn
+                (@ falselabel)
+                (when need-else
+                  (if true-cleanup-label
+                    (x862-mvpass seg false)
+                    (x862-form seg vreg xfer false))
+                  (setq false-stack (x862-encode-stack))))))
+          (when true-cleanup-label
+            (if (setq same-stack-effects (x862-equal-encodings-p true-stack false-stack)) ; can share cleanup code
+              (@ true-cleanup-label))
+            (let* ((*x862-returning-values* :pass))
+              (x862-nlexit seg xfer 1)
+              (x862-branch seg (if (and xfer (neq xfer $backend-mvpass-mask)) xfer (if (not same-stack-effects) endlabel))))
+            (unless same-stack-effects
+              (@ true-cleanup-label)
+              (multiple-value-setq (true *x862-cstack* *x862-vstack* *x862-top-vstack-lcell*)
+                (x862-decode-stack true-stack))
+              (let* ((*x862-returning-values* :pass))
+                (x862-nlexit seg xfer 1)
+                (^)))
+            (x862-close-undo)
+            (multiple-value-setq (*x862-undo-count* *x862-cstack* *x862-vstack* *x862-top-vstack-lcell*) 
+              (x862-decode-stack entry-stack)))
+          (@ endlabel))))))
+
+(defx862 x862-or or (seg vreg xfer forms)
+  (let* ((mvpass (x862-mvpass-p xfer))
+         (tag1 (backend-get-next-label))
+         (tag2 (backend-get-next-label))
+         (vstack *x862-vstack*)
+         (cstack *x862-cstack*)
+         (dest (if (backend-crf-p vreg) vreg (if vreg *x862-arg-z* (available-crf-temp *available-backend-crf-temps*))))
+         (cd1 (x862-make-compound-cd 
+               (if (eq dest *x862-arg-z*) tag1 (x862-cd-merge (x862-cd-true xfer) tag1)) 0)))
+    (while (cdr forms)
+      (x862-form seg dest (if (eq dest *x862-arg-z*) nil cd1) (car forms))
+      (when (eq dest *x862-arg-z*)
+        (with-crf-target () val-crf
+          (x862-copy-register seg val-crf dest)
+          (x862-branch seg cd1)))
+      (setq forms (%cdr forms)))
+    (if mvpass
+      (progn (x862-multiple-value-body seg (car forms)) 
+             (let* ((*x862-returning-values* t)) (x862-branch seg (x862-cd-merge xfer tag2))))
+      (x862-form seg  vreg (if (eq dest *x862-arg-z*) (x862-cd-merge xfer tag2) xfer) (car forms)))
+    (setq *x862-vstack* vstack *x862-cstack* cstack)
+    (@ tag1)
+    (when (eq dest *x862-arg-z*)
+      (<- *x862-arg-z*)
+      (^))
+    (@ tag2)))
+
+(defx862 x862-simple-function simple-function (seg vreg xfer afunc)
+  (x862-immediate seg vreg xfer (x862-afunc-lfun-ref afunc)))
+
+(defx862 x862-list list (seg vreg xfer arglist)
+  (if (null vreg)
+    (dolist (form arglist)
+      (x862-form seg vreg nil form)) 
+    (let* ((*x862-vstack* *x862-vstack*)
+           (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+           (nargs (x862-formlist seg arglist nil)))
+      (x862-set-nargs seg nargs)
+      (! list)
+      (<- *x862-arg-z*)))
+  (^))
+
+(defx862 x862-list* list* (seg vreg xfer arglist)
+  (if (null vreg)
+    (dolist (arg (apply #'append arglist))
+      (x862-form seg nil nil arg))
+    (let* ((*x862-vstack* *x862-vstack*)
+           (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+           (nargs (x862-formlist seg (car arglist) (cadr arglist))))
+      (declare (fixnum nargs))
+      (when (> nargs 1)
+        (x862-set-nargs seg (1- nargs))
+        (! list*))
+      (<- *x862-arg-z*)))
+  (^))
+
+(defx862 x862-minus1 minus1 (seg vreg xfer form)
+  (x862-unary-builtin seg vreg xfer '%negate form))
+
+;;; Return T if form is declare to be something that couldn't be a fixnum.
+(defun x862-explicit-non-fixnum-type-p (form)
+  (let* ((type (x862-form-type form))
+         (target-fixnum-type (nx-target-type 'fixnum)))
+    (and (not (subtypep type target-fixnum-type))
+         (not (subtypep target-fixnum-type type)))))
+
+(defun x862-inline-sub2 (seg vreg xfer form1 form2)
+  (let* ((v2 (acode-fixnum-form-p form2)))
+    (if (and v2 (not (eql v2 most-negative-fixnum)))
+      (x862-inline-add2 seg vreg xfer form1 (make-acode (%nx1-operator fixnum) (- v2)))
+      (with-x86-local-vinsn-macros (seg vreg xfer)
+        (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*))
+    (let* ((out-of-line (backend-get-next-label))
+           (done (backend-get-next-label)))
+      (ensuring-node-target (target vreg)
+        (if (acode-fixnum-form-p form1)
+          (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line))
+          (if (acode-fixnum-form-p form2)
+            (! branch-unless-arg-fixnum ($ *x862-arg-y*) (aref *backend-labels* out-of-line))  
+            (! branch-unless-both-args-fixnums ($ *x862-arg-y*) ($ *x862-arg-z*) (aref *backend-labels* out-of-line))))
+        (! fixnum-sub2 ($ *x862-arg-z*) ($ *x862-arg-y*) ($ *x862-arg-z*))
+        (x862-check-fixnum-overflow seg ($ *x862-arg-z*) done)
+        (@ out-of-line)
+        (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-minus) ($ *x862-arg-y*) ($ *x862-arg-z*))
+        (@ done)
+        (x862-copy-register seg target ($ *x862-arg-z*)))
+      (^))))))
+
+(defun x862-inline-add2 (seg vreg xfer form1 form2)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((c1 (acode-fixnum-form-p form1))
+	   (c2 (acode-fixnum-form-p form2))
+	   (fix1 (s32-fixnum-constant-p c1))
+	   (fix2 (s32-fixnum-constant-p c2))
+	   (otherform (if fix1
+			form2
+			(if fix2
+			  form1))))
+      (if otherform
+        (x862-one-targeted-reg-form seg otherform ($ *x862-arg-z*))
+        (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*)))
+      (let* ((out-of-line (backend-get-next-label))
+             (done (backend-get-next-label)))
+        (ensuring-node-target (target vreg)
+          (if otherform
+            (unless (acode-fixnum-form-p otherform)
+              (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line)))          
+            (if (acode-fixnum-form-p form1)
+              (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line))
+              (if (acode-fixnum-form-p form2)
+                (! branch-unless-arg-fixnum ($ *x862-arg-y*) (aref *backend-labels* out-of-line))  
+                (! branch-unless-both-args-fixnums ($ *x862-arg-y*) ($ *x862-arg-z*) (aref *backend-labels* out-of-line)))))
+          (if otherform
+            (! add-constant ($ *x862-arg-z*) (ash (or fix1 fix2) *x862-target-fixnum-shift*))
+            (! fixnum-add2 ($ *x862-arg-z*) ($ *x862-arg-y*)))
+          (x862-check-fixnum-overflow seg ($ *x862-arg-z*) done)
+          (@ out-of-line)
+          (if otherform
+            (x862-lri seg ($ *x862-arg-y*) (ash (or fix1 fix2) *x862-target-fixnum-shift*)))
+          (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-plus) ($ *x862-arg-y*) ($ *x862-arg-z*))
+          (@ done)
+          (x862-copy-register seg target ($ *x862-arg-z*)))
+        (^)))))
+           
+(defx862 x862-add2 add2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *x862-trust-declarations*)
+    (if (and (x862-form-typep form1 'double-float)
+             (x862-form-typep form2 'double-float))
+      (x862-use-operator (%nx1-operator %double-float+-2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (x862-form-typep form1 'single-float)
+               (x862-form-typep form2 'single-float))
+        (x862-use-operator (%nx1-operator %short-float+-2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+        (if (and (x862-form-typep form1 'fixnum)
+                 (x862-form-typep form2 'fixnum))
+          (x862-use-operator (%nx1-operator %i+)
+                             seg
+                             vreg
+                             xfer
+                             form1
+                             form2
+                             t)
+          (if (or (x862-explicit-non-fixnum-type-p form1)
+                  (x862-explicit-non-fixnum-type-p form2))
+            (x862-binary-builtin seg vreg xfer '+-2 form1 form2)
+            (x862-inline-add2 seg vreg xfer form1 form2)))))))
+
+(defx862 x862-sub2 sub2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *x862-trust-declarations*)
+    (if (and (x862-form-typep form1 'double-float)
+             (x862-form-typep form2 'double-float))
+      (x862-use-operator (%nx1-operator %double-float--2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (x862-form-typep form1 'single-float)
+               (x862-form-typep form2 'single-float))
+        (x862-use-operator (%nx1-operator %short-float--2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+        (if (and (x862-form-typep form1 'fixnum)
+                 (x862-form-typep form2 'fixnum))
+          (x862-use-operator (%nx1-operator %i-)
+                             seg
+                             vreg
+                             xfer
+                             form1
+                             form2
+                             t)
+          (if (or (x862-explicit-non-fixnum-type-p form1)
+                  (x862-explicit-non-fixnum-type-p form2))
+            (x862-binary-builtin seg vreg xfer '--2 form1 form2)
+            (x862-inline-sub2 seg vreg xfer form1 form2)))))))
+
+(defx862 x862-mul2 mul2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *x862-trust-declarations*)
+    (if (and (x862-form-typep form1 'double-float)
+             (x862-form-typep form2 'double-float))
+      (x862-use-operator (%nx1-operator %double-float*-2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (x862-form-typep form1 'single-float)
+               (x862-form-typep form2 'single-float))
+        (x862-use-operator (%nx1-operator %short-float*-2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+        (x862-binary-builtin seg vreg xfer '*-2 form1 form2)))))
+
+(defx862 x862-div2 div2 (seg vreg xfer form1 form2)
+  (multiple-value-bind (form1 form2)
+      (nx-binop-numeric-contagion form1 form2 *x862-trust-declarations*)
+    (if (and (x862-form-typep form1 'double-float)
+             (x862-form-typep form2 'double-float))
+      (x862-use-operator (%nx1-operator %double-float/-2)
+                         seg
+                         vreg
+                         xfer
+                         form1
+                         form2)
+      (if (and (x862-form-typep form1 'single-float)
+               (x862-form-typep form2 'single-float))
+        (x862-use-operator (%nx1-operator %short-float/-2)
+                           seg
+                           vreg
+                           xfer
+                           form1
+                           form2)
+                (let* ((f2 (acode-fixnum-form-p form2))
+               (unwrapped (acode-unwrapped-form form1))
+               (f1 nil)
+               (f1/f2 nil))
+          (if (and f2
+                   (not (zerop f2))
+                   (acode-p unwrapped)
+                   (or (eq (acode-operator unwrapped) (%nx1-operator mul2))
+                       (eq (acode-operator unwrapped) (%nx1-operator %i*)))
+                   (setq f1 (acode-fixnum-form-p (cadr unwrapped)))
+                   (typep (setq f1/f2 (/ f1 f2)) 'fixnum))
+            (x862-use-operator (%nx1-operator mul2)
+                               seg
+                               vreg
+                               xfer
+                               (make-acode (%nx1-operator fixnum) f1/f2)
+                               (caddr unwrapped))
+            (x862-binary-builtin seg vreg xfer '/-2 form1 form2)))))))
+
+(defx862 x862-logbitp logbitp (seg vreg xfer bitnum int)
+  (x862-binary-builtin seg vreg xfer 'logbitp bitnum int))
+
+(defun x862-inline-logior2 (seg vreg xfer form1 form2)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((fix1 (acode-fixnum-form-p form1))
+           (fix2 (acode-fixnum-form-p form2)))
+      (if (and fix1 fix2)
+        (x862-use-operator (%nx1-operator fixnum) seg vreg xfer (logior fix1 fix2))
+        (let* ((fixval (or fix1 fix2))
+               (fiximm (if fixval (<= (integer-length fixval)
+                                      (- 31 *x862-target-fixnum-shift*))))
+               (otherform (when fiximm (if fix1 form2 form1))))
+          (let* ((out-of-line (backend-get-next-label))
+                 (done (backend-get-next-label)))
+            (ensuring-node-target (target vreg)
+              (if otherform
+                (x862-one-targeted-reg-form seg otherform ($ *x862-arg-z*))
+                (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*)))
+              (if otherform
+                (unless (acode-fixnum-form-p otherform)
+                  (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line)))
+                (if (acode-fixnum-form-p form1)
+                  (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line))
+                  (if (acode-fixnum-form-p form2)
+                    (! branch-unless-arg-fixnum ($ *x862-arg-y*) (aref *backend-labels* out-of-line))  
+                    (! branch-unless-both-args-fixnums ($ *x862-arg-y*) ($ *x862-arg-z*) (aref *backend-labels* out-of-line)))))
+              (if otherform
+                (! %logior-c ($ *x862-arg-z*) ($ *x862-arg-z*) (ash fixval *x862-target-fixnum-shift*))
+                (! %logior2 ($ *x862-arg-z*) ($ *x862-arg-z*) ($ *x862-arg-y*)))
+              (-> done)
+              (@ out-of-line)
+              (if otherform
+                (x862-lri seg ($ *x862-arg-y*) (ash fixval *x862-target-fixnum-shift*)))
+              (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-logior) ($ *x862-arg-y*) ($ *x862-arg-z*))
+              (@ done)
+              (x862-copy-register seg target ($ *x862-arg-z*)))
+            (^)))))))
+
+(defx862 x862-logior2 logior2 (seg vreg xfer form1 form2)
+  (if (or (x862-explicit-non-fixnum-type-p form1)
+          (x862-explicit-non-fixnum-type-p form2))
+    (x862-binary-builtin seg vreg xfer 'logior-2 form1 form2)
+    (x862-inline-logior2 seg vreg xfer form1 form2)))
+
+(defx862 x862-logxor2 logxor2 (seg vreg xfer form1 form2)
+  (x862-binary-builtin seg vreg xfer 'logxor-2 form1 form2))
+
+(defun x862-inline-logand2 (seg vreg xfer form1 form2)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((fix1 (acode-fixnum-form-p form1))
+           (fix2 (acode-fixnum-form-p form2)))
+      (if (and fix1 fix2)
+        (x862-use-operator (%nx1-operator fixnum) seg vreg xfer (logand fix1 fix2))
+        (let* ((fixval (or fix1 fix2))
+               (fiximm (if fixval (<= (integer-length fixval)
+                                      (- 31 *x862-target-fixnum-shift*))))
+               (otherform (when fiximm (if fix1 form2 form1))))
+          (let* ((out-of-line (backend-get-next-label))
+                 (done (backend-get-next-label)))
+            (ensuring-node-target (target vreg)
+              (if otherform
+                (x862-one-targeted-reg-form seg otherform ($ *x862-arg-z*))
+                (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*)))
+              (if otherform
+                (unless (acode-fixnum-form-p otherform)
+                  (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line)))
+                (if (acode-fixnum-form-p form1)
+                  (! branch-unless-arg-fixnum ($ *x862-arg-z*) (aref *backend-labels* out-of-line))
+                  (if (acode-fixnum-form-p form2)
+                    (! branch-unless-arg-fixnum ($ *x862-arg-y*) (aref *backend-labels* out-of-line))  
+                    (! branch-unless-both-args-fixnums ($ *x862-arg-y*) ($ *x862-arg-z*) (aref *backend-labels* out-of-line)))))
+              (if otherform
+                (! %logand-c ($ *x862-arg-z*) ($ *x862-arg-z*) (ash fixval *x862-target-fixnum-shift*))
+                (! %logand2 ($ *x862-arg-z*) ($ *x862-arg-z*) ($ *x862-arg-y*)))
+              (-> done)
+              (@ out-of-line)
+              (if otherform
+                (x862-lri seg ($ *x862-arg-y*) (ash fixval *x862-target-fixnum-shift*)))
+              (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-logand) ($ *x862-arg-y*) ($ *x862-arg-z*))
+              (@ done)
+              (x862-copy-register seg target ($ *x862-arg-z*)))
+            (^)))))))
+
+(defx862 x862-logand2 logand2 (seg vreg xfer form1 form2)
+    (if (or (x862-explicit-non-fixnum-type-p form1)
+            (x862-explicit-non-fixnum-type-p form2))
+      (x862-binary-builtin seg vreg xfer 'logand-2 form1 form2)
+      (x862-inline-logand2 seg vreg xfer form1 form2)))
+
+(defx862 x862-%quo2 %quo2 (seg vreg xfer form1 form2)
+  (x862-binary-builtin seg vreg xfer '/-2 form1 form2))
+
+(defx862 x862-%aref1 %aref1 (seg vreg xfer v i)
+  (let* ((vtype (acode-form-type v t))
+         (ctype (if vtype (specifier-type vtype)))
+         (atype (if (array-ctype-p ctype) ctype))
+         (keyword (if (and atype
+                           (let* ((dims (array-ctype-dimensions atype)))
+                             (or (eq dims '*)
+                                 (and (not (atom dims))
+                                      (= (length dims) 1))))
+                           (not (array-ctype-complexp atype)))
+                    (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (if keyword
+      (x862-vref  seg vreg xfer keyword v i (unless *x862-reckless*
+                                              (nx-lookup-target-uvector-subtag keyword)))
+      (x862-binary-builtin seg vreg xfer '%aref1 v i))))
+
+(defx862 x862-%aset1 aset1 (seg vreg xfer v i n)
+  (let* ((vtype (acode-form-type v t))
+         (atype (if vtype (specifier-type vtype)))
+         (keyword (if (and atype
+                           (let* ((dims (array-ctype-dimensions atype)))
+                             (or (eq dims '*)
+                                 (and (not (atom dims))
+                                      (= (length dims) 1))))
+                           (not (array-ctype-complexp atype)))
+                    (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (if keyword
+      (x862-vset seg vreg xfer keyword v i n (not *x862-reckless*))
+      (target-arch-case
+       (:x8632
+	(with-x86-local-vinsn-macros (seg vreg xfer)
+	  (let* ((subprim (subprim-name->offset '.SPaset1))
+		 (tail-p (x862-tailcallok xfer)))
+	    (x862-three-targeted-reg-forms seg
+					   v ($ x8632::temp0)
+					   i ($ x8632::arg_y)
+					   n ($ x8632::arg_z))
+	    (if tail-p
+	      (progn
+		(x862-restore-full-lisp-context seg)
+		(! jump-subprim subprim))
+	      (progn
+		(! call-subprim subprim)
+		(when vreg
+		  (<- ($ x8632::arg_z)))
+		(^))))))
+       (:x8664
+	(x862-ternary-builtin seg vreg xfer '%aset1 v i n))))))
+
+;;; Return VAL if its a fixnum whose boxed representation fits in 32
+;;; bits.  (On a 32-bit platform, that's true of all native fixnums.)
+(defun s32-fixnum-constant-p (val)
+  (when val
+    (target-arch-case
+     (:x8632
+      ;; On x8632, all fixnums fit in 32 bits.
+      val)
+     (:x8664
+      (if (typep val '(signed-byte #.(- 32 x8664::fixnumshift)))
+        val)))))
+
+(defx862 x862-%i+ %i+ (seg vreg xfer form1 form2 &optional overflow)
+  (when overflow
+    (let* ((type *x862-target-half-fixnum-type*))
+      (when (and (x862-form-typep form1 type)
+                 (x862-form-typep form2 type))
+        (setq overflow nil))))
+  (cond ((null vreg) 
+         (x862-form seg nil nil form1) 
+         (x862-form seg nil xfer form2))
+        (t                              
+         (let* ((c1 (acode-fixnum-form-p form1))
+                (c2 (acode-fixnum-form-p form2))
+                (fix1 (s32-fixnum-constant-p c1))
+                (fix2 (s32-fixnum-constant-p c2))
+                (other (if fix1                                
+                         form2
+                         (if fix2
+                           form1)))
+                (sum (and c1 c2 (if overflow (+ c1 c2) (%i+ c1 c2)))))
+
+           (if sum
+             (if (nx1-target-fixnump sum)
+               (x862-use-operator (%nx1-operator fixnum) seg vreg nil sum)
+               (x862-use-operator (%nx1-operator immediate) seg vreg nil sum))
+             (if other
+               (let* ((constant (ash (or fix1 fix2) *x862-target-fixnum-shift*))) 
+                 (if (zerop constant)
+                   (x862-form seg vreg nil other)
+                   (if overflow
+                     (ensuring-node-target (target vreg)
+                       (x862-one-targeted-reg-form seg other target)
+                       (! add-constant target constant)
+                       (x862-check-fixnum-overflow seg target))
+                     (ensuring-node-target (target vreg)
+                       (let* ((reg (x862-one-untargeted-reg-form seg other target)))
+                         (! add-constant3 target reg constant))))))
+               (if (not overflow)
+                 (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form1 *x862-arg-y* form2 *x862-arg-z*)
+                   ;; This isn't guaranteed to set the overflow flag,
+                   ;; but may do so.
+                   (ensuring-node-target (target vreg)
+                     (! fixnum-add3 target r1 r2)))
+                 (ensuring-node-target (target vreg)
+                   (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form1 *x862-arg-y* form2 *x862-arg-z*)
+                     (cond ((= (hard-regspec-value target)
+                               (hard-regspec-value r1))
+                            (! fixnum-add2 target r2))
+                           ((= (hard-regspec-value target)
+                               (hard-regspec-value r2))
+                            (! fixnum-add2 target r1))
+                           (t
+                            (x862-copy-register seg target r1)
+                            (! fixnum-add2 target r2)))
+                     (x862-check-fixnum-overflow seg target))))))
+           (^)))))
+
+(defx862 x862-%i- %i- (seg vreg xfer num1 num2 &optional overflow)
+  (when overflow
+    (let* ((type *x862-target-half-fixnum-type*))
+      (when (and (x862-form-typep num1 type)
+                 (x862-form-typep num2 type))
+        (setq overflow nil))))
+  (let* ((v1 (acode-fixnum-form-p num1))
+         (v2 (acode-fixnum-form-p num2)))
+    (if (and v1 v2)
+      (x862-use-operator (%nx1-operator immediate) seg vreg xfer (if overflow (- v1 v2)(%i- v1 v2)))
+      (if (and v2 (/= v2 (arch::target-most-negative-fixnum (backend-target-arch *target-backend*))))
+        (x862-use-operator (%nx1-operator %i+) seg vreg xfer num1 (make-acode (%nx1-operator fixnum) (- v2)) overflow) 
+          (cond
+           ((null vreg)
+            (x862-form seg nil nil num1)
+            (x862-form seg nil xfer num2))
+           (t
+            (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg num1 *x862-arg-y* num2 *x862-arg-z*)
+              ;; This isn't guaranteed to set the overflow flag,
+              ;; but may do so.
+              (ensuring-node-target (target vreg)
+                (! fixnum-sub2 target r1 r2)
+                (if overflow
+                  (x862-check-fixnum-overflow seg target)))
+              (^))))))))
+
+(defx862 x862-%i* %i* (seg vreg xfer num1 num2)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil num1)
+      (x862-form seg nil xfer num2))  
+    (let* ((fix1 (acode-fixnum-form-p num1))
+           (fix2 (acode-fixnum-form-p num2))
+           (other (if (typep fix1 '(signed-byte 32)) num2 (if (typep fix2 '(signed-byte 32)) num1))))
+      (if (and fix1 fix2)
+        (x862-lri seg vreg (ash (* fix1 fix2) *x862-target-fixnum-shift*))
+        (if other
+          (! multiply-immediate vreg (x862-one-untargeted-reg-form seg other *x862-arg-z*) (or fix1 fix2))
+          (multiple-value-bind (rx ry) (x862-two-untargeted-reg-forms seg num1 *x862-arg-y* num2 *x862-arg-z*)
+            (ensuring-node-target (target vreg)
+              (! multiply-fixnums target rx ry)))))
+      (^))))
+
+(defx862 x862-nth-value nth-value (seg vreg xfer n form)
+  (let* ((*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+    (let* ((nreg (x862-one-untargeted-reg-form seg n *x862-arg-z*)))
+      (unless (acode-fixnum-form-p n)
+        (! trap-unless-fixnum nreg))
+      (x862-vpush-register seg nreg))
+     (x862-multiple-value-body seg form) ; sets nargs
+    (! nth-value *x862-arg-z*))
+  (<- *x862-arg-z*)
+  (^))
+
+(defx862 x862-values values (seg vreg xfer forms)
+  (if (eq (list-length forms) 1)
+    (if (x862-cd-compound-p xfer)
+      (x862-form seg vreg xfer (%car forms))
+      (progn
+        (x862-form seg vreg nil (%car forms))
+        (^)))
+    (if (not (x862-mv-p xfer))
+      (if forms
+        (x862-use-operator (%nx1-operator prog1) seg vreg xfer forms)
+        (x862-nil seg vreg xfer))
+      (progn
+        (let* ((*x862-vstack* *x862-vstack*)
+               (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+          (x862-set-nargs seg (x862-formlist seg forms nil)))
+        (let* ((*x862-returning-values* t))
+          (^))))))
+
+(defx862 x862-base-char-p base-char-p (seg vreg xfer cc form)
+  (x862-char-p seg vreg xfer cc form))
+
+(defun x862-char-p (seg vreg xfer cc form)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+      (! mask-base-char *x862-imm0* (x862-one-untargeted-reg-form seg form *x862-arg-z*))
+      (x862-test-reg-%izerop seg vreg xfer *x862-imm0* cr-bit true-p
+                             (target-arch-case
+                              (:x8632 x8632::subtag-character)
+                              (:x8664 x8664::subtag-character))))))
+
+
+
+(defx862 x862-let* let* (seg vreg xfer vars vals body p2decls &aux
+                             (old-stack (x862-encode-stack)))
+  (x862-check-lcell-depth)
+  (with-x86-p2-declarations p2decls
+    (x862-seq-bind seg vars vals)
+    (x862-undo-body seg vreg xfer body old-stack))
+  (dolist (v vars) (x862-close-var seg v)))
+
+(defx862 x862-multiple-value-bind multiple-value-bind (seg vreg xfer vars valform body p2decls)
+  (let* ((n (list-length vars))
+         (vloc *x862-vstack*)
+         (nbytes (* n *x862-target-node-size*))
+         (old-stack (x862-encode-stack)))
+    (with-x86-p2-declarations p2decls
+      (x862-multiple-value-body seg valform)
+      (! fitvals n)
+      (x862-set-vstack (%i+ vloc nbytes))
+      (let* ((old-top *x862-top-vstack-lcell*)
+             (lcells (progn (x862-reserve-vstack-lcells n) (x862-collect-lcells :reserved old-top))))
+        (dolist (var vars)
+          (let* ((lcell (pop lcells))
+                 (reg (nx2-assign-register-var var)))
+            (if reg
+              (x862-init-regvar seg var reg (x862-vloc-ea vloc))
+              (x862-bind-var seg var vloc lcell))          
+            (setq vloc (%i+ vloc *x862-target-node-size*)))))
+      (x862-undo-body seg vreg xfer body old-stack)
+      (dolist (var vars)
+        (x862-close-var seg var)))))
+
+(defx862 x862-debind debind (seg vreg xfer lambda-list bindform req opt rest keys auxen whole body p2decls cdr-p)
+  (declare (ignore lambda-list))
+  (let* ((old-stack (x862-encode-stack))
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+         (vloc *x862-vstack*))
+    (with-x86-p2-declarations p2decls      
+      (x862-bind-structured-lambda
+       seg 
+       (x862-spread-lambda-list seg bindform whole req opt rest keys nil cdr-p)
+       vloc (x862-vloc-ea vloc) whole req opt rest keys auxen)
+      (x862-undo-body seg vreg xfer body old-stack)
+      (x862-close-structured-lambda seg whole req opt rest keys auxen))))
+
+(defx862 x862-multiple-value-prog1 multiple-value-prog1 (seg vreg xfer forms)
+  (if (or (not (x862-mv-p xfer)) (x862-single-valued-form-p (%car forms)))
+    (x862-use-operator (%nx1-operator prog1) seg vreg xfer forms)
+    (progn
+      (let* ((*x862-vstack* *x862-vstack*)
+             (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+        (x862-multiple-value-body seg (%car forms))
+        (x862-open-undo $undostkblk)
+        (! save-values))
+      (dolist (form (cdr forms))
+        (x862-form seg nil nil form))
+      (x862-set-nargs seg 0)
+      (! recover-values)
+      (x862-close-undo)
+      (let* ((*x862-returning-values* t))
+        (^)))))
+
+(defx862 x862-not not (seg vreg xfer cc form)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (let* ((ea (x862-lexical-reference-ea form nil)))
+      (if (and ea (memory-spec-p ea))
+        (x862-compare-ea-to-nil
+         seg
+         vreg
+         xfer
+         ea
+         cr-bit
+         true-p)
+        (x862-compare-register-to-nil
+         seg 
+         vreg 
+         xfer
+         (x862-one-untargeted-reg-form seg form *x862-arg-z*) 
+         cr-bit
+         true-p)))))
+
+
+(defx862 x862-%alloc-misc %make-uvector (seg vreg xfer element-count st &optional initval)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil element-count)
+      (x862-form seg nil xfer st))
+    (let* ((subtag (acode-fixnum-form-p st))
+           (nelements (acode-fixnum-form-p element-count))         
+           (nbytes (if (and subtag nelements) (x862-misc-byte-count subtag nelements))))
+      (if (and  nbytes (null initval)
+                (< (logand
+                    (lognot (1- *x862-target-dnode-size*))
+                    (+ nbytes *x862-target-node-size*
+                       (1- *x862-target-dnode-size*))) #x8000))
+	(let* ((header *x862-imm0*)
+	       (n (- (* (ceiling (+ nbytes *x862-target-node-size*) *x862-target-dnode-size*) *x862-target-dnode-size*)
+		     (target-arch-case
+		      (:x8632 x8632::fulltag-misc)
+		      (:x8664 x8664::fulltag-misc)))))
+	  (x862-lri seg header (arch::make-vheader nelements subtag))
+	  (target-arch-case
+	   (:x8632
+	    (! setup-uvector-allocation header)
+	    (x862-lri seg x8632::imm0 n))
+	   (:x8664
+	    (x862-lri seg x8664::imm1 n)))
+          (ensuring-node-target (target vreg)
+            (! %allocate-uvector target)))
+        (progn
+          (if initval
+            (progn
+              (x862-three-targeted-reg-forms seg element-count
+					     (target-arch-case
+					      (:x8632 ($ x8632::temp0))
+					      (:x8664 ($ x8664::arg_x)))
+					     st ($ *x862-arg-y*)
+					     initval ($ *x862-arg-z*))
+              (! misc-alloc-init)
+              (<- ($ *x862-arg-z*)))
+            (progn
+              (x862-two-targeted-reg-forms seg element-count ($ *x862-arg-y*) st ($ *x862-arg-z*))
+              (! misc-alloc)
+              (<- ($ *x862-arg-z*))))))
+        (^))))
+
+(defx862 x862-%iasr %iasr (seg vreg xfer form1 form2)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil form1)
+      (x862-form seg vreg xfer form2))
+    (let* ((count (acode-fixnum-form-p form1))
+           (max (target-arch-case (:x8632 31) (:x8664 63))))
+      (declare (fixnum max))
+      (ensuring-node-target (target vreg)
+        (if count
+          (! %iasr-c target (if (> count max) max count)
+             (x862-one-untargeted-reg-form seg form2 *x862-arg-z*))
+          (multiple-value-bind (cnt src) (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*))
+            (! %iasr target cnt src))))
+      (^))))
+
+(defx862 x862-%ilsr %ilsr (seg vreg xfer form1 form2)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil form1)
+      (x862-form seg vreg xfer form2))
+    (let* ((count (acode-fixnum-form-p form1)))
+      (ensuring-node-target (target vreg)
+        (if count
+          (let ((src (x862-one-untargeted-reg-form seg form2 ($ *x862-arg-z*))))
+            (if (<= count 31)
+              (! %ilsr-c target count src)
+              (!  lri target 0)))
+          (multiple-value-bind (cnt src) (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*))
+            (! %ilsr target cnt src))))
+      (^))))
+
+
+(defx862 x862-%i<> %i<> (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (x862-compare seg vreg xfer form1 form2 cr-bit true-p)))
+
+(defx862 x862-%natural<> %natural<> (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (x862-natural-compare seg vreg xfer form1 form2 cr-bit true-p)))
+
+(defx862 x862-double-float-compare double-float-compare (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (with-fp-target () (r1 :double-float)
+      (with-fp-target (r1) (r2 :double-float)
+        (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form1 r1 form2 r2)
+          (x862-compare-double-float-registers seg vreg xfer r1 r2 cr-bit true-p))))))
+
+(defx862 x862-short-float-compare short-float-compare (seg vreg xfer cc form1 form2)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (with-fp-target () (r1 :single-float)
+      (with-fp-target (r1) (r2 :single-float)
+        (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg form1 r1 form2 r2)
+          (x862-compare-single-float-registers seg vreg xfer r1 r2 cr-bit true-p))))))
+ 
+(eval-when (:compile-toplevel :execute)
+  (defmacro defx862-df-op (fname opname vinsn)
+    `(defx862 ,fname ,opname (seg vreg xfer f0 f1)
+      (if (null vreg)
+        (progn
+          (x862-form seg nil nil f0)
+          (x862-form seg vreg xfer f1))
+        (with-fp-target () (r1 :double-float)
+          (with-fp-target (r1) (r2 :double-float)
+            (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg f0 r1 f1 r2)
+              (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+                       (or (not (= (hard-regspec-value vreg)
+                                   (hard-regspec-value r2)))
+                           ,(and 
+                             (not (eq opname '%double-float--2))
+                             (not (eq opname '%double-float/-2)))))
+                (! ,vinsn vreg r1 r2)
+                (with-fp-target (r2) (result :double-float)
+                  (! ,vinsn result r1 r2)
+                  (if (= (hard-regspec-class vreg) hard-reg-class-fpr)
+                    (<- result)
+                    (ensuring-node-target (target vreg)
+                      (x862-copy-register seg target result)))))
+              (^)))))))
+  
+  (defmacro defx862-sf-op (fname opname vinsn)
+    `(defx862 ,fname ,opname (seg vreg xfer f0 f1)
+      (if (null vreg)
+        (progn
+          (x862-form seg nil nil f0)
+          (x862-form seg vreg xfer f1))
+        (with-fp-target () (r1 :single-float)
+          (with-fp-target (r1) (r2 :single-float)
+            (multiple-value-bind (r1 r2) (x862-two-untargeted-reg-forms seg f0 r1 f1 r2)
+              (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+                       (or (not (= (hard-regspec-value vreg)
+                                   (hard-regspec-value r2)))
+                           ,(and 
+                             (not (eq opname '%short-float--2))
+                             (not (eq opname '%short-float/-2)))))
+                (! ,vinsn vreg r1 r2)
+                (with-fp-target (r2) (result :single-float)
+                  (! ,vinsn result r1 r2)
+                  (if (= (hard-regspec-class vreg) hard-reg-class-fpr)
+                    (<- result)
+                    (ensuring-node-target (target vreg)
+                      (x862-copy-register seg target result)))))
+              (^)))))))
+  )
+
+(defx862-df-op x862-%double-float+-2 %double-float+-2 double-float+-2)
+(defx862-df-op x862-%double-float--2 %double-float--2 double-float--2)
+(defx862-df-op x862-%double-float*-2 %double-float*-2 double-float*-2)
+(defx862-df-op x862-%double-float/-2 %double-float/-2 double-float/-2)
+
+(defx862-sf-op x862-%short-float+-2 %short-float+-2 single-float+-2)
+(defx862-sf-op x862-%short-float--2 %short-float--2 single-float--2)
+(defx862-sf-op x862-%short-float*-2 %short-float*-2 single-float*-2)
+(defx862-sf-op x862-%short-float/-2 %short-float/-2 single-float/-2)
+
+(defun x862-get-float (seg vreg xfer ptr offset double-p fp-reg)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (cond ((null vreg)
+           (x862-form seg nil nil ptr)
+           (x862-form seg nil xfer offset))
+          (t
+           (let* ((fixoffset (acode-fixnum-form-p offset)))
+             (if (typep fixoffset '(signed-byte 32))
+               (with-imm-target () (ptrreg :address)
+                 (x862-form seg ptrreg nil ptr)
+                 (if double-p
+                   (! mem-ref-c-double-float fp-reg ptrreg fixoffset)
+                   (! mem-ref-c-single-float fp-reg ptrreg fixoffset)))
+               (with-imm-target () (ptrreg :address)
+		 (with-additional-imm-reg ()
+		   (with-imm-target (ptrreg) (offsetreg :signed-natural)
+		     (x862-two-targeted-reg-forms seg
+						  ptr ptrreg
+						  offset ($ *x862-arg-z*))
+		     (! fixnum->signed-natural offsetreg *x862-arg-z*)
+		     (if double-p
+		       (! mem-ref-double-float fp-reg ptrreg offsetreg)
+		       (! mem-ref-single-float fp-reg ptrreg offsetreg))))))
+             (<- fp-reg))
+           (^)))))
+    
+
+(defx862 x862-%get-double-float %get-double-float (seg vreg xfer ptr offset)
+  (with-fp-target () (fp-reg :double-float)
+    (x862-get-float seg vreg xfer ptr offset t fp-reg)))
+
+(defx862 x862-%get-single-float %get-single-float (seg vreg xfer ptr offset)
+  (with-fp-target () (fp-reg :single-float)
+    (x862-get-float seg vreg xfer ptr offset nil fp-reg)))
+
+(defun x862-set-float (seg vreg xfer ptr offset newval double-p fp-reg)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((fixoffset (acode-fixnum-form-p offset))
+           (immoffset (typep fixoffset '(unsigned-byte 15))))
+      (with-imm-target () (ptr-reg :address) 
+        (cond ((or (null vreg)
+                   (= (hard-regspec-class vreg) hard-reg-class-fpr))
+               (cond (immoffset
+                      (x862-push-register
+                       seg
+                       (x862-one-untargeted-reg-form seg
+                                                     ptr
+                                                     ptr-reg))
+                      (x862-one-targeted-reg-form seg newval fp-reg)
+                      (x862-pop-register seg ptr-reg)
+                      (if double-p
+                        (! mem-set-c-double-float fp-reg ptr-reg fixoffset)
+                        (! mem-set-c-single-float fp-reg ptr-reg fixoffset)))
+                     (t
+		      (with-additional-imm-reg ()
+			(with-imm-target (ptr-reg) (offset-reg :s32)
+			  (x862-push-register
+			   seg
+			   (x862-one-untargeted-reg-form seg
+							 ptr
+							 ptr-reg))
+			  (x862-push-register
+			   seg
+			   (x862-one-untargeted-reg-form seg
+							 offset
+							 *x862-arg-z*))
+			  (x862-one-targeted-reg-form seg newval fp-reg)
+			  (x862-pop-register seg *x862-arg-z*)
+			  (x862-pop-register seg ptr-reg)
+			  (! fixnum->signed-natural offset-reg *x862-arg-z*)
+			  (if double-p
+			    (! mem-set-double-float fp-reg ptr-reg offset-reg)
+			    (! mem-set-single-float fp-reg ptr-reg offset-reg))))))
+               (<- fp-reg))
+              (t
+               (cond (immoffset
+                      (let* ((rnew ($ *x862-arg-z*)))
+                        (x862-push-register
+                         seg
+                         (x862-one-untargeted-reg-form seg
+                                                       ptr
+                                                       ptr-reg))
+                        (x862-one-targeted-reg-form seg newval rnew)
+                        (x862-pop-register seg ptr-reg)
+			(with-additional-imm-reg ()
+			  (with-imm-temps (ptr-reg) ()
+			    (x862-copy-register seg fp-reg rnew)
+			    (if double-p
+			      (! mem-set-c-double-float fp-reg ptr-reg fixoffset)
+			      (! mem-set-c-single-float fp-reg ptr-reg fixoffset))))))
+                     (t
+                      (let* ((roffset ($ *x862-arg-y*))
+                             (rnew ($ *x862-arg-z*)))
+                        (x862-push-register
+                         seg
+                         (x862-one-untargeted-reg-form
+                          seg
+                          ptr ptr-reg))
+                        (x862-two-targeted-reg-forms seg
+                                                   offset roffset
+                                                   newval rnew)
+                        (x862-pop-register seg ptr-reg)
+			(with-additional-imm-reg ()
+			  (with-imm-target (ptr-reg) (offset-reg :s32)
+			    (with-imm-temps (ptr-reg) ()
+			      (x862-copy-register seg fp-reg rnew)
+			      (! fixnum->signed-natural offset-reg roffset))
+			    (if double-p
+			      (! mem-set-double-float fp-reg ptr-reg offset-reg)
+			      (! mem-set-single-float fp-reg ptr-reg offset-reg)))))))
+               (<- *x862-arg-z*)))
+        (^)))))
+
+(defx862 x862-%set-double-float %set-double-float (seg vreg xfer ptr offset newval)
+  (with-fp-target () (fp-reg :double-float)
+    (x862-set-float seg vreg xfer ptr offset newval t fp-reg)))
+      
+(defx862 x862-%set-single-float %set-single-float (seg vreg xfer ptr offset newval)
+  (with-fp-target () (fp-reg :single-float)
+    (x862-set-float seg vreg xfer ptr offset newval nil fp-reg)))
+
+(defx862 x862-immediate-get-ptr immediate-get-ptr (seg vreg xfer ptr offset)
+  (let* ((absptr (acode-absolute-ptr-p ptr))
+         (triv-p (x862-trivial-p offset))
+         (dest vreg)
+         (offval (acode-fixnum-form-p offset)))
+    (cond ((not vreg)
+           (x862-form seg nil nil ptr)
+           (x862-form seg nil xfer offset))
+          (t
+           (if (and absptr offval) 
+             (setq absptr (+ absptr offval) offval 0)
+             (setq absptr nil))
+           (and offval (%i> (integer-length offval) 31) (setq offval nil))
+           (and absptr (%i> (integer-length absptr) 31) (setq absptr nil))
+           (if absptr
+             (! mem-ref-c-absolute-natural dest absptr)
+             (if offval
+               (let* ((src (x862-macptr-arg-to-reg seg ptr ($ *x862-imm0* :mode :address))))
+                 (! mem-ref-c-natural dest src offval))
+               (let* ((src (x862-macptr-arg-to-reg seg ptr ($ *x862-imm0* :mode :address))))
+                 (if triv-p
+		   (with-additional-imm-reg ()
+		     (with-imm-temps (src) (x)
+		       (if (acode-fixnum-form-p offset)
+			 (x862-lri seg x (acode-fixnum-form-p offset))
+			 (! fixnum->signed-natural x (x862-one-untargeted-reg-form seg offset *x862-arg-z*)))
+		       (! mem-ref-natural dest src x)))
+                   (progn
+                     (! temp-push-unboxed-word src)
+                     (x862-open-undo $undostkblk)
+                     (let* ((oreg (x862-one-untargeted-reg-form seg offset *x862-arg-z*)))
+		       (with-additional-imm-reg (*x862-arg-z*)
+			 (with-imm-temps () (src x)
+			   (! temp-pop-unboxed-word src)
+			   (x862-close-undo)
+			   (! fixnum->signed-natural x oreg)
+			   (! mem-ref-natural dest src x)))))))))
+           (^)))))
+
+(defx862 x862-get-bit %get-bit (seg vreg xfer ptr offset)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil ptr)
+      (x862-form seg nil xfer offset))
+    (let* ((offval (acode-fixnum-form-p offset)))
+      (if (typep offval '(signed-byte 32)) ; or thereabouts
+        (with-imm-target () (src-reg :address)
+            (x862-one-targeted-reg-form seg ptr src-reg)
+          (if (node-reg-p vreg)
+	    (! mem-ref-c-bit-fixnum vreg src-reg offval)
+	    (with-imm-target ()         ;OK if src-reg & dest overlap
+		(dest :u8)
+	      (! mem-ref-c-bit dest src-reg offval)
+	      (<- dest))))
+        (with-imm-target () (src-reg :address)
+          (x862-two-targeted-reg-forms seg ptr src-reg offset ($ *x862-arg-z*))
+          (if (node-reg-p vreg)
+            (! mem-ref-bit-fixnum vreg src-reg ($ *x862-arg-z*))
+            (with-imm-target ()           ;OK if src-reg & dest overlap
+                (dest :u8)
+              (! mem-ref-bit dest src-reg offset)
+              (<- dest)))))
+      (^))))
+
+    
+      
+;;; gonna run out of imm regs here                                      
+;;; This returns an unboxed object, unless the caller wants to box it.
+(defx862 x862-immediate-get-xxx immediate-get-xxx (seg vreg xfer bits ptr offset)
+  (declare (fixnum bits))
+  (let* ((fixnump (logbitp 6 bits))
+         (signed (logbitp 5 bits))
+         (size (logand 15 bits))
+         (absptr (acode-absolute-ptr-p ptr))
+         (triv-p (x862-trivial-p offset))
+         (offval (acode-fixnum-form-p offset)))
+    (declare (fixnum size))
+    (cond ((null vreg)
+           (x862-form seg nil nil ptr)
+           (x862-form seg nil xfer offset))
+          (t 
+           (if (and absptr offval) 
+             (setq absptr (+ absptr offval) offval 0)
+             (setq absptr nil))
+           (and offval (%i> (integer-length offval) 31) (setq offval nil))
+           (and absptr (%i> (integer-length absptr) 31) (setq absptr nil))
+	   ;;; huh?
+           (target-arch-case
+            (:x8632 (when (or fixnump (eql size 4) (and (eql size 4) signed))
+		      (and offval (logtest 2 offval) (setq offval nil))
+		      (and absptr (logtest 2 absptr) (setq absptr nil))))
+            (:x8664 (when (or fixnump (eql size 8) (and (eql size 8) signed))
+                      (and offval (logtest 3 offval) (setq offval nil))
+                      (and absptr (logtest 3 absptr) (setq absptr nil))))) 
+	   (cond
+	     (fixnump
+	      (with-imm-target () (dest :signed-natural)
+		(cond
+		  (absptr                              
+		   (target-arch-case
+		    (:x8632 (! mem-ref-c-absolute-fullword dest absptr))
+		    (:x8664 (! mem-ref-c-absolute-doubleword dest  absptr))))
+		  (offval
+		   (with-imm-target () (src-reg :address)
+		     (x862-one-targeted-reg-form seg ptr src-reg)
+		     (target-arch-case
+		      (:x8632 (! mem-ref-c-fullword dest src-reg offval))
+		      (:x8664 (! mem-ref-c-doubleword dest src-reg offval)))))
+		  (t
+		   (with-imm-target () (src-reg :address)
+		     (with-additional-imm-reg ()
+		       (with-imm-target (src-reg) (offset-reg :signed-natural)
+			 (x862-one-targeted-reg-form seg ptr src-reg)
+			 (if triv-p
+			   (if (acode-fixnum-form-p offset)
+			     (x862-lri seg offset-reg (acode-fixnum-form-p offset))
+			     (! fixnum->signed-natural offset-reg (x862-one-untargeted-reg-form seg offset *x862-arg-z*)))
+			   (progn
+			     (! temp-push-unboxed-word src-reg)
+			     (x862-open-undo $undostkblk)
+			     (! fixnum->signed-natural offset-reg (x862-one-untargeted-reg-form seg offset *x862-arg-z*))
+			     (! temp-pop-unboxed-word src-reg)
+			     (x862-close-undo)))
+			 (target-arch-case
+			  (:x8632 (! mem-ref-fullword dest src-reg offset-reg))
+			  (:x8664 (! mem-ref-doubleword dest src-reg offset-reg))))))))
+		(if (node-reg-p vreg)
+		  (! box-fixnum vreg dest)
+		  (<- dest))))
+	     (signed
+	      (with-imm-target () (dest :signed-natural)
+		(cond
+		  (absptr
+		   (case size
+		     (8 (! mem-ref-c-absolute-signed-doubleword dest absptr))
+		     (4 (! mem-ref-c-absolute-signed-fullword dest  absptr))
+		     (2 (! mem-ref-c-absolute-s16 dest absptr))
+		     (1 (! mem-ref-c-absolute-s8 dest absptr))))
+		  (offval
+		   (with-additional-imm-reg ()
+		     (with-imm-target (dest) (src-reg :address)
+		       (x862-one-targeted-reg-form seg ptr src-reg)
+		       (case size
+			 (8 (! mem-ref-c-signed-doubleword dest src-reg offval))
+			 (4 (! mem-ref-c-signed-fullword dest src-reg offval))
+			 (2 (! mem-ref-c-s16 dest src-reg offval))
+			 (1 (! mem-ref-c-s8 dest src-reg offval))))))
+		  (t
+		   (with-imm-target () (src-reg :address)
+		     (with-additional-imm-reg ()
+		       (with-imm-target (src-reg) (offset-reg :signed-natural)
+			 (x862-one-targeted-reg-form seg ptr src-reg)
+			 (if triv-p
+			   (if (acode-fixnum-form-p offset)
+			     (x862-lri seg offset-reg (acode-fixnum-form-p offset))
+			     (! fixnum->signed-natural offset-reg (x862-one-untargeted-reg-form seg offset *x862-arg-z*)))
+			   (progn
+			     (! temp-push-unboxed-word src-reg)
+			     (x862-open-undo $undostkblk)
+			     (! fixnum->signed-natural offset-reg (x862-one-untargeted-reg-form seg offset *x862-arg-z*))
+			     (! temp-pop-unboxed-word src-reg)
+			     (x862-close-undo)))
+			 (case size
+			   (8 (! mem-ref-signed-doubleword dest src-reg offset-reg))
+			   (4 (! mem-ref-signed-fullword dest src-reg offset-reg))
+			   (2 (! mem-ref-s16 dest src-reg offset-reg))
+			   (1 (! mem-ref-s8 dest src-reg offset-reg))))))))
+		(if (node-reg-p vreg)
+		  (case size
+		    ((1 2) (! box-fixnum vreg dest))
+		    (4 (target-arch-case
+			(:x8632 (<- dest))
+			(:x8664 (! box-fixnum vreg dest))))
+		    (8 (<- dest)))
+		  (<- dest))))
+	     (t
+	      (with-imm-target () (dest :natural)
+		(cond
+		  (absptr
+		   (case size
+		     (8 (! mem-ref-c-absolute-doubleword dest absptr))
+		     (4 (! mem-ref-c-absolute-fullword dest absptr))
+		     (2 (! mem-ref-c-absolute-u16 dest absptr))
+		     (1 (! mem-ref-c-absolute-u8 dest absptr))))
+		  (offval
+		   (with-additional-imm-reg ()
+		     (with-imm-target (dest) (src-reg :address)
+		       (x862-one-targeted-reg-form seg ptr src-reg)
+		       (case size
+			 (8 (! mem-ref-c-doubleword dest src-reg offval))
+			 (4 (! mem-ref-c-fullword dest src-reg offval))
+			 (2 (! mem-ref-c-u16 dest src-reg offval))
+			 (1 (! mem-ref-c-u8 dest src-reg offval))))))
+		  (t
+		   (with-additional-imm-reg ()
+		     (with-imm-target () (src-reg :address)
+		       (with-imm-target (src-reg) (offset-reg :signed-natural)
+			 (x862-one-targeted-reg-form seg ptr src-reg)
+			 (if triv-p
+			   (if (acode-fixnum-form-p offset)
+			     (x862-lri seg offset-reg (acode-fixnum-form-p offset))
+			     (! fixnum->signed-natural offset-reg (x862-one-untargeted-reg-form seg offset *x862-arg-z*)))
+			   (progn
+			     (! temp-push-unboxed-word src-reg)
+			     (x862-open-undo $undostkblk)
+			     (! fixnum->signed-natural offset-reg (x862-one-untargeted-reg-form seg offset *x862-arg-z*))
+			     (! temp-pop-unboxed-word src-reg)
+			     (x862-close-undo)))
+			 (case size
+			   (8 (! mem-ref-doubleword dest src-reg offset-reg))
+			   (4 (! mem-ref-fullword dest src-reg offset-reg))
+			   (2 (! mem-ref-u16 dest src-reg offset-reg))
+			   (1 (! mem-ref-u8 dest src-reg offset-reg))))))))
+		(<- (set-regspec-mode 
+		     dest 
+		     (gpr-mode-name-value
+		      (case size
+			(8 :u64)
+			(4 :u32)
+			(2 :u16)
+			(1 :u8))))))))
+           (^)))))
+
+(defx862 x862-let let (seg vreg xfer vars vals body p2decls)
+  (let* ((old-stack (x862-encode-stack))
+         (val nil)
+         (bits nil)
+         (valcopy vals))
+    (with-x86-p2-declarations p2decls
+      (dolist (var vars)
+        (setq val (%car valcopy))
+        (cond ((or (%ilogbitp $vbitspecial (setq bits (nx-var-bits var)))
+                   (and (var-nvr var)
+                        (dolist (val (%cdr valcopy))
+                          (unless (x862-trivial-p val) (return t)))))
+               (let* ((pair (cons (x862-vloc-ea *x862-vstack*) nil)))
+                 (%rplaca valcopy pair)
+                 (if (and (%ilogbitp $vbitdynamicextent bits)
+                          (progn
+                            (setq val 
+                                  (x862-dynamic-extent-form seg (x862-encode-stack) val))
+                            (x862-load-ea-p val)))
+                   (progn
+                     (%rplaca pair (x862-vloc-ea *x862-vstack*))
+                     (x862-vpush-register seg val :reserved))
+                 (x862-vpush-register seg (x862-one-untargeted-reg-form seg val *x862-arg-z*) :reserved))
+                 (%rplacd pair *x862-top-vstack-lcell*)))
+              (t (x862-seq-bind-var seg var val)
+                 (%rplaca valcopy nil)))
+        (setq valcopy (%cdr valcopy)))
+      (dolist (var vars)
+        (declare (list val))
+        (when (setq val (pop vals))
+          (if (%ilogbitp $vbitspecial (nx-var-bits var))
+            (progn
+              (x862-dbind seg (car val) (var-name var))
+              (x862-set-var-ea seg var (x862-vloc-ea (- *x862-vstack* *x862-target-node-size*)))
+              )
+            (x862-seq-bind-var seg var (car val)))))
+      (x862-undo-body seg vreg xfer body old-stack)
+      (dolist (var vars)
+        (x862-close-var seg var)))))
+
+(defx862 x862-closed-function closed-function (seg vreg xfer afunc)
+  (x862-make-closure seg afunc nil)
+  (when vreg (<- *x862-arg-z*))
+  (^))
+
+(defx862 x862-flet flet (seg vreg xfer vars afuncs body p2decls)
+  (if (dolist (afunc afuncs)
+        (unless (eql 0 (afunc-fn-refcount afunc))
+          (return t)))
+    (x862-seq-fbind seg vreg xfer vars afuncs body p2decls)
+    (with-x86-p2-declarations p2decls
+      (x862-form seg vreg xfer body))))
+
+(defx862 x862-labels labels (seg vreg xfer vars afuncs body p2decls)
+  (let* ((fwd-refs nil)
+         (func nil)
+         (togo vars)
+         (real-vars ())
+         (real-funcs ())
+         (funs afuncs))
+    (dolist (v vars)
+      (when (neq 0 (afunc-fn-refcount (setq func (pop funs))))
+        (push v real-vars)
+        (push func real-funcs)
+        (let* ((i (target-arch-case
+		   (:x8632 7)
+		   (:x8664 5))) ; skip 4 words of code, inner function
+               (our-var nil)
+               (item nil))
+          (declare (fixnum i))
+          (dolist (ref (afunc-inherited-vars func))
+            (when (memq (setq our-var (var-bits ref)) togo)
+              (setq item (cons i our-var))
+              (let* ((refs (assq v fwd-refs)))
+                (if refs
+                  (push item (cdr refs))
+                  (push (list v item) fwd-refs))))
+            (incf i)))
+        (setq togo (%cdr togo))))       
+    (if (null fwd-refs)
+      (x862-seq-fbind seg vreg xfer (nreverse real-vars) (nreverse real-funcs) body p2decls)
+      (let* ((old-stack (x862-encode-stack)))
+        (setq real-vars (nreverse real-vars) real-funcs (nreverse real-funcs))
+        (with-x86-p2-declarations p2decls
+          (dolist (var real-vars)
+            (x862-seq-bind-var seg var (nx1-afunc-ref (pop real-funcs))))
+          (dolist (ref fwd-refs)
+            (let ((ea (var-ea (pop ref))))
+              (x862-addrspec-to-reg seg ea *x862-temp0*)
+              (dolist (r ref)
+                (let* ((v-ea (var-ea (cdr r))))
+                  (let* ((val-reg (if (eq v-ea ea)
+                                    *x862-temp0*
+                                    (progn
+                                      (x862-addrspec-to-reg seg v-ea *x862-temp1*)
+                                      *x862-temp1*))))
+                    (! set-closure-forward-reference val-reg *x862-temp0* (car r)))))))
+          (x862-undo-body seg vreg xfer body old-stack)
+          (dolist (var real-vars)
+            (x862-close-var seg var)))))))
+
+;;; Make a function call (e.g., to mapcar) with some of the toplevel arguments
+;;; stack-consed (downward) closures.  Bind temporaries to these closures so
+;;; that tail-recursion/non-local exits work right.
+;;; (all of the closures are distinct: FLET and LABELS establish dynamic extent themselves.)
+(defx862 x862-with-downward-closures with-downward-closures (seg vreg xfer tempvars closures callform)
+  (let* ((old-stack (x862-encode-stack)))
+    (x862-seq-bind seg tempvars closures)
+    (x862-undo-body seg vreg xfer callform old-stack)
+    (dolist (v tempvars) (x862-close-var seg v))))
+
+
+(defx862 x862-local-return-from local-return-from (seg vreg xfer blocktag value)
+  (declare (ignorable vreg xfer))
+  (let* ((*x862-undo-count* *x862-undo-count*)
+         (tagdata (car blocktag))
+         (cur-stack (x862-encode-stack))
+         (dest-vd (caar tagdata))
+         (dest-cd (cdar tagdata))
+         (mv-p (x862-mvpass-p dest-cd))
+         (dest-stack  (cdr tagdata))
+         (need-break (neq cur-stack dest-stack)))
+    (let* ((*x862-vstack* *x862-vstack*)
+           (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+           (*x862-cstack* *x862-cstack*))
+      (if 
+        (or
+         (eq dest-cd $backend-return)
+         (and mv-p 
+              (eq (x862-encoding-undo-count cur-stack)
+                  (x862-encoding-undo-count dest-stack)) 
+              (eq (x862-encoding-cstack-depth cur-stack)
+                  (x862-encoding-cstack-depth dest-stack))))
+        (x862-form seg dest-vd dest-cd value)
+        (if mv-p
+          (progn
+            (x862-multiple-value-body seg value)
+            (let* ((*x862-returning-values* :pass))
+              (x862-nlexit seg dest-cd (%i- *x862-undo-count* (x862-encoding-undo-count dest-stack)))
+              (x862-branch seg dest-cd)))
+          (progn
+            (x862-form 
+             seg
+             (if need-break (if dest-vd *x862-arg-z*) dest-vd) 
+             (if need-break nil dest-cd)
+             value)
+            (when need-break
+              (x862-unwind-set seg dest-cd dest-stack)
+              (when dest-vd (x862-copy-register seg dest-vd *x862-arg-z*))
+              (x862-branch seg dest-cd))))))
+    (x862-unreachable-store)))
+
+(defx862 x862-inherited-arg inherited-arg (seg vreg xfer arg)
+  (when vreg
+    (x862-addrspec-to-reg seg (x862-ea-open (var-ea arg)) vreg))
+  (^))
+
+(defx862 x862-%lisp-word-ref %lisp-word-ref (seg vreg xfer base offset)
+  (let* ((fixoffset (acode-fixnum-form-p offset)))
+    (cond ((null vreg)
+           (x862-form seg nil nil base)
+           (x862-form seg nil xfer offset))
+          ((target-arch-case
+            (:x8632 (typep fixoffset '(signed-byte 30)))
+            (:x8664 (typep fixoffset '(signed-byte 13)))) ;xxx needlessly small
+           (ensuring-node-target (target vreg)
+             (! lisp-word-ref-c target 
+                (x862-one-untargeted-reg-form seg base *x862-arg-z*) 
+                (ash fixoffset *x862-target-fixnum-shift*)))
+           (^))
+          (t (multiple-value-bind (breg oreg)
+                                  (x862-two-untargeted-reg-forms seg base *x862-arg-y* offset *x862-arg-z*)
+               (ensuring-node-target (target vreg)
+                 (! lisp-word-ref target breg oreg))
+               (^))))))
+
+(defx862 x862-%fixnum-ref %fixnum-ref (seg vreg xfer base offset)
+  (let* ((fixoffset (acode-fixnum-form-p offset)))
+    (cond ((null vreg)
+           (x862-form seg nil nil base)
+           (x862-form seg nil xfer offset))
+          ((typep fixoffset '(signed-byte 16))
+           (ensuring-node-target (target vreg)
+             (! lisp-word-ref-c target 
+                (x862-one-untargeted-reg-form seg base *x862-arg-z*) 
+                fixoffset))
+           (^))
+          (t (multiple-value-bind (breg oreg)
+                                  (x862-two-untargeted-reg-forms seg base *x862-arg-y* offset *x862-arg-z*)
+               (with-imm-target () (otemp :s32)
+                 (! fixnum->signed-natural otemp oreg)
+                 (ensuring-node-target (target vreg)
+                   (! lisp-word-ref target breg otemp)))
+               (^))))))
+
+(defx862 x862-%fixnum-ref-natural %fixnum-ref-natural (seg vreg xfer base offset)
+  (let* ((fixoffset (acode-fixnum-form-p offset)))
+    (cond ((null vreg)
+           (x862-form seg nil nil base)
+           (x862-form seg nil xfer offset))
+          ((typep fixoffset '(signed-byte 16))
+           (with-imm-target () (val :natural)
+             (! lisp-word-ref-c val
+                (x862-one-untargeted-reg-form seg base *x862-arg-z*) 
+                fixoffset)
+             (<- val))
+           (^))
+          (t (multiple-value-bind (breg oreg)
+		 (x862-two-untargeted-reg-forms seg base *x862-arg-y* offset *x862-arg-z*)
+               (with-imm-target () (otemp :s32)
+                 (! fixnum->signed-natural otemp oreg)
+		 (with-imm-target () (val :natural)
+		   (! lisp-word-ref val breg otemp)
+		   (<- val)))
+               (^))))))
+
+(defx862 x862-int>0-p int>0-p (seg vreg xfer cc form)
+  (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+    (x862-one-targeted-reg-form seg form ($ *x862-arg-z*))
+    (! integer-sign)
+    (x862-test-reg-%izerop seg vreg xfer *x862-imm0* cr-bit true-p 0)))
+
+
+(defx862 x862-throw throw (seg vreg xfer tag valform )
+  (declare (ignorable vreg xfer))
+  (let* ((*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+    (x862-vpush-register seg (x862-one-untargeted-reg-form seg tag *x862-arg-z*))
+    (if (x862-trivial-p valform)
+      (progn
+        (x862-vpush-register seg (x862-one-untargeted-reg-form seg valform *x862-arg-z*))
+        (x862-set-nargs seg 1))
+      (x862-multiple-value-body seg valform))
+    (! throw)))
+
+;;; This (and unwind-protect and things like that) are a little funky in that
+;;; they have no good way of specifying the exit-point.  The bad way is to
+;;; follow the call to the catch-frame-creating subprim with a branch to that
+;;; exit-point; the subprim returns to the following instruction.
+;;; If the compiler ever gets smart about eliminating dead code, it has to
+;;; be careful not to consider the block following the jump to be dead.
+;;; Use a vinsn other than JUMP to reference the label.
+(defx862 x862-catch catch (seg vreg xfer tag valform)
+  (let* ((tag-label (backend-get-next-label))
+         (tag-label-value (aref *backend-labels* tag-label))
+         (mv-pass (x862-mv-p xfer)))
+    (x862-one-targeted-reg-form seg tag ($ *x862-arg-z*))
+    (if mv-pass
+      (! nmkcatchmv tag-label-value)
+      (! nmkcatch1v tag-label-value))
+    (x862-open-undo)
+    (if mv-pass
+      (x862-multiple-value-body seg valform)  
+      (x862-one-targeted-reg-form seg valform ($ *x862-arg-z*)))
+    (x862-lri seg *x862-imm0* (ash 1 *x862-target-fixnum-shift*))
+    (if mv-pass
+      (! nthrowvalues tag-label-value)
+      (! nthrow1value tag-label-value))
+    (x862-close-undo)
+    (@= tag-label)
+    (unless mv-pass (if vreg (<- *x862-arg-z*)))
+    (let* ((*x862-returning-values* mv-pass)) ; nlexit keeps values on stack
+      (^))))
+
+
+(defx862 x862-fixnum-overflow fixnum-overflow (seg vreg xfer form)
+  (destructuring-bind (op n0 n1) (acode-unwrapped-form form)
+    (x862-use-operator op seg vreg xfer n0 n1 *nx-t*)))
+
+(defx862 x862-%aref2 simple-typed-aref2 (seg vreg xfer typename arr i j &optional dim0 dim1)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil arr)
+      (x862-form seg nil nil i)
+      (x862-form seg nil xfer j)))
+  (let* ((type-keyword (acode-immediate-operand typename))
+         (fixtype (nx-lookup-target-uvector-subtag type-keyword ))
+         (safe (unless *x862-reckless* fixtype))
+         (dim0 (acode-fixnum-form-p dim0))
+         (dim1 (acode-fixnum-form-p dim1)))
+    (x862-aref2 seg vreg xfer arr i j safe type-keyword dim0 dim1)))
+
+(defx862 x862-generic-aref2 general-aref2 (seg vreg xfer arr i j)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+         (keyword (and atype
+		       (or (eq dims '*)
+			   (and (typep dims 'list)
+				(= 2 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims)))
+             (x862-aref2 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         (if *x862-reckless*
+                           nil
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword ;(make-acode (%nx1-operator immediate) )
+                         (if (typep dim0 'fixnum) dim0) (if (typep dim1 'fixnum) dim1))))
+          (t
+           (x862-three-targeted-reg-forms seg
+                                          arr (target-arch-case
+					       (:x8632 ($ x8632::temp0))
+					       (:x8664 ($ x8664::arg_x)))
+                                          i ($ *x862-arg-y*)
+                                          j ($ *x862-arg-z*))
+           (x862-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SParef2))))))
+
+(defx862 x862-%aref3 simple-typed-aref3 (seg vreg xfer typename arr i j k &optional dim0 dim1 dim2)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil arr)
+      (x862-form seg nil nil i)
+      (x862-form seg nil nil j)
+      (x862-form seg nil xfer k)))
+  (let* ((type-keyword (acode-immediate-operand typename))
+         (fixtype (nx-lookup-target-uvector-subtag type-keyword ))
+         (safe (unless *x862-reckless* fixtype))
+         (dim0 (acode-fixnum-form-p dim0))
+         (dim1 (acode-fixnum-form-p dim1))
+         (dim2 (acode-fixnum-form-p dim2)))
+    (x862-aref3 seg vreg xfer arr i j k safe type-keyword dim0 dim1 dim2)))
+
+
+(defx862 x862-general-aref3 general-aref3 (seg vreg xfer arr i j k)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+         (keyword (and atype
+		       (or (eq dims '*)
+			   (and (typep dims 'list)
+				(= 3 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims))
+                  (dim2 (caddr dims)))
+             (x862-aref3 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         k
+                         (if *x862-reckless*
+                           nil
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword ;(make-acode (%nx1-operator immediate) )
+                         (if (typep dim0 'fixnum) dim0)
+                         (if (typep dim1 'fixnum) dim1)
+                         (if (typep dim2 'fixnum) dim2))))
+          (t
+           (x862-four-targeted-reg-forms seg
+                                         arr ($ *x862-temp0*)
+                                         i ($ x8664::arg_x)
+                                         j ($ *x862-arg-y*)
+                                         k ($ *x862-arg-z*))
+           (x862-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SParef3))))))
+                                          
+(defx862 x862-general-aset2 general-aset2 (seg vreg xfer arr i j new)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+         (keyword (and atype
+		       (or (eq dims '*)
+			   (and (typep dims 'list)
+				(= 2 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims)))
+             (x862-aset2 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         new
+                         (unless *x862-reckless*
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword
+                         (if (typep dim0 'fixnum) dim0)
+                         (if (typep dim1 'fixnum) dim1))))
+          (t
+           (x862-four-targeted-reg-forms seg
+                                         arr ($ *x862-temp0*)
+                                         i ($ x8664::arg_x)
+                                         j ($ *x862-arg-y*)
+                                         new ($ *x862-arg-z*))
+           (x862-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SPaset2))))))
+
+(defx862 x862-general-aset3 general-aset3 (seg vreg xfer arr i j k new)
+  (target-arch-case
+   (:x8632 (error "not for x8632 yet")))
+  (let* ((atype0 (acode-form-type arr t))
+         (ctype (if atype0 (specifier-type atype0)))
+         (atype (if (array-ctype-p ctype) ctype))
+	 (dims (and atype (array-ctype-dimensions atype)))
+         (keyword (and atype
+		       (or (eq dims '*)
+			   (unless (atom dims)
+			     (= 3 (length dims))))
+                       (not (array-ctype-complexp atype))
+                       (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        atype))))
+    (cond (keyword
+	   (when (eq dims '*)
+	     (setq dims nil))
+           (let* ((dim0 (car dims))
+                  (dim1 (cadr dims))
+                  (dim2 (caddr dims)))
+             (x862-aset3 seg
+                         vreg
+                         xfer
+                         arr
+                         i
+                         j
+                         k
+                         new
+                         (unless *x862-reckless*
+                           (nx-lookup-target-uvector-subtag keyword ))
+                         keyword
+                         (if (typep dim0 'fixnum) dim0)
+                         (if (typep dim1 'fixnum) dim1)
+                         (if (typep dim2 'fixnum) dim2))))
+          (t
+           (x862-push-register seg (x862-one-untargeted-reg-form seg arr ($ *x862-arg-z*)))
+           (x862-four-targeted-reg-forms seg
+                                         i ($ *x862-temp0*)
+                                         j ($ x8664::arg_x)
+                                         k ($ *x862-arg-y*)
+                                         new ($ *x862-arg-z*))
+           (x862-pop-register seg ($ x8664::temp1))
+           (x862-fixed-call-builtin seg vreg xfer nil (subprim-name->offset '.SPaset3))))))
+
+
+(defx862 x862-%aset2 simple-typed-aset2 (seg vreg xfer typename arr i j new &optional dim0 dim1)
+  (let* ((type-keyword (acode-immediate-operand typename))
+         (fixtype (nx-lookup-target-uvector-subtag type-keyword))
+         (safe (unless *x862-reckless* fixtype))
+         (dim0 (acode-fixnum-form-p dim0))
+         (dim1 (acode-fixnum-form-p dim1)))
+    (x862-aset2 seg vreg xfer arr i j new safe type-keyword dim0 dim1)))
+
+
+(defx862 x862-%aset3 simple-typed-aset3 (seg vreg xfer typename arr i j k new &optional dim0 dim1 dim2)
+  (let* ((type-keyword (acode-immediate-operand typename))
+         (fixtype (nx-lookup-target-uvector-subtag type-keyword))
+         (safe (unless *x862-reckless* fixtype))
+         (dim0 (acode-fixnum-form-p dim0))
+         (dim1 (acode-fixnum-form-p dim1))
+         (dim2 (acode-fixnum-form-p dim2)))
+    (x862-aset3 seg vreg xfer arr i j k new safe type-keyword dim0 dim1 dim2)))
+
+(defx862 x862-%typed-uvref %typed-uvref (seg vreg xfer subtag uvector index)
+  (let* ((type-keyword
+          (let* ((fixtype (acode-fixnum-form-p subtag)))
+            (if fixtype
+              (nx-target-uvector-subtag-name fixtype)
+              (acode-immediate-operand subtag)))))
+    (if type-keyword
+      (x862-vref seg vreg xfer type-keyword uvector index (unless *x862-reckless* (nx-lookup-target-uvector-subtag type-keyword)))
+      (progn
+        (x862-three-targeted-reg-forms seg
+				       subtag (target-arch-case
+					       (:x8632 ($ x8632::temp0))
+					       (:x8664 ($ x8664::arg_x)))
+				       uvector ($ *x862-arg-y*)
+				       index ($ *x862-arg-z*))
+        (! subtag-misc-ref)
+        (when vreg (<- ($ *x862-arg-z*)))
+        (^)) )))
+
+(defx862 x862-%typed-uvset %typed-uvset (seg vreg xfer subtag uvector index newval)
+  (let* ((type-keyword
+          (let* ((fixtype (acode-fixnum-form-p subtag)))
+            (if fixtype
+              (nx-target-uvector-subtag-name fixtype)
+              (acode-immediate-operand subtag)))))
+    (if type-keyword
+      (x862-vset seg vreg xfer type-keyword uvector index newval (unless *x862-reckless* (nx-lookup-target-uvector-subtag type-keyword)))
+      (progn
+	(target-arch-case
+	 (:x8632
+	  (x862-four-targeted-reg-forms seg subtag ($ x8632::temp1) uvector ($ x8632::temp0) index ($ x8632::arg_y) newval ($ x8632::arg_z)))
+	 (:x8664
+	  (x862-four-targeted-reg-forms seg subtag ($ x8664::temp0) uvector ($ x8664::arg_x) index ($ x8664::arg_y) newval ($ x8664::arg_z))))
+        (! subtag-misc-set)
+        (when vreg (<- ($ *x862-arg-z*)))
+        (^)))))
+
+(defx862 x862-%macptrptr% %macptrptr% (seg vreg xfer form)
+  (with-imm-target () (target :address)
+    (x862-one-targeted-reg-form seg form (or vreg target)))
+  (^))
+           
+
+;;; cons a macptr, unless "vreg" is an immediate register of mode :address.
+(defx862 x862-%consmacptr% %consmacptr% (seg vreg xfer form)
+  (cond ((null vreg) (x862-form seg nil xfer form))
+        ((eql (get-regspec-mode vreg) hard-reg-class-gpr-mode-address)
+         (x862-form seg vreg xfer form))
+        (t         
+         (with-imm-target () (temp :address)
+           (<- (x862-one-targeted-reg-form seg form temp))
+           (^)))))
+
+(defx862 x862-%immediate-ptr-to-int %immediate-ptr-to-int (seg vreg xfer form)
+  (if (null vreg)
+    (x862-form seg nil xfer form)
+    (with-imm-target () (address-reg :address)
+      (x862-form seg address-reg nil form)
+      (<- (set-regspec-mode address-reg (gpr-mode-name-value :natural)))
+      (^))))
+
+(defx862 x862-%immediate-int-to-ptr %immediate-int-to-ptr (seg vreg xfer form)
+  (if (null vreg)
+    (x862-form seg nil xfer form)
+    (progn
+      (unless (logbitp (hard-regspec-value vreg) *backend-imm-temps*)
+        (compiler-bug "I give up.  When will I get this right ?"))
+      (let* ((natural-reg (x862-one-targeted-reg-form seg 
+                                                      form
+                                                      ($ vreg :mode :natural))))
+        (<- natural-reg)
+        (^)))))
+
+
+(defx862 x862-%function %function (seg vreg xfer sym)
+  (when vreg
+    (let* ((symreg (x862-one-untargeted-reg-form seg (make-acode (%nx1-operator immediate)
+                                                                 (x862-symbol-entry-locative sym)) *x862-arg-z*)))
+      (with-node-temps (vreg symreg) (val)
+        (! symbol-function val symreg)
+        (<- val))))
+  (^))
+
+(defx862 x862-%unbound-marker %unbound-marker (seg vreg xfer)
+  (when vreg       
+    (ensuring-node-target (target vreg)
+      (x862-lri seg target (target-arch-case
+                            (:x8632 x8632::unbound-marker)
+                            (:x8664 x8664::unbound-marker)))))
+  (^))
+
+(defx862 x862-slot-unbound-marker %slot-unbound-marker (seg vreg xfer)
+  (when vreg    
+    (ensuring-node-target (target vreg)
+      (x862-lri seg target (target-arch-case
+			    (:x8632 x8632::slot-unbound-marker)
+                            (:x8664 x8664::slot-unbound-marker)))))
+  (^))
+
+(defx862 x862-illegal-marker %illegal-marker (seg vreg xfer)
+  (when vreg    
+    (ensuring-node-target (target vreg)
+      (x862-lri seg target (target-arch-case
+			    (:x8632 x8632::illegal-marker)
+                            (:x8664 x8664::illegal-marker)))))
+  (^))
+
+(defx862 x862-lambda-bind lambda-bind (seg vreg xfer vals req rest keys-p auxen body p2decls)
+  (let* ((old-stack (x862-encode-stack))
+         (nreq (list-length req))
+         (rest-arg (nthcdr nreq vals))
+         (apply-body (x862-eliminate-&rest body rest keys-p auxen rest-arg)))
+    (x862-seq-bind seg req vals)
+    (when apply-body (setq rest nil body apply-body))
+    (let*
+      ((vloc *x862-vstack*)
+       (restloc vloc)
+       (nvloc (progn (if (or rest keys-p) (x862-formlist seg rest-arg)) *x862-vstack*)))
+      (with-x86-p2-declarations p2decls
+        (when rest
+          (when keys-p
+            (until (eq restloc nvloc)
+              (with-node-temps () (temp)
+                (x862-stack-to-register seg (x862-vloc-ea restloc) temp)
+                (x862-vpush-register seg temp))
+              (setq restloc (%i+ restloc *x862-target-node-size*))))
+          (x862-set-nargs seg (length rest-arg))
+          (x862-set-vstack restloc)
+          (if (%ilogbitp $vbitdynamicextent (nx-var-bits rest))
+            (progn
+              (! stack-cons-list)
+              (x862-open-undo $undostkblk))
+            (! list))
+          (x862-vpush-register seg *x862-arg-z*))
+        (when rest (x862-bind-var seg rest restloc))
+        (destructuring-bind (vars inits) auxen
+          (while vars
+            (let ((val (%car inits))) 
+              (if (fixnump val)
+                (progn
+                  (when rest (setq val (%i+ (%i+ val val) 1)))
+                  (x862-bind-var seg (%car vars) (%i+ vloc (* val *x862-target-node-size*))))
+                (x862-seq-bind-var seg (%car vars) val)))
+            (setq vars (%cdr vars) inits (%cdr inits))))
+        (x862-undo-body seg vreg xfer body old-stack)
+        (dolist (var req) (x862-close-var seg var))
+        (when rest (x862-close-var seg rest))
+        (dolist (var (%car auxen)) (x862-close-var seg var))))))
+
+(macrolet 
+  ((def-x862-require (function op &optional (vinsn op))
+     `(defx862 ,function ,op (seg vreg xfer val)
+        (let* ((val-reg (x862-one-untargeted-reg-form 
+                         seg 
+                         val 
+                         (if (eq vreg *x862-arg-z*) *x862-arg-y* *x862-arg-z*))))
+          (! ,vinsn val-reg)
+          (when vreg (<- val-reg))
+          (^)))))
+  (def-x862-require x862-require-simple-vector require-simple-vector)
+  (def-x862-require x862-require-simple-string require-simple-string)
+  (def-x862-require x862-require-integer require-integer)
+  (def-x862-require x862-require-fixnum require-fixnum)
+  (def-x862-require x862-require-real require-real)
+  (def-x862-require x862-require-list require-list)
+  (def-x862-require x862-require-character require-character)
+  (def-x862-require x862-require-number require-number)
+  (def-x862-require x862-require-symbol require-symbol)
+  (def-x862-require x862-require-s8 require-s8)
+  (def-x862-require x862-require-s8 require-u8)
+  (def-x862-require x862-require-s8 require-s16)
+  (def-x862-require x862-require-s8 require-u16)
+  (def-x862-require x862-require-s8 require-s32)
+  (def-x862-require x862-require-s8 require-u32)
+  (def-x862-require x862-require-s8 require-s64)
+  (def-x862-require x862-require-s8 require-u64))
+
+(defun x862-typechecked-form (seg vreg xfer typespec form)
+  (with-x86-local-vinsn-macros (seg vreg xfer)
+    (let* ((op
+            (cond ((eq typespec 'fixnum) (%nx1-operator require-fixnum))
+                  ((eq typespec 'integer) (%nx1-operator require-integer))
+                  ((memq typespec '(base-char character))
+                   (%nx1-operator require-character))
+                  ((eq typespec 'symbol) (%nx1-operator require-symbol))
+                  ((eq typespec 'list) (%nx1-operator require-list))
+                  ((eq typespec 'real) (%nx1-operator require-real))
+                  ((memq typespec '(simple-base-string simple-string))
+                   (%nx1-operator require-simple-string))
+                  ((eq typespec 'number) (%nx1-operator require-number))
+                  ((eq typespec 'simple-vector) (%nx1-operator require-simple-vector))
+                  (t
+                   (let* ((ctype (specifier-type typespec)))
+                     (cond ((type= ctype (load-time-value (specifier-type '(signed-byte 8))))
+                            (%nx1-operator require-s8))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 8))))
+                            (%nx1-operator require-u8))
+                           ((type= ctype (load-time-value (specifier-type '(signed-byte 16))))
+                            (%nx1-operator require-s16))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 16))))
+                            (%nx1-operator require-u16))
+                           ((type= ctype (load-time-value (specifier-type '(signed-byte 32))))                            
+                            (%nx1-operator require-s32))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 32))))
+                            (%nx1-operator require-u32))
+                           ((type= ctype (load-time-value (specifier-type '(signed-byte 64))))
+                            (%nx1-operator require-s64))
+                           ((type= ctype (load-time-value (specifier-type '(unsigned-byte 64))))
+                            (%nx1-operator require-u64))))))))
+      (if op
+        (x862-use-operator op seg vreg xfer form)
+        (if (or (eq typespec t)
+                (eq typespec '*))
+          (x862-form seg vreg xfer form)
+          (with-note (form seg)
+            (let* ((ok (backend-get-next-label)))
+              (if (and (symbolp typespec) (non-nil-symbolp (type-predicate typespec)))
+                ;; Do this so can compile the lisp with typechecking even though typep
+                ;; doesn't get defined til fairly late.
+                (progn
+                  (x862-one-targeted-reg-form seg form ($ *x862-arg-z*))
+                  (x862-store-immediate seg (type-predicate typespec) ($ *x862-fname*))
+                  (x862-set-nargs seg 1)
+                  (x862-vpush-register seg ($ *x862-arg-z*)))
+                (progn
+                  (x862-one-targeted-reg-form seg form ($ *x862-arg-y*))
+                  (x862-store-immediate seg typespec ($ *x862-arg-z*))
+                  (x862-store-immediate seg 'typep ($ *x862-fname*))
+                  (x862-set-nargs seg 2)
+                  (x862-vpush-register seg ($ *x862-arg-y*))))
+              (! call-known-symbol ($ *x862-arg-z*))
+              (! compare-to-nil ($ *x862-arg-z*))
+              (x862-vpop-register seg ($ *x862-arg-y*))
+              (! cbranch-false (aref *backend-labels* ok) x86::x86-e-bits)
+              (target-arch-case
+               (:x8632
+                (let* ((*x862-vstack* *x862-vstack*)
+                       (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+                  (! reserve-outgoing-frame)
+                  (incf *x862-vstack* (* 2 *x862-target-node-size*))
+                  (! vpush-fixnum (ash $XWRONGTYPE *x862-target-fixnum-shift*))
+                  (x862-store-immediate seg typespec ($ *x862-arg-z*))
+                  (x862-set-nargs seg 3)
+                  (! ksignalerr)))
+               (:x8664
+                (x862-lri seg ($ x8664::arg_x) (ash $XWRONGTYPE *x862-target-fixnum-shift*))
+                (x862-store-immediate seg typespec ($ *x862-arg-z*))
+                (x862-set-nargs seg 3)
+                (! ksignalerr)))
+              (@ ok)
+              (<- ($ *x862-arg-y*))
+              (^))))))))
+          
+          
+                  
+                  
+                   
+
+(defx862 x862-%badarg2 %badarg2 (seg vreg xfer badthing goodthing)
+  (x862-two-targeted-reg-forms seg badthing ($ *x862-arg-y*) goodthing ($ *x862-arg-z*))
+  (target-arch-case
+   (:x8632
+    (let* ((*x862-vstack* *x862-vstack*)
+	   (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+      (! reserve-outgoing-frame)
+      (incf *x862-vstack* (* 2 *x862-target-node-size*))
+      (! vpush-fixnum (ash $XWRONGTYPE *x862-target-fixnum-shift*))
+      (x862-set-nargs seg 3)
+      (! ksignalerr))
+    (<- nil)
+    (^))
+   (:x8664
+    (x862-lri seg ($ x8664::arg_x) (ash $XWRONGTYPE *x862-target-fixnum-shift*))
+    (x862-set-nargs seg 3)
+    (! ksignalerr)
+    (<- nil)
+    (^))))
+          
+(defx862 x862-%set-sbchar %set-sbchar (seg vreg xfer string index value)
+  (x862-vset 
+   seg 
+   vreg 
+   xfer 
+   :simple-string 
+   string 
+   index
+   value 
+   (unless *x862-reckless* (nx-lookup-target-uvector-subtag :simple-string))))
+
+
+;;; If we didn't use this for stack consing, turn it into a call.  Ugh.
+
+(defx862 x862-make-list make-list (seg vreg xfer size initial-element)
+  (let* ((args (list size
+		     (make-acode (%nx1-operator immediate) :initial-element)
+		     initial-element)))
+    (x862-form seg vreg xfer
+	       (make-acode (%nx1-operator call)
+			   (make-acode (%nx1-operator immediate) 'make-list)
+			   (if (<= (length args) *x862-target-num-arg-regs*)
+			     (list nil (reverse args))
+			     (list (butlast args *x862-target-num-arg-regs*)
+				   (reverse (last args *x862-target-num-arg-regs*))))))))
+
+(defx862 x862-setq-free setq-free (seg vreg xfer sym val)
+  (let* ((rsym ($ *x862-arg-y*))
+         (rval ($ *x862-arg-z*)))
+    (x862-one-targeted-reg-form seg val rval)
+    (x862-immediate seg rsym nil (x862-symbol-value-cell sym))
+    (! setqsym)
+    (<- rval)
+    (^)))
+
+(defx862 x862-%setf-macptr %setf-macptr (seg vreg xfer x y)
+  (x862-vpush-register seg (x862-one-untargeted-reg-form seg x *x862-arg-z*))
+  (with-imm-target () (src-reg :address)
+    (x862-one-targeted-reg-form seg y src-reg)
+    (x862-vpop-register seg *x862-arg-z*)
+    (unless (or *x862-reckless* (x862-form-typep x 'macptr))
+      (with-additional-imm-reg (*x862-arg-z*)
+	(with-imm-temps (src-reg) ()
+	  (! trap-unless-macptr *x862-arg-z*))))
+    (! set-macptr-address src-reg *x862-arg-z*)
+    (<- *x862-arg-z*)
+    (^)))
+
+;; used for x8632 only
+(defx862 x862-%setf-short-float %setf-short-float (seg vref xfer fnode fval)
+  (target-arch-case
+   (:x8664 (error "%setf-short-float makes no sense on x8664")))
+  (x862-vpush-register seg (x862-one-untargeted-reg-form seg fnode *x862-arg-z*))
+  (let* ((target ($ *x862-fp1* :class :fpr :mode :single-float))
+         (node ($ *x862-arg-z*)))
+    (x862-one-targeted-reg-form seg fval target)
+    (x862-vpop-register seg node)
+    (unless (or *x862-reckless* (x862-form-typep fnode 'single-float))
+      (! trap-unless-single-float node))
+    (! store-single node target)
+    (<- node)
+    (^)))
+
+(defx862 x862-%setf-double-float %setf-double-float (seg vref xfer fnode fval)
+  (x862-vpush-register seg (x862-one-untargeted-reg-form seg fnode *x862-arg-z*))
+  (let* ((target ($ *x862-fp1* :class :fpr :mode :double-float))
+         (node ($ *x862-arg-z*)))
+    (x862-one-targeted-reg-form seg fval target)
+    (x862-vpop-register seg node)
+    (unless (or *x862-reckless* (x862-form-typep fnode 'double-float))
+      (! trap-unless-double-float node))
+    (! store-double node target)
+    (<- node)
+    (^)))
+
+    
+
+(defx862 x862-unwind-protect unwind-protect (seg vreg xfer protected-form cleanup-form)
+  (let* ((cleanup-label (backend-get-next-label))
+         (protform-label (backend-get-next-label))
+         (old-stack (x862-encode-stack))
+         (ilevel '*interrupt-level*))
+    (! nmkunwind
+       (aref *backend-labels* protform-label)
+       (aref *backend-labels* cleanup-label))
+    (x862-open-undo $undointerruptlevel)
+    (x862-new-vstack-lcell :special-value *x862-target-lcell-size* 0 ilevel)
+    (x862-new-vstack-lcell :special *x862-target-lcell-size* (ash 1 $vbitspecial) ilevel)
+    (x862-new-vstack-lcell :special-link *x862-target-lcell-size* 0 ilevel)
+    (x862-adjust-vstack (* 3 *x862-target-node-size*))    
+    (@= cleanup-label)
+    (let* ((*x862-vstack* *x862-vstack*)
+           (*x862-top-vstack-lcell* *x862-top-vstack-lcell*))
+      (x862-open-undo $undostkblk)      ; tsp frame created by nthrow.
+      (x862-new-vstack-lcell :cleanup-return *x862-target-lcell-size* 0 nil)
+      (x862-adjust-vstack *x862-target-node-size*)      
+      (x862-form seg nil nil cleanup-form)
+      (x862-close-undo)
+      (! jump-return-pc))
+    (x862-open-undo)
+    (@=  protform-label)
+    (x862-open-undo $undointerruptlevel)
+    (x862-new-vstack-lcell :special-value *x862-target-lcell-size* 0 ilevel)
+    (x862-new-vstack-lcell :special *x862-target-lcell-size* (ash 1 $vbitspecial) ilevel)
+    (x862-new-vstack-lcell :special-link *x862-target-lcell-size* 0 ilevel)
+    (x862-adjust-vstack (* 3 *x862-target-node-size*))
+    (x862-undo-body seg vreg xfer protected-form old-stack)))
+
+(defx862 x862-progv progv (seg vreg xfer symbols values body)
+  (let* ((cleanup-label (backend-get-next-label))
+         (protform-label (backend-get-next-label))
+         (old-stack (x862-encode-stack)))
+    (x862-two-targeted-reg-forms seg symbols ($ *x862-arg-y*) values ($ *x862-arg-z*))
+    (! progvsave)
+    (x862-open-undo $undostkblk)
+    (! mkunwind
+       (aref *backend-labels* protform-label)
+       (aref *backend-labels* cleanup-label))
+    (@= cleanup-label)
+    (! progvrestore)
+    (x862-open-undo)
+    (@= protform-label)
+    (x862-undo-body seg vreg xfer body old-stack)))
+
+(defx862 x862-%ptr-eql %ptr-eql (seg vreg xfer cc x y )
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil x)
+      (x862-form seg nil xfer y))
+    (let* ((x-abs (acode-absolute-ptr-p x t))
+           (y-abs (acode-absolute-ptr-p y t))
+           (abs (or x-abs y-abs))
+           (other (if abs (if x-abs y x))))
+      (multiple-value-bind (cr-bit true-p) (acode-condition-to-x86-cr-bit cc)
+        (if other
+          (with-imm-target () (other-target :address)
+            (x862-one-targeted-reg-form seg other other-target)
+            (if (typep abs '(signed-byte 16))              
+              (x862-test-reg-%izerop seg vreg xfer other-target cr-bit true-p abs)
+	      (with-additional-imm-reg ()
+		(with-imm-temps (other-target) ((abs-target :address))
+		  (use-imm-temp other-target)
+		  (x862-lri seg abs-target abs)
+		  (x862-compare-registers seg vreg xfer other-target abs-target cr-bit true-p)))))
+          ;; Neither expression is obviously a constant-valued macptr.
+          (with-imm-target () (target-a :address)
+            (x862-one-targeted-reg-form seg x target-a)
+            (! temp-push-unboxed-word target-a)
+            (x862-open-undo $undostkblk)
+            (x862-one-targeted-reg-form seg y target-a)
+	    (with-additional-imm-reg ()
+	      (with-imm-target (target-a) (target-b :address)
+		(! temp-pop-unboxed-word target-b)
+		(x862-close-undo)
+		(x862-compare-registers seg vreg xfer target-b target-a cr-bit true-p)))))))))
+
+(defx862 x862-set-bit %set-bit (seg vreg xfer ptr offset newval)
+  (let* ((offval (acode-fixnum-form-p offset))
+         (constval (acode-fixnum-form-p newval)))
+      (if (typep offval '(signed-byte 32))
+        (with-imm-target () (src :address)
+          (x862-one-targeted-reg-form seg ptr src)
+          (if constval
+            (progn
+              (if (eql constval 0)
+                (! mem-set-c-bit-0 src offval)
+                (! mem-set-c-bit-1 src offval))
+              (when vreg
+                (x862-form seg vreg nil newval)))
+            (with-imm-target () (src :address)
+              (x862-two-targeted-reg-forms seg ptr src newval ($ *x862-arg-z*))
+              (! mem-set-c-bit-variable-value src offval ($ *x862-arg-z*))
+              (<- ($ *x862-arg-z*)))))
+        (if constval
+          (with-imm-target () (src :address)
+            (x862-two-targeted-reg-forms seg ptr src offset ($ *x862-arg-z*))
+            (if (eql constval 0)
+              (! mem-set-bit-0 src ($ *x862-arg-z*))
+              (! mem-set-bit-1 src ($ *x862-arg-z*)))
+            (when vreg
+              (x862-form seg vreg nil newval)))
+          (with-imm-target () (src :address)
+            (x862-three-targeted-reg-forms seg ptr src offset ($ *x862-arg-y*) newval ($ *x862-arg-z*))
+            (! mem-set-bit-variable-value src ($ *x862-arg-y*) ($ *x862-arg-z*))
+            (<- ($ *x862-arg-z*)))))
+      (^)))
+
+(defx862 x862-%immediate-set-xxx %immediate-set-xxx (seg vreg xfer bits ptr offset val)
+  (x862-%immediate-store seg vreg xfer bits ptr offset val))
+
+
+
+(defx862 x862-%immediate-inc-ptr %immediate-inc-ptr (seg vreg xfer ptr by)
+  (let* ((triv-by (x862-trivial-p by))
+         (fixnum-by (acode-fixnum-form-p by)))
+    (if (and fixnum-by (eql 0 fixnum-by))
+      (x862-form seg vreg xfer ptr)
+      (let* ((ptr-reg (with-imm-target () (ptr-reg :address)
+                        (x862-one-targeted-reg-form seg ptr ptr-reg)))
+	     (s32-by (s32-fixnum-constant-p fixnum-by)))
+        (if s32-by
+          (let* ((result ptr-reg))
+            (! add-constant result s32-by)
+            (<- result))
+	  (progn
+	    (unless triv-by
+	      (x862-push-register seg ptr-reg))
+	    (let* ((boxed-by (x862-one-targeted-reg-form seg by *x862-arg-z*)))
+	      (unless triv-by
+		(x862-pop-register seg ptr-reg))
+	      (with-additional-imm-reg ()
+		(with-imm-target (ptr-reg) (by-reg :signed-natural)
+		  (! fixnum->signed-natural by-reg boxed-by)
+		  (let* ((result ptr-reg))
+		    (! fixnum-add2 result by-reg)
+		    (<- result)))))))
+        (^)))))
+
+
+
+(defx862 x862-multiple-value-call multiple-value-call (seg vreg xfer fn arglist)
+  (x862-mvcall seg vreg xfer fn arglist))
+
+(defx862 x862-i386-syscall i386-syscall (seg vreg xfer idx argspecs argvals resultspec &optional monitor-exception-ports)
+  (declare (ignore monitor-exception-ports))
+  (let* ((*x862-vstack* *x862-vstack*)
+	 (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+	 (*x862-cstack* *x862-cstack*)
+	 (offset 0)
+	 (nwords 0))
+    (dolist (argspec argspecs)
+      (case argspec
+	((:unsigned-doubleword :signed-doubleword)
+	 (incf nwords 2))
+	(t (incf nwords))))
+    (! alloc-c-frame nwords)
+    (x862-open-undo $undo-x86-c-frame)
+    (x862-vpush-register seg (x862-one-untargeted-reg-form seg idx x8632::arg_z))
+    ;; Evaluate each form into the C frame, according to the
+    ;; matching argspec.
+    (do* ((specs argspecs (cdr specs))
+	  (vals argvals (cdr vals)))
+	 ((null specs))
+      (declare (list specs vals))
+      (let* ((valform (car vals))
+	     (spec (car specs))
+	     (absptr (acode-absolute-ptr-p valform)))
+	(case spec
+	  ((:unsigned-doubleword :signed-doubleword)
+	   (x862-one-targeted-reg-form seg valform ($ x8632::arg_z))
+	   (if (eq spec :signed-doubleword)
+	     (! gets64)
+	     (! getu64))
+	   (! set-c-arg-from-mm0 offset)
+	   (incf offset 2))
+	  (:address
+	   (with-imm-target () (ptr :address)
+	     (if absptr
+	       (x862-lri seg ptr absptr)
+	       (x862-form seg ptr nil valform))
+	     (! set-c-arg ptr offset))
+	   (incf offset))
+	  (t
+	   (with-imm-target () (valreg :natural)
+	     (let* ((reg (x862-unboxed-integer-arg-to-reg seg valform valreg spec)))
+	       (! set-c-arg reg offset)
+	       (incf offset)))))))
+    (x862-vpop-register seg ($ x8632::arg_z))
+    (case resultspec
+      ((:unsigned-doubleword :signed-doubleword)
+       (! syscall2))			;copies doubleword result into %mm0
+      (t
+       (! syscall)))
+    (x862-close-undo)
+    (when vreg
+      (cond ((eq resultspec :void) (<- nil))
+	    ((eq resultspec :unsigned-doubleword)
+	     (ensuring-node-target (target vreg)
+	       (! makeu64)
+	       (x862-copy-register seg target ($ *x862-arg-z*))))
+	    ((eq resultspec :signed-doubleword)
+	     (ensuring-node-target (target vreg)
+	       (! makes64)
+	       (x862-copy-register seg target ($ *x862-arg-z*))))
+	    (t
+	     (case resultspec
+	       (:signed-byte (! sign-extend-s8 *x862-imm0* *x862-imm0*))
+	       (:signed-halfword (! sign-extend-s16 *x862-imm0* *x862-imm0*))
+	       (:unsigned-byte (! zero-extend-u8 *x862-imm0* *x862-imm0*))
+	       (:unsigned-halfword (! zero-extend-u16 *x862-imm0* *x862-imm0*)))
+	     (<- (make-wired-lreg x8632::imm0
+				  :mode
+				  (gpr-mode-name-value
+				   (case resultspec
+				     (:address :address)
+				     (:signed-byte :s8)
+				     (:unsigned-byte :u8)
+				     (:signed-halfword :s16)
+				     (:unsigned-halfword :u16)
+				     (:signed-fullword :s32)
+				     (t :u32))))))))
+    (^)))
+
+
+(defx862 x862-syscall syscall (seg vreg xfer idx argspecs argvals resultspec &optional monitor-exception-ports)
+  (declare (ignore monitor-exception-ports))
+  (let* ((*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+         (*x862-cstack* *x862-cstack*)
+         (gpr-offset 0)
+         (other-offset 6)
+         (nother-words 0)
+         (ngpr-args 0)
+         (simple-foreign-args nil))
+      (declare (fixnum  ngpr-args nother-words
+                        gpr-offset other-offset))
+      (dolist (argspec argspecs)
+        (declare (ignorable argspec))
+        (incf ngpr-args)
+        (if (> ngpr-args 6)
+          (incf nother-words)))
+      (let* ((total-words nother-words))
+        (when (zerop total-words)
+          (setq simple-foreign-args nil))
+        (! alloc-c-frame total-words))
+      (x862-open-undo $undo-x86-c-frame)
+      (setq ngpr-args 0)
+      (unless simple-foreign-args
+        (x862-vpush-register seg (x862-one-untargeted-reg-form seg idx *x862-arg-z*)))
+      ;; Evaluate each form into the C frame, according to the
+      ;; matching argspec.
+      (do* ((specs argspecs (cdr specs))
+            (vals argvals (cdr vals)))
+           ((null specs))
+        (declare (list specs vals))
+        (let* ((valform (car vals))
+               (spec (car specs))
+               (absptr (acode-absolute-ptr-p valform)))
+          (case spec
+            (:address
+             (with-imm-target () (ptr :address)
+               (if absptr
+                 (x862-lri seg ptr absptr)
+                 (x862-form seg ptr nil valform))
+               (incf ngpr-args)
+               (cond ((<= ngpr-args 6)
+                      (! set-c-arg ptr gpr-offset)
+                      (incf gpr-offset))
+                     (t
+                      (! set-c-arg ptr other-offset)
+                      (incf other-offset)))))
+            (t
+             (with-imm-target () (valreg :natural)
+                (let* ((reg (x862-unboxed-integer-arg-to-reg seg valform valreg spec)))
+                  (incf ngpr-args)
+                  (cond ((<= ngpr-args 8)
+                         (! set-c-arg reg gpr-offset)
+                         (incf gpr-offset))
+                        (t
+                         (! set-c-arg reg other-offset)
+                         (incf other-offset)))))))))      
+      (unless simple-foreign-args
+        (x862-vpop-register seg ($ *x862-arg-z*)))
+      (! syscall) 
+      (x862-close-undo)
+      (when vreg
+        (cond ((eq resultspec :void) (<- nil))
+              ((eq resultspec :unsigned-doubleword)
+               (ensuring-node-target (target vreg)
+                 (! makeu64)
+                 (x862-copy-register seg target ($ *x862-arg-z*))))
+              ((eq resultspec :signed-doubleword)
+               (ensuring-node-target (target vreg)
+                 (! makes64)
+                 (x862-copy-register seg target ($ *x862-arg-z*))))
+              (t
+               (case resultspec
+                 (:signed-byte (! sign-extend-s8 *x862-imm0* *x862-imm0*))
+                 (:signed-halfword (! sign-extend-s16 *x862-imm0* *x862-imm0*))
+                 (:signed-fullword (! sign-extend-s32 *x862-imm0* *x862-imm0*))
+                 (:unsigned-byte (! zero-extend-u8 *x862-imm0* *x862-imm0*))
+                 (:unsigned-halfword (! zero-extend-u16 *x862-imm0* *x862-imm0*))
+                 (:unsigned-fullword (! zero-extend-u32 *x862-imm0* *x862-imm0*)))               
+               (<- (make-wired-lreg *x862-imm0*
+                                    :mode
+                                    (gpr-mode-name-value
+                                     (case resultspec
+                                       (:address :address)
+                                       (:signed-byte :s8)
+                                       (:unsigned-byte :u8)
+                                       (:signed-halfword :s16)
+                                       (:unsigned-halfword :u16)
+                                       (:signed-fullword :s32)
+                                       (t :u32))))))))
+      (^)))
+
+(defx862 x862-i386-ff-call i386-ff-call (seg vreg xfer address argspecs argvals resultspec &optional monitor)
+  (declare (ignore monitor))
+  #+debug
+  (format t "~&~%i386-ff-call: argspecs = ~s, argvals = ~s, resultspec = ~s"
+	  argspecs argvals resultspec)
+  (let* ((*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+         (*x862-cstack* *x862-cstack*)
+	 (offset 0)
+	 (simple-foreign-args nil)
+	 (nwords 0))
+    (dolist (argspec argspecs)
+      (case argspec
+	((:double-float :unsigned-doubleword :signed-doubleword)
+	 (incf nwords 2))
+	(t
+	 (if (typep argspec 'unsigned-byte)
+	   (incf nwords argspec)
+	   (incf nwords)))))
+    (when (null argspecs)
+      (setq simple-foreign-args t))
+    (! alloc-c-frame nwords)
+    (x862-open-undo $undo-x86-c-frame)
+    (unless simple-foreign-args
+      (x862-vpush-register seg (x862-one-untargeted-reg-form seg address x8632::arg_z)))
+    ;; Evaluate each form into the C frame, according to the
+    ;; matching argspec.
+    (do* ((specs argspecs (cdr specs))
+	  (vals argvals (cdr vals)))
+	 ((null specs))
+      (declare (list specs vals))
+      (let* ((valform (car vals))
+	     (spec (car specs))
+	     (absptr (acode-absolute-ptr-p valform)))
+	(case spec
+	  (:registers
+	   (error "don't know what to do with argspec ~s" spec))
+	  (:double-float
+	   (let* ((df ($ x8632::fp0 :class :fpr :mode :double-float)))
+	     (x862-one-targeted-reg-form seg valform df)
+	     (! set-double-c-arg df offset))
+	   (incf offset 2))
+	  (:single-float
+	   (let* ((sf ($ x8632::fp0 :class :fpr :mode :single-float)))
+	     (x862-one-targeted-reg-form seg valform sf)
+	     (! set-single-c-arg sf offset))
+	   (incf offset))
+	  (:address
+	   (with-imm-target () (ptr :address)
+	     (if absptr
+	       (x862-lri seg ptr absptr)
+	       (x862-form seg ptr nil valform))
+	     (! set-c-arg ptr offset))
+	   (incf offset))
+          ((:signed-doubleword :unsigned-doubleword)
+           (x862-one-targeted-reg-form seg valform x8632::arg_z)
+           ;; Subprims return 64-bit result in mm0
+           (if (eq spec :unsigned-doubleword)
+             (! getu64)
+             (! gets64))
+           (! set-c-arg-from-mm0 offset)
+           (incf offset 2))
+	  (t
+	   (if (typep spec 'unsigned-byte)
+	     (progn
+	       (with-imm-target () (ptr :address)
+		 (x862-one-targeted-reg-form seg valform ptr)
+		 (with-additional-imm-reg (ptr)
+		   (with-imm-temps (ptr) (r)
+		     (dotimes (i spec)
+		       (! mem-ref-c-fullword r ptr (ash i x8632::word-shift))
+		       (! set-c-arg r (+ offset i))))))
+	       (incf offset spec))
+	     (with-imm-target () (valreg :natural)
+	       (let* ((reg (x862-unboxed-integer-arg-to-reg seg valform valreg spec)))
+		 (! set-c-arg reg offset)
+		 (incf offset))))))))
+    (if simple-foreign-args
+      (x862-one-targeted-reg-form seg address x8632::arg_z)
+      (x862-vpop-register seg ($ x8632::arg_z)))
+    (! ff-call)
+    (x862-close-undo)
+    (when vreg
+      (cond ((eq resultspec :void) (<- nil))
+	    ;; Floating-point results are returned on the x87 stack.
+	    ((eq resultspec :double-float)
+	     (let ((fpreg ($ x8632::fp0 :class :fpr :mode :double-float)))
+	       (! fp-stack-to-double fpreg)
+	       (<- fpreg)))
+	    ((eq resultspec :single-float)
+	     (let ((fpreg ($ x8632::fp0 :class :fpr :mode :single-float)))
+	       (! fp-stack-to-single fpreg)
+	       (<- fpreg)))
+	    ((eq resultspec :unsigned-doubleword)
+	     (ensuring-node-target (target vreg)
+               (! get-64-bit-ffcall-result)
+	       (! makeu64)
+	       (x862-copy-register seg target ($ *x862-arg-z*))))
+	    ((eq resultspec :signed-doubleword)
+	     (ensuring-node-target (target vreg)
+               (! get-64-bit-ffcall-result)
+	       (! makes64)
+	       (x862-copy-register seg target ($ *x862-arg-z*))))
+	    (t
+	     (case resultspec
+	       (:signed-byte (! sign-extend-s8 *x862-imm0* *x862-imm0*))
+	       (:signed-halfword (! sign-extend-s16 *x862-imm0* *x862-imm0*))
+	       (:unsigned-byte (! zero-extend-u8 *x862-imm0* *x862-imm0*))
+	       (:unsigned-halfword (! zero-extend-u16 *x862-imm0* *x862-imm0*)))
+	     (<- (make-wired-lreg x8632::imm0
+				  :mode
+				  (gpr-mode-name-value
+				   (case resultspec
+				     (:address :address)
+				     (:signed-byte :s8)
+				     (:unsigned-byte :u8)
+				     (:signed-halfword :s16)
+				     (:unsigned-halfword :u16)
+				     (:signed-fullword :s32)
+				     (t :u32))))))))
+    (^)))
+
+(defx862 x862-ff-call ff-call (seg vreg xfer address argspecs argvals resultspec &optional monitor)
+  (declare (ignore monitor))
+  (let* ((*x862-vstack* *x862-vstack*)
+         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
+         (*x862-cstack* *x862-cstack*)
+         (gpr-offset 0)
+         (other-offset 6)
+         (single-float-offset 6)
+         (double-float-offset 6)
+         (nsingle-floats 0)              ; F
+         (ndouble-floats 0)             ; D
+         (nother-words 0)
+         (nfpr-args 0)
+         (ngpr-args 0)
+         (simple-foreign-args nil)
+         (fp-loads ())
+         (return-registers ()))
+      (declare (fixnum  nsingle-floats ndouble-floats nfpr-args ngpr-args nother-words
+                        gpr-offset other-offset single-float-offset double-float-offset))
+      (dolist (argspec argspecs)
+        (case argspec
+          (:double-float (incf nfpr-args)
+                         (if (<= nfpr-args 8)
+                           (incf ndouble-floats)
+                           (incf nother-words)))
+          (:single-float (incf nfpr-args)
+                         (if (<= nfpr-args 8)
+                           (incf nsingle-floats)
+                           (incf nother-words)))
+          (:registers (setq return-registers t))
+          (t
+           (if (typep argspec 'unsigned-byte)
+             (incf nother-words argspec)
+             (progn
+               (incf ngpr-args)
+               (if (> ngpr-args 6)
+                 (incf nother-words)))))))
+      (let* ((total-words (+ nother-words nsingle-floats ndouble-floats)))
+        (when (null argspecs)
+          (setq simple-foreign-args t))
+        (! alloc-c-frame total-words))
+      (x862-open-undo $undo-x86-c-frame)
+      (setq single-float-offset (+ other-offset nother-words))
+      (setq double-float-offset
+            (+ single-float-offset nsingle-floats))
+      (setq ngpr-args 0 nfpr-args 0)
+      (unless simple-foreign-args
+        (x862-vpush-register seg (x862-one-untargeted-reg-form seg address x8664::arg_z)))
+      ;; Evaluate each form into the C frame, according to the
+      ;; matching argspec.  Remember type and arg offset of any FP
+      ;; args, since FP regs will have to be loaded later.
+      (do* ((specs argspecs (cdr specs))
+            (vals argvals (cdr vals)))
+           ((null specs))
+        (declare (list specs vals))
+        (let* ((valform (car vals))
+               (spec (car specs))
+               (absptr (acode-absolute-ptr-p valform)))
+          (case spec
+            (:registers
+             (let* ((reg (x862-one-untargeted-reg-form seg valform x8664::arg_z)))
+               (unless *x862-reckless*
+                 (! trap-unless-macptr reg))
+               (x862-vpush-register seg reg)))
+            (:double-float
+             (let* ((df ($ x8664::fp1 :class :fpr :mode :double-float)))
+               (incf nfpr-args)
+               (x862-one-targeted-reg-form seg valform df )
+               (cond ((<= nfpr-args 8)
+                      (! set-double-c-arg df double-float-offset)
+                      (push (cons :double-float double-float-offset) fp-loads)
+                      (incf double-float-offset))
+                     (t
+                      (! set-double-c-arg df other-offset)
+                      (incf other-offset)))))
+            (:single-float
+             (let* ((sf ($ x8664::fp1 :class :fpr :mode :single-float)))
+               (incf nfpr-args)
+               (x862-one-targeted-reg-form
+                seg valform sf)
+               (cond ((<= nfpr-args 8)
+                      (! set-single-c-arg sf single-float-offset)
+                      (push (cons :single-float single-float-offset) fp-loads)
+                      (incf single-float-offset))
+                     (t
+                      (! set-single-c-arg sf other-offset)
+                      (incf other-offset)))))            
+            (:address
+             (with-imm-target () (ptr :address)
+               (if absptr
+                 (x862-lri seg ptr absptr)
+                 (x862-form seg ptr nil valform))
+               (incf ngpr-args)
+               (cond ((<= ngpr-args 6)
+                      (! set-c-arg ptr gpr-offset)
+                      (incf gpr-offset))
+                     (t
+                      (! set-c-arg ptr other-offset)
+                      (incf other-offset)))))
+            (t
+             (if (typep spec 'unsigned-byte)
+               (progn
+                 (with-imm-target () (ptr :address)
+                   (x862-one-targeted-reg-form seg valform ptr)
+                   (with-imm-target (ptr) (r :natural)
+                     (dotimes (i spec)
+                       (! mem-ref-c-doubleword r ptr (ash i x8664::word-shift))
+                       (! set-c-arg r other-offset)
+                       (incf other-offset)))))               
+               (with-imm-target () (valreg :natural)
+                 (let* ((reg (x862-unboxed-integer-arg-to-reg seg valform valreg spec)))
+                   (incf ngpr-args)
+                   (cond ((<= ngpr-args 6)
+                          (! set-c-arg reg gpr-offset)
+                          (incf gpr-offset))
+                         (t
+                          (! set-c-arg reg other-offset)
+                          (incf other-offset))))))))))
+      (do* ((fpreg x8664::fp0 (1+ fpreg))
+            (reloads (nreverse fp-loads) (cdr reloads)))
+           ((or (null reloads) (= fpreg x8664::fp8)))
+        (declare (list reloads) (fixnum fpreg))
+        (let* ((reload (car reloads))
+               (size (car reload))
+               (from (cdr reload)))
+          (if (eq size :double-float)
+            (! reload-double-c-arg ($ fpreg :class :fpr :mode :double-float) from)
+            (! reload-single-c-arg ($ fpreg :class :fpr :mode :single-float) from))))
+      (if return-registers
+        (x862-vpop-register seg ($ x8664::arg_y)))
+      (if simple-foreign-args
+        (x862-one-targeted-reg-form seg address x8664::arg_z)
+        (x862-vpop-register seg ($ x8664::arg_z)))
+      (x862-lri seg x8664::rax (min 8 nfpr-args))
+      (if return-registers
+        (! ff-call-return-registers)
+        (! ff-call) )
+      (x862-close-undo)
+      (when vreg
+        (cond ((eq resultspec :void) (<- nil))
+              ((eq resultspec :double-float)
+               (<- ($  x8664::fp0 :class :fpr :mode :double-float)))
+              ((eq resultspec :single-float)
+               (<- ($ x8664::fp0 :class :fpr :mode :single-float)))
+              ((eq resultspec :unsigned-doubleword)
+               (if (node-reg-p vreg)
+                 (progn
+                   (! makeu64)
+                   (<- ($ x8664::arg_z)))
+                 (<- ($  x8664::rax :class :gpr :mode :u64))))
+              ((eq resultspec :signed-doubleword)
+               (if (node-reg-p vreg)
+                 (progn
+                   (! makes64)
+                   (<- ($ x8664::arg_z)))
+                 (<- ($  x8664::rax :class :gpr :mode :s64))))
+              (t
+               (case resultspec
+                 (:signed-byte (! sign-extend-s8 x8664::imm0 x8664::imm0))
+                 (:signed-halfword (! sign-extend-s16 x8664::imm0 x8664::imm0))
+                 (:signed-fullword (! sign-extend-s32 x8664::imm0 x8664::imm0))
+                 (:unsigned-byte (! zero-extend-u8 x8664::imm0 x8664::imm0))
+                 (:unsigned-halfword (! zero-extend-u16 x8664::imm0 x8664::imm0))
+                 (:unsigned-fullword (! zero-extend-u32 x8664::imm0 x8664::imm0)))
+               (<- (make-wired-lreg x8664::imm0
+                                    :mode
+                                    (gpr-mode-name-value
+                                     (case resultspec
+                                       (:address :address)
+                                       (:signed-byte :s8)
+                                       (:unsigned-byte :u8)
+                                       (:signed-halfword :s16)
+                                       (:unsigned-halfword :u16)
+                                       (:signed-fullword :s32)
+                                       (t :u32))))))))
+      (^)))
+
+
+             
+(defx862 x862-%temp-list %temp-list (seg vreg xfer arglist)
+  (x862-use-operator (%nx1-operator list) seg vreg xfer arglist))
+
+(defx862 x862-%temp-cons %temp-cons (seg vreg xfer car cdr)
+  (x862-use-operator (%nx1-operator cons) seg vreg xfer car cdr))
+
+
+
+(defx862 x862-%debug-trap %debug-trap (seg vreg xfer arg)
+  (x862-one-targeted-reg-form seg arg ($ *x862-arg-z*))
+  (! %debug-trap)
+  (<- ($ *x862-arg-z*))
+  (^))
+
+(defx862 x862-%reference-external-entry-point %reference-external-entry-point
+  (seg vreg xfer arg)
+  (ensuring-node-target (target vreg)
+    (let* ((reg (if (eq (hard-regspec-value target) *x862-arg-z*) ($ *x862-arg-y*) ($ *x862-arg-z*))))
+      (x862-one-targeted-reg-form seg arg reg)
+      (! eep.address target reg)))
+  (^))
+
+(defx862 x862-%natural+ %natural+ (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil x)
+      (x862-form seg nil xfer y))
+    (let* ((fix-x (acode-fixnum-form-p x))
+           (fix-y (acode-fixnum-form-p y)))
+      (if (and fix-x fix-y)
+        (x862-absolute-natural seg vreg xfer (+ fix-x fix-y))
+        (let* ((u31x (and (typep fix-x '(unsigned-byte 31)) fix-x))
+               (u31y (and (typep fix-y '(unsigned-byte 31)) fix-y)))
+          (if (not (or u31x u31y))
+            (with-imm-target () (xreg :natural)
+	      (with-additional-imm-reg ()
+		(with-imm-target (xreg) (yreg :natural)
+		  (x862-two-targeted-reg-forms seg x xreg y yreg)
+		  (! %natural+ xreg yreg)))
+              (<- xreg))
+            (let* ((other (if u31x y x)))
+              (with-imm-target () (other-reg :natural)
+                (x862-one-targeted-reg-form seg other other-reg)
+                (! %natural+-c  other-reg (or u31x u31y))
+                (<- other-reg))))
+          (^))))))
+
+(defx862 x862-%natural- %natural- (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil x)
+      (x862-form seg nil xfer y))
+    (let* ((fix-x (acode-fixnum-form-p x))
+           (fix-y (acode-fixnum-form-p y)))
+      (if (and fix-x fix-y)
+        (x862-absolute-natural seg vreg xfer (- fix-x fix-y))
+        (let* ((u31y (and (typep fix-y '(unsigned-byte 31)) fix-y)))
+          (if (not u31y)
+	    (with-imm-target () (xreg :natural)
+	      (with-additional-imm-reg ()
+		(with-imm-target (xreg) (yreg :natural)
+		  (x862-two-targeted-reg-forms seg x xreg y yreg)
+		  (! %natural- xreg yreg))
+		(<- xreg)))
+            (progn
+              (with-imm-target () (xreg :natural)
+                (x862-one-targeted-reg-form seg x xreg)
+                (! %natural--c xreg u31y)
+                (<- xreg))))
+          (^))))))
+
+(defx862 x862-%natural-logior %natural-logior (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil x)
+      (x862-form seg nil xfer y))
+    (let* ((naturalx (nx-natural-constant-p x))
+           (naturaly (nx-natural-constant-p y)))
+      (if (and naturalx naturaly) 
+        (x862-absolute-natural seg vreg xfer (logior naturalx naturaly))
+        (let* ((u31x (nx-u31-constant-p x))
+               (u31y (nx-u31-constant-p y))
+               (constant (or u31x u31y)))
+          (if (not constant)
+            (with-imm-target () (xreg :natural)
+	      (with-additional-imm-reg ()
+		(with-imm-target (xreg) (yreg :natural)
+		  (x862-two-targeted-reg-forms seg x xreg y yreg)
+		  (! %natural-logior xreg yreg)))
+              (<- xreg))
+            (let* ((other (if u31x y x)))
+              (with-imm-target () (other-reg :natural)
+                (x862-one-targeted-reg-form seg other other-reg)
+                (! %natural-logior-c other-reg constant)
+                (<- other-reg))))
+          (^))))))
+
+(defx862 x862-%natural-logxor %natural-logxor (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil x)
+      (x862-form seg nil xfer y))
+    (let* ((naturalx (nx-natural-constant-p x))
+           (naturaly (nx-natural-constant-p y)))
+      (if (and naturalx naturaly) 
+        (x862-absolute-natural seg vreg xfer (logxor naturalx naturaly))
+        (let* ((u32x (nx-u32-constant-p x))
+               (u32y (nx-u32-constant-p y))
+               (constant (or u32x u32y)))
+          (if (not constant)
+            (with-imm-target () (xreg :natural)
+	      (with-additional-imm-reg ()
+		(with-imm-target (xreg) (yreg :natural)
+		  (x862-two-targeted-reg-forms seg x xreg y yreg)
+		  (! %natural-logxor xreg yreg)))
+              (<- xreg))
+            (let* ((other (if u32x y x)))
+              (with-imm-target () (other-reg :natural)
+                (x862-one-targeted-reg-form seg other other-reg)
+                (! %natural-logxor-c other-reg constant)
+                (<- other-reg))))
+          (^))))))
+
+(defx862 x862-%natural-logand %natural-logand (seg vreg xfer x y)
+  (if (null vreg)
+    (progn
+      (x862-form seg nil nil x)
+      (x862-form seg nil xfer y))
+    (let* ((naturalx (nx-natural-constant-p x))
+           (naturaly (nx-natural-constant-p y)))
+      (if (and naturalx naturaly) 
+        (x862-absolute-natural seg vreg xfer (logand naturalx naturaly))
+        (let* ((u31x (nx-u31-constant-p x))
+               (u31y (nx-u31-constant-p y))
+               (constant (or u31x u31y)))
+          (if (not constant)
+            (with-imm-target () (xreg :natural)
+	      (with-additional-imm-reg ()
+		(with-imm-target (xreg) (yreg :natural)
+		  (x862-two-targeted-reg-forms seg x xreg y yreg)
+		  (! %natural-logand xreg yreg)))
+              (<- xreg))
+            (let* ((other (if u31x y x)))
+              (with-imm-target () (other-reg :natural)
+                (x862-one-targeted-reg-form seg other other-reg)
+                (! %natural-logand-c  other-reg constant)
+                (<- other-reg))))
+          (^))))))
+
+(defx862 x862-natural-shift-right natural-shift-right (seg vreg xfer num amt)
+  (with-imm-target () (dest :natural)
+    (x862-one-targeted-reg-form seg num dest)
+    (! natural-shift-right dest (acode-fixnum-form-p amt))
+    (<- dest)
+    (^)))
+
+(defx862 x862-natural-shift-left natural-shift-left (seg vreg xfer num amt)
+  (with-imm-target () (dest :natural)
+    (x862-one-targeted-reg-form seg num dest)
+    (! natural-shift-left dest  (acode-fixnum-form-p amt))
+    (<- dest)
+    (^)))
+
+;;; This assumes that "global" variables are always boundp.
+(defx862 x862-global-ref global-ref (seg vreg xfer sym)
+  (when vreg
+    (ensuring-node-target (target vreg)
+      (with-node-temps () (symreg)
+        (setq symreg (or (x862-register-constant-p sym)
+                         (x862-store-immediate seg sym symreg)))
+        (! symbol-ref target symreg (target-arch-case
+				     (:x8632 x8632::symbol.vcell-cell)
+				     (:x8664 x8664::symbol.vcell-cell))))))
+  (^))
+
+(defx862 x862-global-setq global-setq (seg vreg xfer sym val)
+  (x862-vset seg 
+             vreg 
+             xfer
+             :symbol
+             (make-acode (%nx1-operator %symptr->symvector)
+                         (make-acode (%nx1-operator immediate) sym))
+             (make-acode (%nx1-operator fixnum)
+                         (target-arch-case
+			  (:x8632 x8632::symbol.vcell-cell)
+                          (:x8664 x8664::symbol.vcell-cell)))
+             val
+             nil))
+
+(defx862 x862-%current-frame-ptr %current-frame-ptr (seg vreg xfer)
+  (cond ((x862-tailcallok xfer)
+	 (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count*)
+	 (x862-restore-full-lisp-context seg)
+	 (! %current-frame-ptr ($ *x862-arg-z*))
+	 (! jump-return-pc))
+	(t
+	 (when vreg
+	   (ensuring-node-target (target vreg)
+				 (! %current-frame-ptr target)))
+	 (^))))
+
+(defx862 x862-%foreign-stack-pointer %foreign-stack-pointer (seg vreg xfer)
+   (when vreg
+     (ensuring-node-target (target vreg)
+       (! %foreign-stack-pointer target)))
+   (^))
+
+
+(defx862 x862-%current-tcr %current-tcr (seg vreg xfer)
+  (when vreg
+    (ensuring-node-target (target vreg)
+      (! %current-tcr target)))
+  (^))
+
+
+
+(defx862 x862-%interrupt-poll %interrupt-poll (seg vreg xfer)
+  (! event-poll)
+  (x862-nil seg vreg xfer))
+
+
+(defx862 x862-with-c-frame with-c-frame (seg vreg xfer body &aux
+                                             (old-stack (x862-encode-stack)))
+  (! alloc-c-frame 0)
+  (x862-open-undo $undo-x86-c-frame)
+  (x862-undo-body seg vreg xfer body old-stack))
+
+(defx862 x862-with-variable-c-frame with-variable-c-frame (seg vreg xfer size body &aux
+                                                               (old-stack (x862-encode-stack)))
+  (let* ((reg (x862-one-untargeted-reg-form seg size *x862-arg-z*)))
+    (! alloc-variable-c-frame reg)
+    (x862-open-undo $undo-x86-c-frame)
+    (x862-undo-body seg vreg xfer body old-stack)))
+
+(defx862 x862-%symbol->symptr %symbol->symptr (seg vreg xfer sym)
+  (let* ((src (x862-one-untargeted-reg-form seg sym *x862-arg-z*)))
+    (ensuring-node-target (target vreg)
+      (! %symbol->symptr target src))
+    (^)))
+
+(defx862 x862-%double-to-single %double-to-single (seg vreg xfer arg)
+  (if (null vreg)
+    (x862-form seg vreg xfer arg)
+    (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+             (= (get-regspec-mode vreg) hard-reg-class-fpr-mode-single))
+      (let* ((dreg (x862-one-untargeted-reg-form 
+                    seg arg
+                    (make-wired-lreg (hard-regspec-value vreg)
+                                     :class hard-reg-class-fpr
+                                     :mode hard-reg-class-fpr-mode-double))))
+        (! double-to-single vreg dreg)
+        (^))
+      (with-fp-target () (argreg :double-float)
+        (x862-one-targeted-reg-form seg arg argreg)
+        (with-fp-target ()  (sreg :single-float)
+          (! double-to-single sreg argreg)
+          (<- sreg)
+          (^))))))
+
+(defx862 x862-%single-to-double %single-to-double (seg vreg xfer arg)
+  (if (null vreg)
+    (x862-form seg vreg xfer arg)
+    (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
+             (= (get-regspec-mode vreg) hard-reg-class-fpr-mode-double))
+      (let* ((sreg (x862-one-untargeted-reg-form 
+                    seg arg
+                    (make-wired-lreg (hard-regspec-value vreg)
+                                     :class hard-reg-class-fpr
+                                     :mode hard-reg-class-fpr-mode-double))))
+        (! single-to-double vreg sreg)
+        (^))
+      (with-fp-target () (sreg :single-float)
+        (x862-one-targeted-reg-form seg arg sreg)
+        (with-fp-target () (dreg :double-float)
+          (! single-to-double dreg sreg)
+          (<- dreg)
+          (^))))))
+
+(defx862 x862-%symptr->symvector %symptr->symvector (seg vreg xfer arg)
+  (if (null vreg)
+    (x862-form seg vreg xfer arg)
+    (progn
+      (ensuring-node-target (target vreg)
+        (x862-one-targeted-reg-form seg arg target)
+        (! %symptr->symvector target))
+      (^))))
+
+(defx862 x862-%symvector->symptr %symvector->symptr (seg vreg xfer arg)
+  (if (null vreg)
+    (x862-form seg vreg xfer arg)
+    (progn
+      (ensuring-node-target (target vreg)
+        (x862-one-targeted-reg-form seg arg target)
+        (! %symvector->symptr target))
+      (^))))
+
+(defx862 x862-%fixnum-to-single %fixnum-to-single (seg vreg xfer arg)
+  (with-fp-target () (sreg :single-float)
+    (let* ((r (x862-one-untargeted-reg-form seg arg *x862-arg-z*)))
+      (unless (or (acode-fixnum-form-p arg)
+                  *x862-reckless*)
+        (! trap-unless-fixnum r))
+      (! fixnum->single-float sreg r)
+      (<- sreg)
+      (^))))
+
+(defx862 x862-%fixnum-to-double %fixnum-to-double (seg vreg xfer arg)
+  (with-fp-target () (dreg :double-float)
+    (let* ((r (x862-one-untargeted-reg-form seg arg *x862-arg-z*)))
+      (unless (or (acode-fixnum-form-p arg)
+                  *x862-reckless*)
+        (! trap-unless-fixnum r))
+      (! fixnum->double-float dreg r)
+      (<- dreg)
+      (^))))
+
+(defx862 x862-%double-float %double-float (seg vreg xfer arg)
+  (let* ((real (or (acode-fixnum-form-p arg)
+                   (let* ((form (acode-unwrapped-form-value arg)))
+                     (if (and (acode-p form)
+                              (eq (acode-operator form)
+                                  (%nx1-operator immediate))
+                              (typep (cadr form) 'real))
+                       (cadr form)))))
+         (dconst (and real (ignore-errors (float real 0.0d0)))))
+    (if dconst
+      (x862-immediate seg vreg xfer dconst)
+      (if (x862-form-typep arg 'single-float)
+        (x862-use-operator (%nx1-operator %single-to-double)
+                           seg
+                           vreg
+                           xfer
+                           arg)
+        (if (x862-form-typep arg 'fixnum)
+          (x862-use-operator (%nx1-operator %fixnum-to-double)
+                             seg
+                             vreg
+                             xfer
+                             arg)
+          (x862-use-operator (%nx1-operator call)
+                             seg
+                             vreg
+                             xfer
+                             (make-acode (%nx1-operator immediate)
+                                         '%double-float)
+                             (list nil (list arg))))))))
+
+(defx862 x862-%single-float %single-float (seg vreg xfer arg)
+  (let* ((real (or (acode-fixnum-form-p arg)
+                   (let* ((form (acode-unwrapped-form-value arg)))
+                     (if (and (acode-p form)
+                              (eq (acode-operator form)
+                                  (%nx1-operator immediate))
+                              (typep (cadr form) 'real))
+                       (cadr form)))))
+         (sconst (and real (ignore-errors (float real 0.0f0)))))
+    (if sconst
+      (x862-immediate seg vreg xfer sconst)
+      (if (x862-form-typep arg 'double-float)
+        (x862-use-operator (%nx1-operator %double-to-single)
+                           seg
+                           vreg
+                           xfer
+                           arg)
+        (if (x862-form-typep arg 'fixnum)
+          (x862-use-operator (%nx1-operator %fixnum-to-single)
+                             seg
+                             vreg
+                             xfer
+                             arg)
+          (x862-use-operator (%nx1-operator call)
+                             seg
+                             vreg
+                             xfer
+                             (make-acode (%nx1-operator immediate)
+                                         '%short-float)
+                             (list nil (list arg))))))))
+
+
+(defx862 x862-%new-ptr %new-ptr (seg vreg xfer size clear-p )
+  (x862-call-fn seg
+                vreg
+                xfer
+                (make-acode (%nx1-operator immediate)
+                            '%new-gcable-ptr)
+                (list nil (list clear-p size))
+                nil))
+
+;------
+
+#+not-yet
+(progn
+
+
+;;;Make a gcable macptr.
+
+
+
+
+)
+
+#-x86-target
+(defun x8664-xcompile-lambda (def &key show-vinsns (symbolic-names t)
+                                  (target :darwinx8664)
+                                  (disassemble t))
+  (let* ((*x862-debug-mask* (if show-vinsns
+                              (ash 1 x862-debug-vinsns-bit)
+                              0))
+         (backend (find-backend target))
+         (*target-ftd* (if backend
+                         (backend-target-foreign-type-data backend)
+                         *target-ftd*)))
+    (multiple-value-bind (xlfun warnings)
+        (compile-named-function def :target target)
+      (signal-or-defer-warnings warnings nil)
+      (when disassemble
+        (format t "~%~%")
+        (apply #'x86-disassemble-xfunction
+               xlfun
+               (unless symbolic-names (list nil))))
+      xlfun)))
+
+#-x8632-target
+(defun x8632-xcompile-lambda (def &key show-vinsns (symbolic-names t)
+                                  (target :darwinx8632)
+                                  (disassemble t))
+  (let* ((*x862-debug-mask* (if show-vinsns
+                              (ash 1 x862-debug-vinsns-bit)
+                              0))
+         (backend (find-backend target))
+         (*target-ftd* (if backend
+                         (backend-target-foreign-type-data backend)
+                         *target-ftd*)))
+    (multiple-value-bind (xlfun warnings)
+        (compile-named-function def :target target)
+      (signal-or-defer-warnings warnings nil)
+      (when disassemble
+	(let ((*target-backend* backend))
+	  (format t "~%~%")
+	  (apply #'x86-disassemble-xfunction
+		 xlfun
+		 (unless symbolic-names (list nil)))))
+      xlfun)))
+
+
Index: /branches/new-random/compiler/acode-rewrite.lisp
===================================================================
--- /branches/new-random/compiler/acode-rewrite.lisp	(revision 13309)
+++ /branches/new-random/compiler/acode-rewrite.lisp	(revision 13309)
@@ -0,0 +1,379 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+(defvar *acode-post-trust-decls* nil)
+
+;;; Rewrite acode trees.
+
+(next-nx-defops)
+(defvar *acode-rewrite-functions* nil)
+(let* ((newsize (%i+ (next-nx-num-ops) 10))
+       (old *acode-rewrite-functions*)
+       (oldsize (length old)))
+  (declare (fixnum newsize oldsize))
+  (unless (>= oldsize newsize)
+    (let* ((v (make-array newsize :initial-element nil)))
+      (dotimes (i oldsize (setq *acode-rewrite-functions* v))
+        (setf (svref v i) (svref old i))))))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro def-acode-rewrite (name operator-list arglist &body body)
+    (if (atom operator-list)
+      (setq operator-list (list operator-list)))
+    (multiple-value-bind (body decls)
+        (parse-body body nil t)
+      (collect ((let-body))
+        (dolist (operator operator-list)
+          (let-body `(setf (svref *acode-rewrite-functions* (logand operator-id-mask (%nx1-operator ,operator))) fun)))
+        (destructuring-bind (op whole type) arglist
+        `(let* ((fun (nfunction ,name 
+                                (lambda (,op ,whole ,type)
+                                  (declare (ignorable ,op ,type))
+                                  ,@decls
+                                  (block ,name ,@body)))))
+          ,@(let-body)))))))
+
+;;; Don't walk the form (that's already happened.)
+(defun acode-post-form-type (form)
+  (when (acode-p form)
+    (let* ((op (acode-operator form))
+           (operands (cdr form)))
+      (cond ((and *acode-post-trust-decls*
+                  (eq op (%nx1-operator typed-form)))
+             (acode-operand 0 operands))
+            ((eq op (%nx1-operator fixnum))
+             'fixnum)
+            ((eq op (%nx1-operator immediate))
+             (type-of (acode-operand 0 operands)))
+            (t t)))))
+
+(defun acode-constant-p (form)
+  (let* ((form (acode-unwrapped-form-value form)))
+    (or (eq form *nx-nil*)
+        (eq form *nx-t*)
+        (let* ((operator (if (acode-p form) (acode-operator form))))
+          (or (eq operator (%nx1-operator fixnum))
+              (eq operator (%nx1-operator immediate)))))))
+
+(defun acode-post-form-typep (form type)
+  (let* ((ctype (specifier-type type))
+         (form (acode-unwrapped-form-value form)))
+    (cond ((eq form *nx-nil*) (ctypep nil ctype))
+          ((eq form *nx-t*) (ctypep t ctype))
+          ((not (acode-p form)) (values nil nil))
+          (t
+           (let* ((op (acode-operator form))
+                  (operands (cdr form)))
+             (cond ((and *acode-post-trust-decls*
+                         (eq op (%nx1-operator typed-form)))
+                    (subtypep (acode-operand 0 operands) type))
+                   ((or (eq op (%nx1-operator fixnum))
+                        (eq op (%nx1-operator immediate)))
+                    (ctypep (acode-operand 0 operands) (specifier-type type)))
+                   (t (values nil nil))))))))
+
+             
+
+(defun rewrite-acode-ref (ref &optional (type t))
+  (let* ((form (car ref)))
+    (if (acode-p form)
+      (let* ((op (acode-operator form))
+             (rewrite (svref *acode-rewrite-functions* (logand op operator-id-mask))))
+        (when rewrite
+          (let* ((new (funcall rewrite op (cdr form) type)))
+            (when new
+              (setf (car ref) new)
+              t)))))))
+
+;;; Maybe ewrite the operands of a binary real arithmetic operation
+(defun acode-post-binop-numeric-contagion (pform1 pform2)
+  (let* ((form1 (car pform1))
+         (form2 (car pform2)))
+    (cond ((acode-post-form-typep form1 'double-float)
+           (unless (acode-post-form-typep form2 'double-float)
+             (let* ((c2 (acode-real-constant-p form2)))
+               (if c2
+                 (setf (car pform2)
+                       (make-acode (%nx1-operator immediate)
+                                   (float c2 0.0d0)))
+                 (if (acode-post-form-typep form2 'fixnum)
+                   (setf (car pform2)
+                         (make-acode (%nx1-operator typed-form)
+                                     'double-float
+                                     (make-acode (%nx1-operator %fixnum-to-double)
+                                                 form2))))))))
+          ((acode-post-form-typep form2 'double-float)
+           (let* ((c1 (acode-real-constant-p form1)))
+             (if c1
+               (setf (car pform1)
+                     (make-acode (%nx1-operator immediate)
+                                 (float c1 0.0d0)))
+               (if (acode-post-form-typep form1 'fixnum)
+                 (setf (car pform1)
+                       (make-acode (%nx1-operator typed-form)
+                                   'double-float
+                                   (make-acode (%nx1-operator %fixnum-to-double)
+                                               form1)))))))
+          ((acode-post-form-typep form1 'single-float)
+           (unless (acode-post-form-typep form2 'single-float)
+             (let* ((c2 (acode-real-constant-p form2)))
+               (if c2
+                 (setf (car pform2) (make-acode (%nx1-operator immediate)
+                                                (float c2 0.0f0)))
+                 (if (acode-post-form-typep form2 'fixnum)
+                   (setf (car pform2)
+                         (make-acode (%nx1-operator typed-form)
+                                     'single-float
+                                     (make-acode (%nx1-operator %fixnum-to-single)
+                                                 form2))))))))
+          ((acode-post-form-typep form2 'single-float)
+           (let* ((c1 (acode-real-constant-p form1)))
+             (if c1
+               (setf (car pform1) (make-acode (%nx1-operator immediate)
+                                              (float c1 0.0f0)))
+
+               (if (acode-post-form-typep form1 'fixnum)
+                 (setf (car pform1)
+                       (make-acode (%nx1-operator typed-form)
+                                   'single-float
+                                   (make-acode (%nx1-operator %fixnum-to-single)
+                                               form1))))))))))
+
+(defun constant-fold-acode-binop (function x y)
+  (let* ((constant-x (acode-real-constant-p x))
+         (constant-y (acode-real-constant-p y)))
+    (if (and constant-x constant-y)
+      (let* ((result (ignore-errors (funcall function x y))))
+        (when result
+          (nx1-form result))))))
+
+(defun acode-rewrite-and-fold-binop (function args)
+  (rewrite-acode-ref args)
+  (rewrite-acode-ref (cdr args))
+  (constant-fold-acode-binop function (car args) (cadr args)))
+
+(defun rewrite-acode-forms (forms)
+  (do* ((head forms (cdr head)))
+       ((null head))
+    (rewrite-acode-ref head)))
+
+(defun acode-assert-type (actualtype operator operands assertedtype)
+  (make-acode (%nx1-operator typed-form)
+              (type-specifier (type-intersection (specifier-type actualtype)
+                                                 (specifier-type assertedtype)))
+              (cons operator operands)))
+
+(def-acode-rewrite acode-rewrite-progn progn (op w type)
+  (rewrite-acode-forms w))
+
+(def-acode-rewrite acode-rewrite-not not (op w type)
+  (rewrite-acode-ref w))
+
+(def-acode-rewrite acode-rewrite-%i+ %i+ (op w type)
+  (or 
+   (acode-rewrite-and-fold-binop '+ w)
+   ;; TODO: maybe cancel overflow check, assert FIXNUM result.
+   (acode-assert-type 'integer op w type)))
+
+(def-acode-rewrite acode-rewrite-%i- %i- (op w type)
+  (or
+   (acode-rewrite-and-fold-binop '- w))
+   ;; TODO: maybe cancel overflow check, assert FIXNUM result.
+   (acode-assert-type 'integer op w type))  
+
+(def-acode-rewrite acode-rewrite-%ilsl %ilsl (op w type)
+  (or
+   (acode-rewrite-and-fold-binop '%ilsl w)
+   (acode-assert-type 'fixnum op w type)))
+
+(def-acode-rewrite acode-rewrite-%ilogand2 %ilogand2 (op w type)
+  (or
+   (acode-rewrite-and-fold-binop 'logand w)
+   ;; If either argument's an UNSIGNED-BYTE constant, the result
+   ;; is an UNSIGNED-BYTE no greater than that constant.
+   (destructuring-bind (x y) w
+     (let* ((fix-x (acode-fixnum-form-p x))
+            (fix-y (acode-fixnum-form-p y)))
+       (acode-assert-type (if fix-x
+                            `(integer 0 ,fix-x)
+                            (if fix-y
+                              `(integer 0 ,fix-y)
+                              'fixnum))
+                          op w type)))))
+
+(def-acode-rewrite acode-rewrite-%ilogior2 %ilogior2 (op w type)
+  (or
+   (acode-rewrite-and-fold-binop 'logior w)
+   ;; If either argument's an UNSIGNED-BYTE constant, the result
+   ;; is an UNSIGNED-BYTE no greater than that constant.
+   (destructuring-bind (x y) w
+     (let* ((fix-x (acode-fixnum-form-p x))
+            (fix-y (acode-fixnum-form-p y)))
+       (acode-assert-type (if fix-x
+                            `(integer 0 ,fix-x)
+                            (if fix-y
+                              `(integer 0 ,fix-y)
+                              'fixnum))
+                          op w type)))))
+
+(def-acode-rewrite acode-rewrite-ilogbitp (logbitp %ilogbitp) (op w type)
+  (or (acode-rewrite-and-fold-binop 'logbitp w)
+      (acode-assert-type 'boolean op w type)))
+
+(def-acode-rewrite acode-rewrite-eq eq (op w type)
+  (or (acode-rewrite-and-fold-binop 'eq w)
+      (acode-assert-type 'boolean op w type)))
+
+(def-acode-rewrite acode-rewrite-neq neq (op w type)
+  (or (acode-rewrite-and-fold-binop 'neq w)
+      (acode-assert-type 'boolean op w type))  )
+
+(def-acode-rewrite acode-rewrite-list list (op w type)
+  (rewrite-acode-forms (car w))
+  (acode-assert-type 'list op w type))
+
+(def-acode-rewrite acode-rewrite-values values (op w type)
+  (rewrite-acode-forms (car w)))
+
+(def-acode-rewrite acode-rewrite-if if (op w type)
+  (rewrite-acode-forms w)
+  (destructuring-bind (test true &optional (false *nx-nil*)) w
+    (if (acode-constant-p test)
+      (if (eq *nx-nil* (acode-unwrapped-form-value test))
+        false
+        true))))
+
+(def-acode-rewrite acode-rewrite-or or (op w type)
+  (rewrite-acode-forms (car w))
+  ;; Try to short-circuit if there are any true constants.
+  ;; The constant-valued case will return a single value.
+  (do* ((forms w (cdr forms)))
+       ((null (cdr forms)))
+    (let* ((form (car forms)))
+      (when (and (acode-constant-p form)
+                 (not (eq *nx-nil* (acode-unwrapped-form-value form))))
+        (progn
+          (rplacd forms nil)
+          (return))))))
+
+(def-acode-rewrite acode-rewrite-%fixnum-ref (%fixnum-ref %fixnum-ref-natural) (op w type)
+  (rewrite-acode-forms w))
+
+(def-acode-rewrite acode-rewrite-multiple-value-prog1 multiple-value-prog1 (op w type)
+  (rewrite-acode-forms w))
+
+(def-acode-rewrite acode-rewrite-multiple-value-bind multiple-value-bind (op w type)
+  (rewrite-acode-forms (cdr w)))
+
+(def-acode-rewrite acode-rewrite-multiple-value-call multiple-value-call (op w type)
+  (rewrite-acode-forms w))
+
+(def-acode-rewrite acode-rewrite-typed-form typed-form (op w type)
+  (let* ((ourtype (car w)))
+    (rewrite-acode-ref (cdr w) ourtype)
+    (let* ((subform (cadr w)))
+      (and (acode-p subform) (eq (acode-operator subform) op) subform))))
+
+;; w: vars, list of initial-value forms, body
+(def-acode-rewrite acode-rewrite-let (let let*) (op w type)
+  (collect ((newvars)
+            (newvals))
+    (do* ((vars (car w) (cdr vars))
+          (vals (cadr w) (cdr vals)))
+         ((null vars)
+          (rplaca w (newvars))
+          (rplaca (cdr w) (newvals))
+          (rewrite-acode-ref (cddr w))
+          (unless (car w) (caddr w)))
+      (rewrite-acode-ref (car vals))
+      (let* ((var (car vars))
+             (bits (nx-var-bits var)))
+        (cond ((logbitp $vbitpuntable bits)
+               (setf (var-bits var)
+                     (logior (ash 1 $vbitpunted) bits)
+                     (var-ea var) (car vals)))
+              (t
+               (newvars var)
+               (newvals (car vals))))))))
+        
+    
+      
+
+
+
+(def-acode-rewrite acode-rewrite-lexical-reference lexical-reference (op w type)
+  (let* ((var (car w)))
+    (if (acode-punted-var-p var)
+      (var-ea var))))
+
+(def-acode-rewrite acode-rewrite-add2 add2 (op w type)
+  (or (acode-rewrite-and-fold-binop '+ w)
+      (progn
+        (acode-post-binop-numeric-contagion w (cdr w))
+        (let* ((xtype (acode-post-form-type (car w)))
+               (ytype (acode-post-form-type (cadr w))))
+          (cond ((and (subtypep xtype 'double-float)
+                      (subtypep ytype 'double-float))
+                 (make-acode (%nx1-operator typed-form)
+                             'double-float
+                             (make-acode* (%nx1-operator %double-float+-2)
+                                          w)))
+                ((and (subtypep xtype 'single-float)
+                      (subtypep ytype 'single-float))
+                 (make-acode (%nx1-operator typed-form)
+                             'single-float
+                             (make-acode* (%nx1-operator %short-float+-2)
+                                          w)))
+                ((and (subtypep xtype 'fixnum)
+                      (subtypep ytype 'fixnum))
+                 (make-acode (%nx1-operator typed-form)
+                             'fixnum
+                             (make-acode (%nx1-operator %i+)
+                                         (car w)
+                                         (cadr w)
+                                         (not (subtypep type 'fixnum))))))))))
+
+(def-acode-rewrite acode-rewrite-sub2 sub2 (op w type)
+  (or (acode-rewrite-and-fold-binop '- w)
+      (progn
+        (acode-post-binop-numeric-contagion w (cdr w))
+        (let* ((xtype (acode-post-form-type (car w)))
+               (ytype (acode-post-form-type (cadr w))))
+          (cond ((and (subtypep xtype 'double-float)
+                      (subtypep ytype 'double-float))
+                 (make-acode (%nx1-operator typed-form)
+                             'double-float
+                             (make-acode* (%nx1-operator %double-float--2)
+                                          w)))
+                ((and (subtypep xtype 'single-float)
+                      (subtypep ytype 'single-float))
+                 (make-acode (%nx1-operator typed-form)
+                             'single-float
+                             (make-acode* (%nx1-operator %short-float--2)
+                                          w)))
+                ((and (subtypep xtype 'fixnum)
+                      (subtypep ytype 'fixnum))
+                 (make-acode (%nx1-operator typed-form)
+                             'fixnum
+                             (make-acode (%nx1-operator %i-)
+                                         (car w)
+                                         (cadr w)
+                                         (not (subtypep type 'fixnum))))))))))
+                 
+
Index: /branches/new-random/compiler/arch.lisp
===================================================================
--- /branches/new-random/compiler/arch.lisp	(revision 13309)
+++ /branches/new-random/compiler/arch.lisp	(revision 13309)
@@ -0,0 +1,364 @@
+;;;-*- Mode: Lisp; Package: (ARCH :use CL) -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(defpackage "ARCH"
+  (:use "CL"))
+
+(in-package "ARCH")
+
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+
+
+(defconstant tcr-flag-bit-foreign 0)
+(defconstant tcr-flag-bit-awaiting-preset 1)
+(defconstant tcr-flag-bit-alt-suspend 2)
+(defconstant tcr-flag-bit-propagate-exception 3)
+(defconstant tcr-flag-bit-suspend-ack-pending 4)
+(defconstant tcr-flag-bit-pending-exception 5)
+(defconstant tcr-flag-bit-foreign-exception 6)
+(defconstant tcr-flag-bit-pending-suspend 7)        
+
+
+
+)
+
+(defmacro make-vheader (element-count subtag)
+  `(logior ,subtag (ash ,element-count 8)))
+
+
+
+;;; Error numbers, as used in UU0s and such.
+;;; These match constants defined in the kernel sources.
+(defconstant error-reg-regnum 0)        ; "real" error number is in RB field of UU0.
+                                        ; Currently only used for :errchk in emulated traps
+                                        ; The errchk macro should expand into a check-trap-error vinsn, too.
+(defconstant error-udf 1)               ; Undefined function (reported by symbol-function)
+(defconstant error-udf-call 2)          ; Attempt to call undefined function
+(defconstant error-throw-tag-missing 3)
+(defconstant error-alloc-failed 4)      ; can't allocate (largish) vector
+(defconstant error-stack-overflow 5)    ; some stack overflowed.
+(defconstant error-excised-function-call 6)     ; excised function was called.
+(defconstant error-too-many-values 7)   ; too many values returned
+(defconstant error-cant-take-car 8)
+(defconstant error-cant-take-cdr 9)
+(defconstant error-propagate-suspend 10)
+(defconstant error-interrupt 11)
+(defconstant error-suspend 12)
+(defconstant error-suspend-all 13)
+(defconstant error-resume 14)
+(defconstant error-resume-all 15)
+(defconstant error-kill 16)
+(defconstant error-cant-call 17)        ; Attempt to funcall something that is not a symbol or function.
+(defconstant error-allocate-list 18)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defconstant error-type-error 128)
+)
+
+
+(defconstant error-fpu-exception-double 1024)   ; FPU exception, binary double-float op
+(defconstant error-fpu-exception-single 1025)
+
+(defconstant error-memory-full 2048)
+
+;; These are now supposed to match (mod ERROR-TYPE-ERROR) the %type-error-typespecs%
+;; array that %err-disp looks at.
+(ccl::defenum (:start  error-type-error :prefix "ERROR-OBJECT-NOT-")
+  array
+  bignum
+  fixnum
+  character
+  integer
+  list
+  number
+  sequence
+  simple-string
+  simple-vector
+  string
+  symbol
+  macptr
+  real
+  cons
+  unsigned-byte
+  radix
+  float  
+  rational
+  ratio
+  short-float
+  double-float
+  complex
+  vector
+  simple-base-string
+  function
+  unsigned-byte-16
+  unsigned-byte-8
+  unsigned-byte-32
+  signed-byte-32
+  signed-byte-16
+  signed-byte-8
+  base-char
+  bit
+  unsigned-byte-24
+  unsigned-byte-64
+  signed-byte-64
+  unsigned-byte-56
+  simple-array-double-float-2d
+  simple-array-single-float-2d
+  mod-char-code-limit
+  array-2d
+  array-3d
+  array-t
+  array-bit
+  array-s8
+  array-u8
+  array-s16
+  array-u16
+  array-s32
+  array-u32
+  array-s64
+  array-u64
+  array-fixnum
+  array-single-float
+  array-double-float
+  array-char
+  array-t-2d
+  array-bit-2d
+  array-s8-2d
+  array-u8-2d
+  array-s16-2d
+  array-u16-2d
+  array-s32-2d
+  array-u32-2d
+  array-s64-2d
+  array-u64-2d
+  array-fixnum-2d
+  array-single-float-2d
+  array-double-float-2d
+  array-char-2d
+  simple-array-t-2d
+  simple-array-bit-2d
+  simple-array-s8-2d
+  simple-array-u8-2d
+  simple-array-s16-2d
+  simple-array-u16-2d
+  simple-array-s32-2d
+  simple-array-u32-2d
+  simple-array-s64-2d
+  simple-array-u64-2d
+  simple-array-fixnum-2d
+  simple-array-char-2d
+  array-t-3d
+  array-bit-3d
+  array-s8-3d
+  array-u8-3d
+  array-s16-3d
+  array-u16-3d
+  array-s32-3d
+  array-u32-3d
+  array-s64-3d
+  array-u64-3d
+  array-fixnum-3d
+  array-single-float-3d
+  array-double-float-3d
+  array-char-3d
+  simple-array-t-3d
+  simple-array-bit-3d
+  simple-array-s8-3d
+  simple-array-u8-3d
+  simple-array-s16-3d
+  simple-array-u16-3d
+  simple-array-s32-3d
+  simple-array-u32-3d
+  simple-array-s64-3d
+  simple-array-u64-3d
+  simple-array-fixnum-3d
+  simple-array-single-float-3d
+  simple-array-double-float-3d
+  simple-array-char-3d
+
+  ;;
+  vector-t
+  bit-vector
+  vector-s8
+  vector-u8
+  vector-s16
+  vector-u16
+  vector-s32
+  vector-u32
+  vector-s64
+  vector-u64
+  vector-fixnum
+  vector-single-float
+  vector-double-float
+  
+  ;; Sentinel
+  unused-max-type-error
+  )
+
+(assert (<= error-object-not-unused-max-type-error (* 2 error-type-error)))
+
+
+
+
+
+(defun builtin-function-name-offset (name)
+  (and name (position name ccl::%builtin-functions% :test #'eq)))
+
+(ccl::defenum ()
+  storage-class-lisp                    ; General lisp objects
+  storage-class-imm                     ; Fixnums, chars, NIL: not relocatable
+  storage-class-wordptr                 ; "Raw" (fixnum-tagged) pointers to stack,etc
+  storage-class-u8                      ; Unsigned, untagged, 8-bit objects
+  storage-class-s8                      ; Signed, untagged, 8-bit objects
+  storage-class-u16                     ; Unsigned, untagged, 16-bit objects
+  storage-class-s16                     ; Signed, untagged, 16-bit objects
+  storage-class-u32                     ; Unsigned, untagged, 8-bit objects
+  storage-class-s32                     ; Signed, untagged, 8-bit objects
+  storage-class-address                 ; "raw" (untagged) 32-bit addresses.
+  storage-class-single-float            ; 32-bit single-float objects
+  storage-class-double-float            ; 64-bit double-float objects
+  storage-class-pc                      ; pointer to/into code vector
+  storage-class-locative                ; pointer to/into node-misc object
+  storage-class-crf                     ; condition register field
+  storage-class-crbit                   ; condition register bit: 0-31
+  storage-class-crfbit                  ; bit within condition register field : 0-3
+  storage-class-u64			; (unsigned-byte 64)
+  storage-class-s64			; (signed-byte 64)
+)
+
+
+(defvar *known-target-archs* ())
+
+(defstruct (target-arch (:conc-name target-)
+                        (:constructor %make-target-arch))
+  (name nil)
+  (lisp-node-size 0)
+  (nil-value 0)
+  (fixnum-shift 0)
+  (most-positive-fixnum 0)
+  (most-negative-fixnum 0)
+  (misc-data-offset 0)
+  (misc-dfloat-offset 0)
+  (nbits-in-word 0)
+  (ntagbits 0)
+  (nlisptagbits 0)
+  (uvector-subtags 0)
+  (max-64-bit-constant-index 0)
+  (max-32-bit-constant-index 0)
+  (max-16-bit-constant-index 0)
+  (max-8-bit-constant-index 0)
+  (max-1-bit-constant-index 0)
+  (word-shift 0)
+  (code-vector-prefix ())
+  (gvector-types ())
+  (1-bit-ivector-types ())
+  (8-bit-ivector-types ())
+  (16-bit-ivector-types ())
+  (32-bit-ivector-types ())
+  (64-bit-ivector-types ())
+  (array-type-name-from-ctype-function ())
+  (package-name ())
+  (t-offset ())
+  (array-data-size-function ())
+  (numeric-type-name-to-typecode-function ())
+  (subprims-base ())
+  (subprims-shift ())
+  (subprims-table ())
+  (primitive->subprims ())
+  (unbound-marker-value ())
+  (slot-unbound-marker-value ())
+  (fixnum-tag 0)
+  (single-float-tag nil)
+  (single-float-tag-is-subtag nil)
+  (double-float-tag nil)
+  (cons-tag nil)
+  (null-tag nil)
+  (symbol-tag nil)
+  (symbol-tag-is-subtag nil)
+  (function-tag nil)
+  (function-tag-is-subtag nil)
+  (big-endian t)
+  (target-macros (make-hash-table :test #'eq))
+  (misc-subtag-offset 0)
+  (car-offset 0)
+  (cdr-offset 0)
+  (subtag-char 0)
+  (charcode-shift 0)
+  (fulltagmask 0)
+  (fulltag-misc 0)
+  (char-code-limit nil))
+  
+
+  
+  
+  
+(defun make-target-arch (&rest keys)
+  (declare (dynamic-extent keys))
+  (let* ((arch (apply #'%make-target-arch keys))
+         (tail (member (target-name arch) *known-target-archs*
+                       :key #'target-name
+                       :test #'eq)))
+    (if tail
+      (rplaca tail arch)
+      (push arch *known-target-archs*))
+    arch))
+
+(defun find-target-arch (name)
+  (car (member name *known-target-archs*
+               :key #'target-name
+               :test #'eq)))
+
+(defun target-arch-macros (arch-name)
+  (let* ((arch (or (find-target-arch arch-name)
+                   (error "unknown arch: ~s" arch-name))))
+    (target-target-macros arch)))
+
+(defmacro defarchmacro (arch-name name arglist &body body &environment env)
+  (let* ((lambda-form (ccl::parse-macro-1 name arglist body env)))
+    `(progn
+      (setf (gethash ',name (target-arch-macros ',arch-name))
+       (ccl::nfunction ,name ,lambda-form))
+      ',name)))
+
+(defun arch-macro-function (arch-name name)
+  (gethash name (target-arch-macros arch-name)))
+    
+
+
+;;; GC related operations
+(defconstant gc-trap-function-immediate-gc -1)
+(defconstant gc-trap-function-gc 0)
+(defconstant gc-trap-function-purify 1)
+(defconstant gc-trap-function-impurify 2)
+(defconstant gc-trap-function-flash-freeze 4)
+(defconstant gc-trap-function-save-application 8)
+(defconstant gc-trap-function-get-lisp-heap-threshold 16)
+(defconstant gc-trap-function-set-lisp-heap-threshold 17)
+(defconstant gc-trap-function-use-lisp-heap-threshold 18)
+(defconstant gc-trap-function-ensure-static-conses 19)
+(defconstant gc-trap-function-egc-control 32)
+(defconstant gc-trap-function-configure-egc 64)
+(defconstant gc-trap-function-freeze 129)
+(defconstant gc-trap-function-thaw 130)
+
+(defconstant watch-trap-function-watch 0)
+(defconstant watch-trap-function-unwatch 1)
+
+(provide "ARCH")
Index: /branches/new-random/compiler/backend.lisp
===================================================================
--- /branches/new-random/compiler/backend.lisp	(revision 13309)
+++ /branches/new-random/compiler/backend.lisp	(revision 13309)
@@ -0,0 +1,493 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "ARCH"))
+
+(defconstant platform-word-size-mask 64)
+(defconstant platform-os-mask 7)
+(defconstant platform-cpu-mask (logandc2 (1- platform-word-size-mask)
+                                         platform-os-mask))
+(defconstant platform-word-size-32 0)
+(defconstant platform-word-size-64 64)
+(defconstant platform-cpu-ppc (ash 0 3))
+(defconstant platform-cpu-sparc (ash 1 3))
+(defconstant platform-cpu-x86 (ash 2 3))
+(defconstant platform-os-vxworks 0)
+(defconstant platform-os-linux 1)
+(defconstant platform-os-solaris 2)
+(defconstant platform-os-darwin 3)
+(defconstant platform-os-freebsd 4)
+(defconstant platform-os-windows 5)
+
+(defstruct backend
+  (name :a :type keyword)
+  (num-arg-regs 3 :type fixnum)    ; number of args passed in registers
+  (num-nvrs 0 :type fixnum)        ; number of callee-save node regs
+  (num-node-regs 0 :type fixnum)     ; number of node temps/arg regs
+  (lap-opcodes #() :type simple-vector)
+  (lookup-opcode #'false :type (or symbol function))
+  (lookup-macro #'false :type (or symbol function))
+  (p2-dispatch #() :type simple-vector)
+  (p2-compile 'error :type (or symbol function))
+  (p2-vinsn-templates (error "Missing arg") :type hash-table)
+  (p2-template-hash-name 'bogus :type symbol)
+  (target-specific-features () :type list)
+  (target-fasl-pathname "" :type (or string pathname))
+  (target-platform 0 :type fixnum)
+  (target-os ())
+  (target-arch-name nil :type symbol)
+  (target-foreign-type-data nil :type (or null foreign-type-data))
+  (lap-macros nil)
+  (target-arch nil)
+  (define-vinsn nil)
+  (platform-syscall-mask 0)
+  (define-callback nil)
+  (defcallback-body nil)
+  (lisp-context-register 0)
+  ;; difference between canonical static address for arch and this
+  ;; target's. Usually 0.
+  (lowmem-bias 0))
+
+(defmethod print-object ((b backend) s)
+  (print-unreadable-object (b s :type t :identity t)
+    (format s "~A" (backend-name b))))
+
+
+(defun target-os-name (&optional (backend *target-backend*))
+  (cdr (assoc (logand platform-os-mask (backend-target-platform backend))
+              *platform-os-names*)))
+
+
+(defparameter *backend-node-regs* 0)
+(defparameter *backend-node-temps* 0)
+(defparameter *available-backend-node-temps* 0)
+(defparameter *backend-imm-temps* 0)
+(defparameter *available-backend-imm-temps* 0)
+(defparameter *backend-fp-temps* 0)
+(defparameter *available-backend-fp-temps* 0)
+(defparameter *backend-crf-temps* 0)
+(defparameter *available-backend-crf-temps* 0)
+(defparameter *backend-allocate-high-node-temps* nil)
+
+(defparameter *mode-name-value-alist*
+  '((:lisp . 0)
+    (:u32 . 1)
+    (:s32 . 2)
+    (:u16 . 3)
+    (:s16 . 4)
+    (:u8 . 5)
+    (:s8 . 6)
+    (:address . 7)
+    (:u64 . 8)
+    (:s64 . 9)))
+
+(defun gpr-mode-name-value (name)
+  (if (eq name :natural)
+    (setq name
+          (target-word-size-case
+           (32 :u32)
+           (64 :u64)))
+    (if (eq name :signed-natural)
+      (setq name
+          (target-word-size-case
+           (32 :s32)
+           (64 :s64)))))
+  (or (cdr (assq name *mode-name-value-alist*))
+      (error "Unknown gpr mode name: ~s" name)))
+
+(defparameter *mode-specifier-types*
+  (vector
+   (specifier-type t)                   ;:lisp
+   (specifier-type '(unsigned-byte 32)) ;:u32
+   (specifier-type '(signed-byte 32))   ;:s32
+   (specifier-type '(unsigned-byte 16)) ;:u16
+   (specifier-type '(signed-byte 16))   ;:s16
+   (specifier-type '(unsigned-byte 8))  ;:u8
+   (specifier-type '(signed-byte 8))    ;:s8
+   (specifier-type 'macptr)             ;:address
+   (specifier-type '(unsigned-byte 64)) ;:u64
+   (specifier-type '(signed-byte 64)))) ;:s64
+
+(defun mode-specifier-type (mode-name)
+  (svref *mode-specifier-types* (gpr-mode-name-value mode-name)))
+   
+
+(defun use-node-temp (n)
+  (declare (fixnum n))
+  (if (logbitp n *available-backend-node-temps*)
+    (setq *available-backend-node-temps*
+	  (logand *available-backend-node-temps* (lognot (ash 1 n)))))
+  n)
+
+(defun node-reg-p (reg)
+  (and (= (hard-regspec-class reg) hard-reg-class-gpr)
+       (= (get-regspec-mode reg) hard-reg-class-gpr-mode-node)))
+
+(defun node-reg-value (reg)
+  (if (node-reg-p reg)
+    (hard-regspec-value reg)))
+
+; if EA is a register-spec of the indicated class, return
+; the register #.
+(defun backend-ea-physical-reg (ea class)
+  (declare (fixnum class))
+  (and ea
+       (register-spec-p ea)
+       (= (hard-regspec-class ea) class)
+       (hard-regspec-value ea)))
+
+(defun backend-crf-p (vreg)
+  (backend-ea-physical-reg vreg hard-reg-class-crf))
+
+(defun available-node-temp (mask)
+  (if *backend-allocate-high-node-temps*
+    (do* ((bit 31 (1- bit)))
+	 ((< bit 0) (error "Bug: ran out of node temp registers."))
+      (when (logbitp bit mask)
+	(return bit)))    
+    (dotimes (bit 32 (error "Bug: ran out of node temp registers."))
+      (when (logbitp bit mask)
+	(return bit)))))
+
+(defun ensure-node-target (reg)
+  (if (node-reg-p reg)
+    reg
+    (available-node-temp *available-backend-node-temps*)))
+
+(defun select-node-temp ()
+  (let* ((mask *available-backend-node-temps*))
+    (if *backend-allocate-high-node-temps*
+      (do* ((bit 31 (1- bit)))
+           ((< bit 0) (error "Bug: ran out of node temp registers."))
+        (when (logbitp bit mask)
+          (setq *available-backend-node-temps* (bitclr bit mask))
+          (return bit)))
+      (dotimes (bit 32 (error "Bug: ran out of node temp registers."))
+        (when (logbitp bit mask)
+          (setq *available-backend-node-temps* (bitclr bit mask))
+          (return bit))))))
+
+(defun available-imm-temp (mask &optional (mode-name :natural))
+  (dotimes (bit 32 (error "Bug: ran out of imm temp registers."))
+    (when (logbitp bit mask)
+      (return (set-regspec-mode bit (gpr-mode-name-value mode-name))))))
+
+(defun use-imm-temp (n)
+  (declare (fixnum n))
+  (setq *available-backend-imm-temps* (logand *available-backend-imm-temps* (lognot (ash 1 n))))
+  n)
+
+
+(defun select-imm-temp (&optional (mode-name :u32))
+  (let* ((mask *available-backend-imm-temps*))
+    (dotimes (bit 32 (error "Bug: ran out of imm temp registers."))
+      (when (logbitp bit mask)
+        (setq *available-backend-imm-temps* (bitclr bit mask))
+        (return (set-regspec-mode bit (gpr-mode-name-value mode-name)))))))
+
+;;; Condition-register fields are PPC-specific, but we might as well have
+;;; a portable interface to them.
+
+(defun use-crf-temp (n)
+  (declare (fixnum n))
+  (setq *available-backend-crf-temps* (logand *available-backend-crf-temps* (lognot (ash 1 (ash n -2)))))
+  n)
+
+(defun select-crf-temp ()
+  (let* ((mask *available-backend-crf-temps*))
+    (dotimes (bit 8 (error "Bug: ran out of CR fields."))
+      (declare (fixnum bit))
+      (when (logbitp bit mask)
+        (setq *available-backend-crf-temps* (bitclr bit mask))
+        (return (make-hard-crf-reg (the fixnum (ash bit 2))))))))
+
+(defun available-crf-temp (mask)
+  (dotimes (bit 8 (error "Bug: ran out of CR fields."))
+    (when (logbitp bit mask)
+      (return (make-hard-crf-reg (the fixnum (ash bit 2)))))))
+
+(defun single-float-reg-p (reg)
+  (and (= (hard-regspec-class reg) hard-reg-class-fpr)
+       (= (get-regspec-mode reg) hard-reg-class-fpr-mode-single)))
+
+(defun use-fp-temp (n)
+    (setq *available-backend-fp-temps* (logand *available-backend-fp-temps* (lognot (ash 1 n))))
+    n)
+
+(defun available-fp-temp (mask &optional (mode-name :double-float))
+  (dotimes (bit (integer-length mask) (error "Bug: ran out of node fp registers."))
+    (when (logbitp bit mask)
+      (let* ((mode (if (eq mode-name :double-float) 
+                     hard-reg-class-fpr-mode-double
+                     hard-reg-class-fpr-mode-single)))
+        (return (make-hard-fp-reg bit mode))))))
+
+(defparameter *backend-all-lregs* ())
+(defun note-logical-register (l)
+  (push l *backend-all-lregs*)
+  l)
+
+(defun free-logical-registers ()
+  (without-interrupts
+   (let* ((prev (pool.data *lreg-freelist*)))
+     (dolist (r *backend-all-lregs*)
+       (setf (lreg-value r) prev
+             prev r))
+     (setf (pool.data *lreg-freelist*) prev)
+     (setq *backend-all-lregs* nil))))
+
+
+(defun make-unwired-lreg (value &key 
+				(class (if value (hard-regspec-class value) 0))
+				(mode (if value (get-regspec-mode value) 0))
+				(type (if value (get-node-regspec-type-modes value) 0)))
+  (note-logical-register (make-lreg (if value (hard-regspec-value value)) class mode type nil)))
+
+;;; Make an lreg with the same class, mode, & type as the prototype.
+(defun make-unwired-lreg-like (proto)
+  (make-unwired-lreg nil
+		     :class (hard-regspec-class proto)
+		     :mode (get-regspec-mode proto)
+		     :type (get-node-regspec-type-modes proto)))
+  
+(defun make-wired-lreg (value &key 
+			      (class (hard-regspec-class value))
+			      (mode (get-regspec-mode value))
+			      (type (get-node-regspec-type-modes value)))
+  (note-logical-register (make-lreg (hard-regspec-value value) class mode type t)))
+
+(defvar *backend-immediates*)
+
+(defun backend-new-immediate (imm)
+  (vector-push-extend imm *backend-immediates*))
+
+(defun backend-immediate-index (imm)
+  (or (position imm *backend-immediates*)
+      (backend-new-immediate imm)))
+
+(defvar *backend-vinsns*)
+
+(defvar *backend-labels*)
+
+(defun backend-gen-label (seg labelnum)
+  (append-dll-node (aref *backend-labels* labelnum) seg)
+  labelnum)
+
+(defconstant $backend-compound-branch-target-bit 18)
+(defconstant $backend-compound-branch-target-mask (ash 1 $backend-compound-branch-target-bit))
+
+(defconstant $backend-mvpass-bit 19)
+(defconstant $backend-mvpass-mask (ash 1 $backend-mvpass-bit))
+
+(defconstant $backend-return (- (ash 1 18) 1))
+(defconstant $backend-mvpass (- (ash 1 18) 2))
+
+(defconstant $backend-compound-branch-false-byte (byte 18 0))
+(defconstant $backend-compound-branch-true-byte (byte 18 20))
+
+
+(defun backend-get-next-label ()
+  (let* ((lnum (length *backend-labels*)))
+    (if (>= lnum $backend-mvpass)
+      (compiler-function-overflow)
+      (vector-push-extend (make-vinsn-label lnum) *backend-labels*))))
+
+
+;;; Loop through all labels in *backend-labels*; if the label has been
+;;; emitted, remove it from vinsns and return it to the
+;;; *vinsn-label-freelist*.  "vinsns" should then contain nothing but
+;;; ... vinsns
+
+(defun backend-remove-labels ()
+  (let* ((labels *backend-labels*)
+         (freelist *vinsn-label-freelist*))
+    (dotimes (i (the fixnum (length labels)))
+      (let* ((lab (aref labels i)))
+        (if lab
+          (if (vinsn-label-succ lab)
+            (remove-and-free-dll-node lab freelist)
+            (free-dll-node lab freelist)))))))
+
+(defun backend-copy-label (from to)
+  (let* ((from-lab (aref *backend-labels* from))
+         (to-lab (aref *backend-labels* to)))
+    (when (null (vinsn-label-succ from-lab))
+      (error "Copy label: not defined yet!"))
+    (backend-merge-labels from-lab to-lab)
+    (setf (aref *backend-labels* to) from-lab)))
+
+(defun backend-merge-labels (from-lab to-lab)
+  (let* ((to-refs (vinsn-label-refs to-lab)))
+    (when to-refs
+      ;; Make all extant refs to TO-LAB refer to FROM-LAB
+      (setf (vinsn-label-refs to-lab) nil)
+      (dolist (vinsn to-refs)
+        (push vinsn (vinsn-label-refs from-lab))
+        (let* ((vp (vinsn-variable-parts vinsn)))
+          (declare (simple-vector vp))
+          (dotimes (i (the fixnum (length vp)))
+            (when (eq to-lab (svref vp i))
+              (setf (svref vp i) from-lab))))))))
+
+;;; For now, the register-spec must be 
+;;; a) non-nil
+;;; c) of an expected class.
+;;; Return the class and value.
+(defun regspec-class-and-value (regspec expected)
+  (declare (fixnum expected))
+  (let* ((class (hard-regspec-class regspec)))
+    (declare (type (unsigned-byte 8) class))
+    (if (logbitp class expected)
+      (values class (if (typep regspec 'lreg)
+		      regspec
+		      (hard-regspec-value regspec)))
+      (error "bug: Register spec class (~d) is not one  of ~s." class expected))))
+
+(defmacro with-node-temps ((&rest reserved) (&rest nodevars) &body body)
+  `(let* ((*available-backend-node-temps* (logand *available-backend-node-temps* (lognot (logior ,@(mapcar #'(lambda (r) `(ash 1 (hard-regspec-value ,r))) reserved)))))
+          ,@(mapcar #'(lambda (v) `(,v (make-unwired-lreg (select-node-temp)))) nodevars))
+     ,@body))
+
+(defmacro with-imm-temps ((&rest reserved) (&rest immvars) &body body)
+  `(let* ((*available-backend-imm-temps* (logand *available-backend-imm-temps* (lognot (logior ,@(mapcar #'(lambda (r) `(ash 1 (hard-regspec-value ,r))) reserved)))))
+          ,@(mapcar #'(lambda (v) (let* ((var (if (atom v) v (car v)))
+                                         (mode-name (if (atom v) :u32 (cadr v)))) 
+                                    `(,var (select-imm-temp ',mode-name)))) immvars))
+          ,@body))
+
+
+(defmacro with-crf-target ((&rest reserved) name &body body)
+  `(let* ((,name (make-unwired-lreg 
+                  (available-crf-temp 
+                   (logand *available-backend-crf-temps* 
+                           (lognot (logior ,@(mapcar #'(lambda (r) `(ash 1 (ash (hard-regspec-value ,r) -2))) reserved))))))))
+     ,@body))
+
+(defmacro regspec-crf-gpr-case ((regspec regval) crf-form gpr-form)
+  (let* ((class (gensym)))
+    `(if ,regspec
+       (multiple-value-bind (,class ,regval) (regspec-class-and-value ,regspec hard-reg-class-gpr-crf-mask)
+         (declare (fixnum ,class))
+         (if (= ,class hard-reg-class-crf)
+           ,crf-form
+           ,gpr-form)))))
+
+;;; The NODE case may need to use ENSURING-NODE-TARGET.
+(defmacro unboxed-other-case ((regspec &rest mode-names)
+                              unboxed-case other-case)
+  `(if (and ,regspec
+        (= (hard-regspec-class ,regspec) hard-reg-class-gpr)
+        (logbitp  (get-regspec-mode ,regspec)
+         (logior ,@(mapcar #'(lambda (x) (ash 1 (gpr-mode-name-value x)))
+                           mode-names))))
+    ,unboxed-case
+    ,other-case))
+
+
+
+
+;;; Choose an immediate register (for targeting), but don't "reserve" it.
+(defmacro with-imm-target ((&rest reserved) spec &body body)
+  (let* ((name (if (atom spec) spec (car spec)))
+         (mode-name (if (atom spec) :natural (cadr spec))))
+    `(let* ((,name (make-unwired-lreg
+		    (available-imm-temp
+		     (logand
+		      *available-backend-imm-temps* 
+		      (lognot (logior ,@(mapcar
+					 #'(lambda (r)
+					     `(ash 1 (hard-regspec-value ,r)))
+					 reserved))))
+		     ',mode-name))))
+       ,@body)))
+
+(defmacro with-node-target ((&rest reserved) name &body body)
+  `(let* ((,name (make-unwired-lreg
+                  (available-node-temp
+                   (logand
+                    *available-backend-node-temps* 
+                    (lognot (logior ,@(mapcar
+                                       #'(lambda (r)
+                                           `(ash 1 (hard-regspec-value ,r)))
+                                       reserved))))))))
+    ,@body))
+
+
+
+
+(defmacro with-fp-target ((&rest reserved) spec &body body)
+  (let* ((name (if (atom spec) spec (car spec)))
+         (mode-name (if (atom spec) :double-float (cadr spec))))
+    `(let* ((,name
+	     (make-unwired-lreg
+	      (available-fp-temp
+	       (logand *available-backend-fp-temps*
+		       (lognot (logior
+				,@(mapcar
+				   #'(lambda (r) 
+				       `(ash 1 (hard-regspec-value ,r)))
+				   reserved))))
+	       ',mode-name))))
+       ,@body)))
+
+(defmacro ensuring-node-target ((target-var vreg-var) &body body)
+  `(let* ((*available-backend-node-temps* *available-backend-node-temps*)
+          (,target-var (ensure-node-target ,vreg-var)))
+    (declare (special *available-backend-node-temps*))
+    (macrolet ((<- (&whole call &rest args)
+                 (declare (ignore args))
+                 (error "Invalid use of <- inside ENSURING-NODE-TARGET: ~s" call))
+               (^ (&whole call &rest args)
+                 (declare (ignore args))
+                 (error "Invalid use of ^ inside ENSURING-NODE-TARGET: ~s" call)))
+      (progn
+        ,@body))
+    (<- ,target-var)))
+
+(defun acode-invert-condition-keyword (k)
+  (or 
+   (cdr (assq k '((:eq . :ne) (:ne . :eq) (:le . :gt) (:lt . :ge) (:ge . :lt) (:gt . :le))))
+   (error "Unknown condition: ~s" k)))
+
+(defun backend-arch-macroexpand (whole env)
+  (let* ((expander (arch::arch-macro-function
+                    (backend-target-arch-name *target-backend*)
+                    (car whole))))
+    (if expander
+      (funcall expander whole env)
+      (error "No arch-specific macro function for ~s in arch ~s"
+             (car whole) (backend-target-arch-name *target-backend*)))))
+
+(defmacro declare-arch-specific-macro (name)
+  `(progn
+    (setf (macro-function ',name) #'backend-arch-macroexpand)
+    ',name))
+
+(defun target-nil-value (&optional (backend *target-backend*))
+  (+ (arch::target-nil-value (backend-target-arch backend))
+     (backend-lowmem-bias backend)))
+
+(defun target-t-value (&optional (backend *target-backend*))
+  (let* ((arch (backend-target-arch backend)))
+    (+ (arch::target-nil-value arch)
+       (arch::target-t-offset arch)
+       (backend-lowmem-bias backend))))
+
+
+     
Index: /branches/new-random/compiler/dll-node.lisp
===================================================================
--- /branches/new-random/compiler/dll-node.lisp	(revision 13309)
+++ /branches/new-random/compiler/dll-node.lisp	(revision 13309)
@@ -0,0 +1,228 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+
+(defstruct (dll-node (:print-function print-dll-node))
+  pred
+  succ)
+
+; Doubly-linked list header (just a distinguished type of node)
+(defstruct (dll-header
+            (:include dll-node)
+            (:constructor %make-dll-header))
+)
+
+
+(defmacro dll-header-last (h) `(dll-header-pred ,h))
+(defmacro dll-header-first (h) `(dll-header-succ ,h))
+
+(defun init-dll-header (h)
+  (setf (dll-header-first h) h
+	(dll-header-last h) h))
+
+(defun make-dll-header ()
+  (init-dll-header (%make-dll-header)))
+
+
+;;; DLL-NODEs are sort of "abstract classes", so we should rarely (if
+;;; ever) have to print one.  On the other hand, they're very circular
+;;; abstract classes ...
+(defun print-dll-node (n stream d)
+  (declare (ignore d))
+  (print-unreadable-object (n stream :type t :identity t)))
+
+;;; Return NODE's list header, if it has one.
+(defun dll-node-header (node)
+  (do* ((n node (dll-node-succ node)))
+       ((or (null n) (typep n 'dll-header)) n)))
+
+;;; Make node be the last node in header's linked list
+(defun append-dll-node (node header)
+  (let* ((last (dll-header-last header)))
+    (setf (dll-node-pred node) last
+          (dll-header-last header) node
+          (dll-node-succ node) header
+          (dll-node-succ last) node)))
+
+;;; Splice one or more nodes out of the containing doubly-linked list.
+;;; Return the first and last nodes in the new chain.
+(defun remove-dll-node (node &optional (count 1))
+  (declare (fixnum count))
+  (do* ((last node (dll-node-succ last))
+        (i 1 (1+ i)))
+       ((= i count)
+        (let* ((prev (dll-node-pred node))
+               (after (dll-node-succ last)))
+          (setf (dll-node-pred after) prev
+                (dll-node-succ prev) after
+                (dll-node-pred node) nil
+                (dll-node-succ last) nil)
+          (values node last)))
+    (declare (fixnum i))
+    ;; This check shouldn't cost much and keeps us from doing
+    ;; something really stupid.
+    (when (typep last 'dll-header)
+      (error "Can't remove header node ."))))
+
+;;; Insert one or mode nodes after a specified node.  To be sane, the
+;;; "chainlast" argument must be "node" or a transitive successor of
+;;; "node", (and "node" EQ to or a transitive predecessor of
+;;; "chainlast", and no list header should appear on the chain between
+;;; "node" and "chainlast".  The typical cases where this is used are
+;;; to insert a freshly consed node into a list or to insert a chain
+;;; of one or more freshly deleted nodes.  Both of these cases satisfy
+;;; the sanity check, so it isn't performed here.
+(defun insert-dll-node-after (node after &optional (chainlast node))
+  (let* ((after-after (dll-node-succ after)))
+    (setf (dll-node-pred node) after
+          (dll-node-succ chainlast) after-after
+          (dll-node-pred after-after) chainlast
+          (dll-node-succ after) node)))
+
+;;; More concise, somehow ...
+(defun insert-dll-node-before (node before &optional (chainlast node))
+  (insert-dll-node-after node (dll-node-pred before) chainlast))
+
+(defun move-dll-nodes (node after &optional (count 1))
+  (multiple-value-bind (first last) (remove-dll-node node count)
+    (insert-dll-node-after first after last)))
+
+;;; Return chain head and tail, or (values nil nil) if empty header.
+(defun detach-dll-nodes (header)
+  (let* ((first (dll-header-first header)))
+    (if (eq first header)
+      (values nil nil)
+      (let* ((last (dll-header-last header)))
+        (setf (dll-header-first header) header
+              (dll-header-last header) header
+              (dll-node-pred first) nil
+              (dll-node-succ last) nil)
+        (values first last)))))
+
+(defun merge-dll-nodes (target &rest others)
+  (declare (dynamic-extent others))
+  (dolist (other others target)
+    (multiple-value-bind (head tail) (detach-dll-nodes other)
+      (when head
+        (insert-dll-node-after head (dll-header-last target) tail)))))
+
+;;; This definition doesn't work when the body unlinks "more than" the
+;;; current node.
+(defmacro do-dll-nodes ((valvar header &optional result) &body body)
+  (let* ((headervar (make-symbol "HEADER"))
+         (next (make-symbol "NEXT")))
+    `(do* ((,headervar ,header)
+           (,valvar (dll-header-first ,headervar) ,next)
+           (,next (dll-node-succ ,valvar) (dll-node-succ ,valvar)))
+          ((eq ,valvar ,headervar)
+           ,result)         
+       ,@body)))
+
+(defun dll-header-length (header)
+  (let* ((count 0))
+    (declare (fixnum count))
+    (do-dll-nodes (n header count)
+      (incf count))))
+
+(defun dll-node-position (node header)
+  (let* ((pos 0))
+    (declare (fixnum pos))
+    (do-dll-nodes (n header)
+      (if (eq n node)
+        (return pos)
+        (incf pos)))))
+
+;;; dll-node freelisting ...
+
+(defun make-dll-node-freelist ()
+  (%cons-pool))
+
+;;; header shouldn't be used after this is called
+(defun return-dll-nodes (header freelist)
+  (without-interrupts
+   (let* ((pool-header (pool.data freelist)))
+     (if (null pool-header)
+       (setf (pool.data freelist) header)
+       (multiple-value-bind (first last) (detach-dll-nodes header)
+         (if first
+           (insert-dll-node-after first (dll-header-last pool-header) last))))
+     nil)))
+
+;;; Pop a node off off the freelist; return NIL if the freelist is
+;;; empty.  Set the succ and pred slots of the node to NIL; other
+;;; slots are undefined.
+(defun alloc-dll-node (freelist)
+  (without-interrupts
+   (let* ((pool-header (pool.data freelist))
+          (node (if pool-header (dll-header-first pool-header))))
+     (if (and node (not (eq node pool-header)))
+       (remove-dll-node node)))))
+
+(defun free-dll-node (node freelist)
+  (without-interrupts
+   (let* ((pool-header (pool.data freelist)))
+     (if (null pool-header)
+       (progn
+         (setq pool-header (make-dll-header))
+         (setf (pool.data freelist) pool-header)))
+     (append-dll-node node pool-header)
+     nil)))
+
+(defun remove-and-free-dll-node (node freelist)
+  (remove-dll-node node)
+  (free-dll-node node freelist))
+
+(defmacro with-dll-node-freelist ((header-var freelist) &body body)
+  (let* ((internal-header-name (gensym))
+         (internal-freelist-name (gensym))
+         (constructor-name 'make-dll-header))
+    (if (consp header-var)
+      (setq constructor-name (cadr header-var)
+            header-var (car header-var)))
+    `(let* ((,internal-header-name (,constructor-name))
+            (,internal-freelist-name ,freelist))
+       (unwind-protect
+         (let* ((,header-var ,internal-header-name))
+           ,@body)
+         (return-dll-nodes ,internal-header-name ,internal-freelist-name)))))
+
+(defstruct (locked-dll-header
+	     (:include dll-header)
+	     (:constructor %make-locked-dll-header))
+  (lock (make-lock)))
+
+(defun make-locked-dll-header ()
+  (init-dll-header (%make-locked-dll-header)))
+
+(defmacro with-locked-dll-header ((h) &body body)
+  `(with-lock-grabbed ((locked-dll-header-lock ,h))
+    ,@body))
+
+(defun locked-dll-header-enqueue (node header)
+  (with-locked-dll-header (header)
+    (append-dll-node node header)))
+
+(defun locked-dll-header-dequeue (header)
+  (with-locked-dll-header (header)
+    (let* ((first (dll-header-first header)))
+      (unless (eq first header)
+	(remove-dll-node first)))))
+
+(provide "DLL-NODE")
Index: /branches/new-random/compiler/lambda-list.lisp
===================================================================
--- /branches/new-random/compiler/lambda-list.lisp	(revision 13309)
+++ /branches/new-random/compiler/lambda-list.lisp	(revision 13309)
@@ -0,0 +1,114 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+
+;;; Compiler functions needed elsewhere
+
+(defun %lfun-info-index (fn)
+  (and (compiled-function-p fn)
+       (let ((bits (lfun-bits fn)))
+         (declare (fixnum bits))
+         (and (logbitp $lfbits-info-bit bits)
+               (%i- (uvsize (function-to-function-vector fn))
+                              (if (logbitp $lfbits-noname-bit bits) 2 3))))))
+(defun %lfun-info (fn)
+  (let* ((index (%lfun-info-index fn)))
+    (if index (%svref (function-to-function-vector fn) index))))
+
+(defun function-source-note (fn)
+  (getf (%lfun-info fn) '%function-source-note))
+
+(defun uncompile-function (fn)
+  (getf (%lfun-info fn) 'function-lambda-expression ))
+
+;;; used-by: backtrace, arglist
+(defun function-symbol-map (fn)
+  (getf (%lfun-info fn) 'function-symbol-map))
+
+(defun find-source-note-at-pc (fn pc)
+  ;(declare (values source-note start-pc end-pc))
+  (let* ((function-note (function-source-note fn))
+         (pc-source-map (getf (%lfun-info fn) 'pc-source-map))
+         (best-guess -1)
+         (best-length 0)
+         (len (length pc-source-map)))
+    (declare (fixnum best-guess best-length len))
+    (when (and function-note pc-source-map)
+      (do ((q 0 (+ q 4)))
+          ((= q len))
+        (declare (fixnum q))
+        (let* ((pc-start (aref pc-source-map q))
+               (pc-end (aref pc-source-map (%i+ q 1))))
+          (declare (fixnum pc-start pc-end))
+          (when (and (<= pc-start pc)
+		     (< pc pc-end)
+                     (or (eql best-guess -1)
+                         (< (%i- pc-end pc-start) best-length)))
+            (setf best-guess q
+                  best-length (- pc-end pc-start)))))
+      (unless (eql best-guess -1)
+        (values
+          (let ((def-pos (source-note-start-pos function-note)))
+            (make-source-note :source function-note
+                              :filename (source-note-filename function-note)
+                              :start-pos (+ def-pos (aref pc-source-map (+ best-guess 2)))
+                              :end-pos (+ def-pos (aref pc-source-map (+ best-guess 3)))))
+          (aref pc-source-map best-guess)
+          (aref pc-source-map (+ best-guess 1)))))))
+
+;;; Lambda-list utilities
+
+
+
+
+
+;;; Lambda-list verification:
+
+;;; these things MUST be compiled.
+(eval-when (:load-toplevel)
+
+(defvar *structured-lambda-list* nil)
+
+
+
+
+(defun parse-body (body env &optional (doc-string-allowed t) &aux
+   decls
+   doc
+   (tail body)
+   form)
+  (declare (ignore env))
+  (loop
+   (if (endp tail) (return))  ; otherwise, it has a %car and a %cdr
+   (if (and (stringp (setq form (%car tail))) (%cdr tail))
+    (if doc-string-allowed
+     (setq doc form)
+     (return))
+    (if (not (and (consp form) (symbolp (%car form)))) 
+     (return)
+     (if (eq (%car form) 'declare)
+      (push form decls)
+      (return))))
+   (setq tail (%cdr tail)))
+  (return-from parse-body (values tail (nreverse decls) doc)))
+
+) ; end of eval-when (load)
+
+;;; End of verify-lambda-list.lisp
Index: /branches/new-random/compiler/nx-base-app.lisp
===================================================================
--- /branches/new-random/compiler/nx-base-app.lisp	(revision 13309)
+++ /branches/new-random/compiler/nx-base-app.lisp	(revision 13309)
@@ -0,0 +1,31 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+; Loaded instead of compiler for standalone applications.
+
+(in-package "CCL")
+
+;(require 'numbers)
+(require 'sort)
+(require 'hash)
+
+; this file is now equiv to nx-basic
+(%include "ccl:compiler;nx-basic.lisp")  ; get cons-var, augment-environment
+; nx-basic includes lambda-list
+
+; End of nx-base-app.lisp
Index: /branches/new-random/compiler/nx-basic.lisp
===================================================================
--- /branches/new-random/compiler/nx-basic.lisp	(revision 13309)
+++ /branches/new-random/compiler/nx-basic.lisp	(revision 13309)
@@ -0,0 +1,709 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;; used by compiler and eval - stuff here is not excised with rest of compiler
+
+
+(in-package :ccl)
+
+#|| Note: when MCL-AppGen 4.0 is built, the following form will need to be included in it:
+; for compiler-special-form-p, called by cheap-eval-in-environment
+(defparameter *nx1-compiler-special-forms*
+  `(%DEFUN %FUNCTION %NEW-PTR %NEWGOTAG %PRIMITIVE %VREFLET BLOCK CATCH COMPILER-LET DEBIND
+    DECLARE EVAL-WHEN FBIND FLET FUNCTION GO IF LABELS LAP LAP-INLINE LET LET* LOAD-TIME-VALUE
+    LOCALLY MACRO-BIND MACROLET MAKE-LIST MULTIPLE-VALUE-BIND MULTIPLE-VALUE-CALL
+    MULTIPLE-VALUE-LIST MULTIPLE-VALUE-PROG1 NEW-LAP NEW-LAP-INLINE NFUNCTION OLD-LAP
+    OLD-LAP-INLINE OR PROG1 PROGN PROGV QUOTE RETURN-FROM SETQ STRUCT-REF STRUCT-SET
+    SYMBOL-MACROLET TAGBODY THE THROW UNWIND-PROTECT WITH-STACK-DOUBLE-FLOATS WITHOUT-INTERRUPTS))
+||#
+
+(eval-when (:compile-toplevel)
+  (require 'nxenv))
+
+(defvar *lisp-compiler-version* 666 "I lost count.")
+
+(defvar *nx-compile-time-types* nil)
+(defvar *nx-proclaimed-types* nil)
+(defvar *nx-method-warning-name* nil)
+
+(defvar *nx-current-code-note*)
+
+;; The problem with undefind type warnings is that there is no in-language way to shut
+;; them up even when the reference is intentional.  (In case of undefined functions,
+;; you can declare FTYPE and that will turn off any warnings without interfering with
+;; the function being defined later).  For now just provide this as an out.
+(defvar *compiler-warn-on-undefined-type-references* #+ccl-0711 t #-ccl-0711 t)
+
+
+
+;; In lieu of a slot in acode.  Don't reference this variable elsewhere because I'm
+;; hoping to make it go away.
+(defparameter *nx-acode-note-map* nil)
+
+(defun acode-note (acode &aux (hash *nx-acode-note-map*))
+  (and hash (gethash acode hash)))
+
+(defun (setf acode-note) (note acode)
+  (when note
+    (assert *nx-acode-note-map*)
+    ;; Only record if have a unique key
+    (unless (or (atom acode)
+                (nx-null acode)
+                (nx-t acode))
+      (setf (gethash acode *nx-acode-note-map*) note))))
+
+
+(defstruct (code-note (:constructor %make-code-note))
+  ;; Code coverage state.  This MUST be the first slot - see nx2-code-coverage.
+  code-coverage
+  ;; The source note of this form, or NIL if random code form (no file info,
+  ;; generated by macros or other source transform)
+  source-note
+  ;; the note that was being compiled when this note was emitted.
+  parent-note
+  #+debug-code-notes ;; The actual source form - useful for debugging, otherwise unused.
+  form)
+
+(defun make-code-note (&key form source-note parent-note)
+  (declare (ignorable form))
+  (let ((note (%make-code-note
+               :source-note source-note
+               :parent-note parent-note)))
+    #+debug-code-notes
+    (when form
+      ;; Unfortunately, recording the macroexpanded form is problematic, since they
+      ;; can have references to non-dumpable forms, see e.g. loop.
+      (setf (code-note-form note)
+	    (with-output-to-string (s) (let ((*print-circle* t)) (prin1 form s)))))
+    note))
+
+(defmethod print-object ((note code-note) stream)
+  (print-unreadable-object (note stream :type t :identity t)
+    (format stream "[~s]" (code-note-code-coverage note))
+    (let ((sn (code-note-source-note note)))
+      (if sn
+        (progn
+          (format stream " for ")
+          (print-source-note sn stream))
+        #+debug-code-notes
+        (when (code-note-form note)
+          (format stream " form ~a"
+                  (string-sans-most-whitespace (code-note-form note))))))))
+
+(defun nx-ensure-code-note (form &optional parent-note)
+  (let* ((parent-note (or parent-note *nx-current-code-note*))
+         (source-note (nx-source-note form)))
+    (unless (and source-note
+                 ;; Look out for a case like a lambda macro that turns (lambda ...)
+                 ;; into (FUNCTION (lambda ...)) which then has (lambda ...)
+                 ;; as a child.  Create a fresh note for the child, to avoid ambiguity.
+                 ;; Another case is forms wrapping THE around themselves.
+                 (neq source-note (code-note-source-note parent-note))
+                 ;; Don't use source notes from a different toplevel form, which could
+                 ;; happen due to inlining etc.  The result then is that the source note
+                 ;; appears in multiple places, and shows partial coverage (from the
+                 ;; other reference) in code that's never executed.
+                 (loop for p = parent-note then (code-note-parent-note p)
+                       when (null p) return t
+                       when (code-note-source-note p)
+                       return (eq (loop for n = source-note then s
+                                        as s = (source-note-source n)
+                                        unless (source-note-p s) return n)
+                                  (loop for n = (code-note-source-note p) then s
+                                        as s = (source-note-source n)
+                                        unless (source-note-p s) return n))))
+      (setq source-note nil))
+    (make-code-note :form form :source-note source-note :parent-note parent-note)))
+
+(defun nx-note-source-transformation (original new &aux (source-notes *nx-source-note-map*) sn)
+  (when (and source-notes
+             (setq sn (gethash original source-notes))
+             (not (gethash new source-notes)))
+    (setf (gethash new source-notes) sn)))
+
+
+(defvar *nx1-alphatizers* (make-hash-table :size 180 :test #'eq))
+
+(let ((policy (%istruct 'compiler-policy
+               #'(lambda (env)
+                   #+ccl-0711 (< (debug-optimize-quantity env) 2)
+                   #-ccl-0711 (neq (debug-optimize-quantity env) 3))   ;  allow-tail-recursion-elimination
+               #'(lambda (env)
+                   (declare (ignorable env))
+                   #+ccl-0711 nil
+                   #-ccl-0711 (eq (debug-optimize-quantity env) 3))   ; inhibit-register-allocation
+               #'(lambda (env)
+                   (let* ((safety (safety-optimize-quantity env)))
+                     (and (< safety 3)
+                          (>= (speed-optimize-quantity env)
+                              safety)))) ; trust-declarations
+               #'(lambda (env)
+                   #+ccl-0711 (> (speed-optimize-quantity env)
+                                 (space-optimize-quantity env))
+                   #-ccl-0711 (>= (speed-optimize-quantity env)
+                                  (+ (space-optimize-quantity env) 2))) ; open-code-inline
+               #'(lambda (env)
+                   (and (eq (speed-optimize-quantity env) 3) 
+                        (eq (safety-optimize-quantity env) 0)))   ; inhibit-safety-checking
+               #'(lambda (env)
+                   (let* ((safety (safety-optimize-quantity env)))
+                     (or (eq safety 3)
+                         (> safety (speed-optimize-quantity env)))))          ;declarations-typecheck
+               #'(lambda (env)
+                   (neq (debug-optimize-quantity env) 3))   ; inline-self-calls
+               #'(lambda (env)
+                   (and (neq (compilation-speed-optimize-quantity env) 3)
+                        (or (neq (speed-optimize-quantity env) 0)
+                            (and (neq (safety-optimize-quantity env) 3)
+                                 (neq (debug-optimize-quantity env) 3))))) ; allow-transforms
+               #'(lambda (var env)       ; force-boundp-checks
+                   (declare (ignore var))
+                   (eq (safety-optimize-quantity env) 3))
+               #'(lambda (var val env)       ; allow-constant-substitution
+                   (declare (ignore var val env))
+                   t)
+               nil           ; extensions
+               )))
+  (defun new-compiler-policy (&key (allow-tail-recursion-elimination nil atr-p)
+                                   (inhibit-register-allocation nil ira-p)
+                                   (trust-declarations nil td-p)
+                                   (open-code-inline nil oci-p)
+                                   (inhibit-safety-checking nil ischeck-p)
+                                   (inline-self-calls nil iscall-p)
+                                   (allow-transforms nil at-p)
+                                   (force-boundp-checks nil fb-p)
+                                   (allow-constant-substitution nil acs-p)
+                                   (declarations-typecheck nil dt-p))
+    (let ((p (copy-uvector policy)))
+      (if atr-p (setf (policy.allow-tail-recursion-elimination p) allow-tail-recursion-elimination))
+      (if ira-p (setf (policy.inhibit-register-allocation p) inhibit-register-allocation))
+      (if td-p (setf (policy.trust-declarations p) trust-declarations))
+      (if oci-p (setf (policy.open-code-inline p) open-code-inline))
+      (if ischeck-p (setf (policy.inhibit-safety-checking p) inhibit-safety-checking))
+      (if iscall-p (setf (policy.inline-self-calls p) inline-self-calls))
+      (if at-p (setf (policy.allow-transforms p) allow-transforms))
+      (if fb-p (setf (policy.force-boundp-checks p) force-boundp-checks))
+      (if acs-p (setf (policy.allow-constant-substitution p) allow-constant-substitution))
+      (if dt-p (setf (policy.declarations-typecheck p) declarations-typecheck))
+      p))
+  (defun %default-compiler-policy () policy))
+
+(%include "ccl:compiler;lambda-list.lisp")
+
+
+;Syntactic Environment Access.
+
+(defun declaration-information (decl-name &optional env)
+  (if (and env (not (istruct-typep env 'lexical-environment)))
+    (report-bad-arg env 'lexical-environment))
+; *** This needs to deal with things defined with DEFINE-DECLARATION ***
+  (case decl-name
+    (optimize
+     (list 
+      (list 'speed (speed-optimize-quantity env))
+      (list 'safety (safety-optimize-quantity env))
+      (list 'compilation-speed (compilation-speed-optimize-quantity env))
+      (list 'space (space-optimize-quantity env))
+      (list 'debug (debug-optimize-quantity env))))
+    (declaration
+     *nx-known-declarations*)))
+
+(defun function-information (name &optional env &aux decls)
+  (let ((name (ensure-valid-function-name name)))
+    (if (and env (not (istruct-typep env 'lexical-environment)))
+      (report-bad-arg env 'lexical-environment))
+    (if (special-operator-p name)
+      (values :special-form nil nil)
+      (flet ((process-new-fdecls (fdecls)
+                                 (dolist (fdecl fdecls)
+                                   (when (eq (car fdecl) name)
+                                     (let ((decl-type (cadr fdecl)))
+                                       (when (and (memq decl-type '(dynamic-extent inline ftype))
+                                                  (not (assq decl-type decls)))
+                                         (push (cdr fdecl) decls)))))))
+        (declare (dynamic-extent #'process-new-fdecls))
+        (do* ((root t)
+              (contour env (when root (lexenv.parent-env contour))))
+             ((null contour)
+              (if (macro-function name)
+                (values :macro nil nil)
+                (if (fboundp name)
+                  (values :function 
+                          nil 
+                          (if (assq 'inline decls)
+			    decls
+                            (if (proclaimed-inline-p name)
+			      (push '(inline . inline) decls)
+                                (if (proclaimed-notinline-p name)
+				  (push '(inline . notinline) decls)))))
+                  (values nil nil decls))))
+          (if (istruct-typep contour 'definition-environment)
+            (if (assq name (defenv.functions contour))
+              (return (values :macro nil nil))
+              (progn (setq root nil) (process-new-fdecls (defenv.fdecls contour))))
+            (progn
+              (process-new-fdecls (lexenv.fdecls contour))
+              (let ((found (assq name (lexenv.functions contour))))
+                (when found
+                  (return
+                   (if (and (consp (cdr found))(eq (%cadr found) 'macro))
+                     (values :macro t nil)
+                     (values :function t decls))))))))))))
+
+(defun variable-information (var &optional env)
+  (setq var (require-type var 'symbol))
+  (if (and env (not (istruct-typep env 'lexical-environment)))
+    (report-bad-arg env 'lexical-environment))
+  (let* ((vartype nil)
+         (boundp nil)
+         (envtype nil)
+         (typedecls (nx-declared-type var env)) ; should grovel nested/shadowed special decls for us.
+         (decls (if (and typedecls (neq t typedecls)) (list (cons 'type typedecls)))))
+    (loop
+      (cond ((null env)
+             (if (constant-symbol-p var)
+               (setq vartype :constant decls nil)
+               (if (proclaimed-special-p var)
+                 (setq vartype :special)
+		 (let* ((not-a-symbol-macro (cons nil nil)))
+		   (declare (dynamic-extent not-a-symbol-macro))
+		   (unless (eq (gethash var *symbol-macros* not-a-symbol-macro)
+			       not-a-symbol-macro)
+		     (setq vartype :symbol-macro)))))
+             (return))
+            ((eq (setq envtype (istruct-type-name env)) 'definition-environment)
+             (cond ((assq var (defenv.constants env))
+                    (setq vartype :constant)
+                    (return))
+		   ((assq var (defenv.symbol-macros env))
+		    (setq vartype :symbol-macro)
+		    (return))
+                   ((assq var (defenv.specials env))
+                    (setq vartype :special)
+                    (return))))
+            (t
+             (dolist (vdecl (lexenv.vdecls env))
+               (when (eq (car vdecl) var)
+                 (let ((decltype (cadr vdecl)))
+                   (unless (assq decltype decls)
+                     (case decltype
+                       (special (setq vartype :special))
+                       ((type dynamic-extent ignore) (push (cdr vdecl) decls)))))))
+             (let ((vars (lexenv.variables env)))
+	       (unless (atom vars)
+                 (dolist (v vars)
+                   (when (eq (var-name v) var)
+                     (setq boundp t)
+                     (if (and (consp (var-ea v))
+                              (eq :symbol-macro (car (var-ea v))))
+                       (setq vartype :symbol-macro)
+                       (unless vartype (setq vartype
+					     (let* ((bits (var-bits v)))
+					       (if (and (typep bits 'integer)
+							(logbitp $vbitspecial bits))
+						 :special
+						 :lexical)))))
+                     (return)))
+		 (when vartype (return))))))
+      (setq env (if (eq envtype 'lexical-environment) (lexenv.parent-env env))))
+    (values vartype boundp decls)))
+
+(defun nx-target-type (typespec)
+  ;; Could do a lot more here
+  (if (or (eq *host-backend* *target-backend*)
+          (not (eq typespec 'fixnum)))
+    typespec
+    (target-word-size-case
+     (32 '(signed-byte 30))
+     (64 '(signed-byte 61)))))
+
+; Type declarations affect all references.
+(defun nx-declared-type (sym &optional (env *nx-lexical-environment*))
+  (loop
+    (when (or (null env) (istruct-typep env 'definition-environment)) (return))
+    (dolist (decl (lexenv.vdecls env))
+      (if (and (eq (car decl) sym)
+               (eq (cadr decl) 'type))
+               (return-from nx-declared-type (nx-target-type (cddr decl)))))
+    (let ((vars (lexenv.variables env)))
+      (when (and (consp vars) 
+                 (dolist (var vars) 
+                   (when (eq (var-name var) sym) 
+                     (return t))))
+        (return-from nx-declared-type t)))
+    (setq env (lexenv.parent-env env)))
+  (let ((decl (or (assq sym *nx-compile-time-types*)
+                     (assq sym *nx-proclaimed-types*))))
+    (if decl (%cdr decl) t)))
+
+(defun nx-declared-result-type (sym &optional (env *nx-lexical-environment*) args)
+  (when (symbolp (setq sym (maybe-setf-function-name sym)))
+    (let* ((ftype (find-ftype-decl sym env args))
+	   (ctype (and ftype (if (typep ftype 'ctype) ftype (specifier-type-if-known ftype env)))))
+      (unless (or (null ctype)
+		  (not (function-ctype-p ctype))
+		  (eq *wild-type* (function-ctype-returns ctype)))
+	(let ((result-type (type-specifier (single-value-type (function-ctype-returns ctype)))))
+	  (and (neq result-type 't) result-type))))))
+
+(defmacro define-declaration (decl-name lambda-list &body body &environment env)
+  (multiple-value-bind (body decls)
+                       (parse-body body env)
+    (let ((fn `(nfunction (define-declaration ,decl-name)
+                          (lambda ,lambda-list
+                            ,@decls
+                            (block ,decl-name
+                              ,@body)))))
+      `(progn
+         (proclaim '(declaration ,decl-name))
+         (setf (getf *declaration-handlers* ',decl-name) ,fn)))))
+
+(defun check-environment-args (variable symbol-macro function macro)
+  (flet ((check-all-pairs (pairlist argname)
+          (dolist (pair pairlist)
+            (unless (and (consp pair) (consp (%cdr pair)) (null (%cddr pair)) (symbolp (%car pair)))
+              (signal-simple-program-error "Malformed ~s argument: ~s is not of the form (~S ~S) in ~S" 
+                                           argname
+                                           pair
+                                           'name
+                                           'definition
+                                           pairlist))))
+         (check-all-symbols (symlist argname pairs pairsname)
+          (dolist (v symlist)
+            (unless (symbolp v) 
+              (signal-simple-program-error "Malformed ~S list: ~S is not a symbol in ~S." argname v symlist))
+            (when (assq v pairs) 
+              (signal-simple-program-error "~S ~S conflicts with ~S ~S" argname v pairsname (assq v pairs))))))
+    (check-all-pairs symbol-macro :symbol-macro)
+    (check-all-pairs macro :macro)
+    (check-all-symbols variable :variable symbol-macro :symbol-macro)
+    (check-all-symbols function :function macro :macro)))
+
+
+;; This -isn't- PARSE-DECLARATIONS.  It can't work; neither can this ...
+(defun process-declarations (env decls symbol-macros)
+  (let ((vdecls nil)
+        (fdecls nil)
+        (mdecls nil))
+    (flet ((add-type-decl (spec)
+            (destructuring-bind (typespec &rest vars) spec
+              (dolist (var vars)
+                (when (non-nil-symbol-p var)
+                  (push (list* var 
+                               'type
+                               (let ((already (assq 'type (nth-value 2 (variable-information var env)))))
+                                 (if already
+                                   (let ((oldtype (%cdr already)))
+                                     (if oldtype
+                                       (if (subtypep oldtype typespec)
+                                         oldtype
+                                         (if (subtypep typespec oldtype)
+                                           typespec))))
+                                   typespec)))
+                        vdecls))))))
+      ; do SPECIAL declarations first - this approximates the right thing, but doesn't quite make it.
+      (dolist (decl decls)
+        (when (eq (car decl) 'special)
+          (dolist (spec (%cdr decl))
+            (when (non-nil-symbol-p spec)
+              (if (assq spec symbol-macros)
+                (signal-program-error "Special declaration cannot be applied to symbol-macro ~S" spec))
+              (push (list* spec 'special t) vdecls)))))
+      (dolist (decl decls)
+        (let ((decltype (car decl)))
+          (case decltype
+              ((inline notinline)
+               (dolist (spec (%cdr decl))
+               (let ((fname nil))
+                 (if (non-nil-symbol-p spec)
+                   (setq fname spec)
+                   (if (setf-function-name-p spec)
+                     (setq fname (setf-function-name (cadr spec)))))
+                 (if fname
+                   (push (list* fname decltype t) fdecls)))))
+              (optimize
+               (dolist (spec (%cdr decl))
+                 (let ((val 3)
+                       (quantity spec))
+                   (if (consp spec)
+                     (setq quantity (car spec) val (cadr spec)))
+                 (if (and (fixnump val) (<= 0 val 3) (memq quantity '(debug speed space safety compilation-speed)))
+                   (push (cons quantity val) mdecls)))))
+              (dynamic-extent
+               (dolist (spec (%cdr decl))
+               (if (non-nil-symbol-p spec)
+                 (push (list* spec decltype t) vdecls)
+                 (if (and (consp spec) (eq (%car spec) 'function))
+                   (let ((fname (cadr spec)))
+                     (if (not (non-nil-symbol-p fname))
+                       (setq fname 
+                             (if (setf-function-name-p fname)
+                               (setf-function-name (cadr fname)))))
+                     (if fname (push (list* fname decltype t) fdecls)))))))
+              (type (add-type-decl (cdr decl)))
+              (ftype (destructuring-bind (typespec &rest fnames) (%cdr decl)
+                       (dolist (name fnames)
+                         (let ((fname name))
+                           (if (not (non-nil-symbol-p fname))
+                             (setq fname 
+                                   (if (setf-function-name-p fname)
+                                     (setf-function-name (cadr fname)))))
+                           (if fname (push (list* fname decltype typespec) fdecls))))))
+              (special)
+              (t
+               (if (memq decltype *cl-types*)
+                 (add-type-decl decl)
+                 (let ((handler (getf *declaration-handlers* decltype)))
+                   (when handler
+                     (multiple-value-bind (type info) (funcall handler decl)
+                       (ecase type
+                         (:variable
+                          (dolist (v info) (push (apply #'list* v) vdecls)))
+                         (:function
+                          (dolist (f info) (push (apply #'list* f) fdecls)))
+                         (:declare  ;; N.B. CLtL/2 semantics
+                          (push info mdecls)))))))))))
+      (setf (lexenv.vdecls env) (nconc vdecls (lexenv.vdecls env))
+            (lexenv.fdecls env) (nconc fdecls (lexenv.fdecls env))
+            (lexenv.mdecls env) (nconc mdecls (lexenv.mdecls env))))))
+
+ 
+(defun cons-var (name &optional (bits 0))
+  (%istruct 'var name bits nil nil nil nil nil nil))
+
+
+(defun augment-environment (env &key variable symbol-macro function macro declare)
+  (if (and env (not (istruct-typep env 'lexical-environment)))
+    (report-bad-arg env 'lexical-environment))
+  (check-environment-args variable symbol-macro function macro)
+  (let* ((vars (mapcar #'cons-var variable))
+         (symbol-macros (mapcar #'(lambda (s)
+				    (let* ((sym (car s)))
+				      (unless (and (symbolp sym)
+						   (not (constantp sym env))
+						   (not (eq (variable-information sym env) :special)))
+					(signal-program-error "~S can't by bound as a SYMBOL-MACRO" sym))
+				      (let ((v (cons-var (car s)))) 
+					(setf (var-expansion v) (cons :symbol-macro (cadr s)))
+					v)))
+				symbol-macro))
+         (macros (mapcar #'(lambda (m) (list* (car m) 'macro (cadr m))) macro))
+         (functions (mapcar #'(lambda (f) (list* f 'function nil)) function))
+         (new-env (new-lexical-environment env)))
+    (setf (lexenv.variables new-env) (nconc vars symbol-macros)
+          (lexenv.functions new-env) (nconc functions macros))
+    (process-declarations new-env declare symbol-macro)
+    new-env))
+
+(defun enclose (lambda-expression &optional env)
+  (if (and env (not (istruct-typep env 'lexical-environment)))
+    (report-bad-arg env 'lexical-environment))
+  (unless (lambda-expression-p lambda-expression)
+    (error "Invalid lambda-expression ~S." lambda-expression))
+  (%make-function nil lambda-expression env))
+
+#|| Might be nicer to do %declaim
+(defmacro declaim (&rest decl-specs &environment env)
+  `(progn
+     (eval-when (:load-toplevel :execute)
+       (proclaim ',@decl-specs))
+     (eval-when (:compile-toplevel)
+       (%declaim ',@decl-specs ,env))))
+||#
+
+(defmacro declaim (&environment env &rest decl-specs)
+  "DECLAIM Declaration*
+  Do a declaration or declarations for the global environment."
+  (let* ((body (mapcar #'(lambda (spec) `(proclaim ',spec)) decl-specs)))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (compile-time-proclamation ',decl-specs ,env))
+     (eval-when (:load-toplevel :execute)
+       ,@body))))
+
+(defvar *strict-checking* nil
+  "If true, issues warnings/errors in more cases, e.g. for valid but non-portable code")
+
+
+;; Should be true if compiler warnings UI doesn't use source locations, false if it does.
+(defvar *merge-compiler-warnings* t "If false, don't merge compiler warnings with different source locations")
+
+;;; If warnings have more than a single entry on their
+;;; args slot, don't merge them.
+(defun merge-compiler-warnings (old-warnings)
+  (let ((warnings nil))
+    (dolist (w old-warnings)
+      (let* ((w-args (compiler-warning-args w)))
+        (if
+          (or (cdr w-args)
+              ;; See if W can be merged into an existing warning
+              (dolist (w1 warnings t) 
+                (let ((w1-args (compiler-warning-args w1)))
+                  (when (and (eq (compiler-warning-warning-type w)
+                                 (compiler-warning-warning-type w1))
+                             w1-args
+                             (null (cdr w1-args))
+                             (eq (%car w-args)
+                                 (%car w1-args))
+                             (or *merge-compiler-warnings*
+                                 (eq (compiler-warning-source-note w)
+                                     (compiler-warning-source-note w1))))
+                    (let ((nrefs (compiler-warning-nrefs w1)))
+                      (setf (compiler-warning-nrefs w1)
+                            (cons (compiler-warning-source-note w)
+                                  (or nrefs
+                                      (list (compiler-warning-source-note w1)))))
+                      (return nil))))))
+          (push w warnings))))
+    warnings))
+
+;;; This is called by, e.g., note-function-info & so can't be -too- funky ...
+;;; don't call proclaimed-inline-p or proclaimed-notinline-p with alphatized crap
+
+(defun nx-declared-inline-p (sym env)
+  (setq sym (maybe-setf-function-name sym))
+  (loop
+    (when (listp env)
+      (return (and (symbolp sym)
+                   (proclaimed-inline-p sym))))
+    (dolist (decl (lexenv.fdecls env))
+      (when (and (eq (car decl) sym)
+                 (eq (cadr decl) 'inline))
+        (return-from nx-declared-inline-p (eq (cddr decl) 'inline))))
+    (setq env (lexenv.parent-env env))))
+
+(defun report-compile-time-argument-mismatch (condition stream &aux (type (compiler-warning-warning-type condition)))
+  (destructuring-bind (callee reason args spread-p)
+      (compiler-warning-args condition)
+    (format stream "In the ~a ~s with arguments ~:s,~%  "
+            (if spread-p "application of" "call to")
+            callee
+            args)
+    (ecase (car reason)
+      (:toomany
+       (destructuring-bind (provided max)
+           (cdr reason)
+         (format stream "~d argument~:p ~:*~[were~;was~:;were~] provided, but at most ~d ~:*~[are~;is~:;are~] accepted~&  by " provided max)))
+      (:toofew
+       (destructuring-bind (provided min)
+           (cdr reason)
+	 (format stream "~d argument~:p ~:*~[were~;was~:;were~] provided, but at least ~d ~:*~[are~;is~:;are~] required~&  by " provided min)))
+      (:odd-keywords
+       (let* ((tail (cadr reason)))
+         (format stream "the variable portion of the argument list ~s contains an odd number~&  of arguments and so can't be used to initialize keyword parameters~&  for " tail)))
+      (:unknown-keyword
+       (destructuring-bind (badguy goodguys)
+           (cdr reason)
+         (format stream "the keyword argument~:[ ~s is~;s~{ ~s~^~#[~; and~:;,~]~} are~] not one of ~:s, which are recognized by "
+		 (consp badguy) badguy goodguys)))
+      (:unknown-gf-keywords
+         (let ((badguys (cadr reason)))
+           (when (and (consp badguys) (null (%cdr badguys))) (setq badguys (car badguys)))
+           (format stream "the keyword argument~:[ ~s is~;s~{ ~s~^~#[~; and~:;,~]~} are~] not recognized by "
+
+                   (consp badguys) badguys))))
+    (format stream
+            (ecase type
+	      (:ftype-mismatch "the FTYPE declaration of ~s")
+              (:global-mismatch "the current global definition of ~s")
+              (:environment-mismatch "the definition of ~s visible in the current compilation unit.")
+              (:lexical-mismatch "the lexically visible definition of ~s")
+              ;; This can happen when compiling without compilation unit:
+              (:deferred-mismatch "~s"))
+            callee)))
+
+(defparameter *compiler-warning-formats*
+  '((:special . "Undeclared free variable ~S")
+    (:unused . "Unused lexical variable ~S")
+    (:ignore . "Variable ~S not ignored.")
+    (:undefined-function . "Undefined function ~S") ;; (deferred)
+    (:undefined-type . "Undefined type ~S")         ;; (deferred)
+    (:unknown-type-in-declaration . "Unknown or invalid type ~S, declaration ignored")
+    (:bad-declaration . "Unknown or invalid declaration ~S")
+    (:invalid-type . report-invalid-type-compiler-warning)
+    (:unknown-declaration-variable . "~s declaration for unknown variable ~s")
+    (:unknown-declaration-function . "~s declaration for unknown function ~s")
+    (:macro-used-before-definition . "Macro function ~S was used before it was defined.")
+    (:unsettable . "Shouldn't assign to variable ~S")
+    (:global-mismatch . report-compile-time-argument-mismatch)
+    (:environment-mismatch . report-compile-time-argument-mismatch)
+    (:lexical-mismatch . report-compile-time-argument-mismatch)    
+    (:ftype-mismatch . report-compile-time-argument-mismatch)
+    (:deferred-mismatch . report-compile-time-argument-mismatch)
+    (:type . "Type declarations violated in ~S")
+    (:type-conflict . "Conflicting type declarations for ~S")
+    (:special-fbinding . "Attempt to bind compiler special name: ~s. Result undefined.")
+    (:lambda . "Suspicious lambda-list: ~s")
+    (:incongruent-gf-lambda-list . "Lambda list of generic function ~s is incongruent with previously defined methods")
+    (:incongruent-method-lambda-list . "Lambda list of ~s is incongruent with previous definition of ~s")
+    (:gf-keys-not-accepted . "~s does not accept keywords ~s required by the generic functions")
+    (:result-ignored . "Function result ignored in call to ~s")
+    (:duplicate-definition . report-compile-time-duplicate-definition)
+    (:format-error . "~:{~@?~%~}")
+    (:program-error . "~a")
+    (:unsure . "Nonspecific warning")))
+
+(defun report-invalid-type-compiler-warning (condition stream)
+  (destructuring-bind (type &optional why) (compiler-warning-args condition)
+    (when (typep why 'invalid-type-specifier)
+      (setq type (invalid-type-specifier-typespec why) why nil))
+    (format stream "Invalid type specifier ~S~@[: ~A~]" type why)))
+
+(defun report-compile-time-duplicate-definition (condition stream)
+  (destructuring-bind (name old-file new-file &optional from to) (compiler-warning-args condition)
+    (format stream
+            "Duplicate definitions of ~s~:[~*~;~:* (as a ~a and a ~a)~]~:[~;, in this file~:[~; and in ~s~]~]"
+            (maybe-setf-name name) from to
+            (and old-file new-file)
+            (neq old-file new-file)
+            old-file)))
+
+(defun adjust-compiler-warning-args (warning-type args)
+  (case warning-type
+    ((:undefined-function :result-ignored) (mapcar #'maybe-setf-name args))
+    (t args)))
+
+
+(defun report-compiler-warning (condition stream &key short)
+  (let* ((warning-type (compiler-warning-warning-type condition))
+         (format-string (cdr (assq warning-type *compiler-warning-formats*)))
+         (warning-args (compiler-warning-args condition)))
+    (unless short
+      (let ((name (reverse (compiler-warning-function-name condition))))
+        (format stream "In ")
+        (print-nested-name name stream)
+        (when (every #'null name)
+          (let ((position (source-note-start-pos (compiler-warning-source-note condition))))
+            (when position (format stream " at position ~s" position))))
+        (format stream ": ")))
+    (if (typep format-string 'string)
+      (apply #'format stream format-string (adjust-compiler-warning-args warning-type warning-args))
+      (if (null format-string)
+	(format stream "~A: ~S" warning-type warning-args)
+	(funcall format-string condition stream)))
+    ;(format stream ".")
+    (let ((nrefs (compiler-warning-nrefs condition)))
+      (when nrefs
+        (format stream " (~D references)" (length nrefs))))))
+
+(defun environment-structref-info (name env)
+  (let ((defenv (definition-environment env)))
+    (when defenv
+      (cdr (assq name (defenv.structrefs defenv))))))
+
+; end
Index: /branches/new-random/compiler/nx.lisp
===================================================================
--- /branches/new-random/compiler/nx.lisp	(revision 13309)
+++ /branches/new-random/compiler/nx.lisp	(revision 13309)
@@ -0,0 +1,228 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel)
+  (require 'nxenv)
+  (require 'numbers)
+  (require 'sequences)
+  (require 'optimizers))
+
+(eval-when (:load-toplevel :execute :compile-toplevel)
+  (require 'numbers) ; just calls 'logcount' and 'integer-length'
+  (require 'sort)    ; just calls '%sort-list-no-keys'
+  (require 'hash))
+
+(%include "ccl:compiler;nx-basic.lisp")
+
+(eval-when (:load-toplevel :execute)
+  (require "DEFSTRUCT"))
+
+(defparameter *nx-start* (cons nil nil))
+
+
+(defvar *host-backend*)
+(defvar *target-backend*)
+
+(defun find-backend (name)
+  (find name *known-backends* :key #'backend-name))
+
+(eval-when (:load-toplevel :execute :compile-toplevel)
+  (require "DLL-NODE")
+  #+ppc-target
+  (require "PPC32-ARCH")
+  (require "VREG")
+  #+ppc-target
+  (require "PPC-ASM")
+  (require "VINSN")
+  (require "REG")
+  (require "SUBPRIMS")
+  #+ppc-target
+  (require "PPC-LAP")
+)
+(%include "ccl:compiler;nx0.lisp")
+(%include "ccl:compiler;nx1.lisp")
+
+; put this in nx-basic too
+;(defvar *lisp-compiler-version* 666 "I lost count.")
+
+; At some point, COMPILE refused to compile things that were defined
+; in a non-null lexical environment (or so I remember.)   That seems
+; to have been broken when the change of 10/11/93 was made.
+; It makes no sense to talk about compiling something that was defined
+; in a lexical environment in which there are symbol or function bindings
+; present;  I'd thought that the old code checked for this, though it
+; may well have botched it.
+(defun compile (spec &optional def &aux (macro-p nil))
+  "Coerce DEFINITION (by default, the function whose name is NAME)
+  to a compiled function, returning (VALUES THING WARNINGS-P FAILURE-P),
+  where if NAME is NIL, THING is the result of compilation, and
+  otherwise THING is NAME. When NAME is not NIL, the compiled function
+  is also set into (MACRO-FUNCTION NAME) if NAME names a macro, or into
+  (FDEFINITION NAME) otherwise."
+  (unless def
+    (setq def (fboundp spec))
+    (when (and (symbolp spec) (not (lfunp def)))
+      (setq def (setq macro-p (macro-function spec)))))
+  #+have-interpreted-functions
+  (when (typep def 'interpreted-function)
+    (let ((lambda (function-lambda-expression def)))
+      (when lambda (setq def lambda))))
+  (unless def
+    (nx-error "Can't find compilable definition for ~S." spec))
+  (multiple-value-bind (lfun warnings)
+                       (if (functionp def)
+                         def
+                         (compile-named-function def
+                                                 :name spec
+                                                 :keep-lambda *save-definitions*
+                                                 :keep-symbols *save-local-symbols*))
+    (let ((harsh nil) (some nil) (init t))
+      (dolist (w warnings)
+        (multiple-value-setq (harsh some) (signal-compiler-warning w init nil harsh some))
+        (setq init nil))
+      (values
+       (if spec
+         (progn
+           (if macro-p
+             (setf (macro-function spec) lfun)
+             (setf (fdefinition spec) lfun))
+           spec)
+         lfun)
+       some
+       harsh))))
+
+(defparameter *default-compiler-policy* (new-compiler-policy))
+
+(defun current-compiler-policy () *default-compiler-policy*)
+
+(defun set-current-compiler-policy (&optional new-policy)
+  (setq *default-compiler-policy* 
+        (if new-policy (require-type new-policy 'compiler-policy) (new-compiler-policy))))
+
+#+ppc-target
+(defun xcompile-lambda (target def)
+  (let* ((*ppc2-debug-mask* (ash 1 ppc2-debug-vinsns-bit))
+         (backend (find-backend target))
+         (*target-ftd* (if backend
+                         (backend-target-foreign-type-data backend)
+                         *target-ftd*))
+         (*target-backend* (or backend *target-backend*)))
+    (multiple-value-bind (xlfun warnings)
+        (compile-named-function def :target target)
+      (signal-or-defer-warnings warnings nil)
+      (ppc-xdisassemble xlfun :target target)
+      xlfun)))
+  
+(defun compile-user-function (def name &optional env)
+  (multiple-value-bind (lfun warnings)
+                       (compile-named-function def
+                                               :name name
+                                               :env env
+                                               :keep-lambda *save-definitions*
+                                               :keep-symbols *save-local-symbols*)
+    (signal-or-defer-warnings warnings env)
+    lfun))
+
+(defun signal-or-defer-warnings (warnings env)
+  (let* ((defenv (definition-environment env))
+         (init t)
+         (defer (and defenv (cdr (defenv.type defenv)) *outstanding-deferred-warnings*)))
+    (dolist (w warnings)
+      (if (and defer (typep w 'undefined-reference))
+        (push w (deferred-warnings.warnings defer))
+        (progn
+          (signal-compiler-warning w init nil nil nil)
+          (setq init nil))))))
+
+(defparameter *load-time-eval-token* nil)
+
+(defparameter *nx-discard-xref-info-hook* nil)
+
+(defparameter *nx-in-frontend* nil)
+
+(defun compile-named-function (def &key name env policy load-time-eval-token target
+                                function-note keep-lambda keep-symbols source-notes
+                                (record-pc-mapping *record-pc-mapping*)
+                                (compile-code-coverage *compile-code-coverage*))
+  ;; SOURCE-NOTES, if not nil, is a hash table mapping source forms to locations,
+  ;;   is used to produce and attach a pc/source map to the lfun, also to attach
+  ;;   source locations and pc/source maps to inner lfuns.
+  ;; FUNCTION-NOTE, if not nil, is a note to attach to the function as the lfun
+  ;;   source location in preference to whatever the source-notes table assigns to it.
+  (when (and name *nx-discard-xref-info-hook*)
+    (funcall *nx-discard-xref-info-hook* name))
+  (setq 
+   def
+   (let* ((*load-time-eval-token* load-time-eval-token)
+	  (*nx-source-note-map* source-notes)
+          (*nx-current-note* function-note)
+          (*record-pc-mapping* (and source-notes record-pc-mapping))
+          (*compile-code-coverage* (and source-notes compile-code-coverage))
+	  (*nx-acode-note-map* (and (or *record-pc-mapping* *compile-code-coverage*)
+                                    (make-hash-table :test #'eq :shared nil)))
+          (*nx-current-code-note* (and *compile-code-coverage*
+                                       (make-code-note :form def :source-note function-note)))
+          (env (new-lexical-environment env)))
+     (setf (lexenv.variables env) 'barrier)
+     (let* ((*target-backend* (or (if target (find-backend target)) *host-backend*))
+            (*nx-in-frontend* t)
+            (afunc (nx1-compile-lambda 
+                    name 
+                    def
+                    (make-afunc) 
+                    nil 
+                    env 
+                    (or policy *default-compiler-policy*)
+                    *load-time-eval-token*)))
+       (setq *nx-in-frontend* nil)
+       (if (afunc-lfun afunc)
+         afunc
+         (funcall (backend-p2-compile *target-backend*)
+                  afunc
+                  ;; will also bind *nx-lexical-environment*
+                  (if keep-lambda (if (lambda-expression-p keep-lambda) keep-lambda def))
+                  keep-symbols)))))
+  (values (afunc-lfun def) (afunc-warnings def)))
+
+(defparameter *compiler-whining-conditions*
+  '((:undefined-function . undefined-function-reference)
+    (:undefined-type . undefined-type-reference)
+    (:deferred-mismatch . undefined-keyword-reference)
+    (:invalid-type . invalid-type-warning)
+    (:global-mismatch . invalid-arguments-global)
+    (:lexical-mismatch . invalid-arguments)
+    (:environment-mismatch . invalid-arguments)
+    (:ftype-mismatch . invalid-arguments)
+    (:ignore . style-warning)
+    (:result-ignored . style-warning)
+    (:lambda . style-warning)
+    (:format-error . style-warning)
+    (:unused . style-warning)))
+
+
+
+(defun compiler-bug (format &rest args)
+  (error (make-condition 'compiler-bug
+                         :format-control format
+                         :format-arguments args)))
+
+
+(defparameter *nx-end* (cons nil nil))
+(provide 'nx)
+
Index: /branches/new-random/compiler/nx0.lisp
===================================================================
--- /branches/new-random/compiler/nx0.lisp	(revision 13309)
+++ /branches/new-random/compiler/nx0.lisp	(revision 13309)
@@ -0,0 +1,2834 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+(in-package "CCL")
+
+;; :compiler:nx0.lisp - part of the compiler
+
+
+(defstruct pending-declarations
+  vdecls
+  fdecls
+  mdecls)
+
+; Phony AFUNC "defstruct":
+(defun make-afunc (&aux (v (%make-afunc)))
+  (setf (afunc-fn-refcount v) 0)
+  (setf (afunc-fn-downward-refcount v) 0)
+  (setf (afunc-bits v) 0)
+  v)
+
+(defvar *compile-code-coverage* nil "True to instrument for code coverage")
+
+(defvar *nx-blocks* nil)
+(defvar *nx-tags* nil)
+(defvar *nx-parent-function* nil)
+(defvar *nx-current-function* nil)
+(defvar *nx-lexical-environment* nil)
+(defvar *nx-symbol-macros* nil)
+(defvar *nx-inner-functions* nil)
+(defvar *nx-cur-func-name* nil)
+(defvar *nx-current-note* nil)
+(defvar *nx-source-note-map* nil) ;; there might be external refs, from macros.
+(defvar *nx-form-type* t)
+;(defvar *nx-proclaimed-inline* nil)
+;(defvar *nx-proclaimed-inline* (make-hash-table :size 400 :test #'eq))
+(defvar *nx-proclaimed-ignore* nil)
+(defvar *nx-parsing-lambda-decls* nil) ; el grosso.
+(defparameter *nx-standard-declaration-handlers* nil)
+(defparameter *nx-hoist-declarations* t)
+(defparameter *nx-loop-nesting-level* 0)
+(defvar *nx-break-on-program-errors* t)
+
+(defvar *nx1-vcells* nil)
+(defvar *nx1-fcells* nil)
+
+(defvar *nx1-operators* (make-hash-table :size 300 :test #'eq))
+
+
+; The compiler can (generally) use temporary vectors for VARs.
+(defun nx-cons-var (name &optional (bits 0))
+  (%istruct 'var name bits nil nil nil nil 0 nil))
+
+
+
+
+(defvar *nx-lambdalist* (make-symbol "lambdalist"))
+(defvar *nx-nil* (list (make-symbol "nil")))
+(defvar *nx-t* (list (make-symbol "t")))
+
+(defparameter *nx-current-compiler-policy* (%default-compiler-policy))
+
+(defvar *nx-next-method-var* nil)
+(defvar *nx-call-next-method-function* nil)
+
+(defvar *nx-sfname* nil)
+(defvar *nx-operators* ())
+(defvar *nx-warnings* nil)
+
+(defvar *nx1-compiler-special-forms* nil "Real special forms")
+
+(defmacro without-compiling-code-coverage (&body body)
+  "Disable code coverage in the lexical scope of the form"
+  `(compiler-let ((*nx-current-code-note* nil))
+     ,@body))
+
+(defparameter *nx-never-tail-call*
+  '(error cerror break warn type-error file-error
+    signal-program-error signal-simple-program-error
+    print-call-history
+    #-bccl %get-frame-pointer
+    #-bccl break-loop)
+  "List of functions which never return multiple values and
+   should never be tail-called.")
+
+(defvar *cross-compiling* nil "bootstrapping")
+
+
+(defparameter *nx-operator-result-types*
+  '((#.(%nx1-operator list) . list)
+    (#.(%nx1-operator memq) . list)
+    (#.(%nx1-operator %temp-list) . list)
+    (#.(%nx1-operator assq) . list)
+    (#.(%nx1-operator cons) . cons)
+    (#.(%nx1-operator rplaca) . cons)
+    (#.(%nx1-operator %rplaca) . cons)
+    (#.(%nx1-operator rplacd) . cons)
+    (#.(%nx1-operator %rplacd) . cons)
+    (#.(%nx1-operator %temp-cons) . cons)
+    (#.(%nx1-operator %i+) . fixnum)
+    (#.(%nx1-operator %i-) . fixnum)
+    (#.(%nx1-operator %i*) . fixnum)
+    (#.(%nx1-operator %ilsl) . fixnum)
+    (#.(%nx1-operator %ilsr) . fixnum)
+    (#.(%nx1-operator %iasr) . fixnum)
+    (#.(%nx1-operator %ilogior2) . fixnum)
+    (#.(%nx1-operator %ilogand2) . fixnum)
+    (#.(%nx1-operator %ilogxor2) . fixnum)
+    (#.(%nx1-operator %code-char) . character)
+    (#.(%nx1-operator schar) . character)
+    (#.(%nx1-operator length) . fixnum)
+    (#.(%nx1-operator uvsize) . fixnum)
+    (#.(%nx1-operator %double-float/-2) . double-float)
+    (#.(%nx1-operator %double-float/-2!) . double-float) ; no such operator
+    (#.(%nx1-operator %double-float+-2) . double-float)
+    (#.(%nx1-operator %double-float+-2!) . double-float)
+    (#.(%nx1-operator %double-float--2) . double-float)
+    (#.(%nx1-operator %double-float--2!) . double-float)
+    (#.(%nx1-operator %double-float*-2) . double-float)
+    (#.(%nx1-operator %double-float*-2!) . double-float)
+    (#.(%nx1-operator %short-float/-2) . double-float)
+    (#.(%nx1-operator %short-float+-2) . double-float)
+    (#.(%nx1-operator %short-float--2) . double-float)
+    (#.(%nx1-operator %short-float*-2) . double-float)
+    (#.(%nx1-operator %double-to-single) . single-float)
+    (#.(%nx1-operator %single-to-double) . double-float)
+    (#.(%nx1-operator %fixnum-to-single) . single-float)
+    (#.(%nx1-operator %fixnum-to-double) . double-float)
+    (#.(%nx1-operator char-code) . #.`(integer 0 (,char-code-limit)))
+   ))
+
+(defparameter *nx-operator-result-types-by-name*
+  '((%ilognot . fixnum)
+    (%ilogxor . fixnum)
+    (%ilogand . fixnum)
+    (%ilogior . fixnum)
+    (char-code . #. `(integer 0 (,char-code-limit)))))
+
+(setq *nx-known-declarations*
+  '(special inline notinline type ftype function ignore optimize dynamic-extent ignorable
+    ignore-if-unused settable unsettable
+     notspecial global-function-name debugging-function-name resident))
+
+(defun find-optimize-quantity (name env)
+  (let ((pair ()))
+    (loop
+      (when (listp env) (return))
+      (when (setq pair (assq name (lexenv.mdecls env)))
+        (return (%cdr pair)))
+      (setq env (lexenv.parent-env env)))))
+    
+(defun debug-optimize-quantity (env)
+  (or (find-optimize-quantity 'debug env)
+      *nx-debug*))
+
+(defun space-optimize-quantity (env)
+  (or (find-optimize-quantity 'space env)
+      *nx-space*))
+
+(defun safety-optimize-quantity (env)
+  (or (find-optimize-quantity 'safety env)
+      *nx-safety*))
+
+(defun speed-optimize-quantity (env)
+  (or (find-optimize-quantity 'speed env)
+      *nx-speed*))
+
+(defun compilation-speed-optimize-quantity (env)
+  (or (find-optimize-quantity 'compilation-speed env)
+      *nx-cspeed*))
+
+(defvar *nx-ignore-if-unused* ())
+(defvar *nx-new-p2decls* ())
+(defvar *nx-inlined-self* t)
+(defvar *nx-all-vars* nil)
+(defvar *nx-bound-vars* nil)
+(defvar *nx-punted-vars* nil)
+(defvar *nx-inline-expansions* nil)
+(defparameter *nx-compile-time-compiler-macros* nil)
+(defvar *nx-global-function-name* nil)
+(defvar *nx-can-constant-fold* ())
+(defvar *nx-synonyms* ())
+(defvar *nx-load-time-eval-token* ())
+
+(define-condition compiler-function-overflow (condition) ())
+
+(defun compiler-function-overflow ()
+  (signal 'compiler-function-overflow)
+  (error "Function size exceeds compiler limitation."))
+
+(defvar *compiler-macros* (make-hash-table :size 100 :test #'eq))
+
+;;; Just who was responsible for the "FUNCALL" nonsense ?
+;;; Whoever it is deserves a slow and painful death ...
+
+(defmacro define-compiler-macro  (name arglist &body body &environment env)
+  "Define a compiler-macro for NAME."
+  (let* ((block-name name)
+         (def-name (validate-function-name name)))
+    (unless (eq def-name block-name)
+      (setq block-name (cadr block-name)))
+    (let ((body (parse-macro-1 block-name arglist body env)))
+      `(eval-when (:compile-toplevel :load-toplevel :execute)
+         (eval-when (:load-toplevel :execute)
+           (record-source-file ',name 'compiler-macro))
+         (setf (compiler-macro-function ',name)
+               (nfunction (compiler-macro-function ,name)  ,body))
+         ',name))))
+
+;;; This is silly (as may be the whole idea of actually -using-
+;;; compiler-macros).  Compiler-macroexpand-1 will return a second
+;;; value of NIL if the value returned by the expansion function is EQ
+;;; to the original form.  This differs from the behavior of
+;;; macroexpand-1, but users are not encouraged to write macros which
+;;; return their &whole args (as the DEFINE-COMPILER-MACRO issue
+;;; encourages them to do ...)  Cheer up! Neither of these things have
+;;; to exist!
+(defun compiler-macroexpand-1 (form &optional env)
+  (let ((expander nil)
+        (newdef nil))
+    (if (and (consp form)
+             (symbolp (car form))
+             (setq expander (compiler-macro-function (car form) env)))
+      (values (setq newdef (funcall *macroexpand-hook* expander form env)) (neq newdef form))
+      (values form nil))))
+
+; ... If this exists, it should probably be exported.
+(defun compiler-macroexpand (form &optional env)
+  (multiple-value-bind (new win) (compiler-macroexpand-1 form env)
+    (do* ((won-at-least-once win))
+         ((null win) (values new won-at-least-once))
+      (multiple-value-setq (new win) (compiler-macroexpand-1 new env)))))
+
+
+
+
+(defun compiler-macro-function (name &optional env)
+  "If NAME names a compiler-macro in ENV, return the expansion function, else
+   return NIL. Can be set with SETF when ENV is NIL."
+  (setq name (validate-function-name name))
+  (unless (nx-lexical-finfo name env)
+    (or (cdr (assq name *nx-compile-time-compiler-macros*))
+        (values (gethash name *compiler-macros*)))))
+
+(defun set-compiler-macro-function (name def)
+  (setq name (validate-function-name name))
+  (if def
+    (setf (gethash name *compiler-macros*) def)
+    (remhash name *compiler-macros*))
+  def)
+
+(defsetf compiler-macro-function set-compiler-macro-function)
+
+(defparameter *nx-add-xref-entry-hook* nil
+  "When non-NIL, assumed to be a function of 3 arguments 
+which asserts that the specied relation from the current
+function to the indicated name is true.")
+
+;; Cross-referencing
+(defun nx-record-xref-info (relation name)
+  (let* ((axe (fboundp '%add-xref-entry)))
+    (when axe
+      (funcall axe relation *nx-cur-func-name* name))))
+
+
+
+(defun nx-apply-env-hook (hook env &rest args)
+  (declare (dynamic-extent args))
+  (when (fixnump hook) (setq hook (uvref *nx-current-compiler-policy* hook)))
+  (if hook
+    (if (functionp hook)
+      (apply hook env args)
+      t)))
+
+(defun nx-self-calls-inlineable (env)
+  (nx-apply-env-hook policy.inline-self-calls env))
+
+(defun nx-allow-register-allocation (env)
+  (not (nx-apply-env-hook policy.inhibit-register-allocation env)))
+
+(defun nx-trust-declarations (env)
+  (unless (eq (safety-optimize-quantity env) 3)
+    (nx-apply-env-hook policy.trust-declarations env)))
+
+(defun nx-open-code-in-line (env)
+  (nx-apply-env-hook policy.open-code-inline env))
+
+(defun nx-inline-car-cdr (env)
+  (unless (eq (safety-optimize-quantity env) 3)
+    (nx-apply-env-hook policy.inhibit-safety-checking env)))
+
+(defun nx-inhibit-safety-checking (env)
+  (unless (eq (safety-optimize-quantity env) 3)
+    (nx-apply-env-hook policy.inhibit-safety-checking env)))
+
+(defun nx-tailcalls (env)
+  (nx-apply-env-hook policy.allow-tail-recursion-elimination env))
+
+(defun nx-allow-transforms (env)
+  (nx-apply-env-hook policy.allow-transforms env))
+
+(defun nx-force-boundp-checks (var env)
+  (or (eq (safety-optimize-quantity env) 3)
+      (nx-apply-env-hook policy.force-boundp-checks var env)))
+
+(defun nx-substititute-constant-value (symbol value env)
+  (nx-apply-env-hook policy.allow-constant-substitution symbol value env))
+
+(defun nx-declarations-typecheck (env)
+  (nx-apply-env-hook policy.declarations-typecheck env))
+
+
+#-bccl
+(defun nx1-default-operator ()
+ (or (gethash *nx-sfname* *nx1-operators*)
+     (error "Bug - operator not found for  ~S" *nx-sfname*)))
+
+(defun nx-new-temp-var (pending &optional (pname "COMPILER-VAR"))
+  (let ((var (nx-new-var pending (make-symbol pname))))
+    (nx-set-var-bits var (%ilogior (%ilsl $vbitignoreunused 1)
+                                   (%ilsl $vbittemporary 1)
+                                   (nx-var-bits var)))
+    var))
+
+(defun nx-new-vdecl (pending name class &optional info)
+  (push (cons name (cons class info)) (pending-declarations-vdecls pending)))
+
+(defun nx-new-fdecl (pending name class &optional info)
+  (push (cons name (cons class info)) (pending-declarations-fdecls pending)))
+
+(defun nx-new-var (pending sym &optional (check t))
+  (nx-init-var pending (nx-cons-var (nx-need-var sym check) 0)))
+                    
+(defun nx-proclaimed-special-p (sym)
+  (setq sym (nx-need-sym sym))
+  (let* ((defenv (definition-environment *nx-lexical-environment*))
+         (specials (if defenv (defenv.specials defenv))))
+    (or (assq sym specials)
+        (proclaimed-special-p sym))))
+
+(defun nx-proclaimed-parameter-p (sym)
+  (setq sym (nx-need-sym sym))
+  (or (constantp sym)
+      (multiple-value-bind (special-p info) (nx-lex-info sym t)
+        (or 
+         (and (eq special-p :special) info)
+         (let* ((defenv (definition-environment *nx-lexical-environment*)))
+           (if defenv 
+             (or (%cdr (assq sym (defenv.specials defenv)))
+                 (assq sym (defenv.constants defenv)))))))))
+
+(defun nx-process-declarations (pending decls &optional (env *nx-lexical-environment*) &aux s f)
+  (dolist (decl decls pending)
+    (dolist (spec (%cdr decl))
+      (if (memq (setq s (car spec)) *nx-known-declarations*)
+        (if (setq f (getf *nx-standard-declaration-handlers* s))
+          (funcall f pending spec env))
+        ; Any type name is now (ANSI CL) a valid declaration.
+        (if (specifier-type-if-known s env)
+          (nx-process-type-decl pending spec s (%cdr spec) env)
+          (nx-bad-decls spec))))))
+
+; Put all variable decls for the symbol VAR into effect in environment ENV.  Now.
+; Returns list of all new vdecls pertaining to VAR.
+(defun nx-effect-vdecls (pending var env)
+  (let ((vdecls (lexenv.vdecls env))
+        (own nil))
+    (dolist (decl (pending-declarations-vdecls pending) (setf (lexenv.vdecls env) vdecls))
+      (when (eq (car decl) var) 
+        (when (eq (cadr decl) 'type)
+          (let* ((newtype (cddr decl))
+                 (merged-type (nx1-type-intersect var newtype (nx-declared-type var env))))
+             (unless (eq merged-type newtype)
+              (rplacd (cdr decl) merged-type))))
+        (push decl vdecls)
+        (push (cdr decl) own)))
+    own))
+
+
+(defun nx1-typed-var-initform (pending sym form &optional (env *nx-lexical-environment*))
+  (let* ((type t)
+         (*nx-form-type* (if (nx-trust-declarations env)
+                           (dolist (decl (pending-declarations-vdecls pending) type)
+                             (when (and (eq (car decl) sym) (eq (cadr decl) 'type))
+                               (setq type (nx1-type-intersect sym (nx-target-type type) (cddr decl)))))
+                           t)))
+    (nx1-typed-form form env)))
+
+; Guess.
+(defun nx-effect-fdecls (pending var env)
+  (let ((fdecls (lexenv.fdecls env))
+        (own nil))
+    (dolist (decl (pending-declarations-fdecls pending) (setf (lexenv.fdecls env) fdecls))
+      (when (eq (car decl) var) 
+        (push decl fdecls)
+        (push (cdr decl) own)))
+    own))
+
+
+
+
+(defun nx-acode-form-typep (form type env)
+  (acode-form-typep form type  (nx-trust-declarations env)))
+
+(defun acode-form-typep (form type trust-decls)
+  (if (acode-p form)
+    (let* ((op (acode-operator form))
+           (opval-p (or (eq op (%nx1-operator fixnum)) (eq op (%nx1-operator immediate))))
+           (optype (acode-form-type form trust-decls)))
+      (values
+       (if optype 
+         (subtypep optype (nx-target-type type))
+         (if opval-p (typep (%cadr form) (nx-target-type type))))))))
+
+(defun nx-acode-form-type (form env)
+  (acode-form-type form (nx-trust-declarations env)))
+
+(defparameter *numeric-acode-ops*
+  (list (%nx1-operator add2)
+        (%nx1-operator sub2)
+        (%nx1-operator mul2)))
+
+
+
+(defun acode-form-type (form trust-decls &optional (assert t))
+  (let* ((typespec
+          (if (nx-null form)
+            'null
+            (if (eq form *nx-t*)
+              'boolean
+              (nx-target-type 
+               (if (acode-p form)
+                 (let* ((op (acode-operator form)))
+                   (if (eq op (%nx1-operator fixnum))
+                     'fixnum
+                     (if (eq op (%nx1-operator immediate))
+                       (type-of (%cadr form))
+                       (and trust-decls
+                            (if (eq op (%nx1-operator type-asserted-form))
+                              (progn
+                                (setq assert nil)
+                                (%cadr form))
+                              (if (eq op (%nx1-operator typed-form))
+                                (progn
+                                  (when (and assert (null (nth 3 form)))
+                                    (setf (%car form) (%nx1-operator type-asserted-form)
+                                          assert nil))
+                                  (if (eq (%cadr form) 'number)
+                                    (or (acode-form-type (nx-untyped-form form) trust-decls)
+                                        'number)
+                                    (%cadr form)))
+                                (if (eq op (%nx1-operator lexical-reference))
+                                  (locally (declare (special *nx-in-frontend*))
+                                    (unless *nx-in-frontend*
+                                      (let* ((var (cadr form))
+                                             (bits (nx-var-bits var))
+                                             (punted (logbitp $vbitpunted bits)))
+                                        (if (or punted
+                                                (eql 0 (%ilogand $vsetqmask bits)))
+                                          (var-inittype var)))))
+                                  (if (or (eq op (%nx1-operator %aref1))
+                                          (eq op (%nx1-operator simple-typed-aref2))
+                                          (eq op (%nx1-operator general-aref2))
+                                          (eq op (%nx1-operator simple-typed-aref3))
+                                          (eq op (%nx1-operator general-aref3)))
+                                    (let* ((atype (acode-form-type (cadr form) t))
+                                           (actype (if atype (specifier-type atype))))
+                                      (if (typep actype 'array-ctype)
+                                        (type-specifier (array-ctype-specialized-element-type
+                                                         actype))))
+                                    (if (member op *numeric-acode-ops*)
+                                      (multiple-value-bind (f1 f2)
+                                          (nx-binop-numeric-contagion (cadr form)
+                                                                      (caddr form)
+                                                                      trust-decls)
+                                        (if (and (acode-form-typep f1 'float trust-decls)
+                                                 (acode-form-typep f2 'float trust-decls))
+
+                                          (if (or (acode-form-typep f1 'double-float trust-decls)
+                                                  (acode-form-typep f2 'double-float trust-decls))
+                                            'double-float
+                                            'single-float)))
+                                      (cdr (assq op *nx-operator-result-types*)))))))))))))))))
+    (when (and (acode-p form) (typep (acode-operator form) 'fixnum) assert)
+      (unless typespec (setq typespec t))
+      (let* ((new (cons typespec (cons (cons (%car form) (%cdr form)) nil))))
+        (setf (%car form) (%nx1-operator type-asserted-form)
+              (%cdr form) new)))
+    typespec))
+
+(defun nx-binop-numeric-contagion (form1 form2 trust-decls)
+  (cond ((acode-form-typep form1 'double-float trust-decls)
+         (if (acode-form-typep form2 'double-float trust-decls)
+           (values form1 form2)
+           (let* ((c2 (acode-real-constant-p form2)))
+             (if c2
+               (values form1 (make-acode (%nx1-operator immediate)
+                                         (float c2 0.0d0)))
+               (if (acode-form-typep form2 'fixnum trust-decls)
+                 (values form1 (make-acode (%nx1-operator %fixnum-to-double)
+                                           form2))
+                 (values form1 form2))))))
+        ((acode-form-typep form2 'double-float trust-decls)
+         (let* ((c1 (acode-real-constant-p form1)))
+           (if c1
+             (values (make-acode (%nx1-operator immediate)
+                                 (float c1 0.0d0)) form2)
+             (if (acode-form-typep form1 'fixnum trust-decls)
+               (values (make-acode (%nx1-operator %fixnum-to-double)
+                                   form1) form2)
+               (values form1 form2)))))
+        ((acode-form-typep form1 'single-float trust-decls)
+         (if (acode-form-typep form2 'single-float trust-decls)
+           (values form1 form2)
+           (let* ((c2 (acode-real-constant-p form2)))
+             (if c2
+               (values form1 (make-acode (%nx1-operator immediate)
+                                         (float c2 0.0f0)))
+               (if (acode-form-typep form2 'fixnum trust-decls)
+                 (values form1 (make-acode (%nx1-operator %fixnum-to-single)
+                                           form2))
+                 (values form1 form2))))))
+        ((acode-form-typep form2 'single-float trust-decls)
+         (let* ((c1 (acode-real-constant-p form1)))
+           (if c1
+             (values (make-acode (%nx1-operator immediate)
+                                 (float c1 0.0f0)) form2)
+             (if (acode-form-typep form1 'fixnum trust-decls)
+               (values (make-acode (%nx1-operator %fixnum-to-single)
+                                   form1) form2)
+               (values form1 form2)))))
+        (t
+         (values form1 form2))))
+
+(defun acode-punted-var-p (var)
+  (let ((bits (nx-var-bits var)))
+    (and (%ilogbitp $vbitpunted bits)
+         (not (%ilogbitp $vbitspecial bits)))))
+
+;; Use acode-unwrapped-form-value to reason about the value of a form at
+;; compile time.   To actually generate code, use acode-unwrapped-form.
+(defun acode-unwrapped-form-value (form)
+  ;; Currently no difference, but if had any operators like with-code-note,
+  ;; would unwrap them here.
+  (acode-unwrapped-form form))
+
+; Strip off any type info or "punted" lexical references.
+; ??? Is it true that the "value" of the punted reference is unwrapped ? ???
+(defun acode-unwrapped-form (form) 
+  (while (and (consp (setq form (nx-untyped-form form)))
+           (eq (%car form) (%nx1-operator lexical-reference))
+           (acode-punted-var-p (cadr form)))
+    (setq form (var-ea (cadr form))))
+  form)
+
+(defun acode-fixnum-form-p (x)
+  (setq x (acode-unwrapped-form-value x))
+  (if (acode-p x)
+    (if (eq (acode-operator x) (%nx1-operator fixnum)) 
+      (cadr x))))
+
+(defun acode-integer-constant-p (x bits)
+  (let* ((int (or (acode-fixnum-form-p x)
+                  (progn
+                    (setq x (acode-unwrapped-form x))
+                    (if (acode-p x)
+                      (if (and (eq (acode-operator x) (%nx1-operator immediate))
+                               (typep (cadr x) 'fixnum))
+                        (cadr x)))))))
+    (and int
+         (or
+           (typep int `(signed-byte ,bits))
+           (typep int `(unsigned-byte ,bits)))
+         int)))
+
+(defun acode-real-constant-p (x)
+  (or (acode-fixnum-form-p x)
+      (progn
+        (setq x (acode-unwrapped-form x))
+        (if (acode-p x)
+          (if (and (eq (acode-operator x) (%nx1-operator immediate))
+                   (typep (cadr x) 'real))
+            (cadr x))))))
+
+
+
+(defun nx-lookup-target-uvector-subtag (name)
+  (or (cdr (assoc name (arch::target-uvector-subtags (backend-target-arch *target-backend*))))
+      (nx-error "Type ~s not supported on target ~s"
+                name (backend-target-arch-name *target-backend*))))
+
+(defun nx-target-uvector-subtag-name (subtag)
+  (or (car (rassoc subtag (arch::target-uvector-subtags (backend-target-arch *target-backend*))))
+      (nx-error "Subtag ~s not native on target ~s"
+                subtag (backend-target-arch-name *target-backend*))))
+
+(defun nx-error-for-simple-2d-array-type (type-keyword)
+  (ecase type-keyword
+    (:simple-vector arch::error-object-not-simple-array-t-2d)
+    (:simple-string arch::error-object-not-simple-array-char-2d)
+    (:bit-vector arch::error-object-not-simple-array-bit-2d)
+    (:unsigned-8-bit-vector arch::error-object-not-simple-array-u8-2d)
+    (:signed-8-bit-vector arch::error-object-not-simple-array-s8-2d)
+    (:unsigned-16-bit-vector arch::error-object-not-simple-array-u16-2d)
+    (:signed-16-bit-vector arch::error-object-not-simple-array-s16-2d)
+    (:unsigned-32-bit-vector arch::error-object-not-simple-array-u32-2d)
+    (:signed-32-bit-vector arch::error-object-not-simple-array-s32-2d)
+    (:unsigned-64-bit-vector arch::error-object-not-simple-array-u64-2d)
+    (:signed-64-bit-vector arch::error-object-not-simple-array-s64-2d)
+    (:double-float-vector arch::error-object-not-simple-array-double-float-2d)
+    (:single-float-vector arch::error-object-not-simple-array-single-float-2d)
+    (:fixnum-vector arch::error-object-not-simple-array-fixnum-2d)))
+
+(defun nx-error-for-simple-3d-array-type (type-keyword)
+  (ecase type-keyword
+    (:simple-vector arch::error-object-not-simple-array-t-3d)
+    (:simple-string arch::error-object-not-simple-array-char-3d)
+    (:bit-vector arch::error-object-not-simple-array-bit-3d)
+    (:unsigned-8-bit-vector arch::error-object-not-simple-array-u8-3d)
+    (:signed-8-bit-vector arch::error-object-not-simple-array-s8-3d)
+    (:unsigned-16-bit-vector arch::error-object-not-simple-array-u16-3d)
+    (:signed-16-bit-vector arch::error-object-not-simple-array-s16-3d)
+    (:unsigned-32-bit-vector arch::error-object-not-simple-array-u32-3d)
+    (:signed-32-bit-vector arch::error-object-not-simple-array-s32-3d)
+    (:unsigned-64-bit-vector arch::error-object-not-simple-array-u64-3d)
+    (:signed-64-bit-vector arch::error-object-not-simple-array-s64-3d)
+    (:double-float-vector arch::error-object-not-simple-array-double-float-3d)
+    (:single-float-vector arch::error-object-not-simple-array-single-float-3d)
+    (:fixnum-vector arch::error-object-not-simple-array-fixnum-3d)))
+
+(defun acode-s16-constant-p (x)
+  (setq x (acode-unwrapped-form x))
+  (if (acode-p x)
+    (let* ((op (acode-operator x)))
+      (if (eql op (%nx1-operator fixnum))
+        (let* ((val (cadr x)))
+          (if (target-word-size-case
+               (32 (typep val '(signed-byte #.(- 16 2))))
+               (64 (typep val '(signed-byte #.(- 16 3)))))
+            (ash val (target-word-size-case
+                      (32 2)
+                      (64 3)))))
+        (if (eql op (%nx1-operator %unbound-marker))
+          (arch::target-unbound-marker-value
+           (backend-target-arch *target-backend*))
+          (if (eql op (%nx1-operator %slot-unbound-marker))
+            (arch::target-slot-unbound-marker-value
+             (backend-target-arch *target-backend*))))))))
+
+(defun acode-s32-constant-p (x)
+  (setq x (acode-unwrapped-form x))
+  (if (acode-p x)
+    (let* ((op (acode-operator x)))
+      (if (eql op (%nx1-operator fixnum))
+        (let* ((val (cadr x)))
+          (if (target-word-size-case
+               (32 (typep val '(signed-byte #.(- 32 2))))
+               (64 (typep val '(signed-byte #.(- 32 3)))))
+            (ash val (target-word-size-case
+                      (32 2)
+                      (64 3)))))
+        (if (eql op (%nx1-operator %unbound-marker))
+          (arch::target-unbound-marker-value
+           (backend-target-arch *target-backend*))
+          (if (eql op (%nx1-operator %slot-unbound-marker))
+            (arch::target-slot-unbound-marker-value
+             (backend-target-arch *target-backend*))))))))
+
+(defun acode-fixnum-type-p (form trust-decls)
+  (or (acode-fixnum-form-p form)
+      (and trust-decls
+           (acode-p form)
+           (eq (acode-operator form) (%nx1-operator typed-form))
+           (subtypep (cadr form) 'fixnum))))
+
+
+(defun nx-acode-fixnum-type-p (form env)
+    (acode-fixnum-type-p form (nx-trust-declarations env)))
+
+; Is acode-expression the result of alphatizing (%int-to-ptr <integer>) ?
+(defun acode-absolute-ptr-p (acode-expression &optional skip)
+  (and (acode-p acode-expression)
+       (or skip (prog1 (eq (acode-operator acode-expression) (%nx1-operator %macptrptr%))
+                  (setq acode-expression (%cadr acode-expression))))
+       (eq (acode-operator acode-expression) (%nx1-operator %consmacptr%))
+       (eq (acode-operator (setq acode-expression (%cadr acode-expression))) 
+           (%nx1-operator %immediate-int-to-ptr))
+       (let ((op (acode-operator (setq acode-expression (%cadr acode-expression)))))
+         (if (or (eq op (%nx1-operator fixnum))
+                 (and (eq op (%nx1-operator immediate))
+                      (integerp (%cadr acode-expression))))
+           (%cadr acode-expression)))))
+
+(defun specifier-type-if-known (typespec &optional env &key whine values)
+  (handler-case (if values (values-specifier-type typespec env) (specifier-type typespec env))
+    (parse-unknown-type (c) 
+      (when (and whine *compiler-warn-on-undefined-type-references*)
+	(nx1-whine :undefined-type typespec))
+      (values nil (parse-unknown-type-specifier c)))
+    ;; catch any errors due to destructuring in type-expand
+    (program-error (c)
+      (when whine
+	(nx1-whine :invalid-type typespec c))
+      (values nil typespec))))
+
+#+debugging-version
+(defun specifier-type-if-known (typespec &optional env &key whine)
+  (handler-bind ((parse-unknown-type (lambda (c)
+                                       (break "caught unknown-type ~s" c)
+				       (when (and whine *compiler-warn-on-undefined-type-references*)
+					 (nx1-whine :undefined-type typespec))
+                                       (return-from specifier-type-if-known
+                                         (values nil (parse-unknown-type-specifier c)))))
+		 (program-error (lambda (c)
+				  (break "caught program-error ~s" c)
+				  (when whine
+				    (nx1-whine :invalid-type typespec c))
+				  (return-from specifier-type-if-known
+				    (values nil typespec)))))
+    (specifier-type typespec env)))
+
+(defun nx-check-vdecl-var-ref (decl)
+  (unless (eq (cadr decl) 'special)
+    (let* ((sym (car decl))
+           (info (nx-lex-info sym)))
+      (when (or (eq info :symbol-macro)
+                (and (null info) (not (nx-proclaimed-special-p sym))))
+        (nx1-whine :unknown-declaration-variable (cadr decl) sym)))))
+
+(defun nx-check-fdecl-var-ref (decl env &aux (sym (car decl)))
+  (unless (eq (cadr decl) 'ftype)
+    ;; Complain about forward references, since need a def to use the declaration.
+    ;; Perhaps should complain if regular macro, but don't for now.  Compiler macros
+    ;; specifically allowed by spec for inline decls
+    (unless (or (nx-lexical-finfo sym env)
+                (fboundp sym)
+                (retrieve-environment-function-info sym env)
+                (gethash sym *nx1-alphatizers*)
+                (assq sym *nx-compile-time-compiler-macros*)
+                (gethash sym *compiler-macros*)
+                (eq sym *nx-global-function-name*))
+      (nx1-whine :unknown-declaration-function (cadr decl) sym))))
+
+
+(defun nx-effect-other-decls (pending env)
+  (flet ((merge-decls (new old)
+                      (dolist (decl new old) (pushnew decl old :test #'eq))))
+    (let ((vdecls (pending-declarations-vdecls pending))
+          (fdecls (pending-declarations-fdecls pending))
+          (mdecls (pending-declarations-mdecls pending)))
+      (when vdecls
+        (let ((env-vdecls (lexenv.vdecls env)))
+          (dolist (decl vdecls (setf (lexenv.vdecls env) env-vdecls))
+            (unless (memq decl env-vdecls)
+              (nx-check-vdecl-var-ref decl)
+              (when (eq (cadr decl) 'type)
+                (let* ((var (car decl))
+                       (newtype (cddr decl))
+                       (merged-type (nx1-type-intersect var newtype (nx-declared-type var env))))
+                  (unless (eq merged-type newtype)
+                    (rplacd (cdr decl) merged-type))))
+              (push decl env-vdecls)))))
+      (when fdecls
+        (let ((env-fdecls (lexenv.fdecls env)))
+          (dolist (decl fdecls (setf (lexenv.fdecls env) env-fdecls))
+            (unless (memq decl env-fdecls)
+              (nx-check-fdecl-var-ref decl env)
+              (push decl env-fdecls)))))
+      (when mdecls (setf (lexenv.mdecls env) (merge-decls mdecls (lexenv.mdecls env))))
+      (setq *nx-inlined-self* (and (nx-self-calls-inlineable env) 
+                                   (let ((name *nx-global-function-name*)) 
+                                     (and name (not (nx-declared-notinline-p name env))))))
+      (unless (nx-allow-register-allocation env)
+        (nx-inhibit-register-allocation))
+      (setq *nx-new-p2decls*
+            (if (eql (safety-optimize-quantity env) 3)
+              (logior $decl_full_safety
+                      (if (nx-tailcalls env) $decl_tailcalls 0))
+              (%ilogior
+                (if (nx-tailcalls env) $decl_tailcalls 0)
+                (if (nx-open-code-in-line env) $decl_opencodeinline 0)
+                (if (nx-inhibit-safety-checking env) $decl_unsafe 0)
+                (if (nx-trust-declarations env) $decl_trustdecls 0)))))))
+
+#|     
+(defun nx-find-misc-decl (declname env)
+  (loop
+    (unless (and env (eq (uvref env 0) 'lexical-environment)) (return))
+    (dolist (mdecl (lexenv.mdecls env))
+      (if (atom mdecl)
+        (if (eq mdecl declname)
+          (return-from nx-find-misc-decl t))
+        (if (eq (%car mdecl) declname)
+          (return-from nx-find-misc-decl (%cdr mdecl)))))
+    (setq env (lexenv.parent-env env))))
+|#
+
+
+(defun nx-bad-decls (decls)
+  (nx1-whine :bad-declaration decls))
+
+
+(defnxdecl special (pending decl env &aux whined)
+  (declare (ignore env))
+  (dolist (s (%cdr decl))
+    (if (symbolp s) 
+      (nx-new-vdecl pending s 'special)
+      (unless (shiftf whined t) (nx-bad-decls decl)))))
+
+(defnxdecl notspecial (pending decl env &aux whined)
+  (declare (ignore env))
+  (dolist (s (%cdr decl))
+    (if (symbolp s)
+      (nx-new-vdecl pending s 'notspecial)
+      (unless (shiftf whined t) (nx-bad-decls decl)))))
+
+(defnxdecl dynamic-extent (pending decl env &aux whined)
+  (declare (ignore env))
+  (dolist (s (%cdr decl))
+    (if (symbolp s) 
+      (nx-new-vdecl pending s 'dynamic-extent t)
+      (if (and (consp s)
+               (eq (%car s) 'function)
+               (consp (%cdr s))
+               (valid-function-name-p (cadr s))
+               (setq s (validate-function-name (cadr s))))
+        (nx-new-fdecl pending s 'dynamic-extent t)
+	(unless (shiftf whined t) (nx-bad-decls decl))))))
+
+(defnxdecl ignorable (pending decl env &aux whined)
+  (declare (ignore env))
+  (dolist (s (%cdr decl))
+    (if (symbolp s) 
+      (nx-new-vdecl pending s 'ignorable)
+      (if (and (consp s)
+               (eq (%car s) 'function)
+               (consp (%cdr s))
+               (valid-function-name-p (cadr s))
+               (setq s (validate-function-name (cadr s))))
+        (nx-new-fdecl pending s 'ignorable)
+	(unless (shiftf whined t) (nx-bad-decls decl))))))
+
+(defnxdecl ftype (pending decl env &aux whined)
+  (destructuring-bind (type &rest fnames) (%cdr decl)
+    (let ((ctype (specifier-type-if-known type env)))
+      (if (null ctype)
+	(nx1-whine :unknown-type-in-declaration type)
+	(if (types-disjoint-p ctype (specifier-type 'function))
+	  (nx-bad-decls decl)
+	  (dolist (s fnames)
+	    (if (or (symbolp s) (setf-function-name-p s))
+	      (nx-new-fdecl pending s 'ftype type)
+	      (unless (shiftf whined t) (nx-bad-decls decl)))))))))
+
+(defnxdecl settable (pending decl env)
+  (nx-settable-decls pending decl env t))
+
+(defnxdecl unsettable (pending decl env)
+  (nx-settable-decls pending decl env nil))
+
+(defun nx-settable-decls (pending decl env val &aux whined)
+  (declare (ignore env))
+  (dolist (s (%cdr decl))
+    (if (symbolp s)
+      (nx-new-vdecl pending s 'settable val)
+      (unless (shiftf whined t) (nx-bad-decls decl)))))
+
+(defnxdecl function (pending decl env)
+  (nx-process-type-decl pending decl (car decl) (cdr decl) env))
+
+(defnxdecl type (pending decl env)
+  (nx-process-type-decl pending decl (cadr decl) (cddr decl) env))
+
+(defun nx-process-type-decl (pending decl type vars env &aux whined)
+  (if (specifier-type-if-known type env)
+    (dolist (sym vars)
+      (if (symbolp sym)
+	(nx-new-vdecl pending sym 'type type)
+	(unless (shiftf whined t) (nx-bad-decls decl))))
+    (nx1-whine :unknown-type-in-declaration type)))
+
+(defnxdecl global-function-name (pending decl env)
+  (declare (ignore pending))
+  (when *nx-parsing-lambda-decls*
+    (let ((name (cadr decl)))
+      (setq *nx-global-function-name* (setf (afunc-name *nx-current-function*) name))
+      (setq *nx-inlined-self* (not (nx-declared-notinline-p name env))))))
+
+(defnxdecl debugging-function-name (pending decl env)
+  (declare (ignore pending env))
+  (when *nx-parsing-lambda-decls*
+    (setf (afunc-name *nx-current-function*) (cadr decl))))
+
+(defnxdecl resident (pending decl env)
+  (declare (ignore env pending))
+  (declare (ignore decl))
+  (nx-decl-set-fbit $fbitresident))
+
+
+(defun nx-inline-decl (pending decl val &aux valid-name whined)
+  (dolist (s (%cdr decl))
+    (multiple-value-setq (valid-name s) (valid-function-name-p s))
+    (if valid-name
+      (progn
+        (if (nx-self-call-p s nil t)
+          (setq *nx-inlined-self* val))
+        (nx-new-fdecl pending s 'inline (if val 'inline 'notinline)))
+      (unless (shiftf whined t) (nx-bad-decls decl)))))
+
+(defnxdecl inline (pending decl env)
+  (declare (ignore env))
+  (nx-inline-decl pending decl t))
+
+(defnxdecl notinline (pending decl env)
+  (declare (ignore env))
+  (nx-inline-decl pending decl nil))
+
+(defnxdecl ignore (pending decl env &aux whined)
+  (declare (ignore env))
+  (dolist (s (%cdr decl))
+    (if (symbolp s)      
+      (nx-new-vdecl pending s 'ignore t)
+      (if (and (consp s)
+               (eq (%car s) 'function)
+               (consp (%cdr s))
+               (valid-function-name-p (cadr s))
+               (setq s (validate-function-name (cadr s))))
+        (nx-new-fdecl pending s 'ignore t)
+        (unless (shiftf whined t) (nx-bad-decls decl))))))
+
+(defnxdecl ignore-if-unused (pending decl env &aux whined)
+  (declare (ignore env))
+  (dolist (s (%cdr decl))
+    (if (symbolp s) 
+      (nx-new-vdecl pending s 'ignore-if-unused)
+      (unless (shiftf whined t) (nx-bad-decls decl)))))
+
+(defun nx-self-call-p (name &optional ignore-lexical (allow *nx-inlined-self*))
+  (when (and name (symbolp name))
+    (let ((current-afunc *nx-current-function*)
+          (target-afunc (unless ignore-lexical (nth-value 1 (nx-lexical-finfo name)))))
+      (or (eq current-afunc target-afunc)
+          (and allow
+               (eq name *nx-global-function-name*)
+               (null target-afunc)
+               (null (afunc-parent current-afunc)))))))
+
+(defun nx-check-var-usage (var)
+  (let* ((sym (var-name var))
+         (bits (nx-var-bits var))
+         (expansion (var-ea var))
+         (setqed (%ilogbitp $vbitsetq bits))
+         (reffed (%ilogbitp $vbitreffed bits))
+         (closed (%ilogbitp $vbitclosed bits))
+         (special (%ilogbitp $vbitspecial bits))
+         (ignored (%ilogbitp $vbitignore bits))
+         (ignoreunused (%ilogbitp $vbitignoreunused bits)))
+    (if (or special reffed closed)
+      (progn
+        (if ignored (nx1-whine :ignore sym))
+        (nx-set-var-bits var (%ilogand (nx-check-downward-vcell var bits) (%ilognot (%ilsl $vbitignore 1)))))
+      (progn
+        (if (and setqed ignored) (nx1-whine :ignore sym))
+        (or ignored ignoreunused 
+            (progn (and (consp expansion) (eq (car expansion) :symbol-macro) (setq sym (list :symbol-macro sym))) (nx1-whine :unused sym)))
+        (when (%izerop (%ilogand bits (%ilogior $vrefmask $vsetqmask)))
+          (nx-set-var-bits var (%ilogior (%ilsl $vbitignore 1) bits)))))))
+
+; if an inherited var isn't setqed, it gets no vcell.  If it -is- setqed, but
+; all inheritors are downward, the vcell can be stack-consed.  Set a bit so that
+; the right thing happens when the var is bound.
+; Set the bit for the next-method var even if it is not setqed.
+(defun nx-check-downward-vcell (v bits)
+  (if (and (%ilogbitp $vbitclosed bits)
+           (or (%ilogbitp $vbitsetq bits)
+               (eq v *nx-next-method-var*))
+           (nx-afuncs-downward-p v (afunc-inner-functions *nx-current-function*)))
+    (%ilogior (%ilsl $vbitcloseddownward 1) bits)
+    bits))
+
+; afunc is "downward wrt v" if it doesn't inherit v or if all refs to afunc
+; are "downward" and no inner function of afunc is not downward with respect to v.
+(defun nx-afunc-downward-p (v afunc)
+  (or (dolist (i (afunc-inherited-vars afunc) t)
+        (when (eq (nx-root-var i) v) (return nil)))
+      (if (nx-afuncs-downward-p v (afunc-inner-functions afunc))
+        (eq (afunc-fn-refcount afunc)
+            (afunc-fn-downward-refcount afunc)))))
+
+(defun nx-afuncs-downward-p (v afuncs)
+  (dolist (afunc afuncs t)
+    (unless (nx-afunc-downward-p v afunc) (return nil))))
+
+(defun nx1-punt-bindings (vars initforms)
+  (dolist (v vars)
+    (nx1-punt-var v (pop initforms))))
+
+;;; at the beginning of a binding construct, note which lexical
+;;; variables are bound to other variables and the number of setqs
+;;; done so far on the initform.  After executing the body, if neither
+;;; variable has been closed over, the new variable hasn't been
+;;; setq'ed, and the old guy wasn't setq'ed in the body, the binding
+;;; can be punted.
+(defun nx1-note-var-binding (var initform)
+  (let* ((init (nx-untyped-form initform))
+         (inittype (nx-acode-form-type initform *nx-lexical-environment*))
+         (bits (nx-var-bits var)))
+    (when (%ilogbitp $vbitspecial bits) (nx-record-xref-info :binds (var-name var)))
+    (when inittype (setf (var-inittype var) inittype))
+    (when (and (not (%ilogbitp $vbitspecial bits))
+               (acode-p init))
+      (let* ((op (acode-operator init)))
+        (if (eq op (%nx1-operator lexical-reference))
+          (let* ((target (%cadr init))
+                 (setq-count (%ilsr 8 (%ilogand $vsetqmask (nx-var-bits target)))))
+            (unless (eq setq-count (%ilsr 8 $vsetqmask))
+              (cons var (cons setq-count target))))
+          (if (and (%ilogbitp $vbitdynamicextent bits)
+                   (or (eq op (%nx1-operator closed-function))
+                       (eq op (%nx1-operator simple-function))))
+            (let* ((afunc (%cadr init)))
+              (setf (afunc-fn-downward-refcount afunc)
+                    (afunc-fn-refcount afunc)
+                    (afunc-bits afunc) (logior (ash 1 $fbitdownward) (ash 1 $fbitbounddownward)
+                                               (the fixnum (afunc-bits afunc))))
+              nil)))))))
+
+
+;;; Process entries involving variables bound to other variables at
+;;; the end of a binding construct.  Each entry is of the form
+;;; (source-var setq-count . target-var), where setq-count is the
+;;; assignment count of TARGET-VAR at the time that the binding's
+;;; initform was evaluated (not, in the case of LET, at the time that
+;;; the bindinw was established.).  If the target isn't closed-over
+;;; and SETQed (somewhere), and wasn't setqed in the body (e.g.,
+;;; still has the same assignment-count as it had when the initform
+;;; was executed), then we can "punt" the source (and replace references
+;;; to it with references to the target.)
+;;; It obviously makes no sense to do this if the source is SPECIAL;
+;;; in some cases (LET), we create the source variable and add it to
+;;; this alist before it's known whether or not the source variable
+;;; is SPECIAL. so we have to ignore that case here.
+(defun nx1-check-var-bindings (alist)
+  (dolist (pair alist)
+    (let* ((var (car pair))
+           (target (cddr pair))
+           (vbits (nx-var-bits var))
+           (target-bits (nx-var-bits target)))
+      (unless (or
+               ;; var can't be special, setq'ed or closed; target can't be
+               ;; setq'ed AND closed.
+               (neq (%ilogand vbits (%ilogior (%ilsl $vbitsetq 1)
+                                              (%ilsl $vbitclosed 1)
+                                              (%ilsl $vbitspecial 1))) 0)
+               (eq (%ilogior (%ilsl $vbitsetq 1) (%ilsl $vbitclosed 1)) 
+                   (%ilogand
+                     (%ilogior (%ilsl $vbitsetq 1) (%ilsl $vbitclosed 1))
+                     target-bits))
+               (neq (%ilsr 8 (%ilogand $vsetqmask target-bits)) (cadr pair)))
+             (push (cons var target) *nx-punted-vars*)))))
+
+(defun nx1-punt-var (var initform)
+  (let* ((bits (nx-var-bits var))
+         (mask (%ilogior (%ilsl $vbitsetq 1) (ash -1 $vbitspecial) (%ilsl $vbitclosed 1)))
+         (nrefs (%ilogand $vrefmask bits))
+         (val (nx-untyped-form initform))
+         (op (if (acode-p val) (acode-operator val))))
+    (when (%izerop (%ilogand mask bits))
+      (if
+        (or 
+         (nx-t val)
+         (nx-null val)
+         (and (eql nrefs 1) (not (logbitp $vbitdynamicextent bits)) ( acode-absolute-ptr-p val t))
+         (eq op (%nx1-operator fixnum))
+         (eq op (%nx1-operator immediate)))
+        (progn
+          (nx-set-var-bits var (%ilogior (%ilsl $vbitpuntable 1) bits)))))
+    (when (and (%ilogbitp $vbitdynamicextent bits)
+               (or (eq op (%nx1-operator closed-function))
+                   (eq op (%nx1-operator simple-function))))
+      (let* ((afunc (cadr val)))
+        (setf (afunc-bits afunc) (%ilogior (%ilsl $fbitbounddownward 1) (afunc-bits afunc))
+              (afunc-fn-downward-refcount afunc) 1))) 
+    nil))
+            
+(defnxdecl optimize (pending specs env)
+  (declare (ignore env))
+  (let* ((q nil)
+         (v nil)
+         (mdecls (pending-declarations-mdecls pending)))
+    (dolist (spec (%cdr specs) (setf (pending-declarations-mdecls pending) mdecls))
+      (if (atom spec)
+        (setq q spec v 3)
+        (setq q (%car spec) v (cadr spec)))
+      (if (and (fixnump v) (<= 0 v 3) (memq q '(speed space compilation-speed safety debug)))
+        (push (cons q v) mdecls)
+        (nx-bad-decls spec)))))
+
+(defun %proclaim-optimize (specs &aux q v)
+  (dolist (spec specs)
+    (if (atom spec)
+      (setq q spec v 3)
+      (setq q (%car spec) v (cadr spec)))
+    (or (and (fixnump v)
+             (<= 0 v 3)
+             (case q
+               (speed (setq *nx-speed* v))
+               (space (setq *nx-space* v))
+               (compilation-speed (setq *nx-cspeed* v))
+               (safety (setq *nx-safety* v))
+               (debug (setq *nx-debug* v))))
+        (bad-proclaim-spec `(optimize ,spec)))))
+
+(defun nx-lexical-finfo (sym &optional (env *nx-lexical-environment*))
+  (let* ((info nil)
+         (barrier-crossed nil))
+    (if env
+      (loop
+        (when (eq 'barrier (lexenv.variables env))
+          (setq barrier-crossed t))
+        (when (setq info (%cdr (assq sym (lexenv.functions env))))
+          (return (values info (if (and (eq (car info) 'function)
+                                        (consp (%cdr info)))
+                                 (progn
+                                   (when barrier-crossed
+                                     (nx-error "Illegal reference to lexically-defined function ~S." sym))
+                                   (%cadr info))))))
+        (if (listp (setq env (lexenv.parent-env env)))
+          (return (values nil nil))))
+      (values nil nil))))
+
+(defun nx-inline-expansion (sym &optional (env *nx-lexical-environment*) global-only)
+  (let* ((lambda-form nil)
+         (containing-env nil)
+         (token nil))
+    (if (and (nx-declared-inline-p sym env)
+             (not (gethash sym *nx1-alphatizers*))
+             (not *nx-current-code-note*))
+      (multiple-value-bind (info afunc) (unless global-only (nx-lexical-finfo sym env))
+        (if info (setq token afunc 
+                       containing-env (afunc-environment afunc)
+                       lambda-form (afunc-lambdaform afunc)))
+        (setq info (cdr (retrieve-environment-function-info sym env)))
+        (if (def-info.lambda info)
+            (setq lambda-form (def-info.lambda info)
+                  token sym
+                  containing-env (new-lexical-environment (definition-environment env)))
+            (unless info
+              (if (cdr (setq info (assq sym *nx-globally-inline*)))
+                (setq lambda-form (%cdr info)
+                      token sym
+                      containing-env (new-lexical-environment (new-definition-environment nil))))))))
+    (values lambda-form (nx-closed-environment env containing-env) token)))
+
+(defun nx-closed-environment (current-env target)
+  (when target
+    (let* ((intervening-functions nil))
+      (do* ((env current-env (lexenv.parent-env env)))
+           ((or (eq env target) (null env) (istruct-typep env 'definition-environment)))
+        (let* ((fn (lexenv.lambda env)))
+          (when fn (push fn intervening-functions))))
+      (let* ((result target))
+        (dolist (fn intervening-functions result)
+          (setf (lexenv.lambda (setq result (new-lexical-environment result))) fn))))))
+
+(defun nx-root-var (v)
+  (do* ((v v bits)
+        (bits (var-bits v) (var-bits v)))
+       ((fixnump bits) v)))
+
+(defun nx-reconcile-inherited-vars (more)
+  (let ((last nil)) ; Bop 'til ya drop.
+    (loop
+      (setq last more more nil)
+      (dolist (callee last)
+        (dolist (caller (afunc-callers callee))
+          (unless (or (eq caller callee)
+                      (eq caller (afunc-parent callee)))
+            (dolist (v (afunc-inherited-vars callee))
+              (let ((root-v (nx-root-var v)))
+                (unless (dolist (caller-v (afunc-inherited-vars caller))
+                          (when (eq root-v (nx-root-var caller-v))
+                            (return t)))
+                  ; caller must inherit root-v in order to call callee without using closure.
+                  ; can't just bind afunc & call nx-lex-info here, 'cause caller may have
+                  ; already shadowed another var with same name.  So:
+                  ; 1) find the ancestor of callee which bound v; this afunc is also an ancestor
+                  ;    of caller
+                  ; 2) ensure that each afunc on the inheritance path from caller to this common
+                  ;    ancestor inherits root-v.
+                  (let ((ancestor (afunc-parent callee))
+                        (inheritors (list caller)))
+                    (until (eq (setq v (var-bits v)) root-v)
+                      (setq ancestor (afunc-parent ancestor)))
+                    (do* ((p (afunc-parent caller) (afunc-parent p)))
+                         ((eq p ancestor))
+                      (push p inheritors))
+                    (dolist (f inheritors)
+                      (setq v (nx-cons-var (var-name v) v))
+                      (unless (dolist (i (afunc-inherited-vars f))
+                                (when (eq root-v (nx-root-var i))
+                                  (return (setq v i))))
+                        (pushnew f more)
+                        (push v (afunc-inherited-vars f))
+                        ; change shared structure of all refs in acode with one swell foop.
+                        (nx1-afunc-ref f))))))))))    
+      (unless more (return)))))
+
+(defun nx-inherit-var (var binder current)
+  (if (eq binder current)
+    (progn
+      (nx-set-var-bits var (%ilogior2 (%ilsl $vbitclosed 1) (nx-var-bits var)))
+      var)
+    (let ((sym (var-name var)))
+      (or (dolist (already (afunc-inherited-vars current))
+            (when (eq sym (var-name already)) (return already)))
+          (progn
+            (setq var (nx-cons-var sym (nx-inherit-var var binder (afunc-parent current))))
+            (push var (afunc-inherited-vars current))
+            var)))))
+
+(defun nx-lex-info (sym &optional current-only)
+  (let* ((current-function *nx-current-function*)
+         (catch nil)
+         (barrier-crossed nil))
+    (multiple-value-bind 
+      (info afunc)
+      (do* ((env *nx-lexical-environment* (lexenv.parent-env env))
+            (continue env (and env (not (istruct-typep env 'definition-environment))))
+            (binder current-function (or (if continue (lexenv.lambda env)) binder)))
+           ((or (not continue) (and (neq binder current-function) current-only)) 
+            (values nil nil))
+        (let ((vars (lexenv.variables env)))
+          (if (eq vars 'catch) 
+            (setq catch t)
+            (if (eq vars 'barrier)
+              (setq barrier-crossed t)
+              (let ((v (dolist (var vars)
+                         (when (eq (var-name var) sym) (return var)))))
+                (when v (return (values v binder)))
+                (dolist (decl (lexenv.vdecls env))
+                  (when (and (eq (car decl) sym)
+                             (eq (cadr decl) 'special))
+                    (return-from nx-lex-info (values :special nil nil)))))))))
+      (if info
+        (if (var-expansion info)
+          (values :symbol-macro (cdr (var-expansion info)) info)
+          (if (%ilogbitp $vbitspecial (nx-var-bits info))
+            (values :special info nil)
+            (if barrier-crossed
+              (nx-error "Illegal reference to lexically defined variable ~S." sym)
+              (if (eq afunc current-function)
+                (values info nil catch)
+                (values (nx-inherit-var info afunc current-function) t catch)))))
+        (values nil nil nil)))))
+
+
+(defun nx-block-info (blockname &optional (afunc *nx-current-function*) &aux
+  blocks
+  parent
+  (toplevel (eq afunc *nx-current-function*))
+  blockinfo)
+ (when afunc
+  (setq
+   blocks (if toplevel *nx-blocks* (afunc-blocks afunc))
+   blockinfo (assq blockname blocks)
+   parent (afunc-parent afunc))
+  (if blockinfo
+   (values blockinfo nil)
+   (when parent
+    (when (setq blockinfo (nx-block-info blockname parent))
+     (values blockinfo t))))))
+
+(defun nx-tag-info (tagname &optional (afunc *nx-current-function*) &aux
+                            tags
+                            parent
+                            index
+                            counter
+                            (toplevel (eq afunc *nx-current-function*))
+                            taginfo)
+  (when afunc
+    (setq
+     tags (if toplevel *nx-tags* (afunc-tags afunc))
+     taginfo (assoc tagname tags)
+     parent (afunc-parent afunc))
+    (if taginfo
+      (values taginfo nil)
+      (when (and parent (setq taginfo (nx-tag-info tagname parent)))
+        (unless (setq index (cadr taginfo))
+          (setq counter (caddr taginfo))
+          (%rplaca counter (%i+ (%car counter) 1))
+          (setq index (%car counter))
+          (%rplaca (%cdr taginfo) index))
+        (values taginfo index)))))
+
+(defun nx1-transitively-punt-bindings (pairs) 
+  (dolist (pair (nreverse pairs))
+    (let* ((var         (%car pair))
+           (boundto     (%cdr pair))
+           (varbits     (nx-var-bits var))
+           (boundtobits (nx-var-bits boundto)))
+      (declare (fixnum varbits boundtobits))
+      (unless (eq (%ilogior
+                    (%ilsl $vbitsetq 1)
+                    (%ilsl $vbitclosed 1))
+                  (%ilogand
+                    (%ilogior
+                      (%ilsl $vbitsetq 1)
+                      (%ilsl $vbitclosed 1))
+                    boundtobits))
+        ;; Can't happen -
+        (unless (%izerop (%ilogand (%ilogior
+                                     (%ilsl $vbitsetq 1) 
+                                     (ash -1 $vbitspecial)
+                                     (%ilsl $vbitclosed 1)) varbits))
+          (error "Bug-o-rama - \"punted\" var had bogus bits. ~
+Or something. Right? ~s ~s" var varbits))
+        (let* ((varcount     (%ilogand $vrefmask varbits)) 
+               (boundtocount (%ilogand $vrefmask boundtobits)))
+          (nx-set-var-bits var (%ilogior
+                                 (%ilsl $vbitpuntable 1)
+                                 (%i- varbits varcount)))
+          (setf (var-refs var) (+ (var-refs var) (var-refs boundto)))
+          (nx-set-var-bits
+           boundto
+           (%i+ (%i- boundtobits boundtocount)
+                (%ilogand $vrefmask
+                          (%i+ (%i- boundtocount 1) varcount)))))))))
+
+;;; Home-baked handler-case replacement.  About 10 times as fast as full handler-case.
+;;;(LET ((S 0)) (DOTIMES (I 1000000) (INCF S))) took 45,678 microseconds
+;;;(LET ((S 0)) (DOTIMES (I 1000000) (BLOCK X (ERROR (CATCH 'X (RETURN-FROM X (INCF S))))))) took 57,485
+;;;(LET ((S 0)) (DOTIMES (I 1000000) (HANDLER-CASE (INCF S) (ERROR (C) C)))) took 168,947
+(defmacro with-program-error-handler (handler &body body)
+  (let ((tag (gensym)))
+    `(block ,tag
+       (,handler (catch 'program-error-handler (return-from ,tag (progn ,@body)))))))
+
+(defun runtime-program-error-form (c)
+  `(signal-program-error "Invalid program: ~a" ,(princ-to-string c)))
+
+(defun nx1-compile-lambda (name lambda-form &optional
+                                 (p (make-afunc))
+                                 q
+                                 parent-env
+                                 (policy *default-compiler-policy*)
+                                 load-time-eval-token)
+
+  (if q
+     (setf (afunc-parent p) q))
+
+  ;; In the case of a method function, the name will get reset at load time to the
+  ;; method object.  However, during compilation, we want any inner functions to use
+  ;; the fully qualified method name, so store that.
+  (when (method-lambda-p lambda-form)
+    (setq name (or *nx-method-warning-name* name)))
+
+  (setf (afunc-name p)
+        (let ((parent-name (and (afunc-parent p) (afunc-name (afunc-parent p)))))
+          (if parent-name
+            (if (and (consp parent-name) (eq (%car parent-name) :internal))
+              (if name
+                `(:internal ,name ,@(cdr parent-name))
+                parent-name)
+              (if name
+                `(:internal ,name ,parent-name)
+                `(:internal ,parent-name)))
+            name)))
+
+  (unless (lambda-expression-p lambda-form)
+    (nx-error "~S is not a valid lambda expression." lambda-form))
+
+  (let* ((*nx-current-function* p)
+         (*nx-parent-function* q)
+         (*nx-current-note* (or *nx-current-note* (nx-source-note lambda-form)))
+         (*nx-lexical-environment* (new-lexical-environment parent-env))
+         (*nx-load-time-eval-token* load-time-eval-token)
+         (*nx-all-vars* nil)
+         (*nx-bound-vars* nil)
+         (*nx-punted-vars* nil)
+         (*nx-current-compiler-policy* policy)
+         (*nx-blocks* nil)
+         (*nx-tags* nil)
+         (*nx-loop-nesting-level* 0)
+         (*nx-inner-functions* nil)
+         (*nx-global-function-name* nil)
+         (*nx-warnings* nil)
+         (*nx1-fcells* nil)
+         (*nx1-vcells* nil)
+         (*nx-inline-expansions* nil)
+         (*nx-parsing-lambda-decls* nil)
+         (*nx-next-method-var* (if q *nx-next-method-var*))
+         (*nx-call-next-method-function* (if q *nx-call-next-method-function*))
+         (*nx-cur-func-name* name))
+    (if (%non-empty-environment-p *nx-lexical-environment*)
+      (setf (afunc-bits p) (logior (ash 1 $fbitnonnullenv) (the fixnum (afunc-bits p)))))
+
+    (setf (afunc-lambdaform p) lambda-form)
+
+    (when *nx-current-note*
+      (setf (afunc-lfun-info p)
+            (list* '%function-source-note *nx-current-note* (afunc-lfun-info p))))
+
+    (with-program-error-handler
+	(lambda (c)
+	  (setf (afunc-acode p) (nx1-lambda '(&rest args) `(args ,(runtime-program-error-form c)) nil)))
+      (handler-bind ((warning (lambda (c)
+                                (nx1-whine :program-error c)
+                                (muffle-warning c)))
+                     (program-error (lambda (c)
+                                      (when *nx-break-on-program-errors*
+                                        (cerror "continue compilation ignoring this form" c))
+                                      (when (typep c 'compile-time-program-error)
+                                        (setq c (make-condition 'simple-program-error
+                                                                :format-control (simple-condition-format-control c)
+                                                                :format-arguments (simple-condition-format-arguments c))))
+                                      (unless *nx-break-on-program-errors*
+                                        (nx1-whine :program-error c))
+                                      (throw 'program-error-handler c))))
+	(multiple-value-bind (body decls)
+	    (with-program-error-handler (lambda (c) (runtime-program-error-form c))
+	      (parse-body (%cddr lambda-form) *nx-lexical-environment* t))
+          (setf (afunc-acode p) (nx1-lambda (%cadr lambda-form) body decls)))))
+
+    (nx1-transitively-punt-bindings *nx-punted-vars*)
+    (setf (afunc-blocks p) *nx-blocks*)
+    (setf (afunc-tags p) *nx-tags*)
+    (setf (afunc-inner-functions p) *nx-inner-functions*)
+    (setf (afunc-all-vars p) *nx-all-vars*)
+    (setf (afunc-vcells p) *nx1-vcells*)
+    (setf (afunc-fcells p) *nx1-fcells*)
+    (let* ((warnings (merge-compiler-warnings *nx-warnings*))
+	   (name *nx-cur-func-name*))        
+      (dolist (inner *nx-inner-functions*)
+	(dolist (w (afunc-warnings inner))
+	  (push name (compiler-warning-function-name w))
+	  (push w warnings)))
+      (setf (afunc-warnings p) warnings))
+    p))
+
+(defun method-lambda-p (form)
+  (and (consp form)
+       (consp (setq form (%cdr form)))       
+       (eq (caar form) '&method)))
+
+
+(defun nx1-lambda (ll body decls &aux (l ll) methvar)
+  (let* ((old-env *nx-lexical-environment*)
+         (*nx-bound-vars* *nx-bound-vars*))
+    (with-nx-declarations (pending)
+      (let* ((*nx-parsing-lambda-decls* t))
+        (nx-process-declarations pending decls))
+      (when (eq (car l) '&lap)
+        (let ((bits nil))
+          (unless (and (eq (length (%cdr l)) 1) (fixnump (setq bits (%cadr l))))
+            (unless (setq bits (encode-lambda-list (%cdr l)))
+              (nx-error "invalid lambda-list  - ~s" l)))
+          (return-from nx1-lambda
+                       (make-acode
+                        (%nx1-operator lambda-list)
+                        (list (cons '&lap bits))
+                        nil
+                        nil
+                        nil
+                        nil
+                        (nx1-env-body body old-env)
+                        *nx-new-p2decls*))))
+      (when (eq (car l) '&method)
+        (setf (afunc-bits *nx-current-function*)
+              (%ilogior (%ilsl $fbitmethodp 1)
+                        (afunc-bits *nx-current-function*)))
+        (setq *nx-inlined-self* nil)
+        (setq *nx-next-method-var* (setq methvar (let ((var (nx-new-var
+							     pending
+							     (%cadr ll))))
+                                                   (nx-set-var-bits var (%ilogior 
+                                                                          (%ilsl $vbitignoreunused 1) 
+                                                                          ;(%ilsl $vbitnoreg 1) 
+                                                                          (nx-var-bits var)))
+                                                   var)))
+                                                   
+        (setq ll (%cddr ll)))
+      (multiple-value-bind (req opt rest keys auxen lexpr)
+                           (nx-parse-simple-lambda-list pending ll)
+        (nx-effect-other-decls pending *nx-lexical-environment*)
+        (setq body (nx1-env-body body old-env))
+        (nx1-punt-bindings (%car auxen) (%cdr auxen))
+        (when methvar
+          (push methvar req)
+          (unless (eq 0 (%ilogand (%ilogior (%ilsl $vbitreffed 1)
+                                            (%ilsl $vbitclosed 1)
+                                            (%ilsl $vbitsetq 1))
+                                  (nx-var-bits methvar)))
+            (setf (afunc-bits *nx-current-function*)
+                  (%ilogior 
+                   (%ilsl $fbitnextmethp 1)
+                   (afunc-bits *nx-current-function*)))))
+        (let ((acode (make-acode
+                      (%nx1-operator lambda-list) 
+                      req
+                      opt 
+                      (if lexpr (list rest) rest)
+                      keys
+                      auxen
+                      body
+                      *nx-new-p2decls*)))
+          (when *nx-current-code-note*
+            (setf (acode-note acode) *nx-current-code-note*))
+          acode)))))
+
+(defun nx-parse-simple-lambda-list (pending ll &aux
+					      req
+					      opt
+					      rest
+					      keys
+					      lexpr
+					      sym)
+  (multiple-value-bind (ok reqsyms opttail resttail keytail auxtail)
+                       (verify-lambda-list ll)
+    (unless ok (nx-error "Bad lambda list : ~S" ll))
+    (dolist (var reqsyms)
+      (push (nx-new-var pending var t) req))
+    (when (eq (pop opttail) '&optional)
+      (let* (optvars optinits optsuppliedp)
+        (until (eq opttail resttail) 
+          (setq sym (pop opttail))
+          (let* ((var sym)
+                 (initform nil)
+                 (spvar nil))
+            (when (consp var)
+              (setq sym (pop var) initform (pop var) spvar (%car var)))
+            (push (nx1-typed-var-initform pending sym initform) optinits)
+            (push (nx-new-var pending sym t) optvars)
+            (push (if spvar (nx-new-var pending spvar t)) optsuppliedp)))
+        (if optvars
+          (setq opt (list (nreverse optvars) (nreverse optinits) (nreverse optsuppliedp)))
+          (nx1-whine :lambda ll))))
+    (let ((temp (pop resttail)))
+      (when (or (eq temp '&rest)
+                (setq lexpr (eq temp '&lexpr)))
+        (setq rest (nx-new-var pending (%car resttail) t))))
+    (when (eq (%car keytail) '&key) 
+      (setq keytail (%cdr keytail))
+      (let* ((keysyms ())
+             (keykeys ())
+             (keyinits ())
+             (keysupp ())
+             (kallowother (not (null (memq '&allow-other-keys ll))))
+             (kvar ())
+             (kkey ())
+             (kinit ())
+             (ksupp))
+        (until (eq keytail auxtail)
+          (unless (eq (setq sym (pop keytail)) '&allow-other-keys)      
+            (setq kinit *nx-nil* ksupp nil)
+            (if (atom sym)
+              (setq kvar sym kkey (make-keyword sym))
+              (progn
+                (if (consp (%car sym))
+                  (setq kkey (%caar sym) kvar (%cadar sym))
+                  (progn
+                    (setq kvar (%car sym))
+                    (setq kkey (make-keyword kvar))))
+                (setq kinit (nx1-typed-var-initform pending kvar (%cadr sym)))
+                (setq ksupp (%caddr sym))))
+            (push (nx-new-var pending kvar t) keysyms)
+            (push kkey keykeys)
+            (push kinit keyinits)
+            (push (if ksupp (nx-new-var pending ksupp t)) keysupp)))
+        (setq 
+         keys
+         (list
+          kallowother
+          (nreverse keysyms)
+          (nreverse keysupp)
+          (nreverse keyinits)
+          (apply #'vector (nreverse keykeys))))))
+    (let (auxvals auxvars)
+      (dolist (pair (%cdr auxtail))
+        (let* ((auxvar (nx-pair-name pair))
+               (auxval (nx1-typed-var-initform pending auxvar (nx-pair-initform pair))))
+          (push auxval auxvals)
+          (push (nx-new-var pending auxvar t) auxvars)))
+      (values
+       (nreverse req) 
+       opt 
+       rest
+       keys
+       (list (nreverse auxvars) (nreverse auxvals))
+       lexpr))))
+
+(defun nx-new-structured-var (pending sym)
+  (if sym
+    (nx-new-var pending sym t)
+    (nx-new-temp-var pending)))
+
+(defun nx-parse-structured-lambda-list (pending ll &optional no-acode whole-p &aux
+                                           req
+                                           opt
+                                           rest
+                                           keys
+                                           sym)
+  (multiple-value-bind (ok reqsyms opttail resttail keytail auxtail all whole structured-p)
+                       (verify-lambda-list ll t whole-p nil)
+    (declare (ignore all))
+    (unless ok (nx-error "Bad lambda list : ~S" ll))
+    (if (or whole (and whole-p structured-p)) (setq whole (nx-new-structured-var pending whole)))
+    (dolist (var reqsyms)
+      (push (if (symbolp var)
+                    (nx-new-structured-var pending var)
+                    (nx-structured-lambda-form pending var no-acode))
+                  req))
+    (when (eq (pop opttail) '&optional)
+      (let* (optvars optinits optsuppliedp)
+        (until (eq opttail resttail) 
+          (setq sym (pop opttail))
+          (let* ((var sym)
+                 (initform nil)
+                 (spvar nil))
+            (when (consp var)
+              (setq sym (pop var) initform (pop var) spvar (%car var)))
+            (push (if no-acode initform (nx1-form initform)) optinits)
+            (push (if (symbolp sym)
+                          (nx-new-structured-var pending sym)
+                          (nx-structured-lambda-form pending sym no-acode))
+                        optvars)
+            (push (if spvar (nx-new-var pending spvar)) optsuppliedp)))
+        (if optvars
+          (setq opt (list (nreverse optvars) (nreverse optinits) (nreverse optsuppliedp)))
+          (nx1-whine :lambda ll))))
+    (let ((var (pop resttail)))
+      (when (or (eq var '&rest)
+                (eq var '&body))
+        (setq var (pop resttail)
+              rest (if (symbolp var)
+                     (nx-new-structured-var pending var)
+                     (nx-structured-lambda-form pending var no-acode)))))
+    (when (eq (%car keytail) '&key) 
+      (setq keytail (%cdr keytail))
+      (let* ((keysyms ())
+             (keykeys ())
+             (keyinits ())
+             (keysupp ())
+             (kallowother (not (null (memq '&allow-other-keys ll))))
+             (kvar ())
+             (kkey ())
+             (kinit ())
+             (ksupp))
+        (until (eq keytail auxtail)
+          (unless (eq (setq sym (pop keytail)) '&allow-other-keys)      
+            (setq kinit *nx-nil* ksupp nil)
+            (if (atom sym)
+              (setq kvar sym kkey (make-keyword sym))
+              (progn
+                (if (consp (%car sym))
+                  (setq kkey (%caar sym) kvar (%cadar sym))
+                  (progn
+                    (setq kvar (%car sym))
+                    (setq kkey (make-keyword kvar))))
+                (setq kinit (if no-acode (%cadr sym) (nx1-form (%cadr sym))))
+                (setq ksupp (%caddr sym))))
+            (push (if (symbolp kvar)
+                          (nx-new-structured-var pending kvar)
+                          (nx-structured-lambda-form pending kvar no-acode))
+                        keysyms)
+            (push kkey keykeys)
+            (push kinit keyinits)
+            (push (if ksupp (nx-new-var pending ksupp)) keysupp)))
+        (setq 
+         keys
+         (list
+          kallowother
+          (nreverse keysyms)
+          (nreverse keysupp)
+          (nreverse keyinits)
+          (apply #'vector (nreverse keykeys))))))
+    (let (auxvals auxvars)
+      (dolist (pair (%cdr auxtail))
+        (let ((auxvar (nx-pair-name pair))
+              (auxval (nx-pair-initform pair)))
+          (push (if no-acode auxval (nx1-form auxval)) auxvals)
+          (push (nx-new-var pending auxvar) auxvars)))
+      (values
+       (nreverse req) 
+       opt 
+       rest 
+       keys
+       (list (nreverse auxvars) (nreverse auxvals))
+       whole))))
+
+(defun nx-structured-lambda-form (pending l &optional no-acode)
+  (multiple-value-bind (req opt rest keys auxen whole)
+                       (nx-parse-structured-lambda-list pending l no-acode t)
+    (list (%nx1-operator lambda-list) whole req opt rest keys auxen)))
+
+(defun nx1-form (form &optional (*nx-lexical-environment* *nx-lexical-environment*))
+  (let* ((*nx-form-type* (if (and (consp form) (eq (car form) 'the))
+                           (nx-target-type (cadr form))
+                           t)))
+    (nx1-typed-form form *nx-lexical-environment*)))
+
+(defun nx1-typed-form (original env)
+  (with-program-error-handler
+      (lambda (c)
+        (let ((replacement (runtime-program-error-form c)))
+          (nx-note-source-transformation original replacement)
+          (nx1-transformed-form (nx-transform replacement env) env)))
+    (multiple-value-bind (form changed source) (nx-transform original env)
+      (declare (ignore changed))
+      ;; Bind this for cases where the transformed form is an atom, so it doesn't remember the source it came from.
+      (let ((*nx-current-note* (or source *nx-current-note*)))
+	(nx1-transformed-form form env)))))
+
+(defun nx1-transformed-form (form env)
+  (let* ((*nx-current-note* (or (nx-source-note form) *nx-current-note*))
+         (*nx-current-code-note*  (and *nx-current-code-note*
+                                       (or (nx-ensure-code-note form *nx-current-code-note*)
+                                           (compiler-bug "No source note for ~s" form))))
+         (acode (if (consp form)
+                  (nx1-combination form env)
+                  (let* ((symbolp (non-nil-symbol-p form))
+                         (constant-value (unless symbolp form))
+                         (constant-symbol-p nil))
+                    (if symbolp 
+                      (multiple-value-setq (constant-value constant-symbol-p) 
+                        (nx-transform-defined-constant form env)))
+                    (if (and symbolp (not constant-symbol-p))
+                      (nx1-symbol form env)
+                      (nx1-immediate (nx-unquote constant-value)))))))
+    (unless (acode-note acode) ;; leave it with most specific note
+      (cond (*nx-current-code-note*
+             (setf (acode-note acode) *nx-current-code-note*))
+            (*record-pc-mapping*
+             (setf (acode-note acode) (nx-source-note form)))))
+    acode))
+
+(defun nx1-prefer-areg (form env)
+  (nx1-form form env))
+
+(defun nx1-target-fixnump (form)
+  (when (typep form 'integer)
+       (let* ((target (backend-target-arch *target-backend*)))
+         (and
+          (>= form (arch::target-most-negative-fixnum target))
+          (<= form (arch::target-most-positive-fixnum target))))))
+
+
+(defun nx1-immediate (form)
+  (if (or (eq form t) (null form))
+    (nx1-sysnode form)
+    (make-acode 
+     (if (nx1-target-fixnump form) 
+       (%nx1-operator fixnum)
+        (%nx1-operator immediate))   ; Screw: chars
+     form)))
+
+(defun nx2-constant-form-value (form)
+  (setq form (nx-untyped-form form))
+  (and (or (nx-null form)
+           (nx-t form)
+           (and (acode-p form)
+                (or (eq (acode-operator form) (%nx1-operator immediate))
+                    (eq (acode-operator form) (%nx1-operator fixnum))
+                    (eq (acode-operator form) (%nx1-operator simple-function)))))
+       form))
+
+(defun nx-natural-constant-p (form)
+  (setq form (nx-untyped-form form))
+  (if (consp form)
+    (let* ((val (if (or (eq (acode-operator form) (%nx1-operator fixnum))
+			(eq (acode-operator form) (%nx1-operator immediate)))
+		  (cadr form))))
+      (target-word-size-case
+       (32 (and (typep val '(unsigned-byte 32)) val))
+       (64 (and (typep val '(unsigned-byte 64)) val))))))
+
+(defun nx-u32-constant-p (form)
+  (setq form (nx-untyped-form form))
+  (if (consp form)
+    (let* ((val (if (or (eq (acode-operator form) (%nx1-operator fixnum))
+			(eq (acode-operator form) (%nx1-operator immediate)))
+		  (cadr form))))
+      (and (typep val '(unsigned-byte 32)) val))))
+
+(defun nx-u31-constant-p (form)
+  (setq form (nx-untyped-form form))
+  (if (consp form)
+    (let* ((val (if (or (eq (acode-operator form) (%nx1-operator fixnum))
+			(eq (acode-operator form) (%nx1-operator immediate)))
+		  (cadr form))))
+      (and (typep val '(unsigned-byte 31)) val))))
+
+
+;;; Reference-count vcell, fcell refs.
+(defun nx1-note-vcell-ref (sym)
+  (let* ((there (assq sym *nx1-vcells*))
+         (count (expt 4 *nx-loop-nesting-level*)))
+    (if there
+      (%rplacd there (%i+ (%cdr there) count))
+      (push (cons sym count) *nx1-vcells*)))
+  sym)
+
+(defun nx1-note-fcell-ref (sym)
+  (let* ((there (assq sym *nx1-fcells*))
+         (count (expt 4 *nx-loop-nesting-level*)))
+    (if there
+      (%rplacd there (%i+ (%cdr there) count))
+      (push (cons sym count) *nx1-fcells*))
+    sym))
+
+; Note that "simple lexical refs" may not be; that's the whole problem ...
+(defun nx1-symbol (form &optional (env *nx-lexical-environment*))
+  (let* ((type (nx-declared-type form))
+         (form
+          (multiple-value-bind (info inherited-p more)
+                               (nx-lex-info form)
+            (if (and info (neq info :special))
+              (if (eq info :symbol-macro)
+                (progn
+                  (nx-set-var-bits more (%ilogior (%ilsl $vbitreffed 1) (nx-var-bits more)))
+                  (if (eq type t)
+                    (nx1-form inherited-p)
+                    (nx1-form `(the ,(prog1 type (setq type t)) ,inherited-p))))
+                (progn
+                  (when (not inherited-p)
+                    (nx-set-var-bits info (%ilogior2 (%ilsl $vbitreffed 1) (nx-var-bits info))))
+                  (nx-adjust-ref-count info)
+                  (nx-make-lexical-reference info)))
+              (make-acode
+	       (if (nx1-check-special-ref form info)
+		   (progn
+		     (nx-record-xref-info :references form)
+		     (if (nx-global-p form env)
+			 (%nx1-operator global-ref)
+		         (if (and (not (nx-force-boundp-checks form env))
+				  (or (nx-proclaimed-parameter-p form)
+				  (assq form *nx-compile-time-types*)
+				  (assq form *nx-proclaimed-types*)
+				  (nx-open-code-in-line env)))
+			     (%nx1-operator bound-special-ref)
+			     (%nx1-operator special-ref))))
+		   (%nx1-operator free-reference))
+               (nx1-note-vcell-ref form))))))
+    (if (eq type t)
+	form
+      (make-acode (%nx1-operator typed-form) type form))))
+
+(defun nx1-check-special-ref (form auxinfo)
+  (or (eq auxinfo :special) 
+      (nx-proclaimed-special-p form)
+      (let ((defenv (definition-environment *nx-lexical-environment*)))
+        (unless (and defenv (eq (car (defenv.type defenv)) :execute) (boundp form))
+          (nx1-whine :special form))
+        nil)))
+
+
+
+(defun nx1-whine (about &rest forms)
+  (push (make-condition (or (cdr (assq about *compiler-whining-conditions*)) 'compiler-warning)
+			:function-name (list *nx-cur-func-name*)
+			:source-note *nx-current-note*
+			:warning-type about
+			:args (or forms (list nil)))
+	*nx-warnings*))
+
+(defun p2-whine (afunc about &rest forms)
+  (let* ((warning (make-condition (or (cdr (assq about *compiler-whining-conditions*)) 'compiler-warning)
+                                  :function-name (list (afunc-name afunc))
+                                  :warning-type about
+                                  :args (or forms (list nil)))))
+    (push warning (afunc-warnings afunc))
+    (do* ((p (afunc-parent afunc) (afunc-parent p)))
+         ((null p) warning)
+      (let* ((pname (afunc-name p)))
+        (push pname (compiler-warning-function-name warning))
+        (push warning (afunc-warnings p))))))
+
+(defun nx1-type-intersect (form type1 type2 &optional (env *nx-lexical-environment*))
+  (let* ((ctype1 (if (typep type1 'ctype) type1 (values-specifier-type type1 env)))
+         (ctype2 (if (typep type2 'ctype) type2 (values-specifier-type type2 env)))
+         (intersection (if (or (values-ctype-p ctype1) (values-ctype-p ctype2))
+                         (values-type-intersection ctype1 ctype2)
+                         (type-intersection ctype1 ctype2))))
+    (when (eq intersection *empty-type*)
+      (let ((type1 (if (typep type1 'ctype)
+                     (type-specifier type1)
+                     type1))
+            (type2 (if (typep type2 'ctype)
+                     (type-specifier type2)
+                     type2)))
+        (nx1-whine :type-conflict form type1 type2)))
+    (type-specifier intersection)))
+
+(defun nx-declared-notinline-p (sym env)
+  (setq sym (maybe-setf-function-name sym))
+  (loop
+    (when (listp env)
+      (return (and (symbolp sym)
+                   (proclaimed-notinline-p sym))))
+    (dolist (decl (lexenv.fdecls env))
+      (when (and (eq (car decl) sym)
+                 (eq (cadr decl) 'inline))
+         (return-from nx-declared-notinline-p (eq (cddr decl) 'notinline))))
+    (setq env (lexenv.parent-env env))))
+
+
+
+(defun nx1-combination (form env)
+  (destructuring-bind (sym &rest args)
+                      form
+    (if (symbolp sym)
+      (let* ((*nx-sfname* sym) special)
+        (if (and (setq special (gethash sym *nx1-alphatizers*))
+                 (or (not (functionp (fboundp sym)))
+                     (memq sym '(apply funcall ;; see bug #285
+                                 %defun        ;; see bug #295
+                                 ))
+                     (< (safety-optimize-quantity env) 3))
+                 ;(not (nx-lexical-finfo sym env))
+                 (not (nx-declared-notinline-p sym *nx-lexical-environment*)))
+          (funcall special form env) ; pass environment arg ...
+          (progn            
+            (nx1-typed-call sym args))))
+      (if (lambda-expression-p sym)
+        (nx1-lambda-bind (%cadr sym) args (%cddr sym))
+      (nx-error "In the form ~S, ~S is not a symbol or lambda expression." form sym)))))
+
+(defun nx1-treat-as-call (args)
+  (nx1-typed-call (car args) (%cdr args)))
+
+(defun nx1-typed-call (fn args &optional spread-p)
+  (let ((global-only nil)
+	(errors-p nil)
+	(result-type t))
+    (when (and (acode-p fn) (eq (acode-operator fn) (%nx1-operator immediate)))
+      (multiple-value-bind (valid name) (valid-function-name-p (%cadr fn))
+	(when valid
+	  (setq fn name global-only t))))
+    (when (non-nil-symbol-p fn)
+      (multiple-value-setq (errors-p args result-type)
+	(nx1-check-typed-call fn args spread-p global-only)))
+    (setq result-type (nx1-type-intersect fn *nx-form-type* result-type))
+    (let ((form (nx1-call fn args spread-p global-only errors-p)))
+      (if (eq result-type t)
+	form
+	(make-acode (%nx1-operator typed-form) result-type form)))))
+
+(defvar *format-arg-functions* '((format . 1) (format-to-string . 1) (error . 0) (warn . 0)
+				 (y-or-n-p . 0) (yes-or-no-p . 0)
+				 (signal-simple-program-error . 0)
+				 (signal-simple-condition . 1)
+				 (signal-reader-error . 1)
+				 (%method-combination-error . 0)
+				 (%invalid-method-error . 1)
+				 (nx-compile-time-error . 0)
+				 (nx-error . 0)
+				 (compiler-bug . 0)))
+
+(defun nx1-find-call-def (sym &optional (env *nx-lexical-environment*) (global-only nil))
+  (and (or (and (not global-only) (nth-value 1 (nx-lexical-finfo sym)))
+	   (retrieve-environment-function-info sym env)
+	   (let ((def (fboundp sym)))
+	     (and (functionp def) def)))))
+
+(defun nx1-check-typed-call (sym args &optional spread-p global-only)
+  (let ((env *nx-lexical-environment*)
+	(result-type t)
+	(typed-args args)
+	(errors-p nil)
+	(ftype nil)
+	(def nil))
+    (setq ftype (find-ftype-decl sym env args spread-p))
+    (setq def (nx1-find-call-def sym env global-only))
+    (when ftype
+      (multiple-value-setq (typed-args result-type errors-p)
+	(nx1-analyze-ftyped-call ftype sym args spread-p env)))
+    (when (and def (not errors-p))
+      (multiple-value-bind (deftype reason) (nx1-check-call-args def args spread-p)
+	(when deftype
+	  (nx1-whine deftype sym reason args spread-p)
+	  (setq errors-p t))))
+    (unless (or def ftype (eq sym *nx-global-function-name*))
+      (nx1-whine :undefined-function sym args spread-p)
+      (setq errors-p t))
+    (unless errors-p
+      (let* ((format-args (and (not spread-p)
+			       (not (typep def 'afunc))
+			       (let* ((n (cdr (assq sym *format-arg-functions*))))
+				 (and n (nthcdr n typed-args)))))
+	     (control (pop format-args)))
+	(when (and (consp control)
+		   (eq (%car control) 'the)
+		   (consp (%cdr control))
+		   (consp (%cddr control)))
+	  (setq control (%caddr control)))
+	(when (stringp (setq control (nx-transform control env)))
+	  (when (nx1-check-format-call control format-args env)
+	    (setq errors-p t)))))
+
+    (values errors-p typed-args result-type)))
+
+(defun known-ftype-for-call (sym args spread-p env)
+  ;; Find ftype based on actual arguments.
+  ;; This should be more general, but for now just pick off some special cases..
+  (when (and args (or (not spread-p) (cdr args)))
+    (cond ((or (eq sym 'aref) (eq sym 'uvref))
+           (let* ((atype (nx-form-type (car args) env))
+                  (a-ctype (specifier-type atype)))
+             (when (array-ctype-p a-ctype)
+               ;; No point declaring the type of an arg whose type we already know
+               `(function (t &rest integer) ,(type-specifier (array-ctype-specialized-element-type
+                                                                  a-ctype))))))
+          ((eq sym 'error)
+           (let ((condition (car args)))
+             (cond ((nx-form-typep condition 'condition env)
+                    '(function (t) *))
+                   ((nx-form-typep condition 'symbol env)
+                    ;; TODO: might be able to figure out actual initargs...
+                    `(function (t &key &allow-other-keys) *))
+                   (t nil))))
+          ((eq sym 'cerror)
+           (when (and (cdr args) (or (not spread-p) (cddr args)))
+             (let ((condition (cadr args)))
+               (cond ((nx-form-typep condition 'condition env)
+                      `(function (string t &rest t) *))
+                     ((nx-form-typep condition 'symbol env)
+                      `(function (string t &key &allow-other-keys) *))
+                     (t `(function (string t &rest t) *))))))
+          (t nil))))
+
+(defun find-ftype-decl (sym &optional (env *nx-lexical-environment*) (args :unknown) spread-p)
+  (setq sym (maybe-setf-function-name sym))
+  (loop
+    for lexenv = env then (lexenv.parent-env lexenv) until (listp lexenv)
+    do (dolist (fdecl (lexenv.fdecls lexenv))
+         (when (and (eq (car fdecl) sym)
+                    (eq (car (%cdr fdecl)) 'ftype))
+           (return-from find-ftype-decl (%cddr fdecl))))
+    do (when (and (istruct-typep lexenv 'lexical-environment)
+                  (assq sym (lexenv.functions lexenv)))
+         (return-from find-ftype-decl nil)))
+  (or (proclaimed-ftype sym)
+      (and (listp args)
+           (known-ftype-for-call sym args spread-p env))))
+
+(defun nx1-analyze-ftyped-call (ftype sym arglist spread-p env)
+  (let ((ctype (if (typep ftype 'ctype) ftype (specifier-type ftype)))
+	(result-type t)
+	(errors-p nil))
+    (unless (or (null ctype) (not (function-ctype-p ctype)))
+      (unless (function-ctype-wild-args ctype)
+	(let ((req (args-ctype-required ctype))
+	      (opt (args-ctype-optional ctype))
+	      (rest (args-ctype-rest ctype))
+	      (keyp (args-ctype-keyp ctype))
+	      (aokp (or spread-p (args-ctype-allowp ctype)))
+	      (keys (args-ctype-keywords ctype))
+	      (typed-arglist nil)
+	      (key-type nil)
+	      (bad-keys nil)
+	      (nargs (if spread-p (1- (length arglist)) (length arglist))))
+	  (flet ((collect-type (arg type)
+		   (push (if (and type
+                                  (neq type *universal-type*)
+                                  (neq type *wild-type*)
+                                  (setq type (type-specifier type))
+                                  ;; Don't record unknown types, just causes spurious warnings.
+                                  (specifier-type-if-known type env :values t))
+                             `(the ,type ,arg)
+                             arg)
+                         typed-arglist))
+                 (key-name (x) (key-info-name x))
+		 (whine (&rest reason)
+		   (nx1-whine :ftype-mismatch sym reason arglist spread-p)
+		   (setq errors-p t)))
+	    (declare (dynamic-extent #'collect-type #'whine))
+	    (loop for arg in arglist as i below nargs
+		  do (cond
+		       (req (collect-type arg (pop req)))
+		       (opt (collect-type arg (pop opt)))
+		       (rest (collect-type arg rest))
+		       (key-type (collect-type arg (shiftf key-type nil)))
+		       (keyp (if (nx-form-constant-p arg env)
+			       (let* ((key (nx-form-constant-value arg env))
+				      (ki (find key keys :key #'key-name)))
+				 (when (eq key :allow-other-keys) (setq aokp t))
+				 (if ki
+				   (setq key-type (key-info-type ki))
+				   (unless aokp (push key bad-keys))))
+			       (setq aokp t))
+			     (collect-type arg nil)
+			     (unless key-type (setq key-type *universal-type*)))
+		       (t (return (whine :toomany
+					 nargs
+					 (+ (length (args-ctype-required ctype))
+					    (length (args-ctype-optional ctype)))))))
+		  finally (cond (spread-p (collect-type arg nil))
+				(req (whine :toofew
+					    nargs
+					    (length (args-ctype-required ctype))))
+				(key-type (whine :odd-keywords 
+						 (nthcdr
+						  (+ (length (args-ctype-required ctype))
+						     (length (args-ctype-optional ctype)))
+						  arglist)))
+				(bad-keys (whine :unknown-keyword
+						 (if (cdr bad-keys)
+						   (nreverse bad-keys)
+						   (car bad-keys))
+						 (map 'list #'key-name keys)))))
+	    (unless errors-p
+	      (setq arglist (nreverse typed-arglist))))))
+      (setq result-type (type-specifier (single-value-type (function-ctype-returns ctype)))))
+    (values arglist (nx-target-type result-type) errors-p)))
+
+
+(defun innermost-lfun-bits-keyvect (def)
+  (let* ((inner-def (closure-function (find-unencapsulated-definition def)))
+         (bits (lfun-bits inner-def))
+         (keys (lfun-keyvect inner-def)))
+    (declare (fixnum bits))
+    #+no
+    (when (and (eq (ash 1 $lfbits-gfn-bit)
+                   (logand bits (logior (ash 1 $lfbits-gfn-bit)
+                                        (ash 1 $lfbits-method-bit))))
+               (logbitp $lfbits-keys-bit bits))
+      (setq bits (logior (ash 1 $lfbits-aok-bit) bits)
+            keys nil))
+    (values bits keys)))
+
+(defun def-info-bits-keyvect (info)
+  (let ((bits (def-info.lfbits info)))
+    (when (and (eq (def-info.function-type info) 'defgeneric)
+               (logbitp $lfbits-keys-bit bits)
+               (not (logbitp $lfbits-aok-bit bits))
+	       #-BOOTSTRAPPED (fboundp 'def-info-method.keyvect)
+               (loop for m in (def-info.methods info)
+                     thereis (null (def-info-method.keyvect m))))
+      ;; Some method has &aok, don't bother checking keywords.
+      (setq bits (logior bits (ash 1 $lfbits-aok-bit))))
+    (values bits (def-info.keyvect info))))
+
+
+(defun nx1-check-call-args (def arglist spread-p)
+  (multiple-value-bind (bits keyvect)
+      (etypecase def
+        (function (innermost-lfun-bits-keyvect def))
+        (afunc (let ((lambda-form (afunc-lambdaform def)))
+                 (and (lambda-expression-p lambda-form)
+                      (encode-lambda-list (cadr lambda-form) t))))
+        (cons (def-info-bits-keyvect (cdr def))))
+    (when bits
+      (multiple-value-bind (reason defer-p)
+          (or (nx1-check-call-bits bits arglist spread-p) ;; never deferred
+              (nx1-check-call-keywords def bits keyvect arglist spread-p))
+        (when reason
+          #-BOOTSTRAPPED (unless (find-class 'undefined-keyword-reference nil)
+                           (return-from nx1-check-call-args nil))
+          (values (if defer-p
+                    :deferred-mismatch
+                    (typecase def
+                      (function :global-mismatch)
+                      (afunc :lexical-mismatch)
+                      (t :environment-mismatch)))
+                  reason))))))
+
+(defun nx1-check-call-bits (bits arglist spread-p)
+  (let* ((nargs (length arglist))
+         (minargs (if spread-p (1- nargs) nargs))
+         (required (ldb $lfbits-numreq bits))
+         (max (if (logtest (logior (ash 1 $lfbits-rest-bit) (ash 1 $lfbits-restv-bit) (ash 1 $lfbits-keys-bit)) bits)
+                nil
+                (+ required (ldb $lfbits-numopt bits)))))
+    ;; If the (apparent) number of args in the call doesn't
+    ;; match the definition, complain.  If "spread-p" is true,
+    ;; we can only be sure of the case when more than the
+    ;; required number of args have been supplied.
+    (or (and (not spread-p)
+             (< minargs required)
+             `(:toofew ,minargs ,required))
+        (and max
+             (> minargs max)
+             `(:toomany ,nargs ,max)))))
+
+(defun nx1-check-call-keywords (def bits keyvect args spread-p &aux (env *nx-lexical-environment*))
+  ;; Ok, if generic function, bits and keyvect are for the generic function itself.
+  ;; Still, since all congruent, can check whether have variable numargs
+  (unless (and (logbitp $lfbits-keys-bit bits)
+               (not spread-p)) ; last argform may contain :allow-other-keys
+    (return-from nx1-check-call-keywords nil))
+  (let* ((bad-keys nil)
+         (key-args (nthcdr (+ (ldb $lfbits-numreq bits) (ldb $lfbits-numopt bits)) args))
+         (generic-p (or (generic-function-p def)
+                        (and (consp def)
+                             (eq (def-info.function-type (cdr def)) 'defgeneric)))))
+    (when (oddp (length key-args))
+      (return-from nx1-check-call-keywords (list :odd-keywords key-args)))
+    (when (logbitp $lfbits-aok-bit bits)
+      (return-from nx1-check-call-keywords nil))
+    (loop for key-form in key-args by #'cddr
+          do (unless (nx-form-constant-p key-form env) ;; could be :aok
+               (return-from nx1-check-call-keywords nil))
+          do (let ((key (nx-form-constant-value key-form env)))
+               (when (eq key :allow-other-keys)
+                 (return-from nx1-check-call-keywords nil))
+               (unless (or (find key keyvect)
+                          (and generic-p (nx1-valid-gf-keyword-p def key)))
+                 (push key bad-keys))))
+    (when bad-keys
+      (if generic-p
+        (values (list :unknown-gf-keywords bad-keys) t)
+        (list :unknown-keyword (if (cdr bad-keys) (nreverse bad-keys) (%car bad-keys)) keyvect)))))
+
+(defun nx1-valid-gf-keyword-p (def key)
+  ;; Can assume has $lfbits-keys-bit and not $lfbits-aok-bit
+  (if (consp def)
+    (let ((definfo (cdr def)))
+      (assert (eq (def-info.function-type definfo) 'defgeneric))
+      (loop for m in (def-info.methods definfo)
+            as keyvect = (def-info-method.keyvect m)
+            thereis (or (null keyvect) (find key keyvect))))
+    (let ((gf (find-unencapsulated-definition def)))
+      (or (find key (%defgeneric-keys gf))
+          (loop for m in (%gf-methods gf)
+                thereis (let* ((func (%inner-method-function m))
+                               (mbits (lfun-bits func)))
+                          (or (and (logbitp $lfbits-aok-bit mbits)
+                                   ;; If no &rest, then either don't use the keyword in which case
+                                   ;; it's good to warn; or it's used via next-method, we'll approve
+                                   ;; it when we get to that method.
+                                   (logbitp $lfbits-rest-bit mbits))
+                              (find key (lfun-keyvect func)))))))))
+
+;;; we can save some space by going through subprims to call "builtin"
+;;; functions for us.
+(defun nx1-builtin-function-offset (name)
+   (arch::builtin-function-name-offset name))
+
+(defun nx1-call-form (global-name afunc arglist spread-p  &optional (env *nx-lexical-environment*))
+  (if afunc
+    (make-acode (%nx1-operator lexical-function-call) afunc (nx1-arglist arglist (if spread-p 1 (backend-num-arg-regs *target-backend*))) spread-p)
+    (let* ((builtin (unless (or spread-p
+                                (eql 3 (safety-optimize-quantity env)))
+                      (nx1-builtin-function-offset global-name))))
+      (if (and builtin
+               (let* ((bits (lfun-bits (fboundp global-name))))
+                 (and bits (eql (logand $lfbits-args-mask bits)
+                                (dpb (length arglist)
+                                     $lfbits-numreq
+                                     0)))))
+        (make-acode (%nx1-operator builtin-call) 
+                    (make-acode (%nx1-operator fixnum) builtin)
+                    (nx1-arglist arglist))
+        (make-acode (%nx1-operator call)
+                     (if (symbolp global-name)
+                       (nx1-immediate (nx1-note-fcell-ref global-name))
+                       global-name)
+                     (nx1-arglist arglist (if spread-p 1 (backend-num-arg-regs *target-backend*)))
+                     spread-p)))))
+  
+;;; If "sym" is an expression (not a symbol which names a function),
+;;; the caller has already alphatized it.
+(defun nx1-call (sym args &optional spread-p global-only inhibit-inline)
+  (nx1-verify-length args 0 nil)
+  (when (and (acode-p sym) (eq (acode-operator sym) (%nx1-operator immediate)))
+    (multiple-value-bind (valid name) (valid-function-name-p (%cadr sym))
+      (when valid
+	(setq global-only t sym name))))
+  (let ((args-in-regs (if spread-p 1 (backend-num-arg-regs *target-backend*))))
+    (if (nx-self-call-p sym global-only)
+      ;; Should check for downward functions here as well.
+      (multiple-value-bind (deftype reason)
+                           (nx1-check-call-args *nx-current-function* args spread-p)
+        (when deftype
+          (nx1-whine deftype sym reason args spread-p))
+        (make-acode (%nx1-operator self-call) (nx1-arglist args args-in-regs) spread-p))
+      (multiple-value-bind (lambda-form containing-env token) (nx-inline-expansion sym *nx-lexical-environment* global-only)
+        (or (and (not inhibit-inline)
+		 (nx1-expand-inline-call lambda-form containing-env token args spread-p *nx-lexical-environment*))
+            (multiple-value-bind (info afunc) (if (and  (symbolp sym) (not global-only)) (nx-lexical-finfo sym))
+              (when (eq 'macro (car info))
+                (nx-error "Can't call macro function ~s" sym))
+	      (nx-record-xref-info :direct-calls sym)
+              (if (and afunc (%ilogbitp $fbitruntimedef (afunc-bits afunc)))
+                (let ((sym (var-name (afunc-lfun afunc))))
+                  (nx1-form 
+                   (if spread-p
+                     `(,(if (eql spread-p 0) 'applyv 'apply) ,sym ,args)
+                     `(funcall ,sym ,@args))))
+                (let* ((val (nx1-call-form sym afunc args spread-p)))
+                    (when afunc
+                      (let ((callers (afunc-callers afunc))
+                            (self *nx-current-function*))
+                        (unless (or (eq self afunc) (memq self callers))
+                          (setf (afunc-callers afunc) (cons self callers)))))
+                    (if (and (null afunc) (memq sym *nx-never-tail-call*))
+                      (make-acode (%nx1-operator values) (list val))
+                      val)))))))))
+
+(defun nx1-expand-inline-call (lambda-form env token args spread-p old-env)
+  (if (and (or (null spread-p) (eq (length args) 1)))
+    (if (and token (not (memq token *nx-inline-expansions*)))
+      (with-program-error-handler (lambda (c) (declare (ignore c)) nil)
+	(let* ((*nx-inline-expansions* (cons token *nx-inline-expansions*))
+	       (lambda-list (cadr lambda-form))
+	       (body (cddr lambda-form))
+	       (new-env (new-lexical-environment env)))
+	  (setf (lexenv.mdecls new-env)
+                `((speed . ,(speed-optimize-quantity old-env))
+		  (space . ,(space-optimize-quantity old-env))
+		  (safety . ,(space-optimize-quantity old-env))
+		  (compilation-speed . ,(compilation-speed-optimize-quantity old-env))
+		  (debug . ,(debug-optimize-quantity old-env))))
+	  (if spread-p
+	    (nx1-destructure lambda-list (car args) nil nil body new-env)
+	    (nx1-lambda-bind lambda-list args body new-env)))))))
+             
+; note that regforms are reversed: arg_z is always in the car
+(defun nx1-arglist (args &optional (nregargs (backend-num-arg-regs *target-backend*)))
+  (declare (fixnum nregargs))
+  (let* ((stkforms nil)
+         (regforms nil)
+         (nstkargs (%i- (length args) nregargs)))
+    (declare (fixnum nstkargs))
+      (list
+       (dotimes (i nstkargs (nreverse stkforms))
+         (declare (fixnum i))
+         (push (nx1-form (%car args)) stkforms)
+         (setq args (%cdr args)))
+       (dolist (arg args regforms)
+         (push (nx1-form arg) regforms)))))
+
+(defun nx1-formlist (args)
+  (let* ((a nil))
+    (dolist (arg args)
+      (push (nx1-form arg) a))
+    (nreverse a)))
+
+(defun nx1-verify-length (forms min max &aux (len (list-length forms)))
+ (if (or (null len)
+         (%i> min len)
+         (and max (%i> len max)))
+     (nx-error "Wrong number of args in form ~S." (cons *nx-sfname* forms))
+     len))
+
+(defun nx-unquote (form)
+  (if (nx-quoted-form-p form)
+    (%cadr form)
+    form))
+
+(defun nx-quoted-form-p (form &aux (f form))
+ (and (consp form)
+      (eq (pop form) 'quote)
+      (or
+       (and (consp form)
+            (not (%cdr form)))
+       (nx-error "Illegally quoted form ~S." f))))
+
+(defun nx-form-constant-p (form env)
+  (declare (ignore env))
+  (or (quoted-form-p form)
+      (self-evaluating-p form)))
+
+(defun nx-form-constant-value (form env)
+  (declare (ignore env))
+  (declare (type (satisfies nx-form-constant-p) form))
+  (if (consp form) (%cadr form) form))
+
+; Returns two values: expansion & win
+; win is true if expansion is not EQ to form.
+; This is a bootstrapping version.
+; The real one is in "ccl:compiler;optimizers.lisp".
+(unless (fboundp 'maybe-optimize-slot-accessor-form)
+
+(defun maybe-optimize-slot-accessor-form (form environment)
+  (declare (ignore environment))
+  (values form nil))
+
+)
+
+(defun nx-source-note (form &aux (source-notes *nx-source-note-map*))
+  (when source-notes
+    (when (or (consp form) (vectorp form) (pathnamep form))
+      (let ((note (gethash form source-notes)))
+        (unless (listp note) note)))))
+
+
+(defun nx-transform (form &optional (environment *nx-lexical-environment*) (source-note-map *nx-source-note-map*))
+  (macrolet ((form-changed (form)
+               `(progn
+                  (unless source (setq source (gethash ,form source-note-map)))
+                  (setq changed t))))
+    (prog (sym transforms lexdefs changed enabled macro-function compiler-macro (source t))
+       (when source-note-map
+         (setq source (gethash form source-note-map)))
+       (go START)
+     LOOP
+       (form-changed form)
+       (when (and (consp form) 
+                  (or (eq (%car form) 'the)
+                      (and sym (eq (%car form) sym))))
+         (go DONE))
+     START
+       (when (non-nil-symbol-p form)
+         (multiple-value-bind (newform win) (nx-transform-symbol form environment)
+           (unless win (go DONE))
+           (setq form newform)
+           (go LOOP)))
+       (when (atom form) (go DONE))
+       (unless (symbolp (setq sym (%car form)))
+         (go DONE))
+       #+no
+       (when (eq sym 'the)
+         (destructuring-bind (typespec thing) (cdr form)
+           (if (constantp thing)
+             (progn
+               (setq form thing)
+               (go LOOP))
+             (multiple-value-bind (newform win) (nx-transform thing environment source-note-map)
+               (when win
+                 (form-changed newform)
+                 (if (and (self-evaluating-p newform)
+                          (typep newform typespec))
+                   (setq form newform)
+                   (setq form `(the ,typespec ,newform)))
+                 (go DONE))))))
+       (when (nx-quoted-form-p form)
+         (when (self-evaluating-p (%cadr form))
+           (setq form (%cadr form)))
+         (go DONE))
+       (when (setq lexdefs (nx-lexical-finfo sym environment))
+         (if (eq 'function (%car lexdefs))
+           (go DONE)))
+       (setq transforms (setq compiler-macro (compiler-macro-function sym environment))
+             macro-function (macro-function sym environment)
+             enabled (nx-allow-transforms environment))
+       (unless macro-function
+         (let* ((win nil))
+           (when (and enabled (functionp (fboundp sym)))
+             (multiple-value-setq (form win) (nx-transform-arglist form environment source-note-map))
+             (when win
+               (form-changed form)))))
+       (when (and enabled
+                  (not (nx-declared-notinline-p sym environment)))
+         (multiple-value-bind (value folded) (nx-constant-fold form environment)
+           (when folded
+             (setq form value)
+             (form-changed form)
+             (unless (and (consp form) (eq (car form) sym)) (go START))))
+         (when compiler-macro
+           (multiple-value-bind (newform win) (compiler-macroexpand-1 form environment)
+             (when win
+               (when (and (consp newform) (eq (car newform) sym) (functionp (fboundp sym)))
+                 (setq sym nil))
+               (setq form newform)
+               (go LOOP))))
+         (multiple-value-bind (newform win) (maybe-optimize-slot-accessor-form form environment)
+           (when win
+             (setq sym nil)
+             (setq form newform)
+             (go START)))
+         (unless macro-function
+           (when (setq transforms (or (environment-structref-info sym environment)
+                                      (and (boundp '%structure-refs%)
+                                           (gethash sym %structure-refs%))))
+             (setq form (defstruct-ref-transform transforms (%cdr form) environment))
+             (form-changed form)
+             (go START))
+           (when (setq transforms (assq sym *nx-synonyms*))
+             (setq form (cons (%cdr transforms) (setq sym (%cdr form))))
+             (go LOOP))))
+       (when (and macro-function
+                  (or lexdefs
+                      (not (and (gethash sym *nx1-alphatizers*) (not (nx-declared-notinline-p sym environment))))))
+         (nx-record-xref-info :macro-calls (function-name macro-function))
+         (setq form (macroexpand-1 form environment))
+         (form-changed form)
+         (go START))
+     DONE
+       (if (eq source t)
+	 (setq source nil)
+	 (let ((this (nx-source-note form)))
+	   (if this
+	     (setq source this)
+	     (when source
+	       (unless (and (consp form)
+			    (eq (%car form) 'the)
+			    (eq source (gethash (caddr form) source-note-map)))
+		 (when (or (consp form) (vectorp form) (pathnamep form))
+		   (unless (or (eq form (%unbound-marker))
+			       (eq form (%slot-unbound-marker)))
+		     (setf (gethash form source-note-map) source))))))))
+       ;; Return source for symbols, even though don't record it in hash table.
+       (return (values form changed source)))))
+
+
+; Transform all of the arguments to the function call form.
+; If any of them won, return a new call form (with the same operator as the original), else return the original
+; call form unchanged.
+(defun nx-transform-arglist (callform env source-note-map)
+  (let* ((any-wins nil)
+         (transformed-call (cons (car callform) nil))
+         (ptr transformed-call)
+         (win nil))
+    (declare (type cons ptr))
+    (dolist (form (cdr callform) (if any-wins (values (copy-list transformed-call) t) (values callform nil)))
+      (multiple-value-setq (form win) (nx-transform form env source-note-map))
+      (rplacd ptr (setq ptr (cons form nil)))
+      (if win (setq any-wins t)))))
+
+;This is needed by (at least) SETF.
+(defun nxenv-local-function-p (name macro-env)
+  (multiple-value-bind (type local-p) (function-information name macro-env)
+    (and local-p (eq :function type))))
+
+           
+;;; This guy has to return multiple values.  The arguments have
+;;; already been transformed; if they're all constant (or quoted), try
+;;; to evaluate the expression at compile-time.
+(defun nx-constant-fold (original-call &optional (environment *nx-lexical-environment*) &aux 
+                                       (fn (car original-call)) form mv foldable foldfn)
+  (flet ((quotify (x) (if (self-evaluating-p x) x (list 'quote x))))
+    (if (and (nx-allow-transforms environment)
+             (let* ((bits (if (symbolp fn) (%symbol-bits fn) 0)))
+               (declare (fixnum bits))
+               (if (setq foldable (logbitp $sym_fbit_constant_fold bits))
+                 (if (logbitp $sym_fbit_fold_subforms bits)
+                   (setq foldfn 'fold-constant-subforms))
+                 (setq foldable (assq fn *nx-can-constant-fold*)
+                       foldfn (cdr foldable)))
+               foldable))
+      (if foldfn
+        (funcall foldfn original-call environment)
+        (progn
+          (let ((args nil))
+            (dolist (arg (cdr original-call) (setq args (nreverse args)))
+              (if (quoted-form-p arg)
+                (setq arg (%cadr arg))
+                (unless (self-evaluating-p arg) (return-from nx-constant-fold (values original-call nil))))
+              (push arg args))
+            (if (nx1-check-call-args (fboundp fn) args nil)
+              (return-from nx-constant-fold (values original-call nil))
+              (setq form (multiple-value-list 
+                             (handler-case (apply fn args)
+                               (error (condition)
+                                      (warn "Error: \"~A\" ~&signalled during compile-time evaluation of ~S ."
+                                            condition original-call)
+                                      (return-from nx-constant-fold
+                                        (values `(locally (declare (notinline ,fn))
+                                                  ,original-call)
+                                                t))))))))
+          (if form
+            (if (null (%cdr form))
+              (setq form (%car form))
+              (setq mv (setq form (cons 'values (mapcar #'quotify form))))))
+          (values (if mv form (quotify form)) T)))
+      (values original-call nil))))
+
+(defun nx-transform-symbol (sym &optional (env *nx-lexical-environment*))
+; Gak.  Can't call NX-LEX-INFO without establishing *nx-lexical-environment*.
+; NX-LEX-INFO should take env arg!.
+  (let* ((*nx-lexical-environment* env))
+    (multiple-value-bind (expansion win) (macroexpand-1 sym env)
+      (if win
+        (let ((type (nx-declared-type sym))
+              (var (nth-value 2 (nx-lex-info sym))))
+          (unless (eq t type) (setq expansion `(the ,type ,expansion)))
+          (if var (nx-set-var-bits var (%ilogior (%ilsl $vbitreffed 1) (nx-var-bits var)))))
+        (progn
+          (multiple-value-setq (expansion win)
+            (nx-transform-defined-constant sym env))
+          (if win (setq win (neq sym expansion)))))
+      (values expansion win))))
+
+; if sym has a substitutable constant value in env (or globally), return
+; (values <value> t), else (values nil nil)
+(defun nx-transform-defined-constant (sym env)
+  (let* ((defenv (definition-environment env))
+         (val (if defenv (assq sym (defenv.constants defenv))))
+         (constant-value-p val))
+    (if val
+      (setq val (%cdr val))
+      (if (constant-symbol-p sym)
+        (setq constant-value-p t val (%sym-global-value sym))))
+    (if (and (neq val (%unbound-marker-8))
+             constant-value-p 
+             (nx-substititute-constant-value sym val env))
+      (values (if (self-evaluating-p val) val (list 'quote val)) t)
+      (values nil nil))))
+
+
+(defun nx-var-bits (var)
+  (do* ((var var bits)
+        (bits (var-bits var) (var-bits var)))
+       ((fixnump bits) bits)))
+
+(defun nx-set-var-bits (var newbits)
+  (do* ((var var bits)
+        (bits (var-bits var) (var-bits var)))
+       ((fixnump bits) (setf (var-bits var) newbits))))
+
+(defun nx-make-lexical-reference (var)
+  (let* ((ref (make-acode (%nx1-operator lexical-reference) var)))
+    (push ref (var-ref-forms var))
+    ref))
+
+(defun nx-adjust-ref-count (var)
+  (let* ((bits (nx-var-bits var))
+         (temp-p (%ilogbitp $vbittemporary bits))
+         (by (if temp-p 1 (expt  4 *nx-loop-nesting-level*)))
+         (new (%imin (%i+ (%ilogand2 $vrefmask bits) by) 255)))
+    (setf (var-refs var) (+ (var-refs var) by))
+    (nx-set-var-bits var (%ilogior (%ilogand (%ilognot $vrefmask) bits) new))
+    new))
+
+;;; Treat (VALUES x . y) as X if it appears in a THE form
+(defun nx-form-type (form &optional (env *nx-lexical-environment*))
+  (if (nx-form-constant-p form env)
+    ;(type-of (nx-form-constant-value form env))
+    `(member ,(nx-form-constant-value form env))
+    (if (and (consp form)	   ; Kinda bogus now, but require-type
+	     (eq (%car form) 'require-type) ; should be special some day
+	     (nx-form-constant-p (caddr form) env))
+      (nx-form-constant-value (%caddr form) env)
+      (if (nx-trust-declarations env)
+	(if (symbolp form)
+	  (nx-target-type (nx-declared-type form env))
+	  (if (consp form)
+	    (if (eq (%car form) 'the)
+	      (destructuring-bind (typespec val) (%cdr form)
+		(declare (ignore val))
+		(nx-target-type (type-specifier (single-value-type (values-specifier-type typespec)))))
+	      (if (eq (%car form) 'setq)
+		(let* ((args (%cdr form))
+		       (n (length args)))
+		  (if (and (evenp n)
+			   (> n 0)
+			   (setq args (nthcdr (- n 2) args))
+			   (non-nil-symbol-p (car args)))
+		    (nx1-type-intersect (%car args)
+					(nx-declared-type (%car args) env)
+					(nx-form-type (%cadr args) env)
+					env)
+		    t))
+		(let* ((op (gethash (%car form) *nx1-operators*)))
+		  (or (and op (cdr (assq op *nx-operator-result-types*)))
+		      (and (not op)(cdr (assq (car form) *nx-operator-result-types-by-name*)))
+		      #+no (and (memq (car form) *numeric-ops*)
+			   (grovel-numeric-form form env))
+		      #+no (and (memq (car form) *logical-ops*)
+			   (grovel-logical-form form env))
+		      (nx-declared-result-type (%car form) env (%cdr form))
+		      t))))
+	    t))
+	t))))
+
+
+(defparameter *numeric-ops* '(+ -  / * +-2 --2 *-2 /-2))
+
+(defparameter *logical-ops* '(logxor-2 logior-2 logand-2  lognot logxor))
+
+(defun numeric-type-p (type &optional not-complex)
+  (or (memq type '(fixnum integer double-float single-float float))
+      (let ((ctype (specifier-type type)))
+        (and (numeric-ctype-p ctype)
+             (or (not not-complex)
+                 (neq (numeric-ctype-complexp ctype) :complex))))))
+
+(defun grovel-numeric-form (form env)
+  (let* ((op (car form))
+         (args (cdr form)))
+    (if (every #'(lambda (x) (nx-form-typep x 'float env)) args)
+      (if (some #'(lambda (x) (nx-form-typep x 'double-float env)) args)
+        'double-float
+        'single-float)
+      (if (every #'(lambda (x) (nx-form-typep x 'integer env)) args)
+        (if (or (eq op '/) (eq op '/-2))
+          t
+          'integer)))))
+
+;; now e.g. logxor of 3 known fixnums is inline as is (logior a (logxor b c))
+;; and (the fixnum (+ a (logxor b c)))
+
+(defun grovel-logical-form (form env)
+  (when (nx-trust-declarations env)
+    (let (;(op (car form))
+          type)
+      (dolist (arg (cdr form))
+        (let ((it (nx-form-type arg env)))          
+          (if (not (subtypep it 'fixnum))
+            (return (setq type nil))
+            (setq type 'fixnum))))
+      type)))
+
+(defun nx-form-typep (arg type &optional (env *nx-lexical-environment*))
+  (setq type (nx-target-type (type-expand type)))
+  (if (nx-form-constant-p arg env)
+    (typep (nx-form-constant-value arg env) type env)
+    (subtypep (nx-form-type arg env) type env)))
+
+
+(defun nx-binary-fixnum-op-p (form1 form2 env &optional ignore-result-type)
+  (setq form1 (nx-transform form1 env)
+        form2 (nx-transform form2 env))
+  (and
+   (target-word-size-case
+    (32 (nx-form-typep form1 '(signed-byte 30) env))
+    (64 (nx-form-typep form1 '(signed-byte 61) env)))
+   (target-word-size-case
+    (32 (nx-form-typep form2 '(signed-byte 30) env))
+    (64 (nx-form-typep form2 '(signed-byte 61) env)))
+   (or ignore-result-type
+        (and (nx-trust-declarations env)
+                (target-word-size-case
+                 (32 (subtypep *nx-form-type* '(signed-byte 30)))
+                 (64 (subtypep *nx-form-type* '(signed-byte 61))))))))
+
+
+(defun nx-binary-natural-op-p (form1 form2 env &optional (ignore-result-type t))
+  (and
+   (target-word-size-case
+    (32
+     (and (nx-form-typep form1 '(unsigned-byte 32)  env)
+          (nx-form-typep form2 '(unsigned-byte 32)  env)))
+    (64
+     (and (nx-form-typep form1 '(unsigned-byte 64)  env)
+          (nx-form-typep form2 '(unsigned-byte 64)  env))))
+   (or ignore-result-type
+       (and (nx-trust-declarations env)
+            (target-word-size-case
+             (32 (subtypep *nx-form-type* '(unsigned-byte 32)))
+             (64 (subtypep *nx-form-type* '(unsigned-byte 64))))))))
+
+    
+
+
+(defun nx-binary-boole-op (whole env arg-1 arg-2 fixop intop naturalop)
+  (let* ((use-fixop (nx-binary-fixnum-op-p arg-1 arg-2 env t))
+	 (use-naturalop (nx-binary-natural-op-p arg-1 arg-2 env)))
+    (if (or use-fixop use-naturalop intop)
+      (make-acode (if use-fixop fixop (if use-naturalop naturalop intop))
+		  (nx1-form arg-1)
+		  (nx1-form arg-2))
+      (nx1-treat-as-call whole))))
+
+(defun nx-global-p (sym &optional (env *nx-lexical-environment*))
+  (or 
+   (logbitp $sym_vbit_global (the fixnum (%symbol-bits sym)))
+   (let* ((defenv (definition-environment env)))
+     (if defenv 
+       (eq :global (%cdr (assq sym (defenv.specials defenv))))))))
+  
+(defun nx-need-var (sym &optional (check-bindable t))
+  (if (and (nx-need-sym sym)
+           (not (constantp sym))
+           (let* ((defenv (definition-environment *nx-lexical-environment*)))
+             (or (null defenv)
+                 (not (assq sym (defenv.constants defenv)))))) ; check compile-time-constants, too
+    (if (and check-bindable (nx-global-p sym))
+      (nx-error "~S is declared static and can not be bound" sym)
+      sym)
+    (nx-error "Can't bind or assign to constant ~S." sym)))
+
+(defun nx-need-sym (sym)
+  (if (symbolp sym)
+    sym
+    (nx-error "~S is not a symbol." sym)))
+
+(defun nx-need-function-name (name)
+  (multiple-value-bind (valid nm) (valid-function-name-p name)
+    (if valid nm (nx-error "Invalid function name ~S" name))))
+
+(defun nx-pair-name (form)
+  (nx-need-sym (if (consp form) (%car form) form)))
+
+(defun nx-pair-initform (form)
+  (if (atom form)
+    nil
+    (if (and (listp (%cdr form)) (null (%cddr form)))
+      (%cadr form)
+      (nx-error "Bad initialization form: ~S." form))))
+
+; some callers might assume that this guy errors out if it can't conjure up
+; a fixnum.  I certainly did ...
+(defun nx-get-fixnum (form &aux (trans (nx-transform form *nx-lexical-environment*)))
+ (if (fixnump trans)
+  trans
+  form))
+ 
+(defun nx1-func-name (gizmo)
+  (and (consp gizmo)
+       (eq (%car gizmo) 'function)
+       (consp (%cdr gizmo))
+       (null (%cddr gizmo))
+       (if (lambda-expression-p (%cadr gizmo))
+	 (%cadr gizmo)
+	 (nth-value 1 (valid-function-name-p (%cadr gizmo))))))
+
+; distinguish between program errors & incidental ones.
+(defun nx-error (format-string &rest args)
+  (error (make-condition 'compile-time-program-error 
+                :context (nx-error-context)
+                :format-control format-string
+                :format-arguments args)))
+
+(defun nx-compile-time-error (format-string &rest args)
+  (error (make-condition 'compile-time-program-error 
+                :context (nx-error-context)
+                :format-control format-string
+                :format-arguments args)))
+
+; Should return information about file being compiled, nested functions, etc. ...
+(defun nx-error-context ()
+  (or *nx-cur-func-name* "an anonymous function"))
+
+(defparameter *warn-if-function-result-ignored*
+  '(sort stable-sort delete delete-if delete-if-not remf nreverse
+    nunion nset-intersection)
+  "Names of functions whos result(s) should ordinarily be used, because of their side-effects or lack of them.")
Index: /branches/new-random/compiler/nx1.lisp
===================================================================
--- /branches/new-random/compiler/nx1.lisp	(revision 13309)
+++ /branches/new-random/compiler/nx1.lisp	(revision 13309)
@@ -0,0 +1,2242 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defnx1 nx1-the the (&whole call typespec form &environment env)
+  ;; Allow VALUES types here (or user-defined types that
+  ;; expand to VALUES types).  We could do a better job
+  ;; of this, but treat them as wild types.
+  ;; Likewise, complex FUNCTION types can be legally used
+  ;; in type declarations, but aren't legal args to TYPEP;
+  ;; treat them as the simple FUNCTION type.
+  (flet ((typespec-for-the (typespec)
+           (let* ((ctype (handler-case (values-specifier-type (nx-target-type typespec) env)
+                           (parse-unknown-type (c)
+                             (nx1-whine :unknown-type-in-declaration (parse-unknown-type-specifier c))
+                             *wild-type*)
+                           (program-error (c)
+                              (nx1-whine :invalid-type typespec c)
+                             *wild-type*))))
+             (if (typep ctype 'function-ctype)
+               'function
+               (if (typep ctype 'values-ctype)
+                 '*
+                 (nx-target-type (type-specifier ctype)))))))
+    (let* ((typespec (typespec-for-the typespec))
+           (*nx-form-type* typespec)
+           (transformed (nx-transform form env)))
+      (flet ((fold-the ()
+               (do* ()
+                    ((or (atom transformed)
+                         (not (eq (car transformed) 'the))))
+                 (destructuring-bind (ftype form) (cdr transformed)
+                   (setq typespec (nx-target-type (nx1-type-intersect call typespec (typespec-for-the ftype)))
+                         *nx-form-type* typespec
+                         transformed form)))))
+        (fold-the)
+        (do* ((last transformed transformed))
+             ()
+          (setq transformed (nx-transform transformed env))
+          (when (or (atom transformed)
+                    (not (eq (car transformed) 'the)))
+            (return))
+          (fold-the)
+          (when (eq transformed last)
+            (return)))
+	(if (and (nx-form-constant-p transformed env)
+                 (or (equal typespec '(values))
+                     (not (typep (nx-form-constant-value transformed env)
+                                 (single-value-type (values-specifier-type typespec))))))
+	  (progn
+            (nx1-whine :type call)
+            (setq typespec '*))
+          (setq typespec (nx-target-type
+                          (or (nx1-type-intersect call
+                                                  typespec
+                                                  (typespec-for-the (nx-form-type transformed env)))
+                              '*))))
+        ;; Wimp out, but don't choke on (the (values ...) form)
+        (when (and (consp typespec) (eq (car typespec) 'values))
+          (setq typespec '*))
+        (make-acode
+         (%nx1-operator typed-form)
+         typespec
+         (let* ((*nx-form-type* typespec))
+           (nx1-transformed-form transformed env))
+         (nx-declarations-typecheck env))))))
+
+(defnx1 nx1-struct-ref struct-ref (&whole whole structure offset)
+  (if (not (fixnump (setq offset (nx-get-fixnum offset))))
+    (nx1-treat-as-call whole)
+    (make-acode (%nx1-operator struct-ref)
+                (nx1-form structure)
+                (nx1-form offset))))
+
+(defnx1 nx1-struct-set struct-set (&whole whole structure offset newval)
+  (if (not (fixnump (setq offset (nx-get-fixnum offset))))
+    (nx1-treat-as-call whole)
+    (make-acode
+     (%nx1-operator struct-set)
+     (nx1-form structure)
+     (nx1-form offset)
+     (nx1-form newval))))
+
+(defnx1 nx1-istruct-typep ((istruct-typep)) (&whole whole thing type &environment env)
+  (if (and (nx-form-constant-p type env) (non-nil-symbol-p (nx-form-constant-value type env)))
+    (make-acode (%nx1-operator istruct-typep)
+                (nx1-immediate :eq)
+                (nx1-form thing)
+                (nx1-form `(register-istruct-cell ,type)))
+    (nx1-treat-as-call whole)))
+
+(defnx1 nx1-make-list make-list (&whole whole size &rest keys &environment env)
+  (if (and keys 
+             (or 
+              (neq (list-length keys) 2)
+              (neq (nx-transform (%car keys) env) :initial-element)))
+    (nx1-treat-as-call whole)
+    (make-acode
+     (%nx1-operator make-list)
+     (nx1-form size)
+     (nx1-form (%cadr keys)))))
+
+;;; New semantics: expansion functions are defined in current lexical environment
+;;; vice null environment.  May be meaningless ...
+(defnx1 nx1-macrolet macrolet (defs &body body)
+  (let* ((old-env *nx-lexical-environment*)
+         (new-env (new-lexical-environment old-env)))
+    (dolist (def defs)
+      (destructuring-bind (name arglist &body mbody) def
+        (push 
+         (cons 
+          name
+          (cons
+           'macro
+           (multiple-value-bind (function warnings)
+               (compile-named-function (parse-macro name arglist mbody old-env) :name name :env old-env)
+             (setq *nx-warnings* (append *nx-warnings* warnings))
+             function)))
+         (lexenv.functions new-env))))
+    (let* ((*nx-lexical-environment* new-env))
+      (with-nx-declarations (pending)
+        (multiple-value-bind (body decls) (parse-body body new-env)
+          (nx-process-declarations pending decls)
+          (nx1-progn-body body))))))
+
+;;; Does SYMBOL-MACROLET allow declarations ?  Yes ...
+(defnx1 nx1-symbol-macrolet symbol-macrolet (defs &body forms)
+  (let* ((old-env *nx-lexical-environment*))
+    (with-nx-declarations (pending)
+      (multiple-value-bind (body decls)
+                           (parse-body forms old-env nil)
+        (nx-process-declarations pending decls)
+        (let ((env *nx-lexical-environment*)
+              (*nx-bound-vars* *nx-bound-vars*))
+          (dolist (def defs)
+            (destructuring-bind (sym expansion) def
+              (let* ((var (nx-new-var pending sym))
+                     (bits (nx-var-bits var)))
+                (when (%ilogbitp $vbitspecial bits)
+                  (nx-error "SPECIAL declaration applies to symbol macro ~s" sym))
+                (nx-set-var-bits var (%ilogior (%ilsl $vbitignoreunused 1) bits))
+                (setf (var-ea var) (cons :symbol-macro expansion)))))
+          (nx-effect-other-decls pending env)
+          (nx1-env-body body old-env))))))
+
+(defnx1 nx1-progn progn (&body args)
+  (nx1-progn-body args))
+
+(defnx1 nx1-with-c-frame with-c-frame (var &body body)
+  (make-acode (%nx1-operator with-c-frame)
+              (nx1-form `(let* ((,var (%foreign-stack-pointer)))
+                          ,@body))))
+
+(defnx1 nx1-with-variable-c-frame with-variable-c-frame (size var &body body)
+  (make-acode (%nx1-operator with-variable-c-frame)
+              (nx1-form size)
+              (nx1-form `(let* ((,var (%foreign-stack-pointer)))
+                          ,@body))))
+
+
+(defun nx1-progn-body (args)
+  (if (null (cdr args))
+    (nx1-form (%car args))
+    (make-acode (%nx1-operator progn) (nx1-formlist args))))
+
+(defnx1 nx1-unaryop ((%word-to-int) (uvsize)  (%reference-external-entry-point)
+                     (%symbol->symptr))
+        (arg)
+  (make-acode
+   (%nx1-default-operator) (nx1-form arg)))
+
+(defnx1 nx1-nullaryop ((%current-tcr) (%interrupt-poll) (%foreign-stack-pointer) (%current-frame-ptr)) ()
+  (make-acode (%nx1-default-operator)))
+
+(defnx1 nx1-fixnum-ref ((%fixnum-ref) (%fixnum-ref-natural)) (base &optional (offset 0))
+  (make-acode (%nx1-default-operator)
+              (nx1-form base)
+              (nx1-form offset)))
+
+(defnx1 nx1-type-unaryop ((typecode) (lisptag) (fulltag))
+  (arg)
+  (let* ((operator
+	  (case *nx-sfname*
+	    ((typecode) (%nx1-operator typecode))
+	    ((lisptag) (%nx1-operator lisptag))
+	    (( fulltag) (%nx1-operator fulltag)))))
+    (make-acode
+     operator (nx1-form arg))))
+        
+
+(defnx1 nx1-code-char ((code-char)) (arg &environment env)
+  (make-acode (if (nx-form-typep arg '(unsigned-byte 8) env)
+                (%nx1-operator %code-char)
+                (if (nx-form-typep arg 'valid-char-code env)
+                  (%nx1-operator %valid-code-char)
+                  (%nx1-operator code-char)))
+              (nx1-form arg)))
+
+(defnx1 nx1-char-code ((char-code)) (arg &environment env)
+  (make-acode (if (nx-form-typep arg 'character env)
+                (%nx1-operator %char-code)
+                (%nx1-operator char-code))
+              (nx1-form arg)))
+
+(defnx1 nx1-cXr ((car) (cdr)) (arg &environment env)
+  (let* ((op (if (eq *nx-sfname* 'car) (%nx1-operator car) (%nx1-operator cdr)))
+         (inline-op (if (eq op (%nx1-operator car)) (%nx1-operator %car) (%nx1-operator %cdr))))
+    (make-acode (if (or (nx-inline-car-cdr env) (nx-form-typep arg 'list env))
+                  inline-op
+                  op)
+                (nx1-prefer-areg arg env))))
+
+(defnx1 nx1-rplacX ((rplaca) (rplacd)) (pairform valform &environment env)
+  (let* ((op (if (eq *nx-sfname* 'rplaca) (%nx1-operator rplaca) (%nx1-operator rplacd)))
+         (inline-op (if (eq op (%nx1-operator rplaca)) (%nx1-operator %rplaca) (%nx1-operator %rplacd))))
+    (make-acode (if (or (nx-inline-car-cdr env)
+                                 (and (nx-trust-declarations env)
+                                      (or (subtypep *nx-form-type* 'cons)
+                                          (nx-form-typep pairform 'cons env))))
+                  inline-op
+                  op)
+                (nx1-prefer-areg pairform env)
+                (nx1-form valform))))
+
+(defnx1 nx1-set-cXr ((set-car) (set-cdr)) (pairform valform &environment env)
+  (let* ((op (if (eq *nx-sfname* 'set-car) (%nx1-operator set-car) (%nx1-operator set-cdr)))
+         (inline-op (if (eq op (%nx1-operator set-car)) (%nx1-operator %rplaca) (%nx1-operator %rplacd)))
+         (inline-p (or (nx-inline-car-cdr env)
+                            (and (nx-trust-declarations env)
+                                 (or (subtypep *nx-form-type* 'cons)
+                                     (nx-form-typep pairform 'cons env)))))
+         (acode (make-acode (if inline-p inline-op op)
+                            (nx1-prefer-areg pairform env)
+                            (nx1-form valform))))
+    (if inline-p
+      (make-acode (if (eq op (%nx1-operator set-car)) (%nx1-operator %car) (%nx1-operator %cdr)) acode)
+      acode)))
+
+(defun nx1-cc-binaryop (op cc form1 form2)
+  (make-acode op (nx1-immediate cc) (nx1-form form1) (nx1-form form2)))
+
+(defnx1 nx1-ccEQ-unaryop ((characterp)  (endp) (consp) (base-char-p)) (arg)
+  (make-acode (%nx1-default-operator) (nx1-immediate :EQ) (nx1-form arg)))
+
+
+
+(defnx1 nx1-ccEQ-binaryop ( (%ptr-eql) (eq))
+        (form1 form2)
+  (nx1-cc-binaryop (%nx1-default-operator) :eq form1 form2))
+
+
+(defnx1 nx1-ccNE-binaryop ((neq))
+        (form1 form2)
+  (nx1-cc-binaryop (%nx1-default-operator) :ne form1 form2))
+
+(defnx1 nx1-logbitp ((logbitp)) (bitnum int &environment env)
+  (if (and (nx-form-typep bitnum
+                          (target-word-size-case (32 '(integer 0 29))
+                                                 (64 '(integer 0 60))) env)
+           (nx-form-typep int 'fixnum env))
+    (nx1-cc-binaryop (%nx1-operator %ilogbitp) :ne bitnum int)
+    (make-acode (%nx1-operator logbitp) (nx1-form bitnum) (nx1-form int))))
+
+
+  
+(defnx1 nx1-ccGT-unaryop ((int>0-p)) (arg)
+  (make-acode (%nx1-default-operator) (nx1-immediate :gt) (nx1-form arg)))
+
+(defnx1 nx1-macro-unaryop (multiple-value-list) (arg)
+  (make-acode
+   (%nx1-default-operator) (nx1-form arg)))
+
+(defnx1 nx1-atom ((atom)) (arg)
+  (nx1-form `(not (consp ,arg))))
+
+(defnx1 nx1-locally locally (&body forms)
+  (with-nx-declarations (pending)
+    (let ((env *nx-lexical-environment*))
+      (multiple-value-bind (body decls) (parse-body forms env  nil)
+        (nx-process-declarations pending decls)
+        (nx-effect-other-decls pending env)
+         (setq body (nx1-progn-body body))
+         (if decls
+           (make-acode (%nx1-operator %decls-body) body *nx-new-p2decls*)
+           body)))))
+
+(defnx1 nx1-%new-ptr (%new-ptr) (size &optional clear-p)
+  (make-acode (%nx1-operator %new-ptr) (nx1-form size) (nx1-form clear-p)))
+
+;;; This might also want to look at, e.g., the last form in a progn:
+;;;  (not (progn ... x)) => (progn ... (not x)), etc.
+(defnx1 nx1-negation ((not) (null)) (arg)
+  (if (nx1-negate-form (setq arg (nx1-form arg)))
+    arg
+    (make-acode (%nx1-operator not) (nx1-immediate :eq) arg)))
+
+(defun nx1-negate-form (form)
+  (let* ((subform (nx-untyped-form form)))
+    (when (and (acode-p subform) (typep (acode-operator subform) 'fixnum))  
+      (let* ((op (acode-operator subform)))
+        (declare (fixnum op))
+        (when (logbitp operator-cc-invertable-bit op)
+          (%rplaca 
+           (%cdr (%cadr subform))
+           (acode-invert-condition-keyword (%cadr (%cadr subform))))
+          t)))))
+
+;;; This is called from pass 1, and therefore shouldn't mess with "puntable bindings"
+;;; (assuming, of course, that anyone should ...)
+(defun nx-untyped-form (form)
+  (while (and (consp form)
+              (or (and (eq (%car form) (%nx1-operator typed-form))
+                       (null (nth 3 form)))
+                  (eq (%car form) (%nx1-operator type-asserted-form))))
+    (setq form (%caddr form)))
+  form)
+
+
+
+(defnx1 nx1-cxxr ((caar) (cadr) (cdar) (cddr)) (form)
+  (let* ((op *nx-sfname*))
+    (let* ((inner (case op 
+                       ((cdar caar) 'car)
+                       (t 'cdr)))
+              (outer (case op
+                       ((cdar cddr) 'cdr)
+                       (t 'car))))
+         (nx1-form `(,outer (,inner ,form))))))      
+
+(defnx1 nx1-%int-to-ptr ((%int-to-ptr)) (int)
+  (make-acode 
+   (%nx1-operator %consmacptr%)
+   (make-acode (%nx1-operator %immediate-int-to-ptr) 
+               (nx1-form int))))
+
+(defnx1 nx1-%ptr-to-int ((%ptr-to-int)) (ptr)
+  (make-acode 
+   (%nx1-operator %immediate-ptr-to-int)
+   (make-acode (%nx1-operator %macptrptr%) 
+               (nx1-form ptr))))
+
+(defnx1 nx1-%null-ptr-p ((%null-ptr-p)) (ptr)
+  (nx1-form `(%ptr-eql ,ptr (%int-to-ptr 0))))
+
+(defnx1 nx1-binop ( (%ilsl) (%ilsr) (%iasr)
+                   (cons) (%temp-cons))
+        (arg1 arg2)
+  (make-acode (%nx1-default-operator) (nx1-form arg1) (nx1-form arg2)))
+
+
+
+(defnx1 nx1-%misc-ref ((%misc-ref)) (v i)
+  (make-acode (%nx1-operator uvref) (nx1-form v) (nx1-form i)))
+
+
+
+
+(defnx1 nx1-schar ((schar)) (s i &environment env)
+  (make-acode (%nx1-operator %sbchar) (nx1-form s env) (nx1-form i env)))
+
+
+;;; This has to be ultra-bizarre because %schar is a macro.
+;;; %schar shouldn't be a macro.
+(defnx1 nx1-%schar ((%schar)) (arg idx &environment env)
+  (let* ((arg (nx-transform arg env))
+         (idx (nx-transform idx env))
+         (argvar (make-symbol "STRING"))
+         (idxvar (make-symbol "INDEX")))
+    (nx1-form `(let* ((,argvar ,arg)
+                      (,idxvar ,idx))
+                 (declare (optimize (speed 3) (safety 0)))
+                 (declare (simple-base-string ,argvar))
+                 (schar ,argvar ,idxvar)) env)))
+        
+(defnx1 nx1-%scharcode ((%scharcode)) (arg idx)
+  (make-acode (%nx1-operator %scharcode) (nx1-form arg)(nx1-form idx)))
+
+
+(defnx1 nx1-svref ((svref) (%svref)) (&environment env v i)
+  (make-acode (if (nx-inhibit-safety-checking env)
+                (%nx1-operator %svref)
+                (%nx1-default-operator))
+              (nx1-prefer-areg v env)
+              (nx1-form i)))
+
+(defnx1 nx1-%slot-ref ((%slot-ref)) (instance idx)
+  (make-acode (%nx1-default-operator)
+              (nx1-form instance)
+              (nx1-form idx)))
+
+
+(defnx1 nx1-%err-disp ((%err-disp)) (&rest args)
+  (make-acode (%nx1-operator %err-disp)
+              (nx1-arglist args)))                       
+              
+(defnx1 nx1-macro-binop ((nth-value)) (arg1 arg2)
+  (make-acode (%nx1-default-operator) (nx1-form arg1) (nx1-form arg2)))
+
+(defnx1 nx1-%typed-miscref ((%typed-miscref) (%typed-misc-ref)) (subtype uvector index)
+  (make-acode (%nx1-operator %typed-uvref) 
+                (nx1-form subtype) 
+                (nx1-form uvector) 
+                (nx1-form index)))
+
+
+
+(defnx1 nx1-%typed-miscset ((%typed-miscset) (%typed-misc-set)) (subtype uvector index newvalue)
+  (make-acode (%nx1-operator %typed-uvset) 
+                (nx1-form subtype) 
+                (nx1-form uvector) 
+                (nx1-form index) 
+                (nx1-form newvalue)))
+
+(defnx1 nx1-logior-2 ((logior-2)) (&whole w &environment env arg-1 arg-2)
+  (nx-binary-boole-op w 
+                      env 
+                      arg-1 
+                      arg-2 
+                      (%nx1-operator %ilogior2)
+                      (%nx1-operator logior2)
+		      (%nx1-operator %natural-logior)))
+
+(defnx1 nx1-logxor-2 ((logxor-2)) (&whole w &environment env arg-1 arg-2)
+  (nx-binary-boole-op w 
+                      env 
+                      arg-1 
+                      arg-2 
+                      (%nx1-operator %ilogxor2)
+                      (%nx1-operator logxor2)
+		      (%nx1-operator %natural-logxor)))
+
+(defnx1 nx1-logand-2 ((logand-2)) (&whole w &environment env arg-1 arg-2)
+  (nx-binary-boole-op w 
+                      env 
+                      arg-1 
+                      arg-2 
+                      (%nx1-operator %ilogand2)
+                      (%nx1-operator logand2)
+		      (%nx1-operator %natural-logand)))
+
+(defnx1 nx1-require ((require-simple-vector)
+                     (require-simple-string)
+                     (require-integer)
+                     (require-list)
+                     (require-fixnum)
+                     (require-real)
+                     (require-character)
+                     (require-number)
+                     (require-symbol)
+                     (require-s8)
+                     (require-u8)
+                     (require-s16)
+                     (require-u16)
+                     (require-s32)
+                     (require-u32)
+                     (require-s64)
+                     (require-u64))
+        (arg &environment env)
+
+  (if (nx-inhibit-safety-checking env)
+    (let* ((op *nx-sfname*)
+           (type (case op
+                   (require-simple-vector 'simple-vector)
+                   (require-simple-string 'simple-string)
+                   (require-integer 'integer)
+		   (require-list 'list)
+		   (require-fixnum 'fixnum)
+		   (require-real 'real)
+		   (require-character 'character)
+		   (require-number 'number)
+		   (require-symbol 'symbol)
+		   (require-s8 '(signed-byte 8))
+		   (require-u8 '(unsigned-byte 8))
+		   (require-s16 '(signed-byte 16))
+		   (require-u16 '(unsigned-byte 16))
+		   (require-s32 '(signed-byte 32))
+		   (require-u32 '(unsigned-byte 32))
+		   (require-s64 '(signed-byte 64))
+		   (require-u64 '(unsigned-byte 64)))))
+      (nx1-form `(the ,type ,arg)))
+    (make-acode (%nx1-default-operator) (nx1-form arg))))
+
+(defnx1 nx1-%marker-marker ((%unbound-marker) (%slot-unbound-marker) (%illegal-marker)) ()
+  (make-acode (%nx1-default-operator)))
+
+(defnx1 nx1-throw (throw) (tag valuesform)
+  (make-acode (%nx1-operator throw) (nx1-form tag) (nx1-form valuesform)))
+
+
+;;; This is still used in inlining/lambda application.
+;;; The tricky parts of handling inlining reasonably have to do with
+;;; processing the body (including &optional/&key forms) in the environment
+;;; in which the lambda was defined (e.g., macros and symbol-macros.)
+;;; (I'm not sure that the traditional MCL/OpenMCL frontend handles
+;;; these cases 100% correctly, but it seems difficult to do this
+;;;  correctly without being able to jerk around with the environment,
+;;; for a variety of reasons.)
+;;; A lambda application - ((lambda ()) ...) is applied in the same
+;;; environment it's defined in, so the hard case involves inlining
+;;; functions whose environment may contain syntactic constructs
+;;; not present in the current environment (and which does -not- generally
+;;; contain whatever randomness is floating around at the point of
+;;; application.)
+(defun nx1-destructure (lambda-list bindform cdr-p &whole-allowed-p forms &optional (body-env *nx-lexical-environment*))
+  (let* ((old-env body-env)
+         (*nx-bound-vars* *nx-bound-vars*)
+         (bindform (nx1-form bindform)))
+    (if (not (verify-lambda-list lambda-list t &whole-allowed-p))
+      (nx-error "Invalid lambda-list ~s" lambda-list)
+      (let* ((*nx-lexical-environment* body-env))
+        (with-nx-declarations (pending)
+          (multiple-value-bind (body decls)
+                               (parse-body forms *nx-lexical-environment*)
+            (nx-process-declarations pending decls)
+            (multiple-value-bind (req opt rest keys auxen whole)
+                                 (nx-parse-structured-lambda-list pending lambda-list nil &whole-allowed-p)
+              (nx-effect-other-decls pending *nx-lexical-environment*)
+              (make-acode
+               (%nx1-operator debind)
+               nil
+               bindform
+               req
+               opt
+               rest
+               keys
+               auxen
+               whole
+               (nx1-env-body body old-env)
+               *nx-new-p2decls*
+               cdr-p))))))))
+
+
+
+(defnx1 nx1-%setf-macptr ((%setf-macptr)) (ptr newval)
+  (let* ((arg1 (nx1-form ptr))
+         (arg2 (nx1-form newval)))
+    (if (and (consp arg1) (eq (%car arg1) (%nx1-operator %consmacptr%)))
+      ;e.g. (%setf-macptr (%null-ptr) <foo>)
+      (make-acode (%nx1-operator %consmacptr%)
+                  (make-acode (%nx1-operator progn)
+                              (list arg1 (make-acode (%nx1-operator %macptrptr%) arg2))))
+      (make-acode (%nx1-operator %setf-macptr) arg1 arg2))))
+
+(defnx1 nx1-%setf-double-float ((%setf-double-float)) (double-node double-val)
+  (make-acode (%nx1-operator %setf-double-float) (nx1-form double-node) (nx1-form double-val)))
+
+(defnx1 nx1-%setf-short-float ((%setf-short-float) (%setf-single-float)) (short-node short-val)
+  (target-word-size-case
+   (32
+    (make-acode (%nx1-operator %setf-short-float) (nx1-form short-node) (nx1-form short-val)))
+   (64
+    (error "%SETF-SHORT-FLOAT makes no sense on 64-bit platforms."))))
+
+   
+(defnx1 nx1-%inc-ptr ((%inc-ptr)) (ptr &optional (increment 1))
+  (make-acode (%nx1-operator %consmacptr%)
+              (make-acode (%nx1-operator %immediate-inc-ptr)
+                          (make-acode (%nx1-operator %macptrptr%) (nx1-form ptr))
+                          (nx1-form increment))))
+
+(defnx1 nx1-svset ((svset) (%svset)) (&environment env vector index value)
+  (make-acode (if (nx-inhibit-safety-checking env)
+                (%nx1-operator %svset)
+                (%nx1-default-operator))
+              (nx1-prefer-areg vector env) (nx1-form index) (nx1-form value)))
+
+(defnx1 nx1-+ ((+-2)) (&environment env num1 num2)
+  (let* ((f1 (nx1-form num1))
+         (f2 (nx1-form num2)))
+    (if (nx-binary-fixnum-op-p num1 num2 env t)
+      (let* ((fixadd (make-acode (%nx1-operator %i+) f1 f2))
+             (small-enough (target-word-size-case
+                            (32 '(signed-byte 28))
+                            (64 '(signed-byte 59)))))
+        (if (or (and (nx-acode-form-typep f1 small-enough env)
+                     (nx-acode-form-typep f2 small-enough env))
+                (nx-binary-fixnum-op-p num1 num2 env nil))
+          fixadd
+          (make-acode (%nx1-operator typed-form) 'integer (make-acode (%nx1-operator fixnum-overflow) fixadd))))
+      (if (and (nx-form-typep num1 'double-float env)
+               (nx-form-typep num2 'double-float env))
+        (nx1-form `(%double-float+-2 ,num1 ,num2))
+        (if (and (nx-form-typep num1 'short-float env)
+                 (nx-form-typep num2 'short-float env))
+          (nx1-form `(%short-float+-2 ,num1 ,num2))
+	  (if (nx-binary-natural-op-p num1 num2 env nil)
+	    (make-acode (%nx1-operator typed-form)
+                        (target-word-size-case
+                         (32 '(unsigned-byte 32))
+                         (64 '(unsigned-byte 64)))
+			(make-acode (%nx1-operator %natural+) f1 f2))
+	    (make-acode (%nx1-operator typed-form) 'number 
+			(make-acode (%nx1-operator add2) f1 f2))))))))
+  
+(defnx1 nx1-%double-float-x-2 ((%double-float+-2) (%double-float--2) (%double-float*-2) (%double-float/-2 ))
+        (f0 f1)
+  (make-acode (%nx1-operator typed-form) 'double-float
+              (make-acode (%nx1-default-operator) (nx1-form f0) (nx1-form f1))))
+
+
+(defnx1 nx1-%short-float-x-2 ((%short-float+-2) (%short-float--2) (%short-float*-2) (%short-float/-2 ))
+        (f0 f1)
+  (make-acode (%nx1-operator typed-form) 'short-float
+              (make-acode (%nx1-default-operator) (nx1-form f0) (nx1-form f1))))
+
+
+(defnx1 nx1-*-2 ((*-2)) (&environment env num1 num2)
+  (if (nx-binary-fixnum-op-p num1 num2 env)
+    (make-acode (%nx1-operator %i*) (nx1-form num1 env) (nx1-form num2 env))
+    (if (and (nx-form-typep num1 'double-float env)
+             (nx-form-typep num2 'double-float env))
+      (nx1-form `(%double-float*-2 ,num1 ,num2))
+      (if (and (nx-form-typep num1 'short-float env)
+               (nx-form-typep num2 'short-float env))
+        (nx1-form `(%short-float*-2 ,num1 ,num2))
+        (make-acode (%nx1-operator mul2) (nx1-form num1 env) (nx1-form num2 env))))))
+
+(defnx1 nx1-%negate ((%negate)) (num &environment env)
+  (if (nx-form-typep num 'fixnum env)
+    (if (subtypep *nx-form-type* 'fixnum)
+      (make-acode (%nx1-operator %%ineg)(nx1-form num))
+      (make-acode (%nx1-operator %ineg) (nx1-form num)))
+    (make-acode (%nx1-operator minus1) (nx1-form num))))
+
+        
+(defnx1 nx1--2 ((--2)) (&environment env num0 num1)        
+  (if (nx-binary-fixnum-op-p num0 num1 env t)
+    (let* ((f0 (nx1-form num0))
+	   (f1 (nx1-form num1))
+	   (fixsub (make-acode (%nx1-operator %i-) f0 f1))
+	   (small-enough (target-word-size-case
+                          (32 '(signed-byte 28))
+                          (64 '(signed-byte 59)))))
+      (if (or (and (nx-acode-form-typep f0 small-enough env)
+		   (nx-acode-form-typep f1 small-enough env))
+              (nx-binary-fixnum-op-p num0 num1 env nil))
+	fixsub
+	(make-acode (%nx1-operator fixnum-overflow) fixsub)))
+    (if (and (nx-form-typep num0 'double-float env)
+	     (nx-form-typep num1 'double-float env))
+      (nx1-form `(%double-float--2 ,num0 ,num1))
+      (if (and (nx-form-typep num0 'short-float env)
+	       (nx-form-typep num1 'short-float env))
+	(nx1-form `(%short-float--2 ,num0 ,num1))
+	(if (nx-binary-natural-op-p num0 num1 env nil)
+	  (make-acode (%nx1-operator %natural-)
+		      (nx1-form num0)
+		      (nx1-form num1))
+          (make-acode (%nx1-operator sub2)
+                      (nx1-form num0)
+                      (nx1-form num1)))))))
+      
+(defnx1 nx1-/-2 ((/-2)) (num0 num1 &environment env)
+  (if (and (nx-form-typep num0 'double-float env)
+           (nx-form-typep num1 'double-float env))
+    (nx1-form `(%double-float/-2 ,num0 ,num1))
+    (if (and (nx-form-typep num0 'short-float env)
+             (nx-form-typep num1 'short-float env))
+      (nx1-form `(%short-float/-2 ,num0 ,num1))
+      (make-acode (%nx1-operator div2) (nx1-form num0) (nx1-form num1)))))
+
+
+
+(defnx1 nx1-numcmp ((<-2) (>-2) (<=-2) (>=-2)) (&environment env num1 num2)
+  (let* ((op *nx-sfname*)
+         (both-fixnums (nx-binary-fixnum-op-p num1 num2 env t))
+         (both-natural (nx-binary-natural-op-p num1 num2 env ))
+         (both-double-floats
+          (let* ((dfloat-1 (nx-form-typep num1 'double-float env))
+                 (dfloat-2 (nx-form-typep num2 'double-float env)))
+            (if dfloat-1 
+              (or dfloat-2 (if (typep num2 'fixnum) (setq num2 (coerce num2 'double-float))))
+              (if dfloat-2 (if (typep num1 'fixnum) (setq num1 (coerce num1 'double-float)))))))
+         (both-short-floats
+          (let* ((sfloat-1 (nx-form-typep num1 'short-float env))
+                 (sfloat-2 (nx-form-typep num2 'short-float env)))
+            (if sfloat-1 
+              (or sfloat-2 (if (typep num2 'fixnum) (setq num2 (coerce num2 'short-float))))
+              (if sfloat-2 (if (typep num1 'fixnum) (setq num1 (coerce num1 'short-float))))))))
+
+    (if (or both-fixnums both-double-floats both-short-floats both-natural)
+      (make-acode
+       (if both-fixnums
+         (%nx1-operator %i<>)
+         (if both-natural
+           (%nx1-operator %natural<>)
+           (if both-double-floats
+             (%nx1-operator double-float-compare)
+             (%nx1-operator short-float-compare))))
+       (make-acode
+        (%nx1-operator immediate)
+        (if (eq op '<-2)
+          :LT
+          (if (eq op '>=-2)
+            :GE
+            (if (eq op '<=-2)
+              :LE
+              :GT))))
+       (nx1-form num1)
+       (nx1-form num2))
+      (make-acode (%nx1-operator numcmp)
+                  (make-acode
+                   (%nx1-operator immediate)
+                   (if (eq op '<-2)
+                     :LT
+                     (if (eq op '>=-2)
+                       :GE
+                       (if (eq op '<=-2)
+                         :LE
+                         :GT))))
+                  (nx1-form num1)
+                  (nx1-form num2)))))
+
+(defnx1 nx1-num= ((=-2) (/=-2)) (&environment env num1 num2 )
+  (let* ((op *nx-sfname*)
+	 (2-fixnums (nx-binary-fixnum-op-p num1 num2 env t))
+	 (2-naturals (nx-binary-natural-op-p num1 num2 env))
+         (2-rats (and (nx-form-typep num1 'rational env)
+                      (nx-form-typep num2 'rational env)))
+         (2-dfloats (let* ((dfloat-1 (nx-form-typep num1 'double-float env))
+                           (dfloat-2 (nx-form-typep num2 'double-float env)))
+                      (if dfloat-1 
+                        (or dfloat-2 (if (typep num2 'fixnum) (setq num2 (coerce num2 'double-float))))
+                        (if dfloat-2 (if (typep num1 'fixnum) (setq num1 (coerce num1 'double-float)))))))
+         (2-sfloats (let* ((sfloat-1 (nx-form-typep num1 'short-float env))
+                           (sfloat-2 (nx-form-typep num2 'short-float env)))
+                      (if sfloat-1 
+                        (or sfloat-2 (if (typep num2 'fixnum) (setq num2 (coerce num2 'short-float))))
+                        (if sfloat-2 (if (typep num1 'fixnum) (setq num1 (coerce num1 'short-float)))))))
+         )
+    (if (and 2-naturals (not 2-fixnums))
+      (make-acode
+       (%nx1-operator %natural<>)
+       (make-acode
+	(%nx1-operator immediate)
+	(if (eq op '=-2)
+	  :EQ
+	  :NE))
+       (nx1-form num1)
+       (nx1-form num2))
+      (if 2-rats
+	(let* ((form `(,(if 2-fixnums 'eq 'eql) ,num1 ,num2))) 
+	  (nx1-form (if (eq op '=-2) form `(not ,form))))
+	(if (or  2-dfloats 2-sfloats)
+	  (make-acode 
+	   (if 2-dfloats
+             (%nx1-operator double-float-compare)
+             (%nx1-operator short-float-compare))
+	   (make-acode
+	    (%nx1-operator immediate)     
+	    (if (eq op '=-2)
+	      :EQ
+	      :NE))
+	   (nx1-form num1)
+	   (nx1-form num2))
+          (make-acode (%nx1-operator numcmp)
+                      (make-acode
+                       (%nx1-operator immediate)     
+                       (if (eq op '=-2)
+                         :EQ
+                         :NE))
+                      (nx1-form num1)
+                      (nx1-form num2)))))))
+             
+
+(defnx1 nx1-uvset ((uvset) (%misc-set)) (vector index value)
+  (make-acode (%nx1-operator uvset)
+              (nx1-form vector)
+              (nx1-form index)
+              (nx1-form value)))
+
+(defnx1 nx1-set-schar ((set-schar)) (s i v)
+  (make-acode (%nx1-operator %set-sbchar) (nx1-form s) (nx1-form i) (nx1-form v)))
+
+
+
+(defnx1 nx1-%set-schar ((%set-schar)) (arg idx char &environment env)
+  (let* ((arg (nx-transform arg env))
+         (idx (nx-transform idx env))
+         (char (nx-transform char env))
+         (argvar (make-symbol "ARG"))
+         (idxvar (make-symbol "IDX"))
+         (charvar (make-symbol "CHAR")))
+    (nx1-form `(let* ((,argvar ,arg)
+                      (,idxvar ,idx)
+                      (,charvar ,char))
+                 (declare (optimize (speed 3) (safety 0)))
+                 (declare (simple-base-string ,argvar))
+                 (setf (schar ,argvar ,idxvar) ,charvar))
+              env)))
+
+(defnx1 nx1-%set-scharcode ((%set-scharcode)) (s i v)
+    (make-acode (%nx1-operator %set-scharcode)
+                (nx1-form s)
+                (nx1-form i)
+                (nx1-form v)))
+              
+
+(defnx1 nx1-list-vector-values ((list) (vector) (values) (%temp-list)) (&rest args)
+  (make-acode (%nx1-default-operator) (nx1-formlist args)))
+
+
+
+(defnx1 nx1-%gvector ( (%gvector)) (&rest args)
+  (make-acode (%nx1-operator %gvector) (nx1-arglist args)))
+
+(defnx1 nx1-quote quote (form)
+  (nx1-immediate form))
+
+(defnx1 nx1-list* ((list*)) (first &rest rest)
+  (make-acode (%nx1-operator list*) (nx1-arglist (cons first rest) 1)))
+
+
+#|
+(defnx1 nx1-append ((append)) (&rest args)
+  (make-acode (%nx1-operator append) (nx1-arglist args 2)))
+
+
+|#
+
+(defnx1 nx1-or or (&whole whole &optional (firstform nil firstform-p) &rest moreforms)
+  (if (not firstform-p)
+    (nx1-form nil)
+    (if (null moreforms)
+      (nx1-form firstform)
+      (progn
+        (make-acode (%nx1-operator or) (nx1-formlist (%cdr whole)))))))
+
+(defun nx1-1d-vref (env arr dim0 &optional uvref-p)
+  (let* ((simple-vector-p (nx-form-typep arr 'simple-vector env))
+         (string-p (unless simple-vector-p 
+                     (if (nx-form-typep arr 'string env)
+                       (or (nx-form-typep arr 'simple-string env)
+                           (return-from nx1-1d-vref (nx1-form `(char ,arr ,dim0)))))))
+         (simple-1d-array-p (unless (or simple-vector-p string-p) 
+                              (nx-form-typep arr '(simple-array * (*)) env)))
+         
+         (array-type (specifier-type  (nx-form-type arr env)))
+         (type-keyword (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        array-type)))
+    (if (and simple-1d-array-p type-keyword)
+      (make-acode (%nx1-operator %typed-uvref) 
+                  (nx1-immediate type-keyword)
+                  (nx1-form arr)
+                  (nx1-form dim0))
+      (let* ((op (cond (simple-1d-array-p (%nx1-operator uvref))
+                       (string-p (%nx1-operator %sbchar))
+                       (simple-vector-p 
+                        (if (nx-inhibit-safety-checking env) (%nx1-operator %svref) (%nx1-operator svref)))
+                       (uvref-p (%nx1-operator uvref))
+                       (t (%nx1-operator %aref1)))))
+        (make-acode op (nx1-form arr) (nx1-form dim0))))))
+  
+(defnx1 nx1-aref ((aref)) (&whole whole &environment env arr &optional (dim0 nil dim0-p)
+                                  &rest other-dims)
+   (if (and dim0-p (null other-dims))
+     (nx1-1d-vref env arr dim0)
+     (nx1-treat-as-call whole)))
+
+(defnx1 nx1-uvref ((uvref)) (&environment env arr dim0)
+  (nx1-1d-vref env arr dim0 t))
+
+(defnx1 nx1-%aref2 ((%aref2)) (&whole whole &environment env arr i j)
+  ;; Bleah.  Breaks modularity.  Specialize later.
+  (target-arch-case
+   (:x8632
+    (return-from nx1-%aref2 (nx1-treat-as-call whole))))
+
+  (let* ((arch (backend-target-arch *target-backend*))
+         (ctype (specifier-type (nx-form-type arr env)))
+         (atype (if (csubtypep ctype (specifier-type '(array * (* *)))) ctype))
+         (simple-atype (if (and atype
+                                (csubtypep atype (specifier-type '(simple-array * (* *)))))
+                         atype))
+         (type-keyword (if atype
+                         (funcall
+                          (arch::target-array-type-name-from-ctype-function arch)
+                          atype))))
+    (if (and type-keyword simple-atype)
+      (let* ((dims (array-ctype-dimensions atype))
+             (dim0 (car dims))
+             (dim1 (cadr dims)))
+        (make-acode (%nx1-operator simple-typed-aref2)
+                    (nx1-form type-keyword)
+                    (nx1-form arr)
+                    (nx1-form i)
+                    (nx1-form j)
+                    (nx1-form (if (typep dim0 'fixnum) dim0))
+                    (nx1-form (if (typep dim1 'fixnum) dim1))))
+      (make-acode (%nx1-operator general-aref2)
+                  (nx1-form arr)
+                  (nx1-form i)
+                  (nx1-form j)))))
+
+(defnx1 nx1-%aref3 ((%aref3)) (&whole whole &environment env arr i j k)
+  ;; Bleah.  Breaks modularity.  Specialize later.
+  (target-arch-case
+   (:x8632
+    (return-from nx1-%aref3 (nx1-treat-as-call whole))))
+
+  (let* ((arch (backend-target-arch *target-backend*))
+         (ctype (specifier-type (nx-form-type arr env)))
+         (atype (if (csubtypep ctype (specifier-type '(array * (* * *)))) ctype))
+         (simple-atype (if (and atype
+                                (csubtypep atype (specifier-type '(simple-array * (* * *)))))
+                         atype))
+         (type-keyword (if atype
+                         (funcall
+                          (arch::target-array-type-name-from-ctype-function arch)
+                          atype))))
+    (if (and type-keyword simple-atype)
+      (let* ((dims (array-ctype-dimensions atype))
+             (dim0 (car dims))
+             (dim1 (cadr dims))
+             (dim2 (caddr dims)))
+        (make-acode (%nx1-operator simple-typed-aref3)
+                    (nx1-form type-keyword)
+                    (nx1-form arr)
+                    (nx1-form i)
+                    (nx1-form j)
+                    (nx1-form k)
+                    (nx1-form (if (typep dim0 'fixnum) dim0))
+                    (nx1-form (if (typep dim1 'fixnum) dim1))
+                    (nx1-form (if (typep dim2 'fixnum) dim2))))
+      (make-acode (%nx1-operator general-aref3)
+                  (nx1-form arr)
+                  (nx1-form i)
+                  (nx1-form j)
+                  (nx1-form k)))))
+
+(defun nx1-1d-vset (arr newval dim0 env)
+  (let* ((simple-vector-p (nx-form-typep arr 'simple-vector env))
+         (string-p (unless simple-vector-p 
+                     (if (nx-form-typep arr 'string env)
+                       (or (nx-form-typep arr 'simple-string env)
+                           (return-from nx1-1d-vset (nx1-form `(set-char ,arr ,newval ,dim0)))))))
+         (simple-1d-array-p (unless (or simple-vector-p string-p) 
+                              (nx-form-typep arr '(simple-array * (*)) env)))
+         (array-type (specifier-type  (nx-form-type arr env)))
+         (type-keyword (funcall
+                        (arch::target-array-type-name-from-ctype-function
+                         (backend-target-arch *target-backend*))
+                        array-type)))
+         (if (and type-keyword simple-1d-array-p)
+             (make-acode (%nx1-operator %typed-uvset) 
+                         (nx1-immediate type-keyword)
+                         (nx1-form arr)
+                         (nx1-form newval)
+                         (nx1-form dim0))
+             (let* ((op (cond (simple-1d-array-p (%nx1-operator uvset))
+                              (string-p (%nx1-operator %set-sbchar))
+                              (simple-vector-p (if (nx-inhibit-safety-checking env) (%nx1-operator %svset) (%nx1-operator svset)))
+                              (t (%nx1-operator aset1)))))
+               (if op
+                   (make-acode
+                    op
+                    (nx1-form arr)
+                    (nx1-form newval)
+                    (nx1-form dim0))
+                   (nx1-form `(,(if string-p 'set-schar '%aset1) ,arr ,newval ,dim0)))))))
+
+(defnx1 nx1-aset ((aset)) (&whole whole 
+                                  arr newval 
+                                  &optional (dim0 nil dim0-p)
+                                  &environment env
+                                  &rest other-dims)
+   (if (and dim0-p (null other-dims))
+       (nx1-1d-vset arr newval dim0 env)
+       (nx1-treat-as-call whole)))
+            
+(defnx1 nx1-%aset2 ((%aset2)) (&whole whole &environment env arr i j new)
+  ;; Bleah.  Breaks modularity.  Specialize later.
+  (target-arch-case
+   (:x8632
+    (return-from nx1-%aset2 (nx1-treat-as-call whole))))
+
+  (let* ((arch (backend-target-arch *target-backend*))
+         (ctype (specifier-type (nx-form-type arr env)))
+         (atype (if (csubtypep ctype (specifier-type '(array * (* *)))) ctype))
+         (simple-atype (if (and atype
+                                (csubtypep atype (specifier-type '(simple-array * (* *)))))
+                         atype))
+         (type-keyword (if atype
+                         (funcall
+                          (arch::target-array-type-name-from-ctype-function arch)
+                          atype))))
+
+    (if (and type-keyword simple-atype)
+      (let* ((dims (array-ctype-dimensions atype))
+             (dim0 (car dims))
+             (dim1 (cadr dims)))
+        (make-acode (%nx1-operator simple-typed-aset2)
+                    (nx1-form type-keyword)
+                    (nx1-form arr)
+                    (nx1-form i)
+                    (nx1-form j)
+                    (nx1-form new)
+                    (nx1-form (if (typep dim0 'fixnum) dim0))
+                    (nx1-form (if (typep dim1 'fixnum) dim1))))
+            (make-acode (%nx1-operator general-aset2)
+                  (nx1-form arr)
+                  (nx1-form i)
+                  (nx1-form j)
+                  (nx1-form new)))))
+
+(defnx1 nx1-%aset3 ((%aset3)) (&whole whole &environment env arr i j k new)
+  ;; Bleah.  Breaks modularity.  Specialize later.
+  (target-arch-case
+   (:x8632
+    (return-from nx1-%aset3 (nx1-treat-as-call whole))))
+
+  (let* ((arch (backend-target-arch *target-backend*))
+         (ctype (specifier-type (nx-form-type arr env)))
+         (atype (if (csubtypep ctype (specifier-type '(array * (* * *)))) ctype))
+         (simple-atype (if (and atype
+                                (csubtypep atype (specifier-type '(simple-array * (* * *)))))
+                         atype))
+         (type-keyword (if atype
+                         (funcall
+                          (arch::target-array-type-name-from-ctype-function arch)
+                          atype))))
+
+    (if (and type-keyword simple-atype)
+      (let* ((dims (array-ctype-dimensions atype))
+             (dim0 (car dims))
+             (dim1 (cadr dims))
+             (dim2 (caddr dims)))
+        (make-acode (%nx1-operator simple-typed-aset3)
+                    (nx1-form type-keyword)
+                    (nx1-form arr)
+                    (nx1-form i)
+                    (nx1-form j)
+                    (nx1-form k)
+                    (nx1-form new)
+                    (nx1-form (if (typep dim0 'fixnum) dim0))
+                    (nx1-form (if (typep dim1 'fixnum) dim1))
+                    (nx1-form (if (typep dim2 'fixnum) dim2))))
+            (make-acode (%nx1-operator general-aset3)
+                  (nx1-form arr)
+                  (nx1-form i)
+                  (nx1-form j)
+                  (nx1-form k)
+                  (nx1-form new)))))
+
+(defnx1 nx1-prog1 (prog1 multiple-value-prog1) (save &body args 
+                                                     &aux (l (list (nx1-form save))))
+  (make-acode 
+   (%nx1-default-operator) 
+   (dolist (arg args (nreverse l))
+     (push (nx1-form arg) l))))
+
+(defnx1 nx1-if if (test true &optional false)
+  (if (null true)
+    (if (null false)
+      (return-from nx1-if (nx1-form `(progn ,test nil)))
+      (psetq test `(not ,test) true false false true)))
+  (let ((test-form (nx1-form test))
+        ;; Once hit a conditional, no more duplicate warnings
+        (*compiler-warn-on-duplicate-definitions* nil))
+    (make-acode (%nx1-operator if) test-form (nx1-form true) (nx1-form false))))
+
+(defnx1 nx1-%debug-trap dbg (&optional arg)
+  (make-acode (%nx1-operator %debug-trap) (nx1-form arg)))
+        
+(defnx1 nx1-setq setq (&whole whole &rest args &environment env &aux res)
+  (when (%ilogbitp 0 (length args))
+    (nx-error "Odd number of forms in ~s ." whole))
+  (while args
+    (let* ((sym (nx-need-var (%car args) nil))
+           (val (%cadr args))
+           (declared-type (nx-declared-type sym env)))
+      (when (nx-declarations-typecheck env)
+        (unless (or (eq declared-type t)
+                    (and (consp val) (eq (%car val) 'the) (equal (cadr val) declared-type)))
+          (setq val `(the ,declared-type ,val))
+          (nx-note-source-transformation (caddr val) val)))
+      (multiple-value-bind (expansion win) (macroexpand-1 sym env)
+	(if win
+            (push (nx1-form `(setf ,expansion ,val)) res)
+            (multiple-value-bind (info inherited catchp)
+		(nx-lex-info sym)
+	      (push
+	       (if (eq info :symbol-macro)
+		   (progn
+		     (nx-set-var-bits catchp
+				      (%ilogior
+				       (%ilsl $vbitsetq 1)
+				       (%ilsl $vbitreffed 1)
+				       (nx-var-bits catchp)))
+		     (nx1-form `(setf ,inherited ,val)))
+		   (let ((valtype (nx-form-type val env)))
+		     (let ((*nx-form-type* declared-type))
+		       (setq val (nx1-typed-form val env)))
+		     (if (and info (neq info :special))
+			 (progn
+			   (nx1-check-assignment sym env)
+			   (let ((inittype (var-inittype info)))
+			     (if (and inittype (not (subtypep valtype inittype)))
+				 (setf (var-inittype info) nil)))
+			   (if inherited
+			       (nx-set-var-bits info (%ilogior (%ilsl $vbitsetq 1)
+							       (%ilsl $vbitnoreg 1) ; I know, I know ... Someday ...
+							       (nx-var-bits info)))
+			       (nx-set-var-bits info (%ilogior2 (%ilsl $vbitsetq 1) (nx-var-bits info))))
+			   (nx-adjust-setq-count info 1 catchp) ; In the hope that that day will come ...
+			   (make-acode (%nx1-operator setq-lexical) info val))
+			 (make-acode
+			  (if (nx1-check-special-ref sym info)
+			      (progn
+				(nx-record-xref-info :references sym)
+				(nx-record-xref-info :sets sym)
+			        (if (nx-global-p sym env)
+			          (%nx1-operator global-setq)
+			          (%nx1-operator setq-special)))
+			    (%nx1-operator setq-free)) ; Screw: no object lisp.  Still need setq-free ? For constants ?
+			  (nx1-note-vcell-ref sym)
+			  val))))
+	       res)))
+	(setq args (%cddr args)))))
+  (make-acode (%nx1-operator progn) (nreverse res)))
+
+;;; See if we're trying to setq something that's currently declared "UNSETTABLE"; whine if so.
+;;; If we find a contour in which a "SETTABLE NIL" vdecl for the variable exists, whine.
+;;; If we find a contour in which a "SETTABLE T" vdecl for the variable exists. or
+;;;    the contour in which the variable's bound, return nil.
+;;; Should find something ...
+(defun nx1-check-assignment (sym env)
+  (loop
+    (unless (and env (istruct-typep env 'lexical-environment))
+      (return))
+    (dolist (decl (lexenv.vdecls env))
+      (when (and (eq (car decl) sym)
+               (eq (cadr decl) 'settable))
+        (unless (cddr decl)
+          (nx1-whine :unsettable sym))
+        (return-from nx1-check-assignment nil)))
+    (let ((vars (lexenv.variables env)))
+      (unless (atom vars)
+        (dolist (var vars)
+          (when (eq (var-name var) sym) (return-from nx1-check-assignment nil)))))
+    (setq env (lexenv.parent-env env))))
+
+;;; The cleanup issue is a little vague (ok, it's a -lot- vague) about the environment in
+;;; which the load-time form is defined, although it apparently gets "executed in a null
+;;; lexical environment".  Ignoring the fact that it's meaningless to talk of executing
+;;; something in a lexical environment, we can sort of infer that it must also be defined
+;;; in a null lexical environment.
+
+(defnx1 nx1-load-time-value (load-time-value) (&environment env form &optional read-only-p)
+  ;; Validate the "read-only-p" argument
+  (if (and read-only-p (neq read-only-p t)) (require-type read-only-p '(member t nil)))
+  ;; Then ignore it.
+  (if *nx-load-time-eval-token*
+    (multiple-value-bind (function warnings)
+                         (compile-named-function 
+                          `(lambda () ,form)
+                          ;; pass in the definition env for special decls
+                          :env (definition-environment env)
+                          :load-time-eval-token *nx-load-time-eval-token*
+                          :target (backend-name *target-backend*))
+      (setq *nx-warnings* (append *nx-warnings* warnings))
+      (nx1-immediate (list *nx-load-time-eval-token* `(funcall ,function))))
+    (nx1-immediate (eval form))))
+
+(defnx1 nx1-catch (catch) (operation &body body)
+  (make-acode (%nx1-operator catch) (nx1-form operation) (nx1-catch-body body)))
+
+(defnx1 nx1-%badarg ((%badarg)) (badthing right-type &environment env)
+  (make-acode (%nx1-operator %badarg2) 
+              (nx1-form badthing) 
+              (nx1-form (or (if (nx-form-constant-p right-type env) (%typespec-id (nx-form-constant-value right-type env)))
+			    right-type))))
+
+(defnx1 nx1-unwind-protect (unwind-protect) (protected-form &body cleanup-form)
+  (if cleanup-form
+    (make-acode (%nx1-operator unwind-protect) 
+                (nx1-catch-body (list protected-form))
+                (nx1-progn-body cleanup-form))
+    (nx1-form protected-form)))
+
+(defnx1 nx1-progv progv (symbols values &body body)
+  (make-acode (%nx1-operator progv) 
+              (nx1-form `(check-symbol-list ,symbols))
+              (nx1-form values) 
+              (nx1-catch-body body)))
+
+(defun nx1-catch-body (body)
+  (let* ((temp (new-lexical-environment *nx-lexical-environment*)))
+    (setf (lexenv.variables temp) 'catch)
+    (let* ((*nx-lexical-environment* (new-lexical-environment temp)))
+      (nx1-progn-body body))))
+
+
+(defnx1 nx1-apply ((apply)) (&whole call fn arg &rest args &environment env)
+  (let ((last (%car (last (push arg args)))))
+    (if (and (nx-form-constant-p last env)
+	     (null (nx-form-constant-value last env)))
+      (nx1-form (let ((new `(funcall ,fn ,@(butlast args))))
+		  (nx-note-source-transformation call new)
+		  new))
+      (nx1-apply-fn fn args t))))
+
+(defnx1 nx1-%apply-lexpr ((%apply-lexpr)) (fn arg &rest args)
+  (nx1-apply-fn fn (cons arg args) 0))
+
+(defun nx1-apply-fn (fn args spread)
+  (let* ((sym (nx1-func-name fn))
+	 (afunc (and (non-nil-symbol-p sym) (nth-value 1 (nx-lexical-finfo sym)))))
+    (when (and afunc (eq afunc *nx-call-next-method-function*))
+      (setq fn (let ((new (list 'quote (if (or (car args) (cdr args))
+					 '%call-next-method-with-args
+					 '%call-next-method))))
+		 (nx-note-source-transformation fn new)
+		 new)
+	    sym nil
+	    args (cons (var-name *nx-next-method-var*) args)))
+    (nx1-typed-call (if (non-nil-symbol-p sym) sym (nx1-form fn)) args spread)))
+
+
+(defnx1 nx1-%defun %defun (&whole w def &optional (doc nil doc-p) &environment env)
+  (declare (ignorable doc doc-p))
+  ; Pretty bogus.
+  (if (and (consp def)
+           (eq (%car def) 'nfunction)
+           (consp (%cdr def))
+           (or (symbolp (%cadr def)) (setf-function-name-p (%cadr def))))
+    (note-function-info (%cadr def) (caddr def) env))
+  (nx1-treat-as-call w))
+
+
+(defnx1 nx1-function function (arg &aux fn afunc)
+  (if (symbolp arg)
+    (progn
+      (when (macro-function arg *nx-lexical-environment*)
+        (nx-error
+         "~S can't be used to reference lexically visible macro ~S." 
+         'function arg))
+      (if (multiple-value-setq (fn afunc) (nx-lexical-finfo arg))
+        (progn
+          (when afunc 
+            (incf (afunc-fn-refcount afunc))
+            (when (%ilogbitp $fbitbounddownward (afunc-bits afunc))
+              (incf (afunc-fn-downward-refcount afunc))))
+          (nx1-symbol (%cddr fn)))
+        (progn
+          (while (setq fn (assq arg *nx-synonyms*))
+            (setq arg (%cdr fn)))
+          (nx1-form `(%function ',arg)))))
+    (if (and (consp arg) (eq (%car arg) 'setf))
+      (nx1-form `(function ,(nx-need-function-name arg)))
+      (nx1-ref-inner-function nil arg))))
+
+(defnx1 nx1-nfunction nfunction (name def)
+ (nx1-ref-inner-function name def))
+
+(defun nx1-ref-inner-function (name def &optional afunc)
+  (setq afunc (nx1-compile-inner-function name def afunc))
+  (setf (afunc-fn-refcount afunc) 1)
+  (nx1-afunc-ref afunc))
+
+(defun nx1-compile-inner-function (name def p
+                                        &optional (env *nx-lexical-environment*)
+                                        &aux (q *nx-current-function*))
+  (unless p (setq p (make-afunc)))
+  (setf (afunc-parent p) q)
+  (setf (afunc-parent q) *nx-parent-function*)
+  (setf (afunc-tags q) *nx-tags*)
+  (setf (afunc-blocks q) *nx-blocks*)
+  (setf (afunc-inner-functions q) (push p *nx-inner-functions*))
+  (setf (lexenv.lambda env) q)
+  (if *nx-current-code-note*
+    (let* ((*nx-current-code-note* (nx-ensure-code-note def *nx-current-code-note*)))
+      (nx1-compile-lambda name def p q env *nx-current-compiler-policy* *nx-load-time-eval-token*)) ;returns p.
+    (nx1-compile-lambda name def p q env *nx-current-compiler-policy* *nx-load-time-eval-token*)))
+
+(defun nx1-afunc-ref (afunc)
+  (let ((op (if (afunc-inherited-vars afunc)
+              (%nx1-operator closed-function)
+              (%nx1-operator simple-function)))
+        (ref (acode-unwrapped-form (afunc-ref-form afunc))))
+    (if ref
+      (%rplaca ref op) ; returns ref
+      (setf (afunc-ref-form afunc)
+            (make-acode
+             op
+             afunc)))))
+    
+(defnx1 nx1-%function %function (form &aux symbol)
+  (let ((sym (nx1-form form)))
+    (if (and (eq (car sym) (%nx1-operator immediate))
+             (setq symbol (cadr sym))
+             (symbolp symbol))
+      (let ((env *nx-lexical-environment*))
+	(unless (or (nx1-find-call-def symbol env)
+		    (find-ftype-decl symbol env)
+		    (eq symbol *nx-global-function-name*))
+	  (nx1-whine :undefined-function symbol))
+        (make-acode (%nx1-default-operator) symbol))
+      (make-acode (%nx1-operator call) (nx1-immediate '%function) (list nil (list sym))))))
+
+(defnx1 nx1-tagbody tagbody (&rest args)
+  (let* ((newtags nil)
+         (*nx-lexical-environment* (new-lexical-environment *nx-lexical-environment*))
+	 (pending (make-pending-declarations))
+         (*nx-bound-vars* *nx-bound-vars*)
+         (catchvar (nx-new-temp-var pending "tagbody-catch-tag"))
+         (indexvar (nx-new-temp-var pending "tagbody-tag-index"))
+         (counter (list 0))
+         (looplabel (cons nil nil))
+         (*nx-tags* *nx-tags*))
+    (dolist (form args)
+      (when (atom form)
+        (if (or (symbolp form) (integerp form))
+          (if (assoc form newtags)
+            (nx-error "Duplicate tag in TAGBODY: ~S." form)
+            (push (list form nil counter catchvar nil nil) newtags))
+          (nx-error "Illegal form in TAGBODY: ~S." form))))
+    (dolist (tag (setq newtags (nreverse newtags)))
+      (push tag *nx-tags*))
+    (let* ((body nil)
+           (*nx-loop-nesting-level* (1+ *nx-loop-nesting-level*)))
+      (dolist (form args (setq body (nreverse body)))
+        (push 
+         (if (atom form)
+           (let ((info (nx-tag-info form)))
+             (%rplaca (%cdr (%cdr (%cdr (%cdr info)))) t)
+             (cons (%nx1-operator tag-label) info))
+           (nx1-form form))
+         body))
+      (if (eq 0 (%car counter))
+        (make-acode (%nx1-operator local-tagbody) newtags body)
+        (progn
+          (nx-set-var-bits catchvar (logior (nx-var-bits catchvar)
+                                            (%ilsl $vbitdynamicextent 1)))
+          (nx-inhibit-register-allocation)   ; There are alternatives ...
+          (dolist (tag (reverse newtags))
+            (when (%cadr tag)
+              (push  
+               (nx1-form `(if (eql ,(var-name indexvar) ,(%cadr tag)) (go ,(%car tag))))
+               body)))
+          (make-acode
+           (%nx1-operator let*)
+           (list catchvar indexvar)
+           (list (make-acode (%nx1-operator cons) *nx-nil* *nx-nil*) *nx-nil*)
+           (make-acode
+            (%nx1-operator local-tagbody)
+            (list looplabel)
+            (list
+             (cons (%nx1-operator tag-label) looplabel)
+             (make-acode
+              (%nx1-operator if)
+              (make-acode 
+               (%nx1-operator setq-lexical)
+               indexvar
+               (make-acode 
+                (%nx1-operator catch)
+                (nx1-form (var-name catchvar)) 
+                (make-acode
+                 (%nx1-operator local-tagbody)
+                 newtags
+                 body)))
+              (make-acode (%nx1-operator local-go) looplabel)
+              *nx-nil*)))
+           0))))))
+
+
+
+(defnx1 nx1-go go (tag)
+  (multiple-value-bind (info closed)
+                       (nx-tag-info tag)
+    (unless info (nx-error "Can't GO to tag ~S." tag))
+    (if (not closed)
+      (let ((defnbackref (cdr (cdr (cdr (cdr info))))))
+        (if (car defnbackref) 
+          (rplaca (cdr defnbackref) t))
+        (make-acode (%nx1-operator local-go) info))
+      (progn
+
+        (make-acode
+         (%nx1-operator throw) (nx1-symbol (var-name (cadddr info))) (nx1-form closed))))))
+
+
+
+
+;;; address-expression should return a fixnum; that's our little
+;;; secret.  result spec can be NIL, :void, or anything that an
+;;; arg-spec can be.  arg-spec can be :double, :single, :address,
+;;; :signed-doubleword, :unsigned-doubleword, :signed-fullword,
+;;; :unsigned-fullword, :signed-halfword, :unsigned-halfword,
+;;; :signed-byte, or :unsigned-byte
+;;; On ppc64, :hybrid-int-float, :hybrid-float-float, and :hybrid-float-int
+;;; can also be used to express some struct-by-value cases.
+
+(defparameter *arg-spec-keywords*
+  '(:double-float :single-float :address :signed-doubleword
+    :unsigned-doubleword :signed-fullword :unsigned-fullword
+    :signed-halfword :unsigned-halfword :signed-byte :unsigned-byte
+    :hybrid-int-float :hybrid-float-int :hybrid-float-float))
+
+
+(defnx1 nx1-ff-call ((%ff-call)) (address-expression &rest arg-specs-and-result-spec)
+   (nx1-ff-call-internal
+    address-expression arg-specs-and-result-spec
+    (ecase (backend-name *target-backend*)
+      (:linuxppc32 (%nx1-operator eabi-ff-call))
+      ((:darwinppc32 :linuxppc64 :darwinppc64) (%nx1-operator poweropen-ff-call))
+      ((:darwinx8632 :linuxx8632 :win32 :solarisx8632 :freebsdx8632) (%nx1-operator i386-ff-call))
+      ((:linuxx8664 :freebsdx8664 :darwinx8664 :solarisx8664 :win64) (%nx1-operator ff-call)))))
+
+(defnx1 nx1-syscall ((%syscall)) (idx &rest arg-specs-and-result-spec)
+  (flet ((map-to-representation-types (list)
+           (collect ((out))
+             (do* ((l list (cddr l)))
+                  ((null (cdr l))
+                   (if l
+                     (progn
+                       (out (foreign-type-to-representation-type (car l)))
+                       (out))
+                     (error "Missing result type in ~s" list)))
+               (out (foreign-type-to-representation-type (car l)))
+               (out (cadr l))))))
+          (nx1-ff-call-internal	
+           idx (map-to-representation-types arg-specs-and-result-spec)
+           (ecase (backend-name *target-backend*)
+             (:linuxppc32 (%nx1-operator eabi-syscall))
+             ((:darwinppc32 :darwinppc64 :linuxppc64)
+              (%nx1-operator poweropen-syscall))
+	     ((:darwinx8632 :linuxx632 :win32) (%nx1-operator i386-syscall))
+             ((:linuxx8664 :freebsdx8664 :darwinx8664 :solarisx8664 :win64) (%nx1-operator syscall))))))
+
+(defun nx1-ff-call-internal (address-expression arg-specs-and-result-spec operator )
+  (let* ((specs ())         
+         (vals ())
+         (register-spec-seen nil)
+         (arg-specs (butlast arg-specs-and-result-spec))
+         (result-spec (car (last arg-specs-and-result-spec))))
+    (unless (evenp (length arg-specs))
+      (error "odd number of arg-specs"))
+    (loop
+      (when (null arg-specs) (return))
+      (let* ((arg-keyword (pop arg-specs))
+	     (value (pop arg-specs)))
+        (if (or (memq arg-keyword *arg-spec-keywords*)
+		(typep arg-keyword 'unsigned-byte))
+          (progn 
+            (push arg-keyword specs)
+            (push value vals))
+          (if (eq arg-keyword :registers)
+            (if register-spec-seen
+              (error "duplicate :registers in ~s" arg-specs-and-result-spec)
+              (progn
+                (setq register-spec-seen t)
+                (push arg-keyword specs)
+                (push value vals)))
+            (error "Unknown argument spec: ~s" arg-keyword)))))
+    (unless (or (eq result-spec :void)
+		(memq result-spec *arg-spec-keywords*))
+      (error "Unknown result spec: ~s" result-spec))
+    (make-acode operator
+		(nx1-form address-expression)
+		(nreverse specs)
+		(mapcar #'nx1-form (nreverse vals))
+		result-spec
+		nil)))
+  
+(defnx1 nx1-block block (blockname &body forms)
+  (let* ((*nx-blocks* *nx-blocks*)
+         (*nx-lexical-environment* (new-lexical-environment *nx-lexical-environment*))
+         (*nx-bound-vars* *nx-bound-vars*)
+         (tagvar (nx-new-temp-var (make-pending-declarations)))
+         (thisblock (cons (setq blockname (nx-need-sym blockname)) tagvar))
+         (body nil))
+    (push thisblock *nx-blocks*)
+    (setq body (nx1-progn-body forms))
+    (%rplacd thisblock nil)
+    (let ((tagbits (nx-var-bits tagvar)))
+      (if (not (%ilogbitp $vbitclosed tagbits))
+        (if (neq 0 (%ilogand $vrefmask tagbits))
+          (make-acode 
+           (%nx1-operator local-block)
+           thisblock
+           body)
+          body)
+        (progn
+          (nx-set-var-bits tagvar (%ilogior (%ilsl $vbitdynamicextent 1) tagbits))
+          (nx-inhibit-register-allocation)   ; Could also set $vbitnoreg in all setqed vars, or keep track better
+          (make-acode
+           (%nx1-operator local-block)
+           thisblock
+           (make-acode
+            (%nx1-operator let)
+            (list tagvar)
+            (list (make-acode (%nx1-operator cons) (nx1-form nil) (nx1-form nil)))
+            (make-acode
+             (%nx1-operator catch)
+             (nx-make-lexical-reference tagvar)
+             body)
+            0)))))))
+
+(defnx1 nx1-return-from return-from (blockname &optional value)
+  (multiple-value-bind (info closed)
+                       (nx-block-info (setq blockname (nx-need-sym blockname)))
+    (unless info (nx-error "Can't RETURN-FROM block : ~S." blockname))
+    (unless closed (nx-adjust-ref-count (cdr info)))
+    (make-acode 
+     (if closed
+       (%nx1-operator throw)
+       (%nx1-operator local-return-from))
+     (if closed
+       (nx1-symbol (var-name (cdr info)))
+       info)
+     (nx1-form value))))
+
+(defnx1 nx1-funcall ((funcall)) (&whole call func &rest args &environment env)
+  (let ((name (nx1-func-name func)))
+    (if (or (null name)
+	    (and (symbolp name) (macro-function name env)))
+      (nx1-typed-call (nx1-form func) args nil)
+      (progn
+	(when (consp name) ;; lambda expression
+	  (nx-note-source-transformation func name))
+	;; This picks up call-next-method evil.
+	(nx1-form (let ((new-form (cons name args)))
+		    (nx-note-source-transformation call new-form)
+		    new-form))))))
+
+(defnx1 nx1-multiple-value-call multiple-value-call (value-form &rest args)
+  (make-acode (%nx1-default-operator)
+              (nx1-form value-form)
+              (nx1-formlist args)))
+
+(defnx1 nx1-compiler-let compiler-let (bindings &body forms)
+  (let* ((vars nil)
+         (varinits nil))
+    (dolist (pair bindings)
+      (push (nx-pair-name pair) vars)
+      (push (eval (nx-pair-initform pair)) varinits))
+   (progv (nreverse vars) (nreverse varinits) (nx1-catch-body forms))))
+
+(defnx1 nx1-fbind fbind (fnspecs &body body &environment old-env)
+  (let* ((fnames nil)
+         (vars nil)
+         (vals nil))
+    (dolist (spec fnspecs (setq vals (nreverse vals)))
+      (destructuring-bind (fname initform) spec
+        (push (setq fname (nx-need-function-name fname)) fnames)
+        (push (nx1-form initform) vals)))
+    (let* ((new-env (new-lexical-environment old-env))
+           (*nx-bound-vars* *nx-bound-vars*)
+           (*nx-lexical-environment* new-env)
+	   (pending (make-pending-declarations)))
+      (dolist (fname fnames)        
+        (let ((var (nx-new-var pending (make-symbol (symbol-name fname)))))
+          (nx-set-var-bits var (%ilogior (%ilsl $vbitignoreunused 1)
+                                         (nx-var-bits var)))
+          (let ((afunc (make-afunc)))
+            (setf (afunc-bits afunc) (%ilsl $fbitruntimedef 1))
+            (setf (afunc-lfun afunc) var)
+            (push var vars)
+            (push (cons fname (cons 'function (cons afunc (var-name var)))) (lexenv.functions new-env)))))
+      (make-acode
+       (%nx1-operator let)
+       vars
+       vals
+       (nx1-env-body body old-env)
+       *nx-new-p2decls*))))
+
+(defun maybe-warn-about-nx1-alphatizer-binding (funcname)
+  (when (and (symbolp funcname)
+             (gethash funcname *nx1-alphatizers*))
+    (nx1-whine :special-fbinding funcname)))
+
+(defnx1 nx1-flet flet (defs &body forms)
+  (with-nx-declarations (pending)
+    (let* ((env *nx-lexical-environment*)
+           (*nx-lexical-environment* env)
+           (*nx-bound-vars* *nx-bound-vars*)
+           (new-env (new-lexical-environment env))
+           (names nil)
+           (funcs nil)
+           (pairs nil)
+           (fname nil)
+           (name nil))
+      (multiple-value-bind (body decls) (parse-body forms env nil)
+        (nx-process-declarations pending decls)
+        (dolist (def defs (setq names (nreverse names) funcs (nreverse funcs)))
+          (destructuring-bind (funcname lambda-list &body flet-function-body) def
+            (setq fname (nx-need-function-name funcname))
+            (maybe-warn-about-nx1-alphatizer-binding funcname)
+            (multiple-value-bind (body decls)
+                                 (parse-body flet-function-body env)
+              (let ((func (make-afunc))
+                    (expansion `(lambda ,lambda-list
+                                  ,@decls
+                                  (block ,(if (consp funcname) (%cadr funcname) funcname)
+                                    ,@body))))
+                (nx-note-source-transformation def expansion)
+                (setf (afunc-environment func) env
+                      (afunc-lambdaform func) expansion)
+                (push func funcs)
+                (when (and *nx-next-method-var*
+                             (eq funcname 'call-next-method)
+                             (null *nx-call-next-method-function*))
+                    (setq *nx-call-next-method-function* func))             
+                (push (cons funcname func) pairs)
+                (if (consp funcname)
+                  (setq funcname fname))
+                (push (setq name (make-symbol (symbol-name funcname))) names)
+                (push (cons funcname (cons 'function (cons func name))) (lexenv.functions new-env))))))
+        (let ((vars nil)
+              (rvars nil)
+              (rfuncs nil))
+          (dolist (sym names vars) (push (nx-new-var pending sym) vars))
+          (nx-effect-other-decls pending new-env)
+          (setq body (let* ((*nx-lexical-environment* new-env))
+                       (nx1-dynamic-extent-functions vars new-env)
+                       (nx1-env-body body env)))
+          (dolist (pair pairs)
+            (let ((afunc (cdr pair))
+                  (var (pop vars)))
+              (when (or (afunc-callers afunc)
+                        (neq 0 (afunc-fn-refcount afunc))
+                        (neq 0 (afunc-fn-downward-refcount afunc)))
+                (push (nx1-compile-inner-function (%car pair)
+                                                  (afunc-lambdaform afunc)
+                                                  afunc
+                                                  (afunc-environment afunc))
+                      rfuncs)
+                (push var rvars))))
+          (nx-reconcile-inherited-vars rfuncs)
+          (dolist (f rfuncs) (nx1-afunc-ref f))
+          (make-acode
+           (%nx1-operator flet)
+           rvars
+           rfuncs
+           body
+           *nx-new-p2decls*))))))
+
+(defun nx1-dynamic-extent-functions (vars env)
+  (let ((bits nil)
+        (varinfo nil))
+    (dolist (decl (lexenv.fdecls env))
+      (let ((downward-guy (if (eq (cadr decl) 'dynamic-extent) (car decl))))
+        (when downward-guy
+          (multiple-value-bind (finfo afunc) (nx-lexical-finfo downward-guy)
+            (when (and afunc 
+                       (not (%ilogbitp $fbitdownward (setq bits (afunc-bits afunc))))
+                       (setq varinfo (and (consp (%cdr finfo)) (nx-lex-info (%cddr finfo))))
+                       (memq varinfo vars))
+              (setf (afunc-bits afunc) 
+                    (%ilogior 
+                     bits 
+                     (%ilsl $fbitdownward 1)
+                     (%ilsl $fbitbounddownward 1)))
+              (nx-set-var-bits varinfo (%ilogior (%ilsl $vbitdynamicextent 1) (nx-var-bits varinfo))))))))))
+          
+(defnx1 nx1-labels labels (defs &body forms)
+  (with-nx-declarations (pending)
+    (let* ((env *nx-lexical-environment*)
+           (old-env (lexenv.parent-env env))
+           (*nx-bound-vars* *nx-bound-vars*)
+           (func nil)
+           (funcs nil)
+           (funcrefs nil)
+           (bodies nil)
+           (vars nil)
+           (blockname nil)
+           (fname nil)
+           (name nil))
+      (multiple-value-bind (body decls) (parse-body forms env nil)
+        (dolist (def defs (setq funcs (nreverse funcs) bodies (nreverse bodies)))
+          (destructuring-bind (funcname lambda-list &body labels-function-body) def
+            (maybe-warn-about-nx1-alphatizer-binding funcname)
+            (push (setq func (make-afunc)) funcs)
+            (setq blockname funcname)
+            (setq fname (nx-need-function-name funcname))
+            (when (consp funcname)
+              (setq blockname (%cadr funcname) funcname fname))
+            (let ((var (nx-new-var pending (setq name (make-symbol (symbol-name funcname))))))
+              (nx-set-var-bits var (%ilsl $vbitignoreunused 1))
+              (push var vars))
+            (push func funcrefs)
+            (multiple-value-bind (body decls)
+                                 (parse-body labels-function-body old-env)
+              (push (cons funcname (cons 'function (cons func name))) (lexenv.functions env))
+              (let* ((expansion `(lambda ,lambda-list 
+                                   ,@decls 
+                                   (block ,blockname
+                                     ,@body))))
+                (nx-note-source-transformation def expansion)
+                (setf (afunc-lambdaform func) expansion
+                      (afunc-environment func) env)
+                (push (cons funcname expansion)
+                      bodies)))))
+        (nx1-dynamic-extent-functions vars env)
+        (dolist (def bodies)
+          (nx1-compile-inner-function (car def) (cdr def) (setq func (pop funcs))))
+        (nx-process-declarations pending decls)
+        (nx-effect-other-decls pending env)
+        (setq body (nx1-env-body body old-env))
+        (nx-reconcile-inherited-vars funcrefs)
+        (dolist (f funcrefs) (nx1-afunc-ref f))
+        (make-acode
+         (%nx1-operator labels)
+         (nreverse vars)
+         (nreverse funcrefs)
+         body
+         *nx-new-p2decls*)))))
+
+
+
+(defnx1 nx1-set-bit ((%set-bit)) (ptr offset &optional (newval nil newval-p))
+  (unless newval-p (setq newval offset offset 0))
+  (make-acode
+   (%nx1-operator %set-bit)
+   (make-acode (%nx1-operator %macptrptr%) (nx1-form ptr))
+   (nx1-form offset)
+   (nx1-form newval)))
+               
+(defnx1 nx1-set-xxx ((%set-ptr) (%set-long)  (%set-word) (%set-byte)
+                     (%set-unsigned-long) (%set-unsigned-word) (%set-unsigned-byte))
+        (ptr offset &optional (newval nil new-val-p) &aux (op *nx-sfname*))
+  (unless new-val-p (setq newval offset offset 0))
+  (make-acode
+   (%nx1-operator %immediate-set-xxx)
+   (case op
+     (%set-ptr 0)
+     (%set-word 2)
+     (%set-unsigned-word (logior 32 2))
+     (%set-byte 1)
+     (%set-unsigned-byte (logior 32 1))
+     (%set-unsigned-long (logior 32 4))
+     (t 4))
+   (make-acode (%nx1-operator %macptrptr%) (nx1-form ptr))
+   (nx1-form offset)
+   (nx1-form newval)))
+
+(defnx1 nx1-set-64-xxx ((%%set-unsigned-longlong) (%%set-signed-longlong)) 
+        (&whole w ptr offset newval &aux (op *nx-sfname*))
+  (target-word-size-case
+   (32 (nx1-treat-as-call w))
+   (64
+    (make-acode
+     (%nx1-operator %immediate-set-xxx)
+     (case op
+       (%%set-signed-longlong 8)
+       (t (logior 32 8)))
+     (make-acode (%nx1-operator %macptrptr%) (nx1-form ptr))
+     (nx1-form offset)
+     (nx1-form newval)))))
+
+
+(defnx1 nx1-get-bit ((%get-bit)) (ptrform &optional (offset 0))
+  (make-acode
+   (%nx1-operator typed-form)
+   'bit
+   (make-acode
+    (%nx1-operator %get-bit)
+    (make-acode (%nx1-operator %macptrptr%) (nx1-form ptrform))
+    (nx1-form offset))))
+
+(defnx1 nx1-get-64-xxx ((%%get-unsigned-longlong) (%%get-signed-longlong))
+  (&whole w ptrform offsetform)
+  (target-word-size-case
+   (32 (nx1-treat-as-call w))
+   (64
+    (let* ((flagbits (case *nx-sfname*
+                       (%%get-unsigned-longlong 8)
+                       (%%get-signed-longlong (logior 32 8))))
+           (signed (logbitp 5 flagbits)))
+      (make-acode (%nx1-operator typed-form)
+                  (if signed
+                    '(signed-byte 64)
+                    '(unsigned-byte 64))
+                (make-acode 
+                 (%nx1-operator immediate-get-xxx)
+                 flagbits
+                 (make-acode (%nx1-operator %macptrptr%) (nx1-form ptrform))
+                 (nx1-form offsetform)))))))
+
+(defnx1 nx1-get-xxx ((%get-long)  (%get-full-long)  (%get-signed-long)
+                     (%get-fixnum) 
+                     (%get-word) (%get-unsigned-word)
+                     (%get-byte) (%get-unsigned-byte)
+                     (%get-signed-word) 
+                     (%get-signed-byte) 
+                     (%get-unsigned-long))
+  (ptrform &optional (offset 0))
+  (let* ((sfname *nx-sfname*)
+         (flagbits (case sfname
+                     ((%get-long %get-full-long  %get-signed-long) (logior 4 32))
+                     (%get-fixnum (logior 4 32 64))
+		     
+                     ((%get-word %get-unsigned-word) 2)
+                     (%get-signed-word (logior 2 32))
+                     ((%get-byte %get-unsigned-byte) 1)
+                     (%get-signed-byte (logior 1 32))
+                     (%get-unsigned-long 4)))
+         (signed (logbitp 5 flagbits)))
+    (declare (fixnum flagbits))
+    (make-acode (%nx1-operator typed-form)
+                (case (logand 15 flagbits)
+                  (4 (if (logbitp 6 flagbits)
+                       'fixnum
+                       (if signed
+                         '(signed-byte 32)
+                         '(unsigned-byte 32))))
+                  (2 (if signed
+                       '(signed-byte 16)
+                       '(unsigned-byte 16)))
+                  (1 (if signed
+                       '(signed-byte 8)
+                       '(unsigned-byte 8))))
+                (make-acode 
+                 (%nx1-operator immediate-get-xxx)
+                 flagbits
+                 (make-acode (%nx1-operator %macptrptr%) (nx1-form ptrform))
+                 (nx1-form offset)))))
+
+(defnx1 nx1-%get-ptr ((%get-ptr) ) (ptrform &optional (offset 0))
+  (make-acode
+   (%nx1-operator %consmacptr%)
+   (make-acode
+    (%nx1-operator immediate-get-ptr)
+    (make-acode (%nx1-operator %macptrptr%) (nx1-form ptrform))
+    (nx1-form offset))))
+
+(defnx1 nx1-%get-float ((%get-single-float)
+			(%get-double-float)) (ptrform &optional (offset 0))
+  (make-acode
+   (%nx1-operator typed-form)
+   (if (eq *nx-sfname* '%get-single-float)
+     'single-float
+     'double-float)
+   (make-acode
+    (%nx1-default-operator)
+    (make-acode (%nx1-operator %macptrptr%) (nx1-form ptrform))
+    (nx1-form offset))))
+
+(defnx1 nx1-%set-float ((%set-single-float)
+			(%set-double-float)) (ptrform offset &optional (newval nil newval-p))
+  (unless newval-p
+    (setq newval offset
+	  offset 0))
+    (make-acode
+     (%nx1-operator typed-form)
+     (if (eq *nx-sfname* '%set-single-float)
+       'single-float
+       'double-float)
+     (make-acode
+      (%nx1-default-operator)
+      (make-acode (%nx1-operator %macptrptr%) (nx1-form ptrform))
+      (nx1-form offset)
+      (nx1-form newval))))
+
+(defnx1 nx1-let let (pairs &body forms &environment old-env)
+  (collect ((vars)
+            (vals)
+            (varbindings))
+    (with-nx-declarations (pending)
+      (multiple-value-bind (body decls)
+                           (parse-body forms *nx-lexical-environment* nil)
+        (nx-process-declarations pending decls)
+        ;; Make sure that the initforms are processed in the outer
+        ;; environment (in case any declaration handlers side-effected
+        ;; the environment.)
+        
+        (let* ((*nx-lexical-environment* old-env))
+          (dolist (pair pairs)
+            (let* ((sym (nx-need-var (nx-pair-name pair)))
+                   (var (nx-cons-var sym))
+                   (val (nx1-typed-var-initform pending sym (nx-pair-initform pair)))
+                   (binding (nx1-note-var-binding var val)))
+              (vars var)
+              (vals val)
+              (when binding (varbindings binding)))))
+        (let* ((*nx-bound-vars* *nx-bound-vars*)
+               (varbindings (varbindings)))
+          (dolist (v (vars)) (nx-init-var pending v))
+          (let* ((form 
+                  (make-acode 
+                   (%nx1-operator let)
+                   (vars)
+                   (vals)
+                   (progn
+                     (nx-effect-other-decls pending *nx-lexical-environment*)
+                     (nx1-env-body body old-env))
+                 *nx-new-p2decls*)))
+          (nx1-check-var-bindings varbindings)
+          (nx1-punt-bindings (vars) (vals))
+          form))))))
+
+
+
+;((lambda (lambda-list) . body) . args)
+(defun nx1-lambda-bind (lambda-list args body &optional (body-environment *nx-lexical-environment*))
+  (let* ((old-env body-environment)
+         (arg-env *nx-lexical-environment*)
+         (arglist nil)
+         var-bound-vars
+         vars vals vars* vals*)
+    ;; If the lambda list contains &LEXPR, we can't do it.  Yet.
+    (multiple-value-bind (ok req opttail resttail) (verify-lambda-list lambda-list)
+      (declare (ignore req opttail))
+      (when (and ok (eq (%car resttail) '&lexpr))
+        (return-from nx1-lambda-bind (nx1-call (nx1-form `(lambda ,lambda-list ,@body)) args))))
+    (let* ((*nx-lexical-environment* body-environment)
+           (*nx-bound-vars* *nx-bound-vars*))
+      (with-nx-declarations (pending)
+        (multiple-value-bind (body decls) (parse-body body *nx-lexical-environment*)
+          (nx-process-declarations pending decls)
+          (multiple-value-bind (req opt rest keys auxen)
+                               (nx-parse-simple-lambda-list pending lambda-list)
+            (let* ((*nx-lexical-environment* arg-env))
+              (setq arglist (nx1-formlist args)))
+            (nx-effect-other-decls pending *nx-lexical-environment*)
+            (setq body (nx1-env-body body old-env))
+            (while req
+              (when (null arglist)
+                (nx-error "Not enough args ~S for (LAMBDA ~s ...)" args lambda-list))
+              (let* ((var (pop req))
+                     (val (pop arglist))
+                     (binding (nx1-note-var-binding var val)))
+                (push var vars)
+                (push val vals)
+                (when binding (push binding var-bound-vars))))
+            (nx1-check-var-bindings var-bound-vars)
+            (nx1-punt-bindings vars vals)
+            (destructuring-bind (&optional optvars inits spvars) opt
+              (while optvars
+                (if arglist
+                  (progn
+                    (push (%car optvars) vars) (push (%car arglist) vals)
+                    (when (%car spvars) (push (%car spvars) vars) (push *nx-t* vals)))
+                  (progn
+                    (push (%car optvars) vars*) (push (%car inits) vals*)
+                    (when (%car spvars) (push (%car spvars) vars*) (push *nx-nil* vals*))))
+                (setq optvars (%cdr optvars) spvars (%cdr spvars) inits (%cdr inits)
+                      arglist (%cdr arglist))))
+            (if arglist
+              (when (and (not keys) (not rest))
+                (nx-error "Extra args ~s for (LAMBDA ~s ...)" args lambda-list))
+              (when rest
+                (push rest vars*) (push *nx-nil* vals*)
+                (nx1-punt-bindings (cons rest nil) (cons *nx-nil* nil))
+                (setq rest nil)))
+            (when keys
+              (let* ((punt nil))
+                (destructuring-bind (kallowother keyvars spvars inits keyvect) keys
+                  (do* ((pairs arglist (%cddr pairs)))
+                       ((null pairs))
+                    (let* ((keyword (car pairs)))
+                      (when (or (not (acode-p keyword))
+                                (neq (acode-operator keyword) (%nx1-operator immediate))
+                                (eq (%cadr keyword) :allow-other-keys))
+                        (return (setq punt t)))))
+                  (do* ((nkeys (length keyvect))
+                        (keyargs (make-array  nkeys :initial-element nil))
+                        (argl arglist (%cddr argl))
+                        (n 0 (%i+ n 1))
+                        idx arg hit)
+                       ((null argl)
+                        (unless rest
+                          (while arglist
+                            (push (%cadr arglist) vals)
+                            (setq arglist (%cddr arglist))))
+                        (dotimes (i (the fixnum nkeys))                      
+                          (push (%car keyvars) vars*)
+                          (push (or (%svref keyargs i) (%car inits)) vals*)
+                          (when (%car spvars)
+                            (push (%car spvars) vars*)
+                            (push (if (%svref keyargs i) *nx-t* *nx-nil*) vals*))
+                          (setq keyvars (%cdr keyvars) inits (%cdr inits) spvars (%cdr spvars)))
+                        (setq keys hit))
+                    (setq arg (%car argl))
+                    (unless (and (not punt)
+                                 (%cdr argl))
+                      (let ((var (nx-new-temp-var pending)))
+                        (when (or (null rest) (%ilogbitp $vbitdynamicextent (nx-var-bits rest)))
+                          (nx-set-var-bits var (%ilogior (%ilsl $vbitdynamicextent 1) (nx-var-bits var))))
+                        (setq body (make-acode
+                                    (%nx1-operator debind)
+                                    nil
+                                    (nx-make-lexical-reference var)
+                                    nil 
+                                    nil 
+                                    rest 
+                                    keys 
+                                    auxen 
+                                    nil 
+                                    body 
+                                    *nx-new-p2decls* 
+                                    nil)
+                              rest var keys nil auxen nil)
+                        (return nil)))
+                    (unless (or (setq idx (position (%cadr arg) keyvect))
+                                (eq (%cadr arg) :allow-other-keys)
+                                (and kallowother (symbolp (%cadr arg))))
+                      (nx-error "Invalid keyword ~s in ~s for (LAMBDA ~S ...)"
+                                (%cadr arg) args lambda-list))
+                    (when (and idx (null (%svref keyargs idx)))
+                      (setq hit t)
+                      (%svset keyargs idx n))))))
+            (destructuring-bind (&optional auxvars auxvals) auxen
+              (let ((vars!% (nreconc vars* auxvars))
+                    (vals!& (nreconc vals* auxvals)))
+                (make-acode (%nx1-operator lambda-bind)
+                            (append (nreverse vals) arglist)
+                            (nreverse vars)
+                            rest
+                            keys
+                            (list vars!% vals!&)
+                            body
+                            *nx-new-p2decls*)))))))))
+
+(defun nx-inhibit-register-allocation (&optional (why 0))
+  (let ((afunc *nx-current-function*))
+    (setf (afunc-bits afunc)
+          (%ilogior (%ilsl $fbitnoregs 1)
+                    why
+                    (afunc-bits afunc)))))
+
+
+
+(defnx1 nx1-lap-function (ppc-lap-function) (name bindings &body body)
+  (declare (ftype (function (t t t)) %define-ppc-lap-function))
+  (require "PPC-LAP" "ccl:compiler;ppc;ppc-lap")
+  (setf (afunc-lfun *nx-current-function*) 
+        (%define-ppc-lap-function name `((let ,bindings ,@body))
+                                  (dpb (length bindings) $lfbits-numreq 0))))
+
+(defnx1 nx1-x86-lap-function (x86-lap-function) (name bindings &body body)
+  (declare (ftype (function (t t t)) %define-x86-lap-function))
+  (require "X86-LAP")
+  (setf (afunc-lfun *nx-current-function*) 
+        (%define-x86-lap-function name `((let ,bindings ,@body))
+				    (dpb (length bindings) $lfbits-numreq 0))))
+
+
+
+(defun nx1-env-body (body old-env &optional (typecheck (nx-declarations-typecheck *nx-lexical-environment*)))
+  (do* ((form (nx1-progn-body body))
+        (typechecks nil)
+        (env *nx-lexical-environment* (lexenv.parent-env env)))
+       ((or (eq env old-env) (null env))
+        (if typechecks
+          (make-acode
+           (%nx1-operator progn)
+           (nconc (nreverse typechecks) (list form)))
+          form))
+    (let ((vars (lexenv.variables env)))
+      (when (consp vars)
+        (dolist (var vars)
+          (nx-check-var-usage var)
+          (when (and typecheck
+                     (let ((expansion (var-expansion var)))
+                       (or (atom expansion) (neq (%car expansion) :symbol-macro))))
+            (let* ((sym (var-name var))
+                   (type (nx-declared-type sym)))
+              (unless (eq type t)
+                (let ((old-bits (nx-var-bits var)))
+                  (push (nx1-form `(the ,type ,sym)) typechecks)
+                  (when (%izerop (%ilogand2 old-bits
+                                            (%ilogior (%ilsl $vbitspecial 1)
+                                                      (%ilsl $vbitreffed 1)
+                                                      (%ilsl $vbitclosed 1)
+                                                      $vrefmask
+                                                      $vsetqmask)))
+                    (nx-set-var-bits var (%ilogand2 (nx-var-bits var)
+                                                    (%ilognot (%ilsl $vbitignore 1))))))))))))))
+
+
+(defnx1 nx1-let* (let*) (varspecs &body forms)
+  (let* ((vars nil)
+         (vals nil)
+         (val nil)
+         (var-bound-vars nil)
+         (*nx-bound-vars* *nx-bound-vars*)
+         (old-env *nx-lexical-environment*))
+    (with-nx-declarations (pending)
+      (multiple-value-bind (body decls)
+                           (parse-body forms *nx-lexical-environment* nil)
+        (nx-process-declarations pending decls)
+        (dolist (pair varspecs)          
+          (let* ((sym (nx-need-var (nx-pair-name pair)))
+                 (var (progn 
+                        (push (setq val (nx1-typed-var-initform pending sym (nx-pair-initform pair))) vals)
+                        (nx-new-var pending sym)))
+                 (binding (nx1-note-var-binding var val)))
+            (when binding (push binding var-bound-vars))
+            (push var vars)))
+        (nx-effect-other-decls pending *nx-lexical-environment*)
+        (let* ((result
+                (make-acode 
+                 (%nx1-default-operator)
+                 (setq vars (nreverse vars))
+                 (setq vals (nreverse vals))
+                 (nx1-env-body body old-env)
+                 *nx-new-p2decls*)))
+          (nx1-check-var-bindings var-bound-vars)
+          (nx1-punt-bindings vars vals)
+          result)))))
+
+(defnx1 nx1-multiple-value-bind multiple-value-bind 
+        (varspecs bindform &body forms)
+  (if (= (length varspecs) 1)
+    (nx1-form `(let* ((,(car varspecs) ,bindform)) ,@forms))
+    (let* ((vars nil)
+           (*nx-bound-vars* *nx-bound-vars*)
+           (old-env *nx-lexical-environment*)
+           (mvform (nx1-form bindform)))
+      (with-nx-declarations (pending)
+        (multiple-value-bind (body decls)
+                             (parse-body forms *nx-lexical-environment* nil)
+          (nx-process-declarations pending decls)
+          (dolist (sym varspecs)
+            (push (nx-new-var pending sym t) vars))
+          (nx-effect-other-decls pending *nx-lexical-environment*)
+          (make-acode
+           (%nx1-operator multiple-value-bind)
+           (nreverse vars)
+           mvform
+           (nx1-env-body body old-env)
+           *nx-new-p2decls*))))))
+
+
+;;; This isn't intended to be user-visible; there isn't a whole lot of 
+;;; sanity-checking applied to the subtag.
+(defnx1 nx1-%alloc-misc ((%alloc-misc)) (element-count subtag &optional (init nil init-p))
+  (if init-p                            ; ensure that "init" is evaluated before miscobj is created.
+    (make-acode (%nx1-operator %make-uvector)
+                (nx1-form element-count)
+                (nx1-form subtag)
+                (nx1-form init))
+    (make-acode (%nx1-operator %make-uvector)
+                (nx1-form element-count)
+                (nx1-form subtag))))
+
+(defnx1 nx1-%lisp-word-ref (%lisp-word-ref) (base offset)
+  (make-acode (%nx1-operator %lisp-word-ref)
+              (nx1-form base)
+              (nx1-form offset)))
+
+(defnx1 nx1-%single-to-double ((%single-to-double)) (arg)
+  (make-acode (%nx1-operator %single-to-double)
+              (nx1-form arg)))
+
+(defnx1 nx1-%double-to-single ((%double-to-single)) (arg)
+  (make-acode (%nx1-operator %double-to-single)
+              (nx1-form arg)))
+
+(defnx1 nx1-%fixnum-to-double ((%fixnum-to-double)) (arg)
+  (make-acode (%nx1-operator %fixnum-to-double)
+              (nx1-form arg)))
+
+(defnx1 nx1-%fixnum-to-single ((%fixnum-to-single)) (arg)
+  (make-acode (%nx1-operator %fixnum-to-single)
+              (nx1-form arg)))
+
+(defnx1 nx1-%double-float ((%double-float)) (&whole whole arg &optional (result nil result-p))
+  (declare (ignore result))
+  (if result-p
+    (nx1-treat-as-call whole)
+    (make-acode (%nx1-operator %double-float) (nx1-form arg))))
+
+(defnx1 nx1-%short-float ((%short-float)) (&whole whole arg &optional (result nil result-p))
+  (declare (ignore result))        
+  (if result-p
+    (nx1-treat-as-call whole)
+    (make-acode (%nx1-operator %single-float) (nx1-form arg))))
+
+
+(defnx1 nx1-symvector ((%symptr->symvector) (%symvector->symptr)) (arg)
+  (make-acode (%nx1-default-operator) (nx1-form arg)))
+        
+(defnx1 nx1-ash (ash) (&whole call &environment env num amt)
+  (let* ((unsigned-natural-type (target-word-size-case
+                                 (32 '(unsigned-byte 32))
+                                 (64 '(unsigned-byte 64))))
+         (max (target-word-size-case (32 32) (64 64)))
+         (maxbits (target-word-size-case
+                   (32 29)
+                   (64 60))))
+    (cond ((eq amt 0) (nx1-form `(require-type ,num 'integer) env))
+          ((and (fixnump amt)
+                (< amt 0))
+           (if (nx-form-typep num 'fixnum env)
+             (make-acode (%nx1-operator %iasr)
+                         (make-acode (%nx1-operator fixnum)
+                                     (- amt))
+                         (nx1-form num))
+             (if (nx-form-typep num unsigned-natural-type env)
+               (make-acode (%nx1-operator natural-shift-right)
+                           (nx1-form num)
+                           (make-acode (%nx1-operator fixnum)
+                                       (min (1- max) (- amt))))
+               (nx1-treat-as-call call))))
+          ((and (fixnump amt)
+                (<= 0 amt maxbits)
+                (or (nx-form-typep num `(signed-byte ,(- (1+ maxbits) amt)) env)
+                    (and (nx-form-typep num 'fixnum env)
+                         (nx-trust-declarations env)
+                         (subtypep *nx-form-type* 'fixnum))))
+           (nx1-form `(%ilsl ,amt ,num)))
+          ((and (fixnump amt)
+                (< amt max)
+                (nx-form-typep num unsigned-natural-type env)
+                (nx-trust-declarations env)
+                (subtypep *nx-form-type* unsigned-natural-type))
+           (make-acode (%nx1-operator natural-shift-left)
+                       (nx1-form num)
+                       (nx1-form amt)))
+          (t (nx1-treat-as-call call)))))
+
+    
+        
+(defun nx-badformat (&rest args)
+ (nx-error "Bad argument format in ~S ." args))
+
+(defnx1 nx1-eval-when eval-when (when &body body)
+  (nx1-progn-body (if (or (memq 'eval when) (memq :execute when)) body)))
+
+(defnx1 nx1-misplaced (declare) (&rest args)
+  (nx-error "~S not expected in ~S." *nx-sfname* (cons *nx-sfname* args)))
+
Index: /branches/new-random/compiler/nx2.lisp
===================================================================
--- /branches/new-random/compiler/nx2.lisp	(revision 13309)
+++ /branches/new-random/compiler/nx2.lisp	(revision 13309)
@@ -0,0 +1,273 @@
+;;;-*-Mode: LISP; Package: ccl -*-
+;;;
+;;;   Copyright (C) 2008-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Shared compiler backend utilities and infrastructure.
+
+(in-package "CCL")
+
+
+(defun nx2-bigger-cdr-than (x y)
+  (declare (cons x y))
+  (> (the fixnum (cdr x)) (the fixnum (cdr y))))
+
+;;; Return an unordered list of "varsets": each var in a varset can be
+;;; assigned a register and all vars in a varset can be assigned the
+;;; same register (e.g., no scope conflicts.)
+
+(defun nx2-partition-vars (vars inherited-vars)
+  (labels ((var-weight (var)
+             (let* ((bits (nx-var-bits var)))
+               (declare (fixnum bits))
+               (if (eql 0 (logand bits (logior
+                                        (ash 1 $vbitpuntable)
+                                        (ash -1 $vbitspecial)
+                                        (ash 1 $vbitnoreg))))
+                 (if (eql (logior (ash 1 $vbitclosed) (ash 1 $vbitsetq))
+                          (logand bits (logior (ash 1 $vbitclosed) (ash 1 $vbitsetq))))
+                   0
+                   (var-refs var))
+                 0)))
+           (sum-weights (varlist) 
+             (let ((sum 0))
+               (dolist (v varlist sum) (incf sum (var-weight v)))))
+           (vars-disjoint-p (v1 v2)
+             (if (eq v1 v2)
+               nil
+               (if (memq v1 (var-binding-info v2))
+                 nil
+                 (if (memq v2 (var-binding-info v1))
+                   nil
+                   t)))))
+    (dolist (iv inherited-vars)
+      (dolist (v vars) (push iv (var-binding-info v)))
+      (push iv vars))
+    (setq vars (%sort-list-no-key
+                ;;(delete-if #'(lambda (v) (eql (var-weight v) 0)) vars) 
+                (do* ((handle (cons nil vars))
+                      (splice handle))
+                     ((null (cdr splice)) (cdr handle))                  
+                  (declare (dynamic-extent handle) (type cons handle splice))
+                  (if (eql 0 (var-weight (%car (cdr splice))))
+                    (rplacd splice (%cdr (cdr splice)))
+                    (setq splice (cdr splice))))
+                #'(lambda (v1 v2) (%i> (var-weight v1) (var-weight v2)))))
+    ;; This isn't optimal.  It partitions all register-allocatable
+    ;; variables into sets such that 1) no variable is a member of
+    ;; more than one set and 2) all variables in a given set are
+    ;; disjoint from each other A set might have exactly one member.
+    ;; If a register is allocated for any member of a set, it's
+    ;; allocated for all members of that set.
+    (let* ((varsets nil))
+      (do* ((all vars (cdr all)))
+           ((null all))
+        (let* ((var (car all)))
+          (when (dolist (already varsets t)
+                  (when (memq var (car already)) (return)))
+            (let* ((varset (cons var nil)))
+              (dolist (v (cdr all))
+                (when (dolist (already varsets t)
+                        (when (memq v (car already)) (return)))
+                  (when (dolist (d varset t)
+                          (unless (vars-disjoint-p v d) (return)))
+                    (push v varset))))
+              (let* ((weight (sum-weights varset)))
+                (declare (fixnum weight))
+                (if (>= weight 3)
+                  (push (cons (nreverse varset) weight) varsets)))))))
+      varsets)))
+
+;;; Maybe globally allocate registers to symbols naming functions & variables,
+;;; and to simple lexical variables.
+(defun nx2-allocate-global-registers (fcells vcells all-vars inherited-vars nvrs)
+  (if (null nvrs)
+    (progn
+      (dolist (c fcells) (%rplacd c nil))
+      (dolist (c vcells) (%rplacd c nil))
+      (values 0 nil))
+    (let* ((maybe (nx2-partition-vars all-vars inherited-vars)))
+      (dolist (c fcells) 
+        (if (>= (the fixnum (cdr c)) 3) (push c maybe)))
+      (dolist (c vcells) 
+        (if (>= (the fixnum (cdr c)) 3) (push c maybe)))
+      (do* ((things (%sort-list-no-key maybe #'nx2-bigger-cdr-than) (cdr things))
+            (n 0 (1+ n))
+            (registers nvrs)
+            (regno (pop registers) (pop registers))
+            (constant-alist ()))
+           ((or (null things) (null regno))
+            (dolist (cell fcells) (%rplacd cell nil))
+            (dolist (cell vcells) (%rplacd cell nil))
+            (values n constant-alist))
+        (declare (list things)
+                 (fixnum n regno))
+        (let* ((thing (car things)))
+          (if (or (memq thing fcells)
+                  (memq thing vcells))
+            (push (cons thing regno) constant-alist)
+            (dolist (var (car thing))
+              (setf (var-nvr var) regno))))))))
+
+(defun nx2-assign-register-var (v)
+  (var-nvr v))
+
+
+(defun nx2-constant-form-p (form)
+  (setq form (nx-untyped-form form))
+  (if form
+    (or (nx-null form)
+        (nx-t form)
+        (and (consp form)
+             (or (eq (acode-operator form) (%nx1-operator immediate))
+                 (eq (acode-operator form) (%nx1-operator fixnum))
+                 (eq (acode-operator form) (%nx1-operator simple-function)))))))
+
+(defun nx2-lexical-reference-p (form)
+  (when (acode-p form)
+    (let ((op (acode-operator (setq form (acode-unwrapped-form-value form)))))
+      (when (or (eq op (%nx1-operator lexical-reference))
+                (eq op (%nx1-operator inherited-arg)))
+        (%cadr form)))))
+
+;;; Returns true iff lexical variable VAR isn't setq'ed in FORM.
+;;; Punts a lot ...
+(defun nx2-var-not-set-by-form-p (var form)
+  (let* ((bits (nx-var-bits var)))
+    (or (not (%ilogbitp $vbitsetq bits))
+        (nx2-setqed-var-not-set-by-form-p var form (logbitp $vbitclosed bits)))))
+
+(defun nx2-setqed-var-not-set-by-form-p (var form &optional closed)
+  (setq form (acode-unwrapped-form form))
+  (or (atom form)
+      (nx2-constant-form-p form)
+      (nx2-lexical-reference-p form)
+      (let ((op (acode-operator form))
+            (subforms nil))
+        (if (eq op (%nx1-operator setq-lexical))
+          (and (neq var (cadr form))
+               (nx2-setqed-var-not-set-by-form-p var (caddr form)))
+          (and (or (not closed)
+                   (logbitp operator-side-effect-free-bit op))
+               (flet ((not-set-in-formlist (formlist)
+                        (dolist (subform formlist t)
+                          (unless (nx2-setqed-var-not-set-by-form-p var subform closed) (return)))))
+                 (if
+                   (cond ((%ilogbitp operator-acode-subforms-bit op) (setq subforms (%cdr form)))
+                         ((%ilogbitp operator-acode-list-bit op) (setq subforms (cadr form))))
+                   (not-set-in-formlist subforms)
+                   (and (or (eq op (%nx1-operator call))
+                            (eq op (%nx1-operator lexical-function-call)))
+                        (nx2-setqed-var-not-set-by-form-p var (cadr form))
+                        (setq subforms (caddr form))
+                        (not-set-in-formlist (car subforms))
+                        (not-set-in-formlist (cadr subforms))))))))))
+
+(defun nx2-node-gpr-p (reg)
+  (and reg
+       (eql (hard-regspec-class reg) hard-reg-class-gpr)
+       (eql (get-regspec-mode reg) hard-reg-class-gpr-mode-node)))
+
+;;; ENTRIES is a list of recorded-symbol entries, built by pushing
+;;; info for each variable referenced by the function AFUNC as it
+;;; comes into scope.  (Inherited variables "come into scope" before
+;;; anything else, then required arguments, etc.)  Supplied-p variables
+;;; may come into scope before "real" arglist entries do, which confuses
+;;; functions that try to construct a function's arglist from the symbol
+;;; map.  I -think- that confusion only exists when supplied-p variables
+;;; are involved, so this returns its first argument unless they are;
+;;; otherwise, it ensures that all toplevel arglist symbols are followed
+;;; only by any inherited variables, and that the arglist symbols are
+;;; in the correct (reversed) order
+(defun nx2-recorded-symbols-in-arglist-order (entries afunc)
+  (let* ((alambda (afunc-acode afunc)))
+    (when (and (acode-p alambda)
+               (eq (acode-operator alambda) (%nx1-operator lambda-list)))
+      (destructuring-bind (req opt rest keys &rest ignore) (cdr alambda)
+        (declare (ignore ignore))
+        (when (or (dolist (sp (caddr opt))
+                    (when sp (return t)))
+                  (dolist (sp (caddr keys))
+                    (when sp (return t))))
+          (let* ((new ()))
+            (flet ((info-for-var (var)
+                     (assoc var entries :test #'eq)))
+              (flet ((add-new-info (var)
+                       (let* ((info (info-for-var var)))
+                         (when info
+                           (push info new)))))
+                (setq entries (nreverse entries))
+                (dolist (var (afunc-inherited-vars afunc))
+                  (add-new-info var))
+                (dolist (r req)
+                  (add-new-info r))
+                (dolist (o (car opt))
+                  (add-new-info o))
+                (when (consp rest)
+                  (setq rest (car rest)))
+                (when rest
+                  (add-new-info rest))
+                (dolist (k (cadr keys))
+                  (add-new-info k))
+                (dolist (e entries)
+                  (unless (member e new :test #'eq)
+                    (push e new)))
+                (setq entries new)))))))
+    entries))
+
+(defun nx2-replace-var-refs (var value)
+  (when (acode-p value)
+    (let* ((op (acode-operator value))
+           (operands (acode-operands value)))
+      (when (typep op 'fixnum)
+        (dolist (ref (var-ref-forms var) (setf (var-ref-forms var) nil))
+          (when (acode-p ref)
+            (setf (acode-operator ref) op
+                  (acode-operands ref) operands)))))))
+
+(defun acode-immediate-operand (x)
+  (let* ((x (acode-unwrapped-form x)))
+    (if (eq (acode-operator x) (%nx1-operator immediate))
+      (cadr x)
+      (compiler-bug "not an immediate: ~s" x))))
+
+(defun nx2-constant-index-ok-for-type-keyword (idx keyword)
+  (when (>= idx 0)
+    (let* ((arch (backend-target-arch *target-backend*))
+           (limit
+            (case keyword
+              ((:bignum 
+                :single-float 
+                :double-float 
+                :xcode-vector
+                :signed-32-bit-vector 
+                :unsigned-32-bit-vector 
+                :single-float-vector 
+                :simple-string)
+               (arch::target-max-32-bit-constant-index arch))
+              (:bit-vector (arch::target-max-1-bit-constant-index arch))
+              ((:signed-8-bit-vector :unsigned-8-bit-vector)
+               (arch::target-max-8-bit-constant-index arch))
+              ((:signed-16-bit-vector :unsigned-16-bit-vector)
+               (arch::target-max-16-bit-constant-index arch))
+              ((:signed-64-bit-vector 
+                :unsigned-64-bit-vector 
+                :double-float-vector)
+               (arch::target-max-64-bit-constant-index arch))
+              (t
+               ;; :fixnum or node
+               (target-word-size-case
+                (32 (arch::target-max-32-bit-constant-index arch))
+                (64 (arch::target-max-64-bit-constant-index arch)))))))
+      (and limit (< idx limit)))))
Index: /branches/new-random/compiler/nxenv.lisp
===================================================================
--- /branches/new-random/compiler/nxenv.lisp	(revision 13309)
+++ /branches/new-random/compiler/nxenv.lisp	(revision 13309)
@@ -0,0 +1,601 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;;; Compile-time environment for the compiler.
+
+
+(in-package "CCL")
+
+(eval-when (:execute :compile-toplevel)
+  (require'backquote)
+  (require 'lispequ)
+)
+
+#-bootstrapped
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (when (and (macro-function 'var-decls)
+             (not (macro-function 'var-ref-forms)))
+    (setf (macro-function 'var-ref-forms)
+          (macro-function 'var-decls))))
+
+#+ppc-target (require "PPCENV")
+#+x8632-target (require "X8632ENV")
+#+x8664-target (require "X8664ENV")
+
+(defconstant $vbittemporary 16)    ; a compiler temporary
+(defconstant $vbitreg 17)          ; really wants to live in a register.
+(defconstant $vbitnoreg 18)        ; something inhibits register allocation
+(defconstant $vbitdynamicextent 19)
+(defconstant $vbitparameter 20)    ; iff special
+(defconstant $vbitpunted 20)       ; iff lexical
+(defconstant $vbitignoreunused 21)
+(defconstant $vbitignorable 21)
+(defconstant $vbitcloseddownward 22)  
+(defconstant $vbitsetq 23)
+(defconstant $vbitpuntable 24)
+(defconstant $vbitclosed 25)
+(defconstant $vbitignore 26)
+(defconstant $vbitreffed 27)
+(defconstant $vbitspecial 28)
+(defconstant $vsetqmask #xff00)
+(defconstant $vrefmask #xff)
+
+(defconstant $decl_optimize (%ilsl 16 0))  ; today's chuckle
+(defconstant $decl_tailcalls (ash 1 16))
+(defconstant $decl_opencodeinline (ash 4 16))
+(defconstant $decl_eventchk (ash 8 16))
+(defconstant $decl_unsafe (ash 16 16))
+(defconstant $decl_trustdecls (ash 32 16))
+(defconstant $decl_full_safety (ash 64 16))
+
+(defconstant $regnote-ea 1)
+
+(defmacro nx-null (x)
+ `(eq ,x *nx-nil*))
+
+(defmacro nx-t (x)
+ `(eq ,x *nx-t*))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+  (defconstant operator-id-mask (1- (%ilsl 10 1)))
+  (defconstant operator-acode-subforms-bit 10)
+  (defconstant operator-acode-subforms-mask (%ilsl operator-acode-subforms-bit 1))
+  (defconstant operator-acode-list-bit 11)
+  (defconstant operator-acode-list-mask (%ilsl operator-acode-list-bit 1))
+  (defconstant operator-side-effect-free-bit 12) ; operator is side-effect free; subforms may not be ...
+  (defconstant operator-side-effect-free-mask 
+    (%ilsl operator-side-effect-free-bit 1))
+  (defconstant operator-single-valued-bit 13)
+  (defconstant operator-single-valued-mask
+    (%ilsl operator-single-valued-bit 1))
+  (defconstant operator-assignment-free-bit 14)
+  (defconstant operator-assignment-free-mask
+    (%ilsl operator-assignment-free-bit 1))
+  (defconstant operator-cc-invertable-bit 15)
+  (defconstant operator-cc-invertable-mask (ash 1 operator-cc-invertable-bit))
+  (defconstant operator-boolean-bit 16)
+  (defconstant operator-boolean-mask (ash 1 operator-boolean-bit))
+  (defconstant operator-returns-address-bit 17)
+  (defconstant operator-returns-address-mask (ash 1 operator-returns-address-bit))
+
+  )
+
+(defparameter *next-nx-operators*
+  (reverse
+   '((%primitive . 0)
+     (progn . #.(logior operator-acode-list-mask operator-assignment-free-mask operator-side-effect-free-mask))
+     (not . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (%i+ . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%i- . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (cxxr . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%dfp-combine . 0)
+     (%ilsl . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%ilogand2 . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%ilogior2 . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%ilogbitp . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (eq . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (neq . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (list . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-list-mask operator-side-effect-free-mask))
+     (values . #.(logior operator-acode-list-mask operator-assignment-free-mask operator-side-effect-free-mask))
+     (if . #.(logior operator-acode-subforms-mask operator-side-effect-free-mask))
+     (or . 0)
+     (without-interrupts . 0)
+     (%fixnum-ref . #.operator-single-valued-mask)
+     (%fixnum-ref-natural . #.operator-single-valued-mask)
+     (%current-tcr . #.operator-single-valued-mask)
+     (%stack-trap . #.operator-single-valued-mask)
+     (multiple-value-prog1 . 0)
+     (multiple-value-bind . 0)
+     (multiple-value-call . 0)
+     (put-xxx . #.operator-single-valued-mask)
+     (get-xxx . #.operator-single-valued-mask)
+     (typed-form . 0)
+     (let . 0)
+     (let* . 0)
+     (tag-label . 0)
+     (local-tagbody . #.operator-single-valued-mask)
+     (%fixnum-set-natural . #.operator-single-valued-mask)
+     (type-asserted-form . 0)
+     (spushp . #.operator-single-valued-mask)
+     (simple-function . #.operator-single-valued-mask)
+     (closed-function . #.operator-single-valued-mask)
+     (setq-lexical . #.operator-single-valued-mask)
+     (lexical-reference . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (free-reference . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (immediate . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (fixnum . #.(logior operator-assignment-free-mask operator-single-valued-mask ))
+     (call . 0)
+     (local-go . 0)
+     (local-block . 0)
+     (local-return-from . 0)
+     (%car . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%cdr . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%rplaca . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (%rplacd . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (cons . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask))
+     (simple-typed-aref2 . #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
+     (setq-free . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (prog1 . 0)
+     (catch . 0)
+     (throw . 0)
+     (unwind-protect . 0)
+     (characterp . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (multiple-value-list . 0)
+     (%izerop . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (%immediate-ptr-to-int . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%immediate-int-to-ptr . #.(logior operator-returns-address-mask operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (immediate-get-xxx . 0)
+     (immediate-put-xxx . 0)
+     (setq-special . 0)
+     (special-ref . 0)
+     (1+ . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (1- . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (add2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (sub2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (numeric-comparison . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-cc-invertable-mask))
+     (numcmp . #.(logior operator-assignment-free-mask operator-acode-subforms-mask operator-single-valued-mask operator-cc-invertable-mask))
+     (struct-ref . 0)
+     (struct-set . 0)
+     (%aref1 . #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask operator-side-effect-free-mask))
+     (embedded-nlexit . 0)
+     (embedded-conditional . 0) 
+     (%word-to-int . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (%svref . #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
+     (%svset . #.(logior operator-acode-subforms-mask operator-single-valued-mask))
+     (%consmacptr% . 0)
+     (%macptrptr% . 0)
+     (%ptr-eql . #.operator-cc-invertable-mask)
+     (%setf-macptr . 0)
+     (bound-special-ref . 0)
+     (%char-code . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%code-char . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (lap . 0)
+     (lap-inline . 0)
+     (%function . #.operator-single-valued-mask)
+     (%valid-code-char . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%ttag . #.operator-single-valued-mask)  
+     (uvsize . #.operator-single-valued-mask)
+     (endp . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (sequence-type . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (fixnum-overflow . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (vector . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (%immediate-inc-ptr . #.(logior operator-returns-address-mask operator-single-valued-mask))
+     (general-aref3 . #.(logior operator-acode-subforms-mask operator-single-valued-mask))
+     (general-aset2 . #.(logior operator-acode-subforms-mask operator-single-valued-mask))
+     (%new-ptr . 0)
+     (%schar . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%set-schar . #.(logior operator-single-valued-mask operator-acode-subforms-mask))	;??
+     (debind . 0)
+     (lambda-bind . 0)
+     (general-aset3 . #.(logior operator-acode-subforms-mask operator-single-valued-mask))
+     (simple-typed-aref3 . #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
+     (simple-typed-aset3 . #.(logior operator-acode-subforms-mask  operator-single-valued-mask))
+     (nth-value . 0)
+     (progv . 0)
+     (svref . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (svset . #.operator-single-valued-mask)
+     (make-list . #.(logior operator-assignment-free-mask operator-single-valued-mask))	; exists only so we can stack-cons
+     (%badarg1 . 0)
+     (%badarg2 . 0)
+     (newblocktag . 0)
+     (newgotag . 0)
+     (flet . 0)				; may not be necessary - for dynamic-extent, mostly
+					; for dynamic-extent, forward refs, etc.
+     (labels . 0)			; removes 75% of LABELS bogosity
+     (lexical-function-call . 0)	; most of other 25%
+     (with-downward-closures . 0)
+     (self-call . 0)
+     (inherited-arg . #.operator-single-valued-mask)
+     (ff-call . 0)
+     (commutative-subprim-binop . 0)
+     (%immediate-set-xxx . #.(logior operator-acode-subforms-mask))
+     (symbol-name . #.(logior operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (memq . #.(logior operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (assq . #.(logior operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (simple-typed-aset2 . #.(logior operator-acode-subforms-mask operator-single-valued-mask))
+     (consp . #.(logior operator-cc-invertable-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-boolean-mask))
+     (aset1 . #.(logior operator-acode-subforms-mask))
+     (syscall . 0)
+     (car . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (cdr . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (length . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (list-length . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (ensure-simple-string . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%ilsr . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (set . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (eql . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-boolean-mask))
+     (%iasr . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (logand2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (logior2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (logxor2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%i<> . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (set-car . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (set-cdr . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (rplaca . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (rplacd . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (with-variable-c-frame . #.(logior operator-acode-list-mask operator-assignment-free-mask))
+     (uvref . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (uvset . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (%temp-cons . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%temp-List . #.(logior operator-single-valued-mask operator-side-effect-free-mask))
+     (%make-uvector . #.(logior operator-assignment-free-mask operator-single-valued-mask  operator-side-effect-free-mask))
+     (%decls-body . 0)
+     (%old-gvector . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%typed-uvref . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%typed-uvset . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (schar . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (set-schar . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (code-char . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (char-code . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (list* . #.(logior operator-assignment-free-mask operator-single-valued-mask  operator-side-effect-free-mask))
+     (append . #.(logior operator-assignment-free-mask operator-single-valued-mask  operator-side-effect-free-mask))
+     (symbolp . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-boolean-mask))
+     (integer-point-h . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (integer-point-v . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (int>0-p . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (immediate-constant .  #.(logior operator-assignment-free-mask operator-single-valued-mask ))
+     (with-stack-double-floats . 0)
+     (short-float . #.operator-single-valued-mask)
+     (istruct-typep . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (%ilogxor2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%err-disp . 0)
+     (%quo2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (minus1 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%ineg . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%i* . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (logbitp . #.(logior operator-single-valued-mask operator-assignment-free-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-boolean-mask))
+     (%sbchar . 0)
+     (%sechar . 0)
+     (%set-sbchar . 0)
+     (%scharcode . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%set-scharcode . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (lambda-list . 0)
+     (ppc-lap-function . 0)
+     (lisptag . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (fulltag . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (typecode . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-simple-vector . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-simple-string . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-integer . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-fixnum . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-real . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-list . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-character . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-number . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-symbol . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (base-char-p . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (%vect-subtype . #.operator-single-valued-mask)
+     (%unbound-marker . #.operator-single-valued-mask)
+     (%slot-unbound-marker . #.operator-single-valued-mask)
+     (%gvector . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (immediate-get-ptr . #.operator-returns-address-mask)
+     (%lisp-word-ref . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (%lisp-lowbyte-ref . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (poweropen-ff-call . 0)
+     (double-float-compare . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (builtin-call . 0)
+     (%setf-double-float . 0)
+     (%double-float+-2 . #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (%double-float--2 .  #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (%double-float*-2 .  #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (%double-float/-2 .  #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (%double-float+-2! . 0)
+     (%double-float--2! . 0)
+     (%double-float*-2! . 0)
+     (%double-float/-2! . 0)
+     (poweropen-syscall . 0)
+     (%debug-trap . 0)
+     (%%ineg . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%setf-short-float . 0)
+     (%short-float+-2 .  #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (%short-float--2 .  #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (%short-float*-2 .  #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (%short-float/-2 .  #.(logior operator-single-valued-mask operator-side-effect-free-mask operator-acode-subforms-mask))
+     (short-float-compare . 0)
+     (eabi-ff-call . 0)
+     (%reference-external-entry-point . 0)
+     (eabi-syscall . 0)
+     (%get-bit . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%set-bit   . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (%natural+ . 0)
+     (%natural- . 0)
+     (%natural-logand . 0)
+     (%natural-logior . 0)
+     (%natural-logxor . 0)
+     (%natural<> . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask operator-cc-invertable-mask))
+     (%get-double-float . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%get-single-float . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%set-double-float . #.(logior operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+      (%set-single-float . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (natural-shift-right  . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (natural-shift-left  . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (global-ref . 0)
+     (global-setq . 0)
+     (disable-interrupts . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+
+     (%interrupt-poll  . #.(logior operator-assignment-free-mask operator-single-valued-mask))
+     (with-c-frame . #.(logior operator-acode-list-mask operator-assignment-free-mask operator-side-effect-free-mask))    
+     (%current-frame-ptr . 0)
+     (%slot-ref . 0)
+     (%illegal-marker . #.operator-single-valued-mask)
+     (%symbol->symptr . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%single-to-double  . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%double-to-single . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%symptr->symvector  . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%symvector->symptr  . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%foreign-stack-pointer . 0)
+     (mul2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (div2 . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%fixnum-to-single  . #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (%fixnum-to-double .  #.(logior operator-assignment-free-mask operator-single-valued-mask operator-acode-subforms-mask operator-side-effect-free-mask))
+     (require-s8 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-u8 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-s16 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-u16 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-s32 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-u32 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-s64 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (require-u64 . #.(logior operator-single-valued-mask operator-acode-subforms-mask))
+     (general-aref2 .  #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
+     (%single-float .  #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
+     (%double-float . #. #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
+     (i386-ff-call . 0)
+     (i386-syscall . 0))))
+
+(defmacro %nx1-operator (sym)
+  (let ((op (assq sym *next-nx-operators*)))
+    (if op (logior (%cdr op) (length (%cdr (memq op *next-nx-operators*))))
+        (error "Bug - operator not found for ~S" sym))))
+
+(declaim (special *nx1-alphatizers* *nx1-operators*))
+
+(defmacro %nx1-default-operator ()
+ #-bccl
+ `(nx1-default-operator)
+ #+bccl
+ `(gethash *nx-sfname* *nx1-operators*))
+
+(defmacro defnx1 (name sym arglist &body forms)
+  (let ((fn `(nfunction ,name ,(parse-macro name arglist forms)))
+        (theprogn ())
+        (ysym (gensym)))
+    `(let ((,ysym ,fn))
+       ,(if (symbolp sym)
+          `(progn
+             (setf (gethash ',sym *nx1-alphatizers*) ,ysym)
+             ;(proclaim '(inline ,sym))
+             (pushnew ',sym *nx1-compiler-special-forms*))
+          (dolist (x sym `(progn ,@(nreverse theprogn)))
+            (if (consp x)
+              (setq x (%car x))
+              (push `(pushnew ',x *nx1-compiler-special-forms*) theprogn))
+            ;(push `(proclaim '(inline ,x)) theprogn)
+            (push `(setf (gethash ',x *nx1-alphatizers*) ,ysym) theprogn)))
+       (record-source-file ',name 'function)
+       ,ysym)))
+
+(defmacro next-nx-num-ops ()
+  (length *next-nx-operators*))
+
+(defmacro next-nx-defops (&aux (ops (gensym)) 
+                                (num (gensym)) 
+                                (flags (gensym)) 
+                                (op (gensym)))
+  `(let ((,num ,(length *next-nx-operators*)) 
+         (,ops ',*next-nx-operators*) 
+         (,flags nil)
+         (,op nil))
+     (while ,ops
+       (setq ,op (%car ,ops)  ,flags (cdr ,op))
+       (setf (gethash (car ,op) *nx1-operators*) 
+             (logior ,flags (setq ,num (%i- ,num 1))))
+       (setq ,ops (cdr ,ops)))))
+
+(defconstant $fbitnextmethargsp 0)
+(defconstant $fbitmethodp 1)
+(defconstant $fbitnextmethp 2)
+(defconstant $fbitnoregs 3)
+(defconstant $fbitdownward 4)
+(defconstant $fbitresident 5)
+(defconstant $fbitbounddownward 6)
+(defconstant $fbitembeddedlap 7)
+(defconstant $fbitruntimedef 8)
+(defconstant $fbitnonnullenv 9)
+(defconstant $fbitccoverage 10)
+
+(defconstant $eaclosedbit 24)
+
+#+what?
+(progn
+;;; condition codes :
+;;; These are 68K condition code values, but the frontend uses them and
+;;; both backends need to understand them.
+;;; They're really backend-specific; it wouldn't hurt to have the frontend
+;;; use a more "neutral" representation.
+(defconstant $ccT 0)
+(defconstant $ccEQ 7)
+(defconstant $ccNE 6)
+(defconstant $ccVC 8)
+(defconstant $ccMI 11)
+(defconstant $ccPL 10)
+(defconstant $ccGE 12)
+(defconstant $ccLT 13)
+(defconstant $ccGT 14)
+(defconstant $ccLE 15)
+)
+
+
+(defmacro %temp-push (value place &environment env)
+  (if (not (consp place))
+    `(setq ,place (%temp-cons ,value ,place))
+    (multiple-value-bind (dummies vals store-var setter getter)
+                         (get-setf-expansion place env)
+      (let ((valvar (gensym)))
+        `(let* ((,valvar ,value)
+                ,@(mapcar #'list dummies vals)
+                (,(car store-var) (%temp-cons ,valvar ,getter)))
+           ,@dummies
+           ,(car store-var)
+           ,setter)))))
+
+; undo tokens :
+
+(defconstant $undocatch 0)  ; do some nthrowing
+(defconstant $undovalues 1) ; flush pending multiple values
+(defconstant $undostkblk 2) ; discard "variable stack block"
+(defconstant $undospecial 3) ; restore dynamic binding
+(defconstant $undointerruptlevel 4) ; restore dynamic binding of *interrupt-level*
+(defconstant $undomvexpect 5) ; stop expecting values
+(defconstant $undoregs 6)   ; allocated regs when dynamic extent var bound.
+
+; Stuff having to do with lisp:
+
+(defmacro make-acode (operator &rest args)
+  `(%temp-list ,operator ,@args))
+
+(defmacro make-acode* (operator &rest args)
+  `(%temp-cons ,operator (mapcar #'nx1-form ,@args)))
+
+; More Bootstrapping Shit.
+(defmacro acode-operator (form)
+  ;; Gak.
+  `(%car ,form))
+
+(defmacro acode-operand (n form)
+  ;; Gak. Gak.
+  `(nth ,n (the list ,form)))
+
+(defmacro acode-operands (form)
+  ;; Gak. Gak. Gak.
+  `(%cdr ,form))
+
+(defmacro acode-p (x)
+  " A big help this is ..."
+  `(consp ,x))
+
+
+(defmacro defnxdecl (sym lambda-list &body forms)
+  (multiple-value-bind (body decls) (parse-body forms nil t)
+    `(setf (getf *nx-standard-declaration-handlers* ',sym )
+           (function (lambda ,lambda-list
+                       ,@decls
+                       ,@body)))))
+
+(defmacro with-declarations ((pending new-env-var &optional old-env) &body body)
+  `(let* ((,pending (make-pending-declarations))
+          (,new-env-var (new-lexical-environment ,old-env)))
+     ,@body))
+
+(defmacro with-nx-declarations ((pending) &body body)
+  `(let* ((*nx-new-p2decls* nil)
+	  (*nx-inlined-self* *nx-inlined-self*))
+    (with-declarations (,pending *nx-lexical-environment* *nx-lexical-environment*)
+      ,@body)))
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+(declaim (inline 
+          nx-decl-set-fbit
+          nx-adjust-setq-count
+          nx-init-var
+          nx1-sysnode
+          ))
+
+(defun nx-init-var (state node)
+  (let* ((sym (var-name node))
+         (env *nx-lexical-environment*)
+         (bits (%i+
+                (if (nx-proclaimed-special-p sym)
+                 (if (nx-proclaimed-parameter-p sym)
+                   (%ilogior (ash -1 $vbitspecial) (%ilsl $vbitparameter 1))
+                   (ash -1 $vbitspecial))
+                 0)
+                (if (proclaimed-ignore-p sym) (%ilsl $vbitignore 1) 0))))
+    (push node (lexenv.variables env))
+    (%temp-push node *nx-all-vars*)
+    (setf (var-binding-info node) *nx-bound-vars*)
+    (%temp-push node *nx-bound-vars*)
+    (dolist (decl (nx-effect-vdecls state sym env) (setf (var-bits node) bits))
+      (case (car decl)
+        (special (setq bits (%ilogior bits (ash -1 $vbitspecial) (%ilsl $vbitparameter 1))))
+        (ignore (setq bits (%ilogior bits (%ilsl $vbitignore 1))))
+        ((ignorable ignore-if-unused) (setq bits (%ilogior bits (%ilsl $vbitignoreunused 1))))
+        (dynamic-extent (setq bits (%ilogior bits (%ilsl $vbitdynamicextent 1))))))
+    node))
+
+(defun nx-decl-set-fbit (bit)
+  (when *nx-parsing-lambda-decls*
+    (let* ((afunc *nx-current-function*))
+      (setf (afunc-bits afunc)
+            (%ilogior (%ilsl bit 1)
+                      (afunc-bits afunc))))))
+
+(defun nx-adjust-setq-count (var &optional (by 1) catchp)
+  (let* ((bits (nx-var-bits var))
+         (scaled-by (if (%ilogbitp $vbittemporary bits)
+                      by
+                      (expt 4 *nx-loop-nesting-level*)))
+         (new (%i+ (%ilsr 8 (%ilogand2 $vsetqmask bits)) scaled-by)))
+    (if (%i> new 255) (setq new 255))
+    (setq bits (nx-set-var-bits var (%ilogior (%ilogand (%ilognot $vsetqmask) bits) (%ilsl 8 new))))
+    ;; If a variable is setq'ed from a catch nested within the construct that
+    ;; bound it, it can't be allocated to a register. *
+    ;; * unless it can be proved that the variable isn't referenced
+    ;;   after that catch construct has been exited. **
+    ;; ** or unless the saved value of the register in the catch frame 
+    ;;    is also updated.
+    (when catchp
+      (nx-set-var-bits var (%ilogior2 bits (%ilsl $vbitnoreg 1))))
+    (setf (var-refs var) (+ (the fixnum (var-refs var)) by))
+    new))
+
+
+(defun nx1-sysnode (form)
+  (if form
+    (if (eq form t)
+      *nx-t*)
+    *nx-nil*))
+)
+
+(defmacro make-mask (&rest weights)
+  `(logior ,@(mapcar #'(lambda (w) `(ash 1 ,w)) weights)))
+
+(provide "NXENV")
+
Index: /branches/new-random/compiler/optimizers.lisp
===================================================================
--- /branches/new-random/compiler/optimizers.lisp	(revision 13309)
+++ /branches/new-random/compiler/optimizers.lisp	(revision 13309)
@@ -0,0 +1,2501 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; Optimizers.lisp - compiler optimizers
+
+(in-package "CCL")
+
+(eval-when (eval compile)
+  (require'backquote)
+  (require'lispequ)
+  (require "ARCH"))
+
+(declaim (special *nx-can-constant-fold* *nx-synonyms*))
+
+(defvar *dont-find-class-optimize* nil) ; t means dont
+
+#|
+;;; can-constant-fold had a bug in the way it called #'proclaim-inline
+|#
+
+;;; There seems to be some confusion about what #'proclaim-inline does.
+;;; The value of the alist entry in *nx-proclaimed-inline* indicates
+;;; whether or not the compiler is allowed to use any special knowledge
+;;; about the symbol in question.  That's a necessary but not sufficient
+;;; condition to enable inline expansion; that's governed by declarations
+;;; in the compile-time environment.
+;;; If someone observed a symptom whereby calling CAN-CONSTANT-FOLD
+;;; caused unintended inline-expansion, the bug's elsewhere ...
+;;; The bug is that nx-declared-inline-p calls proclaimed-inline-p
+;;;  which looks at what proclaim-inline sets.  Presumably, that
+;;;  means that someone fixed it because it showed evidence of
+;;;  being broken.
+;;; The two concepts (the compiler should/should not make assumptions about
+;;;  the signature of known functions, the compiler should/should not arrange
+;;;  to keep the lambda expression around) need to be sorted out.
+
+(defun can-constant-fold (names &aux handler inlines)
+  (dolist (name names)
+    (if (atom name)
+      (setq handler nil)
+      (setq handler (cdr name) name (car name)))
+    (when (and handler (not (eq handler 'fold-constant-subforms)))
+      (warn "Unknown constant-fold handler : ~s" handler)
+      (setq handler nil))
+    (let* ((bits (%symbol-bits name)))
+      (declare (fixnum bits))
+      (%symbol-bits name (logior
+                          (if handler (logior (ash 1 $sym_fbit_fold_subforms) (ash 1 $sym_fbit_constant_fold))
+                              (ash 1 $sym_fbit_constant_fold))
+                          bits)))
+     (push name inlines))
+  '(apply #'proclaim-inline t inlines)
+)
+
+;;; There's a bit somewhere.  This is very partial.  Should be a bit
+;;; somewhere, there are too many of these to keep on a list.
+(can-constant-fold '(specfier-type %ilsl %ilsr 1- 1+ eql eq
+                     byte make-point - / (+ . fold-constant-subforms) (* . fold-constant-subforms) ash character
+                     char-code code-char lsh
+                     (logior . fold-constant-subforms) (logand . fold-constant-subforms)
+                     (logxor . fold-constant-subforms) logcount logorc2 listp consp expt
+                     logorc1 logtest lognand logeqv lognor lognot logandc2 logandc1
+                     numerator denominator ldb-test byte-position byte-size isqrt gcd
+                     floor mod truncate rem round boole max min ldb dpb mask-field deposit-field
+                     length aref svref char schar bit sbit getf identity list-length
+                     car cdr cadr cddr nth nthcdr last load-byte deposit-byte byte-mask
+                     member search count position assoc rassoc integer-length
+		         float not null char-int expt abs
+                     = /= < <= > >=))
+
+(defun %binop-cassoc (call)
+  (unless (and (cddr call) (null (cdr (%cddr call))))
+    (return-from %binop-cassoc call))
+  (let ((func (%car call))
+        (arg1 (%cadr call))
+        (arg2 (%caddr call))
+        (val))
+    (cond ((and (fixnump arg1) (fixnump arg2))
+           (funcall func arg1 arg2))
+          ((or (fixnump arg1) (fixnump arg2))
+           (if (fixnump arg2) (psetq arg1 arg2 arg2 arg1))
+           (if (and (consp arg2)
+                    (eq (%car arg2) func)
+                    (cddr arg2)
+                    (null (cdr (%cddr arg2)))
+                    (or (fixnump (setq val (%cadr arg2)))
+                        (fixnump (setq val (%caddr arg2)))))
+             (list func
+                   (funcall func arg1 val)
+                   (if (eq val (%cadr arg2)) (%caddr arg2) (%cadr arg2)))
+             call))
+          (t call))))
+
+(defun fixnumify (args op &aux (len (length args)))
+  (if (eq len 2)
+    (cons op args)
+    (list op (%car args) (fixnumify (%cdr args) op))))
+
+(defun generic-to-fixnum-n (call env op &aux (args (%cdr call)) targs)
+  (block nil
+    (if (and (%i> (length args) 1)
+             (and (nx-trust-declarations env)
+                  (or (neq op '%i+) (subtypep *nx-form-type* 'fixnum))))
+      (if (dolist (arg args t)
+            (if (nx-form-typep arg 'fixnum env)
+              (push arg targs)
+              (return)))
+        (return
+         (fixnumify (nreverse targs) op))))
+    call))
+
+;;; True if arg is an alternating list of keywords and args, only
+;;; recognizes keywords in keyword package.  Historical note: this
+;;; used to try to ensure that the keyword appeared at most once.  Why
+;;; ? (Even before destructuring, pl-search/getf would have dtrt.)
+;;; Side effects: it's not the right thing to simply pick the value
+;;; associated with the first occurrence of a keyword if the value
+;;; associated with subsequent occurrence could have a side-effect.
+;;; (We -can- ignore a duplicate key if the associated value is
+;;; side-effect free.)
+(defun constant-keywords-p (keys)
+  (when (plistp keys)
+    (do* ((seen ())
+          (keys keys (cddr keys)))
+         ((null keys) t)
+      (let* ((key (car keys)))
+        (if (or (not (keywordp key))
+                (and (memq key seen)
+                     (not (constantp (cadr keys)))))
+          (return))
+        (push key seen)))))
+
+
+(defun remove-explicit-test-keyword-from-test-testnot-key (item list keys default alist testonly)
+  (if (null keys)
+    `(,default ,item ,list)
+     (if (constant-keywords-p keys)
+        (destructuring-bind (&key (test nil test-p)
+                                  (test-not nil test-not-p)
+                                  (key nil key-p))
+                            keys
+          (declare (ignore test-not))
+          (if (and test-p
+                   (not test-not-p)
+                   (or (not key-p)
+                       (and (consp key)
+                            (consp (%cdr key))
+                            (null (%cddr key))
+                            (or (eq (%car key) 'function)
+                                (eq (%car key) 'quote))
+                            (eq (%cadr key) 'identity)))
+                   (consp test)
+                   (consp (%cdr test))
+                   (null (%cddr test))
+                   (or (eq (%car test) 'function)
+                       (eq (%car test) 'quote)))
+            (let* ((testname (%cadr test))
+                   (reduced (cdr (assoc testname alist))))
+              (if reduced
+                `(,reduced ,item ,list)
+                `(,testonly ,item ,list ,test))))))))
+
+
+(defun eql-iff-eq-p (thing env)
+  (if (nx-form-constant-p thing env)
+    (setq thing (nx-form-constant-value thing env))
+    (return-from eql-iff-eq-p
+      (or (nx-form-typep thing  'symbol env)
+	  (nx-form-typep thing 'character env)
+	  (nx-form-typep thing
+			 '(or fixnum
+			   #+64-bit-target single-float
+			   symbol character
+			   (and (not number) (not macptr))) env))))
+  (or (fixnump thing) #+64-bit-target (typep thing 'single-float)
+      (symbolp thing) (characterp thing)
+      (and (not (numberp thing)) (not (macptrp thing)))))
+
+(defun equal-iff-eql-p (thing env)
+  (if (nx-form-constant-p thing env)
+    (setq thing (nx-form-constant-value thing env))
+    (return-from equal-iff-eql-p
+      (nx-form-typep thing
+		     '(and (not cons) (not string) (not bit-vector) (not pathname)) env)))
+  (not (typep thing '(or cons string bit-vector pathname))))
+
+
+(defun fold-constant-subforms (call env)
+    (let* ((constants nil)
+           (forms nil))
+      (declare (list constants forms))
+      (dolist (form (cdr call))
+        (setq form (nx-transform form env))
+        (if (numberp form)
+          (setq constants (%temp-cons form constants))
+          (setq forms (%temp-cons form forms))))
+      (if constants
+        (let* ((op (car call))
+               (constant (if (cdr constants) (handler-case (apply op constants)
+                                               (error (c) (declare (ignore c))
+                                                      (return-from fold-constant-subforms (values call t))))
+                             (car constants))))
+          (values (if forms (cons op (cons constant (reverse forms))) constant) t))
+        (values call nil))))
+
+;;; inline some, etc. in some cases
+;;; in all cases, add dynamic-extent declarations
+(defun some-xx-transform (call env)
+  (destructuring-bind (func predicate sequence &rest args) call
+    (multiple-value-bind (func-constant end-value loop-test)
+                         (case func
+                           (some (values $some nil 'when))
+                           (notany (values $notany t 'when))
+                           (every (values $every t 'unless))
+                           (notevery (values $notevery nil 'unless)))
+      (if args
+        (let ((func-sym (gensym))
+              (seq-sym (gensym))
+              (list-sym (gensym)))
+          `(let ((,func-sym ,predicate)
+                 (,seq-sym ,sequence)
+                 (,list-sym (list ,@args)))
+             (declare (dynamic-extent ,func-sym ,list-sym ,seq-sym))
+             (some-xx-multi ,func-constant ,end-value ,func-sym ,seq-sym ,list-sym)))
+        (let ((loop-function (nx-form-sequence-iterator sequence env)))
+          ;; inline if we know the type of the sequence and if
+          ;; the predicate is a lambda expression
+          ;; otherwise, it blows up the code for not much gain
+          (if (and loop-function
+                   (function-form-p predicate)
+                   (lambda-expression-p (second predicate)))
+            (let ((elt-var (gensym)))
+              (case func
+                (some
+                 `(,loop-function (,elt-var ,sequence ,end-value)
+                                  (let ((result (funcall ,predicate ,elt-var)))
+                                    (when result (return result)))))
+                ((every notevery notany)
+                 `(,loop-function (,elt-var ,sequence ,end-value)
+                                  (,loop-test (funcall ,predicate ,elt-var)
+                                              (return ,(not end-value)))))))
+            (let ((func-sym (gensym))
+                  (seq-sym (gensym)))
+              `(let ((,func-sym ,predicate)
+                     (,seq-sym ,sequence))
+                 (declare (dynamic-extent ,func-sym ,seq-sym))
+                 (some-xx-one ,func-constant ,end-value ,func-sym ,seq-sym)))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; The new (roughly alphabetical) order.
+;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Compiler macros on functions can assume that their arguments have
+;;; already been transformed.
+
+
+(defun transform-real-n-ary-comparision (whole binary-name)
+  (destructuring-bind (n0 &optional (n1 0 n1-p) &rest more) (cdr whole)
+    (if more
+      (if (cdr more)
+        whole
+        (let* ((n2 (car more))
+               (n (gensym)))
+          `(let* ((,n ,n0))
+            (if (,binary-name ,n (setq ,n ,n1))
+              (,binary-name ,n ,n2)))))
+      (if (not n1-p)
+        `(require-type ,n0 'real)
+        `(,binary-name ,n0 ,n1)))))
+
+
+
+(define-compiler-macro < (&whole whole &rest ignore)
+  (declare (ignore ignore))
+  (transform-real-n-ary-comparision whole '<-2))
+
+(define-compiler-macro > (&whole whole &rest ignore)
+  (declare (ignore ignore))
+  (transform-real-n-ary-comparision whole '>-2))
+
+(define-compiler-macro <= (&whole whole &rest ignore)
+  (declare (ignore ignore))
+  (transform-real-n-ary-comparision whole '<=-2))
+
+(define-compiler-macro >= (&whole whole &rest ignore)
+  (declare (ignore ignore))
+  (transform-real-n-ary-comparision whole '>=-2))
+
+
+(define-compiler-macro 1- (x)
+  `(- ,x 1))
+
+(define-compiler-macro 1+ (x)
+  `(+ ,x 1))
+
+(define-compiler-macro append  (&whole call
+                                       &optional arg0
+                                       &rest
+                                       (&whole tail
+                                               &optional (junk nil arg1-p)
+                                               &rest more))
+  ;(append (list x y z) A) -> (list* x y z A)
+  (if (and arg1-p
+           (null more)
+           (consp arg0)
+           (eq (%car arg0) 'list))
+    (cons 'list* (append (%cdr arg0) tail))
+    (if (and arg1-p (null more))
+      `(append-2 ,arg0 ,junk)
+      call)))
+
+
+(define-compiler-macro apply  (&whole call fn arg0 &rest args)
+  ;; Special-case (apply #'make-instance 'name ...)
+  ;; Might be good to make this a little more general, e.g., there
+  ;; may be other things that can be strength-reduced even if we can't
+  ;; get rid of the APPLY.
+  (if (and (consp fn)
+           (or (eq (car fn) 'quote)
+               (eq (car fn) 'function))
+           (consp (cdr fn))
+           (null (cddr fn))
+           (eq (cadr fn) 'make-instance)
+           (consp arg0)
+           (eq (car arg0) 'quote)
+           (consp (cdr arg0))
+           (symbolp (cadr arg0)))
+    (let* ((name (cadr arg0))
+           (class-cell (gensym)))
+      `(let* ((,class-cell (load-time-value (find-class-cell ',name t))))
+        (apply (class-cell-instantiate ,class-cell) ,class-cell ,@args)))
+    (let ((original-fn fn))
+      (if (and arg0
+               (null args)
+               (consp fn)
+               (eq (%car fn) 'function)
+               (null (cdr (%cdr fn)))
+               (consp (setq fn (%cadr fn)))
+               (eq (%car fn) 'lambda))
+        (destructuring-bind (lambda-list &body body) (%cdr fn)
+          `(destructuring-bind ,lambda-list ,arg0 ,@body))
+        (let ((last (%car (last (push arg0 args)))))
+          (if (and (consp last) (memq (%car last) '(cons list* list)))
+            (cons (if (eq (%car last) 'list) 'funcall 'apply)
+                  (cons
+                   original-fn
+                   (nreconc (cdr (reverse args)) (%cdr last))))
+            (if (and (consp last)
+                     (eq (car last) 'quote)
+                     (proper-list-p (cadr last)))
+              (flet ((quotify (arg)
+                       (if (self-evaluating-p arg)
+                         arg
+                         (list 'quote arg))))
+                (cons 'funcall (cons original-fn
+                                     (nreconc (cdr (reverse args)) (mapcar #'quotify (%cadr last))))))
+              call)))))))
+
+
+
+
+(define-compiler-macro assoc (&whole call item list &rest keys)
+  (or (remove-explicit-test-keyword-from-test-testnot-key item list keys 'asseql '((eq . assq) (eql . asseql) (equal . assequal)) 'assoc-test)
+      call))
+
+(define-compiler-macro assequal (&whole call &environment env item list)
+  (if (or (equal-iff-eql-p item env)
+          (and (quoted-form-p list)
+               (proper-list-p (%cadr list))
+               (every (lambda (x) (equal-iff-eql-p (car x) env)) (%cadr list))))
+    `(asseql ,item ,list)
+    call))
+
+(define-compiler-macro asseql (&whole call &environment env item list)
+  (if (or (eql-iff-eq-p item env)
+          (and (quoted-form-p list)
+               (proper-list-p (%cadr list))
+               (every (lambda (x) (eql-iff-eq-p (car x) env)) (%cadr list))))
+    `(assq ,item ,list)
+    call))
+
+(define-compiler-macro assq (item list)
+  (let* ((itemx (gensym))
+         (listx (gensym))
+         (pair (gensym)))
+    `(let* ((,itemx ,item)
+            (,listx ,list))
+      (dolist (,pair ,listx)
+        (when (and ,pair (eq (car ,pair) ,itemx)) (return ,pair))))))
+
+(define-compiler-macro caar (form)
+  `(car (car ,form)))
+
+(define-compiler-macro cadr (form)
+  `(car (cdr ,form)))
+
+(define-compiler-macro cdar (form)
+  `(cdr (car ,form)))
+
+(define-compiler-macro cddr (form)
+  `(cdr (cdr ,form)))
+
+(define-compiler-macro caaar (form)
+  `(car (caar ,form)))
+
+(define-compiler-macro caadr (form)
+  `(car (cadr ,form)))
+
+(define-compiler-macro cadar (form)
+  `(car (cdar ,form)))
+
+(define-compiler-macro caddr (form)
+  `(car (cddr ,form)))
+
+(define-compiler-macro cdaar (form)
+  `(cdr (caar ,form)))
+
+(define-compiler-macro cdadr (form)
+  `(cdr (cadr ,form)))
+
+(define-compiler-macro cddar (form)
+  `(cdr (cdar ,form)))
+
+(define-compiler-macro cdddr (form)
+  `(cdr (cddr ,form)))
+
+(define-compiler-macro caaaar (form)
+  `(car (caaar ,form)))
+
+(define-compiler-macro caaadr (form)
+  `(car (caadr ,form)))
+
+(define-compiler-macro caadar (form)
+  `(car (cadar ,form)))
+
+(define-compiler-macro caaddr (form)
+  `(car (caddr ,form)))
+
+(define-compiler-macro cadaar (form)
+  `(car (cdaar ,form)))
+
+(define-compiler-macro cadadr (form)
+  `(car (cdadr ,form)))
+
+(define-compiler-macro caddar (form)
+  `(car (cddar ,form)))
+
+(define-compiler-macro cadddr (form)
+  `(car (cdddr ,form)))
+
+(define-compiler-macro cdaaar (form)
+  `(cdr (caaar ,form)))
+
+(define-compiler-macro cdaadr (form)
+  `(cdr (caadr ,form)))
+
+(define-compiler-macro cdadar (form)
+  `(cdr (cadar ,form)))
+
+(define-compiler-macro cdaddr (form)
+  `(cdr (caddr ,form)))
+
+(define-compiler-macro cddaar (form)
+  `(cdr (cdaar ,form)))
+
+(define-compiler-macro cddadr (form)
+  `(cdr (cdadr ,form)))
+
+(define-compiler-macro cdddar (form)
+  `(cdr (cddar ,form)))
+
+(define-compiler-macro cddddr (form)
+  `(cdr (cdddr ,form)))
+
+
+
+
+(define-compiler-macro cons (&whole call x y &aux dcall ddcall)
+   (if (consp (setq dcall y))
+     (cond
+      ((or (eq (%car dcall) 'list) (eq (%car dcall) 'list*))
+       ;(CONS A (LIST[*] . args)) -> (LIST[*] A . args)
+       (list* (%car dcall) x (%cdr dcall)))
+      ((or (neq (%car dcall) 'cons) (null (cddr dcall)) (cdddr dcall))
+       call)
+      ((null (setq ddcall (%caddr dcall)))
+       ;(CONS A (CONS B NIL)) -> (LIST A B)
+       `(list ,x ,(%cadr dcall)))
+      ((and (consp ddcall)
+            (eq (%car ddcall) 'cons)
+            (eq (list-length ddcall) 3))
+       ;(CONS A (CONS B (CONS C D))) -> (LIST* A B C D)
+       (list* 'list* x (%cadr dcall) (%cdr ddcall)))
+      (t call))
+     call))
+
+(define-compiler-macro dotimes (&whole call (i n &optional result)
+                                       &body body
+                                       &environment env)
+  (multiple-value-bind (body decls) (parse-body body env)
+    (if (nx-form-typep (setq n (nx-transform n env)) 'fixnum env)
+        (let* ((limit (gensym))
+               (upper (if (nx-form-constant-p n env) (nx-form-constant-value n env) most-positive-fixnum))
+               (top (gensym))
+               (test (gensym)))
+          `(let* ((,limit ,n) (,i 0))
+             ,@decls
+             (declare (fixnum ,limit)
+                      (type (integer 0 ,(if (<= upper 0) 0 upper)) ,i)
+                      (unsettable ,i))
+             (block nil
+               (tagbody
+                 (go ,test)
+                 ,top
+                 ,@body
+                 (locally
+                   (declare (settable ,i))
+                   (setq ,i (1+ ,i)))
+                 ,test
+                 (when (< ,i ,limit) (go ,top)))
+               ,result)))
+        call)))
+
+(define-compiler-macro dpb (&whole call value byte integer)
+  (cond ((and (integerp byte) (> byte 0))
+         (if (integerp value)
+           `(logior ,(dpb value byte 0) (logand ,(lognot byte) ,integer))
+           `(deposit-field (ash ,value ,(byte-position byte)) ,byte ,integer)))
+        ((and (consp byte)
+              (eq (%car byte) 'byte)
+              (eq (list-length (%cdr byte)) 2))
+         `(deposit-byte ,value ,(%cadr byte) ,(%caddr byte) ,integer))
+        (t call)))
+
+(define-compiler-macro eql (&whole call &environment env v1 v2)
+  (if (or (eql-iff-eq-p v1 env) (eql-iff-eq-p v2 env))
+    `(eq ,v1 ,v2)
+    call))
+
+(define-compiler-macro every (&whole call &environment env &rest ignore)
+  (declare (ignore ignore))
+  (some-xx-transform call env))
+
+
+(define-compiler-macro identity (form) form)
+
+(define-compiler-macro if (&whole call test true &optional false &environment env)
+  (let ((test-val (nx-transform test env)))
+    (if (nx-form-constant-p test-val env)
+      (if (nx-form-constant-value test-val env)
+	true
+	false)
+      call)))
+
+(define-compiler-macro %ilsr (&whole call shift value)
+  (if (eql shift 0)
+    value
+    (if (eql value 0)
+      `(progn ,shift 0)
+      call)))
+
+(defun string-designator-p (object)
+  (typecase object
+    (character t)
+    (symbol t)
+    (string t)))
+
+(define-compiler-macro ldb (&whole call &environment env byte integer)
+   (cond ((and (integerp byte) (> byte 0))
+          (let ((size (byte-size byte))
+                (position (byte-position byte)))
+            (cond ((nx-form-typep integer 'fixnum env)
+                   `(logand ,(byte-mask size)
+                     (the fixnum (ash ,integer ,(- position)))))
+                  (t `(load-byte ,size ,position ,integer)))))
+         ((and (consp byte)
+               (eq (%car byte) 'byte)
+               (eq (list-length (%cdr byte)) 2))
+          (let ((size (%cadr byte))
+                (position (%caddr byte)))
+            (if (and (nx-form-typep integer 'fixnum env) (fixnump position))
+              ;; I'm not sure this is worth doing
+              `(logand (byte-mask ,size) (the fixnum (ash ,integer ,(- position))))
+              ;; this IS worth doing
+              `(load-byte ,size ,position ,integer))))
+         (t call)))
+
+(define-compiler-macro length (&whole call &environment env seq)
+  (if (nx-form-typep seq '(simple-array * (*)) env)
+    `(uvsize ,seq)
+    call))
+
+(define-compiler-macro let (&whole call (&optional (first nil first-p) &rest rest) &body body)
+  (if first-p
+    (if rest
+      call
+      `(let* (,first) ,@body))
+    `(locally ,@body)))
+
+(define-compiler-macro let* (&whole call (&rest bindings) &body body)
+  (if bindings
+    call
+    `(locally ,@body)))
+
+(define-compiler-macro list* (&whole call &rest rest  &aux (n (list-length rest)) last)
+  (cond ((%izerop n) nil)
+        ((null (setq last (%car (last call))))
+         (cons 'list (nreverse (cdr (reverse (cdr call))))))
+        ((and (consp last) (memq (%car last) '(list* list cons)))
+         (cons (if (eq (%car last) 'cons) 'list* (%car last))
+                                 (nreconc (cdr (reverse (cdr call))) (%cdr last))))
+        ((eq n 1) (list 'values last))
+        ((eq n 2) (cons 'cons (%cdr call)))
+        (t call)))
+
+
+
+;;;(CONS X NIL) is same size as (LIST X) and faster.
+(define-compiler-macro list  (&whole call &optional (first nil first-p) &rest more)
+  (if more
+    call
+    (if first-p
+      `(cons ,first nil))))
+
+
+(define-compiler-macro locally (&whole call &body body &environment env)
+  (multiple-value-bind (body decls) (parse-body body env nil)
+    (if decls
+      call
+      `(progn ,@body))))
+
+(defun target-element-type-type-keyword (typespec &optional env)
+  (let ((ctype (specifier-type-if-known `(array ,typespec) env)))
+    (when ctype
+      (funcall (arch::target-array-type-name-from-ctype-function
+		(backend-target-arch *target-backend*))
+	       ctype))))
+
+(defun infer-array-type (dims element-type element-type-p displaced-to-p fill-pointer-p adjustable-p env)
+  (let* ((ctype (make-array-ctype :complexp (or displaced-to-p fill-pointer-p adjustable-p))))
+    (if (nx-form-constant-p dims env)
+      (let* ((dims (nx-form-constant-value dims env)))
+        (if (listp dims)
+          (progn
+            (unless (every #'fixnump dims)
+              (warn "Funky-looking array dimensions ~s in MAKE-ARRAY call" dims))
+            (setf (array-ctype-dimensions ctype) dims))
+          (progn
+            (unless (typep dims 'fixnum)
+              (warn "Funky-looking array dimensions ~s in MAKE-ARRAY call" dims))
+            (setf (array-ctype-dimensions ctype) (list dims)))))
+      (if (atom dims)
+        (if (nx-form-typep dims 'fixnum env)
+          (setf (array-ctype-dimensions ctype)
+                (if (typep (setq dims (nx-transform dims env)) 'fixnum)
+                  (list dims)
+                  (list '*)))
+          (setf (array-ctype-dimensions ctype) '*))
+        (if (eq (car dims) 'list)
+          (setf (array-ctype-dimensions ctype)
+                (mapcar #'(lambda (d)
+                            (if (typep (setq d (nx-transform d env)) 'fixnum)
+                              d
+                              '*))
+                        (cdr dims)))
+          ;; Wimp out
+          (setf (array-ctype-dimensions ctype)
+                '*))))
+    (let* ((typespec (if element-type-p
+                       (if (nx-form-constant-p element-type env)
+                         (nx-form-constant-value element-type env)
+                         '*)
+                       t))
+           (element-type (specifier-type-if-known typespec env :whine t)))
+      (setf (array-ctype-element-type ctype) (or element-type *wild-type*))
+      (specialize-array-type ctype))
+    (type-specifier ctype)))
+
+
+
+(define-compiler-macro make-array (&whole call &environment env dims &rest keys)
+  (if (constant-keywords-p keys)
+    (destructuring-bind (&key (element-type t element-type-p)
+                              (displaced-to () displaced-to-p)
+                              (displaced-index-offset () displaced-index-offset-p)
+                              (adjustable () adjustable-p)
+                              (fill-pointer () fill-pointer-p)
+                              (initial-element () initial-element-p)
+                              (initial-contents () initial-contents-p))
+        keys
+      (declare (ignorable element-type element-type-p
+                          displaced-to displaced-to-p
+                          displaced-index-offset displaced-index-offset-p
+                          adjustable adjustable-p
+                          fill-pointer fill-pointer-p
+                          initial-element initial-element-p
+                          initial-contents initial-contents-p))
+      (let* ((element-type-keyword nil)
+             (expansion
+              (cond ((and initial-element-p initial-contents-p)
+		     (signal-program-error  "Incompatible arguments :INITIAL-ELEMENT and :INITIAL-CONTENTS in ~s" call)
+                     call)
+                    (displaced-to-p
+                     (if (or initial-element-p initial-contents-p element-type-p)
+                       (comp-make-array-1 dims keys)
+                       (comp-make-displaced-array dims keys)))
+                    ((or displaced-index-offset-p
+                         (not (nx-form-constant-p element-type env))
+                         (null (setq element-type-keyword
+                                     (target-element-type-type-keyword
+                                      (nx-form-constant-value element-type env) env))))
+                     (comp-make-array-1 dims keys))
+                    ((and (typep element-type-keyword 'keyword)
+                          (nx-form-typep dims 'fixnum env)
+                          (null (or adjustable fill-pointer initial-contents
+                                    initial-contents-p)))
+                     (if
+                       (or (null initial-element-p)
+                           (cond ((eql element-type-keyword :double-float-vector)
+                                  (eql initial-element 0.0d0))
+                                 ((eql element-type-keyword :single-float-vector)
+                                  (eql initial-element 0.0s0))
+                                 ((eql element-type :simple-string)
+                                  (eql initial-element #\Null))
+                                 (t (eql initial-element 0))))
+                       `(allocate-typed-vector ,element-type-keyword ,dims)
+                       `(allocate-typed-vector ,element-type-keyword ,dims ,initial-element)))
+                    (t                        ;Should do more here
+                     (comp-make-uarray dims keys (type-keyword-code element-type-keyword)))))
+             (type (if (nx-trust-declarations env)
+                     (infer-array-type dims element-type element-type-p displaced-to-p fill-pointer-p adjustable-p env)
+                     t)))
+        `(the ,type ,expansion)))
+
+        call))
+
+(defun comp-make-displaced-array (dims keys)
+  (let* ((call-list (make-list 4 :initial-element nil))
+	 (dims-var (make-symbol "DIMS"))
+         (let-list (comp-nuke-keys keys
+                                   '((:displaced-to 0)
+                                     (:fill-pointer 1)
+                                     (:adjustable 2)
+                                     (:displaced-index-offset 3))
+                                   call-list
+				   `((,dims-var ,dims)))))
+
+    `(let ,let-list
+       (%make-displaced-array ,dims-var ,@call-list t))))
+
+(defun comp-make-uarray (dims keys subtype)
+  (if (null keys)
+    `(%make-simple-array ,subtype ,dims)
+    (let* ((call-list (make-list 6))
+           (dims-var (make-symbol "DIMS"))
+           (let-list (comp-nuke-keys keys
+                                     '((:adjustable 0)
+                                       (:fill-pointer 1)
+                                       (:initial-element 2 3)
+                                       (:initial-contents 4 5))
+                                     call-list
+                                     `((,dims-var ,dims)))))
+      `(let ,let-list
+        (make-uarray-1 ,subtype ,dims-var ,@call-list nil nil)))))
+
+(defun comp-make-array-1 (dims keys)
+  (let* ((call-list (make-list 10 :initial-element nil))
+	 (dims-var (make-symbol "DIMS"))
+         (let-list (comp-nuke-keys keys
+                                   '((:element-type 0 1)
+                                     (:displaced-to 2)
+                                     (:displaced-index-offset 3)
+                                     (:adjustable 4)
+                                     (:fill-pointer 5)
+                                     (:initial-element 6 7)
+                                     (:initial-contents 8 9))
+                                   call-list
+				   `((,dims-var ,dims)))))
+    `(let ,let-list
+       (make-array-1 ,dims-var ,@call-list nil))))
+
+(defun comp-nuke-keys (keys key-list call-list &optional required-bindings)
+  ; side effects call list, returns a let-list
+  (let* ((let-list (reverse required-bindings))
+         (seen nil))
+    (do ((lst keys (cddr lst)))
+        ((null lst) nil)
+      (let* ((key (car lst))
+             (val (cadr lst))
+             (ass (assq key key-list))
+             (vpos (cadr ass))
+             (ppos (caddr ass)))
+        (when ass
+          (unless (memq vpos seen)
+            (push vpos seen)
+            (when (not (constantp val))
+              (let ((gen (gensym)))
+                (setq let-list (cons (list gen val) let-list)) ; reverse him
+                (setq val gen)))
+            (rplaca (nthcdr vpos call-list) val)
+            (if ppos (rplaca (nthcdr ppos call-list) t))))))
+    (nreverse let-list)))
+
+(define-compiler-macro make-instance (&whole call class &rest initargs)
+  (if (and (listp class)
+           (eq (car class) 'quote)
+           (symbolp (cadr class))
+           (null (cddr class)))
+    (let* ((cell (gensym)))
+      `(let* ((,cell (load-time-value (find-class-cell ,class t))))
+        (funcall (class-cell-instantiate ,cell) ,cell ,@initargs)))
+    call))
+
+
+
+
+
+
+
+(define-compiler-macro mapc  (&whole call fn lst &rest more)
+  (if more
+    call
+    (let* ((temp-var (gensym))
+           (elt-var (gensym))
+           (fn-var (gensym)))
+       `(let* ((,fn-var ,fn)
+               (,temp-var ,lst))
+          (dolist (,elt-var ,temp-var ,temp-var)
+            (funcall ,fn-var ,elt-var))
+          ))))
+
+(define-compiler-macro mapcar (&whole call fn lst &rest more)
+  (if more
+    call
+    (let* ((temp-var (gensym))
+           (result-var (gensym))
+           (elt-var (gensym))
+           (fn-var (gensym)))
+      `(let* ((,temp-var (cons nil nil))
+              (,result-var ,temp-var)
+              (,fn-var ,fn))
+         (declare (dynamic-extent ,temp-var)
+                  (type cons ,temp-var ,result-var))
+         (dolist (,elt-var ,lst (cdr ,result-var))
+           (setq ,temp-var (setf (cdr ,temp-var) (list (funcall ,fn-var ,elt-var)))))))))
+
+(define-compiler-macro member (&whole call item list &rest keys)
+  (or (remove-explicit-test-keyword-from-test-testnot-key item list keys 'memeql '((eq . memq) (eql . memeql) (equal . memequal)) 'member-test)
+      call))
+
+(define-compiler-macro memequal (&whole call &environment env item list)
+  (if (or (equal-iff-eql-p item env)
+          (and (quoted-form-p list)
+               (proper-list-p (%cadr list))
+               (every (lambda (elt) (equal-iff-eql-p elt env)) (%cadr list))))
+    `(memeql ,item ,list)
+    call))
+
+(define-compiler-macro memeql (&whole call &environment env item list)
+  (if (or (eql-iff-eq-p item env)
+          (and (quoted-form-p list)
+               (proper-list-p (%cadr list))
+               (every (lambda (elt) (eql-iff-eq-p elt env)) (%cadr list))))
+    `(memq ,item ,list)
+    call))
+
+(define-compiler-macro memq (item list)
+  ;;(memq x '(y)) => (if (eq x 'y) '(y))
+  ;;Would it be worth making a two elt list into an OR?  Maybe if
+  ;;optimizing for speed...
+   (if (and (or (quoted-form-p list)
+                (null list))
+            (null (cdr (%cadr list))))
+     (if list `(if (eq ,item ',(%caadr list)) ,list))
+     (let* ((x (gensym))
+            (tail (gensym)))
+       `(do* ((,x ,item)
+              (,tail ,list (cdr (the list ,tail))))
+         ((null ,tail))
+         (if (eq (car ,tail) ,x) (return ,tail))))))
+
+(define-compiler-macro minusp (x)
+  `(< ,x 0))
+
+(define-compiler-macro notany (&whole call &environment env &rest ignore)
+  (declare (ignore ignore))
+  (some-xx-transform call env))
+
+(define-compiler-macro notevery (&whole call &environment env &rest ignore)
+  (declare (ignore ignore))
+  (some-xx-transform call env))
+
+(define-compiler-macro nth  (count list)
+   (if (and (fixnump count)
+            (%i>= count 0)
+            (%i< count 3))
+     `(,(svref '#(car cadr caddr) count) ,list)
+     `(car (nthcdr ,count ,list))))
+
+(define-compiler-macro nthcdr (count list)
+  (if (and (fixnump count)
+           (%i>= count 0)
+           (%i< count 4))
+     (if (%izerop count)
+       `(require-type ,list 'list)
+       `(,(svref '#(cdr cddr cdddr) (%i- count 1)) ,list))
+    (let* ((i (gensym))
+           (n (gensym))                 ; evaluation order
+           (tail (gensym)))
+      `(let* ((,n (require-type ,count 'unsigned-byte))
+              (,tail (require-type ,list 'list)))
+        (dotimes (,i ,n ,tail)
+          (unless (setq ,tail (cdr ,tail))
+            (return nil)))))))
+
+(define-compiler-macro plusp (x)
+  `(> ,x 0))
+
+(define-compiler-macro progn (&whole call &optional (first nil first-p) &rest rest)
+  (if first-p
+    (if rest call first)))
+
+;;; This isn't quite right... The idea is that (car (require-type foo
+;;; 'list)) ;can become just (<typechecking-car> foo) [regardless of
+;;; optimize settings], ;but I don't think this can be done just with
+;;; optimizers... For now, at least try to get it to become (%car
+;;; (<typecheck> foo)).
+(define-compiler-macro require-type (&whole call &environment env arg type &aux ctype)
+  (cond ((and (or (eq type t)
+                  (and (nx-form-constant-p type env)
+                       (setq type (nx-form-constant-value type env))))
+              (setq ctype (specifier-type-if-known type env :whine t)))
+         (cond ((nx-form-typep arg type env) arg)
+               ((and (nx-trust-declarations env) ;; if don't trust declarations, don't bother.
+                     (cond ((eq type 'simple-vector)
+                            `(the simple-vector (require-simple-vector ,arg)))
+                           ((eq type 'simple-string)
+                            `(the simple-string (require-simple-string ,arg)))
+                           ((eq type 'integer)
+                            `(the integer (require-integer ,arg)))
+                           ((eq type 'fixnum)
+                            `(the fixnum (require-fixnum ,arg)))
+                           ((eq type 'real)
+                            `(the real (require-real ,arg)))
+                           ((eq type 'list)
+                            `(the list (require-list ,arg)))
+                           ((eq type 'character)
+                            `(the character (require-character ,arg)))
+                           ((eq type 'number)
+                            `(the number (require-number ,arg)))
+                           ((eq type 'symbol)
+                            `(the symbol (require-symbol ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(signed-byte 8)))
+                            `(the (signed-byte 8) (require-s8 ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(unsigned-byte 8)))
+                            `(the (unsigned-byte 8) (require-u8 ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(signed-byte 16)))
+                            `(the (signed-byte 16) (require-s16 ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(unsigned-byte 16)))
+                            `(the (unsigned-byte 16) (require-u16 ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(signed-byte 32)))
+                            `(the (signed-byte 32) (require-s32 ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(unsigned-byte 32)))
+                            `(the (unsigned-byte 32) (require-u32 ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(signed-byte 64)))
+                            `(the (signed-byte 64) (require-s64 ,arg)))
+                           ((type= ctype
+                                   (specifier-type '(unsigned-byte 64)))
+                            `(the (unsigned-byte 64) (require-u64 ,arg)))
+                           #+nil
+                           ((and (symbolp type)
+                                 (let ((simpler (type-predicate type)))
+                                   (if simpler `(the ,type (%require-type ,arg ',simpler))))))
+                           #+nil
+                           ((and (symbolp type)(find-class type nil env))
+                            `(%require-type-class-cell ,arg (load-time-value (find-class-cell ',type t))))
+                           (t (let* ((val (gensym)))
+                                `(the ,type
+                                   (let* ((,val ,arg))
+                                     (if (typep ,val ',type)
+                                       ,val
+                                       (%kernel-restart $xwrongtype ,val ',type)))))))))
+               (t (let* ((val (gensym)))
+                    `(let* ((,val ,arg))
+                       (if (typep ,val ',type)
+                         ,val
+                         (%kernel-restart $xwrongtype ,val ',type)))))))
+        (t call)))
+
+(define-compiler-macro proclaim (&whole call decl)
+   (if (and (quoted-form-p decl)
+            (eq (car (setq decl (%cadr decl))) 'special))
+       (do ((vars (%cdr decl) (%cdr vars)) (decls ()))
+           ((null vars)
+            (cons 'progn (nreverse decls)))
+         (unless (and (car vars)
+                      (neq (%car vars) t)
+                      (symbolp (%car vars)))
+            (return call))
+         (push (list '%proclaim-special (list 'quote (%car vars))) decls))
+       call))
+
+
+(define-compiler-macro some (&whole call &environment env &rest ignore)
+  (declare (ignore ignore))
+  (some-xx-transform call env))
+
+(define-compiler-macro struct-ref (&whole call &environment env struct offset)
+   (if (nx-inhibit-safety-checking env)
+    `(%svref ,struct ,offset)
+    call))
+
+;;; expand find-if and find-if-not
+
+(define-compiler-macro find-if (test sequence &rest keys)
+  `(find ,test ,sequence
+        :test #'funcall
+        ,@keys))
+
+(define-compiler-macro find-if-not (test sequence &rest keys)
+  `(find ,test ,sequence
+        :test-not #'funcall
+        ,@keys))
+
+;;; inline some cases, and use a positional function in others
+
+(define-compiler-macro find (&whole call &environment env
+                                    item sequence &rest keys)
+  (if (constant-keywords-p keys)
+    (destructuring-bind (&key from-end test test-not (start 0) end key) keys
+      (if (and (eql start 0)
+               (null end)
+               (null from-end)
+               (not (and test test-not)))
+        (let ((find-test (or test test-not '#'eql))
+              (loop-test (if test-not 'unless 'when))
+              (loop-function (nx-form-sequence-iterator sequence env)))
+          (if loop-function
+            (let ((item-var (unless (or (nx-form-constant-p item env)
+                                        (and (equal find-test '#'funcall)
+                                             (function-form-p item)))
+                              (gensym)))
+                  (elt-var (gensym)))
+              `(let (,@(when item-var `((,item-var ,item))))
+                 (,loop-function (,elt-var ,sequence)
+                                 (,loop-test (funcall ,find-test ,(or item-var item)
+                                                      (funcall ,(or key '#'identity) ,elt-var))
+                                             (return ,elt-var)))))
+            (let ((find-function (if test-not 'find-positional-test-not-key 'find-positional-test-key))
+                  (item-var (gensym))
+                  (sequence-var (gensym))
+                  (test-var (gensym))
+                  (key-var (gensym)))
+              `(let ((,item-var ,item)
+                     (,sequence-var ,sequence)
+                     (,test-var ,(or test test-not))
+                     (,key-var ,key))
+                 (declare (dynamic-extent ,item-var ,sequence-var ,test-var ,key-var))
+                 (,find-function ,item-var ,sequence-var ,test-var ,key-var)))))
+        call))
+      call))
+
+;;; expand position-if and position-if-not
+
+(define-compiler-macro position-if (test sequence &rest keys)
+  `(position ,test ,sequence
+             :test #'funcall
+             ,@keys))
+
+(define-compiler-macro position-if-not (test sequence &rest keys)
+  `(position ,test ,sequence
+             :test-not #'funcall
+             ,@keys))
+
+;;; inline some cases, and use positional functions for others
+
+(define-compiler-macro position (&whole call &environment env
+                                        item sequence &rest keys)
+  (if (constant-keywords-p keys)
+    (destructuring-bind (&key from-end test test-not (start 0) end key) keys
+      (if (and (eql start 0)
+               (null end)
+               (null from-end)
+               (not (and test test-not)))
+        (let ((position-test (or test test-not '#'eql))
+              (loop-test (if test-not 'unless 'when)))
+          (cond ((nx-form-typep sequence 'list env)
+                 (let ((item-var (unless (or (nx-form-constant-p item env)
+                                             (and (equal position-test '#'funcall)
+                                                  (function-form-p item)))
+                                   (gensym)))
+                       (elt-var (gensym))
+                       (position-var (gensym)))
+                   `(let (,@(when item-var `((,item-var ,item)))
+                          (,position-var 0))
+                      (dolist (,elt-var ,sequence)
+                        (,loop-test (funcall ,position-test ,(or item-var item)
+                                             (funcall ,(or key '#'identity) ,elt-var))
+                                    (return ,position-var))
+                        (incf ,position-var)))))
+                ((nx-form-typep sequence 'vector env)
+                 (let ((item-var (unless (or (nx-form-constant-p item env)
+                                             (and (equal position-test '#'funcall)
+                                                  (function-form-p item)))
+                                   (gensym)))
+                       (sequence-var (gensym))
+                       (position-var (gensym)))
+                   `(let (,@(when item-var `((,item-var ,item)))
+                          (,sequence-var ,sequence))
+                      ,@(let ((type (nx-form-type sequence env)))
+                          (unless (eq type t)
+                            `((declare (type ,type ,sequence-var)))))
+                      (dotimes (,position-var (length ,sequence-var))
+                        (,loop-test (funcall ,position-test ,(or item-var item)
+                                             (funcall ,(or key '#'identity)
+                                                      (locally (declare (optimize (speed 3) (safety 0)))
+                                                        (aref ,sequence ,position-var))))
+                                    (return ,position-var))))))
+                (t
+                 (let ((position-function (if test-not
+                                            'position-positional-test-not-key
+                                            'position-positional-test-key))
+                       (item-var (gensym))
+                       (sequence-var (gensym))
+                       (test-var (gensym))
+                       (key-var (gensym)))
+                   `(let ((,item-var ,item)
+                          (,sequence-var ,sequence)
+                          (,test-var ,(or test test-not))
+                          (,key-var ,key))
+                      (declare (dynamic-extent ,sequence-var ,test-var ,key-var))
+                      (,position-function ,item-var ,sequence-var ,test-var ,key-var))))))
+        call))
+    call))
+
+;;; inline some cases of remove-if and remove-if-not
+
+(define-compiler-macro remove-if (&whole call &environment env &rest ignore)
+  (declare (ignore ignore))
+  (remove-if-transform call env))
+
+(define-compiler-macro remove-if-not (&whole call &environment env &rest ignore)
+  (declare (ignore ignore))
+  (remove-if-transform call env))
+
+(defun remove-if-transform (call env)
+  (destructuring-bind (function test sequence &rest keys) call
+    (if (constant-keywords-p keys)
+      (destructuring-bind (&key from-end (start 0) end count (key '#'identity)) keys
+        (if (and (eql start 0)
+                 (null end)
+                 (null from-end)
+                 (null count)
+                 (nx-form-typep sequence 'list env))
+          ;; only do the list case, since it's hard to collect vector results
+          (let ((temp-var (gensym))
+                (result-var (gensym))
+                (elt-var (gensym))
+                (loop-test (ecase function (remove-if 'unless) (remove-if-not 'when))))
+            `(the list
+               (let* ((,temp-var (cons nil nil))
+                      (,result-var ,temp-var))
+                 (declare (dynamic-extent ,temp-var))
+                 (dolist (,elt-var ,sequence (%cdr ,result-var))
+                   (,loop-test (funcall ,test (funcall ,key ,elt-var))
+                               (setq ,temp-var
+                                     (%cdr
+                                      (%rplacd ,temp-var (list ,elt-var)))))))))
+          call))
+      call)))
+
+
+
+(define-compiler-macro struct-set (&whole call &environment env struct offset new)
+  (if (nx-inhibit-safety-checking env)
+    `(%svset ,struct ,offset ,new)
+    call))
+
+(define-compiler-macro zerop (arg &environment env)
+  (let* ((z (if (nx-form-typep arg 'float env)
+	      (coerce 0 (nx-form-type arg env))
+	      0)))
+    `(= ,arg ,z)))
+
+
+(define-compiler-macro = (&whole w n0 &optional (n1 nil n1p) &rest more)
+  (if (not n1p)
+    `(require-type ,n0 'number)
+    (if more
+      w
+      `(=-2 ,n0 ,n1))))
+
+(define-compiler-macro /= (&whole w n0 &optional (n1 nil n1p) &rest more)
+  (if (not n1p)
+    `(require-type ,n0 'number)
+    (if more
+      w
+      `(/=-2 ,n0 ,n1))))
+
+(define-compiler-macro + (&optional (n0 nil n0p) (n1 nil n1p) &rest more &environment env)
+  (if more
+    (if (and (nx-trust-declarations env)
+             (subtypep *nx-form-type* 'fixnum)
+             (nx-form-typep n0 'fixnum env)
+             (nx-form-typep n1 'fixnum env)
+             (dolist (m more t)
+               (unless (nx-form-typep m 'fixnum env)
+                 (return nil))))
+      `(+-2 ,n0 (the fixnum (+ ,n1 ,@more)))
+      `(+ (+-2 ,n0 ,n1) ,@more))
+    (if n1p
+      `(+-2 ,n0 ,n1)
+      (if n0p
+        `(require-type ,n0 'number)
+        0))))
+
+(define-compiler-macro - (n0 &optional (n1 nil n1p) &rest more)
+  (if more
+    `(- (--2 ,n0 ,n1) ,@more)
+    (if n1p
+      `(--2 ,n0 ,n1)
+      `(%negate ,n0))))
+
+(define-compiler-macro * (&optional (n0 nil n0p) (n1 nil n1p) &rest more)
+  (if more
+    `(*-2 ,n0 (* ,n1 ,@more))
+    (if n1p
+      `(*-2 ,n0 ,n1)
+      (if n0p
+        `(require-type ,n0 'number)
+        1))))
+
+(define-compiler-macro / (&whole w n0 &optional (n1 nil n1p) &rest more)
+  (if more
+    w
+    (if n1p
+      `(/-2 ,n0 ,n1)
+      `(%quo-1 ,n0))))
+
+;;; beware of limits - truncate of most-negative-fixnum & -1 ain't a
+;;; fixnum - too bad
+(define-compiler-macro truncate (&whole w &environment env n0 &optional (n1 nil n1p))
+  (let ((*nx-form-type* t))
+    (if (nx-form-typep n0 'fixnum env)
+      (if (not n1p)
+        n0
+        (if (nx-form-typep n1 'fixnum env)
+          `(%fixnum-truncate ,n0 ,n1)
+          w))
+      w)))
+
+(define-compiler-macro floor (&whole w &environment env n0 &optional (n1 nil n1p))
+  (let ((*nx-form-type* t))
+    (if (nx-form-typep n0 'fixnum env)
+      (if (not n1p)
+        n0
+        (if (nx-form-typep n1 'fixnum env)
+          `(%fixnum-floor ,n0 ,n1)
+          w))
+      w)))
+
+(define-compiler-macro round (&whole w &environment env n0 &optional (n1 nil n1p))
+  (let ((*nx-form-type* t)) ; it doesn't matter what the result type is declared to be
+    (if (nx-form-typep n0 'fixnum env)
+      (if (not n1p)
+        n0
+        (if (nx-form-typep n1 'fixnum env)
+          `(%fixnum-round ,n0 ,n1)
+          w))
+      w)))
+
+(define-compiler-macro ceiling (&whole w &environment env n0 &optional (n1 nil n1p))
+  (let ((*nx-form-type* t))
+    (if (nx-form-typep n0 'fixnum env)
+      (if (not n1p)
+        n0
+        (if (nx-form-typep n1 'fixnum env)
+          `(%fixnum-ceiling ,n0 ,n1)
+          w))
+      w)))
+
+(define-compiler-macro oddp (&whole w &environment env n0)
+  (if (nx-form-typep n0 'fixnum env)
+    `(logbitp 0 (the fixnum ,n0))
+    w))
+
+(define-compiler-macro evenp (&whole w &environment env n0)
+  (if (nx-form-typep n0 'fixnum env)
+    `(not (logbitp 0 (the fixnum ,n0)))
+    w))
+
+
+(define-compiler-macro logandc2 (n0 n1)
+  (let ((n1var (gensym))
+        (n0var (gensym)))
+    `(let ((,n0var ,n0)
+           (,n1var ,n1))
+       (logandc1 ,n1var ,n0var))))
+
+(define-compiler-macro logorc2 (n0 n1)
+  (let ((n1var (gensym))
+        (n0var (gensym)))
+    `(let ((,n0var ,n0)
+           (,n1var ,n1))
+       (logorc1 ,n1var ,n0var))))
+
+(define-compiler-macro lognand (n0 n1)
+  `(lognot (logand ,n0 ,n1)))
+
+(define-compiler-macro lognor (n0 n1)
+  `(lognot (logior ,n0 ,n1)))
+
+
+(defun transform-logop (whole identity binop &optional (transform-complement t))
+  (destructuring-bind (op &optional (n0 nil n0p) (n1 nil n1p) &rest more) whole
+    (if (and n1p (eql n0 identity))
+      `(,op ,n1 ,@more)
+      (if (and transform-complement n1p (eql n0 (lognot identity)))
+        `(progn
+           (,op ,n1 ,@more)
+           ,(lognot identity))
+        (if more
+          (if (cdr more)
+            whole
+            `(,binop ,n0 (,binop ,n1 ,(car more))))
+          (if n1p
+            `(,binop ,n0 ,n1)
+            (if n0p
+              `(require-type ,n0 'integer)
+              identity)))))))
+
+(define-compiler-macro logand (&whole w &rest all)
+  (declare (ignore all))
+  (transform-logop w -1 'logand-2))
+
+(define-compiler-macro logior (&whole w &rest all)
+  (declare (ignore all))
+  (transform-logop w 0 'logior-2))
+
+(define-compiler-macro logxor (&whole w &rest all)
+  (declare (ignore all))
+  (transform-logop w 0 'logxor-2 nil))
+
+(define-compiler-macro lognot (&whole w &environment env n1)
+  (if (nx-form-typep n1 'fixnum env)
+    `(%ilognot ,n1)
+    w))
+
+(define-compiler-macro logtest (&whole w &environment env n1 n2)
+  (if (and (nx-form-typep n1 'fixnum env)
+           (nx-form-typep n2 'fixnum env))
+    `(not (eql 0 (logand ,n1 ,n2)))
+    w))
+
+
+(defmacro defsynonym (from to)
+  ;Should maybe check for circularities.
+  `(progn
+     (setf (compiler-macro-function ',from) nil)
+     (let ((pair (assq ',from *nx-synonyms*)))
+       (if pair (rplacd pair ',to)
+           (push (cons ',from ',to)
+                 *nx-synonyms*))
+       ',to)))
+
+(defsynonym first car)
+(defsynonym second cadr)
+(defsynonym third caddr)
+(defsynonym fourth cadddr)
+(defsynonym rest cdr)
+
+
+(defsynonym functionp lfunp)
+(defsynonym null not)
+(defsynonym char-int char-code)
+
+;;; Improvemets file by Bob Cassels
+;;; Just what are "Improvemets", anyway ?
+
+;;; Optimize some CL sequence functions, mostly by inlining them in
+;;; simple cases when the type of the sequence is known.  In some
+;;; cases, dynamic-extent declarations are automatically inserted.
+;;; For some sequence functions, if the type of the sequence is known
+;;; at compile time, the function is inlined.  If the type isn't known
+;;; but the call is "simple", a call to a faster (positional-arg)
+;;; function is substituted.
+
+
+(defun nx-form-sequence-iterator (sequence-form env)
+  (cond ((nx-form-typep sequence-form 'vector env) 'dovector)
+        ((nx-form-typep sequence-form 'list env) 'dolist)))
+
+(defun function-form-p (form)
+   ;; c.f. quoted-form-p
+   (and (consp form)
+        (eq (%car form) 'function)
+        (consp (%cdr form))
+        (null (%cdr (%cdr form)))))
+
+
+;; Return a form that checks to see if THING is if type CTYPE, or
+;; NIL if we can't do that for some reason.
+(defun optimize-ctypep (thing ctype)
+  (when (eq *target-backend* *host-backend*)
+    (typecase ctype
+      (numeric-ctype
+       (cond ((eq :real (numeric-ctype-complexp ctype))
+              (let* ((low (numeric-ctype-low ctype))
+                     (high (numeric-ctype-high ctype))
+                     (class (numeric-ctype-class ctype))
+                     (format (numeric-ctype-format ctype))
+                     (type (if (eq class 'float)
+                             (or format class)
+                             (or class 'real))))
+                (cond ((and low (eql low high) (or (not (eq class 'float))
+                                                   format))
+                       `(eql ,thing ,low))
+                      ((and (eq type 'float)
+                            (or low high)
+                            (or (null low)
+                                (typep low 'single-float)
+                                (not (null (ignore-errors
+                                             (coerce (if (atom low)
+                                                       low
+                                                       (car low))
+                                                     'single-float)))))
+                            (or (null high)
+                                (typep high 'single-float)
+                                (not (null (ignore-errors
+                                             (coerce (if (atom high)
+                                                       high
+                                                       (car high))
+                                                     'single-float))))))
+                       (let* ((temp (gensym)))
+                         (flet ((bounded-float (type low high)
+                                  `(,type
+                                    ,(if low
+                                         (if (listp low)
+                                           (list (coerce (car low) type))
+                                           (coerce low type))
+                                         '*)
+                                    ,(if high
+                                         (if (listp high)
+                                           (list (coerce (car high) type))
+                                           (coerce high type))
+                                         '*))))
+                         `(let* ((,temp ,thing))
+                           (or (typep ,temp ',(bounded-float 'single-float low high))
+                            (typep ,temp ',(bounded-float 'double-float low high)))))))
+                      (t
+                       (let* ((temp (gensym)))
+                         (if (and (typep low 'fixnum) (typep high 'fixnum)
+                                  (eq class 'integer))
+                           (setq type 'fixnum))
+                         (if (or low high)
+                           `(let* ((,temp ,thing))
+                             (and (typep ,temp ',type)
+                              ,@(if low `((,(if (consp low) '> '>=) (the ,type ,temp) ,(if (consp low) (car low) low))))
+                              ,@(if high `((,(if (consp high) '< '<=) (the ,type ,temp) ,(if (consp high) (car high) high))))))
+                           `(typep ,thing ',type)))))))
+             (t `(numeric-%%typep ,thing ,ctype))))
+      (array-ctype
+       (or
+        (let* ((typecode (array-ctype-typecode ctype))
+               (dims (array-ctype-dimensions ctype)))
+          (cond ((and typecode (consp dims) (null (cdr dims)))
+                 (case (array-ctype-complexp ctype)
+                   ((nil)
+                    (if (eq (car dims) '*)
+                      `(eql (typecode ,thing) ,typecode)
+                      (let* ((temp (gensym)))
+                        `(let* ((,temp ,thing))
+                          (and (eql (typecode ,temp) ,typecode)
+                           (eq (uvsize ,temp) ,(car dims)))))))
+                   ((* :maybe)
+                    (let* ((temp (gensym))
+                           (tempcode (gensym)))
+                      `(let* ((,temp ,thing)
+                              (,tempcode (typecode ,temp)))
+                        (or (and (eql ,tempcode ,typecode)
+                             ,@(unless (eq (car dims) '*)
+                                       `((eq (uvsize ,temp) ,(car dims)))))
+                         (and (eql ,tempcode target::subtag-vectorH)
+                          (eql (ldb target::arrayH.flags-cell-subtag-byte (the fixnum (%svref ,temp target::arrayH.flags-cell))) ,typecode)
+                          ,@(unless (eq (car dims) '*)
+                                    `((eq (%svref ,temp target::vectorH.logsize-cell) ,(car dims)))))))))))))
+        `(values (array-%%typep ,thing ,ctype)))))))
+
+
+(defun optimize-typep (thing type env)
+  ;; returns a new form, or nil if it can't optimize
+  (let ((ctype (specifier-type-if-known type env :whine t)))
+    (when ctype
+      (let* ((type (type-specifier ctype))
+             (predicate (if (typep type 'symbol) (type-predicate type))))
+        (if (and predicate (symbolp predicate))
+          `(,predicate ,thing)
+          (let* ((pair (assq type *istruct-cells*))
+                 (class (and pair (%wrapper-class (istruct-cell-info pair)))))
+            (if (and class (not (%class-direct-subclasses class)))
+              `(istruct-typep ,thing ',type)              
+              (or (optimize-ctypep thing ctype)
+                  (cond ((symbolp type)
+                         (cond ((%deftype-expander type)
+                                ;; recurse here, rather than returning the
+                                ;; partially-expanded form mostly since it doesn't
+                                ;; seem to further optimize the result otherwise
+                                (let ((expanded-type (type-expand type)))
+                                  (or (optimize-typep thing expanded-type env)
+                                      ;; at least do the first expansion
+                                      `(typep ,thing ',expanded-type))))
+                               ((structure-class-p type env)
+                                `(structure-typep ,thing ',(find-class-cell type t)))
+                               ((find-class type nil env)
+                                ;; If we know for sure that the class
+                                ;; is one whose instances are all
+                                ;; STANDARD-INSTANCEs (not funcallable,
+                                ;; not foreign), we can use
+                                ;; STD-INSTANCE-CLASS-CELL-TYPEP, which
+                                ;; can be a little faster then the more
+                                ;; general CLASS-CELL-TYPEP.  We can
+                                ;; only be sure of that if the class
+                                ;; exists (as a non-COMPILE-TIME-CLASS)
+                                (let* ((class (find-class type nil nil))
+                                       (fname 
+                                        (if (and class
+                                                 (subtypep class 'standard-object)
+                                                 (not (subtypep class 'foreign-standard-object))
+                                                 (not (subtypep class 'funcallable-standard-object)))
+                                          'std-instance-class-cell-typep
+                                          'class-cell-typep)))
+                                  `(,fname ,thing (load-time-value (find-class-cell ',type t)))))
+                               ((info-type-builtin type) ; bootstrap troubles here?
+                                `(builtin-typep ,thing (load-time-value (find-builtin-cell ',type))))
+                               (t nil)))
+                        ((consp type)
+                         (cond
+                           ((info-type-builtin type) ; byte types
+                            `(builtin-typep ,thing (load-time-value (find-builtin-cell ',type))))
+                           (t
+                            (case (%car type)
+                              (satisfies `(funcall ',(cadr type) ,thing))
+                              (eql `(eql ,thing ',(cadr type)))
+                              (member `(not (null (member ,thing ',(%cdr type)))))
+                              (not `(not (typep ,thing ',(cadr type))))
+                              ((or and)
+                               (let ((thing-sym (gensym)))
+                                 `(let ((,thing-sym ,thing))
+                                   (,(%car type)
+                                    ,@(mapcar #'(lambda (type-spec)
+                                                  (or (optimize-typep thing-sym type-spec env)
+                                                      `(typep ,thing-sym ',type-spec)))
+                                              (%cdr type))))))
+                              ((signed-byte unsigned-byte integer mod) ; more byte types
+                               `(builtin-typep ,thing (load-time-value (find-builtin-cell ',type))))
+                              (t nil)))))
+                        (t nil))))))))))
+
+(define-compiler-macro typep  (&whole call &environment env thing type &optional e)
+  (if (nx-form-constant-p type env)
+    (let ((type-val (nx-form-constant-value type env)))
+      (if (eq type-val t)
+        `(progn ,thing t)
+        (if (and (nx-form-constant-p thing env)
+                 (specifier-type-if-known type-val env))
+          (typep (nx-form-constant-value thing env) type-val env)
+          (or (and (null e) (optimize-typep thing type-val env))
+              call))))
+    call))
+
+(define-compiler-macro structure-typep (&whole w thing type)
+  (if (not (quoted-form-p type))
+    (progn
+      (warn "Non-quoted structure-type in ~s" w)
+      w)
+    (let* ((type (nx-unquote type)))
+      (if (symbolp type)
+        `(structure-typep ,thing ',(find-class-cell type t))
+        w))))
+
+(define-compiler-macro true (&rest args)
+  `(progn
+    ,@args
+    t))
+
+
+(define-compiler-macro false (&rest args)
+  `(progn
+    ,@args
+    nil))
+
+(define-compiler-macro find-class (&whole call type &optional (errorp t) env)
+  (if (and (quoted-form-p type)(not *dont-find-class-optimize*)(not env))
+      `(class-cell-find-class (load-time-value (find-class-cell ,type t)) ,errorp)
+    call))
+
+
+(define-compiler-macro gcd (&whole call &optional (n0 nil n0-p) (n1 nil n1-p) &rest rest)
+  (if rest
+    call
+    (if n1-p
+      `(gcd-2 ,n0 ,n1)
+      (if n0-p
+        `(%integer-abs ,n0)
+        0))))
+
+(define-compiler-macro lcm (&whole call &optional (n0 nil n0-p) (n1 nil n1-p) &rest rest)
+  (if rest
+    call
+    (if n1-p
+      `(lcm-2 ,n0 ,n1)
+      (if n0-p
+        `(%integer-abs ,n0)
+        1))))
+
+(define-compiler-macro max (&whole call &environment env n0 &optional (n1 nil n1-p) &rest rest)
+  (if rest
+    call
+    (if n1-p
+      (if (and (nx-form-typep n0 'fixnum env)(nx-form-typep n1 'fixnum env))
+        `(imax-2 ,n0 ,n1)
+        `(max-2 ,n0 ,n1))
+      `(require-type ,n0 'real))))
+
+(define-compiler-macro max-2 (n0 n1)
+  (let* ((g0 (gensym))
+         (g1 (gensym)))
+   `(let* ((,g0 ,n0)
+           (,g1 ,n1))
+      (if (> ,g0 ,g1) ,g0 ,g1))))
+
+(define-compiler-macro imax-2 (n0 n1)
+  (let* ((g0 (gensym))
+         (g1 (gensym)))
+   `(let* ((,g0 ,n0)
+           (,g1 ,n1))
+      (if (%i> ,g0 ,g1) ,g0 ,g1))))
+
+
+
+
+(define-compiler-macro min (&whole call &environment env n0 &optional (n1 nil n1-p) &rest rest)
+  (if rest
+    call
+    (if n1-p
+      (if (and (nx-form-typep n0 'fixnum env)(nx-form-typep n1 'fixnum env))
+        `(imin-2 ,n0 ,n1)
+        `(min-2 ,n0 ,n1))
+      `(require-type ,n0 'real))))
+
+(define-compiler-macro min-2 (n0 n1)
+  (let* ((g0 (gensym))
+         (g1 (gensym)))
+   `(let* ((,g0 ,n0)
+           (,g1 ,n1))
+      (if (< ,g0 ,g1) ,g0 ,g1))))
+
+(define-compiler-macro imin-2 (n0 n1)
+  (let* ((g0 (gensym))
+         (g1 (gensym)))
+   `(let* ((,g0 ,n0)
+           (,g1 ,n1))
+      (if (%i< ,g0 ,g1) ,g0 ,g1))))
+
+
+(defun eq-test-p (test)
+  (or (equal test ''eq) (equal test '#'eq)))
+
+(defun eql-test-p (test)
+  (or (equal test ''eql) (equal test '#'eql)))
+
+(define-compiler-macro adjoin (&whole whole elt list &rest keys)
+  (if (constant-keywords-p keys)
+    (destructuring-bind (&key (test ''eql) test-not key) keys
+      (or (and (null test-not)
+               (null key)
+               (cond ((eq-test-p test)
+                      `(adjoin-eq ,elt ,list))
+                     ((eql-test-p test)
+                      `(adjoin-eql ,elt ,list))
+                     (t nil)))
+          whole))
+    whole))
+
+(define-compiler-macro union (&whole whole list1 list2 &rest keys)
+  (if (constant-keywords-p keys)
+    (destructuring-bind (&key (test ''eql) test-not key) keys
+      (or (and (null test-not)
+               (null key)
+               (cond ((eq-test-p test)
+                      `(union-eq ,list1 ,list2))
+                     ((eql-test-p test)
+                      `(union-eql ,list1 ,list2))
+                     (t nil)))
+          whole))
+    whole))
+
+(define-compiler-macro slot-value (&whole whole &environment env
+                                          instance slot-name-form)
+  (declare (ignore env))
+  (let* ((name (and (quoted-form-p slot-name-form)
+                    (typep (cadr slot-name-form) 'symbol)
+                    (cadr slot-name-form))))
+    (if name
+      `(slot-id-value ,instance (load-time-value (ensure-slot-id ',name)))
+      whole)))
+
+
+(define-compiler-macro set-slot-value (&whole whole &environment env
+                                          instance slot-name-form value-form)
+  (declare (ignore env))
+  (let* ((name (and (quoted-form-p slot-name-form)
+                    (typep (cadr slot-name-form) 'symbol)
+                    (cadr slot-name-form))))
+    (if name
+      `(set-slot-id-value
+        ,instance
+        (load-time-value (ensure-slot-id ',name))
+        ,value-form)
+      whole)))
+
+
+(define-compiler-macro slot-boundp (&whole whole instance slot-name-form)
+  (let* ((name (and (quoted-form-p slot-name-form)
+                    (typep (cadr slot-name-form) 'symbol)
+                    (cadr slot-name-form))))
+    (if name
+      `(slot-id-boundp ,instance (load-time-value (ensure-slot-id ',name)))
+      whole)))
+
+(defsynonym %get-unsigned-byte %get-byte)
+(defsynonym %get-unsigned-word %get-word)
+(defsynonym %get-signed-long %get-long)
+
+
+
+
+(define-compiler-macro arrayp (arg)
+  `(>= (the fixnum (typecode ,arg))
+    ,(nx-lookup-target-uvector-subtag :array-header)))
+
+(define-compiler-macro vectorp (arg)
+  `(>= (the fixnum (typecode ,arg))
+    ,(nx-lookup-target-uvector-subtag :vector-header)))
+
+
+
+(define-compiler-macro fixnump (arg)
+  (let* ((fixnum-tag
+          (arch::target-fixnum-tag (backend-target-arch *target-backend*))))
+    `(eql (lisptag ,arg) ,fixnum-tag)))
+
+
+
+(define-compiler-macro double-float-p (n)
+  (let* ((tag (arch::target-double-float-tag (backend-target-arch *target-backend*))))
+    `(eql (typecode ,n) ,tag)))
+
+
+(define-compiler-macro short-float-p (n)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (tag (arch::target-single-float-tag arch))
+         (op (if (arch::target-single-float-tag-is-subtag arch)
+               'typecode
+               'fulltag)))
+    `(eql (,op ,n) ,tag)))
+
+
+(define-compiler-macro floatp (n)
+  (let* ((typecode (make-symbol "TYPECODE"))
+         (arch (backend-target-arch *target-backend*))
+         (single (arch::target-single-float-tag arch))
+         (double (arch::target-double-float-tag arch)))
+    `(let* ((,typecode (typecode ,n)))
+       (declare (fixnum ,typecode))
+       (or (= ,typecode ,single)
+           (= ,typecode ,double)))))
+
+(define-compiler-macro functionp (n)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (tag (arch::target-function-tag arch))
+         (op (if (arch::target-function-tag-is-subtag arch)
+               'typecode
+               'fulltag)))
+    `(eql (,op  ,n) ,tag)))
+
+(define-compiler-macro symbolp (s)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (symtag (arch::target-symbol-tag arch))
+         (op (if (arch::target-symbol-tag-is-subtag arch)
+               'typecode
+               'fulltag))
+         (niltag (arch::target-null-tag arch)))
+    (if (eql niltag symtag)
+      `(eql (,op ,s) ,symtag)
+      (let* ((sym (gensym)))
+        `(let* ((,sym ,s))
+          (if ,sym (eql (,op ,sym) ,symtag) t))))))
+
+;;; If NIL isn't tagged as a symbol, assume that LISPTAG only looks
+;;; at bits that NIL shares with a cons.
+(define-compiler-macro listp (n)
+  (let* ((arch (backend-target-arch *target-backend*))
+         (cons-tag (arch::target-cons-tag arch))
+         (nil-tag  (arch::target-null-tag arch))
+         (symbol-tag (arch::target-symbol-tag arch)))
+    (if (= nil-tag symbol-tag)
+      (let* ((nvar (gensym)))
+        `(let* ((,nvar ,n))
+          (if ,nvar (consp ,nvar) t)))
+      `(eql (lisptag ,n) ,cons-tag))))
+
+(define-compiler-macro consp (&whole call n)
+  (let* ((arch (backend-target-arch *target-backend*))
+	 (cons-tag (arch::target-cons-tag arch))
+	 (nil-tag (arch::target-null-tag arch)))
+    (if (= nil-tag cons-tag)
+      call
+      `(eql (fulltag ,n) ,cons-tag))))
+
+(define-compiler-macro bignump (n)
+  `(eql (typecode ,n) ,(nx-lookup-target-uvector-subtag :bignum)))
+
+(define-compiler-macro ratiop (n)
+  `(eql (typecode ,n) ,(nx-lookup-target-uvector-subtag :ratio)))
+
+(define-compiler-macro complexp (n)
+  `(eql (typecode ,n) ,(nx-lookup-target-uvector-subtag :complex)))
+
+(define-compiler-macro macptrp (n)
+  `(eql (typecode ,n) ,(nx-lookup-target-uvector-subtag :macptr)))
+
+(define-compiler-macro basic-stream-p (n)
+  `(eql (typecode ,n) ,(nx-lookup-target-uvector-subtag :basic-stream)))
+
+(define-compiler-macro aref (&whole call a &rest subscripts &environment env)
+  (let* ((ctype (if (nx-form-typep a 'array env)
+                  (specifier-type (nx-form-type a env) env)))
+         (ectype (typecase ctype
+                   (array-ctype (array-ctype-specialized-element-type ctype))
+                   (union-ctype (when (every #'array-ctype-p (union-ctype-types ctype))
+                                  (%type-union
+                                   (mapcar (lambda (ct) (array-ctype-specialized-element-type ct))
+                                           (union-ctype-types ctype)))))))
+         (etype (and ectype (type-specifier ectype)))
+         (useful (unless (or (eq etype *) (eq etype t))
+                   etype)))
+    (if (= 2 (length subscripts))
+      (setq call `(%aref2 ,a ,@subscripts))
+      (if (= 3 (length subscripts))
+        (setq call `(%aref3 ,a ,@subscripts))))
+    (if useful
+      `(the ,useful ,call)
+      call)))
+
+
+(define-compiler-macro aset (&whole call a &rest subs&val)
+  (if (= 3 (length subs&val))
+    `(%aset2 ,a ,@subs&val)
+    (if (= 4 (length subs&val))
+      `(%aset3 ,a ,@subs&val)
+      call)))
+
+
+(define-compiler-macro make-sequence (&whole call typespec len &rest keys &key initial-element)
+  (declare (ignore typespec len keys initial-element))
+  call)
+
+(define-compiler-macro make-string (&whole call &environment env size &rest keys)
+  (if (constant-keywords-p keys)
+    (destructuring-bind (&key (element-type () element-type-p)
+                              (initial-element () initial-element-p))
+                        keys
+      (if (and element-type-p
+               (nx-form-constant-p element-type env))
+        (let* ((element-type (nx-form-constant-value element-type env)))
+          (if (subtypep element-type 'base-char)
+            `(allocate-typed-vector :simple-string ,size ,@(if initial-element-p `(,initial-element)))
+            call))
+        (if (not element-type-p)
+          `(allocate-typed-vector :simple-string ,size ,@(if initial-element-p `(,initial-element)))
+          call)))
+    call))
+
+(define-compiler-macro make-string-output-stream (&whole whole &rest keys)
+  (if (null keys)
+    '(make-simple-string-output-stream)
+    whole))
+
+
+(define-compiler-macro write-string (&environment env &whole call
+                                                  string &optional (stream nil) &rest keys)
+  (if (nx-form-typep string 'simple-string env)
+    (if keys
+      `((lambda (string stream &key (start 0) end)
+          (write-simple-string string stream start end))
+        ,string ,stream ,@keys)
+      `(write-simple-string ,string ,stream 0 nil))
+    call))
+
+(define-compiler-macro format (&environment env &whole call stream string &rest args)
+  (if (stringp string)
+    (cond ((and (string-equal string "~a") args (null (cdr args)))
+           (destructuring-bind (object) args
+             (cond ((null stream)
+                    `(princ-to-string ,object))
+                   ((or (eq stream t) (nx-form-typep stream 'stream env))
+                    `(progn (princ ,object ,(and (neq stream t) stream)) nil))
+                   (t `(let ((stream ,stream)
+                             (object ,object))
+                         (if (or (null stream) (stringp stream))
+                           (format-to-string stream ,string object)
+                           (progn (princ object (and (neq stream t) stream)) nil)))))))
+          ((and (string-equal string "~s") args (null (cdr args)))
+           (destructuring-bind (object) args
+             (cond ((null stream)
+                    `(prin1-to-string ,object))
+                   ((or (eq stream t) (nx-form-typep stream 'stream env))
+                    `(progn (prin1 ,object ,(and (neq stream t) stream)) nil))
+                   (t `(let ((stream ,stream)
+                             (object ,object))
+                         (if (or (null stream) (stringp stream))
+                           (format-to-string stream ,string object)
+                           (progn (prin1 object (and (neq stream t) stream)) nil)))))))
+          ((and (null (position #\~ string)) (null args))
+           (cond ((null stream)
+                  string)
+                 ((or (eq stream t) (nx-form-typep stream 'stream env))
+                  `(progn (write-string ,string ,(and (neq stream t) stream)) nil))
+                 (t `(let ((stream ,stream))
+                       (if (or (null stream) (stringp stream))
+                         (format-to-string stream ,string)
+                         (progn (write-string ,string (and (neq stream t) stream)) nil))))))
+          ((let ((new (format-string-sans~newlines string)))
+             (and (neq new string) (setq string new)))
+           `(format ,stream ,string ,@args))
+          ((optimize-format-call stream string args env))
+          (t call))
+    call))
+
+(defun format-string-sans~newlines (string)
+  (loop as pos = 0 then (position #\Newline string :start pos) while pos
+        as ch = (and (> pos 0) (schar string (1- pos)))
+        do (cond ((not (or (eq ch #\~)
+			   (and (or (eq ch #\:) (eq ch #\@))
+				(> pos 1) (eq (schar string (- pos 2)) #\~))))
+		  (incf pos))
+		 ((eq ch #\:)
+		  (decf pos 2)
+		  (setq string (%str-cat (subseq string 0 pos) (subseq string (+ pos 3)))))
+		 ((eq ch #\@)
+		  (setq string (%str-cat (subseq string 0 (- pos 2))
+					 "~%"
+					 (subseq string (or
+                                                         (position-if-not #'whitespacep string
+                                                                          :start (1+ pos))
+                                                         (1+ pos))))))
+                  ((eq ch #\~)
+		  (decf pos)
+		  (setq string (%str-cat (subseq string 0 pos)
+					 (subseq string (or (position-if-not #'whitespacep string
+									 :start (1+ pos))
+                                                            (1+ pos))))))))
+  string)
+
+(defun count-known-format-args (string start end)
+  (declare (fixnum end))
+  (loop with count = 0
+        do (setq start (position #\~ string :start start :end end))
+        when (null start)
+          do (return count)
+        unless (< (incf start) end)
+          do (return nil)
+        do (let ((ch (aref string start)))
+             (cond ((memq ch '(#\a #\A #\s #\S)) (incf count))
+                   ((memq ch '(#\~ #\% #\&)))
+                   (t (return nil)))
+             (incf start))))
+
+(defun optimize-format-call (stream string args env)
+  (let* ((start (or (search "~/" string)
+                    (return-from optimize-format-call nil)))
+         (ipos (+ start 2))
+         (epos (or (position #\/ string :start ipos)
+                   (return-from optimize-format-call nil)))
+         (nargs (or (count-known-format-args string 0 start)
+                    (return-from optimize-format-call nil))))
+    (when (and
+           ;; Must be able to split args
+           (< nargs (length args))
+           ;; Don't deal with packages
+           (not (position #\: string :start ipos :end epos)))
+      (let* ((func (intern (string-upcase (subseq string ipos epos)) :cl-user))
+             (prev (and (< 0 start) (subseq string 0 start)))
+             (prev-args (subseq args 0 nargs))
+             (rest (and (< (1+ epos) (length string)) (subseq string (1+ epos))))
+             (rest-args (nthcdr nargs args))
+             (obj (pop rest-args))
+             (stream-var (gensym))
+             (body `(,@(and prev `((format ,stream-var ,prev ,@prev-args)))
+                       (,func ,stream-var ,obj nil nil)
+                       ,(if rest `(format ,stream-var ,rest ,@rest-args) `nil))))
+        (cond ((null stream)
+               `(with-output-to-string (,stream-var)
+                  (declare (type stream ,stream-var))
+                  ,@body))
+              ((or (eq stream t) (nx-form-typep stream 'stream env))
+               `(let ((,stream-var ,(if (eq stream t) '*standard-output* stream)))
+                  (declare (type stream ,stream-var))
+                  ,@body))
+              (t
+               `(let ((,stream-var ,stream))
+                  (if (or (null ,stream-var) (stringp ,stream-var))
+                    (format-to-string ,stream-var ,string ,@args)
+                    (let ((,stream-var
+                           (if (eq ,stream-var t) *standard-output* ,stream-var)))
+                      ;; For the purposes of body, it's ok to assume stream-var
+                      ;; is a stream. method dispatch will signal any errors
+                      ;; at runtime if it's not true...
+                      (declare (type stream ,stream-var))
+                      ,@body)))))))))
+
+
+(define-compiler-macro sbit (&whole call v &optional sub0 &rest others)
+  (if (and sub0 (null others))
+    `(aref (the simple-bit-vector ,v) ,sub0)
+    call))
+
+(define-compiler-macro %sbitset (&whole call v sub0 &optional (newval nil newval-p) &rest newval-was-really-sub1)
+  (if (and newval-p (not newval-was-really-sub1) )
+    `(setf (aref (the simple-bit-vector ,v) ,sub0) ,newval)
+    call))
+
+(define-compiler-macro simple-base-string-p (thing)
+  `(= (the fixnum (typecode ,thing)) ,(nx-lookup-target-uvector-subtag :simple-string)))
+
+(define-compiler-macro simple-string-p (thing)
+  `(simple-base-string-p ,thing))
+
+(define-compiler-macro stringp (thing)
+  `(base-string-p  ,thing))
+
+(define-compiler-macro base-string-p (thing)
+  (let* ((gthing (gensym))
+         (gtype (gensym)))
+    `(let* ((,gthing ,thing)
+            (,gtype (typecode ,gthing)))
+      (declare (type (unsigned-byte 8) ,gtype))
+      (if (= ,gtype ,(nx-lookup-target-uvector-subtag :vector-header))
+        (= (the (unsigned-byte 8)
+             (ldb target::arrayH.flags-cell-subtag-byte (the fixnum (%svref ,gthing target::arrayH.flags-cell))))
+           ,(nx-lookup-target-uvector-subtag :simple-string))
+        (= ,gtype ,(nx-lookup-target-uvector-subtag :simple-string))))))
+
+
+
+(defsetf %misc-ref %misc-set)
+
+(define-compiler-macro lockp (lock)
+  (let* ((tag (nx-lookup-target-uvector-subtag :lock)))
+    `(eq ,tag (typecode ,lock))))
+
+(define-compiler-macro structurep (s)
+  (let* ((tag (nx-lookup-target-uvector-subtag :struct)))
+    `(eq ,tag (typecode ,s))))
+  
+
+(define-compiler-macro integerp (thing)
+  (let* ((typecode (gensym))
+         (fixnum-tag (arch::target-fixnum-tag (backend-target-arch *target-backend*)))
+         (bignum-tag (nx-lookup-target-uvector-subtag :bignum)))
+    `(let* ((,typecode (typecode ,thing)))
+      (declare (fixnum ,typecode))
+      (if (= ,typecode ,fixnum-tag)
+        t
+        (= ,typecode ,bignum-tag)))))
+
+(define-compiler-macro realp (&whole call x)
+  (if (not (eq *host-backend* *target-backend*))
+    call
+    (let* ((typecode (gensym)))
+      `(let* ((,typecode (typecode ,x)))
+        (declare (type (unsigned-byte 8) ,typecode))
+        #+(or ppc32-target x8632-target)
+        (or (= ,typecode target::tag-fixnum)
+         (and (>= ,typecode target::min-numeric-subtag)
+          (<= ,typecode target::max-real-subtag)))
+        #+ppc64-target
+        (if (<= ,typecode ppc64::subtag-double-float)
+          (logbitp (the (integer 0 #.ppc64::subtag-double-float) ,typecode)
+                   (logior (ash 1 ppc64::tag-fixnum)
+                           (ash 1 ppc64::subtag-single-float)
+                           (ash 1 ppc64::subtag-double-float)
+                           (ash 1 ppc64::subtag-bignum)
+                           (ash 1 ppc64::subtag-ratio))))
+        #+x8664-target
+        (if (<= ,typecode x8664::subtag-double-float)
+          (logbitp (the (integer 0 #.x8664::subtag-double-float) ,typecode)
+                   (logior (ash 1 x8664::tag-fixnum)
+                           (ash 1 x8664::subtag-bignum)
+                           (ash 1 x8664::tag-single-float)
+                           (ash 1 x8664::subtag-double-float)
+                           (ash 1 x8664::subtag-ratio))))))))
+
+(define-compiler-macro %composite-pointer-ref (size pointer offset)
+  (if (constantp size)
+    `(%inc-ptr ,pointer ,offset)
+    `(progn
+      ,size
+      (%inc-ptr ,pointer ,offset))))
+
+
+(define-compiler-macro char= (&whole call ch &optional (other nil other-p) &rest others)
+  (if (null others)
+    (if other-p
+      `(eq (char-code ,ch) (char-code ,other))
+      `(progn (char-code ,ch) t))
+    (if (null (cdr others))
+      (let* ((third (car others))
+             (code (gensym))
+             (code2 (gensym))
+             (code3 (gensym)))
+        `(let* ((,code (char-code ,ch))
+                (,code2 (char-code ,other))
+                (,code3 (char-code ,third)))
+          (and (eq ,code ,code2)
+           (eq ,code2 ,code3))))
+      call)))
+
+(define-compiler-macro char-equal (&whole call ch &optional (other nil other-p) &rest others)
+  (if (null others)
+    (if other-p
+      `(eq (%char-code-upcase (char-code ,ch)) (%char-code-upcase (char-code ,other)))
+      `(progn (char-code ,ch) t))
+    (if (null (cdr others))
+      (let* ((third (car others))
+             (code (gensym))
+             (code2 (gensym))
+             (code3 (gensym)))
+        `(let* ((,code (%char-code-upcase (char-code ,ch)))
+                (,code2 (%char-code-upcase (char-code ,other)))
+                (,code3 (%char-code-upcase (char-code ,third))))
+          (and (eq ,code ,code2)
+           (eq ,code ,code3))))
+      call)))
+
+(define-compiler-macro char/= (&whole call ch &optional (other nil other-p) &rest others)
+  (if (null others)
+    (if other-p
+      `(not (eq (char-code ,ch) (char-code ,other)))
+      `(progn (char-code ,ch) t))
+    call))
+
+
+(define-compiler-macro char< (&whole call ch &optional (other nil other-p) &rest others)
+  (if (null others)
+    (if other-p
+      `(< (the fixnum (char-code ,ch)) (the fixnum (char-code ,other)))
+      `(progn (char-code ,ch) t))
+    (if (null (cdr others))
+      (let* ((third (car others))
+             (code (gensym))
+             (code2 (gensym))
+             (code3 (gensym)))
+        ;; We have to evaluate all forms for side-effects.
+        ;; Hopefully, there won't be any
+        `(let* ((,code (char-code ,ch))
+                (,code2 (char-code ,other))
+                (,code3 (char-code ,third)))
+          (declare (fixnum ,code ,code2 ,code3))
+          (and (< ,code ,code2)
+           (< ,code2 ,code3))))
+      call)))
+
+(define-compiler-macro char<= (&whole call ch &optional (other nil other-p) &rest others)
+  (if (null others)
+    (if other-p
+      `(<= (the fixnum (char-code ,ch)) (the fixnum (char-code ,other)))
+      `(progn (char-code ,ch) t))
+    (if (null (cdr others))
+      (let* ((third (car others))
+             (code (gensym))
+             (code2 (gensym))
+             (code3 (gensym)))
+        `(let* ((,code (char-code ,ch))
+                (,code2 (char-code ,other))
+                (,code3 (char-code ,third)))
+          (declare (fixnum ,code ,code2 ,code3))
+          (and (<= ,code ,code2)
+           (<= ,code2 ,code3))))
+      call)))
+
+(define-compiler-macro char> (&whole call ch &optional (other nil other-p) &rest others)
+  (if (null others)
+    (if other-p
+      `(> (the fixnum (char-code ,ch)) (the fixnum (char-code ,other)))
+      `(progn (char-code ,ch) t))
+    (if (null (cdr others))
+      (let* ((third (car others))
+             (code (gensym))
+             (code2 (gensym))
+             (code3 (gensym)))
+        `(let* ((,code (char-code ,ch))
+                (,code2 (char-code ,other))
+                (,code3 (char-code ,third)))
+          (declare (fixnum ,code ,code2 ,code3))
+          (and (> ,code ,code2)
+           (> ,code2 ,code3))))
+      call)))
+
+(define-compiler-macro char>= (&whole call ch &optional (other nil other-p) &rest others)
+  (if (null others)
+    (if other-p
+      `(>= (the fixnum (char-code ,ch)) (the fixnum (char-code ,other)))
+      `(progn (char-code ,ch) t))
+    (if (null (cdr others))
+      (let* ((third (car others))
+             (code (gensym))
+             (code2 (gensym))
+             (code3 (gensym)))
+        `(let* ((,code (char-code ,ch))
+                (,code2 (char-code ,other))
+                (,code3 (char-code ,third)))
+          (declare (fixnum ,code ,code2 ,code3))
+          (and (>= ,code ,code2)
+           (>= ,code2 ,code3))))
+      call)))
+
+(define-compiler-macro float (&whole call number &optional (other 0.0f0 other-p) &environment env)
+
+  (cond ((and (typep other 'single-float)
+              (nx-form-typep number 'double-float env))
+         `(the single-float (%double-to-single ,number)))
+        ((and (typep other 'double-float)
+              (nx-form-typep number 'single-float env))
+         `(the double-float (%single-to-double ,number)))
+        ((and other-p (typep other 'single-float))
+         `(the single-float (%short-float ,number)))
+        ((typep other 'double-float)
+         `(the double-float (%double-float ,number)))
+        ((null other-p)
+         (let* ((temp (gensym)))
+           `(let* ((,temp ,number))
+             (if (typep ,temp 'double-float)
+               ,temp
+               (the single-float (%short-float ,temp))))))
+        (t call)))
+
+(define-compiler-macro coerce (&whole call &environment env thing type)
+  (cond ((nx-form-constant-p type env)
+	 (setq type (nx-form-constant-value type env))
+	 (let ((ctype (specifier-type-if-known type env :whine t)))
+	   (if ctype
+	     (if (csubtypep ctype (specifier-type 'single-float))
+		 `(float ,thing 0.0f0)
+		 (if (csubtypep ctype (specifier-type 'double-float))
+		     `(float ,thing 0.0d0)
+		     (let ((simple nil)
+			   (extra nil))
+		       (if (and (typep ctype 'array-ctype)
+				(equal (array-ctype-dimensions ctype) '(*)))
+			   (if (eq (array-ctype-specialized-element-type ctype)
+				   (specifier-type 'character))
+			       (setq simple '%coerce-to-string)
+			       (if (and (eq *host-backend* *target-backend*)
+					(array-ctype-typecode ctype))
+				   (setq simple '%coerce-to-vector
+					 extra (list (array-ctype-typecode ctype)))))
+			   (if (eq ctype (specifier-type 'list))
+			       (setq simple '%coerce-to-list)))
+		       (if simple
+			   (let* ((temp (gensym)))
+			     `(let* ((,temp ,thing))
+				(if (typep ,temp ',(type-specifier ctype))
+				    ,temp
+				    (,simple ,temp ,@extra))))
+			   call))))
+	     call)))
+        (t call)))
+
+(define-compiler-macro equal (&whole call x y &environment env)
+  (if (or (equal-iff-eql-p x env)
+          (equal-iff-eql-p y env))
+    `(eql ,x ,y)
+    call))
+
+(define-compiler-macro instance-slots (instance &environment env)
+  (if (and (nx-form-constant-p instance env)
+           (eql (typecode (nx-form-constant-value instance env)) (nx-lookup-target-uvector-subtag :instance)))
+    `(instance.slots ,instance)
+    (let* ((itemp (gensym))
+           (typecode (gensym)))
+      `(let* ((,itemp ,instance)
+              (,typecode (typecode ,itemp)))
+        (declare (type (unsigned-byte 8) ,typecode))
+        (if (eql ,typecode ,(nx-lookup-target-uvector-subtag :instance))
+          (instance.slots ,itemp)
+          (%non-standard-instance-slots ,itemp ,typecode))))))
+
+(define-compiler-macro instance-class-wrapper (instance)
+  (let* ((itemp (gensym)))
+    `(let* ((,itemp ,instance))
+      (if (eql (the (unsigned-byte 8) (typecode ,itemp))
+               ,(nx-lookup-target-uvector-subtag :instance))
+        (instance.class-wrapper ,itemp)
+        (non-standard-instance-class-wrapper ,itemp)))))
+
+;; Instance must be a standard-instance.
+(define-compiler-macro %class-of-instance (instance)
+  `(%wrapper-class (instance.class-wrapper ,instance)))
+
+(define-compiler-macro standard-object-p (thing)
+  (let* ((temp (gensym))
+         (typecode (gensym)))
+    `(let* ((,temp ,thing)
+            (,typecode (typecode ,temp)))
+      (declare (type (unsigned-byte 8) ,typecode))
+      (if (= ,typecode ,(nx-lookup-target-uvector-subtag :instance))
+        (instance.class-wrapper ,temp)
+        (if (= ,typecode ,(nx-lookup-target-uvector-subtag :macptr))
+          (foreign-instance-class-wrapper ,temp))))))
+
+(define-compiler-macro %class-ordinal (class &optional error)
+  (let* ((temp (gensym)))
+    `(let* ((,temp ,class))
+      (if (eql (the (unsigned-byte 8) (typecode ,temp))
+               ,(nx-lookup-target-uvector-subtag :instance))
+        (instance.hash ,temp)
+        (funcall '%class-ordinal ,temp ,error)))))
+
+(define-compiler-macro native-class-p (class)
+  (let* ((temp (gensym)))
+    `(let* ((,temp ,class))
+      (if (eql (the (unsigned-byte 8) (typecode ,temp))
+               ,(nx-lookup-target-uvector-subtag :instance))
+        (< (the fixnum (instance.hash ,temp)) max-class-ordinal)))))
+  
+
+
+(define-compiler-macro unsigned-byte-p (x)
+  (if (typep (nx-unquote x) 'unsigned-byte)
+    t
+    (let* ((val (gensym)))
+      `(let* ((,val ,x))
+        (and (integerp ,val) (not (< ,val 0)))))))
+
+(define-compiler-macro subtypep (&whole w t1 t2 &optional rtenv)
+  (if (and (consp t1)
+           (consp (cdr t1))
+           (null (cddr t1))
+           (eq (car t1) 'type-of))
+    ;; People really write code like this.  I've seen it.
+    `(typep ,(cadr t1) ,t2 ,@(and rtenv `(,rtenv)))
+    (if (and (null rtenv) (quoted-form-p t2))
+      `(cell-csubtypep-2 ,t1 (load-time-value (register-type-cell ,t2)))
+      w)))
+
+
+(define-compiler-macro string-equal (s1 s2 &rest keys)
+  (if (null keys)
+    `(%fixed-string-equal ,s1 ,s2)
+    (let* ((s1-arg (gensym))
+           (s2-arg (gensym)))
+      `(funcall
+        (lambda (,s1-arg ,s2-arg &key start1 end1 start2 end2)
+          (%bounded-string-equal ,s1-arg ,s2-arg start1 end1 start2 end2))
+        ,s1 ,s2 ,@keys))))
+
+;;; Try to use "package-references" to speed up package lookup when
+;;; a package name is used as a constant argument to some functions.
+
+(defun package-ref-form (arg env)
+  (when (and arg (nx-form-constant-p arg env)
+	     (typep (setq arg (nx-form-constant-value arg env))
+		    '(or symbol string)))
+    `(load-time-value (register-package-ref ,(string arg)))))
+
+
+
+(define-compiler-macro intern (&whole w string &optional package &environment env)
+  (let* ((ref (package-ref-form package env)))
+    (if (or ref
+            (setq ref (and (consp package)
+                           (eq (car package) 'find-package)
+                           (consp (cdr package))
+                           (null (cddr package))
+                           (package-ref-form (cadr package) env))))
+      `(%pkg-ref-intern ,string ,ref)
+      w)))
+
+(define-compiler-macro find-symbol (&whole w string &optional package &environment env)
+  (let* ((ref (package-ref-form package env)))
+    (if (or ref
+            (setq ref (and (consp package)
+                           (eq (car package) 'find-package)
+                           (consp (cdr package))
+                           (null (cddr package))
+                           (package-ref-form (cadr package) env))))
+      `(%pkg-ref-find-symbol ,string ,ref)
+      w)))
+
+(define-compiler-macro find-package (&whole w package &environment env)
+  (let* ((ref (package-ref-form package env)))
+    (if ref
+      `(package-ref.pkg ,ref)
+      w)))
+
+(define-compiler-macro pkg-arg (&whole w package &optional allow-deleted &environment env)
+  (let* ((ref (unless allow-deleted (package-ref-form package env))))
+    (if ref
+      (let* ((r (gensym)))
+        `(let* ((,r ,ref))
+          (or (package-ref.pkg ,ref)
+           (%kernel-restart $xnopkg (package-ref.pkg ,r)))))
+      w)))
+
+
+;;; In practice, things that're STREAMP are almost always
+;;; BASIC-STREAMs or FUNDAMENTAL-STREAMs, but STREAMP is a generic
+;;; function.
+(define-compiler-macro streamp (arg)
+  (let* ((s (gensym)))
+    `(let* ((,s ,arg))
+      (or (typep ,s 'basic-stream)
+       (typep ,s 'fundamental-stream)
+       ;; Don't recurse
+       (funcall 'streamp ,s)))))
+
+
+(define-compiler-macro %char-code-case-fold (&whole w code vector &environment env)
+  (if (nx-open-code-in-line env)
+    (let* ((c (gensym))
+           (table (gensym)))
+      `(let* ((,c ,code)
+              (,table ,vector))
+        (declare (type (mod #x110000) ,c)
+                 (type (simple-array (signed-byte 16) (*)) ,table))
+        (if (< ,c (length ,table))
+          (the fixnum (+ ,c (the (signed-byte 16)
+                              (locally (declare (optimize (speed 3) (safety 0)))
+                                (aref ,table ,c)))))
+          ,c)))
+    w))
+        
+(define-compiler-macro %char-code-upcase (code)
+  (if (typep code '(mod #x110000))
+    (%char-code-upcase code)
+    `(%char-code-case-fold ,code *lower-to-upper*)))
+
+(define-compiler-macro %char-code-downcase (code)
+  (if (typep code '(mod #x110000))
+    (%char-code-downcase code)
+    `(%char-code-case-fold ,code *upper-to-lower*)))
+
+(define-compiler-macro char-upcase (char)
+  `(code-char (the valid-char-code (%char-code-upcase (char-code ,char)))))
+
+(define-compiler-macro char-downcase (char)
+  `(code-char (the valid-char-code (%char-code-downcase (char-code ,char)))))
+
+
+(define-compiler-macro register-istruct-cell (&whole w arg &environment env)
+  (if (and (nx-form-constant-p arg env)
+	   (setq arg (nx-form-constant-value arg env))
+	   (symbolp arg))
+    `',(register-istruct-cell arg)
+    w))
+
+(define-compiler-macro get-character-encoding (&whole w name)
+  (or (if (typep name 'keyword) (lookup-character-encoding name))
+      w))
+
+(define-compiler-macro read-char (&optional stream (eof-error-p t) eof-value recursive-p)
+  `(read-char-internal ,stream ,eof-error-p (values ,eof-value ,recursive-p)))
+
+
+(provide "OPTIMIZERS")
Index: /branches/new-random/compiler/reg.lisp
===================================================================
--- /branches/new-random/compiler/reg.lisp	(revision 13309)
+++ /branches/new-random/compiler/reg.lisp	(revision 13309)
@@ -0,0 +1,238 @@
+;;;-*- Mode: Lisp; Package: CCL-*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+(in-package "CCL")
+
+;;; A "register spec" is a fixnum.  Bit 28 is clear; bits 24-26
+;;; (inclusive) define the type of register-spec in question.  Of
+;;; course, a register spec can also be a "logical register" (lreg)
+;;; structure.  Someday soon, these might totally replace the fixnum
+;;; "hard regspecs" that're described in this file, and might be used
+;;; to refer to stack-based values as well as registers.  In the
+;;; meantime, we have to bootstrap a bit.
+
+(defmacro register-spec-p (regspec)
+  `(%register-spec-p ,regspec))
+
+(defun %register-spec-p (regspec)
+  (if (typep regspec 'fixnum)
+    (not (logbitp 28 (the fixnum regspec)))
+    (typep regspec 'lreg)))
+
+(defconstant regspec-type-byte (byte 3 24))
+(defmacro regspec-type (regspec)
+  `(%regspec-type ,regspec))
+
+(defun %regspec-type (regspec)
+  (if (typep regspec 'fixnum)
+    (the fixnum (ldb regspec-type-byte (the fixnum regspec)))
+    (if (typep regspec 'lreg)
+      (the fixnum (lreg-type regspec))
+      (error "bad regspec: ~s" regspec))))
+
+;;; Physical registers.
+;;; A regspec-type of 0 denotes some type of "physical" (machine) register:
+;;; a GPR, FPR, CR field, CR bit, or SPR.
+(defconstant regspec-hard-reg-type 0)
+; There are at most 32 members of any class of hard reg, so bytes 5-8 are
+; used to encode that information; the "value" of the hard reg in question
+; is in bits 0-4.
+; In some cases, we can also attach a "mode" to a hard-reg-spec.
+; Usually, non-0 values of the "mode" field are attached to the
+; "imm" (unboxed) registers.
+; A GPR whose "mode" is hard-reg-class-gpr-mode-node can have a "type"
+; field which asserts that the register's contents map onto one or more
+; of the primitive non-node types.  This information can help some of 
+; the functions that copy between GPRs of different "mode" elide some
+; type-checking.
+(defconstant regspec-hard-reg-type-value-byte (byte 8 0))
+(defconstant regspec-hard-reg-type-class-byte (byte 3 8))
+(defconstant regspec-hard-reg-type-mode-byte (byte 4 11))
+(defconstant regspec-hard-reg-type-type-byte (byte 8 15))
+
+(defconstant hard-reg-class-gpr 0)
+(defconstant hard-reg-class-fpr 1)
+; This is ppc-specific
+(defconstant hard-reg-class-crf 2)      ; Value is one of 0, 4, 8, ... 28
+(defconstant hard-reg-class-crbit 3)
+(defconstant hard-reg-class-spr 4)
+
+; "mode" values for GPRs.
+(defconstant hard-reg-class-gpr-mode-node 0)    ; a tagged lisp object
+(defconstant hard-reg-class-gpr-mode-u32 1)     ; unboxed unsigned 32-bit value
+(defconstant hard-reg-class-gpr-mode-s32 2)     ; unboxed signed 32-bit value
+(defconstant hard-reg-class-gpr-mode-u16 3)     ; unboxed unsigned 16-bit value
+(defconstant hard-reg-class-gpr-mode-s16 4)     ; unboxed signed 16-bit value
+(defconstant hard-reg-class-gpr-mode-u8 5)      ; unboxed unsigned 8-bit value
+(defconstant hard-reg-class-gpr-mode-s8 6)      ; unboxed signed 8-bit value
+(defconstant hard-reg-class-gpr-mode-address 7) ; unboxed unsigned 32-bit address
+(defconstant hard-reg-class-gpr-mode-u64 8)
+(defconstant hard-reg-class-gpr-mode-s64 9)
+
+(defconstant hard-reg-class-gpr-mode-invalid -1) ; Never a valid mode.
+
+; "mode" values for FPRs. 
+(defconstant hard-reg-class-fpr-mode-double 0)          ; unboxed IEEE double
+(defconstant hard-reg-class-fpr-mode-single 1)          ; unboxed IEEE single
+
+; "type" values for FPRs - type of SOURCE may be encoded herein
+(defconstant hard-reg-class-fpr-type-double 0)          ;  IEEE double
+(defconstant hard-reg-class-fpr-type-single 1)          ; IEEE single
+
+
+(defmacro set-regspec-mode (regspec mode)
+  `(%set-regspec-mode ,regspec ,mode))
+
+(defun %set-regspec-mode (regspec mode)
+  (if (typep regspec 'fixnum)
+    (dpb (the fixnum mode) regspec-hard-reg-type-mode-byte regspec)
+    (if (typep regspec 'lreg)
+      (progn (setf (lreg-mode regspec) mode) regspec)
+      (error "bad regspec: ~s" regspec))))
+
+(defmacro get-regspec-mode (regspec)
+  `(%get-regspec-mode ,regspec))
+
+(defun %get-regspec-mode (regspec)
+  (if (typep regspec 'fixnum)
+    (ldb regspec-hard-reg-type-mode-byte regspec)
+    (if (typep regspec 'lreg)
+      (lreg-mode regspec)
+      (error "bad regspec: ~s" regspec))))
+
+
+(defmacro node-regspec-type-modes (modes)
+  `(the fixnum (logior ,@(mapcar #'(lambda (x) `(ash 1 ,x)) modes))))
+
+(defmacro set-node-regspec-type-modes (regspec &rest modes)
+  `(%set-node-regspec-type-modes ,regspec (node-regspec-type-modes ,modes)))
+
+(defun %set-node-regspec-type-modes (regspec modes)
+  (if (typep regspec 'fixnum)
+    (dpb (the fixnum modes) regspec-hard-reg-type-type-byte (the fixnum regspec))
+    (if (typep regspec 'lreg)
+      (progn (setf (lreg-type regspec) modes) regspec)
+      (error "bad regspec: ~s" regspec))))
+
+(defmacro get-node-regspec-type-modes (regspec)
+  `(%get-regspec-type-modes ,regspec))
+
+(defun %get-regspec-type-modes (regspec)
+  (if (typep regspec 'fixnum)
+    (ldb regspec-hard-reg-type-type-byte (the fixnum regspec))
+    (if (typep regspec 'lreg)
+      (lreg-type regspec)
+      (error "bad regspec: ~s" regspec))))
+
+(defmacro hard-reg-class-mask (&rest classes)
+  `(the fixnum (logior ,@(mapcar #'(lambda (x) `(ash 1 ,x)) classes))))
+
+(defconstant hard-reg-class-gpr-mask (hard-reg-class-mask hard-reg-class-gpr))
+(defconstant hard-reg-class-gpr-crf-mask (hard-reg-class-mask hard-reg-class-gpr hard-reg-class-crf))
+
+; Assuming that "regspec" denotes a physical register, return its class.
+(defmacro hard-regspec-class (regspec)
+  `(%hard-regspec-class ,regspec))
+
+(defun %hard-regspec-class (regspec)
+  (if (typep regspec 'fixnum)
+    (the fixnum (ldb regspec-hard-reg-type-class-byte (the fixnum regspec)))
+    (if (typep regspec 'lreg)
+      (lreg-class regspec)
+      (error "bad regspec: ~s" regspec))))
+
+; Return physical regspec's value:
+(defmacro hard-regspec-value (regspec)
+  `(%hard-regspec-value ,regspec))
+
+(defun %hard-regspec-value (regspec)
+  (if (typep regspec 'fixnum)
+    (the fixnum (ldb regspec-hard-reg-type-value-byte (the fixnum regspec)))
+    (if (typep regspec 'lreg)
+      (lreg-value regspec)
+      (error "bad regspec: ~s" regspec))))
+
+;;; Logical (as opposed to "physical") registers are represented by structures
+;;; of type LREG.  The structures let us track information about assignments
+;;; and references to lregs, and the indirection lets us defer decisions about
+;;; storage mapping (register assignment, etc.) until later.
+
+;; A GPR which is allowed to hold any lisp object (but NOT an object header.)
+(defconstant regspec-lisp-reg-type 1)
+
+;; A GPR which is allowed to contain any -non- lisp object.
+(defconstant regspec-unboxed-reg-type 2)
+
+;; A GPR which can contain either an immediate lisp object (fixnum, immediate)
+;; or any non-lisp object.
+(defconstant regspec-any-gpr-reg-type (logior regspec-lisp-reg-type regspec-unboxed-reg-type))
+
+;; An FPR.  All FPRs are created equal; there's no reason to 
+;; worry about whether an FPR's holding a 32 or 64-bit float.
+(defconstant regspec-fpr-reg-type 4)
+
+;; One of the 8 fields of the Condition Register.
+(defconstant regspec-crf-reg-type 5)
+
+;; One of the 32 bits of the Condition Register.
+(defconstant regspec-crbit-reg-type 6)
+
+(defmacro make-hard-crf-reg (crf)
+  `(dpb hard-reg-class-crf regspec-hard-reg-type-class-byte (the fixnum ,crf)))
+  
+(defmacro make-hard-fp-reg (regnum &optional (mode hard-reg-class-fpr-mode-double))
+  `(dpb (the fixnum ,mode) 
+        regspec-hard-reg-type-mode-byte 
+        (dpb hard-reg-class-fpr regspec-hard-reg-type-class-byte (the fixnum ,regnum))))
+  
+;;; "Memory specs" have bit 28 set.  Since bit 28 is the sign bit in 68K MCL,
+;;; we have to be a little careful when creating them to ensure that the result
+;;; is a fixnum.
+
+(defmacro memory-spec-p (thing)
+  `(if (typep ,thing 'fixnum) (logbitp 28 (the fixnum ,thing))))
+
+(defmacro make-memory-spec (thing)
+  `(logior (ash -1 28) (the fixnum ,thing)))
+
+;;; Bits 24-26 (inclusive) of a memory-spec define the type of memory-spec in question.
+(defconstant memspec-type-byte (byte 3 24))
+(defmacro memspec-type (memspec)
+  `(ldb memspec-type-byte (the fixnum ,memspec)))
+
+;;; A slot in the value-stack frame.  This needs to get interpreted
+;;; relative to the top of the vsp.  The low 15 bits denote the
+;;; offset in the frame; the low 2 bits are always clear, since the
+;;; vstack is always aligned on a 32-bit boundary.
+(defconstant memspec-frame-address 0)
+
+
+
+;;; Address-specs - whether memory- or register-based - might be used to indicate the
+;;; canonical address of a variable.  Sometimes, this address is actually the address
+;;; of a "value cell" object; if so, bit 27 will be set in the indicated address.
+
+(defun addrspec-vcell-p (x)
+  (logbitp 27 x))
+
+(defmacro make-vcell-memory-spec (x)
+  `(logior (ash 1 27) (the fixnum ,x)))
+
+(defmacro memspec-frame-address-offset (m)
+  `(logand (the fixnum ,m) #xffff))
+
+
+(provide "REG")
Index: /branches/new-random/compiler/risc-lap.lisp
===================================================================
--- /branches/new-random/compiler/risc-lap.lisp	(revision 13309)
+++ /branches/new-random/compiler/risc-lap.lisp	(revision 13309)
@@ -0,0 +1,198 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; Lap data structures & some generic code (at least for RISC backends.)
+
+(in-package "CCL")
+
+(defvar *lap-labels* ())
+(defvar *lap-instructions* ())
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "ARCH")
+  (require "DLL-NODE")
+  (require "SUBPRIMS"))
+
+
+;;; For assembly/disassembly, at least on RISC platforms.
+(defstruct opcode 
+  (name (error "Opcode name must be present") :type (or string symbol))
+  (opcode 0 :type (unsigned-byte 32))
+  (majorop 0 :type (unsigned-byte 6))
+  (mask #xffffffff :type (unsigned-byte 32))
+  (flags 0 :type (unsigned-byte 32))
+  (operands () :type list)
+  (min-args 0 :type (unsigned-byte 3))
+  (max-args 0 :type (unsigned-byte 3))
+  (op-high 0 :type (unsigned-byte 16))
+  (op-low 0 :type (unsigned-byte 16))
+  (mask-high #xffff :type (unsigned-byte 16))
+  (mask-low #xffff :type (unsigned-byte 16))
+  (vinsn-operands () :type list)
+  (min-vinsn-args 0 :type fixnum)
+  (max-vinsn-args 0 :type fixnum))
+
+(defmethod print-object ((p opcode) stream)
+  (print-unreadable-object (p stream :type t) 
+    (format stream "~a" (string (opcode-name p)))))
+
+(defmethod make-load-form ((p opcode) &optional env)
+  (make-load-form-saving-slots p :environment env))
+
+(defstruct operand
+  (index 0 :type unsigned-byte)
+  (width 0 :type (mod 32))
+  (offset 0 :type (mod 32))
+  (insert-function nil :type (or null symbol function))
+  (extract-function 'nil :type (or symbol function))
+  (flags 0 :type fixnum))
+
+(defmethod make-load-form ((o operand) &optional env)
+  (make-load-form-saving-slots o :environment env))
+
+(defconstant operand-optional 27)
+(defconstant operand-fake 28)
+
+(eval-when (:execute :load-toplevel)
+  (defstruct (instruction-element (:include dll-node))
+    address)
+
+  (defstruct (lap-instruction (:include instruction-element)
+                                  (:constructor %make-lap-instruction (opcode)))
+    opcode
+    parsed-operands
+    )
+
+  (defstruct (lap-note (:include instruction-element))
+    peer
+    id)
+
+  (defstruct (lap-note-begin (:include lap-note)))
+  (defstruct (lap-note-end (:include lap-note)))
+    
+  (defstruct (lap-label (:include instruction-element)
+                            (:constructor %%make-lap-label (name)))
+    name
+    refs))
+
+(def-standard-initial-binding *lap-label-freelist* (make-dll-node-freelist))
+(def-standard-initial-binding *lap-instruction-freelist* (make-dll-node-freelist))
+
+(def-standard-initial-binding *operand-vector-freelist* (%cons-pool))
+
+(defconstant lap-operand-vector-size #+ppc-target 5)
+
+(defun alloc-lap-operand-vector (&optional (size lap-operand-vector-size))
+  (declare (fixnum size))
+  (if (eql size lap-operand-vector-size)
+    (without-interrupts 
+     (let* ((freelist  *operand-vector-freelist*)
+            (v (pool.data freelist)))
+       (if v
+         (progn
+           (setf (pool.data freelist) 
+                 (svref v 0))
+           (%init-misc nil v)
+           v)
+         (make-array lap-operand-vector-size  :initial-element nil))))
+    (make-array size :initial-element nil)))
+
+(defun free-lap-operand-vector (v)
+  (when (= (length v) lap-operand-vector-size)
+    (without-interrupts 
+     (setf (svref v 0) (pool.data *operand-vector-freelist*)
+           (pool.data *operand-vector-freelist*) nil))))
+
+(defun %make-lap-label (name)
+  (let* ((lab (alloc-dll-node *lap-label-freelist*)))
+    (if lab
+      (progn
+        (setf (lap-label-address lab) nil
+              (lap-label-refs lab) nil
+              (lap-label-name lab) name)
+        lab)
+      (%%make-lap-label name))))
+
+(defun make-lap-instruction (opcode)
+  (let* ((insn (alloc-dll-node *lap-instruction-freelist*)))
+    (if (typep insn 'lap-instruction)
+      (progn
+        (setf (lap-instruction-address insn) nil
+              (lap-instruction-parsed-operands insn) nil
+              (lap-instruction-opcode insn) opcode)
+        insn)
+      (%make-lap-instruction opcode))))
+
+(defmacro do-lap-labels ((lab &optional result) &body body)
+  (let* ((thunk-name (gensym))
+         (k (gensym))
+         (xlab (gensym)))
+    `(flet ((,thunk-name (,lab) ,@body))
+      (if (listp *lap-labels*)
+        (dolist (,xlab *lap-labels*)
+          (,thunk-name ,xlab))
+        (maphash #'(lambda (,k ,xlab)
+                     (declare (ignore ,k))
+                     (,thunk-name ,xlab))
+                 *lap-labels*))
+      ,result)))
+
+(defun make-lap-label (name)
+  (let* ((lab (%make-lap-label name)))
+    (if (typep *lap-labels* 'hash-table)
+      (setf (gethash name *lap-labels*) lab)
+      (progn
+        (push lab *lap-labels*)
+        (if (> (length *lap-labels*) 255)
+          (let* ((hash (make-hash-table :size 512 :test #'eq)))
+            (dolist (l *lap-labels* (setq *lap-labels* hash))
+              (setf (gethash (lap-label-name l) hash) l))))))
+    lab))
+
+(defun find-lap-label (name)
+  (if (typep *lap-labels* 'hash-table)
+    (gethash name *lap-labels*)
+    (car (member name *lap-labels* :test #'eq :key #'lap-label-name))))
+
+(defun lap-note-label-reference (labx insn)
+  '(unless (and labx (symbolp labx))
+    (error "Label names must be symbols; otherwise, all hell might break loose."))
+  (let* ((lab (or (find-lap-label labx)
+                  (make-lap-label labx))))
+    (push insn (lap-label-refs lab))
+    lab))
+
+;;; A label can only be emitted once.  Once it's been emitted, its pred/succ
+;;; slots will be non-nil.
+
+(defun lap-label-emitted-p (lab)
+  (not (null (lap-label-pred lab))))
+
+
+(defun emit-lap-label (name)
+  (let* ((lab (find-lap-label name)))
+    (if  lab 
+      (when (lap-label-emitted-p lab)
+        (error "Label ~s: multiply defined." name))
+      (setq lab (make-lap-label name)))
+    (append-dll-node lab *lap-instructions*)))
+
+(defun emit-lap-note (note)
+  (append-dll-node note *lap-instructions*))
+
+(provide "RISC-LAP")
+
Index: /branches/new-random/compiler/subprims.lisp
===================================================================
--- /branches/new-random/compiler/subprims.lisp	(revision 13309)
+++ /branches/new-random/compiler/subprims.lisp	(revision 13309)
@@ -0,0 +1,50 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defstruct subprimitive-info
+  name
+  offset
+  nailed-down
+  argument-mask
+  registers-used
+  )
+
+(defmethod make-load-form ((s subprimitive-info) &optional env)
+  (make-load-form-saving-slots s :environment env))
+
+(defmethod print-object ((s subprimitive-info) stream)
+  (print-unreadable-object (s stream :type t)
+    (format stream "~A @ #x~x" 
+            (subprimitive-info-name s)
+            (subprimitive-info-offset s))))
+
+(defun %subprim-name->offset (name table)
+  (let* ((sprec (find name table 
+                      :test #'string-equal 
+                      :key #'subprimitive-info-name)))
+    (if sprec
+      (subprimitive-info-offset sprec)
+      (error "subprim named ~s not found." name))))
+
+(defun subprim-name->offset (name &optional (backend *target-backend*))
+  (+ (backend-lowmem-bias backend)
+     (%subprim-name->offset name  (arch::target-subprims-table
+                                   (backend-target-arch backend)))))
+
+(provide "SUBPRIMS")
Index: /branches/new-random/compiler/vinsn.lisp
===================================================================
--- /branches/new-random/compiler/vinsn.lisp	(revision 13309)
+++ /branches/new-random/compiler/vinsn.lisp	(revision 13309)
@@ -0,0 +1,774 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(cl:eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "DLL-NODE")
+  (require "BACKEND"))
+
+
+(cl:in-package "CCL")
+
+;;; Specifying the same name for a result and an argument basically
+;;; says that it's ok for the vinsn to clobber that argument.  (In all
+;;; other cases, arguments are assumed to be "read-only", and damned
+;;; well better be.)  Any results that are also arguments must follow
+;;; all results that aren't in the "results" list; any arguments that
+;;; are also results must precede all arguments that aren't in the
+;;; "arguments" list, and all hybrids must appear in the same order in
+;;; both lists. This is what "nhybrids" is about (and why it defaults
+;;; to 0 ...)  Sometimes (often) these hybrid "results" aren't very
+;;; interesting as results;;; it might be clearer to consider
+;;; "mutable" arguments as quasi-temporaries.
+(defstruct vinsn-template
+  name                                  ; a symbol in the target package
+  result-vreg-specs                     ; one or more vreg specs for values defined by the vinsn
+  argument-vreg-specs                   ; may ultimately overlap some result vreg(s)
+  ; one or more vreg specs for temporaries used in vinsn.
+  ; all such temporaries are assumed to have lifetimes which span all
+  ; machine instructions in the vinsn (e.g., they can't conflict with any
+  ; registers used for args/results and may have further constraints.
+  temp-vreg-specs                  
+  local-labels
+  body                                  ; list of target instructions, local labels
+  (nhybrids 0)
+  (nvp 0)
+  results&args                          ;
+  (attributes 0)                        ; attribute bitmask
+  opcode-alist                          ; ((number1 . name1) (number2 . name2) ...)
+)
+
+(defmethod make-load-form ((v vinsn-template) &optional env)
+  (make-load-form-saving-slots v :environment env))
+
+
+(defun get-vinsn-template-cell (name templates)
+  (let* ((n (intern (string name) *ccl-package*)))
+    (or (gethash n templates)
+        (setf (gethash n templates) (cons n nil)))))
+
+(defun need-vinsn-template (name templates)
+  (or (cdr (if (consp name) name (get-vinsn-template-cell name templates)))
+      (error "Unknown vinsn: ~s" name)))
+
+(defun set-vinsn-template (name template templates)
+  (setf (cdr (get-vinsn-template-cell name templates)) template))
+
+(defstruct (vinsn (:include dll-node)
+                  (:print-function print-vinsn)
+                  (:constructor %make-vinsn (template)))
+  template                              ; The vinsn-template of which this is an instance
+  variable-parts                        ; vector of result-vregs, arguments, temps, local-labels
+  annotation
+  (gprs-set 0)
+  (fprs-set 0)
+)
+
+(def-standard-initial-binding *vinsn-freelist* (make-dll-node-freelist))
+
+(defun make-vinsn (template)
+  (let* ((vinsn (alloc-dll-node *vinsn-freelist*)))
+    (loop
+      ; Sometimes, the compiler seems to return its node list
+      ; to the freelist without first removing the vinsn-labels in it.
+      (if (or (null vinsn) (typep vinsn 'vinsn)) (return))
+      (setq vinsn (alloc-dll-node *vinsn-freelist*)))
+    (if vinsn
+      (progn
+        (setf (vinsn-template vinsn) template
+              (vinsn-variable-parts vinsn) nil
+              (vinsn-annotation vinsn) nil
+	      (vinsn-gprs-set vinsn) 0
+	      (vinsn-fprs-set vinsn) 0)
+        vinsn)
+      (%make-vinsn template))))
+
+(eval-when (:load-toplevel :execute)
+(defstruct (vinsn-label (:include dll-node)
+                        (:print-function print-vinsn-label)
+                        (:predicate %vinsn-label-p)
+                        (:constructor %make-vinsn-label (id)))
+  id
+  refs                                  ; vinsns in which this label appears as an operand
+  info                                  ; code-generation stuff
+)
+)
+
+(def-standard-initial-binding *vinsn-label-freelist* (make-dll-node-freelist))
+
+(defun make-vinsn-label (id)
+  (let* ((lab (alloc-dll-node *vinsn-label-freelist*)))
+    (if lab
+      (progn
+        (setf (vinsn-label-id lab) id
+              (vinsn-label-refs lab) nil
+              (vinsn-label-info lab) nil)
+        lab)
+      (%make-vinsn-label id))))
+
+; "Real" labels have fixnum IDs.
+(defun vinsn-label-p (l)
+  (if (%vinsn-label-p l) 
+    (typep (vinsn-label-id l) 'fixnum)))
+
+
+(defun print-vinsn-label (l s d)
+  (declare (ignore d))
+  (print-unreadable-object (l s :type t)
+    (format s "~d" (vinsn-label-id l))))
+
+;;; Notes are attached to (some) vinsns.  They're used to attach
+;;; semantic information to an execution point.  The vinsn
+;;; points to the note via its LABEL-ID; the note has a backpointer to
+;;; the vinsn.
+
+(defstruct (vinsn-note
+            (:constructor %make-vinsn-note)
+            (:print-function print-vinsn-note))
+  (label (make-vinsn-label nil))
+  (peer nil :type (or null vinsn-note))
+  (class nil)
+  (info nil :type (or null simple-vector)))
+
+
+(defun print-vinsn-note (n s d)
+  (declare (ignore d))
+  (print-unreadable-object (n s :type t)
+    (format s "~d" (vinsn-note-class n))
+    (let* ((info (vinsn-note-info n)))
+      (when info (format s " / ~S" info)))))
+  
+(defun make-vinsn-note (class info)
+  (let* ((n (%make-vinsn-note :class class :info (if info (apply #'vector info))))
+         (lab (vinsn-note-label n)))
+    (setf (vinsn-label-id lab) n)
+    n))
+
+(defun close-vinsn-note (n)
+  (let* ((end (%make-vinsn-note :peer n)))
+    (setf (vinsn-label-id (vinsn-note-label end)) end
+          (vinsn-note-peer end) n
+          (vinsn-note-peer n) end)
+    end))
+        
+
+(defun vinsn-vreg-description (value spec)
+  (case (cadr spec)
+    ((:u32 :s32 :u16 :s16 :u8 :s8 :lisp :address :imm)
+     (let* ((mode (if (typep value 'fixnum)
+                    (get-regspec-mode value))))
+       (if (and mode (not (eql 0 mode)))
+         (list (hard-regspec-value value)
+               (car (rassoc mode *mode-name-value-alist* :test #'eq)))
+         value)))
+    (t value)))
+
+(defun collect-vinsn-variable-parts (v start n &optional specs)
+  (declare (fixnum start n))
+  (let* ((varparts (vinsn-variable-parts v)))
+    (when varparts
+      (let* ((head (cons nil nil))
+	     (tail head))
+	(declare (dynamic-extent head) (cons head tail))
+	(do* ((j start (1+ j))
+              (i 0 (1+ i)))
+             ((= i n) (cdr head))
+          (declare (fixnum i j))
+          (setq tail (cdr (rplacd tail (cons (vinsn-vreg-description (svref varparts j) (pop specs)) nil)))))))))
+
+      
+(defun collect-vinsn-results (v)
+  (let* ((template (vinsn-template v))
+         (result-specs (vinsn-template-result-vreg-specs template)))
+    (collect-vinsn-variable-parts v 0 (length result-specs) result-specs)))
+
+(defun collect-vinsn-arguments (v)
+  (let* ((template (vinsn-template v))
+         (arg-specs (vinsn-template-argument-vreg-specs template)))
+    (collect-vinsn-variable-parts v
+                                  (- (length (vinsn-template-result-vreg-specs template)) 
+                                     (vinsn-template-nhybrids template))
+                                  (length arg-specs)
+                                  arg-specs)))
+
+(defun collect-vinsn-temps (v)
+  (let* ((template (vinsn-template v)))
+    (collect-vinsn-variable-parts v 
+                                  (+
+                                   (length (vinsn-template-result-vreg-specs template)) 
+                                   (length (vinsn-template-argument-vreg-specs template)))
+                                  (length (vinsn-template-temp-vreg-specs template)))))
+
+(defun template-infix-p (template)
+  (declare (ignore template))
+  nil)
+
+(defun print-vinsn (v stream d)
+  (declare (ignore d))
+  (let* ((template (vinsn-template v))
+         (results (collect-vinsn-results v))
+         (args (collect-vinsn-arguments v))
+         (opsym (if (cdr results) :== :=))
+         (infix (and (= (length args) 2) (template-infix-p template)))
+         (opname (vinsn-template-name template)))
+    (print-unreadable-object (v stream)
+      (if results (format stream "~A ~S " (if (cdr results) results (car results)) opsym))
+      (if infix
+        (format stream "~A ~A ~A" (car args) opname (cadr args))
+        (format stream "~A~{ ~A~}" opname args))
+      (let* ((annotation (vinsn-annotation v)))
+	(when annotation
+	  (format stream " ||~a|| " annotation))))))
+  
+(defparameter *known-vinsn-attributes*
+  '(
+    :jump				; an unconditional branch
+    :branch				; a conditional branch
+    :call				; a jump that returns
+    :funcall				; A full function call, assumed to bash all volatile registers
+    :subprim-call			; A subprimitive call; bashes some volatile registers
+    :jumpLR				; Jumps to the LR, possibly stopping off at a function along the way.
+    :lrsave				; saves LR in LOC-PC
+    :lrrestore				; restores LR from LOC-PC
+    :lispcontext			; references lisp frame LOC-PC, FN, and entry VSP
+    :node				; saves/restores a node value in stack-like memory
+    :word				; saves/restores an unboxed word in stack-like memory
+    :doubleword				; saves/restores an unboxed doubleword (fp-reg) in stack-like memory
+    :vsp				; uses the vsp to save/restore
+    :tsp				; uses the tsp to save/restore
+    :csp				; uses sp to save/restore
+    :push				; saves something
+    :pop				; restores something
+    :multiple				; saves/restores multiple nodes/words/doublewords
+    :ref				; references memory
+    :set				; sets memory
+    :outgoing-argument			; e.g., pushed as an argument, not to avoid clobbering
+    :xref				; makes some label externally visible
+    :jump-unknown			; Jumps, but we don't know where ...
+    :constant-ref
+    :sets-cc                            ; vinsn sets condition codes based on result
+    :discard                            ; adjusts a stack pointer
+    ))
+
+(defparameter *nvp-max* 10 "size of *vinsn-varparts* freelist elements")
+(def-standard-initial-binding *vinsn-varparts* (%cons-pool))
+
+(defun alloc-varparts-vector ()
+  (without-interrupts
+   (let* ((v (pool.data *vinsn-varparts*)))
+     (if v
+       (progn
+         (setf (pool.data *vinsn-varparts*)
+               (svref v 0))
+          (%init-misc 0 v)
+         v)
+       (make-array (the fixnum *nvp-max*) :initial-element 0)))))
+
+(defun free-varparts-vector (v)
+  (without-interrupts
+   (setf (svref v 0) (pool.data *vinsn-varparts*)
+         (pool.data *vinsn-varparts*) v)
+   nil))
+
+(defun elide-vinsn (vinsn)
+  (let* ((nvp (vinsn-template-nvp (vinsn-template vinsn)))
+	 (vp (vinsn-variable-parts vinsn)))
+    (dotimes (i nvp)
+      (let* ((v (svref vp i)))
+	(when (typep v 'lreg)
+	  (setf (lreg-defs v) (delete vinsn (lreg-defs v)))
+	  (setf (lreg-refs v) (delete vinsn (lreg-refs v))))))
+    (free-varparts-vector vp)
+    (remove-dll-node vinsn)))
+    
+(defun encode-vinsn-attributes (attribute-list)
+  (flet ((attribute-weight (k)
+           (let* ((pos (position k *known-vinsn-attributes*)))
+             (if pos (ash 1 pos) (error "Unknown vinsn attribute: ~s" k)))))
+    (let* ((attr 0))
+      (declare (fixnum attr))
+      (dolist (a attribute-list attr)
+        (setq attr (logior attr (the fixnum (attribute-weight a))))))))
+
+
+(defun %define-vinsn (backend vinsn-name results args temps body)
+  (funcall (backend-define-vinsn backend)
+           backend
+           vinsn-name
+           results
+           args
+           temps
+           body))
+
+
+;; Fix the opnum's in the vinsn-template-body to agree with the
+;; backend's opcode hash table.
+(defun fixup-vinsn-template (orig-template opcode-hash)
+  (let ((template (cdr orig-template)))
+    (when template
+      (unless (vinsn-template-p template)
+        (setq template (require-type template 'vinsn-template)))
+      (let ((new-opcode-alist nil)
+            (changes nil)
+            (opcode-alist (vinsn-template-opcode-alist template)))
+        ;; this is patterned after ppc2-expand-vinsn
+        (labels ((walk-form (f)
+                   (unless (atom f)
+                     (if (fixnump (car f))
+                       (got-one f)
+                       (dolist (subform (cdr f))
+                         (walk-form subform)))))
+                 (got-one (f)
+                   (let* ((old-opcode (car f))
+                          (name (cdr (assq old-opcode opcode-alist)))
+                          (new-opcode (and name (gethash name opcode-hash))))
+                     (unless new-opcode
+                       (cerror "Continue" "Can't find new opcode number ~
+                                   for ~s in ~s" (car f) template))
+                     (setf (assq new-opcode new-opcode-alist) name)
+                     (unless (eq new-opcode old-opcode)
+                       (push (cons f new-opcode) changes)))))
+          (mapc #'walk-form (vinsn-template-body template))
+          (without-interrupts
+           (dolist (change changes)
+             (setf (caar change) (cdr change)))
+           (setf (vinsn-template-opcode-alist template)
+                 new-opcode-alist))))
+      orig-template)))
+
+(defun fixup-vinsn-templates (templates opcode-hash-table)
+  (maphash #'(lambda (name template)
+               (declare (ignore name))
+               (fixup-vinsn-template template opcode-hash-table))
+           templates))
+                                       
+;;; Could probably split this up and do some arg checking at macroexpand time.
+(defun match-template-vregs (template vinsn supplied-vregs)
+  (declare (list supplied-vregs))
+  (let* ((nsupp (length supplied-vregs))
+         (results&args (vinsn-template-results&args template))
+         (nra (length results&args))
+         (temp-specs (vinsn-template-temp-vreg-specs template))
+         (ntemps (length temp-specs))
+         (nvp (vinsn-template-nvp template))
+         (vp (alloc-varparts-vector))
+         (*available-backend-node-temps* *available-backend-node-temps*)
+	 (*available-backend-fp-temps* *available-backend-fp-temps*)
+         (*available-backend-imm-temps* *available-backend-imm-temps*)
+         (*available-backend-crf-temps* *available-backend-crf-temps*))
+    (declare (fixnum nvp ntemps nsupp)
+             (list temp-specs))
+    (unless (= nsupp nra)
+      (error "Vinsn ~A expects ~D result/argument specs, received ~D ."
+             (vinsn-template-name template) nra nsupp))
+    (do* ((i 0 (1+ i))
+          (supp supplied-vregs (cdr supp))
+          (spec results&args (cdr spec)))
+         ((null supp))
+      (declare (fixnum i) (list spec supp))
+      (setf (svref vp i) (match-vreg (car supp) (cadar spec) vinsn vp i)))
+    ;; Allocate some temporaries.
+    (do* ((i (- nvp ntemps) (1+ i))
+          (temps temp-specs (cdr temps)))
+         ((null temps) vp)
+      (declare (fixnum i))
+      (let* ((spec (cadar temps)))
+        (if (and (consp spec) (eq (car spec) :label))
+          (let* ((label (aref *backend-labels* (cadr spec))))
+            (push vinsn (vinsn-label-refs label))
+            (setf (svref vp i) label))
+          (let* ((lreg (allocate-temporary-vreg (car temps)))
+                 (class (hard-regspec-class lreg))
+                 (value (hard-regspec-value lreg)))
+            (when value
+              (case class
+                (#.hard-reg-class-gpr (note-vinsn-sets-gpr vinsn value))
+                (#.hard-reg-class-fpr (note-vinsn-sets-fpr vinsn value))))
+            (setf (svref vp i) lreg)
+            (pushnew vinsn (lreg-defs lreg))
+            (pushnew vinsn (lreg-refs lreg))))))))
+
+;;; "spec" is (<name> <class>).
+;;;  <class> is keyword or (<keyword> <val>)
+(defun allocate-temporary-vreg (spec)
+  (setq spec (cadr spec))
+  (let* ((class (if (atom spec) spec (car spec)))
+         (value (if (atom spec) nil (cadr spec))))
+    (if value
+      (ecase class
+        (:crf (make-wired-lreg (use-crf-temp value) :class hard-reg-class-crf))
+        ((:u8 :s8 :u16 :s16 :u32 :s32 :u64 :s64) 
+         (make-wired-lreg (use-imm-temp value)
+			  :class hard-reg-class-gpr
+			  :mode (gpr-mode-name-value class)))
+        (:lisp (make-wired-lreg 
+                (use-node-temp value) 
+                :class hard-reg-class-gpr
+                :mode hard-reg-class-gpr-mode-node)))
+      (ecase class
+        ((:imm :wordptr) 
+         (make-unwired-lreg
+          (if (= *available-backend-imm-temps* 0) (select-node-temp) (select-imm-temp))
+              :class hard-reg-class-gpr
+              :mode hard-reg-class-gpr-mode-node)) 
+        ((:u8 :s8 :u16 :s16 :u32 :s32 :u64 :s64) 
+         (make-unwired-lreg (select-imm-temp)
+			    :class hard-reg-class-gpr
+			    :mode (gpr-mode-name-value class)))
+        (:lisp 
+         (make-unwired-lreg 
+	  (select-node-temp) 
+	  :class hard-reg-class-gpr
+	  :mode hard-reg-class-gpr-mode-node))
+        (:crf 
+         (make-unwired-lreg (select-crf-temp) :class hard-reg-class-crf))))))
+
+
+
+(defun select-vinsn (template-or-name template-hash vregs)
+  (let* ((template (need-vinsn-template template-or-name template-hash))
+         (vinsn (make-vinsn template)))
+    (setf (vinsn-variable-parts vinsn) (match-template-vregs template vinsn vregs))
+    vinsn))
+
+(defun %emit-vinsn (vlist name vinsn-table &rest vregs)
+  (append-dll-node (select-vinsn name vinsn-table vregs) vlist))
+
+(defun varpart-matches-reg (varpart-value class regval spec)
+  (setq spec (if (atom spec) spec (car spec)))
+  (and
+   (or
+    (and (eq class hard-reg-class-fpr)
+	 (memq spec '(:single-float :double-float)))
+    (and (eq class hard-reg-class-gpr)
+	 (memq spec '(:u32 :s32 :u16 :s16 :u8 :s8 :lisp :address :imm))))
+   (eq (hard-regspec-value varpart-value) regval)))
+
+(defun vinsn-sets-reg-p (element reg)
+  (if (typep element 'vinsn)
+    (if (vinsn-attribute-p element :call)
+      t
+      (let* ((class (hard-regspec-class reg))
+	     (value (hard-regspec-value reg)))
+	(if (eq class hard-reg-class-gpr)
+	  (logbitp value (vinsn-gprs-set element))
+	  (if (eq class hard-reg-class-fpr)
+	    (logbitp value (vinsn-fprs-set element))))))))
+
+;;; Return bitmasks of all GPRs and all FPRs set in the vinsns between
+;;; START and END, exclusive.  Any :call vinsn implicitly clobbers
+;;; all registers.
+(defun regs-set-in-vinsn-sequence (start end)
+  (let* ((gprs-set 0)
+	 (fprs-set 0))
+    (do* ((element (vinsn-succ start) (vinsn-succ element)))
+	 ((eq element end) (values gprs-set fprs-set))n
+      (if (typep element 'vinsn)
+	(if (vinsn-attribute-p element :call)
+	  (return (values #xffffffff #xffffffff))
+	  (setq gprs-set (logior (vinsn-gprs-set element))
+		fprs-set (logior (vinsn-fprs-set element))))))))
+      
+;;; Return T if any vinsn between START and END (exclusive) sets REG.
+(defun vinsn-sequence-sets-reg-p (start end reg)
+  (do* ((element (vinsn-succ start) (vinsn-succ element)))
+       ((eq element end))
+    (if (vinsn-sets-reg-p element reg)
+      (return t))))
+	
+
+;;; Return T if any vinsn between START and END (exclusive) has all
+;;; attributes set in MASK set.
+(defun %vinsn-sequence-has-attribute-p (start end attr)
+  (do* ((element (vinsn-succ start) (vinsn-succ element)))
+       ((eq element end))
+    (when (typep element 'vinsn)
+      (when (eql attr (logand (vinsn-template-attributes (vinsn-template element))))
+        (return t)))))
+
+(defmacro vinsn-sequence-has-attribute-p (start end &rest attrs)
+  `(%vinsn-sequence-has-attribute-p ,start ,end ,(encode-vinsn-attributes attrs)))
+
+                               
+;;; Flow-graph nodes (FGNs)
+
+(defstruct (fgn (:include dll-header))
+  (id 0 :type unsigned-byte)
+  (inedges ())                          ; list of nodes which reference this node
+  (visited nil)                         ; Boolean
+)
+
+
+
+;;; FGNs which don't terminate with an "external jump"
+;;; (jump-return-pc/jump-subprim, etc) jump to their successor, either
+;;; explicitly or by falling through.  We can introduce or remove
+;;; jumps when linearizing the program.
+(defstruct (jumpnode (:include fgn)
+		     (:constructor %make-jumpnode (id)))
+  (outedge)                             ; the FGN we jump/fall in to.
+)
+
+(defun make-jumpnode (id)
+  (init-dll-header (%make-jumpnode id)))
+    
+;;; A node that ends in a conditional branch, followed by an implicit
+;;; or explicit jump.  Keep track of the conditional branch and the
+;;; node it targets.
+(defstruct (condnode (:include jumpnode)
+		     (:constructor %make-condnode (id)))
+  (condbranch)                          ; the :branch vinsn
+  (branchedge)                          ; the FGN it targets
+)
+
+(defun make-condnode (id)
+  (init-dll-header (%make-condnode id)))
+	  
+;;; A node that terminates with a return i.e., a jump-return-pc or
+;;; jump-subprim.
+(defstruct (returnnode (:include fgn)
+		       (:constructor %make-returnnode (id)))
+)
+
+(defun make-returnnode (id)
+  (init-dll-header (%make-returnnode id)))
+
+;;; Some specified attribute is true.
+(defun %vinsn-attribute-p (vinsn mask)
+  (declare (fixnum mask))
+  (if (vinsn-p vinsn)
+    (let* ((template (vinsn-template vinsn)))
+      (not (eql 0 (logand mask (the fixnum (vinsn-template-attributes template))))))))
+
+;;; All specified attributes are true.
+(defun %vinsn-attribute-= (vinsn mask)
+  (declare (fixnum mask))
+  (if (vinsn-p vinsn)
+    (let* ((template (vinsn-template vinsn)))
+      (= mask (the fixnum (logand mask (the fixnum (vinsn-template-attributes template))))))))
+  
+(defmacro vinsn-attribute-p (vinsn &rest attrs)
+  `(%vinsn-attribute-p ,vinsn ,(encode-vinsn-attributes attrs)))
+
+(defmacro vinsn-attribute-= (vinsn &rest attrs)
+  `(%vinsn-attribute-= ,vinsn ,(encode-vinsn-attributes attrs)))
+
+;;; Ensure that conditional branches that aren't followed by jumps are
+;;; followed by (jump lab-next) @lab-next.  Ensure that JUMPs and
+;;; JUMPLRs are followed by labels.  It's easiest to do this by
+;;; walking backwards.  When we're all done, labels will mark the
+;;; start of each block.
+
+(defun normalize-vinsns (header)
+  (do* ((prevtype :label currtype)
+        (current (dll-header-last header) (dll-node-pred current))
+        (currtype nil))
+       ((eq current header)
+	(unless (eq prevtype :label)
+	  (insert-dll-node-after
+	   (aref *backend-labels* (backend-get-next-label))
+	   current)))
+    (setq currtype (cond ((vinsn-label-p current) :label)
+                         ((vinsn-attribute-p current :branch) :branch)
+                         ((vinsn-attribute-p current :jump) :jump)
+                         ((vinsn-attribute-p current :jumplr) :jumplr)))
+    (case currtype
+      ((:jump :jumplr)
+       (unless (eq prevtype :label)
+         (let* ((lab (aref *backend-labels* (backend-get-next-label))))
+           (insert-dll-node-after lab current))))
+      (:branch
+       (unless (eq prevtype :jump)
+         (let* ((lab
+                 (if (eq prevtype :label)
+                   (dll-node-succ current)
+                   (aref *backend-labels* (backend-get-next-label))))
+                (jump (select-vinsn "JUMP" *backend-vinsns* (list lab))))
+           (unless (eq prevtype :label)
+             (insert-dll-node-after lab current))
+           (insert-dll-node-after jump current))))
+      ((nil)
+       (if (eq prevtype :label)
+	 (let* ((lab (dll-node-succ current)))
+	   (when (vinsn-label-p lab)
+             (insert-dll-node-after
+              (select-vinsn "JUMP" *backend-vinsns* (list lab))
+	      current))))))))
+
+
+;;; Unless the header is empty, remove the last vinsn and all preceding
+;;; vinsns up to and including the preceding label.  (Since the vinsns
+;;; have been normalized, there will always be a preceding label.)
+;;; Return the label and the last vinsn, or (values nil nil.)
+(defun remove-last-basic-block (vinsns)
+  (do* ((i 1 (1+ i))
+	(current (dll-header-last vinsns) (dll-node-pred current)))
+       ((eq current vinsns) (values nil nil))
+    (declare (fixnum i))
+    (if (vinsn-label-p current)
+      (return (remove-dll-node current i)))))
+
+;;; Create a flow graph from vinsns and return the entry node.
+(defun create-flow-graph (vinsns)
+  (let* ((nodes ()))
+    (flet ((label->fgn (label) (dll-node-pred label)))
+      (loop
+	  (multiple-value-bind (label last) (remove-last-basic-block vinsns)
+	    (when (null label) (return))
+	    (let* ((id (vinsn-label-id label))
+		   (node (if (vinsn-attribute-p last :jumpLR)
+			   (make-returnnode id)
+			   (if (vinsn-attribute-p (dll-node-pred last) :branch)
+			     (make-condnode id)
+			     (make-jumpnode id)))))
+              (declare (fixnum id))
+	      (insert-dll-node-after label node last)
+	      (push node nodes))))
+      (dolist (node nodes nodes)
+	(if (typep node 'jumpnode)
+	  (let* ((jump (dll-header-last node))
+		 (jmptarget (branch-target-node jump)))
+	    (setf (jumpnode-outedge node) jmptarget)
+	    (pushnew node (fgn-inedges jmptarget))
+	    (if (typep node 'condnode)	; a subtype of jumpnode
+	      (let* ((branch (dll-node-pred jump))
+		     (branchtarget (branch-target-node branch)))
+		(setf (condnode-condbranch node) branch)
+		(pushnew node (fgn-inedges branchtarget))))))))))
+  
+                         
+(defun delete-unreferenced-labels (labels)
+  (delete #'(lambda (l)
+              (unless (vinsn-label-refs l)
+                (when (vinsn-label-succ l)
+                  (remove-dll-node l))
+                t)) labels :test #'funcall))
+
+(defun branch-target-node (v)
+  (dll-node-pred (svref (vinsn-variable-parts v) 0)))
+
+(defun replace-label-refs (vinsn old-label new-label)
+  (let ((vp (vinsn-variable-parts vinsn)))
+    (dotimes (i (length vp))
+      (when (eq (svref vp i) old-label)
+        (setf (svref vp i) new-label)))))
+  
+;;; Try to remove jumps/branches to jumps.
+(defun maximize-jumps (header)
+  (do* ((prev nil next)
+        (next (dll-header-first header) (dll-node-succ next)))
+       ((eq next header))
+    (when (and (vinsn-attribute-p next :jump)
+               (vinsn-label-p  prev))
+      (let* ((target (svref (vinsn-variable-parts next) 0)))
+        (unless (eq target prev)
+          (dolist (ref (vinsn-label-refs prev) (setf (vinsn-label-refs prev) nil))
+            (replace-label-refs ref prev target)
+            (push ref (vinsn-label-refs target))))))))
+
+(defun optimize-vinsns (header)
+  ;; Delete unreferenced labels that the compiler might have emitted.
+  ;; Subsequent operations may cause other labels to become
+  ;; unreferenced.
+  (let* ((labels (collect ((labs)) 
+                   (do-dll-nodes (v header)
+                     (when (vinsn-label-p v) (labs v)))
+                   (labs))))
+    ;; Look for pairs of adjacent, referenced labels.
+    ;; Merge them together (so that one of them becomes unreferenced.)
+    ;; Repeat the process until no pairs are found.
+    (do* ((repeat t))
+         ((not repeat))
+      (setq repeat nil 
+            labels (delete-unreferenced-labels labels))
+      (dolist (l labels)
+        (let* ((succ (vinsn-label-succ l)))
+          (when (vinsn-label-p succ)
+            (backend-merge-labels l succ)
+            (setq repeat t)
+            (return)))))
+    (maximize-jumps header)
+    (delete-unreferenced-labels labels)
+    (normalize-vinsns header)
+  ))
+
+(defun show-vinsns (vinsns indent)
+  (do-dll-nodes (n vinsns)
+    (format t "~&~v@t~s" indent n)))
+
+(defun show-fgn (node)
+  (format t "~&~s (~d) {~a}" (type-of node) (fgn-id node) (mapcar #'fgn-id (fgn-inedges node)))
+  (show-vinsns node 2)
+  (terpri)
+  (terpri))
+
+(defun dfs-walk (fgns &key
+		      process-before process-after
+		      process-succ-before process-succ-after)
+  (labels ((dfs (node)
+	     (when process-before
+	       (funcall process-before node))
+	     (setf (fgn-visited node) t)
+	     (when (typep node 'jumpnode)
+	       (let* ((outedge (jumpnode-outedge node)))
+		 (unless (fgn-visited outedge)
+		   (when process-succ-before
+		     (funcall process-succ-before outedge))
+		   (dfs outedge)
+		   (when process-succ-after
+		     (funcall process-succ-after outedge))))
+	       (when (typep node 'condnode)
+		 (let* ((branchedge (branch-target-node
+				     (condnode-condbranch node))))
+		   (unless (fgn-visited branchedge)
+		     (when process-succ-before
+		       (funcall process-succ-before branchedge))
+		     (dfs branchedge)
+		     (when process-succ-after
+		       (funcall process-succ-after branchedge))))))
+	     (when process-after
+	       (funcall process-after node))))
+    (dolist (n fgns)
+      (setf (fgn-visited n) nil))
+    (dfs (car fgns))))
+
+(defun dfs-postorder (fgns)
+  (let* ((n (length fgns))
+	 (v (make-array n))
+	 (p -1)
+	 (process-after #'(lambda (node)
+			    (setf (svref v (incf p)) node))))
+    (declare (fixnum p) (dynamic-extent process-after))
+    (dfs-walk fgns :process-after process-after)
+    v))
+
+;;; This generally only gives a meaningful result if pass 2 of the
+;;; compiler has been compiled in the current session.
+;;; TODO (maybe): keep track of the "expected missing vinsns" for
+;;; each backend, call this function after compiling pass 2.  That's
+;;; a little weird, since it'd require modifying backend X whenever
+;;; backend Y changes, but it's probably better than blowing up when
+;;; compiling user code.
+(defun missing-vinsns (&optional (backend *target-backend*))
+  (let* ((missing ()))
+    (maphash #'(lambda (name info)
+                 (unless (cdr info)
+                   (push name missing)))
+             (backend-p2-vinsn-templates backend))
+    missing))
+		      
+(provide "VINSN")
Index: /branches/new-random/compiler/vreg.lisp
===================================================================
--- /branches/new-random/compiler/vreg.lisp	(revision 13309)
+++ /branches/new-random/compiler/vreg.lisp	(revision 13309)
@@ -0,0 +1,310 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(cl:eval-when (:compile-toplevel :load-toplevel :execute)
+  (ccl::require "ARCH"))
+
+(in-package "CCL")
+
+(defvar *logical-register-counter* -1)
+
+(def-standard-initial-binding *lreg-freelist* (%cons-pool))
+
+(defstruct (lreg
+            (:print-function print-lreg)
+            (:constructor %make-lreg))
+  (value nil :type t)                   ; physical reg or frame address or ...
+  (id (incf (the fixnum *logical-register-counter*)) :type fixnum)                   ; for printing
+  (class 0 :type fixnum)                ; target storage class: GPR, FPR, CRF ...
+  (mode 0 :type fixnum)                 ; mode (:u8, :address, etc)
+  (type 0 :type fixnum)                 ; type
+  (defs () :type list)                  ; list of vinsns which assign to this reg
+  (refs () :type list)                  ; list of vinsns which reference this vreg
+  (conflicts () :type list)             ; other lregs which can't map to the same physical reg
+  (wired t :type boolean)               ; when true, targeted value must be preserved.
+  (info nil)				; Whatever; used in printing.
+)
+
+(defun free-lreg (l)
+  (without-interrupts                   ; explicitly
+   (let* ((p *lreg-freelist*))
+     (setf (lreg-value l) (pool.data p)
+           (pool.data p) l)
+     nil)))
+
+(defun alloc-lreg ()
+  (let* ((p *lreg-freelist*))
+    (without-interrupts 
+     (let* ((l (pool.data p)))
+       (when l 
+         (setf (pool.data p) (lreg-value l))
+         (setf (lreg-defs l) nil
+               (lreg-refs l) nil
+               (lreg-conflicts l) nil
+               (lreg-id l) (incf *logical-register-counter*)
+               (lreg-wired l) t)
+         l)))))
+
+(defun make-lreg (value class mode type wired)
+  (let* ((l (alloc-lreg)))
+    (cond (l
+           (setf (lreg-value l) value
+                 (lreg-class l) class
+                 (lreg-type l) type
+                 (lreg-mode l) mode
+                 (lreg-wired l) wired)           
+           l)
+          (t (%make-lreg :value value :class class :type type :mode mode :wired wired)))))
+ 
+
+(defun print-lreg (l s d)
+  (declare (ignore d))
+  (print-unreadable-object (l s :type t)
+    (format s "~d" (lreg-id l))
+    (let* ((value (lreg-value l))
+           (class (lreg-class l))
+	   (mode-name (if (eq class hard-reg-class-gpr)
+			(car (rassoc (lreg-mode l) *mode-name-value-alist*)))))
+      (format s " ~a "
+              (case class
+                (#.hard-reg-class-fpr "FPR")
+                (#.hard-reg-class-gpr "GPR")
+                (#.hard-reg-class-crf "CRF")
+                (t  (format nil "class ~d" class))))
+      (if value
+        (format s (if (lreg-wired l) "[~s]" "{~s}") value)
+	(progn
+	  (if mode-name
+	    (format s "{?/~a}" mode-name)
+	    (format s "{?}")))))))
+
+(def-standard-initial-binding *lcell-freelist* (%cons-pool))
+(defvar *next-lcell-id* -1)
+
+(defstruct (lcell 
+            (:print-function print-lcell)
+            (:constructor %make-lcell (kind parent width attributes info)))
+  (kind :node)         ; for printing
+  (id (incf (the fixnum *next-lcell-id*)) :type fixnum)                          ; 
+  (parent nil)                          ; backpointer to unique parent
+  (children nil)                        ; list of children
+  (width 4)                             ; size in bytes or NIL if deleted
+  (offset nil)                          ; sum of ancestor's widths or 0, NIL if deleted
+  (refs nil)                            ; vinsns which load/store into this cell
+  (attributes 0 :type fixnum)           ; bitmask
+  (info nil))                           ; whatever
+
+(defun print-lcell (c s d)
+  (declare (ignore d))
+  (print-unreadable-object (c s :type t)
+    (format s "~d" (lcell-id c))
+    (let* ((offset (lcell-offset c)))
+      (when offset
+        (format s "@#x~x" offset)))))
+
+(defun free-lcell (c)
+  (without-interrupts                   ; explicitly
+   (let* ((p *lcell-freelist*))
+     (setf (lcell-kind c) (pool.data p)
+           (pool.data p) c)
+     nil)))
+
+(defun alloc-lcell (kind parent width attributes info)
+  (let* ((p *lcell-freelist*))
+    (without-interrupts 
+     (let* ((c (pool.data p)))
+       (when c 
+         (setf (pool.data p) (lcell-kind c))
+         (setf (lcell-kind c) kind
+               (lcell-parent c) parent
+               (lcell-width c) width
+               (lcell-attributes c) (the fixnum attributes)
+               (lcell-info c) info
+               (lcell-offset c) nil
+               (lcell-refs c) nil
+               (lcell-children c) nil
+               (lcell-id c) (incf *next-lcell-id*))
+         c)))))
+
+(defun make-lcell (kind parent width attributes info)
+  (let* ((c (or (alloc-lcell kind parent width attributes info)
+                (%make-lcell kind parent width attributes info))))
+    (when parent (push c (lcell-children parent)))
+    c))
+ 
+; Recursively calculate, but don't cache (or pay attention to previously calculated offsets) 
+(defun calc-lcell-offset (c)
+  (if c
+    (let* ((p (lcell-parent c)))
+      (if (null p)
+        0
+        (+ (calc-lcell-offset p) (or (lcell-width p) 0))))
+    0))
+
+; A cell's "depth" is its offset + its width
+(defun calc-lcell-depth (c)
+  (if c 
+    (+ (calc-lcell-offset c) (or (lcell-width c) 0))
+    0))
+
+; I don't know why "compute" means "memoize", but it does.
+(defun compute-lcell-offset (c)
+  (or (lcell-offset c)
+      (setf (lcell-offset c)
+            (let* ((p (lcell-parent c)))
+              (if (null p)
+                0
+                (+ (compute-lcell-offset p) (or (lcell-width p) 0)))))))
+
+(defun compute-lcell-depth (c)
+  (if c
+    (+ (compute-lcell-offset c) (or (lcell-width c) 0))
+    0))
+
+
+
+                    
+
+(defparameter *spec-class-storage-class-alist*
+  `((:lisp . ,arch::storage-class-lisp)
+    (:imm . ,arch::storage-class-imm)
+    (:wordptr . ,arch::storage-class-wordptr)
+    (:u8 . ,arch::storage-class-u8)
+    (:s8 . ,arch::storage-class-s8)
+    (:u16 . ,arch::storage-class-u16)
+    (:s16 . ,arch::storage-class-s16)
+    (:u32 . ,arch::storage-class-u32)
+    (:s32 . ,arch::storage-class-s32)
+    (:u64 . ,arch::storage-class-u64)
+    (:s64 . ,arch::storage-class-s64)
+    (:address . ,arch::storage-class-address)
+    (:single-float . ,arch::storage-class-single-float)
+    (:double-float . ,arch::storage-class-double-float)
+    (:pc . ,arch::storage-class-pc)
+    (:locative . ,arch::storage-class-locative)
+    (:crf . ,arch::storage-class-crf)
+    (:crbit . ,arch::storage-class-crbit)
+    (:crfbit . ,arch::storage-class-crfbit)   
+    (t . nil)))
+    
+(defun spec-class->storage-class (class-name)
+  (or (cdr (assoc class-name *spec-class-storage-class-alist* :test #'eq))
+      (error "Unknown storage-class specifier: ~s" class-name)))
+   
+(defun vreg-ok-for-storage-class (vreg sclass)
+  (declare (ignore vreg sclass))
+  t)
+
+
+
+(defparameter *vreg-specifier-constant-constraints*
+  `((:u8const . ,(specifier-type '(unsigned-byte 8)))
+    (:u16const . ,(specifier-type '(unsigned-byte 16)))
+    (:u32const . ,(specifier-type '(unsigned-byte 32)))
+    (:u64const . ,(specifier-type '(unsigned-byte 64)))
+    (:s8const . ,(specifier-type '(signed-byte 8)))
+    (:s16const . ,(specifier-type '(signed-byte 16)))
+    (:s32const . ,(specifier-type '(signed-byte 32)))
+    (:s64const . ,(specifier-type '(signed-byte 64)))
+    (:lcell . ,(specifier-type 'lcell))))
+
+(defun match-vreg-value (vreg value)
+  (declare (ignorable vreg value))      ; at least until this -does- something.
+  ;(format t "~&vreg = ~s, value = ~s" vreg value)
+  t)
+
+(defun match-vreg-constraint (constraint vreg template valvect n)
+  (let* ((res&args (vinsn-template-results&args template))
+         (target (cadr constraint))
+         (matchspec (assq target res&args))
+         (matchpos (if matchspec (position matchspec res&args))))
+    (unless matchpos
+      (warn "Unknown template vreg name ~s in constraint ~s." target constraint))
+    (unless (< matchpos n)
+      (warn "Forward-referenced vreg name ~s in constraint ~s." target constraint))
+    (let* ((target-val (svref valvect matchpos)))
+      (unless (ecase (car constraint) (:eq (eq vreg target-val)) (:ne (neq vreg target-val)))
+        (warn "~& use of vreg ~s conflicts with value already assigned ~
+               to ~s wrt constraint ~s ." vreg (car matchspec) constraint)))))
+
+(defun note-vinsn-sets-gpr (vinsn gpr)
+  (setf (vinsn-gprs-set vinsn) (logior (vinsn-gprs-set vinsn) (ash 1 gpr))))
+
+(defun note-vinsn-sets-fpr (vinsn fpr)
+  (setf (vinsn-fprs-set vinsn) (logior (vinsn-fprs-set vinsn) (ash 1 fpr))))
+
+(defun match-vreg (vreg spec vinsn vp n)
+  (declare (fixnum n))
+  (let* ((class (if (atom spec) spec (car spec)))
+         (value (if (atom spec) nil (cadr spec)))
+         (template (vinsn-template vinsn))
+         (result-p (< n (the fixnum (length (vinsn-template-result-vreg-specs template))))))
+    (let* ((spec-class (assoc class *spec-class-storage-class-alist* :test #'eq)))
+      (if spec-class
+        (let* ((vreg-value (hard-regspec-value vreg)))
+          (if (typep vreg 'fixnum) 
+            (setq vreg vreg-value)
+            (if (typep vreg 'lreg)
+              (if result-p
+                (pushnew vinsn (lreg-defs vreg))
+                (pushnew vinsn (lreg-refs vreg)))
+              (error "Bad vreg: ~s" vreg)))
+	  (when vreg-value
+	    (case class
+	      (:crf (use-crf-temp vreg-value))
+	      ((:u8 :s8 :u16 :s16 :u32 :s32 :u64 :s64 :address)
+	       (when result-p (note-vinsn-sets-gpr vinsn vreg-value))
+	       (use-imm-temp vreg-value))
+	      ((:single-float :double-float)
+	       (use-fp-temp vreg-value)
+	       (when result-p (note-vinsn-sets-fpr vinsn vreg-value)))
+	      ((:imm t)
+	       (when result-p (note-vinsn-sets-gpr vinsn vreg-value))
+	       (if (logbitp vreg-value *backend-imm-temps*)
+		 (use-imm-temp vreg-value)
+		 (use-node-temp vreg-value)))
+	      (:lisp
+	       (use-node-temp vreg-value)
+	       (when result-p (note-vinsn-sets-gpr vinsn vreg-value)))))
+          (unless (or (eq class 't) (vreg-ok-for-storage-class vreg class))
+            (warn "~s was expected to have storage class matching specifier ~s" vreg class))
+          (when value
+            (if (atom value)
+              (match-vreg-value vreg-value value)
+              (match-vreg-constraint value vreg-value template vp n))))
+        (if (eq class :label)
+          (progn
+            (unless (typep vreg 'vinsn-label)
+              (error "Label expected, found ~s." vreg))
+            (push vinsn (vinsn-label-refs vreg)))
+          (let* ((ctype (cdr (assoc class *vreg-specifier-constant-constraints* :test #'eq))))
+            (unless ctype (error "Unknown vreg constraint : ~s ." class))
+            (unless (ctypep vreg ctype)
+              (error "~S : value doesn't match constraint ~s in template for ~s ." vreg class (vinsn-template-name template)))))))
+    (when (typep vreg 'lcell)
+      (pushnew vinsn (lcell-refs vreg)))
+    vreg))
+
+(defun note-lreg-conflict (lreg conflicts-with)
+  (and (typep lreg 'lreg)
+       (typep conflicts-with 'lreg)
+       (pushnew conflicts-with (lreg-conflicts lreg))
+       (pushnew lreg (lreg-conflicts conflicts-with))
+       t))
+
+(ccl::provide "VREG")
Index: /branches/new-random/contrib/README
===================================================================
--- /branches/new-random/contrib/README	(revision 13309)
+++ /branches/new-random/contrib/README	(revision 13309)
@@ -0,0 +1,7 @@
+This directory contains source code contributed by users.  It
+is on the module search path, so files here can be loaded using
+REQUIRE.
+
+If you are interested in contributing source code here and don't
+have write access to the CCL repository, send a note to
+ccl-devel@clozure.com.
Index: /branches/new-random/contrib/baylis/ca-demo.lisp
===================================================================
--- /branches/new-random/contrib/baylis/ca-demo.lisp	(revision 13309)
+++ /branches/new-random/contrib/baylis/ca-demo.lisp	(revision 13309)
@@ -0,0 +1,136 @@
+;;
+;; Core Animation Demo
+;;
+;; Author: Neil Baylis
+;;
+;; neil.baylis@gmail.com
+;;
+;; usage:
+;;   1. start a 64 bit version of ccl
+;;   2. (load "path to ca-demo.lisp on your system")
+;;   3. (run-demo "absolute path to small image file on your system")
+;;
+;; Click in the window, and the image will move smoothly to the mouse point.
+;; Pressing any key will toggle full-screen mode
+;;
+;; This demo is meant purely to illustrate various objc bridge constructs
+;; as well as minimal steps to make Core Animation do something.
+;;
+(in-package "CL-USER")
+
+(require :cocoa)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (objc:load-framework "Quartz" :quartz))
+
+(defun nsstr (s) (make-instance 'gui::ns-lisp-string :string s))
+
+(defparameter +standard-window-style-mask+
+  (logior #$NSTitledWindowMask
+          #$NSClosableWindowMask
+          #$NSMiniaturizableWindowMask
+          #$NSResizableWindowMask))
+
+(defun make-ns-window (x y &optional (title "Untitled"))
+  (let ((nsw (make-instance 'ns:ns-window
+               :with-content-rect (ns:make-ns-rect 0 0 x y)
+               :style-mask +standard-window-style-mask+
+               :backing #$NSBackingStoreBuffered
+               :defer t)))
+    (#/setTitle: nsw (nsstr title))
+    (#/setBackgroundColor:
+     nsw
+     (#/colorWithDeviceRed:green:blue:alpha: ns:ns-color 0.95 1.0 0.95 1.0 ))
+    (#/center nsw)
+    (#/makeKeyAndOrderFront: nsw nil)
+    nsw))
+
+(defmacro with-focused-view (view &body forms)
+  `(when (#/lockFocusIfCanDraw ,view)
+     (unwind-protect (progn ,@forms)
+       (#/unlockFocus ,view)
+       (#/flushGraphics (#/currentContext ns:ns-graphics-context))
+       (#/flushWindow (#/window ,view)))))
+
+(defclass ca-demo-view (ns:ns-view)
+  ((path :initform (make-instance ns:ns-bezier-path)))
+  (:metaclass ns:+ns-object))
+
+(defvar sprite)
+
+(defun set-layer-position (layer point)
+  (let* ((pos
+	  (make-record
+	   :<CGP>oint x (ns:ns-point-x point) y (ns:ns-point-y point))))
+    (#/removeAllAnimations layer)
+    (#/setPosition: layer pos)
+    (free pos)))
+
+(ccl::define-objc-method ((:void :mouse-down (:id event)) ca-demo-view)
+    (let* ((event-location (#/locationInWindow event))
+	   (view-location (#/convertPoint:fromView: self event-location nil)))
+      (set-layer-position sprite view-location)))
+
+(ccl::define-objc-method ((:void :mouse-dragged (:id event)) ca-demo-view)
+    (let* ((event-location (#/locationInWindow event))
+	   (view-location (#/convertPoint:fromView: self event-location nil)))
+      (set-layer-position sprite view-location)))
+
+(ccl::define-objc-method ((:void :key-down (:id event)) ca-demo-view)
+    (declare (ignore event))
+    (if (#/isInFullScreenMode self)
+	(#/exitFullScreenModeWithOptions: self #$nil)
+	(#/enterFullScreenMode:withOptions: self (#/mainScreen ns:ns-screen) #$nil)))
+
+(ccl::define-objc-method ((:<BOOL> accepts-first-responder) ca-demo-view) #$YES)
+
+(defun set-layer-bounds (layer rect)
+  (let* ((o (make-record :<CGP>oint
+			 x (ns:ns-rect-x rect)
+			 y (ns:ns-rect-y rect)))
+	 (s (make-record :<CGS>ize
+			 width (ns:ns-rect-width rect)
+			 height (ns:ns-rect-height rect)))
+	 (bounds (make-record :<CGR>ect origin o size s)))
+    (#/setBounds: layer bounds)
+    (free bounds)
+    (free s)
+    (free o)))
+
+(defun make-ca-layer (filename)
+  (let* ((layer (#/init (make-instance 'ns:ca-layer)))
+	 (ns-img (make-instance ns:ns-image :init-with-contents-of-file (nsstr filename)))
+	 (s (#/size ns-img))
+	 (repr (#/TIFFRepresentation ns-img))
+	 (sr (#_CGImageSourceCreateWithData repr CCL:+NULL-PTR+))
+	 (ir (#_CGImageSourceCreateImageAtIndex sr 0 CCL:+NULL-PTR+))
+	 )
+    (#/setName: layer (nsstr "sprite"))
+    (#/setContents: layer ir)
+    (set-layer-bounds layer (ns:make-ns-rect 0 0 (pref s :ns-size.width) (pref s :ns-size.height)))
+    (#/release ns-img)
+    (#_CFRelease sr)
+    (#_CGImageRelease ir)
+    layer))
+
+(defun add-layer-to-view (view layer)
+  (#/setDelegate: layer view)
+  (#/addSublayer: (#/layer view) sprite))
+
+;
+; e.g. (run-demo "/foo/bar/my-image.jpg")
+;
+; Make a window.
+; Make a view
+; Tell the view that it needs a CA Backing layer
+; Make a CALayer using the content of the supplied image 
+; Add the newly created layer to the view
+; Add the newly created view to the window
+;
+(defun run-demo (filename)
+  (let ((w (make-ns-window 900 600 "CA Demo"))
+        (v (make-instance 'ca-demo-view)))
+    (#/setWantsLayer: v #$YES)
+    (setf sprite (make-ca-layer filename))
+    (add-layer-to-view v sprite)
+    (#/setContentView: w v)))
Index: /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation-2.lisp
===================================================================
--- /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation-2.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation-2.lisp	(revision 13309)
@@ -0,0 +1,107 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      cl-documentation-2.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds an alphabetical index of :CL commands to the Context-Menu 
+;;;      mechanism.  Command-Right-Click displays a list of letter submenus.
+;;;      Popping the submenu displays entries for all Hemlock Commands starting with
+;;;      that letter.  Selecting an entry opens a documentation dialog.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "CL-DOCUMENTATION") 
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass CL-ALPHABETICAL-MENU-ITEM (ns:ns-menu-item)
+  ((symbol :initarg :symbol :accessor item-symbol))
+  (:documentation "Support for the CL alphabetical menu.")
+  (:metaclass ns:+ns-object))
+
+(defun populate-submenu (menu symbol-list)
+  "Make menu-items for all symbols in SYMBOL-LIST, and add them to MENU"
+  (dolist (symbol (reverse symbol-list))
+    (let* ((menu-item (make-instance 'cl-alphabetical-menu-item :symbol symbol))
+           (attributed-string (#/initWithString:attributes:
+                               (#/alloc ns:ns-attributed-string) 
+                               (ccl::%make-nsstring (string-downcase (string symbol)))
+                               cmenu:*hemlock-menu-dictionary*)))
+;      (setf (item-symbol menu-item) symbol)
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setAction: menu-item (ccl::@selector "clAlphabeticalDocAction:"))
+      (#/setTarget: menu-item  *cl-alphabetical-menu*)
+      (#/addItem: menu menu-item))))
+
+(defun make-submenu-item (title symbol-list)
+  "Create a menu-item with a submenu, and populate the submenu with the symbols in SYMBOL-LIST."
+  (let ((menu-item (make-instance ns:ns-menu-item))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (ccl::%make-nsstring title)
+                            cmenu:*hemlock-menu-dictionary*))
+        (submenu (make-instance ns:ns-menu)))
+    (#/setAttributedTitle: menu-item attributed-string)
+    (#/setSubmenu: menu-item submenu)
+    (populate-submenu submenu symbol-list)
+    menu-item))
+
+(defparameter *ABCs* "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass CL-ALPHABETICAL-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (text-view :initform nil :accessor text-view)
+   (sub-title :initform "alphabetical" :reader sub-title))
+  (:documentation "A popup menu with alphabetically ordered letter submenus.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/clAlphabeticalDocAction: :void) ((m cl-alphabetical-menu) (sender :id))
+  (display-cl-doc (item-symbol sender) (text-view m)))
+
+(defmethod initialize-instance :after ((menu cl-alphabetical-menu) &key)
+  (setf (tool-menu menu) (cmenu:add-default-tool-menu menu)))
+
+(defmethod add-submenus ((menu cl-alphabetical-menu))
+  (let* ((letter-array-length (length *ABCs*))
+         (letter-array (make-array letter-array-length :initial-element nil))
+         miscellaneous first-letter index)
+    (dolist (sym (remove-duplicates (apply #'append *cl-symbol-lists*) :test #'eq))
+      (setq first-letter (elt (string sym) 0))
+      (setq index (position first-letter *ABCs* :test #'char-equal))
+      (if index
+        (push sym (aref letter-array index))
+        (push sym miscellaneous)))
+    (dotimes (idx letter-array-length)
+      (let ((submenu-item (make-submenu-item (elt *ABCs* idx) 
+                                             (sort (coerce (aref letter-array idx) 'list)
+                                                   #'string> :key #'string))))
+        (#/addItem: menu submenu-item)))
+    (when miscellaneous
+      (#/addItem: menu (#/separatorItem ns:ns-menu-item))    
+      (let ((submenu-item (make-submenu-item "Other:" miscellaneous)))
+        (#/addItem: menu submenu-item)))))
+
+(objc:defmethod (#/update :void) ((self cl-alphabetical-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(setq *cl-alphabetical-menu* (make-instance 'cl-alphabetical-menu))
+
+(add-submenus *cl-alphabetical-menu*)
+
+
+
+
Index: /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation-cm.lisp
===================================================================
--- /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation-cm.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation-cm.lisp	(revision 13309)
@@ -0,0 +1,22 @@
+
+;;; cl-documentation.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "CL-DOCUMENTATION-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *cl-documentation-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *cl-documentation-files* 
+    (list (merge-pathnames ";cl-documentation.lisp" *cl-documentation-directory*)
+          (merge-pathnames ";cl-documentation-2.lisp" *cl-documentation-directory*))))
+ 
+(dolist (file *cl-documentation-files*)
+  (load file))
+
+(provide :cl-documentation-cm)
+
+)
Index: /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation.lisp
===================================================================
--- /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/cl-documentation-cm/cl-documentation.lisp	(revision 13309)
@@ -0,0 +1,472 @@
+;;;-*-Mode: LISP; Package: CL-DOCUMENTATION -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      cl-documentation.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code is moronically simple, but surprisingly useful.
+;;;      It adds a documentation tool for CL functions to the Context-Menu mechanism.
+;;;      Right-Click displays a list of submenus.  The submenus are functional groups.
+;;;      Popping the submenu displays entries for all CL functions belonging to that
+;;;      functional group.  Selecting a function open a documentation dialog.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Added a second menu, providing an alphabetical index.
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "CL-DOCUMENTATION" (:nicknames "CLDOC") (:use :cl :ccl))
+(in-package "CL-DOCUMENTATION")
+
+(require :context-menu-cm)
+(cmenu:check-hyperspec-availability "CL-Documentation-CM")
+
+(defparameter *cl-documentation-menu* nil "The cl-documentation-menu instance.")
+(defparameter *cl-alphabetical-menu* nil "The cl-alphabetical-menu instance.")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass CL-DOCUMENTATION-MENU (ns:ns-menu) 
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "functional groups" :reader sub-title)
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*cl-documentation-directory*) :reader doc-path)
+   (text-view :initform nil :accessor text-view))
+  (:documentation "A menu containing CL functions sorted into functional groups.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/clDocumentationAction: :void) ((m cl-documentation-menu) (sender :id))
+  (display-cl-doc (item-symbol sender) (text-view m)))
+
+(objc:defmethod (#/update :void) ((m cl-documentation-menu))
+  (cmenu:update-tool-menu m (tool-menu m) :sub-title (sub-title m))
+  (call-next-method))
+
+(defmethod initialize-instance :after ((m cl-documentation-menu) &key)
+  (setf (tool-menu m) (cmenu:add-default-tool-menu m :doc-file (doc-path m))))
+
+(defun display-cl-doc (symbol text-view)
+  "Display the documentation for SYMBOL."
+  ;; If Hemlock-Commands is loaded, this will be
+  ;; redefined there to use the documentation dialog.
+  (gui::lookup-hyperspec-symbol symbol text-view))
+
+(setq *cl-documentation-menu* (make-instance 'cl-documentation-menu))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass CL-CATEGORY-MENU-ITEM (ns:ns-menu-item) 
+  ((symbol :initform nil :accessor item-symbol))
+  (:documentation "Support for the documentation menu.")
+  (:metaclass ns:+ns-object))
+
+(defun populate-submenu (menu symbol-list)
+  "Create and add menu-items for each functional group in SYMBOL-LIST."
+  (dolist (sym symbol-list)
+    (let ((menu-item (make-instance 'cl-category-menu-item))
+          (attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string) 
+                              (ccl::%make-nsstring (string-downcase (string sym)))
+                              cmenu:*hemlock-menu-dictionary*)))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setAction: menu-item (ccl::@selector "clDocumentationAction:"))
+      (#/setTarget: menu-item  *cl-documentation-menu*)
+      (setf (item-symbol menu-item) sym)
+      (#/addItem: menu menu-item))))
+
+(defun make-submenu-item (title symbol-list)
+  "Create a menu-item with a submenu and populate the submenu based on SYMBOL-LIST."
+  (let ((menu-item (make-instance ns:ns-menu-item))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (ccl::%make-nsstring title)
+                            cmenu:*hemlock-menu-dictionary*))
+        (submenu (make-instance ns:ns-menu)))
+    (#/setAttributedTitle: menu-item attributed-string)
+    (#/setSubmenu: menu-item submenu)
+    (populate-submenu submenu symbol-list)
+    menu-item))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *evaluation-and-compilation-symbol-list*
+  (list 'compile 'compiler-macro-function 'constantp 'declaim 'declare 'define-compiler-macro 
+        'define-symbol-macro 'defmacro 'eval 'eval-when 'lambda 'load-time-value 'locally 
+        'macroexpand 'macroexpand-1 'macro-function 'proclaim 'special-operator-p 'symbol-macrolet
+        'the 'quote))
+
+(defParameter *evaluation-and-compilation*
+  (make-submenu-item "evaluation and compilation" *evaluation-and-compilation-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *types-and-classes-symbol-list*
+  (list 'coerce 'deftype 'subtypep 'type-error-datum 'type-error-expected-type 'type-of 'typep))
+
+(defParameter *types-and-classes*
+  (make-submenu-item "types and classes" *types-and-classes-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *control-and-data-flow-symbol-list*
+  (list 'and 'apply 'block 'case 'catch 'ccase 'compiled-function-p 'complement 'cond 
+        'constantly 'ctypecase 'defconstant 'define-modify-macro 'define-setf-expander 
+        'defparameter 'defsetf 'defun 'defvar 'destructuring-bind 'ecase 'eq 'eql 'equal 'equalp 
+        'etypecase 'every 'fboundp 'fdefinition 'flet 'fmakunbound 'funcall 'function 
+        'function-lambda-expression 'functionp 'labels 'get-setf-expansion 'go 'identity 'if 
+        'let 'let* 'macrolet 'multiple-value-bind 'multiple-value-call 'multiple-value-list 
+        'multiple-value-prog1 'multiple-value-setq 'not 'notany 'notevery 'nth-value 'or 'prog 
+        'prog* 'prog1 'prog2 'progn 'progv 'psetf 'psetq 'return 'return-from 'rotatef 'setf 
+        'setq 'shiftf 'some 'tagbody 'throw 'typecase 'unless 'unwind-protect 'values 
+        'values-list 'when))
+
+(defParameter *control-and-data-flow*
+  (make-submenu-item "control and data flow" *control-and-data-flow-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *iteration-symbol-list*
+  (list 'do 'do* 'dolist 'dotimes 'loop))
+
+(defParameter *iteration*
+  (make-submenu-item "iteration" *iteration-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *objects-symbol-list*
+  (list 'add-method 'allocate-instance 'call-method 'call-next-method 'change-class 'class-name 
+        'class-of 'compute-applicable-methods 'defclass 'defgeneric 'define-method-combination 
+        'defmethod 'ensure-generic-function 'find-class 'find-method 'function-keywords 
+        'initialize-instance 'make-instance 'make-instances-obsolete 'make-load-form 
+        'make-load-form-saving-slots 'method-qualifiers 'next-method-p 'no-applicable-method 
+        'no-next-method 'reinitialize-instance 'remove-method 'shared-initialize 'slot-boundp 
+        'slot-exists-p 'slot-makunbound 'slot-missing 'slot-unbound 'slot-value 'with-accessors 
+        'with-slots 'unbound-slot-instance 'update-instance-for-different-class 
+        'update-instance-for-redefined-class))
+
+(defParameter *objects*
+  (make-submenu-item "objects" *objects-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *structures-symbol-list*
+  (list 'copy-structure 'defstruct))
+
+(defParameter *structures*
+  (make-submenu-item "structures" *structures-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *conditions-symbol-list*
+  (list 'abort 'assert 'break 'cell-error-name 'cerror 'check-type 'compute-restarts 'continue 
+        'define-condition 'error 'find-restart 'handler-bind 'handler-case 'ignore-errors 
+        'invalid-method-error 'invoke-debugger 'invoke-restart 'invoke-restart-interactively 
+        'make-condition 'method-combination-error 'muffle-warning 'restart-bind 'restart-case 
+        'restart-name 'signal 'simple-condition-format-arguments 'simple-condition-format-control 
+        'store-value 'use-value 'warn 'with-condition-restarts 'with-simple-restart))
+
+(defParameter *conditions*
+  (make-submenu-item "conditions" *conditions-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *symbols-symbol-list*
+  (list 'boundp 'copy-symbol 'gensym 'gentemp 'get 'keywordp 'make-symbol 'makunbound 'set 
+        'symbol-function 'symbol-name 'symbolp 'symbol-package 'symbol-plist 'symbol-value 
+        'remprop))
+
+(defParameter *symbols*
+  (make-submenu-item "symbols" *symbols-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *packages-symbol-list*
+  (list 'defpackage 'delete-package 'do-all-symbols 'do-external-symbols 'do-symbols 'export 
+        'find-all-symbols 'find-package 'find-symbol 'import 'in-package 'intern 
+        'list-all-packages 'make-package 'package-error-package 'package-name 'package-nicknames 
+        'packagep 'package-shadowing-symbols 'package-used-by-list 'package-use-list 
+        'rename-package 'shadow 'shadowing-import 'unexport 'unintern 'unuse-package 
+        'with-package-iterator))
+
+(defParameter *packages*
+  (make-submenu-item "packages" *packages-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *numbers-symbol-list*
+  (list 'abs 'acos 'acosh 'arithmetic-error-operands 'arithmetic-error-operation 'ash 'asin 
+        'asinh 'atan 'atanh 'boole 'byte 'byte-position 'byte-size 'ceiling 'cis 'complex 
+        'complexp 'conjugate 'cos 'cosh 'decf 'decode-float 'denominator 'deposit-field 'dpb 
+        'evenp 'exp 'expt 'fceiling 'ffloor 'float 'float-digits 'floatp 'float-precision 
+        'float-radix 'float-sign 'floor 'fround 'ftruncate 'gcd 'imagpart 'incf 
+        'integer-decode-float 'integer-length 'integerp 'isqrt 'lcm 'ldb 'ldb-test 'log 'logand 
+        'logandc1 'logandc2 'logbitp 'logcount 'logeqv 'logior 'lognand 'lognor 'lognot 'logorc1 
+        'logorc2 'logtest 'logxor 'make-random-state 'mask-field 'max 'min 'minusp 'mod 'numberp 
+        'numerator 'oddp 'parse-integer 'phase 'plusp 'random 'random-state-p 'rational 
+        'rationalize 'rationalp 'realp 'realpart 'rem 'round 'scale-float 'signum 'sin 'sinh 
+        'sqrt 'tan 'tanh 'truncate 'upgraded-complex-part-type 'zerop '= '/= '> '< '<= '>= '* 
+        '+ '- '/ '1+ '1- ))
+
+(defParameter *numbers*
+  (make-submenu-item "numbers" *numbers-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *characters-symbol-list*
+  (list 'alpha-char-p 'both-case-p 'alphanumericp 'character 'characterp 'char-code 
+        'char-downcase 'char-greaterp 'char-equal 'char-int 'char-lessp 'char-name 
+        'char-not-greaterp 'char-not-equal 'char-not-lessp 'char-upcase 'char= 'char/= 
+        'char> 'char< 'char<= 'char>= 'code-char 'digit-char 'digit-char-p 'graphic-char-p 
+        'lower-case-p 'name-char 'standard-char-p 'upper-case-p))
+
+(defParameter *characters*
+  (make-submenu-item "characters" *characters-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *conses-symbol-list*
+  (list 'acons 'adjoin 'append 'assoc 'assoc-if 'assoc-if-not 'atom 'butlast 'nbutlast 'car 'cdr 
+        'cons 'consp 'copy-alist 'copy-list 'copy-tree 'endp 'first 'getf 'get-properties 
+        'intersection 'nintersection 'last 'ldiff 'list 'list-length 'listp 'make-list 'mapc 
+        'mapcan 'mapcar 'mapcon 'mapl 'maplist 'member 'member-if 'member-if-not 'nconc 'nth 
+        'nthcdr 'null 'pairlis 'pop 'push 'pushnew 'rassoc 'rassoc-if 'rassoc-if-not 'remf 'rest 
+        'revappend 'nreconc 'rplaca 'rplacd 'set-difference 'nset-difference 'set-exclusive-or 
+        'nset-exclusive-or 'sublis 'nsublis 'subsetp 'subst 'nsubst 'subst-if 'nsubst-if 
+        'subst-if-not 'nsubst-if-not 'tailp 'tree-equal 'union 'nunion))
+
+(defParameter *conses*
+  (make-submenu-item "conses" *conses-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *arrays-symbol-list*
+  (list  'adjustable-array-p 'adjust-array 'aref 'array-dimension 'array-dimensions  
+         'array-displacement 'array-element-type 'array-has-fill-pointer-p 'array-in-bounds-p  
+         'arrayp 'array-rank 'array-row-major-index 'array-total-size 'bit 'bit-and 'bit-andc1  
+         'bit-andc2 'bit-eqv 'bit-ior 'bit-nand 'bit-nor 'bit-not 'bit-orc1 'bit-orc2 'bit-xor  
+         'bit-vector-p 'fill-pointer 'make-array 'row-major-aref 'sbit 'simple-bit-vector-p  
+         'simple-vector-p 'svref 'upgraded-array-element-type 'vector 'vectorp 'vector-pop  
+         'vector-push 'vector-push-extend))
+
+(defParameter *arrays*
+  (make-submenu-item "arrays" *arrays-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *strings-symbol-list*
+  (list 'char 'make-string 'schar 'simple-string-p 'string 'string-capitalize 'nstring-capitalize 
+        'string-downcase 'nstring-downcase 'string-equal 'string-greaterp 'string-upcase 
+        'nstring-upcase 'string-left-trim 'string-lessp 'string-not-equal 'string-not-greaterp 
+        'string-not-lessp 'stringp 'string-right-trim 'string-trim 'string= 'string/= 'string< 
+        'string> 'string<= 'string>=))
+
+(defParameter *strings*
+  (make-submenu-item "strings" *strings-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *sequences-symbol-list*
+  (list 'concatenate 'copy-seq 'count 'count-if 'elt 'fill 'find 'find-if 'find-if-not 'length 
+        'make-sequence 'map 'map-into 'merge 'mismatch 'position 'position-if 'position-if-not 
+        'reduce 'remove 'delete 'remove-duplicates 'delete-duplicates 'remove-if 'delete-if 
+        'remove-if-not 'delete-if-not 'replace 'reverse 'nreverse 'search 'sort 'stable-sort 
+        'subseq 'substitute 'nsubstitute 'substitute-if 'nsubstitute-if 'substitute-if-not 
+        'nsubstitute-if-not))
+
+(defParameter *sequences*
+  (make-submenu-item "sequences" *sequences-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *hash-tables-symbol-list*
+  (list 'clrhash 'gethash 'hash-table-count 'hash-table-p 'hash-table-rehash-size 'hash-table-rehash-threshold 'hash-table-size 'hash-table-test 'make-hash-table 'maphash 'remhash 'sxhash 'with-hash-table-iterator))
+
+(defParameter *hash-tables*
+  (make-submenu-item "hash tables" *hash-tables-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *filenames-symbol-list*
+  (list 'directory-namestring 'enough-namestring 'file-namestring 'host-namestring 
+        'load-logical-pathname-translations 'logical-pathname 'logical-pathname-translations 
+        'make-pathname 'merge-pathnames 'namestring 'parse-namestring 'pathname 'pathname-host 
+        'pathname-device 'pathname-directory 'pathname-match-p 'pathname-name 'pathnamep 
+        'pathname-type 'pathname-version 'translate-logical-pathname 'translate-pathname 
+        'wild-pathname-p))
+
+(defParameter *filenames*
+  (make-submenu-item "filenames" *filenames-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *files-symbol-list*
+  (list 'delete-file 'directory 'ensure-directories-exist 'file-author 'file-error-pathname 
+        'file-write-date 'probe-file 'rename-file 'truename))
+
+(defParameter *files*
+  (make-submenu-item "files" *files-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *streams-symbol-list*
+  (list 'broadcast-stream-streams 'clear-input 'clear-output 'close 'concatenated-stream-streams 
+        'echo-stream-input-stream 'echo-stream-output-stream 'file-length 'file-position 
+        'file-string-length 'finish-output 'force-output 'fresh-line 'get-output-stream-string 
+        'input-stream-p 'interactive-stream-p 'listen 'make-broadcast-stream 
+        'make-concatenated-stream 'make-echo-stream 'make-string-input-stream 
+        'make-string-output-stream 'make-synonym-stream 'make-two-way-stream 'open 
+        'open-stream-p 'output-stream-p 'peek-char 'read-byte 'read-char 'read-char-no-hang 
+        'read-line 'read-sequence 'stream-element-type 'stream-error-stream 
+        'stream-external-format 'streamp 'synonym-stream-symbol 'terpri 
+        'two-way-stream-input-stream 'two-way-stream-output-stream 'unread-char 
+        'with-input-from-string 'with-open-file 'with-open-stream 'with-output-to-string 
+        'write-byte 'write-char 'write-line 'write-sequence 'write-string 'yes-or-no-p 'y-or-n-p))
+
+(defParameter *streams*
+  (make-submenu-item "streams" *streams-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *printer-symbol-list*
+  (list 'copy-pprint-dispatch 'format 'formatter 'pprint 'pprint-dispatch 
+        'pprint-exit-if-list-exhausted 'pprint-fill 'pprint-indent 'pprint-linear 
+        'pprint-logical-block 'pprint-newline 'pprint-pop 'pprint-tab 'pprint-tabular 'princ 
+        'princ-to-string 'print 'print-object 'print-not-readable-object 'print-unreadable-object 
+        'prin1 'prin1-to-string 'set-pprint-dispatch 'write 'write-to-string))
+
+(defParameter *printer*
+  (make-submenu-item "printer" *printer-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *reader-symbol-list*
+  (list 'copy-readtable 'get-dispatch-macro-character 'get-macro-character 
+        'make-dispatch-macro-character 'read 'read-delimited-list 'read-from-string 
+        'read-preserving-whitespace 'readtable-case 'readtablep 'set-dispatch-macro-character 
+        'set-macro-character 'set-syntax-from-char 'with-standard-io-syntax))
+
+(defParameter *reader*
+  (make-submenu-item "reader" *reader-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *system-construction-symbol-list*
+  (list 'copy-readtable 'get-dispatch-macro-character 'get-macro-character 
+        'make-dispatch-macro-character 'read 'read-delimited-list 'read-from-string 
+        'read-preserving-whitespace 'readtable-case 'readtablep 'set-dispatch-macro-character 
+        'set-macro-character 'set-syntax-from-char 'with-standard-io-syntax))
+
+(defParameter *system-construction*
+  (make-submenu-item "system construction" *system-construction-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *environment-symbol-list*
+  (list 'apropos 'apropos-list 'decode-universal-time 'describe 'describe-object 'disassemble 
+        'documentation 'dribble 'ed 'encode-universal-time 'get-decoded-time 
+        'get-internal-real-time 'get-internal-run-time 'get-universal-time 'inspect 
+        'lisp-implementation-type 'lisp-implementation-version 'long-site-name 'machine-instance 
+        'machine-type 'machine-version 'room 'short-site-name 'sleep 'software-type 
+        'software-version 'step 'time 'trace 'untrace 'user-homedir-pathname))
+
+(defParameter *environment*
+  (make-submenu-item "environment" *environment-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *constants-and-variables-symbol-list*
+  (list 'array-dimension-limit 'array-rank-limit 'array-total-size 'boole-1 '*break-on-signals* 
+        'call-arguments-limit 'char-code-limit '*compile-file-pathname* '*compile-file-truename* 
+        '*compile-print* '*compile-verbose* '*debug-io* '*debugger-hook* 
+        '*default-pathname-defaults* 'short-float-epsilon 'single-float-epsilon 
+        'double-float-epsilon 'long-float-epsilon 'short-float-negative-epsilon 
+        'single-float-negative-epsilon 'double-float-negative-epsilon 
+        'long-float-negative-epsilon '*error-output* '*features* '*gensym-counter* 
+        'internal-time-units-per-second 'lambda-list-keywords 'lambda-parameters-limit 
+        'least-negative-short-float 'least-negative-single-float 'least-negative-double-float 
+        'least-negative-long-float 'least-negative-normalized-short-float 
+        'least-negative-normalized-single-float 'least-negative-normalized-double-float 
+        'least-negative-normalized-long-float 'least-positive-short-float 
+        'least-positive-single-float 'least-positive-double-float 'least-positive-long-float
+        'least-positive-normalized-short-float 'least-positive-normalized-single-float 
+        'least-positive-normalized-double-float 'least-positive-normalized-long-float
+        '*load-pathname* '*load-print* '*load-truename* '*load-verbose* '*macroexpand-hook* 
+        '*modules* 'most-negative-fixnum 'most-negative-short-float 'most-negative-single-float 
+        'most-negative-double-float 'most-negative-long-float 'most-positive-fixnum
+        'most-positive-short-float 'most-positive-single-float 'most-positive-double-float 
+        'most-positive-long-float 'multiple-values-limit 'nil '*package* 'pi '*print-array* 
+        '*print-base* '*print-case* '*print-circle* '*print-escape* '*print-gensym* 
+        '*print-length* '*print-level* '*print-lines* '*print-miser-width* 
+        '*print-pprint-dispatch* '*print-pretty* '*print-radix* '*print-readably* 
+        '*print-right-margin* '*query-io* '*random-state* '*read-base* 
+        '*read-default-float-format* '*read-eval* '*read-suppress* '*readtable* 
+        '*standard-input* '*standard-output* 't '*terminal-io* '*trace-output* 
+        '* '** '*** '+ '++ '+++ '- '/ '// '///))
+
+(defParameter *constants-and-variables*
+  (make-submenu-item "constants and variables" *constants-and-variables-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *type-specifiers-symbol-list*
+  (list 'and 'array 'simple-array 'base-string 'simple-base-string 'bit-vector 'simple-bit-vector 
+        'complex 'cons 'eql 'float 'short-float 'single-float 'double-float 'long-float 'function 
+        'integer 'member 'mod 'not 'or 'rational 'real 'satisfies 'signed-byte 'string 
+        'simple-string 'unsigned-byte 'values 'vector 'simple-vector))
+
+(defParameter *type-specifiers*
+  (make-submenu-item "type specifiers" *type-specifiers-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defun add-cl-documentation-submenus (menu)
+  (let ((submenus '(*evaluation-and-compilation* *types-and-classes* 
+                                                 *control-and-data-flow* *iteration* *objects* *structures* 
+                                                 *conditions* *symbols* *packages* *numbers* *characters* 
+                                                 *conses* *arrays* *strings* *sequences* *hash-tables* 
+                                                 *filenames* *files* *streams* *printer* *reader* 
+                                                 *system-construction* *environment* *constants-and-variables* 
+                                                 *type-specifiers*)))
+    (dolist (submenu submenus)
+      (#/addItem: menu (symbol-value submenu)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *cl-symbol-lists*
+  (list 
+   *evaluation-and-compilation-symbol-list* *types-and-classes-symbol-list* 
+   *control-and-data-flow-symbol-list* *iteration-symbol-list* *objects-symbol-list* 
+   *structures-symbol-list* *conditions-symbol-list* *symbols-symbol-list* *packages-symbol-list* 
+   *numbers-symbol-list* *characters-symbol-list* *conses-symbol-list* *arrays-symbol-list* 
+   *strings-symbol-list* *sequences-symbol-list* *hash-tables-symbol-list* *filenames-symbol-list* 
+   *files-symbol-list* *streams-symbol-list* *printer-symbol-list* *reader-symbol-list* 
+   *system-construction-symbol-list* *environment-symbol-list* 
+   *constants-and-variables-symbol-list* *type-specifiers-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defun test-symbol-list (sym-list &optional package)
+  (dolist (sym (rest sym-list))
+    (unless (find-symbol (string-upcase (format nil "~A" sym)) (or package :cl))
+      (format t "~%~A" sym))))
+
+;;; (dolist (list *cl-symbol-lists*) (test-symbol-list list)) 
+
+(add-cl-documentation-submenus *cl-documentation-menu*)
+
+(defun get-cl-documentation-menu (view event) 
+  (cond ((logtest #$NSCommandKeyMask (#/modifierFlags event))
+         (setf (text-view *cl-alphabetical-menu*) view)           
+         *cl-alphabetical-menu*)
+        (t
+         (setf (text-view *cl-documentation-menu*) view)           
+         *cl-documentation-menu*)))
+
+(cmenu:register-tool "CL-Documentation-CM" #'get-cl-documentation-menu)
Index: /branches/new-random/contrib/foy/context-menu-cm/context-menu-cm.lisp
===================================================================
--- /branches/new-random/contrib/foy/context-menu-cm/context-menu-cm.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/context-menu-cm/context-menu-cm.lisp	(revision 13309)
@@ -0,0 +1,22 @@
+
+;;; context-menu-cm.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "CONTEXT-MENU-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *context-menu-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *context-menu-files* 
+    (list (merge-pathnames ";context-menu.lisp" *context-menu-directory*)
+          (merge-pathnames ";context-menu-dialogs.lisp" *context-menu-directory*))))
+ 
+(dolist (file *context-menu-files*)
+  (load file))
+
+(provide :context-menu-cm)
+
+)
Index: /branches/new-random/contrib/foy/context-menu-cm/context-menu-dialogs.lisp
===================================================================
--- /branches/new-random/contrib/foy/context-menu-cm/context-menu-dialogs.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/context-menu-cm/context-menu-dialogs.lisp	(revision 13309)
@@ -0,0 +1,184 @@
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      context-menu-dialogs.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Utilities and dialogs for the Context-Menu tool set.
+;;;
+;;;      The API for writing new tools is described in the accompanying NewTools file.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/14/9  First cut
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "CONTEXT-MENU" (:nicknames "CMENU") (:use :cl :ccl))
+(in-package "CONTEXT-MENU")
+
+(export '(notify window-with-path active-hemlock-window window-path echo-msg))
+
+(defparameter *clozure-jpg* (merge-pathnames ";Clozure.jpg" cl-user::*context-menu-directory*))
+(defparameter *graphic-p* t "To use, or not to use the Clozure graphic.")
+
+
+(defun active-hemlock-window ()
+  "Return the active hemlock-frame."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (and (typep w 'gui::hemlock-frame)
+            (not (typep w 'gui::hemlock-listener-frame))
+            (#/isKeyWindow w)))))
+
+(defun window-path (w)
+  "Return the window's path."
+  (let* ((pane (slot-value w 'gui::pane))
+         (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+         (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+    (when buffer (hi::buffer-pathname buffer))))
+
+;;; This includes a work-around for what appears to be a bug in the hemlock-frame
+;;; #/close method.  After a #/close, the window remains on the (#/orderedWindows *NSApp*)
+;;; list, but (hi::buffer-document buffer) in NIL.  Therefore the extra tests:
+(defun window-with-path (path)
+  "If a window with PATH is open, return it."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (when (and (typep w 'gui::hemlock-frame)
+                  (not (typep w 'gui::hemlock-listener-frame)))
+         (let* ((pane (slot-value w 'gui::pane))
+                (text-view (gui::text-pane-text-view pane))
+                (buffer (gui::hemlock-buffer text-view))
+                (document (when buffer (hi::buffer-document buffer)))
+                (p (hi::buffer-pathname buffer)))
+           (when (and document p) (string-equal path p)))))))
+
+(defun echo-msg (string &rest args)
+  (let* ((window (cmenu:active-hemlock-window))
+         (hemlock-view (when window (gui::hemlock-view window))))
+    (when hemlock-view
+      (let ((hi::*current-view* hemlock-view))
+        (hi::message string args)))))
+
+(defun notify (message &rest args)
+  "FYI"
+  (let ((message-string (apply #'format nil message args)))
+    (if *graphic-p*
+      (open-notification-dialog message-string)
+      (gui::alert-window :title "Notification" :message message-string))))
+
+(defparameter *notify-dialog* nil "The notification-dialog instance.")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass NOTIFICATION-DIALOG (ns:ns-window)
+  ((message-field :initform nil :accessor nd-message-field)
+   (okay-button :initform nil :accessor nd-okay-button))
+  (:documentation "A dialog for displaying messages.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/okayAction: :void) ((d notification-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 0))
+
+(defun open-notification-dialog (message)
+  "Open the notification-dialog and display MESSAGE."
+  (let ((message-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                      (ccl::%make-nsstring message)
+                                                      cmenu::*tool-doc-dictionary*)))
+    (cond (*notify-dialog*
+           (#/setStringValue: (nd-message-field *notify-dialog*) message-string)
+           (#/makeKeyAndOrderFront: *notify-dialog* nil)
+           (#/runModalForWindow: ccl::*nsapp* *notify-dialog*)
+           (#/close *notify-dialog*))
+          (t
+           (let ((dialog (#/alloc notification-dialog)))
+             (setq *notify-dialog* dialog)
+             (ns:with-ns-rect (r 10 300 400 127)
+               (#/initWithContentRect:styleMask:backing:defer: 
+                dialog
+                r
+                #$NSTitledWindowMask 
+                #$NSBackingStoreBuffered
+                #$NO))
+             (dolist (item (get-notify-items dialog))
+               (#/addSubview: (#/contentView dialog) item))
+             (#/setTitle: dialog #@"Notification")
+             (#/setReleasedWhenClosed: dialog nil)
+             (#/setDefaultButtonCell: dialog (nd-okay-button dialog))
+             (#/setStringValue: (nd-message-field dialog) message-string)
+             (#/center dialog)
+             (#/makeKeyAndOrderFront: dialog nil)
+             (#/runModalForWindow: ccl::*nsapp* dialog)
+             (#/close dialog))))))
+
+#|
+(open-notification-dialog "foobear")
+|#
+
+(defmethod get-notify-items ((d notification-dialog))
+  (append
+   (make-notify-graphic)
+   ;; (make-notify-prompt)
+   (make-notify-message d)
+   (make-notify-button d)))
+
+(defun make-notify-graphic ()
+  "Create the Clozure graphic."
+  (when (probe-file *clozure-jpg*)
+    (let ((image (#/alloc ns:ns-image))
+          (image-view (#/alloc ns:ns-image-view)))
+      (ns:with-ns-rect (frame 0 0 108 127)
+        (#/initWithFrame: image-view frame))
+      (#/setImageScaling: image-view #$NSScaleToFit)
+      (#/initWithContentsOfFile: image (ccl::%make-nsstring (namestring *clozure-jpg*)))
+      (#/setImage: image-view image)
+      (list image-view))))
+
+(defun make-notify-prompt ()
+  "Create the prompt text-field."
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Notification"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 120 90 150 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)))
+
+(defun make-notify-message (dialog)
+  "Create the documentation text-view."
+  (list
+   (let ((field (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 120 50 270 60)
+       (#/initWithFrame: field frame))
+     (#/setEditable: field nil)
+     (#/setDrawsBackground: field nil)
+     (#/setBordered: field nil)
+     (setf (nd-message-field dialog) field))))
+
+(defun make-notify-button (dialog)
+  "Construct the button."
+  (list
+   (let ((button (#/alloc ns:ns-button)))
+     (ns:with-ns-rect (frame 310 10 80 32)
+       (#/initWithFrame: button frame))
+     (#/setButtonType: button #$NSMomentaryPushInButton)
+     (#/setBezelStyle: button #$NSRoundedBezelStyle)
+     (#/setTitle: button #@"Okay")
+     (#/setTarget: button dialog)
+     (#/setAction: button (ccl::@selector "okayAction:"))
+     (setf (nd-okay-button dialog) button))))
+
+
+
+
+
Index: /branches/new-random/contrib/foy/context-menu-cm/context-menu.lisp
===================================================================
--- /branches/new-random/contrib/foy/context-menu-cm/context-menu.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/context-menu-cm/context-menu.lisp	(revision 13309)
@@ -0,0 +1,204 @@
+;;;-*-Mode: LISP; Package: CONTEXT-MENU -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      context-menu.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code provides a mechanism for switching the tool that has access to 
+;;;      Hemlock's contextual popup menu.  This is an initial prototype, implementing
+;;;      what may be the simplest approach.
+;;;
+;;;      The API for writing new tools is described in the accompanying NewTools file.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Changed the appearance of the Default Tool submenu.
+;;;      8/31/9  version 0.1b1
+;;;              First cut
+;;;              Numerous User Interface suggestions, Rainer Joswig
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "CONTEXT-MENU" (:nicknames "CMENU") (:use :cl :ccl))
+(in-package "CONTEXT-MENU")
+
+(export '(register-tool add-default-tool-menu update-tool-menu set-default-tool
+          tool-menu *hemlock-menu-dictionary* *tool-label-dictionary* *tool-doc-dictionary*
+          *tool-key-dictionary* *dark-blue-color* *dark-turquoise-color* *light-gray-color* 
+          *wine-red-color* check-hyperspec-availability))
+
+(defparameter *menu-manager* nil "The context-menu-manager instance.")
+
+(defparameter *dark-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.2 0.2 0.5 1.0))
+(defparameter *dark-turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.28 0.28 1.0))
+(defparameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.4 0.1 0.2 1.0))
+(defparameter *light-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.92 0.92 0.92 1.0))
+
+(defparameter *hemlock-menu-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *hemlock-menu-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *hemlock-menu-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *tool-label-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *tool-label-dictionary* (#/systemFontOfSize: ns:ns-font (#/systemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *tool-label-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+
+(defparameter *tool-doc-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *tool-doc-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *tool-doc-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+
+(defparameter *tool-key-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *tool-key-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *tool-key-dictionary* *wine-red-color* #&NSForegroundColorAttributeName)
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass CONTEXT-MENU-MANAGER ()
+  ((tool-alist :initform nil :accessor tool-alist)
+   (default-tool :initform nil :accessor default-tool))
+  (:documentation "A class to manage Hemlock's contextual popup menu, supporting access by multiple tools."))
+
+(defmethod display-menu ((manager context-menu-manager) view event)
+  (when (default-tool manager)
+    (let ((entry (assoc (default-tool manager) (tool-alist manager) :test #'string-equal)))
+      (when entry 
+        (funcall (cdr entry) view event)))))
+
+(objc:defmethod #/menuForEvent: ((view gui::hemlock-text-view) (event :id))
+  (display-menu *menu-manager* view event))
+
+(defun register-tool (tool-name menu-function)
+  "Register the new tool with the menu-manager.  The last tool registered becomes the default tool."
+  (let ((entry (find tool-name (tool-alist *menu-manager*) :test #'string-equal :key #'car)))
+    (cond (entry
+           (gui::alert-window :title "Notification" :message (format nil "Re-registering ~S." tool-name))
+           (setf (tool-alist *menu-manager*) (delete tool-name (tool-alist *menu-manager*) :test #'string-equal :key #'car))
+           (setf (tool-alist *menu-manager*) (cons (cons tool-name menu-function) (tool-alist *menu-manager*))))           
+          (t
+           (setf (tool-alist *menu-manager*) (cons (cons tool-name menu-function) (tool-alist *menu-manager*)))
+           (setf (tool-alist *menu-manager*)
+                 (sort (tool-alist *menu-manager*) #'string< :key #'car))
+           (set-default-tool tool-name)))))
+
+(defun set-default-tool (tool-name)
+  "Set the menu-manager's default tool.  Right-Click will display this tool's menu."
+  (let ((registered-name (car (find tool-name (tool-alist *menu-manager*) :test #'string-equal :key #'car))))
+    (if registered-name
+      (setf (default-tool *menu-manager*) registered-name) ; keep the original capitalization
+      (gui::alert-window :title "Notification" :message (format nil "~S is not a registered tool.  It can't be set as default." tool-name)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFAULT-TOOL-MENU-ITEM (ns:ns-menu-item)
+  ((name :accessor tool-name)) ; Lisp string
+  (:documentation "Support for the Tool submenu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFAULT-TOOL-DOC-MENU-ITEM (ns:ns-menu-item)
+  ((filename :accessor tool-filename))
+  (:documentation "A menu-item to display the default tool's documentation.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFAULT-TOOL-MENU (ns:ns-menu)
+  ()
+  (:documentation "A submenu displaying all registered tools.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/hemlockDefaultToolAction: :void) ((m default-tool-menu) (sender :id))
+  (set-default-tool (tool-name sender)))
+
+(objc:defmethod (#/hemlockDefaultToolDocAction: :void) ((m default-tool-menu) (sender :id))
+  (display-doc (tool-filename sender)))
+
+(defun display-doc (path)
+  "Display the default tool's documentation."
+  (when (probe-file path)
+    (#/openFile:withApplication: (#/sharedWorkspace ns:ns-workspace) 
+                                 (ccl::%make-nsstring (namestring path))
+                                 (ccl::%make-nsstring "TextEdit"))))
+  
+(defmethod populate-menu ((menu default-tool-menu))
+  (dotimes (count (#/numberOfItems menu))
+    (#/removeItemAtIndex: menu 0))
+  (flet ((create-menu-item (name)
+           (let ((menu-item (make-instance 'default-tool-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring name)
+                                     *tool-label-dictionary*)))
+             (setf (tool-name menu-item) name) 
+             (#/setAttributedTitle: menu-item attributed-string)
+             (#/setAction: menu-item (ccl::@selector "hemlockDefaultToolAction:"))
+             (#/setTarget: menu-item  menu)
+             (if (string-equal name (default-tool *menu-manager*))
+               (#/setState: menu-item #$NSOnState)
+               (#/setState: menu-item #$NSOffState))
+             (#/addItem: menu menu-item))))
+    (dolist (entry (tool-alist *menu-manager*))
+      (create-menu-item (car entry)))))
+
+(defun add-default-tool-menu (menu &key doc-file)
+  "Add the default tool submenu and possibly a documentation menu-item to MENU."
+  (let ((default-item (make-instance ns:ns-menu-item))
+        (tool-menu (make-instance 'default-tool-menu)))
+    ;; Title is set by update method.
+    (#/setSubmenu: default-item tool-menu)
+    (#/insertItem:atIndex: menu default-item 0)
+    (cond (doc-file
+           (let ((doc-item (make-instance 'default-tool-doc-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring (format nil "     doc..." (default-tool *menu-manager*)))
+                                     *tool-doc-dictionary*)))
+             (#/setAttributedTitle: doc-item attributed-string)
+             (#/setAction: doc-item (ccl::@selector "hemlockDefaultToolDocAction:"))
+             (#/setTarget: doc-item  tool-menu)
+             (setf (tool-filename doc-item) doc-file)
+             (#/insertItem:atIndex: menu doc-item 1))
+          (#/insertItem:atIndex: menu (#/separatorItem ns:ns-menu-item) 2))
+          (t
+           (#/insertItem:atIndex: menu (#/separatorItem ns:ns-menu-item) 1)))
+    tool-menu))
+
+(defun update-tool-menu (menu default-menu &key sub-title)
+  "Update MENU's Tool submenu."
+  (let ((first-item (#/itemAtIndex: menu 0))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (if sub-title
+                              (ccl::%make-nsstring (format nil "~S
+    (~A)" (default-tool *menu-manager*) sub-title))
+                              (ccl::%make-nsstring (format nil "~S" (default-tool *menu-manager*))))
+                            *tool-label-dictionary*)))
+    (#/setAttributedTitle: first-item attributed-string)
+    (populate-menu default-menu)))
+
+(let (checked-p)
+(defun check-hyperspec-availability (tool-name)
+  "Some tools require the HyperSpec."
+  (unless (or checked-p gui::*hyperspec-root-url*)
+    (rlet ((perror :id  +null-ptr+))
+      (let* ((map-url (make-instance 'ns:ns-url :with-string #@"Data/Map_Sym.txt" :relative-to-url (gui::hyperspec-root-url)))
+             ;; kludge alert:
+             (data (make-instance 'ns:ns-data
+                     :with-contents-of-url map-url
+                     :options 0
+                     :error perror)))
+        (declare (ignore data))
+        (setq checked-p t)
+        (unless (%null-ptr-p (pref perror :id))
+          (gui::alert-window 
+           :title "Notification" 
+           :message (format nil "~S needs the HyperSpec, and it does not appear to be available. Check the documentation in the Context-Menu-CM/ReadMe, and restart CCL." tool-name))))))))
+
+(setq *menu-manager* (make-instance 'context-menu-manager))
+
+
+
Index: /branches/new-random/contrib/foy/hemlock-commands-cm/MCL-doc.lisp
===================================================================
--- /branches/new-random/contrib/foy/hemlock-commands-cm/MCL-doc.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/hemlock-commands-cm/MCL-doc.lisp	(revision 13309)
@@ -0,0 +1,4258 @@
+#|
+; Copyright 1987-1988 Coral Software Corp.
+; Copyright 1989-1994 Apple Computer, Inc.
+; Copyright 1995-2001 Digitool, Inc.
+
+; MCL has been released as an open source application, subject to the GLGPL License.
+|#
+
+* 
+"&rest numbers"
+"[Function / Variable]"
+"as a function, multiplies all the numbers, returning the product. As a variable, bound to the last
+value returned by the read loop."
+
+**  
+NIL "[Variable]"
+"bound to the second to last value returned by the read loop."
+
+***  
+NIL "[Variable]"
+"bound to the third to last value returned by the read loop."
+
+*COMPILE-PRINT* 
+NIL "[Variable]"
+"holds the default value for the :print keyword argument to compile. If the value of this variable is t,
+then compile prints the value of each expression compiled to *standard-output*. The default value is
+nil."
+
+*COMPILE-VERBOSE* 
+NIL "[Variable]"
+"holds the default value for the :verbose keyword argument to compile If true, then compile defaults to
+printing the name of each file compiled. If nil, then compile defaults to not printing the names of files
+compiled."
+
+*DEBUG-IO*  
+NIL "[Variable]"
+"the stream used for input and output when operating inside a break loop."
+
+*DEFAULT-PATHNAME-DEFAULTS* 
+NIL "[Variable]" 
+"the default pathname used to supply missing components when pathnames are merged."
+
+*ERROR-OUTPUT*  
+NIL "[Variable]"
+"the stream to which error messages are sent."
+
+*FEATURES*  
+NIL "[Variable]"
+"a list of features present in the current lisp environment. You can add features to this list as you
+bring tools into your environment. The features should be represented as keywords. This variable is
+used by the #+ and #- reader macros."
+
+*LOAD-PRINT*  
+NIL "[Variable]"
+"holds the default value for the :print keyword argument to load. If the value of this variable is t, then
+load prints the value of each expression loaded to *standard-output*. The default value is nil."
+
+*LOAD-TRUENAME*  
+NIL "[Variable]"
+"a variable bound to the true name of the file being loaded. Its initial value is nil."
+
+*LOAD-VERBOSE*  
+NIL "[Variable]"
+"holds the default value for the :verbose keyword argument to load. If true, then load defaults to
+printing the name of each file loaded. If nil, then load defaults to not printing the names of files loaded."
+
+*MACROEXPAND-HOOK*  
+NIL "[Variable]"
+"used by macroexpand-1. Its initial value is funcall."
+
+#|
+*MODULES*  
+NIL "[Variable]"
+"holds a list of the names of the modules that have been loaded into Macintosh Common Lisp. This list is
+used by the functions require and provide. This variable has been removed from Common Lisp and is
+provided in the CCL: package."
+|#
+
+*PACKAGE*  
+NIL "[Variable]"
+"at any point, this variable is bound to the current package. The functions load and compile-file rebind
+*package* to its current value. The forthcoming ANSI Common Lisp will use the package name
+common-lisp-user instead of user."
+
+*PRINT-ARRAY*  
+NIL "[Variable]"
+"controls whether arrays are printed readably. If the value of this variable is nil, the contents of
+arrays other than strings are never printed."
+
+*PRINT-BASE*  
+NIL "[Variable]"
+"specifies the radix to use for printing rational numbers. The default is base 10. Note that this is the
+radix for printing; it doesnÕt affect the radix for reading numbers."
+
+*PRINT-CASE*  
+NIL "[Variable]"
+"controls the case used for printing symbols. The value of *print-case* should be :upcase (the
+default), :downcase, or :capitalize."
+
+*PRINT-CIRCLE*  
+NIL "[Variable]"
+"Controls the printing of data objects which may be circular, such as arrays and lists. If
+*print-circle* is true, then the printer checks for circular structures (which makes printing
+slower). The default is nil."
+
+*PRINT-ESCAPE*  
+NIL "[Variable]"
+"controls the printing of escape characters. If *print-escape* is true (the default), then escape
+characters are printed (which increases the chances that objects will print readably)."
+
+*PRINT-GENSYM*  
+NIL "[Variable]"
+"controls the printing of uninterned symbols. If true, uninterned symbols are printed with the #:
+reader macro; they will not be interned when read into Lisp. If nil, they are not printed with the
+reader macro, and they will be interned when read back in."
+
+*PRINT-LENGTH*  
+NIL "[Variable]"
+"controls how many elements of a list or array are printed. If nil, then the entire data structure is
+printed."
+
+*PRINT-LEVEL*  
+NIL "[Variable]"
+"controls how many levels of a list or array are printed. If nil, then all levels are printed."
+
+*PRINT-LINES*  
+NIL "[Variable]"
+"When the value of this Common Lisp variable is other than nil, it is a limit on the number of output
+lines produced when an object is pretty printed."
+
+*PRINT-PRETTY*  
+NIL "[Variable]"
+"controls the look of printed expressions. If true, then extra whitespace is inserted to make the
+printed representation of forms more readable. For a description of user-controlled pretty-printing
+in Common Lisp, see Common Lisp: The Language, 2d edition, Chapter 27."
+
+*PRINT-RADIX*  
+NIL "[Variable]"
+"controls the printing of radix specifiers for rational numbers. If true, then rational numbers are
+printed with radix specifiers. This ensures that the numbers may be read back into Lisp. The default
+is nil."
+
+*PRINT-READABLY*  
+NIL "[Variable]"
+"If this Common Lisp variable true, objects are printed out such that the printed representation can
+be read back into Lisp to create a similar object. If false, objects may be printed more tersely."
+
+*PRINT-RIGHT-MARGIN*  
+NIL "[Variable]"
+"If non-nil, this Common Lisp variable specifies the right margin to use when the pretty printer is
+making layout decisions."
+
+*QUERY-IO*  
+NIL "[Variable]"
+"the stream used for asking questions of, and receiving answer from, the user."
+
+*RANDOM-STATE*  
+NIL "[Variable]"
+"the default random state object, used by random when it is not explicitly passed a random state."
+
+*READ-BASE*  
+NIL "[Variable]"
+"specifies the radix used when reading rational numbers. Note that this does not affect the radix used
+when printing numbers."
+
+*READ-DEFAULT-FLOAT-FORMAT*  
+NIL "[Constant]"
+"the default floating-point type in which to read floating-point numbers."
+
+*READ-SUPPRESS*  
+NIL "[Variable]"
+"if true, most read operations are suppressed, preventing the reading of Lisp data objects. This
+variable is most often used by the reader macros #+ and #-."
+
+*READTABLE*  
+NIL "[Variable]"
+"holds the default readtable used by read operations."
+
+*STANDARD-INPUT*  
+NIL "[Variable]"
+"the stream from which the top level read-eval-print loop gets its input. This is the default input
+stream used by functions such as read and read-char."
+
+*STANDARD-OUTPUT*  
+NIL "[Variable]"
+"the stream to which the top level read-eval-print loop sends its output. This is also the default
+output stream for functions such as print, write, etc."
+
+*TERMINAL-IO*  
+NIL "[Variable]"
+"the stream which is used for interacting with the user. *terminal-io* is bound to a stream that reads
+from the Listener and other Fred windows, and from forms which have been set up with
+eval-enqueue. It prints to the *standard-output* or one of the other system output streams (such as
+*error-output*)."
+
+*TRACE-OUTPUT*  
+NIL "[Variable]"
+"the stream to which the output of trace is sent. *trace-output* is initially bound to the same stream
+as *terminal-io*, but may be rebound to redirect the output of trace."
+
++ 
+"&rest numbers"
+"[Function / Variable]"
+"as a function, adds all the arguments and returns the sum. As a variable, bound to the last form read
+by the read loop."
+
+++  
+NIL "[Variable]"
+"bound to the second to last form read by the read loop."
+
++++  
+NIL "[Variable]"
+"bound to the third to last form read by the read loop."
+
+- 
+"number &rest more-numbers"
+"[Function / Variable]"
+"as a function subtracts each argument, from left to right, from the result of the previous
+subtraction, and returns the final difference. As a variable, bound to the form currently being
+executed by the read loop."
+
+/ 
+"number &rest more-numbers"
+"[Function / Variable]"
+"as a function divides each argument, from left to right, into the result of the previous division, and
+returns the final quotient. As a variable, bound to a list containing the multiple values last returned
+by the read loop."
+
+//  
+NIL "[Variable]"
+"bound to a list of the second to last set of multiple values returned by the read loop."
+
+///  
+NIL "[Variable]"
+"bound to a list of the third to last set of multiple values returned by the read loop."
+
+/= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if none of the arguments are numerically equal; otherwise returns nil."
+
+1+ 
+"number"
+"[Function]"
+"returns the result of adding 1 to number."
+
+1- 
+"number"
+"[Function]"
+"returns the result of subtracting 1 from number."
+
+< 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is less than the one following it; otherwise returns nil."
+
+<= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is less than or equal to the one following it; otherwise returns nil."
+
+= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if all the arguments are numerically equal; otherwise returns nil."
+
+> 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is greater than the one following it; otherwise returns nil."
+
+>= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is greater than or equal to the one following it; otherwise returns nil."
+
+ABORT 
+"&optional condition"
+"[Function]"
+"transfers control to the restart named abort. If no such restart exists, an error is signaled. If
+condition is not nil, only restarts associated with condition are considered."
+
+ABS 
+"number"
+"[Function]"
+"returns the absolute value of number."
+
+ACONS 
+"key datum alist"
+"[Function]"
+"creates a cons with key in the car and datum in the cdr, conses this onto the front of alist, and returns
+the resulting list. alist is not destructively modified."
+
+ACOS 
+"radians"
+"[Function]"
+"returns the arc cosine of radians, a number in radians."
+
+ACOSH 
+"radians"
+"[Function]"
+"returns the hyperbolic arc cosine of radians, a number in radians."
+
+ADJOIN 
+"item list &key :test :test-not :key"
+"[Function]"
+"adds item to list if it is not already a member of list, and returns the resulting list. list is not
+destructively modified."
+
+ADJUST-ARRAY 
+"array new-dimensions &key :element-type :initial-element :initial-contents
+:fill-pointer :displaced-to :displaced-index-offset"
+"[Function]"
+"returns an array of the same type and rank as array, with the specified new-dimensions. This
+function may either alter the given array or create and return a new one."
+
+ADJUSTABLE-ARRAY-P 
+"array"
+"[Function]"
+"returns true if array is adjustable, and nil if it is not."
+
+ALPHA-CHAR-P 
+"char"
+"[Function]"
+"returns true if char is an alphabetic character, otherwise false. char must be a character."
+
+ALPHANUMERICP 
+"char"
+"[Function]"
+"returns true if char is an alphabetic or numeric character, otherwise returns nil. char must be a
+character."
+
+AND 
+"{form}*"
+"[Macro]"
+"evaluates each form sequentially. If and reaches a form that returns nil, it returns nil without
+evaluating any more forms. If it reaches the last form, it returns that form's value."
+
+APPEND 
+"&rest lists"
+"[Function]"
+"concatenates the top-level elements of lists, in effect splicing them together. The lists are not
+modified. Returns the resulting concatenated list."
+
+APPLY 
+"function first-arg &rest more-args"
+"[Function]"
+"invokes function, giving it first-arg and more-args as arguments. The value returned by function is
+returned. The last argument to apply should be a list; the elements of this list are passed as
+individual arguments to function. The type of function can be only symbol or function."
+
+APROPOS 
+"string-or-symbol &optional package"
+"[Function]"
+"finds all interned symbols whose print names contain string-or-symbol as a substring and prints
+the name, function definition, and global value of each symbol. The printing is sent to
+*standard-output*. If package is specified, only the given package is searched. apropos returns no
+values."
+
+APROPOS-LIST 
+"string-or-symbol &optional package"
+"[Function]"
+"returns a list of all available symbols whose print names contain string-or-symbol as a substring.
+If package is specified, only the given package is searched."
+
+AREF 
+"array &rest subscripts"
+"[Function]"
+"returns the element of array specified by subscripts. aref can be used with setf to modify an array."
+
+ARRAY-DIMENSION 
+"array dimension"
+"[Function]"
+"returns the length of dimension of array. Vector fill-pointers are ignored (i.e. the total size,
+including inactive elements, is returned)."
+
+#|
+ARRAY-DIMENSION-LIMIT  
+NIL "[Constant]"
+"The maximum allowable number of elements in a single dimension of an array. This value must be a
+fixnum. Its value in Macintosh Common Lisp is 4194304."
+|#
+
+ARRAY-DIMENSIONS 
+"array"
+"[Function]"
+"returns a list whose elements are the dimensions of array."
+
+ARRAY-ELEMENT-TYPE 
+"array"
+"[Function]"
+"returns a type specifier which describes what data types an element of array may have."
+
+ARRAY-HAS-FILL-POINTER-P 
+"array"
+"[Function]"
+"returns t if array is a vector with a fill pointer. Returns nil if array is not a vector or if array does
+not have a fill pointer."
+
+ARRAY-IN-BOUNDS-P 
+"array &rest subscripts"
+"[Function]"
+"returns true if subscripts are all legal subscripts for array."
+
+ARRAY-RANK 
+"array"
+"[Function]"
+"returns the rank (number of dimensions) of array."
+
+#|
+ARRAY-RANK-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the rank (number of dimensions) in an array.
+Its value in Macintosh Common Lisp is 8192."
+|#
+
+ARRAY-ROW-MAJOR-INDEX 
+"array &rest subscripts"
+"[Function]"
+"given an array and a valid set of subscripts, returns a single number indicating the position of the
+accessed element based on row-major ordering. This function ignores fill-pointers."
+
+ARRAY-TOTAL-SIZE 
+"array"
+"[Function]"
+"returns the total size of array. This is the product of the sizes of all the dimensions."
+
+#|
+ARRAY-TOTAL-SIZE-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the total number of elements in an array. Its
+value in Macintosh Common Lisp is 4194304."
+|#
+
+ARRAYP 
+"object"
+"[Function]"
+"returns true if data-object is an array, false if it is not."
+
+ASH 
+"integer count"
+"[Function]"
+"Shifts integer arithmetically left or right by count bits, depending on the sign of count. Bits shifted
+off the right are lost."
+
+ASIN 
+"radians"
+"[Function]"
+"returns the arc sine of radians, a number in radians."
+
+ASINH 
+"radians"
+"[Function]"
+"returns the hyperbolic arc sine of radians, a number in radians."
+
+ASSERT 
+"test-form [({place}*) [string {arg}*]]"
+"[Macro]"
+"signals a continuable error if the value of test-form is nil. If the user continues, the values of some
+variables can be changed, and the assert will start over, evaluating the test-form again. assert
+returns nil."
+
+ASSOC 
+"indicator a-list &key :test :key :test-not"
+"[Function]"
+"searches a-list for the first pair whose car matches indicator. Returns the pair, or nil if the search
+fails."
+
+ASSOC-IF 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose car satisfies predicate. Returns the pair, or
+nil if the search fails."
+
+ASSOC-IF-NOT 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose car does not satisfy predicate. Returns the
+pair, or nil if the search fails."
+
+ATAN 
+"y &optional x"
+"[Function]"
+"returns the arc tangent of y, either the y-component of a number in radians or the complete number,
+encoded as a point."
+
+ATANH 
+"radians"
+"[Function]"
+"returns the hyperbolic arc tangent of radians, a number in radians."
+
+ATOM 
+"data-object"
+"[Function]"
+"returns true if object is not a cons; otherwise returns false. In general , atom is true of anything that
+is not a list. The one exception is the empty list, which is both a list and an atom."
+
+BIT 
+"bit-array &rest subscripts"
+"[Function]"
+"returns the value of the the bit in bit-array specified by the subscripts."
+
+BIT-AND 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical AND of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-ANDC1 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical AND of the bits in the complement of bit-array-1 and the bits in bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-ANDC2 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical AND of the bits in bit-array-1 and the bits in the complement of bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-EQV 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"compares the bits in bit-array-1 and bit-array-2; if both are 1s or both are 0s, a 1 is stored into
+result-bit-array (otherwise a 0 is stored into result-bit-array). If result-bit-array is not
+specified, a new bit-array is created to hold the result. If result-bit-array is t, the result is stored
+into bit-array-1. If result-bit-array is a bit array, the result is destructively placed into that
+array."
+
+BIT-IOR 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical inclusive OR of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-NAND 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical NOT-AND of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-NOR 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical NOT-OR of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-NOT 
+"source-bit-array &optional result-bit-array"
+"[Function]"
+"stores the contents of source-bit-array, with all the bits inverted, into result-bit-array. If
+result-bit-array is not specified, a new bit array is created. If result-bit-array is t, the result is
+stored in source-bit-array. If result-bit-array is a bit array, the result is destructively placed
+into that array."
+
+BIT-ORC1 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical OR of the bits in the complement of bit-array-1 and the bits of bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-ORC2 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical OR of the bits in bit-array-1 and the bits in the complement of bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-VECTOR-P 
+"thing"
+"[Function]"
+"returns true if thing is a bit-vector."
+
+BIT-XOR 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical exclusive OR of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BLOCK 
+"name {form} *"
+"[Special Form]"
+"establishes a lexical construct named name in which the forms are evaluated sequentially. The block
+may be exited at any time by calling return-from with the argument name. Block returns the value
+of the last form, or the value passed to return-from."
+
+BOOLE 
+"op integer-1 integer-2"
+"[Function]"
+"applies the logical operation indicated by op to integer-1 and integer-2."
+
+BOOLE-1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 1 for each bit in the first integer argument
+which is 1."
+
+BOOLE-2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 1 for each bit in the second integer argument
+which is 1."
+
+BOOLE-AND  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the logical and of the two integer arguments."
+
+BOOLE-ANDC1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the and complement of the first integer
+argument with the second integer argument."
+
+BOOLE-ANDC2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the and complement of the second integer
+argument with the first integer argument."
+
+BOOLE-C1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the complement of the first integer argument."
+
+BOOLE-C2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the complement of the second integer argument."
+
+BOOLE-CLR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 0."
+
+BOOLE-EQV  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the exclusive nor of the integer arguments."
+
+BOOLE-IOR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the inclusive or of the integer arguments."
+
+BOOLE-NAND  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the not-and of the integer arguments."
+
+BOOLE-NOR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the not-or of the integer arguments."
+
+BOOLE-ORC1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the or complement of the first integer
+argument with the second integer argument."
+
+BOOLE-ORC2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the or complement of the second integer
+argument with the first integer argument."
+
+BOOLE-SET  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 1."
+
+BOOLE-XOR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return exclusive or of the integer arguments."
+
+BOTH-CASE-P 
+"char"
+"[Function]"
+"returns true if char has both a lowercase and and uppercase version. char must be a character."
+
+BOUNDP 
+"symbol"
+"[Function]"
+"returns true if the dynamic (special) variable named by symbol has a value binding, otherwise
+returns nil. boundp does not check for lexical bindings."
+
+BREAK 
+"&optional format-string &rest arguments"
+"[Function]"
+"Prints the message specified by format-string and arguments, sets up a break catch, and enters a
+break loop. The program will resume when the expression (continue) is evaluated (at which point
+break will return nil)."
+
+BUTLAST 
+"list &optional num"
+"[Function]"
+"copies all of list except the last num elements, and returns the new list. num defaults to 1. If list is
+shorter than num, the empty list is returned. list is not modified."
+
+BYTE 
+"size position"
+"[Function]"
+"constructs and returns a byte specifier from size and position."
+
+BYTE-POSITION 
+"bytespec"
+"[Function]"
+"returns the position component of bytespec."
+
+BYTE-SIZE 
+"bytespec"
+"[Function]"
+"returns the size component of bytespec."
+
+CAAAAR 
+"list"
+"[Function]"
+"returns the fourth car of list."
+
+CAAADR 
+"list"
+"[Function]"
+"returns the car of the car of the car of the cdr of list."
+
+CAAAR 
+"list"
+"[Function]"
+"returns the third car of list."
+
+CAADAR 
+"list"
+"[Function]"
+"returns the car of the car of the cdr of the car of list."
+
+CAADDR 
+"list"
+"[Function]"
+"returns the car of the car of the cdr of the cdr of list."
+
+CAADR 
+"list"
+"[Function]"
+"returns the car of the car of the cdr of list."
+
+CAAR 
+"list"
+"[Function]"
+"returns the car of the car of list."
+
+CADAAR 
+"list"
+"[Function]"
+"returns the car of the cdr of the car of the car of list."
+
+CADADR 
+"list"
+"[Function]"
+"returns the car of the cdr of the car of the cdr of list."
+
+CADAR 
+"list"
+"[Function]"
+"returns the car of the cdr of the car of list."
+
+CADDAR 
+"list"
+"[Function]"
+"returns the car of the cdr of the cdr of the car of list."
+
+CADDDR 
+"list"
+"[Function]"
+"returns the car of the cdr of the cdr of the cdr of list."
+
+CADDR 
+"list"
+"[Function]"
+"returns the car of the cdr of the cdr of list."
+
+CADR 
+"list"
+"[Function]"
+"returns the car of the cdr of list. This is the second element of list."
+
+CALL-ARGUMENTS-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the number of arguments that may be passed to
+a function."
+
+CALL-NEXT-METHOD 
+"&rest args"
+"[Function]"
+"can be used within the body of a method defined by a method-defining form to call the next method.
+The type of method combination used determines which methods can invoke this function and what
+behavior results."
+
+CAR 
+"list"
+"[Function]"
+"returns the first element of list."
+
+CASE 
+"keyform {({({key }*) | key } {form}* ) }*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose keys match the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the keys are not. case permits a
+final case, otherwise or t, that handles all keys not otherwise covered."
+
+CATCH 
+"tag {form}*"
+"[Special Form]"
+"sets up a catch called tag and executes forms sequentially. At any time during the execution of the
+forms a throw to tag will immediately cause catch to return the thrown value. If no throw occurs, the
+value of the last body-form is returned."
+
+CCASE 
+"keyform {({( {key }*) | key } {form}* ) }*"
+"[Macro]"
+"gets the value of keyform (which must be a place acceptable to setf), and then executes the first set of
+forms whose corresponding keys are eql to the keyform value. I A continuable error is signalled if
+there is no match, allowing the user to place a new value in the keyform place."
+
+CDAAAR 
+"list"
+"[Function]"
+"returns the cdr of the car of the car of the car of list."
+
+CDAADR 
+"list"
+"[Function]"
+"returns the cdr of the car of the car of the cdr of list."
+
+CDAAR 
+"list"
+"[Function]"
+"returns the cdr of the car of the car of list."
+
+CDADAR 
+"list"
+"[Function]"
+"returns the cdr of the car of the cdr of the car of list."
+
+CDADDR 
+"list"
+"[Function]"
+"returns the cdr of the car of the cdr of the cdr of list."
+
+CDADR 
+"list"
+"[Function]"
+"returns the cdr of the car of the cdr of list."
+
+CDAR 
+"list"
+"[Function]"
+"returns the cdr of the car of list."
+
+CDDAAR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the car of the car of list."
+
+CDDADR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the car of the cdr of list."
+
+CDDAR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the car of list."
+
+CDDDAR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the cdr of the car of list."
+
+CDDDDR 
+"list"
+"[Function]"
+"returns the fourth cdr of list."
+
+CDDDR 
+"list"
+"[Function]"
+"returns the third cdr of list."
+
+CDDR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of list."
+
+CDR 
+"list"
+"[Function]"
+"returns all of list but the first element."
+
+CEILING 
+"number &optional divisor"
+"[Function]"
+"converts number to an integer by rounding up. That is, it returns the smallest integer which is not
+smaller than number. The remainder is returned as a second value. When divisor is specified, ceiling
+first divides divisor into number, and then applies ceiling to the result."
+
+CERROR 
+"continue-format-string datum &rest args"
+"[Function]"
+"invokes the signal facility on a condition. If the condition is not handled, (invoke-debugger condition)
+is executed. While signaling is going on, it is possible to return from cerrror by invoking continue.
+cerror returns nil."
+
+CHANGE-CLASS 
+"instance new-class"
+"[Generic function]"
+"changes the class of an instance to a new class. This function destructively modifies and returns the
+instance."
+
+CHAR 
+"string index"
+"[Function]"
+"returns as a character object the character in string in the position indicated by index. char may be
+used with setf."
+
+CHAR-CODE 
+"character"
+"[Function]"
+"returns the integer ASCII value of character, a character object."
+
+CHAR-CODE-LIMIT  
+NIL "[Constant]"
+"a non-negative integer that is the upper exclusive bound on values produced by the char-code
+function."
+
+CHAR-DOWNCASE 
+"char"
+"[Function]"
+"returns a character which is the lowercase equivalent of char."
+
+#|
+CHAR-EQUAL 
+"char &rest more-chars"
+"[Function]"
+"returns true if all the characters are equal, otherwise false. In Macintosh Common Lisp, case, font,
+and bits attributes are ignored; that is, Control-A is char-equal to a."
+
+CHAR-GREATERP 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is greater than the one to its right, otherwise false.In Macintosh
+Common Lisp, case, font, and bits attributes are ignored."
+
+CHAR-INT 
+"char"
+"[Function]"
+"returns an integer encoding char, including bit and font information. In Macintosh Common Lisp, this
+function is equal to char-code."
+
+CHAR-LESSP 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is less than the one to its right, otherwise false. In Macintosh Common
+Lisp, case, font, and bits attributes are ignored."
+
+CHAR-NAME 
+"character"
+"[Function]"
+"returns the standard name of character as a string, or nil if character has no standard name."
+
+CHAR-NOT-EQUAL 
+"char &rest more-chars"
+"[Function]"
+"returns true if none of the characters are equal, otherwise false. In Macintosh Common Lisp, case,
+font, and bits attributes are ignored; that is, (char-not-equal #\d #\Control-D) is false."
+
+CHAR-NOT-GREATERP 
+"char &rest more-chars"
+"[Function]"
+"returns true if no character is greater than the one to its right, otherwise false. In Macintosh
+Common Lisp, case, font, and bits attributes are ignored."
+
+CHAR-NOT-LESSP 
+"char &rest more-chars"
+"[Function]"
+"returns true if no character is less than the one to its right, otherwise false. In Macintosh Common
+Lisp, case, font, and bits attributes are ignored."
+|#
+
+CHAR-UPCASE 
+"char"
+"[Function]"
+"returns a character which is the uppercase equivalent of char."
+
+CHAR/= 
+"char &rest more-chars"
+"[Function]"
+"returns true if none of the characters are equal, otherwise false. The comparison is case sensitive."
+
+CHAR< 
+"character &rest characters"
+"[Function]"
+"returns true if the ASCII value of character is less than the ASCII value of any of the other
+characters, otherwise false. Because ASCII values are compared, case is significant."
+
+CHAR<= 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is less than or equal to the character to its right, otherwise false. The
+comparison is case sensitive."
+
+CHAR= 
+"character &rest characters"
+"[Function]"
+"returns true if all the characters are equal. Case is significant, so that characters of different cases
+will never be considered equal."
+
+CHAR> 
+"character &rest characters"
+"[Function]"
+"returns true if the ASCII value of character is greater than the ASCII value of any of the other
+characters, otherwise false. Because ASCII values are compared, case is significant."
+
+CHAR>= 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is greater than or equal to the one to its right, otherwise false. The
+comparison is case sensitive."
+
+CHARACTER 
+"thing"
+"[Function]"
+"coerces thing to a character if possible. thing must be a character, positive integer less than
+char-code-limit, a string of length one, or a symbol whose print-name is a string of length one."
+
+CHARACTERP 
+"object"
+"[Function]"
+"returns true if object is a character; otherwise returns false."
+
+CHECK-TYPE 
+"place typespec &optional string"
+"[Macro]"
+"signals an error if the value place is not of the type typespec. string, if present, provides a
+description of typespec that can appear in an error message."
+
+CLEAR-INPUT 
+"&optional input-stream"
+"[Function]"
+"clears any buffered input associated with input-stream. Returns nil."
+
+CLEAR-OUTPUT 
+"&optional output-stream"
+"[Function]"
+"flushes any pending output to output-stream and returns nil. The output is simply cleared, not sent."
+
+CLOSE 
+"stream &key :abort"
+"[Function]"
+"closes stream so that it can no longer be used for input or output. Returns nil."
+
+CLRHASH 
+"hash-table"
+"[Function]"
+"removes all the entries from the hash table and returns the hash table."
+
+CODE-CHAR 
+"code"
+"[Function]"
+"creates and returns a character object corresponding to the ASCII value code, a non-negative integer.
+Signals an error if code is outside the range of supported ASCII values."
+
+COERCE 
+"thing type-specifier"
+"[Function]"
+"converts thing to an \"equivalent\" object of type type-specifier. Coercions can take place between
+numeric types as long as these would not involve loss of accuracy, between sequence types, from some
+strings, symbols, and numbers to characters, and from a symbol or lambda-function to a function.
+Returns the new object. If the coercion cannot take place, an error is signaled."
+
+COMPILE 
+"name &optional definition"
+"[Function]"
+"compiles the function name, using the definition supplied by definition . If definition is supplied, it
+should be a lambda-expression or a function to be compiled; if not, the symbol-function of the
+symbol is extracted and compiled. The resulting compiled code becomes the function definition of
+name, and name is returned. name may be a symbol or a list whose car is setf."
+
+COMPILE-FILE 
+"filename &key :output-file :verbose :print :load :features :save-local-symbols
+:save-doc-strings :save-definitions"
+"[Function]"
+"produces a compiled version of the file filename. Compiled files (also called fasl files) can be loaded
+much more quickly than source code files. The default values of :verbose and :print are the values of
+*compile-verbose* and *compile-print*. The default value of :save-local-symbols is the value of
+*fasl-save-local-symbols*; of :save-doc-strings, the value of *fasl-save-doc-strings*;; and of
+save-definitions, the value of *fasl-save-definitions*. The default value of :output-file is the input
+file with the file type *.fasl-pathname*."
+
+COMPILED-FUNCTION-P 
+"thing"
+"[Function]"
+"returns true if thing is any compiled code object, otherwise false."
+
+COMPLEX 
+"realpart &optional imagpart"
+"[Function]"
+"creates a complex number from realpart and imagpart."
+
+COMPLEXP 
+"object"
+"[Function]"
+"returns true if object is a complex number; otherwise returns false."
+
+CONCATENATE 
+"result-type &rest sequences"
+"[Function]"
+"copies sequences in order into a new sequence of type result-type."
+
+COND 
+"{(test {form}* )}*"
+"[Macro]"
+"consists of a series of clauses which are tested sequentially. If a test is true, cond evaluates the
+corresponding forms and returns the last form's value. If the test returns nil, cond proceeds to the
+next test / form clause. If all tests fail, cond returns nil."
+
+CONJUGATE 
+"number"
+"[Function]"
+"returns the complex conjugate of number."
+
+CONS 
+"x list-or-thing"
+"[Function]"
+"allocates a new cons cell whose car is x and whose cdr is list-or-thing."
+
+CONSP 
+"object"
+"[Function]"
+"returns true if object is a cons, otherwise returns false. consp of the empty list returns false. (See
+also listp which returns true on the empty list.)"
+
+CONSTANTP 
+"object"
+"[Function]"
+"returns true if object is a constant. Constants include self-evaluating objects such as numbers,
+characters, bit-vectors, strings, and keywords, and all constant symbols defined with defconstant,
+such as nil and t. In addition, a list whose car is quote, such as (quote foo), is considered to be a
+constant."
+
+CONTINUE 
+"&optional condition"
+"[Function]"
+"resumes execution of the code suspended by the most recent call to break or cerror. If there have
+been no calls to break or cerror, continue simply returns to the top level. If condition is present, the
+restart for condition is invoked."
+
+COPY-ALIST 
+"a-list"
+"[Function]"
+"returns a copy of a-list. The top level of list structure is copied; in addition, any element of a-list
+that is a cons is also copied. Used for copying association lists."
+
+COPY-LIST 
+"list"
+"[Function]"
+"returns a list that is equal to but not eq to list."
+
+COPY-READTABLE 
+"&optional from-readtable to-readtable"
+"[Function]"
+"copies from-readtable to to-readtable. from-readtable defaults to the current readtable; if it is
+supplied as nil, the standard. Common Lisp readtable is used. If to-readtable is supplied, it is
+destructively modified to hold the result; otherwise a new readtable is created."
+
+COPY-SEQ 
+"sequence"
+"[Function]"
+"returns a copy of sequence. The result is equalp but not eq to the argument."
+
+COPY-SYMBOL 
+"symbol &optional copy-props"
+"[Function]"
+"returns a uninterned symbol whose print-name is string-=, but not eq, to that of symbol. If
+copy-props is non-nil, then the contents of the value, function, and property cells are copied to the
+new symbol (the property list is actually duplicated). If copy-props is nil (the default), they are
+not copied."
+
+COPY-TREE 
+"tree"
+"[Function]"
+"if tree is not a cons, it is returned directly. Otherwise, a copy of tree is returned, with all conses,
+stopping only when non-conses are encountered. Used for copying trees of conses. This function does
+not preserve circularities and sharing of substructures."
+
+COS 
+"radians"
+"[Function]"
+"returns the cosine of radians, a number in radians."
+
+COSH 
+"radians"
+"[Function]"
+"returns the hyperbolic cosine of radians, a number in radians."
+
+COUNT 
+"item sequence &key :start :end :from-end :key :test :test-not"
+"[Function]"
+"returns the number of elements of sequence that match item using the given test function; returns nil
+if no element matches."
+
+COUNT-IF 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the number of elements in the given range of sequence that satisfy test."
+
+COUNT-IF-NOT 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the number of elements in the given range of sequence which do not satisfy test."
+
+CTYPECASE 
+"keyform {(type {form}* )}*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose type matches the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the type is not. ctypecase does
+not permit an otherwise or t clause. If no clause is satisfied, ctypecase signals a continuable
+type-error."
+
+DECF 
+"place &optional delta"
+"[Function]"
+"decrements the value in place by delta (which defaults to 1)."
+
+DECLAIM 
+"{declaration-spec}*"
+"[Special Form]"
+"provides a declaration that is executable and may be used anywhere proclaim may be called, but each
+declaration-spec is not evaluated."
+
+DECLARE 
+"{declaration-spec}*"
+"[Special Form]"
+"provides a declaration within executable code. The declare form is not executed; it is limited to
+appearing within the bodies of lambda-expressions, certain generic functions, and some special
+forms, and must always appear at the beginning of the body."
+
+DECODE-FLOAT 
+"float"
+"[Function]"
+"returns three values describing the value of float: a new floating-point number representing the
+mantissa, an integer representing the exponent, and a floating-point number indicating the sign
+(+1.0 or -1.0)."
+
+DECODE-UNIVERSAL-TIME 
+"universal-time &optional time-zone"
+"[Function]"
+"returns nine values giving the decoded time equivalents of time-code. The values are: second, minute,
+hour, date, month, year, day of week, daylight-savings-time-p, and time-zone."
+
+DEFCONSTANT 
+"name value &optional documentation"
+"[Macro]"
+"proclaims name to be constant with the value that is the result of evaluatingvalue. Returns name.
+Documentation may be provided as a string."
+
+DEFINE-MODIFY-MACRO 
+"name lambda-list function [doc-string]"
+"[Macro]"
+"defines a read-modify-write macro named name. These macros set a location to a new value based on
+the old value. (incf and decf are examples of read-modify-write macros.)"
+
+DEFINE-SETF-METHOD 
+"access-function lambda-list [[{declaration}* | doc-string]] {form}*"
+"[Macro]"
+"defines how to setf a generalized variable that is accessed by access-function, which should be a
+function or macro."
+
+DEFMACRO 
+"symbol lambda-list {declaration | doc-string}* {form}*"
+"[Macro]"
+"constructs a global macro definition, binds it to symbol, marks symbol as a macro, and returns
+symbol. defmacro is the macro equivalent of defun."
+
+DEFMETHOD 
+"function-name {method-qualifier}* specialized-lambda-list [[{declaration}* |
+doc-string]] {form}*"
+"[Macro]"
+"defines a method on a generic function."
+
+DEFPACKAGE 
+"defined-package-name {option}*"
+"[Macro]"
+"Creates a new package, or modifies an existing one, whose name is defined-package-name (a string or
+symbol) and returns defined-package-name. The standard options are :size, :nicknames, :shadow,
+:shadowing-import-from, :use, :import-from, :intern, and :export."
+
+DEFPARAMETER 
+"variable-name initial-value &optional documentation"
+"[Macro]"
+"proclaims variable-name to be a special variable, sets it to the value of evaluating initial-value, a
+form, and returns variable-name. Documentation may be provided as a string."
+
+DEFSETF 
+"access-function {update-function [doc-string] | lambda-list (store-variable)
+[[{declaration}* | doc-string]] {form}*}"
+"[Macro]"
+"defines how to setf a generalized variable that is accessed by access-function, which should be a
+function or macro."
+
+DEFSTRUCT 
+"name-and-options [doc-string] {slot-description}*"
+"[Macro]"
+"defines a new structure, according to name-and-options, with slots described by the
+slot-descriptions."
+
+DEFTYPE 
+"symbol lambda-list [[{declaration }* | doc-string]] {form}*"
+"[Macro]"
+"defines the type symbol, to be expanded according to the lambda-list and forms, and returns symbol."
+
+DEFUN 
+"symbol lambda-list {declaration | doc-string}* {form}*"
+"[Macro]"
+"defines a function with the name symbol. Once a function is defined, it may be used just like the
+functions which are built into the system. defun returns symbol."
+
+DEFVAR 
+"variable-name &optional initial-value documentation"
+"[Macro]"
+"proclaims variable-name to be a special variable, optionally sets it to the value of initial-value, and
+returns variable-name. If initial-value is given, variable-name is initialized to the result of
+evaluating it unless variable-name already has a value. If initial-name is not used, it is not
+evaluated. The macro defvar only has an effect the first time it is called on a symbol. Documentation
+may be provided as a string."
+
+DELETE 
+"item sequence &key :count :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence with occurrences of item removed. The original sequence
+may be modified. (This is the destructive counterpart of remove.)"
+
+DELETE-DUPLICATES 
+"sequence &key :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that all duplicate elements have been removed. The
+original sequence may be modified. The non-destructive version of this function is
+remove-duplicates."
+
+#|
+DELETE-FILE 
+"file-or-dir &key :if-does-not-exist"
+"[Function]"
+"deletes file-or-dir. Returns the pathname of the file if it was successfully deleted, or nil if the file
+does not exist and the 0value of :if-does-not-exist is nil. If the file does not exist and the value of
+:if-does-not-exist is t, Macintosh Common Lisp signals an error."
+|#
+
+DELETE-IF 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that pass test are removed. The
+original sequence may be destroyed by the operation."
+
+DELETE-IF-NOT 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that fail to pass test are removed. The
+original sequence may be destroyed by the operation."
+
+DENOMINATOR 
+"rational"
+"[Function]"
+"returns the denominator of the canonical reduced form of rational."
+
+DEPOSIT-FIELD 
+"source-integer bytespec destination-integer"
+"[Function]"
+"returns a number that is the same as destination-integer, except that the byte specified by bytespec
+has been replaced by the corresponding byte from source-integer."
+
+DESCRIBE 
+"thing &optional stream"
+"[Function]"
+"prints information about thing to stream, which defaults to the value of *standard-output*. stream
+may also be nil (meaning *standard-output*) or t (meaning *terminal-io*)."
+
+DIGIT-CHAR 
+"weight &optional radix"
+"[Function]"
+"if possible, returns a character corresponding to weight in the given radix. If it is not possible to
+return such a character, returns nil. radix defaults to 10."
+
+DIGIT-CHAR-P 
+"char &optional radix"
+"[Function]"
+"if char is a legal digit in the base given by radix (default 10), then returns the numeric value of the
+digit. If it is not a legal digit, returns nil. char must be a character."
+
+DIRECTORY 
+"pathname &key :directories :files :directory-pathnames :test :resolve-aliases"
+"[Function]"
+"returns a list of the truenames of all files or folders that match pathname, using * as a wildcard
+character. directory must accept logical pathnames but does not return them."
+
+DIRECTORY-NAMESTRING 
+"pathname"
+"[Function]"
+"returns the directory component of pathname, as a string."
+
+DISASSEMBLE 
+"name-or-compiled-function"
+"[Function]"
+"prints out a disassembly of name-or-compiled-function, which should be a compiled function object,
+a symbol, a lambda expression, or a list whose car is setf."
+
+DO 
+"({var | (var [init [step]])}*) (end-test {result}*) {declaration}* {tag | statement}*"
+"[Macro]"
+"at the beginning of each iteration, evaluates all the init forms (before any var is bound), then binds
+each var to the value of its init . Then evaluates end-test; if the result is nil, execution proceeds with
+the body of the form. If the result is non-nil, the result forms are evaluated as an implicit progn and
+the value of the last result form is returned. At the beginning of the second and subsequent iterations,
+all step forms are evaluated, then all variables are updated."
+
+DO* 
+"({(var [init-val [update]])}*) (end-test {result}*) {decl}* {tag | body-form}*"
+"[Macro]"
+"sequentially evaluates each init form and binds each var to the value of its init , then evaluates
+end-test. If the result is nil, execution proceeds with the body of the form. If the result is non-nil,
+the result forms are evaluated as an implicit progn and the value of the last result form is returned.
+At the beginning of the second and subsequent iterations, the first step form is evaluated and its value
+assigned to the first var, then the second step form is evaluated and its value assigned, and so on."
+
+DO-ALL-SYMBOLS 
+"(var [result-form]) {declaration}* {tag | form}*"
+"[Macro]"
+"iterates over all the symbols accessible in any package, binding var to each of them in turn, and
+evaluating the forms. Some symbols may be processed more than once. When done, evaluates
+result-form and returns its value."
+
+DO-EXTERNAL-SYMBOLS 
+"(var [package [result-form]]) {declaration}* {tag | form}*"
+"[Macro]"
+"iterates over all the external symbols of package, binding var to each of them in turn, and evaluating
+the forms. When done, evaluates result-form and returns its value. package may be either a package
+object or a package name."
+
+DO-SYMBOLS 
+"(var [package [result-form]]) {declaration}* {tag | form}*"
+"[Macro]"
+"iterates over all the symbols accessible in package, binding var to each of them in turn, and
+evaluating the forms. When done, evaluates result-form and returns its value."
+
+DOCUMENTATION 
+"symbol &optional doc-type"
+"[Generic Function]"
+"returns the documentation string of doc-type for symbol. Documentation strings may be specified
+when functions, variables, macros, etc. are defined. The documentation strings are only retained if
+*save-doc-strings* is true when the definition occurs. doc-type may be function, variable,
+structure, type, or setf."
+
+DOLIST 
+"(var listform [resultform]) {declaration}* {tag | statement}*"
+"[Macro]"
+"evaluates listform, which produces a list, and executes the body once for every element in the list. On
+each iteration, var is bound to successive elements of the list. Upon completion, resultform is
+evaluated, and the value is returned. If resultform is omitted, the result is nil."
+
+DOTIMES 
+"(var countform [resultform]) {declaration}* {tag | statement}*"
+"[Macro]"
+"executes forms countform times. On successive executions, var is bound to the integers between zero
+and countform. Upon completion, resultform is evaluated, and the value is returned. If resultform is
+omitted, the result is nil."
+
+DOUBLE-FLOAT-EPSILON  
+NIL "[Constant]"
+"The smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+DOUBLE-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+DPB 
+"source-integer. bytespec destination-integer"
+"[Function]"
+"returns a number that is the same as destination-integer., except that the byte specified by bytespec
+is replaced with the appropriate number of low bits from source-integer."
+
+DRIBBLE 
+"&optional pathname"
+"[Function]"
+"sends input/output from an interactive session in the Listener to the file pathname, creating a
+readable record of the session."
+
+ECASE 
+"keyform {({( {key }*) | key } {form}* ) }*"
+"[Macro]"
+"evaluates keyform, and then executes the first set of forms whose corresponding keys ares eql to the
+keyform. An error is signalled if there is no match."
+
+ED 
+"&optional pathname"
+"[Function]"
+"opens an editor window to the file specified by pathname, or a new editor window if pathname is not
+specified. pathname may be a logical pathname."
+
+EIGHTH 
+"list"
+"[Function]"
+"returns the eighth element of list, using one-based addressing."
+
+ELT 
+"sequence index"
+"[Function]"
+"returns the element of sequence specified by index, a non-negative integer less than the length of
+sequence. Zero-based indexing is used."
+
+ENCODE-UNIVERSAL-TIME 
+"second minute hour date month year &optional time-zone"
+"[Function]"
+"returns the time indicated by the arguments in encoded format."
+
+ENDP 
+"list"
+"[Function]"
+"returns t if list is nil; returns nil if list is a cons; errors if list is not a list."
+
+ENOUGH-NAMESTRING 
+"pathname &optional defaults"
+"[Function]"
+"returns a string form of pathname containing just enough information to distinguish it uniquely from
+defaults (which defaults to the value of *default-pathname-defaults*)."
+
+EQ 
+"object1 object2"
+"[Function]"
+"returns true if and only if object1 and object2 are the same object. eq is the fastest and strictest test
+for equality. (eq works by testing whether object1 and object2 address the same location in
+memory.) Things that print the same are not necessarily eq, numbers with the same value need not
+be eq, and two similar lists are usually not eq."
+
+EQL 
+"object1 object2"
+"[Function]"
+"returns true if object1 and object2 are eq, or if they are numbers of the same type with the same
+value, or if they are character objects that represent the same character."
+
+EQUAL 
+"object1 object2"
+"[Function]"
+"returns true when object1 and object2 are structurally similar. A rough rule of thumb is that
+objects are equal when their printed representation is the same. equal is case sensitive when
+comparing strings and characters."
+
+EQUALP 
+"object1 object2"
+"[Function]"
+"returns true if object1 and object2 are equal; if they are characters and satisfy char-equal; if they
+are numbers with the same numeric value (even if they are of different types); or if they have
+components that are all equalp. Special rules apply to arrays, hash tables, and structures; see the
+full Common Lisp specification."
+
+ERROR 
+"datum &rest args"
+"[Function]"
+"invokes the signal facility on a condition. If the condition is not handled, (invoke-debugger condition)
+is executed."
+
+ETYPECASE 
+"keyform {(type {form}* )}*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose type matches the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the type is not. etypecase does
+not permit an otherwise or t clause. If no clause is satisfied, etypecase signals a non-continuable
+type-error."
+
+EVAL 
+"form"
+"[Function]"
+"evaluates form and returns the value returned by form. The evaluation is performed in the current
+dynamic environment and a null lexical environment."
+
+EVAL-WHEN 
+"({situation}*) {form}*"
+"[Special Form]"
+"specifies when form is to be executed; if it is executed, processes the body of its form as an implicit
+progn. situation must be one of :compile-toplevel, :load-toplevel, or :execute."
+
+EVENP 
+"integer"
+"[Function]"
+"returns true if integer is even (evenly divisible by two); otherwise returns nil."
+
+EVERY 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"predicate is applied to the elements of sequence with index 0, then to those with index 1, and so on,
+until the end of the shortest sequence is reached. As soon as predicate returns a nil value, nil is
+returned; otherwise a non-nil value is returned. That is, every is true if every invocation of
+predicate on sequence returns true."
+
+EXP 
+"number"
+"[Function]"
+"returns e raised to the power number, where e is the base of the natural logarithms."
+
+EXPORT 
+"symbols &optional package"
+"[Function]"
+"makes symbols (which should be a symbol or list of symbols) accessible as external symbols in
+package (which defaults to *package*), and returns t."
+
+EXPT 
+"base-number power-number"
+"[Function]"
+"returns base-number raised to power-number."
+
+FBOUNDP 
+"symbol"
+"[Function]"
+"returns true if symbol has a global function binding, otherwise returns nil."
+
+FCEILING 
+"number &optional divisor"
+"[Function]"
+"rounds number upward to a floating-point number. The remainder is returned as a second value.
+When divisor is specified, fceiling first divides divisor into number, then rounds the result upward."
+
+FFLOOR 
+"number &optional divisor"
+"[Function]"
+"rounds number downward to a floating-point number. The remainder of the operation is returned as a
+second value. When divisor is specified, ffloor first divides divisor into number, then rounds the
+result downward."
+
+FIFTH 
+"list"
+"[Function]"
+"returns the fifth element of list, using one-based addressing."
+
+#|
+FILE-AUTHOR 
+"file"
+"[Function]"
+"attempts to determine and return the author of file. In Macintosh Common Lisp, this returns the
+empty string for all files."
+|#
+
+FILE-LENGTH 
+"file-stream &optional new-length"
+"[Function]"
+"returns the length of the file associated with file-stream. If new-length is supplied, the function sets
+the file size and returns new-pos. If new-length is set to less than the current file position the file is
+truncated and the position is set to the new length."
+
+FILE-NAMESTRING 
+"pathname"
+"[Function]"
+"returns the filename portion of pathname, in string format."
+
+FILE-POSITION 
+"file-stream &optional new-position"
+"[Function]"
+"returns or sets the current position within a random access file. If new-position is given, the
+position is set and the new position is returned. If new-position is not given, the current position is
+returned. Stream input or output operations will occur at this position in the file."
+
+FILE-STRING-LENGTH 
+"file-stream object"
+"[Function]"
+"returns a non-negative integer that is the difference between what the file-position of file-stream
+will be after and before writing object to file-stream. If this difference cannot be determined,
+returns nil."
+
+FILE-WRITE-DATE 
+"file"
+"[Function]"
+"returns the time when file was last modified as an integer in Universal Time format. If this cannot be
+determined, returns nil."
+
+FILL 
+"sequence item &key :start :end"
+"[Function]"
+"destructively replaces elements of sequence with item. Returns the destructively modified sequence."
+
+FILL-POINTER 
+"vector"
+"[Function]"
+"returns the fill pointer of vector. If vector does not have a fill pointer, an error is returned."
+
+FIND 
+"item sequence &key :from-end :test :test-not :start :end :key"
+"[Function]"
+"returns the first element in the specified portion of sequence that matches item according to test, or
+nil if no element matches."
+
+FIND-ALL-SYMBOLS 
+"string-or-symbol"
+"[Function]"
+"returns a list of all symbols in any package whose print-name is the same as string-or-symbol. The
+search is case-sensitive. If the argument is a symbol, its print name supplies the string to be
+searched for."
+
+FIND-CLASS 
+"symbol &optional errorp environment"
+"[Function]"
+"returns the class object named by the given signal in the given environment. If there is no such class
+and the errorp argument is nil, find-class returns nil. The default value of errorp is t, which means
+that if there is no such class, find-class returns an error."
+
+FIND-IF 
+"test sequence &key :key :start :end :from-end"
+"[Function]"
+"returns the first element in the specified portion of sequence that satisfies test."
+
+FIND-IF-NOT 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the first element in the specified portion of sequence that fails to satisfy test."
+
+FIND-PACKAGE 
+"package"
+"[Function]"
+"returns the package with package as its name or nickname, or nil if no such package exists. If package
+is a symbol, its print-name is used. If package is a package object, the package is returned."
+
+FIND-SYMBOL 
+"string &optional package"
+"[Function]"
+"searches for the symbol named by string in package (a package object or a package name). Returns
+the symbol if it is found, otherwise returns nil."
+
+FINISH-OUTPUT 
+"&optional output-stream"
+"[Function]"
+"attempts to ensure that any output to output-stream that has been buffered reaches its destination.
+When the output is complete, returns nil."
+
+FIRST 
+"list"
+"[Function]"
+"returns the car of list, using one-based addressing."
+
+FLET 
+"({(name lambda-list {declaration | doc-string}* {form}*)}*) {flet-body-form}*"
+"[Special Form]"
+"creates local function definitions which can be accessed by the flet-body-forms. Within the body of
+the flet, if there are global functions with the same names as the local function definitions, the local
+definitions are used instead of the global. The local definition can refer to the global definition."
+
+FLOAT 
+"number &optional other"
+"[Function]"
+"converts number, any non-complex number, to a floating-point number. If other is given, it should
+be a floating-point number. number is converted to a float of the same type."
+
+FLOAT-SIGN 
+"float1 &optional float2"
+"[Function]"
+"returns a floating-point number with the same sign as float1 and the same absolute value as float2
+(which defaults to 1.0)."
+
+FLOATP 
+"object"
+"[Function]"
+"returns true if object is a floating point number; otherwise returns false."
+
+FLOOR 
+"number &optional divisor"
+"[Function]"
+"converts number to an integer by rounding down. That is, it returns the largest integer which is not
+larger than number. A second value returned is the remainder of the operation. When divisor is
+specified, floor first divides divisor into number, and then applies floor to the result."
+
+FMAKUNBOUND 
+"symbol"
+"[Function]"
+"causes the global function definition of symbol to become unbound (have no value). symbol may be a
+symbol or a list whose car is setf. fmakunbound returns symbol."
+
+FORCE-OUTPUT 
+"&optional output-stream"
+"[Function]"
+"tells output-stream to immediately process all pending buffered output, and returns nil (without
+waiting for completion or acknowledgment)."
+
+FORMAT 
+"destination control-string &rest args"
+"[Function]"
+"generates output from control-string and args, and sends it to destination, which should be a stream,
+t, or nil. If destination is nil, format returns a stream of type string-stream holding the output.
+Otherwise it sends the output to destination (*standard-output* if destination is t) and returns nil."
+
+FOURTH 
+"list"
+"[Function]"
+"returns the fourth element (cadddr) of list, using one-based addressing."
+
+FRESH-LINE 
+"&optional output-stream"
+"[Function]"
+"writes a newline character to output-stream if and only if output-stream is not already at the start
+of a new line. Returns t if it wrote a newline or nil if it did not."
+
+FROUND 
+"number &optional divisor"
+"[Function]"
+"returns as a floating-point number the integer nearest to number. If number is halfway between two
+integers (for example 3.5), fround rounds up to the next integer and expresses it as a floating-point
+number. fround returns a second value, which is the remainder of the rounding operation. When
+divisor is present, fround first divides divisor into number, then rounds up the result."
+
+FTRUNCATE 
+"number &optional divisor"
+"[Function]"
+"returns two values: the integer part of number (i.e. number with the fractional part removed),
+expressed as a floating-point number, and the fractional part. When divisor is present, truncate
+divides divisor into number first and then truncates the result."
+
+FUNCALL 
+"function &rest arguments"
+"[Function]"
+"invokes function, passing it arguments as arguments. Because funcall is a function, function is
+evaluated. The type of function can be only symbol or function. The value returned by the function
+call is returned."
+
+FUNCTION 
+"function-indicator"
+"[Special Form]"
+"returns the function object associated with function-indicator. This function object is the piece of
+code that would be executed if function-indicator was in the car of a list. function is usually
+abbreviated by the reader macro #'."
+
+FUNCTIONP 
+"object"
+"[Function]"
+"returns true if object could be a function, otherwise returns false. However, functionp is always
+false of symbols and lists, including lambda-lists."
+
+GCD 
+"&rest integers"
+"[Function]"
+"returns the greatest common denominator of its arguments."
+
+GENSYM 
+"&optional string-or-number"
+"[Function]"
+"creates and returns a unique uninterned symbol. If string-or-number is given, it will be used in the
+name of the new symbol."
+
+GENTEMP 
+"&optional prefix package"
+"[Function]"
+"creates and returns a new symbol interned in package (which defaults to *package*), guaranteeing
+that the symbol will be a new one not already in package."
+
+GET 
+"symbol property &optional default"
+"[Function]"
+"searches the property list of symbol for property (using eq to test). Returns the property value if
+found; otherwise returns default-value if specified, or nil if no default-value is specified. get may be
+combined with setf to add or change a property."
+
+GET-DECODED-TIME  
+NIL
+"[Function]"
+"returns 9 values giving the current time in Decoded Time format. The 9 values are seconds, minutes,
+hours, date, month, year, day-of-week, daylight-saving-time-p, and time-zone."
+
+GET-DISPATCH-MACRO-CHARACTER 
+"disp-char sub-char &optional readtable"
+"[Function]"
+"returns the function associated with sub-char under disp-char in readtable (which defaults to
+*readtable*)."
+
+#|
+GET-INTERNAL-REAL-TIME  
+NIL
+"[Function]"
+"returns an integer representing, in Internal Time format, the amount of time since your Macintosh
+computer has been turned on."
+
+GET-INTERNAL-RUN-TIME  
+NIL
+"[Function]"
+"returns an integer representing, in Internal Time format, the amount of time since your Macintosh
+computer has been turned on during which Macintosh Common Lisp computation took place."
+|#
+
+GET-MACRO-CHARACTER 
+"char &optional readtable"
+"[Function]"
+"returns two values, the function associated with char in readtable (which defaults to *readtable*),
+and a second value that is the non-terminating-p flag."
+
+GET-OUTPUT-STREAM-STRING 
+"string-output-stream"
+"[Function]"
+"returns a string containing all characters written to string-output-stream and resets the stream."
+
+GET-PROPERTIES 
+"plist indicator-list"
+"[Function]"
+"searches plist for any one of the properties from indicator-list. Returns three values: the first found
+property, its value, and the portion of plist that has yet to be searched. If no property is found, all
+three values are nil."
+
+GET-SETF-METHOD 
+"form &optional environment"
+"[Function]"
+"returns five values constituting the setf method for form in environment."
+
+GET-SETF-METHOD-MULTIPLE-VALUE 
+"form &optional environment"
+"[Function]"
+"returns five values constituting the setf method for form in environment. Used (instead of
+get-setf-method) when multiple values may be stored into a generalized variable."
+
+GET-UNIVERSAL-TIME  
+NIL
+"[Function]"
+"returns the current time as a single integer in Universal Time format. This integer can be decoded
+with decode-universal-time."
+
+GETF 
+"place indicator &optional default"
+"[Function]"
+"searches the property list stored in place for an indicator eq to indicator. Returns the corresponding
+value if indicator matches; otherwise returns default, if specified, or nil. place may be computed
+from a generalized variable acceptable to setf."
+
+GETHASH 
+"key hash-table &optional default"
+"[Function]"
+"returns the value of key in hash-table, or default if key is not entered in hash-table. default is nil if
+not specified. This function can be used with setf to enter a value into a hash table."
+
+GO 
+"tag"
+"[Special Form]"
+"transfers control to the position in a tagbody referred to by tag."
+
+GRAPHIC-CHAR-P 
+"char"
+"[Function]"
+"returns true if char is a printing character (as opposed to formatting or control character),
+otherwise false. char must be a character."
+
+HANDLER-BIND 
+"({(typespec handler)}*) {form}*"
+"[Macro]"
+"executes body in a dynamic context where the given handler bindings are in effect. Each typespec may
+be any type specifier. Each handler should evaluate to a function to be used to handle conditions of the
+given type(s) during execution of form. The function should take a single argument, the condition
+being signaled."
+
+HASH-TABLE-COUNT 
+"hash-table"
+"[Function]"
+"returns the number of entries in hash-table."
+
+HASH-TABLE-P 
+"thing"
+"[Function]"
+"returns true if thing is a hash table, otherwise false."
+
+HOST-NAMESTRING 
+"pathname"
+"[Function]"
+"returns the host portion of pathname, in the form of a string."
+
+IDENTITY 
+"thing"
+"[Function]"
+"returns thing, unaltered."
+
+IF 
+"testform thenform [elseform]"
+"[Special Form]"
+"evaluates testform. If the result is true, evaluates thenform and returns the result; if the result is
+nil, evaluates elseform and returns the result."
+
+IMAGPART 
+"number"
+"[Function]"
+"returns the imaginary part of number."
+
+IMPORT 
+"symbols &optional package"
+"[Function]"
+"imports symbols (which should be a symbol or list of symbols) into package (which defaults to
+*package*), so that they can referenced without the qualifying colon syntax."
+
+IN-PACKAGE 
+"package-name"
+"[Macro]"
+"sets *package* to the package whose name is package-name. An error is signaled if the package does
+not exist. package-name must be a symbol or string; if it is a symbol, the symbol's print-name is
+used."
+
+INCF 
+"place &optional delta"
+"[Function]"
+"increases the value in place (which can be any setf-able location) by delta (which defaults to 1)."
+
+INITIALIZE-INSTANCE 
+"instance &rest initargs"
+"[Generic Function]"
+"called by make-instance to initialize a newly created instance."
+
+INPUT-STREAM-P 
+"thing"
+"[Function]"
+"returns true if stream is a stream which can handle input operations, otherwise returns nil."
+
+INSPECT 
+"thing"
+"[Function]"
+"inspects thing, any Lisp data object."
+
+INTEGER-DECODE-FLOAT 
+"float"
+"[Function]"
+"returns three values: the significand scaled to be an integer, the exponent, and the sign of float."
+
+INTEGERP 
+"object"
+"[Function]"
+"returns true if object is an integer; otherwise returns false."
+
+INTERN 
+"string &optional package"
+"[Function]"
+"searches package (a package object or package name, defaulting to the current package) and all
+inherited packages for the symbol named by string. If not found, it creates and interns such a symbol.
+Returns two values, the found or new symbol, and a Boolean value indicating whether the symbol
+already existed (t indicates that it existed, nil that it was created)."
+
+#|
+INTERNAL-TIME-UNITS-PER-SECOND  
+NIL "[Constant]"
+"an integer that is the number of Macintosh Common Lisp internal time units per second."
+|#
+
+INTERSECTION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns the intersection of list1 and list2, that is, a list of those elements which are in both list1 and
+list2. If either list has duplicate entries, the redundant entries may or may not appear in the result.
+list1 and list2 are not modified."
+
+ISQRT 
+"integer"
+"[Function]"
+"returns the integer square root of integer."
+
+KEYWORDP 
+"thing"
+"[Function]"
+"returns true if thing is a symbol in the keyword package. Every symbol that is a keyword is written
+with a leading colon and always evaluates to itself."
+
+LABELS 
+"({(name lambda-list {declaration | doc-string}* {function-body-form}*)}*)
+{labels-body-form}*"
+"[Special Form]"
+"creates local function definitions whose scope encompasses both the body and the function definitions
+themselves. If there are global functions with the same names, the local definitions take precedence
+within the body of the labels. That is, labels can be used to define mutually recursive functions, while
+flet cannot; but a local function definition with flet can refer to the global definition, while one with
+labels cannot."
+
+LAMBDA 
+"lambda-list {declarations}* {form}*"
+"[Special Form]"
+"indicates a function with parameters specified by lambda-list and body specified by forms."
+
+#|
+LAMBDA-LIST-KEYWORDS  
+NIL "[Constant]"
+"a list of all the lambda-list keywords used in Macintosh Common Lisp, including the additional ones
+used only by defmacro."
+|#
+
+LAMBDA-PARAMETERS-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the number of distinct parameter names that
+may appear in a single lambda list."
+
+LAST 
+"list &optional count"
+"[Function]"
+"returns the last count conses of list."
+
+LCM 
+"&rest integers"
+"[Function]"
+"returns the least common multiple of its arguments."
+
+LDB 
+"bytespec integer"
+"[Function]"
+"returns the byte of integer specified by bytespec."
+
+LDB-TEST 
+"bytespec integer"
+"[Function]"
+"returns true if any of the bits in the specified bytespec of integer are 1's."
+
+LDIFF 
+"list sublist"
+"[Function]"
+"returns a new list containing the portion of list prior to sublist, which should be a cons appearing in
+list. If sublist does not appear in list, a copy of the entire list is returned."
+
+#|
+LEAST-NEGATIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the negative double-float floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-NEGATIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the negative long-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-NEGATIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the negative short-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-NEGATIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"The negative floating-point number closest in value, but not equal to, zero in Macintosh Common Lisp."
+
+LEAST-POSITIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the positive double-float floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-POSITIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the positive long-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-POSITIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the positive short-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-POSITIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"the negative floating-point number closest in value, but not equal to, zero in Macintosh Common Lisp."
+|#
+
+LENGTH 
+"sequence"
+"[Function]"
+"returns the number of elements in sequence."
+
+LET 
+"({variable | (variable value) }*) {declaration}* {form}*"
+"[Special Form]"
+"creates a binding for each variable (in parallel) and evaluates forms in the resulting environment.
+Returns the value of the last form."
+
+LET* 
+"({variable | (variable value) }*) {declaration}* {form}*"
+"[Special Form]"
+"creates a binding for each variable (sequentially) and evaluates forms in the resulting environment.
+This sequential binding allows the expression for the value of a variable to refer to variables bound
+earlier in the let* form. Returns the value of the last form."
+
+#|
+LISP-IMPLEMENTATION-TYPE  
+NIL
+"[Function]"
+"returns the string \"Macintosh Common Lisp\"."
+
+LISP-IMPLEMENTATION-VERSION  
+NIL
+"[Function]"
+"returns the version of Macintosh Common Lisp."
+|#
+
+LIST 
+"&rest arguments"
+"[Function]"
+"constructs and returns a list containing arguments as its elements."
+
+LIST* 
+"object &rest more-objects"
+"[Function]"
+"constructs and returns a list containing object and more-objects. Unlike list, list* places the last
+more-objects in the final cdr of the list. If the last argument to list* is an atom, this will result in a
+dotted list; if the last argument is a list, it will have the effect of appending the other arguments to
+this list."
+
+LIST-ALL-PACKAGES  
+NIL
+"[Function]"
+"returns a list of all packages that currently exist in the Lisp system."
+
+LIST-LENGTH 
+"list"
+"[Function]"
+"returns the length of list as an integer, or nil if list is a circular list."
+
+LISTEN 
+"&optional input-stream"
+"[Function]"
+"returns true if a character is immediately available from input-stream. Returns nil if a character is
+not available or the stream is at end-of-file."
+
+LISTP 
+"object"
+"[Function]"
+"returns true if object is a cons or the empty list; otherwise returns false. listp returns true on the
+empty list. This is the only difference between listp and consp. listp does not check whether the list is
+terminated by nil or is a dotted list."
+
+#|
+LOAD 
+"filename &key :verbose :print :if-does-not-exist :foreign-files :system-libraries
+:unreferenced-lib-names"
+"[Function]"
+"loads the file named by filename into the Macintosh Common Lisp environment. This is equivalent to
+opening an editor buffer to the file and evaluating all the forms in the buffer (which is equivalent to
+typing the forms into the Listener)."
+|#
+
+LOCALLY 
+"{declaration}* {form}*"
+"[Special form]"
+"executes forms with the declarations in effect. When a locally form appears at top level, the forms in
+its body are processed as top-level forms. This function may be used to wrap declarations around a
+defun or defmacro."
+
+LOG 
+"number &optional base"
+"[Function]"
+"returns the logarithm of number in base."
+
+LOGAND 
+"&rest integers"
+"[Function]"
+"returns the bit-wise logical ÒandÓ of its arguments. If no argument is given, then the result is -1."
+
+LOGANDC1 
+"integer1 integer2"
+"[Function]"
+"returns (logand (lognot integer1) integer2)."
+
+LOGANDC2 
+"integer1 integer2"
+"[Function]"
+"returns (logand integer1 (lognot integer2))."
+
+LOGBITP 
+"index integer"
+"[Function]"
+"returns true if the bit in integer whose index is index is a one-bit; return nil if it is a zero bit. The
+rightmost bit of integer is bit 0."
+
+LOGCOUNT 
+"integer"
+"[Function]"
+"returns the number of ÒonÓ bits in integer. If integer is positive, then the one bits in its binary
+representation are counted; if integer is negative, then the zero bits in the twoÕs-complement
+representation are counted."
+
+LOGEQV 
+"&rest integers"
+"[Function]"
+"returns the logical-exclusive-nor of the integers."
+
+LOGIOR 
+"&rest integers"
+"[Function]"
+"returns the bit-wise logical inclusive ÒorÓ of its arguments. If no argument is given, then the result
+is 0."
+
+LOGNAND 
+"integer1 integer2"
+"[Function]"
+"returns (lognot (logand integer1 integer2))."
+
+LOGNOR 
+"integer1 integer2"
+"[Function]"
+"returns the logical nor of integer1 and integer2. Each bit that is a 0 in both integer1 and integer2
+will be a 1 in the result."
+
+LOGNOT 
+"integer"
+"[Function]"
+"returns the bit-wise logical ÒnotÓ of its argument. Every bit of the result is the complement of the
+corresponding bit in the argument."
+
+LOGORC1 
+"integer1 integer2"
+"[Function]"
+"returns (logior (lognot integer1) integer2)."
+
+LOGORC2 
+"integer1 integer2"
+"[Function]"
+"returns (logior integer1 (lognot integer2))."
+
+LOGTEST 
+"integer1 integer2"
+"[Function]"
+"returns true if any of the 1 bits in integer1 are also 1 bits in integer2."
+
+LOGXOR 
+"&rest integers"
+"[Function]"
+"returns the bit-wise logical exclusive ÒorÓ of its arguments. If no argument is given, then the result
+is 0."
+
+LONG-FLOAT-EPSILON  
+NIL "[Constant]"
+"the smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+LONG-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+LONG-SITE-NAME  
+NIL
+"[Function]"
+"returns a string giving the full name of the site at which the Lisp is running. This function should be
+redefined by the user."
+
+LOOP 
+"{form}*"
+"[Macro]"
+"repeatedly evaluates+ forms. loop will continue until explicitly terminated by a throw, return, or
+go. A set of extensions to loop is documented in Common Lisp: The Language, chapter 26."
+
+
+LOOP-FINISH 
+"()"
+"[macro]"
+"Causes the iteration to terminate \"normally\", the same as implicit
+termination by an iteration driving clause, or by use of WHILE or
+UNTIL -- the epilogue code (if any) will be run, and any implicitly
+collected result will be returned as the value of the LOOP."
+
+LOWER-CASE-P 
+"char"
+"[Function]"
+"returns true if char is a lowercase character; otherwise returns false. char must be a character."
+
+#|
+MACHINE-INSTANCE  
+NIL
+"[Function]"
+"returns the name of the machine running Macintosh Common Lisp; this might be a local nickname or
+a serial number. This function should be redefined by the user."
+
+MACHINE-TYPE  
+NIL
+"[Function]"
+"returns the type of Macintosh computer running Macintosh Common Lisp."
+
+MACHINE-VERSION  
+NIL
+"[Function]"
+"returns a string that identifies the version of the current hardware running Macintosh Common Lisp."
+|#
+
+MACRO-FUNCTION 
+"symbol &optional environment"
+"[Function]"
+"returns the macro expansion function of the global macro definition associated with symbol. If
+symbol does not name a macro, returns nil."
+
+MACROEXPAND 
+"form &optional environment"
+"[Function]"
+"expands form repeatedly within environment until it is no longer a macro call, and returns the
+expansion and a second value, t if form was a macro call and nil if it was not."
+
+MACROEXPAND-1 
+"form &optional environment"
+"[Function]"
+"returns the result of expanding form oncewithin environment . Returns the expansion and a second
+value, t if the form was a macro call and nil if it was not."
+
+MACROLET 
+"({(name lambda-list {declaration | doc-string}* {form}*)}*) {form}*"
+"[Special Form]"
+"constructs one or more local macro definitions. macrolet is equivalent to flet except that it generates
+macro definitions rather than functions. the value of the last form is returned."
+
+MAKE-ARRAY 
+"dimensions &key :element-type :initial-element :initial-contents :adjustable
+:fill-pointer :displaced-to :displaced-index-offset"
+"[Function]"
+"constructs and returns an array. dimensions should be an integer or a list of integers."
+
+MAKE-BROADCAST-STREAM 
+"&rest stream"
+"[Function]"
+"returns an output stream which sends its output to all the given streams and returns the result of
+performing the operation on the last stream; all other values are discarded."
+
+MAKE-CONCATENATED-STREAM 
+"&rest streams"
+"[Function]"
+"returns an input stream that reads from streams in sequence; when one stream is at end-of-file, the
+function takes input from the next."
+
+MAKE-DISPATCH-MACRO-CHARACTER 
+"char &optional non-terminating-p readtable"
+"[Function]"
+"makes the character char a dispatching macro character in readtable (which defaults to *readtable*).
+If non-terminating-p is nil (the default), char is a terminating macro character; otherwise it is
+non-terminating and may be embedded within extended tokens."
+
+MAKE-ECHO-STREAM 
+"input-stream output-stream"
+"[Function]"
+"returns a stream that gets input from input-stream and sends output to output-stream. In addition,
+all input received is echoed to output-stream."
+
+MAKE-HASH-TABLE 
+"&key :test :size :rehash-size :rehash-threshold :weak :hash-function"
+"[Function]"
+"creates and returns a new hash table. :test should be one of the values #`eq, #`eql, #`equal, or
+#`equalp, or one of the symbols eq, eql, equal or equalp."
+
+MAKE-INSTANCE 
+"class &rest initargs"
+"[Generic Function]"
+"creates a new instance of the given class."
+
+MAKE-LIST 
+"size &key :initial-element"
+"[Function]"
+"returns a list containing size elements, each of which is intialized to :initial-element. size should be
+a non-negative integer; the default value of :initial-element is nil."
+
+MAKE-LOAD-FORM 
+"object"
+"[Generic Function]"
+"returns two values, a form that, when evaluated at load time, returns an object that is equivalent to
+object, and a form that, when evaluated at load time, performs further initialization of object. See
+Common Lisp: The Language, pages 659-662."
+
+MAKE-LOAD-FORM-SAVING-SLOTS 
+"object &optional slots"
+"[Generic Function]"
+"returns two values suitable for return from a make-load-form method. The first argument is the
+object; the optional second argument is a list of the names of slots to preserve. It defaults to all of the
+local slots."
+
+MAKE-PACKAGE 
+"package-name &key :nicknames :use :internal-size :external-size"
+"[Function]"
+"creates and returns a package named package-name, which may be either a string or symbol. If it is a
+symbol, the symbol's print-name is used. The list :nicknames contains strings that serve as
+alternative names; :use is a list of packages whose external symbols are inherited by the new
+package. The default value of :use is the value of the variable *make-package-use-defaults* which is
+initially (\"COMMON-LISP\" \"CCL\")."
+
+MAKE-PATHNAME 
+"&key :host :device :directory :name :type :version :defaults :case"
+"[Function]"
+"creates and returns a pathname with components based on the arguments."
+
+MAKE-RANDOM-STATE 
+"&optional state"
+"[Function]"
+"returns a new random state object, based on state (which defaults to *random-state*). If state is nil
+or omitted, the current random state object is copied; if it is t, a completely fresh random state is
+generated."
+
+MAKE-SEQUENCE 
+"type size &key :initial-element"
+"[Function]"
+"creates and returns a sequence of type with length size."
+
+MAKE-STRING 
+"size &key :initial-element :element-type"
+"[Function]"
+"returns a simple string of length size, each character of which is initialized to :initial-element. The
+:element-type argument names the type of the elements of the stream; its default is character."
+
+MAKE-STRING-INPUT-STREAM 
+"string &optional start end"
+"[Function]"
+"creates and returns an input stream of type string-stream that reads from string."
+
+MAKE-STRING-OUTPUT-STREAM 
+"&key :element-type"
+"[Function]"
+"creates and returns an output stream that accumulates all output given it in a string-stream for the
+benefit of get-output-stream-string. The :element-type argument specifies what characters must be
+accepted by the created stream; if the argument is omitted the stream must accept all characters."
+
+MAKE-SYMBOL 
+"print-name"
+"[Function]"
+"creates and returns an uninterned symbol with name print-name."
+
+MAKE-SYNONYM-STREAM 
+"symbol"
+"[Function]"
+"returns a synonym stream associated with symbol. Any operations performed on the stream will act
+on the stream that is (at that point) bound to symbol. symbol may be bound to a new stream, and the
+operations will act on the new stream."
+
+MAKE-TWO-WAY-STREAM 
+"input-stream output-stream"
+"[Function]"
+"returns a bidirectional stream that receives input from input-stream and sends output to
+output-stream."
+
+MAKUNBOUND 
+"symbol"
+"[Function]"
+"causes the dynamic (special) variable symbol to become unbound (have no value). makunbound
+returns symbol."
+
+MAP 
+"result-type function sequence &rest more-sequences"
+"[Function]"
+"applies function to the first element of each sequence, then the second element of each, and so on until
+the end of the shortest sequence is reached. The results of the function calls are collected in a
+sequence of type result-type. If the result-type is nil, the results are not collected and nil is
+returned."
+
+MAPC 
+"function list &rest more-lists"
+"[Function]"
+"applies function to the elements of list and more-lists. The results are not stored. list is returned. If
+the lists are not all the same length, the iteration terminates when the shortest list runs out.
+function can be only of type symbol or function."
+
+MAPCAN 
+"function list &rest more-lists"
+"[Function]"
+"applies function to the car of list and more-lists, then to the cadr, and so on. The results, which must
+be lists, are combined using nconc. If the lists are not all the same length, the iteration terminates
+when the shortest list runs out. function can be only of type symbol or function."
+
+MAPCAR 
+"function list &rest more-lists"
+"[Function]"
+"applies function to the car of list and more-lists, then to the cadr, and so on. The results are collected
+into a list, which is returned. If the lists are not all the same length, the iteration terminates when
+the shortest list runs out. function can be only of type symbol or function."
+
+MAPCON 
+"function list &rest more-lists"
+"[Function]"
+"applies function first to list and more-lists, and then to successive cdrs of list and more-lists. The
+results, which must be lists, are combined using nconc. If the lists are not all the same length, the
+iteration terminates when the shortest list runs out. function can be only of type symbol or function."
+
+MAPHASH 
+"function hash-table"
+"[Function]"
+"calls function for each entry in hash-table, passing as arguments both the key and the value. Entries
+should not be added or removed while maphash is in progress. maphash returns nil."
+
+MAPL 
+"function list &rest more-lists"
+"[Function]"
+"applies function first to list and more-lists, and then to successive cdrs of list and more-lists. The
+results are not stored (i.e. the operation is only for side-effect). list is returned. If the lists are not
+all the same length, the iteration terminates when the shortest list runs out. function can be only of
+type symbol or function."
+
+MAPLIST 
+"function list &rest more-lists"
+"[Function]"
+"applies function first to list and more-lists, and then to successive cdrs of list and more-lists. The
+results are collected into a list, which is returned. If the lists are not all the same length, the
+iteration terminates when the shortest list runs out. function can be only of type symbol or function."
+
+MASK-FIELD 
+"bytespec integer"
+"[Function]"
+"returns an integer all of whose bits are zero but the byte specified in bytespec; that byte is the same
+as the one at bytespec pin integer."
+
+MAX 
+"number &rest more-numbers"
+"[Function]"
+"returns the largest of numbers."
+
+MEMBER 
+"item list &key :test :test-not :key"
+"[Function]"
+"searches list for a top-level element that matches item. If a match is successful, member returns the
+rest of the list starting with the element that matched item; otherwise returns nil."
+
+MEMBER-IF 
+"test list &key :key"
+"[Function]"
+"searches list for the first top-level element satisfying test. If one is found, the rest of the list
+(beginning with that element) is returned. If none are found, nil is returned."
+
+MEMBER-IF-NOT 
+"test list &key :key"
+"[Function]"
+"searches list for the first top-level element that fails to satisfy test. If such an element is found, the
+rest of the list (beginning with that element) is returned, otherwise nil is returned."
+
+MERGE 
+"result-type sequence1 sequence2 predicate &key :key"
+"[Function]"
+"destructively merges sequence1 and sequence2 into a new sequence of type result-type. result-type
+must be a subtype of sequence."
+
+MERGE-PATHNAMES 
+"pathname &optional defaults default-version"
+"[Function]"
+"creates a new pathname resulting from merging pathname with defaults (which defaults to
+*default-pathname-defaults*). pathname may be a pathname, a string, or a stream that is or was
+open to a file; if defaults is a logical pathname, pathname may be a logical pathname namestring."
+
+MIN 
+"number &rest more-numbers"
+"[Function]"
+"returns the smallest of numbers."
+
+MINUSP 
+"number"
+"[Function]"
+"returns true if number is strictly less than zero; otherwise returns nil. number must be a
+non-complex number."
+
+MISMATCH 
+"sequence1 sequence2 &key :from-end :test :test-not :key :start1 :start2 :end1 :end2"
+"[Function]"
+"compares the elements of the specified portions of sequence1 and sequence2. If two elements do not
+match, the index within sequence1 of the leftmost position at which the elements fail to match is
+returned. If all elements match, nil is returned."
+
+MOD 
+"number divisor"
+"[Function]"
+"returns the root of number modulo divisor. The result will have the same sign as divisor."
+
+#|
+MOST-NEGATIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the double-float floating-point number closest in value, but not equal to, minus infinity in Macintosh
+Common Lisp."
+
+MOST-NEGATIVE-FIXNUM  
+NIL "[Constant]"
+"The fixnum closest to minus infinity in Macintosh Common Lisp."
+
+MOST-NEGATIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the long-float floating-point number closest in value, but not equal to, minus infinity in Macintosh
+Common Lisp."
+
+MOST-NEGATIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the short-float floating-point number closest in value, but not equal to, minus infinity in Macintosh
+Common Lisp."
+
+MOST-NEGATIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"the floating-point number closest in value, but not equal to, minus infinity in Macintosh Common
+Lisp."
+
+MOST-POSITIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the double-float floating-point number closest in value, but not equal to, infinity in Macintosh
+Common Lisp."
+
+MOST-POSITIVE-FIXNUM  
+NIL "[Constant]"
+"the fixnum closest in value, but not equal to, infinity in Macintosh Common Lisp."
+
+MOST-POSITIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the long-float floating-point number closest in value, but not equal to, infinity in Macintosh Common
+Lisp."
+
+MOST-POSITIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the short-float floating-point number closest in value, but not equal to, infinity in Macintosh
+Common Lisp."
+
+MOST-POSITIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"the floating-point number closest in value, but not equal to, infinity in Macintosh Common Lisp."
+|#
+
+MULTIPLE-VALUE-BIND 
+"({var}*) values-form {declaration}* {form}*"
+"[Macro]"
+"evaluates values-form, and binds the multiple values returned to the vars. The forms are evaluated
+in the resulting environment. The value of the last form is returned."
+
+MULTIPLE-VALUE-CALL 
+"function {form}*"
+"[Special Form]"
+"calls function, passing as arguments all the multiple values returned by forms. The first argument
+(function) is evaluated."
+
+MULTIPLE-VALUE-LIST 
+"form"
+"[Macro]"
+"collects the multiple values returned by form, and returns them in a list."
+
+MULTIPLE-VALUE-PROG1 
+"form {more-forms}*"
+"[Special Form]"
+"evaluates form, and saves the values it returns. Then evaluates more-forms, discarding their
+returned values. When done, returns the values returned by form."
+
+MULTIPLE-VALUE-SETQ 
+"({var}*) form"
+"[Macro]"
+"calls form, and uses the returned multiple values to set (not bind) the vars."
+
+MULTIPLE-VALUES-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the number of values that may be returned
+from a function."
+
+NAME-CHAR 
+"name"
+"[Function]"
+"returns the character with name name, or nil if there is no such character."
+
+NAMESTRING 
+"pathname"
+"[Function]"
+"returns a string representation of pathname, which may be a pathname, a string, or a stream that is
+or was open to a file."
+
+NBUTLAST 
+"list &optional num"
+"[Function]"
+"destructively modifies list to remove the last num elements. num defaults to 1. If list is shorter than
+num, the empty list is returned and list is not modified. (Therefore one normally writes (setq a
+(nbutlast a)) rather than (nbutlast a).)"
+
+NCONC 
+"&rest lists-or-thing"
+"[Function]"
+"concatenates lists destructively and returns the resulting list. The lists are not copied, but are
+destructively altered in place. nconc is the destructive equivalent of append."
+
+#|
+NIL  
+NIL "[Constant]"
+"the false value in Common Lisp. nil is a symbol, a constant, the Boolean false, a data type, a logical
+operator, an object of type null, and the usual terminator of a list. It is also equivalent to the empty
+list. It is no longer equivalent to Pascal null, which in Macintosh Common Lisp is now equivalent to
+the macptr %null-ptr."
+|#
+
+NINTERSECTION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns the intersection of list1 and list2, that is, a list of those elements which are in both list1 and
+list2. If either list has duplicate entries, the redundant entries may or may not appear in the result.
+list1 and list2 may be modified by the process. (nintersection is the destructive form of
+intersection.)"
+
+NINTH 
+"list"
+"[Function]"
+"returns the ninth element of list, using one-based addressing."
+
+NOT 
+"object"
+"[Function]"
+"returns true if object is nil; otherwise returns false. It inverts its argument considered as a Boolean
+value."
+
+NOTANY 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"applies predicate to succesive elements of sequence and more-sequences until a call returns non-nil.
+If a call returns non-nil, notany returns false. If no call returns true, notany returns non-nil.
+predicate must take as many arguments as there are sequences."
+
+NOTEVERY 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"applies predicate to succesive elements of sequence and more-sequences until a call returns nil. If a
+call returns nil, notevery immediately returns a non-nil value. If all calls return true, notevery
+returns nil. predicate must take as many arguments as there are sequences."
+
+NRECONC 
+"list-1 list-2"
+"[Function]"
+"reverses list-1, and places its elements (reversed) at the head of list-2. list-1 is destructively
+modified. This function has exactly the same side-effect behavior as (nconc (nreverse x) y) but is
+potentially more efficient."
+
+NREVERSE 
+"sequence"
+"[Function]"
+"returns a sequence with the elements of sequence reversed. The original sequence may be modified."
+
+NSET-DIFFERENCE 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list of elements in list1 that are not elements of list2. list1 and list2 may be modified by
+the process. (nset-difference is the destructive form of set-difference.)"
+
+NSET-EXCLUSIVE-OR 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing those elements that are in list1 or in list2 but are not in both. list1 and
+list2 may be modified by the process. (nset-exclusive-or is the destructive form of
+set-exclusive-or.)"
+
+NSTRING-CAPITALIZE 
+"string &key :start :end"
+"[Function]"
+"destructively modifies the given portion of string, capitalizing all words."
+
+NSTRING-DOWNCASE 
+"string &key :start :end"
+"[Function]"
+"destructively modifies the given portion of string, converting all uppercase characters to lowercase."
+
+NSTRING-UPCASE 
+"string &key :start :end"
+"[Function]"
+"destructively modifies the given portion of string, converting all lowercase characters to uppercase."
+
+NSUBLIS 
+"a-list tree &key :test :test-not :key"
+"[Function]"
+"destructively modifies tree, replacing elements that appear as keys in a-list with the corresponding
+value from a-list. In effect, nsublis can perform several nsubst operations simultaneously."
+
+NSUBST 
+"new old tree &key :test :test-not :key"
+"[Function]"
+"destructively modifies tree, replacing occurrences of old with new."
+
+NSUBST-IF 
+"new test tree &key :key"
+"[Function]"
+"destructively modifies tree, replacing elements that satisfy test with new."
+
+NSUBST-IF-NOT 
+"new test tree &key :key"
+"[Function]"
+"destructively modifies tree, replacing elements that don't satisfy test with new."
+
+NSUBSTITUTE 
+"new-item old-item sequence &key :start :end :from-end :count :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that occurrences of old-item within a given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence may be modified. This is the destructive
+equivalent of substitute."
+
+NSUBSTITUTE-IF 
+"new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements which satisfy test within the given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence may be modified. This is the destructive
+equivalent of substitute-if."
+
+NSUBSTITUTE-IF-NOT "new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements which do not satisfy test within the
+given subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence may be modified. This is the destructive
+equivalent of substitute-if-not."
+
+NTH 
+"n list"
+"[Function]"
+"returns the nth element of list (where the car of list is the \"zeroth\" element )."
+
+NTHCDR 
+"n list"
+"[Function]"
+"performs the cdr operation n times on list and returns the result."
+
+NULL 
+"thing"
+"[Function]"
+"returns true if thing is the empty list (), otherwise returns nil. This is equivalent to the function
+not, except that null is normally used to check for the empty list and not to invert. The programmer
+can express intent by choice of function name."
+
+NUMBERP 
+"object"
+"[Function]"
+"returns true if object is a number; otherwise returns false. More specific numeric data type tests
+include integerp, rationalp, floatp, and complexp."
+
+NUMERATOR 
+"rational"
+"[Function]"
+"returns the numerator of the canonical reduced form of rational."
+
+NUNION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing the union of the elements list1 and list2. Any element that is contained in
+list1 or list2 will be contained in the result list. list1 and list2 may be modified by the process.
+(nunion is the destructive form of union.)"
+
+ODDP 
+"integer"
+"[Function]"
+"returns true if integer is odd (not evenly divisible by two); otherwise returns nil."
+
+OPEN 
+"filename &key :direction :element-type :if-exists :if-does-not-exist :external-format :fork
+:mac-file-creator"
+"[Function]"
+"opens a stream to the file specified by filename, which may be a string, a pathname, a logical
+pathname, or a stream."
+
+OR 
+"{form}*"
+"[Macro]"
+"evaluates each form sequentially. If or reaches a form that returns non-nil, it returns the value of
+that form without evaluating any more forms. If it reaches the last form, it returns that form's value."
+
+OUTPUT-STREAM-P 
+"thing"
+"[Function]"
+"returns true if thing is a stream which can handle output, otherwise returns nil."
+
+PACKAGE-NAME 
+"package"
+"[Function]"
+"returns the name of package as a string, or nil if applied to a deleted package."
+
+PACKAGE-NICKNAMES 
+"package"
+"[Function]"
+"returns a list of the nickname strings of package. This will not include the primary name."
+
+PACKAGE-SHADOWING-SYMBOLS 
+"package"
+"[Function]"
+"returns a list of symbols which have been declared (by shadow or shadowing-import) as shadowing
+symbols in package."
+
+PACKAGE-USE-LIST 
+"package"
+"[Function]"
+"returns a list of packages used by package."
+
+PACKAGE-USED-BY-LIST 
+"package"
+"[Function]"
+"returns a list of all the packages that use package."
+
+PACKAGEP 
+"thing"
+"[Function]"
+"returns true if thing is a package, otherwise false."
+
+PAIRLIS 
+"keys data &optional a-list"
+"[Function]"
+"creates an a-list associated matching elements from the lists keys and data. This a-list is appended to
+a-list. It is an error if the lists keys and data are not the same length."
+
+PARSE-INTEGER 
+"string &key :start :end :radix :junk-allowed"
+"[Function]"
+"reads and returns an integer from the indicated portion of string. Returns a second value that is the
+index into the string of the delimiter that terminated the parse, or the index beyond the substring if
+the parse terminated at the end of the substring. An error is signaled if the substring cannot be
+parsed as an integer."
+
+PARSE-NAMESTRING 
+"thing &optional host defaults &key :start :end :junk-allowed"
+"[Function]"
+"parses thing to a pathname. thing is usually a string, but may be a logical pathname, pathname, or
+stream. The host and defaults arguments are used only to determine pathname syntax, not for
+supplying default pathname components."
+
+PATHNAME 
+"thing"
+"[Function]"
+"coerces thing to a pathname, which it returns. thing should be a pathname, string, or stream."
+
+PATHNAME-DEVICE 
+"pathname &key :case"
+"[Function]"
+"returns the device component of pathname."
+
+PATHNAME-DIRECTORY 
+"pathname &key :case"
+"[Function]"
+"returns the directory component of pathname."
+
+PATHNAME-HOST 
+"pathname &key :case"
+"[Function]"
+"returns the host component of pathname."
+
+PATHNAME-NAME 
+"pathname &key :case"
+"[Function]"
+"returns the name component of pathname."
+
+PATHNAME-TYPE 
+"pathname &key :case"
+"[Function]"
+"returns the type component of pathname."
+
+PATHNAME-VERSION 
+"pathname"
+"[Function]"
+"returns the version component of pathname."
+
+PATHNAMEP 
+"thing"
+"[Function]"
+"returns true if thing is a pathname, otherwise false."
+
+PEEK-CHAR 
+"&optional peek-type input-stream eof-error-p eof-value recursive-p"
+"[Function]"
+"returns the next character of stream according to peek-type, and leaves the character in the input
+stream. peek-type may be nil (return next character), t (skip whitespace, then return next
+character) or a character (advance to first occurrence of the character)."
+
+PHASE 
+"number"
+"[Function]"
+"returns the angle part of the polar representation of number as a complex number. The return value
+is in radians."
+
+PI  
+NIL "[Constant]"
+"The best possible approximation of pi in floating-point format."
+
+PLUSP 
+"number"
+"[Function]"
+"returns true if number is strictly greater than zero; otherwise returns nil. number must be a
+non-complex number."
+
+POP 
+"place"
+"[Macro]"
+"returns the car of the contents of place , which can be any generalized variable containing a list and
+acceptable as a generalized variable to setf. Sets place to point to the cdr of its previous contents. "
+
+POSITION 
+"item sequence &key :start :end :from-end :key :test :test-not"
+"[Function]"
+"returns the index of the first element of sequence that match item using the given test function;
+returns nil if no element matches."
+
+POSITION-IF 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the position of the first element in the given range of sequence that satisfies test, or nil if no
+element satisfies the test."
+
+POSITION-IF-NOT 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the position of the first element in the given range of sequence that does not satisfy test, or
+nil if all the elements satisfy test."
+
+PPRINT 
+"object &optional output-stream"
+"[Function]"
+"outputs a newline character and the pretty-print representation of object to output-stream. pprint
+returns no value. Common Lisp user-controlled pretty-printing is described in Common Lisp: The
+Language, 2d edition, Chapter 27."
+
+PRIN1 
+"object &optional output-stream"
+"[Function]"
+"outputs the printed representation of data-object to output-stream, using escape characters as
+appropriate. Returns object."
+
+PRIN1-TO-STRING 
+"thing"
+"[Function]"
+"thing is printed, as if by prin1, but the output is collected in a string, which is returned."
+
+PRINC 
+"object &optional output-stream"
+"[Function]"
+"outputs the printed representation of object to output-stream, without any escape characters.
+Returns object."
+
+PRINC-TO-STRING 
+"thing"
+"[Function]"
+"thing is printed, as if by princ, but the output is collected in a string, which is returned."
+
+PRINT 
+"object &optional output-stream"
+"[Function]"
+"outputs the printed representation of data object to output-stream, preceded by a newline and
+followed by a space. Returns object."
+
+PROBE-FILE 
+"pathname"
+"[Function]"
+"if pathname corresponds to an existing file or folder, returns its true name. If pathname does not
+correspond to an existing file or folder, returns nil."
+
+PROCLAIM 
+"declaration-spec"
+"[Function]"
+"provides a global declaration (called a proclamation) or a declaration that is computed by a program.
+proclaim returns nil."
+
+PROG 
+"({var | (var [init])}*) {declaration}* {tag | statement}*"
+"[Macro]"
+"binds the vars to the values of the inits in parallel (or to nil for vars with no corresponding init),
+and then executes the statements. The entire prog form is implicitly surrounded by a block named nil
+(so that return may be used at any time to exit from the construct), and the body is a tagbody. prog
+returns nil."
+
+PROG* 
+"({var | (var [init])}*) {declaration}* {tag | statement}*"
+"[Macro]"
+"binds the vars to the values of the inits in sequence (or to nil for vars with no corresponding init),
+and then executes the statements. The entire prog* form is implicitly surrounded by a block named
+nil (so that return may be used at any time to exit from the construct), and the body is a tagbody.
+prog* returns nil."
+
+PROG1 
+"{form}*"
+"[Macro]"
+"evaluates each form in order, left to right. The first form is evaluated and its value is stored; the
+other forms are evaluated, usually for their side effects; the value of the first form is then returned."
+
+PROG2 
+"{form}*"
+"[Macro]"
+"evaluates each form in order, left to right. The value of the second form is stored and returned."
+
+PROGN 
+"{form}*"
+"[Special Form]"
+"evaluates each form in order, left to right. The values of all forms but the last are discarded; the
+value of the last form is returned."
+
+PROGV 
+"symbols values {form}*"
+"[Special Form]"
+"binds one or more dynamic variables in the list symbols to the values in the list values. With these
+bindings in effect, the forms are executed. Both symbols and values are computed quantities, rather
+than stated explicitly."
+
+PROVIDE 
+"module"
+"[Function]"
+"adds a new module name to the list of modules maintained in the variable *modules*, indicating that
+the module module has been provided. provide is no longer part of the Common Lisp standard."
+
+PSETF 
+"{place newvalue}*"
+"[Macro]"
+"sets the contents of places to the corresponding newvalues. The assignments are done in parallel."
+
+PSETQ 
+"{variable form}*"
+"[Macro]"
+"sets the value of the current binding of each variable to the result of evaluating the corresponding
+form. The assignmentes are performed in parallel Returns nil."
+
+PUSH 
+"item place"
+"[Macro]"
+"conses item onto the list contained in place , which can be any generalized variable containing a list
+and acceptable as a generalized variable to setf. Stores the resulting list in place and returns the new
+contents of place."
+
+PUSHNEW 
+"item place &key :test :test-not :key"
+"[Macro]"
+"pushes item onto the list in place, if the list does not already contain item (as determined by :test).
+The modified list is returned."
+
+QUOTE 
+"object"
+"[Special Form]"
+"returns object , which may be any object, without evaluating it."
+
+RANDOM 
+"number &optional state"
+"[Function]"
+"returns a pseudo random number between zero (inclusive) and number (exclusive). state is an
+object of type random-state and defaults to the value of the variable *random-state*."
+
+RANDOM-STATE-P 
+"thing"
+"[Function]"
+"returns true if thing is a random state, otherwise false."
+
+RASSOC 
+"value a-list &key :test :test-not :key"
+"[Function]"
+"searches a-list for the first pair whose cdr matches value. Returns the pair, or nil if the search fails."
+
+RASSOC-IF 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose cdr satisfies predicate. Returns the pair, or
+nil if the search fails."
+
+RASSOC-IF-NOT 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose cdr does not satisfy predicate. Returns the
+pair, or nil if the search fails."
+
+RATIONAL 
+"number"
+"[Function]"
+"returns the rational representation of number, any non-complex number. With floating-point
+numbers, rational assumes that number is completely accurate and returns a rational number
+mathematically equal to the precise value of the floating-point number. Compare rationalize, which
+returns the best available approximation of number that keeps numerator and denominator small."
+
+RATIONALIZE 
+"number"
+"[Function]"
+"returns the rational representation of number, any non-complex number. With floating-point
+numbers, rationalize assumes that number is accurate only to the precision of the floating-point
+representation and returns the best available approximation of number, keeping numerator and
+denominator small. Compare rational, which returns the precise value."
+
+RATIONALP 
+"object"
+"[Function]"
+"returns true if object is a rational number; otherwise returns false. A rational number is any
+number expressible as the ratio of two integers."
+
+READ 
+"&optional input-stream eof-error-p eof-value recursivep"
+"[Function]"
+"reads the printed representation of a single object from input-stream, builds a corresponding
+object, and returns the object."
+
+READ-BYTE 
+"binary-input-stream &optional eof-errorp eof-value"
+"[Function]"
+"reads one byte from binary-input-stream and returns it in the form of an integer."
+
+READ-CHAR 
+"&optional input-stream eof-error-p eof-value recursive-p"
+"[Function]"
+"reads one character from input-stream, and returns the corresponding character object."
+
+READ-CHAR-NO-HANG 
+"&optional input-stream eof-errorp eof-value recursive-p"
+"[Function]"
+"reads and returns a character from input-stream if one is immediately available, otherwise
+immediately returns nil."
+
+READ-DELIMITED-LIST 
+"char &optional stream recursive-p"
+"[Function]"
+"reads objects from stream, ignoring whitespace and comments, until an occurrence of the character
+char is reached, then returns a list of all the objects it has read so far. char should not be a
+whitespace character."
+
+READ-FROM-STRING 
+"string &optional eof-error-p eof-value &key :start :end :preserve-whitespace"
+"[Function]"
+"reads and returns an expression, taking input from string. A second value returned indicates the
+index of the first character in string not read."
+
+READ-LINE 
+"&optional input-stream eof-error-p eof-value recursive-p"
+"[Function]"
+"reads a line of text terminated by a newline or end of file from input-stream and returns two values,
+the line as a character string and a Boolean value, t if the line was terminated by an end-of-file and
+nil if it was terminated by a newline."
+
+READ-PRESERVING-WHITESPACE 
+"&optional input-stream eof-errorp eof-value recursive-p"
+"[Function]"
+"performs the same operation as read, except that if recursive-p is nil or omitted, delimiting
+whitespace following a token is not discarded, but is retained at the head of the stream, where it can
+be read."
+
+READTABLEP 
+"thing"
+"[Function]"
+"returns t if thing is a readtable, nil if not."
+
+REALP 
+"object"
+"[Function]"
+"returns true if object is a real number; otherwise returns false."
+
+REALPART 
+"number"
+"[Function]"
+"returns the real part of number."
+
+REDUCE 
+"function sequence &key :start :end :from-end :initial-value :key"
+"[Function]"
+"combines the elements of sequence according to function and returns the result. (For example, a list
+of numbers can be combined by adding all the numbers together.)"
+
+REM 
+"number divisor"
+"[Function]"
+"returns the remainder of number divided by divisor. The result will have the same sign as number."
+
+REMF 
+"place property-name"
+"[Macro]"
+"removes the property with an indicator eq to indicator from the property list stored in place. The
+property indicator and its value are removed by destructively splicing the property list. Returns
+true if the property is found; otherwise returns nil. place can be any form acceptable to setf."
+
+REMHASH 
+"key hash-table"
+"[Function]"
+"removes the entry for key from the hash-table hash-table. Returns t if there was such an entry,
+otherwise nil."
+
+REMOVE 
+"item sequence &key :count :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a new sequence equivalent to sequence with occurrences of item removed. The original
+sequence is not modified. (The destructive counterpart of remove is delete.)"
+
+REMOVE-DUPLICATES 
+"sequence &key :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that all duplicate elements have been removed. The
+original sequence is not modified. The destructive version of this function is delete-duplicates."
+
+REMOVE-IF 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements in the given range that pass test are
+removed. The original sequence is not modified."
+
+REMOVE-IF-NOT 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements in the given range that fail test are
+removed. The original sequence is not modified."
+
+REMPROP 
+"symbol property-name"
+"[Function]"
+"removes property-name and its value from the property list of symbol. Returns true if the property
+was found and nil if the property was not found."
+
+RENAME-FILE 
+"old-pathname new-pathname &key :if-exists"
+"[Function]"
+"renames the last component of the specified old-pathname to the result of merging new-pathname
+with old-pathname. The :if-exists argument has the same meaning as for copy-file."
+
+RENAME-PACKAGE 
+"package new-name &optional new-nicknames"
+"[Function]"
+"the old name and nicknames of package are replaced by new-name and new-nicknames. new-name
+should be a string, a symbol (the symbol's print-name is used), or a package object. new-nicknames
+should be a string, a symbol, or a list of strings and symbols. package is returned."
+
+REPLACE 
+"destination-sequence source-sequence &key :start1 :end1 :start2 :end2"
+"[Function]"
+"destructively replaces elements in the specified portion of destination-sequence with the elements of
+the specified portion of source-sequence. Returns the modified destination-sequence."
+
+REQUIRE 
+"module &optional pathname"
+"[Function]"
+"attempts to load the files in module if they have not already been loaded. require is no longer part of
+the Common Lisp standard."
+
+REST 
+"list"
+"[Function]"
+"returns the cdr of list. rest can be used with setf to set the cdr of a list."
+
+RETURN 
+"[result-form]"
+"[Macro]"
+"used to return from a block or from constructs such as do and progn. Returns from a block named nil,
+and the block as a whole returns the value of result-form ). If result-form is not supplied, nil is
+returned."
+
+RETURN-FROM 
+"name [result-form]"
+"[Special Form]"
+"used to return from a block or from constructs such as do and progn. The function exits from the
+innermost block named name, and the block as a whole returns the value of result-form. If
+result-form is not supplied, nil is returned."
+
+REVAPPEND 
+"list thing"
+"[Function]"
+"appends the reverse of list to thing. This is equivalent to (append (reverse list) thing) but is
+potentially more efficient."
+
+REVERSE 
+"sequence"
+"[Function]"
+"returns a new sequence with the elements of sequence reversed. The original sequence is not modified."
+
+ROOM 
+"&optional detailedp"
+"[Function]"
+"prints information on the amount of space available in the Lisp operating system."
+
+ROTATEF 
+"&rest places"
+"[Function]"
+"rotates the contents of all the places to the left. The contents of the leftmost place is put into the
+rightmost place."
+
+ROUND 
+"number &optional divisor"
+"[Function]"
+"returns the integer nearest to number. If number is halfway between two integers (for example
+3.5), round converts number to the nearest integer divisible by 2. round returns a second value,
+which is the remainder of the rounding operation. When there is a second argument, round first
+divides divisor into number, and then applies round to the result."
+
+RPLACA 
+"cons object"
+"[Function]"
+"destructively alters cons so that its car points to object. Returns the modified cons."
+
+RPLACD 
+"cons object"
+"[Function]"
+"destructively alters cons so that its cdr points to object. Returns the modified cons."
+
+SBIT 
+"simple-bit-array &rest subscripts"
+"[Function]"
+"returns the bit in simple-bit-array indicated by the subscripts. This function can be used with setf
+to destructively replace a bit-array element."
+
+SCHAR 
+"string index"
+"[Function]"
+"returns the indexth character in string, which must be a simple string. This function can be used
+with setf to set a character in a simple string. Indexing is zero-origin."
+
+SEARCH 
+"sequence1 sequence2 &key :start1 :end1 :start2 :end2 :from-end :key :test :test-not"
+"[Function]"
+"searches sequence2 for a subsequence whose elements match those of sequence1. If successful,
+returns an index into sequence2 indicating the leftmost element of this subsequence. If not successful,
+returns nil."
+
+SECOND 
+"list"
+"[Function]"
+"returns the cadr of list, using one-based addressing."
+
+SET 
+"symbol value"
+"[Function]"
+"assigns value to the result of evaluating symbol, the name of a dynamic (special) variable. Returns
+symbol. The function set cannot alter a local (lexically bound) variable."
+
+SET-DIFFERENCE 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns the as list of elements of list1 that are not elements of list2. list1 and list2 are not modified."
+
+SET-DISPATCH-MACRO-CHARACTER 
+"disp-char sub-char function &optional readtable"
+"[Function]"
+"causes function to be called when disp-char followed by sub-char is read. readtable is the current
+readtable."
+
+SET-EXCLUSIVE-OR 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing those elements that are in list1 or in list2 but are not in both. list1 and
+list2 are not modified."
+
+SET-MACRO-CHARACTER 
+"char function &optional non-terminating-p readtable"
+"[Function]"
+"sets char to be a macro character in readtable (which defaults to *readtable*). When read
+encounters char, function is invoked."
+
+SET-SYNTAX-FROM-CHAR 
+"to-char from-char &optional to-readtable from-readtable"
+"[Function]"
+"sets the syntax of to-char in to-readtable (which defaults to *readtable*) to be equal to the syntax of
+from-char in from-readtable (which defaults to nil, meaning to use the syntax from the standard
+Common Lisp readtable)."
+
+SETF 
+"{place newvalue}*"
+"[Macro]"
+"stores the result of evaluating newvalue into the location that results from examining place. If
+multiple place-newvalue pairs are specified, they are processed sequentially. setf returns the last
+newvalue."
+
+SETQ 
+"{variable form}*"
+"[Special Form]"
+"sets the value of the current binding of each variable to the result of evaluating the corresponding
+form. The assignments are performed sequentially. Returns the value of the last variable."
+
+SEVENTH 
+"list"
+"[Function]"
+"returns the seventh element of list, using one-based addressing."
+
+SHADOW 
+"symbols &optional package"
+"[Function]"
+"searches package for a symbol with the print-name of symbol. If package does not own such a symbol
+(inherited symbols do not count), a new internal symbol is created in the package and placed on the
+shadowing symbols list. symbols should be a symbol, a string, or a list of symbols and/or strings.
+shadow returns t."
+
+SHADOWING-IMPORT 
+"symbols &optional package"
+"[Function]"
+"imports symbols (which should be a symbol or list of symbols) into package, a package object or
+package name. This function does not error if the importation causes a conflict with symbols already
+accessible in package. The symbols are placed in package's shadowing-symbols list."
+
+SHIFTF 
+"{place}+ newvalue"
+"[Macro]"
+"the contents of all the places are shifted to the place to the left. newvalue is shifted into the rightmost
+placo, and the original value of the leftmost place is returned."
+
+SHORT-FLOAT-EPSILON  
+NIL "[Constant]"
+"The smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+SHORT-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+SHORT-SITE-NAME  
+NIL
+"[Function]"
+"returns the short form of the name of the site in which the Lisp is running. This function should be
+redefined by the user to return an appropriate value."
+
+SIGNUM 
+"number"
+"[Function]"
+"returns an indication of the sign of number. This will be -1, 1, or 0 for rational numbers, -1.0,
+1.0, or 0.0 for floating point numbers. For a complex number z, (signum z) is a complex number of
+the same phase but with unit magnitude unless z is a complex zero, in which case the result is z."
+
+SIMPLE-BIT-VECTOR-P 
+"thing"
+"[Function]"
+"returns true if thing is a simple-bit-vector."
+
+SIMPLE-STRING-P 
+"thing"
+"[Function]"
+"returns true if thing is a simple-string."
+
+SIMPLE-VECTOR-P 
+"thing"
+"[Function]"
+"returns true if thing is a simple-vector."
+
+SIN 
+"radians"
+"[Function]"
+"returns the sine of radians, a number in radians."
+
+SINGLE-FLOAT-EPSILON  
+NIL "[Constant]"
+"The smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+SINGLE-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+SINH 
+"radians"
+"[Function]"
+"returns the hyperbolic sine of radians, a number in radians."
+
+SIXTH 
+"list"
+"[Function]"
+"returns the sixth element of list, using one-based addressing."
+
+SLEEP 
+"seconds"
+"[Function]"
+"pauses for seconds seconds."
+
+SLOT-VALUE 
+"object slot-name"
+"[Function]"
+"returns the value contained in the slot slot-name of the given object."
+
+#|
+SOFTWARE-TYPE  
+NIL
+"[Function]"
+"returns a string identifying the operating system software. In Macintosh Common Lisp, this is the
+type of Macintosh currently running."
+
+SOFTWARE-VERSION  
+NIL
+"[Function]"
+"returns a string identifying version information of the operating system software. In Macintosh
+Common Lisp, this includes the Macintosh ROM version and the operating system file version."
+|#
+
+SOME 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"predicate is applied to the elements of sequence with index 0, then to those with index 1, and so on,
+until the end of the shortest sequence is reached. As soon as predicate returns a non-nil value, that
+value is returned. nil is returned if there is no true value. That is, some is true if some invocation of
+predicate on sequence returns true."
+
+SORT 
+"sequence predicate &key :key"
+"[Function]"
+"destructively sorts the elements of sequence into an order determined by predicate."
+
+SPECIAL-FORM-P 
+"symbol"
+"[Function]"
+"returns true if symbol names a special form; otherwise returns nil. This is the general mechanism
+for seeing if something is a special form."
+
+SQRT 
+"number"
+"[Function]"
+"returns the principal square root of number."
+
+STABLE-SORT 
+"sequence predicate &key :key"
+"[Function]"
+"destructively sorts the elements of sequence into an order determined by predicate. Elements
+considered equal by predicate stay in their original order. (This function is similar to sort, but is
+guaranteed to be stable.)"
+
+STANDARD-CHAR-P 
+"char"
+"[Function]"
+"returns true if char is a standard character, otherwise false. char must be a character."
+
+STEP 
+"form"
+"[Macro]"
+"Evaluates form expression by expression, under user control. Calls to compiled functions within
+form are treated as a single step if the definition was not saved. The stepping is performed in an
+empty lexical environment."
+
+STREAM 
+NIL
+"[Class name]"
+"the class from which all other streams inherit. This is an abstract class. It should not be directly
+instantiated, but instead used for the creation of new subclasses."
+
+STREAM-ELEMENT-TYPE 
+"stream"
+"[Function]"
+"returns a type indicator, describing what types of objects may be read from or written to stream."
+
+STREAMP 
+"thing"
+"[Function]"
+"returns true if thing is a stream, otherwise false."
+
+STRING 
+"object"
+"[Function]"
+"creates a string from object and returns it. Signals an error if object cannot be transformed into a
+string. string can only convert characters and symbols. (Use format to convert numbers.)"
+
+STRING-CAPITALIZE 
+"string &key :start :end"
+"[Function]"
+"returns a string equivalent to string except that all words in the given range have been capitalized."
+
+STRING-DOWNCASE 
+"string &key :start :end"
+"[Function]"
+"returns a string equivalent to string except that all uppercase characters in the given range have
+been converted to lowercase."
+
+STRING-EQUAL 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true if the specified portions of string1 and string2 are equal, ignoring case. Returns nil if
+the strings are not equal. The keywords :start and :end allow comparison of substrings."
+
+STRING-GREATERP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and ignoring
+case. Returns true if the specified portion of string1 is greater than the specified portion of string2,
+otherwise returns nil. If the result is true, it will be an integer index into string1 indicating the
+first different character. The keywords :start and :end allow comparison of substrings."
+
+STRING-LEFT-TRIM 
+"char-bag string"
+"[Function]"
+"returns a substring of string with all characters in char-bag removed from the start."
+
+STRING-LESSP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and ignoring
+case. Returns true if the portion of string1 is less than the portion of string2, otherwise returns nil.
+If the result is true, it will be an integer index into string1 indicating the first different character.
+The keywords :start and :end allow comparison of substrings."
+
+STRING-NOT-EQUAL 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portions of string1 and string2 are not equal. Character case is ignored.
+If the strings are equal, nil is returned. If a true result is returned, it is the index into string1 of the
+first non-matching character."
+
+STRING-NOT-GREATERP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is not greater than the specified portion of string2.
+Character case is ignored."
+
+STRING-NOT-LESSP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is not less than the specified portion of string2.
+Character case is ignored."
+
+STRING-RIGHT-TRIM 
+"char-bag string"
+"[Function]"
+"returns a substring of string with all characters in char-bag removed from the end."
+
+STRING-TRIM 
+"char-bag string"
+"[Function]"
+"returns a substring of string with all characters in char-bag removed from the beginning and end."
+
+STRING-UPCASE 
+"string &key :start :end"
+"[Function]"
+"returns a string equivalent to string except that all lowercase characters in the given range have
+been converted to uppercase."
+
+STRING/= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portions of string1 and string2 are not equal. Character case is
+significant. If the strings are equal, nil is returned. If a true result is returned, it is the index into
+string1 of the first non-matching character."
+
+STRING< 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and treating
+case as significant. Returns true if the portion of string1 is less than the portion of string2,
+otherwise returns nil. If the result is true, it will be an integer index into string1 indicating the
+first different character. The keywords :start and :end allow comparison of substrings."
+
+STRING<= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is less than or equal to the specified portion of
+string2. Character case is significant."
+
+STRING= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true if the specified portions of string1 and string2 are equal, treating case as significant.
+The keywords :start and :end allow comparison of substrings."
+
+STRING> 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and treating
+case as significant. Returns true if the portion of string1 is greater than the portion of string2,
+otherwise returns nil. If the result is true it will be an integer index into string1 indicating the first
+different character. The keywords :start and :end allow comparison of substrings."
+
+STRING>= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is greater than or equal to the specified portion of
+string2. Character case is significant."
+
+STRINGP 
+"object"
+"[Function]"
+"returns true if object is a string; otherwise, returns false."
+
+SUBLIS 
+"a-list tree &key :test :test-not :key"
+"[Function]"
+"creates a new tree based on tree, except that elements that appear as keys in a-list are replaced with
+the corresponding value from a-list. The original tree is not modified, but the new tree may share
+list structure with it. In effect, sublis can perform several subst operations simultaneously."
+
+SUBSEQ 
+"sequence start &optional end"
+"[Function]"
+"returns a new sequence which contains the elements of the portion of sequence specified by start and
+end. subseq may be used with setf to destructively replace a portion of a sequence."
+
+SUBSETP 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns true if every element of list1 matches some element of list2."
+
+SUBST 
+"new old tree &key :test :test-not :key"
+"[Function]"
+"creates a new tree based on tree, except that occurrences of old have been replaced with new. The
+original tree is not modified, but the new tree may share list structure with it."
+
+SUBST-IF 
+"new test tree &key :key"
+"[Function]"
+"creates a new tree based on tree, except that elements that satisfy test have been replaced with new.
+The original tree is not modified, but the new tree may share list structure with it."
+
+SUBST-IF-NOT 
+"new test tree &key :key"
+"[Function]"
+"creates a new tree based on tree, except that elements that don't satisfy test have been replaced with
+new. The original tree is not modified, but the new tree may share list structure with it."
+
+SUBSTITUTE 
+"new-item old-item sequence &key :start :end :from-end :count :test :test-not :key"
+"[Function]"
+"returns a new sequence equivalent to sequence except that occurrences of old-item within a given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence is not modified."
+
+SUBSTITUTE-IF 
+"new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that satisfy test within the given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions that take place. The original sequence is not modified."
+
+SUBSTITUTE-IF-NOT 
+"new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that do not satisfy test within the
+given subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions that take place. The original sequence is not modified."
+
+SUBTYPEP 
+"type-1 type-2"
+"[Function]"
+"returns true if type-1 is definitely a subtype of type-2. If the result is nil, however, type1 may or
+may not be a subtype of type2. A second value is returned indicating the certainty of the result (t
+indicates that type1 definitely is or is not a subtype of type2; nil indicates that the result is
+uncertain). subtypep is not permitted to return a second value of nil unless one or both of its
+arguments involve satisfies, and, or, not, or member. When one or both of its arguments involve
+values or the list form of the function type specifier, subtypep returns an error."
+
+SVREF 
+"simple-vector index"
+"[Function]"
+"returns the element of simple-vector indicated by index."
+
+SXHASH 
+"thing"
+"[Function]"
+"computes a hash code for thing and returns it as a non-negative fixnum."
+
+SYMBOL-FUNCTION 
+"symbol"
+"[Function]"
+"returns the current global function definition named bysymbol. If the symbol has no function
+binding, symbol-function signals an error."
+
+SYMBOL-NAME 
+"symbol"
+"[Function]"
+"returns the print name of symbol as a string."
+
+SYMBOL-PACKAGE 
+"symbol"
+"[Function]"
+"returns the home package of symbol."
+
+SYMBOL-PLIST 
+"symbol"
+"[Function]"
+"returns the property list of symbol."
+
+SYMBOL-VALUE 
+"symbol"
+"[Function]"
+"returns the current value of the special variable named by symbol. An error is signalled if symbol is
+unbound."
+
+SYMBOLP 
+"object"
+"[Function]"
+"returns true if object is a symbol; otherwise returns false."
+
+T  
+NIL "[Constant]"
+"the general truth value in Common Lisp. t is a constant, a class, a stream, and a type."
+
+TAGBODY 
+"{tag | statement}*"
+"[Special Form]"
+"A tagbody consists of a mixture of tags and forms. The tags indicate positions in the tagbody. During
+execution, the statements are evaluated sequentially, except that (go tag ) may redirect execution to
+the position of any tag. If the end of the body is reached, tagbody returns nil."
+
+TAILP 
+"sublist list"
+"[Function]"
+"returns true if and only if there exists an integer n such that (eql sublist (nthcdr n list)). list may
+be a dotted list."
+
+TAN 
+"radians"
+"[Function]"
+"returns the tangent of radians, a number in radians."
+
+TANH 
+"radians"
+"[Function]"
+"returns the hyperbolic tangent of radians, a number in radians."
+
+TENTH 
+"list"
+"[Function]"
+"returns the tenth element of list, using one-based addressing."
+
+TERPRI 
+"&optional output-stream"
+"[Function]"
+"writes a newline character to output-stream and returns nil."
+
+THE 
+"type form"
+"[Special Form]"
+"instructs the compiler that form is of type type. This information can be used by the compiler for
+performing optimizations."
+
+THIRD 
+"list"
+"[Function]"
+"returns the third element (caddr) of list, using one-based addressing."
+
+THROW 
+"tag result"
+"[Special Form]"
+"causes the dynamically active catch named tag to immediately return the value of result. This
+involves exiting any processes begun from the point of the catch."
+
+TIME 
+"form"
+"[Macro]"
+"Executes form, prints the amount of time used in execution (with a special note on garbage collection
+time, if any), and returns the value returned by form. time is useful for testing and optimizing code."
+
+TRACE 
+"{symbol | (symbol {option [modifier] }*) }*"
+"[Macro]"
+"causes the function named by symbol to be traced. Whenever the function is called, information can
+be printed or other options can be performed. modifier specifies that actions can be performed
+:before or :after the function is traced; the modifier :step specifies that the function is stepped when
+it is run. Functions that are compiled in-line cannot be traced."
+
+TREE-EQUAL 
+"x y &key :test :test-not"
+"[Function]"
+"returns true of x and y are equivalent trees, that is, if they have the same shape and the leaves are
+equal. It is true for atoms if they are equal according to the test function (by default eql), and it is
+true for conses if both the car and cdr are tree-equal."
+
+TRUENAME 
+"pathname"
+"[Function]"
+"returns the true name of pathname. This is the name of the pathname as it is actually represented by
+the file system. An error is signalled if pathname does not indicate an actual file or directory."
+
+TRUNCATE 
+"number &optional divisor"
+"[Function]"
+"returns two values: the integer part of number (i.e. number with the fractional part removed), and
+the fractional part. When there is a second argument, truncate divides divisor into number first, and
+then applies truncate to the result."
+
+TYPE-OF 
+"thing"
+"[Function]"
+"returns a type of which thing is a member. Various constraints are now placed on type-of; see
+Common Lisp: The Language, p. 65-67, for clarification."
+
+TYPECASE 
+"keyform {(type {form}* )}*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose type matches the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the type is not. typecase permits
+a final type, otherwise or t, that handles all types not otherwise covered."
+
+TYPEP 
+"thing type"
+"[Function]"
+"returns true if thing is of type type; otherwise returns nil."
+
+UNEXPORT 
+"symbols &optional package"
+"[Function]"
+"makes symbols (which should be a symbol or list of symbols) become internal symbols in package
+(which defaults to *package*), and returns t. It is an error to unexport symbols from the keyword
+package."
+
+UNINTERN 
+"symbol &optional package"
+"[Function]"
+"deletes symbol from the package package. unintern returns true if it removes symbol and nil if the
+symbol was not interned in the first place."
+
+UNION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing the union of the elements list1 and list2. Any element that is contained in
+list1 or list2 will be contained in the result list. If there are duplicate entries, only one will appear
+in the result. list1 and list2 are not modified."
+
+UNLESS 
+"testform {thenform}*"
+"[Macro]"
+"evaluates testform. If the result is non-nil, then no thenforms are evaluated and unless returns nil.
+If the result is nil, evaluates thenforms as an implicit progn, sequentially from left to right, and
+returns the value of the last thenform."
+
+UNREAD-CHAR 
+"character &optional input-stream"
+"[Function]"
+"puts character , the most recently read charadcter, back onto the front of input-stream so that it
+will be read again as the next input character. Returns nil."
+
+UNTRACE 
+"{symbol}*"
+"[Macro]"
+"stops each function named by symbol from being traced. Notices will not be printed when the function
+enters or returns."
+
+UNUSE-PACKAGE 
+"packages-to-unuse &optional package-unusing"
+"[Function]"
+"removes packages-to-unuse to the use-list of package-unusing. packages-to-unuse should be a
+package, package-name, or list of packages and package-names. package-unusing may be a package
+name or package object."
+
+UNWIND-PROTECT 
+"protected-form {cleanup-form}*"
+"[Special Form]"
+"executes protected-form and the cleanup-forms. The cleanup-forms are guaranteed to be executed,
+even if there is a non-local exit during the execution of body-forms. unwind-protect returns the
+value of protected-form if the exit is normal."
+
+UPPER-CASE-P 
+"char"
+"[Function]"
+"returns true if char is an uppercase character; otherwise returns false. char must be a character."
+
+USE-PACKAGE 
+"packages-to-use &optional package-using"
+"[Function]"
+"adds packages-to-use to the use-list of package-using. The external symbols of packages-to-use will
+be directly accessible in package-using. packages-to-use should be a package, package-name, or list
+of packages and package-names. package-using may be a package name or package object."
+
+#|
+USER-HOMEDIR-PATHNAME 
+"&optional host"
+"[Function]"
+"returns the userÕs home directory. This is the expanded form of the \"home:\" logical host. When
+Macintosh Common Lisp files run on the Macintosh, the host argument is ignored."
+|#
+
+VALUES 
+"&rest things"
+"[Function]"
+"returns things in order as multiple values."
+
+VALUES-LIST 
+"list"
+"[Function]"
+"returns the elements of list as multiple values."
+
+VECTOR 
+"&rest objects"
+"[Function]"
+"creates a simple vector (a non-adjustable one-dimensional array without a fill-pointer) whose
+elements are objects."
+
+VECTOR-POP 
+"vector"
+"[Function]"
+"returns the element of vector indicated by vectorÕs fill pointer and decrements the fill pointer.
+vector must be a one-dimensional array that has a fill pointer."
+
+VECTOR-PUSH 
+"new-element vector"
+"[Function]"
+"stores new-element in vector at the location indicated by vectorÕs fill pointer and increments the fill
+pointer by one. Returns the previous value of the fill pointer, or nil if the fill pointer does not
+designate an element of vector. vector must be a one-dimensional array that has a fill pointer."
+
+VECTOR-PUSH-EXTEND 
+"new-element vector &optional extension"
+"[Function]"
+"stores new-element in vector at the location indicated by the fill pointer. If the fill pointer is already
+at the end of vector, vector-push-extend increases the size of vector by an amount given by
+extension. This function is equivalent to vector-push except that it increases the size of the vector if
+it is already full (provided the vector is adjustable). vector must be a one-dimensional array that
+has a fill pointer."
+
+VECTORP 
+"object"
+"[Function]"
+"returns true if object is a vector; otherwise returns false. A vector is a one-dimensional array."
+
+WARN 
+"datum &rest args"
+"[Function]"
+"warns about a situation by signaling a condition of type warning."
+
+WHEN 
+"testform {thenform}*"
+"[Macro]"
+"evaluates testform. If the result is nil, returns nil without evaluating any thenform. If the result is
+true, evaluates thenforms as an implicit progn, sequentially from left to right, and returns the value
+of the last thenform."
+
+WITH-INPUT-FROM-STRING 
+"(var string {keyword value}*) {declaration}* {form}*"
+"[Macro]"
+"executes forms with var bound to an input stream that reads characters from string and returns the
+results from the last form of the body. The keyword options are :index, :start, and :end. The stream
+created by this macro is always of type string-stream."
+
+WITH-OPEN-FILE 
+"(stream filename {option}*) {declaration}* {form}*"
+"[Macro]"
+"evaluates the forms with a stream stream that reads or writes to filename, and returns the value of
+the last form. The file is closed when the body of the with-open-file exits, even if the exit is through
+an error, throw, or return."
+
+WITH-OPEN-STREAM 
+"(variable stream) {declaration}* {form}*"
+"[Macro]"
+"evaluates the forms with stream open and bound to variable. The stream is guaranteed to be closed
+when with-open-stream exits, even if the exit is abnormal (as through a throw). The stream created
+by with-open-stream is always of type file-stream."
+
+WITH-OUTPUT-TO-STRING 
+"(var [string [:element-type type]]) {declaration}* {form}*"
+"[Macro]"
+"executes forms with var bound to a string output stream. If string is supplied, it must be adjustable
+and have a fill-pointer. The value of the last form is returned. If nil is supplied instead of string, the
+:element-type keyword may be used to specify what characters must be accepted by the created
+stream. The stream created by this macro is always of type string-stream."
+
+WITH-PACKAGE-ITERATOR 
+"(mname package-list {symbol-type}*) {form}*"
+"[Macro]"
+"mname is defined as if by macrolet with forms as its lexical scope, such that each invocation of
+(mname) returns a symbol. Successive invocations eventually deliver all the symbols matching
+symbol-types from the packages that are the elements of package-list, which is evaluated exactly
+once. Each invocation of mname returns nil if there are no more symbols to be processed in the
+current package. If symbols remain to be processed, the function returns four values: t, the symbol,
+a keyword indicating its accessibility, and the package from which it was accessed."
+
+WRITE 
+"object &key :stream :escape :radix :base :circle :pretty :level :length :case :gensym :array
+:readably :right-margin :miser-width :lines :pprint-dispatch :simple-bit-vector :simple-vector
+:string-length :structure"
+"[Function]"
+"writes the printed representation of object to the stream specified by :stream and returns object. The
+other keyword arguments specify values used to control the printed representation; each defaults to
+the value of its corresponding global variable."
+
+WRITE-BYTE 
+"integer binary-output-stream"
+"[Function]"
+"writes one byte, the value of integer, to binary-output-stream. It is an error if integer is not of the
+type specified as the :element-type argument for binary-output-stream."
+
+WRITE-CHAR 
+"character &optional output-stream"
+"[Function]"
+"writes character to output-stream, and returns character."
+
+WRITE-LINE 
+"string &optional output-stream &key :start :end"
+"[Function]"
+"sends the specified portion of string to output-stream (which defaults to *standard-output*),
+followed by a newline, and returns string."
+
+WRITE-STRING 
+"string &optional stream &key :start :end"
+"[Function]"
+"sends the specified portion of string to stream (which defaults to *standard-output*), and returns
+string."
+
+WRITE-TO-STRING 
+"thing &key :escape :radix :base :circle :pretty :level :length :case :gensym
+:array :readably :right-margin :miser-width :lines :pprint-dispatch :simple-bit-vector
+:simple-vector :string-length :structure"
+"[Function]"
+"thing is printed, as if by write, but the output is collected in a string, which is returned."
+
+Y-OR-N-P 
+"&optional format-string &rest format-args"
+"[Function]"
+"prints a message from format-string and format-args, followed by (y or n), and waits for the user
+to type y or n. Returns T if the user typed y, or nil if the user typed n."
+
+YES-OR-NO-P 
+"&optional format-string &rest args"
+"[Function]"
+"prints a message from format-string and args, followed by (yes or no), and waits for the user to
+type yes or no followed by a carriage return. Returns t if the user typed yes, nil if the user typed no."
+
+ZEROP 
+"number"
+"[Function]"
+"returns true if number is zero (either the integer zero, a floating-point zero, or a complex zero);
+otherwise returns nil. (zerop -0.0) is always true."
Index: /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-1.lisp
===================================================================
--- /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-1.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-1.lisp	(revision 13309)
@@ -0,0 +1,155 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-commands-1.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a Hemlock Commands documentation tool to the Context-Menu 
+;;;      mechanism.  Right-Click displays a listing of essential Hemlock Commands
+;;;      for the new users.  Selecting an entry executes the command.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Removed doc-path from hemlock-commands-menu.
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "HEMLOCK-COMMANDS" (:nicknames "HCOM") (:use :cl :ccl))
+(in-package "HEMLOCK-COMMANDS")
+
+(require :context-menu-cm)
+(cmenu:check-hyperspec-availability "Hemlock-Commands-CM")
+
+(defparameter *hemlock-commands-menu* nil "The hemlock-commands-menu instance.")
+(defparameter *hemlock-commands-keyword-menu* nil "The hemlock-commands-keyword-menu instance.")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMAND-MENU-ITEM (ns:ns-menu-item)
+  ((key-event :initform nil :accessor key-event))
+  (:documentation "Support for the hemlock-commands-menu.")
+  (:metaclass ns:+ns-object))
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMANDS-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "basic commands" :reader sub-title)
+   (text-view :initform nil :accessor text-view))
+  (:documentation "A popup menu listing a useful subset of Hemlock commands: Hemlock's Greatest Hits, for new users.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/hemlockCommandAction: :void) ((m hemlock-commands-menu) (sender :id))
+  (let ((key-event (key-event sender))) ; can be a vector of events
+    (cond ((typep key-event 'hi::key-event)
+           (hi::handle-hemlock-event (gui::hemlock-view (text-view m)) key-event))
+          ((typep (key-event sender) 'simple-vector)
+           (hi::handle-hemlock-event (gui::hemlock-view (text-view m)) (aref key-event 0))
+           (hi::handle-hemlock-event (gui::hemlock-view (text-view m)) (aref key-event 1))))))
+
+(defmethod initialize-instance :after ((menu hemlock-commands-menu) &key)
+  (flet ((create-menu-item (name key-event)
+           (let ((menu-item (make-instance 'hemlock-command-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring name)
+                                     cmenu:*hemlock-menu-dictionary*)))
+             (#/setAttributedTitle: menu-item attributed-string)
+             (#/setAction: menu-item (ccl::@selector "hemlockCommandAction:"))
+             (#/setTarget: menu-item  menu)
+             (setf (key-event menu-item) key-event)
+             (#/addItem: menu menu-item))))
+    (setf (tool-menu menu) (cmenu:add-default-tool-menu menu))
+    
+    ;;; Hemlock's Greatest Hits:
+    (create-menu-item "Inspect Symbol  (control-x, control-i)" 
+                      #k"control-x control-i")
+    (create-menu-item "Symbol Documentation  (control-x, control-d)" 
+                      #k"control-x control-d")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Current Function Arglist  (control-x, control-a)" 
+                      #k"control-x control-a")
+    (create-menu-item "Goto Definition  (meta-.)"
+                      #k"meta-.")
+    (create-menu-item "Show Callers  (control-meta-c)" 
+                      #k"control-meta-c")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Macroexpand-1 Expression  (control-m)"
+                      #k"control-m")
+    (create-menu-item "Macroexpand Expression  (control-x, control-m)" 
+                      #k"control-x control-m")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Editor Evaluate Defun  (control-x, control-e)" 
+                      #k"control-x control-e")
+    (create-menu-item "Editor Compile Defun  (control-x, control-c)" 
+                      #k"control-x control-c")
+    (create-menu-item "Editor Evaluate Region  (Enter)"
+                      #k"enter")
+    #|
+    (create-menu-item "Editor Compile Region  (unbound)" 
+                      #k"enter")
+    (create-menu-item "Editor Evaluate Buffer  (unbound)"
+                      #k"enter")
+    (create-menu-item "Editor Compile Buffer File  (unbound)"
+                      #k"enter")
+    |#
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Incremental Search  (control-s)"
+                      #k"control-s")
+    (create-menu-item "I-Search Repeat Forward  (control-s)"
+                      #k"control-s")
+    (create-menu-item "I-Search Repeat Backward  (control-r)"
+                      #k"control-r")
+    (create-menu-item "I-Search Abort  (control-g)"
+                      #k"control-g")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Kill Line  (control-k)"
+                      #k"control-k")
+    (create-menu-item "Un-Kill  (control-y)"
+                      #k"control-y")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Forward Character  (control-f)"
+                      #k"control-f")
+    (create-menu-item "Backward Character  (control-b)"
+                      #k"control-b")
+    (create-menu-item "Beginning of Line  (control-a)"
+                      #k"control-a")
+    (create-menu-item "End of Line  (control-e)"
+                      #k"control-e")
+    (create-menu-item "Previous Line  (control-p)"
+                      #k"control-p")
+    (create-menu-item "Next Line  (control-n)"
+                      #k"control-n")
+    (create-menu-item "Beginning of Buffer  (meta-<)"
+                      #k"meta-\<")
+    (create-menu-item "End of Buffer  (meta->)"
+                      #k"meta-\>")
+    (create-menu-item "Scroll Window Down  (control-v)"
+                      #k"control-v")
+    (create-menu-item "Scroll Window Up  (meta-v)"
+                      #k"meta-v")))
+
+(objc:defmethod (#/update :void) ((self hemlock-commands-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(setq *hemlock-commands-menu* (make-instance 'hemlock-commands-menu))
+
+(defun get-hemlock-commands-menu (view event)
+  "Return the appropriate Hemlock Commands menu based on modifier keys."
+  (cond ((logtest #$NSCommandKeyMask (#/modifierFlags event))
+         (setf (text-view *hemlock-commands-menu*) view)           
+         *hemlock-commands-menu*)
+        (t
+         *hemlock-commands-keyword-menu*)))
+
+(cmenu:register-tool "Hemlock-Commands-CM" #'get-hemlock-commands-menu)
+
+
Index: /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-2.lisp
===================================================================
--- /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-2.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-2.lisp	(revision 13309)
@@ -0,0 +1,155 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-commands-2.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a Hemlock Commands documentation tool to the Context-Menu 
+;;;      mechanism.  Right-Click displays a list of submenus.  The submenus are keywords.
+;;;      Popping the submenu displays entries for all Hemlock Commands filtered by that 
+;;;      keyword.  Selecting an entry opens a documentation dialog.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "HEMLOCK-COMMANDS")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMAND-KEYWORD-MENU-ITEM (ns:ns-menu-item)
+  ((command :initform nil :accessor item-command))
+  (:documentation "Support for the hemlock command keyword menu.")
+  (:metaclass ns:+ns-object))
+
+(defun display-doc (command)
+  "Open the documentation dialog for COMMAND."
+  (let ((keystroke-string
+         (do* ((bindings (hi::command-%bindings command) (rest bindings))
+               (bindings-length (length bindings))
+               (binding (car bindings) (car bindings))
+               (event-array (when binding (car binding))
+                            (when binding (car binding)))
+               (num-events (when event-array (array-dimension event-array 0))
+                           (when event-array (array-dimension event-array 0)))
+               (keystrokes "" (if binding 
+                                (concatenate 'string keystrokes ",   ")
+                                keystrokes)))
+              ((or (null bindings) (> bindings-length 4))
+                   (if (> bindings-length 4)
+                     "Too many bindings ..."
+                     keystrokes))
+           (when event-array
+             (cond ((= num-events 1)
+                    (setq keystrokes 
+                          (concatenate 'string
+                                       keystrokes
+                                       (hi::pretty-key-string (aref event-array 0) t))))
+                   (t
+                    (setq keystrokes
+                          (concatenate 'string 
+                                       keystrokes
+                                       (format nil "~A  ~A" 
+                                               (hi::pretty-key-string (aref event-array 0) t)
+                                               (hi::pretty-key-string (aref event-array 1) t))))))))))
+    (open-documentation-dialog (hi::command-%name command)
+                             (if (string= keystroke-string "") "no binding" keystroke-string)
+                             (hi::command-documentation command) :hemlock-p t)))
+
+(defun populate-submenu (menu command-list)
+  "Make menu-items for all commands in COMMAND-LIST, and add them to MENU"
+  (dolist (command-cons (reverse command-list))
+    (let* ((command-name (car command-cons))
+           (command (cdr command-cons))
+           (menu-item (make-instance 'hemlock-command-keyword-menu-item))
+           (attributed-string (#/initWithString:attributes:
+                               (#/alloc ns:ns-attributed-string) 
+                               (ccl::%make-nsstring command-name)
+                               cmenu:*hemlock-menu-dictionary*)))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setAction: menu-item (ccl::@selector "hemlockCommandDocAction:"))
+      (#/setTarget: menu-item  *hemlock-commands-keyword-menu*)
+      ;; (#/setImage: menu-item class-icon)
+      (setf (item-command menu-item) command)
+      (#/addItem: menu menu-item))))
+
+(defun make-submenu-item (title command-list)
+  "Create a menu-item with a submenu, and populate the submenu with the commands in COMMAND-LIST."
+  (let ((menu-item (make-instance ns:ns-menu-item))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (ccl::%make-nsstring title)
+                            cmenu:*hemlock-menu-dictionary*))
+        (submenu (make-instance ns:ns-menu)))
+    (#/setAttributedTitle: menu-item attributed-string)
+    (#/setSubmenu: menu-item submenu)
+    (populate-submenu submenu command-list)
+    menu-item))
+
+(defparameter *hemlock-command-keywords*
+  '("auto" "backward" "beginning" "buffer" "character" "command" "comment" "compile" "completion" "count" "defun" "delete" "describe"
+    "down" "echo" "editor" "end" "evaluate" "expression" "file" "form" "forward" "function" "goto" "help" "i-search"
+    "indent" "insert" "interactive" "kill" "line" "list" "macroexpand" "mark" "mode" "next" "paragraph" "parse"
+    "point" "pop" "previous" "query" "region" "register" "save" "search" "select" "sentence" "set" "show" "space" 
+    "transpose" "up" "what" "word" "write"))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMANDS-KEYWORD-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "keyword filters" :reader sub-title)
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*hemlock-commands-directory*) :reader doc-path))
+  (:documentation "A popup menu with keyword submenus for filtering Hemlock commands.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/hemlockCommandDocAction: :void) ((m hemlock-commands-keyword-menu) (sender :id))
+  (display-doc (item-command sender)))
+
+(defmethod initialize-instance :after ((menu hemlock-commands-keyword-menu) &key)
+  (setf (tool-menu menu) (cmenu:add-default-tool-menu menu :doc-file (doc-path menu))))
+
+(defmethod add-submenus ((menu hemlock-commands-keyword-menu))
+  (let ((keyword-array (make-array  (length *hemlock-command-keywords*) :initial-element nil))
+        miscellaneous)
+    (dotimes (index (hi::string-table-num-nodes hi::*command-names*))
+      (let* ((idx 0)
+             (command (hi::value-node-value (aref (hi::string-table-value-nodes hi::*command-names*) index)))
+             (command-name (hi::command-%name command))
+             (entry-found-p nil))
+        (dolist (keyword *hemlock-command-keywords*)
+          ;; commands will generally have multiple entries
+          (when (search keyword command-name :test #'string-equal)
+            (setq entry-found-p t)
+            (push (cons command-name command) (aref keyword-array idx)))
+          (incf idx))
+      (unless entry-found-p (push (cons command-name command) miscellaneous))))
+    (let ((idx 0))
+      (dolist (keyword *hemlock-command-keywords*)
+        (let ((submenu-item (make-submenu-item keyword (coerce (aref keyword-array idx) 'list))))
+          (#/addItem: menu submenu-item))
+        (incf idx)))
+    (when miscellaneous
+      (#/addItem: menu (#/separatorItem ns:ns-menu-item))    
+      (let ((submenu-item (make-submenu-item "Commands Without Keywords:" miscellaneous)))
+        (#/addItem: menu submenu-item)))))
+
+
+(objc:defmethod (#/update :void) ((self hemlock-commands-keyword-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+
+(setq *hemlock-commands-keyword-menu* (make-instance 'hemlock-commands-keyword-menu))
+
+(add-submenus *hemlock-commands-keyword-menu*)
+
+
+
+
Index: /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-cm.lisp
===================================================================
--- /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-cm.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-cm.lisp	(revision 13309)
@@ -0,0 +1,24 @@
+
+;;; hemlock-commands.lisp
+
+(in-package :common-lisp-user) 
+
+(unless (member "HEMLOCK-COMMANDS-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *hemlock-commands-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *hemlock-commands-files* 
+    (list (merge-pathnames ";hemlock-commands-1.lisp" *hemlock-commands-directory*)
+          (merge-pathnames ";hemlock-commands-2.lisp" *hemlock-commands-directory*)
+          (merge-pathnames ";hemlock-documentation-dialog.lisp" *hemlock-commands-directory*)
+          (merge-pathnames ";hemlock-commands-new.lisp" *hemlock-commands-directory*))))
+ 
+(dolist (file *hemlock-commands-files*)
+  (load file))
+
+(provide :hemlock-commands-cm)
+
+)
Index: /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-new.lisp
===================================================================
--- /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-new.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-commands-new.lisp	(revision 13309)
@@ -0,0 +1,176 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS-TOOL -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-commands-new.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code implements a two new Hemlock commands.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Added "Show Callers" command.
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "HEMLOCK-COMMANDS")
+
+(defparameter *MCL-doc* (merge-pathnames ";MCL-doc.lisp" cl-user::*hemlock-commands-directory*))
+
+;;; Hemlock has some internal code to do this, but it appears to be broken 
+;;; and definitely does not work for ObjC methods.
+(defun parse-symbol ()
+  "Parse and return the symbol at point."
+  (let ((point (hi::current-point)))
+    (hemlock::pre-command-parse-check point)
+    (hi::with-mark ((mark1 point)
+                    (mark2 point))
+      (hemlock::mark-symbol mark1 mark2)
+      ;; For an objc method, mark-symbol removes the prepended #\#
+      (let* ((string (hi::region-to-string (hi::region mark1 mark2)))
+             (objc-p (when string (char= (elt string 0) #\/)))
+             (colons-start-position (when string
+                                      (unless objc-p (position #\: string))))
+             (colons-end-position (when colons-start-position
+                                    (if (char= (elt string (1+ colons-start-position)) #\:)
+                                      (1+ colons-start-position)
+                                      colons-start-position)))
+             (package-prefix (when colons-start-position
+                               (string-upcase (subseq string 0 colons-start-position))))
+             (sym-string (if colons-end-position
+                           (subseq string (incf colons-end-position))
+                           string))
+             (package (if objc-p
+                        (find-package "NEXTSTEP-FUNCTIONS")
+                        (when package-prefix (find-package package-prefix))))
+             symbol)
+        (when (and sym-string objc-p)
+          (setq sym-string (subseq sym-string 1))) ;chuck the #\/
+        (setq symbol (if package
+                       (if objc-p
+                         (find-symbol sym-string package)
+                         (find-symbol (string-upcase sym-string) package))
+                       (find-symbol (string-upcase sym-string) (hemlock::buffer-package hi::*current-buffer*))))
+        symbol))))
+
+(hemlock::defcommand "Inspect Symbol" (p)
+  "Open the Inspector for the symbol at point."
+  (declare (ignore p))
+  (let ((symbol (parse-symbol)))
+    (cond (symbol 
+           (inspect symbol))
+          (t
+           (hi::editor-error "Could not parse a valid symbol at point.")))))
+
+(hi::bind-key "Inspect Symbol" #k"control-x control-i")
+
+(defun MCL-documentation (symbol)
+  "Fetch the MCL documentation for SYMBOL."
+  (let ((path *MCL-doc*))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (let (sym args type doc)
+          (loop
+            (setq sym (read stream nil :eof))
+            (setq args (read stream nil :eof))
+            (setq type (read stream nil :eof))
+            (setq doc (read stream nil :eof))
+            (cond ((eq sym :eof)
+                   (return-from MCL-documentation))
+                  ((eq sym symbol)
+                   (return (values args type doc))))))))))
+
+(defun display-ccl-doc (sym text-view)
+  "Display the CCL documentation for SYM, if it exists."
+  (let (docstring args)
+    (dolist (doctype '(compiler-macro function method-combination
+                                      setf structure t type variable))
+      (when (setq docstring (documentation sym doctype))
+        (when (eq doctype 'function) 
+          (setq args (arglist sym))
+          (when (macro-function sym) (setq doctype 'macro))
+          (when (special-form-p sym) (setq doctype 'special-form)))
+        (when (eq doctype 'type)
+          (when (find-class sym nil)
+            (setq doctype 'class)))
+        (open-documentation-dialog
+         (if args
+           (format nil "~A  ~A" (string-upcase sym) 
+                   (string-downcase (format nil "~A" args)))
+           (string-upcase sym))
+         (format nil "[~A]" (string-capitalize (string-downcase (string doctype))))
+         docstring :text-view text-view :symbol sym)
+        (return t)))))
+
+(defun display-mcl-doc (sym text-view)
+  "Display the MCL documentation for SYM, if it exists."
+  (multiple-value-bind (args type doc)
+                       (MCL-documentation sym)
+    (when doc
+      (setq doc (substitute #\space #\newline doc))
+      (open-documentation-dialog
+       (if args
+         (format nil "~A  ~A" (string-upcase sym) 
+                 (string-downcase (format nil "~A" args)))
+         (string-upcase sym)) 
+       type 
+       (concatenate 'string doc "    (MCL)")
+       :text-view text-view :symbol sym) t)))
+  
+(hi:defcommand "Symbol Documentation" (p)
+  "Display the documentation for the symbol at point."
+  (declare (ignore p))
+  (let* ((sym (parse-symbol))
+         (hemlock-view (hi::current-view))
+         (pane (when hemlock-view (hi::hemlock-view-pane hemlock-view)))
+         (text-view (when pane (gui::text-pane-text-view pane))))
+      (cond ((and sym text-view)
+             (cond ((eq (symbol-package sym) (find-package :common-lisp))
+                    (or (display-ccl-doc sym text-view)
+                        (display-mcl-doc sym text-view)
+                        (gui::lookup-hyperspec-symbol sym text-view)))
+                   (t
+                    (or (display-ccl-doc sym text-view)
+                        (open-documentation-dialog
+                         (format nil "No documentation found for ~S" sym) nil nil)))))
+            (t
+             (hi::editor-error "Could not parse a valid symbol at point.")))))
+
+(hi::bind-key "Symbol Documentation" #k"control-x control-d")
+
+(hi:defcommand "Show Callers" (p)
+  "Display a scrolling list of the callers of the symbol at point.
+   Double-click a row to go to the caller's definition."
+  (declare (ignore p))
+  (let* ((symbol (parse-symbol))
+         (callers (ccl::callers symbol)))
+    (cond (symbol
+           (if callers
+             (make-instance 'gui::sequence-window-controller
+               :title (format nil "Callers of ~a" symbol)
+               :sequence (mapcar #'(lambda (entry)
+                                     (if (listp entry)
+                                       (car (last entry))
+                                       entry))
+                                 (ccl::callers symbol))
+               :result-callback #'hemlock::edit-definition
+               :display #'princ)
+             (gui::alert-window :title "Notification"
+                                :message (format nil "Could not find any callers for ~S" symbol))))
+          (t
+           (hi::editor-error "Could not parse a valid symbol at point.")))))
+
+(hi::bind-key "Show Callers" #k"control-meta-c")
+
+
+
+
+
+
+
+
Index: /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-documentation-dialog.lisp
===================================================================
--- /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-documentation-dialog.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/hemlock-commands-cm/hemlock-documentation-dialog.lisp	(revision 13309)
@@ -0,0 +1,281 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-documentation-dialog.lisp
+;;;
+;;;      copyright Â© 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      A documentation dialog for Hemlock commands, CL function, symbols, etc.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "HEMLOCK-COMMANDS")
+
+(defparameter *doc-dialog* nil)
+(defparameter *hemlock-jpg* (merge-pathnames ";Hemlock.jpg" cl-user::*hemlock-commands-directory*))
+;;; I don't know the name of the artist who drew this graphic, but it is quite nice.
+;;; I also don't know what the copyright issues are, so this will have to be replaced when I get a chance:
+(defparameter *graphic-p* nil "To use, or not to use the eye candy.")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass doc-dialog (ns:ns-window)
+  ((name :accessor name)
+   (symbol :accessor symbol)
+   (name-field :accessor name-field)
+   (key-field :accessor key-field)
+   (doc-text-view :accessor doc-text-view)
+   (hemlock-p :initform nil :accessor hemlock-p)
+   (hyperspec-button :accessor hyperspec-button)
+   (inspect-button :accessor inspect-button)
+   (okay-button :accessor okay-button)
+   (source-button :accessor source-button)
+   (text-view :accessor text-view))
+  (:documentation "A dialog for displaying the documentation of Hemlock Commands, CL function, non-CL functions, etc.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/closeAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/close d))
+
+(objc:defmethod (#/hyperSpecAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (when (symbol d) 
+    (gui::lookup-hyperspec-symbol (symbol d) (text-view d))))
+
+(objc:defmethod (#/inspectSymbolAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (when (symbol d)
+    (inspect (symbol d))))
+
+;;; Should probably just make Hemlock-Commands require List-Definitions:
+#+:list-definitions
+(objc:defmethod (#/commandSourceAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (cond ((hemlock-p d)
+         (let* ((search-string (format nil "(defcommand \"~A\"" (name d)))
+                (hemlock-src-dir (merge-pathnames "cocoa-ide/hemlock/src/" (native-translated-namestring "ccl:")))
+                (files (mapcar #'namestring
+                               (remove-if #'(lambda (path)
+                                              (string-not-equal (pathname-type path) "lisp"))
+                                          (directory (merge-pathnames hemlock-src-dir "*.lisp") :files t :directories nil))))
+                (args (cons "-l" (cons search-string files)))
+                (source-path (string-trim '(#\newline #\space) (gui::call-grep args))))
+           (if (and (stringp source-path) (string-not-equal source-path ""))
+             (ldefs:find-and-display-definition (format nil "~S" (name d)) source-path)
+             (cmenu:notify (format nil "Could not find: ~S" (name d))))))
+        (t
+         (hemlock::edit-definition (symbol d)))))
+
+#-:list-definitions
+(objc:defmethod (#/commandSourceAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (cond ((hemlock-p d)
+         ;; deactivate the button instead of this?
+         (gui::alert-window :title "Notification" :message "Searching for source requires the List-Definitions tool."))
+        (t
+         (hemlock::edit-definition (symbol d)))))
+
+
+(defun open-documentation-dialog (name key-or-type doc &key symbol hemlock-p text-view)
+  "Open the dialog displaying the documentation for NAME."
+  (let* ((name-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                   (ccl::%make-nsstring 
+                                                    (if hemlock-p
+                                                      ;; *** ~S
+                                                      (string-upcase (format nil "\"~A\"" name))
+                                                      (format nil "~A" name)))
+                                                   cmenu::*tool-label-dictionary*))
+        (key-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                  (if key-or-type
+                                                    (ccl::%make-nsstring key-or-type)
+                                                    (ccl::%make-nsstring " "))
+                                                  cmenu::*tool-key-dictionary*))
+         (inspect-p doc) ; "No documentation found"
+         (source-p (when symbol (ccl::%source-files symbol)))
+         (hyperspec-p (when (and symbol text-view) (gethash symbol (gui::hyperspec-map-hash text-view)))))
+    (cond (*doc-dialog*
+           (cond (hemlock-p
+                  (setf (hemlock-p *doc-dialog*) t)
+                  (#/setTitle: *doc-dialog* #@"Hemlock Command Documentation")
+                  (#/setHidden: (inspect-button *doc-dialog*) t)
+                  (#/setHidden: (hyperspec-button *doc-dialog*) t))
+                 (t
+                  (setf (hemlock-p *doc-dialog*) nil)
+                  (if source-p
+                    (#/setEnabled: (source-button *doc-dialog*) t)
+                    (#/setEnabled: (source-button *doc-dialog*) nil))
+                  (if inspect-p
+                    (#/setEnabled: (inspect-button *doc-dialog*) t)
+                    (#/setEnabled: (inspect-button *doc-dialog*) nil))
+                  (#/setHidden: (hyperspec-button *doc-dialog*) nil)
+                  (#/setHidden: (inspect-button *doc-dialog*) nil)
+                  (#/setTitle: *doc-dialog* #@"Documentation")))
+           (setf (name *doc-dialog*) name)
+           (setf (symbol *doc-dialog*) symbol)
+           (setf (text-view *doc-dialog*) text-view)
+           (if hyperspec-p 
+             (#/setEnabled: (hyperspec-button *doc-dialog*) t)
+             (#/setEnabled: (hyperspec-button *doc-dialog*) nil))
+           (#/setStringValue: (name-field *doc-dialog*) name-string)
+           (#/setStringValue: (key-field *doc-dialog*) key-string)
+           (#/setString: (doc-text-view *doc-dialog*) (if doc (ccl::%make-nsstring doc) #@""))
+           (#/makeKeyAndOrderFront: *doc-dialog* nil))
+          (t
+           (let ((dialog (#/alloc doc-dialog)))
+             (setq *doc-dialog* dialog)
+             (ns:with-ns-rect (r 100 100 (if *graphic-p* 625 475) 230)
+               (#/initWithContentRect:styleMask:backing:defer: 
+                dialog
+                r
+                (logior  #$NSTitledWindowMask 
+                         #$NSClosableWindowMask  
+                         #$NSMiniaturizableWindowMask)
+                #$NSBackingStoreBuffered
+                #$NO))
+             (dolist (item (get-items dialog))
+               (#/addSubview: (#/contentView dialog) item))
+             (cond (hemlock-p
+                  (setf (hemlock-p dialog) t)
+                  (#/setTitle: dialog #@"Hemlock Command Documentation")
+                  (#/setHidden: (inspect-button dialog) t)
+                  (#/setHidden: (hyperspec-button dialog) t))
+                 (t
+                  (setf (hemlock-p dialog) nil)
+                  (if source-p
+                    (#/setEnabled: (source-button dialog) t)
+                    (#/setEnabled: (source-button dialog) nil))
+                  (if inspect-p
+                    (#/setEnabled: (inspect-button *doc-dialog*) t)
+                    (#/setEnabled: (inspect-button *doc-dialog*) nil))
+                  (#/setHidden: (hyperspec-button dialog) nil)
+                  (#/setHidden: (inspect-button dialog) nil)
+                  (#/setTitle: dialog #@"Documentation")))
+             (if hyperspec-p 
+               (#/setEnabled: (hyperspec-button *doc-dialog*) t)
+               (#/setEnabled: (hyperspec-button *doc-dialog*) nil))
+             (#/setReleasedWhenClosed: dialog nil)
+             (#/setDefaultButtonCell: dialog (okay-button dialog))
+             (#/center dialog)
+             (#/setStringValue: (name-field dialog) name-string)
+             (#/setStringValue: (key-field dialog) key-string)
+             (#/setString: (doc-text-view dialog) (if doc (ccl::%make-nsstring doc) #@""))
+             (setf (name dialog) name)
+             (setf (symbol dialog) symbol)
+             (setf (text-view dialog) text-view)
+             (#/makeKeyAndOrderFront: dialog nil))))))
+
+;;; This is a redefintion of the function in cl-documentation-1.lisp
+(defun cldoc::display-cl-doc (sym text-view)
+  "If there is CCL or MCL doc, use the doc-dialog to display documentation.  Otherwise use the HyperSpec."
+  (when (eq (symbol-package sym) (find-package :common-lisp))
+    (or (display-ccl-doc sym text-view)
+        (display-mcl-doc sym text-view)
+        (gui::lookup-hyperspec-symbol sym text-view))))
+
+(defmethod get-items ((d doc-dialog))
+  (append
+   (when *graphic-p* 
+     (make-hemlock-image))
+   (make-name-field d)
+   (make-key-field d)
+   (make-doc-text-view d)
+   (make-buttons d)))
+
+(defun make-hemlock-image ()
+  "Create the Hemlock graphic.  You can make this go away by set *graphic-p* to nil above."
+  (let ((image (#/alloc ns:ns-image))
+        (image-view (#/alloc ns:ns-image-view)))
+    (ns:with-ns-rect (frame 10 54 141 164)
+      (#/initWithFrame: image-view frame))
+    (#/initWithContentsOfFile: image (ccl::%make-nsstring (namestring *hemlock-jpg*)))
+    (#/setImage: image-view image)
+    (list image-view)))
+
+(defun make-name-field (dialog)
+  "Create the name text-field."
+  (list
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame (if *graphic-p* 165 15) 178 440 38)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title #@"")
+     (setf (name-field dialog) title))))
+
+(defun make-key-field (dialog)
+  "Create the key text-field."
+  (list
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame (if *graphic-p* 165 15) 162 450 16)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title #@"")
+     (setf (key-field dialog) title))))
+
+(defun make-doc-text-view (dialog)
+  "Create the documentation text-view."
+  (list
+   (let* ((scroll-view (#/alloc ns:ns-scroll-view))
+          (view (#/init (#/alloc ns:ns-text-view))))
+     (ns:with-ns-rect (frame (if *graphic-p* 165 15) 54 460 106)
+       (#/initWithFrame: scroll-view frame))
+     (ns:with-ns-rect (frame 4 60 445 200)
+       (#/initWithFrame: view frame))
+     (#/setString: view #@" ")
+     (#/setHasVerticalScroller: scroll-view t)
+     (#/setHasHorizontalScroller: scroll-view nil)
+     (#/setBorderType: scroll-view #$NSBezelBorder)
+     (#/setDocumentView: scroll-view view)
+     (#/setEditable: view nil)
+     (#/setFont: view (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)))
+     (#/setTextColor: view cmenu:*dark-turquoise-color*)
+     (#/setBackgroundColor: view cmenu:*light-gray-color*)
+     (setf (doc-text-view dialog) view)
+     scroll-view)))
+
+
+(defun make-buttons (dialog)
+  "Construct the buttons."
+  (flet ((make-button (title x-coord y-coord x-dim y-dim action)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame))
+             (#/setButtonType: button #$NSMomentaryPushInButton)
+             ; (#/setImagePosition: button #$NSNoImage)
+             (#/setBezelStyle: button #$NSRoundedBezelStyle)
+             (#/setTitle: button title)
+             (#/setTarget: button dialog)
+             (#/setAction: button action)
+             button)))
+    (list
+     (setf (okay-button dialog)
+           (make-button #@"Okay" (if *graphic-p* 520 370) 10 80 32
+                        (ccl::@selector "closeAction:")))
+     (setf (source-button dialog)
+           (make-button #@"Source..." (if *graphic-p* 420 270) 10 90 32
+                        (ccl::@selector "commandSourceAction:")))
+     (setf (inspect-button dialog)
+           (make-button #@"Inspect..." (if *graphic-p* 320 170) 10 90 32
+                        (ccl::@selector "inspectSymbolAction:")))
+     (setf (hyperspec-button dialog)
+           (make-button #@"HyperSpec..." (if *graphic-p* 180 30) 10 130 32
+                        (ccl::@selector "hyperSpecAction:"))))))
+
+
+
+
+
+
Index: /branches/new-random/contrib/foy/list-definitions-cm/history-lists.lisp
===================================================================
--- /branches/new-random/contrib/foy/list-definitions-cm/history-lists.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/list-definitions-cm/history-lists.lisp	(revision 13309)
@@ -0,0 +1,571 @@
+;;;-*- Mode: Lisp; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      history-lists.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code supports file and position history lists.
+;;;
+;;;      Alt-Right-Click produces a most-recently-visited list of definition 
+;;;      positions.  Alt-Command-Right-Click produces a most-recently-visited
+;;;      list of files.  Both lists are persistent and are stored here:
+;;;
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/file-history
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/position-history
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/31/9  version 0.2b2
+;;;              Modified to work with Context-Menu mechanism.
+;;;      8/17/9  version 0.2b1
+;;;              This file added.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "LIST-DEFINITIONS")
+
+(defParameter *position-history-list-length* 25)
+(defParameter *file-history-list-length* 25)
+
+(defun maybe-open-file (path)
+  "If a window with PATH is open, return it.  Otherwise open a new window."
+  (let ((w (cmenu:window-with-path path)))
+    (if w 
+      w
+      (let ((hemlock-view (gui::cocoa-edit path)))
+        (when hemlock-view (#/window (hi::hemlock-view-pane hemlock-view)))))))
+
+(defun construct-history-path (filename)
+  "Construct the path to the history file."
+    (merge-pathnames (concatenate 'string 
+                                  ";Library;Preferences;org.clairvaux;list-definitions;" 
+                                  filename)
+                     (hemlock::user-homedir-pathname)))
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST-ENTRY ()
+  ((name :initarg :name :reader hle-name)
+   (path :initarg :path :reader hle-path))
+  (:documentation "Support for the history lists."))  
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-LIST-ENTRY (history-list-entry) 
+  ((info :initarg :info :reader hle-info))
+  (:documentation "Support for the position history list."))
+
+(defMethod show-entry ((entry position-list-entry))
+  "Display the file and scroll to position."
+  (let* ((name (hle-name entry))
+         (path (hle-path entry))
+         (window (cmenu:window-with-path path))
+         mark def-list text-view hemlock-view)
+    (unless (probe-file path)
+      (cmenu:notify (format nil "~a does not exist.  It will be deleted from the history lists."
+                      path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (cond (window 
+           (setq hemlock-view (gui::hemlock-view window))
+           (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+          (t
+           (setq hemlock-view (gui::cocoa-edit path))
+           (when hemlock-view
+             (setq window (#/window (hi::hemlock-view-pane hemlock-view)))
+             (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))))
+    (when window
+      (#/makeKeyAndOrderFront: window nil)
+      (setq def-list (list-definitions window))
+      (setq mark (cdr (assoc name def-list 
+                             :test #'string-equal
+                             :key #'(lambda (def-info)
+                                      (let ((def-type (first def-info)))
+                                        (if (or (eq def-type :defmethod)
+                                                (eq def-type :objc))
+                                          (third def-info)
+                                          (second def-info)))))))
+      (cond (mark
+             (display-position text-view mark)
+             (move-entry-to-front *file-history-list* path) t)
+            (t 
+             (cmenu:notify (format nil "Cannot find ~S.  It will be deleted from the position history list." 
+                             name))
+             (remove-entry *position-history-list* name) nil)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-LIST-ENTRY (history-list-entry) 
+  ((short-path :initarg :short-path :accessor hle-short-path))
+  (:documentation "Support for the file history list."))
+
+(defMethod show-entry ((entry file-list-entry))
+  (let ((path (hle-path entry)))
+    (unless (probe-file path)
+      (cmenu:notify (format nil "~S does not exist.  It will be deleted from the history lists." path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (let ((window (cmenu:window-with-path path))) 
+      (unless window 
+        (let ((hemlock-view (gui::cocoa-edit path)))
+          (when hemlock-view 
+            (setq window (#/window (hi::hemlock-view-pane hemlock-view))))))
+      (when window
+        (#/makeKeyAndOrderFront: window nil) t))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST ()
+  ((capacity :initarg :capacity :reader hl-capacity)
+   (path :initarg :path :reader hl-path)
+   (list :initform nil :accessor hl-list))
+  (:documentation "Super class of position-history-list and file-history-list."))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited definition positions."))
+
+(setq *position-history-list* (make-instance 'position-history-list 
+                                :path (construct-history-path "position-history")
+                                :capacity *position-history-list-length*))
+
+(defMethod find-entry ((hl position-history-list) name)
+  (find-if  #'(lambda (entry) (string-equal name (hle-name entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl position-history-list) name)
+  (let ((entry (find-entry hl name)))
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+      entry)))
+
+(defMethod purge-file-references ((hl position-history-list) path)
+  (setf (hl-list hl) (delete-if #'(lambda (entry)
+                                    (equal (hle-path entry) path))
+                                (hl-list hl))))
+
+(defMethod remove-entry ((hl position-history-list) name)
+  (setf (hl-list hl) (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+
+(defMethod add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (second def-info))
+         (signature (third def-info))
+         (entry (make-instance 'position-list-entry 
+                  :name (if (or (eq def-type :defmethod)
+                                (eq def-type :objc))
+                          signature
+                          name)
+                  :info def-info :path path)))
+    (setf (hl-list hl) (cons entry (hl-list hl)))
+    entry))
+
+(defMethod maybe-add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (if (or (eq def-type :defmethod)
+                       (eq def-type :objc))
+                 (third def-info)
+                 (second def-info))))
+    (cond ((member name (hl-list hl) :test #'string-equal :key #'hle-name)
+           ;; it's there; move it to the front:
+           (move-entry-to-front hl name))
+          (t
+           (when (>= (length (hl-list hl)) (hl-capacity hl))
+             ;; bump the last entry, then add:
+             (setf (hl-list hl) (butlast (hl-list hl))))
+           (add-history-entry hl def-info path)))))
+
+(defun clear-position-history-list()
+  "Remove all the entries from the position history list."
+  (setf (hl-list *position-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited files."))
+
+(setf *file-history-list* (make-instance 'file-history-list
+                            :path (construct-history-path "file-history")
+                            :capacity *file-history-list-length*))
+
+(defMethod find-entry ((hl file-history-list) path)
+  (find-if  #'(lambda (entry) (string-equal path (hle-path entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl file-history-list) path)
+  (let ((entry (find-entry hl path))) 
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete path (hl-list hl) :test #'string-equal :key #'hle-path)))
+      entry)))
+
+(defmethod remove-path ((hl file-history-list) path)
+  (setf (hl-list hl) (delete path (hl-list hl) 
+                             :test #'string-equal :key #'hle-path)))
+
+(defMethod add-history-entry ((hl file-history-list) name path)
+  (let* ((name-position (position #\/ path :test #'char= :from-end t))
+         (short-path (when name-position (subseq path 0 (incf name-position))))
+         (entry (when short-path (make-instance 'file-list-entry :name name 
+                                   :short-path short-path :path path))))
+    (when entry
+      (setf (hl-list hl) (cons entry (hl-list hl)))
+      entry)))
+
+(defMethod maybe-add-history-entry ((hl file-history-list) name path)
+  (cond ((member path (hl-list hl) :test #'string-equal :key #'hle-path)
+         (move-entry-to-front hl path))
+        (t 
+         (cond ((< (length (hl-list hl)) (hl-capacity hl))
+                (add-history-entry hl name path))
+               (t 
+                (setf (hl-list hl) (butlast (hl-list hl)))
+                (add-history-entry hl name path))))))
+
+(defun clear-file-history-list ()
+  "Remove all the entries from the file history list."
+  (setf (hl-list *file-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITION-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor position-path)
+    (name :accessor position-name))
+  (:documentation "Support for the positions popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITIONS-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "position history" :reader sub-title))
+  (:documentation "A popup menu of most-recently-visited definition positions.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/positionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (let ((entry (find-entry *position-history-list* (position-name sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-entry *position-history-list* (position-name sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *position-history-list* (position-name sender)))))))
+
+(objc:defmethod (#/clearPositionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-position-history-list))
+
+(objc:defmethod (#/update :void) ((self positions-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(defun positions-context-menu ()
+  "Create the positions context menu."
+  (let* ((menu (make-instance 'positions-menu))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+          menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (setf (tool-menu menu) (cmenu:add-default-tool-menu menu))
+    (dolist (entry (hl-list *position-history-list*))
+      (let* ((def-info (hle-info entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (ccl::%make-nsstring signature)
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (setq menu-item (make-instance 'position-menu-item))
+        (setf (position-path menu-item) (hle-path entry))
+        (if (or (eq def-type :defmethod) (eq def-type :objc))
+          (setf (position-name menu-item) signature)
+          (setf (position-name menu-item) name))
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Classes have a prepended CCL icon:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "positionHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearPositionHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass FILE-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor file-path)
+    (name :accessor file-name))
+  (:documentation "Support for the files popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass FILE-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "file history" :reader sub-title))
+  (:documentation "A popup menu of most-recently-visited files.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/fileHistoryAction: :void) ((m file-menu) (sender :id))
+  (let ((entry (find-entry *file-history-list* (file-path sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-path *file-history-list* (file-path sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *file-history-list* (file-path sender)))))))
+
+(objc:defmethod (#/update :void) ((self file-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(objc:defmethod (#/clearFileHistoryAction: :void) ((m file-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-file-history-list))
+
+(defun files-context-menu ()
+  "Create the files context menu."
+  (let* ((menu (make-instance 'file-menu))
+          menu-item)
+    (setf (tool-menu menu) (cmenu:add-default-tool-menu menu))
+    (dolist (entry (hl-list *file-history-list*))
+      (let ((attributed-string (#/initWithString:attributes:
+                                (#/alloc ns:ns-attributed-string) 
+                                (ccl::%make-nsstring 
+                                 (format nil "~A  ~A" 
+                                         (hle-name entry)
+                                         (hle-short-path entry)))
+                                *file-history-dictionary*)))
+        (setq menu-item (make-instance 'file-menu-item))
+        (setf (file-name menu-item) (hle-name entry))
+        (setf (file-path menu-item) (hle-path entry))
+        (#/setAttributedTitle: menu-item attributed-string)
+        (#/setAction: menu-item (ccl::@selector "fileHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearFileHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; File I/O
+;;;
+(defun read-history-files ()
+  "Read the position and file history lists."
+  (let ((path (hl-path *file-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *file-history-list* stream))))
+  (let ((path (hl-path *position-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *position-history-list* stream t)))))
+
+(defMethod read-history-list ((hl history-list) stream &optional position-p)
+  (flet ((oops ()
+           (cmenu:notify (format nil "There is a problem with ~S. Setting the history to NIL." (hl-path hl)))
+           (setf (hl-list hl) nil)
+           ;;; delete the file?
+           (return-from read-history-list)))
+    (setf (hl-list hl) nil)
+    ;; For the position-history-list, ufo is the def-info list.
+    ;; For the file-history-list, ufo is the filename string.
+    (let (length ufo path input)
+      (setf input (read stream nil :eof))
+      (unless (numberp input) (oops))
+      (setf length input)
+      (dotimes (count length t)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (if position-p
+                    (not (listp input))
+                    (not (stringp input))))
+          (oops))
+        (setf ufo input)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (not (stringp input)))
+          (oops))
+        (setf path input)
+        (when (null (add-history-entry hl ufo path))
+          (oops))))))
+
+(defMethod write-history-list ((hl position-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-info entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defMethod write-history-list ((hl file-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-name entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defun write-history-files ()
+  "Write the history list entries to the path."
+  (let ((path (hl-path *position-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *position-history-list* stream)))
+  (let ((path (hl-path *file-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *file-history-list* stream))))
+
+(defun write-history-files-on-shutdown (&rest args)
+  "Writing function pushed into *lisp-cleanup-functions*."
+  (declare (ignore args))
+  (write-history-files))
+
+(defun read-history-files-on-startup (&rest args)
+  "Reading function (eventually) pushed into *lisp-startup-functions*."
+  (declare (ignore args))
+  (read-history-files))
+
+(pushnew 'write-history-files-on-shutdown ccl::*lisp-cleanup-functions*)
+
+;;; To Do:
+;;; Heap issues involved in saving an image with the utility loaded.
+;;; (pushnew 'read-history-files-on-startup ccl::*lisp-startup-functions*)
+
+;;; ----------------------------------------------------------------------------
+;;; File History Interface:
+;;;
+;;; *** Instead of doing all this stuff need the equivalent of:
+;;; *** (setf ccl::*default-editor-class* 'derived-hemlock-frame-class)
+#-syntax-styling 
+(objc:defMethod (#/becomeKeyWindow :void) ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path)))
+  (let ((become-key-function (find-symbol "BECOME-KEY-WINDOW" (find-package :sax))))
+    (when become-key-function (funcall become-key-function w)))
+  (call-next-method))
+
+#+syntax-styling
+(defMethod become-key-window ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path))))
+
+;;; ----------------------------------------------------------------------------
+;;; Position History Interface:
+;;; 
+(hemlock::defcommand "Add Definition Position" (p)
+  "Add the position of the definition containing point to *position-history-list*."
+  (declare (ignore p))
+  (let* ((buffer (hemlock::current-buffer))
+         (mark (hi::copy-mark (hemlock::buffer-point buffer) :temporary))
+         (path (hi::buffer-pathname buffer))
+         (start-mark (hi::top-level-offset mark -1))
+         (def-info (when start-mark (definition-info start-mark))))
+    (when (and def-info path)
+      (maybe-add-history-entry *position-history-list* def-info path))))
+
+(hemlock::bind-key "Add Definition Position" #k"control-shift-space")
+
+(defun add-top-level-position (&optional buffer)
+  "Maybe add the top-level definition position to the position history list."
+  (let* ((buf (or buffer (hi::current-buffer)))
+         (mark (hi::copy-mark (hemlock::buffer-point buf) :temporary))
+         (path (hi::buffer-pathname buf))
+         start-mark def-info)
+    (if (and (= (hi::mark-charpos mark) 0)
+             (char= (hi::next-character mark) #\())
+      (setq start-mark mark)
+      (setq start-mark (hemlock::top-level-offset mark -1)))
+    (when start-mark
+      (let* ((line-end (hi::line-end (hi::copy-mark start-mark :temporary)))
+             (def-mark (hi::copy-mark start-mark :temporary))
+             (objc-mark (hi::copy-mark start-mark :temporary))
+             (def-p (hi::find-pattern def-mark *def-search-pattern* line-end))
+             (objc-p (hi::find-pattern objc-mark *objc-defmethod-search-pattern* line-end)))
+        (cond (def-p
+               (setq def-info (definition-info start-mark)))
+              (objc-p
+               (setq def-info (definition-info start-mark t)))))
+      (when (and def-info path)
+        (maybe-add-history-entry *position-history-list* def-info path)))))
+
+;;; *** These three redefinitions are not a great way of doing this ***
+;;; *** Where's CLOS when you need it ...
+(hemlock::defcommand "Editor Evaluate Defun" (p)
+  "Evaluates the current or next top-level form in the editor Lisp.
+   If the current region is active, this evaluates the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+    (hemlock::editor-evaluate-region-command nil)
+    (hemlock::eval-region (hemlock::defun-region (hi::current-point))))
+  (add-top-level-position))
+
+(hemlock::defcommand "Editor Compile Defun" (p)
+  "Compiles the current or next top-level form in the editor Lisp.
+   First the form is evaluated, then the result of this evaluation
+   is passed to compile.  If the current region is active, this
+   compiles the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+      (hemlock::editor-compile-region (hemlock::current-region))
+      (hemlock::editor-compile-region (hemlock::defun-region (hi::current-point)) t))
+  (add-top-level-position))
+
+;;; gui::cocoa-edit-single-definition didn't last long.
+;;; This one's days are numbered:
+(defun hemlock::move-point-leaving-mark (target)
+  (let ((point (hi::current-point-collapsing-selection)))
+    (hemlock::push-new-buffer-mark point)
+    (hi::move-mark point target)
+    (add-top-level-position (hi::current-buffer))
+    point))
+
+
+(read-history-files)
+
+;;; Hemlock-Commands needs this, for now:
+(pushnew :list-definitions *features*)
Index: /branches/new-random/contrib/foy/list-definitions-cm/list-definitions-cm.lisp
===================================================================
--- /branches/new-random/contrib/foy/list-definitions-cm/list-definitions-cm.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/list-definitions-cm/list-definitions-cm.lisp	(revision 13309)
@@ -0,0 +1,22 @@
+
+;;; list-definitions.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "LIST-DEFINITIONS-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *list-definitions-directory-string*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *list-definition-files* 
+    (list (merge-pathnames ";list-definitions.lisp" *list-definitions-directory-string*)
+          (merge-pathnames ";history-lists.lisp" *list-definitions-directory-string*))))
+ 
+(dolist (file *list-definition-files*)
+  (load file))
+
+(provide :list-definitions-cm)
+
+)
Index: /branches/new-random/contrib/foy/list-definitions-cm/list-definitions.lisp
===================================================================
--- /branches/new-random/contrib/foy/list-definitions-cm/list-definitions.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/list-definitions-cm/list-definitions.lisp	(revision 13309)
@@ -0,0 +1,383 @@
+;;;-*-Mode: LISP; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      list-definitions.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a dynamic contextual popup menu to Hemlock.
+;;;
+;;;      Right-Click produces an alphabetized listing of the file's definitions.  
+;;;      Command-Right-Click produces a positional listing.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/19/9  Added parse-over-block to list-definitions.
+;;;      8/31/9  Modified to work with Context-Menu mechanism.
+;;;              Numerous interface suggestions, Rainer Joswig.
+;;;      8/17/9  Added position history list and file history list.
+;;;      8/12/9  Numerous interface suggestions, Alexander Repenning.
+;;;      8/10/9  First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "LIST-DEFINITIONS" (:nicknames "LDEFS") (:use :cl :ccl))
+(in-package "LIST-DEFINITIONS")
+
+(require :context-menu-cm)
+
+(export '(find-and-display-definition window-path active-hemlock-window))
+
+(defParameter *objc-defmethod-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(objc:defmethod"))
+(defParameter *def-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(def"))
+(defParameter *left-paren-search-pattern* (hi::new-search-pattern :character :forward #\())
+(defParameter *colon-search-pattern* (hi::new-search-pattern :character :forward #\:))
+(defParameter *slash-search-pattern* (hi::new-search-pattern :character :forward #\/))
+
+(defVar *position-history-list* nil "The position-history-list instance.")
+(defVar *file-history-list* nil "The file-history-list instance.")
+
+(defmacro clone (mark) `(hi::copy-mark ,mark :temporary))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu (ns:ns-menu)
+  ((text-view :initarg :menu-text-view :reader menu-text-view)
+   (path :initarg :menu-path :reader menu-path) ; *** history-path
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*list-definitions-directory-string*) :reader doc-path)
+   (tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform nil :initarg :sub-title :reader sub-title))
+  (:documentation "The definitions popup menu.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/listDefinitionsAction: :void) ((m list-definitions-menu) (sender :id))
+  (display-position (menu-text-view m) (item-mark sender))
+  (maybe-add-history-entry *position-history-list* (item-info sender) (menu-path m)))
+
+ (objc:defmethod (#/update :void) ((self list-definitions-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(defun display-position (text-view mark)
+  "Display the position of MARK in TEXT-VIEW."
+  (let* ((def-pos (hi::mark-absolute-position mark))
+         (def-end-pos (let ((temp-mark (clone mark)))
+                        (when (hemlock::form-offset temp-mark 1)
+                          (hi::mark-absolute-position temp-mark)))))
+    (unless def-end-pos (when def-pos (setq def-end-pos (1+ def-pos))))
+    (when (and def-pos def-end-pos)
+      (ns:with-ns-range (range def-pos (- def-end-pos def-pos))
+        (#/scrollRangeToVisible: text-view range))
+      (hi::move-mark (hi::buffer-point (gui::hemlock-buffer text-view)) mark)
+      (gui::update-paren-highlight text-view))))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu-item (ns:ns-menu-item)
+  ((mark :accessor item-mark)
+   (path :accessor item-path)
+   (info :accessor item-info))
+  (:documentation "Support for the definitions list menu.")
+  (:metaclass ns:+ns-object))
+
+(defparameter *dark-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.2 0.2 0.5 1.0))
+(defparameter *dark-green-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.3 0.1 1.0))
+(defparameter *dark-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.1 0.1 0.1 1.0))
+(defparameter *dark-brown-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.3 0.05 0.0 1.0))
+(defparameter *dark-turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.2 0.3 1.0))
+(defparameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.4 0.1 0.2 1.0))
+
+(defparameter *generic-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *generic-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *generic-dictionary* *dark-gray-color* #&NSForegroundColorAttributeName)
+
+(defparameter *file-history-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *file-history-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *file-history-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defclass-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defclass-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defclass-dictionary* *wine-red-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defclass-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defstruct-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defstruct-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defmethod-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmethod-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmethod-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defun-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defun-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defun-dictionary* *dark-green-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defmacro-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmacro-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmacro-dictionary* *dark-brown-color* #&NSForegroundColorAttributeName)
+
+(defparameter *objc-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *objc-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *objc-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+;;; This is not retained -- assumming autorelease.
+(defun list-definitions-context-menu (text-view &optional alpha-p)
+  "Construct the list-definitions popup menu."
+  (let* ((menu (make-instance 'list-definitions-menu 
+                 :sub-title (if alpha-p "alphabetical" "positional")
+                 :menu-text-view text-view 
+                 :menu-path (cmenu:window-path (#/window text-view))))
+         (window (cmenu:active-hemlock-window))
+         (alist (when window (list-definitions window alpha-p)))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+         current-class menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (setf (tool-menu menu) 
+          (if alpha-p
+            (cmenu:add-default-tool-menu menu :doc-file (doc-path menu))
+            (cmenu:add-default-tool-menu menu)))
+    (dolist (entry alist)
+      (let* ((def-info (car entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (specializer (fourth def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 ;; indent methods if directly under specializing class or struct:
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (if (and (not alpha-p)
+                                            current-class specializer
+                                            (string-equal specializer current-class))
+                                     (ccl::%make-nsstring (format nil "      ~A" signature))
+                                     (ccl::%make-nsstring (format nil "~A" signature)))
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (when (or (eq def-type :defclass) (eq def-type :defstruct)) (setq current-class name))
+        (setq menu-item (make-instance 'list-definitions-menu-item))
+        (setf (item-mark menu-item) (cdr entry))
+        (setf (item-info menu-item) def-info)
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Prepend CCL icon to class names:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "listDefinitionsAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    menu))
+
+(defun get-list-definitions-menu (view event)
+  (let ((view-window (#/window view)))
+    (#/makeKeyAndOrderFront: view-window nil)
+    (if (logtest #$NSAlternateKeyMask (#/modifierFlags event))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (files-context-menu)
+        (positions-context-menu))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (list-definitions-context-menu view nil)
+        (list-definitions-context-menu view t)))))
+
+;;; This includes definitions in sharp-stroke comments.  We'll claim it's a feature.
+(defun list-definitions (hemlock &optional alpha-p)
+  "Create a list of all the top-level definitions in the file."
+  (labels ((get-name (entry)
+             (let ((def-info (car entry)))
+               (second def-info)))
+           (get-defs (mark pattern &optional objc-p)
+             (do ((def-found-p (hi::find-pattern mark pattern)
+                               (hi::find-pattern mark pattern))
+                  alist)
+                 ((not def-found-p) (when alist
+                                      (if alpha-p 
+                                        (sort alist #'string-lessp :key #'get-name) 
+                                        (nreverse alist))))
+               (when (zerop (hi::mark-charpos mark)) 
+                 (let ((def-info (definition-info (clone mark) objc-p)))
+                   (when def-info
+                     (push (cons def-info (hi::line-start (clone mark))) alist))))
+               (hi::line-end mark))))
+    (let* ((pane (slot-value hemlock 'gui::pane))
+           (text-view (gui::text-pane-text-view pane))
+           (buffer (gui::hemlock-buffer text-view))
+           (hi::*current-buffer* buffer))
+      (hemlock::parse-over-block (hi::mark-line (hi::buffer-start-mark buffer))
+                                 (hi::mark-line (hi::buffer-end-mark buffer)))
+      (let* ((def-mark (clone (hi::buffer-start-mark buffer)))
+             (objc-mark (clone (hi::buffer-start-mark buffer)))
+             (def-alist (get-defs def-mark *def-search-pattern*))
+             (objc-alist (get-defs objc-mark *objc-defmethod-search-pattern* t)))
+        (when objc-alist
+          (setq def-alist
+                (if alpha-p
+                  (merge 'list def-alist objc-alist #'string-lessp :key #'get-name)
+                  (merge 'list def-alist objc-alist #'hi::mark< :key #'cdr))))
+        def-alist))))
+
+(defun definition-info (mark &optional objc-p)
+  "Returns (type name) or (type name signature specializer) for methods."
+  (flet ((substring-equal (string len)
+           (string-equal string 
+                         (hi::region-to-string 
+                          (hi::region mark (hi::character-offset (clone mark) len))))))
+    (let* ((def-type (cond (objc-p :objc)
+                           ((substring-equal "(defmethod" 10) :defmethod)
+                           ((substring-equal "(defun" 6) :defun)
+                           ((substring-equal "(defmacro" 9) :defmacro)
+                           ((substring-equal "(defclass" 9) :defclass)
+                           ((substring-equal "(defstruct" 10) :defstruct)
+                           (t :other)))
+           (end (let ((temp-mark (clone mark)))
+                  (when (hemlock::form-offset (hi::mark-after temp-mark) 2)
+                    temp-mark)))
+           (start (when end
+                    (let ((temp-mark (clone end)))
+                      (when (hemlock::form-offset temp-mark -1)
+                        temp-mark)))))
+      (when (and start end)
+        (let ((name (hi::region-to-string (hi::region start end)))
+              param-string specializer)
+          (when (and (stringp name) (string-not-equal name ""))
+            (case def-type
+              (:defmethod
+                  (let ((qualifier-start-mark (clone end))
+                        (left-paren-mark (clone end))
+                        right-paren-mark qualifier-end-mark qualifier-string)
+                    (when (hi::find-pattern left-paren-mark *left-paren-search-pattern*)
+                      (setq right-paren-mark (clone left-paren-mark))
+                      (when (hemlock::form-offset right-paren-mark 1)
+                        (multiple-value-setq (param-string specializer)
+                          (parse-parameters (clone left-paren-mark) right-paren-mark))))
+                    (when (hi::find-pattern qualifier-start-mark *colon-search-pattern* left-paren-mark)
+                      (setq qualifier-end-mark (clone qualifier-start-mark))
+                      (when (hemlock::form-offset qualifier-end-mark 1)
+                        (setq qualifier-string
+                              (hi::region-to-string (hi::region qualifier-start-mark qualifier-end-mark)))))
+                    (if qualifier-string
+                      ;; name is used to simplify the alpha sort:
+                      (list def-type name (format nil "(~A ~A ~A)" name qualifier-string param-string) specializer)
+                      (list def-type name (format nil "(~A ~A)" name param-string) specializer))))
+              (:objc
+               (let* ((name-start-mark (let ((temp-mark (clone start)))
+                                         (when (hi::find-pattern temp-mark *slash-search-pattern*)
+                                           (hi::mark-after temp-mark))))
+                      (name-end-mark (when name-start-mark
+                                       (let ((temp-mark (clone name-start-mark)))
+                                         (when (hemlock::form-offset temp-mark 1)
+                                           temp-mark))))
+                      (objc-name (when (and name-start-mark name-end-mark) 
+                                   (hi::region-to-string (hi::region name-start-mark name-end-mark))))
+                      (left-paren-mark (let ((temp-mark (clone end)))
+                                         (when (hi::find-pattern temp-mark *left-paren-search-pattern*)
+                                           temp-mark)))
+                      (right-paren-mark (when left-paren-mark 
+                                          (let ((temp-mark (clone left-paren-mark)))
+                                            (when (hi::form-offset temp-mark 1)
+                                              temp-mark)))))
+                 (when (and left-paren-mark right-paren-mark)
+                   (multiple-value-setq (param-string specializer)
+                     (parse-parameters left-paren-mark right-paren-mark t))
+                   ;; Using curly braces to distinguish objc methods from Lisp methods:
+                   (list def-type objc-name (format nil "{~A ~A}" objc-name param-string) specializer))))
+              (:defstruct
+                  (cond ((char= (hi::next-character start) #\()
+                         (let* ((space-position (position #\space name :test #'char=))
+                                (new-name (when space-position (subseq name 1 space-position))))
+                           (if new-name
+                             (list def-type new-name)
+                             (list def-type name))))
+                        (t
+                         (list def-type name))))
+              (t
+               (list def-type name)))))))))
+
+(defun parse-parameters (start-mark end-mark &optional objc-p)
+  "Construct the method's parameter string."
+  (let (specializers-processed-p specializer)
+    (flet ((get-param (start end)
+             (let ((next-character (hi::next-character start)))
+               (when (char= next-character #\&) (setq specializers-processed-p t))
+               (cond ((and (char= next-character #\() (not specializers-processed-p))
+                      (let* ((specializer-end (when (hemlock::form-offset (hi::mark-after start) 2) start))
+                             (specializer-start (when specializer-end (clone specializer-end))))
+                        (when (and specializer-end specializer-start
+                                   (hemlock::form-offset specializer-start -1)
+                                   (hi::mark< specializer-end end))
+                          (when objc-p (setq specializers-processed-p t))
+                          (hi::region-to-string (hi::region specializer-start specializer-end)))))
+                     (t 
+                      (unless (char= next-character #\&)
+                        (format nil "t")))))))
+      (do* ((sexp-end (let ((temp-mark (hi::mark-after (clone start-mark))))
+                        (when (hemlock::form-offset temp-mark 1) temp-mark))
+                      (when (hemlock::form-offset (hi::mark-after sexp-end) 1) sexp-end))
+            (sexp-start (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark)))
+                        (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark))))
+            (param-string (when (and sexp-start sexp-end) (get-param (clone sexp-start) 
+                                                                     (clone sexp-end)))
+                          (when (and sexp-start sexp-end) (get-param (clone sexp-start)
+                                                                     (clone sexp-end))))
+            (first-param-p t)
+            parameters)
+           ((or (null sexp-start) (null sexp-end) 
+                (hi::mark> sexp-start end-mark)
+                ;; Empty body case:
+                (hi::mark< sexp-start start-mark))
+            (values (concatenate 'string parameters ")") specializer))
+        (when param-string
+          (cond (first-param-p
+                 (setq parameters (concatenate 'string "(" param-string))
+                 (setq specializer param-string)
+                 (setq first-param-p nil))
+                (t
+                 (setq parameters (concatenate 'string parameters " " param-string)))))))))
+
+;;; This is used by the Hemlock-Commands tool.  
+(defun find-and-display-definition (name path)
+  "Display the file and scroll to the definition position."
+  (let ((window (cmenu:window-with-path path))
+         mark def-list text-view hemlock-view)
+    (unless (probe-file path)
+      (cmenu:notify (format nil "~a does not exist."
+                      path))
+      (return-from find-and-display-definition nil))
+    (cond (window 
+           (setq hemlock-view (gui::hemlock-view window))
+           (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+          (t
+           (setq hemlock-view (gui::cocoa-edit path))
+           (when hemlock-view
+             (setq window (#/window (hi::hemlock-view-pane hemlock-view)))
+             (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))))
+    (when window
+      (#/makeKeyAndOrderFront: window nil)
+      (setq def-list (list-definitions window))
+      (setq mark (cdr (assoc name def-list 
+                             :test #'string-equal
+                             :key #'(lambda (def-info)
+                                      (let ((def-type (first def-info)))
+                                        (if (or (eq def-type :defmethod)
+                                                (eq def-type :objc))
+                                          (third def-info)
+                                          (second def-info)))))))
+      (when mark (display-position text-view mark)))))
+
+
+(cmenu:register-tool "List-Definitions-CM" #'get-list-definitions-menu)
+
Index: /branches/new-random/contrib/foy/list-definitions/history-lists.lisp
===================================================================
--- /branches/new-random/contrib/foy/list-definitions/history-lists.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/list-definitions/history-lists.lisp	(revision 13309)
@@ -0,0 +1,566 @@
+;;;-*- Mode: Lisp; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      history-lists.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code supports file and position history lists.
+;;;
+;;;      Alt-Right-Click produces a most-recently-visited list of definition 
+;;;      positions.  Alt-Command-Right-Click produces a most-recently-visited
+;;;      list of files.  Both lists are persistent and are stored here:
+;;;
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/file-history
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/position-history
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/17/9  version 0.2b1
+;;;              This file added.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "LIST-DEFINITIONS")
+
+(defParameter *position-history-list-length* 25)
+(defParameter *file-history-list-length* 25)
+
+;;; This includes a work-around for what appears to be a bug in the hemlock-frame
+;;; #/close method.  After a #/close, the window remains on the (#/orderedWindows *NSApp*)
+;;; list, but (hi::buffer-document buffer) in NIL.  Therefore the extra tests:
+(defun window-with-path (path)
+  "If a window with PATH is open, return it."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (when (and (typep w 'gui::hemlock-frame)
+                  (not (typep w 'gui::hemlock-listener-frame)))
+         (let* ((pane (slot-value w 'gui::pane))
+                (text-view (gui::text-pane-text-view pane))
+                (buffer (gui::hemlock-buffer text-view))
+                (document (when buffer (hi::buffer-document buffer)))
+                (p (hi::buffer-pathname buffer)))
+           (when (and document p) (string-equal path p)))))))
+
+(defun maybe-open-file (path)
+  "If a window with PATH is open, return it.  Otherwise open a new window."
+  (let ((w (window-with-path path)))
+    (if w 
+      w
+      (let ((hemlock-view (gui::cocoa-edit path)))
+        (when hemlock-view (#/window (hi::hemlock-view-pane hemlock-view)))))))
+
+(defun construct-history-path (filename)
+  "Construct the path to the history file."
+    (merge-pathnames (concatenate 'string 
+                                  ";Library;Preferences;org.clairvaux;list-definitions;" 
+                                  filename)
+                     (hemlock::user-homedir-pathname)))
+
+(defun notify (message)
+  "FYI"
+  (gui::alert-window :title "Notification" :message message))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST-ENTRY ()
+  ((name :initarg :name :reader hle-name)
+   (path :initarg :path :reader hle-path))
+  (:documentation "Support for the history lists."))  
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-LIST-ENTRY (history-list-entry) 
+  ((info :initarg :info :reader hle-info))
+  (:documentation "Support for the position history list."))
+
+(defMethod show-entry ((entry position-list-entry))
+  "Display the file and scroll to position."
+  (let* ((name (hle-name entry))
+         (path (hle-path entry))
+         (window (window-with-path path))
+         mark def-list text-view hemlock-view)
+    (unless (probe-file path)
+      (notify (format nil "~a does not exist.  It will be deleted from the history lists."
+                      path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (cond (window 
+           (setq hemlock-view (gui::hemlock-view window))
+           (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+          (t
+           (setq hemlock-view (gui::cocoa-edit path))
+           (when hemlock-view
+             (setq window (#/window (hi::hemlock-view-pane hemlock-view)))
+             (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))))
+    (when window
+      (#/makeKeyAndOrderFront: window nil)
+      (setq def-list (list-definitions window))
+      (setq mark (cdr (assoc name def-list 
+                             :test #'string-equal
+                             :key #'(lambda (def-info)
+                                      (let ((def-type (first def-info)))
+                                        (if (or (eq def-type :defmethod)
+                                                (eq def-type :objc))
+                                          (third def-info)
+                                          (second def-info)))))))
+      (cond (mark
+             (display-position text-view mark)
+             (move-entry-to-front *file-history-list* path) t)
+            (t 
+             (notify (format nil "Cannot find ~S.  It will be deleted from the position history list." 
+                             name))
+             (remove-entry *position-history-list* name) nil)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-LIST-ENTRY (history-list-entry) 
+  ((short-path :initarg :short-path :accessor hle-short-path))
+  (:documentation "Support for the file history list."))
+
+(defMethod show-entry ((entry file-list-entry))
+  (let ((path (hle-path entry)))
+    (unless (probe-file path)
+      (notify (format nil "~S does not exist.  It will be deleted from the history lists." path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (let ((window (window-with-path path))) 
+      (unless window 
+        (let ((hemlock-view (gui::cocoa-edit path)))
+          (when hemlock-view 
+            (setq window (#/window (hi::hemlock-view-pane hemlock-view))))))
+      (when window
+        (#/makeKeyAndOrderFront: window nil) t))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST ()
+  ((capacity :initarg :capacity :reader hl-capacity)
+   (path :initarg :path :reader hl-path)
+   (list :initform nil :accessor hl-list))
+  (:documentation "Super class of position-history-list and file-history-list."))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited definition positions."))
+
+(setq *position-history-list* (make-instance 'position-history-list 
+                                :path (construct-history-path "position-history")
+                                :capacity *position-history-list-length*))
+
+(defMethod find-entry ((hl position-history-list) name)
+  (find-if  #'(lambda (entry) (string-equal name (hle-name entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl position-history-list) name)
+  (let ((entry (find-entry hl name)))
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+      entry)))
+
+(defMethod purge-file-references ((hl position-history-list) path)
+  (setf (hl-list hl) (delete-if #'(lambda (entry)
+                                    (equal (hle-path entry) path))
+                                (hl-list hl))))
+
+(defMethod remove-entry ((hl position-history-list) name)
+  (setf (hl-list hl) (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+
+(defMethod add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (second def-info))
+         (signature (third def-info))
+         (entry (make-instance 'position-list-entry 
+                  :name (if (or (eq def-type :defmethod)
+                                (eq def-type :objc))
+                          signature
+                          name)
+                  :info def-info :path path)))
+    (setf (hl-list hl) (cons entry (hl-list hl)))
+    entry))
+
+(defMethod maybe-add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (if (or (eq def-type :defmethod)
+                       (eq def-type :objc))
+                 (third def-info)
+                 (second def-info))))
+    (cond ((member name (hl-list hl) :test #'string-equal :key #'hle-name)
+           ;; it's there; move it to the front:
+           (move-entry-to-front hl name))
+          (t
+           (when (>= (length (hl-list hl)) (hl-capacity hl))
+             ;; bump the last entry, then add:
+             (setf (hl-list hl) (butlast (hl-list hl))))
+           (add-history-entry hl def-info path)))))
+
+(defun clear-position-history-list()
+  "Remove all the entries from the position history list."
+  (setf (hl-list *position-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited files."))
+
+(setf *file-history-list* (make-instance 'file-history-list
+                            :path (construct-history-path "file-history")
+                            :capacity *file-history-list-length*))
+
+(defMethod find-entry ((hl file-history-list) path)
+  (find-if  #'(lambda (entry) (string-equal path (hle-path entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl file-history-list) path)
+  (let ((entry (find-entry hl path))) 
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete path (hl-list hl) :test #'string-equal :key #'hle-path)))
+      entry)))
+
+(defmethod remove-path ((hl file-history-list) path)
+  (setf (hl-list hl) (delete path (hl-list hl) 
+                             :test #'string-equal :key #'hle-path)))
+
+(defMethod add-history-entry ((hl file-history-list) name path)
+  (let* ((name-position (position #\/ path :test #'char= :from-end t))
+         (short-path (when name-position (subseq path 0 (incf name-position))))
+         (entry (when short-path (make-instance 'file-list-entry :name name 
+                                   :short-path short-path :path path))))
+    (when entry
+      (setf (hl-list hl) (cons entry (hl-list hl)))
+      entry)))
+
+(defMethod maybe-add-history-entry ((hl file-history-list) name path)
+  (cond ((member path (hl-list hl) :test #'string-equal :key #'hle-path)
+         (move-entry-to-front hl path))
+        (t 
+         (cond ((< (length (hl-list hl)) (hl-capacity hl))
+                (add-history-entry hl name path))
+               (t 
+                (setf (hl-list hl) (butlast (hl-list hl)))
+                (add-history-entry hl name path))))))
+
+(defun clear-file-history-list ()
+  "Remove all the entries from the file history list."
+  (setf (hl-list *file-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITION-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor position-path)
+    (name :accessor position-name))
+  (:documentation "Support for the positions popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITIONS-MENU (ns:ns-menu)
+  ()
+  (:documentation "A popup menu of most-recently-visited definition positions.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/positionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (let ((entry (find-entry *position-history-list* (position-name sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-entry *position-history-list* (position-name sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *position-history-list* (position-name sender)))))))
+
+(objc:defmethod (#/clearPositionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-position-history-list))
+
+(defun positions-context-menu ()
+  "Create the positions context menu."
+  (let* ((menu (make-instance 'positions-menu))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+          menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (dolist (entry (hl-list *position-history-list*))
+      (let* ((def-info (hle-info entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (ccl::%make-nsstring signature)
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (setq menu-item (make-instance 'position-menu-item))
+        (setf (position-path menu-item) (hle-path entry))
+        (if (or (eq def-type :defmethod) (eq def-type :objc))
+          (setf (position-name menu-item) signature)
+          (setf (position-name menu-item) name))
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Classes have a prepended CCL icon:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "positionHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearPositionHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass FILE-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor file-path)
+    (name :accessor file-name))
+  (:documentation "Support for the files popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass FILE-MENU (ns:ns-menu)
+  ()
+  (:documentation "A popup menu of most-recently-visited files.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/fileHistoryAction: :void) ((m file-menu) (sender :id))
+  (let ((entry (find-entry *file-history-list* (file-path sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-path *file-history-list* (file-path sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *file-history-list* (file-path sender)))))))
+
+(objc:defmethod (#/clearFileHistoryAction: :void) ((m file-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-file-history-list))
+
+(defun files-context-menu ()
+  "Create the files context menu."
+  (let* ((menu (make-instance 'file-menu))
+          menu-item)
+    (dolist (entry (hl-list *file-history-list*))
+      (let ((attributed-string (#/initWithString:attributes:
+                                (#/alloc ns:ns-attributed-string) 
+                                (ccl::%make-nsstring 
+                                 (format nil "~A  ~A" 
+                                         (hle-name entry)
+                                         (hle-short-path entry)))
+                                *file-history-dictionary*)))
+        (setq menu-item (make-instance 'file-menu-item))
+        (setf (file-name menu-item) (hle-name entry))
+        (setf (file-path menu-item) (hle-path entry))
+        (#/setAttributedTitle: menu-item attributed-string)
+        (#/setAction: menu-item (ccl::@selector "fileHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearFileHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; File I/O
+;;;
+(defun read-history-files ()
+  "Read the position and file history lists."
+  (let ((path (hl-path *file-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *file-history-list* stream))))
+  (let ((path (hl-path *position-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *position-history-list* stream t)))))
+
+(defMethod read-history-list ((hl history-list) stream &optional position-p)
+  (flet ((oops ()
+           (notify (format nil "There is a problem with ~S. Setting the history to NIL." (hl-path hl)))
+           (setf (hl-list hl) nil)
+           ;;; delete the file?
+           (return-from read-history-list)))
+    (setf (hl-list hl) nil)
+    ;; For the position-history-list, ufo is the def-info list.
+    ;; For the file-history-list, ufo is the filename string.
+    (let (length ufo path input)
+      (setf input (read stream nil :eof))
+      (unless (numberp input) (oops))
+      (setf length input)
+      (dotimes (count length t)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (if position-p
+                    (not (listp input))
+                    (not (stringp input))))
+          (oops))
+        (setf ufo input)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (not (stringp input)))
+          (oops))
+        (setf path input)
+        (when (null (add-history-entry hl ufo path))
+          (oops))))))
+
+(defMethod write-history-list ((hl position-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-info entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defMethod write-history-list ((hl file-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-name entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defun write-history-files ()
+  "Write the history list entries to the path."
+  (let ((path (hl-path *position-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *position-history-list* stream)))
+  (let ((path (hl-path *file-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *file-history-list* stream))))
+
+(defun write-history-files-on-shutdown (&rest args)
+  "Writing function pushed into *lisp-cleanup-functions*."
+  (declare (ignore args))
+  (write-history-files))
+
+(defun read-history-files-on-startup (&rest args)
+  "Reading function (eventually) pushed into *lisp-startup-functions*."
+  (declare (ignore args))
+  (read-history-files))
+
+(pushnew 'write-history-files-on-shutdown ccl::*lisp-cleanup-functions*)
+
+;;; To Do:
+;;; Heap issues involved in saving an image with the utility loaded.
+;;; (pushnew 'read-history-files-on-startup ccl::*lisp-startup-functions*)
+
+;;; ----------------------------------------------------------------------------
+;;; File History Interface:
+;;;
+;;; *** Instead of doing all this stuff need the equivalent of:
+;;; *** (setf ccl::*default-editor-class* 'derived-hemlock-frame-class)
+#-syntax-styling 
+(objc:defMethod (#/becomeKeyWindow :void) ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path)))
+  (let ((become-key-function (find-symbol "BECOME-KEY-WINDOW" (find-package :sax))))
+    (when become-key-function (funcall become-key-function w)))
+  (call-next-method))
+
+#+syntax-styling
+(defMethod become-key-window ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path))))
+
+;;; ----------------------------------------------------------------------------
+;;; Position History Interface:
+;;; 
+(hemlock::defcommand "Add Definition Position" (p)
+  "Add the position of the definition containing point to *position-history-list*."
+  (declare (ignore p))
+  (let* ((buffer (hemlock::current-buffer))
+         (mark (hi::copy-mark (hemlock::buffer-point buffer) :temporary))
+         (path (hi::buffer-pathname buffer))
+         (start-mark (hi::top-level-offset mark -1))
+         (def-info (when start-mark (definition-info start-mark))))
+    (when (and def-info path)
+      (maybe-add-history-entry *position-history-list* def-info path))))
+
+(hemlock::bind-key "Add Definition Position" #k"control-shift-space")
+
+;;; *** buffer?
+(defun add-top-level-position (&optional buffer)
+  "Maybe add the top-level definition position to the position history list."
+  (let* ((buf (or buffer (hi::current-buffer)))
+         (mark (hi::copy-mark (hemlock::buffer-point buf) :temporary))
+         (path (hi::buffer-pathname buf))
+         start-mark def-info)
+    (if (and (= (hi::mark-charpos mark) 0)
+             (char= (hi::next-character mark) #\())
+      (setq start-mark mark)
+      (setq start-mark (hemlock::top-level-offset mark -1)))
+    (when start-mark
+      (setq def-info (definition-info start-mark))
+      (when (and def-info path)
+        (maybe-add-history-entry *position-history-list* def-info path)))))
+
+;;; *** These three redefinitions are not a great way of doing this ***
+;;; *** Where's CLOS when you need it ...
+(hemlock::defcommand "Editor Evaluate Defun" (p)
+  "Evaluates the current or next top-level form in the editor Lisp.
+   If the current region is active, this evaluates the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+    (hemlock::editor-evaluate-region-command nil)
+    (hemlock::eval-region (hemlock::defun-region (hi::current-point))))
+  (add-top-level-position))
+
+(hemlock::defcommand "Editor Compile Defun" (p)
+  "Compiles the current or next top-level form in the editor Lisp.
+   First the form is evaluated, then the result of this evaluation
+   is passed to compile.  If the current region is active, this
+   compiles the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+      (hemlock::editor-compile-region (hemlock::current-region))
+      (hemlock::editor-compile-region (hemlock::defun-region (hi::current-point)) t))
+  (add-top-level-position))
+
+;;; gui::cocoa-edit-single-definition didn't last long.
+;;; This one's days are numbered:
+(defun hemlock::move-point-leaving-mark (target)
+  (let ((point (hi::current-point-collapsing-selection)))
+    (hemlock::push-new-buffer-mark point)
+    (hi::move-mark point target)
+    (add-top-level-position (hi::current-buffer))
+    point))
+
+
+(read-history-files)
Index: /branches/new-random/contrib/foy/list-definitions/list-definitions.lisp
===================================================================
--- /branches/new-random/contrib/foy/list-definitions/list-definitions.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/list-definitions/list-definitions.lisp	(revision 13309)
@@ -0,0 +1,350 @@
+;;;-*-Mode: LISP; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      list-definitions.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a dynamic contextual popup menu to Hemlock.
+;;;
+;;;      Right-Click produces an alphabetized listing of the file's definitions.  
+;;;      Command-Right-Click produces a positional listing.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/19/9  Added parse-over-block to list-definitions.
+;;;      8/17/9  Added position history list and file history list.
+;;;      8/12/9  Numerous interface suggestions, Alexander Repenning.
+;;;      8/10/9  First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+
+(defpackage "LIST-DEFINITIONS" (:nicknames "LDEFS") (:use :cl :ccl))
+(in-package "LIST-DEFINITIONS")
+
+(defParameter *objc-defmethod-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(objc:defmethod"))
+(defParameter *def-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(def"))
+(defParameter *left-paren-search-pattern* (hi::new-search-pattern :character :forward #\())
+(defParameter *colon-search-pattern* (hi::new-search-pattern :character :forward #\:))
+(defParameter *slash-search-pattern* (hi::new-search-pattern :character :forward #\/))
+
+(defVar *position-history-list* nil "The position-history-list instance.")
+(defVar *file-history-list* nil "The file-history-list instance.")
+
+(defmacro clone (mark) `(hi::copy-mark ,mark :temporary))
+
+(defun active-hemlock-window ()
+  "Return the active hemlock-frame."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (and (typep w 'gui::hemlock-frame)
+            (not (typep w 'gui::hemlock-listener-frame))
+            (#/isKeyWindow w)))))
+
+(defun window-path (w)
+  "Return the window's path."
+  (let* ((pane (slot-value w 'gui::pane))
+         (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+         (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+    (when buffer (hi::buffer-pathname buffer))))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu (ns:ns-menu)
+  ((text-view :initarg :menu-text-view :reader menu-text-view)
+   (path :initarg :menu-path :reader menu-path))
+  (:documentation "The definitions popup menu.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/listDefinitionsAction: :void) ((m list-definitions-menu) (sender :id))
+  (display-position (menu-text-view m) (item-mark sender))
+  (maybe-add-history-entry *position-history-list* (item-info sender) (menu-path m)))
+
+(defun display-position (text-view mark)
+  "Display the position of MARK in TEXT-VIEW."
+  (let* ((def-pos (hi::mark-absolute-position mark))
+         (def-end-pos (let ((temp-mark (clone mark)))
+                        (when (hemlock::form-offset temp-mark 1)
+                          (hi::mark-absolute-position temp-mark)))))
+    (unless def-end-pos (when def-pos (setq def-end-pos (1+ def-pos))))
+    (when (and def-pos def-end-pos)
+      (ns:with-ns-range (range def-pos (- def-end-pos def-pos))
+        (#/scrollRangeToVisible: text-view range))
+      (hi::move-mark (hi::buffer-point (gui::hemlock-buffer text-view)) mark)
+      (gui::update-paren-highlight text-view))))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu-item (ns:ns-menu-item)
+  ((mark :accessor item-mark)
+   (path :accessor item-path)
+   (info :accessor item-info))
+  (:documentation "Support for the definitions list menu.")
+  (:metaclass ns:+ns-object))
+
+(defparameter *dark-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.2 0.2 0.5 1.0))
+(defparameter *dark-green-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.3 0.1 1.0))
+(defparameter *dark-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.1 0.1 0.1 1.0))
+(defparameter *dark-brown-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.3 0.05 0.0 1.0))
+(defparameter *dark-turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.2 0.3 1.0))
+(defparameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.4 0.1 0.2 1.0))
+
+(defparameter *generic-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *generic-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *generic-dictionary* *dark-gray-color* #&NSForegroundColorAttributeName)
+
+(defparameter *file-history-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *file-history-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *file-history-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defclass-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defclass-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defclass-dictionary* *wine-red-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defclass-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defstruct-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defstruct-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defmethod-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmethod-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmethod-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defun-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defun-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defun-dictionary* *dark-green-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defmacro-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmacro-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmacro-dictionary* *dark-brown-color* #&NSForegroundColorAttributeName)
+
+(defparameter *objc-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *objc-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *objc-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+;;; This is not retained -- assumming autorelease.
+(defun list-definitions-context-menu (text-view &optional alpha-p)
+  "Construct the list-definitions popup menu."
+  (let* ((menu (make-instance 'list-definitions-menu 
+                 :menu-text-view text-view 
+                 :menu-path (window-path (#/window text-view))))
+         (window (active-hemlock-window))
+         (alist (when window (list-definitions window alpha-p)))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+         current-class menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (dolist (entry alist)
+      (let* ((def-info (car entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (specializer (fourth def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 ;; indent methods if directly under specializing class or struct:
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (if (and (not alpha-p)
+                                            current-class specializer
+                                            (string-equal specializer current-class))
+                                     (ccl::%make-nsstring (format nil "      ~A" signature))
+                                     (ccl::%make-nsstring (format nil "~A" signature)))
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (when (or (eq def-type :defclass) (eq def-type :defstruct)) (setq current-class name))
+        (setq menu-item (make-instance 'list-definitions-menu-item))
+        (setf (item-mark menu-item) (cdr entry))
+        (setf (item-info menu-item) def-info)
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Prepend CCL icon to class names:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "listDefinitionsAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    menu))
+
+(objc:defmethod #/menuForEvent: ((view gui::hemlock-text-view) (event :id))
+  (let ((view-window (#/window view)))
+    (#/makeKeyAndOrderFront: view-window nil)
+    (if (logtest #$NSAlternateKeyMask (#/modifierFlags event))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (files-context-menu)
+        (positions-context-menu))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (list-definitions-context-menu view nil)
+        (list-definitions-context-menu view t)))))
+
+;;; This includes definitions in sharp-stroke comments.  We'll claim it's a feature.
+(defun list-definitions (hemlock &optional alpha-p)
+  "Create a list of all the top-level definitions in the file."
+  (labels ((get-name (entry)
+             (let ((def-info (car entry)))
+               (second def-info)))
+           (get-defs (mark pattern &optional objc-p)
+             (do ((def-found-p (hi::find-pattern mark pattern)
+                               (hi::find-pattern mark pattern))
+                  alist)
+                 ((not def-found-p) (when alist
+                                      (if alpha-p 
+                                        (sort alist #'string-lessp :key #'get-name) 
+                                        (nreverse alist))))
+               (when (zerop (hi::mark-charpos mark)) 
+                 (let ((def-info (definition-info (clone mark) objc-p)))
+                   (when def-info
+                     (push (cons def-info (hi::line-start (clone mark))) alist))))
+               (hi::line-end mark))))
+    (let* ((pane (slot-value hemlock 'gui::pane))
+           (text-view (gui::text-pane-text-view pane))
+           (buffer (gui::hemlock-buffer text-view))
+           (hi::*current-buffer* buffer))
+      (hemlock::parse-over-block (hi::mark-line (hi::buffer-start-mark buffer))
+                                 (hi::mark-line (hi::buffer-end-mark buffer)))
+      (let* ((def-mark (clone (hi::buffer-start-mark buffer)))
+             (objc-mark (clone (hi::buffer-start-mark buffer)))
+             (def-alist (get-defs def-mark *def-search-pattern*))
+             (objc-alist (get-defs objc-mark *objc-defmethod-search-pattern* t)))
+        (when objc-alist
+          (setq def-alist
+                (if alpha-p
+                  (merge 'list def-alist objc-alist #'string-lessp :key #'get-name)
+                  (merge 'list def-alist objc-alist #'hi::mark< :key #'cdr))))
+        def-alist))))
+
+(defun definition-info (mark &optional objc-p)
+  "Returns (type name) or (type name signature specializer) for methods."
+  (flet ((substring-equal (string len)
+           (string-equal string 
+                         (hi::region-to-string 
+                          (hi::region mark (hi::character-offset (clone mark) len))))))
+    (let* ((def-type (cond (objc-p :objc)
+                           ((substring-equal "(defmethod" 10) :defmethod)
+                           ((substring-equal "(defun" 6) :defun)
+                           ((substring-equal "(defmacro" 9) :defmacro)
+                           ((substring-equal "(defclass" 9) :defclass)
+                           ((substring-equal "(defstruct" 10) :defstruct)
+                           (t :other)))
+           (end (let ((temp-mark (clone mark)))
+                  (when (hemlock::form-offset (hi::mark-after temp-mark) 2)
+                    temp-mark)))
+           (start (when end
+                    (let ((temp-mark (clone end)))
+                      (when (hemlock::form-offset temp-mark -1)
+                        temp-mark)))))
+      (when (and start end)
+        (let ((name (hi::region-to-string (hi::region start end)))
+              param-string specializer)
+          (when (and (stringp name) (string-not-equal name ""))
+            (case def-type
+              (:defmethod
+                  (let ((qualifier-start-mark (clone end))
+                        (left-paren-mark (clone end))
+                        right-paren-mark qualifier-end-mark qualifier-string)
+                    (when (hi::find-pattern left-paren-mark *left-paren-search-pattern*)
+                      (setq right-paren-mark (clone left-paren-mark))
+                      (when (hemlock::form-offset right-paren-mark 1)
+                        (multiple-value-setq (param-string specializer)
+                          (parse-parameters (clone left-paren-mark) right-paren-mark))))
+                    (when (hi::find-pattern qualifier-start-mark *colon-search-pattern* left-paren-mark)
+                      (setq qualifier-end-mark (clone qualifier-start-mark))
+                      (when (hemlock::form-offset qualifier-end-mark 1)
+                        (setq qualifier-string
+                              (hi::region-to-string (hi::region qualifier-start-mark qualifier-end-mark)))))
+                    (if qualifier-string
+                      ;; name is used to simplify the alpha sort:
+                      (list def-type name (format nil "(~A ~A ~A)" name qualifier-string param-string) specializer)
+                      (list def-type name (format nil "(~A ~A)" name param-string) specializer))))
+              (:objc
+               (let* ((name-start-mark (let ((temp-mark (clone start)))
+                                         (when (hi::find-pattern temp-mark *slash-search-pattern*)
+                                           (hi::mark-after temp-mark))))
+                      (name-end-mark (when name-start-mark
+                                       (let ((temp-mark (clone name-start-mark)))
+                                         (when (hemlock::form-offset temp-mark 1)
+                                           temp-mark))))
+                      (objc-name (when (and name-start-mark name-end-mark) 
+                                   (hi::region-to-string (hi::region name-start-mark name-end-mark))))
+                      (left-paren-mark (let ((temp-mark (clone end)))
+                                         (when (hi::find-pattern temp-mark *left-paren-search-pattern*)
+                                           temp-mark)))
+                      (right-paren-mark (when left-paren-mark 
+                                          (let ((temp-mark (clone left-paren-mark)))
+                                            (when (hi::form-offset temp-mark 1)
+                                              temp-mark)))))
+                 (when (and left-paren-mark right-paren-mark)
+                   (multiple-value-setq (param-string specializer)
+                     (parse-parameters left-paren-mark right-paren-mark t))
+                   ;; Using curly braces to distinguish objc methods from Lisp methods:
+                   (list def-type objc-name (format nil "{~A ~A}" objc-name param-string) specializer))))
+              (:defstruct
+                  (cond ((char= (hi::next-character start) #\()
+                         (let* ((space-position (position #\space name :test #'char=))
+                                (new-name (when space-position (subseq name 1 space-position))))
+                           (if new-name
+                             (list def-type new-name)
+                             (list def-type name))))
+                        (t
+                         (list def-type name))))
+              (t
+               (list def-type name)))))))))
+
+(defun parse-parameters (start-mark end-mark &optional objc-p)
+  "Construct the method's parameter string."
+  (let (specializers-processed-p specializer)
+    (flet ((get-param (start end)
+             (let ((next-character (hi::next-character start)))
+               (when (char= next-character #\&) (setq specializers-processed-p t))
+               (cond ((and (char= next-character #\() (not specializers-processed-p))
+                      (let* ((specializer-end (when (hemlock::form-offset (hi::mark-after start) 2) start))
+                             (specializer-start (when specializer-end (clone specializer-end))))
+                        (when (and specializer-end specializer-start
+                                   (hemlock::form-offset specializer-start -1)
+                                   (hi::mark< specializer-end end))
+                          (when objc-p (setq specializers-processed-p t))
+                          (hi::region-to-string (hi::region specializer-start specializer-end)))))
+                     (t 
+                      (unless (char= next-character #\&)
+                        (format nil "t")))))))
+      (do* ((sexp-end (let ((temp-mark (hi::mark-after (clone start-mark))))
+                        (when (hemlock::form-offset temp-mark 1) temp-mark))
+                      (when (hemlock::form-offset (hi::mark-after sexp-end) 1) sexp-end))
+            (sexp-start (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark)))
+                        (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark))))
+            (param-string (when (and sexp-start sexp-end) (get-param (clone sexp-start) 
+                                                                     (clone sexp-end)))
+                          (when (and sexp-start sexp-end) (get-param (clone sexp-start)
+                                                                     (clone sexp-end))))
+            (first-param-p t)
+            parameters)
+           ((or (null sexp-start) (null sexp-end) 
+                (hi::mark> sexp-start end-mark)
+                ;; Empty body case:
+                (hi::mark< sexp-start start-mark))
+            (values (concatenate 'string parameters ")") specializer))
+        (when param-string
+          (cond (first-param-p
+                 (setq parameters (concatenate 'string "(" param-string))
+                 (setq specializer param-string)
+                 (setq first-param-p nil))
+                (t
+                 (setq parameters (concatenate 'string parameters " " param-string)))))))))
+
+
+
Index: /branches/new-random/contrib/foy/list-definitions/load-list-definitions.lisp
===================================================================
--- /branches/new-random/contrib/foy/list-definitions/load-list-definitions.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/list-definitions/load-list-definitions.lisp	(revision 13309)
@@ -0,0 +1,23 @@
+
+;;; load-list-definitions.lisp 
+
+(in-package :cl-user)
+
+(unless (member "LIST-DEFINITIONS" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *list-definitions-directory-string*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *list-definition-files* 
+    (list (merge-pathnames ";list-definitions.lisp" *list-definitions-directory-string*)
+          (merge-pathnames ";history-lists.lisp" *list-definitions-directory-string*))))
+ 
+(dolist (file *list-definition-files*)
+  (load file))
+
+(provide :list-definitions)
+
+
+)
Index: /branches/new-random/contrib/foy/source-comparison/source-compare-dialog.lisp
===================================================================
--- /branches/new-random/contrib/foy/source-comparison/source-compare-dialog.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/source-comparison/source-compare-dialog.lisp	(revision 13309)
@@ -0,0 +1,470 @@
+;;;-*- Mode: Lisp; Package: SOURCE-COMPARE -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      source-compare-dialog.lisp, version 0.1b1
+;;;
+;;;      copyright Â© 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This file provides a GUI for Mark Kantrowitz's source-compare.lisp.
+;;;      See source-compare.lisp for documentation.  
+;;;
+;;;      The GUI portion is straight forward.  The browse buttons let you browse 
+;;;      to select the two target files.  The Hemlock buttons will pull in the file 
+;;;      in the top Hemlock window.  
+;;;
+;;;      When the utility prints a diff specification, Alt-Double-Click it to
+;;;      pull up the relevant code in Hemlock windows.  There are various types of
+;;;      diff specs.  A typical one looks like this: 559,565c544,546
+;;;      
+;;;      The most recent version will be available at: www.clairvaux.org/downloads/
+;;;
+;;;      This code is offered "as is" without warranty of any kind.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "SOURCE-COMPARE")
+
+(defConstant %dialog-width% 675)
+(defConstant %dialog-height% 410)
+
+(defParameter *source-compare-dialog* nil)
+
+(defun open-source-compare-dialog ()
+  (#/makeKeyAndOrderFront: *source-compare-dialog* nil))
+
+#|
+(setq *source-compare-dialog* nil)
+
+(gui::execute-in-gui 'open-source-compare-dialog)
+|#
+
+;;; This includes a work-around for what appears to be a bug in the hemlock-frame
+;;; #/close method.  After a #/close, the window remains on the (#/orderedWindows *NSApp*)
+;;; list, but (hi::buffer-document buffer) in NIL.  Therefore the extra tests:
+(defun display-hemlock-position (path start-line &optional end-line)
+  (labels ((window-buffer (w)
+             (let* ((pane (slot-value w 'gui::pane))
+                    (hemlock-view (gui::text-pane-hemlock-view pane)))
+               (hi::hemlock-view-buffer hemlock-view)))
+           (window-with-path (target-path)
+             (gui::first-window-satisfying-predicate 
+              #'(lambda (w)
+                  (when (and (typep w 'gui::hemlock-frame)
+                             (not (typep w 'gui::hemlock-listener-frame)))
+                    (let* ((buffer (window-buffer w))
+                           (document (when buffer (hi::buffer-document buffer)))
+                           (buffer-path (when buffer (hi::buffer-pathname buffer))))
+                      (when (and document (stringp buffer-path))
+                        (string-equal target-path buffer-path))))))))
+    (let* ((w (window-with-path path))
+           (hemlock-view (cond (w 
+                                (gui::hemlock-view w))
+                               (t
+                                (let ((view (gui::cocoa-edit path)))
+                                  (when view
+                                    (setq w (#/window (hi::hemlock-view-pane view)))
+                                    view)))))
+           (text-pane (when w (slot-value w 'gui::pane)))
+           (text-view (when text-pane (gui::text-pane-text-view text-pane)))
+           (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view)))
+           (hi::*current-buffer* buffer)
+           (start-mark (when (and buffer start-line)
+                         (let ((temp (hi::copy-mark (hi::buffer-start-mark buffer) :temporary)))
+                           (when (hi::line-offset temp (1- start-line))
+                             temp))))
+           (start-pos (when start-mark (hi::mark-absolute-position start-mark)))
+           (end-mark (when (and buffer end-line)
+                         (let ((temp (hi::copy-mark (hi::buffer-start-mark buffer) :temporary)))
+                           (when (hi::line-offset temp (1- end-line))
+                             (hi::line-end temp)))))
+           (end-pos (if end-mark 
+                      (hi::mark-absolute-position end-mark)
+                      (when (and start-pos start-mark)
+                        (let ((temp (hi::copy-mark start-mark :temporary)))
+;                          (when (hi::line-offset temp 1)
+                          (hi::mark-absolute-position (hi::line-end temp)))))))
+      (when (and w text-view start-mark start-pos)
+        (#/makeKeyAndOrderFront: w nil)
+        (when (and start-pos end-pos)
+          (ns:with-ns-range (range start-pos (- end-pos start-pos))
+            (#/scrollRangeToVisible: text-view range)
+            (#/setSelectedRange: text-view range))
+          (hi::move-mark (hi::buffer-point buffer) start-mark)
+          (gui::update-paren-highlight text-view))))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass sc-text-view (ns:ns-text-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/mouseDown: :void) ((self sc-text-view) event)
+  (cond ((and (logtest #$NSAlternateKeyMask (#/modifierFlags event))
+              (= (#/clickCount event) 2))
+         ; (#/selectWord: self self)
+         (call-next-method event)
+         (let* ((range (#/selectedRange self))
+                (substring (#/substringWithRange: (#/string self) range)))
+           (process-diff-string (#/window self) (ccl::lisp-string-from-nsstring substring))))
+        (t
+         (call-next-method event))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass SOURCE-COMPARE-WINDOW (ns:ns-window)
+  ((path-1 :initform nil :accessor path-1)
+   (path-1-field :foreign-type :id :initform nil :accessor path-1-field)
+   (path-2 :initform nil :accessor path-2)
+   (path-2-field :foreign-type :id :initform nil :accessor path-2-field)
+   (difference-pane :foreign-type :id :initform nil :accessor difference-pane)
+   (ignore-case-check-box :foreign-type :id :initform nil :accessor ignore-case-check-box)
+   (ignore-whitespace-check-box :foreign-type :id :initform nil :accessor ignore-whitespace-check-box)
+   (ignore-comments-check-box :foreign-type :id :initform nil :accessor ignore-comments-check-box)
+   (ignore-blank-lines-check-box :foreign-type :id :initform nil :accessor ignore-blank-lines-check-box)
+   (print-context-check-box :foreign-type :id :initform nil :accessor print-context-check-box)
+   (print-fancy-header-check-box :foreign-type :id :initform nil :accessor print-fancy-header-check-box)
+   (compare-button :initform nil :accessor compare-button)
+   (action-alist :initform nil :accessor action-alist))
+  (:metaclass ns:+ns-object))
+
+;;; This is called for all GUI actions.  The source-compare-window is always the target.
+;;; Doing it this way means we can use lambdas in the code below rather than
+;;; writing a bunch of objc functions.  Old MCL habits die hard.
+(objc:defmethod (#/interfaceAction: :void) ((w source-compare-window) (sender :id))
+  (let ((pair (assoc sender (action-alist w))))
+    (cond (pair
+           ;; dispatch:
+           (funcall (cdr pair) sender))
+          (t
+           (error "~%Action function not found for ~S" sender)))))
+
+(defmethod clear-difference-pane ((w source-compare-window))
+  (#/setString: (difference-pane w) #@""))
+
+(defmethod process-diff-string ((w source-compare-window) string)
+  (when (and string
+             (every #'(lambda (char)
+                        (member char
+                                '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
+                                      #\c #\a #\d #\,)))
+                    string))
+    (let* ((alpha-char-pos (find-if #'(lambda (char) (alpha-char-p char)) string))
+           (position (position alpha-char-pos string))
+           (lhs (subseq string 0 position))
+           (rhs (subseq string (1+ position)))
+           (lhs-comma (position #\, lhs))
+           (rhs-comma (position #\, rhs))
+           lhs-start lhs-end rhs-start rhs-end)
+      
+      (cond (lhs-comma
+             (setf lhs-start (read-from-string (subseq lhs 0 lhs-comma)))
+             (setf lhs-end (read-from-string (subseq lhs (1+ lhs-comma))))
+             (display-hemlock-position (path-1 w) lhs-start lhs-end))
+            (t
+             (setf lhs-start (read-from-string lhs))
+             (display-hemlock-position (path-1 w) lhs-start)))
+      
+      (cond (rhs-comma
+             (setf rhs-start (read-from-string (subseq rhs 0 rhs-comma)))
+             (setf rhs-end (read-from-string (subseq rhs (1+ rhs-comma))))
+             (display-hemlock-position (path-2 w) rhs-start rhs-end))
+            (t
+             (setf rhs-start (read-from-string rhs))
+             ;; single line 
+             (display-hemlock-position (path-2 w) rhs-start))))))
+          
+(defMethod get-scmp-items ((w source-compare-window))
+  (append 
+   (make-path-items w)
+   (make-button-items w)
+   (make-check-boxes w)
+   (make-miscel-items w)))
+
+(defMethod make-check-boxes ((w source-compare-window))
+  (flet ((make-check-box (title x-coord y-coord x-dim y-dim checked-p)
+           (let ((box (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: box frame))
+             (#/setButtonType: box #$NSSwitchButton)
+             (#/setTitle: box title)
+             (#/setState: box (if checked-p #$NSOnState #$NSOffState))
+             box)))
+    (list
+     (setf (ignore-case-check-box w)
+           (make-check-box #@"ignore case" 10 30 130 20 t))
+
+     (setf (ignore-comments-check-box w)
+           (make-check-box #@"ignore comments" 160 30 130 20 t))
+
+     (setf (ignore-whitespace-check-box w)
+           (make-check-box #@"ignore whitespace" 310 30 130 20 t))
+
+     (setf (ignore-blank-lines-check-box w)
+           (make-check-box #@"ignore blank lines" 10 10 130 20 t))
+
+     (setf (print-context-check-box w)
+           (make-check-box #@"ignore context lines" 160 10 140 20 t))
+
+     (setf (print-fancy-header-check-box w)
+           (make-check-box #@"print fancy header" 310 10 140 20 nil)))))
+
+(defMethod make-button-items ((w source-compare-window))
+  (flet ((make-button (title x-coord y-coord x-dim y-dim lambda)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame)
+               (#/setButtonType: button #$NSMomentaryPushInButton)
+               (#/setImagePosition: button #$NSNoImage)
+               (#/setBezelStyle: button #$NSRoundedBezelStyle))
+             (#/setTitle: button title)
+             (#/setTarget: button w)
+             (#/setAction: button (ccl::@selector "interfaceAction:"))
+             (pushnew (cons button lambda) (action-alist w))
+             button))
+         (front-hemlock-window ()
+           (gui::first-window-satisfying-predicate 
+            #'(lambda (w)
+                (and (typep w 'gui::hemlock-frame)
+                     (not (typep w 'gui::hemlock-listener-frame))))))
+                     ;; (#/isKeyWindow w)))))
+         (window-pathname (w)
+           (when w
+             (let* ((pane (slot-value w 'gui::pane))
+                    (text-view (gui::text-pane-text-view pane))
+                    (buffer (gui::hemlock-buffer text-view)))
+               (hi::buffer-pathname buffer)))))
+
+    (list (make-button #@"Browse" 480 368 80 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let ((path (gui::cocoa-choose-file-dialog :button-string "select")))
+                             (when path
+                               (clear-difference-pane w)
+                               (setf (path-1 w) path)
+                               (#/setStringValue: (path-1-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Browse" 480 338 80 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let ((path (gui::cocoa-choose-file-dialog :button-string "select")))
+                             (when path
+                               (clear-difference-pane w)
+                               (setf (path-2 w) path)
+                               (#/setStringValue: (path-2-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Hemlock" 570 368 90 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let* ((window (front-hemlock-window))
+                                  (path (when window (window-pathname window))))
+                             (when path 
+                               (clear-difference-pane w)
+                               (setf (path-1 w) path)
+                               (#/setStringValue: (path-1-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Hemlock" 570 338 90 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let* ((window (front-hemlock-window))
+                                  (path (when window (window-pathname window))))
+                             (when path 
+                               (clear-difference-pane w)
+                               (setf (path-2 w) path)
+                               (#/setStringValue: (path-2-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Cancel" 480 10 80 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (#/close w)))
+
+          (setf (compare-button w)
+                (make-button #@"Compare" 570 10 90 32
+                             #'(lambda (item)
+                                 (declare (ignore item))
+                                 (compare w)))))))
+
+(defMethod compare ((w source-compare-window))
+
+  (cond ((and (path-1 w) (path-2 w))
+         (unless (probe-file (path-1 w))
+           (format t "~%; File: ~A does not exist." (path-1 w))
+           (return-from compare))
+         (unless (probe-file (path-2 w))
+           (format t "~%; File: ~A does not exist." (path-2 w))
+           (return-from compare))
+
+         (let ((stream (make-string-output-stream)))         
+           ;; out with the old 
+           (#/setString: (difference-pane w) #@" ")
+           (source-compare (path-1 w) (path-2 w)
+                           :output-stream stream
+                           :ignore-case (eql (#/state (ignore-case-check-box w)) #$NSOnState)
+                           :ignore-whitespace (eql (#/state (ignore-whitespace-check-box w)) #$NSOnState)
+                           :ignore-comments (eql (#/state (ignore-comments-check-box w)) #$NSOnState)
+                           :ignore-blank-lines (eql (#/state (ignore-blank-lines-check-box w)) #$NSOnState)
+                           :print-context (eql (#/state (print-context-check-box w)) #$NSOnState)
+                           :print-fancy-header (eql (#/state (print-fancy-header-check-box w)) #$NSOnState))
+           (#/setString: (difference-pane w) (ccl::%make-nsstring (ccl::get-output-stream-string stream)))))
+        (t
+         (#/setString: (difference-pane w) #@"First enter two valid paths."))))
+
+(defMethod make-path-items ((w source-compare-window))
+  (let* ((small-sys-size (#/smallSystemFontSize ns:ns-font))
+         (small-sys-font (#/systemFontOfSize: ns:ns-font small-sys-size)))
+    (list
+     (setf (path-1-field w)
+           (let ((field (#/alloc ns:ns-text-field)))
+             (ns:with-ns-rect (frame 30 375 435 15)
+               (#/initWithFrame: field frame)
+               (#/setEditable: field nil)
+               (#/setDrawsBackground: field nil)
+               (#/setBordered: field nil)
+               (#/setFont: field small-sys-font)
+               (#/setStringValue: field #@""))
+             field))
+     
+     (setf (path-2-field w)
+           (let ((field (#/alloc ns:ns-text-field)))
+             (ns:with-ns-rect (frame 30 345 435 15)
+               (#/initWithFrame: field frame)
+               (#/setEditable: field nil)
+               (#/setDrawsBackground: field nil)
+               (#/setBordered: field nil)
+               (#/setFont: field small-sys-font)
+               (#/setStringValue: field #@""))
+             field)))))
+
+(defMethod make-miscel-items ((w source-compare-window))
+  (list
+   (let* ((scroll-view (#/alloc ns:ns-scroll-view))
+          (view (#/init (#/alloc sc-text-view))))
+     (ns:with-ns-rect (frame 4 60 650 200)
+       (#/initWithFrame: scroll-view frame))
+     (ns:with-ns-rect (frame 4 60 650 200)
+       (#/initWithFrame: view frame))
+     (#/insertText: view #@" ")
+     (#/setHasVerticalScroller: scroll-view t)
+     (#/setHasHorizontalScroller: scroll-view t)
+     (#/setBorderType: scroll-view #$NSBezelBorder)
+     (#/setDocumentView: scroll-view view)
+     (#/setEditable: view nil)
+     (setf (difference-pane w) view)
+     scroll-view)
+
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 5 370 22 22)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     ;; (#/setFont: title style-font)
+     (#/setStringValue: title #@"1:")
+     title)
+
+   (let ((box (#/alloc ns:ns-box)))
+      (ns:with-ns-rect (frame 25 370 450 40)
+        (#/initWithFrame: box frame))
+     (#/setTitle: box #@"")
+     box)
+
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 5 340 22 22)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     ;; (#/setFont: title style-font)
+     (#/setStringValue: title #@"2:")
+     title)
+
+   (let ((box (#/alloc ns:ns-box)))
+      (ns:with-ns-rect (frame 25 340 450 40)
+        (#/initWithFrame: box frame))
+     (#/setTitle: box #@"")
+     box)
+
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 10 310 500 22)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     ;; (#/setFont: title style-font)
+     (#/setStringValue: title #@"Mods required to make file 1 equivalent to file 2:")
+     title)
+
+  (let* ((small-sys-size (#/smallSystemFontSize ns:ns-font))
+         (small-sys-font (#/systemFontOfSize: ns:ns-font small-sys-size))
+         (title (#/alloc ns:ns-text-field)))
+    (ns:with-ns-rect (frame 10 290 500 22)
+      (#/initWithFrame: title frame))
+    (#/setEditable: title nil)
+    (#/setDrawsBackground: title nil)
+    (#/setBordered: title nil)
+    (#/setFont: title small-sys-font)
+    (#/setStringValue: title #@"(a = add, d = delete, c = change, < = file 1, > = file 2)")
+    title)
+
+  (let* ((small-sys-size (#/smallSystemFontSize ns:ns-font))
+         (small-sys-font (#/systemFontOfSize: ns:ns-font small-sys-size))
+         (title (#/alloc ns:ns-text-field)))
+    (ns:with-ns-rect (frame 10 270 500 22)
+      (#/initWithFrame: title frame))
+    (#/setEditable: title nil)
+    (#/setDrawsBackground: title nil)
+    (#/setBordered: title nil)
+    (#/setFont: title small-sys-font)
+    (#/setStringValue: title #@"(To display the relevant code, alt-double-click the difference spec, ie 559,565c544,546)")
+    title)))
+
+(setq *source-compare-dialog*
+      (let ((dialog (#/alloc source-compare-window)))
+        (ns:with-ns-rect (r 100 100 %dialog-width% %dialog-height%)
+          (#/initWithContentRect:styleMask:backing:defer: 
+           dialog
+           r
+           (logior  #$NSTitledWindowMask 
+                    #$NSClosableWindowMask  
+                    #$NSMiniaturizableWindowMask)
+           #$NSBackingStoreBuffered
+           #$NO))
+        (#/setTitle: dialog #@"Source Comparison")
+        (dolist (item (get-scmp-items dialog))
+          (#/addSubview: (#/contentView  dialog) item))
+        (#/setDefaultButtonCell: dialog (compare-button dialog))
+        (#/setReleasedWhenClosed: dialog nil)
+        (#/center dialog)
+        dialog))
+
+;;; ----------------------------------------------------------------------------
+;;; update the Tools Menu
+;;;
+(defParameter *tools-menu* 
+  (#/submenu (#/itemWithTitle: (#/mainMenu (ccl::application-ui-object ccl::*application*)) #@"Tools")))
+
+(let ((item (#/itemWithTitle: *tools-menu* #@"Source Compare...")))
+  (unless (%null-ptr-p item) (#/removeItem: *tools-menu* item))
+  (#/addItem: *tools-menu* (#/separatorItem ns:ns-menu-item))
+  (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc ns:ns-menu-item)
+                                                    #@"Source Compare..."
+                                                    (ccl::@selector "interfaceAction:")
+                                                    #@""))
+  (#/setTarget: item *source-compare-dialog*)
+  (#/addItem: *tools-menu* item)
+  (pushnew (cons item
+                 #'(lambda (sender)
+                     (declare (ignore sender))
+                     (open-source-compare-dialog)))
+           (action-alist *source-compare-dialog*)))
+
+
+
+
+
+
+
+
+
+
Index: /branches/new-random/contrib/foy/source-comparison/source-compare.lisp
===================================================================
--- /branches/new-random/contrib/foy/source-comparison/source-compare.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/source-comparison/source-compare.lisp	(revision 13309)
@@ -0,0 +1,1242 @@
+;;; Tue Dec 25 19:59:50 1990 by Mark Kantrowitz <mkant@GLINDA.OZ.CS.CMU.EDU>
+;;; source-compare.lisp
+
+;;; ****************************************************************
+;;; Source Compare: A 'diff' Program for Lisp **********************
+;;; ****************************************************************
+;;; 
+;;; Source Compare is a common-lisp portable tool for comparing 
+;;; lisp source files, similar to the unix program 'diff'. Like diff
+;;; it can ignore case, whitespace, and blank lines. In addition,
+;;; it can also ignore certain classes of lisp comments. It runs in
+;;; average-case O(m+n) time.
+;;;
+;;; Written by Mark Kantrowitz, December 1990.
+;;; Address:   School of Computer Science
+;;;            Carnegie Mellon University
+;;;            Pittsburgh, PA 15213
+;;;
+;;; Copyright (c) 1990. All rights reserved.
+;;;
+;;; See general license below.
+;;;
+
+;;; ****************************************************************
+;;; General License Agreement and Lack of Warranty *****************
+;;; ****************************************************************
+;;;
+;;; This software is distributed in the hope that it will be useful (both
+;;; in and of itself and as an example of lisp programming), but WITHOUT
+;;; ANY WARRANTY. The author(s) do not accept responsibility to anyone for
+;;; the consequences of using it or for whether it serves any particular
+;;; purpose or works at all. No warranty is made about the software or its
+;;; performance. 
+;;; 
+;;; Use and copying of this software and the preparation of derivative
+;;; works based on this software are permitted, so long as the following
+;;; conditions are met:
+;;; 	o  The copyright notice and this entire notice are included intact
+;;; 	   and prominently carried on all copies and supporting documentation.
+;;; 	o  No fees or compensation are charged for use, copies, or
+;;; 	   access to this software. You may charge a nominal
+;;; 	   distribution fee for the physical act of transferring a
+;;; 	   copy, but you may not charge for the program itself. 
+;;; 	o  If you modify this software, you must cause the modified
+;;; 	   file(s) to carry prominent notices (a Change Log)
+;;; 	   describing the changes, who made the changes, and the date
+;;; 	   of those changes.
+;;; 	o  Any work distributed or published that in whole or in part
+;;; 	   contains or is a derivative of this software or any part 
+;;; 	   thereof is subject to the terms of this agreement. The 
+;;; 	   aggregation of another unrelated program with this software
+;;; 	   or its derivative on a volume of storage or distribution
+;;; 	   medium does not bring the other program under the scope
+;;; 	   of these terms.
+;;; 	o  Permission is granted to manufacturers and distributors of
+;;; 	   lisp compilers and interpreters to include this software
+;;; 	   with their distribution. 
+;;; 
+;;; This software is made available AS IS, and is distributed without 
+;;; warranty of any kind, either expressed or implied.
+;;; 
+;;; In no event will the author(s) or their institutions be liable to you
+;;; for damages, including lost profits, lost monies, or other special,
+;;; incidental or consequential damages arising out of or in connection
+;;; with the use or inability to use (including but not limited to loss of
+;;; data or data being rendered inaccurate or losses sustained by third
+;;; parties or a failure of the program to operate as documented) the 
+;;; program, even if you have been advised of the possibility of such
+;;; damanges, or for any claim by any other party, whether in an action of
+;;; contract, negligence, or other tortious action.
+;;; 
+;;; The current version of this software and a variety of related
+;;; utilities may be obtained by anonymous ftp from a.gp.cs.cmu.edu
+;;; (128.2.242.7) or any other CS machine in the directory 
+;;;       /afs/cs.cmu.edu/user/mkant/Public/Lisp-Utilities/
+;;; You must cd to this directory in one fell swoop, as the CMU
+;;; security mechanisms prevent access to other directories from an
+;;; anonymous ftp. For users accessing the directory via an anonymous
+;;; ftp mail server, the file README contains a current listing and
+;;; description of the files in the directory. The file UPDATES describes
+;;; recent updates to the released versions of the software in the directory.
+;;; The file COPYING contains the current copy of this license agreement.
+;;; Of course, if your site runs the Andrew File System and you have
+;;; afs access, you can just cd to the directory and copy the files directly.
+;;; 
+;;; Please send bug reports, comments, questions and suggestions to
+;;; mkant@cs.cmu.edu. We would also appreciate receiving any changes
+;;; or improvements you may make. 
+;;; 
+;;; If you wish to be added to the CL-Utilities@cs.cmu.edu mailing list, 
+;;; send email to CL-Utilities-Request@cs.cmu.edu with your name, email
+;;; address, and affiliation. This mailing list is primarily for
+;;; notification about major updates, bug fixes, and additions to the lisp
+;;; utilities collection. The mailing list is intended to have low traffic.
+;;;
+
+;;; ********************************
+;;; Change Log *********************
+;;; ********************************
+;;;
+;;;  16-DEC-90  mk   File created.
+;;;  25-DEC-90  mk   First released version.
+;;;  24-JAN-91  mk   Added average-case running time analysis.
+
+;;; ********************************
+;;; To Do **************************
+;;; ********************************
+;;;
+;;; Extend so it can ignore documentation strings?
+;;;
+;;; Extend so it can ignore ALL whitespace (even within line)?
+;;;
+;;; Cache start and end positions for each line? [Modify line-start and
+;;; line-end to first check the cache before redoing the computation.]
+;;;    run the profiler on this code first, though.
+;;;
+;;; The file cache could be flushed after each loop in so-co. Possibly
+;;; worth doing to save space and/or reduce consing.
+;;;
+;;; Implement diff's O(p log n) algorithm using 2-3 trees and k-candidates.
+;;;
+;;; Given that in diff's find-merge-split algorithm the merge is on two
+;;; sets, one with elements less than the others, can we find a way to
+;;; do the find-find-split-merge in constant time? At least keep a table
+;;; of whether r-1,r are in the same k-candidate set. 
+;;;
+;;; Fancy indexing, div&conq, straight-line dist to TR corner metric.
+;;; Hierarchical LCS (i.e., abstract level first)?
+;;;
+;;; Make it aware of which definition it is in to aid matching. (Problem,
+;;; then, of function and variable renaming.)
+;;;
+
+;;; ********************************
+;;; Notes **************************
+;;; ********************************
+;;;
+;;;    SOURCE-COMPARE has been tested (successfully) in the following lisps:
+;;;       CMU Common Lisp (M2.9 15-Aug-90, Compiler M1.8 15-Aug-90)
+;;;       Macintosh Allegro Common Lisp (1.3.2)
+;;;       ExCL (Franz Allegro CL 3.1.12 [DEC 3100] 3/30/90)
+;;;       Lucid CL (Version 2.1 6-DEC-87)
+;;;
+;;;    SOURCE-COMPARE needs to be tested in the following lisps:
+;;;       Symbolics Common Lisp (8.0)
+;;;       Lucid Common Lisp (3.0, 4.0)
+;;;       KCL (June 3, 1987 or later)
+;;;       AKCL (1.86, June 30, 1987 or later)
+;;;       TI (Release 4.1 or later)
+;;;       Ibuki Common Lisp (01/01, October 15, 1987)
+;;;       Golden Common Lisp (3.1 IBM-PC)
+;;;       VAXLisp (2.0, 3.1)
+;;;       HP Common Lisp (same as Lucid?)
+;;;       Procyon Common Lisp
+
+;;; ****************************************************************
+;;; Documentation **************************************************
+;;; ****************************************************************
+;;;
+;;; Source Compare is a common-lisp portable tool for comparing 
+;;; lisp source files, similar to the unix program 'diff'. 
+;;;
+;;; It uses a greedy variation of the usual dynamic programming 
+;;; implementation of LCS (longest common substring) to do the 
+;;; comparison. It tries to maintain the two files being compared
+;;; in sync, and when a difference is encountered, uses the closest
+;;; next match, where distance is minimized against some metric.
+;;; Note that since this is a greedy algorithm, it is possible that it
+;;; will not find the optimum global match sequence. However, this case
+;;; hardly ever occurs in practice, and if it does ever occur, the
+;;; algorithm errs on the side of safety.
+;;;
+;;; Metrics should be chosen so that minimizing distance is
+;;; equivalent to minimizing the edits necessary to bring the two
+;;; files into agreement. Two such metrics include
+;;;     x + y    = *total* additions and deletions from both files
+;;;     max(x,y) = length of largest addition or deletion from either file
+;;; where x is a line number from the first file and y is a line number
+;;; from the second file. Both of these metrics are appropriate to the
+;;; problem, since the former tries to minimize the total changes and
+;;; the latter gives a preference to small changes.
+;;; 
+;;; While neither metric actually builds the dynamic programming table,
+;;; they can be considered as exploring the table in successive
+;;; rectilinear and diagonal manners, respectively.
+;;;                        #####          #
+;;;                            #           #
+;;;                            #            #
+;;;                            #             #
+;;; Both metrics have been implemented.
+;;;
+;;; Both of these metrics lead to a worst-case O(n^2) algorithm
+;;; (actually, O(nm), where n is the length of the first file and
+;;; m is the length of the second file). In practice, however, the
+;;; algorithm seems to have linear running time. This could be a function
+;;; of its use to compare source files, since comparing two completely
+;;; different files would lead to worst-case behavior. The diagonal
+;;; metric seems to be slightly faster and less of a space hog than
+;;; the rectilinear metric, so it has been made the default.
+;;; 
+;;; We show below that the average case running time is O(n+m).
+;;;
+
+;;; ********************************
+;;; Average Case Analysis **********
+;;; ********************************
+;;;
+;;; Thanks to Neil J Calkin (CMU Math Department) for the idea that led to
+;;; this proof.
+;;;
+;;; Let a(i) and b(i) be the ith distances between matches in files A and B,
+;;; respectively. Let k, an integer between 1 and n (inclusive), be the
+;;; number of matches. Then
+;;;	  Sum[i = 1 to k; a(i)] = m and Sum[i = 1 to k; b(i)] = n
+;;; where m is the length in lines of file A, and n is the corresponding
+;;; length for file B. The running time of the algorithm is proportional
+;;; to Sum[i = 1 to k; a(i)b(i)].
+;;;
+;;; Since a(i) and b(i) are positive integers, it follows that
+;;;	    Sum[i; a(i)b(i)] <= Sum[i; a(i)] Sum[i; b(i)] = m n
+;;; and hence the worst-case running time is O(mn). [Best case is, of course,
+;;; linear.]
+;;;
+;;; But the worst-case running time is atypical of the average-case behavior.
+;;; As we shall show, the average-case running time is O(m+n).
+;;;
+;;; Combining the Cauchy-Schwartz inequality
+;;;	 Sum[i;a(i)b(i)] <= Sqrt{Sum[i;a(i)^2]} sqrt{Sum[i;b(i)^2]}
+;;; with the arithmetic-mean geometric-mean inequality
+;;;			    Sqrt{xy} <= (x+y)/2
+;;; yields
+;;;	    Sum[i;a(i)b(i)] <= (Sum[i;a(i)^2] + Sum[i;b(i)^2])/2
+;;;
+;;; So it suffices to look at the average value of Sum[i = 1 to k; r(i)^2]
+;;; over all possible ordered sequences r(i) of positive integers for k = 1
+;;; to n such that Sum[i = 1 to k; r(i)] = n. Such a sequence r(k) is called a
+;;; composition of n into k distinct parts. (The word distinct here
+;;; signifies that permutations of a sequence r(k) are not considered
+;;; identical -- the cells are distinct.)
+;;;
+;;; To compute this average we sum Sum[i = 1 to k; r(i)^2] over all possible
+;;; compositions of n, and divide by the total number of such
+;;; compositions.
+;;;
+;;; Clearly r(i) is an integer between 1 and n (inclusive). For a given
+;;; integer i between 1 and n (inclusive), we count how often i occurs
+;;; in a composition of n into k distinct parts. Call this count
+;;; Comp[n,k,i]. Then the sum is equal to 
+;;;	    Sum[k = 1 to n; Sum[i = 1 to n; Comp[n,k,i] i^2]]
+;;;
+;;; Now the number of occurrences of i in the compositions of n into k
+;;; distinct parts is the same as multiplying together the number of
+;;; compositions of n-i into k-1 parts and the number of positions in
+;;; which i could be inserted to form a k-part composition of n. The 
+;;; latter quantity is clearly k. To see that the former is 
+;;; C(n-i-1,k-2), consider n-i ones separated by (n-i)-1 spaces, and
+;;; choose (k-1)-1 of them to form k-1 integers. Thus Comp[n,k,i] is
+;;; k C(n-i-1,k-2).
+;;; 
+;;; So our sum is equal to
+;;;    Sum[k = 1 to n; Sum[i = 1 to n; k(i^2)C(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n; i^2 Sum[k = 1 to n; kC(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n; i^2 Sum[k = 1 to n; 
+;;;                                 (k-2)C(n-i-1,k-2) + 2C(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n; i^2 Sum[k = 1 to n; 
+;;;                                 (n-i-1)C(n-i-2,k-3) + 2C(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n-2; i^2 (n-i-1) 2^(n-i-2)]
+;;;         + Sum[i = 1 to n; i^2 2^(n-i)]
+;;; Substituting j = n-i+1 yields
+;;;       = Sum[j = 3 to n; (n+1-j)^2 (j-2) 2^(j-3)] 
+;;;         + Sum[j = 1 to n; (n+1-j)^2 2^(j-1)]
+;;;       = Sum[j = 1 to n-2; (n-1-j)^2 j 2^(j-1)] 
+;;;         + Sum[j = 1 to n; (n+1-j)^2 2^(j-1)]
+;;;       = (Sum[j = 1 to n-2; 2^j (j^3 - (2n-2) j^2 + (n-1)^2 j)]
+;;;          + Sum[j = 1 to n; 2^j (j^2 - (2n+2)j + (n+1)^2)])/2
+;;; We substitute using the identities
+;;;    Sum[j = 1 to n; 2^j]     = 2^(n+1) - 2
+;;;    Sum[j = 1 to n; j 2^j]   = (n-1)2^(n+1) + 2
+;;;    Sum[j = 1 to n; j^2 2^j] = (2n^2 - 4n + 6)2^n - 6
+;;;    Sum[j = 1 to n; j^3 2^j] = (2n^3 - 6n^2 + 18n - 26)2^n + 26
+;;; to obtain
+;;;    1/2[2^(n-1)((n-2)^3 - 3(n-2)^2 + 9(n-2) - 13 
+;;;                - 2(n-1)((n-2)^2 - 2(n-2) + 3)
+;;;                + (n-1)^2(n-3))
+;;;        2^n(2n^2 - 4n + 6
+;;;            - (2n+2)(2n-2)
+;;;            + (n+1)^2(2))
+;;;        + (26 + 6(2n-2) + 2(n-1)^2 - 6 - 2(2n+2) - 2(n+1)^2)]
+;;; Luckily the n^3 and n^2 terms cancel, simplifying the expression to
+;;;    (3n-4) 2^(n-1) + 2
+;;; This closed form expression has been empirically verified for n = 1 to 15.
+;;;
+;;; Since there are C(n-1,k-1) compositions of n into k distinct parts, the
+;;; total number of compositions is Sum[k = 1 to n; C(n-1,k-1)] = 2^(n-1)
+;;; by the binomial theorem.
+;;;
+;;; Thus the average value of Sum[n,k; r(i)^2] is the total sum divided by
+;;; the total count, or
+;;;	     [(3n-4) 2^(n-1) + 2]/[2^(n-1)] = 3n-4 + 1/2^(n-2)
+;;; So Sum[i; a(i)b(i)] <= (Sum[i;a(i)^2] + Sum[i;b(i)^2])/2
+;;;                      = (3n-4 + 1/2^(n-2) + 3m-4 + 1/2^(m-2))/2
+;;;                      = 3/2(n+m) - 4 + 1/2^(n-1) + 1/2^(m-1)
+;;; on average, and hence the average case running time is O(m+n).
+;;;
+
+;;; ********************************
+;;; User Guide *********************
+;;; ********************************
+;;;
+;;; SOURCE-COMPARE (filename-1 filename-2 &key                    [FUNCTION]
+;;;                 (output-stream *standard-output*)
+;;;                 (ignore-case *ignore-case*)
+;;;                 (ignore-whitespace *ignore-whitespace*)
+;;;                 (ignore-comments *ignore-comments*)
+;;;                 (ignore-blank-lines *ignore-blank-lines*)
+;;;                 (print-context *print-context*)
+;;;                 (print-fancy-header *print-fancy-header*))
+;;;    Compares the contents of the two files, outputting a report of what
+;;;    lines must be changed to bring the files into agreement. The report
+;;;    is similar to that generated by 'diff': Lines of the forms
+;;;    n1 a n3,n4
+;;;    n1,n2 d n3
+;;;    n1,n2 c n3,n4
+;;;    (where a is ADD, d is DELETE, and c is CHANGE) are followed by the
+;;;    lines affected in the first (left) file flagged by '<' then all
+;;;    the lines affected in the second (right) file flagged by '>'. If
+;;;    PRINT-CONTEXT is T, will print out some additional contextual
+;;;    information, such as additional lines before and after the affected
+;;;    text and the definition most likely to be affected by the changes. If
+;;;    PRINT-FANCY-HEADER is T, prints the file-author and file-write-date
+;;;    in the header. The report is output to OUTPUT-STREAM. Returns T if
+;;;    the files were "identical", NIL otherwise.
+;;;    If IGNORE-CASE is T, uses a case insensitive comparison.
+;;;    If IGNORE-WHITESPACE is T, ignores spaces and tabs that occur at
+;;;    the beginning of the line. If IGNORE-COMMENTS is T, tries to ignore
+;;;    comments at the end of the line. If *dont-ignore-major-comments*
+;;;    is T, will also ignore major comments (comments with a semicolon at
+;;;    char 0 of the line). If IGNORE-BLANK-LINES is T, will ignore blank
+;;;    lines in both files, including lines that are effectively blank
+;;;    because of ignored comments.
+;;;
+;;; *GREEDY-METRIC* (quote find-next-diagonal-match)              [VARIABLE]
+;;;    Variable containing the name of the greedy matching function used
+;;;    to minimize distance to the next match:
+;;;    find-next-rectilinear-match  minimizes  max(x,y)
+;;;    find-next-diagonal-match     minimizes  x+y
+;;;    where x is a line number from the first file and y is a line
+;;;    number from the second file.
+;;;
+;;; FIND-NEXT-DIAGONAL-MATCH (file-1 start-1 file-2 start-2)      [FUNCTION]
+;;;    Difference detected, look ahead for a match [x+y version].
+;;;
+;;; FIND-NEXT-RECTILINEAR-MATCH (file-1 start-1 file-2 start-2)   [FUNCTION]
+;;;    Difference detected, look ahead for a match [max(x,y) version].
+;;;
+;;;
+;;; *** Display Parameters ***
+;;;
+;;; *PRINT-CONTEXT* t                                             [VARIABLE]
+;;;    If T, we print the context marking lines that occur before the
+;;;    difference.
+;;;
+;;; *PRINT-FANCY-HEADER* ()                                       [VARIABLE]
+;;;    If T, prints a fancy header instead of the simple one.
+;;;
+;;; *CONTEXT-LINES-BEFORE-DIFFERENCE* 0                                     [VARIABLE]
+;;;    Number of lines to print before a difference.
+;;;
+;;; *CONTEXT-LINES-AFTER-DIFFERENCE* 1                                      [VARIABLE]
+;;;    Number of lines to print after a difference.
+;;;
+;;;
+;;; *** Program Default Parameters ***
+;;;
+;;; *MINIMUM-MATCH-LENGTH* 2                                     [VARIABLE]
+;;;    The minimum number of lines that must match for it to be considered
+;;;    a match. This has the effect of collecting lots of adjacent small
+;;;    differences together into one larger difference.
+;;;
+;;; *IGNORE-WHITESPACE* t                                         [VARIABLE]
+;;;    If T, will ignore spaces and tabs that occur at the beginning of the
+;;;    line before other text appears and at the end of the line after
+;;;    the last text has appeared.
+;;;
+;;; *IGNORE-CASE* t                                               [VARIABLE]
+;;;    If T, uses a case insensitive comparison. Otherwise uses a case
+;;;    sensitive comparison.
+;;;
+;;; *IGNORE-COMMENTS* t                                           [VARIABLE]
+;;;    If T, will try to ignore comments of the semicolon variety when
+;;;    comparing lines. Tries to be rather intelligent about the context
+;;;    to avoid ignoring something that really isn't a comment. For
+;;;    example, semicolons appearing within strings, even multi-line
+;;;    strings, are not considered comment characters. Uses the following
+;;;    heuristics to decide if a semicolon is a comment character or not:
+;;;    o  Slashification (\) works inside strings ("foo\"bar")
+;;;       and symbol names (|foo\|bar|), but not balanced comments
+;;;       (#|foobar\|#).
+;;;    o  Balanced comments do not work inside strings ("#|") or
+;;;       symbol names.
+;;;    o  Strings do not work inside balanced comments (#|"|#)
+;;;    o  Regular semicolon comments do not work inside strings,
+;;;       symbol names, or balanced comments (#|foo;bar|#).
+;;;    All this is necessary for it to correctly identify when a
+;;;    semicolon indicates the beginning of a comment. Conceivably we should
+;;;    consider a semicolon as a comment when it is inside a balanced
+;;;    comment which isn't terminated from the semicolon to the end of the
+;;;    line. However, besides being complicated and time-consuming to
+;;;    implement, the lisp interpreter doesn't treat it this way, and we
+;;;    like to err on the side of caution. Anyway, changes in the comments
+;;;    within commented out regions of code is worth knowing about.
+;;;
+;;; *DONT-IGNORE-MAJOR-COMMENTS* ()                               [VARIABLE]
+;;;    If T, ignoring comments does not ignore comments with a semicolon
+;;;    at position 0 of the line.
+;;;
+;;; *IGNORE-BLANK-LINES* t                                        [VARIABLE]
+;;;    If T, will ignore blank lines when doing the comparison.
+;;;
+
+;;; ****************************************************************
+;;; Source Compare *************************************************
+;;; ****************************************************************
+
+(defPackage "SOURCE-COMPARE" (:nicknames "SCP") (:use :cl :ccl))
+(in-package "SOURCE-COMPARE")
+
+(export '(source-compare		; main routine
+	  ;; Core function parameters used to keep files in sync.
+	  *greedy-metric*		
+	  *minimum-match-length*
+	  ;; Program default display.
+	  *print-context*		
+	  *print-fancy-header*
+	  *context-lines-before-difference*
+	  *context-lines-after-difference*
+	  ;; Program default modes.
+	  *ignore-comments*
+	  *dont-ignore-major-comments*
+	  *ignore-case*
+	  *ignore-whitespace*
+	  *ignore-blank-lines*))
+
+;;; ********************************
+;;; Global Vars ********************
+;;; ********************************
+(defVar *print-context* t ;nil
+  "If T, we print the context marking lines that occur before the difference.")
+(defVar *print-fancy-header* nil ;t
+  "If T, prints a fancy header instead of the simple one.")
+(defVar *context-lines-before-difference* 0
+  "Number of lines to print before a difference.")
+(defVar *context-lines-after-difference* 1 
+  "Number of lines to print after a difference.")
+
+(defVar *greedy-metric* 'find-next-diagonal-match
+  "Variable containing the name of the greedy matching function used
+   to minimize distance to the next match:
+      find-next-rectilinear-match  minimizes  max(x,y)
+      find-next-diagonal-match     minimizes  x+y
+   where x is a line number from the first file and y is a line number
+   from the second file.")
+
+(defVar *minimum-match-length* 2
+  "The minimum number of lines that must match for it to be considered
+   a match. This has the effect of collecting lots of adjacent small
+   differences together into one larger difference.")
+
+(defVar *ignore-whitespace* t
+  "If T, will ignore spaces and tabs that occur at the beginning of the
+   line before other text appears and at the end of the line after
+   the last text has appeared.")
+(defVar *ignore-case* t
+  "If T, uses a case insensitive comparison. Otherwise uses a case
+   sensitive comparison.")
+(defVar *ignore-comments* t
+  "If T, will try to ignore comments of the semicolon variety when
+   comparing lines. Tries to be rather intelligent about the context
+   to avoid ignoring something that really isn't a comment. For example, 
+   semicolons appearing within strings, even multi-line strings, are not
+   considered comment characters. Uses the following heuristics to decide
+   if a semicolon is a comment character or not:
+       o  Slashification (\\) works inside strings (\"foo\\\"bar\")
+          and symbol names (\|foo\\\|bar\|), but not balanced comments
+          (#|foobar\\|#).
+       o  Balanced comments do not work inside strings (\"\#\|\") or
+          symbol names.
+       o  Strings do not work inside balanced comments (#|\"|#)
+       o  Regular semicolon comments do not work inside strings, symbol
+          names, or balanced comments (#|foo;bar|#).
+   All this is necessary for it to correctly identify when a semicolon
+   indicates the beginning of a comment. Conceivably we should consider
+   a semicolon as a comment when it is inside a balanced comment which
+   isn't terminated from the semicolon to the end of the line. However,
+   besides being complicated and time-consuming to implement, the lisp
+   interpreter doesn't treat it this way, and we like to err on the side
+   of caution. Anyway, changes in the comments within commented out
+   regions of code is worth knowing about.")
+(defVar *dont-ignore-major-comments* nil ;t
+  "If T, ignoring comments does not ignore comments with a semicolon
+   at position 0 of the line.")
+(defVar *ignore-blank-lines* t
+  "If T, will ignore blank lines when doing the comparison.")
+
+;;; ********************************
+;;; File Cache *********************
+;;; ********************************
+
+;;; File-cache is a defstruct used to cache the lines of the file as
+;;; they are read.
+(defStruct (FILE-CACHE (:print-function
+			(lambda (o s d)
+			  (declare (ignore d))
+			  (format s "#<file-cache: ~a ~d ~a>"
+				  (file-cache-file-name o)
+				  (file-cache-length o)
+				  (file-cache-eof o)))))
+  ;; LINE-TABLE is a cache of the lines of the file read so far.
+  ;; INSIDE-STRING-TABLE is a table of flags which indicate whether the line
+  ;; terminates while still inside a string. If so, this table indicates
+  ;; what character will close the string. This is useful for parsing
+  ;; multi-line strings.
+  ;; BALANCED-COMMENT-COUNT-TABLE is a table of flags which indicate whether
+  ;; the line terminates while still inside a balanced comment, and if so,
+  ;; how many are left to be closed. This is useful for parsing multi-line
+  ;; balanced comments. 
+  ;; FILE-NAME is the name of the file.
+  ;; FILE-STREAM is the input stream open to the file.
+  ;; EOF is a flag which is true when the end of the file has been reached.
+  ;; If so, it is one more than the last valid line number.
+  (line-table (make-array (list 100.) 
+			  :element-type t :fill-pointer 0 :adjustable t)) 
+  (inside-string-table (make-array (list 100.) 
+				   :element-type t
+				   :initial-element nil
+				   :fill-pointer 0 :adjustable t))
+  (balanced-comment-count-table (make-array (list 100.) 
+					    :element-type t
+					    :initial-element 0
+					    :fill-pointer 0 :adjustable t))
+  file-name
+  file-stream				
+  (eof nil))
+
+(defun file-cache-length (file)
+  "The number of lines cached is simply the length of the line table.
+   Note that since this table has a fill-pointer, it's length is the 
+   size indicated by the fill-pointer, not the array dimensions."
+  (length (file-cache-line-table file)))
+
+(defun cached-line (file line-no)
+  "Returns a cached line from the line cache, if it exists."
+  (when (< line-no (file-cache-length file))
+    (aref (file-cache-line-table file) line-no)))
+
+(defun cached-comment-position-info (file line-no)
+  "Returns the cached comment position (inside-string and 
+   balanced-comment-count) information for the line, if it exists."
+  (if (< line-no (file-cache-length file))
+      (values (aref (file-cache-inside-string-table file) line-no)
+	      (aref (file-cache-balanced-comment-count-table file) line-no))
+    (values nil 0)))
+(defun set-cached-comment-position-info (file line-no inside-string
+					      balanced-comment-count)
+  "Sets the cached comment position information (inside-string and
+   balanced-comment-count) for the line."
+  ;; We assume that get-and-cache-next-line has ensured that the
+  ;; flag tables are the right length -- otherwise we're hosed.
+  ;; Why doesn't CL have a defsetf with multiple values? That would
+  ;; make life here so much easier. [Done 12-24-90 MK. Not installing
+  ;; here to avoid clashes with other Lisps.]
+  (setf (aref (file-cache-inside-string-table file) line-no) 
+	inside-string)
+  (setf (aref (file-cache-balanced-comment-count-table file) line-no) 
+	balanced-comment-count))
+
+(defun get-and-cache-next-line (file)
+  "Gets the next line from the file, installing it in the cache."
+  (let ((line (read-line (file-cache-file-stream file) nil nil)))
+    (if line
+	;; If there's a line, add it to the cache.
+	(progn
+	  (vector-push-extend line (file-cache-line-table file))
+	  (vector-push-extend nil (file-cache-inside-string-table file))
+	  (vector-push-extend 
+	   0 (file-cache-balanced-comment-count-table file)))
+      ;; If the line was null, we've reached the end of the file.
+      ;; Set the eof flag to be the line number of the end of file.
+      (setf (file-cache-eof file) (file-cache-length file)))
+    ;; Return the line.
+    line))
+
+(defun get-line (file line-no)
+  "Get the line from the file cache. If not present, get it from the stream."
+  (or (cached-line file line-no)
+      (when (not (file-cache-eof file))
+	(get-and-cache-next-line file))))
+
+(defMacro with-open-file-cached ((var filename &rest open-args) &body forms)
+  (let ((abortp (gensym "ABORTP"))
+	(stream (gensym (symbol-name var))))
+    `(let* ((,stream (open ,filename ,@open-args))
+	    (,var (make-file-cache :file-stream ,stream :file-name ,filename))
+	    (,abortp t))
+       (when ,var
+         (unwind-protect
+             (multiple-value-prog1
+                 (progn ,@forms)
+               (setq ,abortp nil))
+           (close ,stream :abort ,abortp))))))
+
+;;; ********************************
+;;; Line Comparison ****************
+;;; ********************************
+(defun first-non-whitespace-char (line &key from-end (start 0) end)
+  "Finds the position of the first character of LINE which is neither
+   a space or a tab. Returns NIL if no character found."
+  (position '(#\space #\tab) line
+	    :test-not #'(lambda (set char)
+			  (find char set :test #'char=))
+	    :from-end from-end
+	    :start start :end end))
+
+(defun line-start (line &optional (start 0))
+  "Returns the position of where in LINE to start the comparison."
+  (if *ignore-whitespace*
+      (or (first-non-whitespace-char line) start)
+    start))
+
+(defVar *slash-char* #\\
+  "The character used to slashify other characters.")
+(defVar *comment-char* #\;
+  "The character used to begin comments.")
+(defVar *string-quotes-char* #\"
+  "The character used to begin and end strings.")
+(defVar *string-bar-char* #\|
+  "The character used to begin and end symbols.")
+(defVar *splat-char* #\#
+  "One of the characters used to begin balanced comments.")
+(defVar *bar-char* #\|
+  "One of the characters used to begin balanced comments.")
+
+(defun find-comment-position (line &optional (start 0) end 
+				   &key inside-string (splat-bar-count 0))
+  "Tries to find the position of the beginning of the comment at the
+   end of LINE, if there is one. START and END delimit the search. END
+   defaults to the end of the line. If INSIDE-STRING is non-nil, it is
+   assumed that we're inside a string before we began (if so, INSIDE-STRING
+   is set to the character which will terminate the string (\#\\\" or \#\\\|).
+   SPLAT-BAR-COUNT is the number of unbalanced begin balanced comments
+   (\#\|'s) that have been seen so far."
+  (unless end (setf end (length line)))
+  (if (< start (length line))
+    (do ((position start (1+ position))
+	 (last-char-was-slash nil)
+	 (inside-string inside-string)
+	 (splat-bar-count splat-bar-count)
+	 (splat-flag nil)(bar-flag nil))
+	((= position end)
+	 ;; If we run off the end, return nil to signify 
+	 ;; that nothing was found.
+	 (values nil inside-string splat-bar-count))
+      (let ((char (char line position)))
+	;; Slashification works inside strings but not balanced comments.
+	;; Balanced comments do not work inside strings. 
+	;; Strings do not work inside balanced comments.
+	;; Regular comments do not work inside strings or balanced comments
+	(cond (last-char-was-slash 
+	       ;; If the last character was a slash, throw this one away
+	       ;; and reset the flag.
+	       (setf last-char-was-slash nil))
+	      ((and (zerop splat-bar-count) (char= char *slash-char*))
+	       ;; This is an unslashed slash occurring outside balanced
+	       ;; comments, so set the slash flag.
+	       (setf last-char-was-slash t))
+	      ((and (not inside-string)(char= char *splat-char*))
+	       ;; We saw a SPLAT which could begin/end a balanced comment.
+	       (cond (bar-flag
+		      ;; This is the second char of an end balanced comment.
+		      (when (plusp splat-bar-count)
+			;; If we see an extra end balanced comment
+			;; (splat-bar-count is zero), ignore it.
+			(decf splat-bar-count))
+		      (setf bar-flag nil))
+		     ((not bar-flag)
+		      ;; This is the first char of a begin balanced comment.
+		      (setf splat-flag t))))
+	      ((and (not inside-string) splat-flag (char= char *bar-char*))
+	       ;; We saw a BAR which could begin a balanced comment.
+	       ;; This is the second char of a begin balanced comment.
+	       (incf splat-bar-count)
+	       (setf splat-flag nil))
+	      ((and (not inside-string) (not splat-flag)
+		    (plusp splat-bar-count) (char= char *bar-char*))
+	       ;; We saw a BAR which could end a balanced comment.
+	       ;; This is the first char of an end balanced comment.
+	       (setf bar-flag t))
+	      ((and (zerop splat-bar-count)
+		    inside-string
+		    (char= char inside-string))
+	       ;; This is an unslashed end string or end symbol occurring
+	       ;; outside balanced comments. So reset inside-string to nil.
+	       (setf inside-string nil))
+	      ((and (zerop splat-bar-count)
+		    (null inside-string)
+		    (or (char= char *string-quotes-char*)
+			(char= char *string-bar-char*)))
+	       ;; This is an unslashed start string or start symbol occurring
+	       ;; outside balanced comments. So set inside-string to the
+	       ;; character which will end the string or symbol.
+	       (setf inside-string char))
+	      ((and (zerop splat-bar-count) (not inside-string)
+		    (char= char *comment-char*))
+	       ;; We're not slashified or inside a string or balanced comment
+	       ;; and we're a comment char, so we must begin a comment.
+	       (return (values position nil 0)))
+	      ((or bar-flag splat-flag)
+	       ;; We last saw a BAR or SPLAT, but some other unimportant
+	       ;; character was seen, so reset the flags.
+	       (setf splat-flag nil
+		     bar-flag nil)))))
+    (values nil nil 0)))
+
+;;; To see GNU-Emacs (and some lesser imitations) die miserably, put the
+;;; cursor before the # on the next line, and try doing C-M-f or C-M-e. Ha!
+#|
+;;; Test find-comment-position on the various combinations of
+;;; #| |#, ;, "foo", |foo|, and \. Note that this commented out
+;;; region of this source file will itself serve as a good test
+;;; when source-compare is run on this file! 
+(find-comment-position "#| ; |# ;")
+(find-comment-position "\" ; \" ;")
+(find-comment-position "| ; | ;")
+(find-comment-position "#\| ; | ;")
+(find-comment-position "#\\| ; | ;")
+(find-comment-position "| ; #\| ;")
+(find-comment-position "| ; #\| \" ;")
+|#
+
+(defun get-comment-position (line file line-no &optional (start 0) end)
+  "Returns the position of the beginning of the semicolon variety comment
+   on this line."
+  ;; Get the cached position info for the previous line. 
+  (multiple-value-bind (inside-string balanced-comment-count)
+      (if (zerop line-no)
+	  ;; Default for first line of the file.
+	  (values nil 0)
+	(cached-comment-position-info file (1- line-no)))
+    ;; Find the comment position for this line.
+    (multiple-value-bind (end new-is new-bcc)
+	(find-comment-position line start end 
+			       :inside-string inside-string
+			       :splat-bar-count balanced-comment-count)
+      ;; Cache the position info for this line.
+      (set-cached-comment-position-info file line-no new-is new-bcc)
+      ;; Return the comment end.
+      end)))
+
+(defun line-end (line file line-no &optional (start 0) end)
+  "Returns the position of where in LINE to end the comparison.
+   If the comparison should end at the end of the line, returns NIL.
+   START, if supplied, is where to start looking for the end."
+  ;; Note that find-comment-position will return nil if it doesn't
+  ;; find a comment, which is the default value of :end keywords
+  ;; in the string comparison functions (signifying the end of the string).
+  (let ((new-end (when *ignore-comments* 
+		   (get-comment-position line file line-no start end))))
+    (cond ((and *dont-ignore-major-comments*
+		*ignore-comments*
+		;; found a comment char and it's at the beginning of the line.
+		new-end (zerop new-end))
+	   ;; If we're not ignoring major comments (one's with the semicolon
+	   ;; at char 0 of the line), return the end of the line.
+	   (or end (length line)))
+	  ((or *ignore-whitespace* *ignore-comments*)
+	   ;; Ignoring comments means that we ignore the whitespace at the
+	   ;; end of the line, no matter what we do at the beginning. Otherwise
+	   ;; ignoring comments would have no affect.
+	   (or (first-non-whitespace-char line :start start :end new-end
+					  :from-end t)
+	       new-end (length line)))
+	  (t
+	   new-end))))
+
+(defun null-string (string &optional (start 0) end)
+  "Returns T if STRING is the null string \"\" between START and END."
+  (unless end (setf end (length string)))
+  (string-equal string "" :start1 start :end1 end))
+
+(defun compare-lines (file-1 line-no-1 file-2 line-no-2)
+  "Intelligently compare two lines. If *ignore-case* is T, uses
+   case-insensitive comparison. If *ignore-whitespace* is T, ignores
+   spaces and tabs at the beginning of the line. If *ignore-comments* 
+   is T, tries to ignore comments at the end of the line."
+  (let ((string-1 (get-line file-1 line-no-1))
+	(string-2 (get-line file-2 line-no-2)))
+    (if (or (null string-1) (null string-2))
+	;; If either of the lines is nil, both must be.
+	(and (null string-1) (null string-2))
+      ;; Both lines are non-nil, compare them!
+      (let* ((start-1 (line-start string-1))
+	     (start-2 (line-start string-2))
+	     (end-1 (line-end string-1 file-1 line-no-1 start-1))
+	     (end-2 (line-end string-2 file-2 line-no-2 start-2))
+	     lines-same)
+	(setf lines-same
+	      (funcall (if *ignore-case* #'string-equal #'string=)
+		       string-1 string-2
+		       :start1 start-1 :start2 start-2
+		       :end1 end-1 :end2 end-2))
+	;; If lines-same is NIL, returns values: lines-same l1-null l2-null
+	;; Otherwise returns just lines-same.
+	(if *ignore-blank-lines*
+	    (values lines-same
+		    (null-string string-1 start-1 end-1)
+		    (null-string string-2 start-2 end-2))
+	  lines-same)))))
+
+;;; ********************************
+;;; Main Routine *******************
+;;; ********************************
+(defun source-compare (filename-1 filename-2
+                                  &key (output-stream *standard-output*) 
+                                  (ignore-case *ignore-case*)
+				  (ignore-whitespace *ignore-whitespace*)
+				  (ignore-comments *ignore-comments*)
+				  (ignore-blank-lines *ignore-blank-lines*)
+				  (print-context *print-context*)
+				  (print-fancy-header *print-fancy-header*))
+  "Compares the contents of the two files, outputting a report of what lines
+   must be changed to bring the files into agreement. The report is similar
+   to that generated by 'diff': Lines of the forms
+      n1 a n3,n4
+      n1,n2 d n3
+      n1,n2 c n3,n4
+   (where a is ADD, d is DELETE, and c is CHANGE) are followed by the
+   lines affected in the first (left) file flagged by '<' then all the
+   lines affected in the second (right) file flagged by '>'. If PRINT-CONTEXT
+   is T, will print out some additional contextual information, such as 
+   additional lines before and after the affected text and the definition
+   most likely to be affected by the changes. If PRINT-FANCY-HEADER is T,
+   prints the file-author and file-write-date in the header. The report is
+   output to OUTPUT-STREAM. Returns T if the files were \"identical\",
+   NIL otherwise.
+   If IGNORE-CASE is T, uses a case insensitive comparison. 
+   If IGNORE-WHITESPACE is T, ignores spaces and tabs that occur at the
+   beginning of the line. If IGNORE-COMMENTS is T, tries to ignore
+   comments at the end of the line. If *dont-ignore-major-comments* is T, will
+   also ignore major comments (comments with a semicolon at char 0 of the
+   line). If IGNORE-BLANK-LINES is T, will ignore blank lines in both
+   files, including lines that are effectively blank because of ignored 
+   comments."
+  (with-open-file-cached (file-1 filename-1 :direction :input)
+    (with-open-file-cached (file-2 filename-2 :direction :input)
+      ;; Print the header.
+      (draw-header filename-1 filename-2 
+		   :stream output-stream 
+		   :print-fancy-header print-fancy-header)
+      ;; Do the actual comparisons.
+      (let ((no-changes
+	     (source-compare-internal file-1 file-2 :stream output-stream 
+				      :ignore-case ignore-case
+				      :ignore-whitespace ignore-whitespace
+				      :ignore-comments ignore-comments
+				      :ignore-blank-lines ignore-blank-lines
+				      :print-context print-context)))
+	;; Print the trailer.
+	(format output-stream  "~&~:[Done.~;No differences found.~]~%"
+		no-changes)
+	no-changes))))
+
+(defun source-compare-internal (file-1 file-2
+				       &key (stream *standard-output*)
+				       ignore-case ignore-whitespace
+				       ignore-comments ignore-blank-lines
+				       print-context)
+  "A greedy implementation of LCS (longest common substring) suitably
+   modified for source comparison. It is similar to the standard
+   O(n^2) dynamic programming algorithm, but we don't actually keep
+   distances or an explicit table. We assume that what has matched so
+   far is a correct match. When we encounter a difference, we find the
+   closest next match, where \"close\" is defined in terms of some
+   metric. Two common metrics are max(x,y) and x+y, where x is a line number
+   from file-2 and y is a line number from file-1. The former leads to 
+   expanding (exploring) the table by increasing rectangles, and the
+   latter by increasing triangles:
+                     #####          #
+                         #           #
+                         #            #
+                         #             #
+   The average case running time of this algorithm is O(m+n), where m and n
+   are the lengths of the two files. This seems to hold in practice. Worst
+   case, of course, is still O(n^2), but this hardly ever occurs for source
+   comparison. The metric is implemented by *greedy-metric*,
+   which is either FIND-NEXT-RECTILINEAR-MATCH or FIND-NEXT-DIAGONAL-MATCH."
+  (let ((*ignore-whitespace* ignore-whitespace) 
+        (*ignore-case* ignore-case)
+        (*ignore-comments* ignore-comments)
+	(*ignore-blank-lines* ignore-blank-lines)
+	(*print-context* print-context)
+	(no-changes t))
+    ;; Loop down both files, until a difference is encountered. Use
+    ;; the function *greedy-metric* to find where they match up again,
+    ;; print out the differences report for this divergence, and continue
+    ;; from where they match.
+    (do ((line-no-1 0 (1+ line-no-1))
+	 (line-no-2 0 (1+ line-no-2)))
+        ((and (file-cache-eof file-1) (>= line-no-1 (file-cache-eof file-1))
+	      (file-cache-eof file-2) (>= line-no-2 (file-cache-eof file-2)))
+	 ;; When we are at the end of both files, return whether the
+	 ;; files are identical or not.
+	 ;; use (eql (file-cache-eof file-1) (1- line-no-1)) here?
+	 ;; need the 1- because of where the incrementing is happening. 
+	 ;; could always have a 1+ in file-cache-eof.... 
+	 ;; well, the >= is safer.
+	 no-changes)
+      (multiple-value-bind (lines-same line-1-blank line-2-blank)
+	  (compare-lines file-1 line-no-1 file-2 line-no-2)
+	(cond (lines-same
+	       ;; The lines are the same. Do nothing.
+	       nil)
+	      ((and *ignore-blank-lines*
+		    (or line-1-blank line-2-blank))
+	       ;; The lines are different, but one is blank.
+	       ;; Skip over the blank lines.
+	       (cond ((and line-1-blank line-2-blank)
+		      ;; Do nothing -- they'll be skipped automatically.
+		      nil)
+		     (line-1-blank
+		      (decf line-no-2))
+		     (line-2-blank
+		      (decf line-no-1))))
+	      (t
+	       ;; Otherwise, a genuine difference has been encountered.
+	       ;; A difference has been encountered.
+	       (setq no-changes nil)
+	       (multiple-value-bind (same-line-no-1 same-line-no-2)
+		   ;; Find where they match up again.
+		   (funcall *greedy-metric* file-1 line-no-1 file-2 line-no-2)
+		 ;; Print the difference report
+		 (print-differences file-1 line-no-1 same-line-no-1
+				    file-2 line-no-2 same-line-no-2 stream)
+		 ;; Continue from where they match.
+		 (setq line-no-1 same-line-no-1
+		       line-no-2 same-line-no-2))))))))
+
+;;; ********************************
+;;; The Metrics ********************
+;;; ********************************
+
+(defun find-next-diagonal-match (file-1 start-1 file-2 start-2)
+  "First difference detected, look ahead for a match [x+y version]."
+  (let ((sum 0)
+	line-1 line-2
+	eof-1 eof-2)
+    ;; Starts sum (x+y) initially at zero, checks for a match on that
+    ;; diagonal, and then tries the next diagonal by incrementing sum.
+    (loop
+     ;; Check for a diagonal match.
+     (multiple-value-setq (line-1 line-2 eof-1 eof-2)
+	 (find-diagonal-match sum file-1 start-1 eof-1 file-2 start-2 eof-2))
+     ;; Have we found a match? If so, exit.
+     (when (and line-1 line-2)
+       (return (values line-1 line-2)))
+     ;; Increment sum
+     (incf sum))))
+
+(defun find-diagonal-match (sum file-1 start-1 eof-1 file-2 start-2 eof-2)
+  "Explores the diagonal with left-corner start-1 start-2 and index (x+y)
+   equal to sum, searching for a match. Returns the match if found."
+  ;; This starts at top left and works toward bottom right. This gives
+  ;; a slight favoring to deletions from file-1.
+  ;; For line-1 from (+ start-1 sum) downto start-1
+  ;; and line-2 from start-2 upto (+ start-2 sum).
+  ;; Need to ensure that the starts and ends aren't beyond the bounds
+  ;; of the files, so check them against eof-1 and eof-2.
+  (let ((init-1 (+ sum start-1))
+	(init-2 start-2)
+	(end-1 start-1)
+	(end-2 (+ sum start-2)))
+    ;; Ensure we have the current EOF line numbers.
+    (unless (or eof-1 (get-line file-1 init-1))
+      (setf eof-1 (file-cache-eof file-1)))
+    (unless (or eof-2 (get-line file-2 end-2))
+      (setf eof-2 (file-cache-eof file-2)))
+    ;; Adjust start and end to fit EOF.
+    (when (and eof-1 (> init-1 eof-1))
+      (setf init-2 (- init-1 eof-1))
+      (setf init-1 eof-1))
+    (when (and eof-2 (> init-2 eof-2))
+      (setf end-1 (- end-2 eof-2))
+      (setf end-2 eof-2))
+    ;; Check all the entries in the diagonal...
+    (do ((line-1 init-1 (1- line-1))
+	 (line-2 init-2 (1+ line-2)))
+	((or (< line-1 end-1)
+	     (> line-2 end-2))
+	 ;; We've walked off the end of the graph.
+	 (values nil nil eof-1 eof-2))
+      ;; If we've found a match, return it. Note that if we've hit
+      ;; EOF on both files, it will be considered a match.
+      (when (found-match file-1 line-1 file-2 line-2)
+	(return (values line-1 line-2 eof-1 eof-2))))))
+
+(defun find-next-rectilinear-match (file-1 start-1 file-2 start-2)
+  "First difference detected, look ahead for a match [max(x,y) version]."
+  (let ((line-1 start-1) 
+	(line-2 start-2)
+        eof-1 eof-2)
+    (loop
+     (when (and eof-1 eof-2)
+       (return (values line-1 line-2)))
+     (when (not eof-1)
+       ;; Check next line from first file against lines from second file.
+       ;; Finds horizontal match.
+       (incf line-1)
+       (let ((match (find-linear-match file-2 start-2 line-2 file-1 line-1)))
+	 (cond ((eq match :eof)
+		(setq eof-1 :eof))
+	       (match
+		(return (values line-1 match))))))
+     (when (not eof-2)
+       ;; Check next line from second file against lines from first file.
+       ;; Finds vertical match.
+       (incf line-2)
+       (let ((match (find-linear-match file-1 start-1 line-1 file-2 line-2)))
+	 (cond ((eq match :eof)
+		(setq eof-2 :eof))
+	       (match
+		(return (values match line-2)))))))))
+
+(defun find-linear-match (file line-start line-end comp-file comp-line-no)
+  "Proceeds linearly in file from line-start to line-end until it 
+   finds a match against comp-line-no of comp-file."
+  (do ((line-no line-start (1+ line-no)))
+      ((> line-no line-end))
+    (cond ((found-match file line-no comp-file comp-line-no)
+	   ;; returns the match
+	   (return line-no))
+	  ((file-cache-eof comp-file)
+	   (return :eof)))))
+
+(defun found-match (file-1 line-1 file-2 line-2)
+  "Check if we've found a match by verifying that the next few lines
+   are identical. If *minimum-match-length* is more than 1, has the
+   effect of grouping together differences separated only by one 
+   matching line."
+  ;; Note that this declares a match as early as possible, keeping
+  ;; comments out of the match region. so-co then has to
+  ;; skip over the same blank lines as we did. Any way to optimize
+  ;; this?
+  (do ((line-1 line-1 (1+ line-1))
+       (line-2 line-2 (1+ line-2))
+       (first-match t)
+       (count 0 (1+ count)))
+      ((= count *minimum-match-length*)
+       t)
+    ;; Should we wrap a (let ((*ignore-comments* nil))) around this
+    ;; so that comments *do* count for matching up? Probably not.
+    (multiple-value-bind (lines-same line-1-blank line-2-blank)
+	(compare-lines file-1 line-1 file-2 line-2)
+      ;; Note that only if *ignore-blank-lines* is T could
+      ;; line-1-blank and line-2-blank be non-nil. 
+      (cond ((and lines-same (not (or line-1-blank line-2-blank)))
+	     ;; A real line matching a real line. Do nothing since
+	     ;; the count is automatically incremented.
+	     nil)
+	    (lines-same
+	     ;; A fake line matching by at least one blank. Skip it
+	     ;; and keep it out of the count.
+	     (decf count))
+	    ((or line-1-blank line-2-blank)
+	     ;; We have a match fail, but because of at least one
+	     ;; blank line. Skip over the blank line,
+	     (cond ((and line-1-blank line-2-blank)
+		    ;; Two blank lines. Do nothing -- they'll be
+		    ;; skipped automatically.
+		    nil)
+		   (first-match 
+		    ;; We have a mismatch of real against blank, and it's on
+		    ;; the first real pairing. Skipping the blank line would
+		    ;; lead to so-co getting out of sync, so we
+		    ;; must fail here and exit.
+		    (return nil))
+		   (line-1-blank
+		    ;; Skip over this blank line (the line number is
+		    ;; automatically incremented), but not over the other.
+		    (decf line-2))
+		   (line-2-blank
+		    (decf line-1)))
+	     ;; and keep this match fail out of the count.
+	     (decf count))
+	    (t
+	     ;; A true non-match. Exit.
+	     (return nil)))
+      (when first-match (setf first-match nil)))))
+
+
+
+#|
+;;; older version
+(defun found-match (file-1 line-1 file-2 line-2)
+  "Check if we've found a match by verifying that the next few lines
+   are identical. If *minimum-match-length* is more than 1, has the
+   effect of grouping together differences separated only by one 
+   matching line."
+  (do ((line-1 line-1 (1+ line-1))
+       (line-2 line-2 (1+ line-2))
+       (count 0 (1+ count)))
+      ((= count *minimum-match-length*)
+       t)
+    ;; Should we wrap a (let ((*ignore-comments* nil))) around this
+    ;; so that comments *do* count for matching up? Probably not.
+    (multiple-value-bind (lines-same line-1-blank line-2-blank)
+	(compare-lines file-1 line-1 file-2 line-2)
+      ;; Note that only if *ignore-blank-lines* is T could
+      ;; line-1-blank and line-2-blank be non-nil. 
+      (cond ((and lines-same (not (or line-1-blank line-2-blank)))
+	     ;; A real line matching a real line. Do nothing.
+	     nil)
+	    (lines-same
+	     ;; A fake line matching by at least one blank. Skip it
+	     ;; and keep it out of the count.
+	     (decf count))
+	    (t
+	     ;; A non-match. Exit.
+	     (return nil))))))
+|#
+
+;;; ********************************
+;;; Line Contexts ******************
+;;; ********************************
+(defun start-context (file line-no)
+  "Walks backwards from LINE-NO until it finds the beginning of a 
+   definition (a line with a left-parenthesis on char 0)."
+  (when (plusp line-no)
+    (do* ((i (1- line-no) (1- i))
+	  (line (get-line file i) (get-line file i)))
+	((zerop i))
+      (when (and (plusp (length line))
+		 (char-equal #\( (char line 0)))
+	(return (values line i))))))
+
+;;; ********************************
+;;; Report Generator ***************
+;;; ********************************
+(defun draw-header (filename-1 filename-2 
+			       &key (stream *standard-output*)
+			       print-fancy-header)
+  "Draw the header for the source compare report."
+  (draw-bar stream)
+  (cond (print-fancy-header
+	 ;; Print the file write dates of the files.
+	 (format stream "~&Source compare of")
+	 (format stream "~&     ~A~&     (written by ~A, ~A)"
+		 filename-1
+		 (file-author filename-1) 
+		 (time-string (file-write-date filename-1)))
+	 (format stream "~&  with")
+	 (format stream "~&     ~A~&     (written by ~A, ~A)"
+		 filename-2 
+		 (file-author filename-2)
+		 (time-string (file-write-date filename-2))))
+	(t
+	 (format stream "~&Source compare of ~A with ~A"
+		 filename-1 filename-2)))
+  (draw-bar stream)	 
+  (finish-output stream))
+
+;;; changed universal-time to u-time - gef 
+(defun time-string (u-time)
+  (when u-time
+    (multiple-value-bind (secs min hour date month year dow)
+	(decode-universal-time u-time)
+      (format nil "~@:(~A ~A-~A-~A ~2,'0d:~2,'0d:~2,'0d~)"
+	      (svref '#("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun") dow)
+	      date 
+	      (svref '#(0 "Jan" "Feb" "Mar" "Apr" "May"
+			  "Jun" "Jul" "Aug" "Sep" "Oct"
+			  "Nov" "Dec")
+		     month)
+	      (mod year 100)
+	      hour min secs))))
+
+(defun draw-bar (&optional (stream *standard-output*))
+  "Draws a dash across the line."
+  (format stream "~&~V,,,'=A~%" 75 "="))
+
+(defun print-range (start end &optional (stream *standard-output*))
+  "Prints a representation of the range from START to END."
+  (cond ((= start end)
+	 (format stream "~D" start))
+	((= start (1- end))
+	 (format stream "~D" (1+ start)))
+	(t
+	 (format stream "~D,~D" (1+ start) end))))
+
+(defun print-differences (file-1 start-1 end-1 file-2 start-2 end-2
+				 &optional (stream *standard-output*))
+  "Print the differences in the two files in a format similar to diff." 
+  (print-range start-1 end-1 stream)
+  (cond ((= end-1 start-1)
+	 ;; We added the text in file2
+	 (format stream "a"))
+	((= end-2 start-2)
+	 ;; We deleted the text from file1
+	 (format stream "d"))
+	(t
+	 ;; We replaced the text from file1 with the text from file2
+	 (format stream "c")))
+  (print-range start-2 end-2 stream)
+  (print-file-segment file-1 start-1 end-1 stream "< ")
+  (format stream "~&---")
+  (print-file-segment file-2 start-2 end-2 stream "> ")
+  (draw-bar stream)
+  ;; Make sure that the output is displayed piecemeal.
+  (finish-output stream))
+
+(defun print-file-segment (file start end 
+				&optional (stream *standard-output*)
+				(left-margin ""))
+  "Prints the region of FILE from START to END."
+  (when *print-context*
+    ;; If we want to provide a little context for the changes,
+    ;; first change the start and end to add in the specified number
+    ;; of extra lines to print.
+    (setf start (max 0 (- start *context-lines-before-difference*))
+	  end (+ end *context-lines-after-difference*))
+    ;; Then print the name of the file and the beginning of the
+    ;; current definition.
+    (let ((context (start-context file start)))
+      (format stream "~&**** File ~A~@[, After \"~A\"~]"
+	      (file-cache-file-name file) context)))
+  ;; Then print the lines from start to end, with a left margin as specified.
+  (do ((line-no start (1+ line-no))
+       (line))
+      ((= line-no end))
+    (unless (setq line (get-line file line-no))
+      (return nil))
+    (format stream "~%~A~A" left-margin line)))
+
+;;; *EOF*
Index: /branches/new-random/contrib/foy/source-comparison/source-comparison.lisp
===================================================================
--- /branches/new-random/contrib/foy/source-comparison/source-comparison.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/source-comparison/source-comparison.lisp	(revision 13309)
@@ -0,0 +1,20 @@
+
+;;; source-comparison.lisp 
+
+(unless (member "SOURCE-COMPARISON" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *source-compare-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *source-compare-files* 
+    (list (merge-pathnames ";source-compare.lisp" *source-compare-directory*)
+          (merge-pathnames ";source-compare-dialog.lisp" *source-compare-directory*))))
+ 
+(dolist (file *source-compare-files*)
+  (load file))
+
+(provide :source-comparison)
+
+)
Index: /branches/new-random/contrib/foy/syntax-styling/syntax-styling-1.lisp
===================================================================
--- /branches/new-random/contrib/foy/syntax-styling/syntax-styling-1.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/syntax-styling/syntax-styling-1.lisp	(revision 13309)
@@ -0,0 +1,1024 @@
+;;;-*- mode: lisp; package: (syntax-styling (cl ccl hemlock-internals)) -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-1.lisp
+;;;      
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod history, most recent first:
+;;;      10/18/9   first cut.
+;;;
+;;; ****************************************************************************
+
+
+(in-package "SAX")
+
+;;; *** redefinition ***
+(let ((text-view nil)
+      (text-view-vscroll -100000))
+  (defMethod gui::compute-temporary-attributes ((self gui::hemlock-textstorage-text-view))
+    #+sax-debug (when *compute-temporary-attributes-debug* 
+                   (debug-out "~%~%~S" 'compute-temporary-attributes)
+                   (debug-out "~%*style-screen-p*: ~S" *style-screen-p*)
+                   (debug-out "~%*style-top-level-form-p*: ~S" *style-top-level-form-p*)
+                   (debug-out "~%*paste-p*: ~S" *paste-p*)
+                   (debug-out "~%*paste-start*: ~S" *paste-start*)
+                   (debug-out "~%*paste-end*: ~S" *paste-end*))
+    (let ((current-vscroll (gui::text-view-vscroll self)))
+      (when (or (not (equal self text-view))
+                (not (= current-vscroll text-view-vscroll)))
+        (when (and *styling-p* *style-screen-p* (not *paste-p*))
+         (style-screen self)))
+        (setq text-view self)
+        (setq text-view-vscroll current-vscroll))
+    (cond (*style-top-level-form-p* 
+           (style-top-level-form self))
+          (*paste-p* 
+           (setq *paste-end* (sexpr-end *paste-start*))
+           (yank-after (gui::hemlock-view self) *paste-start* *paste-end*)))
+    (let* ((container (#/textContainer self))
+           (layout (#/layoutManager container)))
+      (when (eql #$YES (gui::text-view-paren-highlight-enabled self))
+        (let* ((background #&NSBackgroundColorAttributeName)
+               (paren-highlight-left (gui::text-view-paren-highlight-left-pos self))
+               (paren-highlight-right (gui::text-view-paren-highlight-right-pos self))
+               (paren-highlight-color (gui::text-view-paren-highlight-color self))
+               (attrs (#/dictionaryWithObject:forKey: ns:ns-dictionary
+                                                      paren-highlight-color
+                                                      background)))
+          (#/addTemporaryAttributes:forCharacterRange:
+           layout attrs (ns:make-ns-range paren-highlight-left 1))
+          (#/addTemporaryAttributes:forCharacterRange:
+           layout attrs (ns:make-ns-range paren-highlight-right 1))))))
+
+  (defun reset-text-view () (setq text-view nil)))
+
+;;; *** Buffer-writable is broken
+;;; *** Instead of doing all this stuff need the equivalent of:
+;;; *** (setf ccl::*default-editor-class* 'derived-hemlock-frame-class)
+#-list-definitions
+(let ((writable-p t)
+      (lisp-file-p t)
+      (hemlock-frame nil))
+  (objc:defMethod (#/becomeKeyWindow :void) ((w gui::hemlock-frame))
+    (unless (equal w hemlock-frame)
+      (let ((path (window-path w))
+            (file-manager (#/defaultManager ns:ns-file-manager)))
+        (setq writable-p 
+              (if path
+                (#/isWritableFileAtPath: file-manager (ccl::%make-nsstring path))
+                t)) ; new files may not have a path yet.
+        (setq lisp-file-p
+              (if path
+                (string-equal (pathname-type path) "lisp")
+                t))) ; we assume a new file is a lisp file.
+      (setq hemlock-frame w))
+    (let ((become-key-function (find-symbol "BECOME-KEY-WINDOW" (find-package :ldefs))))
+      (when become-key-function (funcall become-key-function w)))
+    (call-next-method))
+  (defun lisp-file-p () lisp-file-p)
+  (defun writable-p () writable-p))
+
+#+list-definitions
+(let ((writable-p t)
+      (lisp-file-p t)
+      (hemlock-frame nil))
+  (defMethod become-key-window ((w gui::hemlock-frame))
+    (unless (equal w hemlock-frame)
+      (let ((path (window-path w))
+            (file-manager (#/defaultManager ns:ns-file-manager)))
+        (setq writable-p 
+              (if path
+                (#/isWritableFileAtPath: file-manager (ccl::%make-nsstring path))
+                t)) ; new files may not have a path yet.
+        (setq lisp-file-p
+              (if path
+                (string-equal (pathname-type path) "lisp")
+                t))) ; we assume a new file is a lisp file.
+      (setq hemlock-frame w)))
+  (defun lisp-file-p () lisp-file-p)
+  (defun writable-p () writable-p))
+
+(defun style-screen (text-view &optional generic-start generic-end)
+  (when *styling-p*
+    #+sax-debug (when *style-screen-debug* 
+                  (debug-out "~%~%~S" 'style-screen)
+                  (debug-out "~%*paste-start*: ~S" *paste-start*)
+                  (debug-out "~%*paste-end*: ~S" *paste-end*))
+    (let* ((container (#/textContainer text-view))
+           (scrollview (#/enclosingScrollView text-view))
+           (contentview (if (%null-ptr-p scrollview) text-view (#/contentView scrollview)))
+           (rect (#/bounds contentview))
+           (layout (#/layoutManager container))
+           (glyph-range (#/glyphRangeForBoundingRect:inTextContainer:
+                         layout rect container))
+           (char-range (#/characterRangeForGlyphRange:actualGlyphRange:
+                        layout glyph-range +null-ptr+))
+           (window (#/window scrollview))
+           (hemlock-view (gui::hemlock-view text-view))
+           (current-buffer (hi::hemlock-view-buffer hemlock-view))
+           (*buf* current-buffer)
+           (hi::*current-buffer* *buf*)
+           (*inc-pos* (clone (buffer-point *buf*)))
+           (*layout* (#/layoutManager container))
+           top-pos bot-pos start-mark end-mark)
+      (unless (typep (#/window scrollview) 'gui::hemlock-listener-frame)
+        (setq top-pos (ns:ns-range-location char-range))
+        (setq bot-pos (+ top-pos (ns:ns-range-length char-range)))
+        (setq start-mark (hemlock::top-level-offset (mark-offset (buf-start-mark current-buffer) top-pos) -1))
+        (setq end-mark (hemlock::top-level-offset (mark-offset (buf-start-mark current-buffer)  bot-pos) 1))
+        (when (null start-mark) (setq start-mark (buf-start-mark)))
+        (when (null end-mark) (setq end-mark (buf-end-mark)))
+        (when (and start-mark end-mark)
+          (hemlock::parse-over-block (hemlock-internals::mark-line start-mark) 
+                                     (hemlock-internals::mark-line end-mark))
+          (if (and generic-start generic-end)
+            (set-generic-text-style text-view generic-start generic-end)
+            (set-generic-text-style text-view start-mark end-mark))
+          (style-comments start-mark end-mark)
+          (style-forms window :start start-mark :end end-mark :caps-p nil :toplevel-p t))))))
+
+(defParameter *defstyle-hash-table* (make-hash-table :test 'equal))
+
+(defun get-function (name)
+  (gethash (string-upcase name) *defstyle-hash-table*))
+
+(defun add-style (name-string func)
+  (setf (gethash (string-upcase name-string) *defstyle-hash-table*) func))
+
+(defun style-elements (symbol-start form-end &optional loop-p)
+  "Step through the code sexpr by sexpr, styling appropriately."
+  #+sax-debug (when *style-elements-debug* 
+               (debug-out "~%~%~S" 'style-elements)
+               (debug-out "~%element symbol-start: ~S" symbol-start)
+               (debug-out "~%element form-end: ~S" form-end))
+  (flet ((not-char-constant-p (element-start)
+           (or (< (mark-charpos element-start) 2)
+               (char/= (mark-char element-start -1) #\\)
+               (char/= (mark-char element-start -2) #\#)))
+         (check-dynamic-p (element-start element-end)
+           (or (not *inc-p*)
+               (and *inc-p*
+                    (mark>= *inc-pos* element-start)
+                    (mark<= *inc-pos* element-end))))
+         (loop-keywd-p (string)
+           ;; hash table?
+           (member string
+                   '("above" "across" "always" "and" "append" "appending" "by" "collect" "collecting" "count" 
+                     "counting" "do" "doing" "downfrom" "downto" "each" "else" "end" "external-symbol" 
+                     "external-symbols" "finally" "for" "from" "hash-key" "hash-keys" "hash-value"
+                     "hash-values" "if" "in" "into" "initially" "loop-finish" "maximize maximizing" 
+                     "minimize" "minimizing" "named" "nconc" "nconcing" "never" "of" "on" "present-symbol" 
+                     "present-symbols" "repeat" "return" "sum" "summing" "symbol" "symbols" "the" "then" 
+                     "thereis" "to" "unless" "until" "upfrom" "upto" "using" "when" "while" "with")
+                   :test #'string-equal)))
+    (do* ((element-start symbol-start
+                         (when element-end (next-sexpr-start element-end)))
+          (element-end (when element-start (sexpr-end element-start))
+                       (when element-start (sexpr-end element-start)))
+          (current-char (when element-start (mark-char element-start))
+                        (when element-start (mark-char element-start))))
+         ((or (null element-start) (null element-end) (mark>= element-start form-end)))
+      #+sax-debug (when *style-elements-debug* 
+                   (debug-out "~%element-start: ~S" element-start)
+                   (debug-out "~%element-end: ~S" element-end))
+      (when (or (not *segment-array*)
+                (not-embedded-in-segment-p *segment-array* element-start))
+        (when (or (char= current-char #\')
+                  (char= current-char #\`)
+                  (char= current-char #\,))
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (when (char= current-char #\@)
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (when (char= current-char #\')
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (when (char= current-char #\,)
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (cond ((and (char= current-char #\()
+                    (not-char-constant-p element-start)
+                    (check-dynamic-p element-start element-end))
+               (rd-style-forms :start element-start :end element-end))
+              ((and (char= current-char #\#)
+                    (mark< element-start (mark-offset (buf-end-mark) -2))
+                    (char= (mark-char element-start 1) #\')
+                    (char= (mark-char element-start 2) #\()
+                    (check-dynamic-p element-start element-end))
+               (rd-style-forms :start (mark-offset element-start 2) :end element-end))
+              ((and (char= current-char #\:)
+                    (not-char-constant-p element-start))
+               (style-region *keyword-package-style*
+                             element-start (sexpr-end element-start)))
+              ((and loop-p
+                    (alpha-char-p current-char)
+                    (loop-keywd-p (region-to-string (region element-start element-end))))
+               (style-region *loop-keyword-style* 
+                             element-start element-end)))))))
+
+(defun backward-top-level-list (start)
+  "Get the previous #\( in charpos 0, that is not embedded in a comment."
+  #+sax-debug (when *backward-top-level-list-debug*
+               (debug-out "~%~%~S" 'backward-top-level-list)
+               (debug-out "~%start: ~S" start))
+  (when (null start) (return-from backward-top-level-list nil))
+  (do* ((next (pattern-search start *l-paren-backward-pattern*)
+              (pattern-search (mark-prev next) *l-paren-backward-pattern*))
+        not-embedded)
+       ((null next) (return nil))
+    #+sax-debug (when *backward-top-level-list-debug* 
+                  (debug-out "~%next: ~S" next))
+    (if *segment-array*
+      (setf not-embedded (not-embedded-in-segment-p *segment-array* next))
+      (setf not-embedded t))
+    #+sax-debug (when *backward-top-level-list-debug* 
+                  (debug-out "~%*segment-array*: ~S" *segment-array*)
+                  (debug-out "~%not-embedded: ~S" not-embedded))
+    (when (and (= (mark-charpos next) 0) not-embedded)
+      (return next))))
+
+(defun forward-top-level-list (start &optional (end (buf-end-mark)))
+  "Get the next #\( in charpos 0, that is not embedded in a comment."
+  #+sax-debug (when *forward-top-level-list-debug*
+               (debug-out "~%~%~S" 'forward-top-level-list)
+               (debug-out "~%start: ~S" start)
+               (debug-out "~%end: ~S" end))
+  (when (or (null start) (null end)) (return-from forward-top-level-list nil))
+  (do* ((next (pattern-search start *l-paren-forward-pattern* end)
+              (pattern-search (mark-next next) *l-paren-forward-pattern* end))
+        not-embedded)
+       ((null next) (return nil))
+    #+sax-debug (when *forward-top-level-list-debug* 
+                  (debug-out "~%next: ~S" next))
+    (if *segment-array*
+      (setf not-embedded (not-embedded-in-segment-p *segment-array* next))
+      (setf not-embedded t))
+    #+sax-debug (when *forward-top-level-list-debug* 
+                  (debug-out "~%*segment-array*: ~S" *segment-array*)
+                  (debug-out "~%not-embedded: ~S" not-embedded))
+    (when (and (= (mark-charpos next) 0) not-embedded)
+      (return next))))
+
+;;; This will skip incomplete forms and continue with the next toplevel list.
+(defun list-top-level-forms (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  "Returns a list of starting marks for all the top-level lists in the range START, END."
+   #+sax-debug (when *list-top-level-forms-debug* 
+               (debug-out "~%~%~S" 'list-top-level-forms)
+               (debug-out "~%start: ~S" start)
+               (debug-out "~%end: ~S" end)) 
+  (do* ((positions nil)
+        (sexpr-start (forward-top-level-list start  end)
+                     (when sexpr-end (forward-top-level-list sexpr-end end)))
+        (sexpr-end (when sexpr-start (limited-sexpr-end sexpr-start end))
+                   (when sexpr-start (limited-sexpr-end sexpr-start end))))
+       ((or (null sexpr-start)
+            (mark> sexpr-start end))
+        (return (nreverse positions)))
+    (cond (sexpr-end ; ie a complete list
+           (push sexpr-start positions))
+          (t ; an incomplete list - skip it
+           (setq sexpr-end (mark-next sexpr-start))))))
+  
+(defun forward-list (start &optional (end (buf-end-mark)))
+  "Get the next #\( that is not embedded in a comment and not a character constant."
+  #+sax-debug (when *forward-list-debug*
+               (debug-out "~%~%~S" 'forward-list)
+               (debug-out "~%forward-list start: ~S" start)
+               (debug-out "~%forward-list end: ~S" end))
+  (when (or (null start) (null end)) (return-from forward-list nil))
+  (do* ((next (pattern-search start *l-paren-forward-pattern* end)
+              (pattern-search (mark-next next) *l-paren-forward-pattern* end))
+        not-embedded)
+       ((null next) (return nil))
+    #+sax-debug (when *forward-list-debug* 
+                 (debug-out "~%next: ~S" next))
+    (if *segment-array*
+      (setf not-embedded (not-embedded-in-segment-p *segment-array* next))
+      (setf not-embedded t))
+    #+sax-debug (when *forward-list-debug* 
+                  (debug-out "~%*segment-array*: ~S" *segment-array*)
+                  (debug-out "~%not-embedded: ~S" not-embedded))
+    (cond ((>= (mark-charpos next) 2)
+           #+sax-debug (when *forward-list-debug* 
+                        (debug-out "~%(>= (mark-charpos next) 2)"))
+           (when (and not-embedded
+                      (not (and (eq (mark-char next -1) #\\)
+                                (eq (mark-char next -2) #\#)))
+                      (neq (mark-char next -1) #\#))
+             #+sax-debug (when *forward-list-debug* 
+                          (debug-out "~%returning: ~S" next))
+             (return next)))
+          (t 
+           #+sax-debug (when *forward-list-debug* 
+                        (debug-out "~%(< (mark-charpos next) 2)"))
+           (when not-embedded 
+             #+sax-debug (when *forward-list-debug* 
+                          (debug-out "~%returning: ~S" next))
+             (return next))))))
+
+(defun list-forms (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  "Returns a list of starting marks for all the lists in the range START, END."
+  #+sax-debug (when *list-forms-debug* 
+               (debug-out "~%~%~S" 'list-forms)
+               (debug-out "~%start: ~S" start)
+               (debug-out "~%end: ~S" end))
+  (do* ((positions nil)
+        (sexpr-start (forward-list start end)
+                    (forward-list sexpr-end end))
+        (sexpr-end (when sexpr-start (limited-sexpr-end sexpr-start end))
+                   (when sexpr-start (limited-sexpr-end sexpr-start end)))
+        (current-char (when sexpr-start (mark-char sexpr-start))
+                      (when sexpr-start (mark-char sexpr-start))))
+       ((or (null sexpr-end)
+            (null sexpr-start)
+            (mark> sexpr-start end))
+        (return (nreverse positions)))
+    #+sax-debug (when *list-forms-debug* 
+                 (debug-out "~%sexpr-start: ~S" sexpr-start)
+                 (debug-out "~%sexpr-end: ~S" sexpr-end)
+                 (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                 (debug-out "~%current-char: ~S" current-char))
+    (when (or (char= current-char #\')
+              (char= current-char #\`)
+              (char= current-char #\,))
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    (when (char= current-char #\@)
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    (when (char= current-char #\')
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    (when (char= current-char #\,)
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    ;; when styling incrementally, only include forms 
+    ;; if *inc-pos* is inside the form.
+    (cond ((char= current-char #\()
+           (when (or (not *inc-p*)
+                     (and *inc-p*
+                          (mark>= *inc-pos* sexpr-start)
+                          (mark<= *inc-pos* sexpr-end)))
+             #+sax-debug (when *list-forms-debug* 
+                           (debug-out "~%pushing: ~S" (region-to-string (region sexpr-start sexpr-end))))
+             (push sexpr-start positions)))
+          ((char= current-char #\#)
+           (cond ((and (mark< sexpr-start (buf-end-mark))
+                       (char= (mark-char sexpr-start 1) #\')
+                       (char= (mark-char sexpr-start 2) #\())
+                  (when (or (not *inc-p*)
+                            (and *inc-p*
+                                 (mark>= *inc-pos* sexpr-start)
+                                 (mark<= *inc-pos* sexpr-end)))
+                    (push (nmark-next (nmark-next sexpr-start)) positions))))))))
+
+(defun defstyle-form-styled-p (position)
+  "If there is a defstyle form at POSITION, style it and return T.  If not, return NIL."
+  (when position
+    #+sax-debug (when *defstyle-form-styled-p-debug* 
+                 (debug-out "~%~%~S" 'defstyle-form-styled-p)
+                 (debug-out "~%defstyle position: ~S" position))
+    (let* ((symbol-start (mark-next position)) ; skip paren
+           (symbol-end (sexpr-end symbol-start))
+           (string (region-to-string (region symbol-start symbol-end)))
+           (styling-function (get-function string)))
+      (when styling-function 
+        (funcall styling-function position) 
+        t))))
+
+(defun package-form-styled-p (position)
+  "If there is a :cl function at POSITION, style it and return T.  If not, return NIL."
+  (when position
+    #+sax-debug (when *package-form-styled-p-debug* 
+                 (debug-out "~%~%~S" 'package-form-styled-p)
+                 (debug-out "~%package position: ~S" position))
+    (let* ((symbol-start (mark-next position))
+           (symbol-end (sexpr-end symbol-start)))
+      (cond ((char= (mark-char position) #\:)
+             (style-region *keyword-package-style* symbol-start symbol-end) t)
+            ((find-symbol (string-upcase (region-to-string (region symbol-start symbol-end))) :cl)
+             (style-region *cl-package-style* symbol-start symbol-end)
+             #+sax-debug (when *package-form-styled-p-debug* (debug-out "~%package styled"))
+             t)))))
+
+(defun rd-style-forms (&key (start (buf-start-mark)) (end (buf-end-mark)) top-level-p)
+  "Style the buffer using a recursive descent algorithm, given the range START, END."
+  #+sax-debug (when *rd-style-forms-debug* 
+                 (debug-out "~%~%~S" 'rd-style-forms)
+                 (debug-out "~%rd-style-forms start: ~S" start)
+                 (debug-out "~%rd-style-forms end: ~S" end))
+  (let ((positions (if top-level-p (list-top-level-forms start end) (list-forms start end)))
+        form-end)
+    #+sax-debug (when *rd-style-forms-debug* 
+                 (debug-out "~%rd-style-forms positions: ~S" positions))
+    (cond (positions 
+           (dolist (position positions)
+             #+sax-debug (when *rd-style-forms-debug* 
+                           (debug-out "~%all positions: ~S" positions)
+                           (debug-out "~%rd position list position: ~S" position))
+             (unless (defstyle-form-styled-p position)
+               (when (setf form-end (limited-sexpr-end position end))
+                 (cond ((package-form-styled-p position)
+                        #+sax-debug (when *rd-style-forms-debug* 
+                                      (debug-out "~%rd position after package style: ~S" position))
+                        (let* ((next (nmark-next position))
+                               (end (sexpr-end next))
+                               (next-start (next-sexpr-start end)))
+                          #+sax-debug (when *rd-style-forms-debug* 
+                                       (debug-out "~%next: ~S" next)
+                                       (debug-out "~%end: ~S" end)
+                                       (debug-out "~%next-start: ~S" next-start))
+                          (setf position next-start))
+                        #+sax-debug (when *rd-style-forms-debug* 
+                                     (debug-out "~%rd position after next-sexpr: ~S" position)))
+                       (t
+                        (nmark-next position)))
+                 (when position (style-elements position form-end))))))
+          (t
+           #+sax-debug (when *rd-style-forms-debug* 
+                        (debug-out "~%No positions in rd positions list -- doing style-elements."))
+           (style-elements (nmark-next start) end)))))
+
+(defMethod style-top-level-form ((text-view gui::hemlock-textstorage-text-view))
+  #+sax-debug (when *style-top-level-form-debug* 
+                (debug-out  (format nil "~%~%~S" 'style-top-level-form)))
+  (setq *style-top-level-form-p* nil)
+  (let* ((hemlock-view (gui::hemlock-view text-view))
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (hi::*current-buffer* *buf*)
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*current-package* (hemlock::buffer-package *buf*))
+         (*style-case-p* (if (null *style-case-p*) nil (writable-p))))
+    (cond ((not (buffer-empty-p))
+           (let* ((start (backward-top-level-list (clone (buffer-point *buf*))))
+                  (end (when start (clone start))))
+             (when (and end (hemlock::form-offset end 1))
+               #+sax-debug (when *style-top-level-form-debug* 
+                             (debug-out  (format nil "~%start: ~S" start))
+                             (debug-out  (format nil "~%end: ~S" end)))
+               (hemlock::parse-over-block (mark-line start) (mark-line end))
+               (set-generic-text-style text-view start end)
+               (rd-style-forms :start start :end end :top-level-p t))))
+          (t
+           (ed-beep)))))
+
+(defMethod style-forms ((hemlock-view hi::hemlock-view) &key (caps-p t) start end toplevel-p)
+  (let* ((text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (hi::*current-buffer* *buf*)
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*current-package* (hemlock::buffer-package *buf*))
+         (*style-case-p* (if (null caps-p) nil *style-case-p*)))
+    (cond ((not (buffer-empty-p))
+           (unless (and start end)
+             (multiple-value-setq (start end)
+               (selection-marks text-view)))
+           (unless (and start end)
+             (setf start (buf-start-mark) end (buf-end-mark)))
+           (hemlock::parse-over-block (mark-line start) (mark-line end))
+           (rd-style-forms :start start :end end :top-level-p toplevel-p))
+          (t
+           (ed-beep)))))
+
+(defMethod style-forms ((window gui::hemlock-frame) &key (caps-p t) start end toplevel-p)
+  (style-forms (gui::hemlock-view window) :start start :end end :caps-p caps-p :toplevel-p toplevel-p))
+
+
+;;; ----------------------------------------------------------------------------
+;;; The batch styling interface:
+;;; ----------------------------------------------------------------------------
+;;;
+(defMethod style-window ((window gui::hemlock-frame))
+  (if (writable-p)
+    (let* ((hemlock-view (gui::hemlock-view window))
+           (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+           (*buf* (hemlock-view-buffer hemlock-view))
+           (hi::*current-buffer* *buf*)
+           (*layout* (#/layoutManager (#/textContainer text-view)))
+           (*current-package* (hemlock::buffer-package *buf*))
+           ;; If a file is not writable, style with color and underlining, but not caps.
+           (*style-case-p* (if (null *style-case-p*) nil (writable-p))))
+      (multiple-value-bind (start end) (selection-marks text-view)
+        (unless (and start end)
+          (setf start (buf-start-mark) end (buf-end-mark)))   
+        (hemlock::parse-over-block (mark-line start) (mark-line end))
+        (set-generic-text-style text-view start end)
+        (style-comments start end)     
+        (style-forms window :start start :end end)))
+    (listener-msg "~%~S is not writable." (window-path window))))
+
+(defun style-folder-recursively ()
+  (let ((dir (gui::cocoa-choose-directory-dialog)))
+    (when dir
+      (cond ((pathnamep dir)
+             (listener-msg "~%~%~a files styled."
+                           (style-folder (directory-namestring dir))))
+            (t
+             (listener-msg "~%~%~a files styled."
+                           (style-folder dir)))))))
+
+(defun style-folder (folder)
+  (let ((files (directory (merge-pathnames folder "*.lisp") :files t :directories nil))
+        (folders (directory (merge-pathnames folder "*") :files nil :directories t))
+        (file-count 0))
+    (dolist (file files)
+      (listener-msg "~%;;; Styling: ~a" file)
+      (incf file-count)
+      (let* ((view (gui::cocoa-edit file))
+             (window (#/window (hi::hemlock-view-pane view)))
+             (buffer (hemlock-view-buffer view))
+             (document (hi::buffer-document buffer)))
+      (cond ((writable-p)
+             (style-window window)
+             (gui::save-hemlock-document document)
+             (#/close window))
+            (t
+             (listener-msg "~%;;; File is read-only: ~S" file)))))
+    (dolist (folder folders)
+      (incf file-count (style-folder folder)))
+    file-count))
+
+(defun vanilla-style (buffer start end)
+  ;; Set the font spec of the text to the default; but leave the capitalization
+  ;; of strings, comments and various constants alone.
+  (let ((buf-start (buf-start-mark buffer))
+        (buf-end (buf-end-mark buffer))
+        skip-list case)
+    (hemlock::parse-over-block (mark-line start) (mark-line end))
+    (set-style-attributes (attribute-dictionary *vanilla-styling*) start end)
+    ;; *** this should use start and end
+    (setf skip-list (get-combined-segment-list))
+    (setf case (style-case *vanilla-styling*))
+    ;; (pprint skip-list)
+    (cond (skip-list
+           (do* ((segment (pop skip-list) (pop skip-list))
+                 (seg-start buf-start next-start)
+                 (seg-end (first segment) (first segment))
+                 (next-start (second segment) (second segment)))
+                ((or (mark>= seg-start end)
+                     (null seg-start)
+                     (null seg-end)))
+             (when (and (mark>= seg-start start)
+                        (mark<= seg-start end))
+               (cond ((eql case :up)
+                      (upcase-region seg-start (mark-min seg-end end)))
+                     ((eql case :down)
+                      (downcase-region seg-start (mark-min seg-end end)))))))
+          (t 
+           (cond ((eql case :up)
+                  (upcase-region buf-start buf-end))
+                 ((eql case :down)
+                  (downcase-region buf-start buf-end)))))))
+
+(defMethod style-vanilla ((window gui::hemlock-frame))
+  (let* ((hemlock-view (gui::hemlock-view window))
+         (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (hi::*current-buffer* *buf*))
+    (cond ((writable-p)
+           (multiple-value-bind (start end) (selection-marks text-view)
+             (unless (and start end)
+               (setf start (buf-start-mark) end (buf-end-mark)))
+             (vanilla-style *buf* start end)))
+          (t
+           (listener-msg "~%;;; File is read-only: ~S" (window-path window))))))
+
+;;; ----------------------------------------------------------------------------
+;;; The interface for the incremental algorithm:
+;;; ----------------------------------------------------------------------------
+;;;
+(defConstant %inserted-parens% 37)
+
+(defun dynamically-style-buffer (hemlock-view)
+  (let* ((*inc-p* t)
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (*form-style* nil)
+         (*form-start* nil)
+         (*form-end* nil)
+         (*superparen-closure* nil)
+         (*segment-array* nil)
+         (hi::*current-buffer* *buf*)
+         (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*inc-pos* (clone (buffer-point *buf*)))
+         (comment-end (or (buffer-top-level-sexpr-end *buf*) (buf-end-mark)))
+         (atom-start (atom-start (mark-prev *inc-pos*))) ; *** ?
+         (atom-end (or (atom-end *inc-pos*) *inc-pos*))
+         (char (mark-char (mark-max (buf-start-mark) (or (mark-prev *inc-pos*) *inc-pos*))))
+         (*style-case-p* (if (null *style-case-p*) nil (writable-p)))
+         style-end)
+    (when char
+      #+sax-debug (when *dynamically-style-buffer-debug* 
+                     (debug-out "~%~%~S" 'dynamically-style-buffer)
+                     (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                     (debug-out "~%char: ~S" char)
+                     (debug-out "~%atom-start: ~s" atom-start)
+                     (debug-out "~%atom-end: ~s" atom-end))
+      (cond ((and (char= char #\#)
+                  (char= (mark-char (mark-max (buf-start-mark) (mark-offset *inc-pos* -2))) #\|))
+             ;; *** could do better than buf-start-mark
+             (style-comments (buf-start-mark) comment-end))
+            (t
+             (multiple-value-bind (start inside-quotes-p semi-colon-pos)
+                                  (calculate-context char)
+               #+sax-debug (when *dynamically-style-buffer-debug* 
+                              (debug-out "~%~%start: ~S" start)
+                              (debug-out "~%inside-quotes-p: ~S" inside-quotes-p)
+                              (debug-out "~%semi-colon-pos: ~S" semi-colon-pos))
+               (unless start (setq start (buf-start-mark)))
+               (dynamically-style-comments start comment-end t t)
+               (when (or inside-quotes-p
+                         (and (char= char #\") (not inside-quotes-p)))
+                 #+sax-debug (when *dynamically-style-buffer-debug* 
+                                (debug-out "~%start: ~S" start)
+                                (debug-out "~%comment-end: ~S" comment-end))
+                 (return-from dynamically-style-buffer (values atom-start atom-end)))
+               (cond (semi-colon-pos
+                      (let ((line-end (line-end (clone semi-colon-pos))))
+                        (when line-end
+                          ;; eliminate paren highlighting:
+                          (let* ((begin (mark-absolute-position start))
+                                 (count (- (mark-absolute-position line-end) begin)))
+                            (when (and begin count)
+                              (ns:with-ns-range  (char-range begin count)
+                                (let* ((layout (#/layoutManager text-view)))
+                                  (#/removeTemporaryAttribute:forCharacterRange: 
+                                   layout #&NSBackgroundColorAttributeName 
+                                   char-range)))))
+                          (set-style-attributes (attribute-dictionary *semi-colon-comment-style*) 
+                                                semi-colon-pos line-end))))
+                     (t
+                      (unwind-protect
+                          (progn
+                            (#/beginEditing (#/textStorage text-view))
+                            (insert-string (copy-mark atom-end) " o ))))))))))))))))))))))))))))))))))")
+                            (setf style-end (mark-offset (copy-mark atom-end) %inserted-parens%))
+                            (hemlock::parse-over-block (hi::mark-line start) (hi::mark-line style-end))
+                            (rd-style-forms :start start :end style-end)
+                            (unless (or *form-style* *paste-p* (member char '(#\( #\) #\" #\space #\;)))
+                              (when atom-start
+                                (setq *form-style* *generic-text-style*
+                                      *form-start* atom-start
+                                      *form-end* atom-end))))
+                        (delete-characters atom-end %inserted-parens%)
+                        (#/endEditing (#/textStorage text-view))
+                        (when *form-style*
+                          (set-style-attributes (attribute-dictionary *form-style*) *form-start* *form-end*))
+                        (when *superparen-closure* 
+                          (funcall *superparen-closure*))
+                        ;; Setting attributes for a region leaves point at the end 
+                        ;; of the symbol.  Move it back, unless editing there:
+                        (let ((point (buffer-point *buf*)))
+                          (when (not (mark= point *inc-pos*))
+                            (let ((offset (- (mark-charpos point) (mark-charpos *inc-pos*))))
+                              (dotimes (count offset)
+                                ;; a less moronic way to do this??
+                                (hi::handle-hemlock-event hemlock-view %backward-char-event%)))))))))))
+      (values atom-start atom-end))))
+
+(defun calculate-context (new-char)
+  "Calculate top-level-start-pos inside-quotes-p semi-colon-pos"
+  #+sax-debug (when *calculate-context-debug* 
+                 (debug-out "~%~%~S" 'calculate-context)
+                 (debug-out "~%new-char: ~S" new-char)
+                 (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                 (debug-out "~%point: ~S" (buffer-point *buf*))
+                 (debug-out "~%(mark-char point): ~S" (mark-char (buffer-point *buf*))))
+  (let* ((point (clone (buffer-point *buf*)))
+         (right-quote-pos (when (char= new-char #\") (clone point)))
+         top-level-start-pos inside-quotes-p semi-colon-pos left-quote-pos)
+    (flet ((return-even-quote-values ()
+             (when (and right-quote-pos left-quote-pos semi-colon-pos)
+               ;; mark< is not trinary
+               (when (and (mark< left-quote-pos semi-colon-pos)
+                          (mark< semi-colon-pos right-quote-pos))
+                 (setq semi-colon-pos nil)))
+             (return-from calculate-context
+                          (values top-level-start-pos inside-quotes-p semi-colon-pos)))
+           (return-odd-quote-values ()
+             (when (and semi-colon-pos left-quote-pos)
+               (cond ((mark< left-quote-pos semi-colon-pos)
+                      (setq semi-colon-pos nil))
+                     (t
+                      (setq inside-quotes-p nil))))
+             (return-from calculate-context
+                          (values top-level-start-pos inside-quotes-p semi-colon-pos))))
+      (do* ((buf-start (buf-start-mark))
+            (pos (or (mark-prev *inc-pos*) buf-start))
+            (char (mark-char pos) (mark-char pos))
+            (char-1 (mark-char (mark-max (or (mark-prev pos) pos) buf-start))
+                    (mark-char (mark-max (or (mark-prev pos) pos) buf-start)))
+            (first-char-p t nil)
+            (quote-count 0)
+            line-start-p)
+           ((and char char-1 (char= char #\() (or (char-eolp char-1) (mark= pos buf-start)))
+            (setq top-level-start-pos pos)
+            #+sax-debug (when *calculate-context-debug* 
+                           (debug-out "~%quote-count: ~S" quote-count))
+            (cond ((= (mod quote-count 2) 0) ; even quotes
+                   (setf inside-quotes-p nil)
+                   (return-even-quote-values))
+                  (t
+                   (setf inside-quotes-p t)
+                   (return-odd-quote-values))))
+        (cond ((null char)
+               (setq semi-colon-pos nil))
+              ((and (char-eolp char) (not first-char-p))
+               (setq line-start-p t))
+              ((and (char= char #\;) (not line-start-p) (not (char= char-1 #\\)))
+               (setq semi-colon-pos pos))
+              ((and (char= char #\") (not (char= char-1 #\\)))
+               (incf quote-count)
+               (unless right-quote-pos (setq right-quote-pos pos))
+               (setq left-quote-pos pos)))
+        (setq pos (mark-prev pos))
+        (when (null pos)
+          (setq top-level-start-pos nil)
+          (cond ((= (mod quote-count 2) 0) 
+                 (setq inside-quotes-p nil)
+                 #+sax-debug (when *calculate-context-debug* 
+                                (debug-out "~%inside-quotes-p is nil"))
+                 (return-even-quote-values))
+                (t
+                 (setq inside-quotes-p t)
+                 #+sax-debug (when *calculate-context-debug* 
+                                (debug-out "~%inside-quotes-p: t"))
+                 (return-odd-quote-values))))))))
+
+;;; *** This need work:
+(defun char-printable-p (char event)
+  "Is the char printable?"
+  (let ((code (char-code char)))
+    #+sax-debug (when *char-printable-p-debug* 
+                 (debug-out "~%~%~S" 'char-printable-p)
+                 (debug-out "~%char: ~s" char)
+                 ;; (hi::print-pretty-key-event (hi::char-key-event char) t t)
+                 (debug-out "~%code: ~s" code))
+    (let ((control-key-p (hi::key-event-bit-p event "Control"))
+          (option-key-p (hi::key-event-bit-p event "Meta")))
+      #+sax-debug
+      (when *automated-testing-p*
+        (setq control-key-p nil
+              option-key-p nil))
+      #+sax-debug (when *char-printable-p-debug* (debug-out "~%control-key-p: ~s" control-key-p))
+      #+sax-debug (when *char-printable-p-debug* (debug-out "~%option-key-p: ~s" option-key-p))
+      (cond ((not (or control-key-p option-key-p))
+             (when (or (and (>= code 32) (<= code 127)) ; this is the primary case
+                       ;; *** define constants
+                       (= code 13) ; #\newline
+                       (= code 8)  ; #\delete, #\backspace
+                       ; #\tab, to accommodate anticipatory-symbol-complete
+                       (= code 9)
+                       (= code 10) ; $\linefeed
+                       (= code 127)) ; #\del
+               #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable1"))
+               t))
+            #+elvis
+            ((and control-key-p option-key-p) 
+             #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable2"))
+             (when (or (= code 8)) ; control-meta-h & control-meta-delete ****
+               t))
+            (control-key-p
+             (when (or (= code 100) ; control-d
+                       ;; (= code 4) ; *** ?
+                       (= code 11) ; control-k
+                       (= code 23)) ; control-w
+               #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable3"))
+               t))
+            (option-key-p
+             (when (or (= code 182) ; meta-d
+                       (= code 202) ; meta-space ?? ***
+                       (= code 199)) ; meta-\ ?? ***
+               #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable4"))
+               t))
+            (t nil)))))
+
+(defun restyle-comment (view)
+  #+sax-debug (when *handle-hemlock-event-debug* (debug-out "~%restyle-comment-p"))
+  (let* ((line-start (buffer-line-start *buf*))
+         (line-end (buffer-line-end *buf*))
+         (hi::*current-buffer* *buf*)
+         (*current-package* (hemlock::buffer-package *buf*))
+         (text-view (gui::text-pane-text-view (hi::hemlock-view-pane view)))
+         (*layout* (#/layoutManager (#/textContainer text-view))))
+    (when (and line-start line-end)
+      (style-region *generic-text-style* line-start line-end nil)
+      (style-comments line-start line-end)
+      (style-forms view :start line-start :end line-end))))
+
+;;; *** redefinition ***
+(defMethod hi::handle-hemlock-event :around ((view hi:hemlock-view) event)
+  (let* ((*buf* (hemlock-view-buffer view))
+         (hi::*current-buffer* *buf*)
+         (*inc-pos* nil)
+         (*paste-p* nil)
+         (*paste-start* nil)
+         (*paste-end* nil)
+         (keysym (when (typep event 'hi::key-event)
+                   (hi::key-event-keysym event)))
+         (keysym-code (when keysym (hi::code-for-keysym keysym))))
+    (cond ((and keysym *styling-p* (not (keywordp  keysym)) ; char can be :end, :home, etc
+                (not (hi::buffer-minor-mode *buf* "I-Search")))
+           (let ((char (code-char keysym-code)))
+           #+sax-debug (when *handle-hemlock-event-debug* 
+                        (debug-out "~%~%~S" 'handle-hemlock-event)
+                        (debug-out "~%char: ~S" char))
+             (when (key-event= event %control-y%)
+               #+sax-debug (when *handle-hemlock-event-debug* 
+                            (debug-out "~%*paste-start*: ~S" (clone (buffer-point *buf*))))
+               (setq *paste-p* t)
+               (setq *paste-start* (clone (buffer-point *buf*))))
+             (when (key-event= event %control-j%)
+               (setq *style-top-level-form-p* t))
+             (if (and char (not (typep (#/window (hi::hemlock-view-pane view)) 'gui::hemlock-listener-frame))
+                      (char-printable-p char event) (lisp-file-p))
+               (let* ((point (buffer-point *buf*))
+                      (point-char (mark-char point))
+                      (char-1 (mark-char (mark-max (or (mark-prev point) point) (buffer-start-mark *buf*))))
+                      (*style-screen-p* nil)
+                      ;; If a file is not writable, style with color and underlining, but not caps.
+                      (*style-case-p* (if (null *style-case-p*) nil (writable-p)))
+                      restyle-comment-p)
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                              (debug-out "~%point: ~S" point)
+                              (debug-out "~%point-char: ~S" point-char)
+                              (debug-out "~%char-1: ~S" char-1))
+                 (cond ((and (key-event= event %backspace%) ; backspace & delete
+                             char-1
+                             (char= char-1 #\;))
+                        (setf restyle-comment-p t))
+                       ((and point-char (char= point-char #\;)
+                             ;; (or (key-event= event %del%) ; #\del
+                             (key-event= event %control-d%)) ; control-d                             
+                        (setf restyle-comment-p t)))
+
+                 ;; insert the char:
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                                (debug-out "~%~%inserting char: ~S" char))
+                 (ccl::with-autorelease-pool
+                     (call-next-method view event))
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                                (debug-out "~%~%char inserted"))
+
+                 (cond (restyle-comment-p
+                        (restyle-comment view))
+                       (t 
+                        (dynamically-style-buffer view))))
+               (ccl::with-autorelease-pool
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                              (debug-out "~%~%not styled -- calling next method."))
+                 (call-next-method view event)
+                 (cond ((key-event= event %control-y%)
+                        #+sax-debug (when *handle-hemlock-event-debug* 
+                                      (debug-out "~%setting *paste-end*: ~S" (clone (buffer-point *buf*))))
+                        (setq *paste-end* (clone (buffer-point *buf*)))))))))
+                       ; (yank-after view *paste-start* *paste-end*)))))))
+                       ; ((key-event= event %control-meta-q%)
+                        ; (indentation-after view)))))))
+          (t
+           (ccl::with-autorelease-pool
+               (call-next-method view event))))))
+
+;;; Neither of these two are right.  See the note below.
+(objc:defMethod (#/paste: :void) ((text-view gui::hemlock-text-view) (sender :id))
+  (reset-text-view)
+  (call-next-method sender))
+  
+(defMethod yank-after ((view  hi::hemlock-view) generic-start generic-end)
+  (let ((text-view (gui::text-pane-text-view (hi::hemlock-view-pane view))))
+    (hi::handle-hemlock-event view #'(lambda () (style-screen text-view generic-start generic-end)))))
+
+#|
+;;; This is the right way to do paste and yank, but the text
+;;; is being set back to plain by some disagreeable and as yet
+;;; unidentified function. (Cocoa??)
+(defMethod yank-after ((view  hi::hemlock-view) generic-start generic-end)
+  (when (and *styling-p* (lisp-file-p)
+             (not (typep (#/window (hi::hemlock-view-pane view)) 'gui::hemlock-listener-frame)))
+    (let* ((text-view (gui::text-pane-text-view (hi::hemlock-view-pane view)))
+           (*buf* (hi::hemlock-view-buffer view))
+           (hi::*current-buffer* *buf*)
+           (*layout* (#/layoutManager (#/textContainer text-view)))
+           (*current-package* (hemlock::buffer-package *buf*))
+           (start (buffer-top-level-sexpr-start *buf*))
+           (end (buffer-point *buf*))
+           (*style-screen-p* nil)
+           ;; If a file is not writable, style with color and underlining, but not caps.
+           (*style-case-p* (if (null *style-case-p*) nil (writable-p))))
+      #+sax-debug (when *yank-after-debug* 
+                    (debug-out "~%~%~S" 'yank-or-paste-after)
+                    (debug-out "~%start: ~S" start)
+                    (debug-out "~%end: ~S" end)
+                    (debug-out "~%*inc-pos*: ~S" *inc-pos*))
+      ;; *paste-p*, *paste-start* and *paste-end* are set above.
+      (when (and start end)
+        (hemlock::parse-over-block (hemlock-internals::mark-line start) 
+                                   (hemlock-internals::mark-line end))
+        (set-generic-text-style text-view generic-start generic-end) 
+        (dynamically-style-comments start end t t)
+        (dynamically-style-buffer view))
+      (setq *paste-p* nil *paste-start* nil *paste-end* nil))))
+      ;; (gui::update-paren-highlight text-view))))
+|#
+
+;;; ----------------------------------------------------------------------------
+;;; styling menu items
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *edit-menu* 
+  (#/submenu (#/itemWithTitle: (#/mainMenu (ccl::application-ui-object ccl::*application*)) #@"Edit")))
+
+(objc:defMethod (#/toggleStylingAction: :void) ((item ns:ns-menu-item) (sender :id))
+  (cond (*styling-p* 
+         (setq *styling-p* nil)
+         (#/setState: sender #$NSOffState))
+        (t
+         (setq *styling-p* t)
+         (#/setState: sender #$NSOnState))))
+
+(let ((styling-item (#/itemWithTitle: *edit-menu* #@"Styling"))
+      item)
+  (unless (%null-ptr-p styling-item) (#/removeItem: *edit-menu* styling-item))
+  (when (%null-ptr-p styling-item)
+    (#/addItem: *edit-menu* (#/separatorItem ns:ns-menu-item))
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc ns:ns-menu-item)
+                                                      #@"Syntax Styling"
+                                                      (ccl::@selector "toggleStylingAction:")
+                                                      #@""))
+    (#/setTarget: item item)
+    (#/setState: item #$NSOnState)
+    (#/addItem: *edit-menu* item)))
+
+
+
+(when *style-case-p*
+
+(defParameter *style-file-item* nil)
+(defParameter *style-file-vanilla-item* nil)
+
+(defClass STYLING-MENU-ITEM (ns:ns-menu-item)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defMethod (#/styleFileAction: :void) ((item styling-menu-item) (sender :id))
+  (declare (ignore sender))
+  (let ((window (active-hemlock-window)))
+    (when window
+      (style-window window))))
+
+(objc:defMethod (#/styleFileVanillaAction: :void) ((item styling-menu-item) (sender :id))
+  (declare (ignore sender))
+  (let ((window (active-hemlock-window)))
+    (when window
+      (style-vanilla window)))) 
+
+(objc:defMethod (#/styleFolderAction: :void) ((item styling-menu-item) (sender :id))
+  (declare (ignore sender))
+  (style-folder-recursively))
+
+(objc:defMethod (#/validateMenuItem: :<BOOL>) ((item styling-menu-item) item)
+  *styling-p*)
+
+(let ((style-file-item (#/itemWithTitle: *edit-menu* #@"Style File"))
+      item)
+  (when (%null-ptr-p style-file-item)
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc styling-menu-item)
+                                                      #@"Style File"
+                                                      (ccl::@selector "styleFileAction:")
+                                                      #@"u"))
+    (#/setTarget: item item)
+    (setq *style-file-item* item)
+    (#/addItem: *edit-menu* item)))
+
+(let ((style-file-vanilla-item (#/itemWithTitle: *edit-menu* #@"Style File Vanilla"))
+      item)
+  (when (%null-ptr-p style-file-vanilla-item)
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc styling-menu-item)
+                                                      #@"Style File Vanilla"
+                                                      (ccl::@selector "styleFileVanillaAction:")
+                                                      #@"U"))
+    (#/setTarget: item item)
+    (setq *style-file-vanilla-item* item)
+    (#/addItem: *edit-menu* item)))
+
+(let ((style-folder-item (#/itemWithTitle: *edit-menu* #@"Style Folder ..."))
+      item)
+  (when (%null-ptr-p style-folder-item)
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc styling-menu-item)
+                                                      #@"Style Folder ..."
+                                                      (ccl::@selector "styleFolderAction:")
+                                                      #@""))
+    (#/setTarget: item item)
+    (#/addItem: *edit-menu* item)))
+
+) ; closing paren for when
+
+
+
Index: /branches/new-random/contrib/foy/syntax-styling/syntax-styling-2.lisp
===================================================================
--- /branches/new-random/contrib/foy/syntax-styling/syntax-styling-2.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/syntax-styling/syntax-styling-2.lisp	(revision 13309)
@@ -0,0 +1,757 @@
+;;;-*- Mode: Lisp; Package: (SYNTAX-STYLING (CL CCL HEMLOCK-INTERNALS)) -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-2.lisp
+;;;      
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Macros and styling functions.
+;;;      
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      10/18/9   First cut.
+;;;
+;;; ****************************************************************************
+
+(in-package "SAX")
+
+;;; ----------------------------------------------------------------------------
+;;; Macros used to construct the styling functions below.
+;;; ----------------------------------------------------------------------------
+;;; 
+;;; NOTE: Not bothering to gensym these macros.  They are only used in this file,
+;;; and the only variable capture is the intensional variable capture of POS.
+;;;
+(defMacro sparen (style debug-flag name)
+  (declare (ignorable debug-flag name))
+  `(when pos 
+     #+sax-debug (when (and debug-function-p ,debug-flag) 
+                   (debug-out "~%~%~S" ,name)
+                   (debug-out "~%pos: ~S" pos))
+     (let ((end (mark-next pos)))
+       #+sax-debug (when (and debug-function-p ,debug-flag) 
+                     (debug-out "~%end: ~S" end))
+       (when end 
+         (if *inc-p*             
+           (when (mark< pos *inc-pos*)
+             (let* ((macro-start (next-sexpr-start end))
+                    (macro-end (sexpr-end macro-start)))
+               (when (or (mark= end *inc-pos*) 
+                         (and macro-end macro-start (alpha-char-p (mark-char macro-start))
+                              (mark= *inc-pos* macro-end) (mark= macro-start end)))
+                 #+sax-debug (when (and debug-function-p ,debug-flag) 
+                               (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                               (debug-out "~%macro-end: ~S" macro-end))
+                 (let ((start (clone pos)))
+                   (setq *superparen-closure*
+                         #'(lambda () 
+                             #+sax-debug (when (and debug-function-p ,debug-flag)
+                                           (debug-out "~%~%closure being called."))
+                             (set-style-attributes (attribute-dictionary ,style)
+                                                   start end)))))))
+           (style-region ,style pos end nil))
+         (setq pos (nnext-sexpr-start end))))))
+
+(defMacro superparen ()
+  "Super parens surround top-level forms and embedded function definitions."
+  `(sparen *superparen-style* *superparen-debug* 'superparen))
+
+(defMacro eval-when-superparen ()
+  "Eval-when deserves a distinctive style for its parens."
+  `(sparen *eval-when-superparen-style* *eval-when-superparen-debug* 'eval-when-superparen))
+
+(defMacro loop-superparen ()
+  "Loop deserves a distinctive style for its parens."
+  `(sparen *loop-superparen-style* *loop-superparen-debug* 'loop-superparen))
+
+(defMacro paren ()
+  "This does no styling; it just increments POS."
+  `(when pos #+sax-debug (when (and debug-function-p *paren-debug*) 
+                          (debug-out "~%~%~S" 'paren))
+     (setq pos (nnext-sexpr-start (mark-next pos)))))
+
+(defMacro optional-paren ()
+  "This does no styling; it just increments POS, if there is a paren."
+  `(when pos #+sax-debug (when (and debug-function-p *optional-paren-debug*)
+                          (debug-out "~%~%~S" 'optional-paren))
+     (let ((pos-char (mark-char pos)))
+       (when (or (char= pos-char #\()
+                 (char= pos-char #\)))
+         (setq pos (nnext-sexpr-start (mark-next pos)))))))
+
+(defMacro objc-symbl (pos)
+  "Style an objc symbol, or list containing symbol and return value."
+  `(setq ,pos (objc-symbol-styling-function ,pos)))
+
+(defMacro symbl ()
+  "Style a symbol-name, taking into account exported symbols."
+  `(when pos #+sax-debug (when (and debug-function-p *symbol-debug*)
+                          (debug-out "~%~%~S" 'symbl)
+                           (debug-out "~%symbol-style: ~S" symbol-style))
+     (let ((pos-end (sexpr-end pos)))
+       (when pos-end 
+         #+sax-debug (when (and debug-function-p *symbol-debug*)
+                      (debug-out "~%pos-end: ~S" pos-end))
+         (let ((name (string-upcase (region-to-string (region pos pos-end)))))
+           (when name
+             (multiple-value-bind (symbol kind)
+                                  (find-symbol name *current-package*)
+               (cond ((and symbol *current-package* (eq kind :external)
+                           (not (eq symbol-style *variable-definition-symbol-style*)))
+                      (cond ((char= (mark-char pos) #\") 
+                             ; a string, don't set caps  
+                             (style-region *exported-symbol-style* pos pos-end nil))
+                            (t
+                             (style-region *exported-symbol-style* pos pos-end))))
+                     (t
+                      (cond ((char= (mark-char pos) #\")
+                             (style-region symbol-style pos pos-end nil))
+                            (t
+                             (style-region symbol-style pos pos-end))))))))
+         (setq pos (next-sexpr-start pos-end))))))
+
+(defMacro struct-sym ()
+  "Style the name of a structure."
+  `(when pos #+sax-debug (when (and debug-function-p *struct-sym-debug*)
+                          (debug-out "~%~%~S" 'struct-sym))
+     (setq pos (next-sexpr-start (struct-sym-styling-function pos)))))
+
+(defMacro struct-fields ()
+  "Style structure fields."
+  `(when pos #+sax-debug (when (and debug-function-p *struct-fields-debug*)
+                          (debug-out "~%~%~S" 'struct-fields))
+     (do* ((field-start pos (next-sexpr-start field-end))
+           (field-end (when field-start (sexpr-end field-start))
+                      (when field-start (sexpr-end field-start))))
+          ((or (null field-start) (mark> field-start form-end)))
+       (cond ((char= (mark-char field-start) #\()
+              (let* ((symbol-start (mark-next field-start))
+                     (symbol-end (when symbol-start (sexpr-end symbol-start)))
+                     (next-start (when symbol-end (next-sexpr-start symbol-end))))
+                (style-region *defstruct-field-style* symbol-start symbol-end)
+                (when next-start (rd-style-forms :start next-start :end field-end))))
+             (t
+              (style-region *defstruct-field-style* field-start field-end))))
+     (setq pos (mark-prev form-end))))
+
+(defMacro ancestor ()
+  "Style a structure's ancestor."
+  `(when pos #+sax-debug (when (and debug-function-p *ancestor-debug*)
+                          (debug-out "~%~%~S" 'ancestor))
+     (let* ((start (next-sexpr-start (mark-next pos)))
+            (end (when start (sexpr-end start)))
+            (string (when (and start end) (region-to-string (region start end))))
+            ancestor-start)
+       (when (and string (string-equal string ":include"))
+         (style-region *keyword-package-style* start end)
+         (when (setq ancestor-start (next-sexpr-start end))
+           (style-region *defstruct-ancestor-style* ancestor-start
+                         (sexpr-end ancestor-start)))
+         (setq pos (next-sexpr-start (sexpr-end pos)))))))
+
+(defMacro macro ()
+  "Style the name of the macro."
+  `(when pos #+sax-debug (when (and debug-function-p *macro-debug*)
+                          (debug-out "~%~%~S" 'macro))
+     (let ((pos-end (sexpr-end pos)))
+       #+sax-debug (when (and debug-function-p *macro-debug*)
+                    (debug-out "~%pos-end: ~S" pos-end))
+       (when pos-end
+         (style-region macro-style pos pos-end)
+         (setq pos (next-sexpr-start pos-end))))))
+
+(defMacro derivation-list ()
+  "Style the DEFCLASS derivation list."
+  `(when pos #+sax-debug (when (and debug-function-p *derivation-list-debug*)
+                          (debug-out "~%~%~S" 'derivation-list))
+     (let* ((pos-char (mark-char pos))
+            (pos-next (mark-next pos))
+            (pos-end (sexpr-end pos))
+            (end-prev (when pos-end (mark-prev pos-end))))
+       (when (and pos-next end-prev pos-char (char= pos-char #\())
+         #+sax-debug (when (and debug-function-p *derivation-list-debug*)
+                      (debug-out "~%pos-next: ~S" pos-next)
+                      (debug-out "~%end-prev: ~S" end-prev))
+         (style-region *defclass-derivation-style* pos-next end-prev))
+     (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro slot-list ()
+  "Style DEFCLASS slots."
+  `(when pos #+sax-debug (when (and debug-function-p *derivation-list-debug*)
+                          (debug-out "~%~%~S" 'slot-list))
+     (let (slot-positions
+           (pos-end (sexpr-end pos)))
+       (do ((current-start (sexpr-start (mark-prev pos-end))
+                           (sexpr-start (mark-prev current-start))))
+           ((mark<= current-start pos))
+         (when (or (not *inc-p*)
+                   (and *inc-p*
+                        (mark>= *inc-pos* current-start)
+                        (mark<= *inc-pos* (sexpr-end current-start))))
+           (push current-start slot-positions)))
+       (dolist (slot-position slot-positions)
+         (rd-style-forms :start slot-position :end (sexpr-end slot-position))
+         (style-region *defclass-slot-style* (mark-next slot-position)
+                       (sexpr-end (mark-next slot-position))))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro qualifier ()
+  "Style method qualifiers."
+  `(when pos #+sax-debug (when (and debug-function-p *qualifier-debug*)
+                          (debug-out "~%~%~S" 'qualifier))
+     (let ((pos-end (sexpr-end pos)))
+       (when (char= (mark-char pos) #\:)
+         (style-region *keyword-package-style* pos pos-end)
+         (setq pos (next-sexpr-start pos-end))))))
+
+(defun list-regions (start end  &aux e1-start e1-end e2-start e2-end)
+  "List parameter and specializer or optional parameter and defaults."
+  (declare (ignorable end))
+  #+sax-debug (when (and debug-function-p *list-regions-debug*)
+                (debug-out "~%~%~S" 'list-regions)
+                (debug-out "~%start: ~S" start)
+                (debug-out "~%end: ~S" end))
+  (setq e1-end (sexpr-end (mark-next start))
+        e1-start (sexpr-start e1-end))
+  (setq e2-start (next-sexpr-start (mark-next e1-end))
+        e2-end (sexpr-end e2-start))
+  (list e1-start e1-end e2-start e2-end))
+
+(defun parameter-regions (list-start)
+  "Collect specialized and non-specialized parameter regions. Style the defaults for
+  lambda-list-keyword parameters."
+  #+sax-debug (when (and debug-function-p *parameter-regions-debug*)
+                (debug-out "~%~%~S" 'parameter-regions))
+  (let ((list-end (sexpr-end list-start))
+        results option-p)
+    (do* ((start (next-sexpr-start (mark-next list-start)) 
+                 (when (sexpr-end start) (next-sexpr-start (sexpr-end start))))
+          (char (when start (mark-char start)) (when start (mark-char start))))
+         ((or (null start) (mark>= start list-end)) results)
+      #+sax-debug (when (and debug-function-p *parameter-regions-debug*)
+                    (debug-out "~%start: ~S" start))
+      (cond ((char= char #\()
+             (let ((specializer-regions (list-regions start (sexpr-end start))))
+               #+sax-debug (when (and debug-function-p *parameter-regions-debug*)
+                             (debug-out "~%specializer-regions: ~S" specializer-regions))
+               (when (and option-p (third specializer-regions) (fourth specializer-regions))
+                 (rd-style-forms :start (third specializer-regions) :end (fourth specializer-regions)))
+               (push (subseq specializer-regions 0 (when option-p 2))
+                     results)))
+            ((char= char #\&) 
+             (style-region *keyword-package-style* start (sexpr-end start))
+             (setq option-p t))
+            (t 
+             (push (list start (sexpr-end start)) results))))))
+
+(defMacro parameter-list ()
+  "Style the parameter list.  This is called by both functions and methods."
+  `(when pos #+sax-debug (when (and debug-function-p *parameter-list-debug*)
+                          (debug-out "~%~%~S" 'parameter-list))
+     (let ((parameter-regions (parameter-regions pos)))
+       #+sax-debug (when (and debug-function-p *parameter-list-debug*)
+                     (debug-out "~%parameter-regions: ~S" parameter-regions))
+       (dolist (arg parameter-regions)
+         (style-region *parameter-style* (first arg) (second arg))
+         (when (and (third arg) (fourth arg))
+           #+sax-debug (when (and debug-function-p *parameter-list-debug*)
+                         (debug-out "~%third: ~S" (third arg))
+                         (debug-out "~%fourth: ~S" (fourth arg))
+                         (debug-out "~%*specializer-style*: ~S" *specializer-style*))
+           (style-region *specializer-style* (third arg) (fourth arg))))
+       (setq pos (next-sexpr-start (sexpr-end pos))))))
+
+(defMacro embedded-function-definitions ()
+  "Style the functions defined by LABELS and FLET."
+  `(when pos #+sax-debug (when (and debug-function-p *embedded-function-definitions-debug*)
+                          (debug-out "~%~%~S" 'embedded-function-definitions))
+     (let ((pos-end (sexpr-end pos)))
+       (do ((position (next-sexpr-start (mark-next pos))
+                      (next-sexpr-start (nmark-next (sexpr-end position)))))
+           ((or (null position) (mark>= position pos-end)))
+         (embedded-function-styling-function (clone position)))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro variable-definitions ()
+  "Style the variables and default values defined by LET, DO*, etc."
+  `(when pos #+sax-debug (when (and debug-function-p *variable-definitions-debug*)
+                          (debug-out "~%~%~S" 'variable-definitions)
+                          (debug-out "~%pos: ~S" pos))
+     (let ((pos-end (sexpr-end pos)))
+       (do ((position (next-sexpr-start (mark-next pos))
+                      (next-sexpr-start (nmark-next (sexpr-end position)))))
+           ((or (null position) (mark>= position pos-end)))
+         #+sax-debug (when (and debug-function-p *variable-definitions-debug*)
+                      (debug-out "~%variable-definition position: ~S" position))
+         (variable-definition-styling-function (clone position)))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro case-match-forms ()
+  "Style the match forms of a case statement"
+  `(when pos #+sax-debug (when (and debug-function-p *case-match-forms-debug*)
+                          (debug-out "~%~%~S" 'case-match-forms))
+     (let ((end (mark-prev form-end)))
+       (do ((position (next-sexpr-start pos)
+                      (next-sexpr-start (nmark-next (sexpr-end position)))))
+           ((or (null position) (mark>= position end)))
+         (case-match-styling-function position))
+       (setq pos (next-sexpr-start end)))))
+
+(defMacro loop-test ()
+  "Style the test form used by an iteration macro."
+  `(when pos #+sax-debug (when (and debug-function-p *loop-test-debug*)
+                          (debug-out "~%~%~S" 'loop-test))
+     (let ((pos-end (sexpr-end pos)))
+       (rd-style-forms :start pos :end pos-end)
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro variable-form ()
+  "Style the initialization form of a variable definition."
+  `(when pos #+sax-debug (when (and debug-function-p *variable-form-debug*)
+                          (debug-out "~%~%~S" 'variable-form))
+     (let ((pos-end (sexpr-end pos)))
+       (variable-definition-styling-function pos)
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro variable-list ()
+  "Style the variable list of multiple-value-setq, multiple-value-bind, etc."
+  `(when pos #+sax-debug (when (and debug-function-p *variable-list-debug*)
+                          (debug-out "~%~%~S" 'variable-list))
+     (let ((pos-end (sexpr-end pos)))
+       (do* ((var-start (next-sexpr-start (mark-next pos)) 
+                        (next-sexpr-start (nmark-next var-end)))
+             (var-end (when var-start (sexpr-end var-start))
+                      (when var-start (sexpr-end var-start))))
+            ((or (null var-start) (mark> var-start pos-end)))
+         (style-region *variable-definition-symbol-style* var-start var-end nil))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro body ()
+  "Style the body of a macro."
+  `(when pos #+sax-debug (when (and debug-function-p *body-debug*)
+                          (debug-out "~%~%~S" 'body)
+                           (debug-out "~%pos: ~S" pos)
+                           (debug-out "~%form-end: ~S" form-end))
+     (rd-style-forms :start pos :end (mark-prev form-end))
+     (setq pos (mark-prev form-end))))
+
+(defMacro loop-body ()
+  "Style the body of a loop macro."
+  `(when pos #+sax-debug (when (and debug-function-p *loop-body-debug*)
+                          (debug-out "~%~%~S" 'loop-body))
+     (style-elements pos (mark-prev form-end) t)
+     (setq pos (mark-prev form-end))))
+
+(defMacro form ()
+  "Style a single form."
+  `(when pos #+sax-debug (when (and debug-function-p *form-debug*)
+                          (debug-out "~%~%~S" 'form)
+                          (debug-out "~%pos: ~S" pos))
+     (let ((pos-end (sexpr-end pos)))
+       #+sax-debug (when (and debug-function-p *form-debug*)
+                    (debug-out "~%pos-end: ~S" pos-end))
+       (rd-style-forms :start pos :end pos-end)
+       (setq pos (if (next-sexpr-start pos-end)
+                   (mark-min (or (mark-prev form-end) form-end)
+                             (next-sexpr-start pos-end))
+                   (mark-prev form-end))))))
+
+(defMacro doc ()
+  "Style the doc in DEFUN, DEFMETHOD, DEFMACRO, DEFPARAMETER, etc."
+  `(when pos #+sax-debug (when (and debug-function-p *doc-debug*)
+                          (debug-out "~%~%~S" 'doc))
+     (let ((pos-end (sexpr-end pos)))
+       (cond ((mark< pos form-end)
+              (cond ((char-equal #\" (mark-char pos))
+                     (cond (*inc-p*
+                            (style-region *string-style* 
+                                          pos (mark-min *inc-pos* (or pos-end pos))
+                                          nil))
+                           (t
+                            (style-region *string-style* pos pos-end nil)))
+                     (setq pos (if (next-sexpr-start pos-end)
+                                 (if (mark< (mark-prev form-end) 
+                                            (next-sexpr-start pos-end))
+                                   (mark-prev form-end)
+                                   (next-sexpr-start pos-end))
+                                 (mark-prev form-end))))
+                    (t
+                     pos)))
+             (t 
+              form-end)))))
+
+(defMacro options ()
+  "Style DEFCLASS and DEFGENERIC options."
+  `(when pos #+sax-debug (when (and debug-function-p *options-debug*)
+                          (debug-out "~%~%~S" 'options))
+     (do* ((option-start pos (next-sexpr-start (sexpr-end option-start)))
+           (symbol-start (when option-start (mark-next option-start))
+                         (when option-start (mark-next option-start)))
+           (symbol-end (when symbol-start (sexpr-end symbol-start))
+                       (when symbol-start (sexpr-end symbol-start))))
+          ((or (null symbol-start) (mark>= symbol-start form-end)))
+       (when (char-equal #\: (mark-char symbol-start))
+         (style-region *keyword-package-style* symbol-start symbol-end nil)
+         (cond ((string-equal (region-to-string (region symbol-start symbol-end))
+                              ":documentation")
+                (when (next-sexpr-start symbol-end)
+                  (style-region *string-style* 
+                                (next-sexpr-start symbol-end)
+                                (sexpr-end (next-sexpr-start symbol-end)) nil)))
+               (t 
+                (when (next-sexpr-start (sexpr-end symbol-start))
+                  (style-elements (next-sexpr-start symbol-end) form-end))))))
+     (setq pos (mark-prev form-end))))
+
+
+;;; These are called by the macros above:
+(defun struct-sym-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defstruct-symbol-style*))
+    (optional-paren) (symbl) (ancestor) (body) (optional-paren) pos))
+
+(defun embedded-function-styling-function (pos)
+  #+sax-debug (when *embedded-function-styling-function-debug*
+                 (debug-out "~%~%~S" 'embedded-function-styling-function))
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *embedded-function-symbol-style*))
+    (superparen) (symbl) (parameter-list) (doc) (body) (superparen) pos))
+
+(defun variable-definition-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *variable-definition-symbol-style*))
+    (optional-paren) (symbl) (body) (optional-paren) pos))
+
+(defun case-match-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *case-match-style*))
+    (paren) (symbl) (body) (paren) pos))
+
+(defun objc-symbol-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *objc-symbol-style*))
+    (optional-paren) (symbl) (body) (optional-paren) pos))
+
+
+;;; The defstyle styles:
+(defun defpackage-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defpackage-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (body) (superparen)))
+
+(add-style "defpackage" #'defpackage-styling-function)
+
+(defun defparameter-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defparameter-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (form) (doc) (superparen)))
+
+(add-style "defparameter" #'defparameter-styling-function)
+
+(defun defvar-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defvar-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (form) (doc) (superparen)))
+
+(add-style "defvar" #'defvar-styling-function)
+
+(defun defconstant-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defconstant-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (form) (doc) (superparen)))
+
+(add-style "defconstant" #'defconstant-styling-function)
+
+(defun defclass-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defclass-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (derivation-list) (slot-list) (options) (superparen)))
+
+(add-style "defclass" #'defclass-styling-function)
+
+(defun defun-styling-function (pos)
+  #+sax-debug (when *defun-styling-function-debug*
+                 (debug-out "~%~%~S" 'defun-styling-function))
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defun-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "defun" #'defun-styling-function)
+
+(defun defmacro-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defmacro-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "defmacro" #'defmacro-styling-function)
+
+(defun define-compiler-macro-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "define-compiler-macro" #'define-compiler-macro-styling-function)
+
+(defun define-modify-macro-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (form) (doc) (superparen)))
+
+(add-style "define-modify-macro" #'define-modify-macro-styling-function)
+
+(defun define-setf-expander-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "define-setf-expander" #'define-setf-expander-styling-function)
+
+(defun define-condition-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (derivation-list) (slot-list) (options) (superparen)))
+
+(add-style "define-condition" #'define-condition-styling-function)
+
+(defun defgeneric-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defgeneric-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (options) (superparen)))
+
+(add-style "defgeneric" #'defgeneric-styling-function)
+
+(defun defmethod-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defmethod-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (when pos 
+    (superparen) (macro) (symbl) (qualifier) (parameter-list) (doc) (body) (superparen))))
+
+(add-style "defmethod" #'defmethod-styling-function)
+
+(defun objc-defmethod-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *objc-macro-style*))
+    (superparen) (macro) (objc-symbl pos) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "objc:defmethod" #'objc-defmethod-styling-function)
+
+(defun defcommand-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defcommand-symbol-style*)
+        (macro-style *defcommand-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (doc) (body) (superparen)))
+
+(add-style "hemlock::defcommand" #'defcommand-styling-function)
+
+(defun labels-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (embedded-function-definitions) (body) (paren)))
+
+(add-style "labels" #'labels-styling-function)
+
+(defun lambda-styling-function (pos)
+  #+sax-debug (when *lambda-styling-function-debug*
+                (debug-out "~%~%~S" 'lambda-styling-function))
+  (let ((form-end (sexpr-end pos))
+        (macro-style *lambda-macro-style*))
+    (superparen) (macro) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "lambda" #'lambda-styling-function)
+
+(defun flet-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (embedded-function-definitions) (body) (paren)))
+
+(add-style "flet" #'flet-styling-function)
+
+(defun loop-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *loop-macro-style*))
+    (loop-superparen) (macro) (loop-body) (loop-superparen)))
+
+(add-style "loop" #'loop-styling-function)
+
+(defun defstruct-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (struct-sym) (doc) (struct-fields) (superparen)))
+
+(add-style "defstruct" #'defstruct-styling-function)
+
+(defun dotimes-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-form) (body) (paren)))
+
+(add-style "dotimes" #'dotimes-styling-function)
+
+(defun dolist-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-form) (body) (paren)))
+
+(add-style "dolist" #'dolist-styling-function)
+
+(defun multiple-value-bind-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-list) (body) (paren)))
+
+(add-style "multiple-value-bind" #'multiple-value-bind-styling-function)
+
+(defun multiple-value-setq-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-list) (body) (paren)))
+
+(add-style "multiple-value-setq" #'multiple-value-setq-styling-function)
+
+(defun destructuring-bind-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (parameter-list) (body) (paren)))
+
+(add-style "destructuring-bind" #'destructuring-bind-styling-function)
+
+(defun do-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "do" #'do-styling-function)
+
+(defun do*-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "do*" #'do-styling-function)
+
+(defun let-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "let" #'let-styling-function)
+
+(defun let*-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "let*" #'let-styling-function)
+
+(defun prog-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "prog" #'prog-styling-function)
+
+(defun prog*-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "prog*" #'prog*-styling-function)
+
+(defun with-slots-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "with-slots" #'with-slots-styling-function)
+
+(defun with-accessors-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "with-accessors" #'with-accessors-styling-function)
+
+(defun with-open-file-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-form) (body) (paren)))
+
+(add-style "with-open-file" #'with-open-file-styling-function)
+
+(defun macrolet-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (embedded-function-definitions) (body) (paren)))
+
+(add-style "macrolet" #'macrolet-styling-function)
+
+(defun case-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (form) (case-match-forms) (paren)))
+
+(add-style "case" #'case-styling-function)
+(add-style "ccase" #'case-styling-function)
+(add-style "ecase" #'case-styling-function)
+(add-style "typecase" #'case-styling-function)
+(add-style "etypecase" #'case-styling-function)
+(add-style "ctypecase" #'case-styling-function)
+
+(defun eval-when-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (eval-when-superparen) (macro) (form) (body) (eval-when-superparen)))
+
+(add-style "eval-when" #'eval-when-styling-function)
+
+;;; history-lists.lisp needs this, for now:
+(pushnew :syntax-styling *features*)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /branches/new-random/contrib/foy/syntax-styling/syntax-styling-comments.lisp
===================================================================
--- /branches/new-random/contrib/foy/syntax-styling/syntax-styling-comments.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/syntax-styling/syntax-styling-comments.lisp	(revision 13309)
@@ -0,0 +1,400 @@
+;;;-*- Mode: Lisp; Package: (SYNTAX-STYLING (CL CCL HEMLOCK-INTERNALS)) -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-comments.lisp
+;;;
+;;;      copyright © 2009 Glen Foy, all rights reserved,
+;;;
+;;;     These classes support the styling of semi-colon and sharp-stroke comments,
+;;;     and strings.  Most unusual cases are correctly handled: strings embedded in 
+;;;     comments, comments inside of strings, etc.
+;;;
+;;;      Mod history, most recent first:
+;;;      10/18/9   first cut.
+;;; 
+;;; ****************************************************************************
+
+(in-package "SAX")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass STYLED-COMMENT ()
+  ((comment-start :initarg :comment-start :initform nil :reader comment-start)
+   (comment-end :initform nil :initarg :comment-end :reader comment-end))
+  (:documentation "Support for styled comments."))
+
+(defClass STYLED-SEMI-COLON-COMMENT (styled-comment) ())
+
+(defClass STYLED-SHARP-COMMENT (styled-comment) ())
+
+(defMethod style-comment ((comment styled-semi-colon-comment))
+  (set-style-attributes (attribute-dictionary *semi-colon-comment-style*)
+                        (comment-start comment) (comment-end comment)))
+
+(defMethod style-comment ((comment styled-sharp-comment))
+  (set-style-attributes (attribute-dictionary *sharp-comment-style*)
+                        (comment-start comment) (comment-end comment)))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass STYLED-STRING ()
+  ((string-start :initarg :string-start :initform nil :reader string-start)
+   (string-end :initform nil :initarg :string-end :reader string-end))
+  (:documentation "Support for styled strings."))
+
+(defMethod style-string ((string styled-string))
+  (cond (*inc-p* ; if dynamic, never style past *inc-pos* 
+         (set-style-attributes (attribute-dictionary *string-style*)
+                               (string-start string) *inc-pos*))
+        (t
+         (set-style-attributes (attribute-dictionary *string-style*)
+                               (string-start string) (string-end string)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass SEGMENT-ARRAY ()
+  ((array :initarg :array :reader segment-array-array)
+   (length :initarg :length :accessor segment-array-length))
+  (:documentation 
+   "A sorted 2d array of the start and end positions for segments  in
+a buffer.  There are three segment types: strings, semi-colon comments, 
+and sharp-stroke comments.  The method not-embedded-in-segment-p does
+ a binary search for the position of a particular char to see if the 
+char is embedded."))
+
+(defMethod print-object ((array segment-array) stream)
+  (declare (ignore stream))
+  #+sax-debug (when *print-object-segment-array-debug*
+                (dump-segment-array array))
+  #-sax-debug (call-next-method))
+
+(defmethod dump-segment-array ((a segment-array))
+  (format t "~%~%segment-array length: ~S" (segment-array-length a))
+  (dotimes (idx (segment-array-length a))
+    (format t "~%   ~S" (aref (segment-array-array a) idx 0))
+    (format t "~%   ~S~%" (aref (segment-array-array a) idx 1))))
+
+(defun unify-segment-lists (segment-list-1 segment-list-2)
+  "Merge two lists, discarding segments which are embedded in segments of the other list."
+  (do* ((list-1 segment-list-1)
+        (list-2 segment-list-2)
+        (segment-1 (first list-1) (first list-1))
+        (segment-2 (first list-2) (first list-2))
+        (unified-list nil))
+       ((and (endp list-1) (endp list-2)) (nreverse unified-list))
+    (cond ((and list-1 list-2)
+           (cond ((mark< (first segment-1) (first segment-2))
+                  (cond ((mark< (first segment-2) (second segment-1))
+                         (pop list-2))
+                        (t 
+                         (push segment-1 unified-list)
+                         (pop list-1))))
+                 (t
+                  (cond ((mark< (first segment-1) (second segment-2))
+                         (pop list-1))
+                        (t 
+                         (push segment-2 unified-list)
+                         (pop list-2))))))
+          (t ; one list is empty - add what's left of the other
+           (cond ((endp list-1)
+                  (return (append (nreverse unified-list) list-2)))
+                 (t
+                  (return (append (nreverse unified-list) list-1))))))))
+
+(defun make-segment-array (table)
+  "Constructor for the segment-array class."
+  (let ((table-length (length table)))
+    (make-instance 'segment-array
+      :length table-length
+      :array (make-array `(,table-length 2)
+                         :initial-contents table))))
+
+;;; This is called when constructing the segment array and to get a list of strings
+;;; to style. When styling dynamically, cull the string list. When constructing the 
+;;; segment array, don't.
+;;;
+(defun create-string-list (start end  &optional styling-p)
+  "Return a list of the form, (start end), for each string in buffer.
+The list is in reverse order."
+  (flet ((semi-colon-commented-p (pos)
+           (do* ((start (mark-move pos 0) (nmark-next start))
+                 (char (mark-char start) (mark-char start)))
+                ((mark>= start pos))
+             (when (char= char #\;) (return-from semi-colon-commented-p t))))
+         (sharp-stroke-commented-p (pos)
+           (do ((start (clone pos) (nmark-prev start))
+                (char (mark-char start) (mark-char start))
+                (char-minus-one 
+                 (when (>= (mark-charpos start) 1) (mark-char (mark-prev pos)))
+                 (when (>= (mark-charpos start) 1) (mark-char (mark-prev pos)))))
+               ((or (= (mark-charpos start) 1)
+                    (and (char= char #\#) (char= char-minus-one #\|))))
+             (when (and (char= char #\|) 
+                        (char= char-minus-one #\|))
+               (return-from sharp-stroke-commented-p t)))))
+    (do* ((position (clone start))
+          string-list string-end)
+         ((or (null position) (mark>= position end)) string-list)
+      (cond ((and (eql (mark-char position) #\") 
+                  (not (eql (mark-char (if (> (mark-charpos position) 0)
+                                         (mark-prev position)
+                                         position)) #\\))
+                  ;; Too expensive; may have a rare mis-styled file
+                  ;; because of an unmatched quote in a sharp-comment.
+                  ;; (not (sharp-stroke-commented-p position))
+                  (not (semi-colon-commented-p position)))
+             (setf string-end (sexpr-end position))
+             (cond ((and string-end (mark<= string-end end))
+                    ;; Support for dynamic styling - only cull the string list
+                    ;; when styling strings, not when constructing the segment array
+                    (if *inc-p* 
+                      (if styling-p
+                        ;; cull
+                        (when (and (mark>= *inc-pos* position)
+                                   (mark<= *inc-pos* string-end))
+                          (push (list position string-end) string-list))
+                        (push (list position string-end) string-list))
+                      (push (list position string-end) string-list))
+                    (setf position (clone string-end)))
+                   (t 
+                    (return string-list))))
+            (t 
+             (nmark-next position))))))
+
+;;; This is only called by get-combined-segment-list, when doing vanilla styling.
+(defun create-semi-colon-comment-list (start end )
+   "Return a list of the form, (start end), for each comment in buffer."
+   (do* ((position (clone start))
+         comment-list comment-end)
+        ((or (null position) (mark> position end)) (nreverse comment-list))
+      (cond ((and (eql (mark-char position) #\;) 
+                  (mark> position (buf-start-mark)) ; *** mode line ???
+                  (not (eql (mark-char (mark-prev position)) #\\)))
+              (setf comment-end (line-end (clone position)))
+              (cond ((and comment-end (mark<= comment-end end))
+                      (push (list (clone position) (mark-next comment-end)) comment-list)
+                      (setf position (mark-next comment-end)))
+                     (t ; hum ...
+                      (setf position (mark-next position)))))
+             (t
+              (setf position (mark-next position))))))
+
+;;; This is only called by get-combined-segment-list, when doing vanilla styling.
+(defun create-sharp-stroke-comment-list (start end )
+  "Return a list of the form, (start end), for each comment in buffer."
+  (do* ((position (clone start))
+        comment-list comment-end)
+       ((or (null position) (mark> position end)) (nreverse comment-list))
+    (cond ((and (eql (mark-char position) #\#)
+                (eql (mark-char (mark-next position)) #\|)
+                (mark> position (buf-start-mark))
+                (not (eql (mark-char (mark-prev position)) #\\)))
+           (setf comment-end (pattern-search position *stroke-sharp-forward-pattern* end))
+           (cond ((and comment-end (mark<= comment-end end))
+                  (push (list position comment-end) comment-list)
+                  (setf position (mark-next comment-end)))
+                 (t 
+                  (return (nreverse comment-list)))))
+          (t
+           (setq position (mark-next position))))))
+
+;;; This is only called by get-combined-segment-list, when doing vanilla styling.
+(defun create-cocoa-syntax-list (start end pattern)
+  "Return a list of the form, (start end), for each Cocoa function name in buffer."
+  (do* ((position (pattern-search (clone start) pattern end)
+                  (pattern-search (clone name-end) pattern end))
+        (name-end (when position (sexpr-end position)) (when position (sexpr-end position)))
+        name-list)
+       ((or (null position) (null name-end) (mark> position end)) (nreverse name-list))
+    (push (list position name-end) name-list)))
+
+(defMethod not-embedded-in-segment-p ((array segment-array) position)
+  ;; Do a binary search of the segment-array to see if the position is embedded.
+  #+sax-debug (when *not-embedded-in-segment-p-debug*
+               (debug-out "~%~%~S" 'not-embedded-in-segment-p)
+               (dump-segment-array array)
+               (debug-out "~%position: ~S" position))
+  (when (or (zerop (segment-array-length array)) (null position))
+    (return-from not-embedded-in-segment-p t))
+  (do* ((top (1- (segment-array-length array)))
+        (bottom 0)
+        (index (truncate (+ bottom top) 2) (truncate (+ bottom top) 2)))
+       ((< top bottom) t)
+    (when (and (mark< (aref (segment-array-array array) index 0) position)
+               (mark> (aref (segment-array-array array) index 1) position))
+      ;; embedded - return the end of the containing segment as the second value:
+      (return (values nil (aref (segment-array-array array) index 1))))
+    (cond ((mark<= position (aref (segment-array-array array) index 0))
+           (setf top (1- index)))
+          ((mark>= position (aref (segment-array-array array) index 1))
+           (setf bottom (1+ index)))
+          (t (error "~&Bad value in binary search: ~a" position)))))
+
+(defun embedded-in-segment-p (pos)
+  (when *segment-array*
+    (multiple-value-bind (not-embedded-p end-of-segment)
+                         (not-embedded-in-segment-p *segment-array* pos)
+      (values (not not-embedded-p) end-of-segment))))
+
+(defun style-strings (&optional (start (buf-start-mark)) (end (buf-end-mark))
+                                &aux string-instances)
+  #+sax-debug (when *style-strings-debug*
+               (debug-out "~%~%~S" 'style-strings))
+  (setf *segment-list* (create-string-list start end *inc-p*))
+  (do* ((string-list *segment-list* (rest string-list))
+        (start-string (first (first string-list)) (first (first string-list)))
+        (end-string (second (first string-list)) (second (first string-list))))
+       ((null start-string))
+    (push (make-instance 'styled-string
+            :string-start start-string
+            :string-end end-string)
+          string-instances))
+  ;; Create the segment array - if styling dynamically.
+  ;; Create the inclusive string list for the segment array.
+  (setf *segment-array* (make-segment-array 
+                         (if *inc-p*
+                           (setf *segment-list* (nreverse (create-string-list start end)))
+                           (setf *segment-list* (nreverse *segment-list*)))))
+  (dolist (string string-instances)
+    (style-string string))
+  string-instances)
+
+(defun style-semi-colon-comments (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  #+sax-debug (when *style-semi-colon-comments-debug*
+                (debug-out "~%~%~S" 'style-semi-colon-comments))
+  (let ((comment-instances nil)
+        (comment-segment-list nil))
+    (do* ((start-comment (pattern-search start *semicolon-forward-pattern* end)
+                         (pattern-search end-comment *semicolon-forward-pattern* end))
+          (end-comment (when start-comment (line-end (clone start-comment)))
+                       (when start-comment (line-end (clone start-comment)))))
+         ((or (not start-comment)
+              (not end-comment)
+              (mark> start-comment end)))
+      #+sax-debug (when *style-semi-colon-comments-debug*
+                   (debug-out "~%start-comment: ~S" start-comment)
+                   (debug-out "~%end-comment: ~S" end-comment))
+
+      ;; The first AND handles the case where a string spans two comments. 
+      (when (or (and (mark= start-comment (mark-line-start start-comment))
+                     (or (not *inc-p*)
+                         (and *inc-p* 
+                              (mark>= *inc-pos* start-comment)
+                              (mark<= (mark-prev *inc-pos*) end-comment))))
+                ;; with dynamically-style-comments *segment-array* may not be there yet.
+                (and (not (embedded-in-segment-p start-comment))
+                     (not (and (>= (mark-charpos start-comment) 2)
+                               (eq (mark-char start-comment -1) #\\)
+                               (eq (mark-char start-comment -2) #\#)))))
+        ;; Need the entire segment array for accurate parsing, even when
+        ;; not styling this comment:
+        (push (list start-comment end-comment) comment-segment-list)
+        (when (or (not *inc-p*)
+                  (and *inc-p* 
+                       (mark>= *inc-pos* start-comment)
+                       (mark<= (mark-prev *inc-pos*) end-comment)))
+          (push (make-instance 'styled-semi-colon-comment 
+                  :comment-start start-comment
+                  :comment-end end-comment)
+                comment-instances))))
+    (setf *segment-list* 
+          (unify-segment-lists (nreverse comment-segment-list) *segment-list*))
+    (setf *segment-array* (make-segment-array *segment-list*))
+    (setf comment-instances (nreverse comment-instances))
+    (dolist (comment comment-instances)
+      (style-comment comment))
+    comment-instances))
+
+(defun style-sharp-comments (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  (flet ((find-end-comment (start-comment)
+           (do* ((level-count 1)
+                 (next-end-comment (pattern-search start-comment *stroke-sharp-forward-pattern* end)
+                                   (when next-start-comment
+                                     (pattern-search (nmark-offset next-start-comment 2) *stroke-sharp-forward-pattern* end)))
+                 (next-start-comment (pattern-search (nmark-offset start-comment 2) *sharp-stroke-forward-pattern* end)
+                                     (when next-start-comment
+                                       (pattern-search (nmark-offset next-start-comment 2) *sharp-stroke-forward-pattern* end))))
+                ((null next-end-comment))
+             (when (and next-start-comment (mark< next-start-comment next-end-comment))
+               ;; nested
+               (incf level-count))
+             (decf level-count)
+             (when (= level-count 0) (return next-end-comment)))))
+    (let ((comment-instances nil)
+          (comment-segment-list nil))
+      (do* ((start-comment (pattern-search start *sharp-stroke-forward-pattern* end)
+                           (pattern-search end-comment *sharp-stroke-forward-pattern* end))
+            (end-comment (when (and start-comment (mark<= start-comment end)) ; *** redundant
+                           (find-end-comment start-comment))
+                         (when (and start-comment (mark<= start-comment end))
+                           (find-end-comment start-comment))))
+           ((or (not start-comment) 
+                (not end-comment)))
+        (cond ((and (not-embedded-in-segment-p *segment-array* start-comment)
+                    (not-embedded-in-segment-p *segment-array* end-comment)
+                    (or (not *inc-p*)
+                        (and *inc-p* 
+                             (mark>= *inc-pos* start-comment)
+                             (mark<= (mark-offset *inc-pos* -3) end-comment))))
+               (push (list start-comment end-comment) comment-segment-list)
+               (push (make-instance 'styled-sharp-comment 
+                       :comment-start (mark-offset start-comment -2)
+                       :comment-end (mark-offset end-comment 2))
+                     comment-instances))))
+      (when comment-instances
+        (setf *segment-list* (unify-segment-lists (nreverse comment-segment-list) *segment-list*))
+        (setf *segment-array* (make-segment-array *segment-list*))
+        (setf comment-instances (nreverse comment-instances))
+        (dolist (comment comment-instances)
+          (style-comment comment))
+        comment-instances))))
+
+(defun style-comments (start end)
+  (style-strings start end)
+  (style-semi-colon-comments start end)
+  (style-sharp-comments start end))
+
+(defun dynamically-style-comments (start end style-strings-p style-semi-colon-comments-p)
+  #+sax-debug (when *dynamically-style-comments-debug*
+                (debug-out "~%~%~S" 'dynamically-style-comments))
+  (let ((hi::*current-buffer* *buf*))
+    (hemlock::parse-over-block (mark-line start) (mark-line end))
+    (when style-strings-p (style-strings start end))
+    (when style-semi-colon-comments-p 
+      ;; (style-semi-colon-comments (mark-line-start end) end))))
+      ;; Start is necessary to generate an complete segment-array for subsequent styling:
+      (style-semi-colon-comments start end))))
+
+;;; *** this needs to use start and end
+(defun get-combined-segment-list ()
+  (let* ((start (buf-start-mark))
+         (end (buf-end-mark))
+         (string-list (nreverse (create-string-list start end)))
+         (semi-colon-comment-list (create-semi-colon-comment-list start end))
+         (sharp-stroke-comment-list (create-sharp-stroke-comment-list start end))
+         (cocoa-function-list (create-cocoa-syntax-list start end *sharp-slash-forward-pattern*))
+         (cocoa-constant1-list (create-cocoa-syntax-list start end *sharp-dollar-forward-pattern*))
+         (cocoa-constant2-list (create-cocoa-syntax-list start end *sharp-ampersand-forward-pattern*))
+         (cocoa-constant3-list (create-cocoa-syntax-list start end *colon-lessthan-forward-pattern*))
+         (cocoa-constant4-list (create-cocoa-syntax-list start end *sharp-backslash-forward-pattern*)))
+    (unify-segment-lists 
+     string-list 
+     (unify-segment-lists 
+      cocoa-constant1-list
+      (unify-segment-lists 
+       cocoa-constant2-list
+       (unify-segment-lists 
+        cocoa-constant3-list
+        (unify-segment-lists 
+         cocoa-constant4-list
+         (unify-segment-lists 
+          cocoa-function-list
+          (unify-segment-lists 
+           semi-colon-comment-list
+           sharp-stroke-comment-list)))))))))
+
+
+
+
Index: /branches/new-random/contrib/foy/syntax-styling/syntax-styling-specials.lisp
===================================================================
--- /branches/new-random/contrib/foy/syntax-styling/syntax-styling-specials.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/syntax-styling/syntax-styling-specials.lisp	(revision 13309)
@@ -0,0 +1,671 @@
+;;;-*- Mode: Lisp; Package: SYNTAX-STYLING -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-specials.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Special variables, utility functions and macros.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      10/18/9   First cut.
+;;;
+;;; ****************************************************************************
+
+#-sax-debug
+(defPackage syntax-styling (:use :cl :ccl :hemlock-internals) (:nicknames "SAX"))
+
+(in-package "SAX")
+
+(defParameter *style-case-p* t "To set case, or not to set case.")
+
+;;; ----------------------------------------------------------------------------
+;;; Configure your style by hacking the colors and style parameters below:
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *black-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.0 0.0 1.0))
+(defParameter *gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.92 0.92 0.92 1.0))
+(defParameter *medium-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.30 0.30 0.30 1.0))
+(defParameter *darker-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.11 0.11 0.11 1.0))
+(defParameter *dark-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.01 0.01 0.01 1.0))
+(defParameter *blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.1 0.65 1.0))
+(defParameter *light-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.35 0.65 1.0))
+(defParameter *green-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.2 0.0 1.0))
+(defParameter *turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.3 0.4 1.0))
+(defParameter *violet-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.15 0.1 0.7 1.0))
+(defParameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.5 0.1 0.2 1.0))
+(defParameter *medium-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.8 0.0 0.2 1.0))
+(defParameter *magenta-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.75 0.0 0.5 1.0))
+(defParameter *dark-magenta-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.35 0.0 0.25 1.0))
+(defParameter *brown-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.35 0.2 0.0 1.0))
+
+(defParameter *generic-symbol-color* *blue-color*)
+(defParameter *generic-macro-color* *wine-red-color*)
+
+;;; Convert style-spec to an ns-dictionary with the specified attributes.
+;;; Temporary text attributes only support color and underlining.
+(defun spec-to-dict (font-spec)
+  (let* ((dict (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+         (color (getf font-spec :font-color)) 
+         (underline (getf font-spec :font-underline)) ; :single :double :thick
+         (underline-int (case underline (:single 1) (:double 2) (:thick 3))))
+    (when color (#/setObject:forKey: dict color 
+                                     #&NSForegroundColorAttributeName))
+    (when (and underline underline-int) 
+      (#/setObject:forKey: dict (#/numberWithInt: ns:ns-number underline-int)
+                           #&NSUnderlineStyleAttributeName))
+    dict))
+
+;;; ----------------------------------------------------------------------------
+;;; The Styles:
+;;; ----------------------------------------------------------------------------
+;;;
+;;; The cdr of each dotted-pair is the capitalization spec:
+(defParameter *vanilla-styling* (cons (spec-to-dict (list :font-color *black-color*)) :down))
+(defParameter *generic-text-style* (cons (spec-to-dict (list :font-color *darker-gray-color*)) :down))
+(defParameter *generic-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :cap3))
+(defParameter *generic-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *generic-function-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))  
+(defParameter *embedded-function-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))  
+;;; This is also the style for lambda-list keywords:
+(defParameter *keyword-package-style* (cons (spec-to-dict (list :font-color *dark-magenta-color*)) :down))
+(defParameter *cl-package-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *exported-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :double)) :up))
+
+(defParameter *semi-colon-comment-style* (cons (spec-to-dict (list :font-color *turquoise-color*)) :unchanged))
+(defParameter *sharp-comment-style* (cons (spec-to-dict (list :font-color *medium-gray-color*)) :unchanged))
+(defParameter *string-style* (cons (spec-to-dict (list :font-color *turquoise-color*)) :unchanged))
+
+(defParameter *superparen-style* (cons (spec-to-dict (list :font-color *magenta-color*)) :unchanged))
+(defParameter *eval-when-superparen-style* (cons (spec-to-dict (list :font-color *magenta-color*)) :unchanged))
+(defParameter *loop-superparen-style* (cons (spec-to-dict (list :font-color *turquoise-color*)) :unchanged))
+
+(defParameter *variable-definition-symbol-style* (cons (spec-to-dict (list :font-color *light-blue-color*)) :down))
+(defParameter *defstruct-field-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *defstruct-ancestor-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *defclass-derivation-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *defclass-slot-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *parameter-style* (cons (spec-to-dict (list :font-color *light-blue-color*)) :down))
+(defParameter *specializer-style* (cons (spec-to-dict (list :font-color *green-color*)) :unchanged))
+(defParameter *case-match-style* (cons (spec-to-dict (list :font-color *light-blue-color*)) :down))
+
+(defParameter *defpackage-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defparameter-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defvar-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defconstant-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defclass-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :up))
+(defParameter *defun-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *defmacro-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *defgeneric-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *defmethod-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *objc-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :unchanged))
+(defParameter *defcommand-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :unchanged))
+(defParameter *defstruct-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :up))
+
+(defParameter *lambda-macro-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *loop-macro-style* (cons (spec-to-dict (list :font-color *magenta-color*)) :up))
+(defParameter *loop-keyword-style* (cons (spec-to-dict (list :font-color *dark-magenta-color*)) :down))
+(defParameter *defun-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :down))
+(defParameter *objc-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :cap8))
+(defParameter *defcommand-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :cap12))
+
+;;; ----------------------------------------------------------------------------
+;;; Various:
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *styling-p* t "To style or not to style.")
+(defParameter *buf* nil "The target buffer.")
+(defParameter *layout* nil "The NSLayoutManager of the target text-view.")
+(defParameter *current-package* nil "Package used to style exported symbols.")
+;;; consolidate these two:
+(defParameter *inc-p* nil "Styling incrementally?")
+(defParameter *inc-pos* nil "Buffer-point during an incremental parse.")
+(defParameter *inside-semi-colon-comment-p* nil)
+(defParameter *paste-p* nil "Is a paste in progress?")
+(defParameter *paste-start* nil "Starting position of a paste operation.")
+(defParameter *paste-end* nil "Ending position of a paste operation.")
+
+;;; test
+(defParameter *style-screen-p* t "To style or not to style the screen after a given operation.")
+(defParameter *style-top-level-form-p* nil "To style or not to style the top-level form after a given operation.")
+(defParameter *segment-list* nil "Comment and string code data structure.")
+(defParameter *segment-array* nil "Comment and string code data structure.")
+
+(defParameter *form-style* nil "The style of the atom being processed incrementally.")
+(defParameter *form-start* nil "The start position of the atom being processed incrementally.")
+(defParameter *form-end* nil "The end position of the atom being processed incrementally.")
+(defParameter *superparen-closure* nil "An ugly hack to style superparens.")
+
+;;; key-event constants:
+(defParameter %control-y% #k"control-y")
+(defParameter %control-meta-q% #k"control-meta-q")
+(defParameter %control-d% #k"control-d")
+(defParameter %backspace% #k"Backspace")
+(defParameter %control-j% #k"control-j")
+(defparameter %backward-char-event% (hi::get-key-event* 98 8))
+
+;;; Search patterns:
+(defparameter *l-paren-forward-pattern* (new-search-pattern :character :forward #\())
+(defparameter *l-paren-backward-pattern* (new-search-pattern :character :backward #\())
+(defparameter *sharp-stroke-forward-pattern* (new-search-pattern :string-insensitive :forward "#|"))
+(defparameter *stroke-sharp-forward-pattern* (new-search-pattern :string-insensitive :forward "|#"))
+(defparameter *semicolon-forward-pattern* (new-search-pattern :character :forward #\;))
+(defParameter *sharp-slash-forward-pattern* (new-search-pattern :string-insensitive :forward "#/"))
+(defParameter *sharp-backslash-forward-pattern* (new-search-pattern :string-insensitive :forward "#\\"))
+(defParameter *sharp-dollar-forward-pattern* (new-search-pattern :string-insensitive :forward "#$"))
+(defParameter *sharp-ampersand-forward-pattern* (new-search-pattern :string-insensitive :forward "#&"))
+(defParameter *colon-lessthan-forward-pattern* (new-search-pattern :string-insensitive :forward ":<"))
+
+;;; ----------------------------------------------------------------------------
+;;; Mark functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+;;; Hemlock's BUFFER is a doubly linked list of LINES.  MARKS specify relative positions 
+;;; within LINES.  Programming Hemlock involves a lot of MARK manipulation. These are some 
+;;; useful macros that operate on MARKS.  Destructive and non-destructive versions
+;;; are usually provided, using the prepended "n" convention for destructive functions.
+
+(defmacro clone (mark) `(hi::copy-mark ,mark :temporary))
+
+(defmacro set-storage (storage source)
+  `(progn
+     (setf (mark-charpos ,storage) (mark-charpos ,source))
+     (setf (mark-line ,storage) (mark-line ,source))
+     ,storage))
+
+;;; Needs to support nested forms as in: (mark-next (sexpr-end pos)),
+;;; only evaluating MARK-OR-FORM once.
+;;; No error, if MARK-OR-FORM evaluates to nil, just return nil.
+(defmacro mark-next (mark-or-form)
+  (let ((param (gensym))
+        (new-mark (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param
+         (let ((,new-mark (clone ,param)))
+           (setq ,new-mark (mark-after ,new-mark))
+           #+sax-debug (when (and *mark-next-debug* (null ,new-mark))
+                         (debug-out "~%mark-next returning nil."))
+           ,new-mark)))))
+
+(defmacro nmark-next (mark-or-form)
+  (let ((param (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param (mark-after ,param)))))
+
+(defmacro mark-prev (mark-or-form)
+  (let ((param (gensym))
+        (new-mark (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param
+         (let ((,new-mark (clone ,param)))
+           (setq ,new-mark (mark-before ,new-mark))
+           #+sax-debug (when (and *mark-prev-debug* (null ,new-mark))
+                         (debug-out "~%mark-prev returning nil."))
+           ,new-mark)))))
+
+(defmacro nmark-prev (mark-or-form)
+  (let ((param (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param (mark-before ,param)))))
+
+;;; This does not cross lines
+(defmacro mark-char (mark &optional offset)
+  (if offset
+    (let ((line (gensym))
+          (line-length (gensym))
+          (mark-charpos (gensym))
+          (offset-position (gensym)))
+      `(when ,mark
+         (let* ((,line (mark-line ,mark))
+                (,line-length (line-length ,line))
+                (,mark-charpos (mark-charpos ,mark))
+                (,offset-position (+ ,mark-charpos ,offset)))
+           (cond ((and (<= 0 ,offset-position) ; offset can be negative
+                       (< ,offset-position ,line-length))
+                  (line-character ,line ,offset-position))
+                 (t
+                  nil)))))
+      `(when ,mark
+         (next-character ,mark))))
+
+(defmacro mark-move (mark pos)
+  (let ((new-mark (gensym)))
+    `(when ,mark
+       (let ((,new-mark (clone ,mark)))
+         (move-to-position ,new-mark ,pos)))))
+
+(defmacro nmark-move (mark pos)
+  `(move-to-position ,mark ,pos))
+
+(defmacro mark-line-start (mark)
+  (let ((new-mark (gensym)))
+    `(when ,mark 
+       (let ((,new-mark (clone ,mark)))
+         (line-start ,new-mark)))))
+
+(defmacro mark-offset (mark offset)
+  (let ((new-mark (gensym)))
+    `(when ,mark
+       (let ((,new-mark (clone ,mark)))
+         (character-offset ,new-mark ,offset)))))
+
+(defmacro nmark-offset (mark offset)
+  `(when ,mark
+     (character-offset ,mark ,offset)
+     ,mark))
+
+(defMacro mark-min (m1 m2) `(if (mark< ,m1 ,m2) ,m1 ,m2))
+
+(defMacro mark-max (m1 m2) `(if (mark> ,m1 ,m2) ,m1 ,m2))
+
+(defmacro buf-end-mark (&optional buffer) 
+  `(clone (buffer-end-mark (if ,buffer ,buffer *buf*))))
+
+(defmacro buf-start-mark (&optional buffer) 
+  `(clone (buffer-start-mark (if ,buffer ,buffer *buf*))))
+
+;;; ----------------------------------------------------------------------------
+;;; Buffer functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+(defmacro buffer-empty-p () `(mark= (buffer-start-mark *buf*) (buffer-end-mark *buf*)))
+
+(defun buffer-line-start (buffer &optional storage)
+  (let ((line (mark-line (buffer-point buffer))))
+    (cond (storage
+           (setf (mark-line storage) line)
+           (setf (mark-charpos storage) 0)
+           storage)
+          (
+           (mark line 0)))))
+
+(defun buffer-line-end (buffer &optional storage)
+  (let ((line (mark-line (buffer-point buffer))))
+    (cond (storage
+           (setf (mark-line storage) line)
+           (setf (mark-charpos storage) (line-length line)))
+          (t
+           (mark line (line-length line))))))
+
+;;; ----------------------------------------------------------------------------
+;;; Lisp syntax functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+(defmacro sexpr-end (start)
+    (let ((sexpr-start (gensym))
+          (sexpr-end (gensym)))
+      `(when ,start
+         (let* ((,sexpr-start (clone ,start))
+                (,sexpr-end (when (hemlock::form-offset ,sexpr-start 1) ,sexpr-start)))
+           (if ,sexpr-end
+             ,sexpr-end
+             #+sax-debug (when *sexpr-end-debug* 
+                           (debug-out "~%sexpr-end returning nil - start-mark: ~S" ,start)))))))
+
+(defmacro sexpr-start (pos)
+  (let ((sexpr-start (gensym)))
+    `(when ,pos
+       (let ((,sexpr-start (clone ,pos)))
+         (if (hemlock::form-offset ,sexpr-start -1) 
+           ,sexpr-start
+           #+sax-debug (when *sexpr-start-debug* 
+                         (debug-out "~%sexpr-start returning nil - pos-mark: ~S" ,pos)))))))
+
+(defmacro limited-sexpr-end (start limit)
+  (let ((sexpr-start (gensym))
+        (sexpr-end (gensym))) 
+    `(when ,start
+       #+sax-debug (when *limited-sexpr-end-debug* 
+                     (debug-out "~%~%~S" 'limited-sexpr-end)
+                     (debug-out "~%start: ~S" ,start)
+                     (debug-out "~%limit: ~S" ,limit))
+       (let* ((,sexpr-start (clone ,start))
+              (,sexpr-end (when (hemlock::form-offset ,sexpr-start 1) ,sexpr-start)))
+         #+sax-debug (when *limited-sexpr-end-debug*
+                       (debug-out "~%sexpr-end: ~S" ,sexpr-end))
+         (if ,sexpr-end
+           (when (mark<= ,sexpr-end ,limit) ,sexpr-end)
+           #+sax-debug (when *limited-sexpr-end-debug* 
+                         (debug-out "~%limited-sexpr-end returning nil - start-mark: ~S" ,start)))))))
+
+(defmacro next-sexpr-start (mark-or-form)
+  (let ((position (gensym))
+        (forward (gensym))
+        (start (gensym))
+        (param (gensym)))
+    ;; evaluate mark-or-form once, only:
+    `(let ((,param ,mark-or-form)) 
+       (when ,param
+         #+sax-debug (when *next-sexpr-start-debug*
+                      (debug-out "~%next-sexpr-start mark-or-form: ~S" ,mark-or-form)
+                      (debug-out "~%next-sexpr-start param: ~S" ,param))
+         (do* ((,position (clone ,param))
+               (,forward (when (hemlock::form-offset ,position 1) ,position)
+                         (when (hemlock::form-offset ,position 1) ,position))
+               (,start (when ,forward (when (hemlock::form-offset ,forward -1) ,forward))
+                       (when ,forward (when (hemlock::form-offset ,forward -1) ,forward))))
+              ((or (null ,start) (mark>= ,start ,param)) 
+               #+sax-debug (when (and *next-sexpr-start-debug* (null ,start)) 
+                            (debug-out "~%next-sexpr-start returning nil"))
+               (if *inc-p*
+                 (when (and ,start (mark< ,start *inc-pos*))
+                   ,start)
+                 ,start))
+           #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%start: ~S" ,start))
+           (hemlock::form-offset ,position 1)
+           #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%(form-offset position 1): ~S" ,position))
+           (cond ((null ,position) 
+                  #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%next-sexpr-start returning nil"))
+                  (return nil))
+                 ((mark<= ,position ,param)
+                  ;; wretched special case: avoid getting stuck:  ie.  (eq ,errsym #.^#$ o )
+                  #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%next-sexpr-start returning (mark-next ,position)"))
+                  (set-storage ,position ,param)
+                  (return (mark-next ,position)))))))))
+
+(defMacro nnext-sexpr-start (mark-or-form)
+  (let ((position (gensym))
+        (forward (gensym))
+        (start (gensym))
+        (param (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param
+         #+sax-debug (when *nnext-sexpr-start-debug*
+                      (debug-out "~%nnext-sexpr-start mark-or-form: ~S" ,mark-or-form)
+                      (debug-out "~%nnext-sexpr-start param: ~S" ,param))
+         (let* ((,position ,param)
+                (,forward (when (hemlock::form-offset ,position 1) ,position))
+                (,start (when ,forward (when (hemlock::form-offset ,forward -1) ,forward))))
+           #+sax-debug (when *nnext-sexpr-start-debug* 
+                        (if (null ,start)
+                          (debug-out "~%nnext-sexpr-start returning nil")
+                          (debug-out "~%nnext-sexpr-start returning: ~S" ,start)))
+           (if *inc-p*
+             (when (and ,start (mark< ,start *inc-pos*))
+               ,start)
+             ,start))))))
+
+(defMacro atom-start (start)
+  (let ((pos (gensym))
+        (char (gensym))
+        (buf-start (gensym)))
+    `(when ,start
+       (let ((,buf-start (buf-start-mark *buf*)))
+         (do* ((,pos ,start (mark-before ,pos))
+               (,char (when (and ,pos (mark>= ,pos ,buf-start))
+                        (mark-char ,pos))
+                      (when (and ,pos (mark>= ,pos ,buf-start))
+                        (mark-char ,pos))))
+              ((or (null ,char) ; ***
+                   (whitespacep ,char) (char= ,char #\() 
+                   (char= ,char #\)) (char= ,char #\"))
+               (if ,pos (mark-after ,pos) ,buf-start)))))))
+
+(defMacro atom-end (s)
+  (let ((start (gensym))
+        (buffer-end-mark (gensym))
+        (pos (gensym))
+        (char (gensym)))
+    `(when ,s
+       (let ((,start (clone ,s))
+             (,buffer-end-mark (buffer-end-mark *buf*)))
+         (do* ((,pos ,start (mark-after ,pos))
+               (,char (when (mark<= ,pos ,buffer-end-mark) (mark-char ,pos))
+                      (when (mark<= ,pos ,buffer-end-mark) (mark-char ,pos))))
+              ((or (null ,char) ; ***
+                   (whitespacep ,char) (char= ,char #\)) (char= ,char #\() 
+                   (char= ,char #\") (char= ,char #\;)) 
+               ,pos))))))
+
+(defun buffer-top-level-sexpr-start (buffer &optional storage)
+  (cond (storage
+         (set-storage storage (buffer-point buffer))
+         (hemlock::top-level-offset storage -1))
+        (t
+         (let ((mark (clone (buffer-point buffer))))
+           (hemlock::top-level-offset mark -1)))))
+
+(defun buffer-top-level-sexpr-end (buffer &optional storage)
+  (cond (storage
+         (set-storage storage (buffer-point buffer))
+         (hemlock::top-level-offset storage 1))
+        (t
+         (let ((mark (clone (buffer-point buffer))))
+           (hemlock::top-level-offset mark 1)))))
+
+
+;;; ----------------------------------------------------------------------------
+;;; Miscellaneous functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+(defun pattern-search (mark pattern &optional end)
+  (with-mark ((m mark))
+    (if end 
+      (when (and (find-pattern m pattern) (mark< m end)) m)
+      (when (find-pattern m pattern) m))))
+
+#|
+;;; (buffer-writable buffer) is broken
+(defun writable-p (thing)
+  (declare (ignore thing))
+  t)
+
+(defun writable-path-p (path)
+  (let* ((file-manager (#/defaultManager ns:ns-file-manager))
+         (path (ccl::%make-nsstring path)))
+    (#/isWritableFileAtPath: file-manager path)))
+
+(defMethod writable-p ((hemlock-view hi::hemlock-view))
+  (let ((buffer (hemlock-view-buffer hemlock-view)))
+    (or (not *style-case-p*)
+        (format t "~%view-writable-p: ~S" (buffer-writable buffer))
+        ;; *** broken
+        (buffer-writable buffer))))
+
+(defMethod writable-p ((text-view gui::hemlock-textstorage-text-view))
+  (let* ((hemlock-view (gui::hemlock-view text-view))
+         (buffer (hemlock-view-buffer hemlock-view)))
+    (or (not *style-case-p*)
+        (format t "~%writable-p: ~S" (buffer-writable buffer))
+        (buffer-writable buffer))))
+
+(defMethod writable-p ((window gui::hemlock-frame))
+  (let* ((hemlock-view (gui::hemlock-view window))
+         (buffer (hemlock-view-buffer hemlock-view)))
+    (or (not *style-case-p*)
+        (format t "~%writable-p: ~S" (buffer-writable buffer))
+        (buffer-writable buffer))))
+|#
+
+(defun active-hemlock-window ()
+  "Return the active hemlock-frame."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (and (typep w 'gui::hemlock-frame)
+            (not (typep w 'gui::hemlock-listener-frame))
+            (#/isKeyWindow w)))))
+
+(defun window-path (w)
+  "Return the window's path."
+  (let* ((pane (slot-value w 'gui::pane))
+         (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+         (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+    (when buffer (hi::buffer-pathname buffer))))
+
+(defmacro char-eolp (char) 
+  `(member ,char '(#\return #\linefeed #\newline ,(code-char #x2028) ,(code-char #x2029))))
+
+(defun ed-beep () (#_NSBeep)) ; *** this beeper doesn't beep
+
+(define-symbol-macro *listener-output* (hemlock-ext::top-listener-output-stream))
+
+(defun listener-msg (string &rest args)
+  (apply 'format *listener-output* string args))
+
+(defun selection-marks (text-view)
+  (let ((selection (#/selectedRange text-view))
+        start end)
+    (when selection
+      (let ((length (ns:ns-range-length selection))
+            (location (ns:ns-range-location selection)))
+        (unless (zerop length)
+          (setf start (move-to-absolute-position (buf-start-mark) location))
+          (setf end (character-offset (clone start) length)))))
+    (values start end)))
+
+(defun key-event= (k1 k2)
+  (and (= (hi::key-event-keysym k1) (hi::key-event-keysym k2))
+       (= (hi::key-event-bits k1) (hi::key-event-bits k2))))
+
+(defmethod hemlock-update ((view hi:hemlock-view) start end &optional count)
+  (let* ((buffer (hemlock-view-buffer view))
+         (document (hi::buffer-document buffer))
+         (text-storage (if document (slot-value document 'gui::textstorage)))
+         (location (mark-absolute-position start))
+         (length (or count (- (mark-absolute-position end) location))))
+;         (count (hemlock::count-characters (region start end))))
+    #+sax-debug (when *hemlock-update-debug*
+                   (debug-out "~%~%~S" 'hemlock-update)
+                   (debug-out "~%start: ~S" start)
+                   (debug-out "~%end: ~S" end)
+                   (debug-out "~%location: ~S" location)
+                   (debug-out "~%length: ~S" length))
+    ;;; 0 is the fontnum
+    (gui::perform-edit-change-notification 
+     text-storage
+     (objc:@selector #/noteHemlockAttrChangeAtPosition:length:)
+     location length 0)))        
+
+(defmethod hemlock-update ((frame gui::hemlock-frame) start end &optional count)
+  (let ((hemlock-view (gui::hemlock-view frame)))
+    (hemlock-update hemlock-view start end count)))
+
+(defMacro attribute-dictionary (var) `(car ,var)) 
+
+(defMacro style-case (var) `(cdr ,var))
+
+(defun set-style-attributes (dictionary &optional (start (buf-start-mark))
+                                        (end (buf-end-mark)))
+  #+sax-debug (when *set-style-attributes-debug* 
+                 (debug-out "~%~%~S" 'set-style-attributes)
+                 (debug-out "~%dictionary: ~S" dictionary)
+                 (debug-out "~%start: ~S" start)
+                 (debug-out "~%end: ~S" end))
+
+  (ns:with-ns-range (range)
+    (let* ((location (mark-absolute-position start))
+           (length (- (mark-absolute-position end) location)))
+      (setf (ns:ns-range-location range) location)
+      (setf (ns:ns-range-length range) length)
+      ;; Remove all temporary attributes from the character range
+      (#/removeTemporaryAttribute:forCharacterRange:
+       *layout* #&NSForegroundColorAttributeName range)
+      (#/removeTemporaryAttribute:forCharacterRange:
+       *layout* #&NSUnderlineStyleAttributeName range)
+      (#/addTemporaryAttributes:forCharacterRange: *layout* dictionary range))))
+
+(defun set-generic-text-style (text-view &optional (start (buf-start-mark)) (end (buf-end-mark)))
+  ;; eliminate paren highlighting:
+  (let* ((begin (mark-absolute-position start))
+         (count (- (mark-absolute-position end) begin)))
+    (when (and begin count)
+      (ns:with-ns-range  (char-range begin count)
+        (let* ((layout (#/layoutManager text-view)))
+          (#/removeTemporaryAttribute:forCharacterRange: 
+           layout #&NSBackgroundColorAttributeName 
+           char-range)))))
+  ;; *** maybe chuck this:
+  (set-style-attributes  (attribute-dictionary *generic-text-style*) start end))
+
+(defun downcase-region (start end)
+  ;; downcases all nonescaped characters in region
+  (filter-region #'string-downcase (region start end)))
+
+(defun upcase-region (start end)
+  (filter-region #'string-upcase (region start end)))
+
+(defun capitalize-region (start end)
+  (filter-region #'string-capitalize (region start end)))
+
+(defMethod set-style-case ((case (eql :down)) start end)
+  (downcase-region start end))
+
+(defMethod set-style-case ((case (eql :up)) start end)
+  ;; don't use eupcase region...
+  (upcase-region start end))
+
+(defMethod set-style-case ((case (eql :unchanged)) start end)
+  (declare (ignore start end)) ())
+
+(defMethod set-style-case ((case (eql :cap)) start end)
+  (capitalize-region start end))
+
+(defMethod set-style-case ((case (eql :cap3)) start end)
+  (set-style-case :down start end)
+  (capitalize-region (mark-offset start 3) (mark-offset start 4)))
+
+(defMethod set-style-case ((case (eql :cap03)) start end)
+  (set-style-case :down start end)
+  (capitalize-region start end)
+  (capitalize-region (mark-offset start 3) (mark-offset start 4)))
+
+(defMethod set-style-case ((case (eql :cap8)) start end)
+  (set-style-case :down start end)
+  (capitalize-region (mark-offset start 8) (mark-offset start 9)))
+
+(defMethod set-style-case ((case (eql :cap12)) start end)
+  (set-style-case :down start end)
+  (capitalize-region (mark-offset start 12) (mark-offset start 13)))
+
+(defMacro style-region (style start end  &optional (set-case-p t))
+  "This is the basic styling macro that calls SET-STYLE-ATTRIBUTES and SET-STYLE-CASE."
+  `(progn
+     #+sax-debug (when *style-region-debug* 
+                  (debug-out "~%~%~S" 'style-region)
+                  (debug-out "~%start: ~S" ,start)
+                  (debug-out "~%end: ~S" ,end)
+                  (debug-out "~%style: ~S" ,style)
+                  (debug-out "~%set-case-p: ~S" ,set-case-p)
+                  (debug-out "~%*paste-p*: ~S" *paste-p*)
+                  (debug-out "~%*paste-start*: ~S" *paste-start*)
+                  (debug-out "~%*paste-end*: ~S" *paste-end*)
+                  (debug-out "~%*inc-p*: ~S" *inc-p*)
+                  (debug-out "~%*inc-pos*: ~S" *inc-pos*))
+     (when (or (and *inc-p* (not *paste-p*)
+                    (mark>= *inc-pos* ,start)
+                    (mark<= *inc-pos* ,end))
+               (not *inc-p*)
+               (and *paste-p*
+                    (mark>= ,start *paste-start*)
+                    (mark<= ,end *paste-end*)))
+
+       (when (and *style-case-p* ,set-case-p (style-case ,style))
+         #+sax-debug (when *style-region-debug*
+                      (debug-out "~%set-style-case, case: ~S" (style-case ,style))
+                      (debug-out "~%set-style-case, region: ~S" (region ,start ,end)))
+           (set-style-case (style-case ,style) ,start ,end))
+
+       (cond ((and *inc-p* (not *paste-p*))
+              ;; Don't set attributes when doing incremental. We are
+              ;; inside #/beginEditing, #/endEditing.  Save the values.
+              #+sax-debug (when *style-region-debug* 
+                            (debug-out "~%~%*** setting *form-style* for: ~S ***" 
+                                       (region-to-string (region ,start ,end))))
+              (setq *form-style* ,style
+                    *form-start* ,start
+                    *form-end* ,end))
+             (t
+              #+sax-debug (when *style-region-debug*
+                             (if (equalp ,style *generic-text-style*)
+                               (debug-out "~%*** styling-region-generically: ~S ***"
+                                          (region-to-string (region ,start ,end)))
+                               (debug-out "~%*** styling-region: ~S ***"
+                                          (region-to-string (region ,start ,end))))
+                             (debug-out "~%style: ~S" ,style))
+              (set-style-attributes (attribute-dictionary ,style) ,start ,end))))))
+
+
Index: /branches/new-random/contrib/foy/syntax-styling/syntax-styling.lisp
===================================================================
--- /branches/new-random/contrib/foy/syntax-styling/syntax-styling.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/syntax-styling/syntax-styling.lisp	(revision 13309)
@@ -0,0 +1,29 @@
+
+;;; syntax-styling.lisp 
+
+(in-package :common-lisp-user)
+
+;;; (pushnew :sax-debug *features*)
+
+(unless (member "SYNTAX-STYLING" *modules* :test #'string-equal)
+  (eval-when (:load-toplevel :execute)
+    (defParameter *syntax-styling-directory*
+      (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+    (defParameter *syntax-styling-files* 
+      (list #+sax-debug (merge-pathnames ";testing-specials.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-specials.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-comments.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-1.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-2.lisp" *syntax-styling-directory*)
+            #+sax-debug (merge-pathnames ";testing1.lisp" *syntax-styling-directory*)
+            #+sax-debug (merge-pathnames ";testing2.lisp" *syntax-styling-directory*)
+            )))
+ 
+(dolist (file *syntax-styling-files*)
+  (load file))
+
+(provide :syntax-styling)
+
+)
Index: /branches/new-random/contrib/foy/window-parking-cm/window-parking-cm.lisp
===================================================================
--- /branches/new-random/contrib/foy/window-parking-cm/window-parking-cm.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/window-parking-cm/window-parking-cm.lisp	(revision 13309)
@@ -0,0 +1,22 @@
+
+;;; cl-documentation.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "WINDOW-PARKING-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *window-parking-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *window-parking-files* 
+    (list (merge-pathnames ";window-parking.lisp" *window-parking-directory*)
+          (merge-pathnames ";window-parking-dialogs.lisp" *window-parking-directory*))))
+ 
+(dolist (file *window-parking-files*)
+  (load file))
+
+(provide :window-parking-cm)
+
+)
Index: /branches/new-random/contrib/foy/window-parking-cm/window-parking-dialogs.lisp
===================================================================
--- /branches/new-random/contrib/foy/window-parking-cm/window-parking-dialogs.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/window-parking-cm/window-parking-dialogs.lisp	(revision 13309)
@@ -0,0 +1,321 @@
+;;;-*- Mode: Lisp; Package: WINDOW-PARKING -*-
+
+;;; ----------------------------------------------------------------------------
+;;; 
+;;;      window-parking-dialogs.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Dialogs for defining and deleting parking spots.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History (most recent edit first)
+;;;      9/9/9  first cut
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "WINDOW-PARKING")
+
+(defparameter *dps-dialog* nil "The define-parking-spot-dialog instance.")
+(defparameter *del-dialog* nil "The delete-parking-spot-dialog instance.")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFINE-PARKING-SPOT-DIALOG (ns:ns-window)
+  ((path :initform nil :accessor psd-path)
+   (okay-button :initform nil :accessor psd-okay-button)
+   (function-key-buttons :initform nil :accessor psd-function-key-buttons)
+   (function-key-matrix :initform nil :accessor psd-function-key-matrix))
+  (:documentation "A dialog for associating a window size and position with a function key.")
+  (:metaclass ns:+ns-object))
+
+(defmethod selected-function-key ((d define-parking-spot-dialog))
+  (read-from-string (ccl::lisp-string-from-nsstring 
+                     (#/title (#/selectedCell (psd-function-key-matrix d))))))
+
+(objc:defmethod (#/okayAction: :void) ((d define-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 0))
+
+(objc:defmethod (#/cancelAction: :void) ((d define-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 1))
+
+(defun open-define-parking-spot-dialog (path &optional (function-key 1))
+  "Open the define-parking-spot-dialog for PATH."
+  (let* ((path-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                    (ccl::%make-nsstring 
+                                                     (format nil "~A" path))
+                                                    cmenu::*tool-key-dictionary*)))
+    (flet ((selectFunctionKey (num)
+             (dolist (button (psd-function-key-buttons *dps-dialog*))
+               (let ((key (read-from-string (ccl::lisp-string-from-nsstring (#/title button)))))
+                 (when (= num key)
+                   (#/selectCell: (psd-function-key-matrix *dps-dialog*) button)
+                   (return))))))
+      (cond (*dps-dialog*
+             (#/setStringValue: (psd-path *dps-dialog*) path-string)
+             (selectFunctionKey function-key)
+             (#/makeKeyAndOrderFront: *dps-dialog* nil)
+             (let ((ret (#/runModalForWindow: ccl::*nsapp* *dps-dialog*)))
+               (#/close *dps-dialog*)
+               (when (zerop ret) (selected-function-key *dps-dialog*))))
+            (t
+             (let ((dialog (#/alloc define-parking-spot-dialog)))
+               (setq *dps-dialog* dialog)
+               (ns:with-ns-rect (r 10 300 600 140)
+                 (#/initWithContentRect:styleMask:backing:defer: 
+                  dialog
+                  r
+                  #$NSTitledWindowMask 
+                  #$NSBackingStoreBuffered
+                  #$NO))
+               (dolist (item (get-items dialog))
+                 (#/addSubview: (#/contentView dialog) item))
+               (#/setTitle: dialog #@"Define Parking Spot")
+               (#/setReleasedWhenClosed: dialog nil)
+               (#/setDefaultButtonCell: dialog (psd-okay-button dialog))
+               (#/center dialog)
+               (#/setStringValue: (psd-path dialog) path-string)
+               (selectFunctionKey function-key)
+               (#/makeKeyAndOrderFront: dialog nil)
+               (let ((ret (#/runModalForWindow: ccl::*nsapp* dialog)))
+                 (#/close dialog)
+                 (when (zerop ret) (selected-function-key dialog)))))))))
+
+(defmethod get-items ((d define-parking-spot-dialog))
+  (append
+   (make-prompt-field)
+   (make-path-field d)
+   (make-function-key-items d)
+   (make-buttons d)))
+
+(defun make-prompt-field ()
+  "Create the prompt text-field."
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Save the front window size, position and function key:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 90 410 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)))
+
+(defun make-path-field (dialog)
+  "Create the path text-field."
+  (list
+   (setf (psd-path dialog)
+         (let* ((string (#/initWithString:attributes: 
+                         (#/alloc ns:ns-attributed-string) 
+                         #@""
+                         cmenu::*tool-doc-dictionary*))
+                (title (#/alloc ns:ns-text-field)))
+           (ns:with-ns-rect (frame 15 72 580 22)
+             (#/initWithFrame: title frame))
+           (#/setEditable: title nil)
+           (#/setDrawsBackground: title nil)
+           (#/setBordered: title nil)
+           (#/setStringValue: title string)
+           title))))
+
+(defun make-function-key-items (dialog)
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Associated Function Key:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 40 200 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)
+   (setf (psd-function-key-matrix dialog)
+         (ns:with-ns-rect (frame 190 40 350 32)
+           (let* ((matrix (#/alloc ns:ns-matrix))
+                  (prototype (#/init (#/alloc ns:ns-button-cell)))
+                  buttons cell-array)
+             (#/setTitle: prototype #@"7     ")
+             (#/setButtonType: prototype #$NSRadioButton)
+             (#/initWithFrame:mode:prototype:numberOfRows:numberOfColumns: 
+              matrix frame #$NSRadioModeMatrix prototype 1 7)
+             (setq cell-array (#/cells matrix))
+             (#/setTitle: (#/objectAtIndex: cell-array 0) #@"1")
+             (push (#/objectAtIndex: cell-array 0) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 1) #@"2")
+             (push (#/objectAtIndex: cell-array 1) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 2) #@"3")
+             (push (#/objectAtIndex: cell-array 2) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 3) #@"4")
+             (push (#/objectAtIndex: cell-array 3) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 4) #@"5")
+             (push (#/objectAtIndex: cell-array 4) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 5) #@"6")
+             (push (#/objectAtIndex: cell-array 5) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 6) #@"7")
+             (push (#/objectAtIndex: cell-array 6) buttons)
+             (setf (psd-function-key-buttons dialog) buttons)
+             matrix)))))
+
+(defun make-buttons (dialog)
+  "Construct the buttons."
+  (flet ((make-button (title x-coord y-coord x-dim y-dim action)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame))
+             (#/setButtonType: button #$NSMomentaryPushInButton)
+             (#/setBezelStyle: button #$NSRoundedBezelStyle)
+             (#/setTitle: button title)
+             (#/setTarget: button dialog)
+             (#/setAction: button action)
+             button)))
+    (list
+     (setf (psd-okay-button dialog)
+           (make-button #@"Okay" 500 10 80 32
+                        (ccl::@selector "okayAction:")))
+     (make-button #@"Cancel" 400 10 90 32
+                  (ccl::@selector "cancelAction:")))))
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DELETE-PARKING-SPOT-DIALOG (ns:ns-window)
+  ((path :initform nil :accessor psd-path)
+   (okay-button :initform nil :accessor psd-okay-button)
+   (function-key-buttons :initform nil :accessor psd-function-key-buttons)
+   (function-key-matrix :initform nil :accessor psd-function-key-matrix))
+  (:documentation "A dialog for deleting parking spots.")
+  (:metaclass ns:+ns-object))
+
+(defmethod selected-function-key ((d delete-parking-spot-dialog))
+  (read-from-string (ccl::lisp-string-from-nsstring 
+                     (#/title (#/selectedCell (psd-function-key-matrix d))))))
+
+(objc:defmethod (#/deleteAction: :void) ((d delete-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 0))
+
+(objc:defmethod (#/cancelAction: :void) ((d delete-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 1))
+
+(defun open-delete-parking-spot-dialog ()
+  "Open the delete-parking-spot-dialog for PATH."
+  (cond (*del-dialog*
+         (#/makeKeyAndOrderFront: *del-dialog* nil)
+         (let ((ret (#/runModalForWindow: ccl::*nsapp* *del-dialog*)))
+           (#/close *del-dialog*)
+           (when (zerop ret) (selected-function-key *del-dialog*))))
+        (t
+         (let ((dialog (#/alloc delete-parking-spot-dialog)))
+           (setq *del-dialog* dialog)
+           (ns:with-ns-rect (r 10 300 600 140)
+             (#/initWithContentRect:styleMask:backing:defer: 
+              dialog
+              r
+              #$NSTitledWindowMask 
+              #$NSBackingStoreBuffered
+              #$NO))
+           (dolist (item (get-delete-items dialog))
+             (#/addSubview: (#/contentView dialog) item))
+           (#/setTitle: dialog #@"Delete Parking Spot")
+           (#/setReleasedWhenClosed: dialog nil)
+           (#/setDefaultButtonCell: dialog (psd-okay-button dialog))
+           (#/center dialog)
+           (#/makeKeyAndOrderFront: dialog nil)
+           (let ((ret (#/runModalForWindow: ccl::*nsapp* dialog)))
+             (#/close dialog)
+             (when (zerop ret) (selected-function-key dialog)))))))
+
+(defmethod get-delete-items ((d delete-parking-spot-dialog))
+  (append
+   (make-delete-prompt-field)
+   (make-delete-function-key-items d)
+   (make-delete-buttons d)))
+
+(defun make-delete-prompt-field ()
+  "Create the prompt text-field."
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Click the number of the parking spot you want to delete:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 90 410 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)))
+
+(defun make-delete-function-key-items (dialog)
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Associated Function Key:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 40 200 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)
+   (setf (psd-function-key-matrix dialog)
+         (ns:with-ns-rect (frame 190 40 350 32)
+           (let* ((matrix (#/alloc ns:ns-matrix))
+                  (prototype (#/init (#/alloc ns:ns-button-cell)))
+                  buttons cell-array)
+             (#/setTitle: prototype #@"7     ")
+             (#/setButtonType: prototype #$NSRadioButton)
+             (#/initWithFrame:mode:prototype:numberOfRows:numberOfColumns: 
+              matrix frame #$NSRadioModeMatrix prototype 1 7)
+             (setq cell-array (#/cells matrix))
+             (#/setTitle: (#/objectAtIndex: cell-array 0) #@"1")
+             (push (#/objectAtIndex: cell-array 0) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 1) #@"2")
+             (push (#/objectAtIndex: cell-array 1) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 2) #@"3")
+             (push (#/objectAtIndex: cell-array 2) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 3) #@"4")
+             (push (#/objectAtIndex: cell-array 3) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 4) #@"5")
+             (push (#/objectAtIndex: cell-array 4) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 5) #@"6")
+             (push (#/objectAtIndex: cell-array 5) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 6) #@"7")
+             (push (#/objectAtIndex: cell-array 6) buttons)
+             (setf (psd-function-key-buttons dialog) buttons)
+             matrix)))))
+
+(defun make-delete-buttons (dialog)
+  "Construct the buttons."
+  (flet ((make-button (title x-coord y-coord x-dim y-dim action)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame))
+             (#/setButtonType: button #$NSMomentaryPushInButton)
+             (#/setBezelStyle: button #$NSRoundedBezelStyle)
+             (#/setTitle: button title)
+             (#/setTarget: button dialog)
+             (#/setAction: button action)
+             button)))
+    (list
+     (setf (psd-okay-button dialog)
+           (make-button #@"Delete" 500 10 80 32
+                        (ccl::@selector "deleteAction:")))
+     (make-button #@"Cancel" 400 10 90 32
+                  (ccl::@selector "cancelAction:")))))
+
Index: /branches/new-random/contrib/foy/window-parking-cm/window-parking.lisp
===================================================================
--- /branches/new-random/contrib/foy/window-parking-cm/window-parking.lisp	(revision 13309)
+++ /branches/new-random/contrib/foy/window-parking-cm/window-parking.lisp	(revision 13309)
@@ -0,0 +1,556 @@
+;;;-*- Mode: Lisp; Package: WINDOW-PARKING -*-
+
+;;; ----------------------------------------------------------------------------
+;;; 
+;;;      window-parking.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code provides a Hemlock window manager and is part of the Context-Menu 
+;;;      tool set.  See the ReadMe file for details.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History (most recent edit first)
+;;;      9/17/9 Fix bogus move after #/saveDocument.
+;;;      9/16/9 Park new window.
+;;;      9/9/9  first cut
+;;;
+;;; ----------------------------------------------------------------------------
+
+
+(defpackage "WINDOW-PARKING" (:nicknames "WP") (:use :cl :ccl))
+(in-package "WINDOW-PARKING")
+
+(require :context-menu-cm)
+(require :list-definitions-cm)
+
+(defparameter *window-parker* nil "The window-parker instance.")
+(defparameter *window-parking-menu* nil "The window-parking-menu instance.")
+(defParameter *park-p* t "To park or not to park.")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass WINDOW-PARKING-MENU (ns:ns-menu) 
+  ((tool-menu :initform nil :accessor tool-menu)
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*window-parking-directory*) :reader doc-path))
+  (:documentation "A menu for adding and deleting parking spots.")
+  (:metaclass ns:+ns-object))
+
+;;; This can be called to add a new parking spot or adjust an existing spot.
+(objc:defmethod (#/defineAction: :void) ((m window-parking-menu) (sender :id))
+  (declare (ignore sender))
+  (let* ((window (cmenu:active-hemlock-window))
+         (path (when window (cmenu:window-path window)))
+         ;; Possibly a re-definition.
+         (current-function-key (get-function-key *window-parker* window))
+         (defined-function-key
+             (when path
+               (if current-function-key
+                 (open-define-parking-spot-dialog path current-function-key)
+                 (open-define-parking-spot-dialog path)))))
+    (when defined-function-key
+      (cond (current-function-key 
+             (cond ((= current-function-key defined-function-key)
+                    ;; Adjusting an existing spot.
+                    (let ((spot (parking-spot-with-function-key *window-parker* current-function-key)))
+                      (init-parking-spot-values spot window current-function-key))
+                    (cmenu:echo-msg "Parking spot ~S modified." current-function-key))
+                   (t
+                    (vacate-current-location *window-parker* window)
+                    (add-parking-spot *window-parker* window defined-function-key)
+                    (cmenu:echo-msg "Parking spot ~S defined." current-function-key))))
+            (t
+             (add-parking-spot *window-parker* window defined-function-key))
+            (cmenu:echo-msg "Parking spot ~S defined." defined-function-key)))))
+
+(objc:defmethod (#/deleteAction: :void) ((m window-parking-menu) (sender :id))
+  (declare (ignore sender))
+  (let ((function-key (open-delete-parking-spot-dialog)))
+    (when function-key
+      (delete-parking-spot *window-parker* function-key))))
+
+(objc:defmethod (#/update :void) ((m window-parking-menu))
+  (cmenu:update-tool-menu m (tool-menu m))
+  (call-next-method))
+
+(defmethod initialize-instance :after ((m window-parking-menu) &key)
+  (setf (tool-menu m) (cmenu:add-default-tool-menu m :doc-file (doc-path m)))
+  (flet ((create-menu-item (name action)
+           (let ((menu-item (make-instance 'ns:ns-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring name)
+                                     cmenu:*hemlock-menu-dictionary*)))
+             (#/setAttributedTitle: menu-item attributed-string)
+             (#/setAction: menu-item action)
+             (#/setTarget: menu-item  m)
+             (#/addItem: m menu-item))))
+    (create-menu-item "Define Parking Spot..." 
+                      (ccl::@selector "defineAction:"))
+    (create-menu-item "Delete Parking Spot..." 
+                      (ccl::@selector "deleteAction:"))))
+  
+(setq *window-parking-menu* (make-instance 'window-parking-menu))
+
+(defun get-window-parking-menu (view event) 
+  (declare (ignore view event))
+  *window-parking-menu*)
+
+(cmenu:register-tool "Window-Parking-CM" #'get-window-parking-menu)
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass PARKABLE-HEMLOCK-FRAME (gui::hemlock-frame)
+  ((parked-p :initform nil :accessor parked-p)
+   (front-p :initform nil :accessor front-p))
+  (:metaclass ns:+ns-object))
+
+(defmethod init-parking ((w parkable-hemlock-frame))
+  (setf (parked-p w) nil)
+  (setf (front-p w) nil))
+
+(defmethod h-position ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.origin.x)))
+
+(defmethod v-position ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.origin.y)))
+
+(defmethod h-dimension ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.size.width)))
+
+(defmethod v-dimension ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.size.height)))
+
+(objc:defmethod (#/close :void) ((w parkable-hemlock-frame))
+  (vacate-current-location *window-parker* w)
+  (call-next-method))
+
+(defmethod modified-p ((w parkable-hemlock-frame))
+  (when w
+    (let* ((pane (slot-value w 'gui::pane))
+           (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+           (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+      (when buffer
+        (hi::buffer-modified buffer)))))
+
+(defmethod print-object ((w parkable-hemlock-frame) stream)
+  (format stream "<parkable-hemlock-frame: ~S>" (namestring (cmenu:window-path w))))
+
+;;; This is a work-around for some odd #/saveDocument behavior:
+;;; Why is the frame being set on a save operation?
+(objc:defmethod (#/saveDocument: :void) ((self gui::hemlock-editor-document) (sender :id))
+  (let* ((url (#/fileURL self))
+         (path (ccl::lisp-string-from-nsstring (#/path url)))
+         (window (cmenu:window-with-path path)))
+    (when window (init-parking window))
+    (call-next-method sender)
+    (when window (setf (parked-p window) t))))
+
+;;; ----------------------------------------------------------------------------
+;;; *** redefinition ***
+;;; Need the equivalent of: (setf ccl::*default-editor-class* 'parkable-hemlock-frame)
+(defun gui::new-hemlock-document-window (class)
+  (let* ((w (gui::new-cocoa-window :class (if (or (eq class 'gui::hemlock-listener-frame)
+                                                  (eq class (find-class 'gui::hemlock-listener-frame)))
+                                            'gui::hemlock-listener-frame
+                                            'parkable-hemlock-frame)
+                                   :auto-display t
+                                   :activate nil))
+         (echo-area-height (+ 1 (gui::size-of-char-in-font gui::*editor-font*))))
+      (values w (gui::add-pane-to-window w :reserve-below echo-area-height))))
+
+(objc:defmethod (#/makeKeyAndOrderFront: :void) ((w parkable-hemlock-frame) (sender :id))
+  (setf (front-p w) t)
+  (call-next-method sender))
+
+(objc:defmethod (#/setFrame:display: :void) ((w parkable-hemlock-frame) (rect :<NSR>ect) (display-p :<BOOL>))
+ (cond ((parked-p w)
+         (call-next-method rect display-p))
+        (t
+         (when (front-p w) (setf (parked-p w) t))
+         (multiple-value-bind (h-position v-position h-dimension v-dimension)
+                              (park *window-parker* w)
+           (if (and h-position v-position h-dimension v-dimension)
+             (ns:with-ns-rect (r h-position v-position h-dimension v-dimension)
+               (call-next-method r display-p))
+             (call-next-method rect display-p))))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass PARKING-SPOT ()
+  ((h-dimension :initform nil :initarg :h-dimension :accessor ps-h-dimension)
+   (v-dimension :initform nil :initarg :v-dimension :accessor ps-v-dimension)
+   (h-position :initform nil :initarg :h-position :accessor ps-h-position)
+   (v-position :initform nil :initarg :v-position :accessor ps-v-position)
+   (tenant :initform nil :initarg :tenant :accessor ps-tenant)
+   (function-key :initform nil :initarg :function-key :accessor ps-function-key))
+  (:documentation "Parking spot position, size, tenant and function key information."))
+
+(defMethod initialize-instance :after ((ps parking-spot) &key window 
+                                       function-key h-dimension v-dimension
+                                       h-position v-position)
+  (cond ((and h-dimension v-dimension h-position v-position function-key)
+         (setf (ps-tenant ps) window)
+         (setf (ps-h-dimension ps) h-dimension)
+         (setf (ps-v-dimension ps) v-dimension)
+         (setf (ps-h-position ps) h-position)
+         (setf (ps-v-position ps) v-position)
+         (setf (ps-function-key ps) function-key))
+        ((and window function-key)
+         (init-parking-spot-values ps window function-key))
+        (t
+         (error "Bogus condition in parking-spot i-i :after"))))
+
+(defMethod init-parking-spot-values ((ps parking-spot) window function-key)
+  (setf (ps-tenant ps) window)
+  (setf (ps-h-dimension ps) (h-dimension window))
+  (setf (ps-v-dimension ps) (v-dimension window))
+  (setf (ps-h-position ps) (h-position window))
+  (setf (ps-v-position ps) (v-position window))
+  (setf (ps-function-key ps) function-key))
+
+(defMethod parking-spot-on-screen-p ((ps parking-spot) &optional window)
+  (let* ((screen (if window 
+                   (#/screen window)
+                   (#/mainScreen ns:ns-screen)))
+         (screen-rect (if (%null-ptr-p screen)
+                        (#/visibleFrame (#/mainScreen ns:ns-screen))
+                        (#/visibleFrame screen)))
+         (screen-left (pref screen-rect :<NSR>ect.origin.x))
+         (screen-right (+ screen-left (pref screen-rect :<NSR>ect.size.width)))
+         (screen-bottom (pref screen-rect :<NSR>ect.origin.y))
+         (screen-top (+ screen-bottom (pref screen-rect :<NSR>ect.size.height))))
+    (and (>= (ps-h-position ps) screen-left)
+         (<= (+ (ps-h-position ps) (ps-h-dimension ps)) screen-right)
+         (>= (ps-v-position ps) screen-bottom)
+         (<= (+ (ps-v-position ps) (ps-v-dimension ps)) screen-top))))
+
+(defMethod print-object ((ps parking-spot) stream)
+  (format stream "<~a ~a ~a>" (type-of ps) (ps-function-key ps)
+          (if (ps-tenant ps) (ps-tenant ps) "empty")))
+
+(defMethod apply-parking-spot-values ((ps parking-spot) window)
+  (setf (ps-tenant ps) window)
+  (when (or (neq (ps-h-dimension ps) (h-dimension window))
+            (neq (ps-v-dimension ps) (v-dimension window))
+            (neq (ps-h-position ps) (h-position window))
+            (neq (ps-v-position ps) (v-position window)))
+    ;; park it
+    (init-parking window)
+    (ns:with-ns-rect (r (ps-h-position ps) (ps-v-position ps) (ps-h-dimension ps) (ps-v-dimension ps))
+      (#/setFrame:display: window r t))
+    (#/makeKeyAndOrderFront: window nil))
+  (let ((style-screen-function (find-symbol "STYLE-SCREEN" (find-package :sax))))
+    (when style-screen-function
+      (let* ((hemlock-view (gui::hemlock-view window))
+             (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+        (when text-view
+          (funcall style-screen-function text-view))))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass WINDOW-PARKER ()
+  ((parking-spots :initform nil :accessor wp-parking-spots)
+   (parking-lot-path :initform (merge-pathnames ";Library;Preferences;org.clairvaux;window-parking;parking-lot" 
+                                                 (hemlock::user-homedir-pathname))
+                      :reader wp-parking-lot-path))
+  (:documentation "A window manager."))
+
+(setf *window-parker* (make-instance 'window-parker))
+
+(defMethod park ((wp window-parker) (window parkable-hemlock-frame))
+  (when (and (wp-parking-spots wp) *park-p*)
+    ;; Already parked?
+    (let* ((position (position window (wp-parking-spots wp) :key #'ps-tenant))
+           spot)
+      (when (null position)
+        (or (setf position (get-empty-position wp))
+            (setf position (bump-position wp (1- (length (wp-parking-spots wp)))))))
+      (cond (position
+             (setq spot (nth position (wp-parking-spots wp)))
+             (move-position-to-front wp position)
+             (setf (ps-tenant spot) window)
+             (values (ps-h-position spot) (ps-v-position spot)
+                     (ps-h-dimension spot) (ps-v-dimension spot)))
+            (t
+             ;; only try to park it once
+             (setf (parked-p window) t))))))
+
+;;; Test to make sure that POSITION is on screen.  If not, call recursively with
+;;; (1- position).  Return POSITION or NIL
+(defMethod bump-position ((wp window-parker) position)
+  ;; Has the recursive call run out of positions?
+  (when (< position 0)
+    (cmenu:notify "There are no on-screen parking spots with unmodified buffers.")
+    (return-from bump-position nil))
+  (let* ((bump-location (nth position (wp-parking-spots wp)))
+         (tenant (when bump-location (ps-tenant bump-location))))
+    (cond ((and bump-location 
+                (parking-spot-on-screen-p bump-location)
+                (not (modified-p tenant)))
+             (when tenant (#/close tenant))
+             position)
+          (t ; location is off-screen or not defined, recursive call
+           (bump-position wp (1- position))))))
+
+;;; Assumes that WINDOW's buffer is unmodified.
+(defMethod bump-location-and-set-location-values ((wp window-parker) location window)
+  (let ((tenant (ps-tenant location)))
+    (when tenant
+      (#/close tenant))
+    (apply-parking-spot-values location window)))
+
+(defMethod move-position-to-front ((wp window-parker) position)
+  (let ((current-location (nth position (wp-parking-spots wp))))
+    (setf (wp-parking-spots wp) 
+          (cons current-location (delete current-location (wp-parking-spots wp))))))
+
+(defMethod parking-spot-with-function-key ((wp window-parker) function-key)
+  (find  function-key (wp-parking-spots wp) :test #'= :key #'ps-function-key))
+
+;;; Find the lowest number parking-spot that has no tenant.
+(defMethod get-empty-position ((wp window-parker))
+  (let ((parking-spots (sort (copy-list (wp-parking-spots wp))
+                             #'(lambda (s1 s2)
+                                 (< (ps-function-key s1) (ps-function-key s2))))))
+    (dolist (spot parking-spots)
+      (when (and (null (ps-tenant spot))
+                 (parking-spot-on-screen-p spot))
+        ;; Return the position in the unsorted list. 
+        (return (position spot (wp-parking-spots wp)))))))
+
+(defMethod add-parking-spot ((wp window-parker) window function-key)
+  (let ((new-parking-spot (make-instance 'parking-spot :window window :function-key function-key)))
+    (setf (wp-parking-spots wp) (cons new-parking-spot (wp-parking-spots wp)))
+    (cmenu:echo-msg "Parking Spot ~a defined." function-key)))
+
+(defMethod add-parking-spot-2 ((wp window-parker) function-key
+                               h-dimension v-dimension h-position v-position)
+  (cond ((and (wp-parking-spots wp)
+              (find-if #'(lambda (spot) (= function-key (ps-function-key spot)))
+                       (wp-parking-spots wp)))
+         (cmenu:notify "Duplicate parking-spot ignored."))
+        (t
+         (let ((new-parking-spot (make-instance 'parking-spot
+                                   :function-key function-key
+                                   :h-dimension h-dimension :v-dimension v-dimension
+                                   :h-position h-position :v-position v-position)))
+           (setf (wp-parking-spots wp) (cons new-parking-spot (wp-parking-spots wp)))))))
+
+(defMethod delete-parking-spot ((wp window-parker) function-key)
+  (let ((parking-spot (find function-key (wp-parking-spots wp) :key #'ps-function-key)))
+    (cond (parking-spot
+           (let ((tenant (ps-tenant parking-spot)))
+             (cond (tenant
+                    (cond ((modified-p tenant)
+                           (cmenu:notify (format nil "First save: ~S.  Then try again."
+                                                 (cmenu:window-path tenant))))
+                          (t
+                           (setf (wp-parking-spots wp) (delete parking-spot (wp-parking-spots wp)))  
+                           (#/close tenant)
+                           (cmenu:echo-msg "Parking Spot ~a deleted." function-key))))
+                   (t
+                    (setf (wp-parking-spots wp) (delete parking-spot (wp-parking-spots wp)))  
+                    (cmenu:echo-msg "Parking Spot ~a deleted." function-key)))))                    
+          (t 
+           (cmenu:notify (format nil "Parking Spot ~a is not currently defined." function-key))))))
+
+(defMethod get-function-key ((wp window-parker) window)
+  (dolist (spot (wp-parking-spots wp))
+    (when (eql window (ps-tenant spot)) (return (ps-function-key spot)))))
+
+(defMethod vacate-current-location ((wp window-parker) window)
+  (let ((location (find window (wp-parking-spots wp) :key #'ps-tenant)))
+    (when location 
+      (setf (ps-tenant location) nil)
+      t)))
+
+(defMethod clear-parking-lot ((wp window-parker))
+  (setf (wp-parking-spots wp) nil))
+
+;;; Move WINDOW to the parking-spot corresponding to the pressed function key,
+;;; unless the parking-spot is not on screen or the window is already in that location.
+(defMethod move-window-to-position ((wp window-parker) window function-key)
+  (when *park-p*
+    (let* ((parking-spot (find function-key (wp-parking-spots wp) :key #'ps-function-key))
+           (tenant (when parking-spot (ps-tenant parking-spot))))
+      (cond ((and parking-spot (parking-spot-on-screen-p parking-spot window))
+             (cond (tenant
+                    (cond ((eql window tenant)
+                           (cmenu:echo-msg "Already in parking-spot ~a." function-key))
+                          (t
+                           (cond ((modified-p tenant)
+                                  (cmenu:notify (format nil "First save: ~S. Then try again." 
+                                                        (cmenu:window-path tenant)))
+                                  (init-parking tenant))
+                                 (t
+                                  (vacate-current-location wp window)
+                                  (bump-location-and-set-location-values wp parking-spot window)
+                                  (#/makeKeyAndOrderFront: window nil)
+                                  (cmenu:echo-msg "Moved to parking-spot ~a." function-key))))))
+                   (t 
+                    (vacate-current-location wp window)
+                    (apply-parking-spot-values parking-spot window)
+                    (#/makeKeyAndOrderFront: window nil)
+                    (cmenu:echo-msg "Moved to parking-spot ~a." function-key))))
+            (t
+             (if (null parking-spot)
+               (cmenu:notify (format nil "Parking-spot ~a is not defined." function-key))
+               (cmenu:notify (format nil "Parking-spot ~a is off screen." function-key))))))))
+
+;;; ----------------------------------------------------------------------------
+;;; file I/O
+;;;
+(defMethod read-parking-spot-entries ((wp window-parker) stream)
+  (let (length h-dimension v-dimension h-position v-position function-key input)
+    (setf input (read stream nil :eof))
+    (when (not (numberp input))
+      (return-from read-parking-spot-entries))
+    (setf length input)
+    (dotimes (count length t)
+      (setf input (read stream nil :eof))
+      ;; *** null ?
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf function-key input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf h-dimension input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf v-dimension input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf h-position input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf v-position input)
+      (add-parking-spot-2 wp function-key h-dimension v-dimension
+                            h-position v-position))))
+
+(defMethod write-parking-spot-entries ((wp window-parker) stream)
+  (let (;; write the positions in reverse order based on their function key order
+        (sorted-parking-spots (sort (copy-list (wp-parking-spots wp)) #'> :key #'ps-function-key)))
+    (format stream "~s~%" (length sorted-parking-spots))
+    (dolist (entry sorted-parking-spots)
+      (format stream "~s~%" (ps-function-key entry))
+      (format stream "~s~%" (ps-h-dimension entry))
+      (format stream "~s~%" (ps-v-dimension entry))
+      (format stream "~s~%" (ps-h-position entry)) 
+      (format stream "~s~%" (ps-v-position entry)))))
+
+(defun read-parking-lot-file ()
+  "Read the parking-lot file."
+  (let ((path (wp-parking-lot-path *window-parker*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (unless (read-parking-spot-entries *window-parker* stream)
+          (cmenu:notify "There is a problem with the parking-lot file.  You will have to redefine your parking spots.")
+          (clear-parking-lot *window-parker*))))))
+
+(defun write-parking-lot-file (&rest args)
+  "Writing function pushed into *lisp-cleanup-functions*."
+  (declare (ignore args))
+  (let ((path (wp-parking-lot-path *window-parker*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-parking-spot-entries *window-parker* stream))))
+
+(pushnew 'write-parking-lot-file ccl::*lisp-cleanup-functions*)
+
+;;; To Do:
+;;; Heap issues involved in saving an image with the utility loaded.
+;;; (pushnew 'read-parking-lot-file ccl::*lisp-startup-functions*)
+
+;;; ----------------------------------------------------------------------------
+;;; Commands and bindings:
+;;;
+(hemlock::defcommand "Move Window to Position 1" (p)
+  "Move the front Hemlock window to parking spot 1."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 1))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 1" #k"F1")
+
+(hemlock::defcommand "Move Window to Position 2" (p)
+  "Move the front Hemlock window to parking spot 2."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 2))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 2" #k"F2")
+
+(hemlock::defcommand "Move Window to Position 3" (p)
+  "Move the front Hemlock window to parking spot 3."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 3))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 3" #k"F3")
+
+(hemlock::defcommand "Move Window to Position 4" (p)
+  "Move the front Hemlock window to parking spot 4."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 4))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 4" #k"F4")
+
+(hemlock::defcommand "Move Window to Position 5" (p)
+  "Move the front Hemlock window to parking spot 5."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 5))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 5" #k"F5")
+
+(hemlock::defcommand "Move Window to Position 6" (p)
+  "Move the front Hemlock window to parking spot 6."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 6))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 6" #k"F6")
+
+(hemlock::defcommand "Move Window to Position 7" (p)
+  "Move the front Hemlock window to parking spot 7."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 7))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 7" #k"F7")
+
+
+(read-parking-lot-file)
+
+
+
+
+
Index: /branches/new-random/contrib/montuori/trivial-ldap/LICENSE.txt
===================================================================
--- /branches/new-random/contrib/montuori/trivial-ldap/LICENSE.txt	(revision 13309)
+++ /branches/new-random/contrib/montuori/trivial-ldap/LICENSE.txt	(revision 13309)
@@ -0,0 +1,136 @@
+                     The Clarified Artistic License
+
+                                Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+        "Package" refers to the collection of files distributed by the
+        Copyright Holder, and derivatives of that collection of files
+        created through textual modification.
+
+        "Standard Version" refers to such a Package if it has not been
+        modified, or has been modified in accordance with the wishes
+        of the Copyright Holder as specified below.
+
+        "Copyright Holder" is whoever is named in the copyright or
+        copyrights for the package.
+
+        "You" is you, if you're thinking about copying or distributing
+        this Package.
+
+        "Distribution fee" is a fee you charge for providing a copy
+        of this Package to another party.
+
+        "Freely Available" means that no fee is charged for the right to
+        use the item, though there may be fees involved in handling the
+        item.  It also means that recipients of the item may redistribute
+        it under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain, or those made Freely Available, or from
+the Copyright Holder.  A Package modified in such a way shall still be
+considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+    a) place your modifications in the Public Domain or otherwise make them
+    Freely Available, such as by posting said modifications to Usenet or an
+    equivalent medium, or placing the modifications on a major network
+    archive site allowing unrestricted access to them, or by allowing the
+    Copyright Holder to include your modifications in the Standard Version
+    of the Package.
+
+    b) use the modified Package only within your corporation or organization.
+
+    c) rename any non-standard executables so the names do not conflict
+    with standard executables, which must also be provided, and provide
+    a separate manual page for each non-standard executable that clearly
+    documents how it differs from the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+    e) permit and encourge anyone who receives a copy of the modified Package
+       permission to make your modifications Freely Available
+       in some specific way.
+
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+    a) distribute a Standard Version of the executables and library files,
+    together with instructions (in the manual page or equivalent) on where
+    to get the Standard Version.
+
+    b) accompany the distribution with the machine-readable source of
+    the Package with your modifications.
+
+    c) give non-standard executables non-standard names, and clearly
+    document the differences in manual pages (or equivalent), together
+    with instructions on where to get the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+    e) offer the machine-readable source of the Package, with your
+       modifications, by mail order.
+
+5. You may charge a distribution fee for any distribution of this Package.
+If you offer support for this Package, you may charge any fee you choose
+for that support.  You may not charge a license fee for the right to use
+this Package itself.  You may distribute this Package in aggregate with
+other (possibly commercial and possibly nonfree) programs as part of a
+larger (possibly commercial and possibly nonfree) software distribution,
+and charge license fees for other parts of that software distribution,
+provided that you do not advertise this Package as a product of your own.
+If the Package includes an interpreter, You may embed this Package's
+interpreter within an executable of yours (by linking); this shall be
+construed as a mere form of aggregation, provided that the complete
+Standard Version of the interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package.  If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of the Standard Version of the Package with a commercial
+distribution is always permitted provided that the use of this Package
+is embedded; that is, when no overt attempt is made to make this Package's
+interfaces visible to the end user of the commercial distribution.
+Such use shall not be construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+                                The End
Index: /branches/new-random/contrib/montuori/trivial-ldap/example.lisp
===================================================================
--- /branches/new-random/contrib/montuori/trivial-ldap/example.lisp	(revision 13309)
+++ /branches/new-random/contrib/montuori/trivial-ldap/example.lisp	(revision 13309)
@@ -0,0 +1,131 @@
+(require 'trivial-ldap)
+
+; see http://www.openldap.org/doc/admin23/quickstart.html for some
+; openldap quickstart documentation.  
+
+;; create a new ldap object.  the port number is the default 389 here.
+(defparameter l
+  (ldap:new-ldap :host "redbaron.local" 
+		 :user "cn=directory manager, dc=example, dc=com"
+		 :sslflag t
+		 :debug t
+		 :pass "secret"
+		 :base "dc=example,dc=com"
+		 :reuse-connection 'ldap:rebind))
+
+
+;; create some entry objects.  
+(defparameter entry-one
+  (ldap:new-entry "dc=example,dc=com" 
+		  :attrs '((objectclass . (dcobject organization))
+			   (o . "example organization"))))
+
+(defparameter entry-two
+  (ldap:new-entry "cn=manager,dc=example,dc=com" 
+		  :attrs '((objectclass . organizationalrole))))
+
+(defparameter entry-three
+  (ldap:new-entry "cn=test user,dc=example,dc=com" 
+		  :attrs '((objectclass . organizationalrole))))
+
+(defparameter entry-four
+  (ldap:new-entry "cn=quuxor,dc=example,dc=com" 
+		  :attrs '((objectclass . (organizationalrole))
+			   (description . "another test entry")
+			   (l . ("Boston" "Cambridge" "Jamaica Plain"))
+			   (st . "Massachusetts")
+			   (postalcode . "02115")
+			   (street . "Commonwealth Avenue"))))
+
+
+; a printed representation:
+(format t "~A" (ldap:ldif entry-four))
+
+; turn on debugging.
+(setf (ldap:debugflag l) t)
+
+; bind to the server.
+(when (ldap:bind l)
+  (write-line "bound to ldap."))
+
+; turn off debugging.
+(setf (ldap:debugflag l) nil)
+
+; add a couple entries.
+(ldap:add entry-one l)
+
+; or use the lower-level add specified on ldap first:
+(multiple-value-bind (res code msg) (ldap:add l entry-two)
+  (format t "res: ~A~%code: ~A~%msg: ~A" res code msg))
+
+; search (and print results in ldif) 
+(ldap:ldif-search l "(cn=*)")
+
+; add another entry.
+(ldap:add entry-three l)
+
+; search for that.
+(if (ldap:search l (ldap:rdn entry-three))
+    (describe (ldap:next-search-result l))
+    (format t "Search Failed."))
+
+; delete an entry.  
+(ldap:delete entry-three l)
+
+; ldap:search will return nil.
+(ldap:search l (ldap:rdn entry-three))
+
+; a fourth entry.
+(ldap:add entry-four l)
+
+; this should be true.
+(ldap:compare entry-four l 'st "Massachusetts")
+
+; as should this, because the st attribute 
+; compares case insensitively.
+(ldap:compare entry-four l 'st 'massachusetts)
+
+; this is false, so it returns nil.
+(ldap:compare entry-four l 'st 'foobarbaz)
+
+; compare (and delete) take strings as well as entry objects.
+(ldap:compare (ldap:dn entry-four) l 'l 'boston)
+(ldap:delete (ldap:dn entry-four) l)
+
+; put entry four back:
+(ldap:add entry-four l)
+
+(ldap:attr-value entry-four 'st)
+(ldap:attr-list entry-four)
+(ldap:attrs entry-four)
+
+(ldap:modify entry-four l '((ldap:delete l "Boston")
+			    (ldap:replace st "Vermont")
+			    (ldap:add st "New Hampshire")
+			    (ldap:add street ("Massachusetts Avenue"
+					      "Newbury Street"
+					      "Boylston Street"))))
+
+(format t "~A~%" (ldap:ldif entry-four))
+
+
+(ldap:moddn entry-four l "cn=buzzer")
+
+; simple ldap filters work more or less as expected.  extended filters
+; however have not been implemented yet.
+(ldap:search l "(cn=buzz*)")
+(ldap:search l "(| (cn=baz*) (cn=*ager))")
+
+; the outside parens are optional:
+(ldap:search l "| (cn=baz*) (cn=*ager)")
+
+; clean up.  with one ldap object fetching the results of the search,
+; a second LDAP object is required for the delete.
+
+(defparameter j (ldap:new-ldap :host "great-pumpkin.local"
+			       :base "dc=example,dc=com"))
+
+; (ldap:dosearch (ent (ldap:search j "cn=*"))
+;   (ldap:delete ent l))
+;  
+; (ldap:delete entry-one l)
Index: /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.asd
===================================================================
--- /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.asd	(revision 13309)
+++ /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.asd	(revision 13309)
@@ -0,0 +1,8 @@
+(defpackage :trivial-ldap-system (:use #:cl #:asdf))
+(in-package :trivial-ldap-system)
+
+
+(defsystem :trivial-ldap
+  :version "0.91"
+  :components ((:file "trivial-ldap"))
+  :depends-on (usocket cl+ssl))
Index: /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.html
===================================================================
--- /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.html	(revision 13309)
+++ /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.html	(revision 13309)
@@ -0,0 +1,554 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- 
+(defun add-api-entry ()
+  (interactive)
+  (let ((function (read-string "Function/Method name: "))
+	(args (read-string "Argument list: "))
+	(type (read-string "Function, Method, or Macro? ")))
+    (insert (format "
+    <dt>
+      <span class=\"term\"><b>%s</b> <i>%s</i></span>
+      <span class=\"type\">[%s]</span>
+    </dt>
+    <br class=\"both\" />
+    <dd>
+    </dd>" function args type))
+    (previous-line 1)))
+-->
+
+
+<html>
+  <head>
+    <title>TRIVIAL-LDAP v0.91</title>
+
+    <style type="text/css">
+      .leftcontent {float: left; width: 75%; padding-left: 12px;}
+      div.head {background-color: #aeffee;}
+      span.term {float: left; text-align: left;}
+      span.type {float: right; text-align: right; font-weight: bold;}
+      br.both {clear: both;}
+      dd {font-style: normal; padding-bottom: 8px;}
+      
+    </style>
+  </head>
+
+  <body class="leftcontent">
+    <h3>TRIVIAL-LDAP v0.91</h3>
+
+    TRIVIAL-LDAP is a one file, all Common Lisp client implementation of
+    parts of RFC 2261.
+
+    <h4>WARNING:</h4> This is beta software.  While I believe the API
+    documented below is correct it is subject to change.  Also, <b>do
+    not run execute the example.lisp program against a production LDAP
+    directory, it will delete your entries.</b>  
+
+    <h4>Introduction</h4> This LDAP client came about as a result of
+    some functionality I required for a different project altogether.
+    As a result it provides functionality that is general enough but
+    probably not in typical low-level API fashion.  (For instance, a
+    "real" LDAP library would probably tackle the BER encoding
+    separately.)  However, as there is a lack of Common Lisp LDAP
+    clients out there I thought I'd share.  <p/>
+
+    I am open to both requests for features and suggestions for
+    improving my Lisp code.  There are features I will be implementing
+    in the short term but for the sake of not creating false
+    expectations neither a comprehensive list nor timeframe is
+    available. <p />
+
+    You can reach me at montuori@gmail.com.  
+
+  <h4>Changes</h4>
+    <dl>
+      <dt>2009-08-16 (v0.91)</dt>
+      <dd>Applied a patch supplied by Nick Dannenberg to fix UTF-8
+      handling for SBCL and CCL.  My sincerest appreciation for taking
+      the time to generate and send the patch along!</dd>
+
+      <dt>2009-03-12 (v0.90)</dt>
+      <dd>Applied patches kindly provided by Slawek Zak.
+	<ul>
+	  <li>Enable UTF-8 encoding for Allegro.</li>
+	  <li>Fixed a compilation failure on Allegro where a number
+	    of constants were not properly defined.</li>
+	  <li>Fixed the dosearch macro for cases where the LDAP 
+	    variable is lexical.</li>
+	</ul>
+	Thanks to Slawek for taking the time to send the patches!
+      </dd>
+
+
+      <dt>2007-01-12 (v0.80)</dt>
+      <dd><ul>
+	  
+	  <li>Converted from trivial-socket to usocket: indications
+	    were that trivial-socket has been deprecated.</li>
+
+	  <li>Added support for SSL with CL+SSL.  Setting the ldap
+	  object slot <code>sslflag</code> to T or
+	  the <code>port</code> slot to 636 will force an encrypted
+	  connection.  Do note that this is not TLS, just ldaps://
+	  ... I don't require TLS; if you do, drop me a line.</li>
+
+	  <li>Added functionality to ease the pain of short slapd
+	  idletimeouts.  The ldap object
+	  slot <code>reuse-connection</code> may be set to NIL (the
+	  default) to not attempt reopening connections, T to reopen
+	  the connection before each request, or TRIVIAL-LDAP:REBIND
+	  if the connection should be opened and a bind message sent
+	  before each request (except, of course, the bind request
+	    itself).  </li>
+
+	  <li>A couple of documentation and logic bugs were corrected</li>
+	</ul></dd>
+
+    </dl>
+<p>
+    
+  <h4>Acknowledgments</h4> I would like to thank Zach Beane for his
+  many helpful comments and suggestions.  Thanks also to Ed Symanzik
+  for pointing out a number inconsistencies in the code and
+  documentation.  
+<p>
+  Also, a nod to my client, Brandeis University, for not fretting too
+  much when I break out emacs + slime to administrate their LDAP
+  directories.
+<p>
+    <h4>License</h4> TRIVIAL-LDAP is distributed under the Clarified
+    Artistic License, a copy of which is included in the downloadable
+    package.  
+
+    <h4>Requirements</h4> TRIVIAL-LDAP has been tested under OpenMCL 1.0
+    (OS X/PPC), SBCL 0.9.7 (OS X/PPC), and SBCL 1.0 (OS X/Intel).
+<p>
+    I would assume any CL that is supported by usockets and CL+SSL
+    would have no issues with this code.  If you encounter problems
+    let me know.
+
+    <p/>Two external packages, usocket and CL+SSL, are required.
+    CL+SSL itself requires trivial-gray-streams, flexi-streams, and
+    cffi.  These may be downloaded from:
+
+   <ul>
+     <li><a href="http://common-lisp.net/project/usocket/">
+	 http://common-lisp.net/project/usocket/</a></li>
+
+     <li><a href="http://common-lisp.net/project/cl-plus-ssl/">
+	 http://common-lisp.net/project/cl-plus-ssl/</a></li>
+
+     <li><a href="http://common-lisp.net/project/cffi/">
+	 http://common-lisp.net/project/cffi/</a></li>
+
+     <li><a href="http://weitz.de/flexi-streams/">
+	 http://weitz.de/flexi-streams/</a></li>
+   </ul>
+
+   The trivial-gray-streams project is part of the CL+SSL project.
+   (Note: to get CL+SSL working on OS X/Intel it was necessary to
+   re-compile openssl with the -m64 flag.)
+
+<p>
+
+    <h4>Limitations</h4>
+    
+    Missing functionality, as specified by RFC 2251,  includes:
+    
+    <ul>
+      <li>UTF-8 is not implemented for all CL implementations</li>
+      <li>SASL authentication is not implemented</li>
+      <li>controls are not implemented</li>
+      <li>extended DN searches are not implemented</li>
+      <li>referrals are not followed</li>
+      <li>extended request/response is not implemented</li>
+    </ul>
+    
+    I do not require this functionality myself, but if there was
+    interest I would consider augmenting TRIVIAL-LDAP with some of
+    this missing functionality.
+
+    <p/>
+      
+    <h4>API</h4>
+    <dl>
+<p><b>LDAP object and associated methods.</b></p>
+
+      <dt>
+	<span class="term"><b>new-ldap</b> <i>&key (host "localhost")
+	(port 389) user pass base debug</i></span> <span
+	class="type">[function]</span>
+      </dt>
+    <br class="both" />
+    <dd>Return an LDAP object.</dd>
+    
+    <dt>
+      <span class="term"><b>host</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the host slot value of
+    ldap-object.  Slot value will be a string.</dd>
+
+    <dt>
+      <span class="term"><b>port</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the port slot value of
+    ldap-object.  Slot value will be an integer.  If the sslflag slot
+    is NIL, defaults to 389; if sslflag slot is T, defaults to 636.
+    If the port parameter is manually set to 636 an SSL connection is
+    used unless the sslflag is explicitly set to nil.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>user</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the user DN to bind as.  Slot
+    value will be a string.
+    </dd>
+  
+
+    <dt>
+      <span class="term"><b>pass</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the simple password to bind with.
+    Slot value will be a string.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>base</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the default base DN for searches.
+    Slot value will be a string.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>debug</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> 
+
+    <dd>Get/set the debug flag.  Slot value will be T or NIL.  When
+    value is T debug output will be written to *debug-io*.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>sslflag</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Get/set the SSL flag.  When T the default port is 636 and a
+    CL+SSL stream is used.  Defaults to nil.  Note that if the port
+    slot is explicitly set to 636 an SSL connection is used unless the
+    sslflag slot is set to nil explicitly.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>reuse-connection</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Get/set the reuse-connection slot parameter.  When T re-open
+    the stream before each reqest; when LDAP:REBIND open the stream
+    and send an (ldap:bind ldap-object) message; when nil, don't do
+    anything special.  Set to NIL by default.
+    </dd>
+
+<p><b>Entry object and associated methods</b></p>
+
+    <dt>
+      <span class="term"><b>new-entry</b> <i>dn &key (attrs ())
+      (infer-rdn t)</i></span> <span class="type">[function]</span>
+    </dt>
+    <br class="both" /> 
+
+    <dd>Return a new entry object with the DN specified.
+    <code>attrs</code>, if specified, will be an alist of
+    attribute/value pairs.  If <code>infer-rdn</code> is T the RDN
+    attribute and value will be appended to the attribute list.
+    </dd>
+
+    
+    <dt>
+      <span class="term"><b>dn</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Return the DN value for entry-object.  
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>rdn</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Return the RDN value for entry-object
+    </dd>    
+
+    <dt>
+      <span class="term"><b>change-rdn</b> <i>entry-object
+      new-rdn</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Change the RDN (and therefore DN) of an
+    entry-object.  The RDN attribute and value will be updated in the
+    attribute list.  No LDAP directory transactions will take place.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>attr-list</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Return the list of attribute symbols
+    belonging to entry-object
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>attr-value</b> <i>entry-object
+      attr</i></span> <span class="type">[method]</span>
+     <br class="both" />
+     <span class="term"><b>attr-value</b> <i>entry-object
+      attr-list</i></span> <span class="type">[method]</span>
+   
+    </dt>
+    <br class="both" /> <dd>Return a list of values associated with
+    the attribute <code>attr</code>.  Return NIL if the attribute does
+    not exist.  If a list of attributes is passed, return a list of
+    lists of values.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>add-attr</b> <i>entry-object attr
+      values</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Add the specified attribute with the value
+    or values specified to the entry object's attribute list.  Returns
+    the entire list of attributes/values.  No LDAP directory transactions
+    will take place.
+    </dd>
+
+    
+    <dt>
+      <span class="term"><b>del-attr</b> <i>entry-object attr
+      &optional values</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Delete the specified attribute (or values
+    for attribute) from the entry object's attribute list.  Returns
+    the entire list of attributes/values.  No LDAP directory
+    transactions will take place.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>replace-attr</b> <i>entry-object attribute
+      values</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Replace current attribute values with
+    values specified.  Returns the entire list of attributes/values.
+    No LDAP directory transactions will take place.
+    </dd>
+
+
+
+    <dt>
+      <span class="term"><b>ldif</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Return an LDIF representation of entry (as a string).
+    </dd>
+
+
+
+<p><b>LDAP Commands</b></p>
+<p>
+<b>NB:</b> Methods below that are specialized first on ldap-object will
+return three values: T/NIL indicating success or failure, the LDAP
+response code (these are exported from the TRIVIAL-LDAP package as
+symbols), and third, any response message received from the LDAP
+directory server (as a string).
+</p>
+<p>
+Methods specialized first on entry-object will return T (or T/NIL
+in the case of compare) and will throw an ldap-response-error if a
+response from the LDAP directory server is other than succesful.
+</p>
+<p>
+<i>dn-or-entry</i> can be either an entry-object or a DN string.
+<i>dn</i> is a string.  Generally if the method only requires the DN
+either the entry or the DN will be acceptable arguments.
+</p>
+
+
+
+    <dt>
+      <span class="term"><b>bind</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Send a bind request to the LDAP directory server.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>unbind</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Send an unbind request to the LDAP
+    directory server and close the stream.
+    </dd>
+
+<dt>
+      <span class="term"><b>abandon</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Send an abandon request to the LDAP
+    directory server and purge any data on the stream waiting to be
+    read.  </dd>
+
+
+    <dt>
+      <span class="term"><b>add</b> <i>ldap-object entry-object</i></span>
+      <span class="type">[method]</span>
+    <br class="both" /> 
+      <span class="term"><b>add</b> <i>entry-object ldap-object</i></span>
+    </dt>
+    <br class="both" /> <dd>Add an entry described by entry-object to
+    the directory specified by ldap-object.
+    </dd>
+
+
+
+    <dt>
+      <span class="term"><b>delete</b> <i>ldap-object
+      dn-or-entry</i></span> <span class="type">[method]</span>
+     <br class="both" />
+      <span class="term"><b>delete</b> <i>entry-object
+      ldap-object</i></span> 
+     <br class="both" />
+      <span class="term"><b>delete</b> <i>dn ldap-object</i></span>
+
+    </dt>
+    <br class="both" /> <dd>Delete entry from directory specified by
+    ldap-object.  <code>dn-or-entry</code> may be an entry object or a
+    DN string.  
+    </dd>
+
+    <dt>
+      <span class="term"><b>moddn</b> <i>ldap-object dn-or-entry
+      new-rdn &key delete-old new-sup</i></span> <span
+      class="type">[method]</span>
+    <br class="both" />
+      <span class="term"><b>moddn</b> <i>entry-object ldap-object
+      new-rdn &key delete-old new-sup</i></span> 
+    <br class="both" />
+      <span class="term"><b>moddn</b> <i>dn ldap-object new-rdn &key
+      delete-old new-sup</i></span> 
+    </dt>
+    <br class="both" /> <dd>Modify the RDN specified by
+    <code>dn-or-entry</code> to the replacement RDN
+    <code>new-rdn</code>.  <code>dn-or-entry</code> may be either an
+    entry object or DN string.  If an object is specified, the DN and
+    attribute associated with the RDN slot values are modified as well
+    as the directory specified by ldap-object.
+    </dd>
+ 
+    <dt>
+      <span class="term"><b>compare</b> <i>ldap-object dn-or-entry
+      attribute value</i></span> <span class="type">[method]</span>
+      <br class="both" /> <span class="term"><b>compare</b>
+      <i>entry-object ldap-object attribute value</i>
+    </dt>
+    <br class="both" /> <dd>Send a compare message to the directory
+    server asserting that entry-obj (or DN) has an attribute
+    <code>attribute</code> with a value <code>value</code>.  Returns
+    either T or NIL (as the only argument or as the first argument)
+    indicating a return code of compareTrue or compareFalse.  
+    </dd>
+
+
+
+    <dt>
+      <span class="term"><b>modify</b> <i>ldap-object dn-or-entry
+      list-of-mods</i></span> <span class="type">[method]</span>
+    <br class="both" />
+      <span class="term"><b>modify</b> <i>entry-object ldap-object
+      list-of-mods</i></span> 
+    </dt>
+    <br class="both" /> <dd>Modify the entry specified by
+    <code>dn-or-entry</code> or <code>entry-object</code>.
+    <code>list-of-mods</code> is a list of (type attribute value)
+    triples.  Type will be one of ldap:add, ldap:delete, or
+    ldap:replace.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>search</b> <i>ldap-object filter &key base
+      (scope 'sub) (deref 'never) (size-limit 0) (time-limit 0)
+      types-only attributes</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Search the directory specified by
+    ldap-object.  <code>filter</code> is an LDAP filter (as a string).
+    The outer parens on the filter are optional.  The search base
+    defaults to the base slot-value of the ldap-object.  This method
+    returns T or NIL, indicating results pending or not, respectively.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>next-search-result</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>After an ldap:search is executed, this
+    method can be used to return each of the entry objects that search
+    resulted in.  next-search-result will return NIL if no more
+    results are available.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>dosearch</b> <i>var search-form &body
+      body</i></span> <span class="type">[macro]</span>
+    </dt>
+    <br class="both" /> <dd>Execute the ldap:search provided as
+    <code>search-form</code> and iterate through the results binding
+    each resulting entry object to <code>var</code> before evaluating
+    <code>body.</code> Returns the number of entries processed.
+    <b>NB: </b>If the body of the loop involves LDAP transactions it
+    is probably best that a difference LDAP instance be employed.
+
+    </dd>
+
+    <dt>
+      <span class="term"><b>ldif-search</b> <i>&rest
+      ldap-search-args</i></span> <span class="type">[macro]</span>
+    </dt>
+    <br class="both" /> <dd>Prints the results of a search in LDIF.
+    This macro is probably most useful in an interactive setting.
+    <code>ldap-search-args</code> are passed directly to the search
+    method described above.
+    </dd>
+
+</dl>
+
+
+    <hr>
+    <address><a href="mailto:montuori@gmail.com">kevin montuori</a></address>
+<!-- Created: Sun Jan 22 14:36:42 EST 2006 -->
+<!-- hhmts start -->
+Last modified: Sat Jan 13 09:01:44 EST 2007
+<!-- hhmts end -->
+  </body>
+</html>
Index: /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.lisp
===================================================================
--- /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.lisp	(revision 13309)
+++ /branches/new-random/contrib/montuori/trivial-ldap/trivial-ldap.lisp	(revision 13309)
@@ -0,0 +1,1281 @@
+;;;; TRIVIAL-LDAP v0.91 -- a one file, all lisp client implementation of
+;;;; parts of RFC 2261.  
+
+;;;; Please see the trivial-ldap.html file for documentation and limitations.
+
+;;;; Updates are available at:
+;;;;    http://homepage.mac.com/ignavusinfo/trivial-ldap/
+
+;;;; TRIVIAL-LDAP is Copyright 2005-2009 Kevin Montuori and is 
+;;;; distributed under The Clarified Artistic License, a copy of which
+;;;; should have accompanied this file.
+
+;;;; Kevin Montuori <montuori@gmail.com>
+
+(defpackage :trivial-ldap
+    (:use :cl-user :common-lisp :usocket)
+  (:nicknames :ldap)
+  (:shadow :delete :search)
+  (:export
+   ; mod types.
+   delete replace add 
+   ; search option symbols
+   base sub one never search find always
+   ; objects.
+   entry ldap
+   ; methods.
+   #:user #:pass #:base #:debugflag #:host #:port #:rdn #:dn #:attrs #:compare
+   #:sslflag #:reuse-connection #:rebind
+   #:bind #:unbind #:abandon #:add #:delete #:moddn #:search 
+   #:new-entry-from-list #:replace-attr #:del-attr #:add-attr #:modify
+   #:attr-list #:attr-value #:new-entry #:new-ldap #:ldif #:change-rdn
+   #:response #:results-pending-p #:next-search-result
+   ; convenience macros
+   #:dosearch #:ldif-search))
+	   
+(in-package :trivial-ldap)
+
+;;;;
+;;;; error conditions
+;;;;
+
+(define-condition ldap-error ()
+  ((note :initarg :mesg
+	 :reader mesg
+	 :initform "LDAP transaction resulted in an error."))
+  (:report (lambda (c stream)
+	     (format stream "~A~%" (mesg c)))))
+
+(define-condition ldap-filter-error (ldap-error)
+  ((filter :initarg :filter
+	   :reader filter
+	   :initform "Not Supplied"))
+  (:report (lambda (c stream)
+	     (format stream "Filter Error: ~A~%Supplied Filter: ~A~%" 
+		     (mesg c) (filter c)))))
+
+(define-condition ldap-connection-error (ldap-error)
+  ((host :initarg :host
+	 :reader  host)
+   (port :initarg :port
+	 :reader port))
+  (:report (lambda (c stream)
+	     (format stream "LDAP Connection Error: ~A~%Host:Port: ~A:~A~%"
+		     (mesg c) (host c) (port c)))))
+
+(define-condition ldap-response-error (ldap-error)
+    ((dn   :initarg :dn
+	   :reader dn
+	   :initform "DN not available.")
+     (code :initarg :code
+	   :reader code
+	   :initform "Result code not available")
+     (msg  :initarg :msg
+	   :reader msg
+	   :initform "N/A"))
+    (:report (lambda (c stream)
+	       (format stream "~A~%DN: ~A~%Code: ~A~%Message: ~A~%"
+		       (mesg c) (dn c) (code c) (msg c)))))
+
+;;;;
+;;;; utility functions
+;;;;
+
+
+;; to appease sbcl (see http://tinyurl.com/auqmr):
+(defmacro define-constant (name value &optional doc)
+  `(defconstant ,name (if (boundp ',name) (symbol-value ',name) ,value)
+    ,@(when doc (list doc))))
+
+(defparameter *hex-print* "~A~%~{~<~%~1,76:;~2,'0,,X~> ~}~%"
+  "Format directive to print a list of line wrapped hex numbers.")
+
+(defun base10->base256 (int)
+  "Return representation of an integer as a list of base 256 'digits'."
+  (assert (and (integerp int) (>= int 0)))
+  (or 
+   (do ((i 0 (+ i 8))
+	(j int (ash j -8))
+	(result nil (cons (logand #xFF j) result)))
+       ((> i (1- (integer-length int))) result))
+   (list 0)))
+
+(defun base256->base10 (list)
+  "Given a list of base 256 'digits' return an integer."
+  (assert (consp list))
+  (let ((len (length list)))
+    (do ((i 0 (1+ i))
+	 (j (- len 1) (1- j))
+	 (int 0 (dpb (pop list) (byte 8 (* 8 j)) int)))
+	((= i len) int))))
+
+(defun int->octet-list (int)
+  "Return 2s comp. representation of INT."
+   (assert (integerp int))
+   (do ((i 0 (+ i 8))
+	(j int (ash j -8))
+	(result nil (cons (logand #xFF j) result)))
+       ((> i (integer-length int)) result)))
+
+(defun octet-list->int (octet-list)
+  "Convert sequence of twos-complement octets into an integer."
+  (assert (consp octet-list))
+  (let ((int 0))
+    (dolist (value octet-list int) (setq int (+ (ash int 8) value)))))
+
+(defun string->char-code-list (string)
+  "Convert a string into a list of bytes."
+   (let ((string (etypecase string 
+ 		  (string string)
+ 		  (symbol (symbol-name string)))))
+     #-(or allegro ccl sbcl)
+     (map 'list #'char-code string)
+     #+ccl
+     (coerce 
+      (ccl::encode-string-to-octets string :external-format :utf-8) 'list)
+     #+sbcl
+     (coerce (sb-ext:string-to-octets string :external-format :utf-8) 'list)
+     #+allegro
+     (coerce (excl:string-to-octets string :null-terminate nil) 'list)))
+
+(defun char-code-list->string (char-code-list)
+  "Convert a list of bytes into a string."
+  (assert (or (null char-code-list) (consp char-code-list)))
+  #-(or allegro ccl sbcl)
+  (map 'string #'code-char char-code-list)
+  #+ccl
+  (ccl::decode-string-from-octets (make-array (list (length char-code-list))
+					      :element-type '(unsigned-byte 8)
+					      :initial-contents char-code-list)
+				  :external-format :utf-8)
+  #+sbcl
+  (sb-ext:octets-to-string (make-array (list (length char-code-list))
+				       :element-type '(unsigned-byte 8)
+				       :initial-contents char-code-list)
+			   :external-format :utf-8)
+  #+allegro
+  (excl:octets-to-string (make-array (list (length char-code-list))
+				     :element-type '(unsigned-byte 8)
+				     :initial-contents char-code-list)
+			 :external-format :utf8))
+
+(defun filter-string->sexp (filter)
+  "Convert a filter-string into a sexp."
+  (unless (and (char= #\( (char filter 0))
+ 	       (char= #\) (char filter (1- (length filter)))))
+    (setf filter (format nil "(~A)" filter)))
+  (unless (balanced-parentheses-p filter)
+    (error 'ldap-filter-error :mesg "unbalanced parentheses" :filter filter))
+  (let ((*package* (find-package :ldap)))
+    (read-from-string (rearrange-filter (quote-verticals filter)) nil nil)))
+
+(defun quote-verticals (string)
+  "Backslash quote the character | (for filter strings)"
+  (with-output-to-string (stream)
+			 (loop for char across string do
+			       (when (char= char #\|) (write-char #\\ stream))
+			       (write-char char stream))))
+
+(defun balanced-parentheses-p (string)
+  (let ((level 0))
+    (dotimes (i (length string) (zerop level))
+      (case (char string i)
+	(#\( (incf level))
+	(#\) (if (zerop level) (return nil) (decf level)))))))
+  
+(defun rearrange-filter (string &optional (beg 0))
+  "Prepare a filter to be (read)."
+  (let ((pos (position #\= string :start beg)))
+    (if pos
+	(flet ((trim (x) (string-trim '(#\Space) x)))
+	  (let* ((opening-paren (position #\( string :from-end t :end pos))
+		 (closing-paren (position #\) string :start pos))
+		 (prev (char string (1- pos)))
+		 (next (char string (1+ pos)))
+		 (op-bounds 
+		  (cond
+		    ((or (eql #\~ prev) (eql #\< prev) (eql #\> prev)) 
+		     (list (1- pos) (1+ pos)))
+		    ((eql #\* next) (list pos (+ 2 pos)))
+		    (t (list pos (1+ pos)))))
+		 (op  (subseq string (first op-bounds) (second op-bounds)))
+		 (att (trim (subseq string (1+ opening-paren) 
+				    (first op-bounds))))
+		 (val (trim (subseq string (second op-bounds) closing-paren)))
+		 (pre-part (subseq string 0 (1+ opening-paren)))
+		 (post-part (subseq string closing-paren)))
+	    (unless (attribute-p att)
+	      (error 'ldap-filter-error
+		     :mesg (format nil "invalid attribute in filter: '~A'" att)
+		     :filter string))
+	    (when (and (string= op "=*") (not (string= val "")))
+	      (setf op "=" val (format nil "*~A" val)))
+	    (let ((this-part (format nil "~A ~A |~A|" op att val)))
+	      (rearrange-filter 
+	       (format nil "~A~A~A" pre-part this-part post-part)
+	       (+ (length pre-part) (length this-part))))))
+	string)))
+
+(defun split-substring (string &optional list)
+  "Split a substring filter value into a list, retaining the * separators."
+  (let ((pos (position #\* string)))
+    (if pos
+	(let* ((capture (subseq string 0 pos))
+	       (vals (if (string= capture "") (list "*") (list "*" capture))))
+	  (split-substring (subseq string (1+ pos))(append vals list)))
+	(nreverse (if (string= string "") list (push string list))))))
+
+;;;;
+;;;; BER encoding constants and constructors.
+;;;;
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (define-constant +max-int+ (- (expt 2 31) 1)
+    "As defined by the LDAP RFC.")
+  
+  (define-constant +ber-class-id+
+      '((universal   . #b00000000) (application . #b01000000)
+	(context     . #b10000000) (private     . #b11000000)))
+  
+  (define-constant +ber-p/c-bit+
+      '((primitive   . #b00000000) (constructed . #b00100000)))
+  
+  (define-constant +ber-multibyte-tag-number+ #b00011111
+    "Flag indicating tag number requires > 1 byte")
+  
+  (define-constant +ber-long-length-marker+   #b10000000
+    "Flag indicating more tag number bytes follow")
+  
+  (defun ber-class-id (class)
+    "Return the bits to construct a BER tag of type class."
+    (or (cdr (assoc class +ber-class-id+))
+	(error "Attempted to retrieve a non-existent BER class.")))
+
+  (defun ber-p/c-bit (p/c)
+    "Return the bit to construct a BER tag of class primitive or constructed."
+    (or (cdr (assoc p/c +ber-p/c-bit+))
+	(error "Attempted to retrieve a non-existent p/c bit.")))
+
+  (defun ber-tag-type (class p/c)
+    "Construct the bits that kicks off a BER tag byte."
+    (+ (ber-class-id class) (ber-p/c-bit p/c)))
+
+  (defun ber-tag (class p/c number-or-command)
+    "Construct the list of bytes that constitute a BER tag number 0-127.
+CLASS should be the symbol universal, applicaiton, context, or private.
+P/C should be the symbol primitive or constructed.
+NUMBER should be either an integer or LDAP application name as symbol."
+    (let ((byte (ber-tag-type class p/c))
+	  (number (etypecase number-or-command 
+		    (integer number-or-command)
+		    (symbol (ldap-command number-or-command)))))
+      (cond 
+	((< number 31)  (list (+ byte number)))
+	((< number 128) (list (+ byte +ber-multibyte-tag-number+) number))
+	(t (error "Length of tag exceeds maximum bounds (0-127).")))))
+
+  (defun ber-length (it)
+    "Given a sequence or integer, return a BER length."
+    (let ((length (etypecase it
+		    (sequence (length it))
+		    (integer it))))
+      (cond
+	((< length 128) (list length))
+	((< length +max-int+)
+	 (let ((output (base10->base256 length)))
+	   (append (list (+ (length output) +ber-long-length-marker+)) 
+		   output)))
+	(t (error "Length exceeds maximum bounds")))))
+
+  (defun ber-msg (tag data)
+    "Given a BER tag and a sequence of data, return a message"
+    (let ((len (ber-length data)))
+      (append tag len data))))
+
+
+;;;;
+;;;; LDAP constants and accessors
+;;;;
+
+(define-constant +ldap-version+     #x03 "LDAP version 3.")
+(define-constant +ldap-port-no-ssl+ 389  "Default LDAP Port.")
+(define-constant +ldap-port-ssl+    636  "Default LDAPS Port.")
+
+(define-constant +ldap-disconnection-response+ "1.3.6.1.4.1.1466.20036"
+  "OID of the unsolicited disconnection reponse.")
+  
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (define-constant +ldap-application-names+
+    '((BindRequest           . 0)
+      (BindResponse          . 1)
+      (UnbindRequest         . 2)
+      (SearchRequest	     . 3)
+      (SearchResultEntry     . 4)
+      (SearchResultReference . 19)
+      (SearchResultDone      . 5)
+      (ModifyRequest         . 6)
+      (ModifyResponse        . 7)
+      (AddRequest            . 8)
+      (AddResponse           . 9)
+      (DelRequest            . 10)
+      (DelResponse           . 11)
+      (ModifyDNRequest       . 12)
+      (ModifyDNResponse      . 13)
+      (CompareRequest        . 14)
+      (CompareResponse       . 15)
+      (AbandonRequest        . 16)
+      (ExtendedRequest       . 23)
+      (ExtendedResponse      . 24)))
+  
+  (defun ldap-command (command)
+    "Given a symbol naming an ldap command, return the command number."
+    (cdr (assoc command +ldap-application-names+)))
+  
+  (defun ldap-command-sym (number)
+    "Given an application number, return the command name as symbol."
+    (car (rassoc number +ldap-application-names+)))
+  
+  (define-constant +ldap-result-codes+
+      '((0  . (success			 "Success"))
+	(1  . (operationsError		 "Operations Error"))
+	(2  . (protocolError		 "Protocol Error"))
+	(3  . (timeLimitExceeded	 "Time Limit Exceeded"))
+	(4  . (sizeLimitExceeded	 "Size Limit Exceeded"))
+	(5  . (compareFalse		 "Compare False"))
+	(6  . (compareTrue		 "Compare True"))
+	(7  . (authMethodNotSupported	 "Auth Method Not Supported"))
+	(8  . (strongAuthRequired	 "Strong Auth Required"))
+	(10 . (referral			 "Referral"))
+	(11 . (adminLimitExceeded	 "Admin Limit Exceeded"))
+	(12 . (unavailableCriticalExtension "Unavailable Critical Extension"))
+	(13 . (confidentialityRequired	 "Confidentiality Required"))
+	(14 . (saslBindInProgress	 "SASL Bind In Progress"))
+	(16 . (noSuchAttribute		 "No Such Attribute"))
+	(17 . (undefinedAttributeType	 "Undefined Attribute Type"))
+	(18 . (inappropriateMatching	 "Inappropriate Matching"))
+	(19 . (constraintViolation	 "Constraint Violation"))
+	(20 . (attributeOrValueExists	 "Attribute Or Value Exists"))
+	(21 . (invalidAttributeSyntax	 "Invalid Attribute Syntax"))
+	(32 . (noSuchObject		 "No Such Object"))
+	(33 . (aliasProblem		 "Alias Problem"))
+	(34 . (invalidDNSyntax		 "Invalid DN Syntax"))
+	(36 . (aliasDereferencingProblem    "Alias Dereferencing Problem"))
+	(48 . (inappropriateAuthentication  "Inappropriate Authentication"))
+	(49 . (invalidCredentials	 "Invalid Credentials"))
+	(50 . (insufficientAccessRights	 "Insufficient Access Rights"))
+	(51 . (busy			 "Busy"))
+	(52 . (unavailable		 "Unavailable"))
+	(53 . (unwillingToPerform	 "Unwilling To Perform"))
+	(54 . (loopDetect		 "Loop Detect"))
+	(64 . (namingViolation		 "Naming Violation"))
+	(65 . (objectClassViolation	 "Object Class Violation"))
+	(66 . (notAllowedOnLeaf		 "Not Allowed On Leaf"))
+	(67 . (notAllowedOnRDN		 "Not Allowed On RDN"))
+	(68 . (entryAlreadyExists	 "Entry Already Exists"))
+	(69 . (objectClassModsProhibited "Object Class Mods Prohibited"))
+	(71 . (affectsMultipleDSAs	 "Affects Multiple DSAs"))
+	(80 . (other			 "Other"))))
+
+  ; export the result code symbols.
+  (dolist (i +ldap-result-codes+) (export (second i) :ldap)))
+
+(defun ldap-result-code-string (code)
+  (second (cdr (assoc code +ldap-result-codes+))))
+
+(defun ldap-result-code-symbol (code)
+  (first (cdr (assoc code +ldap-result-codes+))))
+
+
+(define-constant +ldap-scope+ 
+  '((base . 0)
+    (one  . 1)
+    (sub  . 2)))
+
+(define-constant +ldap-deref+
+  '((never  . 0)
+    (search . 1)
+    (find   . 2)
+    (always . 3)))
+
+(define-constant +ldap-modify-type+
+  '((add . 0)
+    (delete . 1)
+    (replace . 2)))
+
+(define-constant +ldap-filter-comparison-char+
+  '((&  . 0)
+    (\| . 1)
+    (!  . 2)
+    (=  . 3)
+    (>= . 5)
+    (<= . 6)
+    (=* . 7)
+    (~= . 8)
+    (substring . 4)))
+
+(define-constant +ldap-substring+
+  '((initial . 0)
+    (any     . 1)
+    (final   . 2)))
+
+(defun ldap-scope (&optional (scope 'sub))
+  "Given a scope symbol return the enumeration int."
+    (cdr (assoc scope +ldap-scope+)))
+
+(defun ldap-deref (&optional (deref 'never))
+  "Given a deref symbol return the enumeration int."
+  (cdr (assoc deref +ldap-deref+)))
+
+(defun ldap-modify-type (type)
+  "Given a modify type, return the enumeration int."
+  (cdr (assoc type +ldap-modify-type+)))
+	
+(defun ldap-filter-comparison-char (comparison-char-as-symbol)
+  "Given a comparison character, return its integer enum value."
+  (cdr (assoc comparison-char-as-symbol +ldap-filter-comparison-char+)))
+    
+(defun ldap-substring (type)
+  "Given a substring type, return its integer choice value."
+  (cdr (assoc type +ldap-substring+)))
+
+(defun attribute-p (attribute)
+  "Return T if string/symb is legal as an attribute, nil otherwise."
+  (let ((string (etypecase attribute 
+		  (string attribute)
+		  (symbol (symbol-name attribute)))))
+    (let ((bad-char-count 
+	   (count-if-not #'(lambda (x) 
+			     (or
+			      (and (char>= x #\0) (char<= x #\9))
+			      (and (char>= x #\A) (char<= x #\Z))
+			      (and (char>= x #\a) (char<= x #\z))
+			      (char= x #\;)
+			      (char= x #\-))) string)))
+      (if (= 0 bad-char-count) (intern (string-upcase string)) nil))))
+
+;;;;
+;;;; BER sequence creators.
+;;;;
+
+;;; writers.
+(define-constant +ber-bind-tag+ 
+  (ber-tag 'application 'constructed 'bindrequest))
+(define-constant +ber-add-tag+  
+  (ber-tag 'application 'constructed 'addrequest))
+(define-constant +ber-del-tag+  
+  (ber-tag 'application 'primitive 'delrequest))
+(define-constant +ber-moddn-tag+  
+  (ber-tag 'application 'constructed 'modifydnrequest))
+(define-constant +ber-comp-tag+ 
+  (ber-tag 'application 'constructed 'comparerequest))
+(define-constant +ber-search-tag+
+  (ber-tag 'application 'constructed 'searchrequest))
+(define-constant +ber-abandon-tag+
+  (ber-tag 'application 'primitive 'abandonrequest))
+(define-constant +ber-unbind-tag+
+  (ber-tag 'application 'primitive 'unbindrequest))
+(define-constant +ber-modify-tag+
+  (ber-tag 'application 'constructed 'modifyrequest))
+
+;;;; readers.
+(define-constant +ber-tag-extendedresponse+
+    (car (ber-tag 'application 'constructed 'extendedresponse)))
+(define-constant +ber-tag-ext-name+  
+    (car (ber-tag 'context 'primitive 10)))
+(define-constant +ber-tag-ext-val+ 
+    (car (ber-tag 'context 'primitive 11)))
+(define-constant +ber-tag-bool+ 
+    (car (ber-tag 'universal 'primitive #x01)))
+(define-constant +ber-tag-int+ 
+    (car (ber-tag 'universal 'primitive #x02)))
+(define-constant +ber-tag-enum+ 
+    (car(ber-tag 'universal 'primitive #x0A)))
+(define-constant +ber-tag-str+ 
+    (car (ber-tag 'universal 'primitive #x04)))
+(define-constant +ber-tag-seq+ 
+    (car (ber-tag 'universal 'constructed #x10)))
+(define-constant +ber-tag-set+ 
+    (car (ber-tag 'universal 'constructed #x11)))
+
+(defun seq-null ()
+  "BER encode a NULL"
+  (append (ber-tag 'universal 'primitive #x05) (ber-length 0)))
+
+(defun seq-boolean (t/f)
+  "BER encode a boolean value."
+  (let ((value (cond ((eql t/f t)   #xFF)
+		     ((eql t/f nil) #x00)
+		     (t (error "Unknown boolean value.")))))
+    (nconc (ber-tag 'universal 'primitive #x01) (ber-length 1) (list value))))
+
+(defun seq-integer (int)
+  "BER encode an integer value."
+  (assert (integerp int))
+  (let ((bytes (int->octet-list int)))
+    (nconc (ber-tag 'universal 'primitive #x02) (ber-length bytes) bytes)))
+
+(defun seq-enumerated (int)
+  "BER encode an enumeration value."
+  (assert (integerp int))
+  (let ((bytes (int->octet-list int)))
+    (nconc (ber-tag 'universal 'primitive #x0A) (ber-length bytes) bytes)))
+
+(defun seq-octet-string (string)
+  "BER encode an octet string value."
+  (let ((bytes (seq-primitive-string string)))
+    (nconc (ber-tag 'universal 'primitive #x04) (ber-length bytes) bytes)))
+
+(defun seq-sequence (tlv-seq)
+  "BER encode a sequence of TLVs."
+  (assert (or (null tlv-seq) (consp tlv-seq)))
+  (nconc (ber-tag 'universal 'constructed #x10) (ber-length tlv-seq) tlv-seq))
+
+(defun seq-set (tlv-set)
+  "BER encode a set of TLVs."
+  (assert (consp tlv-set))
+  (nconc (ber-tag 'universal 'constructed #x11) (ber-length tlv-set) tlv-set))
+
+(defun seq-primitive-choice (int &optional data)
+  "BER encode a context-specific choice."
+  (assert (integerp int))
+  (let ((tag (ber-tag 'context 'primitive int)))
+    (etypecase data
+      (null (append tag (list #x00)))
+      (string  (if (string= data "") 
+		   (append tag (list #x00))
+		   (append tag (ber-length data) 
+			   (string->char-code-list data))))
+      (integer (seq-integer data))
+      (boolean (seq-boolean data))
+      (symbol  (let ((str (symbol-name data)))
+		 (append tag (ber-length str) 
+			 (string->char-code-list str)))))))
+
+(defun seq-constructed-choice (int &optional data)
+  "BER encode a context-specific, constructed choice."
+  (assert (integerp int))
+  (let ((tag (ber-tag 'context 'constructed int)))
+    (etypecase data
+      (string (let* ((val (seq-octet-string data))
+		     (len (ber-length val)))
+		(append tag len val)))
+      (sequence (let ((len (ber-length data)))
+		  (append tag len data))))))
+		     
+(defun seq-primitive-string (string)
+  "BER encode a string/symbol for use in a primitive context."
+  (assert (or (stringp string) (symbolp string)))
+  (string->char-code-list string))
+
+(defun seq-attribute-alist (atts)
+  "BER encode an entry object's attribute alist (for use in add)."
+  (seq-sequence (mapcan #'(lambda (i) 
+			    (seq-att-and-values (car i) (cdr i))) atts)))
+    
+(defun seq-attribute-list (att-list)
+  "BER encode a list of attributes (for use in search)."
+  (seq-sequence (mapcan #'seq-octet-string att-list)))
+
+(defun seq-attribute-assertion (att val)
+  "BER encode an ldap attribute assertion (for use in compare)."
+  (seq-sequence (nconc (seq-octet-string att) (seq-octet-string val))))
+  
+(defun seq-attribute-value-assertion (att val)
+  "BER encode an ldap attribute value assertion (for use in filters)."
+  (nconc (seq-octet-string att) (seq-octet-string val)))
+
+(defun seq-att-and-values (att vals)
+  "BER encode an attribute and set of values (for use in modify)."
+  (unless (listp vals) (setf vals (list vals)))
+  (seq-sequence (nconc (seq-octet-string att) 
+		       (seq-set (mapcan #'seq-octet-string vals)))))
+
+(defun seq-filter (filter)
+  (let* ((filter (etypecase filter
+		   (cons   filter)
+		   (symbol filter)
+		   (string (filter-string->sexp filter))))
+	 (op  (car filter))
+	 (sub (if (and (eq '= op)
+		       (> (count #\* (symbol-name (third filter))) 0)) t nil)))
+    (cond
+      ((eq '! op) (seq-constructed-choice (ldap-filter-comparison-char op)
+					  (seq-filter (cadr filter))))
+      ((or (eq '&  op) (eq '\| op))
+       (seq-constructed-choice (ldap-filter-comparison-char op)
+			       (mapcan #'seq-filter (cdr filter))))
+      ((or (and (eq '= op) (not sub))
+	   (eq '<= op) (eq '>= op) (eq '~= op))
+       (seq-constructed-choice (ldap-filter-comparison-char op) 
+			       (seq-attribute-value-assertion
+				(second filter) (third filter))))
+      ((eq '=* op) (seq-primitive-choice 
+		    (ldap-filter-comparison-char op) (second filter)))
+      ((and (eq '= op) sub)
+       (seq-constructed-choice (ldap-filter-comparison-char 'substring)
+			       (append (seq-octet-string (second filter))
+				       (seq-substrings (third filter)))))
+      (t (error 'ldap-filter-error 
+		:mesg "unable to determine operator." :filter filter)))))
+
+
+(defun seq-substrings (value)
+  "Given a search value with *s in it, return a BER encoded list."
+  (let ((list (etypecase value 
+		  (symbol (split-substring (symbol-name value)))
+		  (string (split-substring value))))
+	(initial ()) (any ()) (final ()))
+    (when (string/= "*" (car list))   ; initial
+      (setf initial (seq-primitive-choice (ldap-substring 'initial)
+					  (car list))))
+    (setf list (cdr list))            ; last
+    (when (and (> (length list) 0) (string/= "*" (car (last list))))
+      (setf final (seq-primitive-choice (ldap-substring 'final)
+					(car (last list)))))
+    (setf list (butlast list))
+    (when (> (length list) 0)         ; any
+      (dolist (i (remove "*" list :test #'string=))
+	(setf any (append any (seq-primitive-choice 
+			       (ldap-substring 'any) i)))))
+    (seq-sequence (nconc initial any final))))
+
+(defun valid-ldap-response-p (tag-byte)
+  "Return T if this is the valid initial tag byte for an LDAP response."
+  (if (= tag-byte (car (ber-tag 'universal 'constructed #x10))) t nil))
+
+
+;;;;
+;;;; referrer class & methods.
+;;;;
+
+(defclass referrer ()
+  ((url :initarg :url 
+	:initform (error "No URL specified")
+	:type string
+	:accessor url)))
+
+(defun new-referrer (url)
+  "Instantiate a new referrer object."
+  (make-instance 'referrer :url url))
+
+;;;;
+;;;; entry class & methods.
+;;;;
+
+(defclass entry ()
+  ((dn    :initarg :dn     :type string  :accessor dn)
+   (rdn   :initarg :rdn    :type string  :accessor rdn)
+   (attrs :initarg :attrs  :type cons    :accessor attrs)))
+
+(defmethod dn ((dn string)) dn)
+
+(defun rdn-from-dn (dn)
+  "Given a DN, return its RDN and a cons of (att . val)"
+  (let* ((eql-pos (position #\= dn))
+	 (rdn (subseq dn 0 (position #\, dn)))
+	 (rdn-att (subseq rdn 0 eql-pos))
+	 (rdn-val (subseq rdn (1+ eql-pos) (length rdn))))
+    (values rdn (list (intern (string-upcase rdn-att)) rdn-val))))
+
+(defun new-entry (dn &key (attrs ()) (infer-rdn t))
+  "Instantiate a new entry object."
+  (multiple-value-bind (rdn rdn-list) (rdn-from-dn dn)
+   (when (and infer-rdn
+	      (not (assoc (car rdn-list) attrs)))
+     (setf attrs (acons (car rdn-list) (cdr rdn-list) attrs)))
+   (make-instance 'entry :dn dn :rdn rdn :attrs attrs)))
+
+(defmethod change-rdn ((entry entry) new-rdn)
+  "Change the DN and RDN of the specified object, don't touch LDAP."
+  (let* ((len-old (length (rdn entry)))
+	 (dn (concatenate 'string new-rdn (subseq (dn entry) len-old))))
+    (multiple-value-bind (old-rdn old-rdn-parts) (rdn-from-dn (dn entry))
+      (declare (ignore old-rdn))
+      (del-attr entry (first old-rdn-parts) (second old-rdn-parts)))
+    (setf (dn entry) dn  
+	  (rdn entry) new-rdn)
+    (multiple-value-bind (new-rdn new-rdn-parts) (rdn-from-dn (dn entry))
+      (declare (ignore new-rdn))
+      (add-attr entry (first new-rdn-parts) (second new-rdn-parts)))))
+
+(defmethod attr-value ((entry entry) attr)
+  "Given an entry object and attr name (symbol), return list of values."
+  (let ((val (cdr (assoc attr (attrs entry)))))
+    (cond 
+      ((null val) nil)
+      ((consp val) val)
+      (t (list val)))))
+
+(defmethod attr-value ((entry entry) (attrs list))
+  "Given an entry object and list of attr names (as symbols), 
+return list of lists of attributes."
+  (mapcar #'(lambda (attr) (attr-value entry attr)) attrs))
+
+(defmethod attr-list ((entry entry))
+  "Given an entry object, return a list of its attributes."
+  (map 'list #'car (attrs entry)))
+
+(defmethod add-attr ((entry entry) attr vals)
+  "Add an attribute to entry object, do not update LDAP."
+  (let ((old-val-list (attr-value entry attr))
+	(new-val-list (if (consp vals) vals (list vals))))
+    (replace-attr entry attr (append old-val-list new-val-list))))
+
+(defmethod del-attr ((entry entry) attr &optional vals)
+  "Delete an attribute from entry object, do not update LDAP"
+  (let ((old-val (attr-value entry attr))
+	(new-val (if (consp vals) vals (list vals))))
+    (dolist (val new-val)
+      (setf old-val (remove-if #'(lambda (x) (string= val x)) old-val)))
+    (if (or (null (car old-val))
+	    (null (car new-val)))
+	(setf (attrs entry) 
+	      (remove-if #'(lambda (x) (eq (car x) attr)) (attrs entry)))
+	(replace-attr entry attr old-val))))
+	      
+(defmethod replace-attr ((entry entry) attr vals)
+  "Replace attribute values from entry object, do not update LDAP"
+  (let ((vals (remove-if #'null vals)))
+    (if (consp (assoc attr (attrs entry)))
+	(rplacd (assoc attr (attrs entry)) vals)
+	(setf (attrs entry) (acons attr vals (attrs entry))))))
+
+(defmethod ldif ((entry entry))
+  "Return an ldif formatted representation of entry."
+  (let ((results (format nil "DN: ~A~%" (dn entry))))
+    (dolist (att (attr-list entry) results)
+      (dolist (val (attr-value entry att))
+	(setf results (format nil "~@[~A~]~A: ~A~%" results att val))))))
+
+(defun new-entry-from-list (list)
+  "Create an entry object from the list return by search."
+  (let ((dn (car list))
+	(attrs (mapcar #'(lambda (x) (cons (intern (string-upcase (car x)))
+					   (cadr x)))
+		       (cadr list))))
+    (new-entry dn :attrs attrs)))
+
+;;;;
+;;;; LDAP class & methods
+;;;;
+
+(defclass ldap () 
+  ((host   :initarg :host 
+	   :initform "localhost"
+	   :type string 
+	   :accessor host)
+   (port   :initarg :port 
+	   :initform +ldap-port-no-ssl+
+	   :type integer 
+	   :accessor port)
+   (sslflag :initarg :sslflag
+	    :initform nil
+	    :type symbol
+	    :accessor sslflag)
+   (user   :initarg :user 
+	   :initform ""
+	   :type string 
+	   :accessor user)
+   (pass   :initarg :pass 
+	   :initform ""
+	   :type string 
+	   :accessor pass)
+   (ldapstream :initarg :ldapstream  
+	   :initform nil 
+	   :type (or null stream) 
+	   :accessor ldapstream)
+   (ldapsock :initarg :ldapsock
+	   :initform nil 
+	   :accessor ldapsock)
+   (reuse-connection :initarg :reuse-connection
+		     :initform t
+		     :type symbol
+		     :documentation "nil, t, or bind"
+		     :accessor reuse-connection)
+   (mesg   :initarg :mesg 
+	   :initform 0 
+	   :type integer 
+	   :accessor mesg)
+   (debugflag  :initarg :debugflag
+	       :initform nil 
+	       :type symbol 
+	       :accessor debugflag)
+   (base   :initarg :base 
+	   :initform nil 
+	   :type (or null string) 
+	   :accessor base)
+   (response :initarg :response
+	     :initform ()
+	     :type list
+	     :accessor response)
+   (entry-buffer :initarg :entry-buffer
+		 :initform nil
+		 :accessor entry-buffer)
+   (results-pending-p :initarg :results-pending-p
+		      :initform nil
+		      :type (boolean)
+		      :accessor results-pending-p)))
+   
+
+(defun new-ldap (&key (host "localhost") (sslflag nil)
+		 (port (if sslflag +ldap-port-ssl+ +ldap-port-no-ssl+))
+		 (user "") (pass "") (base nil) (debug nil)
+		 (reuse-connection nil))
+  "Instantiate a new ldap object."
+  (make-instance 'ldap :host host :port port :user user :sslflag sslflag
+		 :pass pass :debugflag debug :base base 
+		 :reuse-connection reuse-connection))
+
+(defmethod debug-mesg ((ldap ldap)  message)
+  "If debugging in T, print a message."
+  (when (debugflag ldap) (format *debug-io* "~A~%" message)))
+
+(defmethod mesg-incf ((ldap ldap)) (incf (mesg ldap)))
+
+(defmethod get-stream ((ldap ldap))
+  "Open a usocket to the ldap server and set the ldap object's slot.
+If the port number is 636 or the SSLflag is not null, the stream
+will be made with CL+SSL."
+  (let ((existing-stream (ldapstream ldap)))
+    (unless (and (streamp existing-stream) 
+		 (open-stream-p existing-stream))
+      (let* ((sock (usocket:socket-connect (host ldap) (port ldap)
+					   :element-type '(unsigned-byte 8)))
+	     (stream 
+	      (if (or (sslflag ldap) (= (port ldap) 636))
+		  (cl+ssl:make-ssl-client-stream (usocket:socket-stream sock))
+		  (usocket:socket-stream sock))))
+	(debug-mesg ldap "Opening socket and stream.")
+	(setf (ldapsock ldap) sock)
+	(setf (ldapstream ldap) stream))))
+    (ldapstream ldap))
+
+(defmethod close-stream ((ldap ldap))
+  "Close an ldap connection if it is currently open."
+  (let ((existing-stream (ldapstream ldap))
+	(existing-sock (ldapsock ldap)))
+    (when (and (streamp existing-stream) (open-stream-p existing-stream))
+      (ignore-errors
+	(setf (ldapstream ldap) nil)
+	(setf (ldapsock ldap) nil)
+	(close existing-stream)
+	(usocket:socket-close existing-sock)))))
+
+(defmethod possibly-reopen-and-rebind ((ldap ldap) 
+				       &optional (absolutely-no-bind nil))
+  "Take appropriate reopen or rebind actions based on the reuse-connection attr.
+If the attribute is nil, do nothing; if t, reopen; and, if bind, rebind.
+This function exists to help the poor saps (read: me) with very fast idletimeout
+settings on their LDAP servers."
+  (debug-mesg ldap "reusing connection...")
+  (let (stream)
+    (when (reuse-connection ldap) 
+      (close-stream ldap)
+      (setf stream (get-stream ldap)))
+    (when (and (not absolutely-no-bind)
+	       (eq (reuse-connection ldap) 'rebind))
+      (debug-mesg ldap "rebinding...")
+      (bind ldap))
+    stream))
+  
+(defmethod send-message ((ldap ldap) message &optional (response-expected t))
+  "Send a BER encoded message to ldap."
+  (let ((mesg (seq-sequence (append (seq-integer (mesg-incf ldap)) message)))
+	(stream (get-stream ldap)))
+    (debug-mesg ldap (format nil *hex-print* "To LDAP: " mesg))
+    (dolist (byte mesg) (write-byte byte stream))
+    (handler-case (finish-output stream)
+      (error (e) (error 'ldap-connection-error
+			:host (host ldap) :port (port ldap) :mesg e)))
+    (when response-expected (setf (results-pending-p ldap) t))))
+
+(defmethod receive-length ((ldap ldap))
+  "Read length of LDAP message from stream, return length & the bytes read."
+  (let* ((stream (ldapstream ldap))
+	 (length-byte (read-byte stream))
+	 (byte-seq ())
+	 (byte-len (- length-byte 128))
+	 (length-of-message
+	  (cond
+	    ((< length-byte 128) length-byte)
+	    (t (dotimes (i byte-len) (push (read-byte stream) byte-seq))
+	       (base256->base10 (reverse byte-seq)))))
+	 (all-bytes-consumed (append (list length-byte) (nreverse byte-seq))))
+    (values length-of-message all-bytes-consumed)))
+
+(defmethod receive-message ((ldap ldap))
+  "Read incoming LDAP data from the stream, populate LDAP response slot.
+The initial tag and length of message bytes will have been consumed already
+and will not appear in the response.  Note that this method is executed
+only for its side effects."
+  (let* (ber-response 
+	 (stream (get-stream ldap))
+	 (initial-byte (read-byte stream)))
+    (unless (or (null initial-byte) (valid-ldap-response-p initial-byte))
+      (error "Received unparsable data from LDAP server."))
+    (multiple-value-bind (message-length bytes-read) (receive-length ldap)
+      (dotimes (i message-length) (push (read-byte stream) ber-response))
+      (setf (response ldap) (nreverse ber-response))
+      (debug-mesg ldap (format nil *hex-print* "From LDAP:"
+			       (append (list initial-byte) bytes-read 
+				       (response ldap)))))
+    (let ((response-minus-message-number 
+	   (check-message-number (response ldap) (mesg ldap))))
+      (cond
+	((null response-minus-message-number) (receive-message ldap))
+	(t (setf (response ldap) response-minus-message-number))))))
+  
+(defmethod handle-extended-response ((ldap ldap) content)
+  "Process an extended response.
+Currently this means closing the connection if it is a disconnect request
+and throw an error if it's anything else."
+  (if (string= (fourth content) +ldap-disconnection-response+)
+      (close-stream ldap)
+      (error 'ldap-error 
+	     :mesg (format nil "Received unhandled extended response: ~A~%"
+			   content))))
+
+(defmethod parse-ldap-message ((ldap ldap) &optional (return-entry nil))
+  "Parse an ldap object's response slot."
+  (let ((received-content ()))
+    (multiple-value-bind (content appname) (read-decoder (response ldap))
+      (cond
+	((eq appname 'searchresultentry)
+	 (let ((new-entry (new-entry-from-list content)))
+	   (cond
+	     ((null return-entry)
+	      (setf (entry-buffer ldap) new-entry)
+	      (setf received-content t))
+	     (t (setf received-content new-entry)))))
+	((eq appname 'searchresultreference))
+	((eq appname 'searchresultdone)
+	 (setf (results-pending-p ldap) nil)
+	 (setf received-content nil))
+	((eq appname 'extendedresponse) 
+	 (handle-extended-response ldap content)
+	 (push content received-content)
+	 (setf (results-pending-p ldap) nil))
+	(t 
+	 (push content received-content)
+	 (setf (results-pending-p ldap) nil))))
+    received-content))
+	
+(defmethod process-message ((ldap ldap) message &key (success 'success))
+  "Send a simple request to LDAP and return three values:
+T or NIL, the LDAP response code (as a readable string), and any message
+the directory server returned."
+  (let ((bind-p (equal (msg-bind ldap) message)))
+    (possibly-reopen-and-rebind ldap bind-p))
+  (send-message ldap message)
+  (receive-message ldap)
+  (let* ((results (car (parse-ldap-message ldap)))
+	 (code (car results))
+	 (msg (third results))
+	 (code-sym (ldap-result-code-symbol code))
+	 (rc (if (eq code-sym success) t nil)))
+    (values rc code-sym msg)))
+
+;;;;  
+;;;; ldap user-level commands.
+;;;;
+
+(defmethod bind ((ldap ldap))
+  "Send a BindRequest."
+  (process-message ldap (msg-bind ldap)))
+
+(defmethod unbind ((ldap ldap))
+  "Unbind and close the ldap stream."
+  (send-message ldap (msg-unbind) nil)
+  (setf (mesg ldap) 0)
+  (close-stream ldap))
+
+(defmethod abandon ((ldap ldap))
+  "Abandon the request and suck any data off the incoming stream.
+Because the receive-message will keep receiving messages until it gets
+one with the correct message number, no action needs to be taken here to 
+clear the incoming data off the line.  It's unclear that's the best 
+solution, but (clear-input) doesn't actually work and trying to read non-
+existent bytes blocks..."
+  (send-message ldap (msg-abandon ldap) nil))
+
+
+(defmethod add ((ldap ldap) (entry entry))
+  "Add an entry to the directory."
+  (process-message ldap (msg-add entry)))
+
+(defmethod add ((entry entry) (ldap ldap))
+  "Add an entry object to LDAP; error unless successful."
+  (multiple-value-bind (res code msg) (add ldap entry)
+    (or res (error 'ldap-response-error 
+		   :mesg "Cannot add entry to LDAP directory."
+		   :dn (dn entry) :code code :msg msg))))
+
+(defmethod delete ((ldap ldap) dn-or-entry)
+  "Delete an entry (or DN) from the directory."
+  (process-message ldap (msg-delete dn-or-entry)))
+
+(defmethod delete ((entry entry) (ldap ldap))
+  "Delete an entry object from ldap; error unless successful."
+  (delete (dn entry) ldap))
+
+(defmethod delete ((dn string) (ldap ldap))
+  "Delete an entry from LDAP; error unless successful."
+  (multiple-value-bind (res code msg) (delete ldap dn)
+    (or res (error 'ldap-response-error
+		   :mesg "Cannot delete entry from LDAP directory."
+		   :dn dn :code code :msg msg))))
+
+(defmethod moddn ((ldap ldap) dn-or-entry new-rdn &key delete-old new-sup)
+  "Modify an entry's RDN."
+  (process-message ldap (msg-moddn dn-or-entry new-rdn delete-old new-sup)))
+
+(defmethod moddn ((entry entry) (ldap ldap) new-rdn &key delete-old new-sup)
+  "Modify the RDN of an LDAP entry; update the entry object as well."
+  (when (moddn (dn entry) ldap new-rdn :delete-old delete-old :new-sup new-sup)
+    (change-rdn entry new-rdn)))
+
+(defmethod moddn ((dn string) (ldap ldap) new-rdn &key delete-old new-sup)
+  "Modify the RDN of an LDAP entry."
+  (multiple-value-bind (res code msg)
+      (moddn ldap dn new-rdn :delete-old delete-old :new-sup new-sup)
+    (or res (error 'ldap-response-error 
+		   :mesg "Cannot modify RDN in the LDAP directory."
+		   :dn dn :code code :msg msg))))
+
+(defmethod compare ((ldap ldap) dn-or-entry attribute value)
+  "Assert DN has attribute with specified value."
+  (process-message ldap (msg-compare dn-or-entry attribute value)
+		   :success 'comparetrue))
+
+(defmethod compare ((entry entry) (ldap ldap) attribute value)
+  "Assert an entry has an att=val; return t or nil, or throw error."
+  (compare (dn entry) ldap attribute value))
+
+(defmethod compare ((dn string) (ldap ldap) attribute value)
+  "Compare entry's att/val; calle by both entry/compare methods."
+  (multiple-value-bind (res code msg) (compare ldap dn attribute value)
+    (declare (ignore res))
+    (cond ((eq code 'comparetrue) t)
+	  ((eq code 'comparefalse) nil)
+	  (t (error 'ldap-response-error
+		    :mesg "Cannot compare entry's attribute/value."
+		    :dn dn :code code :msg msg)))))
+
+(defmethod modify ((ldap ldap) dn-or-entry list-of-mods)
+  "Modify and entry's attributes."
+  (process-message ldap (msg-modify dn-or-entry list-of-mods)))
+
+(defmethod modify ((entry entry) (ldap ldap) list-of-mods)
+  "Modify entry attributes in ldap, update the entry object.
+LIST-OF-MODS is a list of (type att val) triples."
+  (multiple-value-bind (res code msg) (modify ldap entry list-of-mods)
+    (when (null res) 
+      (error 'ldap-response-error
+	     :mesg "Cannot modify entry in the LDAP directory."
+	     :dn (dn entry) :code code :msg msg))
+    ; succeeded, so modify the entry.
+    (dolist (i list-of-mods t)
+      (cond
+	((eq (car i) 'delete) (del-attr entry (second i) (third i)))
+	((eq (car i) 'add) (add-attr entry (second i) (third i)))
+	(t (replace-attr entry (second i) (third i)))))))
+
+(defmethod search ((ldap ldap) filter &key base (scope 'sub) 
+		   (deref 'never) (size-limit 0) (time-limit 0) 
+		   types-only attributes)
+  "Search the LDAP directory."
+  (let ((base (if (null base) (base ldap) base))
+	(scope (ldap-scope scope))
+	(deref (ldap-deref deref)))
+    (possibly-reopen-and-rebind ldap)
+    (send-message ldap (msg-search filter base scope deref size-limit 
+				   time-limit types-only attributes))
+    (receive-message ldap)
+    (parse-ldap-message ldap)))
+
+(defmethod next-search-result ((ldap ldap))
+  "Return the next search result (as entry obj) or NIL if none."
+  (if (results-pending-p ldap)
+      (let ((pending-entry (entry-buffer ldap)))
+	(cond 
+	  ((not (null pending-entry))
+	   (setf (entry-buffer ldap) nil)
+	   pending-entry)
+	  (t (receive-message ldap)
+	     (parse-ldap-message ldap t))))
+      nil))
+
+(defmacro dosearch ((var search-form) &body body)
+  (let ((ldap (gensym))
+ 	(count (gensym)))
+    `(let ((,ldap ,(second search-form))
+ 	   (,count 0))
+      ,search-form
+      (do ((,var (next-search-result ,ldap) 
+ 		 (next-search-result ,ldap)))
+ 	  ((null ,var))
+ 	(incf ,count)
+ 	,@body)
+      ,count)))
+
+(defmacro ldif-search (&rest search-parameters)
+  (let ((ent (gensym)))
+    `(dosearch (,ent (search ,@search-parameters))
+      (format t "~A~%" (ldif ,ent)))))
+
+;;;;
+;;;; ldap message constructors.
+;;;;
+
+(defmethod msg-bind ((ldap ldap))
+  "Return the sequence of bytes representing a bind message."
+  (let ((req (append (seq-integer +ldap-version+)
+		     (seq-octet-string (user ldap))
+		     (seq-primitive-choice 0 (pass ldap)))))
+    (ber-msg +ber-bind-tag+ req)))
+
+(defmethod msg-unbind ()
+  (ber-msg +ber-unbind-tag+ (seq-null)))
+
+(defmethod msg-abandon ((ldap ldap))
+  "Return the sequence of bytes representing an abandon message"
+  (let ((last-message-number (seq-integer (mesg ldap))))
+    (ber-msg +ber-abandon-tag+ last-message-number)))
+
+(defmethod msg-add ((entry entry))
+  "Return the sequence of bytes representing an add message."
+  (let ((dn (seq-octet-string (dn entry)))
+	(att (seq-attribute-alist (attrs entry))))
+    (ber-msg +ber-add-tag+ (append dn att))))
+
+(defun msg-delete (dn-or-entry)
+  "Return the sequence of bytes representing a delete message."
+  (let ((dn (seq-primitive-string (dn dn-or-entry))))
+    (ber-msg +ber-del-tag+ dn)))
+	
+(defun msg-moddn (dn-or-entry new-rdn delete-old new-sup)
+  "Return the sequence of bytes representing a moddn message."
+  (let ((dn  (seq-octet-string (dn dn-or-entry)))
+	(rdn (seq-octet-string new-rdn))
+	(del (seq-boolean delete-old))
+	(new-sup (if new-sup (seq-octet-string new-sup) nil)))
+    (ber-msg +ber-moddn-tag+ (append dn rdn del new-sup))))
+
+(defun msg-compare (dn-or-entry attribute value)
+  "Return the sequence of bytes representing a compare message."
+  (let ((dn (seq-octet-string (dn dn-or-entry)))
+	(assertion (seq-attribute-assertion attribute value)))
+    (ber-msg +ber-comp-tag+ (append dn assertion))))
+
+(defun msg-modify (dn-or-entry mod-list)
+  "Return the sequence of bytes representing a modify message."
+  (let ((dn (seq-octet-string (dn dn-or-entry)))
+	(mods 
+	 (mapcan #'(lambda (x) (seq-sequence 
+				(nconc
+				 (seq-enumerated (ldap-modify-type (first x)))
+				 (seq-att-and-values (second x) (third x)))))
+		 mod-list)))
+    (ber-msg +ber-modify-tag+ (append dn (seq-sequence mods)))))
+
+(defun msg-search (filter base scope deref size time types attrs)
+  "Return the sequence of bytes representing a search message."
+  (let ((filter (seq-filter filter))
+	(base   (seq-octet-string base))
+	(scope  (seq-enumerated scope))
+	(deref  (seq-enumerated deref))
+	(size   (seq-integer size))
+	(time   (seq-integer time))
+	(types  (seq-boolean types))
+	(attrs  (seq-attribute-list attrs)))
+    (ber-msg +ber-search-tag+ 
+	     (append base scope deref size time types filter attrs))))
+
+;;;;
+;;;; sequence reader & decoder functions
+;;;;
+
+(defun read-decoder (response)
+  "Decode a BER encoded response (minus initial byte & length) from LDAP."
+  (let ((appname (ldap-command-sym (read-app-number (pop response)))))
+    (multiple-value-bind (size bytes) (read-length response)
+      (declare (ignore size)) 
+      (setf response (subseq response bytes)))
+    (values (read-generic response) appname)))
+
+(defun read-generic (message &optional (res ()))
+  (if (and (consp message) (> (length message) 0))
+      (progn
+	(let* ((tag-byte (car message))
+	       (fn (cond
+		     ((= tag-byte +ber-tag-int+)  #'read-integer)
+		     ((= tag-byte +ber-tag-enum+) #'read-integer)
+		     ((= tag-byte +ber-tag-str+)  #'read-string)
+		     ((= tag-byte +ber-tag-ext-name+) #'read-string)
+		     ((= tag-byte +ber-tag-ext-val+)  #'read-string)
+		     (t nil))))
+	  (cond 
+	    ((functionp fn)                                   ; primitive.
+	     (multiple-value-bind (val bytes) (funcall fn message)
+	       (push val res)
+	       (setf message (subseq message bytes))))
+	    ((or (= tag-byte +ber-tag-set+)                   ; constructed.
+		 (= tag-byte +ber-tag-seq+)
+		 (= tag-byte +ber-tag-extendedresponse+))
+	     (multiple-value-bind (length bytes) 
+		 (read-length (subseq message 1))
+	       (let* ((start-of-data (+ 1 bytes)) ; tag + bytes
+		      (end-of-data   (+ start-of-data length)))
+		 (push (read-generic 
+			(subseq message start-of-data end-of-data)) res)
+		 (setf message (subseq message end-of-data)))))
+	    (t (error 'ldap-error :mesg "Unreadable tag value encountered.")))
+	  (read-generic message res)))
+      (nreverse res)))
+
+(define-constant +ber-app-const-base+
+  (car (ber-tag 'application 'constructed 0)))
+
+(defun read-app-number (tag)
+  "Given an application tag, return which ldap app number it represents."
+  (- (etypecase tag
+       (integer tag)
+       (cons (car tag))) +ber-app-const-base+))
+
+(defun read-integer (message)
+  "Read an int from the message, return int and number of bytes consumed."
+  (values (octet-list->int (subseq message 2 (+ 2 (second message))))
+	  (+ 2 (second message))))
+
+(defun read-string (message)
+  "Read a string from the message, return string and bytes consumed.."
+  (pop message) ; lose the tag.
+  (multiple-value-bind (len bytes) (read-length message)
+    (values (char-code-list->string 
+	     (subseq message bytes (+ len bytes))) (+ 1 bytes len))))
+
+(defun read-length (message)
+  "Given message starting with length marker, return length and bytes consumed"
+  (cond
+    ((< (car message) 128) (values (car message) 1))
+    (t (let ((bytes (+ 1 (- (car message) 128))))
+	 (values (base256->base10 (subseq message 1 bytes)) bytes)))))
+
+(defun read-message-number (response expected-mesg-number)
+  "Read message number from the seq, return t or nil and bytes consumed."
+  (multiple-value-bind (value bytes) (read-integer response)
+    (let ((result (if (or (= value 0) ; 0 is unsolicited notification.
+			  (= value expected-mesg-number))
+		      t ; msg number matches up
+		      nil)))
+      (values result bytes))))
+
+(defun check-message-number (response expected-mesg-number)
+  "Determine if the  message number of a BER response is correct.
+Returns BER response with message number bytes consumed if it is correct
+or NIL otherwise."
+  (multiple-value-bind (mesg-ok? bytes)
+      (read-message-number response expected-mesg-number)
+    (if mesg-ok? (subseq response bytes) nil)))
+
+;;; trivial-ldap.lisp ends here.
Index: /branches/new-random/contrib/paine/workpersistence.lisp
===================================================================
--- /branches/new-random/contrib/paine/workpersistence.lisp	(revision 13309)
+++ /branches/new-random/contrib/paine/workpersistence.lisp	(revision 13309)
@@ -0,0 +1,113 @@
+(in-package :cl-user)
+
+;;; Clozure CL Hemlock editor windows persistence
+;;; ie. on restart of CCL re-open (and position) the last session's open files.
+;;;
+;;; LLGPL Copyright (c) Peter Paine 20080611 
+;;; Maintainer: gmail: p2.edoc 
+;;; To use: add (require :workpersistence) to your home:ccl-init.lisp file,
+;;          or (load ~this-file~)
+;;; Updates 
+;;; 20091018: restore original window order
+;;;           option to save independently per platform and CLZ-version
+;;; 20090906: fix not saving closed windows, fix resizing in gui thread, save in home dir.
+;;; 20090928: re-select Listener
+;;; ToDo: 
+;;;   - how to read window from buffer (without external search via path)?
+;;;   - if on quit, an unsaved buffers prompt, remember-hemlock-files not called (or doesn't save)
+;;;   - multiple choice menu of buffers to save
+;;;   - add auto backup process: auto save modified files as file name variant, check/restore on restart 
+
+#-(and clozure-common-lisp hemlock) (error "Workpersistence only runs under CLZ ~
+                                           Hemlock Nextstep/Cocoa API")
+
+;; Allows separation of working file sets for different platform versions.
+(defvar *separate-ccl-working-file-sets-by-platform-p* T)
+
+;; Independently save working file sets by major/minor version of CLZ.
+(defvar *separate-ccl-working-file-sets-by-ccl-version-p* nil)
+
+(defun work-persistence-file (&optional version)
+  (setq version (if version (format nil "-~A" version) ""))
+  (let ((ccl-version
+         (if *separate-ccl-working-file-sets-by-ccl-version-p*
+           (format nil "-~D-~D" ccl::*openmcl-major-version* ccl::*openmcl-minor-version*)
+           "")))
+  (if *separate-ccl-working-file-sets-by-platform-p*
+    (format nil "home:.ccl-workpersistence-~A~A~A.text" (ccl::platform-description) ccl-version version)
+    (format nil "home:.ccl-workpersistence~A~A.text" ccl-version version))))
+
+(defvar *work-persistence-file* (work-persistence-file) "per user")
+;; (ed *work-persistence-file*)
+
+(defun copy-work-persistence ()
+  (when (probe-file *work-persistence-file*)
+    (copy-file *work-persistence-file* (work-persistence-file "copy") :if-exists :overwrite)))
+;; (ed (work-persistence-file "copy"))
+
+(defun remember-hemlock-files ()
+  (with-open-file (*standard-output*
+                   *work-persistence-file*
+                   :direction :output :if-exists :supersede)
+    (loop for buffer in (hi::all-buffers)
+      do (let* ((path (hi:buffer-pathname buffer)))
+           (when path 
+             (let ((frame (slot-value (find-file-buffer-window path) 'ns:_frame)))
+               (loop initially (format T "~&(")
+                 for fn in '(ns:ns-rect-x ns:ns-rect-y ns:ns-rect-width ns:ns-rect-height)
+                 do (format T "~5D " (floor (funcall fn frame)))
+                 finally (format T "~S)" path))))))))
+
+(defun find-file-buffer-window (path)
+   (loop with win-arr = (#/orderedWindows ccl::*NSApp*)
+     for i below (#/count win-arr)
+     for win = (#/objectAtIndex: win-arr i)
+     when (and (typep win '(and gui::hemlock-frame
+                                (not gui::hemlock-listener-frame)))
+               (equalp path (hi:buffer-pathname (hi:hemlock-view-buffer
+                                                 (gui::hemlock-view win)))))
+     return win))
+
+(defun find-listener () ; there must be a standard way to do this
+  ;; only saves first listener found
+  (loop with win-arr = (#/orderedWindows ccl::*NSApp*)
+    for i below (#/count win-arr)
+    for win = (#/objectAtIndex: win-arr i)
+    when (typep win 'gui::hemlock-listener-frame)
+    return win))
+
+(defun select-listener ()
+  (process-wait "Wait for Listener" 'find-listener)
+  (let ((listener (find-listener)))
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     listener (objc:@selector "makeKeyAndOrderFront:") nil nil)))
+
+(defun open-remembered-hemlock-files ()
+  (let (old-file-specs)
+    (with-open-file (buffer-persistence-stream
+                     *work-persistence-file*
+                     :direction :input :if-does-not-exist nil)
+      (when buffer-persistence-stream ;; reverse order
+        (loop for item = (read buffer-persistence-stream nil)
+                while item do (push item old-file-specs))))
+    (gui::execute-in-gui 
+     #'(lambda () 
+         (dolist (old-file-spec old-file-specs)
+           (destructuring-bind (posx posy width height path) old-file-spec
+             (when (probe-file path)
+               (gui::find-or-make-hemlock-view path)
+               (let ((window (find-file-buffer-window path))) ; round about way*
+                 ;;* how to get from hemlock-view
+                 (when window
+                   ;; should check whether coords are still in screen bounds
+                   ;; (could have changed screen realestate since)
+                   (let ((rect (ns:make-ns-rect posx posy width height)))
+                     (#/setFrame:display: window rect t)))))))
+         (select-listener)))))
+    
+         
+(pushnew 'remember-hemlock-files *lisp-cleanup-functions*)
+(pushnew 'open-remembered-hemlock-files *lisp-startup-functions*)
+
+;; (remember-hemlock-files)
+(open-remembered-hemlock-files)
Index: /branches/new-random/contrib/perryman/finger.lisp
===================================================================
--- /branches/new-random/contrib/perryman/finger.lisp	(revision 13309)
+++ /branches/new-random/contrib/perryman/finger.lisp	(revision 13309)
@@ -0,0 +1,180 @@
+;;;; -*- mode: lisp -*-
+;;;; Copyright (C) 2002-2003 Barry Perryman.
+;;;; 
+;;;; finger.lisp
+;;;; A simple finger client and server as specified by RFC 1288.
+;;;;
+;;;; Anyone who wants to use this code for any purpose is free to do so.
+;;;; In doing so, the user acknowledges that this code is provided "as is",
+;;;; without warranty of any kind, and that no other party is legally or
+;;;; otherwise responsible for any consequences of its use.
+;;;;
+;;;; Changes:
+;;;; 2003-xx-xx: General tidy up of code, especially the interface to the
+;;;;             server. Add some error handling. Update copyright.
+;;;;             Remove package.
+;;;; 2002-07-15: New processes are optional. The system can now forward on
+;;;;             nested queries onto other servers, which can be a security
+;;;;             risk, so by default this is not enabled.
+;;;;
+
+(defconstant +input-buffer-size+ 1024
+  "Size of the input buffer used by read-sequence.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Start off with a couple of utility functions
+(defun write-net-line (line stream)
+  "Write out the string line to the stream, terminating with CRLF."
+  (format stream "~a~c~c" line #\return #\linefeed))
+
+(defun read-net-line (stream)
+  "Read a line from stream."
+  (let ((line (make-array 10 :element-type 'character :adjustable t :fill-pointer 0)))
+    (do ((c (read-char stream nil nil) (read-char stream nil nil)))
+	((or (null c)
+	     (and (char= c #\return)
+		  (char= (peek-char nil stream nil nil) #\linefeed)))
+	 (progn
+	   (read-char stream nil nil)
+	   line))
+      (vector-push-extend c line))))
+
+(defmacro aif (test yes no)
+  `(let ((it ,test))
+    (if it
+	,yes
+	,no)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Finger client
+(defun %finger (host query port)
+  "Send query to host:port using the finger protocol, RFC 1288. Returns the output as a string."
+  (declare (ignore verbose))
+  (with-open-socket (net :remote-host host :remote-port port)
+    (write-net-line query net)
+    (force-output net)			; Doesn't seem to be needed, but just incase
+    (let ((inbuf (make-array +input-buffer-size+ :element-type 'character :initial-element #\space)))
+      (do* ((pos (read-sequence inbuf net) (read-sequence inbuf net))
+	    (output (subseq inbuf 0 pos) (concatenate 'string output (subseq inbuf 0 pos))))
+	   ((zerop pos) output)))))
+
+(defun finger (query &key (verbose nil) (port 79))
+  "Takes a query, in the same format as the unix command line tool and execute it."
+  (let (host
+	(host-query (if verbose "/W " "")))
+    (aif (position #\@ query :from-end t)
+	 (setf host (subseq query (1+ it))
+	       host-query (concatenate 'string host-query (subseq query 0 it)))
+	 (setf host query))
+    (%finger host host-query port)))
+
+;; For testing try:
+;; (where "some-host.com" is a host running a finger server):
+;;   (finger "some-host.com")
+;;   (finger "user@some-host.com") 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Server code
+(defun finger-daemon (handler &key (port 79) (subqueries nil))
+  "Start up a listner on port that responds to the finger protocol"
+  (process-run-function (format nil "finger-daemon on port ~d" port)
+			#'%finger-daemon handler port subqueries))
+  
+(defun %finger-daemon (handler port subqueries)
+  "Specific implementation routine."
+  (with-open-socket (sock :type :stream :connect :passive :local-port port :reuse-address t)
+    (loop
+       (let ((insock (accept-connection sock)))
+	 (process-run-function "Finger request handler"
+			       #'%finger-daemon-handler handler insock subqueries)))))
+
+(defun %finger-daemon-handler (handler socket subqueries)
+  (let* ((line (read-net-line socket))
+	 (verbose (and (>= (length line) 3)
+		       (string= line "/W " :end1 3)))
+	 (proc-line (if verbose (subseq line 3) line))
+	 (req-sub (find #\@ line :test #'char=))
+	 (ret-str (cond ((and subqueries req-sub)
+			 (finger-forward-handler proc-line verbose))
+			(req-sub
+			 "Sub-Queries not supported.")
+			(t
+			 (funcall handler proc-line verbose)))))
+    (if (null ret-str)
+	(write-sequence "Unknown." socket)
+	(write-sequence ret-str socket))
+    (force-output socket)
+    (close socket)))
+
+(defun finger-forward-handler (line verbose)
+  "Handler for forwarding requests a third party"
+  (handler-bind ((error #'(lambda (c)
+			    (declare (ignore c))
+			    (return-from finger-forward-handler "Unable to process the request."))))
+    (finger line :verbose verbose)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Vending machine code, which becomes a simple server
+(defstruct vending
+  button
+  contents
+  description
+  price)
+
+(defparameter *vending-machine* nil
+  "Holds the data for the vending machine.")
+
+(defun populate-vending-machine (data)
+  "Takes a list of data in the format (button short-desc long-desc price) and turns it into a vending mahcine."
+  (setf *vending-machine* (mapcar #'(lambda (x)
+				      (destructuring-bind (b c d p) x
+					(make-vending :button b
+						      :contents c
+						      :description d
+						      :price p)))
+				  data)))
+
+(populate-vending-machine
+ '(("T1" "English Breakfast Tea" "Probably the best tea in the world." 1.0)
+   ("T2" "Earl Grey" "Well if you like the taste of washing up liquid..." 1.1)
+   ("T3" "Herbal Tea (Various)" "Smells great, tastes just like water." 0.80)
+   ("C1" "Cheap 'n' Nasty coffee." "It's awful, doesn't even taste like coffee." 0.50)
+   ("C2" "Freeze Dried Coffee." "Do yourself a favour and go to a coffee shop and get a real coffee." 1.0)
+   ("H1" "Hot Chocolate" "Carefull, this is so hot it'll cook your tastebuds." 1.0)))
+
+(defun vending-machine-details ()
+  (with-output-to-string (stream)
+    (format stream "~%Button~10,0TContents~50,4TPrice~%")
+    (format stream "-------------------------------------------------------~%")
+    (dolist (i *vending-machine*)
+      (format stream "~a~10,0T~a~50,4T~,2f~%"
+	      (vending-button i)
+	      (vending-contents i)
+	      (vending-price i)))))
+
+(defun specific-button-details (button)
+  "This write the specific information for the button"
+  (with-output-to-string (stream)
+    (let ((item (find button *vending-machine*
+		      :key #'vending-button
+		      :test #'string-equal)))
+      (cond ((null item)
+	     (format stream "Not available on this machine.~%"))
+	    (t
+	     (format stream "Button: ~a~50,0tPrice: ~,2f~%"
+		     (vending-button item)
+		     (vending-price item))
+	     (format stream "Contents: ~a~%"
+		     (vending-contents item))
+	     (format stream "Description: ~a~%"
+		     (vending-description item)))))))
+
+(defun process-vending-machine-command (command verbose)
+  "This is the vending machine."
+  (declare (ignore verbose))
+  (if (string= command "")
+      (vending-machine-details)
+      (specific-button-details command)))
+
+(defun vending-machine-demo (port)
+  (finger-daemon #'process-vending-machine-command :port port))
Index: /branches/new-random/contrib/repenning/anticipat-symbol-complete.lisp
===================================================================
--- /branches/new-random/contrib/repenning/anticipat-symbol-complete.lisp	(revision 13309)
+++ /branches/new-random/contrib/repenning/anticipat-symbol-complete.lisp	(revision 13309)
@@ -0,0 +1,692 @@
+;;; -*- package: ccl -*-
+;*********************************************************************
+;*                                                                   *
+;*    PROGRAM     A N T I C I P A T O R Y   SYMBOL COMPLETE          *
+;*                                                                   *
+;*********************************************************************
+   ;* Author    : Alexander Repenning (alexander@agentsheets.com)    *
+   ;*             http://www.agentsheets.com                         *
+   ;* Copyright : (c) 1996-2008, AgentSheets Inc.                    *
+   ;* Filename  : anticipatory-symbol-complete.lisp                  *
+   ;* Updated   : 12/30/08                                           *
+   ;* Version   :                                                    *
+   ;*   1.0     : 06/19/04                                           *
+   ;*   1.0.1   : 07/04/04 Peter Paine: custom -color*, nil wait     *
+   ;*   1.0.2   : 07/07/04 correct position for fred-dialog-item     *
+   ;*   1.1     : 09/08/04 don't get stuck; args and space on tab    *
+   ;*   1.1.1   : 09/09/04 use *Package* if Fred has no package      *
+   ;*   1.2     : 09/17/04 limited support Traps package, #_blabla   *
+   ;*                      cannot find unloaded traps (most)         *
+   ;*   1.3     : 09/29/04 save-exit function to be image friendly   *
+   ;*   1.4     : 10/06/04 play nice with Glen Foy's Color-Coded     * 
+   ;*   1.4.1   : 10/21/04 handle $updateEvt                         *
+   ;*   1.4.2   : 12/14/04 XML "<..." and "</..." support            *
+   ;*   1.5     : 10/21/05 proactive typo alert                      *
+   ;*   1.5.1   : 08/25/06 use "..." instead of ellipsis char        *
+   ;*   1.5.2   : 09/22/06 works with LF EOL Fred buffers            *
+   ;*   1.5.3   : 08/14/07 symbol-completion-enabled-p method        *
+   ;*   1.5.4   : 10/24/07 handle Apple Events as kHighLevelEvent    *
+   ;*   2.0     : 04/22/08 Clozure CL, Gail Zacharias                *
+   ;*   2.0.1   : 04/25/08 auto enabled, release pool, process fix   *
+   ;*   2.0.2   : 12/30/08 kill processes when typing fast           *
+   ;* HW/SW     : G4,  CCL 1.2, OS X 10.5.2                          *
+   ;* Abstract  : Attempt symbol completion while user is typing.    *
+   ;*             #\tab to complete, show arglist if possible        *
+   ;*             #\esc to cancel                                    *
+   ;* Status    : good to go                                         *
+   ;* License   : LGPL                                               *
+   ;******************************************************************
+
+#+digitool (in-package :ccl)
+#+clozure (in-package :hemlock)
+
+(export '(symbol-completion-enabled-p *anticipatory-symbol-completion-enabled-p*))
+
+
+(defvar *Wait-Time-for-Anticipatory-Symbol-Complete* 0.2 "time in seconds to wait before anticipatory symbol complete begins to search.")
+
+(defvar *Anticipatory-Symbol-Completion-Enabled-p* t)
+
+(defvar *Anticipatory-Symbol-Completion-Font-Color* #+digitool *Gray-Color* #+clozure (#/grayColor ns:ns-color))
+
+(defvar *Anticipatory-Symbol-Completion-Background-Color*
+  #+digitool (make-color 55000 55000 64000)
+  #+clozure (gui::color-values-to-nscolor 55000/65535 55000/65535 64000/65535))
+
+(defvar *Zero-Completion-Hook* #+digitool #'ed-beep #+clozure #'beep "Call this function if there are no completions: could be the sign of a typo. Typically replace with more subtle sound.")
+
+;; Better enable these CCL compiler preferences to get more meaninglful arglists
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (unless ccl:*Save-Local-Symbols* (print "ANTICIPATORY SYMBOL COMPLETE hint: To get meaningful arglists for completed functions you should set ccl:*Save-Local-Symbols* to t"))
+  (unless ccl:*Fasl-Save-Local-Symbols* (print "ANTICIPATORY SYMBOL COMPLETE hint: To get meaningful arglists for completed functions you should set ccl:*Fasl-Save-Local-Symbols* to t")))
+
+;___________________________________ 
+; Completion Overlay Window         |
+;___________________________________ 
+
+(defvar *Assistant* nil)
+
+#+digitool (progn
+(defun COMPLETION-OVERLAY-WINDOW () "
+  Return current overlay window used for symbol completion. 
+  Create one if needed."
+  (or *Assistant*
+      (setq *Assistant*
+            (rlet ((&window :pointer)
+                   (&rect :rect :topleft #@(100 100) :bottomright #@(500 140)))
+              (#_CreateNewWindow #$kOverlayWindowClass 0 &rect &window)
+              (%get-ptr &window)))))
+
+
+(defun WAIT-FOR-TIME-OR-KEY-EVENT (Time)
+  (let ((Wakeup-Time (+ (get-internal-real-time) (* Time internal-time-units-per-second))))
+    (without-interrupts   ;; don't allow other threads to steal events
+     (loop
+       ;; timeout
+       (when (>= (get-internal-real-time) Wakeup-Time) (return))
+       (when (mouse-down-p) (return))
+       ;; poll for key events
+       (rlet ((Event :eventrecord))
+         (when (#_EventAvail #$everyEvent Event)
+           (case (rref Event :eventrecord.what)
+             ((#.#$keyDown #.#$keyUp #.#$autoKey)  ;; Key Event
+              (let ((Char (code-char (logand #$charCodeMask (rref Event :eventrecord.message)))))
+                (unless (char= Char #\null)
+                  (return Char))))
+             ((#.#$activateEvt #.#$osEvt #.#$mouseDown #.#$mouseUp #.#$updateEvt)  ;; Window activation or OS event
+              (#_getNextEvent #$everyEvent Event))
+             ;; let OS X handle this Apple Event as high level event
+             ;; http://developer.apple.com/documentation/AppleScript/Conceptual/AppleEvents/dispatch_aes_aepg/chapter_4_section_3.html
+             ;; listing 3-5
+             (#.#$kHighLevelEvent
+              (#_AEProcessAppleEvent Event))
+             (t 
+              ;; unexpected event: send email to Alex if this happens
+              (ed-beep)
+              (format t "unexpected event=~A (send email to Alex)" (rref Event :eventrecord.what))))))))))
+
+
+(defun SHOW-IN-OVERLAY-WINDOW (Text Position) "
+  in:  Text string, Position point.
+  out: Char char.
+  Show <Text> in overlay window at screen <Position>. 
+  Wait for key event or timeout.
+  In case of key event return char."
+  (let ((Window (completion-overlay-window)))
+    (#_MoveWindow Window (point-h Position) (point-v Position) t)
+    (#_ShowWindow window) 
+    (#_SetPort (#_GetWindowPort window))
+    ;; size of string?
+    (with-cfstrs ((string Text))
+      (rlet ((&ioBounds :point)
+             (&outBaseline :signed-integer))
+        (#_GetThemeTextDimensions 
+         String 
+         #$kThemeSmallSystemFont
+         #$kThemeStateActive
+         nil
+         &ioBounds
+         &outBaseline)
+        (let ((Text-Size (add-points (%get-point &ioBounds) #@(10 0))))
+          ;; paint background
+          (rlet ((&rect :rect :topleft #@(-10 1) :botright Text-Size))
+            (with-fore-color *Anticipatory-Symbol-Completion-Background-Color*
+              (#_PaintRoundRect &rect 12 12)))
+          ;; text
+          (rlet ((&rect :rect :topleft #@(1 0) :botright Text-Size))
+            (with-fore-color *Anticipatory-Symbol-Completion-Font-Color*
+              (#_DrawThemeTextBox
+               String
+               #$kThemeSmallSystemFont
+               #$kThemeStateActive
+               nil
+               &rect
+               #$teJustLeft
+               (%null-ptr)))))))
+    (#_QDFlushPortBuffer (#_GetWindowPort window) (%null-ptr))
+    (prog1
+      (wait-for-time-or-key-event 5)
+      (#_HideWindow window))))
+)
+
+#+clozure (progn
+(defclass completion-overlay (ns:ns-view)
+  ((text-attributes :foreign-type :id)
+   (text :foreign-type :id))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/drawRect: :void) ((self completion-overlay) (rect :<NSR>ect))
+  (ccl::with-autorelease-pool 
+      (#/set (#/clearColor ns:ns-color))
+    (#_NSRectFill (#/bounds self))
+    (ns:with-ns-point (point 0 1)
+      (#/drawAtPoint:withAttributes: (slot-value self 'text)
+                                     point
+                                     (slot-value self 'text-attributes)))))
+
+(defun COMPLETION-OVERLAY-WINDOW () "
+  Return current overlay window used for symbol completion. 
+  Create one if needed."
+  (or *Assistant*
+      (setq *Assistant*
+            (ns:with-ns-rect (frame 100 100 400 40)
+              (let* ((w (make-instance 'ns:ns-window
+                          :with-content-rect frame
+                          :style-mask #$NSBorderlessWindowMask
+                          :backing #$NSBackingStoreBuffered
+                          :defer #$YES))
+                     (view (make-instance 'completion-overlay
+                             :with-frame (#/frame (#/contentView w))))
+                     ;; Create attributes to use in window
+                     (attribs (make-instance 'ns:ns-mutable-dictionary :with-capacity 3)))
+                (#/setObject:forKey: attribs (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font))
+                                     #&NSFontAttributeName)
+                (#/setObject:forKey: attribs *Anticipatory-Symbol-Completion-Font-Color*
+                                     #&NSForegroundColorAttributeName)
+                (#/setObject:forKey: attribs *Anticipatory-Symbol-Completion-Background-Color*
+                                     #&NSBackgroundColorAttributeName)
+                (setf (slot-value view 'text-attributes) (#/retain attribs))
+                (setf (slot-value view 'text) (#/retain (gui::%make-nsstring "")))
+                (#/setContentView: w view)
+                ;; Set the background color to clear so that (along with the setOpaque call below)
+                ;; we can see through the parts of the window that we're not drawing into
+                (#/setBackgroundColor: w (#/clearColor ns:ns-color))
+                ;; No transparency for actual drawing into the window
+                (#/setAlphaValue: w (gui::cgfloat 1.0))
+                ;; Allow see through the parts of the window we're not drawing into
+                (#/setOpaque: w #$NO)
+                ;; Make it as unobtrusive as possible
+                (#/setIgnoresMouseEvents: w #$YES)
+                (#/setExcludedFromWindowsMenu: w #$YES)
+                (#/setHidesOnDeactivate: w #$YES)
+                w)))))
+
+
+(defun OPEN-OVERLAY-WINDOW (Text Position)
+  "Show text at screen position"
+  (ccl::with-autorelease-pool 
+      (let ((w (completion-overlay-window)))
+        (#/setFrameOrigin: w Position)
+        (let* ((w (completion-overlay-window))
+               (overlay (#/contentView w))
+               (nsstring (ccl::%make-nsstring Text)))
+          (with-slots (text) overlay
+            (#/release text)
+            (setf text (#/retain nsstring)))
+          (#/display w)
+          (#/orderFront: w ccl:+null-ptr+)))))
+
+(defun CLOSE-OVERLAY-WINDOW ()
+  "Hide the overlay window"
+  (let ((w (completion-overlay-window)))
+    (#/orderOut: w ccl:+null-ptr+)))
+)
+
+;___________________________________ 
+; Symbol String functions           |
+;___________________________________ 
+
+(defun COMMON-PREFIX (String1 String2)
+  ;; if one string is a complete substring then return it
+  (let ((Short-String (if (< (length String1) (length String2)) String1 String2)))
+    (dotimes (I (length Short-String) Short-String)
+      (let ((Char1 (char String1 i)))
+        (unless (char= Char1 (char String2 i))
+          (return (subseq Short-String 0 i)))))))
+    
+
+(defun LONGEST-PREFIX (Symbols)
+  (when Symbols
+    (reduce #'common-prefix (mapcar #'symbol-name Symbols))))
+
+
+;___________________________________ 
+; Cursor HPOS/VPOS Position fixes   |
+;___________________________________ 
+
+#+digitool
+(defmethod FRED-HPOS ((W listener-fred-item) &optional (Pos (buffer-position 
+                                                          (fred-buffer w))))
+  ;; Alice's listener HPOS fix
+  (let* ((Buf (fred-buffer w))
+         (Frec (frec w))
+         (End (buffer-line-end buf pos)))
+    (cond ((and (fr.wrap-p frec)
+                (eql end (buffer-size buf))
+                (> end 0))
+           (let* ((Start (buffer-line-start buf pos))
+                  (Res (%screen-line-hpos frec start pos end)))  ;; << was end end
+             ;(push (list res (fred-hpos w pos)) cow)
+             (+ res 0)))   ;; fudge epsilon
+          (t (fred-hpos w pos)))))
+
+
+#+digitool
+(defmethod FRED-HPOS ((Self fred-dialog-item) &optional (Pos (buffer-position (fred-buffer Self))))
+  ;; need to add dialog item in window offset
+  (declare (ignore Pos))
+  (+ (point-h (convert-coordinates #@(0 0) Self (view-window Self)))
+     (call-next-method)))
+
+
+#+digitool
+(defmethod FRED-VPOS ((Self fred-dialog-item) &optional (Pos (buffer-position (fred-buffer Self))))
+  ;; need to add dialog item in window offset
+  (declare (ignore Pos))
+  (+ (point-v (convert-coordinates #@(0 0) Self (view-window Self)))
+     (call-next-method)))
+
+;___________________________________ 
+; Completion-Request class          |
+;___________________________________ 
+
+(defclass COMPLETION-REQUEST ()
+  ((time-stamp :accessor time-stamp :initform (get-internal-real-time))
+   (completion-string :accessor completion-string :initform "" :initarg :completion-string)
+   (completion-name :accessor completion-name)
+   (completion-package :accessor completion-package)
+   #+clozure (completion-prefix :accessor completion-prefix :initform nil)
+   (fred-instance :accessor fred-instance :initarg :fred-instance)
+   (fred-buffer-start :accessor fred-buffer-start :initarg :fred-buffer-start)
+   (fred-buffer-end :accessor fred-buffer-end :initarg :fred-buffer-end))
+  (:documentation "captures what the request is, when it was made, and where is what made"))
+
+
+
+(defmethod INITIALIZE-INSTANCE :after ((Self completion-request) &rest Args)
+  (declare (ignore Args))
+  (let ((String (completion-string Self)))
+    ;; explore package clues
+    (when String
+      (setf (completion-name Self) 
+            (case (char String 0)
+              ((#\: #\#) (subseq (string-upcase String) 1))
+              (t (string-upcase String))))
+      (setf (completion-package Self) 
+            (or (and (char= (char String 0) #\:) (find-package :keyword))
+                (and (char= (char String 0) #\#) (find-package :traps))
+                #+digitool (window-package (fred-instance Self))
+                #+clozure (buffer-package (hemlock-view-buffer (fred-instance Self)))
+                *Package* )))))
+
+
+(defun ADD-SPECIAL-PACKAGE-PREFIX (String Package)
+  ;; some packages have a special prefix consisting of a single character
+  (cond
+   ((equal Package (find-package :keyword)) (format nil ":~A" String))
+   ((equal Package (find-package :traps)) (format nil "#~A" String))
+   (t String)))
+
+
+(defmethod PROMISING-PREFIX ((Thing string))
+  ;; heuristicly exclude
+  (and
+   (not (char-equal (char Thing 0) #\\))  ;; char names
+   (not (char-equal (char Thing 0) #\"))  ;; beginning of strings
+   (not (every ;; numbers
+         #'(lambda (Item)
+             (member Item '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\d #\D #\s #\S #\e #\E #\. #\/)))
+         Thing))))
+
+#+clozure
+(defmethod completion-screen-position ((Self completion-request))
+  (let* ((view (fred-instance Self))
+         (charpos (mark-absolute-position (buffer-point (hemlock-view-buffer view))))
+         (tv (gui::text-pane-text-view (hi::hemlock-view-pane view))))
+    (multiple-value-bind (x y) (gui::charpos-xy tv charpos)
+      (ns:with-ns-point (pt x (+ y (gui::text-view-line-height tv)))
+        (#/convertBaseToScreen: (#/window tv)
+                                (#/convertPoint:toView: tv pt gui::+null-ptr+))))))
+
+#+clozure
+(defmethod view-active-p ((Self completion-request))
+  (not (ccl:%null-ptr-p (#/window (hi::hemlock-view-pane (fred-instance Self))))))
+
+#+clozure
+(defvar *Completion-Request* nil "Currently active completion request")
+
+
+(defmethod ANTICIPATORY-SYMBOL-COMPLETE ((Self completion-request)) "
+  in: Completion-Request completion-request.
+  Explore the opportunity for symbol completion."
+  (ccl::with-autorelease-pool
+      ;; don't be too eager and wait first a little
+      (sleep *Wait-Time-for-Anticipatory-Symbol-Complete*)
+    ;; find matching symbols
+    (let* ((Local-Symbols (apropos-list (completion-name Self) (completion-package Self)))
+           (Symbols (matching-prefix-symbols (completion-name Self) Local-Symbols))
+           #+digitool (Fred (fred-instance Self)))
+      ;; proactive typo alert
+      (when (and *Zero-Completion-Hook*
+                 (= (length Local-Symbols) 0)
+                 (promising-prefix  (completion-name Self)))
+        (funcall *Zero-Completion-Hook*))  ;; beep when the number has dropped to zero: usually a sign of a typo
+      ;; completion attempt
+      (let ((Prefix (longest-prefix Symbols)))
+        (when (and (> (length Prefix) (length (completion-name Self)))
+                   #+digitool (and (view-window Fred) ;; window may be gone by now!
+                                   (wptr (view-window Fred)))
+                   #+clozure (view-active-p Self))
+          #+digitool (setq *Show-Cursor-P* nil)
+          ;; if we made it this far we better complete things
+          #+digitool
+          (let* ((Extension (string-downcase (subseq Prefix (length (completion-name Self)))))
+                 (Char (show-in-overlay-window
+                        (if (find-symbol Prefix (completion-package Self))
+                          Extension
+                          (format nil "~A..." Extension))
+                        (add-points (add-points (view-position (view-window Fred)) #@(0 -10))
+                                    (make-point (fred-hpos Fred) (fred-vpos Fred))))))
+            (case Char
+              ;; Tab = accept completion but don't do Fred indentation spiel
+              (#\tab
+               (#_FlushEvents (logior #$keyDownMask #$keyUpMask) 0)   ;; avoid indentation
+               (buffer-replace-string
+                Fred
+                (fred-buffer-start Self)
+                (fred-buffer-end Self)
+                (add-special-package-prefix Prefix (completion-package Self))
+                (completion-string Self))
+               (when (find-symbol Prefix (completion-package Self)) 
+                 (without-interrupts  ;; not sure this helps, found cases in which ed-arglist can hang MCL: WHY??
+                  (ed-arglist Fred)))  ;; show arglist if possible
+               (fred-update Fred))))
+          #+clozure
+          (let* ((Extension (string-downcase (subseq Prefix (length (completion-name Self))))))
+            (unwind-protect
+                (progn
+                  (open-overlay-window (if (find-symbol Prefix (completion-package Self))
+                                         Extension
+                                         (format nil "~A..." Extension))
+                                       (completion-screen-position Self))
+                  (setf (completion-prefix Self) Prefix)
+                  ;; If the user types anything while the window is up, this process gets reset with *Completion-Request*
+                  ;; still set, so the Tab command can tell what the Prefix was.  
+                  (setq *Completion-Request* Self)
+                  (sleep 5)
+                  ;; timed out: forget completion request
+                  (setq *Completion-Request* nil))
+              (close-overlay-window)) ))))))
+
+;___________________________________ 
+; Process Management                |
+;___________________________________ 
+
+(defvar *Completion-Process* nil "process used to complete symbols in anticipatory way")
+
+
+(defun COMPLETION-PROCESS ()
+  (or *Completion-Process*
+      (setq *Completion-Process* (ccl:make-process "Anticipatory Symbol Complete" :priority 0 #+digitool :quantum #+digitool 1))))
+
+
+#+digitool
+(defun START-SYMBOL-COMPLETE-PROCESS (Request)
+  (ccl::process-preset (completion-process) #'(lambda ()
+						(setq *Completion-Request* nil)
+						(anticipatory-symbol-complete Request)))
+  (ccl::process-reset-and-enable (completion-process)))
+
+#+clozure
+(defun START-SYMBOL-COMPLETE-PROCESS (Request)
+  (when *Completion-Process*
+    ;; not sure how we get here: before a new completion process is started 
+    ;; the old should have been killed already
+    (ccl:process-kill *Completion-Process*))
+  (setq *Completion-Process*
+	(ccl::process-run-function 
+	 '(:name "Anticipatory Symbol Complete" :priority 0)
+	 #'(lambda () (anticipatory-symbol-complete Request)))))
+
+
+#+clozure
+(defun ABORT-SYMBOL-COMPLETE-PROCESS ()
+  (cond
+   ;; completion still going on
+   (*Completion-Process*
+    (ccl:process-kill *Completion-Process*)
+    (setq *Completion-Process* nil))
+   ;; completion must have timed out: remove completion request
+   (t
+    (setq *Completion-Request* nil))))
+
+;___________________________________ 
+; Symbol-Complete.lisp functions    |
+;___________________________________ 
+
+#+digitool
+(defmethod BUFFER-REPLACE-STRING ((Self fred-mixin) Start End String &optional Old-String) "
+  in:  Self {fred-mixin}, Start End {position}, String {string}, 
+       &optional Old-String {string}.
+  Delete the buffer content between <Start> and <End>, insert
+  <String> and place insertion marker to <End> position."
+  (let ((Mark (fred-buffer Self)))
+    (buffer-delete Mark Start End)
+    (buffer-insert 
+     Mark
+     (if Old-String
+       (case (string-format Old-String)
+         (:upper (string-upcase String))
+         (:lower (string-downcase String))
+         (:capital (string-capitalize String)))
+       String)))
+  ;; play nice with color-coded (when present)
+  (let ((Color-Code-Update-Function (find-symbol "DYNAMICALLY-STYLE-BUFFER" (find-package :cc))))
+    (when (fboundp Color-Code-Update-Function) (funcall Color-Code-Update-Function Self))))
+
+#+clozure
+(defun BUFFER-REPLACE-STRING (Start End String &optional Old-String) "
+  in: Start End {position}, String {string}, 
+       &optional Old-String {string}.
+  Delete the current buffer content between <Start> and <End>, insert
+  <String> and place insertion marker to <End> position."
+  (paste-characters Start (- End Start) 
+                    (if Old-String
+                      (case (string-format Old-String)
+                        (:upper (string-upcase String))
+                        (:lower (string-downcase String))
+                        (:capital (string-capitalize String)))
+                      String)))
+
+(defun STRING-FORMAT (String) "
+  in:  String {string}.
+  out: Capitalization {keyword} :upper, :lower :capital.
+  Return the capitalization status of a string"
+  (case (length String)
+    (0 :lower)
+    (1 (if (lower-case-p (char String 0)) :lower :upper))
+    (t (if (char= (char String 0) #\*)
+         (string-format (subseq String 1))
+         (if (upper-case-p  (char String 0))
+           (if (upper-case-p (char String 1))
+             :upper
+             :capital)
+           :lower)))))
+
+
+(defun MATCHING-PREFIX-SYMBOLS (String Symbols) "
+  in:  String {string}, Symbols {list of: {symbol}}.
+  out: Symbols {list of: {symbol}}.
+  Return only the symbols of which <String> is a prefix."
+  (let ((L (length String)))
+    (remove-if-not
+     #'(lambda (Symbol) (string= String (symbol-name Symbol) :end1 L :end2 L))
+     Symbols)))
+
+;___________________________________ 
+; FRED extensions                   |
+;___________________________________ 
+
+#+digitool
+(defun BUFFER-CURRENT-STRING (Buffer Position)
+  (when (< (buffer-size Buffer) 1) (return-from buffer-current-string))
+  (unless (char= (buffer-char Buffer Position) #\space)
+    (let ((Start Position)
+          (End Position)) 
+      ;; scan left for delimiter
+      (loop
+        (when (= Start 0) (return))
+        (case (buffer-char Buffer Start)
+          ((#\space #\return #\linefeed #\( #\) #\' #\<)
+           ;; special treatment for "<" versus "</" XML prefix 
+           (return (incf Start (if (char= (buffer-char Buffer (1+ Start)) #\/) 2 1)))))
+        (decf Start))
+      ;; scan right for delimiter
+      (loop
+        (when (= End (buffer-size Buffer)) (return))
+        (incf End)
+        (case (buffer-char Buffer End)
+          ((#\space #\return #\linefeed #\( #\)) (return))))
+      (values
+       (buffer-substring Buffer Start End)
+       Start
+       End))))
+
+#+clozure
+(defun BUFFER-CURRENT-STRING ()
+  (with-mark ((Start (current-point))
+              (End (current-point)))
+    (unless (eq (previous-character Start) #\space)
+      ;; scan left for delimiter
+      (loop
+        (case (previous-character Start)
+          ((nil #\space #\tab #\return #\linefeed #\( #\) #\' #\<)
+           ;; special treatment for "<" versus "</" XML prefix
+           (when (eq (next-character start) #\/)
+             (mark-after Start))
+           (return)))
+        (mark-before Start))
+      ;; scan right for delimiter
+      (loop
+        (case (next-character End)
+          ((nil #\space #\tab #\return #\linefeed #\( #\)) (return)))
+        (mark-after End))
+      (values (region-to-string (region Start End))
+              (mark-absolute-position Start)
+              (mark-absolute-position End)))))
+
+#+digitool (progn
+
+(defmethod SYMBOL-COMPLETION-ENABLED-P ((Self fred-mixin))
+  t)
+
+
+(defmethod ED-INSERT-CHAR :after ((Self fred-mixin) Char) "  
+  After typing a delimiter check if there is a link"
+  (unless (and *Anticipatory-Symbol-Completion-Enabled-P* (symbol-completion-enabled-p Self))
+    (return-from ed-insert-char))
+  (case Char
+    ;; user is done with current symbol: stop completion
+    ((#\space #\return)
+       (process-flush (completion-process)))
+    ;; new character part of current symbol
+    (t
+     (multiple-value-bind (String Start End)
+                          (buffer-current-string (fred-buffer Self) (- (buffer-position (fred-buffer Self)) 1))
+       (when (> (length String) 1)
+         (start-symbol-complete-process 
+          (make-instance 'completion-request 
+            :completion-string String
+            :fred-instance Self
+            :fred-buffer-start Start
+            :fred-buffer-end End)))))))
+)
+
+#+clozure (progn
+
+;; enable by default
+(add-hook make-buffer-hook
+                   #'(lambda (buffer)
+                       (setf (buffer-minor-mode buffer "Symbol Completion") t)))
+
+(defmode "Symbol Completion"
+  :documentation "This is a minor mode that provides anticipatory symbol completion")
+
+(defcommand "Symbol Completion Mode" (p)
+  "Toggles Symbol Completion mode in the current buffer"
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Symbol Completion")
+        (not (buffer-minor-mode (current-buffer) "Symbol Completion"))))
+
+(defhvar "Self Insert Command Name"
+  "Name of command to invoke for quoted insert in Symbol Completion mode"
+  :value "Self Insert With Symbol Completion"
+  :mode "Symbol Completion")
+
+(defcommand "Self Insert With Symbol Completion" (p)
+  "Self Insert and start up the completion process"
+  (self-insert-command p)
+  (when *Anticipatory-Symbol-Completion-Enabled-p*
+    (case (last-char-typed)
+      ((#\space #\newline) nil)
+      (t
+       (multiple-value-bind (String Start End) (buffer-current-string)
+         (when (> (length String) 1)
+           (handler-case (start-symbol-complete-process (make-instance 'completion-request
+                                                          :completion-string String
+                                                          :fred-instance (current-view)
+                                                          :fred-buffer-start start
+                                                          :fred-buffer-end end))
+             (t (Condition) (format t "condition: ~A" Condition)))))))))
+
+
+(dolist (c (command-bindings (getstring "Self Insert" *command-names*)))
+  (bind-key "Self Insert with Symbol Completion" (car c) :mode "Symbol Completion"))
+
+
+(defvar *Last-Hemlock-Key* nil "key last pressed in a hemlock view")
+
+
+(defmethod hi::execute-hemlock-key :before ((view hemlock-view) key)
+  (setq *Last-Hemlock-Key* Key)
+  (abort-symbol-complete-process))
+
+
+;; The :transparent-p flag causes this to do the usual binding for the key
+;; unless we explicitly invoke exit-event-handler.
+(defcommand ("Maybe Insert Symbol Completion" :transparent-p t) (p)
+  "Insert symbol completion if there is one, otherwise do the usual action"
+  (declare (ignore p))
+  (let* ((Request *Completion-Request*)
+         (Prefix (and Request (completion-prefix Request))))
+    (when Prefix
+      (buffer-replace-string (fred-buffer-start request)
+                             (fred-buffer-end request)
+                             (add-special-package-prefix Prefix (completion-package Request))
+                             (completion-string Request))
+      (when (find-symbol Prefix (completion-package Request))
+        (current-function-arglist-command nil))
+      (hi::exit-event-handler))))
+
+(bind-key "Maybe Insert Symbol Completion" #k"Tab" :mode "Symbol Completion")
+
+)
+
+;___________________________________ 
+; save-application support          |
+;___________________________________ 
+
+(defun ANTICIPATORY-SYMBOL-COMPLETE-SAVE-EXIT-FUNCTION ()
+  (setq *Assistant* nil)
+  (when *Completion-Process*
+    (ccl:process-kill *Completion-Process*)
+    (setq *Completion-Process* nil)))
+  
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (pushnew 'anticipatory-symbol-complete-save-exit-function ccl:*Save-Exit-Functions*))
+ 
+
+#| Examples:
+
+(time (common-prefix "WITH-OPEN-FILE" "WITH-CLOSED-HOUSE"))
+
+(time (common-prefix "WITH-OPEN-FILE" "WITH-OPEN-FILENAME"))
+
+(time (common-prefix "WITH-OPEN-FILE" "WITH-OPEN-FILE"))
+
+
+
+|#
+
Index: /branches/new-random/contrib/rittweiler/ccl
===================================================================
--- /branches/new-random/contrib/rittweiler/ccl	(revision 13309)
+++ /branches/new-random/contrib/rittweiler/ccl	(revision 13309)
@@ -0,0 +1,77 @@
+#!/bin/sh
+#
+# Change the definition of CCL_DEFAULT_DIRECTORY below to refer to
+# your Clozure CL installation directory.  
+# Any definition of CCL_DEFAULT_DIRECTORY already present in the environment 
+# takes precedence over definitions made below.
+
+probe()
+{
+    if [ -e "$1"  -a  -e "$1/scripts/ccl" ]; then
+        CCL_DEFAULT_DIRECTORY="$1"
+    fi
+}
+
+if [ -z "$CCL_DEFAULT_DIRECTORY"  -a  -n "`which readlink`" ]; then
+    dir="`readlink $0`"
+    probe "${dir%/scripts/ccl}"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "`pwd`"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "/usr/local/src/ccl"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    echo "Can't find CCL directory.  Please edit $0 or"
+    echo "set the environment variable CCL_DEFAULT_DIRECTORY"
+    echo "and try again."
+    exit 1
+fi
+
+export CCL_DEFAULT_DIRECTORY
+
+# This is shorter (& easier to type), making the invocation below
+# a little easier to read.
+
+DD=${CCL_DEFAULT_DIRECTORY}
+
+# If you don't want to guess the name of the Clozure CL kernel on
+# every invocation (or if you want to use a kernel with a
+# non-default name), you might want to uncomment and change
+# the following line:
+#OPENMCL_KERNEL=some_name
+
+# Set the CCL_DEFAULT_DIRECTORY  environment variable; 
+# the lisp will use this to setup translations for the CCL: logical host.
+
+if [ -z "$OPENMCL_KERNEL" ]; then
+  case `uname -s` in
+    Darwin) case `arch` in
+              ppc*) OPENMCL_KERNEL=dppccl ;;
+              i386) OPENMCL_KERNEL=dx86cl ;;
+            esac ;;
+    Linux) case `uname -m` in
+              ppc*) OPENMCL_KERNEL=ppccl ;;
+              *86*) OPENMCL_KERNEL=lx86cl ;;
+           esac ;;
+    CYGWIN*)
+       OPENMCL_KERNEL=wx86cl.exe
+       CCL_DEFAULT_DIRECTORY="C:/cygwin$CCL_DEFAULT_DIRECTORY"
+    ;;
+    SunOS) OPENMCL_KERNEL=sx86cl
+    ;;
+    FreeBSD) OPENMCL_KERNEL=fx86cl
+    ;;
+    *)
+    echo "Can't determine host OS.  Fix this."
+    exit 1
+    ;;
+  esac
+fi
+
+exec ${DD}/${OPENMCL_KERNEL} "$@"
+
Index: /branches/new-random/contrib/rittweiler/ccl64
===================================================================
--- /branches/new-random/contrib/rittweiler/ccl64	(revision 13309)
+++ /branches/new-random/contrib/rittweiler/ccl64	(revision 13309)
@@ -0,0 +1,109 @@
+#!/bin/sh
+#
+# Change the definition of CCL_DEFAULT_DIRECTORY below to refer to
+# your Clozure CL installation directory.  
+# Any definition of CCL_DEFAULT_DIRECTORY already present in the environment 
+# takes precedence over definitions made below.
+
+probe()
+{
+    if [ -e "$1"  -a  -e "$1/scripts/ccl64" ]; then
+        CCL_DEFAULT_DIRECTORY="$1"
+    fi
+}
+
+if [ -z "$CCL_DEFAULT_DIRECTORY"  -a  -n "`which readlink`" ]; then
+    dir="`readlink $0`"
+    probe "${dir%/scripts/ccl64}"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "`pwd`"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "/usr/local/src/ccl"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    echo "Can't find CCL directory.  Please edit $0 or"
+    echo "set the environment variable CCL_DEFAULT_DIRECTORY"
+    echo "and try again."
+    exit 1
+fi
+
+# This is shorter (& easier to type), making the invocation below
+# a little easier to read.
+
+DD=${CCL_DEFAULT_DIRECTORY}
+
+# If you don't want to guess the name of the Clozure CL kernel on
+# every invocation (or if you want to use a kernel with a
+# non-default name), you might want to uncomment and change
+# the following line:
+#OPENMCL_KERNEL=some_name
+
+# Set the CCL_DEFAULT_DIRECTORY  environment variable; 
+# the lisp will use this to setup translations for the CCL: logical host.
+
+if [ -z "$OPENMCL_KERNEL" ]; then
+  case `uname -s` in
+    Darwin)
+    case `arch` in
+      ppc*)
+      OPENMCL_KERNEL=dppccl64
+      ;;
+      i386|x86_64)
+      OPENMCL_KERNEL=dx86cl64
+      ;;
+    esac
+    ;;
+    Linux)
+    case `uname -m` in
+      ppc64)
+      OPENMCL_KERNEL=ppccl64
+      ;;
+      x86_64)
+      OPENMCL_KERNEL=lx86cl64
+      ;;
+      *)
+      echo "Can't determine machine architecture.  Fix this."
+      exit 1
+      ;;
+    esac
+    ;;
+    FreeBSD)
+    case `uname -m` in
+      amd64)
+      OPENMCL_KERNEL=fx86cl64
+      ;;
+      *)
+      echo "unsupported architecture"
+      exit 1
+      ;;
+    esac
+    ;;
+    SunOS)
+    case `uname -m` in
+      i86pc)
+      OPENMCL_KERNEL=sx86cl64
+      ;;
+      *)
+      echo "unsupported architecture"
+      exit 1
+      ;;
+    esac
+    ;;
+    CYGWIN*)
+    OPENMCL_KERNEL=wx86cl64.exe
+    CCL_DEFAULT_DIRECTORY="C:/cygwin$CCL_DEFAULT_DIRECTORY"
+    ;;
+    *)
+    echo "Can't determine host OS.  Fix this."
+    exit 1
+    ;;
+  esac
+fi
+
+CCL_DEFAULT_DIRECTORY=${DD} exec ${DD}/${OPENMCL_KERNEL} "$@"
+
Index: /branches/new-random/doc/LGPL
===================================================================
--- /branches/new-random/doc/LGPL	(revision 13309)
+++ /branches/new-random/doc/LGPL	(revision 13309)
@@ -0,0 +1,513 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
Index: /branches/new-random/doc/LICENSE
===================================================================
--- /branches/new-random/doc/LICENSE	(revision 13309)
+++ /branches/new-random/doc/LICENSE	(revision 13309)
@@ -0,0 +1,65 @@
+
+Preamble to the Gnu Lesser General Public License
+
+Copyright (c) 2000 Franz Incorporated, Berkeley, CA 94704
+
+The concept of the GNU Lesser General Public License version 2.1
+("LGPL") has been adopted to govern the use and distribution of
+above-mentioned application. However, the LGPL uses terminology that
+is more appropriate for a program written in C than one written in
+Lisp. Nevertheless, the LGPL can still be applied to a Lisp program if
+certain clarifications are made. This document details those
+clarifications. Accordingly, the license for the open-source Lisp
+applications consists of this document plus the LGPL. Wherever there
+is a conflict between this document and the LGPL, this document takes
+precedence over the LGPL.
+
+A "Library" in Lisp is a collection of Lisp functions, data and
+foreign modules. The form of the Library can be Lisp source code (for
+processing by an interpreter) or object code (usually the result of
+compilation of source code or built with some other
+mechanisms). Foreign modules are object code in a form that can be
+linked into a Lisp executable. When we speak of functions we do so in
+the most general way to include, in addition, methods and unnamed
+functions. Lisp "data" is also a general term that includes the data
+structures resulting from defining Lisp classes. A Lisp application
+may include the same set of Lisp objects as does a Library, but this
+does not mean that the application is necessarily a "work based on the
+Library" it contains.
+
+The Library consists of everything in the distribution file set before
+any modifications are made to the files. If any of the functions or
+classes in the Library are redefined in other files, then those
+redefinitions ARE considered a work based on the Library. If
+additional methods are added to generic functions in the Library,
+those additional methods are NOT considered a work based on the
+Library. If Library classes are subclassed, these subclasses are NOT
+considered a work based on the Library. If the Library is modified to
+explicitly call other functions that are neither part of Lisp itself
+nor an available add-on module to Lisp, then the functions called by
+the modified Library ARE considered a work based on the Library. The
+goal is to ensure that the Library will compile and run without
+getting undefined function errors.
+
+It is permitted to add proprietary source code to the Library, but it
+must be done in a way such that the Library will still run without
+that proprietary code present. Section 5 of the LGPL distinguishes
+between the case of a library being dynamically linked at runtime and
+one being statically linked at build time. Section 5 of the LGPL
+states that the former results in an executable that is a "work that
+uses the Library." Section 5 of the LGPL states that the latter
+results in one that is a "derivative of the Library", which is
+therefore covered by the LGPL. Since Lisp only offers one choice,
+which is to link the Library into an executable at build time, we
+declare that, for the purpose applying the LGPL to the Library, an
+executable that results from linking a "work that uses the Library"
+with the Library is considered a "work that uses the Library" and is
+therefore NOT covered by the LGPL.
+
+Because of this declaration, section 6 of LGPL is not applicable to
+the Library. However, in connection with each distribution of this
+executable, you must also deliver, in accordance with the terms and
+conditions of the LGPL, the source code of Library (or your derivative
+thereof) that is incorporated into this executable.
+
+End of Document 
Index: /branches/new-random/doc/ccl-documentation.html
===================================================================
--- /branches/new-random/doc/ccl-documentation.html	(revision 13309)
+++ /branches/new-random/doc/ccl-documentation.html	(revision 13309)
@@ -0,0 +1,22983 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <title>Clozure CL Documentation</title>
+    <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
+    <link rel="start" href="#id248940" title="Clozure CL Documentation" />
+    <link rel="next" href="#about-ccl" title="ChapterÂ 1.Â About Clozure CL" />
+  </head>
+  <body>
+    <div class="book" lang="en" xml:lang="en">
+      <div class="titlepage">
+        <div>
+          <div>
+            <h1 class="title"><a id="id248940"></a>Clozure CL Documentation</h1>
+          </div>
+        </div>
+        <hr />
+      </div>
+      <div class="toc">
+        <dl>
+          <dt>
+            <span class="chapter">
+              <a href="#about-ccl">1. About Clozure CL</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#introduction-to-ccl">1.1. Introduction to Clozure CL</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#installing">2. Obtaining, Installing, and Running Clozure CL</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#releases">2.1. Releases and System Requirements</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#obtaining-ccl">2.2. Obtaining Clozure CL</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#command-line-setup">2.3. Command Line Set Up</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Personal-Customization-with-the-Init-File">2.4. Personal Customization with the Init File</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Command-Line-Options">2.5. Command Line Options</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Using-CCL-with-GNU-Emacs-and-SLIME">2.6. Using Clozure CL with GNU Emacs and SLIME</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Example-Programs">2.7. Example Programs</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#building-ccl-from-source">3. Building Clozure CL from its Source Code</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#building-definitions">3.1. Building Definitions</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Setting-Up-to-Build">3.2. Setting Up to Build</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Building-Everything">3.3. Building Everything</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Building-the-kernel">3.4. Building the kernel</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Building-the-heap-image">3.5. Building the heap image</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#using-ccl">4. Using Clozure CL</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#using-ccl-introduction">4.1. Introduction</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Trace">4.2. Trace</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Unicode">4.3. Unicode</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Pathanmes">4.4. Pathnames</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Memory-Mapped-Files">4.5. Memory-mapped Files</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Static_Variables">4.6. Static Variables</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Saving-Applications">4.7. Saving Applications</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#concatenating-fasl-files">4.8. Concatenating FASL Files</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#floating-point">4.9. Floating Point Numbers</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#watched-objects">4.10. Watched Objects</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#code-coverage">4.11. Code Coverage</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#ccl-ide">5. The Clozure CL IDE</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#ccl-ide-introduction">5.1. Introduction</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#building-ccl-ide">5.2. Building the IDE</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#running-ccl-ide">5.3. Running the IDE</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#ccl-ide-features">5.4. IDE Features</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#ide-source-code">5.5. IDE Sources</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#application-builder">5.6. The Application Builder</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Programming-with-Threads">6. Programming with Threads</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Threads-overview">6.1. Threads Overview</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Intentionally--Missing-Functionality">6.2. (Intentionally) Missing Functionality</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Implementation-Decisions-and-Open-Questions">6.3. Implementation Decisions and Open Questions</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Porting-Code-from-the-Old-Thread-Model">6.4. Porting Code from the Old Thread Model</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Background-Terminal-Input">6.5. Background Terminal Input</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#The-Threads-which-CCL-Uses-for-Its-Own-Purposes">6.6. The Threads which Clozure CL Uses for Its Own Purposes</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Threads-Dictionary">6.7. Threads Dictionary</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Programming-with-Sockets">7. Programming with Sockets</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Sockets-Overview">7.1. Overview</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Sockets-Dictionary">7.2. Sockets Dictionary</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Running-Other-Programs-as-Subprocesses">8. Running Other Programs as Subprocesses</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Subprocess-Overview">8.1. Overview</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Subprocess-Examples">8.2. Examples</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Limitations-and-known-bugs">8.3. Limitations and known bugs</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#External-Program-Dictionary">8.4. External-Program Dictionary</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Streams">9. Streams</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#CCL-Stream-Extensions">9.1. Stream Extensions</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Creating-Your-Own-Stream-Classes-with-Gray-Streams">9.2. Creating Your Own Stream Classes with Gray Streams</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Writing-Portable-Extensions-to-the-Object-System-using-the-MetaObject-Protocol">10. Writing Portable Extensions to the Object System  using the MetaObject Protocol</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#MOP-Overview">10.1. Overview</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#MOP-Implementation-status">10.2. Implementation status</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Concurrency-issues">10.3. Concurrency issues</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Profiling">11. Profiling</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Profiling-Using the Linux oprofile system-level profiler">11.1. Using the Linux oprofile system-level profiler</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Profiling-Using-Apples-CHUD-metering-tools">11.2. Using Apple's CHUD metering tools</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#The-Foreign-Function-Interface">12. The Foreign-Function Interface</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Specifying-And-Using-Foreign-Types">12.1. Specifying And Using Foreign Types</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Foreign-Function-Calls">12.2. Foreign Function Calls</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Referencing-and-Using-Foreign-Memory-Addresses">12.3. Referencing and Using Foreign Memory Addresses</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#The-Interface-Database">12.4. The Interface Database</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Using-Interface-Directories">12.5. Using Interface Directories</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Using-Shared-Libraries">12.6. Using Shared Libraries</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#The-Interface-Translator">12.7. The Interface Translator</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Case-sensitivity-of-foreign-names-in-CCL">12.8. Case-sensitivity of foreign names in <code class="literal">CCL</code></a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Reading-Foreign-Names">12.9. Reading Foreign Names</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Tutorial--Using-Basic-Calls-and-Types">12.10. Tutorial: Using Basic Calls and Types</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap">12.11. Tutorial: Allocating Foreign Data on the Lisp Heap </a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#id445662">12.12. The Foreign-Function-Interface Dictionary</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#The-Objective-C-Bridge">13. The Objective-C Bridge</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Objective-C-Changes-1.2">13.1. Changes in 1.2</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Using-Objective-C-Classes">13.2. Using Objective-C Classes</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Instantiating-Objective-C-Objects">13.3. Instantiating Objective-C Objects</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Calling-Objective-C-Methods">13.4. Calling Objective-C Methods</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Defining-Objective-C-Classes">13.5. Defining Objective-C Classes</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Defining-Objective-C-Methods">13.6. Defining Objective-C Methods</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Loading-Objc-Frameworks">13.7. Loading Frameworks</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#How-Objective-C-Names-are-Mapped-to-Lisp-Symbols">13.8. How Objective-C Names are Mapped to Lisp Symbols</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Platform-specific-notes">14. Platform-specific notes</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Platform-specific-overview">14.1. Overview</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Unix-Posix-Darwin-Features">14.2. Unix/Posix/Darwin Features</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Cocoa-Programming-in-CCL">14.3. Cocoa Programming in Clozure CL</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Building-an-Application-Bundle">14.4. Building an Application Bundle</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Recommended-Reading">14.5. Recommended Reading</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Operating-System-Dictionary">14.6. Operating-System Dictionary</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Understanding-and-Configuring-the-Garbage-Collector">15. Understanding and Configuring the Garbage Collector</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Heap-space-allocation">15.1. Heap space allocation</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#The-Ephemeral-GC">15.2. The Ephemeral GC</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#GC-Page-reclamation-policy">15.3. GC Page reclamation policy</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#iPure--areas-are-read-only--paged-from-image-file">15.4. "Pure" areas are read-only, paged from image file</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Weak-References">15.5. Weak References</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Weak-References-Dictionary">15.6. Weak References Dictionary</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Garbage-Collection-Dictionary">15.7. Garbage-Collection Dictionary</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Implementation-Details-of-CCL">16. Implementation Details of Clozure CL</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Threads-and-exceptions">16.1. Threads and exceptions</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Register-usage-and-tagging">16.2. Register usage and tagging</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Heap-Allocation">16.3. Heap Allocation</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#GC-details">16.4. GC details</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#The-ephemeral-GC">16.5. The ephemeral GC</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Fasl-files">16.6. Fasl files</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#The-Objective-C-Bridge--1-">16.7. The Objective-C Bridge</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Modifying-CCL">17. Modifying Clozure CL</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#Contributing-Code-Back-to-the-CCL-Project">17.1. Contributing Code Back to the Clozure CL Project</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Using-CCL-in--development--and-in--user--mode">17.2. Using Clozure CL in "development" and in  "user" mode</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#kernel-debugger">17.3. The Kernel Debugger</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Using-AltiVec-in-CCL-LAP-functions">17.4. Using AltiVec in Clozure CL LAP functions</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#Development-Mode-Dictionary">17.5. Development-Mode Dictionary</a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="chapter">
+              <a href="#Questions-and-Answers">18. Questions and Answers</a>
+            </span>
+          </dt>
+          <dd>
+            <dl>
+              <dt>
+                <span class="sect1">
+                  <a href="#How-can-I-do-nonblocking--aka--unbuffered--and--raw---IO-">18.1. How can I do nonblocking (aka "unbuffered" and "raw") IO?</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#I-m-using-the-graphics-demos--Why-doesn-t-the-menubar-change-">18.2. I'm using the graphics demos. Why doesn't the menubar
+      change?</a>
+                </span>
+              </dt>
+              <dt>
+                <span class="sect1">
+                  <a href="#I-m-using-Slime-and-Cocoa--Why-doesn-t--standard-output--seem-to-work-">18.3. I'm using Slime and Cocoa. Why doesn't *standard-output*
+      seem to work? </a>
+                </span>
+              </dt>
+            </dl>
+          </dd>
+          <dt>
+            <span class="glossary">
+              <a href="#glossary">Glossary of Terms</a>
+            </span>
+          </dt>
+          <dt>
+            <span class="index">
+              <a href="#Symbol-Index">Symbol Index</a>
+            </span>
+          </dt>
+        </dl>
+      </div>
+      <div class="list-of-tables">
+        <p>
+          <b>List of Tables</b>
+        </p>
+        <dl>
+          <dt>3.1. <a href="#Platform-specific-filename-conventions">Platform-specific filename conventions</a></dt>
+          <dt>4.1. <a href="#Line-Termination-Table">Line Termination Keywords</a></dt>
+        </dl>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="about-ccl"></a>ChapterÂ 1.Â About Clozure CL</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#introduction-to-ccl">1.1. Introduction to Clozure CL</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="introduction-to-ccl"></a>1.1.Â Introduction to Clozure CL</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL is a fast, mature, open source Common Lisp
+      implementation that runs on Linux, Mac OS X and BSD on either
+      Intel x86-64 or PPC. Clozure CL was forked from Macintosh Common
+      Lisp (MCL) in 1998 and the development has been entirely separate
+      since. Ports to IA32 and Windows are under development.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When it was forked from MCL in 1998, the new Lisp was named
+      OpenMCL. Recently, Clozure renamed its Lisp to Clozure CL, partly
+      because its ancestor MCL has lately been released as open
+      source. Clozure thought it might be confusing for users if there
+      were two independent open-source projects with such similar
+      names. The new name also reflects Clozure CL's current status as the
+      flagship product of Clozure Associates.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Furthermore, the new name refers to Clozure CL's ancestry: in its
+      early years, MCL was known as Coral Common Lisp, or "CCL". For
+      years the package that contains most of Clozure CL's
+      implementation-specific symbols has been named "CCL", an acronym
+      that once stood for the name of the Lisp product. It seems
+      fitting that "CCL" once again stands for the name of the
+      product.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Some commands and source files may still refer to "OpenMCL"
+      instead of Clozure CL.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL compiles to native code and supports multithreading
+      using native OS threads. It includes a foreign-function interface,
+      and supports both Lisp code that calls external code, and external
+      code that calls Lisp code. Clozure CL can create standalone executables
+      on all supported platforms.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">On Mac OS X, Clozure CL supports building GUI applications that
+      use OS X's native Cocoa frameworks, and the OS X distributions
+      include an IDE written with Cocoa, and distributed with complete
+      sources.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">On all supported platforms, Clozure CL can run as a command-line
+      process, or as an inferior Emacs process using either SLIME or
+      ILISP.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Features of Clozure CL include</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>Very fast compilation speed.</p>
+              </li>
+              <li>
+                <p>A fast, precise, compacting, generational
+      garbage collector written in hand-optimized C. The sizes of the
+      generations are fully configurable. Typically, a generation can
+      be collected in a millisecond on modern
+      systems.</p>
+              </li>
+              <li>
+                <p>Fast execution speed, competitive with other
+      Common Lisp implementations on most
+      benchmarks.</p>
+              </li>
+              <li>
+                <p>Robust and stable. Customers report that their
+      CPU-intensive, multi-threaded applications run for extended
+      periods on Clozure CL without difficulty.</p>
+              </li>
+              <li>
+                <p>Full native OS threads on all platforms. Threads
+      are automatically distributed across multiple cores. The API
+      includes support for shared memory, locking, and blocking for OS
+      operations such as I/O.</p>
+              </li>
+              <li>
+                <p>Full Unicode support.</p>
+              </li>
+              <li>
+                <p>Full SLIME integration.</p>
+              </li>
+              <li>
+                <p>An IDE on Mac OS X, fully integrated with
+      the Macintosh window system and User Interface
+      standards.</p>
+              </li>
+              <li>
+                <p>Excellent debugging facilities. The names of all
+      local variables are available in a backtrace.</p>
+              </li>
+              <li>
+                <p>A complete, mature foreign function interface,
+      including a powerful bridge to Objective-C and Cocoa on Mac OS
+      X.</p>
+              </li>
+              <li>
+                <p>Many extensions including: files mapped to
+      Common Lisp vectors for fast file I/O; thread-local hash tables
+      and streams to eliminate locking overhead; cons hashing support;
+      and much more</p>
+              </li>
+              <li>
+                <p>Very efficient use of memory</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Although it's an open-source project, available free of
+      charge under a liberal license, Clozure CL is also a fully-supported
+      product of Clozure Associates. Clozure continues to extend,
+      improve, and develop Clozure CL in response to customer and user
+      needs, and offers full support and development services for
+      Clozure CL.</p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="installing"></a>ChapterÂ 2.Â Obtaining, Installing, and Running Clozure CL</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#releases">2.1. Releases and System Requirements</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#linuxppc">2.1.1. LinuxPPC</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#linuxx86">2.1.2. Linux x86</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#freebsdx86">2.1.3. FreeBSD x86</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#macosx">2.1.4. Mac OS X (ppc and x86)</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#obtaining-ccl">2.2. Obtaining Clozure CL</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#obtaining-the-mac-way">2.2.1. The Mac Way</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#obtaining-via-svn">2.2.2. Getting Clozure CL with Subversion</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#obtaining-via-tarballs">2.2.3. Tarballs</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#command-line-setup">2.3. Command Line Set Up</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#The-ccl-Shell-Script">2.3.1. The ccl Shell Script</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Invocation">2.3.2. Invocation</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Personal-Customization-with-the-Init-File">2.4. Personal Customization with the Init File</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Command-Line-Options">2.5. Command Line Options</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Using-CCL-with-GNU-Emacs-and-SLIME">2.6. Using Clozure CL with GNU Emacs and SLIME</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Assumptions-and-Requirements">2.6.1. Assumptions and Requirements</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Getting_Slime">2.6.2. Getting SLIME</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#installing-slime">2.6.3. Installing SLIME</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Telling-Emacs-About-SLIME">2.6.4. Telling Emacs About SLIME</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Running-CCL-with-SLIME">2.6.5. Running Clozure CL with SLIME</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#What-if-a-New-Version-of-CCL-Breaks-SLIME-">2.6.6. What if a New Version of Clozure CL Breaks SLIME?</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Known-Bugs">2.6.7. Known Bugs</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Example-Programs">2.7. Example Programs</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="releases"></a>2.1.Â Releases and System Requirements</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Version 1.3 is the latest stable release of Clozure CL as of April
+    2009.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Version 1.3 is available for seven platform configurations:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>Linux on PowerPC (32-bit and 64-bit implementations)</p>
+              </li>
+              <li>
+                <p>Mac OS X on PowerPC (32-bit and 64-bit implementations)</p>
+              </li>
+              <li>
+                <p>Linux on x86 (32-bit and 64-bit implementations)</p>
+              </li>
+              <li>
+                <p>Mac OS X on x86 (32-bit and 64-bit implementations)</p>
+              </li>
+              <li>
+                <p>FreeBSD on x86 (32-bit and 64-bit implementations)</p>
+              </li>
+              <li>
+                <p>Solaris on x86 (32-bit and 64-bit implementations)</p>
+              </li>
+              <li>
+                <p>MS Windows XP and later on x86 (32-bit and 64-bit implementations)</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">A 64-bit version of Clozure CL requires a 64-bit processor
+      running a 64-bit OS variant.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Additional platform-specific information is given in the
+      following subsections.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Older versions are still available for downloading as
+    tarballs.  Version 1.0 was a stable version released in late 2005.
+    Version 1.1 was under active development until late 2007.  A final
+    1.1 release was never made.  It was distributed as a series of
+    development "snapshots" and CVS updates.  1.1 snapshots introduced
+    support for x86-64 platforms, internal use of Unicode, and many
+    other features, but were moving targets.  Version 1.2 was a stable
+    version released in April 2008.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="linuxppc"></a>2.1.1.Â LinuxPPC</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL requires version 2.2.13 (or later) of the Linux
+      kernel and version 2.1.3 (or later) of the GNU C library (glibc)
+      at a bare minimum.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="linuxx86"></a>2.1.2.Â Linux x86</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	Because of the nature of Linux distributions, it's difficult
+	to give precise version number requirements.  In general, a
+	"fairly modern" (no more than 2 or three years old) kernel and
+	C library are more likely to work well than older
+	versions.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="freebsdx86"></a>2.1.3.Â FreeBSD x86</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL should run on
+    FreeBSD 6.x and 7.x.
+    FreeBSD 7 users will need to install the "compat6x" package in order to use
+    the distributed Clozure CL kernel, which is built on a FreeBSD 6.x system.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="macosx"></a>2.1.4.Â Mac OS X (ppc and x86)</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"> Clozure CL runs under Mac OS X versions 10.4 and 10.5.
+      </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">64-bit versions of Clozure CL require 64-bit processors
+      (e.g., a G5 or Core 2 processor).  Some early Intel-based Macintoshes
+      used processors that don't support
+      64-bit operation, so the 64-bit Clozure CL will not run on them, although
+      the 32-bit Clozure CL will.
+      </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL hasn't been tested under Darwin proper, but
+        Clozure CL doesn't intentionally use any Mac OS X features beyond
+        the Darwin subset and therefore it seems likely that Clozure CL
+        would run on Darwin versions that correspond to recent Mac OS X
+        versions.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="obtaining-ccl"></a>2.2.Â Obtaining Clozure CL</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">There two main ways to obtain Clozure CL.  For Mac OS X,
+    there are disk images that can be used to install Clozure CL in
+    the usual Macintosh way. For other OSes, Subversion is the best
+    way to obtain Clozure CL.  Mac OS X users can also use Subversion
+    if they prefer. Tarballs are available for those who prefer them,
+    but if you have Subversion installed, it is simpler and more
+    flexible to use Subversion than tarballs.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml"> There are three popular ways to use Clozure CL: as a
+      stand-alone double-clickable application (Mac OS X only), as a
+      command-line application, or with EMACS and SLIME. The following
+      sections describe these options.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="obtaining-the-mac-way"></a>2.2.1.Â The Mac Way</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">If you are using Mac OS X then you can install and use
+         Clozure CL in the usual Macintosh way.  Download and mount a
+         disk image, then drag the ccl folder to the Applications folder
+	 or wherever you wish.
+         After that you can double-click the Clozure CL application found
+	 inside the ccl directory.  The disk images are available at
+         <a class="ulink" href="ftp://clozure.com/pub/release/1.3/" target="_top">ftp://clozure.com/pub/release/1.3/</a> </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">So that Clozure CL can locate its source code, and for other
+        reasons explained in
+        <a class="xref" href="#Predefined-Logical-Hosts" title="4.4.2.Â Predefined Logical Hosts">SectionÂ 4.4.2, âPredefined Logical Hostsâ</a>, you keep the
+        Clozure CL application
+        in the <code class="literal">ccl</code> directory.  If you use a shell,
+        you can set the value of the
+        <em class="varname">CCL_DEFAULT_DIRECTORY</em> environment variable
+        to explicitly indicate the location of
+        the <code class="literal">ccl</code> directory. If you choose to do
+        that, then the <code class="literal">ccl</code> directory and the Clozure CL
+        application can each be in any location you find
+        convenient.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="obtaining-via-svn"></a>2.2.2.Â Getting Clozure CL with Subversion</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">It is very easy to download, install, and build Clozure CL
+      using Subversion. This is the preferred way to get either the
+      latest, or a specific version of Clozure CL, unless you prefer
+      the Mac Way.  Subversion is a source code control system that is
+      in wide usage.  Most modern OSes come with Subversion
+      pre-installed. A complete, buildable and runnable set of Clozure CL
+      sources and binaries can be retrieved with a single Subversion command.
+      </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Day-to-day development of Clozure CL takes place in an area
+      of the Subversion repository known as the trunk.  At most times,
+      the trunk is perfectly usable, but occasionally it can be unstable
+      or totally broken.  If you wish to live on the 
+      bleeding edge, the following command will fetch a copy of the trunk
+      for Darwin x86 (both 32- and 64-bit versions):
+      </p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          
+svn co http://svn.clozure.com/publicsvn/openmcl/trunk/darwinx86/ccl
+        </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	  To get a trunk Clozure CL for another platform, replace
+	  "darwinx86" with one of the following names (all versions
+	  include both 32- and 64-bit binaries):
+	</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>darwinx86</p>
+                </li>
+                <li>
+                  <p>linuxx86</p>
+                </li>
+                <li>
+                  <p>freebsdx86</p>
+                </li>
+                <li>
+                  <p>solarisx86</p>
+                </li>
+                <li>
+                  <p>windows</p>
+                </li>
+                <li>
+                  <p>linuxppc</p>
+                </li>
+                <li>
+                  <p>darwinppc</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Release versions of Clozure CL are intended to be stable.  While
+	bugs will be fixed in the release branches, enhancements
+	and new features will go into the trunk.  To get the 1.3 release
+	of Clozure CL type:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          
+svn co http://svn.clozure.com/publicsvn/openmcl/release/1.3/darwinx86/ccl
+        </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">The above command will fetch the complete sources and binaries
+        for the Darwin x86 build of Clozure CL. To get a Clozure CL for another platform,
+	replace "darwinx86" with one of the following names (all versions
+	include both 32- and 64-bit binaries):</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>darwinx86</p>
+                </li>
+                <li>
+                  <p>linuxx86</p>
+                </li>
+                <li>
+                  <p>freebsdx86</p>
+                </li>
+                <li>
+                  <p>solarisx86</p>
+                </li>
+                <li>
+                  <p>windows</p>
+                </li>
+                <li>
+                  <p>linuxppc</p>
+                </li>
+                <li>
+                  <p>darwinppc</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">These distributions contain complete sources and
+        binaries. They use Subversion's "externals" features to share
+        common sources; the majority of source code is the same across
+        all versions.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Once the checkout is complete you can build Clozure CL by
+        running the lisp kernel and executing
+        the <code class="literal">rebuild-ccl</code> function. For
+        example:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          
+joe:ccl&gt; ./dx86cl64
+Welcome to Clozure Common Lisp Version 1.2  (DarwinX8664)!
+? (rebuild-ccl :full t)
+
+&lt;lots of compilation output&gt;
+
+  ? (quit)
+  joe:ccl&gt;
+        </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	  If you don't have a C compiler toolchain installed, the
+	  <code class="literal">rebuild-ccl</code> will not work.  Please
+	  refer to <a class="xref" href="#building-ccl-from-source" title="ChapterÂ 3.Â Building Clozure CL from its Source Code">ChapterÂ 3, <i>Building Clozure CL from its Source Code</i></a> for
+	  addtional details.
+	</p>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Checking-Subversion-Installation"></a>2.2.2.1.Â Checking Subversion Installation</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">If <code class="literal">svn co</code> doesn't work, then make sure
+      that Subversion is installed on your system.  Bring up a command
+      line shell and type:
+        </p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          
+shell&gt; svn
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml"> 
+        If Subversion is installed, you will see something like:
+        </p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          
+Type 'svn help' for usage
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+        If Subversion is not installed, you will see something
+        like:
+        </p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          
+-bash: svn: command not found
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+        If Subversion is not installed, you'll need to figure out how
+        to install it on your OS. You can find information about
+        obtaining and installing Subversion at
+        the <a class="ulink" href="http://subversion.tigris.org/project_packages.html" target="_top">Subversion
+        Packages page</a>.</p>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="obtaining-via-tarballs"></a>2.2.3.Â Tarballs</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Tarballs are available at <a class="ulink" href="ftp://clozure.com/pub/release/1.3/" target="_top">ftp://clozure.com/pub/release/1.3/</a>.  Download and extract
+      one on your local disk.  Then edit the Clozure CL shell script to set
+      the value of <em class="varname">CCL_DEFAULT_DIRECTORY</em> and start
+      up the appropriate Clozure CL kernel. See <a class="xref" href="#The-ccl-Shell-Script" title="2.3.1.Â The ccl Shell Script">SectionÂ 2.3.1, âThe ccl Shell Scriptâ</a> for more information about the
+      Clozure CL shell scripts.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="command-line-setup"></a>2.3.Â Command Line Set Up</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Sometimes it's convenient to use Clozure CL from a Unix
+      shell command line.  This is especially true when using Clozure CL
+      as a way to run Common Lisp utilities.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="The-ccl-Shell-Script"></a>2.3.1.Â The ccl Shell Script</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL needs to be able to find the
+        <code class="literal">ccl</code> directory in order to support features
+        such as <code class="literal">require</code> and
+        <code class="literal">provide</code>, access to foreign interface
+        information (see <a class="link" href="#The-Interface-Database" title="12.4.Â The Interface Database">The
+        Interface Database</a>) and the Lisp build process (see
+        <a class="link" href="#Building-CCL">Building Clozure CL from its Source
+        Code</a>). Specifically, it needs to set up logical
+        pathname translations for the <code class="literal">"ccl:"</code>
+        logical host.  If this logical host isn't defined (or isn't
+        defined correctly), some things might work, some things might
+        not, and it'll generally be hard to invoke and use Clozure CL
+        productively.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL uses the value of the environment variable
+        <code class="literal">CCL_DEFAULT_DIRECTORY</code> to determine the
+        filesystem location of the <code class="literal">ccl</code> directory;
+        the ccl shell script is intended to provide a way to
+        invoke Clozure CL with that environment variable set
+        correctly.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">There are two versions of the shell script:
+        <code class="literal">"ccl/scripts/ccl"</code> is used to invoke
+        32-bit implementations of Clozure CL and
+        <code class="literal">"ccl/scripts/ccl64"</code> is used to invoke
+        64-bit implementations.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">To use the script:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>Copy the script to a directory that is on your
+	  <em class="varname">PATH</em>.  This is often
+	  <code class="literal">/usr/local/bin</code> or
+	  <code class="literal">~/bin</code>.  It is better to do this than to
+	  add <code class="literal">ccl/scripts</code> to your
+	  <em class="varname">PATH</em>, because the script needs to be edited,
+	  and editing it in-place means that Subversion sees the script as
+	  modified..</p>
+                </li>
+                <li>
+                  <p>Edit the definition of
+            <code class="literal">CCL_DEFAULT_DIRECTORY</code> near the
+            beginning of the shell script so that it refers to
+            your <code class="literal">ccl</code> directory.  Alternately, set
+            the value of the <code class="literal">CCL_DEFAULT_DIRECTORY</code>
+            environment variable in your .cshrc, .tcshrc,
+            .bashrc,.bash_profile, .MacOSX/environment.plist, or
+            wherever you usually set environment variables.  If there
+            is an existing definition of the variable, the ccl
+            script will not override it. The shell script sets a local
+            variable (<code class="literal">OPENMCL_KERNEL</code>) to the
+            standard name of the Clozure CL kernel approprate for the
+            platform, as determined by 'uname -s'. You might prefer to
+            set this variable manually in the shell script.</p>
+                </li>
+                <li>
+                  <p>Ensure that the shell script is executable, for
+            example:</p>
+                  <p>
+                    <code class="literal">$ chmod +x
+            ~/ccl/ccl/scripts/ccl64</code>
+                  </p>
+                  <p>This command grants execute permission to the named
+            script. If you are using a 32-bit platform, substitute
+            "ccl" in place of "ccl64".
+            </p>
+                  <div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+                    <h3 class="title">Warning</h3>
+                    <p>The above command won't work if you are not the
+	            owner of the installed copy of Clozure CL. In that case,
+	            you can use the "sudo" command like this:</p>
+                    <p>
+                      <code class="literal">$ sudo chmod +x
+                  ~/ccl/ccl/scripts/ccl64</code>
+                    </p>
+                    <p>Give your password when prompted.</p>
+                    <p>If the "sudo" command doesn't work, then you are
+                not an administrator on the system you're using, and you
+                don't have the appropriate "sudo" permissions. In that
+                case you'll need to get help from the system's
+                administrator.</p>
+                  </div>
+                </li>
+              </ol>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that most people won't need both
+      <code class="literal">ccl</code> and <code class="literal">ccl64</code> scripts.
+      You only need both if you sometimes run 32-bit Clozure CL and
+      sometimes run 64-bit Clozure CL.  You can rename the script that
+      you use to whatever you want.  For example, if you are on a
+      64-bit system, and you only use Clozure CL in 64-bit mode, then
+      you can rename  <code class="literal">ccl64</code> to
+      <code class="literal">ccl</code> so that you only need to type
+      "<code class="literal">ccl</code>" to run it.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Once this is done, it should be possible to invoke Clozure CL
+        by typing <code class="literal">ccl</code>
+        or <code class="literal">ccl64</code> at a shell prompt:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+&gt; ccl [args ...]
+Welcome to Clozure CL Version 1.2 (DarwinPPC32)!
+?
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">The ccl shell script passes all of its arguments to the
+      Clozure CL kernel.  See <a class="xref" href="#Invocation" title="2.3.2.Â Invocation">SectionÂ 2.3.2, âInvocationâ</a> for more
+      information about these arguments.  When invoked this way, the
+      Lisp should be able to initialize the <code class="literal">"ccl:"</code>
+      logical host so that its translations refer to the
+      <code class="literal">"ccl"</code> directory. To test this, you can call
+      <code class="literal">probe-file</code> in Clozure CL's read-eval-print
+      loop:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (probe-file "ccl:level-1;level-1.lisp")  ;returns the physical pathname of the file
+#P"/Users/alms/my_lisp_stuff/ccl/level-1/level-1.lisp"
+      </pre>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Invocation"></a>2.3.2.Â Invocation</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Assuming that the shell script is properly installed, it can be used to invoke Clozure CL from a shell prompt:
+	    </p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+shell&gt;<em class="replaceable"><code>ccl</code></em> <span class="emphasis"><em>args</em></span>
+	    </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	    <code class="literal">ccl</code> runs a 32-bit session;
+	    <code class="literal">ccl64</code> runs a 64-bit session.
+	  </p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Personal-Customization-with-the-Init-File"></a>2.4.Â Personal Customization with the Init File</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">By default Clozure CL tries to load the file
+      <code class="literal">"home:ccl-init.lisp"</code> or the compiled
+      <code class="literal">"home:ccl-init.fasl"</code> upon starting up.
+      Clozure CL does this by executing <code class="literal">(load
+      "home:ccl-init")</code>.  If it's unable to load the file
+      (for example because the file doesn't exist), Clozure CL doesn't
+      signal an error or warning, it just completes its startup
+      normally.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      On Unix systems, if <code class="literal">"ccl-init.lisp"</code> is not
+      present, Clozure CL will look for <code class="literal">".ccl-init.lisp"</code>
+      (post 1.2 versions only).
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The <code class="literal">"home:"</code> prefix to the filename is a
+      Common Lisp logical host, which Clozure CL initializes to refer to
+      your home directory. Clozure CL therefore looks for either of the
+      files
+      <code class="literal">~/ccl-init.lisp</code> or
+      <code class="literal">~/ccl-init.fasl</code>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Because the init file is loaded the same way as normal Lisp
+      code is, you can put anything you want in it.  For example, you
+      can change the working directory, and load packages that you use
+      frequently.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">To suppress the loading of this init-file, invoke Clozure CL with the
+      <code class="literal">--no-init</code> option.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Command-Line-Options"></a>2.5.Â Command Line Options</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">When using Clozure CL from the command line, the following
+      options may be used to modify its behavior.  The exact set of
+      Clozure CL command-line arguments may vary per platform and
+      slowly changes over time.  The current set of command line
+      options may be retrieved by using the
+      <code class="literal">--help</code> option.</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p><code class="literal">-h</code> (or
+	      <code class="literal">--help</code>).  Provides a definitive (if
+	      somewhat terse) summary of the command line options
+	      accepted by the Clozure CL implementation and then
+	      exits.</p>
+              </li>
+              <li>
+                <p><code class="literal">-V</code> (or
+	      <code class="literal">--version</code>).  Prints the version of
+	      Clozure CL then exits.  The version string is the same value
+	      that is returned by
+	      <span class="function"><strong>LISP-IMPLEMENTATION-VERSION</strong></span>.</p>
+              </li>
+              <li>
+                <p><code class="literal">-K</code>
+	      <em class="parameter"><code>character-encoding-name</code></em> (or
+	      <code class="literal">--terminal-encoding</code>
+	      <em class="parameter"><code>character-encoding-name</code></em>).
+	      Specifies the character encoding to use for
+	      <em class="varname">*TERMINAL-IO*</em> (see <a class="xref" href="#Character-Encodings" title="4.3.4.Â Character Encodings">SectionÂ 4.3.4, âCharacter Encodingsâ</a>).  Specifically, the
+	      <em class="parameter"><code>character-encoding-name</code></em> string
+	      is uppercased and interned in the KEYWORD package. If an
+	      encoding named by that keyword exists,
+	      <em class="varname">CCL:*TERMINAL-CHARACTER-ENCODING-NAME*</em> is set to the name
+	      of that encoding.   <em class="varname">CCL:*TERMINAL-CHARACTER-ENCODING-NAME*</em> defaults to <code class="literal">NIL</code>, which
+	      is a synonym for <code class="literal">:ISO-8859-1</code>.</p>
+                <p>For example:
+	      </p>
+                <pre class="programlisting">
+shell&gt; ccl -K utf-8
+	      </pre>
+                <p>
+	      has the effect of making the standard CL streams use
+	      <code class="literal">:UTF-8</code> as their character
+	      encoding.</p>
+              </li>
+              <li>
+                <p><code class="literal">-n</code> (or
+	      <code class="literal">--no-init</code>). If this option is given, the
+	      init file is not loaded.  This is useful if Clozure CL is being
+	      invoked by a shell script that should not be affected by
+	      whatever customizations a user might have in place.</p>
+              </li>
+              <li>
+                <p><code class="literal">-e</code> <em class="parameter"><code>form</code></em>
+	      (or <code class="literal">--eval</code>). An expression is read (via
+	      <span class="function"><strong>READ-FROM-STRING</strong></span>) from the string
+	      <em class="parameter"><code>form</code></em> and evaluated. If
+	      <em class="parameter"><code>form</code></em> contains shell metacharacters,
+	      it may be necessary to escape or quote them to prevent the
+	      shell from interpreting them.</p>
+              </li>
+              <li>
+                <p><code class="literal">-l</code> <em class="parameter"><code>path</code></em>
+	      (or <code class="literal">--load</code>
+	      <em class="parameter"><code>path</code></em>). Loads file specified by
+	      <em class="parameter"><code>path</code></em>.</p>
+              </li>
+              <li>
+                <p><code class="literal">-T</code> <em class="parameter"><code>n</code></em> (or
+	      <code class="literal">--set-lisp-heap-gc-threshold</code>
+	      <em class="parameter"><code>n</code></em>).  Sets the Lisp gc threshold to
+	      <em class="parameter"><code>n</code></em>. (see <a class="xref" href="#GC-Page-reclamation-policy" title="15.3.Â GC Page reclamation policy">SectionÂ 15.3, âGC Page reclamation policyâ</a></p>
+              </li>
+              <li>
+                <p><code class="literal">-Q</code> (or
+	      <code class="literal">--quiet</code>). Suppresses printing of
+	      heralds and prompts when the <code class="literal">--batch</code>
+	      command line option is specified.</p>
+              </li>
+              <li>
+                <p><code class="literal">-R</code> <em class="parameter"><code>n</code></em> (or
+	      <code class="literal">--heap-reserve</code>). Reserves
+	      <em class="parameter"><code>n</code></em> bytes for heap expansion.  The
+	      default is <code class="literal"> 549755813888</code>.  (see <a class="xref" href="#Heap-space-allocation" title="15.1.Â Heap space allocation">SectionÂ 15.1, âHeap space allocationâ</a>)</p>
+              </li>
+              <li>
+                <p><code class="literal">-S</code> <em class="parameter"><code>n</code></em> (or
+	      <code class="literal">--stack-size</code> <em class="parameter"><code>n</code></em>). Sets the size of the
+	      initial control stack to <em class="parameter"><code>n</code></em>. (see <a class="xref" href="#Thread-Stack-Sizes" title="6.3.1.Â Thread Stack Sizes">SectionÂ 6.3.1, âThread Stack Sizesâ</a>)</p>
+              </li>
+              <li>
+                <p><code class="literal">-Z</code> <em class="parameter"><code>n</code></em> (or
+	      <code class="literal">--thread-stack-size</code>
+	      <em class="parameter"><code>n</code></em>). Sets the size of the first
+	      thread's stack to <em class="parameter"><code>n</code></em>. (see <a class="xref" href="#Thread-Stack-Sizes" title="6.3.1.Â Thread Stack Sizes">SectionÂ 6.3.1, âThread Stack Sizesâ</a>)</p>
+              </li>
+              <li>
+                <p><code class="literal">-b</code> (or <code class="literal">--batch</code>). Execute in "batch mode". End-of-file
+	      from <em class="varname">*STANDARD-INPUT*</em> causes Clozure CL to exit, as do attempts to
+	      enter a break loop.</p>
+              </li>
+              <li>
+                <p><code class="literal">--no-sigtrap</code> An obscure option for running under GDB.</p>
+              </li>
+              <li>
+                <p><code class="literal">-I</code>
+	      <em class="parameter"><code>image-name</code></em> (or
+	      <code class="literal">--image-name</code>
+	      <em class="parameter"><code>image-name</code></em>). Specifies the image
+	      name for the kernel to load.  Defaults to the kernel name
+	      with ".image" appended.</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The <code class="literal">--load</code> and
+      <code class="literal">--eval</code> options can each be provided
+      multiple times.  They're executed in the order specified on
+      the command line, after the init file (if there is one) is
+      loaded and before the toplevel read-eval-print loop is
+      entered.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Using-CCL-with-GNU-Emacs-and-SLIME"></a>2.6.Â Using Clozure CL with GNU Emacs and SLIME</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">A very common way to use Clozure CL is to run it within the
+      GNU Emacs editor, using a Lisp interface called SLIME ("Superior
+      Lisp Interaction Mode for Emacs"). SLIME is an Emacs package
+      designed to provide good support within Emacs for any of several
+      Common Lisp implementations; one of the supported
+      implementations is Clozure CL. This page describes how you can
+      download SLIME and set it up to work with your Clozure CL
+      installation.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Why use SLIME? With SLIME, you can do the following things from within
+      an Emacs editing session:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>run and control Lisp</p>
+              </li>
+              <li>
+                <p>evaluate, compile, and load files or expressions</p>
+              </li>
+              <li>
+                <p>macroexpand expressions</p>
+              </li>
+              <li>
+                <p>fetch documentation and source code for Lisp symbols</p>
+              </li>
+              <li>
+                <p>autocomplete symbols and package names</p>
+              </li>
+              <li>
+                <p>cross-reference function calls</p>
+              </li>
+              <li>
+                <p>examine stack traces and debug errors</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">For complete information about SLIME, see the
+      SLIME <a class="ulink" href="http://common-lisp.net/project/slime/" target="_top">home
+      page</a>. The SLIME home page provides up-to-date downloads,
+      plus documentation, tutorials, and instructional
+      screencasts.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Assumptions-and-Requirements"></a>2.6.1.Â Assumptions and Requirements</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">In order to simplify these instructions, we'll make
+        several assumptions about your system. Specifically, we
+        assume:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>You have a working installation of GNU Emacs. If you
+	        don't have a working copy of GNU Emacs, see the web page on
+	        <a class="ulink" href="http://www.gnu.org/software/emacs/#Obtaining" target="_top">obtaining
+	        Emacs</a>.  If you prefer to use XEmacs instead of GNU
+	        Emacs, these instructions should still work; SLIME supports
+	        XEmacs Version21. Mac OS X includes an Emacs installation.
+	        If you want to look into different versions, you can check
+	        out theEmacsWiki, which maintains a
+	        page, EmacsForMacOS, that provides much more information
+	        about using Emacs on the Mac.</p>
+                  <p>A popular version of Emacs among Mac users is
+            <a class="ulink" href="http://aquamacs.org/" target="_top">Aquamacs</a>. This
+            application is a version of GNU Emacs with a number of
+            customizations meant to make it behave more like a
+            standard Macintosh application, with windows, a menubar,
+            etc.  Aquamacs includes SLIME; if you like Aquamacs then
+            you can use SLIME right away, without getting and
+            installing it separately. You just need to tell SLIME
+            where to find your installation of Clozure CL.</p>
+                </li>
+                <li>
+                  <p>You have a working copy of Clozure CL, installed in
+            <code class="literal">"~/ccl"</code>If you prefer to install
+            Clozure CL in some directory other
+            than<code class="literal">"~/ccl"</code> then these
+            instructions still work, but you must remember to use your
+            path to your ccl directory instead of the one that we give
+            here.</p>
+                </li>
+                <li>
+                  <p>You install emacs add-ons in the folder
+            <code class="literal">"~/emacs/site/"</code>If this directory
+            doesn't exist on your system, you can just create it.If
+            you prefer to install Emacs add-ons in some place other
+            than<code class="literal">"~/emacs/site/"</code> then you must
+            remember to use your path to Emacs add-ons in place of
+            ours.</p>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Getting_Slime"></a>2.6.2.Â Getting SLIME</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">You can get SLIME from the SLIME Home Page. Stable
+        releases and CVS snapshots are available as archive files, or
+        you can follow the instructions on the SLIME Home Page to
+        check out the latest version from their CVS repository.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's worth noting that stable SLIME releases happen very
+        seldom, but the SLIME developers often make changes and
+        improvements that are available through CVS updates. If you
+        asked the SLIM developers, they would most likely recommend
+        that you get SLIME from their CVS repository and update it
+        frequently.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Whether you get it from CVS, or download and unpack one
+        of the available archives, you should end up with a folder
+        named "slime" that contains the SLIME distribution.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="installing-slime"></a>2.6.3.Â Installing SLIME</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Once you have the "slime" folder described in the previous
+        section, installation is a simple matter of copying the folder
+        to the proper place. You can drag it into the "~/emacs/site/"
+        folder, or you can use a terminal command to copy it
+        there. For example, assuming your working directory contains
+        the unpacked "slime" folder:</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+              <code class="literal">$ cp -R
+        slime ~/emacs/site/</code>
+            </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">That's all it
+        takes.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Telling-Emacs-About-SLIME"></a>2.6.4.Â Telling Emacs About SLIME</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"> Once SLIME and Clozure CL are installed, you just need to
+        add a line to your "~/.emacs" file that tells SLIME where to
+        find the script that runs Clozure CL:</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+              <code class="literal">(setq inferior-lisp-program "~/ccl/scripts/ccl64")</code>
+            </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">or</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+              <code class="literal">(setq inferior-lisp-program "~/ccl/scripts/ccl")</code>
+            </p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+              <h3 class="title">Warning</h3>
+              <p>Aquamacs users should add this line to the file "~/Library/Preferences/Aquamacs Emacs/Preferences.el".</p>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Running-CCL-with-SLIME"></a>2.6.5.Â Running Clozure CL with SLIME</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Once the preparations in the previous section are
+        complete, exit Emacs and restart it, to ensure that it reads
+        the changes you made in your ".emacs" file (alternatively, you
+        could tell Emacs to reload the ".emacs" file). If all went
+        well, you should now be ready to run Clozure CL using
+        SLIME.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">To run Clozure CL, execute the command "M-x slime". SLIME
+        should start an Clozure CL session in a new buffer.  (If you are
+        unfamiliar with the Emacs notation "M-x command", see the GNU
+        Emacs FAQ; specifically, take a look at questions 1, 2, and
+        128.)</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="What-if-a-New-Version-of-CCL-Breaks-SLIME-"></a>2.6.6.Â What if a New Version of Clozure CL Breaks SLIME?</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Sometimes you'll get a new version of Clozure CL, set up
+	    Emacs to use it with SLIME, and SLIME will fail. Most likely
+	    what has happened is that the new version of Clozure CL has a
+	    change in the output files produced by the compiler (Clozure CL
+	    developers will say "the fasl version has changed." fasl
+	    stands for "fast load" aka compiled files). This
+	    problem is easy to fix: just delete the existing SLIME fasl
+	    files. The next time you launch Emacs and start SLIME, it will
+	    automatically recompile the Lisp files, and that should fix
+	    the problem.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">SLIME's load process stores its fasl files in a hidden
+        folder inside your home folder. The path is</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+              <code class="literal">~/.slime/fasl</code>
+            </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">You can use a shell command to remove the fasl files, or
+        remove them using your system's file browser.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><span class="bold"><strong>Note for Macintosh Users:</strong></span> 
+	    The leading "." character in the ".slime" folder's name
+	    prevents the Finder from showing this folder to you. If you
+	    use the "Go To Folder" menu item in the Finder's "Go" menu,
+	    you can type in "~/.slime" and the Finder will show it to
+	    you. You can then drag the "fasl" folder to the trash.
+	  </p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Known-Bugs"></a>2.6.7.Â Known Bugs</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">SLIME has not been updated to account for recent changes
+	    made in Clozure CL to support x86-64 processors. You may run into
+	    bugs running on those platforms.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The SLIME backtrace sometimes shows incorrect information.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">return-from-frame</code> and
+        <code class="literal">apply-in-frame</code> do not work reliably.  (If
+        they work at all, it's pure luck.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Some versions of Emacs on the Macintosh may have trouble
+        finding the shell script that runs Clozure CL unless you specify
+        a full path to it. See the above section "Telling Emacs About
+        SLIME" to learn how to specify the path to the shell
+        script.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">For more help with Clozure CL on Mac OS X, consult the Clozure CL
+        mailing lists. You can find information about the mailing
+        lists on the
+        Clozure CL <a class="ulink" href="http://trac.clozure.com/openmcl" target="_top">wiki</a>.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Example-Programs"></a>2.7.Â Example Programs</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">A number (ok, a <span class="emphasis"><em>small</em></span> number), of
+    example programs are distributed in the "ccl:examples;" directory
+    of the source distribution. See the README-OPENMCL-EXAMPLES text
+    file in that directory for information about prerequisites and
+    usage.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Some of the example programs are derived from C examples
+      in textbooks, etc.; in those cases, the original author and work
+      are cited in the source code.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Unless the original author or contributor claims other
+      rights, you're free to incorporate any of this example code or
+      derivative thereof in any of your own works without
+      restriction. In doing so, you agree that the code was provided
+      "as is", and that no other party is legally or otherwise
+      responsible for any consequences of your decision to use
+      it.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you've developed Clozure CL examples that you'd like to see
+      added to the distribution, please send mail to the Clozure CL mailing
+      lists. Any such contributions would be welcome and appreciated
+      (as would bug fixes and improvements to the existing
+      examples.)</p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="building-ccl-from-source"></a>ChapterÂ 3.Â Building Clozure CL from its Source Code</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#building-definitions">3.1. Building Definitions</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#filename_conventions">3.1.1. Platform-specific filename conventions</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Setting-Up-to-Build">3.2. Setting Up to Build</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Building-Everything">3.3. Building Everything</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Building-the-kernel">3.4. Building the kernel</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Kernel-build-prerequisites">3.4.1. Kernel build prerequisites</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#kernel-build-command">3.4.2. Using "make" to build the lisp kernel</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Building-the-heap-image">3.5. Building the heap image</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Development-cycle">3.5.1. Development cycle</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Generating-a-bootstrapping-image">3.5.2. Generating a bootstrapping image</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Generating-fasl-files">3.5.3. Generating fasl files</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Building-a-full-image-from-a-bootstrapping-image">3.5.4. Building a full image from a bootstrapping image</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+          </dl>
+        </div>
+        <a xmlns="http://www.w3.org/1999/xhtml" id="Building-CCL"></a>
+        <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL, like many other Lisp implementations, consists of a
+    kernel and a heap image.  The kernel is an ordinary C program, and
+    is built with a C compiler.  It provides very basic and
+    fundamental facilities, such as memory management, garbage
+    collection, and bootstrapping.  All the higher-level features are
+    written in Lisp, and compiled into the heap image.  Both parts are
+    needed to have a working Lisp implementation; neither the kernel
+    nor the heap image can stand alone.</p>
+        <p xmlns="http://www.w3.org/1999/xhtml">You may already know that, when you have a C compiler which
+    is written in C, you need a working C compiler to build the
+    compiler. Similarly, the Clozure CL heap image includes a Lisp
+    compiler, which is written in Lisp. You therefore need a working
+    Lisp compiler in order to build the Lisp heap image.</p>
+        <p xmlns="http://www.w3.org/1999/xhtml">Where will you get a working Lisp compiler?  No worries; you
+    can use a precompiled copy of a (slightly older and compatible)
+    version of Clozure CL. This section explains how to do all this.</p>
+        <p xmlns="http://www.w3.org/1999/xhtml">In principle it should be possible to use another
+    implementation of Common Lisp as the host compiler, rather than an
+    older Clozure CL; this would be a challenging and experimental way to
+    build, and is not described here.</p>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="building-definitions"></a>3.1.Â Building Definitions</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The following terms are used in subsequent sections; it
+      may be helpful to refer to these definitions.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml"><a id="id382026" class="indexterm"></a><a class="glossterm" href="#fasl-file"><em class="glossterm">fasl
+        files</em></a> are the object files produced
+      by <code class="literal">compile-file</code>.  fasl files store the
+      machine code associated with function definitions and the
+      external representation of other lisp objects in a compact,
+      machine-readable form. fasl is short for
+      â<code class="literal">FAS</code>t
+      <code class="literal">L</code>oadingâ. Clozure CL uses different pathname
+      types (extensions) to name fasl files on different platforms;
+      see
+      <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a> </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The <a id="id369884" class="indexterm"></a> <a class="glossterm" href="#lisp_kernel"><em class="glossterm">Lisp
+        kernel</em></a> is a C program with a fair amount of
+      platform-specific assembly language code. Its basic job is to
+      map a lisp heap image into memory, transfer control to some
+      compiled lisp code that the image contains, handle any
+      exceptions that occur during the execution of that lisp code,
+      and provide various other forms of runtime support for that
+      code. Clozure CL uses different filenames to name the lisp kernel
+      files on different platforms; see
+      <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">A <a id="id359442" class="indexterm"></a> <a class="glossterm" href="#lisp_image"><em class="glossterm">heap
+        image</em></a> is a file that can be quickly mapped into a
+      process's address space. Conceptually, it's not too different
+      from an executable file or shared library in the OS's native
+      format (ELF or Mach-O/dyld format); for historical reasons,
+      Clozure CL's own heap images are in their own (fairly simple)
+      format. The term <code class="literal">full heap image</code> refers to a
+      heap image file that contains all of the code and data that
+      comprise Clozure CL. Clozure CL uses different filenames to name the
+      standard full heap image files on different platforms; see
+      <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">A <a id="id383160" class="indexterm"></a> bootstrapping image is a minimal
+      heap image used in the process of building Clozure CL itself.  The
+      bootstrapping image contains just enough code to load the rest
+      of Clozure CL from fasl files.  It may help to think of the
+      bootstrapping image as the egg and the full heap image as the
+      chicken. Clozure CL uses different filenames to name the standard
+      bootstrapping image files on different platforms; see
+      <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a>
+      .</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Each supported platform (and possibly a few
+      as-yet-unsupported ones) has a uniquely named subdirectory of
+      <code class="literal">ccl/lisp-kernel/</code>; each such
+      <a id="id383185" class="indexterm"></a>
+      contains a Makefile and may contain some auxiliary files (linker
+      scripts, etc.) that are used to build the lisp kernel on a
+      particular platform.The platform-specific name of the kernel
+      build directory is described in
+      <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a>.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="filename_conventions"></a>3.1.1.Â Platform-specific filename conventions</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="table">
+              <a id="Platform-specific-filename-conventions"></a>
+              <p class="title">
+                <b>TableÂ 3.1.Â Platform-specific filename conventions</b>
+              </p>
+              <div class="table-contents">
+                <table summary="Platform-specific filename conventions" border="1">
+                  <colgroup>
+                    <col />
+                    <col />
+                    <col />
+                    <col />
+                    <col />
+                    <col />
+                  </colgroup>
+                  <thead>
+                    <tr>
+                      <th>Platform</th>
+                      <th>kernel</th>
+                      <th>full-image</th>
+                      <th>boot-image</th>
+                      <th>fasl extension</th>
+                      <th>kernel-build directory</th>
+                    </tr>
+                  </thead>
+                  <tbody>
+                    <tr>
+                      <td>DarwinPPC32</td>
+                      <td>dppccl</td>
+                      <td>dppccl.image</td>
+                      <td>ppc-boot.image</td>
+                      <td>.dfsl</td>
+                      <td>darwinppc</td>
+                    </tr>
+                    <tr>
+                      <td>LinuxPPC32</td>
+                      <td>ppccl</td>
+                      <td>ppccl.image</td>
+                      <td>ppc-boot</td>
+                      <td>.pfsl</td>
+                      <td>linuxppc</td>
+                    </tr>
+                    <tr>
+                      <td>DarwinPPC64</td>
+                      <td>dppccl64</td>
+                      <td>dppccl64.image</td>
+                      <td>ppc-boot64.image</td>
+                      <td>.d64fsl</td>
+                      <td>darwinppc64</td>
+                    </tr>
+                    <tr>
+                      <td>LinuxPPC64</td>
+                      <td>ppccl64</td>
+                      <td>ppccl64.image</td>
+                      <td>ppc-boot64</td>
+                      <td>.p64fsl</td>
+                      <td>linuxppc64</td>
+                    </tr>
+                    <tr>
+                      <td>LinuxX8664</td>
+                      <td>lx86cl64</td>
+                      <td>lx86cl64.image</td>
+                      <td>x86-boot64</td>
+                      <td>.lx64fsl</td>
+                      <td>linuxx8664</td>
+                    </tr>
+                    <tr>
+                      <td>LinuxX8632</td>
+                      <td>lx86cl</td>
+                      <td>lx86cl.image</td>
+                      <td>x86-boot32</td>
+                      <td>.lx32fsl</td>
+                      <td>linuxx8632</td>
+                    </tr>
+                    <tr>
+                      <td>DarwinX8664</td>
+                      <td>dx86cl64</td>
+                      <td>dx86cl64.image</td>
+                      <td>x86-boot64.image</td>
+                      <td>.dx64fsl</td>
+                      <td>darwinx8664</td>
+                    </tr>
+                    <tr>
+                      <td>DarwinX8632</td>
+                      <td>dx86cl</td>
+                      <td>dx86cl.image</td>
+                      <td>x86-boot32.image</td>
+                      <td>.dx32fsl</td>
+                      <td>darwinx8632</td>
+                    </tr>
+                    <tr>
+                      <td>FreeBSDX8664</td>
+                      <td>fx86cl64</td>
+                      <td>fx86cl64.image</td>
+                      <td>fx86-boot64</td>
+                      <td>.fx64fsl</td>
+                      <td>freebsdx8664</td>
+                    </tr>
+                    <tr>
+                      <td>FreeBSDX8632</td>
+                      <td>fx86cl</td>
+                      <td>fx86cl.image</td>
+                      <td>fx86-boot32</td>
+                      <td>.fx32fsl</td>
+                      <td>freebsdx8632</td>
+                    </tr>
+                    <tr>
+                      <td>SolarisX64</td>
+                      <td>sx86cl64</td>
+                      <td>sx86cl64.image</td>
+                      <td>sx86-boot64</td>
+                      <td>.sx64fsl</td>
+                      <td>solarisx64</td>
+                    </tr>
+                    <tr>
+                      <td>SolarisX86</td>
+                      <td>sx86cl</td>
+                      <td>sx86cl.image</td>
+                      <td>sx86-boot32</td>
+                      <td>.sx32fsl</td>
+                      <td>solarisx86</td>
+                    </tr>
+                    <tr>
+                      <td>Win64</td>
+                      <td>wx86cl64.exe</td>
+                      <td>sx86cl64.image</td>
+                      <td>wx86-boot64.image</td>
+                      <td>.wx64fsl</td>
+                      <td>win64</td>
+                    </tr>
+                    <tr>
+                      <td>Win32</td>
+                      <td>wx86cl.exe</td>
+                      <td>wx86cl.image</td>
+                      <td>wx86-boot32.image</td>
+                      <td>.wx32fsl</td>
+                      <td>win32</td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+            </div>
+            <br xmlns="http://www.w3.org/1999/xhtml" class="table-break" />
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Setting-Up-to-Build"></a>3.2.Â Setting Up to Build</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">At a given time, there are generally two versions of Clozure CL that
+    you might want to use (and therefore might want to build from
+      source):</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>The released version</p>
+              </li>
+              <li>
+                <p>The development version, called the "trunk", which
+      may contain both interesting new features and interesting new bugs
+      </p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">All versions are available for download from svn.clozure.com via
+    the Subversion source control system.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      For example, to get a released version (1.3 in this example),
+      use a command like:
+      </p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+	svn co http://svn.clozure.com/publicsvn/openmcl/release/1.3/xxx/ccl
+      </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      To get the trunk version, use:
+      </p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+	svn co http://svn.clozure.com/publicsvn/openmcl/trunk/xxx/ccl
+      </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      Change the "xxx" to one of the following names:
+      <code class="literal">darwinx86</code>,
+      <code class="literal">linuxx86</code>,
+      <code class="literal">freebsdx86</code>,
+      <code class="literal">solarisx86</code>,
+      <code class="literal">window</code>,
+      <code class="literal">linuxppc</code>,
+      or 
+      <code class="literal">darwinppc</code>.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      In the case of released versions, there may also be tar archives
+      available.  See the <a class="ulink" href="http://trac.clozure.com/ccl/" target="_top">Clozure CL
+      Trac</a> for details.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Subversion client programs are pre-installed on Mac OS X 10.5 and
+      later and are typically either pre-installed or readily available
+      on Linux and FreeBSD platforms.  The <a class="ulink" href="http://subversion.tigris.org" target="_top">Subversion web page</a> contains links to subversion client programs
+      for many platforms; users of Mac OS X 10.4 can also
+      install Subversion clients via Fink or MacPorts.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Building-Everything"></a>3.3.Â Building Everything</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Given that you now have everything you need, do the
+      following in a running Clozure CL to bring your Lisp system
+      completely up to date.</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (ccl:rebuild-ccl :full t)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">That call to the function <code class="literal">rebuild-ccl</code>
+      performs the following steps:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>Deletes all fasl files and other object files in the
+	      <code class="literal">ccl</code> directory tree</p>
+              </li>
+              <li>
+                <p>Runs an external process that does a
+	      <code class="literal">make</code> in the current platform's kernel
+	      build directory to create a new kernel.  
+             This step can only work if the C compiler and related
+             tools are installed; see <a class="xref" href="#Kernel-build-prerequisites" title="3.4.1.Â Kernel build prerequisites">SectionÂ 3.4.1, âKernel build prerequisitesâ</a>. 
+           </p>
+              </li>
+              <li>
+                <p>Does <code class="literal">(compile-ccl t)</code> in the running
+	      lisp, to produce a set of fasl files from the âhigher
+	      levelâ lisp sources.</p>
+              </li>
+              <li>
+                <p>Does <code class="literal">(xload-level-0 :force)</code> in the
+	      running lisp, to compile the lisp sources in the
+	      âccl:level-0;â directory into fasl files and
+	      then create a bootstrapping image from those fasl
+	      files.</p>
+              </li>
+              <li>
+                <p>Runs another external process, which causes the newly
+	      compiled lisp kernel to load the new bootstrapping image.
+	      The bootsrtrapping image then loads the âhigher
+	      levelâ fasl files and a new copy of the platform's
+	      full heap image is then saved.</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">If all goes well, it'll all happen without user
+      intervention and with some simple progress messages.  If
+      anything goes wrong during execution of either of the external
+      processes, the process output is displayed as part of a lisp
+      error message.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">rebuild-ccl</code> is essentially just a short
+      cut for running all the individual steps involved in rebuilding
+      the system.  You can also execute these steps individually, as
+      described below.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Building-the-kernel"></a>3.4.Â Building the kernel</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Lisp kernel is the executable that you run to use
+      Lisp.  It doesn't actually contain the entire Lisp
+      implementation; rather, it loads a heap image which contains the
+      specificsâthe "library", as it might be called if this was a C
+      program.  The kernel also provides runtime support to the heap
+      image, such as garbage collection, memory allocation, exception
+      handling, and the OS interface.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Lisp kernel file has different names on different
+      platforms. See
+      <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a>. On all
+      platforms the lisp kernel sources reside
+      in <code class="literal">ccl/lisp-kernel</code>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This section gives directions on how to rebuild the Lisp
+      kernel from its source code.  Most Clozure CL users will rarely
+      have to do this.  You probably will only need to do it if you are
+      attempting to port Clozure CL to a new architecture or extend or enhance
+      its kernel in some way.  As mentioned above, this step happens
+      automatically when you do
+      </p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (rebuild-ccl :full t)
+      </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+    </p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Kernel-build-prerequisites"></a>3.4.1.Â Kernel build prerequisites</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The Clozure CL kernel can be bult with the following widely
+	    available tools:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>cc or gcc- the GNU C compiler</p>
+                </li>
+                <li>
+                  <p>ld - the GNU linker</p>
+                </li>
+                <li>
+                  <p>m4 or gm4- the GNU m4 macro processor</p>
+                </li>
+                <li>
+                  <p>as - the GNU assembler (version 2.10.1 or later)</p>
+                </li>
+                <li>
+                  <p>make - either GNU make or, on FreeBSD, the default BSD make program</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"> In general, the more recent the versions of those
+	    tools, the better; some versions of gcc 3.x on Linux have
+	    difficulty compiling some of the kernel source code correctly
+	    (so gcc 4.0 should be used, if possible.)  On Mac OS X, the
+	    versions of the tools distributed with Xcode should work fine;
+	    on Linux, the versions of the tools installed with the OS (or
+	    available through its package management system) should work
+	    fine if they're "recent enough".  On FreeBSD, the installed
+	    version of the <code class="literal">m4</code> program doesn't support
+	    some features that the kernel build process depends on; the
+	    GNU version of the m4 macroprocessor (called
+	    <code class="literal">gm4</code> on FreeBSD) should be installed.
+	  </p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+              <h3 class="title">Note</h3>
+              <p>In order to build the lisp kernel on Mac OS X
+	  10.6 Snow Leopard, you must install the optional 10.4
+	  support when installing Xcode.</p>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="kernel-build-command"></a>3.4.2.Â Using "make" to build the lisp kernel</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">With those tools in place, do:
+        </p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+shell&gt; cd ccl/lisp-kernel/<em class="replaceable"><code>PLATFORM</code></em>
+shell&gt; make
+	    </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	  </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">That'll assemble several assembly language source files,
+        compile several C source files, and link
+        ../../<em class="replaceable"><code>the kernel</code></em>.
+	  </p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Building-the-heap-image"></a>3.5.Â Building the heap image</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The initial heap image is loaded by the Lisp kernel, and
+      provides most of the language implementation The heap image
+      captures the entire state of a running Lisp (except for external
+      resources, such as open files and TCP sockets).  After it is
+      loaded, the contents of the new Lisp process's memory are
+      exactly the same as those of the old Lisp process when the image
+      was created.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The heap image is how we get around the fact that we can't
+      run Lisp code until we have a working Lisp implementation, and
+      we can't make our Lisp implementation work until we can run Lisp
+      code.  Since the heap image already contains a fully-working
+      implementation, all we need to do is load it into memory and
+      start using it.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you're building a new version of Clozure CL, you need to
+      build a new heap image.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">(You might also wish to build a heap image if you have a
+      large program that is very complicated or time-consuming to
+      load, so that you will be able to load it once, save an image,
+      and thenceforth never have to load it again. At any time, a heap
+      image capturing the entire memory state of a running Lisp can be
+      created by calling the function
+      <code class="literal">ccl:save-application</code>.)</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Development-cycle"></a>3.5.1.Â Development cycle</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Creating a new Clozure CL full heap image consists of the
+        following steps:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>Using your existing Clozure CL, create a
+            bootstrapping image</p>
+                </li>
+                <li>
+                  <p>Using your existing Clozure CL, recompile your
+            updated Clozure CL sources</p>
+                </li>
+                <li>
+                  <p>Invoke Clozure CL with the bootstrapping image
+            you just created (rather than with the existing full heap
+            image).</p>
+                </li>
+              </ol>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">When you invoke Clozure CL with the bootstrapping image, it
+	    starts up, loads all of the Clozure CL fasl files, and saves out a
+	    new full heap image.  Voila.  You've created a new heap
+	    image.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A few points worth noting:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>There's a circular dependency between the full heap
+	        image and the bootstrapping image, in that each is used to
+	        build the other.</p>
+                </li>
+                <li>
+                  <p>There are some minor implementation
+	        differences, but the environment in effect after the
+	        bootstrapping image has loaded its fasl files is essentially
+	        equivalent to the environment provided by the full heap
+	        image; the latter loads a lot faster and is easier to
+	        distribute, of course.</p>
+                </li>
+                <li>
+                  <p>If the full heap image doesn't work (because
+	        of an OS compatibilty problem or other bug), it's very likely
+	        that the bootstrapping image will suffer the same
+	        problems.</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Given a bootstrapping image and a set of up-to-date fasl
+        files, the development cycle usually involves editing lisp
+        sources (or updating those sources via cvs update),
+        recompiling modified files, and using the bootstrapping image
+        to produce a new heap image.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Generating-a-bootstrapping-image"></a>3.5.2.Â Generating a bootstrapping image</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The bootstrapping image isn't provided in Clozure CL
+        distributions. It can be built from the source code provided
+        in distributions (using a lisp image and kernel provided in
+        those distributions) using the procedure described
+        below.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The bootstrapping image is built by invoking a special
+        utility inside a running Clozure CL heap image to load files
+        contained in the <code class="literal">ccl/level-0</code> directory. The
+        bootstrapping image loads several dozen fasl files.  After
+        it's done so, it saves a heap image via
+        <code class="literal">save-application</code>. This process is called
+        "cross-dumping".</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Given a source distribution, a lisp kernel, and a heap
+        image, one can produce a bootstrapping image by first invoking
+        Clozure CL from the shell:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+shell&gt; ccl
+Welcome to Clozure CL .... !
+?
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">then calling <code class="literal">ccl:xload-level-0</code> at the
+	    lisp prompt</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (ccl:xload-level-0)
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">This function compiles the lisp sources in the ccl/level-0
+        directory if they're newer than the corresponding fasl files
+        and then loads the resulting fasl files into a simulated lisp
+        heap contained in data structures inside the running
+        lisp. That simulated heap image is then written to
+        disk.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">xload-level-0</code> should be called
+        whenever your existing boot image is out-of-date with respect
+        to the source files in <code class="literal">ccl:level-0;</code>
+        :</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (ccl:xload-level-0 :force)
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">forces recompilation of the level-0 sources.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Generating-fasl-files"></a>3.5.3.Â Generating fasl files</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"> Calling:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (ccl:compile-ccl)
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">at the lisp prompt compiles any fasl files that are
+	    out-of-date with respect to the corresponding lisp sources;
+	    <code class="literal">(ccl:compile-ccl t)</code> forces
+	    recompilation. <code class="literal">ccl:compile-ccl</code> reloads
+	    newly-compiled versions of some files;
+	    <code class="literal">ccl:xcompile-ccl</code> is analogous, but skips
+	    this reloading step.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Unless there are bootstrapping considerations involved, it
+        usually doesn't matter whether these files are reloaded after
+        they're recompiled.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Calling <code class="literal">compile-ccl</code> or
+        <code class="literal">xcompile-ccl</code> in an environment where fasl
+        files don't yet exist may produce warnings to that effect
+        whenever files are <code class="literal">require</code>d during
+        compilation; those warnings can be safely ignored. Depending
+        on the maturity of the Clozure CL release, calling
+        <code class="literal">compile-ccl</code> or
+        <code class="literal">xcompile-ccl</code> may also produce several
+        warnings about undefined functions, etc. They should be
+        cleaned up at some point.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Building-a-full-image-from-a-bootstrapping-image"></a>3.5.4.Â Building a full image from a bootstrapping image</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">To build a full image from a bootstrapping image, just
+	    invoke the kernel with the bootstrapping image as an
+	    argument</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+$ cd ccl                        # wherever your ccl directory is
+$ ./KERNEL BOOT_IMAGE
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Where <em class="replaceable"><code>KERNEL</code></em> and
+        <em class="replaceable"><code>BOOT_IMAGE</code></em> are the names of
+        the kernel and boot image appropriate to the platform you are
+        running on.  See <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a></p>
+            <p xmlns="http://www.w3.org/1999/xhtml">That should load a few dozen fasl files (printing a
+        message as each file is loaded.) If all of these files
+        successfully load, the lisp will print a prompt. You should be
+        able to do essentially everything in that environment that you
+        can in the environment provided by a "real" heap image. If
+        you're confident that things loaded OK, you can save that
+        image.</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (ccl:save-application "<em class="replaceable"><code>image_name</code></em>") ; Overwiting the existing heap image
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Where <em class="replaceable"><code>image_name</code></em> is the name of
+        the full heap image for your platform. See
+        <a class="xref" href="#Platform-specific-filename-conventions" title="TableÂ 3.1.Â Platform-specific filename conventions">TableÂ 3.1, âPlatform-specific filename conventionsâ</a>.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If things go wrong in the early stages of the loading
+        sequence, errors are often difficult to debug; until a fair
+        amount of code (CLOS, the CL condition system, streams, the
+        reader, the read-eval-print loop) is loaded, it's generally
+        not possible for the lisp to report an error.  Errors that
+        occur during these early stages ("the cold load") sometimes
+        cause the lisp kernel debugger (see ) to be invoked; it's
+        primitive, but can sometimes help one to get oriented.</p>
+          </div>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="using-ccl"></a>ChapterÂ 4.Â Using Clozure CL</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#using-ccl-introduction">4.1. Introduction</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Trace">4.2. Trace</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Unicode">4.3. Unicode</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#unicode-characters">4.3.1. Characters</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#External-Formats">4.3.2. External Formats</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Line-Termination-Keywords">4.3.3. Line Termination Keywords</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Character-Encodings">4.3.4. Character Encodings</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Pathanmes">4.4. Pathnames</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#pathname-tilde-expansion">4.4.1. Pathname Expansion</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Predefined-Logical-Hosts">4.4.2. Predefined Logical Hosts</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#pathnames-on-darwin">4.4.3. OS X (Darwin)</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#pathnames-on-linux">4.4.4. Linux</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#pathnames-on-freebsd">4.4.5. FreeBSD</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Memory-Mapped-Files">4.5. Memory-mapped Files</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Static_Variables">4.6. Static Variables</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Saving-Applications">4.7. Saving Applications</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#concatenating-fasl-files">4.8. Concatenating FASL Files</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#floating-point">4.9. Floating Point Numbers</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#watched-objects">4.10. Watched Objects</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#watched-watch">4.10.1. WATCH</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#watched-unwatch">4.10.2. UNWATCH</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#watched-write-to-watched-object">4.10.3. WRITE-TO-WATCHED-OBJECT</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#watch-notes">4.10.4. Notes</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#watch-examples">4.10.5. Examples</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#code-coverage">4.11. Code Coverage</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#code-coverage-overview">4.11.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#code-coverage-limitations">4.11.2. Limitations</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#code-coverage-usage">4.11.3. Usage</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="using-ccl-introduction"></a>4.1.Â Introduction</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Common Lisp standard allows considerable latitude in the
+      details of an implementation, and each particular Common Lisp
+      system has some idiosyncrasies. This chapter describes ordinary
+      user-level features of Clozure CL, including features that may be
+      part of the Common Lisp standard, but which may have quirks or
+      details in the Clozure CL implementation that are not described by
+      the standard. It also describes extensions to the standard; that
+      is, features of Clozure CL that are not part of the Common Lisp
+      standard at all.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Trace"></a>4.2.Â Trace</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      Clozure CL's tracing facility is invoked by an extended version of the Common Lisp
+      <em class="varname">trace</em> macro.  Extensions allow tracing of methods, as well as finer control
+      over tracing actions.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id395347" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="trace"></a>TRACE</em> {<em class="replaceable"><code>keyword</code></em>
+        <em class="replaceable"><code>global-value</code></em>}* {<em class="replaceable"><code>spec</code></em> |
+        (<em class="replaceable"><code>spec</code></em> {<em class="replaceable"><code>keyword</code></em>
+        <em class="replaceable"><code>local-value</code></em>}*)}* [Macro]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      The <em class="varname">trace</em> macro encapsulates the functions named by
+      <em class="replaceable"><code>spec</code></em>s, causing trace actions to take place on entry and
+      exit from each function.  The default actions print a message on function entry and
+      exit. <em class="replaceable"><code>Keyword</code></em>/<em class="replaceable"><code>value</code></em> options
+      can be used to specify changes in the default behavior.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      Invoking <em class="varname">(trace)</em> without arguments returns a list of functions being traced.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      A <em class="replaceable"><code>spec</code></em> is either a symbol that is the name of a function, or an
+      expression of the form <em class="varname">(setf <em class="replaceable"><code>symbol</code></em>)</em>, or a
+      specific method of a generic function in the form <em class="varname">(:method
+        <em class="replaceable"><code>gf-name</code></em> {<em class="replaceable"><code>qualifier</code></em>}*
+        ({<em class="replaceable"><code>specializer</code></em>}*))</em>, where a
+      <em class="replaceable"><code>specializer</code></em> can be the name of a class or an <em class="varname">EQL</em>
+      specializer.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      A <em class="replaceable"><code>spec</code></em> can also be a string naming a package, or equivalently a
+      list <em class="varname">(:package <em class="replaceable"><code>package-name</code></em>)</em>, in order to
+      request that all functions in the package to be traced.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      By default, whenever a traced function is entered or exited, a short message is
+      printed on <em class="varname">*trace-output*</em> showing the arguments on entry and
+      values on exit.  Options specified as key/value pairs can be used to modify this
+      behavior.  Options preceding the function <em class="replaceable"><code>spec</code></em>s apply to
+      all the functions being traced.  Options specified along with a
+      <em class="replaceable"><code>spec</code></em> apply to that spec only and override any
+      global options. The following options are supported:
+    </p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+            <dl>
+              <dt>
+                <span class="term">
+                  <em class="varname">:methods {T | nil}</em>
+                </span>
+              </dt>
+              <dd>
+                <p> If true, and if applied to a <em class="replaceable"><code>spec</code></em> naming a generic
+	        function, arranges to trace all the methods of the generic function in addition to the
+	        generic function itself.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:inside <em class="replaceable"><code>outside-spec</code></em>
+	        | ({<em class="replaceable"><code>outside-spec</code></em>}*)</em>
+                </span>
+              </dt>
+              <dd>
+                <p>Inhibits all trace actions unless the current
+	        invocation of the function being traced is inside one of the
+	        <em class="replaceable"><code>outside-spec</code></em>'s, i.e. unless a function named by one of the
+	        <em class="replaceable"><code>outside-spec</code></em>'s is currently on the stack.
+	        <em class="replaceable"><code>outside-spec</code></em> can name a function, a
+	        method, or a package, as above.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term"><em class="varname">:if <em class="replaceable"><code>form</code></em></em>, </span>
+                <span class="term">
+                  <em class="varname">:condition <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p> Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced is
+	        about to be entered, and inhibits all trace actions if <em class="replaceable"><code>form</code></em>
+	        returns nil. The form may reference the lexical variable <em class="varname">ccl::args</em>,
+	        which is a list of the arguments in this call. <em class="varname">:condition</em> is just a
+	        synonym for <em class="varname">:if</em>, though if both are specified, both must return non-nil.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:before-if <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p> Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced is
+	        about to be entered, and inhibits the entry trace actions if
+	        <em class="replaceable"><code>form</code></em> returns nil.  The form may reference the lexical variable
+	        <em class="varname">ccl::args</em>, which is a list of the arguments in this call. If both
+	        <em class="varname">:if</em> and <em class="varname">:before-if</em> are specified, both must return
+	        non-nil in order for the before entry actions to happen.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:after-if <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p> Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced has
+	        just exited, and inhibits the exit trace actions if <em class="replaceable"><code>form</code></em>
+	        returns nil.  The form may reference the lexical variable <em class="varname">ccl::vals</em>,
+	        which is a list of values returned by this call. If both <em class="varname">:if</em> and
+	        <em class="varname">:after-if</em> are specified, both must return non-nil in order for the
+	        after exit actions to happen.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:print-before <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p> Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced is
+	        about to be entered, and prints the result before printing the standard entry message.
+	        The form may reference the lexical variable <em class="varname">ccl::args</em>, which is a list
+	        of the arguments in this call.  To see multiple forms, use <em class="varname">values</em>:
+	        <em class="varname">:print-before (values (one-thing) (another-thing))</em>.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:print-after <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p> Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced has
+	        just exited, and prints the result after printing the standard exit message.  The form may
+	        reference the lexical variable <em class="varname">ccl::vals</em>, which is a list of values
+	        returned by this call. To see multiple forms, use <em class="varname">values</em>:
+	        <em class="varname">:print-after (values (one-thing) (another-thing))</em>.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:print <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Equivalent to <em class="varname">:print-before <em class="replaceable"><code>form</code></em> :print-after <em class="replaceable"><code>form</code></em></em>.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:eval-before <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced is
+	        about to be entered.  The form may reference the lexical variable
+	        <em class="varname">ccl::args</em>, which is a list of the arguments in this call.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:eval-after <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Evaluates <em class="replaceable"><code>form</code></em> whenever the function being has just
+	        exited.  The form may reference the lexical variable <em class="varname">ccl::vals</em>, which
+	        is a list of values returned by this call.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:eval <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Equivalent to <em class="varname">:eval-before <em class="replaceable"><code>form</code></em>
+	          :eval-after <em class="replaceable"><code>form</code></em></em>.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:break-before <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced is
+	        about to be entered, and if the result is non-nil, enters a debugger break loop.  The form
+	        may reference the lexical variable <em class="varname">ccl::args</em>, which is a list of the
+	        arguments in this call.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:break-after <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced has
+	        just exited, and if the result is non-nil, enters a debugger break loop. The form may
+	        reference the lexical variable <em class="varname">ccl::vals</em>, which is a list of values
+	        returned by this call.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:break <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Equivalent to <em class="varname">:break-before <em class="replaceable"><code>form</code></em> :break-after <em class="replaceable"><code>form</code></em></em>.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term"><em class="varname">:backtrace-before <em class="replaceable"><code>form</code></em></em>, </span>
+                <span class="term">
+                  <em class="varname">:backtrace <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced is
+	        about to be entered.  The form may reference the lexical variable
+	        <em class="varname">ccl::args</em>, which is a list of the arguments in this call. The value
+	        returned by <em class="replaceable"><code>form</code></em> is intepreted as follows:
+	      </p>
+                <div class="variablelist">
+                  <dl>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">nil</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>does nothing</p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:detailed</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>prints a detailed backtrace to
+	              <em class="varname">*trace-output*</em>.</p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">(:detailed <em class="replaceable"><code>integer</code></em>)</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>prints the top <em class="replaceable"><code>integer</code></em> frames of detailed
+	              backtrace to <em class="varname">*trace-output*</em>.
+	          </p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="replaceable">
+                          <code>integer</code>
+                        </em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>prints top <em class="replaceable"><code>integer</code></em> frames of a terse
+	              backtrace to <em class="varname">*trace-output*</em>.
+	          </p>
+                    </dd>
+                    <dt>
+                      <span class="term">anything else</span>
+                    </dt>
+                    <dd>
+                      <p>prints a terse backtrace to <em class="varname">*trace-output*</em>.
+	          </p>
+                    </dd>
+                  </dl>
+                </div>
+                <p>
+	        Note that unlike with the other options, <em class="varname">:backtrace</em> is equivalent to
+	        <em class="varname">:backtrace-before</em> only, not both before and after, since it's usually
+	        not helpful to print the same backtrace both before and after the function call.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">:backtrace-after <em class="replaceable"><code>form</code></em></em>
+                </span>
+              </dt>
+              <dd>
+                <p>Evaluates <em class="replaceable"><code>form</code></em> whenever the function being traced has
+	        just exited.  The form may reference the lexical variable <em class="varname">ccl::vals</em>,
+	        which is a list of values returned by this call. The value returned by
+	        <em class="replaceable"><code>form</code></em> is intepreted as follows:
+	      </p>
+                <div class="variablelist">
+                  <dl>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">nil</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>does nothing</p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:detailed</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>prints a detailed backtrace to
+	              <em class="varname">*trace-output*</em>.</p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">(:detailed <em class="replaceable"><code>integer</code></em>)</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>prints the top <em class="replaceable"><code>integer</code></em> frames of detailed
+	              backtrace to <em class="varname">*trace-output*</em>.
+	          </p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="replaceable">
+                          <code>integer</code>
+                        </em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>prints top <em class="replaceable"><code>integer</code></em> frames of a terse
+	              backtrace to <em class="varname">*trace-output*</em>.
+	          </p>
+                    </dd>
+                    <dt>
+                      <span class="term">anything else</span>
+                    </dt>
+                    <dd>
+                      <p>prints a terse backtrace to <em class="varname">*trace-output*</em>.
+	          </p>
+                    </dd>
+                  </dl>
+                </div>
+              </dd>
+              <dt>
+                <span class="term"><em class="varname">:before</em> <em class="replaceable"><code>action</code></em></span>
+              </dt>
+              <dd>
+                <p>specifies the action to be taken just before the traced function is entered.  <em class="replaceable"><code>action</code></em> is one of:</p>
+                <div class="variablelist">
+                  <dl>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:print</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>The default, prints a short indented message showing the function name and the invocation arguments</p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:break</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>Equivalent to <em class="varname">:before :print :break-before t</em></p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:backtrace</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>Equivalent to <em class="varname">:before :print :backtrace-before t</em></p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="replaceable">
+                          <code>function</code>
+                        </em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>
+                  Any other value is interpreted as a function to call on entry instead of
+                  printing the standard entry message.  It is called with its first
+                  argument being the name of the function being traced, the remaining
+                  arguments being all the arguments to the function being traced, and
+                  <em class="varname">ccl:*trace-level*</em> bound to the current nesting level
+                  of trace actions. </p>
+                    </dd>
+                  </dl>
+                </div>
+              </dd>
+              <dt>
+                <span class="term"><em class="varname">:after</em> <em class="replaceable"><code>action</code></em></span>
+              </dt>
+              <dd>
+                <p>specifies the action to be taken just after the traced function exits.  <em class="replaceable"><code>action</code></em> is one of:</p>
+                <div class="variablelist">
+                  <dl>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:print</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>The default, prints a short indented message showing the function name and the
+	              returned values </p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:break</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>Equivalent to <em class="varname">:after :print :break-after t</em></p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="varname">:backtrace</em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>Equivalent to <em class="varname">:after :print :backtrace-after t</em></p>
+                    </dd>
+                    <dt>
+                      <span class="term">
+                        <em class="replaceable">
+                          <code>function</code>
+                        </em>
+                      </span>
+                    </dt>
+                    <dd>
+                      <p>Any other value is interpreted as a function to
+	              call on exit instead of printing the standard exit
+	              message.  It is called with its first argument being
+	              the name of the function being traced, the
+	              remaining arguments being all the values returned by the function
+	              being traced, and ccl:*trace-level* bound to the current
+	              nesting level of trace actions.
+	            </p>
+                    </dd>
+                  </dl>
+                </div>
+              </dd>
+            </dl>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id402844" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="trace-level"></a>CCL:*TRACE-LEVEL*</em>    [Variable]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Variable bound to the current nesting level during execution of before and after trace actions.  The default printing actions use it to determine the amount of indentation.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id402870" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="trace-max-indent"></a>CCL:*TRACE-MAX-INDENT*</em>    [Variable]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The default before and after print actions will not indent by more than the value of <em class="varname">ccl:*trace-max-indent*</em> regardless of the current trace level.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id402900" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="trace-function"></a>CCL:TRACE-FUNCTION</em> <em class="replaceable"><code>spec</code></em> <em class="varname">&amp;key</em> {<em class="replaceable"><code>keyword</code></em> <em class="replaceable"><code>value</code></em>}*    [Function]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      This is a functional version of the TRACE macro.  <em class="replaceable"><code>spec</code></em> and
+      <em class="replaceable"><code>keyword</code></em>s are as for TRACE, except that all arguments are evaluated.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id402949" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="trace-print-level"></a>CCL:*TRACE-PRINT-LEVEL*</em>   [Variable]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The default print actions bind <em class="varname">CL:*PRINT-LEVEL*</em> to this value while
+      printing. Note that this rebinding is only in effect during the default entry and exit messages.
+      It does not apply to printing of <em class="varname">:print-before/:print-after</em> forms or any
+      explicit printing done by user code.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id402983" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="trace-print-length"></a>CCL:*TRACE-PRINT-LENGTH*</em>    [Variable]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The default print actions bind <em class="varname">CL:*PRINT-LENGTH*</em> to this value while
+      printing. Note that this rebinding is only in effect during the default entry and exit messages.
+      It does not apply to printing of <em class="varname">:print-before/:print-after</em> forms or any
+      explicit printing done by user code.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id403018" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="trace-bar-frequency"></a>CCL:*TRACE-BAR-FREQUENCY*</em>    [Variable]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">By default, this is nil. If non-nil it should be a integer,
+    and the default entry and exit messages will print a | instead of
+    space every this many levels of indentation.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Unicode"></a>4.3.Â Unicode</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">All characters and strings in Clozure CL fully support Unicode by
+    using UTF-32. There is only one <code class="literal">CHARACTER</code> type
+    and one <code class="literal">STRING</code> type in Clozure CL.  There has been a
+    lot of discussion about this decision which can be found by
+    searching the openmcl-devel archives at <a class="ulink" href="http://clozure.com/pipermail/openmcl-devel/" target="_top">http://clozure.com/pipermail/openmcl-devel/</a>.  Suffice it
+    to say that we decided that the simplicity and speed advantages of
+    only supporting UTF-32 outweigh the space disadvantage.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="unicode-characters"></a>4.3.1.Â Characters</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">There is one <code class="literal">CHARACTER</code> type in Clozure CL.
+    All <code class="literal">CHARACTER</code>s are
+    <code class="literal">BASE-CHAR</code>s.  <em class="varname">CHAR-CODE-LIMIT</em>
+    is now <code class="literal">#x110000</code>, which means that all Unicode
+    characters can be directly represented.  As of Unicode 5.0, only
+    about 100,000 of 1,114,112 possible <code class="literal">CHAR-CODE</code>s
+    are actually defined. The function <span class="function"><strong>CODE-CHAR</strong></span>
+    knows that certain ranges of code values (notably
+    <code class="literal">#xd800</code>-<code class="literal">#xddff</code>) will never be
+    valid character codes and will return <code class="literal">NIL</code> for
+    arguments in that range, but may return a
+    non-<code class="literal">NIL</code> value (an undefined/non-standard
+    <code class="literal">CHARACTER</code> object) for other unassigned code
+    values.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL supports character names of the form
+    <code class="literal">u+xxxx</code>âwhere <code class="literal">x</code> is a
+    sequence of one or more hex digits.  The value of the hex digits
+    denotes the code of the character.  The <code class="literal">+</code>
+    character is optional, so <code class="literal">#\u+0020</code>,
+    <code class="literal">#\U0020</code>, and <code class="literal">#\U+20</code> all
+    refer to the <code class="literal">#\Space</code> character.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Characters with codes in the range
+    <code class="literal">#xa0</code>-<code class="literal">#x7ff</code> also have
+    symbolic names These are the names from the Unicode standard with
+    spaces replaced by underscores.  So
+    <code class="literal">#\Greek_Capital_Letter_Epsilon</code> can be used to
+    refer to the character whose <span class="function"><strong>CHAR-CODE</strong></span> is
+    <code class="literal">#x395</code>.  To see the complete list of supported
+    character names, look just below the definition for
+    <span class="function"><strong>register-character-name</strong></span> in
+    <code class="literal">ccl:level-1;l1-reader.lisp</code>.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="External-Formats"></a>4.3.2.Â External Formats</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"><span class="function"><strong>OPEN</strong></span>, <span class="function"><strong>LOAD</strong></span>, and
+    <span class="function"><strong>COMPILE-FILE</strong></span> all take an
+    <code class="literal">:EXTERNAL-FORMAT</code> keyword argument.  The value
+    of <code class="literal">:EXTERNAL-FORMAT</code> can be
+    <code class="literal">:DEFAULT</code> (the default value), a line
+    termination keyword (see <a class="xref" href="#Line-Termination-Keywords" title="4.3.3.Â Line Termination Keywords">SectionÂ 4.3.3, âLine Termination Keywordsâ</a>), a character encoding
+    keyword (see <a class="xref" href="#Character-Encodings" title="4.3.4.Â Character Encodings">SectionÂ 4.3.4, âCharacter Encodingsâ</a>), an
+    external-format object created using
+    <span class="function"><strong>CCL::MAKE-EXTERNAL-FORMAT</strong></span> (see <a class="xref" href="#f_make-external-format" title="Function MAKE-EXTERNAL-FORMAT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-external-format</b></a>), or a plist with keys:
+    <code class="literal">:DOMAIN</code>, <code class="literal">:CHARACTER-ENCODING</code>
+    and <code class="literal">:LINE-TERMINATION</code>.  If
+    <em class="parameter"><code>argument</code></em> is a plist, the result of
+    <code class="literal">(APPLY #'MAKE-EXTERNAL-FORMAT
+    <em class="parameter"><code>argument</code></em>)</code> will be used.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If <code class="literal">:DEFAULT</code> is specified, then the value
+    of <em class="varname">CCL:*DEFAULT-EXTERNAL-FORMAT*</em> is used.  If
+    no line-termination is specified, then the value of
+    <em class="varname">CCL:*DEFAULT-LINE-TERMINATION*</em> is used, which
+    defaults to <code class="literal">:UNIX</code>.  If no character encoding is
+    specified, then
+    <em class="varname">CCL:*DEFAULT-FILE-CHARACTER-ENCODING*</em> is used
+    for file streams and
+    <em class="varname">CCL:*DEFAULT-SOCKET-CHARACTER-ENCODING*</em> is used
+    for socket streams.  The default, default character encoding is
+    <code class="literal">NIL</code> which is a synonym for
+    <code class="literal">:ISO-8859-1</code>.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that the set of keywords used to denote
+    CHARACTER-ENCODINGs and the set of keywords used to denote
+    line-termination conventions is disjoint: a keyword denotes at
+    most a character encoding or a line termination convention, but
+    never both.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">EXTERNAL-FORMATs are objects (structures) with three
+    read-only fields that can be accessed via the functions:
+    <span class="function"><strong>EXTERNAL-FORMAT-DOMAIN</strong></span>,
+    <span class="function"><strong>EXTERNAL-FORMAT-LINE-TERMINATION</strong></span> and
+    <span class="function"><strong>EXTERNAL-FORMAT-CHARACTER-ENCODING</strong></span>.</p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_make-external-format"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code>
+	  <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-external-format</strong></span>
+	  <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> domain character-encoding line-termination
+	  =&gt; external-format
+	</code>
+              </div>
+              <div class="refentrytitle">Either creates a new external format object, or
+	return an existing one with the same specified slot
+	values.</div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id403480"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">domain</span></i>---This is used to indicate where the external
+	      format is to be used.  Its value can be almost
+	      anything.  It defaults to <code xmlns="http://www.w3.org/1999/xhtml" class="literal">NIL</code>.
+	      There are two domains that have a pre-defined meaning in
+	      Clozure CL: <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:FILE</code> indicates
+	      encoding for a file in the file system and
+	      <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:SOCKET</code> indicates i/o to/from a
+	      socket.  The value of <em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>domain</code></em>
+	      affects the default values for
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>character-encoding</code></em> and
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>line-termination</code></em>.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">character-encoding</span></i>---A keyword that specifies the character encoding
+	      for the external format. <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#Character-Encodings" title="4.3.4.Â Character Encodings">SectionÂ 4.3.4, âCharacter Encodingsâ</a>.  Defaults to
+	      <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:DEFAULT</code> which means if
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>domain</code></em> is
+	      <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:FILE</code> use the value of the variable
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">CCL:*DEFAULT-FILE-CHARACTER-ENCODING*</em>
+	      and if <em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>domain</code></em> is
+	      <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:SOCKET</code>, use the value of the
+	      variable
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">CCL:*DEFAULT-SOCKET-CHARACTER-ENCODING*</em>.
+	      The initial value of both of these variables is
+	      <code xmlns="http://www.w3.org/1999/xhtml" class="literal">NIL</code>, which means the
+	      <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:ISO-8859-1</code> encoding.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">line-termination</span></i>---A keyword that indicates a line termination
+	      keyword <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#Line-Termination-Keywords" title="4.3.3.Â Line Termination Keywords">SectionÂ 4.3.3, âLine Termination Keywordsâ</a>.
+	      Defaults to <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:DEFAULT</code> which means
+	      use the value of the variable
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">CCL:*DEFAULT-LINE-TERMINATION*</em>.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">external-format</span></i>---An external-format object as described above.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id403659"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Despite the function's name, it doesn't necessarily create a
+	new, unique EXTERNAL-FORMAT object: two calls to
+	MAKE-EXTERNAL-FORMAT with the same arguments made in the same
+	dynamic environment return the same (eq) object.
+	</p>
+                </div>
+              </div>
+            </p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Line-Termination-Keywords"></a>4.3.3.Â Line Termination Keywords</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Line termination keywords indicate which characters are used
+  to indicate the end of a line.  On input, the external line
+  termination characters are replaced by <code class="literal">#\Newline</code>
+  and on output, <code class="literal">#\Newline</code>s are converted to the
+  external line termination characters.</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="table">
+              <a id="Line-Termination-Table"></a>
+              <p class="title">
+                <b>TableÂ 4.1.Â Line Termination Keywords</b>
+              </p>
+              <div class="table-contents">
+                <table summary="Line Termination Keywords" border="1">
+                  <colgroup>
+                    <col />
+                    <col />
+                  </colgroup>
+                  <thead>
+                    <tr>
+                      <th align="left">keyword</th>
+                      <th align="left">character(s)</th>
+                    </tr>
+                  </thead>
+                  <tbody>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:UNIX</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Linefeed</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:MACOS</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Return</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:CR</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Return</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:CRLF</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Return #\Linefeed</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:CP/M</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Return #\Linefeed</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:MSDOS</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Return #\Linefeed</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:DOS</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Return #\Linefeed</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:WINDOWS</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Return #\Linefeed</code>
+                      </td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:INFERRED</code>
+                      </td>
+                      <td align="left">see below</td>
+                    </tr>
+                    <tr>
+                      <td align="left">
+                        <code class="literal">:UNICODE</code>
+                      </td>
+                      <td align="left">
+                        <code class="literal">#\Line_Separator</code>
+                      </td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+            </div>
+            <br xmlns="http://www.w3.org/1999/xhtml" class="table-break" />
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">:INFERRED</code> means that a stream's
+  line-termination convention is determined by looking at the contents
+  of a file.  It is only useful for <code class="literal">FILE-STREAM</code>s
+  that're open for <code class="literal">:INPUT</code> or
+  <code class="literal">:IO</code>.  The first buffer full of data is examined,
+  and if a <code class="literal">#\Return</code> character occurs before any
+  <code class="literal">#\Linefeed</code> character, then the line termination
+  type is set to <code class="literal">:MACOS</code>, otherwise it is set to
+  <code class="literal">:UNIX</code>.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Character-Encodings"></a>4.3.4.Â Character Encodings</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Internally, all characters and strings in Clozure CL are in
+    UTF-32.  Externally, files or socket streams may encode characters
+    in a wide variety of ways.  The International Organization for
+    Standardization, widely known as ISO, defines many of these
+    character encodings.  Clozure CL implements some of these encodings as
+    detailed below.  These encodings are part of the specification of
+    external formats <a class="xref" href="#External-Formats" title="4.3.2.Â External Formats">SectionÂ 4.3.2, âExternal Formatsâ</a>.  When reading
+    from a stream, characters are converted from the specified
+    external character encoding to UTF-32.  When writing to a stream,
+    characters are converted from UTF-32 to the specified character
+    encoding.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Internally, CHARACTER-ENCODINGs are objects (structures)
+    that are named by character encoding keywords (:ISO-8859-1,
+    :UTF-8, etc.).  The structures contain attributes of the encoding
+    and functions used to encode/decode external data, but unless
+    you're trying to define or debug an encoding there's little reason
+    to know much about the CHARACTER-ENCODING objects and it's usually
+    preferable to refer to a character encoding by its name.
+    </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+    </p>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id404003"></a>4.3.4.1.Â Encoding Problems</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">On output to streams with character encodings that can
+      encode the full range of Unicodeâand on input from any
+      streamâ"unencodable characters" are represented using the
+      Unicode #\Replacement_Character (= #\U+fffd); the presence of
+      such a character usually indicates that something got lost in
+      translation.  Either data wasn't encoded properly or there was a
+      bug in the decoding process.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id404016"></a>4.3.4.2.Â Byte Order Marks</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">The endianness of a character encoding is sometimes
+      explicit, and sometimes not.  For example,
+      <code class="literal">:UTF-16BE</code> indicates big-endian, but
+      <code class="literal">:UTF-16</code> does not specify endianness.  A byte
+      order mark is a special character that may appear at the
+      beginning of a stream of encoded characters to specify the
+      endianness of a multi-byte character encoding.  (It may also be
+      used with UTF-8 character encodings, where it is simply used to
+      indicate that the encoding is UTF-8.)</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL writes a byte order mark as the first character
+      of a file or socket stream when the endianness of the character
+      encoding is not explicit.  Clozure CL also expects a byte order
+      mark on input from streams where the endianness is not
+      explicit. If a byte order mark is missing from input data, that
+      data is assumed to be in big-endian order.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">A byte order mark from a UTF-8 encoded input stream is not
+      treated specially and just appears as a normal character from
+      the input stream.  It is probably a good idea to skip over this
+      character.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id404054"></a>4.3.4.3.Â <span class="function"><strong>DESCRIBE-CHARACTER-ENCODINGS</strong></span></h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">The set of character encodings supported by Clozure CL can be
+    retrieved by calling
+    <span class="function"><strong>CCL:DESCRIBE-CHARACTER-ENCODINGS</strong></span>.</p>
+              <p>
+                <div class="refentrytitle">
+                  <a id="f_describe-character-encodings"></a>
+                  <strong>[Function]</strong>
+                  <br></br>
+                  <code>
+	    <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>describe-character-encodings</strong></span>
+	  </code>
+                </div>
+                <div class="refentrytitle">Writes descriptions of defined character
+	  encodings to *terminal-io*.</div>
+              </p>
+              <p>
+                <div>
+                  <div class="refsect1" lang="en" xml:lang="en">
+                    <a xmlns="http://www.w3.org/1999/xhtml" id="id404125"></a>
+                    <div class="header">Description:</div>
+                    <p xmlns="http://www.w3.org/1999/xhtml">Writes descriptions of all defined character encodings
+	  to <em class="varname">*terminal-io*</em>.  These descriptions
+	  include the names of the encoding's aliases and a doc string
+	  which briefly describes each encoding's properties and
+	  intended use.</p>
+                  </div>
+                  <div class="refsect1" lang="en" xml:lang="en">
+                    <a xmlns="http://www.w3.org/1999/xhtml" id="id404142"></a>
+                    <div class="header">See Also:</div>
+                    <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#Character-Encodings" title="4.3.4.Â Character Encodings">SectionÂ 4.3.4, âCharacter Encodingsâ</a>, <a class="xref" href="#External-Formats" title="4.3.2.Â External Formats">SectionÂ 4.3.2, âExternal Formatsâ</a>, <a class="xref" href="#Supported-Character-Encodings" title="4.3.4.4.Â Supported Character Encodings">SectionÂ 4.3.4.4, âSupported Character Encodingsâ</a></span>
+                  </div>
+                </div>
+              </p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Supported-Character-Encodings"></a>4.3.4.4.Â Supported Character Encodings</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">The list of supported encodings is reproduced here.  Most
+     encodings have aliases, e.g. the encoding named
+     <code class="literal">:ISO-8859-1</code> can also be referred to by the
+     names <code class="literal">:LATIN1</code> and <code class="literal">:IBM819</code>,
+     among others.  Where possible, the keywordized name of an
+     encoding is equivalent to the preferred MIME charset name (and
+     the aliases are all registered IANA charset names.)</p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-1</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which all character codes map to their Unicode
+       equivalents. Intended to support most characters used in most
+       Western European languages.</p>
+                    <p>Clozure CL uses ISO-8859-1 encoding for
+       <em class="varname">*TERMINAL-IO*</em> and for all streams whose
+       EXTERNAL-FORMAT isn't explicitly specified.  The default for
+       <em class="varname">*TERMINAL-IO*</em> can be set via the
+       <code class="literal">-K</code> command-line argument (see <a class="xref" href="#Command-Line-Options" title="2.5.Â Command Line Options">SectionÂ 2.5, âCommand Line Optionsâ</a>).
+       </p>
+                    <p>ISO-8859-1 just covers the first 256 Unicode code
+       points, where the first 128 code points are equivalent to
+       US-ASCII.  That should be pretty much equivalent to what
+       earliers versions of Clozure CL did that only supported 8-bit characters,
+       but it may not be optimal for users working in a particular
+       locale.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-1, :LATIN1, :L1,
+       :IBM819, :CP819, :CSISOLATIN1</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-2</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in most languages used in
+       Central/Eastern Europe.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-2, :LATIN-2, :L2,
+       :CSISOLATIN2</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-3</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in most languages used in
+       Southern Europe.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-3, :LATIN,3 :L3,
+       :CSISOLATIN3</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-4</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in most languages used in
+       Northern Europe.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-4, :LATIN4, :L4, :CSISOLATIN4</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-5</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Cyrillic
+       alphabet.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-5, :CYRILLIC, :CSISOLATINCYRILLIC,
+       :ISO-IR-144</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-6</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Arabic
+       alphabet.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-6, :ARABIC, :CSISOLATINARABIC,
+       :ISO-IR-127</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-7</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Greek
+       alphabet.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-7, :GREEK, :GREEK8, :CSISOLATINGREEK,
+       :ISO-IR-126, :ELOT_928, :ECMA-118</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-8</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Hebrew
+       alphabet.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-8, :HEBREW, :CSISOLATINHEBREW,
+       :ISO-IR-138</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-9</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#xcf map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Turkish
+       alphabet.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-9, :LATIN5, :CSISOLATIN5,
+       :ISO-IR-148</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-10</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Nordic
+       alphabets.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-10, :LATIN6, :CSISOLATIN6,
+       :ISO-IR-157</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-11</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found the Thai
+       alphabet.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-13</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Baltic
+       alphabets.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-14</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Celtic
+       languages.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-14, :ISO-IR-199, :LATIN8, :L8,
+       :ISO-CELTIC</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-15</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Western European languages
+       (including the Euro sign and some other characters missing from
+       ISO-8859-1.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-15, :LATIN9</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:ISO-8859-16</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Southeast European
+       languages.</p>
+                    <p>Aliases: <code class="literal">:ISO_8859-16, :ISO-IR-199, :LATIN8, :L8,
+       :ISO-CELTIC</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:MACINTOSH</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x7f map to their Unicode equivalents and
+       other codes map to other Unicode character values.
+       Traditionally used on Classic MacOS to encode characters used
+       in western languages.</p>
+                    <p>Aliases: <code class="literal">:MACOS-ROMAN, :MACOSROMAN, :MAC-ROMAN,
+       :MACROMAN</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UCS-2</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 16-bit, fixed-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit word.  The endianness of the encoded data is
+       indicated by the endianness of a byte-order-mark character
+       (#u+feff) prepended to the data; in the absence of such a
+       character on input, the data is assumed to be in big-endian
+       order.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UCS-2BE</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 16-bit, fixed-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit big-endian word. The encoded data is implicitly
+       big-endian; byte-order-mark characters are not interpreted on
+       input or prepended to output.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UCS-2LE</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 16-bit, fixed-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit little-endian word. The encoded data is
+       implicitly little-endian; byte-order-mark characters are not
+       interpreted on input or prepended to output.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:US-ASCII</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 7-bit, fixed-width character encoding in
+       which all character codes map to their Unicode
+       equivalents. </p>
+                    <p>Aliases: <code class="literal">:CSASCII, :CP63,7 :IBM637, :US,
+       :ISO646-US, :ASCII, :ISO-IR-6</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UTF-16</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 16-bit, variable-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit word and characters with larger codes can be
+       encoded in a pair of 16-bit words.  The endianness of the
+       encoded data is indicated by the endianness of a
+       byte-order-mark character (#u+feff) prepended to the data; in
+       the absence of such a character on input, the data is assumed
+       to be in big-endian order. Output is written in native
+       byte-order with a leading byte-order mark.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UTF-16BE</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 16-bit, variable-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit big-endian word and characters with larger
+       codes can be encoded in a pair of 16-bit big-endian words.  The
+       endianness of the encoded data is implicit in the encoding;
+       byte-order-mark characters are not interpreted on input or
+       prepended to output.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UTF-16LE</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 16-bit, variable-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit little-endian word and characters with larger
+       codes can be encoded in a pair of 16-bit little-endian words.
+       The endianness of the encoded data is implicit in the encoding;
+       byte-order-mark characters are not interpreted on input or
+       prepended to output.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UTF-32</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 32-bit, fixed-length encoding in which all
+       Unicode characters can be encoded in a single 32-bit word.  The
+       endianness of the encoded data is indicated by the endianness
+       of a byte-order-mark character (#u+feff) prepended to the data;
+       in the absence of such a character on input, input data is
+       assumed to be in big-endian order.  Output is written in native
+       byte order with a leading byte-order mark.</p>
+                    <p>Alias: <code class="literal">:UTF-4</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UTF-32BE</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 32-bit, fixed-length encoding in which all
+       Unicode characters encoded in a single 32-bit word. The encoded
+       data is implicitly big-endian; byte-order-mark characters are
+       not interpreted on input or prepended to
+       output.</p>
+                    <p>Alias: <code class="literal">:UCS-4BE</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UTF-8</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, variable-length character encoding in
+       which characters with CHAR-CODEs in the range #x00-#x7f can be
+       encoded in a single octet; characters with larger code values
+       can be encoded in 2 to 4 bytes.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:UTF-32LE</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>A 32-bit, fixed-length encoding in which all
+       Unicode characters can encoded in a single 32-bit word. The
+       encoded data is implicitly little-endian; byte-order-mark
+       characters are not interpreted on input or prepended to
+       output.</p>
+                    <p>Alias: <code class="literal">:UCS-4LE</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:Windows-31j</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, variable-length character encoding in
+     which character code points in the range #x00-#x7f can be encoded
+     in a single octet; characters with larger code values can be
+     encoded in 2 bytes.</p>
+                    <p>Aliases: <code class="literal">:CP932, :CSWINDOWS31J</code></p>
+                  </dd>
+                  <dt>
+                    <span class="term">
+                      <code class="literal">:EUC-JP</code>
+                    </span>
+                  </dt>
+                  <dd>
+                    <p>An 8-bit, variable-length character encoding in
+     which character code points in the range #x00-#x7f can be encoded
+     in a single octet; characters with larger code values can be
+     encoded in 2 bytes.</p>
+                    <p>Alias: <code class="literal">:EUCJP</code></p>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id418921"></a>4.3.4.5.Â Encoding and Decoding Strings</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL provides functions to encode and decode strings
+to and from vectors of type (simple-array (unsigned-byte 8)).</p>
+              <p>
+                <div class="refentrytitle">
+                  <a id="count-characters-in-octet-vector"></a>
+                  <strong>[Function]</strong>
+                  <br></br>
+                  <code>
+	<span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>count-characters-in-octet-vector</strong></span>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>vector</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code><em class="varname">&amp;key</em></code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>start</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>end</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>external-format</code></em>
+    </code>
+                </div>
+                <div class="refentrytitle"></div>
+              </p>
+              <p>
+                <div>
+                  <div class="refsect1" lang="en" xml:lang="en">
+                    <a xmlns="http://www.w3.org/1999/xhtml" id="id418997"></a>
+                    <div class="header">Description:</div>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    Returns the number of characters that would be produced by
+    decoding <em class="varname">vector</em> (or the subsequence thereof
+    delimited by <em class="varname">start</em> and <em class="varname">end</em>)
+    according to <em class="varname">external-format</em>.
+  </p>
+                  </div>
+                </div>
+              </p>
+              <p>
+                <div class="refentrytitle">
+                  <a id="decode-string-from-octets"></a>
+                  <strong>[Function]</strong>
+                  <br></br>
+                  <code>
+	<span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>decode-string-from-octets</strong></span>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>vector</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code><em class="varname">&amp;key</em></code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>start</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>end</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>external-format</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>string</code></em>
+    </code>
+                </div>
+                <div class="refentrytitle"></div>
+              </p>
+              <p>
+                <div>
+                  <div class="refsect1" lang="en" xml:lang="en">
+                    <a xmlns="http://www.w3.org/1999/xhtml" id="id419092"></a>
+                    <div class="header">Description:</div>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    Decodes the octets in <em class="varname">vector</em> (or the subsequence
+    of it delimited by <em class="varname">start</em> and
+    <em class="varname">end</em>) into a string according
+    to <em class="varname">external-format</em>.
+  </p>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    If <em class="varname">string</em> is supplied, output will be written into it.
+    It must be large enough to hold the decoded characters.  If <em class="varname">
+    string</em> is not supplied, a new string will be allocated to
+    hold the decoded characters.
+  </p>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    Returns, as multiple values, the decoded string and the position in
+    <em class="varname">vector</em> where the decoding ended.
+  </p>
+                  </div>
+                </div>
+              </p>
+              <p>
+                <div class="refentrytitle">
+                  <a id="encode-string-to-octets"></a>
+                  <strong>[Function]</strong>
+                  <br></br>
+                  <code>
+	<span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>encode-string-to-octets</strong></span>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>string</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code><em class="varname">&amp;key</em></code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>start</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>end</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>external-format</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>use-byte-order-mark</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>vector</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>vector-offset</code></em>
+    </code>
+                </div>
+                <div class="refentrytitle"></div>
+              </p>
+              <p>
+                <div>
+                  <div class="refsect1" lang="en" xml:lang="en">
+                    <a xmlns="http://www.w3.org/1999/xhtml" id="id419216"></a>
+                    <div class="header">Description:</div>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    Encodes <em class="varname">string</em> (or the substring delimited by
+    <em class="varname">start</em> and <em class="varname">end</em>)
+    into <em class="varname">external-format</em> and returns, as multiple
+    values, a vector of octets containing the encoded data and an integer
+    that specifies the offset into the vector where the encoded data ends.
+  </p>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    When <em class="varname">use-byte-order-mark</em> is true, a byte-order mark
+    will be included in the encoded data.
+  </p>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    If <em class="varname">vector</em> is supplied, output will be written
+    to it.  It must be of type (simple-array (unsigned-byte 8)) and be
+    large enough to hold the encoded data.  If it is not supplied, the function
+    will allocate a new vector.
+  </p>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    If <em class="varname">vector-offset</em> is supplied, data will be written
+    into the output vector starting at that offset.
+  </p>
+                  </div>
+                </div>
+              </p>
+              <p>
+                <div class="refentrytitle">
+                  <a id="string-size-in-octets"></a>
+                  <strong>[Function]</strong>
+                  <br></br>
+                  <code>
+	<span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>string-size-in-octets</strong></span>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>string</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code><em class="varname">&amp;key</em></code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>start</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>end</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>external-format</code></em>
+	<em xmlns="http://www.w3.org/1999/xhtml" class="parameter"><code>use-byte-order-mark</code></em>
+    </code>
+                </div>
+                <div class="refentrytitle"></div>
+              </p>
+              <p>
+                <div>
+                  <div class="refsect1" lang="en" xml:lang="en">
+                    <a xmlns="http://www.w3.org/1999/xhtml" id="id419335"></a>
+                    <div class="header">Description:</div>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    Returns the number of octets required to encode
+    <em class="varname">string</em> (or the substring delimited by
+    <em class="varname">start</em> and <em class="varname">end</em>) into
+    <em class="varname">external-format</em>.
+  </p>
+                    <p xmlns="http://www.w3.org/1999/xhtml">
+    When <em class="varname">use-byte-order-mark</em> is true, the returned
+    size will include space for a byte-order marker.
+  </p>
+                  </div>
+                </div>
+              </p>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Pathanmes"></a>4.4.Â Pathnames</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="pathname-tilde-expansion"></a>4.4.1.Â Pathname Expansion</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Leading tilde (~) characters in physical pathname namestrings
+        are expanded in the way that most shells do:</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">"~user/..."</code> can be used to refer to an absolute pathname rooted
+        at the home directory of the user named "user".</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">"~/..."</code> can be used to refer to an absolute pathname rooted at
+        the home directory of the current user.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Predefined-Logical-Hosts"></a>4.4.2.Â Predefined Logical Hosts</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL sets up logical pathname translations for logical hosts:  <code class="literal">ccl</code> and <code class="literal">home</code></p>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="id419423" class="indexterm"></a>
+            <p xmlns="http://www.w3.org/1999/xhtml">The <code class="literal">CCL</code> logical host should point to the
+        <code class="literal">ccl</code> directory.  It is used for a variety of
+        purposes by Clozure CL including: locating Clozure CL source code,
+        <code class="literal">require</code> and <code class="literal">provide</code>, accessing
+        foreign function information, and the Clozure CL build process. It
+        is set to the value of the environment variable
+        <em class="varname">CCL_DEFAULT_DIRECTORY</em>, which is set by the
+        openmcl shell script <a class="xref" href="#The-ccl-Shell-Script" title="2.3.1.Â The ccl Shell Script">SectionÂ 2.3.1, âThe ccl Shell Scriptâ</a>.  If
+        <em class="varname">CCL_DEFAULT_DIRECTORY</em> is not set, then it is set
+        to the directory containing the current heap image.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="pathnames-on-darwin"></a>4.4.3.Â OS X (Darwin)</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL assumes that pathname strings are decomposed UTF-8.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="pathnames-on-linux"></a>4.4.4.Â Linux</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Pathname strings are treated as null-terminated strings
+        coded in the encoding named by the value returned by the function
+      <em class="varname">CCL:PATHNAME-ENCODING-NAME</em>.  This value may be changed
+      with <em class="varname">SETF</em>.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="pathnames-on-freebsd"></a>4.4.5.Â FreeBSD</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Pathname strings are treated as null-terminated strings
+        encoded according to the current locale; a future release may
+        change this convention to use UTF-8.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Memory-Mapped-Files"></a>4.5.Â Memory-mapped Files</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">In release 1.2 and later, Clozure CL
+      supports <a class="glossterm" href="#memory_mapped_file"><em class="glossterm">memory-mapped
+        files</em></a>. On operating systems that support memory-mapped
+      files (including Mac OS X, Linux, and FreeBSD), the operating
+      system can arrange for a range of virtual memory addresses to
+      refer to the contents of an open file. As long as the file remains
+      open, programs can read values from the file by reading addresses
+      in the mapped range.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Using memory-mapped files may in some cases be more
+      efficient than reading the contents of a file into a data
+      structure in memory.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL provides the
+      functions <em class="varname">CCL:MAP-FILE-TO-IVECTOR</em>
+      and <em class="varname">CCL:MAP-FILE-TO-OCTET-VECTOR</em> to support
+      memory-mapping. These functions return vectors whose contents are
+      the contents of memory-mapped files. Reading an element of such a
+      vector returns data from the corresponding position in the
+      file.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Without memory-mapped files, a common idiom for reading the
+      contents of files might be something like this:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(let* ((stream (open pathname :direction :input :element-type '(unsigned-byte 8)))
+       (vector (make-array (file-size-to-vector-size stream)
+                           :element-type '(unsigned-byte 8))))
+  (read-sequence vector stream))
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Using a memory-mapped files has a result that is the same in
+      that, like the above example, it returns a vector whose contents are
+      the same as the contents of the file. It differs in that the above
+      example creates a new vector in memory and copies the file's
+      contents into it; using a memory-mapped file instead arranges for
+      the vector's elements to point to the file's contents on disk
+      directly, without copying them into memory first.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The vectors returned by <em class="varname">CCL:MAP-FILE-TO-IVECTOR</em>
+      and <em class="varname">CCL:MAP-FILE-TO-OCTET-VECTOR</em> are read-only; any
+      attempt to change an element of a vector returned by these
+      functions results in a memory-access error. Clozure CL does not
+      currently support writing data to memory-mapped files.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Vectors created by <em class="varname">CCL:MAP-FILE-TO-IVECTOR</em>
+      and <em class="varname">CCL:MAP-FILE-TO-OCTET-VECTOR</em> are required to
+      respect Clozure CL's limit on the total size of an array. That means
+      that you cannot use these functions to create a vector longer
+      than <em class="varname">ARRAY-TOTAL-SIZE-LIMIT</em>, even if the filesystem
+      supports file sizes that are larger. The value
+      of <em class="varname">ARRAY-TOTAL-SIZE-LIMIT</em> is <em class="varname">(EXPT 2 24)</em>
+      on 32-but platforms; and <em class="varname">(EXPT 2 56)</em> on 64-bit
+      platforms.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id419606" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="map-file-to-ivector"></a>CCL:MAP-FILE-TO-IVECTOR</em>
+        <em class="parameter"><code>pathname</code></em>
+        <em class="parameter"><code>element-type</code></em>
+        [Function]</strong></span>
+    </p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+            <dl>
+              <dt>
+                <span class="term">
+                  <em class="varname">pathname</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The pathname of the file to be memory-mapped.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">element-type</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The element-type of the vector to be
+            created. Specified as
+            a <a class="glossterm" href="#type-specifier"><em class="glossterm">type-specifier</em></a>
+            that names a subtype of either <em class="varname">SIGNED-BYTE</em>
+            or <em class="varname">UNSIGNED-BYTE</em>.</p>
+              </dd>
+            </dl>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      The <em class="varname">map-file-to-ivector</em> function tries to
+      open the file at <em class="parameter"><code>pathname</code></em> for reading. If
+      successful, the function maps the file's contents to a range of
+      virtual addresses. If successful, it returns a read-only vector
+      whose element-type is given
+      by <em class="parameter"><code>element-type</code></em>, and whose contents are
+      the contents of the memory-mapped file.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The returned vector is
+      a <a class="glossterm" href="#displaced-array"><em class="glossterm">displaced-array</em></a>
+      whose element-type is <em class="varname">(UPGRADED-ARRAY-ELEMENT-TYPE
+        element-type)</em>. The target of the displaced array is a
+      vector of type <em class="varname">(SIMPLE-ARRAY element-type (*))</em> whose
+      elements are the contents of the memory-mapped file.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Because of alignment issues, the mapped file's contents
+      start a few bytes (4 bytes on 32-bit platforms, 8 bytes on
+      64-bit platforms) into the vector. The displaced array returned
+      by <em class="varname">CCL:MAP-FILE-TO-IVECTOR</em> hides this overhead, but
+      it's usually more efficient to operate on the underlying simple
+      1-dimensional array.  Given a displaced array (like the value
+      returned by <em class="varname">CCL:MAP-FILE-TO-IVECTOR</em>), the function
+      <em class="varname">ARRAY-DISPLACEMENT</em> returns the underlying array and
+      the displacement index in elements.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Currently, Clozure CL supports only read operations on
+      memory-mapped files. If you try to change the contents of an array
+      returned by <em class="varname">map-file-to-ivector</em>, Clozure CL signals
+      a memory error.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id419739" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="unmap-ivector"></a>CCL:UNMAP-IVECTOR</em>
+        <em class="parameter"><code>displaced-array</code></em>
+        [Function]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If the argument is a displaced-array returned
+      by <em class="varname">map-file-to-ivector</em>, and if it has not yet
+      been unmapped by this function,
+      then <em class="varname">unmap-ivector</em> undoes the memory mapping,
+      closes the mapped file, and changes the displaced-array so that its
+      target is an empty vector (of length zero).</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id419775" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="map-file-to-octet-vector"></a>CCL:MAP-FILE-TO-OCTET-VECTOR</em>
+        <em class="parameter"><code>pathname</code></em>
+        [Function]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This function is a synonym for <em class="varname">(CCL:MAP-FILE-TO-IVECTOR
+        pathname '(UNSIGNED-BYTE 8))</em> It is provided as a convenience
+      for the common case of memory-mapping a file as a vector of
+      bytes.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id419807" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="unmap-octet-vector"></a>CCL:UNMAP-OCTET-VECTOR</em>
+        <em class="parameter"><code>displaced-array</code></em>
+        [Function]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This function is a synonym
+      for <em class="varname">(CCL:UNMAP-IVECTOR)</em></p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Static_Variables"></a>4.6.Â Static Variables</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL supports the definition
+      of <a class="glossterm" href="#static_variable"><em class="glossterm">static
+        variables</em></a>, whose values are the same across threads,
+      and which may not be dynamically bound. The value of a static
+      variable is thus the same across all threads; changing the value
+      in one thread changes it for all threads.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Attempting to dynamically rebind a static variable (for
+      instance, by using <em class="varname">LET</em>, or using the variable name as
+      a parameter in a <em class="varname">LAMBDA</em> form) signals an
+      error. Static variables are shared global resources; a dynamic
+      binding is private to a single thread.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Static variables therefore provide a simple way to share
+      mutable state across threads. They also provide a simple way to
+      introduce race conditions and obscure bugs into your code, since
+      every thread reads and writes the same instance of a given static
+      variable. You must take care, therefore, in how you change the
+      values of static variables, and use normal multithreaded
+      programming techniques, such as locks or semaphores, to protect
+      against race conditions.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In Clozure CL, access to a static variable is usually faster than
+      access to a special variable that has not been declared
+      static.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id419881" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="defstatic"></a>DEFSTATIC</em>
+        <em class="parameter"><code>var</code></em>
+        <em class="parameter"><code>value</code></em>
+        <em class="varname">&amp;key</em>
+        <em class="parameter"><code>doc-string</code></em>
+        [Macro]</strong></span>
+    </p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+            <dl>
+              <dt>
+                <span class="term">
+                  <em class="varname">var</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The name of the new static variable.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">value</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The initial value of the new static variable.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">doc-string</em>
+                </span>
+              </dt>
+              <dd>
+                <p>A documentation string that is assigned to the new
+            variable.</p>
+              </dd>
+            </dl>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Proclaims the
+      variable <a class="glossterm" href="#special_variable"><em class="glossterm">special</em></a>,
+      assigns the variable the supplied value, and assigns
+      the <em class="varname">doc-string</em> to the
+      variable's <em class="varname">VARIABLE</em> documentation. Marks the
+      variable static, preventing any attempt to dynamically rebind
+      it. Any attempt to dynamically rebind <em class="varname">var</em>
+      signals an error.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Saving-Applications"></a>4.7.Â Saving Applications</h2>
+              </div>
+            </div>
+          </div>
+          <a xmlns="http://www.w3.org/1999/xhtml" id="id419993" class="indexterm"></a>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL provides the
+      function <code class="literal">CCL:SAVE-APPLICATION</code>, which creates a file
+      containing an archived Lisp memory image.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL consists of a small executable called the
+      Lisp <a class="glossterm" href="#lisp_image"><em class="glossterm">kernel</em></a>, which
+      implements the very lowest level features of the Lisp system, and
+      an <a class="glossterm" href="#lisp_image"><em class="glossterm">image</em></a>, which
+      contains the in-memory representation of most of the Lisp system,
+      including functions, data structures, variables, and so on. When
+      you start Clozure CL, you are launching the kernel, which then locates
+      and reads an image file, restoring the archived image in
+      memory. Once the image is fully restored, the Lisp system is
+      running.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Using <code class="literal">CCL:SAVE-APPLICATION</code>, you can create a
+      file that contains a modified image, one that includes any changes
+      you've made to the running Lisp system. If you later pass your
+      image file to the Clozure CL kernel as a command-line parameter, it
+      then loads your image file instead of its default one, and Clozure CL
+      starts up with your modifications.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If this scenario seems to you like a convenient way to
+      create an application, that's just as intended. You can create an
+      application by modifying the running Lisp until it does what you
+      want, then use <code class="literal">CCL:SAVE-APPLICATION</code> to preserve your
+      changes and later load them for use.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In fact, you can go further than that. You can replace
+      Clozure CL's <a class="glossterm" href="#toplevel_function"><em class="glossterm">toplevel
+        function</em></a> with your own, and then, when the image is
+      loaded, the Lisp system immediately performs your tasks rather
+      than the default tasks that make it a Lisp development system. If
+      you save an image in which you have done this, the resulting Lisp
+      system is your tool rather than a Lisp development system.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">You can go a step further still. You can
+      tell <code class="literal">CCL:SAVE-APPLICATION</code> to prepend the Lisp kernel
+      to the image file. Doing this makes the resulting image into a
+      self-contained executable binary. When you run the resulting file,
+      the Lisp kernel immediately loads the attached image file and runs
+      your saved system. The Lisp system that starts up can have any
+      behavior you choose. It can be a Lisp development system, but with
+      your customizations; or it can immediately perform some task of
+      your design, making it a specialized tool rather than a general
+      development system.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In other words, you can develop any application you like by
+      interactively modifying Clozure CL until it does what you want, then
+      using <code class="literal">CCL:SAVE-APPLICATION</code> to preserve your changes
+      in an executable image.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">On Mac OS X,
+      the <a class="link" href="#application_builder">application builder</a>
+      uses <code class="literal">CCL:SAVE-APPLICATION</code> to create the executable
+      portion of the <a class="glossterm" href="#application_bundle"><em class="glossterm">application
+        bundle</em></a>. Double-clicking the application bundle runs
+      the executable image created
+      by <code class="literal">CCL:SAVE-APPLICATION</code>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Also on Mac OS X, Clozure CL supports an object type
+      called <code class="literal">MACPTR</code>, which is the type of pointers into the
+      foreign (Mac OS) heap. Examples of
+      commonly-user <code class="literal">MACPTR</code> objects are Cocoa windows and
+      other dynamically-allocated Mac OS system objects.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Because a <code class="literal">MACPTR</code> object is a pointer into a
+      foreign heap that exists for the lifetime of the running Lisp
+      process, and because a saved image is used by loading it into a
+      brand new Lisp process, saved <code class="literal">MACPTR</code> objects cannot
+      be relied on to point to the same things when reconstituted from a
+      saved image. In fact, a restored <code class="literal">MACPTR</code> object might
+      point to anything at allâfor example an arbitrary location
+      in the middle of a block of code, or a completely nonexistent
+      virtual address.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For that reason, <code class="literal">CCL:SAVE-APPLICATION</code> converts
+      all <code class="literal">MACPTR</code> objects to <code class="literal">DEAD-MACPTR</code>
+      objects when writing them to an image
+      file. A <code class="literal">DEAD-MACPTR</code> is functionally identical to
+      a <code class="literal">MACPTR</code>, except that code that operates
+      on <code class="literal">MACPTR</code> objects distinguishes them
+      from <code class="literal">DEAD-MACPTR</code> objects and can handle them
+      appropriatelyâsignaling errors, for example.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">As of Clozure CL 1.2, there is one exception to the conversion
+      of <code class="literal">MACPTR</code> to <code class="literal">DEAD-MACPTR</code> objects:
+      a <code class="literal">MACPTR</code> object that points to the address 0 is not
+      converted, because address 0 can always be relied upon to refer to
+      the same thing.</p>
+          <a xmlns="http://www.w3.org/1999/xhtml" id="id420215" class="indexterm"></a>
+          <p xmlns="http://www.w3.org/1999/xhtml">As of Clozure CL 1.2, the constant <code class="literal">CCL:+NULL-PTR+</code>
+      refers to a <code class="literal">MACPTR</code> object that points to address 0.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">On all supported platforms, you can
+      use <code class="literal">CCL:SAVE-APPLICATION</code> to create a command-line
+      tool that runs the same way any command-line program
+      does. Alternatively, if you choose not to prepend the kernel, you
+      can save an image and then later run it by passing it as a
+      command-line parameter to the <code class="literal">opencml</code>
+      or <code class="literal">opencml64</code> script.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id420262" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="save-application"></a>SAVE-APPLICATION</em>
+        <em class="parameter"><code>filename</code></em>
+        <em class="varname">&amp;key</em>
+        <em class="parameter"><code>toplevel-function</code></em>
+        <em class="parameter"><code>init-file</code></em>
+        <em class="parameter"><code>error-handler</code></em>
+        <em class="parameter"><code>application-class</code></em>
+        <em class="parameter"><code>clear-clos-caches</code></em>
+        <em class="parameter"><code>(purify t)</code></em>
+        <em class="parameter"><code>impurify</code></em>
+        <em class="parameter"><code>(mode #o644)</code></em>
+        <em class="parameter"><code>prepend-kernel</code></em>
+        [Function]</strong></span>
+    </p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+            <dl>
+              <dt>
+                <span class="term">
+                  <em class="varname">filename</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The pathname of the file to be created when Clozure CL
+            saves the application.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">toplevel-function</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The function to be executed after startup is
+            complete. The toplevel is a function of no arguments that
+            performs whatever actions the lisp system should perform
+            when launched with this image.</p>
+                <p>If this parameter is not supplied, Clozure CL uses its
+            default toplevel. The default toplevel runs
+            the <a class="glossterm" href="#REPL"><em class="glossterm">read-eval-print
+              loop</em></a>.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">init-file</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The pathname of a Lisp file to be loaded when the
+            image starts up. You can place initialization expressions in
+            this file, and use it to customize the behavior of the Lisp
+            system when it starts up.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">error-handler</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The error-handling mode for the saved image. The
+            supplied value determines what happens when an error is not
+            handled by the saved image. Valid values
+            are <code class="literal">:quit</code> (Lisp exits with an error
+            message); <code class="literal">:quit-quietly</code> (Lisp exits without an
+            error message); or <code class="literal">:listener</code> (Lisp enters a
+            break loop, enabling you to debug the problem by interacting
+            in a listener). If you don't supply this parameter, the
+            saved image uses the default error handler
+            (<code class="literal">:listener</code>).</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">application-class</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The CLOS class that represents the saved Lisp
+            application. Normally you don't need to supply this
+            parameter; <code class="literal">CCL:SAVE-APPLICATION</code> uses the
+            class <code class="literal">CCL:LISP-DEVELOPMENT-SYSTEM</code>. In some
+            cases you may choose to create a custom application class;
+            in that case, pass the name of the class as the value for
+            this parameter.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">clear-clos-caches</em>
+                </span>
+              </dt>
+              <dd>
+                <p>If true, ensures that CLOS caches are emptied before
+            saving the image. Normally you don't need to supply this
+            parameter, but if for some reason you want to ensure the
+            CLOS caches are clear when the image starts up, you can pass
+            any true value.</p>
+              </dd>
+            </dl>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml"></p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="concatenating-fasl-files"></a>4.8.Â Concatenating FASL Files</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      Multiple fasl files can be concatenated into a single file.
+    </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="fasl-concatenate"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>fasl-concatenate</strong></span> out-file fasl-files <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> (:if-exists :error)</code>
+            </div>
+            <div class="refentrytitle">
+	Concatenate several fasl files, producing a single output file.
+      </div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id420534"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">out-file</span></i>---
+	      Name of the file in which to store the concatenation.
+	    </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">fasl-files</span></i>---
+	      List of names of fasl files to concatenate.
+	    </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">:if-exists</span></i>---
+	      As for <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>OPEN</strong></span>, defaults to <code xmlns="http://www.w3.org/1999/xhtml" class="literal">
+	      :error</code>
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id420593"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	Creates a fasl file which, when loaded, will have the same
+	effect as loading the individual input fasl files in the
+	specified order.  The single file might be easier to
+	distribute or install, and loading it may be at least a little
+	faster than loading the individual files (since it avoids the
+	overhead of opening and closing each file in succession.)
+      </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	The PATHNAME-TYPE of the output file and of each input file
+	defaults to the current platform's fasl file type (.dx64fsl or
+	whatever.)  If any of the input files has a different
+	type/extension an error will be signaled, but it doesn't
+	otherwise try too hard to verify that the input files are real
+	fasl files for the current platform.
+      </p>
+              </div>
+            </div>
+          </p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="floating-point"></a>4.9.Â Floating Point Numbers</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      In Clozure CL, the Common Lisp types short-float and single-float are
+      implemented as IEEE single precision values; double-float and
+      long-float are IEEE double precision values.  On 64-bit
+      platforms, single-floats are immediate values (like fixnums and
+      characters).
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+    Floating-point exceptions are generally enabled and detected.  By
+    default, threads start up with overflow, division-by-zero, and
+    invalid enabled, and the rounding mode is set to nearest. The
+    functions <em class="varname">SET-FPU-MODE</em> and
+    <em class="varname">GET-FPU-MODE</em> provide user control over
+    floating-point behavior.
+  </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_get-fpu-mode"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>get-fpu-mode</strong></span> <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> mode</code>
+            </div>
+            <div class="refentrytitle">
+	Return the state of exception-enable and rounding-mode control
+	flags for the current thread.
+      </div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id420684"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">mode</span></i>---
+	      One of the keywords :rounding-mode, :overflow,
+	      :underflow, :division-by-zero, :invalid, :inexact.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id420707"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	If <em class="varname">mode</em> is supplied, returns the value of
+	the corresponding control flag for the current thread.
+      </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	Otherwise, returns a list of keyword/value pairs which
+	describe the floating-point exception-enable and rounding-mode
+	control flags for the current thread.
+      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">rounding-mode</span></i>---
+	      One of :nearest, :zero, :positive, :negative
+	    </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">overflow, underflow, division-by-zero, invalid, inexact
+	  </span></i>---
+	      If true, the floating-point exception is signaled.
+	      If NIL, it is masked.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_set-fpu-mode"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>set-fpu-mode</strong></span> <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em>
+      rounding-mode overflow underflow division-by-zero
+      invalid inexact</code>
+            </div>
+            <div class="refentrytitle">
+	Set the state of exception-enable and rounding-mode control
+	flags for the current thread.
+      </div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id420803"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">rounding-mode</span></i>---
+	      If supplied, must be one of :nearest, :zero, :positive, or
+	      :negative.
+	    </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">overflow, underflow, division-by-zero, invalid, inexact</span></i>---NIL to mask the exception, T to signal it.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id420839"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	Sets the current thread's exception-enable and rounding-mode
+	control flags to the indicated values for arguments that are
+	supplied, and preserves the values assoicated with those
+	that aren't supplied.
+      </p>
+              </div>
+            </div>
+          </p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="watched-objects"></a>4.10.Â Watched Objects</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+    As of release 1.4, Clozure CL provides a way for lisp objects to
+    be watched so that a condition will be signaled when a thread
+    attempts to write to the watched object. For a certain class of
+    bugs (someone is changing this value, but I don't know who), this
+    can be extremely helpful.
+  </p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="watched-watch"></a>4.10.1.Â WATCH</h3>
+                </div>
+              </div>
+            </div>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_watch"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>watch</strong></span> <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> object</code>
+              </div>
+              <div class="refentrytitle">
+	Monitor a lisp object for writes.
+      </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id420914"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">object</span></i>---
+	      Any memory-allocated lisp object.
+	    </p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id420936"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+	The WATCH function arranges for the specified object to be
+	monitored for writes. This is accomplished by copying the
+	object to its own set of virtual memory pages, which are then
+	write-protected. This protection is enforced by the computer's
+	memory-management hardware; the write-protection does not slow
+	down reads at all.
+      </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+	When any write to the object is attempted, a
+	WRITE-TO-WATCHED-OBJECT condition will be signaled.
+      </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+	When called with no arguments, WATCH returns a freshly-consed
+	list of the objects currently being watched.
+      </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+	WATCH returns NIL if the object cannot be watched (typically
+	because the object is in a static or pure memory area).
+      </p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="watch-dwim"></a>
+                  <div class="header">DWIM:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      WATCH operates at a fairly low level; it is not possible to
+      avoid the details of the internal representation of objects.
+      Nevertheless, as a convenience, WATCHing a standard-instance,
+      a hash-table, or a multi-dimensional or non-simple CL array
+      will watch the underlying slot-vector, hash-table-vector, or
+      data-vector, respectively.
+      </p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="watch-discuss"></a>
+                  <div class="header">Discussion:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      WATCH can monitor any memory-allocated lisp object.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      In Clozure CL, a memory-allocated object is either a cons cell
+      or a uvector.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      WATCH operates on cons cells, not lists. In order to watch a
+      chain of cons cells, each cons cell must be watched
+      individually. Because each watched cons cell takes up its own
+      own virtual memory page (4 Kbytes), it's only feasible to watch
+      relatively short lists.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      If a memory-allocated object isn't a cons cell, then it is a
+      vector-like object called a uvector. A uvector is a
+      memory-allocated lisp object whose first word is a header that
+      describes the object's type and the number of elements that it
+      contains.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      So, a hash table is a uvector, as is a string, a standard
+      instance, a double-float, a CL array or vector, and so forth.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Some CL objects, like strings and other simple vectors, map in a
+      straightforward way onto the uvector representation. It is easy
+      to understand what happens in such cases. The uvector index
+      corresponds directly to the vector index:
+    </p>
+                  <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+? (defvar *s* "xxxxx")
+*S*
+? (watch *s*)
+"xxxxx"
+? (setf (char *s* 3) #\o)
+&gt; Error: Write to watched uvector "xxxxx" at index 3
+&gt;        Faulting instruction: (movl (% eax) (@ -5 (% r15) (% rcx)))
+&gt; While executing: SET-CHAR, in process listener(1).
+&gt; Type :POP to abort, :R for a list of available restarts.
+&gt; Type :? for other options.
+
+    </pre>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      In the case of more complicated objects (e.g., a hash-table, a
+      standard-instance, a package, etc.), the elements of the uvector
+      are like slots in a structure. It's necessary to know which one
+      of those "slots" contains the data that will be changed when the
+      object is written to.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      As mentioned above, watch knows about arrays, hash-tables, and
+      standard-instances, and will automatically watch the appropriate
+      data-containing element.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      An example might make this clearer.
+    </p>
+                  <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+? (defclass foo ()
+    (slot-a slot-b slot-c))
+#&lt;STANDARD-CLASS FOO&gt;
+? (defvar *a-foo* (make-instance 'foo))
+*A-FOO*
+? (watch *a-foo*)
+#&lt;SLOT-VECTOR #xDB00D&gt;
+;;; Note that WATCH has watched the internal slot-vector object
+? (setf (slot-value *a-foo* 'slot-a) 'foo)
+&gt; Error: Write to watched uvector #&lt;SLOT-VECTOR #xDB00D&gt; at index 1
+&gt;        Faulting instruction: (movq (% rsi) (@ -5 (% r8) (% rdi)))
+&gt; While executing: %MAYBE-STD-SETF-SLOT-VALUE-USING-CLASS, in process listener(1).
+&gt; Type :POP to abort, :R for a list of available restarts.
+&gt; Type :? for other options.
+
+    </pre>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Looking at a backtrace would presumably show what object and
+      slot name were written.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Note that even though the write was to slot-a, the uvector index
+      was 1 (not 0). This is because the first element of a
+      slot-vector is a pointer to the instance that owns the slots. We
+      can retrieve that to look at the object that was modified:
+    </p>
+                  <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+1 &gt; (uvref (write-to-watched-object-object *break-condition*) 0)
+#&lt;FOO #x30004113502D&gt;
+1 &gt; (describe *)
+#&lt;FOO #x30004113502D&gt;
+Class: #&lt;STANDARD-CLASS FOO&gt;
+Wrapper: #&lt;CLASS-WRAPPER FOO #x300041135EBD&gt;
+Instance slots
+SLOT-A: #&lt;Unbound&gt;
+SLOT-B: #&lt;Unbound&gt;
+SLOT-C: #&lt;Unbound&gt;
+1 &gt;
+ 
+    </pre>
+                </div>
+              </div>
+            </p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="watched-unwatch"></a>4.10.2.Â UNWATCH</h3>
+                </div>
+              </div>
+            </div>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_unwatch"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>unwatch</strong></span> object</code>
+              </div>
+              <div class="refentrytitle">
+	Stop monitoring a lisp object for writes.
+      </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421111"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+    The UNWATCH function ensures that the specified object is in
+    normal, non-monitored memory. If the object is not currently
+    being watched, UNWATCH does nothing and returns NIL. Otherwise,
+    the newly unwatched object is returned.
+  </p>
+                </div>
+              </div>
+            </p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="watched-write-to-watched-object"></a>4.10.3.Â WRITE-TO-WATCHED-OBJECT</h3>
+                </div>
+              </div>
+            </div>
+            <p>
+              <div class="refentrytitle">
+                <a id="c_write-to-watched-object"></a>
+                <strong>[Condition]</strong>
+                <br></br>
+                <code>WRITE-TO-WATCHED-OBJECT</code>
+              </div>
+              <div class="refentrytitle">
+	Condition signaled when a write to a watched object is attempted.
+      </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421159"></a>
+                  <div class="header">Discussion:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      This condition is signaled when a watched object is written
+      to. There are three slots of interest:
+    </p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">object</span></i>---
+	    The actual object that was the destination of the write.
+	  </p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">offset</span></i>---
+	    The byte offset from the tagged object pointer to the
+	    address of the write.
+	  </p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">instruction</span></i>---
+	    The disassembled machine instruction that attempted the write.
+	  </p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421212"></a>
+                  <div class="header">Restarts:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      A few restarts are provided: one will skip over the faulting
+      write instruction and proceed; another offers to unwatch the
+      object and continue.
+    </p>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      There is also an emulate restart. In some common cases, the
+      faulting write instruction can be emulated, enabling the write
+      to be performed without having to unwatch the object (and
+      therefore let other threads potentially write to it). If the
+      faulting instruction isn't recognized, the emulate restart will
+      not be offered.
+    </p>
+                </div>
+              </div>
+            </p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="watch-notes"></a>4.10.4.Â Notes</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  Although some care has been taken to minimize potential problems
+  arising from watching and unwatching objects from multiple
+  threads, there may well be subtle race conditions present that
+  could cause bad behavior.
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  For example, suppose that a thread attempts to write to a watched
+  object. This causes the operating system to generate an
+  exception. The lisp kernel figures out what the exception is, and
+  calls back into lisp to signal the write-to-watched-object
+  condition and perhaps handle the error.
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  Now, as soon lisp code starts running again (for the callback),
+  it's possible that some other thread could unwatch the very
+  watched object that caused the exception, perhaps before we even
+  have a chance to signal the condition, much less respond to it.
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  Having the object unwatched out from underneath a handler may at
+  least confuse it, if not cause deeper trouble. Use caution with
+  unwatch.
+</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="watch-examples"></a>4.10.5.Â Examples</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  Here are a couple more examples in addition to the above examples
+  of watching a string and a standard-instance.
+</p>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id421270"></a>4.10.5.1.Â Fancy arrays</h4>
+                  </div>
+                </div>
+              </div>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+?  (defvar *f* (make-array '(2 3) :element-type 'double-float))
+*F*
+? (watch *f*)
+#(0.0D0 0.0D0 0.0D0 0.0D0 0.0D0 0.0D0)
+;;; Note that the above vector is the underlying data-vector for the array
+? (setf (aref *f* 1 2) pi)
+&gt; Error: Write to watched uvector #&lt;VECTOR 6 type DOUBLE-FLOAT, simple&gt; at index 5
+&gt;        Faulting instruction: (movq (% rax) (@ -5 (% r8) (% rdi)))
+&gt; While executing: ASET, in process listener(1).
+&gt; Type :POP to abort, :R for a list of available restarts.
+&gt; Type :? for other options.
+1 &gt; 
+  </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+    In this case, uvector index in the report is the row-major index
+    of the element that was written to.
+  </p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id421289"></a>4.10.5.2.Â Hash tables</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+    Hash tables are surprisingly complicated. The representation of a
+    hash table includes an element called a hash-table-vector. The
+    keys and values of the elements are stored pairwise in this
+    vector.
+  </p>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+    One problem with trying to monitor hash tables for writes is that
+    the underlying hash-table-vector is replaced with an entirely new
+    one when the hash table is rehashed. A previously-watched
+    hash-table-vector will not be the used by the hash table after
+    rehashing, and writes to the new vector will not be caught.
+  </p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (defvar *h* (make-hash-table))
+*H*
+? (setf (gethash 'noise *h*) 'feep)
+FEEP
+? (watch *h*)
+#&lt;HASH-TABLE-VECTOR #xDD00D&gt;
+;;; underlying hash-table-vector
+? (setf (gethash 'noise *h*) 'ding)
+&gt; Error: Write to watched uvector #&lt;HASH-TABLE-VECTOR #xDD00D&gt; at index 35
+&gt;        Faulting instruction: (lock)
+&gt;          (cmpxchgq (% rsi) (@ (% r8) (% rdx)))
+&gt; While executing: %STORE-NODE-CONDITIONAL, in process listener(1).
+&gt; Type :POP to abort, :R for a list of available restarts.
+&gt; Type :? for other options.
+;;; see what value is being replaced...
+1 &gt; (uvref (write-to-watched-object-object *break-condition*) 35)
+FEEP
+;;; backtrace shows useful context
+1 &gt; :b
+*(1A109F8) : 0 (%STORE-NODE-CONDITIONAL ???) NIL
+ (1A10A50) : 1 (LOCK-FREE-PUTHASH NOISE #&lt;HASH-TABLE :TEST EQL size 1/60 #x30004117D47D&gt; DING) 653
+ (1A10AC8) : 2 (CALL-CHECK-REGS PUTHASH NOISE #&lt;HASH-TABLE :TEST EQL size 1/60 #x30004117D47D&gt; DING) 229
+ (1A10B00) : 3 (TOPLEVEL-EVAL (SETF (GETHASH # *H*) 'DING) NIL) 709
+ ...
+  </pre>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id421319"></a>4.10.5.3.Â Lists</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+    As previously mentioned, WATCH only watches individual cons cells.
+  </p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (defun watch-list (list)
+    (maplist #'watch list))
+WATCH-LIST
+? (defvar *l* (list 1 2 3))
+*L*
+? (watch-list *l*)
+((1 2 3) (2 3) (3))
+? (setf (nth 2 *l*) 'foo)
+&gt; Error: Write to the CAR of watched cons cell (3)
+&gt;        Faulting instruction: (movq (% rsi) (@ 5 (% rdi)))
+&gt; While executing: %SETNTH, in process listener(1).
+&gt; Type :POP to abort, :R for a list of available restarts.
+&gt; Type :? for other options.
+  </pre>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="code-coverage"></a>4.11.Â Code Coverage</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="code-coverage-overview"></a>4.11.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  In Clozure CL 1.4 and later, code coverage provides information
+  about which paths through generated code have been executed and
+  which haven't. For each source form, it can report one of three
+  possible outcomes:
+</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>
+      Not covered: this form was never entered.
+    </p>
+                </li>
+                <li>
+                  <p>
+      Partly covered: This form was entered, and some parts were
+      executed and some weren't.
+    </p>
+                </li>
+                <li>
+                  <p>
+      Fully covered: Every bit of code generated from this form was
+      executed.
+    </p>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="code-coverage-limitations"></a>4.11.2.Â Limitations</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  While the information gathered for coverage of generated code is
+  complete and precise, the mapping back to source forms is of
+  necessity heuristic, and depends a great deal on the behavior of
+  macros and the path of the source forms through compiler
+  transforms. Source information is not recorded for variables, which
+  further limits the source mapping. In practice, there is often
+  enough information scattered about a partially covered function to
+  figure out which logical path through the code was taken and which
+  wasn't. If that doesn't work, you can try disassembling to see which
+  parts of the compiled code were not executed: in the disassembled
+  code there will be references to #&lt;CODE-NOTE [xxx] ...&gt; where xxx
+  is NIL if the code that follows was never executed and non-NIL if it
+  was.
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  Sometimes the situation can be improved by modifying macros to try
+  to preserve more of the input forms, rather than destructuring and
+  rebuilding them.
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  Because the code coverage information is associated with compiled
+  functions, load-time toplevel expressions do not get reported
+  on. You can work around this by creating a function and calling
+  it. I.e. instead of
+  </p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(progn
+  (do-this)
+  (setq that ...) ...))
+  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  do:
+  </p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defun init-this-and-that ()
+  (do-this)
+  (setq that ...)  ...)
+(init-this-and-that)
+  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+Then you can see the coverage information in the definition of
+init-this-and-that.
+</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="code-coverage-usage"></a>4.11.3.Â Usage</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  In order to gather code coverage information, you first have to
+  recompile all your code to include code coverage
+  instrumentation. Compiling files will generate code coverage
+  instrumentation if <code class="literal">CCL:*COMPILE-CODE-COVERAGE*</code>
+  is true:
+  </p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(setq ccl:*compile-code-coverage* t) 
+(recompile-all-your-files) 
+  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  The compilation process will be many times slower than normal, and
+  the fasl files will be many times bigger.
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  When you execute function loaded from instrumented fasl files, they
+  will record coverage information every time they are executed. The
+  system keeps track of which instrumented files have been loaded.
+</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+  The following functions can be used to manage the coverage data:
+</p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_report-coverage"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>report-coverage</strong></span> <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em>
+    (external-format :default) (statistics t) (html t)
+    </code>
+              </div>
+              <div class="refentrytitle">Generate code coverage report</div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421502"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">html</span></i>---
+	  If non-nil, this will generate an HTML report, consisting of
+	  an index file and one html file for each instrumented source
+	  file that has been loaded in the current session. The
+	  individual source file reports are stored in the same
+	  directory as the index file.
+	</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">external-format</span></i>---
+	  Controls the external format of the html files.
+	</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">statistics</span></i>---
+	  If :statistics is non-nil, a comma-separated file is also
+	  generated with the summary of statistics. You can specify a
+	  filename for the statistics argument, otherwise
+	  "statistics.csv" is created in the output directory. See
+	  documentation of ccl:coverage-statistics below for a
+	  description of the values in the statistics file.
+	</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421554"></a>
+                  <div class="header">Example:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      If you've loaded <code class="filename">foo.lx64fsl</code> and
+      <code class="filename">bar.lx64fsl</code>, and have run some tests, you could
+      do
+    </p>
+                  <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(CCL:REPORT-COVERAGE "/my/dir/coverage/report.html")
+    </pre>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+    and this would generate <code class="filename">report.html</code>,
+    <code class="filename">foo_lisp.html</code> and
+    <code class="filename">bar_lisp.html</code>, and
+    <code class="filename">statistics.csv</code> all in
+    <code class="filename">/my/dir/coverage/</code>.
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_reset-coverage"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code>reset-coverage</code>
+              </div>
+              <div class="refentrytitle">
+      Resets all coverage data back to the "Not Executed" state
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421634"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Resets all coverage data back to the "Not Executed" state
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_clear-coverage"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code>clear-coverage</code>
+              </div>
+              <div class="refentrytitle">
+      Forget about all instrumented files that have been loaded.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421672"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Gets rid of the information about which instrumented files have
+      been loaded, so ccl:report-coverage will not report any files,
+      and ccl:save-coverage-in-file will not save any info, until more
+      instrumented files are loaded.
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_save-coverage-in-file"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>save-coverage-in-file</strong></span> pathname
+    </code>
+              </div>
+              <div class="refentrytitle">
+      Save all coverage into to a file so you can restore it later.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421725"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Saves all coverage info in a file, so you can restore the
+      coverage state later. This allows you to combine multiple runs
+      or continue in a later session. Equivalent to
+      (ccl:write-coverage-to-file (ccl:save-coverage) pathname).
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_restore-coverage-from-file"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>restore-coverage-from-file</strong></span> pathname
+    </code>
+              </div>
+              <div class="refentrytitle">
+      Load coverage state from a file.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421776"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Restores the coverage data previously saved with
+      CCL:SAVE-COVERAGE-IN-FILE, for the set of instrumented fasls
+      that were loaded both at save and restore time. I.e. coverage
+      info is only restored for files that have been loaded in this
+      session. For example if in a previous session you had loaded
+      "foo.lx86fsl" and then saved the coverage info, in this session
+      you must load the same "foo.lx86fsl" before calling
+      ccl:restore-coverage-from-file in order to retrieve the stored
+      coverage info for "foo".  Equivalent to (ccl:restore-coverage
+      (ccl:read-coverage-from-file pathname)).
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_save-coverage"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code>save-coverage</code>
+              </div>
+              <div class="refentrytitle">
+      Returns a snapshot of the current coverage data.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421819"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Returns a snapshot of the current coverage data. A snapshot is a
+      copy of the current coverage state. It can be saved in a file
+      with ccl:write-coverage-to-file, reinstated back as the current
+      state with ccl:restore-coverage, or combined with other
+      snapshots with ccl:combine-coverage.
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_restore-coverage"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>restore-coverage</strong></span> snapshot
+    </code>
+              </div>
+              <div class="refentrytitle">
+      Reinstalls a coverage snapshot as the current coverage state.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421872"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Reinstalls a coverage snapshot as the current coverage state.
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_write-coverage-to-file"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>write-coverage-to-file</strong></span> snapshot pathname
+    </code>
+              </div>
+              <div class="refentrytitle">
+      Save a coverage snapshot in a file.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421923"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Saves the coverage snapshot in a file. The snapshot can be
+      loaded back with ccl:read-coverage-from-file or loaded and
+      restored with ccl:restore-coverage-from-file. Note that the file
+      created is actually a lisp source file and can be compiled for
+      faster loading.
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_read-coverage-from-file"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>read-coverage-from-file</strong></span> pathname
+    </code>
+              </div>
+              <div class="refentrytitle">
+      Return the coverage snapshot saved in a file.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id421976"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Returns the snapshot saved in pathname. Doesn't affect the
+      current coverage state. pathname can be the file previously
+      created with ccl:write-coverage-to-file or
+      ccl:save-coverage-in-file, or it can be the name of the fasl
+      created from compiling such a file.
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_coverage-statistics"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>coverage-statistics</strong></span>
+    </code>
+              </div>
+              <div class="refentrytitle">
+      Returns a sequence of coverage-statistics objects, one per source file.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422028"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      Returns a sequence ccl:coverage-statistics objects, one for each
+      source file, containing the same information as that written to
+      the statistics file by ccl:report-coverage. The following
+      accessors are defined for ccl:coverage-statistics objects:
+      </p>
+                  <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                    <dl>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-source-file</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the name of the source file corresponding to this information
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-expressions-total</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the total number of expressions
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-expressions-entered</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the number of source expressions that have been entered
+	    (i.e. at least partially covered)
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-expressions-covered</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the number of source expressions that were fully covered
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-unreached-branches</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the number of conditionals with one branch taken and one not taken
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-code-forms-total</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the total number of code forms. A code form is an
+	    expression in the final stage of compilation, after all
+	    macroexpansion and compiler transforms and simplification
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-code-forms-covered</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the number of code forms that have been entered
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-functions-total</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the total number of functions
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-functions-fully-covered</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the number of functions that were fully covered
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-functions-partly-covered</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the number of functions that were partly covered
+	  </p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <span class="function">
+                            <strong>ccl:coverage-functions-not-entered</strong>
+                          </span>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>
+	    the number of functions never entered
+	  </p>
+                      </dd>
+                    </dl>
+                  </div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="v_compile-code-coverage"></a>
+                <strong>[Variable]</strong>
+                <br></br>
+                <code><em xmlns="http://www.w3.org/1999/xhtml" class="varname">*compile-code-coverage*</em>
+    </code>
+              </div>
+              <div class="refentrytitle">
+      When true, instrument functions for code coverage.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422263"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      This variable controls whether functions are instrumented for
+      code coverage. Files compiled while this variable is true will
+      contain code coverage instrumentation.
+    </p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="v_without-compiling-code-coverage"></a>
+                <strong>[Macro]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>without-compiling-code-coverage</strong></span>
+    </code>
+              </div>
+              <div class="refentrytitle">
+      Don't record code coverange for forms within the body.
+    </div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422315"></a>
+                  <div class="header">Summary:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">
+      This macro arranges so that body doesn't record internal details
+      of code coverage. It will be considered totally covered if it's
+      entered at all. The Common Lisp macros ASSERT and CHECK-TYPE use
+      this macro.
+    </p>
+                </div>
+              </div>
+            </p>
+          </div>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="ccl-ide"></a>ChapterÂ 5.Â The Clozure CL IDE</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#ccl-ide-introduction">5.1. Introduction</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#building-ccl-ide">5.2. Building the IDE</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#running-ccl-ide">5.3. Running the IDE</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#ccl-ide-features">5.4. IDE Features</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#ide-editor-windows">5.4.1. Editor Windows</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#ide-lisp-menu">5.4.2. The Lisp Menu</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#ide-tools-menu">5.4.3. The Tools Menu</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#ide-inspector-window">5.4.4. The Inspector Window</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#ide-source-code">5.5. IDE Sources</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#application-builder">5.6. The Application Builder</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#running-the-application-builder-from-command-line">5.6.1. Running the Application Builder From the Command
+      Line</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="ccl-ide-introduction"></a>5.1.Â Introduction</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL ships with the complete source code for an integrated
+    development environment written using Cocoa on Mac OS X. This
+    chapter describes how to build and use that environment,
+    referred to hereafter simply as "the IDE".</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The IDE provides a programmable text editor, listener
+      windows, an inspector for Lisp data structures, and a means of
+      easily building a Cocoa application in Lisp. In addition, its
+      source code provides an example of a fairly complex Cocoa
+      application written in Lisp.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The current version of the IDE has seen the addition of numerous
+    features and many bugfixes. Although it's by no means a finished product,
+    we hope it will prove more useful than previous versions, and we
+    plan additional work on the IDE for future releases.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="building-ccl-ide"></a>5.2.Â Building the IDE</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Building the Clozure CL IDE is now a very simple
+      process.</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+            <ol type="1">
+              <li>
+                <p>In a shell session, cd to the ccl directory.</p>
+              </li>
+              <li>
+                <p>Run ccl from the shell. The easiest way to do this is
+          generally to execute the ccl or ccl64 command.</p>
+              </li>
+              <li>
+                <p>Evaluate the form <code class="code">(require :cocoa-application)</code></p>
+              </li>
+            </ol>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">For example, assuming that the Clozure CL distribution is
+      installed in "/usr/local/ccl", the following sequence of shell
+      interactions builds the IDE:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+oshirion:ccl mikel$ ccl64
+Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk  (DarwinX8664)!
+? (require :cocoa-application)
+;Loading #P"ccl:cocoa-ide;fasls;cocoa-utils.dx64fsl.newest"...
+;Loading #P"ccl:cocoa-ide;fasls;cocoa-defaults.dx64fsl.newest"...
+
+[...many lines of "Compiling" and "Loading" omitted...]
+
+Saving application to /usr/local/ccl/Clozure CL.app/
+
+oshirion:ccl mikel$ 
+
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL compiles and loads the various subsystems that
+      make up the IDE, then constructs a Cocoa application bundle
+      named "Clozure CL.app" and saves the Lisp image into
+      it. Normally Clozure CL creates the application bundle in the root
+      directory of the Clozure CL distribution.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="running-ccl-ide"></a>5.3.Â Running the IDE</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">After it has been built, you can run the "Clozure CL.app"
+      application normally, by double-clicking its icon. When
+      launched, the IDE initially displays a
+      single <a class="glossterm" href="#listener_window"><em class="glossterm">listener
+        window</em></a> that you can use to interact with Lisp. You
+      can type Lisp expressions for evaluation at the prompt in the
+      listener window. You can also
+      use <a class="glossterm" href="#hemlock"><em class="glossterm">Hemlock</em></a> editing
+      commands to edit the text of expressions in the listener
+      window.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="ccl-ide-features"></a>5.4.Â IDE Features</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="ide-editor-windows"></a>5.4.1.Â Editor Windows</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">You can open an editor window either by choosing Open from
+        the File menu and then selecting a text file, or by choosing
+        New from the File menu. You can also evaluate the
+        expression <code class="code">(ed)</code> in the listener window; in that
+        case Clozure CL creates a new window as if you had chosen New from
+        the File menu.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Editor windows
+        implement <a class="glossterm" href="#hemlock"><em class="glossterm">Hemlock</em></a>
+        editing commands. You can use all the editing and customization
+        features of Hemlock within any editor window (including listener
+        windows).</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="ide-lisp-menu"></a>5.4.2.Â The Lisp Menu</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The Lisp menu provides several commands for interacting
+        with the running Lisp session, in addition to the ways you can
+        interact with it by evaluating expressions. You can evaluate a
+        selected range of text in any editing buffer. You can compile
+        and load the contents of editor windows (please note that in the
+        current version, Clozure CL compiles and loads the contents of the
+        file associated with an editor window; that means that if you
+        try to load or compile a window that has not been saved to a
+        file, the result is an error).</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">You can interrupt computations, trigger breaks, and select
+        restarts from the Lisp menu. You can also display a backtrace or
+        open the <a class="link" href="#section_inspector_window">Inspector
+          window</a>.</p>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id363782"></a>5.4.2.1.Â Checking for Updates</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">At the bottom of the Lisp menu is an item entitled
+        "Check for Updates". If your copy of Clozure CL came from the
+        Clozure Subversion server (which is the preferred source), and
+        if your internet connection is working, then you can select
+        this menu item to check for updates to your copy of
+        Clozure CL.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">When you select "Check for Updates", Clozure CL uses the svn
+        program to query the Clozure Subversion repository and
+        determine whether new updates to Clozure CL are available. (This
+        means that on Mac OS X versions earlier than 10.5, you must
+        ensure that the Subversion client software is installed before
+        using the "Check for Updates" feature. See
+        the <a class="ulink" href="http://www.wikihow.com/Install-Subversion-on-Mac-OS-X" target="_top">wikiHow
+        page</a> on installing Subversion for more information.)
+        If updates are available, Clozure CL automatically downloads and
+        installs them. After a successful download, Clozure CL rebuilds
+        itself, and then rebuilds the IDE on the newly-rebuilt
+        Lisp. Once this process is finished, you should quit the
+        running IDE and start the newly built one (which will be in
+        the same place that the old one was).</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">Normally, Clozure CL can install updates and rebuild itself
+        without any problems. Occasionally, an unforeseen problem
+        (such as a network outage, or a hardware failure) might
+        interrupt the self-rebuilding process, and leave your copy of
+        Clozure CL unusable. If you are expecting to update your copy of
+        Clozure CL frequently, it might be prudent to keep a backup copy of
+        your working environment ready in case of such
+        situtations. You can also always obtain a full, fresh copy of
+        Clozure CL from Clozure's repository..</p>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="ide-tools-menu"></a>5.4.3.Â The Tools Menu</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The tools menu provides access to the Apropos and
+        Processes windows. The Apropos window searches the running Lisp
+        image for symbols that match any text you enter. You can use the
+        Apropos window to quickly find function names and other useful
+        symbols. The Processes window lists all threads running in the
+        current Lisp session. If you double-click a process entry, Clozure CL
+        opens an <a class="link" href="#section_inspector_window">Inspector
+          window</a> on that process.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="ide-inspector-window"></a>5.4.4.Â The Inspector Window</h3>
+                </div>
+              </div>
+            </div>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="section_inspector_window"></a>
+            <p xmlns="http://www.w3.org/1999/xhtml">The Inspector window displays information about a Lisp
+        value. The information displayed varies from the very simple, in
+        the case of a simple data value such as a character, to the
+        complex, in the case of structured data such as lists or CLOS
+        objects. The left-hand column of the window's display shows the
+        names of the object's attributes; the righthand column shows the
+        values associated with those attributes. You can inspect the
+        values in the righthand column by double-clicking them.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Inspecting a value in the righthand column changes the
+        Inspector window to display the double-clicked object. You can
+        quickly navigate the fields of structured data this way,
+        inspecting objects and the objects that they refer
+        to. Navigation buttons at the top left of the window enable you
+        to retrace your steps, backing up to return to previously-viewed
+        objects, and going forward again to objects you navigated into
+        previously.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">You can change the contents of a structured object by
+        evaluating expressions in a listener window. The refresh button
+        (marked with a curved arrow) updates the display of the
+        Inspector window, enabling you to quickly see the results of
+        changing a data structure.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="ide-source-code"></a>5.5.Â IDE Sources</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL builds the IDE from sources in the "objc-bridge" and
+      "cocoa-ide" directories in the Clozure CL distribution. The IDE as a
+      whole is a relatively complicated application, and is probably not
+      the best place to look when you are first trying to understand how
+      to build Cocoa applications. For that, you might benefit more from
+      the examples in the "examples/cocoa/" directory. Once you are
+      familiar with those examples, though, and have some experience
+      building your own application features using Cocoa and the
+      Objective-C bridge, you might browse through the IDE sources to
+      see how it implements its features.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The search path for Clozure CL's <code class="code">REQUIRE</code> feature
+      includes the "objc-bridge" and "cocoa-ide" directories. You can
+      load features defined in these directories by
+      using <code class="code">REQUIRE</code>. For example, if you want to use the
+      Cocoa features of Clozure CL from a terminal session (or from an Emacs
+      session using SLIME or ILISP), you can evaluate <code class="code">(require
+        :cocoa)</code>.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="application-builder"></a>5.6.Â The Application Builder</h2>
+              </div>
+            </div>
+          </div>
+          <a xmlns="http://www.w3.org/1999/xhtml" id="application_builder"></a>
+          <p xmlns="http://www.w3.org/1999/xhtml">One important feature of the IDE currently has no Cocoa user
+      interface: the application builder. The application builder
+      constructs a
+      Cocoa <a class="glossterm" href="#application_bundle"><em class="glossterm">application
+        bundle</em></a> that runs a Lisp image when double-clicked. You
+      can use the application builder to create Cocoa applications in
+      Lisp. These applications are exactly like Cocoa applications
+      created with XCode and Objective-C, except that they are written
+      in Lisp.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">To make the application builder available, evaluate the
+      expression <code class="code">(require :build-application)</code>. Clozure CL loads
+      the required subsystems, if necessary.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      <a id="id390665" class="indexterm"></a>
+      <span class="command"><strong><em class="varname"><a id="build-application"></a>BUILD-APPLICATION</em> <em class="varname"><em class="varname">&amp;key</em></em>
+        (<em class="parameter"><code>name</code></em> <em class="replaceable"><code>"MyApplication"</code></em>)
+        (<em class="parameter"><code>type-string</code></em> <em class="replaceable"><code>"APPL"</code></em>)
+        (<em class="parameter"><code>creator-string</code></em> <em class="replaceable"><code>"OMCL"</code></em>)
+        (<em class="parameter"><code>directory</code></em> <em class="replaceable"><code>(current-directory)</code></em>)
+        (<em class="parameter"><code>copy-ide-resources</code></em> <em class="replaceable"><code>t</code></em>)
+        (<em class="parameter"><code>info-plist</code></em> <em class="replaceable"><code>NIL</code></em>)
+        (<em class="parameter"><code>nibfiles</code></em> <em class="replaceable"><code>NIL</code></em>)
+        (<em class="parameter"><code>main-nib-name</code></em> <em class="replaceable"><code>NIL</code></em>)
+        (<em class="parameter"><code>application-class</code></em> <em class="replaceable"><code>'GUI::COCOA-APPLICATION</code></em>)
+        (<em class="parameter"><code>toplevel-function</code></em> <em class="replaceable"><code>NIL</code></em>)
+        [Function]</strong></span>
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      The <em class="varname">build-application</em> function constructs an
+      application bundle, populates it with the files needed to satisfy
+      Mac OS X that the bundle is a launchable application, and saves an
+      executable Lisp image to the proper subdirectory of the
+      bundle. Assuming that the saved Lisp image contains correct code,
+      a user can subsequently launch the resulting Cocoa application by
+      double-clicking its icon in the Finder, and the saved Lisp
+      environment runs.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The keyword arguments control various aspects of application
+      bundle as <code class="code">BUILD-APPLICATION</code> builds it.</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+            <dl>
+              <dt>
+                <span class="term">
+                  <em class="varname">name</em>
+                </span>
+              </dt>
+              <dd>
+                <p>Specifies the application name of the
+            bundle. <code class="code">BUILD-APPLICATION</code> creates an application
+            bundle whose name is given by this parameter, with the
+            extension ".app" appended. For example, using the default
+            value for this parameter results in a bundle named
+            "MyApplication.app".</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">type-string</em>
+                </span>
+              </dt>
+              <dd>
+                <p>Specifies type of bundle to create. You should normally
+            never need to change the default value, which Mac OS X uses to
+            identify application bundles.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">creator-string</em>
+                </span>
+              </dt>
+              <dd>
+                <p>Specifies the <a class="glossterm" href="#creator_code"><em class="glossterm">creator
+              code</em></a>, which uniquely identifies the application
+            under Mac OS X. The default creator code is that of Clozure CL. For
+            more information about reserving and assigning creator codes,
+            see
+            Apple's <a class="ulink" href="http://developer.apple.com/datatype/index.html" target="_top">developer
+              page</a> on the topic.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">directory</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The directory in which <code class="code">BUILD-APPLICATION</code>
+            creates the application bundle. By default, it creates the
+            bundle in the current working directory. Unless you
+            use <code class="code">CURRENT-DIRECTORY</code> to set the working
+            directory, the bundle may be created in some unexpected place,
+            so it's safest to specify a full pathname for this argument. A
+            typical value might be <code class="code">"/Users/foo/Desktop/"</code>
+            (assuming, of course, that your username is "foo").</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">copy-ide-resources</em>
+                </span>
+              </dt>
+              <dd>
+                <p>Whether to copy the resource files from the IDE's
+            application bundle. By
+            default, <code class="code">BUILD-APPLICATION</code> copies nibfiles
+            and other resources from the IDE to the newly-created
+            application bundle. This option is often useful when you
+            are developing a new application, because it enables your
+            built application to have a fully-functional user
+            interface even before you have finished designing one. By
+            default, the application uses the application menu and
+            other UI elements of the IDE until you specify
+            otherwise. Once your application's UI is fully
+            implemented, you may choose to pass <code class="literal">NIL</code>
+            for the value of this parameter, in which case the IDE
+            resources are not copied into your application
+            bundle.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">info-plist</em>
+                </span>
+              </dt>
+              <dd>
+                <p>A user-supplied NSDictionary object that defines the
+          contents of the Info.plist file to be written to the
+          application bundle. The default value
+          is <code class="literal">NIL</code>, which specifies that the
+          Info.plist from the IDE is to be used
+          if <em class="replaceable"><code>copy-ide-resources</code></em> is true,
+          and a new dictionary created with default values is to be
+          used otherwise. You can create a suitable NSDictionary
+          object using the
+          function <code class="literal">make-info-dict</code>. For details on
+          the parameters to this function, see its definition in
+          "ccl/cocoa-ide/builder-utilities.lisp".</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">nibfiles</em>
+                </span>
+              </dt>
+              <dd>
+                <p>A list of pathnames, where each pathname identifies
+            a <a class="glossterm" href="#nibfile"><em class="glossterm">nibfile</em></a> created
+            with
+            Apple's <a class="glossterm" href="#InterfaceBuilder"><em class="glossterm">InterfaceBuilder</em></a>
+            application. <code class="code">BUILD-APPLICATION</code> copies each
+            nibfile into the appropriate place in the application bundle,
+            enabling the application to load user-interface elements from
+            them as-needed. It is safest to provide full pathnames to the
+            nibfiles in the list. Each nibfile must be in ".nib" format,
+            not ".xib" format, in order that the application can load
+            it.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">main-nib-name</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The name of
+            the <a class="glossterm" href="#nibfile"><em class="glossterm">nibfile</em></a> to load
+            initially when launching. The user-interface defined in this
+            nibfile becomes the application's main interface. You must
+            supply the name of a suitable nibfile for this parameter, or
+            the resulting application uses the Clozure CL user
+            interface.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">application-class</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The name of the application's CLOS class. The default
+            value is the class provided by Clozure CL for graphical
+            applications. Supply the name of your application class if you
+            implement one. If not, Clozure CL uses the default class.</p>
+              </dd>
+              <dt>
+                <span class="term">
+                  <em class="varname">toplevel-function</em>
+                </span>
+              </dt>
+              <dd>
+                <p>The toplevel function that runs when the application
+            launches. Normally the default value, which is Clozure CL's
+            toplevel, works well, but in some cases you may wish to
+            customize the behavior of the application's toplevel. The best
+            source of information about writing your own toplevel is the
+            Clozure CL source code, especially the implementations
+            of <code class="code">TOPLEVEL-FUNCTION</code> in
+            "ccl/level-1/l1-application.lisp"</p>
+              </dd>
+            </dl>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml"><code class="code">BUILD-APPLICATION</code> creates a folder named
+      "<em class="replaceable"><code>name</code></em>.app" in the
+      directory <em class="replaceable"><code>directory</code></em>. Inside that
+      folder, it creates the "Contents" folder that Mac OS X
+      application bundles are expected to contain, and populates it
+      with the "MacOS" and "Resources" folders, and the "Info.plist"
+      and "PkgInfo" files that must be present in a working
+      application bundle. It takes the contents of the "Info.plist"
+      and "PkgInfo" files from the parameters
+      to <code class="code">BUILD-APPLICATION</code>. If <em class="replaceable"><code>copy-ide-resources</code></em>
+      is true then it copies the contents of the "Resources" folder
+      from the "Resources" folder of the running IDE.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The work needed to produce a running Cocoa application is
+    very minimal. In fact, if you
+    supply <code class="code">BUILD-APPLICATION</code> with a valid nibfile and
+    pathnames, it builds a running Cocoa application that displays
+    your UI. It doesn't need you to write any code at all to do
+    this. Of course, the resulting application doesn't do anything
+    apart from displaying the UI defined in the nibfile. If you want
+    your UI to accomplish anything, you need to write the code to
+    handle its events. But the path to a running application with your
+    UI in it is very short indeed.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Please note that <code class="code">BUILD-APPLICATION</code> is a work in
+    progress. It can easily build a working Cocoa application, but it
+    still has limitations that may in some cases prove
+    inconvenient. For example, in the current version it provides no
+    easy way to specify an application delegate different from the
+    default. If you find the current limitations
+    of <code class="code">BUILD-APPLICATION</code> too restrictive, and want to try
+    extending it for your use, you can find the source code for it in
+    "ccl/cocoa-ide/build-application.lisp". You can see the default
+    values used to populate the "Info.plist" file in
+    "ccl/cocoa-ide/builder-utilities.lisp".</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For more information on how to
+    use <code class="code">BUILD-APPLICATION</code>, see the Currency Converter
+    example in "ccl/examples/cocoa/currency-converter/".</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="running-the-application-builder-from-command-line"></a>5.6.1.Â Running the Application Builder From the Command
+      Line</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's possible to automate use of the application builder
+        by running a call to <code class="literal">CCL:BUILD-APPLICATION</code>
+        from the terminal command line. For example, the following
+        command, entered at a shell prompt in Mac OS X's Terminal
+        window, builds a working copy of the Clozure CL environment called
+        "Foo.app":</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+ccl -b -e "(require :cocoa)" -e "(require :build-application)" -e "(ccl::build-application :name \"Foo\")"
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">You can use the same method to automate building your
+      Lisp/Cocoa applications. Clozure CL handles each Lisp expressions
+      passed with a <code class="literal">-e</code> argument in order, so you
+      can simply evaluate a sequence of Lisp expressions as in the
+      above example to build your application, ending with a call
+      to <code class="literal">CCL:BUILD-APPLICATION</code>. The call
+      to <code class="literal">CCL:BUILD-APPLICATION</code> can process all the
+      same arguments as if you evaluated it in a Listener window in
+      the Clozure CL IDE.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Building a substantial Cocoa application (rather than just
+      reproducing the Lisp environment using defaults, as is done in
+      the above example) is likely to involve a relatively complicated
+      sequence of loading source files and perhaps evaluating Lisp
+      forms. You might be best served to place your command line in a
+      shell script that you can more easily edit and test.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">One potentially complicated issue concerns loading all
+        your Lisp source files in the right order. You might consider
+        using ASDF to define and load a system that includes all the
+        parts of your application before
+        calling <code class="literal">CCL:BUILD-APPLICATION</code>. ASDF is a
+        "another system-definition facility", a sort
+        of <code class="literal">make</code> for Lisp, and is included in the
+        Clozure CL distribution. You can read more about ASDF at the ASDF
+        <a class="ulink" href="http://constantly.at/lisp/asdf/" target="_top">home
+        page</a>.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Alternatively, you could use the standard features of
+        Common Lisp to load your application's files in the proper
+        order.</p>
+          </div>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Programming-with-Threads"></a>ChapterÂ 6.Â Programming with Threads</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Threads-overview">6.1. Threads Overview</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Intentionally--Missing-Functionality">6.2. (Intentionally) Missing Functionality</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Implementation-Decisions-and-Open-Questions">6.3. Implementation Decisions and Open Questions</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Thread-Stack-Sizes">6.3.1. Thread Stack Sizes</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#id366279">6.3.2.  As of August 2003:</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Porting-Code-from-the-Old-Thread-Model">6.4. Porting Code from the Old Thread Model</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Background-Terminal-Input">6.5. Background Terminal Input</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#backgrount-ti-overview">6.5.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#background-terminal-example">6.5.2. An example</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#A-more-elaborate-example-">6.5.3. A more elaborate example.</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Summary">6.5.4. Summary</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#The-Threads-which-CCL-Uses-for-Its-Own-Purposes">6.6. The Threads which Clozure CL Uses for Its Own Purposes</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Threads-Dictionary">6.7. Threads Dictionary</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Threads-overview"></a>6.1.Â Threads Overview</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL provides facilities which enable multiple threads
+      of execution (<span class="emphasis"><em>threads</em></span>, sometimes called
+      <span class="emphasis"><em>lightweight processes</em></span> or just
+      <span class="emphasis"><em>processes</em></span>, though the latter term shouldn't
+      be confused with the OS's notion of a process) within a lisp
+      session. This document describes those facilities and issues
+      related to multithreaded programming in Clozure CL.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Wherever possible, I'll try to use the term "thread" to
+      denote a lisp thread, even though many of the functions in the
+      API have the word "process" in their name. A
+      <span class="emphasis"><em>lisp-process</em></span> is a lisp object (of type
+      CCL:PROCESS) which is used to control and communicate with an
+      underlying <span class="emphasis"><em>native thread</em></span>. Sometimes, the
+      distinction between these two (quite different) objects can be
+      blurred; other times, it's important to maintain.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Lisp threads share the same address space, but maintain
+      their own execution context (stacks and registers) and their own
+      dynamic binding context.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Traditionally, Clozure CL's threads have been
+      <span class="emphasis"><em>cooperatively scheduled</em></span>: through a
+      combination of compiler and runtime support, the currently
+      executing lisp thread arranged to be interrupted at certain
+      discrete points in its execution (typically on entry to a
+      function and at the beginning of any looping construct). This
+      interrupt occurred several dozen times per second; in response,
+      a handler function might observe that the current thread had
+      used up its time slice and another function (<span class="emphasis"><em>the lisp
+        scheduler</em></span>) would be called to find some other thread
+      that was in a runnable state, suspend execution of the current
+      thread, and resume execution of the newly executed thread.  The
+      process of switching contexts between the outgoing and incoming
+      threads happened in some mixture of Lisp and assembly language
+      code; as far as the OS was concerned, there was one native
+      thread running in the Lisp image and its stack pointer and other
+      registers just happened to change from time to time.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Under Clozure CL's cooperative scheduling model, it was
+      possible (via the use of the CCL:WITHOUT-INTERRUPTS construct)
+      to defer handling of the periodic interrupt that invoked the
+      lisp scheduler; it was not uncommon to use WITHOUT-INTERRUPTS to
+      gain safe, exclusive access to global data structures. In some
+      code (including much of Clozure CL itself) this idiom was very
+      common: it was (justifiably) believed to be an efficient way of
+      inhibiting the execution of other threads for a short period of
+      time.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The timer interrupt that drove the cooperative scheduler
+      was only able to (pseudo-)preempt lisp code: if any thread
+      called a blocking OS I/O function, no other thread could be
+      scheduled until that thread resumed execution of lisp code. Lisp
+      library functions were generally attuned to this constraint, and
+      did a complicated mixture of polling and "timed blocking" in an
+      attempt to work around it. Needless to say, this code is
+      complicated and less efficient than it might be; it meant that
+      the lisp was a little busier than it should have been when it
+      was "doing nothing" (waiting for I/O to be possible.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For a variety of reasons - better utilization of CPU
+      resources on single and multiprocessor systems and better
+      integration with the OS in general - threads in Clozure CL 0.14 and
+      later are <span class="emphasis"><em>preemptively scheduled. </em></span>In this
+      model, lisp threads are native threads and all scheduling
+      decisions involving them are made by the OS kernel. (Those
+      decisions might involve scheduling multiple lisp threads
+      simultaneously on multiple processors on SMP systems.) This
+      change has a number of subtle effects:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>it is possible for two (or more) lisp threads to be
+	      executing simultaneously, possibly trying to access and/or
+	      modify the same data structures. Such access really should
+	      have been coordinated through the use of synchronization
+	      objects regardless of the scheduling modeling effect;
+	      preemptively scheduled threads increase the chance of things
+	      going wrong at the wrong time and do not offer
+	      lightweight alternatives to the use of those synchronization
+	      objects.</p>
+              </li>
+              <li>
+                <p>even on a single-processor system, a context switch
+	      can happen on any instruction boundary. Since (in general)
+	      other threads might allocate memory, this means that a GC can
+	      effectively take place at any instruction boundary. That's
+	      mostly an issue for the compiler and runtime system to be
+	      aware of, but it means that certain practices(such as trying
+	      to pass the address of a lisp object to foreign code)that
+	      were always discouraged are now discouraged
+	      ... vehemently.</p>
+              </li>
+              <li>
+                <p>there is no simple and efficient way to "inhibit the
+	      scheduler"or otherwise gain exclusive access to the entire
+	      CPU.</p>
+              </li>
+              <li>
+                <p>There are a variety of simple and efficient ways
+	      to synchronize access to particular data
+	      structures.</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">As a broad generalization: code that's been aggressively
+      tuned to the constraints of the cooperative scheduler may need
+      to be redesigned to work well with the preemptive scheduler (and
+      code written to run under Clozure CL's interface to the native
+      scheduler may be less portable to other CL implementations, many
+      of which offer a cooperative scheduler and an API similar to
+      Clozure CL (&lt; 0.14) 's.) At the same time, there's a large
+      overlap in functionality in the two scheduling models, and it'll
+      hopefully be possible to write interesting and useful MP code
+      that's largely independent of the underlying scheduling
+      details.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The keyword :OPENMCL-NATIVE-THREADS is on *FEATURES* in
+      0.14 and later and can be used for conditionalization where
+      required.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Intentionally--Missing-Functionality"></a>6.2.Â (Intentionally) Missing Functionality</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Much of the functionality described above is similar to
+      that provided by Clozure CL's cooperative scheduler, some other
+      parts of which make no sense in a native threads
+      implementation.</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>PROCESS-RUN-REASONS and PROCESS-ARREST-REASONS were
+	      SETFable process attributes; each was just a list of
+	      arbitrary tokens. A thread was eligible for scheduling
+	      (roughly equivalent to being "enabled") if its arrest-reasons
+	      list was empty and its run-reasons list was not. I don't
+	      think that it's appropriate to encourage a programming style
+	      in which otherwise runnable threads are enabled and disabled
+	      on a regular basis (it's preferable for threads to wait for
+	      some sort of synchronization event to occur if they can't
+	      occupy their time productively.)</p>
+              </li>
+              <li>
+                <p>There were a number of primitives for maintaining
+	      process queues;that's now the OS's job.</p>
+              </li>
+              <li>
+                <p>Cooperative threads were based on coroutining
+	      primitives associated with objects of type
+	      STACK-GROUP. STACK-GROUPs no longerexist.</p>
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Implementation-Decisions-and-Open-Questions"></a>6.3.Â Implementation Decisions and Open Questions</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Thread-Stack-Sizes"></a>6.3.1.Â Thread Stack Sizes</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">When you use MAKE-PROCESS to create a thread, you can
+        specify a stack size. Clozure CL does not impose a limit on the stack
+        size you choose, but there is some evidence that choosing a
+        stack size larger than the operating system's limit can cause
+        excessive paging activity, at least on some operating
+        systems.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The maximum stack size is operating-system-dependent. You
+        can use shell commands to determine what it is on your
+        platform. In bash, use "ulimit -s -H" to find the limit; in
+        tcsh, use "limit -h s".</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">This issue does not affect programs that create threads
+        using the default stack size, which you can do either by
+        specifying no value for the :stack-size argument to
+        MAKE-PROCESS, or by specifying the value
+        CCL::*default-control-stack-size*.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If your program creates threads with a specified stack size,
+        and that size is larger than the OS-specified limit, you may want
+        to consider reducing the stack size in order to avoid possible
+        excessive paging activity.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="id366279"></a>6.3.2.Â  As of August 2003:</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>It's not clear that exposing
+	        PROCESS-SUSPEND/PROCESS-RESUME is a good idea: it's not clear
+	        that they offer ways to win, and it's clear that they offer
+	        ways to lose.</p>
+                </li>
+                <li>
+                  <p>It has traditionally been possible to reset and enable
+	        a process that's "exhausted" . (As used here, the
+	        term"exhausted" means that the process's initial function
+	        has run and returned and the underlying native thread has
+	        been deallocated.) One of the principal uses of PROCESS-RESET
+	        is to "recycle" threads; enabling an exhausted process
+	        involves creating a new native thread (and stacks and
+	        synchronization objects and ...),and this is the sort of
+	        overhead that such a recycling scheme is seeking to avoid. It
+	        might be worth trying to tighten things up and declare that
+	        it's an error to apply PROCESS-ENABLE to an exhausted thread
+	        (and to make PROCESS-ENABLE detect this error.)</p>
+                </li>
+                <li>
+                  <p>When native threads that aren't created by Clozure CL
+	        first call into lisp, a "foreign process" is created, and
+	        that process is given its own set of initial bindings and set
+	        up to look mostly like a process that had been created by
+	        MAKE-PROCESS. The life cycle of a foreign process is
+	        certainly different from that of a lisp-created one: it
+	        doesn't make sense to reset/preset/enable a foreign process,
+	        and attempts to perform these operations should be
+	        detected and treated as errors.</p>
+                </li>
+              </ul>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Porting-Code-from-the-Old-Thread-Model"></a>6.4.Â Porting Code from the Old Thread Model</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Older versions of Clozure CL used what are often called
+      "user-mode threads", a less versatile threading model which does
+      not require specific support from the operating system.  This
+      section discusses how to port code which was written for that
+      mode.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">It's hard to give step-by-step instructions; there are certainly
+      a few things that one should look at carefully:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>It's wise to be suspicious of most uses
+	      of WITHOUT-INTERRUPTS; there may be exceptions, but
+	      WITHOUT-INTERRUPTS is often used as shorthand for
+	      WITH-APPROPRIATE-LOCKING. Determining what type of locking
+	      is appropriate and writing the code to implement it is
+	      likely to be straightforward and simple most of the
+	      time.</p>
+              </li>
+              <li>
+                <p>I've only seen one case where a process's "run reasons"
+	      were used to communicate information as well as to control
+	      execution; I don't think that this is a common idiom, but may
+	      be mistaken about that.
+	    </p>
+              </li>
+              <li>
+                <p>It's certainly possible that programs written
+	      for cooperatively scheduled lisps that have run reliably for
+	      a long time have done so by accident: resource-contention
+	      issues tend to be timing-sensitive, and decoupling thread
+	      scheduling from lisp program execution affects timing. I know
+	      that there is or was code in both Clozure CL and commercial MCL
+	      that was written under the explicit assumption that certain
+	      sequences of open-coded operations were uninterruptable; it's
+	      certainly possible that the same assumptions have been made
+	      (explicitly or otherwise) by application developers.</p>
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Background-Terminal-Input"></a>6.5.Â Background Terminal Input</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="backgrount-ti-overview"></a>6.5.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	    Unless and until Clozure CL provides alternatives (via window
+	    streams, telnet streams, or some other mechanism) all lisp
+	    processes share a common *TERMINAL-IO* stream (and therefore
+	    share *DEBUG-IO*, *QUERY-IO*, and other standard and
+	    internal interactive streams.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's anticipated that most lisp processes other than
+	    the "Initial" process run mostly in the background. If a
+	    background process writes to the output side of
+	    *TERMINAL-IO*, that may be a little messy and a little
+	    confusing to the user, but it shouldn't really be
+	    catastrophic. All I/O to Clozure CL's buffered streams goes
+	    thru a locking mechanism that prevents the worst kinds of
+	    resource-contention problems.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Although the problems associated with terminal output
+	    from multiple processes may be mostly cosmetic, the question
+	    of which process receives input from the terminal is likely
+	    to be a great deal more important. The stream locking
+	    mechanisms can make a confusing situation even worse:
+	    competing processes may "steal" terminal input from each
+	    other unless locks are held longer than they otherwise need
+	    to be, and locks can be held longer than they need to be (as
+	    when a process is merely waiting for input to become
+	    available on an underlying file descriptor).</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Even if background processes rarely need to
+	    intentionally read input from the terminal, they may still
+	    need to do so in response to errors or other unanticipated
+	    situations. There are tradeoffs involved in any solution to
+	    this problem. The protocol described below allows background
+	    processes which follow it to reliably prompt for and receive
+	    terminal input. Background processes which attempt to
+	    receive terminal input without following this protocol will
+	    likely hang indefinitely while attempting to do so. That's
+	    certainly a harsh tradeoff, but since attempts to read
+	    terminal input without following this protocol only worked
+	    some of the time anyway, it doesn't seem to be an
+	    unreasonable one.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In the solution described here (and introduced in
+	    Clozure CL 0.9), the internal stream used to provide terminal
+	    input is always locked by some process (the "owning"
+	    process.) The initial process (the process that typically
+	    runs the read-eval-print loop) owns that stream when it's
+	    first created. By using the macro WITH-TERMINAL-INPUT,
+	    background processes can temporarily obtain ownership of the
+	    terminal and relinquish ownership to the previous owner when
+	    they're done with it.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In Clozure CL, BREAK, ERROR, CERROR, Y-OR-N-P,
+	    YES-OR-NO-P, and CCL:GET-STRING- FROM-USER are all defined
+	    in terms of WITH-TERMINAL-INPUT, as are the :TTY
+	    user-interfaces to STEP and INSPECT.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="background-terminal-example"></a>6.5.2.Â An example</h3>
+                </div>
+              </div>
+            </div>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? Welcome to Clozure CL Version (Beta: linux) 0.9!
+?
+
+? (process-run-function "sleeper" #'(lambda () (sleep 5) (break "broken")))
+#&lt;PROCESS sleeper(1) [Enabled] #x3063B33E&gt;
+
+?
+;;
+;; Process sleeper(1) needs access to terminal input.
+;;
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">This example was run under ILISP; ILISP often gets confused if one
+	    tries to enter input and "point" doesn't follow a prompt.
+	    Entering a "simple" expression at this point gets it back in
+	    synch; that's otherwise not relevant to this example.</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+()
+NIL
+? (:y 1)
+;;
+;; process sleeper(1) now controls terminal input
+;;
+&gt; Break in process sleeper(1): broken
+&gt; While executing: #&lt;Anonymous Function #x3063B276&gt;
+&gt; Type :GO to continue, :POP to abort.
+&gt; If continued: Return from BREAK.
+Type :? for other options.
+1 &gt; :b
+(30C38E30) : 0 "Anonymous Function #x3063B276" 52
+(30C38E40) : 1 "Anonymous Function #x304984A6" 376
+(30C38E90) : 2 "RUN-PROCESS-INITIAL-FORM" 340
+(30C38EE0) : 3 "%RUN-STACK-GROUP-FUNCTION" 768
+1 &gt; :pop
+;;
+;; control of terminal input restored to process Initial(0)
+;;
+?
+      </pre>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="A-more-elaborate-example-"></a>6.5.3.Â A more elaborate example.</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">If a background process ("A") needs access to the terminal
+	    input stream and that stream is owned by another background process
+	    ("B"), process "A" announces that fact, then waits until
+	    the initial process regains control.</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? Welcome to Clozure CL Version (Beta: linux) 0.9!
+?
+
+? (process-run-function "sleep-60" #'(lambda () (sleep 60) (break "Huh?")))
+#&lt;PROCESS sleep-60(1) [Enabled] #x3063BF26&gt;
+
+? (process-run-function "sleep-5" #'(lambda () (sleep 5) (break "quicker")))
+#&lt;PROCESS sleep-5(2) [Enabled] #x3063D0A6&gt;
+
+?       ;;
+;; Process sleep-5(2) needs access to terminal input.
+;;
+()
+NIL
+
+? (:y 2)
+;;
+;; process sleep-5(2) now controls terminal input
+;;
+&gt; Break in process sleep-5(2): quicker
+&gt; While executing: #x3063CFDE&gt;
+&gt; Type :GO to continue, :POP to abort.
+&gt; If continued: Return from BREAK.
+Type :? for other options.
+1 &gt;     ;; Process sleep-60(1) will need terminal access when
+;; the initial process regains control of it.
+;;
+()
+NIL
+1 &gt; :pop
+;;
+;; Process sleep-60(1) needs access to terminal input.
+;;
+;;
+;; control of terminal input restored to process Initial(0)
+;;
+
+? (:y 1)
+;;
+;; process sleep-60(1) now controls terminal input
+;;
+&gt; Break in process sleep-60(1): Huh?
+&gt; While executing: #x3063BE5E&gt;
+&gt; Type :GO to continue, :POP to abort.
+&gt; If continued: Return from BREAK.
+Type :? for other options.
+1 &gt; :pop
+;;
+;; control of terminal input restored to process Initial(0)
+;;
+
+?
+      </pre>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Summary"></a>6.5.4.Â Summary</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">This scheme is certainly not bulletproof: imaginative
+	    use of PROCESS-INTERRUPT and similar functions might be able
+	    to defeat it and deadlock the lisp, and any scenario where
+	    several background processes are clamoring for access to the
+	    shared terminal input stream at the same time is likely to be
+	    confusing and chaotic. (An alternate scheme, where the input
+	    focus was magically granted to whatever thread the user was
+	    thinking about, was considered and rejected due to technical
+	    limitations.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The longer-term fix would probably involve using network or
+	    window-system streams to give each process unique instances of
+	    *TERMINAL-IO*.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Existing code that attempts to read from *TERMINAL-IO*
+        from a background process will need to be changed to use
+        WITH-TERMINAL-INPUT.  Since that code was probably not working
+        reliably in previous versions of Clozure CL, this requirement
+        doesn't seem to be too onerous.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that WITH-TERMINAL-INPUT both requests ownership of
+        the terminal input stream and promises to restore that
+        ownership to the initial process when it's done with it. An ad
+        hoc use of READ or READ-CHAR doesn't make this promise; this
+        is the rationale for the restriction on the :Y command.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="The-Threads-which-CCL-Uses-for-Its-Own-Purposes"></a>6.6.Â The Threads which Clozure CL Uses for Its Own Purposes</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">
+      In the "tty world", Clozure CL starts out with 2 lisp-level threads:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? :proc
+1 : -&gt; listener     [Active]
+0 :    Initial      [Active]
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you look at a running Clozure CL with a debugging tool,
+      such as GDB, or Apple's Thread Viewer.app, you'll see an
+      additional kernel-level thread on Darwin; this is used by the
+      Mach exception-handling mechanism.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The initial thread, conveniently named "initial", is the
+      one that was created by the operating system when it launched
+      Clozure CL.  It maps the heap image into memory, does some
+      Lisp-level initialization, and, when the Cocoa IDE isn't being
+      used, creates the thread "listener", which runs the top-level
+      loop that reads input, evaluates it, and prints the
+      result.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">After the listener thread is created, the initial thread
+      does "housekeeping": it sits in a loop, sleeping most of the
+      time and waking up occasionally to do "periodic tasks".  These
+      tasks include forcing output on specified interactive streams,
+      checking for and handling control-C interrupts, etc.  Currently,
+      those tasks also include polling for the exit status of external
+      processes and handling some kinds of I/O to and from those
+      processes.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In this environment, the initial thread does these
+      "housekeeping" activities as necessary, until
+      <code class="literal">ccl:quit</code> is called;
+      <code class="literal">quit</code>ting interrupts the initial thread, which
+      then ends all other threads in as orderly a fashion as possible
+      and calls the C function <code class="literal">#_exit</code>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The short-term plan is to handle each external-process in
+      a dedicated thread; the worst-case behavior of the current
+      scheme can involve busy-waiting and excessive CPU utilization
+      while waiting for an external process to terminate in some
+      cases.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Cocoa features use more threads.  Adding a Cocoa
+      listener creates two threads:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? :proc
+      3 : -&gt; Listener     [Active]
+      2 :    housekeeping  [Active]
+      1 :    listener     [Active]
+      0 :    Initial      [Active]
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Cocoa event loop has to run in the initial thread;
+      when the event loop starts up, it creates a new thread to do the
+      "housekeeping" tasks which the initial thread would do in the
+      terminal-only mode.  The initial thread then becomes the one to
+      receive all Cocoa events from the window server; it's the only
+      thread which can.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">It also creates one "Listener" (capital-L) thread for each
+      listener window, with a lifetime that lasts as long as the
+      thread does.  So, if you open a second listener, you'll see five
+      threads all together:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? :proc
+      4 : -&gt; Listener-2   [Active]
+      3 :    Listener     [Active]
+      2 :    housekeeping  [Active]
+      1 :    listener     [Active]
+      0 :    Initial      [Active]
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Unix signals, such as SIGINT (control-C), invoke a handler
+      installed by the Lisp kernel.  Although the OS doesn't make any
+      specific guarantee about which thread will receive the signal,
+      in practice, it seems to be the initial thread.  The handler
+      just sets a flag and returns; the housekeeping thread (which may
+      be the initial thread, if Cocoa's not being used) will check for
+      the flag and take whatever action is appropriate to the
+      signal.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In the case of SIGINT, the action is to enter a break
+      loop, by calling on the thread being interrupted.  When there's
+      more than one Lisp listener active, it's not always clear what
+      thread that should be, since it really depends on the user's
+      intentions, which there's no way to divine programmatically.  To
+      make its best guess, the handler first checks whether the value
+      of <code class="literal">ccl:*interactive-abort-process*</code> is a
+      thread, and, if so, uses it.  If that fails, it chooses the
+      thread which currently "owns" the default terminal input stream;
+      see .</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In the bleeding-edge version of the Cocoa support which is
+      based on Hemlock, an Emacs-like editor, each editor window has a
+      dedicated thread associated with it.  When a keypress event
+      comes in which affects that specific window the initial thread
+      sends it to the window's dedicated thread.  The dedicated thread
+      is responsible for trying to interpret keypresses as Hemlock
+      commands, applying those commands to the active buffer; it
+      repeats this in a loop, until the window closes.  The initial
+      thread handles all other events, such as mouse clicks and
+      drags.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This thread-per-window scheme makes many things simpler,
+      including the process of entering a "recursive command loop" in
+      commands like "Incremental Search Forward", etc.  (It might be
+      possible to handle all Hemlock commands in the Cocoa event
+      thread, but these "recursive command loops" would have to
+      maintain a lot of context/state information; threads are a
+      straightforward way of maintaining that information.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Currently (August 2004), when a dedicated thread needs to
+      alter the contents of the buffer or the selection, it does so by
+      invoking methods in the initial thread, for synchronization
+      purposes, but this is probably overkill and will likely be
+      replaced by a more efficient scheme in the future.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The per-window thread could probably take more
+      responsibility for drawing and handling the screen than it
+      currently does; -something- needs to be done to buffer screen
+      updates a bit better in some cases: you don't need to see
+      everything that happens during something like indentation; you
+      do need to see the results...</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When Hemlock is being used, listener windows are editor
+      windows, so in addition to each "Listener" thread, you should
+      also see a thread which handles Hemlock command
+      processing.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Cocoa runtime may make additional threads in certain
+      special situations; these threads usually don't run lisp code,
+      and rarely if ever run much of it.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Threads-Dictionary"></a>6.7.Â Threads Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_all-processes"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>all-processes</strong></span> =&gt; result
+	    </code>
+            </div>
+            <div class="refentrytitle">Obtain a fresh list of all known Lisp
+	      threads.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417015"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---a list of all lisp processes (threads)
+		        known to Clozure CL.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417041"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns a list of all lisp processes (threads) known
+	      to Clozure CL as of
+	      the precise instant it's called. It's safe to traverse
+	      this list and to modify the cons cells that comprise that list
+	      (it's freshly consed.) Since other threads can create and kill
+	      threads at any time, there's generally no way to get an
+	      "accurate" list of all threads, and (generally) no
+	      sense in which such a list can be accurate.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417056"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist">
+                  <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b>
+                  </a>
+                </span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_make-process"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-process</strong></span>
+	      name &amp;key
+	      persistent priority class stack-size vstack-size
+	      tstack-size initial-bindings use-standard-initial-bindings
+	      =&gt; process
+	    </code>
+            </div>
+            <div class="refentrytitle">Creates and returns a new process.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417125"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---a string, used to identify the process.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">persistent</span></i>---if true, requests that information about the process
+		        be retained by SAVE-APPLICATION so that an equivalent
+		        process can be restarted when a saved image is run.  The
+		        default is nil.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">priority</span></i>---ignored.  It
+		        shouldn't be ignored of course, but there are
+		        complications on some platforms.  The default is 0.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">class</span></i>---the class of process object to create;
+		        should be a subclass of CCL:PROCESS.  The default is
+		        CCL:PROCESS.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stack-size</span></i>---the size, in bytes, of the newly-created process's
+		        control stack; used for foreign function calls and to save
+		        function return address context.  The default is
+		        CCL:*DEFAULT-CONTROL-STACK-SIZE*.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">vstack-size</span></i>---the size, in bytes, of the newly-created process's
+		        value stack; used for lisp function arguments, local
+		        variables, and other stack-allocated lisp objects.
+		        The default is CCL:*DEFAULT-VALUE-STACK-SIZE*.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">tstack-size</span></i>---the size, in bytes, of the newly-created process's
+		        temp stack; used for the allocation of dynamic-extent
+		        objects.  The default is CCL:*DEFAULT-TEMP-STACK-SIZE*.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">use-standard-initial-bindings</span></i>---when true, the global "standard initial
+		        bindings" are put into effect in the new thread before. See
+		        DEF-STANDARD-INITIAL-BINDING.  "standard" initial bindings
+		        are put into effect before any bindings specified by
+		        :initial-bindings are.  The default is t.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">initial-bindings</span></i>---an alist of (<em xmlns="http://www.w3.org/1999/xhtml" class="varname">symbol</em> .
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">valueform</em>) pairs, which can be
+		        used to initialize special variable bindings in the new
+		        thread. Each <em xmlns="http://www.w3.org/1999/xhtml" class="varname">valueform</em> is used to
+		        compute the value of a new binding of
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">symbol</em> in the execution environment of
+		        the newly-created thread.  The default is nil.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---the newly-created process.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417313"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Creates and returns a new lisp process (thread) with the
+	      specified attributes. <em class="varname">process</em> will not begin
+	      execution immediately; it will need to be
+	      <span class="emphasis"><em>preset</em></span> (given
+	      an initial function to run, as by
+	      <a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>) and
+	      <span class="emphasis"><em>enabled</em></span>
+	      (allowed to execute, as by <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>)
+	      before it's able to actually do anything.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If <em class="varname">valueform</em> is a function, it is
+	      called, with no arguments, in the execution environment of the
+	      newly-created thread; the primary value it returns is used for
+	      the binding of the corresponding <em class="varname">symbol</em>.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Otherwise, <em class="varname">valueform</em> is evaluated in the
+	      execution
+	      environment of the newly-created thread, and the resulting value
+	      is used.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417365"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>, <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>, <a class="xref" href="#f_process-run-function" title="Function PROCESS-RUN-FUNCTION"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-run-function</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-suspend"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-suspend</strong></span> process
+	      =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Suspends a specified process.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417443"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---T if <em xmlns="http://www.w3.org/1999/xhtml" class="varname">process</em> had been runnable
+		        and is now suspended; NIL otherwise.  That is, T if
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">process</em>'s
+		        <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_process-suspend-count" title="Function PROCESS-SUSPEND-COUNT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend-count</b></a>
+		        transitioned from 0 to 1.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417497"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Suspends <em class="varname">process</em>, preventing it from
+	      running, and stopping it if it was already running. This is a fairly
+	      expensive operation, because it involves a few
+	      calls to the OS.  It also risks creating deadlock if used
+	      improperly, for instance, if the process being suspended owns a
+	      lock or other resource which another process will wait for.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Each
+	      call to <span class="function"><strong>process-suspend</strong></span> must be reversed by
+	      a matching call to <a class="xref" href="#f_process-resume" title="Function PROCESS-RESUME"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-resume</b></a>
+	      before <em class="varname">process</em> is able to run.  What
+	      <span class="function"><strong>process-suspend</strong></span> actually does is increment
+	      the <a class="xref" href="#f_process-suspend-count" title="Function PROCESS-SUSPEND-COUNT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend-count</b></a> of
+	      <em class="varname">process</em>.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">A process can't suspend itself, though this once
+	    worked and this documentation claimed has claimed that it
+	    did.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417552"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-resume" title="Function PROCESS-RESUME"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-resume</b></a>, <a class="xref" href="#f_process-suspend-count" title="Function PROCESS-SUSPEND-COUNT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend-count</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417577"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml"><span class="function"><strong>process-suspend</strong></span> was previously called
+	      <span class="function"><strong>process-disable</strong></span>.
+	      <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>
+	      now names a function for which there is no
+	      obvious inverse, so <span class="function"><strong>process-disable</strong></span>
+	      is no longer
+	      defined.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-resume"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-resume</strong></span> process
+	      =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Resumes a specified process which had previously
+	      been suspended by process-suspend.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417658"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---T if <em xmlns="http://www.w3.org/1999/xhtml" class="varname">process</em> had been suspended
+		        and is now runnable; NIL otherwise.  That is, T if
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">process</em>'s
+		        <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_process-suspend-count" title="Function PROCESS-SUSPEND-COUNT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend-count</b></a>
+		        transitioned from  to 0.
+		      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417712"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Undoes the effect of a previous call to
+	      <a class="xref" href="#f_process-suspend" title="Function PROCESS-SUSPEND"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend</b></a>; if
+	      all such calls are undone, makes the process runnable. Has no
+	      effect if the process is not suspended.  What
+	      <span class="function"><strong>process-resume</strong></span> actually does is decrement
+	      the <a class="xref" href="#f_process-suspend-count" title="Function PROCESS-SUSPEND-COUNT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend-count</b></a> of
+	      <em class="varname">process</em>, to a minimum of 0.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417743"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-suspend" title="Function PROCESS-SUSPEND"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend</b></a>, <a class="xref" href="#f_process-suspend-count" title="Function PROCESS-SUSPEND-COUNT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend-count</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417768"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      This was previously called PROCESS-ENABLE;
+	      <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a> now does something slightly
+	      different.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-suspend-count"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-suspend-count</strong></span>
+	      process =&gt; result
+	    </code>
+            </div>
+            <div class="refentrytitle">Returns the number of currently-pending suspensions
+	      applicable to a given process.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417833"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---The number of "outstanding"
+		        <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_process-suspend" title="Function PROCESS-SUSPEND"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend</b></a> calls on
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">process</em>, or NIL if
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">process</em> has expired.
+		      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417887"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">An "outstanding" <a class="xref" href="#f_process-suspend" title="Function PROCESS-SUSPEND"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend</b></a> call
+	      is one which has not yet been reversed by a call to
+	      <a class="xref" href="#f_process-resume" title="Function PROCESS-RESUME"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-resume</b></a>.  A process expires when
+	      its initial function returns, although it may later be
+	      reset.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">A process is <span class="emphasis"><em>runnable</em></span> when it has a
+	      <span class="function"><strong>process-suspend-count</strong></span> of 0, has been
+	      preset as by <a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>, and has been
+	      enabled as by <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>.  Newly-created
+	      processes have a <span class="function"><strong>process-suspend-count</strong></span> of
+	      0.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id417937"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-suspend" title="Function PROCESS-SUSPEND"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-suspend</b></a>, <a class="xref" href="#f_process-resume" title="Function PROCESS-RESUME"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-resume</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-preset"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-preset</strong></span>
+	      process function <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> args
+	      =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Sets the initial function and arguments of a specified
+	      process.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id418013"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">function</span></i>---a function, designated by itself or by a symbol
+		        which names it.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">args</span></i>---a list of values, appropriate as arguments to
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">function</em>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---undefined.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id418088"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Typically used to initialize a newly-created or newly-reset
+	      process, setting things up so that when <em class="varname">process</em>
+	      becomes enabled, it will begin execution by
+	      applying <em class="varname">function</em> to <em class="varname">args</em>.
+	      <span class="function"><strong>process-preset</strong></span> does not enable
+	      <em class="varname">process</em>,
+	      although a process must be <span class="function"><strong>process-preset</strong></span>
+	      before it can be enabled.  Processes are normally enabled by
+	      <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id418132"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-process" title="Function MAKE-PROCESS"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-process</b></a>, <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>, <a class="xref" href="#f_process-run-function" title="Function PROCESS-RUN-FUNCTION"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-run-function</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-enable"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-enable</strong></span>
+	      process <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> timeout
+	    </code>
+            </div>
+            <div class="refentrytitle">Begins executing the initial function of a specified
+	      process.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id418214"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">timeout</span></i>---a time interval in seconds.  May be any
+		        non-negative real number the <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>floor</strong></span> of
+		        which fits in 32 bits.  The default is 1.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---undefined.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id418277"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tries to begin the execution of <em class="varname">process</em>.
+	      An error is signaled if <em class="varname">process</em> has never
+	      been <a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>.  Otherwise,
+	      <em class="varname">process</em> invokes its initial function.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml"><span class="function"><strong>process-enable</strong></span> attempts to
+	      synchronize with <em class="varname">process</em>, which is presumed
+	      to be reset or in the act of resetting itself.  If this attempt
+	      is not successful within the time interval specified by
+	      <em class="varname">timeout</em>, a continuable error is signaled,
+	      which offers the opportunity to continue waiting.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">A process cannot meaningfully attempt to enable itself.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id418325"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-process" title="Function MAKE-PROCESS"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-process</b></a>, <a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>, <a class="xref" href="#f_process-run-function" title="Function PROCESS-RUN-FUNCTION"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-run-function</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id418356"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">It would be nice to have more discussion of what it means
+	      to synchronize with the process.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-run-function"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-run-function</strong></span>
+	      process-specifier function <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> args =&gt; process</code>
+            </div>
+            <div class="refentrytitle">Creates a process, presets it, and enables it.
+	    </div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410042"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---a string, used to identify the process.
+		        Passed to <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-process</strong></span>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">function</span></i>---a function, designated by itself or by a symbol
+		        which names it.  Passed to
+		        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>preset-process</strong></span>.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">persistent</span></i>---a boolean, passed to <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-process</strong></span>.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">priority</span></i>---ignored.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">class</span></i>---a subclass of CCL:PROCESS.  Passed to
+		        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-process</strong></span>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stack-size</span></i>---a size, in bytes.  Passed to
+		        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-process</strong></span>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">vstack-size</span></i>---a size, in bytes.  Passed to
+		        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-process</strong></span>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">tstack-size</span></i>---a size, in bytes.  Passed to
+		        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-process</strong></span>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---the newly-created process.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410231"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Creates a lisp process (thread) via
+	      <a class="xref" href="#f_make-process" title="Function MAKE-PROCESS"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-process</b></a>,
+	      presets it via <a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>, and
+	      enables it via <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>.  This means
+	      that <em class="varname">process</em> will immediately begin to
+	      execute.
+	      <span class="function"><strong>process-run-function</strong></span> is
+	      the simplest way to create and run a process.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410266"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-process" title="Function MAKE-PROCESS"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-process</b></a>, <a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>, <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-interrupt"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-interrupt</strong></span>
+	      process function <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> args =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Arranges for the target process to invoke a
+	      specified function at some point in the near future, and then
+	      return to what it was doing.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410350"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">function</span></i>---a function.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">args</span></i>---a list of values, appropriate as arguments to
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">function</em>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---the result of applying <em xmlns="http://www.w3.org/1999/xhtml" class="varname">function</em>
+		        to <em xmlns="http://www.w3.org/1999/xhtml" class="varname">args</em> if <em xmlns="http://www.w3.org/1999/xhtml" class="varname">process</em>
+		        is the <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>current-process</strong></span>, otherwise
+		        NIL.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410442"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Arranges for <em class="varname">process</em>
+	      to apply <em class="varname">function</em> to <em class="varname">args</em> at
+	      some point in the near future (interrupting whatever
+	      <em class="varname">process</em>
+	      was doing.) If <em class="varname">function</em> returns normally,
+	      <em class="varname">process</em> resumes
+	      execution at the point at which it was interrupted.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml"><em class="varname">process</em> must be in an enabled state in
+	      order to respond
+	      to a <span class="function"><strong>process-interrupt</strong></span> request.  It's
+	      perfectly legal for a process to call
+	      <span class="function"><strong>process-interrupt</strong></span> on itself.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml"><span class="function"><strong>process-interrupt</strong></span>
+	      uses asynchronous POSIX signals to interrupt threads. If the
+	      thread being interrupted is executing lisp code, it can
+	      respond to the interrupt almost immediately (as soon as it
+	      has finished pseudo-atomic operations like consing and
+	      stack-frame initialization.)</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If the interrupted thread is
+	      blocking in a system call, that system call is aborted by
+	      the signal and the interrupt is handled on return.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">It is
+	      still difficult to reliably interrupt arbitrary foreign code
+	      (that may be stateful or otherwise non-reentrant); the
+	      interrupt request is handled when such foreign code returns
+	      to or enters lisp.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410517"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist">
+                  <a class="xref" href="#m_without-interrupts" title="Macro WITHOUT-INTERRUPTS">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">without-interrupts</b>
+                  </a>
+                </span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410536"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">It would probably be better for <em class="varname">result</em>
+	      to always be NIL, since the present behavior is inconsistent.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      <span class="function"><strong>Process-interrupt</strong></span> works by sending signals
+	      between threads, via the C function
+	      <span class="function"><strong>#_pthread_signal</strong></span>.  It could be argued
+	      that it should be done in one of several possible other ways
+	      under
+	      Darwin, to make it practical to asynchronously interrupt
+	      things which make heavy use of the Mach nanokernel.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_current-process"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>*CURRENT-PROCESS*</code>
+            </div>
+            <div class="refentrytitle">Bound in each process, to that process
+	      itself.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410602"></a>
+                <div class="header">Value Type:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">A lisp process (thread).</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410613"></a>
+                <div class="header">Initial Value:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Bound separately in each process, to that process itself.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410625"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Used when lisp code needs to find out what process it is
+	      executing in.  Shouldn't be set by user code.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410637"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist">
+                  <a class="xref" href="#f_all-processes" title="Function ALL-PROCESSES">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">all-processes</b>
+                  </a>
+                </span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-reset"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-reset</strong></span>
+	      process <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> kill-option =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Causes a specified process to cleanly exit from
+	      any ongoing computation.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410708"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">kill-option</span></i>---an internal argument, must be nil.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---undefined.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410764"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Causes <em class="varname">process</em> to cleanly exit
+	      from any ongoing computation and enter a state where it can be
+	      <a class="xref" href="#f_process-preset" title="Function PROCESS-PRESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-preset</b></a>. This
+	      is implemented by signaling a condition of type PROCESS-RESET;
+	      user-defined condition handlers should generally refrain from
+	      attempting to handle conditions of this type.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The <em class="varname">kill-option</em> argument is for internal
+            use only and should not be specified by user code</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">A process can meaningfully reset itself.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">There is in general no way to know precisely when
+	      <em class="varname">process</em>
+	      has completed the act of resetting or killing itself; a process
+	      which has either entered the limbo of the reset state or exited
+	      has few ways of communicating either fact.
+	      <a class="xref" href="#f_process-enable" title="Function PROCESS-ENABLE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-enable</b></a>
+	      can reliably determine when a process has entered
+	      the "limbo of the reset state", but can't predict how long the
+	      clean exit from ongoing computation might take: that depends on
+	      the behavior of <span class="function"><strong>unwind-protect</strong></span> cleanup
+	      forms, and of the OS scheduler.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Resetting a process other than
+	      <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b></a> involves the
+	      use of <a class="xref" href="#f_process-interrupt" title="Function PROCESS-INTERRUPT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-interrupt</b></a>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410832"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-kill" title="Function PROCESS-KILL"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-kill</b></a>, <a class="xref" href="#f_process-abort" title="Function PROCESS-ABORT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-abort</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-kill"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-kill</strong></span> process
+	      =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Causes a specified process to cleanly exit from any
+	      ongoing computation, and then exit.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410905"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---undefined.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410947"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Entirely equivalent to calling
+	      (PROCESS-RESET PROCESS T).  Causes <em class="varname">process</em>
+	      to cleanly exit from any ongoing computation, and then exit.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id410962"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-reset" title="Function PROCESS-RESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-reset</b></a>, <a class="xref" href="#f_process-abort" title="Function PROCESS-ABORT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-abort</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-abort"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-abort</strong></span> process
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> condition
+	      =&gt; NIL</code>
+            </div>
+            <div class="refentrytitle">Causes a specified process to process an abort
+	      condition, as if it had invoked
+	      abort.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411046"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a lisp process (thread).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">condition</span></i>---a lisp condition.  The default is NIL.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411087"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Entirely equivalent to calling
+	      (<a class="xref" href="#f_process-interrupt" title="Function PROCESS-INTERRUPT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-interrupt</b></a> <em class="varname">process</em>
+	      (<span class="function"><strong>lambda</strong></span> ()
+	      (<span class="function"><strong>abort</strong></span> <em class="varname">condition</em>))).
+	      Causes <em class="varname">process</em> to transfer control to the
+	      applicable handler or restart for <span class="function"><strong>abort</strong></span>.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If <em class="varname">condition</em> is non-NIL,
+	      <span class="function"><strong>process-abort</strong></span> does not consider any
+	      handlers which are explicitly bound to conditions other than
+	      <em class="varname">condition</em>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411150"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-reset" title="Function PROCESS-RESET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-reset</b></a>, <a class="xref" href="#f_process-kill" title="Function PROCESS-KILL"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-kill</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_ticks-per-second"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>*TICKS-PER-SECOND*</code>
+            </div>
+            <div class="refentrytitle">Bound to the clock resolution of the OS
+	      scheduler.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411209"></a>
+                <div class="header">Value Type:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">A positive integer.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411220"></a>
+                <div class="header">Initial Value:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">The clock resolution of the OS scheduler.  Currently,
+	      both LinuxPPC and DarwinPPC yield an initial value of 100.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411232"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">This value is ordinarily of marginal interest at best,
+	      but, for backward compatibility, some functions accept timeout
+	      values expressed in "ticks".  This value gives the number of
+	      ticks per second.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411245"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist">
+                  <a class="xref" href="#f_process-wait-with-timeout" title="Function PROCESS-WAIT-WITH-TIMEOUT">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait-with-timeout</b>
+                  </a>
+                </span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-whostate"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-whostate</strong></span> process
+	      =&gt; whostate</code>
+            </div>
+            <div class="refentrytitle">Returns a string which describes the status of
+	      a specified process.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411350"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">This information is primarily for the benefit of
+	      debugging tools.  <em class="varname">whostate</em> is a terse report
+	      on what <em class="varname">process</em> is doing, or not doing,
+	      and why.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If the process is currently waiting in a call to
+	      <a class="xref" href="#f_process-wait" title="Function PROCESS-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait</b></a> or
+	      <a class="xref" href="#f_process-wait-with-timeout" title="Function PROCESS-WAIT-WITH-TIMEOUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait-with-timeout</b></a>, its
+	      <span class="function"><strong>process-whostate</strong></span> will be the value
+	      which was passed to that function as <em class="varname">whostate</em>.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411393"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-wait" title="Function PROCESS-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait</b></a>, <a class="xref" href="#f_process-wait-with-timeout" title="Function PROCESS-WAIT-WITH-TIMEOUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait-with-timeout</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411424"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">This should arguably be SETFable, but doesn't seem to
+	      ever have been.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-allow-schedule"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="function">
+                  <strong>process-allow-schedule</strong>
+                </span>
+              </code>
+            </div>
+            <div class="refentrytitle">Used for cooperative multitasking; probably never
+	      necessary.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411482"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Advises the OS scheduler that the current thread has nothing
+	      useful to do and that it should try to find some other thread to
+	      schedule in its place. There's almost always a better
+	      alternative, such as waiting for some specific event to
+	      occur.  For example, you could use a lock or semaphore.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411496"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411544"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">This is a holdover from the days of cooperative
+	      multitasking.  All modern general-purpose operating systems use
+	      preemptive multitasking.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-wait"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-wait</strong></span>
+	      whostate function <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> args =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Causes the current lisp process (thread) to wait for
+	      a given
+	      predicate to return true.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411608"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">whostate</span></i>---a string, which will be the value of
+		        <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_process-whostate" title="Function PROCESS-WHOSTATE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-whostate</b></a>
+		        while the process is waiting.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">function</span></i>---a function, designated by itself or by a symbol
+		        which names it.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">args</span></i>---a list of values, appropriate as arguments to
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">function</em>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---NIL.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411688"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Causes the current lisp process (thread) to repeatedly
+	      apply <em class="varname">function</em> to
+	      <em class="varname">args</em> until the call returns a true result, then
+	      returns NIL. After
+	      each failed call, yields the CPU as if by
+	      <a class="xref" href="#f_process-allow-schedule" title="Function PROCESS-ALLOW-SCHEDULE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-allow-schedule</b></a>.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      As with <a class="xref" href="#f_process-allow-schedule" title="Function PROCESS-ALLOW-SCHEDULE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-allow-schedule</b></a>, it's almost
+	      always more efficient to wait for some
+	      specific event to occur; this isn't exactly busy-waiting, but
+	      the OS scheduler can do a better job of scheduling if it's given
+	      the relevant information.  For example, you could use a lock
+	      or semaphore.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411724"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_process-whostate" title="Function PROCESS-WHOSTATE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-whostate</b></a>, <a class="xref" href="#f_process-wait-with-timeout" title="Function PROCESS-WAIT-WITH-TIMEOUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait-with-timeout</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-wait-with-timeout"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-wait-with-timeout</strong></span>
+	      whostate ticks function args =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Causes the current thread to wait for a given
+	      predicate to return true, or for a timeout to expire.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411832"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">whostate</span></i>---a string, which will be the value of
+		        <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_process-whostate" title="Function PROCESS-WHOSTATE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-whostate</b></a>
+		        while the process is waiting.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ticks</span></i>---either a positive integer expressing a duration
+		        in "ticks" (see <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#v_ticks-per-second" title="Variable *TICKS-PER-SECOND*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*ticks-per-second*</b></a>),
+		        or NIL.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">function</span></i>---a function, designated by itself or by a symbol
+		        which names it.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">args</span></i>---a list of values, appropriate as arguments to
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">function</em>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---T if <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-wait-with-timeout</strong></span>
+		        returned because its <em xmlns="http://www.w3.org/1999/xhtml" class="varname">function</em> returned
+		        true, or NIL if it returned because the duration
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">ticks</em> has been exceeded.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id411946"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">If <em class="varname">ticks</em> is NIL, behaves exactly like
+	      <a class="xref" href="#f_process-wait" title="Function PROCESS-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait</b></a>, except for returning T.
+	      Otherwise, <em class="varname">function</em> will be tested repeatedly,
+	      in the same
+	      kind of test/yield loop as in <a class="xref" href="#f_process-wait" title="Function PROCESS-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait</b></a>
+	      until either <em class="varname">function</em> returns true,
+	      or the duration <em class="varname">ticks</em> has been exceeded.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml"> Having already read the descriptions of
+	      <a class="xref" href="#f_process-allow-schedule" title="Function PROCESS-ALLOW-SCHEDULE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-allow-schedule</b></a> and
+	      <a class="xref" href="#f_process-wait" title="Function PROCESS-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait</b></a>, the
+	      astute reader has no doubt anticipated the observation that
+	      better alternatives should be used whenever possible.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id428893"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#v_ticks-per-second" title="Variable *TICKS-PER-SECOND*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*ticks-per-second*</b></a>, <a class="xref" href="#f_process-whostate" title="Function PROCESS-WHOSTATE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-whostate</b></a>, <a class="xref" href="#f_process-wait" title="Function PROCESS-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-wait</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_without-interrupts"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>without-interrupts</strong></span>
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Evaluates its body in an environment in which
+	      process-interrupt requests are deferred.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id428997"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---an implicit progn.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---the primary value returned by
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">body</em>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429035"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Executes <em class="varname">body</em>
+	      in an environment in which <a class="xref" href="#f_process-interrupt" title="Function PROCESS-INTERRUPT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-interrupt</b></a>
+	      requests are
+	      deferred. As noted in the description of
+	      <a class="xref" href="#f_process-interrupt" title="Function PROCESS-INTERRUPT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-interrupt</b></a>, this has nothing to do
+	      with the
+	      scheduling of other threads; it may be necessary to inhibit
+	      <a class="xref" href="#f_process-interrupt" title="Function PROCESS-INTERRUPT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-interrupt</b></a> handling when
+	      (for instance) modifying some data
+	      structure (for which the current thread holds an appropriate lock)
+	      in some manner that's not reentrant.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429064"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist">
+                  <a class="xref" href="#f_process-interrupt" title="Function PROCESS-INTERRUPT">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-interrupt</b>
+                  </a>
+                </span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_make-lock"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-lock</strong></span> <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em>
+	      name =&gt; lock</code>
+            </div>
+            <div class="refentrytitle">Creates and returns a lock object, which can
+	      be used for synchronization between threads.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429126"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---any lisp object; saved as part of
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">lock</em>.  Typically a string or symbol
+		        which may appear in the <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_process-whostate" title="Function PROCESS-WHOSTATE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-whostate</b></a>s
+		        of threads which are waiting for <em xmlns="http://www.w3.org/1999/xhtml" class="varname">lock</em>.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">lock</span></i>---a newly-allocated object of type CCL:LOCK.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429172"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Creates and returns a lock object, which can
+	      be used to synchronize access to some shared resource.
+	      <em class="varname">lock</em> is
+	      initially in a "free" state; a lock can also be
+	      "owned" by a
+	      thread.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429187"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#m_with-lock-grabbed" title="Macro WITH-LOCK-GRABBED"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-lock-grabbed</b></a>, <a class="xref" href="#f_grab-lock" title="Function GRAB-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">grab-lock</b></a>, <a class="xref" href="#f_release-lock" title="Function RELEASE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">release-lock</b></a>, <a class="xref" href="#f_try-lock" title="Function TRY-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">try-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_with-lock-grabbed"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>with-lock-grabbed</strong></span>
+	      (lock) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle">Waits until a given lock can be obtained, then
+	      evaluates its body with the lock held.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429290"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">lock</span></i>---an object of type CCL:LOCK.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---an implicit progn.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---the primary value returned by
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">body</em>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429342"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Waits until <em class="varname">lock</em> is either free or
+	      owned by the calling
+	      thread, then executes <em class="varname">body</em> with the
+	      lock owned by the calling thread. If <em class="varname">lock</em>
+	      was free when <span class="function"><strong>with-lock-grabbed</strong></span> was called,
+	      it is restored to a free state after <em class="varname">body</em>
+	      is executed.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429371"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_grab-lock" title="Function GRAB-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">grab-lock</b></a>, <a class="xref" href="#f_release-lock" title="Function RELEASE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">release-lock</b></a>, <a class="xref" href="#f_try-lock" title="Function TRY-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">try-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_grab-lock"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>grab-lock</strong></span> lock</code>
+            </div>
+            <div class="refentrytitle">Waits until a given lock can be obtained, then
+	      obtains it.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429471"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">lock</span></i>---an object of type CCL:LOCK.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429493"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Blocks until <em class="varname">lock</em> is owned by the
+	      calling thread.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The macro <a class="xref" href="#m_with-lock-grabbed" title="Macro WITH-LOCK-GRABBED"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-lock-grabbed</b></a>
+	      <span class="emphasis"><em>could</em></span> be defined in
+	      terms of <span class="function"><strong>grab-lock</strong></span> and
+	      <a class="xref" href="#f_release-lock" title="Function RELEASE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">release-lock</b></a>, but it is actually
+	      implemented at a slightly lower level.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429526"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#m_with-lock-grabbed" title="Macro WITH-LOCK-GRABBED"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-lock-grabbed</b></a>, <a class="xref" href="#f_release-lock" title="Function RELEASE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">release-lock</b></a>, <a class="xref" href="#f_try-lock" title="Function TRY-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">try-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_release-lock"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>release-lock</strong></span> lock</code>
+            </div>
+            <div class="refentrytitle">Relinquishes ownership of a given lock.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429626"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">lock</span></i>---an object of type CCL:LOCK.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429648"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Signals an error of type CCL:LOCK-NOT-OWNER if
+	      <em class="varname">lock</em>
+	      is not already owned by the calling thread; otherwise, undoes the
+	      effect of one previous 
+	      <a class="xref" href="#f_grab-lock" title="Function GRAB-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">grab-lock</b></a>.  If this means that
+	      <span class="function"><strong>release-lock</strong></span> has now been called on
+	      <em class="varname">lock</em> the same number of times as
+	      <a class="xref" href="#f_grab-lock" title="Function GRAB-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">grab-lock</b></a> has, <em class="varname">lock</em>
+	      becomes free.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429682"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#m_with-lock-grabbed" title="Macro WITH-LOCK-GRABBED"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-lock-grabbed</b></a>, <a class="xref" href="#f_grab-lock" title="Function GRAB-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">grab-lock</b></a>, <a class="xref" href="#f_try-lock" title="Function TRY-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">try-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_try-lock"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>try-lock</strong></span> lock =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Obtains the given lock, but only if it is not
+	      necessary to wait for it.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429782"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">lock</span></i>---an object of type CCL:LOCK.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---T if <em xmlns="http://www.w3.org/1999/xhtml" class="varname">lock</em> has been obtained,
+		        or NIL if it has not.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429820"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tests whether <em class="varname">lock</em>
+	      can be obtained without blocking - that is, either
+	      <em class="varname">lock</em> is already free, or it is already owned
+	      by <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b></a>.  If it can,
+	      causes it to
+	      be owned by the calling lisp process (thread) and returns T.
+	      Otherwise, the lock
+	      is already owned by another thread and cannot be obtained without
+	      blocking; NIL is returned in this case.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429844"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#m_with-lock-grabbed" title="Macro WITH-LOCK-GRABBED"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-lock-grabbed</b></a>, <a class="xref" href="#f_grab-lock" title="Function GRAB-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">grab-lock</b></a>, <a class="xref" href="#f_release-lock" title="Function RELEASE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">release-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_make-read-write-lock"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-read-write-lock</strong></span>
+	      =&gt; read-write-lock</code>
+            </div>
+            <div class="refentrytitle">Creates and returns a read-write lock, which can
+	      be used for synchronization between threads.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429944"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">read-write-lock</span></i>---a newly-allocated object of type
+		        CCL:READ-WRITE-LOCK.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429967"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Creates and returns an object of type CCL::READ-WRITE-LOCK.
+	      A read-write lock may, at any given time, belong to any number
+	      of lisp processes (threads) which act as "readers"; or, it may
+	      belong to at most one process which acts as a "writer".  A
+	      read-write lock may never be held by a reader at the same time as
+	      a writer.  Initially, <em class="varname">read-write-lock</em> has
+	      no readers and no writers.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id429983"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#m_with-read-lock" title="Macro WITH-READ-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-read-lock</b></a>, <a class="xref" href="#m_with-write-lock" title="Macro WITH-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-write-lock</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430031"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">There probably should be some way to
+	      atomically "promote" a reader, making it a writer without
+	      releasing the lock, which could otherwise cause delay.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_with-read-lock"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>with-read-lock</strong></span>
+	      (read-write-lock) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Waits until a given lock is available for
+	      read-only access, then evaluates its body with the lock
+	      held.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430087"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">read-write-lock</span></i>---an object of type
+		        CCL:READ-WRITE-LOCK.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---an implicit progn.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---the primary value returned by
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">body</em>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430138"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Waits until <em class="varname">read-write-lock</em> has no
+	      writer,
+	      ensures that <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b></a> is a
+	      reader of it, then executes <em class="varname">body</em>.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">After executing <em class="varname">body</em>, if
+	      <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b></a> was not a reader of
+	      <em class="varname">read-write-lock</em> before
+	      <span class="function"><strong>with-read-lock</strong></span> was called, the lock is
+	      released.  If it was already a reader, it remains one.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430178"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#m_with-write-lock" title="Macro WITH-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-write-lock</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_with-write-lock"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>with-write-lock</strong></span>
+	      (read-write-lock) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle">Waits until the given lock is available for write
+	      access, then executes its body with the lock held.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430271"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">read-write-lock</span></i>---an object of type
+		        CCL:READ-WRITE-LOCK.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---an implicit progn.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---the primary value returned by
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">body</em>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430323"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Waits until <em class="varname">read-write-lock</em> has no
+	      readers and no writer other than <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b></a>,
+	      then ensures that <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b></a> is the
+	      writer of it.  With the lock held, executes <em class="varname">body</em>.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">After executing <em class="varname">body</em>, if
+	      <a class="xref" href="#v_current-process" title="Variable *CURRENT-PROCESS*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*current-process*</b></a> was not the writer of
+	      <em class="varname">read-write-lock</em> before
+	      <span class="function"><strong>with-write-lock</strong></span> was called, the lock is
+	      released.  If it was already the writer, it remains the
+	      writer.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430367"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#m_with-read-lock" title="Macro WITH-READ-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-read-lock</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_make-semaphore"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-semaphore</strong></span>
+	      =&gt; semaphore</code>
+            </div>
+            <div class="refentrytitle">Creates and returns a semaphore, which can be used
+	      for synchronization between threads.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430457"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">semaphore</span></i>---a newly-allocated object of type CCL:SEMAPHORE.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430480"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Creates and returns an object of type CCL:SEMAPHORE.
+	      A semaphore has an associated "count" which may be incremented
+	      and decremented atomically; incrementing it represents sending
+	      a signal, and decrementing it represents handling that signal.
+	      <em class="varname">semaphore</em> has an initial count of 0.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430495"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_signal-semaphore" title="Function SIGNAL-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">signal-semaphore</b></a>, <a class="xref" href="#f_wait-on-semaphore" title="Function WAIT-ON-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">wait-on-semaphore</b></a>, <a class="xref" href="#f_timed-wait-on-semaphore" title="Function TIMED-WAIT-ON-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">timed-wait-on-semaphore</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_signal-semaphore"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>signal-semaphore</strong></span>
+	      semaphore =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Atomically increments the count of a given
+	      semaphore.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430590"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">semaphore</span></i>---an object of type CCL:SEMAPHORE.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---an integer representing an error identifier
+		        which was returned by the underlying OS call.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430626"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Atomically increments <em class="varname">semaphore</em>'s
+	      "count" by 1; this
+	      may enable a waiting thread to resume execution.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430639"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_wait-on-semaphore" title="Function WAIT-ON-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">wait-on-semaphore</b></a>, <a class="xref" href="#f_timed-wait-on-semaphore" title="Function TIMED-WAIT-ON-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">timed-wait-on-semaphore</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430693"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml"><em class="varname">result</em> should probably be interpreted
+	      and acted on by <span class="function"><strong>signal-semaphore</strong></span>, because
+	      it is not likely to be meaningful to a lisp program, and the
+	      most common cause of failure is a type error.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_wait-on-semaphore"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>wait-on-semaphore</strong></span>
+	      semaphore =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Waits until the given semaphore has a positive
+	      count which can be atomically decremented.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430753"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">semaphore</span></i>---an object of type CCL:SEMAPHORE.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---an integer representing an error identifier
+		        which was returned by the underlying OS call.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430789"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Waits until <em class="varname">semaphore</em>
+	      has a positive count that can be
+	      atomically decremented; this will succeed exactly once for each
+	      corresponding call to SIGNAL-SEMAPHORE.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430803"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_signal-semaphore" title="Function SIGNAL-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">signal-semaphore</b></a>, <a class="xref" href="#f_timed-wait-on-semaphore" title="Function TIMED-WAIT-ON-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">timed-wait-on-semaphore</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430856"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml"><em class="varname">result</em> should probably be interpreted
+	      and acted on by <span class="function"><strong>wait-on-semaphore</strong></span>, because
+	      it is not likely to be meaningful to a lisp program, and the
+	      most common cause of failure is a type error.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_timed-wait-on-semaphore"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>timed-wait-on-semaphore</strong></span>
+	      semaphore timeout =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Waits until the given semaphore has a positive
+	      count which can be atomically decremented, or until a timeout
+	      expires.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430916"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">semaphore</span></i>---An object of type CCL:SEMAPHORE.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">timeout</span></i>---a time interval in seconds.  May be any
+		        non-negative real number the <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>floor</strong></span> of
+		        which fits in 32 bits.  The default is 1.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---T if <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>timed-wait-on-semaphore</strong></span>
+		        returned because it was able to decrement the count of
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">semaphore</em>; NIL if it returned because
+		        the duration <em xmlns="http://www.w3.org/1999/xhtml" class="varname">timeout</em> has been
+		        exceeded.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id430983"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Waits until <em class="varname">semaphore</em>
+	      has a positive count that can be
+	      atomically decremented, or until the duration
+	      <em class="varname">timeout</em> has
+	      elapsed.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431000"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_wait-on-semaphore" title="Function WAIT-ON-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">wait-on-semaphore</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-input-wait"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-input-wait</strong></span>
+	      fd <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> timeout</code>
+            </div>
+            <div class="refentrytitle">Waits until input is available on a given
+	      file-descriptor.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431093"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">fd</span></i>---a file descriptor, which is a non-negative integer
+		        used by the OS to refer to an open file, socket, or similar
+		        I/O connection.  See <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_stream-device" title="Generic Function CCL::STREAM-DEVICE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">ccl::stream-device</b></a>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">timeout</span></i>---either NIL or a time interval in milliseconds.  Must be a non-negative integer.  The default is NIL.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431134"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Wait until input is available on <em class="varname">fd</em>.
+	      This uses the <span class="function"><strong>select()</strong></span> system call, and is
+	      generally a fairly
+	      efficient way of blocking while waiting for input. More
+	      accurately, <span class="function"><strong>process-input-wait</strong></span>
+	      waits until it's possible to read
+	      from fd without blocking, or until <em class="varname">timeout</em>, if
+	      it is not NIL, has been exceeded.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Note that it's possible to read without blocking if
+	      the file is at its end - although, of course, the read will
+	      return zero bytes.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431167"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431205"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      <span class="function"><strong>process-input-wait</strong></span> has a timeout parameter,
+	      and
+	      <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a> does not.  This
+	      inconsistency should probably be corrected.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_process-output-wait"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-output-wait</strong></span>
+	      fd  <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> timeout</code>
+            </div>
+            <div class="refentrytitle">Waits until output is possible on a given file
+	      descriptor.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431270"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">fd</span></i>---a file descriptor, which is a non-negative integer
+		        used by the OS to refer to an open file, socket, or similar
+		        I/O connection.  See <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_stream-device" title="Generic Function CCL::STREAM-DEVICE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">ccl::stream-device</b></a>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">timeout</span></i>---either NIL or a time interval in milliseconds.  Must be a non-negative integer.  The default is NIL.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431311"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Wait until output is possible on <em class="varname">fd</em> or until <em class="varname">timeout</em>, if
+	      it is not NIL, has been exceeded.
+	      This uses the <span class="function"><strong>select()</strong></span> system call, and is
+	      generally a fairly
+	      efficient way of blocking while waiting to output.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If <span class="function"><strong>process-output-wait</strong></span> is called on
+	      a network socket which has not yet established a connection, it
+	      will wait until the connection is established.  This is an
+	      important use, often overlooked.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431344"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a></span>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431382"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a> has a timeout parameter,
+	      and
+	      <span class="function"><strong>process-output-wait</strong></span> does not.  This
+	      inconsistency should probably be corrected.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_with-terminal-input"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>with-terminal-input</strong></span>
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body =&gt; result</code>
+            </div>
+            <div class="refentrytitle">Executes its body in an environment with exclusive
+	      read access to the terminal.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431447"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---an implicit progn.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---the primary value returned by
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">body</em>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431485"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Requests exclusive read access to the standard terminal
+	      stream, <em class="varname">*terminal-io*</em>.  Executes
+	      <em class="varname">body</em> in an environment with that access.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431502"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#v_request-terminal-input-via-break" title="Variable *REQUEST-TERMINAL-INPUT-VIA-BREAK*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*request-terminal-input-via-break*</b></a>, <a class="xref" href="#cmd_y" title="Toplevel Command :Y"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">:y</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_request-terminal-input-via-break"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>*REQUEST-TERMINAL-INPUT-VIA-BREAK*</code>
+            </div>
+            <div class="refentrytitle">Controls how attempts to obtain ownership of
+	      terminal input are made.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431579"></a>
+                <div class="header">Value Type:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">A boolean.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431588"></a>
+                <div class="header">Initial Value:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">NIL.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431598"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Controls how attempts to obtain ownership of terminal input
+	      are made. When NIL, a message is printed on *TERMINAL-IO*;
+	      it's expected that the user will later yield
+	      control of the terminal via the :Y toplevel command. When T, a
+	      BREAK condition is signaled in the owning process; continuing from
+	      the break loop will yield the terminal to the requesting process
+	      (unless the :Y command was already used to do so in the break
+	      loop.)</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431612"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a>, <a class="xref" href="#cmd_y" title="Toplevel Command :Y"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">:y</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="cmd_y"></a>
+              <strong>[Toplevel Command]</strong>
+              <br></br>
+              <code>(<span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>:y</strong></span> p)</code>
+            </div>
+            <div class="refentrytitle">Yields control of terminal input to a specified
+	      lisp process (thread).</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431703"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">p</span></i>---a lisp process (thread), designated either by
+		        an integer which matches its
+		        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-serial-number</strong></span>,
+		        or by a string which is <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>equal</strong></span> to
+		        its <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>process-name</strong></span>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431742"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">:Y is a toplevel command, not a function.  As such, it
+	      can only be used interactively, and only from the initial
+	      process.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The command yields control of terminal input to the
+	      process <em class="varname">p</em>, which must have used
+	      <a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a> to request access to the
+	      terminal input stream.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431764"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#m_with-terminal-input" title="Macro WITH-TERMINAL-INPUT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-terminal-input</b></a>, <a class="xref" href="#v_request-terminal-input-via-break" title="Variable *REQUEST-TERMINAL-INPUT-VIA-BREAK*"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">*request-terminal-input-via-break*</b></a>, <a class="xref" href="#f_make-lock" title="Function MAKE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-lock</b></a>, <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>, <a class="xref" href="#f_make-semaphore" title="Function MAKE-SEMAPHORE"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-semaphore</b></a>, <a class="xref" href="#f_process-input-wait" title="Function PROCESS-INPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-input-wait</b></a>, <a class="xref" href="#f_process-output-wait" title="Function PROCESS-OUTPUT-WAIT"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-output-wait</b></a></span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_join-process"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>join-process</strong></span> process
+	<em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> default =&gt; values</code>
+            </div>
+            <div class="refentrytitle">Waits for a specified process to complete and
+	returns the values that that process's initial function
+	returned.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431857"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">process</span></i>---a process, typically created by <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_process-run-function" title="Function PROCESS-RUN-FUNCTION"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-run-function</b></a> or by <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#f_make-process" title="Function MAKE-PROCESS"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-process</b></a></p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">default</span></i>---A default value to be returned if the specified
+	      process doesn't exit normally.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">values</span></i>---The values returned by the specified process's
+	      initial function if that function returns, or the value
+	      of the default argument, otherwise.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431914"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Waits for the specified process to terminate.  If the
+	process terminates "normally" (if its initial function
+	returns), returns the values that that initial function
+	returnes.  If the process does not terminate normally (e.g.,
+	if it's terminated via <a class="xref" href="#f_process-kill" title="Function PROCESS-KILL"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">process-kill</b></a> and a
+	default argument is provided, returns the value of that
+	default argument.  If the process doesn't terminate normally
+	and no default argument is provided, signals an error.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">A process can't successfully join itself, and only one
+	process can successfully receive notification of another process's
+	termination.</p>
+              </div>
+            </div>
+          </p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Programming-with-Sockets"></a>ChapterÂ 7.Â Programming with Sockets</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Sockets-Overview">7.1. Overview</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Sockets-Dictionary">7.2. Sockets Dictionary</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Sockets-Overview"></a>7.1.Â Overview</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL supports the socket abstraction for
+      interprocess communication. A socket represents a connection to
+      another process, typically (but not necessarily) a TCP/IP
+      network connection to a client or server running on some other
+      machine on the network.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">All symbols mentioned in this chapter are exported from
+      the CCL package. As of version 0.13, these symbols are
+      additionally exported from the OPENMCL-SOCKET package.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL supports three types of sockets: TCP sockets, UDP
+      sockets, and Unix-domain sockets.  This should be enough for all
+      but the most esoteric network situations.  All sockets are
+      created by <a class="xref" href="#f_make-socket" title="Function MAKE-SOCKET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-socket</b></a>.  The type of socket
+      depends on the arguments to it, as follows:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+            <dl>
+              <dt>
+                <span class="term">tcp-stream</span>
+              </dt>
+              <dd>
+                <p>A buffered bi-directional stream over a TCP/IP connection.
+	    tcp-stream is a subclass of stream, and you can read and write to it
+	    using all the usual stream functions. Created by (make-socket
+	    :address-family :internet :type :stream :connect :active ...) or by
+	    (accept-connection ...).</p>
+              </dd>
+              <dt>
+                <span class="term">file-socket-stream</span>
+              </dt>
+              <dd>
+                <p>A buffered bi-directional stream over a "UNIX domain"
+	    connection. file-socket-stream is a subclass of stream, and you can
+	    read and write to it using all the usual stream functions. Created
+	    by (make-socket :address-family :file :type :stream :connect :active
+	    ...) or by (accept-connection ...),</p>
+              </dd>
+              <dt>
+                <span class="term">listener-socket</span>
+              </dt>
+              <dd>
+                <p>A passive socket used to listen for incoming TCP/IP
+	    connections on a particular port. A listener-socket is not a stream.
+	    It doesn't support I/O. It can only be used to create new
+	    tcp-streams by accept-connection. Created by (make-socket :type
+	    :stream :connect :passive ...)</p>
+              </dd>
+              <dt>
+                <span class="term">file-listener-socket</span>
+              </dt>
+              <dd>
+                <p>A passive socket used to listen for incoming UNIX domain
+	    connections named by a file in the local filesystem. A
+	    listener-socket is not a stream. It doesn't support I/O. It can
+	    only be used to create new file-socket-streams by accept-connection.
+	    Created by (make-socket :address-family :file :type :stream :connect
+	    :passive ...)</p>
+              </dd>
+              <dt>
+                <span class="term">udp-socket</span>
+              </dt>
+              <dd>
+                <p>A socket representing a packet-based UDP/IP connection. A
+	    udp-socket supports I/O but it is not a stream. Instead, you must
+	    use the special functions send-to and receive-from to read and write
+	    to it. Created by (make-socket :type :datagram ...)</p>
+              </dd>
+            </dl>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Sockets-Dictionary"></a>7.2.Â Sockets Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_make-socket"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-socket</strong></span> <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em>
+	  address-family type connect eol format remote-host
+	  remote-port local-host local-port local-filename
+	  remote-filename keepalive reuse-address nodelay broadcast
+	  linger backlog input-timeout output-timeout connect-timeout
+	  auto-close deadline</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id404668"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">address-family</span></i>---The address/protocol family of this socket. Currently
+		only :internet (the default), meaning IP, and :file,
+		referring to UNIX domain addresses, are supported.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">type</span></i>---One of :stream (the default) to request a
+		connection-oriented socket, or :datagram to request a
+		connectionless socket. The default is :stream.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">connect</span></i>---This argument is only relevant to sockets of type
+		:stream. One of :active (the default) to request a :passive
+		to request a file or TCP listener socket.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">eol</span></i>---This argument is currently ignored (it is accepted for
+		compatibility with Franz Allegro).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">format</span></i>---One of :text (the default), :binary, or :bivalent.
+		This argument is ignored for :stream sockets for now, as
+		:stream sockets are currently always bivalent (i.e. they
+		support both character and byte I/O). For :datagram sockets,
+		the format determines the type of buffer created by
+		receive-from.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">remote-host</span></i>---Required for TCP streams, it specifies the host to
+		connect to (in any format acceptable to lookup-hostname).
+		Ignored for listener sockets. For UDP sockets, it can be
+		used to specify a default host for subsequent calls to
+		send-to or receive-from.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">remote-port</span></i>---Required for TCP streams, it specifies the port to
+		connect to (in any format acceptable to lookup-port).
+		Ignored for listener sockets. For UDP sockets, it can be
+		used to specify a default port for subsequent calls to for
+		subsequent calls to send-to or receive-from.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">remote-filename</span></i>---Required for file-socket streams, it specifies the
+		name of a file in the local filesystem (e.g., NOT mounted
+		via NFS, AFP, SMB, ...) which names and controls access to a
+		UNIX-domain socket.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">local-host</span></i>---Allows you to specify a local host address for a
+		listener or UDP socket, for the rare case where you want to
+		restrict connections to those coming to a specific local
+		address for security reasons.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">local-port</span></i>---Specify a local port for a socket. Most useful for
+		listener sockets, where it is the port on which the socket
+		will listen for connections.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">local-filename</span></i>---Required for file-listener-sockets. Specifies the name
+		of a file in the local filesystem which is used to name a
+		UNIX-domain socket. The actual filesystem file should not
+		previously exist when the file-listener-socket is created;
+		its parent directory should exist and be writable by the
+		caller. The file used to name the socket will be deleted
+		when the file-listener-socket is closed.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">keepalive</span></i>---If true, enables the periodic transmission of
+		"keepalive" messages.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">reuse-address</span></i>---If true, allows the reuse of local ports in listener
+		sockets, overriding some TCP/IP protocol specifications. You
+		will need this if you are debugging a server..</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">nodelay</span></i>---If true, disables Nagle's algorithm, which tries
+		to minimize TCP packet fragmentation by introducing
+		transmission delays in the absence of replies. Try setting
+		this if you are using a protocol which involves sending a
+		steady stream of data with no replies and are seeing
+		significant degradations in throughput.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">broadcast</span></i>---If true, requests permission to broadcast datagrams on
+		a UDP socket.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">linger</span></i>---If specified and non-nil, should be the number of
+		seconds the OS is allowed to wait for data to be pushed
+		through when a close is done. Only relevant for TCP sockets.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">backlog</span></i>---For a listener socket, specifies the number of
+		connections which can be pending but not accepted. The
+		default is 5, which is also the maximum on some operating
+		systems.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">input-timeout</span></i>---The number of seconds before an input operation
+		times out.  Must be a real number between zero and one
+		million.  If an input operation takes longer than the
+		specified number of seconds, an
+		<code xmlns="http://www.w3.org/1999/xhtml" class="literal">input-timeout</code> error is signalled.
+		(see <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#Stream-Timeouts-And-Deadlines" title="9.1.4.Â Stream Timeouts and Deadlines">SectionÂ 9.1.4, âStream Timeouts and Deadlinesâ</a>)</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">output-timeout</span></i>---The number of seconds before an output operation
+		times out.  Must be a real number between zero and one
+		million.  If an output operation takes longer than the
+		specified number of seconds, an
+		<code xmlns="http://www.w3.org/1999/xhtml" class="literal">output-timeout</code> error is signalled.
+		(see <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#Stream-Timeouts-And-Deadlines" title="9.1.4.Â Stream Timeouts and Deadlines">SectionÂ 9.1.4, âStream Timeouts and Deadlinesâ</a>)</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">connect-timeout</span></i>---The number of seconds before a connection
+		attempt times out. [TODO: what are acceptable values?]
+		If a connection attempt takes longer than the
+		specified number of seconds, a
+		<code xmlns="http://www.w3.org/1999/xhtml" class="literal">socket-error</code> is signalled.  This
+		can be useful if the specified interval is shorter
+		than the interval that the OS's socket layer imposes,
+		which is sometimes a minute or two.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">auto-close</span></i>---When non-nil, any resulting socket stream will
+		be closed when the GC can prove that the stream is
+		unreferenced.  This is done via CCL's termination
+		mechanism [TODO add xref].</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">deadline</span></i>---Specifies an absolute time in
+		internal-time-units.  If an I/O operation on the
+		stream does not complete before the deadline then a
+		<code xmlns="http://www.w3.org/1999/xhtml" class="literal">COMMUNICATION-DEADLINE-EXPIRED</code>
+		error is signalled.  A deadline takes precedence over
+		any input/output timeouts that may be set.  (see <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#Stream-Timeouts-And-Deadlines" title="9.1.4.Â Stream Timeouts and Deadlines">SectionÂ 9.1.4, âStream Timeouts and Deadlinesâ</a>)</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id416533"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Creates and returns a new socket</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_accept-connection"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>accept-connection</strong></span>
+	  (socket listener-socket) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> wait</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id405305"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The listener-socket to listen on.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">wait</span></i>---If true (the default), and there are no connections
+		waiting to be accepted, waits until one arrives. If false,
+		returns NIL immediately.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id405347"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Extracts the first connection on the queue of pending
+	  connections, accepts it (i.e. completes the connection startup
+	  protocol) and returns a new tcp-stream or file-socket-stream
+	  representing the newly established connection. The tcp stream
+	  inherits any properties of the listener socket that are relevant
+	  (e.g. :keepalive, :nodelay, etc.) The original listener socket
+	  continues to be open listening for more connections, so you can
+	  call accept-connection on it again.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_dotted-to-ipaddr"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>dotted-to-ipaddr</strong></span>
+	  dotted <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> errorp</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id405412"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">dotted</span></i>---A string representing an IP address in the
+		"nn.nn.nn.nn" format</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">errorp</span></i>---If true (the default) an error is signaled if dotted
+		is invalid. If false, NIL is returned.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id405454"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Converts a dotted-string representation of a host address to
+	  a 32-bit unsigned IP address.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_ipaddr-to-dotted"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>ipaddr-to-dotted</strong></span>
+	  ipaddr <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> values</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id405516"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ipaddr</span></i>---A 32-bit integer representing an internet host address</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">values</span></i>---If false (the default), returns a string in the form
+		"nn.nn.nn.nn". If true, returns four values
+		representing the four octets of the address as unsigned
+		8-bit integers.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id405558"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Converts a 32-bit unsigned IP address into octets.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_ipaddr-to-hostname"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>ipaddr-to-hostname</strong></span>
+	  ipaddr <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> ignore-cache</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id405619"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ipaddr</span></i>---a 32-bit integer representing an internet host address</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ignore-cache</span></i>---This argument is ignored (it is accepted for
+		compatibility with Franz Allegro)</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415813"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Converts a 32-bit unsigned IP address into a host name
+	  string</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_lookup-hostname"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>lookup-hostname</strong></span>
+	  host</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415871"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">host</span></i>---Specifies the host. It can be either a host name
+		string such as "clozure.com", or a dotted address
+		string such as "192.168.0.1", or a 32-bit unsigned
+		IP address such as 3232235521.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415898"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Converts a host spec in any of the acceptable formats into a
+	  32-bit unsigned IP address</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_lookup-port"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>lookup-port</strong></span>
+	  port protocol</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415956"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">port</span></i>---Specifies the port. It can be either a string, such as
+		"http" or a symbol, such as :http, or an unsigned
+		port number. Note that a string is case-sensitive. A symbol
+		is lowercased before lookup.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">protocol</span></i>---Must be one of "tcp" or "udp".</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415999"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Finds the port number for the specified port and protocol</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_receive-from"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>receive-from</strong></span>
+	  (socket udp-socket) size <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> buffer
+	  extract offset</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id416060"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket to read from</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">size</span></i>---Maximum number of bytes to read. If the packet is
+		larger than this, any extra bytes are discarded.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">buffer</span></i>---If specified, must be either a string or a byte vector
+		which will be used to read in the data. If not specified, a
+		new buffer will be created (of type determined by
+		socket-format).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">extract</span></i>---If true, the subsequence of the buffer corresponding
+		only to the data read in is extracted and returned as the
+		first value. If false (the default) the original buffer is
+		returned even if it is only partially filled.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">offset</span></i>---Specifies the start offset into the buffer at which
+		data is to be stored. The default is 0.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id416151"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Reads a UDP packet from a socket. If no packets are
+	  available, waits for a packet to arrive. Returns four values:</p>
+                <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+                  <ol type="1">
+                    <li>
+                      <p>The buffer with the data</p>
+                    </li>
+                    <li>
+                      <p>The number of bytes read</p>
+                    </li>
+                    <li>
+                      <p>The 32-bit unsigned IP address of the sender of the data</p>
+                    </li>
+                    <li>
+                      <p>The port number of the sender of the data</p>
+                    </li>
+                  </ol>
+                </div>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_send-to"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>send-to</strong></span>
+	  (socket udp-socket) buffer size <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> remote-host
+	  remote-port offset</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414566"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket to write to</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">buffer</span></i>---A vector containing the data to send. It must be
+		either a string or a byte vector (either one is acceptable
+		regardless of the stream format).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">size</span></i>---Number of bytes to send</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">remote-host</span></i>---The host to send the packet to, in any format
+		acceptable to lookup-hostname. The default is the remote
+		host specified in the call to make-socket.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">remote-port</span></i>---The port to send the packet to, in any format
+		acceptable to lookup-port. The default is the remote port
+		specified in the call to make-socket.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">offset</span></i>---The offset in the buffer where the packet data starts</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414670"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Send a UDP packet over a socket.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_shutdown"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>shutdown</strong></span>
+	  socket <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> direction</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414731"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket to shut down (typically a tcp-stream)</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">direction</span></i>---One of :input to disallow further input, or :output to
+		disallow further output.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414772"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Shuts down part of a bidirectional connection. This is
+	  useful if e.g. you need to read responses after sending an
+	  end-of-file signal.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-os-fd"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-os-fd</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414830"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414857"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the native OS's representation of the socket, or
+	  NIL if the socket is closed. On Unix, this is the Unix 'file
+	  descriptor', a small non-negative integer. Note that it is
+	  rather dangerous to mess around with tcp-stream fd's, as there
+	  is all sorts of buffering and asynchronous I/O going on above the
+	  OS level. listener-socket and udp-socket fd's are safer to
+	  mess with directly as there is less magic going on.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_remote-host"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>remote-host</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414918"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id414944"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the 32-bit unsigned IP address of the remote host,
+	  or NIL if the socket is not connected.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_remote-port"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>remote-port</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415002"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415028"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the remote port number, or NIL if the socket is not
+	  connected.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_local-host"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>local-host</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415085"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415111"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns 32-bit unsigned IP address of the local host.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_local-port"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>local-port</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413097"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413123"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the local port number</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-address-family"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-address-family</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413181"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413207"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns :internet or :file, as appropriate.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-connect"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-connect</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413264"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413290"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns :active for tcp-stream, :passive for
+	  listener-socket, and NIL for udp-socket</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-format"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-format</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413348"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413374"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the socket format as specified by the :format
+	  argument to make-socket.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-type"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-type</strong></span>
+	  socket</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413431"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413457"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">returns :stream for tcp-stream and listener-socket, and
+	  :datagram for udp-socket.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="c_socket-error"></a>
+              <strong>[Class]</strong>
+              <br></br>
+              <code>SOCKET-ERROR</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413500"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">The class of OS errors signaled by socket functions</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413511"></a>
+                <div class="header">Superclasses:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">simple-error</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-error-code"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-error-code</strong></span>
+	  socket-error</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413568"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket-error</span></i>---the condition</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413594"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">The OS error code of the error</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-error-identifier"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-error-identifier</strong></span>
+	  socket-error</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id413652"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket-error</span></i>---the condition</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415167"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">A symbol representing the error code in a more
+	  OS-independent way.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">One of: :address-in-use :connection-aborted :no-buffer-space
+	  :connection-timed-out :connection-refused :host-unreachable
+	  :host-down :network-down :address-not-available :network-reset
+	  :connection-reset :shutdown :access-denied or :unknown.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_socket-error-situation"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>socket-error-situation</strong></span>
+	  socket-error</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415230"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket-error</span></i>---the condition</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415256"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">A string describing the context where the error happened. On
+	  Linux, this is the name of the system call which returned the
+	  error.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="o_close"></a>
+              <strong>[Method]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>close</strong></span>
+	  (socket socket) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> abort</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415318"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">socket</span></i>---The socket to close</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">abort</span></i>---If false (the default), closes the socket in an
+		orderly fashion, finishing up any buffered pending I/O,
+		before closing the connection. If true, aborts/ignores
+		pending I/O. (For listener and udp sockets, this argument is
+		effectively ignored since there is never any buffered I/O to
+		clean up).</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415362"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">The close generic function can be applied to sockets. It
+	  releases the operating system resources associated with the
+	  socket.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_with-open-socket"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>with-open-socket</strong></span>
+	  (var . make-socket-args) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415424"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">var</span></i>---variable to bind</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">make-socket-args</span></i>---arguments suitable for passing to make-socket</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---body to execute</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id415480"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">executes body with var bound to the result of applying
+	  make-socket to make-socket-args. The socket gets closed on exit.</p>
+              </div>
+            </div>
+          </p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Running-Other-Programs-as-Subprocesses"></a>ChapterÂ 8.Â Running Other Programs as Subprocesses</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Subprocess-Overview">8.1. Overview</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Subprocess-Examples">8.2. Examples</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Limitations-and-known-bugs">8.3. Limitations and known bugs</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#External-Program-Dictionary">8.4. External-Program Dictionary</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Subprocess-Overview"></a>8.1.Â Overview</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL provides primitives to run external Unix programs,
+      to select and connect Lisp streams to their input and output
+      sources, to (optionally) wait for their completion and to check
+      their execution and exit status.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">All of the global symbols described below are exported
+      from the CCL package.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This implementation is modeled on - and uses some code
+      from - similar facilities in CMUCL.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Subprocess-Examples"></a>8.2.Â Examples</h2>
+              </div>
+            </div>
+          </div>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+;;; Capture the output of the "uname" program in a lisp string-stream
+;;; and return the generated string (which will contain a trailing
+;;; newline.)
+? (with-output-to-string (stream)
+    (run-program "uname" '("-r") :output stream))
+;;; Write a string to *STANDARD-OUTPUT*, the hard way.
+? (run-program "cat" () :input (make-string-input-stream "hello") :output t)
+;;; Find out that "ls" doesn't expand wildcards.
+? (run-program "ls" '("*.lisp") :output t)
+;;; Let the shell expand wildcards.
+? (run-program "sh" '("-c" "ls *.lisp") :output t)
+</pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">These last examples will only produce output if Clozure CL's
+      current directory contains .lisp files, of course.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Limitations-and-known-bugs"></a>8.3.Â Limitations and known bugs</h2>
+              </div>
+            </div>
+          </div>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>Clozure CL and the external process may get
+        confused about who owns which streams when input, output, or
+        error are specified as T and wait is specified as
+        NIL.</p>
+              </li>
+              <li>
+                <p>External processes that need to talk to a
+        terminal device may not work properly; the environment (SLIME,
+        ILISP) under which Clozure CL is run can affect
+        this.</p>
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="External-Program-Dictionary"></a>8.4.Â External-Program Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_run-program"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>run-program</strong></span>
+	    program args <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> (wait t) pty sharing input
+	    if-input-does-not-exist output (if-output-exists :error) (error
+	    :output) (if-error-exists :error) status-hook
+	    external-format</code>
+            </div>
+            <div class="refentrytitle">Invokes an external program as an OS subprocess
+	    of lisp.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id370820"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">program</span></i>---A string or pathname which denotes an executable file.
+		  The PATH environment variable is used to find programs whose
+		  name doesn't contain a directory component.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">args</span></i>---A list of simple-strings</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">wait</span></i>---Indicates whether or not run-program should wait for
+		  the EXTERNAL-PROCESS to complete or should return
+		  immediately.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">pty</span></i>---This option is accepted but currently ignored;
+		  it's intended to make it easier to run external programs
+		  that need to interact with a terminal device.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">sharing</span></i>---Sets a specific sharing mode
+                  (see <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#Stream-SHARING"><code class="literal">:SHARING</code></a>) for any streams created
+                  within RUN-PROGRAM when INPUT, OUTPUT or ERROR are requested
+                  to be a :STREAM.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">input</span></i>---Selects the input source used by the EXTERNAL-PROCESS.
+		  May be any of the following:<div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist"><ul type="disc"><li><p>NIL Specifies that a null input stream (e.g.,
+		      /dev/null) should be used.</p></li><li><p>T Specifies that the EXTERNAL-PROCESS should use
+		      the input source with which Clozure CL was invoked.</p></li><li><p>A string or pathname. Specifies that the
+		      EXTERNAL-PROCESS should receive its input from the named
+		      existing file.</p></li><li><p>:STREAM Creates a Lisp stream opened for character
+		      output. Any data written to this stream (accessible as
+		      the EXTERNAL-PROCESS-INPUT-STREAM of the
+		      EXTERNAL-PROCESS object) appears as input to the
+		      external process.</p></li><li><p>A stream. Specifies that the lisp stream should
+		      provide input to the EXTERNAL-PROCESS.</p></li></ul></div></p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">if-input-does-not-exist</span></i>---If the input argument specifies the name of an
+		  existing file, this argument is used as the
+		  if-does-not-exist argument to OPEN when that file is opened.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">output</span></i>---Specifies where standard output from the external
+		  process should be sent. Analogous to input above.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">if-output-exists</span></i>---If output is specified as a string or pathname, this
+		  argument is used as the if-exists argument to OPEN when that
+		  file is opened.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">error</span></i>---Specifies where error output from the external process
+		  should be sent. In addition to the values allowed for
+		  output, the keyword :OUTPUT can be used to indicate that
+		  error output should be sent where standard output goes.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">if-error-exists</span></i>---Analogous to if-output-exists.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">status-hook</span></i>---A user-defined function of one argument (the
+		  EXTERNAL-PROCESS structure.) This function is called
+		  whenever Clozure CL detects a change in the status of the
+		  EXTERNAL-PROCESS.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">external-format</span></i>---
+		    The external format (see <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#External-Formats" title="4.3.2.Â External Formats">SectionÂ 4.3.2, âExternal Formatsâ</a>) for all of the
+		    streams (input, output, and error) used to
+		    communicate with the external process.
+		  </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id397623"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Runs the specified program in an external (Unix) process,
+	    returning an object of type EXTERNAL-PROCESS if successful.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_signal-external-process"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>signal-external-process</strong></span>
+	    proc signal-number</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id397682"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">proc</span></i>---An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">signal</span></i>---A small integer.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id378604"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Sends the specified "signal" to the specified
+	    external process. (Typically, it would only be useful to call
+	    this function if the EXTERNAL-PROCESS was created with :WAIT
+	    NIL. ) Returns T if successful; signals an error otherwise.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_external-process-id"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>external-process-id</strong></span>
+	    proc</code>
+            </div>
+            <div class="refentrytitle">Returns the "process ID" of an OS subprocess,
+	    a positive integer which identifies it.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id378665"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">proc</span></i>---An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id360188"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the <span class="emphasis"><em>process id</em></span> assigned to
+	    the external process by the operating system. This is typically
+	    a positive, 16-bit number.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_external-process-input-stream"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>external-process-input-stream</strong></span>
+	    proc</code>
+            </div>
+            <div class="refentrytitle">Returns the lisp stream which is used to write
+	    input to a given OS subprocess, if it has one.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id360252"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">proc</span></i>---An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id360278"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the stream created when the input argument to
+	    run-program is specified as :STREAM.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_external-process-output-stream"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>external-process-output-stream</strong></span>
+	    proc</code>
+            </div>
+            <div class="refentrytitle">Returns the lisp stream which is used to read
+	    output from an OS subprocess, if there is one.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id389024"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">proc</span></i>---An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id389050"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the stream created when the output argument to
+	    run-program is specified as :STREAM.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_external-process-error-stream"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>external-process-error-stream</strong></span>
+	    proc</code>
+            </div>
+            <div class="refentrytitle">Returns the stream which is used to read
+	    "error" output from a given OS subprocess, if it has
+	    one.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id407046"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">proc</span></i>---An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id407072"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the stream created when the error argument to
+	    run-program is specified as :STREAM.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_external-process-status"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>external-process-status</strong></span>
+	    proc</code>
+            </div>
+            <div class="refentrytitle">Returns information about whether an OS
+	    subprocess is running; or, if not, why not; and what its
+	    result code was if it completed.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id373724"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">proc</span></i>---An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id373750"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns, as multiple values, a keyword denoting the status
+	    of the external process (one of :running, :stopped, :signaled, or
+	    :exited), and the exit code or terminating signal if the first
+	    value is other than :running.</p>
+              </div>
+            </div>
+          </p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Streams"></a>ChapterÂ 9.Â Streams</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#CCL-Stream-Extensions">9.1. Stream Extensions</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#id367600">9.1.1. Stream External Encoding</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Additional-Open-Keywords">9.1.2. Additional keywords for OPEN and MAKE-SOCKET</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Basic-Versus-Fundamental-Streams">9.1.3. Basic Versus Fundamental Streams</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Stream-Timeouts-And-Deadlines">9.1.4. Stream Timeouts and Deadlines</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Open-File-Streams">9.1.5. Open File Streams</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Creating-Your-Own-Stream-Classes-with-Gray-Streams">9.2. Creating Your Own Stream Classes with Gray Streams</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Streams-Overview">9.2.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Extending-READ-SEQUENCE-and-WRITE-SEQUENCE">9.2.2. Extending READ-SEQUENCE and WRITE-SEQUENCE</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Multibyte-I-O">9.2.3. Multibyte I/O</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Gray-Streams-Dictionary">9.2.4. Gray Streams Dictionary</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="CCL-Stream-Extensions"></a>9.1.Â Stream Extensions</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="id367600"></a>9.1.1.Â Stream External Encoding</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL streams have an external-encoding attribute that
+    may be read using
+    <span class="function"><strong>STREAM-EXTERNAL-ENCODING</strong></span> and set using <span class="function"><strong>(SETF
+    STREAM-EXTERNAL-ENCODING)</strong></span>.
+    </p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Additional-Open-Keywords"></a>9.1.2.Â Additional keywords for OPEN and MAKE-SOCKET</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"><span class="function"><strong>OPEN</strong></span> and
+      <span class="function"><strong>MAKE-SOCKET</strong></span> have each been extended to take
+      the additional keyword arguments: <code class="literal">:CLASS</code>,
+      <code class="literal">:SHARING</code>, and
+      <code class="literal">:BASIC</code>.</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+              <dl>
+                <dt>
+                  <span class="term">
+                    <code class="literal">:CLASS</code>
+                  </span>
+                </dt>
+                <dd>
+                  <p>A symbol that names the desired class of the stream.
+	  The specified class must inherit from
+	  <code class="literal">FILE-STREAM</code> for
+	  <span class="function"><strong>OPEN</strong></span>.</p>
+                </dd>
+                <dt>
+                  <a id="Stream-SHARING"></a>
+                  <span class="term">
+                    <code class="literal">:SHARING</code>
+                  </span>
+                </dt>
+                <dd>
+                  <p>Specifies how a stream can be used by multiple
+	  threads.  The possible values are:
+	  <code class="literal">:PRIVATE</code>, <code class="literal">:LOCK</code> and
+	  <code class="literal">:EXTERNAL</code>. <code class="literal">:PRIVATE</code> is
+	  the default.  <code class="literal">NIL</code> is also accepted as a
+	  synonym for <code class="literal">:EXTERNAL</code>.</p>
+                  <div class="variablelist">
+                    <dl>
+                      <dt>
+                        <span class="term">
+                          <code class="literal">:PRIVATE</code>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>Specifies that the stream can only be accessed
+		by the thread that created it.  This is the default.
+		(There was some discussion on openmcl-devel about the
+		idea of "transferring ownership" of a stream; this has
+		not yet been implemented.)  Attempts to do I/O on a
+		stream with :PRIVATE sharing from a thread other than
+		the stream's owner yield an error.</p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <code class="literal">:LOCK</code>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>Specifies that all access to the stream require
+		the calling thread to obtain a lock. There are
+		separate "read" and "write" locks for IO streams.
+		This makes it possible for instance, for one thread to
+		read from such a stream while another thread writes to
+		it.  (see also <a class="xref" href="#f_make-read-write-lock" title="Function MAKE-READ-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-read-write-lock</b></a>
+		<a class="xref" href="#m_with-read-lock" title="Macro WITH-READ-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-read-lock</b></a> <a class="xref" href="#m_with-write-lock" title="Macro WITH-WRITE-LOCK"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">with-write-lock</b></a>)</p>
+                      </dd>
+                      <dt>
+                        <span class="term">
+                          <code class="literal">:EXTERNAL</code>
+                        </span>
+                      </dt>
+                      <dd>
+                        <p>Specifies that I/O primitives enforce no access
+		protocol.  This may be appropriate for some types of
+		application which can control stream access via
+		application-level protocols.  Note that since even the
+		act of reading from a stream changes its internal
+		state (and simultaneous access from multiple threads
+		can therefore lead to corruption of that state), some
+		care must be taken in the design of such protocols.</p>
+                      </dd>
+                    </dl>
+                  </div>
+                </dd>
+                <dt>
+                  <span class="term">
+                    <code class="literal">:BASIC</code>
+                  </span>
+                </dt>
+                <dd>
+                  <p>A boolean that indicates whether or not the stream is
+	  a Gray stream, i.e. whether or not the stream is an instance
+	  of <code class="literal">FUNDAMENTAL-STREAM</code> or
+	  <code class="literal">CCL::BASIC-STREAM</code>(see <a class="xref" href="#Basic-Versus-Fundamental-Streams" title="9.1.3.Â Basic Versus Fundamental Streams">SectionÂ 9.1.3, âBasic Versus Fundamental Streamsâ</a>).  Defaults to
+	  <code class="literal">T</code>.</p>
+                </dd>
+              </dl>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Basic-Versus-Fundamental-Streams"></a>9.1.3.Â Basic Versus Fundamental Streams</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Gray streams (see <a class="xref" href="#Creating-Your-Own-Stream-Classes-with-Gray-Streams" title="9.2.Â Creating Your Own Stream Classes with Gray Streams">SectionÂ 9.2, âCreating Your Own Stream Classes with Gray Streamsâ</a>)
+      all inherit from <code class="literal">FUNDAMENTAL-STREAM</code> whereas
+      basic streams inherit from <code class="literal">CCL::BASIC-STREAM</code>.
+      The tradeoff between FUNDAMENTAL and BASIC streams is entirely
+      between flexibility and performance, potential or actual.  I/O
+      primitives can recognize BASIC-STREAMs and exploit knowledge of
+      implementation details. FUNDAMENTAL stream classes can be
+      subclassed and extended in a standard way (the Gray streams
+      protocol).</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">For existing stream classes (FILE-STREAMs, SOCKETs, and
+      the internal CCL::FD-STREAM classes used to implement file
+      streams and sockets), a lot of code can be shared between the
+      FUNDAMENTAL and BASIC implementations.  The biggest difference
+      should be that that code can be reached from I/O primitives like
+      READ-CHAR without going through some steps that're there to
+      support generality and extensibility, and skipping those steps
+      when that support isn't needed can improve I/O performance.
+      </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The Gray stream method
+      <span class="function"><strong>STREAM-READ-CHAR</strong></span> should work on appropriate
+      <code class="literal">BASIC-STREAM</code>s.  (There may still be cases
+      where such methods are undefined; such cases should be
+      considered bugs.)  It is not guaranteed that Gray stream methods
+      would ever be called by I/O primitives to read a character from
+      a <code class="literal">BASIC-STREAM</code>, though there are still cases
+      where this happens.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A simple loop reading 2M characters from a text file runs
+      about 10X faster when the file is opened the new defaults
+      <code class="literal">(:SHARING :PRIVATE :BASIC T)</code> than it had
+      before these changes were made.  That sounds good, until one
+      realizes that the "equivalent" C loop can be about 10X faster
+      still ...</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Stream-Timeouts-And-Deadlines"></a>9.1.4.Â Stream Timeouts and Deadlines</h3>
+                </div>
+              </div>
+            </div>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="id414448" class="indexterm"></a>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="id414458" class="indexterm"></a>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="id414468" class="indexterm"></a>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="id414477" class="indexterm"></a>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="id414487" class="indexterm"></a>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="id412866" class="indexterm"></a>
+            <p xmlns="http://www.w3.org/1999/xhtml">A stream that is associated with a file descriptor has
+        attributes and accessors:
+        <span class="function"><strong>STREAM-INPUT-TIMEOUT</strong></span>,
+        <span class="function"><strong>STREAM-OUTPUT-TIMEOUT</strong></span>, and
+        <span class="function"><strong>STREAM-DEADLINE</strong></span>.  All three accessors have
+        corresponding <span class="function"><strong>SETF</strong></span> methods.
+        <span class="function"><strong>STREAM-INPUT-TIMEOUT</strong></span> and
+        <span class="function"><strong>STREAM-OUTPUT-TIMEOUT</strong></span> are specified in
+        seconds and can be any positive real number less than one million.
+        When a timeout is set and the corresponding I/O operation takes
+        longer than the specified interval, an error is signalled.  The
+        error is <code class="literal">INPUT-TIMEOUT</code> for input and
+        <code class="literal">OUTPUT-TIMEOUT</code> for output.
+        <code class="literal">STREAM-DEADLINE</code> specifies an absolute time in
+        internal-time-units.  If an I/O operation on the stream does not
+        complete before the deadline then a
+        <code class="literal">COMMUNICATION-DEADLINE-EXPIRED</code> error is
+        signalled.  A deadline takes precedence over any
+        input/output timeouts that may be set.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Open-File-Streams"></a>9.1.5.Â Open File Streams</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Historically, Clozure CL and MCL maintained a list of open
+        file streams in the value of
+        <code class="literal">CCL:*OPEN-FILE-STREAMS*</code>.  This functionality
+        has been replaced with the thread-safe function:
+        <code class="literal">CCL:OPEN-FILE-STREAMS</code> and its two helper
+        functions: <code class="literal">CCL:NOTE-OPEN-FILE-STREAM</code> and
+        <code class="literal">CCL:REMOVE-OPEN-FILE-STREAM</code>.  Maintaining
+        this list helps to ensure that streams get closed in an orderly
+        manner when the lisp exits.</p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_open-file-streams"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code>
+	        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>open-file-streams</strong></span>
+	        =&gt; stream-list
+	      </code>
+              </div>
+              <div class="refentrytitle">Returns the list of file streams that are currently open.</div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412016"></a>
+                  <div class="header">Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stream-list</span></i>---A list of open file streams.  This is a copy of
+		          an internal list so it may be destructively
+		          modified without ill effect.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412043"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Returns a list of open file streams.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412055"></a>
+                  <div class="header">See Also:</div>
+                  <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_note-open-file-stream" title="Function NOTE-OPEN-FILE-STREAM"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">note-open-file-stream</b></a>, <a class="xref" href="#f_remove-open-file-stream" title="Function REMOVE-OPEN-FILE-STREAM"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">remove-open-file-stream</b></a></span>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_note-open-file-stream"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code>
+	        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>note-open-file-stream</strong></span>
+	        file-stream
+	      </code>
+              </div>
+              <div class="refentrytitle">Adds a file stream to the internal list of open
+	        file streams that is returned by
+	        note-open-file-stream.</div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412136"></a>
+                  <div class="header">Arguments:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">file-stream</span></i>---A file stream.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412162"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Adds a file stream to the internal list of open
+	        file streams that is returned by
+	        <span class="function"><strong>open-file-streams</strong></span>.  This function is
+	        thread-safe.  It will usually only be called from custom
+	        stream code when a file-stream is created.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412181"></a>
+                  <div class="header">See Also:</div>
+                  <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_open-file-streams" title="Function OPEN-FILE-STREAMS"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">open-file-streams</b></a>, <a class="xref" href="#f_remove-open-file-stream" title="Function REMOVE-OPEN-FILE-STREAM"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">remove-open-file-stream</b></a></span>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_remove-open-file-stream"></a>
+                <strong>[Function]</strong>
+                <br></br>
+                <code>
+	        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>remove-open-file-stream</strong></span>
+	        file-stream
+	      </code>
+              </div>
+              <div class="refentrytitle">Removes file stream from the internal list of open
+	        file streams that is returned by
+	        open-file-streams.</div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412262"></a>
+                  <div class="header">Arguments:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">file-stream</span></i>---A file stream.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412288"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Remove file stream from the internal list of open file
+	        streams that is returned by
+	        <span class="function"><strong>open-file-streams</strong></span>.  This function is
+	        thread-safe.  It will usually only be called from custom
+	        stream code when a file-stream is closed.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id412307"></a>
+                  <div class="header">See Also:</div>
+                  <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist"><a class="xref" href="#f_open-file-streams" title="Function OPEN-FILE-STREAMS"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">open-file-streams</b></a>, <a class="xref" href="#f_note-open-file-stream" title="Function NOTE-OPEN-FILE-STREAM"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">note-open-file-stream</b></a></span>
+                </div>
+              </div>
+            </p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Creating-Your-Own-Stream-Classes-with-Gray-Streams"></a>9.2.Â Creating Your Own Stream Classes with Gray Streams</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Streams-Overview"></a>9.2.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">This sect1 is still being written and revised, because
+        it is woefully incomplete.  The dictionary section currently
+        only lists a couple functions.  Caveat lector.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Gray streams are an extension to Common Lisp.  They were
+        proposed for standardization by David Gray (the astute reader
+        now understands their name) quite some years ago, but not
+        accepted, because they had not been tried sufficiently to find
+        conceptual problems with them.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">They have since been implemented by quite a few modern
+        Lisp implementations.  However, they do indeed have some
+        inadequacies, and each implementation has addressed these in
+        different ways.  The situation today is that it's difficult to
+        even find out how to get started using Gray streams.  This is
+        why standards are important.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Here's a list of some classes which you might wish for
+        your new stream class to inherit from:</p>
+            <table xmlns="http://www.w3.org/1999/xhtml" class="simplelist" border="0" summary="Simple list">
+              <tr>
+                <td>fundamental-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-input-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-output-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-character-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-binary-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-character-input-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-character-output-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-binary-input-stream</td>
+              </tr>
+              <tr>
+                <td>fundamental-binary-output-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-input-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-output-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-io-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-character-input-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-character-output-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-character-io-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-binary-input-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-binary-output-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>ccl::buffered-binary-io-stream-mixin</td>
+              </tr>
+              <tr>
+                <td>file-stream</td>
+              </tr>
+              <tr>
+                <td>file-input-stream</td>
+              </tr>
+              <tr>
+                <td>file-output-stream</td>
+              </tr>
+              <tr>
+                <td>file-io-stream</td>
+              </tr>
+              <tr>
+                <td>file-character-input-stream</td>
+              </tr>
+              <tr>
+                <td>file-character-output-stream</td>
+              </tr>
+              <tr>
+                <td>file-character-io-stream</td>
+              </tr>
+              <tr>
+                <td>file-binary-input-stream</td>
+              </tr>
+              <tr>
+                <td>file-binary-output-stream</td>
+              </tr>
+              <tr>
+                <td>file-binary-io-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-input-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-output-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-io-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-character-input-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-character-output-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-character-io-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-binary-input-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-binary-output-stream</td>
+              </tr>
+              <tr>
+                <td>ccl::fd-binary-io-stream</td>
+              </tr>
+            </table>
+            <p xmlns="http://www.w3.org/1999/xhtml">All of these are defined in ccl/level-1/l1-streams.lisp,
+        except for the ccl:file-* ones, which are in
+        ccl/level-1/l1-sysio.lisp.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">According to the original Gray streams proposal, you
+        should inherit from the most specific of the fundamental-*
+        classes which applies.  Using Clozure CL, though, if you want
+        buffering for better performance, which, unless you know of some
+        reason you wouldn't, you do, you should instead inherit from the
+        appropriate ccl::buffered-* class The buffering you get this way
+        is exactly the same as the buffering which is used on ordinary,
+        non-Gray streams, and force-output will work properly on
+        it.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Notice that -mixin suffix in the names of all the
+        ccl::buffered-* classes?  The suffix means that this class is
+        not "complete" by itself; you still need to inherit from a
+        fundamental-* stream, even if you also inherit from a *-mixin
+        stream.  You might consider making your own class like this.
+        ....  Except that they do inherit from the fundamental-*
+        streams, that's weird.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If you want to be able to create an instance of your class
+        with the :class argument to (open) and (with-open-file), you
+        should make it inherit from one of the file-* classes.  If you
+        do this, it's not necessary to inherit from any of the other
+        classes (though it won't hurt anything), since the file-*
+        classes already do.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When you inherit from the file-* classes, you can use
+        (call-next-method) in any of your methods to get the standard
+        behavior.  This is especially useful if you want to create a
+        class which performs some simple filtering operation, such as
+        changing everything to uppercase or to a different character
+        encoding.  If you do this, you will definitely need to
+        specialize ccl::select-stream-class.  Your method on
+        ccl::stream-select-class should accept an instance of the class,
+        but pay no attention to its contents, and return a symbol naming
+        the class to actually be instantiated.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If you need to make your functionality generic across all
+        the different types of stream, probably the best way to
+        implement it is to make it a mixin, define classes with all the
+        variants of input, output, io, character, and binary, which
+        inherit both from your mixin and from the appropriate other
+        class, then define a method on ccl::select-stream-class which
+        chooses from among those classes.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that some of these classes are internal to the CLL
+        package.  If you try to inherit from those ones without the
+        ccl:: prefix, you'll get an error which may confuse you, calling
+        them "forward-referenced classes".  That just means you used the
+        wrong symbol, so add the prefix.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Here's a list of some generic functions which you might
+        wish to specialize for your new stream class, and which ought to
+        be documented at some point.</p>
+            <table xmlns="http://www.w3.org/1999/xhtml" class="simplelist" border="0" summary="Simple list">
+              <tr>
+                <td>stream-direction stream =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-device stream direction =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-length stream <em class="varname">&amp;optional</em> new =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-position stream <em class="varname">&amp;optional</em> new =&gt;</td>
+              </tr>
+              <tr>
+                <td>streamp stream =&gt; boolean</td>
+              </tr>
+              <tr>
+                <td>stream-write-char output-stream char =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-write-entire-string output-stream string =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-read-char input-stream =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-unread-char input-stream char =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-force-output output-stream =&gt; nil</td>
+              </tr>
+              <tr>
+                <td>stream-maybe-force-output output-stream =&gt; nil</td>
+              </tr>
+              <tr>
+                <td>stream-finish-output output-stream =&gt; nil</td>
+              </tr>
+              <tr>
+                <td>stream-clear-output output-stream =&gt; nil</td>
+              </tr>
+              <tr>
+                <td>close stream <em class="varname">&amp;key</em> abort =&gt; boolean</td>
+              </tr>
+              <tr>
+                <td>stream-fresh-line stream =&gt; t</td>
+              </tr>
+              <tr>
+                <td>stream-line-length stream =&gt; length</td>
+              </tr>
+              <tr>
+                <td>interactive-stream-p stream =&gt; boolean</td>
+              </tr>
+              <tr>
+                <td>stream-clear-input input-stream =&gt; nil</td>
+              </tr>
+              <tr>
+                <td>stream-listen input-stream =&gt; boolean</td>
+              </tr>
+              <tr>
+                <td>stream-filename stream =&gt; string</td>
+              </tr>
+              <tr>
+                <td>ccl::select-stream-class instance in-p out-p char-p =&gt;
+	      class</td>
+              </tr>
+            </table>
+            <p xmlns="http://www.w3.org/1999/xhtml">The following functions are standard parts of Common Lisp, but
+        behave in special ways with regard to Gray streams.</p>
+            <table xmlns="http://www.w3.org/1999/xhtml" class="simplelist" border="0" summary="Simple list">
+              <tr>
+                <td>open-stream-p stream =&gt; generalized-boolean</td>
+              </tr>
+              <tr>
+                <td>input-stream-p stream =&gt; generalized-boolean</td>
+              </tr>
+              <tr>
+                <td>output-stream-p stream =&gt; generalized-boolean</td>
+              </tr>
+              <tr>
+                <td>stream-element-type stream =&gt;</td>
+              </tr>
+              <tr>
+                <td>stream-error-stream =&gt;</td>
+              </tr>
+              <tr>
+                <td>open</td>
+              </tr>
+              <tr>
+                <td>close</td>
+              </tr>
+              <tr>
+                <td>with-open-file</td>
+              </tr>
+            </table>
+            <p xmlns="http://www.w3.org/1999/xhtml">Specifically, (open) and (with-open-file) accept a new
+        keyword argument, :class, which may be a symbol naming a class;
+        the class itself; or an instance of it.  The class so given must
+        be a subtype of 'stream, and an instance of it with no
+        particular contents will be passed to ccl::select-stream-class
+        to determine what class to actually instantiate.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The following are standard, and do not behave specially
+        with regard to Gray streams, but probably should.</p>
+            <table xmlns="http://www.w3.org/1999/xhtml" class="simplelist" border="0" summary="Simple list">
+              <tr>
+                <td>stream-external-format</td>
+              </tr>
+            </table>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Extending-READ-SEQUENCE-and-WRITE-SEQUENCE"></a>9.2.2.Â Extending READ-SEQUENCE and WRITE-SEQUENCE</h3>
+                </div>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="extending-read-write-overview"></a>9.2.2.1.Â Overview</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">The "Gray Streams" API is based on an informal proposal that was
+	      made before ANSI CL adopted the READ-SEQUENCE and WRITE-SEQUENCE
+	      functions; as such, there is no "standard" way for the author of a Gray
+	      stream class to improve the performance of these functions by exploiting
+	      knowledge of the stream's internals (e.g., the buffering mechanism it
+	      uses.)</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">In the absence of any such knowledge, READ-SEQUENCE and
+	      WRITE-SEQUENCE are effectively just convenient shorthand for a
+	      loop which calls READ-CHAR/READ-BYTE/WRITE-CHAR/WRITE-BYTE as
+	      appropriate. The mechanism described below allows subclasses
+	      of FUNDAMENTAL-STREAM to define more specialized (and
+	      presumably more efficient) behavior.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Notes"></a>9.2.2.2.Â Notes</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">READ-SEQUENCE and WRITE-SEQUENCE do a certain amount of
+	      sanity-checking and normalization of their arguments before
+	      dispatching to one of the methods above. If an individual
+	      method can't do anything particularly clever, CALL-NEXT-METHOD
+	      can be used to handle the general case.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Example"></a>9.2.2.3.Â Example</h4>
+                  </div>
+                </div>
+              </div>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defclass my-string-input-stream (fundamental-character-input-stream)
+  ((string :initarg :string :accessor my-string-input-stream-string)
+   (index :initform 0 :accessor my-string-input-stream-index)
+   (length)))
+
+(defmethod stream-read-vector ((stream my-string-input-stream) vector start end)
+  (if (not (typep vector 'simple-base-string))
+      (call-next-method)
+      (with-slots (string index length)
+	      (do* ((outpos start (1+ outpos)))
+               ((or (= outpos end)
+                    (= index length))
+                outpos))
+        (setf (schar vector outpos)
+              (schar string index))
+        (incf index)))))
+	    </pre>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Multibyte-I-O"></a>9.2.3.Â Multibyte I/O</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">All heap-allocated objects in Clozure CL that cannot contain
+        pointers to lisp objects are represented as
+        <span class="emphasis"><em>ivectors</em></span>. Clozure CL provides low-level
+        functions, and , to efficiently transfer data between buffered
+        streams and ivectors. There's some overlap in functionality
+        between the functions described here and the ANSI CL
+        READ-SEQUENCE and WRITE-SEQUENCE functions.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">As used here, the term "octet" means roughly the same
+        thing as the term "8-bit byte". The functions described below
+        transfer a specified sequence of octets between a buffered
+        stream and an ivector, and don't really concern themselves with
+        higher-level issues (like whether that octet sequence is within
+        bounds or how it relates to the logical contents of the
+        ivector.) For these reasons, these functions are generally less
+        safe and more flexible than their ANSI counterparts.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Gray-Streams-Dictionary"></a>9.2.4.Â Gray Streams Dictionary</h3>
+                </div>
+              </div>
+            </div>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_stream-read-list"></a>
+                <strong>[Generic Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>stream-read-list</strong></span>
+	        stream list count</code>
+              </div>
+              <div class="refentrytitle"></div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422390"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stream</span></i>---a stream, presumably a fundamental-input-stream.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">list</span></i>---a list. When a STREAM-READ-LIST method is called by
+		          READ-SEQUENCE, this argument is guaranteed to be a proper
+		          list.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">count</span></i>---a non-negative integer. When a STREAM-READ-LIST method
+		          is called by READ-SEQUENCE, this argument is guaranteed not
+		          to be greater than the length of the list.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422448"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Should try to read up to count elements from stream into the
+	        list list, returning the number of elements actually read (which
+	        may be less than count in case of a premature end-of-file.)</p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_stream-write-list"></a>
+                <strong>[Generic Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>stream-write-list</strong></span>
+	        stream list count</code>
+              </div>
+              <div class="refentrytitle"></div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422507"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stream</span></i>---a stream, presumably a fundamental-output-stream.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">list</span></i>---a list. When a STREAM-WRITE-LIST method is called by
+		          WRITE-SEQUENCE, this argument is guaranteed to be a proper
+		          list.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">count</span></i>---a non-negative integer. When a STREAM-WRITE-LIST
+		          method is called by WRITE-SEQUENCE, this argument is
+		          guaranteed not to be greater than the length of the list.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422565"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">should try to write the first count elements of list to
+	        stream. The return value of this method is ignored.</p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_stream-read-vector"></a>
+                <strong>[Generic Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>stream-read-vector</strong></span>
+	        stream vector start end</code>
+              </div>
+              <div class="refentrytitle"></div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422624"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stream</span></i>---a stream, presumably a fundamental-input-stream</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">vector</span></i>---a vector. When a STREAM-READ-VECTOR method is called
+		          by READ-SEQUENCE, this argument is guaranteed to be a simple
+		          one-dimensional array.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">start</span></i>---a non-negative integer. When a STREAM-READ-VECTOR
+		          method is called by READ-SEQUENCE, this argument is
+		          guaranteed to be no greater than end and not greater than
+		          the length of vector.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">end</span></i>---a non-negative integer. When a STREAM-READ-VECTOR
+		          method is called by READ-SEQUENCE, this argument is
+		          guaranteed to be no less than end and not greater than the
+		          length of vector.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422699"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">should try to read successive elements from stream into
+	        vector, starting at element start (inclusive) and continuing
+	        through element end (exclusive.) Should return the index of the
+	        vector element beyond the last one stored into, which may be less
+	        than end in case of premature end-of-file.</p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_stream-write-vector"></a>
+                <strong>[Generic Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>stream-write-vector</strong></span>
+	        stream vector start end</code>
+              </div>
+              <div class="refentrytitle"></div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422759"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stream</span></i>---a stream, presumably a fundamental-output-stream</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">vector</span></i>---a vector. When a STREAM-WRITE-VECTOR method is called
+		          by WRITE-SEQUENCE, this argument is guaranteed to be a
+		          simple one-dimensional array.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">start</span></i>---a non-negative integer. When a STREAM-WRITE-VECTOR
+		          method is called by WRITE-SEQUENCE, this argument is
+		          guaranteed to be no greater than end and not greater than
+		          the length of vector.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">end</span></i>---a non-negative integer. When a STREAM-WRITE-VECTOR
+		          method is called by WRITE-SEQUENCE, this argument is
+		          guaranteed to be no less than end and not greater than the
+		          length of vector.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422834"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">should try to write successive elements of vector to stream,
+	        starting at element start (inclusive) and continuing through
+	        element end (exclusive.)</p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_stream-device"></a>
+                <strong>[Generic Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>ccl::stream-device</strong></span>
+	        s direction</code>
+              </div>
+              <div class="refentrytitle">Returns the OS file descriptor associated with a
+	        given lisp stream.</div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422894"></a>
+                  <div class="header">Method Signatures:</div>
+                  <div class="synopsis"><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>ccl::stream-device</strong></span> <i>
+	        (s stream) direction =&gt; fd</i></div>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422912"></a>
+                  <div class="header">Arguments and Values:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">s</span></i>---a stream.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">direction</span></i>---either :INPUT or :OUTPUT.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">fd</span></i>---a file descriptor, which is a non-negative integer
+		          used by the OS to refer to an open file, socket, or similar
+		          I/O connection.  NIL if there is no file descriptor associated
+		          with <em xmlns="http://www.w3.org/1999/xhtml" class="varname">s</em> in the direction given by
+		          <em xmlns="http://www.w3.org/1999/xhtml" class="varname">direction</em>.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id422978"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Returns the file descriptor associated with
+	        <em class="varname">s</em> in the direction given by
+	        <em class="varname">direction</em>.  It is necessary to specify
+	        <em class="varname">direction</em> because the input and output
+	        file descriptors may be different; the most common case is when
+	        one of them has been redirected by the Unix shell.</p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_stream-read-ivector"></a>
+                <strong>[Generic Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>stream-read-ivector</strong></span>
+	        stream ivector start-octet max-octets</code>
+              </div>
+              <div class="refentrytitle"></div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id423047"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Reads up to max-octets octets from stream into ivector,
+	        storing them at start-octet. Returns the number of octets actually
+	        read.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id423059"></a>
+                  <div class="header">Arguments:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stream</span></i>---An input stream. The method defined on
+		          BUFFERED-INPUT-STREAMs requires that the size in octets of
+		          an instance of the stream's element type is 1.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ivector</span></i>---Any ivector.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">start-octet</span></i>---A non-negative integer.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">max-octets</span></i>---A non-negative integer. The return value may be less
+		          than the value of this parameter if EOF was encountered.</p>
+                </div>
+              </div>
+            </p>
+            <p>
+              <div class="refentrytitle">
+                <a id="f_stream-write-ivector"></a>
+                <strong>[Generic Function]</strong>
+                <br></br>
+                <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>stream-write-ivector stream</strong></span>
+	        ivector start-octet max-octets</code>
+              </div>
+              <div class="refentrytitle"></div>
+            </p>
+            <p>
+              <div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id423179"></a>
+                  <div class="header">Description:</div>
+                  <p xmlns="http://www.w3.org/1999/xhtml">Writes max-octets octets to stream from ivector, starting at
+	        start-octet. Returns max-octets.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id423191"></a>
+                  <div class="header">Arguments:</div>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">stream</span></i>---An input stream. The method defined on
+		          BUFFERED-OUTPUT-STREAMs requires that the size in octets of
+		          an instance of the stream's element type is 1.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ivector</span></i>---Any ivector</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">start-octet</span></i>---A non-negative integer.</p>
+                  <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">max-octet</span></i>---A non-negative integer.</p>
+                </div>
+                <div class="refsect1" lang="en" xml:lang="en">
+                  <a xmlns="http://www.w3.org/1999/xhtml" id="id423263"></a>
+                  <div class="header">Examples:</div>
+                  <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+;;; Write the contents of a (SIMPLE-ARRAY(UNSIGNED-BYTE 16) 3) 
+;;; to a character file stream. Read back the characters.
+(let* ((a (make-array 3 
+                      :element-type '(unsigned-byte 16)
+                      :initial-contents '(26725 27756 28449))))
+  (with-open-file (s "junk"
+                     :element-type 'character
+                     :direction :io
+                     :if-does-not-exist :create
+                     :if-exists :supersede)
+    ;; Write six octets (three elements).
+    (stream-write-ivector s a 0 6)
+    ;; Rewind, then read a line
+    (file-position s 0)
+    (read-line s)))
+
+;;; Write a vector of DOUBLE-FLOATs. Note that (to maintain
+;;; alignment) there are 4 octets of padding before the 0th 
+;;; element of a (VECTOR DOUBLE-FLOAT).
+;;; (Note that (= (- arch::misc-dfloat-offset 
+;;;                  arch::misc-data-offset) 4))
+(defun write-double-float-vector
+    (stream vector &amp;key (start 0) (end (length vector)))
+     (check-type vector (vector double-float))
+     (let* ((start-octet (+ (* start 8) 
+                            (- arch::misc-dfloat-offset
+                               arch::misc-data-offset)))
+	        (num-octets (* 8 (- end start))))
+       (stream-write-ivector stream vector start-octet num-octets)))
+          </pre>
+                </div>
+              </div>
+            </p>
+          </div>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Writing-Portable-Extensions-to-the-Object-System-using-the-MetaObject-Protocol"></a>ChapterÂ 10.Â Writing Portable Extensions to the Object System  using the MetaObject Protocol</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#MOP-Overview">10.1. Overview</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#MOP-Implementation-status">10.2. Implementation status</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Concurrency-issues">10.3. Concurrency issues</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="MOP-Overview"></a>10.1.Â Overview</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL supports a fairly large subset of the
+      semi-standard MetaObject Protocol (MOP) for CLOS, as defined in
+      chapters 5 and 6 of "The Art Of The Metaobject Protocol",
+      (Kiczales et al, MIT Press 1991, ISBN 0-262-61074-4); this
+      specification is also available online at
+      http://www.alu.org/mop/index.html.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="MOP-Implementation-status"></a>10.2.Â Implementation status</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The keyword :openmcl-partial-mop is on *FEATURES* to
+      indicate the presence of this functionality.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">All of the symbols defined in the MOP specification
+      (whether implemented or not) are exported from the "CCL" package
+      and from an "OPENMCL-MOP" package.</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="informaltable">
+            <table border="1">
+              <colgroup>
+                <col align="center" />
+                <col align="center" />
+              </colgroup>
+              <thead>
+                <tr>
+                  <th align="center" valign="top">
+                    <p>construct</p>
+                  </th>
+                  <th align="center" valign="top">
+                    <p>status</p>
+                  </th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>accessor-method-slot-definition</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>add-dependent</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>add-direct-method</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>add-direct-subclass</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>add-method</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-default-initargs</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-direct-default-initargs</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-direct-slots</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-direct-subclasses</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-direct-superclasses</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-finalized-p</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-prototype</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>class-slots</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-applicable-methods</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>-</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-applicable-methods-using-classes</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>-</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-class-precedence-list</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-direct-initargs</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-discriminating-function</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>-</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-effective-method</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-effective-slot-definition</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>compute-slots</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>direct-slot-definition-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>effective-slot-definition-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>ensure-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>ensure-class-using-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>ensure-generic-function-using-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>eql-specializer-object</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>extract-lambda-list</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>extract-specializer-names</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>finalize-inheritance</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>find-method-combination</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>funcallable-standard-instance-access</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>generic-function-argument-precedence-order</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>generic-function-declarations</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>generic-function-lambda-list</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>generic-function-method-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>generic-function-method-combination</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>generic-function-methods</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>generic-function-name</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>intern-eql-specializer</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>make-method-lambda</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>-</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>map-dependents</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>method-function</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>method-generic-function</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>method-lambda-list</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>method-qualifiers</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>method-specializers</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>reader-method-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>remove-dependent</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>remove-direct-method</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>remove-direct-subclass</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>remove-method</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>set-funcallable-instance-function</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>-</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-boundp-using-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-allocation</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-initargs</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-initform</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-initfunction</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-location</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-name</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-readers</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-type</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-definition-writers</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-makunbound-using-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>slot-value-using-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>specializer-direct-generic-functions</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>specializer-direct-methods</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>standard-instance-access</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>update-dependent</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>validate-superclass</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" valign="top">
+                    <p>writer-method-class</p>
+                  </td>
+                  <td align="center" valign="top">
+                    <p>+</p>
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Note that those generic functions whose status is "-" in
+      the table above deal with the internals of generic function
+      dispatch and method invocation (the "Generic Function Invocation
+      Protocol".) Method functions are implemented a bit differently
+      in Clozure CL from what the MOP expects, and it's not yet clear if
+      or how this subprotocol can be well-supported.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Those constructs that are marked as "+" in the table above
+      are nominally implemented as the MOP document specifies
+      (deviations from the specification should be considered bugs;
+      please report them as such.) Note that some CLOS implementations
+      in widespread use (e.g., PCL) implement some things
+      (ENSURE-CLASS-USING-CLASS comes to mind) a bit differently from
+      what the MOP specifies.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Concurrency-issues"></a>10.3.Â Concurrency issues</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The entire CLOS class and generic function hierarchy is
+      effectively a (large, complicated) shared data structure; it's
+      not generally practical for a thread to request exclusive access
+      to all of CLOS, and the effects of volitional modification of
+      the CLOS hierarchy (via class redefinition, CHANGE-CLASS, etc) in
+      a multithreaded environment aren't always tractable.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Native threads exacerbate this problem (in that they
+      increase the opportunities for concurrent modification and
+      access.) The implementation should try to ensure that a thread's
+      view of any subset of the CLOS hierarchy is consistent (to the
+      extent that that's possible) and should try to ensure that
+      incidental modifications of the hierarchy (cache updates, etc.)
+      happen atomically; it's not generally possible for the
+      implementation to guarantee that a thread's view of things is
+      correct and current.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you are loading code and defining classes in the most
+      usual way, which is to say, via the compiler, using only a
+      single thread, these issues are probably not going to affect you
+      much.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If, however, you are making finicky changes to the class
+      hierarchy while you're running multiple threads which manipulate
+      objects related to each other, more care is required.  Before
+      doing such a thing, you should know what you're doing and
+      already be aware of what precautions to take, without being
+      told.  That said, if you do it, you should seriously consider
+      what your application's critical data is, and use locks for
+      critical code sections.</p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Profiling"></a>ChapterÂ 11.Â Profiling</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Profiling-Using the Linux oprofile system-level profiler">11.1. Using the Linux oprofile system-level profiler</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-oprofile-generating-a-lisp-image-for-use-with-oprofile">11.1.1. Generating a lisp image for use with oprofile</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-oprofile-prerequisites">11.1.2. Prerequisites</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-oprofile-generating-elf-symbols-for-lisp-functions">11.1.3. Generating ELF symbols for Lisp functions</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-oprofile-example">11.1.4. Example</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-oprofile-Issues">11.1.5. Issues</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Profiling-Using-Apples-CHUD-metering-tools">11.2. Using Apple's CHUD metering tools</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-CHUD-prerequisites">11.2.1. Prerequisites</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-CHUD-usage-synopsis">11.2.2. Usage synopsis</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-CHUD-profiling-configurations">11.2.3. Profiling "configurations"</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-CHUD-Reference">11.2.4. Reference</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Profiling-CHUD-Acknowledgments">11.2.5. Acknowledgement</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Profiling-Using the Linux oprofile system-level profiler"></a>11.1.Â Using the Linux oprofile system-level profiler</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml"><a class="ulink" href="http://oprofile.sourceforge.net" target="_top"><code class="code">oprofile</code></a> is
+      a system-level profiler that's available for most modern Linux distributions.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Use of oprofile and its companion programs isn't really documented here; what
+      is described is a way of generating symbolic information that enables profiling
+      summaries generated by the <code class="code">opreport</code> program to identify lisp functions
+      meaningfully.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-oprofile-generating-a-lisp-image-for-use-with-oprofile"></a>11.1.1.Â Generating a lisp image for use with oprofile</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Modern Linux uses the 'ELF" (Executable and Linking Format) object file
+	format; the oprofile tools can associate symbolic names with addresses in a
+	memory-mapped file if that file appears to be an ELF object file and if it
+	contains ELF symbol information that describes those memory regions.  So, the
+	general idea is to make a lisp heap image that looks enough like an ELF shared
+	library to fool the <code class="code">oprofile</code> tools (we don't actually load heap
+	images via ELF dynamic linking technology, but we can make it look like we
+	did.)</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-oprofile-prerequisites"></a>11.1.2.Â Prerequisites</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p><code class="code">oprofile</code> itself, which is almost certainly available via
+	    your distribution's package management system if not already
+	    preinstalled.</p>
+                </li>
+                <li>
+                  <p><code class="code">libelf</code>, which provides utilities for reading and writing
+	    ELF files (and is likewise likely preinstalled or readily installable.)</p>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-oprofile-generating-elf-symbols-for-lisp-functions"></a>11.1.3.Â Generating ELF symbols for Lisp functions</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">In order to create a lisp heap image which can be used for
+	<code class="code">oprofile</code>- based profiling, we need to:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>load any code that we want to profile</p>
+                </li>
+                <li>
+                  <p>generate a file that contains ELF symbol information describing the
+	    names and addresses of all lisp functions.</p>
+                  <p>This step involves doing (from within Clozure CL)</p>
+                  <pre class="programlisting">
+? (require "ELF")
+"ELF"
+("ELF")
+
+? (ccl::write-elf-symbols-to-file "home:elf-symbols")
+	    </pre>
+                  <p>The argument to CCL::WRITE-ELF-SYMBOLS-TO-FILE can be any writable
+	    pathname.  The function will do whatever's necessary to nail lisp functions
+	    down in memory (so that they aren't moved by GC), then write an ELF object
+	    file to the indicated pathname.  This typically takes a few seconds.</p>
+                </li>
+                <li>
+                  <p>Generate a lisp heap image in which the ELF symbols generated in the
+	    previous step are prepended.</p>
+                  <p>The function CCL:SAVE-APPLICATION provides a :PREPEND-KERNEL argument,
+	    which is ordinarily used to save a standalone application in which the kernel
+	    and heap image occupy a single file.  :PREPEND-KERNEL doesn't really care what
+	    it's prepending to the image, and we can just as easily ask it to prepend the
+	    ELF symbol file generated in the previous step.</p>
+                  <pre class="programlisting">
+? (save-application "somewhere/image-for-profiling"
+    :prepend-kernel "home:elf-symbols")
+	    </pre>
+                  <p>If you then run</p>
+                  <pre class="programlisting">
+shell&gt; ccl64 somewhare/image-for-profiling
+	    </pre>
+                  <p>any lisp code sampled by oprofile in that image will be identified
+	    "symbolically" by <code class="code">opreport</code>.</p>
+                </li>
+              </ol>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-oprofile-example"></a>11.1.4.Â Example</h3>
+                </div>
+              </div>
+            </div>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+;;; Define some lisp functions that we want to profile and save
+;;; a profiling-enabled image.  In this case, we just want to 
+;;; define the FACTORIAL funcion, to keep things simple.
+? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
+FACT
+? (require "ELF")
+"ELF"
+("ELF")
+? (ccl::write-elf-symbols-to-file "home:elf-symbols")
+"home:elf-symbols"
+? (save-application "home:profiled-ccl" :prepend-kernel "home:elf-symbols")
+
+;;; Setup oprofile with (mostly) default arguments.  This example was
+;;; run on a Fedora 8 system where an uncompressed 'vmlinux' kernel
+;;; image isn't readily available.
+
+;;; Note that use of 'opcontrol' generally requires root access, e.g.,
+;;; 'sudo' or equivalent:
+
+[~] gb@rinpoche&gt; sudo opcontrol --no-vmlinux --setup
+
+;;; Start the profiler
+
+[~] gb@rinpoche&gt; sudo opcontrol --start
+Using 2.6+ OProfile kernel interface.
+Using log file /var/lib/oprofile/samples/oprofiled.log
+Daemon started.
+Profiler running.
+
+;;; Start CCL with the "profiled-ccl" image created above.
+;;; Invoke "(FACT 10000)"
+
+[~] gb@rinpoche&gt; ccl64 profiled-ccl 
+Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk  (LinuxX8664)!
+? (null (fact 10000))
+NIL
+? (quit)
+
+;;; We could stop the profiler (opcontrol --stop) here; instead,
+;;; we simply flush profiling data to disk, where 'opreport' can
+;;; find it.
+
+[~] gb@rinpoche&gt; sudo opcontrol --dump
+
+;;; Ask opreport to show us where we were spending time in the
+;;; 'profiled-ccl' image.
+
+[~] gb@rinpoche&gt; opreport -l profiled-ccl | head
+CPU: Core 2, speed 1596 MHz (estimated)
+Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
+samples  %        symbol name
+6417     65.2466  &lt;Compiled-function.(:INTERNAL.MULTIPLY-UNSIGNED-BIGNUM-AND-1-DIGIT-FIXNUM.MULTIPLY-BIGNUM-AND-FIXNUM).(Non-Global)..0x30004002453F&gt;
+3211     32.6487  &lt;Compiled-function.%MULTIPLY-AND-ADD4.0x300040000AAF&gt;
+17        0.1729  &lt;Compiled-function.%%ONE-ARG-DCODE.0x3000401740AF&gt;
+11        0.1118  &lt;Compiled-function.%UNLOCK-RECURSIVE-LOCK-OBJECT.0x30004007F7DF&gt;
+10        0.1017  &lt;Compiled-function.AUTO-FLUSH-INTERACTIVE-STREAMS.0x3000404ED6AF&gt;
+7         0.0712  &lt;Compiled-function.%NANOSLEEP.0x30004040385F&gt;
+7         0.0712  &lt;Compiled-function.%ZERO-TRAILING-SIGN-DIGITS.0x300040030F3F&gt;
+	</pre>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-oprofile-Issues"></a>11.1.5.Â Issues</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">CCL::WRITE-ELF-SYMBOLS-TO-FILE currently only works on x86-64; it certainly
+	-could- be made to work on ppc32/ppc64 as well.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">So far, no one has been able to make oprofile/opreport options that're
+	supposed to generate call-stack info generate meaningful call-stack info.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">As of a few months ago, there was an attempt to provide symbol info for
+	oprofile/opreport "on the fly", e.g., for use in JIT compilation or other
+	incremental compilations scenarios.  That's obviously more nearly The Right Thing,
+	but it might be awhile before that experimental code makes it into widespread
+	use.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Profiling-Using-Apples-CHUD-metering-tools"></a>11.2.Â Using Apple's CHUD metering tools</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-CHUD-prerequisites"></a>11.2.1.Â Prerequisites</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Apple's CHUD metering tools are available (as of this writing) from:</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><a class="ulink" href="ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/" target="_top">
+	  ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/</a>.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The CHUD tools are also generally bundled with Apple's XCode tools.  CHUD
+	4.5.0 (which seems to be bundled with XCode 3.0) seems to work well with this
+	interface; later versions may have problems.  Versions of CHUD as old as 4.1.1 may
+	work with 32-bit PPC versions of CCL; later versions (not sure exactly -what-
+	versions) added x86, ppc64, and x86-64 support.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">One way to tell whether any version of the CHUD tools is installed is to try
+	to invoke the "shark" command-line program (/usr/bin/shark) from the shell:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+shell&gt; shark --help
+	</pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">and verifying that that prints a usage summary.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">CHUD consists of several components, including command-line programs, GUI
+	applications, kernel extensions, and "frameworks" (collections of libraries,
+	headers, and other resources which applications can use to access functionality
+	provided by the other components.)  Past versions of Clozure CL/OpenMCL have used the
+	CHUD framework libraries to control the CHUD profiler.  Even though the rest of
+	CHUD is currently 64-bit aware, the frameworks are unfortunately still only
+	available as 32-bit libraries, so the traditional way of controlling the profiling
+	facility from Clozure CL has only worked from DarwinPPC32 versions.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Two of the CHUD component programs are of particular interest:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>The "Shark" application (often installed in
+	    "/Developer/Applications/Performance Tools/Shark.app"), which provides a
+	    graphical user interface for exploring and analyzing profiling results and
+	    provides tools for creating "sampling configurations" (see below), among other
+	    things.</p>
+                </li>
+                <li>
+                  <p>The "shark" program ("/usr/bin/shark"), which can be used to control the
+	    CHUD profiling facility and to collect sampling data, which can then be
+	    displayed and analyzed in Shark.app.</p>
+                </li>
+              </ol>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The fact that these two (substantially different) programs have names that
+	differ only in alphabetic case may be confusing.  The discussion below tries to
+	consistently distinguish between "the shark program" and "the Shark
+	application".</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-CHUD-usage-synopsis"></a>11.2.2.Â Usage synopsis</h3>
+                </div>
+              </div>
+            </div>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
+FACT
+? (require "CHUD-METERING")
+"CHUD-METERING"
+("CHUD-METERING")
+? (chud:meter (null (fact 10000)))
+NIL	      ; since that large number is not NULL
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">and, a few seconds after the result is returned, a file whose name is of
+	  the form "session_nnn.mshark" will open in Shark.app.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The fist time that CHUD:METER is used in a lisp session, it'll do a few
+	  things to prepare subsequent profiling sessions.  Those things include:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>creating a directory to store files that are related to using the CHUD
+	      tools in this lisp session.  This directory is created in the user's home
+	      directory and has a name of the form:</p>
+                  <pre class="programlisting">
+profiling-session-&lt;lisp-kernel&gt;-&lt;pid&gt;_&lt;mm&gt;-&lt;dd&gt;-&lt;yyyy&gt;_&lt;h&gt;.&lt;m&gt;.&lt;s&gt;
+	      </pre>
+                  <p>where &lt;pid&gt; is the lisp's process id, &lt;lisp-kernel&gt; is the
+	      name of the lisp kernel (of all things ...), and the other values provide a
+	      timestamp.</p>
+                </li>
+                <li>
+                  <p>does whatever needs to be done to ensure that currently-defined lisp
+	      functions don't move around as the result of GC activity, then writes a text
+	      file describing the names and addresses of those functions to the
+	      profiling-session directory created above.  (The naming conventions for and
+	      format of that file are described in</p>
+                  <p>
+	      <a class="ulink" href="http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42" target="_top">http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42</a></p>
+                </li>
+                <li>
+                  <p>run the shark program ("/usr/bin/shark") and wait until it's ready to
+	      receive signals that control its operation.</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">This startup activity typically takes a few seconds; after it's been
+	  completed, subsequent use of CHUD:METER doesn't involve that overhead.  (See the
+	  discussion of :RESET below.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">After any startup activity is complete, CHUD:METER arranges to send a
+	  "start profiling" signal to the running shark program, executes the form, sends
+	  a "stop profiling" signal to the shark program, and reads its diagnostic output,
+	  looking for the name of the ".mshark" file it produces.  If it's able to find
+	  this filename, it arranges for "Shark.app" to open it.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-CHUD-profiling-configurations"></a>11.2.3.Â Profiling "configurations"</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">By default, a shark profiling session will:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>use "time based" sampling, to periodically interrupt the lisp
+	    process and note the value of the program counter and at least a few levels of
+	    call history.</p>
+                </li>
+                <li>
+                  <p>do this sampling once every millisecond</p>
+                </li>
+                <li>
+                  <p>run for up to 30 seconds, unless told to stop earlier.</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">This is known as "the default configuration"; it's possible to use items
+	  on the "Config" menu in the Shark application to create alternate configurations
+	  which provide different kinds of profiling parameters and to save these
+	  configurations in files for subsequent reuse.  (The set of things that CHUD
+	  knows how to monitor is large and interesting.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">You use alternate profiling configurations (created and "exported" via
+	  Shark.app) with CHUD:METER, but the interface is a little awkward.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-CHUD-Reference"></a>11.2.4.Â Reference</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	    <a id="id404316" class="indexterm"></a>
+	    <span class="command"><strong><em class="varname"><a id="chud_shark-config-file"></a>CHUD:*SHARK-CONFIG-FILE*</em> [Variable]</strong></span>
+	  </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When non-null, this should be the pathname of an alternate profiling
+	  configuration file created by the "Config Editor" in Shark.app.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	    <a id="id404342" class="indexterm"></a>
+	    <span class="command"><strong><em class="varname"><a id="chud_meter"></a>CHUD:METER</em> form <em class="varname">&amp;key</em> (reset nil) (debug-output nil) [Macro]</strong></span>
+	  </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Executes FORM (an arbitrary lisp form) and returns whatever result(s) it
+	  returns, with CHUD profiling enabled during the form's execution.  Tries to
+	  determine the name of the session file (*.mshark) to which the shark program
+	  wrote profiling data and opens this file in the Shark application.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Arguments:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+              <dl>
+                <dt>
+                  <span class="term">
+                    <em class="varname">debug-output</em>
+                  </span>
+                </dt>
+                <dd>
+                  <p>when non-nil, causes output generated by the shark program to be
+		echoed to *TERMINAL-IO*.  For debugging.</p>
+                </dd>
+                <dt>
+                  <span class="term">
+                    <em class="varname">reset</em>
+                  </span>
+                </dt>
+                <dd>
+                  <p>when non-nil, terminates any running instance of the shark program
+		created by previous invocations of CHUD:METER in this lisp session,
+		generates a new .spatch file (describing the names and addresses of lisp
+		functions), and starts a new instance of the shark program; if
+		CHUD:*SHARK-CONFIG-FILE* is non-NIL when this new instance is started,
+		that instance is told to use the specified config file for profiling (in
+		lieu of the default profiling configuration.)</p>
+                </dd>
+              </dl>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Profiling-CHUD-Acknowledgments"></a>11.2.5.Â Acknowledgement</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Both Dan Knapp and Hamilton Link have posted similar CHUD interfaces to
+	  openmcl-devel in the past; Hamilton's also reported bugs in the spatch mechanism
+	  to CHUD developers (and gotten those bugs fixed.)</p>
+          </div>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="The-Foreign-Function-Interface"></a>ChapterÂ 12.Â The Foreign-Function Interface</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Specifying-And-Using-Foreign-Types">12.1. Specifying And Using Foreign Types</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Overview-foreign-types">12.1.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Syntax-of-Foreign-Type-Specifiers">12.1.2. Syntax of Foreign Type Specifiers</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Foreign-Function-Calls">12.2. Foreign Function Calls</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Overview-foreign-calls">12.2.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Return-Conventions-for-C-Structures">12.2.2. Return Conventions for C Structures</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Referencing-and-Using-Foreign-Memory-Addresses">12.3. Referencing and Using Foreign Memory Addresses</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Overview-memory-addresses">12.3.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Foreign-Memory-Addresses-Dictionary">12.3.2. Foreign-Memory-Addresses Dictionary</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#The-Interface-Database">12.4. The Interface Database</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#interface-database-Overview">12.4.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Other-issues">12.4.2. Other issues:</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Using-Interface-Directories">12.5. Using Interface Directories</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Interface-Directory-Overview">12.5.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Creating-new-interface-directories">12.5.2. Creating new interface directories</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Using-Shared-Libraries">12.6. Using Shared Libraries</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Shared-Library-Overview">12.6.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Limitations-and-known-bugs--1-">12.6.2. Limitations and known bugs</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Darwin-Notes">12.6.3. &gt;Darwin Notes</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#The-Interface-Translator">12.7. The Interface Translator</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Interface-translator-overview">12.7.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Details--rebuilding-the-CDB-databases--step-by-step">12.7.2. Details: rebuilding the CDB databases, step by step</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Case-sensitivity-of-foreign-names-in-CCL">12.8. Case-sensitivity of foreign names in <code class="literal">CCL</code></a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Case-sensitivity-overview">12.8.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Foreign-constant-and-function-names">12.8.2. Foreign constant and function names</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Foreign-type--record--and-field-names">12.8.3. Foreign type, record, and field names</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Examples--1-">12.8.4. Examples</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Reading-Foreign-Names">12.9. Reading Foreign Names</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Tutorial--Using-Basic-Calls-and-Types">12.10. Tutorial: Using Basic Calls and Types</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Acknowledgement">12.10.1. Acknowledgement</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap">12.11. Tutorial: Allocating Foreign Data on the Lisp Heap </a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Acknowledgement--1-">12.11.1. Acknowledgement</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#id445662">12.12. The Foreign-Function-Interface Dictionary</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Specifying-And-Using-Foreign-Types"></a>12.1.Â Specifying And Using Foreign Types</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Overview-foreign-types"></a>12.1.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> provides a fairly rich language for defining and
+        specifying foreign data types (this language is derived from
+        CMUCL's "alien type" system.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In practice, most foreign type definitions are
+        introduced into <code class="literal">CCL</code> via its interface database (see ),
+        though it's also possible to define foreign types
+        interactively and/or programmatically.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code>'s foreign type system is "evolving" (a polite word
+        for not-quite-complete): there are some inconsistencies
+        involving package usage, for instance. Symbols used in foreign
+        type specifiers <span class="emphasis"><em>should</em></span> be keywords, but
+        this convention isn't always enforced.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Foreign
+        type, record, and field names are case-sensitive; <code class="literal">CCL</code> uses
+        some escaping conventions (see ) to allow keywords to be used to
+        denote these names.</p>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="type-annotations"></a>12.1.1.1.Â Type Annotations</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">As of version 1.2, <code class="literal">CCL</code> supports annotating the types of
+          foreign pointers on Mac OS X. Forms that create pointers to
+          foreign memoryâthat is, <code class="code">MACPTR</code>sâstore
+          with the <code class="code">MACPTR</code> object a type annotation that
+          identifies the foreign type of the object pointed
+          to. Calling <code class="code">PRINT-OBJECT</code> on a <code class="code">MACPTR</code>
+          attempts to print information about the identified foreign
+          type, including whether it was allocated on the heap or the
+          stack, and whether it's scheduled for automatic reclamation by
+          the garbage collector.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">Support for type annotation is not yet complete. In
+          particular, some uses of <code class="code">PREF</code>
+          and <code class="code">SLOT-VALUE</code> do ot yet take type annotations into
+          account, and neither do <code class="code">DESCRIBE</code>
+          and <code class="code">INSPECT</code>.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="foreign-type-classes"></a>12.1.1.2.Â Foreign Types as Classes</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">Some types of foreign pointers take advantage of the
+          support for type annotations, and pointers of these types
+          can be treated as instances of known classes. Specifically,
+          a pointer to an <code class="code">:&lt;NSR&gt;ect</code> is recognized
+          as an instance of the built-in
+          class <code class="code">NS:NS-RECT</code>, a pointer to
+          an <code class="code">&lt;NSS&gt;ize</code> is treated as an instance
+          of <code class="code">NS:NS-SIZE</code>, a pointer to
+          an <code class="code">&lt;NSP&gt;oint</code> is recognized as an
+          instance of <code class="code">NS:NS-POINT</code>, and a pointer to
+          an <code class="code">&lt;NSR&gt;ange</code> is recognized as an
+          instance of <code class="code">NS:NS-RANGE</code>.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">A few more obscure structure types also support this
+        mechanism, and it's possible that a future version will
+        support user definition of similar type mappings.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">This support for foreign types as classes provides the
+        following conveniences for each supported type:</p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+                <ul type="disc">
+                  <li>
+                    <p>a <code class="code">PRINT-OBJECT</code> method is defined</p>
+                  </li>
+                  <li>
+                    <p>a foreign type name is created and treated as an alias
+          for the corresponding type. As an example, the
+          name <code class="code">:NS-RECT</code> is a name for the type that
+          corresponds to <code class="code">NS:NS-RECT</code>, and you can
+          use <code class="code">:NS-RECT</code> as a type designator
+          in <a class="link" href="#anchor_rlet"><code class="code">RLET</code></a> forms to
+          specify a structure of type <code class="code">NS-RECT</code>.</p>
+                  </li>
+                  <li>
+                    <p>the class is integrated into the type system so that
+            <code class="code">(TYPEP R 'NS:NS-RECT)</code> is implemented with
+            fair efficiency.</p>
+                  </li>
+                  <li>
+                    <p>inlined accessor and <code class="code">SETF</code> inverses are
+            defined for the structure type's fields.  In the case of
+            an <code class="code">&lt;NSR*gt;ect</code>, for example, the fields in
+            question are the fields of the embedded point and size, so
+            that <code class="code">NS:NS-RECT-X</code>, <code class="code">NS:NS-RECT-Y</code>, <code class="code">NS:NS-RECT-WIDTH</code>,
+            <code class="code">NS-RECT-HEIGHT</code> and <code class="code">SETF</code> inverses
+            are defined.  The accessors and setter functions typecheck
+            their arguments and the setters handle coercion to the
+            appropriate type of <code class="code">CGFLOAT</code> where
+            applicable.</p>
+                  </li>
+                  <li>
+                    <p>an initialization function is defined; for
+            example,</p>
+                    <pre class="programlisting">
+(NS:INIT-NS-SIZE s w h)
+          </pre>
+                    <p>is roughly equivalent to</p>
+                    <pre class="programlisting">
+(SETF (NS:NS-SIZE-WIDTH s) w
+      (NS:NS-SIZE-HEIGHT s) h)
+          </pre>
+                    <p>but might be a little more efficient.</p>
+                  </li>
+                  <li>
+                    <p>a creation function is defined; for
+            example</p>
+                    <pre class="programlisting">
+(NS:NS-MAKE-POINT x y)
+          </pre>
+                    <p>is functionally equivalent to</p>
+                    <pre class="programlisting">
+(LET ((P (MAKE-GCABLE-RECORD :NS-POINT)))
+  (NS:INIT-NS-POINT P X Y)
+  p)
+          </pre>
+                  </li>
+                  <li>
+                    <p>a macro is defined which, like <code class="code">RLET</code>,
+            stack-allocates an instance of the foreign record type,
+            optionally initializes that instance, and executes a body
+            of code with a variable bound to that instance.</p>
+                    <p>For example,</p>
+                    <pre class="programlisting">
+(ns:with-ns-range (r loc len)
+  (format t "~&amp; range has location ~s, length ~s" 
+     (ns:ns-range-location r) (ns:ns-range-length r)))
+          </pre>
+                  </li>
+                  <li>
+                    <p></p>
+                  </li>
+                </ul>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Syntax-of-Foreign-Type-Specifiers"></a>12.1.2.Â Syntax of Foreign Type Specifiers</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>Some foreign types are builtin: keywords denote
+            primitive,builtin types such as the IEEE-double-float type
+            (denoted:DOUBLE-FLOAT), in much the same way as certain
+            symbols(CONS, FIXNUM,etc.) define primitive CL
+            types.</p>
+                </li>
+                <li>
+                  <p>Constructors such as :SIGNED and :UNSIGNED can be
+            used to denote signed and unsigned integer subtypes
+            (analogous to the CL type specifiers SIGNED-BYTE and
+            UNSIGNED-BYTE.) :SIGNED is shorthand for(:SIGNED 32) and
+            :UNSIGNED is shorthand for (:UNSIGNED 32).</p>
+                </li>
+                <li>
+                  <p>Aliases for other (perhaps more complicated) types
+            can be defined via CCL:DEF-FOREIGN-TYPE (sort of like
+            CL:DEFTYPE or the C typedef facility). The type :CHAR is
+            defined as an alias for (:SIGNED8) on some platforms, as
+            (:UNSIGNED 8) on others.</p>
+                </li>
+                <li>
+                  <p>The construct (:STRUCT <span class="emphasis"><em>name</em></span>)
+	        can be used to refer to a named structure type; (:UNION
+	        <span class="emphasis"><em>name</em></span>)can be used to refer to a named
+	        union type. It isn't necessary to enumerate a structure or
+	        union type's fields in order to refer to the type.</p>
+                </li>
+                <li>
+                  <p>If <span class="emphasis"><em>X</em></span> is a valid foreign type
+	        reference,then (:* <span class="emphasis"><em>X</em></span>) denotes the
+	        foreign type "pointer to<span class="emphasis"><em> X</em></span>". By
+	        convention, (:* T) denotes an anonymous pointer type,
+	        vaguely equivalent to "void*" in C.</p>
+                </li>
+                <li>
+                  <p>If a fieldlist is a list of lists, each of whose CAR
+	        is a foreign field name (keyword) and whose CADR is a
+	        foreign type specifier, then (:STRUCT
+	        <span class="emphasis"><em>name</em></span> ,@fieldlist) is a definition of
+	        the structure type <span class="emphasis"><em>name</em></span>,
+	        and (:UNION<span class="emphasis"><em> name</em></span> ,@fieldlist) is a
+	        definition of the union type
+	        <span class="emphasis"><em>name</em></span>. Note that it's necessary
+	        to define a structure or union type in order to include
+	        that type in a structure, union, or array, but only
+	        necessary to "refer to" a structure or union type in order
+	        to define a type alias or a pointer type.</p>
+                </li>
+                <li>
+                  <p>If <span class="emphasis"><em>X</em></span> is a defined foreign type
+	        , then (:array <span class="emphasis"><em>X</em></span> &amp;rest dims)
+	        denotes the foreign type "array of
+	        <span class="emphasis"><em>X</em></span>". Although multiple array dimensions
+	        are allowed by the :array constructor,
+	        only single-dimensioned arrays are (at all) well-supported
+	        in <code class="literal">CCL</code>.</p>
+                </li>
+              </ul>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Foreign-Function-Calls"></a>12.2.Â Foreign Function Calls</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Overview-foreign-calls"></a>12.2.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> provides a number of constructs for calling
+        foreign functions from Lisp code (all of them based on the
+        function CCL:%FF-CALL).  In many cases, <code class="literal">CCL</code>'s interface
+        translator (see ) provides information about the foreign
+        function's entrypoint name and argument and return types; this
+        enables the use of the #_ reader macro (described below),
+        which may be more concise and/or more readable than other
+        constructs.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> also provides a mechanism for defining
+        <span class="emphasis"><em>callbacks</em></span>: lisp functions which can be
+        called from foreign code.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">There's no supported way to directly pass lisp data to
+        foreign functions: scalar lisp data must be coerced to an
+        equivalent foreign representation, and lisp arrays (notably
+        strings) must be copied to non-GCed memory.</p>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Type-Designators-for-Arguments-and-Return-Values"></a>12.2.1.1.Â Type Designators for Arguments and Return Values</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">The types of foreign argument and return values in foreign
+	      function calls and callbacks can be specified by any of the following
+          keywords:</p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">:UNSIGNED-BYTE</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (UNSIGNED-BYTE 8)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:SIGNED-BYTE</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (SIGNED-BYTE 8)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:UNSIGNED-HALFWORD</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (UNSIGNED-BYTE 16)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:SIGNED-HALFWORD</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (SIGNED-BYTE 16)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:UNSIGNED-FULLWORD</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (UNSIGNED-BYTE 32)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:SIGNED-FULLWORD</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (SIGNED-BYTE 32)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:UNSIGNED-DOUBLEWORD</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (UNSIGNED-BYTE 64)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:SIGNED-DOUBLEWORD</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type (SIGNED-BYTE 64)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:SINGLE-FLOAT</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type SINGLE-FLOAT</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:DOUBLE-FLOAT</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return value is of type DOUBLE-FLOAT</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:ADDRESS</span>
+                  </dt>
+                  <dd>
+                    <p>The argument/return values
+		        is <a class="link" href="#Referencing-and-Using-Foreign-Memory-Addresses" title="12.3.Â Referencing and Using Foreign Memory Addresses">a MACPTR</a>.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">:VOID</span>
+                  </dt>
+                  <dd>
+                    <p>or NIL Not valid as an argument type specifier; specifies
+		        that there is no meaningful return value</p>
+                  </dd>
+                </dl>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">On some platforms, a small positive integer
+          <span class="emphasis"><em>N</em></span> can also be used as an argument
+          specifier; it indicates that the corresponding argument is a
+          pointer to an <span class="emphasis"><em>N</em></span>-word structure or union
+          which should be passed by value to the foreign
+          function.  Exactly which foreign structures are passed
+	      by value and how is very dependent on the Application
+	      Binary Interface (ABI) of the platform; unless you're
+	      very familiar with ABI details (some of which are quite
+	      baroque), it's often easier to let higher-level constructs
+	      deal with these details.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="External-Entrypoints-and-Named-External-Entrypoints"></a>12.2.1.2.Â External Entrypoints and Named External Entrypoints</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">PowerPC machine instructions are always aligned on
+          32-bit boundaries, so the two least significant bits of the
+          first instruction ("entrypoint") of a foreign function are
+          always 0. <code class="literal">CCL</code> often represents an entrypoint address as
+          a fixnum that's binary-equivalent to the entrypoint address:
+          if<span class="emphasis"><em> E</em></span> is an entrypoint address expressed
+          as a signed 32-bit integer, then (ash <span class="emphasis"><em>E</em></span>
+          -2) is an equivalent fixnum representation of that
+          address. An entrypoint address can also be encapsulated in a
+          MACPTR (see FIXTHIS), but that's somewhat less efficient.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">Although it's possible to use fixnums or macptrs to
+          represent entrypoint addresses, it's somewhat cumbersome to
+          do so. <code class="literal">CCL</code> can cache the addresses of named external
+          functions in structure-like objects of type
+          CCL:EXTERNAL-ENTRY-POINT (sometimes abbreviated as EEP).
+          Through the use of LOAD-TIME-VALUE, compiled lisp functions
+          are able to reference EEPs as constants; the use of an
+          indirection allows <code class="literal">CCL</code> runtime system to ensure that the
+          EEP's address is current and correct.</p>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Return-Conventions-for-C-Structures"></a>12.2.2.Â Return Conventions for C Structures</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"> On some platforms, C functions that are defined to
+        return structures do so by reference: they actually
+        accept a first parameter of type "pointer to returned
+        struct/union" - which must be allocated by the caller - and
+        don't return a meaningful value.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><span class="emphasis"><em>Exactly</em></span> how a C function that's
+	    defined to return a foreign structure does so is dependent on
+	    the ABI (and on the size and composition of the structure/union
+	    in many cases.)</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Referencing-and-Using-Foreign-Memory-Addresses"></a>12.3.Â Referencing and Using Foreign Memory Addresses</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Overview-memory-addresses"></a>12.3.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Basics"></a>12.3.1.1.Â Basics</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">For a variety of technical reasons, it isn't generally
+          possible to directly reference arbitrary absolute addresses
+          (such as those returned by the C library function malloc(),
+          for instance) in <code class="literal">CCL</code>. In <code class="literal">CCL</code> (and in MCL), such
+          addresses need to be <span class="emphasis"><em>encapsulated</em></span> in
+          objects of type CCL:MACPTR; one can think of a MACPTR as
+          being a specialized type of structure whose sole purpose is
+          to provide a way of referring to an underlying "raw"
+          address.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">It's sometimes convenient to blur the distinction
+          between a MACPTR and the address it represents; it's
+          sometimes necessary to maintain that distinction. It's
+          important to remember that a MACPTR is (generally) a
+          first-class Lisp object in the same sense that a CONS cell
+          is: it'll get GCed when it's no longer possible to reference
+          it. The "lifetime" of a MACPTR doesn't generally have
+          anything to do with the lifetime of the block of memory its
+          address points to.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">It might be tempting to ask "How does one obtain the
+          address encapsulated by a MACPTR ?". The answer to that
+          question is that one doesn't do that (and there's no way to
+          do that): addresses aren't first-class objects, and there's
+          no way to refer to one.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">Two MACPTRs that encapsulate the same address are EQL
+          to each other.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">There are a small number of ways to directly create a
+          MACPTR (and there's a fair amount of syntactic sugar built
+          on top of of those primitives.) These primitives will be
+          discussed in greater detail below, but they include:</p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+                <ul type="disc">
+                  <li>
+                    <p>Creating a MACPTR with a specified address, usually
+	          via the function CCL:%INT-TO-PTR.</p>
+                  </li>
+                  <li>
+                    <p>Referencing the return value of a foreign function
+	          call (see )that's specified to return an address.</p>
+                  </li>
+                  <li>
+                    <p>Referencing a memory location that's specified to
+	          contain an address.</p>
+                  </li>
+                </ul>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">All of these primitive MACPTR-creating operations are
+          usually open-coded by the compiler; it has a fairly good
+          notion of what low-level operations "produce" MACPTRs and
+          which operations "consume" the addresses that the
+          encapsulate, and will usually optimize out the introduction
+          of intermediate MACPTRs in a simple expression.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">One consequence of the use of MACPTR objects to
+          encapsulate foreign addresses is that (naively)
+          <span class="emphasis"><em>every reference to a foreign address causes a
+            MACPTR to be allocated.</em></span></p>
+              <p xmlns="http://www.w3.org/1999/xhtml">Consider a code fragment like the following:</p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defun get-next-event ()
+  "get the next event from a hypothetical window system"
+  (loop
+     (let* ((event (#_get_next_window_system_event))) ; via an FF-CALL
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">As this is written, each call to the (hypothetical)
+          foreign function #_get_next_window_system_event will return
+          a new MACPTR object.  Ignoring for the sake of argument the
+          question of whether this code fragment exhibits a good way
+          to poll for external events (it doesn't), it's not hard to
+          imagine that this loop could execute several million times
+          per second (producing several million MACPTRs per second.)
+          Clearly, the "naive" approach is impractical in many
+          cases.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Stack-allocation-of---and-destructive-operations-on---MACPTRs-"></a>12.3.1.2.Â Stack allocation ofâand destructive operations onâMACPTRs.</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">If certain conditions held in the environment in which
+	      GET-NEXT-EVENT ranânamely, if it was guaranteed that
+	      neither NULL-EVENT-P nor HANDLE-EVENT cached or otherwise
+	      retained their arguments (the "event" pointer)âthere'd be
+	      a few alternatives to the naive approach. One of those
+	      approaches would be to use the primitive function
+	      %SETF-MACPTR (described in greater detail below) to
+	      destructively modify a MACPTR (to change the value of the
+	      address it encapsulates.) The GET-NEXT-EVENT example could
+	      be re-written as:</p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defun get-next-event ()
+  (let* ((event (%int-to-ptr 0)))     ; create a MACPTR with address 0
+    (loop
+       (%setf-macptr event (#_get_next_window_system_event)) ; re-use it
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">That version's a bit more realistic: it allocates a
+          single MACPTR outside if the loop, then changes its address
+          to point to the current address of the hypothetical event
+          structure on each loop iteration. If there are a million
+          loop iterations per call to GET-NEXT-EVENT, we're allocating
+          a million times fewer MACPTRs per call; that sounds like a
+          Good Thing.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">An Even Better Thing would be to advise the compiler
+          that the initial value (the null MACPTR) bound to the
+          variable event has dynamic extent (that value won't be
+          referenced once control leaves the extent of the binding of
+          that variable.) Common Lisp allows us to make such an
+          assertion via a DYNAMIC-EXTENT declaration; <code class="literal">CCL</code>'s
+          compiler can recognize the "primitive MACPTR-creating
+          operation" involved and can replace it with an equivalent
+          operation that stack-allocates the MACPTR object. If we're
+          not worried about the cost of allocating that MACPTR on
+          every iteration (the cost is small and there's no hidden GC
+          cost), we could move the binding back inside the
+          loop:</p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defun get-next-event ()
+  (loop
+     (let* ((event (%null-ptr))) ; (%NULL-PTR) is shorthand for (%INT-TO-PTR 0)
+       (declare (dynamic-extent event))
+       (%setf-macptr event (#_get_next_window_system_event))
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">The idiom of binding one or more variables to
+          stack-allocated MACPTRs, then destructively modifying those
+          MACPTRs before executing a body of code is common enough
+          that <code class="literal">CCL</code> provides a macro (WITH-MACPTRS) that handles
+          all of the gory details. The following version of
+          GET-NEXT-EVENT is semantically equivalent to the previous
+          version, but hopefully a bit more concise:</p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defun get-next-event ()
+  (loop
+     (with-macptrs ((event (#_get_next_window_system_event)))
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </pre>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Stack-allocated-memory--and-stack-allocated-pointers-to-it--"></a>12.3.1.3.Â Stack-allocated memory (and stack-allocated pointers to it.)</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">Fairly often, the blocks of foreign memory (obtained
+	      by malloc or something similar) have well-defined lifetimes
+	      (they can safely be freed at some point when it's known that
+	      they're no longer needed and it's known that they're no
+	      longer referenced.) A common idiom might be:</p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(with-macptrs (p (#_allocate_foreign_memory size))
+  (unwind-protect
+       (use-foreign-memory p)
+    (#_deallocate_foreign_memory p)))
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">That's not unreasonable code, but it's fairly
+          expensive for a number of reasons: foreign functions calls
+          are themselves fairly expensive (as is UNWIND-PROTECT), and
+          most library routines for allocating and deallocating
+          foreign memory (things like malloc and free) can be fairly
+          expensive in their own right.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">In the idiomatic code above, both the MACPTR P and the
+          block of memory that's being allocated and freed have
+          dynamic extent and are therefore good candidates for stack
+          allocation. <code class="literal">CCL</code> provides the %STACK-BLOCK macro, which
+          executes a body of code with one or more variables bound to
+          stack-allocated MACPTRs which encapsulate the addresses of
+          stack-allocated blocks of foreign memory. Using
+          %STACK-BLOCK, the idiomatic code is:</p>
+              <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(%stack-block ((p size))
+              (use-foreign-memory p))
+        </pre>
+              <p xmlns="http://www.w3.org/1999/xhtml">which is a bit more efficient and a bit more concise
+          than the version presented earlier.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">%STACK-BLOCK is used as the basis for slightly
+          higher-level things like RLET. (See FIXTHIS for more information
+          about RLET.)</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Caveats-"></a>12.3.1.4.Â Caveats</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">Reading from, writing to, allocating, and freeing
+          foreign memory are all potentially dangerous operations;
+          this is no less true when these operations are performed in
+          <code class="literal">CCL</code> than when they're done in C or some other
+          lower-level language. In addition, destructive operations on
+          Lisp objects be dangerous, as can stack allocation if it's
+          abused (if DYNAMIC-EXTENT declarations are violated.)
+          Correct use of the constructs and primitives described here
+          is reliable and safe; slightly incorrect use of these
+          constructs and primitives can crash <code class="literal">CCL</code>.</p>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Foreign-Memory-Addresses-Dictionary"></a>12.3.2.Â Foreign-Memory-Addresses Dictionary</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Unless otherwise noted, all of the symbols mentioned
+        below are exported from the CCL package.</p>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Scalar-memory-reference"></a>12.3.2.1.Â Scalar memory reference</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%get-signed-byte ptr &amp;optional (offset 0)</p>
+                    <p>%get-unsigned-byte ptr &amp;optional (offset 0)</p>
+                    <p>%get-signed-word ptr &amp;optional (offset 0)</p>
+                    <p>%get-unsigned-word ptr &amp;optional (offset 0)</p>
+                    <p>%get-signed-long ptr &amp;optional (offset 0)</p>
+                    <p>%get-unsigned-long ptr &amp;optional (offset 0)</p>
+                    <p>%%get-signed-longlong ptr &amp;optional (offset 0)</p>
+                    <p>%%get-unsigned-longlong ptr &amp;optional (offset 0)</p>
+                    <p>%get-ptr ptr &amp;optional (offset 0)</p>
+                    <p>%get-single-float ptr &amp;optional (offset 0)</p>
+                    <p>%get-double-float ptr &amp;optional (offset 0)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>References and returns the signed or unsigned 8-bit byte,
+		        signed or unsigned 16-bit word, signed or unsigned 32-bit long
+		        word, signed or unsigned 64-bit long long word, 32-bit address,
+		        32-bit single-float, or 64-bit double-float at the effective byte
+		        address formed by adding offset to the address encapsulated by
+		        ptr.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                        <dt>
+                          <span class="term">offset</span>
+                        </dt>
+                        <dd>
+                          <p>A fixnum</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">All of the memory reference primitives described above can be</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">used with SETF.</p>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="iget-bit--Function-"></a>12.3.2.2.Â %get-bit [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%get-bit ptr bit-offset</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>References and returns the bit-offsetth bit at the address
+		        encapsulated by ptr. (Bit 0 at a given address is the most
+		        significant bit of the byte at that address.) Can be used with
+		        SETF.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                        <dt>
+                          <span class="term">bit-offset</span>
+                        </dt>
+                        <dd>
+                          <p>A fixnum</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="iget-bitfield--Function-"></a>12.3.2.3.Â %get-bitfield [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%get-bitfield ptr bit-offset width</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>References and returns an unsigned integer composed from the
+		        width bits found bit-offset bits from the address encapsulated by
+		        ptr. (The least significant bit of the result is the value of
+		        (%get-bit ptr (1- (+ bit-offset width))). Can be used with SETF.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                  </dd>
+                  <dt>
+                    <span class="term">ptr</span>
+                  </dt>
+                  <dd>
+                    <p>A MACPTR</p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">bit-offset</span>
+                        </dt>
+                        <dd>
+                          <p>A fixnum</p>
+                        </dd>
+                        <dt>
+                          <span class="term">width</span>
+                        </dt>
+                        <dd>
+                          <p>A positive fixnum</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425110"></a>12.3.2.4.Â %int-to-ptr [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%int-to-ptr int</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Creates and returns a MACPTR whose address matches int.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">int</span>
+                        </dt>
+                        <dd>
+                          <p>An (unsigned-byte 32)</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425185"></a>12.3.2.5.Â %inc-ptr [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%inc-ptr ptr &amp;optional (delta 1)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Creates and returns a MACPTR whose address is the address of
+		        ptr plus delta. The idiom (%inc-ptr ptr 0) is sometimes used to
+		        copy a MACPTR, e.g., to create a new MACPTR encapsulating the same
+		        address as ptr.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                        <dt>
+                          <span class="term">delta</span>
+                        </dt>
+                        <dd>
+                          <p>A fixnum</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425276"></a>12.3.2.6.Â %ptr-to-int [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%ptr-to-int ptr</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Returns the address encapsulated by ptr, as an
+		        (unsigned-byte 32).</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425351"></a>12.3.2.7.Â %null-ptr [Macro]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%null-ptr</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Equivalent to (%int-to-ptr 0).</p>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425393"></a>12.3.2.8.Â %null-ptr-p [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%null-ptr-p ptr</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Returns T If ptr is a MACPTR encapsulating the address 0,
+		        NIL if ptr encapsulates some other address.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425468"></a>12.3.2.9.Â %setf-macptr [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%setf-macptr dest-ptr src-ptr</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Causes dest-ptr to encapsulate the same address that src-ptr
+		        does, then returns dest-ptr.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">dest-ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                        <dt>
+                          <span class="term">src-ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425558"></a>12.3.2.10.Â %incf-ptr [Macro]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%incf-ptr ptr &amp;optional (delta 1)</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Destructively modifies ptr, by adding delta to the address
+		        it encapsulates. Returns ptr.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                        <dt>
+                          <span class="term">delta</span>
+                        </dt>
+                        <dd>
+                          <p>A fixnum</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425649"></a>12.3.2.11.Â with-macptrs [Macro]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>with-macptrs (var expr)* &amp;body body</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Executes body in an environment in which each var is bound
+		        to a stack-allocated macptr which encapsulates the foreign address
+		        yielded by the corresponding expr. Returns whatever value(s) body
+		        returns.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">var</span>
+                        </dt>
+                        <dd>
+                          <p>A symbol (variable name)</p>
+                        </dd>
+                        <dt>
+                          <span class="term">expr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR-valued expression</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425741"></a>12.3.2.12.Â %stack-block [Macro]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%stack-block (var expr)* &amp;body body</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Executes body in an environment in which each var is bound
+		        to a stack-allocated macptr which encapsulates the address of a
+		        stack-allocated region of size expr bytes. Returns whatever
+		        value(s) body returns.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">var</span>
+                        </dt>
+                        <dd>
+                          <p>A symbol (variable name)</p>
+                        </dd>
+                        <dt>
+                          <span class="term">expr</span>
+                        </dt>
+                        <dd>
+                          <p>An expression which should evaluate to a non-negative
+		              fixnum</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425833"></a>12.3.2.13.Â make-cstring [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>make-cstring string</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Allocates a block of memory (via malloc) of length (1+
+		        (length string)). Copies the string to this block and appends a
+		        trailing NUL byte; returns a MACPTR to the block.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">string</span>
+                        </dt>
+                        <dd>
+                          <p>A lisp string</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id425909"></a>12.3.2.14.Â with-cstrs [Macro]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>with-cstrs (var string)* &amp;body body</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Executes body in an environment in which each var is bound
+		        to a stack-allocated macptr which encapsulates the %address of a
+		        stack-allocated region of into which each string (and a trailing
+		        NUL byte) has been copied. Returns whatever value(s) body returns.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">var</span>
+                        </dt>
+                        <dd>
+                          <p>A symbol (variable name)</p>
+                        </dd>
+                        <dt>
+                          <span class="term">string</span>
+                        </dt>
+                        <dd>
+                          <p>An expression which should evaluate to a lisp string</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id426001"></a>12.3.2.15.Â with-encoded-cstrs [Macro]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>with-encoded-cstrs ENCODING-NAME (varI stringI)* &amp;body body</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Executes body in an environment in which each varI is
+		        bound to a macptr which encapsulates the %address of a
+		        stack-allocated region of into which each stringI (and a
+		        trailing NUL character) has been copied. Returns whatever
+		        value(s) body returns.</p>
+                    <p>ENCODING-NAME is a keyword constant that names a
+                character encoding. Each foreign string is encoded in the
+                named encoding. Each foreign string has dynamic
+                extent.</p>
+                    <p>WITH-ENCODED-CSTRS does not automatically prepend
+                byte-order marks to its output; the size of the terminating
+                #\NUL character depends on the number of octets per code unit
+                in the encoding.</p>
+                    <p>The expression</p>
+                    <pre class="programlisting">(ccl:with-cstrs ((x "x")) (#_puts x))</pre>
+                    <p>is functionally equivalent to</p>
+                    <pre class="programlisting">(ccl:with-encoded-cstrs :iso-8859-1 ((x "x")) (#_puts x))</pre>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p>Â </p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">varI</span>
+                        </dt>
+                        <dd>
+                          <p>A symbol (variable name)</p>
+                        </dd>
+                        <dt>
+                          <span class="term">stringI</span>
+                        </dt>
+                        <dd>
+                          <p>An expression which should evaluate to a lisp string</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id426124"></a>12.3.2.16.Â %get-cstring [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%get-cstring ptr</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Interprets ptr as a pointer to a (NUL -terminated) C string;
+		        returns an equivalent lisp string.</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <p></p>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A MACPTR</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="id443744"></a>12.3.2.17.Â %str-from-ptr [Function]</h4>
+                  </div>
+                </div>
+              </div>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+                <dl>
+                  <dt>
+                    <span class="term">Syntax</span>
+                  </dt>
+                  <dd>
+                    <p>%str-from-ptr ptr length</p>
+                  </dd>
+                  <dt>
+                    <span class="term">Description</span>
+                  </dt>
+                  <dd>
+                    <p>Returns a lisp string of length <em class="varname">length</em>,
+		        whose contents are initialized from the bytes at<em class="varname"> ptr.</em>
+		      </p>
+                  </dd>
+                  <dt>
+                    <span class="term">Arguments</span>
+                  </dt>
+                  <dd>
+                    <div class="variablelist">
+                      <dl>
+                        <dt>
+                          <span class="term">ptr</span>
+                        </dt>
+                        <dd>
+                          <p>A
+		                MACPTR</p>
+                        </dd>
+                        <dt>
+                          <span class="term">length</span>
+                        </dt>
+                        <dd>
+                          <p>a
+		                non-negative fixnum</p>
+                        </dd>
+                      </dl>
+                    </div>
+                  </dd>
+                </dl>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="The-Interface-Database"></a>12.4.Â The Interface Database</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="interface-database-Overview"></a>12.4.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> uses a set of database files which contain
+        foreign type, record, constant, and function definitions
+        derived from the operating system's header files, be that
+        Linux or Darwin.  An archive containing these database files
+        (and the shell scripts which were used in their creation) is
+        available; see the Distributions page for information about
+        obtaining current interface database files.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Not surprisingly, different platforms use different database files.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> defines reader macros that consult these databases:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>#$foo looks up the value of the constant definition of foo</p>
+                </li>
+                <li>
+                  <p>#_foo looks up the foreign function definition for foo</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">In both cases, the symbol foo is interned in the "OS"
+        package. The #$ reader macro has the side-effect of defining
+        foo as a constant (as if via DEFCONSTANT); the #_ reader macro
+        has the side effect of defining foo as a macro which will
+        expand into an (EXTERNAL-CALL form.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's important to remember that the side-effect happens
+        when the form containing the reader macro is
+        read. Macroexpansion functions that expand into forms which
+        contain instances of those reader macros don't do what one
+        might think that they do, unless the macros are expanded in
+        the same lisp session as the reader macro was read in.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In addition, references to foreign type,
+        structure/union, and field names (when used in the RREF/PREF
+        and RLET macros) will cause these database files to be
+        consulted.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Since the <code class="literal">CCL</code> sources contain instances of these
+        reader macros (and references to foreign record types and
+        fields), compiling <code class="literal">CCL</code> from those sources depends on the
+        ability to find and use (see <a class="xref" href="#Building-the-heap-image" title="3.5.Â Building the heap image">SectionÂ 3.5, âBuilding the heap imageâ</a>).</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Other-issues"></a>12.4.2.Â Other issues:</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p><code class="literal">CCL</code> now preserves the case of external symbols in
+	        its database
+	        files. See <a class="link" href="#Case-sensitivity-of-foreign-names-in-CCL" title="12.8.Â Case-sensitivity of foreign names in CCL">Case-sensitivity
+	        of foreign names in <code class="literal">CCL</code></a> for information about
+	        case in foreign symbol names.</p>
+                </li>
+                <li>
+                  <p>The Linux databases are derived from a somewhat
+	        arbitrary set of Linux header files. Linux is enough of a
+	        moving target that it may be difficult to define a standard,
+	        reference set of interfaces from which to derive a standard,
+	        reference set of database files.This seems to be less of
+	        an issue with Darwin and FreeBSD.</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">For information about building the database files,
+	    see <a class="xref" href="#The-Interface-Translator" title="12.7.Â The Interface Translator">SectionÂ 12.7, âThe Interface Translatorâ</a>.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Using-Interface-Directories"></a>12.5.Â Using Interface Directories</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Interface-Directory-Overview"></a>12.5.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">As distributed, the "ccl:headers;" (for LinuxPPC)
+        directory is organized like:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+        headers/
+        headers/gl/
+        headers/gl/C/
+        headers/gl/C/populate.sh
+        headers/gl/constants.cdb
+        headers/gl/functions.cdb
+        headers/gl/records.cdb
+        headers/gl/objc-classes.cdb
+        headers/gl/objc-methods.cdb
+        headers/gl/types.cdb
+        headers/gnome/
+        headers/gnome/C/
+        headers/gnome/C/populate.sh
+        headers/gnome/constants.cdb
+        headers/gnome/functions.cdb
+        headers/gnome/records.cdb
+        headers/gnome/objc-classes.cdb
+        headers/gnome/objc-methods.cdb
+        headers/gnome/types.cdb
+        headers/gtk/
+        headers/gtk/C/
+        headers/gtk/C/populate.sh
+        headers/gtk/constants.cdb
+        headers/gtk/functions.cdb
+        headers/gtk/records.cdb
+        headers/gtk/objc-classes.cdb
+        headers/gtk/objc-methods.cdb
+        headers/gtk/types.cdb
+        headers/libc/
+        headers/libc/C/
+        headers/libc/C/populate.sh
+        headers/libc/constants.cdb
+        headers/libc/functions.cdb
+        headers/libc/records.cdb
+        headers/libc/objc-classes.cdb
+        headers/libc/objc-methods.cdb
+        headers/libc/types.cdb
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">e.g, as a set of parallel subdirectories, each with a
+        lowercase name and each of which contains a set of 6 database
+        files and a "C" subdirectory which contains a shell script
+        used in the database creation process.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">As one might assume, the database files in each of these
+        subdirectories contain foreign type, constant, and function
+        definitions - as well as Objective-C class and method info -that
+        correspond (roughly) to the information contained in the
+        header files associated with a "-dev" package in a Linux
+        distribution.  "libc" corresponds pretty closely to the
+        interfaces associated with "glibc/libc6" header files, "gl"
+        corresponds to an "openGL+GLUT" development package, "gtk"
+        and "gnome" contain interface information from the GTK+1.2 and
+        GNOME libraries, respectively.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">For Darwin, the "ccl:darwin-headers" directory contains
+        a "libc" subdirectory, whose contents roughly correspond to
+        those of "/usr/include" under Darwin, as well as
+        subdirectories corresponding to the MacOSX Carbon and Cocoa
+        frameworks.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">To see the precise set of .h files used to generate the
+        database files in a given interface directory, consult the
+        corresponding "populate.sh" shell script (in the interface
+        directory's "C" subdirectory.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The intent is that this initial set can be augmented to
+        meet local needs, and that this can be done in a fairly
+        incremental fashion: one needn't have unrelated header files
+        installed in order to generate interface databases for a
+        package of interest.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Hopefully, this scheme will also make it easier to
+        distribute patches and bug fixes.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> maintains a list of directories; when looking
+        for a foreign type, constant, function, or record definition,
+        it'll consult the database files in each directory on that
+        list. Initially, the list contains an entry for the "libc"
+        interface directory. <code class="literal">CCL</code> needs to be explicitly told to
+        look in other interface directories should it need to do
+        so.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Creating-new-interface-directories"></a>12.5.2.Â Creating new interface directories</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">This example refers to "ccl:headers;", which is
+        appropriate for LinuxPPC. The procedure's analogous under
+        Darwin, where the "ccl:darwin-headers;" directory would be
+        used instead.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">To create a new interface directory, "foo", and a set of
+        database files in that directory:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>Create a subdirectory of "ccl:headers;" named
+	        "foo".</p>
+                </li>
+                <li>
+                  <p>Create a subdirectory of "ccl:headers;foo;" named
+	        "C".</p>
+                </li>
+                <li>
+                  <p>Create a file in "ccl:headers;foo;C;" named
+	        "populate.sh".</p>
+                  <p>One way of accomplishing the above steps is:</p>
+                  <pre class="programlisting">
+            ? (close (open "ccl:headers;foo;C;populate.sh" :direction :output :
+                           if-does-not-exist :create :if-exists :overwrite))
+          </pre>
+                </li>
+                <li>
+                  <p>Edit the file created above, using the "populate.sh"
+	        files in the distribution as guidelines.</p>
+                  <p>The file might wind up looking something like:</p>
+                  <pre class="programlisting">#/bin/sh
+            h-to-ffi.sh `foo-config -cflags` /usr/include/foo/foo.h</pre>
+                </li>
+              </ol>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Refer to <a class="xref" href="#The-Interface-Translator" title="12.7.Â The Interface Translator">SectionÂ 12.7, âThe Interface Translatorâ</a> for
+        information about running the interface translator and .ffi
+        parser.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Assuming that all went well, there should now be .cdb
+        files in "ccl:headers;foo;". You can then do
+        </p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          ? (use-interface-dir :foo)
+	    </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml"> 
+	    whenever you need to
+        access the foreign type information in those database
+        files.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Using-Shared-Libraries"></a>12.6.Â Using Shared Libraries</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Shared-Library-Overview"></a>12.6.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> provides facilities to open and close shared
+        libraries.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">"Opening" a shared library, which is done with <a class="xref" href="#f_open-shared-library" title="Function OPEN-SHARED-LIBRARY"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">open-shared-library</b></a>, maps the library's code and
+        data into <code class="literal">CCL</code>'s address space and makes its exported
+        symbols accessible to <code class="literal">CCL</code>.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">"Closing" a shared library, which is done with <a class="xref" href="#f_close-shared-library" title="Function CLOSE-SHARED-LIBRARY"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">close-shared-library</b></a>, unmaps the library's code
+        and and removes the library's symbols from the global
+        namespace.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A small number of shared libraries (including libc,
+        libm, libdl under Linux, and the "system" library under
+        Darwin) are opened by the lisp kernel and can't be
+        closed.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> uses data structures of type
+        EXTERNAL-ENTRY-POINT to map a foreign function name (string)
+        to that foreign function's <span class="emphasis"><em>current</em></span>
+        address. (A function's address may vary from session to
+        session as different versions of shared libraries may load at
+        different addresses; it may vary within a session for similar
+        reasons.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">An EXTERNAL-ENTRY-POINT whose address is known is said
+        to be <span class="emphasis"><em>resolved</em></span>. When an external entry
+        point is resolved, the shared library which defines that entry
+        point is noted; when a shared library is closed, the entry
+        points that it defines are made unresolved.  An
+        EXTERNAL-ENTRY-POINT must be in the resolved state in order to
+        be FF-CALLed; calling an unresolved entry point causes a "last
+        chance" attempt to resolve it. Attempting to resolve an
+        entrypoint that was defined in a closed library will cause an
+        attempt to reopen that library.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> keeps track of all libraries that have been
+        opened in a lisp session. When a saved application is first
+        started, an attempt is made to reopen all libraries that were
+        open when the image was saved, and an attempt is made to
+        resolve all entry points that had been referenced when the
+        image was saved. Either of these attempts can fail "quietly",
+        leaving some entry points in an unresolved state.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Linux shared libraries can be referred to either by a
+        string which describes their full pathname or by their
+        <span class="emphasis"><em>soname</em></span>, a shorter string that can be
+        defined when the library is created. The dynamic linker
+        mechanisms used in Linux make it possible (through a series of
+        filesystem links and other means) to refer to a library via
+        several names; the library's soname is often the most
+        appropriate identifier.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">so names are often less version-specific than other names
+        for libraries; a program that refers to a library by the name
+        "libc.so.6" is more portable than one which refers to
+        "libc-2.1.3.so" or to "libc-2.2.3.so", even though the latter
+        two names might each be platform-specific aliases of the
+        first.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">All of the global symbols described below are exported
+        from the CCL package.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Limitations-and-known-bugs--1-"></a>12.6.2.Â Limitations and known bugs</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>Don't get me started.</p>
+                </li>
+                <li>
+                  <p>The underlying functionality has a poor notion of
+	        dependency;it's not always possible to open libraries that
+	        depend on unopened libraries, but it's possible to close
+	        libraries on which other libraries depend. It
+	        <span class="emphasis"><em>may</em></span> be possible to generate
+	        more explicit dependency information by parsing the output
+	        of the Linux ldd and ldconfig programs.</p>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Darwin-Notes"></a>12.6.3.Â &gt;Darwin Notes</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Darwin shared libraries come in two (basic) flavors:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>"dylibs" (which often have the extension".dylib") are
+	        primarily intended to be linked against at compile/link
+	        time. They can be loaded dynamically,<span class="emphasis"><em>but can't
+	        be unloaded</em></span>. Accordingly,OPEN-SHARED-LIBRARY
+	        can be used to open a .dylib-style library;calling
+	        CLOSE-SHARED-LIBRARY on the result of such a call produces
+	        a warning, and has no other effect. It appears that (due
+	        to an OS bug) attempts to open .dylib shared-libraries
+	        that are already open can cause memory corruption unless
+	        the full pathname of the .dylib file is specified on the
+	        first and all subsequent calls.</p>
+                </li>
+                <li>
+                  <p>"bundles" are intended to serve as application
+	        extensions; they can be opened multiple times (creating
+	        multiple instances of the library!) and closed
+	        properly.</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Thanks to Michael Klingbeil for getting both kinds of
+        Darwin shared libraries working in <code class="literal">CCL</code>.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="The-Interface-Translator"></a>12.7.Â The Interface Translator</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Interface-translator-overview"></a>12.7.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> uses an interface translation system based on the FFIGEN
+	    system, which is described at
+	    <a class="ulink" href="http://www.ccs.neu.edu/home/lth/ffigen/" target="_top">this page</a>
+	    The interface translator makes
+	    the constant, type, structure, and function definitions in a set of
+	    C-language header files available to lisp code.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The basic idea of the FFIGEN scheme is to use the C
+        compiler's frontend and parser to translate .h files into
+        semantically equivalent .ffi files, which represent the
+        definitions from the headers using a syntax based on
+        S-expressions.  Lisp code can then concentrate on the .ffi
+        representation, without having to concern itself with the
+        semantics of header file inclusion or the arcana of C
+        parsing.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The original FFIGEN system used a modified version of
+        the LCC C compiler to produce .ffi files. Since many OS
+        header files contain GCC-specific constructs, <code class="literal">CCL</code>'s
+        translation system uses a modified version of GCC (called,
+        somewhat confusingly, ffigen.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">See <a class="ulink" href="http://trac.clozure.com/openmcl/wiki/BuildFFIGEN" target="_top">
+	here</a> for information on building and installing ffigen.
+	</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A component shell script called h-to-ffi.sh reads a
+        specified .h file (and optional preprocessor arguments) and writes
+         a (hopefully) equivalent .ffi file to standard output, calling 
+        the ffigen program with appropriate  arguments.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">For each interface directory (see FIXTHIS)
+        <span class="emphasis"><em>subdir</em></span> distributed with <code class="literal">CCL</code>, a shell
+        script (distributed with <code class="literal">CCL</code> as
+        "ccl:headers;<span class="emphasis"><em>subdir</em></span>;C;populate.sh"
+        (or some other platform-specific headers directory)
+        calls h-to-ffi.sh on a large number of the header
+        files in /usr/include (or some other <span class="emphasis"><em>system header
+          path</em></span>) and creates a parallel directory tree in
+        "ccl:headers;<span class="emphasis"><em>subdir</em></span>;C;<span class="emphasis"><em>system</em></span>;<span class="emphasis"><em>header</em></span>;<span class="emphasis"><em>path</em></span>;"
+        (or
+        "ccl:darwin-headers;<span class="emphasis"><em>subdir</em></span>;C;<span class="emphasis"><em>system</em></span>;<span class="emphasis"><em>header</em></span>;<span class="emphasis"><em>path</em></span>;", etc.),
+        populating that directory with .ffi files.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A lisp function defined in "ccl:library;parse-ffi.lisp"
+        reads the .ffi files in a specified interface directory
+        <span class="emphasis"><em>subdir</em></span> and generates new versions of the
+        databases (files with the extension .cdb).</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The CDB databases are used by the #$ and #_ reader
+        macros and are used in the expansion of RREF, RLET, and
+        related macros.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Details--rebuilding-the-CDB-databases--step-by-step"></a>12.7.2.Â Details: rebuilding the CDB databases, step by step</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>Ensure that the FFIGEN program is installed. See
+	        the"README" file generated during the FFIGEN build process for
+	        specific installation instructions.This example assumes
+	        LinuxPPC; for other platforms, substitute the appropriate
+		headers directory. </p>
+                </li>
+                <li>
+                  <p>Edit the
+	        "ccl:headers;<span class="emphasis"><em>subdir</em></span>;C;populate.sh"shell
+	        script. When you're confident that the files
+	        and preprocessor options match your environment, cd to
+	        the"ccl:headers;<span class="emphasis"><em>subdir</em></span>;C;" directory
+	        and invoke ./populate.sh. Repeat this step until you're
+	        able to cleanly translate all files referenced in the shell
+	        script.</p>
+                </li>
+                <li>
+                  <p>Run <code class="literal">CCL</code>:
+            </p>
+                  <pre class="programlisting">
+              ? (require "PARSE-FFI")
+              PARSE-FFI
+
+              ? (ccl::parse-standard-ffi-files :SUBDIR)
+              ;;; lots of output ... after a while, shiny new .cdb files should
+              ;;; appear in "ccl:headers;subdir;"
+          </pre>
+                  <p>It may be necessary to call CCL::PARSE-STANDARD-FFI-FILES
+                  twice, to ensure that forward-references are resolved </p>
+                </li>
+              </ol>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Case-sensitivity-of-foreign-names-in-CCL"></a>12.8.Â Case-sensitivity of foreign names in <code class="literal">CCL</code></h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Case-sensitivity-overview"></a>12.8.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">As of release 0.11, <code class="literal">CCL</code> addresses the fact that
+	    foreign type, constant, record, field, and function nams are
+	    case-sensitive and provides mechanisms to refer to these names
+	    via lisp symbols.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Previous versions of <code class="literal">CCL</code> have tried to ignore that
+        fact, under the belief that case conflicts were rare and that
+        many users (and implementors) would prefer not to deal with
+        case-related issues. The fact that some information in the
+        interface databases was incomplete or inaccessible because of
+        this policy made it clearer that the policy was untenable. I
+        can't claim that the approach described here is aesthetically
+        pleasing, but I can honestly say that it's less unpleasant
+        than other approaches that I'd thought of. I'd be interested
+        to hear alternate proposals.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The issues described here have to do with how lisp
+        symbols are used to denote foreign functions, constants,
+        types, records, and fields. It doesn't affect how other lisp
+        objects are sometimes used to denote foreign objects. For
+        instance, the first argument to the EXTERNAL-CALL macros is
+        now and has always been a case-sensitive string.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Foreign-constant-and-function-names"></a>12.8.2.Â Foreign constant and function names</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The primary way of referring to foreign constant and
+        function names in <code class="literal">CCL</code> is via the #$ and #_ reader
+        macros. These reader macro functions each read a symbol into
+        the "OS" package, look up its constant or function definition
+        in the interface database, and assign the value of the
+        constant to the symbol or install a macroexpansion function on
+        the symbol.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In order to observe case-sensitivity, the reader-macros
+        now read the symbol with (READTABLE-CASE :PRESERVE) in
+        effect.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">This means that it's necessary to type the foreign
+        constant or function name in correct case, but it isn't
+        necessary to use any special escaping constructs when writing
+        the variable name. For instance:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+        (#_read fd buf n) ; refers to foreign symbol "read"
+        (#_READ fd buf n) ; refers to foreign symbol "READ", which may
+        ; not exist ...
+        #$o_rdonly ; Probably doesn't exist
+        #$O_RDONLY ; Exists on most platforms
+      </pre>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Foreign-type--record--and-field-names"></a>12.8.3.Â Foreign type, record, and field names</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Constructs like RLET expect a foreign type or record
+	    name to be denoted by a symbol (typically a keyword); RREF
+	    (and PREF) expect an "accessor" form, typically a keyword
+	    formed by concatenating a foreign type or record name with a
+	    sequence of one or more foreign field names, separated by
+	    dots. These names are interned by the reader as other lisp
+	    symbols are, with an arbitrary value of READTABLE-CASE in
+	    effect (typically :UPCASE.) It seems like it would be very
+	    tedious to force users to manually escape (via vertical bar or
+	    backslash syntax) all lowercase characters in symbols used to
+	    specify foreign type, record, and field names (especially
+	    given that many traditional POSIX structure, type, and field
+	    names are entirely lowercase.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The approach taken by <code class="literal">CCL</code> is to allow the symbols
+        (keywords) used to denote foreign type, record, and field
+        names to contain angle brackets (<code class="literal">&lt;</code> and
+        <code class="literal">&gt;</code>). Such symbols are translated to
+	    foreign names via the following set of conventions:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>All instances of &lt; and &gt; in the symbol's pname
+	        are balanced and don't nest.</p>
+                </li>
+                <li>
+                  <p>Any alphabetic characters in the symbol's pname
+	        that aren't enclosed in angle brackets are treated as
+	        lower-case,regardless of the value of READTABLE-CASE and
+	        regardless of the case in which they were written.</p>
+                </li>
+                <li>
+                  <p>Alphabetic characters that appear within angle
+	        brackets are mapped to upper-case, again regardless of how
+	        they were written or interned.</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">There may be many ways of "escaping" (with angle
+	    brackets) sequences of upper-case and non-lower-case
+	    characters in a symbol used to denote a foreign name. When
+	    translating in the other direction, <code class="literal">CCL</code> always escapes the
+	    longest sequence that starts with an upper-case character and
+	    doesn't contain a lower-case character.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's often preferable to use this canonical form of a
+        foreign type name.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The accessor forms used by PREF/RREF should be viewed as
+        a series of foreign type/record and field names; upper-case
+        sequences in the component names should be escaped with angle
+        brackets, but those sequences shouldn't span components. (More
+        simply, the separating dots shouldn't be enclosed, even if
+        both surrounding characters need to be.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Older POSIX code tends to use lower-case exclusively for
+        type, record, and field names; there are only a few cases in
+        the <code class="literal">CCL</code> sources where mixed-case names need to be
+        escaped.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Examples--1-"></a>12.8.4.Â Examples</h3>
+                </div>
+              </div>
+            </div>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+        ;;; Allocate a record of type "window".
+        (rlet ((w :window)) ...)
+        ;;; Allocate a record of type "Window", which is probably a
+        ;;;  different type
+        (rlet ((w :&lt;w&gt;indow)) ...)
+        ;;; This is equivalent to the last example
+        (rlet ((w :&lt;w&gt;INDOW)))
+      </pre>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Reading-Foreign-Names"></a>12.9.Â Reading Foreign Names</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code>
+      provides several reader macros to make it more convenient to
+      handle foreign type, function, variable, and constant
+      names. Each of these reader macros reads symbols preserving the
+      case of the source text, and selects an appropriate package in
+      which to intern the resulting symbol. These reader macros are
+      especially useful when your Lisp code interacts extensively with
+      a foreign libraryâfor example, when using Mac OS X's Cocoa
+      frameworks.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">These reader macros include "#_" to read foreign function
+      names, "#&amp;" to read foreign variable names (note that in
+      earlier versions of OpenMCL the reader macro "#?" was used for
+      this same purpose), "#$" to read foreign constant names, "#/" to
+      read the names of foreign Objective-C methods, and "#&gt;" to read
+      keywords that can be used as the names of types, records, and
+      accessors.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">All of these reader macros preserve the case of the text
+      that they read; beyond that similarity, each performs some
+      additional work, unique to each reader macro, to create symbols
+      suitable for a particular use. For example, the function,
+      variable, and constant reader macros intern the resulting symbol
+      in the "OS" package of the running platform, but the reader
+      macro for Objective-C method names interns symbols in the
+      "NEXTSTEP-FUNCTIONS" package.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">You are likely to see these reader macros used extensively
+      in Lisp code that works with foreign libraries; for example,
+      <code class="literal">CCL</code> IDE code, which defines numerous Objective-C classes
+      and methods, uses these reader macros extensively.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For more detailed descriptions of each of these reader
+      macros, see the Foreign-Function-Interface Dictionary
+      section.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Tutorial--Using-Basic-Calls-and-Types"></a>12.10.Â Tutorial: Using Basic Calls and Types</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">This tutorial is meant to cover the basics of <code class="literal">CCL</code> for
+      calling external C functions and passing data back and forth.
+      These basics will provide the foundation for more advanced
+      techniques which will allow access to the various external
+      libraries and toolkits.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The first step is to start with a simple C dynamic library
+      in order to actually observe what is actually passing between
+      <code class="literal">CCL</code> and C.  So, some C code is in order:</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Create the file typetest.c, and put the following code
+      into it:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+#include &lt;stdio.h&gt;
+
+void
+void_void_test(void)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+}
+
+signed char
+sc_sc_test(signed char data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %d\n", (signed int)data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+unsigned char
+uc_uc_test(unsigned char data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %d\n", (signed int)data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">This defines three functions.  If you're familiar with C,
+      notice that there's no <code class="literal">main()</code>, because we're
+      just building a library, not an executable.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The function <code class="literal">void_void_test()</code> doesn't
+      take any parameters, and doesn't return anything, but it prints
+      two lines to let us know it was called.
+      <code class="literal">sc_sc_test()</code> takes a signed char as a
+      parameter, prints it, and returns it.
+      <code class="literal">uc_uc_test()</code> does the same thing, but with an
+      unsigned char.  Their purpose is just to prove to us that we
+      really can call C functions, pass them values, and get values
+      back from them.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This code is compiled into a dynamic library on OS X
+      10.3.4 with the command:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      gcc -dynamiclib -Wall -o libtypetest.dylib typetest.c \
+      -install_name ./libtypetest.dylib
+    </pre>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="tip" style="margin-left: 0.5in; margin-right: 0.5in;">
+            <h3 class="title">Tip</h3>
+            <p>Users of 64-bit platforms may need to pass options such
+        as "-m64" to gcc, may need to give the output library a different
+        extension (such as ".so"), and may need to user slightly different
+        values for other options in order to create an equivalent test
+        library.</p>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The -dynamiclib tells gcc that we will be compiling this
+      into a dynamic library and not an executable binary program.
+      The output filename is "libtypetest.dylib".  Notice that we
+      chose a name which follows the normal OS X convention, being in
+      the form "libXXXXX.dylib", so that other programs can link to
+      the library.  <code class="literal">CCL</code> doesn't need it to be this way, but it is
+      a good idea to adhere to existing conventions.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The -install_name flag is primarily used when building OS
+      X "bundles".  In this case, we are not using it, so we put a
+      placeholder into it, "./libtypetest.dylib".  If we wanted to use
+      typetest in a bundle, the -install_name argument would be a
+      relative path from some "current" directory.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">After creating this library, the first step is to tell
+      <code class="literal">CCL</code> to open the dynamic library.  This is done by calling
+      .</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      Welcome to <code class="literal">CCL</code> Version (Beta: Darwin) 0.14.2-040506!
+
+      ? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
+      #&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">You should use an absolute path here; using a relative
+      one, such as just "libtypetest.dylib", would appear to work, but
+      there are subtle problems which occur after reloading it.  See
+      the Darwin notes on for details.  It would be a bad idea anyway,
+      because software should never rely on its starting directory
+      being anything in particular.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This command returns a reference to the opened shared library, and
+      <code class="literal">CCL</code> also adds one to the global variable
+      <code class="literal">ccl::*shared-libraries*</code>:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? ccl::*shared-libraries*
+      (#&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E&gt;
+       #&lt;SHLIB /usr/lib/libSystem.B.dylib #x606179E&gt;)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Before we call anything, let's check that the individual
+      functions can actually be found by the system.  We don't have to
+      do this, but it helps to know how to find out whether this is
+      the problem, when something goes wrong.  We use <a class="xref" href="#m_external-call" title="Macro EXTERNAL-CALL"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">external-call</b></a>:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external "_void_void_test")
+      #&lt;EXTERNAL-ENTRY-POINT "_void_void_test" (#x000CFDF8) /Users/andewl/openmcl/libtypetest.dylib #x638EDF6&gt;
+
+      ? (external "_sc_sc_test")
+      #&lt;EXTERNAL-ENTRY-POINT "_sc_sc_test" (#x000CFE50) /Users/andewl/openmcl/libtypetest.dylib #x638EB3E&gt;
+
+      ? (external "_uc_uc_test")
+      #&lt;EXTERNAL-ENTRY-POINT "_uc_uc_test" (#x000CFED4) /Users/andewl/openmcl/libtypetest.dylib #x638E626&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Notice that the actual function names have been "mangled"
+      by the C linker.  The first function was named "void_void_test"
+      in typetest.c, but in libtypetest.dylib, it has an underscore (a
+      "_" symbol) before it: "_void_void_test".  So, this is the name
+      which you have to use.  The mangling - the way the name is
+      changed - may be different for other operating systems or other
+      versions, so you need to "just know" how it's done...</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Also, pay particular attention to the fact that a
+      hexadecimal value appears in the EXTERNAL-ENTRY-POINT.
+      (#x000CFDF8, for example - but what it is doesn't matter.)
+      These hex numbers mean that the function can be dereferenced.
+      Functions which aren't found will not have a hex number.  For
+      example:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external "functiondoesnotexist")
+      #&lt;EXTERNAL-ENTRY-POINT "functiondoesnotexist" {unresolved}  #x638E3F6&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The "unresolved" tells us that <code class="literal">CCL</code> wasn't able to find this
+      function, which means you would get an error, "Can't resolve foreign
+      symbol," if you tried to call it.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">These external function references also are stored in a
+      hash table which is accessible through a global variable,
+      <code class="literal">ccl::*eeps*</code>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">At this point, we are ready to try our first external
+      function call:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external-call "_void_void_test" :void)
+      Entered void_void_test:
+      Exited  void_void_test:
+      NIL
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">We used , which is is the normal mechanism for accessing
+      externally linked code.  The "_void_void_test" is the mangled
+      name of the external function.  The :void refers to the return
+      type of the function.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The next step is to try passing a value to C, and getting one
+      back:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external-call "_sc_sc_test" :signed-byte -128 :signed-byte)
+      Entered sc_sc_test:
+      Data In: -128
+      Exited  sc_sc_test:
+      -128
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The first :signed-byte gives the type of the first
+      argument, and then -128 gives the value to pass for it.  The
+      second :signed-byte gives the return type.  The return type is
+      always given by the last argument to .</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Everything looks good.  Now, let's try a number outside
+      the range which fits in one byte:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external-call "_sc_sc_test" :signed-byte -567 :signed-byte)
+      Entered sc_sc_test:
+      Data In: -55
+      Exited  sc_sc_test:
+      -55
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Hmmmm.  A little odd.  Let's look at the unsigned stuff to
+      see how it reacts:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external-call "_uc_uc_test" :unsigned-byte 255 :unsigned-byte)
+      Entered uc_uc_test:
+      Data In: 255
+      Exited  uc_uc_test:
+      255
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">That looks okay.  Now, let's go outside the valid range again:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external-call "_uc_uc_test" :unsigned-byte 567 :unsigned-byte)
+      Entered uc_uc_test:
+      Data In: 55
+      Exited  uc_uc_test:
+      55
+
+      ? (external-call "_uc_uc_test" :unsigned-byte -567 :unsigned-byte)
+      Entered uc_uc_test:
+      Data In: 201
+      Exited  uc_uc_test:
+      201
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Since a signed byte can only hold values from -128 through 127, and
+      an unsigned one can only hold values from 0 through 255, any number
+      outside that range gets "clipped": only the low eight bits of it
+      are used.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">What is important to remember is that <span class="emphasis"><em>external
+        function calls have
+        very few safety checks.</em></span>
+      Data outside the valid range for its type will silently do
+      very strange things; pointers outside the valid range can very well
+      crash the system.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">That's it for our first example library.  If you're still
+      following along, let's add some more C code to look at the rest
+      of the primitive types.  Then we'll need to recompile the
+      dynamic library, load it again, and then we can see what
+      happens.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Add the following code to typetest.c:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+int
+si_si_test(int data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %d\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+long
+sl_sl_test(long data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %ld\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+long long
+sll_sll_test(long long data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %lld\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+float
+f_f_test(float data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %e\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+double
+d_d_test(double data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %e\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The command line to compile the dynamic library is the same as before:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      gcc -dynamiclib -Wall -o libtypetest.dylib typetest.c \
+      -install_name ./libtypetest.dylib
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Now, restart <code class="literal">CCL</code>.  This step is required because
+      <code class="literal">CCL</code> cannot close and reload a dynamic library on OS
+      X.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Have you restarted?  Okay, try out the new code:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      Welcome to <code class="literal">CCL</code> Version (Beta: Darwin) 0.14.2-040506!
+
+      ? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
+      #&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E&gt;
+
+      ? (external-call "_si_si_test" :signed-fullword -178965 :signed-fullword)
+      Entered si_si_test:
+      Data In: -178965
+      Exited  si_si_test:
+      -178965
+
+      ? ;; long is the same size as int on 32-bit machines.
+      (external-call "_sl_sl_test" :signed-fullword -178965 :signed-fullword)
+      Entered sl_sl_test:
+      Data In: -178965
+      Exited  sl_sl_test:
+      -178965
+
+      ? (external-call "_sll_sll_test"
+      :signed-doubleword -973891578912 :signed-doubleword)
+      Entered sll_sll_test:
+      Data In: -973891578912
+      Exited  sll_sll_test:
+      -973891578912
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Okay, everything seems to be acting as expected.  However,
+      just to remind you that most of this stuff has no safety net,
+      here's what happens if somebody mistakes
+      <code class="literal">sl_sl_test()</code> for
+      <code class="literal">sll_sll_test()</code>, thinking that a long is
+      actually a doubleword:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      ? (external-call "_sl_sl_test"
+      :signed-doubleword -973891578912 :signed-doubleword)
+      Entered sl_sl_test:
+      Data In: -227
+      Exited  sl_sl_test:
+      -974957576192
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Ouch.  The C function changes the value with no warning
+      that something is wrong.  Even worse, it manages to pass the
+      original value back to <code class="literal">CCL</code>, which hides the fact that
+      something is wrong.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Finally, let's take a look at doing this with
+      floating-point numbers.</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+
+      Welcome to <code class="literal">CCL</code> Version (Beta: Darwin) 0.14.2-040506!
+
+      ? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
+      #&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E&gt;
+
+      ? (external-call "_f_f_test" :single-float -1.256791e+11 :single-float)
+      Entered f_f_test:
+      Data In: -1.256791e+11
+      Exited  f_f_test:
+      -1.256791E+11
+
+      ? (external-call "_d_d_test" :double-float -1.256791d+290 :double-float)
+      Entered d_d_test:
+      Data In: -1.256791e+290
+      Exited  d_d_test:
+      -1.256791D+290
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Notice that the number ends with "...e+11" for the single-float,
+      and "...d+290" for the
+      double-float.  Lisp has both of these float types itself, and the
+      d instead of the e is how you specify which to create.  If
+      you tried to pass :double-float 1.0e2 to external-call, Lisp would
+      be nice enough to notice and give you a type error.  Don't get the
+      :double-float wrong, though, because then there's no protection.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Congratulations!  You now know how to call external C functions from
+      within <code class="literal">CCL</code>, and pass numbers back and forth.  Now that the basic
+      mechanics of calling and passing work, the next step is to examine how
+      to pass more complex data structures around.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Acknowledgement"></a>12.10.1.Â Acknowledgement</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">This chapter was generously contributed by Andrew
+	    P. Lentvorski Jr.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap"></a>12.11.Â Tutorial: Allocating Foreign Data on the Lisp Heap </h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Not every foreign function is so marvelously easy to use
+      as the ones we saw in the last section.  Some functions require
+      you to allocate a C struct, fill it with your own
+      information, and pass in a pointer to that struct.  Some of them
+      require you to allocate an empty struct that they will fill in
+      so that you can read the information out of it.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">There are generally two ways to allocate foreign data.  The
+    first way is to allocate it on the stack; the RLET macro is one way to do this.
+    This is analogous to using automatic variables in C.  In the
+    jargon of Common Lisp, data allocated this way is said to have
+    dynamic extent.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The other way to heap-allocate the foreign data.  This is
+    analogous to calling malloc in C.  Again in the jargon of Common
+    Lisp, heap-allocated data is said to have indefinite extent. If a
+    function heap-allocates some data, that data remains valid even
+    after the function itself exits.  This is useful for data which
+    may need to be passed between multiple C calls or multiple
+    threads. Also, some data may be too large to copy multiple times
+    or may be too large to allocate on the stack.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The big disadvantage to allocating data on the heap is
+      that it must be explicitly deallocatedâyou need to "free" it
+      when you're done with it.  Normal Lisp objects, even those with indefinite
+      extent, are deallocated by the garbage collector when it can prove
+      that they're no longer referenced.  Foreign data, though, is outside the
+      GC's ken:  it has no way to know whether a blob of foreign data is still
+      referenced by foreign code or not. It is thus up to the programmer
+      to manage it manually, just as one
+      does in C with malloc and free.
+    </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">What that means is that, if you allocate something and
+      then lose track of the pointer to it, there's no way to ever
+      free that memory.  That's what's called a memory leak, and if
+      your program leaks enough memory it will eventually use up all
+      of it!  So, you need to be careful to not lose your
+      pointers.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">That disadvantage, though, is also an advantage for using
+      foreign functions.  Since the garbage collector doesn't know
+      about this memory, it will never move it around.  External C
+      code needs this, because it doesn't know how to follow it to
+      where it moved, the way that Lisp code does.  If you allocate
+      data manually, you can pass it to foreign code and know that no
+      matter what that code needs to do with it, it will be able to,
+      until you deallocate it.  Of course, you'd better be sure it's
+      done before you do.  Otherwise, your program will be unstable
+      and might crash sometime in the future, and you'll have trouble
+      figuring out what caused the trouble, because there won't be
+      anything pointing back and saying "you deallocated this too
+      soon."</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">And, so, on to the code...</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">As in the last tutorial, our first step
+      is to create a local dynamic library in order to help show
+      what is actually going on between <code class="literal">CCL</code> and C.  So, create the file
+      ptrtest.c, with the following code:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+#include &lt;stdio.h&gt;
+
+void reverse_int_array(int * data, unsigned int dataobjs)
+{
+    int i, t;
+    
+    for(i=0; i&lt;dataobjs/2; i++)
+        {
+            t = *(data+i);
+            *(data+i) = *(data+dataobjs-1-i);
+            *(data+dataobjs-1-i) = t;
+        }
+}
+
+void reverse_int_ptr_array(int **ptrs, unsigned int ptrobjs)
+{
+    int *t;
+    int i;
+    
+    for(i=0; i&lt;ptrobjs/2; i++)
+        {
+            t = *(ptrs+i);
+            *(ptrs+i) = *(ptrs+ptrobjs-1-i);
+            *(ptrs+ptrobjs-1-i) = t;
+        }
+}
+
+void
+reverse_int_ptr_ptrtest(int **ptrs)
+{
+    reverse_int_ptr_array(ptrs, 2);
+    
+    reverse_int_array(*(ptrs+0), 4);
+    reverse_int_array(*(ptrs+1), 4);
+}
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">This defines three functions.
+      <code class="literal">reverse_int_array</code> takes a pointer to an array
+      of <code class="literal">int</code>s, and a count telling how many items
+      are in the array, and loops through it putting the elements in
+      reverse.  <code class="literal">reverse_int_ptr_array</code> does the same
+      thing, but with an array of pointers to <code class="literal">int</code>s.
+      It only reverses the order the pointers are in; each pointer
+      still points to the same thing.
+      <code class="literal">reverse_int_ptr_ptrtest</code> takes an array of
+      pointers to arrays of <code class="literal">int</code>s.  (With me?)  It
+      doesn't need to be told their sizes; it just assumes that the
+      array of pointers has two items, and that both of those are
+      arrays which have four items.  It reverses the array of
+      pointers, then it reverses each of the two arrays of
+      <code class="literal">int</code>s.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Now, compile ptrtest.c into a dynamic library using the
+      command:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      gcc -dynamiclib -Wall -o libptrtest.dylib ptrtest.c -install_name ./libptrtest.dylib
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The function <code class="literal">make-heap-ivector</code> is the
+      primary tool for allocating objects in heap memory.  It
+      allocates a fixed-size <code class="literal">CCL</code> object in heap memory.  It
+      returns both an array reference, which can be used directly from
+      <code class="literal">CCL</code>, and a <code class="literal">macptr</code>, which can be used to
+      access the underlying memory directly.  For example:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? ;; Create an array of 3 4-byte-long integers
+      (multiple-value-bind (la lap)
+          (make-heap-ivector 3 '(unsigned-byte 32))
+        (setq a la)
+        (setq ap lap))
+      ;Compiler warnings :
+      ;   Undeclared free variable A, in an anonymous lambda form.
+      ;   Undeclared free variable AP, in an anonymous lambda form.
+      #&lt;A Mac Pointer #x10217C&gt;
+
+      ? a
+      #(1396 2578 97862649)
+
+      ? ap
+      #&lt;A Mac Pointer #x10217C&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">It's important to realize that the contents of the
+      <code class="literal">ivector</code> we've just created haven't been
+      initialized, so their values are unpredictable, and you should
+      be sure not to read from them before you set them, to avoid
+      confusing results.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">At this point, <code class="literal">a</code> references an object
+      which works just like a normal array.  You can refer to any item
+      of it with the standard <code class="literal">aref</code> function, and
+      set them by combining that with <code class="literal">setf</code>.  As
+      noted above, the <code class="literal">ivector</code>'s contents haven't
+      been initialized, so that's the next order of business:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? a
+      #(1396 2578 97862649)
+
+      ? (aref a 2)
+      97862649
+
+      ? (setf (aref a 0) 3)
+      3
+
+      ? (setf (aref a 1) 4)
+      4
+
+      ? (setf (aref a 2) 5)
+      5
+
+      ? a
+      #(3 4 5)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">In addition, the <code class="literal">macptr</code> allows direct
+      access to the same memory:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? (setq *byte-length-of-long* 4)
+      4
+
+      ? (%get-signed-long ap (* 2 *byte-length-of-long*))
+      5
+
+      ? (%get-signed-long ap (* 0 *byte-length-of-long*))
+      3
+
+      ? (setf (%get-signed-long ap (* 0 *byte-length-of-long*)) 6)
+      6
+
+      ? (setf (%get-signed-long ap (* 2 *byte-length-of-long*)) 7)
+      7
+
+      ? ;; Show that a actually got changed through ap
+      a
+      #(6 4 7)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">So far, there is nothing about this object that could not
+      be done much better with standard Lisp.  However, the
+      <code class="literal">macptr</code> can be used to pass this chunk of
+      memory off to a C function.  Let's use the C code to reverse the
+      elements in the array:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? ;; Insert the full path to your copy of libptrtest.dylib
+      (open-shared-library "/Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib")
+      #&lt;SHLIB /Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib #x639D1E6&gt;
+
+      ? a
+      #(6 4 7)
+
+      ? ap
+      #&lt;A Mac Pointer #x10217C&gt;
+
+      ? (external-call "_reverse_int_array" :address ap :unsigned-int (length a) :address)
+      #&lt;A Mac Pointer #x10217C&gt;
+
+      ? a
+      #(7 4 6)
+
+      ? ap
+      #&lt;A Mac Pointer #x10217C&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The array gets passed correctly to the C function,
+      <code class="literal">reverse_int_array</code>.  The C function reverses
+      the contents of the array in-place; that is, it doesn't make a
+      new array, just keeps the same one and reverses what's in it.
+      Finally, the C function passes control back to <code class="literal">CCL</code>.  Since
+      the allocated array memory has been directly modified, <code class="literal">CCL</code>
+      reflects those changes directly in the array as well.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">There is one final bit of housekeeping to deal with.
+      Before moving on, the memory needs to be deallocated:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? (dispose-heap-ivector a ap)
+      NIL
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The <code class="literal">dispose-heap-ivector</code> macro actually
+      deallocates the ivector, releasing its memory into the heap for
+      something else to use.  Both <code class="literal">a</code> and <code class="literal">ap</code>
+      now have undefined values.
+      </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When do you call <code class="literal">dispose-heap-ivector</code>?
+      Anytime after you know the ivector will never be used again, but
+      no sooner.  If you have a lot of ivectors, say, in a hash table,
+      you need to make sure that when whatever you were doing with the
+      hash table is done, those ivectors all get freed.  Unless
+      there's still something somewhere else which refers to them, of
+      course!  Exactly what strategy to take depends on the situation,
+      so just try to keep things simple unless you know better.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The simplest situation is when you have things set up so
+      that a Lisp object "encapsulates" a pointer to foreign data,
+      taking care of all the details of using it.  In this case, you
+      don't want those two things to have different lifetimes: You
+      want to make sure your Lisp object exists as long as the foreign
+      data does, and no longer; and you want to make sure the foreign
+      data doesn't get deallocated while your Lisp object still refers
+      to it.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you're willing to accept a few limitations, you can
+      make this easy.  First, you can't let foreign code keep a
+      permanent pointer to the memory; it has to always finish what
+      it's doing, then return, and not refer to that memory again.
+      Second, you can't let any Lisp code that isn't part of your
+      encapsulating "wrapper" refer to the pointer directly.  Third,
+      nothing, either foreign code or Lisp code, should explicitly
+      deallocate the memory.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you can make sure all of these are true, you can at
+      least ensure that the foreign pointer is deallocated when the
+      encapsulating object is about to become garbage, by using
+      <code class="literal">CCL</code>'s nonstandard "termination" mechanism, which is
+      essentially the same as what Java and other languages call
+      "finalization".</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Termination is a way of asking the garbage collector to
+      let you know when it's about to destroy an object which isn't
+      used anymore.  Before destroying the object, it calls a function
+      which you write, called a terminator.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">So, you can use termination to find out when a particular
+      <code class="literal">macptr</code> is about to become garbage.  That's
+      not quite as helpful as it might seem: It's not exactly the same
+      thing as knowing that the block of memory it points to is
+      unreferenced.  For example, there could be another
+      <code class="literal">macptr</code> somewhere to the same block; or, if
+      it's a struct, there could be a <code class="literal">macptr</code> to one
+      of its fields.  Most problematically, if the address of that
+      memory has been passed to foreign code, it's sometimes hard to
+      know whether that code has kept the pointer.  Most foreign
+      functions don't, but it's not hard to think of
+      exceptions.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">You can use code such as this to make all this happen:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      (defclass wrapper (whatever)
+        ((element-type :initarg :element-type)
+         (element-count :initarg :element-count)
+         (ivector)
+         (macptr)))
+
+      (defmethod initialize-instance ((wrapper wrapper) <em class="varname">&amp;rest</em> initargs)
+        (declare (ignore initargs))
+        (call-next-method)
+        (ccl:terminate-when-unreachable wrapper)
+        (with-slots (ivector macptr element-type element-count) wrapper
+          (multiple-value-bind (new-ivector new-macptr)
+              (make-heap-ivector element-count element-type)
+            (setq ivector new-ivector
+                  macptr new-macptr))))
+
+      (defmethod ccl:terminate ((wrapper wrapper))
+        (with-slots (ivector macptr) wrapper
+          (when ivector
+            (dispose-heap-ivector ivector macptr)
+            (setq ivector nil
+                  macptr nil))))
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The <code class="literal">ccl:terminate</code> method will be called
+      on some arbitrary thread sometime (hopefully soon) after the GC
+      has decided that there are no strong references to an object
+      which has been the argument of a
+      <code class="literal">ccl:terminate-when-unreachable</code> call.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If it makes sense to say that the foreign object should
+      live as long as there's Lisp code that references it (through
+      the encapsulating object) and no longer, this is one way of doing
+      that.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Now we've covered passing basic types back and forth with
+      C, and we've done the same with pointers.  You may think this is
+      all...  but we've only done pointers to basic types.  Join us
+      next time for pointers... to pointers.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Acknowledgement--1-"></a>12.11.1.Â Acknowledgement</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Much of this chapter was generously contributed by
+	    Andrew P. Lentvorski Jr.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="id445662"></a>12.12.Â The Foreign-Function-Interface Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <a xmlns="http://www.w3.org/1999/xhtml" id="anchor_Foreign-Function-Interface-Dictionary"></a>
+          <p>
+            <div class="refentrytitle">
+              <a id="rm_sharpsign-underscore"></a>
+              <strong>[Reader Macro]</strong>
+              <br></br>
+              <code>#_</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id445700"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Reads a symbol from the current input stream, with *PACKAGE*
+	      bound to the "OS" package and with readtable-case preserved.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Does a lookup on that symbol in <a class="link" href="#The-Interface-Database" title="12.4.Â The Interface Database">the <code class="literal">CCL</code> interface
+	        database</a>, signalling an error if no foreign function
+	      information can be found for the symbol in any active <a class="link" href="#Using-Interface-Directories" title="12.5.Â Using Interface Directories">interface
+	        directory</a>.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Notes the foreign function information, including the foreign
+	      function's return type, the number and type of the foreign
+	      function's required arguments, and an indication of whether or
+	      not the function accepts additional arguments (via e.g., the
+	      "varargs" mechanism in C).</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Defines a macroexpansion function on the symbol, which expand
+	      macro calls involving the symbol into EXTERNAL-CALL forms where
+	      foreign argument type specifiers for required arguments and the
+	      return value specifer are provided from the information in the
+	      database.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the symbol.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The effect of these steps is that it's possible to call
+	      foreign functions that take fixed numbers of arguments by simply
+	      providing argument values, as in:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">(#_isatty fd)
+          (#_read fd buf n)</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">and to call foreign functions that take variable numbers of
+	      arguments by specifying the types of non-required args, as in:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">(with-cstrs ((format-string "the answer is: %d"))
+          (#_printf format-string :int answer))</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">You can query whether a given name is defined in the
+          interface databases by appending the '?' character to the reader
+          macro; for example:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          CL-USER&gt; #_?printf
+          T
+          CL-USER&gt; #_?foo
+          NIL
+        </pre>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="rm_sharpsign-ampersand"></a>
+              <strong>[Reader Macro]</strong>
+              <br></br>
+              <code>#&amp;</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id445806"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">In <code class="literal">CCL</code> 1.2 and later, the #&amp; reader macro can be used to
+	      access foreign variables; this functionality depends on the presence of
+	      "vars.cdb" files in the interface database. The current behavior
+	      of the #&amp; reader macro is to:</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Read a symbol from the current input stream, with *PACKAGE*
+	      bound to the "OS" package and with readtable-case preserved.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Use that symbol's pname to access the <code class="literal">CCL</code> interface
+	      database, signalling an error if no appropriate foreign variable
+	      information can be found with that name in any active interface
+	      directory.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Use type information recorded in the database to construct a
+	      form which can be used to access the foreign variable, and return
+	      that form.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Please note that the set of foreign variables declared in header files
+	      may or may not match the set of foreign variables exported from
+	      libraries (we're generally talking about C and Unix here ...). When
+	      they do match, the form constructed by the #&amp; reader macro manages the
+	      details of resolving and tracking changes to the foreign variable's
+	      address.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Future extensions (via prefix arguments to the reader macro) may
+	      offer additional behavior; it might be convenient (for instance) to be
+	      able to access the address of a foreign variable without dereferencing
+	      that address.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Foreign variables in C code tend to be platform- and
+	      package-specific (the canonical example - "errno" - is typically
+	      not a variable when threads are involved. )</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">In LinuxPPC, </p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">? #&amp;stderr</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">returns a pointer to the stdio error stream ("stderr" is a
+	      macro under OSX/Darwin).</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">On both LinuxPPC and DarwinPPC, </p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">? #&amp;sys_errlist</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">returns a pointer to a C array of C error message strings.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">You can query whether a given name is defined in the
+          interface databases by appending the '?' character to the reader
+          macro; for example:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          CL-USER&gt; #&amp;?sys_errlist
+          T
+          CL-USER&gt; #&amp;?foo
+          NIL
+        </pre>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="rm_sharpsign-dollarsign"></a>
+              <strong>[Reader Macro]</strong>
+              <br></br>
+              <code>#$</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id445924"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">In <code class="literal">CCL</code> 0.14.2 and later, the #? reader macro can be used
+	      to access foreign constants; this functionality depends on the
+	      presence of "constants.cdb" files in the interface
+	      database. The current behavior of the #$ reader macro is
+	      to:</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Read a symbol from the current input stream, with
+	      *PACKAGE* bound to the "OS" package and with
+	      readtable-case preserved.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Use that symbol's pname to access the <code class="literal">CCL</code> interface
+	      database, signalling an error if no appropriate foreign constant
+	      information can be found with that name in any active interface
+	      directory.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Use type information recorded in the database to construct a
+	      form which can be used to access the foreign constant, and return
+	      that form.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Please note that the set of foreign constants declared in
+	      header files may or may not match the set of foreign constants
+	      exported from libraries. When they do match, the form
+	      constructed by the #$ reader macro manages the details of
+	      resolving and tracking changes to the foreign constant's
+	      address.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">You can query whether a given name is defined in the
+          interface databases by appending the '?' character to the reader
+          macro; for example:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          CL-USER&gt; #$?SO_KEEPALIVE
+          T
+          CL-USER&gt; #$?foo
+          NIL
+        </pre>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="rm_sharpsign-slash"></a>
+              <strong>[Reader Macro]</strong>
+              <br></br>
+              <code>#/</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446006"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">In <code class="literal">CCL</code> 1.2 and later, the #/ reader macro can be used to
+	      access foreign functions on the Darwin platform. The current
+	      behavior of the #/ reader macro is to:</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Read a symbol from the current input stream, with
+	      *PACKAGE* bound to the "NEXTSTEP-FUNCTIONS" package, with
+	      readtable-case preserved, and with any colons included.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Do limited sanity-checking on the resulting symbol; for
+          example, any name that contains at least one colon is required
+          also to end with a colon, to conform to Objective-C
+          method-naming conventions.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Export the resulting symbol from the "NEXTSTEP-FUNCTIONS"
+          package and return it.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">For example, reading "#/alloc" interns and returns
+          NEXTSTEP-FUNCTIONS:|alloc|. Reading "#/initWithFrame:" interns
+          and returns NEXTSTEP-FUNCTIONS:|initWithFrame:|.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">A symbol read using this macro can be used as an operand
+          in most places where an Objective-C message name can be used, such as
+          in the (OBJ:@SELECTOR ...) construct.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Please note: the reader macro is not rigorous about
+          enforcing Objective-C method-naming conventions. Despite the
+          simple checking done by the reader macro, it may still be
+          possible to use it to construct invalid names.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The act of interning a new symbol in the
+          NEXTSTEP-FUNCTIONS package triggers an interface database lookup
+          of Objective-C methods with the corresponding message name.  If any
+          such information is found, a special type of dispatching
+          function is created and initialized and the new symbol is given
+          the newly-created dispatching function as its function
+          definition.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The dispatching knows how to call declared Objective-C methods
+          defined on the message. In many cases, all methods have the same
+          foreign type signature, and the dispatching function merely
+          passes any arguments that it receives to a function that does an
+          Objective-C message send with the indicated foreign argument and return
+          types. In other cases, where different Objective-C messages have
+          different type signatures, the dispatching function tries to
+          choose a function that handles the right type signature based on
+          the class of the dispatching function's first argument.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If new information about Objective-C methods is introduced
+          (e.g., by using additional interface files or as Objective-C
+          methods are defined from lisp), the dispatch function is
+          reinitialized to recognize newly-introduced foreign type
+          signatures.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The argument and result coercion that the bridge has
+          traditionally supported is supported by the new mechanism (e.g.,
+          :&lt;BOOL&gt; arguments can be specified as lisp booleans and :&lt;BOOL&gt;
+          results are returned as lisp boolean values, and an argument
+          value of NIL is coerced to a null pointer if the corresponding
+          argument type is :ID.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Some Objective-C methods accept variable numbers of
+          arguments; the foreign types of non-required arguments are
+          determined by the lisp types of those arguments (e.g., integers
+          are passed as integers, floats as floats, pointers as pointers,
+          record types by reference.)</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Examples:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          ;;; #/alloc is a known message.
+          ? #'#/alloc
+          #&lt;OBJC-DISPATCH-FUNCTION NEXTSTEP-FUNCTIONS:|alloc| #x300040E94EBF&gt;
+          ;;; Sadly, #/foo is not ...
+          ? #'#/foo
+          &gt; Error: Undefined function: NEXTSTEP-FUNCTIONS:|foo|
+
+          ;;; We can send an "init" message to a newly-allocated instance of
+          ;;; "NSObject" by:
+
+          (send (send ns:ns-object 'alloc) 'init)
+
+          ;;; or by
+
+          (#/init (#/alloc ns:ns-object))
+        </pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">Objective-C methods that "return" structures return them
+          as garbage-collectable pointers when called via dispatch
+          functions.  For example, if "my-window" is an NS:NS-WINDOW
+          instance, then</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          (#/frame my-window)
+        </pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">returns a garbage-collectable pointer to a structure that
+          describes that window's frame rectangle. This convention means
+          that there's no need to use SLET or special structure-returning
+          message send syntax; keep in mind, though, that #_malloc,
+          #_free, and the GC are all involved in the creation and eventual
+          destruction of structure-typed return values. In some programs
+          these operations may have an impact on performance.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="rm_sharpsign-greaterthan"></a>
+              <strong>[Reader Macro]</strong>
+              <br></br>
+              <code>#&gt;</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446146"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">In <code class="literal">CCL</code> 1.2 and later, the #&gt; reader macro reads
+          the following text as a keyword, preserving the case of the
+          text. For example:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          CL-USER&gt; #&gt;FooBar
+          :&lt;F&gt;OO&lt;B&gt;AR
+        </pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">The resulting keyword can be used as the name of foreign
+          types, records, and accessors.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_close-shared-library"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>close-shared-library</strong></span> library <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em>
+	      completely</code>
+            </div>
+            <div class="refentrytitle">Stops using a shared library, informing the operating
+	      system that it can be unloaded if appropriate.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446220"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">library</span></i>---either an object of type SHLIB, or a string which
+		        designates one by its so-name.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">completely</span></i>---a boolean.  The default is T.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446256"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">If <em class="varname">completely</em> is T, sets the
+	      reference count of <em class="varname">library</em> to 0.  Otherwise,
+	      decrements it by 1.  In either case, if the reference count
+	      becomes 0, <span class="function"><strong>close-shared-library</strong></span>
+	      frees all memory resources consumed <em class="varname">library</em>
+	      and
+	      causes any EXTERNAL-ENTRY-POINTs known to be defined by it to
+	      become unresolved.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_defcallback"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>defcallback</strong></span> name
+	      ({arg-type-specifier var}* <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> result-type-specifier)
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446332"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---A symbol which can be made into a special variable</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg-type-specifer</span></i>---One of the foreign argument-type keywords,
+		        described above, or an equivalent <a xmlns="http://www.w3.org/1999/xhtml" class="link" href="#Specifying-And-Using-Foreign-Types" title="12.1.Â Specifying And Using Foreign Types">foreign
+		          type specifier</a>.  In addition, if the keyword
+		        :WITHOUT-INTERRUPTS is specified, the callback will be
+		        executed with lisp interrupts disabled if the
+		        corresponding var is non-NIL. If :WITHOUT-INTERRUPTS
+		        is specified more than once, the rightmost instance
+		        wins.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">var</span></i>---A symbol (lisp variable), which will be bound to a
+		        value of the specified type.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---A sequence of lisp forms, which should return a value
+		        which can be coerced to the specified result-type.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446404"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Proclaims <em class="varname">name</em>
+	      to be a special variable; sets its value to a
+	      MACPTR which, when called by foreign code, calls a lisp function
+	      which expects foreign arguments of the specified types and which
+	      returns a foreign value of the specified result type. Any argument
+	      variables which correspond to foreign arguments of type :ADDRESS
+	      are bound to stack-allocated MACPTRs.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If <em class="varname">name</em>
+	      is already a callback function pointer, its value is
+	      not changed; instead, it's arranged
+	      that an
+	      updated version of the lisp callback function will be called.
+	      This feature allows for callback functions to be redefined
+	      incrementally, just like Lisp functions are.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml"><span class="function"><strong>defcallback</strong></span>
+	      returns the callback pointer, e.g., the
+	      value of <em class="varname">name</em>.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_def-foreign-type"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>def-foreign-type</strong></span> name foreign-type-spec
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446483"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---NIL or a keyword; the keyword may contain
+		        <a xmlns="http://www.w3.org/1999/xhtml" class="link" href="#Case-sensitivity-of-foreign-names-in-CCL" title="12.8.Â Case-sensitivity of foreign names in CCL">escaping constructs</a>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">foreign-type-spec</span></i>---A foreign type specifier, whose syntax is (loosely)
+		        defined above.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446524"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">If name is non-NIL, defines name to be an alias for the
+	      foreign type specified by foreign-type-spec. If foreign-type-spec
+	      is a named structure or union type, additionally defines that
+	      structure or union type.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If name is NIL, foreign-type-spec must be a named foreign
+	      struct or union definition, in which case the foreign structure
+	      or
+	      union definition is put in effect.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Note that there are two separate namespaces for foreign
+	      type names, one for the names of ordinary types and one for
+	      the names of structs and unions.  Which one
+	      <em class="varname">name</em> refers to depends on
+	      <em class="varname">foreign-type-spec</em> in the obvious manner.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_external"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>external</strong></span> name =&gt; entry
+	    </code>
+            </div>
+            <div class="refentrytitle">Resolves a reference to an external symbol which
+	      is defined in a shared library.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446597"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---
+		        a simple-string which names an external symbol.
+		        Case-sensitive.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">entry</span></i>---
+		        an object of type EXTERNAL-ENTRY-POINT which maintains
+		        the address of the foreign symbol named by
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">name</em>.
+		      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446637"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">If there is already an EXTERNAL-ENTRY-POINT for
+	      the symbol named by <em class="varname">name</em>, finds it and
+	      returns it.  If not, creates one and returns it.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tries to resolve the entry point to a memory address,
+	      and identify the containing library.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Be aware that under Darwin, external functions which
+	      are callable from C have underscores prepended to their names,
+	      as in "_fopen".</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_external-call"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>external-call</strong></span> name
+	      {arg-type-specifier arg}* <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> result-type-specifier
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446706"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---A lisp string. See external, above.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg-type-specifer</span></i>---One of the foreign argument-type keywords, described
+		        above, or an equivalent <a xmlns="http://www.w3.org/1999/xhtml" class="link" href="#Specifying-And-Using-Foreign-Types" title="12.1.Â Specifying And Using Foreign Types">foreign
+		          type specifier</a>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg</span></i>---A lisp value of type indicated by the corresponding
+		        arg-type-specifier</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result-type-specifier</span></i>---One of the foreign argument-type keywords, described
+		        above, or an equivalent <a xmlns="http://www.w3.org/1999/xhtml" class="link" href="#Specifying-And-Using-Foreign-Types" title="12.1.Â Specifying And Using Foreign Types">foreign
+		          type specifier</a>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446780"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Calls the foreign function at the address obtained by
+	      resolving the external-entry-point associated with name, passing
+	      the values of each arg as a foreign argument of type indicated by
+	      the corresponding arg-type-specifier. Returns the foreign function
+	      result (coerced to a Lisp object of type indicated by
+	      result-type-specifier), or NIL if result-type-specifer is :VOID or
+	      NIL</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_Pff-call"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>%ff-call</strong></span> entrypoint
+	      {arg-type-keyword arg}* <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> result-type-keyword
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446840"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">entrypoint</span></i>---A fixnum or MACPTR</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg-type-keyword</span></i>---One of the foreign argument-type keywords, described
+		        above</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg</span></i>---A lisp value of type indicated by the corresponding
+		        arg-type-keyword</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result-type-keyword</span></i>---One of the foreign argument-type keywords, described
+		        above</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446902"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Calls the foreign function at address entrypoint passing the
+	      values of each arg as a foreign argument of type indicated by the
+	      corresponding arg-type-keyword. Returns the foreign function
+	      result (coerced to a Lisp object of type indicated by
+	      result-type-keyword), or NIL if result-type-keyword is :VOID or
+	      NIL</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_ff-call"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>ff-call</strong></span> entrypoint
+	      {arg-type-specifier arg}* <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> result-type-specifier
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id446961"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">entrypoint</span></i>---A fixnum or MACPTR</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg-type-specifer</span></i>---One of the foreign argument-type keywords, described
+		        above, or an equivalent <a xmlns="http://www.w3.org/1999/xhtml" class="link" href="#Specifying-And-Using-Foreign-Types" title="12.1.Â Specifying And Using Foreign Types">foreign
+		          type specifier</a>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg</span></i>---A lisp value of type indicated by the corresponding
+		        arg-type-specifier</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result-type-specifier</span></i>---One of the foreign argument-type keywords, described
+		        above, or an equivalent <a xmlns="http://www.w3.org/1999/xhtml" class="link" href="#Specifying-And-Using-Foreign-Types" title="12.1.Â Specifying And Using Foreign Types">foreign
+		          type specifier</a>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447035"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Calls the foreign function at address entrypoint passing the
+	      values of each arg as a foreign argument of type indicated by the
+	      corresponding arg-type-specifier. Returns the foreign function
+	      result (coerced to a Lisp object of type indicated by
+	      result-type-specifier), or NIL if result-type-specifer is :VOID or
+	      NIL</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_foreign-symbol-address"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>foreign-symbol-address</strong></span> name
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447091"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---A lisp string.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447113"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tries to resolve the address of the foreign symbol
+	      name. If successful, returns that address encapsulated in
+	      <a class="link" href="#Referencing-and-Using-Foreign-Memory-Addresses" title="12.3.Â Referencing and Using Foreign Memory Addresses">a
+	        MACPTR</a>, else returns NIL.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_foreign-symbol-entry"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>foreign-symbol-entry</strong></span> name
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447172"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---A lisp string.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447195"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tries to resolve the address of the foreign symbol name. If
+	      successful, returns a fixnum representation of that address, else
+	      returns NIL.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_free"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>free</strong></span> ptr
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447249"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ptr</span></i>---A <code xmlns="http://www.w3.org/1999/xhtml" class="code">MACPTR</code> that points to a block of
+		      foreign, heap-allocated memory.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447275"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">In <code class="literal">CCL</code> 1.2 and later, the <code class="code">CCL:FREE</code>
+          function invokes the foreign <code class="code">free</code> function from
+          the platform's standard C library to deallocate a block of
+          foreign memory.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Previous versions of <code class="literal">CCL</code> implemented this function,
+          but it was not exported.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">If the argument to <code class="code">CCL:FREE</code> is a gcable
+        pointer (for example, an object returned
+        by <code class="code">MAKE-GCABLE-RECORD</code>)
+        then <code class="code">CCL:FREE</code> informs the garbage collector that
+        the foreign memory has been deallocated before calling the
+        foreign <code class="code">free</code> function.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_make-heap-ivector"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-heap-ivector</strong></span> element-count element-type
+	      =&gt; vector macptr size
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447368"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">element-count</span></i>---A positive integer.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">element-type</span></i>---A type specifier.
+		      
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">vector</span></i>---A lisp vector.  The initial contents are
+		      undefined.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">mactpr</span></i>---A pointer to the first byte of data stored
+		      in the vector.
+		      </p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">size</span></i>---The size of the returned vector in octets.
+		      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447443"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	An "ivector" is a one-dimensional array that's specialized to
+	a numeric or character element type.
+	</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	  <code class="code">MAKE-HEAP-IVECTOR</code> allocates an ivector in
+	  foreign memory.  The GC will never move this vector, and
+	  will in fact not pay any attention to it at all.  The
+	  returned pointer to it can therefore be passed safely to
+	  foreign code.
+	</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	  The vector must be explicitly deallocated with
+	  <code class="code">DISPOSE-HEAP-IVECTOR</code>.
+	</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_makegcable--record"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-gcable-record</strong></span> typespec
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> initforms =&gt; result
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447515"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">typespec</span></i>---A foreign type specifier, or a keyword which is used
+		        as the name of a foreign struct or union.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">initforms</span></i>---If the type denoted by <em xmlns="http://www.w3.org/1999/xhtml" class="varname">typespec</em>
+		        is scalar, a single value appropriate for that type;
+		        otherwise, a list of alternating field names and
+		        values appropriate for the types of those fields.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---
+		        A <span xmlns="http://www.w3.org/1999/xhtml" class="type"><strong>macptr</strong></span> which encapsulates the address of a
+		        newly-allocated record on the foreign heap. The foreign
+		        object returned by <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-gcable-record</strong></span>
+		        is freed when the garbage collector determines that
+		        the <code xmlns="http://www.w3.org/1999/xhtml" class="code">MACPTR</code> object that describes it is
+		        unreachable.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447582"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Allocates a block of foreign memory suitable to hold the foreign
+	      type described by <code class="code">typespec</code>, in the same manner
+	      as <a class="link" href="#anchor_make-record">MAKE-RECORD</a>. In
+	      addition, <code class="code">MAKE-GCABLE-RECORD</code> marks the
+	      returned object gcable; in other words, it informs the garbage
+	      collector that it may reclaim the object when it becomes
+	      unreachable.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">In all other respects, <code class="code">MAKE-GCABLE-RECORD</code> works
+          the same way
+          as <a class="link" href="#anchor_make-record">MAKE-RECORD</a></p>
+                <p xmlns="http://www.w3.org/1999/xhtml"> When using gcable pointers, it's important to remember the
+          distinction between a <code class="code">MACPTR</code> object (which is a
+          lisp object, more or less like any other) and the block of
+          foreign memory that the <code class="code">MACPTR</code> object points to.
+          If a gcable <code class="code">MACPTR</code> object is the only thing in the
+          world (lisp world or foreign world) that references the
+          underlying block of foreign memory, then freeing the foreign
+          memory when it becomes impossible to reference it is convenient
+          and sane.  If other lisp <code class="code">MACPTR</code>s reference the
+          underlying block of foreign memory or if the address of that
+          foreign memory is passed to and retained by foreign code, having
+          the GC free the memory may have unpleasant consequences if those
+          other references are used.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Take care, therefore, not to create a gcable record unless
+          you are sure that the returned <code class="code">MACPTR</code> will be the
+          only reference to the allocated memory that will ever be
+          used.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_make-record"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-record</strong></span> typespec
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> initforms =&gt; result
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447704"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">typespec</span></i>---A foreign type specifier, or a keyword which is used
+		        as the name of a foreign struct or union.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">initforms</span></i>---If the type denoted by <em xmlns="http://www.w3.org/1999/xhtml" class="varname">typespec</em>
+		        is scalar, a single value appropriate for that type;
+		        otherwise, a list of alternating field names and
+		        values appropriate for the types of those fields.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">result</span></i>---
+		        A <span xmlns="http://www.w3.org/1999/xhtml" class="type"><strong>macptr</strong></span> which encapsulates the address of a
+		        newly-allocated record on the foreign heap.
+		      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447762"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Expands into code which allocates and initializes
+	      an instance of the type 
+	      denoted by <em class="varname">typespec</em>, on the foreign
+	      heap.  The record is allocated using the C function
+	      <span class="function"><strong>malloc</strong></span>, and the user of
+	      <span class="function"><strong>make-record</strong></span> must explicitly call
+	      the function <span class="function"><strong>CCL:FREE</strong></span> to deallocate the
+	      record, when it is no longer needed.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      If <em class="varname">initforms</em> is provided, its value
+	      or values are used in the initialization.  When the type
+	      is a scalar, <em class="varname">initforms</em> is either a single
+	      value which can be coerced to that type, or no value, in which
+	      case binary 0 is used.  When the type is a <span class="type"><strong>struct</strong></span>,
+	      <em class="varname">initforms</em> is a list, giving field names
+	      and the values for each.  Each field is treated in the same way
+	      as a scalar is: If a value for it is given, it must be
+	      coerceable to the field's type; if not, binary 0 is used.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      When the type is an array, <em class="varname">initforms</em> may
+	      not be provided, because <span class="function"><strong>make-record</strong></span>
+	      cannot initialize its values.  <span class="function"><strong>make-record</strong></span>
+	      is also unable to initialize fields of a <span class="type"><strong>struct</strong></span>
+	      which are themselves
+	      <span class="type"><strong>struct</strong></span>s.  The user of
+	      <span class="function"><strong>make-record</strong></span> should set these values
+	      by another means.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      A possibly-significant limitation is that it must be possible to
+	      find the foreign type at the time the macro is expanded;
+	      <span class="function"><strong>make-record</strong></span> signals an error if this is
+	      not the case.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447852"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      It is inconvenient that <span class="function"><strong>make-record</strong></span> is a
+	      macro, because this means that <em class="varname">typespec</em>
+	      cannot be a variable; it must be an immediate value.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      If it weren't for this requirement,
+	      <span class="function"><strong>make-record</strong></span> could be a function.  However,
+	      that would mean that any stand-alone application using it would
+	      have to include a copy of the interface database
+	      (see <a class="xref" href="#The-Interface-Database" title="12.4.Â The Interface Database">SectionÂ 12.4, âThe Interface Databaseâ</a>), which is undesirable
+	      because it's large.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_open-shared-library"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>open-shared-library</strong></span> name =&gt; library
+	    </code>
+            </div>
+            <div class="refentrytitle">Asks the operating system to load a shared library
+	      for CCL to use.</div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447935"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---A SIMPLE-STRING which is presumed to be the so-name of
+		        or a filesystem path to the library.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">library</span></i>---An object of type SHLIB which describes the
+		        library denoted by <em xmlns="http://www.w3.org/1999/xhtml" class="varname">name</em>.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447976"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">If the library denoted by <em class="varname">name</em> can
+	      be loaded by the
+	      operating system, returns an object of type SHLIB that describes
+	      the library; if the library is already open, increments a
+	      reference count. If the library can't be loaded, signals a
+	      SIMPLE-ERROR which contains an often-cryptic message from the
+	      operating system.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id447991"></a>
+                <div class="header">Examples:</div>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">;;; Try to do something simple.
+          ? (open-shared-library "libgtk.so")
+          &gt; Error: Error opening shared library "libgtk.so": /usr/lib/libgtk.so: undefined symbol: gdk_threads_mutex
+          &gt; While executing: OPEN-SHARED-LIBRARY
+
+          ;;; Grovel around, curse, and try to find out where "gdk_threads_mutex"
+          ;;; might be defined. Then try again:
+
+          ? (open-shared-library "libgdk.so")
+          #&lt;SHLIB libgdk.so #x3046DBB6&gt;
+
+          ? (open-shared-library "libgtk.so")
+          #&lt;SHLIB libgtk.so #x3046DC86&gt;
+
+          ;;; Reference an external symbol defined in one of those libraries.
+
+          ? (external "gtk_main")
+          #&lt;EXTERNAL-ENTRY-POINT "gtk_main" (#x012C3004) libgtk.so #x3046FE46&gt;
+
+          ;;; Close those libraries.
+
+          ? (close-shared-library "libgtk.so")
+          T
+
+          ? (close-shared-library "libgdk.so")
+          T
+
+          ;;; Reference the external symbol again.
+
+          ? (external "gtk_main")
+          #&lt;EXTERNAL-ENTRY-POINT "gtk_main" {unresolved} libgtk.so #x3046FE46&gt;</pre>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448012"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">It would be helpful to describe what an soname is and give
+	      examples of one.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Does the SHLIB still get returned if the library is
+	      already open?</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_pref"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>pref</strong></span> ptr accessor-form
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448069"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">ptr</span></i>---<a xmlns="http://www.w3.org/1999/xhtml" class="link" href="#Referencing-and-Using-Foreign-Memory-Addresses" title="12.3.Â Referencing and Using Foreign Memory Addresses">a MACPTR</a>.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">accessor-form</span></i>---a keyword which names a foreign type or record, as
+		        described in <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#Foreign-type--record--and-field-names" title="12.8.3.Â Foreign type, record, and field names">SectionÂ 12.8.3, âForeign type, record, and field namesâ</a>.
+		      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448114"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">References an instance of a foreign type (or a component of
+	      a foreign type) accessible via ptr.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Expands into code which references the indicated scalar type
+	      or component, or returns a pointer to a composite type.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">PREF can be used with SETF.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">RREF is a deprecated alternative to PREF. It accepts a
+	      :STORAGE keyword and rather loudly ignores it.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_Preference-external-entry-point"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>%reference-external-entry-point</strong></span> eep
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448179"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">eep</span></i>---An EXTERNAL-ENTRY-POINT, as obtained by the EXTERNAL
+		        macro.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448202"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tries to resolve the address of the EXTERNAL-ENTRY-POINT
+	      eep; returns a fixnum representation of that address if
+	      successful, else signals an error.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_rlet"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>rlet</strong></span> (var typespec <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> initforms)*
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448273"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">var</span></i>---A symbol (a lisp variable)</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">typespec</span></i>---A foreign type specifier or foreign record name.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">initforms</span></i>---As described above, for
+		        <a xmlns="http://www.w3.org/1999/xhtml" class="xref" href="#m_make-record" title="Macro MAKE-RECORD"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-record</b></a></p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448324"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Executes <em class="varname">body</em>
+	      in an environment in which each var is bound
+	      to <a class="link" href="#Referencing-and-Using-Foreign-Memory-Addresses" title="12.3.Â Referencing and Using Foreign Memory Addresses">a MACPTR</a> encapsulating the
+	      address of a stack-allocated foreign memory block, allocated and
+	      initialized from typespec and initforms as per
+	      <a class="xref" href="#m_make-record" title="Macro MAKE-RECORD"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">make-record</b></a>.
+	      Returns whatever value(s) <em class="varname">body</em>
+	      returns.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Record fields that aren't explicitly initialized have
+	      unspecified contents.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_rletz"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>rletz</strong></span> (var typespec <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em> initforms)*
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448405"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">var</span></i>---A symbol (a lisp variable)</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">typespec</span></i>---A foreign type specifier or foreign record name.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">initforms</span></i>---As described above, for ccl:make-record</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448453"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Executes body in an environment in which each var is
+	      bound to <a class="link" href="#Referencing-and-Using-Foreign-Memory-Addresses" title="12.3.Â Referencing and Using Foreign Memory Addresses">a
+	        MACPTR</a> encapsulating the address of a stack-allocated
+	      foreign memory block, allocated and initialized from
+	      typespec and initforms as ccl:make-record.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns whatever value(s) body returns.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Unlike rlet, record fields that aren't explicitly
+	      initialized are set to binary 0.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_terminate-when-unreachable"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>terminate-when-unreachable</strong></span> object
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448520"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">object</span></i>---A CLOS object of a class for which there exists
+		        a method of the generic function
+		        <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>ccl:terminate</strong></span>.
+		      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448549"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      The "termination" mechanism is a way to have the garbage
+	      collector run a function right before an object is about to
+	      become garbage.  It is very similar to the "finalization"
+	      mechanism which Java has.  It is not standard Common Lisp,
+	      although other Lisp implementations have similar features.
+	      It is useful when there is some sort of special cleanup,
+	      deallocation, or releasing of resources which needs to happen
+	      when a certain object is no longer being used.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      When the garbage collector discovers that an object is no
+	      longer referred to anywhere in the program, it deallocates
+	      that object, freeing its memory.  However, if
+	      <span class="function"><strong>ccl:terminate-when-unreachable</strong></span> has been
+	      called on the object at any time, the garbage collector first
+	      invokes the generic function <span class="function"><strong>ccl:terminate</strong></span>,
+	      passing it the object as a parameter.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Therefore, to make termination do something useful, you need to
+	      define a method on <span class="function"><strong>ccl:terminate</strong></span>.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Because calling
+	      <span class="function"><strong>ccl:terminate-when-unreachable</strong></span> only
+	      affects a single object, rather than all objects of its
+	      class, you
+	      may wish to put a call to it in the
+	      <span class="function"><strong>initialize-instance</strong></span> method of a
+	      class.  Of course, this is only appropriate if you do in fact
+	      want to use termination for all objects of a given class.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448605"></a>
+                <div class="header">Example:</div>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+          (defclass resource-wrapper ()
+            ((resource :accessor resource)))
+
+          (defmethod initialize-instance :after ((x resource-wrapper) &amp;rest initargs)
+             (ccl:terminate-when-unreachable x))
+
+          (defmethod ccl:terminate ((x resource-wrapper))
+             (when (resource x)
+                (deallocate (resource x))))</pre>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448620"></a>
+                <div class="header">See Also:</div>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="simplelist">
+                  <a class="xref" href="#Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap" title="12.11.Â Tutorial: Allocating Foreign Data on the Lisp Heap">SectionÂ 12.11, âTutorial: Allocating Foreign Data on the Lisp Heap â</a>
+                </span>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_unuse-interface-dir"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>unuse-interface-dir</strong></span> dir-id
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448680"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">dir-id</span></i>---A keyword whose pname, mapped to lower case, names a
+		        subdirectory of "ccl:headers;" (or
+		        "ccl:darwin-headers;")</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448703"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tells <code class="literal">CCL</code> to remove the interface directory denoted by
+	      dir-id from the list of interface directories which are
+	      consulted for
+	      foreign type and function information. Returns T if the directory
+	      was on the search list, NIL otherwise.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_use-interface-dir"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	      <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>use-interface-dir</strong></span> dir-id
+	    </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448764"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">dir-id</span></i>---A keyword whose pname, mapped to lower case, names a
+		        subdirectory of "ccl:headers;" (or
+		        "ccl:darwin-headers;")</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448787"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tells <code class="literal">CCL</code> to add the interface directory denoted by
+	      dir-id to the list of interface directories which it consults for
+	      foreign type and function information. Arranges that that
+	      directory is searched before any others.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Note that <span class="function"><strong>use-interface-dir</strong></span>
+	      merely adds an entry
+	      to a search list.
+	      If the named directory doesn't exist in the file system
+	      or doesn't
+	      contain a set of database files, a runtime error may occur
+	      when <code class="literal">CCL</code>
+	      tries to open some database file in that directory, and it
+	      will try to
+	      open such a database file whenever it needs to find any
+	      foreign type or
+	      function information. <a class="xref" href="#f_unuse-interface-dir" title="Function UNUSE-INTERFACE-DIR"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">unuse-interface-dir</b></a>
+	      may come in
+	      handy in that case.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id448825"></a>
+                <div class="header">Examples:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">One typically wants interface information to be
+	      available at compile-time (or, in many cases, at read-time).
+	      A typical idiom would be:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">(eval-when (:compile-toplevel :execute)
+          (use-interface-dir :GTK))</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">Using the :GTK interface directory makes available
+	      information on
+	      foreign types, functions, and constants.  It's generally
+	      necessary to
+	      load foreign libraries before actually calling the
+	      foreign code, which for GTK can be done like this:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">(load-gtk-libraries)</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">It should now be possible to do things like:</p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">(#_gtk_widget_destroy w)</pre>
+              </div>
+            </div>
+          </p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="The-Objective-C-Bridge"></a>ChapterÂ 13.Â The Objective-C Bridge</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Objective-C-Changes-1.2">13.1. Changes in 1.2</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Using-Objective-C-Classes">13.2. Using Objective-C Classes</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Instantiating-Objective-C-Objects">13.3. Instantiating Objective-C Objects</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Calling-Objective-C-Methods">13.4. Calling Objective-C Methods</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Type-Coercion-for-ObjC-Method-Calls">13.4.1. Type Coercion for Objective-C Method Calls</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Methods-which-Return-Structures">13.4.2. Methods which Return Structures</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Variable-Arity-Messages">13.4.3. Variable-Arity Messages</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Optimization">13.4.4. Optimization</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Defining-Objective-C-Classes">13.5. Defining Objective-C Classes</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Defining-classes-with-foreign-slots">13.5.1. Defining classes with foreign slots</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Defining-classes-with-Lisp-slots">13.5.2. Defining classes with Lisp slots</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Defining-Objective-C-Methods">13.6. Defining Objective-C Methods</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#id426590">13.6.1. Using <code class="literal">define-objc-method</code></a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#id426833">13.6.2. Using <code class="literal">objc:defmethod</code></a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Method-Redefinition-Constraints">13.6.3. Method Redefinition Constraints</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Loading-Objc-Frameworks">13.7. Loading Frameworks</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#How-Objective-C-Names-are-Mapped-to-Lisp-Symbols">13.8. How Objective-C Names are Mapped to Lisp Symbols</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <p xmlns="http://www.w3.org/1999/xhtml">Mac OS X APIs use a language called Objective-C, which is
+    approximately C with some object-oriented extensions modeled on
+    Smalltalk.  The Objective-C bridge makes it possible to work with
+    Objective-C objects and classes from Lisp, and to define classes
+    in Lisp which can be used by Objective-C.</p>
+        <p xmlns="http://www.w3.org/1999/xhtml">The ultimate purpose of the Objective-C and Cocoa bridges is
+    to make Cocoa (the standard user-interface framework on Mac OS X)
+    as easy as possible to use from Clozure CL, in order to support the
+    development of GUI applications and IDEs on Mac OS X (and on any
+    platform that supports Objective-C, such as GNUStep).  The
+    eventual goal, which is much closer than it used to be, is
+    complete integration of Cocoa into CLOS.</p>
+        <p xmlns="http://www.w3.org/1999/xhtml">The current release provides Lisp-like syntax and naming
+    conventions for the basic Objective-C operations, with automatic type
+    processing and messages checked for validity at compile-time.  It
+    also provides some convenience facilities for working with
+    Cocoa.</p>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Objective-C-Changes-1.2"></a>13.1.Â Changes in 1.2</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Version 1.2 of Clozure CL exports most of the useful symbols
+    described in this chapter; in previous releases, most of them were
+    private in the <code class="literal">CCL</code> package.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">There are several new reader macros that make it much more
+    convenient than before to refer to several classes of symbols used
+    with the Objective-C bridge. For a full description of these
+    reader-macros, see
+    the <a class="link" href="#anchor_Foreign-Function-Interface-Dictionary">Foreign-Function-Interface
+    Dictionary</a>, especially the entries at the beginning,
+    describing reader macros.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">As in previous releases, 32-bit versions of Clozure CL use 32-bit
+    floats and integers in data structures that describe geometry,
+    font sizes and metrics, and so on. 64-bit versions of Clozure CL use
+    64-bit values where appropriate.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Objective-C bridge defines the
+      type <code class="literal">NS:CGFLOAT</code> as the Lisp type of the preferred
+      floating-point type on the current platform, and defines the
+      constant <code class="literal">NS:+CGFLOAT+</code>.  On DarwinPPC32, the foreign
+      types <code class="literal">:cgfloat</code>, <code class="literal">:&lt;NSUI&gt;nteger</code>,
+      and
+      <code class="literal">:&lt;NSI&gt;nteger</code> are defined by the Objective-C
+      bridge (as 32-bit float, 32-bit unsigned integer, and 32-bit
+      signed integer, respectively); these types are defined as 64-bit
+      variants in the 64-bit interfaces.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Every Objective-C class is now properly named, either with a
+      name exported from the <code class="literal">NS</code> package (in the case of a
+      predefined class declared in the interface files) or with the
+      name provided in the <code class="literal">DEFCLASS</code> form (with <code class="literal">:METACLASS</code>
+      <code class="literal">NS:+NS-OBJECT</code>) which defines the class from Lisp.
+      The class's Lisp name is now proclaimed to be a "static"
+      variable (as if by <code class="literal">DEFSTATIC</code>, as described in the
+      <a class="link" href="#Static_Variables" title="4.6.Â Static Variables">"Static Variables"
+      section</a>) and given the class object as its value.  In
+      other words:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(send (find-class 'ns:ns-application) 'shared-application)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">and</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(send ns:ns-application 'shared-application)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">are equivalent.  (Since it's not legal to bind a "static"
+  variable, it may be necessary to rename some things so that
+  unrelated variables whose names coincidentally conflict with
+  Objective-C class names don't do so.)</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Using-Objective-C-Classes"></a>13.2.Â Using Objective-C Classes</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The class of most standard CLOS classes is named
+      STANDARD-CLASS. In the Objective-C object model, each class is
+      an instance of a (usually unique) metaclass, which is itself an
+      instance of a "base" metaclass (often the metaclass of the class
+      named "NSObject".) So, the Objective-C class named "NSWindow"
+      and the Objective-C class "NSArray" are (sole) instances of
+      their distinct metaclasses whose names are also "NSWindow" and
+      "NSArray", respectively. (In the Objective-C world, it's much
+      more common and useful to specialize class behavior such as
+      instance allocation.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When Clozure CL first loads foreign libraries containing
+      Objective-C classes, it identifies the classes they contain. The
+      foreign class name, such as "NSWindow", is mapped to an external
+      symbol in the "NS" package via the bridge's translation rules,
+      such as NS:NS-WINDOW.  A similar transformation happens to the
+      metaclass name, with a "+" prepended, yielding something like
+      NS:+NS-WINDOW.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">These classes are integrated into CLOS such that the
+      metaclass is an instance of the class OBJC:OBJC-METACLASS and
+      the class
+      is an instance of the metaclass. SLOT-DESCRIPTION metaobjects are
+      created for each instance variable, and the class and metaclass go
+      through something very similar to the "standard" CLOS class
+      initialization protocol (with a difference being that these classes
+      have already been allocated.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Performing all this initialization, which is done when you
+      (require "COCOA"), currently takes several
+      seconds; it could conceivably be sped up some, but it's never likely
+      to be fast.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When the process is complete, CLOS is aware of several hundred
+      new Objective-C classes and their metaclasses. Clozure CL's runtime system can
+      reliably recognize MACPTRs to Objective-C classes as being CLASS objects, and
+      can (fairly reliably but heuristically) recognize instances of those
+      classes (though there are complicating factors here; see below.)
+      SLOT-VALUE can be used to access (and, with care, set) instance
+      variables in Objective-C instances. To see this, do:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? (require "COCOA")
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">and, after waiting a bit longer for a Cocoa listener window to
+      appear, activate that Cocoa listener and do:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">? (describe (ccl::send ccl::*NSApp* 'key-window))
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">This sends a message asking for the key window, which is the window
+      that has the input focus (often the frontmost), and then describes
+      it. As we can see, NS:NS-WINDOWs have lots of interesting slots.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Instantiating-Objective-C-Objects"></a>13.3.Â Instantiating Objective-C Objects</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Making an instance of an Objective-C class (whether the class in
+      question is predefined or defined by the application) involves
+      calling MAKE-INSTANCE with the class and a set of initargs as
+      arguments.  As with STANDARD-CLASS, making an instance involves
+      initializing (with INITIALIZE-INSTANCE) an object allocated with
+      ALLOCATE-INSTANCE.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For example, you can create an ns:ns-number like this:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? (make-instance 'ns:ns-number :init-with-int 42)
+      #&lt;NS-CF-NUMBER 42 (#x85962210)&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">It's worth looking at how this would be done if you were
+      writing in Objective C:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      [[NSNumber alloc] initWithInt: 42]
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Allocating an instance of an Objective-C class involves sending the
+      class an "alloc" message, and then using those initargs that
+      <span class="emphasis"><em>don't</em></span> correspond to slot initargs as the
+      "init" message to be sent to the newly-allocated instance.  So, the
+      example above could have been done more verbosely as:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? (defvar *n* (ccl::send (find-class 'ns:ns-number) 'alloc))
+      *N*
+
+      ? (setq *n* (ccl::send *n* :init-with-int 42))
+      #&lt;NS-CF-NUMBER 42 (#x16D340)&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">That setq is important; this is a case where init
+      decides to replace the object and return the new one, instead
+      of modifying the existing one.
+      In fact, if you leave out the setq and
+      then try to view the value of *N*, Clozure CL will freeze.  There's
+      little reason to ever do it this way; this is just to show
+      what's going on.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">You've seen that an Objective-C initialization method doesn't have to
+      return the same object it was passed.  In fact, it doesn't have
+      to return any object at all; in this case, the initialization fails
+      and make-instance returns nil.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In some special cases, such as loading an ns:ns-window-controller
+      from a .nib file, it may be necessary for you to pass the
+      instance itself as one of the parameters to the initialization
+      method.  It goes like this:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      ? (defvar *controller*
+      (make-instance 'ns:ns-window-controller))
+      *CONTROLLER*
+
+      ? (setq *controller*
+      (ccl::send *controller*
+      :init-with-window-nib-name #@"DataWindow"
+      :owner *controller*))
+      #&lt;NS-WINDOW-CONTROLLER &lt;NSWindowController: 0x1fb520&gt; (#x1FB520)&gt;
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">This example calls (make-instance) with no initargs.  When you
+      do this, the object is only allocated, and not initialized.  It
+      then sends the "init" message to do the initialization by hand.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">There is an alternative API for instantiating Objective-C
+      classes. You can
+      call <code class="literal">OBJC:MAKE-OBJC-INSTANCE</code>, passing it the
+      name of the Objective-C class as a string. In previous
+      releases, <code class="literal">OBJC:MAKE-OBJC-INSTANCE</code> could be
+      more efficient than <code class="literal">OBJC:MAKE-INSTANCE</code> in
+      cases where the class did not define any Lisp slots; this is no
+      longer the case. You can now
+      regard <code class="literal">OBJC:MAKE-OBJC-INSTANCE</code> as completely
+      equivalent to <code class="literal">OBJC:MAKE-INSTANCE</code>, except that
+      you can pass a string for the classname, which may be convenient
+      in the case that the classname is in some way unusual.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Calling-Objective-C-Methods"></a>13.4.Â Calling Objective-C Methods</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">In Objective-C, methods are called "messages", and there's
+      a special syntax to send a message to an object:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      [w alphaValue]
+      [w setAlphaValue: 0.5]
+      [v mouse: p inRect: r]
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The first line sends the method "alphaValue" to the object
+      <code class="literal">w</code>, with no parameters.  The second line sends
+      the method "setAlphaValue", with the parameter 0.5.  The third
+      line sends the method "mouse:inRect:" - yes, all one long word -
+      with the parameters <code class="literal">p</code> and
+      <code class="literal">r</code>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In Lisp, these same three lines are:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      (send w 'alpha-value)
+      (send w :set-alpha-value 0.5)
+      (send v :mouse p :in-rect r)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Notice that when a method has no parameters, its name is an ordinary
+      symbol (it doesn't matter what package the symbol is in, as
+      only its name is checked).  When a method has parameters,
+      each part of its name is a keyword, and the keywords alternate
+      with the values.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">These two lines break those rules, and both  will
+      result in error messages:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+      (send w :alpha-value)
+      (send w 'set-alpha-value 0.5)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Instead of (send), you can also invoke (send-super), with the
+      same interface.  It has roughly the same purpose as CLOS's
+      (call-next-method); when you use (send-super), the message is
+      handled by the superclass.  This can be used to get at the
+      original implementation of a method when it is shadowed by a
+      method in your subclass.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Type-Coercion-for-ObjC-Method-Calls"></a>13.4.1.Â Type Coercion for Objective-C Method Calls</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL's FFI handles many common conversions between
+        Lisp and foreign data, such as unboxing floating-point args
+        and boxing floating-point results.  The bridge adds a few more
+        automatic conversions:</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">NIL is equivalent to (%NULL-PTR) for any message
+        argument that requires a pointer.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">T/NIL are equivalent to #$YES/#$NO for any boolean argument.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A #$YES/#$NO returned by any method that returns BOOL
+        will be automatically converted to T/NIL.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Methods-which-Return-Structures"></a>13.4.2.Â Methods which Return Structures</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Some Cocoa methods return small structures, such as
+        those used to represent points, rects, sizes and ranges. When
+        writing in Objective C, the compiler hides the implementation
+        details.  Unfortunately, in Lisp we must be slightly more
+        aware of them.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Methods which return structures are called in a special
+        way; the caller allocates space for the result, and passes a
+        pointer to it as an extra argument to the method.  This is
+        called a Structure Return, or STRET.  Don't look at me; I
+        don't name these things.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Here's a simple use of this in Objective C.  The first line
+	    sends the "bounds" message to v1, which returns a rectangle.
+	    The second line sends the "setBounds" message to v2, passing
+	    that same rectangle as a parameter.</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+        NSRect r = [v1 bounds];
+        [v2 setBounds r];
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">In Lisp, we must explicitly allocate the memory, which
+        is done most easily and safely with <a class="xref" href="#m_rlet" title="Macro RLET"><b xmlns="http://www.w3.org/TR/xhtml1/transitional">rlet</b></a>.
+        We do it like this:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(rlet ((r :&lt;NSR&gt;ect))
+          (send/stret r v1 'bounds)
+          (send v2 :set-bounds r))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">The rlet allocates the storage (but doesn't initialize
+        it), and makes sure that it will be deallocated when we're
+        done.  It binds the variable r to refer to it.  The call to
+        <code class="literal">send/stret</code> is just like an ordinary call to
+        <code class="literal">send</code>, except that r is passed as an extra,
+        first parameter.  The third line, which calls
+        <code class="literal">send</code>, does not need to do anything special,
+        because there's nothing complicated about passing a structure
+        as a parameter.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In order to make STRETs easier to use, the bridge
+	    provides two conveniences.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">First, you can use the macros <code class="literal">slet</code>
+        and <code class="literal">slet*</code> to allocate and initialize local
+        variables to foreign structures in one step.  The example
+        above could have been written more tersely as:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(slet ((r (send v1 'bounds)))
+      (send v2 :set-bounds r))
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Second, when one call to <code class="literal">send</code> is made
+        inside another, the inner one has an implicit
+        <code class="literal">slet</code> around it.  So, one could in fact
+        just write:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(send v1 :set-bounds (send v2 'bounds))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">There are also several pseudo-functions provided for convenience
+        by the Objective-C compiler, to make objects of specific types. The
+        following are currently supported by the bridge: NS-MAKE-POINT,
+        NS-MAKE-RANGE, NS-MAKE-RECT, and NS-MAKE-SIZE.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">These pseudo-functions can be used within an SLET initform:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(slet ((p (ns-make-point 100.0 200.0)))
+      (send w :set-frame-origin p))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Or within a call to <code class="literal">send</code>:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(send w :set-origin (ns-make-point 100.0 200.0))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">However, since these aren't real functions, a call like the
+        following won't work:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(setq p (ns-make-point 100.0 200.0))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">To extract fields from these objects, there are also some
+        convenience macros: NS-MAX-RANGE, NS-MIN-X,
+        NS-MIN-Y, NS-MAX-X, NS-MAX-Y, NS-MID-X, NS-MID-Y,
+        NS-HEIGHT, and NS-WIDTH.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that there is also a <code class="literal">send-super/stret</code>
+        for use within methods.  Like <code class="literal">send-super</code>,
+        it ignores any shadowing methods in a subclass, and calls the
+        version of a method which belongs to its superclass.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Variable-Arity-Messages"></a>13.4.3.Â Variable-Arity Messages</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+        There are a few messages in Cocoa which take variable numbers
+        of arguments. Perhaps the most common examples involve
+        formatted strings:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+[NSClass stringWithFormat: "%f %f" x y]
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">In Lisp, this would be written:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(send (find-class 'ns:ns-string)
+      :string-with-format #@"%f %f"
+      (:double-float x :double-float y))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that it's necessary to specify the foreign types of the
+        variables (in this example, :double-float), because the
+        compiler has no general way of knowing these types.  (You
+        might think that it could parse the format string, but this
+        would only work for format strings which are not determined
+        at runtime.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Because the Objective-C runtime system does not provide any information
+        on which messages are variable arity, they must be explicitly
+        declared. The standard variable arity messages in Cocoa are
+        predeclared by the bridge.  If you need to declare a new
+        variable arity message, use
+        (DEFINE-VARIABLE-ARITY-MESSAGE "myVariableArityMessage:").</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Optimization"></a>13.4.4.Â Optimization</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The bridge works fairly hard to optimize message sends,
+        when it has enough information to do so.  There are two cases
+        when it does.  In either, a message send should be nearly as
+        efficient as when writing in Objective C.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The first case is when both the message and the
+        receiver's class are known at compile-time. In general, the
+        only way the receiver's class is known is if you declare it,
+        which you can do with either a DECLARE or a THE form.  For
+        example:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(send (the ns:ns-window w) 'center)
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that there is no way in Objective-C to name the class of a
+        class.  Thus the bridge provides a declaration, @METACLASS.
+        The type of an instance of "NSColor" is ns:ns-color.  The type
+        of the <span class="emphasis"><em>class</em></span> "NSColor" is (@metaclass
+        ns:ns-color):</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(let ((c (find-class 'ns:ns-color)))
+  (declare ((ccl::@metaclass ns:ns-color) c))
+  (send c 'white-color))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">The other case that allows optimization is when only
+        the message is known at compile-time, but its type signature
+        is unique. Of the more-than-6000 messages currently provided
+        by Cocoa, only about 50 of them have nonunique type
+        signatures.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">An example of a message with a type signature that is
+        not unique is SET.  It returns VOID for NSColor, but ID for
+        NSSet.  In order to optimize sends of messages with nonunique
+        type signatures, the class of the receiver must be declared at
+        compile-time.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If the type signature is nonunique or the message is
+        unknown at compile-time, then a slower runtime call must be
+        used.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When the receiver's class is unknown, the bridge's
+        ability to optimize relies on a type-signature table which it
+        maintains.  When first loaded, the bridge initializes this
+        table by scanning every method of every Objective-C class.  When new
+        methods are defined later, the table must be updated.  This
+        happens automatically when you define methods in Lisp.  After
+        any other major change, such as loading an external framework,
+        you should rebuild the table:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (update-type-signatures)
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Because <code class="literal">send</code> and its relatives
+        <code class="literal">send-super</code>, <code class="literal">send/stret</code>,
+        and <code class="literal">send-super/stret</code> are macros, they
+        cannot be <code class="literal">funcall</code>ed,
+        <code class="literal">apply</code>ed, or passed as arguments to
+        functions.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">To work around this, there are function equivalents to
+        them: <code class="literal">%send</code>,
+        <code class="literal">%send-super</code>,
+        <code class="literal">%send/stret</code>, and
+        <code class="literal">%send-super/stret</code>.  However, these
+        functions should be used only when the macros will not do,
+        because they are unable to optimize.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Defining-Objective-C-Classes"></a>13.5.Â Defining Objective-C Classes</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">You can define your own foreign classes, which can then be
+      passed to foreign functions; the methods which you implement in
+      Lisp will be made available to the foreign code as
+      callbacks.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">You can also define subclasses of existing classes,
+      implementing your subclass in Lisp even though the parent class
+      was in Objective C.  One such subclass is CCL::NS-LISP-STRING.
+      It is also particularly useful to make subclasses of
+      NS-WINDOW-CONTROLLER.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">We can use the MOP to define new Objective-C classes, but
+      we have to do something a little funny: the :METACLASS that we'd
+      want to use in a DEFCLASS option generally doesn't exist until
+      we've created the class (recall that Objective-C classes have, for the
+      sake of argument, unique and private metaclasses.) We can sort
+      of sleaze our way around this by specifying a known Objective-C
+      metaclass object name as the value of the DEFCLASS :METACLASS
+      object; the metaclass of the root class NS:NS-OBJECT,
+      NS:+NS-OBJECT, makes a good choice. To make a subclass of
+      NS:NS-WINDOW (that, for simplicity's sake, doesn't define any
+      new slots), we could do:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defclass example-window (ns:ns-window)
+  ()
+  (:metaclass ns:+ns-object))
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">That'll create a new Objective-C class named EXAMPLE-WINDOW whose
+      metaclass is the class named +EXAMPLE-WINDOW. The class will be
+      an object of type OBJC:OBJC-CLASS, and the metaclass will be of
+      type OBJC:OBJC-METACLASS.  EXAMPLE-WINDOW will be a subclass of
+      NS-WINDOW.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Defining-classes-with-foreign-slots"></a>13.5.1.Â Defining classes with foreign slots</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">If a slot specification in an Objective-C class
+        definition contains the keyword :FOREIGN-TYPE, the slot will
+        be a "foreign slot" (i.e. an Objective-C instance variable). Be aware
+        that it is an error to redefine an Objective-C class so that its
+        foreign slots change in any way, and Clozure CL doesn't do
+        anything consistent when you try to.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The value of the :FOREIGN-TYPE initarg should be a
+        foreign type specifier. For example, if we wanted (for some
+        reason) to define a subclass of NS:NS-WINDOW that kept track
+        of the number of key events it had received (and needed an
+        instance variable to keep that information in), we could
+        say:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defclass key-event-counting-window (ns:ns-window)
+  ((key-event-count :foreign-type :int
+                    :initform 0
+                    :accessor window-key-event-count))
+  (:metaclass ns:+ns-object))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">Foreign slots are always SLOT-BOUNDP, and the initform
+        above is redundant: foreign slots are initialized to binary
+        0.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Defining-classes-with-Lisp-slots"></a>13.5.2.Â Defining classes with Lisp slots</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">A slot specification in an Objective-C class definition that
+        doesn't contain the :FOREIGN-TYPE initarg defines a
+        pretty-much normal lisp slot that'll happen to be associated
+        with "an instance of a foreign class". For instance:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defclass hemlock-buffer-string (ns:ns-string)
+  ((hemlock-buffer :type hi::hemlock-buffer
+                   :initform hi::%make-hemlock-buffer
+                   :accessor string-hemlock-buffer))
+  (:metaclass ns:+ns-object))
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">As one might expect, this has memory-management
+        implications: we have to maintain an association between a
+        MACPTR and a set of lisp objects (its slots) as long as the
+        Objective-C instance exists, and we have to ensure that the Objective-C
+        instance exists (does not have its -dealloc method called)
+        while lisp is trying to think of it as a first-class object
+        that can't be "deallocated" while it's still possible to
+        reference it. Associating one or more lisp objects with a
+        foreign instance is something that's often very useful; if you
+        were to do this "by hand", you'd have to face many of the same
+        memory-management issues.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Defining-Objective-C-Methods"></a>13.6.Â Defining Objective-C Methods</h2>
+              </div>
+            </div>
+          </div>
+          <a xmlns="http://www.w3.org/1999/xhtml" id="anchor_Defining-Objective-C-Methods"></a>
+          <p xmlns="http://www.w3.org/1999/xhtml">In Objective-C, unlike in CLOS, every method belongs to some
+      particular class.  This is probably not a strange concept to
+      you, because C++ and Java do the same thing.  When you use Lisp
+      to define Objective-C methods, it is only possible to define methods
+      belonging to Objective-C classes which have been defined in
+      Lisp.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">You can use either of two different macros to define methods
+      on Objective-C classes. <code class="literal">define-objc-method</code>
+      accepts a two-element list containing a message selector name
+      and a class name, and a body. <code class="literal">objc:defmethod</code>
+      superficially resembles the normal
+      CLOS <code class="literal">defmethod</code>, but creates methods on
+      Objective-C classes with the same restrictions as those created
+      by <code class="literal">define-objc-method</code>.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="id426590"></a>13.6.1.Â Using <code class="literal">define-objc-method</code></h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">As described in the
+        section <a class="link" href="#Calling-Objective-C-Methods" title="13.4.Â Calling Objective-C Methods">Calling
+        Objective-C Methods</a>, the names of Objective-C methods
+        are broken into pieces, each piece followed by a parameter.
+        The types of all parameters must be explicitly
+        declared.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Consider a few examples, meant to illustrate the use
+        of <code class="literal">define-objc-method</code>. Let us define a
+        class to use in them:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defclass data-window-controller (ns:ns-window-controller)
+  ((window :foreign-type :id :accessor window)
+   (data :initform nil :accessor data))
+  (:metaclass ns:+ns-object))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">There's nothing special about this class.  It inherits from
+        <code class="literal">ns:ns-window-controller</code>.  It has two slots:
+        <code class="literal">window</code> is a foreign slot, stored in the Objective-C
+        world; and <code class="literal">data</code> is an ordinary slot, stored
+        in the Lisp world.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Here is an example of how to define a method which takes no
+        arguments:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(define-objc-method ((:id get-window)
+                     data-window-controller)
+    (window self))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">The return type of this method is the foreign type :id,
+        which is used for all Objective-C objects.  The name of the
+        method is
+        <code class="literal">get-window</code>.  The body of the method is the
+        single line <code class="literal">(window self)</code>.  The
+        variable <code class="literal">self</code> is bound, within the body, to
+        the instance that is receiving the message.  The call
+        to <code class="literal">window</code> uses the CLOS accessor to get the
+        value of the window field.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Here's an example that takes a parameter.  Notice that the
+        name of the method without a parameter was an ordinary symbol,
+        but with a parameter, it's a keyword:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(define-objc-method ((:id :init-with-multiplier (:int multiplier))
+                     data-window-controller)
+  (setf (data self) (make-array 100))
+  (dotimes (i 100)
+    (setf (aref (data self) i)
+          (* i multiplier)))
+  self)
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">To Objective-C code that uses the class, the name of this
+        method is <code class="literal">initWithMultiplier:</code>.  The name of
+        the parameter is
+        <code class="literal">multiplier</code>, and its type
+        is <code class="literal">:int</code>.  The body of the method does some
+        meaningless things.  Then it returns
+        <code class="literal">self</code>, because this is an initialization
+        method.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Here's an example with more than one parameter:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(define-objc-method ((:id :init-with-multiplier (:int multiplier)
+                          :and-addend (:int addend))
+                     data-window-controller)
+  (setf (data self) (make-array size))
+  (dotimes (i 100)
+    (setf (aref (data self) i)
+          (+ (* i multiplier)
+             addend)))
+  self)
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">To Objective-C, the name of this method is
+        <code class="literal">initWithMultiplier:andAddend:</code>.  Both
+        parameters are of type <code class="literal">:int</code>; the first is
+        named <code class="literal">multiplier</code>, and the second
+        is <code class="literal">addend</code>.  Again, the method returns
+        <code class="literal">self</code>.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Here is a method that does not return any value, a so-called
+        "void method".  Where our other methods
+        said <code class="literal">:id</code>, this one
+        says <code class="literal">:void</code> for the return type:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(define-objc-method ((:void :take-action (:id sender))
+                     data-window-controller)
+  (declare (ignore sender))
+  (dotimes (i 100)
+    (setf (aref (data self) i)
+          (- (aref (data self) i)))))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">This method would be called <code class="literal">takeAction:</code>
+        in Objective-C.  The convention for methods that are going to be
+        used as Cocoa actions is that they take one parameter, which is
+        the object responsible for triggering the action.  However, this
+        method doesn't actually need to use that parameter, so it
+        explicitly ignores it to avoid a compiler warning.  As promised,
+        the method doesn't return any value.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">There is also an alternate syntax, illustrated here.  The
+        following two method definitions are equivalent:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(define-objc-method ("applicationShouldTerminate:"
+                     "LispApplicationDelegate")
+    (:id sender :&lt;BOOL&gt;)
+    (declare (ignore sender))
+    nil)
+  
+(define-objc-method ((:&lt;BOOL&gt;
+                        :application-should-terminate sender)
+                       lisp-application-delegate)
+    (declare (ignore sender))
+    nil)
+      </pre>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="id426833"></a>13.6.2.Â Using <code class="literal">objc:defmethod</code></h3>
+                </div>
+              </div>
+            </div>
+            <a xmlns="http://www.w3.org/1999/xhtml" id="anchor_Using-objc-defmethod"></a>
+            <p xmlns="http://www.w3.org/1999/xhtml">The macro <code class="literal">OBJC:DEFMETHOD</code> can be used to
+        define Objective-C methods.  It looks superficially like
+        <code class="literal">CL:DEFMETHOD</code> in some respects.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Its syntax is</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(OBC:DEFMETHOD name-and-result-type 
+               ((receiver-arg-and-class) <em class="varname">&amp;rest</em> other-args) 
+      <em class="varname">&amp;body</em> body)
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">name-and-result-type</code> is either an
+        Objective-C message name, for methods that return a value of
+        type <code class="literal">:ID</code>, or a list containing an
+        Objective-C message name and a foreign type specifier for
+        methods with a different foreign result type.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">receiver-arg-and-class</code> is a two-element
+        list whose first element is a variable name and whose second
+        element is the Lisp name of an Objective-C class or metaclass.
+        The receiver variable name can be any bindable lisp variable
+        name, but <code class="literal">SELF</code> might be a reasonable
+        choice.  The receiver variable is declared to be "unsettable";
+        i.e., it is an error to try to change the value of the
+        receiver in the body of the method definition.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">other-args</code> are either variable names
+            (denoting parameters of type <code class="literal">:ID</code>) or
+            2-element lists whose first element is a variable name and
+            whose second element is a foreign type specifier.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Consider this example:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(objc:defmethod (#/characterAtIndex: :unichar)
+    ((self hemlock-buffer-string) (index :&lt;NSUI&gt;nteger))
+  ...)
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">The method <code class="literal">characterAtIndex:</code>, when
+        invoked on an object of
+        class <code class="literal">HEMLOCK-BUFFER-STRING</code> with an
+        additional argument of
+        type <code class="literal">:&lt;NSU&gt;integer</code> returns a value of
+        type
+        <code class="literal">:unichar</code>.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Arguments that wind up as some pointer type other
+        than <code class="literal">:ID</code> (e.g. pointers, records passed by
+        value) are represented as typed foreign pointers, so that the
+        higher-level, type-checking accessors can be used on arguments
+        of
+        type <code class="literal">:ns-rect</code>, <code class="literal">:ns-point</code>,
+        and so on.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Within the body of methods defined
+        via <code class="literal">OBJC:DEFMETHOD</code>, the local function
+        <code class="literal">CL:CALL-NEXT-METHOD</code> is defined.  It isn't
+        quite as general as <code class="literal">CL:CALL-NEXT-METHOD</code> is
+        when used in a CLOS method, but it has some of the same
+        semantics.  It accepts as many arguments as are present in the
+        containing method's <code class="literal">other-args</code> list and
+        invokes version of the containing method that would have been
+        invoked on instances of the receiver's class's superclass with
+        the receiver and other provided arguments.  (The idiom of
+        passing the current method's arguments to the next method is
+        common enough that the <code class="literal">CALL-NEXT-METHOD</code> in
+        <code class="literal">OBJC:DEFMETHODs</code> should probably do this if
+        it receives no arguments.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A method defined via <code class="literal">OBJC:DEFMETHOD</code>
+        that returns a structure "by value" can do so by returning a
+        record created via <code class="literal">MAKE-GCABLE-RECORD</code>, by
+        returning the value returned
+        via <code class="literal">CALL-NEXT-METHOD</code>, or by other similar
+        means. Behind the scenes, there may be a pre-allocated
+        instance of the record type (used to support native
+        structure-return conventions), and any value returned by the
+        method body will be copied to this internal record instance.
+        Within the body of a method defined
+        with <code class="literal">OBJC:DEFMETHOD</code> that's declared to
+        return a structure type, the local macro
+        <code class="literal">OBJC:RETURNING-FOREIGN-STRUCT</code> can be used
+        to access the internal structure. For example:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(objc:defmethod (#/reallyTinyRectangleAtPoint: :ns-rect) 
+  ((self really-tiny-view) (where :ns-point))
+  (objc:returning-foreign-struct (r)
+    (ns:init-ns-rect r (ns:ns-point-x where) (ns:ns-point-y where)
+                        single-float-epsilon single-float-epsilon)
+    r))
+       </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">If the <code class="literal">OBJC:DEFMETHOD</code> creates a new
+       method, then it displays a message to that effect. These
+       messages may be helpful in catching errors in the names of
+       method definitions. In addition, if
+       a <code class="literal">OBJC:DEFMETHOD</code> form redefines a method in
+       a way that changes its type signature, Clozure CL signals a
+       continuable error.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Method-Redefinition-Constraints"></a>13.6.3.Â Method Redefinition Constraints</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Objective C was not designed, as Lisp was, with runtime
+        redefinition in mind.  So, there are a few constraints about
+        how and when you can replace the definition of an Objective C
+        method.  Currently, if you break these rules, nothing will
+        collapse, but the behavior will be confusing; so
+        don't.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Objective C methods can be redefined at runtime, but
+        their signatures shouldn't change.  That is, the types of the
+        arguments and the return type have to stay the same.  The
+        reason for this is that changing the signature changes the
+        selector which is used to call the method.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When a method has already been defined in one class, and
+        you define it in a subclass, shadowing the original method,
+        they must both have the same type signature.  There is no such
+        constraint, though, if the two classes aren't related and the
+        methods just happen to have the same name.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Loading-Objc-Frameworks"></a>13.7.Â Loading Frameworks</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">On Mac OS X, a framework is a structured directory
+      containing one or more shared libraries along with metadata such
+      as C and Objective-C header files. In some cases, frameworks may
+      also contain additional items such as executables.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Loading a framework means opening the shared libraries and
+      processing any declarations so that Clozure CL can subsequently call
+      its entry points and use its data structures. Clozure CL provides the
+      function <code class="literal">OBJC:LOAD-FRAMEWORK</code> for this
+      purpose.</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(OBJC:LOAD-FRAMEWORK framework-name interface-dir)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">framework-name</code> is a string that names the
+    framework (for example, "Foundation", or "Cocoa"),
+    and <code class="literal">interface-dir</code> is a keyword that names the
+    set of interface databases associated with the named framework
+    (for example, <code class="literal">:foundation</code>,
+    or <code class="literal">:cocoa</code>).</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Assuming that interface databases for the named frameworks
+    exist on the standard search
+    path, <code class="literal">OBJC:LOAD-FRAMEWORK</code> finds and initializes
+    the framework bundle by searching OS X's standard framework search
+    paths. Loading the named framework may create new Objective-C
+    classes and methods, add foreign type descriptions and entry
+    points, and adjust Clozure CL's dispatch functions.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If interface databases don't exist for a framework you want
+    to use, you will need to create them. For more information about
+    creating interface databases,
+    see <a class="link" href="#Creating-new-interface-directories" title="12.5.2.Â Creating new interface directories">Creating
+    new interface directories</a>.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="How-Objective-C-Names-are-Mapped-to-Lisp-Symbols"></a>13.8.Â How Objective-C Names are Mapped to Lisp Symbols</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">There is a standard set of naming conventions for Cocoa
+      classes, messages, etc.  As long as they are followed, the
+      bridge is fairly good at automatically translating between Objective-C
+      and Lisp names.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For example, "NSOpenGLView" becomes ns:ns-opengl-view;
+      "NSURLHandleClient" becomes ns:ns-url-handle-client; and
+      "nextEventMatchingMask:untilDate:inMode:dequeue:" becomes
+      (:next-event-matching-mask :until-date :in-mode :dequeue).  What
+      a mouthful.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">To see how a given Objective-C or Lisp name will be translated by
+      the bridge, you can use the following functions:</p>
+          <table xmlns="http://www.w3.org/1999/xhtml" class="simplelist" border="0" summary="Simple list">
+            <tr>
+              <td>(ccl::objc-to-lisp-classname string)</td>
+            </tr>
+            <tr>
+              <td>(ccl::lisp-to-objc-classname symbol)</td>
+            </tr>
+            <tr>
+              <td>(ccl::objc-to-lisp-message string)</td>
+            </tr>
+            <tr>
+              <td>(ccl::lisp-to-objc-message string)</td>
+            </tr>
+            <tr>
+              <td>(ccl::objc-to-lisp-init string)</td>
+            </tr>
+            <tr>
+              <td>(ccl::lisp-to-objc-init keyword-list)</td>
+            </tr>
+          </table>
+          <p xmlns="http://www.w3.org/1999/xhtml">Of course, there will always be exceptions to any naming
+      convention.  Please tell us on the mailing lists if you come
+      across any name translation problems that seem to be bugs.
+      Otherwise, the bridge provides two ways of dealing with
+      exceptions:</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">First, you can pass a string as the class name of
+      MAKE-OBJC-INSTANCE and as the message to SEND.  These strings
+      will be directly interpreted as Objective-C names, with no
+      translation. This is useful for a one-time exception.  For
+      example:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(ccl::make-objc-instance "WiErDclass")
+(ccl::send o "WiErDmEsSaGe:WithARG:" x y)
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Alternatively, you can define a special translation rule
+      for your exception.  This is useful for an exceptional name that
+      you need to use throughout your code.  Some examples:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(ccl::define-classname-translation "WiErDclass" wierd-class)
+(ccl::define-message-translation "WiErDmEsSaGe:WithARG:" (:weird-message :with-arg))
+(ccl::define-init-translation "WiErDiNiT:WITHOPTION:" (:weird-init :option))
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">The normal rule in Objective-C names is that each word begins with a
+      capital letter (except possibly the first).  Using this rule
+      literally, "NSWindow" would be translated as N-S-WINDOW, which
+      seems wrong.  "NS" is a special word in Objective-C that should not be
+      broken at each capital letter. Likewise "URL", "PDF", "OpenGL",
+      etc. Most common special words used in Cocoa are already defined
+      in the bridge, but you can define new ones as follows:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(ccl::define-special-objc-word "QuickDraw")
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">Note that message keywords in a SEND such as (SEND V
+      :MOUSE P :IN-RECT R) may look like the keyword arguments in a
+      Lisp function call, but they really aren't. All keywords must be
+      present and the order is significant. Neither (:IN-RECT :MOUSE)
+      nor (:MOUSE) translate to "mouse:inRect:"</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Also, as a special exception, an "init" prefix is optional
+      in the initializer keywords, so (MAKE-OBJC-INSTANCE 'NS-NUMBER
+      :INIT-WITH-FLOAT 2.7) can also be expressed as
+      (MAKE-OBJC-INSTANCE 'NS-NUMBER :WITH-FLOAT 2.7)</p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Platform-specific-notes"></a>ChapterÂ 14.Â Platform-specific notes</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Platform-specific-overview">14.1. Overview</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#differences-between-32-bit-and-64-bit-implementations">14.1.1. Differences Between 32-bit and 64-bit implementations</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#File-system-case">14.1.2. File-system case</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Line-Termination-Characters">14.1.3. Line Termination Characters</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Single-precision-trig---transcendental-functions">14.1.4. Single-precision trig &amp; transcendental functions</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Shared-libraries">14.1.5. Shared libraries</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Unix-Posix-Darwin-Features">14.2. Unix/Posix/Darwin Features</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Cocoa-Programming-in-CCL">14.3. Cocoa Programming in Clozure CL</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#The-Command-Line-and-the-Window-System">14.3.1. The Command Line and the Window System</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Writing--and-reading--Cocoa-code">14.3.2. Writing (and reading) Cocoa code</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#The-Application-Kit-and-Multiple-Threads">14.3.3. The Application Kit and Multiple Threads</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Acknowledgement--2-">14.3.4. Acknowledgement</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Building-an-Application-Bundle">14.4. Building an Application Bundle</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Recommended-Reading">14.5. Recommended Reading</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Operating-System-Dictionary">14.6. Operating-System Dictionary</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Platform-specific-overview"></a>14.1.Â Overview</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml"> The documentation and whatever experience you may have in
+      using Clozure CL under Linux should also apply to using it under
+      Darwin/MacOS X and FreeBSD. There are some differences between
+      the platforms, and these differences are sometimes exposed in
+      the implementation.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="differences-between-32-bit-and-64-bit-implementations"></a>14.1.1.Â Differences Between 32-bit and 64-bit implementations</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Fixnums on 32-bit systems are 30 bits long, and are in the
+	  range -536870912 through 536870911.  Fixnums on 64-bit
+	  systems are 61 bits long, and are in the range
+	  -1152921504606846976 through 1152921504606846975. (see <a class="xref" href="#Tagging-scheme" title="16.2.4.Â Tagging scheme">SectionÂ 16.2.4, âTagging schemeâ</a>)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Since we have much larger fixnums on 64-bit systems,
+	    <em class="varname">INTERNAL-TIME-UNITS-PER-SECOND</em> is 1000000
+	    on 64-bit systems but remains 1000 on 32-bit systems.  This
+	    enables much finer grained timing on 64-bit systems.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="File-system-case"></a>14.1.2.Â File-system case</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Darwin and MacOS X use HFS+ file systems by default;
+	    HFS+ file systems are usually case-insensitive. Most of
+	    Clozure CL's filesystem and pathname code assumes that the
+	    underlying filesystem is case-sensitive; this assumption
+	    extends to functions like EQUAL, which assumes that #p"FOO"
+	    and #p"foo" denote different, un-EQUAL filenames. Since
+	    Darwin/MacOS X can also use UFS and NFS filesystems, the
+	    opposite assumption would be no more correct than the one
+	    that's currently made.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Whatever the best solution to this problem turns out to
+        be, there are some practical considerations. Doing:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (save-application "DPPCCL")
+	  </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">on 32-bit DarwinPPC has the unfortunate side-effect of
+        trying to overwrite the Darwin Clozure CL kernel, "dppccl", on a
+        case-insensitive filesystem.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">To work around this, the Darwin Clozure CL kernel expects
+        the default heap image file name to be the kernel's own
+        filename with the string ".image" appended, so the idiom would
+        be:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (save-application "dppccl.image")
+	  </pre>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Line-Termination-Characters"></a>14.1.3.Â Line Termination Characters</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">MacOSX effectively supports two distinct line-termination
+	    conventions. Programs in its Darwin substrate follow the Unix
+	    convention of recognizing #\LineFeed as a line terminator; traditional
+	    MacOS programs use #\Return for this purpose.  Many modern
+	    GUI programs try to support several different line-termination
+	    conventions (on the theory that the user shouldn't be too concerned
+	    about what conventions are used an that it probably doesn't matter.
+	    Sometimes this is true, other times ... not so much.
+	  </p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL follows the Unix convention on both Darwin and
+        LinuxPPC, but offers some support for reading and writing
+        files that use other conventions (including traditional MacOS
+        conventions) as well.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">This support (and anything like it) is by nature
+	    heuristic: it can successfully hide the distinction between
+	    newline conventions much of the time, but could mistakenly
+	    change the meaning of otherwise correct programs (typically
+	    when files contain both #\Return and #\Linefeed characters or
+	    when files contain mixtures of text and binary data.) Because
+	    of this concern, the default settings of some of the variables
+	    that control newline translation and interpretation are
+	    somewhat conservative.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Although the issue of multiple newline conventions
+	    primarily affects MacOSX users, the functionality described
+	    here is available under LinuxPPC as well (and may occasionally
+	    be useful there.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">None of this addresses issues
+	    related to the third newline convention ("CRLF") in widespread
+	    use (since that convention isn't native to any platform on
+	    which Clozure CL currently runs). If Clozure CL is ever ported to
+	    such a platform, that issue might be revisited.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Note that some MacOS programs (including some versions
+	    of commercial MCL) may use HFS file type information to
+	    recognize TEXT and other file types and so may fail to
+	    recognize files created with Clozure CL or other Darwin
+	    applications (regardless of line termination issues.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Unless otherwise noted, the symbols mentioned in this
+	    documentation are exported from the CCL package.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Single-precision-trig---transcendental-functions"></a>14.1.4.Â Single-precision trig &amp; transcendental functions</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">
+	    Despite what Darwin's man pages say, early versions of its math library
+	    (up to and including at least OSX 10.2 (Jaguar) don't implement
+	    single-precision variants of the transcendental and trig functions
+	    (#_sinf, #_atanf, etc.) Clozure CL worked around this by coercing
+	    single-precision args to double-precision, calling the
+	    double-precision version of the math library function, and coercing
+	    the result back to a SINGLE-FLOAT. These steps can introduce rounding
+	    errors (and potentially overflow conditions) that might not be present
+	    or as severe if true 32-bit variants were available.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Shared-libraries"></a>14.1.5.Â Shared libraries</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Darwin/MacOS X distinguishes between "shared libraries"
+        and "bundles" or "extensions"; Linux and FreeBSD don't. In
+        Darwin, "shared libraries" have the file type "dylib" : the
+        expectation is that this class of file is linked against when
+        executable files are created and loaded by the OS when the
+        executable is launched. The latter class -
+        "bundles/extensions" - are expected to be loaded into and
+        unloaded from a running application, via a mechanism like the
+        one used by Clozure CL's OPEN-SHARED-LIBRARY function.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Unix-Posix-Darwin-Features"></a>14.2.Â Unix/Posix/Darwin Features</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL has several convenience functions which allow you
+      to make Posix (portable Unix) calls without having to use the
+      foreign-function interface.  Each of these corresponds directly
+      to a single Posix function call, as it might be made in C.
+      There is no attempt to make these calls correspond to Lisp
+      idioms, such as <code class="literal">setf</code>.  This means that their
+      behavior is simple and predictable.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For working with environment variables, there are
+      CCL::GETENV and CCL::SETENV.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For working with user and group IDs, there are
+      CCL::GETUID, CCL::SETUID, and CCL::SETGID.  To find the home
+      directory of an arbitrary user, as set in the user database
+      (/etc/passwd), there is CCL::GET-USER-HOME-DIR.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For process IDs, there is CCL::GETPID.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For the <code class="literal">system()</code> function, there is
+      CCL::OS-COMMAND.  Ordinarily, it is better - both more efficient
+      and more predictable - to use the features described in <a class="xref" href="#Running-Other-Programs-as-Subprocesses" title="ChapterÂ 8.Â Running Other Programs as Subprocesses">ChapterÂ 8, <i>Running Other Programs as Subprocesses</i></a>.  However,
+      sometimes you may want to specifically ask the shell to invoke a
+      command for you.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Cocoa-Programming-in-CCL"></a>14.3.Â Cocoa Programming in Clozure CL</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Cocoa is one of Apple's APIs for GUI programming; for most
+      purposes, development is considerably faster with Cocoa than
+      with the alternatives.  You should have a little familiarity
+      with it, to better understand this section.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">A small sample Cocoa program can be invoked by evaluating
+      (REQUIRE 'TINY) and then (CCL::TINY-SETUP). This program
+      provides a simple example of using several of the bridge's
+      capabilities.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Tiny demo creates Cocoa objects dynamically, at
+      runtime, which is always an option.  However, for large
+      applications, it is usually more convenient to create your
+      objects with Apple Interface Builder, and store them in .nib
+      files to be loaded when needed.  Both approaches can be freely
+      mixed in a single program.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="The-Command-Line-and-the-Window-System"></a>14.3.1.Â The Command Line and the Window System</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL is ordinarily a command-line application (it
+        doesn't have a connection to the OSX Window server, doesn't
+        have its own menubar or dock icon, etc.) By opening some
+        libraries and jumping through some hoops, it's able to sort of
+        transform itself into a full-fledged GUI application (while
+        retaining its original TTY-based listener.) The general idea
+        is that this hybrid environment can be used to test and
+        protoype UI ideas and the resulting application can eventually
+        be fully transformed into a bundled, double-clickable
+        application. This is to some degree possible, but there needs
+        to be a bit more infrastructure in place before many people
+        would find it easy.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Cocoa applications use the NSLog function to write
+        informational/warning/error messages to the application's
+        standard output stream. When launched by the Finder, a GUI
+        application's standard output is diverted to a logging
+        facility that can be monitored with the Console application
+        (found in /Applications/Utilities/Console.app).  In the hybrid
+        environment, the application's standard output stream is
+        usually the initial listener's standard output stream. With
+        two different buffered stream mechanisms trying to write to
+        the same underlying Unix file descriptor, it's not uncommon to
+        see NSLog output mixed with lisp output on the initial
+        listener.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Writing--and-reading--Cocoa-code"></a>14.3.2.Â Writing (and reading) Cocoa code</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The
+	    syntax of the constructs used to define Cocoa classes and
+	    methods has changed a bit (it was never documented outside of
+	    the source code and never too well documented at all), largely
+	    as the result of functionality offered by Randall Beer's
+	    bridge; the âstandard name-mapping conventionsâ
+	    referenced below are described in his CocoaBridgeDoc.txt file,
+	    as are the constructs used to invoke (âsend messages
+	    toâ) Cocoa methods.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">All of the symbols described below are currently internal to
+        the CCL package.</p>
+            <table xmlns="http://www.w3.org/1999/xhtml" class="simplelist" border="0" summary="Simple list">
+              <tr>
+                <td>
+                  <a class="xref" href="#m_class" title="Macro CCL::@CLASS">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">ccl::@class</b>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  <a class="xref" href="#m_selector" title="Macro CCL::@SELECTOR">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">ccl::@selector</b>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  <a class="xref" href="#m_define-objc-method" title="Macro CCL::DEFINE-OBJC-METHOD">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">ccl::define-objc-method</b>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  <a class="xref" href="#m_define-objc-class-method" title="Macro CCL::DEFINE-OBJC-CLASS-METHOD">
+                    <b xmlns="http://www.w3.org/TR/xhtml1/transitional">ccl::define-objc-class-method</b>
+                  </a>
+                </td>
+              </tr>
+            </table>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="The-Application-Kit-and-Multiple-Threads"></a>14.3.3.Â The Application Kit and Multiple Threads</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The Cocoa API is broken into several pieces.  The
+        Application Kit, affectionately called AppKit, is the one
+        which deals with window management, drawing, and handling
+        events.  AppKit really wants all these things to be done by a
+        "distinguished thread".  creation, and drawing to take place
+        on a distinguished thread.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Apple has published some guidelines which discuss these
+        issues in some detail; see the Apple Multithreading
+        Documentation, and in particular the guidelines on Using the
+        Application Kit from Multiple Threads.  The upshot is that
+        there can sometimes be unexpected behavior when objects are
+        created in threads other than the distinguished event thread;
+        eg, the event thread sometimes starts performing operations on
+        objects that haven't been fully initialized.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's
+        certainly more convenient to do certain types of exploratory
+        programming by typing things into a listener or evaluating a
+        âdefunâ in an Emacs buffer; it may sometimes be
+        necessary to be aware of this issue while doing so.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Each thread in the Cocoa runtime system is expected to
+        maintain a current âautorelease poolâ (an instance
+        of the NSAutoreleasePool class); newly created objects are
+        often added to the current autorelease pool (via the
+        -autorelease method), and periodically the current autorelease
+        pool is sent a â-releaseâ message, which causes it
+        to send â-releaseâ messages to all of the objects
+        that have been added to it.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If the current thread doesn't have a current autorelease
+        pool, the attempt to autorelease any object will result in a
+        severe-looking warning being written via NSLog. The event
+        thread maintains an autorelease pool (it releases the current
+        pool after each event is processed and creates a new one for
+        the next event), so code that only runs in that thread should
+        never provoke any of these severe-looking NSLog
+        messages.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">To try to suppress these messages (and
+        still participate in the Cocoa memory management scheme), each
+        listener thread (the initial listener and any created via the
+        âNew Listenerâ command in the IDE) is given a
+        default autorelease pool; there are REPL colon-commands for
+        manipulating the current listener's âtoplevel
+        autorelease poolâ.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In the current scheme, every time that Cocoa calls lisp
+        code, a lisp error handler is established which maps any lisp
+        conditions to ObjC exceptions and arranges that this exception
+        is raised when the callback to lisp returns. Whenever lisp
+        code invokes a Cocoa method, it does so with an ObjC exception
+        handler in place; this handler maps ObjC exceptions to lisp
+        conditions and signals those conditions.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Any
+        unhandled lisp error or ObjC exception that occurs during the
+        execution of the distinguished event thread's event loop
+        causes a message to be NSLog'ed and the event loop to (try to)
+        continue execution. Any error that occurs in other threads is
+        handled at the point of the outermost Cocoa method
+        invocation. (Note that the error is not necessarily
+        âhandledâ in the dynamic context in which it
+        occurs.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Both of these behaviors could possibly be improved; both of them
+        seem to be substantial improvements over previous behaviors (where,
+        for instance, a misspelled message name typically terminated the
+        application.)</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Acknowledgement--2-"></a>14.3.4.Â Acknowledgement</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The Cocoa bridge was originally developed, and
+        generously contributed by, Randall Beer.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Building-an-Application-Bundle"></a>14.4.Â Building an Application Bundle</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">You may have noticed that (require "COCOA") takes a long
+      time to load.  It is possible to avoid this by saving a Lisp
+      heap image which has everything already loaded.  There is an
+      example file which allows you to do this,
+      "ccl/examples/cocoa-application.lisp", by producing a
+      double-clickable application which runs your program.  First,
+      load your own program.  Then, do:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (require "COCOA-APPLICATION")
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">When it finishes, you should be able to double-click the Clozure CL icon
+      in the ccl directory, to quickly start your program.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The OS may have already decided that Clozure CL.app isn't a valid
+      executable bundle, and therefore won't let you double-click it.
+      If this happens to you, to force it to reconsider, just update the
+      last-modified time of the bundle.  In Terminal:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">&gt; touch Clozure CL.app
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">There is one important caveat.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Because of the way that the ObjC bridge currently works, a saved
+      image is dependent upon the <span class="emphasis"><em>exact</em></span> versions of
+      the Cocoa libraries which were present when it was saved.
+      Specifically, the interface database is.  So, for example, an
+      application produced under OS X 10.3.5 will not work under
+      OS X 10.3.6.  This is inconvenient when you wish to distribute an
+      application you have built this way.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When an image which had contained ObjC classes (which are also
+      CLOS classes) is re-launched, those classes are "revived": all
+      preexisting classes have their addresses updated destructively, so that
+      existing subclass/superclass/metaclass relationships are maintained.
+      It's not possible (and may never be) to preserve foreign
+      instances across SAVE-APPLICATION. (It may be the case that NSArchiver
+      and NSCoder and related classes offer some approximation of that.)</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Recommended-Reading"></a>14.5.Â Recommended Reading</h2>
+              </div>
+            </div>
+          </div>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+            <dl>
+              <dt>
+                <span class="term">
+	      <a class="ulink" href="http://developer.apple.com/documentation/Cocoa/" target="_top">Cocoa Documentation</a>
+	    </span>
+              </dt>
+              <dd>
+                <p>
+	        This is the top page for all of Apple's documentation on
+	        Cocoa.  If you are unfamiliar with Cocoa, it is a good
+	        place to start.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+	      <a class="ulink" href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html" target="_top">Foundation Reference for Objective-C</a>
+	    </span>
+              </dt>
+              <dd>
+                <p>
+	        This is one of the two most important Cocoa references; it
+	        covers all of the basics, except for GUI programming.  This is
+	        a reference, not a tutorial.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+	      <a class="ulink" href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/index.html" target="_top">Application Kit Reference for Objective-C</a>
+	    </span>
+              </dt>
+              <dd>
+                <p>
+	        This is the other; it covers GUI programming with Cocoa
+	        in considerable depth.  This is a reference, not a tutorial.
+	      </p>
+              </dd>
+              <dt>
+                <span class="term">
+	      <a class="ulink" href="http://developer.apple.com/documentation/index.html" target="_top">Apple Developer Documentation</a>
+	    </span>
+              </dt>
+              <dd>
+                <p>
+	        This is the site which the above two documents are found on;
+	        go here to find the documentation on any other Apple API.
+	        Also go here if you need general guidance about OS X, Carbon,
+	        Cocoa, Core Foundation, or Objective C.
+	      </p>
+              </dd>
+            </dl>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Operating-System-Dictionary"></a>14.6.Â Operating-System Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_getenv"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>getenv</strong></span> name =&gt; value</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439502"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---a string which is the name of an existing
+		        environment variable;
+		        case-sensitive</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">value</span></i>---if there is an environment variable named
+		        <em xmlns="http://www.w3.org/1999/xhtml" class="varname">name</em>, its value, as a string; if there
+		        is not, NIL</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439547"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Looks up the value of the environment variable named by
+	      <em class="varname">name</em>, in the OS environment.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_setenv"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>setenv</strong></span> name value =&gt; errno</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439608"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name</span></i>---a string which is the name of a new or existing
+		        environment variable;
+		        case-sensitive</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">value</span></i>---a string, to be the new value of the
+		        environment variable
+		        named by <em xmlns="http://www.w3.org/1999/xhtml" class="varname">name</em></p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">errno</span></i>---zero if the function call completes successfully;
+		        otherwise, a platform-dependent integer which describes
+		        the problem</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439668"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Sets the value of the environment variable named by
+	      <em class="varname">name</em>, in the OS environment.  If there is
+	      no such environment
+	      variable, creates it.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_current-directory-name"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>current-directory-name</strong></span>
+	      =&gt; path</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439730"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">path</span></i>---a string, an absolute pathname in Posix format - with
+		        directory components separated by slashes</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439757"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Looks up the current working directory of the Clozure CL process;
+	      unless it has been changed, this is the directory Clozure CL was
+	      started in.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_getuid"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>getuid</strong></span> =&gt; uid</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439816"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">uid</span></i>---a non-negative integer, identifying a specific user
+		        account as defined in the OS user database</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439843"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Returns the ("real") user ID of the current user.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_setuid"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>setuid</strong></span> uid =&gt; errno</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439900"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">uid</span></i>---a non-negative integer, identifying a specific user
+		        account as defined in the OS user database</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">errno</span></i>---zero if the function call completes successfully;
+		        otherwise, a platform-dependent integer which describes
+		        the problem</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id439943"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Attempts to change the current user ID (both "real" and
+	      "effective"); fails unless
+	      the Clozure CL process has super-user privileges or the ID
+	      given is that of the current user.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_setgid"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>setgid</strong></span> gid =&gt; errno</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440002"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">gid</span></i>---a non-negative integer, identifying a specific
+		        group as defined in the OS user database</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">errno</span></i>---zero if the function call completes successfully;
+		        otherwise, a platform-dependent integer which describes
+		        the problem</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440045"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Attempts to change the current group ID (both "real" and
+	      "effective"); fails unless
+	      the Clozure CL process has super-user privileges or the ID
+	      given is that of a group to which the current user belongs.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_getpid"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>getpid</strong></span> =&gt; pid</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440104"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">pid</span></i>---a non-negative integer, identifying an OS process</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440130"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Returns the ID of the Clozure CL OS process.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_get-user-home-dir"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>get-user-home-dir</strong></span> 
+	      uid =&gt; path</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440187"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">uid</span></i>---a non-negative integer, identifying a specific user
+		        account as defined in the OS user database</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">path</span></i>---a string, an absolute pathname in Posix format - with
+		        directory components separated by slashes; or NIL</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440230"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Looks up and returns the defined home directory of the user
+	      identified by <em class="varname">uid</em>.  This value comes from the
+	      OS user database, not from the <em class="varname">$HOME</em>
+	      environment variable.  Returns NIL if there is no user with
+	      the ID <em class="varname">uid</em>.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_os-command"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>os-command</strong></span> command-line
+	      =&gt; exit-code</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440299"></a>
+                <div class="header">Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">command-line</span></i>---a string, obeying all the whitespace and
+	            escaping
+	            conventions required by the user's default system shell</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">exit-code</span></i>---a non-negative integer, returned as the exit
+	            code of a subprocess; zero indicates success</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440341"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      Invokes the Posix function <span class="function"><strong>system()</strong></span>, which
+	      invokes the user's default system shell (such as
+	      sh or tcsh) as a new process, and has that shell execute
+	      <em class="varname">command-line</em>.
+	    </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      If the shell was able to find the command specified in
+	      <em class="varname">command-line</em>, then <em class="varname">exit-code</em>
+	      is the exit code of that command.  If not, it is the exit
+	      code of the shell itself.
+	    </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440375"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      By convention, an exit code of 0 indicates success.  There are
+	      also other conventions; unfortunately, they are OS-specific, and
+	      the portable macros to decode their meaning are implemented
+	      by the system headers as C preprocessor macros.  This means
+	      that there is no good, automated way to make them available
+	      to Lisp.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_class"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>@class</strong></span> class-name</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440436"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">class-name</span></i>---a string which denotes an existing class name, or a
+		        symbol which can be mapped to such a string via the standard
+		        name-mapping conventions for class names</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440463"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Used to refer to a known ObjC class by name. (Via the use
+	      LOAD-TIME-VALUE, the results of a class-name -&gt; class lookup
+	      are cached.)</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	      <span class="function"><strong>@class</strong></span> is obsolete as of late 2004, because
+	      find-class now works on ObjC classes.  It is described here
+	      only because some old code still uses it.
+	    </p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_selector"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>@selector</strong></span> string</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440532"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">string</span></i>---a string constant, used to canonically refer to an
+		        ObjC method selector</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440558"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Used to refer to an ObjC method selector (method name). Uses
+	      LOAD-TIME-VALUE to cache the result of a string -&gt; selector
+	      lookup.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_objc-defmethod"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>objc:defmethod</strong></span>
+	      name-and-result-type ((receiver-arg-and-class) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;rest</em>
+	      other-args) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440624"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">name-and-result-type</span></i>---either an Objective-C message name, for methods
+                that return a value of type <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:ID</code>, or
+                a list containing an Objective-C message name and a
+                foreign type specifier for methods with a different
+                foreign result type.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">receiver-arg-and-class</span></i>---a two-element list whose first element is a
+                variable name and whose second element is the Lisp
+                name of an Objective-C class or metaclass.  The
+                receiver variable name can be any bindable lisp
+                variable name, but <code xmlns="http://www.w3.org/1999/xhtml" class="literal">SELF</code> might be a
+                reasonable choice.  The receiver variable is declared
+                to be "unsettable"; i.e., it is an error to try to
+                change the value of the receiver in the body of the
+                method definition.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">other-args</span></i>---either variable names (denoting parameters of
+            type <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:ID</code>) or 2-element lists whose
+            first element is a variable name and whose second element
+            is a foreign type specifier.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440705"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Defines an Objective-C-callable method which implements
+	        the specified message selector for instances of the existing
+	        named Objective-C class.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">For a detailed description of the features and
+          restrictions of the <code class="literal">OBJC:DEFMETHOD</code> macro,
+          see the
+          section <a class="link" href="#anchor_Using-objc-defmethod">Using <code class="literal">objc:defmethod</code></a>.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_define-objc-method"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>define-objc-method</strong></span>
+	        (selector class-name) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440788"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">selector</span></i>---either a string which represents the name of the
+		          selector or a list which describes the method's return
+		          type, selector components, and argument types (see below.)
+		          If the first form is used, then the first form in the body
+		          must be a list which describes the selector's argument
+		          types and return value type, as per DEFCALLBACK.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">class-name</span></i>---either a string which names an existing ObjC class
+		          name or a list symbol which can map to such a string via the
+		          standard name-mapping conventions for class names. (Note
+		          that the "canonical" lisp class name is such a
+		          symbol)</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440835"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Defines an ObjC-callable method which implements the
+	        specified message selector for instances of the existing ObjC
+	        class class-name.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="m_define-objc-class-method"></a>
+              <strong>[Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>define-objc-class-method</strong></span>
+	        (selector class-name) <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440898"></a>
+                <div class="header">Arguments and Values:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">As per DEFINE-OBJC-METHOD</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440909"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Like DEFINE-OBJC-METHOD, only used to define methods on the
+	        <span class="emphasis"><em>class</em></span> named by class-name and on its
+	        subclasses.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">For both DEFINE-OBJC-METHOD and DEFINE-OBJC-CLASS-METHOD, the
+	        "selector" argument can be a list whose first element is a
+	        foreign type specifier for the method's return value type and whose
+	        subsequent elements are either:</p>
+                <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+                  <ul type="disc">
+                    <li>
+                      <p>a non-keyword symbol, which can be mapped to a selector string
+		        for a parameterless method according to the standard name-mapping
+		        conventions for method selectors.</p>
+                    </li>
+                    <li>
+                      <p>a list of alternating keywords and variable/type specifiers,
+		        where the set of keywords can be mapped to a selector string for a
+		        parameterized method according to the standard name-mapping
+		        conventions for method selectors and each variable/type-specifier is
+		        either a variable name (denoting a value of type :ID) or a list whose
+		        CAR is a variable name and whose CADR is the corresponding
+		        argument's foreign type specifier.</p>
+                    </li>
+                  </ul>
+                </div>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_alternate-line-terminator"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>CCL:*ALTERNATE-LINE-TERMINATOR*</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id440986"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">This variable is currently only used by the standard reader macro
+	        function for #\; (single-line comments); that function reads successive
+	        characters until EOF, a #\NewLine is read, or a character EQL to the
+	        value of *alternate-line-terminator* is read. In Clozure CL for Darwin, the
+	        value of this variable is initially #\Return ; in Clozure CL for LinuxPPC,
+	        it's initially NIL.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Their default treatment by the #\; reader macro is the primary way
+	        in which #\Return and #\Linefeed differ syntactically; by extending the
+	        #\; reader macro to (conditionally) treat #\Return as a
+	        comment-terminator, that distinction is eliminated. This seems to make
+	        LOAD and COMPILE-FILE insensitive to line-termination issues in many
+	        cases. It could fail in the (hopefully rare) case where a LF-terminated
+	        (Unix) text file contains embedded #\Return characters, and this
+	        mechanism isn't adequate to handle cases where newlines are embedded
+	        in string constants or other tokens (and presumably should be translated
+	        from an external convention to the external one) : it doesn't change
+	        what READ-CHAR or READ-LINE "see", and that may be necessary to
+	        handle some more complicated cases.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="k_external-format"></a>
+              <strong>[Keyword Argument]</strong>
+              <br></br>
+              <code>:EXTERNAL-FORMAT</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441043"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Per ANSI CL, Clozure CL supports the :EXTERNAL-FORMAT keyword
+	        argument to the functions OPEN, LOAD, and COMPILE-FILE. This argument is
+	        intended to provide a standard way of providing implementation-dependent
+	        information about the format of files opened with an element-type of
+	        CHARACTER. This argument can meaningfully take on the values :DEFAULT
+	        (the default), :MACOS, :UNIX, or :INFERRED in Clozure CL.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">When defaulted to or specified as :DEFAULT, the format of the file
+	        stream is determined by the value of the variable
+	        CCL:*DEFAULT-EXTERNAL-FORMAT*. See below.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">When specified as :UNIX, all characters are read from and written
+	        to files verbatim.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">When specified as :MACOS, all #\Return characters read from the
+	        file are immediately translated to #\Linefeed (#\Newline); all #\Newline
+	        (#\Linefeed) characters are written externally as #\Return characters.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">When specified as :INFERRED and the file is open for input, the
+	        first buffer-full of input data is examined; if a #\Return character
+	        appears in the buffer before the first #\Linefeed, the file stream's
+	        external-format is set to :MACOS; otherwise, it is set to :UNIX.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">All other values of :EXTERNAL-FORMAT - and any combinations that
+	        don't make sense, such as trying to infer the format of a
+	        newly-created output file stream - are treated as if :UNIX was
+	        specified. As mentioned above, the :EXTERNAL-FORMAT argument doesn't
+	        apply to binary file streams.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">The translation performed when :MACOS is specified or inferred has
+	        a somewhat greater chance of doing the right thing than the
+	        *alternate-line-terminator* mechanism does; it probably has a somewhat
+	        greater chance of doing the wrong thing, as well.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_default-external-format"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>CCL:*DEFAULT-EXTERNAL-FORMAT*</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441123"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">The value of this variable is used when :EXTERNAL-FORMAT is
+	        unspecified or specified as :DEFAULT. It can meaningfully be given any
+	        of the values :UNIX, :MACOS, or :INFERRED, each of which is interpreted
+	        as described above.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Because there's some risk that unsolicited newline translation
+	        could have undesirable consequences, the initial value of this variable
+	        in Clozure CL is :UNIX.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="c_ns-lisp-string"></a>
+              <strong>[Class]</strong>
+              <br></br>
+              <code>CCL::NS-LISP-STRING</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441173"></a>
+                <div class="header">Superclasses:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">NS:NS-STRING</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441185"></a>
+                <div class="header">Initargs:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">:string</span></i>---
+		          a Lisp string which is to be the content of
+		          the newly-created ns-lisp-string.
+		        </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441212"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	        This class
+	        implements the interface of an NSString, which means that it can
+	        be passed to any Cocoa or Core Foundation function which expects
+	        one.
+	      </p>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	        The string itself is stored on the Lisp heap, which
+	        means that its memory management is automatic.  However, the
+	        ns-lisp-string object itself is a foreign
+	        object (that is, it has an objc metaclass), and resides on the
+	        foreign heap.  Therefore, it is necessary to explicitly free
+	        it, by sending a dealloc message.
+	      </p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441231"></a>
+                <div class="header">Examples:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	        You can create an ns-lisp-string with
+	        <span class="function"><strong>make-instance</strong></span>, just like
+	        any normal Lisp class:
+	      </p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">? (defvar *the-string*
+     (make-instance 'ccl::ns-lisp-string
+                    :string "Hello, Cocoa."))
+</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	        When you are done with the string, you must explicitly
+	        deallocate it:
+	      </p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">? (ccl::send *the-string* 'dealloc)</pre>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	        You may wish to use an <span class="function"><strong>unwind-protect</strong></span>
+	        form to ensure that this happens:
+	      </p>
+                <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">(let (*the-string*)
+  (unwind-protect (progn (setq *the-string*
+                               (make-instance 'ccl::ns-lisp-string
+                                              :string "Hello, Cocoa."))
+                         (format t "~&amp;The string is ~D characters long.~%"
+                                 (ccl::send *the-string* 'length)))
+    (when *the-string*
+      (ccl::send *the-string* 'dealloc))))
+</pre>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441284"></a>
+                <div class="header">Notes:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">
+	        Currently, ns-lisp-string is defined in
+	        the file ccl/examples/cocoa-backtrace.lisp, which is a
+	        rather awkward place.  It was probably not originally meant
+	        as a public utility at all.  It would be good if it were
+	        moved someplace else.  Use at your own risk.
+	      </p>
+              </div>
+            </div>
+          </p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Understanding-and-Configuring-the-Garbage-Collector"></a>ChapterÂ 15.Â Understanding and Configuring the Garbage Collector</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Heap-space-allocation">15.1. Heap space allocation</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#The-Ephemeral-GC">15.2. The Ephemeral GC</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#GC-Page-reclamation-policy">15.3. GC Page reclamation policy</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#iPure--areas-are-read-only--paged-from-image-file">15.4. "Pure" areas are read-only, paged from image file</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Weak-References">15.5. Weak References</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Weak-References-Dictionary">15.6. Weak References Dictionary</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Garbage-Collection-Dictionary">15.7. Garbage-Collection Dictionary</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Heap-space-allocation"></a>15.1.Â Heap space allocation</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Release 0.10 or later of <code class="literal">CCL</code> uses a different memory
+      management scheme than previous versions did. Those earlier
+      versions would allocate a block of memory (of specified size) at
+      startup and would allocate lisp objects within that block. When
+      that block filled with live (non-GCed) objects, the lisp would
+      signal a "heap full" condition. The heap size imposed a limit on
+      the size of the largest object that could be allocated.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The new strategy involves reserving a very large (2GB on
+      DarwinPPC32, 1GB on LinuxPPC, "very large" on 64-bit
+      implementations) block at startup and consuming (and
+      relinquishing) its contents as the size of the live lisp heap
+      data grows and shrinks. After the initial heap image loads and
+      after each full GC, the lisp kernel will try to ensure that a
+      specified amount (the "lisp-heap-gc-threshold") of free memory
+      is available. The initial value of this kernel variable is 16MB
+      on 32-bit implementations and 32MB on 64-bit implementations ;
+      it can be manipulated from Lisp (see below.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The large reserved memory block consumes very little in
+      the way of system resources; memory that's actually committed to
+      the lisp heap (live data and the "threshold" area where
+      allocation takes place) consumes finite resources (physical
+      memory and swap space). The lisp's consumption of those
+      resources is proportional to its actual memory usage, which is
+      generally a good thing.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">This scheme is much more flexible than the old one, but it
+      may also increase the possibility that those resources can
+      become exhausted.  Neither the new scheme nor the old handles
+      that situation gracefully; under the old scheme, a program that
+      consumes lots of memory may have run into an artificial limit on
+      heap size before exhausting virtual memory.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The -R or âheap-reserve command-line option can be
+      use to limit the size of the reserved block and therefore bound
+      heap expansion. Running</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+&gt; openmcl --heap-reserve 8M
+</pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">would provide an execution environment that's very similar to
+that provided by earlier <code class="literal">CCL</code> versions.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="The-Ephemeral-GC"></a>15.2.Â The Ephemeral GC</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">For many programs, the following observations are true to
+      a very large degree:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+            <ol type="1">
+              <li>
+                <p>Most heap-allocated objects have very short lifetimes ("are
+	  ephemeral"): they become inaccessible soon after they're created.</p>
+              </li>
+              <li>
+                <p>Most non-ephemeral objects have very long lifetimes: it's
+	  rarely productive for the GC to consider reclaiming them, since
+	  it's rarely able to do so. (An object that has survived a large
+	  number of GCs is likely to survive the next one. That's not always
+	  true of course, but it's a reasonable heuristic.)</p>
+              </li>
+              <li>
+                <p>It's relatively rare for an old object to be destructively
+	  modified (via SETF) so that it points to a new one, therefore most
+	  references to newly-created objects can be found in the stacks and
+	  registers of active threads. It's not generally necessary to scan
+	  the entire heap to find references to new objects (or to prove that
+	  such references don't exists), though it is necessary to keep
+	  track of the (hopefully exceptional) cases where old objects are
+	  modified to point at new ones.</p>
+              </li>
+            </ol>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">"Ephemeral" (or "generational") garbage collectors try to
+      exploit these observations: by concentrating on frequently
+      reclaiming newly-created objects quickly, it's less often
+      necessary to do more expensive GCs of the entire heap in order
+      to reclaim unreferenced memory.  In some environments, the
+      pauses associated with such full GCs can be noticeable and
+      disruptive, and minimizing the frequency (and sometimes the
+      duration) of these pauses is probably the EGC's primary goal
+      (though there may be other benefits, such as increased locality
+      of reference and better paging behavior.) The EGC generally
+      leads to slightly longer execution times (and slightly higher,
+      amortized GC time), but there are cases where it can improve
+      overall performance as well; the nature and degree of its impact
+      on performance is highly application-dependent.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Most EGC strategies (including the one employed by
+      <code class="literal">CCL</code>) logically or physically divide memory into one or more
+      areas of relatively young objects ("generations") and one or
+      more areas of old objects.  Objects that have survived one or
+      more GCs as members of a young generation are promoted (or
+      "tenured") into an older generation, where they may or may not
+      survive long enough to be promoted to the next generation and
+      eventually may become "old" objects that can only be reclaimed
+      if a full GC proves that there are no live references to them.
+      This filtering process isn't perfect - a certain amount of
+      premature tenuring may take place - but it usually works very
+      well in practice.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">It's important to note that a GC of the youngest
+      generation is typically very fast (perhaps a few milliseconds on
+      a modern CPU, depending on various factors), <code class="literal">CCL</code>'s EGC is
+      not concurrent and doesn't offer realtime guarantees.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code>'s EGC maintains three ephemeral generations; all
+      newly created objects are created as members of the youngest
+      generation. Each generation has an associated
+      <span class="emphasis"><em>threshold</em></span>, which indicates the number of
+      bytes in it and all younger generations that can be allocated
+      before a GC is triggered. These GCs will involve the target
+      generation and all younger ones (and may therefore cause some
+      premature tenuring); since the older generations have larger
+      thresholds, they're GCed less frequently and most short-lived
+      objects that make it into an older generation tend not to
+      survive there very long.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The EGC can be <span class="emphasis"><em>enabled</em></span> or
+      <span class="emphasis"><em>disabled</em></span> under program control; under some
+      circumstances, it may be enabled but
+      <span class="emphasis"><em>inactive</em></span> (because a full GC is imminent.)
+      Since it may be hard to know or predict the consing behavior of
+      other threads, the distinction between the "active" and
+      "inactive" state isn't very meaningful, especially when native
+      threads are involved.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="GC-Page-reclamation-policy"></a>15.3.Â GC Page reclamation policy</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">After a full GC finishes, it'll try to ensure that at
+      least (LISP-HEAP-GC-THRESHOLD) of virtual memory are available;
+      objects will be allocated in this block of memory until it fills
+      up, the GC is triggered, and the process repeats itself.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Many programs reach near stasis in terms of the amount of
+      logical memory that's in use after full GC (or run for long
+      periods of time in a nearly static state), so the logical
+      address range used for consing after the Nth full GC is likely
+      to be nearly or entirely identical to the address range used by
+      the N+1th full GC.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">By default (and traditionally in <code class="literal">CCL</code>), the GC's policy
+      is to "release" the pages in this address range: to advise the
+      virtual memory system that the pages contain garbage and any
+      physical pages associated with them don't need to be swapped out
+      to disk before being reused and to (re-)map the logical address
+      range so that the pages will be zero-filled by the virtual
+      memory system when they're next accessed.  This policy is
+      intended to reduce the load on the VM system and keep <code class="literal">CCL</code>'s
+      working set to a minimum.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For some programs (especially those that cons at a very
+      high rate), the default policy may be less than ideal: releasing
+      pages that are going to be needed almost immediately - and
+      zero-fill-faulting them back in, lazily - incurs unnecessary
+      overhead. (There's a false economy associated with minimizing
+      the size of the working set if it's just going to shoot back up
+      again until the next GC.) A policy of "retaining" pages between
+      GCs might work better in such an environment.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Functions described below give the user some control over
+      this behavior. An adaptive, feedback-mediated approach might
+      yield a better solution.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="iPure--areas-are-read-only--paged-from-image-file"></a>15.4.Â "Pure" areas are read-only, paged from image file</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">SAVE-APPLICATION identifies code vectors and the pnames of
+      interned symbols and copies these objects to a "pure" area of
+      the image file it creates. (The "pure" area accounts for most of
+      what the ROOM function reports as "static" space.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When the resulting image file is loaded, the pure area of
+      the file is now memory-mapped with read-only access. Code and
+      pure data are paged in from the image file as needed (and don't
+      compete for global virtual memory resources with other memory
+      areas.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Code-vectors and interned symbol pnames are immutable : it
+      is an error to try to change the contents of such an
+      object. Previously, that error would have manifested itself in
+      some random way. In the new scheme, it'll manifest itself as an
+      "unhandled exception" error in the Lisp kernel. The kernel could
+      probably be made to detect a spurious, accidental write to
+      read-only space and signal a lisp error in that case, but it
+      doesn't yet do so.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The image file should be opened and/or mapped in some mode
+      which disallows writing to the memory-mapped regions of the file
+      from other processes. I'm not sure of how to do that; writing to
+      the file when it's mapped by <code class="literal">CCL</code> can have unpredictable and
+      unpleasant results.  SAVE-APPLICATION will delete its output
+      file's directory entry and create a new file; one may need to
+      exercise care when using file system utilities (like tar, for
+      instance) that might overwrite an existing image file.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Weak-References"></a>15.5.Â Weak References</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">In general, a "weak reference" is a reference to an object
+      which does not prevent the object from being garbage-collected.
+      For example, suppose that you want to keep a list of all the
+      objects of a certain type.  If you don't take special steps, the
+      fact that you have a list of them will mean that the objects are
+      always "live", because you can always reference them through the
+      list.  Therefore, they will never be garbage-collected, and
+      their memory will never be reclaimed, even if they are
+      referenced nowhere else in the program.  If you don't want this
+      behavior, you need weak references.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml"><code class="literal">CCL</code> supports weak references with two kinds of objects:
+      weak hash tables and populations.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Weak hash tables are created with the standard Common Lisp
+      function <code class="literal">make-hash-table</code>, which is extended
+      to accept the keyword argument <code class="literal">:weak</code>.  Hash
+      tables may be weak with respect to either their keys or their
+      values.  To make a hash table with weak keys, invoke
+      <code class="literal">make-hash-table</code> with the option :weak t, or,
+      equivalently, :weak :key.  To make one with weak values, use
+      :weak :value.  When the key is weak, the equality test must be
+      #'eq (because it wouldn't make sense otherwise).</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When garbage-collection occurs, key-value pairs are
+      removed from the hash table if there are no non-weak references to
+      the weak element of the pair (key or value).</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In general, weak-key hash tables are useful when you want
+      to use the hash to store some extra information about the
+      objects you look up in it, while weak-value hash tables are
+      useful when you want to use the hash as an index for looking up
+      objects.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">A population encapsulates an object, causing certain
+      reference from the object to be considered weak.  <code class="literal">CCL</code> supports
+      two kinds of populations: lists, in which case the encapsulated
+      object is a list of elements, which are spliced out of the list
+      when there are no non-weak references to the element; and alists,
+      in which case the encapsulated object is a list of conses which
+      are spliced out of the list if there are no non-weak references
+      to the car of the cons.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you are experimenting with weak references
+      interactively, remember that an object is not dead if it was
+      returned by one of the last three interactively-evaluated
+      expressions, because of the variables <code class="literal">*</code>,
+      <code class="literal">**</code>, and <code class="literal">***</code>.  The easy
+      workaround is to evaluate some meaningless expression before
+      invoking <code class="literal">gc</code>, to get the object out of the
+      REPL variables.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Weak-References-Dictionary"></a>15.6.Â Weak References Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_make-population"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>make-population</strong></span> <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;key</em> type initial-contents</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id442732"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">type</span></i>---The type of population, one of <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:LIST</code> (the default) or <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:ALIST</code></p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">initial-contents</span></i>--- A sequence of elements (or conses, for <code xmlns="http://www.w3.org/1999/xhtml" class="literal">:alist</code>) to be used to initialize the
+              population. The sequence itself (and the conses in case of an
+              alist) is not stored in the population, a new list or alist is created to hold the elements.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id442791"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Creates a new population of the specified type.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_population-type"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>population-type</strong></span> population</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id442848"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">returns the type of <code class="literal">population</code>, one of <code class="literal">:LIST</code> or <code class="literal">:ALIST</code></p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_population-contents"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>population-contents</strong></span> population</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id443018"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">returns the list encapsulated in <code class="literal">population</code>.
+        Note that as long as there is a direct (non-weak) reference to this
+        list, it will not be modified by the garbage collector.  Therefore it is
+        safe to traverse the list, and even modify it, no different from any
+        other list. If you want the elements to become garbage-collectable
+        again, you must stop refering to the list directly.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_setf_population-contents"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>(setf (<span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>population-contents</strong></span> population) contents)</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id443087"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Sets the list encapsulated in <code class="literal">population</code> to
+        <code class="literal">contents</code>.  <code class="literal">Contents</code> is not copied,
+        it is used directly.</p>
+              </div>
+            </div>
+          </p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Garbage-Collection-Dictionary"></a>15.7.Â Garbage-Collection Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_lisp-heap-gc-threshold"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="function">
+                  <strong>lisp-heap-gc-threshold</strong>
+                </span>
+              </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id443171"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns the value of the kernel variable that specifies the
+	  amount of free space to leave in the heap after full GC.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_set-lisp-heap-gc-threshold"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	    <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>set-lisp-heap-gc-threshold</strong></span> new-threshold
+	  </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id443232"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">new-threshold</span></i>---The requested new lisp-heap-gc-threshold.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id443258"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Sets the value of the kernel variable that specifies the
+	  amount of free space to leave in the heap after full GC to
+	  new-value, which should be a non-negative fixnum. Returns the
+	  value of that kernel variable (which may be somewhat larger than
+	  what was specified).</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_use-lisp-heap-gc-threshold"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+	    <span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>use-lisp-heap-gc-threshold</strong></span>
+	  </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id443319"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tries to grow or shrink lisp's heap space, so that the
+	  free space is (approximately) equal to the current heap threshold.
+	  Returns NIL</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_egc"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>egc</strong></span> arg</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id431982"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg</span></i>---a generalized boolean</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432008"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Enables the EGC if arg is non-nil, disables the EGC
+	  otherwise. Returns the previous enabled status. Although this
+	  function is thread-safe (in the sense that calls to it are
+	  serialized), it doesn't make a whole lot of sense to be
+	  turning the EGC on and off from multiple threads ...</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_egc-enabled-p"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="function">
+                  <strong>egc-enabled-p</strong>
+                </span>
+              </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432067"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns T if the EGC was enabled at the time of the call,
+	  NIL otherwise.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_egc-active-p"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="function">
+                  <strong>egc-active-p</strong>
+                </span>
+              </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432123"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns T if the EGC was active at the time of the call, NIL
+	  otherwise. Since this is generally a volatile piece of
+	  information, it's not clear whether this function serves a
+	  useful purpose when native threads are involved.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_egc-configuration"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="function">
+                  <strong>egc-configuration</strong>
+                </span>
+              </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432181"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns, as multiple values, the sizes in kilobytes of the
+	  thresholds associated with the youngest ephemeral generation, the
+	  middle ephemeral generation, and the oldest ephemeral generation</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_configure-gcc"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>configure-egc</strong></span>
+	  generation-0-size generation-1-size
+	  generation-2-size</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432239"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">generation-0-size</span></i>---the requested threshold size of the youngest
+		generation, in kilobytes</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">generation-1-size</span></i>---the requested threshold size of the middle generation,
+		in kilobytes</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">generation-2-size</span></i>---the requested threshold size of the oldest generation,
+		in kilobytes</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432295"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Puts the indicated threshold sizes in effect.
+          Each threshold indicates the total size that may be allocated
+          in that and all younger generations before a GC is triggered.
+          Disables EGC while setting the values.
+	  (The provided threshold sizes are rounded up to a multiple of
+	  64Kbytes in <code class="literal">CCL</code> 0.14 and to a multiple of 32KBytes in earlier
+	  versions.)</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_gc-retain-pages"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>gc-retain-pages</strong></span> arg</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432360"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">arg</span></i>---a generalized boolean</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432386"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Tries to influence the GC to retain/recycle the pages
+	  allocated between GCs if arg is true, and to release them
+	  otherwise. This is generally a tradeoff between paging and other
+	  VM considerations.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_gc-retaining-pages"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="function">
+                  <strong>gc-retaining-pages</strong>
+                </span>
+              </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id432444"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns T if the GC tries to retain pages between full GCs
+	  and NIL if it's trying to release them to improve VM paging
+	  performance.</p>
+              </div>
+            </div>
+          </p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Implementation-Details-of-CCL"></a>ChapterÂ 16.Â Implementation Details of Clozure CL</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Threads-and-exceptions">16.1. Threads and exceptions</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#The-Thread-Context-Record">16.1.1. The Thread Context Record</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Exception-contexts-comma---and-exception-handling-in-general">16.1.2. Exception contexts, and exception-handling in general</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Threads-comma---exceptions-comma---and-the-GC">16.1.3. Threads, exceptions, and the GC</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#PC-lusering">16.1.4. PC-lusering</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Register-usage-and-tagging">16.2. Register usage and tagging</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Register-usage-and-tagging-overview">16.2.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#pc-locatives-on-the-PPC">16.2.2. pc-locatives on the PPC</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Register-and-stack-usage-conventions">16.2.3. Register and stack usage conventions</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Tagging-scheme">16.2.4. Tagging scheme</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Heap-Allocation">16.3. Heap Allocation</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Per-thread-object-allocation">16.3.1. Per-thread object allocation</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Allocation-of-reserved-heap-segments">16.3.2. Allocation of reserved heap segments</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Heap-growth">16.3.3. Heap growth</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#GC-details">16.4. GC details</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Mark-phase">16.4.1. Mark phase</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Relocation-phase">16.4.2. Relocation phase</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Forwarding-phase">16.4.3. Forwarding phase</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Compact-phase">16.4.4. Compact phase</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#The-ephemeral-GC">16.5. The ephemeral GC</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Fasl-files">16.6. Fasl files</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#The-Objective-C-Bridge--1-">16.7. The Objective-C Bridge</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#How-CCL-Recognizes-Objective-C-Objects">16.7.1. How Clozure CL Recognizes Objective-C Objects</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#id437620">16.7.2. Recommended Reading</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+          </dl>
+        </div>
+        <p xmlns="http://www.w3.org/1999/xhtml">This chapter describes many aspects of OpenMCL's
+    implementation as of (roughly) version 1.1. Details vary a bit
+    between the three architectures (PPC32, PPC64, and x86-64)
+    currently supported and those details change over time, so the
+    definitive reference is the source code (especially some files in
+    the ccl/compiler/ directory whose names contain the string "arch"
+    and some files in the ccl/lisp-kernel/ directory whose names
+    contain the string "constants".) Hopefully, this chapter will make
+    it easier for someone who's interested to read and understand the
+    contents of those files.</p>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Threads-and-exceptions"></a>16.1.Â Threads and exceptions</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL's threads are "native" (meaning that they're
+        scheduled and controlled by the operating system.)  Most of the
+        implications of this are discussed elsewhere; this section tries
+        to describe how threads look from the lisp kernel's perspective
+        (and especially from the GC's point of view.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL's runtime system tries to use machine-level
+        exception mechanisms (conditional traps when available,
+        illegal instructions, memory access protection in some cases)
+        to detect and handle exceptional situations.  These situations
+        include some TYPE-ERRORs and PROGRAM-ERRORS (notably
+        wrong-number-of-args errors), and also include cases like "not
+        being able to allocate memory without GCing or obtaining more
+        memory from the OS."  The general idea is that it's usually
+        faster to pay (very occasional) exception-processing overhead
+        and figure out what's going on in an exception handler than it
+        is to maintain enough state and context to handle an
+        exceptional case via a lighter-weight mechanism when that
+        exceptional case (by definition) rarely occurs.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Some emulated execution environments (the Rosetta PPC
+        emulator on x86 versions of Mac OS X) don't provide accurate
+        exception information to exception handling functions. Clozure CL
+        can't run in such environments.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="The-Thread-Context-Record"></a>16.1.1.Â The Thread Context Record</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">When a lisp thread is first created (or when a thread
+          created by foreign code first calls back to lisp), a data
+          structure called a Thread Context Record (or TCR) is
+          allocated and initialized.  On modern versions of Linux and
+          FreeBSD, the allocation actually happens via a set of
+          thread-local-storage ABI extensions, so a thread's TCR is
+          created when the thread is created and dies when the thread
+          dies.  (The World's Most Advanced Operating Systemâas
+          Apple's marketing literature refers to Darwinâis not
+          very advanced in this regard, and I know of no reason to
+          assume that advances will be made in this area anytime
+          soon.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A TCR contains a few dozen fields (and is therefore a
+          few hundred bytes in size.)  The fields are mostly
+          thread-specific information about the thread's stacks'
+          locations and sizes, information about the underlying (POSIX)
+          thread, and information about the thread's dynamic binding
+          history and pending CATCH/UNWIND-PROTECTs.  Some of this
+          information could be kept in individual machine registers
+          while the thread is running (and the PPC - which has more
+          registers available - keeps a few things in registers that the
+          X86-64 has to access via the TCR), but it's important to
+          remember that the information is thread-specific and can't
+          (for instance) be kept in a fixed global memory
+          location.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When lisp code is running, the current thread's TCR is
+          kept in a register.  On PPC platforms, a general purpose
+          register is used; on x86-64, an (otherwise nearly useless)
+          segment register works well (prevents the expenditure of a
+          more generally useful general- purpose register for this
+          purpose.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The address of a TCR is aligned in memory in such a way
+          that a FIXNUM can be used to represent it.  The lisp function
+          CCL::%CURRENT-TCR returns the calling thread's TCR as a
+          fixnum; actual value of the TCR's address is 4 or 8 times the
+          value of this fixnum.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When the lisp kernel initializes a new TCR, it's added
+          to a global list maintained by the kernel; when a thread
+          exits, its TCR is removed from this list.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When a thread calls foreign code, lisp stack pointers
+          are saved in its TCR, lisp registers (at least those whose
+          value should be preserved across the call) are saved on the
+          thread's value stack, and (on x86-64) RSP is switched to the
+          control stack.  A field in the TCR (tcr.valence) is then set
+          to indicate that the thread is running foreign code, foreign
+          argument registers are loaded from a frame on the foreign
+          stack, and the foreign function is called. (That's a little
+          oversimplified and possibly inaccurate, but the important
+          things to note are that the thread "stops following lisp
+          stack and register usage conventions" and that it advertises
+          the fact that it's done so.  Similar transitions in a
+          thread's state ("valence") occur when it enters or exits an
+          exception handler (which is sort of an OS/hardware-mandated
+          foreign function call where the OS thoughtfully saves the
+          thread's register state for it beforehand.)</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Exception-contexts-comma---and-exception-handling-in-general"></a>16.1.2.Â Exception contexts, and exception-handling in general</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Unix-like OSes tend to refer to exceptions as "signals";
+          the same general mechanism ("signal handling") is used to
+          process both asynchronous OS-level events (such as the result
+          of the keyboard driver noticing that ^C or ^Z has been
+          pressed) and synchronous hardware-level events (like trying to
+          execute an illegal instruction or access protected memory.)
+          It makes some sense to defer ("block") handling of
+          asynchronous signals so that some critical code sequences
+          complete without interruption; since it's generally not
+          possible for a thread to proceed after a synchronous exception
+          unless and until its state is modified by an exception
+          handler, it makes no sense to talk about blocking synchronous
+          signals (though some OSes will let you do so and doing so can
+          have mysterious effects.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">On OSX/Darwin, the POSIX signal handling facilities
+          coexist with lower-level Mach-based exception handling
+          facilities.  Unfortunately, the way that this is implemented
+          interacts poorly with debugging tools: GDB will generally stop
+          whenever the target program encounters a Mach-level exception
+          and offers no way to proceed from that point (and let the
+          program's POSIX signal handler try to handle the exception);
+          Apple's CrashReporter program has had a similar issue and,
+          depending on how it's configured, may bombard the user with
+          alert dialogs which falsely claim that an application has
+          crashed (when in fact the application in question has
+          routinely handled a routine exception.)  On Darwin/OSX,
+          Clozure CL uses Mach thread-level exception handling facilities
+          which run before GDB or CrashReporter get a chance to confuse
+          themselves; Clozure CL's Mach exception handling tries to force
+          the thread which received a synchronous exception to invoke a
+          signal handling function ("as if" signal handling worked more
+          usefully under Darwin.)  Mach exception handlers run in a
+          dedicated thread (which basically does nothing but wait for
+          exception messages from the lisp kernel, obtain and modify
+          information about the state of threads in which exceptions
+          have occurred, and reply to the exception messages with an
+          indication that the exception has been handled.  The reply
+          from a thread-level exception handler keeps the exception from
+          being reported to GDB or CrashReporter and avoids the problems
+          related to those programs.  Since Clozure CL's Mach exception
+          handler doesn't claim to handle debugging-related exceptions
+          (from breakpoints or single-step operations), it's possible to
+          use GDB to debug Clozure CL.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">On platforms where signal handling and debugging don't
+          get in each other's way, a signal handler is entered with
+          all signals blocked.  (This behavior is specified in the
+          call to the sigaction() function which established the
+          signal handler.)  The signal handler receives three
+          arguments from the OS kernel; the first is an integer that
+          identifies the signal, the second is a pointer to an object
+          of type "siginfo_t", which may or may not contain a few
+          fields that would help to identify the cause of the
+          exception, and the third argument is a pointer to a data
+          structure (called a "ucontext" or something similar), which
+          contains machine-dependent information about the state of
+          the thread at the time that the exception/signal occurred.
+          While asynchronous signals are blocked, the signal handler
+          stores the pointer to its third argument (the "signal
+          context") in a field in the current thread's TCR, sets some
+          bits in another TCR field to indicate that the thread is now
+          waiting to handle an exception, unblocks asynchronous
+          signals, and waits for a global exception lock that
+          serializes exception processing.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">On Darwin, the Mach exception thread creates a signal
+          context (and maybe a siginfo_t structure), stores the signal
+          context in the thread's TCR, sets the TCR field which describes
+          the thread's state, and arranges that the thread resume
+          execution at its signal handling function (with a signal
+          handler, possibly NULL siginfo_t, and signal context as
+          arguments.  When the thread resumes, it waits for the global
+          exception lock.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">On x86-64 platforms where signal handing can be used to
+          handle synchronous exceptions, there's an additional
+          complication: the OS kernel ordinarily allocates the signal
+          context and siginfo structures on the stack of the thread
+          that received the signal; in practice, that means "wherever
+          RSP is pointing."  Clozure CL's
+          <a class="xref" href="#Register-and-stack-usage-conventions" title="16.2.3.Â Register and stack usage conventions">SectionÂ 16.2.3, âRegister and stack usage conventionsâ</a>
+          require that the thread's value stackâwhere RSP is
+          usually pointing while lisp code is runningâcontain
+          only "nodes" (properly tagged lisp objects), and scribbling
+          a signal context all over the value stack would violate this
+          requirement.  To maintain consistency, the sigaltstack()
+          mechanism is used to cause the signal to be delivered on
+          (and the signal context and siginfo to be allocated on) a
+          special stack area (the last few pages of the thread's
+          control stack, in practice).  When the signal handler runs,
+          it (carefully) copies the signal context and siginfo to the
+          thread's control stack and makes RSP point into that stack
+          before invoking the "real" signal handler. The effect of
+          this hack is that the "real" signal handler always runs on
+          the thread's control stack.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Once the exception handler has obtained the global
+          exception lock, it uses the values of the signal number,
+          siginfo_t, and signal context arguments to determine the
+          (logical) cause of the exception.  Some exceptions may be
+          caused by factors that should generate lisp errors or other
+          serious conditions (stack overflow); if this is the case, the
+          kernel code may release the global exception lock and call out
+          to lisp code.  (The lisp code in question may need to repeat
+          some of the exception decoding process; in particular, it
+          needs to be able to interpret register values in the signal
+          context that it receives as an argument.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In some cases, the lisp kernel exception handler may not
+          be able to recover from the exception (this is currently true
+          of some types of memory-access fault and is also true of traps
+          or illegal instructions that occur during foreign code
+          execution.  In such cases, the kernel exception handler
+          reports the exception as "unhandled", and the kernel debugger
+          is invoked.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If the kernel exception handler identifies the
+          exception's cause as being a transient out-of-memory condition
+          (indicating that the current thread needs more memory to cons
+          in), it tries to make that memory available.  In some cases,
+          doing so involves invoking the GC.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Threads-comma---exceptions-comma---and-the-GC"></a>16.1.3.Â Threads, exceptions, and the GC</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL's GC is not concurrent: when the GC is invoked in
+          response to an exception in a particular thread, all other
+          lisp threads must stop until the GC's work is done.  The
+          thread that triggered the GC iterates over the global TCR
+          list, sending each other thread a distinguished "suspend"
+          signal, then iterates over the list again, waiting for a
+          per-thread semaphore that indicates that the thread has
+          received the "suspend" signal and responded appropriately.
+          Once all other threads have acknowledged the request to
+          suspend themselves, the GC thread can run the GC proper (after
+          doing any necessary <a class="xref" href="#PC-lusering" title="16.1.4.Â PC-lusering">SectionÂ 16.1.4, âPC-luseringâ</a>.)  Once the
+          GC's completed its work, the thread that invoked the GC
+          iterates over the global TCR list, raising a per-thread
+          "resume" semaphore for each other thread.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The signal handler for the asynchronous "suspend" signal
+          is entered with all asynchronous signals blocked.  It saves
+          its signal-context argument in a TCR slot, raises the tcr's
+          "suspend" semaphore, then waits on the TCR's "resume"
+          semaphore.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The GC thread has access to the signal contexts of all
+          TCRs (including its own) at the time when the thread received
+          an exception or acknowledged a request to suspend itself.
+          This information (and information about stack areas in the TCR
+          itself) allows the GC to identify the "stack locations and
+          register contents" that are elements of the GC's root
+          set.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="PC-lusering"></a>16.1.4.Â PC-lusering</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's not quite accurate to say that Clozure CL's compiler
+          and runtime follow precise stack and register usage
+          conventions at all times; there are a few exceptions:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>On both PPC and x86-64 platforms, consing isn't
+	          fully atomic.It takes at least a few instructions to
+	          allocate an object in memory(and slap a header on it if
+	          necessary); if a thread is interrupted in the middle of
+	          that instruction sequence, the new object may or may
+	          not have been created or fully initialized at the point in
+	          time that the interrupt occurred.  (There are actually a
+	          few different states of partial initialization)</p>
+                </li>
+                <li>
+                  <p>On the PPC, the common act of building a lisp
+	          control stack frame involves allocating a four-word frame
+	          and storing three register values into that frame.  (The
+	          fourth word - the back pointer to the previous frame - is
+	          automatically set when the frame is allocated.)  The
+	          previous contents of those three words are unknown (there
+	          might have been a foreign stack frame at the same address a
+	          few instructions earlier),so interrupting a thread that's
+	          in the process of initializing a PPC control stack frame
+	          isn't GC-safe.</p>
+                </li>
+                <li>
+                  <p>There are similar problems with the initialization
+	          of temp stackframes on the PPC.  (Allocation and
+	          initialization doesn't happen atomically, and the newly
+	          allocated stack memory may have undefined contents.)</p>
+                </li>
+                <li>
+                  <p><a class="xref" href="#The-ephemeral-GC" title="16.5.Â The ephemeral GC">SectionÂ 16.5, âThe ephemeral GCâ</a>'s write barrier
+	          has to be implemented atomically (i.e.,both an
+	          intergenerational store and the update of a
+	          corresponding reference bit has to happen without
+	          interruption, or neither of these events can
+	          happen.)</p>
+                </li>
+                <li>
+                  <p>There are a few more similar cases.</p>
+                </li>
+              </ul>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Fortunately, the number of these non-atomic instruction
+          sequences is small, and fortunately it's fairly easy for the
+          interrupting thread to recognize when the interrupted thread
+          is in the middle of such a sequence.  When this is detected,
+          the interrupting thread modifies the state of the interrupted
+          thread (modifying its PC and other registers) so that it is no
+          longer in the middle of such a sequence (it's either backed
+          out of it or the remaining instructions are emulated.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">This works because (a) many of the troublesome
+          instruction sequences are PPC-specific and it's relatively
+          easy to partially disassemble the instructions surrounding the
+          interrupted thread's PC on the PPC and (b) those instruction
+          sequences are heavily stylized and intended to be easily
+          recognized.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Register-usage-and-tagging"></a>16.2.Â Register usage and tagging</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Register-usage-and-tagging-overview"></a>16.2.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Regardless of other details of its implementation, a
+	      garbage collector's job is to partition the set of all
+	      heap-allocated lisp objects (CONSes, STRINGs, INSTANCEs, etc.)
+	      into two subsets.  The first subset contains all objects that
+	      are transitively referenced from a small set of "root" objects
+	      (the contents of the stacks and registers of all active
+	      threads at the time the GC occurs and the values of some
+	      global variables.)  The second subset contains everything
+	      else: those lisp objects that are not transitively reachable
+	      from the roots are garbage, and the memory occupied by garbage
+	      objects can be reclaimed (since the GC has just proven that
+ 	      it's impossible to reference them.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The set of live, reachable lisp objects basically form
+          the nodes of a (usually large) graph, with edges from each
+          node A to any other objects (nodes) that object A
+          references.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Some nodes in this graph can never have outgoing edges:
+          an array with a specialized numeric or character type usually
+          represents its elements in some (possibly more compact)
+          specialized way.  Some nodes may refer to lisp objects that
+          are never allocated in memory (FIXNUMs, CHARACTERs,
+          SINGLE-FLOATs on 64-bit platforms ..)  This latter class of
+          objects are sometimes called "immediates", but that's a little
+          confusing because the term "immediate" is sometimes used to
+          refer to things that can never be part of the big connectivity
+          graph (e.g., the "raw" bits that make up a floating-point
+          value, foreign address, or numeric value that needs to be used
+          - at least fleetingly - in compiled code.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">For the GC to be able to build the connectivity graph
+          reliably, it's necessary for it to be able to reliably tell
+          (a) whether or not a "potential root" - the contents of a
+          machine register or stack location - is in fact a node and (b)
+          for any node, whether it may have components that refer to
+          other nodes.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">There's no reliable way to answer the first question on
+          stock hardware.  (If everything was a node, as might be the
+          case on specially microcoded "lisp machine" hardware, it
+          wouldn't even need to be asked.)  Since there's no way to just
+          look at a machine word (the contents of a machine register or
+          stack location) and tell whether or not it's a node or just
+          some random non-node value, we have to either adopt and
+          enforce strict conventions on register and stack usage or
+          tolerate ambiguity.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">"Tolerating ambiguity" is an approach taken by some
+          ("conservative") GC schemes; by contrast, Clozure CL's GC is
+          "precise", which in this case means that it believes that the
+          contents of certain machine registers and stack locations are
+          always nodes and that other registers and stack locations are
+          never nodes and that these conventions are never violated by
+          the compiler or runtime system.  The fact that threads are
+          preemptively scheduled means that a GC could occur (because of
+          activity in some other thread) on any instruction boundary,
+          which in turn means that the compiler and runtime system must
+          follow precise <a class="xref" href="#Register-and-stack-usage-conventions" title="16.2.3.Â Register and stack usage conventions">SectionÂ 16.2.3, âRegister and stack usage conventionsâ</a> at all
+          times.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Once we've decided that a given machine word is a node,
+          a <a class="xref" href="#Tagging-scheme" title="16.2.4.Â Tagging scheme">SectionÂ 16.2.4, âTagging schemeâ</a> describes how the node's
+          value and type are encoded in that machine word.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Most of this discussionâso farâhas treated
+          things from the GC's very low-level perspective. From a much
+          higher point of view, lisp functions accept nodes as
+          arguments, return nodes as values, and (usually) perform
+          some operations on those arguments in order to produce those
+          results.  (In many cases, the operations in question involve
+          raw non-node values.)  Higher-level parts of the lisp type
+          system (functions like TYPE-OF and CLASS-OF, etc.) depend on
+          the <a class="xref" href="#Tagging-scheme" title="16.2.4.Â Tagging scheme">SectionÂ 16.2.4, âTagging schemeâ</a>.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="pc-locatives-on-the-PPC"></a>16.2.2.Â pc-locatives on the PPC</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">On the PPC, there's a third case (besides "node" and
+          "immediate" values).  As discussed below, a node that denotes
+          a memory-allocated lisp object is a biased (tagged) pointer
+          -to- that object; it's not generally possible to point -into-
+          some composite (multi-element) object (such a pointer would
+          not be a node, and the GC would have no way to update the
+          pointer if it were to move the underlying object.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Such a pointer ("into" the interior of a heap-allocated
+          object) is often called a <span class="emphasis"><em>locative</em></span>; the
+          cases where locatives are allowed in Clozure CL mostly involve
+          the behavior of function call and return instructions.  (To be
+          technically accurate, the other case also arises on x86-64, but
+          that case isn't as user-visible.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">On the PowerPC (both PPC32 and PPC64), all machine
+          instructions are 32 bits wide and all instruction words are
+          allocated on 32-bit boundaries.  In PPC Clozure CL, a CODE-VECTOR
+          is a specialized type of vector-like object; its elements
+          are 32-bit PPC machine instructions.  A CODE-VECTOR is an
+          attribute of a FUNCTION object; a function call involves
+          accessing the function's code-vector and jumping to the
+          address of its first instruction.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">As each instruction in the code vector sequentially
+          executes, the hardware program counter (PC) register advances
+          to the address of the next instruction (a locative into the
+          code vector); since PPC instructions are always 32 bits wide
+          and aligned on 32-bit boundaries, the low two bits of the PC
+          are always 0.  If the function executes a call (simple call
+          instructions have the mnemonic "bl" on the PPC, which stands
+          for "branch and link"), the address of the next instruction
+          (also a word-aligned locative into a code-vector) is copied
+          into the special- purpose PPC "link register" (lr); a function
+          returns to its caller via a "branch to link register" (blr)
+          instruction.  Some cases of function call and return might
+          also use the PPC's "count register" (ctr), and if either the
+          lr or ctr needs to be stored in memory it needs to first be
+          copied to a general-purpose register.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL's GC understands that certain registers contain
+          these special "pc-locatives" (locatives that point into
+          CODE-VECTOR objects); it contains special support for
+          finding the containing CODE-VECTOR object and for adjusting
+          all of these "pc-locatives" if the containing object is
+          moved in memory.  The first part of that
+          operationâfinding the containing objectâis
+          possible and practical on the PPC because of architectural
+          artifacts (fixed-width instructions and arcana of
+          instruction encoding.)  It's not possible on x86-64, but
+          fortunately not necessary either (though the second part -
+          adjusting the PC/RIP when the containing object moves) is
+          both necessary and simple.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Register-and-stack-usage-conventions"></a>16.2.3.Â Register and stack usage conventions</h3>
+                </div>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Stack-conventions"></a>16.2.3.1.Â Stack conventions</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">On both PPC and X86 platforms, each lisp thread uses 3
+            stacks; the ways in which these stacks are used differs
+            between the PPC and X86.</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">Each thread has:</p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+                <ul type="disc">
+                  <li>
+                    <p>A "control stack".  On both platforms, this is
+	            "the stack" used by foreign code.  On the PPC, it
+	            consists of a linked list of frames where the first word
+	            in each frame points to the first word in the previous
+	            frame (and the outermost frame points to 0.)  Some
+	            frames on a PPC control stack are lisp frames; lisp
+	            frames are always 4 words in size and contain (in
+	            addition to the back pointer to the previous frame) the
+	            calling function (a node), the return address (a
+	            "locative" into the calling function's code-vector), and
+	            the value to which the value-stack pointer (see below)
+	            should be restored on function exit.  On the PPC, the GC
+	            has to look at control-stack frames, identify which of
+	            those frames are lisp frames, and treat the contents of
+	            the saved function slot as a node (and handle the return
+	            address locative specially.)  On x86-64, the control
+	            stack is used for dynamic-extent allocation of immediate
+	            objects.  Since the control stack never contains nodes
+	            on x86-64, the GC ignores it on that platform.
+	            Alignment of the control stack follows the ABI
+	            conventions of the platform (at least at any point in
+	            time where foreign code could run.)  On PPC, the r1
+	            register always points to the top of the current
+	            thread's control stack; on x86-64, the RSP register
+	            points to the top of the current thread's control stack
+	            when the thread is running foreign code and the address
+	            of the top of the control stack is kept in the thread's
+	            TCR (see <a class="xref" href="#The-Thread-Context-Record" title="16.1.1.Â The Thread Context Record">SectionÂ 16.1.1, âThe Thread Context Recordâ</a>
+	            when not running foreign code.  The control stack "grows
+	            down."</p>
+                  </li>
+                  <li>
+                    <p>A "value stack".  On both platforms, all values on
+	            the value stack are nodes (including "tagged return
+	            addresses" on x86-64.)  The value stack is always
+	            aligned to the native word size; objects are always
+	            pushed on the value stack using atomic instructions
+	            ("stwu"/"stdu" on PPC, "push" on x86-64), so the
+	            contents of the value stack between its bottom and top
+	            are always unambiguously nodes; the compiler usually
+	            tries to pop or discard nodes from the value stack as
+	            soon as possible after their last use (as soon as they
+	            may have become garbage.)  On x86-64, the RSP register
+	            addresses the top of the value stack when running lisp
+	            code; that address is saved in the TCR when running
+	            foreign code.  On the PPC, a dedicated register (VSP,
+	            currently r15) is used to address the top of the value
+	            stack when running lisp code, and the VSP value is saved
+	            in the TCR when running foreign code.  The value stack
+	            grows down.</p>
+                  </li>
+                  <li>
+                    <p>A "temp stack".  The temp stack consists of a
+	            linked list of frames, each of which points to the
+	            previous temp stack frame.  The number of native
+	            machine words in each temp stack frame is always even,
+	            so the temp stack is aligned on a two-word (64- or
+	            128-bit) boundary.  The temp stack is used for
+	            dynamic-extent objects on both platforms; on the PPC,
+	            it's used for essentially all such objects (regardless
+	            of whether or not the objects contain nodes); on the
+	            x86-64, immediate dynamic-extent objects (strings,
+	            foreign pointers, etc.)  are allocated on the control
+	            stack and only node-containing dynamic-extent objects
+	            are allocated on the temp stack.  Data structures used
+	            to implement CATCH and UNWIND-PROTECT are stored on
+	            the temp stack on both ppc and x86-64.  Temp stack
+	            frames are always doublenode aligned and objects
+	            within a temp stack frame are aligned on doublenode
+	            boundaries.  The first word in each frame contains a
+	            back pointer to the previous frame; on the PPC, the
+	            second word is used to indicate to the GC whether the
+	            remaining objects are nodes (if the second word is 0)
+	            or immediate (otherwise.)  On x86-64, where temp stack
+	            frames always contain nodes, the second word is always
+	            0.  The temp stack grows down.  It usually takes
+	            several instructions to allocate and safely initialize
+	            a temp stack frame that's intended to contain nodes,
+	            and the GC has to recognize the case where a thread is
+	            in the process of allocating and initializing a temp
+	            stack frame and take care not to interpret any
+	            uninitialized words in the frame as nodes. The PPC
+	            keeps the current top of the temp stack in a dedicated
+	            register (TSP, currently r12) when running lisp code
+	            and saves this register's value in the TCR when
+	            running foreign code.  The x86-64 keeps the address of
+	            the top of each thread's temp stack in the thread's
+	            TCR.</p>
+                  </li>
+                </ul>
+              </div>
+            </div>
+            <div class="sect3" lang="en" xml:lang="en">
+              <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+                <div>
+                  <div>
+                    <h4 class="title"><a id="Register-conventions"></a>16.2.3.2.Â Register conventions</h4>
+                  </div>
+                </div>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">If there are a "reasonable" (for some value of
+            "reasonable") number of general-purpose registers and the
+            instruction set is "reasonably" orthogonal (most
+            instructions that operate on GPRs can operate on any GPR),
+            then it's possible to statically partition the GPRs into at
+            least two sets: "immediate registers" never contain nodes,
+            and "node registers" always contain nodes.  (On the PPC, a
+            few registers are members of a third set of "PC locatives",
+            and on both platforms some registers may have dedicated
+            roles as stack or heap pointers; the latter class is treated
+            as immediates by the GC proper but may be used to help
+            determine the bounds of stack and heap memory areas.)</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">The ultimate definition of register partitioning is
+            hardwired into the GC in functions like "mark_xp()" and
+            "forward_xp()", which process the values of some of the
+            registers in an exception frame as nodes and may give some
+            sort of special treatment to other register values they
+            encounter there.)</p>
+              <p xmlns="http://www.w3.org/1999/xhtml">On x86-64, the static register partitioning scheme involves:</p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+                <ul type="disc">
+                  <li>
+                    <p>(only) three "immediate" registers.</p>
+                    <p>The RAX, RCX, and RDX registers are used as the
+	            implicit operands and results of some extended-precision
+	            multiply and divide instructions which generally involve
+	            non-node values; since their use in these instructions
+	            means that they can't be guaranteed to contain node
+	            values at all times, it's natural to put these registers
+	            in the "immediate" set. RAX is generally given the
+	            symbolic name "imm0", RDX is given the symbolic name
+	            "imm1" and RCX is given the symbolic name "imm2"; you
+	            may see these names in disassembled code, usually in
+	            operations involving type checking, array indexing, and
+	            foreign memory and function access.</p>
+                  </li>
+                  <li>
+                    <p>(only) two "dedicated" registers.</p>
+                    <p>RSP and RBP have
+	            dedicated functionality dictated by the hardware and
+	            calling conventions.</p>
+                  </li>
+                  <li>
+                    <p>11 "node" registers.</p>
+                    <p>All other registers (RBX, RSI, RDI, and R8-R15)
+	            are asserted to contain node values at (almost) all
+	            times; legacy "string" operations that implicitly use RSI
+	            and/or RDI are not used.</p>
+                  </li>
+                </ul>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+		On 32-bit x86, the default register partitioning scheme
+		involves:
+	      </p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+                <ul type="disc">
+                  <li>
+                    <p>
+		  A single "immediate" register.
+		  </p>
+                    <p>
+		    The EAX register is given the symbolic name
+		    "imm0".
+		  </p>
+                  </li>
+                  <li>
+                    <p>
+		    There are two "dedicated" registers.
+		  </p>
+                    <p>
+		    ESP and EBP have dedicated functionality dictated by the
+		    hardware and calling conventions.
+		  </p>
+                  </li>
+                  <li>
+                    <p>
+		    5 "node" registers.
+		  </p>
+                    <p>
+		    The remaining registers, (EBX, ECX, EDX, ESI, EDI) normally
+		    contain node values.  As on x86-64, string instructions
+		    that implicity use ESI and EDI are not used.
+		  </p>
+                  </li>
+                </ul>
+              </div>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+		There are times when this default partitioning scheme is
+		inadequate.  As mentioned in the x86-64 section, there are
+		instructions like the extended-precision MUL and DIV which
+		require the use of EAX and EDX.  We therefore need a way to
+		change this partitioning at run-time.
+	      </p>
+              <p xmlns="http://www.w3.org/1999/xhtml">
+		Two schemes are employed.  The first uses a mask in the TCR
+		that contains a bit for each register.  If the bit is set,
+		the register is interpreted by the GC as a node register; if it's
+		clear, the register is treated as an immediate register.  The
+		second scheme uses the direction flag in the EFLAGS register.
+		If DF is set, EDX is treated as an immediate register.
+		(We don't use the string instructions, so DF isn't otherwise
+		used.)
+	      </p>
+              <p xmlns="http://www.w3.org/1999/xhtml">On the PPC, the static register partitioning scheme
+            involves:</p>
+              <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+                <ul type="disc">
+                  <li>
+                    <p>6 "immediate" registers.</p>
+                    <p>Registers r3-r8 are given
+	            the symbolic names imm0-imm5.  As a RISC architecture
+	            with simpler addressing modes, the PPC probably
+	            uses immediate registers a bit more often than the CISC
+	            x86-64 does, but they're generally used for the same sort
+	            of things (type checking, array indexing, FFI,
+	            etc.)</p>
+                  </li>
+                  <li>
+                    <p>9 dedicated registers
+	            </p>
+                    <div class="itemizedlist">
+                      <ul type="circle">
+                        <li>
+                          <p>r0 (symbolic name rzero) always contains the
+		              value 0 when running lisp code.  Its value is
+		              sometimes read as 0 when it's used as the base
+		              register in a memory address; keeping the value 0
+		              there is sometimes convenient and avoids
+		              asymmetry.</p>
+                        </li>
+                        <li>
+                          <p>r1 (symbolic name sp) is the control stack
+		              pointer, by PPC convention.</p>
+                        </li>
+                        <li>
+                          <p>r2 is used to hold the current thread's TCR on
+		              ppc64 systems; it's not used on ppc32.</p>
+                        </li>
+                        <li>
+                          <p>r9 and r10 (symbolic names allocptr and
+		              allocbase) are used to do per-thread memory
+		              allocation</p>
+                        </li>
+                        <li>
+                          <p>r11 (symbolic name nargs) contains the number
+		              of function arguments on entry and the number of
+		              return values in multiple-value returning
+		              constructs.  It's not used more generally as either
+		              a node or immediate register because of the way that
+		              certain trap instruction encodings are
+		              interpreted.</p>
+                        </li>
+                        <li>
+                          <p>r12 (symbolic name tsp) holds the top of the
+		              current thread's temp stack.</p>
+                        </li>
+                        <li>
+                          <p>r13 is used to hold the TCR on PPC32 systems;
+		              it's not used on PPC64.</p>
+                        </li>
+                        <li>
+                          <p>r14 (symbolic name loc-pc) is used to copy
+		              "pc-locative" values between main memory and
+		              special-purpose PPC registers (LR and CTR) used in
+		              function-call and return instructions.</p>
+                        </li>
+                        <li>
+                          <p>r15 (symbolic name vsp) addresses the top of
+		              the current thread's value stack.</p>
+                        </li>
+                        <li>
+                          <p>lr and ctr are PPC branch-unit registers used
+		              in function call and return instructions; they're
+		              always treated as "pc-locatives", which precludes
+		              the use of the ctr in some PPC looping
+		              constructs.</p>
+                        </li>
+                      </ul>
+                    </div>
+                    <p>
+	          </p>
+                  </li>
+                  <li>
+                    <p>17 "node" registers</p>
+                    <p>r15-r31 are always treated as node
+	            registers</p>
+                  </li>
+                </ul>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Tagging-scheme"></a>16.2.4.Â Tagging scheme</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL always allocates lisp objects on double-node
+          (64-bit for 32-bit platforms, 128-bit for 64-bit platforms)
+          boundaries; this mean that the low 3 bits (32-bit lisp) or 4
+          bits (64-bit lisp) are always 0 and are therefore redundant
+          (we only really need to know the upper 29 or 60 bits in order
+          to identify the aligned object address.)  The extra bits in a
+          lisp node can be used to encode at least some information
+          about the node's type, and the other 29/60 bits represent
+          either an immediate value or a doublenode-aligned memory
+          address.  The low 3 or 4 bits of a node are called the node's
+          "tag bits", and the conventions used to encode type
+          information in those tag bits are called a "tagging
+          scheme."</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It might be possible to use the same tagging scheme on
+          all platforms (at least on all platforms with the same word
+          size and/or the same number of available tag bits), but there
+          are often some strong reasons for not doing so.  These
+          arguments tend to be very machine-specific: sometimes, there
+          are fairly obvious machine-dependent tricks that can be
+          exploited to make common operations on some types of tagged
+          objects faster; other times, there are architectural
+          restrictions that make it impractical to use certain tags for
+          certain types.  (On PPC64, the "ld" (load doubleword) and
+          "std" (store doubleword) instructions - which load and store a
+          GPR operand at the effective address formed by adding the
+          value of another GPR operand and a 16-bit constant operand -
+          require that the low two bits of that constant operand be 0.
+          Since such instructions would typically be used to access the
+          fields of things like CONS cells and structures, it's
+          desirable that that the tags chosen for CONS cells and
+          structures allow the use of these instructions as opposed to
+          more expensive alternatives.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">One architecture-dependent tagging trick that works well
+          on all architectures is to use a tag of 0 for FIXNUMs: a
+          fixnum basically encodes its value shifted left a few bits
+          and keeps those low bits clear. FIXNUM addition,
+          subtraction, and binary logical operations can operate
+          directly on the node operands, addition and subtraction can
+          exploit hardware-based overflow detection, and (in the
+          absence of overflow) the hardware result of those operations
+          is a node (fixnum).  Some other slightly-less-common
+          operations may require a few extra instructions, but
+          arithmetic operations on FIXNUMs should be as cheap as
+          possible and using a tag of zero for FIXNUMs helps to ensure
+          that it will be.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If we have N available tag bits (N = 3 for 32-bit Clozure CL
+	      and N = 4 for 64-bit Clozure CL), this way of representing
+	      fixnums with the low M bits forced to 0 works as long as M
+	      &lt;= N.  The smaller we make M, the larger the values of
+	      MOST-POSITIVE-FIXNUM and MOST-NEGATIVE become; the larger we
+	      make N, the more distinct non-FIXNUM tags become available.
+	      A reasonable compromise is to choose M = N-1; this basically
+	      yields two distinct FIXNUM tags (one for even fixnums, one
+	      for odd fixnums), gives 30-bit fixnums on 32-bit platforms
+	      and 61-bit fixnums on 64-bit platforms, and leaves us with 6
+	      or 14 tags to encoded other types.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Once we get past the assignment of FIXNUM tags, things
+          quickly devolve into machine-dependencies.  We can fairly
+          easily see that we can't directly tag all other primitive
+          lisp object types with only 6 or 14 available tag values;
+          the details of how types are encoded vary between the ppc32,
+          ppc64, and x86-64 implementations, but there are some
+          general common principles:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+              <ul type="disc">
+                <li>
+                  <p>CONS cells always contain exactly 2 elements and are
+	          usually fairly common.It therefore makes sense to give
+	          CONS cells their own tag.  Unlike the fixnum case -
+	          where a tag value of 0 had positive implications - there
+	          doesn't seem to be any advantage to using any particular
+	          value.  (A longtime ago - in the case of 68K MCL - the
+	          CONS tag and the order of CAR and CDR in memory were
+	          chosen to allow smaller, cheaper addressing modes to be
+	          used to "cdr down a list."  That's not a factor on ppc
+	          or x86-64, but all versions of Clozure CL still store the CDR
+	          of a CONS cell first in memory.  It doesn't matter, but
+	          doing it the way that the host system did made
+	          boostrapping to a new target system a little easier.)
+	        </p>
+                </li>
+                <li>
+                  <p>Any way you look at it, NIL is a bit
+	          ... unusual. NIL is both a SYMBOL and a LIST (as well as
+	          being a canonical truth value and probably a few other
+	          things.)  Its role as a LIST is probably much more
+	          important to most programs than its role as a SYMBOL is:
+	          LISTP has to be true of NIL and primitives like CAR and
+	          CDR do LISTP implicitly when safe and want that
+	          operation to be fast. There are several possible
+	          approaches to this problem; Clozure CL uses two of them. On
+	          PPC32 and X86-64, NIL is basically a weird CONS cell
+	          that straddles two doublenodes; the tag of NIL is unique
+	          and congruent modulo 4 (modulo 8 on 64-bit) with the tag
+	          used for CONS cells.  LISTP is therefore true of any
+	          node whose low 2 (or 3) bits contain the appropriate tag
+	          value (it's not otherwise necessary to special-case
+	          NIL.)  SYMBOL accessors (SYMBOL-NAME, SYMBOL-VALUE,
+	          SYMBOL-PLIST ..) -do- have to special-case NIL (and
+	          access the components of an internal proxy symbol.) On
+	          PPC64 (where architectural restrictions dictate the set
+	          of tags that can be used to access fixed components of
+	          an object), that approach wasn't practical.  NIL is just
+	          a distinguished SYMBOL,and it just happens to be the
+	          case that its pname slot and values slot are at the same
+	          offsets from a tagged pointer as a CONS cell's CDR and
+	          CAR would be.  NIL's pname is set to NIL (SYMBOL-NAME
+	          checks for this and returns the string "NIL"), and LISTP
+	          (and therefore safe CAR and CDR) has to check for (OR
+	          NULL CONSP). At least in the case of CAR and CDR, the
+	          fact that the PPC has multiple condition-code fields
+	          keeps that extra test from being prohibitively
+	          expensive.  On IA-32, we can't afford to dedicate a tag to
+		  NIL. NIL is therefore just a distinguished CONS
+		  cell, and we have to explicitly check for a NIL argument
+		  in CONSP/RPLACA/RPLACD.
+		</p>
+                </li>
+                <li>
+                  <p>Some objects are immediate (but not FIXNUMs). This
+	          is true of CHARACTERs and, on 64-bit platforms,
+	          SINGLE-FLOATs. It's also true of some nodes used in the
+	          runtime system (special values used to indicate unbound
+	          variables and slots, for instance.) On 64-bit platforms,
+	          SINGLE-FLOATs have their own unique tag (making them a
+	          little easier to recognize; on all platforms, CHARACTERs
+	          share a tag with other immediate objects (unbound
+	          markers) but are easy to recognize (by looking at
+	          several of their low bits.)  The GC treats any node with
+	          an immediate tag (and any node with a fixnum tag) as a
+	          leaf.</p>
+                </li>
+                <li>
+                  <p>There are some advantages to treating everything
+	          elseâmemory-allocated objects that aren't CONS
+	          cellsâuniformly.There are some disadvantages to
+	          that uniform treatment as well, and the treatment of
+	          "memory-allocated non-CONS objects" isn't entirely
+	          uniform across all Clozure CL implementations.  Let's first
+	          pretend that the treatment is uniform, then discuss the
+	          ways in which it isn't.The "uniform approach" is to
+	          treat all memory-allocated non-CONS objects as if they
+	          were vectors; this use of the term is a little looser
+	          than what's implied by the CL VECTOR type.  Clozure CL
+	          actually uses the term "uvector" to mean "a
+	          memory-allocated lisp object other than a CONS cell,
+	          whose first word is a header that describes the object's
+	          type and the number of elements that it contains."  In
+	          this view, a SYMBOL is a UVECTOR, as is a STRING, a
+	          STANDARD-INSTANCE, a CL array or vector, a FUNCTION, and
+	          even a DOUBLE-FLOAT. In the PPC implementations (where
+	          things are a little more ... uniform), a single tag
+	          value is used to denote any uvector; in order to
+	          determine something more specific about the type of the
+	          object in question, it's necessary to fetch the low byte
+	          of the header word from memory.  On the x86-64 platform,
+	          certain types of uvectors - SYMBOLs and FUNCTIONs -are
+	          given their own unique tags.  The good news about the
+	          x86-64 approach is that SYMBOLs and FUNCTIONs can be
+	          recognized without referencing memory; the slightly bad
+	          news is that primitive operations that work on
+	          UVECTOR-tagged objectsâlike the function
+	          CCL:UVREFâdon't work on SYMBOLs or FUNCTIONs on
+	          x86-64 (but -do- work on those types of objects in the
+	          PPC ports.) The header word that precedes a UVECTOR's
+	          data in memory contains 8 bits of type information in
+	          the low byte and either 24 or 56 bits of "element-count"
+	          information in the rest of the word.  (This is where the
+	          sometimes-limiting value of 2^24 for
+	          ARRAY-TOTAL-SIZE-LIMIT on 32-bit platforms comes from.)
+	          The low byte of the headerâsometimes called the
+	          uvector's subtagâis itself tagged (which means
+	          that the header is tagged.)  The (3 or 4) tag bits in
+	          the subtag are used to determine whether the uvector's
+	          elements are nodes or immediates. (A UVECTOR whose
+	          elements are nodes is called a GVECTOR; a UVECTOR whose
+	          elements are immediates is called an IVECTOR.  This
+	          terminology came from Spice Lisp, which was a
+	          predecessor of CMUCL.)  Even though a uvector header is
+	          tagged, a header is not a node.  There's no (supported)
+	          way to get your hands on one in lisp and doing so could
+	          be dangerous.  (If the value of a header wound up in a
+	          lisp node register and that register wound up getting
+	          pushed on a thread's value stack, the GC might
+	          misinterpret that situation to mean that there was a
+	          stack-allocated UVECTOR on the value stack.)</p>
+                </li>
+              </ul>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Heap-Allocation"></a>16.3.Â Heap Allocation</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">When the Clozure CL kernel first
+        starts up, a large contiguous chunk of the process's address
+        space is mapped as "anonymous, no access" memory. ("Large"
+        means different things in different contexts; on LinuxPPC32,
+        it means "about 1 gigabyte", on DarwinPPC32, it means "about 2
+        gigabytes", and on current 64-bit platforms it ranges from 128
+        to 512 gigabytes, depending on OS. These values are both
+        defaults and upper limits;
+        the <code class="literal">--heap-reserve</code> argument can be used to
+        try to reserve less than the default.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Reserving address space that can't (yet) be read or
+        written to doesn't cost much; in particular, it doesn't require
+        that corresponding swap space or physical memory be available.
+        Marking the address range as being "mapped" helps to ensure that
+        other things (results from random calls to malloc(), dynamically
+        loaded shared libraries) won't be allocated in this region that
+        lisp has reserved for its own heap growth.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">A small portion (around 1/32 on 32-bit platforms and 1/64
+        on 64-bit platforms) of that large chunk of address space is
+        reserved for GC data structures.  Memory pages reserved for
+        these data structures are mapped read-write as pages are made
+        writable in the main portion of the heap.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The initial heap image is mapped into this reserved
+        address space and an additional (LISP-HEAP-GC-THRESHOLD) bytes
+        are mapped read-write.  GC data structures grow to match the
+        amount of GC-able memory in the initial image plus the gc
+        threshold, and control is transferred to lisp code.
+        Inevitably, that code spoils everything and starts consing;
+        there are basically three layers of memory allocation that can
+        go on.</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Per-thread-object-allocation"></a>16.3.1.Â Per-thread object allocation</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Each lisp thread has a private "reserved memory
+          segment"; when a thread starts up, its reserved memory segment
+          is empty.  PPC ports maintain the highest unallocated address
+          and the lowest allocatable address in the current segment in
+          registers when running lisp code; on x86-664, these values are
+          maintained in the current threads's TCR.  (An "empty" heap
+          segment is one whose high pointer and low pointer are equal.)
+          When a thread is not in the middle of allocating something, the
+          low 3 or 4 bits of the high and low pointers are clear (the
+          pointers are doublenode-aligned.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">A thread tries to allocate an object whose physical size
+          in bytes is X and whose tag is Y by:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>decrementing the "high" pointer by (- X Y)</p>
+                </li>
+                <li>
+                  <p>trapping if the high pointer is less than the low
+	          pointer</p>
+                </li>
+                <li>
+                  <p>using the (tagged) high pointer to initialize the
+	          object, if necessary</p>
+                </li>
+                <li>
+                  <p>clearing the low bits of the high pointer</p>
+                </li>
+              </ol>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">On PPC32, where the size of a CONS cell is 8 bytes and
+          the tag of a CONS cell is 1, machine code which sets the arg_z
+          register to the result of doing (CONS arg_y arg_z) looks
+          like:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+  (SUBI ALLOCPTR ALLOCPTR 7)    ; decrement the high pointer by (- 8 1)
+  (TWLLT ALLOCPTR ALLOCBASE)    ; trap if the high pointer is below the base
+  (STW ARG_Z -1 ALLOCPTR)       ; set the CDR of the tagged high pointer
+  (STW ARG_Y 3 ALLOCPTR)        ; set the CAR
+  (MR ARG_Z ALLOCPTR)           ; arg_z is the new CONS cell
+  (RLWINM ALLOCPTR ALLOCPTR 0 0 28)     ; clear tag bits
+	    </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">On x86-64, the idea's similar but the implementation is
+          different.  The high and low pointers to the current thread's
+          reserved segment are kept in the TCR, which is addressed by
+          the gs segment register. An x86-64 CONS cell is 16 bytes wide
+          and has a tag of 3; we canonically use the temp0 register to
+          initialize the object</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+  (subq ($ 13) ((% gs) 216))    ; decrement allocptr
+  (movq ((% gs) 216) (% temp0)) ; load allocptr into temp0
+  (cmpq ((% gs) 224) (% temp0)) ; compare to allocabase
+  (jg L1)                       ; skip trap
+  (uuo-alloc)                   ; uh, don't skip trap
+L1
+  (andb ($ 240) ((% gs) 216))   ; untag allocptr in the tcr
+  (movq (% arg_y) (5 (% temp0))) ; set the car
+  (movq (% arg_z) (-3 (% temp0))); set the cdr
+  (movq (% temp0) (% arg_z))    ; return the cons
+	    </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">If we don't take the trap (if allocating 8-16 bytes
+          doesn't exhaust the thread's reserved memory segment), that's
+          a fairly short and simple instruction sequence.  If we do take
+          the trap, we'll have to do some additional work in order to
+          get a new segment for the current thread.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Allocation-of-reserved-heap-segments"></a>16.3.2.Â Allocation of reserved heap segments</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">After the lisp image is first mapped into memory - and after
+          each full GC - the lisp kernel ensures that
+          (LISP-HEAP-GC-TRESHOLD) additional bytes beyond the current
+          end of the heap are mapped read-write.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If a thread traps while trying to allocate memory, the
+          thread goes through the usual exception-handling protocol (to
+          ensure that any other thread that GCs "sees" the state of the
+          trapping thread and to serialize exception handling.)  When
+          the exception handler runs, it determines the nature and size
+          of the failed allocation and tries to complete the allocation
+          on the thread's behalf (and leave it with a reasonably large
+          thread-specific memory segment so that the next small
+          allocation is unlikely to trap.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Depending on the size of the requested segment
+          allocation, the number of segment allocations that have
+          occurred since the last GC, and the EGC and GC thresholds, the
+          segment allocation trap handler may invoke a full or ephemeral
+          GC before returning a new segment.  It's worth noting that the
+          [E]GC is triggered based on the number of and size of these
+          segments that have been allocated since the last GC; it doesn't
+          have much to do with how "full" each of those per-thread
+          segments are.  It's possible for a large number of threads to
+          do fairly incidental memory allocation and trigger the GC as a
+          result; avoiding this involves tuning the per-thread
+          allocation quantum and the GC/EGC thresholds
+          appropriately.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Heap-growth"></a>16.3.3.Â Heap growth</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">All OSes on which Clozure CL currently runs use an
+          "overcommit" memory allocation strategy by default (though
+          some of them provide ways of overriding that default.)  What
+          this means in general is that the OS doesn't necessarily
+          ensure that backing store is available when asked to map pages
+          as read-write; it'll often return a success indicator from the
+          mapping attempt (mapping the pages as "zero-fill,
+          copy-on-write"), and only try to allocate the backing store
+          (swap space and/or physical memory) when non-zero contents are
+          written to the pages.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It -sounds- like it'd be better to have the mmap() call
+          fail immediately, but it's actually a complicated issue.
+          (It's possible that other applications will stop using some
+          backing store before lisp code actually touches the pages that
+          need it, for instance.)  It's also not guaranteed that lisp
+          code would be able to "cleanly" signal an out-of-memory
+          condition if lisp is ... out of memory</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">I don't know that I've ever seen an abrupt out-of-memory
+	      failure that wasn't preceded by several minutes of excessive
+	      paging activity.  The most expedient course in cases like this
+	      is to either (a) use less memory or (b) get more memory; it's
+	      generally hard to use memory that you don't have.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="GC-details"></a>16.4.Â GC details</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The GC uses a Mark/Compact algorithm; its
+        execution time is essentially a factor of the amount of live
+        data in the heap. (The somewhat better-known Mark/Sweep
+        algorithms don't compact the live data but instead traverse the
+        garbage to rebuild free-lists; their execution time is therefore
+        a factor of the total heap size.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">As mentioned in <a class="xref" href="#Heap-Allocation" title="16.3.Â Heap Allocation">SectionÂ 16.3, âHeap Allocationâ</a>, two
+        auxiliary data structures (proportional to the size of the lisp
+        heap) are maintained. These are</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+            <ol type="1">
+              <li>
+                <p>the markbits bitvector, which contains a bit for
+	        every doublenode in the dynamic heap (plus a few extra words
+	        for alignment and so that sub-bitvectors can start on word
+	        boundaries.)</p>
+              </li>
+              <li>
+                <p>the relocation table, which contains a native word for
+	        every 32 or 64 doublenodes in the dynamic heap, plus an
+	        extra word used to keep track of the end of the heap.</p>
+              </li>
+            </ol>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">The total GC space overhead is therefore on the order of
+        3% (2/64 or 1/32).</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The general algorithm proceeds as follows:</p>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Mark-phase"></a>16.4.1.Â Mark phase</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Each doublenode in the dynamic heap has a corresponding
+          bit in the markbits vector. (For any doublenode in the heap,
+          the index of its mark bit is determined by subtracting the
+          address of the start of the heap from the address of the
+          object and dividing the result by 8 or 16.) The GC knows the
+          markbit index of the free pointer, so determining that the
+          markbit index of a doubleword address is between the start of
+          the heap and the free pointer can be done with a single
+          unsigned comparison.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The markbits of all doublenodes in the dynamic heap are
+          zeroed before the mark phase begins. An object is
+          <span class="emphasis"><em>marked</em></span> if the markbits of all of its
+          constituent doublewords are set and unmarked otherwise;
+          setting an object's markbits involves setting the corresponding
+          markbits of all constituent doublenodes in the object.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The mark phase traverses each root. If the tag of the
+          value of the root indicates that it's a non-immediate node
+          whose address lies in the lisp heap, then:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>If the object is already marked, do nothing.</p>
+                </li>
+                <li>
+                  <p>Set the object's markbit(s).</p>
+                </li>
+                <li>
+                  <p>If the object is an ivector, do nothing further.</p>
+                </li>
+                <li>
+                  <p>If the object is a cons cell, recursively mark its
+	          car and cdr.</p>
+                </li>
+                <li>
+                  <p>Otherwise, the object is a gvector. Recursively mark
+	          its elements.</p>
+                </li>
+              </ol>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Marking an object thus involves ensuring that its mark
+          bits are set and then recursively marking any pointers
+          contained within the object if the object was originally
+          unmarked. If this recursive step was implemented in the
+          obvious manner, marking an object would take stack space
+          proportional to the length of the pointer chain from some root
+          to that object. Rather than storing that pointer chain
+          implicitly on the stack (in a series of recursive calls to the
+          mark subroutine), the Clozure CL marker uses mixture of recursion
+          and a technique called <span class="emphasis"><em>link inversion</em></span> to
+          store the pointer chain in the objects themselves.  (Recursion
+          tends to be simpler and faster; if a recursive step notes that
+          stack space is becoming limited, the link-inversion technique
+          is used.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Certain types of objects are treated a little specially:</p>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="orderedlist">
+              <ol type="1">
+                <li>
+                  <p>To support a feature called <span class="emphasis"><em>GCTWA
+                <sup>[<a id="id437172" href="#ftn.id437172" class="footnote">1</a>]</sup>
+	            , </em></span>the vector that contains the internal
+	          symbols of the current package is marked on entry to the
+	          mark phase, but the symbols themselves are not marked at
+	          this time. Near the end of the mark phase, symbols
+	          referenced from this vector which are not otherwise
+	          marked are marked if and only if they're somehow
+	          distinguishable from newly created symbols (by virtue of
+	          their having function bindings, value bindings, plists,
+	          or other attributes.)</p>
+                </li>
+                <li>
+                  <p>Pools have their first element set to NIL before any
+	          other elements are marked.</p>
+                </li>
+                <li>
+                  <p>All hash tables have certain fields (used to cache
+	          previous results) invalidated.</p>
+                </li>
+                <li>
+                  <p>Weak Hash Tables and other weak objects are put on a
+	          linkedlist as they're encountered; their contents are only
+	          retained if there are other (non-weak) references to
+	          them.</p>
+                </li>
+              </ol>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">At the end of the mark phase, the markbits of all
+          objects that are transitively reachable from the roots are
+          set and all other markbits are clear.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Relocation-phase"></a>16.4.2.Â Relocation phase</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The <span class="emphasis"><em>forwarding address</em></span> of a
+	      doublenode in the dynamic heap is (&lt;its current address&gt; -
+	      (size_of_doublenode * &lt;the number of unmarked markbits that
+	      precede it&gt;)) or alternately (&lt;the base of the heap&gt; +
+	      (size_of_doublenode * &lt;the number of marked markbits that
+	      precede it &gt;)). Rather than count the number of preceding
+	      markbits each time, the relocation table is used to precompute
+	      an approximation of the forwarding addresses for all
+	      doublewords. Given this approximate address and a pointer into
+	      the markbits vector, it's relatively easy to compute the exact
+	      forwarding address.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The relocation table contains the forwarding addresses
+	      of each <span class="emphasis"><em>pagelet</em></span>, where a pagelet is 256
+	      bytes (or 32 doublenodes). The forwarding address of the first
+	      pagelet is the base of the heap. The forwarding address of the
+	      second pagelet is the sum of the forwarding address of the
+	      first and 8 bytes for each mark bit set in the first 32-bit
+	      word in the markbits table. The last entry in the relocation
+	      table contains the forwarding address that the freepointer
+	      would have, e.g., the new value of the freepointer after
+	      compaction.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In many programs, old objects rarely become garbage and
+	      new objects often do. When building the relocation table, the
+	      relocation phase notes the address of the first unmarked
+	      object in the dynamic heap. Only the area of the heap between
+	      the first unmarked object and the freepointer needs to be
+	      compacted; only pointers to this area will need to be
+	      forwarded (the forwarding address of all other pointers to the
+	      dynamic heap is the address of that pointer.)  Often, the
+	      first unmarked object is much nearer the free pointer than it
+	      is to the base of the heap.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Forwarding-phase"></a>16.4.3.Â Forwarding phase</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The forwarding phase traverses all roots and the "old"
+          part of the dynamic heap (the part between the base of the
+          heap and the first unmarked object.) All references to objects
+          whose address is between the first unmarked object and the
+          free pointer are updated to point to the address the object
+          will have after compaction by using the relocation table and
+          the markbits vector and interpolating.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The relocation table entry for the pagelet nearest the
+	      object is found. If the pagelet's address is less than the
+	      object's address, the number of set markbits that precede
+	      the object on the pagelet is used to determine the object's
+	      address; otherwise, the number of set markbits that follow
+	      the object on the pagelet is used.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Since forwarding views the heap as a set of doublewords,
+          locatives are (mostly) treated like any other pointers. (The
+          basic difference is that locatives may appear to be tagged as
+          fixnums, in which case they're treated as word-aligned
+          pointers into the object.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">If the forward phase changes the address of any hash
+          table key in a hash table that hashes by address (e.g., an EQ
+          hash table), it sets a bit in the hash table's header. The
+          hash table code will rehash the hash table's contents if it
+          tries to do a lookup on a key in such a table.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Profiling reveals that about half of the total time
+          spent in the GC is spent in the subroutine which determines a
+          pointer's forwarding address. Exploiting GCC-specific idioms,
+          hand-coding the routine, and inlining calls to it could all be
+          expected to improve GC performance.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Compact-phase"></a>16.4.4.Â Compact phase</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">The compact phase compacts the area between the first
+          unmarked object and the freepointer so that it contains only
+          marked objects.  While doing so, it forwards any pointers it
+          finds in the objects it copies.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">When the compact phase is finished, so is the GC (more
+          or less): the free pointer and some other data structures are
+          updated and control returns to the exception handler that
+          invoked the GC. If sufficient memory has been freed to satisfy
+          any allocation request that may have triggered the GC, the
+          exception handler returns; otherwise, a "seriously low on
+          memory" condition is signaled, possibly after releasing a
+          small emergency pool of memory.</p>
+          </div>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="footnotes">
+            <br />
+            <hr width="100" align="left" />
+            <div class="footnote">
+              <p><sup>[<a id="ftn.id437172" href="#id437172" class="para">1</a>] </sup>I believe that the acronym comes from MACLISP,
+		            where it stood for "Garbage Collection of Truly
+		            Worthless Atoms".</p>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="The-ephemeral-GC"></a>16.5.Â The ephemeral GC</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">In the Clozure CL memory management scheme, the relative age
+        of two objects in the dynamic heap can be determined by their
+        addresses: if addresses X and Y are both addresses in the
+        dynamic heap, X is younger than Y (X was created more recently
+        than Y) if it is nearer to the free pointer (and farther from
+        the base of the heap) than Y.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Ephemeral (or generational) garbage collectors attempt to
+        exploit the following assumptions:</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>most newly created objects become garbage soon after
+	        they'recreated.</p>
+              </li>
+              <li>
+                <p>most objects that have already survived several GCs
+	        are unlikely to ever become garbage.</p>
+              </li>
+              <li>
+                <p>old objects can only point to newer objects as the
+	        result of a destructive modification (e.g., via
+	        SETF.)</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">By concentrating its efforts on (frequently and quickly)
+        reclaiming newly created garbage, an ephemeral collector hopes
+        to postpone the more costly full GC as long as possible. It's
+        important to note that most programs create some long-lived
+        garbage, so an EGC can't typically eliminate the need for full
+        GC.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">An EGC views each object in the heap as belonging to
+        exactly one <span class="emphasis"><em>generation</em></span>; generations are
+        sets of objects that are related to each other by age: some
+        generation is the youngest, some the oldest, and there's an age
+        relationship between any intervening generations. Objects are
+        typically assigned to the youngest generation when first
+        allocated; any object that has survived some number of GCs in
+        its current generation is promoted (or
+        <span class="emphasis"><em>tenured</em></span>) into an older generation.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When a generation is GCed, the roots consist of the
+        stacks, registers, and global variables as always and also of
+        any pointers to objects in that generation from other
+        generations. To avoid the need to scan those (often large) other
+        generations looking for such intergenerational references, the
+        runtime system must note all such intergenerational references
+        at the point where they're created (via Setf).<sup>[<a id="id437407" href="#ftn.id437407" class="footnote">2</a>]</sup> The
+        set of pointers that may contain intergenerational references is
+        sometimes called <span class="emphasis"><em>the remembered set</em></span>.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">In Clozure CL's EGC, the heap is organized exactly the same
+        as otherwise; "generations" are merely structures which contain
+        pointers to regions of the heap (which is already ordered by
+        age.) When a generation needs to be GCed, any younger generation
+        is incorporated into it; all objects which survive a GC of a
+        given generation are promoted into the next older
+        generation. The only intergenerational references that can exist
+        are therefore those where an old object is modified to contain a
+        pointer to a new object.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The EGC uses exactly the same code as the full GC. When a
+        given GC is "ephemeral",</p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="itemizedlist">
+            <ul type="disc">
+              <li>
+                <p>the "base of the heap" used to determine an object's
+	        markbit address is the base of the generation
+	        being collected;</p>
+              </li>
+              <li>
+                <p>the markbits vector is actually a pointer into the
+	        middle of the global markbits table; preceding entries in
+	        this table are used to note doubleword addresses in older
+	        generations that (may) contain intergenerational
+	        references;</p>
+              </li>
+              <li>
+                <p>some steps (notably GCTWA and the handling of weak
+	        objects) are not performed;</p>
+              </li>
+              <li>
+                <p>the intergenerational references table is used to
+	        find additional roots for the mark and forward phases. If a
+	        bit is set in the intergenerational references table, that
+	        means that the corresponding doubleword (in some "old"
+	        generation, in some "earlier" part of the heap) may have had
+	        a pointer to an object in a younger generation stored into
+	        it.</p>
+              </li>
+            </ul>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">With one exception (the implicit setfs that occur on entry
+        to and exit from the binding of a special variable), all setfs
+        that might introduce an intergenerational reference must be
+        memoized.
+        <sup>[<a id="id437477" href="#ftn.id437477" class="footnote">3</a>]</sup> It's always safe to
+        push any cons cell or gvector locative onto the memo stack;
+        it's never safe to push anything else.
+      </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Typically, the intergenerational references bitvector is
+        sparse: a relatively small number of old locations are stored
+        into, although some of them may have been stored into many
+        times. The routine that scans the memoization buffer does a lot
+        of work and usually does it fairly often; it uses a simple,
+        brute-force method but might run faster if it was smarter about
+        recognizing addresses that it'd already seen.
+      </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">When the EGC mark and forward phases scan the
+        intergenerational reference bits, they can clear any bits that
+        denote doublewords that definitely do not contain
+        intergenerational references.
+      </p>
+          <div xmlns="http://www.w3.org/1999/xhtml" class="footnotes">
+            <br />
+            <hr width="100" align="left" />
+            <div class="footnote">
+              <p><sup>[<a id="ftn.id437407" href="#id437407" class="para">2</a>] </sup>This is
+            sometimes called "The Write Barrier": all assignments which
+            might result in intergenerational references must be noted, as
+            if the other generations were write-protected.</p>
+            </div>
+            <div class="footnote">
+              <p><sup>[<a id="ftn.id437477" href="#id437477" class="para">3</a>] </sup>Note that the implicit setfs that occur when
+        initializing an object - as in the case of a call to cons or
+        vector - can't introduce intergenerational references, since
+        the newly created object is always younger than the objects
+        used to initialize it.</p>
+            </div>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Fasl-files"></a>16.6.Â Fasl files</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">Saving and loading of Fasl files is implemented in
+        xdump/faslenv.lisp, level-0/nfasload.lisp, and lib/nfcomp.lisp.
+        The information here is only an overview, which might help when
+        reading the source.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The Clozure CL Fasl format is forked from the old MCL Fasl
+        format; there are a few differences, but they are minor.  The
+        name "nfasload" comes from the fact that this is the so-called
+        "new" Fasl system, which was true in 1986 or so.  </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">A Fasl file begins with a "file header", which contains
+        version information and a count of the following "blocks".
+        There's typically only one "block" per Fasl file.  The blocks
+        are part of a mechanism for combining multiple logical files
+        into a single physical file, in order to simplify the
+        distribution of precompiled programs. </p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Each block begins with a header for itself, which just
+        describes the size of the data that follows.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The data in each block is treated as a simple stream of
+        bytes, which define a bytecode program.  The actual bytecodes,
+        "fasl operators", are defined in xdump/faslenv.lisp.  The
+        descriptions in the source file are terse, but, according to
+        Gary, "probably accurate".</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Some of the operators are used to create a per-block
+        "object table", which is a vector used to keep track of
+        previously-loaded objects and simplify references to them.  When
+        the table is created, an index associated with it is set to
+        zero; this is analogous to an array fill-pointer, and allows the
+        table to be treated like a stack.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The low seven bits of each bytecode are used to specify
+        the fasl operator; currently, about fifty operators are defined.
+        The high byte, when set, indicates that the result of the
+        operation should be pushed onto the object table.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Most bytecodes are followed by operands; the operand data
+        is byte-aligned.  How many operands there are, and their type,
+        depend on the bytecode.  Operands can be indices into the object
+        table, immediate values, or some combination of these.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">An exception is the bytecode #xFF, which has the symbolic
+        name ccl::$faslend; it is used to mark the end of the
+        block.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="The-Objective-C-Bridge--1-"></a>16.7.Â The Objective-C Bridge</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="How-CCL-Recognizes-Objective-C-Objects"></a>16.7.1.Â How Clozure CL Recognizes Objective-C Objects</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">In most cases, pointers to instances of Objective-C
+          classes are recognized as such; the recognition is (and
+          probably always will be) slightly heuristic. Basically, any
+          pointer that passes basic sanity checks and whose first word
+          is a pointer to a known ObjC class is considered to be an
+          instance of that class; the Objective-C runtime system would
+          reach the same conclusion.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's certainly possible that a random pointer to an
+          arbitrary memory address could look enough like an ObjC
+          instance to fool the lisp runtime system, and it's possible
+          that pointers could have their contents change so that
+          something that had either been a true ObjC instance (or had
+          looked a lot like one) is changed (possibly by virtue of
+          having been deallocated.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">In the first case, we can improve the heuristics
+          substantially: we can make stronger assertions that a
+          particular pointer is really "of type :ID" when it's a
+          parameter to a function declared to take such a pointer as an
+          argument or a similarly declared function result; we can be
+          more confident of something we obtained via SLOT-VALUE of a
+          slot defined to be of type :ID than if we just dug a pointer
+          out of memory somewhere.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The second case is a little more subtle: ObjC memory
+          management is based on a reference-counting scheme, and it's
+          possible for an object to ... cease to be an object while lisp
+          is still referencing it.  If we don't want to deal with this
+          possibility (and we don't), we'll basically have to ensure
+          that the object is not deallocated while lisp is still
+          thinking of it as a first-class object. There's some support
+          for this in the case of objects created with MAKE-INSTANCE,
+          but we may need to give similar treatment to foreign objects
+          that are introduced to the lisp runtime in other ways (as
+          function arguments, return values, SLOT-VALUE results, etc. as
+          well as those instances that are created under lisp
+          control.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">This doesn't all work yet (in fact, not much of it works
+          yet); in practice, this has not yet been as much of a problem
+          as anticipated, but that may be because existing Cocoa code
+          deals primarily with relatively long-lived objects such as
+          windows, views, menus, etc.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="id437620"></a>16.7.2.Â Recommended Reading</h3>
+                </div>
+              </div>
+            </div>
+            <div xmlns="http://www.w3.org/1999/xhtml" class="variablelist">
+              <dl>
+                <dt>
+                  <span class="term">
+	          <a class="ulink" href="http://developer.apple.com/documentation/Cocoa/" target="_top">Cocoa Documentation</a>
+	        </span>
+                </dt>
+                <dd>
+                  <p>
+	            This is the top page for all of Apple's documentation on
+	            Cocoa.  If you are unfamiliar with Cocoa, it is a good
+	            place to start.
+	          </p>
+                </dd>
+                <dt>
+                  <span class="term">
+	          <a class="ulink" href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html" target="_top">Foundation Reference for Objective-C</a>
+	        </span>
+                </dt>
+                <dd>
+                  <p>
+	            This is one of the two most important Cocoa references; it
+	            covers all of the basics, except for GUI programming.  This is
+	            a reference, not a tutorial.
+	          </p>
+                </dd>
+              </dl>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Modifying-CCL"></a>ChapterÂ 17.Â Modifying Clozure CL</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#Contributing-Code-Back-to-the-CCL-Project">17.1. Contributing Code Back to the Clozure CL Project</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Using-CCL-in--development--and-in--user--mode">17.2. Using Clozure CL in "development" and in  "user" mode</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#kernel-debugger">17.3. The Kernel Debugger</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#Using-AltiVec-in-CCL-LAP-functions">17.4. Using AltiVec in Clozure CL LAP functions</a>
+              </span>
+            </dt>
+            <dd>
+              <dl>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Overview--16-">17.4.1. Overview</a>
+                  </span>
+                </dt>
+                <dt>
+                  <span class="sect2">
+                    <a href="#Register-usage-conventions">17.4.2. Register usage conventions</a>
+                  </span>
+                </dt>
+              </dl>
+            </dd>
+            <dt>
+              <span class="sect1">
+                <a href="#Development-Mode-Dictionary">17.5. Development-Mode Dictionary</a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Contributing-Code-Back-to-the-CCL-Project"></a>17.1.Â Contributing Code Back to the Clozure CL Project</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">This section is a placeholder, added as of August 2004.  The
+      full text is being written, and will be added as soon as it is
+      available.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Using-CCL-in--development--and-in--user--mode"></a>17.2.Â Using Clozure CL in "development" and in  "user" mode</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">As it's distributed, Clozure CL starts up with *PACKAGE* set to
+      the CL-USER package and with most predefined functions and
+      methods protected against accidental redefinition.  The package
+      setting is of course a requirement of ANSI CL, and the
+      protection of predefined functions and methods is intended to
+      catch certain types of programming errors (accidentally
+      redefining a CL or CCL function) before those errors have a
+      chance to do much damage.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">These settings may make using Clozure CL to develop Clozure CL a bit
+      awkward, because much of that process assumes you are working in
+      the CCL package is current, and a primary purpose of Clozure CL
+      development is to redefine some predefined, builtin functions.
+      The standard, "routine" ways of building Clozure CL from sources (see
+      ) - COMPILE-CCL, XCOMPILE-CCL, and XLOAD-LEVEL-0 - bind
+      *PACKAGE* to the "CCL" package and enable the redefinition of
+      predefined functions; the symbols COMPILE-CCL, XCOMPILE-CCL, and
+      XLOAD-LEVEL-0 are additionally now exported from the "CCL"
+      package.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Some other (more ad-hoc) ways of doing development on
+      Clozure CLâcompiling and/or loading individual files,
+      incrementally redefining individual functionsâmay be
+      awkward unless one reverts to the mode of operation which was
+      traditionally offered in Clozure CL. Some Clozure CL source files -
+      especially those that comprise the bootstrapping image sources
+      and the first few files in the "cold load" sequence - are
+      compiled and loaded in the "CCL" package but don't contain
+      (IN-PACKAGE "CCL") forms, since IN-PACKAGE doesn't work until
+      later in the cold load sequence.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The somewhat bizarre behavior of both SET-USER-ENVIRONMENT
+      and SET-DEVELOPMENT-ENVIRONMENT with respect to the special
+      variables they affect is intended to allow those constructs to
+      take effect when the read-eval-print loop next returns to a
+      top-level '? ' prompt; the constructs can meaningfully be used
+      inside LOAD, for instance (recall that LOAD binds *PACKAGE*),
+      though using both constructs within the same LOAD call would
+      likely be pretty confusing.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">"user" and "development" are otherwise very generic terms;
+      here they're intended to enforce the distinction between "using"
+      Clozure CL and "developing" it.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The initial environment from which Clozure CL images are
+      saved is one where (SET-USER-ENVIRONMENT T) has just been
+      called; in previous versions, it was effectively as if
+      (SET-DEVELOPMENT-ENVIRONMENT T) had just been called.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Hopefully, most users of Clozure CL can safely ignore these
+      issues most of the time. Note that doing (SET-USER-ENVIRONMENT
+      T) after loading one's own code (or 3rd-party code) into Clozure CL
+      would protect that code (as well as Clozure CL's) from accidental
+      redefinition; that may be useful in some cases.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="kernel-debugger"></a>17.3.Â The Kernel Debugger</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml"> In a perfect world, something like this couldn't
+      happen:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+Welcome to Clozure CL Version x.y!
+? (defun foo (x)
+    (declare (cons x))
+    (cdr x))
+FOO
+
+? (foo -1) ;Oops. Too late ...
+Unhandled exception 11 at 0x300e90c8, context-&gt;regs at #x7ffff6b8
+Continue/Debugger/eXit &lt;enter&gt;?
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">As you may have noticed, it's not a perfect world; it's rare
+      that the cause (attempting to reference the CDR of -1, and therefore
+      accessing unmapped memory near location 0) of this effect (an
+      "Unhandled exception ..." message) is so obvious.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The addresses printed in the message above aren't very useful
+      unless you're debugging the kernel with GDB (and they're often
+      very useful if you are.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">Aside from causing an exception that the lisp kernel doesn't
+      know how to handle, one can also enter the kernel debugger (more)
+      deliberately:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (defun classify (n)
+    (cond ((&gt; n 0) "Greater")
+          ((&lt; n 0) "Less")
+          (t
+           ;; Sheesh ! What else could it be ?
+           (ccl::bug "I give up. How could this happen ?"))))
+CLASSIFY
+
+? (classify 0)
+Bug in Clozure CL system code:
+I give up. How could this happen ?
+? for help
+[12345] Clozure CL kernel debugger:
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">CCL::BUG isn't quite the right tool for this example (a
+      call to BREAK or PRINT might do a better job of clearing up the
+      mystery), but it's sometimes helpful when those other tools
+      can't be used.  The lisp error system notices, for instance, if
+      attempts to signal errors themselves cause errors to be
+      signaled; this sort of thing can happen if CLOS or the I/O
+      system are broken or missing. After some small number of
+      recursive errors, the error system gives up and calls
+      CCL::BUG.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If one enters a '?' at the kernel debugger prompt, one
+      will see output like:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(S)  Find and describe symbol matching specified name
+(B)  Show backtrace
+(X)  Exit from this debugger, asserting that any exception was handled
+(K)  Kill Clozure CL process
+(?)  Show this help
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">CCL::BUG just does an FF-CALL into the lisp kernel.  If
+      the kernel debugger was invoked because of an unhandled
+      exception (such as an illegal memory reference) the OS kernel
+      saves the machine state ("context") in a data structure for us,
+      and in that case some additional options can be used to display
+      the contents of the registers at the point of the
+      exception. Another functionâCCL::DBGâcauses a special
+      exception to be generated and enters the lisp kernel debugger
+      with a non-null "context":</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (defun classify2 (n)
+    (cond ((&gt; n 0) "Greater")
+          ((&lt; n 0) "Less")
+          (t (dbg n))))
+CLASSIFY2
+
+? (classify2 0)
+Lisp Breakpoint
+While executing: #&lt;Function CLASSIFY2 #x08476cfe&gt;
+? for help
+[12345] Clozure CL kernel debugger: ?
+(G)  Set specified GPR to new value
+(A)  Advance the program counter by one instruction (use with caution!)
+(D)  Describe the current exception in greater detail
+(R)  Show raw GPR/SPR register values
+(L)  Show Lisp values of tagged registers
+(F)  Show FPU registers
+(S)  Find and describe symbol matching specified name
+(B)  Show backtrace
+(X)  Exit from this debugger, asserting that any exception was handled
+(P)  Propagate the exception to another handler (debugger or OS)
+(K)  Kill Clozure CL process
+(?)  Show this help
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">CCL::DBG takes an argument, whose value is copied into the register
+      that Clozure CL uses to return a function's primary value (arg_z, which
+      is r23 on the PowerPC). If we were to choose the (L) option at this point,
+      we'd see a dislay like:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+rnil = 0x01836015
+nargs = 0
+r16 (fn) = #&lt;Function CLASSIFY2 #x30379386&gt;
+r23 (arg_z) = 0
+r22 (arg_y) = 0
+r21 (arg_x) = 0
+r20 (temp0) = #&lt;26-element vector subtag = 2F @#x303793ee&gt;
+r19 (temp1/next_method_context) = 6393788
+r18 (temp2/nfn) = #&lt;Function CLASSIFY2 #x30379386&gt;
+r17 (temp3/fname) = CLASSIFY2
+r31 (save0) = 0
+r30 (save1) = *TERMINAL-IO*
+r29 (save2) = 0
+r28 (save3) = (#&lt;RESTART @#x01867f2e&gt; #&lt;RESTART @#x01867f56&gt;)
+r27 (save4) = ()
+r26 (save5) = ()
+r25 (save6) = ()
+r24 (save7) = ()
+    </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">From this we can conclude that the problematic argument to CLASSIFY2
+      was 0 (see r23/arg_z), and that I need to work on a better example.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The R option shows the values of the ALU (and PPC branch unit)
+      registers in hex; the F option shows the values of the FPU registers.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">The (B) option shows a raw stack backtrace; it'll try to
+      identify foreign functions as well as lisp functions. (Foreign function
+      names are guesses based on the nearest preceding exported symbol.)</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If you ever unexpectedly find yourself in the "lisp kernel
+      debugger", the output of the (L) and (B) options are often the most
+      helpful things to include in a bug report.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Using-AltiVec-in-CCL-LAP-functions"></a>17.4.Â Using AltiVec in Clozure CL LAP functions</h2>
+              </div>
+            </div>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Overview--16-"></a>17.4.1.Â Overview</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">It's now possible to use AltiVec instructions in PPC LAP
+        (assembler) functions.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The lisp kernel detects the presence or absence of
+        AltiVec and preserves AltiVec state on lisp thread switch and
+        in response to exceptions, but the implementation doesn't
+        otherwise use vector operations.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">This document doesn't document PPC LAP programming in
+        general.  Ideally, there would be some document that
+        did.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">This document does explain AltiVec register-usage
+        conventions in Clozure CL and explains the use of some lap macros
+        that help to enforce those conventions.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">All of the global symbols described below are exported
+        from the CCL package. Note that lap macro names, ppc
+        instruction names, and (in most cases) register names are
+        treated as strings, so this only applies to functions and
+        global variable names.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">Much of the Clozure CL support for AltiVec LAP programming
+        is based on work contributed to MCL by Shannon Spires.</p>
+          </div>
+          <div class="sect2" lang="en" xml:lang="en">
+            <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+              <div>
+                <div>
+                  <h3 class="title"><a id="Register-usage-conventions"></a>17.4.2.Â Register usage conventions</h3>
+                </div>
+              </div>
+            </div>
+            <p xmlns="http://www.w3.org/1999/xhtml">Clozure CL LAP functions that use AltiVec instructions must
+        interoperate with each other and with C functions; that fact
+        suggests that they follow C AltiVec register usage
+        conventions. (vr0-vr1 scratch, vr2-vr13 parameters/return
+        value, vr14-vr19 temporaries, vr20-vr31 callee-save
+        non-volatile registers.)</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The EABI (Embedded Application Binary Interface) used in
+        LinuxPPC doesn't ascribe particular significance to the vrsave
+        special-purpose register; on other platforms (notably MacOS),
+        it's used as a bitmap which indicates to system-level code
+        which vector registers contain meaningful values.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">The WITH-ALTIVEC-REGISTERS lap macro generates code that
+        saves, updates, and restores VRSAVE on platforms where this is
+        required (as indicated by the value of the special variable
+        that controls this behavior) and ignores VRSAVE on platforms
+        that don't require it to be maintained.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">On all PPC platforms, it's necessary to save any non-volatile
+        vector registers (vr20 .. vr31) before assigning to them and to restore
+        such registers before returning to the caller.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">On platforms that require that VRSAVE be maintained, it's
+        not necessary to mention the "use" of vector registers that
+        are used as incoming parameters. It's not incorrect to mention
+        their use in a WITH-ALTIVEC-REGISTERS form, but it may be
+        unnecessary in many interesting cases. One can likewise assume
+        that the caller of any function that returns a vector value in
+        vr2 has already set the appropriate bit in VRSAVE to indicate
+        that this register is live. One could therefore write a leaf
+        function that added the bytes in vr3 and vr2 and returned the
+        result in vr2 as:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defppclapfunction vaddubs ((y vr3) (z vr2))
+  (vaddubs z y z)
+  (blr))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">When vector registers that aren't incoming parameters are used
+        in a LAP function, WITH-ALTIVEC-REGISTERS takes care of maintaining VRSAVE
+        and of saving/restoring any non-volatile vector registers:</p>
+            <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+(defppclapfunction load-array ((n arg_z))
+  (check-nargs 1)
+  (with-altivec-registers (vr1 vr2 vr3 vr27) ; Clobbers imm0
+    (li imm0 arch::misc-data-offset)
+    (lvx vr1 arg_z imm0)                ; load MSQ
+    (lvsl vr27 arg_z imm0)              ; set the permute vector
+    (addi imm0 imm0 16)                 ; address of LSQ
+    (lvx vr2 arg_z imm0)                ; load LSQ
+    (vperm vr3 vr1 vr2 vr27)           ; aligned result appears in VR3
+    (dbg t))                         ; Look at result in some debugger
+  (blr))
+      </pre>
+            <p xmlns="http://www.w3.org/1999/xhtml">AltiVec registers are not preserved by CATCH and UNWIND-PROTECT.
+        Since AltiVec is only accessible from LAP in Clozure CL and since LAP
+        functions rarely use high-level control structures, this should rarely be
+        a problem in practice.</p>
+            <p xmlns="http://www.w3.org/1999/xhtml">LAP functions that use non-volatile vector registers and
+        that call (Lisp ?) code which may use CATCH or UNWIND-PROTECT
+        should save those vector registers before such a call and
+        restore them on return. This is one of the intended uses of
+        the WITH-VECTOR-BUFFER lap macro.</p>
+          </div>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="Development-Mode-Dictionary"></a>17.5.Â Development-Mode Dictionary</h2>
+              </div>
+            </div>
+          </div>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_warn-if-redefine-kernel"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>*WARN-IF-REDEFINE-KERNEL*</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441733"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">When true, attempts to redefine (via DEFUN or DEFMETHOD)
+	      functions and methods that are marked as being
+	      "predefined" signal continuable errors.</p>
+                <p xmlns="http://www.w3.org/1999/xhtml">Note that these are CERRORs, not warnings, and that
+	      no lisp functions or methods have been defined in the kernel
+	      in MCL or Clozure CL since 1987 or so.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_set-development-environment"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>set-development-environment</strong></span>
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em>
+	      unmark-builtin-functions</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441799"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Arranges that the outermost special bindings of *PACKAGE*
+	      and *WARN-IF-REDEFINE-KERNEL* restore values of the "CCL"
+	      package and NIL to these variables, respectively. If the optional
+	      argument is true, marks all globally defined functions and methods
+	      as being "not predefined" (this is a fairly expensive
+	      operation.)</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_set-user-environment"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>set-user-environment</strong></span>
+	      <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;optional</em> mark-builtin-functions</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id442061"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Arranges that the outermost special bindings of *PACKAGE*
+	      and *WARN-IF-REDEFINE-KERNEL* restore values of the
+	      "CL-USER" package and T to these variables, respectively.
+	      If the optional argument is true, marks all globally defined
+	      functions and methods as being "predefined" (this is a
+	      fairly expensive operation.)</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_altivec-available"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>*ALTIVEC-AVAILABLE*</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id442107"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">This variable is initialized each time an Clozure CL session
+	      starts based on information provided by the lisp kernel. Its value
+	      is true if AltiVec is present and false otherwise. This variable
+	      shouldn't be set by user code.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="f_altivec-available-p"></a>
+              <strong>[Function]</strong>
+              <br></br>
+              <code>
+                <span xmlns="http://www.w3.org/1999/xhtml" class="function">
+                  <strong>altivec-available-p</strong>
+                </span>
+              </code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id442165"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Returns non-NIL if AltiVec is available.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="v_altivec-lapmacros-maintain-vrsave-p"></a>
+              <strong>[Variable]</strong>
+              <br></br>
+              <code>*ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P*</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441875"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Intended to control the expansion of certain lap macros.
+	      Initialized to NIL on LinuxPPC; initialized to T on platforms
+	      (such as MacOS X/Darwin) that require that the VRSAVE SPR contain
+	      a bitmask of active vector registers at all times.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="lapm_with-altivec-registers"></a>
+              <strong>[LAP Macro]</strong>
+              <br></br>
+              <code><span xmlns="http://www.w3.org/1999/xhtml" class="function"><strong>with-altivec-registers</strong></span>
+	      reglist <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441938"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">reglist</span></i>---A list of vector register names (vr0 .. vr31).</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---A sequence of PPC LAP instructions.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441979"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Specifies the set of AltiVec registers used in body. If
+	      *altivec-lapmacros-maintain-vrsave-p* is true when the macro is
+	      expanded, generates code to save the VRSAVE SPR and updates VRSAVE
+	      to include a bitmask generated from the specified register list.
+	      Generates code which saves any non-volatile vector registers which
+	      appear in the register list, executes body, and restores the saved
+	      non-volatile vector registers (and, if
+	      *altivec-lapmacros-maintain-vrsave-p* is true, restores VRSAVE as
+	      well. Uses the IMM0 register (r3) as a temporary.</p>
+              </div>
+            </div>
+          </p>
+          <p>
+            <div class="refentrytitle">
+              <a id="lapm_with-vector-buffer"></a>
+              <strong>[LAP Macro]</strong>
+              <br></br>
+              <code>with-vector-buffer base n <em xmlns="http://www.w3.org/1999/xhtml" class="varname">&amp;body</em> body</code>
+            </div>
+            <div class="refentrytitle"></div>
+          </p>
+          <p>
+            <div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441626"></a>
+                <div class="header">Arguments and Values:</div>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">base</span></i>---Any available general-purpose register.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">n</span></i>---An integer between 1 and 254, inclusive. (Should
+		        typically be much, much closer to 1.) Specifies the size of
+		        the buffer, in 16-byte units.</p>
+                <p><i><span xmlns="http://www.w3.org/1999/xhtml" class="term">body</span></i>---A sequence of PPC LAP instructions.</p>
+              </div>
+              <div class="refsect1" lang="en" xml:lang="en">
+                <a xmlns="http://www.w3.org/1999/xhtml" id="id441683"></a>
+                <div class="header">Description:</div>
+                <p xmlns="http://www.w3.org/1999/xhtml">Generates code which allocates a 16-byte aligned buffer
+	      large enough to contain N vector registers; the GPR base points to
+	      the lowest address of this buffer. After processing body, the
+	      buffer will be deallocated. The body should preserve the value of
+	      base as long as it needs to reference the buffer. It's
+	      intended that base be used as a base register in stvx and lvx
+	      instructions within the body.</p>
+              </div>
+            </div>
+          </p>
+        </div>
+      </div>
+      <div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="chapter" lang="en" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Questions-and-Answers"></a>ChapterÂ 18.Â Questions and Answers</h2>
+            </div>
+          </div>
+        </div>
+        <div xmlns="http://www.w3.org/1999/xhtml" class="toc">
+          <dl>
+            <dt>
+              <span class="sect1">
+                <a href="#How-can-I-do-nonblocking--aka--unbuffered--and--raw---IO-">18.1. How can I do nonblocking (aka "unbuffered" and "raw") IO?</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#I-m-using-the-graphics-demos--Why-doesn-t-the-menubar-change-">18.2. I'm using the graphics demos. Why doesn't the menubar
+      change?</a>
+              </span>
+            </dt>
+            <dt>
+              <span class="sect1">
+                <a href="#I-m-using-Slime-and-Cocoa--Why-doesn-t--standard-output--seem-to-work-">18.3. I'm using Slime and Cocoa. Why doesn't *standard-output*
+      seem to work? </a>
+              </span>
+            </dt>
+          </dl>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="How-can-I-do-nonblocking--aka--unbuffered--and--raw---IO-"></a>18.1.Â How can I do nonblocking (aka "unbuffered" and "raw") IO?</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">There's some code for manipulating TTY modes in
+      "ccl:library;pty.lisp".</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (require "PTY")
+
+? (ccl::disable-tty-local-modes 0 #$ICANON)
+T
+      </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">will turn off "input canonicalization" on file descriptor
+      0, which is at least part of what you need to do here.  This
+      disables the #$ICANON mode, which tells the OS not to do any
+      line-buffering or line-editing.  Of course, this only has any
+      effect in situations where the OS ever does that, which means
+      when stdin is a TTY or PTY.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">If the #$ICANON mode is disabled, you can do things like:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (progn (read-char) (read-char))
+a
+#\a
+      </pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">(where the first READ-CHAR consumes the newline, which
+      isn't really necessary to make the reader happy anymore.)  So,
+      you can do:</p>
+          <pre xmlns="http://www.w3.org/1999/xhtml" class="programlisting">
+? (read-char)
+#\Space
+</pre>
+          <p xmlns="http://www.w3.org/1999/xhtml">(where there's a space after the close-paren) without
+      having to type a newline.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="I-m-using-the-graphics-demos--Why-doesn-t-the-menubar-change-"></a>18.2.Â I'm using the graphics demos. Why doesn't the menubar
+      change?</h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">When you interact with text-only Clozure CL, you're either
+      in Terminal or in Emacs, running Clozure CL as a subprocess.  When
+      you load Cocoa or the graphical environment, the subprocess does
+      some tricky things that turn it into a full-fledged Application,
+      as far as the OS is concerned.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">So, it gets its own icon in the dock, and its own menubar,
+      and so on.  It can be confusing, because standard input and
+      output will still be connected to Terminal or Emacs, so you can
+      still type commands to Clozure CL from there.  To see the menubar
+      you loaded, or the windows you opened, just click on the Clozure CL
+      icon in the dock.</p>
+        </div>
+        <div class="sect1" lang="en" xml:lang="en">
+          <div xmlns="http://www.w3.org/1999/xhtml" class="titlepage">
+            <div>
+              <div>
+                <h2 class="title" style="clear: both"><a id="I-m-using-Slime-and-Cocoa--Why-doesn-t--standard-output--seem-to-work-"></a>18.3.Â I'm using Slime and Cocoa. Why doesn't *standard-output*
+      seem to work? </h2>
+              </div>
+            </div>
+          </div>
+          <p xmlns="http://www.w3.org/1999/xhtml">This comes up if you're using the Slime interface
+      to run Clozure CL under Emacs, and you are doing Cocoa programming
+      which involves printing to *standard-output*.  It seems as
+      though the output goes nowhere; no error is reported, but it
+      doesn't appear in the *slime-repl* buffer.</p>
+          <p xmlns="http://www.w3.org/1999/xhtml">For the most part, this is only relevant when you are
+      trying to insert debug code into your event handlers.  The SLIME
+      listener runs in a thread where the standard stream variables
+      (like <code class="literal">*STANDARD-OUTPUT* and</code> and
+      <code class="literal">*TERMINAL-IO*</code> are bound to the stream used to
+      communicate with Emacs; the Cocoa event thread has its own
+      bindings of these standard stream variables, and output to these
+      streams goes to the *inferior-lisp* buffer instead.  Look for it
+      there.</p>
+        </div>
+      </div>
+      <div class="glossary">
+        <div class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="glossary"></a>Glossary of Terms</h2>
+            </div>
+          </div>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">A</h3>
+          <dl>
+            <dt><a id="application_bundle"></a>application bundle</dt>
+            <dd>
+              <p>A specially-structured directory that Mac OS X
+		recognizes as a
+		launchable <a class="glossterm" href="#Cocoa"><em class="glossterm">Cocoa</em></a>
+		application. Graphical applications on Mac OS X are
+		represented as application bundles.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">C</h3>
+          <dl>
+            <dt><a id="Cocoa"></a>Cocoa</dt>
+            <dd>
+              <p>The standard user-interface libraries and frameworks
+		provided by Apple for development of applications on Mac OS
+		X.</p>
+            </dd>
+            <dt><a id="creator_code"></a>creator code</dt>
+            <dd>
+              <p>A four-character identifier used in Mac OS X to uniquely
+		identify an application.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">D</h3>
+          <dl>
+            <dt><a id="displaced-array"></a>displaced array</dt>
+            <dd>
+              <p>An array with no storage of its own for elements, which
+		points to the storage of another array, called its
+		target. Reading or writing the elements of the displaced array
+		returns or changes the contents of the target.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">F</h3>
+          <dl>
+            <dt><a id="fasl-file"></a>fasl file</dt>
+            <dd>
+              <p>A file containing compiled lisp code that the Lisp is
+		able to quickly load and use. A "fast-load" file.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">H</h3>
+          <dl>
+            <dt><a id="hemlock"></a>Hemlock</dt>
+            <dd>
+              <p>A text editor, written in Common Lisp, similar in
+		features to Emacs. Hemlock was originally developed as part of
+		CMU Common Lisp. A portable version of Hemlock is built into
+		the Clozure CL <a class="glossterm" href="#IDE"><em class="glossterm">IDE</em></a>.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">I</h3>
+          <dl>
+            <dt><a id="IDE"></a>IDE</dt>
+            <dd>
+              <p>"Integrated Development Environment". In the context of
+		Clozure CL, "the IDE" refers to the experimental <a class="glossterm" href="#Cocoa"><em class="glossterm">Cocoa</em></a>
+		windowing development environment provided in source form with
+		Clozure CL distributions.</p>
+            </dd>
+            <dt><a id="lisp_image"></a>image</dt>
+            <dd>
+              <p>The in-memory state of a running Lisp system, containing
+		functions, data structures, variables, and so on. Also, a file
+		containing archived versions of these data in a format that
+		can be loaded and reconstituted by the
+		Lisp <a class="glossterm" href="#lisp_kernel"><em class="glossterm">kernel</em></a>. A
+		working Clozure CL system consists of the kernel and
+		an <a class="glossterm" href="#lisp_image"><em class="glossterm">image</em></a>.</p>
+            </dd>
+            <dt><a id="InterfaceBuilder"></a>InterfaceBuilder</dt>
+            <dd>
+              <p>An application supplied by Apple with their developer
+		tools that can be used to interactively build user-interface
+		elements for <a class="glossterm" href="#Cocoa"><em class="glossterm">Cocoa</em></a>
+		applications.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">K</h3>
+          <dl>
+            <dt><a id="lisp_kernel"></a>kernel</dt>
+            <dd>
+              <p>The binary executable program that implements the lowest
+		levels of the Lisp system. A working Clozure CL system consists of
+		the kernel and
+		an <a class="glossterm" href="#lisp_image"><em class="glossterm">image</em></a>.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">L</h3>
+          <dl>
+            <dt><a id="listener_window"></a>listener window</dt>
+            <dd>
+              <p>In the <a class="glossterm" href="#IDE"><em class="glossterm">IDE</em></a>,
+		a <a class="glossterm" href="#Cocoa"><em class="glossterm">Cocoa</em></a>
+		window that contains a pseudo-terminal session that
+		communicates with a Lisp <a class="glossterm" href="#REPL"><em class="glossterm">REPL</em></a>.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">M</h3>
+          <dl>
+            <dt><a id="memory_mapped_file"></a>memory-mapped file</dt>
+            <dd>
+              <p>A file whose contents are accessible as a range of
+		memory addresses. Some operating systems support this feature,
+		in which the virtual memory subsystem arranges for a range of
+		virtual memory addresses to point to the contents of an open
+		file. Programs can then gain access to the file's contents by
+		operating on memory addresses in that range. Access to the
+		file's contents is valid only as long as the file remains
+		open.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">N</h3>
+          <dl>
+            <dt><a id="nibfile"></a>nibfile</dt>
+            <dd>
+              <p>A data file created by
+		Apple's <a class="glossterm" href="#InterfaceBuilder"><em class="glossterm">InterfaceBuilder</em></a>
+		application, which contains archived Objective-C objects that
+		define user-interface elements for
+		a <a class="glossterm" href="#Cocoa"><em class="glossterm">Cocoa</em></a>
+		application. Under Mac OS
+		X, <a class="glossterm" href="#Cocoa"><em class="glossterm">Cocoa</em></a> applications
+		typically create their user interface elements by reading
+		nibfiles and unarchiving the objects in them.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">R</h3>
+          <dl>
+            <dt><a id="REPL"></a>REPL</dt>
+            <dd>
+              <p>"Read-eval-print loop". The interactive shell provided
+		by Clozure CL for interaction with Lisp.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">S</h3>
+          <dl>
+            <dt><a id="s-expression"></a>s-expression</dt>
+            <dd>
+              <p>The simplest, most general element of Lisp syntax. An
+		s-expression may be an atom (such as a symbol, integer, or
+		string), or it may be a list of s-expressions.</p>
+            </dd>
+            <dt><a id="special_variable"></a>special variable</dt>
+            <dd>
+              <p>A variable whose binding is in the dynamic
+		environment. Special variables are essentially equivalent to
+		global variables in languages other than Lisp. A special
+		variable binding is visible in any lexical environment, so
+		long as a lexical binding has not shadowed it.</p>
+            </dd>
+            <dt><a id="static_variable"></a>static variable</dt>
+            <dd>
+              <p>In Clozure CL, a variable whose value is shared across all
+		threads, and which may not be dynamically rebound. Changing a
+		static variable's value in one thread causes all threads to
+		see the new value. Attempting to dynamically rebind the
+		variable (for instance, by using <code class="code">LET</code>, or using
+		the variable name as a parameter in a <code class="code">LAMBDA</code>
+		form) signals an error.</p>
+            </dd>
+          </dl>
+        </div>
+        <div class="glossdiv">
+          <h3 class="title">T</h3>
+          <dl>
+            <dt><a id="toplevel_function"></a>toplevel function</dt>
+            <dd>
+              <p>The function executed by Lisp automatically once its
+		startup is complete. Clozure CL's default toplevel is the
+		interactive <a class="glossterm" href="#REPL"><em class="glossterm">read-eval-print
+		loop</em></a> that you normally use to interact with
+		Lisp. You can, however, replace the toplevel with a function
+		of your own design, changing Clozure CL from a Lisp development
+		system into some tool of your making.</p>
+            </dd>
+            <dt><a id="type-specifier"></a>type-specifier</dt>
+            <dd>
+              <p>An expression that denotes a type. Type specifiers may
+		be symbols (such as <code class="code">CONS</code>
+		and <code class="code">STRING</code>), or they may be more complex
+		<a class="glossterm" href="#s-expression"><em class="glossterm">S-expressions</em></a>
+		(such as (UNSIGNED-BYTE 8)).</p>
+            </dd>
+          </dl>
+        </div>
+      </div>
+      <div class="index">
+        <div class="titlepage">
+          <div>
+            <div>
+              <h2 class="title"><a id="Symbol-Index"></a>Symbol Index</h2>
+            </div>
+          </div>
+        </div>
+        <div class="index">
+          <div class="indexdiv">
+            <h3>Symbols</h3>
+            <dl>
+              <dt>"decode-string-from-octets, <a class="indexterm" href="#decode-string-from-octets">Function decode-string-from-octets</a></dt>
+              <dt>#$, <a class="indexterm" href="#rm_sharpsign-dollarsign">Reader Macro #$</a></dt>
+              <dt>#&amp;, <a class="indexterm" href="#rm_sharpsign-ampersand">Reader Macro #&amp;</a></dt>
+              <dt>#/, <a class="indexterm" href="#rm_sharpsign-slash">Reader Macro #/</a></dt>
+              <dt>#&gt;, <a class="indexterm" href="#rm_sharpsign-greaterthan">Reader Macro #&gt;</a></dt>
+              <dt>#_, <a class="indexterm" href="#rm_sharpsign-underscore">Reader Macro #_</a></dt>
+              <dt>%ff-call, <a class="indexterm" href="#f_Pff-call">Function %FF-CALL</a></dt>
+              <dt>%reference-external-entry-point, <a class="indexterm" href="#f_Preference-external-entry-point">Function %REFERENCE-EXTERNAL-ENTRY-POINT</a></dt>
+              <dt>(setf population-contents), <a class="indexterm" href="#f_setf_population-contents">Function (SETF POPULATION-CONTENTS)</a></dt>
+              <dt>*alternate-line-terminator*, <a class="indexterm" href="#v_alternate-line-terminator">Variable CCL:*ALTERNATE-LINE-TERMINATOR*</a></dt>
+              <dt>*altivec-available*, <a class="indexterm" href="#v_altivec-available">Variable *ALTIVEC-AVAILABLE*</a></dt>
+              <dt>*altivec-lapmacros-maintain-vrsave-p*, <a class="indexterm" href="#v_altivec-lapmacros-maintain-vrsave-p">Variable *ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P*</a></dt>
+              <dt>*COMPILE-CODE-COVERAGE*, <a class="indexterm" href="#v_compile-code-coverage">Variable *COMPILE-CODE-COVERAGE*</a></dt>
+              <dt>*current-process*, <a class="indexterm" href="#v_current-process">Variable *CURRENT-PROCESS*</a></dt>
+              <dt>*default-external-format*, <a class="indexterm" href="#v_default-external-format">Variable CCL:*DEFAULT-EXTERNAL-FORMAT*</a></dt>
+              <dt>*ticks-per-second*, <a class="indexterm" href="#v_ticks-per-second">Variable *TICKS-PER-SECOND*</a></dt>
+              <dt>*warn-if-redefine-kernel, <a class="indexterm" href="#v_warn-if-redefine-kernel">Variable *WARN-IF-REDEFINE-KERNEL*</a></dt>
+              <dt>+NULL-PTR+, <a class="indexterm" href="#Saving-Applications">Saving Applications</a></dt>
+              <dt>:external-format, <a class="indexterm" href="#k_external-format">Keyword Argument :EXTERNAL-FORMAT</a></dt>
+              <dt>:y, <a class="indexterm" href="#cmd_y">Toplevel Command :Y</a></dt>
+              <dt>@class, <a class="indexterm" href="#m_class">Macro CCL::@CLASS</a></dt>
+              <dt>@selector, <a class="indexterm" href="#m_selector">Macro CCL::@SELECTOR</a></dt>
+              <dt>[fn-name], <a class="indexterm" href="#f_describe-character-encodings">Function DESCRIBE-CHARACTER-ENCODINGS</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3></h3>
+            <dl>
+              <dt>, <a class="indexterm" href="#trace">Trace</a>, <a class="indexterm" href="#map-file-to-ivector">Memory-mapped Files</a>, <a class="indexterm" href="#defstatic">Static Variables</a>, <a class="indexterm" href="#save-application">Saving Applications</a>, <a class="indexterm" href="#build-application">The Application Builder</a>, <a class="indexterm" href="#chud_shark-config-file">Reference</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>A</h3>
+            <dl>
+              <dt>accept-connection, <a class="indexterm" href="#f_accept-connection">Function ACCEPT-CONNECTION</a></dt>
+              <dt>all-processes, <a class="indexterm" href="#f_all-processes">Function ALL-PROCESSES</a></dt>
+              <dt>altivec-available-p, <a class="indexterm" href="#f_altivec-available-p">Function ALTIVEC-AVAILABLE-P</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>B</h3>
+            <dl>
+              <dt>bootstrapping
+          image, <a class="indexterm" href="#building-definitions">Building Definitions</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>C</h3>
+            <dl>
+              <dt>CCL Logical Host, <a class="indexterm" href="#Predefined-Logical-Hosts">Predefined Logical Hosts</a></dt>
+              <dt>clear-coverage, <a class="indexterm" href="#f_clear-coverage">Function clear-coverage</a></dt>
+              <dt>close, <a class="indexterm" href="#o_close">Method CLOSE</a></dt>
+              <dt>close-shared-library, <a class="indexterm" href="#f_close-shared-library">Function CLOSE-SHARED-LIBRARY</a></dt>
+              <dt>communication-deadline-expired, <a class="indexterm" href="#Stream-Timeouts-And-Deadlines">Stream Timeouts and Deadlines</a></dt>
+              <dt>configure-gcc, <a class="indexterm" href="#f_configure-gcc">Function CONFIGURE-GCC</a></dt>
+              <dt>count-characters-in-octet-vector, <a class="indexterm" href="#count-characters-in-octet-vector">Function count-characters-in-octet-vector</a></dt>
+              <dt>coverage-statistics, <a class="indexterm" href="#f_coverage-statistics">Function COVERAGE-STATISTICS</a></dt>
+              <dt>current-directory-name, <a class="indexterm" href="#f_current-directory-name">Function CCL::CURRENT-DIRECTORY-NAME</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>D</h3>
+            <dl>
+              <dt>def-foreign-type, <a class="indexterm" href="#m_def-foreign-type">Macro DEF-FOREIGN-TYPE</a></dt>
+              <dt>defcallback, <a class="indexterm" href="#m_defcallback">Macro DEFCALLBACK</a></dt>
+              <dt>define-objc-class-method, <a class="indexterm" href="#m_define-objc-class-method">Macro CCL::DEFINE-OBJC-CLASS-METHOD</a></dt>
+              <dt>define-objc-method, <a class="indexterm" href="#m_define-objc-method">Macro CCL::DEFINE-OBJC-METHOD</a></dt>
+              <dt>dotted-to-ipaddr, <a class="indexterm" href="#f_dotted-to-ipaddr">Function DOTTED-TO-IPADDR</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>E</h3>
+            <dl>
+              <dt>egc, <a class="indexterm" href="#f_egc">Function EGC</a></dt>
+              <dt>egc-active-p, <a class="indexterm" href="#f_egc-active-p">Function EGC-ACTIVE-P</a></dt>
+              <dt>egc-configuration, <a class="indexterm" href="#f_egc-configuration">Function EGC-CONFIGURATION</a></dt>
+              <dt>egc-enabled-p, <a class="indexterm" href="#f_egc-enabled-p">Function EGC-ENABLED-P</a></dt>
+              <dt>encode-string-to-octets, <a class="indexterm" href="#encode-string-to-octets">Function encode-string-to-octets</a></dt>
+              <dt>external, <a class="indexterm" href="#m_external">Macro EXTERNAL</a></dt>
+              <dt>external-call, <a class="indexterm" href="#m_external-call">Macro EXTERNAL-CALL</a></dt>
+              <dt>external-process-error-stream, <a class="indexterm" href="#f_external-process-error-stream">Function EXTERNAL-PROCESS-ERROR-STREAM</a></dt>
+              <dt>external-process-id, <a class="indexterm" href="#f_external-process-id">Function EXTERNAL-PROCESS-ID</a></dt>
+              <dt>external-process-input-stream, <a class="indexterm" href="#f_external-process-input-stream">Function EXTERNAL-PROCESS-INPUT-STREAM</a></dt>
+              <dt>external-process-output-stream, <a class="indexterm" href="#f_external-process-output-stream">Function EXTERNAL-PROCESS-OUTPUT-STREAM</a></dt>
+              <dt>external-process-status, <a class="indexterm" href="#f_external-process-status">Function EXTERNAL-PROCESS-STATUS</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>F</h3>
+            <dl>
+              <dt>fasl
+          files, <a class="indexterm" href="#building-definitions">Building Definitions</a></dt>
+              <dt>fasl-concatenate, <a class="indexterm" href="#"></a></dt>
+              <dt>ff-call, <a class="indexterm" href="#m_ff-call">Macro FF-CALL</a></dt>
+              <dt>foreign-symbol-address, <a class="indexterm" href="#f_foreign-symbol-address">Function FOREIGN-SYMBOL-ADDRESS</a></dt>
+              <dt>foreign-symbol-entry, <a class="indexterm" href="#f_foreign-symbol-entry">Function FOREIGN-SYMBOL-ENTRY</a></dt>
+              <dt>free, <a class="indexterm" href="#f_free">Function FREE</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>G</h3>
+            <dl>
+              <dt>gc-retain-pages, <a class="indexterm" href="#f_gc-retain-pages">Function GC-RETAIN-PAGES</a></dt>
+              <dt>gc-retaining-pages, <a class="indexterm" href="#f_gc-retaining-pages">Function GC-RETAINING-PAGES</a></dt>
+              <dt>get-fpu-mode, <a class="indexterm" href="#f_get-fpu-mode">Function GET-FPU-MODE</a></dt>
+              <dt>get-user-home-dir, <a class="indexterm" href="#f_get-user-home-dir">Function CCL::GET-USER-HOME-DIR</a></dt>
+              <dt>getenv, <a class="indexterm" href="#f_getenv">Function CCL::GETENV</a></dt>
+              <dt>getpid, <a class="indexterm" href="#f_getpid">Function CCL::GETPID</a></dt>
+              <dt>getuid, <a class="indexterm" href="#f_getuid">Function CCL::GETUID</a></dt>
+              <dt>grab-lock, <a class="indexterm" href="#f_grab-lock">Function GRAB-LOCK</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>H</h3>
+            <dl>
+              <dt>heap
+          image, <a class="indexterm" href="#building-definitions">Building Definitions</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>I</h3>
+            <dl>
+              <dt>input-timeout, <a class="indexterm" href="#Stream-Timeouts-And-Deadlines">Stream Timeouts and Deadlines</a></dt>
+              <dt>ipaddr-to-dotted, <a class="indexterm" href="#f_ipaddr-to-dotted">Function IPADDR-TO-DOTTED</a></dt>
+              <dt>ipaddr-to-hostname, <a class="indexterm" href="#f_ipaddr-to-hostname">Function IPADDR-TO-HOSTNAME</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>J</h3>
+            <dl>
+              <dt>join-process, <a class="indexterm" href="#f_join-process">Function JOIN-PROCESS</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>K</h3>
+            <dl>
+              <dt>kernel build directory, <a class="indexterm" href="#building-definitions">Building Definitions</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>L</h3>
+            <dl>
+              <dt>lisp
+          kernel, <a class="indexterm" href="#building-definitions">Building Definitions</a></dt>
+              <dt>lisp-heap-gc-threshold, <a class="indexterm" href="#f_lisp-heap-gc-threshold">Function LISP-HEAP-GC-THRESHOLD</a></dt>
+              <dt>local-host, <a class="indexterm" href="#f_local-host">Function LOCAL-HOST</a></dt>
+              <dt>local-port, <a class="indexterm" href="#f_local-port">Function LOCAL-PORT</a></dt>
+              <dt>lookup-hostname, <a class="indexterm" href="#f_lookup-hostname">Function LOOKUP-HOSTNAME</a></dt>
+              <dt>lookup-port, <a class="indexterm" href="#f_lookup-port">Function LOOKUP-PORT</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>M</h3>
+            <dl>
+              <dt>make-external-format, <a class="indexterm" href="#f_make-external-format">Function MAKE-EXTERNAL-FORMAT</a></dt>
+              <dt>make-gcable-record, <a class="indexterm" href="#m_make-record">Macro MAKE-RECORD</a></dt>
+              <dt>make-heap-ivector, <a class="indexterm" href="#f_make-heap-ivector">Function MAKE-HEAP-IVECTOR</a></dt>
+              <dt>make-lock, <a class="indexterm" href="#f_make-lock">Function MAKE-LOCK</a></dt>
+              <dt>make-population, <a class="indexterm" href="#f_make-population">Function MAKE-POPULATION</a></dt>
+              <dt>make-process, <a class="indexterm" href="#f_make-process">Function MAKE-PROCESS</a></dt>
+              <dt>make-read-write-lock, <a class="indexterm" href="#f_make-read-write-lock">Function MAKE-READ-WRITE-LOCK</a></dt>
+              <dt>make-record, <a class="indexterm" href="#m_make-record">Macro MAKE-RECORD</a></dt>
+              <dt>make-semaphore, <a class="indexterm" href="#f_make-semaphore">Function MAKE-SEMAPHORE</a></dt>
+              <dt>make-socket, <a class="indexterm" href="#f_make-socket">Function MAKE-SOCKET</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>N</h3>
+            <dl>
+              <dt>note-open-file-stream, <a class="indexterm" href="#f_note-open-file-stream">Function NOTE-OPEN-FILE-STREAM</a></dt>
+              <dt>ns-lisp-string, <a class="indexterm" href="#c_ns-lisp-string">Class CCL::NS-LISP-STRING</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>O</h3>
+            <dl>
+              <dt>objc:defmethod, <a class="indexterm" href="#m_objc-defmethod">Macro objc:defmethod</a></dt>
+              <dt>open-file-streams, <a class="indexterm" href="#f_open-file-streams">Function OPEN-FILE-STREAMS</a></dt>
+              <dt>open-shared-library, <a class="indexterm" href="#f_open-shared-library">Function OPEN-SHARED-LIBRARY</a></dt>
+              <dt>os-command, <a class="indexterm" href="#f_os-command">Function CCL::OS-COMMAND</a></dt>
+              <dt>output-timeout, <a class="indexterm" href="#Stream-Timeouts-And-Deadlines">Stream Timeouts and Deadlines</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>P</h3>
+            <dl>
+              <dt>population-contents, <a class="indexterm" href="#f_population-contents">Function POPULATION-CONTENTS</a></dt>
+              <dt>population-type, <a class="indexterm" href="#f_population-type">Function POPULATION-TYPE</a></dt>
+              <dt>pref, <a class="indexterm" href="#m_pref">Macro PREF</a></dt>
+              <dt>process-abort, <a class="indexterm" href="#f_process-abort">Function PROCESS-ABORT</a></dt>
+              <dt>process-allow-schedule, <a class="indexterm" href="#f_process-allow-schedule">Function PROCESS-ALLOW-SCHEDULE</a></dt>
+              <dt>process-enable, <a class="indexterm" href="#f_process-enable">Function PROCESS-ENABLE</a></dt>
+              <dt>process-input-wait, <a class="indexterm" href="#f_process-input-wait">Function PROCESS-INPUT-WAIT</a></dt>
+              <dt>process-interrupt, <a class="indexterm" href="#f_process-interrupt">Function PROCESS-INTERRUPT</a></dt>
+              <dt>process-kill, <a class="indexterm" href="#f_process-kill">Function PROCESS-KILL</a></dt>
+              <dt>process-output-wait, <a class="indexterm" href="#f_process-output-wait">Function PROCESS-OUTPUT-WAIT</a></dt>
+              <dt>process-preset, <a class="indexterm" href="#f_process-preset">Function PROCESS-PRESET</a></dt>
+              <dt>process-reset, <a class="indexterm" href="#f_process-reset">Function PROCESS-RESET</a></dt>
+              <dt>process-resume, <a class="indexterm" href="#f_process-resume">Function PROCESS-RESUME</a></dt>
+              <dt>process-run-function, <a class="indexterm" href="#f_process-run-function">Function PROCESS-RUN-FUNCTION</a></dt>
+              <dt>process-suspend, <a class="indexterm" href="#f_process-suspend">Function PROCESS-SUSPEND</a></dt>
+              <dt>process-suspend-count, <a class="indexterm" href="#f_process-suspend-count">Function PROCESS-SUSPEND-COUNT</a></dt>
+              <dt>process-wait, <a class="indexterm" href="#f_process-wait">Function PROCESS-WAIT</a></dt>
+              <dt>process-wait-with-timeout, <a class="indexterm" href="#f_process-wait-with-timeout">Function PROCESS-WAIT-WITH-TIMEOUT</a></dt>
+              <dt>process-whostate, <a class="indexterm" href="#f_process-whostate">Function PROCESS-WHOSTATE</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>R</h3>
+            <dl>
+              <dt>read-coverage-from-file, <a class="indexterm" href="#f_read-coverage-from-file">Function READ-COVERAGE-FROM-FILE</a></dt>
+              <dt>receive-from, <a class="indexterm" href="#f_receive-from">Function RECEIVE-FROM</a></dt>
+              <dt>release-lock, <a class="indexterm" href="#f_release-lock">Function RELEASE-LOCK</a></dt>
+              <dt>remote-host, <a class="indexterm" href="#f_remote-host">Function REMOTE-HOST</a></dt>
+              <dt>remote-port, <a class="indexterm" href="#f_remote-port">Function REMOTE-PORT</a></dt>
+              <dt>remove-open-file-stream, <a class="indexterm" href="#f_remove-open-file-stream">Function REMOVE-OPEN-FILE-STREAM</a></dt>
+              <dt>report-coverage, <a class="indexterm" href="#f_report-coverage">Function REPORT-COVERAGE</a></dt>
+              <dt>request-terminal-input-via-break, <a class="indexterm" href="#v_request-terminal-input-via-break">Variable *REQUEST-TERMINAL-INPUT-VIA-BREAK*</a></dt>
+              <dt>reset-coverage, <a class="indexterm" href="#f_reset-coverage">Function reset-coverage</a></dt>
+              <dt>restore-coverage, <a class="indexterm" href="#f_restore-coverage">Function RESTORE-COVERAGE</a></dt>
+              <dt>restore-coverage-from-file, <a class="indexterm" href="#f_restore-coverage-from-file">Function restore-coverage-from-file</a></dt>
+              <dt>rlet, <a class="indexterm" href="#m_rlet">Macro RLET</a></dt>
+              <dt>rletz, <a class="indexterm" href="#m_rletz">Macro RLETZ</a></dt>
+              <dt>run-program, <a class="indexterm" href="#f_run-program">Function RUN-PROGRAM</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>S</h3>
+            <dl>
+              <dt>save-application, <a class="indexterm" href="#Saving-Applications">Saving Applications</a></dt>
+              <dt>save-coverage, <a class="indexterm" href="#f_save-coverage">Function save-coverage</a></dt>
+              <dt>save-coverage-in-file, <a class="indexterm" href="#f_save-coverage-in-file">Function save-coverage-in-file</a></dt>
+              <dt>send-to, <a class="indexterm" href="#f_send-to">Function SEND-TO</a></dt>
+              <dt>set-development-environment, <a class="indexterm" href="#f_set-development-environment">Function SET-DEVELOPMENT-ENVIRONMENT</a></dt>
+              <dt>set-fpu-mode, <a class="indexterm" href="#f_set-fpu-mode">Function SET-FPU-MODE</a></dt>
+              <dt>set-lisp-heap-gc-threshold, <a class="indexterm" href="#f_set-lisp-heap-gc-threshold">Function SET-LISP-HEAP-GC-THRESHOLD</a></dt>
+              <dt>set-user-environment, <a class="indexterm" href="#f_set-user-environment">Function SET-USER-ENVIRONMENT</a></dt>
+              <dt>setenv, <a class="indexterm" href="#f_setenv">Function CCL::SETENV</a></dt>
+              <dt>setgid, <a class="indexterm" href="#f_setgid">Function CCL::SETGID</a></dt>
+              <dt>setuid, <a class="indexterm" href="#f_setuid">Function CCL::SETUID</a></dt>
+              <dt>shutdown, <a class="indexterm" href="#f_shutdown">Function SHUTDOWN</a></dt>
+              <dt>signal-external-process, <a class="indexterm" href="#f_signal-external-process">Function SIGNAL-EXTERNAL-PROCESS</a></dt>
+              <dt>signal-semaphore, <a class="indexterm" href="#f_signal-semaphore">Function SIGNAL-SEMAPHORE</a></dt>
+              <dt>socket-address-family, <a class="indexterm" href="#f_socket-address-family">Function SOCKET-ADDRESS-FAMILY</a></dt>
+              <dt>socket-connect, <a class="indexterm" href="#f_socket-connect">Function SOCKET-CONNECT</a></dt>
+              <dt>socket-error, <a class="indexterm" href="#c_socket-error">Class SOCKET-ERROR</a></dt>
+              <dt>socket-error-code, <a class="indexterm" href="#f_socket-error-code">Function SOCKET-ERROR-CODE</a></dt>
+              <dt>socket-error-identifier, <a class="indexterm" href="#f_socket-error-identifier">Function SOCKET-ERROR-IDENTIFIER</a></dt>
+              <dt>socket-error-situation, <a class="indexterm" href="#f_socket-error-situation">Function SOCKET-ERROR-SITUATION</a></dt>
+              <dt>socket-format, <a class="indexterm" href="#f_socket-format">Function SOCKET-FORMAT</a></dt>
+              <dt>socket-os-fd, <a class="indexterm" href="#f_socket-os-fd">Function SOCKET-OS-FD</a></dt>
+              <dt>socket-type, <a class="indexterm" href="#f_socket-type">Function SOCKET-TYPE</a></dt>
+              <dt>stream-deadline, <a class="indexterm" href="#Stream-Timeouts-And-Deadlines">Stream Timeouts and Deadlines</a></dt>
+              <dt>stream-device, <a class="indexterm" href="#f_stream-device">Generic Function CCL::STREAM-DEVICE</a></dt>
+              <dt>stream-input-timeout, <a class="indexterm" href="#Stream-Timeouts-And-Deadlines">Stream Timeouts and Deadlines</a></dt>
+              <dt>stream-output-timeout, <a class="indexterm" href="#Stream-Timeouts-And-Deadlines">Stream Timeouts and Deadlines</a></dt>
+              <dt>stream-read-ivector, <a class="indexterm" href="#f_stream-read-ivector">Generic Function STREAM-READ-IVECTOR</a></dt>
+              <dt>stream-read-list, <a class="indexterm" href="#f_stream-read-list">Generic Function CCL:STREAM-READ-LIST</a></dt>
+              <dt>stream-read-vector, <a class="indexterm" href="#f_stream-read-vector">Generic Function CCL:STREAM-READ-VECTOR</a></dt>
+              <dt>stream-write-ivector, <a class="indexterm" href="#f_stream-write-ivector">Generic Function STREAM-WRITE-IVECTOR</a></dt>
+              <dt>stream-write-list, <a class="indexterm" href="#f_stream-write-list">Generic Function CCL:STREAM-WRITE-LIST</a></dt>
+              <dt>stream-write-vector, <a class="indexterm" href="#f_stream-write-vector">Generic Function CCL:STREAM-WRITE-VECTOR</a></dt>
+              <dt>string-size-in-octets, <a class="indexterm" href="#string-size-in-octets">Function string-size-in-octets</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>T</h3>
+            <dl>
+              <dt>terminate-when-unreachable, <a class="indexterm" href="#f_terminate-when-unreachable">Function TERMINATE-WHEN-UNREACHABLE</a></dt>
+              <dt>timed-wait-on-semaphore, <a class="indexterm" href="#f_timed-wait-on-semaphore">Function TIMED-WAIT-ON-SEMAPHORE</a></dt>
+              <dt>try-lock, <a class="indexterm" href="#f_try-lock">Function TRY-LOCK</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>U</h3>
+            <dl>
+              <dt>unuse-interface-dir, <a class="indexterm" href="#f_unuse-interface-dir">Function UNUSE-INTERFACE-DIR</a></dt>
+              <dt>unwatch, <a class="indexterm" href="#f_unwatch">Function UNWATCH</a></dt>
+              <dt>use-interface-dir, <a class="indexterm" href="#f_use-interface-dir">Function USE-INTERFACE-DIR</a></dt>
+              <dt>use-lisp-heap-gc-threshold, <a class="indexterm" href="#f_use-lisp-heap-gc-threshold">Function USE-LISP-HEAP-GC-THRESHOLD</a></dt>
+            </dl>
+          </div>
+          <div class="indexdiv">
+            <h3>W</h3>
+            <dl>
+              <dt>wait-on-semaphore, <a class="indexterm" href="#f_wait-on-semaphore">Function WAIT-ON-SEMAPHORE</a></dt>
+              <dt>watch, <a class="indexterm" href="#f_watch">Function WATCH</a></dt>
+              <dt>with-altivec-registers, <a class="indexterm" href="#lapm_with-altivec-registers">LAP Macro WITH-ALTIVEC-REGISTERS</a></dt>
+              <dt>with-lock-grabbed, <a class="indexterm" href="#m_with-lock-grabbed">Macro WITH-LOCK-GRABBED</a></dt>
+              <dt>with-open-socket, <a class="indexterm" href="#m_with-open-socket">Macro WITH-OPEN-SOCKET</a></dt>
+              <dt>with-read-lock, <a class="indexterm" href="#m_with-read-lock">Macro WITH-READ-LOCK</a></dt>
+              <dt>with-terminal-input, <a class="indexterm" href="#m_with-terminal-input">Macro WITH-TERMINAL-INPUT</a></dt>
+              <dt>with-vector-buffer, <a class="indexterm" href="#lapm_with-vector-buffer">LAP Macro WITH-VECTOR-BUFFER</a></dt>
+              <dt>with-write-lock, <a class="indexterm" href="#m_with-write-lock">Macro WITH-WRITE-LOCK</a></dt>
+              <dt>without-compiling-code-coverage, <a class="indexterm" href="#v_without-compiling-code-coverage">Macro WITHOUT-COMPILING-CODE-COVERAGE</a></dt>
+              <dt>without-interrupts, <a class="indexterm" href="#m_without-interrupts">Macro WITHOUT-INTERRUPTS</a></dt>
+              <dt>write-coverage-to-file, <a class="indexterm" href="#f_write-coverage-to-file">Function WRITE-COVERAGE-TO-FILE</a></dt>
+              <dt>write-to-watched-object, <a class="indexterm" href="#c_write-to-watched-object">Condition WRITE-TO-WATCHED-OBJECT</a></dt>
+            </dl>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div xmlns="http://www.w3.org/TR/xhtml1/transitional" align="center">
+      <a href="#Symbol-Index">Symbol Index</a>
+    </div>
+    <p xmlns="http://www.w3.org/TR/xhtml1/transitional" xmlns:date="http://exslt.org/dates-and-times" class="footer">This document was last modified at 19:42 on December 10, 2009, in UTC.<br></br>It uses version 1.73.2 of the Norman Walsh Docbook stylesheets.<br></br>Built from subversion rev 13291<br></br>Using libxml 20631, libxslt 10122 and libexslt 813.</p>
+  </body>
+</html>
Index: /branches/new-random/doc/doc-splitter.lisp
===================================================================
--- /branches/new-random/doc/doc-splitter.lisp	(revision 13309)
+++ /branches/new-random/doc/doc-splitter.lisp	(revision 13309)
@@ -0,0 +1,416 @@
+;;; Copyright (c) 2008 Clozure Associates.  All Rights Reserved.
+
+;;;
+;;; (doc-splitter:split-doc-file "ccl:doc;ccl-documentation.html" "ccl:doc;manual;")
+;;;
+
+(eval-when (eval compile load)
+  (defpackage doc-splitter
+    (:use common-lisp ccl)
+    (:export #:split-doc-file)))
+
+(in-package doc-splitter)
+
+(defparameter *output-template*
+  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
+<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
+<html xmlns=\"http://www.w3.org/1999/xhtml\">
+  <head>
+    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />
+    <title>Clozure CL Documentation</title>
+  </head>
+  <body>
+
+<table width=\"100%\" cellspacing=\"1\" cellpadding=\"1\" border=\"1\">
+<tr><td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((PREVIOUS))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((NEXT))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"0%\"></td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((HOME))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((GLOSSARY))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((INDEX))</td>
+</tr></table>
+<hr>
+ ((BODY))
+<hr>
+<table width=\"100%\" cellspacing=\"1\" cellpadding=\"1\" border=\"1\">
+<tr><td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((PREVIOUS))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((NEXT))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"0%\"></td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((HOME))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((GLOSSARY))</td>
+    <td align=\"center\" bgcolor=\"((BGCOLOR))\" width=\"20%\">((INDEX))</td>
+</tr></table>
+</body>
+")
+
+(defparameter *links-bgcolor* "lightgray")
+
+(defparameter *link-names* '((:previous . "Previous")
+                             (:next . "Next")
+                             (:up . "Up")
+                             (:home . "Table of Contents")
+                             (:glossary . "Glossary")
+                             (:index . "Index")))
+
+(defun output-split-doc-header-link (stream sf link)
+  (let ((name (cdr (assq link *link-names*))))
+    (if sf
+      (format stream "<a href=\"~a\"><b>~a~@[ ~a~]</b></a>"
+              (split-file-name sf)
+              name
+              (and (memq link '(:previous :next))
+                   (if (eq (split-file-type sf) :sect1) "Section" "Chapter")))
+      (format stream "~:(~a~)" name))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defstruct node
+  start
+  end)
+
+;; Text node
+(defstruct (tnode (:include node))
+  )
+
+;; Compound node
+(defstruct (cnode (:include node))
+  tag
+  tag-end
+  children)
+
+(defmethod print-object ((node cnode) stream)
+  (print-unreadable-object (node stream :type t) 
+    (format stream "~s ~s:~s:~s~a"
+	    (cnode-tag node) (cnode-start node) (cnode-tag-end node) (cnode-end node)
+	    (cond ((null (cnode-children node)) "")
+		  ((null (cdr (cnode-children node))) " 1 child")
+		  (t (format nil " ~s children" (length (cnode-children node))))))))
+
+(defun node-tag (node)
+  (and (cnode-p node) (cnode-tag node)))
+
+;; Toplevel node
+(defstruct html
+  string
+  node)
+
+(defmethod print-object ((node html) stream)
+  (print-unreadable-object (node stream :type t)
+    (let ((*print-string-length* 400))
+      (format stream ":STRING ~s :NODE ~s" (html-string node) (html-node node)))))
+
+(defstruct split-file
+  type
+  name
+  up
+  nodes)
+
+(defvar *cur-html* nil)
+
+(defun split-doc-file (html directory)
+  (unless (html-p html)
+    (setq html (read-html-file html)))
+  (ensure-directories-exist directory)
+  (let* ((*cur-html* html)
+         (splits (doc-file-splits html))
+         (id-table (make-hash-table :test #'equal))
+         (top (find :book splits :key #'split-file-type))
+         (glossary (find :glossary splits :key #'split-file-type))
+         (index (find :symbol-index splits :key #'split-file-type)))
+    (loop for sf in splits as name = (split-file-name sf)
+      do (loop for node in (split-file-nodes sf)
+           do (doc-file-register-ids node name id-table)))
+    (loop
+      for prev = nil then sf
+      for prev-chap = nil then (if (eq (split-file-type sf) :sect1) prev-chap sf)
+      for sfs on splits
+      for sf = (car sfs)
+      do (with-open-file (stream (merge-pathnames (split-file-name sf) directory)
+                                 :direction :output
+                                 :if-exists :supersede)
+           (output-split-doc-file sf stream id-table
+                                  :previous (if (eq (split-file-type sf) :sect1) prev prev-chap)
+                                  :next (if (eq (split-file-type sf) :sect1)
+                                          (cadr sfs)
+                                          (find :sect1 (cdr sfs) :key #'split-file-type :test #'neq))
+                                  :top top
+                                  :glossary glossary
+                                  :index index)))))
+
+(defun output-split-doc-file (sf stream id-table &key previous next top glossary index)
+  (loop with template = *output-template*
+    for start = 0 then (+ epos 2)
+    as bpos = (search "((" template :start2 start) while bpos
+    as epos = (search "))" template :start2 bpos)
+    do (write-string template stream :start start :end bpos)
+    do (ecase (intern (subseq template (+ bpos 2) epos) :keyword)
+         (:previous
+          (output-split-doc-header-link stream previous :previous))
+         (:next
+          (output-split-doc-header-link stream next :next))
+         (:home
+          (output-split-doc-header-link stream top :home))
+         (:glossary
+          (output-split-doc-header-link stream glossary :glossary))
+         (:index
+          (output-split-doc-header-link stream index :index))
+         (:bgcolor
+          (write-string *links-bgcolor* stream))
+         (:body
+          (output-split-doc-file-body stream sf id-table)))
+    finally (write-string template stream :start start)))
+
+;; (setq *print-string-length* 400 *print-length* 100 *print-level* 50)
+(defun read-html-file (pathname)
+  (with-open-file (stream pathname)
+    (let ((str (make-string (file-length stream))))
+      (read-sequence str stream)
+      (make-html :string str
+                 :node (read-html-form str (search "<html" str :test #'char-equal) (length str))))))
+
+
+(defun output-split-doc-file-body (stream sf id-table)
+  (let* ((up (split-file-up sf))
+         (up-title (and up (split-file-title up))))
+    (when up-title
+      (format stream "<a href=\"~a\">~a</a>" (split-file-name up) up-title)))
+  (loop with string = (html-string *cur-html*)
+    for node in (split-file-nodes sf)
+    do (let ((hrefs (doc-file-collect-hrefs node id-table)))
+         (setq hrefs (sort hrefs #'< :key #'car))
+         (assert (or (null hrefs) (<= (node-start node) (caar hrefs))))
+         (loop as start = (node-start node) then pos
+           for (pos . name) in hrefs
+           do (write-string string stream :start start :end pos)
+           do (write-string name stream)
+           finally (write-string string stream :start start :end (node-end node)))
+         (fresh-line stream))))
+
+(defun doc-file-register-ids (node name hash)
+  (when (cnode-p node)
+    (let ((id (and (eq (cnode-tag node) :a)
+                   (cnode-attribute-value node :id))))
+      (when id
+        (let ((old (gethash id hash)))
+          (when old
+            (warn "~s already registered in file ~s" id old)))
+        (setf (gethash id hash) name)))
+    (loop for subnode in (cnode-children node)
+      do (doc-file-register-ids subnode name hash))))
+
+(defun doc-file-collect-hrefs (node hash)
+  (when (cnode-p node)
+    (let* ((hrefs (loop for subnode in (cnode-children node)
+                    nconc (doc-file-collect-hrefs subnode hash)))
+           (href (and (eq (cnode-tag node) :a)
+                      (cnode-attribute-value node :href))))
+      (when (and href (eql 0 (position #\# href)))
+        (let ((name (gethash (subseq href 1) hash)))
+          (unless name
+             (warn "Couldn't find the split file id for href ~s" href))
+          (when name
+            (let ((pos (search (format nil "href=~s" href) (html-string *cur-html*)
+                               :start2 (cnode-start node) :end2 (cnode-tag-end node))))
+              (assert pos)
+              (push (cons (+ pos 6) name) hrefs)))))
+      hrefs)))
+
+(defparameter *times* 0)
+(defun split-file-title (sf)
+  (labels ((title (node)
+             (when (cnode-p node)
+               (if (and (eq (cnode-tag node) :h2)
+                        (equal (cnode-attribute-value node :class) "title"))
+                 (labels ((text (node)
+                            (if (tnode-p node)
+                              (subseq (html-string *cur-html*) (node-start node) (node-end node))
+                              (apply #'concatenate 'string
+                                     (loop for sub in (cnode-children node) collect (text sub))))))
+                   (text node))
+                 (loop for sub in (cnode-children node) thereis (title sub))))))
+    (loop for node in (split-file-nodes sf) thereis (title node))))
+
+(defun doc-file-splits (html)
+  (let* ((*cur-html* html)
+         (node (html-node html)))
+    (assert (eq (node-tag node) :html))
+    (setq node (find :body (cnode-children node) :key #'node-tag))
+    (assert node)
+    (setq node (find :div (cnode-children node) :key #'node-tag))
+    (assert node)
+    (assert (equal (cnode-attribute-value node :class) "book"))
+    (loop with nchapters = 0
+      for subnode in (cnode-children node)
+      as class = (and (eq (node-tag subnode) :div) (cnode-attribute-value subnode :class))
+      if (member class '("chapter" "glossary" "index") :test #'equal)
+      nconc (doc-file-chapter-splits subnode (incf nchapters)) into sections
+      else collect subnode into nodes
+      finally (let ((sf (make-split-file :name "index.html" :type :book :nodes nodes)))
+                (loop for sub in sections
+                  unless (eq (split-file-type sub) :sect1) do (setf (split-file-up sub) sf))
+                (return (cons sf sections))))))
+
+(defun doc-file-chapter-splits (node num)
+  (let* ((class (and (eq (node-tag node) :div) (cnode-attribute-value node :class))))
+    (cond ((equal class "chapter")
+           (loop with nsect = 0
+             for subnode in (cnode-children node)
+             as class = (and (eq (node-tag subnode) :div) (cnode-attribute-value subnode :class))
+             if (equal class "sect1")
+             collect (make-split-file :name (format nil "chapter~d.~d.html" num (incf nsect))
+                                      :type :sect1 :nodes (list subnode)) into sections
+             else collect subnode into nodes
+             finally (let ((sf (make-split-file :name (format nil "chapter~d.html" num)
+                                                    :type :chapter :nodes nodes)))
+                       (loop for sub in sections do (setf (split-file-up sub) sf))
+                       (return (cons sf sections)))))
+          ((equal class "glossary")
+           (list (make-split-file :name "glossary.html" :type :glossary :nodes (list node))))
+          ((equal class "index")
+           (list (make-split-file :name "symbol-index.html" :type :symbol-index :nodes (list node))))
+          (t (error "expected a chapter, glossary or index: ~s" class)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Returns NIL for </tag> case.
+(defun read-html-tag (str s e &aux (s1 (1+ s)))
+  (and (< s e)
+       (eq (char str s) #\<)
+       (let* ((te (or (position-if #'(lambda (ch) (or (whitespacep ch)
+                                                      (char= ch #\>)
+                                                      (char= ch #\/)))
+                                   str :start s1 :end e)
+                      e)))
+	 (and (< s1 te)
+	      (intern (nstring-upcase (subseq str s1 te)) ccl::*keyword-package*)))))
+
+;; Returns NIL if at end of buffer or if looking at "</..."
+(defun read-html-form (str s e &optional (tag (read-html-tag str s e)))
+  (cond (tag
+	 (let* ((te (1+ (position-ignoring-strings #\> str s e)))
+		(node (make-cnode :tag tag
+				  :start s
+				  :tag-end te
+				  :end e
+				  :children nil)))
+	   (if (eq (char str (- te 2)) #\/)
+	     (setf (node-end node) te)
+	     (read-html-children-into-cnode str node))
+	   node))
+	((>= s e) NIL)
+	((eq (char str s) #\<)
+	 (assert (and (< (1+ s) e) (eq (char str (1+ s)) #\/)))
+	 NIL)
+	(t (make-tnode :start s :end (or (position #\< str :start s :end e) e)))))
+
+(defun position-ignoring-strings (ch str start end)
+  (let* ((p (position ch str :start start :end end)))
+    (and p
+	 (let ((q (position #\" str :start start :end p)))
+	   (if (null q)
+	     p
+	     (let ((qe (position #\" str :start (1+ q) :end end)))
+	       (and qe
+		    (position-ignoring-strings ch str (1+ qe) end))))))))
+
+(defun read-html-children-into-cnode (str node)
+  ;; This is entered with node-end = end of region, and it updates both
+  ;; cnode-children and node-end.  Eats up the ending tag if it matches
+  ;; the node tag, otherwise leaves it to be re-read.
+  (let* ((s (cnode-tag-end node))
+	 (e (cnode-end node)))
+    (loop
+      (assert (< s e) () "Unended tag ~S" (subseq str (cnode-start node) e))
+      (when (string= "</" str :start2 s :end2 (min (+ s 2) e))
+	(let* ((te (1+ (position #\> str :start s :end e))))
+	  (setf (cnode-end node)
+		(if (string-equal str (symbol-name (cnode-tag node))
+				   :start1 (+ s 2) :end1 (1- te))
+		  te s))
+	  (return)))
+      (let* ((ntag (read-html-tag str s e))
+             (child (read-html-form str s e ntag)))
+        (setq s (node-end child))
+        (push child (cnode-children node))))
+    (setf (cnode-children node) (nreverse (cnode-children node)))))
+
+(defun cnode-attributes (node &optional string-or-html &aux string)
+  (setq string-or-html (or string-or-html *cur-html*))
+  (setq string (if (html-p string-or-html) (html-string string-or-html) string-or-html))
+  (multiple-value-bind (start end)
+      (let* ((start (1+ (node-start node)))
+             (end (cnode-tag-end node))
+             (word-end (position-if #'(lambda (ch) (or (whitespacep ch)
+                                                       (char= ch #\>)
+                                                       (char= ch #\/)))
+                                    string :start start :end end)))
+        (assert word-end)
+        (values word-end (1- end)))
+    (flet ((next-token (type)
+             (when (setq start (position-if-not #'whitespacep string :start start :end end))
+               (let ((ch (char string start)))
+                 (incf start)
+                 (case ch
+                   ((#\" #\')
+                    (assert (eq type :value))
+                    (let ((tend (position ch string :start start :end end)))
+                      (prog1
+                          (subseq string start tend)
+                        (setq start (1+ tend)))))
+                   ((#\=)
+                    (assert (eq type :separator))
+                    t)
+                   ((nil)
+                    (assert (or (eq type :attribute) (eq type :separator)))
+                    nil)
+                   (t
+                    (assert (or (eq type :value) (eq type :attribute)))
+                    (let ((tend (or (position-if #'(lambda (ch) (or (whitespacep ch) (eql ch #\=)))
+                                                 string :start start :end end) end)))
+                      (prog1
+                          (subseq string (1- start) tend)
+                        (setq start tend)))))))))
+      (loop
+        as attribute = (next-token :attribute) while attribute
+        collect (cons (intern (string-upcase attribute) :keyword)
+                      (if (next-token :separator) (next-token :value) t))))))
+
+(defun cnode-attribute-value (node attribute &optional string-or-html)
+  (cdr (assoc attribute (cnode-attributes node string-or-html) :test #'eq)))
+
+#+debugging
+(defun debug-print-html (str node &key (stream t) (depth nil))
+  (when (html-p str) (setq str (html-string str)))
+  (if (null stream)
+    (with-output-to-string (s) (debug-print-html str node :stream s :depth depth))
+    (labels ((print (node cur-depth)
+               (etypecase node
+                 (tnode (format stream "~A" (subseq str (node-start node) (node-end node))))
+                 (cnode (format stream "~A" (subseq str (node-start node) (cnode-tag-end node)))
+                        (if (or (null depth) (< cur-depth depth))
+                          (dolist (child (cnode-children node))
+                            (print child (1+ cur-depth)))
+                          (format stream "..."))
+                        (format stream "</~A>" (node-tag node))))))
+      (print node 0))))
+
+#+debugging
+(defun debug-outline-html (str node &key (stream t) (depth nil))
+  (if (null stream)
+    (with-output-to-string (s) (debug-outline-html str node s depth))
+    (labels ((outline (node cur-depth idx)
+               (etypecase node
+                 (tnode (unless (loop for i from (node-start node) below (node-end node)
+                                  always (whitespacep (char str i)))
+                          (if idx (format stream "[~a]..." idx) (format stream "..."))))
+                 (cnode (fresh-line stream)
+                        (if idx (format stream "~&[~a]" idx) (format stream "~&"))
+                        (dotimes (i cur-depth) (write-char #\Space stream))
+                        (format stream "<~A ~:a>" (cnode-tag node) (cnode-attributes node str))
+                        (when (or (null depth) (< cur-depth depth))
+                          (loop for i upfrom 0 as child in  (cnode-children node)
+                            do (outline child (1+ cur-depth) (if idx (format nil "~a.~d" idx i)
+                                                               (format nil "~d" i)))))
+                        (format stream "</~A>" (node-tag node))))))
+      (outline node 0 nil))))
Index: /branches/new-random/doc/release-notes-1.1.txt
===================================================================
--- /branches/new-random/doc/release-notes-1.1.txt	(revision 13309)
+++ /branches/new-random/doc/release-notes-1.1.txt	(revision 13309)
@@ -0,0 +1,2140 @@
+OpenMCL 1.1-pre-070722
+- This will hopefully be the last set of snapshots whose version
+  number contains the string "pre-"; whether or not the last
+  20 months worth of "1.1-pre-yymmdd" snapshot releases are
+  more or less stable than something without "pre-" in its name
+  doesn't have too much to do much to do with whether or not "pre-"
+  is in the version number (and has lots to do with other things.)
+  I'd like to move to a model that's mostly similar to how things
+  have been (new version every month or two, old versions become
+  obsolete soon after, sometimes changes introduce binary incompatiblity)
+  but drop the "prerelease" designation and change the name of the
+  "testing" directory to something like "current".
+- The FASL version didn't change (for the first time in a long time.)
+  It's probably a lot easier to bootstrap new sources with a new
+  lisp and it's probably desirable to recompile your own source
+  code with the new lisp, but there shouldn't be any user-visible
+  low-level ABI changes that make that mandatory.
+- CCL::WITH-ENCODED-CSTRS (which has been unexported and somewhat
+  broken) is now exported and somewhat less broken.
+
+  (ccl:with-encoded-cstrs ENCODING-NAME ((varI stringI)*) &body body)
+
+  where ENCODING-NAME is a keyword constant that names a character
+  encoding executes BODY in an environment where each variable varI
+  is bound to a nul-terminated, dynamic-extent foreign pointer to
+  an encoded version of the corresponding stringI.
+
+  (ccl:with-cstrs ((x "x")) (#_puts x))
+
+  is functionally equivalent to:
+
+  (ccl:with-encoded-cstrs :iso-8859-1 ((x "x")) (#_puts x))
+
+
+  CCL:WITH-ENCODED-CSTRS doesn't automatically prepend byte-order-marks
+  to its output; the size of the terminating #\NUL depends on the
+  number of octets-per-code-unit in the encoding.
+
+  There are certainly lots of other conventions for expressing
+  the length of foreign strings besides NUL-termination (length in
+  code units, length in octets.)  I'm not sure if it's better to
+  try to come up with high-level interfaces that support those
+  conventions ("with-encoded-string-and-length-in-octets ...")
+  or to try to support mid-level primitives ("number of octets
+  in encoded version of lisp string in specified encoding", etc.)
+
+- STREAM-ERRORs (and their subclasses, including READER-ERROR)
+  try to describe the context in which they occur a little better
+  (e.g., by referencing the file position if available and
+  by trying to show a few surrounding characters when possible.)
+  Since streams are usually buffered, this context information
+  may be incomplete, but it's often much better than nothing.
+
+- Hashing (where some objects are hashed by address) and OpenMCL's
+  GC (which often changes the addresses of lisp objects, possibly
+  invalidating hash tables in which those objects are used as keys)
+  have never interacted well; to minimize the negative effects of
+  this interaction, most primitive functions which access hash
+  tables has disabled the GC while performing that access, secure
+  in the knowledge that hash table keys won't be moving around
+  (because of GC activity in other threads) while the hash table
+  lookup is being performed.
+
+  Disabling and reenabling the GC can be somewhat expensive, both
+  directly (in terms of the primitive operations used to do so)
+  and indirectly (in terms of the cost of - temporarily - not being
+  able to GC when otherwise desirable.)  If the GC runs (and possibly
+  moves a hash-table key) very rarely relative to the frequency of
+  hash-table access - and that's probably true, much of the time -
+  then it seems like it'd be desirable to avoid the overhead of
+  disabling/reenabling the GC on every hash table access, and it'd
+  be correct to do this as long as we're careful about it.
+
+  I was going to try to change all hash-table primitives to try
+  to make them avoid inhibiting/enabling the GC for as long as
+  possible, but wimped out and only did that for GETHASH.  (If
+  another thread could GC while we're accessing a hash table, there
+  can still be weird intercations between things like the GC's
+  handling of weak objects and code which looks at the hash table,
+  and that weirdness seemed easier to deal with in the GETHASH case
+  than in some others.)
+
+  If GETHASH's performance has improved without loss of correctness,
+  then it'd likely be worth trying to make similar changes to
+  REMHASH and CCL::PUTHASH (which implements (SETF (GETHASH ...) ...).
+  If problems are observed or performance still hasn't improved, it'd
+  probably be worth re-thinking some of this.
+
+- Leading tilde (~) characters in physical pathname namestrings
+  are expanded in the way that most shells do:
+
+  "~user/...." can be used to refer to an absolute pathname rooted
+  at the home directory of the user named "user"
+
+  "~/..." can be used to refer to an absulte pathname rooted at
+  the home directory of the current user.
+
+- The break-loop colon commands for showing the contents of
+  stack frames try to present the frame's contents in a way that's
+  (hopefully) more meaningful and useful.  For each stack frame
+  shown in detail, the corresponding function's argument list
+  is printed, followed by the current values of the function's
+  arguments (indented slightly), a blank line, and the current
+  values of the function's local variables (outdented slightly.)
+  The old method of showing a stack frame's "raw" contents is
+  still available as the :RAW break loop command.
+
+  The new style of presenting a stack-frame's contents is also
+  used in the Cocoa IDE.
+
+- It's historically been possible to create stacks (for threads
+  other than the original one) whose size exceeds the nominal
+  OS resource limits for a stack's size.  (OpenMCL's threads
+  use multiple stacks; the stack in question is the one that
+  OpenMCL generally refers to as the "control" or "C" stack.)
+  It's not entirely clear what (if anything) the consequences
+  of exceeding these limits have been, but OpenMCL's GC can
+  use all of the available (C) stack space that it thinks it
+  has under some conditions, and, under OSX/Mach/Darwin, there
+  have been reports of excessive page file creation and paging
+  activity that don't seem related to heap behavior in environments
+  where the GC is running on (and possibly using much of) a stack
+  whose size greatly exceeds the hard resource limit on stack
+  size.
+
+  Trying to determine exactly what was causing the excessive
+  pages got me trapped in a twisty maze of Mach kernel sources,
+  all alike.  I tried to pin C stack size to the hard resource
+  limit on stack size and have not been able to provoke the
+  excessive paging problems since, but am not confident in
+  concluding (yet) that the problems had to do with resource
+  limits being exceeded.
+
+  The hard resource limits on stack size for the OS versions
+  that I have readily available (in bash, do "ulimit -s -H";
+  in tcsh, it's "limit -h s", don't know offhand about other
+  shells) are:
+
+  unlimited on Linux
+  ~512M on FreeBSD
+  ~64M on Darwin
+
+  The effect of observing (rather than exceeding) this limit
+  on the maximum depth of lisp recursion in OpenMCL is:
+
+  * nothing, on x86-64 (the C stack is not used by lisp code
+    on x86-64)
+
+  * visible on ppc32, which uses 4 32-bit words on the control
+    stack for each lisp function invocation
+
+  * more visible on ppc64, which uses 4 64-bit words of control
+    stack for each lisp function invocation.
+
+  That seems to suggest that (given that the actual stack resource
+  limit is a bit under 64M and that OpenMCL signals stack overflow
+  when the stack pointer gets within a few hundred KB of the actual
+  limit) that ppc64 threads are now limited to a maximum of about
+  2000000 function calls.
+
+  (All of this only matters if attempts are made to create threads
+  with large stacks; the default stack sizes in OpenMCL are usually
+  1-2 MB.)
+
+- On a cheerier (and certainly less confusing) note: for the last few
+  years, OpenMCL has shipped with an extended example which provides an
+  integrated development environment (IDE) based on Cocoa; that's often
+  been described as "the demo IDE" and could also be fairly described as
+  "slow", "buggy", "incomplete", and "little more than a proof of
+  concept."
+
+  I think that it's fair to describe the current state of the IDE as
+  being "less slow", "less buggy", "less incomplete", and "much more
+  than a proof of concept" than it has been (e.g., there's been some
+  actual progress over the last few months and there are plans to
+  try to continue working on the IDE and related tools.)  It'd probably
+  be optimistic to call it "usable" in its current state (that may
+  depend on how low one's threshold of usability is), but I hope that
+  people who've been discouraged by the lack of IDE progress over the
+  last few years will see reason to be encouraged (and that anyone
+  interested will submit bug reports, patches, feature requests, code ...)
+
+- There are now "objc-bridge" and "cocoa-ide" subdirectories; by default,
+  REQUIRE will look in these directories for files whose name matches
+  a module name.  Several files were moved from the "examples" directory
+  to "objc-bridge"; other example files, the "OpenMCL.app" skeleton
+  bundle, and the "hemlock" directory were moved to "cocoa-ide".
+
+
+OpenMCL 1.1-pre-070512
+- The FASL version changed (old FASL files won't work with this
+  lisp version), as did the version information which tries to
+  keep the kernel in sync with heap images.  Note that it's generally
+  a lot easier to recompile recent sources with recent images, e.g.,
+  trying to compile 070512 sources with an 070407 image is unlikely
+  to work without tricky bootstrapping.
+- Most of the changes in this release involve the calling sequence
+  used on x86-64.  In very general terms, some kinds of function-call
+  intensive code may see a significant performance boost, most code
+  should see a slight improvement, some code might see a (hopefully
+  very slight) degradation, and anything significantly slower than
+  previous releases should be reported as a bug.
+  It is -possible- that some of these changes may cause errors to
+  be reported differently (the function reported as the function
+  executing when the error ocurred might be different/wrong).  I
+  have not seen as many cases of this as I expected to when making
+  the change, but am also not sure that I fixed all possible cases.
+- The FFI-related reader macros #_, #$, and #& all read a case-sensitive
+  foreign function, constant, or variable name from the input stream
+  and try to find the corresponding definition in the interface files.
+  If the name is prefixed with a #\? - as in #_?foo - the macros
+  return true if the definition could be found and false otherwise.
+  (The general idea is that this might be useful for conditionalizing
+  code in some cases, and there should be -some- way of quietly testing 
+  that something's defined.)
+- There is now support for making the contents of (possibly very large)
+  files accessible as lisp vectors.  (This may be many times faster
+  than something like 
+
+  (let* ((stream (open pathname :direction :input :element-type 'whatever))
+         (vector (make-array (file-size-to-vector-size stream)
+                             :element-type 'whatever)))
+    (read-sequence vector stream))
+
+  but has the similar effect of making the contents of VECTOR match the
+  contents of the file.)
+
+  CCL:MAP-FILE-TO-IVECTOR pathname element-type [Function]
+
+  "element-type" should be a type specifier such that
+  (UPGRADED-ARRAY-ELEMENT-TYPE element-type) is a subtype
+  of either SIGNED-BYTE or UNSIGNED-BYTE.
+
+  Tries to open the file named by "pathname" for reading and to
+  map its contents into the process's address space via #_mmap;
+  if successful, returns a lisp vector of element-type
+  (UPGRADED-ARRAY-ELEMENT-TYPE element-type) which is displaced
+  to an underlying (SIMPLE-ARRAY element-type (*)) whose contents
+  match the mapped file's.
+
+  Because of alignment issues, the mapped file's contents will
+  start a few bytes (4 bytes on 32-bit platforms, 8 bytes on 64-bit
+  platforms) "into" the vector; the displaced array returned by
+  CCL:MAP-FILE-TO-IVECTOR hides this overhead, but its usually
+  more efficient to operate on the underlying simple 1-dimensional
+  array.  Given a displaced array (like the value returned by
+  CCL:MAP-FILE-TO-IVECTOR), the CL function ARRAY-DISPLACEMENT
+  returns the underlying array and the displacement index in elements.
+
+  Currently, only read-only file mapping is supported; the underlying
+  vector will be allocated in read-only memory, and attempts to use
+  (e.g.) (SETF (AREF ...) ...) to modify the mapped vector's contents
+  will result in memory faults.
+  
+  CCL:MAP-FILE-TO-OCTET-VECTOR pathname [Function]
+
+  Equivalent to (CCL:MAP-FILE-TO-IVECTOR pathname '(UNSIGNED-BYTE 8)).
+
+  CCL:UNMAP-IVECTOR displaced-vector
+
+  If the argument is a mapped vector (as returned by
+  MAP-FILE-TO-IVECTOR) that has not yet been "unmapped" by this
+  function, undoes the memory mapping, closes the mapped file, and
+  adjusts its argument so that it's displaced to a 0-length vector.
+
+  CCL:UNMAP-OCTET-VECTOR is an alias for CCL:UNMAP-IVECTOR
+
+  Note that whether a vector's created by MAKE-ARRAY or by mapping
+  a file's contents, it can't have ARRAY-TOTAL-SIZE-LIMIT or more
+  elements.  (ARRAY-TOTAL-SIZE-LIMIT is (EXPT 2 24) in 32-bit OpenMCL
+  and (EXPT 2 56) in 64-bit versions.
+
+- The lisp kernel now tries to signal memory faults that occur when
+  running lisp code as lisp errors.  As a silly example:
+
+  ? (defun foo (x)
+     "Crash and burn if X is not a list"
+     (declare (optimize (speed 3) (safety 0)) (list x))
+     (car x))
+  FOO
+  ? (foo 0)
+  > Error: Fault during read of memory address #x4
+  > While executing: FOO, in process listener(1).
+
+  The fact that things are handled this way (rather than going
+  into the kernel debugger with no easy way of recovering) makes
+  it possible to continue a session without losing work in many
+  cases.  In a trivial example like the one above, it's relatively
+  easy to see that no harm has been done and the error should
+  not be hard to recover from.  In some other cases, it may be
+  true that a buggy function has been scribbling ofer memory for
+  a while before that scribbling resulted in a machine exception.
+
+  Moral: if you get an unexpected "memory fault" error (the
+  condition type is actually CCL::INVALID-MEMORY-ACCESS) and
+  don't understand why the fault occurred and the consequences
+  of continuing in the lisp session where the fault occurred,
+  you should view the state of that session with some suspicion.
+
+  Faults in foreign code (should) still trap into the kernel
+  debugger.  (It'd be nice to be able to treat these as lisp
+  errors with the same caveats as described above, but that
+  is more complicated in some cases and isn't yet implemented.)
+
+- An obscure kernel debugger command - (A), which tries to advance
+  the program counter by one instruction - is now disabled on x86-64.
+  (On the PPC, "one instruction" always meant "4 bytes"; implementing
+  this correctly on x86-64 would require the ability to at least
+  partially disassemble arbitrary x86-64 instructions.)
+
+  On the other hand, the kernel debugger should be able to show
+  FPU registers on x86-64.
+
+
+OpenMCL 1.1-pre-070408
+- The FASL version changed (old FASL files won't work with this
+  lisp version), as did the version information which tries to
+  keep the kernel in sync with heap images.  Note that it's generally
+  a lot easier to recompile recent sources with recent images, e.g.,
+  trying to compile 070408 sources with an 070214 image is unlikely
+  to work without tricky bootstrapping.
+- There's now a Trac bug-tracking/wiki site for OpenMCL at 
+  <http://trac.clozure.com/openmcl>.  It needs bug reports; please
+  visit that site and use the features there to report any bugs
+  that you find.
+- DEFSTATIC (aka DEFGLOBAL)
+  (CCL:DEFSTATIC var value &optional doc-string)
+  is like DEFPARAMETER in that it proclaims the variable "var" to
+  be special, sets its value to "value", and sets the symbol's
+  VARIABLE documentation to the optional doc-string.  It differs
+  from DEFPARAMETER in that it further asserts that the variable
+  should never be bound dynamically in any thread (via LET/LAMBDA/etc.);
+  the compiler treats any attempts to bind a "static" variable as an
+  error.
+  It is legal to change the value of a "static" variable, but since
+  all threads see the same (static) binding of that variable it may
+  be necessary to synchronize assignments made from multiple threads.
+  (A "static" variable binding is effectively a shared, global resource;
+  a dynamic binding is thread-private.)
+  Access to the value of a static variable is typically faster than
+  is access to the value a special variable that's not proclaimed to
+  be "static".
+  This functionality has been in MCL/OpenMCL for a long time under
+  the name CCL:DEFGLOBAL; CCL:DEFGLOBAL is an alias for CCL:DEFSTATIC,
+  but the latter seemed to be a better name.
+- The type of foreign object that a MACPTR points to can now be
+  asserted (this means that a MACPTR object can contain a small
+  integer which identifies the alleged FOREIGN-TYPE of the object that
+  the points to.  RLET, MAKE-RECORD, and MAKE-GCABLE-RECORD (see below)
+  assert the foreign type of the object that the MACPTR object they
+  create (as do some new features of the ObjC bridge, described further
+  below.)
+  PRINT-OBJECT on a MACPTR will try to print information about the
+  asserted type of that pointer, as well as information about where
+  the pointer was allocated (heap, stack) and whether it's scheduled
+  for automatic reclamation by the GC.
+  A few constructs that conceivable should assert the type of the
+  pointers they create (e.g., some flavor of PREF, SLOT-VALUE in
+  the ObjC bridge) don't yet do so.
+  A rather obvious way of exploiting typed pointers - namely, extending
+  DESCRIBE and INSPECT to show the contents of foreign records - is
+  not yet implemented.
+- MAKE-GCABLE-RECORD is like MAKE-RECORD, in that it "makes an instance
+  of a foreign record type".  (Or, to be more banal about it, uses
+  #_malloc to allocate a block of foreign memory of the size of the
+  foreign record type named by its argument.)  MAKE-GCABLE-RECORD
+  additionally tells the lisp garbage collector that it should free
+  the foreign memory when the MACPTR object that describes it becomes
+  garbage.
+  When using "gcable pointers", it's important to remember the
+  distinction between a MACPTR object (which is a lisp object, more-
+  or-less like any other) and the block of foreign memory that the
+  MACPTR object points to.  If a gcable MACPTR is the only thing
+  in the world ("lisp world" or "foreign world") that references
+  the underlying block of foreign memory, then freeing the foreign
+  memory when it becomes impossible to reference it is convenient
+  and sane.  If other lisp MACPTRs reference the underlying block
+  of foreign memory or if the address of that foreign memory is
+  passed to and retained by foreign code, having the GC free the
+  memory may have unpleasant consequences if those other references
+  are used.
+- CCL:FREE (which is mostly just a wrapper around #_free that allows
+  #_free to be called early in the bootstrapping process) is now 
+  exported; if its argument is a gcable pointer (e.g., created via
+  MAKE-GCABLE-POINTER), it will tell the GC that the pointer's
+  foreign memory has been freed "manually" before calling #_free.
+- The mechanisms used to implement locks has changed (for the curious,
+  the changes involve the use of spinlocks rather than a sequence
+  of atomic additions.)  Someone demonstrated a case of deadlock
+  (where a thread was waiting for a lock that was available) under
+  the old implementation.  I'm not sure that I fully understand how
+  that could have happened, but the new implementation at least has
+  the advantage of being a little easier to understand and might be
+  a tiny bit faster.  Please let me know if either of these assumptions
+  was incorrect.
+- An EOF (control-d) in the REPL (when standard input is a tty or pty
+  device) has traditionally caused an exit to the outer break loop
+  (or had no effect if the REPL was not in a break loop).  If
+  CCL:*QUIT-ON-EOF* is set, an EOF causes the lisp to quit.  (It
+  actually invokes a listener-specific method, so in a multi-listener
+  window system environemt, it might simply cause the listener which
+  receives the EOF to exit.)
+  None of this has any effect when running under environments like
+  SLIME, and (as mentioned above) only matters if the standard input
+  devices is a tty or pseudo-tty (where it's possible to continue
+  reading after an EOF has been read.)  If running under an xterm
+  or OSX Terminal.app, standard input is probably a pty; if running
+  in an Emacs shell buffer or under other means under emacs, different
+  types of IPC mechanisms (pipes, sockets) might be used.
+- SAVE-APPLICATION has historically changed the type of all MACPTR
+  objects (turning them into "dead macptrs", since it's generally
+  meaningless to refer to a foreign pointer from a previous session
+  and generally better to get a type error than some more mysterious
+  or severe failure).  This no longer happens for null pointers (pointers
+  to address 0); COMPILE-FILE also now allows null pointers to be referenced
+  as constants in compiled code.
+- Not entirely coincidentally, CCL:+NULL-PTR+ is now defined as a constant
+  (whose value is a null pointer.)  In some cases, it may be more
+  efficient or convenient to pass CCL:+NULL-PTR+ to foreign code than
+  it would be to call (CCL:%NULL-PTR) to "produce" one.
+- Historically, OpenMCL (and MCL) have maintained a list of open file
+  streams in the value of CCL:*OPEN-FILE-STREAMS*; maintaining this
+  list helps to ensure that streams get closed in as orderly a manner
+  as possible when the lisp exits.  The code which accessed this list
+  didn't do so in a thread-safe manner.
+  The list is now maintained in a lexical variable; the function
+  CCL:OPEN-FILE-STREAMS returns a copy of that list, 
+  CCL:NOTE-OPEN-FILE-STREAM adds its argument (a file stream) to the
+  list, and CCL:REMOVE-OPEN-FILE-STREAM removes its argument (a file stream)
+  from the list.  (All of these functions use appropriate locking.)
+- There were a number of timing-related problems related to PROCESS-INTERRUPT
+  (usually involving rapidly and repeatedly interrupting a thread over
+  a long period of time.)  This should be a lot more reliable now
+  (exactly what could go wrong and why and how is all a little hard to
+  describe.) 
+- Some Linux distributions may initialize the user's environment in
+  a way that imposes a soft limit on the amount of virtual memory that
+  a process is allowed to map.  OpenMCL now tries to raise this limit
+  before reserving what may be a very large amount of address space,
+  thanks to a patch from Andi Kleen.
+- There were a number of problems with UTF-16 streams, found and
+  fixed by Takehiko Abe.
+- Takehiko Abe also provided fixes for some code in "ccl:lib;xref.lisp"
+  and in source-file recording/reporting that (still) didn't understand
+  the concept of EQL-SPECIALIZER metaobjects.
+- ObjC bridge and ObjC examples
+  The ObjC bridge provides a few new mechanisms for defining ObjC
+  methods, for calling ObjC "generic functions" (e.g., message sending),
+  and for dealing with frequently-used record types and with differences
+  between 32-bit and (forthcoming) 64-bit ObjC/Cocoa implementations.
+  
+  A lot of macros/functions/other things that really should have been
+  exported from some package for the last few years finally have been
+  exported from the OBJC or NS packages (and a lot of things that have
+  historically been internal to CCL are re-imported into CCL).
+
+  Cocoa (and the underlying Core Graphics libraries) have historically
+  used 32-bit floats and 32-bit integers in data structures that describe
+  geometry, font sizes and metrics, and elsewhere.  64-bit Cocoa will
+  use 64-bit floats and 64-bit integers in many cases.
+
+  The bridge defines the type NS:CGFLOAT as the lisp type of the 
+  preferred float type on the platform, and the constant NS:+CGFLOAT+.
+  On DarwinPPC32, the foreign types :cgfloat, :<NSUI>nteger, and
+  :<NSI>nteger are defined by the bridge (as 32-bit float, 32-bit
+  unsigned integer, and 32-bit signed integer, respectively.); these 
+  types are defined (as 64-bit variants) in the 64-bit interfaces.
+
+  All ObjC classes are properly named, either with a name exported
+  from the NS package (in the case of a predefined class declared in
+  the interface files) or with the name provided in the DEFCLASS
+  form (with :METACLASS NS:+NS-OBJECT) which defines the class from
+  lisp.  The class's lisp name is now proclaimed to be a "static"
+  variable (as if by DEFSTATIC, as described above) and given the
+  class object as its value.  In other words:
+
+(send (find-class 'ns:ns-application) 'shared-application)
+
+  and
+
+(send ns:ns-application 'shared-application)
+
+  are equivalent.  (Since it's not legal to bind a "static" variable,
+  it may be necessary to rename some things so that unrelated
+  variables whose names coincidentally conflict with ObjC class names
+  don't do so.)
+
+- A new reader macro - #/ - reads a sequence of "constituent" characters
+  (including colons) from the stream on which it appears and interns
+  that sequence - with case preserved and colons intact - in a new package
+  whose name is NEXTSTEP-FUNCTIONS, exporting the symbol from that package.
+  This means that the act of reading "#/alloc" returns the the symbol
+  NEXTSTEP-FUNCTIONS:|alloc|, and the act of reading "#/initWithFrame:"
+  returns the symbol NEXTSTEP-FUNCTIONS:|initWithFrame:|.  The intent
+  is that the reader macro can be used to construct symbols whose names
+  match ObjC message names; the reader macro tries to do some sanity
+  checks (such as insisting that a name that contains at least one
+  colon ends in a colon), but isn't totally rigourous about enforcing
+  ObjC message name conventions.
+
+  A symbol read using this macro can be used as an operand in
+  most places where an ObjC message name can be used, such as
+  in the (@SELECTOR ...) construct (which is now OBJC:@SELECTOR, 
+  btw.)
+
+  Marco Baringer proposed the idea of using a reader macro to
+  construct lisp symbols which matched ObjC message names.
+
+- The act of interning a new symbol in the NEXTSTEP-FUNCTIONS
+  package triggers an interface database lookup of Objc methods
+  with the corresponding message name.  If any such information
+  is found, a special type of dispatching function is created
+  and initialized and the weird-looking symbol is given that
+  dispatching function as its function definition.
+
+  The dispatching knows how to call declared ObjC methods defined on
+  the message.  In many cases, all methods have the same foreign type
+  signature, and the dispatching function merely passes any arguments
+  that it receives to a function that does an ObjC message send with
+  the indicated foreign argument and return types.  In other cases,
+  where different ObjC messages have different type signatures, the
+  dispatching function tries to choose a function that handles the
+  right type signature based on the class of the dispatching function's
+  first argument.
+
+  If new information about ObjC methods is introduced (e.g., by
+  using additional interface files or as ObjC methods are defined
+  from lisp), the dispatch function is reinitialized to recognize
+  newly-introduced foreign type signatures.
+
+  The argument and result coercion that the bridge has tradionally
+  supported is supported by the new mechanism (e.g., :<BOOL> arguments
+  can be specified as lisp booleans and :<BOOL> results are returned
+  as lisp boolean values, and an argument value of NIL is coerced to
+  a null pointer if the corresponding argument type is :ID.
+
+  Some ObjC methods accept variable numbers of arguments; the
+  foreign types of non-required arguments are determined by the
+  lisp types of those arguments (e.g., integers are passed as
+  integers, floats as floats, pointers as pointers, record types
+  by reference.)
+
+  Some examples:
+
+;;; #/alloc is a known message.
+? #'#/alloc
+#<OBJC-DISPATCH-FUNCTION NEXTSTEP-FUNCTIONS:|alloc| #x300040E94EBF>
+;;; Sadly, #/foo is not ...
+? #'#/foo
+> Error: Undefined function: NEXTSTEP-FUNCTIONS:|foo|
+
+;;; We can send an "init" message to a newly-allocated instance of
+;;; "NSObject" by:
+
+(send (send ns:ns-object 'alloc) 'init)
+
+;;; or by
+
+(#/init (#/alloc ns:ns-object))
+
+  ObjC methods that "return" structures return them as gcable pointers
+  when called via dispatch functions.  E.g., if "my-window" is an
+  NS:NS-WINDOW instance, then
+
+(#/frame my-window)
+
+  will return a gcable pointer to a structure that describes that window's
+  frame rectangle.  (The good news is that there's no need to use SLET
+  or special structure-returning message send syntax; the bad news is
+  that #_malloc, #_free, and the GC are all involved in the creation
+  and eventual destruction of structure-typed return values.  Unless
+  and until those factors negatively affect performance, the advantages
+  seem to outweigh the disadvantages.)
+
+- Since foreign pointers are now (sometimes, somewhat) typed, it's
+  possible to treat pointers to some foreign types as "instances of
+  built-in classes."  Specifically, a pointer to an :<NSR>ect is
+  recognized as an instance of the built-in class NS:NS-RECT, a
+  pointer to an <NSS>ize is treated as an instance of NS:NS-SIZE,
+  <NSP>oint is recognized as NS:NS-POINT, and <NSR>ange maps to
+  NS:NS-RANGE.  (There are a few other more obscure structure
+  types that get this treatment, and with a little more work the
+  mechanism could be made extensible.)
+
+  For each of these built-in classes:
+
+  - a PRINT-OBJECT method is defined
+
+  - a foreign type name derived from the class name (e.g., :NS-RECT
+    for NS:NS-RECT) is made an alias for the corresponding type
+    (so it's possible to say (RLET ((R :NS-RECT)) ...)).
+
+  - the class is is integrated into the type system (so that 
+    (TYPEP R 'NS:NS-RECT) is fairly efficently implemented.)
+
+  - inlined accessor and setf inverses are defined for the structure
+    type's fields.  In the case of an :<NSR>ect, the fields in question
+    are the fields of the embedded point and size, so NS:NS-RECT-X,
+    NS:NS-RECT-Y, NS:NS-RECT-WIDTH, NS-RECT-HEIGHT and SETF inverses
+    are defined.  The accessors and setter functions typecheck their
+    arguments and the setters handle coercion to the approprate type
+    of CGFLOAT where applicable.
+
+  - an initialization function is defined; (NS:INIT-NS-SIZE s w h) is
+    roughly equivalent to (SETF (NS:NS-SIZE-WIDTH s) w
+    (NS:NS-SIZE-HEIGHT s) h), but might be a little more efficient.
+
+  - a creation function is defined: (NS:NS-MAKE-POINT x y) is basically
+    equivalent to:
+    (LET ((P (MAKE-GCABLE-RECORD :NS-POINT)))
+      (NS:INIT-NS-POINT P X Y)
+      p)
+
+  - a macro is defined which (much like RLET) stack-allocates an
+    instance of the foreign record type, optionally iniitializes
+    that instance, and executes a body of code with a variable
+    bound to that instance.  E.g.
+
+    (ns:with-ns-range (r loc len)
+      (format t "~& range has location ~s, length ~s" 
+         (ns:ns-range-location r) (ns:ns-range-length r)))
+
+    which is probably not the world's most realistic example.
+
+   Note that it's possible to construct a record
+   instance that has a very short useful lifetime:
+
+   (#/initWithFrame: new-view (ns:ns-make-rect 100 100 200 200))
+
+   The rectangle above will -eventually- get reclaimed by the GC;
+   if you don't want to give the GC so much work to do, you might
+   prefer to do:
+
+   (ns:with-ns-rect (r 100 100 200 200)
+     (#/initWithFrame: new-view r))
+
+
+ - The macro OBJC:DEFMETHOD can be used to define ObjC methods.
+   It looks superficially like CL:DEFMETHOD in some respects.
+   The syntax is:
+
+   (OBC:DEFMETHOD name-and-result-type ((receiver-arg-and-class) &rest other-args) &body body)
+
+   where:
+
+   "name-and-result-type" is either an ObjC message name (use #/ !)
+   for methods that return a value of type :ID, or a list of an ObjC
+   message name and a foreign type specifier for methods with a different
+   foreign result type
+
+   "receiver-type-and-class" is a two-element list whose CAR is 
+   a variable name and whose CADR is the lisp name of an ObjC class
+   or metaclass.  The receiver variable name can be any bindable
+   lisp variable name, but SELF (in some package) might be a reasonable
+   choice.  The receiver variable is declared to be "unsettable", i.e.,
+   it is an error to try to change the value of the receiver in the
+   body of the method definition.
+
+   "other-args" are either variable names (denoting parameters of type
+   :ID) or 2-element lists whose first element is a variable name and
+    whose second element is a foreign type specifier.
+
+  For example:
+
+(objc:defmethod (#/characterAtIndex: :unichar)
+    ((self hemlock-buffer-string) (index :<NSUI>nteger))
+  ...)
+  
+  The method "characterAtIndex:", when invoked on an object of class
+  HEMLOCK-BUFFER-STRING with an additional argument of type :<NSU>integer
+  returns a value of type :unichar.)
+
+  Arguments that wind up as some non-:ID pointer type (pointers,
+  records passed by value) are represented as typed foreign pointers
+  (so the higher-level, type-checking accessors can be used on
+  arguments of type :ns-rect, :ns-pointe, etc.)
+
+  Within the body of methods defined via OBJC:DEFMETHOD, the local
+  function CL:CALL-NEXT-METHOD is defined.  It isn't quite as
+  general as CL:CALL-NEXT-METHOD is when used in a CLOS method,
+  but it has some of the same semantics.  It accepts as many arguments
+  as are present in the containing method's "other args" list and
+  invokes version of the containing method that would have been
+  invoked on instances of the receiver's class's superclass with
+  the receiver and other provided arguments.  (The idiom of passing
+  the current method's arguments to the next method is common enough
+  that the CALL-NEXT-METHOD in OBJC:DEFMETHODs should probably do
+  this if it receives no arguments.)
+
+  A method defined via OBJC:DEFMETHOD that returns a structure "by value"
+  can do so by returning a record created via MAKE-GCABLE-RECORD, by
+  returning the value returned via CALL-NEXT-METHOD, or by other similar
+  means.  Behind the scenes, there may be a pre-allocated instance of
+  the record type (used to support native structure-return conventions),
+  and any value returned by the method body will be copied to this
+  internal record instance.  Within the body of a method defined with
+  OBJC:DEFMETHOD that's declared to return a structure type, the local
+  macro OBJC:RETURNING-FOREIGN-STRUCT can be used to access the internal
+  structure:
+
+  (objc:defmethod (#/reallyTinyRectangleAtPoint: :ns-rect) 
+    ((self really-tiny-view) (where :ns-point))
+    (objc:returning-foreign-struct (r)
+      (ns:init-ns-rect r (ns:ns-point-x where) (ns:ns-point-y where)
+                          single-float-epsilon single-float-epsilon)
+      r))
+
+ - If OBJC:DEFMETHOD introduces a new ObjC message, a ... message
+   to that effect.  Sometimes, these messages are merely informative
+   (and barely informative, at that ...), but they may also indicate
+   that a message name is misspelled (or possibly missing a trailing
+   colon.)  If a method is redefined in such a way that it's type
+   signature changes, a continuable error is signaled.
+
+ - there used to be some fairly obscure reasons that led to 
+   MAKE-OBJC-INSTANCE being a bit more efficient than MAKE-INSTANCE
+   in some cases (some of the methods invoked by MAKE-INSTANCE did
+   some extra work to handle Lisp slots even if the class didn't
+   define any Lisp slots.  This work isn't done anymore, and consequently
+   there's less reason to prefer MAKE-OBJC-INSTANCE.  (MAKE-OBJC-INSTANCE
+   is still defined and exported from the OBJC:PACKAGE).
+
+ - the preferred means of loading an add-on framework and processing
+   the declarations in its interfaces has changed several times over
+   the last several months.  The currently preferred (new) way to
+   do that is via the new function OBJC:LOAD-FRAMEWORK
+
+   (OBJC:LOAD-FRAMEWORK framework-name interface-dir)
+
+   where "framework-name" is a string which names the framework and
+   "interface-dir" is a keyword that names the associated set of
+   interfaces.  OBJC:LOAD-FRAMEWORK should find and initialize the 
+   framework bundle (looking in standard framework search paths),
+   introduce new ObjC classes to CLOS, update information about
+   declared messages and their methods' type signatures, adjust
+   affected dispatch functions, and make the interfaces other
+   definitions available.  The order in which it does these
+   things isn't specified, and may change in the future.
+
+ - Most Cocoa-related examples (the demo IDE, the Rubix and Webkit
+   examples) have been rewritten to use the new bridge features.
+   (I may have missed some contributed examples; if people want
+   to convert these, that'd be great.)  It's too early to say
+   whether the new approach is better or worse than the old, but
+   I've (so far) found some of the code easier to read and maintain.
+   We might find that some things that (for instance) SEND does
+   more efficiently could and should be done via SEND (I'm thinking
+   mostly of struct-return stuff), but so far I haven't seen the
+   new stuff keel over.
+
+   The converted code looks like "lisp code with strange-looking
+   function names" at first glance, and that seems about right.
+   The function names might get to look more familiar as the
+   reader becomes more familiar with Cocoa; as someone here pointed
+   out, it's arguably good that the function names are distinctive
+   in that that helps to remind the reader that these are likely
+   lower-level functions that are less tolerant of type- and other
+   errors than the typical lisp function would be.
+
+
+
+OpenMCL 1.1-pre-070214
+- The FASL version changed (old FASL files won't work with this
+  lisp version), as did the version information which tries to
+  keep the kernel in sync with heap images.
+- There are new interface files for all platforms.  These files
+  encode some foreign type information a little differently
+  than older ones did (notably information about foreign functions 
+  that return structures or accept structure args by value.)  The
+  new .cdb files can't be used by older versions of OpenMCL; using
+  older .cdb files with this version is "allowed, but not supported
+  or recommended."
+- Almost all of the changes in functionality since the last (061231)
+  snapshots and since the CVS freeze on 070117 have to do with
+  relatively obscure issues having to do with passing structures
+  to foreign functions by value and/or returning structures from foreign
+  function calls.
+
+  These idioms are fairly rare in traditional C code (though it's
+  fairly common to pass -pointers- to structures by reference
+  and sometimes to return pointers to structures.  There are
+  a few C compiler runtime routines that perform some flavor
+  of integer division and return a two-element structure that
+  contains "quotient" and "remainder" fields, but that's typically
+  about the extent of the use of this idiom.)  The idioms are used
+  much more often in Apple's Carbon and Cooca libraries and in
+  some of the frameworks (CoreGraphics, CoreFoundation) that those
+  libraries are based on.
+
+  OpenMCL's FFI has provided some support for this in the past;
+  notably, it's provided support for (most of the) structure-returning
+  and struct-by-value conventions used on 32-bit PPC Darwin.  In these
+  conventions, a foreign function that returned a structure received
+  a pointer to an instance of that structure type as a first argument,
+  and a function that received a structure argument by value received
+  the structure's contents in 32-bit word-size integer chunks (regardless
+  of the types or sizes of the structure's fields.)  Knowledge of these
+  conventions was hardwired into various parts of the system (e.g.,
+  the interface database), so that it was not generally possible to
+  tell whether a given foreign function returned a structure type
+  (or just happened to take an extra pointer argument.)
+
+  Unfortunately, there are at least 4 other sets of conventions for
+  dealing with structure arguments/return values on the platforms
+  that OpenMCL runs on (and even the DarwinPPC32 conventions weren't
+  fully/correctly implemented.)  OpenMCL's FFI is generally pretty
+  low-level, but to the extent that it's reasonable to talk about
+  "higher level" constructs (EXTERNAL-CALL, SEND, FF-CALL, #_), those
+  higher-level constructs try to enforce uniform syntax and try
+  to hide the platform-specific details in backend-specific functions.
+
+  The impact of these changes should generally be pretty minimal.
+  In a "higher-level" construct used to call a foreign function that
+  returns a structure type, the first parameter in the call should
+  be a pointer to an instance of that structure type.
+
+  For example, if a :rect structure is defined as:
+
+  (def-foreign-type nil
+    (:struct :rect
+      (:width :int)
+      (:height :int)
+      (:x :int)  ; x coordinate of origin
+      (:y :int)))
+
+  and a foreign function named "inset_rect" takes a rect and an integer
+  delta and returns a new :rect "inset" by that delta, a call to that
+  foreign function might look like:
+
+  (rlet ((result :rect))
+    (ff-call *address-of-inset-rect* result (:struct :rect) r :int delta :(:struct rect))
+    ;; or, if "inset_rect" was declared in the interface database:
+    (#_inset_rect result r delta))
+
+
+  A callback that returns a :rect likewise should accept a pointer
+  to an instance of the :rect type as a first (unqualified) argument
+  and explicitly declare that it returns a (:STRUCT :RECT).
+
+  (defcallback *address-of-inset-rect (result (:struct :rect) r :int delta (:struct :rect))
+    (setf (pref result :rect.x) (+ (pref r :rect.x) delta)
+          (pref result :rect.y) (+ (pref r :rect.y) delta)
+          (pref result :rect.width) (- (pref r :rect.width) (* 2 delta))
+          (pref result :rect.height) (- (pref r :rect.height) (* 2 delta))))
+
+  Note that this is very similar to what's been (implicitly) supported
+  on DarwinPPC32; the basic difference is that the return type
+  ("(:STRUCT :RECT)") is explicitly specified (or, in the case of #_,
+  specified in the interface database).  Whether the "result" pointer
+  is actually passed as an argument or not is platform-dependent (on
+  DarwinPPC64, the :rect structure would be "returned" by returning
+  4 :int values in 4 different machine registers), but the same syntax
+  can be used (and hides those details) on all platforms.
+
+  In the examples above, we said that the (presumed source) rectangle
+  was passed by value as a value of type (:struct :rect), and we let
+  the FFI deal with the details.  Historically, this parameter could
+  have been specified as a small unsigned integer N (denoting the 
+  DarwinPPC32 convention of passing the structure value a N 
+  native-word-size integer arguments.)  Again, there are several
+  different conventions for passing and receiving structure values,
+  and it's best to let the FFI decide how to follow those conventions.
+  (Some of those conventions are quite complicated, and depend on
+  the size of the structure as well as the types of its fields.)
+
+  In all cases, a callback which declares a parameter to be of a
+  structure type can treat that parameter as a pointer an instance of
+  that structure type with fields initialized by the caller (as in
+  the case of "r" in the example above.)
+
+  In the ObjC bridge, the DEFINE-OBJC-METHOD macro has always provided
+  syntax for specifiying that the method "returns" a structure. (That
+  syntax is (:struct <struct-type> <parameter-name>). That continues
+  to be supported.
+
+  Apple's ObjC runtime provides different functions (#_objc_msgSend and
+  #_objc_msgSend_stret) to handle the cases of sending messages which
+  return non-structure and structure results.  These low-level functions
+  are very sensitive to whether the structure is actually returned via
+  an "invisible" first argument or not (this is only one of a few different
+  conventions on some platforms.)  OpenMCL's ObjC bridge makes similar
+  distinctions, but uses simple, consistent rules: a message that returns
+  a structure should always be sent via SEND/STRET (or some variant of
+  SEND/STRET) and should have a first parameter of type "pointer to
+  returned structure type", regardless of whether or not that pointer
+  is actually passed to the method implementation or just used as by
+  some platform-specific code to transfer register values.)
+
+  The end result of all of this (several weeks of bootstrapping) is
+  that most things are pretty much the same, at least on DarwinPPC32;
+  only foreign function calls/callbacks that involve passing structures
+  by value or returning structures need change at all, and the changes
+  generally involve being more explicit/declarative about what's going
+  on.  These changes -do- allow these idioms to be used on other
+  (64-bit) platforms, and since they're heavily used in Apple GUI
+  libraries and since 64-bit versions of Carbon and Cocoa are announced
+  features of Leopard, it seemed appropriate to get support for this
+  stuff into the FFI on those platforms and to try to do it in a way
+  that hid the platform-dependent details.  (I didn't expect all of
+  this to take so long.)
+
+- The initial listener PROCESS now persists across SAVE-APPLICATION.
+  This means that (for instance):
+
+  ? (defvar *listener-process* (current-process))
+  *LISTENER-PROCESS*
+  ? (save-application "new.image")
+  shell> openmcl new.image
+  ? (eq (current-process) *listener-process*)
+  T
+  ;; though of course the underlying OS thread, stacks, etc are unlikely
+  ;; to be "equal" in any sense.
+
+  The current process is sometimes used to mark "ownership" of thread-private
+  hash-tables and streams.  (Even though it doesn't make much sense for
+  STREAMs to persist across SAVE-APPLICATION, it does make sense for
+  HASH-TABLEs to do so; HASH-TABLES created with the :PRIVATE T option
+  and "owned" by the initial listener process continue to be owned by
+  that the current listener process in the new image.)
+
+- All of the FFI changes above do seem to allow the Cocoa IDE example
+  to run on ppc64/x86-64 (as well as ppc32) under Leopard, and
+  hopefully that'll soon be true of applications generated via Mikel
+  Evins' Bosco system as well.  The bridge and demo code have been
+  conditionalized to support ObjC 2.0 on 64-bit systems, to avoid
+  deprecated functions and methods, and to support 64-bit Cocoa
+  changes.  Hopefully, this has been done in a way that doesn't break
+  PPC32 Cocoa under Tiger (he said, quickly rushing to the nearest
+  PPC32 Tiger machine and breathing a sigh of relief when the Cocoa
+  listener appeared ..)  64-bit Cocoa sometimes used 64-bit signed and
+  unsigned integers in place of 32-bit integers; accordingly, the
+  foreign types :<NSI>nteger and :<NSUI>nteger are defined (as 32-bit
+  signed/unsigned integers) on 32-bit platforms, and these types are
+  used in some method and type definitions.  (Those integer types are
+  predefined in Objc 2.0, and are 64 bits wide on 64-bit platforms.)
+
+  More pervasively (and a little more problematically), CoreGraphics
+  (and things built on top of it, including Cocoa) uses double-floats
+  instead of single-floats for many things on 64-bit hardware; the
+  difference is abstracted (a little) via the new CGFloat type.
+  This means that (for instance) code which initializes a constant-sized
+  NSRect on a 32-bit machines and has traditionally done so via
+  something like:
+
+  (ns-make-rect 0.0 0.0 500.0 200.0)
+
+  now needs to do something like:
+
+  (ns-make-rect (float 0.0 ccl::+cgfloat-zero+) ..)
+
+  in order to compile and run on both 32-bit and 64-bit platforms.
+
+  where ccl::+cgfloat-zero+ is defined as 1.0f0 on 32-bit platforms
+  and as 1.0d0 on 64-bit machines.  Cases involving constants won't
+  incur any runtime overhead and the occasional runtime overhead in
+  other cases -probably- isn't that great in context (compared to
+  initializing a view hierarchy ...)  but it's certainly ugly to
+  look at.  It's possible that some of this ugliness could be
+  hidden in the bridge/FFI (by making them do the necessary coercions
+  for you), but there are tradeoffs there.
+
+- The ObjC bridge has had a long-standing bug whereby a standalone
+  Cocoa application may have needed to find the interface databases
+  at runtime in order for MAKE-OBJC-INSTANCE and MAKE-INSTANCE of
+  an ObjC class to work.  (These functions needed to be able to
+  send an "init" message to the newly-allocated instance, and needed
+  to know the type signature of that init message in order to do that.)
+  The current scheme tries to avoid this by pre-compiling helper
+  functions to enable calling all known "init" message signatures.
+  (More accurately, all fixed-argument "init" message signatures.)
+  This scheme avoids the need to send messages whose argument
+  and result types are computed at runtime (via %SEND), and %SEND
+  (a) was known to be inefficient and (b) would have a lot of
+  difficulty handling all known structure return/passing conventions
+  on supported platforms.  Accordingly, %SEND has been deprecated
+  (with extreme prejudice, e.g., removed.)
+
+- a couple of little functions are defined (but their names are
+  not yet exported) on x86-64: ccl::rdtsc and ccl::rdtsc64 provide
+  access to the values returned by on-chip cycle counting instructions.
+  For instance:
+
+? (let* ((start (ccl::rdtsc)))
+    (sleep 1) 
+    (- (ccl::rdtsc) start))
+1995065244
+
+  Hmm.  Apparently, the 2.0GHz MacBook I tried that on is actually
+  a 1.995GHz MacBook.
+
+  There are all kinds of ways for rdtsc to lose (and return 
+  inaccurate or misleading results): the cycle counters for
+  each CPU core in a multi-core system aren't necessarily
+  kept in sync, and many modern systems allow CPU clock rates
+  to vary (for power-management reasons) and/or allow the CPU
+  to sleep/hibernate.  OSes seem to offer some support for
+  compensating for these effects, and it seems like ccl::rdtsc
+  and ccl::rdtsc64 can be used to obtain interesting results.
+
+  The RDTSC instruction actually returns an unsigned 64-bit
+  result; apparently, some Intel documentation claims that this
+  value will not "wrap around" to 0 at contemporary clock rates
+  for at least 10 years after the system was booted.  (If you can
+  keep an Intel system running for 9 years between reboots, you 
+  might consider telling Intel that the RDTSC counter wrapped around
+  a year early; they might give you a refund.  Or maybe not.)
+  A non-negative OpenMCL64 fixnum is limited to 60 bits; the
+  ccl::rdtsc function truncates the 64-bit counter value so
+  that it fits in a non-negative fixnum; if the 10 year limit
+  for the 64-bit value is accurate, the 60-bit value would
+  wrap around after about 223 days of uptime.
+
+  ccl::rdtsc64 returns the full 64-bit counter value, but
+  may return a bignum after 223 days of uptime.
+  
+- lots of bug fixes (not all of which involved the FFI or ObjC
+  bridge.)  
+
+  
+
+openmcl 1.1-pre-061231
+- The FASL version changed (old FASL files won't work with this
+  lisp version), as did the version information which tries to
+  keep the kernel in sync with heap images.
+  The binary incompatibility has to do with how a few pages of
+  low memory in the lisp kernel's address space are mapped and
+  used.  OpenMCL was generally assuming that these pages were
+  otherwise unused and could be used to map a small static data
+  area from the heap image file; on some platforms, the dynamic
+  linker may have already allocated data in those unused pages
+  before the lisp kernel even starts to run.  Fixing this involved
+  changing the address of that small static data area slightly,
+  and this caused the addresses of some objects contained within
+  that static data area - notably NIL - to change, as well.
+- This snapshot is otherwise just a set of bug fixes/work-in-progress
+  changes.
+- Even though no supported filesystem actually supports versioned files,
+  OpenMCL now tries to retain PATHNAME-VERSION informaton for physical
+  pathnames.  (The fact that it didn't caused several ANSI test failures.)
+  This change introduced/exposed a few other bugs; I think that I've
+  caught at least the most obvious ones, but it's possible that some
+  new pathname-related bugs have been introduced.
+- The cron job that runs on clozure.com and updates the ChangeLog from
+  CVS commit info stopped running as of a system upgrade in late November.
+  The problem was fixed a couple of weeks ago, so it's once again meaningful
+  to refer to the ChangeLog for details of bug fixes.
+- FSQRT and FSQRTS instructions are "optional" on the PPC.  In practice,
+  that often meant that they are implemented on chips made by IBM and
+  not on chips made by Motorola/FreeScale.  This version of OpenMCL
+  assumes that they're implemented and emulates them if they aren't.
+- OSX 10.2 (Jaguar) and earlier versions are officially no longer
+  supported.  (I honestly don't know if things have actually worked
+  on Jaguar in a while, but some recent changes are known not to
+  work on Jaguar and the kernel now inists on at least Panther on
+  startup.
+OpenMCL 1.1-pre-061205
+- This release is intended to package up the bug fixes since
+  the 061110 tarballs.  There aren't too many changes in 
+  functionality or any deep architectural changes since 061110, 
+  and it should be easy to bootstrap from current sources with 
+  061110 images.
+  (It'd still be a good idea to recompile your code with 
+  up-to-date images, whether you download those images or
+  build them yourself from CVS.)
+- The one (barely) notable change in functionality has to do
+  with how the lisp sets up pathname translations for the
+  "ccl" logical host when the "CCL_DEFAULT_DIRECTORY" environment
+  variable isn't set (e.g., when a shell script isn't used to
+  invoke the lisp.)  Previous versions just used the current
+  directory; this version tries to use the directory containing
+  the current heap image.  The new scheme might get fooled by
+  symbolic links (either following them or not following them
+  could be wrong), but it's more likely to work for people
+  who don't read or understand the discussion of the shell script
+  in the documentation.
+- All (knock wood) bugs that have been reported since the 061110
+  images were released should be fixed.  Well, almost all.  The
+  fixes include:
+
+  - a typo (wrong register) in the "generic" version of the
+    code which implements (SETF AREF) on 2-dimensional arrays
+    on x86-64
+  - incorrect bounds checking on vector references on x86-64,
+    which caused some invalid indices to be treated as valid
+    (usually leading to a segfault).  IIRC, the invalid indices
+    that were erroneously accepted were fixnums whose absolute
+    value was > (expt 2 56).  (More or less.).
+  - Missing stream methods (especially involving string streams)
+    affecting all platforms.
+  - Several bugs involving GCD, some of which were specific to
+    64-bit platforms and some of which affected all platforms.
+    (These bugs sometimes affected results returned by #'/,
+    LCM, and other funtions.)
+
+  - OpenMCL has only ever supported an ELEMENT-TYPE argument of
+   ([signed,unsigned]-byte 8|16|32|64) on binary file streams (with
+   64-bit types supported only on 64-bit platforms.)  It has not
+   previously tried to upgrade a supplied element-type to a supported
+   one (it does now) and any errors that resulted from supplying an
+   element-type that was not supported (and could not be upgraded) were
+   either obscure side-effects or quiet misbehavior; an error (a
+   SIMPLE-ERROR complaining about the unsupported element type) is now
+   signaled as soon as attempts to upgrade to a supported element type
+   fail.  I believe that the current behavior is both compliant and
+   reasonable; it's probably better to discuss that issue on 
+   openmcl-devel than to do so here.
+
+
+OpenMCL 1.1-pre-061110
+- The FASL version changed (old FASL files won't work with this
+  lisp version), as did the version information which tries to
+  keep the kernel in sync with heap images.
+- Several bug fixes (see ChangeLog), and modest-to-moderate
+  performance improvements.  Notably, AREF and (SETF AREF)
+  of 2- and 3-dimensional arrays are open-coded in more cases
+  and are usually at least 5x faster than in previous versions.
+  If the compiler knows that the array in question is a
+  SIMPLE-ARRAY of appropiate dimensionality and knows the
+  array's element-type, the speedup can be much greater.
+  There are certainly opportunities for further improvements
+  here, both in breadth (handling more cases) and depth
+  (eliminating some type-and-bounds checking in safe code,
+  doing parts of index calculations at compile-time when
+  bounds and indices are constants ...), but things are
+  generally improved.
+- QUIT and SAVE-APPLICATION work a little differently; in
+  particular, SAVE-APPLICATION sometimes runs after #_exit
+  is called (via the #_atexit mechanism).
+  The motivation for this change has to do with how some
+  environments (Cocoa, to name one) conflate the ideas of
+  "shutting down the GUI" with "exiting the application".
+  Previous versions of OpenMCL tried to work around this
+  by overriding some internal Cocoa methods; that approach
+  was never particularly attractive and (predictably) it'll
+  break in future OSX releases.
+  The new scheme (which involves letting code run after #_exit
+  has been called) certainly offers other ways to lose; so
+  far, I haven't seen evidence of such lossage.
+- For historical reasons (forgotten historical reasons, in fact)
+  the PPC versions of OpenMCL run with floating-point underflow
+  exceptions disabled (the x86-64 versions enable these exceptions
+  by default.)  This should change soon (as soon as I remember
+  to change it ...); it's unlikely that this will affect much
+  user code, but it's possible that it'll do so.
+OpenMCL 1.1-pre-061024
+- The FASL version changed (old FASL files won't work with this
+  lisp version), as did the version information which tries to
+  keep the kernel in sync with heap images.
+- Linux users: it's possible (depending on the distribution that
+  you use) that the lisp kernel will claim to depend on newer
+  versions of some shared libraries than the versions that you
+  have installed.  This is mostly just an artifact of the GNU
+  linker, which adds version information to dependent library
+  references even though no strong dependency exists.  If you
+  run into this, you should be able to simply cd to the appropriate
+  build directory under ccl/lisp-kernel and do a "make".
+- There's now a port of OpenMCL to FreeBSD/amd64; it claims to be
+  of beta quality.  (The problems that made it too unstable
+  to release as of a few months ago have been fixed;  I stil run
+  into occasional FreeBSD-specific issues, and some such issues
+  may remain.)
+- The Darwin X8664 port is a bit more stable (no longer generates
+  obscure "Trace/BKPT trap" exits or spurious-looking FP exceptions.)
+  I'd never want to pass up a chance to speak ill of Mach, but both
+  of these bugs seemed to be OpenMCL problems rather than Mach kernel
+  problems, as I'd previously more-or-less assumed.
+- I generally don't use SLIME with OpenMCL, but limited testing
+  with the 2006-04-20 verson of SLIME seems to indicate that no
+  changes to SLIME are necessary to work with this version.
+- CHAR-CODE-LIMIT is now #x110000, which means that all Unicode
+  characters can be directly represented.  There is one CHARACTER
+  type (all CHARACTERs are BASE-CHARs) and one string type (all
+  STRINGs are BASE-STRINGs.)  This change (and some other changes
+  in the compiler and runtime) made the heap images a few MB larger
+  than in previous versions.
+- As of Unicode 5.0, only about 100,000 of 1114112./#x110000 CHAR-CODEs
+  are actually defined; the function CODE-CHAR knows that certain
+  ranges of code values (notably #xd800-#xddff) will never be valid
+  character codes and will return NIL for arguments in that range,
+  but may return a non-NIL value (an undefined/non-standard CHARACTER
+  object) for other unassigned code values.
+- The :EXTERNAL-FORMAT argument to OPEN/LOAD/COMPILE-FILE has been
+  extended to allow the stream's character encoding scheme (as well
+  as line-termination conventions) to be specified; see more
+  details below.  MAKE-SOCKET has been extended to allow an
+  :EXTERNAL-FORMAT argument with similar semantics.
+- Strings of the form "u+xxxx" - where "x" is a sequence of one
+  or more hex digits- can be used as as character names to denote
+  the character whose code is the value of the string of hex digits. 
+  (The +  character is actually optional, so  #\u+0020, #\U0020, and
+  #\U+20 all refer to the #\Space character.)  Characters with codes
+  in the range #xa0-#x7ff (IIRC) also have symbolic names (the
+  names from the Unicode standard with spaces replaced with underscores),
+  so #\Greek_Capital_Letter_Epsilon can be used to refer to the character
+  whose CHAR-CODE is #x395.
+- The line-termination convention popularized with the CP/M operating
+  system (and used in its descendants) - e.g., CRLF - is now supported,
+  as is the use of Unicode #\Line_Separator (#\u+2028).
+- About 15-20 character encoding schemes are defined (so far); these
+  include UTF-8/16/32 and the big-endian/little-endian variants of
+  the latter two and ISO-8859-* 8-bit encodings.  (There is not
+  yet any support for traditional (non-Unicode) ways of externally
+  encoding characters used in Asian languages, support for legacy
+  MacOS encodings, legacy Windows/DOS/IBM encodings, ...)  It's hoped
+  that the existing infrastructure will handle most (if not all) of
+  what's missing; that may not be the case for "stateful" encodings
+  (where the way that a given character is encoded/decoded depend
+  on context, like the value of the preceding/following character.)
+- There isn't yet any support for Unicode-aware collation (CHAR>
+  and related CL functions just compare character codes, which
+  can give meaningless results for non-STANDARD-CHARs), case-inversion,
+  or normalization/denormalization.  There's generally good support
+  for this sort of thing in OS-provided libraries (e.g., CoreFoundation
+  on MacOSX), and it's not yet clear whether it'd be best to duplicate
+  that in lisp or leverage library support.
+- Unicode-aware FFI functions and macros are still in a sort of
+  embryonic state if they're there at all; things like WITH-CSTRs
+  continue to exist (and continue to assume an 8-bit character
+  encoding.)
+- Characters that can't be represented in a fixed-width 8-bit
+  character encoding are replaced with #\Sub (= (code-char 26) =
+  ^Z) on output, so if you do something like:
+
+? (format t "~a" #\u+20a0)
+
+  you might see a #\Sub character (however that's displayed on
+  the terminal device/Emacs buffer) or a Euro currency sign or
+  practically anything else (depending on how lisp is configured
+  to encode output to *TERMINAL-IO* and on how the terminal/Emacs
+  is configured to decode its input.
+
+  On output to streams with character encodings that can encode
+  the full range of Unicode - and on input from any stream -
+  "unencodable characters" are represented using the Unicode
+  #\Replacement_Character (= #\U+fffd); the presence of such a
+  character usually indicates that something got lost in translation
+  (data wasn't encoded properly or there was a bug in the decoding
+  process.)
+- Streams encoded in schemes which use more than one octet per code unit
+  (UTF-16, UTF-32, ...) and whose endianness is not explicit will be 
+  written with a leading byte-order-mark character on (new) output and
+  will expect a BOM on input; if a BOM is missing from input data,
+  that data will be assumed to have been serialized in big-endian order.
+  Streams encoded in variants of these schemes whose endianness is
+  explicit (UTF-16BE, UCS-4LE, ...) will not have byte-order-marks written
+  on output or expected on input.  (UTF-8 streams might also contain
+  encoded byte-order-marks; even though UTF-8 uses a single octet per
+  code unit - and possibly more than one code unit per character - this
+  convention is sometimes used to advertise that the stream is UTF-8-
+  encoded.  The current implementation doesn't skip over/ignore leading
+  BOMs on UTF8-encoded input, but it probably should.)
+
+  If the preceding paragraph made little sense, a shorter version is
+  that sometimes the endianness of encoded data matters and there
+  are conventions for expressing the endianness of encoded data; I
+  think that OpenMCL gets it mostly right, but (even if that's true)
+  the real world may be messier.
+- By default, OpenMCL uses ISO-8859-1 encoding for *TERMINAL-IO*
+  and for all streams whose EXTERNAL-FORMAT isn't explicitly specified.
+  (ISO-8859-1 just covers the first 256 Unicode code points, where
+  the first 128 code points are equivalent to US-ASCII.)  That should
+  be pretty much equivalent to what previous versions (that only
+  supported 8-bit characters) did, but it may not be optimal for 
+  users working in a particular locale.  The default for *TERMINAL-IO*
+  can be set via a command-line argument (see below) and this setting
+  persists across calls to SAVE-APPLICATION, but it's not clear that
+  there's a good way of setting it automatically (e.g., by checking
+  the POSIX "locale" settings on startup.)  Thing like POSIX locales
+  aren't always set correctly (even if they're set correctly for
+  the shell/terminal, they may not be set correctly when running
+  under Emacs ...) and in general, *TERMINAL-IO*'s notion of the
+  character encoding it's using and the "terminal device"/Emacs subprocess's
+  notion need to agree (and fonts need to contain glyphs for the
+  right set of characters) in order for everything to "work".  Using
+  ISO-8859-1 as the default seemed to increase the likelyhood that
+  most things would work even if things aren't quite set up ideally
+  (since no character translation occurs for 8-bit characters in
+  ISO-8859-1.)
+- In non-Unicode-related news: the rewrite of OpenMCL's stream code
+  that was started a few months ago should now be complete (no more
+  "missing method for BASIC-STREAM" errors, or at least there shouldn't
+  be any.)
+- I haven't done anything with the Cocoa bridge/demos lately, besides
+  a little bit of smoke-testing.
+
+Some implementation/usage details:
+
+Character encodings.
+
+CHARACTER-ENCODINGs are objects (structures) that're named by keywords
+(:ISO-8859-1, :UTF-8, etc.).  The structures contain attributes of
+the encoding and functions used to encode/decode external data, but
+unless you're trying to define or debug an encoding there's little
+reason to know much about the CHARACTER-ENCODING objects and it's
+generally desirable (and sometimes necessary) to refer to the encoding
+via its name.
+
+Most encodings have "aliases"; the encoding named :ISO-8859-1 can
+also be referred to by the names :LATIN1 and :IBM819, among others.
+Where possible, the keywordized name of an encoding is equivalent
+to the preferred MIME charset name (and the aliases are all registered
+IANA charset names.)
+
+NIL is an alias for the :ISO-8859-1 encoding; it's treated a little
+specially by the I/O system.
+
+The function CCL:DESCRIBE-CHARACTER-ENCODINGS will write descriptions
+of all defined character encodings to *terminal-io*; these descriptions
+include the names of the encoding's aliases and a doc string which
+briefly describes each encoding's properties and intended use.
+
+Line-termination conventions.
+
+As noted in the <=1.0 documentation, the keywords :UNIX, :MACOS, and
+:INFERRED can be used to denote a stream's line-termination conventions.
+(:INFERRED is only useful for FILE-STREAMs that're open for :INPUT or
+:IO.)  In this release, the keyword :CR can also be used to indicate
+that a stream uses #\Return characters for line-termination (equivalent
+to :MACOS), the keyword :UNICODE denotes that the stream uses Unicode
+#\Line_Separator characters to terminate lines, and the keywords :CRLF,
+:CP/M, :MSDOS, :DOS, and :WINDOWS all indicate that lines are terminated
+via a #\Return #\Linefeed sequence.
+
+In some contexts (when specifying EXTERNAL-FORMATs), the keyword :DEFAULT
+can also be used; in this case, it's equivalent to specifying the value
+of the variable CCL:*DEFAULT-LINE-TERMINATION*.  The initial value of
+this variable is :UNIX.
+
+Note that the set of keywords used to denote CHARACTER-ENCODINGs and
+the set of keywords used to denote line-termination conventions is
+disjoint: a keyword denotes at most a character encoding or a line
+termination convention, but never both.
+
+External-formats.
+
+EXTERNAL-FORMATs are also objects (structures) with two read-only
+fields that can be accessed via the functions EXTERNAL-FORMAT-LINE-TERMINATION
+and EXTERNAL-FORMAT-CHARACTER-ENCODING; the values of these fields are
+line-termination-convention-names and character-encoding names as described
+above.
+
+An EXTERNAL-FORMAT object via the function MAKE-EXTERNAL-FORMAT:
+
+MAKE-EXTERNAL-FORMAT &key domain character-encoding line-termination
+
+(Despite the function's name, it doesn't necessarily create a new,
+unique EXTERNAL-FORMAT object: two calls to MAKE-EXTERNAL-FORMAT
+with the same arguments made in the same dynamic environment will
+return the same (eq) object.)
+
+Both the :LINE-TERMINATION and :CHARACTER-ENCODING arguments default
+to :DEFAULT; if :LINE-TERMINATION is specified as or defaults to
+:DEFAULT, the value of CCL:*DEFAULT-LINE-TERMINATION* is used to
+provide a concrete value. 
+
+When the :CHARACTER-ENCODING argument is specifed as/defaults to
+:DEFAULT, the concrete character encoding name that's actually used
+depends on the value of the :DOMAIN argument to MAKE-EXTERNAL-FORMAT.
+The :DOMAIN-ARGUMENT's value can be practically anything; when it's
+the keyword :FILE and the :CHARACTER-ENCODING argument's value is
+:DEFAULT, the concrete character encoding name that's used will be
+the value of the variable CCL:*DEFAULT-FILE-CHARACTER-ENCODING*; the
+initial value of this variable is NIL (which is an alias for :ISO-8859-1).
+If the value of the :DOMAIN argument is :SOCKET and the :CHARACTER-ENCODING
+argument's value is :DEFAULT, the value of 
+CCL:*DEFAULT-SOCKET-CHARACTER-ENCODING* is used as a concrete character
+encoding name.  The initial value of CCL:*DEFAULT-SOCKET-CHARACTER-ENCODING*
+is NIL, again denoting the :ISO-8859-1 encoding.
+If the value of the :DOMAIN argument is anything else, :ISO-8859-1 is
+also used (but there's no way to override this.)  
+
+The result of a call to MAKE-EXTERNAL-FORMAT can be used as the value
+of the :EXTERNAL-FORMAT argument to OPEN, LOAD, COMPILE-FILE, and
+MAKE-SOCKET; it's also possible to use a few shorthand constructs
+in these contexts:
+
+* if ARG is unspecified or specified as :DEFAULT, the value of the
+  variable CCL:*DEFAULT-EXTERNAL-FORMAT* is used.  Since the value
+  of this variable has historically been used to name a default
+  line-termination convention, this case effectively falls into
+  the next one:
+* if ARG is a keyword which names a concrete line-termination convention,
+  an EXTERNAL-FORMAT equivalent to the result of calling
+  (MAKE-EXTERNAL-FORMAT :line-termination ARG)
+   will be used
+* if ARG is a keyword which names a character encoding, an EXTERNAL-FORMAT
+  equvalent to the result of calling 
+  (MAKE-EXTERNAL-FORMAT :character-encoding ARG)
+  will be used
+* if ARG is a list, the result of (APPLY #'MAKE-EXTERNAL-FORMAT ARG)
+  will be used
+
+(When MAKE-EXTERNAL-FORMAT is called to create an EXTERNAL-FORMAT
+object from one of these shorthand designators, the value of the
+:DOMAIN keyword argument is :FILE for OPEN,LOAD, and COMPILE-FILE
+and :SOCKET for MAKE-SOCKET.)
+
+STREAM-EXTERNAL-FORMAT.
+The CL function STREAM-EXTERNAL-FORMAT - which is portably defined
+on FILE-STREAMs - can be applied to any open stream in this release
+and will return an EXTERNAL-FORMAT object when applied to an open
+CHARACTER-STREAM. For open CHARACTER-STREAMs (other than STRING-STREAMs),
+SETF can be used with STREAM-EXTERNAL-FORMAT to change the stream's
+character encoding, line-termination, or both.
+
+If a "shorthand" external-format designator is used in a call to
+(SETF STREAM-EXTERNAL-FORMAT), the "domain" used to construct an
+EXTERNAL-FORMAT is derived from the class of the stream in the
+obvious way (:FILE for FILE-STREAMs, :SOCKET for ... well, for
+sockets ...)
+
+Note that the effect or doing something like:
+
+(let* ((s (open "foo" ... :external-format :utf-8)))
+  ...
+  (unread-char ch s)
+  (eetf (stream-external-format s) :us-ascii)
+  (read-char s))
+
+might or might not be what was intended.  The current behavior is
+that the call to READ-CHAR will return the previously unread character
+CH, which might surprise any code which assumes that the READ-CHAR
+will return something encodable in 7 or 8 bits.  Since functions
+like READ may call UNREAD-CHAR "behind your back", it may or may
+not be obvious that this has even occurred; the best approach to
+dealing with this issue might be to avoid using READ or explicit
+calls to UNREAD-CHAR when processing content encoded in multiple
+external formats.
+
+There's a similar issue with "bivalent" streams (sockets) which
+can do both character and binary I/O with an :ELEMENT-TYPE of
+(UNSIGNED-BYTE 8).  Historically, the sequence:
+
+   (unread-char ch s)
+   (read-byte s)
+
+caused the READ-BYTE to return (CHAR-CODE CH); that made sense
+when everything was implicitly encoded as :ISO-8859-1, but may not
+make any sense anymore.  (The only thing that seems to make sense
+in that case is to clear the unread character and read the next
+octet; that's implemented in some cases but I don't think that
+things are always handled consistently.)
+
+Command-line argument for specifying the character encoding to
+be used for *TERMINAL-IO*.
+
+Shortly after a saved lisp image starts up, it creates the standard
+CL streams (like *STANDARD-OUTPUT*, *TERMINAL-IO*, *QUERY-IO*, etc.);
+most of these streams are usually SYNONYM-STREAMS which reference
+the TWO-WAY-STREAM *TERMINAL-IO*, which is itself comprised of
+a pair of CHARACTER-STREAMs.  The character encoding used for
+any CHARACTER-STREAMs created during this process is the one
+named by the value of the variable CCL:*TERMINAL-CHARACTER-ENCODING-NAME*;
+this value is initially NIL.
+
+The -K or --terminal-encoding command-line argument can be used to
+set the value of this variable (the argument is processed before the
+standard streams are created.)  The string which is the value of
+the -K/--terminal-encoding argument is uppercased and interned in
+the KEYWORD package; if an encoding named by that keyword exists,
+CCL:*TERMINAL-CHARACTER-ENCODING-NAME* is set to the name of that
+encoding.  For example:
+
+shell> openmcl -K utf-8
+
+will have the effect of making the standard CL streams use :UTF-8
+as their character encoding.
+
+(It's probably possible - but a bit awkward - to use (SETF EXTERNAL-FORMAT)
+from one's init file or --eval arguments or similar to change existing
+streams' character encodings; the hard/awkward parts of doing so include
+the difficulty of determining which standard streams are "real" character
+streams and which are aliases/composite streams.)
+
+OpenMCL 1.1-pre-069826
+- There's an (alpha-quality, maybe) port to x86-64 Darwin (e.g., the
+  Mac Pro.)  Some known problems include:
+  
+  * infrequently (but not infrequently enough) the lisp dies on
+    startup with a spurious "Trace/BKPT trap" error message.  This
+    seems to be timing-dependent and (very generally) seems to
+    involve the Mach exception thread not recognizing an exception
+    used to effect exception return.  Sometimes, this shows up
+    as a (:SIGNALED 5) error when REBUILD-CCL runs the lisp to
+    create a new image.
+
+  * some math library primitives (#_asin, for one) generate
+    spurious incidental FP exceptions that have nothing to
+    do with the validity of the arguments or result.  To work around
+    this, the lisp ignores FP exceptions which might have occurred
+    during a call into the math library; that means that it doesn't
+    detect -real- FP exceptions when they're signaled.  (This bug
+    only affects things that call into the system math library;
+    lisp arithmetic operations that're done inline are not affected.)
+
+  * The version of OSX/Darwin that shipped with the Mac Pro is missing
+    some functionality that from OpenMCL's point of view is highly
+    desirable (namely, the ability to keep application-level thread-
+    specific data in a per-thread block of memory addressed by an
+    otherwise unused segment register.)  To get things working (as
+    well as they are), the lisp "shares" the segment register that
+    the pthreads library uses to access thread data.  This scheme
+    isn't intended to be long-lived (and negatively affects
+    performance of things like foreign-function calls, callbacks,
+    and exception handling).
+ 
+  * The .cdb files (libc only for Tiger) in ccl:darwin-x86-headers64;
+    were cross-developed on a Linux x86-64 system, since Apple
+    has not yet released the sources to their x86-64 enabled gcc.
+
+- On all platforms, stream code has been rewritten and often offers
+  better (sometimes substantially better) performance.  OPEN and
+  MAKE-SOCKET have each been extended to take additional keyword
+  arguments.
+
+  :SHARING, which can have the values :PRIVATE (the default), :LOCK,
+  or :EXTERNAL (NIL is also accepted as synonym for :EXTERNAL)
+
+   :PRIVATE specifies that the stream can only be accessed by
+   the thread that created it.  (There was some discussion on openmcl-devel
+   about the idea of "transferring ownership" of a stream; this has
+   not yet been implemented.)  Attempts to do I/O on a stream with
+   :PRIVATE sharing from a thread other than the stream's owner yield
+   an error.
+
+   :LOCK specifies that all access to the stream require the calling
+   thread to obtain a lock; there are separate "read" and "write"
+   locks for IO streams (so it's possible for one thread to read
+   from such a stream while another thread writes to it, for instance.)
+   :LOCK was the implicit default for all streams prior to this change.
+   (See below - under the discussion of the AUTO-FLUSH mechanism -
+   for a discussion of one of the implications of this change that
+   affects SLIME users.)
+
+   :EXTERNAL (or NIL) specifies that I/O primitives enforce no
+   access protocol.  This may be appropriate for some types of application
+   which can control stream access via application-level protocols.  Note
+   that since even the act of reading from a stream changes its internal
+   state (and simultaneous access from multiple threads can therefore
+   lead to corruption of that state), some care must be taken in the
+   design of such protocols.
+
+  The :BASIC keyword argument influences whether or not the stream
+  will be an instance of the class FUNDAMENTAL-STREAM (the superclass
+  from which all Gray stream classes inherit) or a subclass of the
+  built-in class CCL::BASIC-STREAM.  The default value of :BASIC
+  is T and this has effect for FILE-STREAMs created via OPEN;
+  SOCKETs are still always implemented as FUNDAMENTAL (Gray) streams,
+  though this should change soon.
+
+   The tradeoff between FUNDAMENTAL and BASIC streams is entirely
+   between flexibility and (potential or actual) performance.  I/O
+   primitives can recognize BASIC-STREAMs and exploit knowledge of
+   implementation details; FUNDAMENTAL stream classes can be
+   subclassed in a semi-standard way (the Gray streams protocol.)
+
+   For existing stream classes (FILE-STREAMs, SOCKETs, and the
+   internal CCL::FD-STREAM classes used to implement file streams
+   and sockets), a lot of code can be shared between the
+   FUNDAMENTAL and BASIC implementations.  The biggest difference
+   should be that that code can be reached from I/O primitives
+   like READ-CHAR without going through some steps that're there
+   to support generality and extensibility, and skipping those
+   steps when that support isn't needed can improve I/O performance.
+
+   Gray stream methods (STREAM-READ-CHAR) should work on
+   appropriate BASIC-STREAMs.  (There may still be cases where
+   such methods are undefined; such cases should be considered
+   bugs.)  It is not guaranteed that Gray stream methods would
+   ever be called by I/O primitives to read a character from
+   a BASIC-STREAM (though there are still cases where this happens.)
+
+   A simple loop reading 2M characters from a text file runs about
+   10X faster when the file is opened the new defaults (:SHARING :PRIVATE
+   :BASIC T) than it had before these changes were made.  That sounds
+   good, until one realizes that the "equivalent" C loop can be about
+   10X faster still ...
+
+ - Forcing output to interactive streams.
+
+   OpenMCL has long had a (mostly undocumented) mechanism whereby
+   a mostly idle thread wakes up a few (~3) times per second and
+   calls FORCE-OUTPUT on specified OUTPUT-STREAMS; this helps to
+   ensure that streams with which a user would be expected to
+   interact (the output side of *TERMINAL-IO*, listener windows
+   in a GUI, etc.) have all buffered output flushed without
+   requiring application or I/O library code to be concerned about
+   that.
+
+   The SLIME lisp interaction mode for Emacs uses this mechanism,
+   but the changes described above interfere with SLIMEs use of
+   it:  in order to be safely accessed from multiple threads (the
+   SLIME REPL thread and the thread which does the background
+   periodic flushing of buffered output), a stream must have
+   been created with :SHARING :LOCK in effect.  This is no longer
+   the effective default; the code which does the periodic
+   output flushing ignores streams which do not use locks as an
+   access/sharing mechanism.  THIS MEANS THAT BUFFERRED OUTPUT
+   TO SLIME REPLs WILL NOT BE AUTOMATICALLY FLUSHED TO THE SCREEN.
+   A small change to SLIME's "swank-openmcl.lisp" is required
+   to restore this functionality.  First,  a brief description of
+   a couple of new primitives:
+
+   (CCL:ADD-AUTO-FLUSH-STREAM s)
+
+    Adds "s", which should be a "simple" OUTPUT-STREAM as returned
+    by OPEN or MAKE-SOCKET, to a list of streams whose buffered
+    output should be periodically flushed.  If S was not created
+    with :SHARING :LOCK in effect, the stream will have its
+    :SHARING mode changed to put :SHARING :LOCK into effect.
+
+   (CCL:REMOVE-AUTO-FLUSH-STREAM s)
+    
+    Removes S from the internal list of automatically flushed
+    streams.  Does not restore the stream's :SHARING mode, which
+    may have been changed by a previous call to ADD-AUTO-FLUSH-STREAM.
+
+ - SLIME changes
+   In slime:swank-openmcl.lisp, around line 182, the method
+
+(defmethod make-stream-interactive ((stream ccl:fundamental-output-stream))
+  (push stream ccl::*auto-flush-streams*))
+
+   should be changed to use CCL:ADD-AUTOFLUSH-STREAM if it's defined:
+
+(defmethod make-stream-interactive ((stream ccl:fundamental-output-stream))
+  (if (fboundp 'ccl::add-auto-flush-stream)
+    (ccl::add-auto-flush-stream stream)
+    (push stream ccl::*auto-flush-streams*)))
+
+   That's adequate for the moment, since sockets are still 
+   FUNDAMENTAL-STREAMs.  When that changes, some more extensive changes
+   to swank-openmcl.lisp may become necessary.
+
+- on x86-64, floating-point-underflow exceptions are now enabled
+  by default.  (They really should be on ppc as well.)  Again,
+  this affects FP operations that are done in lisp code and
+  the results of FP operations that are reported in response
+  to calls to reasonable (non-Darwin) math libraries.  This
+  can affect whether or not some "potential number"  reader 
+  tokens are representable as numbers, e.g., whether or not
+  attempts to read something like "1.0f-50" signal underflow
+  or are quietly mapped to 0.0f0.
+
+- examples: Phil (from the mailing list) has added code which 
+  supports some of the ffi examples from the documentation.
+
+- Bug fixes: see ChangeLog
+
+
+
+OpenMCL 1.1-pre-060705
+- Bug fixes again.  Some internal changes to support a FreeBSD/AMD64
+  port that's not quite ready.
+
+- :MCL is back on *features*; there seem to be too many packages out
+  there that expect it to be, and there hasn't been enough advance
+  notice of its pending removal.
+    
+OpenMCL 1.1-pre-060623
+- Mostly bug fixes (a CLOS bug that prevented the ObjC bridge from 
+  working, FIXNUM arrays weren't quite finished on PPC)
+
+- Use Tiger inferfaces (from XCode 10.4u SDK) on DarwinPPC32
+
+- Add gl, gtk2, gnome2 interfaces for x86-64.  Add a tiny
+  "gtk2-clock" example, tweak the opengl-ffi (GLUT) example
+  so that it works on x86-64.
+
+- Some changes to the ObjC bridge to support loading additional
+  frameworks; update the WebKit example to use these new features.
+
+- Still an outstanding issue where things like MAKE-OBJC-INSTANCE
+  need access to the interfaces at runtime (and can crash if they
+  aren't available.) 
+
+- Build snapshots for LinuxPPC{32,64}.
+
+OpenMCL 1.1-pre-060608
+- The FASL version changed, as did the version number which pairs
+  the lisp kernel with heap images.  Images saved with older kernels
+  can't be loaded on this one; the images/kernels in the 060608
+  snapshot tarballs should match.
+
+  Most of the ABI changes that caused these version changes were
+  x86-64 specific; some auxiliary stack pointers that had been
+  kept in MMX registers are now kept in per-thread memory. (Signal/
+  exception handlers generally need to be able to access these
+  stack pointers, but at least some versions of the Linux kernel
+  don't reliably pass correct values of the MMX registers in the
+  signal contexts passed to signal handlers.  Moral: some kinds
+  of stack-allocation and foreign-function operations may (or may not)
+  be a few cycles slower, but OpenMCL should be a bit less prone
+  to fatal segfault exceptions.)
+
+  Other than that, most changes since the 060530 snapshots are
+  bugfixes (see the ChangeLog for details).  The x86-64 port has been
+  exercised fairly heavily (if somewhat narrowly) and its welcome
+  banner now claims that it's a beta release.  I think that that's
+  probably fair, and hope that anyone who may have been reluctant to
+  test an alpha release will agree and be less reluctant.
+
+- There's still much more to be done, but some preliminary 1.1 documentation
+  is now online at:
+
+<http://newsite.openmcl.clozure.com/Doc>
+
+  Note that some relative links on "newsite" may be invalid, but the
+  internal links in the Doc directory should work.
+
+  As noted above, it still needs a lot of work; feedback, criticism,
+  and help would all be appreciated.
+
+OpenMCL 1.1-pre-060530
+
+- These release notes have gotten woefully out of date.
+
+- OpenMCL now runs on x86-64 (AMD64, Intel EM64T) systems under Linux.
+  It announces itself as an alpha release in the Welcome banner; it should
+  in fact be very nearly feature-complete (but possibly still buggy.)
+  There's a chicken-and-egg issue in that it needs more testing before
+  it can be formally released and some people may be waiting for a more
+  stable version.
+
+  The build process and most user-visible things should behave the same
+  way as on PPC; using REBUILD-CCL (described below) is generally the
+  simplest way to rebuild from sources.  A few (intentional) differences:
+ 
+  * the lisp kernel is named "lx86cl64", the default heap image is
+    named "LX86CL64" (e.g., the kernel name, case-inverted) and the
+    bootstrapping image is conventionally named "x86-boot64".
+
+  * FASL files have the extension "lx64fsl"
+
+  * the kernel build directory is "ccl/lisp-kernel/linuxx8664"
+
+  * the "openmcl64" shell script can be used to invoke the
+    lisp, as on 64-bit PPC platforms.
+
+Other changes tend to be a little more modest:
+
+- there is now a specialized FIXNUM array element type on all platforms.
+  (distinct from T or (SIGNED-BYTE <machine-word-size>)).  Access to
+  such vectors is a little cheaper than the SIGNED-BYTE case (since
+  elements are known to be fixnums) and a little easier on the GC
+  than the T case (the GC can avoid looking at their contents and
+  there are no associated EGC write-barrier issues.)
+
+- "colon" commands entered into the REPL/break loops don't need to
+  be parenthesized if the command and all operands are on the same
+  line. E.g.
+
+1> :f 0
+
+  and
+
+1> (:f 0)
+
+  are equivalent (and have the effect of examining the raw contents of
+  the 0th stack frame)
+
+- the syntax of the :B (backtrace) break-loop has changed; rather
+  than taking an optional argument which specifies whether or not
+  frame details should be shown, it now accepts keyword arguments
+  for specifying:
+   
+  :start	; unsigned integer: the index of the first frame to show
+  :count	; unsigned integer: the maximum number of frames to show
+  :detailed-p	; boolean: whether or not to show frame detail
+
+- a new break-loop command :NFRAMES returns the number of stack frames
+  accessible to backtrace.  (Both this change and the previous
+  are intended to help deal with deep recursion/stack overflow cases.)
+
+- any command-line arguments that follow a "--" pseudo-argument
+  are not processed by the lisp startup code and are stored
+  (as a list of strings) in CCL:*UNPROCESSED-COMMAND-LINE-ARGUMENTS*.
+  E.g.:
+
+shell> openmcl -- -foo 17
+[...]
+? ccl:*UNPROCESSED-COMMAND-LINE-ARGUMENTS*
+=> ("-foo" "17")
+
+OpenMCL 1.1-pre-060226
+
+- The --thread-stack-size (or -Z)  command-line argument changes the values
+  of the variables used to determine the sizes of the listener thread.
+  The values of these variables will persist accross SAVE-APPLICATION;
+  these values have no effect on the sizes of stacks in threads created
+  under explicit user control.
+
+- New functions:
+
+  (CCL:GC-VERBOSE on-full-gc &optional (on-egc on-full-gc))
+
+  Causes the GC to print (or stop printing ...) informational messages
+  on entry and exit.  The ON-FULL-GC argument controls whether or
+  not these messages are printed on ... a full GC, and the ON-EGC
+  argument (which defaults to the value of the ON-FULL-GC argument)
+  controls whether messages are printed on ephemeral GCs.
+
+  (CCL:GC-VERBOSE-P)
+
+  Returns two values (corresponding to the arguments of the last call
+  to CCL:GC-VERBOSE.)
+
+  (CCL:REBUILD-CCL &key :FULL :CLEAN :KERNEL :FORCE :RELOAD :EXIT 
+                         :RELOAD-ARGUMENTS)
+
+  Depending on the values of its arguments, recompiles lisp and/or
+  kernel sources and optionallly re-generates ("reloads") a heap
+  image.
+
+  Arguments:
+
+  clean   deletes FASL and .o files before performing other steps
+  kernel  rebuilds the lisp kernel
+  force   forces recompilation, even if binary is newer than source
+  reload  tries to rebuild a full heap image after other build steps
+  exit    quits after all other steps
+  full    equivalent to :CLEAN T :KERNEL T :RELOAD T
+  reload-arguments a list of strings, passed as additional arguments
+                   to the reload step.  E.g. '("--thread-stack-size" "128M").
+
+  Output from the :KERNEL and :RELOAD steps is ordinarily only displayed
+  if an error occurs.
+  
+
+- Changes
+
+  TRACE now prints an integer (corresponding to the level of indentation)
+  on each line of output.
+
+  Tracing callbacks is currently broken (it may be reimplemented; if so,
+  it'd be implemented somewhat differently ...)
+
+- Bugs
+
+  Several bugs involving interactions between the GC and (many) active
+  threads have been fixed; at least one such bug remains (the symptom
+  involves a recently allocated  array somehow getting trashed or GCed
+  incorrectly; the  cause has been under investigation for weeks but is 
+  still not known.)
+
+OpenMCL 1.1-pre-060125
+
+- FASL version changed; delete old FASL (.dfsl, .pfsl, .dfsl64, .pfsl64) files
+ 
+- "kernel ABI version" changed; build a new lisp kernel before trying to load/use
+   060125 images.
+
+-  Changes: (see also ChangeLog)
+
+   New variable:
+
+   CCL:*HOST-PAGE-SIZE*
+
+   Initialized on application startup to contain the MMU/OS page size in bytes.
+   This is 4K on PPC platforms (and likely on most? all? x86 platforms).
+
+   New functions:
+
+   CCL:DEFAULT-ALLOCATION-QUANTUM
+
+   Returns an integer, the value of which is used by the lisp kernel when
+   mapping heap memory from the OS.  Mapping requests are usually made in
+   multiples of this value.  
+
+   This value is read-only; currently, it's 64KB on 32-bit platforms and
+   128KB on 64-bit platforms.
+
+
+   CCL:PROCESS-ALLOCATION-QUANTUM p
+
+   Returns the (per-thread) allocation quantum of the process P.  By default,
+   this is the same value as that returned by CCL:DEFAULT-ALLOCATION-QUANTUM,
+   but lower values can be specified on a per-process basis (see below.)
+
+   This value is read-only.
+
+   CCL:CURRENT-PROCESS-ALLOCATION-QUANTUM
+
+   Equivalent to (CCL:PROCESS-ALLOCATION-QUANTUM *CURRENT-PROCESS*),
+   but can be used with SETF to change the current processes's
+   allocation quantum to a value which is between *HOST-PAGE-SIZE* and
+   (DEFAULT-ALLOCATION-QUANTUM), inclusive, and which is a power of 2.
+
+
+   Changes to existing functions:
+
+   Both PROCESS-RUN-FUNCTION and MAKE-PROCESS accept an :ALLOCATION-QUANTUM
+   &key argument, which defaults to the value returned by (DEFAULT-ALLOCATION-QUANTUM).
+   If provided, the value of the argument should should satisfy the same
+   constraints that (SETF (CURRENT-PROCESS-ALLOCATION-QUANTUM) is subject to.
+
+Discussion
+
+In general, larger per-thread allocation quanta are appropriate for programs
+where a relatively small number of threads need to allocate memory frequently
+and small per-thread quanta are appropriate for larger numbers of threads
+that are expected to do small, infrequent memory allocations.
+
+The worst-case scenarios would involve a large number of threads doing
+incidental memory allocation with large quanta (that wastes memory and may
+trigger the GC too frequently) or a small number of threads doing frequent
+memory allocation with small quanta (since such threads could be expected
+to fill up their small per-thread memory allocations quickly and frequently
+and would waste time frequently allocating more small chunks.)
+
+All of these values interact with the GC and EGC thresholds; the ability
+to exercise some control over how much per-threads memory is allocated
+at a time can help to ensure that those interactions are appropriate.
+When these mechanisms are insufficient, applications should consider the
+use of available mechanisms for adjusting GC and EGC thresholds.
+
+
+
+
+OpenMCL 1.1-pre-051027
+
+- A lot of internal changes in the way that special bindings, UNWIND-PROTECT,
+  and WITHOUT-INTERRUPTS are implemented (and in how they interact with
+  each other.
+
+  One user-visible aspect of this is that UNWIND-PROTECT cleanup forms
+  are run with interrupts disabled (the protected form is run with
+  interrupts enabled if they were enabled on entry to the UNWIND-PROTECT.)
+  This means that something like:
+
+  (unwind-protect
+      nil
+    (loop))
+
+  will loop uninterruptibly.
+
+- CCL:WITH-INTERRUPTS-ENABLED &body body executes the body with interrupts
+  enabled.  The example above could be rewritten as:
+
+  (unwind-protect
+      nil
+    (with-interrupts-enabled (loop)))
+
+  and the loop would be interruptible.
+
+  These changes introduce binary incompatibility (the FASL version changed,
+  as did an internal version number that tries to keep the kernel and
+  heap image in synch.)
+
+  Things basically work, but there may be lingering bugs (e.g., as of
+  a little while ago, QUIT didn't work because the initial process
+  was running with interrupts disabled.)
+
+- PROCESS-TERMINATION-SEMAPHORE
+  MAKE-PROCESS and PROCESS-RUN-FUNCTION accept a :TERMINATION-SEMAPHORE
+  argument; processes have a PROCESS-TERMINATION-SEMAPHORE accessor
+  method.  If the argument is specified and non-null, its value should
+  of type SEMAPHORE.
+
+  If a process dies by any means after it's been successfully enabled
+  and it has a non-null termination semaphore "at the time of its death", 
+  that semaphore will be signaled just before the underlying OS thread
+  is destroyed.
+
+  SETF can be used with PROCESS-TERMINATION-SEMAPHORE to change or
+  clear a the termination semaphore of a process.  If the target
+  process is not the current process when this happens, it's possible
+  that the process could die before the SETF takes effect; this
+  possibility must be addressed at the application level (i.e., the
+  implementation doesn't try to synchronize the calling thread and
+  the target in any way.
+
+  A simple example:
+
+  (let* ((s (make-semaphore)))
+    (process-run-function `(:name "sleepy" :termination-semaphore ,s)
+                           #'(lambda () (sleep 10)))
+    (wait-on-semaphore s))
+
+  The calling thread will wait for (roughly) 10 seconds (until the
+  "sleepy" thread has had its nap and signals its termination semaphore.)
+
+- A change that was introduced prior to 0.14.3 led to strange, usually
+  fatal crashes (usually an unhandled bus error, occasionally a cryptic
+  "can't find active area" message and a trip to the kernel debugger)
+  under Darwin.  This was caused by an attempt to use certain Mach
+  primitives to suspend and resume threads (the way that those
+  primitives were used, Mach exception messages were sometimes sent
+  twice if the first send was interrupted, and the second send occurred
+  after the exception had already been handled (because the first send
+  was recieved but not replied to ...)
+
+  1.0 backed out of this change, and used signal handling primitives
+  (instead of Mach primitives) to suspend and resume threads.  I -think-
+  that I understand the issue with the Mach primitives 
+  (#_thread_abort_safely isn't necessary and caused the duplicate
+  exception messages to be sent) and have tried to revert to using
+  the Mach thread suspension mechanisms.  (If unhandled bus errors -
+  that exit to the shell - or cryptic "can't find active area" messages
+  reappear, this experiment will be shown to be a failure.)
+
+  There are some obscure but good reasons for favoring the Mach
+  primiitves, so it'd be good to know if the problem with using them
+  has indeed been identified.
+
+  (The test case involves bad luck and bad timing: two or more
+  threads having pending exceptions at the same time and the thread
+  whose exception is handled first tries to suspend the others, typically
+  on behalf of the GC.  It was possible to run stress tests for many
+  hours in 0.14.3 without encountering the bug, and possible to
+  encounter it under seemingly light loads.)
+
+- INCF and DECF argument order and fixnum arithmetic.
+
+  Bryan fixed some ANSI test failures related to the order in which INCF
+  and DECF evaluate their args.  (One example is:
+
+  (let* ((x 3))
+    (incf x (setq x 5)))
+
+  where the correct answer is 10, not 8.)  We both found that fixing
+  some cases involving INCF caused some OpenMCL code to compile
+  incorrectly and were nervous about introducing these changes fairly
+  late in the development cycle, so we backed out of them prior to
+  the 1.0 code freeze.
+
+  The reasons for the miscompiled code have to do with how the
+  compiler interprets fixnum declarations under typical optimization
+  settings.  If A and B are both declared to be FIXNUMS, then
+  the expression
+
+  (setq a (+ a b))
+
+  will usually compile to a simple ADD instruction (with no overflow
+  checking); if A and B are fixnums, the result will be a fixnum,
+  though if an undetected overflow occurred in the addition, the
+  result might be missing a significant bit.
+
+  There was code in OpenMCL that assumed that
+
+  (incf a b)
+
+  was exactly the same as
+
+  (setq a (+ a b))
+
+  and in fact that was true under the old (incorrect) definition of
+  INCF.  The new definition introduced some temporary bindings:
+
+  (let* ((...)
+         (#:temp (+ a b))
+         (...))
+     (setq a #:temp))
+
+  In this case, the addition was allowed to generate an overflow
+  (no type declaration on #:temp), and the SETQ quietly violated
+  a type declaration (assigning a non-FIXNUM value to A), leading
+  to further problems.
+
+  So far, I found a couple of cases of this in the OpenMCL sources.
+  (FWIW, both functions were originally transliterated from C code
+  and were trying to mimic C's silent overflow behavior.)
+
+  Moral: if you have code that assumes that INCF or DECF expand
+  into simple assignments and are trying to exploit the ways that
+  those assignments interact with type declarations, you may
+  want to review those assumptions.  If you write code that has
+  side effects in the DELTA arguments of INCF or DECF rorms,
+  you'll (hopefully) be pleased to see that Bryan's changes 
+  allow these side-effects to be handled correctly (at the
+  right time.)  If you don't fall into either of these categories,
+  you probably won't notice any difference ...
+
+- 64-bit Linux support
+
+  There's a 64-bit LinuxPPC heap image and some rudimentary (libc-only)
+  64-bit Linux interfaces in the testing directory.
+
+  (Unlike 64-bit Darwin, 64-bit Linux distributions typically provide
+  64-bit versions of "all" standard libraries; I haven't gotten around
+  to building 64-bit gnome/gtk/X11/... interfaces yet, but wouldn't
+  expect there to be a problem.)
+
+  The 64-bit Linux OpenMCL seems to basically work, but ... OpenMCL
+  likes to map its kernel into low addresses (around #x5000); this
+  allows compiled lisp code to use conditional branches to "short"
+  (16-bit) absolute addresses.  Newer Linux kernels provide a
+  "vdso" shared library that's intended to simply communication
+  between the OS kernel and userspace libraries and programs; when
+  a program is mapped at "non-standard" addresses, the vdso gets
+  mapped at address 0.
+
+  I don't fully understand the imlications of this (beyond the fact that
+  indirecting through a NULL pointer will access bits and pieces
+  of the vdso instead of segfaulting.)  As far as I know, this is
+  seen as a minor bug in the Linux kernel, and I -think- that I've
+  seen kernel ChangeLog entries that indicate that the problem's been
+  fixed in the relatively recent past (and will likely start to
+  make it into Linux distributions in the near future.)
+
+  That said - and seeing a library at address 0 certainly makes me a
+  little nervous - the LinuxPPC64 port seems to work at least as
+  well as the DarwinPPC64 port does (i.e., there may be word-size
+  or other bugs lurking around or hiding in plain sight, but it's
+  not usually easy to encounter them.)
+
+- As documented (and as hasn't been true in a long time), EOF
+  from *STANDARD-INPUT* terminates the REPL when the --batch argument
+  is in effect (even if *STANDARD-INPUT* is a tty.)
+
+- QUIT does a FRESH-LINE on and FORCE-OUTPUT to the standard output
+  stream (people had reported that output wasn't always flushed
+  when --batch or --eval was used; 1.0 was better about this than
+  previous versions were, but it still wasn't reliable.)
+
+OpenMCL 1.1-pre-051028
+I had been doing development on G5s, and hadn't noticed that the
+32-bit lisp had been using a 64-bit instruction.  (I'm a little
+confused about how that could have worked; perhaps the 64-bit
+instruction gets emulated by the OS, or perhaps my model of
+whether 64-bit instructions can be executed in 32-bit mode
+is simply incorrect.)
+
+In any case, the 32-bit images produced yesterday don't run on
+G4s (or presumably G3s or older systems.)  Ooops.  New images.
+
+OpenMCL 1.1-pre-051029
+ A function used by both SET-USER-ENVIRONMENT
+and SET-DEVELOPMENT-ENVIRONMENT wasn't properly changing saved bindings
+of *PACKAGE*; the last few 1.1-pre releases have come up in the CCL
+package, as a result.  Ooops again; new images, again.
+
+
+OpenMCL 1.1-pre-051204
+Not a lot of user-visible changes, but the changes that're there
+are a little hard to bootstrap.
+Note that new kernel build directories (darwinppc, darwinppc64,
+linuxppc, linuxppc64, ...) repace the old versions that don't
+have "ppc" in their names.  CVS may not prune the old directories,
+especially if they contain files (.o, random junk).
Index: /branches/new-random/doc/release-notes-1.2.txt
===================================================================
--- /branches/new-random/doc/release-notes-1.2.txt	(revision 13309)
+++ /branches/new-random/doc/release-notes-1.2.txt	(revision 13309)
@@ -0,0 +1,215 @@
+ClozureCL 1.2
+=============
+
+Welcome to the first ClozureCL (aka OpenMCL) release in about 2.5 years!
+(There have been a lot of 1.1-prerelease snapshots in that time frame,
+and there's been a lot of development activity; hopefully, it'll be
+a little easier for people who wish to use a relatively stable version
+to do so and still make it easy for those who want to track the bleeding
+edge of development to do so.)
+
+[In the fall of 2007, Alice Hartley of Digitool announced that MCL (the
+commercial product from which OpenMCL was derived) would be opensourced.
+In order to reduce potential confusion between the new "open MCL" and
+"OpenMCL" - and to coincidentally make the primary implementation package
+and default installation directory name ("ccl") meaningful again - we
+decided to rename OpenMCL to "Clozure CL" (or "CCL").  There are still
+references to the old name in URLs, bits and pieces of the lisp itself,
+mailing lists, and elsewhere.]
+
+Obtaining Clozure CL
+--------------------
+Gzip'ed tar archives of Clozure CL 1.2  are available via anonymous FTP
+from:
+
+<ftp://clozure.com/pub/release/1.2>
+
+in files whose names are of the form
+clozurecl-1.2-[RELEASE-LEVEL-]PLATFORM.tar.gz
+
+where
+RELEASE-LEVEL may be "rcN" to indicate "release candidate N", or absent, and
+PLATFORM is one of "linuxppc", "darwinppc", "linuxx8664", "darwinx8664", or
+"freebsdx8664".  The "ppc" archives contain 32- and 64-bit binaries and
+interfaces; the x8664 archives are (still) 64-bit only.  All archives
+contain full sources and documentation, and also svn 1.4x metainformation
+(see below.)
+
+It's also possible to check out content equivalent to any of these
+archives by using an "svn" client (again, see below.).  The URL is of the
+form:
+
+http://svn.clozure.com/publicsvn/openmcl/release/1.2/PLATFORM/ccl
+
+where PLATFORM is defined as above.
+
+To check out a fresh copy of the current CCL 1.2 distribution for DarwinPPC,
+one would do something like:
+
+shell> cd some-directory-that-doesn't-have-a-ccl-subdirectory
+shell> svn co http://svn.clozure.com/publicsvn/openmcl/release/1.2/darwinppc/ccl
+
+We plan on making disk images (.dmg files) containing the Cocaa IDE and
+the full CCL distribution available in the near future.
+
+Documentation
+-------------
+
+Documentation is available online at: 
+
+<http://ccl.clozure.com/ccl-documentation.html>
+
+A recent version of the HTML documentation is also included in the
+distribution, along with the DocBook source from which it's derived.
+These release notes describe some important recent (for some value
+of "recent") changes.
+
+Bug Reporting
+-------------
+
+Please use the trac instance at 
+
+<http://trac.clozure.com/openmcl>
+
+to review existing bug reports and submit new ones.
+
+CVS out, SVN in:
+---------------
+
+Until the spring of 2007, ClozureCL used CVS for revision control;
+tar archives for the 1.0 release and 1.1 snapshots contained CVS
+metainformation, and it was generally possible to use "cvs update"
+and related commands to update an installation to the latest version.
+
+At that time, we switched to using the Subversion ("SVN") revision
+control system, but continued to mirror the main line of development
+in CVS (to the extent that this was possible, given some limitations
+of CVS.)
+
+This release is entirely SVN-based and makes use of Subversion features
+that can't be supported in CVS. Subversion clients are widely available
+for all platforms that ClozureCL runs on:
+
+ - FreeBSD and Linux users will likely find that subversion packages
+   are readily available through their distribution's package management
+   systems.
+
+ - 'svn' is preinstalled on OSX Leopard
+
+ - OSX Tiger users can install Subversion via Fink or MacPorts, or
+   look at <http://downloads.open.collab.net/binaries.html> for other
+   options.
+
+It should be possible to use GUI svn clients if you prefer.
+
+Note that the tar archives that contain ClozureCL distributions
+contain svn metainformation that assumes the use of a version 1.4 or
+later svn client; the format of some of that metainformation isn't
+understood by older clients.  If you have an older client (and can't
+install something more up-to-date), you ignore the tarballs and just
+check out the full CCL distribution (sources, binaries, interfaces
+...) via svn.
+
+Quick guide to svn:
+------------------
+shell> cd ccl           # wherever that is ...
+shell> svn update       # try to synch working copy with svn repository
+
+shell> svn revert <files> # discard local changes to <files>, recover
+                          # versions from last update.
+
+svn notes/issues
+----------------
+
+svn does a fairly good job of handling binary files, and in fact the
+CCL lisp kernel, heap image, and interface database files are maintained
+in svn.  (One benefit of this scheme is that it may be a little easier
+to distribute modified heap images that reflect changes that may be hard
+to bootstrap from source.)  Occasionally, an "svn update" operation may
+fail to replace a locally-modified copy of a binary file; when this
+happens, one way to recover is to use "svn revert" to discard local
+changes.
+
+The "Welcome ..." banner (and the string returned by
+LISP-IMPLEMENTATION-VERSION) contain the repository's revision number
+(an integer that increases whenever any file in the CCL repository
+changes) as of the time that the lisp image is built.  If there are
+locally-modified files (including re-compiled kernels or heap images)
+in the working copy, the revision number may contain a trailing "M"
+character; this isn't very significant, but might be a little mysterious.
+
+1.1 release notes
+-----------------
+All of the information contained in the file ccl/doc/release-notes-1.1.txt
+should be incorporated into the documentation; people who didn't use
+the 1.1 "snapshot" releases might find that file to be worth skimming.
+Some highlights include:
+
+ - use of Unicode internally, and support for reading and writing streams
+encoded in many commonly-used character encoding schemes.
+ - support for 64-bit x86 (amd64/x86-64) hardware (32-bit Intel support
+is under active development, but is not yet ready for public consumption.)
+ - many changes to the Cocoa Bridge, lots of enhancements to the Cocoa-based
+IDE (which runs on 32-bit DarwinPPC under Tiger and Leopard and on 64-bit
+DarwinX8664 on Leopard.
+ - lots of other changes (didn't I already write down descriptions of
+them somewhere ?
+
+More recent changes
+-------------------
+
+- The keywords :MCL and :OPENMCL-HASH-CONSING have been removed from
+*FEATURES*, and the keywords :CLOZURE-COMMON-LISP, :CCL and :CCL-1.2
+have been added.  :OPENMCL-HASH-CONSING denoted an experimental
+feature that was never used, and the presence of :MCL created some
+confusion (OpenMCL/CCL and commercial MCL have been diverging for
+about 10 years now, and many of the things that typically need read-time
+conditionalization - pathname syntax, threading, networking ... - need
+to be conditionalized differently for the two implementations.)  Code
+that has used the presence/absence of the :MCL feature to conditionalize
+for OpenMCL may need to be reviewed.
+
+The presence of :CCL-1.2 should be viewed as "features described in the
+Clozure CL 1.2 documentation are present", i.e., "this is at least version
+1.2 of CCL".
+
+There should also be a "simple" keyword denoting the OS name - :LINUX,
+:DARWIN, or :FREEBSD.
+
+- sockets support :CONNECT-TIMEOUT arguments and streams (including sockets)
+support :READ-TIMEOUT and :WRITE-TIMEOUT arguments in their creation functions
+(OPEN, MAKE-SOCKET, etc.)  An active socket connect operation that takes
+longer than the number of seconds specified in the socket's :CONNECT-TIMEOUT
+argument - or an I/O operation that takes longer than the applicable
+:READ-TIMEOUT or :WRITE-TIMEOUT's argument - will cause an error to be
+signaled.
+
+- profiling via Apple's CHUD tools (finally) works on 64-bit versions of
+CCL.  See ccl/library/chud-metering.txt for details.
+
+- profiling on x86-64 Linux - using the 'oprofile' profiler - is now 
+supported (or, more accurately, it's possible to generate symbolic 
+information that allows 'oprofile' and related tools to give meaningful
+names to lisp functions.)  See ccl/library/oprofile.txt for details.
+
+- on OSX/Darwin, pathnames are now recognized as being encoded in
+"decomposed UTF-8", which isn't quite as bad as it sounds.  (This
+should mean that pathnames that contain non-ASCII characters should
+be handled correctly.)
+
+- in the Cocoa IDE, Hemlock editor commands now run in the main event
+thread (they used to run in a dedicated, per-window thread), and many
+other aspects of Hemlock/Cocoa integration have been simplified and
+improved.  Aside from offering greater stability, these changes make
+the Hemlock programming interface a lot more tractable.  People
+interested in writing Hemlock editor commands for use in the IDE may
+find a revised version of the Hemlock Command Implementor's Manual
+<http://trac.clozure.com/openmcl/wiki/HemlockProgrammer> useful.
+
+When run as a standalone application, the IDE provides a "console"
+window which displays diagnostic output that otherwise only appears
+in the system logs.
+
+- lots of bug fixes, smaller changes, and performance improvements.
+
+
Index: /branches/new-random/doc/release-notes.txt
===================================================================
--- /branches/new-random/doc/release-notes.txt	(revision 13309)
+++ /branches/new-random/doc/release-notes.txt	(revision 13309)
@@ -0,0 +1,2 @@
+Please see http://trac.clozure.com/ccl/wiki/ReleaseNotes/1.3
+
Index: /branches/new-random/doc/src/Makefile.debian
===================================================================
--- /branches/new-random/doc/src/Makefile.debian	(revision 13309)
+++ /branches/new-random/doc/src/Makefile.debian	(revision 13309)
@@ -0,0 +1,39 @@
+# -*- coding: unix -*-
+# Use xsltproc and an XSL stylesheet to translate DocBook XML to HTML
+# This require GNU "make", GNU "tar", Posix "find", Posix "date", and
+# "bzip2".  All those external dependencies are, of course, less than
+# ideal.
+
+# for Linux (Fedora; other distros may require some tweaking.)
+
+# The pathname to the xsltproc executable.  Since most alternate
+# translators use Java, this makefile would need to be rewritten to use
+# anything but xsltproc.
+
+XSLTPROC = /usr/bin/xsltproc
+
+
+# On a new system or when using a new version of xsltproc or of the
+# stylesheet packages, it's a good idea to run with --load-trace and
+# peruse the output to  make sure that none of the stylesheets are being
+# pulled over the network.  It's a significant expense, compounded by
+# the fact that they aren't cached across invocations of xsltproc.  If they
+# are, you should make sure that the correct catalog file is being used
+# (see below), and, if so, that its contents are correct.
+#EXTRAPARAMS= --load-trace
+EXTRAPARAMS= --xinclude --nonet
+
+# The catalog file tells the translator where to find XSL stylesheets on the
+# local system.  The first choice here is what should be used for builds
+# which are going to take place on the clozure.com server.  The second is
+# for when you have installed docbook on OS X using the fink package manager.
+# If neither applies, comment both out, and the translator will automagically
+# look on the web for the stylesheets, instead.
+
+
+export XML_CATALOG_FILES = xsl/catalog-debian
+
+CCL=/usr/local/bin/ccl64
+
+include makefile-common
+
Index: /branches/new-random/doc/src/Makefile.fedora
===================================================================
--- /branches/new-random/doc/src/Makefile.fedora	(revision 13309)
+++ /branches/new-random/doc/src/Makefile.fedora	(revision 13309)
@@ -0,0 +1,39 @@
+# -*- coding: unix -*-
+# Use xsltproc and an XSL stylesheet to translate DocBook XML to HTML
+# This require GNU "make", GNU "tar", Posix "find", Posix "date", and
+# "bzip2".  All those external dependencies are, of course, less than
+# ideal.
+
+# for Linux (Fedora; other distros may require some tweaking.)
+
+# The pathname to the xsltproc executable.  Since most alternate
+# translators use Java, this makefile would need to be rewritten to use
+# anything but xsltproc.
+
+XSLTPROC = /usr/bin/xsltproc
+
+
+# On a new system or when using a new version of xsltproc or of the
+# stylesheet packages, it's a good idea to run with --load-trace and
+# peruse the output to  make sure that none of the stylesheets are being
+# pulled over the network.  It's a significant expense, compounded by
+# the fact that they aren't cached across invocations of xsltproc.  If they
+# are, you should make sure that the correct catalog file is being used
+# (see below), and, if so, that its contents are correct.
+#EXTRAPARAMS= --load-trace
+EXTRAPARAMS= --xinclude --nonet
+
+# The catalog file tells the translator where to find XSL stylesheets on the
+# local system.  The first choice here is what should be used for builds
+# which are going to take place on the clozure.com server.  The second is
+# for when you have installed docbook on OS X using the fink package manager.
+# If neither applies, comment both out, and the translator will automagically
+# look on the web for the stylesheets, instead.
+
+
+export XML_CATALOG_FILES = xsl/catalog-fedora
+
+CCL=/usr/local/bin/ccl64
+
+include makefile-common
+
Index: /branches/new-random/doc/src/Makefile.macports
===================================================================
--- /branches/new-random/doc/src/Makefile.macports	(revision 13309)
+++ /branches/new-random/doc/src/Makefile.macports	(revision 13309)
@@ -0,0 +1,37 @@
+# -*- coding: unix -*-
+# Use xsltproc and an XSL stylesheet to translate DocBook XML to HTML
+# This require GNU "make", GNU "tar", Posix "find", Posix "date", and
+# "bzip2".  All those external dependencies are, of course, less than
+# ideal.
+
+# for Linux (Fedora; other distros may require some tweaking.)
+
+# The pathname to the xsltproc executable.  Since most alternate
+# translators use Java, this makefile would need to be rewritten to use
+# anything but xsltproc.
+
+XSLTPROC = xsltproc
+
+
+# On a new system or when using a new version of xsltproc or of the
+# stylesheet packages, it's a good idea to run with --load-trace and
+# peruse the output to  make sure that none of the stylesheets are being
+# pulled over the network.  It's a significant expense, compounded by
+# the fact that they aren't cached across invocations of xsltproc.  If they
+# are, you should make sure that the correct catalog file is being used
+# (see below), and, if so, that its contents are correct.
+#EXTRAPARAMS= --load-trace
+EXTRAPARAMS= --xinclude --nonet
+
+# The catalog file tells the translator where to find XSL stylesheets on the
+# local system.  The first choice here is what should be used for builds
+# which are going to take place on the clozure.com server.  The second is
+# for when you have installed docbook on OS X using the fink package manager.
+# If neither applies, comment both out, and the translator will automagically
+# look on the web for the stylesheets, instead.
+
+
+export XML_CATALOG_FILES = xsl/catalog-macports
+
+include makefile-common
+
Index: /branches/new-random/doc/src/about.xml
===================================================================
--- /branches/new-random/doc/src/about.xml	(revision 13309)
+++ /branches/new-random/doc/src/about.xml	(revision 13309)
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="about-ccl"><title>About &CCL;</title>
+  
+  <!-- ============================================================ -->
+  <sect1 id="introduction-to-ccl"><title>Introduction to &CCL;</title>
+    
+    <para>&CCL; is a fast, mature, open source Common Lisp
+      implementation that runs on Linux, Mac OS X and BSD on either
+      Intel x86-64 or PPC. &CCL; was forked from Macintosh Common
+      Lisp (MCL) in 1998 and the development has been entirely separate
+      since. Ports to IA32 and Windows are under development.</para>
+
+    <para>When it was forked from MCL in 1998, the new Lisp was named
+      OpenMCL. Recently, Clozure renamed its Lisp to &CCL;, partly
+      because its ancestor MCL has lately been released as open
+      source. Clozure thought it might be confusing for users if there
+      were two independent open-source projects with such similar
+      names. The new name also reflects &CCL;'s current status as the
+      flagship product of Clozure Associates.</para> 
+
+    <para>Furthermore, the new name refers to &CCL;'s ancestry: in its
+      early years, MCL was known as Coral Common Lisp, or "CCL". For
+      years the package that contains most of &CCL;'s
+      implementation-specific symbols has been named "CCL", an acronym
+      that once stood for the name of the Lisp product. It seems
+      fitting that "CCL" once again stands for the name of the
+      product.</para>
+
+    <para>Some commands and source files may still refer to "OpenMCL"
+      instead of &CCL;.</para>
+
+    <para>&CCL; compiles to native code and supports multithreading
+      using native OS threads. It includes a foreign-function interface,
+      and supports both Lisp code that calls external code, and external
+      code that calls Lisp code. &CCL; can create standalone executables
+      on all supported platforms.</para>
+
+    <para>On Mac OS X, &CCL; supports building GUI applications that
+      use OS X's native Cocoa frameworks, and the OS X distributions
+      include an IDE written with Cocoa, and distributed with complete
+      sources.</para>
+
+    <para>On all supported platforms, &CCL; can run as a command-line
+      process, or as an inferior Emacs process using either SLIME or
+      ILISP.</para>
+
+    <para>Features of &CCL; include</para>
+
+    <itemizedlist>
+      <listitem><para>Very fast compilation speed.</para></listitem>
+      <listitem><para>A fast, precise, compacting, generational
+      garbage collector written in hand-optimized C. The sizes of the
+      generations are fully configurable. Typically, a generation can
+      be collected in a millisecond on modern
+      systems.</para></listitem>
+      <listitem><para>Fast execution speed, competitive with other
+      Common Lisp implementations on most
+      benchmarks.</para></listitem>
+      <listitem><para>Robust and stable. Customers report that their
+      CPU-intensive, multi-threaded applications run for extended
+      periods on &CCL; without difficulty.</para></listitem>
+      <listitem><para>Full native OS threads on all platforms. Threads
+      are automatically distributed across multiple cores. The API
+      includes support for shared memory, locking, and blocking for OS
+      operations such as I/O.</para></listitem>
+      <listitem><para>Full Unicode support.</para></listitem>
+      <listitem><para>Full SLIME integration.</para></listitem>
+      <listitem><para>An IDE on Mac OS X, fully integrated with
+      the Macintosh window system and User Interface
+      standards.</para></listitem>
+      <listitem><para>Excellent debugging facilities. The names of all
+      local variables are available in a backtrace.</para></listitem>
+      <listitem><para>A complete, mature foreign function interface,
+      including a powerful bridge to Objective-C and Cocoa on Mac OS
+      X.</para></listitem>
+      <listitem><para>Many extensions including: files mapped to
+      Common Lisp vectors for fast file I/O; thread-local hash tables
+      and streams to eliminate locking overhead; cons hashing support;
+      and much more</para></listitem>
+      <listitem><para>Very efficient use of memory</para></listitem>
+    </itemizedlist>
+
+    <para>Although it's an open-source project, available free of
+      charge under a liberal license, &CCL; is also a fully-supported
+      product of Clozure Associates. Clozure continues to extend,
+      improve, and develop &CCL; in response to customer and user
+      needs, and offers full support and development services for
+      &CCL;.</para>
+  </sect1>
+
+
+</chapter>
Index: /branches/new-random/doc/src/build.xml
===================================================================
--- /branches/new-random/doc/src/build.xml	(revision 13309)
+++ /branches/new-random/doc/src/build.xml	(revision 13309)
@@ -0,0 +1,604 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+<chapter id="building-ccl-from-source"><title>Building &CCL; from its Source Code</title>
+  <anchor id="Building-CCL"/>
+  <para>&CCL;, like many other Lisp implementations, consists of a
+    kernel and a heap image.  The kernel is an ordinary C program, and
+    is built with a C compiler.  It provides very basic and
+    fundamental facilities, such as memory management, garbage
+    collection, and bootstrapping.  All the higher-level features are
+    written in Lisp, and compiled into the heap image.  Both parts are
+    needed to have a working Lisp implementation; neither the kernel
+    nor the heap image can stand alone.</para>
+
+  <para>You may already know that, when you have a C compiler which
+    is written in C, you need a working C compiler to build the
+    compiler. Similarly, the &CCL; heap image includes a Lisp
+    compiler, which is written in Lisp. You therefore need a working
+    Lisp compiler in order to build the Lisp heap image.</para>
+  
+  <para>Where will you get a working Lisp compiler?  No worries; you
+    can use a precompiled copy of a (slightly older and compatible)
+    version of &CCL;. This section explains how to do all this.</para>
+
+  <para>In principle it should be possible to use another
+    implementation of Common Lisp as the host compiler, rather than an
+    older &CCL;; this would be a challenging and experimental way to
+    build, and is not described here.</para>
+
+  <!-- =========================================================== -->
+  <sect1 id="building-definitions">
+    <title>Building Definitions</title>
+    <para>The following terms are used in subsequent sections; it
+      may be helpful to refer to these definitions.</para>
+
+    <para><indexterm><primary>fasl
+          files</primary></indexterm><glossterm linkend="fasl-file">fasl
+        files</glossterm> are the object files produced
+      by <literal>compile-file</literal>.  fasl files store the
+      machine code associated with function definitions and the
+      external representation of other lisp objects in a compact,
+      machine-readable form. fasl is short for
+      &ldquo;<literal>FAS</literal>t
+      <literal>L</literal>oading&rdquo;. &CCL; uses different pathname
+      types (extensions) to name fasl files on different platforms;
+      see
+      <xref linkend="Platform-specific-filename-conventions"/> </para>
+
+    <para>The <indexterm><primary>lisp
+          kernel</primary></indexterm> <glossterm linkend="lisp_kernel">Lisp
+        kernel</glossterm> is a C program with a fair amount of
+      platform-specific assembly language code. Its basic job is to
+      map a lisp heap image into memory, transfer control to some
+      compiled lisp code that the image contains, handle any
+      exceptions that occur during the execution of that lisp code,
+      and provide various other forms of runtime support for that
+      code. &CCL; uses different filenames to name the lisp kernel
+      files on different platforms; see
+      <xref linkend="Platform-specific-filename-conventions"/>.</para>
+
+    <para>A <indexterm><primary>heap
+          image</primary></indexterm> <glossterm linkend="lisp_image">heap
+        image</glossterm> is a file that can be quickly mapped into a
+      process's address space. Conceptually, it's not too different
+      from an executable file or shared library in the OS's native
+      format (ELF or Mach-O/dyld format); for historical reasons,
+      &CCL;'s own heap images are in their own (fairly simple)
+      format. The term <literal>full heap image</literal> refers to a
+      heap image file that contains all of the code and data that
+      comprise &CCL;. &CCL; uses different filenames to name the
+      standard full heap image files on different platforms; see
+      <xref linkend="Platform-specific-filename-conventions"/>.</para>
+
+    <para>A <indexterm><primary>bootstrapping
+          image</primary></indexterm> bootstrapping image is a minimal
+      heap image used in the process of building &CCL; itself.  The
+      bootstrapping image contains just enough code to load the rest
+      of &CCL; from fasl files.  It may help to think of the
+      bootstrapping image as the egg and the full heap image as the
+      chicken. &CCL; uses different filenames to name the standard
+      bootstrapping image files on different platforms; see
+      <xref linkend="Platform-specific-filename-conventions"/>
+      .</para>
+
+    <para>Each supported platform (and possibly a few
+      as-yet-unsupported ones) has a uniquely named subdirectory of
+      <literal>ccl/lisp-kernel/</literal>; each such
+      <indexterm><primary>kernel build directory</primary></indexterm>
+      contains a Makefile and may contain some auxiliary files (linker
+      scripts, etc.) that are used to build the lisp kernel on a
+      particular platform.The platform-specific name of the kernel
+      build directory is described in
+      <xref linkend="Platform-specific-filename-conventions"/>.</para>
+
+    <!-- ******************************************************** -->
+    <sect2 id="filename_conventions">
+      <title>Platform-specific filename conventions</title>
+      <table id ="Platform-specific-filename-conventions">
+	    <title>Platform-specific filename conventions</title>
+	    <tgroup cols="6">
+	      <thead>
+            <row>
+              <entry>Platform</entry>
+              <entry>kernel</entry>
+              <entry>full-image</entry>
+              <entry>boot-image</entry>
+              <entry>fasl extension</entry>
+              <entry>kernel-build directory</entry>
+	        </row>
+	      </thead>
+	      <tbody>
+	        <row>
+	          <entry>DarwinPPC32</entry>
+                  <entry>dppccl</entry>
+                  <entry>dppccl.image</entry>
+                  <entry>ppc-boot.image</entry>
+                  <entry>.dfsl</entry>
+                 <entry>darwinppc</entry>
+	        </row>
+	        <row>
+	          <entry>LinuxPPC32</entry>
+                  <entry>ppccl</entry>
+	          <entry>ppccl.image</entry>
+                  <entry>ppc-boot</entry>
+                  <entry>.pfsl</entry>
+                  <entry>linuxppc</entry>
+	        </row>
+	        <row>
+	          <entry>DarwinPPC64</entry>
+	          <entry>dppccl64</entry>
+	          <entry>dppccl64.image</entry>
+	          <entry>ppc-boot64.image</entry>
+	          <entry>.d64fsl</entry>
+	          <entry>darwinppc64</entry>
+                </row>
+                <row>
+	          <entry>LinuxPPC64</entry>
+                  <entry>ppccl64</entry>
+                  <entry>ppccl64.image</entry>
+                  <entry>ppc-boot64</entry>
+                  <entry>.p64fsl</entry>
+                  <entry>linuxppc64</entry>
+                </row>
+	        <row>
+	          <entry>LinuxX8664</entry>
+                  <entry>lx86cl64</entry>
+                  <entry>lx86cl64.image</entry>
+                  <entry>x86-boot64</entry>
+                  <entry>.lx64fsl</entry>
+                  <entry>linuxx8664</entry>
+                </row>
+	        <row>
+	          <entry>LinuxX8632</entry>
+                  <entry>lx86cl</entry>
+                  <entry>lx86cl.image</entry>
+                  <entry>x86-boot32</entry>
+                  <entry>.lx32fsl</entry>
+                  <entry>linuxx8632</entry>
+               </row>
+	       <row>
+	          <entry>DarwinX8664</entry>
+    	          <entry>dx86cl64</entry>
+                  <entry>dx86cl64.image</entry>
+                  <entry>x86-boot64.image</entry>
+                  <entry>.dx64fsl</entry>
+                  <entry>darwinx8664</entry>
+               </row>
+	       <row>
+	          <entry>DarwinX8632</entry>
+	          <entry>dx86cl</entry>
+                  <entry>dx86cl.image</entry>
+                  <entry>x86-boot32.image</entry>
+                  <entry>.dx32fsl</entry>
+                  <entry>darwinx8632</entry>
+               </row>
+	       <row>
+	          <entry>FreeBSDX8664</entry>
+                  <entry>fx86cl64</entry>
+                  <entry>fx86cl64.image</entry>
+                  <entry>fx86-boot64</entry>
+                  <entry>.fx64fsl</entry>
+                  <entry>freebsdx8664</entry>
+               </row>
+	       <row>
+                  <entry>FreeBSDX8632</entry>
+                  <entry>fx86cl</entry>
+                  <entry>fx86cl.image</entry>
+                  <entry>fx86-boot32</entry>
+                  <entry>.fx32fsl</entry>
+                  <entry>freebsdx8632</entry>
+               </row>
+               <row>
+	          <entry>SolarisX64</entry>
+                  <entry>sx86cl64</entry>
+                  <entry>sx86cl64.image</entry>
+                  <entry>sx86-boot64</entry>
+                  <entry>.sx64fsl</entry>
+                  <entry>solarisx64</entry>
+               </row>
+	       <row>
+		  <entry>SolarisX86</entry>
+                  <entry>sx86cl</entry>
+                  <entry>sx86cl.image</entry>
+                  <entry>sx86-boot32</entry>
+                  <entry>.sx32fsl</entry>
+                  <entry>solarisx86</entry>
+               </row>
+               <row>
+	          <entry>Win64</entry>
+                  <entry>wx86cl64.exe</entry>
+                  <entry>sx86cl64.image</entry>
+                  <entry>wx86-boot64.image</entry>
+                  <entry>.wx64fsl</entry>
+                  <entry>win64</entry>
+               </row>
+	       <row>
+		  <entry>Win32</entry>
+                  <entry>wx86cl.exe</entry>
+                  <entry>wx86cl.image</entry>
+                  <entry>wx86-boot32.image</entry>
+                  <entry>.wx32fsl</entry>
+                  <entry>win32</entry>
+               </row>
+	      </tbody>
+	    </tgroup>
+      </table>
+    </sect2>
+  </sect1>
+
+  <!-- =========================================================== -->
+  <sect1 id="Setting-Up-to-Build">
+    <title>Setting Up to Build</title>
+    <para>At a given time, there are generally two versions of &CCL; that
+    you might want to use (and therefore might want to build from
+      source):</para>
+    <itemizedlist>
+      <listitem><para>The released version</para></listitem>
+      <listitem><para>The development version, called the "trunk", which
+      may contain both interesting new features and interesting new bugs
+      </para></listitem>
+    </itemizedlist>
+    <para>All versions are available for download from svn.clozure.com via
+    the Subversion source control system.</para>
+    <para>
+      For example, to get a released version (1.3 in this example),
+      use a command like:
+      <programlisting>
+	svn co http://svn.clozure.com/publicsvn/openmcl/release/1.3/xxx/ccl
+      </programlisting>
+    </para>
+    <para>
+      To get the trunk version, use:
+      <programlisting>
+	svn co http://svn.clozure.com/publicsvn/openmcl/trunk/xxx/ccl
+      </programlisting>
+    </para>
+    <para>
+      Change the "xxx" to one of the following names:
+      <literal>darwinx86</literal>,
+      <literal>linuxx86</literal>,
+      <literal>freebsdx86</literal>,
+      <literal>solarisx86</literal>,
+      <literal>window</literal>,
+      <literal>linuxppc</literal>,
+      or 
+      <literal>darwinppc</literal>.
+    </para>
+    <para>
+      In the case of released versions, there may also be tar archives
+      available.  See the <ulink url="http://trac.clozure.com/ccl/">Clozure CL
+      Trac</ulink> for details.
+    </para>
+    <para>Subversion client programs are pre-installed on Mac OS X 10.5 and
+      later and are typically either pre-installed or readily available
+      on Linux and FreeBSD platforms.  The <ulink url="http://subversion.tigris.org">Subversion web page</ulink> contains links to subversion client programs
+      for many platforms; users of Mac OS X 10.4 can also
+      install Subversion clients via Fink or MacPorts.</para>
+    
+  </sect1>
+
+  <!-- =========================================================== -->
+  <sect1 id="Building-Everything">
+    <title>Building Everything</title>
+    <para>Given that you now have everything you need, do the
+      following in a running &CCL; to bring your Lisp system
+      completely up to date.</para>
+    <programlisting>
+? (ccl:rebuild-ccl :full t)
+    </programlisting>
+    <para>That call to the function <literal>rebuild-ccl</literal>
+      performs the following steps:</para>
+    <itemizedlist>
+      <listitem>
+	    <para>Deletes all fasl files and other object files in the
+	      <literal>ccl</literal> directory tree</para>
+	  </listitem>
+      <listitem>
+	    <para>Runs an external process that does a
+	      <literal>make</literal> in the current platform's kernel
+	      build directory to create a new kernel.  
+             This step can only work if the C compiler and related
+             tools are installed; see <xref linkend="Kernel-build-prerequisites"/>. 
+           </para>
+	  </listitem>
+      <listitem>
+	    <para>Does <literal>(compile-ccl t)</literal> in the running
+	      lisp, to produce a set of fasl files from the &ldquo;higher
+	      level&rdquo; lisp sources.</para>
+	  </listitem>
+      <listitem>
+	    <para>Does <literal>(xload-level-0 :force)</literal> in the
+	      running lisp, to compile the lisp sources in the
+	      &ldquo;ccl:level-0;&rdquo; directory into fasl files and
+	      then create a bootstrapping image from those fasl
+	      files.</para>
+	  </listitem>
+      <listitem>
+	    <para>Runs another external process, which causes the newly
+	      compiled lisp kernel to load the new bootstrapping image.
+	      The bootsrtrapping image then loads the &ldquo;higher
+	      level&rdquo; fasl files and a new copy of the platform's
+	      full heap image is then saved.</para>
+	  </listitem>
+    </itemizedlist>
+    <para>If all goes well, it'll all happen without user
+      intervention and with some simple progress messages.  If
+      anything goes wrong during execution of either of the external
+      processes, the process output is displayed as part of a lisp
+      error message.</para>
+    <para><literal>rebuild-ccl</literal> is essentially just a short
+      cut for running all the individual steps involved in rebuilding
+      the system.  You can also execute these steps individually, as
+      described below.</para>
+  </sect1>
+
+  <!-- =========================================================== -->
+  <sect1 id="Building-the-kernel">
+    <title>Building the kernel</title>
+    <para>The Lisp kernel is the executable that you run to use
+      Lisp.  It doesn't actually contain the entire Lisp
+      implementation; rather, it loads a heap image which contains the
+      specifics&mdash;the "library", as it might be called if this was a C
+      program.  The kernel also provides runtime support to the heap
+      image, such as garbage collection, memory allocation, exception
+      handling, and the OS interface.</para>
+
+    <para>The Lisp kernel file has different names on different
+      platforms. See
+      <xref linkend="Platform-specific-filename-conventions"/>. On all
+      platforms the lisp kernel sources reside
+      in <literal>ccl/lisp-kernel</literal>.</para>
+
+    <para>This section gives directions on how to rebuild the Lisp
+      kernel from its source code.  Most &CCL; users will rarely
+      have to do this.  You probably will only need to do it if you are
+      attempting to port &CCL; to a new architecture or extend or enhance
+      its kernel in some way.  As mentioned above, this step happens
+      automatically when you do
+      <programlisting>
+? (rebuild-ccl :full t)
+      </programlisting>
+    </para>
+
+
+    <!-- ******************************************************** -->
+    <sect2 id="Kernel-build-prerequisites">
+      <title>Kernel build prerequisites</title>
+	  <para>The &CCL; kernel can be bult with the following widely
+	    available tools:</para>
+      <itemizedlist>
+        <listitem><para>cc or gcc- the GNU C compiler</para></listitem>
+        <listitem><para>ld - the GNU linker</para></listitem>
+        <listitem><para>m4 or gm4- the GNU m4 macro processor</para></listitem>
+        <listitem><para>as - the GNU assembler (version 2.10.1 or later)</para></listitem>
+	    <listitem><para>make - either GNU make or, on FreeBSD, the default BSD make program</para></listitem>
+	  </itemizedlist>
+	  <para> In general, the more recent the versions of those
+	    tools, the better; some versions of gcc 3.x on Linux have
+	    difficulty compiling some of the kernel source code correctly
+	    (so gcc 4.0 should be used, if possible.)  On Mac OS X, the
+	    versions of the tools distributed with Xcode should work fine;
+	    on Linux, the versions of the tools installed with the OS (or
+	    available through its package management system) should work
+	    fine if they're "recent enough".  On FreeBSD, the installed
+	    version of the <literal>m4</literal> program doesn't support
+	    some features that the kernel build process depends on; the
+	    GNU version of the m4 macroprocessor (called
+	    <literal>gm4</literal> on FreeBSD) should be installed.
+	  </para>
+	  <note><para>In order to build the lisp kernel on Mac OS X
+	  10.6 Snow Leopard, you must install the optional 10.4
+	  support when installing Xcode.</para>
+	  </note>
+    </sect2>
+
+    <!-- ******************************************************** -->
+    <sect2 id="kernel-build-command">
+	  <title>Using "make" to build the lisp kernel</title>
+      <para>With those tools in place, do:
+        <programlisting>
+shell> cd ccl/lisp-kernel/<replaceable>PLATFORM</replaceable>
+shell> make
+	    </programlisting>
+	  </para>
+      <para>That'll assemble several assembly language source files,
+        compile several C source files, and link
+        ../../<replaceable>the kernel</replaceable>.
+	  </para>
+    </sect2>
+  </sect1>
+
+  <!-- =========================================================== -->
+  <sect1 id="Building-the-heap-image">
+    <title>Building the heap image</title>
+    <para>The initial heap image is loaded by the Lisp kernel, and
+      provides most of the language implementation The heap image
+      captures the entire state of a running Lisp (except for external
+      resources, such as open files and TCP sockets).  After it is
+      loaded, the contents of the new Lisp process's memory are
+      exactly the same as those of the old Lisp process when the image
+      was created.</para>
+    <para>The heap image is how we get around the fact that we can't
+      run Lisp code until we have a working Lisp implementation, and
+      we can't make our Lisp implementation work until we can run Lisp
+      code.  Since the heap image already contains a fully-working
+      implementation, all we need to do is load it into memory and
+      start using it.</para>
+    <para>If you're building a new version of &CCL;, you need to
+      build a new heap image.</para>
+    <para>(You might also wish to build a heap image if you have a
+      large program that is very complicated or time-consuming to
+      load, so that you will be able to load it once, save an image,
+      and thenceforth never have to load it again. At any time, a heap
+      image capturing the entire memory state of a running Lisp can be
+      created by calling the function
+      <literal>ccl:save-application</literal>.)</para>
+
+    <!-- ******************************************************** -->
+    <sect2 id="Development-cycle">
+	  <title>Development cycle</title>
+      <para>Creating a new &CCL; full heap image consists of the
+        following steps:</para>
+      <orderedlist>
+        <listitem><para>Using your existing &CCL;, create a
+            bootstrapping image</para></listitem>
+        <listitem><para>Using your existing &CCL;, recompile your
+            updated &CCL; sources</para></listitem>
+        <listitem><para>Invoke &CCL; with the bootstrapping image
+            you just created (rather than with the existing full heap
+            image).</para></listitem>
+	  </orderedlist>
+	  <para>When you invoke &CCL; with the bootstrapping image, it
+	    starts up, loads all of the &CCL; fasl files, and saves out a
+	    new full heap image.  Voila.  You've created a new heap
+	    image.</para>
+      <para>A few points worth noting:</para>
+	  <itemizedlist>
+        <listitem>
+	      <para>There's a circular dependency between the full heap
+	        image and the bootstrapping image, in that each is used to
+	        build the other.</para>
+	    </listitem>
+        <listitem>
+	      <para>There are some minor implementation
+	        differences, but the environment in effect after the
+	        bootstrapping image has loaded its fasl files is essentially
+	        equivalent to the environment provided by the full heap
+	        image; the latter loads a lot faster and is easier to
+	        distribute, of course.</para>
+	    </listitem>
+        <listitem>
+	      <para>If the full heap image doesn't work (because
+	        of an OS compatibilty problem or other bug), it's very likely
+	        that the bootstrapping image will suffer the same
+	        problems.</para>
+	    </listitem>
+	  </itemizedlist>
+      <para>Given a bootstrapping image and a set of up-to-date fasl
+        files, the development cycle usually involves editing lisp
+        sources (or updating those sources via cvs update),
+        recompiling modified files, and using the bootstrapping image
+        to produce a new heap image.</para>
+    </sect2>
+
+    <!-- ******************************************************** -->
+    <sect2 id="Generating-a-bootstrapping-image">
+      <title>Generating a bootstrapping image</title>
+      <para>The bootstrapping image isn't provided in &CCL;
+        distributions. It can be built from the source code provided
+        in distributions (using a lisp image and kernel provided in
+        those distributions) using the procedure described
+        below.</para>
+
+      <para>The bootstrapping image is built by invoking a special
+        utility inside a running &CCL; heap image to load files
+        contained in the <literal>ccl/level-0</literal> directory. The
+        bootstrapping image loads several dozen fasl files.  After
+        it's done so, it saves a heap image via
+        <literal>save-application</literal>. This process is called
+        "cross-dumping".</para>
+
+      <para>Given a source distribution, a lisp kernel, and a heap
+        image, one can produce a bootstrapping image by first invoking
+        &CCL; from the shell:</para>
+      <programlisting>
+shell&gt; ccl
+Welcome to &CCL; .... !
+?
+	  </programlisting>
+	  <para>then calling <literal>ccl:xload-level-0</literal> at the
+	    lisp prompt</para>
+	  <programlisting>
+? (ccl:xload-level-0)
+	  </programlisting>
+      <para>This function compiles the lisp sources in the ccl/level-0
+        directory if they're newer than the corresponding fasl files
+        and then loads the resulting fasl files into a simulated lisp
+        heap contained in data structures inside the running
+        lisp. That simulated heap image is then written to
+        disk.</para>
+      <para><literal>xload-level-0</literal> should be called
+        whenever your existing boot image is out-of-date with respect
+        to the source files in <literal>ccl:level-0;</literal>
+        :</para>
+      <programlisting>
+? (ccl:xload-level-0 :force)
+      </programlisting>
+      <para>forces recompilation of the level-0 sources.</para>
+    </sect2>
+
+    <!-- ******************************************************** -->
+    <sect2 id="Generating-fasl-files">
+      <title>Generating fasl files</title>
+	  <para> Calling:</para>
+      <programlisting>
+? (ccl:compile-ccl)
+	  </programlisting>
+	  <para>at the lisp prompt compiles any fasl files that are
+	    out-of-date with respect to the corresponding lisp sources;
+	    <literal>(ccl:compile-ccl t)</literal> forces
+	    recompilation. <literal>ccl:compile-ccl</literal> reloads
+	    newly-compiled versions of some files;
+	    <literal>ccl:xcompile-ccl</literal> is analogous, but skips
+	    this reloading step.</para>
+      <para>Unless there are bootstrapping considerations involved, it
+        usually doesn't matter whether these files are reloaded after
+        they're recompiled.</para>
+      <para>Calling <literal>compile-ccl</literal> or
+        <literal>xcompile-ccl</literal> in an environment where fasl
+        files don't yet exist may produce warnings to that effect
+        whenever files are <literal>require</literal>d during
+        compilation; those warnings can be safely ignored. Depending
+        on the maturity of the &CCL; release, calling
+        <literal>compile-ccl</literal> or
+        <literal>xcompile-ccl</literal> may also produce several
+        warnings about undefined functions, etc. They should be
+        cleaned up at some point.</para>
+    </sect2>
+
+    <!-- ******************************************************** -->
+    <sect2 id="Building-a-full-image-from-a-bootstrapping-image">
+	  <title>Building a full image from a bootstrapping image</title>
+	  <para>To build a full image from a bootstrapping image, just
+	    invoke the kernel with the bootstrapping image as an
+	    argument</para>
+      <programlisting>
+$ cd ccl                        # wherever your ccl directory is
+$ ./KERNEL BOOT_IMAGE
+	  </programlisting>
+      <para>Where <replaceable>KERNEL</replaceable> and
+        <replaceable>BOOT_IMAGE</replaceable> are the names of
+        the kernel and boot image appropriate to the platform you are
+        running on.  See <xref linkend="Platform-specific-filename-conventions"/></para>
+      <para>That should load a few dozen fasl files (printing a
+        message as each file is loaded.) If all of these files
+        successfully load, the lisp will print a prompt. You should be
+        able to do essentially everything in that environment that you
+        can in the environment provided by a "real" heap image. If
+        you're confident that things loaded OK, you can save that
+        image.</para>
+      <programlisting>
+? (ccl:save-application "<replaceable>image_name</replaceable>") ; Overwiting the existing heap image
+	  </programlisting>
+	  <para>Where <replaceable>image_name</replaceable> is the name of
+        the full heap image for your platform. See
+        <xref linkend="Platform-specific-filename-conventions"/>.</para>
+      <para>If things go wrong in the early stages of the loading
+        sequence, errors are often difficult to debug; until a fair
+        amount of code (CLOS, the CL condition system, streams, the
+        reader, the read-eval-print loop) is loaded, it's generally
+        not possible for the lisp to report an error.  Errors that
+        occur during these early stages ("the cold load") sometimes
+        cause the lisp kernel debugger (see ) to be invoked; it's
+        primitive, but can sometimes help one to get oriented.</para>
+    </sect2>
+  </sect1>
+</chapter>
Index: /branches/new-random/doc/src/ccl-documentation.xml
===================================================================
--- /branches/new-random/doc/src/ccl-documentation.xml	(revision 13309)
+++ /branches/new-random/doc/src/ccl-documentation.xml	(revision 13309)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "Clozure CL">
+]>
+
+<book lang="en">
+ <bookinfo>
+  <title>&CCL; Documentation</title>
+ </bookinfo>
+<!-- -->
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="about.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="install.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="build.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="using.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="ide.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="threads.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="sockets.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="external-process.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="streams.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="mop.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="profile.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="ffi.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="objc-bridge.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="platform-notes.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="gc.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="implementation.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="modifying.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="q-and-a.xml"/>
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+            href="glossary.xml"/>
+
+ <index id="Symbol-Index"><title>Symbol Index</title></index>
+</book>
Index: /branches/new-random/doc/src/docbook-rng-4.5/calstblx.rnc
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/calstblx.rnc	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/calstblx.rnc	(revision 13309)
@@ -0,0 +1,164 @@
+# ......................................................................
+
+# DocBook CALS Table Model V4.5 ........................................
+
+# File calstblx.mod ....................................................
+
+# Copyright 1992-2002 HaL Computer Systems, Inc.,
+# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+# Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+# Organization for the Advancement of Structured Information
+# Standards (OASIS).
+# 
+# This DTD is based on the CALS Table Model
+# PUBLIC "-//USA-DOD//DTD Table Model 951010//EN"
+# 
+# $Id: calstblx.dtd 6340 2006-10-03 13:23:24Z nwalsh $
+# 
+# Permission to use, copy, modify and distribute the DocBook DTD
+# and its accompanying documentation for any purpose and without fee
+# is hereby granted in perpetuity, provided that the above copyright
+# notice and this paragraph appear in all copies.  The copyright
+# holders make no representation about the suitability of the DTD for
+# any purpose.  It is provided "as is" without expressed or implied
+# warranty.
+# 
+# If you modify the DocBook DTD in any way, except for declaring and
+# referencing additional sets of general entities and declaring
+# additional notations, label your DTD as a variant of DocBook.  See
+# the maintenance documentation for more information.
+# 
+# Please direct all questions, bug reports, or suggestions for
+# changes to the docbook@lists.oasis-open.org mailing list. For more
+# information, see http://www.oasis-open.org/docbook/.
+
+# ......................................................................
+
+# This module contains the definitions for the CALS Table Model
+# converted to XML. It has been modified slightly for use in the
+# combined HTML/CALS models supported by DocBook V4.5.
+
+# These definitions are not directly related to the table model, but are
+# used in the default CALS table model and are usually defined elsewhere
+# (and prior to the inclusion of this table module) in a CALS DTD.
+
+# no if zero(s),
+# yes if any other digits value
+
+yesorno = string
+titles = title?
+# default for use in entry content
+
+# The parameter entities as defined below provide the CALS table model
+# as published (as part of the Example DTD) in MIL-HDBK-28001.
+# 
+# These following declarations provide the CALS-compliant default definitions
+# for these entities.  However, these entities can and should be redefined
+# (by giving the appropriate parameter entity declaration(s) prior to the
+# reference to this Table Model declaration set entity) to fit the needs
+# of the current application.
+tbl.table-titles.mdl = titles
+tbl.table-main.mdl = tgroup+ | graphic+
+tbl.tgroup.mdl = colspec*, spanspec*, thead?, tfoot?, tbody
+tbl.tgroup.att = attribute tgroupstyle { text }?
+tbl.row.mdl = (entry | entrytbl)+
+tbl.entrytbl.mdl = colspec*, spanspec*, thead?, tbody
+# =====  Element and attribute declarations follow. =====
+
+# doc:A formal table in a document.
+table = element table { table.attlist, tbl.table.mdl }
+table.attlist &=
+  attribute frame { tbl.frame.attval }?,
+  attribute colsep { yesorno }?,
+  attribute rowsep { yesorno }?,
+  tbl.table.att,
+  bodyatt,
+  secur
+# doc:A wrapper for the main content of a table, or part of a table.
+tgroup = element tgroup { tgroup.attlist, tbl.tgroup.mdl }
+tgroup.attlist &=
+  attribute cols { text },
+  tbl.tgroup.att,
+  attribute colsep { yesorno }?,
+  attribute rowsep { yesorno }?,
+  attribute align { "left" | "right" | "center" | "justify" | "char" }?,
+  attribute char { text }?,
+  attribute charoff { text }?,
+  secur
+# doc:Specifications for a column in a table.
+colspec = element colspec { colspec.attlist, empty }
+colspec.attlist &=
+  attribute colnum { text }?,
+  attribute colname { text }?,
+  attribute colwidth { text }?,
+  attribute colsep { yesorno }?,
+  attribute rowsep { yesorno }?,
+  attribute align { "left" | "right" | "center" | "justify" | "char" }?,
+  attribute char { text }?,
+  attribute charoff { text }?
+# doc:Formatting information for a spanned column in a table.
+spanspec = element spanspec { spanspec.attlist, empty }
+spanspec.attlist &=
+  attribute namest { text },
+  attribute nameend { text },
+  attribute spanname { text },
+  attribute colsep { yesorno }?,
+  attribute rowsep { yesorno }?,
+  attribute align { "left" | "right" | "center" | "justify" | "char" }?,
+  attribute char { text }?,
+  attribute charoff { text }?
+# doc:A table header consisting of one or more rows.
+thead = element thead { thead.attlist, tbl.hdft.mdl }
+thead.attlist &=
+  attribute valign { "top" | "middle" | "bottom" }?,
+  secur
+# doc:A table footer consisting of one or more rows.
+tfoot = element tfoot { tfoot.attlist, tbl.hdft.mdl }
+tfoot.attlist &=
+  attribute valign { "top" | "middle" | "bottom" }?,
+  secur
+# doc:A wrapper for the rows of a table or informal table.
+tbody = element tbody { tbody.attlist, tbl.tbody.mdl }
+tbody.attlist &=
+  attribute valign { "top" | "middle" | "bottom" }?,
+  secur
+# doc:A row in a table.
+row = element row { row.attlist, tbl.row.mdl }
+row.attlist &=
+  attribute rowsep { yesorno }?,
+  attribute valign { "top" | "middle" | "bottom" }?,
+  secur
+# doc:A subtable appearing in place of an Entry in a table.
+entrytbl = element entrytbl { entrytbl.attlist, tbl.entrytbl.mdl }
+entrytbl.attlist &=
+  attribute cols { text },
+  tbl.tgroup.att,
+  attribute colname { text }?,
+  attribute spanname { text }?,
+  attribute namest { text }?,
+  attribute nameend { text }?,
+  attribute colsep { yesorno }?,
+  attribute rowsep { yesorno }?,
+  attribute align { "left" | "right" | "center" | "justify" | "char" }?,
+  attribute char { text }?,
+  attribute charoff { text }?,
+  secur
+# doc:A cell in a table.
+entry = element entry { entry.attlist, tbl.entry.mdl* }
+entry.attlist &=
+  attribute colname { text }?,
+  attribute namest { text }?,
+  attribute nameend { text }?,
+  attribute spanname { text }?,
+  attribute morerows { text }?,
+  attribute colsep { yesorno }?,
+  attribute rowsep { yesorno }?,
+  attribute align { "left" | "right" | "center" | "justify" | "char" }?,
+  attribute char { text }?,
+  attribute charoff { text }?,
+  attribute rotate { yesorno }?,
+  attribute valign { "top" | "middle" | "bottom" }?,
+  secur
+# End of DocBook CALS Table Model V4.5 .................................
+
+# ......................................................................
Index: /branches/new-random/doc/src/docbook-rng-4.5/calstblx.rng
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/calstblx.rng	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/calstblx.rng	(revision 13309)
@@ -0,0 +1,477 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ...................................................................... -->
+<!-- DocBook CALS Table Model V4.5 ........................................ -->
+<!-- File calstblx.mod .................................................... -->
+<!--
+  Copyright 1992-2002 HaL Computer Systems, Inc.,
+  O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+  Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+  Organization for the Advancement of Structured Information
+  Standards (OASIS).
+  
+  This DTD is based on the CALS Table Model
+  PUBLIC "-//USA-DOD//DTD Table Model 951010//EN"
+  
+  $Id: calstblx.dtd 6340 2006-10-03 13:23:24Z nwalsh $
+  
+  Permission to use, copy, modify and distribute the DocBook DTD
+  and its accompanying documentation for any purpose and without fee
+  is hereby granted in perpetuity, provided that the above copyright
+  notice and this paragraph appear in all copies.  The copyright
+  holders make no representation about the suitability of the DTD for
+  any purpose.  It is provided "as is" without expressed or implied
+  warranty.
+  
+  If you modify the DocBook DTD in any way, except for declaring and
+  referencing additional sets of general entities and declaring
+  additional notations, label your DTD as a variant of DocBook.  See
+  the maintenance documentation for more information.
+  
+  Please direct all questions, bug reports, or suggestions for
+  changes to the docbook@lists.oasis-open.org mailing list. For more
+  information, see http://www.oasis-open.org/docbook/.
+-->
+<!-- ...................................................................... -->
+<!--
+  This module contains the definitions for the CALS Table Model
+  converted to XML. It has been modified slightly for use in the
+  combined HTML/CALS models supported by DocBook V4.5.
+-->
+<!--
+  These definitions are not directly related to the table model, but are
+  used in the default CALS table model and are usually defined elsewhere
+  (and prior to the inclusion of this table module) in a CALS DTD.
+-->
+<!--
+  no if zero(s),
+  yes if any other digits value
+-->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="">
+  <define name="yesorno">
+    <data type="string"/>
+  </define>
+  <define name="titles">
+    <optional>
+      <ref name="title"/>
+    </optional>
+  </define>
+  <!-- default for use in entry content -->
+  <!--
+    The parameter entities as defined below provide the CALS table model
+    as published (as part of the Example DTD) in MIL-HDBK-28001.
+    
+    These following declarations provide the CALS-compliant default definitions
+    for these entities.  However, these entities can and should be redefined
+    (by giving the appropriate parameter entity declaration(s) prior to the
+    reference to this Table Model declaration set entity) to fit the needs
+    of the current application.
+  -->
+  <define name="tbl.table-titles.mdl">
+    <ref name="titles"/>
+  </define>
+  <define name="tbl.table-main.mdl">
+    <choice>
+      <oneOrMore>
+        <ref name="tgroup"/>
+      </oneOrMore>
+      <oneOrMore>
+        <ref name="graphic"/>
+      </oneOrMore>
+    </choice>
+  </define>
+  <define name="tbl.tgroup.mdl">
+    <zeroOrMore>
+      <ref name="colspec"/>
+    </zeroOrMore>
+    <zeroOrMore>
+      <ref name="spanspec"/>
+    </zeroOrMore>
+    <optional>
+      <ref name="thead"/>
+    </optional>
+    <optional>
+      <ref name="tfoot"/>
+    </optional>
+    <ref name="tbody"/>
+  </define>
+  <define name="tbl.tgroup.att">
+    <optional>
+      <attribute name="tgroupstyle"/>
+    </optional>
+  </define>
+  <define name="tbl.row.mdl">
+    <oneOrMore>
+      <choice>
+        <ref name="entry"/>
+        <ref name="entrytbl"/>
+      </choice>
+    </oneOrMore>
+  </define>
+  <define name="tbl.entrytbl.mdl">
+    <zeroOrMore>
+      <ref name="colspec"/>
+    </zeroOrMore>
+    <zeroOrMore>
+      <ref name="spanspec"/>
+    </zeroOrMore>
+    <optional>
+      <ref name="thead"/>
+    </optional>
+    <ref name="tbody"/>
+  </define>
+  <!-- =====  Element and attribute declarations follow. ===== -->
+  <!-- doc:A formal table in a document. -->
+  <define name="table">
+    <element name="table">
+      <ref name="table.attlist"/>
+      <ref name="tbl.table.mdl"/>
+    </element>
+  </define>
+  <define name="table.attlist" combine="interleave">
+    <optional>
+      <attribute name="frame">
+        <choice>
+          <ref name="tbl.frame.attval"/>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="colsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <ref name="tbl.table.att"/>
+    <ref name="bodyatt"/>
+    <ref name="secur"/>
+  </define>
+  <!-- doc:A wrapper for the main content of a table, or part of a table. -->
+  <define name="tgroup">
+    <element name="tgroup">
+      <ref name="tgroup.attlist"/>
+      <ref name="tbl.tgroup.mdl"/>
+    </element>
+  </define>
+  <define name="tgroup.attlist" combine="interleave">
+    <attribute name="cols"/>
+    <ref name="tbl.tgroup.att"/>
+    <optional>
+      <attribute name="colsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+          <value>justify</value>
+          <value>char</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="char"/>
+    </optional>
+    <optional>
+      <attribute name="charoff"/>
+    </optional>
+    <ref name="secur"/>
+  </define>
+  <!-- doc:Specifications for a column in a table. -->
+  <define name="colspec">
+    <element name="colspec">
+      <ref name="colspec.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <define name="colspec.attlist" combine="interleave">
+    <optional>
+      <attribute name="colnum"/>
+    </optional>
+    <optional>
+      <attribute name="colname"/>
+    </optional>
+    <optional>
+      <attribute name="colwidth"/>
+    </optional>
+    <optional>
+      <attribute name="colsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+          <value>justify</value>
+          <value>char</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="char"/>
+    </optional>
+    <optional>
+      <attribute name="charoff"/>
+    </optional>
+  </define>
+  <!-- doc:Formatting information for a spanned column in a table. -->
+  <define name="spanspec">
+    <element name="spanspec">
+      <ref name="spanspec.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <define name="spanspec.attlist" combine="interleave">
+    <attribute name="namest"/>
+    <attribute name="nameend"/>
+    <attribute name="spanname"/>
+    <optional>
+      <attribute name="colsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+          <value>justify</value>
+          <value>char</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="char"/>
+    </optional>
+    <optional>
+      <attribute name="charoff"/>
+    </optional>
+  </define>
+  <!-- doc:A table header consisting of one or more rows. -->
+  <define name="thead">
+    <element name="thead">
+      <ref name="thead.attlist"/>
+      <ref name="tbl.hdft.mdl"/>
+    </element>
+  </define>
+  <define name="thead.attlist" combine="interleave">
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="secur"/>
+  </define>
+  <!-- doc:A table footer consisting of one or more rows. -->
+  <define name="tfoot">
+    <element name="tfoot">
+      <ref name="tfoot.attlist"/>
+      <ref name="tbl.hdft.mdl"/>
+    </element>
+  </define>
+  <define name="tfoot.attlist" combine="interleave">
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="secur"/>
+  </define>
+  <!-- doc:A wrapper for the rows of a table or informal table. -->
+  <define name="tbody">
+    <element name="tbody">
+      <ref name="tbody.attlist"/>
+      <ref name="tbl.tbody.mdl"/>
+    </element>
+  </define>
+  <define name="tbody.attlist" combine="interleave">
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="secur"/>
+  </define>
+  <!-- doc:A row in a table. -->
+  <define name="row">
+    <element name="row">
+      <ref name="row.attlist"/>
+      <ref name="tbl.row.mdl"/>
+    </element>
+  </define>
+  <define name="row.attlist" combine="interleave">
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="secur"/>
+  </define>
+  <!-- doc:A subtable appearing in place of an Entry in a table. -->
+  <define name="entrytbl">
+    <element name="entrytbl">
+      <ref name="entrytbl.attlist"/>
+      <ref name="tbl.entrytbl.mdl"/>
+    </element>
+  </define>
+  <define name="entrytbl.attlist" combine="interleave">
+    <attribute name="cols"/>
+    <ref name="tbl.tgroup.att"/>
+    <optional>
+      <attribute name="colname"/>
+    </optional>
+    <optional>
+      <attribute name="spanname"/>
+    </optional>
+    <optional>
+      <attribute name="namest"/>
+    </optional>
+    <optional>
+      <attribute name="nameend"/>
+    </optional>
+    <optional>
+      <attribute name="colsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+          <value>justify</value>
+          <value>char</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="char"/>
+    </optional>
+    <optional>
+      <attribute name="charoff"/>
+    </optional>
+    <ref name="secur"/>
+  </define>
+  <!-- doc:A cell in a table. -->
+  <define name="entry">
+    <element name="entry">
+      <ref name="entry.attlist"/>
+      <zeroOrMore>
+        <ref name="tbl.entry.mdl"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <define name="entry.attlist" combine="interleave">
+    <optional>
+      <attribute name="colname"/>
+    </optional>
+    <optional>
+      <attribute name="namest"/>
+    </optional>
+    <optional>
+      <attribute name="nameend"/>
+    </optional>
+    <optional>
+      <attribute name="spanname"/>
+    </optional>
+    <optional>
+      <attribute name="morerows"/>
+    </optional>
+    <optional>
+      <attribute name="colsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+          <value>justify</value>
+          <value>char</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="char"/>
+    </optional>
+    <optional>
+      <attribute name="charoff"/>
+    </optional>
+    <optional>
+      <attribute name="rotate">
+        <ref name="yesorno"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="secur"/>
+  </define>
+</grammar>
+<!-- End of DocBook CALS Table Model V4.5 ................................. -->
+<!-- ...................................................................... -->
Index: /branches/new-random/doc/src/docbook-rng-4.5/dbhierx.rnc
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/dbhierx.rnc	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/dbhierx.rnc	(revision 13309)
@@ -0,0 +1,1549 @@
+# ......................................................................
+
+# DocBook document hierarchy module V4.5 ...............................
+
+# File dbhierx.mod .....................................................
+
+# Copyright 1992-2004 HaL Computer Systems, Inc.,
+# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+# Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+# Organization for the Advancement of Structured Information
+# Standards (OASIS).
+# 
+# $Id: dbhierx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+# 
+# Permission to use, copy, modify and distribute the DocBook DTD
+# and its accompanying documentation for any purpose and without fee
+# is hereby granted in perpetuity, provided that the above copyright
+# notice and this paragraph appear in all copies.  The copyright
+# holders make no representation about the suitability of the DTD for
+# any purpose.  It is provided "as is" without expressed or implied
+# warranty.
+# 
+# If you modify the DocBook DTD in any way, except for declaring and
+# referencing additional sets of general entities and declaring
+# additional notations, label your DTD as a variant of DocBook.  See
+# the maintenance documentation for more information.
+# 
+# Please direct all questions, bug reports, or suggestions for
+# changes to the docbook@lists.oasis-open.org mailing list. For more
+# information, see http://www.oasis-open.org/docbook/.
+
+# ......................................................................
+
+# This module contains the definitions for the overall document
+# hierarchies of DocBook documents.  It covers computer documentation
+# manuals and manual fragments, as well as reference entries (such as
+# man pages) and technical journals or anthologies containing
+# articles.
+# 
+# This module depends on the DocBook information pool module.  All
+# elements and entities referenced but not defined here are assumed
+# to be defined in the information pool module.
+# 
+# In DTD driver files referring to this module, please use an entity
+# declaration that uses the public identifier shown below:
+# 
+# <!ENTITY % dbhier PUBLIC
+# "-//OASIS//ELEMENTS DocBook Document Hierarchy V4.5//EN"
+# "dbhierx.mod">
+# %dbhier;
+# 
+# See the documentation for detailed information on the parameter
+# entity and module scheme used in DocBook, customizing DocBook and
+# planning for interchange, and changes made since the last release
+# of DocBook.
+
+# ......................................................................
+
+# Entities for module inclusions .......................................
+
+# ......................................................................
+
+# Entities for element classes .........................................
+
+local.appendix.class = notAllowed
+appendix.class = appendix | local.appendix.class
+local.article.class = notAllowed
+article.class = article | local.article.class
+local.book.class = notAllowed
+book.class = book | local.book.class
+local.chapter.class = notAllowed
+chapter.class = chapter | local.chapter.class
+local.index.class = notAllowed
+index.class = index | setindex | local.index.class
+local.refentry.class = notAllowed
+refentry.class = refentry | local.refentry.class
+local.section.class = notAllowed
+section.class = section | local.section.class
+local.nav.class = notAllowed
+nav.class =
+  toc | lot | index | glossary | bibliography | local.nav.class
+# Redeclaration placeholder ............................................
+
+# For redeclaring entities that are declared after this point while
+# retaining their references to the entities that are declared before
+# this point
+
+# ......................................................................
+
+# Entities for element mixtures ........................................
+local.divcomponent.mix = notAllowed
+divcomponent.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | compound.class
+  | genobj.class
+  | descobj.class
+  | ndxterm.class
+  | beginpage
+  | forms.hook
+  | local.divcomponent.mix
+local.refcomponent.mix = notAllowed
+refcomponent.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | compound.class
+  | genobj.class
+  | descobj.class
+  | ndxterm.class
+  | beginpage
+  | forms.hook
+  | local.refcomponent.mix
+local.indexdivcomponent.mix = notAllowed
+indexdivcomponent.mix =
+  itemizedlist
+  | orderedlist
+  | variablelist
+  | simplelist
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | anchor
+  | remark
+  | link.char.class
+  | beginpage
+  | local.indexdivcomponent.mix
+local.refname.char.mix = notAllowed
+refname.char.mix = text | tech.char.class | local.refname.char.mix
+local.partcontent.mix = notAllowed
+partcontent.mix =
+  appendix.class
+  | chapter.class
+  | nav.class
+  | article.class
+  | preface
+  | refentry.class
+  | reference
+  | local.partcontent.mix
+local.refinline.char.mix = notAllowed
+refinline.char.mix =
+  text
+  | xref.char.class
+  | gen.char.class
+  | link.char.class
+  | tech.char.class
+  | base.char.class
+  | docinfo.char.class
+  | other.char.class
+  | ndxterm.class
+  | beginpage
+  | local.refinline.char.mix
+local.refclass.char.mix = notAllowed
+refclass.char.mix = text | application | local.refclass.char.mix
+# Redeclaration placeholder 2 ..........................................
+
+# For redeclaring entities that are declared after this point while
+# retaining their references to the entities that are declared before
+# this point
+
+# ......................................................................
+
+# Entities for content models ..........................................
+div.title.content = title, subtitle?, titleabbrev?
+bookcomponent.title.content = title, subtitle?, titleabbrev?
+sect.title.content = title, subtitle?, titleabbrev?
+refsect.title.content = title, subtitle?, titleabbrev?
+bookcomponent.content =
+  (divcomponent.mix+,
+   (sect1* | refentry.class* | simplesect* | section.class*))
+  | (sect1+ | refentry.class+ | simplesect+ | section.class+)
+# ......................................................................
+
+# Set and SetInfo ......................................................
+local.set.attrib = empty
+set.role.attrib = role.attrib
+# doc:A collection of books.
+set =
+  element set {
+    set.attlist,
+    div.title.content?,
+    setinfo?,
+    toc?,
+    (set | book.class)+,
+    setindex?
+  }
+# end of set.element
+
+# FPI: SGML formal public identifier
+set.attlist &=
+  attribute fpi { text }?,
+  status.attrib,
+  common.attrib,
+  set.role.attrib,
+  local.set.attrib
+# end of set.attlist
+
+# end of set.module
+local.setinfo.attrib = empty
+setinfo.role.attrib = role.attrib
+# doc:Meta-information for a Set.
+setinfo = element setinfo { setinfo.attlist, info.class+ }
+# end of setinfo.element
+
+# Contents: IDs of the ToC, Books, and SetIndex that comprise
+# the set, in the order of their appearance
+setinfo.attlist &=
+  attribute contents { xsd:IDREFS }?,
+  common.attrib,
+  setinfo.role.attrib,
+  local.setinfo.attrib
+# end of setinfo.attlist
+
+# end of setinfo.module
+
+# end of set.content.module
+
+# ......................................................................
+
+# Book and BookInfo ....................................................
+local.book.attrib = empty
+book.role.attrib = role.attrib
+# doc:A book.
+book =
+  element book {
+    book.attlist,
+    div.title.content?,
+    bookinfo?,
+    (dedication
+     | toc
+     | lot
+     | glossary
+     | bibliography
+     | preface
+     | chapter.class
+     | reference
+     | part
+     | article.class
+     | appendix.class
+     | index.class
+     | colophon)*
+  }
+# end of book.element
+
+# FPI: SGML formal public identifier
+book.attlist &=
+  attribute fpi { text }?,
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  book.role.attrib,
+  local.book.attrib
+# end of book.attlist
+
+# end of book.module
+local.bookinfo.attrib = empty
+bookinfo.role.attrib = role.attrib
+# doc:Meta-information for a Book.
+bookinfo = element bookinfo { bookinfo.attlist, info.class+ }
+# end of bookinfo.element
+
+# Contents: IDs of the ToC, LoTs, Prefaces, Parts, Chapters,
+# Appendixes, References, GLossary, Bibliography, and indexes
+# comprising the Book, in the order of their appearance
+bookinfo.attlist &=
+  attribute contents { xsd:IDREFS }?,
+  common.attrib,
+  bookinfo.role.attrib,
+  local.bookinfo.attrib
+# end of bookinfo.attlist
+
+# end of bookinfo.module
+
+# end of book.content.module
+
+# ......................................................................
+
+# Dedication, ToC, and LoT .............................................
+local.dedication.attrib = empty
+dedication.role.attrib = role.attrib
+# doc:A wrapper for the dedication section of a book.
+dedication =
+  element dedication {
+    dedication.attlist, sect.title.content?, legalnotice.mix+
+  }
+# end of dedication.element
+dedication.attlist &=
+  status.attrib,
+  common.attrib,
+  dedication.role.attrib,
+  local.dedication.attrib
+# end of dedication.attlist
+
+# end of dedication.module
+local.colophon.attrib = empty
+colophon.role.attrib = role.attrib
+# doc:Text at the back of a book describing facts about its production.
+colophon =
+  element colophon {
+    colophon.attlist, sect.title.content?, textobject.mix+
+  }
+# end of colophon.element
+colophon.attlist &=
+  status.attrib,
+  common.attrib,
+  colophon.role.attrib,
+  local.colophon.attrib
+# end of colophon.attlist
+
+# end of colophon.module
+local.toc.attrib = empty
+toc.role.attrib = role.attrib
+# doc:A table of contents.
+toc =
+  element toc {
+    toc.attlist,
+    beginpage?,
+    bookcomponent.title.content?,
+    tocfront*,
+    (tocpart | tocchap)*,
+    tocback*
+  }
+# end of toc.element
+toc.attlist &=
+  pagenum.attrib, common.attrib, toc.role.attrib, local.toc.attrib
+# end of toc.attlist
+
+# end of toc.module
+local.tocfront.attrib = empty
+tocfront.role.attrib = role.attrib
+# doc:An entry in a table of contents for a front matter component.
+tocfront = element tocfront { tocfront.attlist, para.char.mix* }
+# end of tocfront.element
+
+# to element that this entry represents
+tocfront.attlist &=
+  label.attrib,
+  linkend.attrib,
+  pagenum.attrib,
+  common.attrib,
+  tocfront.role.attrib,
+  local.tocfront.attrib
+# end of tocfront.attlist
+
+# end of tocfront.module
+local.tocentry.attrib = empty
+tocentry.role.attrib = role.attrib
+# doc:A component title in a table of contents.
+tocentry = element tocentry { tocentry.attlist, para.char.mix* }
+# end of tocentry.element
+
+# to element that this entry represents
+tocentry.attlist &=
+  linkend.attrib,
+  pagenum.attrib,
+  common.attrib,
+  tocentry.role.attrib,
+  local.tocentry.attrib
+# end of tocentry.attlist
+
+# end of tocentry.module
+local.tocpart.attrib = empty
+tocpart.role.attrib = role.attrib
+# doc:An entry in a table of contents for a part of a book.
+tocpart = element tocpart { tocpart.attlist, tocentry+, tocchap* }
+# end of tocpart.element
+tocpart.attlist &=
+  common.attrib, tocpart.role.attrib, local.tocpart.attrib
+# end of tocpart.attlist
+
+# end of tocpart.module
+local.tocchap.attrib = empty
+tocchap.role.attrib = role.attrib
+# doc:An entry in a table of contents for a component in the body of a document.
+tocchap = element tocchap { tocchap.attlist, tocentry+, toclevel1* }
+# end of tocchap.element
+tocchap.attlist &=
+  label.attrib, common.attrib, tocchap.role.attrib, local.tocchap.attrib
+# end of tocchap.attlist
+
+# end of tocchap.module
+local.toclevel1.attrib = empty
+toclevel1.role.attrib = role.attrib
+# doc:A top-level entry within a table of contents entry for a chapter-like component.
+toclevel1 =
+  element toclevel1 { toclevel1.attlist, tocentry+, toclevel2* }
+# end of toclevel1.element
+toclevel1.attlist &=
+  common.attrib, toclevel1.role.attrib, local.toclevel1.attrib
+# end of toclevel1.attlist
+
+# end of toclevel1.module
+local.toclevel2.attrib = empty
+toclevel2.role.attrib = role.attrib
+# doc:A second-level entry within a table of contents entry for a chapter-like component.
+toclevel2 =
+  element toclevel2 { toclevel2.attlist, tocentry+, toclevel3* }
+# end of toclevel2.element
+toclevel2.attlist &=
+  common.attrib, toclevel2.role.attrib, local.toclevel2.attrib
+# end of toclevel2.attlist
+
+# end of toclevel2.module
+local.toclevel3.attrib = empty
+toclevel3.role.attrib = role.attrib
+# doc:A third-level entry within a table of contents entry for a chapter-like component.
+toclevel3 =
+  element toclevel3 { toclevel3.attlist, tocentry+, toclevel4* }
+# end of toclevel3.element
+toclevel3.attlist &=
+  common.attrib, toclevel3.role.attrib, local.toclevel3.attrib
+# end of toclevel3.attlist
+
+# end of toclevel3.module
+local.toclevel4.attrib = empty
+toclevel4.role.attrib = role.attrib
+# doc:A fourth-level entry within a table of contents entry for a chapter-like component.
+toclevel4 =
+  element toclevel4 { toclevel4.attlist, tocentry+, toclevel5* }
+# end of toclevel4.element
+toclevel4.attlist &=
+  common.attrib, toclevel4.role.attrib, local.toclevel4.attrib
+# end of toclevel4.attlist
+
+# end of toclevel4.module
+local.toclevel5.attrib = empty
+toclevel5.role.attrib = role.attrib
+# doc:A fifth-level entry within a table of contents entry for a chapter-like component.
+toclevel5 = element toclevel5 { toclevel5.attlist, tocentry+ }
+# end of toclevel5.element
+toclevel5.attlist &=
+  common.attrib, toclevel5.role.attrib, local.toclevel5.attrib
+# end of toclevel5.attlist
+
+# end of toclevel5.module
+local.tocback.attrib = empty
+tocback.role.attrib = role.attrib
+# doc:An entry in a table of contents for a back matter component.
+tocback = element tocback { tocback.attlist, para.char.mix* }
+# end of tocback.element
+
+# to element that this entry represents
+tocback.attlist &=
+  label.attrib,
+  linkend.attrib,
+  pagenum.attrib,
+  common.attrib,
+  tocback.role.attrib,
+  local.tocback.attrib
+# end of tocback.attlist
+
+# end of tocback.module
+
+# end of toc.content.module
+local.lot.attrib = empty
+lot.role.attrib = role.attrib
+# doc:A list of the titles of formal objects (as tables or figures) in a document.
+lot =
+  element lot {
+    lot.attlist, beginpage?, bookcomponent.title.content?, lotentry*
+  }
+# end of lot.element
+lot.attlist &=
+  label.attrib, common.attrib, lot.role.attrib, local.lot.attrib
+# end of lot.attlist
+
+# end of lot.module
+local.lotentry.attrib = empty
+lotentry.role.attrib = role.attrib
+# doc:An entry in a list of titles.
+lotentry = element lotentry { lotentry.attlist, para.char.mix* }
+# end of lotentry.element
+
+# SrcCredit: Information about the source of the entry,
+# as for a list of illustrations
+
+# linkend: to element that this entry represents
+lotentry.attlist &=
+  linkend.attrib,
+  pagenum.attrib,
+  attribute srccredit { text }?,
+  common.attrib,
+  lotentry.role.attrib,
+  local.lotentry.attrib
+# end of lotentry.attlist
+
+# end of lotentry.module
+
+# end of lot.content.module
+
+# ......................................................................
+
+# Appendix, Chapter, Part, Preface, Reference, PartIntro ...............
+local.appendix.attrib = empty
+appendix.role.attrib = role.attrib
+# doc:An appendix in a Book or Article.
+appendix =
+  element appendix {
+    appendix.attlist,
+    beginpage?,
+    appendixinfo?,
+    bookcomponent.title.content,
+    nav.class*,
+    tocchap?,
+    bookcomponent.content,
+    nav.class*
+  }
+# end of appendix.element
+appendix.attlist &=
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  appendix.role.attrib,
+  local.appendix.attrib
+# end of appendix.attlist
+
+# end of appendix.module
+local.chapter.attrib = empty
+chapter.role.attrib = role.attrib
+# doc:A chapter, as of a book.
+chapter =
+  element chapter {
+    chapter.attlist,
+    beginpage?,
+    chapterinfo?,
+    bookcomponent.title.content,
+    nav.class*,
+    tocchap?,
+    bookcomponent.content,
+    nav.class*
+  }
+# end of chapter.element
+chapter.attlist &=
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  chapter.role.attrib,
+  local.chapter.attrib
+# end of chapter.attlist
+
+# end of chapter.module
+
+# Note that Part was to have its content model reduced in V4.5.  This
+# change will not be made after all.
+local.part.attrib = empty
+part.role.attrib = role.attrib
+# doc:A division in a book.
+part =
+  element part {
+    part.attlist,
+    beginpage?,
+    partinfo?,
+    bookcomponent.title.content,
+    partintro?,
+    partcontent.mix+
+  }
+# end of part.element
+part.attlist &=
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  part.role.attrib,
+  local.part.attrib
+# end of part.attlist
+
+# ELEMENT PartIntro (defined below)
+
+# end of part.module
+local.preface.attrib = empty
+preface.role.attrib = role.attrib
+# doc:Introductory matter preceding the first chapter of a book.
+preface =
+  element preface {
+    preface.attlist,
+    beginpage?,
+    prefaceinfo?,
+    bookcomponent.title.content,
+    nav.class*,
+    tocchap?,
+    bookcomponent.content,
+    nav.class*
+  }
+# end of preface.element
+preface.attlist &=
+  status.attrib,
+  common.attrib,
+  preface.role.attrib,
+  local.preface.attrib
+# end of preface.attlist
+
+# end of preface.module
+local.reference.attrib = empty
+reference.role.attrib = role.attrib
+# doc:A collection of reference entries.
+reference =
+  element reference {
+    reference.attlist,
+    beginpage?,
+    referenceinfo?,
+    bookcomponent.title.content,
+    partintro?,
+    refentry.class+
+  }
+# end of reference.element
+reference.attlist &=
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  reference.role.attrib,
+  local.reference.attrib
+# end of reference.attlist
+
+# ELEMENT PartIntro (defined below)
+
+# end of reference.module
+local.partintro.attrib = empty
+partintro.role.attrib = role.attrib
+# doc:An introduction to the contents of a part.
+partintro =
+  element partintro {
+    partintro.attlist, div.title.content?, bookcomponent.content
+  }
+# end of partintro.element
+partintro.attlist &=
+  label.attrib,
+  common.attrib,
+  partintro.role.attrib,
+  local.partintro.attrib
+# end of partintro.attlist
+
+# end of partintro.module
+
+# ......................................................................
+
+# Other Info elements ..................................................
+local.appendixinfo.attrib = empty
+appendixinfo.role.attrib = role.attrib
+# doc:Meta-information for an Appendix.
+appendixinfo =
+  element appendixinfo { appendixinfo.attlist, info.class+ }
+# end of appendixinfo.element
+appendixinfo.attlist &=
+  common.attrib, appendixinfo.role.attrib, local.appendixinfo.attrib
+# end of appendixinfo.attlist
+
+# end of appendixinfo.module
+local.bibliographyinfo.attrib = empty
+bibliographyinfo.role.attrib = role.attrib
+# doc:Meta-information for a Bibliography.
+bibliographyinfo =
+  element bibliographyinfo { bibliographyinfo.attlist, info.class+ }
+# end of bibliographyinfo.element
+bibliographyinfo.attlist &=
+  common.attrib,
+  bibliographyinfo.role.attrib,
+  local.bibliographyinfo.attrib
+# end of bibliographyinfo.attlist
+
+# end of bibliographyinfo.module
+local.chapterinfo.attrib = empty
+chapterinfo.role.attrib = role.attrib
+# doc:Meta-information for a Chapter.
+chapterinfo = element chapterinfo { chapterinfo.attlist, info.class+ }
+# end of chapterinfo.element
+chapterinfo.attlist &=
+  common.attrib, chapterinfo.role.attrib, local.chapterinfo.attrib
+# end of chapterinfo.attlist
+
+# end of chapterinfo.module
+local.glossaryinfo.attrib = empty
+glossaryinfo.role.attrib = role.attrib
+# doc:Meta-information for a Glossary.
+glossaryinfo =
+  element glossaryinfo { glossaryinfo.attlist, info.class+ }
+# end of glossaryinfo.element
+glossaryinfo.attlist &=
+  common.attrib, glossaryinfo.role.attrib, local.glossaryinfo.attrib
+# end of glossaryinfo.attlist
+
+# end of glossaryinfo.module
+local.indexinfo.attrib = empty
+indexinfo.role.attrib = role.attrib
+# doc:Meta-information for an Index.
+indexinfo = element indexinfo { indexinfo.attlist, info.class+ }
+# end of indexinfo.element
+indexinfo.attlist &=
+  common.attrib, indexinfo.role.attrib, local.indexinfo.attrib
+# end of indexinfo.attlist
+
+# end of indexinfo.module
+local.setindexinfo.attrib = empty
+setindexinfo.role.attrib = role.attrib
+# doc:Meta-information for a SetIndex.
+setindexinfo =
+  element setindexinfo { setindexinfo.attlist, info.class+ }
+# end of setindexinfo.element
+setindexinfo.attlist &=
+  common.attrib, setindexinfo.role.attrib, local.setindexinfo.attrib
+# end of setindexinfo.attlist
+
+# end of setindexinfo.module
+local.partinfo.attrib = empty
+partinfo.role.attrib = role.attrib
+# doc:Meta-information for a Part.
+partinfo = element partinfo { partinfo.attlist, info.class+ }
+# end of partinfo.element
+partinfo.attlist &=
+  common.attrib, partinfo.role.attrib, local.partinfo.attrib
+# end of partinfo.attlist
+
+# end of partinfo.module
+local.prefaceinfo.attrib = empty
+prefaceinfo.role.attrib = role.attrib
+# doc:Meta-information for a Preface.
+prefaceinfo = element prefaceinfo { prefaceinfo.attlist, info.class+ }
+# end of prefaceinfo.element
+prefaceinfo.attlist &=
+  common.attrib, prefaceinfo.role.attrib, local.prefaceinfo.attrib
+# end of prefaceinfo.attlist
+
+# end of prefaceinfo.module
+local.refentryinfo.attrib = empty
+refentryinfo.role.attrib = role.attrib
+# doc:Meta-information for a Refentry.
+refentryinfo =
+  element refentryinfo { refentryinfo.attlist, info.class+ }
+# end of refentryinfo.element
+refentryinfo.attlist &=
+  common.attrib, refentryinfo.role.attrib, local.refentryinfo.attrib
+# end of refentryinfo.attlist
+
+# end of refentryinfo.module
+local.refsectioninfo.attrib = empty
+refsectioninfo.role.attrib = role.attrib
+# doc:Meta-information for a refsection.
+refsectioninfo =
+  element refsectioninfo { refsectioninfo.attlist, info.class+ }
+# end of refsectioninfo.element
+refsectioninfo.attlist &=
+  common.attrib, refsectioninfo.role.attrib, local.refsectioninfo.attrib
+# end of refsectioninfo.attlist
+
+# end of refsectioninfo.module
+local.refsect1info.attrib = empty
+refsect1info.role.attrib = role.attrib
+# doc:Meta-information for a RefSect1.
+refsect1info =
+  element refsect1info { refsect1info.attlist, info.class+ }
+# end of refsect1info.element
+refsect1info.attlist &=
+  common.attrib, refsect1info.role.attrib, local.refsect1info.attrib
+# end of refsect1info.attlist
+
+# end of refsect1info.module
+local.refsect2info.attrib = empty
+refsect2info.role.attrib = role.attrib
+# doc:Meta-information for a RefSect2.
+refsect2info =
+  element refsect2info { refsect2info.attlist, info.class+ }
+# end of refsect2info.element
+refsect2info.attlist &=
+  common.attrib, refsect2info.role.attrib, local.refsect2info.attrib
+# end of refsect2info.attlist
+
+# end of refsect2info.module
+local.refsect3info.attrib = empty
+refsect3info.role.attrib = role.attrib
+# doc:Meta-information for a RefSect3.
+refsect3info =
+  element refsect3info { refsect3info.attlist, info.class+ }
+# end of refsect3info.element
+refsect3info.attlist &=
+  common.attrib, refsect3info.role.attrib, local.refsect3info.attrib
+# end of refsect3info.attlist
+
+# end of refsect3info.module
+local.refsynopsisdivinfo.attrib = empty
+refsynopsisdivinfo.role.attrib = role.attrib
+# doc:Meta-information for a RefSynopsisDiv.
+refsynopsisdivinfo =
+  element refsynopsisdivinfo { refsynopsisdivinfo.attlist, info.class+ }
+# end of refsynopsisdivinfo.element
+refsynopsisdivinfo.attlist &=
+  common.attrib,
+  refsynopsisdivinfo.role.attrib,
+  local.refsynopsisdivinfo.attrib
+# end of refsynopsisdivinfo.attlist
+
+# end of refsynopsisdivinfo.module
+local.referenceinfo.attrib = empty
+referenceinfo.role.attrib = role.attrib
+# doc:Meta-information for a Reference.
+referenceinfo =
+  element referenceinfo { referenceinfo.attlist, info.class+ }
+# end of referenceinfo.element
+referenceinfo.attlist &=
+  common.attrib, referenceinfo.role.attrib, local.referenceinfo.attrib
+# end of referenceinfo.attlist
+
+# end of referenceinfo.module
+local.sect1info.attrib = empty
+sect1info.role.attrib = role.attrib
+# doc:Meta-information for a Sect1.
+sect1info = element sect1info { sect1info.attlist, info.class+ }
+# end of sect1info.element
+sect1info.attlist &=
+  common.attrib, sect1info.role.attrib, local.sect1info.attrib
+# end of sect1info.attlist
+local.sect2info.attrib = empty
+sect2info.role.attrib = role.attrib
+# doc:Meta-information for a Sect2.
+sect2info = element sect2info { sect2info.attlist, info.class+ }
+# end of sect2info.element
+sect2info.attlist &=
+  common.attrib, sect2info.role.attrib, local.sect2info.attrib
+# end of sect2info.attlist
+local.sect3info.attrib = empty
+sect3info.role.attrib = role.attrib
+# doc:Meta-information for a Sect3.
+sect3info = element sect3info { sect3info.attlist, info.class+ }
+# end of sect3info.element
+sect3info.attlist &=
+  common.attrib, sect3info.role.attrib, local.sect3info.attrib
+# end of sect3info.attlist
+local.sect4info.attrib = empty
+sect4info.role.attrib = role.attrib
+# doc:Meta-information for a Sect4.
+sect4info = element sect4info { sect4info.attlist, info.class+ }
+# end of sect4info.element
+sect4info.attlist &=
+  common.attrib, sect4info.role.attrib, local.sect4info.attrib
+# end of sect4info.attlist
+local.sect5info.attrib = empty
+sect5info.role.attrib = role.attrib
+# doc:Meta-information for a Sect5.
+sect5info = element sect5info { sect5info.attlist, info.class+ }
+# end of sect5info.element
+sect5info.attlist &=
+  common.attrib, sect5info.role.attrib, local.sect5info.attrib
+# end of sect5info.attlist
+
+# ......................................................................
+
+# Section (parallel to Sect*) .........................................
+local.section.attrib = empty
+section.role.attrib = role.attrib
+# doc:A recursive section.
+section =
+  element section {
+    section.attlist,
+    sectioninfo?,
+    sect.title.content,
+    nav.class*,
+    ((divcomponent.mix+,
+      (refentry.class* | section.class* | simplesect*))
+     | refentry.class+
+     | section.class+
+     | simplesect+),
+    nav.class*
+  }
+# end of section.element
+section.attlist &=
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  section.role.attrib,
+  local.section.attrib
+# end of section.attlist
+
+# end of section.module
+sectioninfo.role.attrib = role.attrib
+local.sectioninfo.attrib = empty
+# doc:Meta-information for a recursive section.
+sectioninfo = element sectioninfo { sectioninfo.attlist, info.class+ }
+# end of sectioninfo.element
+sectioninfo.attlist &=
+  common.attrib, sectioninfo.role.attrib, local.sectioninfo.attrib
+# end of sectioninfo.attlist
+
+# end of sectioninfo.module
+
+# end of section.content.module
+
+# ......................................................................
+
+# Sect1, Sect2, Sect3, Sect4, Sect5 ....................................
+local.sect1.attrib = empty
+sect1.role.attrib = role.attrib
+# doc:A top-level section of document.
+sect1 =
+  element sect1 {
+    sect1.attlist,
+    sect1info?,
+    sect.title.content,
+    nav.class*,
+    ((divcomponent.mix+, (refentry.class* | sect2* | simplesect*))
+     | refentry.class+
+     | sect2+
+     | simplesect+),
+    nav.class*
+  }
+# end of sect1.element
+
+# Renderas: Indicates the format in which the heading should
+# appear
+sect1.attlist &=
+  attribute renderas { "sect2" | "sect3" | "sect4" | "sect5" }?,
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  sect1.role.attrib,
+  local.sect1.attrib
+# end of sect1.attlist
+
+# end of sect1.module
+local.sect2.attrib = empty
+sect2.role.attrib = role.attrib
+# doc:A subsection within a Sect1.
+sect2 =
+  element sect2 {
+    sect2.attlist,
+    sect2info?,
+    sect.title.content,
+    nav.class*,
+    ((divcomponent.mix+, (refentry.class* | sect3* | simplesect*))
+     | refentry.class+
+     | sect3+
+     | simplesect+),
+    nav.class*
+  }
+# end of sect2.element
+
+# Renderas: Indicates the format in which the heading should
+# appear
+sect2.attlist &=
+  attribute renderas { "sect1" | "sect3" | "sect4" | "sect5" }?,
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  sect2.role.attrib,
+  local.sect2.attrib
+# end of sect2.attlist
+
+# end of sect2.module
+local.sect3.attrib = empty
+sect3.role.attrib = role.attrib
+# doc:A subsection within a Sect2.
+sect3 =
+  element sect3 {
+    sect3.attlist,
+    sect3info?,
+    sect.title.content,
+    nav.class*,
+    ((divcomponent.mix+, (refentry.class* | sect4* | simplesect*))
+     | refentry.class+
+     | sect4+
+     | simplesect+),
+    nav.class*
+  }
+# end of sect3.element
+
+# Renderas: Indicates the format in which the heading should
+# appear
+sect3.attlist &=
+  attribute renderas { "sect1" | "sect2" | "sect4" | "sect5" }?,
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  sect3.role.attrib,
+  local.sect3.attrib
+# end of sect3.attlist
+
+# end of sect3.module
+local.sect4.attrib = empty
+sect4.role.attrib = role.attrib
+# doc:A subsection within a Sect3.
+sect4 =
+  element sect4 {
+    sect4.attlist,
+    sect4info?,
+    sect.title.content,
+    nav.class*,
+    ((divcomponent.mix+, (refentry.class* | sect5* | simplesect*))
+     | refentry.class+
+     | sect5+
+     | simplesect+),
+    nav.class*
+  }
+# end of sect4.element
+
+# Renderas: Indicates the format in which the heading should
+# appear
+sect4.attlist &=
+  attribute renderas { "sect1" | "sect2" | "sect3" | "sect5" }?,
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  sect4.role.attrib,
+  local.sect4.attrib
+# end of sect4.attlist
+
+# end of sect4.module
+local.sect5.attrib = empty
+sect5.role.attrib = role.attrib
+# doc:A subsection within a Sect4.
+sect5 =
+  element sect5 {
+    sect5.attlist,
+    sect5info?,
+    sect.title.content,
+    nav.class*,
+    ((divcomponent.mix+, (refentry.class* | simplesect*))
+     | refentry.class+
+     | simplesect+),
+    nav.class*
+  }
+# end of sect5.element
+
+# Renderas: Indicates the format in which the heading should
+# appear
+sect5.attlist &=
+  attribute renderas { "sect1" | "sect2" | "sect3" | "sect4" }?,
+  label.attrib,
+  status.attrib,
+  common.attrib,
+  sect5.role.attrib,
+  local.sect5.attrib
+# end of sect5.attlist
+
+# end of sect5.module
+local.simplesect.attrib = empty
+simplesect.role.attrib = role.attrib
+# doc:A section of a document with no subdivisions.
+simplesect =
+  element simplesect {
+    simplesect.attlist, sect.title.content, divcomponent.mix+
+  }
+# end of simplesect.element
+simplesect.attlist &=
+  common.attrib, simplesect.role.attrib, local.simplesect.attrib
+# end of simplesect.attlist
+
+# end of simplesect.module
+
+# ......................................................................
+
+# Bibliography .........................................................
+local.bibliography.attrib = empty
+bibliography.role.attrib = role.attrib
+# doc:A bibliography.
+bibliography =
+  element bibliography {
+    bibliography.attlist,
+    bibliographyinfo?,
+    bookcomponent.title.content?,
+    component.mix*,
+    (bibliodiv+ | (biblioentry | bibliomixed)+)
+  }
+# end of bibliography.element
+bibliography.attlist &=
+  status.attrib,
+  common.attrib,
+  bibliography.role.attrib,
+  local.bibliography.attrib
+# end of bibliography.attlist
+
+# end of bibliography.module
+local.bibliodiv.attrib = empty
+bibliodiv.role.attrib = role.attrib
+# doc:A section of a Bibliography.
+bibliodiv =
+  element bibliodiv {
+    bibliodiv.attlist,
+    sect.title.content?,
+    component.mix*,
+    (biblioentry | bibliomixed)+
+  }
+# end of bibliodiv.element
+bibliodiv.attlist &=
+  status.attrib,
+  common.attrib,
+  bibliodiv.role.attrib,
+  local.bibliodiv.attrib
+# end of bibliodiv.attlist
+
+# end of bibliodiv.module
+
+# end of bibliography.content.module
+
+# ......................................................................
+
+# Glossary .............................................................
+local.glossary.attrib = empty
+glossary.role.attrib = role.attrib
+# doc:A glossary.
+glossary =
+  element glossary {
+    glossary.attlist,
+    glossaryinfo?,
+    bookcomponent.title.content?,
+    component.mix*,
+    (glossdiv+ | glossentry+),
+    bibliography?
+  }
+# end of glossary.element
+glossary.attlist &=
+  status.attrib,
+  common.attrib,
+  glossary.role.attrib,
+  local.glossary.attrib
+# end of glossary.attlist
+
+# end of glossary.module
+local.glossdiv.attrib = empty
+glossdiv.role.attrib = role.attrib
+# doc:A division in a Glossary.
+glossdiv =
+  element glossdiv {
+    glossdiv.attlist, sect.title.content, component.mix*, glossentry+
+  }
+# end of glossdiv.element
+glossdiv.attlist &=
+  status.attrib,
+  common.attrib,
+  glossdiv.role.attrib,
+  local.glossdiv.attrib
+# end of glossdiv.attlist
+
+# end of glossdiv.module
+
+# end of glossary.content.module
+
+# ......................................................................
+
+# Index and SetIndex ...................................................
+local.indexes.attrib = empty
+indexes.role.attrib = role.attrib
+# doc:An index.
+index =
+  element index {
+    index.attlist,
+    indexinfo?,
+    bookcomponent.title.content?,
+    component.mix*,
+    (indexdiv* | indexentry*)
+  }
+# end of index.element
+index.attlist &=
+  attribute type { text }?,
+  common.attrib,
+  indexes.role.attrib,
+  local.indexes.attrib
+# end of index.attlist
+
+# doc:An index to a set of books.
+setindex =
+  element setindex {
+    setindex.attlist,
+    setindexinfo?,
+    bookcomponent.title.content?,
+    component.mix*,
+    (indexdiv* | indexentry*)
+  }
+# end of setindex.element
+setindex.attlist &=
+  common.attrib, indexes.role.attrib, local.indexes.attrib
+# end of setindex.attlist
+
+# end of indexes.module
+
+# SegmentedList in this content is useful for marking up permuted
+# indices.
+local.indexdiv.attrib = empty
+indexdiv.role.attrib = role.attrib
+# doc:A division in an index.
+indexdiv =
+  element indexdiv {
+    indexdiv.attlist,
+    sect.title.content?,
+    (indexdivcomponent.mix*, (indexentry+ | segmentedlist))
+  }
+# end of indexdiv.element
+indexdiv.attlist &=
+  common.attrib, indexdiv.role.attrib, local.indexdiv.attrib
+# end of indexdiv.attlist
+
+# end of indexdiv.module
+
+# Index entries appear in the index, not the text.
+local.indexentry.attrib = empty
+indexentry.role.attrib = role.attrib
+# doc:An entry in an index.
+indexentry =
+  element indexentry {
+    indexentry.attlist,
+    primaryie,
+    (seeie | seealsoie)*,
+    (secondaryie, (seeie | seealsoie | tertiaryie)*)*
+  }
+# end of indexentry.element
+indexentry.attlist &=
+  common.attrib, indexentry.role.attrib, local.indexentry.attrib
+# end of indexentry.attlist
+
+# end of indexentry.module
+local.primsecterie.attrib = empty
+primsecterie.role.attrib = role.attrib
+# doc:A primary term in an index entry, not in the text.
+primaryie = element primaryie { primaryie.attlist, ndxterm.char.mix* }
+# end of primaryie.element
+
+# to IndexTerms that these entries represent
+primaryie.attlist &=
+  linkends.attrib,
+  common.attrib,
+  primsecterie.role.attrib,
+  local.primsecterie.attrib
+# end of primaryie.attlist
+
+# doc:A secondary term in an index entry, rather than in the text.
+secondaryie =
+  element secondaryie { secondaryie.attlist, ndxterm.char.mix* }
+# end of secondaryie.element
+
+# to IndexTerms that these entries represent
+secondaryie.attlist &=
+  linkends.attrib,
+  common.attrib,
+  primsecterie.role.attrib,
+  local.primsecterie.attrib
+# end of secondaryie.attlist
+
+# doc:A tertiary term in an index entry, rather than in the text.
+tertiaryie =
+  element tertiaryie { tertiaryie.attlist, ndxterm.char.mix* }
+# end of tertiaryie.element
+
+# to IndexTerms that these entries represent
+tertiaryie.attlist &=
+  linkends.attrib,
+  common.attrib,
+  primsecterie.role.attrib,
+  local.primsecterie.attrib
+# end of tertiaryie.attlist
+
+# end of primsecterie.module
+local.seeie.attrib = empty
+seeie.role.attrib = role.attrib
+# doc:A See entry in an index, rather than in the text.
+seeie = element seeie { seeie.attlist, ndxterm.char.mix* }
+# end of seeie.element
+
+# to IndexEntry to look up
+seeie.attlist &=
+  linkend.attrib, common.attrib, seeie.role.attrib, local.seeie.attrib
+# end of seeie.attlist
+
+# end of seeie.module
+local.seealsoie.attrib = empty
+seealsoie.role.attrib = role.attrib
+# doc:A See also entry in an index, rather than in the text.
+seealsoie = element seealsoie { seealsoie.attlist, ndxterm.char.mix* }
+# end of seealsoie.element
+
+# to related IndexEntries
+seealsoie.attlist &=
+  linkends.attrib,
+  common.attrib,
+  seealsoie.role.attrib,
+  local.seealsoie.attrib
+# end of seealsoie.attlist
+
+# end of seealsoie.module
+
+# end of index.content.module
+
+# ......................................................................
+
+# RefEntry .............................................................
+local.refentry.attrib = empty
+refentry.role.attrib = role.attrib
+# doc:A reference page (originally a UNIX man-style reference page).
+refentry =
+  element refentry {
+    refentry.attlist,
+    beginpage?,
+    ndxterm.class*,
+    refentryinfo?,
+    refmeta?,
+    (remark | link.char.class)*,
+    refnamediv+,
+    refsynopsisdiv?,
+    (refsect1+ | refsection+)
+  }
+# end of refentry.element
+refentry.attlist &=
+  status.attrib,
+  common.attrib,
+  refentry.role.attrib,
+  local.refentry.attrib
+# end of refentry.attlist
+
+# end of refentry.module
+local.refmeta.attrib = empty
+refmeta.role.attrib = role.attrib
+# doc:Meta-information for a reference entry.
+refmeta =
+  element refmeta {
+    refmeta.attlist,
+    ndxterm.class*,
+    refentrytitle,
+    manvolnum?,
+    refmiscinfo*,
+    ndxterm.class*
+  }
+# end of refmeta.element
+refmeta.attlist &=
+  common.attrib, refmeta.role.attrib, local.refmeta.attrib
+# end of refmeta.attlist
+
+# end of refmeta.module
+local.refmiscinfo.attrib = empty
+refmiscinfo.role.attrib = role.attrib
+# doc:Meta-information for a reference entry other than the title and volume number.
+refmiscinfo =
+  element refmiscinfo { refmiscinfo.attlist, docinfo.char.mix* }
+# end of refmiscinfo.element
+
+# Class: Freely assignable parameter; no default
+refmiscinfo.attlist &=
+  attribute class { text }?,
+  common.attrib,
+  refmiscinfo.role.attrib,
+  local.refmiscinfo.attrib
+# end of refmiscinfo.attlist
+
+# end of refmiscinfo.module
+local.refnamediv.attrib = empty
+refnamediv.role.attrib = role.attrib
+# doc:The name, purpose, and classification of a reference page.
+refnamediv =
+  element refnamediv {
+    refnamediv.attlist,
+    refdescriptor?,
+    refname+,
+    refpurpose,
+    refclass*,
+    (remark | link.char.class)*
+  }
+# end of refnamediv.element
+refnamediv.attlist &=
+  common.attrib, refnamediv.role.attrib, local.refnamediv.attrib
+# end of refnamediv.attlist
+
+# end of refnamediv.module
+local.refdescriptor.attrib = empty
+refdescriptor.role.attrib = role.attrib
+# doc:A description of the topic of a reference page.
+refdescriptor =
+  element refdescriptor { refdescriptor.attlist, refname.char.mix* }
+# end of refdescriptor.element
+refdescriptor.attlist &=
+  common.attrib, refdescriptor.role.attrib, local.refdescriptor.attrib
+# end of refdescriptor.attlist
+
+# end of refdescriptor.module
+local.refname.attrib = empty
+refname.role.attrib = role.attrib
+# doc:The name of (one of) the subject(s) of a reference page.
+refname = element refname { refname.attlist, refname.char.mix* }
+# end of refname.element
+refname.attlist &=
+  common.attrib, refname.role.attrib, local.refname.attrib
+# end of refname.attlist
+
+# end of refname.module
+local.refpurpose.attrib = empty
+refpurpose.role.attrib = role.attrib
+# doc:A short (one sentence) synopsis of the topic of a reference page.
+refpurpose =
+  element refpurpose { refpurpose.attlist, refinline.char.mix* }
+# end of refpurpose.element
+refpurpose.attlist &=
+  common.attrib, refpurpose.role.attrib, local.refpurpose.attrib
+# end of refpurpose.attlist
+
+# end of refpurpose.module
+local.refclass.attrib = empty
+refclass.role.attrib = role.attrib
+# doc:The scope or other indication of applicability of a reference entry.
+refclass = element refclass { refclass.attlist, refclass.char.mix* }
+# end of refclass.element
+refclass.attlist &=
+  common.attrib, refclass.role.attrib, local.refclass.attrib
+# end of refclass.attlist
+
+# end of refclass.module
+local.refsynopsisdiv.attrib = empty
+refsynopsisdiv.role.attrib = role.attrib
+# doc:A syntactic synopsis of the subject of the reference page.
+refsynopsisdiv =
+  element refsynopsisdiv {
+    refsynopsisdiv.attlist,
+    refsynopsisdivinfo?,
+    refsect.title.content?,
+    ((refcomponent.mix+, refsect2*) | refsect2+)
+  }
+# end of refsynopsisdiv.element
+refsynopsisdiv.attlist &=
+  common.attrib, refsynopsisdiv.role.attrib, local.refsynopsisdiv.attrib
+# end of refsynopsisdiv.attlist
+
+# end of refsynopsisdiv.module
+local.refsection.attrib = empty
+refsection.role.attrib = role.attrib
+# doc:A recursive section in a refentry.
+refsection =
+  element refsection {
+    refsection.attlist,
+    refsectioninfo?,
+    refsect.title.content,
+    ((refcomponent.mix+, refsection*) | refsection+)
+  }
+# end of refsection.element
+refsection.attlist &=
+  status.attrib,
+  common.attrib,
+  refsection.role.attrib,
+  local.refsection.attrib
+# end of refsection.attlist
+
+# end of refsection.module
+local.refsect1.attrib = empty
+refsect1.role.attrib = role.attrib
+# doc:A major subsection of a reference entry.
+refsect1 =
+  element refsect1 {
+    refsect1.attlist,
+    refsect1info?,
+    refsect.title.content,
+    ((refcomponent.mix+, refsect2*) | refsect2+)
+  }
+# end of refsect1.element
+refsect1.attlist &=
+  status.attrib,
+  common.attrib,
+  refsect1.role.attrib,
+  local.refsect1.attrib
+# end of refsect1.attlist
+
+# end of refsect1.module
+local.refsect2.attrib = empty
+refsect2.role.attrib = role.attrib
+# doc:A subsection of a RefSect1.
+refsect2 =
+  element refsect2 {
+    refsect2.attlist,
+    refsect2info?,
+    refsect.title.content,
+    ((refcomponent.mix+, refsect3*) | refsect3+)
+  }
+# end of refsect2.element
+refsect2.attlist &=
+  status.attrib,
+  common.attrib,
+  refsect2.role.attrib,
+  local.refsect2.attrib
+# end of refsect2.attlist
+
+# end of refsect2.module
+local.refsect3.attrib = empty
+refsect3.role.attrib = role.attrib
+# doc:A subsection of a RefSect2.
+refsect3 =
+  element refsect3 {
+    refsect3.attlist,
+    refsect3info?,
+    refsect.title.content,
+    refcomponent.mix+
+  }
+# end of refsect3.element
+refsect3.attlist &=
+  status.attrib,
+  common.attrib,
+  refsect3.role.attrib,
+  local.refsect3.attrib
+# end of refsect3.attlist
+
+# end of refsect3.module
+
+# end of refentry.content.module
+
+# ......................................................................
+
+# Article ..............................................................
+
+# An Article is a chapter-level, stand-alone document that is often,
+# but need not be, collected into a Book.
+local.article.attrib = empty
+article.role.attrib = role.attrib
+# doc:An article.
+article =
+  element article {
+    article.attlist,
+    div.title.content?,
+    articleinfo?,
+    tocchap?,
+    lot*,
+    bookcomponent.content,
+    (nav.class | appendix.class | colophon | ackno)*
+  }
+# end of article.element
+
+# Class: Indicates the type of a particular article;
+# all articles have the same structure and general purpose.
+# No default.
+
+# ParentBook: ID of the enclosing Book
+article.attlist &=
+  attribute class {
+    "journalarticle"
+    | "productsheet"
+    | "whitepaper"
+    | "techreport"
+    | "specification"
+    | "faq"
+  }?,
+  attribute parentbook { xsd:IDREF }?,
+  status.attrib,
+  common.attrib,
+  article.role.attrib,
+  local.article.attrib
+# end of article.attlist
+
+# end of article.module
+
+# End of DocBook document hierarchy module V4.5 ........................
+
+# ......................................................................
Index: /branches/new-random/doc/src/docbook-rng-4.5/dbhierx.rng
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/dbhierx.rng	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/dbhierx.rng	(revision 13309)
@@ -0,0 +1,2978 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ...................................................................... -->
+<!-- DocBook document hierarchy module V4.5 ............................... -->
+<!-- File dbhierx.mod ..................................................... -->
+<!--
+  Copyright 1992-2004 HaL Computer Systems, Inc.,
+  O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+  Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+  Organization for the Advancement of Structured Information
+  Standards (OASIS).
+  
+  $Id: dbhierx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+  
+  Permission to use, copy, modify and distribute the DocBook DTD
+  and its accompanying documentation for any purpose and without fee
+  is hereby granted in perpetuity, provided that the above copyright
+  notice and this paragraph appear in all copies.  The copyright
+  holders make no representation about the suitability of the DTD for
+  any purpose.  It is provided "as is" without expressed or implied
+  warranty.
+  
+  If you modify the DocBook DTD in any way, except for declaring and
+  referencing additional sets of general entities and declaring
+  additional notations, label your DTD as a variant of DocBook.  See
+  the maintenance documentation for more information.
+  
+  Please direct all questions, bug reports, or suggestions for
+  changes to the docbook@lists.oasis-open.org mailing list. For more
+  information, see http://www.oasis-open.org/docbook/.
+-->
+<!-- ...................................................................... -->
+<!--
+  This module contains the definitions for the overall document
+  hierarchies of DocBook documents.  It covers computer documentation
+  manuals and manual fragments, as well as reference entries (such as
+  man pages) and technical journals or anthologies containing
+  articles.
+  
+  This module depends on the DocBook information pool module.  All
+  elements and entities referenced but not defined here are assumed
+  to be defined in the information pool module.
+  
+  In DTD driver files referring to this module, please use an entity
+  declaration that uses the public identifier shown below:
+  
+  <!ENTITY % dbhier PUBLIC
+  "-//OASIS//ELEMENTS DocBook Document Hierarchy V4.5//EN"
+  "dbhierx.mod">
+  %dbhier;
+  
+  See the documentation for detailed information on the parameter
+  entity and module scheme used in DocBook, customizing DocBook and
+  planning for interchange, and changes made since the last release
+  of DocBook.
+-->
+<!-- ...................................................................... -->
+<!-- Entities for module inclusions ....................................... -->
+<!-- ...................................................................... -->
+<!-- Entities for element classes ......................................... -->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+  <define name="local.appendix.class">
+    <notAllowed/>
+  </define>
+  <define name="appendix.class">
+    <choice>
+      <ref name="appendix"/>
+      <ref name="local.appendix.class"/>
+    </choice>
+  </define>
+  <define name="local.article.class">
+    <notAllowed/>
+  </define>
+  <define name="article.class">
+    <choice>
+      <ref name="article"/>
+      <ref name="local.article.class"/>
+    </choice>
+  </define>
+  <define name="local.book.class">
+    <notAllowed/>
+  </define>
+  <define name="book.class">
+    <choice>
+      <ref name="book"/>
+      <ref name="local.book.class"/>
+    </choice>
+  </define>
+  <define name="local.chapter.class">
+    <notAllowed/>
+  </define>
+  <define name="chapter.class">
+    <choice>
+      <ref name="chapter"/>
+      <ref name="local.chapter.class"/>
+    </choice>
+  </define>
+  <define name="local.index.class">
+    <notAllowed/>
+  </define>
+  <define name="index.class">
+    <choice>
+      <ref name="index"/>
+      <ref name="setindex"/>
+      <ref name="local.index.class"/>
+    </choice>
+  </define>
+  <define name="local.refentry.class">
+    <notAllowed/>
+  </define>
+  <define name="refentry.class">
+    <choice>
+      <ref name="refentry"/>
+      <ref name="local.refentry.class"/>
+    </choice>
+  </define>
+  <define name="local.section.class">
+    <notAllowed/>
+  </define>
+  <define name="section.class">
+    <choice>
+      <ref name="section"/>
+      <ref name="local.section.class"/>
+    </choice>
+  </define>
+  <define name="local.nav.class">
+    <notAllowed/>
+  </define>
+  <define name="nav.class">
+    <choice>
+      <ref name="toc"/>
+      <ref name="lot"/>
+      <ref name="index"/>
+      <ref name="glossary"/>
+      <ref name="bibliography"/>
+      <ref name="local.nav.class"/>
+    </choice>
+  </define>
+  <!-- Redeclaration placeholder ............................................ -->
+  <!--
+    For redeclaring entities that are declared after this point while
+    retaining their references to the entities that are declared before
+    this point
+  -->
+  <!-- ...................................................................... -->
+  <!-- Entities for element mixtures ........................................ -->
+  <define name="local.divcomponent.mix">
+    <notAllowed/>
+  </define>
+  <define name="divcomponent.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="compound.class"/>
+      <ref name="genobj.class"/>
+      <ref name="descobj.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forms.hook"/>
+      <ref name="local.divcomponent.mix"/>
+    </choice>
+  </define>
+  <define name="local.refcomponent.mix">
+    <notAllowed/>
+  </define>
+  <define name="refcomponent.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="compound.class"/>
+      <ref name="genobj.class"/>
+      <ref name="descobj.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forms.hook"/>
+      <ref name="local.refcomponent.mix"/>
+    </choice>
+  </define>
+  <define name="local.indexdivcomponent.mix">
+    <notAllowed/>
+  </define>
+  <define name="indexdivcomponent.mix">
+    <choice>
+      <ref name="itemizedlist"/>
+      <ref name="orderedlist"/>
+      <ref name="variablelist"/>
+      <ref name="simplelist"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="anchor"/>
+      <ref name="remark"/>
+      <ref name="link.char.class"/>
+      <ref name="beginpage"/>
+      <ref name="local.indexdivcomponent.mix"/>
+    </choice>
+  </define>
+  <define name="local.refname.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="refname.char.mix">
+    <choice>
+      <text/>
+      <ref name="tech.char.class"/>
+      <ref name="local.refname.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.partcontent.mix">
+    <notAllowed/>
+  </define>
+  <define name="partcontent.mix">
+    <choice>
+      <ref name="appendix.class"/>
+      <ref name="chapter.class"/>
+      <ref name="nav.class"/>
+      <ref name="article.class"/>
+      <ref name="preface"/>
+      <ref name="refentry.class"/>
+      <ref name="reference"/>
+      <ref name="local.partcontent.mix"/>
+    </choice>
+  </define>
+  <define name="local.refinline.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="refinline.char.mix">
+    <choice>
+      <text/>
+      <ref name="xref.char.class"/>
+      <ref name="gen.char.class"/>
+      <ref name="link.char.class"/>
+      <ref name="tech.char.class"/>
+      <ref name="base.char.class"/>
+      <ref name="docinfo.char.class"/>
+      <ref name="other.char.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="local.refinline.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.refclass.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="refclass.char.mix">
+    <choice>
+      <text/>
+      <ref name="application"/>
+      <ref name="local.refclass.char.mix"/>
+    </choice>
+  </define>
+  <!-- Redeclaration placeholder 2 .......................................... -->
+  <!--
+    For redeclaring entities that are declared after this point while
+    retaining their references to the entities that are declared before
+    this point
+  -->
+  <!-- ...................................................................... -->
+  <!-- Entities for content models .......................................... -->
+  <define name="div.title.content">
+    <ref name="title"/>
+    <optional>
+      <ref name="subtitle"/>
+    </optional>
+    <optional>
+      <ref name="titleabbrev"/>
+    </optional>
+  </define>
+  <define name="bookcomponent.title.content">
+    <ref name="title"/>
+    <optional>
+      <ref name="subtitle"/>
+    </optional>
+    <optional>
+      <ref name="titleabbrev"/>
+    </optional>
+  </define>
+  <define name="sect.title.content">
+    <ref name="title"/>
+    <optional>
+      <ref name="subtitle"/>
+    </optional>
+    <optional>
+      <ref name="titleabbrev"/>
+    </optional>
+  </define>
+  <define name="refsect.title.content">
+    <ref name="title"/>
+    <optional>
+      <ref name="subtitle"/>
+    </optional>
+    <optional>
+      <ref name="titleabbrev"/>
+    </optional>
+  </define>
+  <define name="bookcomponent.content">
+    <choice>
+      <group>
+        <oneOrMore>
+          <ref name="divcomponent.mix"/>
+        </oneOrMore>
+        <choice>
+          <zeroOrMore>
+            <ref name="sect1"/>
+          </zeroOrMore>
+          <zeroOrMore>
+            <ref name="refentry.class"/>
+          </zeroOrMore>
+          <zeroOrMore>
+            <ref name="simplesect"/>
+          </zeroOrMore>
+          <zeroOrMore>
+            <ref name="section.class"/>
+          </zeroOrMore>
+        </choice>
+      </group>
+      <choice>
+        <oneOrMore>
+          <ref name="sect1"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="refentry.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplesect"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="section.class"/>
+        </oneOrMore>
+      </choice>
+    </choice>
+  </define>
+  <!-- ...................................................................... -->
+  <!-- Set and SetInfo ...................................................... -->
+  <define name="local.set.attrib">
+    <empty/>
+  </define>
+  <define name="set.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A collection of books. -->
+  <define name="set">
+    <element name="set">
+      <ref name="set.attlist"/>
+      <optional>
+        <ref name="div.title.content"/>
+      </optional>
+      <optional>
+        <ref name="setinfo"/>
+      </optional>
+      <optional>
+        <ref name="toc"/>
+      </optional>
+      <oneOrMore>
+        <choice>
+          <ref name="set"/>
+          <ref name="book.class"/>
+        </choice>
+      </oneOrMore>
+      <optional>
+        <ref name="setindex"/>
+      </optional>
+    </element>
+  </define>
+  <!-- end of set.element -->
+  <!-- FPI: SGML formal public identifier -->
+  <define name="set.attlist" combine="interleave">
+    <optional>
+      <attribute name="fpi"/>
+    </optional>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="set.role.attrib"/>
+    <ref name="local.set.attrib"/>
+  </define>
+  <!-- end of set.attlist -->
+  <!-- end of set.module -->
+  <define name="local.setinfo.attrib">
+    <empty/>
+  </define>
+  <define name="setinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Set. -->
+  <define name="setinfo">
+    <element name="setinfo">
+      <ref name="setinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of setinfo.element -->
+  <!--
+    Contents: IDs of the ToC, Books, and SetIndex that comprise
+    the set, in the order of their appearance
+  -->
+  <define name="setinfo.attlist" combine="interleave">
+    <optional>
+      <attribute name="contents">
+        <data type="IDREFS"/>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="setinfo.role.attrib"/>
+    <ref name="local.setinfo.attrib"/>
+  </define>
+  <!-- end of setinfo.attlist -->
+  <!-- end of setinfo.module -->
+  <!-- end of set.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Book and BookInfo .................................................... -->
+  <define name="local.book.attrib">
+    <empty/>
+  </define>
+  <define name="book.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A book. -->
+  <define name="book">
+    <element name="book">
+      <ref name="book.attlist"/>
+      <optional>
+        <ref name="div.title.content"/>
+      </optional>
+      <optional>
+        <ref name="bookinfo"/>
+      </optional>
+      <zeroOrMore>
+        <choice>
+          <ref name="dedication"/>
+          <ref name="toc"/>
+          <ref name="lot"/>
+          <ref name="glossary"/>
+          <ref name="bibliography"/>
+          <ref name="preface"/>
+          <ref name="chapter.class"/>
+          <ref name="reference"/>
+          <ref name="part"/>
+          <ref name="article.class"/>
+          <ref name="appendix.class"/>
+          <ref name="index.class"/>
+          <ref name="colophon"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of book.element -->
+  <!-- FPI: SGML formal public identifier -->
+  <define name="book.attlist" combine="interleave">
+    <optional>
+      <attribute name="fpi"/>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="book.role.attrib"/>
+    <ref name="local.book.attrib"/>
+  </define>
+  <!-- end of book.attlist -->
+  <!-- end of book.module -->
+  <define name="local.bookinfo.attrib">
+    <empty/>
+  </define>
+  <define name="bookinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Book. -->
+  <define name="bookinfo">
+    <element name="bookinfo">
+      <ref name="bookinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of bookinfo.element -->
+  <!--
+    Contents: IDs of the ToC, LoTs, Prefaces, Parts, Chapters,
+    Appendixes, References, GLossary, Bibliography, and indexes
+    comprising the Book, in the order of their appearance
+  -->
+  <define name="bookinfo.attlist" combine="interleave">
+    <optional>
+      <attribute name="contents">
+        <data type="IDREFS"/>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="bookinfo.role.attrib"/>
+    <ref name="local.bookinfo.attrib"/>
+  </define>
+  <!-- end of bookinfo.attlist -->
+  <!-- end of bookinfo.module -->
+  <!-- end of book.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Dedication, ToC, and LoT ............................................. -->
+  <define name="local.dedication.attrib">
+    <empty/>
+  </define>
+  <define name="dedication.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for the dedication section of a book. -->
+  <define name="dedication">
+    <element name="dedication">
+      <ref name="dedication.attlist"/>
+      <optional>
+        <ref name="sect.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="legalnotice.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of dedication.element -->
+  <define name="dedication.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="dedication.role.attrib"/>
+    <ref name="local.dedication.attrib"/>
+  </define>
+  <!-- end of dedication.attlist -->
+  <!-- end of dedication.module -->
+  <define name="local.colophon.attrib">
+    <empty/>
+  </define>
+  <define name="colophon.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Text at the back of a book describing facts about its production. -->
+  <define name="colophon">
+    <element name="colophon">
+      <ref name="colophon.attlist"/>
+      <optional>
+        <ref name="sect.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="textobject.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of colophon.element -->
+  <define name="colophon.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="colophon.role.attrib"/>
+    <ref name="local.colophon.attrib"/>
+  </define>
+  <!-- end of colophon.attlist -->
+  <!-- end of colophon.module -->
+  <define name="local.toc.attrib">
+    <empty/>
+  </define>
+  <define name="toc.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A table of contents. -->
+  <define name="toc">
+    <element name="toc">
+      <ref name="toc.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <optional>
+        <ref name="bookcomponent.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="tocfront"/>
+      </zeroOrMore>
+      <zeroOrMore>
+        <choice>
+          <ref name="tocpart"/>
+          <ref name="tocchap"/>
+        </choice>
+      </zeroOrMore>
+      <zeroOrMore>
+        <ref name="tocback"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of toc.element -->
+  <define name="toc.attlist" combine="interleave">
+    <ref name="pagenum.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="toc.role.attrib"/>
+    <ref name="local.toc.attrib"/>
+  </define>
+  <!-- end of toc.attlist -->
+  <!-- end of toc.module -->
+  <define name="local.tocfront.attrib">
+    <empty/>
+  </define>
+  <define name="tocfront.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a table of contents for a front matter component. -->
+  <define name="tocfront">
+    <element name="tocfront">
+      <ref name="tocfront.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of tocfront.element -->
+  <!-- to element that this entry represents -->
+  <define name="tocfront.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="linkend.attrib"/>
+    <ref name="pagenum.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="tocfront.role.attrib"/>
+    <ref name="local.tocfront.attrib"/>
+  </define>
+  <!-- end of tocfront.attlist -->
+  <!-- end of tocfront.module -->
+  <define name="local.tocentry.attrib">
+    <empty/>
+  </define>
+  <define name="tocentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A component title in a table of contents. -->
+  <define name="tocentry">
+    <element name="tocentry">
+      <ref name="tocentry.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of tocentry.element -->
+  <!-- to element that this entry represents -->
+  <define name="tocentry.attlist" combine="interleave">
+    <ref name="linkend.attrib"/>
+    <ref name="pagenum.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="tocentry.role.attrib"/>
+    <ref name="local.tocentry.attrib"/>
+  </define>
+  <!-- end of tocentry.attlist -->
+  <!-- end of tocentry.module -->
+  <define name="local.tocpart.attrib">
+    <empty/>
+  </define>
+  <define name="tocpart.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a table of contents for a part of a book. -->
+  <define name="tocpart">
+    <element name="tocpart">
+      <ref name="tocpart.attlist"/>
+      <oneOrMore>
+        <ref name="tocentry"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="tocchap"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of tocpart.element -->
+  <define name="tocpart.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="tocpart.role.attrib"/>
+    <ref name="local.tocpart.attrib"/>
+  </define>
+  <!-- end of tocpart.attlist -->
+  <!-- end of tocpart.module -->
+  <define name="local.tocchap.attrib">
+    <empty/>
+  </define>
+  <define name="tocchap.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a table of contents for a component in the body of a document. -->
+  <define name="tocchap">
+    <element name="tocchap">
+      <ref name="tocchap.attlist"/>
+      <oneOrMore>
+        <ref name="tocentry"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="toclevel1"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of tocchap.element -->
+  <define name="tocchap.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="tocchap.role.attrib"/>
+    <ref name="local.tocchap.attrib"/>
+  </define>
+  <!-- end of tocchap.attlist -->
+  <!-- end of tocchap.module -->
+  <define name="local.toclevel1.attrib">
+    <empty/>
+  </define>
+  <define name="toclevel1.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A top-level entry within a table of contents entry for a chapter-like component. -->
+  <define name="toclevel1">
+    <element name="toclevel1">
+      <ref name="toclevel1.attlist"/>
+      <oneOrMore>
+        <ref name="tocentry"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="toclevel2"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of toclevel1.element -->
+  <define name="toclevel1.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="toclevel1.role.attrib"/>
+    <ref name="local.toclevel1.attrib"/>
+  </define>
+  <!-- end of toclevel1.attlist -->
+  <!-- end of toclevel1.module -->
+  <define name="local.toclevel2.attrib">
+    <empty/>
+  </define>
+  <define name="toclevel2.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A second-level entry within a table of contents entry for a chapter-like component. -->
+  <define name="toclevel2">
+    <element name="toclevel2">
+      <ref name="toclevel2.attlist"/>
+      <oneOrMore>
+        <ref name="tocentry"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="toclevel3"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of toclevel2.element -->
+  <define name="toclevel2.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="toclevel2.role.attrib"/>
+    <ref name="local.toclevel2.attrib"/>
+  </define>
+  <!-- end of toclevel2.attlist -->
+  <!-- end of toclevel2.module -->
+  <define name="local.toclevel3.attrib">
+    <empty/>
+  </define>
+  <define name="toclevel3.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A third-level entry within a table of contents entry for a chapter-like component. -->
+  <define name="toclevel3">
+    <element name="toclevel3">
+      <ref name="toclevel3.attlist"/>
+      <oneOrMore>
+        <ref name="tocentry"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="toclevel4"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of toclevel3.element -->
+  <define name="toclevel3.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="toclevel3.role.attrib"/>
+    <ref name="local.toclevel3.attrib"/>
+  </define>
+  <!-- end of toclevel3.attlist -->
+  <!-- end of toclevel3.module -->
+  <define name="local.toclevel4.attrib">
+    <empty/>
+  </define>
+  <define name="toclevel4.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A fourth-level entry within a table of contents entry for a chapter-like component. -->
+  <define name="toclevel4">
+    <element name="toclevel4">
+      <ref name="toclevel4.attlist"/>
+      <oneOrMore>
+        <ref name="tocentry"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="toclevel5"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of toclevel4.element -->
+  <define name="toclevel4.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="toclevel4.role.attrib"/>
+    <ref name="local.toclevel4.attrib"/>
+  </define>
+  <!-- end of toclevel4.attlist -->
+  <!-- end of toclevel4.module -->
+  <define name="local.toclevel5.attrib">
+    <empty/>
+  </define>
+  <define name="toclevel5.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A fifth-level entry within a table of contents entry for a chapter-like component. -->
+  <define name="toclevel5">
+    <element name="toclevel5">
+      <ref name="toclevel5.attlist"/>
+      <oneOrMore>
+        <ref name="tocentry"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of toclevel5.element -->
+  <define name="toclevel5.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="toclevel5.role.attrib"/>
+    <ref name="local.toclevel5.attrib"/>
+  </define>
+  <!-- end of toclevel5.attlist -->
+  <!-- end of toclevel5.module -->
+  <define name="local.tocback.attrib">
+    <empty/>
+  </define>
+  <define name="tocback.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a table of contents for a back matter component. -->
+  <define name="tocback">
+    <element name="tocback">
+      <ref name="tocback.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of tocback.element -->
+  <!-- to element that this entry represents -->
+  <define name="tocback.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="linkend.attrib"/>
+    <ref name="pagenum.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="tocback.role.attrib"/>
+    <ref name="local.tocback.attrib"/>
+  </define>
+  <!-- end of tocback.attlist -->
+  <!-- end of tocback.module -->
+  <!-- end of toc.content.module -->
+  <define name="local.lot.attrib">
+    <empty/>
+  </define>
+  <define name="lot.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A list of the titles of formal objects (as tables or figures) in a document. -->
+  <define name="lot">
+    <element name="lot">
+      <ref name="lot.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <optional>
+        <ref name="bookcomponent.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="lotentry"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of lot.element -->
+  <define name="lot.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="lot.role.attrib"/>
+    <ref name="local.lot.attrib"/>
+  </define>
+  <!-- end of lot.attlist -->
+  <!-- end of lot.module -->
+  <define name="local.lotentry.attrib">
+    <empty/>
+  </define>
+  <define name="lotentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a list of titles. -->
+  <define name="lotentry">
+    <element name="lotentry">
+      <ref name="lotentry.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of lotentry.element -->
+  <!--
+    SrcCredit: Information about the source of the entry,
+    as for a list of illustrations
+  -->
+  <!--  linkend: to element that this entry represents -->
+  <define name="lotentry.attlist" combine="interleave">
+    <ref name="linkend.attrib"/>
+    <ref name="pagenum.attrib"/>
+    <optional>
+      <attribute name="srccredit"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="lotentry.role.attrib"/>
+    <ref name="local.lotentry.attrib"/>
+  </define>
+  <!-- end of lotentry.attlist -->
+  <!-- end of lotentry.module -->
+  <!-- end of lot.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Appendix, Chapter, Part, Preface, Reference, PartIntro ............... -->
+  <define name="local.appendix.attrib">
+    <empty/>
+  </define>
+  <define name="appendix.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An appendix in a Book or Article. -->
+  <define name="appendix">
+    <element name="appendix">
+      <ref name="appendix.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <optional>
+        <ref name="appendixinfo"/>
+      </optional>
+      <ref name="bookcomponent.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="tocchap"/>
+      </optional>
+      <ref name="bookcomponent.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of appendix.element -->
+  <define name="appendix.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="appendix.role.attrib"/>
+    <ref name="local.appendix.attrib"/>
+  </define>
+  <!-- end of appendix.attlist -->
+  <!-- end of appendix.module -->
+  <define name="local.chapter.attrib">
+    <empty/>
+  </define>
+  <define name="chapter.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A chapter, as of a book. -->
+  <define name="chapter">
+    <element name="chapter">
+      <ref name="chapter.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <optional>
+        <ref name="chapterinfo"/>
+      </optional>
+      <ref name="bookcomponent.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="tocchap"/>
+      </optional>
+      <ref name="bookcomponent.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of chapter.element -->
+  <define name="chapter.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="chapter.role.attrib"/>
+    <ref name="local.chapter.attrib"/>
+  </define>
+  <!-- end of chapter.attlist -->
+  <!-- end of chapter.module -->
+  <!--
+    Note that Part was to have its content model reduced in V4.5.  This
+    change will not be made after all.
+  -->
+  <define name="local.part.attrib">
+    <empty/>
+  </define>
+  <define name="part.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A division in a book. -->
+  <define name="part">
+    <element name="part">
+      <ref name="part.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <optional>
+        <ref name="partinfo"/>
+      </optional>
+      <ref name="bookcomponent.title.content"/>
+      <optional>
+        <ref name="partintro"/>
+      </optional>
+      <oneOrMore>
+        <ref name="partcontent.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of part.element -->
+  <define name="part.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="part.role.attrib"/>
+    <ref name="local.part.attrib"/>
+  </define>
+  <!-- end of part.attlist -->
+  <!-- ELEMENT PartIntro (defined below) -->
+  <!-- end of part.module -->
+  <define name="local.preface.attrib">
+    <empty/>
+  </define>
+  <define name="preface.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Introductory matter preceding the first chapter of a book. -->
+  <define name="preface">
+    <element name="preface">
+      <ref name="preface.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <optional>
+        <ref name="prefaceinfo"/>
+      </optional>
+      <ref name="bookcomponent.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="tocchap"/>
+      </optional>
+      <ref name="bookcomponent.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of preface.element -->
+  <define name="preface.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="preface.role.attrib"/>
+    <ref name="local.preface.attrib"/>
+  </define>
+  <!-- end of preface.attlist -->
+  <!-- end of preface.module -->
+  <define name="local.reference.attrib">
+    <empty/>
+  </define>
+  <define name="reference.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A collection of reference entries. -->
+  <define name="reference">
+    <element name="reference">
+      <ref name="reference.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <optional>
+        <ref name="referenceinfo"/>
+      </optional>
+      <ref name="bookcomponent.title.content"/>
+      <optional>
+        <ref name="partintro"/>
+      </optional>
+      <oneOrMore>
+        <ref name="refentry.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of reference.element -->
+  <define name="reference.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="reference.role.attrib"/>
+    <ref name="local.reference.attrib"/>
+  </define>
+  <!-- end of reference.attlist -->
+  <!-- ELEMENT PartIntro (defined below) -->
+  <!-- end of reference.module -->
+  <define name="local.partintro.attrib">
+    <empty/>
+  </define>
+  <define name="partintro.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An introduction to the contents of a part. -->
+  <define name="partintro">
+    <element name="partintro">
+      <ref name="partintro.attlist"/>
+      <optional>
+        <ref name="div.title.content"/>
+      </optional>
+      <ref name="bookcomponent.content"/>
+    </element>
+  </define>
+  <!-- end of partintro.element -->
+  <define name="partintro.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="partintro.role.attrib"/>
+    <ref name="local.partintro.attrib"/>
+  </define>
+  <!-- end of partintro.attlist -->
+  <!-- end of partintro.module -->
+  <!-- ...................................................................... -->
+  <!-- Other Info elements .................................................. -->
+  <define name="local.appendixinfo.attrib">
+    <empty/>
+  </define>
+  <define name="appendixinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for an Appendix. -->
+  <define name="appendixinfo">
+    <element name="appendixinfo">
+      <ref name="appendixinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of appendixinfo.element -->
+  <define name="appendixinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="appendixinfo.role.attrib"/>
+    <ref name="local.appendixinfo.attrib"/>
+  </define>
+  <!-- end of appendixinfo.attlist -->
+  <!-- end of appendixinfo.module -->
+  <define name="local.bibliographyinfo.attrib">
+    <empty/>
+  </define>
+  <define name="bibliographyinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Bibliography. -->
+  <define name="bibliographyinfo">
+    <element name="bibliographyinfo">
+      <ref name="bibliographyinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of bibliographyinfo.element -->
+  <define name="bibliographyinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="bibliographyinfo.role.attrib"/>
+    <ref name="local.bibliographyinfo.attrib"/>
+  </define>
+  <!-- end of bibliographyinfo.attlist -->
+  <!-- end of bibliographyinfo.module -->
+  <define name="local.chapterinfo.attrib">
+    <empty/>
+  </define>
+  <define name="chapterinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Chapter. -->
+  <define name="chapterinfo">
+    <element name="chapterinfo">
+      <ref name="chapterinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of chapterinfo.element -->
+  <define name="chapterinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="chapterinfo.role.attrib"/>
+    <ref name="local.chapterinfo.attrib"/>
+  </define>
+  <!-- end of chapterinfo.attlist -->
+  <!-- end of chapterinfo.module -->
+  <define name="local.glossaryinfo.attrib">
+    <empty/>
+  </define>
+  <define name="glossaryinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Glossary. -->
+  <define name="glossaryinfo">
+    <element name="glossaryinfo">
+      <ref name="glossaryinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of glossaryinfo.element -->
+  <define name="glossaryinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="glossaryinfo.role.attrib"/>
+    <ref name="local.glossaryinfo.attrib"/>
+  </define>
+  <!-- end of glossaryinfo.attlist -->
+  <!-- end of glossaryinfo.module -->
+  <define name="local.indexinfo.attrib">
+    <empty/>
+  </define>
+  <define name="indexinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for an Index. -->
+  <define name="indexinfo">
+    <element name="indexinfo">
+      <ref name="indexinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of indexinfo.element -->
+  <define name="indexinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="indexinfo.role.attrib"/>
+    <ref name="local.indexinfo.attrib"/>
+  </define>
+  <!-- end of indexinfo.attlist -->
+  <!-- end of indexinfo.module -->
+  <define name="local.setindexinfo.attrib">
+    <empty/>
+  </define>
+  <define name="setindexinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a SetIndex. -->
+  <define name="setindexinfo">
+    <element name="setindexinfo">
+      <ref name="setindexinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of setindexinfo.element -->
+  <define name="setindexinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="setindexinfo.role.attrib"/>
+    <ref name="local.setindexinfo.attrib"/>
+  </define>
+  <!-- end of setindexinfo.attlist -->
+  <!-- end of setindexinfo.module -->
+  <define name="local.partinfo.attrib">
+    <empty/>
+  </define>
+  <define name="partinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Part. -->
+  <define name="partinfo">
+    <element name="partinfo">
+      <ref name="partinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of partinfo.element -->
+  <define name="partinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="partinfo.role.attrib"/>
+    <ref name="local.partinfo.attrib"/>
+  </define>
+  <!-- end of partinfo.attlist -->
+  <!-- end of partinfo.module -->
+  <define name="local.prefaceinfo.attrib">
+    <empty/>
+  </define>
+  <define name="prefaceinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Preface. -->
+  <define name="prefaceinfo">
+    <element name="prefaceinfo">
+      <ref name="prefaceinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of prefaceinfo.element -->
+  <define name="prefaceinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="prefaceinfo.role.attrib"/>
+    <ref name="local.prefaceinfo.attrib"/>
+  </define>
+  <!-- end of prefaceinfo.attlist -->
+  <!-- end of prefaceinfo.module -->
+  <define name="local.refentryinfo.attrib">
+    <empty/>
+  </define>
+  <define name="refentryinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Refentry. -->
+  <define name="refentryinfo">
+    <element name="refentryinfo">
+      <ref name="refentryinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of refentryinfo.element -->
+  <define name="refentryinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refentryinfo.role.attrib"/>
+    <ref name="local.refentryinfo.attrib"/>
+  </define>
+  <!-- end of refentryinfo.attlist -->
+  <!-- end of refentryinfo.module -->
+  <define name="local.refsectioninfo.attrib">
+    <empty/>
+  </define>
+  <define name="refsectioninfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a refsection. -->
+  <define name="refsectioninfo">
+    <element name="refsectioninfo">
+      <ref name="refsectioninfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of refsectioninfo.element -->
+  <define name="refsectioninfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refsectioninfo.role.attrib"/>
+    <ref name="local.refsectioninfo.attrib"/>
+  </define>
+  <!-- end of refsectioninfo.attlist -->
+  <!-- end of refsectioninfo.module -->
+  <define name="local.refsect1info.attrib">
+    <empty/>
+  </define>
+  <define name="refsect1info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a RefSect1. -->
+  <define name="refsect1info">
+    <element name="refsect1info">
+      <ref name="refsect1info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of refsect1info.element -->
+  <define name="refsect1info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refsect1info.role.attrib"/>
+    <ref name="local.refsect1info.attrib"/>
+  </define>
+  <!-- end of refsect1info.attlist -->
+  <!-- end of refsect1info.module -->
+  <define name="local.refsect2info.attrib">
+    <empty/>
+  </define>
+  <define name="refsect2info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a RefSect2. -->
+  <define name="refsect2info">
+    <element name="refsect2info">
+      <ref name="refsect2info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of refsect2info.element -->
+  <define name="refsect2info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refsect2info.role.attrib"/>
+    <ref name="local.refsect2info.attrib"/>
+  </define>
+  <!-- end of refsect2info.attlist -->
+  <!-- end of refsect2info.module -->
+  <define name="local.refsect3info.attrib">
+    <empty/>
+  </define>
+  <define name="refsect3info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a RefSect3. -->
+  <define name="refsect3info">
+    <element name="refsect3info">
+      <ref name="refsect3info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of refsect3info.element -->
+  <define name="refsect3info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refsect3info.role.attrib"/>
+    <ref name="local.refsect3info.attrib"/>
+  </define>
+  <!-- end of refsect3info.attlist -->
+  <!-- end of refsect3info.module -->
+  <define name="local.refsynopsisdivinfo.attrib">
+    <empty/>
+  </define>
+  <define name="refsynopsisdivinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a RefSynopsisDiv. -->
+  <define name="refsynopsisdivinfo">
+    <element name="refsynopsisdivinfo">
+      <ref name="refsynopsisdivinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of refsynopsisdivinfo.element -->
+  <define name="refsynopsisdivinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refsynopsisdivinfo.role.attrib"/>
+    <ref name="local.refsynopsisdivinfo.attrib"/>
+  </define>
+  <!-- end of refsynopsisdivinfo.attlist -->
+  <!-- end of refsynopsisdivinfo.module -->
+  <define name="local.referenceinfo.attrib">
+    <empty/>
+  </define>
+  <define name="referenceinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Reference. -->
+  <define name="referenceinfo">
+    <element name="referenceinfo">
+      <ref name="referenceinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of referenceinfo.element -->
+  <define name="referenceinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="referenceinfo.role.attrib"/>
+    <ref name="local.referenceinfo.attrib"/>
+  </define>
+  <!-- end of referenceinfo.attlist -->
+  <!-- end of referenceinfo.module -->
+  <define name="local.sect1info.attrib">
+    <empty/>
+  </define>
+  <define name="sect1info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Sect1. -->
+  <define name="sect1info">
+    <element name="sect1info">
+      <ref name="sect1info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sect1info.element -->
+  <define name="sect1info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sect1info.role.attrib"/>
+    <ref name="local.sect1info.attrib"/>
+  </define>
+  <!-- end of sect1info.attlist -->
+  <define name="local.sect2info.attrib">
+    <empty/>
+  </define>
+  <define name="sect2info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Sect2. -->
+  <define name="sect2info">
+    <element name="sect2info">
+      <ref name="sect2info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sect2info.element -->
+  <define name="sect2info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sect2info.role.attrib"/>
+    <ref name="local.sect2info.attrib"/>
+  </define>
+  <!-- end of sect2info.attlist -->
+  <define name="local.sect3info.attrib">
+    <empty/>
+  </define>
+  <define name="sect3info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Sect3. -->
+  <define name="sect3info">
+    <element name="sect3info">
+      <ref name="sect3info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sect3info.element -->
+  <define name="sect3info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sect3info.role.attrib"/>
+    <ref name="local.sect3info.attrib"/>
+  </define>
+  <!-- end of sect3info.attlist -->
+  <define name="local.sect4info.attrib">
+    <empty/>
+  </define>
+  <define name="sect4info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Sect4. -->
+  <define name="sect4info">
+    <element name="sect4info">
+      <ref name="sect4info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sect4info.element -->
+  <define name="sect4info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sect4info.role.attrib"/>
+    <ref name="local.sect4info.attrib"/>
+  </define>
+  <!-- end of sect4info.attlist -->
+  <define name="local.sect5info.attrib">
+    <empty/>
+  </define>
+  <define name="sect5info.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Sect5. -->
+  <define name="sect5info">
+    <element name="sect5info">
+      <ref name="sect5info.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sect5info.element -->
+  <define name="sect5info.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sect5info.role.attrib"/>
+    <ref name="local.sect5info.attrib"/>
+  </define>
+  <!-- end of sect5info.attlist -->
+  <!-- ...................................................................... -->
+  <!-- Section (parallel to Sect*) ......................................... -->
+  <define name="local.section.attrib">
+    <empty/>
+  </define>
+  <define name="section.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A recursive section. -->
+  <define name="section">
+    <element name="section">
+      <ref name="section.attlist"/>
+      <optional>
+        <ref name="sectioninfo"/>
+      </optional>
+      <ref name="sect.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="divcomponent.mix"/>
+          </oneOrMore>
+          <choice>
+            <zeroOrMore>
+              <ref name="refentry.class"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="section.class"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="simplesect"/>
+            </zeroOrMore>
+          </choice>
+        </group>
+        <oneOrMore>
+          <ref name="refentry.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="section.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplesect"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of section.element -->
+  <define name="section.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="section.role.attrib"/>
+    <ref name="local.section.attrib"/>
+  </define>
+  <!-- end of section.attlist -->
+  <!-- end of section.module -->
+  <define name="sectioninfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <define name="local.sectioninfo.attrib">
+    <empty/>
+  </define>
+  <!-- doc:Meta-information for a recursive section. -->
+  <define name="sectioninfo">
+    <element name="sectioninfo">
+      <ref name="sectioninfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sectioninfo.element -->
+  <define name="sectioninfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sectioninfo.role.attrib"/>
+    <ref name="local.sectioninfo.attrib"/>
+  </define>
+  <!-- end of sectioninfo.attlist -->
+  <!-- end of sectioninfo.module -->
+  <!-- end of section.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Sect1, Sect2, Sect3, Sect4, Sect5 .................................... -->
+  <define name="local.sect1.attrib">
+    <empty/>
+  </define>
+  <define name="sect1.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A top-level section of document. -->
+  <define name="sect1">
+    <element name="sect1">
+      <ref name="sect1.attlist"/>
+      <optional>
+        <ref name="sect1info"/>
+      </optional>
+      <ref name="sect.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="divcomponent.mix"/>
+          </oneOrMore>
+          <choice>
+            <zeroOrMore>
+              <ref name="refentry.class"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="sect2"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="simplesect"/>
+            </zeroOrMore>
+          </choice>
+        </group>
+        <oneOrMore>
+          <ref name="refentry.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="sect2"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplesect"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of sect1.element -->
+  <!--
+    Renderas: Indicates the format in which the heading should
+    appear
+  -->
+  <define name="sect1.attlist" combine="interleave">
+    <optional>
+      <attribute name="renderas">
+        <choice>
+          <value>sect2</value>
+          <value>sect3</value>
+          <value>sect4</value>
+          <value>sect5</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="sect1.role.attrib"/>
+    <ref name="local.sect1.attrib"/>
+  </define>
+  <!-- end of sect1.attlist -->
+  <!-- end of sect1.module -->
+  <define name="local.sect2.attrib">
+    <empty/>
+  </define>
+  <define name="sect2.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subsection within a Sect1. -->
+  <define name="sect2">
+    <element name="sect2">
+      <ref name="sect2.attlist"/>
+      <optional>
+        <ref name="sect2info"/>
+      </optional>
+      <ref name="sect.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="divcomponent.mix"/>
+          </oneOrMore>
+          <choice>
+            <zeroOrMore>
+              <ref name="refentry.class"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="sect3"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="simplesect"/>
+            </zeroOrMore>
+          </choice>
+        </group>
+        <oneOrMore>
+          <ref name="refentry.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="sect3"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplesect"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of sect2.element -->
+  <!--
+    Renderas: Indicates the format in which the heading should
+    appear
+  -->
+  <define name="sect2.attlist" combine="interleave">
+    <optional>
+      <attribute name="renderas">
+        <choice>
+          <value>sect1</value>
+          <value>sect3</value>
+          <value>sect4</value>
+          <value>sect5</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="sect2.role.attrib"/>
+    <ref name="local.sect2.attrib"/>
+  </define>
+  <!-- end of sect2.attlist -->
+  <!-- end of sect2.module -->
+  <define name="local.sect3.attrib">
+    <empty/>
+  </define>
+  <define name="sect3.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subsection within a Sect2. -->
+  <define name="sect3">
+    <element name="sect3">
+      <ref name="sect3.attlist"/>
+      <optional>
+        <ref name="sect3info"/>
+      </optional>
+      <ref name="sect.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="divcomponent.mix"/>
+          </oneOrMore>
+          <choice>
+            <zeroOrMore>
+              <ref name="refentry.class"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="sect4"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="simplesect"/>
+            </zeroOrMore>
+          </choice>
+        </group>
+        <oneOrMore>
+          <ref name="refentry.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="sect4"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplesect"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of sect3.element -->
+  <!--
+    Renderas: Indicates the format in which the heading should
+    appear
+  -->
+  <define name="sect3.attlist" combine="interleave">
+    <optional>
+      <attribute name="renderas">
+        <choice>
+          <value>sect1</value>
+          <value>sect2</value>
+          <value>sect4</value>
+          <value>sect5</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="sect3.role.attrib"/>
+    <ref name="local.sect3.attrib"/>
+  </define>
+  <!-- end of sect3.attlist -->
+  <!-- end of sect3.module -->
+  <define name="local.sect4.attrib">
+    <empty/>
+  </define>
+  <define name="sect4.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subsection within a Sect3. -->
+  <define name="sect4">
+    <element name="sect4">
+      <ref name="sect4.attlist"/>
+      <optional>
+        <ref name="sect4info"/>
+      </optional>
+      <ref name="sect.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="divcomponent.mix"/>
+          </oneOrMore>
+          <choice>
+            <zeroOrMore>
+              <ref name="refentry.class"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="sect5"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="simplesect"/>
+            </zeroOrMore>
+          </choice>
+        </group>
+        <oneOrMore>
+          <ref name="refentry.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="sect5"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplesect"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of sect4.element -->
+  <!--
+    Renderas: Indicates the format in which the heading should
+    appear
+  -->
+  <define name="sect4.attlist" combine="interleave">
+    <optional>
+      <attribute name="renderas">
+        <choice>
+          <value>sect1</value>
+          <value>sect2</value>
+          <value>sect3</value>
+          <value>sect5</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="sect4.role.attrib"/>
+    <ref name="local.sect4.attrib"/>
+  </define>
+  <!-- end of sect4.attlist -->
+  <!-- end of sect4.module -->
+  <define name="local.sect5.attrib">
+    <empty/>
+  </define>
+  <define name="sect5.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subsection within a Sect4. -->
+  <define name="sect5">
+    <element name="sect5">
+      <ref name="sect5.attlist"/>
+      <optional>
+        <ref name="sect5info"/>
+      </optional>
+      <ref name="sect.title.content"/>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="divcomponent.mix"/>
+          </oneOrMore>
+          <choice>
+            <zeroOrMore>
+              <ref name="refentry.class"/>
+            </zeroOrMore>
+            <zeroOrMore>
+              <ref name="simplesect"/>
+            </zeroOrMore>
+          </choice>
+        </group>
+        <oneOrMore>
+          <ref name="refentry.class"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplesect"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <ref name="nav.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of sect5.element -->
+  <!--
+    Renderas: Indicates the format in which the heading should
+    appear
+  -->
+  <define name="sect5.attlist" combine="interleave">
+    <optional>
+      <attribute name="renderas">
+        <choice>
+          <value>sect1</value>
+          <value>sect2</value>
+          <value>sect3</value>
+          <value>sect4</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="sect5.role.attrib"/>
+    <ref name="local.sect5.attrib"/>
+  </define>
+  <!-- end of sect5.attlist -->
+  <!-- end of sect5.module -->
+  <define name="local.simplesect.attrib">
+    <empty/>
+  </define>
+  <define name="simplesect.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A section of a document with no subdivisions. -->
+  <define name="simplesect">
+    <element name="simplesect">
+      <ref name="simplesect.attlist"/>
+      <ref name="sect.title.content"/>
+      <oneOrMore>
+        <ref name="divcomponent.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of simplesect.element -->
+  <define name="simplesect.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="simplesect.role.attrib"/>
+    <ref name="local.simplesect.attrib"/>
+  </define>
+  <!-- end of simplesect.attlist -->
+  <!-- end of simplesect.module -->
+  <!-- ...................................................................... -->
+  <!-- Bibliography ......................................................... -->
+  <define name="local.bibliography.attrib">
+    <empty/>
+  </define>
+  <define name="bibliography.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A bibliography. -->
+  <define name="bibliography">
+    <element name="bibliography">
+      <ref name="bibliography.attlist"/>
+      <optional>
+        <ref name="bibliographyinfo"/>
+      </optional>
+      <optional>
+        <ref name="bookcomponent.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="component.mix"/>
+      </zeroOrMore>
+      <choice>
+        <oneOrMore>
+          <ref name="bibliodiv"/>
+        </oneOrMore>
+        <oneOrMore>
+          <choice>
+            <ref name="biblioentry"/>
+            <ref name="bibliomixed"/>
+          </choice>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of bibliography.element -->
+  <define name="bibliography.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="bibliography.role.attrib"/>
+    <ref name="local.bibliography.attrib"/>
+  </define>
+  <!-- end of bibliography.attlist -->
+  <!-- end of bibliography.module -->
+  <define name="local.bibliodiv.attrib">
+    <empty/>
+  </define>
+  <define name="bibliodiv.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A section of a Bibliography. -->
+  <define name="bibliodiv">
+    <element name="bibliodiv">
+      <ref name="bibliodiv.attlist"/>
+      <optional>
+        <ref name="sect.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="component.mix"/>
+      </zeroOrMore>
+      <oneOrMore>
+        <choice>
+          <ref name="biblioentry"/>
+          <ref name="bibliomixed"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of bibliodiv.element -->
+  <define name="bibliodiv.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="bibliodiv.role.attrib"/>
+    <ref name="local.bibliodiv.attrib"/>
+  </define>
+  <!-- end of bibliodiv.attlist -->
+  <!-- end of bibliodiv.module -->
+  <!-- end of bibliography.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Glossary ............................................................. -->
+  <define name="local.glossary.attrib">
+    <empty/>
+  </define>
+  <define name="glossary.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A glossary. -->
+  <define name="glossary">
+    <element name="glossary">
+      <ref name="glossary.attlist"/>
+      <optional>
+        <ref name="glossaryinfo"/>
+      </optional>
+      <optional>
+        <ref name="bookcomponent.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="component.mix"/>
+      </zeroOrMore>
+      <choice>
+        <oneOrMore>
+          <ref name="glossdiv"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="glossentry"/>
+        </oneOrMore>
+      </choice>
+      <optional>
+        <ref name="bibliography"/>
+      </optional>
+    </element>
+  </define>
+  <!-- end of glossary.element -->
+  <define name="glossary.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="glossary.role.attrib"/>
+    <ref name="local.glossary.attrib"/>
+  </define>
+  <!-- end of glossary.attlist -->
+  <!-- end of glossary.module -->
+  <define name="local.glossdiv.attrib">
+    <empty/>
+  </define>
+  <define name="glossdiv.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A division in a Glossary. -->
+  <define name="glossdiv">
+    <element name="glossdiv">
+      <ref name="glossdiv.attlist"/>
+      <ref name="sect.title.content"/>
+      <zeroOrMore>
+        <ref name="component.mix"/>
+      </zeroOrMore>
+      <oneOrMore>
+        <ref name="glossentry"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of glossdiv.element -->
+  <define name="glossdiv.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="glossdiv.role.attrib"/>
+    <ref name="local.glossdiv.attrib"/>
+  </define>
+  <!-- end of glossdiv.attlist -->
+  <!-- end of glossdiv.module -->
+  <!-- end of glossary.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Index and SetIndex ................................................... -->
+  <define name="local.indexes.attrib">
+    <empty/>
+  </define>
+  <define name="indexes.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An index. -->
+  <define name="index">
+    <element name="index">
+      <ref name="index.attlist"/>
+      <optional>
+        <ref name="indexinfo"/>
+      </optional>
+      <optional>
+        <ref name="bookcomponent.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="component.mix"/>
+      </zeroOrMore>
+      <choice>
+        <zeroOrMore>
+          <ref name="indexdiv"/>
+        </zeroOrMore>
+        <zeroOrMore>
+          <ref name="indexentry"/>
+        </zeroOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of index.element -->
+  <define name="index.attlist" combine="interleave">
+    <optional>
+      <attribute name="type"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="indexes.role.attrib"/>
+    <ref name="local.indexes.attrib"/>
+  </define>
+  <!-- end of index.attlist -->
+  <!-- doc:An index to a set of books. -->
+  <define name="setindex">
+    <element name="setindex">
+      <ref name="setindex.attlist"/>
+      <optional>
+        <ref name="setindexinfo"/>
+      </optional>
+      <optional>
+        <ref name="bookcomponent.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="component.mix"/>
+      </zeroOrMore>
+      <choice>
+        <zeroOrMore>
+          <ref name="indexdiv"/>
+        </zeroOrMore>
+        <zeroOrMore>
+          <ref name="indexentry"/>
+        </zeroOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of setindex.element -->
+  <define name="setindex.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="indexes.role.attrib"/>
+    <ref name="local.indexes.attrib"/>
+  </define>
+  <!-- end of setindex.attlist -->
+  <!-- end of indexes.module -->
+  <!--
+    SegmentedList in this content is useful for marking up permuted
+    indices.
+  -->
+  <define name="local.indexdiv.attrib">
+    <empty/>
+  </define>
+  <define name="indexdiv.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A division in an index. -->
+  <define name="indexdiv">
+    <element name="indexdiv">
+      <ref name="indexdiv.attlist"/>
+      <optional>
+        <ref name="sect.title.content"/>
+      </optional>
+      <group>
+        <zeroOrMore>
+          <ref name="indexdivcomponent.mix"/>
+        </zeroOrMore>
+        <choice>
+          <oneOrMore>
+            <ref name="indexentry"/>
+          </oneOrMore>
+          <ref name="segmentedlist"/>
+        </choice>
+      </group>
+    </element>
+  </define>
+  <!-- end of indexdiv.element -->
+  <define name="indexdiv.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="indexdiv.role.attrib"/>
+    <ref name="local.indexdiv.attrib"/>
+  </define>
+  <!-- end of indexdiv.attlist -->
+  <!-- end of indexdiv.module -->
+  <!-- Index entries appear in the index, not the text. -->
+  <define name="local.indexentry.attrib">
+    <empty/>
+  </define>
+  <define name="indexentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in an index. -->
+  <define name="indexentry">
+    <element name="indexentry">
+      <ref name="indexentry.attlist"/>
+      <ref name="primaryie"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="seeie"/>
+          <ref name="seealsoie"/>
+        </choice>
+      </zeroOrMore>
+      <zeroOrMore>
+        <ref name="secondaryie"/>
+        <zeroOrMore>
+          <choice>
+            <ref name="seeie"/>
+            <ref name="seealsoie"/>
+            <ref name="tertiaryie"/>
+          </choice>
+        </zeroOrMore>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of indexentry.element -->
+  <define name="indexentry.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="indexentry.role.attrib"/>
+    <ref name="local.indexentry.attrib"/>
+  </define>
+  <!-- end of indexentry.attlist -->
+  <!-- end of indexentry.module -->
+  <define name="local.primsecterie.attrib">
+    <empty/>
+  </define>
+  <define name="primsecterie.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A primary term in an index entry, not in the text. -->
+  <define name="primaryie">
+    <element name="primaryie">
+      <ref name="primaryie.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of primaryie.element -->
+  <!-- to IndexTerms that these entries represent -->
+  <define name="primaryie.attlist" combine="interleave">
+    <ref name="linkends.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="primsecterie.role.attrib"/>
+    <ref name="local.primsecterie.attrib"/>
+  </define>
+  <!-- end of primaryie.attlist -->
+  <!-- doc:A secondary term in an index entry, rather than in the text. -->
+  <define name="secondaryie">
+    <element name="secondaryie">
+      <ref name="secondaryie.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of secondaryie.element -->
+  <!-- to IndexTerms that these entries represent -->
+  <define name="secondaryie.attlist" combine="interleave">
+    <ref name="linkends.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="primsecterie.role.attrib"/>
+    <ref name="local.primsecterie.attrib"/>
+  </define>
+  <!-- end of secondaryie.attlist -->
+  <!-- doc:A tertiary term in an index entry, rather than in the text. -->
+  <define name="tertiaryie">
+    <element name="tertiaryie">
+      <ref name="tertiaryie.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of tertiaryie.element -->
+  <!-- to IndexTerms that these entries represent -->
+  <define name="tertiaryie.attlist" combine="interleave">
+    <ref name="linkends.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="primsecterie.role.attrib"/>
+    <ref name="local.primsecterie.attrib"/>
+  </define>
+  <!-- end of tertiaryie.attlist -->
+  <!-- end of primsecterie.module -->
+  <define name="local.seeie.attrib">
+    <empty/>
+  </define>
+  <define name="seeie.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A See entry in an index, rather than in the text. -->
+  <define name="seeie">
+    <element name="seeie">
+      <ref name="seeie.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of seeie.element -->
+  <!-- to IndexEntry to look up -->
+  <define name="seeie.attlist" combine="interleave">
+    <ref name="linkend.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="seeie.role.attrib"/>
+    <ref name="local.seeie.attrib"/>
+  </define>
+  <!-- end of seeie.attlist -->
+  <!-- end of seeie.module -->
+  <define name="local.seealsoie.attrib">
+    <empty/>
+  </define>
+  <define name="seealsoie.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A See also entry in an index, rather than in the text. -->
+  <define name="seealsoie">
+    <element name="seealsoie">
+      <ref name="seealsoie.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of seealsoie.element -->
+  <!-- to related IndexEntries -->
+  <define name="seealsoie.attlist" combine="interleave">
+    <ref name="linkends.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="seealsoie.role.attrib"/>
+    <ref name="local.seealsoie.attrib"/>
+  </define>
+  <!-- end of seealsoie.attlist -->
+  <!-- end of seealsoie.module -->
+  <!-- end of index.content.module -->
+  <!-- ...................................................................... -->
+  <!-- RefEntry ............................................................. -->
+  <define name="local.refentry.attrib">
+    <empty/>
+  </define>
+  <define name="refentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A reference page (originally a UNIX man-style reference page). -->
+  <define name="refentry">
+    <element name="refentry">
+      <ref name="refentry.attlist"/>
+      <optional>
+        <ref name="beginpage"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="ndxterm.class"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="refentryinfo"/>
+      </optional>
+      <optional>
+        <ref name="refmeta"/>
+      </optional>
+      <zeroOrMore>
+        <choice>
+          <ref name="remark"/>
+          <ref name="link.char.class"/>
+        </choice>
+      </zeroOrMore>
+      <oneOrMore>
+        <ref name="refnamediv"/>
+      </oneOrMore>
+      <optional>
+        <ref name="refsynopsisdiv"/>
+      </optional>
+      <choice>
+        <oneOrMore>
+          <ref name="refsect1"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="refsection"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of refentry.element -->
+  <define name="refentry.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="refentry.role.attrib"/>
+    <ref name="local.refentry.attrib"/>
+  </define>
+  <!-- end of refentry.attlist -->
+  <!-- end of refentry.module -->
+  <define name="local.refmeta.attrib">
+    <empty/>
+  </define>
+  <define name="refmeta.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a reference entry. -->
+  <define name="refmeta">
+    <element name="refmeta">
+      <ref name="refmeta.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.class"/>
+      </zeroOrMore>
+      <ref name="refentrytitle"/>
+      <optional>
+        <ref name="manvolnum"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="refmiscinfo"/>
+      </zeroOrMore>
+      <zeroOrMore>
+        <ref name="ndxterm.class"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refmeta.element -->
+  <define name="refmeta.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refmeta.role.attrib"/>
+    <ref name="local.refmeta.attrib"/>
+  </define>
+  <!-- end of refmeta.attlist -->
+  <!-- end of refmeta.module -->
+  <define name="local.refmiscinfo.attrib">
+    <empty/>
+  </define>
+  <define name="refmiscinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a reference entry other than the title and volume number. -->
+  <define name="refmiscinfo">
+    <element name="refmiscinfo">
+      <ref name="refmiscinfo.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refmiscinfo.element -->
+  <!-- Class: Freely assignable parameter; no default -->
+  <define name="refmiscinfo.attlist" combine="interleave">
+    <optional>
+      <attribute name="class"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="refmiscinfo.role.attrib"/>
+    <ref name="local.refmiscinfo.attrib"/>
+  </define>
+  <!-- end of refmiscinfo.attlist -->
+  <!-- end of refmiscinfo.module -->
+  <define name="local.refnamediv.attrib">
+    <empty/>
+  </define>
+  <define name="refnamediv.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name, purpose, and classification of a reference page. -->
+  <define name="refnamediv">
+    <element name="refnamediv">
+      <ref name="refnamediv.attlist"/>
+      <optional>
+        <ref name="refdescriptor"/>
+      </optional>
+      <oneOrMore>
+        <ref name="refname"/>
+      </oneOrMore>
+      <ref name="refpurpose"/>
+      <zeroOrMore>
+        <ref name="refclass"/>
+      </zeroOrMore>
+      <zeroOrMore>
+        <choice>
+          <ref name="remark"/>
+          <ref name="link.char.class"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refnamediv.element -->
+  <define name="refnamediv.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refnamediv.role.attrib"/>
+    <ref name="local.refnamediv.attrib"/>
+  </define>
+  <!-- end of refnamediv.attlist -->
+  <!-- end of refnamediv.module -->
+  <define name="local.refdescriptor.attrib">
+    <empty/>
+  </define>
+  <define name="refdescriptor.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A description of the topic of a reference page. -->
+  <define name="refdescriptor">
+    <element name="refdescriptor">
+      <ref name="refdescriptor.attlist"/>
+      <zeroOrMore>
+        <ref name="refname.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refdescriptor.element -->
+  <define name="refdescriptor.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refdescriptor.role.attrib"/>
+    <ref name="local.refdescriptor.attrib"/>
+  </define>
+  <!-- end of refdescriptor.attlist -->
+  <!-- end of refdescriptor.module -->
+  <define name="local.refname.attrib">
+    <empty/>
+  </define>
+  <define name="refname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of (one of) the subject(s) of a reference page. -->
+  <define name="refname">
+    <element name="refname">
+      <ref name="refname.attlist"/>
+      <zeroOrMore>
+        <ref name="refname.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refname.element -->
+  <define name="refname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refname.role.attrib"/>
+    <ref name="local.refname.attrib"/>
+  </define>
+  <!-- end of refname.attlist -->
+  <!-- end of refname.module -->
+  <define name="local.refpurpose.attrib">
+    <empty/>
+  </define>
+  <define name="refpurpose.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A short (one sentence) synopsis of the topic of a reference page. -->
+  <define name="refpurpose">
+    <element name="refpurpose">
+      <ref name="refpurpose.attlist"/>
+      <zeroOrMore>
+        <ref name="refinline.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refpurpose.element -->
+  <define name="refpurpose.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refpurpose.role.attrib"/>
+    <ref name="local.refpurpose.attrib"/>
+  </define>
+  <!-- end of refpurpose.attlist -->
+  <!-- end of refpurpose.module -->
+  <define name="local.refclass.attrib">
+    <empty/>
+  </define>
+  <define name="refclass.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The scope or other indication of applicability of a reference entry. -->
+  <define name="refclass">
+    <element name="refclass">
+      <ref name="refclass.attlist"/>
+      <zeroOrMore>
+        <ref name="refclass.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refclass.element -->
+  <define name="refclass.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refclass.role.attrib"/>
+    <ref name="local.refclass.attrib"/>
+  </define>
+  <!-- end of refclass.attlist -->
+  <!-- end of refclass.module -->
+  <define name="local.refsynopsisdiv.attrib">
+    <empty/>
+  </define>
+  <define name="refsynopsisdiv.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A syntactic synopsis of the subject of the reference page. -->
+  <define name="refsynopsisdiv">
+    <element name="refsynopsisdiv">
+      <ref name="refsynopsisdiv.attlist"/>
+      <optional>
+        <ref name="refsynopsisdivinfo"/>
+      </optional>
+      <optional>
+        <ref name="refsect.title.content"/>
+      </optional>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="refcomponent.mix"/>
+          </oneOrMore>
+          <zeroOrMore>
+            <ref name="refsect2"/>
+          </zeroOrMore>
+        </group>
+        <oneOrMore>
+          <ref name="refsect2"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of refsynopsisdiv.element -->
+  <define name="refsynopsisdiv.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refsynopsisdiv.role.attrib"/>
+    <ref name="local.refsynopsisdiv.attrib"/>
+  </define>
+  <!-- end of refsynopsisdiv.attlist -->
+  <!-- end of refsynopsisdiv.module -->
+  <define name="local.refsection.attrib">
+    <empty/>
+  </define>
+  <define name="refsection.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A recursive section in a refentry. -->
+  <define name="refsection">
+    <element name="refsection">
+      <ref name="refsection.attlist"/>
+      <optional>
+        <ref name="refsectioninfo"/>
+      </optional>
+      <ref name="refsect.title.content"/>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="refcomponent.mix"/>
+          </oneOrMore>
+          <zeroOrMore>
+            <ref name="refsection"/>
+          </zeroOrMore>
+        </group>
+        <oneOrMore>
+          <ref name="refsection"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of refsection.element -->
+  <define name="refsection.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="refsection.role.attrib"/>
+    <ref name="local.refsection.attrib"/>
+  </define>
+  <!-- end of refsection.attlist -->
+  <!-- end of refsection.module -->
+  <define name="local.refsect1.attrib">
+    <empty/>
+  </define>
+  <define name="refsect1.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A major subsection of a reference entry. -->
+  <define name="refsect1">
+    <element name="refsect1">
+      <ref name="refsect1.attlist"/>
+      <optional>
+        <ref name="refsect1info"/>
+      </optional>
+      <ref name="refsect.title.content"/>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="refcomponent.mix"/>
+          </oneOrMore>
+          <zeroOrMore>
+            <ref name="refsect2"/>
+          </zeroOrMore>
+        </group>
+        <oneOrMore>
+          <ref name="refsect2"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of refsect1.element -->
+  <define name="refsect1.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="refsect1.role.attrib"/>
+    <ref name="local.refsect1.attrib"/>
+  </define>
+  <!-- end of refsect1.attlist -->
+  <!-- end of refsect1.module -->
+  <define name="local.refsect2.attrib">
+    <empty/>
+  </define>
+  <define name="refsect2.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subsection of a RefSect1. -->
+  <define name="refsect2">
+    <element name="refsect2">
+      <ref name="refsect2.attlist"/>
+      <optional>
+        <ref name="refsect2info"/>
+      </optional>
+      <ref name="refsect.title.content"/>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="refcomponent.mix"/>
+          </oneOrMore>
+          <zeroOrMore>
+            <ref name="refsect3"/>
+          </zeroOrMore>
+        </group>
+        <oneOrMore>
+          <ref name="refsect3"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of refsect2.element -->
+  <define name="refsect2.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="refsect2.role.attrib"/>
+    <ref name="local.refsect2.attrib"/>
+  </define>
+  <!-- end of refsect2.attlist -->
+  <!-- end of refsect2.module -->
+  <define name="local.refsect3.attrib">
+    <empty/>
+  </define>
+  <define name="refsect3.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subsection of a RefSect2. -->
+  <define name="refsect3">
+    <element name="refsect3">
+      <ref name="refsect3.attlist"/>
+      <optional>
+        <ref name="refsect3info"/>
+      </optional>
+      <ref name="refsect.title.content"/>
+      <oneOrMore>
+        <ref name="refcomponent.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of refsect3.element -->
+  <define name="refsect3.attlist" combine="interleave">
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="refsect3.role.attrib"/>
+    <ref name="local.refsect3.attrib"/>
+  </define>
+  <!-- end of refsect3.attlist -->
+  <!-- end of refsect3.module -->
+  <!-- end of refentry.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Article .............................................................. -->
+  <!--
+    An Article is a chapter-level, stand-alone document that is often,
+    but need not be, collected into a Book.
+  -->
+  <define name="local.article.attrib">
+    <empty/>
+  </define>
+  <define name="article.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An article. -->
+  <define name="article">
+    <element name="article">
+      <ref name="article.attlist"/>
+      <optional>
+        <ref name="div.title.content"/>
+      </optional>
+      <optional>
+        <ref name="articleinfo"/>
+      </optional>
+      <optional>
+        <ref name="tocchap"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="lot"/>
+      </zeroOrMore>
+      <ref name="bookcomponent.content"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="nav.class"/>
+          <ref name="appendix.class"/>
+          <ref name="colophon"/>
+          <ref name="ackno"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of article.element -->
+  <!--
+    Class: Indicates the type of a particular article;
+    all articles have the same structure and general purpose.
+    No default.
+  -->
+  <!-- ParentBook: ID of the enclosing Book -->
+  <define name="article.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>journalarticle</value>
+          <value>productsheet</value>
+          <value>whitepaper</value>
+          <value>techreport</value>
+          <value>specification</value>
+          <value>faq</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="parentbook">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <ref name="status.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="article.role.attrib"/>
+    <ref name="local.article.attrib"/>
+  </define>
+</grammar>
+<!-- end of article.attlist -->
+<!-- end of article.module -->
+<!-- End of DocBook document hierarchy module V4.5 ........................ -->
+<!-- ...................................................................... -->
Index: /branches/new-random/doc/src/docbook-rng-4.5/dbnotnx.rnc
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/dbnotnx.rnc	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/dbnotnx.rnc	(revision 13309)
@@ -0,0 +1,85 @@
+# ......................................................................
+
+# DocBook notations module V4.5 ........................................
+
+# File dbnotnx.mod .....................................................
+
+# Copyright 1992-2004 HaL Computer Systems, Inc.,
+# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+# Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+# Organization for the Advancement of Structured Information
+# Standards (OASIS).
+# 
+# $Id: dbnotnx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+# 
+# Permission to use, copy, modify and distribute the DocBook DTD
+# and its accompanying documentation for any purpose and without fee
+# is hereby granted in perpetuity, provided that the above copyright
+# notice and this paragraph appear in all copies.  The copyright
+# holders make no representation about the suitability of the DTD for
+# any purpose.  It is provided "as is" without expressed or implied
+# warranty.
+# 
+# If you modify the DocBook DTD in any way, except for declaring and
+# referencing additional sets of general entities and declaring
+# additional notations, label your DTD as a variant of DocBook.  See
+# the maintenance documentation for more information.
+# 
+# Please direct all questions, bug reports, or suggestions for
+# changes to the docbook@lists.oasis-open.org mailing list. For more
+# information, see http://www.oasis-open.org/docbook/.
+
+# ......................................................................
+
+# This module contains the notation declarations used by DocBook.
+# 
+# In DTD driver files referring to this module, please use an entity
+# declaration that uses the public identifier shown below:
+# 
+# <!ENTITY % dbnotn PUBLIC
+# "-//OASIS//ENTITIES DocBook Notations V4.5//EN"
+# "dbnotnx.mod">
+# %dbnotn;
+# 
+# See the documentation for detailed information on the parameter
+# entity and module scheme used in DocBook, customizing DocBook and
+# planning for interchange, and changes made since the last release
+# of DocBook.
+
+local.notation.class = notAllowed
+notation.class =
+  "BMP"
+  | "CGM-CHAR"
+  | "CGM-BINARY"
+  | "CGM-CLEAR"
+  | "DITROFF"
+  | "DVI"
+  | "EPS"
+  | "EQN"
+  | "FAX"
+  | "GIF"
+  | "GIF87a"
+  | "GIF89a"
+  | "JPG"
+  | "JPEG"
+  | "IGES"
+  | "PCX"
+  | "PIC"
+  | "PNG"
+  | "PS"
+  | "SGML"
+  | "TBL"
+  | "TEX"
+  | "TIFF"
+  | "WMF"
+  | "WPG"
+  | "SVG"
+  | "PDF"
+  | "SWF"
+  | "linespecific"
+  | local.notation.class
+# WordPerfect Graphic format
+
+# End of DocBook notations module V4.5 .................................
+
+# ......................................................................
Index: /branches/new-random/doc/src/docbook-rng-4.5/dbnotnx.rng
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/dbnotnx.rng	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/dbnotnx.rng	(revision 13309)
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ...................................................................... -->
+<!-- DocBook notations module V4.5 ........................................ -->
+<!-- File dbnotnx.mod ..................................................... -->
+<!--
+  Copyright 1992-2004 HaL Computer Systems, Inc.,
+  O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+  Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+  Organization for the Advancement of Structured Information
+  Standards (OASIS).
+  
+  $Id: dbnotnx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+  
+  Permission to use, copy, modify and distribute the DocBook DTD
+  and its accompanying documentation for any purpose and without fee
+  is hereby granted in perpetuity, provided that the above copyright
+  notice and this paragraph appear in all copies.  The copyright
+  holders make no representation about the suitability of the DTD for
+  any purpose.  It is provided "as is" without expressed or implied
+  warranty.
+  
+  If you modify the DocBook DTD in any way, except for declaring and
+  referencing additional sets of general entities and declaring
+  additional notations, label your DTD as a variant of DocBook.  See
+  the maintenance documentation for more information.
+  
+  Please direct all questions, bug reports, or suggestions for
+  changes to the docbook@lists.oasis-open.org mailing list. For more
+  information, see http://www.oasis-open.org/docbook/.
+-->
+<!-- ...................................................................... -->
+<!--
+  This module contains the notation declarations used by DocBook.
+  
+  In DTD driver files referring to this module, please use an entity
+  declaration that uses the public identifier shown below:
+  
+  <!ENTITY % dbnotn PUBLIC
+  "-//OASIS//ENTITIES DocBook Notations V4.5//EN"
+  "dbnotnx.mod">
+  %dbnotn;
+  
+  See the documentation for detailed information on the parameter
+  entity and module scheme used in DocBook, customizing DocBook and
+  planning for interchange, and changes made since the last release
+  of DocBook.
+-->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0">
+  <define name="local.notation.class">
+    <notAllowed/>
+  </define>
+  <define name="notation.class">
+    <choice>
+      <value>BMP</value>
+      <value>CGM-CHAR</value>
+      <value>CGM-BINARY</value>
+      <value>CGM-CLEAR</value>
+      <value>DITROFF</value>
+      <value>DVI</value>
+      <value>EPS</value>
+      <value>EQN</value>
+      <value>FAX</value>
+      <value>GIF</value>
+      <value>GIF87a</value>
+      <value>GIF89a</value>
+      <value>JPG</value>
+      <value>JPEG</value>
+      <value>IGES</value>
+      <value>PCX</value>
+      <value>PIC</value>
+      <value>PNG</value>
+      <value>PS</value>
+      <value>SGML</value>
+      <value>TBL</value>
+      <value>TEX</value>
+      <value>TIFF</value>
+      <value>WMF</value>
+      <value>WPG</value>
+      <value>SVG</value>
+      <value>PDF</value>
+      <value>SWF</value>
+      <value>linespecific</value>
+      <ref name="local.notation.class"/>
+    </choice>
+  </define>
+</grammar>
+<!-- WordPerfect Graphic format -->
+<!-- End of DocBook notations module V4.5 ................................. -->
+<!-- ...................................................................... -->
Index: /branches/new-random/doc/src/docbook-rng-4.5/dbpoolx.rnc
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/dbpoolx.rnc	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/dbpoolx.rnc	(revision 13309)
@@ -0,0 +1,5785 @@
+# ......................................................................
+
+# DocBook XML information pool module V4.5 .............................
+
+# File dbpoolx.mod .....................................................
+
+# Copyright 1992-2004 HaL Computer Systems, Inc.,
+# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+# Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+# Organization for the Advancement of Structured Information
+# Standards (OASIS).
+# 
+# $Id: dbpoolx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+# 
+# Permission to use, copy, modify and distribute the DocBook XML DTD
+# and its accompanying documentation for any purpose and without fee
+# is hereby granted in perpetuity, provided that the above copyright
+# notice and this paragraph appear in all copies.  The copyright
+# holders make no representation about the suitability of the DTD for
+# any purpose.  It is provided "as is" without expressed or implied
+# warranty.
+# 
+# If you modify the DocBook XML DTD in any way, except for declaring and
+# referencing additional sets of general entities and declaring
+# additional notations, label your DTD as a variant of DocBook.  See
+# the maintenance documentation for more information.
+# 
+# Please direct all questions, bug reports, or suggestions for
+# changes to the docbook@lists.oasis-open.org mailing list. For more
+# information, see http://www.oasis-open.org/docbook/.
+
+# ......................................................................
+
+# This module contains the definitions for the objects, inline
+# elements, and so on that are available to be used as the main
+# content of DocBook documents.  Some elements are useful for general
+# publishing, and others are useful specifically for computer
+# documentation.
+# 
+# This module has the following dependencies on other modules:
+# 
+# o It assumes that a %notation.class; entity is defined by the
+#   driver file or other high-level module.  This entity is
+#   referenced in the NOTATION attributes for the graphic-related and
+#   ModeSpec elements.
+# 
+# o It assumes that an appropriately parameterized table module is
+#   available for use with the table-related elements.
+# 
+# In DTD driver files referring to this module, please use an entity
+# declaration that uses the public identifier shown below:
+# 
+# <!ENTITY % dbpool PUBLIC
+# "-//OASIS//ELEMENTS DocBook XML Information Pool V4.5//EN"
+# "dbpoolx.mod">
+# %dbpool;
+# 
+# See the documentation for detailed information on the parameter
+# entity and module scheme used in DocBook, customizing DocBook and
+# planning for interchange, and changes made since the last release
+# of DocBook.
+
+# ......................................................................
+
+# Forms entities .......................................................
+
+# These PEs provide the hook by which the forms module can be inserted
+
+# into the DTD.
+
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+forminlines.hook = notAllowed
+forms.hook = notAllowed
+# ......................................................................
+
+# General-purpose semantics entities ...................................
+yesorno.attvals = string
+# ......................................................................
+
+# Entities for module inclusions .......................................
+
+# ......................................................................
+
+# Entities for element classes and mixtures ............................
+
+# "Ubiquitous" classes: ndxterm.class and beginpage
+local.ndxterm.class = notAllowed
+ndxterm.class = indexterm | local.ndxterm.class
+# Object-level classes .................................................
+local.list.class = notAllowed
+list.class =
+  calloutlist
+  | glosslist
+  | bibliolist
+  | itemizedlist
+  | orderedlist
+  | segmentedlist
+  | simplelist
+  | variablelist
+  | local.list.class
+local.admon.class = notAllowed
+admon.class =
+  caution | important | note | tip | warning | local.admon.class
+local.linespecific.class = notAllowed
+linespecific.class =
+  literallayout
+  | programlisting
+  | programlistingco
+  | screen
+  | screenco
+  | screenshot
+  | local.linespecific.class
+local.method.synop.class = notAllowed
+method.synop.class =
+  constructorsynopsis
+  | destructorsynopsis
+  | methodsynopsis
+  | local.method.synop.class
+local.synop.class = notAllowed
+synop.class =
+  synopsis
+  | cmdsynopsis
+  | funcsynopsis
+  | classsynopsis
+  | fieldsynopsis
+  | method.synop.class
+  | local.synop.class
+local.para.class = notAllowed
+para.class = formalpara | para | simpara | local.para.class
+local.informal.class = notAllowed
+informal.class =
+  address
+  | blockquote
+  | graphic
+  | graphicco
+  | mediaobject
+  | mediaobjectco
+  | informalequation
+  | informalexample
+  | informalfigure
+  | informaltable
+  | local.informal.class
+local.formal.class = notAllowed
+formal.class = equation | example | figure | table | local.formal.class
+# The DocBook TC may produce an official EBNF module for DocBook.
+
+# This PE provides the hook by which it can be inserted into the DTD.
+ebnf.block.hook = notAllowed
+local.compound.class = notAllowed
+compound.class =
+  msgset
+  | procedure
+  | sidebar
+  | qandaset
+  | task
+  | ebnf.block.hook
+  | local.compound.class
+local.genobj.class = notAllowed
+genobj.class =
+  anchor | bridgehead | remark | highlights | local.genobj.class
+local.descobj.class = notAllowed
+descobj.class = abstract | authorblurb | epigraph | local.descobj.class
+# Character-level classes ..............................................
+local.xref.char.class = notAllowed
+xref.char.class = footnoteref | xref | biblioref | local.xref.char.class
+local.gen.char.class = notAllowed
+gen.char.class =
+  abbrev
+  | acronym
+  | citation
+  | citerefentry
+  | citetitle
+  | citebiblioid
+  | emphasis
+  | firstterm
+  | foreignphrase
+  | glossterm
+  | termdef
+  | footnote
+  | phrase
+  | orgname
+  | quote
+  | trademark
+  | wordasword
+  | personname
+  | local.gen.char.class
+local.link.char.class = notAllowed
+link.char.class = link | olink | ulink | local.link.char.class
+# The DocBook TC may produce an official EBNF module for DocBook.
+
+# This PE provides the hook by which it can be inserted into the DTD.
+ebnf.inline.hook = notAllowed
+local.tech.char.class = notAllowed
+tech.char.class =
+  action
+  | application
+  | classname
+  | methodname
+  | interfacename
+  | exceptionname
+  | ooclass
+  | oointerface
+  | ooexception
+  | package
+  | command
+  | computeroutput
+  | database
+  | email
+  | envar
+  | errorcode
+  | errorname
+  | errortype
+  | errortext
+  | filename
+  | function
+  | guibutton
+  | guiicon
+  | guilabel
+  | guimenu
+  | guimenuitem
+  | guisubmenu
+  | hardware
+  | interface
+  | keycap
+  | keycode
+  | keycombo
+  | keysym
+  | literal
+  | code
+  | constant
+  | markup
+  | medialabel
+  | menuchoice
+  | mousebutton
+  | option
+  | optional
+  | parameter
+  | prompt
+  | property
+  | replaceable
+  | returnvalue
+  | sgmltag
+  | structfield
+  | structname
+  | symbol
+  | systemitem
+  | uri
+  | \token
+  | type
+  | userinput
+  | varname
+  | ebnf.inline.hook
+  | local.tech.char.class
+local.base.char.class = notAllowed
+base.char.class = anchor | local.base.char.class
+local.docinfo.char.class = notAllowed
+docinfo.char.class =
+  author
+  | authorinitials
+  | corpauthor
+  | corpcredit
+  | modespec
+  | othercredit
+  | productname
+  | productnumber
+  | revhistory
+  | local.docinfo.char.class
+local.other.char.class = notAllowed
+other.char.class =
+  remark | subscript | superscript | local.other.char.class
+local.inlineobj.char.class = notAllowed
+inlineobj.char.class =
+  inlinegraphic
+  | inlinemediaobject
+  | inlineequation
+  | local.inlineobj.char.class
+# ......................................................................
+
+# Entities for content models ..........................................
+formalobject.title.content = title, titleabbrev?
+# Redeclaration placeholder ............................................
+
+# For redeclaring entities that are declared after this point while
+# retaining their references to the entities that are declared before
+# this point
+
+# Object-level mixtures ................................................
+
+#                       list admn line synp para infm form cmpd gen  desc
+# Component mixture       X    X    X    X    X    X    X    X    X    X
+# Sidebar mixture         X    X    X    X    X    X    X    a    X
+# Footnote mixture        X         X    X    X    X
+# Example mixture         X         X    X    X    X
+# Highlights mixture      X    X              X
+# Paragraph mixture       X         X    X         X
+# Admonition mixture      X         X    X    X    X    X    b    c
+# Figure mixture                    X    X         X
+# Table entry mixture     X    X    X         X    d
+# Glossary def mixture    X         X    X    X    X         e
+# Legal notice mixture    X    X    X         X    f
+# 
+# a. Just Procedure; not Sidebar itself or MsgSet.
+# b. No MsgSet.
+# c. No Highlights.
+# d. Just Graphic; no other informal objects.
+# e. No Anchor, BridgeHead, or Highlights.
+# f. Just BlockQuote; no other informal objects.
+local.component.mix = notAllowed
+component.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | compound.class
+  | genobj.class
+  | descobj.class
+  | ndxterm.class
+  | beginpage
+  | forms.hook
+  | local.component.mix
+local.sidebar.mix = notAllowed
+sidebar.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | procedure
+  | genobj.class
+  | ndxterm.class
+  | beginpage
+  | forms.hook
+  | local.sidebar.mix
+local.qandaset.mix = notAllowed
+qandaset.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | procedure
+  | genobj.class
+  | ndxterm.class
+  | forms.hook
+  | local.qandaset.mix
+local.revdescription.mix = notAllowed
+revdescription.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | procedure
+  | genobj.class
+  | ndxterm.class
+  | local.revdescription.mix
+local.footnote.mix = notAllowed
+footnote.mix =
+  list.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | local.footnote.mix
+local.example.mix = notAllowed
+example.mix =
+  list.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | ndxterm.class
+  | beginpage
+  | procedure
+  | forms.hook
+  | local.example.mix
+local.highlights.mix = notAllowed
+highlights.mix =
+  list.class
+  | admon.class
+  | para.class
+  | ndxterm.class
+  | local.highlights.mix
+# %formal.class; is explicitly excluded from many contexts in which
+# paragraphs are used
+local.para.mix = notAllowed
+para.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | informal.class
+  | formal.class
+  | local.para.mix
+local.admon.mix = notAllowed
+admon.mix =
+  list.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | procedure
+  | sidebar
+  | anchor
+  | bridgehead
+  | remark
+  | ndxterm.class
+  | beginpage
+  | forms.hook
+  | local.admon.mix
+local.figure.mix = notAllowed
+figure.mix =
+  linespecific.class
+  | synop.class
+  | informal.class
+  | ndxterm.class
+  | beginpage
+  | forms.hook
+  | local.figure.mix
+local.tabentry.mix = notAllowed
+tabentry.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | para.class
+  | graphic
+  | mediaobject
+  | forms.hook
+  | local.tabentry.mix
+local.glossdef.mix = notAllowed
+glossdef.mix =
+  list.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | formal.class
+  | remark
+  | ndxterm.class
+  | beginpage
+  | local.glossdef.mix
+local.legalnotice.mix = notAllowed
+legalnotice.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | para.class
+  | blockquote
+  | ndxterm.class
+  | beginpage
+  | local.legalnotice.mix
+local.textobject.mix = notAllowed
+textobject.mix =
+  list.class
+  | admon.class
+  | linespecific.class
+  | para.class
+  | blockquote
+  | local.textobject.mix
+local.mediaobject.mix = notAllowed
+mediaobject.mix =
+  videoobject
+  | audioobject
+  | imageobject
+  | imageobjectco
+  | textobject
+  | local.mediaobject.mix
+local.listpreamble.mix = notAllowed
+listpreamble.mix =
+  admon.class
+  | linespecific.class
+  | synop.class
+  | para.class
+  | informal.class
+  | genobj.class
+  | descobj.class
+  | ndxterm.class
+  | beginpage
+  | forms.hook
+  | local.listpreamble.mix
+# Character-level mixtures .............................................
+
+# sgml.features
+
+# not [sgml.features[
+
+# ]] not sgml.features
+
+#                     #PCD xref word link cptr base dnfo othr inob (synop)
+# para.char.mix         X    X    X    X    X    X    X    X    X
+# title.char.mix        X    X    X    X    X    X    X    X    X
+# ndxterm.char.mix      X    X    X    X    X    X    X    X    a
+# cptr.char.mix         X              X    X    X         X    a
+# smallcptr.char.mix    X                   b                   a
+# word.char.mix         X         c    X         X         X    a
+# docinfo.char.mix      X         d    X    b              X    a
+# 
+# a. Just InlineGraphic; no InlineEquation.
+# b. Just Replaceable; no other computer terms.
+# c. Just Emphasis and Trademark; no other word elements.
+# d. Just Acronym, Emphasis, and Trademark; no other word elements.
+local.para.char.mix = notAllowed
+para.char.mix =
+  text
+  | xref.char.class
+  | gen.char.class
+  | link.char.class
+  | tech.char.class
+  | base.char.class
+  | docinfo.char.class
+  | other.char.class
+  | inlineobj.char.class
+  | synop.class
+  | ndxterm.class
+  | beginpage
+  | forminlines.hook
+  | local.para.char.mix
+local.title.char.mix = notAllowed
+title.char.mix =
+  text
+  | xref.char.class
+  | gen.char.class
+  | link.char.class
+  | tech.char.class
+  | base.char.class
+  | docinfo.char.class
+  | other.char.class
+  | inlineobj.char.class
+  | ndxterm.class
+  | local.title.char.mix
+local.ndxterm.char.mix = notAllowed
+ndxterm.char.mix =
+  text
+  | xref.char.class
+  | gen.char.class
+  | link.char.class
+  | tech.char.class
+  | base.char.class
+  | docinfo.char.class
+  | other.char.class
+  | inlinegraphic
+  | inlinemediaobject
+  | local.ndxterm.char.mix
+local.cptr.char.mix = notAllowed
+cptr.char.mix =
+  text
+  | link.char.class
+  | tech.char.class
+  | base.char.class
+  | other.char.class
+  | inlinegraphic
+  | inlinemediaobject
+  | ndxterm.class
+  | beginpage
+  | local.cptr.char.mix
+local.smallcptr.char.mix = notAllowed
+smallcptr.char.mix =
+  text
+  | replaceable
+  | inlinegraphic
+  | inlinemediaobject
+  | ndxterm.class
+  | beginpage
+  | local.smallcptr.char.mix
+local.word.char.mix = notAllowed
+word.char.mix =
+  text
+  | acronym
+  | emphasis
+  | trademark
+  | link.char.class
+  | base.char.class
+  | other.char.class
+  | inlinegraphic
+  | inlinemediaobject
+  | ndxterm.class
+  | beginpage
+  | local.word.char.mix
+local.docinfo.char.mix = notAllowed
+docinfo.char.mix =
+  text
+  | link.char.class
+  | emphasis
+  | trademark
+  | replaceable
+  | other.char.class
+  | inlinegraphic
+  | inlinemediaobject
+  | ndxterm.class
+  | local.docinfo.char.mix
+# ENTITY % bibliocomponent.mix (see Bibliographic section, below)
+
+# ENTITY % person.ident.mix (see Bibliographic section, below)
+
+# ......................................................................
+
+# Entities for attributes and attribute components .....................
+
+# Effectivity attributes ...............................................
+
+# Arch: Computer or chip architecture to which element applies; no
+# default
+arch.attrib = attribute arch { text }?
+# Condition: General-purpose effectivity attribute
+condition.attrib = attribute condition { text }?
+# Conformance: Standards conformance characteristics
+conformance.attrib = attribute conformance { xsd:NMTOKENS }?
+# OS: Operating system to which element applies; no default
+os.attrib = attribute os { text }?
+# Revision: Editorial revision to which element belongs; no default
+revision.attrib = attribute revision { text }?
+# Security: Security classification; no default
+security.attrib = attribute security { text }?
+# UserLevel: Level of user experience to which element applies; no
+# default
+userlevel.attrib = attribute userlevel { text }?
+# Vendor: Computer vendor to which element applies; no default
+vendor.attrib = attribute vendor { text }?
+# Wordsize: Computer word size (32 bit, 64 bit, etc.); no default
+wordsize.attrib = attribute wordsize { text }?
+local.effectivity.attrib = empty
+effectivity.attrib =
+  arch.attrib,
+  condition.attrib,
+  conformance.attrib,
+  os.attrib,
+  revision.attrib,
+  security.attrib,
+  userlevel.attrib,
+  vendor.attrib,
+  wordsize.attrib,
+  local.effectivity.attrib
+# Common attributes ....................................................
+
+# Id: Unique identifier of element; no default
+id.attrib = attribute id { xsd:ID }?
+# Id: Unique identifier of element; a value must be supplied; no
+# default
+idreq.attrib = attribute id { xsd:ID }
+# Lang: Indicator of language in which element is written, for
+# translation, character set management, etc.; no default
+lang.attrib = attribute lang { text }?
+# Remap: Previous role of element before conversion; no default
+remap.attrib = attribute remap { text }?
+# Role: New role of element in local environment; no default
+role.attrib = attribute role { text }?
+# XRefLabel: Alternate labeling string for XRef text generation;
+# default is usually title or other appropriate label text already
+# contained in element
+xreflabel.attrib = attribute xreflabel { text }?
+# RevisionFlag: Revision status of element; default is that element
+# wasn't revised
+revisionflag.attrib =
+  attribute revisionflag { "changed" | "added" | "deleted" | "off" }?
+local.common.attrib = empty
+# dir: Bidirectional override
+dir.attrib = attribute dir { "ltr" | "rtl" | "lro" | "rlo" }?
+# xml:base: base URI
+xml-base.attrib = attribute xml:base { text }?
+# Role is included explicitly on each element
+common.attrib =
+  id.attrib,
+  lang.attrib,
+  remap.attrib,
+  xreflabel.attrib,
+  revisionflag.attrib,
+  effectivity.attrib,
+  dir.attrib,
+  xml-base.attrib,
+  local.common.attrib
+# Role is included explicitly on each element
+idreq.common.attrib =
+  idreq.attrib,
+  lang.attrib,
+  remap.attrib,
+  xreflabel.attrib,
+  revisionflag.attrib,
+  effectivity.attrib,
+  dir.attrib,
+  xml-base.attrib,
+  local.common.attrib
+# Semi-common attributes and other attribute entities ..................
+local.graphics.attrib = empty
+# EntityRef: Name of an external entity containing the content
+# of the graphic
+
+# FileRef: Filename, qualified by a pathname if desired,
+# designating the file containing the content of the graphic
+
+# Format: Notation of the element content, if any
+
+# SrcCredit: Information about the source of the Graphic
+
+# Width: Same as CALS reprowid (desired width)
+
+# Depth: Same as CALS reprodep (desired depth)
+
+# Align: Same as CALS hplace with 'none' removed; #IMPLIED means
+# application-specific
+
+# Scale: Conflation of CALS hscale and vscale
+
+# Scalefit: Same as CALS scalefit
+graphics.attrib =
+  attribute entityref { xsd:ENTITY }?,
+  attribute fileref { text }?,
+  attribute format { notation.class }?,
+  attribute srccredit { text }?,
+  attribute width { text }?,
+  attribute contentwidth { text }?,
+  attribute depth { text }?,
+  attribute contentdepth { text }?,
+  attribute align { "left" | "right" | "center" }?,
+  attribute valign { "top" | "middle" | "bottom" }?,
+  attribute scale { text }?,
+  attribute scalefit { yesorno.attvals }?,
+  local.graphics.attrib
+local.keyaction.attrib = empty
+# Action: Key combination type; default is unspecified if one
+# child element, Simul if there is more than one; if value is
+# Other, the OtherAction attribute must have a nonempty value
+
+# OtherAction: User-defined key combination type
+keyaction.attrib =
+  attribute action {
+    "click" | "double-click" | "press" | "seq" | "simul" | "other"
+  }?,
+  attribute otheraction { text }?,
+  local.keyaction.attrib
+# Label: Identifying number or string; default is usually the
+# appropriate number or string autogenerated by a formatter
+label.attrib = attribute label { text }?
+# xml:space: whitespace treatment
+xml-space.attrib = attribute xml:space { "preserve" }?
+# Format: whether element is assumed to contain significant white
+# space
+linespecific.attrib =
+  [ a:defaultValue = "linespecific" ]
+  attribute format { "linespecific" }?,
+  xml-space.attrib,
+  attribute linenumbering { "numbered" | "unnumbered" }?,
+  attribute continuation { "continues" | "restarts" }?,
+  attribute startinglinenumber { text }?,
+  attribute language { text }?
+# Linkend: link to related information; no default
+linkend.attrib = attribute linkend { xsd:IDREF }?
+# Linkend: required link to related information
+linkendreq.attrib = attribute linkend { xsd:IDREF }
+# Linkends: link to one or more sets of related information; no
+# default
+linkends.attrib = attribute linkends { xsd:IDREFS }?
+local.mark.attrib = empty
+mark.attrib =
+  attribute mark { text }?,
+  local.mark.attrib
+# MoreInfo: whether element's content has an associated RefEntry
+moreinfo.attrib =
+  [ a:defaultValue = "none" ]
+  attribute moreinfo { "refentry" | "none" }?
+# Pagenum: number of page on which element appears; no default
+pagenum.attrib = attribute pagenum { text }?
+local.status.attrib = empty
+# Status: Editorial or publication status of the element
+# it applies to, such as "in review" or "approved for distribution"
+status.attrib =
+  attribute status { text }?,
+  local.status.attrib
+# Width: width of the longest line in the element to which it
+# pertains, in number of characters
+width.attrib = attribute width { text }?
+# ......................................................................
+
+# Title elements .......................................................
+local.title.attrib = empty
+title.role.attrib = role.attrib
+# doc:The text of the title of a section of a document or of a formal block-level element.
+title = element title { title.attlist, title.char.mix* }
+# end of title.element
+title.attlist &=
+  pagenum.attrib, common.attrib, title.role.attrib, local.title.attrib
+# end of title.attlist
+
+# end of title.module
+local.titleabbrev.attrib = empty
+titleabbrev.role.attrib = role.attrib
+# doc:The abbreviation of a Title.
+titleabbrev =
+  element titleabbrev { titleabbrev.attlist, title.char.mix* }
+# end of titleabbrev.element
+titleabbrev.attlist &=
+  common.attrib, titleabbrev.role.attrib, local.titleabbrev.attrib
+# end of titleabbrev.attlist
+
+# end of titleabbrev.module
+local.subtitle.attrib = empty
+subtitle.role.attrib = role.attrib
+# doc:The subtitle of a document.
+subtitle = element subtitle { subtitle.attlist, title.char.mix* }
+# end of subtitle.element
+subtitle.attlist &=
+  common.attrib, subtitle.role.attrib, local.subtitle.attrib
+# end of subtitle.attlist
+
+# end of subtitle.module
+
+# ......................................................................
+
+# Bibliographic entities and elements ..................................
+
+# The bibliographic elements are typically used in the document
+# hierarchy. They do not appear in content models of information
+# pool elements.  See also the document information elements,
+# below.
+local.person.ident.mix = notAllowed
+person.ident.mix =
+  honorific
+  | firstname
+  | surname
+  | lineage
+  | othername
+  | affiliation
+  | authorblurb
+  | contrib
+  | local.person.ident.mix
+local.bibliocomponent.mix = notAllowed
+bibliocomponent.mix =
+  abbrev
+  | abstract
+  | address
+  | artpagenums
+  | author
+  | authorgroup
+  | authorinitials
+  | bibliomisc
+  | biblioset
+  | collab
+  | confgroup
+  | contractnum
+  | contractsponsor
+  | copyright
+  | corpauthor
+  | corpname
+  | corpcredit
+  | date
+  | edition
+  | editor
+  | invpartnumber
+  | isbn
+  | issn
+  | issuenum
+  | orgname
+  | biblioid
+  | citebiblioid
+  | bibliosource
+  | bibliorelation
+  | bibliocoverage
+  | othercredit
+  | pagenums
+  | printhistory
+  | productname
+  | productnumber
+  | pubdate
+  | publisher
+  | publishername
+  | pubsnumber
+  | releaseinfo
+  | revhistory
+  | seriesvolnums
+  | subtitle
+  | title
+  | titleabbrev
+  | volumenum
+  | citetitle
+  | personname
+  | person.ident.mix
+  | ndxterm.class
+  | local.bibliocomponent.mix
+# I don't think this is well placed, but it needs to be here because of
+
+# the reference to bibliocomponent.mix
+local.info.class = notAllowed
+info.class =
+  graphic
+  | mediaobject
+  | legalnotice
+  | modespec
+  | subjectset
+  | keywordset
+  | itermset
+  | bibliocomponent.mix
+  | local.info.class
+# BiblioList ........................
+local.bibliolist.attrib = empty
+bibliolist.role.attrib = role.attrib
+# doc:A wrapper for a set of bibliography entries.
+bibliolist =
+  element bibliolist {
+    bibliolist.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    (biblioentry | bibliomixed)+
+  }
+# end of bibliolist.element
+bibliolist.attlist &=
+  common.attrib, bibliolist.role.attrib, local.bibliolist.attrib
+# end of bibliolist.attlist
+
+# end of bibliolist.module
+local.biblioentry.attrib = empty
+biblioentry.role.attrib = role.attrib
+# doc:An entry in a Bibliography.
+biblioentry =
+  element biblioentry {
+    biblioentry.attlist, (articleinfo | bibliocomponent.mix)+
+  }
+# end of biblioentry.element
+biblioentry.attlist &=
+  common.attrib, biblioentry.role.attrib, local.biblioentry.attrib
+# end of biblioentry.attlist
+
+# end of biblioentry.module
+local.bibliomixed.attrib = empty
+bibliomixed.role.attrib = role.attrib
+# doc:An entry in a Bibliography.
+bibliomixed =
+  element bibliomixed {
+    bibliomixed.attlist, (text | bibliocomponent.mix | bibliomset)*
+  }
+# end of bibliomixed.element
+bibliomixed.attlist &=
+  common.attrib, bibliomixed.role.attrib, local.bibliomixed.attrib
+# end of bibliomixed.attlist
+
+# end of bibliomixed.module
+local.articleinfo.attrib = empty
+articleinfo.role.attrib = role.attrib
+# doc:Meta-information for an Article.
+articleinfo = element articleinfo { articleinfo.attlist, info.class+ }
+# end of articleinfo.element
+articleinfo.attlist &=
+  common.attrib, articleinfo.role.attrib, local.articleinfo.attrib
+# end of articleinfo.attlist
+
+# end of articleinfo.module
+local.biblioset.attrib = empty
+biblioset.role.attrib = role.attrib
+# doc:A "raw" container for related bibliographic information.
+biblioset =
+  element biblioset { biblioset.attlist, bibliocomponent.mix+ }
+# end of biblioset.element
+
+# Relation: Relationship of elements contained within BiblioSet
+biblioset.attlist &=
+  attribute relation { text }?,
+  common.attrib,
+  biblioset.role.attrib,
+  local.biblioset.attrib
+# end of biblioset.attlist
+
+# end of biblioset.module
+bibliomset.role.attrib = role.attrib
+local.bibliomset.attrib = empty
+# doc:A "cooked" container for related bibliographic information.
+bibliomset =
+  element bibliomset {
+    bibliomset.attlist, (text | bibliocomponent.mix | bibliomset)*
+  }
+# end of bibliomset.element
+
+# Relation: Relationship of elements contained within BiblioMSet
+bibliomset.attlist &=
+  attribute relation { text }?,
+  common.attrib,
+  bibliomset.role.attrib,
+  local.bibliomset.attrib
+# end of bibliomset.attlist
+
+# end of bibliomset.module
+local.bibliomisc.attrib = empty
+bibliomisc.role.attrib = role.attrib
+# doc:Untyped bibliographic information.
+bibliomisc = element bibliomisc { bibliomisc.attlist, para.char.mix* }
+# end of bibliomisc.element
+bibliomisc.attlist &=
+  common.attrib, bibliomisc.role.attrib, local.bibliomisc.attrib
+# end of bibliomisc.attlist
+
+# end of bibliomisc.module
+
+# ......................................................................
+
+# Subject, Keyword, and ITermSet elements ..............................
+local.subjectset.attrib = empty
+subjectset.role.attrib = role.attrib
+# doc:A set of terms describing the subject matter of a document.
+subjectset = element subjectset { subjectset.attlist, subject+ }
+# end of subjectset.element
+
+# Scheme: Controlled vocabulary employed in SubjectTerms
+subjectset.attlist &=
+  attribute scheme { xsd:NMTOKEN }?,
+  common.attrib,
+  subjectset.role.attrib,
+  local.subjectset.attrib
+# end of subjectset.attlist
+
+# end of subjectset.module
+local.subject.attrib = empty
+subject.role.attrib = role.attrib
+# doc:One of a group of terms describing the subject matter of a document.
+subject = element subject { subject.attlist, subjectterm+ }
+# end of subject.element
+
+# Weight: Ranking of this group of SubjectTerms relative
+# to others, 0 is low, no highest value specified
+subject.attlist &=
+  attribute weight { text }?,
+  common.attrib,
+  subject.role.attrib,
+  local.subject.attrib
+# end of subject.attlist
+
+# end of subject.module
+local.subjectterm.attrib = empty
+subjectterm.role.attrib = role.attrib
+# doc:A term in a group of terms describing the subject matter of a document.
+subjectterm = element subjectterm { subjectterm.attlist, text }
+# end of subjectterm.element
+subjectterm.attlist &=
+  common.attrib, subjectterm.role.attrib, local.subjectterm.attrib
+# end of subjectterm.attlist
+
+# end of subjectterm.module
+
+# end of subjectset.content.module
+local.keywordset.attrib = empty
+keywordset.role.attrib = role.attrib
+# doc:A set of keywords describing the content of a document.
+keywordset = element keywordset { keywordset.attlist, keyword+ }
+# end of keywordset.element
+keywordset.attlist &=
+  common.attrib, keywordset.role.attrib, local.keywordset.attrib
+# end of keywordset.attlist
+
+# end of keywordset.module
+local.keyword.attrib = empty
+keyword.role.attrib = role.attrib
+# doc:One of a set of keywords describing the content of a document.
+keyword = element keyword { keyword.attlist, text }
+# end of keyword.element
+keyword.attlist &=
+  common.attrib, keyword.role.attrib, local.keyword.attrib
+# end of keyword.attlist
+
+# end of keyword.module
+
+# end of keywordset.content.module
+local.itermset.attrib = empty
+itermset.role.attrib = role.attrib
+# doc:A set of index terms in the meta-information of a document.
+itermset = element itermset { itermset.attlist, indexterm+ }
+# end of itermset.element
+itermset.attlist &=
+  common.attrib, itermset.role.attrib, local.itermset.attrib
+# end of itermset.attlist
+
+# end of itermset.module
+
+# Bibliographic info for "blocks"
+local.blockinfo.attrib = empty
+blockinfo.role.attrib = role.attrib
+# doc:Meta-information for a block element.
+blockinfo = element blockinfo { blockinfo.attlist, info.class+ }
+# end of blockinfo.element
+blockinfo.attlist &=
+  common.attrib, blockinfo.role.attrib, local.blockinfo.attrib
+# end of blockinfo.attlist
+
+# end of blockinfo.module
+
+# ......................................................................
+
+# Compound (section-ish) elements ......................................
+
+# Message set ......................
+local.msgset.attrib = empty
+msgset.role.attrib = role.attrib
+# doc:A detailed set of messages, usually error messages.
+msgset =
+  element msgset {
+    msgset.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    (msgentry+ | simplemsgentry+)
+  }
+# end of msgset.element
+msgset.attlist &= common.attrib, msgset.role.attrib, local.msgset.attrib
+# end of msgset.attlist
+
+# end of msgset.module
+local.msgentry.attrib = empty
+msgentry.role.attrib = role.attrib
+# doc:A wrapper for an entry in a message set.
+msgentry =
+  element msgentry { msgentry.attlist, msg+, msginfo?, msgexplan* }
+# end of msgentry.element
+msgentry.attlist &=
+  common.attrib, msgentry.role.attrib, local.msgentry.attrib
+# end of msgentry.attlist
+
+# end of msgentry.module
+local.simplemsgentry.attrib = empty
+simplemsgentry.role.attrib = role.attrib
+# doc:A wrapper for a simpler entry in a message set.
+simplemsgentry =
+  element simplemsgentry { simplemsgentry.attlist, msgtext, msgexplan+ }
+# end of simplemsgentry.element
+simplemsgentry.attlist &=
+  attribute audience { text }?,
+  attribute level { text }?,
+  attribute origin { text }?,
+  common.attrib,
+  simplemsgentry.role.attrib,
+  local.simplemsgentry.attrib
+# end of simplemsgentry.attlist
+
+# end of simplemsgentry.module
+local.msg.attrib = empty
+msg.role.attrib = role.attrib
+# doc:A message in a message set.
+msg = element msg { msg.attlist, title?, msgmain, (msgsub | msgrel)* }
+# end of msg.element
+msg.attlist &= common.attrib, msg.role.attrib, local.msg.attrib
+# end of msg.attlist
+
+# end of msg.module
+local.msgmain.attrib = empty
+msgmain.role.attrib = role.attrib
+# doc:The primary component of a message in a message set.
+msgmain = element msgmain { msgmain.attlist, title?, msgtext }
+# end of msgmain.element
+msgmain.attlist &=
+  common.attrib, msgmain.role.attrib, local.msgmain.attrib
+# end of msgmain.attlist
+
+# end of msgmain.module
+local.msgsub.attrib = empty
+msgsub.role.attrib = role.attrib
+# doc:A subcomponent of a message in a message set.
+msgsub = element msgsub { msgsub.attlist, title?, msgtext }
+# end of msgsub.element
+msgsub.attlist &= common.attrib, msgsub.role.attrib, local.msgsub.attrib
+# end of msgsub.attlist
+
+# end of msgsub.module
+local.msgrel.attrib = empty
+msgrel.role.attrib = role.attrib
+# doc:A related component of a message in a message set.
+msgrel = element msgrel { msgrel.attlist, title?, msgtext }
+# end of msgrel.element
+msgrel.attlist &= common.attrib, msgrel.role.attrib, local.msgrel.attrib
+# end of msgrel.attlist
+
+# end of msgrel.module
+
+# MsgText (defined in the Inlines section, below)
+local.msginfo.attrib = empty
+msginfo.role.attrib = role.attrib
+# doc:Information about a message in a message set.
+msginfo =
+  element msginfo { msginfo.attlist, (msglevel | msgorig | msgaud)* }
+# end of msginfo.element
+msginfo.attlist &=
+  common.attrib, msginfo.role.attrib, local.msginfo.attrib
+# end of msginfo.attlist
+
+# end of msginfo.module
+local.msglevel.attrib = empty
+msglevel.role.attrib = role.attrib
+# doc:The level of importance or severity of a message in a message set.
+msglevel = element msglevel { msglevel.attlist, smallcptr.char.mix* }
+# end of msglevel.element
+msglevel.attlist &=
+  common.attrib, msglevel.role.attrib, local.msglevel.attrib
+# end of msglevel.attlist
+
+# end of msglevel.module
+local.msgorig.attrib = empty
+msgorig.role.attrib = role.attrib
+# doc:The origin of a message in a message set.
+msgorig = element msgorig { msgorig.attlist, smallcptr.char.mix* }
+# end of msgorig.element
+msgorig.attlist &=
+  common.attrib, msgorig.role.attrib, local.msgorig.attrib
+# end of msgorig.attlist
+
+# end of msgorig.module
+local.msgaud.attrib = empty
+msgaud.role.attrib = role.attrib
+# doc:The audience to which a message in a message set is relevant.
+msgaud = element msgaud { msgaud.attlist, para.char.mix* }
+# end of msgaud.element
+msgaud.attlist &= common.attrib, msgaud.role.attrib, local.msgaud.attrib
+# end of msgaud.attlist
+
+# end of msgaud.module
+local.msgexplan.attrib = empty
+msgexplan.role.attrib = role.attrib
+# doc:Explanatory material relating to a message in a message set.
+msgexplan =
+  element msgexplan { msgexplan.attlist, title?, component.mix+ }
+# end of msgexplan.element
+msgexplan.attlist &=
+  common.attrib, msgexplan.role.attrib, local.msgexplan.attrib
+# end of msgexplan.attlist
+
+# end of msgexplan.module
+
+# end of msgset.content.module
+local.task.attrib = empty
+task.role.attrib = role.attrib
+# doc:A task to be completed.
+task =
+  element task {
+    task.attlist,
+    blockinfo?,
+    ndxterm.class*,
+    formalobject.title.content,
+    tasksummary?,
+    taskprerequisites?,
+    procedure,
+    example*,
+    taskrelated?
+  }
+# end of task.element
+task.attlist &= common.attrib, task.role.attrib, local.task.attrib
+# end of task.attlist
+
+# end of task.module
+local.tasksummary.attrib = empty
+tasksummary.role.attrib = role.attrib
+# doc:A summary of a task.
+tasksummary =
+  element tasksummary {
+    tasksummary.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    component.mix+
+  }
+# end of tasksummary.element
+tasksummary.attlist &=
+  common.attrib, tasksummary.role.attrib, local.tasksummary.attrib
+# end of tasksummary.attlist
+
+# end of tasksummary.module
+local.taskprerequisites.attrib = empty
+taskprerequisites.role.attrib = role.attrib
+# doc:The prerequisites for a task.
+taskprerequisites =
+  element taskprerequisites {
+    taskprerequisites.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    component.mix+
+  }
+# end of taskprerequisites.element
+taskprerequisites.attlist &=
+  common.attrib,
+  taskprerequisites.role.attrib,
+  local.taskprerequisites.attrib
+# end of taskprerequisites.attlist
+
+# end of taskprerequisites.module
+local.taskrelated.attrib = empty
+taskrelated.role.attrib = role.attrib
+# doc:Information related to a task.
+taskrelated =
+  element taskrelated {
+    taskrelated.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    component.mix+
+  }
+# end of taskrelated.element
+taskrelated.attlist &=
+  common.attrib, taskrelated.role.attrib, local.taskrelated.attrib
+# end of taskrelated.attlist
+
+# end of taskrelated.module
+
+# end of task.content.module
+
+# QandASet ........................
+local.qandaset.attrib = empty
+qandaset.role.attrib = role.attrib
+# doc:A question-and-answer set.
+qandaset =
+  element qandaset {
+    qandaset.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    qandaset.mix*,
+    (qandadiv+ | qandaentry+)
+  }
+# end of qandaset.element
+qandaset.attlist &=
+  attribute defaultlabel { "qanda" | "number" | "none" }?,
+  common.attrib,
+  qandaset.role.attrib,
+  local.qandaset.attrib
+# end of qandaset.attlist
+
+# end of qandaset.module
+local.qandadiv.attrib = empty
+qandadiv.role.attrib = role.attrib
+# doc:A titled division in a QandASet.
+qandadiv =
+  element qandadiv {
+    qandadiv.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    qandaset.mix*,
+    (qandadiv+ | qandaentry+)
+  }
+# end of qandadiv.element
+qandadiv.attlist &=
+  common.attrib, qandadiv.role.attrib, local.qandadiv.attrib
+# end of qandadiv.attlist
+
+# end of qandadiv.module
+local.qandaentry.attrib = empty
+qandaentry.role.attrib = role.attrib
+# doc:A question/answer set within a QandASet.
+qandaentry =
+  element qandaentry {
+    qandaentry.attlist, blockinfo?, revhistory?, question, answer*
+  }
+# end of qandaentry.element
+qandaentry.attlist &=
+  common.attrib, qandaentry.role.attrib, local.qandaentry.attrib
+# end of qandaentry.attlist
+
+# end of qandaentry.module
+local.question.attrib = empty
+question.role.attrib = role.attrib
+# doc:A question in a QandASet.
+question = element question { question.attlist, label?, qandaset.mix+ }
+# end of question.element
+question.attlist &=
+  common.attrib, question.role.attrib, local.question.attrib
+# end of question.attlist
+
+# end of question.module
+local.answer.attrib = empty
+answer.role.attrib = role.attrib
+# doc:An answer to a question posed in a QandASet.
+answer =
+  element answer { answer.attlist, label?, qandaset.mix*, qandaentry* }
+# end of answer.element
+answer.attlist &= common.attrib, answer.role.attrib, local.answer.attrib
+# end of answer.attlist
+
+# end of answer.module
+local.label.attrib = empty
+label.role.attrib = role.attrib
+# doc:A label on a Question or Answer.
+label = element label { label.attlist, word.char.mix* }
+# end of label.element
+label.attlist &= common.attrib, label.role.attrib, local.label.attrib
+# end of label.attlist
+
+# end of label.module
+
+# end of qandaset.content.module
+
+# Procedure ........................
+local.procedure.attrib = empty
+procedure.role.attrib = role.attrib
+# doc:A list of operations to be performed in a well-defined sequence.
+procedure =
+  element procedure {
+    procedure.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    component.mix*,
+    step+
+  }
+# end of procedure.element
+procedure.attlist &=
+  common.attrib, procedure.role.attrib, local.procedure.attrib
+# end of procedure.attlist
+
+# end of procedure.module
+local.step.attrib = empty
+step.role.attrib = role.attrib
+# doc:A unit of action in a procedure.
+step =
+  element step {
+    step.attlist,
+    title?,
+    ((component.mix+,
+      ((substeps | stepalternatives), component.mix*)?)
+     | ((substeps | stepalternatives), component.mix*))
+  }
+# end of step.element
+
+# Performance: Whether the Step must be performed
+
+# not #REQUIRED!
+step.attlist &=
+  [ a:defaultValue = "required" ]
+  attribute performance { "optional" | "required" }?,
+  common.attrib,
+  step.role.attrib,
+  local.step.attrib
+# end of step.attlist
+
+# end of step.module
+local.substeps.attrib = empty
+substeps.role.attrib = role.attrib
+# doc:A wrapper for steps that occur within steps in a procedure.
+substeps = element substeps { substeps.attlist, step+ }
+# end of substeps.element
+
+# Performance: whether entire set of substeps must be performed
+
+# not #REQUIRED!
+substeps.attlist &=
+  [ a:defaultValue = "required" ]
+  attribute performance { "optional" | "required" }?,
+  common.attrib,
+  substeps.role.attrib,
+  local.substeps.attrib
+# end of substeps.attlist
+
+# end of substeps.module
+local.stepalternatives.attrib = empty
+stepalternatives.role.attrib = role.attrib
+# doc:Alternative steps in a procedure.
+stepalternatives =
+  element stepalternatives { stepalternatives.attlist, step+ }
+# end of stepalternatives.element
+
+# Performance: Whether (one of) the alternatives must be performed
+
+# not #REQUIRED!
+stepalternatives.attlist &=
+  [ a:defaultValue = "required" ]
+  attribute performance { "optional" | "required" }?,
+  common.attrib,
+  stepalternatives.role.attrib,
+  local.stepalternatives.attrib
+# end of stepalternatives.attlist
+
+# end of stepalternatives.module
+
+# end of procedure.content.module
+
+# Sidebar ..........................
+local.sidebarinfo.attrib = empty
+sidebarinfo.role.attrib = role.attrib
+# doc:Meta-information for a Sidebar.
+sidebarinfo = element sidebarinfo { sidebarinfo.attlist, info.class+ }
+# end of sidebarinfo.element
+sidebarinfo.attlist &=
+  common.attrib, sidebarinfo.role.attrib, local.sidebarinfo.attrib
+# end of sidebarinfo.attlist
+
+# end of sidebarinfo.module
+local.sidebar.attrib = empty
+sidebar.role.attrib = role.attrib
+# doc:A portion of a document that is isolated from the main narrative flow.
+sidebar =
+  element sidebar {
+    sidebar.attlist,
+    sidebarinfo?,
+    formalobject.title.content?,
+    sidebar.mix+
+  }
+# end of sidebar.element
+sidebar.attlist &=
+  common.attrib, sidebar.role.attrib, local.sidebar.attrib
+# end of sidebar.attlist
+
+# end of sidebar.module
+
+# end of sidebar.content.model
+
+# ......................................................................
+
+# Paragraph-related elements ...........................................
+local.abstract.attrib = empty
+abstract.role.attrib = role.attrib
+# doc:A summary.
+abstract = element abstract { abstract.attlist, title?, para.class+ }
+# end of abstract.element
+abstract.attlist &=
+  common.attrib, abstract.role.attrib, local.abstract.attrib
+# end of abstract.attlist
+
+# end of abstract.module
+local.authorblurb.attrib = empty
+authorblurb.role.attrib = role.attrib
+# doc:A short description or note about an author.
+authorblurb =
+  element authorblurb { authorblurb.attlist, title?, para.class+ }
+# end of authorblurb.element
+authorblurb.attlist &=
+  common.attrib, authorblurb.role.attrib, local.authorblurb.attrib
+# end of authorblurb.attlist
+
+# end of authorblurb.module
+local.personblurb.attrib = empty
+personblurb.role.attrib = role.attrib
+# doc:A short description or note about a person.
+personblurb =
+  element personblurb { personblurb.attlist, title?, para.class+ }
+# end of personblurb.element
+personblurb.attlist &=
+  common.attrib, personblurb.role.attrib, local.personblurb.attrib
+# end of personblurb.attlist
+
+# end of personblurb.module
+local.blockquote.attrib = empty
+blockquote.role.attrib = role.attrib
+# doc:A quotation set off from the main text.
+blockquote =
+  element blockquote {
+    blockquote.attlist, blockinfo?, title?, attribution?, component.mix+
+  }
+# end of blockquote.element
+blockquote.attlist &=
+  common.attrib, blockquote.role.attrib, local.blockquote.attrib
+# end of blockquote.attlist
+
+# end of blockquote.module
+local.attribution.attrib = empty
+attribution.role.attrib = role.attrib
+# doc:The source of a block quote or epigraph.
+attribution =
+  element attribution { attribution.attlist, para.char.mix* }
+# end of attribution.element
+attribution.attlist &=
+  common.attrib, attribution.role.attrib, local.attribution.attrib
+# end of attribution.attlist
+
+# end of attribution.module
+local.bridgehead.attrib = empty
+bridgehead.role.attrib = role.attrib
+# doc:A free-floating heading.
+bridgehead = element bridgehead { bridgehead.attlist, title.char.mix* }
+# end of bridgehead.element
+
+# Renderas: Indicates the format in which the BridgeHead
+# should appear
+bridgehead.attlist &=
+  attribute renderas {
+    "other" | "sect1" | "sect2" | "sect3" | "sect4" | "sect5"
+  }?,
+  common.attrib,
+  bridgehead.role.attrib,
+  local.bridgehead.attrib
+# end of bridgehead.attlist
+
+# end of bridgehead.module
+local.remark.attrib = empty
+remark.role.attrib = role.attrib
+# doc:A remark (or comment) intended for presentation in a draft manuscript.
+remark = element remark { remark.attlist, para.char.mix* }
+# end of remark.element
+remark.attlist &= common.attrib, remark.role.attrib, local.remark.attrib
+# end of remark.attlist
+
+# end of remark.module
+local.epigraph.attrib = empty
+epigraph.role.attrib = role.attrib
+# doc:A short inscription at the beginning of a document or component.
+epigraph =
+  element epigraph {
+    epigraph.attlist, attribution?, (para.class | literallayout)+
+  }
+# end of epigraph.element
+epigraph.attlist &=
+  common.attrib, epigraph.role.attrib, local.epigraph.attrib
+# end of epigraph.attlist
+
+# Attribution (defined above)
+
+# end of epigraph.module
+local.footnote.attrib = empty
+footnote.role.attrib = role.attrib
+# doc:A footnote.
+footnote = element footnote { footnote.attlist, footnote.mix+ }
+# end of footnote.element
+footnote.attlist &=
+  label.attrib,
+  common.attrib,
+  footnote.role.attrib,
+  local.footnote.attrib
+# end of footnote.attlist
+
+# end of footnote.module
+local.highlights.attrib = empty
+highlights.role.attrib = role.attrib
+# doc:A summary of the main points of the discussed component.
+highlights = element highlights { highlights.attlist, highlights.mix+ }
+# end of highlights.element
+highlights.attlist &=
+  common.attrib, highlights.role.attrib, local.highlights.attrib
+# end of highlights.attlist
+
+# end of highlights.module
+local.formalpara.attrib = empty
+formalpara.role.attrib = role.attrib
+# doc:A paragraph with a title.
+formalpara =
+  element formalpara { formalpara.attlist, title, ndxterm.class*, para }
+# end of formalpara.element
+formalpara.attlist &=
+  common.attrib, formalpara.role.attrib, local.formalpara.attrib
+# end of formalpara.attlist
+
+# end of formalpara.module
+local.para.attrib = empty
+para.role.attrib = role.attrib
+# doc:A paragraph.
+para = element para { para.attlist, (para.char.mix | para.mix)* }
+# end of para.element
+para.attlist &= common.attrib, para.role.attrib, local.para.attrib
+# end of para.attlist
+
+# end of para.module
+local.simpara.attrib = empty
+simpara.role.attrib = role.attrib
+# doc:A paragraph that contains only text and inline markup, no block elements.
+simpara = element simpara { simpara.attlist, para.char.mix* }
+# end of simpara.element
+simpara.attlist &=
+  common.attrib, simpara.role.attrib, local.simpara.attrib
+# end of simpara.attlist
+
+# end of simpara.module
+local.admon.attrib = empty
+admon.role.attrib = role.attrib
+# doc:A note of caution.
+caution = element caution { caution.attlist, title?, admon.mix+ }
+# end of caution.element
+caution.attlist &= common.attrib, admon.role.attrib, local.admon.attrib
+# end of caution.attlist
+
+# doc:An admonition set off from the text.
+important = element important { important.attlist, title?, admon.mix+ }
+# end of important.element
+important.attlist &=
+  common.attrib, admon.role.attrib, local.admon.attrib
+# end of important.attlist
+
+# doc:A message set off from the text.
+note = element note { note.attlist, title?, admon.mix+ }
+# end of note.element
+note.attlist &= common.attrib, admon.role.attrib, local.admon.attrib
+# end of note.attlist
+
+# doc:A suggestion to the user, set off from the text.
+tip = element tip { tip.attlist, title?, admon.mix+ }
+# end of tip.element
+tip.attlist &= common.attrib, admon.role.attrib, local.admon.attrib
+# end of tip.attlist
+
+# doc:An admonition set off from the text.
+warning = element warning { warning.attlist, title?, admon.mix+ }
+# end of warning.element
+warning.attlist &= common.attrib, admon.role.attrib, local.admon.attrib
+# end of warning.attlist
+
+# end of admon.module
+
+# ......................................................................
+
+# Lists ................................................................
+
+# GlossList ........................
+local.glosslist.attrib = empty
+glosslist.role.attrib = role.attrib
+# doc:A wrapper for a set of GlossEntrys.
+glosslist =
+  element glosslist {
+    glosslist.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    glossentry+
+  }
+# end of glosslist.element
+glosslist.attlist &=
+  common.attrib, glosslist.role.attrib, local.glosslist.attrib
+# end of glosslist.attlist
+
+# end of glosslist.module
+local.glossentry.attrib = empty
+glossentry.role.attrib = role.attrib
+# doc:An entry in a Glossary or GlossList.
+glossentry =
+  element glossentry {
+    glossentry.attlist,
+    glossterm,
+    acronym?,
+    abbrev?,
+    ndxterm.class*,
+    revhistory?,
+    (glosssee | glossdef+)
+  }
+# end of glossentry.element
+
+# SortAs: String by which the GlossEntry is to be sorted
+# (alphabetized) in lieu of its proper content
+glossentry.attlist &=
+  attribute sortas { text }?,
+  common.attrib,
+  glossentry.role.attrib,
+  local.glossentry.attrib
+# end of glossentry.attlist
+
+# end of glossentry.module
+
+# GlossTerm (defined in the Inlines section, below)
+local.glossdef.attrib = empty
+glossdef.role.attrib = role.attrib
+# doc:A definition in a GlossEntry.
+glossdef =
+  element glossdef { glossdef.attlist, glossdef.mix+, glossseealso* }
+# end of glossdef.element
+
+# Subject: List of subjects; keywords for the definition
+glossdef.attlist &=
+  attribute subject { text }?,
+  common.attrib,
+  glossdef.role.attrib,
+  local.glossdef.attrib
+# end of glossdef.attlist
+
+# end of glossdef.module
+local.glosssee.attrib = empty
+glosssee.role.attrib = role.attrib
+# doc:A cross-reference from one GlossEntry to another.
+glosssee = element glosssee { glosssee.attlist, para.char.mix* }
+# end of glosssee.element
+
+# OtherTerm: Reference to the GlossEntry whose GlossTerm
+# should be displayed at the point of the GlossSee
+glosssee.attlist &=
+  attribute otherterm { xsd:IDREF }?,
+  common.attrib,
+  glosssee.role.attrib,
+  local.glosssee.attrib
+# end of glosssee.attlist
+
+# end of glosssee.module
+local.glossseealso.attrib = empty
+glossseealso.role.attrib = role.attrib
+# doc:A cross-reference from one GlossEntry to another.
+glossseealso =
+  element glossseealso { glossseealso.attlist, para.char.mix* }
+# end of glossseealso.element
+
+# OtherTerm: Reference to the GlossEntry whose GlossTerm
+# should be displayed at the point of the GlossSeeAlso
+glossseealso.attlist &=
+  attribute otherterm { xsd:IDREF }?,
+  common.attrib,
+  glossseealso.role.attrib,
+  local.glossseealso.attrib
+# end of glossseealso.attlist
+
+# end of glossseealso.module
+
+# end of glossentry.content.module
+
+# ItemizedList and OrderedList .....
+local.itemizedlist.attrib = empty
+itemizedlist.role.attrib = role.attrib
+# doc:A list in which each entry is marked with a bullet or other dingbat.
+itemizedlist =
+  element itemizedlist {
+    itemizedlist.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    listpreamble.mix*,
+    listitem+
+  }
+# end of itemizedlist.element
+
+# Spacing: Whether the vertical space in the list should be
+# compressed
+
+# Mark: Keyword, e.g., bullet, dash, checkbox, none;
+# list of keywords and defaults are implementation specific
+itemizedlist.attlist &=
+  attribute spacing { "normal" | "compact" }?,
+  mark.attrib,
+  common.attrib,
+  itemizedlist.role.attrib,
+  local.itemizedlist.attrib
+# end of itemizedlist.attlist
+
+# end of itemizedlist.module
+local.orderedlist.attrib = empty
+orderedlist.role.attrib = role.attrib
+# doc:A list in which each entry is marked with a sequentially incremented label.
+orderedlist =
+  element orderedlist {
+    orderedlist.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    listpreamble.mix*,
+    listitem+
+  }
+# end of orderedlist.element
+
+# Numeration: Style of ListItem numbered; default is expected
+# to be Arabic
+
+# InheritNum: Specifies for a nested list that the numbering
+# of ListItems should include the number of the item
+# within which they are nested (e.g., 1a and 1b within 1,
+# rather than a and b)
+
+# Continuation: Where list numbering begins afresh (Restarts,
+# the default) or continues that of the immediately preceding
+# list (Continues)
+
+# Spacing: Whether the vertical space in the list should be
+# compressed
+orderedlist.attlist &=
+  attribute numeration {
+    "arabic" | "upperalpha" | "loweralpha" | "upperroman" | "lowerroman"
+  }?,
+  [ a:defaultValue = "ignore" ]
+  attribute inheritnum { "inherit" | "ignore" }?,
+  [ a:defaultValue = "restarts" ]
+  attribute continuation { "continues" | "restarts" }?,
+  attribute spacing { "normal" | "compact" }?,
+  common.attrib,
+  orderedlist.role.attrib,
+  local.orderedlist.attrib
+# end of orderedlist.attlist
+
+# end of orderedlist.module
+local.listitem.attrib = empty
+listitem.role.attrib = role.attrib
+# doc:A wrapper for the elements of a list item.
+listitem = element listitem { listitem.attlist, component.mix+ }
+# end of listitem.element
+
+# Override: Indicates the mark to be used for this ListItem
+# instead of the default mark or the mark specified by
+# the Mark attribute on the enclosing ItemizedList
+listitem.attlist &=
+  attribute override { text }?,
+  common.attrib,
+  listitem.role.attrib,
+  local.listitem.attrib
+# end of listitem.attlist
+
+# end of listitem.module
+
+# SegmentedList ....................
+local.segmentedlist.attrib = empty
+segmentedlist.role.attrib = role.attrib
+# doc:A segmented list, a list of sets of elements.
+segmentedlist =
+  element segmentedlist {
+    segmentedlist.attlist,
+    formalobject.title.content?,
+    segtitle+,
+    seglistitem+
+  }
+# end of segmentedlist.element
+segmentedlist.attlist &=
+  common.attrib, segmentedlist.role.attrib, local.segmentedlist.attrib
+# end of segmentedlist.attlist
+
+# end of segmentedlist.module
+local.segtitle.attrib = empty
+segtitle.role.attrib = role.attrib
+# doc:The title of an element of a list item in a segmented list.
+segtitle = element segtitle { segtitle.attlist, title.char.mix* }
+# end of segtitle.element
+segtitle.attlist &=
+  common.attrib, segtitle.role.attrib, local.segtitle.attrib
+# end of segtitle.attlist
+
+# end of segtitle.module
+local.seglistitem.attrib = empty
+seglistitem.role.attrib = role.attrib
+# doc:A list item in a segmented list.
+seglistitem = element seglistitem { seglistitem.attlist, seg+ }
+# end of seglistitem.element
+seglistitem.attlist &=
+  common.attrib, seglistitem.role.attrib, local.seglistitem.attrib
+# end of seglistitem.attlist
+
+# end of seglistitem.module
+local.seg.attrib = empty
+seg.role.attrib = role.attrib
+# doc:An element of a list item in a segmented list.
+seg = element seg { seg.attlist, para.char.mix* }
+# end of seg.element
+seg.attlist &= common.attrib, seg.role.attrib, local.seg.attrib
+# end of seg.attlist
+
+# end of seg.module
+
+# end of segmentedlist.content.module
+
+# SimpleList .......................
+local.simplelist.attrib = empty
+simplelist.role.attrib = role.attrib
+# doc:An undecorated list of single words or short phrases.
+simplelist = element simplelist { simplelist.attlist, member+ }
+# end of simplelist.element
+
+# Columns: The number of columns the array should contain
+
+# Type: How the Members of the SimpleList should be
+# formatted: Inline (members separated with commas etc.
+# inline), Vert (top to bottom in n Columns), or Horiz (in
+# the direction of text flow) in n Columns.  If Column
+# is 1 or implied, Type=Vert and Type=Horiz give the same
+# results.
+simplelist.attlist &=
+  attribute columns { text }?,
+  [ a:defaultValue = "vert" ]
+  attribute type { "inline" | "vert" | "horiz" }?,
+  common.attrib,
+  simplelist.role.attrib,
+  local.simplelist.attrib
+# end of simplelist.attlist
+
+# end of simplelist.module
+local.member.attrib = empty
+member.role.attrib = role.attrib
+# doc:An element of a simple list.
+member = element member { member.attlist, para.char.mix* }
+# end of member.element
+member.attlist &= common.attrib, member.role.attrib, local.member.attrib
+# end of member.attlist
+
+# end of member.module
+
+# end of simplelist.content.module
+
+# VariableList .....................
+local.variablelist.attrib = empty
+variablelist.role.attrib = role.attrib
+# doc:A list in which each entry is composed of a set of one or more terms and an associated description.
+variablelist =
+  element variablelist {
+    variablelist.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    listpreamble.mix*,
+    varlistentry+
+  }
+# end of variablelist.element
+
+# TermLength: Length beyond which the presentation engine
+# may consider the Term too long and select an alternate
+# presentation of the Term and, or, its associated ListItem.
+variablelist.attlist &=
+  attribute termlength { text }?,
+  attribute spacing { "normal" | "compact" }?,
+  common.attrib,
+  variablelist.role.attrib,
+  local.variablelist.attrib
+# end of variablelist.attlist
+
+# end of variablelist.module
+local.varlistentry.attrib = empty
+varlistentry.role.attrib = role.attrib
+# doc:A wrapper for a set of terms and the associated description in a variable list.
+varlistentry =
+  element varlistentry { varlistentry.attlist, term+, listitem }
+# end of varlistentry.element
+varlistentry.attlist &=
+  common.attrib, varlistentry.role.attrib, local.varlistentry.attrib
+# end of varlistentry.attlist
+
+# end of varlistentry.module
+local.term.attrib = empty
+term.role.attrib = role.attrib
+# doc:The word or phrase being defined or described in a variable list.
+term = element term { term.attlist, para.char.mix* }
+# end of term.element
+term.attlist &= common.attrib, term.role.attrib, local.term.attrib
+# end of term.attlist
+
+# end of term.module
+
+# ListItem (defined above)
+
+# end of variablelist.content.module
+
+# CalloutList ......................
+local.calloutlist.attrib = empty
+calloutlist.role.attrib = role.attrib
+# doc:A list of Callouts.
+calloutlist =
+  element calloutlist {
+    calloutlist.attlist, formalobject.title.content?, callout+
+  }
+# end of calloutlist.element
+calloutlist.attlist &=
+  common.attrib, calloutlist.role.attrib, local.calloutlist.attrib
+# end of calloutlist.attlist
+
+# end of calloutlist.module
+local.callout.attrib = empty
+callout.role.attrib = role.attrib
+# doc:A &ldquo;called out&rdquo; description of a marked Area.
+callout = element callout { callout.attlist, component.mix+ }
+# end of callout.element
+
+# AreaRefs: IDs of one or more Areas or AreaSets described
+# by this Callout
+callout.attlist &=
+  attribute arearefs { xsd:IDREFS },
+  common.attrib,
+  callout.role.attrib,
+  local.callout.attrib
+# end of callout.attlist
+
+# end of callout.module
+
+# end of calloutlist.content.module
+
+# ......................................................................
+
+# Objects ..............................................................
+
+# Examples etc. ....................
+local.example.attrib = empty
+example.role.attrib = role.attrib
+# doc:A formal example, with a title.
+example =
+  element example {
+    example.attlist,
+    blockinfo?,
+    formalobject.title.content,
+    example.mix+
+  }
+# end of example.element
+example.attlist &=
+  attribute floatstyle { text }?,
+  label.attrib,
+  width.attrib,
+  common.attrib,
+  example.role.attrib,
+  local.example.attrib
+# end of example.attlist
+
+# end of example.module
+local.informalexample.attrib = empty
+informalexample.role.attrib = role.attrib
+# doc:A displayed example without a title.
+informalexample =
+  element informalexample {
+    informalexample.attlist, blockinfo?, example.mix+
+  }
+# end of informalexample.element
+informalexample.attlist &=
+  attribute floatstyle { text }?,
+  width.attrib,
+  common.attrib,
+  informalexample.role.attrib,
+  local.informalexample.attrib
+# end of informalexample.attlist
+
+# end of informalexample.module
+local.programlistingco.attrib = empty
+programlistingco.role.attrib = role.attrib
+# doc:A program listing with associated areas used in callouts.
+programlistingco =
+  element programlistingco {
+    programlistingco.attlist, areaspec, programlisting, calloutlist*
+  }
+# end of programlistingco.element
+programlistingco.attlist &=
+  common.attrib,
+  programlistingco.role.attrib,
+  local.programlistingco.attrib
+# end of programlistingco.attlist
+
+# CalloutList (defined above in Lists)
+
+# end of informalexample.module
+local.areaspec.attrib = empty
+areaspec.role.attrib = role.attrib
+# doc:A collection of regions in a graphic or code example.
+areaspec = element areaspec { areaspec.attlist, (area | areaset)+ }
+# end of areaspec.element
+
+# Units: global unit of measure in which coordinates in
+# this spec are expressed:
+# 
+# - CALSPair "x1,y1 x2,y2": lower-left and upper-right
+# coordinates in a rectangle describing repro area in which
+# graphic is placed, where X and Y dimensions are each some
+# number 0..10000 (taken from CALS graphic attributes)
+# 
+# - LineColumn "line column": line number and column number
+# at which to start callout text in "linespecific" content
+# 
+# - LineRange "startline endline": whole lines from startline
+# to endline in "linespecific" content
+# 
+# - LineColumnPair "line1 col1 line2 col2": starting and ending
+# points of area in "linespecific" content that starts at
+# first position and ends at second position (including the
+# beginnings of any intervening lines)
+# 
+# - Other: directive to look at value of OtherUnits attribute
+# to get implementation-specific keyword
+# 
+# The default is implementation-specific; usually dependent on
+# the parent element (GraphicCO gets CALSPair, ProgramListingCO
+# and ScreenCO get LineColumn)
+
+# OtherUnits: User-defined units
+areaspec.attlist &=
+  attribute units {
+    "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other"
+  }?,
+  attribute otherunits { xsd:NMTOKEN }?,
+  common.attrib,
+  areaspec.role.attrib,
+  local.areaspec.attrib
+# end of areaspec.attlist
+
+# end of areaspec.module
+local.area.attrib = empty
+area.role.attrib = role.attrib
+# doc:A region defined for a Callout in a graphic or code example.
+area = element area { area.attlist, empty }
+# end of area.element
+
+# bug number/symbol override or initialization
+
+# to any related information
+
+# Units: unit of measure in which coordinates in this
+# area are expressed; inherits from AreaSet and AreaSpec
+
+# OtherUnits: User-defined units
+area.attlist &=
+  label.attrib,
+  linkends.attrib,
+  attribute units {
+    "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other"
+  }?,
+  attribute otherunits { xsd:NMTOKEN }?,
+  attribute coords { text },
+  idreq.common.attrib,
+  area.role.attrib,
+  local.area.attrib
+# end of area.attlist
+
+# end of area.module
+local.areaset.attrib = empty
+areaset.role.attrib = role.attrib
+# doc:A set of related areas in a graphic or code example.
+areaset = element areaset { areaset.attlist, area+ }
+# end of areaset.element
+
+# bug number/symbol override or initialization
+
+# Units: unit of measure in which coordinates in this
+# area are expressed; inherits from AreaSpec
+areaset.attlist &=
+  label.attrib,
+  attribute units {
+    "calspair" | "linecolumn" | "linerange" | "linecolumnpair" | "other"
+  }?,
+  attribute otherunits { xsd:NMTOKEN }?,
+  attribute coords { text },
+  idreq.common.attrib,
+  areaset.role.attrib,
+  local.areaset.attrib
+# end of areaset.attlist
+
+# end of areaset.module
+
+# end of areaspec.content.module
+local.programlisting.attrib = empty
+programlisting.role.attrib = role.attrib
+# doc:A literal listing of all or part of a program.
+programlisting =
+  element programlisting {
+    programlisting.attlist,
+    (para.char.mix | co | coref | lineannotation | textobject)*
+  }
+# end of programlisting.element
+programlisting.attlist &=
+  width.attrib,
+  linespecific.attrib,
+  common.attrib,
+  programlisting.role.attrib,
+  local.programlisting.attrib
+# end of programlisting.attlist
+
+# end of programlisting.module
+local.literallayout.attrib = empty
+literallayout.role.attrib = role.attrib
+# doc:A block of text in which line breaks and white space are to be reproduced faithfully.
+literallayout =
+  element literallayout {
+    literallayout.attlist,
+    (para.char.mix | co | coref | textobject | lineannotation)*
+  }
+# end of literallayout.element
+literallayout.attlist &=
+  width.attrib,
+  linespecific.attrib,
+  [ a:defaultValue = "normal" ]
+  attribute class { "monospaced" | "normal" }?,
+  common.attrib,
+  literallayout.role.attrib,
+  local.literallayout.attrib
+# end of literallayout.attlist
+
+# LineAnnotation (defined in the Inlines section, below)
+
+# end of literallayout.module
+local.screenco.attrib = empty
+screenco.role.attrib = role.attrib
+# doc:A screen with associated areas used in callouts.
+screenco =
+  element screenco { screenco.attlist, areaspec, screen, calloutlist* }
+# end of screenco.element
+screenco.attlist &=
+  common.attrib, screenco.role.attrib, local.screenco.attrib
+# end of screenco.attlist
+
+# AreaSpec (defined above)
+
+# CalloutList (defined above in Lists)
+
+# end of screenco.module
+local.screen.attrib = empty
+screen.role.attrib = role.attrib
+# doc:Text that a user sees or might see on a computer screen.
+screen =
+  element screen {
+    screen.attlist,
+    (para.char.mix | co | coref | textobject | lineannotation)*
+  }
+# end of screen.element
+screen.attlist &=
+  width.attrib,
+  linespecific.attrib,
+  common.attrib,
+  screen.role.attrib,
+  local.screen.attrib
+# end of screen.attlist
+
+# end of screen.module
+local.screenshot.attrib = empty
+screenshot.role.attrib = role.attrib
+# doc:A representation of what the user sees or might see on a computer screen.
+screenshot =
+  element screenshot {
+    screenshot.attlist,
+    screeninfo?,
+    (graphic | graphicco | mediaobject | mediaobjectco)
+  }
+# end of screenshot.element
+screenshot.attlist &=
+  common.attrib, screenshot.role.attrib, local.screenshot.attrib
+# end of screenshot.attlist
+
+# end of screenshot.module
+local.screeninfo.attrib = empty
+screeninfo.role.attrib = role.attrib
+# doc:Information about how a screen shot was produced.
+screeninfo = element screeninfo { screeninfo.attlist, para.char.mix* }
+# end of screeninfo.element
+screeninfo.attlist &=
+  common.attrib, screeninfo.role.attrib, local.screeninfo.attrib
+# end of screeninfo.attlist
+
+# end of screeninfo.module
+
+# end of screenshot.content.module
+
+# Figures etc. .....................
+local.figure.attrib = empty
+figure.role.attrib = role.attrib
+# doc:A formal figure, generally an illustration, with a title.
+figure =
+  element figure {
+    figure.attlist,
+    blockinfo?,
+    formalobject.title.content,
+    (figure.mix | link.char.class)+
+  }
+# end of figure.element
+
+# Float: Whether the Figure is supposed to be rendered
+# where convenient (yes (1) value) or at the place it occurs
+# in the text (no (0) value, the default)
+figure.attlist &=
+  [ a:defaultValue = "0" ] attribute float { yesorno.attvals }?,
+  attribute floatstyle { text }?,
+  attribute pgwide { yesorno.attvals }?,
+  label.attrib,
+  common.attrib,
+  figure.role.attrib,
+  local.figure.attrib
+# end of figure.attlist
+
+# end of figure.module
+local.informalfigure.attrib = empty
+informalfigure.role.attrib = role.attrib
+# doc:A untitled figure.
+informalfigure =
+  element informalfigure {
+    informalfigure.attlist, blockinfo?, (figure.mix | link.char.class)+
+  }
+# end of informalfigure.element
+
+# Float: Whether the Figure is supposed to be rendered
+# where convenient (yes (1) value) or at the place it occurs
+# in the text (no (0) value, the default)
+informalfigure.attlist &=
+  [ a:defaultValue = "0" ] attribute float { yesorno.attvals }?,
+  attribute floatstyle { text }?,
+  attribute pgwide { yesorno.attvals }?,
+  label.attrib,
+  common.attrib,
+  informalfigure.role.attrib,
+  local.informalfigure.attrib
+# end of informalfigure.attlist
+
+# end of informalfigure.module
+local.graphicco.attrib = empty
+graphicco.role.attrib = role.attrib
+# doc:A graphic that contains callout areas.
+graphicco =
+  element graphicco {
+    graphicco.attlist, areaspec, graphic, calloutlist*
+  }
+# end of graphicco.element
+graphicco.attlist &=
+  common.attrib, graphicco.role.attrib, local.graphicco.attrib
+# end of graphicco.attlist
+
+# AreaSpec (defined above in Examples)
+
+# CalloutList (defined above in Lists)
+
+# end of graphicco.module
+
+# Graphical data can be the content of Graphic, or you can reference
+# an external file either as an entity (Entitref) or a filename
+# (Fileref).
+local.graphic.attrib = empty
+graphic.role.attrib = role.attrib
+# doc:A displayed graphical object (not an inline).
+graphic = element graphic { graphic.attlist, empty }
+# end of graphic.element
+graphic.attlist &=
+  graphics.attrib,
+  common.attrib,
+  graphic.role.attrib,
+  local.graphic.attrib
+# end of graphic.attlist
+
+# end of graphic.module
+local.inlinegraphic.attrib = empty
+inlinegraphic.role.attrib = role.attrib
+# doc:An object containing or pointing to graphical data that will be rendered inline.
+inlinegraphic = element inlinegraphic { inlinegraphic.attlist, empty }
+# end of inlinegraphic.element
+inlinegraphic.attlist &=
+  graphics.attrib,
+  common.attrib,
+  inlinegraphic.role.attrib,
+  local.inlinegraphic.attrib
+# end of inlinegraphic.attlist
+
+# end of inlinegraphic.module
+local.mediaobject.attrib = empty
+mediaobject.role.attrib = role.attrib
+# doc:A displayed media object (video, audio, image, etc.).
+mediaobject =
+  element mediaobject {
+    mediaobject.attlist, objectinfo?, mediaobject.mix+, caption?
+  }
+# end of mediaobject.element
+mediaobject.attlist &=
+  common.attrib, mediaobject.role.attrib, local.mediaobject.attrib
+# end of mediaobject.attlist
+
+# end of mediaobject.module
+local.inlinemediaobject.attrib = empty
+inlinemediaobject.role.attrib = role.attrib
+# doc:An inline media object (video, audio, image, and so on).
+inlinemediaobject =
+  element inlinemediaobject {
+    inlinemediaobject.attlist, objectinfo?, mediaobject.mix+
+  }
+# end of inlinemediaobject.element
+inlinemediaobject.attlist &=
+  common.attrib,
+  inlinemediaobject.role.attrib,
+  local.inlinemediaobject.attrib
+# end of inlinemediaobject.attlist
+
+# end of inlinemediaobject.module
+local.videoobject.attrib = empty
+videoobject.role.attrib = role.attrib
+# doc:A wrapper for video data and its associated meta-information.
+videoobject =
+  element videoobject { videoobject.attlist, objectinfo?, videodata }
+# end of videoobject.element
+videoobject.attlist &=
+  common.attrib, videoobject.role.attrib, local.videoobject.attrib
+# end of videoobject.attlist
+
+# end of videoobject.module
+local.audioobject.attrib = empty
+audioobject.role.attrib = role.attrib
+# doc:A wrapper for audio data and its associated meta-information.
+audioobject =
+  element audioobject { audioobject.attlist, objectinfo?, audiodata }
+# end of audioobject.element
+audioobject.attlist &=
+  common.attrib, audioobject.role.attrib, local.audioobject.attrib
+# end of audioobject.attlist
+
+# end of audioobject.module
+local.imageobject.attrib = empty
+imageobject.role.attrib = role.attrib
+# doc:A wrapper for image data and its associated meta-information.
+imageobject =
+  element imageobject { imageobject.attlist, objectinfo?, imagedata }
+# end of imageobject.element
+imageobject.attlist &=
+  common.attrib, imageobject.role.attrib, local.imageobject.attrib
+# end of imageobject.attlist
+
+# end of imageobject.module
+local.textobject.attrib = empty
+textobject.role.attrib = role.attrib
+# doc:A wrapper for a text description of an object and its associated meta-information.
+textobject =
+  element textobject {
+    textobject.attlist,
+    objectinfo?,
+    (phrase | textdata | textobject.mix+)
+  }
+# end of textobject.element
+textobject.attlist &=
+  common.attrib, textobject.role.attrib, local.textobject.attrib
+# end of textobject.attlist
+
+# end of textobject.module
+local.objectinfo.attrib = empty
+objectinfo.role.attrib = role.attrib
+# doc:Meta-information for an object.
+objectinfo = element objectinfo { objectinfo.attlist, info.class+ }
+# end of objectinfo.element
+objectinfo.attlist &=
+  common.attrib, objectinfo.role.attrib, local.objectinfo.attrib
+# end of objectinfo.attlist
+
+# end of objectinfo.module
+
+# EntityRef: Name of an external entity containing the content
+# of the object data
+
+# FileRef: Filename, qualified by a pathname if desired,
+# designating the file containing the content of the object data
+
+# Format: Notation of the element content, if any
+
+# SrcCredit: Information about the source of the image
+local.objectdata.attrib = empty
+objectdata.attrib =
+  attribute entityref { xsd:ENTITY }?,
+  attribute fileref { text }?,
+  attribute format { notation.class }?,
+  attribute srccredit { text }?,
+  local.objectdata.attrib
+local.videodata.attrib = empty
+videodata.role.attrib = role.attrib
+# doc:Pointer to external video data.
+videodata = element videodata { videodata.attlist, empty }
+# end of videodata.element
+
+# Width: Same as CALS reprowid (desired width)
+
+# Depth: Same as CALS reprodep (desired depth)
+
+# Align: Same as CALS hplace with 'none' removed; #IMPLIED means
+# application-specific
+
+# Scale: Conflation of CALS hscale and vscale
+
+# Scalefit: Same as CALS scalefit
+videodata.attlist &=
+  attribute width { text }?,
+  attribute contentwidth { text }?,
+  attribute depth { text }?,
+  attribute contentdepth { text }?,
+  attribute align { "left" | "right" | "center" }?,
+  attribute valign { "top" | "middle" | "bottom" }?,
+  attribute scale { text }?,
+  attribute scalefit { yesorno.attvals }?,
+  objectdata.attrib,
+  common.attrib,
+  videodata.role.attrib,
+  local.videodata.attrib
+# end of videodata.attlist
+
+# end of videodata.module
+local.audiodata.attrib = empty
+audiodata.role.attrib = role.attrib
+# doc:Pointer to external audio data.
+audiodata = element audiodata { audiodata.attlist, empty }
+# end of audiodata.element
+audiodata.attlist &=
+  objectdata.attrib,
+  common.attrib,
+  audiodata.role.attrib,
+  local.audiodata.attrib
+# end of audiodata.attlist
+
+# end of audiodata.module
+local.imagedata.attrib = empty
+imagedata.role.attrib = role.attrib
+# doc:Pointer to external image data.
+imagedata = element imagedata { imagedata.attlist, empty }
+# end of imagedata.element
+
+# Width: Same as CALS reprowid (desired width)
+
+# Depth: Same as CALS reprodep (desired depth)
+
+# Align: Same as CALS hplace with 'none' removed; #IMPLIED means
+# application-specific
+
+# Scale: Conflation of CALS hscale and vscale
+
+# Scalefit: Same as CALS scalefit
+imagedata.attlist &=
+  attribute width { text }?,
+  attribute contentwidth { text }?,
+  attribute depth { text }?,
+  attribute contentdepth { text }?,
+  attribute align { "left" | "right" | "center" }?,
+  attribute valign { "top" | "middle" | "bottom" }?,
+  attribute scale { text }?,
+  attribute scalefit { yesorno.attvals }?,
+  objectdata.attrib,
+  common.attrib,
+  imagedata.role.attrib,
+  local.imagedata.attrib
+# end of imagedata.attlist
+
+# end of imagedata.module
+local.textdata.attrib = empty
+textdata.role.attrib = role.attrib
+# doc:Pointer to external text data.
+textdata = element textdata { textdata.attlist, empty }
+# end of textdata.element
+textdata.attlist &=
+  attribute encoding { text }?,
+  objectdata.attrib,
+  common.attrib,
+  textdata.role.attrib,
+  local.textdata.attrib
+# end of textdata.attlist
+
+# end of textdata.module
+local.mediaobjectco.attrib = empty
+mediaobjectco.role.attrib = role.attrib
+# doc:A media object that contains callouts.
+mediaobjectco =
+  element mediaobjectco {
+    mediaobjectco.attlist,
+    objectinfo?,
+    imageobjectco,
+    (imageobjectco | textobject)*
+  }
+# end of mediaobjectco.element
+mediaobjectco.attlist &=
+  common.attrib, mediaobjectco.role.attrib, local.mediaobjectco.attrib
+# end of mediaobjectco.attlist
+
+# end of mediaobjectco.module
+local.imageobjectco.attrib = empty
+imageobjectco.role.attrib = role.attrib
+# doc:A wrapper for an image object with callouts.
+imageobjectco =
+  element imageobjectco {
+    imageobjectco.attlist, areaspec, imageobject, calloutlist*
+  }
+# end of imageobjectco.element
+imageobjectco.attlist &=
+  common.attrib, imageobjectco.role.attrib, local.imageobjectco.attrib
+# end of imageobjectco.attlist
+
+# end of imageobjectco.module
+
+# end of mediaobject.content.module
+
+# Equations ........................
+
+# This PE provides a mechanism for replacing equation content,
+
+# perhaps adding a new or different model (e.g., MathML)
+equation.content = alt?, (graphic+ | mediaobject+ | mathphrase+)
+inlineequation.content =
+  alt?, (graphic+ | inlinemediaobject+ | mathphrase+)
+local.equation.attrib = empty
+equation.role.attrib = role.attrib
+# doc:A displayed mathematical equation.
+equation =
+  element equation {
+    equation.attlist,
+    blockinfo?,
+    formalobject.title.content?,
+    (informalequation | equation.content)
+  }
+# end of equation.element
+equation.attlist &=
+  attribute floatstyle { text }?,
+  label.attrib,
+  common.attrib,
+  equation.role.attrib,
+  local.equation.attrib
+# end of equation.attlist
+
+# end of equation.module
+local.informalequation.attrib = empty
+informalequation.role.attrib = role.attrib
+# doc:A displayed mathematical equation without a title.
+informalequation =
+  element informalequation {
+    informalequation.attlist, blockinfo?, equation.content
+  }
+# end of informalequation.element
+informalequation.attlist &=
+  attribute floatstyle { text }?,
+  common.attrib,
+  informalequation.role.attrib,
+  local.informalequation.attrib
+# end of informalequation.attlist
+
+# end of informalequation.module
+local.inlineequation.attrib = empty
+inlineequation.role.attrib = role.attrib
+# doc:A mathematical equation or expression occurring inline.
+inlineequation =
+  element inlineequation {
+    inlineequation.attlist, inlineequation.content
+  }
+# end of inlineequation.element
+inlineequation.attlist &=
+  common.attrib, inlineequation.role.attrib, local.inlineequation.attrib
+# end of inlineequation.attlist
+
+# end of inlineequation.module
+local.alt.attrib = empty
+alt.role.attrib = role.attrib
+# doc:Text representation for a graphical element.
+alt = element alt { alt.attlist, text }
+# end of alt.element
+alt.attlist &= common.attrib, alt.role.attrib, local.alt.attrib
+# end of alt.attlist
+
+# end of alt.module
+local.mathphrase.attrib = empty
+mathphrase.role.attrib = role.attrib
+# doc:A mathematical phrase, an expression that can be represented with ordinary text and a small amount of markup.
+mathphrase =
+  element mathphrase {
+    mathphrase.attlist, (text | subscript | superscript | emphasis)*
+  }
+# end of mathphrase.element
+mathphrase.attlist &=
+  common.attrib, mathphrase.role.attrib, local.mathphrase.attrib
+# end of mathphrase.attlist
+
+# end of mathphrase.module
+
+# Tables ...........................
+
+# Choose a table model. CALS or OASIS XML Exchange
+
+# Do we allow the HTML table model as well?
+
+# ======================================================
+
+# xhtmltbl.mod defines HTML tables and sets parameter
+# entities so that, when the CALS table module is read,
+# we end up allowing any table to be CALS or HTML.
+# i.e. This include must come first!
+
+# ======================================================
+include "htmltblx.rnc"
+# end of allow.html.tables
+
+# Add label and role attributes to table and informaltable
+
+# Add common attributes to Table, TGroup, TBody, THead, TFoot, Row,
+# EntryTbl, and Entry (and InformalTable element).
+
+# Content model for Table.
+
+# Allow either objects or inlines; beware of REs between elements.
+
+# Reference CALS Table Model
+include "calstblx.rnc"
+# end of table.module
+
+# Note that InformalTable is dependent on some of the entity
+# declarations that customize Table.
+local.informaltable.attrib = empty
+# the following entity may have been declared by the XHTML table module
+
+# doc:A table without a title.
+informaltable =
+  element informaltable {
+    informaltable.attlist, blockinfo?, informal.tbl.table.mdl
+  }
+# end of informaltable.element
+
+# Frame, Colsep, and Rowsep must be repeated because
+# they are not in entities in the table module.
+
+# includes TabStyle, ToCentry, ShortEntry,
+# Orient, PgWide
+
+# includes Label
+
+# includes common attributes
+informaltable.attlist &=
+  attribute frame { tbl.frame.attval }?,
+  attribute colsep { yesorno.attvals }?,
+  attribute rowsep { yesorno.attvals }?,
+  common.table.attribs,
+  tbl.table.att,
+  local.informaltable.attrib
+# end of informaltable.attlist
+
+# end of informaltable.module
+local.caption.attrib = empty
+caption.role.attrib = role.attrib
+# doc:A caption.
+caption = element caption { caption.attlist, (text | textobject.mix)* }
+# end of caption.element
+
+# attrs comes from HTML tables ...
+
+# common.attrib, but without ID because ID is in attrs
+caption.attlist.content =
+  caption.role.attrib,
+  attrs,
+  attribute align { "top" | "bottom" | "left" | "right" }?,
+  local.caption.attrib
+caption.attlist &= caption.attlist.content
+# end of caption.attlist
+
+# end of caption.module
+
+# ......................................................................
+
+# Synopses .............................................................
+
+# Synopsis .........................
+local.synopsis.attrib = empty
+synopsis.role.attrib = role.attrib
+# doc:A general-purpose element for representing the syntax of commands or functions.
+synopsis =
+  element synopsis {
+    synopsis.attlist,
+    (para.char.mix
+     | graphic
+     | mediaobject
+     | co
+     | coref
+     | textobject
+     | lineannotation)*
+  }
+# end of synopsis.element
+synopsis.attlist &=
+  label.attrib,
+  linespecific.attrib,
+  common.attrib,
+  synopsis.role.attrib,
+  local.synopsis.attrib
+# end of synopsis.attlist
+
+# LineAnnotation (defined in the Inlines section, below)
+
+# end of synopsis.module
+
+# CmdSynopsis ......................
+local.cmdsynopsis.attrib = empty
+cmdsynopsis.role.attrib = role.attrib
+# doc:A syntax summary for a software command.
+cmdsynopsis =
+  element cmdsynopsis {
+    cmdsynopsis.attlist, (command | arg | group | sbr)+, synopfragment*
+  }
+# end of cmdsynopsis.element
+
+# Sepchar: Character that should separate command and all
+# top-level arguments; alternate value might be e.g., &Delta;
+cmdsynopsis.attlist &=
+  label.attrib,
+  [ a:defaultValue = " " ] attribute sepchar { text }?,
+  attribute cmdlength { text }?,
+  common.attrib,
+  cmdsynopsis.role.attrib,
+  local.cmdsynopsis.attrib
+# end of cmdsynopsis.attlist
+
+# end of cmdsynopsis.module
+local.arg.attrib = empty
+arg.role.attrib = role.attrib
+# doc:An argument in a CmdSynopsis.
+arg =
+  element arg {
+    arg.attlist,
+    (text
+     | arg
+     | group
+     | option
+     | synopfragmentref
+     | replaceable
+     | sbr)*
+  }
+# end of arg.element
+
+# Choice: Whether Arg must be supplied: Opt (optional to
+# supply, e.g. [arg]; the default), Req (required to supply,
+# e.g. {arg}), or Plain (required to supply, e.g. arg)
+
+# Rep: whether Arg is repeatable: Norepeat (e.g. arg without
+# ellipsis; the default), or Repeat (e.g. arg...)
+arg.attlist &=
+  [ a:defaultValue = "opt" ]
+  attribute choice { "opt" | "req" | "plain" }?,
+  [ a:defaultValue = "norepeat" ]
+  attribute rep { "norepeat" | "repeat" }?,
+  common.attrib,
+  arg.role.attrib,
+  local.arg.attrib
+# end of arg.attlist
+
+# end of arg.module
+local.group.attrib = empty
+group.role.attrib = role.attrib
+# doc:A group of elements in a CmdSynopsis.
+group =
+  element group {
+    group.attlist,
+    (arg | group | option | synopfragmentref | replaceable | sbr)+
+  }
+# end of group.element
+
+# Choice: Whether Group must be supplied: Opt (optional to
+# supply, e.g.  [g1|g2|g3]; the default), Req (required to
+# supply, e.g.  {g1|g2|g3}), Plain (required to supply,
+# e.g.  g1|g2|g3), OptMult (can supply zero or more, e.g.
+# [[g1|g2|g3]]), or ReqMult (must supply one or more, e.g.
+# {{g1|g2|g3}})
+
+# Rep: whether Group is repeatable: Norepeat (e.g. group
+# without ellipsis; the default), or Repeat (e.g. group...)
+group.attlist &=
+  [ a:defaultValue = "opt" ]
+  attribute choice { "opt" | "req" | "plain" }?,
+  [ a:defaultValue = "norepeat" ]
+  attribute rep { "norepeat" | "repeat" }?,
+  common.attrib,
+  group.role.attrib,
+  local.group.attrib
+# end of group.attlist
+
+# end of group.module
+local.sbr.attrib = empty
+# Synopsis break
+sbr.role.attrib = role.attrib
+# doc:An explicit line break in a command synopsis.
+sbr = element sbr { sbr.attlist, empty }
+# end of sbr.element
+sbr.attlist &= common.attrib, sbr.role.attrib, local.sbr.attrib
+# end of sbr.attlist
+
+# end of sbr.module
+local.synopfragmentref.attrib = empty
+synopfragmentref.role.attrib = role.attrib
+# doc:A reference to a fragment of a command synopsis.
+synopfragmentref =
+  element synopfragmentref { synopfragmentref.attlist, text }
+# end of synopfragmentref.element
+
+# to SynopFragment of complex synopsis
+# material for separate referencing
+synopfragmentref.attlist &=
+  linkendreq.attrib,
+  common.attrib,
+  synopfragmentref.role.attrib,
+  local.synopfragmentref.attrib
+# end of synopfragmentref.attlist
+
+# end of synopfragmentref.module
+local.synopfragment.attrib = empty
+synopfragment.role.attrib = role.attrib
+# doc:A portion of a CmdSynopsis broken out from the main body of the synopsis.
+synopfragment =
+  element synopfragment { synopfragment.attlist, (arg | group)+ }
+# end of synopfragment.element
+synopfragment.attlist &=
+  idreq.common.attrib,
+  synopfragment.role.attrib,
+  local.synopfragment.attrib
+# end of synopfragment.attlist
+
+# end of synopfragment.module
+
+# Command (defined in the Inlines section, below)
+
+# Option (defined in the Inlines section, below)
+
+# Replaceable (defined in the Inlines section, below)
+
+# end of cmdsynopsis.content.module
+
+# FuncSynopsis .....................
+local.funcsynopsis.attrib = empty
+funcsynopsis.role.attrib = role.attrib
+# doc:The syntax summary for a function definition.
+funcsynopsis =
+  element funcsynopsis {
+    funcsynopsis.attlist, (funcsynopsisinfo | funcprototype)+
+  }
+# end of funcsynopsis.element
+funcsynopsis.attlist &=
+  label.attrib,
+  common.attrib,
+  funcsynopsis.role.attrib,
+  local.funcsynopsis.attrib
+# end of funcsynopsis.attlist
+
+# end of funcsynopsis.module
+local.funcsynopsisinfo.attrib = empty
+funcsynopsisinfo.role.attrib = role.attrib
+# doc:Information supplementing the FuncDefs of a FuncSynopsis.
+funcsynopsisinfo =
+  element funcsynopsisinfo {
+    funcsynopsisinfo.attlist,
+    (cptr.char.mix | textobject | lineannotation)*
+  }
+# end of funcsynopsisinfo.element
+funcsynopsisinfo.attlist &=
+  linespecific.attrib,
+  common.attrib,
+  funcsynopsisinfo.role.attrib,
+  local.funcsynopsisinfo.attrib
+# end of funcsynopsisinfo.attlist
+
+# end of funcsynopsisinfo.module
+local.funcprototype.attrib = empty
+funcprototype.role.attrib = role.attrib
+# doc:The prototype of a function.
+funcprototype =
+  element funcprototype {
+    funcprototype.attlist,
+    modifier*,
+    funcdef,
+    (void | varargs | (paramdef+, varargs?)),
+    modifier*
+  }
+# end of funcprototype.element
+funcprototype.attlist &=
+  common.attrib, funcprototype.role.attrib, local.funcprototype.attrib
+# end of funcprototype.attlist
+
+# end of funcprototype.module
+local.funcdef.attrib = empty
+funcdef.role.attrib = role.attrib
+# doc:A function (subroutine) name and its return type.
+funcdef =
+  element funcdef {
+    funcdef.attlist, (text | type | replaceable | function)*
+  }
+# end of funcdef.element
+funcdef.attlist &=
+  common.attrib, funcdef.role.attrib, local.funcdef.attrib
+# end of funcdef.attlist
+
+# end of funcdef.module
+local.void.attrib = empty
+void.role.attrib = role.attrib
+# doc:An empty element in a function synopsis indicating that the function in question takes no arguments.
+void = element void { void.attlist, empty }
+# end of void.element
+void.attlist &= common.attrib, void.role.attrib, local.void.attrib
+# end of void.attlist
+
+# end of void.module
+local.varargs.attrib = empty
+varargs.role.attrib = role.attrib
+# doc:An empty element in a function synopsis indicating a variable number of arguments.
+varargs = element varargs { varargs.attlist, empty }
+# end of varargs.element
+varargs.attlist &=
+  common.attrib, varargs.role.attrib, local.varargs.attrib
+# end of varargs.attlist
+
+# end of varargs.module
+
+# Processing assumes that only one Parameter will appear in a
+# ParamDef, and that FuncParams will be used at most once, for
+# providing information on the "inner parameters" for parameters that
+# are pointers to functions.
+local.paramdef.attrib = empty
+paramdef.role.attrib = role.attrib
+# doc:Information about a function parameter in a programming language.
+paramdef =
+  element paramdef {
+    paramdef.attlist,
+    (text | initializer | type | replaceable | parameter | funcparams)*
+  }
+# end of paramdef.element
+paramdef.attlist &=
+  attribute choice { "opt" | "req" }?,
+  common.attrib,
+  paramdef.role.attrib,
+  local.paramdef.attrib
+# end of paramdef.attlist
+
+# end of paramdef.module
+local.funcparams.attrib = empty
+funcparams.role.attrib = role.attrib
+# doc:Parameters for a function referenced through a function pointer in a synopsis.
+funcparams = element funcparams { funcparams.attlist, cptr.char.mix* }
+# end of funcparams.element
+funcparams.attlist &=
+  common.attrib, funcparams.role.attrib, local.funcparams.attrib
+# end of funcparams.attlist
+
+# end of funcparams.module
+
+# LineAnnotation (defined in the Inlines section, below)
+
+# Replaceable (defined in the Inlines section, below)
+
+# Function (defined in the Inlines section, below)
+
+# Parameter (defined in the Inlines section, below)
+
+# end of funcsynopsis.content.module
+
+# ClassSynopsis .....................
+local.classsynopsis.attrib = empty
+classsynopsis.role.attrib = role.attrib
+# doc:The syntax summary for a class definition.
+classsynopsis =
+  element classsynopsis {
+    classsynopsis.attlist,
+    (ooclass | oointerface | ooexception)+,
+    (classsynopsisinfo | fieldsynopsis | method.synop.class)*
+  }
+# end of classsynopsis.element
+classsynopsis.attlist &=
+  attribute language { text }?,
+  [ a:defaultValue = "class" ]
+  attribute class { "class" | "interface" }?,
+  common.attrib,
+  classsynopsis.role.attrib,
+  local.classsynopsis.attrib
+# end of classsynopsis.attlist
+
+# end of classsynopsis.module
+local.classsynopsisinfo.attrib = empty
+classsynopsisinfo.role.attrib = role.attrib
+# doc:Information supplementing the contents of a ClassSynopsis.
+classsynopsisinfo =
+  element classsynopsisinfo {
+    classsynopsisinfo.attlist,
+    (cptr.char.mix | textobject | lineannotation)*
+  }
+# end of classsynopsisinfo.element
+classsynopsisinfo.attlist &=
+  linespecific.attrib,
+  common.attrib,
+  classsynopsisinfo.role.attrib,
+  local.classsynopsisinfo.attrib
+# end of classsynopsisinfo.attlist
+
+# end of classsynopsisinfo.module
+local.ooclass.attrib = empty
+ooclass.role.attrib = role.attrib
+# doc:A class in an object-oriented programming language.
+ooclass =
+  element ooclass { ooclass.attlist, (modifier | package)*, classname }
+# end of ooclass.element
+ooclass.attlist &=
+  common.attrib, ooclass.role.attrib, local.ooclass.attrib
+# end of ooclass.attlist
+
+# end of ooclass.module
+local.oointerface.attrib = empty
+oointerface.role.attrib = role.attrib
+# doc:An interface in an object-oriented programming language.
+oointerface =
+  element oointerface {
+    oointerface.attlist, (modifier | package)*, interfacename
+  }
+# end of oointerface.element
+oointerface.attlist &=
+  common.attrib, oointerface.role.attrib, local.oointerface.attrib
+# end of oointerface.attlist
+
+# end of oointerface.module
+local.ooexception.attrib = empty
+ooexception.role.attrib = role.attrib
+# doc:An exception in an object-oriented programming language.
+ooexception =
+  element ooexception {
+    ooexception.attlist, (modifier | package)*, exceptionname
+  }
+# end of ooexception.element
+ooexception.attlist &=
+  common.attrib, ooexception.role.attrib, local.ooexception.attrib
+# end of ooexception.attlist
+
+# end of ooexception.module
+local.modifier.attrib = empty
+modifier.role.attrib = role.attrib
+# doc:Modifiers in a synopsis.
+modifier = element modifier { modifier.attlist, smallcptr.char.mix* }
+# end of modifier.element
+modifier.attlist &=
+  common.attrib, modifier.role.attrib, local.modifier.attrib
+# end of modifier.attlist
+
+# end of modifier.module
+local.interfacename.attrib = empty
+interfacename.role.attrib = role.attrib
+# doc:The name of an interface.
+interfacename =
+  element interfacename { interfacename.attlist, cptr.char.mix* }
+# end of interfacename.element
+interfacename.attlist &=
+  common.attrib, interfacename.role.attrib, local.interfacename.attrib
+# end of interfacename.attlist
+
+# end of interfacename.module
+local.exceptionname.attrib = empty
+exceptionname.role.attrib = role.attrib
+# doc:The name of an exception.
+exceptionname =
+  element exceptionname { exceptionname.attlist, smallcptr.char.mix* }
+# end of exceptionname.element
+exceptionname.attlist &=
+  common.attrib, exceptionname.role.attrib, local.exceptionname.attrib
+# end of exceptionname.attlist
+
+# end of exceptionname.module
+local.fieldsynopsis.attrib = empty
+fieldsynopsis.role.attrib = role.attrib
+# doc:The name of a field in a class definition.
+fieldsynopsis =
+  element fieldsynopsis {
+    fieldsynopsis.attlist, modifier*, type?, varname, initializer?
+  }
+# end of fieldsynopsis.element
+fieldsynopsis.attlist &=
+  attribute language { text }?,
+  common.attrib,
+  fieldsynopsis.role.attrib,
+  local.fieldsynopsis.attrib
+# end of fieldsynopsis.attlist
+
+# end of fieldsynopsis.module
+local.initializer.attrib = empty
+initializer.role.attrib = role.attrib
+# doc:The initializer for a FieldSynopsis.
+initializer =
+  element initializer { initializer.attlist, smallcptr.char.mix* }
+# end of initializer.element
+initializer.attlist &=
+  common.attrib, initializer.role.attrib, local.initializer.attrib
+# end of initializer.attlist
+
+# end of initializer.module
+local.constructorsynopsis.attrib = empty
+constructorsynopsis.role.attrib = role.attrib
+# doc:A syntax summary for a constructor.
+constructorsynopsis =
+  element constructorsynopsis {
+    constructorsynopsis.attlist,
+    modifier*,
+    methodname?,
+    (methodparam+ | void?),
+    exceptionname*
+  }
+# end of constructorsynopsis.element
+constructorsynopsis.attlist &=
+  attribute language { text }?,
+  common.attrib,
+  constructorsynopsis.role.attrib,
+  local.constructorsynopsis.attrib
+# end of constructorsynopsis.attlist
+
+# end of constructorsynopsis.module
+local.destructorsynopsis.attrib = empty
+destructorsynopsis.role.attrib = role.attrib
+# doc:A syntax summary for a destructor.
+destructorsynopsis =
+  element destructorsynopsis {
+    destructorsynopsis.attlist,
+    modifier*,
+    methodname?,
+    (methodparam+ | void?),
+    exceptionname*
+  }
+# end of destructorsynopsis.element
+destructorsynopsis.attlist &=
+  attribute language { text }?,
+  common.attrib,
+  destructorsynopsis.role.attrib,
+  local.destructorsynopsis.attrib
+# end of destructorsynopsis.attlist
+
+# end of destructorsynopsis.module
+local.methodsynopsis.attrib = empty
+methodsynopsis.role.attrib = role.attrib
+# doc:A syntax summary for a method.
+methodsynopsis =
+  element methodsynopsis {
+    methodsynopsis.attlist,
+    modifier*,
+    (type | void)?,
+    methodname,
+    (methodparam+ | void?),
+    exceptionname*,
+    modifier*
+  }
+# end of methodsynopsis.element
+methodsynopsis.attlist &=
+  attribute language { text }?,
+  common.attrib,
+  methodsynopsis.role.attrib,
+  local.methodsynopsis.attrib
+# end of methodsynopsis.attlist
+
+# end of methodsynopsis.module
+local.methodname.attrib = empty
+methodname.role.attrib = role.attrib
+# doc:The name of a method.
+methodname =
+  element methodname { methodname.attlist, smallcptr.char.mix* }
+# end of methodname.element
+methodname.attlist &=
+  common.attrib, methodname.role.attrib, local.methodname.attrib
+# end of methodname.attlist
+
+# end of methodname.module
+local.methodparam.attrib = empty
+methodparam.role.attrib = role.attrib
+# doc:Parameters to a method.
+methodparam =
+  element methodparam {
+    methodparam.attlist,
+    modifier*,
+    type?,
+    ((parameter, initializer?) | funcparams),
+    modifier*
+  }
+# end of methodparam.element
+methodparam.attlist &=
+  [ a:defaultValue = "req" ]
+  attribute choice { "opt" | "req" | "plain" }?,
+  [ a:defaultValue = "norepeat" ]
+  attribute rep { "norepeat" | "repeat" }?,
+  common.attrib,
+  methodparam.role.attrib,
+  local.methodparam.attrib
+# end of methodparam.attlist
+
+# end of methodparam.module
+
+# end of classsynopsis.content.module
+
+# ......................................................................
+
+# Document information entities and elements ...........................
+
+# The document information elements include some elements that are
+# currently used only in the document hierarchy module. They are
+# defined here so that they will be available for use in customized
+# document hierarchies.
+
+# ..................................
+
+# Ackno ............................
+local.ackno.attrib = empty
+ackno.role.attrib = role.attrib
+# doc:Acknowledgements in an Article.
+ackno = element ackno { ackno.attlist, docinfo.char.mix* }
+# end of ackno.element
+ackno.attlist &= common.attrib, ackno.role.attrib, local.ackno.attrib
+# end of ackno.attlist
+
+# end of ackno.module
+
+# Address ..........................
+local.address.attrib = empty
+address.role.attrib = role.attrib
+# doc:A real-world address, generally a postal address.
+address =
+  element address {
+    address.attlist,
+    (text
+     | personname
+     | person.ident.mix
+     | street
+     | pob
+     | postcode
+     | city
+     | state
+     | country
+     | phone
+     | fax
+     | email
+     | otheraddr)*
+  }
+# end of address.element
+address.attlist &=
+  linespecific.attrib,
+  common.attrib,
+  address.role.attrib,
+  local.address.attrib
+# end of address.attlist
+
+# end of address.module
+local.street.attrib = empty
+street.role.attrib = role.attrib
+# doc:A street address in an address.
+street = element street { street.attlist, docinfo.char.mix* }
+# end of street.element
+street.attlist &= common.attrib, street.role.attrib, local.street.attrib
+# end of street.attlist
+
+# end of street.module
+local.pob.attrib = empty
+pob.role.attrib = role.attrib
+# doc:A post office box in an address.
+pob = element pob { pob.attlist, docinfo.char.mix* }
+# end of pob.element
+pob.attlist &= common.attrib, pob.role.attrib, local.pob.attrib
+# end of pob.attlist
+
+# end of pob.module
+local.postcode.attrib = empty
+postcode.role.attrib = role.attrib
+# doc:A postal code in an address.
+postcode = element postcode { postcode.attlist, docinfo.char.mix* }
+# end of postcode.element
+postcode.attlist &=
+  common.attrib, postcode.role.attrib, local.postcode.attrib
+# end of postcode.attlist
+
+# end of postcode.module
+local.city.attrib = empty
+city.role.attrib = role.attrib
+# doc:The name of a city in an address.
+city = element city { city.attlist, docinfo.char.mix* }
+# end of city.element
+city.attlist &= common.attrib, city.role.attrib, local.city.attrib
+# end of city.attlist
+
+# end of city.module
+local.state.attrib = empty
+state.role.attrib = role.attrib
+# doc:A state or province in an address.
+state = element state { state.attlist, docinfo.char.mix* }
+# end of state.element
+state.attlist &= common.attrib, state.role.attrib, local.state.attrib
+# end of state.attlist
+
+# end of state.module
+local.country.attrib = empty
+country.role.attrib = role.attrib
+# doc:The name of a country.
+country = element country { country.attlist, docinfo.char.mix* }
+# end of country.element
+country.attlist &=
+  common.attrib, country.role.attrib, local.country.attrib
+# end of country.attlist
+
+# end of country.module
+local.phone.attrib = empty
+phone.role.attrib = role.attrib
+# doc:A telephone number.
+phone = element phone { phone.attlist, docinfo.char.mix* }
+# end of phone.element
+phone.attlist &= common.attrib, phone.role.attrib, local.phone.attrib
+# end of phone.attlist
+
+# end of phone.module
+local.fax.attrib = empty
+fax.role.attrib = role.attrib
+# doc:A fax number.
+fax = element fax { fax.attlist, docinfo.char.mix* }
+# end of fax.element
+fax.attlist &= common.attrib, fax.role.attrib, local.fax.attrib
+# end of fax.attlist
+
+# end of fax.module
+
+# Email (defined in the Inlines section, below)
+local.otheraddr.attrib = empty
+otheraddr.role.attrib = role.attrib
+# doc:Uncategorized information in address.
+otheraddr = element otheraddr { otheraddr.attlist, docinfo.char.mix* }
+# end of otheraddr.element
+otheraddr.attlist &=
+  common.attrib, otheraddr.role.attrib, local.otheraddr.attrib
+# end of otheraddr.attlist
+
+# end of otheraddr.module
+
+# end of address.content.module
+
+# Affiliation ......................
+local.affiliation.attrib = empty
+affiliation.role.attrib = role.attrib
+# doc:The institutional affiliation of an individual.
+affiliation =
+  element affiliation {
+    affiliation.attlist,
+    shortaffil?,
+    jobtitle*,
+    orgname?,
+    orgdiv*,
+    address*
+  }
+# end of affiliation.element
+affiliation.attlist &=
+  common.attrib, affiliation.role.attrib, local.affiliation.attrib
+# end of affiliation.attlist
+
+# end of affiliation.module
+local.shortaffil.attrib = empty
+shortaffil.role.attrib = role.attrib
+# doc:A brief description of an affiliation.
+shortaffil =
+  element shortaffil { shortaffil.attlist, docinfo.char.mix* }
+# end of shortaffil.element
+shortaffil.attlist &=
+  common.attrib, shortaffil.role.attrib, local.shortaffil.attrib
+# end of shortaffil.attlist
+
+# end of shortaffil.module
+local.jobtitle.attrib = empty
+jobtitle.role.attrib = role.attrib
+# doc:The title of an individual in an organization.
+jobtitle = element jobtitle { jobtitle.attlist, docinfo.char.mix* }
+# end of jobtitle.element
+jobtitle.attlist &=
+  common.attrib, jobtitle.role.attrib, local.jobtitle.attrib
+# end of jobtitle.attlist
+
+# end of jobtitle.module
+
+# OrgName (defined elsewhere in this section)
+local.orgdiv.attrib = empty
+orgdiv.role.attrib = role.attrib
+# doc:A division of an organization.
+orgdiv = element orgdiv { orgdiv.attlist, docinfo.char.mix* }
+# end of orgdiv.element
+orgdiv.attlist &= common.attrib, orgdiv.role.attrib, local.orgdiv.attrib
+# end of orgdiv.attlist
+
+# end of orgdiv.module
+
+# Address (defined elsewhere in this section)
+
+# end of affiliation.content.module
+
+# ArtPageNums ......................
+local.artpagenums.attrib = empty
+artpagenums.role.attrib = role.attrib
+# doc:The page numbers of an article as published.
+artpagenums =
+  element artpagenums { artpagenums.attlist, docinfo.char.mix* }
+# end of artpagenums.element
+artpagenums.attlist &=
+  common.attrib, artpagenums.role.attrib, local.artpagenums.attrib
+# end of artpagenums.attlist
+
+# end of artpagenums.module
+
+# PersonName
+local.personname.attrib = empty
+personname.role.attrib = role.attrib
+# doc:The personal name of an individual.
+personname =
+  element personname {
+    personname.attlist,
+    (honorific | firstname | surname | lineage | othername)+
+  }
+# end of personname.element
+personname.attlist &=
+  common.attrib, personname.role.attrib, local.personname.attrib
+# end of personname.attlist
+
+# end of personname.module
+
+# Author ...........................
+local.author.attrib = empty
+author.role.attrib = role.attrib
+# doc:The name of an individual author.
+author =
+  element author {
+    author.attlist,
+    (personname | person.ident.mix+),
+    (personblurb | email | address)*
+  }
+# end of author.element
+author.attlist &= common.attrib, author.role.attrib, local.author.attrib
+# end of author.attlist
+
+# (see "Personal identity elements" for %person.ident.mix;)
+
+# end of author.module
+
+# AuthorGroup ......................
+local.authorgroup.attrib = empty
+authorgroup.role.attrib = role.attrib
+# doc:Wrapper for author information when a document has multiple authors or collabarators.
+authorgroup =
+  element authorgroup {
+    authorgroup.attlist,
+    (author | editor | collab | corpauthor | corpcredit | othercredit)+
+  }
+# end of authorgroup.element
+authorgroup.attlist &=
+  common.attrib, authorgroup.role.attrib, local.authorgroup.attrib
+# end of authorgroup.attlist
+
+# end of authorgroup.module
+
+# Author (defined elsewhere in this section)
+
+# Editor (defined elsewhere in this section)
+local.collab.attrib = empty
+collab.role.attrib = role.attrib
+# doc:Identifies a collaborator.
+collab = element collab { collab.attlist, collabname, affiliation* }
+# end of collab.element
+collab.attlist &= common.attrib, collab.role.attrib, local.collab.attrib
+# end of collab.attlist
+
+# end of collab.module
+local.collabname.attrib = empty
+collabname.role.attrib = role.attrib
+# doc:The name of a collaborator.
+collabname =
+  element collabname { collabname.attlist, docinfo.char.mix* }
+# end of collabname.element
+collabname.attlist &=
+  common.attrib, collabname.role.attrib, local.collabname.attrib
+# end of collabname.attlist
+
+# end of collabname.module
+
+# Affiliation (defined elsewhere in this section)
+
+# end of collab.content.module
+
+# CorpAuthor (defined elsewhere in this section)
+
+# OtherCredit (defined elsewhere in this section)
+
+# end of authorgroup.content.module
+
+# AuthorInitials ...................
+local.authorinitials.attrib = empty
+authorinitials.role.attrib = role.attrib
+# doc:The initials or other short identifier for an author.
+authorinitials =
+  element authorinitials { authorinitials.attlist, docinfo.char.mix* }
+# end of authorinitials.element
+authorinitials.attlist &=
+  common.attrib, authorinitials.role.attrib, local.authorinitials.attrib
+# end of authorinitials.attlist
+
+# end of authorinitials.module
+
+# ConfGroup ........................
+local.confgroup.attrib = empty
+confgroup.role.attrib = role.attrib
+# doc:A wrapper for document meta-information about a conference.
+confgroup =
+  element confgroup {
+    confgroup.attlist,
+    (confdates | conftitle | confnum | address | confsponsor)*
+  }
+# end of confgroup.element
+confgroup.attlist &=
+  common.attrib, confgroup.role.attrib, local.confgroup.attrib
+# end of confgroup.attlist
+
+# end of confgroup.module
+local.confdates.attrib = empty
+confdates.role.attrib = role.attrib
+# doc:The dates of a conference for which a document was written.
+confdates = element confdates { confdates.attlist, docinfo.char.mix* }
+# end of confdates.element
+confdates.attlist &=
+  common.attrib, confdates.role.attrib, local.confdates.attrib
+# end of confdates.attlist
+
+# end of confdates.module
+local.conftitle.attrib = empty
+conftitle.role.attrib = role.attrib
+# doc:The title of a conference for which a document was written.
+conftitle = element conftitle { conftitle.attlist, docinfo.char.mix* }
+# end of conftitle.element
+conftitle.attlist &=
+  common.attrib, conftitle.role.attrib, local.conftitle.attrib
+# end of conftitle.attlist
+
+# end of conftitle.module
+local.confnum.attrib = empty
+confnum.role.attrib = role.attrib
+# doc:An identifier, frequently numerical, associated with a conference for which a document was written.
+confnum = element confnum { confnum.attlist, docinfo.char.mix* }
+# end of confnum.element
+confnum.attlist &=
+  common.attrib, confnum.role.attrib, local.confnum.attrib
+# end of confnum.attlist
+
+# end of confnum.module
+
+# Address (defined elsewhere in this section)
+local.confsponsor.attrib = empty
+confsponsor.role.attrib = role.attrib
+# doc:The sponsor of a conference for which a document was written.
+confsponsor =
+  element confsponsor { confsponsor.attlist, docinfo.char.mix* }
+# end of confsponsor.element
+confsponsor.attlist &=
+  common.attrib, confsponsor.role.attrib, local.confsponsor.attrib
+# end of confsponsor.attlist
+
+# end of confsponsor.module
+
+# end of confgroup.content.module
+
+# ContractNum ......................
+local.contractnum.attrib = empty
+contractnum.role.attrib = role.attrib
+# doc:The contract number of a document.
+contractnum =
+  element contractnum { contractnum.attlist, docinfo.char.mix* }
+# end of contractnum.element
+contractnum.attlist &=
+  common.attrib, contractnum.role.attrib, local.contractnum.attrib
+# end of contractnum.attlist
+
+# end of contractnum.module
+
+# ContractSponsor ..................
+local.contractsponsor.attrib = empty
+contractsponsor.role.attrib = role.attrib
+# doc:The sponsor of a contract.
+contractsponsor =
+  element contractsponsor { contractsponsor.attlist, docinfo.char.mix* }
+# end of contractsponsor.element
+contractsponsor.attlist &=
+  common.attrib,
+  contractsponsor.role.attrib,
+  local.contractsponsor.attrib
+# end of contractsponsor.attlist
+
+# end of contractsponsor.module
+
+# Copyright ........................
+local.copyright.attrib = empty
+copyright.role.attrib = role.attrib
+# doc:Copyright information about a document.
+copyright = element copyright { copyright.attlist, year+, holder* }
+# end of copyright.element
+copyright.attlist &=
+  common.attrib, copyright.role.attrib, local.copyright.attrib
+# end of copyright.attlist
+
+# end of copyright.module
+local.year.attrib = empty
+year.role.attrib = role.attrib
+# doc:The year of publication of a document.
+year = element year { year.attlist, docinfo.char.mix* }
+# end of year.element
+year.attlist &= common.attrib, year.role.attrib, local.year.attrib
+# end of year.attlist
+
+# end of year.module
+local.holder.attrib = empty
+holder.role.attrib = role.attrib
+# doc:The name of the individual or organization that holds a copyright.
+holder = element holder { holder.attlist, docinfo.char.mix* }
+# end of holder.element
+holder.attlist &= common.attrib, holder.role.attrib, local.holder.attrib
+# end of holder.attlist
+
+# end of holder.module
+
+# end of copyright.content.module
+
+# CorpAuthor .......................
+local.corpauthor.attrib = empty
+corpauthor.role.attrib = role.attrib
+# doc:A corporate author, as opposed to an individual.
+corpauthor =
+  element corpauthor { corpauthor.attlist, docinfo.char.mix* }
+# end of corpauthor.element
+corpauthor.attlist &=
+  common.attrib, corpauthor.role.attrib, local.corpauthor.attrib
+# end of corpauthor.attlist
+
+# end of corpauthor.module
+
+# CorpCredit ......................
+local.corpcredit.attrib = empty
+corpcredit.role.attrib = role.attrib
+# doc:A corporation or organization credited in a document.
+corpcredit =
+  element corpcredit { corpcredit.attlist, docinfo.char.mix* }
+# end of corpcredit.element
+corpcredit.attlist &=
+  attribute class {
+    "graphicdesigner"
+    | "productioneditor"
+    | "copyeditor"
+    | "technicaleditor"
+    | "translator"
+    | "other"
+  }?,
+  common.attrib,
+  corpcredit.role.attrib,
+  local.corpcredit.attrib
+# end of corpcredit.attlist
+
+# end of corpcredit.module
+
+# CorpName .........................
+local.corpname.attrib = empty
+# doc:The name of a corporation.
+corpname = element corpname { corpname.attlist, docinfo.char.mix* }
+# end of corpname.element
+corpname.role.attrib = role.attrib
+corpname.attlist &=
+  common.attrib, corpname.role.attrib, local.corpname.attrib
+# end of corpname.attlist
+
+# end of corpname.module
+
+# Date .............................
+local.date.attrib = empty
+date.role.attrib = role.attrib
+# doc:The date of publication or revision of a document.
+date = element date { date.attlist, docinfo.char.mix* }
+# end of date.element
+date.attlist &= common.attrib, date.role.attrib, local.date.attrib
+# end of date.attlist
+
+# end of date.module
+
+# Edition ..........................
+local.edition.attrib = empty
+edition.role.attrib = role.attrib
+# doc:The name or number of an edition of a document.
+edition = element edition { edition.attlist, docinfo.char.mix* }
+# end of edition.element
+edition.attlist &=
+  common.attrib, edition.role.attrib, local.edition.attrib
+# end of edition.attlist
+
+# end of edition.module
+
+# Editor ...........................
+local.editor.attrib = empty
+editor.role.attrib = role.attrib
+# doc:The name of the editor of a document.
+editor =
+  element editor {
+    editor.attlist,
+    (personname | person.ident.mix+),
+    (personblurb | email | address)*
+  }
+# end of editor.element
+editor.attlist &= common.attrib, editor.role.attrib, local.editor.attrib
+# end of editor.attlist
+
+# (see "Personal identity elements" for %person.ident.mix;)
+
+# end of editor.module
+
+# ISBN .............................
+local.isbn.attrib = empty
+isbn.role.attrib = role.attrib
+# doc:The International Standard Book Number of a document.
+isbn = element isbn { isbn.attlist, docinfo.char.mix* }
+# end of isbn.element
+isbn.attlist &= common.attrib, isbn.role.attrib, local.isbn.attrib
+# end of isbn.attlist
+
+# end of isbn.module
+
+# ISSN .............................
+local.issn.attrib = empty
+issn.role.attrib = role.attrib
+# doc:The International Standard Serial Number of a periodical.
+issn = element issn { issn.attlist, docinfo.char.mix* }
+# end of issn.element
+issn.attlist &= common.attrib, issn.role.attrib, local.issn.attrib
+# end of issn.attlist
+
+# end of issn.module
+
+# BiblioId .................
+biblio.class.attrib =
+  attribute class {
+    "uri"
+    | "doi"
+    | "isbn"
+    | "isrn"
+    | "issn"
+    | "libraryofcongress"
+    | "pubnumber"
+    | "other"
+  }?,
+  attribute otherclass { text }?
+local.biblioid.attrib = empty
+biblioid.role.attrib = role.attrib
+# doc:An identifier for a document.
+biblioid = element biblioid { biblioid.attlist, docinfo.char.mix* }
+# end of biblioid.element
+biblioid.attlist &=
+  biblio.class.attrib,
+  common.attrib,
+  biblioid.role.attrib,
+  local.biblioid.attrib
+# end of biblioid.attlist
+
+# end of biblioid.module
+
+# CiteBiblioId .................
+local.citebiblioid.attrib = empty
+citebiblioid.role.attrib = role.attrib
+# doc:A citation of a bibliographic identifier.
+citebiblioid =
+  element citebiblioid { citebiblioid.attlist, docinfo.char.mix* }
+# end of citebiblioid.element
+citebiblioid.attlist &=
+  biblio.class.attrib,
+  common.attrib,
+  citebiblioid.role.attrib,
+  local.citebiblioid.attrib
+# end of citebiblioid.attlist
+
+# end of citebiblioid.module
+
+# BiblioSource .................
+local.bibliosource.attrib = empty
+bibliosource.role.attrib = role.attrib
+# doc:The source of a document.
+bibliosource =
+  element bibliosource { bibliosource.attlist, docinfo.char.mix* }
+# end of bibliosource.element
+bibliosource.attlist &=
+  biblio.class.attrib,
+  common.attrib,
+  bibliosource.role.attrib,
+  local.bibliosource.attrib
+# end of bibliosource.attlist
+
+# end of bibliosource.module
+
+# BiblioRelation .................
+local.bibliorelation.attrib = empty
+local.bibliorelation.types = notAllowed
+bibliorelation.type.attrib =
+  attribute type {
+    "isversionof"
+    | "hasversion"
+    | "isreplacedby"
+    | "replaces"
+    | "isrequiredby"
+    | "requires"
+    | "ispartof"
+    | "haspart"
+    | "isreferencedby"
+    | "references"
+    | "isformatof"
+    | "hasformat"
+    | "othertype"
+    | local.bibliorelation.types
+  }?,
+  attribute othertype { text }?
+bibliorelation.role.attrib = role.attrib
+# doc:The relationship of a document to another.
+bibliorelation =
+  element bibliorelation { bibliorelation.attlist, docinfo.char.mix* }
+# end of bibliorelation.element
+bibliorelation.attlist &=
+  biblio.class.attrib,
+  bibliorelation.type.attrib,
+  common.attrib,
+  bibliorelation.role.attrib,
+  local.bibliorelation.attrib
+# end of bibliorelation.attlist
+
+# end of bibliorelation.module
+
+# BiblioCoverage .................
+local.bibliocoverage.attrib = empty
+bibliocoverage.role.attrib = role.attrib
+# doc:The spatial or temporal coverage of a document.
+bibliocoverage =
+  element bibliocoverage { bibliocoverage.attlist, docinfo.char.mix* }
+# end of bibliocoverage.element
+bibliocoverage.attlist &=
+  attribute spatial {
+    "dcmipoint" | "iso3166" | "dcmibox" | "tgn" | "otherspatial"
+  }?,
+  attribute otherspatial { text }?,
+  attribute temporal { "dcmiperiod" | "w3c-dtf" | "othertemporal" }?,
+  attribute othertemporal { text }?,
+  common.attrib,
+  bibliocoverage.role.attrib,
+  local.bibliocoverage.attrib
+# end of bibliocoverage.attlist
+
+# end of bibliocoverage.module
+
+# InvPartNumber ....................
+local.invpartnumber.attrib = empty
+invpartnumber.role.attrib = role.attrib
+# doc:An inventory part number.
+invpartnumber =
+  element invpartnumber { invpartnumber.attlist, docinfo.char.mix* }
+# end of invpartnumber.element
+invpartnumber.attlist &=
+  common.attrib, invpartnumber.role.attrib, local.invpartnumber.attrib
+# end of invpartnumber.attlist
+
+# end of invpartnumber.module
+
+# IssueNum .........................
+local.issuenum.attrib = empty
+issuenum.role.attrib = role.attrib
+# doc:The number of an issue of a journal.
+issuenum = element issuenum { issuenum.attlist, docinfo.char.mix* }
+# end of issuenum.element
+issuenum.attlist &=
+  common.attrib, issuenum.role.attrib, local.issuenum.attrib
+# end of issuenum.attlist
+
+# end of issuenum.module
+
+# LegalNotice ......................
+local.legalnotice.attrib = empty
+legalnotice.role.attrib = role.attrib
+# doc:A statement of legal obligations or requirements.
+legalnotice =
+  element legalnotice {
+    legalnotice.attlist, blockinfo?, title?, legalnotice.mix+
+  }
+# end of legalnotice.element
+legalnotice.attlist &=
+  common.attrib, legalnotice.role.attrib, local.legalnotice.attrib
+# end of legalnotice.attlist
+
+# end of legalnotice.module
+
+# ModeSpec .........................
+local.modespec.attrib = empty
+modespec.role.attrib = role.attrib
+# doc:Application-specific information necessary for the completion of an OLink.
+modespec = element modespec { modespec.attlist, docinfo.char.mix* }
+# end of modespec.element
+
+# Application: Type of action required for completion
+# of the links to which the ModeSpec is relevant (e.g.,
+# retrieval query)
+modespec.attlist &=
+  attribute application { notation.class }?,
+  common.attrib,
+  modespec.role.attrib,
+  local.modespec.attrib
+# end of modespec.attlist
+
+# end of modespec.module
+
+# OrgName ..........................
+local.orgname.attrib = empty
+orgname.role.attrib = role.attrib
+# doc:The name of an organization other than a corporation.
+orgname = element orgname { orgname.attlist, docinfo.char.mix* }
+# end of orgname.element
+orgname.attlist &=
+  common.attrib,
+  attribute class {
+    "corporation" | "nonprofit" | "consortium" | "informal" | "other"
+  }?,
+  attribute otherclass { text }?,
+  orgname.role.attrib,
+  local.orgname.attrib
+# end of orgname.attlist
+
+# end of orgname.module
+
+# OtherCredit ......................
+local.othercredit.attrib = empty
+othercredit.role.attrib = role.attrib
+# doc:A person or entity, other than an author or editor, credited in a document.
+othercredit =
+  element othercredit {
+    othercredit.attlist,
+    (personname | person.ident.mix+),
+    (personblurb | email | address)*
+  }
+# end of othercredit.element
+othercredit.attlist &=
+  attribute class {
+    "graphicdesigner"
+    | "productioneditor"
+    | "copyeditor"
+    | "technicaleditor"
+    | "translator"
+    | "other"
+  }?,
+  common.attrib,
+  othercredit.role.attrib,
+  local.othercredit.attrib
+# end of othercredit.attlist
+
+# (see "Personal identity elements" for %person.ident.mix;)
+
+# end of othercredit.module
+
+# PageNums .........................
+local.pagenums.attrib = empty
+pagenums.role.attrib = role.attrib
+# doc:The numbers of the pages in a book, for use in a bibliographic entry.
+pagenums = element pagenums { pagenums.attlist, docinfo.char.mix* }
+# end of pagenums.element
+pagenums.attlist &=
+  common.attrib, pagenums.role.attrib, local.pagenums.attrib
+# end of pagenums.attlist
+
+# end of pagenums.module
+
+# Personal identity elements .......
+
+# These elements are used only within Author, Editor, and
+# OtherCredit.
+local.contrib.attrib = empty
+contrib.role.attrib = role.attrib
+# doc:A summary of the contributions made to a document by a credited source.
+contrib = element contrib { contrib.attlist, docinfo.char.mix* }
+# end of contrib.element
+contrib.attlist &=
+  common.attrib, contrib.role.attrib, local.contrib.attrib
+# end of contrib.attlist
+
+# end of contrib.module
+local.firstname.attrib = empty
+firstname.role.attrib = role.attrib
+# doc:The first name of a person.
+firstname = element firstname { firstname.attlist, docinfo.char.mix* }
+# end of firstname.element
+firstname.attlist &=
+  common.attrib, firstname.role.attrib, local.firstname.attrib
+# end of firstname.attlist
+
+# end of firstname.module
+local.honorific.attrib = empty
+honorific.role.attrib = role.attrib
+# doc:The title of a person.
+honorific = element honorific { honorific.attlist, docinfo.char.mix* }
+# end of honorific.element
+honorific.attlist &=
+  common.attrib, honorific.role.attrib, local.honorific.attrib
+# end of honorific.attlist
+
+# end of honorific.module
+local.lineage.attrib = empty
+lineage.role.attrib = role.attrib
+# doc:The portion of a person's name indicating a relationship to ancestors.
+lineage = element lineage { lineage.attlist, docinfo.char.mix* }
+# end of lineage.element
+lineage.attlist &=
+  common.attrib, lineage.role.attrib, local.lineage.attrib
+# end of lineage.attlist
+
+# end of lineage.module
+local.othername.attrib = empty
+othername.role.attrib = role.attrib
+# doc:A component of a persons name that is not a first name, surname, or lineage.
+othername = element othername { othername.attlist, docinfo.char.mix* }
+# end of othername.element
+othername.attlist &=
+  common.attrib, othername.role.attrib, local.othername.attrib
+# end of othername.attlist
+
+# end of othername.module
+local.surname.attrib = empty
+surname.role.attrib = role.attrib
+# doc:A family name; in western cultures the last name.
+surname = element surname { surname.attlist, docinfo.char.mix* }
+# end of surname.element
+surname.attlist &=
+  common.attrib, surname.role.attrib, local.surname.attrib
+# end of surname.attlist
+
+# end of surname.module
+
+# end of person.ident.module
+
+# PrintHistory .....................
+local.printhistory.attrib = empty
+printhistory.role.attrib = role.attrib
+# doc:The printing history of a document.
+printhistory =
+  element printhistory { printhistory.attlist, para.class+ }
+# end of printhistory.element
+printhistory.attlist &=
+  common.attrib, printhistory.role.attrib, local.printhistory.attrib
+# end of printhistory.attlist
+
+# end of printhistory.module
+
+# ProductName ......................
+local.productname.attrib = empty
+productname.role.attrib = role.attrib
+# doc:The formal name of a product.
+productname =
+  element productname { productname.attlist, para.char.mix* }
+# end of productname.element
+
+# Class: More precisely identifies the item the element names
+productname.attlist &=
+  [ a:defaultValue = "trade" ]
+  attribute class { "service" | "trade" | "registered" | "copyright" }?,
+  common.attrib,
+  productname.role.attrib,
+  local.productname.attrib
+# end of productname.attlist
+
+# end of productname.module
+
+# ProductNumber ....................
+local.productnumber.attrib = empty
+productnumber.role.attrib = role.attrib
+# doc:A number assigned to a product.
+productnumber =
+  element productnumber { productnumber.attlist, docinfo.char.mix* }
+# end of productnumber.element
+productnumber.attlist &=
+  common.attrib, productnumber.role.attrib, local.productnumber.attrib
+# end of productnumber.attlist
+
+# end of productnumber.module
+
+# PubDate ..........................
+local.pubdate.attrib = empty
+pubdate.role.attrib = role.attrib
+# doc:The date of publication of a document.
+pubdate = element pubdate { pubdate.attlist, docinfo.char.mix* }
+# end of pubdate.element
+pubdate.attlist &=
+  common.attrib, pubdate.role.attrib, local.pubdate.attrib
+# end of pubdate.attlist
+
+# end of pubdate.module
+
+# Publisher ........................
+local.publisher.attrib = empty
+publisher.role.attrib = role.attrib
+# doc:The publisher of a document.
+publisher =
+  element publisher { publisher.attlist, publishername, address* }
+# end of publisher.element
+publisher.attlist &=
+  common.attrib, publisher.role.attrib, local.publisher.attrib
+# end of publisher.attlist
+
+# end of publisher.module
+local.publishername.attrib = empty
+publishername.role.attrib = role.attrib
+# doc:The name of the publisher of a document.
+publishername =
+  element publishername { publishername.attlist, docinfo.char.mix* }
+# end of publishername.element
+publishername.attlist &=
+  common.attrib, publishername.role.attrib, local.publishername.attrib
+# end of publishername.attlist
+
+# end of publishername.module
+
+# Address (defined elsewhere in this section)
+
+# end of publisher.content.module
+
+# PubsNumber .......................
+local.pubsnumber.attrib = empty
+pubsnumber.role.attrib = role.attrib
+# doc:A number assigned to a publication other than an ISBN or ISSN or inventory part number.
+pubsnumber =
+  element pubsnumber { pubsnumber.attlist, docinfo.char.mix* }
+# end of pubsnumber.element
+pubsnumber.attlist &=
+  common.attrib, pubsnumber.role.attrib, local.pubsnumber.attrib
+# end of pubsnumber.attlist
+
+# end of pubsnumber.module
+
+# ReleaseInfo ......................
+local.releaseinfo.attrib = empty
+releaseinfo.role.attrib = role.attrib
+# doc:Information about a particular release of a document.
+releaseinfo =
+  element releaseinfo { releaseinfo.attlist, docinfo.char.mix* }
+# end of releaseinfo.element
+releaseinfo.attlist &=
+  common.attrib, releaseinfo.role.attrib, local.releaseinfo.attrib
+# end of releaseinfo.attlist
+
+# end of releaseinfo.module
+
+# RevHistory .......................
+local.revhistory.attrib = empty
+revhistory.role.attrib = role.attrib
+# doc:A history of the revisions to a document.
+revhistory = element revhistory { revhistory.attlist, revision+ }
+# end of revhistory.element
+revhistory.attlist &=
+  common.attrib, revhistory.role.attrib, local.revhistory.attrib
+# end of revhistory.attlist
+
+# end of revhistory.module
+local.revision.attrib = empty
+revision.role.attrib = role.attrib
+# doc:An entry describing a single revision in the history of the revisions to a document.
+revision =
+  element revision {
+    revision.attlist,
+    revnumber?,
+    date,
+    (author | authorinitials)*,
+    (revremark | revdescription)?
+  }
+# end of revision.element
+revision.attlist &=
+  common.attrib, revision.role.attrib, local.revision.attrib
+# end of revision.attlist
+
+# end of revision.module
+local.revnumber.attrib = empty
+revnumber.role.attrib = role.attrib
+# doc:A document revision number.
+revnumber = element revnumber { revnumber.attlist, docinfo.char.mix* }
+# end of revnumber.element
+revnumber.attlist &=
+  common.attrib, revnumber.role.attrib, local.revnumber.attrib
+# end of revnumber.attlist
+
+# end of revnumber.module
+
+# Date (defined elsewhere in this section)
+
+# AuthorInitials (defined elsewhere in this section)
+local.revremark.attrib = empty
+revremark.role.attrib = role.attrib
+# doc:A description of a revision to a document.
+revremark = element revremark { revremark.attlist, docinfo.char.mix* }
+# end of revremark.element
+revremark.attlist &=
+  common.attrib, revremark.role.attrib, local.revremark.attrib
+# end of revremark.attlist
+
+# end of revremark.module
+local.revdescription.attrib = empty
+revdescription.role.attrib = role.attrib
+# doc:A extended description of a revision to a document.
+revdescription =
+  element revdescription { revdescription.attlist, revdescription.mix+ }
+# end of revdescription.element
+revdescription.attlist &=
+  common.attrib, revdescription.role.attrib, local.revdescription.attrib
+# end of revdescription.attlist
+
+# end of revdescription.module
+
+# end of revhistory.content.module
+
+# SeriesVolNums ....................
+local.seriesvolnums.attrib = empty
+seriesvolnums.role.attrib = role.attrib
+# doc:Numbers of the volumes in a series of books.
+seriesvolnums =
+  element seriesvolnums { seriesvolnums.attlist, docinfo.char.mix* }
+# end of seriesvolnums.element
+seriesvolnums.attlist &=
+  common.attrib, seriesvolnums.role.attrib, local.seriesvolnums.attrib
+# end of seriesvolnums.attlist
+
+# end of seriesvolnums.module
+
+# VolumeNum ........................
+local.volumenum.attrib = empty
+volumenum.role.attrib = role.attrib
+# doc:The volume number of a document in a set (as of books in a set or articles in a journal).
+volumenum = element volumenum { volumenum.attlist, docinfo.char.mix* }
+# end of volumenum.element
+volumenum.attlist &=
+  common.attrib, volumenum.role.attrib, local.volumenum.attrib
+# end of volumenum.attlist
+
+# end of volumenum.module
+
+# ..................................
+
+# end of docinfo.content.module
+
+# ......................................................................
+
+# Inline, link, and ubiquitous elements ................................
+
+# Technical and computer terms .........................................
+local.accel.attrib = empty
+accel.role.attrib = role.attrib
+# doc:A graphical user interface (GUI) keyboard shortcut.
+accel = element accel { accel.attlist, smallcptr.char.mix* }
+# end of accel.element
+accel.attlist &= common.attrib, accel.role.attrib, local.accel.attrib
+# end of accel.attlist
+
+# end of accel.module
+local.action.attrib = empty
+action.role.attrib = role.attrib
+# doc:A response to a user event.
+action = element action { action.attlist, cptr.char.mix* }
+# end of action.element
+action.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  action.role.attrib,
+  local.action.attrib
+# end of action.attlist
+
+# end of action.module
+local.application.attrib = empty
+application.role.attrib = role.attrib
+# doc:The name of a software program.
+application =
+  element application { application.attlist, para.char.mix* }
+# end of application.element
+application.attlist &=
+  attribute class { "hardware" | "software" }?,
+  moreinfo.attrib,
+  common.attrib,
+  application.role.attrib,
+  local.application.attrib
+# end of application.attlist
+
+# end of application.module
+local.classname.attrib = empty
+classname.role.attrib = role.attrib
+# doc:The name of a class, in the object-oriented programming sense.
+classname = element classname { classname.attlist, smallcptr.char.mix* }
+# end of classname.element
+classname.attlist &=
+  common.attrib, classname.role.attrib, local.classname.attrib
+# end of classname.attlist
+
+# end of classname.module
+local.package.attrib = empty
+package.role.attrib = role.attrib
+# doc:A package.
+package = element package { package.attlist, smallcptr.char.mix* }
+# end of package.element
+package.attlist &=
+  common.attrib, package.role.attrib, local.package.attrib
+# end of package.attlist
+
+# end of package.module
+local.co.attrib = empty
+# CO is a callout area of the LineColumn unit type (a single character
+# position); the position is directly indicated by the location of CO.
+co.role.attrib = role.attrib
+# doc:The location of a callout embedded in text.
+co = element co { co.attlist, empty }
+# end of co.element
+
+# bug number/symbol override or initialization
+
+# to any related information
+co.attlist &=
+  label.attrib,
+  linkends.attrib,
+  idreq.common.attrib,
+  co.role.attrib,
+  local.co.attrib
+# end of co.attlist
+
+# end of co.module
+local.coref.attrib = empty
+# COREF is a reference to a CO
+coref.role.attrib = role.attrib
+# doc:A cross reference to a co.
+coref = element coref { coref.attlist, empty }
+# end of coref.element
+
+# bug number/symbol override or initialization
+
+# to any related information
+coref.attlist &=
+  label.attrib,
+  linkendreq.attrib,
+  common.attrib,
+  coref.role.attrib,
+  local.coref.attrib
+# end of coref.attlist
+
+# end of coref.module
+local.command.attrib = empty
+command.role.attrib = role.attrib
+# doc:The name of an executable program or other software command.
+command = element command { command.attlist, cptr.char.mix* }
+# end of command.element
+command.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  command.role.attrib,
+  local.command.attrib
+# end of command.attlist
+
+# end of command.module
+local.computeroutput.attrib = empty
+computeroutput.role.attrib = role.attrib
+# doc:Data, generally text, displayed or presented by a computer.
+computeroutput =
+  element computeroutput {
+    computeroutput.attlist, (cptr.char.mix | co)*
+  }
+# end of computeroutput.element
+computeroutput.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  computeroutput.role.attrib,
+  local.computeroutput.attrib
+# end of computeroutput.attlist
+
+# end of computeroutput.module
+local.database.attrib = empty
+database.role.attrib = role.attrib
+# doc:The name of a database, or part of a database.
+database = element database { database.attlist, cptr.char.mix* }
+# end of database.element
+
+# Class: Type of database the element names; no default
+database.attlist &=
+  attribute class {
+    "name"
+    | "table"
+    | "field"
+    | "key1"
+    | "key2"
+    | "record"
+    | "index"
+    | "view"
+    | "primarykey"
+    | "secondarykey"
+    | "foreignkey"
+    | "altkey"
+    | "procedure"
+    | "datatype"
+    | "constraint"
+    | "rule"
+    | "user"
+    | "group"
+  }?,
+  moreinfo.attrib,
+  common.attrib,
+  database.role.attrib,
+  local.database.attrib
+# end of database.attlist
+
+# end of database.module
+local.email.attrib = empty
+email.role.attrib = role.attrib
+# doc:An email address.
+email = element email { email.attlist, docinfo.char.mix* }
+# end of email.element
+email.attlist &= common.attrib, email.role.attrib, local.email.attrib
+# end of email.attlist
+
+# end of email.module
+local.envar.attrib = empty
+envar.role.attrib = role.attrib
+# doc:A software environment variable.
+envar = element envar { envar.attlist, smallcptr.char.mix* }
+# end of envar.element
+envar.attlist &= common.attrib, envar.role.attrib, local.envar.attrib
+# end of envar.attlist
+
+# end of envar.module
+local.errorcode.attrib = empty
+errorcode.role.attrib = role.attrib
+# doc:An error code.
+errorcode = element errorcode { errorcode.attlist, smallcptr.char.mix* }
+# end of errorcode.element
+errorcode.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  errorcode.role.attrib,
+  local.errorcode.attrib
+# end of errorcode.attlist
+
+# end of errorcode.module
+local.errorname.attrib = empty
+errorname.role.attrib = role.attrib
+# doc:An error name.
+errorname = element errorname { errorname.attlist, smallcptr.char.mix* }
+# end of errorname.element
+errorname.attlist &=
+  common.attrib, errorname.role.attrib, local.errorname.attrib
+# end of errorname.attlist
+
+# end of errorname.module
+local.errortext.attrib = empty
+errortext.role.attrib = role.attrib
+# doc:An error message..
+errortext = element errortext { errortext.attlist, smallcptr.char.mix* }
+# end of errortext.element
+errortext.attlist &=
+  common.attrib, errortext.role.attrib, local.errortext.attrib
+# end of errortext.attlist
+
+# end of errortext.module
+local.errortype.attrib = empty
+errortype.role.attrib = role.attrib
+# doc:The classification of an error message.
+errortype = element errortype { errortype.attlist, smallcptr.char.mix* }
+# end of errortype.element
+errortype.attlist &=
+  common.attrib, errortype.role.attrib, local.errortype.attrib
+# end of errortype.attlist
+
+# end of errortype.module
+local.filename.attrib = empty
+filename.role.attrib = role.attrib
+# doc:The name of a file.
+filename = element filename { filename.attlist, cptr.char.mix* }
+# end of filename.element
+
+# Class: Type of filename the element names; no default
+
+# Path: Search path (possibly system-specific) in which
+# file can be found
+filename.attlist &=
+  attribute class {
+    "headerfile"
+    | "partition"
+    | "devicefile"
+    | "libraryfile"
+    | "directory"
+    | "extension"
+    | "symlink"
+  }?,
+  attribute path { text }?,
+  moreinfo.attrib,
+  common.attrib,
+  filename.role.attrib,
+  local.filename.attrib
+# end of filename.attlist
+
+# end of filename.module
+local.function.attrib = empty
+function.role.attrib = role.attrib
+# doc:The name of a function or subroutine, as in a programming language.
+function = element function { function.attlist, cptr.char.mix* }
+# end of function.element
+function.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  function.role.attrib,
+  local.function.attrib
+# end of function.attlist
+
+# end of function.module
+local.guibutton.attrib = empty
+guibutton.role.attrib = role.attrib
+# doc:The text on a button in a GUI.
+guibutton =
+  element guibutton {
+    guibutton.attlist,
+    (smallcptr.char.mix | accel | superscript | subscript)*
+  }
+# end of guibutton.element
+guibutton.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  guibutton.role.attrib,
+  local.guibutton.attrib
+# end of guibutton.attlist
+
+# end of guibutton.module
+local.guiicon.attrib = empty
+guiicon.role.attrib = role.attrib
+# doc:Graphic and/or text appearing as a icon in a GUI.
+guiicon =
+  element guiicon {
+    guiicon.attlist,
+    (smallcptr.char.mix | accel | superscript | subscript)*
+  }
+# end of guiicon.element
+guiicon.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  guiicon.role.attrib,
+  local.guiicon.attrib
+# end of guiicon.attlist
+
+# end of guiicon.module
+local.guilabel.attrib = empty
+guilabel.role.attrib = role.attrib
+# doc:The text of a label in a GUI.
+guilabel =
+  element guilabel {
+    guilabel.attlist,
+    (smallcptr.char.mix | accel | superscript | subscript)*
+  }
+# end of guilabel.element
+guilabel.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  guilabel.role.attrib,
+  local.guilabel.attrib
+# end of guilabel.attlist
+
+# end of guilabel.module
+local.guimenu.attrib = empty
+guimenu.role.attrib = role.attrib
+# doc:The name of a menu in a GUI.
+guimenu =
+  element guimenu {
+    guimenu.attlist,
+    (smallcptr.char.mix | accel | superscript | subscript)*
+  }
+# end of guimenu.element
+guimenu.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  guimenu.role.attrib,
+  local.guimenu.attrib
+# end of guimenu.attlist
+
+# end of guimenu.module
+local.guimenuitem.attrib = empty
+guimenuitem.role.attrib = role.attrib
+# doc:The name of a terminal menu item in a GUI.
+guimenuitem =
+  element guimenuitem {
+    guimenuitem.attlist,
+    (smallcptr.char.mix | accel | superscript | subscript)*
+  }
+# end of guimenuitem.element
+guimenuitem.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  guimenuitem.role.attrib,
+  local.guimenuitem.attrib
+# end of guimenuitem.attlist
+
+# end of guimenuitem.module
+local.guisubmenu.attrib = empty
+guisubmenu.role.attrib = role.attrib
+# doc:The name of a submenu in a GUI.
+guisubmenu =
+  element guisubmenu {
+    guisubmenu.attlist,
+    (smallcptr.char.mix | accel | superscript | subscript)*
+  }
+# end of guisubmenu.element
+guisubmenu.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  guisubmenu.role.attrib,
+  local.guisubmenu.attrib
+# end of guisubmenu.attlist
+
+# end of guisubmenu.module
+local.hardware.attrib = empty
+hardware.role.attrib = role.attrib
+# doc:A physical part of a computer system.
+hardware = element hardware { hardware.attlist, cptr.char.mix* }
+# end of hardware.element
+hardware.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  hardware.role.attrib,
+  local.hardware.attrib
+# end of hardware.attlist
+
+# end of hardware.module
+local.interface.attrib = empty
+interface.role.attrib = role.attrib
+# doc:An element of a GUI.
+interface =
+  element interface { interface.attlist, (smallcptr.char.mix | accel)* }
+# end of interface.element
+
+# Class: Type of the Interface item; no default
+interface.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  interface.role.attrib,
+  local.interface.attrib
+# end of interface.attlist
+
+# end of interface.module
+local.keycap.attrib = empty
+keycap.role.attrib = role.attrib
+# doc:The text printed on a key on a keyboard.
+keycap = element keycap { keycap.attlist, cptr.char.mix* }
+# end of keycap.element
+keycap.attlist &=
+  attribute function {
+    "alt"
+    | "control"
+    | "shift"
+    | "meta"
+    | "escape"
+    | "enter"
+    | "tab"
+    | "backspace"
+    | "command"
+    | "option"
+    | "space"
+    | "delete"
+    | "insert"
+    | "up"
+    | "down"
+    | "left"
+    | "right"
+    | "home"
+    | "end"
+    | "pageup"
+    | "pagedown"
+    | "other"
+  }?,
+  attribute otherfunction { text }?,
+  moreinfo.attrib,
+  common.attrib,
+  keycap.role.attrib,
+  local.keycap.attrib
+# end of keycap.attlist
+
+# end of keycap.module
+local.keycode.attrib = empty
+keycode.role.attrib = role.attrib
+# doc:The internal, frequently numeric, identifier for a key on a keyboard.
+keycode = element keycode { keycode.attlist, smallcptr.char.mix* }
+# end of keycode.element
+keycode.attlist &=
+  common.attrib, keycode.role.attrib, local.keycode.attrib
+# end of keycode.attlist
+
+# end of keycode.module
+local.keycombo.attrib = empty
+keycombo.role.attrib = role.attrib
+# doc:A combination of input actions.
+keycombo =
+  element keycombo {
+    keycombo.attlist, (keycap | keycombo | keysym | mousebutton)+
+  }
+# end of keycombo.element
+keycombo.attlist &=
+  keyaction.attrib,
+  moreinfo.attrib,
+  common.attrib,
+  keycombo.role.attrib,
+  local.keycombo.attrib
+# end of keycombo.attlist
+
+# end of keycombo.module
+local.keysym.attrib = empty
+keysysm.role.attrib = role.attrib
+# doc:The symbolic name of a key on a keyboard.
+keysym = element keysym { keysym.attlist, smallcptr.char.mix* }
+# end of keysym.element
+keysym.attlist &=
+  common.attrib, keysysm.role.attrib, local.keysym.attrib
+# end of keysym.attlist
+
+# end of keysym.module
+local.lineannotation.attrib = empty
+lineannotation.role.attrib = role.attrib
+# doc:A comment on a line in a verbatim listing.
+lineannotation =
+  element lineannotation { lineannotation.attlist, para.char.mix* }
+# end of lineannotation.element
+lineannotation.attlist &=
+  common.attrib, lineannotation.role.attrib, local.lineannotation.attrib
+# end of lineannotation.attlist
+
+# end of lineannotation.module
+local.literal.attrib = empty
+literal.role.attrib = role.attrib
+# doc:Inline text that is some literal value.
+literal = element literal { literal.attlist, cptr.char.mix* }
+# end of literal.element
+literal.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  literal.role.attrib,
+  local.literal.attrib
+# end of literal.attlist
+
+# end of literal.module
+local.code.attrib = empty
+code.role.attrib = role.attrib
+# doc:An inline code fragment.
+code = element code { code.attlist, cptr.char.mix* }
+# end of code.element
+code.attlist &=
+  attribute language { text }?,
+  common.attrib,
+  code.role.attrib,
+  local.code.attrib
+# end of code.attlist
+
+# end of code.module
+local.constant.attrib = empty
+constant.role.attrib = role.attrib
+# doc:A programming or system constant.
+constant = element constant { constant.attlist, smallcptr.char.mix* }
+# end of constant.element
+constant.attlist &=
+  attribute class { "limit" }?,
+  common.attrib,
+  constant.role.attrib,
+  local.constant.attrib
+# end of constant.attlist
+
+# end of constant.module
+local.varname.attrib = empty
+varname.role.attrib = role.attrib
+# doc:The name of a variable.
+varname = element varname { varname.attlist, smallcptr.char.mix* }
+# end of varname.element
+varname.attlist &=
+  common.attrib, varname.role.attrib, local.varname.attrib
+# end of varname.attlist
+
+# end of varname.module
+local.markup.attrib = empty
+markup.role.attrib = role.attrib
+# doc:A string of formatting markup in text that is to be represented literally.
+markup = element markup { markup.attlist, smallcptr.char.mix* }
+# end of markup.element
+markup.attlist &= common.attrib, markup.role.attrib, local.markup.attrib
+# end of markup.attlist
+
+# end of markup.module
+local.medialabel.attrib = empty
+medialabel.role.attrib = role.attrib
+# doc:A name that identifies the physical medium on which some information resides.
+medialabel =
+  element medialabel { medialabel.attlist, smallcptr.char.mix* }
+# end of medialabel.element
+
+# Class: Type of medium named by the element; no default
+medialabel.attlist &=
+  attribute class { "cartridge" | "cdrom" | "disk" | "tape" }?,
+  common.attrib,
+  medialabel.role.attrib,
+  local.medialabel.attrib
+# end of medialabel.attlist
+
+# end of medialabel.module
+local.menuchoice.attrib = empty
+menuchoice.role.attrib = role.attrib
+# doc:A selection or series of selections from a menu.
+menuchoice =
+  element menuchoice {
+    menuchoice.attlist,
+    shortcut?,
+    (guibutton
+     | guiicon
+     | guilabel
+     | guimenu
+     | guimenuitem
+     | guisubmenu
+     | interface)+
+  }
+# end of menuchoice.element
+menuchoice.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  menuchoice.role.attrib,
+  local.menuchoice.attrib
+# end of menuchoice.attlist
+
+# end of menuchoice.module
+
+# See also KeyCombo
+local.shortcut.attrib = empty
+shortcut.role.attrib = role.attrib
+# doc:A key combination for an action that is also accessible through a menu.
+shortcut =
+  element shortcut {
+    shortcut.attlist, (keycap | keycombo | keysym | mousebutton)+
+  }
+# end of shortcut.element
+shortcut.attlist &=
+  keyaction.attrib,
+  moreinfo.attrib,
+  common.attrib,
+  shortcut.role.attrib,
+  local.shortcut.attrib
+# end of shortcut.attlist
+
+# end of shortcut.module
+
+# end of menuchoice.content.module
+local.mousebutton.attrib = empty
+mousebutton.role.attrib = role.attrib
+# doc:The conventional name of a mouse button.
+mousebutton =
+  element mousebutton { mousebutton.attlist, smallcptr.char.mix* }
+# end of mousebutton.element
+mousebutton.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  mousebutton.role.attrib,
+  local.mousebutton.attrib
+# end of mousebutton.attlist
+
+# end of mousebutton.module
+local.msgtext.attrib = empty
+msgtext.role.attrib = role.attrib
+# doc:The actual text of a message component in a message set.
+msgtext = element msgtext { msgtext.attlist, component.mix+ }
+# end of msgtext.element
+msgtext.attlist &=
+  common.attrib, msgtext.role.attrib, local.msgtext.attrib
+# end of msgtext.attlist
+
+# end of msgtext.module
+local.option.attrib = empty
+option.role.attrib = role.attrib
+# doc:An option for a software command.
+option = element option { option.attlist, cptr.char.mix* }
+# end of option.element
+option.attlist &= common.attrib, option.role.attrib, local.option.attrib
+# end of option.attlist
+
+# end of option.module
+local.optional.attrib = empty
+optional.role.attrib = role.attrib
+# doc:Optional information.
+optional = element optional { optional.attlist, cptr.char.mix* }
+# end of optional.element
+optional.attlist &=
+  common.attrib, optional.role.attrib, local.optional.attrib
+# end of optional.attlist
+
+# end of optional.module
+local.parameter.attrib = empty
+parameter.role.attrib = role.attrib
+# doc:A value or a symbolic reference to a value.
+parameter = element parameter { parameter.attlist, cptr.char.mix* }
+# end of parameter.element
+
+# Class: Type of the Parameter; no default
+parameter.attlist &=
+  attribute class { "command" | "function" | "option" }?,
+  moreinfo.attrib,
+  common.attrib,
+  parameter.role.attrib,
+  local.parameter.attrib
+# end of parameter.attlist
+
+# end of parameter.module
+local.prompt.attrib = empty
+prompt.role.attrib = role.attrib
+# doc:A character or string indicating the start of an input field in a  computer display.
+prompt = element prompt { prompt.attlist, (smallcptr.char.mix | co)* }
+# end of prompt.element
+prompt.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  prompt.role.attrib,
+  local.prompt.attrib
+# end of prompt.attlist
+
+# end of prompt.module
+local.property.attrib = empty
+property.role.attrib = role.attrib
+# doc:A unit of data associated with some part of a computer system.
+property = element property { property.attlist, cptr.char.mix* }
+# end of property.element
+property.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  property.role.attrib,
+  local.property.attrib
+# end of property.attlist
+
+# end of property.module
+local.replaceable.attrib = empty
+replaceable.role.attrib = role.attrib
+# doc:Content that may or must be replaced by the user.
+replaceable =
+  element replaceable {
+    replaceable.attlist,
+    (text
+     | link.char.class
+     | optional
+     | base.char.class
+     | other.char.class
+     | inlinegraphic
+     | inlinemediaobject
+     | co)*
+  }
+# end of replaceable.element
+
+# Class: Type of information the element represents; no
+# default
+replaceable.attlist &=
+  attribute class { "command" | "function" | "option" | "parameter" }?,
+  common.attrib,
+  replaceable.role.attrib,
+  local.replaceable.attrib
+# end of replaceable.attlist
+
+# end of replaceable.module
+local.returnvalue.attrib = empty
+returnvalue.role.attrib = role.attrib
+# doc:The value returned by a function.
+returnvalue =
+  element returnvalue { returnvalue.attlist, smallcptr.char.mix* }
+# end of returnvalue.element
+returnvalue.attlist &=
+  common.attrib, returnvalue.role.attrib, local.returnvalue.attrib
+# end of returnvalue.attlist
+
+# end of returnvalue.module
+local.sgmltag.attrib = empty
+sgmltag.role.attrib = role.attrib
+# doc:A component of SGML markup.
+sgmltag = element sgmltag { sgmltag.attlist, smallcptr.char.mix* }
+# end of sgmltag.element
+
+# Class: Type of SGML construct the element names; no default
+sgmltag.attlist &=
+  attribute class {
+    "attribute"
+    | "attvalue"
+    | "element"
+    | "endtag"
+    | "emptytag"
+    | "genentity"
+    | "numcharref"
+    | "paramentity"
+    | "pi"
+    | "xmlpi"
+    | "starttag"
+    | "sgmlcomment"
+    | "prefix"
+    | "namespace"
+    | "localname"
+  }?,
+  attribute namespace { text }?,
+  common.attrib,
+  sgmltag.role.attrib,
+  local.sgmltag.attrib
+# end of sgmltag.attlist
+
+# end of sgmltag.module
+local.structfield.attrib = empty
+structfield.role.attrib = role.attrib
+# doc:A field in a structure (in the programming language sense).
+structfield =
+  element structfield { structfield.attlist, smallcptr.char.mix* }
+# end of structfield.element
+structfield.attlist &=
+  common.attrib, structfield.role.attrib, local.structfield.attrib
+# end of structfield.attlist
+
+# end of structfield.module
+local.structname.attrib = empty
+structname.role.attrib = role.attrib
+# doc:The name of a structure (in the programming language sense).
+structname =
+  element structname { structname.attlist, smallcptr.char.mix* }
+# end of structname.element
+structname.attlist &=
+  common.attrib, structname.role.attrib, local.structname.attrib
+# end of structname.attlist
+
+# end of structname.module
+local.symbol.attrib = empty
+symbol.role.attrib = role.attrib
+# doc:A name that is replaced by a value before processing.
+symbol = element symbol { symbol.attlist, smallcptr.char.mix* }
+# end of symbol.element
+
+# Class: Type of symbol; no default
+symbol.attlist &=
+  attribute class { "limit" }?,
+  common.attrib,
+  symbol.role.attrib,
+  local.symbol.attrib
+# end of symbol.attlist
+
+# end of symbol.module
+local.systemitem.attrib = empty
+systemitem.role.attrib = role.attrib
+# doc:A system-related item or term.
+systemitem =
+  element systemitem {
+    systemitem.attlist, (cptr.char.mix | acronym | co)*
+  }
+# end of systemitem.element
+
+# Class: Type of system item the element names; no default
+systemitem.attlist &=
+  attribute class {
+    "constant"
+    | "daemon"
+    | "domainname"
+    | "etheraddress"
+    | "event"
+    | "eventhandler"
+    | "filesystem"
+    | "fqdomainname"
+    | "groupname"
+    | "ipaddress"
+    | "library"
+    | "macro"
+    | "netmask"
+    | "newsgroup"
+    | "osname"
+    | "protocol"
+    | "resource"
+    | "systemname"
+    | "username"
+    | "process"
+    | "server"
+    | "service"
+  }?,
+  moreinfo.attrib,
+  common.attrib,
+  systemitem.role.attrib,
+  local.systemitem.attrib
+# end of systemitem.attlist
+
+# end of systemitem.module
+local.uri.attrib = empty
+uri.role.attrib = role.attrib
+# doc:A Uniform Resource Identifier.
+uri = element uri { uri.attlist, smallcptr.char.mix* }
+# end of uri.element
+
+# Type: Type of URI; no default
+uri.attlist &=
+  attribute type { text }?,
+  common.attrib,
+  uri.role.attrib,
+  local.uri.attrib
+# end of uri.attlist
+
+# end of uri.module
+local.token.attrib = empty
+token.role.attrib = role.attrib
+# doc:A unit of information.
+\token = element token { token.attlist, smallcptr.char.mix* }
+# end of token.element
+token.attlist &= common.attrib, token.role.attrib, local.token.attrib
+# end of token.attlist
+
+# end of token.module
+local.type.attrib = empty
+type.role.attrib = role.attrib
+# doc:The classification of a value.
+type = element type { type.attlist, smallcptr.char.mix* }
+# end of type.element
+type.attlist &= common.attrib, type.role.attrib, local.type.attrib
+# end of type.attlist
+
+# end of type.module
+local.userinput.attrib = empty
+userinput.role.attrib = role.attrib
+# doc:Data entered by the user.
+userinput =
+  element userinput { userinput.attlist, (cptr.char.mix | co)* }
+# end of userinput.element
+userinput.attlist &=
+  moreinfo.attrib,
+  common.attrib,
+  userinput.role.attrib,
+  local.userinput.attrib
+# end of userinput.attlist
+
+# end of userinput.module
+local.termdef.attrib = empty
+termdef.role.attrib = role.attrib
+# doc:An inline definition of a term.
+termdef = element termdef { termdef.attlist, para.char.mix* }
+# end of termdef.element
+termdef.attlist &=
+  common.attrib, termdef.role.attrib, local.termdef.attrib
+# end of termdef.attlist
+
+# end of termdef.module
+
+# General words and phrases ............................................
+local.abbrev.attrib = empty
+abbrev.role.attrib = role.attrib
+# doc:An abbreviation, especially one followed by a period.
+abbrev = element abbrev { abbrev.attlist, word.char.mix* }
+# end of abbrev.element
+abbrev.attlist &= common.attrib, abbrev.role.attrib, local.abbrev.attrib
+# end of abbrev.attlist
+
+# end of abbrev.module
+local.acronym.attrib = empty
+acronym.role.attrib = role.attrib
+# doc:An often pronounceable word made from the initial (or selected) letters of a name or phrase.
+acronym = element acronym { acronym.attlist, word.char.mix* }
+# end of acronym.element
+acronym.attlist &=
+  common.attrib, acronym.role.attrib, local.acronym.attrib
+# end of acronym.attlist
+
+# end of acronym.module
+local.citation.attrib = empty
+citation.role.attrib = role.attrib
+# doc:An inline bibliographic reference to another published work.
+citation = element citation { citation.attlist, para.char.mix* }
+# end of citation.element
+citation.attlist &=
+  common.attrib, citation.role.attrib, local.citation.attrib
+# end of citation.attlist
+
+# end of citation.module
+local.citerefentry.attrib = empty
+citerefentry.role.attrib = role.attrib
+# doc:A citation to a reference page.
+citerefentry =
+  element citerefentry {
+    citerefentry.attlist, refentrytitle, manvolnum?
+  }
+# end of citerefentry.element
+citerefentry.attlist &=
+  common.attrib, citerefentry.role.attrib, local.citerefentry.attrib
+# end of citerefentry.attlist
+
+# end of citerefentry.module
+local.refentrytitle.attrib = empty
+refentrytitle.role.attrib = role.attrib
+# doc:The title of a reference page.
+refentrytitle =
+  element refentrytitle { refentrytitle.attlist, para.char.mix* }
+# end of refentrytitle.element
+refentrytitle.attlist &=
+  common.attrib, refentrytitle.role.attrib, local.refentrytitle.attrib
+# end of refentrytitle.attlist
+
+# end of refentrytitle.module
+local.manvolnum.attrib = empty
+namvolnum.role.attrib = role.attrib
+# doc:A reference volume number.
+manvolnum = element manvolnum { manvolnum.attlist, word.char.mix* }
+# end of manvolnum.element
+manvolnum.attlist &=
+  common.attrib, namvolnum.role.attrib, local.manvolnum.attrib
+# end of manvolnum.attlist
+
+# end of manvolnum.module
+local.citetitle.attrib = empty
+citetitle.role.attrib = role.attrib
+# doc:The title of a cited work.
+citetitle = element citetitle { citetitle.attlist, para.char.mix* }
+# end of citetitle.element
+
+# Pubwork: Genre of published work cited; no default
+citetitle.attlist &=
+  attribute pubwork {
+    "article"
+    | "book"
+    | "chapter"
+    | "part"
+    | "refentry"
+    | "section"
+    | "journal"
+    | "series"
+    | "set"
+    | "manuscript"
+    | "cdrom"
+    | "dvd"
+    | "wiki"
+    | "gopher"
+    | "bbs"
+    | "emailmessage"
+    | "webpage"
+    | "newsposting"
+  }?,
+  common.attrib,
+  citetitle.role.attrib,
+  local.citetitle.attrib
+# end of citetitle.attlist
+
+# end of citetitle.module
+local.emphasis.attrib = empty
+emphasis.role.attrib = role.attrib
+# doc:Emphasized text.
+emphasis = element emphasis { emphasis.attlist, para.char.mix* }
+# end of emphasis.element
+emphasis.attlist &=
+  common.attrib, emphasis.role.attrib, local.emphasis.attrib
+# end of emphasis.attlist
+
+# end of emphasis.module
+local.foreignphrase.attrib = empty
+foreignphrase.role.attrib = role.attrib
+# doc:A word or phrase in a language other than the primary language of the document.
+foreignphrase =
+  element foreignphrase { foreignphrase.attlist, para.char.mix* }
+# end of foreignphrase.element
+foreignphrase.attlist &=
+  common.attrib, foreignphrase.role.attrib, local.foreignphrase.attrib
+# end of foreignphrase.attlist
+
+# end of foreignphrase.module
+local.glossterm.attrib = empty
+glossterm.role.attrib = role.attrib
+# doc:A glossary term.
+glossterm = element glossterm { glossterm.attlist, para.char.mix* }
+# end of glossterm.element
+
+# to GlossEntry if Glossterm used in text
+
+# BaseForm: Provides the form of GlossTerm to be used
+# for indexing
+glossterm.attlist &=
+  attribute baseform { text }?,
+  linkend.attrib,
+  common.attrib,
+  glossterm.role.attrib,
+  local.glossterm.attrib
+# end of glossterm.attlist
+
+# end of glossterm.module
+local.firstterm.attrib = empty
+firstterm.role.attrib = role.attrib
+# doc:The first occurrence of a term.
+firstterm = element firstterm { firstterm.attlist, para.char.mix* }
+# end of firstterm.element
+
+# to GlossEntry or other explanation
+firstterm.attlist &=
+  attribute baseform { text }?,
+  linkend.attrib,
+  common.attrib,
+  firstterm.role.attrib,
+  local.firstterm.attrib
+# end of firstterm.attlist
+
+# end of firstterm.module
+local.phrase.attrib = empty
+phrase.role.attrib = role.attrib
+# doc:A span of text.
+phrase = element phrase { phrase.attlist, para.char.mix* }
+# end of phrase.element
+phrase.attlist &= common.attrib, phrase.role.attrib, local.phrase.attrib
+# end of phrase.attlist
+
+# end of phrase.module
+local.quote.attrib = empty
+quote.role.attrib = role.attrib
+# doc:An inline quotation.
+quote = element quote { quote.attlist, para.char.mix* }
+# end of quote.element
+quote.attlist &= common.attrib, quote.role.attrib, local.quote.attrib
+# end of quote.attlist
+
+# end of quote.module
+local.ssscript.attrib = empty
+ssscript.role.attrib = role.attrib
+# doc:A subscript (as in H{^2}O, the molecular formula for water).
+subscript =
+  element subscript {
+    subscript.attlist,
+    (text
+     | link.char.class
+     | emphasis
+     | replaceable
+     | symbol
+     | inlinegraphic
+     | inlinemediaobject
+     | base.char.class
+     | other.char.class)*
+  }
+# end of subscript.element
+subscript.attlist &=
+  common.attrib, ssscript.role.attrib, local.ssscript.attrib
+# end of subscript.attlist
+
+# doc:A superscript (as in x^2, the mathematical notation for x multiplied by itself).
+superscript =
+  element superscript {
+    superscript.attlist,
+    (text
+     | link.char.class
+     | emphasis
+     | replaceable
+     | symbol
+     | inlinegraphic
+     | inlinemediaobject
+     | base.char.class
+     | other.char.class)*
+  }
+# end of superscript.element
+superscript.attlist &=
+  common.attrib, ssscript.role.attrib, local.ssscript.attrib
+# end of superscript.attlist
+
+# end of ssscript.module
+local.trademark.attrib = empty
+trademark.role.attrib = role.attrib
+# doc:A trademark.
+trademark =
+  element trademark {
+    trademark.attlist,
+    (text
+     | link.char.class
+     | tech.char.class
+     | base.char.class
+     | other.char.class
+     | inlinegraphic
+     | inlinemediaobject
+     | emphasis)*
+  }
+# end of trademark.element
+
+# Class: More precisely identifies the item the element names
+trademark.attlist &=
+  [ a:defaultValue = "trade" ]
+  attribute class { "service" | "trade" | "registered" | "copyright" }?,
+  common.attrib,
+  trademark.role.attrib,
+  local.trademark.attrib
+# end of trademark.attlist
+
+# end of trademark.module
+local.wordasword.attrib = empty
+wordasword.role.attrib = role.attrib
+# doc:A word meant specifically as a word and not representing anything else.
+wordasword = element wordasword { wordasword.attlist, word.char.mix* }
+# end of wordasword.element
+wordasword.attlist &=
+  common.attrib, wordasword.role.attrib, local.wordasword.attrib
+# end of wordasword.attlist
+
+# end of wordasword.module
+
+# Links and cross-references ...........................................
+local.link.attrib = empty
+link.role.attrib = role.attrib
+# doc:A hypertext link.
+link = element link { link.attlist, para.char.mix* }
+# end of link.element
+
+# Endterm: ID of element containing text that is to be
+# fetched from elsewhere in the document to appear as
+# the content of this element
+
+# to linked-to object
+
+# Type: Freely assignable parameter
+link.attlist &=
+  attribute endterm { xsd:IDREF }?,
+  attribute xrefstyle { text }?,
+  attribute type { text }?,
+  linkendreq.attrib,
+  common.attrib,
+  link.role.attrib,
+  local.link.attrib
+# end of link.attlist
+
+# end of link.module
+local.olink.attrib = empty
+olink.role.attrib = role.attrib
+# doc:A link that addresses its target indirectly, through an entity.
+olink = element olink { olink.attlist, para.char.mix* }
+# end of olink.element
+
+# TargetDocEnt: Name of an entity to be the target of the link
+
+# LinkMode: ID of a ModeSpec containing instructions for
+# operating on the entity named by TargetDocEnt
+
+# LocalInfo: Information that may be passed to ModeSpec
+
+# Type: Freely assignable parameter
+olink.attlist &=
+  attribute targetdocent { xsd:ENTITY }?,
+  attribute linkmode { xsd:IDREF }?,
+  attribute localinfo { text }?,
+  attribute type { text }?,
+  attribute targetdoc { text }?,
+  attribute targetptr { text }?,
+  attribute xrefstyle { text }?,
+  common.attrib,
+  olink.role.attrib,
+  local.olink.attrib
+# end of olink.attlist
+
+# end of olink.module
+local.ulink.attrib = empty
+ulink.role.attrib = role.attrib
+# doc:A link that addresses its target by means of a URL (Uniform Resource Locator).
+ulink = element ulink { ulink.attlist, para.char.mix* }
+# end of ulink.element
+
+# URL: uniform resource locator; the target of the ULink
+
+# Type: Freely assignable parameter
+ulink.attlist &=
+  attribute url { text },
+  attribute type { text }?,
+  attribute xrefstyle { text }?,
+  common.attrib,
+  ulink.role.attrib,
+  local.ulink.attrib
+# end of ulink.attlist
+
+# end of ulink.module
+local.footnoteref.attrib = empty
+footnoteref.role.attrib = role.attrib
+# doc:A cross reference to a footnote (a footnote mark).
+footnoteref = element footnoteref { footnoteref.attlist, empty }
+# end of footnoteref.element
+
+# to footnote content supplied elsewhere
+footnoteref.attlist &=
+  linkendreq.attrib,
+  label.attrib,
+  common.attrib,
+  footnoteref.role.attrib,
+  local.footnoteref.attrib
+# end of footnoteref.attlist
+
+# end of footnoteref.module
+local.xref.attrib = empty
+xref.role.attrib = role.attrib
+# doc:A cross reference to another part of the document.
+xref = element xref { xref.attlist, empty }
+# end of xref.element
+
+# Endterm: ID of element containing text that is to be
+# fetched from elsewhere in the document to appear as
+# the content of this element
+
+# to linked-to object
+xref.attlist &=
+  attribute endterm { xsd:IDREF }?,
+  attribute xrefstyle { text }?,
+  common.attrib,
+  linkendreq.attrib,
+  xref.role.attrib,
+  local.xref.attrib
+# end of xref.attlist
+
+# end of xref.module
+local.biblioref.attrib = empty
+biblioref.role.attrib = role.attrib
+# doc:A cross reference to a bibliographic entry.
+biblioref = element biblioref { biblioref.attlist, empty }
+# end of biblioref.element
+biblioref.attlist &=
+  attribute endterm { xsd:IDREF }?,
+  attribute xrefstyle { text }?,
+  attribute units { text }?,
+  attribute begin { text }?,
+  attribute end { text }?,
+  common.attrib,
+  linkendreq.attrib,
+  biblioref.role.attrib,
+  local.biblioref.attrib
+# end of biblioref.attlist
+
+# end of biblioref.module
+
+# Ubiquitous elements ..................................................
+local.anchor.attrib = empty
+anchor.role.attrib = role.attrib
+# doc:A spot in the document.
+anchor = element anchor { anchor.attlist, empty }
+# end of anchor.element
+
+# required
+
+# replaces Lang
+anchor.attlist &=
+  idreq.attrib,
+  pagenum.attrib,
+  remap.attrib,
+  xreflabel.attrib,
+  revisionflag.attrib,
+  effectivity.attrib,
+  anchor.role.attrib,
+  local.anchor.attrib
+# end of anchor.attlist
+
+# end of anchor.module
+local.beginpage.attrib = empty
+beginpage.role.attrib = role.attrib
+# doc:The location of a page break in a print version of the document.
+beginpage = element beginpage { beginpage.attlist, empty }
+# end of beginpage.element
+
+# PageNum: Number of page that begins at this point
+beginpage.attlist &=
+  pagenum.attrib,
+  common.attrib,
+  beginpage.role.attrib,
+  local.beginpage.attrib
+# end of beginpage.attlist
+
+# end of beginpage.module
+
+# IndexTerms appear in the text flow for generating or linking an
+# index.
+local.indexterm.attrib = empty
+indexterm.role.attrib = role.attrib
+# doc:A wrapper for terms to be indexed.
+indexterm =
+  element indexterm {
+    indexterm.attlist,
+    primary?,
+    ((secondary,
+      ((tertiary, (see | seealso+)?)
+       | see
+       | seealso+)?)
+     | see
+     | seealso+)?
+  }
+# end of indexterm.element
+
+# Scope: Indicates which generated indices the IndexTerm
+# should appear in: Global (whole document set), Local (this
+# document only), or All (both)
+
+# Significance: Whether this IndexTerm is the most pertinent
+# of its series (Preferred) or not (Normal, the default)
+
+# Class: Indicates type of IndexTerm; default is Singular,
+# or EndOfRange if StartRef is supplied; StartOfRange value
+# must be supplied explicitly on starts of ranges
+
+# StartRef: ID of the IndexTerm that starts the indexing
+# range ended by this IndexTerm
+
+# Zone: IDs of the elements to which the IndexTerm applies,
+# and indicates that the IndexTerm applies to those entire
+# elements rather than the point at which the IndexTerm
+# occurs
+indexterm.attlist &=
+  pagenum.attrib,
+  attribute scope { "all" | "global" | "local" }?,
+  [ a:defaultValue = "normal" ]
+  attribute significance { "preferred" | "normal" }?,
+  attribute class { "singular" | "startofrange" | "endofrange" }?,
+  attribute startref { xsd:IDREF }?,
+  attribute zone { xsd:IDREFS }?,
+  attribute type { text }?,
+  common.attrib,
+  indexterm.role.attrib,
+  local.indexterm.attrib
+# end of indexterm.attlist
+
+# end of indexterm.module
+local.primsecter.attrib = empty
+primsecter.role.attrib = role.attrib
+# doc:The primary word or phrase under which an index term should be sorted.
+primary = element primary { primary.attlist, ndxterm.char.mix* }
+# end of primary.element
+
+# SortAs: Alternate sort string for index sorting, e.g.,
+# "fourteen" for an element containing "14"
+primary.attlist &=
+  attribute sortas { text }?,
+  common.attrib,
+  primsecter.role.attrib,
+  local.primsecter.attrib
+# end of primary.attlist
+
+# doc:A secondary word or phrase in an index term.
+secondary = element secondary { secondary.attlist, ndxterm.char.mix* }
+# end of secondary.element
+
+# SortAs: Alternate sort string for index sorting, e.g.,
+# "fourteen" for an element containing "14"
+secondary.attlist &=
+  attribute sortas { text }?,
+  common.attrib,
+  primsecter.role.attrib,
+  local.primsecter.attrib
+# end of secondary.attlist
+
+# doc:A tertiary word or phrase in an index term.
+tertiary = element tertiary { tertiary.attlist, ndxterm.char.mix* }
+# end of tertiary.element
+
+# SortAs: Alternate sort string for index sorting, e.g.,
+# "fourteen" for an element containing "14"
+tertiary.attlist &=
+  attribute sortas { text }?,
+  common.attrib,
+  primsecter.role.attrib,
+  local.primsecter.attrib
+# end of tertiary.attlist
+
+# end of primsecter.module
+local.seeseealso.attrib = empty
+seeseealso.role.attrib = role.attrib
+# doc:Part of an index term directing the reader instead to another entry in the index.
+see = element see { see.attlist, ndxterm.char.mix* }
+# end of see.element
+see.attlist &=
+  common.attrib, seeseealso.role.attrib, local.seeseealso.attrib
+# end of see.attlist
+
+# doc:Part of an index term directing the reader also to another entry in the index.
+seealso = element seealso { seealso.attlist, ndxterm.char.mix* }
+# end of seealso.element
+seealso.attlist &=
+  common.attrib, seeseealso.role.attrib, local.seeseealso.attrib
+# end of seealso.attlist
+
+# end of seeseealso.module
+
+# end of indexterm.content.module
+
+# End of DocBook XML information pool module V4.5 ......................
+
+# ......................................................................
Index: /branches/new-random/doc/src/docbook-rng-4.5/dbpoolx.rng
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/dbpoolx.rng	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/dbpoolx.rng	(revision 13309)
@@ -0,0 +1,10774 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ...................................................................... -->
+<!-- DocBook XML information pool module V4.5 ............................. -->
+<!-- File dbpoolx.mod ..................................................... -->
+<!--
+  Copyright 1992-2004 HaL Computer Systems, Inc.,
+  O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+  Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+  Organization for the Advancement of Structured Information
+  Standards (OASIS).
+  
+  $Id: dbpoolx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+  
+  Permission to use, copy, modify and distribute the DocBook XML DTD
+  and its accompanying documentation for any purpose and without fee
+  is hereby granted in perpetuity, provided that the above copyright
+  notice and this paragraph appear in all copies.  The copyright
+  holders make no representation about the suitability of the DTD for
+  any purpose.  It is provided "as is" without expressed or implied
+  warranty.
+  
+  If you modify the DocBook XML DTD in any way, except for declaring and
+  referencing additional sets of general entities and declaring
+  additional notations, label your DTD as a variant of DocBook.  See
+  the maintenance documentation for more information.
+  
+  Please direct all questions, bug reports, or suggestions for
+  changes to the docbook@lists.oasis-open.org mailing list. For more
+  information, see http://www.oasis-open.org/docbook/.
+-->
+<!-- ...................................................................... -->
+<!--
+  This module contains the definitions for the objects, inline
+  elements, and so on that are available to be used as the main
+  content of DocBook documents.  Some elements are useful for general
+  publishing, and others are useful specifically for computer
+  documentation.
+  
+  This module has the following dependencies on other modules:
+  
+  o It assumes that a %notation.class; entity is defined by the
+    driver file or other high-level module.  This entity is
+    referenced in the NOTATION attributes for the graphic-related and
+    ModeSpec elements.
+  
+  o It assumes that an appropriately parameterized table module is
+    available for use with the table-related elements.
+  
+  In DTD driver files referring to this module, please use an entity
+  declaration that uses the public identifier shown below:
+  
+  <!ENTITY % dbpool PUBLIC
+  "-//OASIS//ELEMENTS DocBook XML Information Pool V4.5//EN"
+  "dbpoolx.mod">
+  %dbpool;
+  
+  See the documentation for detailed information on the parameter
+  entity and module scheme used in DocBook, customizing DocBook and
+  planning for interchange, and changes made since the last release
+  of DocBook.
+-->
+<!-- ...................................................................... -->
+<!-- Forms entities ....................................................... -->
+<!-- These PEs provide the hook by which the forms module can be inserted -->
+<!-- into the DTD. -->
+<grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+  <define name="forminlines.hook">
+    <notAllowed/>
+  </define>
+  <define name="forms.hook">
+    <notAllowed/>
+  </define>
+  <!-- ...................................................................... -->
+  <!-- General-purpose semantics entities ................................... -->
+  <define name="yesorno.attvals">
+    <data type="string" datatypeLibrary=""/>
+  </define>
+  <!-- ...................................................................... -->
+  <!-- Entities for module inclusions ....................................... -->
+  <!-- ...................................................................... -->
+  <!-- Entities for element classes and mixtures ............................ -->
+  <!-- "Ubiquitous" classes: ndxterm.class and beginpage -->
+  <define name="local.ndxterm.class">
+    <notAllowed/>
+  </define>
+  <define name="ndxterm.class">
+    <choice>
+      <ref name="indexterm"/>
+      <ref name="local.ndxterm.class"/>
+    </choice>
+  </define>
+  <!-- Object-level classes ................................................. -->
+  <define name="local.list.class">
+    <notAllowed/>
+  </define>
+  <define name="list.class">
+    <choice>
+      <ref name="calloutlist"/>
+      <ref name="glosslist"/>
+      <ref name="bibliolist"/>
+      <ref name="itemizedlist"/>
+      <ref name="orderedlist"/>
+      <ref name="segmentedlist"/>
+      <ref name="simplelist"/>
+      <ref name="variablelist"/>
+      <ref name="local.list.class"/>
+    </choice>
+  </define>
+  <define name="local.admon.class">
+    <notAllowed/>
+  </define>
+  <define name="admon.class">
+    <choice>
+      <ref name="caution"/>
+      <ref name="important"/>
+      <ref name="note"/>
+      <ref name="tip"/>
+      <ref name="warning"/>
+      <ref name="local.admon.class"/>
+    </choice>
+  </define>
+  <define name="local.linespecific.class">
+    <notAllowed/>
+  </define>
+  <define name="linespecific.class">
+    <choice>
+      <ref name="literallayout"/>
+      <ref name="programlisting"/>
+      <ref name="programlistingco"/>
+      <ref name="screen"/>
+      <ref name="screenco"/>
+      <ref name="screenshot"/>
+      <ref name="local.linespecific.class"/>
+    </choice>
+  </define>
+  <define name="local.method.synop.class">
+    <notAllowed/>
+  </define>
+  <define name="method.synop.class">
+    <choice>
+      <ref name="constructorsynopsis"/>
+      <ref name="destructorsynopsis"/>
+      <ref name="methodsynopsis"/>
+      <ref name="local.method.synop.class"/>
+    </choice>
+  </define>
+  <define name="local.synop.class">
+    <notAllowed/>
+  </define>
+  <define name="synop.class">
+    <choice>
+      <ref name="synopsis"/>
+      <ref name="cmdsynopsis"/>
+      <ref name="funcsynopsis"/>
+      <ref name="classsynopsis"/>
+      <ref name="fieldsynopsis"/>
+      <ref name="method.synop.class"/>
+      <ref name="local.synop.class"/>
+    </choice>
+  </define>
+  <define name="local.para.class">
+    <notAllowed/>
+  </define>
+  <define name="para.class">
+    <choice>
+      <ref name="formalpara"/>
+      <ref name="para"/>
+      <ref name="simpara"/>
+      <ref name="local.para.class"/>
+    </choice>
+  </define>
+  <define name="local.informal.class">
+    <notAllowed/>
+  </define>
+  <define name="informal.class">
+    <choice>
+      <ref name="address"/>
+      <ref name="blockquote"/>
+      <ref name="graphic"/>
+      <ref name="graphicco"/>
+      <ref name="mediaobject"/>
+      <ref name="mediaobjectco"/>
+      <ref name="informalequation"/>
+      <ref name="informalexample"/>
+      <ref name="informalfigure"/>
+      <ref name="informaltable"/>
+      <ref name="local.informal.class"/>
+    </choice>
+  </define>
+  <define name="local.formal.class">
+    <notAllowed/>
+  </define>
+  <define name="formal.class">
+    <choice>
+      <ref name="equation"/>
+      <ref name="example"/>
+      <ref name="figure"/>
+      <ref name="table"/>
+      <ref name="local.formal.class"/>
+    </choice>
+  </define>
+  <!-- The DocBook TC may produce an official EBNF module for DocBook. -->
+  <!-- This PE provides the hook by which it can be inserted into the DTD. -->
+  <define name="ebnf.block.hook">
+    <notAllowed/>
+  </define>
+  <define name="local.compound.class">
+    <notAllowed/>
+  </define>
+  <define name="compound.class">
+    <choice>
+      <ref name="msgset"/>
+      <ref name="procedure"/>
+      <ref name="sidebar"/>
+      <ref name="qandaset"/>
+      <ref name="task"/>
+      <ref name="ebnf.block.hook"/>
+      <ref name="local.compound.class"/>
+    </choice>
+  </define>
+  <define name="local.genobj.class">
+    <notAllowed/>
+  </define>
+  <define name="genobj.class">
+    <choice>
+      <ref name="anchor"/>
+      <ref name="bridgehead"/>
+      <ref name="remark"/>
+      <ref name="highlights"/>
+      <ref name="local.genobj.class"/>
+    </choice>
+  </define>
+  <define name="local.descobj.class">
+    <notAllowed/>
+  </define>
+  <define name="descobj.class">
+    <choice>
+      <ref name="abstract"/>
+      <ref name="authorblurb"/>
+      <ref name="epigraph"/>
+      <ref name="local.descobj.class"/>
+    </choice>
+  </define>
+  <!-- Character-level classes .............................................. -->
+  <define name="local.xref.char.class">
+    <notAllowed/>
+  </define>
+  <define name="xref.char.class">
+    <choice>
+      <ref name="footnoteref"/>
+      <ref name="xref"/>
+      <ref name="biblioref"/>
+      <ref name="local.xref.char.class"/>
+    </choice>
+  </define>
+  <define name="local.gen.char.class">
+    <notAllowed/>
+  </define>
+  <define name="gen.char.class">
+    <choice>
+      <ref name="abbrev"/>
+      <ref name="acronym"/>
+      <ref name="citation"/>
+      <ref name="citerefentry"/>
+      <ref name="citetitle"/>
+      <ref name="citebiblioid"/>
+      <ref name="emphasis"/>
+      <ref name="firstterm"/>
+      <ref name="foreignphrase"/>
+      <ref name="glossterm"/>
+      <ref name="termdef"/>
+      <ref name="footnote"/>
+      <ref name="phrase"/>
+      <ref name="orgname"/>
+      <ref name="quote"/>
+      <ref name="trademark"/>
+      <ref name="wordasword"/>
+      <ref name="personname"/>
+      <ref name="local.gen.char.class"/>
+    </choice>
+  </define>
+  <define name="local.link.char.class">
+    <notAllowed/>
+  </define>
+  <define name="link.char.class">
+    <choice>
+      <ref name="link"/>
+      <ref name="olink"/>
+      <ref name="ulink"/>
+      <ref name="local.link.char.class"/>
+    </choice>
+  </define>
+  <!-- The DocBook TC may produce an official EBNF module for DocBook. -->
+  <!-- This PE provides the hook by which it can be inserted into the DTD. -->
+  <define name="ebnf.inline.hook">
+    <notAllowed/>
+  </define>
+  <define name="local.tech.char.class">
+    <notAllowed/>
+  </define>
+  <define name="tech.char.class">
+    <choice>
+      <ref name="action"/>
+      <ref name="application"/>
+      <ref name="classname"/>
+      <ref name="methodname"/>
+      <ref name="interfacename"/>
+      <ref name="exceptionname"/>
+      <ref name="ooclass"/>
+      <ref name="oointerface"/>
+      <ref name="ooexception"/>
+      <ref name="package"/>
+      <ref name="command"/>
+      <ref name="computeroutput"/>
+      <ref name="database"/>
+      <ref name="email"/>
+      <ref name="envar"/>
+      <ref name="errorcode"/>
+      <ref name="errorname"/>
+      <ref name="errortype"/>
+      <ref name="errortext"/>
+      <ref name="filename"/>
+      <ref name="function"/>
+      <ref name="guibutton"/>
+      <ref name="guiicon"/>
+      <ref name="guilabel"/>
+      <ref name="guimenu"/>
+      <ref name="guimenuitem"/>
+      <ref name="guisubmenu"/>
+      <ref name="hardware"/>
+      <ref name="interface"/>
+      <ref name="keycap"/>
+      <ref name="keycode"/>
+      <ref name="keycombo"/>
+      <ref name="keysym"/>
+      <ref name="literal"/>
+      <ref name="code"/>
+      <ref name="constant"/>
+      <ref name="markup"/>
+      <ref name="medialabel"/>
+      <ref name="menuchoice"/>
+      <ref name="mousebutton"/>
+      <ref name="option"/>
+      <ref name="optional"/>
+      <ref name="parameter"/>
+      <ref name="prompt"/>
+      <ref name="property"/>
+      <ref name="replaceable"/>
+      <ref name="returnvalue"/>
+      <ref name="sgmltag"/>
+      <ref name="structfield"/>
+      <ref name="structname"/>
+      <ref name="symbol"/>
+      <ref name="systemitem"/>
+      <ref name="uri"/>
+      <ref name="token"/>
+      <ref name="type"/>
+      <ref name="userinput"/>
+      <ref name="varname"/>
+      <ref name="ebnf.inline.hook"/>
+      <ref name="local.tech.char.class"/>
+    </choice>
+  </define>
+  <define name="local.base.char.class">
+    <notAllowed/>
+  </define>
+  <define name="base.char.class">
+    <choice>
+      <ref name="anchor"/>
+      <ref name="local.base.char.class"/>
+    </choice>
+  </define>
+  <define name="local.docinfo.char.class">
+    <notAllowed/>
+  </define>
+  <define name="docinfo.char.class">
+    <choice>
+      <ref name="author"/>
+      <ref name="authorinitials"/>
+      <ref name="corpauthor"/>
+      <ref name="corpcredit"/>
+      <ref name="modespec"/>
+      <ref name="othercredit"/>
+      <ref name="productname"/>
+      <ref name="productnumber"/>
+      <ref name="revhistory"/>
+      <ref name="local.docinfo.char.class"/>
+    </choice>
+  </define>
+  <define name="local.other.char.class">
+    <notAllowed/>
+  </define>
+  <define name="other.char.class">
+    <choice>
+      <ref name="remark"/>
+      <ref name="subscript"/>
+      <ref name="superscript"/>
+      <ref name="local.other.char.class"/>
+    </choice>
+  </define>
+  <define name="local.inlineobj.char.class">
+    <notAllowed/>
+  </define>
+  <define name="inlineobj.char.class">
+    <choice>
+      <ref name="inlinegraphic"/>
+      <ref name="inlinemediaobject"/>
+      <ref name="inlineequation"/>
+      <ref name="local.inlineobj.char.class"/>
+    </choice>
+  </define>
+  <!-- ...................................................................... -->
+  <!-- Entities for content models .......................................... -->
+  <define name="formalobject.title.content">
+    <ref name="title"/>
+    <optional>
+      <ref name="titleabbrev"/>
+    </optional>
+  </define>
+  <!-- Redeclaration placeholder ............................................ -->
+  <!--
+    For redeclaring entities that are declared after this point while
+    retaining their references to the entities that are declared before
+    this point
+  -->
+  <!-- Object-level mixtures ................................................ -->
+  <!--
+                          list admn line synp para infm form cmpd gen  desc
+    Component mixture       X    X    X    X    X    X    X    X    X    X
+    Sidebar mixture         X    X    X    X    X    X    X    a    X
+    Footnote mixture        X         X    X    X    X
+    Example mixture         X         X    X    X    X
+    Highlights mixture      X    X              X
+    Paragraph mixture       X         X    X         X
+    Admonition mixture      X         X    X    X    X    X    b    c
+    Figure mixture                    X    X         X
+    Table entry mixture     X    X    X         X    d
+    Glossary def mixture    X         X    X    X    X         e
+    Legal notice mixture    X    X    X         X    f
+    
+    a. Just Procedure; not Sidebar itself or MsgSet.
+    b. No MsgSet.
+    c. No Highlights.
+    d. Just Graphic; no other informal objects.
+    e. No Anchor, BridgeHead, or Highlights.
+    f. Just BlockQuote; no other informal objects.
+  -->
+  <define name="local.component.mix">
+    <notAllowed/>
+  </define>
+  <define name="component.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="compound.class"/>
+      <ref name="genobj.class"/>
+      <ref name="descobj.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forms.hook"/>
+      <ref name="local.component.mix"/>
+    </choice>
+  </define>
+  <define name="local.sidebar.mix">
+    <notAllowed/>
+  </define>
+  <define name="sidebar.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="procedure"/>
+      <ref name="genobj.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forms.hook"/>
+      <ref name="local.sidebar.mix"/>
+    </choice>
+  </define>
+  <define name="local.qandaset.mix">
+    <notAllowed/>
+  </define>
+  <define name="qandaset.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="procedure"/>
+      <ref name="genobj.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="forms.hook"/>
+      <ref name="local.qandaset.mix"/>
+    </choice>
+  </define>
+  <define name="local.revdescription.mix">
+    <notAllowed/>
+  </define>
+  <define name="revdescription.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="procedure"/>
+      <ref name="genobj.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="local.revdescription.mix"/>
+    </choice>
+  </define>
+  <define name="local.footnote.mix">
+    <notAllowed/>
+  </define>
+  <define name="footnote.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="local.footnote.mix"/>
+    </choice>
+  </define>
+  <define name="local.example.mix">
+    <notAllowed/>
+  </define>
+  <define name="example.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="procedure"/>
+      <ref name="forms.hook"/>
+      <ref name="local.example.mix"/>
+    </choice>
+  </define>
+  <define name="local.highlights.mix">
+    <notAllowed/>
+  </define>
+  <define name="highlights.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="para.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="local.highlights.mix"/>
+    </choice>
+  </define>
+  <!--
+    %formal.class; is explicitly excluded from many contexts in which
+    paragraphs are used
+  -->
+  <define name="local.para.mix">
+    <notAllowed/>
+  </define>
+  <define name="para.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="local.para.mix"/>
+    </choice>
+  </define>
+  <define name="local.admon.mix">
+    <notAllowed/>
+  </define>
+  <define name="admon.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="procedure"/>
+      <ref name="sidebar"/>
+      <ref name="anchor"/>
+      <ref name="bridgehead"/>
+      <ref name="remark"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forms.hook"/>
+      <ref name="local.admon.mix"/>
+    </choice>
+  </define>
+  <define name="local.figure.mix">
+    <notAllowed/>
+  </define>
+  <define name="figure.mix">
+    <choice>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="informal.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forms.hook"/>
+      <ref name="local.figure.mix"/>
+    </choice>
+  </define>
+  <define name="local.tabentry.mix">
+    <notAllowed/>
+  </define>
+  <define name="tabentry.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="para.class"/>
+      <ref name="graphic"/>
+      <ref name="mediaobject"/>
+      <ref name="forms.hook"/>
+      <ref name="local.tabentry.mix"/>
+    </choice>
+  </define>
+  <define name="local.glossdef.mix">
+    <notAllowed/>
+  </define>
+  <define name="glossdef.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="formal.class"/>
+      <ref name="remark"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="local.glossdef.mix"/>
+    </choice>
+  </define>
+  <define name="local.legalnotice.mix">
+    <notAllowed/>
+  </define>
+  <define name="legalnotice.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="para.class"/>
+      <ref name="blockquote"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="local.legalnotice.mix"/>
+    </choice>
+  </define>
+  <define name="local.textobject.mix">
+    <notAllowed/>
+  </define>
+  <define name="textobject.mix">
+    <choice>
+      <ref name="list.class"/>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="para.class"/>
+      <ref name="blockquote"/>
+      <ref name="local.textobject.mix"/>
+    </choice>
+  </define>
+  <define name="local.mediaobject.mix">
+    <notAllowed/>
+  </define>
+  <define name="mediaobject.mix">
+    <choice>
+      <ref name="videoobject"/>
+      <ref name="audioobject"/>
+      <ref name="imageobject"/>
+      <ref name="imageobjectco"/>
+      <ref name="textobject"/>
+      <ref name="local.mediaobject.mix"/>
+    </choice>
+  </define>
+  <define name="local.listpreamble.mix">
+    <notAllowed/>
+  </define>
+  <define name="listpreamble.mix">
+    <choice>
+      <ref name="admon.class"/>
+      <ref name="linespecific.class"/>
+      <ref name="synop.class"/>
+      <ref name="para.class"/>
+      <ref name="informal.class"/>
+      <ref name="genobj.class"/>
+      <ref name="descobj.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forms.hook"/>
+      <ref name="local.listpreamble.mix"/>
+    </choice>
+  </define>
+  <!-- Character-level mixtures ............................................. -->
+  <!-- sgml.features -->
+  <!-- not [sgml.features[ -->
+  <!-- ]] not sgml.features -->
+  <!--
+                        #PCD xref word link cptr base dnfo othr inob (synop)
+    para.char.mix         X    X    X    X    X    X    X    X    X
+    title.char.mix        X    X    X    X    X    X    X    X    X
+    ndxterm.char.mix      X    X    X    X    X    X    X    X    a
+    cptr.char.mix         X              X    X    X         X    a
+    smallcptr.char.mix    X                   b                   a
+    word.char.mix         X         c    X         X         X    a
+    docinfo.char.mix      X         d    X    b              X    a
+    
+    a. Just InlineGraphic; no InlineEquation.
+    b. Just Replaceable; no other computer terms.
+    c. Just Emphasis and Trademark; no other word elements.
+    d. Just Acronym, Emphasis, and Trademark; no other word elements.
+  -->
+  <define name="local.para.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="para.char.mix">
+    <choice>
+      <text/>
+      <ref name="xref.char.class"/>
+      <ref name="gen.char.class"/>
+      <ref name="link.char.class"/>
+      <ref name="tech.char.class"/>
+      <ref name="base.char.class"/>
+      <ref name="docinfo.char.class"/>
+      <ref name="other.char.class"/>
+      <ref name="inlineobj.char.class"/>
+      <ref name="synop.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="forminlines.hook"/>
+      <ref name="local.para.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.title.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="title.char.mix">
+    <choice>
+      <text/>
+      <ref name="xref.char.class"/>
+      <ref name="gen.char.class"/>
+      <ref name="link.char.class"/>
+      <ref name="tech.char.class"/>
+      <ref name="base.char.class"/>
+      <ref name="docinfo.char.class"/>
+      <ref name="other.char.class"/>
+      <ref name="inlineobj.char.class"/>
+      <ref name="ndxterm.class"/>
+      <ref name="local.title.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.ndxterm.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="ndxterm.char.mix">
+    <choice>
+      <text/>
+      <ref name="xref.char.class"/>
+      <ref name="gen.char.class"/>
+      <ref name="link.char.class"/>
+      <ref name="tech.char.class"/>
+      <ref name="base.char.class"/>
+      <ref name="docinfo.char.class"/>
+      <ref name="other.char.class"/>
+      <ref name="inlinegraphic"/>
+      <ref name="inlinemediaobject"/>
+      <ref name="local.ndxterm.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.cptr.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="cptr.char.mix">
+    <choice>
+      <text/>
+      <ref name="link.char.class"/>
+      <ref name="tech.char.class"/>
+      <ref name="base.char.class"/>
+      <ref name="other.char.class"/>
+      <ref name="inlinegraphic"/>
+      <ref name="inlinemediaobject"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="local.cptr.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.smallcptr.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="smallcptr.char.mix">
+    <choice>
+      <text/>
+      <ref name="replaceable"/>
+      <ref name="inlinegraphic"/>
+      <ref name="inlinemediaobject"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="local.smallcptr.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.word.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="word.char.mix">
+    <choice>
+      <text/>
+      <ref name="acronym"/>
+      <ref name="emphasis"/>
+      <ref name="trademark"/>
+      <ref name="link.char.class"/>
+      <ref name="base.char.class"/>
+      <ref name="other.char.class"/>
+      <ref name="inlinegraphic"/>
+      <ref name="inlinemediaobject"/>
+      <ref name="ndxterm.class"/>
+      <ref name="beginpage"/>
+      <ref name="local.word.char.mix"/>
+    </choice>
+  </define>
+  <define name="local.docinfo.char.mix">
+    <notAllowed/>
+  </define>
+  <define name="docinfo.char.mix">
+    <choice>
+      <text/>
+      <ref name="link.char.class"/>
+      <ref name="emphasis"/>
+      <ref name="trademark"/>
+      <ref name="replaceable"/>
+      <ref name="other.char.class"/>
+      <ref name="inlinegraphic"/>
+      <ref name="inlinemediaobject"/>
+      <ref name="ndxterm.class"/>
+      <ref name="local.docinfo.char.mix"/>
+    </choice>
+  </define>
+  <!-- ENTITY % bibliocomponent.mix (see Bibliographic section, below) -->
+  <!-- ENTITY % person.ident.mix (see Bibliographic section, below) -->
+  <!-- ...................................................................... -->
+  <!-- Entities for attributes and attribute components ..................... -->
+  <!-- Effectivity attributes ............................................... -->
+  <!--
+    Arch: Computer or chip architecture to which element applies; no
+    default
+  -->
+  <define name="arch.attrib">
+    <optional>
+      <attribute name="arch"/>
+    </optional>
+  </define>
+  <!-- Condition: General-purpose effectivity attribute -->
+  <define name="condition.attrib">
+    <optional>
+      <attribute name="condition"/>
+    </optional>
+  </define>
+  <!-- Conformance: Standards conformance characteristics -->
+  <define name="conformance.attrib">
+    <optional>
+      <attribute name="conformance">
+        <data type="NMTOKENS"/>
+      </attribute>
+    </optional>
+  </define>
+  <!-- OS: Operating system to which element applies; no default -->
+  <define name="os.attrib">
+    <optional>
+      <attribute name="os"/>
+    </optional>
+  </define>
+  <!-- Revision: Editorial revision to which element belongs; no default -->
+  <define name="revision.attrib">
+    <optional>
+      <attribute name="revision"/>
+    </optional>
+  </define>
+  <!-- Security: Security classification; no default -->
+  <define name="security.attrib">
+    <optional>
+      <attribute name="security"/>
+    </optional>
+  </define>
+  <!--
+    UserLevel: Level of user experience to which element applies; no
+    default
+  -->
+  <define name="userlevel.attrib">
+    <optional>
+      <attribute name="userlevel"/>
+    </optional>
+  </define>
+  <!-- Vendor: Computer vendor to which element applies; no default -->
+  <define name="vendor.attrib">
+    <optional>
+      <attribute name="vendor"/>
+    </optional>
+  </define>
+  <!-- Wordsize: Computer word size (32 bit, 64 bit, etc.); no default -->
+  <define name="wordsize.attrib">
+    <optional>
+      <attribute name="wordsize"/>
+    </optional>
+  </define>
+  <define name="local.effectivity.attrib">
+    <empty/>
+  </define>
+  <define name="effectivity.attrib">
+    <ref name="arch.attrib"/>
+    <ref name="condition.attrib"/>
+    <ref name="conformance.attrib"/>
+    <ref name="os.attrib"/>
+    <ref name="revision.attrib"/>
+    <ref name="security.attrib"/>
+    <ref name="userlevel.attrib"/>
+    <ref name="vendor.attrib"/>
+    <ref name="wordsize.attrib"/>
+    <ref name="local.effectivity.attrib"/>
+  </define>
+  <!-- Common attributes .................................................... -->
+  <!-- Id: Unique identifier of element; no default -->
+  <define name="id.attrib">
+    <optional>
+      <attribute name="id">
+        <data type="ID"/>
+      </attribute>
+    </optional>
+  </define>
+  <!--
+    Id: Unique identifier of element; a value must be supplied; no
+    default
+  -->
+  <define name="idreq.attrib">
+    <attribute name="id">
+      <data type="ID"/>
+    </attribute>
+  </define>
+  <!--
+    Lang: Indicator of language in which element is written, for
+    translation, character set management, etc.; no default
+  -->
+  <define name="lang.attrib">
+    <optional>
+      <attribute name="lang"/>
+    </optional>
+  </define>
+  <!-- Remap: Previous role of element before conversion; no default -->
+  <define name="remap.attrib">
+    <optional>
+      <attribute name="remap"/>
+    </optional>
+  </define>
+  <!-- Role: New role of element in local environment; no default -->
+  <define name="role.attrib">
+    <optional>
+      <attribute name="role"/>
+    </optional>
+  </define>
+  <!--
+    XRefLabel: Alternate labeling string for XRef text generation;
+    default is usually title or other appropriate label text already
+    contained in element
+  -->
+  <define name="xreflabel.attrib">
+    <optional>
+      <attribute name="xreflabel"/>
+    </optional>
+  </define>
+  <!--
+    RevisionFlag: Revision status of element; default is that element
+    wasn't revised
+  -->
+  <define name="revisionflag.attrib">
+    <optional>
+      <attribute name="revisionflag">
+        <choice>
+          <value>changed</value>
+          <value>added</value>
+          <value>deleted</value>
+          <value>off</value>
+        </choice>
+      </attribute>
+    </optional>
+  </define>
+  <define name="local.common.attrib">
+    <empty/>
+  </define>
+  <!-- dir: Bidirectional override -->
+  <define name="dir.attrib">
+    <optional>
+      <attribute name="dir">
+        <choice>
+          <value>ltr</value>
+          <value>rtl</value>
+          <value>lro</value>
+          <value>rlo</value>
+        </choice>
+      </attribute>
+    </optional>
+  </define>
+  <!-- xml:base: base URI -->
+  <define name="xml-base.attrib">
+    <optional>
+      <attribute name="xml:base"/>
+    </optional>
+  </define>
+  <!-- Role is included explicitly on each element -->
+  <define name="common.attrib">
+    <ref name="id.attrib"/>
+    <ref name="lang.attrib"/>
+    <ref name="remap.attrib"/>
+    <ref name="xreflabel.attrib"/>
+    <ref name="revisionflag.attrib"/>
+    <ref name="effectivity.attrib"/>
+    <ref name="dir.attrib"/>
+    <ref name="xml-base.attrib"/>
+    <ref name="local.common.attrib"/>
+  </define>
+  <!-- Role is included explicitly on each element -->
+  <define name="idreq.common.attrib">
+    <ref name="idreq.attrib"/>
+    <ref name="lang.attrib"/>
+    <ref name="remap.attrib"/>
+    <ref name="xreflabel.attrib"/>
+    <ref name="revisionflag.attrib"/>
+    <ref name="effectivity.attrib"/>
+    <ref name="dir.attrib"/>
+    <ref name="xml-base.attrib"/>
+    <ref name="local.common.attrib"/>
+  </define>
+  <!-- Semi-common attributes and other attribute entities .................. -->
+  <define name="local.graphics.attrib">
+    <empty/>
+  </define>
+  <!--
+    EntityRef: Name of an external entity containing the content
+    of the graphic
+  -->
+  <!--
+    FileRef: Filename, qualified by a pathname if desired,
+    designating the file containing the content of the graphic
+  -->
+  <!-- Format: Notation of the element content, if any -->
+  <!-- SrcCredit: Information about the source of the Graphic -->
+  <!-- Width: Same as CALS reprowid (desired width) -->
+  <!-- Depth: Same as CALS reprodep (desired depth) -->
+  <!--
+    Align: Same as CALS hplace with 'none' removed; #IMPLIED means
+    application-specific
+  -->
+  <!-- Scale: Conflation of CALS hscale and vscale -->
+  <!-- Scalefit: Same as CALS scalefit -->
+  <define name="graphics.attrib">
+    <optional>
+      <attribute name="entityref">
+        <data type="ENTITY"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="fileref"/>
+    </optional>
+    <optional>
+      <attribute name="format">
+        <choice>
+          <ref name="notation.class"/>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="srccredit"/>
+    </optional>
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <optional>
+      <attribute name="contentwidth"/>
+    </optional>
+    <optional>
+      <attribute name="depth"/>
+    </optional>
+    <optional>
+      <attribute name="contentdepth"/>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="scale"/>
+    </optional>
+    <optional>
+      <attribute name="scalefit">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <ref name="local.graphics.attrib"/>
+  </define>
+  <define name="local.keyaction.attrib">
+    <empty/>
+  </define>
+  <!--
+    Action: Key combination type; default is unspecified if one
+    child element, Simul if there is more than one; if value is
+    Other, the OtherAction attribute must have a nonempty value
+  -->
+  <!-- OtherAction: User-defined key combination type -->
+  <define name="keyaction.attrib">
+    <optional>
+      <attribute name="action">
+        <choice>
+          <value>click</value>
+          <value>double-click</value>
+          <value>press</value>
+          <value>seq</value>
+          <value>simul</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otheraction"/>
+    </optional>
+    <ref name="local.keyaction.attrib"/>
+  </define>
+  <!--
+    Label: Identifying number or string; default is usually the
+    appropriate number or string autogenerated by a formatter
+  -->
+  <define name="label.attrib">
+    <optional>
+      <attribute name="label"/>
+    </optional>
+  </define>
+  <!-- xml:space: whitespace treatment -->
+  <define name="xml-space.attrib">
+    <optional>
+      <attribute name="xml:space">
+        <choice>
+          <value>preserve</value>
+        </choice>
+      </attribute>
+    </optional>
+  </define>
+  <!--
+    Format: whether element is assumed to contain significant white
+    space
+  -->
+  <define name="linespecific.attrib">
+    <optional>
+      <attribute name="format" a:defaultValue="linespecific">
+        <choice>
+          <value>linespecific</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="xml-space.attrib"/>
+    <optional>
+      <attribute name="linenumbering">
+        <choice>
+          <value>numbered</value>
+          <value>unnumbered</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="continuation">
+        <choice>
+          <value>continues</value>
+          <value>restarts</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="startinglinenumber"/>
+    </optional>
+    <optional>
+      <attribute name="language"/>
+    </optional>
+  </define>
+  <!-- Linkend: link to related information; no default -->
+  <define name="linkend.attrib">
+    <optional>
+      <attribute name="linkend">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+  </define>
+  <!-- Linkend: required link to related information -->
+  <define name="linkendreq.attrib">
+    <attribute name="linkend">
+      <data type="IDREF"/>
+    </attribute>
+  </define>
+  <!--
+    Linkends: link to one or more sets of related information; no
+    default
+  -->
+  <define name="linkends.attrib">
+    <optional>
+      <attribute name="linkends">
+        <data type="IDREFS"/>
+      </attribute>
+    </optional>
+  </define>
+  <define name="local.mark.attrib">
+    <empty/>
+  </define>
+  <define name="mark.attrib">
+    <optional>
+      <attribute name="mark"/>
+    </optional>
+    <ref name="local.mark.attrib"/>
+  </define>
+  <!-- MoreInfo: whether element's content has an associated RefEntry -->
+  <define name="moreinfo.attrib">
+    <optional>
+      <attribute name="moreinfo" a:defaultValue="none">
+        <choice>
+          <value>refentry</value>
+          <value>none</value>
+        </choice>
+      </attribute>
+    </optional>
+  </define>
+  <!-- Pagenum: number of page on which element appears; no default -->
+  <define name="pagenum.attrib">
+    <optional>
+      <attribute name="pagenum"/>
+    </optional>
+  </define>
+  <define name="local.status.attrib">
+    <empty/>
+  </define>
+  <!--
+    Status: Editorial or publication status of the element
+    it applies to, such as "in review" or "approved for distribution"
+  -->
+  <define name="status.attrib">
+    <optional>
+      <attribute name="status"/>
+    </optional>
+    <ref name="local.status.attrib"/>
+  </define>
+  <!--
+    Width: width of the longest line in the element to which it
+    pertains, in number of characters
+  -->
+  <define name="width.attrib">
+    <optional>
+      <attribute name="width"/>
+    </optional>
+  </define>
+  <!-- ...................................................................... -->
+  <!-- Title elements ....................................................... -->
+  <define name="local.title.attrib">
+    <empty/>
+  </define>
+  <define name="title.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The text of the title of a section of a document or of a formal block-level element. -->
+  <define name="title">
+    <element name="title">
+      <ref name="title.attlist"/>
+      <zeroOrMore>
+        <ref name="title.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of title.element -->
+  <define name="title.attlist" combine="interleave">
+    <ref name="pagenum.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="title.role.attrib"/>
+    <ref name="local.title.attrib"/>
+  </define>
+  <!-- end of title.attlist -->
+  <!-- end of title.module -->
+  <define name="local.titleabbrev.attrib">
+    <empty/>
+  </define>
+  <define name="titleabbrev.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The abbreviation of a Title. -->
+  <define name="titleabbrev">
+    <element name="titleabbrev">
+      <ref name="titleabbrev.attlist"/>
+      <zeroOrMore>
+        <ref name="title.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of titleabbrev.element -->
+  <define name="titleabbrev.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="titleabbrev.role.attrib"/>
+    <ref name="local.titleabbrev.attrib"/>
+  </define>
+  <!-- end of titleabbrev.attlist -->
+  <!-- end of titleabbrev.module -->
+  <define name="local.subtitle.attrib">
+    <empty/>
+  </define>
+  <define name="subtitle.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The subtitle of a document. -->
+  <define name="subtitle">
+    <element name="subtitle">
+      <ref name="subtitle.attlist"/>
+      <zeroOrMore>
+        <ref name="title.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of subtitle.element -->
+  <define name="subtitle.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="subtitle.role.attrib"/>
+    <ref name="local.subtitle.attrib"/>
+  </define>
+  <!-- end of subtitle.attlist -->
+  <!-- end of subtitle.module -->
+  <!-- ...................................................................... -->
+  <!-- Bibliographic entities and elements .................................. -->
+  <!--
+    The bibliographic elements are typically used in the document
+    hierarchy. They do not appear in content models of information
+    pool elements.  See also the document information elements,
+    below.
+  -->
+  <define name="local.person.ident.mix">
+    <notAllowed/>
+  </define>
+  <define name="person.ident.mix">
+    <choice>
+      <ref name="honorific"/>
+      <ref name="firstname"/>
+      <ref name="surname"/>
+      <ref name="lineage"/>
+      <ref name="othername"/>
+      <ref name="affiliation"/>
+      <ref name="authorblurb"/>
+      <ref name="contrib"/>
+      <ref name="local.person.ident.mix"/>
+    </choice>
+  </define>
+  <define name="local.bibliocomponent.mix">
+    <notAllowed/>
+  </define>
+  <define name="bibliocomponent.mix">
+    <choice>
+      <ref name="abbrev"/>
+      <ref name="abstract"/>
+      <ref name="address"/>
+      <ref name="artpagenums"/>
+      <ref name="author"/>
+      <ref name="authorgroup"/>
+      <ref name="authorinitials"/>
+      <ref name="bibliomisc"/>
+      <ref name="biblioset"/>
+      <ref name="collab"/>
+      <ref name="confgroup"/>
+      <ref name="contractnum"/>
+      <ref name="contractsponsor"/>
+      <ref name="copyright"/>
+      <ref name="corpauthor"/>
+      <ref name="corpname"/>
+      <ref name="corpcredit"/>
+      <ref name="date"/>
+      <ref name="edition"/>
+      <ref name="editor"/>
+      <ref name="invpartnumber"/>
+      <ref name="isbn"/>
+      <ref name="issn"/>
+      <ref name="issuenum"/>
+      <ref name="orgname"/>
+      <ref name="biblioid"/>
+      <ref name="citebiblioid"/>
+      <ref name="bibliosource"/>
+      <ref name="bibliorelation"/>
+      <ref name="bibliocoverage"/>
+      <ref name="othercredit"/>
+      <ref name="pagenums"/>
+      <ref name="printhistory"/>
+      <ref name="productname"/>
+      <ref name="productnumber"/>
+      <ref name="pubdate"/>
+      <ref name="publisher"/>
+      <ref name="publishername"/>
+      <ref name="pubsnumber"/>
+      <ref name="releaseinfo"/>
+      <ref name="revhistory"/>
+      <ref name="seriesvolnums"/>
+      <ref name="subtitle"/>
+      <ref name="title"/>
+      <ref name="titleabbrev"/>
+      <ref name="volumenum"/>
+      <ref name="citetitle"/>
+      <ref name="personname"/>
+      <ref name="person.ident.mix"/>
+      <ref name="ndxterm.class"/>
+      <ref name="local.bibliocomponent.mix"/>
+    </choice>
+  </define>
+  <!-- I don't think this is well placed, but it needs to be here because of -->
+  <!-- the reference to bibliocomponent.mix -->
+  <define name="local.info.class">
+    <notAllowed/>
+  </define>
+  <define name="info.class">
+    <choice>
+      <ref name="graphic"/>
+      <ref name="mediaobject"/>
+      <ref name="legalnotice"/>
+      <ref name="modespec"/>
+      <ref name="subjectset"/>
+      <ref name="keywordset"/>
+      <ref name="itermset"/>
+      <ref name="bibliocomponent.mix"/>
+      <ref name="local.info.class"/>
+    </choice>
+  </define>
+  <!-- BiblioList ........................ -->
+  <define name="local.bibliolist.attrib">
+    <empty/>
+  </define>
+  <define name="bibliolist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for a set of bibliography entries. -->
+  <define name="bibliolist">
+    <element name="bibliolist">
+      <ref name="bibliolist.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <choice>
+          <ref name="biblioentry"/>
+          <ref name="bibliomixed"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of bibliolist.element -->
+  <define name="bibliolist.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="bibliolist.role.attrib"/>
+    <ref name="local.bibliolist.attrib"/>
+  </define>
+  <!-- end of bibliolist.attlist -->
+  <!-- end of bibliolist.module -->
+  <define name="local.biblioentry.attrib">
+    <empty/>
+  </define>
+  <define name="biblioentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a Bibliography. -->
+  <define name="biblioentry">
+    <element name="biblioentry">
+      <ref name="biblioentry.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="articleinfo"/>
+          <ref name="bibliocomponent.mix"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of biblioentry.element -->
+  <define name="biblioentry.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="biblioentry.role.attrib"/>
+    <ref name="local.biblioentry.attrib"/>
+  </define>
+  <!-- end of biblioentry.attlist -->
+  <!-- end of biblioentry.module -->
+  <define name="local.bibliomixed.attrib">
+    <empty/>
+  </define>
+  <define name="bibliomixed.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a Bibliography. -->
+  <define name="bibliomixed">
+    <element name="bibliomixed">
+      <ref name="bibliomixed.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="bibliocomponent.mix"/>
+          <ref name="bibliomset"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of bibliomixed.element -->
+  <define name="bibliomixed.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="bibliomixed.role.attrib"/>
+    <ref name="local.bibliomixed.attrib"/>
+  </define>
+  <!-- end of bibliomixed.attlist -->
+  <!-- end of bibliomixed.module -->
+  <define name="local.articleinfo.attrib">
+    <empty/>
+  </define>
+  <define name="articleinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for an Article. -->
+  <define name="articleinfo">
+    <element name="articleinfo">
+      <ref name="articleinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of articleinfo.element -->
+  <define name="articleinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="articleinfo.role.attrib"/>
+    <ref name="local.articleinfo.attrib"/>
+  </define>
+  <!-- end of articleinfo.attlist -->
+  <!-- end of articleinfo.module -->
+  <define name="local.biblioset.attrib">
+    <empty/>
+  </define>
+  <define name="biblioset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A "raw" container for related bibliographic information. -->
+  <define name="biblioset">
+    <element name="biblioset">
+      <ref name="biblioset.attlist"/>
+      <oneOrMore>
+        <ref name="bibliocomponent.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of biblioset.element -->
+  <!-- Relation: Relationship of elements contained within BiblioSet -->
+  <define name="biblioset.attlist" combine="interleave">
+    <optional>
+      <attribute name="relation"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="biblioset.role.attrib"/>
+    <ref name="local.biblioset.attrib"/>
+  </define>
+  <!-- end of biblioset.attlist -->
+  <!-- end of biblioset.module -->
+  <define name="bibliomset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <define name="local.bibliomset.attrib">
+    <empty/>
+  </define>
+  <!-- doc:A "cooked" container for related bibliographic information. -->
+  <define name="bibliomset">
+    <element name="bibliomset">
+      <ref name="bibliomset.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="bibliocomponent.mix"/>
+          <ref name="bibliomset"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of bibliomset.element -->
+  <!-- Relation: Relationship of elements contained within BiblioMSet -->
+  <define name="bibliomset.attlist" combine="interleave">
+    <optional>
+      <attribute name="relation"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="bibliomset.role.attrib"/>
+    <ref name="local.bibliomset.attrib"/>
+  </define>
+  <!-- end of bibliomset.attlist -->
+  <!-- end of bibliomset.module -->
+  <define name="local.bibliomisc.attrib">
+    <empty/>
+  </define>
+  <define name="bibliomisc.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Untyped bibliographic information. -->
+  <define name="bibliomisc">
+    <element name="bibliomisc">
+      <ref name="bibliomisc.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of bibliomisc.element -->
+  <define name="bibliomisc.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="bibliomisc.role.attrib"/>
+    <ref name="local.bibliomisc.attrib"/>
+  </define>
+  <!-- end of bibliomisc.attlist -->
+  <!-- end of bibliomisc.module -->
+  <!-- ...................................................................... -->
+  <!-- Subject, Keyword, and ITermSet elements .............................. -->
+  <define name="local.subjectset.attrib">
+    <empty/>
+  </define>
+  <define name="subjectset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A set of terms describing the subject matter of a document. -->
+  <define name="subjectset">
+    <element name="subjectset">
+      <ref name="subjectset.attlist"/>
+      <oneOrMore>
+        <ref name="subject"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of subjectset.element -->
+  <!-- Scheme: Controlled vocabulary employed in SubjectTerms -->
+  <define name="subjectset.attlist" combine="interleave">
+    <optional>
+      <attribute name="scheme">
+        <data type="NMTOKEN"/>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="subjectset.role.attrib"/>
+    <ref name="local.subjectset.attrib"/>
+  </define>
+  <!-- end of subjectset.attlist -->
+  <!-- end of subjectset.module -->
+  <define name="local.subject.attrib">
+    <empty/>
+  </define>
+  <define name="subject.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:One of a group of terms describing the subject matter of a document. -->
+  <define name="subject">
+    <element name="subject">
+      <ref name="subject.attlist"/>
+      <oneOrMore>
+        <ref name="subjectterm"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of subject.element -->
+  <!--
+    Weight: Ranking of this group of SubjectTerms relative
+    to others, 0 is low, no highest value specified
+  -->
+  <define name="subject.attlist" combine="interleave">
+    <optional>
+      <attribute name="weight"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="subject.role.attrib"/>
+    <ref name="local.subject.attrib"/>
+  </define>
+  <!-- end of subject.attlist -->
+  <!-- end of subject.module -->
+  <define name="local.subjectterm.attrib">
+    <empty/>
+  </define>
+  <define name="subjectterm.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A term in a group of terms describing the subject matter of a document. -->
+  <define name="subjectterm">
+    <element name="subjectterm">
+      <ref name="subjectterm.attlist"/>
+      <text/>
+    </element>
+  </define>
+  <!-- end of subjectterm.element -->
+  <define name="subjectterm.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="subjectterm.role.attrib"/>
+    <ref name="local.subjectterm.attrib"/>
+  </define>
+  <!-- end of subjectterm.attlist -->
+  <!-- end of subjectterm.module -->
+  <!-- end of subjectset.content.module -->
+  <define name="local.keywordset.attrib">
+    <empty/>
+  </define>
+  <define name="keywordset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A set of keywords describing the content of a document. -->
+  <define name="keywordset">
+    <element name="keywordset">
+      <ref name="keywordset.attlist"/>
+      <oneOrMore>
+        <ref name="keyword"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of keywordset.element -->
+  <define name="keywordset.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="keywordset.role.attrib"/>
+    <ref name="local.keywordset.attrib"/>
+  </define>
+  <!-- end of keywordset.attlist -->
+  <!-- end of keywordset.module -->
+  <define name="local.keyword.attrib">
+    <empty/>
+  </define>
+  <define name="keyword.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:One of a set of keywords describing the content of a document. -->
+  <define name="keyword">
+    <element name="keyword">
+      <ref name="keyword.attlist"/>
+      <text/>
+    </element>
+  </define>
+  <!-- end of keyword.element -->
+  <define name="keyword.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="keyword.role.attrib"/>
+    <ref name="local.keyword.attrib"/>
+  </define>
+  <!-- end of keyword.attlist -->
+  <!-- end of keyword.module -->
+  <!-- end of keywordset.content.module -->
+  <define name="local.itermset.attrib">
+    <empty/>
+  </define>
+  <define name="itermset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A set of index terms in the meta-information of a document. -->
+  <define name="itermset">
+    <element name="itermset">
+      <ref name="itermset.attlist"/>
+      <oneOrMore>
+        <ref name="indexterm"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of itermset.element -->
+  <define name="itermset.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="itermset.role.attrib"/>
+    <ref name="local.itermset.attrib"/>
+  </define>
+  <!-- end of itermset.attlist -->
+  <!-- end of itermset.module -->
+  <!-- Bibliographic info for "blocks" -->
+  <define name="local.blockinfo.attrib">
+    <empty/>
+  </define>
+  <define name="blockinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a block element. -->
+  <define name="blockinfo">
+    <element name="blockinfo">
+      <ref name="blockinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of blockinfo.element -->
+  <define name="blockinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="blockinfo.role.attrib"/>
+    <ref name="local.blockinfo.attrib"/>
+  </define>
+  <!-- end of blockinfo.attlist -->
+  <!-- end of blockinfo.module -->
+  <!-- ...................................................................... -->
+  <!-- Compound (section-ish) elements ...................................... -->
+  <!-- Message set ...................... -->
+  <define name="local.msgset.attrib">
+    <empty/>
+  </define>
+  <define name="msgset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A detailed set of messages, usually error messages. -->
+  <define name="msgset">
+    <element name="msgset">
+      <ref name="msgset.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <choice>
+        <oneOrMore>
+          <ref name="msgentry"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="simplemsgentry"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of msgset.element -->
+  <define name="msgset.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgset.role.attrib"/>
+    <ref name="local.msgset.attrib"/>
+  </define>
+  <!-- end of msgset.attlist -->
+  <!-- end of msgset.module -->
+  <define name="local.msgentry.attrib">
+    <empty/>
+  </define>
+  <define name="msgentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for an entry in a message set. -->
+  <define name="msgentry">
+    <element name="msgentry">
+      <ref name="msgentry.attlist"/>
+      <oneOrMore>
+        <ref name="msg"/>
+      </oneOrMore>
+      <optional>
+        <ref name="msginfo"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="msgexplan"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of msgentry.element -->
+  <define name="msgentry.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgentry.role.attrib"/>
+    <ref name="local.msgentry.attrib"/>
+  </define>
+  <!-- end of msgentry.attlist -->
+  <!-- end of msgentry.module -->
+  <define name="local.simplemsgentry.attrib">
+    <empty/>
+  </define>
+  <define name="simplemsgentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for a simpler entry in a message set. -->
+  <define name="simplemsgentry">
+    <element name="simplemsgentry">
+      <ref name="simplemsgentry.attlist"/>
+      <ref name="msgtext"/>
+      <oneOrMore>
+        <ref name="msgexplan"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of simplemsgentry.element -->
+  <define name="simplemsgentry.attlist" combine="interleave">
+    <optional>
+      <attribute name="audience"/>
+    </optional>
+    <optional>
+      <attribute name="level"/>
+    </optional>
+    <optional>
+      <attribute name="origin"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="simplemsgentry.role.attrib"/>
+    <ref name="local.simplemsgentry.attrib"/>
+  </define>
+  <!-- end of simplemsgentry.attlist -->
+  <!-- end of simplemsgentry.module -->
+  <define name="local.msg.attrib">
+    <empty/>
+  </define>
+  <define name="msg.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A message in a message set. -->
+  <define name="msg">
+    <element name="msg">
+      <ref name="msg.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <ref name="msgmain"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="msgsub"/>
+          <ref name="msgrel"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of msg.element -->
+  <define name="msg.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msg.role.attrib"/>
+    <ref name="local.msg.attrib"/>
+  </define>
+  <!-- end of msg.attlist -->
+  <!-- end of msg.module -->
+  <define name="local.msgmain.attrib">
+    <empty/>
+  </define>
+  <define name="msgmain.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The primary component of a message in a message set. -->
+  <define name="msgmain">
+    <element name="msgmain">
+      <ref name="msgmain.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <ref name="msgtext"/>
+    </element>
+  </define>
+  <!-- end of msgmain.element -->
+  <define name="msgmain.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgmain.role.attrib"/>
+    <ref name="local.msgmain.attrib"/>
+  </define>
+  <!-- end of msgmain.attlist -->
+  <!-- end of msgmain.module -->
+  <define name="local.msgsub.attrib">
+    <empty/>
+  </define>
+  <define name="msgsub.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subcomponent of a message in a message set. -->
+  <define name="msgsub">
+    <element name="msgsub">
+      <ref name="msgsub.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <ref name="msgtext"/>
+    </element>
+  </define>
+  <!-- end of msgsub.element -->
+  <define name="msgsub.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgsub.role.attrib"/>
+    <ref name="local.msgsub.attrib"/>
+  </define>
+  <!-- end of msgsub.attlist -->
+  <!-- end of msgsub.module -->
+  <define name="local.msgrel.attrib">
+    <empty/>
+  </define>
+  <define name="msgrel.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A related component of a message in a message set. -->
+  <define name="msgrel">
+    <element name="msgrel">
+      <ref name="msgrel.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <ref name="msgtext"/>
+    </element>
+  </define>
+  <!-- end of msgrel.element -->
+  <define name="msgrel.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgrel.role.attrib"/>
+    <ref name="local.msgrel.attrib"/>
+  </define>
+  <!-- end of msgrel.attlist -->
+  <!-- end of msgrel.module -->
+  <!--  MsgText (defined in the Inlines section, below) -->
+  <define name="local.msginfo.attrib">
+    <empty/>
+  </define>
+  <define name="msginfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Information about a message in a message set. -->
+  <define name="msginfo">
+    <element name="msginfo">
+      <ref name="msginfo.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="msglevel"/>
+          <ref name="msgorig"/>
+          <ref name="msgaud"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of msginfo.element -->
+  <define name="msginfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msginfo.role.attrib"/>
+    <ref name="local.msginfo.attrib"/>
+  </define>
+  <!-- end of msginfo.attlist -->
+  <!-- end of msginfo.module -->
+  <define name="local.msglevel.attrib">
+    <empty/>
+  </define>
+  <define name="msglevel.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The level of importance or severity of a message in a message set. -->
+  <define name="msglevel">
+    <element name="msglevel">
+      <ref name="msglevel.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of msglevel.element -->
+  <define name="msglevel.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msglevel.role.attrib"/>
+    <ref name="local.msglevel.attrib"/>
+  </define>
+  <!-- end of msglevel.attlist -->
+  <!-- end of msglevel.module -->
+  <define name="local.msgorig.attrib">
+    <empty/>
+  </define>
+  <define name="msgorig.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The origin of a message in a message set. -->
+  <define name="msgorig">
+    <element name="msgorig">
+      <ref name="msgorig.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of msgorig.element -->
+  <define name="msgorig.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgorig.role.attrib"/>
+    <ref name="local.msgorig.attrib"/>
+  </define>
+  <!-- end of msgorig.attlist -->
+  <!-- end of msgorig.module -->
+  <define name="local.msgaud.attrib">
+    <empty/>
+  </define>
+  <define name="msgaud.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The audience to which a message in a message set is relevant. -->
+  <define name="msgaud">
+    <element name="msgaud">
+      <ref name="msgaud.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of msgaud.element -->
+  <define name="msgaud.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgaud.role.attrib"/>
+    <ref name="local.msgaud.attrib"/>
+  </define>
+  <!-- end of msgaud.attlist -->
+  <!-- end of msgaud.module -->
+  <define name="local.msgexplan.attrib">
+    <empty/>
+  </define>
+  <define name="msgexplan.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Explanatory material relating to a message in a message set. -->
+  <define name="msgexplan">
+    <element name="msgexplan">
+      <ref name="msgexplan.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of msgexplan.element -->
+  <define name="msgexplan.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgexplan.role.attrib"/>
+    <ref name="local.msgexplan.attrib"/>
+  </define>
+  <!-- end of msgexplan.attlist -->
+  <!-- end of msgexplan.module -->
+  <!-- end of msgset.content.module -->
+  <define name="local.task.attrib">
+    <empty/>
+  </define>
+  <define name="task.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A task to be completed. -->
+  <define name="task">
+    <element name="task">
+      <ref name="task.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="ndxterm.class"/>
+      </zeroOrMore>
+      <ref name="formalobject.title.content"/>
+      <optional>
+        <ref name="tasksummary"/>
+      </optional>
+      <optional>
+        <ref name="taskprerequisites"/>
+      </optional>
+      <ref name="procedure"/>
+      <zeroOrMore>
+        <ref name="example"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="taskrelated"/>
+      </optional>
+    </element>
+  </define>
+  <!-- end of task.element -->
+  <define name="task.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="task.role.attrib"/>
+    <ref name="local.task.attrib"/>
+  </define>
+  <!-- end of task.attlist -->
+  <!-- end of task.module -->
+  <define name="local.tasksummary.attrib">
+    <empty/>
+  </define>
+  <define name="tasksummary.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A summary of a task. -->
+  <define name="tasksummary">
+    <element name="tasksummary">
+      <ref name="tasksummary.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of tasksummary.element -->
+  <define name="tasksummary.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="tasksummary.role.attrib"/>
+    <ref name="local.tasksummary.attrib"/>
+  </define>
+  <!-- end of tasksummary.attlist -->
+  <!-- end of tasksummary.module -->
+  <define name="local.taskprerequisites.attrib">
+    <empty/>
+  </define>
+  <define name="taskprerequisites.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The prerequisites for a task. -->
+  <define name="taskprerequisites">
+    <element name="taskprerequisites">
+      <ref name="taskprerequisites.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of taskprerequisites.element -->
+  <define name="taskprerequisites.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="taskprerequisites.role.attrib"/>
+    <ref name="local.taskprerequisites.attrib"/>
+  </define>
+  <!-- end of taskprerequisites.attlist -->
+  <!-- end of taskprerequisites.module -->
+  <define name="local.taskrelated.attrib">
+    <empty/>
+  </define>
+  <define name="taskrelated.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Information related to a task. -->
+  <define name="taskrelated">
+    <element name="taskrelated">
+      <ref name="taskrelated.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of taskrelated.element -->
+  <define name="taskrelated.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="taskrelated.role.attrib"/>
+    <ref name="local.taskrelated.attrib"/>
+  </define>
+  <!-- end of taskrelated.attlist -->
+  <!-- end of taskrelated.module -->
+  <!-- end of task.content.module -->
+  <!-- QandASet ........................ -->
+  <define name="local.qandaset.attrib">
+    <empty/>
+  </define>
+  <define name="qandaset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A question-and-answer set. -->
+  <define name="qandaset">
+    <element name="qandaset">
+      <ref name="qandaset.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="qandaset.mix"/>
+      </zeroOrMore>
+      <choice>
+        <oneOrMore>
+          <ref name="qandadiv"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="qandaentry"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of qandaset.element -->
+  <define name="qandaset.attlist" combine="interleave">
+    <optional>
+      <attribute name="defaultlabel">
+        <choice>
+          <value>qanda</value>
+          <value>number</value>
+          <value>none</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="qandaset.role.attrib"/>
+    <ref name="local.qandaset.attrib"/>
+  </define>
+  <!-- end of qandaset.attlist -->
+  <!-- end of qandaset.module -->
+  <define name="local.qandadiv.attrib">
+    <empty/>
+  </define>
+  <define name="qandadiv.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A titled division in a QandASet. -->
+  <define name="qandadiv">
+    <element name="qandadiv">
+      <ref name="qandadiv.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="qandaset.mix"/>
+      </zeroOrMore>
+      <choice>
+        <oneOrMore>
+          <ref name="qandadiv"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="qandaentry"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of qandadiv.element -->
+  <define name="qandadiv.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="qandadiv.role.attrib"/>
+    <ref name="local.qandadiv.attrib"/>
+  </define>
+  <!-- end of qandadiv.attlist -->
+  <!-- end of qandadiv.module -->
+  <define name="local.qandaentry.attrib">
+    <empty/>
+  </define>
+  <define name="qandaentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A question/answer set within a QandASet. -->
+  <define name="qandaentry">
+    <element name="qandaentry">
+      <ref name="qandaentry.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="revhistory"/>
+      </optional>
+      <ref name="question"/>
+      <zeroOrMore>
+        <ref name="answer"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of qandaentry.element -->
+  <define name="qandaentry.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="qandaentry.role.attrib"/>
+    <ref name="local.qandaentry.attrib"/>
+  </define>
+  <!-- end of qandaentry.attlist -->
+  <!-- end of qandaentry.module -->
+  <define name="local.question.attrib">
+    <empty/>
+  </define>
+  <define name="question.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A question in a QandASet. -->
+  <define name="question">
+    <element name="question">
+      <ref name="question.attlist"/>
+      <optional>
+        <ref name="label"/>
+      </optional>
+      <oneOrMore>
+        <ref name="qandaset.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of question.element -->
+  <define name="question.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="question.role.attrib"/>
+    <ref name="local.question.attrib"/>
+  </define>
+  <!-- end of question.attlist -->
+  <!-- end of question.module -->
+  <define name="local.answer.attrib">
+    <empty/>
+  </define>
+  <define name="answer.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An answer to a question posed in a QandASet. -->
+  <define name="answer">
+    <element name="answer">
+      <ref name="answer.attlist"/>
+      <optional>
+        <ref name="label"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="qandaset.mix"/>
+      </zeroOrMore>
+      <zeroOrMore>
+        <ref name="qandaentry"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of answer.element -->
+  <define name="answer.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="answer.role.attrib"/>
+    <ref name="local.answer.attrib"/>
+  </define>
+  <!-- end of answer.attlist -->
+  <!-- end of answer.module -->
+  <define name="local.label.attrib">
+    <empty/>
+  </define>
+  <define name="label.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A label on a Question or Answer. -->
+  <define name="label">
+    <element name="label">
+      <ref name="label.attlist"/>
+      <zeroOrMore>
+        <ref name="word.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of label.element -->
+  <define name="label.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="label.role.attrib"/>
+    <ref name="local.label.attrib"/>
+  </define>
+  <!-- end of label.attlist -->
+  <!-- end of label.module -->
+  <!-- end of qandaset.content.module -->
+  <!-- Procedure ........................ -->
+  <define name="local.procedure.attrib">
+    <empty/>
+  </define>
+  <define name="procedure.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A list of operations to be performed in a well-defined sequence. -->
+  <define name="procedure">
+    <element name="procedure">
+      <ref name="procedure.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="component.mix"/>
+      </zeroOrMore>
+      <oneOrMore>
+        <ref name="step"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of procedure.element -->
+  <define name="procedure.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="procedure.role.attrib"/>
+    <ref name="local.procedure.attrib"/>
+  </define>
+  <!-- end of procedure.attlist -->
+  <!-- end of procedure.module -->
+  <define name="local.step.attrib">
+    <empty/>
+  </define>
+  <define name="step.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A unit of action in a procedure. -->
+  <define name="step">
+    <element name="step">
+      <ref name="step.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <choice>
+        <group>
+          <oneOrMore>
+            <ref name="component.mix"/>
+          </oneOrMore>
+          <optional>
+            <choice>
+              <ref name="substeps"/>
+              <ref name="stepalternatives"/>
+            </choice>
+            <zeroOrMore>
+              <ref name="component.mix"/>
+            </zeroOrMore>
+          </optional>
+        </group>
+        <group>
+          <choice>
+            <ref name="substeps"/>
+            <ref name="stepalternatives"/>
+          </choice>
+          <zeroOrMore>
+            <ref name="component.mix"/>
+          </zeroOrMore>
+        </group>
+      </choice>
+    </element>
+  </define>
+  <!-- end of step.element -->
+  <!-- Performance: Whether the Step must be performed -->
+  <!-- not #REQUIRED! -->
+  <define name="step.attlist" combine="interleave">
+    <optional>
+      <attribute name="performance" a:defaultValue="required">
+        <choice>
+          <value>optional</value>
+          <value>required</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="step.role.attrib"/>
+    <ref name="local.step.attrib"/>
+  </define>
+  <!-- end of step.attlist -->
+  <!-- end of step.module -->
+  <define name="local.substeps.attrib">
+    <empty/>
+  </define>
+  <define name="substeps.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for steps that occur within steps in a procedure. -->
+  <define name="substeps">
+    <element name="substeps">
+      <ref name="substeps.attlist"/>
+      <oneOrMore>
+        <ref name="step"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of substeps.element -->
+  <!-- Performance: whether entire set of substeps must be performed -->
+  <!-- not #REQUIRED! -->
+  <define name="substeps.attlist" combine="interleave">
+    <optional>
+      <attribute name="performance" a:defaultValue="required">
+        <choice>
+          <value>optional</value>
+          <value>required</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="substeps.role.attrib"/>
+    <ref name="local.substeps.attrib"/>
+  </define>
+  <!-- end of substeps.attlist -->
+  <!-- end of substeps.module -->
+  <define name="local.stepalternatives.attrib">
+    <empty/>
+  </define>
+  <define name="stepalternatives.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Alternative steps in a procedure. -->
+  <define name="stepalternatives">
+    <element name="stepalternatives">
+      <ref name="stepalternatives.attlist"/>
+      <oneOrMore>
+        <ref name="step"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of stepalternatives.element -->
+  <!-- Performance: Whether (one of) the alternatives must be performed -->
+  <!-- not #REQUIRED! -->
+  <define name="stepalternatives.attlist" combine="interleave">
+    <optional>
+      <attribute name="performance" a:defaultValue="required">
+        <choice>
+          <value>optional</value>
+          <value>required</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="stepalternatives.role.attrib"/>
+    <ref name="local.stepalternatives.attrib"/>
+  </define>
+  <!-- end of stepalternatives.attlist -->
+  <!-- end of stepalternatives.module -->
+  <!-- end of procedure.content.module -->
+  <!-- Sidebar .......................... -->
+  <define name="local.sidebarinfo.attrib">
+    <empty/>
+  </define>
+  <define name="sidebarinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for a Sidebar. -->
+  <define name="sidebarinfo">
+    <element name="sidebarinfo">
+      <ref name="sidebarinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sidebarinfo.element -->
+  <define name="sidebarinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sidebarinfo.role.attrib"/>
+    <ref name="local.sidebarinfo.attrib"/>
+  </define>
+  <!-- end of sidebarinfo.attlist -->
+  <!-- end of sidebarinfo.module -->
+  <define name="local.sidebar.attrib">
+    <empty/>
+  </define>
+  <define name="sidebar.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A portion of a document that is isolated from the main narrative flow. -->
+  <define name="sidebar">
+    <element name="sidebar">
+      <ref name="sidebar.attlist"/>
+      <optional>
+        <ref name="sidebarinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="sidebar.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of sidebar.element -->
+  <define name="sidebar.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sidebar.role.attrib"/>
+    <ref name="local.sidebar.attrib"/>
+  </define>
+  <!-- end of sidebar.attlist -->
+  <!-- end of sidebar.module -->
+  <!-- end of sidebar.content.model -->
+  <!-- ...................................................................... -->
+  <!-- Paragraph-related elements ........................................... -->
+  <define name="local.abstract.attrib">
+    <empty/>
+  </define>
+  <define name="abstract.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A summary. -->
+  <define name="abstract">
+    <element name="abstract">
+      <ref name="abstract.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="para.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of abstract.element -->
+  <define name="abstract.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="abstract.role.attrib"/>
+    <ref name="local.abstract.attrib"/>
+  </define>
+  <!-- end of abstract.attlist -->
+  <!-- end of abstract.module -->
+  <define name="local.authorblurb.attrib">
+    <empty/>
+  </define>
+  <define name="authorblurb.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A short description or note about an author. -->
+  <define name="authorblurb">
+    <element name="authorblurb">
+      <ref name="authorblurb.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="para.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of authorblurb.element -->
+  <define name="authorblurb.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="authorblurb.role.attrib"/>
+    <ref name="local.authorblurb.attrib"/>
+  </define>
+  <!-- end of authorblurb.attlist -->
+  <!-- end of authorblurb.module -->
+  <define name="local.personblurb.attrib">
+    <empty/>
+  </define>
+  <define name="personblurb.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A short description or note about a person. -->
+  <define name="personblurb">
+    <element name="personblurb">
+      <ref name="personblurb.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="para.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of personblurb.element -->
+  <define name="personblurb.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="personblurb.role.attrib"/>
+    <ref name="local.personblurb.attrib"/>
+  </define>
+  <!-- end of personblurb.attlist -->
+  <!-- end of personblurb.module -->
+  <define name="local.blockquote.attrib">
+    <empty/>
+  </define>
+  <define name="blockquote.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A quotation set off from the main text. -->
+  <define name="blockquote">
+    <element name="blockquote">
+      <ref name="blockquote.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <optional>
+        <ref name="attribution"/>
+      </optional>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of blockquote.element -->
+  <define name="blockquote.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="blockquote.role.attrib"/>
+    <ref name="local.blockquote.attrib"/>
+  </define>
+  <!-- end of blockquote.attlist -->
+  <!-- end of blockquote.module -->
+  <define name="local.attribution.attrib">
+    <empty/>
+  </define>
+  <define name="attribution.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The source of a block quote or epigraph. -->
+  <define name="attribution">
+    <element name="attribution">
+      <ref name="attribution.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of attribution.element -->
+  <define name="attribution.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="attribution.role.attrib"/>
+    <ref name="local.attribution.attrib"/>
+  </define>
+  <!-- end of attribution.attlist -->
+  <!-- end of attribution.module -->
+  <define name="local.bridgehead.attrib">
+    <empty/>
+  </define>
+  <define name="bridgehead.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A free-floating heading. -->
+  <define name="bridgehead">
+    <element name="bridgehead">
+      <ref name="bridgehead.attlist"/>
+      <zeroOrMore>
+        <ref name="title.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of bridgehead.element -->
+  <!--
+    Renderas: Indicates the format in which the BridgeHead
+    should appear
+  -->
+  <define name="bridgehead.attlist" combine="interleave">
+    <optional>
+      <attribute name="renderas">
+        <choice>
+          <value>other</value>
+          <value>sect1</value>
+          <value>sect2</value>
+          <value>sect3</value>
+          <value>sect4</value>
+          <value>sect5</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="bridgehead.role.attrib"/>
+    <ref name="local.bridgehead.attrib"/>
+  </define>
+  <!-- end of bridgehead.attlist -->
+  <!-- end of bridgehead.module -->
+  <define name="local.remark.attrib">
+    <empty/>
+  </define>
+  <define name="remark.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A remark (or comment) intended for presentation in a draft manuscript. -->
+  <define name="remark">
+    <element name="remark">
+      <ref name="remark.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of remark.element -->
+  <define name="remark.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="remark.role.attrib"/>
+    <ref name="local.remark.attrib"/>
+  </define>
+  <!-- end of remark.attlist -->
+  <!-- end of remark.module -->
+  <define name="local.epigraph.attrib">
+    <empty/>
+  </define>
+  <define name="epigraph.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A short inscription at the beginning of a document or component. -->
+  <define name="epigraph">
+    <element name="epigraph">
+      <ref name="epigraph.attlist"/>
+      <optional>
+        <ref name="attribution"/>
+      </optional>
+      <oneOrMore>
+        <choice>
+          <ref name="para.class"/>
+          <ref name="literallayout"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of epigraph.element -->
+  <define name="epigraph.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="epigraph.role.attrib"/>
+    <ref name="local.epigraph.attrib"/>
+  </define>
+  <!-- end of epigraph.attlist -->
+  <!--  Attribution (defined above) -->
+  <!-- end of epigraph.module -->
+  <define name="local.footnote.attrib">
+    <empty/>
+  </define>
+  <define name="footnote.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A footnote. -->
+  <define name="footnote">
+    <element name="footnote">
+      <ref name="footnote.attlist"/>
+      <oneOrMore>
+        <ref name="footnote.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of footnote.element -->
+  <define name="footnote.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="footnote.role.attrib"/>
+    <ref name="local.footnote.attrib"/>
+  </define>
+  <!-- end of footnote.attlist -->
+  <!-- end of footnote.module -->
+  <define name="local.highlights.attrib">
+    <empty/>
+  </define>
+  <define name="highlights.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A summary of the main points of the discussed component. -->
+  <define name="highlights">
+    <element name="highlights">
+      <ref name="highlights.attlist"/>
+      <oneOrMore>
+        <ref name="highlights.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of highlights.element -->
+  <define name="highlights.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="highlights.role.attrib"/>
+    <ref name="local.highlights.attrib"/>
+  </define>
+  <!-- end of highlights.attlist -->
+  <!-- end of highlights.module -->
+  <define name="local.formalpara.attrib">
+    <empty/>
+  </define>
+  <define name="formalpara.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A paragraph with a title. -->
+  <define name="formalpara">
+    <element name="formalpara">
+      <ref name="formalpara.attlist"/>
+      <ref name="title"/>
+      <zeroOrMore>
+        <ref name="ndxterm.class"/>
+      </zeroOrMore>
+      <ref name="para"/>
+    </element>
+  </define>
+  <!-- end of formalpara.element -->
+  <define name="formalpara.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="formalpara.role.attrib"/>
+    <ref name="local.formalpara.attrib"/>
+  </define>
+  <!-- end of formalpara.attlist -->
+  <!-- end of formalpara.module -->
+  <define name="local.para.attrib">
+    <empty/>
+  </define>
+  <define name="para.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A paragraph. -->
+  <define name="para">
+    <element name="para">
+      <ref name="para.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="para.char.mix"/>
+          <ref name="para.mix"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of para.element -->
+  <define name="para.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="para.role.attrib"/>
+    <ref name="local.para.attrib"/>
+  </define>
+  <!-- end of para.attlist -->
+  <!-- end of para.module -->
+  <define name="local.simpara.attrib">
+    <empty/>
+  </define>
+  <define name="simpara.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A paragraph that contains only text and inline markup, no block elements. -->
+  <define name="simpara">
+    <element name="simpara">
+      <ref name="simpara.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of simpara.element -->
+  <define name="simpara.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="simpara.role.attrib"/>
+    <ref name="local.simpara.attrib"/>
+  </define>
+  <!-- end of simpara.attlist -->
+  <!-- end of simpara.module -->
+  <define name="local.admon.attrib">
+    <empty/>
+  </define>
+  <define name="admon.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A note of caution. -->
+  <define name="caution">
+    <element name="caution">
+      <ref name="caution.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="admon.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of caution.element -->
+  <define name="caution.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="admon.role.attrib"/>
+    <ref name="local.admon.attrib"/>
+  </define>
+  <!-- end of caution.attlist -->
+  <!-- doc:An admonition set off from the text. -->
+  <define name="important">
+    <element name="important">
+      <ref name="important.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="admon.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of important.element -->
+  <define name="important.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="admon.role.attrib"/>
+    <ref name="local.admon.attrib"/>
+  </define>
+  <!-- end of important.attlist -->
+  <!-- doc:A message set off from the text. -->
+  <define name="note">
+    <element name="note">
+      <ref name="note.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="admon.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of note.element -->
+  <define name="note.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="admon.role.attrib"/>
+    <ref name="local.admon.attrib"/>
+  </define>
+  <!-- end of note.attlist -->
+  <!-- doc:A suggestion to the user, set off from the text. -->
+  <define name="tip">
+    <element name="tip">
+      <ref name="tip.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="admon.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of tip.element -->
+  <define name="tip.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="admon.role.attrib"/>
+    <ref name="local.admon.attrib"/>
+  </define>
+  <!-- end of tip.attlist -->
+  <!-- doc:An admonition set off from the text. -->
+  <define name="warning">
+    <element name="warning">
+      <ref name="warning.attlist"/>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="admon.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of warning.element -->
+  <define name="warning.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="admon.role.attrib"/>
+    <ref name="local.admon.attrib"/>
+  </define>
+  <!-- end of warning.attlist -->
+  <!-- end of admon.module -->
+  <!-- ...................................................................... -->
+  <!-- Lists ................................................................ -->
+  <!-- GlossList ........................ -->
+  <define name="local.glosslist.attrib">
+    <empty/>
+  </define>
+  <define name="glosslist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for a set of GlossEntrys. -->
+  <define name="glosslist">
+    <element name="glosslist">
+      <ref name="glosslist.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="glossentry"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of glosslist.element -->
+  <define name="glosslist.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="glosslist.role.attrib"/>
+    <ref name="local.glosslist.attrib"/>
+  </define>
+  <!-- end of glosslist.attlist -->
+  <!-- end of glosslist.module -->
+  <define name="local.glossentry.attrib">
+    <empty/>
+  </define>
+  <define name="glossentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry in a Glossary or GlossList. -->
+  <define name="glossentry">
+    <element name="glossentry">
+      <ref name="glossentry.attlist"/>
+      <ref name="glossterm"/>
+      <optional>
+        <ref name="acronym"/>
+      </optional>
+      <optional>
+        <ref name="abbrev"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="ndxterm.class"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="revhistory"/>
+      </optional>
+      <choice>
+        <ref name="glosssee"/>
+        <oneOrMore>
+          <ref name="glossdef"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of glossentry.element -->
+  <!--
+    SortAs: String by which the GlossEntry is to be sorted
+    (alphabetized) in lieu of its proper content
+  -->
+  <define name="glossentry.attlist" combine="interleave">
+    <optional>
+      <attribute name="sortas"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="glossentry.role.attrib"/>
+    <ref name="local.glossentry.attrib"/>
+  </define>
+  <!-- end of glossentry.attlist -->
+  <!-- end of glossentry.module -->
+  <!--  GlossTerm (defined in the Inlines section, below) -->
+  <define name="local.glossdef.attrib">
+    <empty/>
+  </define>
+  <define name="glossdef.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A definition in a GlossEntry. -->
+  <define name="glossdef">
+    <element name="glossdef">
+      <ref name="glossdef.attlist"/>
+      <oneOrMore>
+        <ref name="glossdef.mix"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="glossseealso"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of glossdef.element -->
+  <!-- Subject: List of subjects; keywords for the definition -->
+  <define name="glossdef.attlist" combine="interleave">
+    <optional>
+      <attribute name="subject"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="glossdef.role.attrib"/>
+    <ref name="local.glossdef.attrib"/>
+  </define>
+  <!-- end of glossdef.attlist -->
+  <!-- end of glossdef.module -->
+  <define name="local.glosssee.attrib">
+    <empty/>
+  </define>
+  <define name="glosssee.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A cross-reference from one GlossEntry to another. -->
+  <define name="glosssee">
+    <element name="glosssee">
+      <ref name="glosssee.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of glosssee.element -->
+  <!--
+    OtherTerm: Reference to the GlossEntry whose GlossTerm
+    should be displayed at the point of the GlossSee
+  -->
+  <define name="glosssee.attlist" combine="interleave">
+    <optional>
+      <attribute name="otherterm">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="glosssee.role.attrib"/>
+    <ref name="local.glosssee.attrib"/>
+  </define>
+  <!-- end of glosssee.attlist -->
+  <!-- end of glosssee.module -->
+  <define name="local.glossseealso.attrib">
+    <empty/>
+  </define>
+  <define name="glossseealso.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A cross-reference from one GlossEntry to another. -->
+  <define name="glossseealso">
+    <element name="glossseealso">
+      <ref name="glossseealso.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of glossseealso.element -->
+  <!--
+    OtherTerm: Reference to the GlossEntry whose GlossTerm
+    should be displayed at the point of the GlossSeeAlso
+  -->
+  <define name="glossseealso.attlist" combine="interleave">
+    <optional>
+      <attribute name="otherterm">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="glossseealso.role.attrib"/>
+    <ref name="local.glossseealso.attrib"/>
+  </define>
+  <!-- end of glossseealso.attlist -->
+  <!-- end of glossseealso.module -->
+  <!-- end of glossentry.content.module -->
+  <!-- ItemizedList and OrderedList ..... -->
+  <define name="local.itemizedlist.attrib">
+    <empty/>
+  </define>
+  <define name="itemizedlist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A list in which each entry is marked with a bullet or other dingbat. -->
+  <define name="itemizedlist">
+    <element name="itemizedlist">
+      <ref name="itemizedlist.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="listpreamble.mix"/>
+      </zeroOrMore>
+      <oneOrMore>
+        <ref name="listitem"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of itemizedlist.element -->
+  <!--
+    Spacing: Whether the vertical space in the list should be
+    compressed
+  -->
+  <!--
+    Mark: Keyword, e.g., bullet, dash, checkbox, none;
+    list of keywords and defaults are implementation specific
+  -->
+  <define name="itemizedlist.attlist" combine="interleave">
+    <optional>
+      <attribute name="spacing">
+        <choice>
+          <value>normal</value>
+          <value>compact</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="mark.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="itemizedlist.role.attrib"/>
+    <ref name="local.itemizedlist.attrib"/>
+  </define>
+  <!-- end of itemizedlist.attlist -->
+  <!-- end of itemizedlist.module -->
+  <define name="local.orderedlist.attrib">
+    <empty/>
+  </define>
+  <define name="orderedlist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A list in which each entry is marked with a sequentially incremented label. -->
+  <define name="orderedlist">
+    <element name="orderedlist">
+      <ref name="orderedlist.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="listpreamble.mix"/>
+      </zeroOrMore>
+      <oneOrMore>
+        <ref name="listitem"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of orderedlist.element -->
+  <!--
+    Numeration: Style of ListItem numbered; default is expected
+    to be Arabic
+  -->
+  <!--
+    InheritNum: Specifies for a nested list that the numbering
+    of ListItems should include the number of the item
+    within which they are nested (e.g., 1a and 1b within 1,
+    rather than a and b)
+  -->
+  <!--
+    Continuation: Where list numbering begins afresh (Restarts,
+    the default) or continues that of the immediately preceding
+    list (Continues)
+  -->
+  <!--
+    Spacing: Whether the vertical space in the list should be
+    compressed
+  -->
+  <define name="orderedlist.attlist" combine="interleave">
+    <optional>
+      <attribute name="numeration">
+        <choice>
+          <value>arabic</value>
+          <value>upperalpha</value>
+          <value>loweralpha</value>
+          <value>upperroman</value>
+          <value>lowerroman</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="inheritnum" a:defaultValue="ignore">
+        <choice>
+          <value>inherit</value>
+          <value>ignore</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="continuation" a:defaultValue="restarts">
+        <choice>
+          <value>continues</value>
+          <value>restarts</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="spacing">
+        <choice>
+          <value>normal</value>
+          <value>compact</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="orderedlist.role.attrib"/>
+    <ref name="local.orderedlist.attrib"/>
+  </define>
+  <!-- end of orderedlist.attlist -->
+  <!-- end of orderedlist.module -->
+  <define name="local.listitem.attrib">
+    <empty/>
+  </define>
+  <define name="listitem.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for the elements of a list item. -->
+  <define name="listitem">
+    <element name="listitem">
+      <ref name="listitem.attlist"/>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of listitem.element -->
+  <!--
+    Override: Indicates the mark to be used for this ListItem
+    instead of the default mark or the mark specified by
+    the Mark attribute on the enclosing ItemizedList
+  -->
+  <define name="listitem.attlist" combine="interleave">
+    <optional>
+      <attribute name="override"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="listitem.role.attrib"/>
+    <ref name="local.listitem.attrib"/>
+  </define>
+  <!-- end of listitem.attlist -->
+  <!-- end of listitem.module -->
+  <!-- SegmentedList .................... -->
+  <define name="local.segmentedlist.attrib">
+    <empty/>
+  </define>
+  <define name="segmentedlist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A segmented list, a list of sets of elements. -->
+  <define name="segmentedlist">
+    <element name="segmentedlist">
+      <ref name="segmentedlist.attlist"/>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="segtitle"/>
+      </oneOrMore>
+      <oneOrMore>
+        <ref name="seglistitem"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of segmentedlist.element -->
+  <define name="segmentedlist.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="segmentedlist.role.attrib"/>
+    <ref name="local.segmentedlist.attrib"/>
+  </define>
+  <!-- end of segmentedlist.attlist -->
+  <!-- end of segmentedlist.module -->
+  <define name="local.segtitle.attrib">
+    <empty/>
+  </define>
+  <define name="segtitle.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The title of an element of a list item in a segmented list. -->
+  <define name="segtitle">
+    <element name="segtitle">
+      <ref name="segtitle.attlist"/>
+      <zeroOrMore>
+        <ref name="title.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of segtitle.element -->
+  <define name="segtitle.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="segtitle.role.attrib"/>
+    <ref name="local.segtitle.attrib"/>
+  </define>
+  <!-- end of segtitle.attlist -->
+  <!-- end of segtitle.module -->
+  <define name="local.seglistitem.attrib">
+    <empty/>
+  </define>
+  <define name="seglistitem.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A list item in a segmented list. -->
+  <define name="seglistitem">
+    <element name="seglistitem">
+      <ref name="seglistitem.attlist"/>
+      <oneOrMore>
+        <ref name="seg"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of seglistitem.element -->
+  <define name="seglistitem.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="seglistitem.role.attrib"/>
+    <ref name="local.seglistitem.attrib"/>
+  </define>
+  <!-- end of seglistitem.attlist -->
+  <!-- end of seglistitem.module -->
+  <define name="local.seg.attrib">
+    <empty/>
+  </define>
+  <define name="seg.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An element of a list item in a segmented list. -->
+  <define name="seg">
+    <element name="seg">
+      <ref name="seg.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of seg.element -->
+  <define name="seg.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="seg.role.attrib"/>
+    <ref name="local.seg.attrib"/>
+  </define>
+  <!-- end of seg.attlist -->
+  <!-- end of seg.module -->
+  <!-- end of segmentedlist.content.module -->
+  <!-- SimpleList ....................... -->
+  <define name="local.simplelist.attrib">
+    <empty/>
+  </define>
+  <define name="simplelist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An undecorated list of single words or short phrases. -->
+  <define name="simplelist">
+    <element name="simplelist">
+      <ref name="simplelist.attlist"/>
+      <oneOrMore>
+        <ref name="member"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of simplelist.element -->
+  <!-- Columns: The number of columns the array should contain -->
+  <!--
+    Type: How the Members of the SimpleList should be
+    formatted: Inline (members separated with commas etc.
+    inline), Vert (top to bottom in n Columns), or Horiz (in
+    the direction of text flow) in n Columns.  If Column
+    is 1 or implied, Type=Vert and Type=Horiz give the same
+    results.
+  -->
+  <define name="simplelist.attlist" combine="interleave">
+    <optional>
+      <attribute name="columns"/>
+    </optional>
+    <optional>
+      <attribute name="type" a:defaultValue="vert">
+        <choice>
+          <value>inline</value>
+          <value>vert</value>
+          <value>horiz</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="simplelist.role.attrib"/>
+    <ref name="local.simplelist.attrib"/>
+  </define>
+  <!-- end of simplelist.attlist -->
+  <!-- end of simplelist.module -->
+  <define name="local.member.attrib">
+    <empty/>
+  </define>
+  <define name="member.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An element of a simple list. -->
+  <define name="member">
+    <element name="member">
+      <ref name="member.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of member.element -->
+  <define name="member.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="member.role.attrib"/>
+    <ref name="local.member.attrib"/>
+  </define>
+  <!-- end of member.attlist -->
+  <!-- end of member.module -->
+  <!-- end of simplelist.content.module -->
+  <!-- VariableList ..................... -->
+  <define name="local.variablelist.attrib">
+    <empty/>
+  </define>
+  <define name="variablelist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A list in which each entry is composed of a set of one or more terms and an associated description. -->
+  <define name="variablelist">
+    <element name="variablelist">
+      <ref name="variablelist.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="listpreamble.mix"/>
+      </zeroOrMore>
+      <oneOrMore>
+        <ref name="varlistentry"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of variablelist.element -->
+  <!--
+    TermLength: Length beyond which the presentation engine
+    may consider the Term too long and select an alternate
+    presentation of the Term and, or, its associated ListItem.
+  -->
+  <define name="variablelist.attlist" combine="interleave">
+    <optional>
+      <attribute name="termlength"/>
+    </optional>
+    <optional>
+      <attribute name="spacing">
+        <choice>
+          <value>normal</value>
+          <value>compact</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="variablelist.role.attrib"/>
+    <ref name="local.variablelist.attrib"/>
+  </define>
+  <!-- end of variablelist.attlist -->
+  <!-- end of variablelist.module -->
+  <define name="local.varlistentry.attrib">
+    <empty/>
+  </define>
+  <define name="varlistentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for a set of terms and the associated description in a variable list. -->
+  <define name="varlistentry">
+    <element name="varlistentry">
+      <ref name="varlistentry.attlist"/>
+      <oneOrMore>
+        <ref name="term"/>
+      </oneOrMore>
+      <ref name="listitem"/>
+    </element>
+  </define>
+  <!-- end of varlistentry.element -->
+  <define name="varlistentry.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="varlistentry.role.attrib"/>
+    <ref name="local.varlistentry.attrib"/>
+  </define>
+  <!-- end of varlistentry.attlist -->
+  <!-- end of varlistentry.module -->
+  <define name="local.term.attrib">
+    <empty/>
+  </define>
+  <define name="term.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The word or phrase being defined or described in a variable list. -->
+  <define name="term">
+    <element name="term">
+      <ref name="term.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of term.element -->
+  <define name="term.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="term.role.attrib"/>
+    <ref name="local.term.attrib"/>
+  </define>
+  <!-- end of term.attlist -->
+  <!-- end of term.module -->
+  <!--  ListItem (defined above) -->
+  <!-- end of variablelist.content.module -->
+  <!-- CalloutList ...................... -->
+  <define name="local.calloutlist.attrib">
+    <empty/>
+  </define>
+  <define name="calloutlist.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A list of Callouts. -->
+  <define name="calloutlist">
+    <element name="calloutlist">
+      <ref name="calloutlist.attlist"/>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <oneOrMore>
+        <ref name="callout"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of calloutlist.element -->
+  <define name="calloutlist.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="calloutlist.role.attrib"/>
+    <ref name="local.calloutlist.attrib"/>
+  </define>
+  <!-- end of calloutlist.attlist -->
+  <!-- end of calloutlist.module -->
+  <define name="local.callout.attrib">
+    <empty/>
+  </define>
+  <define name="callout.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A &ldquo;called out&rdquo; description of a marked Area. -->
+  <define name="callout">
+    <element name="callout">
+      <ref name="callout.attlist"/>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of callout.element -->
+  <!--
+    AreaRefs: IDs of one or more Areas or AreaSets described
+    by this Callout
+  -->
+  <define name="callout.attlist" combine="interleave">
+    <attribute name="arearefs">
+      <data type="IDREFS"/>
+    </attribute>
+    <ref name="common.attrib"/>
+    <ref name="callout.role.attrib"/>
+    <ref name="local.callout.attrib"/>
+  </define>
+  <!-- end of callout.attlist -->
+  <!-- end of callout.module -->
+  <!-- end of calloutlist.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Objects .............................................................. -->
+  <!-- Examples etc. .................... -->
+  <define name="local.example.attrib">
+    <empty/>
+  </define>
+  <define name="example.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A formal example, with a title. -->
+  <define name="example">
+    <element name="example">
+      <ref name="example.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <ref name="formalobject.title.content"/>
+      <oneOrMore>
+        <ref name="example.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of example.element -->
+  <define name="example.attlist" combine="interleave">
+    <optional>
+      <attribute name="floatstyle"/>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="width.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="example.role.attrib"/>
+    <ref name="local.example.attrib"/>
+  </define>
+  <!-- end of example.attlist -->
+  <!-- end of example.module -->
+  <define name="local.informalexample.attrib">
+    <empty/>
+  </define>
+  <define name="informalexample.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A displayed example without a title. -->
+  <define name="informalexample">
+    <element name="informalexample">
+      <ref name="informalexample.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <oneOrMore>
+        <ref name="example.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of informalexample.element -->
+  <define name="informalexample.attlist" combine="interleave">
+    <optional>
+      <attribute name="floatstyle"/>
+    </optional>
+    <ref name="width.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="informalexample.role.attrib"/>
+    <ref name="local.informalexample.attrib"/>
+  </define>
+  <!-- end of informalexample.attlist -->
+  <!-- end of informalexample.module -->
+  <define name="local.programlistingco.attrib">
+    <empty/>
+  </define>
+  <define name="programlistingco.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A program listing with associated areas used in callouts. -->
+  <define name="programlistingco">
+    <element name="programlistingco">
+      <ref name="programlistingco.attlist"/>
+      <ref name="areaspec"/>
+      <ref name="programlisting"/>
+      <zeroOrMore>
+        <ref name="calloutlist"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of programlistingco.element -->
+  <define name="programlistingco.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="programlistingco.role.attrib"/>
+    <ref name="local.programlistingco.attrib"/>
+  </define>
+  <!-- end of programlistingco.attlist -->
+  <!--  CalloutList (defined above in Lists) -->
+  <!-- end of informalexample.module -->
+  <define name="local.areaspec.attrib">
+    <empty/>
+  </define>
+  <define name="areaspec.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A collection of regions in a graphic or code example. -->
+  <define name="areaspec">
+    <element name="areaspec">
+      <ref name="areaspec.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="area"/>
+          <ref name="areaset"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of areaspec.element -->
+  <!--
+    Units: global unit of measure in which coordinates in
+    this spec are expressed:
+    
+    - CALSPair "x1,y1 x2,y2": lower-left and upper-right
+    coordinates in a rectangle describing repro area in which
+    graphic is placed, where X and Y dimensions are each some
+    number 0..10000 (taken from CALS graphic attributes)
+    
+    - LineColumn "line column": line number and column number
+    at which to start callout text in "linespecific" content
+    
+    - LineRange "startline endline": whole lines from startline
+    to endline in "linespecific" content
+    
+    - LineColumnPair "line1 col1 line2 col2": starting and ending
+    points of area in "linespecific" content that starts at
+    first position and ends at second position (including the
+    beginnings of any intervening lines)
+    
+    - Other: directive to look at value of OtherUnits attribute
+    to get implementation-specific keyword
+    
+    The default is implementation-specific; usually dependent on
+    the parent element (GraphicCO gets CALSPair, ProgramListingCO
+    and ScreenCO get LineColumn)
+  -->
+  <!-- OtherUnits: User-defined units -->
+  <define name="areaspec.attlist" combine="interleave">
+    <optional>
+      <attribute name="units">
+        <choice>
+          <value>calspair</value>
+          <value>linecolumn</value>
+          <value>linerange</value>
+          <value>linecolumnpair</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otherunits">
+        <data type="NMTOKEN"/>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="areaspec.role.attrib"/>
+    <ref name="local.areaspec.attrib"/>
+  </define>
+  <!-- end of areaspec.attlist -->
+  <!-- end of areaspec.module -->
+  <define name="local.area.attrib">
+    <empty/>
+  </define>
+  <define name="area.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A region defined for a Callout in a graphic or code example. -->
+  <define name="area">
+    <element name="area">
+      <ref name="area.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of area.element -->
+  <!-- bug number/symbol override or initialization -->
+  <!-- to any related information -->
+  <!--
+    Units: unit of measure in which coordinates in this
+    area are expressed; inherits from AreaSet and AreaSpec
+  -->
+  <!-- OtherUnits: User-defined units -->
+  <define name="area.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="linkends.attrib"/>
+    <optional>
+      <attribute name="units">
+        <choice>
+          <value>calspair</value>
+          <value>linecolumn</value>
+          <value>linerange</value>
+          <value>linecolumnpair</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otherunits">
+        <data type="NMTOKEN"/>
+      </attribute>
+    </optional>
+    <attribute name="coords"/>
+    <ref name="idreq.common.attrib"/>
+    <ref name="area.role.attrib"/>
+    <ref name="local.area.attrib"/>
+  </define>
+  <!-- end of area.attlist -->
+  <!-- end of area.module -->
+  <define name="local.areaset.attrib">
+    <empty/>
+  </define>
+  <define name="areaset.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A set of related areas in a graphic or code example. -->
+  <define name="areaset">
+    <element name="areaset">
+      <ref name="areaset.attlist"/>
+      <oneOrMore>
+        <ref name="area"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of areaset.element -->
+  <!-- bug number/symbol override or initialization -->
+  <!--
+    Units: unit of measure in which coordinates in this
+    area are expressed; inherits from AreaSpec
+  -->
+  <define name="areaset.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <optional>
+      <attribute name="units">
+        <choice>
+          <value>calspair</value>
+          <value>linecolumn</value>
+          <value>linerange</value>
+          <value>linecolumnpair</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otherunits">
+        <data type="NMTOKEN"/>
+      </attribute>
+    </optional>
+    <attribute name="coords"/>
+    <ref name="idreq.common.attrib"/>
+    <ref name="areaset.role.attrib"/>
+    <ref name="local.areaset.attrib"/>
+  </define>
+  <!-- end of areaset.attlist -->
+  <!-- end of areaset.module -->
+  <!-- end of areaspec.content.module -->
+  <define name="local.programlisting.attrib">
+    <empty/>
+  </define>
+  <define name="programlisting.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A literal listing of all or part of a program. -->
+  <define name="programlisting">
+    <element name="programlisting">
+      <ref name="programlisting.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="para.char.mix"/>
+          <ref name="co"/>
+          <ref name="coref"/>
+          <ref name="lineannotation"/>
+          <ref name="textobject"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of programlisting.element -->
+  <define name="programlisting.attlist" combine="interleave">
+    <ref name="width.attrib"/>
+    <ref name="linespecific.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="programlisting.role.attrib"/>
+    <ref name="local.programlisting.attrib"/>
+  </define>
+  <!-- end of programlisting.attlist -->
+  <!-- end of programlisting.module -->
+  <define name="local.literallayout.attrib">
+    <empty/>
+  </define>
+  <define name="literallayout.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A block of text in which line breaks and white space are to be reproduced faithfully. -->
+  <define name="literallayout">
+    <element name="literallayout">
+      <ref name="literallayout.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="para.char.mix"/>
+          <ref name="co"/>
+          <ref name="coref"/>
+          <ref name="textobject"/>
+          <ref name="lineannotation"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of literallayout.element -->
+  <define name="literallayout.attlist" combine="interleave">
+    <ref name="width.attrib"/>
+    <ref name="linespecific.attrib"/>
+    <optional>
+      <attribute name="class" a:defaultValue="normal">
+        <choice>
+          <value>monospaced</value>
+          <value>normal</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="literallayout.role.attrib"/>
+    <ref name="local.literallayout.attrib"/>
+  </define>
+  <!-- end of literallayout.attlist -->
+  <!--  LineAnnotation (defined in the Inlines section, below) -->
+  <!-- end of literallayout.module -->
+  <define name="local.screenco.attrib">
+    <empty/>
+  </define>
+  <define name="screenco.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A screen with associated areas used in callouts. -->
+  <define name="screenco">
+    <element name="screenco">
+      <ref name="screenco.attlist"/>
+      <ref name="areaspec"/>
+      <ref name="screen"/>
+      <zeroOrMore>
+        <ref name="calloutlist"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of screenco.element -->
+  <define name="screenco.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="screenco.role.attrib"/>
+    <ref name="local.screenco.attrib"/>
+  </define>
+  <!-- end of screenco.attlist -->
+  <!--  AreaSpec (defined above) -->
+  <!--  CalloutList (defined above in Lists) -->
+  <!-- end of screenco.module -->
+  <define name="local.screen.attrib">
+    <empty/>
+  </define>
+  <define name="screen.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Text that a user sees or might see on a computer screen. -->
+  <define name="screen">
+    <element name="screen">
+      <ref name="screen.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="para.char.mix"/>
+          <ref name="co"/>
+          <ref name="coref"/>
+          <ref name="textobject"/>
+          <ref name="lineannotation"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of screen.element -->
+  <define name="screen.attlist" combine="interleave">
+    <ref name="width.attrib"/>
+    <ref name="linespecific.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="screen.role.attrib"/>
+    <ref name="local.screen.attrib"/>
+  </define>
+  <!-- end of screen.attlist -->
+  <!-- end of screen.module -->
+  <define name="local.screenshot.attrib">
+    <empty/>
+  </define>
+  <define name="screenshot.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A representation of what the user sees or might see on a computer screen. -->
+  <define name="screenshot">
+    <element name="screenshot">
+      <ref name="screenshot.attlist"/>
+      <optional>
+        <ref name="screeninfo"/>
+      </optional>
+      <choice>
+        <ref name="graphic"/>
+        <ref name="graphicco"/>
+        <ref name="mediaobject"/>
+        <ref name="mediaobjectco"/>
+      </choice>
+    </element>
+  </define>
+  <!-- end of screenshot.element -->
+  <define name="screenshot.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="screenshot.role.attrib"/>
+    <ref name="local.screenshot.attrib"/>
+  </define>
+  <!-- end of screenshot.attlist -->
+  <!-- end of screenshot.module -->
+  <define name="local.screeninfo.attrib">
+    <empty/>
+  </define>
+  <define name="screeninfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Information about how a screen shot was produced. -->
+  <define name="screeninfo">
+    <element name="screeninfo">
+      <ref name="screeninfo.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of screeninfo.element -->
+  <define name="screeninfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="screeninfo.role.attrib"/>
+    <ref name="local.screeninfo.attrib"/>
+  </define>
+  <!-- end of screeninfo.attlist -->
+  <!-- end of screeninfo.module -->
+  <!-- end of screenshot.content.module -->
+  <!-- Figures etc. ..................... -->
+  <define name="local.figure.attrib">
+    <empty/>
+  </define>
+  <define name="figure.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A formal figure, generally an illustration, with a title. -->
+  <define name="figure">
+    <element name="figure">
+      <ref name="figure.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <ref name="formalobject.title.content"/>
+      <oneOrMore>
+        <choice>
+          <ref name="figure.mix"/>
+          <ref name="link.char.class"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of figure.element -->
+  <!--
+    Float: Whether the Figure is supposed to be rendered
+    where convenient (yes (1) value) or at the place it occurs
+    in the text (no (0) value, the default)
+  -->
+  <define name="figure.attlist" combine="interleave">
+    <optional>
+      <attribute name="float" a:defaultValue="0">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="floatstyle"/>
+    </optional>
+    <optional>
+      <attribute name="pgwide">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="figure.role.attrib"/>
+    <ref name="local.figure.attrib"/>
+  </define>
+  <!-- end of figure.attlist -->
+  <!-- end of figure.module -->
+  <define name="local.informalfigure.attrib">
+    <empty/>
+  </define>
+  <define name="informalfigure.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A untitled figure. -->
+  <define name="informalfigure">
+    <element name="informalfigure">
+      <ref name="informalfigure.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <oneOrMore>
+        <choice>
+          <ref name="figure.mix"/>
+          <ref name="link.char.class"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of informalfigure.element -->
+  <!--
+    Float: Whether the Figure is supposed to be rendered
+    where convenient (yes (1) value) or at the place it occurs
+    in the text (no (0) value, the default)
+  -->
+  <define name="informalfigure.attlist" combine="interleave">
+    <optional>
+      <attribute name="float" a:defaultValue="0">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="floatstyle"/>
+    </optional>
+    <optional>
+      <attribute name="pgwide">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="informalfigure.role.attrib"/>
+    <ref name="local.informalfigure.attrib"/>
+  </define>
+  <!-- end of informalfigure.attlist -->
+  <!-- end of informalfigure.module -->
+  <define name="local.graphicco.attrib">
+    <empty/>
+  </define>
+  <define name="graphicco.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A graphic that contains callout areas. -->
+  <define name="graphicco">
+    <element name="graphicco">
+      <ref name="graphicco.attlist"/>
+      <ref name="areaspec"/>
+      <ref name="graphic"/>
+      <zeroOrMore>
+        <ref name="calloutlist"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of graphicco.element -->
+  <define name="graphicco.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="graphicco.role.attrib"/>
+    <ref name="local.graphicco.attrib"/>
+  </define>
+  <!-- end of graphicco.attlist -->
+  <!--  AreaSpec (defined above in Examples) -->
+  <!--  CalloutList (defined above in Lists) -->
+  <!-- end of graphicco.module -->
+  <!--
+    Graphical data can be the content of Graphic, or you can reference
+    an external file either as an entity (Entitref) or a filename
+    (Fileref).
+  -->
+  <define name="local.graphic.attrib">
+    <empty/>
+  </define>
+  <define name="graphic.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A displayed graphical object (not an inline). -->
+  <define name="graphic">
+    <element name="graphic">
+      <ref name="graphic.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of graphic.element -->
+  <define name="graphic.attlist" combine="interleave">
+    <ref name="graphics.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="graphic.role.attrib"/>
+    <ref name="local.graphic.attrib"/>
+  </define>
+  <!-- end of graphic.attlist -->
+  <!-- end of graphic.module -->
+  <define name="local.inlinegraphic.attrib">
+    <empty/>
+  </define>
+  <define name="inlinegraphic.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An object containing or pointing to graphical data that will be rendered inline. -->
+  <define name="inlinegraphic">
+    <element name="inlinegraphic">
+      <ref name="inlinegraphic.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of inlinegraphic.element -->
+  <define name="inlinegraphic.attlist" combine="interleave">
+    <ref name="graphics.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="inlinegraphic.role.attrib"/>
+    <ref name="local.inlinegraphic.attrib"/>
+  </define>
+  <!-- end of inlinegraphic.attlist -->
+  <!-- end of inlinegraphic.module -->
+  <define name="local.mediaobject.attrib">
+    <empty/>
+  </define>
+  <define name="mediaobject.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A displayed media object (video, audio, image, etc.). -->
+  <define name="mediaobject">
+    <element name="mediaobject">
+      <ref name="mediaobject.attlist"/>
+      <optional>
+        <ref name="objectinfo"/>
+      </optional>
+      <oneOrMore>
+        <ref name="mediaobject.mix"/>
+      </oneOrMore>
+      <optional>
+        <ref name="caption"/>
+      </optional>
+    </element>
+  </define>
+  <!-- end of mediaobject.element -->
+  <define name="mediaobject.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="mediaobject.role.attrib"/>
+    <ref name="local.mediaobject.attrib"/>
+  </define>
+  <!-- end of mediaobject.attlist -->
+  <!-- end of mediaobject.module -->
+  <define name="local.inlinemediaobject.attrib">
+    <empty/>
+  </define>
+  <define name="inlinemediaobject.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An inline media object (video, audio, image, and so on). -->
+  <define name="inlinemediaobject">
+    <element name="inlinemediaobject">
+      <ref name="inlinemediaobject.attlist"/>
+      <optional>
+        <ref name="objectinfo"/>
+      </optional>
+      <oneOrMore>
+        <ref name="mediaobject.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of inlinemediaobject.element -->
+  <define name="inlinemediaobject.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="inlinemediaobject.role.attrib"/>
+    <ref name="local.inlinemediaobject.attrib"/>
+  </define>
+  <!-- end of inlinemediaobject.attlist -->
+  <!-- end of inlinemediaobject.module -->
+  <define name="local.videoobject.attrib">
+    <empty/>
+  </define>
+  <define name="videoobject.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for video data and its associated meta-information. -->
+  <define name="videoobject">
+    <element name="videoobject">
+      <ref name="videoobject.attlist"/>
+      <optional>
+        <ref name="objectinfo"/>
+      </optional>
+      <ref name="videodata"/>
+    </element>
+  </define>
+  <!-- end of videoobject.element -->
+  <define name="videoobject.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="videoobject.role.attrib"/>
+    <ref name="local.videoobject.attrib"/>
+  </define>
+  <!-- end of videoobject.attlist -->
+  <!-- end of videoobject.module -->
+  <define name="local.audioobject.attrib">
+    <empty/>
+  </define>
+  <define name="audioobject.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for audio data and its associated meta-information. -->
+  <define name="audioobject">
+    <element name="audioobject">
+      <ref name="audioobject.attlist"/>
+      <optional>
+        <ref name="objectinfo"/>
+      </optional>
+      <ref name="audiodata"/>
+    </element>
+  </define>
+  <!-- end of audioobject.element -->
+  <define name="audioobject.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="audioobject.role.attrib"/>
+    <ref name="local.audioobject.attrib"/>
+  </define>
+  <!-- end of audioobject.attlist -->
+  <!-- end of audioobject.module -->
+  <define name="local.imageobject.attrib">
+    <empty/>
+  </define>
+  <define name="imageobject.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for image data and its associated meta-information. -->
+  <define name="imageobject">
+    <element name="imageobject">
+      <ref name="imageobject.attlist"/>
+      <optional>
+        <ref name="objectinfo"/>
+      </optional>
+      <ref name="imagedata"/>
+    </element>
+  </define>
+  <!-- end of imageobject.element -->
+  <define name="imageobject.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="imageobject.role.attrib"/>
+    <ref name="local.imageobject.attrib"/>
+  </define>
+  <!-- end of imageobject.attlist -->
+  <!-- end of imageobject.module -->
+  <define name="local.textobject.attrib">
+    <empty/>
+  </define>
+  <define name="textobject.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for a text description of an object and its associated meta-information. -->
+  <define name="textobject">
+    <element name="textobject">
+      <ref name="textobject.attlist"/>
+      <optional>
+        <ref name="objectinfo"/>
+      </optional>
+      <choice>
+        <ref name="phrase"/>
+        <ref name="textdata"/>
+        <oneOrMore>
+          <ref name="textobject.mix"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <!-- end of textobject.element -->
+  <define name="textobject.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="textobject.role.attrib"/>
+    <ref name="local.textobject.attrib"/>
+  </define>
+  <!-- end of textobject.attlist -->
+  <!-- end of textobject.module -->
+  <define name="local.objectinfo.attrib">
+    <empty/>
+  </define>
+  <define name="objectinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Meta-information for an object. -->
+  <define name="objectinfo">
+    <element name="objectinfo">
+      <ref name="objectinfo.attlist"/>
+      <oneOrMore>
+        <ref name="info.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of objectinfo.element -->
+  <define name="objectinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="objectinfo.role.attrib"/>
+    <ref name="local.objectinfo.attrib"/>
+  </define>
+  <!-- end of objectinfo.attlist -->
+  <!-- end of objectinfo.module -->
+  <!--
+    EntityRef: Name of an external entity containing the content
+    of the object data
+  -->
+  <!--
+    FileRef: Filename, qualified by a pathname if desired,
+    designating the file containing the content of the object data
+  -->
+  <!-- Format: Notation of the element content, if any -->
+  <!-- SrcCredit: Information about the source of the image -->
+  <define name="local.objectdata.attrib">
+    <empty/>
+  </define>
+  <define name="objectdata.attrib">
+    <optional>
+      <attribute name="entityref">
+        <data type="ENTITY"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="fileref"/>
+    </optional>
+    <optional>
+      <attribute name="format">
+        <choice>
+          <ref name="notation.class"/>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="srccredit"/>
+    </optional>
+    <ref name="local.objectdata.attrib"/>
+  </define>
+  <define name="local.videodata.attrib">
+    <empty/>
+  </define>
+  <define name="videodata.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Pointer to external video data. -->
+  <define name="videodata">
+    <element name="videodata">
+      <ref name="videodata.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of videodata.element -->
+  <!-- Width: Same as CALS reprowid (desired width) -->
+  <!-- Depth: Same as CALS reprodep (desired depth) -->
+  <!--
+    Align: Same as CALS hplace with 'none' removed; #IMPLIED means
+    application-specific
+  -->
+  <!-- Scale: Conflation of CALS hscale and vscale -->
+  <!-- Scalefit: Same as CALS scalefit -->
+  <define name="videodata.attlist" combine="interleave">
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <optional>
+      <attribute name="contentwidth"/>
+    </optional>
+    <optional>
+      <attribute name="depth"/>
+    </optional>
+    <optional>
+      <attribute name="contentdepth"/>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="scale"/>
+    </optional>
+    <optional>
+      <attribute name="scalefit">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <ref name="objectdata.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="videodata.role.attrib"/>
+    <ref name="local.videodata.attrib"/>
+  </define>
+  <!-- end of videodata.attlist -->
+  <!-- end of videodata.module -->
+  <define name="local.audiodata.attrib">
+    <empty/>
+  </define>
+  <define name="audiodata.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Pointer to external audio data. -->
+  <define name="audiodata">
+    <element name="audiodata">
+      <ref name="audiodata.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of audiodata.element -->
+  <define name="audiodata.attlist" combine="interleave">
+    <ref name="objectdata.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="audiodata.role.attrib"/>
+    <ref name="local.audiodata.attrib"/>
+  </define>
+  <!-- end of audiodata.attlist -->
+  <!-- end of audiodata.module -->
+  <define name="local.imagedata.attrib">
+    <empty/>
+  </define>
+  <define name="imagedata.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Pointer to external image data. -->
+  <define name="imagedata">
+    <element name="imagedata">
+      <ref name="imagedata.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of imagedata.element -->
+  <!-- Width: Same as CALS reprowid (desired width) -->
+  <!-- Depth: Same as CALS reprodep (desired depth) -->
+  <!--
+    Align: Same as CALS hplace with 'none' removed; #IMPLIED means
+    application-specific
+  -->
+  <!-- Scale: Conflation of CALS hscale and vscale -->
+  <!-- Scalefit: Same as CALS scalefit -->
+  <define name="imagedata.attlist" combine="interleave">
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <optional>
+      <attribute name="contentwidth"/>
+    </optional>
+    <optional>
+      <attribute name="depth"/>
+    </optional>
+    <optional>
+      <attribute name="contentdepth"/>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>right</value>
+          <value>center</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="scale"/>
+    </optional>
+    <optional>
+      <attribute name="scalefit">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <ref name="objectdata.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="imagedata.role.attrib"/>
+    <ref name="local.imagedata.attrib"/>
+  </define>
+  <!-- end of imagedata.attlist -->
+  <!-- end of imagedata.module -->
+  <define name="local.textdata.attrib">
+    <empty/>
+  </define>
+  <define name="textdata.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Pointer to external text data. -->
+  <define name="textdata">
+    <element name="textdata">
+      <ref name="textdata.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of textdata.element -->
+  <define name="textdata.attlist" combine="interleave">
+    <optional>
+      <attribute name="encoding"/>
+    </optional>
+    <ref name="objectdata.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="textdata.role.attrib"/>
+    <ref name="local.textdata.attrib"/>
+  </define>
+  <!-- end of textdata.attlist -->
+  <!-- end of textdata.module -->
+  <define name="local.mediaobjectco.attrib">
+    <empty/>
+  </define>
+  <define name="mediaobjectco.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A media object that contains callouts. -->
+  <define name="mediaobjectco">
+    <element name="mediaobjectco">
+      <ref name="mediaobjectco.attlist"/>
+      <optional>
+        <ref name="objectinfo"/>
+      </optional>
+      <ref name="imageobjectco"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="imageobjectco"/>
+          <ref name="textobject"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of mediaobjectco.element -->
+  <define name="mediaobjectco.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="mediaobjectco.role.attrib"/>
+    <ref name="local.mediaobjectco.attrib"/>
+  </define>
+  <!-- end of mediaobjectco.attlist -->
+  <!-- end of mediaobjectco.module -->
+  <define name="local.imageobjectco.attrib">
+    <empty/>
+  </define>
+  <define name="imageobjectco.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for an image object with callouts. -->
+  <define name="imageobjectco">
+    <element name="imageobjectco">
+      <ref name="imageobjectco.attlist"/>
+      <ref name="areaspec"/>
+      <ref name="imageobject"/>
+      <zeroOrMore>
+        <ref name="calloutlist"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of imageobjectco.element -->
+  <define name="imageobjectco.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="imageobjectco.role.attrib"/>
+    <ref name="local.imageobjectco.attrib"/>
+  </define>
+  <!-- end of imageobjectco.attlist -->
+  <!-- end of imageobjectco.module -->
+  <!-- end of mediaobject.content.module -->
+  <!-- Equations ........................ -->
+  <!-- This PE provides a mechanism for replacing equation content, -->
+  <!-- perhaps adding a new or different model (e.g., MathML) -->
+  <define name="equation.content">
+    <optional>
+      <ref name="alt"/>
+    </optional>
+    <choice>
+      <oneOrMore>
+        <ref name="graphic"/>
+      </oneOrMore>
+      <oneOrMore>
+        <ref name="mediaobject"/>
+      </oneOrMore>
+      <oneOrMore>
+        <ref name="mathphrase"/>
+      </oneOrMore>
+    </choice>
+  </define>
+  <define name="inlineequation.content">
+    <optional>
+      <ref name="alt"/>
+    </optional>
+    <choice>
+      <oneOrMore>
+        <ref name="graphic"/>
+      </oneOrMore>
+      <oneOrMore>
+        <ref name="inlinemediaobject"/>
+      </oneOrMore>
+      <oneOrMore>
+        <ref name="mathphrase"/>
+      </oneOrMore>
+    </choice>
+  </define>
+  <define name="local.equation.attrib">
+    <empty/>
+  </define>
+  <define name="equation.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A displayed mathematical equation. -->
+  <define name="equation">
+    <element name="equation">
+      <ref name="equation.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="formalobject.title.content"/>
+      </optional>
+      <choice>
+        <ref name="informalequation"/>
+        <ref name="equation.content"/>
+      </choice>
+    </element>
+  </define>
+  <!-- end of equation.element -->
+  <define name="equation.attlist" combine="interleave">
+    <optional>
+      <attribute name="floatstyle"/>
+    </optional>
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="equation.role.attrib"/>
+    <ref name="local.equation.attrib"/>
+  </define>
+  <!-- end of equation.attlist -->
+  <!-- end of equation.module -->
+  <define name="local.informalequation.attrib">
+    <empty/>
+  </define>
+  <define name="informalequation.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A displayed mathematical equation without a title. -->
+  <define name="informalequation">
+    <element name="informalequation">
+      <ref name="informalequation.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <ref name="equation.content"/>
+    </element>
+  </define>
+  <!-- end of informalequation.element -->
+  <define name="informalequation.attlist" combine="interleave">
+    <optional>
+      <attribute name="floatstyle"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="informalequation.role.attrib"/>
+    <ref name="local.informalequation.attrib"/>
+  </define>
+  <!-- end of informalequation.attlist -->
+  <!-- end of informalequation.module -->
+  <define name="local.inlineequation.attrib">
+    <empty/>
+  </define>
+  <define name="inlineequation.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A mathematical equation or expression occurring inline. -->
+  <define name="inlineequation">
+    <element name="inlineequation">
+      <ref name="inlineequation.attlist"/>
+      <ref name="inlineequation.content"/>
+    </element>
+  </define>
+  <!-- end of inlineequation.element -->
+  <define name="inlineequation.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="inlineequation.role.attrib"/>
+    <ref name="local.inlineequation.attrib"/>
+  </define>
+  <!-- end of inlineequation.attlist -->
+  <!-- end of inlineequation.module -->
+  <define name="local.alt.attrib">
+    <empty/>
+  </define>
+  <define name="alt.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Text representation for a graphical element. -->
+  <define name="alt">
+    <element name="alt">
+      <ref name="alt.attlist"/>
+      <text/>
+    </element>
+  </define>
+  <!-- end of alt.element -->
+  <define name="alt.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="alt.role.attrib"/>
+    <ref name="local.alt.attrib"/>
+  </define>
+  <!-- end of alt.attlist -->
+  <!-- end of alt.module -->
+  <define name="local.mathphrase.attrib">
+    <empty/>
+  </define>
+  <define name="mathphrase.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A mathematical phrase, an expression that can be represented with ordinary text and a small amount of markup. -->
+  <define name="mathphrase">
+    <element name="mathphrase">
+      <ref name="mathphrase.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="subscript"/>
+          <ref name="superscript"/>
+          <ref name="emphasis"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of mathphrase.element -->
+  <define name="mathphrase.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="mathphrase.role.attrib"/>
+    <ref name="local.mathphrase.attrib"/>
+  </define>
+  <!-- end of mathphrase.attlist -->
+  <!-- end of mathphrase.module -->
+  <!-- Tables ........................... -->
+  <!-- Choose a table model. CALS or OASIS XML Exchange -->
+  <!-- Do we allow the HTML table model as well? -->
+  <!-- ====================================================== -->
+  <!--
+    xhtmltbl.mod defines HTML tables and sets parameter
+    entities so that, when the CALS table module is read,
+    we end up allowing any table to be CALS or HTML.
+    i.e. This include must come first!
+  -->
+  <!-- ====================================================== -->
+  <include href="htmltblx.rng"/>
+  <!-- end of allow.html.tables -->
+  <!-- Add label and role attributes to table and informaltable -->
+  <!--
+    Add common attributes to Table, TGroup, TBody, THead, TFoot, Row,
+    EntryTbl, and Entry (and InformalTable element).
+  -->
+  <!-- Content model for Table. -->
+  <!-- Allow either objects or inlines; beware of REs between elements. -->
+  <!-- Reference CALS Table Model -->
+  <include href="calstblx.rng"/>
+  <!-- end of table.module -->
+  <!--
+    Note that InformalTable is dependent on some of the entity
+    declarations that customize Table.
+  -->
+  <define name="local.informaltable.attrib">
+    <empty/>
+  </define>
+  <!-- the following entity may have been declared by the XHTML table module -->
+  <!-- doc:A table without a title. -->
+  <define name="informaltable">
+    <element name="informaltable">
+      <ref name="informaltable.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <ref name="informal.tbl.table.mdl"/>
+    </element>
+  </define>
+  <!-- end of informaltable.element -->
+  <!--
+    Frame, Colsep, and Rowsep must be repeated because
+    they are not in entities in the table module.
+  -->
+  <!--
+    includes TabStyle, ToCentry, ShortEntry,
+    Orient, PgWide
+  -->
+  <!-- includes Label -->
+  <!-- includes common attributes -->
+  <define name="informaltable.attlist" combine="interleave">
+    <optional>
+      <attribute name="frame">
+        <choice>
+          <ref name="tbl.frame.attval"/>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="colsep">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowsep">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <ref name="common.table.attribs"/>
+    <ref name="tbl.table.att"/>
+    <ref name="local.informaltable.attrib"/>
+  </define>
+  <!-- end of informaltable.attlist -->
+  <!-- end of informaltable.module -->
+  <define name="local.caption.attrib">
+    <empty/>
+  </define>
+  <define name="caption.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A caption. -->
+  <define name="caption">
+    <element name="caption">
+      <ref name="caption.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="textobject.mix"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of caption.element -->
+  <!-- attrs comes from HTML tables ... -->
+  <!-- common.attrib, but without ID because ID is in attrs -->
+  <define name="caption.attlist.content">
+    <ref name="caption.role.attrib"/>
+    <ref name="attrs"/>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>top</value>
+          <value>bottom</value>
+          <value>left</value>
+          <value>right</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="local.caption.attrib"/>
+  </define>
+  <define name="caption.attlist" combine="interleave">
+    <ref name="caption.attlist.content"/>
+  </define>
+  <!-- end of caption.attlist -->
+  <!-- end of caption.module -->
+  <!-- ...................................................................... -->
+  <!-- Synopses ............................................................. -->
+  <!-- Synopsis ......................... -->
+  <define name="local.synopsis.attrib">
+    <empty/>
+  </define>
+  <define name="synopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A general-purpose element for representing the syntax of commands or functions. -->
+  <define name="synopsis">
+    <element name="synopsis">
+      <ref name="synopsis.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="para.char.mix"/>
+          <ref name="graphic"/>
+          <ref name="mediaobject"/>
+          <ref name="co"/>
+          <ref name="coref"/>
+          <ref name="textobject"/>
+          <ref name="lineannotation"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of synopsis.element -->
+  <define name="synopsis.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="linespecific.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="synopsis.role.attrib"/>
+    <ref name="local.synopsis.attrib"/>
+  </define>
+  <!-- end of synopsis.attlist -->
+  <!--  LineAnnotation (defined in the Inlines section, below) -->
+  <!-- end of synopsis.module -->
+  <!-- CmdSynopsis ...................... -->
+  <define name="local.cmdsynopsis.attrib">
+    <empty/>
+  </define>
+  <define name="cmdsynopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A syntax summary for a software command. -->
+  <define name="cmdsynopsis">
+    <element name="cmdsynopsis">
+      <ref name="cmdsynopsis.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="command"/>
+          <ref name="arg"/>
+          <ref name="group"/>
+          <ref name="sbr"/>
+        </choice>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="synopfragment"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of cmdsynopsis.element -->
+  <!--
+    Sepchar: Character that should separate command and all
+    top-level arguments; alternate value might be e.g., &Delta;
+  -->
+  <define name="cmdsynopsis.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <optional>
+      <attribute name="sepchar" a:defaultValue=" "/>
+    </optional>
+    <optional>
+      <attribute name="cmdlength"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="cmdsynopsis.role.attrib"/>
+    <ref name="local.cmdsynopsis.attrib"/>
+  </define>
+  <!-- end of cmdsynopsis.attlist -->
+  <!-- end of cmdsynopsis.module -->
+  <define name="local.arg.attrib">
+    <empty/>
+  </define>
+  <define name="arg.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An argument in a CmdSynopsis. -->
+  <define name="arg">
+    <element name="arg">
+      <ref name="arg.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="arg"/>
+          <ref name="group"/>
+          <ref name="option"/>
+          <ref name="synopfragmentref"/>
+          <ref name="replaceable"/>
+          <ref name="sbr"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of arg.element -->
+  <!--
+    Choice: Whether Arg must be supplied: Opt (optional to
+    supply, e.g. [arg]; the default), Req (required to supply,
+    e.g. {arg}), or Plain (required to supply, e.g. arg)
+  -->
+  <!--
+    Rep: whether Arg is repeatable: Norepeat (e.g. arg without
+    ellipsis; the default), or Repeat (e.g. arg...)
+  -->
+  <define name="arg.attlist" combine="interleave">
+    <optional>
+      <attribute name="choice" a:defaultValue="opt">
+        <choice>
+          <value>opt</value>
+          <value>req</value>
+          <value>plain</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rep" a:defaultValue="norepeat">
+        <choice>
+          <value>norepeat</value>
+          <value>repeat</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="arg.role.attrib"/>
+    <ref name="local.arg.attrib"/>
+  </define>
+  <!-- end of arg.attlist -->
+  <!-- end of arg.module -->
+  <define name="local.group.attrib">
+    <empty/>
+  </define>
+  <define name="group.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A group of elements in a CmdSynopsis. -->
+  <define name="group">
+    <element name="group">
+      <ref name="group.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="arg"/>
+          <ref name="group"/>
+          <ref name="option"/>
+          <ref name="synopfragmentref"/>
+          <ref name="replaceable"/>
+          <ref name="sbr"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of group.element -->
+  <!--
+    Choice: Whether Group must be supplied: Opt (optional to
+    supply, e.g.  [g1|g2|g3]; the default), Req (required to
+    supply, e.g.  {g1|g2|g3}), Plain (required to supply,
+    e.g.  g1|g2|g3), OptMult (can supply zero or more, e.g.
+    [[g1|g2|g3]]), or ReqMult (must supply one or more, e.g.
+    {{g1|g2|g3}})
+  -->
+  <!--
+    Rep: whether Group is repeatable: Norepeat (e.g. group
+    without ellipsis; the default), or Repeat (e.g. group...)
+  -->
+  <define name="group.attlist" combine="interleave">
+    <optional>
+      <attribute name="choice" a:defaultValue="opt">
+        <choice>
+          <value>opt</value>
+          <value>req</value>
+          <value>plain</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rep" a:defaultValue="norepeat">
+        <choice>
+          <value>norepeat</value>
+          <value>repeat</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="group.role.attrib"/>
+    <ref name="local.group.attrib"/>
+  </define>
+  <!-- end of group.attlist -->
+  <!-- end of group.module -->
+  <define name="local.sbr.attrib">
+    <empty/>
+  </define>
+  <!-- Synopsis break -->
+  <define name="sbr.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An explicit line break in a command synopsis. -->
+  <define name="sbr">
+    <element name="sbr">
+      <ref name="sbr.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of sbr.element -->
+  <define name="sbr.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="sbr.role.attrib"/>
+    <ref name="local.sbr.attrib"/>
+  </define>
+  <!-- end of sbr.attlist -->
+  <!-- end of sbr.module -->
+  <define name="local.synopfragmentref.attrib">
+    <empty/>
+  </define>
+  <define name="synopfragmentref.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A reference to a fragment of a command synopsis. -->
+  <define name="synopfragmentref">
+    <element name="synopfragmentref">
+      <ref name="synopfragmentref.attlist"/>
+      <text/>
+    </element>
+  </define>
+  <!-- end of synopfragmentref.element -->
+  <!--
+    to SynopFragment of complex synopsis
+    material for separate referencing
+  -->
+  <define name="synopfragmentref.attlist" combine="interleave">
+    <ref name="linkendreq.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="synopfragmentref.role.attrib"/>
+    <ref name="local.synopfragmentref.attrib"/>
+  </define>
+  <!-- end of synopfragmentref.attlist -->
+  <!-- end of synopfragmentref.module -->
+  <define name="local.synopfragment.attrib">
+    <empty/>
+  </define>
+  <define name="synopfragment.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A portion of a CmdSynopsis broken out from the main body of the synopsis. -->
+  <define name="synopfragment">
+    <element name="synopfragment">
+      <ref name="synopfragment.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="arg"/>
+          <ref name="group"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of synopfragment.element -->
+  <define name="synopfragment.attlist" combine="interleave">
+    <ref name="idreq.common.attrib"/>
+    <ref name="synopfragment.role.attrib"/>
+    <ref name="local.synopfragment.attrib"/>
+  </define>
+  <!-- end of synopfragment.attlist -->
+  <!-- end of synopfragment.module -->
+  <!--  Command (defined in the Inlines section, below) -->
+  <!--  Option (defined in the Inlines section, below) -->
+  <!--  Replaceable (defined in the Inlines section, below) -->
+  <!-- end of cmdsynopsis.content.module -->
+  <!-- FuncSynopsis ..................... -->
+  <define name="local.funcsynopsis.attrib">
+    <empty/>
+  </define>
+  <define name="funcsynopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The syntax summary for a function definition. -->
+  <define name="funcsynopsis">
+    <element name="funcsynopsis">
+      <ref name="funcsynopsis.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="funcsynopsisinfo"/>
+          <ref name="funcprototype"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of funcsynopsis.element -->
+  <define name="funcsynopsis.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="funcsynopsis.role.attrib"/>
+    <ref name="local.funcsynopsis.attrib"/>
+  </define>
+  <!-- end of funcsynopsis.attlist -->
+  <!-- end of funcsynopsis.module -->
+  <define name="local.funcsynopsisinfo.attrib">
+    <empty/>
+  </define>
+  <define name="funcsynopsisinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Information supplementing the FuncDefs of a FuncSynopsis. -->
+  <define name="funcsynopsisinfo">
+    <element name="funcsynopsisinfo">
+      <ref name="funcsynopsisinfo.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="cptr.char.mix"/>
+          <ref name="textobject"/>
+          <ref name="lineannotation"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of funcsynopsisinfo.element -->
+  <define name="funcsynopsisinfo.attlist" combine="interleave">
+    <ref name="linespecific.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="funcsynopsisinfo.role.attrib"/>
+    <ref name="local.funcsynopsisinfo.attrib"/>
+  </define>
+  <!-- end of funcsynopsisinfo.attlist -->
+  <!-- end of funcsynopsisinfo.module -->
+  <define name="local.funcprototype.attrib">
+    <empty/>
+  </define>
+  <define name="funcprototype.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The prototype of a function. -->
+  <define name="funcprototype">
+    <element name="funcprototype">
+      <ref name="funcprototype.attlist"/>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+      <ref name="funcdef"/>
+      <choice>
+        <ref name="void"/>
+        <ref name="varargs"/>
+        <group>
+          <oneOrMore>
+            <ref name="paramdef"/>
+          </oneOrMore>
+          <optional>
+            <ref name="varargs"/>
+          </optional>
+        </group>
+      </choice>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of funcprototype.element -->
+  <define name="funcprototype.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="funcprototype.role.attrib"/>
+    <ref name="local.funcprototype.attrib"/>
+  </define>
+  <!-- end of funcprototype.attlist -->
+  <!-- end of funcprototype.module -->
+  <define name="local.funcdef.attrib">
+    <empty/>
+  </define>
+  <define name="funcdef.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A function (subroutine) name and its return type. -->
+  <define name="funcdef">
+    <element name="funcdef">
+      <ref name="funcdef.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="type"/>
+          <ref name="replaceable"/>
+          <ref name="function"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of funcdef.element -->
+  <define name="funcdef.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="funcdef.role.attrib"/>
+    <ref name="local.funcdef.attrib"/>
+  </define>
+  <!-- end of funcdef.attlist -->
+  <!-- end of funcdef.module -->
+  <define name="local.void.attrib">
+    <empty/>
+  </define>
+  <define name="void.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An empty element in a function synopsis indicating that the function in question takes no arguments. -->
+  <define name="void">
+    <element name="void">
+      <ref name="void.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of void.element -->
+  <define name="void.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="void.role.attrib"/>
+    <ref name="local.void.attrib"/>
+  </define>
+  <!-- end of void.attlist -->
+  <!-- end of void.module -->
+  <define name="local.varargs.attrib">
+    <empty/>
+  </define>
+  <define name="varargs.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An empty element in a function synopsis indicating a variable number of arguments. -->
+  <define name="varargs">
+    <element name="varargs">
+      <ref name="varargs.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of varargs.element -->
+  <define name="varargs.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="varargs.role.attrib"/>
+    <ref name="local.varargs.attrib"/>
+  </define>
+  <!-- end of varargs.attlist -->
+  <!-- end of varargs.module -->
+  <!--
+    Processing assumes that only one Parameter will appear in a
+    ParamDef, and that FuncParams will be used at most once, for
+    providing information on the "inner parameters" for parameters that
+    are pointers to functions.
+  -->
+  <define name="local.paramdef.attrib">
+    <empty/>
+  </define>
+  <define name="paramdef.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Information about a function parameter in a programming language. -->
+  <define name="paramdef">
+    <element name="paramdef">
+      <ref name="paramdef.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="initializer"/>
+          <ref name="type"/>
+          <ref name="replaceable"/>
+          <ref name="parameter"/>
+          <ref name="funcparams"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of paramdef.element -->
+  <define name="paramdef.attlist" combine="interleave">
+    <optional>
+      <attribute name="choice">
+        <choice>
+          <value>opt</value>
+          <value>req</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="paramdef.role.attrib"/>
+    <ref name="local.paramdef.attrib"/>
+  </define>
+  <!-- end of paramdef.attlist -->
+  <!-- end of paramdef.module -->
+  <define name="local.funcparams.attrib">
+    <empty/>
+  </define>
+  <define name="funcparams.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Parameters for a function referenced through a function pointer in a synopsis. -->
+  <define name="funcparams">
+    <element name="funcparams">
+      <ref name="funcparams.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of funcparams.element -->
+  <define name="funcparams.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="funcparams.role.attrib"/>
+    <ref name="local.funcparams.attrib"/>
+  </define>
+  <!-- end of funcparams.attlist -->
+  <!-- end of funcparams.module -->
+  <!--  LineAnnotation (defined in the Inlines section, below) -->
+  <!--  Replaceable (defined in the Inlines section, below) -->
+  <!--  Function (defined in the Inlines section, below) -->
+  <!--  Parameter (defined in the Inlines section, below) -->
+  <!-- end of funcsynopsis.content.module -->
+  <!-- ClassSynopsis ..................... -->
+  <define name="local.classsynopsis.attrib">
+    <empty/>
+  </define>
+  <define name="classsynopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The syntax summary for a class definition. -->
+  <define name="classsynopsis">
+    <element name="classsynopsis">
+      <ref name="classsynopsis.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="ooclass"/>
+          <ref name="oointerface"/>
+          <ref name="ooexception"/>
+        </choice>
+      </oneOrMore>
+      <zeroOrMore>
+        <choice>
+          <ref name="classsynopsisinfo"/>
+          <ref name="fieldsynopsis"/>
+          <ref name="method.synop.class"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of classsynopsis.element -->
+  <define name="classsynopsis.attlist" combine="interleave">
+    <optional>
+      <attribute name="language"/>
+    </optional>
+    <optional>
+      <attribute name="class" a:defaultValue="class">
+        <choice>
+          <value>class</value>
+          <value>interface</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="classsynopsis.role.attrib"/>
+    <ref name="local.classsynopsis.attrib"/>
+  </define>
+  <!-- end of classsynopsis.attlist -->
+  <!-- end of classsynopsis.module -->
+  <define name="local.classsynopsisinfo.attrib">
+    <empty/>
+  </define>
+  <define name="classsynopsisinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Information supplementing the contents of a ClassSynopsis. -->
+  <define name="classsynopsisinfo">
+    <element name="classsynopsisinfo">
+      <ref name="classsynopsisinfo.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="cptr.char.mix"/>
+          <ref name="textobject"/>
+          <ref name="lineannotation"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of classsynopsisinfo.element -->
+  <define name="classsynopsisinfo.attlist" combine="interleave">
+    <ref name="linespecific.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="classsynopsisinfo.role.attrib"/>
+    <ref name="local.classsynopsisinfo.attrib"/>
+  </define>
+  <!-- end of classsynopsisinfo.attlist -->
+  <!-- end of classsynopsisinfo.module -->
+  <define name="local.ooclass.attrib">
+    <empty/>
+  </define>
+  <define name="ooclass.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A class in an object-oriented programming language. -->
+  <define name="ooclass">
+    <element name="ooclass">
+      <ref name="ooclass.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="modifier"/>
+          <ref name="package"/>
+        </choice>
+      </zeroOrMore>
+      <ref name="classname"/>
+    </element>
+  </define>
+  <!-- end of ooclass.element -->
+  <define name="ooclass.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="ooclass.role.attrib"/>
+    <ref name="local.ooclass.attrib"/>
+  </define>
+  <!-- end of ooclass.attlist -->
+  <!-- end of ooclass.module -->
+  <define name="local.oointerface.attrib">
+    <empty/>
+  </define>
+  <define name="oointerface.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An interface in an object-oriented programming language. -->
+  <define name="oointerface">
+    <element name="oointerface">
+      <ref name="oointerface.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="modifier"/>
+          <ref name="package"/>
+        </choice>
+      </zeroOrMore>
+      <ref name="interfacename"/>
+    </element>
+  </define>
+  <!-- end of oointerface.element -->
+  <define name="oointerface.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="oointerface.role.attrib"/>
+    <ref name="local.oointerface.attrib"/>
+  </define>
+  <!-- end of oointerface.attlist -->
+  <!-- end of oointerface.module -->
+  <define name="local.ooexception.attrib">
+    <empty/>
+  </define>
+  <define name="ooexception.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An exception in an object-oriented programming language. -->
+  <define name="ooexception">
+    <element name="ooexception">
+      <ref name="ooexception.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="modifier"/>
+          <ref name="package"/>
+        </choice>
+      </zeroOrMore>
+      <ref name="exceptionname"/>
+    </element>
+  </define>
+  <!-- end of ooexception.element -->
+  <define name="ooexception.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="ooexception.role.attrib"/>
+    <ref name="local.ooexception.attrib"/>
+  </define>
+  <!-- end of ooexception.attlist -->
+  <!-- end of ooexception.module -->
+  <define name="local.modifier.attrib">
+    <empty/>
+  </define>
+  <define name="modifier.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Modifiers in a synopsis. -->
+  <define name="modifier">
+    <element name="modifier">
+      <ref name="modifier.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of modifier.element -->
+  <define name="modifier.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="modifier.role.attrib"/>
+    <ref name="local.modifier.attrib"/>
+  </define>
+  <!-- end of modifier.attlist -->
+  <!-- end of modifier.module -->
+  <define name="local.interfacename.attrib">
+    <empty/>
+  </define>
+  <define name="interfacename.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of an interface. -->
+  <define name="interfacename">
+    <element name="interfacename">
+      <ref name="interfacename.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of interfacename.element -->
+  <define name="interfacename.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="interfacename.role.attrib"/>
+    <ref name="local.interfacename.attrib"/>
+  </define>
+  <!-- end of interfacename.attlist -->
+  <!-- end of interfacename.module -->
+  <define name="local.exceptionname.attrib">
+    <empty/>
+  </define>
+  <define name="exceptionname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of an exception. -->
+  <define name="exceptionname">
+    <element name="exceptionname">
+      <ref name="exceptionname.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of exceptionname.element -->
+  <define name="exceptionname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="exceptionname.role.attrib"/>
+    <ref name="local.exceptionname.attrib"/>
+  </define>
+  <!-- end of exceptionname.attlist -->
+  <!-- end of exceptionname.module -->
+  <define name="local.fieldsynopsis.attrib">
+    <empty/>
+  </define>
+  <define name="fieldsynopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a field in a class definition. -->
+  <define name="fieldsynopsis">
+    <element name="fieldsynopsis">
+      <ref name="fieldsynopsis.attlist"/>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="type"/>
+      </optional>
+      <ref name="varname"/>
+      <optional>
+        <ref name="initializer"/>
+      </optional>
+    </element>
+  </define>
+  <!-- end of fieldsynopsis.element -->
+  <define name="fieldsynopsis.attlist" combine="interleave">
+    <optional>
+      <attribute name="language"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="fieldsynopsis.role.attrib"/>
+    <ref name="local.fieldsynopsis.attrib"/>
+  </define>
+  <!-- end of fieldsynopsis.attlist -->
+  <!-- end of fieldsynopsis.module -->
+  <define name="local.initializer.attrib">
+    <empty/>
+  </define>
+  <define name="initializer.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The initializer for a FieldSynopsis. -->
+  <define name="initializer">
+    <element name="initializer">
+      <ref name="initializer.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of initializer.element -->
+  <define name="initializer.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="initializer.role.attrib"/>
+    <ref name="local.initializer.attrib"/>
+  </define>
+  <!-- end of initializer.attlist -->
+  <!-- end of initializer.module -->
+  <define name="local.constructorsynopsis.attrib">
+    <empty/>
+  </define>
+  <define name="constructorsynopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A syntax summary for a constructor. -->
+  <define name="constructorsynopsis">
+    <element name="constructorsynopsis">
+      <ref name="constructorsynopsis.attlist"/>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="methodname"/>
+      </optional>
+      <choice>
+        <oneOrMore>
+          <ref name="methodparam"/>
+        </oneOrMore>
+        <optional>
+          <ref name="void"/>
+        </optional>
+      </choice>
+      <zeroOrMore>
+        <ref name="exceptionname"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of constructorsynopsis.element -->
+  <define name="constructorsynopsis.attlist" combine="interleave">
+    <optional>
+      <attribute name="language"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="constructorsynopsis.role.attrib"/>
+    <ref name="local.constructorsynopsis.attrib"/>
+  </define>
+  <!-- end of constructorsynopsis.attlist -->
+  <!-- end of constructorsynopsis.module -->
+  <define name="local.destructorsynopsis.attrib">
+    <empty/>
+  </define>
+  <define name="destructorsynopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A syntax summary for a destructor. -->
+  <define name="destructorsynopsis">
+    <element name="destructorsynopsis">
+      <ref name="destructorsynopsis.attlist"/>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="methodname"/>
+      </optional>
+      <choice>
+        <oneOrMore>
+          <ref name="methodparam"/>
+        </oneOrMore>
+        <optional>
+          <ref name="void"/>
+        </optional>
+      </choice>
+      <zeroOrMore>
+        <ref name="exceptionname"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of destructorsynopsis.element -->
+  <define name="destructorsynopsis.attlist" combine="interleave">
+    <optional>
+      <attribute name="language"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="destructorsynopsis.role.attrib"/>
+    <ref name="local.destructorsynopsis.attrib"/>
+  </define>
+  <!-- end of destructorsynopsis.attlist -->
+  <!-- end of destructorsynopsis.module -->
+  <define name="local.methodsynopsis.attrib">
+    <empty/>
+  </define>
+  <define name="methodsynopsis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A syntax summary for a method. -->
+  <define name="methodsynopsis">
+    <element name="methodsynopsis">
+      <ref name="methodsynopsis.attlist"/>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+      <optional>
+        <choice>
+          <ref name="type"/>
+          <ref name="void"/>
+        </choice>
+      </optional>
+      <ref name="methodname"/>
+      <choice>
+        <oneOrMore>
+          <ref name="methodparam"/>
+        </oneOrMore>
+        <optional>
+          <ref name="void"/>
+        </optional>
+      </choice>
+      <zeroOrMore>
+        <ref name="exceptionname"/>
+      </zeroOrMore>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of methodsynopsis.element -->
+  <define name="methodsynopsis.attlist" combine="interleave">
+    <optional>
+      <attribute name="language"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="methodsynopsis.role.attrib"/>
+    <ref name="local.methodsynopsis.attrib"/>
+  </define>
+  <!-- end of methodsynopsis.attlist -->
+  <!-- end of methodsynopsis.module -->
+  <define name="local.methodname.attrib">
+    <empty/>
+  </define>
+  <define name="methodname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a method. -->
+  <define name="methodname">
+    <element name="methodname">
+      <ref name="methodname.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of methodname.element -->
+  <define name="methodname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="methodname.role.attrib"/>
+    <ref name="local.methodname.attrib"/>
+  </define>
+  <!-- end of methodname.attlist -->
+  <!-- end of methodname.module -->
+  <define name="local.methodparam.attrib">
+    <empty/>
+  </define>
+  <define name="methodparam.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Parameters to a method. -->
+  <define name="methodparam">
+    <element name="methodparam">
+      <ref name="methodparam.attlist"/>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="type"/>
+      </optional>
+      <choice>
+        <group>
+          <ref name="parameter"/>
+          <optional>
+            <ref name="initializer"/>
+          </optional>
+        </group>
+        <ref name="funcparams"/>
+      </choice>
+      <zeroOrMore>
+        <ref name="modifier"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of methodparam.element -->
+  <define name="methodparam.attlist" combine="interleave">
+    <optional>
+      <attribute name="choice" a:defaultValue="req">
+        <choice>
+          <value>opt</value>
+          <value>req</value>
+          <value>plain</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rep" a:defaultValue="norepeat">
+        <choice>
+          <value>norepeat</value>
+          <value>repeat</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="methodparam.role.attrib"/>
+    <ref name="local.methodparam.attrib"/>
+  </define>
+  <!-- end of methodparam.attlist -->
+  <!-- end of methodparam.module -->
+  <!-- end of classsynopsis.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Document information entities and elements ........................... -->
+  <!--
+    The document information elements include some elements that are
+    currently used only in the document hierarchy module. They are
+    defined here so that they will be available for use in customized
+    document hierarchies.
+  -->
+  <!-- .................................. -->
+  <!-- Ackno ............................ -->
+  <define name="local.ackno.attrib">
+    <empty/>
+  </define>
+  <define name="ackno.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Acknowledgements in an Article. -->
+  <define name="ackno">
+    <element name="ackno">
+      <ref name="ackno.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of ackno.element -->
+  <define name="ackno.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="ackno.role.attrib"/>
+    <ref name="local.ackno.attrib"/>
+  </define>
+  <!-- end of ackno.attlist -->
+  <!-- end of ackno.module -->
+  <!-- Address .......................... -->
+  <define name="local.address.attrib">
+    <empty/>
+  </define>
+  <define name="address.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A real-world address, generally a postal address. -->
+  <define name="address">
+    <element name="address">
+      <ref name="address.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="personname"/>
+          <ref name="person.ident.mix"/>
+          <ref name="street"/>
+          <ref name="pob"/>
+          <ref name="postcode"/>
+          <ref name="city"/>
+          <ref name="state"/>
+          <ref name="country"/>
+          <ref name="phone"/>
+          <ref name="fax"/>
+          <ref name="email"/>
+          <ref name="otheraddr"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of address.element -->
+  <define name="address.attlist" combine="interleave">
+    <ref name="linespecific.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="address.role.attrib"/>
+    <ref name="local.address.attrib"/>
+  </define>
+  <!-- end of address.attlist -->
+  <!-- end of address.module -->
+  <define name="local.street.attrib">
+    <empty/>
+  </define>
+  <define name="street.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A street address in an address. -->
+  <define name="street">
+    <element name="street">
+      <ref name="street.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of street.element -->
+  <define name="street.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="street.role.attrib"/>
+    <ref name="local.street.attrib"/>
+  </define>
+  <!-- end of street.attlist -->
+  <!-- end of street.module -->
+  <define name="local.pob.attrib">
+    <empty/>
+  </define>
+  <define name="pob.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A post office box in an address. -->
+  <define name="pob">
+    <element name="pob">
+      <ref name="pob.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of pob.element -->
+  <define name="pob.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="pob.role.attrib"/>
+    <ref name="local.pob.attrib"/>
+  </define>
+  <!-- end of pob.attlist -->
+  <!-- end of pob.module -->
+  <define name="local.postcode.attrib">
+    <empty/>
+  </define>
+  <define name="postcode.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A postal code in an address. -->
+  <define name="postcode">
+    <element name="postcode">
+      <ref name="postcode.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of postcode.element -->
+  <define name="postcode.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="postcode.role.attrib"/>
+    <ref name="local.postcode.attrib"/>
+  </define>
+  <!-- end of postcode.attlist -->
+  <!-- end of postcode.module -->
+  <define name="local.city.attrib">
+    <empty/>
+  </define>
+  <define name="city.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a city in an address. -->
+  <define name="city">
+    <element name="city">
+      <ref name="city.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of city.element -->
+  <define name="city.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="city.role.attrib"/>
+    <ref name="local.city.attrib"/>
+  </define>
+  <!-- end of city.attlist -->
+  <!-- end of city.module -->
+  <define name="local.state.attrib">
+    <empty/>
+  </define>
+  <define name="state.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A state or province in an address. -->
+  <define name="state">
+    <element name="state">
+      <ref name="state.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of state.element -->
+  <define name="state.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="state.role.attrib"/>
+    <ref name="local.state.attrib"/>
+  </define>
+  <!-- end of state.attlist -->
+  <!-- end of state.module -->
+  <define name="local.country.attrib">
+    <empty/>
+  </define>
+  <define name="country.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a country. -->
+  <define name="country">
+    <element name="country">
+      <ref name="country.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of country.element -->
+  <define name="country.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="country.role.attrib"/>
+    <ref name="local.country.attrib"/>
+  </define>
+  <!-- end of country.attlist -->
+  <!-- end of country.module -->
+  <define name="local.phone.attrib">
+    <empty/>
+  </define>
+  <define name="phone.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A telephone number. -->
+  <define name="phone">
+    <element name="phone">
+      <ref name="phone.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of phone.element -->
+  <define name="phone.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="phone.role.attrib"/>
+    <ref name="local.phone.attrib"/>
+  </define>
+  <!-- end of phone.attlist -->
+  <!-- end of phone.module -->
+  <define name="local.fax.attrib">
+    <empty/>
+  </define>
+  <define name="fax.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A fax number. -->
+  <define name="fax">
+    <element name="fax">
+      <ref name="fax.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of fax.element -->
+  <define name="fax.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="fax.role.attrib"/>
+    <ref name="local.fax.attrib"/>
+  </define>
+  <!-- end of fax.attlist -->
+  <!-- end of fax.module -->
+  <!--  Email (defined in the Inlines section, below) -->
+  <define name="local.otheraddr.attrib">
+    <empty/>
+  </define>
+  <define name="otheraddr.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Uncategorized information in address. -->
+  <define name="otheraddr">
+    <element name="otheraddr">
+      <ref name="otheraddr.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of otheraddr.element -->
+  <define name="otheraddr.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="otheraddr.role.attrib"/>
+    <ref name="local.otheraddr.attrib"/>
+  </define>
+  <!-- end of otheraddr.attlist -->
+  <!-- end of otheraddr.module -->
+  <!-- end of address.content.module -->
+  <!-- Affiliation ...................... -->
+  <define name="local.affiliation.attrib">
+    <empty/>
+  </define>
+  <define name="affiliation.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The institutional affiliation of an individual. -->
+  <define name="affiliation">
+    <element name="affiliation">
+      <ref name="affiliation.attlist"/>
+      <optional>
+        <ref name="shortaffil"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="jobtitle"/>
+      </zeroOrMore>
+      <optional>
+        <ref name="orgname"/>
+      </optional>
+      <zeroOrMore>
+        <ref name="orgdiv"/>
+      </zeroOrMore>
+      <zeroOrMore>
+        <ref name="address"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of affiliation.element -->
+  <define name="affiliation.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="affiliation.role.attrib"/>
+    <ref name="local.affiliation.attrib"/>
+  </define>
+  <!-- end of affiliation.attlist -->
+  <!-- end of affiliation.module -->
+  <define name="local.shortaffil.attrib">
+    <empty/>
+  </define>
+  <define name="shortaffil.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A brief description of an affiliation. -->
+  <define name="shortaffil">
+    <element name="shortaffil">
+      <ref name="shortaffil.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of shortaffil.element -->
+  <define name="shortaffil.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="shortaffil.role.attrib"/>
+    <ref name="local.shortaffil.attrib"/>
+  </define>
+  <!-- end of shortaffil.attlist -->
+  <!-- end of shortaffil.module -->
+  <define name="local.jobtitle.attrib">
+    <empty/>
+  </define>
+  <define name="jobtitle.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The title of an individual in an organization. -->
+  <define name="jobtitle">
+    <element name="jobtitle">
+      <ref name="jobtitle.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of jobtitle.element -->
+  <define name="jobtitle.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="jobtitle.role.attrib"/>
+    <ref name="local.jobtitle.attrib"/>
+  </define>
+  <!-- end of jobtitle.attlist -->
+  <!-- end of jobtitle.module -->
+  <!--  OrgName (defined elsewhere in this section) -->
+  <define name="local.orgdiv.attrib">
+    <empty/>
+  </define>
+  <define name="orgdiv.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A division of an organization. -->
+  <define name="orgdiv">
+    <element name="orgdiv">
+      <ref name="orgdiv.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of orgdiv.element -->
+  <define name="orgdiv.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="orgdiv.role.attrib"/>
+    <ref name="local.orgdiv.attrib"/>
+  </define>
+  <!-- end of orgdiv.attlist -->
+  <!-- end of orgdiv.module -->
+  <!--  Address (defined elsewhere in this section) -->
+  <!-- end of affiliation.content.module -->
+  <!-- ArtPageNums ...................... -->
+  <define name="local.artpagenums.attrib">
+    <empty/>
+  </define>
+  <define name="artpagenums.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The page numbers of an article as published. -->
+  <define name="artpagenums">
+    <element name="artpagenums">
+      <ref name="artpagenums.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of artpagenums.element -->
+  <define name="artpagenums.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="artpagenums.role.attrib"/>
+    <ref name="local.artpagenums.attrib"/>
+  </define>
+  <!-- end of artpagenums.attlist -->
+  <!-- end of artpagenums.module -->
+  <!-- PersonName -->
+  <define name="local.personname.attrib">
+    <empty/>
+  </define>
+  <define name="personname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The personal name of an individual. -->
+  <define name="personname">
+    <element name="personname">
+      <ref name="personname.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="honorific"/>
+          <ref name="firstname"/>
+          <ref name="surname"/>
+          <ref name="lineage"/>
+          <ref name="othername"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of personname.element -->
+  <define name="personname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="personname.role.attrib"/>
+    <ref name="local.personname.attrib"/>
+  </define>
+  <!-- end of personname.attlist -->
+  <!-- end of personname.module -->
+  <!-- Author ........................... -->
+  <define name="local.author.attrib">
+    <empty/>
+  </define>
+  <define name="author.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of an individual author. -->
+  <define name="author">
+    <element name="author">
+      <ref name="author.attlist"/>
+      <choice>
+        <ref name="personname"/>
+        <oneOrMore>
+          <ref name="person.ident.mix"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <choice>
+          <ref name="personblurb"/>
+          <ref name="email"/>
+          <ref name="address"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of author.element -->
+  <define name="author.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="author.role.attrib"/>
+    <ref name="local.author.attrib"/>
+  </define>
+  <!-- end of author.attlist -->
+  <!-- (see "Personal identity elements" for %person.ident.mix;) -->
+  <!-- end of author.module -->
+  <!-- AuthorGroup ...................... -->
+  <define name="local.authorgroup.attrib">
+    <empty/>
+  </define>
+  <define name="authorgroup.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Wrapper for author information when a document has multiple authors or collabarators. -->
+  <define name="authorgroup">
+    <element name="authorgroup">
+      <ref name="authorgroup.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="author"/>
+          <ref name="editor"/>
+          <ref name="collab"/>
+          <ref name="corpauthor"/>
+          <ref name="corpcredit"/>
+          <ref name="othercredit"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of authorgroup.element -->
+  <define name="authorgroup.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="authorgroup.role.attrib"/>
+    <ref name="local.authorgroup.attrib"/>
+  </define>
+  <!-- end of authorgroup.attlist -->
+  <!-- end of authorgroup.module -->
+  <!--  Author (defined elsewhere in this section) -->
+  <!--  Editor (defined elsewhere in this section) -->
+  <define name="local.collab.attrib">
+    <empty/>
+  </define>
+  <define name="collab.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Identifies a collaborator. -->
+  <define name="collab">
+    <element name="collab">
+      <ref name="collab.attlist"/>
+      <ref name="collabname"/>
+      <zeroOrMore>
+        <ref name="affiliation"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of collab.element -->
+  <define name="collab.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="collab.role.attrib"/>
+    <ref name="local.collab.attrib"/>
+  </define>
+  <!-- end of collab.attlist -->
+  <!-- end of collab.module -->
+  <define name="local.collabname.attrib">
+    <empty/>
+  </define>
+  <define name="collabname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a collaborator. -->
+  <define name="collabname">
+    <element name="collabname">
+      <ref name="collabname.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of collabname.element -->
+  <define name="collabname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="collabname.role.attrib"/>
+    <ref name="local.collabname.attrib"/>
+  </define>
+  <!-- end of collabname.attlist -->
+  <!-- end of collabname.module -->
+  <!--  Affiliation (defined elsewhere in this section) -->
+  <!-- end of collab.content.module -->
+  <!--  CorpAuthor (defined elsewhere in this section) -->
+  <!--  OtherCredit (defined elsewhere in this section) -->
+  <!-- end of authorgroup.content.module -->
+  <!-- AuthorInitials ................... -->
+  <define name="local.authorinitials.attrib">
+    <empty/>
+  </define>
+  <define name="authorinitials.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The initials or other short identifier for an author. -->
+  <define name="authorinitials">
+    <element name="authorinitials">
+      <ref name="authorinitials.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of authorinitials.element -->
+  <define name="authorinitials.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="authorinitials.role.attrib"/>
+    <ref name="local.authorinitials.attrib"/>
+  </define>
+  <!-- end of authorinitials.attlist -->
+  <!-- end of authorinitials.module -->
+  <!-- ConfGroup ........................ -->
+  <define name="local.confgroup.attrib">
+    <empty/>
+  </define>
+  <define name="confgroup.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for document meta-information about a conference. -->
+  <define name="confgroup">
+    <element name="confgroup">
+      <ref name="confgroup.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="confdates"/>
+          <ref name="conftitle"/>
+          <ref name="confnum"/>
+          <ref name="address"/>
+          <ref name="confsponsor"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of confgroup.element -->
+  <define name="confgroup.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="confgroup.role.attrib"/>
+    <ref name="local.confgroup.attrib"/>
+  </define>
+  <!-- end of confgroup.attlist -->
+  <!-- end of confgroup.module -->
+  <define name="local.confdates.attrib">
+    <empty/>
+  </define>
+  <define name="confdates.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The dates of a conference for which a document was written. -->
+  <define name="confdates">
+    <element name="confdates">
+      <ref name="confdates.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of confdates.element -->
+  <define name="confdates.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="confdates.role.attrib"/>
+    <ref name="local.confdates.attrib"/>
+  </define>
+  <!-- end of confdates.attlist -->
+  <!-- end of confdates.module -->
+  <define name="local.conftitle.attrib">
+    <empty/>
+  </define>
+  <define name="conftitle.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The title of a conference for which a document was written. -->
+  <define name="conftitle">
+    <element name="conftitle">
+      <ref name="conftitle.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of conftitle.element -->
+  <define name="conftitle.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="conftitle.role.attrib"/>
+    <ref name="local.conftitle.attrib"/>
+  </define>
+  <!-- end of conftitle.attlist -->
+  <!-- end of conftitle.module -->
+  <define name="local.confnum.attrib">
+    <empty/>
+  </define>
+  <define name="confnum.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An identifier, frequently numerical, associated with a conference for which a document was written. -->
+  <define name="confnum">
+    <element name="confnum">
+      <ref name="confnum.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of confnum.element -->
+  <define name="confnum.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="confnum.role.attrib"/>
+    <ref name="local.confnum.attrib"/>
+  </define>
+  <!-- end of confnum.attlist -->
+  <!-- end of confnum.module -->
+  <!--  Address (defined elsewhere in this section) -->
+  <define name="local.confsponsor.attrib">
+    <empty/>
+  </define>
+  <define name="confsponsor.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The sponsor of a conference for which a document was written. -->
+  <define name="confsponsor">
+    <element name="confsponsor">
+      <ref name="confsponsor.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of confsponsor.element -->
+  <define name="confsponsor.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="confsponsor.role.attrib"/>
+    <ref name="local.confsponsor.attrib"/>
+  </define>
+  <!-- end of confsponsor.attlist -->
+  <!-- end of confsponsor.module -->
+  <!-- end of confgroup.content.module -->
+  <!-- ContractNum ...................... -->
+  <define name="local.contractnum.attrib">
+    <empty/>
+  </define>
+  <define name="contractnum.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The contract number of a document. -->
+  <define name="contractnum">
+    <element name="contractnum">
+      <ref name="contractnum.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of contractnum.element -->
+  <define name="contractnum.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="contractnum.role.attrib"/>
+    <ref name="local.contractnum.attrib"/>
+  </define>
+  <!-- end of contractnum.attlist -->
+  <!-- end of contractnum.module -->
+  <!-- ContractSponsor .................. -->
+  <define name="local.contractsponsor.attrib">
+    <empty/>
+  </define>
+  <define name="contractsponsor.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The sponsor of a contract. -->
+  <define name="contractsponsor">
+    <element name="contractsponsor">
+      <ref name="contractsponsor.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of contractsponsor.element -->
+  <define name="contractsponsor.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="contractsponsor.role.attrib"/>
+    <ref name="local.contractsponsor.attrib"/>
+  </define>
+  <!-- end of contractsponsor.attlist -->
+  <!-- end of contractsponsor.module -->
+  <!-- Copyright ........................ -->
+  <define name="local.copyright.attrib">
+    <empty/>
+  </define>
+  <define name="copyright.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Copyright information about a document. -->
+  <define name="copyright">
+    <element name="copyright">
+      <ref name="copyright.attlist"/>
+      <oneOrMore>
+        <ref name="year"/>
+      </oneOrMore>
+      <zeroOrMore>
+        <ref name="holder"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of copyright.element -->
+  <define name="copyright.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="copyright.role.attrib"/>
+    <ref name="local.copyright.attrib"/>
+  </define>
+  <!-- end of copyright.attlist -->
+  <!-- end of copyright.module -->
+  <define name="local.year.attrib">
+    <empty/>
+  </define>
+  <define name="year.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The year of publication of a document. -->
+  <define name="year">
+    <element name="year">
+      <ref name="year.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of year.element -->
+  <define name="year.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="year.role.attrib"/>
+    <ref name="local.year.attrib"/>
+  </define>
+  <!-- end of year.attlist -->
+  <!-- end of year.module -->
+  <define name="local.holder.attrib">
+    <empty/>
+  </define>
+  <define name="holder.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of the individual or organization that holds a copyright. -->
+  <define name="holder">
+    <element name="holder">
+      <ref name="holder.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of holder.element -->
+  <define name="holder.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="holder.role.attrib"/>
+    <ref name="local.holder.attrib"/>
+  </define>
+  <!-- end of holder.attlist -->
+  <!-- end of holder.module -->
+  <!-- end of copyright.content.module -->
+  <!-- CorpAuthor ....................... -->
+  <define name="local.corpauthor.attrib">
+    <empty/>
+  </define>
+  <define name="corpauthor.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A corporate author, as opposed to an individual. -->
+  <define name="corpauthor">
+    <element name="corpauthor">
+      <ref name="corpauthor.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of corpauthor.element -->
+  <define name="corpauthor.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="corpauthor.role.attrib"/>
+    <ref name="local.corpauthor.attrib"/>
+  </define>
+  <!-- end of corpauthor.attlist -->
+  <!-- end of corpauthor.module -->
+  <!-- CorpCredit ...................... -->
+  <define name="local.corpcredit.attrib">
+    <empty/>
+  </define>
+  <define name="corpcredit.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A corporation or organization credited in a document. -->
+  <define name="corpcredit">
+    <element name="corpcredit">
+      <ref name="corpcredit.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of corpcredit.element -->
+  <define name="corpcredit.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>graphicdesigner</value>
+          <value>productioneditor</value>
+          <value>copyeditor</value>
+          <value>technicaleditor</value>
+          <value>translator</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="corpcredit.role.attrib"/>
+    <ref name="local.corpcredit.attrib"/>
+  </define>
+  <!-- end of corpcredit.attlist -->
+  <!-- end of corpcredit.module -->
+  <!-- CorpName ......................... -->
+  <define name="local.corpname.attrib">
+    <empty/>
+  </define>
+  <!-- doc:The name of a corporation. -->
+  <define name="corpname">
+    <element name="corpname">
+      <ref name="corpname.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of corpname.element -->
+  <define name="corpname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <define name="corpname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="corpname.role.attrib"/>
+    <ref name="local.corpname.attrib"/>
+  </define>
+  <!-- end of corpname.attlist -->
+  <!-- end of corpname.module -->
+  <!-- Date ............................. -->
+  <define name="local.date.attrib">
+    <empty/>
+  </define>
+  <define name="date.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The date of publication or revision of a document. -->
+  <define name="date">
+    <element name="date">
+      <ref name="date.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of date.element -->
+  <define name="date.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="date.role.attrib"/>
+    <ref name="local.date.attrib"/>
+  </define>
+  <!-- end of date.attlist -->
+  <!-- end of date.module -->
+  <!-- Edition .......................... -->
+  <define name="local.edition.attrib">
+    <empty/>
+  </define>
+  <define name="edition.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name or number of an edition of a document. -->
+  <define name="edition">
+    <element name="edition">
+      <ref name="edition.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of edition.element -->
+  <define name="edition.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="edition.role.attrib"/>
+    <ref name="local.edition.attrib"/>
+  </define>
+  <!-- end of edition.attlist -->
+  <!-- end of edition.module -->
+  <!-- Editor ........................... -->
+  <define name="local.editor.attrib">
+    <empty/>
+  </define>
+  <define name="editor.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of the editor of a document. -->
+  <define name="editor">
+    <element name="editor">
+      <ref name="editor.attlist"/>
+      <choice>
+        <ref name="personname"/>
+        <oneOrMore>
+          <ref name="person.ident.mix"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <choice>
+          <ref name="personblurb"/>
+          <ref name="email"/>
+          <ref name="address"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of editor.element -->
+  <define name="editor.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="editor.role.attrib"/>
+    <ref name="local.editor.attrib"/>
+  </define>
+  <!-- end of editor.attlist -->
+  <!-- (see "Personal identity elements" for %person.ident.mix;) -->
+  <!-- end of editor.module -->
+  <!-- ISBN ............................. -->
+  <define name="local.isbn.attrib">
+    <empty/>
+  </define>
+  <define name="isbn.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The International Standard Book Number of a document. -->
+  <define name="isbn">
+    <element name="isbn">
+      <ref name="isbn.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of isbn.element -->
+  <define name="isbn.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="isbn.role.attrib"/>
+    <ref name="local.isbn.attrib"/>
+  </define>
+  <!-- end of isbn.attlist -->
+  <!-- end of isbn.module -->
+  <!-- ISSN ............................. -->
+  <define name="local.issn.attrib">
+    <empty/>
+  </define>
+  <define name="issn.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The International Standard Serial Number of a periodical. -->
+  <define name="issn">
+    <element name="issn">
+      <ref name="issn.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of issn.element -->
+  <define name="issn.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="issn.role.attrib"/>
+    <ref name="local.issn.attrib"/>
+  </define>
+  <!-- end of issn.attlist -->
+  <!-- end of issn.module -->
+  <!-- BiblioId ................. -->
+  <define name="biblio.class.attrib">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>uri</value>
+          <value>doi</value>
+          <value>isbn</value>
+          <value>isrn</value>
+          <value>issn</value>
+          <value>libraryofcongress</value>
+          <value>pubnumber</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otherclass"/>
+    </optional>
+  </define>
+  <define name="local.biblioid.attrib">
+    <empty/>
+  </define>
+  <define name="biblioid.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An identifier for a document. -->
+  <define name="biblioid">
+    <element name="biblioid">
+      <ref name="biblioid.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of biblioid.element -->
+  <define name="biblioid.attlist" combine="interleave">
+    <ref name="biblio.class.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="biblioid.role.attrib"/>
+    <ref name="local.biblioid.attrib"/>
+  </define>
+  <!-- end of biblioid.attlist -->
+  <!-- end of biblioid.module -->
+  <!-- CiteBiblioId ................. -->
+  <define name="local.citebiblioid.attrib">
+    <empty/>
+  </define>
+  <define name="citebiblioid.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A citation of a bibliographic identifier. -->
+  <define name="citebiblioid">
+    <element name="citebiblioid">
+      <ref name="citebiblioid.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of citebiblioid.element -->
+  <define name="citebiblioid.attlist" combine="interleave">
+    <ref name="biblio.class.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="citebiblioid.role.attrib"/>
+    <ref name="local.citebiblioid.attrib"/>
+  </define>
+  <!-- end of citebiblioid.attlist -->
+  <!-- end of citebiblioid.module -->
+  <!-- BiblioSource ................. -->
+  <define name="local.bibliosource.attrib">
+    <empty/>
+  </define>
+  <define name="bibliosource.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The source of a document. -->
+  <define name="bibliosource">
+    <element name="bibliosource">
+      <ref name="bibliosource.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of bibliosource.element -->
+  <define name="bibliosource.attlist" combine="interleave">
+    <ref name="biblio.class.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="bibliosource.role.attrib"/>
+    <ref name="local.bibliosource.attrib"/>
+  </define>
+  <!-- end of bibliosource.attlist -->
+  <!-- end of bibliosource.module -->
+  <!-- BiblioRelation ................. -->
+  <define name="local.bibliorelation.attrib">
+    <empty/>
+  </define>
+  <define name="local.bibliorelation.types">
+    <notAllowed/>
+  </define>
+  <define name="bibliorelation.type.attrib">
+    <optional>
+      <attribute name="type">
+        <choice>
+          <value>isversionof</value>
+          <value>hasversion</value>
+          <value>isreplacedby</value>
+          <value>replaces</value>
+          <value>isrequiredby</value>
+          <value>requires</value>
+          <value>ispartof</value>
+          <value>haspart</value>
+          <value>isreferencedby</value>
+          <value>references</value>
+          <value>isformatof</value>
+          <value>hasformat</value>
+          <value>othertype</value>
+          <ref name="local.bibliorelation.types"/>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="othertype"/>
+    </optional>
+  </define>
+  <define name="bibliorelation.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The relationship of a document to another. -->
+  <define name="bibliorelation">
+    <element name="bibliorelation">
+      <ref name="bibliorelation.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of bibliorelation.element -->
+  <define name="bibliorelation.attlist" combine="interleave">
+    <ref name="biblio.class.attrib"/>
+    <ref name="bibliorelation.type.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="bibliorelation.role.attrib"/>
+    <ref name="local.bibliorelation.attrib"/>
+  </define>
+  <!-- end of bibliorelation.attlist -->
+  <!-- end of bibliorelation.module -->
+  <!-- BiblioCoverage ................. -->
+  <define name="local.bibliocoverage.attrib">
+    <empty/>
+  </define>
+  <define name="bibliocoverage.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The spatial or temporal coverage of a document. -->
+  <define name="bibliocoverage">
+    <element name="bibliocoverage">
+      <ref name="bibliocoverage.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of bibliocoverage.element -->
+  <define name="bibliocoverage.attlist" combine="interleave">
+    <optional>
+      <attribute name="spatial">
+        <choice>
+          <value>dcmipoint</value>
+          <value>iso3166</value>
+          <value>dcmibox</value>
+          <value>tgn</value>
+          <value>otherspatial</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otherspatial"/>
+    </optional>
+    <optional>
+      <attribute name="temporal">
+        <choice>
+          <value>dcmiperiod</value>
+          <value>w3c-dtf</value>
+          <value>othertemporal</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="othertemporal"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="bibliocoverage.role.attrib"/>
+    <ref name="local.bibliocoverage.attrib"/>
+  </define>
+  <!-- end of bibliocoverage.attlist -->
+  <!-- end of bibliocoverage.module -->
+  <!-- InvPartNumber .................... -->
+  <define name="local.invpartnumber.attrib">
+    <empty/>
+  </define>
+  <define name="invpartnumber.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An inventory part number. -->
+  <define name="invpartnumber">
+    <element name="invpartnumber">
+      <ref name="invpartnumber.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of invpartnumber.element -->
+  <define name="invpartnumber.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="invpartnumber.role.attrib"/>
+    <ref name="local.invpartnumber.attrib"/>
+  </define>
+  <!-- end of invpartnumber.attlist -->
+  <!-- end of invpartnumber.module -->
+  <!-- IssueNum ......................... -->
+  <define name="local.issuenum.attrib">
+    <empty/>
+  </define>
+  <define name="issuenum.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The number of an issue of a journal. -->
+  <define name="issuenum">
+    <element name="issuenum">
+      <ref name="issuenum.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of issuenum.element -->
+  <define name="issuenum.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="issuenum.role.attrib"/>
+    <ref name="local.issuenum.attrib"/>
+  </define>
+  <!-- end of issuenum.attlist -->
+  <!-- end of issuenum.module -->
+  <!-- LegalNotice ...................... -->
+  <define name="local.legalnotice.attrib">
+    <empty/>
+  </define>
+  <define name="legalnotice.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A statement of legal obligations or requirements. -->
+  <define name="legalnotice">
+    <element name="legalnotice">
+      <ref name="legalnotice.attlist"/>
+      <optional>
+        <ref name="blockinfo"/>
+      </optional>
+      <optional>
+        <ref name="title"/>
+      </optional>
+      <oneOrMore>
+        <ref name="legalnotice.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of legalnotice.element -->
+  <define name="legalnotice.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="legalnotice.role.attrib"/>
+    <ref name="local.legalnotice.attrib"/>
+  </define>
+  <!-- end of legalnotice.attlist -->
+  <!-- end of legalnotice.module -->
+  <!-- ModeSpec ......................... -->
+  <define name="local.modespec.attrib">
+    <empty/>
+  </define>
+  <define name="modespec.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Application-specific information necessary for the completion of an OLink. -->
+  <define name="modespec">
+    <element name="modespec">
+      <ref name="modespec.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of modespec.element -->
+  <!--
+    Application: Type of action required for completion
+    of the links to which the ModeSpec is relevant (e.g.,
+    retrieval query)
+  -->
+  <define name="modespec.attlist" combine="interleave">
+    <optional>
+      <attribute name="application">
+        <choice>
+          <ref name="notation.class"/>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="modespec.role.attrib"/>
+    <ref name="local.modespec.attrib"/>
+  </define>
+  <!-- end of modespec.attlist -->
+  <!-- end of modespec.module -->
+  <!-- OrgName .......................... -->
+  <define name="local.orgname.attrib">
+    <empty/>
+  </define>
+  <define name="orgname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of an organization other than a corporation. -->
+  <define name="orgname">
+    <element name="orgname">
+      <ref name="orgname.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of orgname.element -->
+  <define name="orgname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>corporation</value>
+          <value>nonprofit</value>
+          <value>consortium</value>
+          <value>informal</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otherclass"/>
+    </optional>
+    <ref name="orgname.role.attrib"/>
+    <ref name="local.orgname.attrib"/>
+  </define>
+  <!-- end of orgname.attlist -->
+  <!-- end of orgname.module -->
+  <!-- OtherCredit ...................... -->
+  <define name="local.othercredit.attrib">
+    <empty/>
+  </define>
+  <define name="othercredit.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A person or entity, other than an author or editor, credited in a document. -->
+  <define name="othercredit">
+    <element name="othercredit">
+      <ref name="othercredit.attlist"/>
+      <choice>
+        <ref name="personname"/>
+        <oneOrMore>
+          <ref name="person.ident.mix"/>
+        </oneOrMore>
+      </choice>
+      <zeroOrMore>
+        <choice>
+          <ref name="personblurb"/>
+          <ref name="email"/>
+          <ref name="address"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of othercredit.element -->
+  <define name="othercredit.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>graphicdesigner</value>
+          <value>productioneditor</value>
+          <value>copyeditor</value>
+          <value>technicaleditor</value>
+          <value>translator</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="othercredit.role.attrib"/>
+    <ref name="local.othercredit.attrib"/>
+  </define>
+  <!-- end of othercredit.attlist -->
+  <!-- (see "Personal identity elements" for %person.ident.mix;) -->
+  <!-- end of othercredit.module -->
+  <!-- PageNums ......................... -->
+  <define name="local.pagenums.attrib">
+    <empty/>
+  </define>
+  <define name="pagenums.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The numbers of the pages in a book, for use in a bibliographic entry. -->
+  <define name="pagenums">
+    <element name="pagenums">
+      <ref name="pagenums.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of pagenums.element -->
+  <define name="pagenums.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="pagenums.role.attrib"/>
+    <ref name="local.pagenums.attrib"/>
+  </define>
+  <!-- end of pagenums.attlist -->
+  <!-- end of pagenums.module -->
+  <!-- Personal identity elements ....... -->
+  <!--
+    These elements are used only within Author, Editor, and
+    OtherCredit.
+  -->
+  <define name="local.contrib.attrib">
+    <empty/>
+  </define>
+  <define name="contrib.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A summary of the contributions made to a document by a credited source. -->
+  <define name="contrib">
+    <element name="contrib">
+      <ref name="contrib.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of contrib.element -->
+  <define name="contrib.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="contrib.role.attrib"/>
+    <ref name="local.contrib.attrib"/>
+  </define>
+  <!-- end of contrib.attlist -->
+  <!-- end of contrib.module -->
+  <define name="local.firstname.attrib">
+    <empty/>
+  </define>
+  <define name="firstname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The first name of a person. -->
+  <define name="firstname">
+    <element name="firstname">
+      <ref name="firstname.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of firstname.element -->
+  <define name="firstname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="firstname.role.attrib"/>
+    <ref name="local.firstname.attrib"/>
+  </define>
+  <!-- end of firstname.attlist -->
+  <!-- end of firstname.module -->
+  <define name="local.honorific.attrib">
+    <empty/>
+  </define>
+  <define name="honorific.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The title of a person. -->
+  <define name="honorific">
+    <element name="honorific">
+      <ref name="honorific.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of honorific.element -->
+  <define name="honorific.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="honorific.role.attrib"/>
+    <ref name="local.honorific.attrib"/>
+  </define>
+  <!-- end of honorific.attlist -->
+  <!-- end of honorific.module -->
+  <define name="local.lineage.attrib">
+    <empty/>
+  </define>
+  <define name="lineage.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The portion of a person's name indicating a relationship to ancestors. -->
+  <define name="lineage">
+    <element name="lineage">
+      <ref name="lineage.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of lineage.element -->
+  <define name="lineage.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="lineage.role.attrib"/>
+    <ref name="local.lineage.attrib"/>
+  </define>
+  <!-- end of lineage.attlist -->
+  <!-- end of lineage.module -->
+  <define name="local.othername.attrib">
+    <empty/>
+  </define>
+  <define name="othername.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A component of a persons name that is not a first name, surname, or lineage. -->
+  <define name="othername">
+    <element name="othername">
+      <ref name="othername.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of othername.element -->
+  <define name="othername.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="othername.role.attrib"/>
+    <ref name="local.othername.attrib"/>
+  </define>
+  <!-- end of othername.attlist -->
+  <!-- end of othername.module -->
+  <define name="local.surname.attrib">
+    <empty/>
+  </define>
+  <define name="surname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A family name; in western cultures the last name. -->
+  <define name="surname">
+    <element name="surname">
+      <ref name="surname.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of surname.element -->
+  <define name="surname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="surname.role.attrib"/>
+    <ref name="local.surname.attrib"/>
+  </define>
+  <!-- end of surname.attlist -->
+  <!-- end of surname.module -->
+  <!-- end of person.ident.module -->
+  <!-- PrintHistory ..................... -->
+  <define name="local.printhistory.attrib">
+    <empty/>
+  </define>
+  <define name="printhistory.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The printing history of a document. -->
+  <define name="printhistory">
+    <element name="printhistory">
+      <ref name="printhistory.attlist"/>
+      <oneOrMore>
+        <ref name="para.class"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of printhistory.element -->
+  <define name="printhistory.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="printhistory.role.attrib"/>
+    <ref name="local.printhistory.attrib"/>
+  </define>
+  <!-- end of printhistory.attlist -->
+  <!-- end of printhistory.module -->
+  <!-- ProductName ...................... -->
+  <define name="local.productname.attrib">
+    <empty/>
+  </define>
+  <define name="productname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The formal name of a product. -->
+  <define name="productname">
+    <element name="productname">
+      <ref name="productname.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of productname.element -->
+  <!-- Class: More precisely identifies the item the element names -->
+  <define name="productname.attlist" combine="interleave">
+    <optional>
+      <attribute name="class" a:defaultValue="trade">
+        <choice>
+          <value>service</value>
+          <value>trade</value>
+          <value>registered</value>
+          <value>copyright</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="productname.role.attrib"/>
+    <ref name="local.productname.attrib"/>
+  </define>
+  <!-- end of productname.attlist -->
+  <!-- end of productname.module -->
+  <!-- ProductNumber .................... -->
+  <define name="local.productnumber.attrib">
+    <empty/>
+  </define>
+  <define name="productnumber.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A number assigned to a product. -->
+  <define name="productnumber">
+    <element name="productnumber">
+      <ref name="productnumber.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of productnumber.element -->
+  <define name="productnumber.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="productnumber.role.attrib"/>
+    <ref name="local.productnumber.attrib"/>
+  </define>
+  <!-- end of productnumber.attlist -->
+  <!-- end of productnumber.module -->
+  <!-- PubDate .......................... -->
+  <define name="local.pubdate.attrib">
+    <empty/>
+  </define>
+  <define name="pubdate.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The date of publication of a document. -->
+  <define name="pubdate">
+    <element name="pubdate">
+      <ref name="pubdate.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of pubdate.element -->
+  <define name="pubdate.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="pubdate.role.attrib"/>
+    <ref name="local.pubdate.attrib"/>
+  </define>
+  <!-- end of pubdate.attlist -->
+  <!-- end of pubdate.module -->
+  <!-- Publisher ........................ -->
+  <define name="local.publisher.attrib">
+    <empty/>
+  </define>
+  <define name="publisher.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The publisher of a document. -->
+  <define name="publisher">
+    <element name="publisher">
+      <ref name="publisher.attlist"/>
+      <ref name="publishername"/>
+      <zeroOrMore>
+        <ref name="address"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of publisher.element -->
+  <define name="publisher.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="publisher.role.attrib"/>
+    <ref name="local.publisher.attrib"/>
+  </define>
+  <!-- end of publisher.attlist -->
+  <!-- end of publisher.module -->
+  <define name="local.publishername.attrib">
+    <empty/>
+  </define>
+  <define name="publishername.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of the publisher of a document. -->
+  <define name="publishername">
+    <element name="publishername">
+      <ref name="publishername.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of publishername.element -->
+  <define name="publishername.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="publishername.role.attrib"/>
+    <ref name="local.publishername.attrib"/>
+  </define>
+  <!-- end of publishername.attlist -->
+  <!-- end of publishername.module -->
+  <!--  Address (defined elsewhere in this section) -->
+  <!-- end of publisher.content.module -->
+  <!-- PubsNumber ....................... -->
+  <define name="local.pubsnumber.attrib">
+    <empty/>
+  </define>
+  <define name="pubsnumber.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A number assigned to a publication other than an ISBN or ISSN or inventory part number. -->
+  <define name="pubsnumber">
+    <element name="pubsnumber">
+      <ref name="pubsnumber.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of pubsnumber.element -->
+  <define name="pubsnumber.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="pubsnumber.role.attrib"/>
+    <ref name="local.pubsnumber.attrib"/>
+  </define>
+  <!-- end of pubsnumber.attlist -->
+  <!-- end of pubsnumber.module -->
+  <!-- ReleaseInfo ...................... -->
+  <define name="local.releaseinfo.attrib">
+    <empty/>
+  </define>
+  <define name="releaseinfo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Information about a particular release of a document. -->
+  <define name="releaseinfo">
+    <element name="releaseinfo">
+      <ref name="releaseinfo.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of releaseinfo.element -->
+  <define name="releaseinfo.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="releaseinfo.role.attrib"/>
+    <ref name="local.releaseinfo.attrib"/>
+  </define>
+  <!-- end of releaseinfo.attlist -->
+  <!-- end of releaseinfo.module -->
+  <!-- RevHistory ....................... -->
+  <define name="local.revhistory.attrib">
+    <empty/>
+  </define>
+  <define name="revhistory.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A history of the revisions to a document. -->
+  <define name="revhistory">
+    <element name="revhistory">
+      <ref name="revhistory.attlist"/>
+      <oneOrMore>
+        <ref name="revision"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of revhistory.element -->
+  <define name="revhistory.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="revhistory.role.attrib"/>
+    <ref name="local.revhistory.attrib"/>
+  </define>
+  <!-- end of revhistory.attlist -->
+  <!-- end of revhistory.module -->
+  <define name="local.revision.attrib">
+    <empty/>
+  </define>
+  <define name="revision.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An entry describing a single revision in the history of the revisions to a document. -->
+  <define name="revision">
+    <element name="revision">
+      <ref name="revision.attlist"/>
+      <optional>
+        <ref name="revnumber"/>
+      </optional>
+      <ref name="date"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="author"/>
+          <ref name="authorinitials"/>
+        </choice>
+      </zeroOrMore>
+      <optional>
+        <choice>
+          <ref name="revremark"/>
+          <ref name="revdescription"/>
+        </choice>
+      </optional>
+    </element>
+  </define>
+  <!-- end of revision.element -->
+  <define name="revision.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="revision.role.attrib"/>
+    <ref name="local.revision.attrib"/>
+  </define>
+  <!-- end of revision.attlist -->
+  <!-- end of revision.module -->
+  <define name="local.revnumber.attrib">
+    <empty/>
+  </define>
+  <define name="revnumber.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A document revision number. -->
+  <define name="revnumber">
+    <element name="revnumber">
+      <ref name="revnumber.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of revnumber.element -->
+  <define name="revnumber.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="revnumber.role.attrib"/>
+    <ref name="local.revnumber.attrib"/>
+  </define>
+  <!-- end of revnumber.attlist -->
+  <!-- end of revnumber.module -->
+  <!--  Date (defined elsewhere in this section) -->
+  <!--  AuthorInitials (defined elsewhere in this section) -->
+  <define name="local.revremark.attrib">
+    <empty/>
+  </define>
+  <define name="revremark.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A description of a revision to a document. -->
+  <define name="revremark">
+    <element name="revremark">
+      <ref name="revremark.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of revremark.element -->
+  <define name="revremark.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="revremark.role.attrib"/>
+    <ref name="local.revremark.attrib"/>
+  </define>
+  <!-- end of revremark.attlist -->
+  <!-- end of revremark.module -->
+  <define name="local.revdescription.attrib">
+    <empty/>
+  </define>
+  <define name="revdescription.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A extended description of a revision to a document. -->
+  <define name="revdescription">
+    <element name="revdescription">
+      <ref name="revdescription.attlist"/>
+      <oneOrMore>
+        <ref name="revdescription.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of revdescription.element -->
+  <define name="revdescription.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="revdescription.role.attrib"/>
+    <ref name="local.revdescription.attrib"/>
+  </define>
+  <!-- end of revdescription.attlist -->
+  <!-- end of revdescription.module -->
+  <!-- end of revhistory.content.module -->
+  <!-- SeriesVolNums .................... -->
+  <define name="local.seriesvolnums.attrib">
+    <empty/>
+  </define>
+  <define name="seriesvolnums.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Numbers of the volumes in a series of books. -->
+  <define name="seriesvolnums">
+    <element name="seriesvolnums">
+      <ref name="seriesvolnums.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of seriesvolnums.element -->
+  <define name="seriesvolnums.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="seriesvolnums.role.attrib"/>
+    <ref name="local.seriesvolnums.attrib"/>
+  </define>
+  <!-- end of seriesvolnums.attlist -->
+  <!-- end of seriesvolnums.module -->
+  <!-- VolumeNum ........................ -->
+  <define name="local.volumenum.attrib">
+    <empty/>
+  </define>
+  <define name="volumenum.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The volume number of a document in a set (as of books in a set or articles in a journal). -->
+  <define name="volumenum">
+    <element name="volumenum">
+      <ref name="volumenum.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of volumenum.element -->
+  <define name="volumenum.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="volumenum.role.attrib"/>
+    <ref name="local.volumenum.attrib"/>
+  </define>
+  <!-- end of volumenum.attlist -->
+  <!-- end of volumenum.module -->
+  <!-- .................................. -->
+  <!-- end of docinfo.content.module -->
+  <!-- ...................................................................... -->
+  <!-- Inline, link, and ubiquitous elements ................................ -->
+  <!-- Technical and computer terms ......................................... -->
+  <define name="local.accel.attrib">
+    <empty/>
+  </define>
+  <define name="accel.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A graphical user interface (GUI) keyboard shortcut. -->
+  <define name="accel">
+    <element name="accel">
+      <ref name="accel.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of accel.element -->
+  <define name="accel.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="accel.role.attrib"/>
+    <ref name="local.accel.attrib"/>
+  </define>
+  <!-- end of accel.attlist -->
+  <!-- end of accel.module -->
+  <define name="local.action.attrib">
+    <empty/>
+  </define>
+  <define name="action.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A response to a user event. -->
+  <define name="action">
+    <element name="action">
+      <ref name="action.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of action.element -->
+  <define name="action.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="action.role.attrib"/>
+    <ref name="local.action.attrib"/>
+  </define>
+  <!-- end of action.attlist -->
+  <!-- end of action.module -->
+  <define name="local.application.attrib">
+    <empty/>
+  </define>
+  <define name="application.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a software program. -->
+  <define name="application">
+    <element name="application">
+      <ref name="application.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of application.element -->
+  <define name="application.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>hardware</value>
+          <value>software</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="application.role.attrib"/>
+    <ref name="local.application.attrib"/>
+  </define>
+  <!-- end of application.attlist -->
+  <!-- end of application.module -->
+  <define name="local.classname.attrib">
+    <empty/>
+  </define>
+  <define name="classname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a class, in the object-oriented programming sense. -->
+  <define name="classname">
+    <element name="classname">
+      <ref name="classname.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of classname.element -->
+  <define name="classname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="classname.role.attrib"/>
+    <ref name="local.classname.attrib"/>
+  </define>
+  <!-- end of classname.attlist -->
+  <!-- end of classname.module -->
+  <define name="local.package.attrib">
+    <empty/>
+  </define>
+  <define name="package.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A package. -->
+  <define name="package">
+    <element name="package">
+      <ref name="package.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of package.element -->
+  <define name="package.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="package.role.attrib"/>
+    <ref name="local.package.attrib"/>
+  </define>
+  <!-- end of package.attlist -->
+  <!-- end of package.module -->
+  <define name="local.co.attrib">
+    <empty/>
+  </define>
+  <!--
+    CO is a callout area of the LineColumn unit type (a single character
+    position); the position is directly indicated by the location of CO.
+  -->
+  <define name="co.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The location of a callout embedded in text. -->
+  <define name="co">
+    <element name="co">
+      <ref name="co.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of co.element -->
+  <!-- bug number/symbol override or initialization -->
+  <!-- to any related information -->
+  <define name="co.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="linkends.attrib"/>
+    <ref name="idreq.common.attrib"/>
+    <ref name="co.role.attrib"/>
+    <ref name="local.co.attrib"/>
+  </define>
+  <!-- end of co.attlist -->
+  <!-- end of co.module -->
+  <define name="local.coref.attrib">
+    <empty/>
+  </define>
+  <!-- COREF is a reference to a CO -->
+  <define name="coref.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A cross reference to a co. -->
+  <define name="coref">
+    <element name="coref">
+      <ref name="coref.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of coref.element -->
+  <!-- bug number/symbol override or initialization -->
+  <!-- to any related information -->
+  <define name="coref.attlist" combine="interleave">
+    <ref name="label.attrib"/>
+    <ref name="linkendreq.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="coref.role.attrib"/>
+    <ref name="local.coref.attrib"/>
+  </define>
+  <!-- end of coref.attlist -->
+  <!-- end of coref.module -->
+  <define name="local.command.attrib">
+    <empty/>
+  </define>
+  <define name="command.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of an executable program or other software command. -->
+  <define name="command">
+    <element name="command">
+      <ref name="command.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of command.element -->
+  <define name="command.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="command.role.attrib"/>
+    <ref name="local.command.attrib"/>
+  </define>
+  <!-- end of command.attlist -->
+  <!-- end of command.module -->
+  <define name="local.computeroutput.attrib">
+    <empty/>
+  </define>
+  <define name="computeroutput.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Data, generally text, displayed or presented by a computer. -->
+  <define name="computeroutput">
+    <element name="computeroutput">
+      <ref name="computeroutput.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="cptr.char.mix"/>
+          <ref name="co"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of computeroutput.element -->
+  <define name="computeroutput.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="computeroutput.role.attrib"/>
+    <ref name="local.computeroutput.attrib"/>
+  </define>
+  <!-- end of computeroutput.attlist -->
+  <!-- end of computeroutput.module -->
+  <define name="local.database.attrib">
+    <empty/>
+  </define>
+  <define name="database.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a database, or part of a database. -->
+  <define name="database">
+    <element name="database">
+      <ref name="database.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of database.element -->
+  <!-- Class: Type of database the element names; no default -->
+  <define name="database.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>name</value>
+          <value>table</value>
+          <value>field</value>
+          <value>key1</value>
+          <value>key2</value>
+          <value>record</value>
+          <value>index</value>
+          <value>view</value>
+          <value>primarykey</value>
+          <value>secondarykey</value>
+          <value>foreignkey</value>
+          <value>altkey</value>
+          <value>procedure</value>
+          <value>datatype</value>
+          <value>constraint</value>
+          <value>rule</value>
+          <value>user</value>
+          <value>group</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="database.role.attrib"/>
+    <ref name="local.database.attrib"/>
+  </define>
+  <!-- end of database.attlist -->
+  <!-- end of database.module -->
+  <define name="local.email.attrib">
+    <empty/>
+  </define>
+  <define name="email.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An email address. -->
+  <define name="email">
+    <element name="email">
+      <ref name="email.attlist"/>
+      <zeroOrMore>
+        <ref name="docinfo.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of email.element -->
+  <define name="email.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="email.role.attrib"/>
+    <ref name="local.email.attrib"/>
+  </define>
+  <!-- end of email.attlist -->
+  <!-- end of email.module -->
+  <define name="local.envar.attrib">
+    <empty/>
+  </define>
+  <define name="envar.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A software environment variable. -->
+  <define name="envar">
+    <element name="envar">
+      <ref name="envar.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of envar.element -->
+  <define name="envar.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="envar.role.attrib"/>
+    <ref name="local.envar.attrib"/>
+  </define>
+  <!-- end of envar.attlist -->
+  <!-- end of envar.module -->
+  <define name="local.errorcode.attrib">
+    <empty/>
+  </define>
+  <define name="errorcode.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An error code. -->
+  <define name="errorcode">
+    <element name="errorcode">
+      <ref name="errorcode.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of errorcode.element -->
+  <define name="errorcode.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="errorcode.role.attrib"/>
+    <ref name="local.errorcode.attrib"/>
+  </define>
+  <!-- end of errorcode.attlist -->
+  <!-- end of errorcode.module -->
+  <define name="local.errorname.attrib">
+    <empty/>
+  </define>
+  <define name="errorname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An error name. -->
+  <define name="errorname">
+    <element name="errorname">
+      <ref name="errorname.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of errorname.element -->
+  <define name="errorname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="errorname.role.attrib"/>
+    <ref name="local.errorname.attrib"/>
+  </define>
+  <!-- end of errorname.attlist -->
+  <!-- end of errorname.module -->
+  <define name="local.errortext.attrib">
+    <empty/>
+  </define>
+  <define name="errortext.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An error message.. -->
+  <define name="errortext">
+    <element name="errortext">
+      <ref name="errortext.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of errortext.element -->
+  <define name="errortext.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="errortext.role.attrib"/>
+    <ref name="local.errortext.attrib"/>
+  </define>
+  <!-- end of errortext.attlist -->
+  <!-- end of errortext.module -->
+  <define name="local.errortype.attrib">
+    <empty/>
+  </define>
+  <define name="errortype.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The classification of an error message. -->
+  <define name="errortype">
+    <element name="errortype">
+      <ref name="errortype.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of errortype.element -->
+  <define name="errortype.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="errortype.role.attrib"/>
+    <ref name="local.errortype.attrib"/>
+  </define>
+  <!-- end of errortype.attlist -->
+  <!-- end of errortype.module -->
+  <define name="local.filename.attrib">
+    <empty/>
+  </define>
+  <define name="filename.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a file. -->
+  <define name="filename">
+    <element name="filename">
+      <ref name="filename.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of filename.element -->
+  <!-- Class: Type of filename the element names; no default -->
+  <!--
+    Path: Search path (possibly system-specific) in which
+    file can be found
+  -->
+  <define name="filename.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>headerfile</value>
+          <value>partition</value>
+          <value>devicefile</value>
+          <value>libraryfile</value>
+          <value>directory</value>
+          <value>extension</value>
+          <value>symlink</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="path"/>
+    </optional>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="filename.role.attrib"/>
+    <ref name="local.filename.attrib"/>
+  </define>
+  <!-- end of filename.attlist -->
+  <!-- end of filename.module -->
+  <define name="local.function.attrib">
+    <empty/>
+  </define>
+  <define name="function.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a function or subroutine, as in a programming language. -->
+  <define name="function">
+    <element name="function">
+      <ref name="function.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of function.element -->
+  <define name="function.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="function.role.attrib"/>
+    <ref name="local.function.attrib"/>
+  </define>
+  <!-- end of function.attlist -->
+  <!-- end of function.module -->
+  <define name="local.guibutton.attrib">
+    <empty/>
+  </define>
+  <define name="guibutton.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The text on a button in a GUI. -->
+  <define name="guibutton">
+    <element name="guibutton">
+      <ref name="guibutton.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="accel"/>
+          <ref name="superscript"/>
+          <ref name="subscript"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of guibutton.element -->
+  <define name="guibutton.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="guibutton.role.attrib"/>
+    <ref name="local.guibutton.attrib"/>
+  </define>
+  <!-- end of guibutton.attlist -->
+  <!-- end of guibutton.module -->
+  <define name="local.guiicon.attrib">
+    <empty/>
+  </define>
+  <define name="guiicon.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Graphic and/or text appearing as a icon in a GUI. -->
+  <define name="guiicon">
+    <element name="guiicon">
+      <ref name="guiicon.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="accel"/>
+          <ref name="superscript"/>
+          <ref name="subscript"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of guiicon.element -->
+  <define name="guiicon.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="guiicon.role.attrib"/>
+    <ref name="local.guiicon.attrib"/>
+  </define>
+  <!-- end of guiicon.attlist -->
+  <!-- end of guiicon.module -->
+  <define name="local.guilabel.attrib">
+    <empty/>
+  </define>
+  <define name="guilabel.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The text of a label in a GUI. -->
+  <define name="guilabel">
+    <element name="guilabel">
+      <ref name="guilabel.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="accel"/>
+          <ref name="superscript"/>
+          <ref name="subscript"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of guilabel.element -->
+  <define name="guilabel.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="guilabel.role.attrib"/>
+    <ref name="local.guilabel.attrib"/>
+  </define>
+  <!-- end of guilabel.attlist -->
+  <!-- end of guilabel.module -->
+  <define name="local.guimenu.attrib">
+    <empty/>
+  </define>
+  <define name="guimenu.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a menu in a GUI. -->
+  <define name="guimenu">
+    <element name="guimenu">
+      <ref name="guimenu.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="accel"/>
+          <ref name="superscript"/>
+          <ref name="subscript"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of guimenu.element -->
+  <define name="guimenu.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="guimenu.role.attrib"/>
+    <ref name="local.guimenu.attrib"/>
+  </define>
+  <!-- end of guimenu.attlist -->
+  <!-- end of guimenu.module -->
+  <define name="local.guimenuitem.attrib">
+    <empty/>
+  </define>
+  <define name="guimenuitem.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a terminal menu item in a GUI. -->
+  <define name="guimenuitem">
+    <element name="guimenuitem">
+      <ref name="guimenuitem.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="accel"/>
+          <ref name="superscript"/>
+          <ref name="subscript"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of guimenuitem.element -->
+  <define name="guimenuitem.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="guimenuitem.role.attrib"/>
+    <ref name="local.guimenuitem.attrib"/>
+  </define>
+  <!-- end of guimenuitem.attlist -->
+  <!-- end of guimenuitem.module -->
+  <define name="local.guisubmenu.attrib">
+    <empty/>
+  </define>
+  <define name="guisubmenu.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a submenu in a GUI. -->
+  <define name="guisubmenu">
+    <element name="guisubmenu">
+      <ref name="guisubmenu.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="accel"/>
+          <ref name="superscript"/>
+          <ref name="subscript"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of guisubmenu.element -->
+  <define name="guisubmenu.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="guisubmenu.role.attrib"/>
+    <ref name="local.guisubmenu.attrib"/>
+  </define>
+  <!-- end of guisubmenu.attlist -->
+  <!-- end of guisubmenu.module -->
+  <define name="local.hardware.attrib">
+    <empty/>
+  </define>
+  <define name="hardware.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A physical part of a computer system. -->
+  <define name="hardware">
+    <element name="hardware">
+      <ref name="hardware.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of hardware.element -->
+  <define name="hardware.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="hardware.role.attrib"/>
+    <ref name="local.hardware.attrib"/>
+  </define>
+  <!-- end of hardware.attlist -->
+  <!-- end of hardware.module -->
+  <define name="local.interface.attrib">
+    <empty/>
+  </define>
+  <define name="interface.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An element of a GUI. -->
+  <define name="interface">
+    <element name="interface">
+      <ref name="interface.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="accel"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of interface.element -->
+  <!-- Class: Type of the Interface item; no default -->
+  <define name="interface.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="interface.role.attrib"/>
+    <ref name="local.interface.attrib"/>
+  </define>
+  <!-- end of interface.attlist -->
+  <!-- end of interface.module -->
+  <define name="local.keycap.attrib">
+    <empty/>
+  </define>
+  <define name="keycap.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The text printed on a key on a keyboard. -->
+  <define name="keycap">
+    <element name="keycap">
+      <ref name="keycap.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of keycap.element -->
+  <define name="keycap.attlist" combine="interleave">
+    <optional>
+      <attribute name="function">
+        <choice>
+          <value>alt</value>
+          <value>control</value>
+          <value>shift</value>
+          <value>meta</value>
+          <value>escape</value>
+          <value>enter</value>
+          <value>tab</value>
+          <value>backspace</value>
+          <value>command</value>
+          <value>option</value>
+          <value>space</value>
+          <value>delete</value>
+          <value>insert</value>
+          <value>up</value>
+          <value>down</value>
+          <value>left</value>
+          <value>right</value>
+          <value>home</value>
+          <value>end</value>
+          <value>pageup</value>
+          <value>pagedown</value>
+          <value>other</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="otherfunction"/>
+    </optional>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="keycap.role.attrib"/>
+    <ref name="local.keycap.attrib"/>
+  </define>
+  <!-- end of keycap.attlist -->
+  <!-- end of keycap.module -->
+  <define name="local.keycode.attrib">
+    <empty/>
+  </define>
+  <define name="keycode.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The internal, frequently numeric, identifier for a key on a keyboard. -->
+  <define name="keycode">
+    <element name="keycode">
+      <ref name="keycode.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of keycode.element -->
+  <define name="keycode.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="keycode.role.attrib"/>
+    <ref name="local.keycode.attrib"/>
+  </define>
+  <!-- end of keycode.attlist -->
+  <!-- end of keycode.module -->
+  <define name="local.keycombo.attrib">
+    <empty/>
+  </define>
+  <define name="keycombo.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A combination of input actions. -->
+  <define name="keycombo">
+    <element name="keycombo">
+      <ref name="keycombo.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="keycap"/>
+          <ref name="keycombo"/>
+          <ref name="keysym"/>
+          <ref name="mousebutton"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of keycombo.element -->
+  <define name="keycombo.attlist" combine="interleave">
+    <ref name="keyaction.attrib"/>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="keycombo.role.attrib"/>
+    <ref name="local.keycombo.attrib"/>
+  </define>
+  <!-- end of keycombo.attlist -->
+  <!-- end of keycombo.module -->
+  <define name="local.keysym.attrib">
+    <empty/>
+  </define>
+  <define name="keysysm.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The symbolic name of a key on a keyboard. -->
+  <define name="keysym">
+    <element name="keysym">
+      <ref name="keysym.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of keysym.element -->
+  <define name="keysym.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="keysysm.role.attrib"/>
+    <ref name="local.keysym.attrib"/>
+  </define>
+  <!-- end of keysym.attlist -->
+  <!-- end of keysym.module -->
+  <define name="local.lineannotation.attrib">
+    <empty/>
+  </define>
+  <define name="lineannotation.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A comment on a line in a verbatim listing. -->
+  <define name="lineannotation">
+    <element name="lineannotation">
+      <ref name="lineannotation.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of lineannotation.element -->
+  <define name="lineannotation.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="lineannotation.role.attrib"/>
+    <ref name="local.lineannotation.attrib"/>
+  </define>
+  <!-- end of lineannotation.attlist -->
+  <!-- end of lineannotation.module -->
+  <define name="local.literal.attrib">
+    <empty/>
+  </define>
+  <define name="literal.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Inline text that is some literal value. -->
+  <define name="literal">
+    <element name="literal">
+      <ref name="literal.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of literal.element -->
+  <define name="literal.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="literal.role.attrib"/>
+    <ref name="local.literal.attrib"/>
+  </define>
+  <!-- end of literal.attlist -->
+  <!-- end of literal.module -->
+  <define name="local.code.attrib">
+    <empty/>
+  </define>
+  <define name="code.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An inline code fragment. -->
+  <define name="code">
+    <element name="code">
+      <ref name="code.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of code.element -->
+  <define name="code.attlist" combine="interleave">
+    <optional>
+      <attribute name="language"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="code.role.attrib"/>
+    <ref name="local.code.attrib"/>
+  </define>
+  <!-- end of code.attlist -->
+  <!-- end of code.module -->
+  <define name="local.constant.attrib">
+    <empty/>
+  </define>
+  <define name="constant.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A programming or system constant. -->
+  <define name="constant">
+    <element name="constant">
+      <ref name="constant.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of constant.element -->
+  <define name="constant.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>limit</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="constant.role.attrib"/>
+    <ref name="local.constant.attrib"/>
+  </define>
+  <!-- end of constant.attlist -->
+  <!-- end of constant.module -->
+  <define name="local.varname.attrib">
+    <empty/>
+  </define>
+  <define name="varname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a variable. -->
+  <define name="varname">
+    <element name="varname">
+      <ref name="varname.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of varname.element -->
+  <define name="varname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="varname.role.attrib"/>
+    <ref name="local.varname.attrib"/>
+  </define>
+  <!-- end of varname.attlist -->
+  <!-- end of varname.module -->
+  <define name="local.markup.attrib">
+    <empty/>
+  </define>
+  <define name="markup.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A string of formatting markup in text that is to be represented literally. -->
+  <define name="markup">
+    <element name="markup">
+      <ref name="markup.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of markup.element -->
+  <define name="markup.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="markup.role.attrib"/>
+    <ref name="local.markup.attrib"/>
+  </define>
+  <!-- end of markup.attlist -->
+  <!-- end of markup.module -->
+  <define name="local.medialabel.attrib">
+    <empty/>
+  </define>
+  <define name="medialabel.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A name that identifies the physical medium on which some information resides. -->
+  <define name="medialabel">
+    <element name="medialabel">
+      <ref name="medialabel.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of medialabel.element -->
+  <!-- Class: Type of medium named by the element; no default -->
+  <define name="medialabel.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>cartridge</value>
+          <value>cdrom</value>
+          <value>disk</value>
+          <value>tape</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="medialabel.role.attrib"/>
+    <ref name="local.medialabel.attrib"/>
+  </define>
+  <!-- end of medialabel.attlist -->
+  <!-- end of medialabel.module -->
+  <define name="local.menuchoice.attrib">
+    <empty/>
+  </define>
+  <define name="menuchoice.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A selection or series of selections from a menu. -->
+  <define name="menuchoice">
+    <element name="menuchoice">
+      <ref name="menuchoice.attlist"/>
+      <optional>
+        <ref name="shortcut"/>
+      </optional>
+      <oneOrMore>
+        <choice>
+          <ref name="guibutton"/>
+          <ref name="guiicon"/>
+          <ref name="guilabel"/>
+          <ref name="guimenu"/>
+          <ref name="guimenuitem"/>
+          <ref name="guisubmenu"/>
+          <ref name="interface"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of menuchoice.element -->
+  <define name="menuchoice.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="menuchoice.role.attrib"/>
+    <ref name="local.menuchoice.attrib"/>
+  </define>
+  <!-- end of menuchoice.attlist -->
+  <!-- end of menuchoice.module -->
+  <!-- See also KeyCombo -->
+  <define name="local.shortcut.attrib">
+    <empty/>
+  </define>
+  <define name="shortcut.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A key combination for an action that is also accessible through a menu. -->
+  <define name="shortcut">
+    <element name="shortcut">
+      <ref name="shortcut.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="keycap"/>
+          <ref name="keycombo"/>
+          <ref name="keysym"/>
+          <ref name="mousebutton"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of shortcut.element -->
+  <define name="shortcut.attlist" combine="interleave">
+    <ref name="keyaction.attrib"/>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="shortcut.role.attrib"/>
+    <ref name="local.shortcut.attrib"/>
+  </define>
+  <!-- end of shortcut.attlist -->
+  <!-- end of shortcut.module -->
+  <!-- end of menuchoice.content.module -->
+  <define name="local.mousebutton.attrib">
+    <empty/>
+  </define>
+  <define name="mousebutton.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The conventional name of a mouse button. -->
+  <define name="mousebutton">
+    <element name="mousebutton">
+      <ref name="mousebutton.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of mousebutton.element -->
+  <define name="mousebutton.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="mousebutton.role.attrib"/>
+    <ref name="local.mousebutton.attrib"/>
+  </define>
+  <!-- end of mousebutton.attlist -->
+  <!-- end of mousebutton.module -->
+  <define name="local.msgtext.attrib">
+    <empty/>
+  </define>
+  <define name="msgtext.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The actual text of a message component in a message set. -->
+  <define name="msgtext">
+    <element name="msgtext">
+      <ref name="msgtext.attlist"/>
+      <oneOrMore>
+        <ref name="component.mix"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- end of msgtext.element -->
+  <define name="msgtext.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="msgtext.role.attrib"/>
+    <ref name="local.msgtext.attrib"/>
+  </define>
+  <!-- end of msgtext.attlist -->
+  <!-- end of msgtext.module -->
+  <define name="local.option.attrib">
+    <empty/>
+  </define>
+  <define name="option.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An option for a software command. -->
+  <define name="option">
+    <element name="option">
+      <ref name="option.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of option.element -->
+  <define name="option.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="option.role.attrib"/>
+    <ref name="local.option.attrib"/>
+  </define>
+  <!-- end of option.attlist -->
+  <!-- end of option.module -->
+  <define name="local.optional.attrib">
+    <empty/>
+  </define>
+  <define name="optional.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Optional information. -->
+  <define name="optional">
+    <element name="optional">
+      <ref name="optional.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of optional.element -->
+  <define name="optional.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="optional.role.attrib"/>
+    <ref name="local.optional.attrib"/>
+  </define>
+  <!-- end of optional.attlist -->
+  <!-- end of optional.module -->
+  <define name="local.parameter.attrib">
+    <empty/>
+  </define>
+  <define name="parameter.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A value or a symbolic reference to a value. -->
+  <define name="parameter">
+    <element name="parameter">
+      <ref name="parameter.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of parameter.element -->
+  <!-- Class: Type of the Parameter; no default -->
+  <define name="parameter.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>command</value>
+          <value>function</value>
+          <value>option</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="parameter.role.attrib"/>
+    <ref name="local.parameter.attrib"/>
+  </define>
+  <!-- end of parameter.attlist -->
+  <!-- end of parameter.module -->
+  <define name="local.prompt.attrib">
+    <empty/>
+  </define>
+  <define name="prompt.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A character or string indicating the start of an input field in a  computer display. -->
+  <define name="prompt">
+    <element name="prompt">
+      <ref name="prompt.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="smallcptr.char.mix"/>
+          <ref name="co"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of prompt.element -->
+  <define name="prompt.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="prompt.role.attrib"/>
+    <ref name="local.prompt.attrib"/>
+  </define>
+  <!-- end of prompt.attlist -->
+  <!-- end of prompt.module -->
+  <define name="local.property.attrib">
+    <empty/>
+  </define>
+  <define name="property.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A unit of data associated with some part of a computer system. -->
+  <define name="property">
+    <element name="property">
+      <ref name="property.attlist"/>
+      <zeroOrMore>
+        <ref name="cptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of property.element -->
+  <define name="property.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="property.role.attrib"/>
+    <ref name="local.property.attrib"/>
+  </define>
+  <!-- end of property.attlist -->
+  <!-- end of property.module -->
+  <define name="local.replaceable.attrib">
+    <empty/>
+  </define>
+  <define name="replaceable.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Content that may or must be replaced by the user. -->
+  <define name="replaceable">
+    <element name="replaceable">
+      <ref name="replaceable.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="link.char.class"/>
+          <ref name="optional"/>
+          <ref name="base.char.class"/>
+          <ref name="other.char.class"/>
+          <ref name="inlinegraphic"/>
+          <ref name="inlinemediaobject"/>
+          <ref name="co"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of replaceable.element -->
+  <!--
+    Class: Type of information the element represents; no
+    default
+  -->
+  <define name="replaceable.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>command</value>
+          <value>function</value>
+          <value>option</value>
+          <value>parameter</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="replaceable.role.attrib"/>
+    <ref name="local.replaceable.attrib"/>
+  </define>
+  <!-- end of replaceable.attlist -->
+  <!-- end of replaceable.module -->
+  <define name="local.returnvalue.attrib">
+    <empty/>
+  </define>
+  <define name="returnvalue.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The value returned by a function. -->
+  <define name="returnvalue">
+    <element name="returnvalue">
+      <ref name="returnvalue.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of returnvalue.element -->
+  <define name="returnvalue.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="returnvalue.role.attrib"/>
+    <ref name="local.returnvalue.attrib"/>
+  </define>
+  <!-- end of returnvalue.attlist -->
+  <!-- end of returnvalue.module -->
+  <define name="local.sgmltag.attrib">
+    <empty/>
+  </define>
+  <define name="sgmltag.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A component of SGML markup. -->
+  <define name="sgmltag">
+    <element name="sgmltag">
+      <ref name="sgmltag.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of sgmltag.element -->
+  <!-- Class: Type of SGML construct the element names; no default -->
+  <define name="sgmltag.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>attribute</value>
+          <value>attvalue</value>
+          <value>element</value>
+          <value>endtag</value>
+          <value>emptytag</value>
+          <value>genentity</value>
+          <value>numcharref</value>
+          <value>paramentity</value>
+          <value>pi</value>
+          <value>xmlpi</value>
+          <value>starttag</value>
+          <value>sgmlcomment</value>
+          <value>prefix</value>
+          <value>namespace</value>
+          <value>localname</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="namespace"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="sgmltag.role.attrib"/>
+    <ref name="local.sgmltag.attrib"/>
+  </define>
+  <!-- end of sgmltag.attlist -->
+  <!-- end of sgmltag.module -->
+  <define name="local.structfield.attrib">
+    <empty/>
+  </define>
+  <define name="structfield.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A field in a structure (in the programming language sense). -->
+  <define name="structfield">
+    <element name="structfield">
+      <ref name="structfield.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of structfield.element -->
+  <define name="structfield.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="structfield.role.attrib"/>
+    <ref name="local.structfield.attrib"/>
+  </define>
+  <!-- end of structfield.attlist -->
+  <!-- end of structfield.module -->
+  <define name="local.structname.attrib">
+    <empty/>
+  </define>
+  <define name="structname.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The name of a structure (in the programming language sense). -->
+  <define name="structname">
+    <element name="structname">
+      <ref name="structname.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of structname.element -->
+  <define name="structname.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="structname.role.attrib"/>
+    <ref name="local.structname.attrib"/>
+  </define>
+  <!-- end of structname.attlist -->
+  <!-- end of structname.module -->
+  <define name="local.symbol.attrib">
+    <empty/>
+  </define>
+  <define name="symbol.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A name that is replaced by a value before processing. -->
+  <define name="symbol">
+    <element name="symbol">
+      <ref name="symbol.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of symbol.element -->
+  <!-- Class: Type of symbol; no default -->
+  <define name="symbol.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>limit</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="symbol.role.attrib"/>
+    <ref name="local.symbol.attrib"/>
+  </define>
+  <!-- end of symbol.attlist -->
+  <!-- end of symbol.module -->
+  <define name="local.systemitem.attrib">
+    <empty/>
+  </define>
+  <define name="systemitem.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A system-related item or term. -->
+  <define name="systemitem">
+    <element name="systemitem">
+      <ref name="systemitem.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="cptr.char.mix"/>
+          <ref name="acronym"/>
+          <ref name="co"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of systemitem.element -->
+  <!-- Class: Type of system item the element names; no default -->
+  <define name="systemitem.attlist" combine="interleave">
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>constant</value>
+          <value>daemon</value>
+          <value>domainname</value>
+          <value>etheraddress</value>
+          <value>event</value>
+          <value>eventhandler</value>
+          <value>filesystem</value>
+          <value>fqdomainname</value>
+          <value>groupname</value>
+          <value>ipaddress</value>
+          <value>library</value>
+          <value>macro</value>
+          <value>netmask</value>
+          <value>newsgroup</value>
+          <value>osname</value>
+          <value>protocol</value>
+          <value>resource</value>
+          <value>systemname</value>
+          <value>username</value>
+          <value>process</value>
+          <value>server</value>
+          <value>service</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="systemitem.role.attrib"/>
+    <ref name="local.systemitem.attrib"/>
+  </define>
+  <!-- end of systemitem.attlist -->
+  <!-- end of systemitem.module -->
+  <define name="local.uri.attrib">
+    <empty/>
+  </define>
+  <define name="uri.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A Uniform Resource Identifier. -->
+  <define name="uri">
+    <element name="uri">
+      <ref name="uri.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of uri.element -->
+  <!-- Type: Type of URI; no default -->
+  <define name="uri.attlist" combine="interleave">
+    <optional>
+      <attribute name="type"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="uri.role.attrib"/>
+    <ref name="local.uri.attrib"/>
+  </define>
+  <!-- end of uri.attlist -->
+  <!-- end of uri.module -->
+  <define name="local.token.attrib">
+    <empty/>
+  </define>
+  <define name="token.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A unit of information. -->
+  <define name="token">
+    <element name="token">
+      <ref name="token.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of token.element -->
+  <define name="token.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="token.role.attrib"/>
+    <ref name="local.token.attrib"/>
+  </define>
+  <!-- end of token.attlist -->
+  <!-- end of token.module -->
+  <define name="local.type.attrib">
+    <empty/>
+  </define>
+  <define name="type.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The classification of a value. -->
+  <define name="type">
+    <element name="type">
+      <ref name="type.attlist"/>
+      <zeroOrMore>
+        <ref name="smallcptr.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of type.element -->
+  <define name="type.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="type.role.attrib"/>
+    <ref name="local.type.attrib"/>
+  </define>
+  <!-- end of type.attlist -->
+  <!-- end of type.module -->
+  <define name="local.userinput.attrib">
+    <empty/>
+  </define>
+  <define name="userinput.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Data entered by the user. -->
+  <define name="userinput">
+    <element name="userinput">
+      <ref name="userinput.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="cptr.char.mix"/>
+          <ref name="co"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of userinput.element -->
+  <define name="userinput.attlist" combine="interleave">
+    <ref name="moreinfo.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="userinput.role.attrib"/>
+    <ref name="local.userinput.attrib"/>
+  </define>
+  <!-- end of userinput.attlist -->
+  <!-- end of userinput.module -->
+  <define name="local.termdef.attrib">
+    <empty/>
+  </define>
+  <define name="termdef.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An inline definition of a term. -->
+  <define name="termdef">
+    <element name="termdef">
+      <ref name="termdef.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of termdef.element -->
+  <define name="termdef.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="termdef.role.attrib"/>
+    <ref name="local.termdef.attrib"/>
+  </define>
+  <!-- end of termdef.attlist -->
+  <!-- end of termdef.module -->
+  <!-- General words and phrases ............................................ -->
+  <define name="local.abbrev.attrib">
+    <empty/>
+  </define>
+  <define name="abbrev.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An abbreviation, especially one followed by a period. -->
+  <define name="abbrev">
+    <element name="abbrev">
+      <ref name="abbrev.attlist"/>
+      <zeroOrMore>
+        <ref name="word.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of abbrev.element -->
+  <define name="abbrev.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="abbrev.role.attrib"/>
+    <ref name="local.abbrev.attrib"/>
+  </define>
+  <!-- end of abbrev.attlist -->
+  <!-- end of abbrev.module -->
+  <define name="local.acronym.attrib">
+    <empty/>
+  </define>
+  <define name="acronym.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An often pronounceable word made from the initial (or selected) letters of a name or phrase. -->
+  <define name="acronym">
+    <element name="acronym">
+      <ref name="acronym.attlist"/>
+      <zeroOrMore>
+        <ref name="word.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of acronym.element -->
+  <define name="acronym.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="acronym.role.attrib"/>
+    <ref name="local.acronym.attrib"/>
+  </define>
+  <!-- end of acronym.attlist -->
+  <!-- end of acronym.module -->
+  <define name="local.citation.attrib">
+    <empty/>
+  </define>
+  <define name="citation.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An inline bibliographic reference to another published work. -->
+  <define name="citation">
+    <element name="citation">
+      <ref name="citation.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of citation.element -->
+  <define name="citation.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="citation.role.attrib"/>
+    <ref name="local.citation.attrib"/>
+  </define>
+  <!-- end of citation.attlist -->
+  <!-- end of citation.module -->
+  <define name="local.citerefentry.attrib">
+    <empty/>
+  </define>
+  <define name="citerefentry.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A citation to a reference page. -->
+  <define name="citerefentry">
+    <element name="citerefentry">
+      <ref name="citerefentry.attlist"/>
+      <ref name="refentrytitle"/>
+      <optional>
+        <ref name="manvolnum"/>
+      </optional>
+    </element>
+  </define>
+  <!-- end of citerefentry.element -->
+  <define name="citerefentry.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="citerefentry.role.attrib"/>
+    <ref name="local.citerefentry.attrib"/>
+  </define>
+  <!-- end of citerefentry.attlist -->
+  <!-- end of citerefentry.module -->
+  <define name="local.refentrytitle.attrib">
+    <empty/>
+  </define>
+  <define name="refentrytitle.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The title of a reference page. -->
+  <define name="refentrytitle">
+    <element name="refentrytitle">
+      <ref name="refentrytitle.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of refentrytitle.element -->
+  <define name="refentrytitle.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="refentrytitle.role.attrib"/>
+    <ref name="local.refentrytitle.attrib"/>
+  </define>
+  <!-- end of refentrytitle.attlist -->
+  <!-- end of refentrytitle.module -->
+  <define name="local.manvolnum.attrib">
+    <empty/>
+  </define>
+  <define name="namvolnum.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A reference volume number. -->
+  <define name="manvolnum">
+    <element name="manvolnum">
+      <ref name="manvolnum.attlist"/>
+      <zeroOrMore>
+        <ref name="word.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of manvolnum.element -->
+  <define name="manvolnum.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="namvolnum.role.attrib"/>
+    <ref name="local.manvolnum.attrib"/>
+  </define>
+  <!-- end of manvolnum.attlist -->
+  <!-- end of manvolnum.module -->
+  <define name="local.citetitle.attrib">
+    <empty/>
+  </define>
+  <define name="citetitle.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The title of a cited work. -->
+  <define name="citetitle">
+    <element name="citetitle">
+      <ref name="citetitle.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of citetitle.element -->
+  <!-- Pubwork: Genre of published work cited; no default -->
+  <define name="citetitle.attlist" combine="interleave">
+    <optional>
+      <attribute name="pubwork">
+        <choice>
+          <value>article</value>
+          <value>book</value>
+          <value>chapter</value>
+          <value>part</value>
+          <value>refentry</value>
+          <value>section</value>
+          <value>journal</value>
+          <value>series</value>
+          <value>set</value>
+          <value>manuscript</value>
+          <value>cdrom</value>
+          <value>dvd</value>
+          <value>wiki</value>
+          <value>gopher</value>
+          <value>bbs</value>
+          <value>emailmessage</value>
+          <value>webpage</value>
+          <value>newsposting</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="citetitle.role.attrib"/>
+    <ref name="local.citetitle.attrib"/>
+  </define>
+  <!-- end of citetitle.attlist -->
+  <!-- end of citetitle.module -->
+  <define name="local.emphasis.attrib">
+    <empty/>
+  </define>
+  <define name="emphasis.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Emphasized text. -->
+  <define name="emphasis">
+    <element name="emphasis">
+      <ref name="emphasis.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of emphasis.element -->
+  <define name="emphasis.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="emphasis.role.attrib"/>
+    <ref name="local.emphasis.attrib"/>
+  </define>
+  <!-- end of emphasis.attlist -->
+  <!-- end of emphasis.module -->
+  <define name="local.foreignphrase.attrib">
+    <empty/>
+  </define>
+  <define name="foreignphrase.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A word or phrase in a language other than the primary language of the document. -->
+  <define name="foreignphrase">
+    <element name="foreignphrase">
+      <ref name="foreignphrase.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of foreignphrase.element -->
+  <define name="foreignphrase.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="foreignphrase.role.attrib"/>
+    <ref name="local.foreignphrase.attrib"/>
+  </define>
+  <!-- end of foreignphrase.attlist -->
+  <!-- end of foreignphrase.module -->
+  <define name="local.glossterm.attrib">
+    <empty/>
+  </define>
+  <define name="glossterm.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A glossary term. -->
+  <define name="glossterm">
+    <element name="glossterm">
+      <ref name="glossterm.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of glossterm.element -->
+  <!-- to GlossEntry if Glossterm used in text -->
+  <!--
+    BaseForm: Provides the form of GlossTerm to be used
+    for indexing
+  -->
+  <define name="glossterm.attlist" combine="interleave">
+    <optional>
+      <attribute name="baseform"/>
+    </optional>
+    <ref name="linkend.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="glossterm.role.attrib"/>
+    <ref name="local.glossterm.attrib"/>
+  </define>
+  <!-- end of glossterm.attlist -->
+  <!-- end of glossterm.module -->
+  <define name="local.firstterm.attrib">
+    <empty/>
+  </define>
+  <define name="firstterm.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The first occurrence of a term. -->
+  <define name="firstterm">
+    <element name="firstterm">
+      <ref name="firstterm.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of firstterm.element -->
+  <!-- to GlossEntry or other explanation -->
+  <define name="firstterm.attlist" combine="interleave">
+    <optional>
+      <attribute name="baseform"/>
+    </optional>
+    <ref name="linkend.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="firstterm.role.attrib"/>
+    <ref name="local.firstterm.attrib"/>
+  </define>
+  <!-- end of firstterm.attlist -->
+  <!-- end of firstterm.module -->
+  <define name="local.phrase.attrib">
+    <empty/>
+  </define>
+  <define name="phrase.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A span of text. -->
+  <define name="phrase">
+    <element name="phrase">
+      <ref name="phrase.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of phrase.element -->
+  <define name="phrase.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="phrase.role.attrib"/>
+    <ref name="local.phrase.attrib"/>
+  </define>
+  <!-- end of phrase.attlist -->
+  <!-- end of phrase.module -->
+  <define name="local.quote.attrib">
+    <empty/>
+  </define>
+  <define name="quote.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:An inline quotation. -->
+  <define name="quote">
+    <element name="quote">
+      <ref name="quote.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of quote.element -->
+  <define name="quote.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="quote.role.attrib"/>
+    <ref name="local.quote.attrib"/>
+  </define>
+  <!-- end of quote.attlist -->
+  <!-- end of quote.module -->
+  <define name="local.ssscript.attrib">
+    <empty/>
+  </define>
+  <define name="ssscript.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A subscript (as in H{^2}O, the molecular formula for water). -->
+  <define name="subscript">
+    <element name="subscript">
+      <ref name="subscript.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="link.char.class"/>
+          <ref name="emphasis"/>
+          <ref name="replaceable"/>
+          <ref name="symbol"/>
+          <ref name="inlinegraphic"/>
+          <ref name="inlinemediaobject"/>
+          <ref name="base.char.class"/>
+          <ref name="other.char.class"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of subscript.element -->
+  <define name="subscript.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="ssscript.role.attrib"/>
+    <ref name="local.ssscript.attrib"/>
+  </define>
+  <!-- end of subscript.attlist -->
+  <!-- doc:A superscript (as in x^2, the mathematical notation for x multiplied by itself). -->
+  <define name="superscript">
+    <element name="superscript">
+      <ref name="superscript.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="link.char.class"/>
+          <ref name="emphasis"/>
+          <ref name="replaceable"/>
+          <ref name="symbol"/>
+          <ref name="inlinegraphic"/>
+          <ref name="inlinemediaobject"/>
+          <ref name="base.char.class"/>
+          <ref name="other.char.class"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of superscript.element -->
+  <define name="superscript.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="ssscript.role.attrib"/>
+    <ref name="local.ssscript.attrib"/>
+  </define>
+  <!-- end of superscript.attlist -->
+  <!-- end of ssscript.module -->
+  <define name="local.trademark.attrib">
+    <empty/>
+  </define>
+  <define name="trademark.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A trademark. -->
+  <define name="trademark">
+    <element name="trademark">
+      <ref name="trademark.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <text/>
+          <ref name="link.char.class"/>
+          <ref name="tech.char.class"/>
+          <ref name="base.char.class"/>
+          <ref name="other.char.class"/>
+          <ref name="inlinegraphic"/>
+          <ref name="inlinemediaobject"/>
+          <ref name="emphasis"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of trademark.element -->
+  <!-- Class: More precisely identifies the item the element names -->
+  <define name="trademark.attlist" combine="interleave">
+    <optional>
+      <attribute name="class" a:defaultValue="trade">
+        <choice>
+          <value>service</value>
+          <value>trade</value>
+          <value>registered</value>
+          <value>copyright</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="trademark.role.attrib"/>
+    <ref name="local.trademark.attrib"/>
+  </define>
+  <!-- end of trademark.attlist -->
+  <!-- end of trademark.module -->
+  <define name="local.wordasword.attrib">
+    <empty/>
+  </define>
+  <define name="wordasword.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A word meant specifically as a word and not representing anything else. -->
+  <define name="wordasword">
+    <element name="wordasword">
+      <ref name="wordasword.attlist"/>
+      <zeroOrMore>
+        <ref name="word.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of wordasword.element -->
+  <define name="wordasword.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="wordasword.role.attrib"/>
+    <ref name="local.wordasword.attrib"/>
+  </define>
+  <!-- end of wordasword.attlist -->
+  <!-- end of wordasword.module -->
+  <!-- Links and cross-references ........................................... -->
+  <define name="local.link.attrib">
+    <empty/>
+  </define>
+  <define name="link.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A hypertext link. -->
+  <define name="link">
+    <element name="link">
+      <ref name="link.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of link.element -->
+  <!--
+    Endterm: ID of element containing text that is to be
+    fetched from elsewhere in the document to appear as
+    the content of this element
+  -->
+  <!-- to linked-to object -->
+  <!-- Type: Freely assignable parameter -->
+  <define name="link.attlist" combine="interleave">
+    <optional>
+      <attribute name="endterm">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="xrefstyle"/>
+    </optional>
+    <optional>
+      <attribute name="type"/>
+    </optional>
+    <ref name="linkendreq.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="link.role.attrib"/>
+    <ref name="local.link.attrib"/>
+  </define>
+  <!-- end of link.attlist -->
+  <!-- end of link.module -->
+  <define name="local.olink.attrib">
+    <empty/>
+  </define>
+  <define name="olink.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A link that addresses its target indirectly, through an entity. -->
+  <define name="olink">
+    <element name="olink">
+      <ref name="olink.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of olink.element -->
+  <!-- TargetDocEnt: Name of an entity to be the target of the link -->
+  <!--
+    LinkMode: ID of a ModeSpec containing instructions for
+    operating on the entity named by TargetDocEnt
+  -->
+  <!-- LocalInfo: Information that may be passed to ModeSpec -->
+  <!-- Type: Freely assignable parameter -->
+  <define name="olink.attlist" combine="interleave">
+    <optional>
+      <attribute name="targetdocent">
+        <data type="ENTITY"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="linkmode">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="localinfo"/>
+    </optional>
+    <optional>
+      <attribute name="type"/>
+    </optional>
+    <optional>
+      <attribute name="targetdoc"/>
+    </optional>
+    <optional>
+      <attribute name="targetptr"/>
+    </optional>
+    <optional>
+      <attribute name="xrefstyle"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="olink.role.attrib"/>
+    <ref name="local.olink.attrib"/>
+  </define>
+  <!-- end of olink.attlist -->
+  <!-- end of olink.module -->
+  <define name="local.ulink.attrib">
+    <empty/>
+  </define>
+  <define name="ulink.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A link that addresses its target by means of a URL (Uniform Resource Locator). -->
+  <define name="ulink">
+    <element name="ulink">
+      <ref name="ulink.attlist"/>
+      <zeroOrMore>
+        <ref name="para.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of ulink.element -->
+  <!-- URL: uniform resource locator; the target of the ULink -->
+  <!-- Type: Freely assignable parameter -->
+  <define name="ulink.attlist" combine="interleave">
+    <attribute name="url"/>
+    <optional>
+      <attribute name="type"/>
+    </optional>
+    <optional>
+      <attribute name="xrefstyle"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="ulink.role.attrib"/>
+    <ref name="local.ulink.attrib"/>
+  </define>
+  <!-- end of ulink.attlist -->
+  <!-- end of ulink.module -->
+  <define name="local.footnoteref.attrib">
+    <empty/>
+  </define>
+  <define name="footnoteref.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A cross reference to a footnote (a footnote mark). -->
+  <define name="footnoteref">
+    <element name="footnoteref">
+      <ref name="footnoteref.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of footnoteref.element -->
+  <!-- to footnote content supplied elsewhere -->
+  <define name="footnoteref.attlist" combine="interleave">
+    <ref name="linkendreq.attrib"/>
+    <ref name="label.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="footnoteref.role.attrib"/>
+    <ref name="local.footnoteref.attrib"/>
+  </define>
+  <!-- end of footnoteref.attlist -->
+  <!-- end of footnoteref.module -->
+  <define name="local.xref.attrib">
+    <empty/>
+  </define>
+  <define name="xref.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A cross reference to another part of the document. -->
+  <define name="xref">
+    <element name="xref">
+      <ref name="xref.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of xref.element -->
+  <!--
+    Endterm: ID of element containing text that is to be
+    fetched from elsewhere in the document to appear as
+    the content of this element
+  -->
+  <!-- to linked-to object -->
+  <define name="xref.attlist" combine="interleave">
+    <optional>
+      <attribute name="endterm">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="xrefstyle"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="linkendreq.attrib"/>
+    <ref name="xref.role.attrib"/>
+    <ref name="local.xref.attrib"/>
+  </define>
+  <!-- end of xref.attlist -->
+  <!-- end of xref.module -->
+  <define name="local.biblioref.attrib">
+    <empty/>
+  </define>
+  <define name="biblioref.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A cross reference to a bibliographic entry. -->
+  <define name="biblioref">
+    <element name="biblioref">
+      <ref name="biblioref.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of biblioref.element -->
+  <define name="biblioref.attlist" combine="interleave">
+    <optional>
+      <attribute name="endterm">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="xrefstyle"/>
+    </optional>
+    <optional>
+      <attribute name="units"/>
+    </optional>
+    <optional>
+      <attribute name="begin"/>
+    </optional>
+    <optional>
+      <attribute name="end"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="linkendreq.attrib"/>
+    <ref name="biblioref.role.attrib"/>
+    <ref name="local.biblioref.attrib"/>
+  </define>
+  <!-- end of biblioref.attlist -->
+  <!-- end of biblioref.module -->
+  <!-- Ubiquitous elements .................................................. -->
+  <define name="local.anchor.attrib">
+    <empty/>
+  </define>
+  <define name="anchor.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A spot in the document. -->
+  <define name="anchor">
+    <element name="anchor">
+      <ref name="anchor.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of anchor.element -->
+  <!-- required -->
+  <!-- replaces Lang -->
+  <define name="anchor.attlist" combine="interleave">
+    <ref name="idreq.attrib"/>
+    <ref name="pagenum.attrib"/>
+    <ref name="remap.attrib"/>
+    <ref name="xreflabel.attrib"/>
+    <ref name="revisionflag.attrib"/>
+    <ref name="effectivity.attrib"/>
+    <ref name="anchor.role.attrib"/>
+    <ref name="local.anchor.attrib"/>
+  </define>
+  <!-- end of anchor.attlist -->
+  <!-- end of anchor.module -->
+  <define name="local.beginpage.attrib">
+    <empty/>
+  </define>
+  <define name="beginpage.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The location of a page break in a print version of the document. -->
+  <define name="beginpage">
+    <element name="beginpage">
+      <ref name="beginpage.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- end of beginpage.element -->
+  <!-- PageNum: Number of page that begins at this point -->
+  <define name="beginpage.attlist" combine="interleave">
+    <ref name="pagenum.attrib"/>
+    <ref name="common.attrib"/>
+    <ref name="beginpage.role.attrib"/>
+    <ref name="local.beginpage.attrib"/>
+  </define>
+  <!-- end of beginpage.attlist -->
+  <!-- end of beginpage.module -->
+  <!--
+    IndexTerms appear in the text flow for generating or linking an
+    index.
+  -->
+  <define name="local.indexterm.attrib">
+    <empty/>
+  </define>
+  <define name="indexterm.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:A wrapper for terms to be indexed. -->
+  <define name="indexterm">
+    <element name="indexterm">
+      <ref name="indexterm.attlist"/>
+      <optional>
+        <ref name="primary"/>
+      </optional>
+      <optional>
+        <choice>
+          <group>
+            <ref name="secondary"/>
+            <optional>
+              <choice>
+                <group>
+                  <ref name="tertiary"/>
+                  <optional>
+                    <choice>
+                      <ref name="see"/>
+                      <oneOrMore>
+                        <ref name="seealso"/>
+                      </oneOrMore>
+                    </choice>
+                  </optional>
+                </group>
+                <ref name="see"/>
+                <oneOrMore>
+                  <ref name="seealso"/>
+                </oneOrMore>
+              </choice>
+            </optional>
+          </group>
+          <ref name="see"/>
+          <oneOrMore>
+            <ref name="seealso"/>
+          </oneOrMore>
+        </choice>
+      </optional>
+    </element>
+  </define>
+  <!-- end of indexterm.element -->
+  <!--
+    Scope: Indicates which generated indices the IndexTerm
+    should appear in: Global (whole document set), Local (this
+    document only), or All (both)
+  -->
+  <!--
+    Significance: Whether this IndexTerm is the most pertinent
+    of its series (Preferred) or not (Normal, the default)
+  -->
+  <!--
+    Class: Indicates type of IndexTerm; default is Singular,
+    or EndOfRange if StartRef is supplied; StartOfRange value
+    must be supplied explicitly on starts of ranges
+  -->
+  <!--
+    StartRef: ID of the IndexTerm that starts the indexing
+    range ended by this IndexTerm
+  -->
+  <!--
+    Zone: IDs of the elements to which the IndexTerm applies,
+    and indicates that the IndexTerm applies to those entire
+    elements rather than the point at which the IndexTerm
+    occurs
+  -->
+  <define name="indexterm.attlist" combine="interleave">
+    <ref name="pagenum.attrib"/>
+    <optional>
+      <attribute name="scope">
+        <choice>
+          <value>all</value>
+          <value>global</value>
+          <value>local</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="significance" a:defaultValue="normal">
+        <choice>
+          <value>preferred</value>
+          <value>normal</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="class">
+        <choice>
+          <value>singular</value>
+          <value>startofrange</value>
+          <value>endofrange</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="startref">
+        <data type="IDREF"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="zone">
+        <data type="IDREFS"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="type"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="indexterm.role.attrib"/>
+    <ref name="local.indexterm.attrib"/>
+  </define>
+  <!-- end of indexterm.attlist -->
+  <!-- end of indexterm.module -->
+  <define name="local.primsecter.attrib">
+    <empty/>
+  </define>
+  <define name="primsecter.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:The primary word or phrase under which an index term should be sorted. -->
+  <define name="primary">
+    <element name="primary">
+      <ref name="primary.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of primary.element -->
+  <!--
+    SortAs: Alternate sort string for index sorting, e.g.,
+    "fourteen" for an element containing "14"
+  -->
+  <define name="primary.attlist" combine="interleave">
+    <optional>
+      <attribute name="sortas"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="primsecter.role.attrib"/>
+    <ref name="local.primsecter.attrib"/>
+  </define>
+  <!-- end of primary.attlist -->
+  <!-- doc:A secondary word or phrase in an index term. -->
+  <define name="secondary">
+    <element name="secondary">
+      <ref name="secondary.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of secondary.element -->
+  <!--
+    SortAs: Alternate sort string for index sorting, e.g.,
+    "fourteen" for an element containing "14"
+  -->
+  <define name="secondary.attlist" combine="interleave">
+    <optional>
+      <attribute name="sortas"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="primsecter.role.attrib"/>
+    <ref name="local.primsecter.attrib"/>
+  </define>
+  <!-- end of secondary.attlist -->
+  <!-- doc:A tertiary word or phrase in an index term. -->
+  <define name="tertiary">
+    <element name="tertiary">
+      <ref name="tertiary.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of tertiary.element -->
+  <!--
+    SortAs: Alternate sort string for index sorting, e.g.,
+    "fourteen" for an element containing "14"
+  -->
+  <define name="tertiary.attlist" combine="interleave">
+    <optional>
+      <attribute name="sortas"/>
+    </optional>
+    <ref name="common.attrib"/>
+    <ref name="primsecter.role.attrib"/>
+    <ref name="local.primsecter.attrib"/>
+  </define>
+  <!-- end of tertiary.attlist -->
+  <!-- end of primsecter.module -->
+  <define name="local.seeseealso.attrib">
+    <empty/>
+  </define>
+  <define name="seeseealso.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- doc:Part of an index term directing the reader instead to another entry in the index. -->
+  <define name="see">
+    <element name="see">
+      <ref name="see.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of see.element -->
+  <define name="see.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="seeseealso.role.attrib"/>
+    <ref name="local.seeseealso.attrib"/>
+  </define>
+  <!-- end of see.attlist -->
+  <!-- doc:Part of an index term directing the reader also to another entry in the index. -->
+  <define name="seealso">
+    <element name="seealso">
+      <ref name="seealso.attlist"/>
+      <zeroOrMore>
+        <ref name="ndxterm.char.mix"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- end of seealso.element -->
+  <define name="seealso.attlist" combine="interleave">
+    <ref name="common.attrib"/>
+    <ref name="seeseealso.role.attrib"/>
+    <ref name="local.seeseealso.attrib"/>
+  </define>
+</grammar>
+<!-- end of seealso.attlist -->
+<!-- end of seeseealso.module -->
+<!-- end of indexterm.content.module -->
+<!-- End of DocBook XML information pool module V4.5 ...................... -->
+<!-- ...................................................................... -->
Index: /branches/new-random/doc/src/docbook-rng-4.5/docbook.rnc
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/docbook.rnc	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/docbook.rnc	(revision 13309)
@@ -0,0 +1,499 @@
+# ......................................................................
+
+# DocBook XML DTD V4.5 .................................................
+
+# File docbookx.dtd ....................................................
+
+# Copyright 1992-2006 HaL Computer Systems, Inc.,
+# O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+# Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+# Organization for the Advancement of Structured Information
+# Standards (OASIS).
+# 
+# See also http://docbook.org/specs/
+# 
+# $Id: docbookx.dtd 6340 2006-10-03 13:23:24Z nwalsh $
+# 
+# Permission to use, copy, modify and distribute the DocBook XML DTD
+# and its accompanying documentation for any purpose and without fee
+# is hereby granted in perpetuity, provided that the above copyright
+# notice and this paragraph appear in all copies.  The copyright
+# holders make no representation about the suitability of the DTD for
+# any purpose.  It is provided "as is" without expressed or implied
+# warranty.
+# 
+# If you modify the DocBook DTD in any way, except for declaring and
+# referencing additional sets of general entities and declaring
+# additional notations, label your DTD as a variant of DocBook.  See
+# the maintenance documentation for more information.
+# 
+# Please direct all questions, bug reports, or suggestions for
+# changes to the docbook@lists.oasis-open.org mailing list. For more
+# information, see http://www.oasis-open.org/docbook/.
+
+# ......................................................................
+
+# This is the driver file for V4.5 of the DocBook DTD.
+# Please use the following formal public identifier to identify it:
+# 
+# "-//OASIS//DTD DocBook XML V4.5//EN"
+# 
+# For example, if your document's top-level element is Book, and
+# you are using DocBook directly, use the FPI in the DOCTYPE
+# declaration:
+# 
+# <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+#                "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
+#                [...]>
+# 
+# Or, if you have a higher-level driver file that customizes DocBook,
+# use the FPI in the parameter entity declaration:
+# 
+# <!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+#            "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+# %DocBookDTD;
+# 
+# See the documentation for detailed information on the parameter
+# entity and module scheme used in DocBook, customizing DocBook and
+# planning for interchange, and changes made since the last release
+# of DocBook.
+
+# ......................................................................
+
+# Enable SGML features .................................................
+
+# ......................................................................
+
+# Notation declarations ................................................
+
+include "dbnotnx.rnc"
+# ......................................................................
+
+# ISO character entity sets ............................................
+
+# euro sign, U+20AC NEW
+
+# ......................................................................
+
+# DTD modules ..........................................................
+
+# Information pool ..............
+include "dbpoolx.rnc"
+# Redeclaration placeholder .....
+
+# Document hierarchy ............
+include "dbhierx.rnc"
+start =
+  articleinfo
+  | honorific
+  | legalnotice
+  | procedure
+  | simplelist
+  | keycode
+  | refsynopsisdiv
+  | article
+  | phrase
+  | destructorsynopsis
+  | itemizedlist
+  | audioobject
+  | link
+  | sect1info
+  | xref
+  | glossaryinfo
+  | varname
+  | keywordset
+  | informalequation
+  | toc
+  | pagenums
+  | lot
+  | shortcut
+  | glosslist
+  | option
+  | bibliosource
+  | variablelist
+  | filename
+  | pob
+  | colgroup
+  | foreignphrase
+  | group
+  | substeps
+  | conftitle
+  | textobject
+  | menuchoice
+  | colspec
+  | contractsponsor
+  | tocback
+  | contractnum
+  | constant
+  | dedication
+  | inlineequation
+  | bibliographyinfo
+  | country
+  | glossseealso
+  | bridgehead
+  | mousebutton
+  | surname
+  | stepalternatives
+  | tertiaryie
+  | mediaobject
+  | msgentry
+  | fax
+  | initializer
+  | table
+  | task
+  | setinfo
+  | videodata
+  | bibliodiv
+  | issuenum
+  | phone
+  | state
+  | refsynopsisdivinfo
+  | member
+  | glossentry
+  | term
+  | msgtext
+  | tr
+  | errortype
+  | confdates
+  | inlinegraphic
+  | th
+  | segmentedlist
+  | remark
+  | preface
+  | structname
+  | publisher
+  | td
+  | oointerface
+  | refsection
+  | type
+  | taskrelated
+  | msgrel
+  | artpagenums
+  | bibliomixed
+  | revnumber
+  | firstterm
+  | seeie
+  | spanspec
+  | toclevel5
+  | trademark
+  | toclevel4
+  | toclevel3
+  | toclevel2
+  | indexentry
+  | toclevel1
+  | colophon
+  | methodparam
+  | sidebarinfo
+  | productnumber
+  | funcprototype
+  | inlinemediaobject
+  | refclass
+  | lotentry
+  | paramdef
+  | classsynopsisinfo
+  | qandaset
+  | footnote
+  | msglevel
+  | keysym
+  | citation
+  | simplemsgentry
+  | othercredit
+  | subjectset
+  | keycap
+  | orderedlist
+  | refmiscinfo
+  | blockinfo
+  | programlistingco
+  | abbrev
+  | sidebar
+  | informalfigure
+  | tip
+  | primaryie
+  | appendixinfo
+  | partintro
+  | glossdiv
+  | confgroup
+  | segtitle
+  | taskprerequisites
+  | street
+  | tbody
+  | caption
+  | markup
+  | setindex
+  | msgsub
+  | subscript
+  | orgname
+  | fieldsynopsis
+  | refname
+  | void
+  | sect5
+  | sect4
+  | sect3
+  | chapter
+  | sect2
+  | sect1
+  | modifier
+  | col
+  | orgdiv
+  | city
+  | bibliolist
+  | funcparams
+  | application
+  | \token
+  | imageobject
+  | literal
+  | funcsynopsis
+  | olink
+  | package
+  | collab
+  | seealsoie
+  | primary
+  | glossterm
+  | termdef
+  | area
+  | ackno
+  | function
+  | collabname
+  | lineannotation
+  | guisubmenu
+  | msgexplan
+  | errorname
+  | property
+  | synopfragmentref
+  | refentryinfo
+  | entry
+  | manvolnum
+  | synopsis
+  | emphasis
+  | appendix
+  | bookinfo
+  | contrib
+  | otheraddr
+  | copyright
+  | methodname
+  | email
+  | ooclass
+  | videoobject
+  | abstract
+  | firstname
+  | revremark
+  | glossdef
+  | guibutton
+  | informalexample
+  | screen
+  | errorcode
+  | command
+  | seriesvolnums
+  | refpurpose
+  | parameter
+  | equation
+  | tfoot
+  | code
+  | jobtitle
+  | sgmltag
+  | screenco
+  | holder
+  | isbn
+  | corpcredit
+  | biblioset
+  | part
+  | symbol
+  | row
+  | bibliomisc
+  | imagedata
+  | secondary
+  | classname
+  | callout
+  | screenshot
+  | bibliomset
+  | indexterm
+  | refsect3
+  | tocchap
+  | para
+  | refsect2
+  | refsect1
+  | date
+  | refdescriptor
+  | wordasword
+  | epigraph
+  | audiodata
+  | hardware
+  | confsponsor
+  | authorgroup
+  | warning
+  | authorinitials
+  | medialabel
+  | varlistentry
+  | authorblurb
+  | itermset
+  | refsect3info
+  | informaltable
+  | guimenuitem
+  | postcode
+  | subjectterm
+  | refnamediv
+  | note
+  | figure
+  | envar
+  | listitem
+  | methodsynopsis
+  | affiliation
+  | funcsynopsisinfo
+  | structfield
+  | blockquote
+  | keyword
+  | chapterinfo
+  | tertiary
+  | year
+  | subtitle
+  | personblurb
+  | refentry
+  | citebiblioid
+  | seglistitem
+  | bibliography
+  | msg
+  | constructorsynopsis
+  | refsect2info
+  | volumenum
+  | database
+  | funcdef
+  | uri
+  | graphicco
+  | biblioid
+  | msgmain
+  | printhistory
+  | glosssee
+  | beginpage
+  | glossary
+  | set
+  | highlights
+  | objectinfo
+  | tocpart
+  | guiicon
+  | revhistory
+  | seg
+  | see
+  | msgorig
+  | areaspec
+  | partinfo
+  | index
+  | sectioninfo
+  | refsectioninfo
+  | optional
+  | confnum
+  | replaceable
+  | refsect1info
+  | corpauthor
+  | step
+  | anchor
+  | arg
+  | mathphrase
+  | setindexinfo
+  | keycombo
+  | address
+  | cmdsynopsis
+  | computeroutput
+  | literallayout
+  | qandaentry
+  | sect5info
+  | bibliocoverage
+  | coref
+  | editor
+  | superscript
+  | personname
+  | pubsnumber
+  | graphic
+  | simplesect
+  | accel
+  | secondaryie
+  | biblioref
+  | publishername
+  | bibliorelation
+  | prefaceinfo
+  | revision
+  | screeninfo
+  | sbr
+  | example
+  | citetitle
+  | issn
+  | invpartnumber
+  | indexdiv
+  | sect4info
+  | corpname
+  | lineage
+  | ooexception
+  | reference
+  | revdescription
+  | title
+  | edition
+  | co
+  | msgaud
+  | guimenu
+  | shortaffil
+  | titleabbrev
+  | msginfo
+  | refmeta
+  | qandadiv
+  | mediaobjectco
+  | seealso
+  | exceptionname
+  | answer
+  | programlisting
+  | tgroup
+  | refentrytitle
+  | book
+  | errortext
+  | varargs
+  | sect3info
+  | citerefentry
+  | tasksummary
+  | quote
+  | othername
+  | prompt
+  | entrytbl
+  | interfacename
+  | acronym
+  | modespec
+  | msgset
+  | thead
+  | textdata
+  | userinput
+  | attribution
+  | footnoteref
+  | action
+  | tocentry
+  | tocfront
+  | author
+  | imageobjectco
+  | alt
+  | question
+  | ulink
+  | subject
+  | pubdate
+  | returnvalue
+  | label
+  | caution
+  | section
+  | systemitem
+  | referenceinfo
+  | sect2info
+  | calloutlist
+  | classsynopsis
+  | productname
+  | simpara
+  | synopfragment
+  | important
+  | interface
+  | releaseinfo
+  | formalpara
+  | areaset
+  | biblioentry
+  | indexinfo
+  | guilabel
+# ......................................................................
+
+# Other general entities ...............................................
+
+# End of DocBook XML DTD V4.5 ..........................................
+
+# ......................................................................
Index: /branches/new-random/doc/src/docbook-rng-4.5/docbook.rng
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/docbook.rng	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/docbook.rng	(revision 13309)
@@ -0,0 +1,490 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ...................................................................... -->
+<!-- DocBook XML DTD V4.5 ................................................. -->
+<!-- File docbookx.dtd .................................................... -->
+<!--
+  Copyright 1992-2006 HaL Computer Systems, Inc.,
+  O'Reilly & Associates, Inc., ArborText, Inc., Fujitsu Software
+  Corporation, Norman Walsh, Sun Microsystems, Inc., and the
+  Organization for the Advancement of Structured Information
+  Standards (OASIS).
+  
+  See also http://docbook.org/specs/
+  
+  $Id: docbookx.dtd 6340 2006-10-03 13:23:24Z nwalsh $
+  
+  Permission to use, copy, modify and distribute the DocBook XML DTD
+  and its accompanying documentation for any purpose and without fee
+  is hereby granted in perpetuity, provided that the above copyright
+  notice and this paragraph appear in all copies.  The copyright
+  holders make no representation about the suitability of the DTD for
+  any purpose.  It is provided "as is" without expressed or implied
+  warranty.
+  
+  If you modify the DocBook DTD in any way, except for declaring and
+  referencing additional sets of general entities and declaring
+  additional notations, label your DTD as a variant of DocBook.  See
+  the maintenance documentation for more information.
+  
+  Please direct all questions, bug reports, or suggestions for
+  changes to the docbook@lists.oasis-open.org mailing list. For more
+  information, see http://www.oasis-open.org/docbook/.
+-->
+<!-- ...................................................................... -->
+<!--
+  This is the driver file for V4.5 of the DocBook DTD.
+  Please use the following formal public identifier to identify it:
+  
+  "-//OASIS//DTD DocBook XML V4.5//EN"
+  
+  For example, if your document's top-level element is Book, and
+  you are using DocBook directly, use the FPI in the DOCTYPE
+  declaration:
+  
+  <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+                 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
+                 [...]>
+  
+  Or, if you have a higher-level driver file that customizes DocBook,
+  use the FPI in the parameter entity declaration:
+  
+  <!ENTITY % DocBookDTD PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+             "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+  %DocBookDTD;
+  
+  See the documentation for detailed information on the parameter
+  entity and module scheme used in DocBook, customizing DocBook and
+  planning for interchange, and changes made since the last release
+  of DocBook.
+-->
+<!-- ...................................................................... -->
+<!-- Enable SGML features ................................................. -->
+<!-- ...................................................................... -->
+<!-- Notation declarations ................................................ -->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0">
+  <include href="dbnotnx.rng"/>
+  <!-- ...................................................................... -->
+  <!-- ISO character entity sets ............................................ -->
+  <!-- euro sign, U+20AC NEW -->
+  <!-- ...................................................................... -->
+  <!-- DTD modules .......................................................... -->
+  <!-- Information pool .............. -->
+  <include href="dbpoolx.rng"/>
+  <!-- Redeclaration placeholder ..... -->
+  <!-- Document hierarchy ............ -->
+  <include href="dbhierx.rng"/>
+  <start>
+    <choice>
+      <ref name="articleinfo"/>
+      <ref name="honorific"/>
+      <ref name="legalnotice"/>
+      <ref name="procedure"/>
+      <ref name="simplelist"/>
+      <ref name="keycode"/>
+      <ref name="refsynopsisdiv"/>
+      <ref name="article"/>
+      <ref name="phrase"/>
+      <ref name="destructorsynopsis"/>
+      <ref name="itemizedlist"/>
+      <ref name="audioobject"/>
+      <ref name="link"/>
+      <ref name="sect1info"/>
+      <ref name="xref"/>
+      <ref name="glossaryinfo"/>
+      <ref name="varname"/>
+      <ref name="keywordset"/>
+      <ref name="informalequation"/>
+      <ref name="toc"/>
+      <ref name="pagenums"/>
+      <ref name="lot"/>
+      <ref name="shortcut"/>
+      <ref name="glosslist"/>
+      <ref name="option"/>
+      <ref name="bibliosource"/>
+      <ref name="variablelist"/>
+      <ref name="filename"/>
+      <ref name="pob"/>
+      <ref name="colgroup"/>
+      <ref name="foreignphrase"/>
+      <ref name="group"/>
+      <ref name="substeps"/>
+      <ref name="conftitle"/>
+      <ref name="textobject"/>
+      <ref name="menuchoice"/>
+      <ref name="colspec"/>
+      <ref name="contractsponsor"/>
+      <ref name="tocback"/>
+      <ref name="contractnum"/>
+      <ref name="constant"/>
+      <ref name="dedication"/>
+      <ref name="inlineequation"/>
+      <ref name="bibliographyinfo"/>
+      <ref name="country"/>
+      <ref name="glossseealso"/>
+      <ref name="bridgehead"/>
+      <ref name="mousebutton"/>
+      <ref name="surname"/>
+      <ref name="stepalternatives"/>
+      <ref name="tertiaryie"/>
+      <ref name="mediaobject"/>
+      <ref name="msgentry"/>
+      <ref name="fax"/>
+      <ref name="initializer"/>
+      <ref name="table"/>
+      <ref name="task"/>
+      <ref name="setinfo"/>
+      <ref name="videodata"/>
+      <ref name="bibliodiv"/>
+      <ref name="issuenum"/>
+      <ref name="phone"/>
+      <ref name="state"/>
+      <ref name="refsynopsisdivinfo"/>
+      <ref name="member"/>
+      <ref name="glossentry"/>
+      <ref name="term"/>
+      <ref name="msgtext"/>
+      <ref name="tr"/>
+      <ref name="errortype"/>
+      <ref name="confdates"/>
+      <ref name="inlinegraphic"/>
+      <ref name="th"/>
+      <ref name="segmentedlist"/>
+      <ref name="remark"/>
+      <ref name="preface"/>
+      <ref name="structname"/>
+      <ref name="publisher"/>
+      <ref name="td"/>
+      <ref name="oointerface"/>
+      <ref name="refsection"/>
+      <ref name="type"/>
+      <ref name="taskrelated"/>
+      <ref name="msgrel"/>
+      <ref name="artpagenums"/>
+      <ref name="bibliomixed"/>
+      <ref name="revnumber"/>
+      <ref name="firstterm"/>
+      <ref name="seeie"/>
+      <ref name="spanspec"/>
+      <ref name="toclevel5"/>
+      <ref name="trademark"/>
+      <ref name="toclevel4"/>
+      <ref name="toclevel3"/>
+      <ref name="toclevel2"/>
+      <ref name="indexentry"/>
+      <ref name="toclevel1"/>
+      <ref name="colophon"/>
+      <ref name="methodparam"/>
+      <ref name="sidebarinfo"/>
+      <ref name="productnumber"/>
+      <ref name="funcprototype"/>
+      <ref name="inlinemediaobject"/>
+      <ref name="refclass"/>
+      <ref name="lotentry"/>
+      <ref name="paramdef"/>
+      <ref name="classsynopsisinfo"/>
+      <ref name="qandaset"/>
+      <ref name="footnote"/>
+      <ref name="msglevel"/>
+      <ref name="keysym"/>
+      <ref name="citation"/>
+      <ref name="simplemsgentry"/>
+      <ref name="othercredit"/>
+      <ref name="subjectset"/>
+      <ref name="keycap"/>
+      <ref name="orderedlist"/>
+      <ref name="refmiscinfo"/>
+      <ref name="blockinfo"/>
+      <ref name="programlistingco"/>
+      <ref name="abbrev"/>
+      <ref name="sidebar"/>
+      <ref name="informalfigure"/>
+      <ref name="tip"/>
+      <ref name="primaryie"/>
+      <ref name="appendixinfo"/>
+      <ref name="partintro"/>
+      <ref name="glossdiv"/>
+      <ref name="confgroup"/>
+      <ref name="segtitle"/>
+      <ref name="taskprerequisites"/>
+      <ref name="street"/>
+      <ref name="tbody"/>
+      <ref name="caption"/>
+      <ref name="markup"/>
+      <ref name="setindex"/>
+      <ref name="msgsub"/>
+      <ref name="subscript"/>
+      <ref name="orgname"/>
+      <ref name="fieldsynopsis"/>
+      <ref name="refname"/>
+      <ref name="void"/>
+      <ref name="sect5"/>
+      <ref name="sect4"/>
+      <ref name="sect3"/>
+      <ref name="chapter"/>
+      <ref name="sect2"/>
+      <ref name="sect1"/>
+      <ref name="modifier"/>
+      <ref name="col"/>
+      <ref name="orgdiv"/>
+      <ref name="city"/>
+      <ref name="bibliolist"/>
+      <ref name="funcparams"/>
+      <ref name="application"/>
+      <ref name="token"/>
+      <ref name="imageobject"/>
+      <ref name="literal"/>
+      <ref name="funcsynopsis"/>
+      <ref name="olink"/>
+      <ref name="package"/>
+      <ref name="collab"/>
+      <ref name="seealsoie"/>
+      <ref name="primary"/>
+      <ref name="glossterm"/>
+      <ref name="termdef"/>
+      <ref name="area"/>
+      <ref name="ackno"/>
+      <ref name="function"/>
+      <ref name="collabname"/>
+      <ref name="lineannotation"/>
+      <ref name="guisubmenu"/>
+      <ref name="msgexplan"/>
+      <ref name="errorname"/>
+      <ref name="property"/>
+      <ref name="synopfragmentref"/>
+      <ref name="refentryinfo"/>
+      <ref name="entry"/>
+      <ref name="manvolnum"/>
+      <ref name="synopsis"/>
+      <ref name="emphasis"/>
+      <ref name="appendix"/>
+      <ref name="bookinfo"/>
+      <ref name="contrib"/>
+      <ref name="otheraddr"/>
+      <ref name="copyright"/>
+      <ref name="methodname"/>
+      <ref name="email"/>
+      <ref name="ooclass"/>
+      <ref name="videoobject"/>
+      <ref name="abstract"/>
+      <ref name="firstname"/>
+      <ref name="revremark"/>
+      <ref name="glossdef"/>
+      <ref name="guibutton"/>
+      <ref name="informalexample"/>
+      <ref name="screen"/>
+      <ref name="errorcode"/>
+      <ref name="command"/>
+      <ref name="seriesvolnums"/>
+      <ref name="refpurpose"/>
+      <ref name="parameter"/>
+      <ref name="equation"/>
+      <ref name="tfoot"/>
+      <ref name="code"/>
+      <ref name="jobtitle"/>
+      <ref name="sgmltag"/>
+      <ref name="screenco"/>
+      <ref name="holder"/>
+      <ref name="isbn"/>
+      <ref name="corpcredit"/>
+      <ref name="biblioset"/>
+      <ref name="part"/>
+      <ref name="symbol"/>
+      <ref name="row"/>
+      <ref name="bibliomisc"/>
+      <ref name="imagedata"/>
+      <ref name="secondary"/>
+      <ref name="classname"/>
+      <ref name="callout"/>
+      <ref name="screenshot"/>
+      <ref name="bibliomset"/>
+      <ref name="indexterm"/>
+      <ref name="refsect3"/>
+      <ref name="tocchap"/>
+      <ref name="para"/>
+      <ref name="refsect2"/>
+      <ref name="refsect1"/>
+      <ref name="date"/>
+      <ref name="refdescriptor"/>
+      <ref name="wordasword"/>
+      <ref name="epigraph"/>
+      <ref name="audiodata"/>
+      <ref name="hardware"/>
+      <ref name="confsponsor"/>
+      <ref name="authorgroup"/>
+      <ref name="warning"/>
+      <ref name="authorinitials"/>
+      <ref name="medialabel"/>
+      <ref name="varlistentry"/>
+      <ref name="authorblurb"/>
+      <ref name="itermset"/>
+      <ref name="refsect3info"/>
+      <ref name="informaltable"/>
+      <ref name="guimenuitem"/>
+      <ref name="postcode"/>
+      <ref name="subjectterm"/>
+      <ref name="refnamediv"/>
+      <ref name="note"/>
+      <ref name="figure"/>
+      <ref name="envar"/>
+      <ref name="listitem"/>
+      <ref name="methodsynopsis"/>
+      <ref name="affiliation"/>
+      <ref name="funcsynopsisinfo"/>
+      <ref name="structfield"/>
+      <ref name="blockquote"/>
+      <ref name="keyword"/>
+      <ref name="chapterinfo"/>
+      <ref name="tertiary"/>
+      <ref name="year"/>
+      <ref name="subtitle"/>
+      <ref name="personblurb"/>
+      <ref name="refentry"/>
+      <ref name="citebiblioid"/>
+      <ref name="seglistitem"/>
+      <ref name="bibliography"/>
+      <ref name="msg"/>
+      <ref name="constructorsynopsis"/>
+      <ref name="refsect2info"/>
+      <ref name="volumenum"/>
+      <ref name="database"/>
+      <ref name="funcdef"/>
+      <ref name="uri"/>
+      <ref name="graphicco"/>
+      <ref name="biblioid"/>
+      <ref name="msgmain"/>
+      <ref name="printhistory"/>
+      <ref name="glosssee"/>
+      <ref name="beginpage"/>
+      <ref name="glossary"/>
+      <ref name="set"/>
+      <ref name="highlights"/>
+      <ref name="objectinfo"/>
+      <ref name="tocpart"/>
+      <ref name="guiicon"/>
+      <ref name="revhistory"/>
+      <ref name="seg"/>
+      <ref name="see"/>
+      <ref name="msgorig"/>
+      <ref name="areaspec"/>
+      <ref name="partinfo"/>
+      <ref name="index"/>
+      <ref name="sectioninfo"/>
+      <ref name="refsectioninfo"/>
+      <ref name="optional"/>
+      <ref name="confnum"/>
+      <ref name="replaceable"/>
+      <ref name="refsect1info"/>
+      <ref name="corpauthor"/>
+      <ref name="step"/>
+      <ref name="anchor"/>
+      <ref name="arg"/>
+      <ref name="mathphrase"/>
+      <ref name="setindexinfo"/>
+      <ref name="keycombo"/>
+      <ref name="address"/>
+      <ref name="cmdsynopsis"/>
+      <ref name="computeroutput"/>
+      <ref name="literallayout"/>
+      <ref name="qandaentry"/>
+      <ref name="sect5info"/>
+      <ref name="bibliocoverage"/>
+      <ref name="coref"/>
+      <ref name="editor"/>
+      <ref name="superscript"/>
+      <ref name="personname"/>
+      <ref name="pubsnumber"/>
+      <ref name="graphic"/>
+      <ref name="simplesect"/>
+      <ref name="accel"/>
+      <ref name="secondaryie"/>
+      <ref name="biblioref"/>
+      <ref name="publishername"/>
+      <ref name="bibliorelation"/>
+      <ref name="prefaceinfo"/>
+      <ref name="revision"/>
+      <ref name="screeninfo"/>
+      <ref name="sbr"/>
+      <ref name="example"/>
+      <ref name="citetitle"/>
+      <ref name="issn"/>
+      <ref name="invpartnumber"/>
+      <ref name="indexdiv"/>
+      <ref name="sect4info"/>
+      <ref name="corpname"/>
+      <ref name="lineage"/>
+      <ref name="ooexception"/>
+      <ref name="reference"/>
+      <ref name="revdescription"/>
+      <ref name="title"/>
+      <ref name="edition"/>
+      <ref name="co"/>
+      <ref name="msgaud"/>
+      <ref name="guimenu"/>
+      <ref name="shortaffil"/>
+      <ref name="titleabbrev"/>
+      <ref name="msginfo"/>
+      <ref name="refmeta"/>
+      <ref name="qandadiv"/>
+      <ref name="mediaobjectco"/>
+      <ref name="seealso"/>
+      <ref name="exceptionname"/>
+      <ref name="answer"/>
+      <ref name="programlisting"/>
+      <ref name="tgroup"/>
+      <ref name="refentrytitle"/>
+      <ref name="book"/>
+      <ref name="errortext"/>
+      <ref name="varargs"/>
+      <ref name="sect3info"/>
+      <ref name="citerefentry"/>
+      <ref name="tasksummary"/>
+      <ref name="quote"/>
+      <ref name="othername"/>
+      <ref name="prompt"/>
+      <ref name="entrytbl"/>
+      <ref name="interfacename"/>
+      <ref name="acronym"/>
+      <ref name="modespec"/>
+      <ref name="msgset"/>
+      <ref name="thead"/>
+      <ref name="textdata"/>
+      <ref name="userinput"/>
+      <ref name="attribution"/>
+      <ref name="footnoteref"/>
+      <ref name="action"/>
+      <ref name="tocentry"/>
+      <ref name="tocfront"/>
+      <ref name="author"/>
+      <ref name="imageobjectco"/>
+      <ref name="alt"/>
+      <ref name="question"/>
+      <ref name="ulink"/>
+      <ref name="subject"/>
+      <ref name="pubdate"/>
+      <ref name="returnvalue"/>
+      <ref name="label"/>
+      <ref name="caution"/>
+      <ref name="section"/>
+      <ref name="systemitem"/>
+      <ref name="referenceinfo"/>
+      <ref name="sect2info"/>
+      <ref name="calloutlist"/>
+      <ref name="classsynopsis"/>
+      <ref name="productname"/>
+      <ref name="simpara"/>
+      <ref name="synopfragment"/>
+      <ref name="important"/>
+      <ref name="interface"/>
+      <ref name="releaseinfo"/>
+      <ref name="formalpara"/>
+      <ref name="areaset"/>
+      <ref name="biblioentry"/>
+      <ref name="indexinfo"/>
+      <ref name="guilabel"/>
+    </choice>
+  </start>
+</grammar>
+<!-- ...................................................................... -->
+<!-- Other general entities ............................................... -->
+<!-- End of DocBook XML DTD V4.5 .......................................... -->
+<!-- ...................................................................... -->
Index: /branches/new-random/doc/src/docbook-rng-4.5/htmltblx.rnc
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/htmltblx.rnc	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/htmltblx.rnc	(revision 13309)
@@ -0,0 +1,225 @@
+# ......................................................................
+
+# DocBook XML HTML Table Module V4.5 ...................................
+
+# File htmltblx.mod ....................................................
+
+# Copyright 2003-2006 ArborText, Inc., Norman Walsh, Sun Microsystems,
+# Inc., and the Organization for the Advancement of Structured Information
+# Standards (OASIS).
+# 
+# $Id: htmltblx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+# 
+# Permission to use, copy, modify and distribute the DocBook XML DTD
+# and its accompanying documentation for any purpose and without fee
+# is hereby granted in perpetuity, provided that the above copyright
+# notice and this paragraph appear in all copies.  The copyright
+# holders make no representation about the suitability of the DTD for
+# any purpose.  It is provided "as is" without expressed or implied
+# warranty.
+# 
+# If you modify the DocBook XML DTD in any way, except for declaring and
+# referencing additional sets of general entities and declaring
+# additional notations, label your DTD as a variant of DocBook.  See
+# the maintenance documentation for more information.
+# 
+# Please direct all questions, bug reports, or suggestions for
+# changes to the docbook@lists.oasis-open.org mailing list. For more
+# information, see http://www.oasis-open.org/docbook/.
+
+# ......................................................................
+
+# This module contains the definitions for elements that are
+# isomorphic to the HTML elements. One could argue we should
+# instead have based ourselves on the XHTML Table Module, but the
+# HTML one is more like what browsers are likely to accept today
+# and users are likely to use.
+# 
+# This module has been developed for use with the DocBook V4.5
+# "union table model" in which elements and attlists common to both
+# models are defined (as the union) in the CALS table module by
+# setting various parameter entities appropriately in this file.
+# 
+# In DTD driver files referring to this module, please use an entity
+# declaration that uses the public identifier shown below:
+# 
+# <!ENTITY % htmltbl PUBLIC
+# "-//OASIS//ELEMENTS DocBook XML HTML Tables V4.5//EN"
+# "htmltblx.mod">
+# %htmltbl;
+# 
+# See the documentation for detailed information on the parameter
+# entity and module scheme used in DocBook, customizing DocBook and
+# planning for interchange, and changes made since the last release
+# of DocBook.
+
+# ======================= XHTML Tables =======================================
+
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+html.coreattrs =
+  common.attrib,
+  attribute class { text }?,
+  attribute style { text }?,
+  attribute title { text }?
+# Does not contain lang or dir because they are in %common.attribs
+i18n = attribute xml:lang { xsd:NMTOKEN }?
+events =
+  attribute onclick { text }?,
+  attribute ondblclick { text }?,
+  attribute onmousedown { text }?,
+  attribute onmouseup { text }?,
+  attribute onmouseover { text }?,
+  attribute onmousemove { text }?,
+  attribute onmouseout { text }?,
+  attribute onkeypress { text }?,
+  attribute onkeydown { text }?,
+  attribute onkeyup { text }?
+attrs = html.coreattrs, i18n, events
+cellhalign =
+  attribute align { "left" | "center" | "right" | "justify" | "char" }?,
+  attribute char { text }?,
+  attribute charoff { text }?
+cellvalign =
+  attribute valign { "top" | "middle" | "bottom" | "baseline" }?
+# doc:A group of columns in an HTML table.
+colgroup = element colgroup { colgroup.attlist, col* }
+# doc:Specifications for a column in an HTML table.
+col = element col { col.attlist, empty }
+# doc:A row in an HTML table.
+tr = element tr { tr.attlist, (th | td)+ }
+# doc:A table header entry in an HTML table.
+th =
+  element th {
+    th.attlist, (para.char.mix | tabentry.mix | table | informaltable)*
+  }
+# doc:A table ntry in an HTML table.
+td =
+  element td {
+    td.attlist, (para.char.mix | tabentry.mix | table | informaltable)*
+  }
+colgroup.attlist &=
+  attrs,
+  [ a:defaultValue = "1" ] attribute span { text }?,
+  attribute width { text }?,
+  cellhalign,
+  cellvalign
+col.attlist &=
+  attrs,
+  [ a:defaultValue = "1" ] attribute span { text }?,
+  attribute width { text }?,
+  cellhalign,
+  cellvalign
+tr.attlist &=
+  attrs,
+  cellhalign,
+  cellvalign,
+  attribute bgcolor { text }?
+th.attlist &=
+  attrs,
+  attribute abbr { text }?,
+  attribute axis { text }?,
+  attribute headers { xsd:IDREFS }?,
+  attribute scope { "row" | "col" | "rowgroup" | "colgroup" }?,
+  [ a:defaultValue = "1" ] attribute rowspan { text }?,
+  [ a:defaultValue = "1" ] attribute colspan { text }?,
+  cellhalign,
+  cellvalign,
+  attribute nowrap { "nowrap" }?,
+  attribute bgcolor { text }?,
+  attribute width { text }?,
+  attribute height { text }?
+td.attlist &=
+  attrs,
+  attribute abbr { text }?,
+  attribute axis { text }?,
+  attribute headers { xsd:IDREFS }?,
+  attribute scope { "row" | "col" | "rowgroup" | "colgroup" }?,
+  [ a:defaultValue = "1" ] attribute rowspan { text }?,
+  [ a:defaultValue = "1" ] attribute colspan { text }?,
+  cellhalign,
+  cellvalign,
+  attribute nowrap { "nowrap" }?,
+  attribute bgcolor { text }?,
+  attribute width { text }?,
+  attribute height { text }?
+# ======================================================
+
+# Set up to read in the CALS model configured to
+# merge with the XHTML table model
+
+# ======================================================
+tables.role.attrib = role.attrib
+# Add label and role attributes to table and informaltable
+bodyatt =
+  attribute floatstyle { text }?,
+  attribute rowheader { "firstcol" | "norowheader" }?,
+  label.attrib
+# Add common attributes to Table, TGroup, TBody, THead, TFoot, Row, 
+# EntryTbl, and Entry (and InformalTable element).
+secur =
+  common.attrib,
+  attribute class { text }?,
+  attribute style { text }?,
+  attribute title { text }?,
+  i18n,
+  events,
+  tables.role.attrib
+common.table.attribs = bodyatt, secur
+# Content model for Table (that also allows HTML tables)
+tbl.table.mdl =
+  (blockinfo?,
+   formalobject.title.content,
+   ndxterm.class*,
+   textobject*,
+   (graphic+ | mediaobject+ | tgroup+))
+  | (caption, (col* | colgroup*), thead?, tfoot?, (tbody+ | tr+))
+informal.tbl.table.mdl =
+  (textobject*, (graphic+ | mediaobject+ | tgroup+))
+  | ((col* | colgroup*), thead?, tfoot?, (tbody+ | tr+))
+# Attributes for Table (including HTML ones)
+
+# N.B. rules = (none | groups | rows | cols | all) but it can't be spec'd
+
+# that way because 'all' already occurs in a different enumeration in
+
+# CALS tables (frame).
+tbl.table.att =
+  attribute tabstyle { text }?,
+  attribute tocentry { yesorno.attvals }?,
+  attribute shortentry { yesorno.attvals }?,
+  attribute orient { "port" | "land" }?,
+  attribute pgwide { yesorno.attvals }?,
+  attribute summary { text }?,
+  attribute width { text }?,
+  attribute border { text }?,
+  attribute rules { text }?,
+  attribute cellspacing { text }?,
+  attribute cellpadding { text }?,
+  attribute align { "left" | "center" | "right" }?,
+  attribute bgcolor { text }?
+tbl.frame.attval =
+  "void"
+  | "above"
+  | "below"
+  | "hsides"
+  | "lhs"
+  | "rhs"
+  | "vsides"
+  | "box"
+  | "border"
+  | "top"
+  | "bottom"
+  | "topbot"
+  | "all"
+  | "sides"
+  | "none"
+# Allow either objects or inlines; beware of REs between elements.
+tbl.entry.mdl = para.char.mix | tabentry.mix
+# thead, tfoot, and tbody are defined in both table models,
+# so we set up parameter entities to define union models for them
+tbl.hdft.mdl = tr+ | (colspec*, row+)
+tbl.tbody.mdl = tr+ | row+
+# End of DocBook XML HTML Table Module V4.5 ............................
+
+# ......................................................................
Index: /branches/new-random/doc/src/docbook-rng-4.5/htmltblx.rng
===================================================================
--- /branches/new-random/doc/src/docbook-rng-4.5/htmltblx.rng	(revision 13309)
+++ /branches/new-random/doc/src/docbook-rng-4.5/htmltblx.rng	(revision 13309)
@@ -0,0 +1,590 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ...................................................................... -->
+<!-- DocBook XML HTML Table Module V4.5 ................................... -->
+<!-- File htmltblx.mod .................................................... -->
+<!--
+  Copyright 2003-2006 ArborText, Inc., Norman Walsh, Sun Microsystems,
+  Inc., and the Organization for the Advancement of Structured Information
+  Standards (OASIS).
+  
+  $Id: htmltblx.mod 6340 2006-10-03 13:23:24Z nwalsh $
+  
+  Permission to use, copy, modify and distribute the DocBook XML DTD
+  and its accompanying documentation for any purpose and without fee
+  is hereby granted in perpetuity, provided that the above copyright
+  notice and this paragraph appear in all copies.  The copyright
+  holders make no representation about the suitability of the DTD for
+  any purpose.  It is provided "as is" without expressed or implied
+  warranty.
+  
+  If you modify the DocBook XML DTD in any way, except for declaring and
+  referencing additional sets of general entities and declaring
+  additional notations, label your DTD as a variant of DocBook.  See
+  the maintenance documentation for more information.
+  
+  Please direct all questions, bug reports, or suggestions for
+  changes to the docbook@lists.oasis-open.org mailing list. For more
+  information, see http://www.oasis-open.org/docbook/.
+-->
+<!-- ...................................................................... -->
+<!--
+  This module contains the definitions for elements that are
+  isomorphic to the HTML elements. One could argue we should
+  instead have based ourselves on the XHTML Table Module, but the
+  HTML one is more like what browsers are likely to accept today
+  and users are likely to use.
+  
+  This module has been developed for use with the DocBook V4.5
+  "union table model" in which elements and attlists common to both
+  models are defined (as the union) in the CALS table module by
+  setting various parameter entities appropriately in this file.
+  
+  In DTD driver files referring to this module, please use an entity
+  declaration that uses the public identifier shown below:
+  
+  <!ENTITY % htmltbl PUBLIC
+  "-//OASIS//ELEMENTS DocBook XML HTML Tables V4.5//EN"
+  "htmltblx.mod">
+  %htmltbl;
+  
+  See the documentation for detailed information on the parameter
+  entity and module scheme used in DocBook, customizing DocBook and
+  planning for interchange, and changes made since the last release
+  of DocBook.
+-->
+<!-- ======================= XHTML Tables ======================================= -->
+<grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+  <define name="html.coreattrs">
+    <ref name="common.attrib"/>
+    <optional>
+      <attribute name="class"/>
+    </optional>
+    <optional>
+      <attribute name="style"/>
+    </optional>
+    <optional>
+      <attribute name="title"/>
+    </optional>
+  </define>
+  <!-- Does not contain lang or dir because they are in %common.attribs -->
+  <define name="i18n">
+    <optional>
+      <attribute name="xml:lang">
+        <data type="NMTOKEN"/>
+      </attribute>
+    </optional>
+  </define>
+  <define name="events">
+    <optional>
+      <attribute name="onclick"/>
+    </optional>
+    <optional>
+      <attribute name="ondblclick"/>
+    </optional>
+    <optional>
+      <attribute name="onmousedown"/>
+    </optional>
+    <optional>
+      <attribute name="onmouseup"/>
+    </optional>
+    <optional>
+      <attribute name="onmouseover"/>
+    </optional>
+    <optional>
+      <attribute name="onmousemove"/>
+    </optional>
+    <optional>
+      <attribute name="onmouseout"/>
+    </optional>
+    <optional>
+      <attribute name="onkeypress"/>
+    </optional>
+    <optional>
+      <attribute name="onkeydown"/>
+    </optional>
+    <optional>
+      <attribute name="onkeyup"/>
+    </optional>
+  </define>
+  <define name="attrs">
+    <ref name="html.coreattrs"/>
+    <ref name="i18n"/>
+    <ref name="events"/>
+  </define>
+  <define name="cellhalign">
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>center</value>
+          <value>right</value>
+          <value>justify</value>
+          <value>char</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="char"/>
+    </optional>
+    <optional>
+      <attribute name="charoff"/>
+    </optional>
+  </define>
+  <define name="cellvalign">
+    <optional>
+      <attribute name="valign">
+        <choice>
+          <value>top</value>
+          <value>middle</value>
+          <value>bottom</value>
+          <value>baseline</value>
+        </choice>
+      </attribute>
+    </optional>
+  </define>
+  <!-- doc:A group of columns in an HTML table. -->
+  <define name="colgroup">
+    <element name="colgroup">
+      <ref name="colgroup.attlist"/>
+      <zeroOrMore>
+        <ref name="col"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- doc:Specifications for a column in an HTML table. -->
+  <define name="col">
+    <element name="col">
+      <ref name="col.attlist"/>
+      <empty/>
+    </element>
+  </define>
+  <!-- doc:A row in an HTML table. -->
+  <define name="tr">
+    <element name="tr">
+      <ref name="tr.attlist"/>
+      <oneOrMore>
+        <choice>
+          <ref name="th"/>
+          <ref name="td"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <!-- doc:A table header entry in an HTML table. -->
+  <define name="th">
+    <element name="th">
+      <ref name="th.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="para.char.mix"/>
+          <ref name="tabentry.mix"/>
+          <ref name="table"/>
+          <ref name="informaltable"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <!-- doc:A table ntry in an HTML table. -->
+  <define name="td">
+    <element name="td">
+      <ref name="td.attlist"/>
+      <zeroOrMore>
+        <choice>
+          <ref name="para.char.mix"/>
+          <ref name="tabentry.mix"/>
+          <ref name="table"/>
+          <ref name="informaltable"/>
+        </choice>
+      </zeroOrMore>
+    </element>
+  </define>
+  <define name="colgroup.attlist" combine="interleave">
+    <ref name="attrs"/>
+    <optional>
+      <attribute name="span" a:defaultValue="1"/>
+    </optional>
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <ref name="cellhalign"/>
+    <ref name="cellvalign"/>
+  </define>
+  <define name="col.attlist" combine="interleave">
+    <ref name="attrs"/>
+    <optional>
+      <attribute name="span" a:defaultValue="1"/>
+    </optional>
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <ref name="cellhalign"/>
+    <ref name="cellvalign"/>
+  </define>
+  <define name="tr.attlist" combine="interleave">
+    <ref name="attrs"/>
+    <ref name="cellhalign"/>
+    <ref name="cellvalign"/>
+    <optional>
+      <attribute name="bgcolor"/>
+    </optional>
+  </define>
+  <define name="th.attlist" combine="interleave">
+    <ref name="attrs"/>
+    <optional>
+      <attribute name="abbr"/>
+    </optional>
+    <optional>
+      <attribute name="axis"/>
+    </optional>
+    <optional>
+      <attribute name="headers">
+        <data type="IDREFS"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="scope">
+        <choice>
+          <value>row</value>
+          <value>col</value>
+          <value>rowgroup</value>
+          <value>colgroup</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowspan" a:defaultValue="1"/>
+    </optional>
+    <optional>
+      <attribute name="colspan" a:defaultValue="1"/>
+    </optional>
+    <ref name="cellhalign"/>
+    <ref name="cellvalign"/>
+    <optional>
+      <attribute name="nowrap">
+        <choice>
+          <value>nowrap</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="bgcolor"/>
+    </optional>
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <optional>
+      <attribute name="height"/>
+    </optional>
+  </define>
+  <define name="td.attlist" combine="interleave">
+    <ref name="attrs"/>
+    <optional>
+      <attribute name="abbr"/>
+    </optional>
+    <optional>
+      <attribute name="axis"/>
+    </optional>
+    <optional>
+      <attribute name="headers">
+        <data type="IDREFS"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="scope">
+        <choice>
+          <value>row</value>
+          <value>col</value>
+          <value>rowgroup</value>
+          <value>colgroup</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="rowspan" a:defaultValue="1"/>
+    </optional>
+    <optional>
+      <attribute name="colspan" a:defaultValue="1"/>
+    </optional>
+    <ref name="cellhalign"/>
+    <ref name="cellvalign"/>
+    <optional>
+      <attribute name="nowrap">
+        <choice>
+          <value>nowrap</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="bgcolor"/>
+    </optional>
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <optional>
+      <attribute name="height"/>
+    </optional>
+  </define>
+  <!-- ====================================================== -->
+  <!--
+    Set up to read in the CALS model configured to
+    merge with the XHTML table model
+  -->
+  <!-- ====================================================== -->
+  <define name="tables.role.attrib">
+    <ref name="role.attrib"/>
+  </define>
+  <!-- Add label and role attributes to table and informaltable -->
+  <define name="bodyatt">
+    <optional>
+      <attribute name="floatstyle"/>
+    </optional>
+    <optional>
+      <attribute name="rowheader">
+        <choice>
+          <value>firstcol</value>
+          <value>norowheader</value>
+        </choice>
+      </attribute>
+    </optional>
+    <ref name="label.attrib"/>
+  </define>
+  <!--
+    Add common attributes to Table, TGroup, TBody, THead, TFoot, Row, 
+    EntryTbl, and Entry (and InformalTable element).
+  -->
+  <define name="secur">
+    <ref name="common.attrib"/>
+    <optional>
+      <attribute name="class"/>
+    </optional>
+    <optional>
+      <attribute name="style"/>
+    </optional>
+    <optional>
+      <attribute name="title"/>
+    </optional>
+    <ref name="i18n"/>
+    <ref name="events"/>
+    <ref name="tables.role.attrib"/>
+  </define>
+  <define name="common.table.attribs">
+    <ref name="bodyatt"/>
+    <ref name="secur"/>
+  </define>
+  <!-- Content model for Table (that also allows HTML tables) -->
+  <define name="tbl.table.mdl">
+    <choice>
+      <group>
+        <optional>
+          <ref name="blockinfo"/>
+        </optional>
+        <ref name="formalobject.title.content"/>
+        <zeroOrMore>
+          <ref name="ndxterm.class"/>
+        </zeroOrMore>
+        <zeroOrMore>
+          <ref name="textobject"/>
+        </zeroOrMore>
+        <choice>
+          <oneOrMore>
+            <ref name="graphic"/>
+          </oneOrMore>
+          <oneOrMore>
+            <ref name="mediaobject"/>
+          </oneOrMore>
+          <oneOrMore>
+            <ref name="tgroup"/>
+          </oneOrMore>
+        </choice>
+      </group>
+      <group>
+        <ref name="caption"/>
+        <choice>
+          <zeroOrMore>
+            <ref name="col"/>
+          </zeroOrMore>
+          <zeroOrMore>
+            <ref name="colgroup"/>
+          </zeroOrMore>
+        </choice>
+        <optional>
+          <ref name="thead"/>
+        </optional>
+        <optional>
+          <ref name="tfoot"/>
+        </optional>
+        <choice>
+          <oneOrMore>
+            <ref name="tbody"/>
+          </oneOrMore>
+          <oneOrMore>
+            <ref name="tr"/>
+          </oneOrMore>
+        </choice>
+      </group>
+    </choice>
+  </define>
+  <define name="informal.tbl.table.mdl">
+    <choice>
+      <group>
+        <zeroOrMore>
+          <ref name="textobject"/>
+        </zeroOrMore>
+        <choice>
+          <oneOrMore>
+            <ref name="graphic"/>
+          </oneOrMore>
+          <oneOrMore>
+            <ref name="mediaobject"/>
+          </oneOrMore>
+          <oneOrMore>
+            <ref name="tgroup"/>
+          </oneOrMore>
+        </choice>
+      </group>
+      <group>
+        <choice>
+          <zeroOrMore>
+            <ref name="col"/>
+          </zeroOrMore>
+          <zeroOrMore>
+            <ref name="colgroup"/>
+          </zeroOrMore>
+        </choice>
+        <optional>
+          <ref name="thead"/>
+        </optional>
+        <optional>
+          <ref name="tfoot"/>
+        </optional>
+        <choice>
+          <oneOrMore>
+            <ref name="tbody"/>
+          </oneOrMore>
+          <oneOrMore>
+            <ref name="tr"/>
+          </oneOrMore>
+        </choice>
+      </group>
+    </choice>
+  </define>
+  <!-- Attributes for Table (including HTML ones) -->
+  <!-- N.B. rules = (none | groups | rows | cols | all) but it can't be spec'd -->
+  <!-- that way because 'all' already occurs in a different enumeration in -->
+  <!-- CALS tables (frame). -->
+  <define name="tbl.table.att">
+    <optional>
+      <attribute name="tabstyle"/>
+    </optional>
+    <optional>
+      <attribute name="tocentry">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="shortentry">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="orient">
+        <choice>
+          <value>port</value>
+          <value>land</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="pgwide">
+        <ref name="yesorno.attvals"/>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="summary"/>
+    </optional>
+    <optional>
+      <attribute name="width"/>
+    </optional>
+    <optional>
+      <attribute name="border"/>
+    </optional>
+    <optional>
+      <attribute name="rules"/>
+    </optional>
+    <optional>
+      <attribute name="cellspacing"/>
+    </optional>
+    <optional>
+      <attribute name="cellpadding"/>
+    </optional>
+    <optional>
+      <attribute name="align">
+        <choice>
+          <value>left</value>
+          <value>center</value>
+          <value>right</value>
+        </choice>
+      </attribute>
+    </optional>
+    <optional>
+      <attribute name="bgcolor"/>
+    </optional>
+  </define>
+  <define name="tbl.frame.attval">
+    <choice>
+      <value>void</value>
+      <value>above</value>
+      <value>below</value>
+      <value>hsides</value>
+      <value>lhs</value>
+      <value>rhs</value>
+      <value>vsides</value>
+      <value>box</value>
+      <value>border</value>
+      <value>top</value>
+      <value>bottom</value>
+      <value>topbot</value>
+      <value>all</value>
+      <value>sides</value>
+      <value>none</value>
+    </choice>
+  </define>
+  <!-- Allow either objects or inlines; beware of REs between elements. -->
+  <define name="tbl.entry.mdl">
+    <choice>
+      <ref name="para.char.mix"/>
+      <ref name="tabentry.mix"/>
+    </choice>
+  </define>
+  <!--
+    thead, tfoot, and tbody are defined in both table models,
+    so we set up parameter entities to define union models for them
+  -->
+  <define name="tbl.hdft.mdl">
+    <choice>
+      <oneOrMore>
+        <ref name="tr"/>
+      </oneOrMore>
+      <group>
+        <zeroOrMore>
+          <ref name="colspec"/>
+        </zeroOrMore>
+        <oneOrMore>
+          <ref name="row"/>
+        </oneOrMore>
+      </group>
+    </choice>
+  </define>
+  <define name="tbl.tbody.mdl">
+    <choice>
+      <oneOrMore>
+        <ref name="tr"/>
+      </oneOrMore>
+      <oneOrMore>
+        <ref name="row"/>
+      </oneOrMore>
+    </choice>
+  </define>
+</grammar>
+<!-- End of DocBook XML HTML Table Module V4.5 ............................ -->
+<!-- ...................................................................... -->
Index: /branches/new-random/doc/src/external-process.xml
===================================================================
--- /branches/new-random/doc/src/external-process.xml	(revision 13309)
+++ /branches/new-random/doc/src/external-process.xml	(revision 13309)
@@ -0,0 +1,506 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "Clozure CL">
+]>
+
+  <chapter id="Running-Other-Programs-as-Subprocesses">
+    <title>Running Other Programs as Subprocesses</title>
+
+    <sect1 id="Subprocess-Overview">
+      <title>Overview</title>
+      <para>&CCL; provides primitives to run external Unix programs,
+      to select and connect Lisp streams to their input and output
+      sources, to (optionally) wait for their completion and to check
+      their execution and exit status.</para>
+      <para>All of the global symbols described below are exported
+      from the CCL package.</para>
+      <para>This implementation is modeled on - and uses some code
+      from - similar facilities in CMUCL.</para>
+    </sect1>
+
+    <sect1 id="Subprocess-Examples">
+      <title>Examples</title>
+      <programlisting>
+;;; Capture the output of the "uname" program in a lisp string-stream
+;;; and return the generated string (which will contain a trailing
+;;; newline.)
+? (with-output-to-string (stream)
+    (run-program "uname" '("-r") :output stream))
+;;; Write a string to *STANDARD-OUTPUT*, the hard way.
+? (run-program "cat" () :input (make-string-input-stream "hello") :output t)
+;;; Find out that "ls" doesn't expand wildcards.
+? (run-program "ls" '("*.lisp") :output t)
+;;; Let the shell expand wildcards.
+? (run-program "sh" '("-c" "ls *.lisp") :output t)
+</programlisting>
+      <para>These last examples will only produce output if &CCL;'s
+      current directory contains .lisp files, of course.</para>
+    </sect1>
+
+    <sect1 id="Limitations-and-known-bugs">
+      <title>Limitations and known bugs</title>
+      <itemizedlist>
+        <listitem><para>&CCL; and the external process may get
+        confused about who owns which streams when input, output, or
+        error are specified as T and wait is specified as
+        NIL.</para></listitem>
+        <listitem><para>External processes that need to talk to a
+        terminal device may not work properly; the environment (SLIME,
+        ILISP) under which &CCL; is run can affect
+        this.</para></listitem>
+      
+      </itemizedlist>
+    </sect1>
+
+    <sect1 id="External-Program-Dictionary">
+      <title>External-Program Dictionary</title>
+	<refentry id="f_run-program">
+	  <indexterm zone="f_run-program">
+	    <primary>run-program</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>RUN-PROGRAM</refname>
+	    <refpurpose>Invokes an external program as an OS subprocess
+	    of lisp.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>run-program</function>
+	    program args &key; (wait t) pty sharing input
+	    if-input-does-not-exist output (if-output-exists :error) (error
+	    :output) (if-error-exists :error) status-hook
+	    external-format</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		<term>program</term>
+
+		<listitem>
+		  <para>A string or pathname which denotes an executable file.
+		  The PATH environment variable is used to find programs whose
+		  name doesn't contain a directory component.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>args</term>
+
+		<listitem>
+		  <para>A list of simple-strings</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>wait</term>
+
+		<listitem>
+		  <para>Indicates whether or not run-program should wait for
+		  the EXTERNAL-PROCESS to complete or should return
+		  immediately.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>pty</term>
+
+		<listitem>
+		  <para>This option is accepted but currently ignored;
+		  it's intended to make it easier to run external programs
+		  that need to interact with a terminal device.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>sharing</term>
+
+		<listitem>
+                  <para>Sets a specific sharing mode
+                  (see <xref linkend="Stream-SHARING"/>) for any streams created
+                  within RUN-PROGRAM when INPUT, OUTPUT or ERROR are requested
+                  to be a :STREAM.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>input</term>
+
+		<listitem>
+		  <para>Selects the input source used by the EXTERNAL-PROCESS.
+		  May be any of the following:</para>
+
+		  <itemizedlist>
+		    <listitem>
+		      <para>NIL Specifies that a null input stream (e.g.,
+		      /dev/null) should be used.</para>
+		    </listitem>
+
+		    <listitem>
+		      <para>T Specifies that the EXTERNAL-PROCESS should use
+		      the input source with which &CCL; was invoked.</para>
+		    </listitem>
+
+		    <listitem>
+		      <para>A string or pathname. Specifies that the
+		      EXTERNAL-PROCESS should receive its input from the named
+		      existing file.</para>
+		    </listitem>
+
+		    <listitem>
+		      <para>:STREAM Creates a Lisp stream opened for character
+		      output. Any data written to this stream (accessible as
+		      the EXTERNAL-PROCESS-INPUT-STREAM of the
+		      EXTERNAL-PROCESS object) appears as input to the
+		      external process.</para>
+		    </listitem>
+
+		    <listitem>
+		      <para>A stream. Specifies that the lisp stream should
+		      provide input to the EXTERNAL-PROCESS.</para>
+		    </listitem>
+		  </itemizedlist>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>if-input-does-not-exist</term>
+
+		<listitem>
+		  <para>If the input argument specifies the name of an
+		  existing file, this argument is used as the
+		  if-does-not-exist argument to OPEN when that file is opened.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>output</term>
+
+		<listitem>
+		  <para>Specifies where standard output from the external
+		  process should be sent. Analogous to input above.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>if-output-exists</term>
+
+		<listitem>
+		  <para>If output is specified as a string or pathname, this
+		  argument is used as the if-exists argument to OPEN when that
+		  file is opened.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>error</term>
+
+		<listitem>
+		  <para>Specifies where error output from the external process
+		  should be sent. In addition to the values allowed for
+		  output, the keyword :OUTPUT can be used to indicate that
+		  error output should be sent where standard output goes.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>if-error-exists</term>
+
+		<listitem>
+		  <para>Analogous to if-output-exists.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>status-hook</term>
+
+		<listitem>
+		  <para>A user-defined function of one argument (the
+		  EXTERNAL-PROCESS structure.) This function is called
+		  whenever &CCL; detects a change in the status of the
+		  EXTERNAL-PROCESS.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>external-format</term>
+
+		<listitem>
+		  <para>
+		    The external format (see <xref
+		    linkend="External-Formats"/>) for all of the
+		    streams (input, output, and error) used to
+		    communicate with the external process.
+		  </para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Runs the specified program in an external (Unix) process,
+	    returning an object of type EXTERNAL-PROCESS if successful.</para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="f_signal-external-process">
+	  <indexterm zone="f_signal-external-process">
+	    <primary>signal-external-process</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>SIGNAL-EXTERNAL-PROCESS</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>signal-external-process</function>
+	    proc signal-number</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		<term>proc</term>
+
+		<listitem>
+		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
+		</listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		<term>signal</term>
+
+		<listitem>
+		  <para>A small integer.</para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Sends the specified "signal" to the specified
+	    external process. (Typically, it would only be useful to call
+	    this function if the EXTERNAL-PROCESS was created with :WAIT
+	    NIL. ) Returns T if successful; signals an error otherwise.</para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="f_external-process-id">
+	  <indexterm zone="f_external-process-id">
+	    <primary>external-process-id</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>EXTERNAL-PROCESS-ID</refname>
+	    <refpurpose>Returns the "process ID" of an OS subprocess,
+	    a positive integer which identifies it.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>external-process-id</function>
+	    proc</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		<term>proc</term>
+
+		<listitem>
+		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Returns the <emphasis>process id</emphasis> assigned to
+	    the external process by the operating system. This is typically
+	    a positive, 16-bit number.</para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="f_external-process-input-stream">
+	  <indexterm zone="f_external-process-input-stream">
+	    <primary>external-process-input-stream</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>EXTERNAL-PROCESS-INPUT-STREAM</refname>
+	    <refpurpose>Returns the lisp stream which is used to write
+	    input to a given OS subprocess, if it has one.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>external-process-input-stream</function>
+	    proc</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		<term>proc</term>
+
+		<listitem>
+		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Returns the stream created when the input argument to
+	    run-program is specified as :STREAM.</para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="f_external-process-output-stream">
+	  <indexterm zone="f_external-process-output-stream">
+	    <primary>external-process-output-stream</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>EXTERNAL-PROCESS-OUTPUT-STREAM</refname>
+	    <refpurpose>Returns the lisp stream which is used to read
+	    output from an OS subprocess, if there is one.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>external-process-output-stream</function>
+	    proc</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		<term>proc</term>
+
+		<listitem>
+		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Returns the stream created when the output argument to
+	    run-program is specified as :STREAM.</para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="f_external-process-error-stream">
+	  <indexterm zone="f_external-process-error-stream">
+	    <primary>external-process-error-stream</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>EXTERNAL-PROCESS-ERROR-STREAM</refname>
+	    <refpurpose>Returns the stream which is used to read
+	    "error" output from a given OS subprocess, if it has
+	    one.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>external-process-error-stream</function>
+	    proc</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		<term>proc</term>
+
+		<listitem>
+		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Returns the stream created when the error argument to
+	    run-program is specified as :STREAM.</para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="f_external-process-status">
+	  <indexterm zone="f_external-process-status">
+	    <primary>external-process-status</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>EXTERNAL-PROCESS-STATUS</refname>
+	    <refpurpose>Returns information about whether an OS
+	    subprocess is running; or, if not, why not; and what its
+	    result code was if it completed.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>external-process-status</function>
+	    proc</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		<term>proc</term>
+
+		<listitem>
+		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
+		</listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Returns, as multiple values, a keyword denoting the status
+	    of the external process (one of :running, :stopped, :signaled, or
+	    :exited), and the exit code or terminating signal if the first
+	    value is other than :running.</para>
+	  </refsect1>
+	</refentry>
+    </sect1>
+  </chapter>
Index: /branches/new-random/doc/src/ffi.xml
===================================================================
--- /branches/new-random/doc/src/ffi.xml	(revision 13309)
+++ /branches/new-random/doc/src/ffi.xml	(revision 13309)
@@ -0,0 +1,4569 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "<literal>CCL</literal>">
+          ]>
+
+<chapter id="The-Foreign-Function-Interface">
+  <title>The Foreign-Function Interface</title>
+  
+  <!-- ******************************************  -->
+  <sect1 id="Specifying-And-Using-Foreign-Types">
+    <title>Specifying And Using Foreign Types</title>
+    
+    <sect2 id="Overview-foreign-types">
+      <title>Overview</title>
+      <para>&CCL; provides a fairly rich language for defining and
+        specifying foreign data types (this language is derived from
+        CMUCL's "alien type" system.)</para>
+      <para>In practice, most foreign type definitions are
+        introduced into &CCL; via its interface database (see ),
+        though it's also possible to define foreign types
+        interactively and/or programmatically.</para>
+      <para>&CCL;'s foreign type system is "evolving" (a polite word
+        for not-quite-complete): there are some inconsistencies
+        involving package usage, for instance. Symbols used in foreign
+        type specifiers <emphasis>should</emphasis> be keywords, but
+        this convention isn't always enforced.</para> <para>Foreign
+        type, record, and field names are case-sensitive; &CCL; uses
+        some escaping conventions (see ) to allow keywords to be used to
+        denote these names.</para>
+
+      <sect3 id="type-annotations">
+        <title>Type Annotations</title>
+        <para>As of version 1.2, &CCL; supports annotating the types of
+          foreign pointers on Mac OS X. Forms that create pointers to
+          foreign memory&mdash;that is, <code>MACPTR</code>s&mdash;store
+          with the <code>MACPTR</code> object a type annotation that
+          identifies the foreign type of the object pointed
+          to. Calling <code>PRINT-OBJECT</code> on a <code>MACPTR</code>
+          attempts to print information about the identified foreign
+          type, including whether it was allocated on the heap or the
+          stack, and whether it's scheduled for automatic reclamation by
+          the garbage collector.</para>
+
+        <para>Support for type annotation is not yet complete. In
+          particular, some uses of <code>PREF</code>
+          and <code>SLOT-VALUE</code> do ot yet take type annotations into
+          account, and neither do <code>DESCRIBE</code>
+          and <code>INSPECT</code>.</para>
+      </sect3>
+
+      <sect3 id="foreign-type-classes">
+        <title>Foreign Types as Classes</title>
+        <para>Some types of foreign pointers take advantage of the
+          support for type annotations, and pointers of these types
+          can be treated as instances of known classes. Specifically,
+          a pointer to an <code>:&lt;NSR&gt;ect</code> is recognized
+          as an instance of the built-in
+          class <code>NS:NS-RECT</code>, a pointer to
+          an <code>&lt;NSS&gt;ize</code> is treated as an instance
+          of <code>NS:NS-SIZE</code>, a pointer to
+          an <code>&lt;NSP&gt;oint</code> is recognized as an
+          instance of <code>NS:NS-POINT</code>, and a pointer to
+          an <code>&lt;NSR&gt;ange</code> is recognized as an
+          instance of <code>NS:NS-RANGE</code>.</para>
+
+        <para>A few more obscure structure types also support this
+        mechanism, and it's possible that a future version will
+        support user definition of similar type mappings.</para>
+
+        <para>This support for foreign types as classes provides the
+        following conveniences for each supported type:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>a <code>PRINT-OBJECT</code> method is defined</para>
+        </listitem>
+        <listitem>
+          <para>a foreign type name is created and treated as an alias
+          for the corresponding type. As an example, the
+          name <code>:NS-RECT</code> is a name for the type that
+          corresponds to <code>NS:NS-RECT</code>, and you can
+          use <code>:NS-RECT</code> as a type designator
+          in <link linkend="anchor_rlet"><code>RLET</code></link> forms to
+          specify a structure of type <code>NS-RECT</code>.</para>
+        </listitem>
+        <listitem>
+          <para>the class is integrated into the type system so that
+            <code>(TYPEP R 'NS:NS-RECT)</code> is implemented with
+            fair efficiency.</para>
+        </listitem>
+        <listitem>
+          <para>inlined accessor and <code>SETF</code> inverses are
+            defined for the structure type's fields.  In the case of
+            an <code>&lt;NSR*gt;ect</code>, for example, the fields in
+            question are the fields of the embedded point and size, so
+            that <code>NS:NS-RECT-X</code>, <code>NS:NS-RECT-Y</code>, <code>NS:NS-RECT-WIDTH</code>,
+            <code>NS-RECT-HEIGHT</code> and <code>SETF</code> inverses
+            are defined.  The accessors and setter functions typecheck
+            their arguments and the setters handle coercion to the
+            appropriate type of <code>CGFLOAT</code> where
+            applicable.</para>
+        </listitem>
+        <listitem>
+          <para>an initialization function is defined; for
+            example,</para> 
+
+          <programlisting>
+(NS:INIT-NS-SIZE s w h)
+          </programlisting>
+
+          <para>is roughly equivalent to</para>
+
+          <programlisting>
+(SETF (NS:NS-SIZE-WIDTH s) w
+      (NS:NS-SIZE-HEIGHT s) h)
+          </programlisting>
+
+          <para>but might be a little more efficient.</para>
+        </listitem>
+        <listitem>
+          <para>a creation function is defined; for
+            example</para>
+
+          <programlisting>
+(NS:NS-MAKE-POINT x y)
+          </programlisting> 
+
+          <para>is functionally equivalent to</para>
+
+          <programlisting>
+(LET ((P (MAKE-GCABLE-RECORD :NS-POINT)))
+  (NS:INIT-NS-POINT P X Y)
+  p)
+          </programlisting>
+
+        </listitem>
+        <listitem>
+          <para>a macro is defined which, like <code>RLET</code>,
+            stack-allocates an instance of the foreign record type,
+            optionally initializes that instance, and executes a body
+            of code with a variable bound to that instance.</para>
+
+          <para>For example,</para>
+          <programlisting>
+(ns:with-ns-range (r loc len)
+  (format t "~&amp; range has location ~s, length ~s" 
+     (ns:ns-range-location r) (ns:ns-range-length r)))
+          </programlisting>
+        </listitem>
+        <listitem>
+          <para></para>
+        </listitem>
+      </itemizedlist>
+      </sect3>
+
+    </sect2>
+
+    <sect2 id="Syntax-of-Foreign-Type-Specifiers">
+      <title>Syntax of Foreign Type Specifiers</title>
+      <itemizedlist>
+        <listitem>
+          <para>Some foreign types are builtin: keywords denote
+            primitive,builtin types such as the IEEE-double-float type
+            (denoted:DOUBLE-FLOAT), in much the same way as certain
+            symbols(CONS, FIXNUM,etc.) define primitive CL
+            types.</para>
+        </listitem>
+        <listitem>
+          <para>Constructors such as :SIGNED and :UNSIGNED can be
+            used to denote signed and unsigned integer subtypes
+            (analogous to the CL type specifiers SIGNED-BYTE and
+            UNSIGNED-BYTE.) :SIGNED is shorthand for(:SIGNED 32) and
+            :UNSIGNED is shorthand for (:UNSIGNED 32).</para>
+        </listitem>
+        <listitem>
+          <para>Aliases for other (perhaps more complicated) types
+            can be defined via CCL:DEF-FOREIGN-TYPE (sort of like
+            CL:DEFTYPE or the C typedef facility). The type :CHAR is
+            defined as an alias for (:SIGNED8) on some platforms, as
+            (:UNSIGNED 8) on others.</para>
+	    </listitem>
+        <listitem>
+	      <para>The construct (:STRUCT <emphasis>name</emphasis>)
+	        can be used to refer to a named structure type; (:UNION
+	        <emphasis>name</emphasis>)can be used to refer to a named
+	        union type. It isn't necessary to enumerate a structure or
+	        union type's fields in order to refer to the type.</para>
+	    </listitem>
+        <listitem>
+	      <para>If <emphasis>X</emphasis> is a valid foreign type
+	        reference,then (:* <emphasis>X</emphasis>) denotes the
+	        foreign type "pointer to<emphasis> X</emphasis>". By
+	        convention, (:* T) denotes an anonymous pointer type,
+	        vaguely equivalent to "void*" in C.</para>
+	    </listitem>
+        <listitem>
+	      <para>If a fieldlist is a list of lists, each of whose CAR
+	        is a foreign field name (keyword) and whose CADR is a
+	        foreign type specifier, then (:STRUCT
+	        <emphasis>name</emphasis> ,@fieldlist) is a definition of
+	        the structure type <emphasis>name</emphasis>,
+	        and (:UNION<emphasis> name</emphasis> ,@fieldlist) is a
+	        definition of the union type
+	        <emphasis>name</emphasis>. Note that it's necessary
+	        to define a structure or union type in order to include
+	        that type in a structure, union, or array, but only
+	        necessary to "refer to" a structure or union type in order
+	        to define a type alias or a pointer type.</para>
+	    </listitem>
+	    <listitem>
+	      <para>If <emphasis>X</emphasis> is a defined foreign type
+	        , then (:array <emphasis>X</emphasis> &amp;rest dims)
+	        denotes the foreign type "array of
+	        <emphasis>X</emphasis>". Although multiple array dimensions
+	        are allowed by the :array constructor,
+	        only single-dimensioned arrays are (at all) well-supported
+	        in &CCL;.</para>
+	    </listitem>
+      </itemizedlist>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Foreign-Function-Calls">
+    <title>Foreign Function Calls</title>
+
+    <sect2 id="Overview-foreign-calls">
+	  <title>Overview</title>
+      <para>&CCL; provides a number of constructs for calling
+        foreign functions from Lisp code (all of them based on the
+        function CCL:%FF-CALL).  In many cases, &CCL;'s interface
+        translator (see ) provides information about the foreign
+        function's entrypoint name and argument and return types; this
+        enables the use of the #_ reader macro (described below),
+        which may be more concise and/or more readable than other
+        constructs.</para>
+      <para>&CCL; also provides a mechanism for defining
+        <emphasis>callbacks</emphasis>: lisp functions which can be
+        called from foreign code.</para>
+      <para>There's no supported way to directly pass lisp data to
+        foreign functions: scalar lisp data must be coerced to an
+        equivalent foreign representation, and lisp arrays (notably
+        strings) must be copied to non-GCed memory.</para>
+
+      <sect3 id="Type-Designators-for-Arguments-and-Return-Values">
+	    <title>Type Designators for Arguments and Return Values</title>
+        <para>The types of foreign argument and return values in foreign
+	      function calls and callbacks can be specified by any of the following
+          keywords:</para>
+	    <variablelist>
+	      <varlistentry>
+	        <term>:UNSIGNED-BYTE</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (UNSIGNED-BYTE 8)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:SIGNED-BYTE</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (SIGNED-BYTE 8)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:UNSIGNED-HALFWORD</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (UNSIGNED-BYTE 16)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:SIGNED-HALFWORD</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (SIGNED-BYTE 16)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:UNSIGNED-FULLWORD</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (UNSIGNED-BYTE 32)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:SIGNED-FULLWORD</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (SIGNED-BYTE 32)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:UNSIGNED-DOUBLEWORD</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (UNSIGNED-BYTE 64)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:SIGNED-DOUBLEWORD</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type (SIGNED-BYTE 64)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:SINGLE-FLOAT</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type SINGLE-FLOAT</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:DOUBLE-FLOAT</term>
+
+	        <listitem>
+		      <para>The argument/return value is of type DOUBLE-FLOAT</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:ADDRESS</term>
+
+	        <listitem>
+		      <para>The argument/return values
+		        is <link linkend="Referencing-and-Using-Foreign-Memory-Addresses">a MACPTR</link>.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>:VOID</term>
+
+	        <listitem>
+		      <para>or NIL Not valid as an argument type specifier; specifies
+		        that there is no meaningful return value</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+
+        <para>On some platforms, a small positive integer
+          <emphasis>N</emphasis> can also be used as an argument
+          specifier; it indicates that the corresponding argument is a
+          pointer to an <emphasis>N</emphasis>-word structure or union
+          which should be passed by value to the foreign
+          function.  Exactly which foreign structures are passed
+	      by value and how is very dependent on the Application
+	      Binary Interface (ABI) of the platform; unless you're
+	      very familiar with ABI details (some of which are quite
+	      baroque), it's often easier to let higher-level constructs
+	      deal with these details.</para>
+      </sect3>
+
+      <sect3 id="External-Entrypoints-and-Named-External-Entrypoints">
+	    <title>External Entrypoints and Named External Entrypoints</title>
+        <para>PowerPC machine instructions are always aligned on
+          32-bit boundaries, so the two least significant bits of the
+          first instruction ("entrypoint") of a foreign function are
+          always 0. &CCL; often represents an entrypoint address as
+          a fixnum that's binary-equivalent to the entrypoint address:
+          if<emphasis> E</emphasis> is an entrypoint address expressed
+          as a signed 32-bit integer, then (ash <emphasis>E</emphasis>
+          -2) is an equivalent fixnum representation of that
+          address. An entrypoint address can also be encapsulated in a
+          MACPTR (see FIXTHIS), but that's somewhat less efficient.</para>
+        <para>Although it's possible to use fixnums or macptrs to
+          represent entrypoint addresses, it's somewhat cumbersome to
+          do so. &CCL; can cache the addresses of named external
+          functions in structure-like objects of type
+          CCL:EXTERNAL-ENTRY-POINT (sometimes abbreviated as EEP).
+          Through the use of LOAD-TIME-VALUE, compiled lisp functions
+          are able to reference EEPs as constants; the use of an
+          indirection allows &CCL; runtime system to ensure that the
+          EEP's address is current and correct.</para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="Return-Conventions-for-C-Structures">
+	  <title>Return Conventions for C Structures</title>
+      <para> On some platforms, C functions that are defined to
+        return structures do so by reference: they actually
+        accept a first parameter of type "pointer to returned
+        struct/union" - which must be allocated by the caller - and
+        don't return a meaningful value.</para>
+	  <para><emphasis>Exactly</emphasis> how a C function that's
+	    defined to return a foreign structure does so is dependent on
+	    the ABI (and on the size and composition of the structure/union
+	    in many cases.)</para>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Referencing-and-Using-Foreign-Memory-Addresses">
+    <title>Referencing and Using Foreign Memory Addresses</title>
+
+    <sect2 id="Overview-memory-addresses">
+      <title>Overview</title>
+
+      <sect3 id="Basics">
+	    <title>Basics</title>
+        <para>For a variety of technical reasons, it isn't generally
+          possible to directly reference arbitrary absolute addresses
+          (such as those returned by the C library function malloc(),
+          for instance) in &CCL;. In &CCL; (and in MCL), such
+          addresses need to be <emphasis>encapsulated</emphasis> in
+          objects of type CCL:MACPTR; one can think of a MACPTR as
+          being a specialized type of structure whose sole purpose is
+          to provide a way of referring to an underlying "raw"
+          address.</para>
+        <para>It's sometimes convenient to blur the distinction
+          between a MACPTR and the address it represents; it's
+          sometimes necessary to maintain that distinction. It's
+          important to remember that a MACPTR is (generally) a
+          first-class Lisp object in the same sense that a CONS cell
+          is: it'll get GCed when it's no longer possible to reference
+          it. The "lifetime" of a MACPTR doesn't generally have
+          anything to do with the lifetime of the block of memory its
+          address points to.</para>
+        <para>It might be tempting to ask "How does one obtain the
+          address encapsulated by a MACPTR ?". The answer to that
+          question is that one doesn't do that (and there's no way to
+          do that): addresses aren't first-class objects, and there's
+          no way to refer to one.</para>
+        <para>Two MACPTRs that encapsulate the same address are EQL
+          to each other.</para>
+        <para>There are a small number of ways to directly create a
+          MACPTR (and there's a fair amount of syntactic sugar built
+          on top of of those primitives.) These primitives will be
+          discussed in greater detail below, but they include:</para>
+
+	    <itemizedlist>
+          <listitem>
+	        <para>Creating a MACPTR with a specified address, usually
+	          via the function CCL:%INT-TO-PTR.</para>
+	      </listitem>
+          <listitem>
+	        <para>Referencing the return value of a foreign function
+	          call (see )that's specified to return an address.</para>
+	      </listitem>
+          <listitem>
+	        <para>Referencing a memory location that's specified to
+	          contain an address.</para>
+	      </listitem>
+	    </itemizedlist>
+
+        <para>All of these primitive MACPTR-creating operations are
+          usually open-coded by the compiler; it has a fairly good
+          notion of what low-level operations "produce" MACPTRs and
+          which operations "consume" the addresses that the
+          encapsulate, and will usually optimize out the introduction
+          of intermediate MACPTRs in a simple expression.</para>
+        <para>One consequence of the use of MACPTR objects to
+          encapsulate foreign addresses is that (naively)
+          <emphasis>every reference to a foreign address causes a
+            MACPTR to be allocated.</emphasis></para>
+        <para>Consider a code fragment like the following:</para>
+        <programlisting>
+(defun get-next-event ()
+  "get the next event from a hypothetical window system"
+  (loop
+     (let* ((event (#_get_next_window_system_event))) ; via an FF-CALL
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </programlisting>
+        <para>As this is written, each call to the (hypothetical)
+          foreign function #_get_next_window_system_event will return
+          a new MACPTR object.  Ignoring for the sake of argument the
+          question of whether this code fragment exhibits a good way
+          to poll for external events (it doesn't), it's not hard to
+          imagine that this loop could execute several million times
+          per second (producing several million MACPTRs per second.)
+          Clearly, the "naive" approach is impractical in many
+          cases.</para>
+      </sect3>
+
+      <sect3 id="Stack-allocation-of---and-destructive-operations-on---MACPTRs-">
+        <title>Stack allocation of&mdash;and destructive operations on&mdash;MACPTRs.</title>
+	    <para>If certain conditions held in the environment in which
+	      GET-NEXT-EVENT ran&mdash;namely, if it was guaranteed that
+	      neither NULL-EVENT-P nor HANDLE-EVENT cached or otherwise
+	      retained their arguments (the "event" pointer)&mdash;there'd be
+	      a few alternatives to the naive approach. One of those
+	      approaches would be to use the primitive function
+	      %SETF-MACPTR (described in greater detail below) to
+	      destructively modify a MACPTR (to change the value of the
+	      address it encapsulates.) The GET-NEXT-EVENT example could
+	      be re-written as:</para>
+        <programlisting>
+(defun get-next-event ()
+  (let* ((event (%int-to-ptr 0)))     ; create a MACPTR with address 0
+    (loop
+       (%setf-macptr event (#_get_next_window_system_event)) ; re-use it
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </programlisting>
+        <para>That version's a bit more realistic: it allocates a
+          single MACPTR outside if the loop, then changes its address
+          to point to the current address of the hypothetical event
+          structure on each loop iteration. If there are a million
+          loop iterations per call to GET-NEXT-EVENT, we're allocating
+          a million times fewer MACPTRs per call; that sounds like a
+          Good Thing.</para>
+        <para>An Even Better Thing would be to advise the compiler
+          that the initial value (the null MACPTR) bound to the
+          variable event has dynamic extent (that value won't be
+          referenced once control leaves the extent of the binding of
+          that variable.) Common Lisp allows us to make such an
+          assertion via a DYNAMIC-EXTENT declaration; &CCL;'s
+          compiler can recognize the "primitive MACPTR-creating
+          operation" involved and can replace it with an equivalent
+          operation that stack-allocates the MACPTR object. If we're
+          not worried about the cost of allocating that MACPTR on
+          every iteration (the cost is small and there's no hidden GC
+          cost), we could move the binding back inside the
+          loop:</para>
+        <programlisting>
+(defun get-next-event ()
+  (loop
+     (let* ((event (%null-ptr))) ; (%NULL-PTR) is shorthand for (%INT-TO-PTR 0)
+       (declare (dynamic-extent event))
+       (%setf-macptr event (#_get_next_window_system_event))
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </programlisting>
+        <para>The idiom of binding one or more variables to
+          stack-allocated MACPTRs, then destructively modifying those
+          MACPTRs before executing a body of code is common enough
+          that &CCL; provides a macro (WITH-MACPTRS) that handles
+          all of the gory details. The following version of
+          GET-NEXT-EVENT is semantically equivalent to the previous
+          version, but hopefully a bit more concise:</para>
+        <programlisting>
+(defun get-next-event ()
+  (loop
+     (with-macptrs ((event (#_get_next_window_system_event)))
+       (unless (null-event-p event)
+         (handle-event event)))))
+        </programlisting>
+      </sect3>
+
+      <sect3 id="Stack-allocated-memory--and-stack-allocated-pointers-to-it--">
+        <title>Stack-allocated memory (and stack-allocated pointers to it.)</title>
+	    <para>Fairly often, the blocks of foreign memory (obtained
+	      by malloc or something similar) have well-defined lifetimes
+	      (they can safely be freed at some point when it's known that
+	      they're no longer needed and it's known that they're no
+	      longer referenced.) A common idiom might be:</para>
+        <programlisting>
+(with-macptrs (p (#_allocate_foreign_memory size))
+  (unwind-protect
+       (use-foreign-memory p)
+    (#_deallocate_foreign_memory p)))
+        </programlisting>
+        <para>That's not unreasonable code, but it's fairly
+          expensive for a number of reasons: foreign functions calls
+          are themselves fairly expensive (as is UNWIND-PROTECT), and
+          most library routines for allocating and deallocating
+          foreign memory (things like malloc and free) can be fairly
+          expensive in their own right.</para>
+        <para>In the idiomatic code above, both the MACPTR P and the
+          block of memory that's being allocated and freed have
+          dynamic extent and are therefore good candidates for stack
+          allocation. &CCL; provides the %STACK-BLOCK macro, which
+          executes a body of code with one or more variables bound to
+          stack-allocated MACPTRs which encapsulate the addresses of
+          stack-allocated blocks of foreign memory. Using
+          %STACK-BLOCK, the idiomatic code is:</para>
+        <programlisting>
+(%stack-block ((p size))
+              (use-foreign-memory p))
+        </programlisting>
+        <para>which is a bit more efficient and a bit more concise
+          than the version presented earlier.</para>
+        <para>%STACK-BLOCK is used as the basis for slightly
+          higher-level things like RLET. (See FIXTHIS for more information
+          about RLET.)</para>
+      </sect3>
+
+      <sect3 id="Caveats-">
+	    <title>Caveats</title>
+        <para>Reading from, writing to, allocating, and freeing
+          foreign memory are all potentially dangerous operations;
+          this is no less true when these operations are performed in
+          &CCL; than when they're done in C or some other
+          lower-level language. In addition, destructive operations on
+          Lisp objects be dangerous, as can stack allocation if it's
+          abused (if DYNAMIC-EXTENT declarations are violated.)
+          Correct use of the constructs and primitives described here
+          is reliable and safe; slightly incorrect use of these
+          constructs and primitives can crash &CCL;.</para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="Foreign-Memory-Addresses-Dictionary">
+	  <title>Foreign-Memory-Addresses Dictionary</title>
+      <para>Unless otherwise noted, all of the symbols mentioned
+        below are exported from the CCL package.</para>
+
+      <sect3 id="Scalar-memory-reference">
+        <title>Scalar memory reference</title>
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%get-signed-byte ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-unsigned-byte ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-signed-word ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-unsigned-word ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-signed-long ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-unsigned-long ptr &#38;optional (offset 0)</para>
+
+		      <para>%%get-signed-longlong ptr &#38;optional (offset 0)</para>
+
+		      <para>%%get-unsigned-longlong ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-ptr ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-single-float ptr &#38;optional (offset 0)</para>
+
+		      <para>%get-double-float ptr &#38;optional (offset 0)</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>References and returns the signed or unsigned 8-bit byte,
+		        signed or unsigned 16-bit word, signed or unsigned 32-bit long
+		        word, signed or unsigned 64-bit long long word, 32-bit address,
+		        32-bit single-float, or 64-bit double-float at the effective byte
+		        address formed by adding offset to the address encapsulated by
+		        ptr.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>offset</term>
+
+		          <listitem>
+		            <para>A fixnum</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+
+        <para>All of the memory reference primitives described above can be</para>
+        <para>used with SETF.</para>
+      </sect3>
+
+      <sect3 id="iget-bit--Function-">
+	    <title>%get-bit [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%get-bit ptr bit-offset</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>References and returns the bit-offsetth bit at the address
+		        encapsulated by ptr. (Bit 0 at a given address is the most
+		        significant bit of the byte at that address.) Can be used with
+		        SETF.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>bit-offset</term>
+
+		          <listitem>
+		            <para>A fixnum</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+      </sect3>
+
+      <sect3 id="iget-bitfield--Function-">
+        <title>%get-bitfield [Function]</title>
+ 	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%get-bitfield ptr bit-offset width</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>References and returns an unsigned integer composed from the
+		        width bits found bit-offset bits from the address encapsulated by
+		        ptr. (The least significant bit of the result is the value of
+		        (%get-bit ptr (1- (+ bit-offset width))). Can be used with SETF.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>ptr</term>
+
+	        <listitem>
+		      <para>A MACPTR</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>bit-offset</term>
+
+		          <listitem>
+		            <para>A fixnum</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>width</term>
+
+		          <listitem>
+		            <para>A positive fixnum</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+      </sect3>
+
+	  <sect3>
+	    <title>%int-to-ptr [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%int-to-ptr int</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Creates and returns a MACPTR whose address matches int.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>int</term>
+
+		          <listitem>
+		            <para>An (unsigned-byte 32)</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%inc-ptr [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%inc-ptr ptr &#38;optional (delta 1)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Creates and returns a MACPTR whose address is the address of
+		        ptr plus delta. The idiom (%inc-ptr ptr 0) is sometimes used to
+		        copy a MACPTR, e.g., to create a new MACPTR encapsulating the same
+		        address as ptr.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>delta</term>
+
+		          <listitem>
+		            <para>A fixnum</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%ptr-to-int [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%ptr-to-int ptr</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Returns the address encapsulated by ptr, as an
+		        (unsigned-byte 32).</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%null-ptr [Macro]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%null-ptr</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Equivalent to (%int-to-ptr 0).</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%null-ptr-p [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%null-ptr-p ptr</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Returns T If ptr is a MACPTR encapsulating the address 0,
+		        NIL if ptr encapsulates some other address.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%setf-macptr [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%setf-macptr dest-ptr src-ptr</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Causes dest-ptr to encapsulate the same address that src-ptr
+		        does, then returns dest-ptr.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>dest-ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>src-ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%incf-ptr [Macro]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%incf-ptr ptr &#38;optional (delta 1)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Destructively modifies ptr, by adding delta to the address
+		        it encapsulates. Returns ptr.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>delta</term>
+
+		          <listitem>
+		            <para>A fixnum</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>with-macptrs [Macro]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>with-macptrs (var expr)* &#38;body body</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Executes body in an environment in which each var is bound
+		        to a stack-allocated macptr which encapsulates the foreign address
+		        yielded by the corresponding expr. Returns whatever value(s) body
+		        returns.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>var</term>
+
+		          <listitem>
+		            <para>A symbol (variable name)</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>expr</term>
+
+		          <listitem>
+		            <para>A MACPTR-valued expression</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%stack-block [Macro]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%stack-block (var expr)* &#38;body body</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Executes body in an environment in which each var is bound
+		        to a stack-allocated macptr which encapsulates the address of a
+		        stack-allocated region of size expr bytes. Returns whatever
+		        value(s) body returns.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>var</term>
+
+		          <listitem>
+		            <para>A symbol (variable name)</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>expr</term>
+
+		          <listitem>
+		            <para>An expression which should evaluate to a non-negative
+		              fixnum</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>make-cstring [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+		    <term>Syntax</term>
+
+		    <listitem>
+		      <para>make-cstring string</para>
+		    </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		    <term>Description</term>
+
+		    <listitem>
+		      <para>Allocates a block of memory (via malloc) of length (1+
+		        (length string)). Copies the string to this block and appends a
+		        trailing NUL byte; returns a MACPTR to the block.</para>
+		    </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+		    <term>Arguments</term>
+
+		    <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>string</term>
+
+		          <listitem>
+			        <para>A lisp string</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+		    </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>with-cstrs [Macro]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>with-cstrs (var string)* &#38;body body</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Executes body in an environment in which each var is bound
+		        to a stack-allocated macptr which encapsulates the %address of a
+		        stack-allocated region of into which each string (and a trailing
+		        NUL byte) has been copied. Returns whatever value(s) body returns.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>var</term>
+
+		          <listitem>
+		            <para>A symbol (variable name)</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>string</term>
+
+		          <listitem>
+		            <para>An expression which should evaluate to a lisp string</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+      <sect3>
+        <title>with-encoded-cstrs [Macro]</title>
+
+        <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>with-encoded-cstrs ENCODING-NAME (varI stringI)* &#38;body body</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Executes body in an environment in which each varI is
+		        bound to a macptr which encapsulates the %address of a
+		        stack-allocated region of into which each stringI (and a
+		        trailing NUL character) has been copied. Returns whatever
+		        value(s) body returns.</para>
+
+              <para>ENCODING-NAME is a keyword constant that names a
+                character encoding. Each foreign string is encoded in the
+                named encoding. Each foreign string has dynamic
+                extent.</para>
+
+              <para>WITH-ENCODED-CSTRS does not automatically prepend
+                byte-order marks to its output; the size of the terminating
+                #\NUL character depends on the number of octets per code unit
+                in the encoding.</para>
+
+              <para>The expression</para>
+
+              <programlisting>(ccl:with-cstrs ((x "x")) (#_puts x))</programlisting>
+
+              <para>is functionally equivalent to</para>
+
+              <programlisting>(ccl:with-encoded-cstrs :iso-8859-1 ((x "x")) (#_puts x))</programlisting>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para>&#x00A0;</para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>varI</term>
+
+		          <listitem>
+		            <para>A symbol (variable name)</para>
+		          </listitem>
+		        </varlistentry>
+
+		        <varlistentry>
+		          <term>stringI</term>
+
+		          <listitem>
+		            <para>An expression which should evaluate to a lisp string</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+        </variablelist>
+      </sect3>
+
+	  <sect3>
+	    <title>%get-cstring [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%get-cstring ptr</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Interprets ptr as a pointer to a (NUL -terminated) C string;
+		        returns an equivalent lisp string.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para></para>
+
+		      <variablelist>
+		        <varlistentry>
+		          <term>ptr</term>
+
+		          <listitem>
+		            <para>A MACPTR</para>
+		          </listitem>
+		        </varlistentry>
+		      </variablelist>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+
+	  <sect3>
+	    <title>%str-from-ptr [Function]</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>Syntax</term>
+
+	        <listitem>
+		      <para>%str-from-ptr ptr length</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Description</term>
+
+	        <listitem>
+		      <para>Returns a lisp string of length <varname>length</varname>,
+		        whose contents are initialized from the bytes at<varname> ptr.</varname>
+		      </para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>Arguments</term>
+
+	        <listitem>
+		      <para><variablelist><varlistentry><term>ptr</term><listitem><para>A
+		                MACPTR</para></listitem></varlistentry><varlistentry><term>length</term><listitem><para>a
+		                non-negative fixnum</para></listitem></varlistentry></variablelist></para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </sect3>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="The-Interface-Database">
+    <title>The Interface Database</title>
+
+    <sect2 id="interface-database-Overview">
+	  <title>Overview</title>
+      <para>&CCL; uses a set of database files which contain
+        foreign type, record, constant, and function definitions
+        derived from the operating system's header files, be that
+        Linux or Darwin.  An archive containing these database files
+        (and the shell scripts which were used in their creation) is
+        available; see the Distributions page for information about
+        obtaining current interface database files.</para>
+      <para>Not surprisingly, different platforms use different database files.</para>
+      <para>&CCL; defines reader macros that consult these databases:</para>
+	  <itemizedlist>
+        <listitem>
+	      <para>#$foo looks up the value of the constant definition of foo</para>
+	    </listitem>
+	    <listitem>
+	      <para>#_foo looks up the foreign function definition for foo</para>
+	    </listitem>
+        
+      </itemizedlist>
+      <para>In both cases, the symbol foo is interned in the "OS"
+        package. The #$ reader macro has the side-effect of defining
+        foo as a constant (as if via DEFCONSTANT); the #_ reader macro
+        has the side effect of defining foo as a macro which will
+        expand into an (EXTERNAL-CALL form.)</para>
+      <para>It's important to remember that the side-effect happens
+        when the form containing the reader macro is
+        read. Macroexpansion functions that expand into forms which
+        contain instances of those reader macros don't do what one
+        might think that they do, unless the macros are expanded in
+        the same lisp session as the reader macro was read in.</para>
+      <para>In addition, references to foreign type,
+        structure/union, and field names (when used in the RREF/PREF
+        and RLET macros) will cause these database files to be
+        consulted.</para>
+      <para>Since the &CCL; sources contain instances of these
+        reader macros (and references to foreign record types and
+        fields), compiling &CCL; from those sources depends on the
+        ability to find and use (see <xref
+                                        linkend="Building-the-heap-image"/>).</para>
+    </sect2>
+
+    <sect2 id="Other-issues">
+      <title>Other issues:</title>
+      <itemizedlist>
+        <listitem>
+	      <para>&CCL; now preserves the case of external symbols in
+	        its database
+	        files. See <link linkend="Case-sensitivity-of-foreign-names-in-CCL">Case-sensitivity
+	        of foreign names in &CCL;</link> for information about
+	        case in foreign symbol names.</para>
+	    </listitem>
+	    <listitem>
+	      <para>The Linux databases are derived from a somewhat
+	        arbitrary set of Linux header files. Linux is enough of a
+	        moving target that it may be difficult to define a standard,
+	        reference set of interfaces from which to derive a standard,
+	        reference set of database files.This seems to be less of
+	        an issue with Darwin and FreeBSD.</para>
+	    </listitem>
+	  </itemizedlist>
+      <para>For information about building the database files,
+	    see <xref linkend="The-Interface-Translator"/>.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Using-Interface-Directories">
+    <title>Using Interface Directories</title>
+
+    <sect2 id="Interface-Directory-Overview">
+	  <title>Overview</title>
+      <para>As distributed, the "ccl:headers;" (for LinuxPPC)
+        directory is organized like:</para>
+      <programlisting>
+        headers/
+        headers/gl/
+        headers/gl/C/
+        headers/gl/C/populate.sh
+        headers/gl/constants.cdb
+        headers/gl/functions.cdb
+        headers/gl/records.cdb
+        headers/gl/objc-classes.cdb
+        headers/gl/objc-methods.cdb
+        headers/gl/types.cdb
+        headers/gnome/
+        headers/gnome/C/
+        headers/gnome/C/populate.sh
+        headers/gnome/constants.cdb
+        headers/gnome/functions.cdb
+        headers/gnome/records.cdb
+        headers/gnome/objc-classes.cdb
+        headers/gnome/objc-methods.cdb
+        headers/gnome/types.cdb
+        headers/gtk/
+        headers/gtk/C/
+        headers/gtk/C/populate.sh
+        headers/gtk/constants.cdb
+        headers/gtk/functions.cdb
+        headers/gtk/records.cdb
+        headers/gtk/objc-classes.cdb
+        headers/gtk/objc-methods.cdb
+        headers/gtk/types.cdb
+        headers/libc/
+        headers/libc/C/
+        headers/libc/C/populate.sh
+        headers/libc/constants.cdb
+        headers/libc/functions.cdb
+        headers/libc/records.cdb
+        headers/libc/objc-classes.cdb
+        headers/libc/objc-methods.cdb
+        headers/libc/types.cdb
+      </programlisting>
+      <para>e.g, as a set of parallel subdirectories, each with a
+        lowercase name and each of which contains a set of 6 database
+        files and a "C" subdirectory which contains a shell script
+        used in the database creation process.</para>
+      <para>As one might assume, the database files in each of these
+        subdirectories contain foreign type, constant, and function
+        definitions - as well as Objective-C class and method info -that
+        correspond (roughly) to the information contained in the
+        header files associated with a "-dev" package in a Linux
+        distribution.  "libc" corresponds pretty closely to the
+        interfaces associated with "glibc/libc6" header files, "gl"
+        corresponds to an "openGL+GLUT" development package, "gtk"
+        and "gnome" contain interface information from the GTK+1.2 and
+        GNOME libraries, respectively.</para>
+      <para>For Darwin, the "ccl:darwin-headers" directory contains
+        a "libc" subdirectory, whose contents roughly correspond to
+        those of "/usr/include" under Darwin, as well as
+        subdirectories corresponding to the MacOSX Carbon and Cocoa
+        frameworks.</para>
+      <para>To see the precise set of .h files used to generate the
+        database files in a given interface directory, consult the
+        corresponding "populate.sh" shell script (in the interface
+        directory's "C" subdirectory.)</para>
+      <para>The intent is that this initial set can be augmented to
+        meet local needs, and that this can be done in a fairly
+        incremental fashion: one needn't have unrelated header files
+        installed in order to generate interface databases for a
+        package of interest.</para>
+      <para>Hopefully, this scheme will also make it easier to
+        distribute patches and bug fixes.</para>
+      <para>&CCL; maintains a list of directories; when looking
+        for a foreign type, constant, function, or record definition,
+        it'll consult the database files in each directory on that
+        list. Initially, the list contains an entry for the "libc"
+        interface directory. &CCL; needs to be explicitly told to
+        look in other interface directories should it need to do
+        so.</para>
+    </sect2>
+
+    <sect2 id="Creating-new-interface-directories">
+	  <title>Creating new interface directories</title>
+      <para>This example refers to "ccl:headers;", which is
+        appropriate for LinuxPPC. The procedure's analogous under
+        Darwin, where the "ccl:darwin-headers;" directory would be
+        used instead.</para>
+      <para>To create a new interface directory, "foo", and a set of
+        database files in that directory:</para>
+	  <orderedlist continuation="restarts" inheritnum="ignore">
+	    <listitem>
+	      <para>Create a subdirectory of &#34;ccl:headers;&#34; named
+	        &#34;foo&#34;.</para>
+	    </listitem>
+
+	    <listitem>
+	      <para>Create a subdirectory of &#34;ccl:headers;foo;&#34; named
+	        &#34;C&#34;.</para>
+	    </listitem>
+
+	    <listitem>
+	      <para>Create a file in &#34;ccl:headers;foo;C;&#34; named
+	        &#34;populate.sh&#34;.</para>
+
+	      <para>One way of accomplishing the above steps is:</para>
+
+	      <programlisting format="linespecific">
+            ? (close (open &#34;ccl:headers;foo;C;populate.sh&#34; :direction :output :
+                           if-does-not-exist :create :if-exists :overwrite))
+          </programlisting>
+	    </listitem>
+
+	    <listitem>
+	      <para>Edit the file created above, using the &#34;populate.sh&#34;
+	        files in the distribution as guidelines.</para>
+
+	      <para>The file might wind up looking something like:</para>
+
+	      <programlisting format="linespecific">#/bin/sh
+            h-to-ffi.sh `foo-config -cflags` /usr/include/foo/foo.h</programlisting>
+	    </listitem>
+	  </orderedlist>
+
+      <para>Refer to <xref linkend="The-Interface-Translator"/> for
+        information about running the interface translator and .ffi
+        parser.</para>
+      <para>Assuming that all went well, there should now be .cdb
+        files in "ccl:headers;foo;". You can then do
+        <programlisting>
+          ? (use-interface-dir :foo)
+	    </programlisting> 
+	    whenever you need to
+        access the foreign type information in those database
+        files.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Using-Shared-Libraries">
+    <title>Using Shared Libraries</title>
+
+    <sect2 id="Shared-Library-Overview">
+	  <title>Overview</title>
+
+      <para>&CCL; provides facilities to open and close shared
+        libraries.</para>
+      <para>"Opening" a shared library, which is done with <xref
+                                                              linkend="f_open-shared-library"/>, maps the library's code and
+        data into &CCL;'s address space and makes its exported
+        symbols accessible to &CCL;.</para>
+      <para>"Closing" a shared library, which is done with <xref
+                                                              linkend="f_close-shared-library"/>, unmaps the library's code
+        and and removes the library's symbols from the global
+        namespace.</para>
+      <para>A small number of shared libraries (including libc,
+        libm, libdl under Linux, and the "system" library under
+        Darwin) are opened by the lisp kernel and can't be
+        closed.</para>
+      <para>&CCL; uses data structures of type
+        EXTERNAL-ENTRY-POINT to map a foreign function name (string)
+        to that foreign function's <emphasis>current</emphasis>
+        address. (A function's address may vary from session to
+        session as different versions of shared libraries may load at
+        different addresses; it may vary within a session for similar
+        reasons.)</para>
+      <para>An EXTERNAL-ENTRY-POINT whose address is known is said
+        to be <emphasis>resolved</emphasis>. When an external entry
+        point is resolved, the shared library which defines that entry
+        point is noted; when a shared library is closed, the entry
+        points that it defines are made unresolved.  An
+        EXTERNAL-ENTRY-POINT must be in the resolved state in order to
+        be FF-CALLed; calling an unresolved entry point causes a "last
+        chance" attempt to resolve it. Attempting to resolve an
+        entrypoint that was defined in a closed library will cause an
+        attempt to reopen that library.</para>
+      <para>&CCL; keeps track of all libraries that have been
+        opened in a lisp session. When a saved application is first
+        started, an attempt is made to reopen all libraries that were
+        open when the image was saved, and an attempt is made to
+        resolve all entry points that had been referenced when the
+        image was saved. Either of these attempts can fail "quietly",
+        leaving some entry points in an unresolved state.</para>
+      <para>Linux shared libraries can be referred to either by a
+        string which describes their full pathname or by their
+        <emphasis>soname</emphasis>, a shorter string that can be
+        defined when the library is created. The dynamic linker
+        mechanisms used in Linux make it possible (through a series of
+        filesystem links and other means) to refer to a library via
+        several names; the library's soname is often the most
+        appropriate identifier.</para>
+      <para>so names are often less version-specific than other names
+        for libraries; a program that refers to a library by the name
+        "libc.so.6" is more portable than one which refers to
+        "libc-2.1.3.so" or to "libc-2.2.3.so", even though the latter
+        two names might each be platform-specific aliases of the
+        first.</para>
+      <para>All of the global symbols described below are exported
+        from the CCL package.</para>
+    </sect2>
+
+    <sect2 id="Limitations-and-known-bugs--1-">
+      <title>Limitations and known bugs</title>
+	  <itemizedlist>
+        <listitem>
+	      <para>Don't get me started.</para>
+	    </listitem>
+        <listitem>
+	      <para>The underlying functionality has a poor notion of
+	        dependency;it's not always possible to open libraries that
+	        depend on unopened libraries, but it's possible to close
+	        libraries on which other libraries depend. It
+	        <emphasis>may</emphasis> be possible to generate
+	        more explicit dependency information by parsing the output
+	        of the Linux ldd and ldconfig programs.</para>
+	    </listitem>
+        
+	  </itemizedlist>
+    </sect2>
+
+    <sect2 id="Darwin-Notes">
+      <title>>Darwin Notes</title>
+	  <para>Darwin shared libraries come in two (basic) flavors:</para>
+	  <itemizedlist>
+        <listitem>
+	      <para>"dylibs" (which often have the extension".dylib") are
+	        primarily intended to be linked against at compile/link
+	        time. They can be loaded dynamically,<emphasis>but can't
+	        be unloaded</emphasis>. Accordingly,OPEN-SHARED-LIBRARY
+	        can be used to open a .dylib-style library;calling
+	        CLOSE-SHARED-LIBRARY on the result of such a call produces
+	        a warning, and has no other effect. It appears that (due
+	        to an OS bug) attempts to open .dylib shared-libraries
+	        that are already open can cause memory corruption unless
+	        the full pathname of the .dylib file is specified on the
+	        first and all subsequent calls.</para>
+	    </listitem>
+        <listitem>
+	      <para>"bundles" are intended to serve as application
+	        extensions; they can be opened multiple times (creating
+	        multiple instances of the library!) and closed
+	        properly.</para>
+        </listitem>
+	  </itemizedlist>
+      <para>Thanks to Michael Klingbeil for getting both kinds of
+        Darwin shared libraries working in &CCL;.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="The-Interface-Translator">
+    <title>The Interface Translator</title>
+
+    <sect2 id="Interface-translator-overview">
+	  <title>Overview</title>
+	  <para>&CCL; uses an interface translation system based on the FFIGEN
+	    system, which is described at
+	    <ulink url="http://www.ccs.neu.edu/home/lth/ffigen/">this page</ulink>
+	    The interface translator makes
+	    the constant, type, structure, and function definitions in a set of
+	    C-language header files available to lisp code.</para>
+      <para>The basic idea of the FFIGEN scheme is to use the C
+        compiler's frontend and parser to translate .h files into
+        semantically equivalent .ffi files, which represent the
+        definitions from the headers using a syntax based on
+        S-expressions.  Lisp code can then concentrate on the .ffi
+        representation, without having to concern itself with the
+        semantics of header file inclusion or the arcana of C
+        parsing.</para>
+      <para>The original FFIGEN system used a modified version of
+        the LCC C compiler to produce .ffi files. Since many OS
+        header files contain GCC-specific constructs, &CCL;'s
+        translation system uses a modified version of GCC (called,
+        somewhat confusingly, ffigen.)</para>
+       <para>See <ulink url="http://trac.clozure.com/openmcl/wiki/BuildFFIGEN">
+	here</ulink> for information on building and installing ffigen.
+	</para>
+      <para>A component shell script called h-to-ffi.sh reads a
+        specified .h file (and optional preprocessor arguments) and writes
+         a (hopefully) equivalent .ffi file to standard output, calling 
+        the ffigen program with appropriate  arguments.</para>
+      <para>For each interface directory (see FIXTHIS)
+        <emphasis>subdir</emphasis> distributed with &CCL;, a shell
+        script (distributed with &CCL; as
+        "ccl:headers;<emphasis>subdir</emphasis>;C;populate.sh"
+        (or some other platform-specific headers directory)
+        calls h-to-ffi.sh on a large number of the header
+        files in /usr/include (or some other <emphasis>system header
+          path</emphasis>) and creates a parallel directory tree in
+        "ccl:headers;<emphasis>subdir</emphasis>;C;<emphasis>system</emphasis>;<emphasis>header</emphasis>;<emphasis>path</emphasis>;"
+        (or
+        "ccl:darwin-headers;<emphasis>subdir</emphasis>;C;<emphasis>system</emphasis>;<emphasis>header</emphasis>;<emphasis>path</emphasis>;", etc.),
+        populating that directory with .ffi files.</para>
+      <para>A lisp function defined in "ccl:library;parse-ffi.lisp"
+        reads the .ffi files in a specified interface directory
+        <emphasis>subdir</emphasis> and generates new versions of the
+        databases (files with the extension .cdb).</para>
+      <para>The CDB databases are used by the #$ and #_ reader
+        macros and are used in the expansion of RREF, RLET, and
+        related macros.</para>
+    </sect2>
+
+    <sect2 id="Details--rebuilding-the-CDB-databases--step-by-step">
+      <title>Details: rebuilding the CDB databases, step by step</title>
+	  <orderedlist>
+	    <listitem>
+	      <para>Ensure that the FFIGEN program is installed. See
+	        the"README" file generated during the FFIGEN build process for
+	        specific installation instructions.This example assumes
+	        LinuxPPC; for other platforms, substitute the appropriate
+		headers directory. </para>
+	    </listitem>
+        <listitem>
+	      <para>Edit the
+	        "ccl:headers;<emphasis>subdir</emphasis>;C;populate.sh"shell
+	        script. When you're confident that the files
+	        and preprocessor options match your environment, cd to
+	        the"ccl:headers;<emphasis>subdir</emphasis>;C;" directory
+	        and invoke ./populate.sh. Repeat this step until you're
+	        able to cleanly translate all files referenced in the shell
+	        script.</para>
+	    </listitem>
+	    <listitem>
+	      <para>Run &CCL;:
+            <programlisting>
+              ? (require "PARSE-FFI")
+              PARSE-FFI
+
+              ? (ccl::parse-standard-ffi-files :SUBDIR)
+              ;;; lots of output ... after a while, shiny new .cdb files should
+              ;;; appear in "ccl:headers;subdir;"
+          </programlisting></para>
+            <para>It may be necessary to call CCL::PARSE-STANDARD-FFI-FILES
+                  twice, to ensure that forward-references are resolved </para>
+	    </listitem>
+	  </orderedlist>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Case-sensitivity-of-foreign-names-in-CCL">
+    <title>Case-sensitivity of foreign names in &CCL;</title>
+
+    <sect2 id="Case-sensitivity-overview">
+	  <title>Overview</title>
+	  <para>As of release 0.11, &CCL; addresses the fact that
+	    foreign type, constant, record, field, and function nams are
+	    case-sensitive and provides mechanisms to refer to these names
+	    via lisp symbols.</para>
+      <para>Previous versions of &CCL; have tried to ignore that
+        fact, under the belief that case conflicts were rare and that
+        many users (and implementors) would prefer not to deal with
+        case-related issues. The fact that some information in the
+        interface databases was incomplete or inaccessible because of
+        this policy made it clearer that the policy was untenable. I
+        can't claim that the approach described here is aesthetically
+        pleasing, but I can honestly say that it's less unpleasant
+        than other approaches that I'd thought of. I'd be interested
+        to hear alternate proposals.</para>
+      <para>The issues described here have to do with how lisp
+        symbols are used to denote foreign functions, constants,
+        types, records, and fields. It doesn't affect how other lisp
+        objects are sometimes used to denote foreign objects. For
+        instance, the first argument to the EXTERNAL-CALL macros is
+        now and has always been a case-sensitive string.</para>
+    </sect2>
+
+    <sect2 id="Foreign-constant-and-function-names">
+	  <title>Foreign constant and function names</title>
+      <para>The primary way of referring to foreign constant and
+        function names in &CCL; is via the #$ and #_ reader
+        macros. These reader macro functions each read a symbol into
+        the "OS" package, look up its constant or function definition
+        in the interface database, and assign the value of the
+        constant to the symbol or install a macroexpansion function on
+        the symbol.</para>
+      <para>In order to observe case-sensitivity, the reader-macros
+        now read the symbol with (READTABLE-CASE :PRESERVE) in
+        effect.</para>
+      <para>This means that it's necessary to type the foreign
+        constant or function name in correct case, but it isn't
+        necessary to use any special escaping constructs when writing
+        the variable name. For instance:</para>
+      <programlisting>
+        (#_read fd buf n) ; refers to foreign symbol "read"
+        (#_READ fd buf n) ; refers to foreign symbol "READ", which may
+        ; not exist ...
+        #$o_rdonly ; Probably doesn't exist
+        #$O_RDONLY ; Exists on most platforms
+      </programlisting>
+    </sect2>
+
+    <sect2 id="Foreign-type--record--and-field-names">
+	  <title>Foreign type, record, and field names</title>
+	  <para>Constructs like RLET expect a foreign type or record
+	    name to be denoted by a symbol (typically a keyword); RREF
+	    (and PREF) expect an "accessor" form, typically a keyword
+	    formed by concatenating a foreign type or record name with a
+	    sequence of one or more foreign field names, separated by
+	    dots. These names are interned by the reader as other lisp
+	    symbols are, with an arbitrary value of READTABLE-CASE in
+	    effect (typically :UPCASE.) It seems like it would be very
+	    tedious to force users to manually escape (via vertical bar or
+	    backslash syntax) all lowercase characters in symbols used to
+	    specify foreign type, record, and field names (especially
+	    given that many traditional POSIX structure, type, and field
+	    names are entirely lowercase.)</para>
+      <para>The approach taken by &CCL; is to allow the symbols
+        (keywords) used to denote foreign type, record, and field
+        names to contain angle brackets (<literal>&lt;</literal> and
+        <literal>&gt;</literal>). Such symbols are translated to
+	    foreign names via the following set of conventions:</para>
+	  <itemizedlist>
+        <listitem>
+	      <para>All instances of &lt; and &gt; in the symbol's pname
+	        are balanced and don't nest.</para>
+	    </listitem>
+        <listitem>
+	      <para>Any alphabetic characters in the symbol's pname
+	        that aren't enclosed in angle brackets are treated as
+	        lower-case,regardless of the value of READTABLE-CASE and
+	        regardless of the case in which they were written.</para>
+	    </listitem>
+        <listitem>
+	      <para>Alphabetic characters that appear within angle
+	        brackets are mapped to upper-case, again regardless of how
+	        they were written or interned.</para>
+	    </listitem>
+      </itemizedlist>
+	  <para>There may be many ways of "escaping" (with angle
+	    brackets) sequences of upper-case and non-lower-case
+	    characters in a symbol used to denote a foreign name. When
+	    translating in the other direction, &CCL; always escapes the
+	    longest sequence that starts with an upper-case character and
+	    doesn't contain a lower-case character.</para>
+      <para>It's often preferable to use this canonical form of a
+        foreign type name.</para>
+      <para>The accessor forms used by PREF/RREF should be viewed as
+        a series of foreign type/record and field names; upper-case
+        sequences in the component names should be escaped with angle
+        brackets, but those sequences shouldn't span components. (More
+        simply, the separating dots shouldn't be enclosed, even if
+        both surrounding characters need to be.)</para>
+      <para>Older POSIX code tends to use lower-case exclusively for
+        type, record, and field names; there are only a few cases in
+        the &CCL; sources where mixed-case names need to be
+        escaped.</para>
+	  
+    </sect2>
+
+    <sect2 id="Examples--1-">
+      <title>Examples</title>
+      <programlisting>
+        ;;; Allocate a record of type "window".
+        (rlet ((w :window)) ...)
+        ;;; Allocate a record of type "Window", which is probably a
+        ;;;  different type
+        (rlet ((w :&lt;w&gt;indow)) ...)
+        ;;; This is equivalent to the last example
+        (rlet ((w :&lt;w&gt;INDOW)))
+      </programlisting>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Reading-Foreign-Names">
+    <title>Reading Foreign Names</title> <para>&CCL;
+      provides several reader macros to make it more convenient to
+      handle foreign type, function, variable, and constant
+      names. Each of these reader macros reads symbols preserving the
+      case of the source text, and selects an appropriate package in
+      which to intern the resulting symbol. These reader macros are
+      especially useful when your Lisp code interacts extensively with
+      a foreign library&mdash;for example, when using Mac OS X's Cocoa
+      frameworks.</para>
+
+    <para>These reader macros include "#_" to read foreign function
+      names, "#&amp;" to read foreign variable names (note that in
+      earlier versions of OpenMCL the reader macro "#?" was used for
+      this same purpose), "#$" to read foreign constant names, "#/" to
+      read the names of foreign Objective-C methods, and "#>" to read
+      keywords that can be used as the names of types, records, and
+      accessors.</para>
+
+    <para>All of these reader macros preserve the case of the text
+      that they read; beyond that similarity, each performs some
+      additional work, unique to each reader macro, to create symbols
+      suitable for a particular use. For example, the function,
+      variable, and constant reader macros intern the resulting symbol
+      in the "OS" package of the running platform, but the reader
+      macro for Objective-C method names interns symbols in the
+      "NEXTSTEP-FUNCTIONS" package.</para>
+
+    <para>You are likely to see these reader macros used extensively
+      in Lisp code that works with foreign libraries; for example,
+      &CCL; IDE code, which defines numerous Objective-C classes
+      and methods, uses these reader macros extensively.</para>
+
+    <para>For more detailed descriptions of each of these reader
+      macros, see the Foreign-Function-Interface Dictionary
+      section.</para>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Tutorial--Using-Basic-Calls-and-Types">
+    <title>Tutorial: Using Basic Calls and Types</title>
+    <para>This tutorial is meant to cover the basics of &CCL; for
+      calling external C functions and passing data back and forth.
+      These basics will provide the foundation for more advanced
+      techniques which will allow access to the various external
+      libraries and toolkits.</para>
+    <para>The first step is to start with a simple C dynamic library
+      in order to actually observe what is actually passing between
+      &CCL; and C.  So, some C code is in order:</para>
+    <para>Create the file typetest.c, and put the following code
+      into it:</para>
+    <programlisting>
+#include &lt;stdio.h&gt;
+
+void
+void_void_test(void)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+}
+
+signed char
+sc_sc_test(signed char data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %d\n", (signed int)data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+unsigned char
+uc_uc_test(unsigned char data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %d\n", (signed int)data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+    </programlisting>
+    <para>This defines three functions.  If you're familiar with C,
+      notice that there's no <literal>main()</literal>, because we're
+      just building a library, not an executable.</para>
+    <para>The function <literal>void_void_test()</literal> doesn't
+      take any parameters, and doesn't return anything, but it prints
+      two lines to let us know it was called.
+      <literal>sc_sc_test()</literal> takes a signed char as a
+      parameter, prints it, and returns it.
+      <literal>uc_uc_test()</literal> does the same thing, but with an
+      unsigned char.  Their purpose is just to prove to us that we
+      really can call C functions, pass them values, and get values
+      back from them.</para>
+    <para>This code is compiled into a dynamic library on OS X
+      10.3.4 with the command:</para>
+    <programlisting>
+
+      gcc -dynamiclib -Wall -o libtypetest.dylib typetest.c \
+      -install_name ./libtypetest.dylib
+    </programlisting>
+    <tip><para>Users of 64-bit platforms may need to pass options such
+        as "-m64" to gcc, may need to give the output library a different
+        extension (such as ".so"), and may need to user slightly different
+        values for other options in order to create an equivalent test
+        library.</para></tip>
+
+    <para>The -dynamiclib tells gcc that we will be compiling this
+      into a dynamic library and not an executable binary program.
+      The output filename is "libtypetest.dylib".  Notice that we
+      chose a name which follows the normal OS X convention, being in
+      the form "libXXXXX.dylib", so that other programs can link to
+      the library.  &CCL; doesn't need it to be this way, but it is
+      a good idea to adhere to existing conventions.</para>
+    <para>The -install_name flag is primarily used when building OS
+      X "bundles".  In this case, we are not using it, so we put a
+      placeholder into it, "./libtypetest.dylib".  If we wanted to use
+      typetest in a bundle, the -install_name argument would be a
+      relative path from some "current" directory.</para>
+    <para>After creating this library, the first step is to tell
+      &CCL; to open the dynamic library.  This is done by calling
+      .</para>
+    <programlisting>
+
+      Welcome to &CCL; Version (Beta: Darwin) 0.14.2-040506!
+
+      ? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
+      #&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E&gt;
+    </programlisting>
+    <para>You should use an absolute path here; using a relative
+      one, such as just "libtypetest.dylib", would appear to work, but
+      there are subtle problems which occur after reloading it.  See
+      the Darwin notes on for details.  It would be a bad idea anyway,
+      because software should never rely on its starting directory
+      being anything in particular.</para>
+    <para>This command returns a reference to the opened shared library, and
+      &CCL; also adds one to the global variable
+      <literal>ccl::*shared-libraries*</literal>:</para>
+    <programlisting>
+
+      ? ccl::*shared-libraries*
+      (#&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E>
+       #&lt;SHLIB /usr/lib/libSystem.B.dylib #x606179E>)
+    </programlisting>
+    <para>Before we call anything, let's check that the individual
+      functions can actually be found by the system.  We don't have to
+      do this, but it helps to know how to find out whether this is
+      the problem, when something goes wrong.  We use <xref
+                                                         linkend="m_external-call"/>:</para>
+    <programlisting>
+
+      ? (external "_void_void_test")
+      #&lt;EXTERNAL-ENTRY-POINT "_void_void_test" (#x000CFDF8) /Users/andewl/openmcl/libtypetest.dylib #x638EDF6>
+
+      ? (external "_sc_sc_test")
+      #&lt;EXTERNAL-ENTRY-POINT "_sc_sc_test" (#x000CFE50) /Users/andewl/openmcl/libtypetest.dylib #x638EB3E>
+
+      ? (external "_uc_uc_test")
+      #&lt;EXTERNAL-ENTRY-POINT "_uc_uc_test" (#x000CFED4) /Users/andewl/openmcl/libtypetest.dylib #x638E626>
+    </programlisting>
+    <para>Notice that the actual function names have been "mangled"
+      by the C linker.  The first function was named "void_void_test"
+      in typetest.c, but in libtypetest.dylib, it has an underscore (a
+      "_" symbol) before it: "_void_void_test".  So, this is the name
+      which you have to use.  The mangling - the way the name is
+      changed - may be different for other operating systems or other
+      versions, so you need to "just know" how it's done...</para>
+    <para>Also, pay particular attention to the fact that a
+      hexadecimal value appears in the EXTERNAL-ENTRY-POINT.
+      (#x000CFDF8, for example - but what it is doesn't matter.)
+      These hex numbers mean that the function can be dereferenced.
+      Functions which aren't found will not have a hex number.  For
+      example:</para>
+    <programlisting>
+
+      ? (external "functiondoesnotexist")
+      #&lt;EXTERNAL-ENTRY-POINT "functiondoesnotexist" {unresolved}  #x638E3F6>
+    </programlisting>
+    <para>The "unresolved" tells us that &CCL; wasn't able to find this
+      function, which means you would get an error, "Can't resolve foreign
+      symbol," if you tried to call it.</para>
+    <para>These external function references also are stored in a
+      hash table which is accessible through a global variable,
+      <literal>ccl::*eeps*</literal>.</para>
+    <para>At this point, we are ready to try our first external
+      function call:</para>
+    <programlisting>
+
+      ? (external-call "_void_void_test" :void)
+      Entered void_void_test:
+      Exited  void_void_test:
+      NIL
+    </programlisting>
+    <para>We used , which is is the normal mechanism for accessing
+      externally linked code.  The "_void_void_test" is the mangled
+      name of the external function.  The :void refers to the return
+      type of the function.</para>
+    <para>The next step is to try passing a value to C, and getting one
+      back:</para>
+    <programlisting>
+
+      ? (external-call "_sc_sc_test" :signed-byte -128 :signed-byte)
+      Entered sc_sc_test:
+      Data In: -128
+      Exited  sc_sc_test:
+      -128
+    </programlisting>
+    <para>The first :signed-byte gives the type of the first
+      argument, and then -128 gives the value to pass for it.  The
+      second :signed-byte gives the return type.  The return type is
+      always given by the last argument to .</para>
+    <para>Everything looks good.  Now, let's try a number outside
+      the range which fits in one byte:</para>
+    <programlisting>
+
+      ? (external-call "_sc_sc_test" :signed-byte -567 :signed-byte)
+      Entered sc_sc_test:
+      Data In: -55
+      Exited  sc_sc_test:
+      -55
+    </programlisting>
+    <para>Hmmmm.  A little odd.  Let's look at the unsigned stuff to
+      see how it reacts:</para>
+    <programlisting>
+
+      ? (external-call "_uc_uc_test" :unsigned-byte 255 :unsigned-byte)
+      Entered uc_uc_test:
+      Data In: 255
+      Exited  uc_uc_test:
+      255
+    </programlisting>
+    <para>That looks okay.  Now, let's go outside the valid range again:</para>
+    <programlisting>
+
+      ? (external-call "_uc_uc_test" :unsigned-byte 567 :unsigned-byte)
+      Entered uc_uc_test:
+      Data In: 55
+      Exited  uc_uc_test:
+      55
+
+      ? (external-call "_uc_uc_test" :unsigned-byte -567 :unsigned-byte)
+      Entered uc_uc_test:
+      Data In: 201
+      Exited  uc_uc_test:
+      201
+    </programlisting>
+    <para>Since a signed byte can only hold values from -128 through 127, and
+      an unsigned one can only hold values from 0 through 255, any number
+      outside that range gets "clipped": only the low eight bits of it
+      are used.</para>
+    <para>What is important to remember is that <emphasis>external
+        function calls have
+        very few safety checks.</emphasis>
+      Data outside the valid range for its type will silently do
+      very strange things; pointers outside the valid range can very well
+      crash the system.</para>
+    <para>That's it for our first example library.  If you're still
+      following along, let's add some more C code to look at the rest
+      of the primitive types.  Then we'll need to recompile the
+      dynamic library, load it again, and then we can see what
+      happens.</para>
+    <para>Add the following code to typetest.c:</para>
+    <programlisting>
+int
+si_si_test(int data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %d\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+long
+sl_sl_test(long data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %ld\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+long long
+sll_sll_test(long long data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %lld\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+float
+f_f_test(float data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %e\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+
+double
+d_d_test(double data)
+{
+    printf("Entered %s:\n", __FUNCTION__);
+    printf("Data In: %e\n", data);
+    printf("Exited  %s:\n", __FUNCTION__);
+    fflush(stdout);
+    return data;
+}
+    </programlisting>
+    <para>The command line to compile the dynamic library is the same as before:</para>
+    <programlisting>
+
+      gcc -dynamiclib -Wall -o libtypetest.dylib typetest.c \
+      -install_name ./libtypetest.dylib
+    </programlisting>
+    <para>Now, restart &CCL;.  This step is required because
+      &CCL; cannot close and reload a dynamic library on OS
+      X.</para>
+    <para>Have you restarted?  Okay, try out the new code:</para>
+    <programlisting>
+
+      Welcome to &CCL; Version (Beta: Darwin) 0.14.2-040506!
+
+      ? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
+      #&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E>
+
+      ? (external-call "_si_si_test" :signed-fullword -178965 :signed-fullword)
+      Entered si_si_test:
+      Data In: -178965
+      Exited  si_si_test:
+      -178965
+
+      ? ;; long is the same size as int on 32-bit machines.
+      (external-call "_sl_sl_test" :signed-fullword -178965 :signed-fullword)
+      Entered sl_sl_test:
+      Data In: -178965
+      Exited  sl_sl_test:
+      -178965
+
+      ? (external-call "_sll_sll_test"
+      :signed-doubleword -973891578912 :signed-doubleword)
+      Entered sll_sll_test:
+      Data In: -973891578912
+      Exited  sll_sll_test:
+      -973891578912
+    </programlisting>
+    <para>Okay, everything seems to be acting as expected.  However,
+      just to remind you that most of this stuff has no safety net,
+      here's what happens if somebody mistakes
+      <literal>sl_sl_test()</literal> for
+      <literal>sll_sll_test()</literal>, thinking that a long is
+      actually a doubleword:</para>
+    <programlisting>
+
+      ? (external-call "_sl_sl_test"
+      :signed-doubleword -973891578912 :signed-doubleword)
+      Entered sl_sl_test:
+      Data In: -227
+      Exited  sl_sl_test:
+      -974957576192
+    </programlisting>
+    <para>Ouch.  The C function changes the value with no warning
+      that something is wrong.  Even worse, it manages to pass the
+      original value back to &CCL;, which hides the fact that
+      something is wrong.</para>
+    <para>Finally, let's take a look at doing this with
+      floating-point numbers.</para>
+    <programlisting>
+
+      Welcome to &CCL; Version (Beta: Darwin) 0.14.2-040506!
+
+      ? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
+      #&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E>
+
+      ? (external-call "_f_f_test" :single-float -1.256791e+11 :single-float)
+      Entered f_f_test:
+      Data In: -1.256791e+11
+      Exited  f_f_test:
+      -1.256791E+11
+
+      ? (external-call "_d_d_test" :double-float -1.256791d+290 :double-float)
+      Entered d_d_test:
+      Data In: -1.256791e+290
+      Exited  d_d_test:
+      -1.256791D+290
+    </programlisting>
+    <para>Notice that the number ends with "...e+11" for the single-float,
+      and "...d+290" for the
+      double-float.  Lisp has both of these float types itself, and the
+      d instead of the e is how you specify which to create.  If
+      you tried to pass :double-float 1.0e2 to external-call, Lisp would
+      be nice enough to notice and give you a type error.  Don't get the
+      :double-float wrong, though, because then there's no protection.</para>
+    <para>Congratulations!  You now know how to call external C functions from
+      within &CCL;, and pass numbers back and forth.  Now that the basic
+      mechanics of calling and passing work, the next step is to examine how
+      to pass more complex data structures around.</para>
+
+    <sect2 id="Acknowledgement">
+      <title>Acknowledgement</title>
+	  <para>This chapter was generously contributed by Andrew
+	    P. Lentvorski Jr.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1 id="Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap">
+    <title>Tutorial: Allocating Foreign Data on the Lisp Heap </title>
+    <para>Not every foreign function is so marvelously easy to use
+      as the ones we saw in the last section.  Some functions require
+      you to allocate a C struct, fill it with your own
+      information, and pass in a pointer to that struct.  Some of them
+      require you to allocate an empty struct that they will fill in
+      so that you can read the information out of it.</para>
+    <para>There are generally two ways to allocate foreign data.  The
+    first way is to allocate it on the stack; the RLET macro is one way to do this.
+    This is analogous to using automatic variables in C.  In the
+    jargon of Common Lisp, data allocated this way is said to have
+    dynamic extent.</para>
+    <para>The other way to heap-allocate the foreign data.  This is
+    analogous to calling malloc in C.  Again in the jargon of Common
+    Lisp, heap-allocated data is said to have indefinite extent. If a
+    function heap-allocates some data, that data remains valid even
+    after the function itself exits.  This is useful for data which
+    may need to be passed between multiple C calls or multiple
+    threads. Also, some data may be too large to copy multiple times
+    or may be too large to allocate on the stack.</para>
+    <para>The big disadvantage to allocating data on the heap is
+      that it must be explicitly deallocated&mdash;you need to "free" it
+      when you're done with it.  Normal Lisp objects, even those with indefinite
+      extent, are deallocated by the garbage collector when it can prove
+      that they're no longer referenced.  Foreign data, though, is outside the
+      GC's ken:  it has no way to know whether a blob of foreign data is still
+      referenced by foreign code or not. It is thus up to the programmer
+      to manage it manually, just as one
+      does in C with malloc and free.
+    </para>
+    <para>What that means is that, if you allocate something and
+      then lose track of the pointer to it, there's no way to ever
+      free that memory.  That's what's called a memory leak, and if
+      your program leaks enough memory it will eventually use up all
+      of it!  So, you need to be careful to not lose your
+      pointers.</para>
+    <para>That disadvantage, though, is also an advantage for using
+      foreign functions.  Since the garbage collector doesn't know
+      about this memory, it will never move it around.  External C
+      code needs this, because it doesn't know how to follow it to
+      where it moved, the way that Lisp code does.  If you allocate
+      data manually, you can pass it to foreign code and know that no
+      matter what that code needs to do with it, it will be able to,
+      until you deallocate it.  Of course, you'd better be sure it's
+      done before you do.  Otherwise, your program will be unstable
+      and might crash sometime in the future, and you'll have trouble
+      figuring out what caused the trouble, because there won't be
+      anything pointing back and saying "you deallocated this too
+      soon."</para>
+    <para>And, so, on to the code...</para>
+    <para>As in the last tutorial, our first step
+      is to create a local dynamic library in order to help show
+      what is actually going on between &CCL; and C.  So, create the file
+      ptrtest.c, with the following code:</para>
+    <programlisting>
+#include &lt;stdio.h&gt;
+
+void reverse_int_array(int * data, unsigned int dataobjs)
+{
+    int i, t;
+    
+    for(i=0; i&lt;dataobjs/2; i++)
+        {
+            t = *(data+i);
+            *(data+i) = *(data+dataobjs-1-i);
+            *(data+dataobjs-1-i) = t;
+        }
+}
+
+void reverse_int_ptr_array(int **ptrs, unsigned int ptrobjs)
+{
+    int *t;
+    int i;
+    
+    for(i=0; i&lt;ptrobjs/2; i++)
+        {
+            t = *(ptrs+i);
+            *(ptrs+i) = *(ptrs+ptrobjs-1-i);
+            *(ptrs+ptrobjs-1-i) = t;
+        }
+}
+
+void
+reverse_int_ptr_ptrtest(int **ptrs)
+{
+    reverse_int_ptr_array(ptrs, 2);
+    
+    reverse_int_array(*(ptrs+0), 4);
+    reverse_int_array(*(ptrs+1), 4);
+}
+    </programlisting>
+    <para>This defines three functions.
+      <literal>reverse_int_array</literal> takes a pointer to an array
+      of <literal>int</literal>s, and a count telling how many items
+      are in the array, and loops through it putting the elements in
+      reverse.  <literal>reverse_int_ptr_array</literal> does the same
+      thing, but with an array of pointers to <literal>int</literal>s.
+      It only reverses the order the pointers are in; each pointer
+      still points to the same thing.
+      <literal>reverse_int_ptr_ptrtest</literal> takes an array of
+      pointers to arrays of <literal>int</literal>s.  (With me?)  It
+      doesn't need to be told their sizes; it just assumes that the
+      array of pointers has two items, and that both of those are
+      arrays which have four items.  It reverses the array of
+      pointers, then it reverses each of the two arrays of
+      <literal>int</literal>s.</para>
+    <para>Now, compile ptrtest.c into a dynamic library using the
+      command:</para>
+    <programlisting>
+      gcc -dynamiclib -Wall -o libptrtest.dylib ptrtest.c -install_name ./libptrtest.dylib
+    </programlisting>
+    <para>The function <literal>make-heap-ivector</literal> is the
+      primary tool for allocating objects in heap memory.  It
+      allocates a fixed-size &CCL; object in heap memory.  It
+      returns both an array reference, which can be used directly from
+      &CCL;, and a <literal>macptr</literal>, which can be used to
+      access the underlying memory directly.  For example:</para>
+    <programlisting>
+      ? ;; Create an array of 3 4-byte-long integers
+      (multiple-value-bind (la lap)
+          (make-heap-ivector 3 '(unsigned-byte 32))
+        (setq a la)
+        (setq ap lap))
+      ;Compiler warnings :
+      ;   Undeclared free variable A, in an anonymous lambda form.
+      ;   Undeclared free variable AP, in an anonymous lambda form.
+      #&lt;A Mac Pointer #x10217C>
+
+      ? a
+      #(1396 2578 97862649)
+
+      ? ap
+      #&lt;A Mac Pointer #x10217C>
+    </programlisting>
+    <para>It's important to realize that the contents of the
+      <literal>ivector</literal> we've just created haven't been
+      initialized, so their values are unpredictable, and you should
+      be sure not to read from them before you set them, to avoid
+      confusing results.</para>
+    <para>At this point, <literal>a</literal> references an object
+      which works just like a normal array.  You can refer to any item
+      of it with the standard <literal>aref</literal> function, and
+      set them by combining that with <literal>setf</literal>.  As
+      noted above, the <literal>ivector</literal>'s contents haven't
+      been initialized, so that's the next order of business:</para>
+    <programlisting>
+      ? a
+      #(1396 2578 97862649)
+
+      ? (aref a 2)
+      97862649
+
+      ? (setf (aref a 0) 3)
+      3
+
+      ? (setf (aref a 1) 4)
+      4
+
+      ? (setf (aref a 2) 5)
+      5
+
+      ? a
+      #(3 4 5)
+    </programlisting>
+    <para>In addition, the <literal>macptr</literal> allows direct
+      access to the same memory:</para>
+    <programlisting>
+      ? (setq *byte-length-of-long* 4)
+      4
+
+      ? (%get-signed-long ap (* 2 *byte-length-of-long*))
+      5
+
+      ? (%get-signed-long ap (* 0 *byte-length-of-long*))
+      3
+
+      ? (setf (%get-signed-long ap (* 0 *byte-length-of-long*)) 6)
+      6
+
+      ? (setf (%get-signed-long ap (* 2 *byte-length-of-long*)) 7)
+      7
+
+      ? ;; Show that a actually got changed through ap
+      a
+      #(6 4 7)
+    </programlisting>
+    <para>So far, there is nothing about this object that could not
+      be done much better with standard Lisp.  However, the
+      <literal>macptr</literal> can be used to pass this chunk of
+      memory off to a C function.  Let's use the C code to reverse the
+      elements in the array:</para>
+    <programlisting>
+      ? ;; Insert the full path to your copy of libptrtest.dylib
+      (open-shared-library "/Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib")
+      #&lt;SHLIB /Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib #x639D1E6>
+
+      ? a
+      #(6 4 7)
+
+      ? ap
+      #&lt;A Mac Pointer #x10217C>
+
+      ? (external-call "_reverse_int_array" :address ap :unsigned-int (length a) :address)
+      #&lt;A Mac Pointer #x10217C>
+
+      ? a
+      #(7 4 6)
+
+      ? ap
+      #&lt;A Mac Pointer #x10217C>
+    </programlisting>
+    <para>The array gets passed correctly to the C function,
+      <literal>reverse_int_array</literal>.  The C function reverses
+      the contents of the array in-place; that is, it doesn't make a
+      new array, just keeps the same one and reverses what's in it.
+      Finally, the C function passes control back to &CCL;.  Since
+      the allocated array memory has been directly modified, &CCL;
+      reflects those changes directly in the array as well.</para>
+    <para>There is one final bit of housekeeping to deal with.
+      Before moving on, the memory needs to be deallocated:</para>
+    <programlisting>
+      ? (dispose-heap-ivector a ap)
+      NIL
+    </programlisting>
+    <para>The <literal>dispose-heap-ivector</literal> macro actually
+      deallocates the ivector, releasing its memory into the heap for
+      something else to use.  Both <literal>a</literal> and <literal>ap</literal>
+      now have undefined values.
+      </para>
+    <para>When do you call <literal>dispose-heap-ivector</literal>?
+      Anytime after you know the ivector will never be used again, but
+      no sooner.  If you have a lot of ivectors, say, in a hash table,
+      you need to make sure that when whatever you were doing with the
+      hash table is done, those ivectors all get freed.  Unless
+      there's still something somewhere else which refers to them, of
+      course!  Exactly what strategy to take depends on the situation,
+      so just try to keep things simple unless you know better.</para>
+    <para>The simplest situation is when you have things set up so
+      that a Lisp object "encapsulates" a pointer to foreign data,
+      taking care of all the details of using it.  In this case, you
+      don't want those two things to have different lifetimes: You
+      want to make sure your Lisp object exists as long as the foreign
+      data does, and no longer; and you want to make sure the foreign
+      data doesn't get deallocated while your Lisp object still refers
+      to it.</para>
+    <para>If you're willing to accept a few limitations, you can
+      make this easy.  First, you can't let foreign code keep a
+      permanent pointer to the memory; it has to always finish what
+      it's doing, then return, and not refer to that memory again.
+      Second, you can't let any Lisp code that isn't part of your
+      encapsulating "wrapper" refer to the pointer directly.  Third,
+      nothing, either foreign code or Lisp code, should explicitly
+      deallocate the memory.</para>
+    <para>If you can make sure all of these are true, you can at
+      least ensure that the foreign pointer is deallocated when the
+      encapsulating object is about to become garbage, by using
+      &CCL;'s nonstandard "termination" mechanism, which is
+      essentially the same as what Java and other languages call
+      "finalization".</para>
+    <para>Termination is a way of asking the garbage collector to
+      let you know when it's about to destroy an object which isn't
+      used anymore.  Before destroying the object, it calls a function
+      which you write, called a terminator.</para>
+    <para>So, you can use termination to find out when a particular
+      <literal>macptr</literal> is about to become garbage.  That's
+      not quite as helpful as it might seem: It's not exactly the same
+      thing as knowing that the block of memory it points to is
+      unreferenced.  For example, there could be another
+      <literal>macptr</literal> somewhere to the same block; or, if
+      it's a struct, there could be a <literal>macptr</literal> to one
+      of its fields.  Most problematically, if the address of that
+      memory has been passed to foreign code, it's sometimes hard to
+      know whether that code has kept the pointer.  Most foreign
+      functions don't, but it's not hard to think of
+      exceptions.</para>
+    <para>You can use code such as this to make all this happen:</para>
+    <programlisting>
+      (defclass wrapper (whatever)
+        ((element-type :initarg :element-type)
+         (element-count :initarg :element-count)
+         (ivector)
+         (macptr)))
+
+      (defmethod initialize-instance ((wrapper wrapper) &rest; initargs)
+        (declare (ignore initargs))
+        (call-next-method)
+        (ccl:terminate-when-unreachable wrapper)
+        (with-slots (ivector macptr element-type element-count) wrapper
+          (multiple-value-bind (new-ivector new-macptr)
+              (make-heap-ivector element-count element-type)
+            (setq ivector new-ivector
+                  macptr new-macptr))))
+
+      (defmethod ccl:terminate ((wrapper wrapper))
+        (with-slots (ivector macptr) wrapper
+          (when ivector
+            (dispose-heap-ivector ivector macptr)
+            (setq ivector nil
+                  macptr nil))))
+    </programlisting>
+    <para>The <literal>ccl:terminate</literal> method will be called
+      on some arbitrary thread sometime (hopefully soon) after the GC
+      has decided that there are no strong references to an object
+      which has been the argument of a
+      <literal>ccl:terminate-when-unreachable</literal> call.</para>
+    <para>If it makes sense to say that the foreign object should
+      live as long as there's Lisp code that references it (through
+      the encapsulating object) and no longer, this is one way of doing
+      that.</para>
+    <para>Now we've covered passing basic types back and forth with
+      C, and we've done the same with pointers.  You may think this is
+      all...  but we've only done pointers to basic types.  Join us
+      next time for pointers... to pointers.</para>
+
+    <sect2 id="Acknowledgement--1-">
+	  <title>Acknowledgement</title>
+	  <para>Much of this chapter was generously contributed by
+	    Andrew P. Lentvorski Jr.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ******************************************  -->
+  <sect1>
+    <title>The Foreign-Function-Interface Dictionary</title>
+    <anchor id="anchor_Foreign-Function-Interface-Dictionary"/>
+    <!-- ====================================  -->
+    <refentry id="rm_sharpsign-underscore">
+      <indexterm zone="rm_sharpsign-underscore">
+	    <primary>#_</primary>
+      </indexterm>
+
+      <refnamediv>
+	    <refname>#_</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Reader Macro</refclass>
+      </refnamediv>
+
+      <refsect1>
+	    <title>Description</title>
+
+	    <para>Reads a symbol from the current input stream, with *PACKAGE*
+	      bound to the &#34;OS&#34; package and with readtable-case preserved.</para>
+	    
+	    <para>Does a lookup on that symbol in <link
+	                                             linkend="The-Interface-Database">the &CCL; interface
+	        database</link>, signalling an error if no foreign function
+	      information can be found for the symbol in any active <link
+	                                                               linkend="Using-Interface-Directories">interface
+	        directory</link>.</para>
+
+	    <para>Notes the foreign function information, including the foreign
+	      function&#39;s return type, the number and type of the foreign
+	      function&#39;s required arguments, and an indication of whether or
+	      not the function accepts additional arguments (via e.g., the
+	      &#34;varargs&#34; mechanism in C).</para>
+
+	    <para>Defines a macroexpansion function on the symbol, which expand
+	      macro calls involving the symbol into EXTERNAL-CALL forms where
+	      foreign argument type specifiers for required arguments and the
+	      return value specifer are provided from the information in the
+	      database.</para>
+
+	    <para>Returns the symbol.</para>
+
+	    <para>The effect of these steps is that it&#39;s possible to call
+	      foreign functions that take fixed numbers of arguments by simply
+	      providing argument values, as in:</para>
+
+	    <programlisting format="linespecific">(#_isatty fd)
+          (#_read fd buf n)</programlisting>
+
+	    <para>and to call foreign functions that take variable numbers of
+	      arguments by specifying the types of non-required args, as in:</para>
+
+	    <programlisting format="linespecific">(with-cstrs ((format-string &#34;the answer is: %d&#34;))
+          (#_printf format-string :int answer))</programlisting>
+
+        <para>You can query whether a given name is defined in the
+          interface databases by appending the '?' character to the reader
+          macro; for example:</para>
+
+        <programlisting>
+          CL-USER&gt; #_?printf
+          T
+          CL-USER&gt; #_?foo
+          NIL
+        </programlisting>
+
+      </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="rm_sharpsign-ampersand">
+      <indexterm zone="rm_sharpsign-ampersand">
+	    <primary>#&amp;</primary>
+      </indexterm>
+
+      <refnamediv>
+	    <refname>#&amp;</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Reader Macro</refclass>
+      </refnamediv>
+
+      <refsect1>
+	    <title>Description</title>
+
+	    <para>In &CCL; 1.2 and later, the #&amp; reader macro can be used to
+	      access foreign variables; this functionality depends on the presence of
+	      &#34;vars.cdb&#34; files in the interface database. The current behavior
+	      of the #&amp; reader macro is to:</para>
+
+	    <para>Read a symbol from the current input stream, with *PACKAGE*
+	      bound to the &#34;OS&#34; package and with readtable-case preserved.</para>
+	    
+	    <para>Use that symbol&#39;s pname to access the &CCL; interface
+	      database, signalling an error if no appropriate foreign variable
+	      information can be found with that name in any active interface
+	      directory.</para>
+
+	    <para>Use type information recorded in the database to construct a
+	      form which can be used to access the foreign variable, and return
+	      that form.</para>
+
+	    <para>Please note that the set of foreign variables declared in header files
+	      may or may not match the set of foreign variables exported from
+	      libraries (we&#39;re generally talking about C and Unix here ...). When
+	      they do match, the form constructed by the #&amp; reader macro manages the
+	      details of resolving and tracking changes to the foreign variable&#39;s
+	      address.</para>
+
+	    <para>Future extensions (via prefix arguments to the reader macro) may
+	      offer additional behavior; it might be convenient (for instance) to be
+	      able to access the address of a foreign variable without dereferencing
+	      that address.</para>
+
+	    <para>Foreign variables in C code tend to be platform- and
+	      package-specific (the canonical example - &#34;errno&#34; - is typically
+	      not a variable when threads are involved. )</para>
+
+	    <para>In LinuxPPC, </para>
+
+	    <programlisting>? #&amp;stderr</programlisting>
+
+	    <para>returns a pointer to the stdio error stream (&#34;stderr&#34; is a
+	      macro under OSX/Darwin).</para>
+
+	    <para>On both LinuxPPC and DarwinPPC, </para>
+
+	    <programlisting>? #&amp;sys_errlist</programlisting>
+
+	    <para>returns a pointer to a C array of C error message strings.</para>
+
+        <para>You can query whether a given name is defined in the
+          interface databases by appending the '?' character to the reader
+          macro; for example:</para>
+
+        <programlisting>
+          CL-USER&gt; #&amp;?sys_errlist
+          T
+          CL-USER&gt; #&amp;?foo
+          NIL
+        </programlisting>
+
+      </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="rm_sharpsign-dollarsign">
+      <indexterm zone="rm_sharpsign-dollarsign">
+        <primary>#$</primary>
+      </indexterm>
+      
+      <refnamediv>
+        <refname>#$</refname>
+        <refpurpose></refpurpose>
+        <refclass>Reader Macro</refclass>
+      </refnamediv>
+      
+      <refsect1>
+        <title>Description</title>
+        
+	    <para>In &CCL; 0.14.2 and later, the #? reader macro can be used
+	      to access foreign constants; this functionality depends on the
+	      presence of &#34;constants.cdb&#34; files in the interface
+	      database. The current behavior of the #$ reader macro is
+	      to:</para>
+
+	    <para>Read a symbol from the current input stream, with
+	      *PACKAGE* bound to the &#34;OS&#34; package and with
+	      readtable-case preserved.</para>
+	    
+	    <para>Use that symbol&#39;s pname to access the &CCL; interface
+	      database, signalling an error if no appropriate foreign constant
+	      information can be found with that name in any active interface
+	      directory.</para>
+
+	    <para>Use type information recorded in the database to construct a
+	      form which can be used to access the foreign constant, and return
+	      that form.</para>
+
+	    <para>Please note that the set of foreign constants declared in
+	      header files may or may not match the set of foreign constants
+	      exported from libraries. When they do match, the form
+	      constructed by the #$ reader macro manages the details of
+	      resolving and tracking changes to the foreign constant's
+	      address.</para>
+
+        <para>You can query whether a given name is defined in the
+          interface databases by appending the '?' character to the reader
+          macro; for example:</para>
+
+        <programlisting>
+          CL-USER&gt; #$?SO_KEEPALIVE
+          T
+          CL-USER&gt; #$?foo
+          NIL
+        </programlisting>
+
+      </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="rm_sharpsign-slash">
+      <indexterm zone="rm_sharpsign-slash">
+        <primary>#/</primary>
+      </indexterm>
+      
+      <refnamediv>
+        <refname>#/</refname>
+        <refpurpose></refpurpose>
+        <refclass>Reader Macro</refclass>
+      </refnamediv>
+      
+      <refsect1>
+        <title>Description</title>
+        
+	    <para>In &CCL; 1.2 and later, the #/ reader macro can be used to
+	      access foreign functions on the Darwin platform. The current
+	      behavior of the #/ reader macro is to:</para>
+
+	    <para>Read a symbol from the current input stream, with
+	      *PACKAGE* bound to the "NEXTSTEP-FUNCTIONS" package, with
+	      readtable-case preserved, and with any colons included.</para>
+
+        <para>Do limited sanity-checking on the resulting symbol; for
+          example, any name that contains at least one colon is required
+          also to end with a colon, to conform to Objective-C
+          method-naming conventions.</para>
+
+        <para>Export the resulting symbol from the "NEXTSTEP-FUNCTIONS"
+          package and return it.</para>
+
+        <para>For example, reading "#/alloc" interns and returns
+          NEXTSTEP-FUNCTIONS:|alloc|. Reading "#/initWithFrame:" interns
+          and returns NEXTSTEP-FUNCTIONS:|initWithFrame:|.</para>
+
+        <para>A symbol read using this macro can be used as an operand
+          in most places where an Objective-C message name can be used, such as
+          in the (OBJ:@SELECTOR ...) construct.</para>
+
+        <para>Please note: the reader macro is not rigorous about
+          enforcing Objective-C method-naming conventions. Despite the
+          simple checking done by the reader macro, it may still be
+          possible to use it to construct invalid names.</para>
+
+        <para>The act of interning a new symbol in the
+          NEXTSTEP-FUNCTIONS package triggers an interface database lookup
+          of Objective-C methods with the corresponding message name.  If any
+          such information is found, a special type of dispatching
+          function is created and initialized and the new symbol is given
+          the newly-created dispatching function as its function
+          definition.</para>
+
+        <para>The dispatching knows how to call declared Objective-C methods
+          defined on the message. In many cases, all methods have the same
+          foreign type signature, and the dispatching function merely
+          passes any arguments that it receives to a function that does an
+          Objective-C message send with the indicated foreign argument and return
+          types. In other cases, where different Objective-C messages have
+          different type signatures, the dispatching function tries to
+          choose a function that handles the right type signature based on
+          the class of the dispatching function's first argument.</para>
+	    
+        <para>If new information about Objective-C methods is introduced
+          (e.g., by using additional interface files or as Objective-C
+          methods are defined from lisp), the dispatch function is
+          reinitialized to recognize newly-introduced foreign type
+          signatures.</para>
+
+        <para>The argument and result coercion that the bridge has
+          traditionally supported is supported by the new mechanism (e.g.,
+          :&lt;BOOL&gt; arguments can be specified as lisp booleans and :&lt;BOOL&gt;
+          results are returned as lisp boolean values, and an argument
+          value of NIL is coerced to a null pointer if the corresponding
+          argument type is :ID.</para>
+
+        <para>Some Objective-C methods accept variable numbers of
+          arguments; the foreign types of non-required arguments are
+          determined by the lisp types of those arguments (e.g., integers
+          are passed as integers, floats as floats, pointers as pointers,
+          record types by reference.)</para>
+
+        <para>Examples:</para>
+
+        <programlisting>
+          ;;; #/alloc is a known message.
+          ? #'#/alloc
+          #&lt;OBJC-DISPATCH-FUNCTION NEXTSTEP-FUNCTIONS:|alloc| #x300040E94EBF&gt;
+          ;;; Sadly, #/foo is not ...
+          ? #'#/foo
+          &gt; Error: Undefined function: NEXTSTEP-FUNCTIONS:|foo|
+
+          ;;; We can send an "init" message to a newly-allocated instance of
+          ;;; "NSObject" by:
+
+          (send (send ns:ns-object 'alloc) 'init)
+
+          ;;; or by
+
+          (#/init (#/alloc ns:ns-object))
+        </programlisting>
+
+        <para>Objective-C methods that "return" structures return them
+          as garbage-collectable pointers when called via dispatch
+          functions.  For example, if "my-window" is an NS:NS-WINDOW
+          instance, then</para>
+
+        <programlisting>
+          (#/frame my-window)
+        </programlisting>
+
+        <para>returns a garbage-collectable pointer to a structure that
+          describes that window's frame rectangle. This convention means
+          that there's no need to use SLET or special structure-returning
+          message send syntax; keep in mind, though, that #_malloc,
+          #_free, and the GC are all involved in the creation and eventual
+          destruction of structure-typed return values. In some programs
+          these operations may have an impact on performance.</para>
+
+      </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="rm_sharpsign-greaterthan">
+      <indexterm zone="rm_sharpsign-greaterthan">
+        <primary>#&gt;</primary>
+      </indexterm>
+      
+      <refnamediv>
+        <refname>#&gt;</refname>
+        <refpurpose></refpurpose>
+        <refclass>Reader Macro</refclass>
+      </refnamediv>
+      
+      <refsect1>
+        <title>Description</title>
+        
+        <para>In &CCL; 1.2 and later, the #&gt; reader macro reads
+          the following text as a keyword, preserving the case of the
+          text. For example:</para>
+
+        <programlisting>
+          CL-USER&gt; #&gt;FooBar
+          :&lt;F&gt;OO&lt;B&gt;AR
+        </programlisting>
+
+        <para>The resulting keyword can be used as the name of foreign
+          types, records, and accessors.</para>
+        
+      </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_close-shared-library">
+	  <indexterm zone="f_close-shared-library">
+	    <primary>close-shared-library</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CLOSE-SHARED-LIBRARY</refname>
+	    <refpurpose>Stops using a shared library, informing the operating
+	      system that it can be unloaded if appropriate.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>close-shared-library</function> library &key;
+	      completely</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>library</term>
+
+	        <listitem>
+		      <para>either an object of type SHLIB, or a string which
+		        designates one by its so-name.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>completely</term>
+
+	        <listitem>
+		      <para>a boolean.  The default is T.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>If <varname>completely</varname> is T, sets the
+	      reference count of <varname>library</varname> to 0.  Otherwise,
+	      decrements it by 1.  In either case, if the reference count
+	      becomes 0, <function>close-shared-library</function>
+	      frees all memory resources consumed <varname>library</varname>
+	      and
+	      causes any EXTERNAL-ENTRY-POINTs known to be defined by it to
+	      become unresolved.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_defcallback">
+	  <indexterm zone="m_defcallback">
+	    <primary>defcallback</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>DEFCALLBACK</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>defcallback</function> name
+	      ({arg-type-specifier var}* &optional; result-type-specifier)
+	      &body; body
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+
+	        <listitem>
+		      <para>A symbol which can be made into a special variable</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>arg-type-specifer</term>
+
+	        <listitem>
+		      <para>One of the foreign argument-type keywords,
+		        described above, or an equivalent <link
+		                                             linkend="Specifying-And-Using-Foreign-Types">foreign
+		          type specifier</link>.  In addition, if the keyword
+		        :WITHOUT-INTERRUPTS is specified, the callback will be
+		        executed with lisp interrupts disabled if the
+		        corresponding var is non-NIL. If :WITHOUT-INTERRUPTS
+		        is specified more than once, the rightmost instance
+		        wins.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>var</term>
+
+	        <listitem>
+		      <para>A symbol (lisp variable), which will be bound to a
+		        value of the specified type.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>body</term>
+
+	        <listitem>
+		      <para>A sequence of lisp forms, which should return a value
+		        which can be coerced to the specified result-type.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Proclaims <varname>name</varname>
+	      to be a special variable; sets its value to a
+	      MACPTR which, when called by foreign code, calls a lisp function
+	      which expects foreign arguments of the specified types and which
+	      returns a foreign value of the specified result type. Any argument
+	      variables which correspond to foreign arguments of type :ADDRESS
+	      are bound to stack-allocated MACPTRs.</para>
+	    
+	    <para>If <varname>name</varname>
+	      is already a callback function pointer, its value is
+	      not changed; instead, it&#39;s arranged
+	      that an
+	      updated version of the lisp callback function will be called.
+	      This feature allows for callback functions to be redefined
+	      incrementally, just like Lisp functions are.</para>
+
+	    <para><function>defcallback</function>
+	      returns the callback pointer, e.g., the
+	      value of <varname>name</varname>.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_def-foreign-type">
+	  <indexterm zone="m_def-foreign-type">
+	    <primary>def-foreign-type</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>DEF-FOREIGN-TYPE</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>def-foreign-type</function> name foreign-type-spec
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+	        
+	        <listitem>
+		      <para>NIL or a keyword; the keyword may contain
+		        <link linkend="Case-sensitivity-of-foreign-names-in-CCL" >escaping constructs</link>.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>foreign-type-spec</term>
+	        
+	        <listitem>
+		      <para>A foreign type specifier, whose syntax is (loosely)
+		        defined above.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>If name is non-NIL, defines name to be an alias for the
+	      foreign type specified by foreign-type-spec. If foreign-type-spec
+	      is a named structure or union type, additionally defines that
+	      structure or union type.</para>
+	    
+	    <para>If name is NIL, foreign-type-spec must be a named foreign
+	      struct or union definition, in which case the foreign structure
+	      or
+	      union definition is put in effect.</para>
+	    
+	    <para>Note that there are two separate namespaces for foreign
+	      type names, one for the names of ordinary types and one for
+	      the names of structs and unions.  Which one
+	      <varname>name</varname> refers to depends on
+	      <varname>foreign-type-spec</varname> in the obvious manner.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_external">
+	  <indexterm zone="m_external">
+	    <primary>external</primary>
+	  </indexterm>
+	  
+	  <refnamediv>
+	    <refname>EXTERNAL</refname>
+	    <refpurpose>Resolves a reference to an external symbol which
+	      is defined in a shared library.</refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>external</function> name => entry
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+	        <listitem>
+		      <para>
+		        a simple-string which names an external symbol.
+		        Case-sensitive.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>entry</term>
+	        <listitem>
+		      <para>
+		        an object of type EXTERNAL-ENTRY-POINT which maintains
+		        the address of the foreign symbol named by
+		        <varname>name</varname>.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>If there is already an EXTERNAL-ENTRY-POINT for
+	      the symbol named by <varname>name</varname>, finds it and
+	      returns it.  If not, creates one and returns it.</para>
+
+	    <para>Tries to resolve the entry point to a memory address,
+	      and identify the containing library.</para>
+
+	    <para>Be aware that under Darwin, external functions which
+	      are callable from C have underscores prepended to their names,
+	      as in "_fopen".</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_external-call">
+	  <indexterm zone="m_external-call">
+	    <primary>external-call</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>EXTERNAL-CALL</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>external-call</function> name
+	      {arg-type-specifier arg}* &optional; result-type-specifier
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+
+	        <listitem>
+		      <para>A lisp string. See external, above.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>arg-type-specifer</term>
+
+	        <listitem>
+		      <para>One of the foreign argument-type keywords, described
+		        above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
+		          type specifier</link>.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>arg</term>
+
+	        <listitem>
+		      <para>A lisp value of type indicated by the corresponding
+		        arg-type-specifier</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>result-type-specifier</term>
+
+	        <listitem>
+		      <para>One of the foreign argument-type keywords, described
+		        above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
+		          type specifier</link>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Calls the foreign function at the address obtained by
+	      resolving the external-entry-point associated with name, passing
+	      the values of each arg as a foreign argument of type indicated by
+	      the corresponding arg-type-specifier. Returns the foreign function
+	      result (coerced to a Lisp object of type indicated by
+	      result-type-specifier), or NIL if result-type-specifer is :VOID or
+	      NIL</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_Pff-call">
+	  <indexterm zone="f_Pff-call">
+	    <primary>%ff-call</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>%FF-CALL</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>%ff-call</function> entrypoint
+	      {arg-type-keyword arg}* &optional; result-type-keyword
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>entrypoint</term>
+	        
+	        <listitem>
+		      <para>A fixnum or MACPTR</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>arg-type-keyword</term>
+
+	        <listitem>
+		      <para>One of the foreign argument-type keywords, described
+		        above</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>arg</term>
+
+	        <listitem>
+		      <para>A lisp value of type indicated by the corresponding
+		        arg-type-keyword</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>result-type-keyword</term>
+
+	        <listitem>
+		      <para>One of the foreign argument-type keywords, described
+		        above</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Calls the foreign function at address entrypoint passing the
+	      values of each arg as a foreign argument of type indicated by the
+	      corresponding arg-type-keyword. Returns the foreign function
+	      result (coerced to a Lisp object of type indicated by
+	      result-type-keyword), or NIL if result-type-keyword is :VOID or
+	      NIL</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_ff-call">
+	  <indexterm zone="m_ff-call">
+	    <primary>ff-call</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>FF-CALL</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>ff-call</function> entrypoint
+	      {arg-type-specifier arg}* &optional; result-type-specifier
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>entrypoint</term>
+
+	        <listitem>
+		      <para>A fixnum or MACPTR</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>arg-type-specifer</term>
+
+	        <listitem>
+		      <para>One of the foreign argument-type keywords, described
+		        above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
+		          type specifier</link>.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>arg</term>
+
+	        <listitem>
+		      <para>A lisp value of type indicated by the corresponding
+		        arg-type-specifier</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>result-type-specifier</term>
+
+	        <listitem>
+		      <para>One of the foreign argument-type keywords, described
+		        above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
+		          type specifier</link>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Calls the foreign function at address entrypoint passing the
+	      values of each arg as a foreign argument of type indicated by the
+	      corresponding arg-type-specifier. Returns the foreign function
+	      result (coerced to a Lisp object of type indicated by
+	      result-type-specifier), or NIL if result-type-specifer is :VOID or
+	      NIL</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_foreign-symbol-address">
+	  <indexterm zone="f_foreign-symbol-address">
+	    <primary>foreign-symbol-address</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>FOREIGN-SYMBOL-ADDRESS</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>foreign-symbol-address</function> name
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+
+	        <listitem>
+		      <para>A lisp string.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Tries to resolve the address of the foreign symbol
+	      name. If successful, returns that address encapsulated in
+	      <link
+	         linkend="Referencing-and-Using-Foreign-Memory-Addresses">a
+	        MACPTR</link>, else returns NIL.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_foreign-symbol-entry">
+	  <indexterm zone="f_foreign-symbol-entry">
+	    <primary>foreign-symbol-entry</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>FOREIGN-SYMBOL-ENTRY</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>foreign-symbol-entry</function> name
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+
+	        <listitem>
+		      <para>A lisp string.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Tries to resolve the address of the foreign symbol name. If
+	      successful, returns a fixnum representation of that address, else
+	      returns NIL.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_free">
+      <indexterm zone="f_free">
+        <primary>free</primary>
+      </indexterm>
+      
+      <refnamediv>
+        <refname>FREE</refname>
+        <refpurpose></refpurpose>
+        <refclass>Function</refclass>
+      </refnamediv>
+      
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>free</function> ptr
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>ptr</term>
+
+	        <listitem>
+		      <para>A <code>MACPTR</code> that points to a block of
+		      foreign, heap-allocated memory.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+      <refsect1>
+        <title>Description</title>
+        
+        <para>In &CCL; 1.2 and later, the <code>CCL:FREE</code>
+          function invokes the foreign <code>free</code> function from
+          the platform's standard C library to deallocate a block of
+          foreign memory.</para>
+
+        <para>Previous versions of &CCL; implemented this function,
+          but it was not exported.</para>
+
+        <para>If the argument to <code>CCL:FREE</code> is a gcable
+        pointer (for example, an object returned
+        by <code>MAKE-GCABLE-RECORD</code>)
+        then <code>CCL:FREE</code> informs the garbage collector that
+        the foreign memory has been deallocated before calling the
+        foreign <code>free</code> function.</para>
+        
+      </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_make-heap-ivector">
+      <indexterm zone="f_make-heap-ivector">
+        <primary>make-heap-ivector</primary>
+      </indexterm>
+      
+      <refnamediv>
+        <refname>MAKE-HEAP-IVECTOR</refname>
+        <refpurpose></refpurpose>
+        <refclass>Function</refclass>
+      </refnamediv>
+      
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>make-heap-ivector</function> element-count element-type
+	      => vector macptr size
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>element-count</term>
+
+	        <listitem>
+		      <para>A positive integer.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>element-type</term>
+
+	        <listitem>
+		      <para>A type specifier.
+		      
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>vector</term>
+
+	        <listitem>
+		      <para>A lisp vector.  The initial contents are
+		      undefined.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>mactpr</term>
+
+	        <listitem>
+		      <para>A pointer to the first byte of data stored
+		      in the vector.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>size</term>
+
+	        <listitem>
+		      <para>The size of the returned vector in octets.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      
+	    </variablelist>
+	  </refsect1>
+      <refsect1>
+        <title>Description</title>
+        
+        <para>
+	An "ivector" is a one-dimensional array that's specialized to
+	a numeric or character element type.
+	</para>
+	<para>
+	  <code>MAKE-HEAP-IVECTOR</code> allocates an ivector in
+	  foreign memory.  The GC will never move this vector, and
+	  will in fact not pay any attention to it at all.  The
+	  returned pointer to it can therefore be passed safely to
+	  foreign code.
+	</para>
+	<para>
+	  The vector must be explicitly deallocated with
+	  <code>DISPOSE-HEAP-IVECTOR</code>.
+	</para>
+      </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_makegcable--record">
+      <indexterm zone="m_make-record">
+	    <primary>make-gcable-record</primary>
+      </indexterm>
+
+      <refnamediv>
+	    <refname>MAKE-GCABLE-RECORD</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+      </refnamediv>
+
+      <refsynopsisdiv>
+	    <synopsis>
+	      <function>make-gcable-record</function> typespec
+	      &rest; initforms => result
+	    </synopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>typespec</term>
+
+	        <listitem>
+		      <para>A foreign type specifier, or a keyword which is used
+		        as the name of a foreign struct or union.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>initforms</term>
+
+	        <listitem>
+		      <para>If the type denoted by <varname>typespec</varname>
+		        is scalar, a single value appropriate for that type;
+		        otherwise, a list of alternating field names and
+		        values appropriate for the types of those fields.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>result</term>
+
+	        <listitem>
+		      <para>
+		        A <type>macptr</type> which encapsulates the address of a
+		        newly-allocated record on the foreign heap. The foreign
+		        object returned by <function>make-gcable-record</function>
+		        is freed when the garbage collector determines that
+		        the <code>MACPTR</code> object that describes it is
+		        unreachable.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+      </refsect1>
+
+      <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Allocates a block of foreign memory suitable to hold the foreign
+	      type described by <code>typespec</code>, in the same manner
+	      as <link linkend="anchor_make-record">MAKE-RECORD</link>. In
+	      addition, <code>MAKE-GCABLE-RECORD</code> marks the
+	      returned object gcable; in other words, it informs the garbage
+	      collector that it may reclaim the object when it becomes
+	      unreachable.
+	    </para>
+
+        <para>In all other respects, <code>MAKE-GCABLE-RECORD</code> works
+          the same way
+          as <link linkend="anchor_make-record">MAKE-RECORD</link></para>
+
+        <para> When using gcable pointers, it's important to remember the
+          distinction between a <code>MACPTR</code> object (which is a
+          lisp object, more or less like any other) and the block of
+          foreign memory that the <code>MACPTR</code> object points to.
+          If a gcable <code>MACPTR</code> object is the only thing in the
+          world (lisp world or foreign world) that references the
+          underlying block of foreign memory, then freeing the foreign
+          memory when it becomes impossible to reference it is convenient
+          and sane.  If other lisp <code>MACPTR</code>s reference the
+          underlying block of foreign memory or if the address of that
+          foreign memory is passed to and retained by foreign code, having
+          the GC free the memory may have unpleasant consequences if those
+          other references are used.</para>
+
+        <para>Take care, therefore, not to create a gcable record unless
+          you are sure that the returned <code>MACPTR</code> will be the
+          only reference to the allocated memory that will ever be
+          used.</para>
+      </refsect1>
+
+    </refentry>
+
+
+    <!-- ====================================  -->
+    <refentry id="m_make-record">
+      <indexterm zone="m_make-record">
+	<primary>make-record</primary>
+      </indexterm>
+      <refmeta>
+      <refentrytitle>
+	MAKE-RECORD
+	<anchor id="anchor_make-record"/>
+      </refentrytitle>
+      </refmeta>
+	  <refnamediv>
+	    <refname>MAKE-RECORD</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>make-record</function> typespec
+	      &rest; initforms => result
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>typespec</term>
+
+	        <listitem>
+		      <para>A foreign type specifier, or a keyword which is used
+		        as the name of a foreign struct or union.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>initforms</term>
+
+	        <listitem>
+		      <para>If the type denoted by <varname>typespec</varname>
+		        is scalar, a single value appropriate for that type;
+		        otherwise, a list of alternating field names and
+		        values appropriate for the types of those fields.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>result</term>
+
+	        <listitem>
+		      <para>
+		        A <type>macptr</type> which encapsulates the address of a
+		        newly-allocated record on the foreign heap.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Expands into code which allocates and initializes
+	      an instance of the type 
+	      denoted by <varname>typespec</varname>, on the foreign
+	      heap.  The record is allocated using the C function
+	      <function>malloc</function>, and the user of
+	      <function>make-record</function> must explicitly call
+	      the function <function>CCL:FREE</function> to deallocate the
+	      record, when it is no longer needed.
+	    </para>
+
+	    <para>
+	      If <varname>initforms</varname> is provided, its value
+	      or values are used in the initialization.  When the type
+	      is a scalar, <varname>initforms</varname> is either a single
+	      value which can be coerced to that type, or no value, in which
+	      case binary 0 is used.  When the type is a <type>struct</type>,
+	      <varname>initforms</varname> is a list, giving field names
+	      and the values for each.  Each field is treated in the same way
+	      as a scalar is: If a value for it is given, it must be
+	      coerceable to the field's type; if not, binary 0 is used.
+	    </para>
+
+	    <para>
+	      When the type is an array, <varname>initforms</varname> may
+	      not be provided, because <function>make-record</function>
+	      cannot initialize its values.  <function>make-record</function>
+	      is also unable to initialize fields of a <type>struct</type>
+	      which are themselves
+	      <type>struct</type>s.  The user of
+	      <function>make-record</function> should set these values
+	      by another means.
+	    </para>
+
+	    <para>
+	      A possibly-significant limitation is that it must be possible to
+	      find the foreign type at the time the macro is expanded;
+	      <function>make-record</function> signals an error if this is
+	      not the case.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>
+	      It is inconvenient that <function>make-record</function> is a
+	      macro, because this means that <varname>typespec</varname>
+	      cannot be a variable; it must be an immediate value.
+	    </para>
+	    
+	    <para>
+	      If it weren't for this requirement,
+	      <function>make-record</function> could be a function.  However,
+	      that would mean that any stand-alone application using it would
+	      have to include a copy of the interface database
+	      (see <xref linkend="The-Interface-Database"/>), which is undesirable
+	      because it's large.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_open-shared-library">
+	  <indexterm zone="f_open-shared-library">
+	    <primary>open-shared-library</primary>
+	  </indexterm>
+	  
+	  <refnamediv>
+	    <refname>OPEN-SHARED-LIBRARY</refname>
+	    <refpurpose>Asks the operating system to load a shared library
+	      for &CCL; to use.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+	  
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>open-shared-library</function> name => library
+	    </synopsis>
+	  </refsynopsisdiv>
+	  
+	  <refsect1>
+	    <title>Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>	
+	        <listitem>
+		      <para>A SIMPLE-STRING which is presumed to be the so-name of
+		        or a filesystem path to the library.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>library</term>
+	        <listitem>
+		      <para>An object of type SHLIB which describes the
+		        library denoted by <varname>name</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+	  
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>If the library denoted by <varname>name</varname> can
+	      be loaded by the
+	      operating system, returns an object of type SHLIB that describes
+	      the library; if the library is already open, increments a
+	      reference count. If the library can&#39;t be loaded, signals a
+	      SIMPLE-ERROR which contains an often-cryptic message from the
+	      operating system.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Examples</title>
+
+	    <programlisting format="linespecific">;;; Try to do something simple.
+          ? (open-shared-library &#34;libgtk.so&#34;)
+          &#62; Error: Error opening shared library &#34;libgtk.so&#34;: /usr/lib/libgtk.so: undefined symbol: gdk_threads_mutex
+          &#62; While executing: OPEN-SHARED-LIBRARY
+
+          ;;; Grovel around, curse, and try to find out where &#34;gdk_threads_mutex&#34;
+          ;;; might be defined. Then try again:
+
+          ? (open-shared-library &#34;libgdk.so&#34;)
+          #&#60;SHLIB libgdk.so #x3046DBB6&#62;
+
+          ? (open-shared-library &#34;libgtk.so&#34;)
+          #&#60;SHLIB libgtk.so #x3046DC86&#62;
+
+          ;;; Reference an external symbol defined in one of those libraries.
+
+          ? (external &#34;gtk_main&#34;)
+          #&#60;EXTERNAL-ENTRY-POINT &#34;gtk_main&#34; (#x012C3004) libgtk.so #x3046FE46&#62;
+
+          ;;; Close those libraries.
+
+          ? (close-shared-library &#34;libgtk.so&#34;)
+          T
+
+          ? (close-shared-library &#34;libgdk.so&#34;)
+          T
+
+          ;;; Reference the external symbol again.
+
+          ? (external &#34;gtk_main&#34;)
+          #&#60;EXTERNAL-ENTRY-POINT &#34;gtk_main&#34; {unresolved} libgtk.so #x3046FE46&#62;</programlisting>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>It would be helpful to describe what an soname is and give
+	      examples of one.</para>
+
+	    <para>Does the SHLIB still get returned if the library is
+	      already open?</para>
+	  </refsect1>
+    </refentry>
+    
+    <!-- ====================================  -->
+    <refentry id="m_pref">
+	  <indexterm zone="m_pref">
+	    <primary>pref</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PREF</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>pref</function> ptr accessor-form
+	    </synopsis>
+
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>ptr</term>
+
+	        <listitem>
+		      <para><link linkend="Referencing-and-Using-Foreign-Memory-Addresses">a MACPTR</link>.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>accessor-form</term>
+
+	        <listitem>
+		      <para>a keyword which names a foreign type or record, as
+		        described in <xref linkend="Foreign-type--record--and-field-names"/>.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>References an instance of a foreign type (or a component of
+	      a foreign type) accessible via ptr.</para>
+	    
+	    <para>Expands into code which references the indicated scalar type
+	      or component, or returns a pointer to a composite type.</para>
+	    
+	    <para>PREF can be used with SETF.</para>
+	    
+	    <para>RREF is a deprecated alternative to PREF. It accepts a
+	      :STORAGE keyword and rather loudly ignores it.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_Preference-external-entry-point">
+	  <indexterm zone="f_Preference-external-entry-point">
+	    <primary>%reference-external-entry-point</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>%REFERENCE-EXTERNAL-ENTRY-POINT</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>%reference-external-entry-point</function> eep
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>eep</term>
+
+	        <listitem>
+		      <para>An EXTERNAL-ENTRY-POINT, as obtained by the EXTERNAL
+		        macro.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Tries to resolve the address of the EXTERNAL-ENTRY-POINT
+	      eep; returns a fixnum representation of that address if
+	      successful, else signals an error.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_rlet">
+	  <indexterm zone="m_rlet">
+	    <primary>rlet</primary>
+	  </indexterm>
+	  <refmeta>
+	    <refentrytitle>
+	      RLET
+	      <anchor id="anchor_rlet"/>
+	    </refentrytitle>
+	  </refmeta>
+
+	  <refnamediv>
+	    <refname>RLET</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>rlet</function> (var typespec &rest; initforms)*
+	      &body; body
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>var</term>
+
+	        <listitem>
+		      <para>A symbol (a lisp variable)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>typespec</term>
+
+	        <listitem>
+		      <para>A foreign type specifier or foreign record name.</para>
+	        </listitem>
+	      </varlistentry>
+
+          <varlistentry>
+	        <term>initforms</term>
+
+	        <listitem>
+		      <para>As described above, for
+		        <xref linkend="m_make-record"/></para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Executes <varname>body</varname>
+	      in an environment in which each var is bound
+	      to <link linkend="Referencing-and-Using-Foreign-Memory-Addresses">a MACPTR</link> encapsulating the
+	      address of a stack-allocated foreign memory block, allocated and
+	      initialized from typespec and initforms as per
+	      <xref linkend="m_make-record"/>.
+	      Returns whatever value(s) <varname>body</varname>
+	      returns.</para>
+	    
+	    <para>Record fields that aren&#39;t explicitly initialized have
+	      unspecified contents.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="m_rletz">
+	  <indexterm zone="m_rletz">
+	    <primary>rletz</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>RLETZ</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>rletz</function> (var typespec &rest; initforms)*
+	      &body; body
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>var</term>
+
+	        <listitem>
+		      <para>A symbol (a lisp variable)</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>typespec</term>
+
+	        <listitem>
+		      <para>A foreign type specifier or foreign record name.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>initforms</term>
+
+	        <listitem>
+		      <para>As described above, for ccl:make-record</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Executes body in an environment in which each var is
+	      bound to <link
+	                  linkend="Referencing-and-Using-Foreign-Memory-Addresses">a
+	        MACPTR</link> encapsulating the address of a stack-allocated
+	      foreign memory block, allocated and initialized from
+	      typespec and initforms as ccl:make-record.</para>
+	    
+	    <para>Returns whatever value(s) body returns.</para>
+
+	    <para>Unlike rlet, record fields that aren&#39;t explicitly
+	      initialized are set to binary 0.</para>
+	  </refsect1>
+    </refentry>
+
+    <!-- ====================================  -->
+    <refentry id="f_terminate-when-unreachable">
+	  <indexterm zone="f_terminate-when-unreachable">
+	    <primary>terminate-when-unreachable</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>TERMINATE-WHEN-UNREACHABLE</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>terminate-when-unreachable</function> object
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>object</term>
+
+	        <listitem>
+		      <para>A CLOS object of a class for which there exists
+		        a method of the generic function
+		        <function>ccl:terminate</function>.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      The "termination" mechanism is a way to have the garbage
+	      collector run a function right before an object is about to
+	      become garbage.  It is very similar to the "finalization"
+	      mechanism which Java has.  It is not standard Common Lisp,
+	      although other Lisp implementations have similar features.
+	      It is useful when there is some sort of special cleanup,
+	      deallocation, or releasing of resources which needs to happen
+	      when a certain object is no longer being used.
+	    </para>
+
+	    <para>
+	      When the garbage collector discovers that an object is no
+	      longer referred to anywhere in the program, it deallocates
+	      that object, freeing its memory.  However, if
+	      <function>ccl:terminate-when-unreachable</function> has been
+	      called on the object at any time, the garbage collector first
+	      invokes the generic function <function>ccl:terminate</function>,
+	      passing it the object as a parameter.
+	    </para>
+
+	    <para>
+	      Therefore, to make termination do something useful, you need to
+	      define a method on <function>ccl:terminate</function>.
+	    </para>
+
+	    <para>
+	      Because calling
+	      <function>ccl:terminate-when-unreachable</function> only
+	      affects a single object, rather than all objects of its
+	      class, you
+	      may wish to put a call to it in the
+	      <function>initialize-instance</function> method of a
+	      class.  Of course, this is only appropriate if you do in fact
+	      want to use termination for all objects of a given class.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Example</title>
+
+        <programlisting format="linespecific">
+          (defclass resource-wrapper ()
+            ((resource :accessor resource)))
+
+          (defmethod initialize-instance :after ((x resource-wrapper) &amp;rest initargs)
+             (ccl:terminate-when-unreachable x))
+
+          (defmethod ccl:terminate ((x resource-wrapper))
+             (when (resource x)
+                (deallocate (resource x))))</programlisting>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+
+	    <simplelist type="inline">
+	      <member><xref linkend="Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap"/></member>
+	    </simplelist>
+	  </refsect1>
+
+    </refentry>
+
+     <!-- ====================================  -->
+    <refentry id="f_unuse-interface-dir">
+	  <indexterm zone="f_unuse-interface-dir">
+	    <primary>unuse-interface-dir</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>UNUSE-INTERFACE-DIR</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>unuse-interface-dir</function> dir-id
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>dir-id</term>
+
+	        <listitem>
+		      <para>A keyword whose pname, mapped to lower case, names a
+		        subdirectory of &#34;ccl:headers;&#34; (or
+		        "ccl:darwin-headers;")</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Tells &CCL; to remove the interface directory denoted by
+	      dir-id from the list of interface directories which are
+	      consulted for
+	      foreign type and function information. Returns T if the directory
+	      was on the search list, NIL otherwise.</para>
+	  </refsect1>
+    </refentry>
+
+   <!-- ====================================  -->
+    <refentry id="f_use-interface-dir">
+	  <indexterm zone="f_use-interface-dir">
+	    <primary>use-interface-dir</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>USE-INTERFACE-DIR</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>use-interface-dir</function> dir-id
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>dir-id</term>
+
+	        <listitem>
+		      <para>A keyword whose pname, mapped to lower case, names a
+		        subdirectory of &#34;ccl:headers;&#34; (or
+		        "ccl:darwin-headers;")</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Tells &CCL; to add the interface directory denoted by
+	      dir-id to the list of interface directories which it consults for
+	      foreign type and function information. Arranges that that
+	      directory is searched before any others.</para>
+
+	    <para>Note that <function>use-interface-dir</function>
+	      merely adds an entry
+	      to a search list.
+	      If the named directory doesn&#39;t exist in the file system
+	      or doesn&#39;t
+	      contain a set of database files, a runtime error may occur
+	      when &CCL;
+	      tries to open some database file in that directory, and it
+	      will try to
+	      open such a database file whenever it needs to find any
+	      foreign type or
+	      function information. <xref linkend="f_unuse-interface-dir"/>
+	      may come in
+	      handy in that case.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Examples</title>
+
+	    <para>One typically wants interface information to be
+	      available at compile-time (or, in many cases, at read-time).
+	      A typical idiom would be:</para>
+
+	    <programlisting format="linespecific">(eval-when (:compile-toplevel :execute)
+          (use-interface-dir :GTK))</programlisting>
+
+	    <para>Using the :GTK interface directory makes available
+	      information on
+	      foreign types, functions, and constants.  It's generally
+	      necessary to
+	      load foreign libraries before actually calling the
+	      foreign code, which for GTK can be done like this:</para>
+
+	    <programlisting>(load-gtk-libraries)</programlisting>
+
+	    <para>It should now be possible to do things like:</para>
+
+	    <programlisting>(#_gtk_widget_destroy w)</programlisting>
+	  </refsect1>
+    </refentry>
+
+  </sect1>
+</chapter>
Index: /branches/new-random/doc/src/gc.xml
===================================================================
--- /branches/new-random/doc/src/gc.xml	(revision 13309)
+++ /branches/new-random/doc/src/gc.xml	(revision 13309)
@@ -0,0 +1,713 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "<literal>CCL</literal>">
+]>
+  <chapter id="Understanding-and-Configuring-the-Garbage-Collector">
+    <title>Understanding and Configuring the Garbage Collector</title>
+
+    <sect1 id="Heap-space-allocation">
+      <title>Heap space allocation</title>
+      <para>Release 0.10 or later of &CCL; uses a different memory
+      management scheme than previous versions did. Those earlier
+      versions would allocate a block of memory (of specified size) at
+      startup and would allocate lisp objects within that block. When
+      that block filled with live (non-GCed) objects, the lisp would
+      signal a "heap full" condition. The heap size imposed a limit on
+      the size of the largest object that could be allocated.</para>
+      <para>The new strategy involves reserving a very large (2GB on
+      DarwinPPC32, 1GB on LinuxPPC, "very large" on 64-bit
+      implementations) block at startup and consuming (and
+      relinquishing) its contents as the size of the live lisp heap
+      data grows and shrinks. After the initial heap image loads and
+      after each full GC, the lisp kernel will try to ensure that a
+      specified amount (the "lisp-heap-gc-threshold") of free memory
+      is available. The initial value of this kernel variable is 16MB
+      on 32-bit implementations and 32MB on 64-bit implementations ;
+      it can be manipulated from Lisp (see below.)</para>
+      <para>The large reserved memory block consumes very little in
+      the way of system resources; memory that's actually committed to
+      the lisp heap (live data and the "threshold" area where
+      allocation takes place) consumes finite resources (physical
+      memory and swap space). The lisp's consumption of those
+      resources is proportional to its actual memory usage, which is
+      generally a good thing.</para>
+      <para>This scheme is much more flexible than the old one, but it
+      may also increase the possibility that those resources can
+      become exhausted.  Neither the new scheme nor the old handles
+      that situation gracefully; under the old scheme, a program that
+      consumes lots of memory may have run into an artificial limit on
+      heap size before exhausting virtual memory.</para> 
+
+      <para>The -R or &ndash;heap-reserve command-line option can be
+      use to limit the size of the reserved block and therefore bound
+      heap expansion. Running</para>
+      <programlisting>
+> openmcl --heap-reserve 8M
+</programlisting>
+      <para>would provide an execution environment that's very similar to
+that provided by earlier &CCL; versions.</para>
+    </sect1>
+
+    <sect1 id="The-Ephemeral-GC">
+      <title>The Ephemeral GC</title>
+      <para>For many programs, the following observations are true to
+      a very large degree:</para>
+
+      <orderedlist continuation="restarts" inheritnum="ignore">
+	<listitem>
+	  <para>Most heap-allocated objects have very short lifetimes ("are
+	  ephemeral"): they become inaccessible soon after they're created.</para>
+	</listitem>
+
+	<listitem>
+	  <para>Most non-ephemeral objects have very long lifetimes: it's
+	  rarely productive for the GC to consider reclaiming them, since
+	  it's rarely able to do so. (An object that has survived a large
+	  number of GCs is likely to survive the next one. That's not always
+	  true of course, but it's a reasonable heuristic.)</para>
+	</listitem>
+
+	<listitem>
+	  <para>It's relatively rare for an old object to be destructively
+	  modified (via SETF) so that it points to a new one, therefore most
+	  references to newly-created objects can be found in the stacks and
+	  registers of active threads. It's not generally necessary to scan
+	  the entire heap to find references to new objects (or to prove that
+	  such references don't exists), though it is necessary to keep
+	  track of the (hopefully exceptional) cases where old objects are
+	  modified to point at new ones.</para>
+	</listitem>
+      </orderedlist>
+
+      <para>"Ephemeral" (or "generational") garbage collectors try to
+      exploit these observations: by concentrating on frequently
+      reclaiming newly-created objects quickly, it's less often
+      necessary to do more expensive GCs of the entire heap in order
+      to reclaim unreferenced memory.  In some environments, the
+      pauses associated with such full GCs can be noticeable and
+      disruptive, and minimizing the frequency (and sometimes the
+      duration) of these pauses is probably the EGC's primary goal
+      (though there may be other benefits, such as increased locality
+      of reference and better paging behavior.) The EGC generally
+      leads to slightly longer execution times (and slightly higher,
+      amortized GC time), but there are cases where it can improve
+      overall performance as well; the nature and degree of its impact
+      on performance is highly application-dependent.</para>
+      <para>Most EGC strategies (including the one employed by
+      &CCL;) logically or physically divide memory into one or more
+      areas of relatively young objects ("generations") and one or
+      more areas of old objects.  Objects that have survived one or
+      more GCs as members of a young generation are promoted (or
+      "tenured") into an older generation, where they may or may not
+      survive long enough to be promoted to the next generation and
+      eventually may become "old" objects that can only be reclaimed
+      if a full GC proves that there are no live references to them.
+      This filtering process isn't perfect - a certain amount of
+      premature tenuring may take place - but it usually works very
+      well in practice.</para>
+      <para>It's important to note that a GC of the youngest
+      generation is typically very fast (perhaps a few milliseconds on
+      a modern CPU, depending on various factors), &CCL;'s EGC is
+      not concurrent and doesn't offer realtime guarantees.</para>
+      <para>&CCL;'s EGC maintains three ephemeral generations; all
+      newly created objects are created as members of the youngest
+      generation. Each generation has an associated
+      <emphasis>threshold</emphasis>, which indicates the number of
+      bytes in it and all younger generations that can be allocated
+      before a GC is triggered. These GCs will involve the target
+      generation and all younger ones (and may therefore cause some
+      premature tenuring); since the older generations have larger
+      thresholds, they're GCed less frequently and most short-lived
+      objects that make it into an older generation tend not to
+      survive there very long.</para>
+      <para>The EGC can be <emphasis>enabled</emphasis> or
+      <emphasis>disabled</emphasis> under program control; under some
+      circumstances, it may be enabled but
+      <emphasis>inactive</emphasis> (because a full GC is imminent.)
+      Since it may be hard to know or predict the consing behavior of
+      other threads, the distinction between the "active" and
+      "inactive" state isn't very meaningful, especially when native
+      threads are involved.</para>
+    </sect1>
+
+    <sect1 id="GC-Page-reclamation-policy">
+      <title>GC Page reclamation policy</title>
+      <para>After a full GC finishes, it'll try to ensure that at
+      least (LISP-HEAP-GC-THRESHOLD) of virtual memory are available;
+      objects will be allocated in this block of memory until it fills
+      up, the GC is triggered, and the process repeats itself.</para>
+      <para>Many programs reach near stasis in terms of the amount of
+      logical memory that's in use after full GC (or run for long
+      periods of time in a nearly static state), so the logical
+      address range used for consing after the Nth full GC is likely
+      to be nearly or entirely identical to the address range used by
+      the N+1th full GC.</para>
+      <para>By default (and traditionally in &CCL;), the GC's policy
+      is to "release" the pages in this address range: to advise the
+      virtual memory system that the pages contain garbage and any
+      physical pages associated with them don't need to be swapped out
+      to disk before being reused and to (re-)map the logical address
+      range so that the pages will be zero-filled by the virtual
+      memory system when they're next accessed.  This policy is
+      intended to reduce the load on the VM system and keep &CCL;'s
+      working set to a minimum.</para>
+      <para>For some programs (especially those that cons at a very
+      high rate), the default policy may be less than ideal: releasing
+      pages that are going to be needed almost immediately - and
+      zero-fill-faulting them back in, lazily - incurs unnecessary
+      overhead. (There's a false economy associated with minimizing
+      the size of the working set if it's just going to shoot back up
+      again until the next GC.) A policy of "retaining" pages between
+      GCs might work better in such an environment.</para>
+      <para>Functions described below give the user some control over
+      this behavior. An adaptive, feedback-mediated approach might
+      yield a better solution.</para>
+    </sect1>
+
+    <sect1 id="iPure--areas-are-read-only--paged-from-image-file">
+      <title>"Pure" areas are read-only, paged from image file</title>
+      <para>SAVE-APPLICATION identifies code vectors and the pnames of
+      interned symbols and copies these objects to a "pure" area of
+      the image file it creates. (The "pure" area accounts for most of
+      what the ROOM function reports as "static" space.)</para>
+      <para>When the resulting image file is loaded, the pure area of
+      the file is now memory-mapped with read-only access. Code and
+      pure data are paged in from the image file as needed (and don't
+      compete for global virtual memory resources with other memory
+      areas.)</para>
+      <para>Code-vectors and interned symbol pnames are immutable : it
+      is an error to try to change the contents of such an
+      object. Previously, that error would have manifested itself in
+      some random way. In the new scheme, it'll manifest itself as an
+      "unhandled exception" error in the Lisp kernel. The kernel could
+      probably be made to detect a spurious, accidental write to
+      read-only space and signal a lisp error in that case, but it
+      doesn't yet do so.</para>
+      <para>The image file should be opened and/or mapped in some mode
+      which disallows writing to the memory-mapped regions of the file
+      from other processes. I'm not sure of how to do that; writing to
+      the file when it's mapped by &CCL; can have unpredictable and
+      unpleasant results.  SAVE-APPLICATION will delete its output
+      file's directory entry and create a new file; one may need to
+      exercise care when using file system utilities (like tar, for
+      instance) that might overwrite an existing image file.</para>
+    </sect1>
+
+    <sect1 id="Weak-References">
+      <title>Weak References</title>
+      <para>In general, a "weak reference" is a reference to an object
+      which does not prevent the object from being garbage-collected.
+      For example, suppose that you want to keep a list of all the
+      objects of a certain type.  If you don't take special steps, the
+      fact that you have a list of them will mean that the objects are
+      always "live", because you can always reference them through the
+      list.  Therefore, they will never be garbage-collected, and
+      their memory will never be reclaimed, even if they are
+      referenced nowhere else in the program.  If you don't want this
+      behavior, you need weak references.</para>
+
+      <para>&CCL; supports weak references with two kinds of objects:
+      weak hash tables and populations.</para>
+
+      <para>Weak hash tables are created with the standard Common Lisp
+      function <literal>make-hash-table</literal>, which is extended
+      to accept the keyword argument <literal>:weak</literal>.  Hash
+      tables may be weak with respect to either their keys or their
+      values.  To make a hash table with weak keys, invoke
+      <literal>make-hash-table</literal> with the option :weak t, or,
+      equivalently, :weak :key.  To make one with weak values, use
+      :weak :value.  When the key is weak, the equality test must be
+      #'eq (because it wouldn't make sense otherwise).</para>
+
+      <para>When garbage-collection occurs, key-value pairs are
+      removed from the hash table if there are no non-weak references to
+      the weak element of the pair (key or value).</para>
+
+      <para>In general, weak-key hash tables are useful when you want
+      to use the hash to store some extra information about the
+      objects you look up in it, while weak-value hash tables are
+      useful when you want to use the hash as an index for looking up
+      objects.</para>
+
+      <para>A population encapsulates an object, causing certain
+      reference from the object to be considered weak.  &CCL; supports
+      two kinds of populations: lists, in which case the encapsulated
+      object is a list of elements, which are spliced out of the list
+      when there are no non-weak references to the element; and alists,
+      in which case the encapsulated object is a list of conses which
+      are spliced out of the list if there are no non-weak references
+      to the car of the cons.</para>
+
+    <para>If you are experimenting with weak references
+      interactively, remember that an object is not dead if it was
+      returned by one of the last three interactively-evaluated
+      expressions, because of the variables <literal>*</literal>,
+      <literal>**</literal>, and <literal>***</literal>.  The easy
+      workaround is to evaluate some meaningless expression before
+      invoking <literal>gc</literal>, to get the object out of the
+      REPL variables.</para>
+    </sect1>
+
+    <sect1 id="Weak-References-Dictionary">
+      <title>Weak References Dictionary</title>
+
+    <refentry id="f_make-population">
+      <indexterm zone="f_make-population">
+        <primary>make-population</primary>
+      </indexterm>
+
+      <refnamediv>
+        <refname>MAKE-POPULATION</refname>
+        <refpurpose></refpurpose>
+        <refclass>Function</refclass>
+      </refnamediv>
+        
+      <refsynopsisdiv>
+        <synopsis><function>make-population</function> &key; type initial-contents</synopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+        <title>Arguments and Values</title>
+
+        <variablelist>
+          <varlistentry>
+            <term>type</term>
+            <listitem>
+              <para>The type of population, one of <literal>:LIST</literal> (the default) or <literal>:ALIST</literal></para>
+            </listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term>initial-contents</term>
+            <listitem>
+              <para> A sequence of elements (or conses, for <literal>:alist</literal>) to be used to initialize the
+              population. The sequence itself (and the conses in case of an
+              alist) is not stored in the population, a new list or alist is created to hold the elements.</para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+      </refsect1>
+      <refsect1>
+        <title>Description</title>
+
+        <para>Creates a new population of the specified type.</para>
+      </refsect1>
+    </refentry>
+
+    <refentry id="f_population-type">
+      <indexterm zone="f_population-type">
+        <primary>population-type</primary>
+      </indexterm>
+
+      <refnamediv>
+        <refname>POPULATION-TYPE</refname>
+        <refpurpose></refpurpose>
+        <refclass>Function</refclass>
+      </refnamediv>
+      
+      <refsynopsisdiv>
+        <synopsis><function>population-type</function> population</synopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+        <title>Description</title>
+
+        <para>returns the type of <literal>population</literal>, one of <literal>:LIST</literal> or <literal>:ALIST</literal></para>
+
+      </refsect1>
+    </refentry>
+
+    <refentry id="f_population-contents">
+      <indexterm zone="f_population-contents">
+        <primary>population-contents</primary>
+      </indexterm>
+
+      <refnamediv>
+        <refname>POPULATION-CONTENTS</refname>
+        <refpurpose></refpurpose>
+        <refclass>Function</refclass>
+      </refnamediv>
+      
+      <refsynopsisdiv>
+        <synopsis><function>population-contents</function> population</synopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+        <title>Description</title>
+
+        <para>returns the list encapsulated in <literal>population</literal>.
+        Note that as long as there is a direct (non-weak) reference to this
+        list, it will not be modified by the garbage collector.  Therefore it is
+        safe to traverse the list, and even modify it, no different from any
+        other list. If you want the elements to become garbage-collectable
+        again, you must stop refering to the list directly.</para>
+      </refsect1>
+    </refentry>
+
+
+    <refentry id="f_setf_population-contents">
+      <indexterm zone="f_setf_population-contents">
+        <primary>(setf population-contents)</primary>
+      </indexterm>
+
+      <refnamediv>
+        <refname>(SETF POPULATION-CONTENTS)</refname>
+        <refpurpose></refpurpose>
+        <refclass>Function</refclass>
+      </refnamediv>
+      
+      <refsynopsisdiv>
+        <synopsis>(setf (<function>population-contents</function> population) contents)</synopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+        <title>Description</title>
+
+        <para>Sets the list encapsulated in <literal>population</literal> to
+        <literal>contents</literal>.  <literal>Contents</literal> is not copied,
+        it is used directly.</para>
+      </refsect1>
+    </refentry>
+
+    </sect1>
+
+
+    <sect1 id="Garbage-Collection-Dictionary">
+      <title>Garbage-Collection Dictionary</title>
+
+      <refentry id="f_lisp-heap-gc-threshold">
+	<indexterm zone="f_lisp-heap-gc-threshold">
+	  <primary>lisp-heap-gc-threshold</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>LISP-HEAP-GC-THRESHOLD</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>lisp-heap-gc-threshold</function></synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns the value of the kernel variable that specifies the
+	  amount of free space to leave in the heap after full GC.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_set-lisp-heap-gc-threshold">
+	<indexterm zone="f_set-lisp-heap-gc-threshold">
+	  <primary>set-lisp-heap-gc-threshold</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>SET-LISP-HEAP-GC-THRESHOLD</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis>
+	    <function>set-lisp-heap-gc-threshold</function> new-threshold
+	  </synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>new-threshold</term>
+
+	      <listitem>
+		<para>The requested new lisp-heap-gc-threshold.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Sets the value of the kernel variable that specifies the
+	  amount of free space to leave in the heap after full GC to
+	  new-value, which should be a non-negative fixnum. Returns the
+	  value of that kernel variable (which may be somewhat larger than
+	  what was specified).</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_use-lisp-heap-gc-threshold">
+	<indexterm zone="f_use-lisp-heap-gc-threshold">
+	  <primary>use-lisp-heap-gc-threshold</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>USE-LISP-HEAP-GC-THRESHOLD</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis>
+	    <function>use-lisp-heap-gc-threshold</function>
+	  </synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Tries to grow or shrink lisp&#39;s heap space, so that the
+	  free space is (approximately) equal to the current heap threshold.
+	  Returns NIL</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_egc">
+	<indexterm zone="f_egc">
+	  <primary>egc</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>EGC</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>egc</function> arg</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>arg</term>
+
+	      <listitem>
+		<para>a generalized boolean</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Enables the EGC if arg is non-nil, disables the EGC
+	  otherwise. Returns the previous enabled status. Although this
+	  function is thread-safe (in the sense that calls to it are
+	  serialized), it doesn&#39;t make a whole lot of sense to be
+	  turning the EGC on and off from multiple threads ...</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_egc-enabled-p">
+	<indexterm zone="f_egc-enabled-p">
+	  <primary>egc-enabled-p</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>EGC-ENABLED-P</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>egc-enabled-p</function></synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns T if the EGC was enabled at the time of the call,
+	  NIL otherwise.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_egc-active-p">
+	<indexterm zone="f_egc-active-p">
+	  <primary>egc-active-p</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>EGC-ACTIVE-P</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>egc-active-p</function></synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns T if the EGC was active at the time of the call, NIL
+	  otherwise. Since this is generally a volatile piece of
+	  information, it&#39;s not clear whether this function serves a
+	  useful purpose when native threads are involved.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_egc-configuration">
+	<indexterm zone="f_egc-configuration">
+	  <primary>egc-configuration</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>EGC-CONFIGURATION</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>egc-configuration</function></synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns, as multiple values, the sizes in kilobytes of the
+	  thresholds associated with the youngest ephemeral generation, the
+	  middle ephemeral generation, and the oldest ephemeral generation</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_configure-gcc">
+	<indexterm zone="f_configure-gcc">
+	  <primary>configure-gcc</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>CONFIGURE-GCC</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>configure-egc</function>
+	  generation-0-size generation-1-size
+	  generation-2-size</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>generation-0-size</term>
+
+	      <listitem>
+		<para>the requested threshold size of the youngest
+		generation, in kilobytes</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>generation-1-size</term>
+
+	      <listitem>
+		<para>the requested threshold size of the middle generation,
+		in kilobytes</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>generation-2-size</term>
+
+	      <listitem>
+		<para>the requested threshold size of the oldest generation,
+		in kilobytes</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Puts the indicated threshold sizes in effect.
+          Each threshold indicates the total size that may be allocated
+          in that and all younger generations before a GC is triggered.
+          Disables EGC while setting the values.
+	  (The provided threshold sizes are rounded up to a multiple of
+	  64Kbytes in &CCL; 0.14 and to a multiple of 32KBytes in earlier
+	  versions.)</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_gc-retain-pages">
+	<indexterm zone="f_gc-retain-pages">
+	  <primary>gc-retain-pages</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>GC-RETAIN-PAGES</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>gc-retain-pages</function> arg</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>arg</term>
+
+	      <listitem>
+		<para>a generalized boolean</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Tries to influence the GC to retain/recycle the pages
+	  allocated between GCs if arg is true, and to release them
+	  otherwise. This is generally a tradeoff between paging and other
+	  VM considerations.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_gc-retaining-pages">
+	<indexterm zone="f_gc-retaining-pages">
+	  <primary>gc-retaining-pages</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>GC-RETAINING-PAGES</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>gc-retaining-pages</function></synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns T if the GC tries to retain pages between full GCs
+	  and NIL if it&#39;s trying to release them to improve VM paging
+	  performance.</para>
+	</refsect1>
+      </refentry>
+    </sect1>
+  </chapter>
Index: /branches/new-random/doc/src/glossary.xml
===================================================================
--- /branches/new-random/doc/src/glossary.xml	(revision 13309)
+++ /branches/new-random/doc/src/glossary.xml	(revision 13309)
@@ -0,0 +1,375 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+          "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<glossary id="glossary">
+  <glossaryinfo>
+	<title>Glossary of Terms</title>
+  </glossaryinfo>
+
+  <glossdiv id="A">
+	<!-- ******************** A ********************  -->
+	<title>A</title>
+
+	<glossentry id="application_bundle">
+	  <glossterm>application bundle</glossterm>
+
+	  <glossdef>
+
+		<para>A specially-structured directory that Mac OS X
+		recognizes as a
+		launchable <glossterm linkend="Cocoa">Cocoa</glossterm>
+		application. Graphical applications on Mac OS X are
+		represented as application bundles.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="C">
+	<!-- ******************** C ********************  -->
+	<title>C</title>
+
+	<glossentry id="Cocoa">
+	  <glossterm>Cocoa</glossterm>
+
+	  <glossdef>
+
+		<para>The standard user-interface libraries and frameworks
+		provided by Apple for development of applications on Mac OS
+		X.</para>
+
+	  </glossdef>
+	</glossentry>
+    
+	<glossentry id="creator_code">
+	  <glossterm>creator code</glossterm>
+
+	  <glossdef>
+
+		<para>A four-character identifier used in Mac OS X to uniquely
+		identify an application.</para>
+
+	  </glossdef>
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="D">
+	<!-- ******************** D ********************  -->
+	<title>D</title>
+
+	<glossentry id="displaced-array">
+	  <glossterm>displaced array</glossterm>
+
+	  <glossdef>
+
+		<para>An array with no storage of its own for elements, which
+		points to the storage of another array, called its
+		target. Reading or writing the elements of the displaced array
+		returns or changes the contents of the target.</para>
+
+	  </glossdef>
+	</glossentry>
+
+  </glossdiv>
+
+  <glossdiv id="F">
+	<!-- ******************** F ********************  -->
+	<title>F</title>
+
+	<glossentry id="fasl-file">
+	  <glossterm>fasl file</glossterm>
+
+	  <glossdef>
+
+		<para>A file containing compiled lisp code that the Lisp is
+		able to quickly load and use. A "fast-load" file.</para>
+
+	  </glossdef>
+	</glossentry>
+
+  </glossdiv>
+
+  <glossdiv id="H">
+	<!-- ******************** H ********************  -->
+	<title>H</title>
+
+	<glossentry id="hemlock">
+	  <glossterm>Hemlock</glossterm>
+
+	  <glossdef>
+
+		<para>A text editor, written in Common Lisp, similar in
+		features to Emacs. Hemlock was originally developed as part of
+		CMU Common Lisp. A portable version of Hemlock is built into
+		the &CCL; <glossterm linkend="IDE">IDE</glossterm>.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="I">
+	<!-- ******************** I ********************  -->
+	<title>I</title>
+
+	<glossentry id="IDE">
+	  <glossterm>IDE</glossterm>
+
+	  <glossdef>
+
+		<para>"Integrated Development Environment". In the context of
+		&CCL;, "the IDE" refers to the experimental <glossterm linkend="Cocoa">Cocoa</glossterm>
+		windowing development environment provided in source form with
+		&CCL; distributions.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+	<glossentry id="lisp_image">
+	  <glossterm>image</glossterm>
+
+	  <glossdef>
+
+		<para>The in-memory state of a running Lisp system, containing
+		functions, data structures, variables, and so on. Also, a file
+		containing archived versions of these data in a format that
+		can be loaded and reconstituted by the
+		Lisp <glossterm linkend="lisp_kernel">kernel</glossterm>. A
+		working &CCL; system consists of the kernel and
+		an <glossterm linkend="lisp_image">image</glossterm>.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+	<glossentry id="InterfaceBuilder">
+	  <glossterm>InterfaceBuilder</glossterm>
+
+	  <glossdef>
+
+		<para>An application supplied by Apple with their developer
+		tools that can be used to interactively build user-interface
+		elements for <glossterm linkend="Cocoa">Cocoa</glossterm>
+		applications.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="K">
+	<!-- ******************** K ********************  -->
+	<title>K</title>
+
+	<glossentry id="lisp_kernel">
+	  <glossterm>kernel</glossterm>
+
+	  <glossdef>
+
+		<para>The binary executable program that implements the lowest
+		levels of the Lisp system. A working &CCL; system consists of
+		the kernel and
+		an <glossterm linkend="lisp_image">image</glossterm>.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="L">
+	<!-- ******************** L ********************  -->
+	<title>L</title>
+
+	<glossentry id="listener_window">
+	  <glossterm>listener window</glossterm>
+
+	  <glossdef>
+
+		<para>In the <glossterm linkend="IDE">IDE</glossterm>,
+		a <glossterm linkend="Cocoa">Cocoa</glossterm>
+		window that contains a pseudo-terminal session that
+		communicates with a Lisp <glossterm linkend="REPL">REPL</glossterm>.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="M">
+	<!-- ******************** M ********************  -->
+	<title>M</title>
+
+	<glossentry id="memory_mapped_file">
+	  <glossterm>memory-mapped file</glossterm>
+
+	  <glossdef>
+
+		<para>A file whose contents are accessible as a range of
+		memory addresses. Some operating systems support this feature,
+		in which the virtual memory subsystem arranges for a range of
+		virtual memory addresses to point to the contents of an open
+		file. Programs can then gain access to the file's contents by
+		operating on memory addresses in that range. Access to the
+		file's contents is valid only as long as the file remains
+		open.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="N">
+	<!-- ******************** N ********************  -->
+	<title>N</title>
+
+	<glossentry id="nibfile">
+	  <glossterm>nibfile</glossterm>
+
+	  <glossdef>
+
+		<para>A data file created by
+		Apple's <glossterm linkend="InterfaceBuilder">InterfaceBuilder</glossterm>
+		application, which contains archived Objective-C objects that
+		define user-interface elements for
+		a <glossterm linkend="Cocoa">Cocoa</glossterm>
+		application. Under Mac OS
+		X, <glossterm linkend="Cocoa">Cocoa</glossterm> applications
+		typically create their user interface elements by reading
+		nibfiles and unarchiving the objects in them.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="R">
+
+	<!-- ******************** R ********************  -->
+	<title>R</title>
+
+	<glossentry id="REPL">
+	  <glossterm>REPL</glossterm>
+
+	  <glossdef>
+
+		<para>"Read-eval-print loop". The interactive shell provided
+		by &CCL; for interaction with Lisp.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="S">
+
+	<!-- ******************** S ********************  -->
+	<title>S</title>
+
+	<glossentry id="s-expression">
+	  <glossterm>s-expression</glossterm>
+
+	  <glossdef>
+
+		<para>The simplest, most general element of Lisp syntax. An
+		s-expression may be an atom (such as a symbol, integer, or
+		string), or it may be a list of s-expressions.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+	<glossentry id="special_variable">
+	  <glossterm>special variable</glossterm>
+
+	  <glossdef>
+
+		<para>A variable whose binding is in the dynamic
+		environment. Special variables are essentially equivalent to
+		global variables in languages other than Lisp. A special
+		variable binding is visible in any lexical environment, so
+		long as a lexical binding has not shadowed it.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+	<glossentry id="static_variable">
+	  <glossterm>static variable</glossterm>
+
+	  <glossdef>
+
+		<para>In &CCL;, a variable whose value is shared across all
+		threads, and which may not be dynamically rebound. Changing a
+		static variable's value in one thread causes all threads to
+		see the new value. Attempting to dynamically rebind the
+		variable (for instance, by using <code>LET</code>, or using
+		the variable name as a parameter in a <code>LAMBDA</code>
+		form) signals an error.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+  <glossdiv id="T">
+
+	<!-- ******************** T ********************  -->
+	<title>T</title>
+
+	<glossentry id="toplevel_function">
+	  <glossterm>toplevel function</glossterm>
+
+	  <glossdef>
+
+		<para>The function executed by Lisp automatically once its
+		startup is complete. &CCL;'s default toplevel is the
+		interactive <glossterm linkend="REPL">read-eval-print
+		loop</glossterm> that you normally use to interact with
+		Lisp. You can, however, replace the toplevel with a function
+		of your own design, changing &CCL; from a Lisp development
+		system into some tool of your making.</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+	<glossentry id="type-specifier">
+	  <glossterm>type-specifier</glossterm>
+
+	  <glossdef>
+
+		<para>An expression that denotes a type. Type specifiers may
+		be symbols (such as <code>CONS</code>
+		and <code>STRING</code>), or they may be more complex
+		<glossterm linkend="s-expression">S-expressions</glossterm>
+		(such as (UNSIGNED-BYTE 8)).</para>
+
+	  </glossdef>
+
+	</glossentry>
+    
+  </glossdiv>
+
+</glossary>
+
Index: /branches/new-random/doc/src/ide.xml
===================================================================
--- /branches/new-random/doc/src/ide.xml	(revision 13309)
+++ /branches/new-random/doc/src/ide.xml	(revision 13309)
@@ -0,0 +1,516 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+          "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="ccl-ide"><title>The &CCL; IDE</title>
+  
+  <!-- ================================================================ -->
+  <sect1 id="ccl-ide-introduction"><title>Introduction</title>
+    
+    <para>&CCL; ships with the complete source code for an integrated
+    development environment written using Cocoa on Mac OS X. This
+    chapter describes how to build and use that environment,
+    referred to hereafter simply as "the IDE".</para>
+
+    <para>The IDE provides a programmable text editor, listener
+      windows, an inspector for Lisp data structures, and a means of
+      easily building a Cocoa application in Lisp. In addition, its
+      source code provides an example of a fairly complex Cocoa
+      application written in Lisp.</para>
+
+    <para>The current version of the IDE has seen the addition of numerous
+    features and many bugfixes. Although it's by no means a finished product,
+    we hope it will prove more useful than previous versions, and we
+    plan additional work on the IDE for future releases.</para>
+  </sect1>
+
+  <!-- ================================================================ -->
+  <sect1 id="building-ccl-ide"><title>Building the IDE</title>
+    
+    <para>Building the &CCL; IDE is now a very simple
+      process.</para>
+
+    <orderedlist>
+      <listitem>
+        <para>In a shell session, cd to the ccl directory.</para>
+      </listitem>
+      <listitem>
+        <para>Run ccl from the shell. The easiest way to do this is
+          generally to execute the ccl or ccl64 command.</para>
+      </listitem>
+      <listitem>
+        <para>Evaluate the form <code language="lisp">(require :cocoa-application)</code></para>
+      </listitem>
+    </orderedlist>
+
+    <para>For example, assuming that the &CCL; distribution is
+      installed in "/usr/local/ccl", the following sequence of shell
+      interactions builds the IDE:</para>
+
+    <programlisting>
+oshirion:ccl mikel$ ccl64
+Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk  (DarwinX8664)!
+? (require :cocoa-application)
+;Loading #P"ccl:cocoa-ide;fasls;cocoa-utils.dx64fsl.newest"...
+;Loading #P"ccl:cocoa-ide;fasls;cocoa-defaults.dx64fsl.newest"...
+
+[...many lines of "Compiling" and "Loading" omitted...]
+
+Saving application to /usr/local/ccl/Clozure CL.app/
+
+oshirion:ccl mikel$ 
+
+    </programlisting>
+
+    <para>&CCL; compiles and loads the various subsystems that
+      make up the IDE, then constructs a Cocoa application bundle
+      named "Clozure CL.app" and saves the Lisp image into
+      it. Normally &CCL; creates the application bundle in the root
+      directory of the &CCL; distribution.</para>
+
+  </sect1>
+
+  <!-- ================================================================ -->
+  <sect1 id="running-ccl-ide"><title>Running the IDE</title>
+    
+    <para>After it has been built, you can run the "Clozure CL.app"
+      application normally, by double-clicking its icon. When
+      launched, the IDE initially displays a
+      single <glossterm linkend="listener_window">listener
+        window</glossterm> that you can use to interact with Lisp. You
+      can type Lisp expressions for evaluation at the prompt in the
+      listener window. You can also
+      use <glossterm linkend="hemlock">Hemlock</glossterm> editing
+      commands to edit the text of expressions in the listener
+      window.</para>
+
+  </sect1>
+
+  <!-- ================================================================ -->
+  <sect1 id="ccl-ide-features">
+    <title>IDE Features</title>
+
+    <sect2 id="ide-editor-windows">
+      <title>Editor Windows</title>
+      <para>You can open an editor window either by choosing Open from
+        the File menu and then selecting a text file, or by choosing
+        New from the File menu. You can also evaluate the
+        expression <code>(ed)</code> in the listener window; in that
+        case &CCL; creates a new window as if you had chosen New from
+        the File menu.</para>
+
+      <para>Editor windows
+        implement <glossterm linkend="hemlock">Hemlock</glossterm>
+        editing commands. You can use all the editing and customization
+        features of Hemlock within any editor window (including listener
+        windows).</para>
+    </sect2>
+    
+    <sect2 id="ide-lisp-menu">
+      <title>The Lisp Menu</title>
+      <para>The Lisp menu provides several commands for interacting
+        with the running Lisp session, in addition to the ways you can
+        interact with it by evaluating expressions. You can evaluate a
+        selected range of text in any editing buffer. You can compile
+        and load the contents of editor windows (please note that in the
+        current version, &CCL; compiles and loads the contents of the
+        file associated with an editor window; that means that if you
+        try to load or compile a window that has not been saved to a
+        file, the result is an error).</para>
+
+      <para>You can interrupt computations, trigger breaks, and select
+        restarts from the Lisp menu. You can also display a backtrace or
+        open the <link linkend="section_inspector_window">Inspector
+          window</link>.</para>
+
+      <sect3>
+        <title>Checking for Updates</title>
+        <para>At the bottom of the Lisp menu is an item entitled
+        "Check for Updates". If your copy of &CCL; came from the
+        Clozure Subversion server (which is the preferred source), and
+        if your internet connection is working, then you can select
+        this menu item to check for updates to your copy of
+        &CCL;.</para>
+
+        <para>When you select "Check for Updates", &CCL; uses the svn
+        program to query the Clozure Subversion repository and
+        determine whether new updates to &CCL; are available. (This
+        means that on Mac OS X versions earlier than 10.5, you must
+        ensure that the Subversion client software is installed before
+        using the "Check for Updates" feature. See
+        the <ulink url="http://www.wikihow.com/Install-Subversion-on-Mac-OS-X">wikiHow
+        page</ulink> on installing Subversion for more information.)
+        If updates are available, &CCL; automatically downloads and
+        installs them. After a successful download, &CCL; rebuilds
+        itself, and then rebuilds the IDE on the newly-rebuilt
+        Lisp. Once this process is finished, you should quit the
+        running IDE and start the newly built one (which will be in
+        the same place that the old one was).</para>
+
+        <para>Normally, &CCL; can install updates and rebuild itself
+        without any problems. Occasionally, an unforeseen problem
+        (such as a network outage, or a hardware failure) might
+        interrupt the self-rebuilding process, and leave your copy of
+        &CCL; unusable. If you are expecting to update your copy of
+        &CCL; frequently, it might be prudent to keep a backup copy of
+        your working environment ready in case of such
+        situtations. You can also always obtain a full, fresh copy of
+        &CCL; from Clozure's repository..</para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="ide-tools-menu">
+      <title>The Tools Menu</title>
+      <para>The tools menu provides access to the Apropos and
+        Processes windows. The Apropos window searches the running Lisp
+        image for symbols that match any text you enter. You can use the
+        Apropos window to quickly find function names and other useful
+        symbols. The Processes window lists all threads running in the
+        current Lisp session. If you double-click a process entry, &CCL;
+        opens an <link linkend="section_inspector_window">Inspector
+          window</link> on that process.</para>
+    </sect2>
+
+    <sect2 id="ide-inspector-window">
+      <title>The Inspector Window</title>
+      <anchor id="section_inspector_window"/>
+      <para>The Inspector window displays information about a Lisp
+        value. The information displayed varies from the very simple, in
+        the case of a simple data value such as a character, to the
+        complex, in the case of structured data such as lists or CLOS
+        objects. The left-hand column of the window's display shows the
+        names of the object's attributes; the righthand column shows the
+        values associated with those attributes. You can inspect the
+        values in the righthand column by double-clicking them.</para>
+
+      <para>Inspecting a value in the righthand column changes the
+        Inspector window to display the double-clicked object. You can
+        quickly navigate the fields of structured data this way,
+        inspecting objects and the objects that they refer
+        to. Navigation buttons at the top left of the window enable you
+        to retrace your steps, backing up to return to previously-viewed
+        objects, and going forward again to objects you navigated into
+        previously.</para>
+
+      <para>You can change the contents of a structured object by
+        evaluating expressions in a listener window. The refresh button
+        (marked with a curved arrow) updates the display of the
+        Inspector window, enabling you to quickly see the results of
+        changing a data structure.</para>
+    </sect2>
+
+  </sect1>
+  
+  <!-- ================================================================ -->
+  <sect1 id="ide-source-code"><title>IDE Sources</title>
+    
+    <para>&CCL; builds the IDE from sources in the "objc-bridge" and
+      "cocoa-ide" directories in the &CCL; distribution. The IDE as a
+      whole is a relatively complicated application, and is probably not
+      the best place to look when you are first trying to understand how
+      to build Cocoa applications. For that, you might benefit more from
+      the examples in the "examples/cocoa/" directory. Once you are
+      familiar with those examples, though, and have some experience
+      building your own application features using Cocoa and the
+      Objective-C bridge, you might browse through the IDE sources to
+      see how it implements its features.</para>
+
+    <para>The search path for &CCL;'s <code>REQUIRE</code> feature
+      includes the "objc-bridge" and "cocoa-ide" directories. You can
+      load features defined in these directories by
+      using <code>REQUIRE</code>. For example, if you want to use the
+      Cocoa features of &CCL; from a terminal session (or from an Emacs
+      session using SLIME or ILISP), you can evaluate <code>(require
+        :cocoa)</code>.</para>
+  </sect1>
+
+  <!-- ================================================================ -->
+  <sect1 id="application-builder"><title>The Application Builder</title>
+    <anchor id="application_builder"/>
+    <para>One important feature of the IDE currently has no Cocoa user
+      interface: the application builder. The application builder
+      constructs a
+      Cocoa <glossterm linkend="application_bundle">application
+        bundle</glossterm> that runs a Lisp image when double-clicked. You
+      can use the application builder to create Cocoa applications in
+      Lisp. These applications are exactly like Cocoa applications
+      created with XCode and Objective-C, except that they are written
+      in Lisp.</para>
+
+    <para>To make the application builder available, evaluate the
+      expression <code>(require :build-application)</code>. &CCL; loads
+      the required subsystems, if necessary.</para>
+
+    <para>
+      <indexterm zone="build-application"/>
+      <command><varname id="build-application">BUILD-APPLICATION</varname> <varname>&key;</varname>
+        (<parameter>name</parameter> <replaceable>"MyApplication"</replaceable>)
+        (<parameter>type-string</parameter> <replaceable>"APPL"</replaceable>)
+        (<parameter>creator-string</parameter> <replaceable>"OMCL"</replaceable>)
+        (<parameter>directory</parameter> <replaceable>(current-directory)</replaceable>)
+        (<parameter>copy-ide-resources</parameter> <replaceable>t</replaceable>)
+        (<parameter>info-plist</parameter> <replaceable>NIL</replaceable>)
+        (<parameter>nibfiles</parameter> <replaceable>NIL</replaceable>)
+        (<parameter>main-nib-name</parameter> <replaceable>NIL</replaceable>)
+        (<parameter>application-class</parameter> <replaceable>'GUI::COCOA-APPLICATION</replaceable>)
+        (<parameter>toplevel-function</parameter> <replaceable>NIL</replaceable>)
+        [Function]</command>
+    </para>
+
+    <para>
+      The <varname>build-application</varname> function constructs an
+      application bundle, populates it with the files needed to satisfy
+      Mac OS X that the bundle is a launchable application, and saves an
+      executable Lisp image to the proper subdirectory of the
+      bundle. Assuming that the saved Lisp image contains correct code,
+      a user can subsequently launch the resulting Cocoa application by
+      double-clicking its icon in the Finder, and the saved Lisp
+      environment runs.
+    </para>
+
+    <para>The keyword arguments control various aspects of application
+      bundle as <code>BUILD-APPLICATION</code> builds it.</para>
+    <variablelist>
+
+      <varlistentry>
+        <term><varname>name</varname></term>
+        <listitem>
+          <para>Specifies the application name of the
+            bundle. <code>BUILD-APPLICATION</code> creates an application
+            bundle whose name is given by this parameter, with the
+            extension ".app" appended. For example, using the default
+            value for this parameter results in a bundle named
+            "MyApplication.app".</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>type-string</varname></term>
+        <listitem>
+          <para>Specifies type of bundle to create. You should normally
+            never need to change the default value, which Mac OS X uses to
+            identify application bundles.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>creator-string</varname></term>
+        <listitem>
+          <para>Specifies the <glossterm linkend="creator_code">creator
+              code</glossterm>, which uniquely identifies the application
+            under Mac OS X. The default creator code is that of &CCL;. For
+            more information about reserving and assigning creator codes,
+            see
+            Apple's <ulink url="http://developer.apple.com/datatype/index.html">developer
+              page</ulink> on the topic.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>directory</varname></term>
+        <listitem>
+          <para>The directory in which <code>BUILD-APPLICATION</code>
+            creates the application bundle. By default, it creates the
+            bundle in the current working directory. Unless you
+            use <code>CURRENT-DIRECTORY</code> to set the working
+            directory, the bundle may be created in some unexpected place,
+            so it's safest to specify a full pathname for this argument. A
+            typical value might be <code>"/Users/foo/Desktop/"</code>
+            (assuming, of course, that your username is "foo").</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>copy-ide-resources</varname></term>
+        <listitem>
+          <para>Whether to copy the resource files from the IDE's
+            application bundle. By
+            default, <code>BUILD-APPLICATION</code> copies nibfiles
+            and other resources from the IDE to the newly-created
+            application bundle. This option is often useful when you
+            are developing a new application, because it enables your
+            built application to have a fully-functional user
+            interface even before you have finished designing one. By
+            default, the application uses the application menu and
+            other UI elements of the IDE until you specify
+            otherwise. Once your application's UI is fully
+            implemented, you may choose to pass <literal>NIL</literal>
+            for the value of this parameter, in which case the IDE
+            resources are not copied into your application
+            bundle.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>info-plist</varname></term>
+        <listitem>
+          <para>A user-supplied NSDictionary object that defines the
+          contents of the Info.plist file to be written to the
+          application bundle. The default value
+          is <literal>NIL</literal>, which specifies that the
+          Info.plist from the IDE is to be used
+          if <replaceable>copy-ide-resources</replaceable> is true,
+          and a new dictionary created with default values is to be
+          used otherwise. You can create a suitable NSDictionary
+          object using the
+          function <literal>make-info-dict</literal>. For details on
+          the parameters to this function, see its definition in
+          "ccl/cocoa-ide/builder-utilities.lisp".</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>nibfiles</varname></term>
+        <listitem>
+          <para>A list of pathnames, where each pathname identifies
+            a <glossterm linkend="nibfile">nibfile</glossterm> created
+            with
+            Apple's <glossterm linkend="InterfaceBuilder">InterfaceBuilder</glossterm>
+            application. <code>BUILD-APPLICATION</code> copies each
+            nibfile into the appropriate place in the application bundle,
+            enabling the application to load user-interface elements from
+            them as-needed. It is safest to provide full pathnames to the
+            nibfiles in the list. Each nibfile must be in ".nib" format,
+            not ".xib" format, in order that the application can load
+            it.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>main-nib-name</varname></term>
+        <listitem>
+          <para>The name of
+            the <glossterm linkend="nibfile">nibfile</glossterm> to load
+            initially when launching. The user-interface defined in this
+            nibfile becomes the application's main interface. You must
+            supply the name of a suitable nibfile for this parameter, or
+            the resulting application uses the &CCL; user
+            interface.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>application-class</varname></term>
+        <listitem>
+          <para>The name of the application's CLOS class. The default
+            value is the class provided by &CCL; for graphical
+            applications. Supply the name of your application class if you
+            implement one. If not, &CCL; uses the default class.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>toplevel-function</varname></term>
+        <listitem>
+          <para>The toplevel function that runs when the application
+            launches. Normally the default value, which is &CCL;'s
+            toplevel, works well, but in some cases you may wish to
+            customize the behavior of the application's toplevel. The best
+            source of information about writing your own toplevel is the
+            &CCL; source code, especially the implementations
+            of <code>TOPLEVEL-FUNCTION</code> in
+            "ccl/level-1/l1-application.lisp"</para>
+        </listitem>
+      </varlistentry>
+
+    </variablelist>
+
+    <para><code>BUILD-APPLICATION</code> creates a folder named
+      "<replaceable>name</replaceable>.app" in the
+      directory <replaceable>directory</replaceable>. Inside that
+      folder, it creates the "Contents" folder that Mac OS X
+      application bundles are expected to contain, and populates it
+      with the "MacOS" and "Resources" folders, and the "Info.plist"
+      and "PkgInfo" files that must be present in a working
+      application bundle. It takes the contents of the "Info.plist"
+      and "PkgInfo" files from the parameters
+      to <code>BUILD-APPLICATION</code>. If <replaceable>copy-ide-resources</replaceable>
+      is true then it copies the contents of the "Resources" folder
+      from the "Resources" folder of the running IDE.</para>
+
+    <para>The work needed to produce a running Cocoa application is
+    very minimal. In fact, if you
+    supply <code>BUILD-APPLICATION</code> with a valid nibfile and
+    pathnames, it builds a running Cocoa application that displays
+    your UI. It doesn't need you to write any code at all to do
+    this. Of course, the resulting application doesn't do anything
+    apart from displaying the UI defined in the nibfile. If you want
+    your UI to accomplish anything, you need to write the code to
+    handle its events. But the path to a running application with your
+    UI in it is very short indeed.</para>
+
+   <para>Please note that <code>BUILD-APPLICATION</code> is a work in
+    progress. It can easily build a working Cocoa application, but it
+    still has limitations that may in some cases prove
+    inconvenient. For example, in the current version it provides no
+    easy way to specify an application delegate different from the
+    default. If you find the current limitations
+    of <code>BUILD-APPLICATION</code> too restrictive, and want to try
+    extending it for your use, you can find the source code for it in
+    "ccl/cocoa-ide/build-application.lisp". You can see the default
+    values used to populate the "Info.plist" file in
+    "ccl/cocoa-ide/builder-utilities.lisp".</para>
+
+    <para>For more information on how to
+    use <code>BUILD-APPLICATION</code>, see the Currency Converter
+    example in "ccl/examples/cocoa/currency-converter/".</para>
+
+    <!-- ***************************************************** -->
+    <sect2 id="running-the-application-builder-from-command-line">
+      <title>Running the Application Builder From the Command
+      Line</title>
+
+      <para>It's possible to automate use of the application builder
+        by running a call to <literal>CCL:BUILD-APPLICATION</literal>
+        from the terminal command line. For example, the following
+        command, entered at a shell prompt in Mac OS X's Terminal
+        window, builds a working copy of the &CCL; environment called
+        "Foo.app":</para>
+
+      <programlisting>
+ccl -b -e "(require :cocoa)" -e "(require :build-application)" -e "(ccl::build-application :name \"Foo\")"
+      </programlisting>
+
+      <para>You can use the same method to automate building your
+      Lisp/Cocoa applications. &CCL; handles each Lisp expressions
+      passed with a <literal>-e</literal> argument in order, so you
+      can simply evaluate a sequence of Lisp expressions as in the
+      above example to build your application, ending with a call
+      to <literal>CCL:BUILD-APPLICATION</literal>. The call
+      to <literal>CCL:BUILD-APPLICATION</literal> can process all the
+      same arguments as if you evaluated it in a Listener window in
+      the &CCL; IDE.</para>
+
+      <para>Building a substantial Cocoa application (rather than just
+      reproducing the Lisp environment using defaults, as is done in
+      the above example) is likely to involve a relatively complicated
+      sequence of loading source files and perhaps evaluating Lisp
+      forms. You might be best served to place your command line in a
+      shell script that you can more easily edit and test.</para>
+
+      <para>One potentially complicated issue concerns loading all
+        your Lisp source files in the right order. You might consider
+        using ASDF to define and load a system that includes all the
+        parts of your application before
+        calling <literal>CCL:BUILD-APPLICATION</literal>. ASDF is a
+        "another system-definition facility", a sort
+        of <literal>make</literal> for Lisp, and is included in the
+        &CCL; distribution. You can read more about ASDF at the ASDF
+        <ulink url="http://constantly.at/lisp/asdf/">home
+        page</ulink>.</para>
+
+      <para>Alternatively, you could use the standard features of
+        Common Lisp to load your application's files in the proper
+        order.</para>
+    </sect2>
+  </sect1>
+
+</chapter>
Index: /branches/new-random/doc/src/implementation.xml
===================================================================
--- /branches/new-random/doc/src/implementation.xml	(revision 13309)
+++ /branches/new-random/doc/src/implementation.xml	(revision 13309)
@@ -0,0 +1,1542 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "Clozure CL">
+]>
+  <chapter id="Implementation-Details-of-CCL">
+    <title>Implementation Details of &CCL;</title>
+    <para>This chapter describes many aspects of OpenMCL's
+    implementation as of (roughly) version 1.1. Details vary a bit
+    between the three architectures (PPC32, PPC64, and x86-64)
+    currently supported and those details change over time, so the
+    definitive reference is the source code (especially some files in
+    the ccl/compiler/ directory whose names contain the string "arch"
+    and some files in the ccl/lisp-kernel/ directory whose names
+    contain the string "constants".) Hopefully, this chapter will make
+    it easier for someone who's interested to read and understand the
+    contents of those files.</para>
+
+    <sect1 id="Threads-and-exceptions">
+      <title>Threads and exceptions</title>
+
+      <para>&CCL;'s threads are "native" (meaning that they're
+        scheduled and controlled by the operating system.)  Most of the
+        implications of this are discussed elsewhere; this section tries
+        to describe how threads look from the lisp kernel's perspective
+        (and especially from the GC's point of view.)</para>
+      <para>&CCL;'s runtime system tries to use machine-level
+        exception mechanisms (conditional traps when available,
+        illegal instructions, memory access protection in some cases)
+        to detect and handle exceptional situations.  These situations
+        include some TYPE-ERRORs and PROGRAM-ERRORS (notably
+        wrong-number-of-args errors), and also include cases like "not
+        being able to allocate memory without GCing or obtaining more
+        memory from the OS."  The general idea is that it's usually
+        faster to pay (very occasional) exception-processing overhead
+        and figure out what's going on in an exception handler than it
+        is to maintain enough state and context to handle an
+        exceptional case via a lighter-weight mechanism when that
+        exceptional case (by definition) rarely occurs.</para>
+      <para>Some emulated execution environments (the Rosetta PPC
+        emulator on x86 versions of Mac OS X) don't provide accurate
+        exception information to exception handling functions. &CCL;
+        can't run in such environments.</para>
+
+      <sect2 id="The-Thread-Context-Record">
+	    <title>The Thread Context Record</title>
+
+	    <para>When a lisp thread is first created (or when a thread
+          created by foreign code first calls back to lisp), a data
+          structure called a Thread Context Record (or TCR) is
+          allocated and initialized.  On modern versions of Linux and
+          FreeBSD, the allocation actually happens via a set of
+          thread-local-storage ABI extensions, so a thread's TCR is
+          created when the thread is created and dies when the thread
+          dies.  (The World's Most Advanced Operating System&mdash;as
+          Apple's marketing literature refers to Darwin&mdash;is not
+          very advanced in this regard, and I know of no reason to
+          assume that advances will be made in this area anytime
+          soon.)</para>
+        <para>A TCR contains a few dozen fields (and is therefore a
+          few hundred bytes in size.)  The fields are mostly
+          thread-specific information about the thread's stacks'
+          locations and sizes, information about the underlying (POSIX)
+          thread, and information about the thread's dynamic binding
+          history and pending CATCH/UNWIND-PROTECTs.  Some of this
+          information could be kept in individual machine registers
+          while the thread is running (and the PPC - which has more
+          registers available - keeps a few things in registers that the
+          X86-64 has to access via the TCR), but it's important to
+          remember that the information is thread-specific and can't
+          (for instance) be kept in a fixed global memory
+          location.</para>
+        <para>When lisp code is running, the current thread's TCR is
+          kept in a register.  On PPC platforms, a general purpose
+          register is used; on x86-64, an (otherwise nearly useless)
+          segment register works well (prevents the expenditure of a
+          more generally useful general- purpose register for this
+          purpose.)</para>
+        <para>The address of a TCR is aligned in memory in such a way
+          that a FIXNUM can be used to represent it.  The lisp function
+          CCL::%CURRENT-TCR returns the calling thread's TCR as a
+          fixnum; actual value of the TCR's address is 4 or 8 times the
+          value of this fixnum.</para>
+        <para>When the lisp kernel initializes a new TCR, it's added
+          to a global list maintained by the kernel; when a thread
+          exits, its TCR is removed from this list.</para>
+        <para>When a thread calls foreign code, lisp stack pointers
+          are saved in its TCR, lisp registers (at least those whose
+          value should be preserved across the call) are saved on the
+          thread's value stack, and (on x86-64) RSP is switched to the
+          control stack.  A field in the TCR (tcr.valence) is then set
+          to indicate that the thread is running foreign code, foreign
+          argument registers are loaded from a frame on the foreign
+          stack, and the foreign function is called. (That's a little
+          oversimplified and possibly inaccurate, but the important
+          things to note are that the thread "stops following lisp
+          stack and register usage conventions" and that it advertises
+          the fact that it's done so.  Similar transitions in a
+          thread's state ("valence") occur when it enters or exits an
+          exception handler (which is sort of an OS/hardware-mandated
+          foreign function call where the OS thoughtfully saves the
+          thread's register state for it beforehand.)</para>
+      </sect2>
+
+      <sect2 id="Exception-contexts-comma---and-exception-handling-in-general">
+	    <title>Exception contexts, and exception-handling in general</title>
+        <para>Unix-like OSes tend to refer to exceptions as "signals";
+          the same general mechanism ("signal handling") is used to
+          process both asynchronous OS-level events (such as the result
+          of the keyboard driver noticing that ^C or ^Z has been
+          pressed) and synchronous hardware-level events (like trying to
+          execute an illegal instruction or access protected memory.)
+          It makes some sense to defer ("block") handling of
+          asynchronous signals so that some critical code sequences
+          complete without interruption; since it's generally not
+          possible for a thread to proceed after a synchronous exception
+          unless and until its state is modified by an exception
+          handler, it makes no sense to talk about blocking synchronous
+          signals (though some OSes will let you do so and doing so can
+          have mysterious effects.)</para>
+        <para>On OSX/Darwin, the POSIX signal handling facilities
+          coexist with lower-level Mach-based exception handling
+          facilities.  Unfortunately, the way that this is implemented
+          interacts poorly with debugging tools: GDB will generally stop
+          whenever the target program encounters a Mach-level exception
+          and offers no way to proceed from that point (and let the
+          program's POSIX signal handler try to handle the exception);
+          Apple's CrashReporter program has had a similar issue and,
+          depending on how it's configured, may bombard the user with
+          alert dialogs which falsely claim that an application has
+          crashed (when in fact the application in question has
+          routinely handled a routine exception.)  On Darwin/OSX,
+          &CCL; uses Mach thread-level exception handling facilities
+          which run before GDB or CrashReporter get a chance to confuse
+          themselves; &CCL;'s Mach exception handling tries to force
+          the thread which received a synchronous exception to invoke a
+          signal handling function ("as if" signal handling worked more
+          usefully under Darwin.)  Mach exception handlers run in a
+          dedicated thread (which basically does nothing but wait for
+          exception messages from the lisp kernel, obtain and modify
+          information about the state of threads in which exceptions
+          have occurred, and reply to the exception messages with an
+          indication that the exception has been handled.  The reply
+          from a thread-level exception handler keeps the exception from
+          being reported to GDB or CrashReporter and avoids the problems
+          related to those programs.  Since &CCL;'s Mach exception
+          handler doesn't claim to handle debugging-related exceptions
+          (from breakpoints or single-step operations), it's possible to
+          use GDB to debug &CCL;.</para>
+        <para>On platforms where signal handling and debugging don't
+          get in each other's way, a signal handler is entered with
+          all signals blocked.  (This behavior is specified in the
+          call to the sigaction() function which established the
+          signal handler.)  The signal handler receives three
+          arguments from the OS kernel; the first is an integer that
+          identifies the signal, the second is a pointer to an object
+          of type "siginfo_t", which may or may not contain a few
+          fields that would help to identify the cause of the
+          exception, and the third argument is a pointer to a data
+          structure (called a "ucontext" or something similar), which
+          contains machine-dependent information about the state of
+          the thread at the time that the exception/signal occurred.
+          While asynchronous signals are blocked, the signal handler
+          stores the pointer to its third argument (the "signal
+          context") in a field in the current thread's TCR, sets some
+          bits in another TCR field to indicate that the thread is now
+          waiting to handle an exception, unblocks asynchronous
+          signals, and waits for a global exception lock that
+          serializes exception processing.</para>
+        <para>On Darwin, the Mach exception thread creates a signal
+          context (and maybe a siginfo_t structure), stores the signal
+          context in the thread's TCR, sets the TCR field which describes
+          the thread's state, and arranges that the thread resume
+          execution at its signal handling function (with a signal
+          handler, possibly NULL siginfo_t, and signal context as
+          arguments.  When the thread resumes, it waits for the global
+          exception lock.</para>
+        <para>On x86-64 platforms where signal handing can be used to
+          handle synchronous exceptions, there's an additional
+          complication: the OS kernel ordinarily allocates the signal
+          context and siginfo structures on the stack of the thread
+          that received the signal; in practice, that means "wherever
+          RSP is pointing."  &CCL;'s
+          <xref linkend="Register-and-stack-usage-conventions"/>
+          require that the thread's value stack&mdash;where RSP is
+          usually pointing while lisp code is running&mdash;contain
+          only "nodes" (properly tagged lisp objects), and scribbling
+          a signal context all over the value stack would violate this
+          requirement.  To maintain consistency, the sigaltstack()
+          mechanism is used to cause the signal to be delivered on
+          (and the signal context and siginfo to be allocated on) a
+          special stack area (the last few pages of the thread's
+          control stack, in practice).  When the signal handler runs,
+          it (carefully) copies the signal context and siginfo to the
+          thread's control stack and makes RSP point into that stack
+          before invoking the "real" signal handler. The effect of
+          this hack is that the "real" signal handler always runs on
+          the thread's control stack.</para>
+        <para>Once the exception handler has obtained the global
+          exception lock, it uses the values of the signal number,
+          siginfo_t, and signal context arguments to determine the
+          (logical) cause of the exception.  Some exceptions may be
+          caused by factors that should generate lisp errors or other
+          serious conditions (stack overflow); if this is the case, the
+          kernel code may release the global exception lock and call out
+          to lisp code.  (The lisp code in question may need to repeat
+          some of the exception decoding process; in particular, it
+          needs to be able to interpret register values in the signal
+          context that it receives as an argument.)</para>
+        <para>In some cases, the lisp kernel exception handler may not
+          be able to recover from the exception (this is currently true
+          of some types of memory-access fault and is also true of traps
+          or illegal instructions that occur during foreign code
+          execution.  In such cases, the kernel exception handler
+          reports the exception as "unhandled", and the kernel debugger
+          is invoked.</para>
+        <para>If the kernel exception handler identifies the
+          exception's cause as being a transient out-of-memory condition
+          (indicating that the current thread needs more memory to cons
+          in), it tries to make that memory available.  In some cases,
+          doing so involves invoking the GC.</para>
+      </sect2>
+
+      <sect2 id="Threads-comma---exceptions-comma---and-the-GC">
+	    <title>Threads, exceptions, and the GC</title>
+        <para>&CCL;'s GC is not concurrent: when the GC is invoked in
+          response to an exception in a particular thread, all other
+          lisp threads must stop until the GC's work is done.  The
+          thread that triggered the GC iterates over the global TCR
+          list, sending each other thread a distinguished "suspend"
+          signal, then iterates over the list again, waiting for a
+          per-thread semaphore that indicates that the thread has
+          received the "suspend" signal and responded appropriately.
+          Once all other threads have acknowledged the request to
+          suspend themselves, the GC thread can run the GC proper (after
+          doing any necessary <xref linkend="PC-lusering"/>.)  Once the
+          GC's completed its work, the thread that invoked the GC
+          iterates over the global TCR list, raising a per-thread
+          "resume" semaphore for each other thread.</para>
+        <para>The signal handler for the asynchronous "suspend" signal
+          is entered with all asynchronous signals blocked.  It saves
+          its signal-context argument in a TCR slot, raises the tcr's
+          "suspend" semaphore, then waits on the TCR's "resume"
+          semaphore.</para>
+        <para>The GC thread has access to the signal contexts of all
+          TCRs (including its own) at the time when the thread received
+          an exception or acknowledged a request to suspend itself.
+          This information (and information about stack areas in the TCR
+          itself) allows the GC to identify the "stack locations and
+          register contents" that are elements of the GC's root
+          set.</para>
+      </sect2>
+
+      <sect2 id="PC-lusering">
+	    <title>PC-lusering</title>
+        <para>It's not quite accurate to say that &CCL;'s compiler
+          and runtime follow precise stack and register usage
+          conventions at all times; there are a few exceptions:</para>
+
+	    <itemizedlist>
+          <listitem>
+	        <para>On both PPC and x86-64 platforms, consing isn't
+	          fully atomic.It takes at least a few instructions to
+	          allocate an object in memory(and slap a header on it if
+	          necessary); if a thread is interrupted in the middle of
+	          that instruction sequence, the new object may or may
+	          not have been created or fully initialized at the point in
+	          time that the interrupt occurred.  (There are actually a
+	          few different states of partial initialization)</para>
+	      </listitem>
+	      <listitem>
+	        <para>On the PPC, the common act of building a lisp
+	          control stack frame involves allocating a four-word frame
+	          and storing three register values into that frame.  (The
+	          fourth word - the back pointer to the previous frame - is
+	          automatically set when the frame is allocated.)  The
+	          previous contents of those three words are unknown (there
+	          might have been a foreign stack frame at the same address a
+	          few instructions earlier),so interrupting a thread that's
+	          in the process of initializing a PPC control stack frame
+	          isn't GC-safe.</para>
+	      </listitem>
+          <listitem>
+	        <para>There are similar problems with the initialization
+	          of temp stackframes on the PPC.  (Allocation and
+	          initialization doesn't happen atomically, and the newly
+	          allocated stack memory may have undefined contents.)</para>
+	      </listitem>
+          <listitem>
+	        <para><xref linkend="The-ephemeral-GC"/>'s write barrier
+	          has to be implemented atomically (i.e.,both an
+	          intergenerational store and the update of a
+	          corresponding reference bit has to happen without
+	          interruption, or neither of these events can
+	          happen.)</para>
+	      </listitem>
+          <listitem>
+	        <para>There are a few more similar cases.</para>
+	      </listitem>
+        </itemizedlist>
+
+        <para>Fortunately, the number of these non-atomic instruction
+          sequences is small, and fortunately it's fairly easy for the
+          interrupting thread to recognize when the interrupted thread
+          is in the middle of such a sequence.  When this is detected,
+          the interrupting thread modifies the state of the interrupted
+          thread (modifying its PC and other registers) so that it is no
+          longer in the middle of such a sequence (it's either backed
+          out of it or the remaining instructions are emulated.)</para>
+        <para>This works because (a) many of the troublesome
+          instruction sequences are PPC-specific and it's relatively
+          easy to partially disassemble the instructions surrounding the
+          interrupted thread's PC on the PPC and (b) those instruction
+          sequences are heavily stylized and intended to be easily
+          recognized.</para>
+      </sect2>
+    </sect1>
+
+    <sect1 id="Register-usage-and-tagging">
+      <title>Register usage and tagging</title>
+      
+      <sect2 id="Register-usage-and-tagging-overview">
+	    <title>Overview</title>
+	    <para>Regardless of other details of its implementation, a
+	      garbage collector's job is to partition the set of all
+	      heap-allocated lisp objects (CONSes, STRINGs, INSTANCEs, etc.)
+	      into two subsets.  The first subset contains all objects that
+	      are transitively referenced from a small set of "root" objects
+	      (the contents of the stacks and registers of all active
+	      threads at the time the GC occurs and the values of some
+	      global variables.)  The second subset contains everything
+	      else: those lisp objects that are not transitively reachable
+	      from the roots are garbage, and the memory occupied by garbage
+	      objects can be reclaimed (since the GC has just proven that
+ 	      it's impossible to reference them.)</para>
+        <para>The set of live, reachable lisp objects basically form
+          the nodes of a (usually large) graph, with edges from each
+          node A to any other objects (nodes) that object A
+          references.</para>
+        <para>Some nodes in this graph can never have outgoing edges:
+          an array with a specialized numeric or character type usually
+          represents its elements in some (possibly more compact)
+          specialized way.  Some nodes may refer to lisp objects that
+          are never allocated in memory (FIXNUMs, CHARACTERs,
+          SINGLE-FLOATs on 64-bit platforms ..)  This latter class of
+          objects are sometimes called "immediates", but that's a little
+          confusing because the term "immediate" is sometimes used to
+          refer to things that can never be part of the big connectivity
+          graph (e.g., the "raw" bits that make up a floating-point
+          value, foreign address, or numeric value that needs to be used
+          - at least fleetingly - in compiled code.)</para>
+        <para>For the GC to be able to build the connectivity graph
+          reliably, it's necessary for it to be able to reliably tell
+          (a) whether or not a "potential root" - the contents of a
+          machine register or stack location - is in fact a node and (b)
+          for any node, whether it may have components that refer to
+          other nodes.</para>
+        <para>There's no reliable way to answer the first question on
+          stock hardware.  (If everything was a node, as might be the
+          case on specially microcoded "lisp machine" hardware, it
+          wouldn't even need to be asked.)  Since there's no way to just
+          look at a machine word (the contents of a machine register or
+          stack location) and tell whether or not it's a node or just
+          some random non-node value, we have to either adopt and
+          enforce strict conventions on register and stack usage or
+          tolerate ambiguity.</para>
+        <para>"Tolerating ambiguity" is an approach taken by some
+          ("conservative") GC schemes; by contrast, &CCL;'s GC is
+          "precise", which in this case means that it believes that the
+          contents of certain machine registers and stack locations are
+          always nodes and that other registers and stack locations are
+          never nodes and that these conventions are never violated by
+          the compiler or runtime system.  The fact that threads are
+          preemptively scheduled means that a GC could occur (because of
+          activity in some other thread) on any instruction boundary,
+          which in turn means that the compiler and runtime system must
+          follow precise <xref
+                            linkend="Register-and-stack-usage-conventions"/> at all
+          times.</para>
+        <para>Once we've decided that a given machine word is a node,
+          a <xref linkend="Tagging-scheme"/> describes how the node's
+          value and type are encoded in that machine word.</para>
+        <para>Most of this discussion&mdash;so far&mdash;has treated
+          things from the GC's very low-level perspective. From a much
+          higher point of view, lisp functions accept nodes as
+          arguments, return nodes as values, and (usually) perform
+          some operations on those arguments in order to produce those
+          results.  (In many cases, the operations in question involve
+          raw non-node values.)  Higher-level parts of the lisp type
+          system (functions like TYPE-OF and CLASS-OF, etc.) depend on
+          the <xref linkend="Tagging-scheme"/>.</para>
+      </sect2>
+
+      <sect2 id="pc-locatives-on-the-PPC">
+	    <title>pc-locatives on the PPC</title>
+        <para>On the PPC, there's a third case (besides "node" and
+          "immediate" values).  As discussed below, a node that denotes
+          a memory-allocated lisp object is a biased (tagged) pointer
+          -to- that object; it's not generally possible to point -into-
+          some composite (multi-element) object (such a pointer would
+          not be a node, and the GC would have no way to update the
+          pointer if it were to move the underlying object.)</para>
+        <para>Such a pointer ("into" the interior of a heap-allocated
+          object) is often called a <emphasis>locative</emphasis>; the
+          cases where locatives are allowed in &CCL; mostly involve
+          the behavior of function call and return instructions.  (To be
+          technically accurate, the other case also arises on x86-64, but
+          that case isn't as user-visible.)</para>
+        <para>On the PowerPC (both PPC32 and PPC64), all machine
+          instructions are 32 bits wide and all instruction words are
+          allocated on 32-bit boundaries.  In PPC &CCL;, a CODE-VECTOR
+          is a specialized type of vector-like object; its elements
+          are 32-bit PPC machine instructions.  A CODE-VECTOR is an
+          attribute of a FUNCTION object; a function call involves
+          accessing the function's code-vector and jumping to the
+          address of its first instruction.</para>
+        <para>As each instruction in the code vector sequentially
+          executes, the hardware program counter (PC) register advances
+          to the address of the next instruction (a locative into the
+          code vector); since PPC instructions are always 32 bits wide
+          and aligned on 32-bit boundaries, the low two bits of the PC
+          are always 0.  If the function executes a call (simple call
+          instructions have the mnemonic "bl" on the PPC, which stands
+          for "branch and link"), the address of the next instruction
+          (also a word-aligned locative into a code-vector) is copied
+          into the special- purpose PPC "link register" (lr); a function
+          returns to its caller via a "branch to link register" (blr)
+          instruction.  Some cases of function call and return might
+          also use the PPC's "count register" (ctr), and if either the
+          lr or ctr needs to be stored in memory it needs to first be
+          copied to a general-purpose register.</para>
+        <para>&CCL;'s GC understands that certain registers contain
+          these special "pc-locatives" (locatives that point into
+          CODE-VECTOR objects); it contains special support for
+          finding the containing CODE-VECTOR object and for adjusting
+          all of these "pc-locatives" if the containing object is
+          moved in memory.  The first part of that
+          operation&mdash;finding the containing object&mdash;is
+          possible and practical on the PPC because of architectural
+          artifacts (fixed-width instructions and arcana of
+          instruction encoding.)  It's not possible on x86-64, but
+          fortunately not necessary either (though the second part -
+          adjusting the PC/RIP when the containing object moves) is
+          both necessary and simple.</para>
+      </sect2>
+
+      <sect2 id="Register-and-stack-usage-conventions">
+        <title>Register and stack usage conventions</title>
+        
+        <sect3 id="Stack-conventions">
+	      <title>Stack conventions</title>
+          <para>On both PPC and X86 platforms, each lisp thread uses 3
+            stacks; the ways in which these stacks are used differs
+            between the PPC and X86.</para>
+          <para>Each thread has:</para>
+	      <itemizedlist>
+            <listitem>
+	          <para>A "control stack".  On both platforms, this is
+	            "the stack" used by foreign code.  On the PPC, it
+	            consists of a linked list of frames where the first word
+	            in each frame points to the first word in the previous
+	            frame (and the outermost frame points to 0.)  Some
+	            frames on a PPC control stack are lisp frames; lisp
+	            frames are always 4 words in size and contain (in
+	            addition to the back pointer to the previous frame) the
+	            calling function (a node), the return address (a
+	            "locative" into the calling function's code-vector), and
+	            the value to which the value-stack pointer (see below)
+	            should be restored on function exit.  On the PPC, the GC
+	            has to look at control-stack frames, identify which of
+	            those frames are lisp frames, and treat the contents of
+	            the saved function slot as a node (and handle the return
+	            address locative specially.)  On x86-64, the control
+	            stack is used for dynamic-extent allocation of immediate
+	            objects.  Since the control stack never contains nodes
+	            on x86-64, the GC ignores it on that platform.
+	            Alignment of the control stack follows the ABI
+	            conventions of the platform (at least at any point in
+	            time where foreign code could run.)  On PPC, the r1
+	            register always points to the top of the current
+	            thread's control stack; on x86-64, the RSP register
+	            points to the top of the current thread's control stack
+	            when the thread is running foreign code and the address
+	            of the top of the control stack is kept in the thread's
+	            TCR (see <xref linkend="The-Thread-Context-Record"/>
+	            when not running foreign code.  The control stack "grows
+	            down."</para>
+	        </listitem>
+            <listitem>
+	          <para>A "value stack".  On both platforms, all values on
+	            the value stack are nodes (including "tagged return
+	            addresses" on x86-64.)  The value stack is always
+	            aligned to the native word size; objects are always
+	            pushed on the value stack using atomic instructions
+	            ("stwu"/"stdu" on PPC, "push" on x86-64), so the
+	            contents of the value stack between its bottom and top
+	            are always unambiguously nodes; the compiler usually
+	            tries to pop or discard nodes from the value stack as
+	            soon as possible after their last use (as soon as they
+	            may have become garbage.)  On x86-64, the RSP register
+	            addresses the top of the value stack when running lisp
+	            code; that address is saved in the TCR when running
+	            foreign code.  On the PPC, a dedicated register (VSP,
+	            currently r15) is used to address the top of the value
+	            stack when running lisp code, and the VSP value is saved
+	            in the TCR when running foreign code.  The value stack
+	            grows down.</para>
+	        </listitem>
+	        <listitem>
+	          <para>A "temp stack".  The temp stack consists of a
+	            linked list of frames, each of which points to the
+	            previous temp stack frame.  The number of native
+	            machine words in each temp stack frame is always even,
+	            so the temp stack is aligned on a two-word (64- or
+	            128-bit) boundary.  The temp stack is used for
+	            dynamic-extent objects on both platforms; on the PPC,
+	            it's used for essentially all such objects (regardless
+	            of whether or not the objects contain nodes); on the
+	            x86-64, immediate dynamic-extent objects (strings,
+	            foreign pointers, etc.)  are allocated on the control
+	            stack and only node-containing dynamic-extent objects
+	            are allocated on the temp stack.  Data structures used
+	            to implement CATCH and UNWIND-PROTECT are stored on
+	            the temp stack on both ppc and x86-64.  Temp stack
+	            frames are always doublenode aligned and objects
+	            within a temp stack frame are aligned on doublenode
+	            boundaries.  The first word in each frame contains a
+	            back pointer to the previous frame; on the PPC, the
+	            second word is used to indicate to the GC whether the
+	            remaining objects are nodes (if the second word is 0)
+	            or immediate (otherwise.)  On x86-64, where temp stack
+	            frames always contain nodes, the second word is always
+	            0.  The temp stack grows down.  It usually takes
+	            several instructions to allocate and safely initialize
+	            a temp stack frame that's intended to contain nodes,
+	            and the GC has to recognize the case where a thread is
+	            in the process of allocating and initializing a temp
+	            stack frame and take care not to interpret any
+	            uninitialized words in the frame as nodes. The PPC
+	            keeps the current top of the temp stack in a dedicated
+	            register (TSP, currently r12) when running lisp code
+	            and saves this register's value in the TCR when
+	            running foreign code.  The x86-64 keeps the address of
+	            the top of each thread's temp stack in the thread's
+	            TCR.</para>
+	        </listitem>
+          </itemizedlist>
+        </sect3>
+
+        <sect3 id="Register-conventions">
+	      <title>Register conventions</title>
+          <para>If there are a "reasonable" (for some value of
+            "reasonable") number of general-purpose registers and the
+            instruction set is "reasonably" orthogonal (most
+            instructions that operate on GPRs can operate on any GPR),
+            then it's possible to statically partition the GPRs into at
+            least two sets: "immediate registers" never contain nodes,
+            and "node registers" always contain nodes.  (On the PPC, a
+            few registers are members of a third set of "PC locatives",
+            and on both platforms some registers may have dedicated
+            roles as stack or heap pointers; the latter class is treated
+            as immediates by the GC proper but may be used to help
+            determine the bounds of stack and heap memory areas.)</para>
+	      <para>The ultimate definition of register partitioning is
+            hardwired into the GC in functions like "mark_xp()" and
+            "forward_xp()", which process the values of some of the
+            registers in an exception frame as nodes and may give some
+            sort of special treatment to other register values they
+            encounter there.)</para>
+          <para>On x86-64, the static register partitioning scheme involves:</para>
+	      <itemizedlist>
+            <listitem>
+	          <para>(only) three "immediate" registers.</para>
+	          <para>The RAX, RCX, and RDX registers are used as the
+	            implicit operands and results of some extended-precision
+	            multiply and divide instructions which generally involve
+	            non-node values; since their use in these instructions
+	            means that they can't be guaranteed to contain node
+	            values at all times, it's natural to put these registers
+	            in the "immediate" set. RAX is generally given the
+	            symbolic name "imm0", RDX is given the symbolic name
+	            "imm1" and RCX is given the symbolic name "imm2"; you
+	            may see these names in disassembled code, usually in
+	            operations involving type checking, array indexing, and
+	            foreign memory and function access.</para>
+	        </listitem>
+            <listitem>
+	          <para>(only) two "dedicated" registers.</para>
+	          <para>RSP and RBP have
+	            dedicated functionality dictated by the hardware and
+	            calling conventions.</para>
+	        </listitem>
+            <listitem>
+	          <para>11 "node" registers.</para>
+	          <para>All other registers (RBX, RSI, RDI, and R8-R15)
+	            are asserted to contain node values at (almost) all
+	            times; legacy "string" operations that implicitly use RSI
+	            and/or RDI are not used.</para>
+	        </listitem>
+	      </itemizedlist>
+	      <para>
+		On 32-bit x86, the default register partitioning scheme
+		involves:
+	      </para>
+	      <itemizedlist>
+		<listitem>
+		  <para>
+		  A single "immediate" register.
+		  </para>
+		  <para>
+		    The EAX register is given the symbolic name
+		    "imm0".
+		  </para>
+		</listitem>
+		<listitem>
+		  <para>
+		    There are two "dedicated" registers.
+		  </para>
+		  <para>
+		    ESP and EBP have dedicated functionality dictated by the
+		    hardware and calling conventions.
+		  </para>
+		</listitem>
+		<listitem>
+		  <para>
+		    5 "node" registers.
+		  </para>
+		  <para>
+		    The remaining registers, (EBX, ECX, EDX, ESI, EDI) normally
+		    contain node values.  As on x86-64, string instructions
+		    that implicity use ESI and EDI are not used.
+		  </para>
+		</listitem>
+	      </itemizedlist>
+	      <para>
+		There are times when this default partitioning scheme is
+		inadequate.  As mentioned in the x86-64 section, there are
+		instructions like the extended-precision MUL and DIV which
+		require the use of EAX and EDX.  We therefore need a way to
+		change this partitioning at run-time.
+	      </para>
+	      <para>
+		Two schemes are employed.  The first uses a mask in the TCR
+		that contains a bit for each register.  If the bit is set,
+		the register is interpreted by the GC as a node register; if it's
+		clear, the register is treated as an immediate register.  The
+		second scheme uses the direction flag in the EFLAGS register.
+		If DF is set, EDX is treated as an immediate register.
+		(We don't use the string instructions, so DF isn't otherwise
+		used.)
+	      </para>
+
+          <para>On the PPC, the static register partitioning scheme
+            involves:</para>
+	      <itemizedlist>
+            <listitem>
+	          <para>6 "immediate" registers.</para>
+	          <para>Registers r3-r8 are given
+	            the symbolic names imm0-imm5.  As a RISC architecture
+	            with simpler addressing modes, the PPC probably
+	            uses immediate registers a bit more often than the CISC
+	            x86-64 does, but they're generally used for the same sort
+	            of things (type checking, array indexing, FFI,
+	            etc.)</para>
+	        </listitem>
+	        <listitem>
+	          <para>9 dedicated registers
+	            <itemizedlist>
+		          <listitem>
+		            <para>r0 (symbolic name rzero) always contains the
+		              value 0 when running lisp code.  Its value is
+		              sometimes read as 0 when it's used as the base
+		              register in a memory address; keeping the value 0
+		              there is sometimes convenient and avoids
+		              asymmetry.</para>
+		          </listitem>
+		          <listitem>
+		            <para>r1 (symbolic name sp) is the control stack
+		              pointer, by PPC convention.</para>
+		          </listitem>
+                  <listitem>
+		            <para>r2 is used to hold the current thread's TCR on
+		              ppc64 systems; it's not used on ppc32.</para>
+		          </listitem>
+                  <listitem>
+		            <para>r9 and r10 (symbolic names allocptr and
+		              allocbase) are used to do per-thread memory
+		              allocation</para>
+		          </listitem>
+                  <listitem>
+		            <para>r11 (symbolic name nargs) contains the number
+		              of function arguments on entry and the number of
+		              return values in multiple-value returning
+		              constructs.  It's not used more generally as either
+		              a node or immediate register because of the way that
+		              certain trap instruction encodings are
+		              interpreted.</para>
+		          </listitem>
+                  <listitem>
+		            <para>r12 (symbolic name tsp) holds the top of the
+		              current thread's temp stack.</para>
+		          </listitem>
+		          <listitem>
+		            <para>r13 is used to hold the TCR on PPC32 systems;
+		              it's not used on PPC64.</para>
+		          </listitem>
+		          <listitem>
+		            <para>r14 (symbolic name loc-pc) is used to copy
+		              "pc-locative" values between main memory and
+		              special-purpose PPC registers (LR and CTR) used in
+		              function-call and return instructions.</para>
+		          </listitem>
+                  <listitem>
+		            <para>r15 (symbolic name vsp) addresses the top of
+		              the current thread's value stack.</para>
+		          </listitem>
+		          <listitem>
+		            <para>lr and ctr are PPC branch-unit registers used
+		              in function call and return instructions; they're
+		              always treated as "pc-locatives", which precludes
+		              the use of the ctr in some PPC looping
+		              constructs.</para>
+		          </listitem>
+                  
+	            </itemizedlist>
+	          </para>
+	        </listitem>
+            <listitem>
+	          <para>17 "node" registers</para>
+	          <para>r15-r31 are always treated as node
+	            registers</para>
+	        </listitem>
+	        
+          </itemizedlist>
+        </sect3>
+      </sect2>
+
+      <sect2 id="Tagging-scheme">
+	    <title>Tagging scheme</title>
+        <para>&CCL; always allocates lisp objects on double-node
+          (64-bit for 32-bit platforms, 128-bit for 64-bit platforms)
+          boundaries; this mean that the low 3 bits (32-bit lisp) or 4
+          bits (64-bit lisp) are always 0 and are therefore redundant
+          (we only really need to know the upper 29 or 60 bits in order
+          to identify the aligned object address.)  The extra bits in a
+          lisp node can be used to encode at least some information
+          about the node's type, and the other 29/60 bits represent
+          either an immediate value or a doublenode-aligned memory
+          address.  The low 3 or 4 bits of a node are called the node's
+          "tag bits", and the conventions used to encode type
+          information in those tag bits are called a "tagging
+          scheme."</para>
+        <para>It might be possible to use the same tagging scheme on
+          all platforms (at least on all platforms with the same word
+          size and/or the same number of available tag bits), but there
+          are often some strong reasons for not doing so.  These
+          arguments tend to be very machine-specific: sometimes, there
+          are fairly obvious machine-dependent tricks that can be
+          exploited to make common operations on some types of tagged
+          objects faster; other times, there are architectural
+          restrictions that make it impractical to use certain tags for
+          certain types.  (On PPC64, the "ld" (load doubleword) and
+          "std" (store doubleword) instructions - which load and store a
+          GPR operand at the effective address formed by adding the
+          value of another GPR operand and a 16-bit constant operand -
+          require that the low two bits of that constant operand be 0.
+          Since such instructions would typically be used to access the
+          fields of things like CONS cells and structures, it's
+          desirable that that the tags chosen for CONS cells and
+          structures allow the use of these instructions as opposed to
+          more expensive alternatives.)</para>
+        <para>One architecture-dependent tagging trick that works well
+          on all architectures is to use a tag of 0 for FIXNUMs: a
+          fixnum basically encodes its value shifted left a few bits
+          and keeps those low bits clear. FIXNUM addition,
+          subtraction, and binary logical operations can operate
+          directly on the node operands, addition and subtraction can
+          exploit hardware-based overflow detection, and (in the
+          absence of overflow) the hardware result of those operations
+          is a node (fixnum).  Some other slightly-less-common
+          operations may require a few extra instructions, but
+          arithmetic operations on FIXNUMs should be as cheap as
+          possible and using a tag of zero for FIXNUMs helps to ensure
+          that it will be.</para>
+	    <para>If we have N available tag bits (N = 3 for 32-bit &CCL;
+	      and N = 4 for 64-bit &CCL;), this way of representing
+	      fixnums with the low M bits forced to 0 works as long as M
+	      &lt;= N.  The smaller we make M, the larger the values of
+	      MOST-POSITIVE-FIXNUM and MOST-NEGATIVE become; the larger we
+	      make N, the more distinct non-FIXNUM tags become available.
+	      A reasonable compromise is to choose M = N-1; this basically
+	      yields two distinct FIXNUM tags (one for even fixnums, one
+	      for odd fixnums), gives 30-bit fixnums on 32-bit platforms
+	      and 61-bit fixnums on 64-bit platforms, and leaves us with 6
+	      or 14 tags to encoded other types.</para>
+        <para>Once we get past the assignment of FIXNUM tags, things
+          quickly devolve into machine-dependencies.  We can fairly
+          easily see that we can't directly tag all other primitive
+          lisp object types with only 6 or 14 available tag values;
+          the details of how types are encoded vary between the ppc32,
+          ppc64, and x86-64 implementations, but there are some
+          general common principles:</para>
+
+	    <itemizedlist>
+	      <listitem>
+	        <para>CONS cells always contain exactly 2 elements and are
+	          usually fairly common.It therefore makes sense to give
+	          CONS cells their own tag.  Unlike the fixnum case -
+	          where a tag value of 0 had positive implications - there
+	          doesn't seem to be any advantage to using any particular
+	          value.  (A longtime ago - in the case of 68K MCL - the
+	          CONS tag and the order of CAR and CDR in memory were
+	          chosen to allow smaller, cheaper addressing modes to be
+	          used to "cdr down a list."  That's not a factor on ppc
+	          or x86-64, but all versions of &CCL; still store the CDR
+	          of a CONS cell first in memory.  It doesn't matter, but
+	          doing it the way that the host system did made
+	          boostrapping to a new target system a little easier.)
+	        </para>
+	      </listitem>
+	      <listitem>
+	        <para>Any way you look at it, NIL is a bit
+	          ... unusual. NIL is both a SYMBOL and a LIST (as well as
+	          being a canonical truth value and probably a few other
+	          things.)  Its role as a LIST is probably much more
+	          important to most programs than its role as a SYMBOL is:
+	          LISTP has to be true of NIL and primitives like CAR and
+	          CDR do LISTP implicitly when safe and want that
+	          operation to be fast. There are several possible
+	          approaches to this problem; &CCL; uses two of them. On
+	          PPC32 and X86-64, NIL is basically a weird CONS cell
+	          that straddles two doublenodes; the tag of NIL is unique
+	          and congruent modulo 4 (modulo 8 on 64-bit) with the tag
+	          used for CONS cells.  LISTP is therefore true of any
+	          node whose low 2 (or 3) bits contain the appropriate tag
+	          value (it's not otherwise necessary to special-case
+	          NIL.)  SYMBOL accessors (SYMBOL-NAME, SYMBOL-VALUE,
+	          SYMBOL-PLIST ..) -do- have to special-case NIL (and
+	          access the components of an internal proxy symbol.) On
+	          PPC64 (where architectural restrictions dictate the set
+	          of tags that can be used to access fixed components of
+	          an object), that approach wasn't practical.  NIL is just
+	          a distinguished SYMBOL,and it just happens to be the
+	          case that its pname slot and values slot are at the same
+	          offsets from a tagged pointer as a CONS cell's CDR and
+	          CAR would be.  NIL's pname is set to NIL (SYMBOL-NAME
+	          checks for this and returns the string "NIL"), and LISTP
+	          (and therefore safe CAR and CDR) has to check for (OR
+	          NULL CONSP). At least in the case of CAR and CDR, the
+	          fact that the PPC has multiple condition-code fields
+	          keeps that extra test from being prohibitively
+	          expensive.  On IA-32, we can't afford to dedicate a tag to
+		  NIL. NIL is therefore just a distinguished CONS
+		  cell, and we have to explicitly check for a NIL argument
+		  in CONSP/RPLACA/RPLACD.
+		</para>
+	      </listitem>
+	      <listitem>
+	        <para>Some objects are immediate (but not FIXNUMs). This
+	          is true of CHARACTERs and, on 64-bit platforms,
+	          SINGLE-FLOATs. It's also true of some nodes used in the
+	          runtime system (special values used to indicate unbound
+	          variables and slots, for instance.) On 64-bit platforms,
+	          SINGLE-FLOATs have their own unique tag (making them a
+	          little easier to recognize; on all platforms, CHARACTERs
+	          share a tag with other immediate objects (unbound
+	          markers) but are easy to recognize (by looking at
+	          several of their low bits.)  The GC treats any node with
+	          an immediate tag (and any node with a fixnum tag) as a
+	          leaf.</para>
+	      </listitem>
+          <listitem>
+	        <para>There are some advantages to treating everything
+	          else&mdash;memory-allocated objects that aren't CONS
+	          cells&mdash;uniformly.There are some disadvantages to
+	          that uniform treatment as well, and the treatment of
+	          "memory-allocated non-CONS objects" isn't entirely
+	          uniform across all &CCL; implementations.  Let's first
+	          pretend that the treatment is uniform, then discuss the
+	          ways in which it isn't.The "uniform approach" is to
+	          treat all memory-allocated non-CONS objects as if they
+	          were vectors; this use of the term is a little looser
+	          than what's implied by the CL VECTOR type.  &CCL;
+	          actually uses the term "uvector" to mean "a
+	          memory-allocated lisp object other than a CONS cell,
+	          whose first word is a header that describes the object's
+	          type and the number of elements that it contains."  In
+	          this view, a SYMBOL is a UVECTOR, as is a STRING, a
+	          STANDARD-INSTANCE, a CL array or vector, a FUNCTION, and
+	          even a DOUBLE-FLOAT. In the PPC implementations (where
+	          things are a little more ... uniform), a single tag
+	          value is used to denote any uvector; in order to
+	          determine something more specific about the type of the
+	          object in question, it's necessary to fetch the low byte
+	          of the header word from memory.  On the x86-64 platform,
+	          certain types of uvectors - SYMBOLs and FUNCTIONs -are
+	          given their own unique tags.  The good news about the
+	          x86-64 approach is that SYMBOLs and FUNCTIONs can be
+	          recognized without referencing memory; the slightly bad
+	          news is that primitive operations that work on
+	          UVECTOR-tagged objects&mdash;like the function
+	          CCL:UVREF&mdash;don't work on SYMBOLs or FUNCTIONs on
+	          x86-64 (but -do- work on those types of objects in the
+	          PPC ports.) The header word that precedes a UVECTOR's
+	          data in memory contains 8 bits of type information in
+	          the low byte and either 24 or 56 bits of "element-count"
+	          information in the rest of the word.  (This is where the
+	          sometimes-limiting value of 2^24 for
+	          ARRAY-TOTAL-SIZE-LIMIT on 32-bit platforms comes from.)
+	          The low byte of the header&mdash;sometimes called the
+	          uvector's subtag&mdash;is itself tagged (which means
+	          that the header is tagged.)  The (3 or 4) tag bits in
+	          the subtag are used to determine whether the uvector's
+	          elements are nodes or immediates. (A UVECTOR whose
+	          elements are nodes is called a GVECTOR; a UVECTOR whose
+	          elements are immediates is called an IVECTOR.  This
+	          terminology came from Spice Lisp, which was a
+	          predecessor of CMUCL.)  Even though a uvector header is
+	          tagged, a header is not a node.  There's no (supported)
+	          way to get your hands on one in lisp and doing so could
+	          be dangerous.  (If the value of a header wound up in a
+	          lisp node register and that register wound up getting
+	          pushed on a thread's value stack, the GC might
+	          misinterpret that situation to mean that there was a
+	          stack-allocated UVECTOR on the value stack.)</para>
+	      </listitem>
+          
+	    </itemizedlist>
+      </sect2>
+    </sect1>
+
+    <sect1 id="Heap-Allocation">
+      <title>Heap Allocation</title> <para>When the &CCL; kernel first
+        starts up, a large contiguous chunk of the process's address
+        space is mapped as "anonymous, no access" memory. ("Large"
+        means different things in different contexts; on LinuxPPC32,
+        it means "about 1 gigabyte", on DarwinPPC32, it means "about 2
+        gigabytes", and on current 64-bit platforms it ranges from 128
+        to 512 gigabytes, depending on OS. These values are both
+        defaults and upper limits;
+        the <literal>--heap-reserve</literal> argument can be used to
+        try to reserve less than the default.)</para>
+      <para>Reserving address space that can't (yet) be read or
+        written to doesn't cost much; in particular, it doesn't require
+        that corresponding swap space or physical memory be available.
+        Marking the address range as being "mapped" helps to ensure that
+        other things (results from random calls to malloc(), dynamically
+        loaded shared libraries) won't be allocated in this region that
+        lisp has reserved for its own heap growth.</para>
+      <para>A small portion (around 1/32 on 32-bit platforms and 1/64
+        on 64-bit platforms) of that large chunk of address space is
+        reserved for GC data structures.  Memory pages reserved for
+        these data structures are mapped read-write as pages are made
+        writable in the main portion of the heap.</para>
+      <para>The initial heap image is mapped into this reserved
+        address space and an additional (LISP-HEAP-GC-THRESHOLD) bytes
+        are mapped read-write.  GC data structures grow to match the
+        amount of GC-able memory in the initial image plus the gc
+        threshold, and control is transferred to lisp code.
+        Inevitably, that code spoils everything and starts consing;
+        there are basically three layers of memory allocation that can
+        go on.</para>
+
+      <sect2 id="Per-thread-object-allocation">
+	    <title>Per-thread object allocation</title>
+        <para>Each lisp thread has a private "reserved memory
+          segment"; when a thread starts up, its reserved memory segment
+          is empty.  PPC ports maintain the highest unallocated address
+          and the lowest allocatable address in the current segment in
+          registers when running lisp code; on x86-664, these values are
+          maintained in the current threads's TCR.  (An "empty" heap
+          segment is one whose high pointer and low pointer are equal.)
+          When a thread is not in the middle of allocating something, the
+          low 3 or 4 bits of the high and low pointers are clear (the
+          pointers are doublenode-aligned.)</para>
+        <para>A thread tries to allocate an object whose physical size
+          in bytes is X and whose tag is Y by:</para>
+	    <orderedlist>
+	      <listitem>
+	        <para>decrementing the "high" pointer by (- X Y)</para>
+	      </listitem>
+	      <listitem>
+	        <para>trapping if the high pointer is less than the low
+	          pointer</para>
+	      </listitem>
+	      <listitem>
+	        <para>using the (tagged) high pointer to initialize the
+	          object, if necessary</para>
+	      </listitem>
+	      <listitem>
+	        <para>clearing the low bits of the high pointer</para>
+	      </listitem>
+	    </orderedlist>
+        <para>On PPC32, where the size of a CONS cell is 8 bytes and
+          the tag of a CONS cell is 1, machine code which sets the arg_z
+          register to the result of doing (CONS arg_y arg_z) looks
+          like:</para>
+        <programlisting>
+  (SUBI ALLOCPTR ALLOCPTR 7)    ; decrement the high pointer by (- 8 1)
+  (TWLLT ALLOCPTR ALLOCBASE)    ; trap if the high pointer is below the base
+  (STW ARG_Z -1 ALLOCPTR)       ; set the CDR of the tagged high pointer
+  (STW ARG_Y 3 ALLOCPTR)        ; set the CAR
+  (MR ARG_Z ALLOCPTR)           ; arg_z is the new CONS cell
+  (RLWINM ALLOCPTR ALLOCPTR 0 0 28)     ; clear tag bits
+	    </programlisting>
+	    <para>On x86-64, the idea's similar but the implementation is
+          different.  The high and low pointers to the current thread's
+          reserved segment are kept in the TCR, which is addressed by
+          the gs segment register. An x86-64 CONS cell is 16 bytes wide
+          and has a tag of 3; we canonically use the temp0 register to
+          initialize the object</para>
+        <programlisting>
+  (subq ($ 13) ((% gs) 216))    ; decrement allocptr
+  (movq ((% gs) 216) (% temp0)) ; load allocptr into temp0
+  (cmpq ((% gs) 224) (% temp0)) ; compare to allocabase
+  (jg L1)                       ; skip trap
+  (uuo-alloc)                   ; uh, don't skip trap
+L1
+  (andb ($ 240) ((% gs) 216))   ; untag allocptr in the tcr
+  (movq (% arg_y) (5 (% temp0))) ; set the car
+  (movq (% arg_z) (-3 (% temp0))); set the cdr
+  (movq (% temp0) (% arg_z))    ; return the cons
+	    </programlisting>
+        <para>If we don't take the trap (if allocating 8-16 bytes
+          doesn't exhaust the thread's reserved memory segment), that's
+          a fairly short and simple instruction sequence.  If we do take
+          the trap, we'll have to do some additional work in order to
+          get a new segment for the current thread.</para>
+      </sect2>
+
+      <sect2 id="Allocation-of-reserved-heap-segments">
+	    <title>Allocation of reserved heap segments</title>
+        <para>After the lisp image is first mapped into memory - and after
+          each full GC - the lisp kernel ensures that
+          (LISP-HEAP-GC-TRESHOLD) additional bytes beyond the current
+          end of the heap are mapped read-write.</para>
+        <para>If a thread traps while trying to allocate memory, the
+          thread goes through the usual exception-handling protocol (to
+          ensure that any other thread that GCs "sees" the state of the
+          trapping thread and to serialize exception handling.)  When
+          the exception handler runs, it determines the nature and size
+          of the failed allocation and tries to complete the allocation
+          on the thread's behalf (and leave it with a reasonably large
+          thread-specific memory segment so that the next small
+          allocation is unlikely to trap.</para>
+        <para>Depending on the size of the requested segment
+          allocation, the number of segment allocations that have
+          occurred since the last GC, and the EGC and GC thresholds, the
+          segment allocation trap handler may invoke a full or ephemeral
+          GC before returning a new segment.  It's worth noting that the
+          [E]GC is triggered based on the number of and size of these
+          segments that have been allocated since the last GC; it doesn't
+          have much to do with how "full" each of those per-thread
+          segments are.  It's possible for a large number of threads to
+          do fairly incidental memory allocation and trigger the GC as a
+          result; avoiding this involves tuning the per-thread
+          allocation quantum and the GC/EGC thresholds
+          appropriately.</para>
+      </sect2>
+
+      <sect2 id="Heap-growth">
+	    <title>Heap growth</title>
+        <para>All OSes on which &CCL; currently runs use an
+          "overcommit" memory allocation strategy by default (though
+          some of them provide ways of overriding that default.)  What
+          this means in general is that the OS doesn't necessarily
+          ensure that backing store is available when asked to map pages
+          as read-write; it'll often return a success indicator from the
+          mapping attempt (mapping the pages as "zero-fill,
+          copy-on-write"), and only try to allocate the backing store
+          (swap space and/or physical memory) when non-zero contents are
+          written to the pages.</para>
+        <para>It -sounds- like it'd be better to have the mmap() call
+          fail immediately, but it's actually a complicated issue.
+          (It's possible that other applications will stop using some
+          backing store before lisp code actually touches the pages that
+          need it, for instance.)  It's also not guaranteed that lisp
+          code would be able to "cleanly" signal an out-of-memory
+          condition if lisp is ... out of memory</para>
+	    <para>I don't know that I've ever seen an abrupt out-of-memory
+	      failure that wasn't preceded by several minutes of excessive
+	      paging activity.  The most expedient course in cases like this
+	      is to either (a) use less memory or (b) get more memory; it's
+	      generally hard to use memory that you don't have.</para>
+      </sect2>
+    </sect1>
+
+    <sect1 id="GC-details">
+      <title>GC details</title>
+      <para>The GC uses a Mark/Compact algorithm; its
+        execution time is essentially a factor of the amount of live
+        data in the heap. (The somewhat better-known Mark/Sweep
+        algorithms don't compact the live data but instead traverse the
+        garbage to rebuild free-lists; their execution time is therefore
+        a factor of the total heap size.)</para>
+      <para>As mentioned in <xref linkend="Heap-Allocation"/>, two
+        auxiliary data structures (proportional to the size of the lisp
+        heap) are maintained. These are</para>
+      <orderedlist>
+	    <listitem>
+	      <para>the markbits bitvector, which contains a bit for
+	        every doublenode in the dynamic heap (plus a few extra words
+	        for alignment and so that sub-bitvectors can start on word
+	        boundaries.)</para>
+	    </listitem>
+	    <listitem>
+	      <para>the relocation table, which contains a native word for
+	        every 32 or 64 doublenodes in the dynamic heap, plus an
+	        extra word used to keep track of the end of the heap.</para>
+	    </listitem>
+      </orderedlist>
+      <para>The total GC space overhead is therefore on the order of
+        3% (2/64 or 1/32).</para>
+      <para>The general algorithm proceeds as follows:</para>
+
+      <sect2 id="Mark-phase">
+	    <title>Mark phase</title>
+        <para>Each doublenode in the dynamic heap has a corresponding
+          bit in the markbits vector. (For any doublenode in the heap,
+          the index of its mark bit is determined by subtracting the
+          address of the start of the heap from the address of the
+          object and dividing the result by 8 or 16.) The GC knows the
+          markbit index of the free pointer, so determining that the
+          markbit index of a doubleword address is between the start of
+          the heap and the free pointer can be done with a single
+          unsigned comparison.</para>
+        <para>The markbits of all doublenodes in the dynamic heap are
+          zeroed before the mark phase begins. An object is
+          <emphasis>marked</emphasis> if the markbits of all of its
+          constituent doublewords are set and unmarked otherwise;
+          setting an object's markbits involves setting the corresponding
+          markbits of all constituent doublenodes in the object.</para>
+        <para>The mark phase traverses each root. If the tag of the
+          value of the root indicates that it's a non-immediate node
+          whose address lies in the lisp heap, then:</para>
+	    <orderedlist>
+	      <listitem>
+	        <para>If the object is already marked, do nothing.</para>
+	      </listitem>
+	      <listitem>
+	        <para>Set the object's markbit(s).</para>
+	      </listitem>
+	      <listitem>
+	        <para>If the object is an ivector, do nothing further.</para>
+	      </listitem>
+	      <listitem>
+	        <para>If the object is a cons cell, recursively mark its
+	          car and cdr.</para>
+	      </listitem>
+	      <listitem>
+	        <para>Otherwise, the object is a gvector. Recursively mark
+	          its elements.</para>
+	      </listitem>
+	    </orderedlist>
+        <para>Marking an object thus involves ensuring that its mark
+          bits are set and then recursively marking any pointers
+          contained within the object if the object was originally
+          unmarked. If this recursive step was implemented in the
+          obvious manner, marking an object would take stack space
+          proportional to the length of the pointer chain from some root
+          to that object. Rather than storing that pointer chain
+          implicitly on the stack (in a series of recursive calls to the
+          mark subroutine), the &CCL; marker uses mixture of recursion
+          and a technique called <emphasis>link inversion</emphasis> to
+          store the pointer chain in the objects themselves.  (Recursion
+          tends to be simpler and faster; if a recursive step notes that
+          stack space is becoming limited, the link-inversion technique
+          is used.)</para>
+        <para>Certain types of objects are treated a little specially:</para>
+	    <orderedlist>
+	      <listitem>
+	        <para>To support a feature called <emphasis>GCTWA
+                <footnote>
+		          <para>I believe that the acronym comes from MACLISP,
+		            where it stood for "Garbage Collection of Truly
+		            Worthless Atoms".</para>
+                </footnote>
+	            , </emphasis>the vector that contains the internal
+	          symbols of the current package is marked on entry to the
+	          mark phase, but the symbols themselves are not marked at
+	          this time. Near the end of the mark phase, symbols
+	          referenced from this vector which are not otherwise
+	          marked are marked if and only if they're somehow
+	          distinguishable from newly created symbols (by virtue of
+	          their having function bindings, value bindings, plists,
+	          or other attributes.)</para>
+	      </listitem>
+	      <listitem>
+	        <para>Pools have their first element set to NIL before any
+	          other elements are marked.</para>
+	      </listitem>
+	      <listitem>
+	        <para>All hash tables have certain fields (used to cache
+	          previous results) invalidated.</para>
+	      </listitem>
+	      <listitem>
+	        <para>Weak Hash Tables and other weak objects are put on a
+	          linkedlist as they're encountered; their contents are only
+	          retained if there are other (non-weak) references to
+	          them.</para>
+	      </listitem>
+	    </orderedlist>
+        <para>At the end of the mark phase, the markbits of all
+          objects that are transitively reachable from the roots are
+          set and all other markbits are clear.</para>
+      </sect2>
+
+      <sect2 id="Relocation-phase">
+	    <title>Relocation phase</title>
+	    <para>The <emphasis>forwarding address</emphasis> of a
+	      doublenode in the dynamic heap is (&lt;its current address> -
+	      (size_of_doublenode * &lt;the number of unmarked markbits that
+	      precede it>)) or alternately (&lt;the base of the heap> +
+	      (size_of_doublenode * &lt;the number of marked markbits that
+	      precede it &gt;)). Rather than count the number of preceding
+	      markbits each time, the relocation table is used to precompute
+	      an approximation of the forwarding addresses for all
+	      doublewords. Given this approximate address and a pointer into
+	      the markbits vector, it's relatively easy to compute the exact
+	      forwarding address.</para>
+	    <para>The relocation table contains the forwarding addresses
+	      of each <emphasis>pagelet</emphasis>, where a pagelet is 256
+	      bytes (or 32 doublenodes). The forwarding address of the first
+	      pagelet is the base of the heap. The forwarding address of the
+	      second pagelet is the sum of the forwarding address of the
+	      first and 8 bytes for each mark bit set in the first 32-bit
+	      word in the markbits table. The last entry in the relocation
+	      table contains the forwarding address that the freepointer
+	      would have, e.g., the new value of the freepointer after
+	      compaction.</para>
+	    <para>In many programs, old objects rarely become garbage and
+	      new objects often do. When building the relocation table, the
+	      relocation phase notes the address of the first unmarked
+	      object in the dynamic heap. Only the area of the heap between
+	      the first unmarked object and the freepointer needs to be
+	      compacted; only pointers to this area will need to be
+	      forwarded (the forwarding address of all other pointers to the
+	      dynamic heap is the address of that pointer.)  Often, the
+	      first unmarked object is much nearer the free pointer than it
+	      is to the base of the heap.</para>
+      </sect2>
+
+      <sect2 id="Forwarding-phase">
+	    <title>Forwarding phase</title>
+        <para>The forwarding phase traverses all roots and the "old"
+          part of the dynamic heap (the part between the base of the
+          heap and the first unmarked object.) All references to objects
+          whose address is between the first unmarked object and the
+          free pointer are updated to point to the address the object
+          will have after compaction by using the relocation table and
+          the markbits vector and interpolating.</para>
+	    <para>The relocation table entry for the pagelet nearest the
+	      object is found. If the pagelet's address is less than the
+	      object's address, the number of set markbits that precede
+	      the object on the pagelet is used to determine the object's
+	      address; otherwise, the number of set markbits that follow
+	      the object on the pagelet is used.</para>
+        <para>Since forwarding views the heap as a set of doublewords,
+          locatives are (mostly) treated like any other pointers. (The
+          basic difference is that locatives may appear to be tagged as
+          fixnums, in which case they're treated as word-aligned
+          pointers into the object.)</para>
+        <para>If the forward phase changes the address of any hash
+          table key in a hash table that hashes by address (e.g., an EQ
+          hash table), it sets a bit in the hash table's header. The
+          hash table code will rehash the hash table's contents if it
+          tries to do a lookup on a key in such a table.</para>
+        <para>Profiling reveals that about half of the total time
+          spent in the GC is spent in the subroutine which determines a
+          pointer's forwarding address. Exploiting GCC-specific idioms,
+          hand-coding the routine, and inlining calls to it could all be
+          expected to improve GC performance.</para>
+      </sect2>
+
+      <sect2 id="Compact-phase">
+	    <title>Compact phase</title>
+        <para>The compact phase compacts the area between the first
+          unmarked object and the freepointer so that it contains only
+          marked objects.  While doing so, it forwards any pointers it
+          finds in the objects it copies.</para>
+        <para>When the compact phase is finished, so is the GC (more
+          or less): the free pointer and some other data structures are
+          updated and control returns to the exception handler that
+          invoked the GC. If sufficient memory has been freed to satisfy
+          any allocation request that may have triggered the GC, the
+          exception handler returns; otherwise, a "seriously low on
+          memory" condition is signaled, possibly after releasing a
+          small emergency pool of memory.</para>
+      </sect2>
+    </sect1>
+
+    <sect1 id="The-ephemeral-GC">
+      <title>The ephemeral GC</title>
+      <para>In the &CCL; memory management scheme, the relative age
+        of two objects in the dynamic heap can be determined by their
+        addresses: if addresses X and Y are both addresses in the
+        dynamic heap, X is younger than Y (X was created more recently
+        than Y) if it is nearer to the free pointer (and farther from
+        the base of the heap) than Y.</para>
+      <para>Ephemeral (or generational) garbage collectors attempt to
+        exploit the following assumptions:</para>
+      <itemizedlist>
+	    <listitem>
+	      <para>most newly created objects become garbage soon after
+	        they'recreated.</para>
+	    </listitem>
+	    <listitem>
+	      <para>most objects that have already survived several GCs
+	        are unlikely to ever become garbage.</para>
+	    </listitem>
+	    <listitem>
+	      <para>old objects can only point to newer objects as the
+	        result of a destructive modification (e.g., via
+	        SETF.)</para>
+	    </listitem>
+      </itemizedlist>
+
+      <para>By concentrating its efforts on (frequently and quickly)
+        reclaiming newly created garbage, an ephemeral collector hopes
+        to postpone the more costly full GC as long as possible. It's
+        important to note that most programs create some long-lived
+        garbage, so an EGC can't typically eliminate the need for full
+        GC.</para>
+      <para>An EGC views each object in the heap as belonging to
+        exactly one <emphasis>generation</emphasis>; generations are
+        sets of objects that are related to each other by age: some
+        generation is the youngest, some the oldest, and there's an age
+        relationship between any intervening generations. Objects are
+        typically assigned to the youngest generation when first
+        allocated; any object that has survived some number of GCs in
+        its current generation is promoted (or
+        <emphasis>tenured</emphasis>) into an older generation.</para>
+      <para>When a generation is GCed, the roots consist of the
+        stacks, registers, and global variables as always and also of
+        any pointers to objects in that generation from other
+        generations. To avoid the need to scan those (often large) other
+        generations looking for such intergenerational references, the
+        runtime system must note all such intergenerational references
+        at the point where they're created (via Setf).<footnote><para>This is
+            sometimes called "The Write Barrier": all assignments which
+            might result in intergenerational references must be noted, as
+            if the other generations were write-protected.</para></footnote> The
+        set of pointers that may contain intergenerational references is
+        sometimes called <emphasis>the remembered set</emphasis>.</para>
+      <para>In &CCL;'s EGC, the heap is organized exactly the same
+        as otherwise; "generations" are merely structures which contain
+        pointers to regions of the heap (which is already ordered by
+        age.) When a generation needs to be GCed, any younger generation
+        is incorporated into it; all objects which survive a GC of a
+        given generation are promoted into the next older
+        generation. The only intergenerational references that can exist
+        are therefore those where an old object is modified to contain a
+        pointer to a new object.</para>
+      <para>The EGC uses exactly the same code as the full GC. When a
+        given GC is "ephemeral",</para>
+      <itemizedlist>
+        <listitem>
+	      <para>the "base of the heap" used to determine an object's
+	        markbit address is the base of the generation
+	        being collected;</para>
+	    </listitem>
+        <listitem>
+	      <para>the markbits vector is actually a pointer into the
+	        middle of the global markbits table; preceding entries in
+	        this table are used to note doubleword addresses in older
+	        generations that (may) contain intergenerational
+	        references;</para>
+	    </listitem>
+        <listitem>
+	      <para>some steps (notably GCTWA and the handling of weak
+	        objects) are not performed;</para>
+	    </listitem>
+        <listitem>
+	      <para>the intergenerational references table is used to
+	        find additional roots for the mark and forward phases. If a
+	        bit is set in the intergenerational references table, that
+	        means that the corresponding doubleword (in some "old"
+	        generation, in some "earlier" part of the heap) may have had
+	        a pointer to an object in a younger generation stored into
+	        it.</para>
+	    </listitem>
+        
+      </itemizedlist>
+      <para>With one exception (the implicit setfs that occur on entry
+        to and exit from the binding of a special variable), all setfs
+        that might introduce an intergenerational reference must be
+        memoized.
+        <footnote><para>Note that the implicit setfs that occur when
+        initializing an object - as in the case of a call to cons or
+        vector - can't introduce intergenerational references, since
+        the newly created object is always younger than the objects
+        used to initialize it.</para></footnote> It's always safe to
+        push any cons cell or gvector locative onto the memo stack;
+        it's never safe to push anything else.
+      </para>
+
+      <para>Typically, the intergenerational references bitvector is
+        sparse: a relatively small number of old locations are stored
+        into, although some of them may have been stored into many
+        times. The routine that scans the memoization buffer does a lot
+        of work and usually does it fairly often; it uses a simple,
+        brute-force method but might run faster if it was smarter about
+        recognizing addresses that it'd already seen.
+      </para>
+
+      <para>When the EGC mark and forward phases scan the
+        intergenerational reference bits, they can clear any bits that
+        denote doublewords that definitely do not contain
+        intergenerational references.
+      </para>
+    </sect1>
+
+    <sect1 id="Fasl-files">
+      <title>Fasl files</title>
+      <para>Saving and loading of Fasl files is implemented in
+        xdump/faslenv.lisp, level-0/nfasload.lisp, and lib/nfcomp.lisp.
+        The information here is only an overview, which might help when
+        reading the source.</para>
+      <para>The &CCL; Fasl format is forked from the old MCL Fasl
+        format; there are a few differences, but they are minor.  The
+        name "nfasload" comes from the fact that this is the so-called
+        "new" Fasl system, which was true in 1986 or so.  </para>
+      <para>A Fasl file begins with a "file header", which contains
+        version information and a count of the following "blocks".
+        There's typically only one "block" per Fasl file.  The blocks
+        are part of a mechanism for combining multiple logical files
+        into a single physical file, in order to simplify the
+        distribution of precompiled programs. </para>
+      <para>Each block begins with a header for itself, which just
+        describes the size of the data that follows.</para>
+      <para>The data in each block is treated as a simple stream of
+        bytes, which define a bytecode program.  The actual bytecodes,
+        "fasl operators", are defined in xdump/faslenv.lisp.  The
+        descriptions in the source file are terse, but, according to
+        Gary, "probably accurate".</para>
+      <para>Some of the operators are used to create a per-block
+        "object table", which is a vector used to keep track of
+        previously-loaded objects and simplify references to them.  When
+        the table is created, an index associated with it is set to
+        zero; this is analogous to an array fill-pointer, and allows the
+        table to be treated like a stack.</para>
+      <para>The low seven bits of each bytecode are used to specify
+        the fasl operator; currently, about fifty operators are defined.
+        The high byte, when set, indicates that the result of the
+        operation should be pushed onto the object table.</para>
+      <para>Most bytecodes are followed by operands; the operand data
+        is byte-aligned.  How many operands there are, and their type,
+        depend on the bytecode.  Operands can be indices into the object
+        table, immediate values, or some combination of these.</para>
+      <para>An exception is the bytecode #xFF, which has the symbolic
+        name ccl::$faslend; it is used to mark the end of the
+        block.</para>
+    </sect1>
+
+
+
+    <sect1 id="The-Objective-C-Bridge--1-">
+      <title>The Objective-C Bridge</title>
+
+      <sect2 id="How-CCL-Recognizes-Objective-C-Objects">
+	    <title>How &CCL; Recognizes Objective-C Objects</title>
+        <para>In most cases, pointers to instances of Objective-C
+          classes are recognized as such; the recognition is (and
+          probably always will be) slightly heuristic. Basically, any
+          pointer that passes basic sanity checks and whose first word
+          is a pointer to a known ObjC class is considered to be an
+          instance of that class; the Objective-C runtime system would
+          reach the same conclusion.</para>
+        <para>It's certainly possible that a random pointer to an
+          arbitrary memory address could look enough like an ObjC
+          instance to fool the lisp runtime system, and it's possible
+          that pointers could have their contents change so that
+          something that had either been a true ObjC instance (or had
+          looked a lot like one) is changed (possibly by virtue of
+          having been deallocated.)</para>
+        <para>In the first case, we can improve the heuristics
+          substantially: we can make stronger assertions that a
+          particular pointer is really "of type :ID" when it's a
+          parameter to a function declared to take such a pointer as an
+          argument or a similarly declared function result; we can be
+          more confident of something we obtained via SLOT-VALUE of a
+          slot defined to be of type :ID than if we just dug a pointer
+          out of memory somewhere.</para>
+        <para>The second case is a little more subtle: ObjC memory
+          management is based on a reference-counting scheme, and it's
+          possible for an object to ... cease to be an object while lisp
+          is still referencing it.  If we don't want to deal with this
+          possibility (and we don't), we'll basically have to ensure
+          that the object is not deallocated while lisp is still
+          thinking of it as a first-class object. There's some support
+          for this in the case of objects created with MAKE-INSTANCE,
+          but we may need to give similar treatment to foreign objects
+          that are introduced to the lisp runtime in other ways (as
+          function arguments, return values, SLOT-VALUE results, etc. as
+          well as those instances that are created under lisp
+          control.)</para>
+        <para>This doesn't all work yet (in fact, not much of it works
+          yet); in practice, this has not yet been as much of a problem
+          as anticipated, but that may be because existing Cocoa code
+          deals primarily with relatively long-lived objects such as
+          windows, views, menus, etc.</para>
+      </sect2>
+
+      <sect2>
+	    <title>Recommended Reading</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>
+	          <ulink url="http://developer.apple.com/documentation/Cocoa/">Cocoa Documentation</ulink>
+	        </term>
+	        
+	        <listitem>
+	          <para>
+	            This is the top page for all of Apple's documentation on
+	            Cocoa.  If you are unfamiliar with Cocoa, it is a good
+	            place to start.
+	          </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>
+	          <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html">Foundation Reference for Objective-C</ulink>
+	        </term>
+
+	        <listitem>
+	          <para>
+	            This is one of the two most important Cocoa references; it
+	            covers all of the basics, except for GUI programming.  This is
+	            a reference, not a tutorial.
+	          </para>
+	        </listitem>
+	      </varlistentry>
+        </variablelist>
+      </sect2>
+    </sect1>
+  </chapter>
Index: /branches/new-random/doc/src/install.xml
===================================================================
--- /branches/new-random/doc/src/install.xml	(revision 13309)
+++ /branches/new-random/doc/src/install.xml	(revision 13309)
@@ -0,0 +1,801 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+          "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="installing"><title>Obtaining, Installing, and Running &CCL;</title>
+  
+  <!-- ============================================================ -->
+  <sect1 id="releases"><title>Releases and System Requirements</title>
+    
+    <para>Version 1.3 is the latest stable release of &CCL; as of April
+    2009.</para>
+
+   <para>Version 1.3 is available for seven platform configurations:</para>
+    <itemizedlist>
+      <listitem>
+        <para>Linux on PowerPC (32-bit and 64-bit implementations)</para>
+      </listitem>
+      <listitem>
+        <para>Mac OS X on PowerPC (32-bit and 64-bit implementations)</para>
+      </listitem>
+      <listitem>
+        <para>Linux on x86 (32-bit and 64-bit implementations)</para>
+      </listitem>
+      <listitem>
+        <para>Mac OS X on x86 (32-bit and 64-bit implementations)</para>
+      </listitem>
+      <listitem>
+	<para>FreeBSD on x86 (32-bit and 64-bit implementations)</para>
+      </listitem>
+      <listitem>
+	<para>Solaris on x86 (32-bit and 64-bit implementations)</para>
+      </listitem>
+      <listitem>
+	<para>MS Windows XP and later on x86 (32-bit and 64-bit implementations)</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>A 64-bit version of &CCL; requires a 64-bit processor
+      running a 64-bit OS variant.</para>
+    
+    <para>Additional platform-specific information is given in the
+      following subsections.</para>
+
+    <para>Older versions are still available for downloading as
+    tarballs.  Version 1.0 was a stable version released in late 2005.
+    Version 1.1 was under active development until late 2007.  A final
+    1.1 release was never made.  It was distributed as a series of
+    development "snapshots" and CVS updates.  1.1 snapshots introduced
+    support for x86-64 platforms, internal use of Unicode, and many
+    other features, but were moving targets.  Version 1.2 was a stable
+    version released in April 2008.</para>
+
+    <!-- ***************************************************** -->
+    <sect2 id="linuxppc"><title>LinuxPPC</title> 
+      
+      <para>&CCL; requires version 2.2.13 (or later) of the Linux
+      kernel and version 2.1.3 (or later) of the GNU C library (glibc)
+      at a bare minimum.</para>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="linuxx86"><title>Linux x86</title> 
+    
+      <para>
+	Because of the nature of Linux distributions, it's difficult
+	to give precise version number requirements.  In general, a
+	"fairly modern" (no more than 2 or three years old) kernel and
+	C library are more likely to work well than older
+	versions.</para>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="freebsdx86"><title>FreeBSD x86</title>
+    <para>&CCL; should run on
+    FreeBSD 6.x and 7.x.
+    FreeBSD 7 users will need to install the "compat6x" package in order to use
+    the distributed &CCL; kernel, which is built on a FreeBSD 6.x system.</para>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="macosx"><title>Mac OS X (ppc and x86)</title>
+
+      <para> &CCL; runs under Mac OS X versions 10.4 and 10.5.
+      </para>
+
+      <para>64-bit versions of &CCL; require 64-bit processors
+      (e.g., a G5 or Core 2 processor).  Some early Intel-based Macintoshes
+      used processors that don't support
+      64-bit operation, so the 64-bit &CCL; will not run on them, although
+      the 32-bit &CCL; will.
+      </para>
+
+      <para>&CCL; hasn't been tested under Darwin proper, but
+        &CCL; doesn't intentionally use any Mac OS X features beyond
+        the Darwin subset and therefore it seems likely that &CCL;
+        would run on Darwin versions that correspond to recent Mac OS X
+        versions.</para>
+    </sect2>
+
+  </sect1>
+
+
+  <!-- ============================================================ -->
+  <sect1 id="obtaining-ccl"><title>Obtaining &CCL;</title>
+    <para>There two main ways to obtain &CCL;.  For Mac OS X,
+    there are disk images that can be used to install &CCL; in
+    the usual Macintosh way. For other OSes, Subversion is the best
+    way to obtain &CCL;.  Mac OS X users can also use Subversion
+    if they prefer. Tarballs are available for those who prefer them,
+    but if you have Subversion installed, it is simpler and more
+    flexible to use Subversion than tarballs.
+    </para>
+
+    <para> There are three popular ways to use &CCL;: as a
+      stand-alone double-clickable application (Mac OS X only), as a
+      command-line application, or with EMACS and SLIME. The following
+      sections describe these options.</para>
+
+    <!-- ***************************************************** -->
+    <sect2 id="obtaining-the-mac-way"><title>The Mac Way</title>
+      <para>If you are using Mac OS X then you can install and use
+         &CCL; in the usual Macintosh way.  Download and mount a
+         disk image, then drag the ccl folder to the Applications folder
+	 or wherever you wish.
+         After that you can double-click the Clozure CL application found
+	 inside the ccl directory.  The disk images are available at
+         <ulink url="ftp://clozure.com/pub/release/1.3/"/> </para>
+
+      <para>So that &CCL; can locate its source code, and for other
+        reasons explained in
+        <xref linkend="Predefined-Logical-Hosts"/>, you keep the
+        Clozure CL application
+        in the <literal>ccl</literal> directory.  If you use a shell,
+        you can set the value of the
+        <varname>CCL_DEFAULT_DIRECTORY</varname> environment variable
+        to explicitly indicate the location of
+        the <literal>ccl</literal> directory. If you choose to do
+        that, then the <literal>ccl</literal> directory and the Clozure CL
+        application can each be in any location you find
+        convenient.</para>
+    </sect2>
+    
+
+    <!-- ***************************************************** -->
+    <sect2 id="obtaining-via-svn"><title>Getting &CCL; with Subversion</title>
+      <para>It is very easy to download, install, and build &CCL;
+      using Subversion. This is the preferred way to get either the
+      latest, or a specific version of &CCL;, unless you prefer
+      the Mac Way.  Subversion is a source code control system that is
+      in wide usage.  Most modern OSes come with Subversion
+      pre-installed. A complete, buildable and runnable set of &CCL;
+      sources and binaries can be retrieved with a single Subversion command.
+      </para>
+
+      <para>Day-to-day development of &CCL; takes place in an area
+      of the Subversion repository known as the trunk.  At most times,
+      the trunk is perfectly usable, but occasionally it can be unstable
+      or totally broken.  If you wish to live on the 
+      bleeding edge, the following command will fetch a copy of the trunk
+      for Darwin x86 (both 32- and 64-bit versions):
+      </para>
+
+        <programlisting>
+          <![CDATA[
+svn co http://svn.clozure.com/publicsvn/openmcl/trunk/darwinx86/ccl]]>
+        </programlisting>
+
+	<para>
+	  To get a trunk &CCL; for another platform, replace
+	  "darwinx86" with one of the following names (all versions
+	  include both 32- and 64-bit binaries):
+	</para>
+	<itemizedlist>
+	  <listitem><para>darwinx86</para></listitem>
+	  <listitem><para>linuxx86</para></listitem>
+	  <listitem><para>freebsdx86</para></listitem>
+	  <listitem><para>solarisx86</para></listitem>
+	  <listitem><para>windows</para></listitem>
+	  <listitem><para>linuxppc</para></listitem>
+	  <listitem><para>darwinppc</para></listitem>
+	</itemizedlist>
+
+	<para>Release versions of &CCL; are intended to be stable.  While
+	bugs will be fixed in the release branches, enhancements
+	and new features will go into the trunk.  To get the 1.3 release
+	of &CCL; type:</para>
+        <programlisting>
+          <![CDATA[
+svn co http://svn.clozure.com/publicsvn/openmcl/release/1.3/darwinx86/ccl]]>
+        </programlisting>
+
+        
+        <para>The above command will fetch the complete sources and binaries
+        for the Darwin x86 build of &CCL;. To get a &CCL; for another platform,
+	replace "darwinx86" with one of the following names (all versions
+	include both 32- and 64-bit binaries):</para>
+
+        <itemizedlist>
+	  <listitem><para>darwinx86</para></listitem>
+	  <listitem><para>linuxx86</para></listitem>
+	  <listitem><para>freebsdx86</para></listitem>
+	  <listitem><para>solarisx86</para></listitem>
+	  <listitem><para>windows</para></listitem>
+	  <listitem><para>linuxppc</para></listitem>
+	  <listitem><para>darwinppc</para></listitem>
+        </itemizedlist>
+
+        <para>These distributions contain complete sources and
+        binaries. They use Subversion's "externals" features to share
+        common sources; the majority of source code is the same across
+        all versions.</para> 
+
+        <para>Once the checkout is complete you can build &CCL; by
+        running the lisp kernel and executing
+        the <literal>rebuild-ccl</literal> function. For
+        example:</para>
+
+        <programlisting>
+          <![CDATA[
+joe:ccl> ./dx86cl64
+Welcome to Clozure Common Lisp Version 1.2  (DarwinX8664)!
+? (rebuild-ccl :full t)
+
+<lots of compilation output>
+
+  ? (quit)
+  joe:ccl>]]>
+        </programlisting>
+
+	<para>
+	  If you don't have a C compiler toolchain installed, the
+	  <literal>rebuild-ccl</literal> will not work.  Please
+	  refer to <xref linkend="building-ccl-from-source"/> for
+	  addtional details.
+	</para>
+	<sect3 id="Checking-Subversion-Installation"><title>Checking Subversion Installation</title>
+      <para>If <literal>svn co</literal> doesn't work, then make sure
+      that Subversion is installed on your system.  Bring up a command
+      line shell and type:
+        <programlisting>
+          <![CDATA[
+shell> svn]]>
+        </programlisting> 
+        If Subversion is installed, you will see something like:
+        <programlisting>
+          <![CDATA[
+Type 'svn help' for usage]]>
+        </programlisting>
+        If Subversion is not installed, you will see something
+        like:
+        <programlisting>
+          <![CDATA[
+-bash: svn: command not found]]>
+        </programlisting>
+        If Subversion is not installed, you'll need to figure out how
+        to install it on your OS. You can find information about
+        obtaining and installing Subversion at
+        the <ulink url="http://subversion.tigris.org/project_packages.html">Subversion
+        Packages page</ulink>.</para></sect3>
+
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="obtaining-via-tarballs"><title>Tarballs</title>
+      <para>Tarballs are available at <ulink
+      url="ftp://clozure.com/pub/release/1.3/"/>.  Download and extract
+      one on your local disk.  Then edit the &CCL; shell script to set
+      the value of <varname>CCL_DEFAULT_DIRECTORY</varname> and start
+      up the appropriate &CCL; kernel. See <xref
+      linkend="The-ccl-Shell-Script"/> for more information about the
+      &CCL; shell scripts.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="command-line-setup"><title>Command Line Set Up</title>
+    <para>Sometimes it's convenient to use &CCL; from a Unix
+      shell command line.  This is especially true when using &CCL;
+      as a way to run Common Lisp utilities.</para>
+
+    <!-- ***************************************************** -->
+    <sect2 id="The-ccl-Shell-Script"><title>The ccl Shell Script</title>
+      <para>&CCL; needs to be able to find the
+        <literal>ccl</literal> directory in order to support features
+        such as <literal>require</literal> and
+        <literal>provide</literal>, access to foreign interface
+        information (see <link linkend="The-Interface-Database">The
+        Interface Database</link>) and the Lisp build process (see
+        <link linkend="Building-CCL">Building &CCL; from its Source
+        Code</link>). Specifically, it needs to set up logical
+        pathname translations for the <literal>"ccl:"</literal>
+        logical host.  If this logical host isn't defined (or isn't
+        defined correctly), some things might work, some things might
+        not, and it'll generally be hard to invoke and use &CCL;
+        productively.</para>
+
+      <para>&CCL; uses the value of the environment variable
+        <literal>CCL_DEFAULT_DIRECTORY</literal> to determine the
+        filesystem location of the <literal>ccl</literal> directory;
+        the ccl shell script is intended to provide a way to
+        invoke &CCL; with that environment variable set
+        correctly.</para>
+      <para>There are two versions of the shell script:
+        <literal>"ccl/scripts/ccl"</literal> is used to invoke
+        32-bit implementations of &CCL; and
+        <literal>"ccl/scripts/ccl64"</literal> is used to invoke
+        64-bit implementations.</para>
+      <para>To use the script:</para>
+      <orderedlist>
+	<listitem>
+	  <para>Copy the script to a directory that is on your
+	  <varname>PATH</varname>.  This is often
+	  <literal>/usr/local/bin</literal> or
+	  <literal>~/bin</literal>.  It is better to do this than to
+	  add <literal>ccl/scripts</literal> to your
+	  <varname>PATH</varname>, because the script needs to be edited,
+	  and editing it in-place means that Subversion sees the script as
+	  modified..</para>
+	</listitem>
+        <listitem>
+          <para>Edit the definition of
+            <literal>CCL_DEFAULT_DIRECTORY</literal> near the
+            beginning of the shell script so that it refers to
+            your <literal>ccl</literal> directory.  Alternately, set
+            the value of the <literal>CCL_DEFAULT_DIRECTORY</literal>
+            environment variable in your .cshrc, .tcshrc,
+            .bashrc,.bash_profile, .MacOSX/environment.plist, or
+            wherever you usually set environment variables.  If there
+            is an existing definition of the variable, the ccl
+            script will not override it. The shell script sets a local
+            variable (<literal>OPENMCL_KERNEL</literal>) to the
+            standard name of the &CCL; kernel approprate for the
+            platform, as determined by 'uname -s'. You might prefer to
+            set this variable manually in the shell script.</para>
+        </listitem>
+
+        <listitem>
+          <para>Ensure that the shell script is executable, for
+            example:</para> 
+          <para><literal>$ chmod +x
+            ~/ccl/ccl/scripts/ccl64</literal></para> 
+          <para>This command grants execute permission to the named
+            script. If you are using a 32-bit platform, substitute
+            "ccl" in place of "ccl64".
+            <warning>
+	          <para>The above command won't work if you are not the
+	            owner of the installed copy of &CCL;. In that case,
+	            you can use the "sudo" command like this:</para>
+              <para><literal>$ sudo chmod +x
+                  ~/ccl/ccl/scripts/ccl64</literal></para>
+              <para>Give your password when prompted.</para>
+              <para>If the "sudo" command doesn't work, then you are
+                not an administrator on the system you're using, and you
+                don't have the appropriate "sudo" permissions. In that
+                case you'll need to get help from the system's
+                administrator.</para>
+          </warning></para>
+        </listitem>
+      </orderedlist>
+
+      <para>Note that most people won't need both
+      <literal>ccl</literal> and <literal>ccl64</literal> scripts.
+      You only need both if you sometimes run 32-bit &CCL; and
+      sometimes run 64-bit &CCL;.  You can rename the script that
+      you use to whatever you want.  For example, if you are on a
+      64-bit system, and you only use &CCL; in 64-bit mode, then
+      you can rename  <literal>ccl64</literal> to
+      <literal>ccl</literal> so that you only need to type
+      "<literal>ccl</literal>" to run it.</para>
+
+      <para>Once this is done, it should be possible to invoke &CCL;
+        by typing <literal>ccl</literal>
+        or <literal>ccl64</literal> at a shell prompt:</para>
+      <programlisting>
+&gt; ccl [args ...]
+Welcome to &CCL; Version 1.2 (DarwinPPC32)!
+?
+      </programlisting>
+      
+      <para>The ccl shell script passes all of its arguments to the
+      &CCL; kernel.  See <xref linkend="Invocation"/> for more
+      information about these arguments.  When invoked this way, the
+      Lisp should be able to initialize the <literal>"ccl:"</literal>
+      logical host so that its translations refer to the
+      <literal>"ccl"</literal> directory. To test this, you can call
+      <literal>probe-file</literal> in &CCL;'s read-eval-print
+      loop:</para>
+      <programlisting>
+? (probe-file "ccl:level-1;level-1.lisp")  ;returns the physical pathname of the file
+#P"/Users/alms/my_lisp_stuff/ccl/level-1/level-1.lisp"
+      </programlisting>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="Invocation">
+	  <title>Invocation</title>
+	  <para>Assuming that the shell script is properly installed, it can be used to invoke &CCL; from a shell prompt:
+	    <programlisting>
+shell&gt;<replaceable>ccl</replaceable> <emphasis>args</emphasis>
+	    </programlisting>
+	    <literal>ccl</literal> runs a 32-bit session;
+	    <literal>ccl64</literal> runs a 64-bit session.
+	  </para>
+    </sect2>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Personal-Customization-with-the-Init-File">
+	<title>Personal Customization with the Init File</title>
+    <para>By default &CCL; tries to load the file
+      <literal>"home:ccl-init.lisp"</literal> or the compiled
+      <literal>"home:ccl-init.fasl"</literal> upon starting up.
+      &CCL; does this by executing <literal>(load
+      "home:ccl-init")</literal>.  If it's unable to load the file
+      (for example because the file doesn't exist), &CCL; doesn't
+      signal an error or warning, it just completes its startup
+      normally.</para>
+    <para>
+      On Unix systems, if <literal>"ccl-init.lisp"</literal> is not
+      present, &CCL; will look for <literal>".ccl-init.lisp"</literal>
+      (post 1.2 versions only).
+    </para>
+    <para>The <literal>"home:"</literal> prefix to the filename is a
+      Common Lisp logical host, which &CCL; initializes to refer to
+      your home directory. &CCL; therefore looks for either of the
+      files
+      <literal>~/ccl-init.lisp</literal> or
+      <literal>~/ccl-init.fasl</literal>.</para>
+    <para>Because the init file is loaded the same way as normal Lisp
+      code is, you can put anything you want in it.  For example, you
+      can change the working directory, and load packages that you use
+      frequently.</para>
+    <para>To suppress the loading of this init-file, invoke &CCL; with the
+      <literal>--no-init</literal> option.</para>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Command-Line-Options">
+	<title>Command Line Options</title>
+    <para>When using &CCL; from the command line, the following
+      options may be used to modify its behavior.  The exact set of
+      &CCL; command-line arguments may vary per platform and
+      slowly changes over time.  The current set of command line
+      options may be retrieved by using the
+      <literal>--help</literal> option.</para>
+	<itemizedlist>
+	  <listitem>
+	    <para><literal>-h</literal> (or
+	      <literal>--help</literal>).  Provides a definitive (if
+	      somewhat terse) summary of the command line options
+	      accepted by the &CCL; implementation and then
+	      exits.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-V</literal> (or
+	      <literal>--version</literal>).  Prints the version of
+	      &CCL; then exits.  The version string is the same value
+	      that is returned by
+	      <function>LISP-IMPLEMENTATION-VERSION</function>.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-K</literal>
+	      <parameter>character-encoding-name</parameter> (or
+	      <literal>--terminal-encoding</literal>
+	      <parameter>character-encoding-name</parameter>).
+	      Specifies the character encoding to use for
+	      <varname>*TERMINAL-IO*</varname> (see <xref
+	                                               linkend="Character-Encodings"/>).  Specifically, the
+	      <parameter>character-encoding-name</parameter> string
+	      is uppercased and interned in the KEYWORD package. If an
+	      encoding named by that keyword exists,
+	      <varname>CCL:*TERMINAL-CHARACTER-ENCODING-NAME*</varname> is set to the name
+	      of that encoding.   <varname>CCL:*TERMINAL-CHARACTER-ENCODING-NAME*</varname> defaults to <literal>NIL</literal>, which
+	      is a synonym for <literal>:ISO-8859-1</literal>.</para>
+	    <para>For example:
+	      <programlisting>
+<![CDATA[shell> ccl -K utf-8]]>
+	      </programlisting>
+	      has the effect of making the standard CL streams use
+	      <literal>:UTF-8</literal> as their character
+	      encoding.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-n</literal> (or
+	      <literal>--no-init</literal>). If this option is given, the
+	      init file is not loaded.  This is useful if &CCL; is being
+	      invoked by a shell script that should not be affected by
+	      whatever customizations a user might have in place.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-e</literal> <parameter>form</parameter>
+	      (or <literal>--eval</literal>). An expression is read (via
+	      <function>READ-FROM-STRING</function>) from the string
+	      <parameter>form</parameter> and evaluated. If
+	      <parameter>form</parameter> contains shell metacharacters,
+	      it may be necessary to escape or quote them to prevent the
+	      shell from interpreting them.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-l</literal> <parameter>path</parameter>
+	      (or <literal>--load</literal>
+	      <parameter>path</parameter>). Loads file specified by
+	      <parameter>path</parameter>.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-T</literal> <parameter>n</parameter> (or
+	      <literal>--set-lisp-heap-gc-threshold</literal>
+	      <parameter>n</parameter>).  Sets the Lisp gc threshold to
+	      <parameter>n</parameter>. (see <xref
+	                                        linkend="GC-Page-reclamation-policy"/></para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-Q</literal> (or
+	      <literal>--quiet</literal>). Suppresses printing of
+	      heralds and prompts when the <literal>--batch</literal>
+	      command line option is specified.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-R</literal> <parameter>n</parameter> (or
+	      <literal>--heap-reserve</literal>). Reserves
+	      <parameter>n</parameter> bytes for heap expansion.  The
+	      default is <literal> 549755813888</literal>.  (see <xref
+	                                                            linkend="Heap-space-allocation"/>)</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-S</literal> <parameter>n</parameter> (or
+	      <literal>--stack-size</literal> <parameter>n</parameter>). Sets the size of the
+	      initial control stack to <parameter>n</parameter>. (see <xref
+	                                                                 linkend="Thread-Stack-Sizes"/>)</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-Z</literal> <parameter>n</parameter> (or
+	      <literal>--thread-stack-size</literal>
+	      <parameter>n</parameter>). Sets the size of the first
+	      thread's stack to <parameter>n</parameter>. (see <xref
+	                                                          linkend="Thread-Stack-Sizes"/>)</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-b</literal> (or <literal>--batch</literal>). Execute in "batch mode". End-of-file
+	      from <varname>*STANDARD-INPUT*</varname> causes &CCL; to exit, as do attempts to
+	      enter a break loop.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>--no-sigtrap</literal> An obscure option for running under GDB.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><literal>-I</literal>
+	      <parameter>image-name</parameter> (or
+	      <literal>--image-name</literal>
+	      <parameter>image-name</parameter>). Specifies the image
+	      name for the kernel to load.  Defaults to the kernel name
+	      with ".image" appended.</para>
+	  </listitem>
+	</itemizedlist>
+
+    <para>The <literal>--load</literal> and
+      <literal>--eval</literal> options can each be provided
+      multiple times.  They're executed in the order specified on
+      the command line, after the init file (if there is one) is
+      loaded and before the toplevel read-eval-print loop is
+      entered.</para>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Using-CCL-with-GNU-Emacs-and-SLIME">
+    <title>Using &CCL; with GNU Emacs and SLIME</title>
+    <para>A very common way to use &CCL; is to run it within the
+      GNU Emacs editor, using a Lisp interface called SLIME ("Superior
+      Lisp Interaction Mode for Emacs"). SLIME is an Emacs package
+      designed to provide good support within Emacs for any of several
+      Common Lisp implementations; one of the supported
+      implementations is &CCL;. This page describes how you can
+      download SLIME and set it up to work with your &CCL;
+      installation.</para>
+    <para>Why use SLIME? With SLIME, you can do the following things from within
+      an Emacs editing session:</para>
+    <itemizedlist>
+      <listitem><para>run and control Lisp</para></listitem>
+      <listitem><para>evaluate, compile, and load files or expressions</para></listitem>
+      <listitem><para>macroexpand expressions</para></listitem>
+      <listitem><para>fetch documentation and source code for Lisp symbols</para></listitem>
+      <listitem><para>autocomplete symbols and package names</para></listitem>
+      <listitem><para>cross-reference function calls</para></listitem>
+      <listitem><para>examine stack traces and debug errors</para></listitem>
+      
+    </itemizedlist>
+    <para>For complete information about SLIME, see the
+      SLIME <ulink url="http://common-lisp.net/project/slime/">home
+      page</ulink>. The SLIME home page provides up-to-date downloads,
+      plus documentation, tutorials, and instructional
+      screencasts.</para>
+
+    <!-- ***************************************************** -->
+    <sect2 id="Assumptions-and-Requirements">
+	  <title>Assumptions and Requirements</title>
+      <para>In order to simplify these instructions, we'll make
+        several assumptions about your system. Specifically, we
+        assume:</para>
+      <itemizedlist>
+        <listitem>
+	      <para>You have a working installation of GNU Emacs. If you
+	        don't have a working copy of GNU Emacs, see the web page on
+	        <ulink url="http://www.gnu.org/software/emacs/#Obtaining">obtaining
+	        Emacs</ulink>.  If you prefer to use XEmacs instead of GNU
+	        Emacs, these instructions should still work; SLIME supports
+	        XEmacs Version21. Mac OS X includes an Emacs installation.
+	        If you want to look into different versions, you can check
+	        out theEmacsWiki, which maintains a
+	        page, EmacsForMacOS, that provides much more information
+	        about using Emacs on the Mac.</para>
+          <para>A popular version of Emacs among Mac users is
+            <ulink url="http://aquamacs.org/">Aquamacs</ulink>. This
+            application is a version of GNU Emacs with a number of
+            customizations meant to make it behave more like a
+            standard Macintosh application, with windows, a menubar,
+            etc.  Aquamacs includes SLIME; if you like Aquamacs then
+            you can use SLIME right away, without getting and
+            installing it separately. You just need to tell SLIME
+            where to find your installation of &CCL;.</para>
+	    </listitem>
+        <listitem>
+          <para>You have a working copy of &CCL;, installed in
+            <literal>"~/ccl"</literal>If you prefer to install
+            &CCL; in some directory other
+            than<literal>"~/ccl"</literal> then these
+            instructions still work, but you must remember to use your
+            path to your ccl directory instead of the one that we give
+            here.</para>
+        </listitem>
+        <listitem>
+          <para>You install emacs add-ons in the folder
+            <literal>"~/emacs/site/"</literal>If this directory
+            doesn't exist on your system, you can just create it.If
+            you prefer to install Emacs add-ons in some place other
+            than<literal>"~/emacs/site/"</literal> then you must
+            remember to use your path to Emacs add-ons in place of
+            ours.</para>
+        </listitem>
+        
+      </itemizedlist>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="Getting_Slime"><title>Getting SLIME</title>       
+
+      <para>You can get SLIME from the SLIME Home Page. Stable
+        releases and CVS snapshots are available as archive files, or
+        you can follow the instructions on the SLIME Home Page to
+        check out the latest version from their CVS repository.</para>
+
+      <para>It's worth noting that stable SLIME releases happen very
+        seldom, but the SLIME developers often make changes and
+        improvements that are available through CVS updates. If you
+        asked the SLIM developers, they would most likely recommend
+        that you get SLIME from their CVS repository and update it
+        frequently.</para>
+
+      <para>Whether you get it from CVS, or download and unpack one
+        of the available archives, you should end up with a folder
+        named "slime" that contains the SLIME distribution.</para>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="installing-slime"><title>Installing SLIME</title> 
+
+      <para>Once you have the "slime" folder described in the previous
+        section, installation is a simple matter of copying the folder
+        to the proper place. You can drag it into the "~/emacs/site/"
+        folder, or you can use a terminal command to copy it
+        there. For example, assuming your working directory contains
+        the unpacked "slime" folder:</para> <para><literal>$ cp -R
+        slime ~/emacs/site/</literal></para> <para>That's all it
+        takes.</para>
+
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="Telling-Emacs-About-SLIME">
+	  <title>Telling Emacs About SLIME</title>
+      <para> Once SLIME and &CCL; are installed, you just need to
+        add a line to your "~/.emacs" file that tells SLIME where to
+        find the script that runs &CCL;:</para>
+      <para><literal>(setq inferior-lisp-program "~/ccl/scripts/ccl64")</literal></para>
+      <para>or</para>
+      <para><literal>(setq inferior-lisp-program "~/ccl/scripts/ccl")</literal></para>
+      <warning>
+        <para>Aquamacs users should add this line to the file "~/Library/Preferences/Aquamacs Emacs/Preferences.el".</para>
+      </warning>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="Running-CCL-with-SLIME">
+	  <title>Running &CCL; with SLIME</title>
+      <para>Once the preparations in the previous section are
+        complete, exit Emacs and restart it, to ensure that it reads
+        the changes you made in your ".emacs" file (alternatively, you
+        could tell Emacs to reload the ".emacs" file). If all went
+        well, you should now be ready to run &CCL; using
+        SLIME.</para>
+      <para>To run &CCL;, execute the command "M-x slime". SLIME
+        should start an &CCL; session in a new buffer.  (If you are
+        unfamiliar with the Emacs notation "M-x command", see the GNU
+        Emacs FAQ; specifically, take a look at questions 1, 2, and
+        128.)</para>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="What-if-a-New-Version-of-CCL-Breaks-SLIME-">
+	  <title>What if a New Version of &CCL; Breaks SLIME?</title>
+	  <para>Sometimes you'll get a new version of &CCL;, set up
+	    Emacs to use it with SLIME, and SLIME will fail. Most likely
+	    what has happened is that the new version of &CCL; has a
+	    change in the output files produced by the compiler (&CCL;
+	    developers will say "the fasl version has changed." fasl
+	    stands for "fast load" aka compiled files). This
+	    problem is easy to fix: just delete the existing SLIME fasl
+	    files. The next time you launch Emacs and start SLIME, it will
+	    automatically recompile the Lisp files, and that should fix
+	    the problem.</para>
+      <para>SLIME's load process stores its fasl files in a hidden
+        folder inside your home folder. The path is</para>
+      <para><literal>~/.slime/fasl</literal></para>
+      <para>You can use a shell command to remove the fasl files, or
+        remove them using your system's file browser.</para>
+      <para><emphasis role="bold">Note for Macintosh Users:</emphasis> 
+	    The leading "." character in the ".slime" folder's name
+	    prevents the Finder from showing this folder to you. If you
+	    use the "Go To Folder" menu item in the Finder's "Go" menu,
+	    you can type in "~/.slime" and the Finder will show it to
+	    you. You can then drag the "fasl" folder to the trash.
+	  </para>
+    </sect2>
+
+    <!-- ***************************************************** -->
+    <sect2 id="Known-Bugs">
+	  <title>Known Bugs</title>
+	  <para>SLIME has not been updated to account for recent changes
+	    made in &CCL; to support x86-64 processors. You may run into
+	    bugs running on those platforms.</para>
+      <para>The SLIME backtrace sometimes shows incorrect information.</para>
+      <para><literal>return-from-frame</literal> and
+        <literal>apply-in-frame</literal> do not work reliably.  (If
+        they work at all, it's pure luck.)</para>
+      <para>Some versions of Emacs on the Macintosh may have trouble
+        finding the shell script that runs &CCL; unless you specify
+        a full path to it. See the above section "Telling Emacs About
+        SLIME" to learn how to specify the path to the shell
+        script.</para>
+      <para>For more help with &CCL; on Mac OS X, consult the &CCL;
+        mailing lists. You can find information about the mailing
+        lists on the
+        &CCL; <ulink url="http://trac.clozure.com/openmcl">wiki</ulink>.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Example-Programs">
+    <title>Example Programs</title>
+    <para>A number (ok, a <emphasis>small</emphasis> number), of
+    example programs are distributed in the "ccl:examples;" directory
+    of the source distribution. See the README-OPENMCL-EXAMPLES text
+    file in that directory for information about prerequisites and
+    usage.</para>
+    <para>Some of the example programs are derived from C examples
+      in textbooks, etc.; in those cases, the original author and work
+      are cited in the source code.</para>
+    <para>Unless the original author or contributor claims other
+      rights, you're free to incorporate any of this example code or
+      derivative thereof in any of your own works without
+      restriction. In doing so, you agree that the code was provided
+      "as is", and that no other party is legally or otherwise
+      responsible for any consequences of your decision to use
+      it.</para>
+    <para>If you've developed &CCL; examples that you'd like to see
+      added to the distribution, please send mail to the &CCL; mailing
+      lists. Any such contributions would be welcome and appreciated
+      (as would bug fixes and improvements to the existing
+      examples.)</para>
+  </sect1>
+</chapter>
Index: /branches/new-random/doc/src/makefile-common
===================================================================
--- /branches/new-random/doc/src/makefile-common	(revision 13309)
+++ /branches/new-random/doc/src/makefile-common	(revision 13309)
@@ -0,0 +1,83 @@
+# -*- coding: unix -*-
+
+ifdef COMMIT
+SVN=/usr/bin/svn
+else
+SVN=/bin/true
+endif
+
+
+# The local stylesheet imports the generic stylesheets and
+# sets some custom parameters.
+
+STYLESHEET = xsl/openmcl.xsl
+
+# Obtain a temporary ID to be used as the identifier of this invocation of
+# make.
+
+TEMP := build-$(shell date +%s)
+
+# Save the current directory for use in the tarfile target.
+
+CWD := $(shell pwd)
+
+# There's datestamps on the page; let's make sure they're in
+# UTC instead of local time.
+
+export TZ = UTC
+
+# Compute some targets.
+
+XMLFILES = $(wildcard *.xml)
+XSLFILES = $(shell find xsl -name "*.xsl")
+HTMLFILES = ccl-documentation.html
+PARENT = ../ccl-documentation.html
+
+# Save the xsltproc version string for use in debugging.
+
+XSLTPROCVERSION = $(shell $(XSLTPROC) --version | head -n 1)
+
+# Try to determine the svn revishion
+SVNREV = $(shell /usr/bin/svnversion)
+
+
+.PHONY: all clean distclean show
+
+
+$(HTMLFILES): $(XMLFILES)  $(XSLFILES)
+	rm -rf build-* *~
+	$(XSLTPROC) \
+		--xinclude \
+		--stringparam root.filename $(basename $(@F)) \
+		--stringparam base.dir $(TEMP)/ \
+		--stringparam openmcl.directory $(@D)/ \
+		--stringparam onechunk \
+			$(if $(findstring Doc, $(@D)), 0, 1) \
+		--stringparam xsltproc.version "$(XSLTPROCVERSION)." \
+                --stringparam svnrev "$(SVNREV)"\
+		$(EXTRAPARAMS) \
+		$(STYLESHEET) ccl-documentation.xml
+	rm -f $(if $(findstring Doc, $(@D)), $(@D)/*.html, $@)
+	mv $(TEMP)/*.html $(@D)/
+
+${PARENT}: ${HTMLFILES}
+	cp ${HTMLFILES} ${PARENT}
+	$(CCL) -b -n -l ../doc-splitter -e '(doc-splitter:split-doc-file "ccl-documentation.html" "../manual/")' </dev/null
+	(cd .. ; $(SVN) commit -m "updated" ccl-documentation.html)
+
+all: ${TEMP} ${HTMLFILES} distclean
+	echo ${HTMLFILES}
+
+
+install: $(PARENT)
+
+
+$(TEMP):
+	mkdir $(TEMP)
+
+clean:
+	rm -rf build-*
+
+distclean: clean 
+	rm -f *~
+
Index: /branches/new-random/doc/src/modifying.xml
===================================================================
--- /branches/new-random/doc/src/modifying.xml	(revision 13309)
+++ /branches/new-random/doc/src/modifying.xml	(revision 13309)
@@ -0,0 +1,564 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="Modifying-CCL">
+  <title>Modifying &CCL;</title>
+
+  <sect1 id="Contributing-Code-Back-to-the-CCL-Project">
+    <title>Contributing Code Back to the &CCL; Project</title>
+    <para>This section is a placeholder, added as of August 2004.  The
+      full text is being written, and will be added as soon as it is
+      available.</para>
+  </sect1>
+
+  <sect1 id="Using-CCL-in--development--and-in--user--mode">
+    <title>Using &CCL; in "development" and in  "user" mode</title>
+
+    <para>As it's distributed, &CCL; starts up with *PACKAGE* set to
+      the CL-USER package and with most predefined functions and
+      methods protected against accidental redefinition.  The package
+      setting is of course a requirement of ANSI CL, and the
+      protection of predefined functions and methods is intended to
+      catch certain types of programming errors (accidentally
+      redefining a CL or CCL function) before those errors have a
+      chance to do much damage.</para>
+    <para>These settings may make using &CCL; to develop &CCL; a bit
+      awkward, because much of that process assumes you are working in
+      the CCL package is current, and a primary purpose of &CCL;
+      development is to redefine some predefined, builtin functions.
+      The standard, "routine" ways of building &CCL; from sources (see
+      ) - COMPILE-CCL, XCOMPILE-CCL, and XLOAD-LEVEL-0 - bind
+      *PACKAGE* to the "CCL" package and enable the redefinition of
+      predefined functions; the symbols COMPILE-CCL, XCOMPILE-CCL, and
+      XLOAD-LEVEL-0 are additionally now exported from the "CCL"
+      package.</para>
+    <para>Some other (more ad-hoc) ways of doing development on
+      &CCL;&mdash;compiling and/or loading individual files,
+      incrementally redefining individual functions&mdash;may be
+      awkward unless one reverts to the mode of operation which was
+      traditionally offered in &CCL;. Some &CCL; source files -
+      especially those that comprise the bootstrapping image sources
+      and the first few files in the "cold load" sequence - are
+      compiled and loaded in the "CCL" package but don't contain
+      (IN-PACKAGE "CCL") forms, since IN-PACKAGE doesn't work until
+      later in the cold load sequence.</para>
+    <para>The somewhat bizarre behavior of both SET-USER-ENVIRONMENT
+      and SET-DEVELOPMENT-ENVIRONMENT with respect to the special
+      variables they affect is intended to allow those constructs to
+      take effect when the read-eval-print loop next returns to a
+      top-level '? ' prompt; the constructs can meaningfully be used
+      inside LOAD, for instance (recall that LOAD binds *PACKAGE*),
+      though using both constructs within the same LOAD call would
+      likely be pretty confusing.</para>
+    <para>"user" and "development" are otherwise very generic terms;
+      here they're intended to enforce the distinction between "using"
+      &CCL; and "developing" it.</para>
+    <para>The initial environment from which &CCL; images are
+      saved is one where (SET-USER-ENVIRONMENT T) has just been
+      called; in previous versions, it was effectively as if
+      (SET-DEVELOPMENT-ENVIRONMENT T) had just been called.</para>
+    <para>Hopefully, most users of &CCL; can safely ignore these
+      issues most of the time. Note that doing (SET-USER-ENVIRONMENT
+      T) after loading one's own code (or 3rd-party code) into &CCL;
+      would protect that code (as well as &CCL;'s) from accidental
+      redefinition; that may be useful in some cases.</para>
+  </sect1>
+
+  <sect1 id="kernel-debugger">
+    <title>The Kernel Debugger</title>
+    <para> In a perfect world, something like this couldn't
+      happen:</para>
+    <programlisting>
+Welcome to &CCL; Version x.y!
+? (defun foo (x)
+    (declare (cons x))
+    (cdr x))
+FOO
+
+? (foo -1) ;Oops. Too late ...
+Unhandled exception 11 at 0x300e90c8, context->regs at #x7ffff6b8
+Continue/Debugger/eXit &lt;enter&gt;?
+    </programlisting>
+
+    <para>As you may have noticed, it's not a perfect world; it's rare
+      that the cause (attempting to reference the CDR of -1, and therefore
+      accessing unmapped memory near location 0) of this effect (an
+      "Unhandled exception ..." message) is so obvious.</para>
+    <para>The addresses printed in the message above aren't very useful
+      unless you're debugging the kernel with GDB (and they're often
+      very useful if you are.)</para>
+    <para>Aside from causing an exception that the lisp kernel doesn't
+      know how to handle, one can also enter the kernel debugger (more)
+      deliberately:</para>
+
+    <programlisting>
+? (defun classify (n)
+    (cond ((&gt; n 0) "Greater")
+          ((&lt; n 0) "Less")
+          (t
+           ;; Sheesh ! What else could it be ?
+           (ccl::bug "I give up. How could this happen ?"))))
+CLASSIFY
+
+? (classify 0)
+Bug in &CCL; system code:
+I give up. How could this happen ?
+? for help
+[12345] &CCL; kernel debugger:
+    </programlisting>
+
+    <para>CCL::BUG isn't quite the right tool for this example (a
+      call to BREAK or PRINT might do a better job of clearing up the
+      mystery), but it's sometimes helpful when those other tools
+      can't be used.  The lisp error system notices, for instance, if
+      attempts to signal errors themselves cause errors to be
+      signaled; this sort of thing can happen if CLOS or the I/O
+      system are broken or missing. After some small number of
+      recursive errors, the error system gives up and calls
+      CCL::BUG.</para>
+    <para>If one enters a '?' at the kernel debugger prompt, one
+      will see output like:</para>
+
+    <programlisting>
+(S)  Find and describe symbol matching specified name
+(B)  Show backtrace
+(X)  Exit from this debugger, asserting that any exception was handled
+(K)  Kill &CCL; process
+(?)  Show this help
+    </programlisting>
+
+    <para>CCL::BUG just does an FF-CALL into the lisp kernel.  If
+      the kernel debugger was invoked because of an unhandled
+      exception (such as an illegal memory reference) the OS kernel
+      saves the machine state ("context") in a data structure for us,
+      and in that case some additional options can be used to display
+      the contents of the registers at the point of the
+      exception. Another function&mdash;CCL::DBG&mdash;causes a special
+      exception to be generated and enters the lisp kernel debugger
+      with a non-null "context":</para>
+
+    <programlisting>
+? (defun classify2 (n)
+    (cond ((&gt; n 0) "Greater")
+          ((&lt; n 0) "Less")
+          (t (dbg n))))
+CLASSIFY2
+
+? (classify2 0)
+Lisp Breakpoint
+While executing: #&lt;Function CLASSIFY2 #x08476cfe>
+? for help
+[12345] &CCL; kernel debugger: ?
+(G)  Set specified GPR to new value
+(A)  Advance the program counter by one instruction (use with caution!)
+(D)  Describe the current exception in greater detail
+(R)  Show raw GPR/SPR register values
+(L)  Show Lisp values of tagged registers
+(F)  Show FPU registers
+(S)  Find and describe symbol matching specified name
+(B)  Show backtrace
+(X)  Exit from this debugger, asserting that any exception was handled
+(P)  Propagate the exception to another handler (debugger or OS)
+(K)  Kill &CCL; process
+(?)  Show this help
+    </programlisting>
+
+    <para>CCL::DBG takes an argument, whose value is copied into the register
+      that &CCL; uses to return a function's primary value (arg_z, which
+      is r23 on the PowerPC). If we were to choose the (L) option at this point,
+      we'd see a dislay like:</para>
+
+    <programlisting>
+rnil = 0x01836015
+nargs = 0
+r16 (fn) = #&lt;Function CLASSIFY2 #x30379386>
+r23 (arg_z) = 0
+r22 (arg_y) = 0
+r21 (arg_x) = 0
+r20 (temp0) = #&lt;26-element vector subtag = 2F @#x303793ee>
+r19 (temp1/next_method_context) = 6393788
+r18 (temp2/nfn) = #&lt;Function CLASSIFY2 #x30379386>
+r17 (temp3/fname) = CLASSIFY2
+r31 (save0) = 0
+r30 (save1) = *TERMINAL-IO*
+r29 (save2) = 0
+r28 (save3) = (#&lt;RESTART @#x01867f2e> #&lt;RESTART @#x01867f56>)
+r27 (save4) = ()
+r26 (save5) = ()
+r25 (save6) = ()
+r24 (save7) = ()
+    </programlisting>
+
+    <para>From this we can conclude that the problematic argument to CLASSIFY2
+      was 0 (see r23/arg_z), and that I need to work on a better example.</para>
+    <para>The R option shows the values of the ALU (and PPC branch unit)
+      registers in hex; the F option shows the values of the FPU registers.</para>
+    <para>The (B) option shows a raw stack backtrace; it'll try to
+      identify foreign functions as well as lisp functions. (Foreign function
+      names are guesses based on the nearest preceding exported symbol.)</para>
+    <para>If you ever unexpectedly find yourself in the "lisp kernel
+      debugger", the output of the (L) and (B) options are often the most
+      helpful things to include in a bug report.</para>
+  </sect1>
+
+  <sect1 id="Using-AltiVec-in-CCL-LAP-functions">
+    <title>Using AltiVec in &CCL; LAP functions</title>
+
+    <sect2 id="Overview--16-">
+	  <title>Overview</title>
+      <para>It's now possible to use AltiVec instructions in PPC LAP
+        (assembler) functions.</para>
+      <para>The lisp kernel detects the presence or absence of
+        AltiVec and preserves AltiVec state on lisp thread switch and
+        in response to exceptions, but the implementation doesn't
+        otherwise use vector operations.</para>
+      <para>This document doesn't document PPC LAP programming in
+        general.  Ideally, there would be some document that
+        did.</para>
+      <para>This document does explain AltiVec register-usage
+        conventions in &CCL; and explains the use of some lap macros
+        that help to enforce those conventions.</para>
+      <para>All of the global symbols described below are exported
+        from the CCL package. Note that lap macro names, ppc
+        instruction names, and (in most cases) register names are
+        treated as strings, so this only applies to functions and
+        global variable names.</para>
+      <para>Much of the &CCL; support for AltiVec LAP programming
+        is based on work contributed to MCL by Shannon Spires.</para>
+    </sect2>
+
+    <sect2 id="Register-usage-conventions">
+	  <title>Register usage conventions</title>
+      <para>&CCL; LAP functions that use AltiVec instructions must
+        interoperate with each other and with C functions; that fact
+        suggests that they follow C AltiVec register usage
+        conventions. (vr0-vr1 scratch, vr2-vr13 parameters/return
+        value, vr14-vr19 temporaries, vr20-vr31 callee-save
+        non-volatile registers.)</para>
+      <para>The EABI (Embedded Application Binary Interface) used in
+        LinuxPPC doesn't ascribe particular significance to the vrsave
+        special-purpose register; on other platforms (notably MacOS),
+        it's used as a bitmap which indicates to system-level code
+        which vector registers contain meaningful values.</para>
+      <para>The WITH-ALTIVEC-REGISTERS lap macro generates code that
+        saves, updates, and restores VRSAVE on platforms where this is
+        required (as indicated by the value of the special variable
+        that controls this behavior) and ignores VRSAVE on platforms
+        that don't require it to be maintained.</para>
+      <para>On all PPC platforms, it's necessary to save any non-volatile
+        vector registers (vr20 .. vr31) before assigning to them and to restore
+        such registers before returning to the caller.</para>
+      <para>On platforms that require that VRSAVE be maintained, it's
+        not necessary to mention the "use" of vector registers that
+        are used as incoming parameters. It's not incorrect to mention
+        their use in a WITH-ALTIVEC-REGISTERS form, but it may be
+        unnecessary in many interesting cases. One can likewise assume
+        that the caller of any function that returns a vector value in
+        vr2 has already set the appropriate bit in VRSAVE to indicate
+        that this register is live. One could therefore write a leaf
+        function that added the bytes in vr3 and vr2 and returned the
+        result in vr2 as:</para>
+
+      <programlisting>
+(defppclapfunction vaddubs ((y vr3) (z vr2))
+  (vaddubs z y z)
+  (blr))
+      </programlisting>
+
+      <para>When vector registers that aren't incoming parameters are used
+        in a LAP function, WITH-ALTIVEC-REGISTERS takes care of maintaining VRSAVE
+        and of saving/restoring any non-volatile vector registers:</para>
+
+      <programlisting>
+(defppclapfunction load-array ((n arg_z))
+  (check-nargs 1)
+  (with-altivec-registers (vr1 vr2 vr3 vr27) ; Clobbers imm0
+    (li imm0 arch::misc-data-offset)
+    (lvx vr1 arg_z imm0)                ; load MSQ
+    (lvsl vr27 arg_z imm0)              ; set the permute vector
+    (addi imm0 imm0 16)                 ; address of LSQ
+    (lvx vr2 arg_z imm0)                ; load LSQ
+    (vperm vr3 vr1 vr2 vr27)           ; aligned result appears in VR3
+    (dbg t))                         ; Look at result in some debugger
+  (blr))
+      </programlisting>
+
+      <para>AltiVec registers are not preserved by CATCH and UNWIND-PROTECT.
+        Since AltiVec is only accessible from LAP in &CCL; and since LAP
+        functions rarely use high-level control structures, this should rarely be
+        a problem in practice.</para>
+      <para>LAP functions that use non-volatile vector registers and
+        that call (Lisp ?) code which may use CATCH or UNWIND-PROTECT
+        should save those vector registers before such a call and
+        restore them on return. This is one of the intended uses of
+        the WITH-VECTOR-BUFFER lap macro.</para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="Development-Mode-Dictionary">
+    <title>Development-Mode Dictionary</title>
+
+    <refentry id="v_warn-if-redefine-kernel">
+	  <indexterm zone="v_warn-if-redefine-kernel">
+	    <primary>*warn-if-redefine-kernel</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>*WARN-IF-REDEFINE-KERNEL*</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Variable</refclass>
+	  </refnamediv>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>When true, attempts to redefine (via DEFUN or DEFMETHOD)
+	      functions and methods that are marked as being
+	      &#34;predefined&#34; signal continuable errors.</para>
+
+	    <para>Note that these are CERRORs, not warnings, and that
+	      no lisp functions or methods have been defined in the kernel
+	      in MCL or &CCL; since 1987 or so.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_set-development-environment">
+	  <indexterm zone="f_set-development-environment">
+	    <primary>set-development-environment</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>SET-DEVELOPMENT-ENVIRONMENT</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>set-development-environment</function>
+	      &optional;
+	      unmark-builtin-functions</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Arranges that the outermost special bindings of *PACKAGE*
+	      and *WARN-IF-REDEFINE-KERNEL* restore values of the &#34;CCL&#34;
+	      package and NIL to these variables, respectively. If the optional
+	      argument is true, marks all globally defined functions and methods
+	      as being &#34;not predefined&#34; (this is a fairly expensive
+	      operation.)</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_set-user-environment">
+	  <indexterm zone="f_set-user-environment">
+	    <primary>set-user-environment</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>SET-USER-ENVIRONMENT</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>set-user-environment</function>
+	      &optional; mark-builtin-functions</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Arranges that the outermost special bindings of *PACKAGE*
+	      and *WARN-IF-REDEFINE-KERNEL* restore values of the
+	      &#34;CL-USER&#34; package and T to these variables, respectively.
+	      If the optional argument is true, marks all globally defined
+	      functions and methods as being &#34;predefined&#34; (this is a
+	      fairly expensive operation.)</para>
+	  </refsect1>
+    </refentry>
+    <refentry id="v_altivec-available">
+	  <indexterm zone="v_altivec-available">
+	    <primary>*altivec-available*</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>*ALTIVEC-AVAILABLE*</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Variable</refclass>
+	  </refnamediv>
+
+	  <refsect1>
+	    <title>Description</title>
+	    <para>This variable is initialized each time an &CCL; session
+	      starts based on information provided by the lisp kernel. Its value
+	      is true if AltiVec is present and false otherwise. This variable
+	      shouldn't be set by user code.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_altivec-available-p">
+	  <indexterm zone="f_altivec-available-p">
+	    <primary>altivec-available-p</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>ALTIVEC-AVAILABLE-P</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+	  
+	  <refsynopsisdiv>
+	    <synopsis><function>altivec-available-p</function></synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Returns non-NIL if AltiVec is available.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="v_altivec-lapmacros-maintain-vrsave-p">
+	  <indexterm zone="v_altivec-lapmacros-maintain-vrsave-p">
+	    <primary>*altivec-lapmacros-maintain-vrsave-p*</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>*ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P*</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Variable</refclass>
+	  </refnamediv>
+	  
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Intended to control the expansion of certain lap macros.
+	      Initialized to NIL on LinuxPPC; initialized to T on platforms
+	      (such as MacOS X/Darwin) that require that the VRSAVE SPR contain
+	      a bitmask of active vector registers at all times.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="lapm_with-altivec-registers">
+	  <indexterm zone="lapm_with-altivec-registers">
+	    <primary>with-altivec-registers</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WITH-ALTIVEC-REGISTERS</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>LAP Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>with-altivec-registers</function>
+	      reglist &body; body</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>reglist</term>
+
+	        <listitem>
+		      <para>A list of vector register names (vr0 .. vr31).</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>body</term>
+
+	        <listitem>
+		      <para>A sequence of PPC LAP instructions.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Specifies the set of AltiVec registers used in body. If
+	      *altivec-lapmacros-maintain-vrsave-p* is true when the macro is
+	      expanded, generates code to save the VRSAVE SPR and updates VRSAVE
+	      to include a bitmask generated from the specified register list.
+	      Generates code which saves any non-volatile vector registers which
+	      appear in the register list, executes body, and restores the saved
+	      non-volatile vector registers (and, if
+	      *altivec-lapmacros-maintain-vrsave-p* is true, restores VRSAVE as
+	      well. Uses the IMM0 register (r3) as a temporary.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="lapm_with-vector-buffer">
+	  <indexterm zone="lapm_with-vector-buffer">
+	    <primary>with-vector-buffer</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WITH-VECTOR-BUFFER</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>LAP Macro</refclass>
+	  </refnamediv>
+	  
+	  <refsynopsisdiv>
+	    <synopsis>with-vector-buffer base n &body; body</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>base</term>
+
+	        <listitem>
+		      <para>Any available general-purpose register.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>n</term>
+
+	        <listitem>
+		      <para>An integer between 1 and 254, inclusive. (Should
+		        typically be much, much closer to 1.) Specifies the size of
+		        the buffer, in 16-byte units.</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>body</term>
+
+	        <listitem>
+		      <para>A sequence of PPC LAP instructions.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+	    <para>Generates code which allocates a 16-byte aligned buffer
+	      large enough to contain N vector registers; the GPR base points to
+	      the lowest address of this buffer. After processing body, the
+	      buffer will be deallocated. The body should preserve the value of
+	      base as long as it needs to reference the buffer. It's
+	      intended that base be used as a base register in stvx and lvx
+	      instructions within the body.</para>
+	  </refsect1>
+    </refentry>
+  </sect1>
+</chapter>
Index: /branches/new-random/doc/src/mop.xml
===================================================================
--- /branches/new-random/doc/src/mop.xml	(revision 13309)
+++ /branches/new-random/doc/src/mop.xml	(revision 13309)
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "Clozure CL">
+]>
+
+  <chapter id="Writing-Portable-Extensions-to-the-Object-System-using-the-MetaObject-Protocol">
+    <title>Writing Portable Extensions to the Object System  using the MetaObject Protocol</title>
+
+    <sect1 id="MOP-Overview">
+      <title>Overview</title>
+      <para>&CCL; supports a fairly large subset of the
+      semi-standard MetaObject Protocol (MOP) for CLOS, as defined in
+      chapters 5 and 6 of "The Art Of The Metaobject Protocol",
+      (Kiczales et al, MIT Press 1991, ISBN 0-262-61074-4); this
+      specification is also available online at
+      http://www.alu.org/mop/index.html.</para>
+    </sect1>
+
+    <sect1 id="MOP-Implementation-status">
+      <title>Implementation status</title>
+      <para>The keyword :openmcl-partial-mop is on *FEATURES* to
+      indicate the presence of this functionality.</para>
+
+      <para>All of the symbols defined in the MOP specification
+      (whether implemented or not) are exported from the "CCL" package
+      and from an "OPENMCL-MOP" package.</para>
+      <para><informaltable><tgroup cols="2" colsep="1"
+      rowsep="1"><colspec align="center" colname="col0" /><colspec
+      align="center" colname="col1" /><thead><row><entry
+      align="center" valign="top"><para>construct</para></entry><entry
+      align="center"
+      valign="top"><para>status</para></entry></row></thead><tbody><row><entry
+      align="center"
+      valign="top"><para>accessor-method-slot-definition</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>add-dependent</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>add-direct-method</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>add-direct-subclass</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>add-method</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-default-initargs</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-direct-default-initargs</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-direct-slots</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-direct-subclasses</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-direct-superclasses</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-finalized-p</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-prototype</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>class-slots</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-applicable-methods</para></entry><entry
+      align="center"
+      valign="top"><para>-</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-applicable-methods-using-classes</para></entry><entry
+      align="center"
+      valign="top"><para>-</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-class-precedence-list</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-direct-initargs</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-discriminating-function</para></entry><entry
+      align="center"
+      valign="top"><para>-</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-effective-method</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-effective-slot-definition</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>compute-slots</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>direct-slot-definition-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>effective-slot-definition-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>ensure-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>ensure-class-using-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>ensure-generic-function-using-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>eql-specializer-object</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>extract-lambda-list</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>extract-specializer-names</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>finalize-inheritance</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>find-method-combination</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>funcallable-standard-instance-access</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>generic-function-argument-precedence-order</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>generic-function-declarations</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>generic-function-lambda-list</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>generic-function-method-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>generic-function-method-combination</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>generic-function-methods</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>generic-function-name</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>intern-eql-specializer</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>make-method-lambda</para></entry><entry
+      align="center"
+      valign="top"><para>-</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>map-dependents</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>method-function</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>method-generic-function</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>method-lambda-list</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>method-qualifiers</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>method-specializers</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>reader-method-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>remove-dependent</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>remove-direct-method</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>remove-direct-subclass</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>remove-method</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>set-funcallable-instance-function</para></entry><entry
+      align="center"
+      valign="top"><para>-</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-boundp-using-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-allocation</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-initargs</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-initform</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-initfunction</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-location</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-name</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-readers</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-type</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-definition-writers</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-makunbound-using-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>slot-value-using-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>specializer-direct-generic-functions</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>specializer-direct-methods</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>standard-instance-access</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>update-dependent</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>validate-superclass</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row><row><entry
+      align="center"
+      valign="top"><para>writer-method-class</para></entry><entry
+      align="center"
+      valign="top"><para>+</para></entry></row></tbody></tgroup></informaltable></para>
+      
+      <para>Note that those generic functions whose status is "-" in
+      the table above deal with the internals of generic function
+      dispatch and method invocation (the "Generic Function Invocation
+      Protocol".) Method functions are implemented a bit differently
+      in &CCL; from what the MOP expects, and it's not yet clear if
+      or how this subprotocol can be well-supported.</para>
+      <para>Those constructs that are marked as "+" in the table above
+      are nominally implemented as the MOP document specifies
+      (deviations from the specification should be considered bugs;
+      please report them as such.) Note that some CLOS implementations
+      in widespread use (e.g., PCL) implement some things
+      (ENSURE-CLASS-USING-CLASS comes to mind) a bit differently from
+      what the MOP specifies.</para>
+    </sect1>
+
+    <sect1 id="Concurrency-issues">
+      <title>Concurrency issues</title>
+      <para>The entire CLOS class and generic function hierarchy is
+      effectively a (large, complicated) shared data structure; it's
+      not generally practical for a thread to request exclusive access
+      to all of CLOS, and the effects of volitional modification of
+      the CLOS hierarchy (via class redefinition, CHANGE-CLASS, etc) in
+      a multithreaded environment aren't always tractable.</para>
+      <para>Native threads exacerbate this problem (in that they
+      increase the opportunities for concurrent modification and
+      access.) The implementation should try to ensure that a thread's
+      view of any subset of the CLOS hierarchy is consistent (to the
+      extent that that's possible) and should try to ensure that
+      incidental modifications of the hierarchy (cache updates, etc.)
+      happen atomically; it's not generally possible for the
+      implementation to guarantee that a thread's view of things is
+      correct and current.</para>
+      <para>If you are loading code and defining classes in the most
+      usual way, which is to say, via the compiler, using only a
+      single thread, these issues are probably not going to affect you
+      much.</para>
+      <para>If, however, you are making finicky changes to the class
+      hierarchy while you're running multiple threads which manipulate
+      objects related to each other, more care is required.  Before
+      doing such a thing, you should know what you're doing and
+      already be aware of what precautions to take, without being
+      told.  That said, if you do it, you should seriously consider
+      what your application's critical data is, and use locks for
+      critical code sections.</para>
+    </sect1>
+  </chapter>
Index: /branches/new-random/doc/src/objc-bridge.xml
===================================================================
--- /branches/new-random/doc/src/objc-bridge.xml	(revision 13309)
+++ /branches/new-random/doc/src/objc-bridge.xml	(revision 13309)
@@ -0,0 +1,918 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+<chapter id="The-Objective-C-Bridge">
+  <title>The Objective-C Bridge</title>
+
+  <para>Mac OS X APIs use a language called Objective-C, which is
+    approximately C with some object-oriented extensions modeled on
+    Smalltalk.  The Objective-C bridge makes it possible to work with
+    Objective-C objects and classes from Lisp, and to define classes
+    in Lisp which can be used by Objective-C.</para>
+  <para>The ultimate purpose of the Objective-C and Cocoa bridges is
+    to make Cocoa (the standard user-interface framework on Mac OS X)
+    as easy as possible to use from &CCL;, in order to support the
+    development of GUI applications and IDEs on Mac OS X (and on any
+    platform that supports Objective-C, such as GNUStep).  The
+    eventual goal, which is much closer than it used to be, is
+    complete integration of Cocoa into CLOS.</para>
+  <para>The current release provides Lisp-like syntax and naming
+    conventions for the basic Objective-C operations, with automatic type
+    processing and messages checked for validity at compile-time.  It
+    also provides some convenience facilities for working with
+    Cocoa.</para>
+
+  <!-- ============================================================ -->
+  <sect1 id="Objective-C-Changes-1.2">
+    <title>Changes in 1.2</title>
+
+    <para>Version 1.2 of &CCL; exports most of the useful symbols
+    described in this chapter; in previous releases, most of them were
+    private in the <literal>CCL</literal> package.</para>
+
+    <para>There are several new reader macros that make it much more
+    convenient than before to refer to several classes of symbols used
+    with the Objective-C bridge. For a full description of these
+    reader-macros, see
+    the <link linkend="anchor_Foreign-Function-Interface-Dictionary">Foreign-Function-Interface
+    Dictionary</link>, especially the entries at the beginning,
+    describing reader macros.</para>
+
+    <para>As in previous releases, 32-bit versions of &CCL; use 32-bit
+    floats and integers in data structures that describe geometry,
+    font sizes and metrics, and so on. 64-bit versions of &CCL; use
+    64-bit values where appropriate.</para>
+
+    <para>The Objective-C bridge defines the
+      type <literal>NS:CGFLOAT</literal> as the Lisp type of the preferred
+      floating-point type on the current platform, and defines the
+      constant <literal>NS:+CGFLOAT+</literal>.  On DarwinPPC32, the foreign
+      types <literal>:cgfloat</literal>, <literal>:&lt;NSUI&gt;nteger</literal>,
+      and
+      <literal>:&lt;NSI&gt;nteger</literal> are defined by the Objective-C
+      bridge (as 32-bit float, 32-bit unsigned integer, and 32-bit
+      signed integer, respectively); these types are defined as 64-bit
+      variants in the 64-bit interfaces.</para>
+
+    <para>Every Objective-C class is now properly named, either with a
+      name exported from the <literal>NS</literal> package (in the case of a
+      predefined class declared in the interface files) or with the
+      name provided in the <literal>DEFCLASS</literal> form (with <literal>:METACLASS</literal>
+      <literal>NS:+NS-OBJECT</literal>) which defines the class from Lisp.
+      The class's Lisp name is now proclaimed to be a "static"
+      variable (as if by <literal>DEFSTATIC</literal>, as described in the
+      <link linkend="Static_Variables">"Static Variables"
+      section</link>) and given the class object as its value.  In
+      other words:</para>
+
+    <programlisting>
+(send (find-class 'ns:ns-application) 'shared-application)
+    </programlisting>
+
+  <para>and</para>
+
+    <programlisting>
+(send ns:ns-application 'shared-application)
+    </programlisting>
+
+  <para>are equivalent.  (Since it's not legal to bind a "static"
+  variable, it may be necessary to rename some things so that
+  unrelated variables whose names coincidentally conflict with
+  Objective-C class names don't do so.)</para>
+
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Using-Objective-C-Classes">
+    <title>Using Objective-C Classes</title>
+
+    <para>The class of most standard CLOS classes is named
+      STANDARD-CLASS. In the Objective-C object model, each class is
+      an instance of a (usually unique) metaclass, which is itself an
+      instance of a "base" metaclass (often the metaclass of the class
+      named "NSObject".) So, the Objective-C class named "NSWindow"
+      and the Objective-C class "NSArray" are (sole) instances of
+      their distinct metaclasses whose names are also "NSWindow" and
+      "NSArray", respectively. (In the Objective-C world, it's much
+      more common and useful to specialize class behavior such as
+      instance allocation.)</para>
+    <para>When &CCL; first loads foreign libraries containing
+      Objective-C classes, it identifies the classes they contain. The
+      foreign class name, such as "NSWindow", is mapped to an external
+      symbol in the "NS" package via the bridge's translation rules,
+      such as NS:NS-WINDOW.  A similar transformation happens to the
+      metaclass name, with a "+" prepended, yielding something like
+      NS:+NS-WINDOW.</para>
+    <para>These classes are integrated into CLOS such that the
+      metaclass is an instance of the class OBJC:OBJC-METACLASS and
+      the class
+      is an instance of the metaclass. SLOT-DESCRIPTION metaobjects are
+      created for each instance variable, and the class and metaclass go
+      through something very similar to the "standard" CLOS class
+      initialization protocol (with a difference being that these classes
+      have already been allocated.)</para>
+    <para>Performing all this initialization, which is done when you
+      (require "COCOA"), currently takes several
+      seconds; it could conceivably be sped up some, but it's never likely
+      to be fast.</para>
+    <para>When the process is complete, CLOS is aware of several hundred
+      new Objective-C classes and their metaclasses. &CCL;'s runtime system can
+      reliably recognize MACPTRs to Objective-C classes as being CLASS objects, and
+      can (fairly reliably but heuristically) recognize instances of those
+      classes (though there are complicating factors here; see below.)
+      SLOT-VALUE can be used to access (and, with care, set) instance
+      variables in Objective-C instances. To see this, do:</para>
+    <programlisting>
+      ? (require "COCOA")
+    </programlisting>
+    <para>and, after waiting a bit longer for a Cocoa listener window to
+      appear, activate that Cocoa listener and do:</para>
+    <programlisting>? (describe (ccl::send ccl::*NSApp* 'key-window))
+    </programlisting>
+    <para>This sends a message asking for the key window, which is the window
+      that has the input focus (often the frontmost), and then describes
+      it. As we can see, NS:NS-WINDOWs have lots of interesting slots.</para>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Instantiating-Objective-C-Objects">
+    <title>Instantiating Objective-C Objects</title>
+    <para>Making an instance of an Objective-C class (whether the class in
+      question is predefined or defined by the application) involves
+      calling MAKE-INSTANCE with the class and a set of initargs as
+      arguments.  As with STANDARD-CLASS, making an instance involves
+      initializing (with INITIALIZE-INSTANCE) an object allocated with
+      ALLOCATE-INSTANCE.</para>
+    <para>For example, you can create an ns:ns-number like this:</para>
+    <programlisting>
+      ? (make-instance 'ns:ns-number :init-with-int 42)
+      #&lt;NS-CF-NUMBER 42 (#x85962210)>
+    </programlisting>
+    <para>It's worth looking at how this would be done if you were
+      writing in Objective C:</para>
+    <programlisting>
+      [[NSNumber alloc] initWithInt: 42]
+    </programlisting>
+    <para>Allocating an instance of an Objective-C class involves sending the
+      class an "alloc" message, and then using those initargs that
+      <emphasis>don't</emphasis> correspond to slot initargs as the
+      "init" message to be sent to the newly-allocated instance.  So, the
+      example above could have been done more verbosely as:</para>
+    <programlisting>
+      ? (defvar *n* (ccl::send (find-class 'ns:ns-number) 'alloc))
+      *N*
+
+      ? (setq *n* (ccl::send *n* :init-with-int 42))
+      #&lt;NS-CF-NUMBER 42 (#x16D340)>
+    </programlisting>
+    <para>That setq is important; this is a case where init
+      decides to replace the object and return the new one, instead
+      of modifying the existing one.
+      In fact, if you leave out the setq and
+      then try to view the value of *N*, &CCL; will freeze.  There's
+      little reason to ever do it this way; this is just to show
+      what's going on.</para>
+    <para>You've seen that an Objective-C initialization method doesn't have to
+      return the same object it was passed.  In fact, it doesn't have
+      to return any object at all; in this case, the initialization fails
+      and make-instance returns nil.</para>
+    <para>In some special cases, such as loading an ns:ns-window-controller
+      from a .nib file, it may be necessary for you to pass the
+      instance itself as one of the parameters to the initialization
+      method.  It goes like this:</para>
+    <programlisting>
+      ? (defvar *controller*
+      (make-instance 'ns:ns-window-controller))
+      *CONTROLLER*
+
+      ? (setq *controller*
+      (ccl::send *controller*
+      :init-with-window-nib-name #@"DataWindow"
+      :owner *controller*))
+      #&lt;NS-WINDOW-CONTROLLER &lt;NSWindowController: 0x1fb520> (#x1FB520)>
+    </programlisting>
+    <para>This example calls (make-instance) with no initargs.  When you
+      do this, the object is only allocated, and not initialized.  It
+      then sends the "init" message to do the initialization by hand.</para>
+
+    <para>There is an alternative API for instantiating Objective-C
+      classes. You can
+      call <literal>OBJC:MAKE-OBJC-INSTANCE</literal>, passing it the
+      name of the Objective-C class as a string. In previous
+      releases, <literal>OBJC:MAKE-OBJC-INSTANCE</literal> could be
+      more efficient than <literal>OBJC:MAKE-INSTANCE</literal> in
+      cases where the class did not define any Lisp slots; this is no
+      longer the case. You can now
+      regard <literal>OBJC:MAKE-OBJC-INSTANCE</literal> as completely
+      equivalent to <literal>OBJC:MAKE-INSTANCE</literal>, except that
+      you can pass a string for the classname, which may be convenient
+      in the case that the classname is in some way unusual.</para>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Calling-Objective-C-Methods">
+    <title>Calling Objective-C Methods</title>
+    <para>In Objective-C, methods are called "messages", and there's
+      a special syntax to send a message to an object:</para>
+    <programlisting>
+      [w alphaValue]
+      [w setAlphaValue: 0.5]
+      [v mouse: p inRect: r]
+    </programlisting>
+    <para>The first line sends the method "alphaValue" to the object
+      <literal>w</literal>, with no parameters.  The second line sends
+      the method "setAlphaValue", with the parameter 0.5.  The third
+      line sends the method "mouse:inRect:" - yes, all one long word -
+      with the parameters <literal>p</literal> and
+      <literal>r</literal>.</para>
+    <para>In Lisp, these same three lines are:</para>
+    <programlisting>
+      (send w 'alpha-value)
+      (send w :set-alpha-value 0.5)
+      (send v :mouse p :in-rect r)
+    </programlisting>
+    <para>Notice that when a method has no parameters, its name is an ordinary
+      symbol (it doesn't matter what package the symbol is in, as
+      only its name is checked).  When a method has parameters,
+      each part of its name is a keyword, and the keywords alternate
+      with the values.</para>
+    <para>These two lines break those rules, and both  will
+      result in error messages:</para>
+    <programlisting>
+      (send w :alpha-value)
+      (send w 'set-alpha-value 0.5)
+    </programlisting>
+    <para>Instead of (send), you can also invoke (send-super), with the
+      same interface.  It has roughly the same purpose as CLOS's
+      (call-next-method); when you use (send-super), the message is
+      handled by the superclass.  This can be used to get at the
+      original implementation of a method when it is shadowed by a
+      method in your subclass.</para>
+
+    <sect2 id="Type-Coercion-for-ObjC-Method-Calls">
+	  <title>Type Coercion for Objective-C Method Calls</title>
+      <para>&CCL;'s FFI handles many common conversions between
+        Lisp and foreign data, such as unboxing floating-point args
+        and boxing floating-point results.  The bridge adds a few more
+        automatic conversions:</para>
+      <para>NIL is equivalent to (%NULL-PTR) for any message
+        argument that requires a pointer.</para>
+      <para>T/NIL are equivalent to #$YES/#$NO for any boolean argument.</para>
+      <para>A #$YES/#$NO returned by any method that returns BOOL
+        will be automatically converted to T/NIL.</para>
+    </sect2>
+
+    <sect2 id="Methods-which-Return-Structures">
+	  <title>Methods which Return Structures</title>
+      <para>Some Cocoa methods return small structures, such as
+        those used to represent points, rects, sizes and ranges. When
+        writing in Objective C, the compiler hides the implementation
+        details.  Unfortunately, in Lisp we must be slightly more
+        aware of them.</para>
+      <para>Methods which return structures are called in a special
+        way; the caller allocates space for the result, and passes a
+        pointer to it as an extra argument to the method.  This is
+        called a Structure Return, or STRET.  Don't look at me; I
+        don't name these things.</para>
+      <para>Here's a simple use of this in Objective C.  The first line
+	    sends the "bounds" message to v1, which returns a rectangle.
+	    The second line sends the "setBounds" message to v2, passing
+	    that same rectangle as a parameter.</para>
+      <programlisting>
+        NSRect r = [v1 bounds];
+        [v2 setBounds r];
+	  </programlisting>
+      <para>In Lisp, we must explicitly allocate the memory, which
+        is done most easily and safely with <xref linkend="m_rlet"/>.
+        We do it like this:</para>
+      <programlisting>
+(rlet ((r :&lt;NSR&gt;ect))
+          (send/stret r v1 'bounds)
+          (send v2 :set-bounds r))
+      </programlisting>
+      <para>The rlet allocates the storage (but doesn't initialize
+        it), and makes sure that it will be deallocated when we're
+        done.  It binds the variable r to refer to it.  The call to
+        <literal>send/stret</literal> is just like an ordinary call to
+        <literal>send</literal>, except that r is passed as an extra,
+        first parameter.  The third line, which calls
+        <literal>send</literal>, does not need to do anything special,
+        because there's nothing complicated about passing a structure
+        as a parameter.</para>
+	  <para>In order to make STRETs easier to use, the bridge
+	    provides two conveniences.</para>
+      <para>First, you can use the macros <literal>slet</literal>
+        and <literal>slet*</literal> to allocate and initialize local
+        variables to foreign structures in one step.  The example
+        above could have been written more tersely as:</para>
+      <programlisting>
+(slet ((r (send v1 'bounds)))
+      (send v2 :set-bounds r))
+	  </programlisting>
+      <para>Second, when one call to <literal>send</literal> is made
+        inside another, the inner one has an implicit
+        <literal>slet</literal> around it.  So, one could in fact
+        just write:</para>
+      <programlisting>
+(send v1 :set-bounds (send v2 'bounds))
+      </programlisting>
+      <para>There are also several pseudo-functions provided for convenience
+        by the Objective-C compiler, to make objects of specific types. The
+        following are currently supported by the bridge: NS-MAKE-POINT,
+        NS-MAKE-RANGE, NS-MAKE-RECT, and NS-MAKE-SIZE.</para>
+      <para>These pseudo-functions can be used within an SLET initform:</para>
+      <programlisting>
+(slet ((p (ns-make-point 100.0 200.0)))
+      (send w :set-frame-origin p))
+      </programlisting>
+      <para>Or within a call to <literal>send</literal>:</para>
+      <programlisting>
+(send w :set-origin (ns-make-point 100.0 200.0))
+      </programlisting>
+      <para>However, since these aren't real functions, a call like the
+        following won't work:</para>
+      <programlisting>
+(setq p (ns-make-point 100.0 200.0))
+      </programlisting>
+      <para>To extract fields from these objects, there are also some
+        convenience macros: NS-MAX-RANGE, NS-MIN-X,
+        NS-MIN-Y, NS-MAX-X, NS-MAX-Y, NS-MID-X, NS-MID-Y,
+        NS-HEIGHT, and NS-WIDTH.</para>
+      <para>Note that there is also a <literal>send-super/stret</literal>
+        for use within methods.  Like <literal>send-super</literal>,
+        it ignores any shadowing methods in a subclass, and calls the
+        version of a method which belongs to its superclass.</para>
+    </sect2>
+
+    <sect2 id="Variable-Arity-Messages">
+	  <title>Variable-Arity Messages</title>
+      <para>
+        There are a few messages in Cocoa which take variable numbers
+        of arguments. Perhaps the most common examples involve
+        formatted strings:</para>
+      <programlisting>
+[NSClass stringWithFormat: "%f %f" x y]
+      </programlisting>
+      <para>In Lisp, this would be written:</para>
+      <programlisting>
+(send (find-class 'ns:ns-string)
+      :string-with-format #@"%f %f"
+      (:double-float x :double-float y))
+      </programlisting>
+      <para>Note that it's necessary to specify the foreign types of the
+        variables (in this example, :double-float), because the
+        compiler has no general way of knowing these types.  (You
+        might think that it could parse the format string, but this
+        would only work for format strings which are not determined
+        at runtime.)</para>
+      <para>Because the Objective-C runtime system does not provide any information
+        on which messages are variable arity, they must be explicitly
+        declared. The standard variable arity messages in Cocoa are
+        predeclared by the bridge.  If you need to declare a new
+        variable arity message, use
+        (DEFINE-VARIABLE-ARITY-MESSAGE "myVariableArityMessage:").</para>
+    </sect2>
+
+    <sect2 id="Optimization">
+	  <title>Optimization</title>
+      <para>The bridge works fairly hard to optimize message sends,
+        when it has enough information to do so.  There are two cases
+        when it does.  In either, a message send should be nearly as
+        efficient as when writing in Objective C.</para>
+      <para>The first case is when both the message and the
+        receiver's class are known at compile-time. In general, the
+        only way the receiver's class is known is if you declare it,
+        which you can do with either a DECLARE or a THE form.  For
+        example:</para>
+      <programlisting>
+(send (the ns:ns-window w) 'center)
+	  </programlisting>
+      <para>Note that there is no way in Objective-C to name the class of a
+        class.  Thus the bridge provides a declaration, @METACLASS.
+        The type of an instance of "NSColor" is ns:ns-color.  The type
+        of the <emphasis>class</emphasis> "NSColor" is (@metaclass
+        ns:ns-color):</para>
+      <programlisting>
+(let ((c (find-class 'ns:ns-color)))
+  (declare ((ccl::@metaclass ns:ns-color) c))
+  (send c 'white-color))
+      </programlisting>
+      <para>The other case that allows optimization is when only
+        the message is known at compile-time, but its type signature
+        is unique. Of the more-than-6000 messages currently provided
+        by Cocoa, only about 50 of them have nonunique type
+        signatures.</para>
+      <para>An example of a message with a type signature that is
+        not unique is SET.  It returns VOID for NSColor, but ID for
+        NSSet.  In order to optimize sends of messages with nonunique
+        type signatures, the class of the receiver must be declared at
+        compile-time.</para>
+      <para>If the type signature is nonunique or the message is
+        unknown at compile-time, then a slower runtime call must be
+        used.</para>
+      <para>When the receiver's class is unknown, the bridge's
+        ability to optimize relies on a type-signature table which it
+        maintains.  When first loaded, the bridge initializes this
+        table by scanning every method of every Objective-C class.  When new
+        methods are defined later, the table must be updated.  This
+        happens automatically when you define methods in Lisp.  After
+        any other major change, such as loading an external framework,
+        you should rebuild the table:</para>
+      <programlisting>
+? (update-type-signatures)
+      </programlisting>
+      <para>Because <literal>send</literal> and its relatives
+        <literal>send-super</literal>, <literal>send/stret</literal>,
+        and <literal>send-super/stret</literal> are macros, they
+        cannot be <literal>funcall</literal>ed,
+        <literal>apply</literal>ed, or passed as arguments to
+        functions.</para>
+      <para>To work around this, there are function equivalents to
+        them: <literal>%send</literal>,
+        <literal>%send-super</literal>,
+        <literal>%send/stret</literal>, and
+        <literal>%send-super/stret</literal>.  However, these
+        functions should be used only when the macros will not do,
+        because they are unable to optimize.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Defining-Objective-C-Classes">
+    <title>Defining Objective-C Classes</title>
+    <para>You can define your own foreign classes, which can then be
+      passed to foreign functions; the methods which you implement in
+      Lisp will be made available to the foreign code as
+      callbacks.</para>
+    <para>You can also define subclasses of existing classes,
+      implementing your subclass in Lisp even though the parent class
+      was in Objective C.  One such subclass is CCL::NS-LISP-STRING.
+      It is also particularly useful to make subclasses of
+      NS-WINDOW-CONTROLLER.</para>
+    <para>We can use the MOP to define new Objective-C classes, but
+      we have to do something a little funny: the :METACLASS that we'd
+      want to use in a DEFCLASS option generally doesn't exist until
+      we've created the class (recall that Objective-C classes have, for the
+      sake of argument, unique and private metaclasses.) We can sort
+      of sleaze our way around this by specifying a known Objective-C
+      metaclass object name as the value of the DEFCLASS :METACLASS
+      object; the metaclass of the root class NS:NS-OBJECT,
+      NS:+NS-OBJECT, makes a good choice. To make a subclass of
+      NS:NS-WINDOW (that, for simplicity's sake, doesn't define any
+      new slots), we could do:</para>
+    <programlisting>
+(defclass example-window (ns:ns-window)
+  ()
+  (:metaclass ns:+ns-object))
+    </programlisting>
+    <para>That'll create a new Objective-C class named EXAMPLE-WINDOW whose
+      metaclass is the class named +EXAMPLE-WINDOW. The class will be
+      an object of type OBJC:OBJC-CLASS, and the metaclass will be of
+      type OBJC:OBJC-METACLASS.  EXAMPLE-WINDOW will be a subclass of
+      NS-WINDOW.</para>
+
+    <sect2 id="Defining-classes-with-foreign-slots">
+	  <title>Defining classes with foreign slots</title>
+      <para>If a slot specification in an Objective-C class
+        definition contains the keyword :FOREIGN-TYPE, the slot will
+        be a "foreign slot" (i.e. an Objective-C instance variable). Be aware
+        that it is an error to redefine an Objective-C class so that its
+        foreign slots change in any way, and &CCL; doesn't do
+        anything consistent when you try to.</para>
+      <para>The value of the :FOREIGN-TYPE initarg should be a
+        foreign type specifier. For example, if we wanted (for some
+        reason) to define a subclass of NS:NS-WINDOW that kept track
+        of the number of key events it had received (and needed an
+        instance variable to keep that information in), we could
+        say:</para>
+      <programlisting>
+(defclass key-event-counting-window (ns:ns-window)
+  ((key-event-count :foreign-type :int
+                    :initform 0
+                    :accessor window-key-event-count))
+  (:metaclass ns:+ns-object))
+      </programlisting>
+      <para>Foreign slots are always SLOT-BOUNDP, and the initform
+        above is redundant: foreign slots are initialized to binary
+        0.</para>
+    </sect2>
+
+    <sect2 id="Defining-classes-with-Lisp-slots">
+	  <title>Defining classes with Lisp slots</title>
+      <para>A slot specification in an Objective-C class definition that
+        doesn't contain the :FOREIGN-TYPE initarg defines a
+        pretty-much normal lisp slot that'll happen to be associated
+        with "an instance of a foreign class". For instance:</para>
+      <programlisting>
+(defclass hemlock-buffer-string (ns:ns-string)
+  ((hemlock-buffer :type hi::hemlock-buffer
+                   :initform hi::%make-hemlock-buffer
+                   :accessor string-hemlock-buffer))
+  (:metaclass ns:+ns-object))
+	  </programlisting>
+      <para>As one might expect, this has memory-management
+        implications: we have to maintain an association between a
+        MACPTR and a set of lisp objects (its slots) as long as the
+        Objective-C instance exists, and we have to ensure that the Objective-C
+        instance exists (does not have its -dealloc method called)
+        while lisp is trying to think of it as a first-class object
+        that can't be "deallocated" while it's still possible to
+        reference it. Associating one or more lisp objects with a
+        foreign instance is something that's often very useful; if you
+        were to do this "by hand", you'd have to face many of the same
+        memory-management issues.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Defining-Objective-C-Methods">
+    <anchor id="anchor_Defining-Objective-C-Methods"/>
+    <title>Defining Objective-C Methods</title>
+    <para>In Objective-C, unlike in CLOS, every method belongs to some
+      particular class.  This is probably not a strange concept to
+      you, because C++ and Java do the same thing.  When you use Lisp
+      to define Objective-C methods, it is only possible to define methods
+      belonging to Objective-C classes which have been defined in
+      Lisp.</para>
+
+    <para>You can use either of two different macros to define methods
+      on Objective-C classes. <literal>define-objc-method</literal>
+      accepts a two-element list containing a message selector name
+      and a class name, and a body. <literal>objc:defmethod</literal>
+      superficially resembles the normal
+      CLOS <literal>defmethod</literal>, but creates methods on
+      Objective-C classes with the same restrictions as those created
+      by <literal>define-objc-method</literal>.</para>
+
+    <sect2>
+      <title>Using <literal>define-objc-method</literal></title>
+      <para>As described in the
+        section <link linkend="Calling-Objective-C-Methods">Calling
+        Objective-C Methods</link>, the names of Objective-C methods
+        are broken into pieces, each piece followed by a parameter.
+        The types of all parameters must be explicitly
+        declared.</para>
+      <para>Consider a few examples, meant to illustrate the use
+        of <literal>define-objc-method</literal>. Let us define a
+        class to use in them:</para>
+
+      <programlisting>
+(defclass data-window-controller (ns:ns-window-controller)
+  ((window :foreign-type :id :accessor window)
+   (data :initform nil :accessor data))
+  (:metaclass ns:+ns-object))
+      </programlisting>
+
+      <para>There's nothing special about this class.  It inherits from
+        <literal>ns:ns-window-controller</literal>.  It has two slots:
+        <literal>window</literal> is a foreign slot, stored in the Objective-C
+        world; and <literal>data</literal> is an ordinary slot, stored
+        in the Lisp world.</para>
+
+      <para>Here is an example of how to define a method which takes no
+        arguments:</para>
+
+      <programlisting>
+(define-objc-method ((:id get-window)
+                     data-window-controller)
+    (window self))
+      </programlisting>
+
+      <para>The return type of this method is the foreign type :id,
+        which is used for all Objective-C objects.  The name of the
+        method is
+        <literal>get-window</literal>.  The body of the method is the
+        single line <literal>(window self)</literal>.  The
+        variable <literal>self</literal> is bound, within the body, to
+        the instance that is receiving the message.  The call
+        to <literal>window</literal> uses the CLOS accessor to get the
+        value of the window field.</para>
+
+      <para>Here's an example that takes a parameter.  Notice that the
+        name of the method without a parameter was an ordinary symbol,
+        but with a parameter, it's a keyword:</para>
+
+      <programlisting>
+(define-objc-method ((:id :init-with-multiplier (:int multiplier))
+                     data-window-controller)
+  (setf (data self) (make-array 100))
+  (dotimes (i 100)
+    (setf (aref (data self) i)
+          (* i multiplier)))
+  self)
+      </programlisting>
+
+      <para>To Objective-C code that uses the class, the name of this
+        method is <literal>initWithMultiplier:</literal>.  The name of
+        the parameter is
+        <literal>multiplier</literal>, and its type
+        is <literal>:int</literal>.  The body of the method does some
+        meaningless things.  Then it returns
+        <literal>self</literal>, because this is an initialization
+        method.</para>
+
+      <para>Here's an example with more than one parameter:</para>
+
+      <programlisting>
+(define-objc-method ((:id :init-with-multiplier (:int multiplier)
+                          :and-addend (:int addend))
+                     data-window-controller)
+  (setf (data self) (make-array size))
+  (dotimes (i 100)
+    (setf (aref (data self) i)
+          (+ (* i multiplier)
+             addend)))
+  self)
+      </programlisting>
+
+      <para>To Objective-C, the name of this method is
+        <literal>initWithMultiplier:andAddend:</literal>.  Both
+        parameters are of type <literal>:int</literal>; the first is
+        named <literal>multiplier</literal>, and the second
+        is <literal>addend</literal>.  Again, the method returns
+        <literal>self</literal>.</para>
+
+      <para>Here is a method that does not return any value, a so-called
+        "void method".  Where our other methods
+        said <literal>:id</literal>, this one
+        says <literal>:void</literal> for the return type:</para>
+
+      <programlisting>
+(define-objc-method ((:void :take-action (:id sender))
+                     data-window-controller)
+  (declare (ignore sender))
+  (dotimes (i 100)
+    (setf (aref (data self) i)
+          (- (aref (data self) i)))))
+      </programlisting>
+
+      <para>This method would be called <literal>takeAction:</literal>
+        in Objective-C.  The convention for methods that are going to be
+        used as Cocoa actions is that they take one parameter, which is
+        the object responsible for triggering the action.  However, this
+        method doesn't actually need to use that parameter, so it
+        explicitly ignores it to avoid a compiler warning.  As promised,
+        the method doesn't return any value.</para>
+
+      <para>There is also an alternate syntax, illustrated here.  The
+        following two method definitions are equivalent:</para>
+
+      <programlisting>
+(define-objc-method ("applicationShouldTerminate:"
+                     "LispApplicationDelegate")
+    (:id sender :&lt;BOOL>)
+    (declare (ignore sender))
+    nil)
+  
+(define-objc-method ((:&lt;BOOL>
+                        :application-should-terminate sender)
+                       lisp-application-delegate)
+    (declare (ignore sender))
+    nil)
+      </programlisting>
+      </sect2>
+
+    <sect2>
+      <anchor id="anchor_Using-objc-defmethod"/>
+
+	  <title>Using <literal>objc:defmethod</literal></title>
+
+      <para>The macro <literal>OBJC:DEFMETHOD</literal> can be used to
+        define Objective-C methods.  It looks superficially like
+        <literal>CL:DEFMETHOD</literal> in some respects.</para>
+
+      <para>Its syntax is</para>
+
+      <programlisting>
+(OBC:DEFMETHOD name-and-result-type 
+               ((receiver-arg-and-class) &rest; other-args) 
+      &body; body)
+      </programlisting>
+
+      <para><literal>name-and-result-type</literal> is either an
+        Objective-C message name, for methods that return a value of
+        type <literal>:ID</literal>, or a list containing an
+        Objective-C message name and a foreign type specifier for
+        methods with a different foreign result type.</para>
+
+      <para><literal>receiver-arg-and-class</literal> is a two-element
+        list whose first element is a variable name and whose second
+        element is the Lisp name of an Objective-C class or metaclass.
+        The receiver variable name can be any bindable lisp variable
+        name, but <literal>SELF</literal> might be a reasonable
+        choice.  The receiver variable is declared to be "unsettable";
+        i.e., it is an error to try to change the value of the
+        receiver in the body of the method definition.</para>
+
+      <para><literal>other-args</literal> are either variable names
+            (denoting parameters of type <literal>:ID</literal>) or
+            2-element lists whose first element is a variable name and
+            whose second element is a foreign type specifier.</para>
+
+      <para>Consider this example:</para>
+
+      <programlisting>
+(objc:defmethod (#/characterAtIndex: :unichar)
+    ((self hemlock-buffer-string) (index :&lt;NSUI&gt;nteger))
+  ...)
+      </programlisting>
+
+      <para>The method <literal>characterAtIndex:</literal>, when
+        invoked on an object of
+        class <literal>HEMLOCK-BUFFER-STRING</literal> with an
+        additional argument of
+        type <literal>:&lt;NSU&gt;integer</literal> returns a value of
+        type
+        <literal>:unichar</literal>.</para>
+
+      <para>Arguments that wind up as some pointer type other
+        than <literal>:ID</literal> (e.g. pointers, records passed by
+        value) are represented as typed foreign pointers, so that the
+        higher-level, type-checking accessors can be used on arguments
+        of
+        type <literal>:ns-rect</literal>, <literal>:ns-point</literal>,
+        and so on.</para>
+
+      <para>Within the body of methods defined
+        via <literal>OBJC:DEFMETHOD</literal>, the local function
+        <literal>CL:CALL-NEXT-METHOD</literal> is defined.  It isn't
+        quite as general as <literal>CL:CALL-NEXT-METHOD</literal> is
+        when used in a CLOS method, but it has some of the same
+        semantics.  It accepts as many arguments as are present in the
+        containing method's <literal>other-args</literal> list and
+        invokes version of the containing method that would have been
+        invoked on instances of the receiver's class's superclass with
+        the receiver and other provided arguments.  (The idiom of
+        passing the current method's arguments to the next method is
+        common enough that the <literal>CALL-NEXT-METHOD</literal> in
+        <literal>OBJC:DEFMETHODs</literal> should probably do this if
+        it receives no arguments.)</para>
+
+      <para>A method defined via <literal>OBJC:DEFMETHOD</literal>
+        that returns a structure "by value" can do so by returning a
+        record created via <literal>MAKE-GCABLE-RECORD</literal>, by
+        returning the value returned
+        via <literal>CALL-NEXT-METHOD</literal>, or by other similar
+        means. Behind the scenes, there may be a pre-allocated
+        instance of the record type (used to support native
+        structure-return conventions), and any value returned by the
+        method body will be copied to this internal record instance.
+        Within the body of a method defined
+        with <literal>OBJC:DEFMETHOD</literal> that's declared to
+        return a structure type, the local macro
+        <literal>OBJC:RETURNING-FOREIGN-STRUCT</literal> can be used
+        to access the internal structure. For example:</para>
+
+       <programlisting>
+(objc:defmethod (#/reallyTinyRectangleAtPoint: :ns-rect) 
+  ((self really-tiny-view) (where :ns-point))
+  (objc:returning-foreign-struct (r)
+    (ns:init-ns-rect r (ns:ns-point-x where) (ns:ns-point-y where)
+                        single-float-epsilon single-float-epsilon)
+    r))
+       </programlisting>
+     
+       <para>If the <literal>OBJC:DEFMETHOD</literal> creates a new
+       method, then it displays a message to that effect. These
+       messages may be helpful in catching errors in the names of
+       method definitions. In addition, if
+       a <literal>OBJC:DEFMETHOD</literal> form redefines a method in
+       a way that changes its type signature, &CCL; signals a
+       continuable error.</para>
+    </sect2>
+
+    <sect2 id="Method-Redefinition-Constraints">
+	  <title>Method Redefinition Constraints</title>
+      <para>Objective C was not designed, as Lisp was, with runtime
+        redefinition in mind.  So, there are a few constraints about
+        how and when you can replace the definition of an Objective C
+        method.  Currently, if you break these rules, nothing will
+        collapse, but the behavior will be confusing; so
+        don't.</para>
+      <para>Objective C methods can be redefined at runtime, but
+        their signatures shouldn't change.  That is, the types of the
+        arguments and the return type have to stay the same.  The
+        reason for this is that changing the signature changes the
+        selector which is used to call the method.</para>
+      <para>When a method has already been defined in one class, and
+        you define it in a subclass, shadowing the original method,
+        they must both have the same type signature.  There is no such
+        constraint, though, if the two classes aren't related and the
+        methods just happen to have the same name.</para>
+    </sect2>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Loading-Objc-Frameworks">
+    <title>Loading Frameworks</title>
+
+    <para>On Mac OS X, a framework is a structured directory
+      containing one or more shared libraries along with metadata such
+      as C and Objective-C header files. In some cases, frameworks may
+      also contain additional items such as executables.</para>
+
+    <para>Loading a framework means opening the shared libraries and
+      processing any declarations so that &CCL; can subsequently call
+      its entry points and use its data structures. &CCL; provides the
+      function <literal>OBJC:LOAD-FRAMEWORK</literal> for this
+      purpose.</para>
+
+    <programlisting>
+(OBJC:LOAD-FRAMEWORK framework-name interface-dir)
+    </programlisting>
+
+    <para><literal>framework-name</literal> is a string that names the
+    framework (for example, "Foundation", or "Cocoa"),
+    and <literal>interface-dir</literal> is a keyword that names the
+    set of interface databases associated with the named framework
+    (for example, <literal>:foundation</literal>,
+    or <literal>:cocoa</literal>).</para>
+
+    <para>Assuming that interface databases for the named frameworks
+    exist on the standard search
+    path, <literal>OBJC:LOAD-FRAMEWORK</literal> finds and initializes
+    the framework bundle by searching OS X's standard framework search
+    paths. Loading the named framework may create new Objective-C
+    classes and methods, add foreign type descriptions and entry
+    points, and adjust &CCL;'s dispatch functions.</para>
+
+    <para>If interface databases don't exist for a framework you want
+    to use, you will need to create them. For more information about
+    creating interface databases,
+    see <link linkend="Creating-new-interface-directories">Creating
+    new interface directories</link>.</para>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="How-Objective-C-Names-are-Mapped-to-Lisp-Symbols">
+    <title>How Objective-C Names are Mapped to Lisp Symbols</title>
+    <para>There is a standard set of naming conventions for Cocoa
+      classes, messages, etc.  As long as they are followed, the
+      bridge is fairly good at automatically translating between Objective-C
+      and Lisp names.</para>
+    <para>For example, "NSOpenGLView" becomes ns:ns-opengl-view;
+      "NSURLHandleClient" becomes ns:ns-url-handle-client; and
+      "nextEventMatchingMask:untilDate:inMode:dequeue:" becomes
+      (:next-event-matching-mask :until-date :in-mode :dequeue).  What
+      a mouthful.</para>
+    <para>To see how a given Objective-C or Lisp name will be translated by
+      the bridge, you can use the following functions:</para>
+	<simplelist type="vert">
+	  <member>(ccl::objc-to-lisp-classname string)</member>
+	  <member>(ccl::lisp-to-objc-classname symbol)</member>
+	  <member>(ccl::objc-to-lisp-message string)</member>
+	  <member>(ccl::lisp-to-objc-message string)</member>
+	  <member>(ccl::objc-to-lisp-init string)</member>
+	  <member>(ccl::lisp-to-objc-init keyword-list)</member>
+	</simplelist>
+
+    <para>Of course, there will always be exceptions to any naming
+      convention.  Please tell us on the mailing lists if you come
+      across any name translation problems that seem to be bugs.
+      Otherwise, the bridge provides two ways of dealing with
+      exceptions:</para>
+    <para>First, you can pass a string as the class name of
+      MAKE-OBJC-INSTANCE and as the message to SEND.  These strings
+      will be directly interpreted as Objective-C names, with no
+      translation. This is useful for a one-time exception.  For
+      example:</para>
+    <programlisting>
+(ccl::make-objc-instance "WiErDclass")
+(ccl::send o "WiErDmEsSaGe:WithARG:" x y)
+    </programlisting>
+    <para>Alternatively, you can define a special translation rule
+      for your exception.  This is useful for an exceptional name that
+      you need to use throughout your code.  Some examples:</para>
+    <programlisting>
+(ccl::define-classname-translation "WiErDclass" wierd-class)
+(ccl::define-message-translation "WiErDmEsSaGe:WithARG:" (:weird-message :with-arg))
+(ccl::define-init-translation "WiErDiNiT:WITHOPTION:" (:weird-init :option))
+    </programlisting>
+    <para>The normal rule in Objective-C names is that each word begins with a
+      capital letter (except possibly the first).  Using this rule
+      literally, "NSWindow" would be translated as N-S-WINDOW, which
+      seems wrong.  "NS" is a special word in Objective-C that should not be
+      broken at each capital letter. Likewise "URL", "PDF", "OpenGL",
+      etc. Most common special words used in Cocoa are already defined
+      in the bridge, but you can define new ones as follows:</para>
+    <programlisting>
+(ccl::define-special-objc-word "QuickDraw")
+    </programlisting>
+    <para>Note that message keywords in a SEND such as (SEND V
+      :MOUSE P :IN-RECT R) may look like the keyword arguments in a
+      Lisp function call, but they really aren't. All keywords must be
+      present and the order is significant. Neither (:IN-RECT :MOUSE)
+      nor (:MOUSE) translate to "mouse:inRect:"</para>
+    <para>Also, as a special exception, an "init" prefix is optional
+      in the initializer keywords, so (MAKE-OBJC-INSTANCE 'NS-NUMBER
+      :INIT-WITH-FLOAT 2.7) can also be expressed as
+      (MAKE-OBJC-INSTANCE 'NS-NUMBER :WITH-FLOAT 2.7)</para>
+  </sect1>
+</chapter>
Index: /branches/new-random/doc/src/platform-notes.xml
===================================================================
--- /branches/new-random/doc/src/platform-notes.xml	(revision 13309)
+++ /branches/new-random/doc/src/platform-notes.xml	(revision 13309)
@@ -0,0 +1,1348 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="Platform-specific-notes">
+  <title>Platform-specific notes</title>
+  
+
+  <sect1 id="Platform-specific-overview">
+    <title>Overview</title>
+    <para> The documentation and whatever experience you may have in
+      using &CCL; under Linux should also apply to using it under
+      Darwin/MacOS X and FreeBSD. There are some differences between
+      the platforms, and these differences are sometimes exposed in
+      the implementation.</para>
+
+    <sect2 id="differences-between-32-bit-and-64-bit-implementations">
+	  <title>Differences Between 32-bit and 64-bit implementations</title>
+
+	  <para>Fixnums on 32-bit systems are 30 bits long, and are in the
+	  range -536870912 through 536870911.  Fixnums on 64-bit
+	  systems are 61 bits long, and are in the range
+	  -1152921504606846976 through 1152921504606846975. (see <xref
+	  linkend="Tagging-scheme"/>)</para>
+
+	  <para>Since we have much larger fixnums on 64-bit systems,
+	    <varname>INTERNAL-TIME-UNITS-PER-SECOND</varname> is 1000000
+	    on 64-bit systems but remains 1000 on 32-bit systems.  This
+	    enables much finer grained timing on 64-bit systems.</para>
+    </sect2>
+
+    <sect2 id="File-system-case">
+	  <title>File-system case</title>
+
+	  <para>Darwin and MacOS X use HFS+ file systems by default;
+	    HFS+ file systems are usually case-insensitive. Most of
+	    &CCL;'s filesystem and pathname code assumes that the
+	    underlying filesystem is case-sensitive; this assumption
+	    extends to functions like EQUAL, which assumes that #p"FOO"
+	    and #p"foo" denote different, un-EQUAL filenames. Since
+	    Darwin/MacOS X can also use UFS and NFS filesystems, the
+	    opposite assumption would be no more correct than the one
+	    that's currently made.</para>
+      <para>Whatever the best solution to this problem turns out to
+        be, there are some practical considerations. Doing:</para>
+      <programlisting>
+? (save-application "DPPCCL")
+	  </programlisting>
+      <para>on 32-bit DarwinPPC has the unfortunate side-effect of
+        trying to overwrite the Darwin &CCL; kernel, "dppccl", on a
+        case-insensitive filesystem.</para>
+      <para>To work around this, the Darwin &CCL; kernel expects
+        the default heap image file name to be the kernel's own
+        filename with the string ".image" appended, so the idiom would
+        be:</para>
+      <programlisting>
+? (save-application "dppccl.image")
+	  </programlisting>
+    </sect2>
+
+    <sect2 id="Line-Termination-Characters">
+	  <title>Line Termination Characters</title>
+      <para>MacOSX effectively supports two distinct line-termination
+	    conventions. Programs in its Darwin substrate follow the Unix
+	    convention of recognizing #\LineFeed as a line terminator; traditional
+	    MacOS programs use #\Return for this purpose.  Many modern
+	    GUI programs try to support several different line-termination
+	    conventions (on the theory that the user shouldn't be too concerned
+	    about what conventions are used an that it probably doesn't matter.
+	    Sometimes this is true, other times ... not so much.
+	  </para>
+      <para>&CCL; follows the Unix convention on both Darwin and
+        LinuxPPC, but offers some support for reading and writing
+        files that use other conventions (including traditional MacOS
+        conventions) as well.</para> 
+	  <para>This support (and anything like it) is by nature
+	    heuristic: it can successfully hide the distinction between
+	    newline conventions much of the time, but could mistakenly
+	    change the meaning of otherwise correct programs (typically
+	    when files contain both #\Return and #\Linefeed characters or
+	    when files contain mixtures of text and binary data.) Because
+	    of this concern, the default settings of some of the variables
+	    that control newline translation and interpretation are
+	    somewhat conservative.</para>
+	  <para>Although the issue of multiple newline conventions
+	    primarily affects MacOSX users, the functionality described
+	    here is available under LinuxPPC as well (and may occasionally
+	    be useful there.)</para> <para>None of this addresses issues
+	    related to the third newline convention ("CRLF") in widespread
+	    use (since that convention isn't native to any platform on
+	    which &CCL; currently runs). If &CCL; is ever ported to
+	    such a platform, that issue might be revisited.</para>
+	  <para>Note that some MacOS programs (including some versions
+	    of commercial MCL) may use HFS file type information to
+	    recognize TEXT and other file types and so may fail to
+	    recognize files created with &CCL; or other Darwin
+	    applications (regardless of line termination issues.)</para>
+	  <para>Unless otherwise noted, the symbols mentioned in this
+	    documentation are exported from the CCL package.</para>
+    </sect2>
+
+    <sect2 id="Single-precision-trig---transcendental-functions">
+	  <title>Single-precision trig &amp; transcendental functions</title>
+      <para>
+	    Despite what Darwin's man pages say, early versions of its math library
+	    (up to and including at least OSX 10.2 (Jaguar) don't implement
+	    single-precision variants of the transcendental and trig functions
+	    (#_sinf, #_atanf, etc.) &CCL; worked around this by coercing
+	    single-precision args to double-precision, calling the
+	    double-precision version of the math library function, and coercing
+	    the result back to a SINGLE-FLOAT. These steps can introduce rounding
+	    errors (and potentially overflow conditions) that might not be present
+	    or as severe if true 32-bit variants were available.</para>
+    </sect2>
+
+    <sect2 id="Shared-libraries">
+	  <title>Shared libraries</title>
+      <para>Darwin/MacOS X distinguishes between "shared libraries"
+        and "bundles" or "extensions"; Linux and FreeBSD don't. In
+        Darwin, "shared libraries" have the file type "dylib" : the
+        expectation is that this class of file is linked against when
+        executable files are created and loaded by the OS when the
+        executable is launched. The latter class -
+        "bundles/extensions" - are expected to be loaded into and
+        unloaded from a running application, via a mechanism like the
+        one used by &CCL;'s OPEN-SHARED-LIBRARY function.</para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="Unix-Posix-Darwin-Features">
+    <title>Unix/Posix/Darwin Features</title>
+    <para>&CCL; has several convenience functions which allow you
+      to make Posix (portable Unix) calls without having to use the
+      foreign-function interface.  Each of these corresponds directly
+      to a single Posix function call, as it might be made in C.
+      There is no attempt to make these calls correspond to Lisp
+      idioms, such as <literal>setf</literal>.  This means that their
+      behavior is simple and predictable.</para>
+    <para>For working with environment variables, there are
+      CCL::GETENV and CCL::SETENV.</para>
+    <para>For working with user and group IDs, there are
+      CCL::GETUID, CCL::SETUID, and CCL::SETGID.  To find the home
+      directory of an arbitrary user, as set in the user database
+      (/etc/passwd), there is CCL::GET-USER-HOME-DIR.</para>
+    <para>For process IDs, there is CCL::GETPID.</para>
+    <para>For the <literal>system()</literal> function, there is
+      CCL::OS-COMMAND.  Ordinarily, it is better - both more efficient
+      and more predictable - to use the features described in <xref
+                                                                 linkend="Running-Other-Programs-as-Subprocesses"/>.  However,
+      sometimes you may want to specifically ask the shell to invoke a
+      command for you.</para>
+  </sect1>
+
+  <sect1 id="Cocoa-Programming-in-CCL">
+    <title>Cocoa Programming in &CCL;</title>
+    <para>Cocoa is one of Apple's APIs for GUI programming; for most
+      purposes, development is considerably faster with Cocoa than
+      with the alternatives.  You should have a little familiarity
+      with it, to better understand this section.</para>
+    <para>A small sample Cocoa program can be invoked by evaluating
+      (REQUIRE 'TINY) and then (CCL::TINY-SETUP). This program
+      provides a simple example of using several of the bridge's
+      capabilities.</para>
+    <para>The Tiny demo creates Cocoa objects dynamically, at
+      runtime, which is always an option.  However, for large
+      applications, it is usually more convenient to create your
+      objects with Apple Interface Builder, and store them in .nib
+      files to be loaded when needed.  Both approaches can be freely
+      mixed in a single program.</para>
+
+    <sect2 id="The-Command-Line-and-the-Window-System">
+	  <title>The Command Line and the Window System</title>
+      <para>&CCL; is ordinarily a command-line application (it
+        doesn't have a connection to the OSX Window server, doesn't
+        have its own menubar or dock icon, etc.) By opening some
+        libraries and jumping through some hoops, it's able to sort of
+        transform itself into a full-fledged GUI application (while
+        retaining its original TTY-based listener.) The general idea
+        is that this hybrid environment can be used to test and
+        protoype UI ideas and the resulting application can eventually
+        be fully transformed into a bundled, double-clickable
+        application. This is to some degree possible, but there needs
+        to be a bit more infrastructure in place before many people
+        would find it easy.</para>
+      <para>Cocoa applications use the NSLog function to write
+        informational/warning/error messages to the application's
+        standard output stream. When launched by the Finder, a GUI
+        application's standard output is diverted to a logging
+        facility that can be monitored with the Console application
+        (found in /Applications/Utilities/Console.app).  In the hybrid
+        environment, the application's standard output stream is
+        usually the initial listener's standard output stream. With
+        two different buffered stream mechanisms trying to write to
+        the same underlying Unix file descriptor, it's not uncommon to
+        see NSLog output mixed with lisp output on the initial
+        listener.</para>
+    </sect2>
+
+    <sect2 id="Writing--and-reading--Cocoa-code">
+	  <title>Writing (and reading) Cocoa code</title> <para>The
+	    syntax of the constructs used to define Cocoa classes and
+	    methods has changed a bit (it was never documented outside of
+	    the source code and never too well documented at all), largely
+	    as the result of functionality offered by Randall Beer's
+	    bridge; the &ldquo;standard name-mapping conventions&rdquo;
+	    referenced below are described in his CocoaBridgeDoc.txt file,
+	    as are the constructs used to invoke (&ldquo;send messages
+	    to&rdquo;) Cocoa methods.</para>
+      <para>All of the symbols described below are currently internal to
+        the CCL package.</para>
+	  <simplelist type="vert" columns="1">
+	    <member><xref linkend="m_class"/></member>
+	    <member><xref linkend="m_selector"/></member>
+	    <member><xref linkend="m_define-objc-method"/></member>
+	    <member><xref linkend="m_define-objc-class-method"/></member>
+	  </simplelist>
+    </sect2>
+
+    <sect2 id="The-Application-Kit-and-Multiple-Threads">
+	  <title>The Application Kit and Multiple Threads</title>
+      <para>The Cocoa API is broken into several pieces.  The
+        Application Kit, affectionately called AppKit, is the one
+        which deals with window management, drawing, and handling
+        events.  AppKit really wants all these things to be done by a
+        "distinguished thread".  creation, and drawing to take place
+        on a distinguished thread.</para>
+      <para>Apple has published some guidelines which discuss these
+        issues in some detail; see the Apple Multithreading
+        Documentation, and in particular the guidelines on Using the
+        Application Kit from Multiple Threads.  The upshot is that
+        there can sometimes be unexpected behavior when objects are
+        created in threads other than the distinguished event thread;
+        eg, the event thread sometimes starts performing operations on
+        objects that haven't been fully initialized.</para> <para>It's
+        certainly more convenient to do certain types of exploratory
+        programming by typing things into a listener or evaluating a
+        &ldquo;defun&rdquo; in an Emacs buffer; it may sometimes be
+        necessary to be aware of this issue while doing so.</para>
+      <para>Each thread in the Cocoa runtime system is expected to
+        maintain a current &ldquo;autorelease pool&rdquo; (an instance
+        of the NSAutoreleasePool class); newly created objects are
+        often added to the current autorelease pool (via the
+        -autorelease method), and periodically the current autorelease
+        pool is sent a &ldquo;-release&rdquo; message, which causes it
+        to send &ldquo;-release&rdquo; messages to all of the objects
+        that have been added to it.</para>
+      <para>If the current thread doesn't have a current autorelease
+        pool, the attempt to autorelease any object will result in a
+        severe-looking warning being written via NSLog. The event
+        thread maintains an autorelease pool (it releases the current
+        pool after each event is processed and creates a new one for
+        the next event), so code that only runs in that thread should
+        never provoke any of these severe-looking NSLog
+        messages.</para> <para>To try to suppress these messages (and
+        still participate in the Cocoa memory management scheme), each
+        listener thread (the initial listener and any created via the
+        &ldquo;New Listener&rdquo; command in the IDE) is given a
+        default autorelease pool; there are REPL colon-commands for
+        manipulating the current listener's &ldquo;toplevel
+        autorelease pool&rdquo;.</para>
+      <para>In the current scheme, every time that Cocoa calls lisp
+        code, a lisp error handler is established which maps any lisp
+        conditions to ObjC exceptions and arranges that this exception
+        is raised when the callback to lisp returns. Whenever lisp
+        code invokes a Cocoa method, it does so with an ObjC exception
+        handler in place; this handler maps ObjC exceptions to lisp
+        conditions and signals those conditions.</para> <para>Any
+        unhandled lisp error or ObjC exception that occurs during the
+        execution of the distinguished event thread's event loop
+        causes a message to be NSLog'ed and the event loop to (try to)
+        continue execution. Any error that occurs in other threads is
+        handled at the point of the outermost Cocoa method
+        invocation. (Note that the error is not necessarily
+        &ldquo;handled&rdquo; in the dynamic context in which it
+        occurs.)</para>
+      <para>Both of these behaviors could possibly be improved; both of them
+        seem to be substantial improvements over previous behaviors (where,
+        for instance, a misspelled message name typically terminated the
+        application.)</para>
+    </sect2>
+
+    <sect2 id="Acknowledgement--2-">
+	  <title>Acknowledgement</title>
+      <para>The Cocoa bridge was originally developed, and
+        generously contributed by, Randall Beer.</para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="Building-an-Application-Bundle">
+    <title>Building an Application Bundle</title>
+    <para>You may have noticed that (require "COCOA") takes a long
+      time to load.  It is possible to avoid this by saving a Lisp
+      heap image which has everything already loaded.  There is an
+      example file which allows you to do this,
+      "ccl/examples/cocoa-application.lisp", by producing a
+      double-clickable application which runs your program.  First,
+      load your own program.  Then, do:</para>
+    <programlisting>
+? (require "COCOA-APPLICATION")
+    </programlisting>
+    <para>When it finishes, you should be able to double-click the &CCL; icon
+      in the ccl directory, to quickly start your program.</para>
+    <para>The OS may have already decided that &CCL;.app isn't a valid
+      executable bundle, and therefore won't let you double-click it.
+      If this happens to you, to force it to reconsider, just update the
+      last-modified time of the bundle.  In Terminal:</para>
+    <programlisting>> touch &CCL;.app
+    </programlisting>
+    <para>There is one important caveat.</para>
+    <para>Because of the way that the ObjC bridge currently works, a saved
+      image is dependent upon the <emphasis>exact</emphasis> versions of
+      the Cocoa libraries which were present when it was saved.
+      Specifically, the interface database is.  So, for example, an
+      application produced under OS X 10.3.5 will not work under
+      OS X 10.3.6.  This is inconvenient when you wish to distribute an
+      application you have built this way.</para>
+    <para>When an image which had contained ObjC classes (which are also
+      CLOS classes) is re-launched, those classes are "revived": all
+      preexisting classes have their addresses updated destructively, so that
+      existing subclass/superclass/metaclass relationships are maintained.
+      It's not possible (and may never be) to preserve foreign
+      instances across SAVE-APPLICATION. (It may be the case that NSArchiver
+      and NSCoder and related classes offer some approximation of that.)</para>
+  </sect1>
+
+  <sect1 id="Recommended-Reading">
+    <title>Recommended Reading</title>
+    <variablelist>
+	  <varlistentry>
+	    <term>
+	      <ulink url="http://developer.apple.com/documentation/Cocoa/">Cocoa Documentation</ulink>
+	    </term>
+
+	    <listitem>
+	      <para>
+	        This is the top page for all of Apple's documentation on
+	        Cocoa.  If you are unfamiliar with Cocoa, it is a good
+	        place to start.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry>
+	    <term>
+	      <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html">Foundation Reference for Objective-C</ulink>
+	    </term>
+
+	    <listitem>
+	      <para>
+	        This is one of the two most important Cocoa references; it
+	        covers all of the basics, except for GUI programming.  This is
+	        a reference, not a tutorial.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>
+	      <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/index.html">Application Kit Reference for Objective-C</ulink>
+	    </term>
+
+	    <listitem>
+	      <para>
+	        This is the other; it covers GUI programming with Cocoa
+	        in considerable depth.  This is a reference, not a tutorial.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>
+	      <ulink url="http://developer.apple.com/documentation/index.html">Apple Developer Documentation</ulink>
+	    </term>
+
+	    <listitem>
+	      <para>
+	        This is the site which the above two documents are found on;
+	        go here to find the documentation on any other Apple API.
+	        Also go here if you need general guidance about OS X, Carbon,
+	        Cocoa, Core Foundation, or Objective C.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+    </variablelist>
+
+  </sect1>
+
+  <sect1 id="Operating-System-Dictionary">
+    <title>Operating-System Dictionary</title>
+
+    <refentry id="f_getenv">
+	  <indexterm zone="f_getenv">
+	    <primary>getenv</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::GETENV</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>getenv</function> name => value</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+
+	        <listitem>
+		      <para>a string which is the name of an existing
+		        environment variable;
+		        case-sensitive</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>value</term>
+
+	        <listitem>
+		      <para>if there is an environment variable named
+		        <varname>name</varname>, its value, as a string; if there
+		        is not, NIL</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Looks up the value of the environment variable named by
+	      <varname>name</varname>, in the OS environment.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_setenv">
+	  <indexterm zone="f_setenv">
+	    <primary>setenv</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::SETENV</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>setenv</function> name value => errno</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+
+	        <listitem>
+		      <para>a string which is the name of a new or existing
+		        environment variable;
+		        case-sensitive</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>value</term>
+
+	        <listitem>
+		      <para>a string, to be the new value of the
+		        environment variable
+		        named by <varname>name</varname></para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>errno</term>
+
+	        <listitem>
+		      <para>zero if the function call completes successfully;
+		        otherwise, a platform-dependent integer which describes
+		        the problem</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Sets the value of the environment variable named by
+	      <varname>name</varname>, in the OS environment.  If there is
+	      no such environment
+	      variable, creates it.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_current-directory-name">
+	  <indexterm zone="f_current-directory-name">
+	    <primary>current-directory-name</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::CURRENT-DIRECTORY-NAME</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>current-directory-name</function>
+	      => path</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>path</term>
+
+	        <listitem>
+		      <para>a string, an absolute pathname in Posix format - with
+		        directory components separated by slashes</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Looks up the current working directory of the &CCL; process;
+	      unless it has been changed, this is the directory &CCL; was
+	      started in.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_getuid">
+	  <indexterm zone="f_getuid">
+	    <primary>getuid</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::GETUID</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>getuid</function> => uid</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>uid</term>
+
+	        <listitem>
+		      <para>a non-negative integer, identifying a specific user
+		        account as defined in the OS user database</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Returns the ("real") user ID of the current user.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_setuid">
+	  <indexterm zone="f_setuid">
+	    <primary>setuid</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::SETUID</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>setuid</function> uid => errno</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>uid</term>
+
+	        <listitem>
+		      <para>a non-negative integer, identifying a specific user
+		        account as defined in the OS user database</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>errno</term>
+
+	        <listitem>
+		      <para>zero if the function call completes successfully;
+		        otherwise, a platform-dependent integer which describes
+		        the problem</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Attempts to change the current user ID (both "real" and
+	      "effective"); fails unless
+	      the &CCL; process has super-user privileges or the ID
+	      given is that of the current user.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_setgid">
+	  <indexterm zone="f_setgid">
+	    <primary>setgid</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::SETGID</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>setgid</function> gid => errno</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>gid</term>
+
+	        <listitem>
+		      <para>a non-negative integer, identifying a specific
+		        group as defined in the OS user database</para>
+	        </listitem>
+	      </varlistentry>
+
+	      <varlistentry>
+	        <term>errno</term>
+
+	        <listitem>
+		      <para>zero if the function call completes successfully;
+		        otherwise, a platform-dependent integer which describes
+		        the problem</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Attempts to change the current group ID (both "real" and
+	      "effective"); fails unless
+	      the &CCL; process has super-user privileges or the ID
+	      given is that of a group to which the current user belongs.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_getpid">
+	  <indexterm zone="f_getpid">
+	    <primary>getpid</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::GETPID</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>getpid</function> => pid</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>pid</term>
+
+	        <listitem>
+		      <para>a non-negative integer, identifying an OS process</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Returns the ID of the &CCL; OS process.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_get-user-home-dir">
+	  <indexterm zone="f_get-user-home-dir">
+	    <primary>get-user-home-dir</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::GET-USER-HOME-DIR</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>get-user-home-dir</function> 
+	      uid => path</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>uid</term>
+
+	        <listitem>
+		      <para>a non-negative integer, identifying a specific user
+		        account as defined in the OS user database</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>path</term>
+
+	        <listitem>
+		      <para>a string, an absolute pathname in Posix format - with
+		        directory components separated by slashes; or NIL</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Looks up and returns the defined home directory of the user
+	      identified by <varname>uid</varname>.  This value comes from the
+	      OS user database, not from the <varname>$HOME</varname>
+	      environment variable.  Returns NIL if there is no user with
+	      the ID <varname>uid</varname>.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_os-command">
+	  <indexterm zone="f_os-command">
+	    <primary>os-command</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::OS-COMMAND</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>os-command</function> command-line
+	      => exit-code</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>command-line</term>
+
+	        <listitem><para>a string, obeying all the whitespace and
+	            escaping
+	            conventions required by the user's default system shell</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	    <variablelist>
+	      <varlistentry>
+	        <term>exit-code</term>
+
+	        <listitem><para>a non-negative integer, returned as the exit
+	            code of a subprocess; zero indicates success</para></listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>
+	      Invokes the Posix function <function>system()</function>, which
+	      invokes the user's default system shell (such as
+	      sh or tcsh) as a new process, and has that shell execute
+	      <varname>command-line</varname>.
+	    </para>
+	    
+	    <para>
+	      If the shell was able to find the command specified in
+	      <varname>command-line</varname>, then <varname>exit-code</varname>
+	      is the exit code of that command.  If not, it is the exit
+	      code of the shell itself.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>
+	      By convention, an exit code of 0 indicates success.  There are
+	      also other conventions; unfortunately, they are OS-specific, and
+	      the portable macros to decode their meaning are implemented
+	      by the system headers as C preprocessor macros.  This means
+	      that there is no good, automated way to make them available
+	      to Lisp.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="m_class">
+	  <indexterm zone="m_class">
+	    <primary>@class</primary>
+	  </indexterm>
+	  
+	  <refnamediv>
+	    <refname>CCL::@CLASS</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>@class</function> class-name</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>class-name</term>
+
+	        <listitem>
+		      <para>a string which denotes an existing class name, or a
+		        symbol which can be mapped to such a string via the standard
+		        name-mapping conventions for class names</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Used to refer to a known ObjC class by name. (Via the use
+	      LOAD-TIME-VALUE, the results of a class-name -&#62; class lookup
+	      are cached.)</para>
+
+	    <para>
+	      <function>@class</function> is obsolete as of late 2004, because
+	      find-class now works on ObjC classes.  It is described here
+	      only because some old code still uses it.
+	    </para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="m_selector">
+	  <indexterm zone="m_selector">
+	    <primary>@selector</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>CCL::@SELECTOR</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>@selector</function> string</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+		    <term>string</term>
+
+		    <listitem>
+		      <para>a string constant, used to canonically refer to an
+		        ObjC method selector</para>
+		    </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Used to refer to an ObjC method selector (method name). Uses
+	      LOAD-TIME-VALUE to cache the result of a string -&#62; selector
+	      lookup.</para>
+	  </refsect1>
+	</refentry>
+
+	<refentry id="m_objc-defmethod">
+	  <indexterm zone="m_objc-defmethod">
+	    <primary>objc:defmethod</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>objc:defmethod</refname>
+	    <refpurpose></refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>objc:defmethod</function>
+	      name-and-result-type ((receiver-arg-and-class) &rest;
+	      other-args) &body; body</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+
+	      <varlistentry>
+		    <term>name-and-result-type</term>
+            
+		    <listitem>
+		      <para>either an Objective-C message name, for methods
+                that return a value of type <literal>:ID</literal>, or
+                a list containing an Objective-C message name and a
+                foreign type specifier for methods with a different
+                foreign result type.</para>
+		    </listitem>
+	      </varlistentry>
+          
+	      <varlistentry>
+		    <term>receiver-arg-and-class</term>
+            
+		    <listitem>
+		      <para>a two-element list whose first element is a
+                variable name and whose second element is the Lisp
+                name of an Objective-C class or metaclass.  The
+                receiver variable name can be any bindable lisp
+                variable name, but <literal>SELF</literal> might be a
+                reasonable choice.  The receiver variable is declared
+                to be "unsettable"; i.e., it is an error to try to
+                change the value of the receiver in the body of the
+                method definition.</para>
+		    </listitem>
+	      </varlistentry>
+          
+	      <varlistentry>
+		    <term>other-args</term>
+            
+		    <listitem>
+		      <para>either variable names (denoting parameters of
+            type <literal>:ID</literal>) or 2-element lists whose
+            first element is a variable name and whose second element
+            is a foreign type specifier.</para>
+		    </listitem>
+	      </varlistentry>
+          
+	      </variablelist>
+	    </refsect1>
+        
+	    <refsect1>
+	      <title>Description</title>
+          
+	      <para>Defines an Objective-C-callable method which implements
+	        the specified message selector for instances of the existing
+	        named Objective-C class.</para>
+
+          <para>For a detailed description of the features and
+          restrictions of the <literal>OBJC:DEFMETHOD</literal> macro,
+          see the
+          section <link linkend="anchor_Using-objc-defmethod">Using <literal>objc:defmethod</literal></link>.</para>
+	    </refsect1>
+	  </refentry>
+      
+	  <refentry id="m_define-objc-method">
+	    <indexterm zone="m_define-objc-method">
+	      <primary>define-objc-method</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL::DEFINE-OBJC-METHOD</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Macro</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>define-objc-method</function>
+	        (selector class-name) &body; body</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments and Values</title>
+
+	      <variablelist>
+	        <varlistentry>
+		      <term>selector</term>
+
+		      <listitem>
+		        <para>either a string which represents the name of the
+		          selector or a list which describes the method's return
+		          type, selector components, and argument types (see below.)
+		          If the first form is used, then the first form in the body
+		          must be a list which describes the selector's argument
+		          types and return value type, as per DEFCALLBACK.</para>
+		      </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+		      <term>class-name</term>
+
+		      <listitem>
+		        <para>either a string which names an existing ObjC class
+		          name or a list symbol which can map to such a string via the
+		          standard name-mapping conventions for class names. (Note
+		          that the "canonical" lisp class name is such a
+		          symbol)</para>
+		      </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>Defines an ObjC-callable method which implements the
+	        specified message selector for instances of the existing ObjC
+	        class class-name.</para>
+	    </refsect1>
+	  </refentry>
+
+	  <refentry id="m_define-objc-class-method">
+	    <indexterm zone="m_define-objc-class-method">
+	      <primary>define-objc-class-method</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL::DEFINE-OBJC-CLASS-METHOD</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Macro</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>define-objc-class-method</function>
+	        (selector class-name) &body; body</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments and Values</title>
+
+	      <para>As per DEFINE-OBJC-METHOD</para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>Like DEFINE-OBJC-METHOD, only used to define methods on the
+	        <emphasis>class</emphasis> named by class-name and on its
+	        subclasses.</para>
+
+	      <para>For both DEFINE-OBJC-METHOD and DEFINE-OBJC-CLASS-METHOD, the
+	        "selector" argument can be a list whose first element is a
+	        foreign type specifier for the method's return value type and whose
+	        subsequent elements are either:</para>
+
+	      <itemizedlist>
+	        <listitem>
+		      <para>a non-keyword symbol, which can be mapped to a selector string
+		        for a parameterless method according to the standard name-mapping
+		        conventions for method selectors.</para>
+	        </listitem>
+	        
+	        <listitem>
+		      <para>a list of alternating keywords and variable/type specifiers,
+		        where the set of keywords can be mapped to a selector string for a
+		        parameterized method according to the standard name-mapping
+		        conventions for method selectors and each variable/type-specifier is
+		        either a variable name (denoting a value of type :ID) or a list whose
+		        CAR is a variable name and whose CADR is the corresponding
+		        argument's foreign type specifier.</para>
+	        </listitem>
+	      </itemizedlist>
+	    </refsect1>
+	  </refentry>
+
+	  <refentry id="v_alternate-line-terminator">
+	    <indexterm zone="v_alternate-line-terminator">
+	      <primary>*alternate-line-terminator*</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL:*ALTERNATE-LINE-TERMINATOR*</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Variable</refclass>
+	    </refnamediv>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>This variable is currently only used by the standard reader macro
+	        function for #\; (single-line comments); that function reads successive
+	        characters until EOF, a #\NewLine is read, or a character EQL to the
+	        value of *alternate-line-terminator* is read. In &CCL; for Darwin, the
+	        value of this variable is initially #\Return ; in &CCL; for LinuxPPC,
+	        it&#39;s initially NIL.</para>
+	      
+	      <para>Their default treatment by the #\; reader macro is the primary way
+	        in which #\Return and #\Linefeed differ syntactically; by extending the
+	        #\; reader macro to (conditionally) treat #\Return as a
+	        comment-terminator, that distinction is eliminated. This seems to make
+	        LOAD and COMPILE-FILE insensitive to line-termination issues in many
+	        cases. It could fail in the (hopefully rare) case where a LF-terminated
+	        (Unix) text file contains embedded #\Return characters, and this
+	        mechanism isn&#39;t adequate to handle cases where newlines are embedded
+	        in string constants or other tokens (and presumably should be translated
+	        from an external convention to the external one) : it doesn&#39;t change
+	        what READ-CHAR or READ-LINE &#34;see&#34;, and that may be necessary to
+	        handle some more complicated cases.</para>
+	    </refsect1>
+	  </refentry>
+
+	  <refentry id="k_external-format">
+	    <indexterm zone="k_external-format">
+	      <primary>:external-format</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>:EXTERNAL-FORMAT</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Keyword Argument</refclass>
+	    </refnamediv>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>Per ANSI CL, &CCL; supports the :EXTERNAL-FORMAT keyword
+	        argument to the functions OPEN, LOAD, and COMPILE-FILE. This argument is
+	        intended to provide a standard way of providing implementation-dependent
+	        information about the format of files opened with an element-type of
+	        CHARACTER. This argument can meaningfully take on the values :DEFAULT
+	        (the default), :MACOS, :UNIX, or :INFERRED in &CCL;.</para>
+	      
+	      <para>When defaulted to or specified as :DEFAULT, the format of the file
+	        stream is determined by the value of the variable
+	        CCL:*DEFAULT-EXTERNAL-FORMAT*. See below.</para>
+	      
+	      <para>When specified as :UNIX, all characters are read from and written
+	        to files verbatim.</para>
+	      
+	      <para>When specified as :MACOS, all #\Return characters read from the
+	        file are immediately translated to #\Linefeed (#\Newline); all #\Newline
+	        (#\Linefeed) characters are written externally as #\Return characters.</para>
+	      
+	      <para>When specified as :INFERRED and the file is open for input, the
+	        first buffer-full of input data is examined; if a #\Return character
+	        appears in the buffer before the first #\Linefeed, the file stream&#39;s
+	        external-format is set to :MACOS; otherwise, it is set to :UNIX.</para>
+	      
+	      <para>All other values of :EXTERNAL-FORMAT - and any combinations that
+	        don&#39;t make sense, such as trying to infer the format of a
+	        newly-created output file stream - are treated as if :UNIX was
+	        specified. As mentioned above, the :EXTERNAL-FORMAT argument doesn&#39;t
+	        apply to binary file streams.</para>
+	      
+	      <para>The translation performed when :MACOS is specified or inferred has
+	        a somewhat greater chance of doing the right thing than the
+	        *alternate-line-terminator* mechanism does; it probably has a somewhat
+	        greater chance of doing the wrong thing, as well.</para>
+	    </refsect1>
+	  </refentry>
+
+	  <refentry id="v_default-external-format">
+	    <indexterm zone="v_default-external-format">
+	      <primary>*default-external-format*</primary>
+	    </indexterm>
+	    
+	    <refnamediv>
+	      <refname>CCL:*DEFAULT-EXTERNAL-FORMAT*</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Variable</refclass>
+	    </refnamediv>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>The value of this variable is used when :EXTERNAL-FORMAT is
+	        unspecified or specified as :DEFAULT. It can meaningfully be given any
+	        of the values :UNIX, :MACOS, or :INFERRED, each of which is interpreted
+	        as described above.</para>
+	      
+	      <para>Because there&#39;s some risk that unsolicited newline translation
+	        could have undesirable consequences, the initial value of this variable
+	        in &CCL; is :UNIX.</para>
+	    </refsect1>
+	  </refentry>
+
+	  <refentry id="c_ns-lisp-string">
+	    <indexterm zone="c_ns-lisp-string">
+	      <primary>ns-lisp-string</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL::NS-LISP-STRING</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Class</refclass>
+	    </refnamediv>
+
+	    <refsect1>
+	      <title>Superclasses</title>
+
+	      <para>NS:NS-STRING</para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Initargs</title>
+	      
+	      <variablelist>
+	        <varlistentry>
+		      <term>:string</term>
+		      
+		      <listitem>
+		        <para>
+		          a Lisp string which is to be the content of
+		          the newly-created ns-lisp-string.
+		        </para>
+		      </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>
+	        This class
+	        implements the interface of an NSString, which means that it can
+	        be passed to any Cocoa or Core Foundation function which expects
+	        one.
+	      </para>
+
+	      <para>
+	        The string itself is stored on the Lisp heap, which
+	        means that its memory management is automatic.  However, the
+	        ns-lisp-string object itself is a foreign
+	        object (that is, it has an objc metaclass), and resides on the
+	        foreign heap.  Therefore, it is necessary to explicitly free
+	        it, by sending a dealloc message.
+	      </para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Examples</title>
+
+	      <para>
+	        You can create an ns-lisp-string with
+	        <function>make-instance</function>, just like
+	        any normal Lisp class:
+	      </para>
+
+	      <programlisting format="linespecific"
+>? (defvar *the-string*
+     (make-instance 'ccl::ns-lisp-string
+                    :string "Hello, Cocoa."))
+</programlisting>
+	      
+	      <para>
+	        When you are done with the string, you must explicitly
+	        deallocate it:
+	      </para>
+
+	      <programlisting format="linespecific">? (ccl::send *the-string* 'dealloc)</programlisting>
+
+	      <para>
+	        You may wish to use an <function>unwind-protect</function>
+	        form to ensure that this happens:
+	      </para>
+
+	      <programlisting format="linespecific"
+>(let (*the-string*)
+  (unwind-protect (progn (setq *the-string*
+                               (make-instance 'ccl::ns-lisp-string
+                                              :string "Hello, Cocoa."))
+                         (format t "~&amp;The string is ~D characters long.~%"
+                                 (ccl::send *the-string* 'length)))
+    (when *the-string*
+      (ccl::send *the-string* 'dealloc))))
+</programlisting>
+
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Notes</title>
+
+	      <para>
+	        Currently, ns-lisp-string is defined in
+	        the file ccl/examples/cocoa-backtrace.lisp, which is a
+	        rather awkward place.  It was probably not originally meant
+	        as a public utility at all.  It would be good if it were
+	        moved someplace else.  Use at your own risk.
+	      </para>
+	    </refsect1>
+	  </refentry>
+    </sect1>
+  </chapter>
Index: /branches/new-random/doc/src/profile.xml
===================================================================
--- /branches/new-random/doc/src/profile.xml	(revision 13309)
+++ /branches/new-random/doc/src/profile.xml	(revision 13309)
@@ -0,0 +1,376 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "Clozure CL">
+]>
+
+  <chapter id="Profiling">
+    <title>Profiling</title>
+
+    <sect1 id="Profiling-Using the Linux oprofile system-level profiler">
+      <title>Using the Linux oprofile system-level profiler</title>
+
+      <para><ulink url="http://oprofile.sourceforge.net"><code>oprofile</code></ulink> is
+      a system-level profiler that's available for most modern Linux distributions.</para>
+
+      <para>Use of oprofile and its companion programs isn't really documented here; what
+      is described is a way of generating symbolic information that enables profiling
+      summaries generated by the <code>opreport</code> program to identify lisp functions
+      meaningfully.</para>
+
+      <sect2 id="Profiling-oprofile-generating-a-lisp-image-for-use-with-oprofile">
+	<title>Generating a lisp image for use with oprofile</title>
+
+	<para>Modern Linux uses the 'ELF" (Executable and Linking Format) object file
+	format; the oprofile tools can associate symbolic names with addresses in a
+	memory-mapped file if that file appears to be an ELF object file and if it
+	contains ELF symbol information that describes those memory regions.  So, the
+	general idea is to make a lisp heap image that looks enough like an ELF shared
+	library to fool the <code>oprofile</code> tools (we don't actually load heap
+	images via ELF dynamic linking technology, but we can make it look like we
+	did.)</para>
+
+      </sect2>
+      <sect2 id="Profiling-oprofile-prerequisites">
+	<title>Prerequisites</title>
+
+	<itemizedlist>
+	  <listitem>
+	    <para><code>oprofile</code> itself, which is almost certainly available via
+	    your distribution's package management system if not already
+	    preinstalled.</para>
+	  </listitem>
+	  <listitem>
+	    <para><code>libelf</code>, which provides utilities for reading and writing
+	    ELF files (and is likewise likely preinstalled or readily installable.)</para>
+	  </listitem>
+	</itemizedlist>
+      </sect2>
+      <sect2 id="Profiling-oprofile-generating-elf-symbols-for-lisp-functions">
+	<title>Generating ELF symbols for Lisp functions</title>
+
+	<para>In order to create a lisp heap image which can be used for
+	<code>oprofile</code>- based profiling, we need to:</para>
+	<orderedlist>
+	  <listitem>
+	    <para>load any code that we want to profile</para>
+	  </listitem>
+	  <listitem>
+	    <para>generate a file that contains ELF symbol information describing the
+	    names and addresses of all lisp functions.</para>
+	    <para>This step involves doing (from within &CCL;)</para>
+	    <programlisting>
+? (require "ELF")
+"ELF"
+("ELF")
+
+? (ccl::write-elf-symbols-to-file "home:elf-symbols")
+	    </programlisting>
+	    <para>The argument to CCL::WRITE-ELF-SYMBOLS-TO-FILE can be any writable
+	    pathname.  The function will do whatever's necessary to nail lisp functions
+	    down in memory (so that they aren't moved by GC), then write an ELF object
+	    file to the indicated pathname.  This typically takes a few seconds.</para>
+	  </listitem>
+	  <listitem>
+	    <para>Generate a lisp heap image in which the ELF symbols generated in the
+	    previous step are prepended.</para>
+	    <para>The function CCL:SAVE-APPLICATION provides a :PREPEND-KERNEL argument,
+	    which is ordinarily used to save a standalone application in which the kernel
+	    and heap image occupy a single file.  :PREPEND-KERNEL doesn't really care what
+	    it's prepending to the image, and we can just as easily ask it to prepend the
+	    ELF symbol file generated in the previous step.</para>
+	    <programlisting>
+? (save-application "somewhere/image-for-profiling"
+    :prepend-kernel "home:elf-symbols")
+	    </programlisting>
+	    <para>If you then run</para>
+	    <programlisting>
+shell> ccl64 somewhare/image-for-profiling
+	    </programlisting>
+	    <para>any lisp code sampled by oprofile in that image will be identified
+	    "symbolically" by <code>opreport</code>.</para>
+	  </listitem>
+	</orderedlist>
+      </sect2>
+      <sect2 id="Profiling-oprofile-example">
+	<title>Example</title>
+	<programlisting>
+;;; Define some lisp functions that we want to profile and save
+;;; a profiling-enabled image.  In this case, we just want to 
+;;; define the FACTORIAL funcion, to keep things simple.
+? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
+FACT
+? (require "ELF")
+"ELF"
+("ELF")
+? (ccl::write-elf-symbols-to-file "home:elf-symbols")
+"home:elf-symbols"
+? (save-application "home:profiled-ccl" :prepend-kernel "home:elf-symbols")
+
+;;; Setup oprofile with (mostly) default arguments.  This example was
+;;; run on a Fedora 8 system where an uncompressed 'vmlinux' kernel
+;;; image isn't readily available.
+
+;;; Note that use of 'opcontrol' generally requires root access, e.g.,
+;;; 'sudo' or equivalent:
+
+[~] gb@rinpoche> sudo opcontrol --no-vmlinux --setup
+
+;;; Start the profiler
+
+[~] gb@rinpoche> sudo opcontrol --start
+Using 2.6+ OProfile kernel interface.
+Using log file /var/lib/oprofile/samples/oprofiled.log
+Daemon started.
+Profiler running.
+
+;;; Start CCL with the "profiled-ccl" image created above.
+;;; Invoke "(FACT 10000)"
+
+[~] gb@rinpoche> ccl64 profiled-ccl 
+Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk  (LinuxX8664)!
+? (null (fact 10000))
+NIL
+? (quit)
+
+;;; We could stop the profiler (opcontrol --stop) here; instead,
+;;; we simply flush profiling data to disk, where 'opreport' can
+;;; find it.
+
+[~] gb@rinpoche> sudo opcontrol --dump
+
+;;; Ask opreport to show us where we were spending time in the
+;;; 'profiled-ccl' image.
+
+[~] gb@rinpoche> opreport -l profiled-ccl | head
+CPU: Core 2, speed 1596 MHz (estimated)
+Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
+samples  %        symbol name
+6417     65.2466  &lt;Compiled-function.(:INTERNAL.MULTIPLY-UNSIGNED-BIGNUM-AND-1-DIGIT-FIXNUM.MULTIPLY-BIGNUM-AND-FIXNUM).(Non-Global)..0x30004002453F&gt;
+3211     32.6487  &lt;Compiled-function.%MULTIPLY-AND-ADD4.0x300040000AAF&gt;
+17        0.1729  &lt;Compiled-function.%%ONE-ARG-DCODE.0x3000401740AF&gt;
+11        0.1118  &lt;Compiled-function.%UNLOCK-RECURSIVE-LOCK-OBJECT.0x30004007F7DF&gt;
+10        0.1017  &lt;Compiled-function.AUTO-FLUSH-INTERACTIVE-STREAMS.0x3000404ED6AF&gt;
+7         0.0712  &lt;Compiled-function.%NANOSLEEP.0x30004040385F&gt;
+7         0.0712  &lt;Compiled-function.%ZERO-TRAILING-SIGN-DIGITS.0x300040030F3F&gt;
+	</programlisting>
+      </sect2>
+      <sect2 id="Profiling-oprofile-Issues">
+	<title>Issues</title>
+	<para>CCL::WRITE-ELF-SYMBOLS-TO-FILE currently only works on x86-64; it certainly
+	-could- be made to work on ppc32/ppc64 as well.</para>
+
+	<para>So far, no one has been able to make oprofile/opreport options that're
+	supposed to generate call-stack info generate meaningful call-stack info.</para>
+
+	<para>As of a few months ago, there was an attempt to provide symbol info for
+	oprofile/opreport "on the fly", e.g., for use in JIT compilation or other
+	incremental compilations scenarios.  That's obviously more nearly The Right Thing,
+	but it might be awhile before that experimental code makes it into widespread
+	use.</para>
+      </sect2>
+    </sect1>
+
+    <sect1 id="Profiling-Using-Apples-CHUD-metering-tools">
+      <title>Using Apple's CHUD metering tools</title>
+      
+      <sect2 id="Profiling-CHUD-prerequisites">
+	<title>Prerequisites</title>
+
+	<para>Apple's CHUD metering tools are available (as of this writing) from:</para>
+
+	<para><ulink url="ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/">
+	  ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/</ulink>.</para>
+
+	<para>The CHUD tools are also generally bundled with Apple's XCode tools.  CHUD
+	4.5.0 (which seems to be bundled with XCode 3.0) seems to work well with this
+	interface; later versions may have problems.  Versions of CHUD as old as 4.1.1 may
+	work with 32-bit PPC versions of CCL; later versions (not sure exactly -what-
+	versions) added x86, ppc64, and x86-64 support.</para>
+
+	<para>One way to tell whether any version of the CHUD tools is installed is to try
+	to invoke the "shark" command-line program (/usr/bin/shark) from the shell:</para>
+	<programlisting>
+shell> shark --help
+	</programlisting>
+	<para>and verifying that that prints a usage summary.</para>
+
+	<para>CHUD consists of several components, including command-line programs, GUI
+	applications, kernel extensions, and "frameworks" (collections of libraries,
+	headers, and other resources which applications can use to access functionality
+	provided by the other components.)  Past versions of &CCL;/OpenMCL have used the
+	CHUD framework libraries to control the CHUD profiler.  Even though the rest of
+	CHUD is currently 64-bit aware, the frameworks are unfortunately still only
+	available as 32-bit libraries, so the traditional way of controlling the profiling
+	facility from &CCL; has only worked from DarwinPPC32 versions.</para>
+
+	<para>Two of the CHUD component programs are of particular interest:</para>
+
+	<orderedlist>
+	  <listitem>
+	    <para>The "Shark" application (often installed in
+	    "/Developer/Applications/Performance Tools/Shark.app"), which provides a
+	    graphical user interface for exploring and analyzing profiling results and
+	    provides tools for creating "sampling configurations" (see below), among other
+	    things.</para>
+	  </listitem>
+	  <listitem>
+	    <para>The "shark" program ("/usr/bin/shark"), which can be used to control the
+	    CHUD profiling facility and to collect sampling data, which can then be
+	    displayed and analyzed in Shark.app.</para>
+	  </listitem>
+	</orderedlist>
+
+	<para>The fact that these two (substantially different) programs have names that
+	differ only in alphabetic case may be confusing.  The discussion below tries to
+	consistently distinguish between "the shark program" and "the Shark
+	application".</para>
+
+      </sect2>
+      <sect2 id="Profiling-CHUD-usage-synopsis">
+	  <title>Usage synopsis</title>
+	  <programlisting>
+? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
+FACT
+? (require "CHUD-METERING")
+"CHUD-METERING"
+("CHUD-METERING")
+? (chud:meter (null (fact 10000)))
+NIL	      ; since that large number is not NULL
+	  </programlisting>
+
+	  <para>and, a few seconds after the result is returned, a file whose name is of
+	  the form "session_nnn.mshark" will open in Shark.app.</para>
+
+	  <para>The fist time that CHUD:METER is used in a lisp session, it'll do a few
+	  things to prepare subsequent profiling sessions.  Those things include:</para>
+
+	  <itemizedlist>
+	    <listitem>
+	      <para>creating a directory to store files that are related to using the CHUD
+	      tools in this lisp session.  This directory is created in the user's home
+	      directory and has a name of the form:</para>
+
+	      <programlisting>
+profiling-session-&lt;lisp-kernel&gt;-&lt;pid&gt;_&lt;mm&gt;-&lt;dd&gt;-&lt;yyyy&gt;_&lt;h&gt;.&lt;m&gt;.&lt;s&gt;
+	      </programlisting>
+
+	      <para>where &lt;pid&gt; is the lisp's process id, &lt;lisp-kernel&gt; is the
+	      name of the lisp kernel (of all things ...), and the other values provide a
+	      timestamp.</para>
+	    </listitem>
+	    <listitem>
+	      <para>does whatever needs to be done to ensure that currently-defined lisp
+	      functions don't move around as the result of GC activity, then writes a text
+	      file describing the names and addresses of those functions to the
+	      profiling-session directory created above.  (The naming conventions for and
+	      format of that file are described in</para>
+	      <para>
+	      <ulink url="http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42">http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42</ulink></para>
+	    </listitem>
+	    <listitem>
+	      <para>run the shark program ("/usr/bin/shark") and wait until it's ready to
+	      receive signals that control its operation.</para>
+	    </listitem>
+	  </itemizedlist>
+
+	  <para>This startup activity typically takes a few seconds; after it's been
+	  completed, subsequent use of CHUD:METER doesn't involve that overhead.  (See the
+	  discussion of :RESET below.)</para>
+
+	  <para>After any startup activity is complete, CHUD:METER arranges to send a
+	  "start profiling" signal to the running shark program, executes the form, sends
+	  a "stop profiling" signal to the shark program, and reads its diagnostic output,
+	  looking for the name of the ".mshark" file it produces.  If it's able to find
+	  this filename, it arranges for "Shark.app" to open it.</para>
+	</sect2>
+
+	<sect2 id="Profiling-CHUD-profiling-configurations">
+	  <title>Profiling "configurations"</title>
+
+	  <para>By default, a shark profiling session will:</para>
+	  <itemizedlist>
+	    <listitem>
+	      <para>use "time based" sampling, to periodically interrupt the lisp
+	    process and note the value of the program counter and at least a few levels of
+	    call history.</para>
+	    </listitem>
+	    <listitem>
+	      <para>do this sampling once every millisecond</para>
+	    </listitem>
+	    <listitem>
+	      <para>run for up to 30 seconds, unless told to stop earlier.</para>
+	    </listitem>
+	  </itemizedlist>
+
+	  <para>This is known as "the default configuration"; it's possible to use items
+	  on the "Config" menu in the Shark application to create alternate configurations
+	  which provide different kinds of profiling parameters and to save these
+	  configurations in files for subsequent reuse.  (The set of things that CHUD
+	  knows how to monitor is large and interesting.)</para>
+
+	  <para>You use alternate profiling configurations (created and "exported" via
+	  Shark.app) with CHUD:METER, but the interface is a little awkward.</para>
+	</sect2>
+
+	<sect2 id="Profiling-CHUD-Reference">
+	  <title>Reference</title>
+
+	  <para>
+	    <indexterm zone="chud_shark-config-file"/>
+	    <command><varname id="chud_shark-config-file">CHUD:*SHARK-CONFIG-FILE*</varname> [Variable]</command>
+	  </para>
+
+	  <para>When non-null, this should be the pathname of an alternate profiling
+	  configuration file created by the "Config Editor" in Shark.app.</para>
+
+	  <para>
+	    <indexterm zone="chud_meter"/>
+	    <command><varname id="chud_meter">CHUD:METER</varname> form &key; (reset nil) (debug-output nil) [Macro]</command>
+	  </para>
+	      
+	  <para>Executes FORM (an arbitrary lisp form) and returns whatever result(s) it
+	  returns, with CHUD profiling enabled during the form's execution.  Tries to
+	  determine the name of the session file (*.mshark) to which the shark program
+	  wrote profiling data and opens this file in the Shark application.</para>
+	  
+	  <para>Arguments:</para>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term><varname>debug-output</varname></term>
+	      <listitem>
+		<para>when non-nil, causes output generated by the shark program to be
+		echoed to *TERMINAL-IO*.  For debugging.</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term><varname>reset</varname></term>
+	      <listitem>
+		<para>when non-nil, terminates any running instance of the shark program
+		created by previous invocations of CHUD:METER in this lisp session,
+		generates a new .spatch file (describing the names and addresses of lisp
+		functions), and starts a new instance of the shark program; if
+		CHUD:*SHARK-CONFIG-FILE* is non-NIL when this new instance is started,
+		that instance is told to use the specified config file for profiling (in
+		lieu of the default profiling configuration.)</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</sect2>
+
+	<sect2 id="Profiling-CHUD-Acknowledgments">
+	  <title>Acknowledgement</title>
+	  <para>Both Dan Knapp and Hamilton Link have posted similar CHUD interfaces to
+	  openmcl-devel in the past; Hamilton's also reported bugs in the spatch mechanism
+	  to CHUD developers (and gotten those bugs fixed.)</para>
+	</sect2>
+
+      </sect1>
+
+  </chapter>
Index: /branches/new-random/doc/src/q-and-a.xml
===================================================================
--- /branches/new-random/doc/src/q-and-a.xml	(revision 13309)
+++ /branches/new-random/doc/src/q-and-a.xml	(revision 13309)
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "Clozure CL">
+]>
+  <chapter id="Questions-and-Answers">
+
+    <title>Questions and Answers</title>
+
+    <sect1 id="How-can-I-do-nonblocking--aka--unbuffered--and--raw---IO-">
+      <title>How can I do nonblocking (aka "unbuffered" and "raw") IO?</title>
+      <para>There's some code for manipulating TTY modes in
+      "ccl:library;pty.lisp".</para>
+      <programlisting>
+? (require "PTY")
+
+? (ccl::disable-tty-local-modes 0 #$ICANON)
+T
+      </programlisting>
+      <para>will turn off "input canonicalization" on file descriptor
+      0, which is at least part of what you need to do here.  This
+      disables the #$ICANON mode, which tells the OS not to do any
+      line-buffering or line-editing.  Of course, this only has any
+      effect in situations where the OS ever does that, which means
+      when stdin is a TTY or PTY.</para>
+      <para>If the #$ICANON mode is disabled, you can do things like:</para>
+      <programlisting>
+? (progn (read-char) (read-char))
+a
+#\a
+      </programlisting>
+      <para>(where the first READ-CHAR consumes the newline, which
+      isn't really necessary to make the reader happy anymore.)  So,
+      you can do:</para>
+      <programlisting>
+? (read-char)
+#\Space
+</programlisting>
+      <para>(where there's a space after the close-paren) without
+      having to type a newline.</para>
+    </sect1>
+
+    <sect1 id="I-m-using-the-graphics-demos--Why-doesn-t-the-menubar-change-">
+      <title>I'm using the graphics demos. Why doesn't the menubar
+      change?</title>
+      <para>When you interact with text-only &CCL;, you're either
+      in Terminal or in Emacs, running &CCL; as a subprocess.  When
+      you load Cocoa or the graphical environment, the subprocess does
+      some tricky things that turn it into a full-fledged Application,
+      as far as the OS is concerned.</para>
+      <para>So, it gets its own icon in the dock, and its own menubar,
+      and so on.  It can be confusing, because standard input and
+      output will still be connected to Terminal or Emacs, so you can
+      still type commands to &CCL; from there.  To see the menubar
+      you loaded, or the windows you opened, just click on the &CCL;
+      icon in the dock.</para>
+    </sect1>
+
+    <sect1 id="I-m-using-Slime-and-Cocoa--Why-doesn-t--standard-output--seem-to-work-">
+      <title>I'm using Slime and Cocoa. Why doesn't *standard-output*
+      seem to work? </title>
+      <para>This comes up if you're using the Slime interface
+      to run &CCL; under Emacs, and you are doing Cocoa programming
+      which involves printing to *standard-output*.  It seems as
+      though the output goes nowhere; no error is reported, but it
+      doesn't appear in the *slime-repl* buffer.</para>
+
+      <para>For the most part, this is only relevant when you are
+      trying to insert debug code into your event handlers.  The SLIME
+      listener runs in a thread where the standard stream variables
+      (like <literal>*STANDARD-OUTPUT* and</literal> and
+      <literal>*TERMINAL-IO*</literal> are bound to the stream used to
+      communicate with Emacs; the Cocoa event thread has its own
+      bindings of these standard stream variables, and output to these
+      streams goes to the *inferior-lisp* buffer instead.  Look for it
+      there.</para>
+    </sect1>
+  </chapter>
Index: /branches/new-random/doc/src/schemas.xml
===================================================================
--- /branches/new-random/doc/src/schemas.xml	(revision 13309)
+++ /branches/new-random/doc/src/schemas.xml	(revision 13309)
@@ -0,0 +1,4 @@
+<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
+<documentElement prefix="" localName="chapter" typeId="DocBook"/>
+<typeId id="DocBook" uri="docbook-rng-4.5/docbook.rnc"/>
+</locatingRules>
Index: /branches/new-random/doc/src/sockets.xml
===================================================================
--- /branches/new-random/doc/src/sockets.xml	(revision 13309)
+++ /branches/new-random/doc/src/sockets.xml	(revision 13309)
@@ -0,0 +1,1465 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY rest "<varname>&amp;rest</varname>">
+<!ENTITY key "<varname>&amp;key</varname>">
+<!ENTITY optional "<varname>&amp;optional</varname>">
+<!ENTITY body "<varname>&amp;body</varname>">
+<!ENTITY aux "<varname>&amp;aux</varname>">
+<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+<!ENTITY CCL "Clozure CL">
+]>
+
+  <chapter id="Programming-with-Sockets">
+    <title>Programming with Sockets</title>
+
+    <sect1 id="Sockets-Overview">
+      <title>Overview</title>
+
+      <para>&CCL; supports the socket abstraction for
+      interprocess communication. A socket represents a connection to
+      another process, typically (but not necessarily) a TCP/IP
+      network connection to a client or server running on some other
+      machine on the network.</para>
+      <para>All symbols mentioned in this chapter are exported from
+      the CCL package. As of version 0.13, these symbols are
+      additionally exported from the OPENMCL-SOCKET package.</para>
+      <para>&CCL; supports three types of sockets: TCP sockets, UDP
+      sockets, and Unix-domain sockets.  This should be enough for all
+      but the most esoteric network situations.  All sockets are
+      created by <xref linkend="f_make-socket"/>.  The type of socket
+      depends on the arguments to it, as follows:</para>
+
+      <variablelist>
+	<varlistentry>
+	  <term>tcp-stream</term>
+
+	  <listitem>
+	    <para>A buffered bi-directional stream over a TCP/IP connection.
+	    tcp-stream is a subclass of stream, and you can read and write to it
+	    using all the usual stream functions. Created by (make-socket
+	    :address-family :internet :type :stream :connect :active ...) or by
+	    (accept-connection ...).</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term>file-socket-stream</term>
+
+	  <listitem>
+	    <para>A buffered bi-directional stream over a &#34;UNIX domain&#34;
+	    connection. file-socket-stream is a subclass of stream, and you can
+	    read and write to it using all the usual stream functions. Created
+	    by (make-socket :address-family :file :type :stream :connect :active
+	    ...) or by (accept-connection ...),</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term>listener-socket</term>
+
+	  <listitem>
+	    <para>A passive socket used to listen for incoming TCP/IP
+	    connections on a particular port. A listener-socket is not a stream.
+	    It doesn&#39;t support I/O. It can only be used to create new
+	    tcp-streams by accept-connection. Created by (make-socket :type
+	    :stream :connect :passive ...)</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term>file-listener-socket</term>
+
+	  <listitem>
+	    <para>A passive socket used to listen for incoming UNIX domain
+	    connections named by a file in the local filesystem. A
+	    listener-socket is not a stream. It doesn&#39;t support I/O. It can
+	    only be used to create new file-socket-streams by accept-connection.
+	    Created by (make-socket :address-family :file :type :stream :connect
+	    :passive ...)</para>
+	  </listitem>
+	</varlistentry>
+
+	<varlistentry>
+	  <term>udp-socket</term>
+
+	  <listitem>
+	    <para>A socket representing a packet-based UDP/IP connection. A
+	    udp-socket supports I/O but it is not a stream. Instead, you must
+	    use the special functions send-to and receive-from to read and write
+	    to it. Created by (make-socket :type :datagram ...)</para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </sect1>
+
+    <sect1 id="Sockets-Dictionary">
+      <title>Sockets Dictionary</title>
+      <refentry id="f_make-socket">
+	<indexterm zone="f_make-socket">
+	  <primary>make-socket</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>MAKE-SOCKET</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>make-socket</function> &key;
+	  address-family type connect eol format remote-host
+	  remote-port local-host local-port local-filename
+	  remote-filename keepalive reuse-address nodelay broadcast
+	  linger backlog input-timeout output-timeout connect-timeout
+	  auto-close deadline</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>address-family</term>
+
+	      <listitem>
+		<para>The address/protocol family of this socket. Currently
+		only :internet (the default), meaning IP, and :file,
+		referring to UNIX domain addresses, are supported.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>type</term>
+
+	      <listitem>
+		<para>One of :stream (the default) to request a
+		connection-oriented socket, or :datagram to request a
+		connectionless socket. The default is :stream.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>connect</term>
+
+	      <listitem>
+		<para>This argument is only relevant to sockets of type
+		:stream. One of :active (the default) to request a :passive
+		to request a file or TCP listener socket.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>eol</term>
+
+	      <listitem>
+		<para>This argument is currently ignored (it is accepted for
+		compatibility with Franz Allegro).</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>format</term>
+
+	      <listitem>
+		<para>One of :text (the default), :binary, or :bivalent.
+		This argument is ignored for :stream sockets for now, as
+		:stream sockets are currently always bivalent (i.e. they
+		support both character and byte I/O). For :datagram sockets,
+		the format determines the type of buffer created by
+		receive-from.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>remote-host</term>
+
+	      <listitem>
+		<para>Required for TCP streams, it specifies the host to
+		connect to (in any format acceptable to lookup-hostname).
+		Ignored for listener sockets. For UDP sockets, it can be
+		used to specify a default host for subsequent calls to
+		send-to or receive-from.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>remote-port</term>
+
+	      <listitem>
+		<para>Required for TCP streams, it specifies the port to
+		connect to (in any format acceptable to lookup-port).
+		Ignored for listener sockets. For UDP sockets, it can be
+		used to specify a default port for subsequent calls to for
+		subsequent calls to send-to or receive-from.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>remote-filename</term>
+
+	      <listitem>
+		<para>Required for file-socket streams, it specifies the
+		name of a file in the local filesystem (e.g., NOT mounted
+		via NFS, AFP, SMB, ...) which names and controls access to a
+		UNIX-domain socket.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>local-host</term>
+
+	      <listitem>
+		<para>Allows you to specify a local host address for a
+		listener or UDP socket, for the rare case where you want to
+		restrict connections to those coming to a specific local
+		address for security reasons.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>local-port</term>
+
+	      <listitem>
+		<para>Specify a local port for a socket. Most useful for
+		listener sockets, where it is the port on which the socket
+		will listen for connections.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>local-filename</term>
+
+	      <listitem>
+		<para>Required for file-listener-sockets. Specifies the name
+		of a file in the local filesystem which is used to name a
+		UNIX-domain socket. The actual filesystem file should not
+		previously exist when the file-listener-socket is created;
+		its parent directory should exist and be writable by the
+		caller. The file used to name the socket will be deleted
+		when the file-listener-socket is closed.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>keepalive</term>
+
+	      <listitem>
+		<para>If true, enables the periodic transmission of
+		&#34;keepalive&#34; messages.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>reuse-address</term>
+
+	      <listitem>
+		<para>If true, allows the reuse of local ports in listener
+		sockets, overriding some TCP/IP protocol specifications. You
+		will need this if you are debugging a server..</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>nodelay</term>
+
+	      <listitem>
+		<para>If true, disables Nagle&#39;s algorithm, which tries
+		to minimize TCP packet fragmentation by introducing
+		transmission delays in the absence of replies. Try setting
+		this if you are using a protocol which involves sending a
+		steady stream of data with no replies and are seeing
+		significant degradations in throughput.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>broadcast</term>
+
+	      <listitem>
+		<para>If true, requests permission to broadcast datagrams on
+		a UDP socket.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>linger</term>
+
+	      <listitem>
+		<para>If specified and non-nil, should be the number of
+		seconds the OS is allowed to wait for data to be pushed
+		through when a close is done. Only relevant for TCP sockets.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>backlog</term>
+
+	      <listitem>
+		<para>For a listener socket, specifies the number of
+		connections which can be pending but not accepted. The
+		default is 5, which is also the maximum on some operating
+		systems.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>input-timeout</term>
+
+	      <listitem>
+		<para>The number of seconds before an input operation
+		times out.  Must be a real number between zero and one
+		million.  If an input operation takes longer than the
+		specified number of seconds, an
+		<literal>input-timeout</literal> error is signalled.
+		(see <xref
+		linkend="Stream-Timeouts-And-Deadlines"/>)</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>output-timeout</term>
+
+	      <listitem>
+		<para>The number of seconds before an output operation
+		times out.  Must be a real number between zero and one
+		million.  If an output operation takes longer than the
+		specified number of seconds, an
+		<literal>output-timeout</literal> error is signalled.
+		(see <xref
+		linkend="Stream-Timeouts-And-Deadlines"/>)</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>connect-timeout</term>
+
+	      <listitem>
+		<para>The number of seconds before a connection
+		attempt times out. [TODO: what are acceptable values?]
+		If a connection attempt takes longer than the
+		specified number of seconds, a
+		<literal>socket-error</literal> is signalled.  This
+		can be useful if the specified interval is shorter
+		than the interval that the OS's socket layer imposes,
+		which is sometimes a minute or two.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>auto-close</term>
+
+	      <listitem>
+		<para>When non-nil, any resulting socket stream will
+		be closed when the GC can prove that the stream is
+		unreferenced.  This is done via CCL's termination
+		mechanism [TODO add xref].</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term>deadline</term>
+
+	      <listitem>
+		<para>Specifies an absolute time in
+		internal-time-units.  If an I/O operation on the
+		stream does not complete before the deadline then a
+		<literal>COMMUNICATION-DEADLINE-EXPIRED</literal>
+		error is signalled.  A deadline takes precedence over
+		any input/output timeouts that may be set.  (see <xref
+		linkend="Stream-Timeouts-And-Deadlines"/>)</para>
+	      </listitem>
+	    </varlistentry>
+
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Creates and returns a new socket</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_accept-connection">
+	<indexterm zone="f_accept-connection">
+	  <primary>accept-connection</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>ACCEPT-CONNECTION</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>accept-connection</function>
+	  (socket listener-socket) &key; wait</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The listener-socket to listen on.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>wait</term>
+
+	      <listitem>
+		<para>If true (the default), and there are no connections
+		waiting to be accepted, waits until one arrives. If false,
+		returns NIL immediately.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Extracts the first connection on the queue of pending
+	  connections, accepts it (i.e. completes the connection startup
+	  protocol) and returns a new tcp-stream or file-socket-stream
+	  representing the newly established connection. The tcp stream
+	  inherits any properties of the listener socket that are relevant
+	  (e.g. :keepalive, :nodelay, etc.) The original listener socket
+	  continues to be open listening for more connections, so you can
+	  call accept-connection on it again.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_dotted-to-ipaddr">
+	<indexterm zone="f_dotted-to-ipaddr">
+	  <primary>dotted-to-ipaddr</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>DOTTED-TO-IPADDR</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>dotted-to-ipaddr</function>
+	  dotted &key; errorp</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>dotted</term>
+
+	      <listitem>
+		<para>A string representing an IP address in the
+		&#34;nn.nn.nn.nn&#34; format</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>errorp</term>
+
+	      <listitem>
+		<para>If true (the default) an error is signaled if dotted
+		is invalid. If false, NIL is returned.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Converts a dotted-string representation of a host address to
+	  a 32-bit unsigned IP address.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_ipaddr-to-dotted">
+	<indexterm zone="f_ipaddr-to-dotted">
+	  <primary>ipaddr-to-dotted</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>IPADDR-TO-DOTTED</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>ipaddr-to-dotted</function>
+	  ipaddr &key; values</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>ipaddr</term>
+
+	      <listitem>
+		<para>A 32-bit integer representing an internet host address</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>values</term>
+
+	      <listitem>
+		<para>If false (the default), returns a string in the form
+		&#34;nn.nn.nn.nn&#34;. If true, returns four values
+		representing the four octets of the address as unsigned
+		8-bit integers.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Converts a 32-bit unsigned IP address into octets.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_ipaddr-to-hostname">
+	<indexterm zone="f_ipaddr-to-hostname">
+	  <primary>ipaddr-to-hostname</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>IPADDR-TO-HOSTNAME</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>ipaddr-to-hostname</function>
+	  ipaddr &key; ignore-cache</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>ipaddr</term>
+
+	      <listitem>
+		<para>a 32-bit integer representing an internet host address</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>ignore-cache</term>
+
+	      <listitem>
+		<para>This argument is ignored (it is accepted for
+		compatibility with Franz Allegro)</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Converts a 32-bit unsigned IP address into a host name
+	  string</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_lookup-hostname">
+	<indexterm zone="f_lookup-hostname">
+	  <primary>lookup-hostname</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>LOOKUP-HOSTNAME</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>lookup-hostname</function>
+	  host</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>host</term>
+
+	      <listitem>
+		<para>Specifies the host. It can be either a host name
+		string such as &#34;clozure.com&#34;, or a dotted address
+		string such as &#34;192.168.0.1&#34;, or a 32-bit unsigned
+		IP address such as 3232235521.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Converts a host spec in any of the acceptable formats into a
+	  32-bit unsigned IP address</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_lookup-port">
+	<indexterm zone="f_lookup-port">
+	  <primary>lookup-port</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>LOOKUP-PORT</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>lookup-port</function>
+	  port protocol</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>port</term>
+
+	      <listitem>
+		<para>Specifies the port. It can be either a string, such as
+		&#34;http&#34; or a symbol, such as :http, or an unsigned
+		port number. Note that a string is case-sensitive. A symbol
+		is lowercased before lookup.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>protocol</term>
+
+	      <listitem>
+		<para>Must be one of &#34;tcp&#34; or &#34;udp&#34;.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Finds the port number for the specified port and protocol</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_receive-from">
+	<indexterm zone="f_receive-from">
+	  <primary>receive-from</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>RECEIVE-FROM</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>receive-from</function>
+	  (socket udp-socket) size &key; buffer
+	  extract offset</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket to read from</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>size</term>
+
+	      <listitem>
+		<para>Maximum number of bytes to read. If the packet is
+		larger than this, any extra bytes are discarded.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>buffer</term>
+
+	      <listitem>
+		<para>If specified, must be either a string or a byte vector
+		which will be used to read in the data. If not specified, a
+		new buffer will be created (of type determined by
+		socket-format).</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>extract</term>
+
+	      <listitem>
+		<para>If true, the subsequence of the buffer corresponding
+		only to the data read in is extracted and returned as the
+		first value. If false (the default) the original buffer is
+		returned even if it is only partially filled.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>offset</term>
+
+	      <listitem>
+		<para>Specifies the start offset into the buffer at which
+		data is to be stored. The default is 0.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Reads a UDP packet from a socket. If no packets are
+	  available, waits for a packet to arrive. Returns four values:</para>
+
+	  <orderedlist continuation="restarts" inheritnum="ignore">
+	    <listitem>
+	      <para>The buffer with the data</para>
+	    </listitem>
+
+	    <listitem>
+	      <para>The number of bytes read</para>
+	    </listitem>
+
+	    <listitem>
+	      <para>The 32-bit unsigned IP address of the sender of the data</para>
+	    </listitem>
+
+	    <listitem>
+	      <para>The port number of the sender of the data</para>
+	    </listitem>
+	  </orderedlist>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_send-to">
+	<indexterm zone="f_send-to">
+	  <primary>send-to</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SEND-TO</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>send-to</function>
+	  (socket udp-socket) buffer size &key; remote-host
+	  remote-port offset</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket to write to</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>buffer</term>
+
+	      <listitem>
+		<para>A vector containing the data to send. It must be
+		either a string or a byte vector (either one is acceptable
+		regardless of the stream format).</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>size</term>
+
+	      <listitem>
+		<para>Number of bytes to send</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>remote-host</term>
+
+	      <listitem>
+		<para>The host to send the packet to, in any format
+		acceptable to lookup-hostname. The default is the remote
+		host specified in the call to make-socket.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>remote-port</term>
+
+	      <listitem>
+		<para>The port to send the packet to, in any format
+		acceptable to lookup-port. The default is the remote port
+		specified in the call to make-socket.</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>offset</term>
+
+	      <listitem>
+		<para>The offset in the buffer where the packet data starts</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Send a UDP packet over a socket.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_shutdown">
+	<indexterm zone="f_shutdown">
+	  <primary>shutdown</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SHUTDOWN</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>shutdown</function>
+	  socket &key; direction</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket to shut down (typically a tcp-stream)</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>direction</term>
+
+	      <listitem>
+		<para>One of :input to disallow further input, or :output to
+		disallow further output.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Shuts down part of a bidirectional connection. This is
+	  useful if e.g. you need to read responses after sending an
+	  end-of-file signal.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-os-fd">
+	<indexterm zone="f_socket-os-fd">
+	  <primary>socket-os-fd</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-OS-FD</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-os-fd</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns the native OS&#39;s representation of the socket, or
+	  NIL if the socket is closed. On Unix, this is the Unix &#39;file
+	  descriptor&#39;, a small non-negative integer. Note that it is
+	  rather dangerous to mess around with tcp-stream fd&#39;s, as there
+	  is all sorts of buffering and asynchronous I/O going on above the
+	  OS level. listener-socket and udp-socket fd&#39;s are safer to
+	  mess with directly as there is less magic going on.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_remote-host">
+	<indexterm zone="f_remote-host">
+	  <primary>remote-host</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>REMOTE-HOST</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>remote-host</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns the 32-bit unsigned IP address of the remote host,
+	  or NIL if the socket is not connected.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_remote-port">
+	<indexterm zone="f_remote-port">
+	  <primary>remote-port</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>REMOTE-PORT</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>remote-port</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns the remote port number, or NIL if the socket is not
+	  connected.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_local-host">
+	<indexterm zone="f_local-host">
+	  <primary>local-host</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>LOCAL-HOST</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>local-host</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns 32-bit unsigned IP address of the local host.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_local-port">
+	<indexterm zone="f_local-port">
+	  <primary>local-port</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>LOCAL-PORT</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>local-port</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns the local port number</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-address-family">
+	<indexterm zone="f_socket-address-family">
+	  <primary>socket-address-family</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-ADDRESS-FAMILY</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-address-family</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns :internet or :file, as appropriate.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-connect">
+	<indexterm zone="f_socket-connect">
+	  <primary>socket-connect</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-CONNECT</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-connect</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns :active for tcp-stream, :passive for
+	  listener-socket, and NIL for udp-socket</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-format">
+	<indexterm zone="f_socket-format">
+	  <primary>socket-format</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-FORMAT</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-format</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Returns the socket format as specified by the :format
+	  argument to make-socket.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-type">
+	<indexterm zone="f_socket-type">
+	  <primary>socket-type</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-TYPE</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-type</function>
+	  socket</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>returns :stream for tcp-stream and listener-socket, and
+	  :datagram for udp-socket.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="c_socket-error">
+	<indexterm zone="c_socket-error">
+	  <primary>socket-error</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-ERROR</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Class</refclass>
+	</refnamediv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>The class of OS errors signaled by socket functions</para>
+	</refsect1>
+
+	<refsect1>
+	  <title>Superclasses</title>
+
+	  <para>simple-error</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-error-code">
+	<indexterm zone="f_socket-error-code">
+	  <primary>socket-error-code</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-ERROR-CODE</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-error-code</function>
+	  socket-error</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket-error</term>
+
+	      <listitem>
+		<para>the condition</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>The OS error code of the error</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-error-identifier">
+	<indexterm zone="f_socket-error-identifier">
+	  <primary>socket-error-identifier</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-ERROR-IDENTIFIER</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-error-identifier</function>
+	  socket-error</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket-error</term>
+
+	      <listitem>
+		<para>the condition</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>A symbol representing the error code in a more
+	  OS-independent way.</para>
+
+	  <para>One of: :address-in-use :connection-aborted :no-buffer-space
+	  :connection-timed-out :connection-refused :host-unreachable
+	  :host-down :network-down :address-not-available :network-reset
+	  :connection-reset :shutdown :access-denied or :unknown.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="f_socket-error-situation">
+	<indexterm zone="f_socket-error-situation">
+	  <primary>socket-error-situation</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>SOCKET-ERROR-SITUATION</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>socket-error-situation</function>
+	  socket-error</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket-error</term>
+
+	      <listitem>
+		<para>the condition</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>A string describing the context where the error happened. On
+	  Linux, this is the name of the system call which returned the
+	  error.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="o_close">
+	<indexterm zone="o_close">
+	  <primary>close</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>CLOSE</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Method</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>close</function>
+	  (socket socket) &key; abort</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>socket</term>
+
+	      <listitem>
+		<para>The socket to close</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>abort</term>
+
+	      <listitem>
+		<para>If false (the default), closes the socket in an
+		orderly fashion, finishing up any buffered pending I/O,
+		before closing the connection. If true, aborts/ignores
+		pending I/O. (For listener and udp sockets, this argument is
+		effectively ignored since there is never any buffered I/O to
+		clean up).</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>The close generic function can be applied to sockets. It
+	  releases the operating system resources associated with the
+	  socket.</para>
+	</refsect1>
+      </refentry>
+
+      <refentry id="m_with-open-socket">
+	<indexterm zone="m_with-open-socket">
+	  <primary>with-open-socket</primary>
+	</indexterm>
+	<refnamediv>
+	  <refname>WITH-OPEN-SOCKET</refname>
+	  <refpurpose></refpurpose>
+	  <refclass>Macro</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis><function>with-open-socket</function>
+	  (var . make-socket-args) &body; body</synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+
+	  <variablelist>
+	    <varlistentry>
+	      <term>var</term>
+
+	      <listitem>
+		<para>variable to bind</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>make-socket-args</term>
+
+	      <listitem>
+		<para>arguments suitable for passing to make-socket</para>
+	      </listitem>
+	    </varlistentry>
+
+	    <varlistentry>
+	      <term>body</term>
+
+	      <listitem>
+		<para>body to execute</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>executes body with var bound to the result of applying
+	  make-socket to make-socket-args. The socket gets closed on exit.</para>
+	</refsect1>
+      </refentry>
+    </sect1>
+  </chapter>
Index: /branches/new-random/doc/src/streams.xml
===================================================================
--- /branches/new-random/doc/src/streams.xml	(revision 13309)
+++ /branches/new-random/doc/src/streams.xml	(revision 13309)
@@ -0,0 +1,1087 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="Streams">
+  <title>Streams</title>
+
+  <sect1 id="CCL-Stream-Extensions">
+    <title>Stream Extensions</title>
+
+    <sect2><title>Stream External Encoding</title>
+    <para>&CCL; streams have an external-encoding attribute that
+    may be read using
+    <function>STREAM-EXTERNAL-ENCODING</function> and set using <function>(SETF
+    STREAM-EXTERNAL-ENCODING)</function>.
+    </para>
+    </sect2>
+
+    <sect2 id="Additional-Open-Keywords">
+      <title>Additional keywords for OPEN and MAKE-SOCKET</title>
+      <para><function>OPEN</function> and
+      <function>MAKE-SOCKET</function> have each been extended to take
+      the additional keyword arguments: <literal>:CLASS</literal>,
+      <literal>:SHARING</literal>, and
+      <literal>:BASIC</literal>.</para>
+
+    <variablelist>
+      <varlistentry>
+	<term><literal>:CLASS</literal></term>
+	<listitem>
+	  <para>A symbol that names the desired class of the stream.
+	  The specified class must inherit from
+	  <literal>FILE-STREAM</literal> for
+	  <function>OPEN</function>.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry id="Stream-SHARING">
+	<term><literal>:SHARING</literal></term>
+	<listitem>
+	  <para>Specifies how a stream can be used by multiple
+	  threads.  The possible values are:
+	  <literal>:PRIVATE</literal>, <literal>:LOCK</literal> and
+	  <literal>:EXTERNAL</literal>. <literal>:PRIVATE</literal> is
+	  the default.  <literal>NIL</literal> is also accepted as a
+	  synonym for <literal>:EXTERNAL</literal>.</para>
+	  <variablelist>
+	    <varlistentry>
+	      <term><literal>:PRIVATE</literal></term>
+	      <listitem>
+		<para>Specifies that the stream can only be accessed
+		by the thread that created it.  This is the default.
+		(There was some discussion on openmcl-devel about the
+		idea of "transferring ownership" of a stream; this has
+		not yet been implemented.)  Attempts to do I/O on a
+		stream with :PRIVATE sharing from a thread other than
+		the stream's owner yield an error.</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term><literal>:LOCK</literal></term>
+	      <listitem>
+		<para>Specifies that all access to the stream require
+		the calling thread to obtain a lock. There are
+		separate "read" and "write" locks for IO streams.
+		This makes it possible for instance, for one thread to
+		read from such a stream while another thread writes to
+		it.  (see also <xref linkend="f_make-read-write-lock"/>
+		<xref linkend="m_with-read-lock"/> <xref
+		linkend="m_with-write-lock"/>)</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term><literal>:EXTERNAL</literal></term>
+	      <listitem>
+		<para>Specifies that I/O primitives enforce no access
+		protocol.  This may be appropriate for some types of
+		application which can control stream access via
+		application-level protocols.  Note that since even the
+		act of reading from a stream changes its internal
+		state (and simultaneous access from multiple threads
+		can therefore lead to corruption of that state), some
+		care must be taken in the design of such protocols.</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><literal>:BASIC</literal></term>
+	<listitem>
+	  <para>A boolean that indicates whether or not the stream is
+	  a Gray stream, i.e. whether or not the stream is an instance
+	  of <literal>FUNDAMENTAL-STREAM</literal> or
+	  <literal>CCL::BASIC-STREAM</literal>(see <xref
+	  linkend="Basic-Versus-Fundamental-Streams"/>).  Defaults to
+	  <literal>T</literal>.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+
+    </sect2>
+
+    <sect2 id="Basic-Versus-Fundamental-Streams">
+      <title>Basic Versus Fundamental Streams</title>
+      <para>Gray streams (see <xref
+      linkend="Creating-Your-Own-Stream-Classes-with-Gray-Streams"/>)
+      all inherit from <literal>FUNDAMENTAL-STREAM</literal> whereas
+      basic streams inherit from <literal>CCL::BASIC-STREAM</literal>.
+      The tradeoff between FUNDAMENTAL and BASIC streams is entirely
+      between flexibility and performance, potential or actual.  I/O
+      primitives can recognize BASIC-STREAMs and exploit knowledge of
+      implementation details. FUNDAMENTAL stream classes can be
+      subclassed and extended in a standard way (the Gray streams
+      protocol).</para>
+
+      <para>For existing stream classes (FILE-STREAMs, SOCKETs, and
+      the internal CCL::FD-STREAM classes used to implement file
+      streams and sockets), a lot of code can be shared between the
+      FUNDAMENTAL and BASIC implementations.  The biggest difference
+      should be that that code can be reached from I/O primitives like
+      READ-CHAR without going through some steps that're there to
+      support generality and extensibility, and skipping those steps
+      when that support isn't needed can improve I/O performance.
+      </para>
+
+      <para>The Gray stream method
+      <function>STREAM-READ-CHAR</function> should work on appropriate
+      <literal>BASIC-STREAM</literal>s.  (There may still be cases
+      where such methods are undefined; such cases should be
+      considered bugs.)  It is not guaranteed that Gray stream methods
+      would ever be called by I/O primitives to read a character from
+      a <literal>BASIC-STREAM</literal>, though there are still cases
+      where this happens.</para>
+
+      <para>A simple loop reading 2M characters from a text file runs
+      about 10X faster when the file is opened the new defaults
+      <literal>(:SHARING :PRIVATE :BASIC T)</literal> than it had
+      before these changes were made.  That sounds good, until one
+      realizes that the "equivalent" C loop can be about 10X faster
+      still ...</para>
+    </sect2>
+
+
+    <sect2 id="Stream-Timeouts-And-Deadlines">
+      <title>Stream Timeouts and Deadlines</title>
+      <indexterm>
+        <primary>stream-input-timeout</primary>
+      </indexterm>
+      <indexterm>
+        <primary>stream-output-timeout</primary>
+      </indexterm>
+      <indexterm>
+        <primary>stream-deadline</primary>
+      </indexterm>
+      <indexterm>
+        <primary>input-timeout</primary>
+      </indexterm>
+      <indexterm>
+        <primary>output-timeout</primary>
+      </indexterm>
+      <indexterm>
+        <primary>communication-deadline-expired</primary>
+      </indexterm>
+      <para>A stream that is associated with a file descriptor has
+        attributes and accessors:
+        <function>STREAM-INPUT-TIMEOUT</function>,
+        <function>STREAM-OUTPUT-TIMEOUT</function>, and
+        <function>STREAM-DEADLINE</function>.  All three accessors have
+        corresponding <function>SETF</function> methods.
+        <function>STREAM-INPUT-TIMEOUT</function> and
+        <function>STREAM-OUTPUT-TIMEOUT</function> are specified in
+        seconds and can be any positive real number less than one million.
+        When a timeout is set and the corresponding I/O operation takes
+        longer than the specified interval, an error is signalled.  The
+        error is <literal>INPUT-TIMEOUT</literal> for input and
+        <literal>OUTPUT-TIMEOUT</literal> for output.
+        <literal>STREAM-DEADLINE</literal> specifies an absolute time in
+        internal-time-units.  If an I/O operation on the stream does not
+        complete before the deadline then a
+        <literal>COMMUNICATION-DEADLINE-EXPIRED</literal> error is
+        signalled.  A deadline takes precedence over any
+        input/output timeouts that may be set.</para>
+    </sect2>
+
+    <sect2 id="Open-File-Streams">
+      <title>Open File Streams</title>
+      <para>Historically, &CCL; and MCL maintained a list of open
+        file streams in the value of
+        <literal>CCL:*OPEN-FILE-STREAMS*</literal>.  This functionality
+        has been replaced with the thread-safe function:
+        <literal>CCL:OPEN-FILE-STREAMS</literal> and its two helper
+        functions: <literal>CCL:NOTE-OPEN-FILE-STREAM</literal> and
+        <literal>CCL:REMOVE-OPEN-FILE-STREAM</literal>.  Maintaining
+        this list helps to ensure that streams get closed in an orderly
+        manner when the lisp exits.</para>
+
+      <refentry id="f_open-file-streams">
+	    <indexterm zone="f_open-file-streams">
+	      <primary>open-file-streams</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>OPEN-FILE-STREAMS</refname>
+	      <refpurpose>Returns the list of file streams that are currently open.</refpurpose>
+	      <refclass>Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis>
+	        <function>open-file-streams</function>
+	        => stream-list
+	      </synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Values</title>
+	      
+	      <variablelist>
+	        <varlistentry>
+	          <term>stream-list</term>
+	          <listitem>
+		        <para>A list of open file streams.  This is a copy of
+		          an internal list so it may be destructively
+		          modified without ill effect.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+	      <para>Returns a list of open file streams.</para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>See Also</title>	 
+	      <simplelist type="inline">
+	        <member><xref linkend="f_note-open-file-stream"/></member>
+	        <member><xref linkend="f_remove-open-file-stream"/></member>
+	      </simplelist>
+	    </refsect1>
+      </refentry>
+
+      <refentry id="f_note-open-file-stream">
+	    <indexterm zone="f_note-open-file-stream">
+	      <primary>note-open-file-stream</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>NOTE-OPEN-FILE-STREAM</refname>
+	      <refpurpose>Adds a file stream to the internal list of open
+	        file streams that is returned by
+	        <function>note-open-file-stream</function>.</refpurpose>
+	      <refclass>Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis>
+	        <function>note-open-file-stream</function>
+	        file-stream
+	      </synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments</title>
+	      
+	      <variablelist>
+	        <varlistentry>
+	          <term>file-stream</term>
+	          <listitem>
+		        <para>A file stream.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+	      <para>Adds a file stream to the internal list of open
+	        file streams that is returned by
+	        <function>open-file-streams</function>.  This function is
+	        thread-safe.  It will usually only be called from custom
+	        stream code when a file-stream is created.</para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>See Also</title>	 
+	      <simplelist type="inline">
+	        <member><xref linkend="f_open-file-streams"/></member>
+	        <member><xref linkend="f_remove-open-file-stream"/></member>
+	      </simplelist>
+	    </refsect1>
+
+      </refentry>
+
+      <refentry id="f_remove-open-file-stream">
+	    <indexterm zone="f_remove-open-file-stream">
+	      <primary>remove-open-file-stream</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>REMOVE-OPEN-FILE-STREAM</refname>
+	      <refpurpose>Removes file stream from the internal list of open
+	        file streams that is returned by
+	        <function>open-file-streams</function>.</refpurpose>
+	      <refclass>Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis>
+	        <function>remove-open-file-stream</function>
+	        file-stream
+	      </synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments</title>
+	      
+	      <variablelist>
+	        <varlistentry>
+	          <term>file-stream</term>
+	          <listitem>
+		        <para>A file stream.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+	      <para>Remove file stream from the internal list of open file
+	        streams that is returned by
+	        <function>open-file-streams</function>.  This function is
+	        thread-safe.  It will usually only be called from custom
+	        stream code when a file-stream is closed.</para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>See Also</title>	 
+	      <simplelist type="inline">
+	        <member><xref linkend="f_open-file-streams"/></member>
+	        <member><xref linkend="f_note-open-file-stream"/></member>
+	      </simplelist>
+	    </refsect1>
+
+      </refentry>
+
+    </sect2>
+  </sect1>
+
+  <sect1 id="Creating-Your-Own-Stream-Classes-with-Gray-Streams">
+    <title>Creating Your Own Stream Classes with Gray Streams</title>
+
+    <sect2 id="Streams-Overview">
+      <title>Overview</title>
+      <para>This sect1 is still being written and revised, because
+        it is woefully incomplete.  The dictionary section currently
+        only lists a couple functions.  Caveat lector.</para>
+      <para>Gray streams are an extension to Common Lisp.  They were
+        proposed for standardization by David Gray (the astute reader
+        now understands their name) quite some years ago, but not
+        accepted, because they had not been tried sufficiently to find
+        conceptual problems with them.</para>
+      <para>They have since been implemented by quite a few modern
+        Lisp implementations.  However, they do indeed have some
+        inadequacies, and each implementation has addressed these in
+        different ways.  The situation today is that it's difficult to
+        even find out how to get started using Gray streams.  This is
+        why standards are important.</para>
+      <para>Here's a list of some classes which you might wish for
+        your new stream class to inherit from:</para>
+      
+      <simplelist>
+	    <member>fundamental-stream</member>
+	    <member>fundamental-input-stream</member>
+	    <member>fundamental-output-stream</member>
+	    <member>fundamental-character-stream</member>
+	    <member>fundamental-binary-stream</member>
+	    <member>fundamental-character-input-stream</member>
+	    <member>fundamental-character-output-stream</member>
+	    <member>fundamental-binary-input-stream</member>
+	    <member>fundamental-binary-output-stream</member>
+	    <member>ccl::buffered-stream-mixin</member>
+	    <member>ccl::buffered-input-stream-mixin</member>
+	    <member>ccl::buffered-output-stream-mixin</member>
+	    <member>ccl::buffered-io-stream-mixin</member>
+	    <member>ccl::buffered-character-input-stream-mixin</member>
+	    <member>ccl::buffered-character-output-stream-mixin</member>
+	    <member>ccl::buffered-character-io-stream-mixin</member>
+	    <member>ccl::buffered-binary-input-stream-mixin</member>
+	    <member>ccl::buffered-binary-output-stream-mixin</member>
+	    <member>ccl::buffered-binary-io-stream-mixin</member>
+	    <member>file-stream</member>
+	    <member>file-input-stream</member>
+	    <member>file-output-stream</member>
+	    <member>file-io-stream</member>
+	    <member>file-character-input-stream</member>
+	    <member>file-character-output-stream</member>
+	    <member>file-character-io-stream</member>
+	    <member>file-binary-input-stream</member>
+	    <member>file-binary-output-stream</member>
+	    <member>file-binary-io-stream</member>
+	    <member>ccl::fd-stream</member>
+	    <member>ccl::fd-input-stream</member>
+	    <member>ccl::fd-output-stream</member>
+	    <member>ccl::fd-io-stream</member>
+	    <member>ccl::fd-character-input-stream</member>
+	    <member>ccl::fd-character-output-stream</member>
+	    <member>ccl::fd-character-io-stream</member>
+	    <member>ccl::fd-binary-input-stream</member>
+	    <member>ccl::fd-binary-output-stream</member>
+	    <member>ccl::fd-binary-io-stream</member>
+      </simplelist>
+
+      <para>All of these are defined in ccl/level-1/l1-streams.lisp,
+        except for the ccl:file-* ones, which are in
+        ccl/level-1/l1-sysio.lisp.</para>
+      <para>According to the original Gray streams proposal, you
+        should inherit from the most specific of the fundamental-*
+        classes which applies.  Using &CCL;, though, if you want
+        buffering for better performance, which, unless you know of some
+        reason you wouldn't, you do, you should instead inherit from the
+        appropriate ccl::buffered-* class The buffering you get this way
+        is exactly the same as the buffering which is used on ordinary,
+        non-Gray streams, and force-output will work properly on
+        it.</para>
+      <para>Notice that -mixin suffix in the names of all the
+        ccl::buffered-* classes?  The suffix means that this class is
+        not "complete" by itself; you still need to inherit from a
+        fundamental-* stream, even if you also inherit from a *-mixin
+        stream.  You might consider making your own class like this.
+        ....  Except that they do inherit from the fundamental-*
+        streams, that's weird.</para>
+      <para>If you want to be able to create an instance of your class
+        with the :class argument to (open) and (with-open-file), you
+        should make it inherit from one of the file-* classes.  If you
+        do this, it's not necessary to inherit from any of the other
+        classes (though it won't hurt anything), since the file-*
+        classes already do.</para>
+      <para>When you inherit from the file-* classes, you can use
+        (call-next-method) in any of your methods to get the standard
+        behavior.  This is especially useful if you want to create a
+        class which performs some simple filtering operation, such as
+        changing everything to uppercase or to a different character
+        encoding.  If you do this, you will definitely need to
+        specialize ccl::select-stream-class.  Your method on
+        ccl::stream-select-class should accept an instance of the class,
+        but pay no attention to its contents, and return a symbol naming
+        the class to actually be instantiated.</para>
+      <para>If you need to make your functionality generic across all
+        the different types of stream, probably the best way to
+        implement it is to make it a mixin, define classes with all the
+        variants of input, output, io, character, and binary, which
+        inherit both from your mixin and from the appropriate other
+        class, then define a method on ccl::select-stream-class which
+        chooses from among those classes.</para>
+      <para>Note that some of these classes are internal to the CLL
+        package.  If you try to inherit from those ones without the
+        ccl:: prefix, you'll get an error which may confuse you, calling
+        them "forward-referenced classes".  That just means you used the
+        wrong symbol, so add the prefix.</para>
+      <para>Here's a list of some generic functions which you might
+        wish to specialize for your new stream class, and which ought to
+        be documented at some point.</para>
+      <simplelist>
+	    <member>stream-direction stream =></member>
+	    <member>stream-device stream direction =></member>
+	    <member>stream-length stream &optional; new =></member>
+	    <member>stream-position stream &optional; new =></member>
+	    <member>streamp stream => boolean</member>
+	    <member>stream-write-char output-stream char =></member>
+	    <member>stream-write-entire-string output-stream string =></member>
+	    <member>stream-read-char input-stream =></member>
+	    <member>stream-unread-char input-stream char =></member>
+	    <member>stream-force-output output-stream => nil</member>
+	    <member>stream-maybe-force-output output-stream => nil</member>
+	    <member>stream-finish-output output-stream => nil</member>
+	    <member>stream-clear-output output-stream => nil</member>
+	    <member>close stream &key; abort => boolean</member>
+	    <member>stream-fresh-line stream => t</member>
+	    <member>stream-line-length stream => length</member>
+	    <member>interactive-stream-p stream => boolean</member>
+	    <member>stream-clear-input input-stream => nil</member>
+	    <member>stream-listen input-stream => boolean</member>
+	    <member>stream-filename stream => string</member>
+	    <member>ccl::select-stream-class instance in-p out-p char-p =>
+	      class</member>
+      </simplelist>
+      <para>The following functions are standard parts of Common Lisp, but
+        behave in special ways with regard to Gray streams.</para>
+      <simplelist>
+	    <member>open-stream-p stream => generalized-boolean</member>
+	    <member>input-stream-p stream => generalized-boolean</member>
+	    <member>output-stream-p stream => generalized-boolean</member>
+	    <member>stream-element-type stream =></member>
+	    <member>stream-error-stream =></member>
+	    <member>open</member>
+	    <member>close</member>
+	    <member>with-open-file</member>
+      </simplelist>
+
+      <para>Specifically, (open) and (with-open-file) accept a new
+        keyword argument, :class, which may be a symbol naming a class;
+        the class itself; or an instance of it.  The class so given must
+        be a subtype of 'stream, and an instance of it with no
+        particular contents will be passed to ccl::select-stream-class
+        to determine what class to actually instantiate.</para>
+      <para>The following are standard, and do not behave specially
+        with regard to Gray streams, but probably should.</para>
+      <simplelist>
+	    <member>stream-external-format</member>
+      </simplelist>
+    </sect2>
+
+    <sect2 id="Extending-READ-SEQUENCE-and-WRITE-SEQUENCE">
+      <title>Extending READ-SEQUENCE and WRITE-SEQUENCE</title>
+
+      <sect3 id="extending-read-write-overview">
+	    <title>Overview</title>
+	    <para>The "Gray Streams" API is based on an informal proposal that was
+	      made before ANSI CL adopted the READ-SEQUENCE and WRITE-SEQUENCE
+	      functions; as such, there is no "standard" way for the author of a Gray
+	      stream class to improve the performance of these functions by exploiting
+	      knowledge of the stream's internals (e.g., the buffering mechanism it
+	      uses.)</para>
+	    <para>In the absence of any such knowledge, READ-SEQUENCE and
+	      WRITE-SEQUENCE are effectively just convenient shorthand for a
+	      loop which calls READ-CHAR/READ-BYTE/WRITE-CHAR/WRITE-BYTE as
+	      appropriate. The mechanism described below allows subclasses
+	      of FUNDAMENTAL-STREAM to define more specialized (and
+	      presumably more efficient) behavior.</para>
+      </sect3>
+
+      <sect3 id="Notes">
+	    <title>Notes</title>
+	    <para>READ-SEQUENCE and WRITE-SEQUENCE do a certain amount of
+	      sanity-checking and normalization of their arguments before
+	      dispatching to one of the methods above. If an individual
+	      method can't do anything particularly clever, CALL-NEXT-METHOD
+	      can be used to handle the general case.</para>
+      </sect3>
+
+      <sect3 id="Example">
+	    <title>Example</title>
+	    <programlisting>
+(defclass my-string-input-stream (fundamental-character-input-stream)
+  ((string :initarg :string :accessor my-string-input-stream-string)
+   (index :initform 0 :accessor my-string-input-stream-index)
+   (length)))
+
+(defmethod stream-read-vector ((stream my-string-input-stream) vector start end)
+  (if (not (typep vector 'simple-base-string))
+      (call-next-method)
+      (with-slots (string index length)
+	      (do* ((outpos start (1+ outpos)))
+               ((or (= outpos end)
+                    (= index length))
+                outpos))
+        (setf (schar vector outpos)
+              (schar string index))
+        (incf index)))))
+	    </programlisting>
+      </sect3>
+    </sect2>
+
+    <sect2 id="Multibyte-I-O">
+      <title>Multibyte I/O</title>
+      <para>All heap-allocated objects in &CCL; that cannot contain
+        pointers to lisp objects are represented as
+        <emphasis>ivectors</emphasis>. &CCL; provides low-level
+        functions, and , to efficiently transfer data between buffered
+        streams and ivectors. There's some overlap in functionality
+        between the functions described here and the ANSI CL
+        READ-SEQUENCE and WRITE-SEQUENCE functions.</para>
+      <para>As used here, the term "octet" means roughly the same
+        thing as the term "8-bit byte". The functions described below
+        transfer a specified sequence of octets between a buffered
+        stream and an ivector, and don't really concern themselves with
+        higher-level issues (like whether that octet sequence is within
+        bounds or how it relates to the logical contents of the
+        ivector.) For these reasons, these functions are generally less
+        safe and more flexible than their ANSI counterparts.</para>
+    </sect2>
+
+    <sect2 id="Gray-Streams-Dictionary">
+      <title>Gray Streams Dictionary</title>
+      <refentry id="f_stream-read-list">
+	    <indexterm zone="f_stream-read-list">
+	      <primary>stream-read-list</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL:STREAM-READ-LIST</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Generic Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>stream-read-list</function>
+	        stream list count</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments and Values</title>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term>stream</term>
+
+	          <listitem>
+		        <para>a stream, presumably a fundamental-input-stream.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>list</term>
+
+	          <listitem>
+		        <para>a list. When a STREAM-READ-LIST method is called by
+		          READ-SEQUENCE, this argument is guaranteed to be a proper
+		          list.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>count</term>
+
+	          <listitem>
+		        <para>a non-negative integer. When a STREAM-READ-LIST method
+		          is called by READ-SEQUENCE, this argument is guaranteed not
+		          to be greater than the length of the list.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>Should try to read up to count elements from stream into the
+	        list list, returning the number of elements actually read (which
+	        may be less than count in case of a premature end-of-file.)</para>
+	    </refsect1>
+      </refentry>
+
+      <refentry id="f_stream-write-list">
+	    <indexterm zone="f_stream-write-list">
+	      <primary>stream-write-list</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL:STREAM-WRITE-LIST</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Generic Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>stream-write-list</function>
+	        stream list count</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments and Values</title>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term>stream</term>
+
+	          <listitem>
+		        <para>a stream, presumably a fundamental-output-stream.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>list</term>
+
+	          <listitem>
+		        <para>a list. When a STREAM-WRITE-LIST method is called by
+		          WRITE-SEQUENCE, this argument is guaranteed to be a proper
+		          list.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>count</term>
+
+	          <listitem>
+		        <para>a non-negative integer. When a STREAM-WRITE-LIST
+		          method is called by WRITE-SEQUENCE, this argument is
+		          guaranteed not to be greater than the length of the list.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>should try to write the first count elements of list to
+	        stream. The return value of this method is ignored.</para>
+	    </refsect1>
+      </refentry>
+
+      <refentry id="f_stream-read-vector">
+	    <indexterm zone="f_stream-read-vector">
+	      <primary>stream-read-vector</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL:STREAM-READ-VECTOR</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Generic Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>stream-read-vector</function>
+	        stream vector start end</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments and Values</title>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term>stream</term>
+
+	          <listitem>
+		        <para>a stream, presumably a fundamental-input-stream</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>vector</term>
+
+	          <listitem>
+		        <para>a vector. When a STREAM-READ-VECTOR method is called
+		          by READ-SEQUENCE, this argument is guaranteed to be a simple
+		          one-dimensional array.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>start</term>
+
+	          <listitem>
+		        <para>a non-negative integer. When a STREAM-READ-VECTOR
+		          method is called by READ-SEQUENCE, this argument is
+		          guaranteed to be no greater than end and not greater than
+		          the length of vector.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>end</term>
+
+	          <listitem>
+		        <para>a non-negative integer. When a STREAM-READ-VECTOR
+		          method is called by READ-SEQUENCE, this argument is
+		          guaranteed to be no less than end and not greater than the
+		          length of vector.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>should try to read successive elements from stream into
+	        vector, starting at element start (inclusive) and continuing
+	        through element end (exclusive.) Should return the index of the
+	        vector element beyond the last one stored into, which may be less
+	        than end in case of premature end-of-file.</para>
+	    </refsect1>
+      </refentry>
+
+      <refentry id="f_stream-write-vector">
+	    <indexterm zone="f_stream-write-vector">
+	      <primary>stream-write-vector</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL:STREAM-WRITE-VECTOR</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Generic Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>stream-write-vector</function>
+	        stream vector start end</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Arguments and Values</title>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term>stream</term>
+
+	          <listitem>
+		        <para>a stream, presumably a fundamental-output-stream</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>vector</term>
+
+	          <listitem>
+		        <para>a vector. When a STREAM-WRITE-VECTOR method is called
+		          by WRITE-SEQUENCE, this argument is guaranteed to be a
+		          simple one-dimensional array.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>start</term>
+
+	          <listitem>
+		        <para>a non-negative integer. When a STREAM-WRITE-VECTOR
+		          method is called by WRITE-SEQUENCE, this argument is
+		          guaranteed to be no greater than end and not greater than
+		          the length of vector.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>end</term>
+
+	          <listitem>
+		        <para>a non-negative integer. When a STREAM-WRITE-VECTOR
+		          method is called by WRITE-SEQUENCE, this argument is
+		          guaranteed to be no less than end and not greater than the
+		          length of vector.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>should try to write successive elements of vector to stream,
+	        starting at element start (inclusive) and continuing through
+	        element end (exclusive.)</para>
+	    </refsect1>
+      </refentry>
+
+      <refentry id="f_stream-device">
+	    <indexterm zone="f_stream-device">
+	      <primary>stream-device</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>CCL::STREAM-DEVICE</refname>
+	      <refpurpose>Returns the OS file descriptor associated with a
+	        given lisp stream.</refpurpose>
+	      <refclass>Generic Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>ccl::stream-device</function>
+	        s direction</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Method Signatures</title>
+
+	      <synopsis><function>ccl::stream-device</function>
+	        (s stream) direction => fd</synopsis>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Arguments and Values</title>
+	      
+	      <variablelist>
+	        <varlistentry>
+	          <term>s</term>
+	          <listitem>
+		        <para>a stream.</para>
+	          </listitem>
+	        </varlistentry>
+	        <varlistentry>
+	          <term>direction</term>
+	          <listitem>
+		        <para>either :INPUT or :OUTPUT.</para>
+	          </listitem>
+	        </varlistentry>
+	        <varlistentry>
+	          <term>fd</term>
+	          <listitem>
+		        <para>a file descriptor, which is a non-negative integer
+		          used by the OS to refer to an open file, socket, or similar
+		          I/O connection.  NIL if there is no file descriptor associated
+		          with <varname>s</varname> in the direction given by
+		          <varname>direction</varname>.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>Returns the file descriptor associated with
+	        <varname>s</varname> in the direction given by
+	        <varname>direction</varname>.  It is necessary to specify
+	        <varname>direction</varname> because the input and output
+	        file descriptors may be different; the most common case is when
+	        one of them has been redirected by the Unix shell.</para>
+	    </refsect1>
+      </refentry>
+
+      <refentry id="f_stream-read-ivector">
+	    <indexterm zone="f_stream-read-ivector">
+	      <primary>stream-read-ivector</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>STREAM-READ-IVECTOR</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Generic Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>stream-read-ivector</function>
+	        stream ivector start-octet max-octets</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>Reads up to max-octets octets from stream into ivector,
+	        storing them at start-octet. Returns the number of octets actually
+	        read.</para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Arguments</title>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term>stream</term>
+
+	          <listitem>
+		        <para>An input stream. The method defined on
+		          BUFFERED-INPUT-STREAMs requires that the size in octets of
+		          an instance of the stream's element type is 1.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>ivector</term>
+
+	          <listitem>
+		        <para>Any ivector.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>start-octet</term>
+
+	          <listitem>
+		        <para>A non-negative integer.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>max-octets</term>
+
+	          <listitem>
+		        <para>A non-negative integer. The return value may be less
+		          than the value of this parameter if EOF was encountered.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+      </refentry>
+
+      <refentry id="f_stream-write-ivector">
+	    <indexterm zone="f_stream-write-ivector">
+	      <primary>stream-write-ivector</primary>
+	    </indexterm>
+
+	    <refnamediv>
+	      <refname>STREAM-WRITE-IVECTOR</refname>
+	      <refpurpose></refpurpose>
+	      <refclass>Generic Function</refclass>
+	    </refnamediv>
+
+	    <refsynopsisdiv>
+	      <synopsis><function>stream-write-ivector stream</function>
+	        ivector start-octet max-octets</synopsis>
+	    </refsynopsisdiv>
+
+	    <refsect1>
+	      <title>Description</title>
+
+	      <para>Writes max-octets octets to stream from ivector, starting at
+	        start-octet. Returns max-octets.</para>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Arguments</title>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term>stream</term>
+
+	          <listitem>
+		        <para>An input stream. The method defined on
+		          BUFFERED-OUTPUT-STREAMs requires that the size in octets of
+		          an instance of the stream's element type is 1.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>ivector</term>
+
+	          <listitem>
+		        <para>Any ivector</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>start-octet</term>
+
+	          <listitem>
+		        <para>A non-negative integer.</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>max-octet</term>
+
+	          <listitem>
+		        <para>A non-negative integer.</para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </refsect1>
+
+	    <refsect1>
+	      <title>Examples</title>
+
+	      <programlisting format="linespecific">
+;;; Write the contents of a (SIMPLE-ARRAY(UNSIGNED-BYTE 16) 3) 
+;;; to a character file stream. Read back the characters.
+(let* ((a (make-array 3 
+                      :element-type '(unsigned-byte 16)
+                      :initial-contents '(26725 27756 28449))))
+  (with-open-file (s "junk"
+                     :element-type 'character
+                     :direction :io
+                     :if-does-not-exist :create
+                     :if-exists :supersede)
+    ;; Write six octets (three elements).
+    (stream-write-ivector s a 0 6)
+    ;; Rewind, then read a line
+    (file-position s 0)
+    (read-line s)))
+
+;;; Write a vector of DOUBLE-FLOATs. Note that (to maintain
+;;; alignment) there are 4 octets of padding before the 0th 
+;;; element of a (VECTOR DOUBLE-FLOAT).
+;;; (Note that (= (- arch::misc-dfloat-offset 
+;;;                  arch::misc-data-offset) 4))
+(defun write-double-float-vector
+    (stream vector &#38;key (start 0) (end (length vector)))
+     (check-type vector (vector double-float))
+     (let* ((start-octet (+ (* start 8) 
+                            (- arch::misc-dfloat-offset
+                               arch::misc-data-offset)))
+	        (num-octets (* 8 (- end start))))
+       (stream-write-ivector stream vector start-octet num-octets)))
+          </programlisting>
+	    </refsect1>
+      </refentry>
+    </sect2>
+  </sect1>
+</chapter>
Index: /branches/new-random/doc/src/templates/function
===================================================================
--- /branches/new-random/doc/src/templates/function	(revision 13309)
+++ /branches/new-random/doc/src/templates/function	(revision 13309)
@@ -0,0 +1,59 @@
+
+      <refentry id="f_[fn-name]">
+	<indexterm zone="f_[fn-name]">
+	  <primary>[fn-name]</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>[FN-NAME]</refname>
+	  <refpurpose>[function purpose]</refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis>
+	    <function>[fn-name]</function>
+	    [arg] &key; [keyword-arg]
+	    => [result]
+	  </synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Arguments and Values</title>
+	  
+	  <variablelist>
+	    <varlistentry>
+	      <term>[arg]</term>
+	      <listitem>
+		<para>[description]</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term>[keyword-arg]</term>
+	      <listitem>
+		<para>[description]</para>
+	      </listitem>
+	    </varlistentry>
+	    <varlistentry>
+	      <term>[result]</term>
+	      <listitem>
+		<para>[description]</para>
+	      </listitem>
+	    </varlistentry>
+	  </variablelist>
+	</refsect1>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>[description]</para>
+	</refsect1>
+
+	<refsect1>
+	  <title>See Also</title>
+	 
+	  <simplelist type="inline">
+	    <member><xref linkend="[ref-id]"/></member>
+	  </simplelist>
+	</refsect1>
+      </refentry>
Index: /branches/new-random/doc/src/threads.xml
===================================================================
--- /branches/new-random/doc/src/threads.xml	(revision 13309)
+++ /branches/new-random/doc/src/threads.xml	(revision 13309)
@@ -0,0 +1,3327 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="Programming-with-Threads">
+  <title>Programming with Threads</title>
+
+  <sect1 id="Threads-overview">
+    <title>Threads Overview</title>
+
+    <para>&CCL; provides facilities which enable multiple threads
+      of execution (<emphasis>threads</emphasis>, sometimes called
+      <emphasis>lightweight processes</emphasis> or just
+      <emphasis>processes</emphasis>, though the latter term shouldn't
+      be confused with the OS's notion of a process) within a lisp
+      session. This document describes those facilities and issues
+      related to multithreaded programming in &CCL;.</para>
+
+    <para>Wherever possible, I'll try to use the term "thread" to
+      denote a lisp thread, even though many of the functions in the
+      API have the word "process" in their name. A
+      <emphasis>lisp-process</emphasis> is a lisp object (of type
+      CCL:PROCESS) which is used to control and communicate with an
+      underlying <emphasis>native thread</emphasis>. Sometimes, the
+      distinction between these two (quite different) objects can be
+      blurred; other times, it's important to maintain.</para>
+    <para>Lisp threads share the same address space, but maintain
+      their own execution context (stacks and registers) and their own
+      dynamic binding context.</para>
+    
+    <para>Traditionally, &CCL;'s threads have been
+      <emphasis>cooperatively scheduled</emphasis>: through a
+      combination of compiler and runtime support, the currently
+      executing lisp thread arranged to be interrupted at certain
+      discrete points in its execution (typically on entry to a
+      function and at the beginning of any looping construct). This
+      interrupt occurred several dozen times per second; in response,
+      a handler function might observe that the current thread had
+      used up its time slice and another function (<emphasis>the lisp
+        scheduler</emphasis>) would be called to find some other thread
+      that was in a runnable state, suspend execution of the current
+      thread, and resume execution of the newly executed thread.  The
+      process of switching contexts between the outgoing and incoming
+      threads happened in some mixture of Lisp and assembly language
+      code; as far as the OS was concerned, there was one native
+      thread running in the Lisp image and its stack pointer and other
+      registers just happened to change from time to time.</para>
+    <para>Under &CCL;'s cooperative scheduling model, it was
+      possible (via the use of the CCL:WITHOUT-INTERRUPTS construct)
+      to defer handling of the periodic interrupt that invoked the
+      lisp scheduler; it was not uncommon to use WITHOUT-INTERRUPTS to
+      gain safe, exclusive access to global data structures. In some
+      code (including much of &CCL; itself) this idiom was very
+      common: it was (justifiably) believed to be an efficient way of
+      inhibiting the execution of other threads for a short period of
+      time.</para>
+
+    <para>The timer interrupt that drove the cooperative scheduler
+      was only able to (pseudo-)preempt lisp code: if any thread
+      called a blocking OS I/O function, no other thread could be
+      scheduled until that thread resumed execution of lisp code. Lisp
+      library functions were generally attuned to this constraint, and
+      did a complicated mixture of polling and "timed blocking" in an
+      attempt to work around it. Needless to say, this code is
+      complicated and less efficient than it might be; it meant that
+      the lisp was a little busier than it should have been when it
+      was "doing nothing" (waiting for I/O to be possible.)</para>
+
+    <para>For a variety of reasons - better utilization of CPU
+      resources on single and multiprocessor systems and better
+      integration with the OS in general - threads in &CCL; 0.14 and
+      later are <emphasis>preemptively scheduled. </emphasis>In this
+      model, lisp threads are native threads and all scheduling
+      decisions involving them are made by the OS kernel. (Those
+      decisions might involve scheduling multiple lisp threads
+      simultaneously on multiple processors on SMP systems.) This
+      change has a number of subtle effects:</para>
+
+    <itemizedlist>
+      <listitem>
+	    <para>it is possible for two (or more) lisp threads to be
+	      executing simultaneously, possibly trying to access and/or
+	      modify the same data structures. Such access really should
+	      have been coordinated through the use of synchronization
+	      objects regardless of the scheduling modeling effect;
+	      preemptively scheduled threads increase the chance of things
+	      going wrong at the wrong time and do not offer
+	      lightweight alternatives to the use of those synchronization
+	      objects.</para>
+	  </listitem>
+      <listitem>
+	    <para>even on a single-processor system, a context switch
+	      can happen on any instruction boundary. Since (in general)
+	      other threads might allocate memory, this means that a GC can
+	      effectively take place at any instruction boundary. That's
+	      mostly an issue for the compiler and runtime system to be
+	      aware of, but it means that certain practices(such as trying
+	      to pass the address of a lisp object to foreign code)that
+	      were always discouraged are now discouraged
+	      ... vehemently.</para>
+	  </listitem>
+      <listitem>
+	    <para>there is no simple and efficient way to "inhibit the
+	      scheduler"or otherwise gain exclusive access to the entire
+	      CPU.</para>
+	  </listitem>
+      <listitem>
+	    <para>There are a variety of simple and efficient ways
+	      to synchronize access to particular data
+	      structures.</para>
+	  </listitem>
+    </itemizedlist>
+    <para>As a broad generalization: code that's been aggressively
+      tuned to the constraints of the cooperative scheduler may need
+      to be redesigned to work well with the preemptive scheduler (and
+      code written to run under &CCL;'s interface to the native
+      scheduler may be less portable to other CL implementations, many
+      of which offer a cooperative scheduler and an API similar to
+      &CCL; (&lt; 0.14) 's.) At the same time, there's a large
+      overlap in functionality in the two scheduling models, and it'll
+      hopefully be possible to write interesting and useful MP code
+      that's largely independent of the underlying scheduling
+      details.</para>
+    <para>The keyword :OPENMCL-NATIVE-THREADS is on *FEATURES* in
+      0.14 and later and can be used for conditionalization where
+      required.</para>
+  </sect1>
+
+  <sect1 id="Intentionally--Missing-Functionality">
+    <title>(Intentionally) Missing Functionality</title>
+    <para>Much of the functionality described above is similar to
+      that provided by &CCL;'s cooperative scheduler, some other
+      parts of which make no sense in a native threads
+      implementation.</para>
+    <itemizedlist>
+      <listitem>
+	    <para>PROCESS-RUN-REASONS and PROCESS-ARREST-REASONS were
+	      SETFable process attributes; each was just a list of
+	      arbitrary tokens. A thread was eligible for scheduling
+	      (roughly equivalent to being "enabled") if its arrest-reasons
+	      list was empty and its run-reasons list was not. I don't
+	      think that it's appropriate to encourage a programming style
+	      in which otherwise runnable threads are enabled and disabled
+	      on a regular basis (it's preferable for threads to wait for
+	      some sort of synchronization event to occur if they can't
+	      occupy their time productively.)</para>
+	  </listitem>
+      <listitem>
+	    <para>There were a number of primitives for maintaining
+	      process queues;that's now the OS's job.</para>
+	  </listitem>
+      <listitem>
+	    <para>Cooperative threads were based on coroutining
+	      primitives associated with objects of type
+	      STACK-GROUP. STACK-GROUPs no longerexist.</para>
+	  </listitem>
+    </itemizedlist>
+  </sect1>
+
+
+  <sect1 id="Implementation-Decisions-and-Open-Questions">
+    <title>Implementation Decisions and Open Questions</title>
+    <sect2 id="Thread-Stack-Sizes">
+      <title>Thread Stack Sizes</title>
+      <para>When you use MAKE-PROCESS to create a thread, you can
+        specify a stack size. &CCL; does not impose a limit on the stack
+        size you choose, but there is some evidence that choosing a
+        stack size larger than the operating system's limit can cause
+        excessive paging activity, at least on some operating
+        systems.</para>
+      <para>The maximum stack size is operating-system-dependent. You
+        can use shell commands to determine what it is on your
+        platform. In bash, use "ulimit -s -H" to find the limit; in
+        tcsh, use "limit -h s".</para>
+      <para>This issue does not affect programs that create threads
+        using the default stack size, which you can do either by
+        specifying no value for the :stack-size argument to
+        MAKE-PROCESS, or by specifying the value
+        CCL::*default-control-stack-size*.</para>
+      <para>If your program creates threads with a specified stack size,
+        and that size is larger than the OS-specified limit, you may want
+        to consider reducing the stack size in order to avoid possible
+        excessive paging activity.</para>
+    </sect2>
+    <sect2>
+      <title> As of August 2003:</title>
+      <itemizedlist>
+        <listitem>
+	      <para>It's not clear that exposing
+	        PROCESS-SUSPEND/PROCESS-RESUME is a good idea: it's not clear
+	        that they offer ways to win, and it's clear that they offer
+	        ways to lose.</para>
+	    </listitem>
+        <listitem>
+	      <para>It has traditionally been possible to reset and enable
+	        a process that's "exhausted" . (As used here, the
+	        term"exhausted" means that the process's initial function
+	        has run and returned and the underlying native thread has
+	        been deallocated.) One of the principal uses of PROCESS-RESET
+	        is to "recycle" threads; enabling an exhausted process
+	        involves creating a new native thread (and stacks and
+	        synchronization objects and ...),and this is the sort of
+	        overhead that such a recycling scheme is seeking to avoid. It
+	        might be worth trying to tighten things up and declare that
+	        it's an error to apply PROCESS-ENABLE to an exhausted thread
+	        (and to make PROCESS-ENABLE detect this error.)</para>
+	    </listitem>
+        <listitem>
+	      <para>When native threads that aren't created by &CCL;
+	        first call into lisp, a "foreign process" is created, and
+	        that process is given its own set of initial bindings and set
+	        up to look mostly like a process that had been created by
+	        MAKE-PROCESS. The life cycle of a foreign process is
+	        certainly different from that of a lisp-created one: it
+	        doesn't make sense to reset/preset/enable a foreign process,
+	        and attempts to perform these operations should be
+	        detected and treated as errors.</para>
+	    </listitem>
+      </itemizedlist>
+    </sect2>
+  </sect1>
+
+
+
+  <sect1 id="Porting-Code-from-the-Old-Thread-Model">
+    <title>Porting Code from the Old Thread Model</title>
+    <para>Older versions of &CCL; used what are often called
+      "user-mode threads", a less versatile threading model which does
+      not require specific support from the operating system.  This
+      section discusses how to port code which was written for that
+      mode.</para>
+    <para>It's hard to give step-by-step instructions; there are certainly
+      a few things that one should look at carefully:</para>
+    <itemizedlist>
+      <listitem>
+	    <para>It's wise to be suspicious of most uses
+	      of WITHOUT-INTERRUPTS; there may be exceptions, but
+	      WITHOUT-INTERRUPTS is often used as shorthand for
+	      WITH-APPROPRIATE-LOCKING. Determining what type of locking
+	      is appropriate and writing the code to implement it is
+	      likely to be straightforward and simple most of the
+	      time.</para>
+	  </listitem>
+      <listitem>
+	    <para>I've only seen one case where a process's "run reasons"
+	      were used to communicate information as well as to control
+	      execution; I don't think that this is a common idiom, but may
+	      be mistaken about that.
+	    </para>
+	  </listitem>
+      <listitem>
+	    <para>It's certainly possible that programs written
+	      for cooperatively scheduled lisps that have run reliably for
+	      a long time have done so by accident: resource-contention
+	      issues tend to be timing-sensitive, and decoupling thread
+	      scheduling from lisp program execution affects timing. I know
+	      that there is or was code in both &CCL; and commercial MCL
+	      that was written under the explicit assumption that certain
+	      sequences of open-coded operations were uninterruptable; it's
+	      certainly possible that the same assumptions have been made
+	      (explicitly or otherwise) by application developers.</para>
+	  </listitem>
+    </itemizedlist>
+  </sect1>
+
+  <sect1 id="Background-Terminal-Input">
+    <title>Background Terminal Input</title>
+
+    <sect2 id="backgrount-ti-overview">
+      <title>Overview</title>
+	  <para>
+	    Unless and until &CCL; provides alternatives (via window
+	    streams, telnet streams, or some other mechanism) all lisp
+	    processes share a common *TERMINAL-IO* stream (and therefore
+	    share *DEBUG-IO*, *QUERY-IO*, and other standard and
+	    internal interactive streams.)</para>
+	  <para>It's anticipated that most lisp processes other than
+	    the "Initial" process run mostly in the background. If a
+	    background process writes to the output side of
+	    *TERMINAL-IO*, that may be a little messy and a little
+	    confusing to the user, but it shouldn't really be
+	    catastrophic. All I/O to &CCL;'s buffered streams goes
+	    thru a locking mechanism that prevents the worst kinds of
+	    resource-contention problems.</para>
+	  <para>Although the problems associated with terminal output
+	    from multiple processes may be mostly cosmetic, the question
+	    of which process receives input from the terminal is likely
+	    to be a great deal more important. The stream locking
+	    mechanisms can make a confusing situation even worse:
+	    competing processes may "steal" terminal input from each
+	    other unless locks are held longer than they otherwise need
+	    to be, and locks can be held longer than they need to be (as
+	    when a process is merely waiting for input to become
+	    available on an underlying file descriptor).</para>
+	  <para>Even if background processes rarely need to
+	    intentionally read input from the terminal, they may still
+	    need to do so in response to errors or other unanticipated
+	    situations. There are tradeoffs involved in any solution to
+	    this problem. The protocol described below allows background
+	    processes which follow it to reliably prompt for and receive
+	    terminal input. Background processes which attempt to
+	    receive terminal input without following this protocol will
+	    likely hang indefinitely while attempting to do so. That's
+	    certainly a harsh tradeoff, but since attempts to read
+	    terminal input without following this protocol only worked
+	    some of the time anyway, it doesn't seem to be an
+	    unreasonable one.</para>
+	  <para>In the solution described here (and introduced in
+	    &CCL; 0.9), the internal stream used to provide terminal
+	    input is always locked by some process (the "owning"
+	    process.) The initial process (the process that typically
+	    runs the read-eval-print loop) owns that stream when it's
+	    first created. By using the macro WITH-TERMINAL-INPUT,
+	    background processes can temporarily obtain ownership of the
+	    terminal and relinquish ownership to the previous owner when
+	    they're done with it.</para>
+	  <para>In &CCL;, BREAK, ERROR, CERROR, Y-OR-N-P,
+	    YES-OR-NO-P, and CCL:GET-STRING- FROM-USER are all defined
+	    in terms of WITH-TERMINAL-INPUT, as are the :TTY
+	    user-interfaces to STEP and INSPECT.</para>
+    </sect2>
+
+    <sect2 id="background-terminal-example">
+      <title>An example</title>
+
+      <programlisting>
+? Welcome to &CCL; Version (Beta: linux) 0.9!
+?
+
+? (process-run-function "sleeper" #'(lambda () (sleep 5) (break "broken")))
+#&lt;PROCESS sleeper(1) [Enabled] #x3063B33E&gt;
+
+?
+;;
+;; Process sleeper(1) needs access to terminal input.
+;;
+      </programlisting>
+
+      <para>This example was run under ILISP; ILISP often gets confused if one
+	    tries to enter input and "point" doesn't follow a prompt.
+	    Entering a "simple" expression at this point gets it back in
+	    synch; that's otherwise not relevant to this example.</para>
+
+	  <programlisting>
+()
+NIL
+? (:y 1)
+;;
+;; process sleeper(1) now controls terminal input
+;;
+> Break in process sleeper(1): broken
+> While executing: #&lt;Anonymous Function #x3063B276&gt;
+> Type :GO to continue, :POP to abort.
+> If continued: Return from BREAK.
+Type :? for other options.
+1 &gt; :b
+(30C38E30) : 0 "Anonymous Function #x3063B276" 52
+(30C38E40) : 1 "Anonymous Function #x304984A6" 376
+(30C38E90) : 2 "RUN-PROCESS-INITIAL-FORM" 340
+(30C38EE0) : 3 "%RUN-STACK-GROUP-FUNCTION" 768
+1 &gt; :pop
+;;
+;; control of terminal input restored to process Initial(0)
+;;
+?
+      </programlisting>
+    </sect2>
+
+    <sect2 id="A-more-elaborate-example-">
+      <title>A more elaborate example.</title>
+	  <para>If a background process ("A") needs access to the terminal
+	    input stream and that stream is owned by another background process
+	    ("B"), process "A" announces that fact, then waits until
+	    the initial process regains control.</para>
+
+	  <programlisting>
+? Welcome to &CCL; Version (Beta: linux) 0.9!
+?
+
+? (process-run-function "sleep-60" #'(lambda () (sleep 60) (break "Huh?")))
+#&lt;PROCESS sleep-60(1) [Enabled] #x3063BF26&gt;
+
+? (process-run-function "sleep-5" #'(lambda () (sleep 5) (break "quicker")))
+#&lt;PROCESS sleep-5(2) [Enabled] #x3063D0A6&gt;
+
+?       ;;
+;; Process sleep-5(2) needs access to terminal input.
+;;
+()
+NIL
+
+? (:y 2)
+;;
+;; process sleep-5(2) now controls terminal input
+;;
+> Break in process sleep-5(2): quicker
+> While executing: #x3063CFDE>
+> Type :GO to continue, :POP to abort.
+> If continued: Return from BREAK.
+Type :? for other options.
+1 >     ;; Process sleep-60(1) will need terminal access when
+;; the initial process regains control of it.
+;;
+()
+NIL
+1 > :pop
+;;
+;; Process sleep-60(1) needs access to terminal input.
+;;
+;;
+;; control of terminal input restored to process Initial(0)
+;;
+
+? (:y 1)
+;;
+;; process sleep-60(1) now controls terminal input
+;;
+> Break in process sleep-60(1): Huh?
+> While executing: #x3063BE5E>
+> Type :GO to continue, :POP to abort.
+> If continued: Return from BREAK.
+Type :? for other options.
+1 > :pop
+;;
+;; control of terminal input restored to process Initial(0)
+;;
+
+?
+      </programlisting>
+
+    </sect2>
+
+    <sect2 id="Summary">
+	  <title>Summary</title>
+	  <para>This scheme is certainly not bulletproof: imaginative
+	    use of PROCESS-INTERRUPT and similar functions might be able
+	    to defeat it and deadlock the lisp, and any scenario where
+	    several background processes are clamoring for access to the
+	    shared terminal input stream at the same time is likely to be
+	    confusing and chaotic. (An alternate scheme, where the input
+	    focus was magically granted to whatever thread the user was
+	    thinking about, was considered and rejected due to technical
+	    limitations.)</para>
+	  <para>The longer-term fix would probably involve using network or
+	    window-system streams to give each process unique instances of
+	    *TERMINAL-IO*.</para>
+      <para>Existing code that attempts to read from *TERMINAL-IO*
+        from a background process will need to be changed to use
+        WITH-TERMINAL-INPUT.  Since that code was probably not working
+        reliably in previous versions of &CCL;, this requirement
+        doesn't seem to be too onerous.</para>
+      <para>Note that WITH-TERMINAL-INPUT both requests ownership of
+        the terminal input stream and promises to restore that
+        ownership to the initial process when it's done with it. An ad
+        hoc use of READ or READ-CHAR doesn't make this promise; this
+        is the rationale for the restriction on the :Y command.</para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="The-Threads-which-CCL-Uses-for-Its-Own-Purposes">
+    <title>The Threads which &CCL; Uses for Its Own Purposes</title>
+    <para>
+      In the "tty world", &CCL; starts out with 2 lisp-level threads:</para>
+
+    <programlisting>
+? :proc
+1 : -> listener     [Active]
+0 :    Initial      [Active]
+    </programlisting>
+
+    <para>If you look at a running &CCL; with a debugging tool,
+      such as GDB, or Apple's Thread Viewer.app, you'll see an
+      additional kernel-level thread on Darwin; this is used by the
+      Mach exception-handling mechanism.</para>
+    <para>The initial thread, conveniently named "initial", is the
+      one that was created by the operating system when it launched
+      &CCL;.  It maps the heap image into memory, does some
+      Lisp-level initialization, and, when the Cocoa IDE isn't being
+      used, creates the thread "listener", which runs the top-level
+      loop that reads input, evaluates it, and prints the
+      result.</para>
+    <para>After the listener thread is created, the initial thread
+      does "housekeeping": it sits in a loop, sleeping most of the
+      time and waking up occasionally to do "periodic tasks".  These
+      tasks include forcing output on specified interactive streams,
+      checking for and handling control-C interrupts, etc.  Currently,
+      those tasks also include polling for the exit status of external
+      processes and handling some kinds of I/O to and from those
+      processes.</para>
+    <para>In this environment, the initial thread does these
+      "housekeeping" activities as necessary, until
+      <literal>ccl:quit</literal> is called;
+      <literal>quit</literal>ting interrupts the initial thread, which
+      then ends all other threads in as orderly a fashion as possible
+      and calls the C function <literal>#_exit</literal>.</para>
+    <para>The short-term plan is to handle each external-process in
+      a dedicated thread; the worst-case behavior of the current
+      scheme can involve busy-waiting and excessive CPU utilization
+      while waiting for an external process to terminate in some
+      cases.</para>
+    <para>The Cocoa features use more threads.  Adding a Cocoa
+      listener creates two threads:</para>
+
+    <programlisting>
+      ? :proc
+      3 : -> Listener     [Active]
+      2 :    housekeeping  [Active]
+      1 :    listener     [Active]
+      0 :    Initial      [Active]
+    </programlisting>
+
+    <para>The Cocoa event loop has to run in the initial thread;
+      when the event loop starts up, it creates a new thread to do the
+      "housekeeping" tasks which the initial thread would do in the
+      terminal-only mode.  The initial thread then becomes the one to
+      receive all Cocoa events from the window server; it's the only
+      thread which can.</para>
+    <para>It also creates one "Listener" (capital-L) thread for each
+      listener window, with a lifetime that lasts as long as the
+      thread does.  So, if you open a second listener, you'll see five
+      threads all together:</para>
+
+    <programlisting>
+      ? :proc
+      4 : -> Listener-2   [Active]
+      3 :    Listener     [Active]
+      2 :    housekeeping  [Active]
+      1 :    listener     [Active]
+      0 :    Initial      [Active]
+    </programlisting>
+
+    <para>Unix signals, such as SIGINT (control-C), invoke a handler
+      installed by the Lisp kernel.  Although the OS doesn't make any
+      specific guarantee about which thread will receive the signal,
+      in practice, it seems to be the initial thread.  The handler
+      just sets a flag and returns; the housekeeping thread (which may
+      be the initial thread, if Cocoa's not being used) will check for
+      the flag and take whatever action is appropriate to the
+      signal.</para>
+    <para>In the case of SIGINT, the action is to enter a break
+      loop, by calling on the thread being interrupted.  When there's
+      more than one Lisp listener active, it's not always clear what
+      thread that should be, since it really depends on the user's
+      intentions, which there's no way to divine programmatically.  To
+      make its best guess, the handler first checks whether the value
+      of <literal>ccl:*interactive-abort-process*</literal> is a
+      thread, and, if so, uses it.  If that fails, it chooses the
+      thread which currently "owns" the default terminal input stream;
+      see .</para>
+    <para>In the bleeding-edge version of the Cocoa support which is
+      based on Hemlock, an Emacs-like editor, each editor window has a
+      dedicated thread associated with it.  When a keypress event
+      comes in which affects that specific window the initial thread
+      sends it to the window's dedicated thread.  The dedicated thread
+      is responsible for trying to interpret keypresses as Hemlock
+      commands, applying those commands to the active buffer; it
+      repeats this in a loop, until the window closes.  The initial
+      thread handles all other events, such as mouse clicks and
+      drags.</para>
+    <para>This thread-per-window scheme makes many things simpler,
+      including the process of entering a "recursive command loop" in
+      commands like "Incremental Search Forward", etc.  (It might be
+      possible to handle all Hemlock commands in the Cocoa event
+      thread, but these "recursive command loops" would have to
+      maintain a lot of context/state information; threads are a
+      straightforward way of maintaining that information.)</para>
+    <para>Currently (August 2004), when a dedicated thread needs to
+      alter the contents of the buffer or the selection, it does so by
+      invoking methods in the initial thread, for synchronization
+      purposes, but this is probably overkill and will likely be
+      replaced by a more efficient scheme in the future.</para>
+    <para>The per-window thread could probably take more
+      responsibility for drawing and handling the screen than it
+      currently does; -something- needs to be done to buffer screen
+      updates a bit better in some cases: you don't need to see
+      everything that happens during something like indentation; you
+      do need to see the results...</para>
+    <para>When Hemlock is being used, listener windows are editor
+      windows, so in addition to each "Listener" thread, you should
+      also see a thread which handles Hemlock command
+      processing.</para>
+    <para>The Cocoa runtime may make additional threads in certain
+      special situations; these threads usually don't run lisp code,
+      and rarely if ever run much of it.</para>
+  </sect1>
+
+  <sect1 id="Threads-Dictionary">
+    <title>Threads Dictionary</title>
+    <refentry id="f_all-processes">
+	  <indexterm zone="f_all-processes">
+	    <primary>all-processes</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>ALL-PROCESSES</refname>
+	    <refpurpose>Obtain a fresh list of all known Lisp
+	      threads.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>all-processes</function> => result
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>a list of all lisp processes (threads)
+		        known to &CCL;.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Returns a list of all lisp processes (threads) known
+	      to &CCL; as of
+	      the precise instant it&#39;s called. It&#39;s safe to traverse
+	      this list and to modify the cons cells that comprise that list
+	      (it&#39;s freshly consed.) Since other threads can create and kill
+	      threads at any time, there&#39;s generally no way to get an
+	      &#34;accurate&#34; list of all threads, and (generally) no
+	      sense in which such a list can be accurate.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="v_current-process"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_make-process">
+	  <indexterm zone="f_make-process">
+	    <primary>make-process</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>MAKE-PROCESS</refname>
+	    <refpurpose>Creates and returns a new process.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>make-process</function>
+	      name &amp;key
+	      persistent priority class stack-size vstack-size
+	      tstack-size initial-bindings use-standard-initial-bindings
+	      => process
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+	        
+	        <listitem>
+		      <para>a string, used to identify the process.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>persistent</term>
+	        
+	        <listitem>
+		      <para>if true, requests that information about the process
+		        be retained by SAVE-APPLICATION so that an equivalent
+		        process can be restarted when a saved image is run.  The
+		        default is nil.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>priority</term>
+	        
+	        <listitem>
+		      <para>ignored.  It
+		        shouldn't be ignored of course, but there are
+		        complications on some platforms.  The default is 0.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>class</term>
+	        
+	        <listitem>
+		      <para>the class of process object to create;
+		        should be a subclass of CCL:PROCESS.  The default is
+		        CCL:PROCESS.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>stack-size</term>
+	        
+	        <listitem>
+		      <para>the size, in bytes, of the newly-created process's
+		        control stack; used for foreign function calls and to save
+		        function return address context.  The default is
+		        CCL:*DEFAULT-CONTROL-STACK-SIZE*.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>vstack-size</term>
+	        
+	        <listitem>
+		      <para>the size, in bytes, of the newly-created process's
+		        value stack; used for lisp function arguments, local
+		        variables, and other stack-allocated lisp objects.
+		        The default is CCL:*DEFAULT-VALUE-STACK-SIZE*.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>tstack-size</term>
+	        
+	        <listitem>
+		      <para>the size, in bytes, of the newly-created process's
+		        temp stack; used for the allocation of dynamic-extent
+		        objects.  The default is CCL:*DEFAULT-TEMP-STACK-SIZE*.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>use-standard-initial-bindings</term>
+	        
+	        <listitem>
+		      <para>when true, the global "standard initial
+		        bindings" are put into effect in the new thread before. See
+		        DEF-STANDARD-INITIAL-BINDING.  "standard" initial bindings
+		        are put into effect before any bindings specified by
+		        :initial-bindings are.  The default is t.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>initial-bindings</term>
+	        
+	        <listitem>
+		      <para>an alist of (<varname>symbol</varname> .
+		        <varname>valueform</varname>) pairs, which can be
+		        used to initialize special variable bindings in the new
+		        thread. Each <varname>valueform</varname> is used to
+		        compute the value of a new binding of
+		        <varname>symbol</varname> in the execution environment of
+		        the newly-created thread.  The default is nil.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>process</term>
+	        
+	        <listitem>
+		      <para>the newly-created process.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Creates and returns a new lisp process (thread) with the
+	      specified attributes. <varname>process</varname> will not begin
+	      execution immediately; it will need to be
+	      <emphasis>preset</emphasis> (given
+	      an initial function to run, as by
+	      <xref linkend="f_process-preset"/>) and
+	      <emphasis>enabled</emphasis>
+	      (allowed to execute, as by <xref linkend="f_process-enable"/>)
+	      before it&#39;s able to actually do anything.</para>
+
+	    <para>If <varname>valueform</varname> is a function, it is
+	      called, with no arguments, in the execution environment of the
+	      newly-created thread; the primary value it returns is used for
+	      the binding of the corresponding <varname>symbol</varname>.</para>
+
+	    <para>Otherwise, <varname>valueform</varname> is evaluated in the
+	      execution
+	      environment of the newly-created thread, and the resulting value
+	      is used.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-preset"/></member>
+	      <member><xref linkend="f_process-enable"/></member>
+	      <member><xref linkend="f_process-run-function"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-suspend">
+	  <indexterm zone="f_process-suspend">
+	    <primary>process-suspend</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-SUSPEND</refname>
+	    <refpurpose>Suspends a specified process.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+	  
+	  <refsynopsisdiv>
+	    <synopsis><function>process-suspend</function> process
+	      => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>T if <varname>process</varname> had been runnable
+		        and is now suspended; NIL otherwise.  That is, T if
+		        <varname>process</varname>'s
+		        <xref linkend="f_process-suspend-count"/>
+		        transitioned from 0 to 1.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Suspends <varname>process</varname>, preventing it from
+	      running, and stopping it if it was already running. This is a fairly
+	      expensive operation, because it involves a few
+	      calls to the OS.  It also risks creating deadlock if used
+	      improperly, for instance, if the process being suspended owns a
+	      lock or other resource which another process will wait for.</para>
+
+	    <para>
+	      Each
+	      call to <function>process-suspend</function> must be reversed by
+	      a matching call to <xref linkend="f_process-resume"/>
+	      before <varname>process</varname> is able to run.  What
+	      <function>process-suspend</function> actually does is increment
+	      the <xref linkend="f_process-suspend-count"/> of
+	      <varname>process</varname>.
+	    </para>
+
+	    <para>A process can't suspend itself, though this once
+	    worked and this documentation claimed has claimed that it
+	    did.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-resume"/></member>
+	      <member><xref linkend="f_process-suspend-count"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+	    <para><function>process-suspend</function> was previously called
+	      <function>process-disable</function>.
+	      <xref linkend="f_process-enable"/>
+	      now names a function for which there is no
+	      obvious inverse, so <function>process-disable</function>
+	      is no longer
+	      defined.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-resume">
+	  <indexterm zone="f_process-resume">
+	    <primary>process-resume</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-RESUME</refname>
+	    <refpurpose>Resumes a specified process which had previously
+	      been suspended by process-suspend.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-resume</function> process
+	      => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>T if <varname>process</varname> had been suspended
+		        and is now runnable; NIL otherwise.  That is, T if
+		        <varname>process</varname>'s
+		        <xref linkend="f_process-suspend-count"/>
+		        transitioned from  to 0.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Undoes the effect of a previous call to
+	      <xref linkend="f_process-suspend"/>; if
+	      all such calls are undone, makes the process runnable. Has no
+	      effect if the process is not suspended.  What
+	      <function>process-resume</function> actually does is decrement
+	      the <xref linkend="f_process-suspend-count"/> of
+	      <varname>process</varname>, to a minimum of 0.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-suspend"/></member>
+	      <member><xref linkend="f_process-suspend-count"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>
+	      This was previously called PROCESS-ENABLE;
+	      <xref linkend="f_process-enable"/> now does something slightly
+	      different.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-suspend-count">
+	  <indexterm zone="f_process-suspend-count">
+	    <primary>process-suspend-count</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-SUSPEND-COUNT</refname>
+	    <refpurpose>Returns the number of currently-pending suspensions
+	      applicable to a given process.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>
+	      <function>process-suspend-count</function>
+	      process => result
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>The number of "outstanding"
+		        <xref linkend="f_process-suspend"/> calls on
+		        <varname>process</varname>, or NIL if
+		        <varname>process</varname> has expired.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>An "outstanding" <xref linkend="f_process-suspend"/> call
+	      is one which has not yet been reversed by a call to
+	      <xref linkend="f_process-resume"/>.  A process expires when
+	      its initial function returns, although it may later be
+	      reset.</para>
+
+	    <para>A process is <emphasis>runnable</emphasis> when it has a
+	      <function>process-suspend-count</function> of 0, has been
+	      preset as by <xref linkend="f_process-preset"/>, and has been
+	      enabled as by <xref linkend="f_process-enable"/>.  Newly-created
+	      processes have a <function>process-suspend-count</function> of
+	      0.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-suspend"/></member>
+	      <member><xref linkend="f_process-resume"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-preset">
+	  <indexterm zone="f_process-preset">
+	    <primary>process-preset</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-PRESET</refname>
+	    <refpurpose>Sets the initial function and arguments of a specified
+	      process.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-preset</function>
+	      process function &rest; args
+	      => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>function</term>
+	        <listitem>
+		      <para>a function, designated by itself or by a symbol
+		        which names it.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>args</term>
+	        <listitem>
+		      <para>a list of values, appropriate as arguments to
+		        <varname>function</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>undefined.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Typically used to initialize a newly-created or newly-reset
+	      process, setting things up so that when <varname>process</varname>
+	      becomes enabled, it will begin execution by
+	      applying <varname>function</varname> to <varname>args</varname>.
+	      <function>process-preset</function> does not enable
+	      <varname>process</varname>,
+	      although a process must be <function>process-preset</function>
+	      before it can be enabled.  Processes are normally enabled by
+	      <xref linkend="f_process-enable"/>.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-process"/></member>
+	      <member><xref linkend="f_process-enable"/></member>
+	      <member><xref linkend="f_process-run-function"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-enable">
+	  <indexterm zone="f_process-enable">
+	    <primary>process-enable</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-ENABLE</refname>
+	    <refpurpose>Begins executing the initial function of a specified
+	      process.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-enable</function>
+	      process &optional; timeout
+	    </synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>timeout</term>
+	        <listitem>
+		      <para>a time interval in seconds.  May be any
+		        non-negative real number the <function>floor</function> of
+		        which fits in 32 bits.  The default is 1.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>undefined.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Tries to begin the execution of <varname>process</varname>.
+	      An error is signaled if <varname>process</varname> has never
+	      been <xref linkend="f_process-preset"/>.  Otherwise,
+	      <varname>process</varname> invokes its initial function.
+	    </para>
+	    
+	    <para><function>process-enable</function> attempts to
+	      synchronize with <varname>process</varname>, which is presumed
+	      to be reset or in the act of resetting itself.  If this attempt
+	      is not successful within the time interval specified by
+	      <varname>timeout</varname>, a continuable error is signaled,
+	      which offers the opportunity to continue waiting.
+	    </para>
+
+	    <para>A process cannot meaningfully attempt to enable itself.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-process"/></member>
+	      <member><xref linkend="f_process-preset"/></member>
+	      <member><xref linkend="f_process-run-function"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>It would be nice to have more discussion of what it means
+	      to synchronize with the process.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-run-function">
+	  <indexterm zone="f_process-run-function">
+	    <primary>process-run-function</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-RUN-FUNCTION</refname>
+	    <refpurpose>Creates a process, presets it, and enables it.
+	    </refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-run-function</function>
+	      process-specifier function &rest; args => process</synopsis>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process-specifier</term>
+	        <listitem>
+		      <para>
+		        <varname>name</varname> | 
+		        (&key; <varname>name</varname>
+		        <varname>persistent</varname>
+		        <varname>priority</varname>
+		        <varname>class</varname>
+		        <varname>stack-size</varname>
+		        <varname>vstack-size</varname>
+		        <varname>tstack-size</varname>)
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+	        <listitem>
+		      <para>a string, used to identify the process.
+		        Passed to <function>make-process</function>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>function</term>
+	        <listitem>
+		      <para>a function, designated by itself or by a symbol
+		        which names it.  Passed to
+		        <function>preset-process</function>.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>persistent</term>
+	        
+	        <listitem>
+		      <para>a boolean, passed to <function>make-process</function>.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>priority</term>
+	        
+	        <listitem>
+		      <para>ignored.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>class</term>
+	        
+	        <listitem>
+		      <para>a subclass of CCL:PROCESS.  Passed to
+		        <function>make-process</function>.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>stack-size</term>
+	        
+	        <listitem>
+		      <para>a size, in bytes.  Passed to
+		        <function>make-process</function>.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>vstack-size</term>
+	        
+	        <listitem>
+		      <para>a size, in bytes.  Passed to
+		        <function>make-process</function>.</para>
+	        </listitem>
+	      </varlistentry>
+	      
+	      <varlistentry>
+	        <term>tstack-size</term>
+	        
+	        <listitem>
+		      <para>a size, in bytes.  Passed to
+		        <function>make-process</function>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>the newly-created process.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Creates a lisp process (thread) via
+	      <xref linkend="f_make-process"/>,
+	      presets it via <xref linkend="f_process-preset"/>, and
+	      enables it via <xref linkend="f_process-enable"/>.  This means
+	      that <varname>process</varname> will immediately begin to
+	      execute.
+	      <function>process-run-function</function> is
+	      the simplest way to create and run a process.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-process"/></member>
+	      <member><xref linkend="f_process-preset"/></member>
+	      <member><xref linkend="f_process-enable"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-interrupt">
+	  <indexterm zone="f_process-interrupt">
+	    <primary>process-interrupt</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-INTERRUPT</refname>
+	    <refpurpose>Arranges for the target process to invoke a
+	      specified function at some point in the near future, and then
+	      return to what it was doing.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-interrupt</function>
+	      process function &rest; args => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>function</term>
+	        <listitem>
+		      <para>a function.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>args</term>
+	        <listitem>
+		      <para>a list of values, appropriate as arguments to
+		        <varname>function</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>the result of applying <varname>function</varname>
+		        to <varname>args</varname> if <varname>process</varname>
+		        is the <function>current-process</function>, otherwise
+		        NIL.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Arranges for <varname>process</varname>
+	      to apply <varname>function</varname> to <varname>args</varname> at
+	      some point in the near future (interrupting whatever
+	      <varname>process</varname>
+	      was doing.) If <varname>function</varname> returns normally,
+	      <varname>process</varname> resumes
+	      execution at the point at which it was interrupted.</para>
+
+	    <para><varname>process</varname> must be in an enabled state in
+	      order to respond
+	      to a <function>process-interrupt</function> request.  It's
+	      perfectly legal for a process to call
+	      <function>process-interrupt</function> on itself.</para>
+
+	    <para><function>process-interrupt</function>
+	      uses asynchronous POSIX signals to interrupt threads. If the
+	      thread being interrupted is executing lisp code, it can
+	      respond to the interrupt almost immediately (as soon as it
+	      has finished pseudo-atomic operations like consing and
+	      stack-frame initialization.)</para>
+
+	    <para>If the interrupted thread is
+	      blocking in a system call, that system call is aborted by
+	      the signal and the interrupt is handled on return.
+	    </para>
+
+	    <para>It is
+	      still difficult to reliably interrupt arbitrary foreign code
+	      (that may be stateful or otherwise non-reentrant); the
+	      interrupt request is handled when such foreign code returns
+	      to or enters lisp.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="m_without-interrupts"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>It would probably be better for <varname>result</varname>
+	      to always be NIL, since the present behavior is inconsistent.
+	    </para>
+
+	    <para>
+	      <function>Process-interrupt</function> works by sending signals
+	      between threads, via the C function
+	      <function>#_pthread_signal</function>.  It could be argued
+	      that it should be done in one of several possible other ways
+	      under
+	      Darwin, to make it practical to asynchronously interrupt
+	      things which make heavy use of the Mach nanokernel.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="v_current-process">
+	  <indexterm zone="v_current-process">
+	    <primary>*current-process*</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>*CURRENT-PROCESS*</refname>
+	    <refpurpose>Bound in each process, to that process
+	      itself.</refpurpose>
+	    <refclass>Variable</refclass>
+	  </refnamediv>
+
+	  <refsect1>
+	    <title>Value Type</title>
+
+	    <para>A lisp process (thread).</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Initial Value</title>
+	    
+	    <para>Bound separately in each process, to that process itself.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Used when lisp code needs to find out what process it is
+	      executing in.  Shouldn't be set by user code.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_all-processes"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-reset">
+	  <indexterm zone="f_process-reset">
+	    <primary>process-reset</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-RESET</refname>
+	    <refpurpose>Causes a specified process to cleanly exit from
+	      any ongoing computation.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-reset</function>
+	      process &optional; kill-option => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>kill-option</term>
+	        <listitem>
+		      <para>an internal argument, must be nil.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>undefined.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Causes <varname>process</varname> to cleanly exit
+	      from any ongoing computation and enter a state where it can be
+	      <xref linkend="f_process-preset"/>. This
+	      is implemented by signaling a condition of type PROCESS-RESET;
+	      user-defined condition handlers should generally refrain from
+	      attempting to handle conditions of this type.</para>
+
+            <para>The <varname>kill-option</varname> argument is for internal
+            use only and should not be specified by user code</para>
+
+	    <para>A process can meaningfully reset itself.</para>
+
+	    <para>There is in general no way to know precisely when
+	      <varname>process</varname>
+	      has completed the act of resetting or killing itself; a process
+	      which has either entered the limbo of the reset state or exited
+	      has few ways of communicating either fact.
+	      <xref linkend="f_process-enable"/>
+	      can reliably determine when a process has entered
+	      the "limbo of the reset state", but can't predict how long the
+	      clean exit from ongoing computation might take: that depends on
+	      the behavior of <function>unwind-protect</function> cleanup
+	      forms, and of the OS scheduler.</para>
+
+	    <para>Resetting a process other than
+	      <xref linkend="v_current-process"/> involves the
+	      use of <xref linkend="f_process-interrupt"/>.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-kill"/></member>
+	      <member><xref linkend="f_process-abort"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-kill">
+	  <indexterm zone="f_process-kill">
+	    <primary>process-kill</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-KILL</refname>
+	    <refpurpose>Causes a specified process to cleanly exit from any
+	      ongoing computation, and then exit.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-kill</function> process
+	      => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>undefined.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Entirely equivalent to calling
+	      (PROCESS-RESET PROCESS T).  Causes <varname>process</varname>
+	      to cleanly exit from any ongoing computation, and then exit.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-reset"/></member>
+	      <member><xref linkend="f_process-abort"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-abort">
+	  <indexterm zone="f_process-abort">
+	    <primary>process-abort</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-ABORT</refname>
+	    <refpurpose>Causes a specified process to process an abort
+	      condition, as if it had invoked
+	      <function>abort</function>.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-abort</function> process
+	      &optional; condition
+	      => NIL</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>condition</term>
+	        <listitem>
+		      <para>a lisp condition.  The default is NIL.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Entirely equivalent to calling
+	      (<xref linkend="f_process-interrupt"/> <varname>process</varname>
+	      (<function>lambda</function> ()
+	      (<function>abort</function> <varname>condition</varname>))).
+	      Causes <varname>process</varname> to transfer control to the
+	      applicable handler or restart for <function>abort</function>.</para>
+
+	    <para>If <varname>condition</varname> is non-NIL,
+	      <function>process-abort</function> does not consider any
+	      handlers which are explicitly bound to conditions other than
+	      <varname>condition</varname>.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-reset"/></member>
+	      <member><xref linkend="f_process-kill"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="v_ticks-per-second">
+	  <indexterm zone="v_ticks-per-second">
+	    <primary>*ticks-per-second*</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>*TICKS-PER-SECOND*</refname>
+	    <refpurpose>Bound to the clock resolution of the OS
+	      scheduler.</refpurpose>
+	    <refclass>Variable</refclass>
+	  </refnamediv>
+
+	  <refsect1>
+	    <title>Value Type</title>
+
+	    <para>A positive integer.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Initial Value</title>
+	    
+	    <para>The clock resolution of the OS scheduler.  Currently,
+	      both LinuxPPC and DarwinPPC yield an initial value of 100.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>This value is ordinarily of marginal interest at best,
+	      but, for backward compatibility, some functions accept timeout
+	      values expressed in "ticks".  This value gives the number of
+	      ticks per second.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-wait-with-timeout"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-whostate">
+	  <indexterm zone="f_process-whostate">
+	    <primary>process-whostate</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-WHOSTATE</refname>
+	    <refpurpose>Returns a string which describes the status of
+	      a specified process.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-whostate</function> process
+	      => whostate</synopsis>
+	    <variablelist>
+	      <varlistentry>
+	        <term>process</term>
+	        <listitem>
+		      <para>a lisp process (thread).</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>whostate</term>
+	        <listitem>
+		      <para>a string which describes the "state" of
+		        <varname>process</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>This information is primarily for the benefit of
+	      debugging tools.  <varname>whostate</varname> is a terse report
+	      on what <varname>process</varname> is doing, or not doing,
+	      and why.</para>
+
+	    <para>If the process is currently waiting in a call to
+	      <xref linkend="f_process-wait"/> or
+	      <xref linkend="f_process-wait-with-timeout"/>, its
+	      <function>process-whostate</function> will be the value
+	      which was passed to that function as <varname>whostate</varname>.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-wait"/></member>
+	      <member><xref linkend="f_process-wait-with-timeout"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>This should arguably be SETFable, but doesn't seem to
+	      ever have been.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-allow-schedule">
+	  <indexterm zone="f_process-allow-schedule">
+	    <primary>process-allow-schedule</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-ALLOW-SCHEDULE</refname>
+	    <refpurpose>Used for cooperative multitasking; probably never
+	      necessary.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-allow-schedule</function></synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Advises the OS scheduler that the current thread has nothing
+	      useful to do and that it should try to find some other thread to
+	      schedule in its place. There's almost always a better
+	      alternative, such as waiting for some specific event to
+	      occur.  For example, you could use a lock or semaphore.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>This is a holdover from the days of cooperative
+	      multitasking.  All modern general-purpose operating systems use
+	      preemptive multitasking.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-wait">
+	  <indexterm zone="f_process-wait">
+	    <primary>process-wait</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-WAIT</refname>
+	    <refpurpose>Causes the current lisp process (thread) to wait for
+	      a given
+	      predicate to return true.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-wait</function>
+	      whostate function &rest; args => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>whostate</term>
+
+	        <listitem>
+		      <para>a string, which will be the value of
+		        <xref linkend="f_process-whostate"/>
+		        while the process is waiting.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>function</term>
+	        <listitem>
+		      <para>a function, designated by itself or by a symbol
+		        which names it.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>args</term>
+	        <listitem>
+		      <para>a list of values, appropriate as arguments to
+		        <varname>function</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>NIL.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Causes the current lisp process (thread) to repeatedly
+	      apply <varname>function</varname> to
+	      <varname>args</varname> until the call returns a true result, then
+	      returns NIL. After
+	      each failed call, yields the CPU as if by
+	      <xref linkend="f_process-allow-schedule"/>.</para>
+	    
+	    <para>
+	      As with <xref linkend="f_process-allow-schedule"/>, it's almost
+	      always more efficient to wait for some
+	      specific event to occur; this isn't exactly busy-waiting, but
+	      the OS scheduler can do a better job of scheduling if it's given
+	      the relevant information.  For example, you could use a lock
+	      or semaphore.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-whostate"/></member>
+	      <member><xref linkend="f_process-wait-with-timeout"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-wait-with-timeout">
+	  <indexterm zone="f_process-wait-with-timeout">
+	    <primary>process-wait-with-timeout</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-WAIT-WITH-TIMEOUT</refname>
+	    <refpurpose>Causes the current thread to wait for a given
+	      predicate to return true, or for a timeout to expire.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-wait-with-timeout</function>
+	      whostate ticks function args => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>whostate</term>
+	        <listitem>
+		      <para>a string, which will be the value of
+		        <xref linkend="f_process-whostate"/>
+		        while the process is waiting.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>ticks</term>
+	        <listitem>
+		      <para>either a positive integer expressing a duration
+		        in "ticks" (see <xref linkend="v_ticks-per-second"/>),
+		        or NIL.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>function</term>
+	        <listitem>
+		      <para>a function, designated by itself or by a symbol
+		        which names it.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>args</term>
+	        <listitem>
+		      <para>a list of values, appropriate as arguments to
+		        <varname>function</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>T if <function>process-wait-with-timeout</function>
+		        returned because its <varname>function</varname> returned
+		        true, or NIL if it returned because the duration
+		        <varname>ticks</varname> has been exceeded.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>If <varname>ticks</varname> is NIL, behaves exactly like
+	      <xref linkend="f_process-wait"/>, except for returning T.
+	      Otherwise, <varname>function</varname> will be tested repeatedly,
+	      in the same
+	      kind of test/yield loop as in <xref linkend="f_process-wait"/>
+	      until either <varname>function</varname> returns true,
+	      or the duration <varname>ticks</varname> has been exceeded.
+	    </para>
+
+	    <para> Having already read the descriptions of
+	      <xref linkend="f_process-allow-schedule"/> and
+	      <xref linkend="f_process-wait"/>, the
+	      astute reader has no doubt anticipated the observation that
+	      better alternatives should be used whenever possible.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="v_ticks-per-second"/></member>
+	      <member><xref linkend="f_process-whostate"/></member>
+	      <member><xref linkend="f_process-wait"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="m_without-interrupts">
+	  <indexterm zone="m_without-interrupts">
+	    <primary>without-interrupts</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WITHOUT-INTERRUPTS</refname>
+	    <refpurpose>Evaluates its body in an environment in which
+	      process-interrupt requests are deferred.</refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>without-interrupts</function>
+	      &body; body => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>body</term>
+	        <listitem>
+		      <para>an implicit progn.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>the primary value returned by
+		        <varname>body</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Executes <varname>body</varname>
+	      in an environment in which <xref linkend="f_process-interrupt"/>
+	      requests are
+	      deferred. As noted in the description of
+	      <xref linkend="f_process-interrupt"/>, this has nothing to do
+	      with the
+	      scheduling of other threads; it may be necessary to inhibit
+	      <xref linkend="f_process-interrupt"/> handling when
+	      (for instance) modifying some data
+	      structure (for which the current thread holds an appropriate lock)
+	      in some manner that&#39;s not reentrant.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_process-interrupt"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_make-lock">
+	  <indexterm zone="f_make-lock">
+	    <primary>make-lock</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>MAKE-LOCK</refname>
+	    <refpurpose>Creates and returns a lock object, which can
+	      be used for synchronization between threads.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>make-lock</function> &optional;
+	      name => lock</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>name</term>
+	        <listitem>
+		      <para>any lisp object; saved as part of
+		        <varname>lock</varname>.  Typically a string or symbol
+		        which may appear in the <xref linkend="f_process-whostate"/>s
+		        of threads which are waiting for <varname>lock</varname>.
+		      </para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>lock</term>
+	        <listitem>
+		      <para>a newly-allocated object of type CCL:LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Creates and returns a lock object, which can
+	      be used to synchronize access to some shared resource.
+	      <varname>lock</varname> is
+	      initially in a &#34;free&#34; state; a lock can also be
+	      &#34;owned&#34; by a
+	      thread.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="m_with-lock-grabbed"/></member>
+	      <member><xref linkend="f_grab-lock"/></member>
+	      <member><xref linkend="f_release-lock"/></member>
+	      <member><xref linkend="f_try-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="m_with-lock-grabbed">
+	  <indexterm zone="m_with-lock-grabbed">
+	    <primary>with-lock-grabbed</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WITH-LOCK-GRABBED</refname>
+	    <refpurpose>Waits until a given lock can be obtained, then
+	      evaluates its body with the lock held.</refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>with-lock-grabbed</function>
+	      (lock) &body; body</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>lock</term>
+	        <listitem>
+		      <para>an object of type CCL:LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>body</term>
+	        <listitem>
+		      <para>an implicit progn.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>the primary value returned by
+		        <varname>body</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Waits until <varname>lock</varname> is either free or
+	      owned by the calling
+	      thread, then executes <varname>body</varname> with the
+	      lock owned by the calling thread. If <varname>lock</varname>
+	      was free when <function>with-lock-grabbed</function> was called,
+	      it is restored to a free state after <varname>body</varname>
+	      is executed.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_grab-lock"/></member>
+	      <member><xref linkend="f_release-lock"/></member>
+	      <member><xref linkend="f_try-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_grab-lock">
+	  <indexterm zone="f_grab-lock">
+	    <primary>grab-lock</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>GRAB-LOCK</refname>
+	    <refpurpose>Waits until a given lock can be obtained, then
+	      obtains it.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>grab-lock</function> lock</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>lock</term>
+	        <listitem>
+		      <para>an object of type CCL:LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Blocks until <varname>lock</varname> is owned by the
+	      calling thread.</para>
+
+	    <para>The macro <xref linkend="m_with-lock-grabbed"/>
+	      <emphasis>could</emphasis> be defined in
+	      terms of <function>grab-lock</function> and
+	      <xref linkend="f_release-lock"/>, but it is actually
+	      implemented at a slightly lower level.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="m_with-lock-grabbed"/></member>
+	      <member><xref linkend="f_release-lock"/></member>
+	      <member><xref linkend="f_try-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_release-lock">
+	  <indexterm zone="f_release-lock">
+	    <primary>release-lock</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>RELEASE-LOCK</refname>
+	    <refpurpose>Relinquishes ownership of a given lock.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>release-lock</function> lock</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>lock</term>
+	        <listitem>
+		      <para>an object of type CCL:LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Signals an error of type CCL:LOCK-NOT-OWNER if
+	      <varname>lock</varname>
+	      is not already owned by the calling thread; otherwise, undoes the
+	      effect of one previous 
+	      <xref linkend="f_grab-lock"/>.  If this means that
+	      <function>release-lock</function> has now been called on
+	      <varname>lock</varname> the same number of times as
+	      <xref linkend="f_grab-lock"/> has, <varname>lock</varname>
+	      becomes free.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="m_with-lock-grabbed"/></member>
+	      <member><xref linkend="f_grab-lock"/></member>
+	      <member><xref linkend="f_try-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_try-lock">
+	  <indexterm zone="f_try-lock">
+	    <primary>try-lock</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>TRY-LOCK</refname>
+	    <refpurpose>Obtains the given lock, but only if it is not
+	      necessary to wait for it.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>try-lock</function> lock => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>lock</term>
+	        <listitem>
+		      <para>an object of type CCL:LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>T if <varname>lock</varname> has been obtained,
+		        or NIL if it has not.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Tests whether <varname>lock</varname>
+	      can be obtained without blocking - that is, either
+	      <varname>lock</varname> is already free, or it is already owned
+	      by <xref linkend="v_current-process"/>.  If it can,
+	      causes it to
+	      be owned by the calling lisp process (thread) and returns T.
+	      Otherwise, the lock
+	      is already owned by another thread and cannot be obtained without
+	      blocking; NIL is returned in this case.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="m_with-lock-grabbed"/></member>
+	      <member><xref linkend="f_grab-lock"/></member>
+	      <member><xref linkend="f_release-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_make-read-write-lock">
+	  <indexterm zone="f_make-read-write-lock">
+	    <primary>make-read-write-lock</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>MAKE-READ-WRITE-LOCK</refname>
+	    <refpurpose>Creates and returns a read-write lock, which can
+	      be used for synchronization between threads.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>make-read-write-lock</function>
+	      => read-write-lock</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>read-write-lock</term>
+	        <listitem>
+		      <para>a newly-allocated object of type
+		        CCL:READ-WRITE-LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Creates and returns an object of type CCL::READ-WRITE-LOCK.
+	      A read-write lock may, at any given time, belong to any number
+	      of lisp processes (threads) which act as "readers"; or, it may
+	      belong to at most one process which acts as a "writer".  A
+	      read-write lock may never be held by a reader at the same time as
+	      a writer.  Initially, <varname>read-write-lock</varname> has
+	      no readers and no writers.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="m_with-read-lock"/></member>
+	      <member><xref linkend="m_with-write-lock"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>There probably should be some way to
+	      atomically &#34;promote&#34; a reader, making it a writer without
+	      releasing the lock, which could otherwise cause delay.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="m_with-read-lock">
+	  <indexterm zone="m_with-read-lock">
+	    <primary>with-read-lock</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WITH-READ-LOCK</refname>
+	    <refpurpose>Waits until a given lock is available for
+	      read-only access, then evaluates its body with the lock
+	      held.</refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>with-read-lock</function>
+	      (read-write-lock) &body; body => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>read-write-lock</term>
+	        <listitem>
+		      <para>an object of type
+		        CCL:READ-WRITE-LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>body</term>
+	        <listitem>
+		      <para>an implicit progn.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>the primary value returned by
+		        <varname>body</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Waits until <varname>read-write-lock</varname> has no
+	      writer,
+	      ensures that <xref linkend="v_current-process"/> is a
+	      reader of it, then executes <varname>body</varname>.
+	    </para>
+
+	    <para>After executing <varname>body</varname>, if
+	      <xref linkend="v_current-process"/> was not a reader of
+	      <varname>read-write-lock</varname> before
+	      <function>with-read-lock</function> was called, the lock is
+	      released.  If it was already a reader, it remains one.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="m_with-write-lock"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="m_with-write-lock">
+	  <indexterm zone="m_with-write-lock">
+	    <primary>with-write-lock</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WITH-WRITE-LOCK</refname>
+	    <refpurpose>Waits until the given lock is available for write
+	      access, then executes its body with the lock held.</refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>with-write-lock</function>
+	      (read-write-lock) &body; body</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>read-write-lock</term>
+	        <listitem>
+		      <para>an object of type
+		        CCL:READ-WRITE-LOCK.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>body</term>
+	        <listitem>
+		      <para>an implicit progn.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>the primary value returned by
+		        <varname>body</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Waits until <varname>read-write-lock</varname> has no
+	      readers and no writer other than <xref linkend="v_current-process"/>,
+	      then ensures that <xref linkend="v_current-process"/> is the
+	      writer of it.  With the lock held, executes <varname>body</varname>.
+	    </para>
+
+	    <para>After executing <varname>body</varname>, if
+	      <xref linkend="v_current-process"/> was not the writer of
+	      <varname>read-write-lock</varname> before
+	      <function>with-write-lock</function> was called, the lock is
+	      released.  If it was already the writer, it remains the
+	      writer.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="m_with-read-lock"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_make-semaphore">
+	  <indexterm zone="f_make-semaphore">
+	    <primary>make-semaphore</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>MAKE-SEMAPHORE</refname>
+	    <refpurpose>Creates and returns a semaphore, which can be used
+	      for synchronization between threads.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>make-semaphore</function>
+	      => semaphore</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>semaphore</term>
+	        <listitem>
+		      <para>a newly-allocated object of type CCL:SEMAPHORE.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Creates and returns an object of type CCL:SEMAPHORE.
+	      A semaphore has an associated "count" which may be incremented
+	      and decremented atomically; incrementing it represents sending
+	      a signal, and decrementing it represents handling that signal.
+	      <varname>semaphore</varname> has an initial count of 0.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_signal-semaphore"/></member>
+	      <member><xref linkend="f_wait-on-semaphore"/></member>
+	      <member><xref linkend="f_timed-wait-on-semaphore"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_signal-semaphore">
+	  <indexterm zone="f_signal-semaphore">
+	    <primary>signal-semaphore</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>SIGNAL-SEMAPHORE</refname>
+	    <refpurpose>Atomically increments the count of a given
+	      semaphore.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>signal-semaphore</function>
+	      semaphore => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>semaphore</term>
+	        <listitem>
+		      <para>an object of type CCL:SEMAPHORE.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>an integer representing an error identifier
+		        which was returned by the underlying OS call.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Atomically increments <varname>semaphore</varname>'s
+	      "count" by 1; this
+	      may enable a waiting thread to resume execution.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_wait-on-semaphore"/></member>
+	      <member><xref linkend="f_timed-wait-on-semaphore"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para><varname>result</varname> should probably be interpreted
+	      and acted on by <function>signal-semaphore</function>, because
+	      it is not likely to be meaningful to a lisp program, and the
+	      most common cause of failure is a type error.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_wait-on-semaphore">
+	  <indexterm zone="f_wait-on-semaphore">
+	    <primary>wait-on-semaphore</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WAIT-ON-SEMAPHORE</refname>
+	    <refpurpose>Waits until the given semaphore has a positive
+	      count which can be atomically decremented.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>wait-on-semaphore</function>
+	      semaphore => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>semaphore</term>
+	        <listitem>
+		      <para>an object of type CCL:SEMAPHORE.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>an integer representing an error identifier
+		        which was returned by the underlying OS call.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Waits until <varname>semaphore</varname>
+	      has a positive count that can be
+	      atomically decremented; this will succeed exactly once for each
+	      corresponding call to SIGNAL-SEMAPHORE.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_signal-semaphore"/></member>
+	      <member><xref linkend="f_timed-wait-on-semaphore"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para><varname>result</varname> should probably be interpreted
+	      and acted on by <function>wait-on-semaphore</function>, because
+	      it is not likely to be meaningful to a lisp program, and the
+	      most common cause of failure is a type error.</para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_timed-wait-on-semaphore">
+	  <indexterm zone="f_timed-wait-on-semaphore">
+	    <primary>timed-wait-on-semaphore</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>TIMED-WAIT-ON-SEMAPHORE</refname>
+	    <refpurpose>Waits until the given semaphore has a positive
+	      count which can be atomically decremented, or until a timeout
+	      expires.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>timed-wait-on-semaphore</function>
+	      semaphore timeout => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>semaphore</term>
+	        <listitem>
+		      <para>An object of type CCL:SEMAPHORE.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>timeout</term>
+	        <listitem>
+		      <para>a time interval in seconds.  May be any
+		        non-negative real number the <function>floor</function> of
+		        which fits in 32 bits.  The default is 1.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>T if <function>timed-wait-on-semaphore</function>
+		        returned because it was able to decrement the count of
+		        <varname>semaphore</varname>; NIL if it returned because
+		        the duration <varname>timeout</varname> has been
+		        exceeded.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Waits until <varname>semaphore</varname>
+	      has a positive count that can be
+	      atomically decremented, or until the duration
+	      <varname>timeout</varname> has
+	      elapsed.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_wait-on-semaphore"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-input-wait">
+	  <indexterm zone="f_process-input-wait">
+	    <primary>process-input-wait</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-INPUT-WAIT</refname>
+	    <refpurpose>Waits until input is available on a given
+	      file-descriptor.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-input-wait</function>
+	      fd &optional; timeout</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>fd</term>
+	        <listitem>
+		      <para>a file descriptor, which is a non-negative integer
+		        used by the OS to refer to an open file, socket, or similar
+		        I/O connection.  See <xref linkend="f_stream-device"/>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>timeout</term>
+	        <listitem>
+		      <para>either NIL or a time interval in milliseconds.  Must be a non-negative integer.  The default is NIL.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Wait until input is available on <varname>fd</varname>.
+	      This uses the <function>select()</function> system call, and is
+	      generally a fairly
+	      efficient way of blocking while waiting for input. More
+	      accurately, <function>process-input-wait</function>
+	      waits until it&#39;s possible to read
+	      from fd without blocking, or until <varname>timeout</varname>, if
+	      it is not NIL, has been exceeded.</para>
+
+	    <para>
+	      Note that it&#39;s possible to read without blocking if
+	      the file is at its end - although, of course, the read will
+	      return zero bytes.</para>
+	  </refsect1>
+	  
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>
+	      <function>process-input-wait</function> has a timeout parameter,
+	      and
+	      <xref linkend="f_process-output-wait"/> does not.  This
+	      inconsistency should probably be corrected.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_process-output-wait">
+	  <indexterm zone="f_process-output-wait">
+	    <primary>process-output-wait</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>PROCESS-OUTPUT-WAIT</refname>
+	    <refpurpose>Waits until output is possible on a given file
+	      descriptor.</refpurpose>
+	    <refclass>Function</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>process-output-wait</function>
+	      fd  &optional; timeout</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>fd</term>
+	        <listitem>
+		      <para>a file descriptor, which is a non-negative integer
+		        used by the OS to refer to an open file, socket, or similar
+		        I/O connection.  See <xref linkend="f_stream-device"/>.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>timeout</term>
+	        <listitem>
+		      <para>either NIL or a time interval in milliseconds.  Must be a non-negative integer.  The default is NIL.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Wait until output is possible on <varname>fd</varname> or until <varname>timeout</varname>, if
+	      it is not NIL, has been exceeded.
+	      This uses the <function>select()</function> system call, and is
+	      generally a fairly
+	      efficient way of blocking while waiting to output.</para>
+
+	    <para>If <function>process-output-wait</function> is called on
+	      a network socket which has not yet established a connection, it
+	      will wait until the connection is established.  This is an
+	      important use, often overlooked.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	    </simplelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Notes</title>
+
+	    <para>
+	      <xref linkend="f_process-input-wait"/> has a timeout parameter,
+	      and
+	      <function>process-output-wait</function> does not.  This
+	      inconsistency should probably be corrected.
+	    </para>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="m_with-terminal-input">
+	  <indexterm zone="m_with-terminal-input">
+	    <primary>with-terminal-input</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>WITH-TERMINAL-INPUT</refname>
+	    <refpurpose>Executes its body in an environment with exclusive
+	      read access to the terminal.</refpurpose>
+	    <refclass>Macro</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis><function>with-terminal-input</function>
+	      &body; body => result</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+	    
+	    <variablelist>
+	      <varlistentry>
+	        <term>body</term>
+	        <listitem>
+		      <para>an implicit progn.</para>
+	        </listitem>
+	      </varlistentry>
+	      <varlistentry>
+	        <term>result</term>
+	        <listitem>
+		      <para>the primary value returned by
+		        <varname>body</varname>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Requests exclusive read access to the standard terminal
+	      stream, <varname>*terminal-io*</varname>.  Executes
+	      <varname>body</varname> in an environment with that access.
+	    </para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref
+	                 linkend="v_request-terminal-input-via-break"/></member>
+	      <member><xref linkend="cmd_y"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="v_request-terminal-input-via-break">
+	  <indexterm zone="v_request-terminal-input-via-break">
+	    <primary>request-terminal-input-via-break</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>*REQUEST-TERMINAL-INPUT-VIA-BREAK*</refname>
+	    <refpurpose>Controls how attempts to obtain ownership of
+	      terminal input are made.</refpurpose>
+	    <refclass>Variable</refclass>
+	  </refnamediv>
+
+	  <refsect1>
+	    <title>Value Type</title>
+
+	    <para>A boolean.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Initial Value</title>
+	    
+	    <para>NIL.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>Controls how attempts to obtain ownership of terminal input
+	      are made. When NIL, a message is printed on *TERMINAL-IO*;
+	      it's expected that the user will later yield
+	      control of the terminal via the :Y toplevel command. When T, a
+	      BREAK condition is signaled in the owning process; continuing from
+	      the break loop will yield the terminal to the requesting process
+	      (unless the :Y command was already used to do so in the break
+	      loop.)</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	      <member><xref linkend="cmd_y"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="cmd_y">
+	  <indexterm zone="cmd_y">
+	    <primary>:y</primary>
+	  </indexterm>
+
+	  <refnamediv>
+	    <refname>:Y</refname>
+	    <refpurpose>Yields control of terminal input to a specified
+	      lisp process (thread).</refpurpose>
+	    <refclass>Toplevel Command</refclass>
+	  </refnamediv>
+
+	  <refsynopsisdiv>
+	    <synopsis>(<function>:y</function> p)</synopsis>
+	  </refsynopsisdiv>
+
+	  <refsect1>
+	    <title>Arguments and Values</title>
+
+	    <variablelist>
+	      <varlistentry>
+	        <term>p</term>
+	        <listitem>
+		      <para>a lisp process (thread), designated either by
+		        an integer which matches its
+		        <function>process-serial-number</function>,
+		        or by a string which is <function>equal</function> to
+		        its <function>process-name</function>.</para>
+	        </listitem>
+	      </varlistentry>
+	    </variablelist>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>Description</title>
+
+	    <para>:Y is a toplevel command, not a function.  As such, it
+	      can only be used interactively, and only from the initial
+	      process.</para>
+
+	    <para>The command yields control of terminal input to the
+	      process <varname>p</varname>, which must have used
+	      <xref linkend="m_with-terminal-input"/> to request access to the
+	      terminal input stream.</para>
+	  </refsect1>
+
+	  <refsect1>
+	    <title>See Also</title>
+	    
+	    <simplelist type="inline">
+	      <member><xref linkend="m_with-terminal-input"/></member>
+	      <member><xref
+	                 linkend="v_request-terminal-input-via-break"/></member>
+	      <member><xref linkend="f_make-lock"/></member>
+	      <member><xref linkend="f_make-read-write-lock"/></member>
+	      <member><xref linkend="f_make-semaphore"/></member>
+	      <member><xref linkend="f_process-input-wait"/></member>
+	      <member><xref linkend="f_process-output-wait"/></member>
+	    </simplelist>
+	  </refsect1>
+    </refentry>
+
+    <refentry id="f_join-process">
+      <indexterm zone="f_join-process">
+	<primary>join-process</primary>
+      </indexterm>
+
+      <refnamediv>
+	<refname>JOIN-PROCESS</refname>
+	<refpurpose>Waits for a specified process to complete and
+	returns the values that that process's initial function
+	returned.</refpurpose>
+	<refclass>Function</refclass>
+      </refnamediv>
+
+      <refsynopsisdiv>
+	<synopsis><function>join-process</function> process
+	&optional; default => values</synopsis>
+      </refsynopsisdiv>
+      
+      <refsect1>
+	<title>Arguments and Values</title>
+
+	<variablelist>
+	  <varlistentry>
+	    <term>process</term>
+	    <listitem>
+	      <para>a process, typically created by <xref
+	      linkend="f_process-run-function"/> or by <xref
+	      linkend="f_make-process"/></para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry>
+	    <term>default</term>
+	    <listitem>
+	      <para>A default value to be returned if the specified
+	      process doesn't exit normally.</para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry>
+	    <term>values</term>
+	    <listitem>
+	      <para>The values returned by the specified process's
+	      initial function if that function returns, or the value
+	      of the default argument, otherwise.</para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </refsect1>
+
+      <refsect1>
+	<title>Description</title>
+	<para>Waits for the specified process to terminate.  If the
+	process terminates "normally" (if its initial function
+	returns), returns the values that that initial function
+	returnes.  If the process does not terminate normally (e.g.,
+	if it's terminated via <xref linkend="f_process-kill"/> and a
+	default argument is provided, returns the value of that
+	default argument.  If the process doesn't terminate normally
+	and no default argument is provided, signals an error.</para>
+	
+	<para>A process can't successfully join itself, and only one
+	process can successfully receive notification of another process's
+	termination.</para>
+      </refsect1>
+    </refentry>
+
+  </sect1>
+</chapter>
Index: /branches/new-random/doc/src/using.xml
===================================================================
--- /branches/new-random/doc/src/using.xml	(revision 13309)
+++ /branches/new-random/doc/src/using.xml	(revision 13309)
@@ -0,0 +1,2946 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[
+          <!ENTITY rest "<varname>&amp;rest</varname>">
+          <!ENTITY key "<varname>&amp;key</varname>">
+          <!ENTITY optional "<varname>&amp;optional</varname>">
+          <!ENTITY body "<varname>&amp;body</varname>">
+          <!ENTITY aux "<varname>&amp;aux</varname>">
+          <!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
+          <!ENTITY CCL "Clozure CL">
+          ]>
+
+<chapter id="using-ccl"><title>Using &CCL;</title>
+  
+  <!-- ============================================================ -->
+  <sect1 id="using-ccl-introduction"><title>Introduction</title>
+    
+    <para>The Common Lisp standard allows considerable latitude in the
+      details of an implementation, and each particular Common Lisp
+      system has some idiosyncrasies. This chapter describes ordinary
+      user-level features of &CCL;, including features that may be
+      part of the Common Lisp standard, but which may have quirks or
+      details in the &CCL; implementation that are not described by
+      the standard. It also describes extensions to the standard; that
+      is, features of &CCL; that are not part of the Common Lisp
+      standard at all.</para>
+
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Trace"><title>Trace</title>
+
+    <para>
+      &CCL;'s tracing facility is invoked by an extended version of the Common Lisp
+      <varname>trace</varname> macro.  Extensions allow tracing of methods, as well as finer control
+      over tracing actions.
+    </para>
+
+    <para>
+      <indexterm zone="trace"/>
+      <command><varname id="trace">TRACE</varname> {<replaceable>keyword</replaceable>
+        <replaceable>global-value</replaceable>}* {<replaceable>spec</replaceable> |
+        (<replaceable>spec</replaceable> {<replaceable>keyword</replaceable>
+        <replaceable>local-value</replaceable>}*)}* [Macro]</command>
+    </para>
+
+    <para>
+      The <varname>trace</varname> macro encapsulates the functions named by
+      <replaceable>spec</replaceable>s, causing trace actions to take place on entry and
+      exit from each function.  The default actions print a message on function entry and
+      exit. <replaceable>Keyword</replaceable>/<replaceable>value</replaceable> options
+      can be used to specify changes in the default behavior.
+    </para>
+
+    <para>
+      Invoking <varname>(trace)</varname> without arguments returns a list of functions being traced.
+    </para>
+    
+    <para>
+      A <replaceable>spec</replaceable> is either a symbol that is the name of a function, or an
+      expression of the form <varname>(setf <replaceable>symbol</replaceable>)</varname>, or a
+      specific method of a generic function in the form <varname>(:method
+        <replaceable>gf-name</replaceable> {<replaceable>qualifier</replaceable>}*
+        ({<replaceable>specializer</replaceable>}*))</varname>, where a
+      <replaceable>specializer</replaceable> can be the name of a class or an <varname>EQL</varname>
+      specializer.
+    </para>
+
+    <para>
+      A <replaceable>spec</replaceable> can also be a string naming a package, or equivalently a
+      list <varname>(:package <replaceable>package-name</replaceable>)</varname>, in order to
+      request that all functions in the package to be traced.
+    </para>
+
+    <para>
+      By default, whenever a traced function is entered or exited, a short message is
+      printed on <varname>*trace-output*</varname> showing the arguments on entry and
+      values on exit.  Options specified as key/value pairs can be used to modify this
+      behavior.  Options preceding the function <replaceable>spec</replaceable>s apply to
+      all the functions being traced.  Options specified along with a
+      <replaceable>spec</replaceable> apply to that spec only and override any
+      global options. The following options are supported:
+    </para>
+
+    <variablelist>
+
+      <varlistentry>
+	    <term><varname>:methods {T | nil}</varname></term>
+	    <listitem>
+	      <para> If true, and if applied to a <replaceable>spec</replaceable> naming a generic
+	        function, arranges to trace all the methods of the generic function in addition to the
+	        generic function itself.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:inside <replaceable>outside-spec</replaceable>
+	        | ({<replaceable>outside-spec</replaceable>}*)</varname></term>
+	    <listitem>
+	      <para>Inhibits all trace actions unless the current
+	        invocation of the function being traced is inside one of the
+	        <replaceable>outside-spec</replaceable>'s, i.e. unless a function named by one of the
+	        <replaceable>outside-spec</replaceable>'s is currently on the stack.
+	        <replaceable>outside-spec</replaceable> can name a function, a
+	        method, or a package, as above.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:if <replaceable>form</replaceable></varname></term>
+	    <term><varname>:condition <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para> Evaluates <replaceable>form</replaceable> whenever the function being traced is
+	        about to be entered, and inhibits all trace actions if <replaceable>form</replaceable>
+	        returns nil. The form may reference the lexical variable <varname>ccl::args</varname>,
+	        which is a list of the arguments in this call. <varname>:condition</varname> is just a
+	        synonym for <varname>:if</varname>, though if both are specified, both must return non-nil.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:before-if <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para> Evaluates <replaceable>form</replaceable> whenever the function being traced is
+	        about to be entered, and inhibits the entry trace actions if
+	        <replaceable>form</replaceable> returns nil.  The form may reference the lexical variable
+	        <varname>ccl::args</varname>, which is a list of the arguments in this call. If both
+	        <varname>:if</varname> and <varname>:before-if</varname> are specified, both must return
+	        non-nil in order for the before entry actions to happen.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:after-if <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para> Evaluates <replaceable>form</replaceable> whenever the function being traced has
+	        just exited, and inhibits the exit trace actions if <replaceable>form</replaceable>
+	        returns nil.  The form may reference the lexical variable <varname>ccl::vals</varname>,
+	        which is a list of values returned by this call. If both <varname>:if</varname> and
+	        <varname>:after-if</varname> are specified, both must return non-nil in order for the
+	        after exit actions to happen.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:print-before <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para> Evaluates <replaceable>form</replaceable> whenever the function being traced is
+	        about to be entered, and prints the result before printing the standard entry message.
+	        The form may reference the lexical variable <varname>ccl::args</varname>, which is a list
+	        of the arguments in this call.  To see multiple forms, use <varname>values</varname>:
+	        <varname>:print-before (values (one-thing) (another-thing))</varname>.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:print-after <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para> Evaluates <replaceable>form</replaceable> whenever the function being traced has
+	        just exited, and prints the result after printing the standard exit message.  The form may
+	        reference the lexical variable <varname>ccl::vals</varname>, which is a list of values
+	        returned by this call. To see multiple forms, use <varname>values</varname>:
+	        <varname>:print-after (values (one-thing) (another-thing))</varname>.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:print <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Equivalent to <varname>:print-before <replaceable>form</replaceable> :print-after <replaceable>form</replaceable></varname>.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:eval-before <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Evaluates <replaceable>form</replaceable> whenever the function being traced is
+	        about to be entered.  The form may reference the lexical variable
+	        <varname>ccl::args</varname>, which is a list of the arguments in this call.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:eval-after <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Evaluates <replaceable>form</replaceable> whenever the function being has just
+	        exited.  The form may reference the lexical variable <varname>ccl::vals</varname>, which
+	        is a list of values returned by this call.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:eval <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Equivalent to <varname>:eval-before <replaceable>form</replaceable>
+	          :eval-after <replaceable>form</replaceable></varname>.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:break-before <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Evaluates <replaceable>form</replaceable> whenever the function being traced is
+	        about to be entered, and if the result is non-nil, enters a debugger break loop.  The form
+	        may reference the lexical variable <varname>ccl::args</varname>, which is a list of the
+	        arguments in this call.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:break-after <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Evaluates <replaceable>form</replaceable> whenever the function being traced has
+	        just exited, and if the result is non-nil, enters a debugger break loop. The form may
+	        reference the lexical variable <varname>ccl::vals</varname>, which is a list of values
+	        returned by this call.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:break <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Equivalent to <varname>:break-before <replaceable>form</replaceable> :break-after <replaceable>form</replaceable></varname>.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:backtrace-before <replaceable>form</replaceable></varname></term>
+	    <term><varname>:backtrace <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Evaluates <replaceable>form</replaceable> whenever the function being traced is
+	        about to be entered.  The form may reference the lexical variable
+	        <varname>ccl::args</varname>, which is a list of the arguments in this call. The value
+	        returned by <replaceable>form</replaceable> is intepreted as follows:
+	      </para>
+
+	      <variablelist>
+
+	        <varlistentry>
+	          <term><varname>nil</varname></term>
+	          <listitem><para>does nothing</para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><varname>:detailed</varname></term>
+	          <listitem><para>prints a detailed backtrace to
+	              <varname>*trace-output*</varname>.</para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><varname>(:detailed <replaceable>integer</replaceable>)</varname></term>
+	          <listitem><para>prints the top <replaceable>integer</replaceable> frames of detailed
+	              backtrace to <varname>*trace-output*</varname>.
+	          </para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><replaceable>integer</replaceable></term>
+	          <listitem><para>prints top <replaceable>integer</replaceable> frames of a terse
+	              backtrace to <varname>*trace-output*</varname>.
+	          </para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>anything else</term>
+	          <listitem><para>prints a terse backtrace to <varname>*trace-output*</varname>.
+	          </para></listitem>
+	        </varlistentry>
+	      </variablelist>
+	      <para>
+	        Note that unlike with the other options, <varname>:backtrace</varname> is equivalent to
+	        <varname>:backtrace-before</varname> only, not both before and after, since it's usually
+	        not helpful to print the same backtrace both before and after the function call.
+	      </para>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+	    <term><varname>:backtrace-after <replaceable>form</replaceable></varname></term>
+	    <listitem>
+	      <para>Evaluates <replaceable>form</replaceable> whenever the function being traced has
+	        just exited.  The form may reference the lexical variable <varname>ccl::vals</varname>,
+	        which is a list of values returned by this call. The value returned by
+	        <replaceable>form</replaceable> is intepreted as follows:
+	      </para>
+
+	      <variablelist>
+
+	        <varlistentry>
+	          <term><varname>nil</varname></term>
+	          <listitem><para>does nothing</para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><varname>:detailed</varname></term>
+	          <listitem><para>prints a detailed backtrace to
+	              <varname>*trace-output*</varname>.</para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><varname>(:detailed <replaceable>integer</replaceable>)</varname></term>
+	          <listitem><para>prints the top <replaceable>integer</replaceable> frames of detailed
+	              backtrace to <varname>*trace-output*</varname>.
+	          </para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><replaceable>integer</replaceable></term>
+	          <listitem><para>prints top <replaceable>integer</replaceable> frames of a terse
+	              backtrace to <varname>*trace-output*</varname>.
+	          </para></listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term>anything else</term>
+	          <listitem><para>prints a terse backtrace to <varname>*trace-output*</varname>.
+	          </para></listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>:before</varname> <replaceable>action</replaceable></term>
+        <listitem>
+	      <para>specifies the action to be taken just before the traced function is entered.  <replaceable>action</replaceable> is one of:</para>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term><varname>:print</varname></term>
+	          <listitem>
+		        <para>The default, prints a short indented message showing the function name and the invocation arguments</para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><varname>:break</varname></term>
+	          <listitem>
+		        <para>Equivalent to <varname>:before :print :break-before t</varname></para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><varname>:backtrace</varname></term>
+	          <listitem>
+		        <para>Equivalent to <varname>:before :print :backtrace-before t</varname></para>
+	          </listitem>
+	        </varlistentry>
+
+
+	        <varlistentry>
+	          <term><replaceable>function</replaceable></term>
+	          <listitem>
+		        <para>
+                  Any other value is interpreted as a function to call on entry instead of
+                  printing the standard entry message.  It is called with its first
+                  argument being the name of the function being traced, the remaining
+                  arguments being all the arguments to the function being traced, and
+                  <varname>ccl:*trace-level*</varname> bound to the current nesting level
+                  of trace actions. </para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+	    </listitem>
+      </varlistentry>
+
+      <varlistentry>
+
+        <term><varname>:after</varname> <replaceable>action</replaceable></term>
+        <listitem>
+
+	      <para>specifies the action to be taken just after the traced function exits.  <replaceable>action</replaceable> is one of:</para>
+
+	      <variablelist>
+	        <varlistentry>
+	          <term><varname>:print</varname></term>
+	          <listitem>
+	            <para>The default, prints a short indented message showing the function name and the
+	              returned values </para>
+	          </listitem>
+	        </varlistentry>
+
+	        <varlistentry>
+	          <term><varname>:break</varname></term>
+	          <listitem>
+	            <para>Equivalent to <varname>:after :print :break-after t</varname></para>
+	          </listitem>
+	        </varlistentry>
+
+		    <varlistentry>
+		      <term><varname>:backtrace</varname></term>
+		      <listitem>
+		        <para>Equivalent to <varname>:after :print :backtrace-after t</varname></para>
+		      </listitem>
+		    </varlistentry>
+
+	        <varlistentry>
+	          <term><replaceable>function</replaceable></term>
+	          <listitem>
+	            <para>Any other value is interpreted as a function to
+	              call on exit instead of printing the standard exit
+	              message.  It is called with its first argument being
+	              the name of the function being traced, the
+	              remaining arguments being all the values returned by the function
+	              being traced, and ccl:*trace-level* bound to the current
+	              nesting level of trace actions.
+	            </para>
+	          </listitem>
+	        </varlistentry>
+	      </variablelist>
+        </listitem>
+      </varlistentry>
+
+    </variablelist>
+
+
+    <para>
+      <indexterm zone="trace-level"/>
+      <command><varname id="trace-level">CCL:*TRACE-LEVEL*</varname>    [Variable]</command>
+    </para>
+
+    <para>Variable bound to the current nesting level during execution of before and after trace actions.  The default printing actions use it to determine the amount of indentation.</para>
+
+    <para>
+      <indexterm zone="trace-max-indent"/>
+      <command><varname id="trace-max-indent">CCL:*TRACE-MAX-INDENT*</varname>    [Variable]</command>
+    </para>
+
+    <para>The default before and after print actions will not indent by more than the value of <varname>ccl:*trace-max-indent*</varname> regardless of the current trace level.</para>
+
+    <para>
+      <indexterm zone="trace-function"/>
+      <command><varname id="trace-function">CCL:TRACE-FUNCTION</varname> <replaceable>spec</replaceable> &key; {<replaceable>keyword</replaceable> <replaceable>value</replaceable>}*    [Function]</command>
+    </para>
+    
+    <para>
+      This is a functional version of the TRACE macro.  <replaceable>spec</replaceable> and
+      <replaceable>keyword</replaceable>s are as for TRACE, except that all arguments are evaluated.
+    </para>
+
+    <para>
+      <indexterm zone="trace-print-level"/>
+      <command><varname id="trace-print-level">CCL:*TRACE-PRINT-LEVEL*</varname>   [Variable]</command>
+    </para>
+
+    <para>The default print actions bind <varname>CL:*PRINT-LEVEL*</varname> to this value while
+      printing. Note that this rebinding is only in effect during the default entry and exit messages.
+      It does not apply to printing of <varname>:print-before/:print-after</varname> forms or any
+      explicit printing done by user code.</para>
+
+    <para>
+      <indexterm zone="trace-print-length"/>
+      <command><varname id="trace-print-length">CCL:*TRACE-PRINT-LENGTH*</varname>    [Variable]</command>
+    </para>
+    
+    <para>The default print actions bind <varname>CL:*PRINT-LENGTH*</varname> to this value while
+      printing. Note that this rebinding is only in effect during the default entry and exit messages.
+      It does not apply to printing of <varname>:print-before/:print-after</varname> forms or any
+      explicit printing done by user code.</para>
+
+    <para>
+      <indexterm zone="trace-bar-frequency"/>
+      <command><varname id="trace-bar-frequency">CCL:*TRACE-BAR-FREQUENCY*</varname>    [Variable]</command>
+    </para>
+
+    <para>By default, this is nil. If non-nil it should be a integer,
+    and the default entry and exit messages will print a | instead of
+    space every this many levels of indentation.</para>
+
+
+  </sect1>
+
+  <sect1 id="Unicode"><title>Unicode</title>
+
+    <para>All characters and strings in &CCL; fully support Unicode by
+    using UTF-32. There is only one <literal>CHARACTER</literal> type
+    and one <literal>STRING</literal> type in &CCL;.  There has been a
+    lot of discussion about this decision which can be found by
+    searching the openmcl-devel archives at <ulink
+    url="http://clozure.com/pipermail/openmcl-devel/"/>.  Suffice it
+    to say that we decided that the simplicity and speed advantages of
+    only supporting UTF-32 outweigh the space disadvantage.</para>
+
+
+
+  <sect2 id="unicode-characters"><title>Characters</title>
+    <para>There is one <literal>CHARACTER</literal> type in &CCL;.
+    All <literal>CHARACTER</literal>s are
+    <literal>BASE-CHAR</literal>s.  <varname>CHAR-CODE-LIMIT</varname>
+    is now <literal>#x110000</literal>, which means that all Unicode
+    characters can be directly represented.  As of Unicode 5.0, only
+    about 100,000 of 1,114,112 possible <literal>CHAR-CODE</literal>s
+    are actually defined. The function <function>CODE-CHAR</function>
+    knows that certain ranges of code values (notably
+    <literal>#xd800</literal>-<literal>#xddff</literal>) will never be
+    valid character codes and will return <literal>NIL</literal> for
+    arguments in that range, but may return a
+    non-<literal>NIL</literal> value (an undefined/non-standard
+    <literal>CHARACTER</literal> object) for other unassigned code
+    values.</para>
+
+    <para>&CCL; supports character names of the form
+    <literal>u+xxxx</literal>&mdash;where <literal>x</literal> is a
+    sequence of one or more hex digits.  The value of the hex digits
+    denotes the code of the character.  The <literal>+</literal>
+    character is optional, so <literal>#\u+0020</literal>,
+    <literal>#\U0020</literal>, and <literal>#\U+20</literal> all
+    refer to the <literal>#\Space</literal> character.</para>
+
+    <para>Characters with codes in the range
+    <literal>#xa0</literal>-<literal>#x7ff</literal> also have
+    symbolic names These are the names from the Unicode standard with
+    spaces replaced by underscores.  So
+    <literal>#\Greek_Capital_Letter_Epsilon</literal> can be used to
+    refer to the character whose <function>CHAR-CODE</function> is
+    <literal>#x395</literal>.  To see the complete list of supported
+    character names, look just below the definition for
+    <function>register-character-name</function> in
+    <literal>ccl:level-1;l1-reader.lisp</literal>.</para>
+  </sect2>
+
+
+  <sect2 id="External-Formats"><title>External Formats</title>
+    <para><function>OPEN</function>, <function>LOAD</function>, and
+    <function>COMPILE-FILE</function> all take an
+    <literal>:EXTERNAL-FORMAT</literal> keyword argument.  The value
+    of <literal>:EXTERNAL-FORMAT</literal> can be
+    <literal>:DEFAULT</literal> (the default value), a line
+    termination keyword (see <xref
+    linkend="Line-Termination-Keywords"/>), a character encoding
+    keyword (see <xref linkend="Character-Encodings"/>), an
+    external-format object created using
+    <function>CCL::MAKE-EXTERNAL-FORMAT</function> (see <xref
+    linkend="f_make-external-format"/>), or a plist with keys:
+    <literal>:DOMAIN</literal>, <literal>:CHARACTER-ENCODING</literal>
+    and <literal>:LINE-TERMINATION</literal>.  If
+    <parameter>argument</parameter> is a plist, the result of
+    <literal>(APPLY #'MAKE-EXTERNAL-FORMAT
+    <parameter>argument</parameter>)</literal> will be used.</para>
+
+    <para>If <literal>:DEFAULT</literal> is specified, then the value
+    of <varname>CCL:*DEFAULT-EXTERNAL-FORMAT*</varname> is used.  If
+    no line-termination is specified, then the value of
+    <varname>CCL:*DEFAULT-LINE-TERMINATION*</varname> is used, which
+    defaults to <literal>:UNIX</literal>.  If no character encoding is
+    specified, then
+    <varname>CCL:*DEFAULT-FILE-CHARACTER-ENCODING*</varname> is used
+    for file streams and
+    <varname>CCL:*DEFAULT-SOCKET-CHARACTER-ENCODING*</varname> is used
+    for socket streams.  The default, default character encoding is
+    <literal>NIL</literal> which is a synonym for
+    <literal>:ISO-8859-1</literal>.</para>
+
+    <para>Note that the set of keywords used to denote
+    CHARACTER-ENCODINGs and the set of keywords used to denote
+    line-termination conventions is disjoint: a keyword denotes at
+    most a character encoding or a line termination convention, but
+    never both.</para>
+
+    <para>EXTERNAL-FORMATs are objects (structures) with three
+    read-only fields that can be accessed via the functions:
+    <function>EXTERNAL-FORMAT-DOMAIN</function>,
+    <function>EXTERNAL-FORMAT-LINE-TERMINATION</function> and
+    <function>EXTERNAL-FORMAT-CHARACTER-ENCODING</function>.</para>
+
+  
+    <refentry id="f_make-external-format">
+      <indexterm zone="f_make-external-format">
+	<primary>make-external-format</primary>
+      </indexterm>
+      
+      <refnamediv>
+	<refname>MAKE-EXTERNAL-FORMAT</refname>
+	<refpurpose>Either creates a new external format object, or
+	return an existing one with the same specified slot
+	values.</refpurpose>
+	<refclass>Function</refclass>
+      </refnamediv>
+
+      <refsynopsisdiv>
+	<synopsis>
+	  <function>make-external-format</function>
+	  &key; domain character-encoding line-termination
+	  => external-format
+	</synopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+	<title>Arguments and Values</title>
+	
+	<variablelist>
+	  <varlistentry>
+	    <term>domain</term>
+	    <listitem>
+	      <para>This is used to indicate where the external
+	      format is to be used.  Its value can be almost
+	      anything.  It defaults to <literal>NIL</literal>.
+	      There are two domains that have a pre-defined meaning in
+	      &CCL;: <literal>:FILE</literal> indicates
+	      encoding for a file in the file system and
+	      <literal>:SOCKET</literal> indicates i/o to/from a
+	      socket.  The value of <parameter>domain</parameter>
+	      affects the default values for
+	      <parameter>character-encoding</parameter> and
+	      <parameter>line-termination</parameter>.</para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry>
+	    <term>character-encoding</term>
+	    <listitem>
+	      <para>A keyword that specifies the character encoding
+	      for the external format. <xref
+	      linkend="Character-Encodings"/>.  Defaults to
+	      <literal>:DEFAULT</literal> which means if
+	      <parameter>domain</parameter> is
+	      <literal>:FILE</literal> use the value of the variable
+	      <varname>CCL:*DEFAULT-FILE-CHARACTER-ENCODING*</varname>
+	      and if <parameter>domain</parameter> is
+	      <literal>:SOCKET</literal>, use the value of the
+	      variable
+	      <varname>CCL:*DEFAULT-SOCKET-CHARACTER-ENCODING*</varname>.
+	      The initial value of both of these variables is
+	      <literal>NIL</literal>, which means the
+	      <literal>:ISO-8859-1</literal> encoding.</para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry>
+	    <term>line-termination</term>
+	    <listitem>
+	      <para>A keyword that indicates a line termination
+	      keyword <xref linkend="Line-Termination-Keywords"/>.
+	      Defaults to <literal>:DEFAULT</literal> which means
+	      use the value of the variable
+	      <varname>CCL:*DEFAULT-LINE-TERMINATION*</varname>.</para>
+	    </listitem>
+	  </varlistentry>
+	  <varlistentry>
+	    <term>external-format</term>
+	    <listitem>
+	      <para>An external-format object as described above.</para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </refsect1>
+      
+      <refsect1>
+	<title>Description</title>
+	
+	<para>Despite the function's name, it doesn't necessarily create a
+	new, unique EXTERNAL-FORMAT object: two calls to
+	MAKE-EXTERNAL-FORMAT with the same arguments made in the same
+	dynamic environment return the same (eq) object.
+	</para>
+      </refsect1>
+    </refentry>
+
+  </sect2>
+
+  <sect2 id="Line-Termination-Keywords"><title>Line Termination Keywords</title>
+  <para>Line termination keywords indicate which characters are used
+  to indicate the end of a line.  On input, the external line
+  termination characters are replaced by <literal>#\Newline</literal>
+  and on output, <literal>#\Newline</literal>s are converted to the
+  external line termination characters.</para>
+  <table id="Line-Termination-Table" frame='all'><title>Line Termination Keywords</title>
+  <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+    <thead>
+      <row>
+	<entry>keyword</entry>
+	<entry>character(s)</entry>
+      </row>
+    </thead>
+    <tbody>
+      <row>
+	<entry><literal>:UNIX</literal></entry>
+	<entry><literal>#\Linefeed</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:MACOS</literal></entry>
+	<entry><literal>#\Return</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:CR</literal></entry>
+	<entry><literal>#\Return</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:CRLF</literal></entry>
+	<entry><literal>#\Return #\Linefeed</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:CP/M</literal></entry>
+	<entry><literal>#\Return #\Linefeed</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:MSDOS</literal></entry>
+	<entry><literal>#\Return #\Linefeed</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:DOS</literal></entry>
+	<entry><literal>#\Return #\Linefeed</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:WINDOWS</literal></entry>
+	<entry><literal>#\Return #\Linefeed</literal></entry>
+      </row>
+      <row>
+	<entry><literal>:INFERRED</literal></entry>
+	<entry>see below</entry>
+      </row>
+      <row>
+	<entry><literal>:UNICODE</literal></entry>
+	<entry><literal>#\Line_Separator</literal></entry>
+      </row>
+    </tbody>
+  </tgroup>
+  </table>
+  <para><literal>:INFERRED</literal> means that a stream's
+  line-termination convention is determined by looking at the contents
+  of a file.  It is only useful for <literal>FILE-STREAM</literal>s
+  that're open for <literal>:INPUT</literal> or
+  <literal>:IO</literal>.  The first buffer full of data is examined,
+  and if a <literal>#\Return</literal> character occurs before any
+  <literal>#\Linefeed</literal> character, then the line termination
+  type is set to <literal>:MACOS</literal>, otherwise it is set to
+  <literal>:UNIX</literal>.</para>
+  </sect2>
+  
+
+
+  <sect2 id="Character-Encodings"><title>Character Encodings</title>
+    <para>Internally, all characters and strings in &CCL; are in
+    UTF-32.  Externally, files or socket streams may encode characters
+    in a wide variety of ways.  The International Organization for
+    Standardization, widely known as ISO, defines many of these
+    character encodings.  &CCL; implements some of these encodings as
+    detailed below.  These encodings are part of the specification of
+    external formats <xref linkend="External-Formats"/>.  When reading
+    from a stream, characters are converted from the specified
+    external character encoding to UTF-32.  When writing to a stream,
+    characters are converted from UTF-32 to the specified character
+    encoding.</para>
+
+    <para>Internally, CHARACTER-ENCODINGs are objects (structures)
+    that are named by character encoding keywords (:ISO-8859-1,
+    :UTF-8, etc.).  The structures contain attributes of the encoding
+    and functions used to encode/decode external data, but unless
+    you're trying to define or debug an encoding there's little reason
+    to know much about the CHARACTER-ENCODING objects and it's usually
+    preferable to refer to a character encoding by its name.
+    </para>
+
+    <para>
+    </para>
+
+    <sect3><title>Encoding Problems</title>
+      <para>On output to streams with character encodings that can
+      encode the full range of Unicode&mdash;and on input from any
+      stream&mdash;"unencodable characters" are represented using the
+      Unicode #\Replacement_Character (= #\U+fffd); the presence of
+      such a character usually indicates that something got lost in
+      translation.  Either data wasn't encoded properly or there was a
+      bug in the decoding process.</para>
+    </sect3>
+
+    <sect3><title>Byte Order Marks</title>
+      <para>The endianness of a character encoding is sometimes
+      explicit, and sometimes not.  For example,
+      <literal>:UTF-16BE</literal> indicates big-endian, but
+      <literal>:UTF-16</literal> does not specify endianness.  A byte
+      order mark is a special character that may appear at the
+      beginning of a stream of encoded characters to specify the
+      endianness of a multi-byte character encoding.  (It may also be
+      used with UTF-8 character encodings, where it is simply used to
+      indicate that the encoding is UTF-8.)</para>
+
+      <para>&CCL; writes a byte order mark as the first character
+      of a file or socket stream when the endianness of the character
+      encoding is not explicit.  &CCL; also expects a byte order
+      mark on input from streams where the endianness is not
+      explicit. If a byte order mark is missing from input data, that
+      data is assumed to be in big-endian order.</para>
+
+      <para>A byte order mark from a UTF-8 encoded input stream is not
+      treated specially and just appears as a normal character from
+      the input stream.  It is probably a good idea to skip over this
+      character.</para>
+    </sect3>
+
+  <sect3><title><function>DESCRIBE-CHARACTER-ENCODINGS</function></title>
+    <para>The set of character encodings supported by &CCL; can be
+    retrieved by calling
+    <function>CCL:DESCRIBE-CHARACTER-ENCODINGS</function>.</para>
+
+
+      <refentry id="f_describe-character-encodings">
+	<indexterm zone="f_describe-character-encodings">
+	  <primary>[fn-name]</primary>
+	</indexterm>
+
+	<refnamediv>
+	  <refname>DESCRIBE-CHARACTER-ENCODINGS</refname>
+	  <refpurpose>Writes descriptions of defined character
+	  encodings to <varname>*terminal-io*</varname>.</refpurpose>
+	  <refclass>Function</refclass>
+	</refnamediv>
+
+	<refsynopsisdiv>
+	  <synopsis>
+	    <function>describe-character-encodings</function>
+	  </synopsis>
+	</refsynopsisdiv>
+
+	<refsect1>
+	  <title>Description</title>
+
+	  <para>Writes descriptions of all defined character encodings
+	  to <varname>*terminal-io*</varname>.  These descriptions
+	  include the names of the encoding's aliases and a doc string
+	  which briefly describes each encoding's properties and
+	  intended use.</para>
+	</refsect1>
+
+	<refsect1>
+	  <title>See Also</title>
+	 
+	  <simplelist type="inline">
+	    <member><xref linkend="Character-Encodings"/></member>
+	    <member><xref linkend="External-Formats"/></member>
+	    <member><xref linkend="Supported-Character-Encodings"/></member>
+	  </simplelist>
+	</refsect1>
+      </refentry>
+  </sect3>
+
+  <sect3 id="Supported-Character-Encodings"><title>Supported Character Encodings</title>
+     <para>The list of supported encodings is reproduced here.  Most
+     encodings have aliases, e.g. the encoding named
+     <literal>:ISO-8859-1</literal> can also be referred to by the
+     names <literal>:LATIN1</literal> and <literal>:IBM819</literal>,
+     among others.  Where possible, the keywordized name of an
+     encoding is equivalent to the preferred MIME charset name (and
+     the aliases are all registered IANA charset names.)</para>
+
+  <variablelist>
+    <varlistentry><term><literal>:ISO-8859-1</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which all character codes map to their Unicode
+       equivalents. Intended to support most characters used in most
+       Western European languages.</para>
+       <para>&CCL; uses ISO-8859-1 encoding for
+       <varname>*TERMINAL-IO*</varname> and for all streams whose
+       EXTERNAL-FORMAT isn't explicitly specified.  The default for
+       <varname>*TERMINAL-IO*</varname> can be set via the
+       <literal>-K</literal> command-line argument (see <xref
+       linkend="Command-Line-Options"/>).
+       </para>
+       <para>ISO-8859-1 just covers the first 256 Unicode code
+       points, where the first 128 code points are equivalent to
+       US-ASCII.  That should be pretty much equivalent to what
+       earliers versions of &CCL; did that only supported 8-bit characters,
+       but it may not be optimal for users working in a particular
+       locale.</para>
+       <para>Aliases: <literal>:ISO_8859-1, :LATIN1, :L1,
+       :IBM819, :CP819, :CSISOLATIN1</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-2</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in most languages used in
+       Central/Eastern Europe.</para>
+       <para>Aliases: <literal>:ISO_8859-2, :LATIN-2, :L2,
+       :CSISOLATIN2</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-3</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in most languages used in
+       Southern Europe.</para>
+       <para>Aliases: <literal>:ISO_8859-3, :LATIN,3 :L3,
+       :CSISOLATIN3</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-4</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in most languages used in
+       Northern Europe.</para>
+       <para>Aliases: <literal>:ISO_8859-4, :LATIN4, :L4, :CSISOLATIN4</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-5</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Cyrillic
+       alphabet.</para>
+       <para>Aliases: <literal>:ISO_8859-5, :CYRILLIC, :CSISOLATINCYRILLIC,
+       :ISO-IR-144</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-6</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Arabic
+       alphabet.</para>
+       <para>Aliases: <literal>:ISO_8859-6, :ARABIC, :CSISOLATINARABIC,
+       :ISO-IR-127</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-7</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Greek
+       alphabet.</para>
+       <para>Aliases: <literal>:ISO_8859-7, :GREEK, :GREEK8, :CSISOLATINGREEK,
+       :ISO-IR-126, :ELOT_928, :ECMA-118</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-8</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Hebrew
+       alphabet.</para>
+       <para>Aliases: <literal>:ISO_8859-8, :HEBREW, :CSISOLATINHEBREW,
+       :ISO-IR-138</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-9</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#xcf map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in the Turkish
+       alphabet.</para>
+       <para>Aliases: <literal>:ISO_8859-9, :LATIN5, :CSISOLATIN5,
+       :ISO-IR-148</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-10</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Nordic
+       alphabets.</para>
+       <para>Aliases: <literal>:ISO_8859-10, :LATIN6, :CSISOLATIN6,
+       :ISO-IR-157</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-11</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found the Thai
+       alphabet.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-13</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Baltic
+       alphabets.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-14</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Celtic
+       languages.</para>
+       <para>Aliases: <literal>:ISO_8859-14, :ISO-IR-199, :LATIN8, :L8,
+       :ISO-CELTIC</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-15</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Western European languages
+       (including the Euro sign and some other characters missing from
+       ISO-8859-1.</para>
+       <para>Aliases: <literal>:ISO_8859-15, :LATIN9</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:ISO-8859-16</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x9f map to their Unicode equivalents and
+       other codes map to other Unicode character values.  Intended to
+       provide most characters found in Southeast European
+       languages.</para>
+       <para>Aliases: <literal>:ISO_8859-16, :ISO-IR-199, :LATIN8, :L8,
+       :ISO-CELTIC</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:MACINTOSH</literal></term>
+       <listitem><para>An 8-bit, fixed-width character encoding in
+       which codes #x00-#x7f map to their Unicode equivalents and
+       other codes map to other Unicode character values.
+       Traditionally used on Classic MacOS to encode characters used
+       in western languages.</para>
+       <para>Aliases: <literal>:MACOS-ROMAN, :MACOSROMAN, :MAC-ROMAN,
+       :MACROMAN</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UCS-2</literal></term>
+       <listitem><para>A 16-bit, fixed-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit word.  The endianness of the encoded data is
+       indicated by the endianness of a byte-order-mark character
+       (#u+feff) prepended to the data; in the absence of such a
+       character on input, the data is assumed to be in big-endian
+       order.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UCS-2BE</literal></term>
+       <listitem><para>A 16-bit, fixed-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit big-endian word. The encoded data is implicitly
+       big-endian; byte-order-mark characters are not interpreted on
+       input or prepended to output.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UCS-2LE</literal></term>
+       <listitem><para>A 16-bit, fixed-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit little-endian word. The encoded data is
+       implicitly little-endian; byte-order-mark characters are not
+       interpreted on input or prepended to output.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:US-ASCII</literal></term>
+       <listitem><para>An 7-bit, fixed-width character encoding in
+       which all character codes map to their Unicode
+       equivalents. </para>
+       <para>Aliases: <literal>:CSASCII, :CP63,7 :IBM637, :US,
+       :ISO646-US, :ASCII, :ISO-IR-6</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UTF-16</literal></term>
+       <listitem><para>A 16-bit, variable-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit word and characters with larger codes can be
+       encoded in a pair of 16-bit words.  The endianness of the
+       encoded data is indicated by the endianness of a
+       byte-order-mark character (#u+feff) prepended to the data; in
+       the absence of such a character on input, the data is assumed
+       to be in big-endian order. Output is written in native
+       byte-order with a leading byte-order mark.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UTF-16BE</literal></term>
+       <listitem><para>A 16-bit, variable-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit big-endian word and characters with larger
+       codes can be encoded in a pair of 16-bit big-endian words.  The
+       endianness of the encoded data is implicit in the encoding;
+       byte-order-mark characters are not interpreted on input or
+       prepended to output.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UTF-16LE</literal></term>
+       <listitem><para>A 16-bit, variable-length encoding in which
+       characters with CHAR-CODEs less than #x10000 can be encoded in
+       a single 16-bit little-endian word and characters with larger
+       codes can be encoded in a pair of 16-bit little-endian words.
+       The endianness of the encoded data is implicit in the encoding;
+       byte-order-mark characters are not interpreted on input or
+       prepended to output.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UTF-32</literal></term>
+       <listitem><para>A 32-bit, fixed-length encoding in which all
+       Unicode characters can be encoded in a single 32-bit word.  The
+       endianness of the encoded data is indicated by the endianness
+       of a byte-order-mark character (#u+feff) prepended to the data;
+       in the absence of such a character on input, input data is
+       assumed to be in big-endian order.  Output is written in native
+       byte order with a leading byte-order mark.</para>
+       <para>Alias: <literal>:UTF-4</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UTF-32BE</literal></term>
+       <listitem><para>A 32-bit, fixed-length encoding in which all
+       Unicode characters encoded in a single 32-bit word. The encoded
+       data is implicitly big-endian; byte-order-mark characters are
+       not interpreted on input or prepended to
+       output.</para>
+       <para>Alias: <literal>:UCS-4BE</literal></para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UTF-8</literal></term>
+       <listitem><para>An 8-bit, variable-length character encoding in
+       which characters with CHAR-CODEs in the range #x00-#x7f can be
+       encoded in a single octet; characters with larger code values
+       can be encoded in 2 to 4 bytes.</para></listitem>
+     </varlistentry>
+    <varlistentry><term><literal>:UTF-32LE</literal></term>
+       <listitem><para>A 32-bit, fixed-length encoding in which all
+       Unicode characters can encoded in a single 32-bit word. The
+       encoded data is implicitly little-endian; byte-order-mark
+       characters are not interpreted on input or prepended to
+       output.</para>
+       <para>Alias: <literal>:UCS-4LE</literal></para></listitem>
+     </varlistentry>
+     <varlistentry><term><literal>:Windows-31j</literal></term>
+     <listitem><para>An 8-bit, variable-length character encoding in
+     which character code points in the range #x00-#x7f can be encoded
+     in a single octet; characters with larger code values can be
+     encoded in 2 bytes.</para>
+     <para>Aliases: <literal>:CP932, :CSWINDOWS31J</literal></para></listitem>
+     </varlistentry>
+     <varlistentry><term><literal>:EUC-JP</literal></term>
+     <listitem><para>An 8-bit, variable-length character encoding in
+     which character code points in the range #x00-#x7f can be encoded
+     in a single octet; characters with larger code values can be
+     encoded in 2 bytes.</para>
+     <para>Alias: <literal>:EUCJP</literal></para></listitem>
+     </varlistentry>
+   </variablelist>
+ </sect3>
+
+ <sect3><title>Encoding and Decoding Strings</title>
+ <para>&CCL; provides functions to encode and decode strings
+to and from vectors of type (simple-array (unsigned-byte 8)).</para>
+
+<refentry id="count-characters-in-octet-vector">
+  <indexterm zone="count-characters-in-octet-vector">
+    <primary>count-characters-in-octet-vector</primary>
+  </indexterm>
+
+  <refnamediv>
+    <refname>count-characters-in-octet-vector</refname>
+    <refpurpose></refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis>
+	<function>count-characters-in-octet-vector</function>
+	<parameter>vector</parameter>
+	<parameter>&key;</parameter>
+	<parameter>start</parameter>
+	<parameter>end</parameter>
+	<parameter>external-format</parameter>
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Description</title>
+  <para>
+    Returns the number of characters that would be produced by
+    decoding <varname>vector</varname> (or the subsequence thereof
+    delimited by <varname>start</varname> and <varname>end</varname>)
+    according to <varname>external-format</varname>.
+  </para>
+  </refsect1>
+</refentry>
+
+<refentry id="decode-string-from-octets">
+  <indexterm zone="decode-string-from-octets">
+    <primary>"decode-string-from-octets</primary>
+  </indexterm>
+
+  <refnamediv>
+    <refname>decode-string-from-octets</refname>
+    <refpurpose></refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis>
+	<function>decode-string-from-octets</function>
+	<parameter>vector</parameter>
+	<parameter>&key;</parameter>
+	<parameter>start</parameter>
+	<parameter>end</parameter>
+	<parameter>external-format</parameter>
+	<parameter>string</parameter>
+    </synopsis>
+  </refsynopsisdiv>
+
+
+  <refsect1><title>Description</title>
+  <para>
+    Decodes the octets in <varname>vector</varname> (or the subsequence
+    of it delimited by <varname>start</varname> and
+    <varname>end</varname>) into a string according
+    to <varname>external-format</varname>.
+  </para>
+  <para>
+    If <varname>string</varname> is supplied, output will be written into it.
+    It must be large enough to hold the decoded characters.  If <varname>
+    string</varname> is not supplied, a new string will be allocated to
+    hold the decoded characters.
+  </para>
+  <para>
+    Returns, as multiple values, the decoded string and the position in
+    <varname>vector</varname> where the decoding ended.
+  </para>
+  </refsect1>
+</refentry>
+
+<refentry id="encode-string-to-octets">
+  <indexterm zone="encode-string-to-octets">
+    <primary>encode-string-to-octets</primary>
+  </indexterm>
+
+  <refnamediv>
+    <refname>encode-string-to-octets</refname>
+    <refpurpose></refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis>
+	<function>encode-string-to-octets</function>
+	<parameter>string</parameter>
+	<parameter>&key;</parameter>
+	<parameter>start</parameter>
+	<parameter>end</parameter>
+	<parameter>external-format</parameter>
+	<parameter>use-byte-order-mark</parameter>
+	<parameter>vector</parameter>
+	<parameter>vector-offset</parameter>
+    </synopsis>
+  </refsynopsisdiv>
+
+
+  <refsect1><title>Description</title>
+  <para>
+    Encodes <varname>string</varname> (or the substring delimited by
+    <varname>start</varname> and <varname>end</varname>)
+    into <varname>external-format</varname> and returns, as multiple
+    values, a vector of octets containing the encoded data and an integer
+    that specifies the offset into the vector where the encoded data ends.
+  </para>
+  <para>
+    When <varname>use-byte-order-mark</varname> is true, a byte-order mark
+    will be included in the encoded data.
+  </para>
+  <para>
+    If <varname>vector</varname> is supplied, output will be written
+    to it.  It must be of type (simple-array (unsigned-byte 8)) and be
+    large enough to hold the encoded data.  If it is not supplied, the function
+    will allocate a new vector.
+  </para>
+  <para>
+    If <varname>vector-offset</varname> is supplied, data will be written
+    into the output vector starting at that offset.
+  </para>
+  </refsect1>
+</refentry>
+
+<refentry id="string-size-in-octets">
+  <indexterm zone="string-size-in-octets">
+    <primary>string-size-in-octets</primary>
+  </indexterm>
+
+  <refnamediv>
+    <refname>string-size-in-octets</refname>
+    <refpurpose></refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis>
+	<function>string-size-in-octets</function>
+	<parameter>string</parameter>
+	<parameter>&key;</parameter>
+	<parameter>start</parameter>
+	<parameter>end</parameter>
+	<parameter>external-format</parameter>
+	<parameter>use-byte-order-mark</parameter>
+    </synopsis>
+  </refsynopsisdiv>
+
+
+  <refsect1><title>Description</title>
+  <para>
+    Returns the number of octets required to encode
+    <varname>string</varname> (or the substring delimited by
+    <varname>start</varname> and <varname>end</varname>) into
+    <varname>external-format</varname>.
+  </para>
+  <para>
+    When <varname>use-byte-order-mark</varname> is true, the returned
+    size will include space for a byte-order marker.
+  </para>
+  </refsect1>
+</refentry>
+
+ </sect3>
+
+
+  </sect2>
+
+  </sect1>
+
+  <sect1 id="Pathanmes"><title>Pathnames</title>
+
+    <sect2 id="pathname-tilde-expansion">
+      <title>Pathname Expansion</title>
+      <para>Leading tilde (~) characters in physical pathname namestrings
+        are expanded in the way that most shells do:</para>
+      
+      <para><literal>"~user/..."</literal> can be used to refer to an absolute pathname rooted
+        at the home directory of the user named "user".</para>
+      
+      <para><literal>"~/..."</literal> can be used to refer to an absolute pathname rooted at
+        the home directory of the current user.</para>
+    </sect2>
+
+    <sect2 id="Predefined-Logical-Hosts"><title>Predefined Logical Hosts</title>
+
+      <para>&CCL; sets up logical pathname translations for logical hosts:  <literal>ccl</literal> and <literal>home</literal></para>
+
+      <indexterm><primary>CCL Logical Host</primary></indexterm>
+      <para>The <literal>CCL</literal> logical host should point to the
+        <literal>ccl</literal> directory.  It is used for a variety of
+        purposes by &CCL; including: locating &CCL; source code,
+        <literal>require</literal> and <literal>provide</literal>, accessing
+        foreign function information, and the &CCL; build process. It
+        is set to the value of the environment variable
+        <varname>CCL_DEFAULT_DIRECTORY</varname>, which is set by the
+        openmcl shell script <xref linkend="The-ccl-Shell-Script"/>.  If
+        <varname>CCL_DEFAULT_DIRECTORY</varname> is not set, then it is set
+        to the directory containing the current heap image.</para>
+    </sect2>
+    
+    
+    <sect2 id="pathnames-on-darwin">
+      <title>OS X (Darwin)</title>
+      
+      <para>&CCL; assumes that pathname strings are decomposed UTF-8.</para>
+    </sect2>
+    <sect2 id="pathnames-on-linux">
+      <title>Linux</title>
+      
+      <para>Pathname strings are treated as null-terminated strings
+        coded in the encoding named by the value returned by the function
+      <varname>CCL:PATHNAME-ENCODING-NAME</varname>.  This value may be changed
+      with <varname>SETF</varname>.</para>
+    </sect2>
+    <sect2 id="pathnames-on-freebsd">
+      <title>FreeBSD</title>
+      
+      <para>Pathname strings are treated as null-terminated strings
+        encoded according to the current locale; a future release may
+        change this convention to use UTF-8.</para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="Memory-Mapped-Files">
+    <title>Memory-mapped Files</title>
+    <para>In release 1.2 and later, &CCL;
+      supports <glossterm linkend="memory_mapped_file">memory-mapped
+        files</glossterm>. On operating systems that support memory-mapped
+      files (including Mac OS X, Linux, and FreeBSD), the operating
+      system can arrange for a range of virtual memory addresses to
+      refer to the contents of an open file. As long as the file remains
+      open, programs can read values from the file by reading addresses
+      in the mapped range.</para>
+
+    <para>Using memory-mapped files may in some cases be more
+      efficient than reading the contents of a file into a data
+      structure in memory.</para>
+
+    <para>&CCL; provides the
+      functions <varname>CCL:MAP-FILE-TO-IVECTOR</varname>
+      and <varname>CCL:MAP-FILE-TO-OCTET-VECTOR</varname> to support
+      memory-mapping. These functions return vectors whose contents are
+      the contents of memory-mapped files. Reading an element of such a
+      vector returns data from the corresponding position in the
+      file.</para>
+
+    <para>Without memory-mapped files, a common idiom for reading the
+      contents of files might be something like this:</para>
+
+    <programlisting>
+(let* ((stream (open pathname :direction :input :element-type '(unsigned-byte 8)))
+       (vector (make-array (file-size-to-vector-size stream)
+                           :element-type '(unsigned-byte 8))))
+  (read-sequence vector stream))
+    </programlisting>
+
+    <para>Using a memory-mapped files has a result that is the same in
+      that, like the above example, it returns a vector whose contents are
+      the same as the contents of the file. It differs in that the above
+      example creates a new vector in memory and copies the file's
+      contents into it; using a memory-mapped file instead arranges for
+      the vector's elements to point to the file's contents on disk
+      directly, without copying them into memory first.</para>
+
+    <para>The vectors returned by <varname>CCL:MAP-FILE-TO-IVECTOR</varname>
+      and <varname>CCL:MAP-FILE-TO-OCTET-VECTOR</varname> are read-only; any
+      attempt to change an element of a vector returned by these
+      functions results in a memory-access error. &CCL; does not
+      currently support writing data to memory-mapped files.</para>
+
+    <para>Vectors created by <varname>CCL:MAP-FILE-TO-IVECTOR</varname>
+      and <varname>CCL:MAP-FILE-TO-OCTET-VECTOR</varname> are required to
+      respect &CCL;'s limit on the total size of an array. That means
+      that you cannot use these functions to create a vector longer
+      than <varname>ARRAY-TOTAL-SIZE-LIMIT</varname>, even if the filesystem
+      supports file sizes that are larger. The value
+      of <varname>ARRAY-TOTAL-SIZE-LIMIT</varname> is <varname>(EXPT 2 24)</varname>
+      on 32-but platforms; and <varname>(EXPT 2 56)</varname> on 64-bit
+      platforms.</para>
+
+    <para>
+      <indexterm zone="map-file-to-ivector"/>
+      <command><varname id="map-file-to-ivector">CCL:MAP-FILE-TO-IVECTOR</varname>
+        <parameter>pathname</parameter>
+        <parameter>element-type</parameter>
+        [Function]</command>
+    </para>
+
+    <variablelist>
+      <varlistentry>
+        <term><varname>pathname</varname></term>
+        <listitem>
+          <para>The pathname of the file to be memory-mapped.</para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><varname>element-type</varname></term>
+        <listitem>
+          <para>The element-type of the vector to be
+            created. Specified as
+            a <glossterm linkend="type-specifier">type-specifier</glossterm>
+            that names a subtype of either <varname>SIGNED-BYTE</varname>
+            or <varname>UNSIGNED-BYTE</varname>.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+
+    <para>
+      The <varname>map-file-to-ivector</varname> function tries to
+      open the file at <parameter>pathname</parameter> for reading. If
+      successful, the function maps the file's contents to a range of
+      virtual addresses. If successful, it returns a read-only vector
+      whose element-type is given
+      by <parameter>element-type</parameter>, and whose contents are
+      the contents of the memory-mapped file.
+    </para>
+
+    <para>The returned vector is
+      a <glossterm linkend="displaced-array">displaced-array</glossterm>
+      whose element-type is <varname>(UPGRADED-ARRAY-ELEMENT-TYPE
+        element-type)</varname>. The target of the displaced array is a
+      vector of type <varname>(SIMPLE-ARRAY element-type (*))</varname> whose
+      elements are the contents of the memory-mapped file.</para>
+
+    <para>Because of alignment issues, the mapped file's contents
+      start a few bytes (4 bytes on 32-bit platforms, 8 bytes on
+      64-bit platforms) into the vector. The displaced array returned
+      by <varname>CCL:MAP-FILE-TO-IVECTOR</varname> hides this overhead, but
+      it's usually more efficient to operate on the underlying simple
+      1-dimensional array.  Given a displaced array (like the value
+      returned by <varname>CCL:MAP-FILE-TO-IVECTOR</varname>), the function
+      <varname>ARRAY-DISPLACEMENT</varname> returns the underlying array and
+      the displacement index in elements.
+    </para>
+
+    <para>Currently, &CCL; supports only read operations on
+      memory-mapped files. If you try to change the contents of an array
+      returned by <varname>map-file-to-ivector</varname>, &CCL; signals
+      a memory error.</para>
+
+    <para>
+      <indexterm zone="unmap-ivector"/>
+      <command><varname id="unmap-ivector">CCL:UNMAP-IVECTOR</varname>
+        <parameter>displaced-array</parameter>
+        [Function]</command>
+    </para>
+
+    <para>If the argument is a displaced-array returned
+      by <varname>map-file-to-ivector</varname>, and if it has not yet
+      been unmapped by this function,
+      then <varname>unmap-ivector</varname> undoes the memory mapping,
+      closes the mapped file, and changes the displaced-array so that its
+      target is an empty vector (of length zero).</para>
+
+    <para>
+      <indexterm zone="map-file-to-octet-vector"/>
+      <command><varname id="map-file-to-octet-vector">CCL:MAP-FILE-TO-OCTET-VECTOR</varname>
+        <parameter>pathname</parameter>
+        [Function]</command>
+    </para>
+
+    <para>This function is a synonym for <varname>(CCL:MAP-FILE-TO-IVECTOR
+        pathname '(UNSIGNED-BYTE 8))</varname> It is provided as a convenience
+      for the common case of memory-mapping a file as a vector of
+      bytes.</para>
+
+    <para>
+      <indexterm zone="unmap-octet-vector"/>
+      <command><varname id="unmap-octet-vector">CCL:UNMAP-OCTET-VECTOR</varname>
+        <parameter>displaced-array</parameter>
+        [Function]</command>
+    </para>
+
+    <para>This function is a synonym
+      for <varname>(CCL:UNMAP-IVECTOR)</varname></para>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Static_Variables">
+    <title>Static Variables</title>
+
+    <para>&CCL; supports the definition
+      of <glossterm linkend="static_variable">static
+        variables</glossterm>, whose values are the same across threads,
+      and which may not be dynamically bound. The value of a static
+      variable is thus the same across all threads; changing the value
+      in one thread changes it for all threads.</para> 
+
+    <para>Attempting to dynamically rebind a static variable (for
+      instance, by using <varname>LET</varname>, or using the variable name as
+      a parameter in a <varname>LAMBDA</varname> form) signals an
+      error. Static variables are shared global resources; a dynamic
+      binding is private to a single thread.</para>
+
+    <para>Static variables therefore provide a simple way to share
+      mutable state across threads. They also provide a simple way to
+      introduce race conditions and obscure bugs into your code, since
+      every thread reads and writes the same instance of a given static
+      variable. You must take care, therefore, in how you change the
+      values of static variables, and use normal multithreaded
+      programming techniques, such as locks or semaphores, to protect
+      against race conditions.</para>
+
+    <para>In &CCL;, access to a static variable is usually faster than
+      access to a special variable that has not been declared
+      static.</para>
+
+    <para>
+      <indexterm zone="defstatic"/>
+      <command><varname id="defstatic">DEFSTATIC</varname>
+        <parameter>var</parameter>
+        <parameter>value</parameter>
+        &key;
+        <parameter>doc-string</parameter>
+        [Macro]</command>
+    </para>
+    
+    <variablelist>
+      <varlistentry>
+        <term><varname>var</varname></term>
+        <listitem>
+          <para>The name of the new static variable.</para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><varname>value</varname></term>
+        <listitem>
+          <para>The initial value of the new static variable.</para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><varname>doc-string</varname></term>
+        <listitem>
+          <para>A documentation string that is assigned to the new
+            variable.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>Proclaims the
+      variable <glossterm linkend="special_variable">special</glossterm>,
+      assigns the variable the supplied value, and assigns
+      the <varname>doc-string</varname> to the
+      variable's <varname>VARIABLE</varname> documentation. Marks the
+      variable static, preventing any attempt to dynamically rebind
+      it. Any attempt to dynamically rebind <varname>var</varname>
+      signals an error.</para>
+  </sect1>
+
+  <!-- ============================================================ -->
+  <sect1 id="Saving-Applications">
+    <title>Saving Applications</title>
+    <indexterm zone="Saving-Applications">
+      <primary>save-application</primary>
+    </indexterm>
+
+    <para>&CCL; provides the
+      function <literal>CCL:SAVE-APPLICATION</literal>, which creates a file
+      containing an archived Lisp memory image.</para>
+
+    <para>&CCL; consists of a small executable called the
+      Lisp <glossterm linkend="lisp_image">kernel</glossterm>, which
+      implements the very lowest level features of the Lisp system, and
+      an <glossterm linkend="lisp_image">image</glossterm>, which
+      contains the in-memory representation of most of the Lisp system,
+      including functions, data structures, variables, and so on. When
+      you start &CCL;, you are launching the kernel, which then locates
+      and reads an image file, restoring the archived image in
+      memory. Once the image is fully restored, the Lisp system is
+      running.</para>
+
+    <para>Using <literal>CCL:SAVE-APPLICATION</literal>, you can create a
+      file that contains a modified image, one that includes any changes
+      you've made to the running Lisp system. If you later pass your
+      image file to the &CCL; kernel as a command-line parameter, it
+      then loads your image file instead of its default one, and &CCL;
+      starts up with your modifications.</para>
+
+    <para>If this scenario seems to you like a convenient way to
+      create an application, that's just as intended. You can create an
+      application by modifying the running Lisp until it does what you
+      want, then use <literal>CCL:SAVE-APPLICATION</literal> to preserve your
+      changes and later load them for use.</para>
+
+    <para>In fact, you can go further than that. You can replace
+      &CCL;'s <glossterm linkend="toplevel_function">toplevel
+        function</glossterm> with your own, and then, when the image is
+      loaded, the Lisp system immediately performs your tasks rather
+      than the default tasks that make it a Lisp development system. If
+      you save an image in which you have done this, the resulting Lisp
+      system is your tool rather than a Lisp development system.</para>
+
+    <para>You can go a step further still. You can
+      tell <literal>CCL:SAVE-APPLICATION</literal> to prepend the Lisp kernel
+      to the image file. Doing this makes the resulting image into a
+      self-contained executable binary. When you run the resulting file,
+      the Lisp kernel immediately loads the attached image file and runs
+      your saved system. The Lisp system that starts up can have any
+      behavior you choose. It can be a Lisp development system, but with
+      your customizations; or it can immediately perform some task of
+      your design, making it a specialized tool rather than a general
+      development system.</para>
+
+    <para>In other words, you can develop any application you like by
+      interactively modifying &CCL; until it does what you want, then
+      using <literal>CCL:SAVE-APPLICATION</literal> to preserve your changes
+      in an executable image.</para>
+
+    <para>On Mac OS X,
+      the <link linkend="application_builder">application builder</link>
+      uses <literal>CCL:SAVE-APPLICATION</literal> to create the executable
+      portion of the <glossterm linkend="application_bundle">application
+        bundle</glossterm>. Double-clicking the application bundle runs
+      the executable image created
+      by <literal>CCL:SAVE-APPLICATION</literal>.</para>
+
+    <para>Also on Mac OS X, &CCL; supports an object type
+      called <literal>MACPTR</literal>, which is the type of pointers into the
+      foreign (Mac OS) heap. Examples of
+      commonly-user <literal>MACPTR</literal> objects are Cocoa windows and
+      other dynamically-allocated Mac OS system objects.</para>
+
+    <para>Because a <literal>MACPTR</literal> object is a pointer into a
+      foreign heap that exists for the lifetime of the running Lisp
+      process, and because a saved image is used by loading it into a
+      brand new Lisp process, saved <literal>MACPTR</literal> objects cannot
+      be relied on to point to the same things when reconstituted from a
+      saved image. In fact, a restored <literal>MACPTR</literal> object might
+      point to anything at all&mdash;for example an arbitrary location
+      in the middle of a block of code, or a completely nonexistent
+      virtual address.</para> 
+
+    <para>For that reason, <literal>CCL:SAVE-APPLICATION</literal> converts
+      all <literal>MACPTR</literal> objects to <literal>DEAD-MACPTR</literal>
+      objects when writing them to an image
+      file. A <literal>DEAD-MACPTR</literal> is functionally identical to
+      a <literal>MACPTR</literal>, except that code that operates
+      on <literal>MACPTR</literal> objects distinguishes them
+      from <literal>DEAD-MACPTR</literal> objects and can handle them
+      appropriately&mdash;signaling errors, for example.</para>
+
+    <para>As of &CCL; 1.2, there is one exception to the conversion
+      of <literal>MACPTR</literal> to <literal>DEAD-MACPTR</literal> objects:
+      a <literal>MACPTR</literal> object that points to the address 0 is not
+      converted, because address 0 can always be relied upon to refer to
+      the same thing.</para>
+
+	<indexterm zone="Saving-Applications">
+	  <primary>+NULL-PTR+</primary>
+	</indexterm>
+    <para>As of &CCL; 1.2, the constant <literal>CCL:+NULL-PTR+</literal>
+      refers to a <literal>MACPTR</literal> object that points to address 0.</para>
+
+    <para>On all supported platforms, you can
+      use <literal>CCL:SAVE-APPLICATION</literal> to create a command-line
+      tool that runs the same way any command-line program
+      does. Alternatively, if you choose not to prepend the kernel, you
+      can save an image and then later run it by passing it as a
+      command-line parameter to the <literal>opencml</literal>
+      or <literal>opencml64</literal> script.</para>
+
+    <para>
+      <indexterm zone="save-application"/>
+      <command><varname id="save-application">SAVE-APPLICATION</varname>
+        <parameter>filename</parameter>
+        &key;
+        <parameter>toplevel-function</parameter>
+        <parameter>init-file</parameter>
+        <parameter>error-handler</parameter>
+        <parameter>application-class</parameter>
+        <parameter>clear-clos-caches</parameter>
+        <parameter>(purify t)</parameter>
+        <parameter>impurify</parameter>
+        <parameter>(mode #o644)</parameter>
+        <parameter>prepend-kernel</parameter>
+        [Function]</command>
+    </para>
+    
+    <variablelist>
+      <varlistentry>
+        <term><varname>filename</varname></term>
+        <listitem>
+          <para>The pathname of the file to be created when &CCL;
+            saves the application.</para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><varname>toplevel-function</varname></term>
+        <listitem>
+          <para>The function to be executed after startup is
+            complete. The toplevel is a function of no arguments that
+            performs whatever actions the lisp system should perform
+            when launched with this image.</para>
+          <para>If this parameter is not supplied, &CCL; uses its
+            default toplevel. The default toplevel runs
+            the <glossterm linkend="REPL">read-eval-print
+              loop</glossterm>.</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>init-file</varname></term>
+        <listitem>
+          <para>The pathname of a Lisp file to be loaded when the
+            image starts up. You can place initialization expressions in
+            this file, and use it to customize the behavior of the Lisp
+            system when it starts up.</para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><varname>error-handler</varname></term>
+        <listitem>
+          <para>The error-handling mode for the saved image. The
+            supplied value determines what happens when an error is not
+            handled by the saved image. Valid values
+            are <literal>:quit</literal> (Lisp exits with an error
+            message); <literal>:quit-quietly</literal> (Lisp exits without an
+            error message); or <literal>:listener</literal> (Lisp enters a
+            break loop, enabling you to debug the problem by interacting
+            in a listener). If you don't supply this parameter, the
+            saved image uses the default error handler
+            (<literal>:listener</literal>).</para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>application-class</varname></term>
+        <listitem>
+          <para>The CLOS class that represents the saved Lisp
+            application. Normally you don't need to supply this
+            parameter; <literal>CCL:SAVE-APPLICATION</literal> uses the
+            class <literal>CCL:LISP-DEVELOPMENT-SYSTEM</literal>. In some
+            cases you may choose to create a custom application class;
+            in that case, pass the name of the class as the value for
+            this parameter.</para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><varname>clear-clos-caches</varname></term>
+        <listitem>
+          <para>If true, ensures that CLOS caches are emptied before
+            saving the image. Normally you don't need to supply this
+            parameter, but if for some reason you want to ensure the
+            CLOS caches are clear when the image starts up, you can pass
+            any true value.</para>
+        </listitem>
+      </varlistentry>
+      
+      
+    </variablelist>
+
+    <para></para>
+  </sect1>
+
+  <sect1 id="concatenating-fasl-files">
+    <title>Concatenating FASL Files</title>
+    <para>
+      Multiple fasl files can be concatenated into a single file.
+    </para>
+  <refentry id="fasl-concatenate">
+    <indexterm zone="f_fasl-concatenate">
+      <primary>fasl-concatenate</primary>
+    </indexterm>
+
+    <refnamediv>
+      <refname>FASL-CONCATENATE</refname>
+      <refpurpose>
+	Concatenate several fasl files, producing a single output file.
+      </refpurpose>
+      <refclass>Function</refclass>
+    </refnamediv>
+    
+    <refsynopsisdiv>
+      <synopsis><function>fasl-concatenate</function> out-file fasl-files &key; (:if-exists :error)</synopsis>
+    </refsynopsisdiv>
+
+    <refsect1>
+      <title>Arguments and Values</title>
+      <variablelist>
+	<varlistentry>
+	  <term>out-file</term>
+	  <listitem>
+	    <para>
+	      Name of the file in which to store the concatenation.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>fasl-files</term>
+	  <listitem>
+	    <para>
+	      List of names of fasl files to concatenate.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>:if-exists</term>
+	  <listitem>
+	    <para>
+	      As for <function>OPEN</function>, defaults to <literal>
+	      :error</literal>
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </refsect1>
+    
+    <refsect1>
+      <title>Description</title>
+      <para>
+	Creates a fasl file which, when loaded, will have the same
+	effect as loading the individual input fasl files in the
+	specified order.  The single file might be easier to
+	distribute or install, and loading it may be at least a little
+	faster than loading the individual files (since it avoids the
+	overhead of opening and closing each file in succession.)
+      </para>
+      <para>
+	The PATHNAME-TYPE of the output file and of each input file
+	defaults to the current platform's fasl file type (.dx64fsl or
+	whatever.)  If any of the input files has a different
+	type/extension an error will be signaled, but it doesn't
+	otherwise try too hard to verify that the input files are real
+	fasl files for the current platform.
+      </para>
+    </refsect1>
+  </refentry>
+  </sect1>
+  <sect1 id="floating-point">
+    <title>Floating Point Numbers</title>
+
+    <para>
+      In &CCL;, the Common Lisp types short-float and single-float are
+      implemented as IEEE single precision values; double-float and
+      long-float are IEEE double precision values.  On 64-bit
+      platforms, single-floats are immediate values (like fixnums and
+      characters).
+    </para>
+
+  <para>
+    Floating-point exceptions are generally enabled and detected.  By
+    default, threads start up with overflow, division-by-zero, and
+    invalid enabled, and the rounding mode is set to nearest. The
+    functions <varname>SET-FPU-MODE</varname> and
+    <varname>GET-FPU-MODE</varname> provide user control over
+    floating-point behavior.
+  </para>
+
+  <refentry id="f_get-fpu-mode">
+    <indexterm zone="f_get-fpu-mode">
+      <primary>get-fpu-mode</primary>
+    </indexterm>
+
+    <refnamediv>
+      <refname>GET-FPU-MODE</refname>
+      <refpurpose>
+	Return the state of exception-enable and rounding-mode control
+	flags for the current thread.
+      </refpurpose>
+      <refclass>Function</refclass>
+    </refnamediv>
+    
+    <refsynopsisdiv>
+      <synopsis><function>get-fpu-mode</function> &optional; mode</synopsis>
+    </refsynopsisdiv>
+
+    <refsect1>
+      <title>Arguments and Values</title>
+      <variablelist>
+	<varlistentry>
+	  <term>mode</term>
+	  <listitem>
+	    <para>
+	      One of the keywords :rounding-mode, :overflow,
+	      :underflow, :division-by-zero, :invalid, :inexact.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </refsect1>
+    
+    <refsect1>
+      <title>Description</title>
+      <para>
+	If <varname>mode</varname> is supplied, returns the value of
+	the corresponding control flag for the current thread.
+      </para>
+      <para>
+	Otherwise, returns a list of keyword/value pairs which
+	describe the floating-point exception-enable and rounding-mode
+	control flags for the current thread.
+      </para>
+      <variablelist>
+	<varlistentry>
+	  <term>rounding-mode</term>
+	  <listitem>
+	    <para>
+	      One of :nearest, :zero, :positive, :negative
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>overflow, underflow, division-by-zero, invalid, inexact
+	  </term>
+	  <listitem>
+	    <para>
+	      If true, the floating-point exception is signaled.
+	      If NIL, it is masked.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </refsect1>
+  </refentry>
+
+  <refentry id="f_set-fpu-mode">
+    <indexterm zone="f_set-fpu-mode">
+      <primary>set-fpu-mode</primary>
+    </indexterm>
+
+    <refnamediv>
+      <refname>SET-FPU-MODE</refname>
+      <refpurpose>
+	Set the state of exception-enable and rounding-mode control
+	flags for the current thread.
+      </refpurpose>
+      <refclass>Function</refclass>
+    </refnamediv>
+    
+    <refsynopsisdiv>
+      <synopsis><function>set-fpu-mode</function> &key;
+      rounding-mode overflow underflow division-by-zero
+      invalid inexact</synopsis>
+    </refsynopsisdiv>
+
+    <refsect1>
+      <title>Arguments and Values</title>
+      <variablelist>
+	<varlistentry>
+	  <term>rounding-mode</term>
+	  <listitem>
+	    <para>
+	      If supplied, must be one of :nearest, :zero, :positive, or
+	      :negative.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>overflow, underflow, division-by-zero, invalid, inexact</term>
+	  <listitem>
+	    <para>NIL to mask the exception, T to signal it.</para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </refsect1>
+    
+    <refsect1>
+      <title>Description</title>
+      <para>
+	Sets the current thread's exception-enable and rounding-mode
+	control flags to the indicated values for arguments that are
+	supplied, and preserves the values assoicated with those
+	that aren't supplied.
+      </para>
+    </refsect1>
+  </refentry>
+  </sect1>
+
+  <sect1 id="watched-objects"><title>Watched Objects</title>
+  <para>
+    As of release 1.4, Clozure CL provides a way for lisp objects to
+    be watched so that a condition will be signaled when a thread
+    attempts to write to the watched object. For a certain class of
+    bugs (someone is changing this value, but I don't know who), this
+    can be extremely helpful.
+  </para>
+  <sect2 id="watched-watch"><title>WATCH</title>
+  <refentry id="f_watch">
+    <indexterm zone="f_watch">
+      <primary>watch</primary>
+    </indexterm>
+    
+    <refnamediv>
+      <refname>WATCH</refname>
+      <refpurpose>
+	Monitor a lisp object for writes.
+      </refpurpose>
+      <refclass>Function</refclass>
+    </refnamediv>
+    
+    <refsynopsisdiv>
+      <synopsis><function>watch</function> &optional; object</synopsis>
+    </refsynopsisdiv>
+    
+    <refsect1>
+      <title>Arguments and Values</title>
+      <variablelist>
+	<varlistentry>
+	  <term>object</term>
+	  <listitem>
+	    <para>
+	      Any memory-allocated lisp object.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </refsect1>
+
+    <refsect1>
+      <title>Description</title>
+      <para>
+	The WATCH function arranges for the specified object to be
+	monitored for writes. This is accomplished by copying the
+	object to its own set of virtual memory pages, which are then
+	write-protected. This protection is enforced by the computer's
+	memory-management hardware; the write-protection does not slow
+	down reads at all.
+      </para>
+      <para>
+	When any write to the object is attempted, a
+	WRITE-TO-WATCHED-OBJECT condition will be signaled.
+      </para>
+      <para>
+	When called with no arguments, WATCH returns a freshly-consed
+	list of the objects currently being watched.
+      </para>
+      <para>
+	WATCH returns NIL if the object cannot be watched (typically
+	because the object is in a static or pure memory area).
+      </para>
+    </refsect1>
+    <refsect1 id="watch-dwim"><title>DWIM</title>
+    <para>
+      WATCH operates at a fairly low level; it is not possible to
+      avoid the details of the internal representation of objects.
+      Nevertheless, as a convenience, WATCHing a standard-instance,
+      a hash-table, or a multi-dimensional or non-simple CL array
+      will watch the underlying slot-vector, hash-table-vector, or
+      data-vector, respectively.
+      </para>
+    </refsect1>
+    <refsect1 id="watch-discuss"><title>Discussion</title>
+    <para>
+      WATCH can monitor any memory-allocated lisp object.
+    </para>
+    <para>
+      In Clozure CL, a memory-allocated object is either a cons cell
+      or a uvector.
+    </para>
+    <para>
+      WATCH operates on cons cells, not lists. In order to watch a
+      chain of cons cells, each cons cell must be watched
+      individually. Because each watched cons cell takes up its own
+      own virtual memory page (4 Kbytes), it's only feasible to watch
+      relatively short lists.
+    </para>
+    <para>
+      If a memory-allocated object isn't a cons cell, then it is a
+      vector-like object called a uvector. A uvector is a
+      memory-allocated lisp object whose first word is a header that
+      describes the object's type and the number of elements that it
+      contains.
+    </para>
+    <para>
+      So, a hash table is a uvector, as is a string, a standard
+      instance, a double-float, a CL array or vector, and so forth.
+    </para>
+    <para>
+      Some CL objects, like strings and other simple vectors, map in a
+      straightforward way onto the uvector representation. It is easy
+      to understand what happens in such cases. The uvector index
+      corresponds directly to the vector index:
+    </para>
+    <programlisting>
+<![CDATA[
+? (defvar *s* "xxxxx")
+*S*
+? (watch *s*)
+"xxxxx"
+? (setf (char *s* 3) #\o)
+> Error: Write to watched uvector "xxxxx" at index 3
+>        Faulting instruction: (movl (% eax) (@ -5 (% r15) (% rcx)))
+> While executing: SET-CHAR, in process listener(1).
+> Type :POP to abort, :R for a list of available restarts.
+> Type :? for other options.
+]]>
+    </programlisting>
+    <para>
+      In the case of more complicated objects (e.g., a hash-table, a
+      standard-instance, a package, etc.), the elements of the uvector
+      are like slots in a structure. It's necessary to know which one
+      of those "slots" contains the data that will be changed when the
+      object is written to.
+    </para>
+    <para>
+      As mentioned above, watch knows about arrays, hash-tables, and
+      standard-instances, and will automatically watch the appropriate
+      data-containing element.
+    </para>
+    <para>
+      An example might make this clearer.
+    </para>
+    <programlisting>
+<![CDATA[
+? (defclass foo ()
+    (slot-a slot-b slot-c))
+#<STANDARD-CLASS FOO>
+? (defvar *a-foo* (make-instance 'foo))
+*A-FOO*
+? (watch *a-foo*)
+#<SLOT-VECTOR #xDB00D>
+;;; Note that WATCH has watched the internal slot-vector object
+? (setf (slot-value *a-foo* 'slot-a) 'foo)
+> Error: Write to watched uvector #<SLOT-VECTOR #xDB00D> at index 1
+>        Faulting instruction: (movq (% rsi) (@ -5 (% r8) (% rdi)))
+> While executing: %MAYBE-STD-SETF-SLOT-VALUE-USING-CLASS, in process listener(1).
+> Type :POP to abort, :R for a list of available restarts.
+> Type :? for other options.
+]]>
+    </programlisting>
+    <para>
+      Looking at a backtrace would presumably show what object and
+      slot name were written.
+    </para>
+    <para>
+      Note that even though the write was to slot-a, the uvector index
+      was 1 (not 0). This is because the first element of a
+      slot-vector is a pointer to the instance that owns the slots. We
+      can retrieve that to look at the object that was modified:
+    </para>
+    <programlisting>
+<![CDATA[
+1 > (uvref (write-to-watched-object-object *break-condition*) 0)
+#<FOO #x30004113502D>
+1 > (describe *)
+#<FOO #x30004113502D>
+Class: #<STANDARD-CLASS FOO>
+Wrapper: #<CLASS-WRAPPER FOO #x300041135EBD>
+Instance slots
+SLOT-A: #<Unbound>
+SLOT-B: #<Unbound>
+SLOT-C: #<Unbound>
+1 >
+]]> 
+    </programlisting>
+    </refsect1>
+  </refentry>
+</sect2>
+<sect2 id="watched-unwatch"><title>UNWATCH</title>
+<refentry id="f_unwatch">
+  <indexterm zone="f_unwatch">
+    <primary>unwatch</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>UNWATCH</refname>
+      <refpurpose>
+	Stop monitoring a lisp object for writes.
+      </refpurpose>
+      <refclass>Function</refclass>
+  </refnamediv>
+  
+  <refsynopsisdiv>
+    <synopsis><function>unwatch</function> object</synopsis>
+  </refsynopsisdiv>
+  
+  <refsect1><title>Description</title>
+  <para>
+    The UNWATCH function ensures that the specified object is in
+    normal, non-monitored memory. If the object is not currently
+    being watched, UNWATCH does nothing and returns NIL. Otherwise,
+    the newly unwatched object is returned.
+  </para>
+  </refsect1>
+</refentry>
+</sect2>
+<sect2 id="watched-write-to-watched-object">
+  <title>WRITE-TO-WATCHED-OBJECT</title>
+  <refentry id="c_write-to-watched-object">
+    <indexterm zone="c_write-to-watched-object">
+      <primary>write-to-watched-object</primary>
+    </indexterm>
+    
+    <refnamediv>
+      <refname>WRITE-TO-WATCHED-OBJECT</refname>
+      <refpurpose>
+	Condition signaled when a write to a watched object is attempted.
+      </refpurpose>
+      <refclass>Condition</refclass>
+    </refnamediv>
+
+    <refsect1><title>Discussion</title>
+    <para>
+      This condition is signaled when a watched object is written
+      to. There are three slots of interest:
+    </para>
+    <variablelist>
+      <varlistentry>
+	<term>object</term>
+	<listitem>
+	  <para>
+	    The actual object that was the destination of the write.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term>offset</term>
+	<listitem>
+	  <para>
+	    The byte offset from the tagged object pointer to the
+	    address of the write.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term>instruction</term>
+	<listitem>
+	  <para>
+	    The disassembled machine instruction that attempted the write.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+    </refsect1>
+
+    <refsect1><title>Restarts</title>
+    <para>
+      A few restarts are provided: one will skip over the faulting
+      write instruction and proceed; another offers to unwatch the
+      object and continue.
+    </para>
+    <para>
+      There is also an emulate restart. In some common cases, the
+      faulting write instruction can be emulated, enabling the write
+      to be performed without having to unwatch the object (and
+      therefore let other threads potentially write to it). If the
+      faulting instruction isn't recognized, the emulate restart will
+      not be offered.
+    </para>
+    </refsect1>
+  </refentry>
+</sect2>
+<sect2 id="watch-notes"><title>Notes</title>
+<para>
+  Although some care has been taken to minimize potential problems
+  arising from watching and unwatching objects from multiple
+  threads, there may well be subtle race conditions present that
+  could cause bad behavior.
+</para>
+<para>
+  For example, suppose that a thread attempts to write to a watched
+  object. This causes the operating system to generate an
+  exception. The lisp kernel figures out what the exception is, and
+  calls back into lisp to signal the write-to-watched-object
+  condition and perhaps handle the error.
+</para>
+<para>
+  Now, as soon lisp code starts running again (for the callback),
+  it's possible that some other thread could unwatch the very
+  watched object that caused the exception, perhaps before we even
+  have a chance to signal the condition, much less respond to it.
+</para>
+<para>
+  Having the object unwatched out from underneath a handler may at
+  least confuse it, if not cause deeper trouble. Use caution with
+  unwatch.
+</para>
+</sect2>
+<sect2 id="watch-examples"><title>Examples</title>
+<para>
+  Here are a couple more examples in addition to the above examples
+  of watching a string and a standard-instance.
+</para>
+<sect3><title>Fancy arrays</title>
+<programlisting>
+?  (defvar *f* (make-array '(2 3) :element-type 'double-float))
+*F*
+? (watch *f*)
+#(0.0D0 0.0D0 0.0D0 0.0D0 0.0D0 0.0D0)
+;;; Note that the above vector is the underlying data-vector for the array
+? (setf (aref *f* 1 2) pi)
+> Error: Write to watched uvector #&lt;VECTOR 6 type DOUBLE-FLOAT, simple> at index 5
+>        Faulting instruction: (movq (% rax) (@ -5 (% r8) (% rdi)))
+> While executing: ASET, in process listener(1).
+> Type :POP to abort, :R for a list of available restarts.
+> Type :? for other options.
+1 > 
+  </programlisting>
+  <para>
+    In this case, uvector index in the report is the row-major index
+    of the element that was written to.
+  </para>
+  </sect3>
+  <sect3><title>Hash tables</title>
+  <para>
+    Hash tables are surprisingly complicated. The representation of a
+    hash table includes an element called a hash-table-vector. The
+    keys and values of the elements are stored pairwise in this
+    vector.
+  </para>
+  <para>
+    One problem with trying to monitor hash tables for writes is that
+    the underlying hash-table-vector is replaced with an entirely new
+    one when the hash table is rehashed. A previously-watched
+    hash-table-vector will not be the used by the hash table after
+    rehashing, and writes to the new vector will not be caught.
+  </para>
+  <programlisting>
+? (defvar *h* (make-hash-table))
+*H*
+? (setf (gethash 'noise *h*) 'feep)
+FEEP
+? (watch *h*)
+#&lt;HASH-TABLE-VECTOR #xDD00D>
+;;; underlying hash-table-vector
+? (setf (gethash 'noise *h*) 'ding)
+> Error: Write to watched uvector #&lt;HASH-TABLE-VECTOR #xDD00D> at index 35
+>        Faulting instruction: (lock)
+>          (cmpxchgq (% rsi) (@ (% r8) (% rdx)))
+> While executing: %STORE-NODE-CONDITIONAL, in process listener(1).
+> Type :POP to abort, :R for a list of available restarts.
+> Type :? for other options.
+;;; see what value is being replaced...
+1 > (uvref (write-to-watched-object-object *break-condition*) 35)
+FEEP
+;;; backtrace shows useful context
+1 > :b
+*(1A109F8) : 0 (%STORE-NODE-CONDITIONAL ???) NIL
+ (1A10A50) : 1 (LOCK-FREE-PUTHASH NOISE #&lt;HASH-TABLE :TEST EQL size 1/60 #x30004117D47D> DING) 653
+ (1A10AC8) : 2 (CALL-CHECK-REGS PUTHASH NOISE #&lt;HASH-TABLE :TEST EQL size 1/60 #x30004117D47D> DING) 229
+ (1A10B00) : 3 (TOPLEVEL-EVAL (SETF (GETHASH # *H*) 'DING) NIL) 709
+ ...
+  </programlisting>
+  </sect3>
+  <sect3><title>Lists</title>
+  <para>
+    As previously mentioned, WATCH only watches individual cons cells.
+  </para>
+  <programlisting>
+? (defun watch-list (list)
+    (maplist #'watch list))
+WATCH-LIST
+? (defvar *l* (list 1 2 3))
+*L*
+? (watch-list *l*)
+((1 2 3) (2 3) (3))
+? (setf (nth 2 *l*) 'foo)
+> Error: Write to the CAR of watched cons cell (3)
+>        Faulting instruction: (movq (% rsi) (@ 5 (% rdi)))
+> While executing: %SETNTH, in process listener(1).
+> Type :POP to abort, :R for a list of available restarts.
+> Type :? for other options.
+  </programlisting>
+  </sect3>
+  </sect2>
+</sect1>
+
+<sect1 id="code-coverage"><title>Code Coverage</title>
+<sect2 id="code-coverage-overview"><title>Overview</title>
+<para>
+  In Clozure CL 1.4 and later, code coverage provides information
+  about which paths through generated code have been executed and
+  which haven't. For each source form, it can report one of three
+  possible outcomes:
+</para>
+<itemizedlist>
+  <listitem>
+    <para>
+      Not covered: this form was never entered.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Partly covered: This form was entered, and some parts were
+      executed and some weren't.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      Fully covered: Every bit of code generated from this form was
+      executed.
+    </para>
+  </listitem>
+</itemizedlist>
+</sect2>
+
+<sect2 id="code-coverage-limitations"><title>Limitations</title>
+<para>
+  While the information gathered for coverage of generated code is
+  complete and precise, the mapping back to source forms is of
+  necessity heuristic, and depends a great deal on the behavior of
+  macros and the path of the source forms through compiler
+  transforms. Source information is not recorded for variables, which
+  further limits the source mapping. In practice, there is often
+  enough information scattered about a partially covered function to
+  figure out which logical path through the code was taken and which
+  wasn't. If that doesn't work, you can try disassembling to see which
+  parts of the compiled code were not executed: in the disassembled
+  code there will be references to #&lt;CODE-NOTE [xxx] ...> where xxx
+  is NIL if the code that follows was never executed and non-NIL if it
+  was.
+</para>
+<para>
+  Sometimes the situation can be improved by modifying macros to try
+  to preserve more of the input forms, rather than destructuring and
+  rebuilding them.
+</para>
+<para>
+  Because the code coverage information is associated with compiled
+  functions, load-time toplevel expressions do not get reported
+  on. You can work around this by creating a function and calling
+  it. I.e. instead of
+  <programlisting>
+(progn
+  (do-this)
+  (setq that ...) ...))
+  </programlisting>
+  do:
+  <programlisting>
+(defun init-this-and-that ()
+  (do-this)
+  (setq that ...)  ...)
+(init-this-and-that)
+  </programlisting>
+Then you can see the coverage information in the definition of
+init-this-and-that.
+</para>
+</sect2>
+
+<sect2 id="code-coverage-usage"><title>Usage</title>
+<para>
+  In order to gather code coverage information, you first have to
+  recompile all your code to include code coverage
+  instrumentation. Compiling files will generate code coverage
+  instrumentation if <literal>CCL:*COMPILE-CODE-COVERAGE*</literal>
+  is true:
+  <programlisting>
+(setq ccl:*compile-code-coverage* t) 
+(recompile-all-your-files) 
+  </programlisting>
+</para>
+<para>
+  The compilation process will be many times slower than normal, and
+  the fasl files will be many times bigger.
+</para>
+<para>
+  When you execute function loaded from instrumented fasl files, they
+  will record coverage information every time they are executed. The
+  system keeps track of which instrumented files have been loaded.
+</para>
+<para>
+  The following functions can be used to manage the coverage data:
+</para>
+
+<refentry id="f_report-coverage">
+  <indexterm zone="f_report-coverage">
+    <primary>report-coverage</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>REPORT-COVERAGE</refname>
+    <refpurpose>Generate code coverage report</refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>report-coverage</function> &key;
+    (external-format :default) (statistics t) (html t)
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Arguments and Values</title>
+  <variablelist>
+    <varlistentry>
+      <term>html</term>
+      <listitem>
+	<para>
+	  If non-nil, this will generate an HTML report, consisting of
+	  an index file and one html file for each instrumented source
+	  file that has been loaded in the current session. The
+	  individual source file reports are stored in the same
+	  directory as the index file.
+	</para>
+      </listitem>
+    </varlistentry>
+    <varlistentry>
+      <term>external-format</term>
+      <listitem>
+	<para>
+	  Controls the external format of the html files.
+	</para>
+      </listitem>
+    </varlistentry>
+    <varlistentry>
+      <term>statistics</term>
+      <listitem>
+	<para>
+	  If :statistics is non-nil, a comma-separated file is also
+	  generated with the summary of statistics. You can specify a
+	  filename for the statistics argument, otherwise
+	  "statistics.csv" is created in the output directory. See
+	  documentation of ccl:coverage-statistics below for a
+	  description of the values in the statistics file.
+	</para>
+      </listitem>
+    </varlistentry>
+  </variablelist>
+  </refsect1>
+  <refsect1><title>Example</title>
+    <para>
+      If you've loaded <filename>foo.lx64fsl</filename> and
+      <filename>bar.lx64fsl</filename>, and have run some tests, you could
+      do
+    <programlisting>
+(CCL:REPORT-COVERAGE "/my/dir/coverage/report.html")
+    </programlisting>
+    and this would generate <filename>report.html</filename>,
+    <filename>foo_lisp.html</filename> and
+    <filename>bar_lisp.html</filename>, and
+    <filename>statistics.csv</filename> all in
+    <filename>/my/dir/coverage/</filename>.
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_reset-coverage">
+  <indexterm zone="f_reset-coverage">
+    <primary>reset-coverage</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>reset-coverage</refname>
+    <refpurpose>
+      Resets all coverage data back to the "Not Executed" state
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Resets all coverage data back to the "Not Executed" state
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_clear-coverage">
+  <indexterm zone="f_clear-coverage">
+    <primary>clear-coverage</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>clear-coverage</refname>
+    <refpurpose>
+      Forget about all instrumented files that have been loaded.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Gets rid of the information about which instrumented files have
+      been loaded, so ccl:report-coverage will not report any files,
+      and ccl:save-coverage-in-file will not save any info, until more
+      instrumented files are loaded.
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_save-coverage-in-file">
+  <indexterm zone="f_save-coverage-in-file">
+    <primary>save-coverage-in-file</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>save-coverage-in-file</refname>
+    <refpurpose>
+      Save all coverage into to a file so you can restore it later.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>save-coverage-in-file</function> pathname
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Saves all coverage info in a file, so you can restore the
+      coverage state later. This allows you to combine multiple runs
+      or continue in a later session. Equivalent to
+      (ccl:write-coverage-to-file (ccl:save-coverage) pathname).
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_restore-coverage-from-file">
+  <indexterm zone="f_restore-coverage-from-file">
+    <primary>restore-coverage-from-file</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>restore-coverage-from-file</refname>
+    <refpurpose>
+      Load coverage state from a file.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>restore-coverage-from-file</function> pathname
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Restores the coverage data previously saved with
+      CCL:SAVE-COVERAGE-IN-FILE, for the set of instrumented fasls
+      that were loaded both at save and restore time. I.e. coverage
+      info is only restored for files that have been loaded in this
+      session. For example if in a previous session you had loaded
+      "foo.lx86fsl" and then saved the coverage info, in this session
+      you must load the same "foo.lx86fsl" before calling
+      ccl:restore-coverage-from-file in order to retrieve the stored
+      coverage info for "foo".  Equivalent to (ccl:restore-coverage
+      (ccl:read-coverage-from-file pathname)).
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_save-coverage">
+  <indexterm zone="f_save-coverage">
+    <primary>save-coverage</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>save-coverage</refname>
+    <refpurpose>
+      Returns a snapshot of the current coverage data.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Returns a snapshot of the current coverage data. A snapshot is a
+      copy of the current coverage state. It can be saved in a file
+      with ccl:write-coverage-to-file, reinstated back as the current
+      state with ccl:restore-coverage, or combined with other
+      snapshots with ccl:combine-coverage.
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_restore-coverage">
+  <indexterm zone="f_restore-coverage">
+    <primary>restore-coverage</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>RESTORE-COVERAGE</refname>
+    <refpurpose>
+      Reinstalls a coverage snapshot as the current coverage state.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>restore-coverage</function> snapshot
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Reinstalls a coverage snapshot as the current coverage state.
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_write-coverage-to-file">
+  <indexterm zone="f_write-coverage-to-file">
+    <primary>write-coverage-to-file</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>WRITE-COVERAGE-TO-FILE</refname>
+    <refpurpose>
+      Save a coverage snapshot in a file.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>write-coverage-to-file</function> snapshot pathname
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Saves the coverage snapshot in a file. The snapshot can be
+      loaded back with ccl:read-coverage-from-file or loaded and
+      restored with ccl:restore-coverage-from-file. Note that the file
+      created is actually a lisp source file and can be compiled for
+      faster loading.
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_read-coverage-from-file">
+  <indexterm zone="f_read-coverage-from-file">
+    <primary>read-coverage-from-file</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>READ-COVERAGE-FROM-FILE</refname>
+    <refpurpose>
+      Return the coverage snapshot saved in a file.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>read-coverage-from-file</function> pathname
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Returns the snapshot saved in pathname. Doesn't affect the
+      current coverage state. pathname can be the file previously
+      created with ccl:write-coverage-to-file or
+      ccl:save-coverage-in-file, or it can be the name of the fasl
+      created from compiling such a file.
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="f_coverage-statistics">
+  <indexterm zone="f_coverage-statistics">
+    <primary>coverage-statistics</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>COVERAGE-STATISTICS</refname>
+    <refpurpose>
+      Returns a sequence of coverage-statistics objects, one per source file.
+    </refpurpose>
+    <refclass>Function</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>coverage-statistics</function>
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      Returns a sequence ccl:coverage-statistics objects, one for each
+      source file, containing the same information as that written to
+      the statistics file by ccl:report-coverage. The following
+      accessors are defined for ccl:coverage-statistics objects:
+      <variablelist>
+      <varlistentry>
+	<term><function>ccl:coverage-source-file</function></term>
+	<listitem>
+	  <para>
+	    the name of the source file corresponding to this information
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-expressions-total</function></term>
+	<listitem>
+	  <para>
+	    the total number of expressions
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-expressions-entered</function></term>
+	<listitem>
+	  <para>
+	    the number of source expressions that have been entered
+	    (i.e. at least partially covered)
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-expressions-covered</function></term>
+	<listitem>
+	  <para>
+	    the number of source expressions that were fully covered
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-unreached-branches</function></term>
+	<listitem>
+	  <para>
+	    the number of conditionals with one branch taken and one not taken
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-code-forms-total</function></term>
+	<listitem>
+	  <para>
+	    the total number of code forms. A code form is an
+	    expression in the final stage of compilation, after all
+	    macroexpansion and compiler transforms and simplification
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-code-forms-covered</function></term>
+	<listitem>
+	  <para>
+	    the number of code forms that have been entered
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-functions-total</function></term>
+	<listitem>
+	  <para>
+	    the total number of functions
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-functions-fully-covered</function></term>
+	<listitem>
+	  <para>
+	    the number of functions that were fully covered
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-functions-partly-covered</function></term>
+	<listitem>
+	  <para>
+	    the number of functions that were partly covered
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><function>ccl:coverage-functions-not-entered</function></term>
+	<listitem>
+	  <para>
+	    the number of functions never entered
+	  </para>
+	</listitem>
+      </varlistentry>
+      </variablelist>
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="v_compile-code-coverage">
+  <indexterm zone="v_compile-code-coverage">
+    <primary>*COMPILE-CODE-COVERAGE*</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>*COMPILE-CODE-COVERAGE*</refname>
+    <refpurpose>
+      When true, instrument functions for code coverage.
+    </refpurpose>
+    <refclass>Variable</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><varname>*compile-code-coverage*</varname>
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      This variable controls whether functions are instrumented for
+      code coverage. Files compiled while this variable is true will
+      contain code coverage instrumentation.
+    </para>
+  </refsect1>
+</refentry>
+
+<refentry id="v_without-compiling-code-coverage">
+  <indexterm zone="v_without-compiling-code-coverage">
+    <primary>without-compiling-code-coverage</primary>
+  </indexterm>
+  
+  <refnamediv>
+    <refname>WITHOUT-COMPILING-CODE-COVERAGE</refname>
+    <refpurpose>
+      Don't record code coverange for forms within the body.
+    </refpurpose>
+    <refclass>Macro</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <synopsis><function>without-compiling-code-coverage</function>
+    </synopsis>
+  </refsynopsisdiv>
+
+  <refsect1><title>Summary</title>
+    <para>
+      This macro arranges so that body doesn't record internal details
+      of code coverage. It will be considered totally covered if it's
+      entered at all. The Common Lisp macros ASSERT and CHECK-TYPE use
+      this macro.
+    </para>
+  </refsect1>
+</refentry>
+
+</sect2>
+</sect1>
+</chapter>
Index: /branches/new-random/doc/src/xsl/catalog
===================================================================
--- /branches/new-random/doc/src/xsl/catalog	(revision 13309)
+++ /branches/new-random/doc/src/xsl/catalog	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+   PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+   "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+<!-- These are probably wrong.
+  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///usr/local/share/xml/dtd/docbookx/4.2.0"/>
+
+  <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///usr/local/share/xml/dtd/docbookx/4.2.0"/>
+  -->
+
+  <rewriteURI
+       uriStartString="http://docbook.sourceforge.net/release/xsl/1.62.4/"
+       rewritePrefix="file:///usr/local/share/xsl/docbook/" />
+
+  <nextCatalog catalog="/usr/local/share/xml/catalog"/>
+</catalog>
Index: /branches/new-random/doc/src/xsl/catalog-debian
===================================================================
--- /branches/new-random/doc/src/xsl/catalog-debian	(revision 13309)
+++ /branches/new-random/doc/src/xsl/catalog-debian	(revision 13309)
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+   PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+   "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///usr/share/sgml/docbook/dtd/4.2"/>
+
+  <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///usr/share/sgml/docbook/dtd/4.2"/>
+
+  <nextCatalog catalog="/etc/xml/catalog"/>
+</catalog>
+
Index: /branches/new-random/doc/src/xsl/catalog-fedora
===================================================================
--- /branches/new-random/doc/src/xsl/catalog-fedora	(revision 13309)
+++ /branches/new-random/doc/src/xsl/catalog-fedora	(revision 13309)
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+   PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+   "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///usr/share/sgml/docbook/xml-dtd-4.2-1.0-30.1"/>
+
+  <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///usr/share/sgml/docbook/xml-dtd-4.2-1.0-30.1"/>
+
+  <nextCatalog catalog="/etc/xml/catalog"/>
+</catalog>
+
Index: /branches/new-random/doc/src/xsl/catalog-fink
===================================================================
--- /branches/new-random/doc/src/xsl/catalog-fink	(revision 13309)
+++ /branches/new-random/doc/src/xsl/catalog-fink	(revision 13309)
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+   PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+   "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///sw/share/xml/dtd/docbookx/4.2.0"/>
+
+  <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///sw/share/xml/dtd/docbookx/4.2.0"/>
+
+  <nextCatalog catalog="/sw/etc/xml/catalog"/>
+</catalog>
+
Index: /branches/new-random/doc/src/xsl/catalog-macports
===================================================================
--- /branches/new-random/doc/src/xsl/catalog-macports	(revision 13309)
+++ /branches/new-random/doc/src/xsl/catalog-macports	(revision 13309)
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+   PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+   "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+  <rewriteSystem systemIdStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///opt/local/share/xml/docbook/4.2"/>
+
+  <rewriteURI uriStartString="http://www.oasis-open.org/docbook/xml/4.2" rewritePrefix="file:///opt/local/share/xml/docbook/4.2"/>
+
+  <nextCatalog catalog="/opt/local/etc/xml/catalog"/>
+</catalog>
+
Index: /branches/new-random/doc/src/xsl/directory-fixes.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/directory-fixes.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/directory-fixes.xsl	(revision 13309)
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		exclude-result-prefixes="#default">
+
+  <xsl:param name="openmcl.depth">
+    <xsl:choose>
+      <xsl:when test="$openmcl.directory = './'">
+	<xsl:value-of select="0"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:call-template name="count.uri.path.depth">
+	  <xsl:with-param name="filename" select="$openmcl.directory"/>
+	</xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:param>
+
+  <xsl:param name="openmcl.base">
+    <xsl:call-template name="copy-string">
+      <xsl:with-param name="string" select="'../'"/>
+      <xsl:with-param name="count" select="$openmcl.depth"/>
+    </xsl:call-template>
+  </xsl:param>
+
+   <!-- Be aware that href.target.uri cannot be defined in this file,
+       because it would be overridden by the definition in
+       optional-onechunk.xsl. -->
+
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/footer.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/footer.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/footer.xsl	(revision 13309)
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		xmlns:date="http://exslt.org/dates-and-times"
+		exclude-result-prefixes="#default">
+
+  <xsl:template name="user.footer.navigation">
+    <xsl:if test="count(/book/index) > 0">
+      <div align="center">
+	<a>
+	  <xsl:attribute name="href">
+	    <xsl:call-template name="href.target">
+	      <xsl:with-param name="object" select="/book/index"/>
+	    </xsl:call-template>
+	  </xsl:attribute>
+	  <xsl:text>Symbol Index</xsl:text>
+	</a>
+      </div>
+    </xsl:if>
+
+    <p class="footer">
+      <xsl:variable name="now" select="date:date-time()"/>
+      <xsl:text>This document was last modified at </xsl:text>
+      <xsl:value-of select="date:hour-in-day($now)"/>
+      <xsl:text>:</xsl:text>
+      <xsl:value-of select="date:minute-in-hour($now)"/>     
+      <xsl:text> on </xsl:text>
+      <xsl:value-of select="date:month-name($now)"/>
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="date:day-in-month($now)"/>
+      <xsl:text>, </xsl:text>
+      <xsl:value-of select="date:year($now)"/>
+      <xsl:text>, in UTC.</xsl:text>
+      <br/>
+      <xsl:text>It uses version </xsl:text>
+      <xsl:value-of select="$VERSION"/>
+      <xsl:text> of the Norman Walsh Docbook stylesheets.</xsl:text>
+      <br/>
+      <xsl:text>Built from subversion rev </xsl:text>
+      <xsl:value-of select="$svnrev"/>
+      <br/>
+      <xsl:value-of select="$xsltproc.version"/>
+    </p>
+  </xsl:template>
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/minor-customizations.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/minor-customizations.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/minor-customizations.xsl	(revision 13309)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		exclude-result-prefixes="#default">
+  <xsl:param name="local.l10n.xml" select="document('')"/>
+
+  <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
+    <l:l10n language="en">
+      <l:gentext key="nav-home" text="Table of Contents"/>
+    </l:l10n>
+  </l:i18n>
+
+  <xsl:template match="varname">
+    <xsl:call-template name="inline.italicseq"/>
+  </xsl:template>
+
+  <xsl:template match="function">
+    <xsl:call-template name="inline.boldseq"/>
+  </xsl:template>
+
+  <xsl:template match="type">
+    <xsl:call-template name="inline.boldseq"/>
+  </xsl:template>
+ 
+  <xsl:template match="property">
+    <xsl:call-template name="inline.boldseq"/>
+  </xsl:template>
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/openmcl.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/openmcl.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/openmcl.xsl	(revision 13309)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		xmlns:date="http://exslt.org/dates-and-times"
+		exclude-result-prefixes="#default">
+
+  <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"/>
+  <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk-common.xsl"/>
+
+  <xsl:import href="toc-at-end.xsl"/>
+
+  <xsl:include href="http://docbook.sourceforge.net/release/xsl/current/html/manifest.xsl"/>
+
+  <xsl:include href="parameters.xsl"/>
+  <!-- xsl:include href="site-navigator.xsl"/ -->
+  <xsl:include href="footer.xsl"/>
+  <xsl:include href="minor-customizations.xsl"/>
+  <xsl:include href="optional-onechunk.xsl"/>
+
+  <xsl:include href="http://docbook.sourceforge.net/release/xsl/current/html/chunk-code.xsl"/>
+  <xsl:include href="refentry.xsl"/>
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/optional-onechunk.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/optional-onechunk.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/optional-onechunk.xsl	(revision 13309)
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		exclude-result-prefixes="#default">
+  <xsl:param name="local.l10n.xml" select="document('')"/>
+  <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
+    <l:l10n language="en">
+      <l:gentext key="nav-home" text="Table of Contents"/>
+    </l:l10n>
+  </l:i18n>
+
+  <xsl:param name="suppress.navigation">
+    <xsl:choose>
+      <xsl:when test="$onechunk != 0">
+	<xsl:value-of select="1"/>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:value-of select="0"/>
+      </xsl:otherwise>    
+    </xsl:choose>
+  </xsl:param>
+
+  <xsl:template name="href.target.uri">
+    <xsl:param name="object" select="."/>
+    <xsl:choose>
+      <xsl:when test="$onechunk != 0">
+	<!-- The contents of this block are entirely taken from
+	     onechunk.xsl in the Norman Walsh stylesheets, version 1.65.1. -->
+	<xsl:text>#</xsl:text>
+	<xsl:call-template name="object.id">
+	  <xsl:with-param name="object" select="$object"/>
+	</xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>
+	<!-- The contents of this block are entirely taken from
+             chunk-common.xsl in the Norman Walsh stylesheets,
+             version 1.65.1. -->
+	<xsl:variable name="ischunk">
+	  <xsl:call-template name="chunk">
+	    <xsl:with-param name="node" select="$object"/>
+	  </xsl:call-template>
+	</xsl:variable>
+	
+	<xsl:apply-templates mode="chunk-filename" select="$object"/>
+	
+	<xsl:if test="$ischunk='0'">
+	  <xsl:text>#</xsl:text>
+	  <xsl:call-template name="object.id">
+	    <xsl:with-param name="object" select="$object"/>
+	  </xsl:call-template>
+	</xsl:if>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/parameters.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/parameters.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/parameters.xsl	(revision 13309)
@@ -0,0 +1,39 @@
+<?xml version='1.0' encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		exclude-result-prefixes="#default">
+
+  <xsl:param name="section.autolabel" select="1"/>
+  <xsl:param name="section.label.includes.component.label" select="1"/>
+  
+  <xsl:variable name="toc.max.depth">2</xsl:variable>
+  
+  <xsl:param name="html.extra.head.links" select="0"/>
+
+  <xsl:param name="chunk.first.sections" select="1"/>
+  <xsl:param name="chunk.section.depth" select="1"/>
+  
+  <xsl:param name="chunk.fast" select="1"/>
+  <xsl:param name="chunker.output.indent" select="'yes'"/>
+
+  <xsl:param name="generate.toc">
+    appendix  toc
+    article/appendix  nop
+    article   toc
+    book      toc,figure,table,example,equation
+    chapter   toc
+    part      toc
+    preface   toc
+    qandadiv  toc
+    qandaset  toc
+    reference toc
+    sect1     toc
+    sect2     toc
+    sect3     toc
+    sect4     toc
+    sect5     toc
+    section   toc
+    set       toc
+  </xsl:param>
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/refentry.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/refentry.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/refentry.xsl	(revision 13309)
@@ -0,0 +1,159 @@
+<?xml version='1.0' encoding="iso-8859-1"?>
+<!DOCTYPE xsl:stylesheet [
+  <!ENTITY lowercase "'abcdefghijklmnopqrstuvwxyz'">
+  <!ENTITY uppercase "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'">
+]>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		xmlns:ns="http://exslt.org/common"
+		exclude-result-prefixes="#default">
+
+  <!--
+    <xsl:template name="refentry.list">
+    <xsl:for-each select="refentry">
+    <xsl:sort select="refnamediv/refname"/>
+    
+    <xsl:apply-templates select="."/>
+    <xsl:apply-imports/>
+    </xsl:for-each>
+    </xsl:template>-->
+
+  <xsl:template name="refentry.title">
+    <xsl:param name="node" select="."/>
+    
+    <i><xsl:value-of select="$node/refnamediv/refclass"/></i>
+    <xsl:text> </xsl:text>
+    <b><xsl:value-of select="$node/refnamediv/refname"/></b>
+  </xsl:template>
+
+  <xsl:template match="refentry" mode="object.title.markup">
+    <xsl:call-template name="refentry.title"/>
+  </xsl:template>
+
+  <xsl:template match="refentry" mode="title.markup">
+    <xsl:call-template name="refentry.title"/>
+  </xsl:template>
+
+  <xsl:template match="refentry">
+    <p>
+      <div class="refentrytitle">
+	<a>
+	  <xsl:attribute name="id">
+	    <xsl:value-of select="@id"/>
+	  </xsl:attribute>
+	</a>
+	<strong>[<xsl:value-of select="refnamediv/refclass"/>]</strong><br/>
+	<xsl:choose>
+	  <xsl:when test="refsynopsisdiv/synopsis">
+	    <code><xsl:apply-templates select="refsynopsisdiv/synopsis/node()"/></code>
+	  </xsl:when>
+	  <xsl:otherwise>
+	    <code><xsl:value-of select="refnamediv/refname"/></code>
+	  </xsl:otherwise>
+	</xsl:choose>
+      </div>
+      <div class="refentrytitle">
+	<xsl:value-of select="refnamediv/refpurpose"/>
+      </div>
+    </p>
+    <p>
+      <div>
+	<xsl:apply-templates select="refsect1"/>
+      </div>
+    </p>
+  </xsl:template>
+
+
+  <xsl:template match="refentry" mode="xref-to">
+    <b>
+      <xsl:value-of
+	 select="translate(refnamediv/refname[1], &uppercase;, &lowercase;)"/>
+    </b>
+  </xsl:template>
+
+  <xsl:template match="refnamediv">
+    <div class="refheader">
+      <xsl:call-template name="refentry.title">
+	<xsl:with-param name="node" select=".."/>
+      </xsl:call-template>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="refsynopsisdiv">
+    <div class="header">
+      <xsl:text>Syntax:</xsl:text>
+    </div>
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="synopsis">
+    <div class="{name(.)}">
+      <xsl:apply-templates select="function"/>
+      <xsl:text> </xsl:text>
+      <i>
+	<xsl:apply-templates select="text()|*[position()>1]"/>
+      </i>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="refsection|refsect1|refsect2|refsect3">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:call-template name="anchor">
+	<xsl:with-param name="conditional" select="0"/>
+      </xsl:call-template>
+      <div class="header">
+	<xsl:value-of select="title"/>
+	<xsl:text>:</xsl:text>
+      </div>
+      <xsl:apply-templates select="text()|*[name() != 'title']"/>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="refsect1/variablelist">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="refsect1/variablelist/varlistentry">
+    <p>
+      <i>
+	<xsl:apply-templates select="term"/>
+      </i>
+      <xsl:text>---</xsl:text>
+      <xsl:apply-templates select="listitem"/>
+    </p>
+  </xsl:template>
+
+  <xsl:template match="refsect1/variablelist/varlistentry/listitem">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="refsect1/variablelist/varlistentry/listitem/para">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="refsynopsisdiv/variablelist">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="refsynopsisdiv/variablelist/varlistentry">
+    <p>
+      <xsl:apply-templates select="term"/>
+      <xsl:text> :: </xsl:text>
+      <xsl:apply-templates select="listitem"/>
+    </p>
+  </xsl:template>
+
+  <xsl:template match="refsynopsisdiv/variablelist/varlistentry/term">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="refsynopsisdiv/variablelist/varlistentry/listitem">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="refsynopsisdiv/variablelist/varlistentry/listitem/para">
+    <xsl:apply-templates/>
+  </xsl:template>
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/site-navigator.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/site-navigator.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/site-navigator.xsl	(revision 13309)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		exclude-result-prefixes="#default">
+
+  <xsl:template name="user.header.navigation">
+    <xsl:element name="table">
+      <xsl:attribute name="width">100%</xsl:attribute>
+      <xsl:attribute name="border">0</xsl:attribute>
+      <xsl:attribute name="cellspacing">0</xsl:attribute>
+      <xsl:attribute name="cellpadding">0</xsl:attribute>
+      <tr>
+	<td colspan="2" align="center">
+	  <hr/>
+	  <center>
+	    <font face="arial" size="2">
+	      [
+	      <xsl:element name="a">
+		<xsl:attribute name="href"><xsl:value-of select="$openmcl.base"/>index.html</xsl:attribute>
+		Home
+	      </xsl:element>
+	      |
+	      <xsl:element name="a">
+		<xsl:attribute name="href"><xsl:value-of select="$openmcl.base"/>FAQ</xsl:attribute>
+		FAQ
+	      </xsl:element>
+	      |
+	      <xsl:element name="a">
+		<xsl:attribute name="href"><xsl:value-of select="$openmcl.base"/>Doc/index.html</xsl:attribute>
+		Documentation
+	      </xsl:element>
+	      |
+	      <xsl:element name="a">
+		<xsl:attribute name="href"><xsl:value-of select="$openmcl.base"/>Distributions/index.html</xsl:attribute>
+		Distributions
+	      </xsl:element>
+	      |
+	      <xsl:element name="a">
+		<xsl:attribute name="href"><xsl:value-of select="$openmcl.base"/>TmpCVS/index.html</xsl:attribute>
+		CVS Access
+	      </xsl:element>
+	      |
+	      <xsl:element name="a">
+		<xsl:attribute name="href"><xsl:value-of select="$openmcl.base"/>mail/index.html</xsl:attribute>
+		Mailing-Lists
+	      </xsl:element>
+	      |
+	      <xsl:element name="a">
+		<xsl:attribute name="href"><xsl:value-of select="$openmcl.base"/>support.html</xsl:attribute>
+		Support
+	      </xsl:element>
+	      |
+	      <a href="http://openmcl.clozure.com/openmcl-wiki">Wiki</a>
+	      ]
+	    </font>
+	    <hr/>
+	  </center>
+	</td>
+      </tr>
+    </xsl:element>
+  </xsl:template>
+</xsl:stylesheet>
Index: /branches/new-random/doc/src/xsl/toc-at-end.xsl
===================================================================
--- /branches/new-random/doc/src/xsl/toc-at-end.xsl	(revision 13309)
+++ /branches/new-random/doc/src/xsl/toc-at-end.xsl	(revision 13309)
@@ -0,0 +1,309 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		version='1.0'
+		xmlns="http://www.w3.org/TR/xhtml1/transitional"
+		exclude-result-prefixes="#default">
+
+  <!-- Based on Norman Walsh's stylesheets, version 1.62.4.  Last updated
+       in June 2004. -->
+
+  <!-- From component.xsl. -->
+  <xsl:template match="preface">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:if test="$generate.id.attributes != 0">
+	<xsl:attribute name="id">
+	  <xsl:call-template name="object.id"/>
+	</xsl:attribute>
+      </xsl:if>
+
+      <xsl:call-template name="component.separator"/>
+      <xsl:call-template name="preface.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.footnotes"/>
+
+      <xsl:if test="contains($toc.params, 'toc')">
+	<xsl:call-template name="component.toc.separator"/>
+	<xsl:call-template name="component.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+
+  <!-- From component.xsl. -->
+  <xsl:template match="chapter">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:if test="$generate.id.attributes != 0">
+	<xsl:attribute name="id">
+	  <xsl:call-template name="object.id"/>
+	</xsl:attribute>
+      </xsl:if>
+
+      <xsl:call-template name="component.separator"/>
+      <xsl:call-template name="chapter.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:if test="contains($toc.params, 'toc')">
+	<xsl:call-template name="component.toc.separator"/>
+	<xsl:call-template name="component.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.footnotes"/>
+
+    </div>
+  </xsl:template>
+
+  <!-- From component.xsl. -->
+  <xsl:template match="appendix">
+    <xsl:variable name="ischunk">
+      <xsl:call-template name="chunk"/>
+    </xsl:variable>
+
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:if test="$generate.id.attributes != 0">
+	<xsl:attribute name="id">
+	  <xsl:call-template name="object.id"/>
+	</xsl:attribute>
+      </xsl:if>
+
+      <xsl:choose>
+	<xsl:when test="parent::article and $ischunk = 0">
+	  <xsl:call-template name="section.heading">
+	    <xsl:with-param name="level" select="1"/>
+	    <xsl:with-param name="title">
+	      <xsl:apply-templates select="." mode="object.title.markup"/>
+	    </xsl:with-param>
+	  </xsl:call-template>
+	</xsl:when>
+	<xsl:otherwise>
+	  <xsl:call-template name="component.separator"/>
+	  <xsl:call-template name="appendix.titlepage"/>
+	</xsl:otherwise>
+      </xsl:choose>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+
+      <xsl:if test="not(parent::article) or $ischunk != 0">
+	<xsl:call-template name="process.footnotes"/>
+      </xsl:if>
+
+      <xsl:if test="contains($toc.params, 'toc')">
+	<xsl:call-template name="component.toc.separator"/>
+	<xsl:call-template name="component.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+
+  <!-- From component.xsl.  Commented out because I actually prefer to leave
+       the ToC at the beginning for articles. -->
+<!--
+  <xsl:template match="article">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:if test="$generate.id.attributes != 0">
+	<xsl:attribute name="id">
+	  <xsl:call-template name="object.id"/>
+	</xsl:attribute>
+      </xsl:if>
+
+      <xsl:call-template name="article.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.footnotes"/>
+
+      <xsl:call-template name="make.lots">
+	<xsl:with-param name="toc.params" select="$toc.params"/>
+	<xsl:with-param name="toc">
+	  <xsl:call-template name="component.toc">
+	    <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	  </xsl:call-template>
+	</xsl:with-param>
+      </xsl:call-template>
+    </div>
+  </xsl:template>
+-->
+
+  <!-- From section.xsl. -->
+  <xsl:template match="section">
+    <xsl:variable name="depth" select="count(ancestor::section)+1"/>
+
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:call-template name="section.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.chunk.footnotes"/>
+
+      <xsl:if test="contains($toc.params, 'toc')
+	      and $depth &lt;= $generate.section.toc.level">
+	<xsl:call-template name="section.toc.separator"/>
+	<xsl:call-template name="section.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+
+  <!-- From section.xsl. -->
+  <xsl:template match="sect1">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:call-template name="sect1.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.chunk.footnotes"/>
+
+      <xsl:if test="contains($toc.params, 'toc')
+	      and $generate.section.toc.level &gt;= 1">
+	<xsl:call-template name="section.toc.separator"/>
+	<xsl:call-template name="section.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+
+  <!-- From section.xsl. -->
+  <xsl:template match="sect2">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:call-template name="sect2.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.chunk.footnotes"/>
+
+      <xsl:if test="contains($toc.params, 'toc')
+	      and $generate.section.toc.level &gt;= 2">
+	<xsl:call-template name="section.toc.separator"/>
+	<xsl:call-template name="section.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+
+  <!-- From section.xsl. -->
+  <xsl:template match="sect3">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:call-template name="sect3.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.chunk.footnotes"/>
+
+      <xsl:if test="contains($toc.params, 'toc')
+	      and $generate.section.toc.level &gt;= 3">
+	<xsl:call-template name="section.toc.separator"/>
+	<xsl:call-template name="section.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+
+  <!-- From section.xsl. -->
+  <xsl:template match="sect4">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:call-template name="sect4.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.chunk.footnotes"/>
+
+      <xsl:if test="contains($toc.params, 'toc')
+	      and $generate.section.toc.level &gt;= 4">
+	<xsl:call-template name="section.toc.separator"/>
+	<xsl:call-template name="section.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+
+  <!-- From section.xsl. -->
+  <xsl:template match="sect5">
+    <div class="{name(.)}">
+      <xsl:call-template name="language.attribute"/>
+      <xsl:call-template name="sect5.titlepage"/>
+
+      <xsl:variable name="toc.params">
+	<xsl:call-template name="find.path.params">
+	  <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+	</xsl:call-template>
+      </xsl:variable>
+
+      <xsl:apply-templates/>
+      <xsl:call-template name="process.chunk.footnotes"/>
+
+      <xsl:if test="contains($toc.params, 'toc')
+	      and $generate.section.toc.level &gt;= 5">
+	<xsl:call-template name="section.toc.separator"/>
+	<xsl:call-template name="section.toc">
+	  <xsl:with-param name="toc.title.p" select="contains($toc.params, 'title')"/>
+	</xsl:call-template>
+      </xsl:if>
+    </div>
+  </xsl:template>
+</xsl:stylesheet>
Index: /branches/new-random/examples/.cvsignore
===================================================================
--- /branches/new-random/examples/.cvsignore	(revision 13309)
+++ /branches/new-random/examples/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest-compile.sh
===================================================================
--- /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest-compile.sh	(revision 13309)
+++ /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest-compile.sh	(revision 13309)
@@ -0,0 +1,4 @@
+#!/bin/sh
+cd $1
+echo In directory: `pwd`
+gcc -dynamiclib -Wall -o libptrtest.dylib ptrtest.c -install_name ./libptrtest.dylib
Index: /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest.c
===================================================================
--- /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest.c	(revision 13309)
+++ /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest.c	(revision 13309)
@@ -0,0 +1,35 @@
+#include <stdio.h>
+
+void reverse_int_array(int * data, unsigned int dataobjs)
+{
+  int i, t;
+  
+  for(i=0; i<dataobjs/2; i++)
+    {
+      t = *(data+i);
+      *(data+i) = *(data+dataobjs-1-i);
+      *(data+dataobjs-1-i) = t;
+    }
+}
+
+void reverse_int_ptr_array(int **ptrs, unsigned int ptrobjs)
+{
+  int *t;
+  int i;
+  
+  for(i=0; i<ptrobjs/2; i++)
+    {
+      t = *(ptrs+i);
+      *(ptrs+i) = *(ptrs+ptrobjs-1-i);
+      *(ptrs+ptrobjs-1-i) = t;
+    }
+}
+
+void
+reverse_int_ptr_ptrtest(int **ptrs)
+{
+  reverse_int_ptr_array(ptrs, 2);
+  
+  reverse_int_array(*(ptrs+0), 4);
+  reverse_int_array(*(ptrs+1), 4);
+}
Index: /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest.lisp
===================================================================
--- /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest.lisp	(revision 13309)
+++ /branches/new-random/examples/FFI/Allocating-foreign-data-on-the-lisp-heap/ptrtest.lisp	(revision 13309)
@@ -0,0 +1,104 @@
+(defun message (string)
+  (format t "~a~%~%" string)
+  (force-output))
+
+;; Setup
+(message "*** Building the shared library")
+(run-program (namestring
+	      (translate-logical-pathname #P"ccl:examples;FFI;Allocating-foreign-data-on-the-lisp-heap;ptrtest-compile.sh"))
+	     (list
+	      (namestring
+	       (translate-logical-pathname #P"ccl:examples;FFI;Allocating-foreign-data-on-the-lisp-heap")))
+	     :output t)
+
+;; make-heap-ivector courtesy of Gary Byers
+; This is now predefined by OpenMCL
+#|(defun make-heap-ivector (element-count element-type)
+  (let* ((subtag (ccl::element-type-subtype element-type)))
+    (unless (= (logand subtag target::fulltagmask)
+	       target::fulltag-immheader)
+      (error "~s is not an ivector subtype." element-type))
+    (let* ((size-in-bytes (ccl::subtag-bytes subtag element-count)))
+      (ccl::%make-heap-ivector subtag size-in-bytes element-count))))|#
+
+;; dispose-heap-ivector created for symmetry
+; This is now predefined by OpenMCL but the example uses a different definition so we'll change the name
+(defmacro my-dispose-heap-ivector (a mp)
+  `(progn
+     (ccl::%dispose-heap-ivector ,a)
+     ;; Demolish the arguments for safety
+     (setf ,a nil)
+     (setf ,mp nil)))
+
+;; Create an array of 3 4-byte-long integers
+(multiple-value-bind (la lap)
+    (make-heap-ivector 3 '(unsigned-byte 32))
+  (setq a la)
+  (setq ap lap))
+
+(message (format nil "a: ~a~%" a))
+(message (format nil "ap: ~a~%" ap))
+(message (format nil "(aref a 2): ~a~%" (aref a 2)))
+(message "Setting values of a to #(3 4 5)")
+(setf (aref a 0) 3)
+(setf (aref a 1) 4)
+(setf (aref a 2) 5)
+(message (format nil "a: ~a~%" a))
+
+(setq *byte-length-of-long* 4)
+(message (format nil
+		 "(%get-signed-long ap (* 2 *byte-length-of-long*)): ~a~%"
+		 (%get-signed-long ap (* 2 *byte-length-of-long*))))
+(message (format nil
+		 "(%get-signed-long ap (* 0 *byte-length-of-long*)): ~a~%"
+		 (%get-signed-long ap (* 0 *byte-length-of-long*))))
+(message "Setting values of ap to (setf (%get-signed-long ap (* 0 *byte-length-of-long*)) 6) and (setf (%get-signed-long ap (* 2 *byte-length-of-long*)) 7)~%")
+(setf (%get-signed-long ap (* 0 *byte-length-of-long*)) 6)
+(setf (%get-signed-long ap (* 2 *byte-length-of-long*)) 7)
+;; Show that a actually got changed through ap
+(message (format nil "a: ~a~%" a))
+
+;; Insert the full path to your copy of libptrtest.dylib
+(message "*** Loading the shared library")
+(open-shared-library (namestring
+		      (translate-logical-pathname #P"ccl:examples;FFI;Allocating-foreign-data-on-the-lisp-heap;libptrtest.dylib")))
+
+(message (format nil "a: ~a~%" a))
+(message (format nil "ap: ~a~%" ap))
+
+(message "Calling: (external-call \"_reverse_int_array\" :address ap :unsigned-int (length a) :address)")
+(external-call "_reverse_int_array" :address ap :unsigned-int (length a) :address)
+
+(message (format nil "a: ~a~%" a))
+(message (format nil "ap: ~a~%" ap))
+
+(message "Calling: (my-dispose-heap-ivector a ap)")
+(my-dispose-heap-ivector a ap)
+
+(message (format nil "a: ~a~%" a))
+(message (format nil "ap: ~a~%" ap))
+
+#|
+(defclass wrapper (whatever)
+  ((element-type :initarg :element-type)
+   (element-count :initarg :element-count)
+   (ivector)
+   (macptr)))
+
+(defmethod initialize-instance ((wrapper wrapper) &rest initargs)
+  (declare (ignore initargs))
+  (call-next-method)
+  (ccl:terminate-when-unreachable wrapper)
+  (with-slots (ivector macptr element-type element-count) wrapper
+    (multiple-value-bind (new-ivector new-macptr)
+	(make-heap-ivector element-count element-type)
+      (setq ivector new-ivector
+	    macptr new-macptr))))
+
+(defmethod ccl:terminate ((wrapper wrapper))
+  (with-slots (ivector macptr) wrapper
+    (when ivector
+      (dispose-heap-ivector ivector macptr)
+      (setq ivector nil
+	    macptr nil))))
+|#
Index: /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest-compile.sh
===================================================================
--- /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest-compile.sh	(revision 13309)
+++ /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest-compile.sh	(revision 13309)
@@ -0,0 +1,4 @@
+#!/bin/sh
+cd $1
+echo In directory: `pwd`
+gcc -dynamiclib -Wall -o libtypetest.dylib typetest.c -install_name ./libtypetest.dylib
Index: /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest.c
===================================================================
--- /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest.c	(revision 13309)
+++ /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest.c	(revision 13309)
@@ -0,0 +1,75 @@
+#include <stdio.h>
+
+// First set of tuturial functions
+
+void
+void_void_test(void)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Exited  %s:\n", __FUNCTION__);
+}
+
+signed char
+sc_sc_test(signed char data)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Data In: %d\n", (signed int)data);
+  printf("Exited  %s:\n", __FUNCTION__);
+  return data;
+}
+
+unsigned char
+uc_uc_test(unsigned char data)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Data In: %d\n", (signed int)data);
+  printf("Exited  %s:\n", __FUNCTION__);
+  return data;
+}
+
+// Second set of tutorial functions
+
+int
+si_si_test(int data)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Data In: %d\n", data);
+  printf("Exited  %s:\n", __FUNCTION__);
+  return data;
+}
+     
+long
+sl_sl_test(long data)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Data In: %ld\n", data);
+  printf("Exited  %s:\n", __FUNCTION__);
+  return data;
+}
+     
+long long
+sll_sll_test(long long data)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Data In: %lld\n", data);
+  printf("Exited  %s:\n", __FUNCTION__);
+  return data;
+}
+     
+float
+f_f_test(float data)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Data In: %e\n", data);
+  printf("Exited  %s:\n", __FUNCTION__);
+  return data;
+}
+     
+double
+d_d_test(double data)
+{
+  printf("Entered %s:\n", __FUNCTION__);
+  printf("Data In: %e\n", data);
+  printf("Exited  %s:\n", __FUNCTION__);
+  return data;
+}
Index: /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest.lisp
===================================================================
--- /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest.lisp	(revision 13309)
+++ /branches/new-random/examples/FFI/Using-basic-calls-and-types/typetest.lisp	(revision 13309)
@@ -0,0 +1,118 @@
+(defun message (string)
+  (format t "~a~%~%" string)
+  (force-output))
+
+;; Setup
+(message "*** Building the shared library")
+(run-program (namestring
+	      (translate-logical-pathname #P"ccl:examples;FFI;Using-basic-calls-and-types;typetest-compile.sh"))
+	     (list
+	      (namestring
+	       (translate-logical-pathname #P"ccl:examples;FFI;Using-basic-calls-and-types")))
+	     :output t)
+(message (format nil "*** Shared libraries (before load): ~a~%~%*** Loading the shared library"ccl::*shared-libraries*))
+(open-shared-library (namestring
+		      (translate-logical-pathname #P"ccl:examples;FFI;Using-basic-calls-and-types;libtypetest.dylib")))
+(message (format nil "*** Shared libraries (after load): ~a"ccl::*shared-libraries*))
+
+;; First set of tutorial function calls
+(message "*** Calling first group of test functions")
+; test the basics
+(message
+ (format nil
+	 "_void_void_test: ~a"
+	 (external "_void_void_test")))
+(message
+ (format nil
+	 "_sc_sc_test: ~a"
+	 (external "_sc_sc_test")))
+(message
+ (format nil
+	 "_uc_uc_test: ~a"
+	 (external "_uc_uc_test")))
+(message
+ (format nil
+	 "functiondoesnotexist: ~a"
+(external "functiondoesnotexist")))
+(message
+ (format nil
+	 "_void_void_test returned: ~a"
+	 (external-call "_void_void_test"
+			:void)))
+(message
+ (format nil
+	 "_sc_sc_test returned: ~a"
+	 (external-call "_sc_sc_test"
+			:signed-byte -128
+			:signed-byte)))
+; value exceeding limit and clips
+(message "* The following calls will exceed limits and clip results:")
+(message
+ (format nil
+	 "_sc_sc_test returned: ~a"
+	 (external-call "_sc_sc_test"
+			:signed-byte -567
+			:signed-byte)))
+(message
+ (format nil
+	 "_uc_uc_test returned: ~a"
+	 (external-call "_uc_uc_test"
+			:unsigned-byte 255
+			:unsigned-byte)))
+(message
+ (format nil
+	 "_uc_uc_test returned: ~a"
+	 (external-call "_uc_uc_test"
+			:unsigned-byte 567
+			:unsigned-byte)))
+(message
+ (format nil
+	 "_uc_uc_test returned: ~a"
+	 (external-call "_uc_uc_test"
+			:unsigned-byte -567
+			:unsigned-byte)))
+
+;; Second set of tutorial function calls
+(message "*** Calling second group of test functions")
+(message
+ (format nil
+	 "_si_si_test returned: ~a"
+	 (external-call "_si_si_test"
+			:signed-fullword -178965
+			:signed-fullword)))
+(message "* Longs are the same size as ints")
+(message
+ (format nil
+	 "_sl_sl_test returned: ~a"
+	 (external-call "_sl_sl_test"
+			:signed-fullword -178965
+			:signed-fullword)))
+(message
+ (format nil
+	 "_sll_sll_test returned: ~a"
+	 (external-call "_sll_sll_test"
+			:signed-doubleword -973891578912
+			:signed-doubleword)))
+(message "* Mistakenly calling sl_sl_test() for sll_sll_test(), thinking that a long is actually a doubleword:")
+(message
+ (format nil
+	 "_sl_sl_test returned: ~a"
+	 (external-call "_sl_sl_test"
+			:signed-doubleword -973891578912
+			:signed-doubleword)))
+
+;; Third set of tutuorial function calls
+(message "*** Calling the third group of test functions")
+
+(message
+ (format nil
+	 "_f_f_test returned: ~a"
+	 (external-call "_f_f_test"
+			:single-float -1.256791e+11
+			:single-float)))
+(message
+ (format nil
+	 "_d_d_test returned: ~a"
+	 (external-call "_d_d_test"
+			:double-float -1.256791d+290
+			:double-float)))
Index: /branches/new-random/examples/README-OPENMCL-EXAMPLES
===================================================================
--- /branches/new-random/examples/README-OPENMCL-EXAMPLES	(revision 13309)
+++ /branches/new-random/examples/README-OPENMCL-EXAMPLES	(revision 13309)
@@ -0,0 +1,184 @@
+
+LinuxPPC-specific examples:
+
+Prerequisites.
+  All of these example programs require OpenMCL 0.9 or later.
+  Most additionally require that X11 runtime libraries are installed,
+   and that OpenMCL is running under an X server.
+  Additional libraries may also be required.  One way to check for
+   the presence of a shared library named "LIBNAME.so" is to do:
+
+% /sbin/ldconfig -p | fgrep LIBNAME.so
+
+   If that returns a line of the form:
+
+     LIBNAME.so (<other info>) => /path/to/some/lib/on/your/system
+
+   you're in luck; if it doesn't, you may have to hunt around to
+   find a package (.deb, .rpm, ...) which contains the library in
+   a form that's appropriate for your Linux distribution.  Different
+   distributions package things differently, and packages often
+   depend on other packages; it's hard to be specific about what a
+   given distribution needs, but I'll try to provide some hints.
+
+ Beginning with release 0.9, OpenMCL uses "interface directories",
+  to try to modularize its interface database somewhat.  If any of
+  these examples need interface directories that aren't distributed
+  with OpenMCL, the example's description will note that.  ("interface
+  directories" are subdirectories of "ccl:headers;" that contain -
+  among other things - a set of files whose extension is "db".)
+
+----------------------------------------------------------------------
+file: "opengl-ffi.lisp"
+description: 2d Gasket example  taken from
+  "Interactive Computer Graphics:
+   A Top-Down Approach with OpenGL" by Ed Angel
+contributor: Hamilton Link
+interface-dir: gl	; distributed with OpenMCL
+libraries:  libGL.so	; may be part of a "mesa" or "opengl" package
+            libGLU.so	; may be part of a "mesa" or "opengl" package
+            libglut.so	; may be part of a "glutg3" or "glutg3-dev" package
+invocation:
+? (require "opengl-ffi")
+? (2dgasket::main)
+notes:
+OpenGL doesn't seem to provide a way to do event handling incrementally
+or concurrently with OpenMCL; when its event handling function finishes
+(when the OpenGL window closes), the OpenMCL process will exit and when
+the OpenGL event-loop is active, OpenMCL isn't responsive.)
+It's possible that the "gtkglarea" package would provide a way of doing
+OpenGL graphics in a way that's a little less intrusive.
+----------------------------------------------------------------------
+file: "gtk-clock.lisp"
+description: A double-buffered analog clock, derived from the
+  double-buffered clock example in "Developing Linux Applications
+  with GDK and GTK+", Eric Harlow, (c) 1999 New Riders Publishing.
+contributor: Clozure
+interface-dir: gtk	; distributed with OpenMCL
+libraries:  libgtk.so	; may be part of a "libgtk-1.2" package
+invocation:
+? (require "gtk-clock")
+? (ccl::gtk-clock)
+notes:
+The clock is reentrant: it should be possible to call (ccl::gtk-clock)
+multiple times, and clutter your desktop with way too many 
+clocks.
+----------------------------------------------------------------------
+file: "gtk-minesweepr.lisp"
+description: An implementation of the Minesweeper game, derived from the
+  Minesweeper example in "Developing Linux Applications
+  with GDK and GTK+", Eric Harlow, (c) 1999 New Riders Publishing.
+contributor: Clozure
+interface-dir: gtk	; distributed with OpenMCL
+libraries:  libgtk.so	; may be part of a "libgtk-1.2" package
+invocation:
+? (require "gtk-minesweeper")
+? (minesweeper:minesweeper)
+notes:
+Minesweeper -isn't- reentrant (too much state is kept in global variables);
+if you try to invoke (minesweeper:minesweeper) while a minesweeper window
+is already active, it'll let you close the old window or abort the attempt
+to open a new one.
+
+I found that there were display issues with the way that GtkToggleButtons
+were used in the original program and made a subclass - GtkQuietToggelButton -
+that handles "enter" and "leave" events differently.  The quiet buttons are
+probably better (you can do
+
+? (setq  MINESWEEPER::*MINESWEEPER-USE-QUIET-TOGGLE-BUTTONS* nil)
+
+to use the original implementation), but some display artifacts remain.
+There may be a better approach to the problem than the one I took, and
+I'd have to assume that GTK is flexible enough to offer a solution.
+
+Maybe not the world's best Minesweeper game, but the only one I know of
+that allows you to develop CL programs while you're playing ...
+
+----------------------------------------------------------------------
+file: "gtk-step.lisp"
+description: An alternate user interface to OpenMCL's STEP command.
+contributor: Clozure
+interface-dir: gtk	; distributed with OpenMCL
+libraries:  libgtk.so	; may be part of a "libgtk-1.2" package
+invocation:
+? (require "gtk-step")
+? (step <some form>)
+Notes:
+Since OpenMCL is essentially a "compile-only" implementation, one has
+to take special ... steps to ensure that STEP will step through evaluated
+code.  (This is true regardless of what user interface STEP uses.)
+
+Most of the STEP output is displayed in a GtkText widget; it often feels
+like it's dragging a reluctant vertical scrollbar with it, fighting tooth
+and nail to convince that scrollbar to scroll to where the most recent
+output is.  I sincerely hope that I'm doing something wrong here ...
+
+-------------
+MacOSX-specific examples:
+(These currently depend on the Cocoa application framework, which is part
+of MacOSX.  In the future, they may also work under Linux and/or Darwin
+with the GNUstep application framework (an opensource implementation of
+the OpenSTEP framework on which Cocoa is based.)
+
+----------------------------------------------------------------------
+file: "cocoa.lisp"
+description: A preliminary Cocoa-based lisp development system
+contributor: Clozure
+interface-dir: cocoa	; distributed with OpenMCL
+libraries:  /System/Library/Frameworks/Cocoa.framework/Cocoa
+invocation:
+? (require "COCOA")
+After a few seconds, an "OpenMCL" dock entry should appear, identifying
+a new window layer in which a Cocoa-based listener and OpenMCL menubar
+should be present.  There's a text editor that supports basic Emacs-style
+key bindings for cursor movement, etc.; it isn't (yet) very lisp-aware.
+
+----------------------------------------------------------------------
+file: "cocoa-inspector.lisp"
+description: A browser-style inspector for the preliminary Cocoa IDE.
+contributor: Clozure
+interface-dir: cocoa	; distributed with OpenMCL
+libraries:  /System/Library/Frameworks/Cocoa.framework/Cocoa
+invocation:
+? (require "COCOA-INSPECTOR")
+This loads the Cocoa IDE and adds support for graphically inspecting
+Lisp objects:
+? (ccl::cinspect <form>)
+
+Hopefully, we'll be able to tie this in (to the Cocoa editor/listener,
+to the menubar, to the CL:INSPECT function ...) in the near future.
+
+----------------------------------------------------------------------
+file: "cocoa-application.lisp"
+description: Save the "preliminary Cocoa IDE" as a double-clickable
+             MacOSX application bundle
+contributor: Clozure
+interface-dir: cocoa	; distributed with OpenMCL
+libraries:  /System/Library/Frameworks/Cocoa.framework/Cocoa
+invocation:
+? (require "COCOA-APPLICATION") ; after first carefully reading the
+                                ; comments in that file.
+
+It may be a little premature to worry about this (since the Cocoa IDE
+is still pretty feature-starved.)  It -does- demonstrate that it's
+possible to make .nib-based, double-clickable applications in OpenMCL,
+and I think that it's reasonable to assume that the process will get
+smoother in the future.
+
+Platform-neutral examples:
+
+
+file: "finger.lisp"
+description: An RFC 1288 "finger" protocol client and server
+contributor: Barry Perryman
+interface-dir: libc	; distributed with OpenMCL
+libraries:  
+invocation: (require "FINGER")
+
+This is a clear, self-contained example of TCP programming in OpenMCL.
+Note that it may not be possible to run a FINGER server on the standard
+port (79), since doing so may require root privileges (and since there
+may already be a finger service running on that port, via inetd/xinetd.)
+
+I suppose that I should also say that one should always exercise caution 
+when running any type of server on a machine connected to the Internet.
Index: /branches/new-random/examples/cocoa-inspector.lisp
===================================================================
--- /branches/new-random/examples/cocoa-inspector.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa-inspector.lisp	(revision 13309)
@@ -0,0 +1,469 @@
+;;;-*-Mode: LISP; Package: GUI -*-
+
+(in-package "GUI")
+
+#|
+(cinspect <thing>)
+
+A cocoa-based lisp inspector, LGPL'ed by Hamilton Link
+
+This code is freely distributable, etc. but I would appreciate people
+submitting changes back to me and making suggestions about how it
+could be altered or improved to me rather than starting a totally
+separate inspector.
+
+Major plans:
+ Shift all the browser columns over to allow the first column to just have the object
+ Make double-clicking an object bring any existing inspector for that object to the front unless shift key is held
+
+Minor tweaks:
+  test on all sorts of things for sanity of leaf-ness of nodes and fields
+  test on all sorts of things for santity in what's safely editable in table view
+  fix the leaf-ness fields with a macptr value
+  change the font to something smaller (or even better, be settable)
+  clean up this file, maybe make a dedicated cinspector package for such things
+  document lessons learned about NSBrowser and NSTableView for next time
+
+Bugs:
+  - when selecting a non-item in a lower column that was just being
+  displayed (in the NSBrowser), the tableview isn't cleared and it
+  probably should be.
+
+  Possibly a reasonable next thing after that would be to make control-
+or alt-double-clicking open new windows with other browsing metaphors
+appropriate to the object (like a class heirarchy browser, maybe a
+table view for matrices, etc.), we'll see.
+  Eventually I'd like to expand the whole inspector functionality to
+deal with ObjC things (methods and objects) and C foreign data in
+general, but that's further off unless someone wants to take a crack
+at it. Once we know we've got a macptr into ObjC we can deal, but some
+very carefully written functions need to exist to safely interrogate
+a random pointer to make that determination.
+
+Note the variable name convention in this file: "cinspector" refers to
+a cocoa-inspector object containing a set of objects being displayed,
+while "inspector" refers to an inspector object from the :inspector
+package, which are used for command-line inspecting.
+
+|#
+
+
+#|
+I'd rather set up this file to be
+- in-package cl-user
+- require of some things
+- a package definition for this code that brings in inspector::this-and-that and ccl::objc-stuff
+- a couple of load-file forms that populate the new package and have the bulk of the following code
+|#
+
+;;; This is useful when @ won't work, dynamically creating a NSString
+;;; pointer from a string.
+
+(defun nsstringptr (string)
+  (ccl::objc-constant-string-nsstringptr
+   (ccl::ns-constant-string string)))
+
+#+old
+(defmacro handler-case-for-cocoa (id form)
+  (declare (ignorable id))
+  `(handler-case
+    ,form
+    (condition (c)
+      (declare (ignorable c))
+      #+ignore
+      (format t "~s: Trapping condition: ~a" ,id c)
+      nil)))
+
+; for now this will map windows to objects -- the windows are pretty big,
+; though, so it would be nice to extend them so the list of inspected objects
+; is switchable in a single window (shouldn't be too hard once basic functionality
+; is slapped down)
+(defparameter *cocoa-inspector-nswindows-table* (make-hash-table :test 'eql))
+
+;;; this is what a window should map to - an object that manages all
+;;; the data a window might be displaying
+(defclass cocoa-inspector ()
+  ((object-vector :initform (make-array 0 :adjustable t :fill-pointer 0) :accessor object-vector)
+   (inspector-vector :initform (make-array 0 :adjustable t :fill-pointer 0) :accessor inspector-vector)
+   (focal-point :initform 0 :accessor focal-point)))
+
+;;; note that ELT pays attention to the fill pointer, while AREF doesn't!
+(defmethod object ((cinspector cocoa-inspector))
+  (elt (object-vector cinspector) (focal-point cinspector)))
+(defmethod nth-object ((cinspector cocoa-inspector) n)
+  (elt (object-vector cinspector) n))
+(defmethod inspector ((cinspector cocoa-inspector))
+  ;; This can return nil.
+  (let* ((i (focal-point cinspector))
+         (v (inspector-vector cinspector))
+         (n (length v)))
+    (if (< i n)
+      (aref v i))))
+(defmethod nth-inspector ((cinspector cocoa-inspector) n)
+  (elt (inspector-vector cinspector) n))
+(defmethod push-object (object (cinspector cocoa-inspector))
+  (let ((inspector (inspector::make-inspector object)))
+    (vector-push-extend object (object-vector cinspector))
+    (vector-push-extend inspector (inspector-vector cinspector))
+    (inspector::update-line-count inspector))
+  #+ignore
+  (format t "    after push-object, fill pointers = ~a ~a~%"
+	  (fill-pointer (object-vector cinspector)) (fill-pointer (inspector-vector cinspector)))
+  object)
+(defmethod (setf max-column) (value (cinspector cocoa-inspector))
+  (when (and (numberp value) (<= 0 value (1- (fill-pointer (object-vector cinspector)))))
+    (setf ; new fill-pointers are just outside of the valid bounds
+          (fill-pointer (object-vector cinspector)) (1+ value)
+	  (fill-pointer (inspector-vector cinspector)) (1+ value)
+	  ; new focal point is either what it was before, or the new max column if that's smaller
+	  (focal-point cinspector) (min value (focal-point cinspector)))
+    #+ignore
+    (format t "  after (setf max-column), fill pointers = ~a ~a~%"
+	    (fill-pointer (object-vector cinspector)) (fill-pointer (inspector-vector cinspector)))
+    value))
+
+;; In the browser view, we'll find the element for some column
+;; and consider whether any of its components merit further inspection
+;; and, if so, which ones
+(defmethod leaf-node-p ((thing t)) nil)
+(defmethod leaf-node-p ((thing (eql t))) t)
+(defmethod leaf-node-p ((thing null)) t)
+(defmethod leaf-node-p ((thing number)) t)
+(defmethod leaf-node-p ((thing string)) t)
+(defmethod leaf-node-p ((thing inspector::unbound-marker)) t)
+(defmethod leaf-field-p ((thing t) n)
+  (declare (ignore n))
+  nil) ; for a non-leaf node, all fields are futher probable by default
+(defmethod leaf-field-p ((thing symbol) n)
+  (when (and (keywordp thing) (= n 4)) t))
+
+; whatever is currently the selected object in the inspector, get its
+; properties and values for the tableView and print them to a string
+(defun focus-nth-line (cinspector n)
+  (let* ((inspector (inspector cinspector))
+	 (*print-circle* t)
+	 (output-stream (make-string-output-stream)))
+    (inspector::prin1-line-n inspector output-stream n)
+    (get-output-stream-string output-stream)))
+(defun nth-object-nth-line (cinspector obj-n line-n)
+  (let* ((inspector (nth-inspector cinspector obj-n))
+	 (*print-circle* t)
+	 (output-stream (make-string-output-stream)))
+    (inspector::prin1-line-n inspector output-stream line-n)
+    (get-output-stream-string output-stream)))
+(defun focus-nth-property (cinspector n)
+  (let ((inspector (inspector cinspector)))
+    (multiple-value-bind (value label type) (inspector::line-n inspector n)
+      (declare (ignore value type))
+      (if label
+	  (format nil "~a" label)
+	""))))
+(defun focus-nth-value (cinspector n)
+  (let* ((inspector (inspector cinspector))
+	 (*print-circle* t)
+	 (output-stream (make-string-output-stream))
+	 (*package* (find-package :cl-user)))
+    (multiple-value-bind (value label type) (inspector::line-n inspector n)
+      (declare (ignore label type))
+      (format output-stream "~s" value))
+    (get-output-stream-string output-stream)))
+(defun nth-object-nth-value (cinspector obj-n line-n)
+  (let ((inspector (nth-inspector cinspector obj-n)))
+    (multiple-value-bind (value label type) (inspector::line-n inspector line-n)
+      (declare (ignore label type))
+      value)))
+(defun (setf focus-nth-value) (value cinspector n)
+  (let ((inspector (inspector cinspector)))
+    (setf (inspector::line-n inspector n) value)))
+(defun focus-nth-value-editable (cinspector n)
+  (let ((inspector (inspector cinspector)))
+    (multiple-value-bind (value label type) (inspector::line-n inspector n)
+      (declare (ignore value))
+      (and (or (null type)
+	       (eq :normal type)
+	       (eq :colon type))
+	   (editable-field-p (object cinspector) n label)))))
+(defun nth-object-nth-value-editable (cinspector obj-n line-n)
+  (let ((inspector (nth-inspector cinspector obj-n)))
+    (multiple-value-bind (value label type) (inspector::line-n inspector line-n)
+      (declare (ignore value))
+      (and (or (null type)
+	       (eq :normal type)
+	       (eq :colon type))
+	   (editable-field-p (nth-object cinspector obj-n) line-n label)))))
+;; for now most of these will assume that field numbers are good enough,
+;; certain things have inspector fields that move around (like symbols)
+;; and can be dealt with on a case by case basis, but that's the reason
+;; for passing in the label along with the field number
+(defmethod editable-field-p ((thing t) n label)
+  (declare (ignore n label))
+  t)
+;; for lists field 4 is length, could cause a change but inspector doesn't just handle it
+;; and at the moment I haven't started thinking of a framework for allowing such extensions
+(defmethod editable-field-p ((thing list) n label)
+  (declare (ignore label))
+  (/= n 4))
+
+#|
+I think most of the following should be pretty straightforward for
+most utilities meant to run under openmcl: A NIB file, some delegates
+and data sources, and some specialized callback functions for talking
+with the ObjC world, and some standard code for keeping track of the
+appropriate windows.  -hel
+|#
+
+; When loading a NIB file with an NSWindowController, DON'T omit the .nib extension
+; if you're calling initWithWindowNibPath:owner: (even though the documentation says you should!)
+#+ignore
+(defparameter *default-inspector-nib-pathname* #p"CCL:OpenMCL.app;Contents;Resources;English.lproj;OpenmclInspector.nib")
+; When loading it with a custom WindowController and initWithWindowNibName:, just the main file name
+(defparameter *default-inspector-nib-pathname* #p"OpenmclInspector")
+
+;; Q: Is this subclass of NSBrowser enabling the doubleAction? I added it expecting to have to
+;; specialize mouseDown (or whatever) to track double-clicking, but it just started working.
+(defclass inspector-ns-browser (ns:ns-browser) ; just to specialize mousing, not add slots
+    ()
+  (:metaclass ns:+ns-object))
+
+(defclass inspector-window-controller (ns:ns-window-controller)
+    ((inspector-browser :foreign-type :id :reader inspector-browser))
+  (:metaclass ns:+ns-object))
+
+(defclass inspector-browser-delegate (ns:ns-object)
+    ((inspector-table-view :foreign-type :id :reader inspector-table-view)
+     (inspector-window :foreign-type :id :reader inspector-window))
+  (:metaclass ns:+ns-object))
+
+; why is the order of these two slots important?
+; I get a segfault selecting the browser when they're in window/browser order after doing modifications in the table.
+(defclass inspector-table-view-data-source (ns:ns-object)
+    ((inspector-browser :foreign-type :id :reader inspector-browser)
+     (inspector-window :foreign-type :id :reader inspector-window))
+  (:metaclass ns:+ns-object))
+
+(defclass inspector-table-view-delegate (ns:ns-object)
+    ((inspector-window :foreign-type :id :reader inspector-window))
+  (:metaclass ns:+ns-object))  
+
+
+;;; is there some reason this is called before the cell is actually
+;;; selected? In any case, when a non-leaf cell is selected, this
+;;; function is called first for the new column, so it has to push the
+;;; new element into the cinspector -- what the browserAction will be
+;;; left doing it remains to be seen. The only other time this is
+;;; called AFAICT is when loadColumnZero or reloadColumn is called
+(objc:defmethod (#/browser:numberOfRowsInColumn: :<NSI>nteger)
+    ((self inspector-browser-delegate)
+     browser
+     (column :<NSI>nteger))
+  (or (let* ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*))
+             (selected-column (#/selectedColumn browser)) ; probably always (1- column), when a column is selected
+             (cinspector-column (1- selected-column)) ; 2nd column of nsbrowser <-> 1st column of cinspector
+             (row (#/selectedRowInColumn: browser selected-column)))
+        #+ignore
+        (format t "getting length of column ~d based on row ~d in column ~d~%" column row selected-column)
+        (cond ((not cinspector) 0)
+              ((= column 0) 1)          ; just displaying the printed representaiton of the top inspected object
+              ((= selected-column 0)    ; selected the printed rep of the inspected object (column should = 1)
+               (setf (max-column cinspector) 0) ; crop object-vector in cinspector
+               (let ((inspector (nth-inspector cinspector 0))) ; inspector for top object
+                 (inspector::inspector-line-count inspector)))
+              ((>= selected-column 1)   ; (-1 is the N/A column)
+               (setf (max-column cinspector) cinspector-column) ; crop object-vector in cinspector
+               (push-object (nth-object-nth-value cinspector cinspector-column row) cinspector)
+               (let ((inspector (nth-inspector cinspector (1+ cinspector-column)))) ; inspector for object just pushed
+                 (inspector::inspector-line-count inspector)))))
+      0))
+
+#|
+;; temporarily saved in case the above fails horribly
+    (if cinspector
+	(handler-case
+	 (progn (when (<= 0 selected-column) ; -1 is sort of the N/A column
+		  (setf (max-column cinspector) selected-column)
+		  (push-object (nth-object-nth-value cinspector selected-column row) cinspector))
+		(let ((inspector (nth-inspector cinspector column)))
+		  (inspector::inspector-line-count inspector)))
+	 (condition () 0))
+      0)))
+|#
+
+;; In the following method defn this is unnecessary, the Browser can tell this for itself
+;; [cell "setLoaded:" :<BOOL> #$YES]
+(objc:defmethod (#/browser:willDisplayCell:atRow:column: :void)
+    ((self inspector-browser-delegate)
+     browser
+     cell
+     (row :<NSI>nteger)
+     (column :<NSI>nteger))
+  (declare (ignorable browser column))
+  (let ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*))
+        (cinspector-column (1- column))) ; 2nd column of nsbrowser <-> 1st column of cinspector
+    #+ignore
+    (format t "asking for value for column ~a, row ~a~%" column row)
+    (cond ((not cinspector) nil)
+          ((= column 0)
+           (#/setStringValue: cell  (nsstringptr (format nil "~s" (nth-object cinspector 0))))
+           (#/setLeaf: cell nil))
+          (t
+           ;; when switching between widgets to the browser, we can
+           ;; have reloaded a column and need to drill down a row
+           ;; from where we are at the moment
+           (#/setStringValue: cell  (nsstringptr (nth-object-nth-line cinspector cinspector-column row)))
+           ;; leaf-p should really consider the type of the object in
+           ;; question (eventually taking into account whether we're
+           ;; browsing the class heirarchy or into objc or whatever)
+           (#/setLeaf: cell (or (leaf-node-p (nth-object cinspector cinspector-column)) ; i.e. no fields drill down
+                                (leaf-field-p (nth-object cinspector cinspector-column) row)
+                                ;; for now...
+                                (= row 0)
+                                (not (nth-object-nth-value-editable cinspector cinspector-column row))))))))
+
+;;; when all is said and done and once the cinspector is properly
+;;; populated, the selected object in the browser's nth column is
+;;; actually the object in the cinspector's nth column (i.e. because
+;;; the selected object is displayed in the next browser column over,
+;;; and the cinspector and nsbrowser have a 1-off discrepancy, they
+;;; cancel out) -- just a note to make the difference between these
+;;; next two functions and the previous two functions
+
+;;; change the focus of the the table view to be the selected object
+(objc:defmethod (#/browserAction: :void)
+    ((self inspector-browser-delegate)
+     sender); don't know why I'd want to, but could use a separate IBTarget class
+  #+ignore (format t "browserAction~%")
+  (let* ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*))
+         (column (#/selectedColumn sender)))
+    (when (<= 0 column)
+      (setf (focal-point cinspector) column)
+      (#/reloadData (inspector-table-view self))
+      #+ignore
+      (format t "      responding to selection in column ~d~%" column))))
+
+;; open a new inspector on the selected object
+(objc:defmethod (#/browserDoubleAction: :void)
+    ((self inspector-browser-delegate)
+     sender)
+  #+ignore (format t "browserDoubleAction~%")
+  (let* ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*))
+         (column (#/selectedColumn sender)))
+    (when (< -1 column (length (object-vector cinspector)))
+      ;; this seems to work, but I'm not really paying attention to
+      ;; thread stuff...
+      (cinspect (nth-object cinspector column)))))
+
+(objc:defmethod (#/numberOfRowsInTableView: :<NSI>nteger)
+    ((self inspector-table-view-data-source)
+     table-view)
+  (declare (ignore table-view))
+  
+  (or (let ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*)))
+        (if cinspector
+          (let ((inspector (inspector cinspector)))
+            (if inspector
+              (inspector::inspector-line-count inspector)
+              0))))
+      0))
+
+(objc:defmethod #/tableView:objectValueForTableColumn:row:
+    ((self inspector-table-view-data-source)
+     table-view
+     table-column
+     (row :<NSI>nteger))
+  (declare (ignore table-view))
+  (let ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*)))
+    (cond ((not cinspector)
+	   #@"")
+	  ((#/isEqual: (#/identifier table-column) #@"property")
+	   (nsstringptr (focus-nth-property cinspector row)))
+	  ((#/isEqual: (#/identifier table-column) #@"value")
+	   (nsstringptr (focus-nth-value cinspector row))))))
+
+;; I'm hoping that the delegate will prevent this from being called willy-nilly
+(objc:defmethod (#/tableView:setObjectValue:forTableColumn:row: :void)
+    ((self inspector-table-view-data-source)
+     table-view object table-column (row :<NSI>nteger))
+  (declare (ignore table-column))
+   (let ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*)))
+     ;; without any formatters, object appears to be an NSCFString
+     ;; also note we should probably save the original value (including unboundness etc)
+     ;; first so that we can return to it in the event of any error
+     ;; plus we should avoid doing anything if the original string and the new string are equal
+     (when cinspector
+       (setf (focus-nth-value cinspector row)
+	     (let ((*package* (find-package :cl-user)))
+	       ;; with-autorelease-pool could possibly be needed to
+	       ;; autorelease the cString we're handling (I think)
+	       (eval (read-from-string (lisp-string-from-nsstring object)))))
+       (#/reloadData table-view) ; really could just reload that one cell, but don't know how...
+       ;; changing the focused object may effect the browser's path,
+       ;; reload its column and keep the cinspector consistent Here we
+       ;; have to make sure that the column we're reloading and the
+       ;; column after both have values to display, for when
+       ;; reloadColumn: invokes browser:willDisplayCell:atRow:column:
+       (#/reloadColumn: (inspector-browser self) (focal-point cinspector))
+       ;; [inspector-browser "scrollColumnToVisible:" :int (focal-point cinspector)] ; maybe need this, too
+       )))
+
+;;; In the table view, the properties are not editable, but the
+;;; values (if editable) allow lisp forms to be entered that are
+;;; read and evaluated to determine the new property value.
+(objc:defmethod (#/tableView:shouldEditTableColumn:row: :<BOOL>)
+    ((self inspector-table-view-delegate)
+     table-view table-column (row :<NSI>nteger))
+  (declare (ignore table-view))
+  (let ((cinspector (gethash (inspector-window self) *cocoa-inspector-nswindows-table*)))
+    (and cinspector
+         (#/isEqual: (#/identifier table-column) #@"value")
+         (/= row 0)                     ; in practice the reference to
+                                        ; the object isn't editable, and
+                                        ; the GUI semantics aren't clear anyway,
+                                        ; possibly there will come a
+                                        ; time when I put row 0 in the
+                                        ; table title, but I need to
+                                        ; maintain the 0-indexed
+                                        ; focus-nth-whatever API here
+                                        ; and elsewhere if I do that
+         (focus-nth-value-editable cinspector row))))
+
+;; the inspectorwindowcontroller is set up as the delegate of the window...
+;; we now eliminate the dangling pointer to the window from the hash table
+(objc:defmethod (#/windowWillClose: :void)
+    ((self inspector-window-controller) notification)
+  (let ((nswindow (#/object notification)))
+    (remhash nswindow *cocoa-inspector-nswindows-table*)))
+
+;;; hopefully a generally useful function
+(defun load-windowcontroller-from-nib (wc-classname nib-pathname)
+  "Takes a NIB name and returns a new window controller"
+  (with-autorelease-pool
+      (make-instance 
+       wc-classname
+       :with-window-nib-name (nsstringptr (namestring nib-pathname)))))
+
+;;; make a new inspector window from the nib file, and hash the window's
+;;; browser and tableview to the object
+(defun cinspect (object)
+  (with-autorelease-pool
+      (let* ((windowcontroller (load-windowcontroller-from-nib 'inspector-window-controller *default-inspector-nib-pathname*))
+	     (window (#/window windowcontroller))
+	     (cinspector (make-instance 'cocoa-inspector)))
+	;; set up the window's initial "focused" object -- this may change as
+	;; different parts of the inspector are clicked on, and actually we
+	;; probably want to track more information than that associated with the
+	;; window, so probably this will eventually be hashed to something like
+	;; an inspector for the object or an even bigger wrapper
+	(setf (gethash window *cocoa-inspector-nswindows-table*) cinspector)
+	(push-object object cinspector)
+	;; is this working? it isn't breaking, but double-clicking is
+	;; being handled as two single actions
+	(let* ((browser (inspector-browser windowcontroller)))
+          (#/setColumnResizingType: browser #$NSBrowserUserColumnResizing)
+          (#/setPrefersAllColumnUserResizing: browser nil)
+	  (#/setDoubleAction: browser (@selector #/browserDoubleAction:))
+	  (#/setIgnoresMultiClick: browser t))
+	(#/showWindow: windowcontroller window)
+	window)))
+
+;;; Make INSPECT call CINSPECT.
+(setq inspector::*default-inspector-ui-creation-function* 'cinspect)
Index: /branches/new-random/examples/cocoa/.cvsignore
===================================================================
--- /branches/new-random/examples/cocoa/.cvsignore	(revision 13309)
+++ /branches/new-random/examples/cocoa/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/examples/cocoa/currency-converter/CurrencyConverter.nib/designable.nib
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/CurrencyConverter.nib/designable.nib	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/CurrencyConverter.nib/designable.nib	(revision 13309)
@@ -0,0 +1,2923 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.01">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9A581</string>
+		<string key="IBDocument.InterfaceBuilderVersion">629</string>
+		<string key="IBDocument.AppKitVersion">949</string>
+		<string key="IBDocument.HIToolboxVersion">343.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="111"/>
+			<integer value="368"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string id="418681816">com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1021">
+				<string key="NSClassName" id="310050156">NSApplication</string>
+			</object>
+			<object class="NSCustomObject" id="1014">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1050">
+				<reference key="NSClassName" ref="310050156"/>
+			</object>
+			<object class="NSMenu" id="649796088">
+				<string key="NSTitle">AMainMenu</string>
+				<object class="NSMutableArray" key="NSMenuItems">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMenuItem" id="694149608">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle" id="756066857">Currency Converter</string>
+						<string key="NSKeyEquiv" id="829414822"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<object class="NSCustomResource" key="NSOnImage" id="499884332">
+							<string key="NSClassName" id="538522715">NSImage</string>
+							<string key="NSResourceName">NSMenuCheckmark</string>
+						</object>
+						<object class="NSCustomResource" key="NSMixedImage" id="303439570">
+							<reference key="NSClassName" ref="538522715"/>
+							<string key="NSResourceName">NSMenuMixedState</string>
+						</object>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="110575045">
+							<reference key="NSTitle" ref="756066857"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="238522557">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">About Currency Converter</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="304266470">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="609285721">
+									<reference key="NSMenu" ref="110575045"/>
+									<string type="base64-UTF8" key="NSTitle">UHJlZmVyZW5jZXPigKY</string>
+									<string key="NSKeyEquiv">,</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="481834944">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="1046388886">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle" id="787847730">Services</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="752062318">
+										<reference key="NSTitle" ref="787847730"/>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+										</object>
+										<string key="NSName">_NSServicesMenu</string>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="646227648">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="755159360">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide Currency Converter</string>
+									<string key="NSKeyEquiv" id="824766112">h</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="342932134">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide Others</string>
+									<reference key="NSKeyEquiv" ref="824766112"/>
+									<int key="NSKeyEquivModMask">1572864</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="908899353">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Show All</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="1056857174">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="632727374">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Quit Currency Converter</string>
+									<string key="NSKeyEquiv">q</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+							</object>
+							<string key="NSName">_NSAppleMenu</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="379814623">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle" id="815839962">File</string>
+						<reference key="NSKeyEquiv" ref="829414822"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="499884332"/>
+						<reference key="NSMixedImage" ref="303439570"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="720053764">
+							<reference key="NSTitle" ref="815839962"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="705341025">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">New</string>
+									<string key="NSKeyEquiv">n</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="722745758">
+									<reference key="NSMenu" ref="720053764"/>
+									<string type="base64-UTF8" key="NSTitle">T3BlbuKApg</string>
+									<string key="NSKeyEquiv">o</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="1025936716">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle" id="50471215">Open Recent</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="1065607017">
+										<reference key="NSTitle" ref="50471215"/>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSMenuItem" id="759406840">
+												<reference key="NSMenu" ref="1065607017"/>
+												<string key="NSTitle">Clear Menu</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+										</object>
+										<string key="NSName">_NSRecentDocumentsMenu</string>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="425164168">
+									<reference key="NSMenu" ref="720053764"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="776162233">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Close</string>
+									<string key="NSKeyEquiv">w</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="1023925487">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Save</string>
+									<string key="NSKeyEquiv">s</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="117038363">
+									<reference key="NSMenu" ref="720053764"/>
+									<string type="base64-UTF8" key="NSTitle">U2F2ZSBBc+KApg</string>
+									<string key="NSKeyEquiv">S</string>
+									<int key="NSKeyEquivModMask">1179648</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="579971712">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Revert to Saved</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="1010469920">
+									<reference key="NSMenu" ref="720053764"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="294629803">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Page Setup...</string>
+									<string key="NSKeyEquiv">P</string>
+									<int key="NSKeyEquivModMask">1179648</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+									<reference key="NSToolTip" ref="829414822"/>
+								</object>
+								<object class="NSMenuItem" id="49223823">
+									<reference key="NSMenu" ref="720053764"/>
+									<string type="base64-UTF8" key="NSTitle">UHJpbnTigKY</string>
+									<string key="NSKeyEquiv">p</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="952259628">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle" id="173179266">Edit</string>
+						<reference key="NSKeyEquiv" ref="829414822"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="499884332"/>
+						<reference key="NSMixedImage" ref="303439570"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="789758025">
+							<reference key="NSTitle" ref="173179266"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="1058277027">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle">Undo</string>
+									<string key="NSKeyEquiv">z</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="790794224">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle">Redo</string>
+									<string key="NSKeyEquiv">Z</string>
+									<int key="NSKeyEquivModMask">1179648</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="1040322652">
+									<reference key="NSMenu" ref="789758025"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="296257095">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle">Cut</string>
+									<string key="NSKeyEquiv">x</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="860595796">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle">Copy</string>
+									<string key="NSKeyEquiv">c</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="29853731">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle">Paste</string>
+									<string key="NSKeyEquiv">v</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="437104165">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle">Delete</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="583158037">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle">Select All</string>
+									<string key="NSKeyEquiv">a</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="212016141">
+									<reference key="NSMenu" ref="789758025"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="892235320">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle" id="293323797">Find</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="963351320">
+										<reference key="NSTitle" ref="293323797"/>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSMenuItem" id="447796847">
+												<reference key="NSMenu" ref="963351320"/>
+												<string type="base64-UTF8" key="NSTitle">RmluZOKApg</string>
+												<string key="NSKeyEquiv">f</string>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+												<int key="NSTag">1</int>
+											</object>
+											<object class="NSMenuItem" id="326711663">
+												<reference key="NSMenu" ref="963351320"/>
+												<string key="NSTitle">Find Next</string>
+												<string key="NSKeyEquiv">g</string>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+												<int key="NSTag">2</int>
+											</object>
+											<object class="NSMenuItem" id="270902937">
+												<reference key="NSMenu" ref="963351320"/>
+												<string key="NSTitle">Find Previous</string>
+												<string key="NSKeyEquiv">G</string>
+												<int key="NSKeyEquivModMask">1179648</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+												<int key="NSTag">3</int>
+											</object>
+											<object class="NSMenuItem" id="159080638">
+												<reference key="NSMenu" ref="963351320"/>
+												<string key="NSTitle">Use Selection for Find</string>
+												<string key="NSKeyEquiv">e</string>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+												<int key="NSTag">7</int>
+											</object>
+											<object class="NSMenuItem" id="88285865">
+												<reference key="NSMenu" ref="963351320"/>
+												<string key="NSTitle">Jump to Selection</string>
+												<string key="NSKeyEquiv">j</string>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+										</object>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="972420730">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle" id="429534365">Spelling and Grammar</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="769623530">
+										<reference key="NSTitle" ref="429534365"/>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSMenuItem" id="679648819">
+												<reference key="NSMenu" ref="769623530"/>
+												<string type="base64-UTF8" key="NSTitle">U2hvdyBTcGVsbGluZ+KApg</string>
+												<string key="NSKeyEquiv">:</string>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+											<object class="NSMenuItem" id="96193923">
+												<reference key="NSMenu" ref="769623530"/>
+												<string key="NSTitle">Check Spelling</string>
+												<string key="NSKeyEquiv">;</string>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+											<object class="NSMenuItem" id="948374510">
+												<reference key="NSMenu" ref="769623530"/>
+												<string key="NSTitle">Check Spelling While Typing</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+											<object class="NSMenuItem" id="967646866">
+												<reference key="NSMenu" ref="769623530"/>
+												<string key="NSTitle">Check Grammar With Spelling</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+										</object>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="507821607">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle" id="787965120">Substitutions</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="698887838">
+										<reference key="NSTitle" ref="787965120"/>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSMenuItem" id="605118523">
+												<reference key="NSMenu" ref="698887838"/>
+												<string key="NSTitle">Smart Copy/Paste</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+												<int key="NSTag">1</int>
+											</object>
+											<object class="NSMenuItem" id="197661976">
+												<reference key="NSMenu" ref="698887838"/>
+												<string key="NSTitle">Smart Quotes</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+												<int key="NSTag">2</int>
+											</object>
+											<object class="NSMenuItem" id="708854459">
+												<reference key="NSMenu" ref="698887838"/>
+												<string key="NSTitle">Smart Links</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+												<int key="NSTag">3</int>
+											</object>
+										</object>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="676164635">
+									<reference key="NSMenu" ref="789758025"/>
+									<string key="NSTitle" id="422195618">Speech</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="785027613">
+										<reference key="NSTitle" ref="422195618"/>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSMenuItem" id="731782645">
+												<reference key="NSMenu" ref="785027613"/>
+												<string key="NSTitle">Start Speaking</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+											<object class="NSMenuItem" id="680220178">
+												<reference key="NSMenu" ref="785027613"/>
+												<string key="NSTitle">Stop Speaking</string>
+												<reference key="NSKeyEquiv" ref="829414822"/>
+												<int key="NSKeyEquivModMask">1048576</int>
+												<int key="NSMnemonicLoc">2147483647</int>
+												<reference key="NSOnImage" ref="499884332"/>
+												<reference key="NSMixedImage" ref="303439570"/>
+											</object>
+										</object>
+									</object>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="626404410">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle" id="249100029">Format</string>
+						<reference key="NSKeyEquiv" ref="829414822"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="499884332"/>
+						<reference key="NSMixedImage" ref="303439570"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="502084290">
+							<reference key="NSTitle" ref="249100029"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="519768076">
+									<reference key="NSMenu" ref="502084290"/>
+									<string key="NSTitle">Show Fonts</string>
+									<string key="NSKeyEquiv" id="394503829">t</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="1028416764">
+									<reference key="NSMenu" ref="502084290"/>
+									<string key="NSTitle">Show Colors</string>
+									<string key="NSKeyEquiv">C</string>
+									<int key="NSKeyEquivModMask">1179648</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="586577488">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle" id="875236103">View</string>
+						<reference key="NSKeyEquiv" ref="829414822"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="499884332"/>
+						<reference key="NSMixedImage" ref="303439570"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="466310130">
+							<reference key="NSTitle" ref="875236103"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="102151532">
+									<reference key="NSMenu" ref="466310130"/>
+									<string key="NSTitle">Show Toolbar</string>
+									<reference key="NSKeyEquiv" ref="394503829"/>
+									<int key="NSKeyEquivModMask">1572864</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="237841660">
+									<reference key="NSMenu" ref="466310130"/>
+									<string type="base64-UTF8" key="NSTitle">Q3VzdG9taXplIFRvb2xiYXLigKY</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="713487014">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle" id="358639831">Window</string>
+						<reference key="NSKeyEquiv" ref="829414822"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="499884332"/>
+						<reference key="NSMixedImage" ref="303439570"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="835318025">
+							<reference key="NSTitle" ref="358639831"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="1011231497">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Minimize</string>
+									<string key="NSKeyEquiv">m</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="575023229">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Zoom</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="299356726">
+									<reference key="NSMenu" ref="835318025"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<reference key="NSTitle" ref="829414822"/>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+								<object class="NSMenuItem" id="625202149">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Bring All to Front</string>
+									<reference key="NSKeyEquiv" ref="829414822"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+							</object>
+							<string key="NSName">_NSWindowsMenu</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="391199113">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle" id="255122429">Help</string>
+						<reference key="NSKeyEquiv" ref="829414822"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="499884332"/>
+						<reference key="NSMixedImage" ref="303439570"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="374024848">
+							<reference key="NSTitle" ref="255122429"/>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="238773614">
+									<reference key="NSMenu" ref="374024848"/>
+									<string key="NSTitle">Currency Converter Help</string>
+									<string key="NSKeyEquiv">?</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="499884332"/>
+									<reference key="NSMixedImage" ref="303439570"/>
+								</object>
+							</object>
+						</object>
+					</object>
+				</object>
+				<string key="NSName">_NSMainMenu</string>
+			</object>
+			<object class="NSWindowTemplate" id="513744381">
+				<int key="NSWindowStyleMask">7</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{306, 767}, {350, 189}}</string>
+				<int key="NSWTFlags">611844096</int>
+				<reference key="NSWindowTitle" ref="756066857"/>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<object class="NSView" key="NSWindowView" id="414427165">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="933737783">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{195, 147}, {135, 22}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="784994109">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">272630784</int>
+								<reference key="NSContents" ref="829414822"/>
+								<object class="NSFont" key="NSSupport" id="532763475">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="933737783"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor" id="350567593">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName" id="609685845">System</string>
+									<string key="NSColorName">textBackgroundColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="139158475">
+									<int key="NSColorSpace">6</int>
+									<reference key="NSCatalogName" ref="609685845"/>
+									<string key="NSColorName">textColor</string>
+									<object class="NSColor" key="NSColor" id="931403188">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="775915874">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{195, 115}, {135, 22}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="899290995">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">272630784</int>
+								<reference key="NSContents" ref="829414822"/>
+								<reference key="NSSupport" ref="532763475"/>
+								<reference key="NSControlView" ref="775915874"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="350567593"/>
+								<reference key="NSTextColor" ref="139158475"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="247106261">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{195, 83}, {135, 22}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="31819280">
+								<int key="NSCellFlags">-2072904127</int>
+								<int key="NSCellFlags2">272630784</int>
+								<reference key="NSContents" ref="829414822"/>
+								<reference key="NSSupport" ref="532763475"/>
+								<reference key="NSControlView" ref="247106261"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="350567593"/>
+								<reference key="NSTextColor" ref="139158475"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="12526602">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{47, 149}, {143, 17}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="385927916">
+								<int key="NSCellFlags">67239488</int>
+								<int key="NSCellFlags2">71304192</int>
+								<string key="NSContents">Exchange rate per $1:</string>
+								<reference key="NSSupport" ref="532763475"/>
+								<reference key="NSControlView" ref="12526602"/>
+								<object class="NSColor" key="NSBackgroundColor" id="645417562">
+									<int key="NSColorSpace">6</int>
+									<reference key="NSCatalogName" ref="609685845"/>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="786989944">
+									<int key="NSColorSpace">6</int>
+									<reference key="NSCatalogName" ref="609685845"/>
+									<string key="NSColorName">controlTextColor</string>
+									<reference key="NSColor" ref="931403188"/>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="433602985">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{67, 115}, {123, 17}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="917041781">
+								<int key="NSCellFlags">67239488</int>
+								<int key="NSCellFlags2">71304192</int>
+								<string key="NSContents">Dollars to Convert:</string>
+								<reference key="NSSupport" ref="532763475"/>
+								<reference key="NSControlView" ref="433602985"/>
+								<reference key="NSBackgroundColor" ref="645417562"/>
+								<reference key="NSTextColor" ref="786989944"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="263151680">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 83}, {173, 17}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="710696568">
+								<int key="NSCellFlags">67239488</int>
+								<int key="NSCellFlags2">71304192</int>
+								<string key="NSContents">Amount in other Currency:</string>
+								<reference key="NSSupport" ref="532763475"/>
+								<reference key="NSControlView" ref="263151680"/>
+								<reference key="NSBackgroundColor" ref="645417562"/>
+								<reference key="NSTextColor" ref="786989944"/>
+							</object>
+						</object>
+						<object class="NSButton" id="667602245">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{214, 12}, {96, 32}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="613837648">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Convert</string>
+								<reference key="NSSupport" ref="532763475"/>
+								<reference key="NSControlView" ref="667602245"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<reference key="NSAlternateContents" ref="829414822"/>
+								<string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+						<object class="NSBox" id="136421666">
+							<reference key="NSNextResponder" ref="414427165"/>
+							<int key="NSvFlags">12</int>
+							<string key="NSFrame">{{20, 58}, {310, 5}}</string>
+							<reference key="NSSuperview" ref="414427165"/>
+							<reference key="NSWindow"/>
+							<string key="NSOffsets">{0, 0}</string>
+							<object class="NSTextFieldCell" key="NSTitleCell">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents">Box</string>
+								<reference key="NSSupport" ref="532763475"/>
+								<reference key="NSBackgroundColor" ref="350567593"/>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
+								</object>
+							</object>
+							<int key="NSBorderType">3</int>
+							<int key="NSBoxType">2</int>
+							<int key="NSTitlePosition">0</int>
+							<bool key="NSTransparent">NO</bool>
+						</object>
+					</object>
+					<string key="NSFrameSize">{350, 189}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
+			</object>
+			<object class="NSCustomObject" id="1001780962">
+				<string key="NSClassName" id="171510208">Converter</string>
+			</object>
+			<object class="NSCustomObject" id="627880282">
+				<string key="NSClassName" id="416391972">ConverterController</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performMiniaturize:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="1011231497"/>
+					</object>
+					<int key="connectionID">37</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">arrangeInFront:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="625202149"/>
+					</object>
+					<int key="connectionID">39</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">print:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="49223823"/>
+					</object>
+					<int key="connectionID">86</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">runPageLayout:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="294629803"/>
+					</object>
+					<int key="connectionID">87</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">clearRecentDocuments:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="759406840"/>
+					</object>
+					<int key="connectionID">127</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">orderFrontStandardAboutPanel:</string>
+						<reference key="source" ref="1021"/>
+						<reference key="destination" ref="238522557"/>
+					</object>
+					<int key="connectionID">142</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performClose:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="776162233"/>
+					</object>
+					<int key="connectionID">193</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">toggleContinuousSpellChecking:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="948374510"/>
+					</object>
+					<int key="connectionID">222</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">undo:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="1058277027"/>
+					</object>
+					<int key="connectionID">223</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">copy:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="860595796"/>
+					</object>
+					<int key="connectionID">224</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">checkSpelling:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="96193923"/>
+					</object>
+					<int key="connectionID">225</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">paste:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="29853731"/>
+					</object>
+					<int key="connectionID">226</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">stopSpeaking:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="680220178"/>
+					</object>
+					<int key="connectionID">227</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">cut:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="296257095"/>
+					</object>
+					<int key="connectionID">228</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">showGuessPanel:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="679648819"/>
+					</object>
+					<int key="connectionID">230</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">redo:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="790794224"/>
+					</object>
+					<int key="connectionID">231</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">selectAll:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="583158037"/>
+					</object>
+					<int key="connectionID">232</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">startSpeaking:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="731782645"/>
+					</object>
+					<int key="connectionID">233</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">delete:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="437104165"/>
+					</object>
+					<int key="connectionID">235</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performZoom:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="575023229"/>
+					</object>
+					<int key="connectionID">240</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performFindPanelAction:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="447796847"/>
+					</object>
+					<int key="connectionID">241</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">centerSelectionInVisibleArea:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="88285865"/>
+					</object>
+					<int key="connectionID">245</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">toggleGrammarChecking:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="967646866"/>
+					</object>
+					<int key="connectionID">347</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">toggleSmartInsertDelete:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="605118523"/>
+					</object>
+					<int key="connectionID">355</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">toggleAutomaticQuoteSubstitution:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="197661976"/>
+					</object>
+					<int key="connectionID">356</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">toggleAutomaticLinkDetection:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="708854459"/>
+					</object>
+					<int key="connectionID">357</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">showHelp:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="238773614"/>
+					</object>
+					<int key="connectionID">360</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">orderFrontColorPanel:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="1028416764"/>
+					</object>
+					<int key="connectionID">361</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">saveDocument:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="1023925487"/>
+					</object>
+					<int key="connectionID">362</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">saveDocumentAs:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="117038363"/>
+					</object>
+					<int key="connectionID">363</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">revertDocumentToSaved:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="579971712"/>
+					</object>
+					<int key="connectionID">364</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">runToolbarCustomizationPalette:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="237841660"/>
+					</object>
+					<int key="connectionID">365</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">toggleToolbarShown:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="102151532"/>
+					</object>
+					<int key="connectionID">366</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hide:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="755159360"/>
+					</object>
+					<int key="connectionID">369</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hideOtherApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="342932134"/>
+					</object>
+					<int key="connectionID">370</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">terminate:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="632727374"/>
+					</object>
+					<int key="connectionID">371</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">unhideAllApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="908899353"/>
+					</object>
+					<int key="connectionID">372</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="75124843">nextKeyView</string>
+						<reference key="source" ref="933737783"/>
+						<reference key="destination" ref="775915874"/>
+					</object>
+					<int key="connectionID">390</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<reference key="label" ref="75124843"/>
+						<reference key="source" ref="775915874"/>
+						<reference key="destination" ref="933737783"/>
+					</object>
+					<int key="connectionID">391</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">initialFirstResponder</string>
+						<reference key="source" ref="513744381"/>
+						<reference key="destination" ref="933737783"/>
+					</object>
+					<int key="connectionID">392</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="1041581452">rateField</string>
+						<reference key="source" ref="627880282"/>
+						<reference key="destination" ref="933737783"/>
+					</object>
+					<int key="connectionID">396</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="90614103">dollarField</string>
+						<reference key="source" ref="627880282"/>
+						<reference key="destination" ref="775915874"/>
+					</object>
+					<int key="connectionID">397</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="829906625">amountField</string>
+						<reference key="source" ref="627880282"/>
+						<reference key="destination" ref="247106261"/>
+					</object>
+					<int key="connectionID">398</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label" id="943815538">converter</string>
+						<reference key="source" ref="627880282"/>
+						<reference key="destination" ref="1001780962"/>
+					</object>
+					<int key="connectionID">399</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label" id="408592174">convert:</string>
+						<reference key="source" ref="627880282"/>
+						<reference key="destination" ref="667602245"/>
+					</object>
+					<int key="connectionID">400</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1049">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1048"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1021"/>
+						<reference key="parent" ref="1049"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1014"/>
+						<reference key="parent" ref="1049"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1050"/>
+						<reference key="parent" ref="1049"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="649796088"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="713487014"/>
+							<reference ref="694149608"/>
+							<reference ref="391199113"/>
+							<reference ref="952259628"/>
+							<reference ref="379814623"/>
+							<reference ref="586577488"/>
+							<reference ref="626404410"/>
+						</object>
+						<reference key="parent" ref="1049"/>
+						<string key="objectName">MainMenu</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="713487014"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="835318025"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">56</int>
+						<reference key="object" ref="694149608"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="110575045"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">103</int>
+						<reference key="object" ref="391199113"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="374024848"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+						<string key="objectName" id="300007682">1</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">217</int>
+						<reference key="object" ref="952259628"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="789758025"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">83</int>
+						<reference key="object" ref="379814623"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="720053764"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">81</int>
+						<reference key="object" ref="720053764"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1023925487"/>
+							<reference ref="117038363"/>
+							<reference ref="49223823"/>
+							<reference ref="722745758"/>
+							<reference ref="705341025"/>
+							<reference ref="1025936716"/>
+							<reference ref="294629803"/>
+							<reference ref="776162233"/>
+							<reference ref="425164168"/>
+							<reference ref="579971712"/>
+							<reference ref="1010469920"/>
+						</object>
+						<reference key="parent" ref="379814623"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">75</int>
+						<reference key="object" ref="1023925487"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName">3</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">80</int>
+						<reference key="object" ref="117038363"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName">8</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">78</int>
+						<reference key="object" ref="49223823"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName">6</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">72</int>
+						<reference key="object" ref="722745758"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">82</int>
+						<reference key="object" ref="705341025"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName">9</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">124</int>
+						<reference key="object" ref="1025936716"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1065607017"/>
+						</object>
+						<reference key="parent" ref="720053764"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">77</int>
+						<reference key="object" ref="294629803"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName">5</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">73</int>
+						<reference key="object" ref="776162233"/>
+						<reference key="parent" ref="720053764"/>
+						<reference key="objectName" ref="300007682"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">79</int>
+						<reference key="object" ref="425164168"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName">7</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">112</int>
+						<reference key="object" ref="579971712"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName">10</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">74</int>
+						<reference key="object" ref="1010469920"/>
+						<reference key="parent" ref="720053764"/>
+						<string key="objectName" id="794385857">2</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">125</int>
+						<reference key="object" ref="1065607017"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="759406840"/>
+						</object>
+						<reference key="parent" ref="1025936716"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">126</int>
+						<reference key="object" ref="759406840"/>
+						<reference key="parent" ref="1065607017"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">205</int>
+						<reference key="object" ref="789758025"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="437104165"/>
+							<reference ref="583158037"/>
+							<reference ref="1058277027"/>
+							<reference ref="212016141"/>
+							<reference ref="296257095"/>
+							<reference ref="29853731"/>
+							<reference ref="860595796"/>
+							<reference ref="1040322652"/>
+							<reference ref="790794224"/>
+							<reference ref="892235320"/>
+							<reference ref="972420730"/>
+							<reference ref="676164635"/>
+							<reference ref="507821607"/>
+						</object>
+						<reference key="parent" ref="952259628"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">202</int>
+						<reference key="object" ref="437104165"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">198</int>
+						<reference key="object" ref="583158037"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">207</int>
+						<reference key="object" ref="1058277027"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">214</int>
+						<reference key="object" ref="212016141"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">199</int>
+						<reference key="object" ref="296257095"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">203</int>
+						<reference key="object" ref="29853731"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">197</int>
+						<reference key="object" ref="860595796"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">206</int>
+						<reference key="object" ref="1040322652"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">215</int>
+						<reference key="object" ref="790794224"/>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">218</int>
+						<reference key="object" ref="892235320"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="963351320"/>
+						</object>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">216</int>
+						<reference key="object" ref="972420730"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="769623530"/>
+						</object>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">200</int>
+						<reference key="object" ref="769623530"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="948374510"/>
+							<reference ref="96193923"/>
+							<reference ref="679648819"/>
+							<reference ref="967646866"/>
+						</object>
+						<reference key="parent" ref="972420730"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">219</int>
+						<reference key="object" ref="948374510"/>
+						<reference key="parent" ref="769623530"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">201</int>
+						<reference key="object" ref="96193923"/>
+						<reference key="parent" ref="769623530"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">204</int>
+						<reference key="object" ref="679648819"/>
+						<reference key="parent" ref="769623530"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">220</int>
+						<reference key="object" ref="963351320"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="270902937"/>
+							<reference ref="88285865"/>
+							<reference ref="159080638"/>
+							<reference ref="326711663"/>
+							<reference ref="447796847"/>
+						</object>
+						<reference key="parent" ref="892235320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">213</int>
+						<reference key="object" ref="270902937"/>
+						<reference key="parent" ref="963351320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">210</int>
+						<reference key="object" ref="88285865"/>
+						<reference key="parent" ref="963351320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">221</int>
+						<reference key="object" ref="159080638"/>
+						<reference key="parent" ref="963351320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">208</int>
+						<reference key="object" ref="326711663"/>
+						<reference key="parent" ref="963351320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">209</int>
+						<reference key="object" ref="447796847"/>
+						<reference key="parent" ref="963351320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">106</int>
+						<reference key="object" ref="374024848"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="238773614"/>
+						</object>
+						<reference key="parent" ref="391199113"/>
+						<reference key="objectName" ref="794385857"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">111</int>
+						<reference key="object" ref="238773614"/>
+						<reference key="parent" ref="374024848"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">57</int>
+						<reference key="object" ref="110575045"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="238522557"/>
+							<reference ref="755159360"/>
+							<reference ref="908899353"/>
+							<reference ref="632727374"/>
+							<reference ref="646227648"/>
+							<reference ref="609285721"/>
+							<reference ref="481834944"/>
+							<reference ref="304266470"/>
+							<reference ref="1046388886"/>
+							<reference ref="1056857174"/>
+							<reference ref="342932134"/>
+						</object>
+						<reference key="parent" ref="694149608"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">58</int>
+						<reference key="object" ref="238522557"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">134</int>
+						<reference key="object" ref="755159360"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">150</int>
+						<reference key="object" ref="908899353"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">136</int>
+						<reference key="object" ref="632727374"/>
+						<reference key="parent" ref="110575045"/>
+						<string key="objectName">1111</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">144</int>
+						<reference key="object" ref="646227648"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">129</int>
+						<reference key="object" ref="609285721"/>
+						<reference key="parent" ref="110575045"/>
+						<string key="objectName">121</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">143</int>
+						<reference key="object" ref="481834944"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">236</int>
+						<reference key="object" ref="304266470"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">131</int>
+						<reference key="object" ref="1046388886"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="752062318"/>
+						</object>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">149</int>
+						<reference key="object" ref="1056857174"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">145</int>
+						<reference key="object" ref="342932134"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">130</int>
+						<reference key="object" ref="752062318"/>
+						<reference key="parent" ref="1046388886"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="835318025"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="299356726"/>
+							<reference ref="625202149"/>
+							<reference ref="575023229"/>
+							<reference ref="1011231497"/>
+						</object>
+						<reference key="parent" ref="713487014"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">92</int>
+						<reference key="object" ref="299356726"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="625202149"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">239</int>
+						<reference key="object" ref="575023229"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="1011231497"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">295</int>
+						<reference key="object" ref="586577488"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="466310130"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">296</int>
+						<reference key="object" ref="466310130"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="102151532"/>
+							<reference ref="237841660"/>
+						</object>
+						<reference key="parent" ref="586577488"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">297</int>
+						<reference key="object" ref="102151532"/>
+						<reference key="parent" ref="466310130"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">298</int>
+						<reference key="object" ref="237841660"/>
+						<reference key="parent" ref="466310130"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">299</int>
+						<reference key="object" ref="626404410"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="502084290"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">300</int>
+						<reference key="object" ref="502084290"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="519768076"/>
+							<reference ref="1028416764"/>
+						</object>
+						<reference key="parent" ref="626404410"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">344</int>
+						<reference key="object" ref="519768076"/>
+						<reference key="parent" ref="502084290"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">345</int>
+						<reference key="object" ref="1028416764"/>
+						<reference key="parent" ref="502084290"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">211</int>
+						<reference key="object" ref="676164635"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="785027613"/>
+						</object>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">212</int>
+						<reference key="object" ref="785027613"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="680220178"/>
+							<reference ref="731782645"/>
+						</object>
+						<reference key="parent" ref="676164635"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">195</int>
+						<reference key="object" ref="680220178"/>
+						<reference key="parent" ref="785027613"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">196</int>
+						<reference key="object" ref="731782645"/>
+						<reference key="parent" ref="785027613"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">346</int>
+						<reference key="object" ref="967646866"/>
+						<reference key="parent" ref="769623530"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">348</int>
+						<reference key="object" ref="507821607"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="698887838"/>
+						</object>
+						<reference key="parent" ref="789758025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">349</int>
+						<reference key="object" ref="698887838"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="605118523"/>
+							<reference ref="197661976"/>
+							<reference ref="708854459"/>
+						</object>
+						<reference key="parent" ref="507821607"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">350</int>
+						<reference key="object" ref="605118523"/>
+						<reference key="parent" ref="698887838"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">351</int>
+						<reference key="object" ref="197661976"/>
+						<reference key="parent" ref="698887838"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">354</int>
+						<reference key="object" ref="708854459"/>
+						<reference key="parent" ref="698887838"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">367</int>
+						<reference key="object" ref="513744381"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="414427165"/>
+						</object>
+						<reference key="parent" ref="1049"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">368</int>
+						<reference key="object" ref="414427165"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="933737783"/>
+							<reference ref="775915874"/>
+							<reference ref="247106261"/>
+							<reference ref="12526602"/>
+							<reference ref="433602985"/>
+							<reference ref="263151680"/>
+							<reference ref="667602245"/>
+							<reference ref="136421666"/>
+						</object>
+						<reference key="parent" ref="513744381"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">373</int>
+						<reference key="object" ref="933737783"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="784994109"/>
+						</object>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">374</int>
+						<reference key="object" ref="784994109"/>
+						<reference key="parent" ref="933737783"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">375</int>
+						<reference key="object" ref="775915874"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="899290995"/>
+						</object>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">376</int>
+						<reference key="object" ref="899290995"/>
+						<reference key="parent" ref="775915874"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">377</int>
+						<reference key="object" ref="247106261"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="31819280"/>
+						</object>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">378</int>
+						<reference key="object" ref="31819280"/>
+						<reference key="parent" ref="247106261"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">379</int>
+						<reference key="object" ref="12526602"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="385927916"/>
+						</object>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">380</int>
+						<reference key="object" ref="385927916"/>
+						<reference key="parent" ref="12526602"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">381</int>
+						<reference key="object" ref="433602985"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="917041781"/>
+						</object>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">382</int>
+						<reference key="object" ref="917041781"/>
+						<reference key="parent" ref="433602985"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">383</int>
+						<reference key="object" ref="263151680"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="710696568"/>
+						</object>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">384</int>
+						<reference key="object" ref="710696568"/>
+						<reference key="parent" ref="263151680"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">385</int>
+						<reference key="object" ref="667602245"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="613837648"/>
+						</object>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">386</int>
+						<reference key="object" ref="613837648"/>
+						<reference key="parent" ref="667602245"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">389</int>
+						<reference key="object" ref="136421666"/>
+						<reference key="parent" ref="414427165"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">394</int>
+						<reference key="object" ref="1001780962"/>
+						<reference key="parent" ref="1049"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">395</int>
+						<reference key="object" ref="627880282"/>
+						<reference key="parent" ref="1049"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>103.IBPluginDependency</string>
+					<string>103.ImportedFromIB2</string>
+					<string>106.IBPluginDependency</string>
+					<string>106.ImportedFromIB2</string>
+					<string>106.editorWindowContentRectSynchronizationRect</string>
+					<string>111.IBPluginDependency</string>
+					<string>111.ImportedFromIB2</string>
+					<string>112.IBPluginDependency</string>
+					<string>112.ImportedFromIB2</string>
+					<string>124.IBPluginDependency</string>
+					<string>124.ImportedFromIB2</string>
+					<string>125.IBPluginDependency</string>
+					<string>125.ImportedFromIB2</string>
+					<string>125.editorWindowContentRectSynchronizationRect</string>
+					<string>126.IBPluginDependency</string>
+					<string>126.ImportedFromIB2</string>
+					<string>129.IBPluginDependency</string>
+					<string>129.ImportedFromIB2</string>
+					<string>130.IBPluginDependency</string>
+					<string>130.ImportedFromIB2</string>
+					<string>130.editorWindowContentRectSynchronizationRect</string>
+					<string>131.IBPluginDependency</string>
+					<string>131.ImportedFromIB2</string>
+					<string>134.IBPluginDependency</string>
+					<string>134.ImportedFromIB2</string>
+					<string>136.IBPluginDependency</string>
+					<string>136.ImportedFromIB2</string>
+					<string>143.IBPluginDependency</string>
+					<string>143.ImportedFromIB2</string>
+					<string>144.IBPluginDependency</string>
+					<string>144.ImportedFromIB2</string>
+					<string>145.IBPluginDependency</string>
+					<string>145.ImportedFromIB2</string>
+					<string>149.IBPluginDependency</string>
+					<string>149.ImportedFromIB2</string>
+					<string>150.IBPluginDependency</string>
+					<string>150.ImportedFromIB2</string>
+					<string>19.IBPluginDependency</string>
+					<string>19.ImportedFromIB2</string>
+					<string>195.IBPluginDependency</string>
+					<string>195.ImportedFromIB2</string>
+					<string>196.IBPluginDependency</string>
+					<string>196.ImportedFromIB2</string>
+					<string>197.IBPluginDependency</string>
+					<string>197.ImportedFromIB2</string>
+					<string>198.IBPluginDependency</string>
+					<string>198.ImportedFromIB2</string>
+					<string>199.IBPluginDependency</string>
+					<string>199.ImportedFromIB2</string>
+					<string>200.IBPluginDependency</string>
+					<string>200.ImportedFromIB2</string>
+					<string>200.editorWindowContentRectSynchronizationRect</string>
+					<string>201.IBPluginDependency</string>
+					<string>201.ImportedFromIB2</string>
+					<string>202.IBPluginDependency</string>
+					<string>202.ImportedFromIB2</string>
+					<string>203.IBPluginDependency</string>
+					<string>203.ImportedFromIB2</string>
+					<string>204.IBPluginDependency</string>
+					<string>204.ImportedFromIB2</string>
+					<string>205.IBPluginDependency</string>
+					<string>205.ImportedFromIB2</string>
+					<string>205.editorWindowContentRectSynchronizationRect</string>
+					<string>206.IBPluginDependency</string>
+					<string>206.ImportedFromIB2</string>
+					<string>207.IBPluginDependency</string>
+					<string>207.ImportedFromIB2</string>
+					<string>208.IBPluginDependency</string>
+					<string>208.ImportedFromIB2</string>
+					<string>209.IBPluginDependency</string>
+					<string>209.ImportedFromIB2</string>
+					<string>210.IBPluginDependency</string>
+					<string>210.ImportedFromIB2</string>
+					<string>211.IBPluginDependency</string>
+					<string>211.ImportedFromIB2</string>
+					<string>212.IBPluginDependency</string>
+					<string>212.ImportedFromIB2</string>
+					<string>212.editorWindowContentRectSynchronizationRect</string>
+					<string>213.IBPluginDependency</string>
+					<string>213.ImportedFromIB2</string>
+					<string>214.IBPluginDependency</string>
+					<string>214.ImportedFromIB2</string>
+					<string>215.IBPluginDependency</string>
+					<string>215.ImportedFromIB2</string>
+					<string>216.IBPluginDependency</string>
+					<string>216.ImportedFromIB2</string>
+					<string>217.IBPluginDependency</string>
+					<string>217.ImportedFromIB2</string>
+					<string>218.IBPluginDependency</string>
+					<string>218.ImportedFromIB2</string>
+					<string>219.IBPluginDependency</string>
+					<string>219.ImportedFromIB2</string>
+					<string>220.IBPluginDependency</string>
+					<string>220.ImportedFromIB2</string>
+					<string>220.editorWindowContentRectSynchronizationRect</string>
+					<string>221.IBPluginDependency</string>
+					<string>221.ImportedFromIB2</string>
+					<string>23.IBPluginDependency</string>
+					<string>23.ImportedFromIB2</string>
+					<string>236.IBPluginDependency</string>
+					<string>236.ImportedFromIB2</string>
+					<string>239.IBPluginDependency</string>
+					<string>239.ImportedFromIB2</string>
+					<string>24.IBPluginDependency</string>
+					<string>24.ImportedFromIB2</string>
+					<string>24.editorWindowContentRectSynchronizationRect</string>
+					<string>29.IBPluginDependency</string>
+					<string>29.ImportedFromIB2</string>
+					<string>29.WindowOrigin</string>
+					<string>29.editorWindowContentRectSynchronizationRect</string>
+					<string>295.IBPluginDependency</string>
+					<string>296.IBPluginDependency</string>
+					<string>296.editorWindowContentRectSynchronizationRect</string>
+					<string>297.IBPluginDependency</string>
+					<string>298.IBPluginDependency</string>
+					<string>299.IBPluginDependency</string>
+					<string>300.IBPluginDependency</string>
+					<string>300.editorWindowContentRectSynchronizationRect</string>
+					<string>344.IBPluginDependency</string>
+					<string>345.IBPluginDependency</string>
+					<string>346.IBPluginDependency</string>
+					<string>346.ImportedFromIB2</string>
+					<string>348.IBPluginDependency</string>
+					<string>348.ImportedFromIB2</string>
+					<string>349.IBPluginDependency</string>
+					<string>349.ImportedFromIB2</string>
+					<string>349.editorWindowContentRectSynchronizationRect</string>
+					<string>350.IBPluginDependency</string>
+					<string>350.ImportedFromIB2</string>
+					<string>351.IBPluginDependency</string>
+					<string>351.ImportedFromIB2</string>
+					<string>354.IBPluginDependency</string>
+					<string>354.ImportedFromIB2</string>
+					<string>367.IBPluginDependency</string>
+					<string>367.IBWindowTemplateEditedContentRect</string>
+					<string>367.NSWindowTemplate.visibleAtLaunch</string>
+					<string>367.editorWindowContentRectSynchronizationRect</string>
+					<string>368.IBPluginDependency</string>
+					<string>373.IBPluginDependency</string>
+					<string>374.IBPluginDependency</string>
+					<string>375.IBPluginDependency</string>
+					<string>376.IBPluginDependency</string>
+					<string>377.IBPluginDependency</string>
+					<string>378.IBPluginDependency</string>
+					<string>379.IBPluginDependency</string>
+					<string>380.IBPluginDependency</string>
+					<string>381.IBPluginDependency</string>
+					<string>382.IBPluginDependency</string>
+					<string>383.IBPluginDependency</string>
+					<string>384.IBPluginDependency</string>
+					<string>385.IBPluginDependency</string>
+					<string>386.IBPluginDependency</string>
+					<string>389.IBPluginDependency</string>
+					<string>394.IBPluginDependency</string>
+					<string>395.IBPluginDependency</string>
+					<string>5.IBPluginDependency</string>
+					<string>5.ImportedFromIB2</string>
+					<string>56.IBPluginDependency</string>
+					<string>56.ImportedFromIB2</string>
+					<string>57.IBPluginDependency</string>
+					<string>57.ImportedFromIB2</string>
+					<string>57.editorWindowContentRectSynchronizationRect</string>
+					<string>58.IBPluginDependency</string>
+					<string>58.ImportedFromIB2</string>
+					<string>72.IBPluginDependency</string>
+					<string>72.ImportedFromIB2</string>
+					<string>73.IBPluginDependency</string>
+					<string>73.ImportedFromIB2</string>
+					<string>74.IBPluginDependency</string>
+					<string>74.ImportedFromIB2</string>
+					<string>75.IBPluginDependency</string>
+					<string>75.ImportedFromIB2</string>
+					<string>77.IBPluginDependency</string>
+					<string>77.ImportedFromIB2</string>
+					<string>78.IBPluginDependency</string>
+					<string>78.ImportedFromIB2</string>
+					<string>79.IBPluginDependency</string>
+					<string>79.ImportedFromIB2</string>
+					<string>80.IBPluginDependency</string>
+					<string>80.ImportedFromIB2</string>
+					<string>81.IBPluginDependency</string>
+					<string>81.ImportedFromIB2</string>
+					<string>81.editorWindowContentRectSynchronizationRect</string>
+					<string>82.IBPluginDependency</string>
+					<string>82.ImportedFromIB2</string>
+					<string>83.IBPluginDependency</string>
+					<string>83.ImportedFromIB2</string>
+					<string>92.IBPluginDependency</string>
+					<string>92.ImportedFromIB2</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<integer value="1" id="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{532, 981}, {242, 23}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{522, 812}, {146, 23}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{436, 809}, {64, 6}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{608, 612}, {275, 83}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{301, 761}, {243, 243}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{608, 612}, {167, 43}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{608, 612}, {241, 103}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{461, 931}, {197, 73}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{74, 862}</string>
+					<string>{{88, 1004}, {505, 20}}</string>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<string>{{411, 961}, {234, 43}}</string>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<string>{{345, 961}, {176, 43}}</string>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{440, 714}, {177, 63}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<string id="119914469">{{87, 713}, {350, 189}}</string>
+					<reference ref="9"/>
+					<reference ref="119914469"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{100, 821}, {271, 183}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<string>{{259, 801}, {199, 203}}</string>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+					<reference ref="418681816"/>
+					<reference ref="9"/>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">400</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<reference key="className" ref="416391972"/>
+					<nil key="superclassName"/>
+					<object class="NSMutableDictionary" key="actions">
+						<reference key="NS.key.0" ref="408592174"/>
+						<string key="NS.object.0" id="718040419">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="829906625"/>
+							<reference ref="943815538"/>
+							<reference ref="90614103"/>
+							<reference ref="1041581452"/>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="718040419"/>
+							<reference ref="718040419"/>
+							<reference ref="718040419"/>
+							<reference ref="718040419"/>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey" id="330926809">IBUserSource</string>
+						<reference key="minorKey" ref="829414822"/>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<reference key="className" ref="171510208"/>
+					<nil key="superclassName"/>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">myAction1:</string>
+						<reference key="NS.object.0" ref="718040419"/>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<reference key="majorKey" ref="330926809"/>
+						<reference key="minorKey" ref="829414822"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableData" key="IBDocument.RunnableNib">
+			<bytes key="NS.bytes">YnBsaXN0MDDUAAEAAgADAAQABQAGAAkAClgkdmVyc2lvblQkdG9wWSRhcmNoaXZlclgkb2JqZWN0cxIA
+AYag0QAHAAhdSUIub2JqZWN0ZGF0YYABXxAPTlNLZXllZEFyY2hpdmVyrxECfAALAAwAMQA1ADYAPAA9
+AEIAVgBXAFgAWQALAGYAcQB9AH4AkACRAJkAmgCdAKcAqACpAK4AsAC1ALYAuQC9AMMAywDMANQA3ADd
+AOYA7gDvAPgA+QD+AP8BAgEHAQgBEAERARgBGQEhASIBKQEqATIBMwFGAUcBSAFLAU4BXwFgAWEBZwFo
+AWsBbgFyAAsBcwF1AXYBeQF9Aa0BswHDAcgByQHKAc8B0AHRAdQB2AHZAdwB3QHhAecB6gHrAewB7wHz
+AfsB/wIAAgECAgIGAg0CEQISAhMCFwIeAh8CIAIkAi0CLgIvAjACNAI7AjwCPQJCAkMCRwJOAlMCVAJV
+AlYCWgJhAmUCZgJnAmgCbAJzAngCeQJ6AnsCfwKGAooCiwKMAo0CkQKaAp4CnwKgAqQCqwKsAq0CrgKy
+ArkCugK7ArwCwALHAsgCyQLKAs4C1QLWAtcC2wLjAuQC5QLmAuoC8QL1AvYC9wL4AvwDAwMEAwUDCQMQ
+AxUDFgMXAxsDIgMjAyQDJQMpAzADMQMyAzYDPQM+Az8DQANEA0sDTANNA1IDUwNXA14DYgNjA2QDZQNp
+A3ADcQNyA3MDdwN+A38DgAOFA4gDiQOKA44DlQOWA5cDmwOiA6MDpAOlA6kDsAOxA7IDtwO4A7wDwwPE
+A8UDyQPQA9ED0gPTA9cD3gPfA+AD4QPlA+wD7QPuA/MD+gP7A/wEAQQCBAYEDQQOBA8EFAQVBBkEIAQh
+BCIEIwQoBCwEMwQ3BDgEOQQ6BKEErAS1BLYEvQTGBMcEyQTUBNUE1gTbBOQE6QTVBOoE+gUDBQwFFQTV
+BRYFHgUlBSYFJwUuBS8FMAU3BTgFOQVCBNUFQwVKBVME1QVUBVoFXwVgBWMFZAVtBXQFdQV+BNUFfwWD
+BYoFiwWMBZMFlAWVBNUFngWsBbUE1QW+BccFyAXPBdAF0QXSBeAF6QTVBeoF7gXvBfgE1QYBBgIGBwYQ
+BNUGEQYWBNUGHwTVBigGKQYzBjQGNwY5BqAHCAdwB3EHcgdzB3QHdQd2B3cHeAd5B3oHewd8B30Hfgd/
+B4AHgQeCB4MHhAeFB4YHhweIB4kHigeLB4wHjQeOB48HkAeRB5IHkweUB5UHlgeXB5gHmQeaB5sHnAed
+B54HnwegB6EHogejB6QHpQemB6cHqAepB6oHqwesB60HrgevB7AHsQeyB7MHtAe1B7YHtwe4B7kHuge7
+B7wHvQe+B78HwAfBB8IHwwfEB8UHxgfHB8gHyQfKB8sHzAfNB84DiAfPB9AH0QfSB9MH1AfXB9oIbwkE
+CQUJBgkHCQgJCQkKCQsJDAkNCQ4JDwkQCREJEgkTCRQJFQkWCRcJGAkZCRoJGwkcCR0JHgkfCSAJIQki
+CSMJJAklCSYJJwkoCSkJKgkrCSwJLQkuCS8JMAkxCTIJMwk0CTUJNgE+CTcJOAk5CToJOwk8CT0JPgk/
+CUAJQQlCCUMJRAlFCUYJRwlICUkJSglLCUwJTQlOCU8JUAlRAUMJUglTCVQJVQlWCVcJWAlZCVoJWwlc
+CV0JXglfCWAJYQliCWMJZAllCWYJZwloCWkJaglrCWwJbQluCW8JcAlxCXIJcwl0CXUJdgl3CXgJeQl6
+CXsJfAl9CX4JfwmACYEJggmDCYQJhQmGCYcJiAmJCYoJiwmMCY0JjgmPCZAJkQmSCZMJlAmXCZoJnVUk
+bnVsbN8QEgANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYA
+JwAoACkAKgArACwALQAuAC8AMFZOU1Jvb3RWJGNsYXNzXU5TT2JqZWN0c0tleXNfEA9OU0NsYXNzZXNW
+YWx1ZXNfEBlOU0FjY2Vzc2liaWxpdHlPaWRzVmFsdWVzXU5TQ29ubmVjdGlvbnNbTlNOYW1lc0tleXNb
+TlNGcmFtZXdvcmtdTlNDbGFzc2VzS2V5c1pOU09pZHNLZXlzXU5TTmFtZXNWYWx1ZXNfEBlOU0FjY2Vz
+c2liaWxpdHlDb25uZWN0b3JzXU5TRm9udE1hbmFnZXJfEBBOU1Zpc2libGVXaW5kb3dzXxAPTlNPYmpl
+Y3RzVmFsdWVzXxAXTlNBY2Nlc3NpYmlsaXR5T2lkc0tleXNZTlNOZXh0T2lkXE5TT2lkc1ZhbHVlc4AC
+gQJ7gQEdgQHjgQJ6gEuBAXuABYEB4oEB5IEBfIECeIAAgAaBAXqBAnkRAZKBAeXSAA4AMgAzADRbTlND
+bGFzc05hbWWABIADXU5TQXBwbGljYXRpb27SADcAOAA5ADpYJGNsYXNzZXNaJGNsYXNzbmFtZaIAOgA7
+Xk5TQ3VzdG9tT2JqZWN0WE5TT2JqZWN0XxAQSUJDb2NvYUZyYW1ld29ya9IADgA+AD8AQFpOUy5vYmpl
+Y3RzgEqhAEGAB9oAQwAOAEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVAArXE5TV2luZG93
+Vmlld1xOU1NjcmVlblJlY3RdTlNXaW5kb3dUaXRsZVlOU1dURmxhZ3NdTlNXaW5kb3dDbGFzc1xOU1dp
+bmRvd1JlY3RfEA9OU1dpbmRvd0JhY2tpbmdfEBFOU1dpbmRvd1N0eWxlTWFza1tOU1ZpZXdDbGFzc4AL
+gEmASIAJEiR4AACACoAIEAIQB4AAXxAYe3szMDYsIDc2N30sIHszNTAsIDE4OX19XxASQ3VycmVuY3kg
+Q29udmVydGVyWE5TV2luZG931wBaAA4AWwBcAF0AWABeAF8AYABhAGIAYwBfAGVfEA9OU05leHRSZXNw
+b25kZXJaTlNTdWJ2aWV3c1hOU3ZGbGFnc1tOU0ZyYW1lU2l6ZVtOU1N1cGVydmlld4AMgEeADREBAIBF
+gAyARtIADgA+AGcAaIBEqABpAGoAawBsAG0AbgBvAHCADoAfgCKAJYAugDKANoA92ABaAA4AcgBzAFwA
+dABYAF4ATAB2AHcAeAB5AHoAXwBMV05TRnJhbWVWTlNDZWxsWU5TRW5hYmxlZIALgB6AD4AQEQEMCYAM
+gAtfEBd7ezE5NSwgMTQ3fSwgezEzNSwgMjJ9fdkAfwAOAIAAgQCCAIMAhACFAIYAhwCIAIkAigCLAGkA
+jQB6AI9bTlNDZWxsRmxhZ3NfEBFOU0JhY2tncm91bmRDb2xvclpOU0NvbnRlbnRzWU5TU3VwcG9ydF1O
+U0NvbnRyb2xWaWV3XE5TQ2VsbEZsYWdzMl8QEU5TRHJhd3NCYWNrZ3JvdW5kW05TVGV4dENvbG9yE///
+//+Ucf5BgB2AFYARgBKADhIQQAQACYAaUNQADgCSAJMAlACVAJYAlwCYVk5TU2l6ZVZOU05hbWVYTlNm
+RmxhZ3OAFCNAKgAAAAAAAIATEQQUXEx1Y2lkYUdyYW5kZdIANwA4AJsAnKIAnAA7Vk5TRm9udNUADgCe
+AJ8AoAChAKIAowCkAKUApldOU0NvbG9yXE5TQ29sb3JTcGFjZVtOU0NvbG9yTmFtZV1OU0NhdGFsb2dO
+YW1lgBmAGBAGgBeAFlZTeXN0ZW1fEBN0ZXh0QmFja2dyb3VuZENvbG9y0wAOAJ8AqgCiAKwArVdOU1do
+aXRlgBkQA0IxANIANwA4AK8AnqIAngA71QAOAJ4AnwCgAKEAogCyAKQAswCmgBmAHIAbgBZZdGV4dENv
+bG9y0wAOAJ8AqgCiAKwAuIAZQjAA0gA3ADgAugC7pAC7ALwAcwA7XxAPTlNUZXh0RmllbGRDZWxsXE5T
+QWN0aW9uQ2VsbNIANwA4AL4Av6UAvwDAAMEAwgA7W05TVGV4dEZpZWxkWU5TQ29udHJvbFZOU1ZpZXdb
+TlNSZXNwb25kZXLYAFoADgByAHMAXAB0AFgAXgBMAHYAxgDHAHkAegBfAEyAC4AegCCAIQmADIALXxAX
+e3sxOTUsIDExNX0sIHsxMzUsIDIyfX3ZAH8ADgCAAIEAggCDAIQAhQCGAIcAiACJAIoAiwBqAI0AegCP
+gB2AFYARgBKAHwmAGtgAWgAOAHIAcwBcAHQAWABeAEwAdgDXANgAeQB6AF8ATIALgB6AI4AkCYAMgAtf
+EBZ7ezE5NSwgODN9LCB7MTM1LCAyMn192QB/AA4AgACBAIIAgwCEAIUAhgDeAIgAiQCKAIsAawCNAHoA
+jxP/////hHH+QYAdgBWAEYASgCIJgBrYAFoADgByAHMAXAB0AFgAXgBMAHYA6QDqAHkAegBfAEyAC4Ae
+gCaAJwmADIALXxAWe3s0NywgMTQ5fSwgezE0MywgMTd9fdgAfwAOAIAAgQCCAIMAhACGAPAAiADyAPMA
+iwBsAPYA9xIEAf5AgB2AKYAogBKAJRIEQAQAgCxfEBVFeGNoYW5nZSByYXRlIHBlciAkMTrVAA4AngCf
+AKAAoQCiAPsApAD8AKaAGYArgCqAFlxjb250cm9sQ29sb3LTAA4AnwCqAKIArAEBgBlLMC42NjY2NjY2
+OQDVAA4AngCfAKAAoQCiALIApAEFAKaAGYAcgC2AFl8QEGNvbnRyb2xUZXh0Q29sb3LYAFoADgByAHMA
+XAB0AFgAXgBMAHYBCwEMAHkAegBfAEyAC4AegC+AMAmADIALXxAWe3s2NywgMTE1fSwgezEyMywgMTd9
+fdgAfwAOAIAAgQCCAIMAhACGAPAAiADyARQAiwBtAPYA94AdgCmAMYASgC6ALF8QE0RvbGxhcnMgdG8g
+Q29udmVydDrYAFoADgByAHMAXAB0AFgAXgBMAHYBHAEdAHkAegBfAEyAC4AegDOANAmADIALXxAVe3sx
+NywgODN9LCB7MTczLCAxN3192AB/AA4AgACBAIIAgwCEAIYA8ACIAPIBJQCLAG4A9gD3gB2AKYA1gBKA
+MoAsXxAZQW1vdW50IGluIG90aGVyIEN1cnJlbmN5OtgAWgAOAHIAcwBcAHQAWABeAEwBLAEtAS4AeQB6
+AF8ATIALgDyAN4A4CYAMgAtfEBV7ezIxNCwgMTJ9LCB7OTYsIDMyfX3cAH8ADgE0ATUBNgE3AIEAggCD
+ATgAhAE5AToBOwCKAT0BPgE/AUAAiwBvAUMBRAFFXxATTlNBbHRlcm5hdGVDb250ZW50c18QEk5TUGVy
+aW9kaWNJbnRlcnZhbF5OU0J1dHRvbkZsYWdzMl8QD05TS2V5RXF1aXZhbGVudF8QD05TUGVyaW9kaWNE
+ZWxheV1OU0J1dHRvbkZsYWdzEgQB/gCAO4AREBkQgYA6gDmAEoA2EMgSCAAAABP/////hoJA/1dDb252
+ZXJ0UQ3SADcAOAFJAUqkAUoAvABzADtcTlNCdXR0b25DZWxs0gA3ADgBTAFNpQFNAMAAwQDCADtYTlNC
+dXR0b27cAFoBTwAOAVAAcgFRAFwBUgBYAVMBVABeAEwAUwFWAVcBWAFZAVoArABfAVwBXQBMWU5TQm94
+VHlwZVtOU1RpdGxlQ2VsbF1OU1RyYW5zcGFyZW50XE5TQm9yZGVyVHlwZVlOU09mZnNldHNfEA9OU1Rp
+dGxlUG9zaXRpb26AC4BDgECAPggQDIAMgD8QAIALXxAUe3syMCwgNTh9LCB7MzEwLCA1fX1WezAsIDB9
+1wB/AA4AgACBAIIAhACGAToAiACJAWQAiwFdAWaAHYAVgEGAEoBCU0JveNMADgCfAKoAogCsAWqAGU0w
+IDAuODAwMDAwMDEA0gA3ADgBbAFtpAFtAMEAwgA7VU5TQm940gA3ADgBbwFwowFwAXEAO15OU011dGFi
+bGVBcnJheVdOU0FycmF5WnszNTAsIDE4OX3SADcAOAF0AMGjAMEAwgA7XxAWe3swLCAwfSwgezE5MjAs
+IDExNzh9fdIANwA4AXcBeKIBeAA7XxAQTlNXaW5kb3dUZW1wbGF0ZdIANwA4AXoBe6MBewF8ADtcTlNN
+dXRhYmxlU2V0VU5TU2V00gAOAD4AZwF/gESvEC0BgAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4B
+jwGQAZEBkgGTAZQBlQGWAZcBmAGZAZoBmwGcAZ0BngGfAaABoQGiAaMBpAGlAaYBpwGoAakBqgGrAayA
+TIBagF+AZYBqgG6Ac4B3gHmAf4CFgIuAkYCWgJuAoIClgKmAroC0gLiAvYDCgMaAy4DPgNGA14DcgOCA
+5IDogO2A8YDzgPeA/IEBAYEBBYEBCYEBC4EBD4EBEYEBFoEBF9MADgGuAa8BsAGxAbJYTlNTb3VyY2VX
+TlNMYWJlbIBZgE2AWNgADgG0AbUBtgG3AbgBuQG6AbsBvAG9Ab4BvwHAAcEBwldOU1RpdGxlXxARTlNL
+ZXlFcXVpdk1vZE1hc2taTlNLZXlFcXVpdl1OU01uZW1vbmljTG9jWU5TT25JbWFnZVxOU01peGVkSW1h
+Z2VWTlNNZW51gFeATxIAEgAAgFASf////4BRgFWATtMADgG0AcQBxQHGAcdbTlNNZW51SXRlbXOBASSB
+AWGBAWJoAFMAYQB2AGUAIABBAHMgJlFT0wAOADIBywHMAc0Bzl5OU1Jlc291cmNlTmFtZYBUgFKAU1dO
+U0ltYWdlXxAPTlNNZW51Q2hlY2ttYXJr0gA3ADgB0gHTogHTADtfEBBOU0N1c3RvbVJlc291cmNl0wAO
+ADIBywHMAc0B14BUgFKAVl8QEE5TTWVudU1peGVkU3RhdGXSADcAOAHaAduiAdsAO1pOU01lbnVJdGVt
+XxAPc2F2ZURvY3VtZW50QXM60gA3ADgB3gHfowHfAeAAO18QFU5TTmliQ29udHJvbENvbm5lY3Rvcl5O
+U05pYkNvbm5lY3RvctQADgHiAa4BrwHjAGkB5QHmXU5TRGVzdGluYXRpb26AXoAOgFuAXdIADgAyADMB
+6YAEgFxfEBNDb252ZXJ0ZXJDb250cm9sbGVyWXJhdGVGaWVsZNIANwA4Ae0B7qMB7gHgADtfEBROU05p
+Yk91dGxldENvbm5lY3RvctMADgGuAa8BsAHxAfKAWYBggGTYAA4BtAG1AbYBtwG4AbkBugG7AfUB9gH3
+Ab8BwAHBAfqAV4BiEgAQAACAY4BRgFWAYdMADgG0AcQBxQH9Af6BASSBAT6BAUBeQ2hlY2sgU3BlbGxp
+bmdRO15jaGVja1NwZWxsaW5nOtMADgGuAa8BsAIEAgWAWYBmgGnYAA4BtAG1AbYBtwG4AbkBugG7AggB
+9gCKAb8BwAHBAgyAV4BogBGAUYBVgGfTAA4BtAHEAcUCDwIQgQEkgQEmgQEoXVN0b3AgU3BlYWtpbmdd
+c3RvcFNwZWFraW5nOtMADgGuAa8BsAIVAhaAWYBrgG3YAA4BtAG1AbYBtwG4AbkBugG7AhkB9gCKAb8B
+wAHBAgyAV4BsgBGAUYBVgGdeU3RhcnQgU3BlYWtpbmdec3RhcnRTcGVha2luZzrTAA4BrgGvAbACIgIj
+gFmAb4By2QAOAiUBtAG1AbYBtwG4AbkBugG7AIoCKAG9AikBvwHAAcEBwllOU1Rvb2xUaXCAV4ARgHCA
+cYBRgFWATl1QYWdlIFNldHVwLi4uUVBecnVuUGFnZUxheW91dDrTAA4BrgGvAbACMgIzgFmAdIB22AAO
+AbQBtQG2AbcBuAG5AboBuwI2AfYAigG/AcABwQH6gFeAdYARgFGAVYBhXxAbQ2hlY2sgR3JhbW1hciBX
+aXRoIFNwZWxsaW5nXxAWdG9nZ2xlR3JhbW1hckNoZWNraW5nOtQADgHiAa4BrwHjAGoAaQJBgF6AH4AO
+gHhbbmV4dEtleVZpZXfTAA4BrgGvAbACRQJGgFmAeoB+2AAOAbQBtQG2AbcBuAG5AboBuwJJAfYCSgG/
+AcABwQJNgFeAfIB9gFGAVYB71AAOAbQAkwHEAcUCUAJRAlKBASSBASCBASOBASFYTWluaW1pemVRbV8Q
+E3BlcmZvcm1NaW5pYXR1cml6ZTrTAA4BrgGvAbACWAJZgFmAgICE2AAOAbQBtQG2AbcBuAG5AboBuwJc
+AfYCXQG/AcABwQJggFeAgoCDgFGAVYCB0wAOAbQBxAHFAmMCZIEBJIEBK4EBLVVQYXN0ZVF2VnBhc3Rl
+OtMADgGuAa8BsAJqAmuAWYCGgIrYAA4BtAG1AbYBtwG4AbkBugG7Am4B9gJvAb8BwAHBAnKAV4CIgImA
+UYBVgIfUAA4BtACTAcQBxQBPAnYCd4EBJIAJgQFdgQFYXxAXUXVpdCBDdXJyZW5jeSBDb252ZXJ0ZXJR
+cVp0ZXJtaW5hdGU60wAOAa4BrwGwAn0CfoBZgIyAkNgADgG0AbUBtgG3AbgBuQG6AbsCgQG9AoIBvwHA
+AcEChYBXgI6Aj4BRgFWAjdMADgG0AcQBxQKIAomBASSBAWuBAWxbU2hvdyBDb2xvcnNRQ18QFW9yZGVy
+RnJvbnRDb2xvclBhbmVsOtMADgGuAa8BsAKPApCAWYCSgJXYAA4BtAG2AbcBuAG5AboCkgG7ApQAigG/
+AcABwQKYAplVTlNUYWeAV4CUgBGAUYBVgJMQAdMADgG0AcQBxQKcAp2BASSBAUKBAURfEBBTbWFydCBD
+b3B5L1Bhc3RlXxAYdG9nZ2xlU21hcnRJbnNlcnREZWxldGU60wAOAa4BrwGwAqICo4BZgJeAmtgADgG0
+AbUBtgG3AbgBuQG6AbsCpgH2AqcBvwHAAcECYIBXgJiAmYBRgFWAgVNDdXRReFRjdXQ60wAOAa4BrwGw
+ArACsYBZgJyAn9gADgG0AbUBtgG3AbgBuQG6AbsCtAH2ArUBvwHAAcEBwoBXgJ2AnoBRgFWATmYAUABy
+AGkAbgB0ICZRcFZwcmludDrTAA4BrgGvAbACvgK/gFmAoYCk2AAOAbQBtQG2AbcBuAG5AboBuwLCAfYC
+wwG/AcABwQHCgFeAooCjgFGAVYBOVFNhdmVRc11zYXZlRG9jdW1lbnQ60wAOAa4BrwGwAswCzYBZgKaA
+qNgADgG0AbUBtgG3AbgBuQG6AbsC0AH2AIoBvwHAAcEB+oBXgKeAEYBRgFWAYV8QG0NoZWNrIFNwZWxs
+aW5nIFdoaWxlIFR5cGluZ18QHnRvZ2dsZUNvbnRpbnVvdXNTcGVsbENoZWNraW5nOtMADgGuAa8BsALZ
+AtqAWYCqgK3YAA4BtAG1AbYBtwG4AbkBugG7At0C3gLfAb8BwAHBAnKAV4CrEgAYAACArIBRgFWAh1tI
+aWRlIE90aGVyc1FoXxAWaGlkZU90aGVyQXBwbGljYXRpb25zOtMADgGuAa8BsALoAumAWYCvgLPZAA4B
+tAG1AbYBtwG4AbkBugKSAbsC7AH2Au0BvwHAAcEC8AKZgFeAsYCygFGAVYCw0wAOAbQBxAHFAvMC9IEB
+JIEBMYEBM2UARgBpAG4AZCAmUWZfEBdwZXJmb3JtRmluZFBhbmVsQWN0aW9uOtMADgGuAa8BsAL6AvuA
+WYC1gLfXAA4BtAG2AbcBuAG5AboBuwL+AIoBvwHAAcEBwoBXgLaAEYBRgFWATl8QD1JldmVydCB0byBT
+YXZlZF8QFnJldmVydERvY3VtZW50VG9TYXZlZDrTAA4BrgGvAbADBwMIgFmAuYC82AAOAbQBtQG2AbcB
+uAG5AboBuwMLAfYAigG/AcABwQMPgFeAu4ARgFGAVYC61AAOAbQAkwHEAcUDEgMTAxSBASSBAWSBAWeB
+AWZaQ2xlYXIgTWVudV8QFWNsZWFyUmVjZW50RG9jdW1lbnRzOtMADgGuAa8BsAMZAxqAWYC+gMHYAA4B
+tAG1AbYBtwG4AbkBugG7Ax0B9gMeAb8BwAHBAfqAV4C/gMCAUYBVgGFuAFMAaABvAHcAIABTAHAAZQBs
+AGwAaQBuAGcgJlE6XxAPc2hvd0d1ZXNzUGFuZWw60wAOAa4BrwGwAycDKIBZgMOAxdgADgG0AbYBtwG4
+AbkBugKSAbsDKwCKAb8BwAHBApgArIBXgMSAEYBRgFWAk1tTbWFydCBMaW5rc18QHXRvZ2dsZUF1dG9t
+YXRpY0xpbmtEZXRlY3Rpb2460wAOAa4BrwGwAzQDNYBZgMeAytgADgG0AbUBtgG3AbgBuQG6AbsDOAH2
+AzkBvwHAAcECYIBXgMiAyYBRgFWAgVpTZWxlY3QgQWxsUWFac2VsZWN0QWxsOtMADgGuAa8BsANCA0OA
+WYDMgM7YAA4BtAG1AbYBtwG4AbkBugG7A0YB9gLfAb8BwAHBAnKAV4DNgKyAUYBVgIdfEBdIaWRlIEN1
+cnJlbmN5IENvbnZlcnRlclVoaWRlOtQADgHiAa4BrwHjAGsB5QNRgF6AIoBbgNBbYW1vdW50RmllbGTT
+AA4BrgGvAbADVQNWgFmA0oDW2AAOAbQBtQG2AbcBuAG5AboBuwNZAt4DWgG/AcABwQNdgFeA1IDVgFGA
+VYDT0wAOAbQBxAHFA2ADYYEBJIEBboEBcFxTaG93IFRvb2xiYXJRdF8QE3RvZ2dsZVRvb2xiYXJTaG93
+bjrTAA4BrgGvAbADZwNogFmA2IDb2AAOAbQBtQG2AbcBuAG5AboBuwNrAfYDbAG/AcABwQJggFeA2YDa
+gFGAVYCBVFVuZG9RelV1bmRvOtMADgGuAa8BsAN1A3aAWYDdgN/YAA4BtAG1AbYBtwG4AbkBugG7A3kB
+9gCKAb8BwAHBAmCAV4DegBGAUYBVgIFWRGVsZXRlV2RlbGV0ZTrUAA4B4gGuAa8B4wOCAeUDhIBegOGA
+W4Dj0gAOADIAMwOHgASA4llDb252ZXJ0ZXJZY29udmVydGVy0wAOAa4BrwGwA4wDjYBZgOWA59gADgG0
+AbUBtgG3AbgBuQG6AbsDkAH2AIoBvwHAAcECcoBXgOaAEYBRgFWAh1hTaG93IEFsbF8QFnVuaGlkZUFs
+bEFwcGxpY2F0aW9uczrTAA4BrgGvAbADmQOagFmA6YDs2AAOAbQBtQG2AbcBuAG5AboBuwOdAfYDngG/
+AcABwQHCgFeA6oDrgFGAVYBOVUNsb3NlUXddcGVyZm9ybUNsb3NlOtMADgGuAa8BsAOnA6iAWYDugPDY
+AA4BtAG1AbYBtwG4AbkBugG7A6sB9gCKAb8BwAHBAk2AV4DvgBGAUYBVgHtUWm9vbVxwZXJmb3JtWm9v
+bTrUAA4B4gGuAa8BsAHlAG8DtoBZgFuANoDyWGNvbnZlcnQ60wAOAa4BrwGwA7oDu4BZgPSA9tgADgG0
+AbYBtwG4AbkBugKSAbsDvgCKAb8BwAHBApgAU4BXgPWAEYBRgFWAk1xTbWFydCBRdW90ZXNfECF0b2dn
+bGVBdXRvbWF0aWNRdW90ZVN1YnN0aXR1dGlvbjrTAA4BrgGvAbADxwPIgFmA+ID72AAOAbQBtQG2AbcB
+uAG5AboBuwPLAfYDzAG/AcABwQJggFeA+YD6gFGAVYCBVENvcHlRY1Vjb3B5OtMADgGuAa8BsAPVA9aA
+WYD9gQEA2AAOAbQBtQG2AbcBuAG5AboBuwPZAfYD2gG/AcABwQLwgFeA/oD/gFGAVYCwXxARSnVtcCB0
+byBTZWxlY3Rpb25Ral8QHWNlbnRlclNlbGVjdGlvbkluVmlzaWJsZUFyZWE60wAOAa4BrwGwA+MD5IBZ
+gQECgQEE2AAOAbQBtQG2AbcBuAG5AboBuwPnAfYAigG/AcABwQJNgFeBAQOAEYBRgFWAe18QEkJyaW5n
+IEFsbCB0byBGcm9udF8QD2FycmFuZ2VJbkZyb250OtQADgHiAa4BrwGwAB8D8QPygFmAAoEBBoEBCNcA
+DgG0AbYBtwG4AbkBugG7A/UAigG/AcABwQJygFeBAQeAEYBRgFWAh18QGEFib3V0IEN1cnJlbmN5IENv
+bnZlcnRlcl8QHW9yZGVyRnJvbnRTdGFuZGFyZEFib3V0UGFuZWw61AAOAeIBrgGvAeMAagHlBACAXoAf
+gFuBAQpbZG9sbGFyRmllbGTTAA4BrgGvAbAEBAQFgFmBAQyBAQ7YAA4BtAG1AbYBtwG4AbkBugG7BAgB
+9gCKAb8BwAHBA12AV4EBDYARgFGAVYDTbxASAEMAdQBzAHQAbwBtAGkAegBlACAAVABvAG8AbABiAGEA
+ciAmXxAfcnVuVG9vbGJhckN1c3RvbWl6YXRpb25QYWxldHRlOtQADgHiAa4BrwHjAGkAQQQTgF6ADoAH
+gQEQXxAVaW5pdGlhbEZpcnN0UmVzcG9uZGVy0wAOAa4BrwGwBBcEGIBZgQESgQEV2AAOAbQBtQG2AbcB
+uAG5AboBuwQbAb0EHAG/AcABwQJggFeBAROBARSAUYBVgIFUUmVkb1FaVXJlZG861AAOAeIBrgGvAeMA
+aQBqAkGAXoAOgB+AeNMADgGuAa8BsAQqBCuAWYEBGIEBHNgADgG0AbUBtgG3AbgBuQG6AbsELgH2BC8B
+vwHAAcEEMoBXgQEagQEbgFGAVYEBGdMADgG0AcQBxQQ1BDaBASSBAU2BAU9fEBdDdXJyZW5jeSBDb252
+ZXJ0ZXIgSGVscFE/WXNob3dIZWxwOtIADgA+BDsEPIEBea8QZAIyBD4C2QQEBEEEFwBuAk0A2ARGAmoC
+IgRJA2cCzARMA/EATARPBFAAcAHlA5kBHQBsAGkC8AKwA8cEWgRbAOoEXQOMAHgEMgRhBGIDNAJYBGUD
+JwMHAmAEaQN1AGsDGQRtBG4CDAHCA7oEcgBtAoUEdQH6A10D1QGxBHoEewR8BH0EfgLoA1UAQQJyBIMA
+bwJFAvoEhwMPAGoEigNCA+MEjQQqAMcEkAEMA6cEkwKYAr4CjwEuAfECFQKiA4ICBASdBJ4CfQSggHSB
+AR6AqoEBDIEBH4EBEoAygHuAJIEBJYCGgG+BASmA2ICmgQFFgQEGgAuBAUmBAUqAPYBbgOmANIAlgA6A
+sICcgPiBAS+BAS6AJ4EBTIDlgBCBARmBAVCBATSAx4CAgQFBgMOAuYCBgQFTgN2AIoC+gQFWgQFegGeA
+ToD0gQFpgC6AjYEBbYBhgNOA/YBNgQE3gQE9gQFxgQFzgQFagK+A0oAHgIeBATqANoB6gLWBAWOAuoAf
+gQEigMyBAQKBAVmBARiAIYEBXIAwgO6BASqAk4ChgJKAOIBggGuAl4DhgGaBAWiBAXiAjIEBMNoADgG0
+AbUEogG2BKMBtwG4AbkBugG7AIoB9gB6AIoAegG/AcABwQJyXU5TSXNTZXBhcmF0b3JcTlNJc0Rpc2Fi
+bGVkgFeAEQmAEQmAUYBVgIfaAA4BtAG1BKIBtgSjAbcBuAG5AboBuwCKAfYAegCKAHoBvwHAAcECcoBX
+gBEJgBEJgFGAVYCHVldpbmRvd9IADgA+AGcEuIBEpAJFA6cEigPjgHqA7oEBIoEBAtoADgG0AbUEogG2
+BKMBtwG4AbkBugG7AIoB9gB6AIoAegG/AcABwQJNgFeAEQmAEQmAUYBVgHteX05TV2luZG93c01lbnXS
+ADcAOATIAbqiAboAO9oADgTKAbQBtQG2AbcBuAG5AboEywG7AgwCDwH2AIoBvwHAAcECYATTWU5TU3Vi
+bWVudVhOU0FjdGlvboBXgGeBASaAEYBRgFWAgYEBJ1ZTcGVlY2hec3VibWVudUFjdGlvbjrSAA4APgBn
+BNiARKICFQIEgGuAZtoADgTKAbQBtQG2AbcBuAG5AboEywG7AmACYwH2AIoBvwHAAcEEkwTjgFeAgYEB
+K4ARgFGAVYEBKoEBLNQADgG0AJMBxAHFBOYE5wTogQEkgQF1gQF3gQF2VEVkaXTSAA4APgBnBOyARK0D
+ZwQXBFsCogPHAlgDdQM0BFoEoAR7BGUERoDYgQESgQEugJeA+ICAgN2Ax4EBL4EBMIEBPYEBQYEBJdoA
+DgG0AbUEogG2BKMBtwG4AbkBugG7AIoB9gB6AIoAegG/AcABwQJggFeAEQmAEQmAUYBVgIHaAA4BtAG1
+BKIBtgSjAbcBuAG5AboBuwCKAfYAegCKAHoBvwHAAcECYIBXgBEJgBEJgFGAVYCB2gAOBMoBtAG1AbYB
+twG4AbkBugTLAbsC8ALzAfYAigG/AcABwQJgBRSAV4CwgQExgBGAUYBVgIGBATJURmluZNIADgA+AGcF
+GIBEpQLoBGIEegSDA9WAr4EBNIEBN4EBOoD92QAOAbQBtQG2AbcBuAG5AboCkgG7BSAB9gUhAb8BwAHB
+AvAAU4BXgQE1gQE2gFGAVYCwWUZpbmQgTmV4dFFn2QAOAbQBtQG2AbcBuAG5AboCkgG7BSkBvQUqAb8B
+wAHBAvAArIBXgQE4gQE5gFGAVYCwXUZpbmQgUHJldmlvdXNRR9kADgG0AbUBtgG3AbgBuQG6ApIBuwUy
+AfYFMwG/AcABwQLwAFSAV4EBO4EBPIBRgFWAsF8QFlVzZSBTZWxlY3Rpb24gZm9yIEZpbmRRZdoADgTK
+AbQBtQG2AbcBuAG5AboEywG7AfoB/QH2AIoBvwHAAcECYAVBgFeAYYEBPoARgFGAVYCBgQE/XxAUU3Bl
+bGxpbmcgYW5kIEdyYW1tYXLSAA4APgBnBUWARKQDGQHxAswCMoC+gGCApoB02gAOBMoBtAG1AbYBtwG4
+AbkBugTLAbsCmAKcAfYAigG/AcABwQJgBVKAV4CTgQFCgBGAUYBVgIGBAUNdU3Vic3RpdHV0aW9uc9IA
+DgA+AGcFVoBEowKPA7oDJ4CSgPSAw9QADgG0AJMBxAHFBVwFXQVegQEkgQFGgQFIgQFHWFNlcnZpY2Vz
+0gAOAD4AZwVigESgXxAPX05TU2VydmljZXNNZW512gAOAbQBtQSiAbYEowG3AbgBuQG6AbsAigH2AHoA
+igB6Ab8BwAHBAcKAV4ARCYARCYBRgFWATtgADgG0AbUBtgG3AbgBuQG6AbsFbwH2A1oBvwHAAcEChYBX
+gQFLgNWAUYBVgI1aU2hvdyBGb250c9oADgTKAbQBtQG2AbcBuAG5AboEywG7BDIENQH2AIoBvwHAAcEE
+kwV9gFeBARmBAU2AEYBRgFWBASqBAU5USGVscNIADgA+AGcFgYBEoQQqgQEY2AAOAbQBtQG2AbcBuAG5
+AboBuwWFAfYFhgG/AcABwQJygFeBAVGBAVKAUYBVgIdsAFAAcgBlAGYAZQByAGUAbgBjAGUAcyAmUSzY
+AA4BtAG1AbYBtwG4AbkBugG7BY4B9gWPAb8BwAHBAcKAV4EBVIEBVYBRgFWATlNOZXdRbtoADgTKAbQB
+tQG2AbcBuAG5AboEywG7AnIATwH2AIoBvwHAAcEEkwWdgFeAh4AJgBGAUYBVgQEqgQFX0gAOAD4AZwWg
+gESrA/EEjQRhBD4EfgSQA0IC2QOMBEECaoEBBoEBWYEBUIEBHoEBWoEBXIDMgKqA5YEBH4CG2gAOAbQB
+tQSiAbYEowG3AbgBuQG6AbsAigH2AHoAigB6Ab8BwAHBAnKAV4ARCYARCYBRgFWAh9oADgTKAbQBtQG2
+AbcBuAG5AboEywG7BEwFXAH2AIoBvwHAAcECcgW9gFeBAUWBAUaAEYBRgFWAh4EBW9oADgG0AbUEogG2
+BKMBtwG4AbkBugG7AIoB9gB6AIoAegG/AcABwQJygFeAEQmAEQmAUYBVgIdcX05TQXBwbGVNZW512AAO
+AbQBtQG2AbcBuAG5AboBuwXKAfYFywG/AcABwQHCgFeBAV+BAWCAUYBVgE5lAE8AcABlAG4gJlFvVEZp
+bGXSAA4APgBnBdSARKsEaQRuBIcEnQOZAr4BsQL6BE8CIgKwgQFTgQFegQFjgQFogOmAoYBNgLWBAUmA
+b4Cc2gAOBMoBtAG1AbYBtwG4AbkBugTLAbsDDwMSAfYAigG/AcABwQHCBeiAV4C6gQFkgBGAUYBVgE6B
+AWVbT3BlbiBSZWNlbnTSAA4APgBnBeyARKEDB4C5XxAWX05TUmVjZW50RG9jdW1lbnRzTWVuddoADgG0
+AbUEogG2BKMBtwG4AbkBugG7AIoB9gB6AIoAegG/AcABwQHCgFeAEQmAEQmAUYBVgE7aAA4EygG0AbUB
+tgG3AbgBuQG6BMsBuwJNAlAB9gCKAb8BwAHBBJMGAIBXgHuBASCAEYBRgFWBASqBAWpWRm9ybWF00gAO
+AD4AZwYEgESiBFACfYEBSoCM2gAOBMoBtAG1AbYBtwG4AbkBugTLAbsDXQNgAfYAigG/AcABwQSTBg+A
+V4DTgQFugBGAUYBVgQEqgQFvVFZpZXfSAA4APgBnBhOARKIDVQQEgNKBAQzaAA4EygG0AbUBtgG3AbgB
+uQG6BMsBuwHCAcYB9gCKAb8BwAHBBJMGHoBXgE6BAWGAEYBRgFWBASqBAXLaAA4EygG0AbUBtgG3AbgB
+uQG6BMsBuwKFAogB9gCKAb8BwAHBBJMGJ4BXgI2BAWuAEYBRgFWBASqBAXRZQU1haW5NZW510gAOAD4A
+ZwYrgESnBG0EfARJBH0EdQRyBF2BAVaBAXGBASmBAXOBAW2BAWmBAUxbX05TTWFpbk1lbnXSAA4AMgAz
+ADSABIAD0gA3ADgGOAFxogFxADvSAA4APgQ7BjuBAXmvEGQB+gJyAnIDXQJyAmAATARyAGsCYAJyAcIE
+kwJgAfoEfgJyAEEBwgKFAEwAHwHCAG4ATABMBKABwgJgAmACYABsBJMCcgBpBF0CcgLwAmACYAJgApgD
+DwRJAcICYABMAfoEkwHCBEYEfAKYBJMATAR9BJMEewR1AvABwgLwAmAEkwSTAnIC8ANdAB8EbQLwAEwC
+TQHCAcIEhwBMAk0CcgJNAnIEMgBqAnIAbQJNAB8EZQHCApgAbwH6AgwCYAAfAgwBwgAfAoUCYIBhgIeA
+h4DTgIeAgYALgQFpgCKAgYCHgE6BASqAgYBhgQFagIeAB4BOgI2AC4ACgE6AMoALgAuBATCAToCBgIGA
+gYAlgQEqgIeADoEBTICHgLCAgYCBgIGAk4C6gQEpgE6AgYALgGGBASqAToEBJYEBcYCTgQEqgAuBAXOB
+ASqBAT2BAW2AsIBOgLCAgYEBKoEBKoCHgLCA04ACgQFWgLCAC4B7gE6AToEBY4ALgHuAh4B7gIeBARmA
+H4CHgC6Ae4ACgQFBgE6Ak4A2gGGAZ4CBgAKAZ4BOgAKAjYCB0gAOAD4EOwaigQF5rxBlAjIEPgLZBAQE
+FwBuBEECTQDYBEYCagIiBEkATAPxA2cAcARMBE8EUALMAeUDmQEdAGwAaQKwAvADxwRaBFsA6gRdA4wA
+eAQyBGEEYgM0AlgEZQMnAwcCYARpA3UAawMZBG0EbgIMAcIDugRyAG0ChQR1AfoDXQGxA9UEewR9BHwE
+egR+A1UAQQLoAnIEgwBvAkUAagL6BIcDDwSKA0ID4wQqBI0AxwSQAQwDpwSTApgCvgKPAS4B8QIVAqIA
+HwOCAgQEnQSeAn0EoIB0gQEegKqBAQyBARKAMoEBH4B7gCSBASWAhoBvgQEpgAuBAQaA2IA9gQFFgQFJ
+gQFKgKaAW4DpgDSAJYAOgJyAsID4gQEvgQEugCeBAUyA5YAQgQEZgQFQgQE0gMeAgIEBQYDDgLmAgYEB
+U4DdgCKAvoEBVoEBXoBngE6A9IEBaYAugI2BAW2AYYDTgE2A/YEBPYEBc4EBcYEBN4EBWoDSgAeAr4CH
+gQE6gDaAeoAfgLWBAWOAuoEBIoDMgQECgQEYgQFZgCGBAVyAMIDugQEqgJOAoYCSgDiAYIBrgJeAAoDh
+gGaBAWiBAXiAjIEBMNIADgA+BDsHCoEBea8QZQcLBwwHDQcOBw8HEAcRBxIHEwcUBxUHFgcXBxgHGQca
+BxsHHAcdBx4HHwcgByEHIgcjByQHJQcmBycHKAcpByoHKwcsBy0HLgcvBzAHMQcyBzMHNAc1BzYHNwc4
+BzkHOgc7BzwHPQc+Bz8HQAdBB0IHQwdEB0UHRgdHB0gHSQdKB0sHTAdNB04HTwdQB1EHUgdTB1QHVQdW
+B1cHWAdZB1oHWwdcB10HXgdfB2AHYQdiB2MHZAdlB2YHZwdoB2kHagdrB2wHbQduB2+BAX2BAX6BAX+B
+AYCBAYGBAYKBAYOBAYSBAYWBAYaBAYeBAYiBAYmBAYqBAYuBAYyBAY2BAY6BAY+BAZCBAZGBAZKBAZOB
+AZSBAZWBAZaBAZeBAZiBAZmBAZqBAZuBAZyBAZ2BAZ6BAZ+BAaCBAaGBAaKBAaOBAaSBAaWBAaaBAaeB
+AaiBAamBAaqBAauBAayBAa2BAa6BAa+BAbCBAbGBAbKBAbOBAbSBAbWBAbaBAbeBAbiBAbmBAbqBAbuB
+AbyBAb2BAb6BAb+BAcCBAcGBAcKBAcOBAcSBAcWBAcaBAceBAciBAcmBAcqBAcuBAcyBAc2BAc6BAc+B
+AdCBAdGBAdKBAdOBAdSBAdWBAdaBAdeBAdiBAdmBAdqBAduBAdyBAd2BAd6BAd+BAeCBAeFfECdNZW51
+IEl0ZW0gKENoZWNrIEdyYW1tYXIgV2l0aCBTcGVsbGluZylbU2VwYXJhdG9yLTJfEBdNZW51IEl0ZW0g
+KEhpZGUgT3RoZXJzKW8QHgBNAGUAbgB1ACAASQB0AGUAbQAgACgAQwB1AHMAdABvAG0AaQB6AGUAIABU
+AG8AbwBsAGIAYQByICYAKV8QEE1lbnUgSXRlbSAoUmVkbylfECdTdGF0aWMgVGV4dCAoQW1vdW50IGlu
+IG90aGVyIEN1cnJlbmN5OilbU2VwYXJhdG9yLTNdTWVudSAoV2luZG93KV8QEVRleHQgRmllbGQgQ2Vs
+bC0xXxASTWVudSBJdGVtIChTcGVlY2gpVDExMTFRNV8QEE1lbnUgSXRlbSAoRWRpdClcQ29udGVudCBW
+aWV3XxAkTWVudSBJdGVtIChBYm91dCBDdXJyZW5jeSBDb252ZXJ0ZXIpXxAQTWVudSBJdGVtIChVbmRv
+KV8QD0hvcml6b250YWwgTGluZV8QD01lbnUgKFNlcnZpY2VzKVMyLTFfEBZNZW51IEl0ZW0gKFNob3cg
+Rm9udHMpXxAnTWVudSBJdGVtIChDaGVjayBTcGVsbGluZyBXaGlsZSBUeXBpbmcpXxAUQ29udmVydGVy
+IENvbnRyb2xsZXJTMS0xXxArVGV4dCBGaWVsZCBDZWxsIChBbW91bnQgaW4gb3RoZXIgQ3VycmVuY3k6
+KV8QI1N0YXRpYyBUZXh0IChFeGNoYW5nZSByYXRlIHBlciAkMTopWlRleHQgRmllbGRRNltNZW51IChG
+aW5kKV8QEE1lbnUgSXRlbSAoQ29weSlZU2VwYXJhdG9yW1NlcGFyYXRvci0xXxAnVGV4dCBGaWVsZCBD
+ZWxsIChFeGNoYW5nZSByYXRlIHBlciAkMTopUTFfEBRNZW51IEl0ZW0gKFNob3cgQWxsKV8QD1RleHQg
+RmllbGQgQ2VsbFEyUzEyMV8QFU1lbnUgSXRlbSAoRmluZCBOZXh0KV8QFk1lbnUgSXRlbSAoU2VsZWN0
+IEFsbClfEBFNZW51IEl0ZW0gKFBhc3RlKV8QGU1lbnUgSXRlbSAoU3Vic3RpdHV0aW9ucylfEBdNZW51
+IEl0ZW0gKFNtYXJ0IExpbmtzKV8QFk1lbnUgSXRlbSAoQ2xlYXIgTWVudSlbTWVudSAoRWRpdClROV8Q
+Ek1lbnUgSXRlbSAoRGVsZXRlKVxUZXh0IEZpZWxkLTFvEBoATQBlAG4AdQAgAEkAdABlAG0AIAAoAFMA
+aABvAHcAIABTAHAAZQBsAGwAaQBuAGcgJgApXxAeTWVudSBJdGVtIChDdXJyZW5jeSBDb252ZXJ0ZXIp
+bxARAE0AZQBuAHUAIABJAHQAZQBtACAAKABPAHAAZQBuICYAKV1NZW51IChTcGVlY2gpW01lbnUgKEZp
+bGUpXxAYTWVudSBJdGVtIChTbWFydCBRdW90ZXMpXxASTWVudSBJdGVtIChXaW5kb3cpXxAhU3RhdGlj
+IFRleHQgKERvbGxhcnMgdG8gQ29udmVydDopXU1lbnUgKEZvcm1hdClfEBBNZW51IEl0ZW0gKFZpZXcp
+XxAbTWVudSAoU3BlbGxpbmcgYW5kIEdyYW1tYXIpW01lbnUgKFZpZXcpUThfEB1NZW51IEl0ZW0gKEp1
+bXAgdG8gU2VsZWN0aW9uKV8QIE1lbnUgSXRlbSAoU3BlbGxpbmcgYW5kIEdyYW1tYXIpXxASTWVudSBJ
+dGVtIChGb3JtYXQpXxAQTWVudSBJdGVtIChGaWxlKV8QGU1lbnUgSXRlbSAoRmluZCBQcmV2aW91cylf
+EBRNZW51IEl0ZW0gKFNlcnZpY2VzKV8QGE1lbnUgSXRlbSAoU2hvdyBUb29sYmFyKV8QG1dpbmRvdyAo
+Q3VycmVuY3kgQ29udmVydGVyKW8QEQBNAGUAbgB1ACAASQB0AGUAbQAgACgARgBpAG4AZCAmAClfEBlN
+ZW51IChDdXJyZW5jeSBDb252ZXJ0ZXIpXxAiTWVudSBJdGVtIChVc2UgU2VsZWN0aW9uIGZvciBGaW5k
+KV8QFVB1c2ggQnV0dG9uIChDb252ZXJ0KV8QFE1lbnUgSXRlbSAoTWluaW1pemUpXFRleHQgRmllbGQt
+MlIxMF8QF01lbnUgSXRlbSAoT3BlbiBSZWNlbnQpXxASTWVudSAoT3BlbiBSZWNlbnQpW1NlcGFyYXRv
+ci02XxAjTWVudSBJdGVtIChIaWRlIEN1cnJlbmN5IENvbnZlcnRlcilfEB5NZW51IEl0ZW0gKEJyaW5n
+IEFsbCB0byBGcm9udClfECNNZW51IEl0ZW0gKEN1cnJlbmN5IENvbnZlcnRlciBIZWxwKVtTZXBhcmF0
+b3ItNF8QEVRleHQgRmllbGQgQ2VsbC0yW1NlcGFyYXRvci01XxAlVGV4dCBGaWVsZCBDZWxsIChEb2xs
+YXJzIHRvIENvbnZlcnQ6KV8QEE1lbnUgSXRlbSAoWm9vbSlYTWFpbk1lbnVfEBRNZW51IChTdWJzdGl0
+dXRpb25zKVEzXxAcTWVudSBJdGVtIChTbWFydCBDb3B5L1Bhc3RlKV8QFUJ1dHRvbiBDZWxsIChDb252
+ZXJ0KV8QGk1lbnUgSXRlbSAoQ2hlY2sgU3BlbGxpbmcpXxAaTWVudSBJdGVtIChTdGFydCBTcGVha2lu
+ZylfEA9NZW51IEl0ZW0gKEN1dClcRmlsZSdzIE93bmVyXxAZTWVudSBJdGVtIChTdG9wIFNwZWFraW5n
+KVE3W0FwcGxpY2F0aW9uXxAXTWVudSBJdGVtIChTaG93IENvbG9ycylfEBBNZW51IEl0ZW0gKEZpbmQp
+0gAOAD4EOwfWgQF5oNIADgA+BDsH2YEBeaDSAA4APgQ7B9yBAXmvEJICMgGUAakEPgLZBAQEQQQXAG4B
+nQGRAacBgQJNANgERgJqAiIBmQGGAZwBiQGlBEkDZwLMBEwD8QBMBE8EUABwAeUBlQGEA5kBHQBsAGkC
+8AKwA8cEWgRbAaIBmwDqBF0DjAB4BDIEYQGDAZYEYgM0AlgEZQMnAwcCYARpAZgDdQBrAxkEbQRuAgwB
+kgGaAcIDugRyAG0BpAKFAY8EdQH6A10D1QGxBHoEewR8BH0EfgLoA1UAQQGMAZ4BqgJyAawEgwBvAkUC
++gSHAw8AagGCBIoDQgGLA+MBlwSNBCoAxwSQAQwDpwGNAZMBnwSTAYABoAGoAaMBpgKYAZACvgKPAS4B
+8QIVAqIBigGIAasBhwGFAB8BoQOCAgQEnQSeAn0EoAGOgHSAuIEBD4EBHoCqgQEMgQEfgQESgDKA4ICp
+gQEJgFqAe4AkgQElgIaAb4DPgHOA3IB/gQEBgQEpgNiApoEBRYEBBoALgQFJgQFKgD2AW4C9gGqA6YA0
+gCWADoCwgJyA+IEBL4EBLoDzgNeAJ4EBTIDlgBCBARmBAVCAZYDCgQE0gMeAgIEBQYDDgLmAgYEBU4DL
+gN2AIoC+gQFWgQFegGeAroDRgE6A9IEBaYAugPyAjYCggQFtgGGA04D9gE2BATeBAT2BAXGBAXOBAVqA
+r4DSgAeAkYDkgQERgIeBAReBATqANoB6gLWBAWOAuoAfgF+BASKAzICLgQECgMaBAVmBARiAIYEBXIAw
+gO6AloC0gOiBASqATIDtgQELgPeBAQWAk4ClgKGAkoA4gGCAa4CXgIWAeYEBFoB3gG6AAoDxgOGAZoEB
+aIEBeICMgQEwgJvSAA4APgQ7CHGBAXmvEJIIcghzCHQIdQh2CHcIeAh5CHoIewh8CH0Ifgh/CIAIgQiC
+CIMIhAiFCIYIhwiICIkIigiLCIwIjQiOCI8IkAiRCJIIkwiUCJUIlgiXCJgImQiaCJsInAidCJ4Inwig
+CKEIogijCKQIpQimCKcIqAipCKoIqwisCK0IrgivCLAIsQiyCLMItAi1CLYItwi4CLkIugi7CLwIvQi+
+CL8IwAjBCMIIwwjECMUIxgjHCMgIyQjKCMsIzAjNCM4IzwjQCNEI0gjTCNQI1QjWCNcI2AjZCNoI2wjc
+CN0I3gjfCOAI4QjiCOMI5AjlCOYI5wjoCOkI6gjrCOwI7QjuCO8I8AjxCPII8wj0CPUI9gj3CPgI+Qj6
+CPsI/Aj9CP4I/wkACQEJAgkDgQHmgQHngQHogQHpgQHqgQHrgQHsgQHtgQHugQHvgQHwgQHxgQHygQHz
+gQH0gQH1gQH2gQH3gQH4gQH5gQH6gQH7gQH8gQH9gQH+gQH/gQIAgQIBgQICgQIDgQIEgQIFgQIGgQIH
+gQIIgQIJgQIKgQILgQIMgQINgQIOgQIPgQIQgQIRgQISgQITgQIUgQIVgQIWgQIXgQIYgQIZgQIagQIb
+gQIcgQIdgQIegQIfgQIggQIhgQIigQIjgQIkgQIlgQImgQIngQIogQIpgQIqgQIrgQIsgQItgQIugQIv
+gQIwgQIxgQIygQIzgQI0gQI1gQI2gQI3gQI4gQI5gQI6gQI7gQI8gQI9gQI+gQI/gQJAgQJBgQJCgQJD
+gQJEgQJFgQJGgQJHgQJIgQJJgQJKgQJLgQJMgQJNgQJOgQJPgQJQgQJRgQJSgQJTgQJUgQJVgQJWgQJX
+gQJYgQJZgQJagQJbgQJcgQJdgQJegQJfgQJggQJhgQJigQJjgQJkgQJlgQJmgQJngQJogQJpgQJqgQJr
+gQJsgQJtgQJugQJvgQJwgQJxgQJygQJzgQJ0gQJ1gQJ2gQJ3EQFaEH8RAYgQjxCREQEqEJUQ1xEBfxEB
+jxEBchEBjREBjBAYEQF6ENMQiBBNEQGOEQFbEOsQ4hAnENkQzxDbEIIQOhEBcBBKEQFYEQGFEQGLEOYQ
+6RBJEQGAEQF7EQF1ENwQThDFENYQzhEBZBDfEQF8EGcQlhEBdhBqEOMRAWUQ0BDGEMsRAVwRAWIQfhDN
+EFIRAXEQyhEBeRDMEDgQSBDUEPERAW4QUREBXxATEQF9EPURASwRAWoRAScRASgQ0hBQENUQ2BBTEQEr
+EIMQ0REBKREBbxEBYxEBdBDnEDkRAWgQ3REBgRAXEHAQfBB9EQF3EOEQXBCGEQFpEAUQ6BDsEG8RAXgQ
+kBEBfhDvEOQRAWwQwRAdEQFrEPARAW0Q4BCOEQFdEN4QSxEBXhEBghDJEMQQxxEBcxAlEQGHEQGGEFcR
+AZERAZARAYoQwxBPE//////////9EQFZENoQVtIADgA+AGcJloBEoNIADgA+BDsJmYEBeaDSAA4APgQ7
+CZyBAXmg0gA3ADgJngmfogmfADteTlNJQk9iamVjdERhdGEACAAZACIAJwAxADoAPwBEAFIAVABmBWIF
+aAWzBboFwQXPBeEF/QYLBhcGIwYxBjwGSgZmBnQGhwaZBrMGvQbKBswGzwbSBtUG2AbaBt0G3wbiBuUG
+6AbrBu0G7wbyBvUG+Ab7BwQHEAcSBxQHIgcrBzQHPwdEB1MHXAdvB3gHgweFB4gHigezB8AHzQfbB+UH
+8wgACBIIJggyCDQINgg4CDoIPwhBCEMIRQhHCEkIZAh5CIIInwixCLwIxQjRCN0I3wjhCOMI5gjoCOoI
+7Aj1CPcJCAkKCQwJDgkQCRIJFAkWCRgJOQlBCUgJUglUCVYJWAlaCV0JXglgCWIJfAmhCa0JwQnMCdYJ
+5AnxCgUKEQoaChwKHgogCiIKJAopCioKLAotCj4KRQpMClUKVwpgCmIKZQpyCnsKgAqHCpwKpAqxCr0K
+ywrNCs8K0QrTCtUK3AryCv8LBwsJCwsLDgsXCxwLMQszCzULNws5C0MLUAtSC1ULXgtnC3kLhguPC5oL
+pguwC7cLwwvkC+YL6AvqC+wL7QvvC/EMCwwwDDIMNAw2DDgMOgw7DD0MXgxgDGIMZAxmDGcMaQxrDIQM
+qQyyDLQMtgy4DLoMvAy9DL8M4AziDOQM5gzoDOkM6wztDQYNJw0sDS4NMA0yDTQNNg07DT0NVQ1qDWwN
+bg1wDXINfw2MDY4Nmg2vDbENsw21DbcNyg3rDe0N7w3xDfMN9A32DfgOEQ4yDjQONg44DjoOPA4+DlQO
+dQ53DnkOew59Dn4OgA6CDpoOuw69Dr8OwQ7DDsUOxw7jDwQPBg8IDwoPDA8NDw8PEQ8pD1oPcA+FD5QP
+pg+4D8YPyw/ND88P0Q/TD9UP1w/ZD9sP3Q/iD+sP8w/1D/4QBxAUEB0QKBAxEGIQbBB4EIYQkxCdEK8Q
+sRCzELUQtxC4ELoQvBC+EMAQwhDZEOAQ/RD/EQERAxEFEQcRCxEYERoRKBExEToRQBFJEVARXxFnEXIR
+exGCEZsRpBGpEbwRxRHMEdkR3xHoEeoSRxJJEksSTRJPElESUxJVElcSWRJbEl0SXxJhEmMSZRJnEmkS
+axJtEm8ScRJzEnUSdxJ5EnsSfRJ/EoESgxKFEocSiRKLEo0SjxKREpQSlxKaEp0SoBKjEqYSqRK2Er8S
+xxLJEssSzRLuEvYTChMVEyMTLRM6E0ETQxNFE0oTTBNRE1MTVRNXE2QTcBNzE3YTeROKE4wTmROoE6oT
+rBOuE7YTyBPRE9YT6RP2E/gT+hP8FA8UGBQdFCgUOhRDFEoUYhRxFIIUkBSSFJQUlhSYFKEUoxSlFLsU
+xRTOFNUU7BT5FPsU/RT/FSAVIhUkFSkVKxUtFS8VMRU+FUEVRBVHFVYVWBVnFXQVdhV4FXoVmxWdFZ8V
+oRWjFaUVpxW0FbcVuhW9FcsV2RXmFegV6hXsFg0WDxYRFhMWFRYXFhkWKBY3FkQWRhZIFkoWbxZ5FnsW
+fRZ/FoEWgxaFFocWlRaXFqYWsxa1FrcWuRbaFtwW3hbgFuIW5BbmFwQXHRcuFzAXMhc0FzYXQhdPF1EX
+UxdVF3YXeBd6F3wXfheAF4IXkxeWF5kXnBefF6gXqhfAF80XzxfRF9MX9Bf2F/gX+hf8F/4YABgNGBAY
+ExgWGBwYHhglGDIYNBg2GDgYWRhbGF0YXxhhGGMYZRh2GHkYexh+GIEYmxidGKgYtRi3GLkYuxjcGN4Y
+4BjiGOQY5hjoGPUY+Bj7GP4ZChkMGSQZMRkzGTUZNxlYGV4ZYBliGWQZZhloGWoZbBl5GXwZfxmCGZUZ
+sBm9Gb8ZwRnDGeQZ5hnoGeoZ7BnuGfAZ9Bn2GfsaCBoKGgwaDhovGjEaMxo1GjcaORo7GkgaShpRGl4a
+YBpiGmQahRqHGokaixqNGo8akRqWGpgaphqzGrUatxq5Gtoa3BreGuAa4hrkGuYbBBslGzIbNBs2Gzgb
+WRtbG10bYhtkG2YbaBtqG3YbeBuRG54boBuiG6QbyRvLG80bzxvRG9Mb1RviG+Ub6BvrG/Yb+BwSHB8c
+IRwjHCUcQhxEHEYcSBxKHEwcThxgHHkchhyIHIocjBytHK8csRyzHLUctxy5HMoczRzQHNMc1hzhHPkd
+Bh0IHQodDB0tHS8dMR0zHTUdNx05HVYdWB1qHXcdeR17HX0dnh2gHaIdpB2mHagdqh22HdYd4x3lHecd
+6R4KHgweDh4QHhIeFB4WHiEeIx4uHjsePR4/HkEeYh5kHmYeaB5qHmwebh6IHo4enx6hHqMepR6nHrMe
+wB7CHsQexh7nHuke6x7tHu8e8R7zHwAfAx8GHwkfFh8YHy4fOx89Hz8fQR9iH2QfZh9oH2ofbB9uH3Mf
+dR97H4gfih+MH44frx+xH7MftR+3H7kfux/CH8of2x/dH98f4R/jH+wf7h/wH/ogBCARIBMgFSAXIDgg
+OiA8ID4gQCBCIEQgTSBmIHMgdSB3IHkgmiCcIJ4goCCiIKQgpiCsIK4gvCDJIMsgzSDPIPAg8iD0IPYg
++CD6IPwhASEOIR8hISEjISUhJyEwIT0hPyFBIUMhZCFmIWghaiFsIW4hcCF9IaEhriGwIbIhtCHVIdch
+2SHbId0h3yHhIeYh6CHuIfsh/SH/IgIiIyIlIiciKSIrIi0iLyJDIkUiZSJyInQidyJ6IpsinSKgIqIi
+pCKmIqgivSLPIuAi4iLkIuci6iMHIwkjDCMOIxAjEiMUIy8jTyNgI2IjZCNmI2kjdSOCI4QjhyOKI6sj
+rSOwI7IjtCO2I7gj3yQBJBIkFCQWJBgkGyQzJEAkQiRFJEgkaSRrJG4kcSRzJHUkdyR8JH4khCSVJJck
+mSSbJJ0kqiSsJK8ksiTTJNUk2CTbJN0k3yTiJO8k8iT1JPglEiUUJR4lJyUqJfUl9yX6Jfwl/yYCJgUm
+ByYJJgsmDiYQJhImFSYXJhkmHCYfJiEmJCYnJikmKyYtJi8mMSYzJjUmNyY5JjwmPyZBJkQmRiZIJksm
+TiZRJlMmVSZYJlomXCZeJmEmYyZlJmcmaiZtJm8mcSZzJnYmeCZ6Jn0mfyaBJoMmhSaIJosmjiaRJpQm
+liaYJpomnCafJqEmoyalJqgmqiasJq8msSa0Jrcmuia8Jr8mwSbDJsYmyCbKJswmzibQJtIm1CbWJtgm
+2ybeJuAm4ycMJxonJycpJysnLCcuJy8nMSczJzUnXidgJ2InYydlJ2YnaCdqJ2wncyd8J34nhyeJJ4sn
+jieRJ7onvCe+J78nwSfCJ8QnxifIJ9cn4CflKA4oGCghKCMoJSgoKCooLCguKDAoMyg6KEkoUihUKFko
+WyhdKIYoiCiKKI0ojyiRKJMoliiZKKoorSiwKLMotii7KMQoxijhKOMo5ijpKOso7SjvKPEo8yj2KPko
+/Cj/KQIpKyktKS8pMCkyKTMpNSk3KTkpYilkKWYpZylpKWopbCluKXApmSmbKZ0poCmiKaQppimoKasp
+sCm5KbspxinIKcspzinRKdMp+Cn6Kf0qACoCKgQqBioQKhIqNyo5KjwqPypBKkMqRSpTKlUqeip8Kn8q
+giqEKoYqiCqhKqMqzCrOKtAq0yrVKtcq2SrbKt4q9Sr+KwArCSsLKw0rDysRKzorPCs+K0ErQytFK0cr
+SStMK1orYytlK2wrbitwK3IrgyuGK4krjCuPK5groSujK6QrtivfK+Er4yvkK+Yr5yvpK+sr7SwOLBAs
+EywVLBcsGSwbLCYsTyxRLFQsVyxZLFssXSxgLGMsaCxxLHMsdix5LJosnCyfLKIspCymLKgswSzDLOQs
+5izpLOws7izwLPIs9iz4LSEtIy0lLSctKS0rLS0tMC0zLTwtPi1VLVgtWy1eLWEtZC1nLWktay1tLXAt
+ci2bLZ0tny2gLaItoy2lLactqS3SLdQt1y3aLdwt3i3gLeIt5S4OLhAuEi4TLhUuFi4YLhouHC4pLkou
+TC5PLlIuVC5WLlguYy5lLmoucy51Lowujy6SLpUumC6aLpwuni6gLqMupS6nLtAu0i7ULtcu2S7bLt0u
+3y7iLu4u9y75Lvwu/i8XL0AvQi9EL0UvRy9IL0ovTC9OL3cveS97L34vgC+CL4Qvhy+KL5Evmi+cL6Ev
+pC+mL88v0S/TL9Yv2C/aL9wv3y/iL+cv8C/yL/cv+S/8MCUwJzApMCwwLjAwMDIwNTA4MGEwYzBlMGgw
+ajBsMG4wcTB0MH4whzCJMJgwmzCeMKEwpDCnMKowrTC5MMIwxDDGMM8w1DDdMOAxqzGtMa8xsTGzMbUx
+tzG5MbwxvjHAMcIxxDHHMckxyzHOMdAx0jHUMdYx2DHaMdwx3jHgMeIx5THnMekx6zHtMe8x8jH0MfYx
++TH7Mf0x/zIBMgMyBTIHMgoyDDIOMhAyEjIVMhcyGjIdMh8yIjIkMicyKjItMjAyMjI0MjYyODI7Mj4y
+QDJCMkQyRjJJMksyTTJPMlEyUzJWMlgyWjJcMl4yYDJjMmUyZzJpMmsybTJwMnIydDJ2MngyejJ8Mn4y
+gDKCMoQyhjKIMpEylDNhM2MzZjNoM2szbjNwM3MzdTN3M3ozfDN+M4EzgzOGM4gzijONM5AzkzOVM5cz
+mTObM50znzOhM6MzpTOoM6szrTOwM7IztDO3M7ozvTO/M8EzxDPGM8gzyjPNM88z0TPTM9Yz2TPbM90z
+3zPiM+Qz5jPpM+sz7TPvM/Ez9DP3M/oz/TQANAI0BDQGNAg0CzQNNA80ETQTNBY0GDQbNB00IDQjNCY0
+KDQrNC00LzQyNDQ0NjQ4NDo0PDQ+NEA0QjRENEY0STRMNE40UTRaNF01KjUtNTA1MzU2NTk1PDU/NUI1
+RTVINUs1TjVRNVQ1VzVaNV01YDVjNWY1aTVsNW81cjV1NXg1ezV+NYE1hDWHNYo1jTWQNZM1ljWZNZw1
+nzWiNaU1qDWrNa41sTW0Nbc1ujW9NcA1wzXGNck1zDXPNdI11TXYNds13jXhNeQ15zXqNe018DXzNfY1
++TX8Nf82AjYFNgg2CzYONhE2FDYXNho2HTYgNiM2JjYpNiw2LzYyNjU2ODY7Nj42QTZENkc2SjZNNlA2
+UzZWNlk2gzaPNqk26Db7NyU3MTc/N1M3aDdtN283gjePN7Y3yTfbN+038TgKODQ4SzhPOH04oziuOLA4
+vDjPONk45TkPORE5KDk6OTw5QDlYOXE5hTmhObs51DngOeI59zoEOjs6XDqBOo86mzq2Oss67zr9OxA7
+Ljs6Ozw7XDt/O5Q7pzvDO9o79TwTPDg8VDx5PJE8qDy1PLg80jznPPM9GT06PWA9bD2APYw9tD3HPdA9
+5z3pPgg+ID49Plo+bD55PpU+lz6jPr0+0D7ZPtw+3T7mPuk+6j7zPvZAHUAfQCFAJEAnQClALEAvQDJA
+NEA2QDhAO0A9QD9AQUBEQEZASEBKQExATkBQQFNAVkBYQFpAXUBgQGJAZUBoQGpAbEBuQHBAckB0QHZA
+eEB6QHxAfkCBQIRAhkCIQIpAjUCPQJFAlECXQJlAm0CeQKBAokClQKdAqUCrQK5AsECyQLRAtkC5QLxA
+vkDAQMJAxEDGQMlAy0DNQM9A0UDUQNZA2EDaQNxA30DiQOVA6EDrQO1A70DxQPNA9UD4QPpA/UEAQQJB
+BEEGQQlBC0ENQQ9BEkEUQRZBGUEbQR5BIUEjQSZBKEEqQSxBLkEwQTNBNUE3QTpBPEE/QUFBQ0FFQUdB
+SUFLQU1BT0FRQVNBVkFYQVpBXEFeQWBBYkFlQWhBakFtQW9BeEF7QqJCpUKoQqtCrkKxQrRCt0K6Qr1C
+wELDQsZCyULMQs9C0kLVQthC20LeQuFC5ELnQupC7ULwQvNC9kL5QvxC/0MCQwVDCEMLQw5DEUMUQxdD
+GkMdQyBDI0MmQylDLEMvQzJDNUM4QztDPkNBQ0RDR0NKQ01DUENTQ1ZDWUNcQ19DYkNlQ2hDa0NuQ3FD
+dEN3Q3pDfUOAQ4NDhkOJQ4xDj0OSQ5VDmEObQ55DoUOkQ6dDqkOtQ7BDs0O2Q7lDvEO/Q8JDxUPIQ8tD
+zkPRQ9RD10PaQ91D4EPjQ+ZD6UPsQ+9D8kP1Q/hD+0P+RAFEBEQHRApEDUQQRBNEFkQZRBxEH0QiRCVE
+KEQrRC5EMUQ0RDdEOkQ9REBEQ0RGRElETERPRFJEVURYRFtEXURgRGJEZERnRGlEa0RuRHFEdER3RHpE
+fER/RIFEg0SFRIhEi0SNRI9EkUSTRJVEl0SZRJtEnkSgRKNEpkSpRKtErUSvRLJEtUS4RLpEvES+RMBE
+wkTFRMdEykTMRM5E0UTTRNVE2ETaRNxE3kThRORE5kToROpE7UTvRPJE9ET2RPhE+kT8RP9FAUUERQZF
+CUULRQ5FEUUURRdFGUUbRR1FH0UhRSRFJkUoRStFLkUxRTRFNkU4RTtFPUVARUJFREVGRUhFS0VNRU9F
+UUVURVZFWEVaRVxFX0VhRWRFZkVoRWtFbUVvRXJFdEV3RXlFe0V+RYBFgkWFRYhFikWMRY5FkUWTRZZF
+mUWbRZ5FoUWkRaZFqEWxRbRFtkW4RcFFw0XERc1F0EXRRdpF3UXeRedF7AAAAAAAAAICAAAAAAAACaAA
+AAAAAAAAAAAAAAAAAEX7A</bytes>
+		</object>
+	</data>
+</archive>
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO.html	(revision 13309)
@@ -0,0 +1,130 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="HOWTO_files/stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>CurrencyConverter HOWTO</h1>
+    </div>
+
+    <div class="subtitle">
+      <h2>Creating Apple's <a
+      href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/index.html">
+            Currency Converter</a> example<br/>
+          with Clozure CL
+      </h2></div>
+
+
+    <div class="body-text">
+      <p>This HOWTO guide explains how to use Clozure CL (formerly
+      OpenMCL) to create a Cocoa application that is functionally
+      identical to Apple's
+      <a
+      href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/index.html">
+        Currency Converter</a> example. The most important
+        difference between Apple's example and this one is that this
+        one is implemented in Common Lisp instead of Objective-C. It
+        uses Clozure CL's Objective-C bridge to provide communication
+        between the Lisp code that you write and Apple's Cocoa
+        frameworks. The resulting application looks and acts just
+        like any other Cocoa application.</p>
+
+      <p>This HOWTO doesn't discuss all the background information
+      that Apple's tutorial covers. Instead, we assume that you have
+      Apple's document handy for reference, and we just describe the
+      specific steps needed to build the example using
+      Apple's InterfaceBuilder application and Clozure CL.</p>
+
+      <p>An observant programmer will look at the code in this example
+      and say, "well, that's trivial! Why create all those classes and
+      connections and so forth just to perform a multiplcation?" That
+      observation is correct: the actual work done by the Currency
+      Converter application is trivial&mdash;both in the Lisp and the
+      Objective-C versions. The point of this example (and Apple's) is
+      not to show you how to perform a multiplication. The point is to
+      show you how Apple's frameworks implement and support the
+      Model-View-Controller paradigm, and how you can use that support
+      to build Cocoa applications. In fact, the work done by the
+      application is <em>intentionally trivial</em>, to emphasize the
+      frameworks rather than the particulars of the application.</p> 
+
+      <p>This HOWTO has the additional purpose of showing you how
+      Clozure CL makes it possible to do exactly the same thing in
+      Lisp that you can do with Objective-C, so that you will
+      understand how to use Lisp with Apple's frameworks.</p>
+
+      <p>The current version of the Clozure CL Objective-C bridge
+      includes code that was formerly distributed separately as the
+      "Bosco" application framework. Because that framework has been
+      integrated with Clozure CL proper, it no longer exists as a
+      separate project.</p>
+    </div>
+
+    <div class="section-head">
+      <h2>Apple's Currency Converter Example</h2>
+    </div>
+
+    <div class="body-text">
+      <p>It will be helpful in understanding this example if you can
+      easily refer to
+      Apple's <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/index.html">
+      Currency Converter</a> tutorial while working through this
+      HOWTO. You might consider opening a separate window or tab, and
+      keeping the Apple example handy while you work.</p>
+
+      <p>In some ways, the Lisp version of the example is simpler
+      than the Objective-C example, but the basic concepts are the
+      same. In particular, the Lisp example follows the same
+      <a
+      href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/02Essence/chapter_2_section_4.html#//apple_ref/doc/uid/TP40000863-CH3-DontLinkElementID_6">
+        Model-View-Controller</a> paradigm that the Apple tutorial
+        uses. If you are new to Cocoa programming, or if you are not
+        familiar with how it uses the Model-View-Controller paradigm,
+        it's probably a good idea to read through the Apple example in
+        full, paying special attention to the Model-View-Controller
+        section. Once you've done that, keep the Apple pages handy in
+        a window for easy reference.</p>
+
+      <p>This Common Lisp version of the Currency Converter example
+      uses Apple's InterfaceBuilder application to build a window and
+      main menu, and then uses Common Lisp code to load and operate
+      that user interface. The Common Lisp code relies on Clozure CL's
+      Objective-C bridge to provide communication between the running
+      Lisp code and Apple's Cocoa frameworks. Once the code is
+      complete, we use the BUILD-APPLICATION function to save a
+      working Cocoa application bundle. That bundle looks and acts
+      just like any other Cocoa application.</p>
+
+    </div>
+
+    <div class="section-head">
+      <h2>Requirements Before You Start</h2>
+    </div>
+
+    <div class="body-text">
+      <p>In order to build this example you will need:</p>
+
+      <ul>
+        <li><p>Mac OS X Leopard (version 10.5.x) or Mac OS X Tiger
+        (version 10.4.x)</p></li>
+        <li><p>Apple's XCode development tools</p></li>
+        <li><p>Apple's InterfaceBuilder application (included with XCode)</p></li>
+        <li><p>A recent version of Clozure CL</p></li>
+        <li><p>The Apple <a
+      href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/index.html">
+        Currency Converter</a> example, for reference</p></li>
+      </ul>
+    </div>
+
+    <div class="nav">
+      <p><a href="HOWTO_files/pages/making_project.html">next</a></p>
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/build_app.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/build_app.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/build_app.html	(revision 13309)
@@ -0,0 +1,144 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Building the Application</h1>
+    </div>
+
+    <div class="body-text">
+      <p>Both the user interface and the behavior of the
+      CurrencyConverter are complete now. All that remains for us to
+      do is to build the application executable into a Cocoa
+      application bundle. Apple's tutorial relies on XCode to build
+      the application from Objective-C source files; we will use the
+      Clozure CL IDE to build it from our Lisp source file.</p>
+
+      <p>We build the application using the optional
+      BUILD-APPLICATION feature, distributed as part of Clozure CL. The
+      steps to build the Cocoa application are:</p>
+
+      <ol>
+        <li><p>Load the application code into the IDE</p></li>
+        <li><p>Load the BUILD_APPLICATION feature</p></li>
+        <li><p>Run BUILD_APPLICATION with the proper arguments</p></li>
+      </ol>
+
+      <p>This sequence of steps causes Clozure CL to construct a Cocoa
+      application bundle and write out the application executable to
+      it, then quit. If all goes well, you should be able to run the
+      application by double-clicking it, and use the UI you built in
+      InterfaceBuilder to convert currencies.</p>
+    </div>
+
+    <div class="section-head">
+      <h2>Building the Application, Step-by-Step</h2>
+    </div>
+
+    <div class="body-text">
+      <ol>
+        <li><p>Launch the Clozure CL IDE. It's safest to build the
+        application with a fresh IDE session, so if you have it
+        running, you may wish to quit and relaunch before following
+        the rest of the steps.</p></li>
+
+        <li><p>For convenience, set the working directory to your
+        "currency-converter" folder. For example, you can do
+        something like this (using your pathnames in place of mine, of
+        course:):</p>
+          <p><code>(setf (current-directory) "/Users/mikel/Valise/clozure/openmcl/example-code/currency-converter/")</code></p>
+        </li>
+
+        <li><p>Load the application code:</p>
+          <p><code>(load "currency-converter")</code></p>
+        </li>
+
+        <li><p>Load the BUILD-APPLICATION feature:</p>
+          <p><code>(require "build-application")</code></p>
+        </li>
+
+        <li><p>Run BUILD-APPLICATION (be sure to correct the pathname
+        to your CurrencyConverter nibfile. It is safest to use a full,
+        absolute pathname&mdash;not the relative pathname you see
+        below):</p>
+          <p><pre>
+(ccl::build-application :name "CurrencyConverter"
+                        :main-nib-name "CurrencyConverter"
+                        :nibfiles 
+  '(#P"currency-converter/CurrencyConverter.nib"))</pre></p>
+        </li>
+      </ol>
+
+      <p>By default, BUILD-APPLICATION constructs the application
+      bundle in the current working directory. If you followed the
+      instructions here, that means it will build
+      CurrencyConverter.app in your currency-converter folder. You
+      can control where BUILD-APPLICATION puts the application bundle
+      by passing a pathname as the value of the keyword argument
+      :DIRECTORY, like so:</p>
+
+          <p><pre>
+(ccl::build-application :name "CurrencyConverter"
+                        :directory #P"/Users/mikel/Desktop/"
+                        :main-nib-name "CurrencyConverter"
+                        :nibfiles 
+  '(#P"currency-converter/CurrencyConverter.nib"))</pre></p>
+
+      <p>If all goes well, BUILD-APPLICATION constructs an
+        application bundle, copies "CurrencyConverter.nib" into it,
+        writes the application executable, and quits. You should now
+        be able to launch CurrencyConverter.app by double-clicking
+        the application icon:</p>
+
+      <div class="subtitle">
+        <img src="../images/cc1.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>CurrencyConverter.app launches and displays your user
+      interface, which you can then use to convert currencies:</p>
+
+      <div class="subtitle">
+        <img src="../images/cc2.jpg"alt="" 
+             border='0'/>
+      </div>
+
+
+    </div>
+
+    <div class="section-head">
+      <h2>Correcting the Application Name</h2>
+    </div>
+
+    <div class="body-text">
+      <p>You'll notice when you run the application that, even though
+      you named it CurrencyConverter, the name in the main menu
+      appears as "Clozure CL". That's because OS X takes the
+      application's name, not from the application bundle's name, nor
+      from the running code, but from an InfoPlist.strings file hidden
+      inside the application bundle. To make the name appear
+      correctly in the running application, you need to edit the file</p>
+
+      <p>CurrencyConverter.app/Contents/Resources/English.lproj/InfoPlist.strings</p>
+
+      <p>Find the entry named "CFBundleName" and change its value
+      from "Clozure CL" to "CurrencyConverter". The application's name
+      in the main menu bar should now appear correctly, as
+      "CurrencyConverter". You may also want to change the other
+      strings in the "InfoPlist.strings" file.</p>
+    </div>
+
+    <div class="nav">
+      <p><a href="../../HOWTO.html">start</a>|<a href="conclusion.html">next</a></p>
+    </div>
+
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/building_ui.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/building_ui.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/building_ui.html	(revision 13309)
@@ -0,0 +1,323 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Building the User Interface</h1>
+    </div>
+
+    <div class="body-text">
+      <p>The next step in creating a Lisp version of the currency
+      converter application is to construct the user
+      interface. Apple's
+      tutorial <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/05View/chapter_5_section_1.html#//apple_ref/doc/uid/TP40000863-CH7-SW1"> 
+      describes in detail</a> how to do this.</p>
+
+<div class="section-head">
+  <h2>Apple's Tutorial</h2>
+</div>
+
+<p>Apple's tutorial explains how to use InterfaceBuilder to create the
+  user interface, and how to use XCode to create project files and
+  write Objective-C code. Our project uses Lisp instead of
+  Objective-C, and does not use XCode project files, so you can skip
+  the part of the tutorial that explains how to use XCode.</p>
+
+<div class="section-head">
+  <h2>Using InterfaceBuilder to Create the UI</h2>
+</div>
+
+      <p>We'll begin by using Apple's InterfaceBuilder application to
+        create a nibfile. The nibfile contains
+        archived versions of the Objective-C objects that define the
+        application's user interface. When you launch an application,
+        Mac OS X uses the archived objects in the nibfile to create the
+        windows and menus you see on the screen. </p>
+
+      <p>Start by locating Apple's InterfaceBuilder application. If
+        you installed Apple's Developer Tools, InterfaceBuilder should
+        be in the folder "/Developer/Applications/":</p>
+
+      <div class="inline-image">
+        <img src="../images/finder-win1.jpg"alt="" 
+             border='0'/>
+      </div>
+      
+
+      <p class= "note"><strong><em>NOTE:</em></strong> If you have not installed Apple's Developer Tools, you should
+        do that now. You will not be able to build the CurrencyConverter
+        example without them. The Developer Tools are distributed as an
+        optional install with Mac OS X 10.5 ("Leopard"). Look for the
+        "XCode Tools" package in the "Optional Installs" folder on the
+        Mac OS 10.5 install disk.</p>
+
+      <p>Once you have located InterfaceBuilder, double-click to launch
+        the application. InterfaceBuilder presents a window you can use
+        to choose a template for the nibfile you are going to create.</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard1.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>Click the "Application" icon and then click the "Choose" button to
+        create an application nibfile. InterfaceBuilder creates a new
+        application nibfile, but doesn't immediately save it. The
+        Objective-C objects that represent the new application's
+        interface appear in a new untitled window:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard2.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>The intial window and menubar also appear on the screen. The
+      new application's name appears in the menus as
+      "NewApplication". Save the new nibfile into the
+      "currency-converter" folder that you created earlier
+      (on <a href="making_project.html">this
+      page</a>). InterfaceBuilder 3.0 gives you a choice of file
+      formats when you save a new nibfile; use the "NIB 3.x"
+      format&mdash;the "XIB 3.x" format works fine for editing your
+      user interface, but will not work correctly if you try to use it
+      in a working application. Give the new file the name
+      "CurrencyConverter.nib".</p>
+
+      <div class="note">
+        <p><strong><em>NOTE:</em></strong> Most Objective-C application projects use a main
+        nibfile called "MainMenu.nib", and if you use XCode to create
+        a new application project, it creates a nibfile with that
+        name. Apple's CurrencyConverter tutorial assumes that the
+        name of the main nibfile is "MainMenu.nib".</p>
+
+        <p>So, why do we tell you to use a different name? Clozure CL
+          has a main nibfile built into it, whose name is
+          "MainMenu.nib". Normally you don't see it, and don't even
+          need to know that it exists. But the Clozure CL
+          application-building tools create a new application by
+          copying resources from the Clozure CL application, so that
+          your new application has available to it all the built-in
+          Clozure CL tools. We ask you to name your nibfile
+          "CurrencyConverter.nib" so that it can coexist with the
+          Clozure CL main nibfile without causing any problems.</p>
+
+        <p>This difference between a Lisp project and an Objective-C
+        project might be a little confusing at first. Just try to keep
+        in mind that whenever Apple's tutorial refers to the
+        "MainMenu.nib" file, it means the file we have just created
+        and named "CurrencyConverter.nib". In a Clozure CL project,
+        "MainMenu.nib" is the name of the main Lisp nibfile, not your
+        application's main nibfile.</p>
+      </div>
+
+
+<p>Skip straight to the part of Apple's tutorial
+called <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/05View/chapter_5_section_1.html#//apple_ref/doc/uid/TP40000863-CH7-SW1">Defining
+the View: Building the User Interface</a>. Read the introduction to
+nibfiles, and follow the instructions to create the Currency Converter
+interface. (Remember that when the tutorial tells you to open and edit
+"MainMenu.nib", you will instead open and edit your
+"CurrencyConverter.nib".) When you reach the end of the section
+called <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/05View/chapter_5_section_5.html#//apple_ref/doc/uid/TP40000863-CH7-DontLinkElementID_38">Test
+the Interface</a>, and move on to the short section afterward
+called <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/05View/chapter_5_section_6.html#//apple_ref/doc/uid/TP40000863-CH7-DontLinkElementID_39">What's
+Next</a>, you are done creating the interface for your
+application. Save your nibfile and continue with the next section of
+this HOWTO.</p>
+
+<div class="section-head">
+  <h2>What if You Need to Use InterfaceBuilder 2.x?</h2>
+</div>
+
+<p>If you are still using Mac OS X 10.4.x ("Tiger"), you can still
+  create a working nibfile and you can still follow the instructions
+  in this HOWTO to create a Cocoa application with Clozure CL. The
+  main obstacle to doing so is that the earlier versions of
+  InterfaceBuilder have a significantly different user interface, and
+  so you may find it hard to follow Apple's tutorial when working with
+  InterfaceBuilder.</p>
+
+<p>If you are working with Mac OS X 10.4.x ("Tiger"), you can
+  look <a href="building_ui_tiger.html">here</a> to find a description
+  of how to build the user interface files with the earlier version of
+  InterfaceBuilder. When you have finished building your user
+  interface, you can continue with the <a href="create_lisp.html">next
+  section</a>, "Creating a Lisp File".</p>
+
+<p>One other thing: if you are using Mac OS X 10.4.x ("Tiger"), you
+  will be able to build Cocoa applications only on PPC Macs. The
+  Clozure CL Objective-C support for Intel systems works only on Mac
+  OS X 10.5.x ("Leopard").</p>
+
+
+<div class="section-head">
+  <h2>Adding Custom Classes to the nibfile</h2>
+</div>
+
+<p>Once the user interface for your application looks right, there is
+  still one important task to complete before you can use it. You must
+  record some information in the nibfile about the classes of the
+  objects, so that the application can create them with the right
+  connections in place.</p>
+
+<p>When you use XCode to write an Objective-C application,
+  InterfaceBuilder can read the Objective-C header files and use the
+  information in them to create descriptions of the classes in the
+  Objective-C code. When the application is written in Lisp,
+  InterfaceBuilder can't read the class descriptions from the code,
+  and so we'll have to manually tell the nibfile about any classes
+  that we use in the user interface.</p>
+
+<p>As you will see in the following sections, we'll use Lisp code to
+  define two Objective-C classes: Converter, and
+  ConverterController. The Converter class implements the method that
+  performs the actual currency conversion for our application; the
+  ConverterController class provides communication between the user
+  interface and the Converter object. We need a way to create
+  instances of these two classes in the nibfile, so that launching the
+  application sets up all the objects correctly.</p>
+
+<div class="section-head">
+  <h2>Create Instances of Custom Classes</h2>
+</div>
+
+<p>In InterfaceBuilder's Library window, select the Cocoa Objects and
+  Controllers view:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard3.jpg"alt="" 
+             border='0'/>
+      </div>
+
+<p>Drag an Object from the Library window and drop it into the main
+  CurrencyConverter window:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard4.jpg"alt="" 
+             border='0'/>
+      </div>
+
+<p>Now tell InterfaceBuilder the name of the new object's class. With
+  the Object icon selected in the main CurrencyConverter window,
+  choose the Identity tab of the Inspector. At the top of the
+  Identity view is a "Class" field; type the name of your custom
+  class (in this case, "Converter") into the "Class" field and save
+  the nibfile:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard5.jpg"alt="" 
+             border='0'/>
+      </div>
+
+<p>Repeat the previous steps to create an instance of the
+  ConverterController class: drag an "Object" icon and drop it in the
+  main CurrencyConverter window. Then, change the name of the
+  Object's class to "ConverterController".</p>
+
+<p>That's all it takes to add an instance of a custom class to the
+  nibfile. We do still have to add the names of instance variables and
+  actions, and we need to create the connections between the
+  instances.</p>
+
+<div class="section-head">
+  <h2>Add Outlets and Actions</h2>
+</div>
+
+<p>Now, using the "+" button below the "Class Outlets" section of the
+  Inspector, add outlets to the ConverterController class. The
+  outlets you need to add are named "amountField", "converter",
+  "dollarField", and "rateField".</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard6.jpg"alt="" 
+             border='0'/>
+      </div>
+
+<p>We'll connect each of the "field" outlets to one of the text fields
+  in the CurrencyConverter UI, and we'll connect the "converter"
+  outlet to the Converter instance that we created before. When the
+  application launches, it creates the Converter and
+  ConverterController instances and establishes the connections that
+  we've specified in the nibfile.</p>
+
+
+<p>First, though, we need to tell the nibfile about actions as well as
+  outlets. With the "ConverterController" instance selected, use the
+  "+" button below the "Class Actions" section to add a new
+  action. Name the action "convert:":</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard7.jpg"alt="" 
+             border='0'/>
+      </div>
+
+<p>In this application, the "convert:" action is the only action
+  defined for the user interface, so we are done with actions now. In
+  more complex applications you may need to define many actions and
+  outlets.</p>
+
+<p>Now we'll connect outlets and actions to objects.</p>
+
+<div class="section-head">
+  <h2>Add Connections</h2>
+</div>
+
+<p>InterfaceBuilder enables you to connect objects by
+  "Control-dragging" from one to another. To "Control-drag", you hold
+  down the Control key while dragging from one object to the next.</p>
+
+<p>Select the "ConverterController" instance in the nibfile's main
+  window, and Control-drag a connection to the "Exchange rate" text
+  field in the application's main window. (Be sure to connect to the
+  text field, not to its label!) When you release the mouse button,
+  InterfaceBuilder pops up a menu that lists the available
+  outlets. Choose "rateField" from the menu. The "rateField" outlet of
+  the "ConverterController" instance is now connected to the "Exchange
+  rate" text field.</p>
+
+<p>Repeat the same steps for the "Dollars" field and the "Amount"
+  field, connecting them to the "dollarField" and "amountField"
+  outlets, respectively.</p>
+
+<p>Finally, Control-drag a connection from the "ConverterController"
+  instance to the "Converter" instance. Choose "converter" from the
+  popup menu to connect the "converter" field of the
+  "ConverterController" instance to the "Converter" instance.</p>
+
+<p>To confirm that the connections are correct, you can use the
+  Connections view in the inspector. With the "ConverterController"
+  instance selected, click the blue arrow icon at the top of the
+  Inspector window to display connections. You should see a list of
+  outlets and the types of objects they are connected to:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-leopard8.jpg"alt="" 
+             border='0'/>
+      </div>
+
+<p>We need to add one more connection: from the "Convert" button in
+  the application window to the "ConverterController"
+  instance. Control drag a connection from the "Convert" button in the
+  application window to the "ConverterController" instance in the
+  nibfile's main window. InterfaceBuilder pops up a menu; choose the
+  "convert:" action from the menu to connect the button to the
+  action.</p>
+
+<p>The nibfile now contains descriptions of the needed cusstom
+  classes and their connections. You can continue with the next
+  section, which explains how to write the Lisp code that implements
+  the application's behavior.</p>
+
+    <div class="nav">
+      <p><a href="../../HOWTO.html">start</a>|<a href="making_project.html">previous</a>|<a href="create_lisp.html">next</a></p>
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/building_ui_tiger.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/building_ui_tiger.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/building_ui_tiger.html	(revision 13309)
@@ -0,0 +1,586 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Building the User Interface on "Tiger"</h1>
+    </div>
+
+    <div class="body-text">
+      <p>If you are using Mac OS X 10.4.x ("Tiger") to build your
+      application, then the Apple tutorial's section on building the
+      UI may be somewhat confusing. Apple's tutorial uses
+      InterfaceBuilder 3.x to show how to build an interface, and
+      there were many interface changes between versions 2.x and 3.x
+      of InterfaceBuilder. In this section we see how to build the UI
+      using InterfaceBuilder 2.x.</p>
+
+      <div class="section-head">
+        <h2>Launch InterfaceBuilder</h2>
+      </div>
+
+      <p>Start by locating Apple's InterfaceBuilder application. If
+        you installed Apple's Developer Tools, InterfaceBuilder should
+        be in the folder "/Developer/Applications/":</p>
+
+      <div class="inline-image">
+        <img src="../images/finder-win2.jpg"alt="" 
+             border='0'/>
+      </div>
+    
+      <p class= "note"><strong><em>NOTE:</em></strong> If you have not
+        installed Apple's Developer Tools, you should do that now. You
+        will not be able to build the CurrencyConverter example
+        without them. The Developer Tools are distributed as an
+        optional install with Mac OS X 10.4 ("Tiger"). Look for the
+        "XCode Tools" package in the "Optional Installs" folder on the
+        Mac OS 10.4 install disk.</p>
+
+      <p>Once you have located InterfaceBuilder, double-click to launch
+        the application. InterfaceBuilder presents a window you can use
+        to choose a template for the nibfile you are going to create.</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger1.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>Make sure the "Application" option is selected in the "Cocoa"
+      section and click the "New" button to create a new
+      nibfile. InterfaceBuilder creates a new application nibfile, but
+      doesn't immediately save it. The Objective-C objects that
+      represent the new application's interface appear in a new
+      untitled window:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger2.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>The intial window and menubar also appear on the screen. The
+      new application's name appears in the menus as
+      "NewApplication". Save the new nibfile into the
+      "currency-converter" folder that you created earlier
+      (on <a href="making_project.html">this page</a>). Give the new
+      file the name "CurrencyConverter.nib"</p>
+
+      <div class="note">
+        <p><strong><em>NOTE:</em></strong> Most Objective-C application projects use a main
+        nibfile called "MainMenu.nib", and if you use XCode to create
+        a new application project, it creates a nibfile with that
+        name. Apple's CurrencyConverter tutorial assumes that the
+        name of the main nibfile is "MainMenu.nib".</p>
+
+        <p>So, why do we tell you to use a different name? Clozure CL
+          has a main nibfile built into it, whose name is
+          "MainMenu.nib". Normally you don't see it, and don't even
+          need to know that it exists. But the Clozure CL
+          application-building tools create a new application by
+          copying resources from the Clozure CL application, so that
+          your new application has available to it all the built-in
+          Clozure CL tools. We ask you to name your nibfile
+          "CurrencyConverter.nib" so that it can coexist with the
+          Clozure CL main nibfile without causing any problems.</p>
+
+        <p>This difference between a Lisp project and an Objective-C
+        project might be a little confusing at first. Just try to keep
+        in mind that whenever Apple's tutorial refers to the
+        "MainMenu.nib" file, it means the file we have just created
+        and named "CurrencyConverter.nib". In a Clozure CL project,
+        "MainMenu.nib" is the name of the main Lisp nibfile, not your
+        application's main nibfile.</p>
+      </div>
+
+      <div class="section-head">
+        <h2>Resize the Window</h2>
+      </div>
+      
+      <p>Make the window smaller by dragging the bottom-right corner
+      of the window inward.</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger3.jpg"alt="" 
+             border='0'/>
+      </div>
+      
+      <div class="section-head">
+        <h2>Change the Title of the Window</h2>
+      </div>
+      
+      <p>InterfaceBuilder creates the initial window with the title
+      "Window". Change the title to the more appropriate "Currency
+      Converter":</p>
+
+      <ol>
+        <li><p>Click the Window object in the "Currency Converter"
+        window.</p>
+          <p><div class="inline-image">
+              <img src="../images/ibwin-tiger4.jpg"alt="" 
+                   border='0'/>
+            </div>
+        </p></li>
+        <li><p>Choose "Attributes" from the drop-down menu in the
+        Inspector window:</p>
+          <p><div class="inline-image">
+              <img src="../images/ibwin-tiger5.jpg"alt="" 
+                   border='0'/>
+            </div>
+        </p></li>
+        <li><p>Change the "Window Title" field to read "Currency Converter":</p>
+          <p><div class="inline-image">
+              <img src="../images/ibwin-tiger6.jpg"alt="" 
+                   border='0'/>
+            </div>
+        </p></li>
+      </ol>
+
+      <div class="section-head">
+        <h2>Add Text Fields</h2>
+      </div>
+
+      <p>In InterfaceBuilder's Palettes window, select the "Cocoa
+      Text" view, and find the NSTextView object:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger7.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>Drag an NSTextView object and drop it into the "Currency
+      Converter" window:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger8.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>If you drag a view near the edges of a window,
+      InterfaceBuilder displays blue guide lines that show the
+      standard placement of a view near the edge of the window. Drag
+      the text view to the right and upward until the guide lines
+      appear, and then let go. The text view is then positioned in
+      the standard way.</p>
+
+      <p>Now add two more text fields. You can drag them from the
+      palette as you did the first one, or you can duplicate the
+      first one. To duplicate, select the first text view and then
+      choose "Duplicate" from the "Edit" menu. Alternatively, you can
+      option-drag the text field to duplicate it.</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger9.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <div class="section-head">
+        <h2>Label the Text Fields</h2>
+      </div>
+
+      <p>Now add labels to the text fields, to identify their
+      purposes for the user. For each text field, drag a Label object
+      from the palette and drop it next to the field. (Alternatively,
+      you can drop one Label and then duplicate it, just as you can
+      duplicate the text fields.)</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger10.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>Just as InterfaceBuilder displayed guidelines to help you
+      position the text field near the edge of the window, it also
+      displays guide lines to help you position the labels near the
+      text fields. Just drag each label until the blue guide lines
+      appear, then release the label.</p>
+
+      <p>Now change the text of the labels. Click a label to select
+      it. Then show the Inspector by choosing the "Show Inspector"
+      item from the "Tools" menu. Select the "Attributes" item from
+      the pull-down menu at the top of the Inspector window, and type
+      the correct text into the Title field. For example, here is how
+      to enter the text for the top label:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger11.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>Here's how the labels should look after you have entered the
+      text for all three:</p>
+
+      <div class="inline-image">
+        <img src="../images/ibwin-tiger12.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>When you first enter the text for a label, the label may not
+      be wide enough to show it all. In that case, you'll see only
+      part of the text in the label. You can resize the label to make
+      the full text visible. Click the label to select it. Notice the
+      small blue dots that surround it. Grab a dot on the left side
+      and drag it to the left to make the label wider, until you can
+      see the entire text.</p>
+
+      <div class="section-head">
+        <h2>Change Text Field Attributes</h2>
+      </div>
+      
+      <p>The first two text fields accept user input; the last
+      displays the result of the conversion. We want the first two
+      text fields to be editable, so users can enter the values to use
+      in the conversion. We don't want the last field to be editable,
+      but we do want users to be able to copy text from it.</p>
+
+      <p>We can control all this behavior using text-field
+      attributes, configurable in the Inspector.</p>
+
+      <ol>
+        <li><p>Select the first text field</p></li>
+        <li><p>Choose "Show Inspector" from the "Tools" menu</p></li>
+        <li><p>Make sure "Attributes" is selected in the pull-down
+        menu at the top of the Inspector window</p></li>
+        <li><p>Ensure that the "Editable" and "Enabled" boxes are
+        checked in the "Attributes" display of the Inspector window</p></li>
+        <li><p>Repeat this process for the second text field</p></li>
+        <li><p>Finally, repeat it again for the last text field, but
+        this time make sure the "Editable" box is unchecked</p></li>
+      </ol>
+
+      <div class="section-head">
+        <h2>Add a Button</h2>
+      </div>
+      
+      <p>Now we add a button that activates the currency conversion.</p>
+      
+      <ol>
+        <li><p>Drag a Button object from the palette and drop it on
+            the window</p>
+          <p><div class="inline-image">
+              <img src="../images/ibwin-tiger13.jpg"alt="" 
+                   border='0'/>
+            </div>
+        </p></li>
+        <li><p>Double-click the button and change its title to "Convert"</p>
+          <p><div class="inline-image">
+              <img src="../images/ibwin-tiger14.jpg"alt="" 
+                   border='0'/>
+            </div>
+        </p></li>
+        <li><p>Select the button and then choose "Attributes" from
+        the pull-down menu at the top of the Inspector window. Almost
+        halfway down the "Attributes" view of the Inspector window,
+        find the "Key Equiv" field. Choose "Return" from the pulldown
+        menu in that field.</p>
+          <p><div class="inline-image">
+              <img src="../images/ibwin-tiger15.jpg"alt="" 
+                   border='0'/>
+            </div>
+        </p>
+        <p>When you choose "Return", InterfaceBuilder enters "\R" in
+        the text field for the Key Equivalent. Now when a user hits
+        the "Return" key, your application will behave as if they had
+        clicked the "Convert" button.</p></li>
+      </ol>
+
+      <div class="section-head">
+        <h2>Add a Separator</h2>
+      </div>
+      
+      <p>Now add a separator line to visually group the text fields
+      together. Drag a separator line from the palette and drop it
+      above the button.</p>
+      
+      <p><div class="inline-image">
+          <img src="../images/ibwin-tiger16.jpg"alt="" 
+               border='0'/>
+        </div>
+      </p>
+
+      <p>Drag the ends of the separator line until it spans a
+        visually pleasing width. As always, you can use the blue
+        guidelines that InterfaceBuilder displays to adjust the size
+        and position of the line and other elements to conform to
+        Apple's Human Interface Guidelines.</p>
+
+      <div class="section-head">
+        <h2>Set Up the Menus</h2>
+      </div>
+
+      <p>InterfaceBuilder creates the standard menus for a new
+      application, but it doesn't know the name of the
+      application. Consequently, the Application menu and several menu
+      items use the name "NewApplication" where they should use the
+      name of your application. Change the text of these items so that
+      they read "Currency Converter" instead of "NewApplication".</p>
+
+      <ol>
+        <li><p>Double-click the text "NewApplication" in the
+        application menu of your application's menubar. Change the
+        text to "Currency Converter".</p>
+          <p><div class="inline-image">
+              <img src="../images/ibwin-tiger17.jpg"alt="" 
+                   border='0'/>
+            </div>
+          </p>
+        <p><strong>NOTE:</strong> This change isn't really enough to get your
+        application to display the right name for the Application menu
+        when it's launched; the <a href="build_app.html">section</a>
+        on building the application explains how to make sure the
+        correct name appears.</p></li>
+        <li><p>Repeat this process for each menu item where the name
+        "NewApplication" appears. Using the same method you used to
+        change the name of the application menu, edit the "About
+        NewApplication" item, the "Hide NewApplication" item, and the
+        "Quit NewApplication" item in the application menu. Then edit
+        the "NewApplication Help" item in the "Help" menu.</p></li>
+      </ol>
+
+      <div class="section-head">
+        <h2>Tighten Up the Window Layout</h2>
+      </div>
+
+      <p>InterfaceBuilder provides layout tools with which you can
+      easily clean up the layout of a UI window and ensure it
+      conforms to Apple's user interface guidelines.</p>
+
+      <ol>
+        <li><p>Select the "Exchange Rate" text label. Then
+        Shift-click the other two labels to include them in the
+        selection (actually, it doesn't matter which label you select first).</p></li>
+        <li><p>Choose "Layout" > "Size to Fit" to shrink the labels
+        to the smallest sizes that still show all the text</p></li>
+        <li><p>Choose "Layout" > "Alignment" > "Align Right Edges" to
+        line up the right sides of the labels</p></li>
+        <li><p>With all three labels still selected, drag them up and
+        to the left. Release them when the blue guidelines show at
+        the top and left side of the window.</p></li>
+        <li><p>Now select all three text fields. You can click one of
+        them, then Shift-click to add the others to the
+        selection. Drag them up and left, toward the labels. Again,
+        release them when the blue guide line appears to show you the
+        proper distance from the labels. A guide line also appears to
+        show you when the fields are vertically aligned with the
+        center label.</p></li>
+        <li><p>Next, grab the separator line and move it up and to the
+        left. Release it when its left edge is aligned with the left
+        edge of the bottom label, and its top is the recommended
+        distance from the bottom label and its text field. Then drag
+        the right end of the separator line to resize it until its
+        right edge is aligned with the right edge of the bottom text
+        field.  Again, guide lines show when you have found the proper
+        distances.</p></li>
+        <li><p>Grab the button and move it up and left, again using
+        the guide lines to help you find a good position.</p></li>
+        <li><p>Finally, resize the window. When the blue guide lines
+        appear on the right and bottom of the window, it's the right
+        size for its contents.</p></li>
+      </ol>
+
+      <p>Now your application window should look something like the
+      one in the illustration:</p>
+
+      <p><div class="inline-image">
+          <img src="../images/ibwin-tiger18.jpg"alt="" 
+               border='0'/>
+        </div>
+      </p>
+
+      <div class="section-head">
+        <h2>Enable Tabbing Between Text Fields</h2>
+      </div>
+
+      <p>Users generally expect to be able to use the Tab key to move
+      from one text field to the next in a dialog
+      box. InterfaceBuilder enables you to specify the tabbing order
+      in text fields.</p>
+
+      <ol>
+        <li><p>Choose "Layout" > "Keyboard Navigation" > "Show
+        Keyboard Check". InterfaceBuilder displays a set of small
+        icons that identify UI elements that can respond to key
+        events.</p></li>
+        <li><p>Select the "Exchange Rate" text field (the field, not
+        the label) and then choose "Layout" > "Keyboard Navigation" >
+        "Make Initial First Responder". A small "1" icon appears in
+        the text field to show that when the application launches,
+        that field receives keyboard events.</p></li>
+        <li><p>Control-drag from the "Exchange Rate" field to the
+        "Dollars" field. InterfaceBuilder shows the "Connections"
+        Inspector, and, because Keyboard Check is enabled,
+        automatically selects the "nextKeyView" outlet. Click the
+        "Connect" button in the Inspector window to confirm.</p></li>
+        <li><p>Repeat the previous steps to connect the "Dollars"
+        field back to the "Exchange Rate" field. That way, tabbing
+        moves the insertion point from the "Exchange Rate" field to
+        the "Dollars" field, and then back to the "Exchange Rate"
+        field. Control-drag from the "Dollars" field to the "Exchange
+        Rate" field, then click "Connect" to confirm.</p></li>
+      </ol>
+
+      <p>We don't enable tabbing into the "Amount" field because it's
+      not an editable field; it's used only to show the result of a
+      conversion.</p>
+
+      <div class="section-head">
+        <h2>Set Up the Classes Used In the User Interface</h2>
+      </div>
+
+      <p>The visual elements of your application's user interface are
+      all ready now. The last thing you must do is create descriptions
+      of any custom classes used by the application when users
+      interact with the interface.</p>
+
+      <p>When a user clicks the "Convert" button, it should send a
+      message to a custom class that causes the conversion to take
+      place. In order for the application to connect the user
+      interface to classes that perform these actions, you must add
+      descriptions of your classes to the nibfile. Fortunately,
+      InterfaceBuilder can create class descriptions and save them in
+      the nibfile for you.</p>
+
+      <div class="section-head">
+        <h3>ConverterController</h3>
+      </div>
+
+      <p>ConverterController is the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/02Essence/chapter_2_section_4.html#//apple_ref/doc/uid/TP40000863-CH3-SW4">controller</a> class that the user
+      interface communicates with directly when the "Convert" button
+      is pressed. Create a description of the ConverterController
+      class, and then create an instance of it.</p>
+
+      <ol>
+        <li><p>In InterfaceBuilder's "CurrencyConverter.nib" window,
+        click the "Classes" tab. The window shows a browser view of
+        all available Objective-C classes:</p>
+        <p><div class="inline-image">
+          <img src="../images/ibwin-tiger19.jpg"alt="" 
+               border='0'/>
+        </div></p>
+        </li>
+        <li><p>Control-click the "NSObject" entry in the browser, and
+        choose "Subclass NSObject" from the popup
+        menu. InterfaceBuilder creates a new entry initially called
+        "MyObject". Change the name from "MyObject" to "ConverterController".</p></li>
+        <li><p>Select the "ConverterController" class in the browser,
+        then activate the Inspector window and choose "Attributes"
+        from the popup menu at the top of the Inspector. At the
+        bottom of the "Attributes" view is a list of actions or
+        outlets. Select "Outlets", and use the "Add" button to add
+        four fields:</p>
+        <p><div class="inline-image">
+          <img src="../images/ibwin-tiger20.jpg"alt="" 
+               border='0'/>
+        </div></p>
+        <p>Rename these four fields to: "amountField", "dollarField",
+        "rateField", and "converter":</p>
+        <p><div class="inline-image">
+            <img src="../images/ibwin-tiger21.jpg"alt="" 
+                 border='0'/>
+        </div></p></li>
+        <li><p>Now add the action that is triggered when the
+        "Convert" button is pressed: switch to the Actions view and
+        use the "Add" button to add a new action:</p>
+        <p><div class="inline-image">
+            <img src="../images/ibwin-tiger22.jpg"alt="" 
+                 border='0'/>
+        </div></p>
+        <p>Change the name of the action from "myAction:" to "convert:"</p></li>
+        <li><p>Now create an instance of the ConverterController
+        class. In the browser, Right-click the ConverterController
+        class and choose "Instantiate ConverterController". The
+        browser view automatically switches to the Instances view to
+        show you the newly-created instance of ConverterController as
+        a blue box icon. There is a small yellow flag next to the
+        ConverterController instances to show that it has outlets
+        that are not connected to anything. In our final step, we'll
+        create the correct connections for the instance's outlets,
+        which will enable the application to send messages correctly
+        to the objects that implement its behavior.</p></li>
+      </ol>
+
+      <div class="section-head">
+        <h3>Converter</h3>
+      </div>
+
+      <p>Converter is
+      the <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/02Essence/chapter_2_section_4.html#//apple_ref/doc/uid/TP40000863-CH3-SW4">model</a>
+      class that implements the actual conversion code. Create a
+      description of the Converter class, and then create an
+      instance of it. Repeat the steps you used to create the
+      ConverterController class and instance to create a Converter
+      class and instance:</p>
+
+      <ol>
+        <li><p>Switch to the browser view in the
+        "CurrencyConverter.nib" window.</p></li>
+        <li><p>Control-click NSObject and choose "Subclass NSObject"
+        from the resulting popup menu.</p></li>
+        <li><p>Change the name of the newly-created class from
+        "MyObject" to "Converter"</p></li>
+        <li><p>Control-click the "Converter" class and choose
+        "Instantiate Converter" to create an instance of the
+        Converter class.</p></li>
+      </ol>
+
+      <p>The model class, "Converter", has no outlets or actions, so
+      you don't need to add anything to it before instantiating
+      it. Your code will implement a conversion method, but
+      InterfaceBuilder doesn't need to know about it; the "convert:"
+      method in your code will know everything it needs to about the
+      "Converter" class. You just need to create the class
+      description and the instance so that your application will
+      start up with the correct objects created and connected.</p>
+
+      <div class="section-head">
+        <h3>Connecting the Outlets</h3>
+      </div>
+
+      <p>The final step in setting up the user interface is
+      establishing connections between the outlets and objects in the
+      interface, so that messages are sent from the user interface to
+      the correct objects.</p>
+
+      <ol>
+        <li><p>Connect the "Convert" button to the
+        "ConverterController" instance. Control-drag from the
+        "Convert" button to the "ConverterController" instance. Make
+        sure the "convert:" action is selected in the "Target/Action"
+        view of the Inspector window, then click the "connect" button
+        to confirm.</p></li>
+        <li><p>Connect the "ConverterController" instance to the text
+        fields. Control-drag from the "ConverterController" instance
+        to the "Exchange Rate" field. Select "rateField" in the
+        "Outlets" view of the Inspector window and click "connect" to
+        confirm. Then repeat this process, connecting "dollarField" to
+        the "Dollars" text field, and "amountField" to the "Amount"
+        field.</p></li>
+        <li><p>Finally, connect the "ConverterController" to the
+        "Converter" instance. Control-drag from the
+        "ConverterController" instance to the "Converter"
+        instance. Select the "converter" outlet in the Inspector
+        window and click "connect" to confirm.</p></li>
+      </ol>
+
+      <p>The nibfile now contains descriptions of the custom classes
+      that your code will implement, including connections between
+      their outlets and the objects with which they must
+      communicate. You can save the nibfile and proceed to write the
+      code that implements their behavior.</p>
+
+      <p>You can continue now with the section on <a href="create_lisp.html">"Creating a Lisp File"</a>.</p>
+
+
+
+    </div>
+
+    <div class="nav">
+      <p><a href="../../HOWTO.html">start</a>|<a href="making_project.html">previous</a>|<a href="create_lisp.html">next</a></p>
+    </div>
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/conclusion.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/conclusion.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/conclusion.html	(revision 13309)
@@ -0,0 +1,40 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Conclusion</h1>
+    </div>
+
+    <div class="body-text">
+      <p>This concludes our HOWTO on building the Apple
+      CurrencyConverter example in Lisp with Clozure CL. Your own Lisp
+      applications are likely to be considerably more complex than the
+      Currency Converter, which, after all, just does a simple
+      multiplication. You can, however, use exactly the same steps to
+      build a much richer and more full-featured Cocoa
+      application.</p>
+      
+      <p>A more complex application will still consist of one or more
+      nibfiles and one or more Lisp source files. You will still use
+      the Objective-C bridge to define Objective-C classes and
+      methods, and to use Cocoa library features. And you will still
+      use BUILD-APPLICATION to turn your source and nibfiles into
+      standalone Cocoa applications.</p>
+
+      <p>You should now be able to use Clozure CL to accomplish anything
+      that an Objective-C user can accomplish with Cocoa. Good luck!</p>
+
+    <div class="nav">
+      <p><a href="../../HOWTO.html">start</a></p>
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/create_lisp.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/create_lisp.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/create_lisp.html	(revision 13309)
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Creating a Lisp File</h1>
+    </div>
+
+    <div class="body-text">
+      <p>Now that you have created the nibfile that defines your
+      application's user interface, it's time to create the Lisp
+      source file that defines its behavior. When you work with
+      Objective C, as in Apple's tutorial, you use Apple's XCode
+      application to create and manage projects, to edit Objective C
+      source files, and to build the final application. In this HOWTO,
+      the Clozure CL application takes the place of XCode. The Lisp
+      project structure is much simpler than the XCode project
+      structure: to build the Lisp application we need only the
+      nibfile created in the previous section, and a single Lisp
+      source file.</p>
+      
+      <p>Double-click Clozure CL to launch it. Clozure CL displays a Listener window:</p>
+
+      <div class="subtitle">
+        <img src="../images/listener1.jpg"alt="" 
+             border='0'/>
+      </div>
+
+      <p>Choose "New" from the "File" menu to create a new Lisp source
+      window. Save it with the name "CurrencyConverter.lisp" into the
+      same "currency-converter" folder where you saved your nibfile in
+      the earlier section. You should now have a "currency-converter"
+      folder that contains a "CurrencyConverter.lisp" item and a
+      "CurrencyConverter.nib" item.</p>
+
+      <p>Now you're ready to continue, and write the Lisp code that
+      implements the application's behavior.</p>
+
+    <div class="nav">
+      <p><a href="../../HOWTO.html">start</a>|<a href="building_ui.html">previous</a>|<a href="writing_lisp.html">next</a></p>
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/making_project.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/making_project.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/making_project.html	(revision 13309)
@@ -0,0 +1,60 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Creating a Project</h1>
+    </div>
+
+    <div class="section-head">
+      <h2>Example Files</h2>
+    </div>
+
+    <div class="body-text">
+      <p>This HOWTO is distributed with example files that include a
+      working <em>nibfile</em> (a file of user-interface objects,
+      named "CurrencyConverter.nib") and a Lisp source file (named
+      "CurrencyConverter.lisp"). You can build a working copy of the
+      example application by using these files, but you probably
+      shouldn't. If you want to understand how to build your own Lisp
+      application projects, you should follow the instructions here to
+      create your own source file and nibfile, and use the example
+      files only for reference in case something goes wrong.</p>
+    </div>
+
+    <div class="section-head">
+      <h2>Create the Project Folder</h2>
+    </div>
+
+    <div class="body-text">
+      <p>First, create a project folder to hold the files you are
+      going to create. When your project is complete, the folder will
+      contain a nibfile that defines the user interface, and
+      a Lisp source file that defines the behavior of the
+      application. Those two files are really all there is to a Lisp
+      application, though not all applications are as simple as this
+      currency converter. For more complex applications it makes sense
+      to split your UI into several nibfiles, and to split your
+      implementation into several source files. The basic principle
+      remains the same, however: nibfiles define your user interface,
+      and Lisp files define your application's behavior.</p>
+
+      <p>Create a folder somewhere convenient, and name it
+      "currency-converter". Next we will use Apple's InterfaceBuilder
+      application to create the user interface The next page tells you
+      how to do that; when you create your nibfile, save it into your
+      "currency-converter" folder.</p>
+
+    <div class="nav">
+      <p><a href="../../HOWTO.html">start</a>|<a href="building_ui.html">next</a></p>
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/writing_lisp.html
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/writing_lisp.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/pages/writing_lisp.html	(revision 13309)
@@ -0,0 +1,229 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>CurrencyConverter HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="../stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Writing the Lisp Source</h1>
+    </div>
+
+    <div class="body-text">
+      <p>In this section we'll write Lisp code that duplicates the
+      features provided by the Objective-C code in Apple's
+      tutorial. In Apple's tutorial, the explanation of the Objective
+      C code begins with the
+      section <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCTutorial/06Controller/chapter_6_section_1.html#//apple_ref/doc/uid/TP40000863-CH8-SW1">Bridging
+      the Model and View: The Controller</a>.</p>
+
+      <p>The Lisp code in this section of the HOWTO is considerably
+      simpler than the corresponding Objective-C code, in part
+      because we can ignore the conventions that XCode uses for
+      laying out source files. We can just write all our definitions
+      into a single Lisp source file, and load that file into Clozure CL
+      when we are ready to build the application.</p>
+
+    <div class="section-head">
+      <h2>First Things First</h2>
+    </div>
+
+    <div class="body-text">
+      <p>Place the following line at the top of your Lisp source file:</p>
+      
+      <pre>(in-package "CCL")</pre> 
+
+      <p>Clozure CL's Objective-C bridge code is defined in the "CCL"
+      package. Usually, when building an application, you'll create a
+      package for that application and import the definitions you need
+      to use. In order to keep the discussion short in this simple
+      example, we just place all our definitions in the "CCL"
+      package.</p>
+      
+    </div>
+    
+    <div class="section-head">
+      <h2>Defining the Converter Class</h2>
+    </div>
+    
+    <div class="body-text">
+      <p>We begin by defining the Converter class. Recall from Apple's
+        tutorial that this is the Model class that implements the
+        conversion between dollars and other currencies. Here is the
+        Lisp definition that implements the class you created in
+        InterfaceBuilder:</p>
+      
+      <pre>
+(defclass converter (ns:ns-object)
+  ()
+  (:metaclass ns:+ns-object))
+      </pre>    
+    </div>  
+
+    <div class="body-text">
+      <p>This is an ordinary CLOS class definition, with a couple of
+      simple wrinkles. First, the superclass it inherits from is the
+      NS-OBJECT class in the "NS" package. NS-OBJECT is an Objective-C
+      class, the ancestor of all Objective-C objects. This CLOS
+      definition actually creates a new Objective-C class named
+      "Converter".</p>
+
+      <p>We tell Clozure CL how to build the right kind of class object
+      by including the :METACLASS option in the definition:</p>
+
+      <pre>
+  (:metaclass ns:+ns-object)
+      </pre>    
+
+      <p>The Objective-C bridge knows that when the metaclass
+      is <code>ns:+ns-object</code>, it must lay out the class object
+      in memory as an Objective-C class, rather than a normal CLOS
+      STANDARD-CLASS.</p>
+
+      <p>Next, we define the method "convertCurrency:atRate:":</p>
+
+      <pre>
+(objc:defmethod (#/convertCurrency:atRate: :float) 
+    ((self converter) (currency :float) (rate :float))
+  (* currency rate))
+      </pre>
+
+      <p>This is the method that actually does the currency
+      conversion. It's a Lisp method that will be called when the
+      AppKit sends the Objective-C message "convertCurrency:atRate:"
+      It's very simple&mdash;really, it just multiples
+      <code>currency</code> times <code>rate</code>. Most of the text in the definition is
+      Objective-C bridge code that links the definition to the right
+      class with the right argument and return types.</p>
+
+      <p><code>objc:defmethod</code> is a version of DEFMETHOD that
+      creates methods that can execute in response to Objective-C
+      message-sends.</p>
+
+      <p>The syntax <code>#/convertCurrency:atRate:</code> uses the
+      "#/" reader macro to read a symbol with case preserved, so that
+      you can see in your code the same name that Objective-C uses for
+      the method, without worrying about how the name might be
+      converted between Lisp and Objective-C conventions.</p>
+
+      <p>The number of arguments to an Objective-C method is the
+      number of colons in the name, plus one. Each colon indicates an
+      argument, and there is always an extra "self" argument that
+      refers to the object that receives the message. These are normal
+      Objective-C conventions, but we perhaps need to emphasize the
+      details, since we are using Lisp code to call the Objective-C
+      methods.</p>
+
+      <p>We indicate the return type and the types of arguments in
+      the method definition by surrounding parameters and the method
+      name with parentheses, and appending the type name.</p> 
+
+      <p>Thus, for example, </p>
+
+      <pre>
+(#/convertCurrency:atRate: :float) 
+      </pre>
+
+      <p>means that the return type of the method is :FLOAT, and </p>
+
+      <pre>
+(self converter) 
+      </pre>
+
+      <p>means that the type of the receiving object is Converter.</p>
+      
+      <p>You will see these same conventions repeated in the next
+      section.</p>
+      </div>
+
+    <div class="section-head">
+      <h2>Defining the ConverterController Class</h2>
+    </div>
+
+    <div class="body-text">
+      <p>The previous section defined the Model class, Converter. All
+      we need now is a definition for the ConverterController
+      class. Recall from your reading of Apple's Tutorial that the
+      CurrencyConverter example uses the Model-View-Controller
+      paradigm. You used InterfaceBuilder to construct the
+      application's views. The Converter class provides the model
+      that represents application data. Now we define the controller
+      class, ConverterController, which connects the View and the
+      Model.</p>
+
+      <p>Here's the definition of the ConverterController class:</p>
+
+      <pre>
+(defclass converter-controller (ns:ns-object)
+  ((amount-field :foreign-type :id :accessor amount-field)
+   (converter :foreign-type :id :accessor converter)
+   (dollar-field :foreign-type :id :accessor dollar-field)
+   (rate-field :foreign-type :id :accessor rate-field))
+  (:metaclass ns:+ns-object))
+      </pre>
+      
+      <p>Once again we use the Objective-C bridge to define an
+      Objective-C class. This time, we provide several
+      instance-variable definitions in the class, and name accessors
+      for each of them explicitly. The <code>:FOREIGN-TYPE</code>
+      initargs enable us to specify the type of each field in the
+      foreign (Objective-C) class.</p>
+
+      <p>Each field in the definition of the ConverterController class
+      is an outlet that will be used to store a reference to one of
+      the text fields that you created in InterfaceBuilder. For
+      example, <code>amount-field</code> will be connected to the
+      "Amount" text field.</p>
+
+      <p>Why did we spell the name "amount-field" in Lisp code, and
+      "amountField" when creating the outlet in InterfaceBuilder?  The
+      Objective-C bridge automatically converts Lisp-style field names
+      (like "amount-field") to Objective-C-style field names (like
+      "amountField"), when handling class definitions.</p>
+
+      <p>The <code>converter</code> field at launch time contains a
+      reference to the Converter object, whose class definition is in
+      the previous section.</p>
+
+      <p>The final piece of the implementation is a definition of the
+      "convert:" method. This is the method that is called when a
+      user clicks the "Convert" button in the user interface.</p>
+
+      <pre>
+(objc:defmethod (#/convert: :void) ((self converter-controller) sender)
+  (declare (ignore sender))
+  (let* ((conv (converter self))
+         (dollar-field (dollar-field self))
+         (rate-field (rate-field self))
+         (amount-field (amount-field self))
+         (dollars (#/floatValue dollar-field))
+         (rate (#/floatValue rate-field))
+         (amount (#/convertCurrency:atRate: conv dollars rate)))
+    (#/setFloatValue: amount-field amount)
+    (#/selectText: rate-field self)))
+      </pre>
+
+      <p>Just as in the Apple example, this method reads the dollar
+      and rate values, and passes them to the
+      "convertCurrency:atRate:" method of the Converter class. It then
+      sets the text of the amount-field to reflect the result of the
+      conversion. The only significant difference between this
+      implementation and Apple's is that the code is written in Lisp
+      rather than Objective-C.</p>
+
+      <p>This completes the definition of the CurrencyConverter's
+      behavior. All that remains is to actually build the Cocoa
+      application. The next section shows how to do that.</p>
+
+    </div>
+
+    <div class="nav">
+      <p><a href="../../HOWTO.html">start</a>|<a href="create_lisp.html">previous</a>|<a href="build_app.html">next</a></p>
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/stylesheets/styles.css
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/stylesheets/styles.css	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/HOWTO_files/stylesheets/styles.css	(revision 13309)
@@ -0,0 +1,55 @@
+body {
+	background-color: white;
+	font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
+}
+
+.title {
+	text-align: center;
+	font-size: 16pt;
+}
+
+.subtitle {
+	font-size: medium;
+	font-weight: bold;
+	text-align: center;
+}
+
+.byline {
+	text-align: center;
+	font-weight: bold;
+	font-size: small;
+}
+
+.section-head {
+	padding-top: 2em;
+	padding-left: 1em;
+}
+
+.body-text {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 4em;
+	margin-right: 4em;
+	text-indent: 3em;
+}
+
+.note {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 6em;
+	margin-right: 6em;
+	text-indent: 0em;
+}
+
+.inline-image {
+	text-align: center;
+}
+
+.nav {
+	text-align: center;
+	font-size: large;
+	font-weight: bold;
+	padding-top: 4em;
+}
+
+li, pre {
+	text-indent: 0;
+}
Index: /branches/new-random/examples/cocoa/currency-converter/currency-converter.lisp
===================================================================
--- /branches/new-random/examples/cocoa/currency-converter/currency-converter.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/currency-converter/currency-converter.lisp	(revision 13309)
@@ -0,0 +1,54 @@
+(in-package "CCL")
+
+;;; define the classes referenced in the nibfile
+
+(defclass converter (ns:ns-object)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/convertCurrency:atRate: :float) 
+    ((self converter) (currency :float) (rate :float))
+  (* currency rate))
+
+(defclass converter-controller (ns:ns-object)
+  ((amount-field :foreign-type :id :accessor amount-field)
+   (converter :foreign-type :id :accessor converter)
+   (dollar-field :foreign-type :id :accessor dollar-field)
+   (rate-field :foreign-type :id :accessor rate-field))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/convert: :void) ((self converter-controller) sender)
+  (declare (ignore sender))
+  (let* ((conv (converter self))
+         (dollar-field (dollar-field self))
+         (rate-field (rate-field self))
+         (amount-field (amount-field self))
+         (dollars (#/floatValue dollar-field))
+         (rate (#/floatValue rate-field))
+         (amount (#/convertCurrency:atRate: conv dollars rate)))
+    (#/setFloatValue: amount-field amount)
+    (#/selectText: rate-field self)))
+
+
+
+
+#|
+"/Users/mikel/Valise/clozure/openmcl/example-code/currency-converter/CurrencyConverter.nib"
+
+building the app:
+
+(progn
+  (setf (current-directory) "/Users/mikel/Valise/clozure/openmcl/example-code/currency-converter/")
+  (load "currency-converter")
+  (require "build-application")
+  (ccl::build-application :name "CurrencyConverter"
+                          :main-nib-name "CurrencyConverter"
+			  :directory "/Users/mikel/Desktop/"
+                          :nibfiles '(#P"/usr/local/openmcl/trunk/ccl/examples/cocoa/currency-converter/CurrencyConverter.xib")))
+
+TODO NOTES:
+
+The name of the app in the main menu title is determined by the CFBundleName field in the
+InfoPlist.strings file in the English.lproj resources folder.
+
+|#
Index: /branches/new-random/examples/cocoa/easygui.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui.lisp	(revision 13309)
@@ -0,0 +1,8 @@
+(in-package :cl-user)
+
+(let ((path (or *load-pathname* *loading-file-source-file*)))
+  (load (merge-pathnames ";easygui;easygui.asd" path)))
+
+(asdf:operate 'asdf:load-op 'easygui)
+
+(push :easygui *features*)
Index: /branches/new-random/examples/cocoa/easygui/.cvsignore
===================================================================
--- /branches/new-random/examples/cocoa/easygui/.cvsignore	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*~.*
+*fsl
Index: /branches/new-random/examples/cocoa/easygui/action-targets.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/action-targets.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/action-targets.lisp	(revision 13309)
@@ -0,0 +1,17 @@
+(in-package :easygui)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; action/targets
+
+(defclass generic-easygui-target (ns:ns-object)
+     ((handler :initarg :handler :reader target-handler))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/activateAction :void) ((self generic-easygui-target))
+  (funcall (target-handler self)))
+
+(defmethod (setf action) (handler (view view))
+  (let ((target (make-instance 'generic-easygui-target
+                   :handler handler)))
+    (#/setTarget: (cocoa-ref view) target)
+    (#/setAction: (cocoa-ref view) (@selector #/activateAction))))
Index: /branches/new-random/examples/cocoa/easygui/dialogs.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/dialogs.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/dialogs.lisp	(revision 13309)
@@ -0,0 +1,56 @@
+(in-package :easygui)
+
+;;; Contributed to Clozure CL by AWSC, Feb 2009.
+;;; Permission is granted to use, redistribute, and modify.
+;;;
+;;; Provides some generally useful dialogs:
+;;;    y-or-n-dialog
+;;;    choose-file-dialog     (original from Gary Byers)
+;;;    choose-new-file-dialog (adapted from that)
+;;;    user-pick-color        (TODO: improve)
+;;; To use them you will probably want to set *debug-cocoa-calls* to NIL.
+
+(defun y-or-n-dialog (message)
+  (let ((alert (make-instance 'ns:ns-alert)))
+    (#/setMessageText: alert (ccl::%make-nsstring message))
+    (#/addButtonWithTitle: alert (ccl::%make-nsstring "Yes"))
+    (#/addButtonWithTitle: alert (ccl::%make-nsstring "No"))
+    (eql (#/runModal alert) #$NSAlertFirstButtonReturn)))
+
+(defvar *beepnsleep* t)
+
+(defun choose-file-dialog (&key directory file-types file button-string)
+  (gui::cocoa-choose-file-dialog :directory directory :file-types file-types :file file :button-string button-string))
+
+(defun choose-new-file-dialog (&key directory file-types file button-string)
+  (declare (ignore button-string))
+  (gui::cocoa-choose-new-file-dialog :directory directory :file-types file-types :file file))
+
+(defun cocoa-choose-directory-dialog (&key directory button-string)
+  (declare (ignore button-string))
+  (cocoa-choose-directory-dialog :directory directory))
+
+(objc:defmethod (#/NSWindowWillCloseNotification :void) ((self ns:ns-color-panel))
+  (dcc (#/stopModal (#/sharedApplication ns:ns-application))))
+  
+(defun user-pick-color (&key color (prompt "Pick a color") position)
+  "POSITION argument is provided only for Digitool MCL compatibility, it is ignored"
+  (declare (ignore position))
+  (gui::with-autorelease-pool 
+    (let* ((panel (dcc (#/sharedColorPanel ns:ns-color-panel)))) ; find or create the NSColorPanel
+      (dcc (#/setPickerMode: ns:ns-color-panel #$NSWheelModeColorPanel))
+      (dcc (#/setTitle: panel (ccl::%make-nsstring prompt)))
+      (dcc (#/addObserver:selector:name:object:                 ; observe yourself close but
+       (dcc (#/defaultCenter ns:ns-notification-center))        ; sadly confound OK & CANCEL
+       panel
+       (objc:\@selector #/NSWindowWillCloseNotification)
+       (ccl::%make-nsstring "NSWindowWillCloseNotification")
+       panel))
+      (when color (dcc (#/setColor: panel color)))
+      (dcc (#/runModalForWindow: (#/sharedApplication ns:ns-application) panel))
+      (dcc (#/removeObserver:name:object:                       ; prevent pileup
+       (dcc (#/defaultCenter ns:ns-notification-center))
+       panel
+       (ccl::%make-nsstring "NSWindowWillCloseNotification")
+       panel))
+      (dcc (#/retain (dcc (#/color panel)))))))
Index: /branches/new-random/examples/cocoa/easygui/easygui.asd
===================================================================
--- /branches/new-random/examples/cocoa/easygui/easygui.asd	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/easygui.asd	(revision 13309)
@@ -0,0 +1,38 @@
+;;; -*- lisp -*-
+
+#+openmcl
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :asdf))
+
+#-openmcl
+(error "Requires OpenMCL")
+
+
+(cl:defpackage :easygui-system (:use :cl :asdf))
+
+(in-package :easygui-system)
+
+(defsystem cocoa.asd)
+
+(defmethod perform :after ((o compile-op) (sys (eql (find-system :cocoa.asd))))
+  (require :cocoa))
+
+(defmethod operation-done-p ((o compile-op) (sys (eql (find-system :cocoa.asd))))
+  nil)
+
+(defsystem easygui
+  :depends-on (cocoa.asd)
+  :components ((:file "package")
+               (:file "new-cocoa-bindings" :depends-on ("package"))
+               (:file "events" :depends-on ("new-cocoa-bindings"))
+               (:file "rgb" :depends-on ("package"))
+               (:file "views" :depends-on ("events"))
+               (:file "action-targets" :depends-on ("views"))
+               (:file "dialogs" :depends-on ("new-cocoa-bindings"))
+               (:module "example"
+                        :depends-on ("action-targets" "dialogs" "rgb")
+                        :components
+                        ((:file "tiny")
+                         (:file "currency-converter")
+                         (:file "view-hierarchy")
+                         (:file "extended-demo")))))
Index: /branches/new-random/examples/cocoa/easygui/events.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/events.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/events.lisp	(revision 13309)
@@ -0,0 +1,82 @@
+(in-package :easygui)
+
+;;; Changed by AWSC (arthur.cater@ucd.ie) Feb 2009:
+;;; Modified define-chaining-responder-method to allow subclasses of easygui
+;;; views to inherit mouse handling behaviour.
+;;; Changed by AWSC Apr 2009:
+;;; Modified define-chaining-responder-method to bind *modifier-key-pattern*
+;;; when Lisp mouse handlers are being called.
+;;; The original work I changed is by an unknown author.
+;;; Permission to use disseminate and further modify these changes is granted.
+
+;;; Event handling basics
+
+(defvar *modifier-key-pattern*)
+
+(defmacro define-chaining-responder-method (class-name
+                                            (objc-name lisp-name)
+                                            (self-arg event-arg)
+                                            &body arg-compute-forms)
+  `(objc:defmethod (,objc-name :void) ((,self-arg ,class-name)
+                                       ,event-arg)
+     (let ((superclasses (ccl:class-precedence-list (class-of (easygui-view-of ,self-arg)))))
+       (if (some #'(lambda (super)
+                     (find-method #',lisp-name nil (list (class-name super)) nil))
+                 superclasses)
+           (let ((*modifier-key-pattern* (#/modifierFlags ,event-arg)))
+             (,lisp-name (easygui-view-of ,self-arg)
+                         ,@arg-compute-forms))
+           (,objc-name (#/nextResponder ,self-arg) ,event-arg)))))
+
+(defmacro define-useful-mouse-event-handling-routines (class-name)
+  `(progn
+     (define-chaining-responder-method ,class-name
+         (#/mouseDown: mouse-down) (self event)
+       :cocoa-event event
+       :location (let ((objc-pt (#/convertPoint:fromView:
+                                 self
+                                 (#/locationInWindow event)
+                                 nil)))
+                   (point (ns:ns-point-x objc-pt) (ns:ns-point-y objc-pt)))
+       :button (#/buttonNumber event)
+       :click-count (#/clickCount event)
+       :delta (point (#/deltaX event) (#/deltaY event)))
+     (define-chaining-responder-method ,class-name
+         (#/mouseUp: mouse-up) (self event)
+       :cocoa-event event
+       :location (let ((objc-pt (#/convertPoint:fromView:
+                                 self
+                                 (#/locationInWindow event)
+                                 nil)))
+                   (point (ns:ns-point-x objc-pt) (ns:ns-point-y objc-pt)))
+       :button (#/buttonNumber event)
+       :click-count (#/clickCount event)
+       :delta (point (#/deltaX event) (#/deltaY event)))
+     (define-chaining-responder-method ,class-name
+         (#/mouseDragged: mouse-dragged) (self event)
+       :cocoa-event event
+       :location (let ((objc-pt (#/convertPoint:fromView:
+                                 self
+                                 (#/locationInWindow event)
+                                 nil)))
+                   (point (ns:ns-point-x objc-pt) (ns:ns-point-y objc-pt))))))
+
+;;; Mouse:
+
+(defclass event-handler-mixin () ())
+
+(defclass mouse-event-handler-mixin () ())
+
+
+(macrolet ((defgeneric-and-empty-method (name (&rest args) &rest options)
+               `(defgeneric ,name ,args
+                  ,@options
+                  (:method ,args
+                    (declare (ignore ,@(remove-if (lambda (sym) (member sym lambda-list-keywords)) args)))))))
+  ;; TODO: mouse-move
+  (defgeneric-and-empty-method mouse-down (view &key cocoa-event location button
+                                                click-count delta))
+  (defgeneric-and-empty-method mouse-up (view &key cocoa-event location button
+                                              click-count delta))
+  (defgeneric-and-empty-method mouse-dragged (view &key cocoa-event location
+                                                   delta)))
Index: /branches/new-random/examples/cocoa/easygui/example/currency-converter.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/example/currency-converter.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/example/currency-converter.lisp	(revision 13309)
@@ -0,0 +1,41 @@
+(in-package :easygui-demo)
+
+(defclass converter-window (window)
+   ()
+   (:default-initargs :size (point 383 175)
+     :position (point 125 513)
+     :title "Currency Converter"
+     :resizable-p nil
+     :minimizable-p t))
+
+(defmethod initialize-view :after ((cw converter-window))
+  (let ((currency-form (make-instance 'form-view
+                          :autosize-cells-p t
+                          :interline-spacing 9.0
+                          :position (point 15 70)                          
+                          :size (point 353 90)))
+        (convert-button (make-instance 'push-button-view
+                           :default-button-p t
+                           :text "Convert"
+                           :position (point 247 15)))
+        (line (make-instance 'box-view
+                 :position (point 15 59)
+                 :size (point 353 2))))
+    (setf (action convert-button)
+          #'(lambda ()
+              (let ((exchange-rate (read-from-string
+                                    (entry-text currency-form 1) nil nil))
+                    (amount (read-from-string (entry-text currency-form 0)
+                                              nil nil)))
+                (when (and (numberp exchange-rate) (numberp amount))
+                  (setf (entry-text currency-form 2)
+                        (prin1-to-string (* exchange-rate amount)))))))
+    (setf (editable-p (car (last (add-entries currency-form
+                                              "Exchange Rate per $1:"
+                                              "Dollars to Convert:"
+                                              "Amount in other Currency:"))))
+          nil)
+    (add-subviews cw currency-form line convert-button)
+    (window-show cw)))
+
+;(make-instance 'converter-window)
Index: /branches/new-random/examples/cocoa/easygui/example/extended-demo.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/example/extended-demo.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/example/extended-demo.lisp	(revision 13309)
@@ -0,0 +1,316 @@
+(in-package :easygui-demo)
+
+; ---------------
+; Demo for the new control types for EasyGui within Clozure CL
+; Contributed March 2009 by AWSC (arthur.cater@ucd.ie)
+; based upon earlier work by an unknown author.
+; Permission is given to disseminate, use, and modify.
+; No warranty is expressed or implied.
+;
+; Tested in cclv1.2 on 32-bitPPC, in cclv1.3 on 32-bitPPC and 64-bitIntel Macs.
+; Tested only in images constructed using (require :cocoa-application).
+
+(setf easygui::*debug-cocoa-calls* nil)
+
+(defclass view-hierarchy-demo-window (window)
+     ((with :initarg :with :initform :button)
+      (textbox :initarg :textbox :initform nil :accessor demo-textbox))
+  (:default-initargs :size (point 480 270)
+    :position (point 125 513)
+    :resizable-p nil
+    :minimizable-p t
+    :title "View tree demo")
+  (:documentation "Shows a window with a simple view hierarchy and one or more controls
+ that manipulate this hierarchy."))
+
+(defclass brown-drawing-view (drawing-view) ())
+
+(defmethod draw-view-rectangle ((drawing brown-drawing-view) rectangle)
+  (declare (ignore rectangle))
+  (let* ((cocoa-view (cocoa-ref drawing))
+         (rect (dcc (#/bounds cocoa-view)))
+         (brown (dcc (#/brownColor ns:ns-color))))
+    (with-focused-view cocoa-view
+      (dcc (#/setFill brown))
+      (dcc (#_NSRectFill rect)))))
+         
+(defmethod initialize-view :after ((w view-hierarchy-demo-window))
+  (let (left-box right-box button left-button right-button checkbox popup pulldown slider
+        drawing text (leftp t)
+        (normalfont (gui::default-font :name "Monaco" :size 10.0 :attributes nil))
+        (shoutfont (gui::default-font :name "Courier" :size 36.0 :attributes '(:bold :italic))))
+    (labels ((to-left ()
+               (retaining-objects (text)
+                 (cond ((not leftp)
+                        (remove-subviews right-box text)
+                        (add-subviews left-box text))))
+               (setf leftp t))
+            (to-right ()
+             (retaining-objects (text)
+                (cond (leftp
+                       (remove-subviews left-box text)
+                       (add-subviews right-box text))))
+             (setf leftp nil))
+            (to-other ()
+             (retaining-objects (text)
+                (cond ((not leftp)
+                       (remove-subviews right-box text)
+                       (add-subviews left-box text))
+                      (leftp
+                       (remove-subviews left-box text)
+                       (add-subviews right-box text))))
+             (setf leftp (not leftp)))
+            (generate-menu-items ()
+              (list (make-instance 'menu-item-view :title "Left" :action #'to-left)
+                    (make-instance 'menu-item-view :title "Right" :action #'to-right)
+                    (make-instance 'menu-item-view :title "Other" :action #'to-other)
+                    (make-instance 'pop-up-menu :title "Text Options"
+                      :menu-items
+                      (list (make-instance 'menu-item-view :title "Oink"
+                              :action #'(lambda () (setf (view-font text) normalfont)
+                                                   (setf (view-text text) "Oink!")
+                                                   (setf (view-size text) (point 60 20))
+                                                   (setf (view-position text) (point 37 112))))
+                            (make-instance 'menu-item-view :title "SHOUT!"
+                              :action #'(lambda () (setf (view-font text) shoutfont)
+                                                   (setf (view-text text) "HEY!")
+                                                   (setf (view-size text) (point 160 60))
+                                                   (setf (view-position text) (point 17 10))))
+                            (make-instance 'pop-up-menu :title "Whisper"
+                              :menu-items
+                              (list (make-instance 'menu-item-view :title "sh!"
+                                      :action #'(lambda () (setf (view-font text) normalfont)
+                                                           (setf (view-text text) "sh!")))
+                                    (make-instance 'menu-item-view :title "psst!"
+                                      :action #'(lambda () (setf (view-font text) normalfont)
+                                                           (setf (view-text text) "psst!"))))))))))
+      (setf left-box (make-instance 'box-view
+                       :position (point 17 51)
+                       :size (point 208 199)
+                       :title "Left"
+                       :tip #'(lambda nil (unless leftp "The occupied box has no tooltip"))
+                       :view-nick-name :leftbox)
+            right-box (make-instance 'box-view
+                        :position (point 255 51)
+                        :size (point 208 199)
+                        :tip #'(lambda nil (if leftp "The occupied box has no tooltip"))
+                        :title "Right"
+                        :view-nick-name :rightbox)
+            button (make-instance 'push-button-view
+                       :position (point 173 12)
+                       :text "Change side"
+                       :tip #'(lambda nil "Button tip does not work!")
+                       :view-nick-name :push-button
+                       :action #'to-other)
+            left-button (make-instance 'radio-button-view
+                          :position (point 103 12)
+                          :text "Left side"
+                          :selected t
+                          :view-nick-name :leftbutton
+                          :tip #'(lambda nil (format nil
+                                                       "Where's the amazing tooltip?~%The text is in the box on the ~:[right~;left~]"
+                                                       leftp))
+                          :action #'to-left)
+            right-button (make-instance 'radio-button-view
+                           :position (point 243 12)
+                           :text "Right side"
+                           :view-nick-name :rightbutton
+                           :tip #'(lambda nil (format nil
+                                                        "Where's the amazing tooltip?~%The text is in the box on the ~:[right~;left~]"
+                                                        leftp))
+                   
+                           :action #'to-right)
+            checkbox (make-instance 'check-box-view
+                       :position (point 173 12)
+                       :text "Right side"
+                       :view-nick-name :checkbox
+                       :tip #'(lambda nil (format nil
+                                                    "Where's the amazing tooltip?~%The text is in the box on the ~:[right~;left~]"
+                                                    leftp))
+                       :action #'to-other)
+            popup (make-instance 'pop-up-menu
+                   :position (point 173 12)
+                   :size (point 120 24)
+                   :title "Command?"
+                   :tip #'(lambda nil (format nil "Pop up menus can have tooltips,~%however their menu items cannot."))
+                   :view-nick-name :pop-up-menu
+                   :menu-items (generate-menu-items))
+            pulldown (make-instance 'pull-down-menu
+                   :position (point 173 12)
+                   :size (point 120 24)
+                   :title "Command?"
+                   :tip #'(lambda nil (format nil "Pull down menus can have tooltips,~%however their menu items cannot."))
+                   :view-nick-name :pull-down-menu
+                   :menu-items (generate-menu-items))
+            drawing (make-instance 'brown-drawing-view
+                   :position (point 173 12)
+                   :size (point 120 24)
+                   :view-nick-name :drawing
+                   :tip #'(lambda nil (format nil
+                                                "See the amazing tooltip!~%The text is in the box on the ~:[right~;left~]"
+                                                leftp))
+                   :mouse-down #'(lambda (view &key &allow-other-keys)
+                                   (declare (ignore view))
+                                   (if (shift-key-p) (to-left) (to-other))))
+            text (make-instance 'static-text-view
+                   :text "Oink!"
+                   :view-font normalfont
+                   :tip :identify
+                   :position (point 37 112)
+                   :size (point 60 20)
+                   :fore-color (make-rgb :red 0 :green 0 :blue 255)
+                   :back-color (make-rgb :red 255 :green 220 :blue 200))
+            slider (make-instance 'slider-view :min-value 0 :max-value 1
+                     ;            :text "How right"   ;; No provision for title or text?
+                     :position (point 173 12) :size (point 136 24)
+                     :view-nick-name :slider
+                     :tip #'(lambda nil (format nil
+                                                "See the amazing tooltip!~%The text is in the box on the ~:[right~;left~]"
+                                                leftp))
+                     :action #'(lambda ()
+                                 (if (> (dcc (#/floatValue (cocoa-ref slider))) 0.5)
+                                   (to-right)
+                                   (to-left)))))
+      (add-subviews w left-box right-box)
+      (case (slot-value w 'with)
+        (:button (add-subviews w button))
+        (:radio (add-subviews w left-button right-button))
+        (:check (add-subviews w checkbox))
+        (:popup  (add-subviews w popup))
+        (:pulldown (add-subviews w pulldown))
+        (:slider (add-subviews w slider))
+        (:drawing (add-subviews w drawing))
+        (otherwise (format t "~&** The WITH slot is ~s, it must be either :BUTTON :RADIO :CHECK :POPUP ~
+                           :PULLDOWN :DRAWING or :SLIDER~%"
+                           (slot-value w 'with))))
+      (add-subviews left-box text)
+      (setf (demo-textbox w) text)
+      (add-contextual-menu w
+                           (make-instance 'contextual-menu
+                             :menu-items (generate-menu-items))
+                           t)
+      (window-show w))))
+
+(defparameter *w nil)
+
+(defparameter *run-file-chooser-anyway* nil)
+
+(defvar *closing-under-program-control* nil
+"Used in demonstrating tailored window-closing behaviour.")
+ 
+(defmethod window-may-close ((w view-hierarchy-demo-window))
+  (or *closing-under-program-control*
+      (when (y-or-n-dialog "Do you really want to close the window like this?")
+        (setf *w nil)
+        t)))
+
+(defun run-demo ()
+  (flet ((example (with)
+           (when *w (let ((*closing-under-program-control* t)) (perform-close *w)))
+           (setf *w (make-instance 'view-hierarchy-demo-window :with with))))
+    (dolist (spec `(("Did you know?" "Contextual Menus"        ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know there are contextual menus ~
+                                                                                       available - in many but not all places - ~
+                                                                                       when you press control-click?"))))
+                    ("Did you know?" "New TOOLS item"          ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know there is a \"Choose Color\" ~
+                                                                                       item added to the TOOLS menu?~%
+                                                                                       (Sadly however there is no keyboard ~
+                                                                                       shortcut for it and it simply prints the ~
+                                                                                       chosen color in the console window.)"))))
+                    ("Did you know?" "Tooltips"                ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that some sorts of view ~
+                                                                                       have tooltips attached?~%~
+                                                                                       (Sadly however some do not work as intended.)~%~
+                                                                                       These may be fixed strings, dynamically ~
+                                                                                       generated strings, or cocoa descriptions."))))
+                    ("Did you know?" "Choose File menu items (not working)"
+                                                               ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that there are items in the File menu ~
+                                                                                       and in the Easygui Demo menu that let you use a ~
+                                                                                       Choose-File-Dialog? Sadly however they do not work properly ~
+                                                                                       right now and will probably crash your CCL session. ~
+                                                                                       If you want to go ahead anyway, first select the ~
+                                                                                       \"Run File Chooser Anyway\" item."))))
+                    ("Did you know?" "Flipped screen mode"     ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that it is possible to position windows ~
+                                                                                       and items within them as if screen coordinates had their ~
+                                                                                       origin at screen top-left, as in Digitool's MCL?"))))
+                    ("Did you know?" "Cocoa tracing"           ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that debugging messages can be ~
+                                                                                       produced when Cocoa calls are made? ~
+                                                                                       This relies on the DCC macro being used conscientiously, ~
+                                                                                       it is not automatic."))))
+                    ("Did you know?" "Font and Color support"  ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that there is some limited support for ~
+                                                                                       handling text fonts and colors and backgrounds? ~
+                                                                                       Try out the \"SHOUT!\" options in a demo window menu."))))
+                    ("Did you know?" "Window Close behaviour"  ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that windows can be made to invoke Lisp ~
+                                                                                       code when they are told to close? The primary method ~
+                                                                                       for Window-Should-Close decides whether the window ~
+                                                                                       should close or not, before- and after-methods could ~
+                                                                                       be used for other purposes. The Demo Window behaves ~
+                                                                                       differently when you close the window as part of ~
+                                                                                       creating a new one, and when you press its close button."))))
+                    ("Give Example" "With Button"              ,#'(lambda nil (example :button)))
+                    ("Give Example" "With Radio Buttons"       ,#'(lambda nil (example :radio)))
+                    ("Give Example" "With Checkbox"            ,#'(lambda nil (example :check)))
+                    ("Give Example" "With Popup Menu"          ,#'(lambda nil (example :popup)))
+                    ("Give Example" "With Pulldown Menu"       ,#'(lambda nil (example :pulldown)))
+                    ("Give Example" "With Drawing"             ,#'(lambda nil (example :drawing)))
+                    ("Give Example" "With Slider"              ,#'(lambda nil (example :slider)))
+                    ("Flipping" "New windows are flipped"      ,#'(lambda nil (setf *screen-flipped* t)))
+                    ("Flipping" "New windows are not flipped"  ,#'(lambda nil (setf *screen-flipped* nil)))
+                    ("Tracing" "Cocoa Calls are traced"        ,#'(lambda nil (setf easygui::*debug-cocoa-calls* t)))
+                    ("Tracing" "Cocoa Calls are not traced"    ,#'(lambda nil (setf easygui::*debug-cocoa-calls* nil)))
+                    ("Color Picker" "Text"                     ,#'(lambda nil
+                                                                    (cl-user::process-run-function "Pick color for text in box"
+                                                                     #'(lambda nil
+                                                                         (gui::with-autorelease-pool
+                                                                             (let* ((textbox (if *w (demo-textbox *w)))
+                                                                                    (color (if textbox
+                                                                                             (get-fore-color textbox)
+                                                                                             (make-rgb :red 0 :green 0 :blue 255))))
+                                                                               (setf color (user-pick-color :color color
+                                                                                              :prompt "Pick a text color"))
+                                                                               (when textbox
+                                                                                 (set-fore-color textbox color)
+                                                                                 (invalidate-view textbox))))))))
+                    ("Color Picker" "Background"               ,#'(lambda nil
+                                                                    (cl-user::process-run-function "Pick color for text in box"
+                                                                     #'(lambda nil
+                                                                         (gui::with-autorelease-pool
+                                                                             (let* ((textbox (if *w (demo-textbox *w)))
+                                                                                    (color (if textbox
+                                                                                             (get-back-color textbox)
+                                                                                             (make-rgb :red 255 :green 220 :blue 200))))
+                                                                               (setf color (user-pick-color :color color
+                                                                                              :prompt "Pick a background color"))
+                                                                               (when textbox
+                                                                                 (set-back-color textbox color t))))))))
+                    ("Destroy this menu"                       ,#'(lambda nil (remove-topbar-item (list "Easygui Demo"))))
+                    ("Run File Chooser Anyway"                 ,#'(lambda nil (setf *run-file-chooser-anyway* t)))
+                    ("File" "Get a pathname"                   ,#'(lambda nil
+                                                                    (when *run-file-chooser-anyway*
+                                                                      (print "Getting a pathname(Easygui Demo Menu)...doomed to failure!")
+                                                                      (choose-file-dialog :button-string "Get a pathname(EG)"))))))
+      (add-topbar-item (cons "Easygui Demo" (butlast spec)) (first (last spec))))
+    (add-topbar-item '("Tools" "Choose Color")                 #'(lambda nil
+                                                                   (print (user-pick-color))))
+    (add-topbar-item '("File" "Get a pathname")                #'(lambda nil
+                                                                   (when *run-file-chooser-anyway*
+                                                                     (running-on-main-thread ()
+                                                                       (print "Getting a pathname(File Menu)...doomed to failure")
+                                                                       (print (choose-file-dialog :button-string "Get a pathname(FILE)"))))))
+    (y-or-n-dialog "Have you spotted the new \"Easygui Demo\" item in the menubar?")))
+
+; (easygui-demo::run-extended-demo)
Index: /branches/new-random/examples/cocoa/easygui/example/tiny.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/example/tiny.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/example/tiny.lisp	(revision 13309)
@@ -0,0 +1,62 @@
+;;; Another example:
+;;; This one creates a full-window view and draws in it.
+;;; This is the easygui equivalent of examples/cocoa/tiny.lisp.
+
+(in-package :easygui-demo)   ; In user code, this might be easygui-user
+
+(defclass tiny-demo-drawing-view (drawing-view) ()
+  (:default-initargs :accept-key-events-p t))
+
+(defconstant short-pi (coerce pi 'short-float))
+(defparameter numsides 12)
+
+(defmethod draw-view-rectangle ((view tiny-demo-drawing-view) rectangle)
+  (declare (ignore rectangle))
+  (let* ((view (cocoa-ref view))
+         (bounds (#/bounds view))
+         (width (ns:ns-rect-width bounds))
+         (height (ns:ns-rect-height bounds)))
+    (macrolet ((X (tt) `(* (1+ (sin ,tt)) width 0.5))
+               (Y (tt) `(* (1+ (cos ,tt)) height 0.5)))
+      ;; Fill the view with white
+      (#/set (#/whiteColor ns:ns-color))
+      ;; Trace two polygons with N sides and connect all of the vertices 
+      ;; with lines
+      (#/set (#/blackColor ns:ns-color))
+      (loop 
+        for f from 0.0 below (* 2 short-pi) by (* 2 (/ short-pi numsides))
+        do (loop 
+             for g from 0.0 below (* 2 short-pi) by (* 2 (/ short-pi numsides))
+             do (#/strokeLineFromPoint:toPoint:
+                                      ns:ns-bezier-path
+                                      (ns:make-ns-point (X f) (Y f))
+                                      (ns:make-ns-point (X g) (Y g))))))))
+
+(defclass tiny-demo-window (window) ()
+  (:default-initargs :size (point 400 400)
+    :position (point 100 350)
+    :title "Tiny rectangle drawing demo"
+    :resizable-p nil
+    :minimizable-p t))
+
+(defmethod initialize-view :after ((window tiny-demo-window))
+  (let ((draw-view (make-instance 'tiny-demo-drawing-view)))
+    (setf (content-view window) draw-view)
+    (window-show window)))
+
+;;; Mouse handling:
+;;; (Drag up to increase number of points, down to decrease)
+(defvar *original-point* nil)
+
+(defmethod mouse-down ((view tiny-demo-drawing-view) &key location
+                       &allow-other-keys)
+  (setf *original-point* location))
+
+(defmethod mouse-up ((view tiny-demo-drawing-view) &key location
+                     &allow-other-keys)
+  (when *original-point*
+    (cond ((> (point-y location) (point-y *original-point*))
+           (incf numsides))
+          ((< (point-y location) (point-y *original-point*))
+           (decf numsides)))
+    (redisplay view)))
Index: /branches/new-random/examples/cocoa/easygui/example/view-hierarchy.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/example/view-hierarchy.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/example/view-hierarchy.lisp	(revision 13309)
@@ -0,0 +1,43 @@
+(in-package :easygui-user)
+
+(defclass view-hierarchy-demo-window (window)
+     ()
+  (:default-initargs :size (point 480 270)
+    :position (point 125 513)
+    :resizable-p nil
+    :minimizable-p t
+    :title "View tree demo")
+  (:documentation "Shows a window with a simple view hierarchy and a button
+action that manipulates this hierarchy."))
+
+(defmethod initialize-view :after ((w view-hierarchy-demo-window))
+  (let ((left-box (make-instance 'box-view
+                     :position (point 17 51)
+                     :size (point 208 199)
+                     :title "Left"))
+        (right-box (make-instance 'box-view
+                      :position (point 255 51)
+                      :size (point 208 199)
+                      :title "Right"))
+        (swap-button (make-instance 'push-button-view
+                        :position (point 173 12)
+                        :text "Switch sides"))
+        (text (make-instance 'static-text-view
+                 :text "Oink!"
+                 :position (point 37 112)))
+        (leftp t))
+    (setf (action swap-button)
+          (lambda ()
+            (retaining-objects (text)
+              (cond (leftp
+                     (remove-subviews left-box text)
+                     (add-subviews right-box text))
+                    (t
+                     (remove-subviews right-box text)
+                     (add-subviews left-box text))))
+            (setf leftp (not leftp))))
+    (add-subviews w left-box right-box swap-button)
+    (add-subviews left-box text)
+    (window-show w)))
+
+;;; (make-instance 'view-hierarchy-demo-window)
Index: /branches/new-random/examples/cocoa/easygui/new-cocoa-bindings.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/new-cocoa-bindings.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/new-cocoa-bindings.lisp	(revision 13309)
@@ -0,0 +1,162 @@
+(in-package :easygui)
+
+;;; Helper types:
+
+;;; point:
+(defclass eg-point ()
+     ((x :initarg :x :reader point-x)
+      (y :initarg :y :reader point-y)))
+
+(defun point (x y)
+  (assert (>= x 0))
+  (assert (>= y 0))
+  (make-instance 'eg-point :x x :y y))
+
+(defmethod print-object ((o eg-point) s)
+  (print-unreadable-object (o s :identity nil :type t)
+    (format s "(~,2,F/~,2,F)" (point-x o) (point-y o))))
+
+;;; range:
+(defclass eg-range ()
+     ((start :initarg :start :reader range-start)
+      (end :initarg :end :reader range-end)))
+
+(defun range (start end)
+  (assert (>= end start))
+  (make-instance 'eg-range :start start :end end))
+
+(defun range-nsrange (range)
+  (ns:make-ns-range (range-start range) (range-end range)))
+
+(defclass eg-rectangle ()
+     ((x :initarg :x :reader rectangle-x)
+      (y :initarg :y :reader rectangle-y)
+      (width :initarg :width :reader rectangle-width)
+      (height :initarg :height :reader rectangle-height)))
+
+(defun rectangle (x y width height)
+  (assert (>= x 0))
+  (assert (>= y 0))
+  (assert (>= width 0))
+  (assert (>= height 0))
+  (make-instance 'eg-rectangle :x x :y y :width width :height height))
+
+(defun rectangle-nsrect (r)
+  (ns:make-ns-rect (rectangle-x r) (rectangle-y r)
+                   (rectangle-width r) (rectangle-height r)))
+
+(defun nsrect-rectangle (r)
+  (rectangle (ns:ns-rect-x r) (ns:ns-rect-y r)
+             (ns:ns-rect-width r) (ns:ns-rect-height r)))
+
+;;; Base class for all Cocoa-based Easygui objects:
+(defclass easy-cocoa-object ()
+     ((ref :initarg :cocoa-ref)
+      (ref-valid-p :initform t :accessor cocoa-ref-valid-p)))
+
+(defgeneric cocoa-ref (eg-object)
+  (:method ((eg-object easy-cocoa-object))
+     (if (cocoa-ref-valid-p eg-object)
+         (slot-value eg-object 'ref)
+         (error "Attempting to access an invalidated Cocoa object on ~A!"
+                eg-object))))
+  
+(defgeneric (setf cocoa-ref) (new eg-object)
+  (:method (new (eg-object easy-cocoa-object))
+     (setf (cocoa-ref-valid-p eg-object) t
+	   (slot-value eg-object 'ref) new)))
+
+(defvar *window-position-default-x* 200)
+(defvar *window-position-default-y* 200)
+(defvar *window-size-default-x* 200)
+(defvar *window-size-default-y* 200)
+
+(defun ns-rect-from-points (posn size)
+  (ns:make-ns-rect (point-x posn) (point-y posn)
+                   (point-x size) (point-y size)))
+
+(defparameter *flag-to-mask-alist*
+              `( ;; (:zoomable-p . #$NSZoomableWindowMask) ; doesn't work
+                (:minimizable-p . ,#$NSMiniaturizableWindowMask)
+                (:resizable-p . ,#$NSResizableWindowMask)
+                (:closable-p . ,#$NSClosableWindowMask)))
+
+(defun flag-mask (keyword enabled-p)
+  (if enabled-p
+      (or (cdr (assoc keyword *flag-to-mask-alist*)) 0)
+      0))
+
+(defparameter *key-to-mask-alist*
+              `((:control . ,#$NSControlKeyMask)
+                (:alt     . ,#$NSAlternateKeyMask)
+                (:command . ,#$NSCommandKeyMask)))
+
+(defun key-mask (keyword)
+  (or (cdr (assoc keyword *key-to-mask-alist*)) 0))
+
+;;; Memory management helpers:
+
+(defmacro maybe-invalidating-object ((eg-object) &body body)
+  `(if (= 1 (#/retainCount (cocoa-ref ,eg-object)))
+       (multiple-value-prog1 (progn ,@body)
+                             (setf (cocoa-ref-valid-p ,eg-object) nil))
+       (progn ,@body)))
+
+(defmethod retain-object ((o easy-cocoa-object))
+  (#/retain (cocoa-ref o)))
+
+(defmethod release-object ((o easy-cocoa-object))
+  (#/release (cocoa-ref o)))
+
+(defmacro retaining-objects ((&rest eg-objects) &body body)
+  "Retains EG-OBJECTS, runs BODY forms and releases them after control
+has left BODY."
+  (let ((objects (gensym)))
+    `(let ((,objects (list ,@eg-objects)))
+       (mapc #'retain-object ,objects)
+       (unwind-protect (progn ,@body)
+         (mapc #'release-object ,objects)))))
+
+;;; debug macro for #/ funcalls:
+
+(defvar *debug-cocoa-calls* nil)
+;; Default changed to NIL by arthur, March 2009
+
+(defparameter *cocoa-pause* nil
+"When *debug-cocoa-calls* is not NIL, then a numeric value of *cocoa-pause* causes
+some sleep after every message produced by the DCC macro. Useful if something is
+causing a crash. During development it happened to me :-(")
+
+(defmacro dcc (form)
+;; Trace output identifies process, and may pause: arthur, March 2009
+  `(progn
+     (when *debug-cocoa-calls*
+       (format *trace-output* "[~a]Calling ~A on ~S~%"
+               (ccl::process-serial-number ccl::*current-process*) ',(first form) (list ,@(rest form)))
+       (when (and *cocoa-pause* (numberp *cocoa-pause*)) (sleep *cocoa-pause*)))
+     ,form))
+
+;;; Running things on the main thread:
+
+(defclass cocoa-thunk (ns:ns-object)
+     ((thunk :accessor thunk-of))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/run :void) ((self cocoa-thunk))
+  (funcall (thunk-of self)))
+
+(defun run-on-main-thread (waitp thunk)
+  (let ((thunk* (make-instance 'cocoa-thunk)))
+    (setf (thunk-of thunk*) thunk)
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     thunk*
+     (@selector #/run)
+     +null-ptr+
+     (not (not waitp)))))
+
+(defmacro running-on-main-thread ((&key (waitp t)) &body body)
+  `(run-on-main-thread ,waitp (lambda () ,@body)))
+
+;;; Getting views from objc objects:
+
+(defgeneric easygui-view-of (cocoa-view))
Index: /branches/new-random/examples/cocoa/easygui/package.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/package.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/package.lisp	(revision 13309)
@@ -0,0 +1,58 @@
+(cl:defpackage :easygui
+  (:use :cl)
+  (:import-from :ccl with-autorelease-pool @selector lisp-string-from-nsstring +null-ptr+)
+  (:export #:point #:ns-point-from-point #:range #:rectangle #:window
+           #:point-x #:point-y #:rectangle-x #:rectangle-y #:rectangle-width
+           #:rectangle-height
+           ;; cocoa stuff
+           #:retain-object #:release-object #:retaining-objects
+           ;; view classes
+           #:view #:static-text-view #:text-input-view #:password-input-view
+           #:push-button-view
+           #:form-view #:form-cell-view #:box-view #:drawing-view #:slider-view
+           #:check-box-view #:radio-button-view
+           #:menu-item-view #:pop-up-menu #:pull-down-menu #:contextual-menu 
+           ;; event methods
+           #:mouse-down #:mouse-dragged #:mouse-up  #:view-key-event-handler
+           ;; operators
+           #:cocoa-ref
+           #:add-subviews #:remove-subviews #:view-subviews
+           #:window-show #:set-window-title
+           #:content-view #:view-container
+           #:initialize-view #:action #:view-text
+           #:add-entry #:add-entries #:editable-p
+           #:draw-view-rectangle
+           #:entry-text #:cell-count #:nth-cell #:selection #:redisplay
+           #:string-value-of #:integer-value-of #:float-value-of
+           #:double-value-of
+           #:view-named #:view-nick-name
+           #:view-size view-position
+           #:view-mouse-position
+           #:view-font #:with-focused-view
+           #:clear-page
+           #:check-box-check #:check-box-uncheck #:check-box-checked-p
+           #:radio-button-selected-p #:radio-button-select #:radio-button-deselect
+           #:dialog-item-enabled-p #:set-dialog-item-enabled-p
+           #:shift-key-p #:control-key-p #:alt-key-p #:command-key-p
+           #:get-fore-color #:get-back-color #:set-fore-color #:set-back-color
+           #:invalidate-view
+           #:menu-selection #:menu-items #:set-menu-item-title #:add-contextual-menu
+           #:application-main-menu
+           #:navigate-menu #:navigate-topbar #:add-topbar-item
+           #:make-rgb #:rgb-red #:rgb-green #:rgb-blue #:rgb-opacity
+           ;; canned dialogs
+           #:y-or-n-dialog #:user-pick-color
+           #:choose-file-dialog #:choose-new-file-dialog #:choose-directory-dialog          
+         
+           #:dcc
+           #:perform-close #:window-may-close
+           ;; variables
+           #:*screen-flipped*
+           #:*suppress-window-flushing*))
+
+(cl:defpackage :easygui-demo
+  (:use :cl :easygui)
+  (:export #:converter-window #:tiny-demo-window))
+
+(cl:defpackage :easygui-user
+  (:use :cl :easygui))
Index: /branches/new-random/examples/cocoa/easygui/rgb.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/rgb.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/rgb.lisp	(revision 13309)
@@ -0,0 +1,33 @@
+(in-package :easygui)
+
+; --------------------------------------------------------------------------------
+; This provides for Clozure CL some RGB functions to match Allegro CL.
+; Contributed by AWSC (arthur.cater@ucd.ie) March 2009.
+; Permission to disseminate, use and modify is granted.
+; --------------------------------------------------------------------------------
+
+(defun make-rgb (&key (red 0) (green 0) (blue 0) (opacity 1.0))
+  (assert (typep red     '(integer 0 255)) (red)
+          "Value of RED component for make-rgb must be an integer 0-255 inclusive")
+  (assert (typep green   '(integer 0 255)) (green)
+          "Value of GREEN component for make-rgb must be an integer 0-255 inclusive")
+  (assert (typep blue    '(integer 0 255)) (blue)
+          "Value of BLUE component for make-rgb must be an integer 0-255 inclusive")
+  (assert (typep opacity '(single-float 0.0 1.0)) (opacity)
+          "Value of OPACITY component for make-rgb must be a single-float 0.0-1.0 inclusive")
+  (#/retain
+   (#/colorWithCalibratedRed:green:blue:alpha:
+    ns:ns-color
+    (/ red 255.0)
+    (/ green 255.0)
+    (/ blue 255.0)
+    opacity)))
+
+(defun rgb-red (color)   (round (* 255 (#/redComponent color))))
+
+(defun rgb-green (color) (round (* 255 (#/greenComponent color))))
+
+(defun rgb-blue (color)  (round (* 255 (#/blueComponent color))))
+
+(defun rgb-opacity (color)  (#/alphaComponent color))
+
Index: /branches/new-random/examples/cocoa/easygui/views.lisp
===================================================================
--- /branches/new-random/examples/cocoa/easygui/views.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/easygui/views.lisp	(revision 13309)
@@ -0,0 +1,1650 @@
+(in-package :easygui)
+
+; ----------------------------------------------------------------------
+; This is the Clozure Common Lisp file named 'views.lisp', March 2009,
+; in the folder ccl/examples/cocoa/easygui/
+; It has been modified by AWSC (arthur.cater@ucd.ie), based upon
+; an earlier contribution by an unknown author,  borrowing also from
+; the 'Seuss.lisp' contribution of 'KD'.
+; Permission to use, further modify, disseminate, is hereby granted.
+; No warranty is expressed or implied.
+; Suggestions for - or accomplishment of - further improvement are welcome.
+; Accompanying documentation for this and related files will be written
+; and placed in ccl/examples/cocoa/easygui/documentation.txt
+; Testing has been only with Mac OS 10.5.6 on a 32 bit PPC
+; A demo of some capabilities is in 'easygui-demo-2.lisp'
+; ----------------------------------------------------------------------
+; It extends previous work in the following principal ways:
+; - windows, views and subviews may have nicknames
+; - checkboxes and radio-buttons are provided
+; - menus (pop-up, pull-down, contextual, and main-menu) are provided
+; - MCL-like coordinates (Y increases downward) may optionally be used
+;   for placing windows on the screen, placing subviews within windows,
+;   and graphics within drawing views.
+; - views can generally respond to mouse entry, exit, movement
+; - static text views can respond to mouse clicks
+; - text views can have colored text and colored background
+; - windows can decline to close, and/or invoke daemons upon closing.
+; - views and windows can have specific OBJC subclassed counterparts
+; - Shift, Command, Control and Option keys may be interrogated
+; ----------------------------------------------------------------------
+
+(defmacro running-on-this-thread ((&key (waitp t)) &rest body)
+;; The purpose of this trivial macro is to mark places where it is thought possible that
+;; it may be preferable to use running-on-main-thread.
+  (declare (ignore waitp))
+  `(progn ,@body))
+
+
+(defparameter *screen-flipped* nil
+"When NIL, window positions are taken as referring to their bottom left,
+as per Cocoa's native coordinate system.
+When non-NIL, window positions are taken to refer to their top left,
+as per - for instance - Digitool's MCL.
+The default orientation for graphics within a drawing view is set to
+correspond at the time of creation of that drawing view.")
+
+(defvar *cocoa-event* nil "Allows SHIFT-KEY-P & friends to operate on mouse clicks")
+
+(defvar *suppress-window-flushing* nil "
+When T, graphics output produced with calls to With-Focused-View will not be immediately
+flushed. This can reduce flicker and increase speed when there are many related uses of
+With-Focused-View. It is then necessary though to make sure that somebody somewhere
+calls Flush-Graphics at an appropriate time.
+The same effect can be obtained for an individual use of With-Focused-View by giving
+:WITHOUT-FLUSH as the first form in its body.")
+
+(defun ns-point-from-point (eg-point)  ;; probably belongs in new-cocoa-bindings.lisp
+  (ns:make-ns-point (point-x eg-point) (point-y eg-point)))
+
+(defmacro with-focused-view (cocoa-view &body forms)
+;; From KD's SEUSS.LISP but with added :WITHOUT-FLUSH syntax element
+;; If the first of forms is the keyword :WITHOUT-FLUSH, or if dynamically
+;; the value of *suppress-window-flushing* is non-NIL, then graphics output is not
+;; immediately flushed.
+  (let ((noflush (eq (first forms) ':without-flush)))
+    `(if (dcc (#/lockFocusIfCanDraw ,cocoa-view))
+       (unwind-protect
+           (progn ,@forms)
+         (dcc (#/unlockFocus ,cocoa-view))
+         ,(unless noflush
+            `(unless *suppress-window-flushing* (flush-graphics ,cocoa-view)))))))
+
+(defun flush-graphics (cocoa-view)
+  (running-on-this-thread ()
+    (dcc (#/flushGraphics (#/currentContext ns:ns-graphics-context)))
+    (dcc (#/flushWindow (#/window cocoa-view)))))
+
+(defun cocoa-null (ptr)
+  (equalp ptr ccl:+null-ptr+))
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; view protocol
+
+(defgeneric initialize-view (view)
+  (:documentation "Initializes the view with a cocoa object, sets it up
+according to initargs."))
+
+(defgeneric add-1-subview (view super-view)
+  (:documentation "Adds a subview to another view in the view hierarchy."))
+
+(defgeneric remove-1-subview (view super-view)
+  (:documentation "Removes a view from its superview, possibly deallocating it.
+To avoid deallocation, use RETAINING-OBJECTS"))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; mixins
+;;;
+;;; Some view classes have an associated 'value', which can be accessed and set through
+;;; accessors STRING-VALUE-OF, INTEGER-VALUE-OF, FLOAT-VALUE-OF, DOUBLE-VALUE-OF
+;;; Such classes include STATIC-TEXT-VIEW, TEXT-INPUT-VIEW, PASSWORD-INPUT-VIEW, FORM-CELL-VIEW, SLIDER-VIEW
+;;;
+;;; Some view classes have an associated 'title', accessible and settable through VIEW-TEXT
+;;; Such classes include WINDOW, PUSH-BUTTON-VIEW, BOX-VIEW, RADIO-BUTTON-VIEW, CHECK-BOX-VIEW, MENU-VIEW, MENU-ITEM-VIEW
+;;;
+;;; Some view classes have an associated 'text', also accessible and settable through VIEW-TEXT
+;;; Such classes include STATIC-TEXT-VIEW, TEXT-INPUT-VIEW, PASSWORD-INPUT-VIEW, FORM-CELL-VIEW
+;;;
+;;; Most of those, apart from STATIC-TEXT-VIEW, may be manually 'editable'.
+;;;
+;;; Some view classes have an associated 'action'.
+;;; Such classes include PUSH-BUTTON-VIEW, SLIDER-VIEW, RADIO-BUTTON-VIEW, CHECK-BOX-VIEW, MENU-ITEM-VIEW
+;;;
+;;; Some view classes cannot ever have a contextual menu attached to them, even though their superview
+;;; and their subviews (if any) possibly do.
+;;; Such classes include PUSH-BUTTON-VIEW, RADIO-BUTTON-VIEW, CHECK-BOX-VIEW, MENU-VIEW, MENU-ITEM-VIEW
+;;; Perhaps these should be the same classes as those with actions.
+;;;
+;;; No view classes inherit from 'one-selection-mixin'
+;;; Apparently it was intended that TEXT-INPUT-VIEW might do so some day.
+;;;
+;;; Some view classes have a single 'content view'.
+;;; Such classes include WINDOW, BOX-VIEW.
+;;;
+;;; Some view classes inherit from 'background-coloring-mixin'
+;;; Such classes include STATIC-TEXT-VIEW ... for now
+;;;
+;;; Some view classes inherit from 'text-coloring-mixin'
+;;; Such classes include ...
+;;;
+;;; Some view classes inherit from 'fonting-mixin'
+;;; Such classes include ...
+;;;
+;;; Some view classes inherit from 'mouse-updownabout-mixin'
+;;; Such classes include ...
+;;;
+;;; Some view classes inherit from 'mouse-tracking-mixin'
+;;; Such classes include ...
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mixins dealing with text string and numeric equivalents
+
+(defclass value-mixin () ())
+
+(defclass string-value-mixin (value-mixin) ())
+
+(defclass numeric-value-mixin (value-mixin) ())
+
+(defclass view-text-mixin ()
+     ((text :initarg :text :initarg :dialog-item-text)))
+
+(defclass view-text-via-stringvalue-mixin (view-text-mixin string-value-mixin)
+     ())
+
+(defclass view-text-via-title-mixin (view-text-mixin)
+     ((text :initarg :title)))
+
+(macrolet ((def-type-accessor (class lisp-type cocoa-reader cocoa-writer
+                                     &key (new-value-form 'new-value) (return-value-converter 'identity))
+               (let ((name (intern (format nil "~A-VALUE-OF" lisp-type))))
+                 `(progn
+                    (defmethod ,name ((o ,class))
+                      (,return-value-converter (dcc (,cocoa-reader (cocoa-ref o)))))
+                    (defmethod (setf ,name) (new-value (o ,class))
+                      (dcc (,cocoa-writer (cocoa-ref o) ,new-value-form)))))))
+  (def-type-accessor string-value-mixin string   #/stringValue #/setStringValue:
+    :return-value-converter lisp-string-from-nsstring )
+  (def-type-accessor numeric-value-mixin integer #/intValue #/setIntValue:)
+  (def-type-accessor numeric-value-mixin float   #/floatValue #/setFloatValue:
+    :new-value-form (coerce new-value 'single-float))
+  (def-type-accessor numeric-value-mixin double  #/doubleValue #/setDoubleValue:
+    :new-value-form (coerce new-value 'double-float)))
+
+(defmethod view-text ((view view-text-via-stringvalue-mixin))
+  (string-value-of view))
+
+(defmethod view-text ((view view-text-via-title-mixin))
+  (lisp-string-from-nsstring (dcc (#/title (cocoa-ref view)))))
+
+(defmethod (setf view-text) (new-text (view view-text-via-stringvalue-mixin))
+  (setf (string-value-of view) (ccl::%make-nsstring new-text)))
+
+(defmethod (setf view-text) (new-text (view view-text-via-title-mixin))
+  (dcc (#/setTitle: (cocoa-ref view) (ccl::%make-nsstring new-text)))
+  new-text)
+
+(defmethod initialize-view :after ((view view-text-mixin))
+  (when (slot-boundp view 'text)
+    (setf (view-text view) (slot-value view 'text))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mixins dealing with mouse sensitivity (1)
+
+(defclass action-view-mixin ()
+  ((action :initarg :action)
+   (enabled :accessor dialog-item-enabled-p :initarg :dialog-item-enabled-p :initform t)))
+
+(defclass decline-menu-mixin () ())
+
+(defmethod set-dialog-item-enabled-p ((view action-view-mixin) value)
+  (unless (eq (not value) (not (dialog-item-enabled-p view)))
+    (setf (dialog-item-enabled-p view) value)
+    (dcc (#/setEnabled: (cocoa-ref view) (if value #$YES #$NO)))))
+
+(defmethod initialize-view :after ((view action-view-mixin))
+  (when (and (slot-boundp view 'action) (slot-value view 'action))
+    (setf (action view) (slot-value view 'action)))
+  (unless (dialog-item-enabled-p view)
+    (dcc (#/setEnabled: (cocoa-ref view) #$NO))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mixins dealing with text properties - font, foreground and background colors, editability
+
+(defclass text-coloring-mixin () ())
+
+(defclass text-fonting-mixin () ())
+
+(defclass editable-mixin () ())
+
+(defclass background-coloring-mixin ()
+  ((drawsbackground     :initform t :initarg :draws-background)))
+
+(defmethod initialize-view :after ((view background-coloring-mixin))
+  (dcc (#/setDrawsBackground: (cocoa-ref view) (slot-value view 'drawsbackground)))
+  (when (and (cocoa-ref view) (slot-boundp view 'background))
+      (dcc (#/setBackgroundColor: (cocoa-ref view) (slot-value view 'background)))))
+
+(defmethod editable-p ((view editable-mixin))
+  (dcc (#/isEditable (cocoa-ref view))))
+
+(defmethod (setf editable-p) (editable-p (view editable-mixin))
+  (check-type editable-p boolean)
+  (dcc (#/setEditable: (cocoa-ref view) editable-p))
+  editable-p)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mixin dealing with selection: Possibly obsolete?
+
+(defclass one-selection-mixin () ())
+
+(defmethod (setf selection) (selection (view one-selection-mixin))
+  (dcc (#/setSelectedRange: (cocoa-ref view) (range-nsrange selection)))
+  selection)
+
+(defmethod selection ((view one-selection-mixin))
+  (let ((range (dcc (#/selectedRange (cocoa-ref view)))))
+    (if (= (ns:ns-range-location range) #$NSNotFound)
+        nil
+        (range (ns:ns-range-location range)
+               (ns:ns-range-length range)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mixin for content views: window, box, perhaps others.
+
+(defclass content-view-mixin ()
+  ((content-view)
+   (flipped :initarg :flipped :initform *screen-flipped*)))
+
+(defmethod initialize-view :after ((view content-view-mixin))
+  (unless (slot-boundp view 'content-view)
+    (let ((containee (make-instance 'contained-view
+                       :cocoa-ref (dcc (#/contentView (cocoa-ref view)))
+                       :view-nick-name '%CONTENT-OF-CONTENT-VIEW%
+                       :flipped (slot-value view 'flipped))))
+      (setf (slot-value view 'content-view) containee
+            (slot-value containee 'parent) view))))
+
+(defmethod (setf content-view) (new-content-view (view content-view-mixin))
+  (setf (slot-value view 'content-view) new-content-view)
+  (dcc (#/setContentView: (cocoa-ref view) (cocoa-ref new-content-view)))
+  new-content-view)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mixin for views that can respond to mouse entry, exit, and movement
+
+(defclass mouse-tracking-mixin ()
+  ((mouse-target :reader view-mouse-target :initform nil)
+   (mouse-enter :accessor view-mouse-enter :initarg :mouse-enter :initform nil)
+   (mouse-exit :accessor view-mouse-exit :initarg :mouse-exit :initform nil)
+   (mouse-move :accessor view-mouse-move :initarg :mouse-move :initform nil)))
+
+(defclass easygui-mouse-target (ns:ns-object)
+  ((view :initarg :view :reader mouse-target-view :initform nil))
+  (:metaclass ns:+ns-object))
+
+(defmethod initialize-view :after ((view mouse-tracking-mixin))
+  (let ((cocoaview (cocoa-ref view)))
+   (when cocoaview
+      (let ((target (make-instance 'easygui-mouse-target :view view)))
+        (setf (slot-value view 'mouse-target) target)
+        (dcc (#/retain target))
+        (dcc (#/addTrackingRect:owner:userData:assumeInside:
+         cocoaview
+         (dcc (#/bounds cocoaview))
+         target
+         ccl:+null-ptr+
+         #$NO))))))
+
+(objc:define-objc-method ((:void :mouse-entered (:id event)) easygui-mouse-target)
+  (let* ((view (mouse-target-view self))
+         (fn (view-mouse-enter view)))
+    (when fn (funcall fn view :event event :allow-other-keys t))))
+
+(objc:define-objc-method ((:void :mouse-exited (:id event)) easygui-mouse-target)
+  (let* ((view (mouse-target-view self))
+         (fn (view-mouse-exit view)))
+    (when fn (funcall fn view :event event :allow-other-keys t))))
+
+(objc:define-objc-method ((:void :mouse-move (:id event)) easygui-mouse-target)
+  (let* ((view (mouse-target-view self))
+         (fn (view-mouse-move view)))
+    (when fn (funcall fn view :event event :allow-other-keys t))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Class for the sort of view that is contained by a content view.
+
+(defclass contained-view (view)
+  ((flipped :initarg :flipped)))
+
+(defmethod content-view ((view content-view-mixin))
+  (assert (eql (cocoa-ref (slot-value view 'content-view))
+               (dcc (#/contentView (cocoa-ref view)))))
+  (slot-value view 'content-view))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; the actual views (when adding a new class,
+;;; consider *view-class-to-ns-class-map*):
+
+(defclass view (easy-cocoa-object)
+     ((position :initarg :position :reader view-position)
+      (size :initarg :size :reader view-size)
+      (frame-inited-p :initform nil)
+      (parent :reader view-container :initform nil)
+      (subviews :reader view-subviews :initarg :subviews :initform nil)
+      ;; When adding/removing multiple subviews, prevent multiple redraws.
+      ;; But - what code does those redraws?
+      (subviews-busy :accessor view-subviews-busy :initform nil)
+      (nickname :accessor view-nick-name :initarg :view-nick-name :initform nil)
+      (contextmenu :initarg :contextual-menu :initform nil)
+      (background :initarg :back-color :initform (#/whiteColor ns:ns-color))
+      (foreground :initarg :fore-color :initform (#/blackColor ns:ns-color))
+      (font :reader view-font :initarg :font :initarg :view-font :initform nil)
+      (specifically :reader view-specifically :initarg :specifically :initform nil)
+      ;; Next three not yet operative
+      (tip :initarg :tip :reader view-tip :initform nil)
+      (tiptag :initform nil)))
+
+(defclass window (content-view-mixin view-text-via-title-mixin view)
+     ((text :initarg :title :initform "" :reader window-title)
+      (zoomable-p :initarg :zoomable-p :initform t :reader window-zoomable-p)
+      (minimizable-p :initarg :minimizable-p :initform t
+                     :reader window-minimizable-p)
+      (resizable-p :initarg :resizable-p :initform t
+                   :reader window-resizable-p)
+      (closable-p :initarg :closable-p :initform t :reader window-closable-p)
+      (level :initarg :window-level :accessor window-level
+             :initform (dcc (#_CGWindowLevelForKey #$kCGNormalWindowLevelKey)))
+      (hidden :initarg :hidden :reader window-hidden :initform nil)
+      (window-needs-display-on-show :initform t)
+      (optimized :initarg :optimized :initform t) ; Set to NIL if you anticipate overlapping views in this window
+      (style :initarg :window-style :initform #$NSTitledWindowMask))
+  (:default-initargs :specifically 'cocoa-contained-view))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+(defmethod clear-page ((view view))
+  (let* ((cview (cocoa-ref view))
+         (rect (dcc (#/bounds cview)))
+         (color (slot-value view 'background)))
+    (with-focused-view cview
+      (dcc (#/setFill color))
+      (dcc (#_NSRectFill rect)))))
+
+(defmethod clear-page ((window content-view-mixin))
+  (clear-page (content-view window)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+(defclass static-text-view (view view-text-via-stringvalue-mixin action-view-mixin text-coloring-mixin text-fonting-mixin background-coloring-mixin mouse-tracking-mixin)
+  ((mousedown           :initform nil :initarg :mouse-down    :accessor static-text-view-mouse-down)
+   (mouseup             :initform nil :initarg :mouse-up      :accessor static-text-view-mouse-up)
+   (mousedragged        :initform nil :initarg :mouse-dragged :accessor static-text-view-mouse-dragged)))
+
+(defclass text-input-view (view editable-mixin text-coloring-mixin text-fonting-mixin view-text-via-stringvalue-mixin
+                                ;; XXX: requires NSTextView, but this is an
+                                ;; NSTextField:
+                                #+not-yet one-selection-mixin
+                                mouse-tracking-mixin)
+     ((input-locked-p :initform nil :initarg :input-locked-p
+                      :reader text-input-locked-p)))
+
+(defclass password-input-view (text-input-view)
+     ())
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+(defclass push-button-view (view view-text-via-title-mixin action-view-mixin decline-menu-mixin)
+     ((default-button-p :initarg :default-button-p :initform nil
+                        :reader default-button-p)
+      (bezelstyle       :reader bezel-style        :initarg :bezel-style      :initform :rounded)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+(defclass form-view (view)
+     ((autosize-cells-p :initarg :autosize-cells-p :initform nil)
+      (interline-spacing :initarg :interline-spacing :initform 9)
+      ;; cell width
+      ))
+
+(defclass form-cell-view (view editable-mixin view-text-via-stringvalue-mixin)
+     ())
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+(defclass box-view (content-view-mixin view-text-via-title-mixin view) ())
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+(defclass drawing-view (view mouse-tracking-mixin)
+     (
+      ;; TODO: make this a mixin
+      (accept-key-events-p :initform nil :initarg :accept-key-events-p
+                           :accessor accept-key-events-p)
+      (flipped             :initform *screen-flipped* :initarg :flipped :reader flipped-p)
+      (mousedown           :initform nil :initarg :mouse-down    :accessor drawing-view-mouse-down)
+      (mouseup             :initform nil :initarg :mouse-up      :accessor drawing-view-mouse-up)
+      (mousedragged        :initform nil :initarg :mouse-dragged :accessor drawing-view-mouse-dragged)
+      (draw-fn             :initform nil :initarg :draw-fn :accessor draw-fn)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+(defclass slider-view (view numeric-value-mixin action-view-mixin)
+     ((max-value :initarg :max-value)
+      (min-value :initarg :min-value)
+      (tick-mark-count :initarg :tick-mark-count)
+      (tick-mark-values :initarg :tick-mark-values)
+      (discrete-tick-marks-p :initarg :discrete-tick-marks-p)))
+
+; ----------------------------------------------------------------------
+; Specialisations of ns-xxx classes always begin 'cocoa-'.
+; They allow such things as
+; - finding the easygui window associated with a ns-view & easygui::view
+; - flipped windows, flipped drawing-views
+; - clickable static text, editable text fields
+; - tooltips
+; ----------------------------------------------------------------------
+
+(defun calculate-ns-tooltip (cview)
+  ;; Returns a Lisp string to bhe used as a tooltip, or NIL.
+  ;; Easygu Views may or may not be created with a specific :TIP keyword argument.
+  ;; If there is none, there will be no tooltip displayed for the corresponding cocoa-view.
+  ;; Otherwise, if the argument is
+  ;;   - a string, that string is used
+  ;;   - a function, then if its return value is
+  ;;        - a string, that string is used
+  ;;        - NIL, a string informing that the tooltip is null and cocoa-describing the cocoa-view
+  ;;               (possibly useful for identifying this view if it turns up in errors or inspector)
+  ;;        - else a string naming the type of the result returned (possibly useful for debugging)
+  ;;   - the keyword :IDENTIFY, the cocoa-description of the cocoa-view
+  ;;   - anything else, a string informing what type the argument is.
+  (let* ((egview (when (slot-boundp cview 'easygui-view) (slot-value cview 'easygui-view)))
+         (tip (when egview (slot-value egview 'tip))))
+    (cond
+     ((stringp tip)
+      tip)
+     ((functionp tip)
+      (let ((it (funcall tip)))
+        (cond
+         ((stringp it)  it)
+         ((null it)     (format nil "Null tooltip for ~a" (lisp-string-from-nsstring (dcc (#/description cview)))))
+         (t (format nil "** Tooltip function returned non-string object of type ~s **" (type-of it))))))
+     ((eq tip :identify) (lisp-string-from-nsstring (dcc (#/description cview))))
+     ((null egview) 
+      (format nil "** Cocoa view ~s has no EasyGui-View **" cview))
+     ((null tip) (format nil "No tooltip for ~a" (lisp-string-from-nsstring (dcc (#/description cview)))))
+     (t (format nil "** Tip slot of Cocoa view ~s~%is of type ~s,~%not a string or a function or :IDENTIFY. **" cview tip)))))
+
+(defmacro define-tooltip-accessor (cocoa-class)
+  `(progn
+     (objc:defmethod #/view:stringForToolTip:point:userData:
+                     ((self ,cocoa-class)
+		      view
+                      (tag :<NST>ool<T>ip<T>ag)
+                      (point :<NSP>oint)
+                      (userdata :address))
+       (declare (ignorable tag point userdata))
+       (ccl::%make-nsstring (or (calculate-ns-tooltip view) "")))
+     (objc:defmethod #/toolTip ((view ,cocoa-class))
+       (ccl::%make-nsstring (or (calculate-ns-tooltip view) "")))))
+
+(defclass cocoa-window (ns:ns-window)
+  ((easygui-window :reader easygui-window-of))
+  (:metaclass ns:+ns-object))
+
+(defmethod print-object ((object cocoa-window) stream)
+  (print-unreadable-object (object stream :type t :identity t)
+    (let ((egview (if (slot-boundp object 'easygui-window) (easygui-window-of object) nil)))
+      (format stream "[~:[~;~s~]]" egview (when egview (view-nick-name egview)))))
+  object)
+
+(defmethod easygui-window-of ((eview view))
+  (if (cocoa-ref eview) (easygui-window-of (cocoa-ref eview)) nil))
+
+(defmethod easygui-window-of ((nsview ns:ns-view))
+  (let ((nswindow (dcc (#/window nsview))))
+    (if (typep nswindow 'cocoa-window) (easygui-window-of nswindow) nil)))
+
+(defclass cocoa-extension-mixin ()
+  ((easygui-view :initarg :eg-view :reader easygui-view-of)))
+
+(defmethod print-object ((object cocoa-extension-mixin) stream)
+  (print-unreadable-object (object stream :type t :identity t)
+    (let ((egview (if (slot-boundp object 'easygui-view) (easygui-view-of object) nil)))
+      (format stream "[~:[~;~s~]]" egview (when egview (view-nick-name egview)))))
+  object)
+
+(defclass cocoa-text-field (cocoa-extension-mixin ns:ns-text-field) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-text-field)
+
+(defclass cocoa-mouseable-text-field (cocoa-text-field) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-mouseable-text-field)
+
+(defclass cocoa-contained-view (cocoa-extension-mixin ns:ns-view)
+  ((flipped :initarg :flipped :initform *screen-flipped*))
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-contained-view)
+
+(defclass cocoa-secure-text-field (cocoa-extension-mixin ns:ns-secure-text-field) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-secure-text-field)
+
+(defclass cocoa-button (cocoa-extension-mixin ns:ns-button) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-button)
+
+(defclass cocoa-pop-up-button (cocoa-extension-mixin ns:ns-pop-up-button) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-pop-up-button)
+
+(defclass cocoa-menu-item (cocoa-extension-mixin ns:ns-menu-item) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-menu-item)
+
+(defclass cocoa-form (cocoa-extension-mixin ns:ns-form) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-form)
+
+(defclass cocoa-form-cell (cocoa-extension-mixin ns:ns-form-cell) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-form-cell)
+
+(defclass cocoa-box (cocoa-extension-mixin ns:ns-box) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-box)
+
+(defclass cocoa-drawing-view (cocoa-extension-mixin ns:ns-view)
+  ((flipped :initarg :flipped :initform *screen-flipped*))
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-drawing-view)
+
+(defclass cocoa-slider (cocoa-extension-mixin ns:ns-slider) ()
+  (:metaclass ns:+ns-object))
+
+(define-tooltip-accessor cocoa-slider)
+
+(defparameter *view-class-to-ns-class-map*
+              '((static-text-view     . cocoa-mouseable-text-field)
+                (password-input-view  . cocoa-secure-text-field)
+                (text-input-view      . cocoa-text-field)
+                (push-button-view     . cocoa-button)
+                (check-box-view       . cocoa-button)
+                (radio-button-view    . cocoa-button)
+                (menu-view            . cocoa-pop-up-button)
+                (menu-item-view       . cocoa-menu-item)
+                (form-view            . cocoa-form)
+                (form-cell-view       . cocoa-form-cell)
+                (box-view             . cocoa-box)
+                (drawing-view         . cocoa-drawing-view)
+                (slider-view          . cocoa-slider)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; view initialization:
+
+(defmethod shared-initialize :around ((view view) new-slots &rest initargs)
+  (declare (ignore new-slots initargs))
+  (call-next-method)
+  (running-on-main-thread ()
+    (initialize-view view)))
+
+(defmethod initialize-view ((view view))
+  "Initializes the view using the class-to-ns-class map both as constraint
+on valid values of the :SPECIFICALLY initarg, and as source of default value.
+Also attaches contextual menu if there is one."
+  (when (slot-boundp view 'ref)
+    (return-from initialize-view nil))
+  (let ((ns-view-class (cdr (assoc (class-name (class-of view))
+                                   *view-class-to-ns-class-map*
+                                   :test #'subtypep)))
+        (specifically (view-specifically view))
+        cocoaview)
+    (when specifically
+      (cond
+       ((not (find-class specifically nil))
+        (cerror "Ignore ~a and use ~a default" "~a value for :SPECIFICALLY does not name a class" specifically ns-view-class))
+       ((or (null ns-view-class) (subtypep specifically ns-view-class))
+        (setf ns-view-class specifically))
+       (t (cerror "Ignore ~a and use ~a default" "~a value for :SPECIFICALLY is not a subclass of ~a" specifically ns-view-class))))
+    (if ns-view-class
+      (setf cocoaview
+            (cond
+              ((and (slot-boundp view 'position)
+                    (slot-boundp view 'size))
+               (setf (slot-value view 'frame-inited-p) t)
+               (make-instance ns-view-class
+                  :with-frame (with-slots (position size) view
+                                 (ns-rect-from-points position size))))
+              (t (make-instance ns-view-class)))
+            (cocoa-ref view) cocoaview)
+      (cerror "Continue with cocoa-ref unset" "No view class found for type ~a" (class-of view)))
+    (when (and cocoaview (slot-boundp view 'contextmenu))
+      (let ((menu (slot-value view 'contextmenu)))
+        (cond
+         ((null menu))
+         ((null ns-view-class))
+         ((typep menu 'menu-view)
+          (dcc (#/setMenu: cocoaview (slot-value menu 'ns-menu))))
+         (t (warn "Ignoring contextmenu value ~s for view ~s" menu view)))))
+   (when (and cocoaview
+              (slot-value view 'tip)
+              (dcc (#/respondsToSelector: cocoaview (\@selector #/bounds))))
+     (let ((bounds (#/bounds cocoaview)))
+       (setf (slot-value view 'tiptag)
+             (dcc (#/addToolTipRect:owner:userData: cocoaview bounds cocoaview ccl:+null-ptr+)))))))
+
+(defun screen-height nil
+  (running-on-this-thread ()
+    (ns:ns-rect-height (dcc (#/frame (#/objectAtIndex: (#/screens ns:ns-screen) 0))))))
+
+(defmethod view-content-rect ((view view) &optional hidden)
+  (if hidden
+    (ns:make-ns-rect 0 0 0 0)
+    (with-slots (position size) view
+      ;(if (slot-boundp view 'size)
+      ;  (format t "~&View ~s has size ~s~%" view size)
+      ;  (format t "~&View ~s has size unbound~%" view))
+      (let* ((height (if (slot-boundp view 'size) (point-y size) *window-size-default-y*))
+             (stated (if (slot-boundp view 'position) (point-y position) *window-position-default-y*))
+             (screentop (screen-height))  ;; TODO: dtrt for multiple screens
+             (bottom (if (and *screen-flipped* (typep view 'window))
+                       (- screentop height stated)
+                       stated)))
+        (ns:make-ns-rect
+         (if (slot-boundp view 'position) (point-x position) *window-position-default-x*)
+         bottom
+         (if (slot-boundp view 'size) (point-x size) *window-size-default-x*)
+         height)))))
+
+(defmethod initialize-view ((win window))
+  "Initialize size, title, flags."
+  (with-slots (level hidden optimized style flipped specifically) win
+    (unless (and (find-class specifically nil) (subtypep specifically 'cocoa-contained-view))
+      (cerror "Ignore ~a and create content view of type ~a"
+              "Value given for \":specifically\" is ~a which is not a subtype of ~a"
+              specifically 'cocoa-contained-view)
+      (setf specifically 'cocoa-contained-view))
+     (let* ((content-rect (view-content-rect win hidden))
+            (style-mask (logior ;; (flag-mask :zoomable-p (zoomable-p win))
+                         (flag-mask :resizable-p   (window-resizable-p win))
+                         (flag-mask :minimizable-p (window-minimizable-p win))
+                         (flag-mask :closable-p    (window-closable-p win))
+                         (if (or (window-resizable-p win) (window-minimizable-p win) (window-closable-p win))
+                           #$NSTitledWindowMask
+                           0)
+                         style))
+            (c-win
+             (make-instance 'cocoa-window
+               :with-content-rect content-rect
+               :style-mask style-mask
+               :backing #$NSBackingStoreBuffered ; TODO?
+               :defer t))
+            (containee (make-instance specifically)))
+       (setf (slot-value containee 'flipped) flipped)
+       (dcc (#/setFrame: containee content-rect))
+       (dcc (#/setContentView: c-win containee))
+       (dcc (#/setDelegate: c-win c-win))
+       (dcc (#/setBackgroundColor: c-win (slot-value win 'background)))
+       (dcc (#/setLevel: c-win level))
+       (when optimized (dcc (#/useOptimizedDrawing: c-win #$YES)))
+       (setf (cocoa-ref win) c-win)
+       (setf (slot-value c-win 'easygui-window) win)
+       (if hidden
+         (dcc (#/disableFlushWindow c-win))
+         (window-show win))
+       c-win)))
+
+(defmethod initialize-view :after ((view text-input-view))
+  (setf (editable-p view) (not (text-input-locked-p view)))
+  (setf (slot-value (cocoa-ref view) 'easygui-view) view))
+
+(defmethod initialize-view :after ((view static-text-view))
+  (dcc (#/setEditable: (cocoa-ref view) nil))
+  (dcc (#/setBordered: (cocoa-ref view) nil))
+  (dcc (#/setBezeled: (cocoa-ref view) nil))
+  (setf (slot-value (cocoa-ref view) 'easygui-view) view))
+
+(defparameter *bezelstyle-alist*
+  `((:round                    . #.#$NSRoundedBezelStyle)
+    (:square                   . #.#$NSRegularSquareBezelStyle)
+    (:regular-square           . #.#$NSRegularSquareBezelStyle)
+    (:thick-square             . #.#$NSThickSquareBezelStyle)
+    (:thicker-square           . #.#$NSThickerSquareBezelStyle)
+    (:disclosure               . #.#$NSDisclosureBezelStyle)
+    (:Shadowless-square        . #.#$NSShadowlessSquareBezelStyle)
+    (:circular                 . #.#$NSCircularBezelStyle)
+    (:textured-square          . #.#$NSTexturedSquareBezelStyle)
+    (:help-button              . #.#$NSHelpButtonBezelStyle)
+    (:small-square             . #.#$NSSmallSquareBezelStyle)
+    (:textured-rounded         . #.#$NSTexturedRoundedBezelStyle)
+    (:round-rect               . #.#$NSRoundRectBezelStyle)
+    (:recessed                 . #.#$NSRecessedBezelStyle)
+    (:rounded-disclosure       . #.#$NSRoundedDisclosureBezelStyle)))
+
+(defun bezel-style-lookup (key)
+  (rest (or (assoc key *bezelstyle-alist*) (first *bezelstyle-alist*))))
+
+(defmethod (setf bezel-style) (stylename (view push-button-view))
+  (setf (slot-value view 'bezelstyle) (if (assoc stylename *bezelstyle-alist*) stylename :round))
+  (dcc (#/setBezelStyle: (cocoa-ref view) (bezel-style-lookup (slot-value view 'bezelstyle))))
+  stylename)
+
+(defmethod initialize-view :after ((view push-button-view))
+  (dcc (#/setBezelStyle: (cocoa-ref view) (bezel-style-lookup (bezel-style view))))
+  (let ((default-button-p (slot-value view 'default-button-p)))
+    (typecase default-button-p
+      (cons
+       (dcc (#/setKeyEquivalent: (cocoa-ref view) 
+                                 (ccl::%make-nsstring (string (first default-button-p)))))
+       (dcc (#/setKeyEquivalentModifierMask:
+         (cocoa-ref view)
+         (apply #'logior (mapcar #'key-mask (cdr default-button-p))))))
+      (string
+       (dcc (#/setKeyEquivalent: (cocoa-ref view) (ccl::%make-nsstring default-button-p))))
+      (null)
+      (t
+       (dcc (#/setKeyEquivalent: (cocoa-ref view) (ccl::@ #.(string #\return)))))))
+  (setf (slot-value (cocoa-ref view) 'easygui-view) view))
+
+(defmethod initialize-view :after ((view box-view))
+  (setf (slot-value (cocoa-ref view) 'easygui-view) view))
+
+(defmethod initialize-view :after ((view form-view))
+  (when (slot-boundp view 'interline-spacing)
+    (dcc (#/setInterlineSpacing: (cocoa-ref view)
+                             (gui::cgfloat (slot-value view 'interline-spacing)))))
+  (setf (slot-value (cocoa-ref view) 'easygui-view) view))
+
+(defmethod initialize-view :after ((view slider-view))
+  (with-slots (discrete-tick-marks-p tick-mark-count tick-mark-values min-value max-value) view
+     (cond ((and (slot-boundp view 'tick-mark-count)
+                 (slot-boundp view 'discrete-tick-marks-p)
+                 (slot-boundp view 'tick-mark-values)
+                 (/= (length tick-mark-values) tick-mark-count))
+            (error "Incompatible tick mark specification: ~A doesn't match ~
+                     count of ~A" tick-mark-count tick-mark-values))
+           ((or (not (slot-boundp view 'max-value))
+                (not (slot-boundp view 'min-value)))
+            (error "A slider view needs both :min-value and :max-value set.")))
+     (dcc (#/setMinValue: (cocoa-ref view) (float min-value (or 1.0d0 ns:+cgfloat-zero+))))
+     (dcc (#/setMaxValue: (cocoa-ref view) (float max-value (or 1.0d0 ns:+cgfloat-zero+))))
+     (when (slot-boundp view 'tick-mark-count)
+       (dcc (#/setNumberOfTickMarks: (cocoa-ref view) tick-mark-count))
+       (dcc (#/setAllowsTickMarkValuesOnly:
+             (cocoa-ref view) (not (not discrete-tick-marks-p))))))
+  (setf (slot-value (cocoa-ref view) 'easygui-view) view))
+
+(defmethod initialize-view :after ((view text-coloring-mixin))
+  (dcc (#/setTextColor: (cocoa-ref view) (slot-value view 'foreground))))
+
+(defmethod initialize-view :after ((view text-fonting-mixin))
+  (when (slot-value view 'font)
+    (dcc (#/setFont: (cocoa-ref view) (slot-value view 'font)))))
+
+(defmethod (setf view-font) ((new ns:ns-font) (view view))
+  (setf (slot-value view 'font) new)
+  (dcc (#/setFont: (cocoa-ref view) new)))
+
+; ----------------------------------------------------------------------
+; Modifying position / size    of    view / window
+; ----------------------------------------------------------------------
+
+(defmethod (setf view-position) (point (self view))
+  (running-on-main-thread ()
+    (setf (slot-value self 'position) point)
+    (when (slot-value self 'frame-inited-p)
+      (dcc (#/setFrame: (cocoa-ref self) (view-content-rect self)))
+      (dcc (#/setNeedsDisplay (cocoa-ref self))))))
+
+(defmethod (setf view-position) (point (self window))
+  (running-on-main-thread ()
+    (setf (slot-value self 'position) point)
+    (unless (window-hidden self)
+      (let* ((contentrect (view-content-rect self nil))
+             (framerect (dcc (#/frameRectForContentRect: (cocoa-ref self) contentrect))))
+        (dcc (#/setFrame:display: (cocoa-ref self) framerect t))))))
+
+(defmethod (setf view-size) (point (self view))
+  (running-on-main-thread ()
+    (setf (slot-value self 'size) point)
+    (when (slot-value self 'frame-inited-p)
+      (dcc (#/setFrame: (cocoa-ref self) (view-content-rect self)))
+      (dcc (#/setNeedsDisplay (cocoa-ref self))))))
+
+(defmethod (setf view-size) (point (self window))
+  (running-on-main-thread ()
+    (setf (slot-value self 'size) point)
+    (unless (window-hidden self)
+      (let* ((contentrect (view-content-rect self nil))
+             (framerect (dcc (#/frameRectForContentRect: (cocoa-ref self) contentrect))))
+        (dcc (#/setFrame:display: (cocoa-ref self) framerect t))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; view hierarchies:
+
+(defmethod set-needs-display ((view view) flag)
+  (running-on-this-thread ()
+    (dcc (#/setNeedsDisplay: (cocoa-ref view) flag))))
+
+(defmethod set-needs-display ((view content-view-mixin) flag)
+  (set-needs-display (content-view view) flag))
+
+(defmethod set-needs-display ((view window) flag)
+  (if (window-hidden view)
+    (setf (slot-value view 'window-needs-display-on-show) flag)
+    (set-needs-display (content-view view) flag)))
+
+(defmethod add-1-subview :around ((view view) (cw-view content-view-mixin))
+  (add-1-subview view (content-view cw-view)))
+
+(defmethod add-1-subview :around ((view view) (super-view view))
+  "Correctly initialize view positions"
+  (call-next-method)
+  (with-slots (position size frame-inited-p) view
+    (unless frame-inited-p
+      (setf frame-inited-p t)
+      (running-on-this-thread ()
+        (let ((cocoa-view (cocoa-ref view)))
+          (dcc (#/setFrameOrigin: cocoa-view (ns-point-from-point position)))
+          (if (slot-boundp view 'size)
+            (dcc (#/setFrameSize: cocoa-view (ns-point-from-point size)))
+            (dcc (#/sizeToFit cocoa-view))))))
+    (set-needs-display view t)
+    (unless (view-subviews-busy super-view) (set-needs-display super-view t))))
+
+(defmethod add-1-subview ((view view) (super-view view))
+  (running-on-this-thread ()
+    (setf (slot-value view 'parent) super-view)
+    (push view (slot-value super-view 'subviews))
+    (dcc (#/addSubview: (cocoa-ref super-view) (cocoa-ref view)))))
+
+(defun add-subviews (superview subview &rest subviews)
+  (setf (view-subviews-busy superview) t)
+  (add-1-subview subview superview)
+  (dolist (subview subviews)
+    (add-1-subview subview superview))
+  (set-needs-display superview t)
+  (setf (view-subviews-busy superview) nil)
+  superview)
+
+(defmethod remove-1-subview ((view view) (cw-view content-view-mixin))
+  (remove-1-subview view (content-view cw-view)))
+
+(defmethod remove-1-subview ((view view) (super-view view))
+  (assert (eql (cocoa-ref super-view) (dcc (#/superview (cocoa-ref view)))))
+  (assert (member view (view-subviews super-view)))
+  (assert (eq super-view (slot-value view 'parent)))
+  (maybe-invalidating-object (view)
+    (setf (slot-value super-view 'subviews) (delete view (slot-value super-view 'subviews)))
+    (setf (slot-value view 'parent) nil)
+    (running-on-this-thread ()
+      (dcc (#/removeFromSuperview (cocoa-ref view))))))
+
+(defun remove-subviews (superview subview &rest subviews)
+  (setf (view-subviews-busy superview) t)
+  (remove-1-subview subview superview)
+  (dolist (subview subviews)
+    (remove-1-subview subview superview))
+  (set-needs-display superview t)
+  (setf (view-subviews-busy superview) nil)
+  superview)
+
+(defmethod window-show ((window window))
+  (running-on-this-thread ()
+    (let ((cwin (cocoa-ref window)))
+      (when (window-hidden window)
+        (setf (slot-value window 'hidden) nil)
+        (let* ((contentrect (view-content-rect window nil))
+               (framerect (dcc (#/frameRectForContentRect: (cocoa-ref window) contentrect))))
+          (dcc (#/setFrame:display: (cocoa-ref window) framerect nil)))
+        (when (dcc (#/isMiniaturized cwin)) (dcc (#/deminiaturize: cwin cwin)))
+        (when (slot-value window 'window-needs-display-on-show)
+          (setf (slot-value window 'window-needs-display-on-show) nil)
+          (dcc (#/setNeedsDisplay: (cocoa-ref (content-view window)) t))))
+      (dcc (#/makeKeyAndOrderFront: cwin nil))
+      (when (dcc (#/isFlushWindowDisabled cwin))
+        (dcc (#/enableFlushWindow cwin))
+        (dcc (#/flushWindow cwin)))
+      window)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Forms:
+
+(defmethod add-entry (entry (view form-view))
+  (make-instance 'form-cell-view
+     :cocoa-ref (dcc (#/addEntry: (cocoa-ref view) (ccl::%make-nsstring entry)))))
+
+(defun add-entries (view &rest entries)
+  (prog1 (mapcar (lambda (entry) (add-entry entry view)) entries)
+         (dcc (#/setAutosizesCells: (cocoa-ref view)
+                                    (slot-value view 'autosize-cells-p)))))
+
+(defmethod cell-count ((view form-view))
+  (dcc (#/numberOfRows (cocoa-ref view))))
+
+(defmethod nth-cell (index view)
+  (assert (< index (cell-count view)))
+  (let ((cocoa-cell (dcc (#/cellAtIndex: (cocoa-ref view) index))))
+    (when cocoa-cell
+      (make-instance 'form-cell-view :cocoa-ref cocoa-cell))))
+
+(defmethod (setf entry-text) (text view index)
+  (setf (view-text (nth-cell index view)) text))
+
+(defmethod entry-text (view index)
+  (view-text (nth-cell index view)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Window closing
+         
+(defmethod window-may-close ((w window))
+"This generic is intended to allow applications to define :BEFORE and/or :AFTER methods
+invoked when windows are closed. The default primary method returns T to indicate that
+the window may close. If an overriding primary method returns NIL, the window will not
+close in response to user action but will still close if the application quits.
+(This is because window-may-close is called when the COCOA-WINDOW (specialised NS:NS-WINDOW)
+that is attached to an EASYGUI::WINDOW object receives a performClose: message, as when
+a user clicks the close button for example.)"
+  (declare (ignore w))
+  t)
+
+(defmethod perform-close ((w window))
+"This generic is intended to allow applications to mimic the user clicking a window's
+close button."
+  (running-on-this-thread ()
+    (dcc (#/performClose: (cocoa-ref w)  ccl:+null-ptr+))))
+
+(objc:define-objc-method ((:<BOOL> :window-should-close (:id sender)) cocoa-window)
+  (declare (ignore sender))  ; The cocoa-window has been set up as its own delegate. Naughty?
+  (if (window-may-close (easygui-window-of self)) #$YES #$NO))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Drawing:
+
+(defmethod clear-page ((cocoa-view cocoa-drawing-view))
+  (let* ((view (easygui-view-of cocoa-view))
+         (rect (dcc (#/bounds cocoa-view)))
+         (color (slot-value view 'background)))
+    (with-focused-view cocoa-view
+      (dcc (#/setFill color))
+      (dcc (#_NSRectFill rect)))))
+         
+(objc::defmethod (#/isFlipped :<BOOL>) ((self cocoa-drawing-view))
+  (if (slot-value self 'flipped) #$YES #$NO))
+
+(objc::defmethod (#/isFlipped :<BOOL>) ((self cocoa-contained-view))
+  (if (slot-value self 'flipped) #$YES #$NO))
+
+(defmethod initialize-view :after ((view drawing-view))
+  (setf (slot-value (cocoa-ref view) 'flipped) (slot-value view 'flipped))
+  (setf (slot-value (cocoa-ref view) 'easygui-view) view))
+
+(objc:defmethod (#/drawRect: :void) ((self cocoa-drawing-view)
+                                     (rect :<NSR>ect))
+  (dcc (draw-view-rectangle (easygui-view-of self) (nsrect-rectangle rect))))
+
+(objc:defmethod (#/acceptsFirstReponder: :boolean) ((view cocoa-drawing-view))
+  (accept-key-events-p (easygui-view-of view)))
+
+(defgeneric draw-view-rectangle (view rectangle)
+  (:method ((view drawing-view) rectangle)
+    (declare (ignorable view rectangle))
+    (when (draw-fn view)
+      (let ((cview (cocoa-ref view)))
+        (with-focused-view cview (funcall (draw-fn view) view cview))))
+    nil))
+
+(defmethod redisplay ((view drawing-view)
+                      &key rect)
+  (setf rect (if rect
+                 (rectangle-nsrect rect)
+                 (dcc (#/bounds (cocoa-ref view)))))
+  (dcc (#/setNeedsDisplayInRect: (cocoa-ref view) rect)))
+
+(define-useful-mouse-event-handling-routines cocoa-drawing-view)
+(define-useful-mouse-event-handling-routines cocoa-mouseable-text-field)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Around methods for VIEW provide bindings for *modifier-key-pattern* for all kinds of views,
+;; allowing for Shift-Key-P and friends.
+;; Primary methods do nothing, but may be overridden by user code.
+
+;(defmethod mouse-down :around ((view view) &key cocoa-event location button click-count delta)
+;  (declare (ignorable cocoa-event location button click-count delta))
+;  (let ((*cocoa-event* cocoa-event)
+;        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+;    (call-next-method)))
+  
+(defmethod mouse-down ((view view) &key cocoa-event location button click-count delta)
+  (declare (ignorable view cocoa-event location button click-count delta))
+  nil)
+  
+;(defmethod mouse-up :around ((view view) &key cocoa-event location button click-count delta)
+;  (declare (ignorable cocoa-event location button click-count delta))
+;  (let ((*cocoa-event* cocoa-event)
+;        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+;    (call-next-method)))
+  
+(defmethod mouse-up ((view view) &key cocoa-event location button click-count delta)
+  (declare (ignorable view cocoa-event location button click-count delta))
+  nil)
+
+;(defmethod mouse-dragged :around ((view view) &key cocoa-event location button click-count delta)
+;  (declare (ignorable cocoa-event location button click-count delta))
+;  (let ((*cocoa-event* cocoa-event)
+;        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+;    (call-next-method)))
+  
+(defmethod mouse-dragged ((view view) &key cocoa-event location button click-count delta)
+  (declare (ignorable view cocoa-event location button click-count delta))
+  nil)
+  
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Primary methods for DRAWING-VIEW. What now is the point?
+
+(defmethod mouse-down ((view drawing-view) &key cocoa-event location button click-count delta)
+  (let ((mousefn (drawing-view-mouse-down view))
+        (*cocoa-event* cocoa-event)
+        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+    (when mousefn
+      (funcall mousefn view
+               :location location
+               :allow-other-keys t
+               :button button
+               :cocoa-event cocoa-event
+               :click-count click-count
+               :delta delta))))
+
+(defmethod mouse-up ((view drawing-view) &key cocoa-event location button click-count delta)
+  (let ((mousefn (drawing-view-mouse-up view))
+        (*cocoa-event* cocoa-event)
+        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+    (when mousefn
+      (funcall mousefn view
+               :location location
+               :allow-other-keys t
+               :button button
+               :cocoa-event cocoa-event
+               :click-count click-count
+               :delta delta))))
+
+(defmethod mouse-dragged ((view drawing-view) &key cocoa-event location button click-count delta)
+  (let ((mousefn (drawing-view-mouse-dragged view))
+        (*cocoa-event* cocoa-event)
+        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+    (when mousefn
+      (funcall mousefn view
+               :location location
+               :allow-other-keys t
+               :button button
+               :cocoa-event cocoa-event
+               :click-count click-count
+               :delta delta))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Primary methods for STATIC-TEXT-VIEW. What now is the point?
+
+(defmethod mouse-down ((view static-text-view) &key cocoa-event location button click-count delta)
+  (let ((mousefn (static-text-view-mouse-down view))
+        (*cocoa-event* cocoa-event)
+        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+    (when mousefn
+      (funcall mousefn view
+               :location location
+               :allow-other-keys t
+               :button button
+               :cocoa-event cocoa-event
+               :click-count click-count
+               :delta delta))))
+
+(defmethod mouse-up ((view static-text-view) &key cocoa-event location button click-count delta)
+  (let ((mousefn (static-text-view-mouse-up view))
+        (*cocoa-event* cocoa-event)
+        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+    (when mousefn
+      (funcall mousefn view
+               :location location
+               :allow-other-keys t
+               :button button
+               :cocoa-event cocoa-event
+               :click-count click-count
+               :delta delta))))
+
+(defmethod mouse-dragged ((view static-text-view) &key cocoa-event location button click-count delta)
+  (let ((mousefn (static-text-view-mouse-dragged view))
+        (*cocoa-event* cocoa-event)
+        (*modifier-key-pattern* (dcc (#/modifierFlags cocoa-event))))
+    (when mousefn
+      (funcall mousefn view
+               :location location
+               :allow-other-keys t
+               :button button
+               :cocoa-event cocoa-event
+               :click-count click-count
+               :delta delta))))
+
+; -------------------
+(defmethod view-named (name (view view))
+  (find name (view-subviews view) :key #'view-nick-name))
+
+(defmethod view-named (name (container content-view-mixin))
+  (view-named name (content-view container)))
+
+(defmethod view-subviews ((w content-view-mixin))
+  (view-subviews (content-view w)))
+
+; ----------------------
+
+(defmethod view-nickname-chain ((view view) &optional include-everything) "
+Yields two values:
+- a list of nicknames of containing views, starting with outermost container
+- the view or window that contains the view with the first name in the list,
+  or NIL if the first name belongs to a window.
+If include-everything is NIL (the default), the list does not contain the
+autogenerated name for content views of windows or boxes, and contains names
+of views or windows that have non-NIL names. The second value may then be
+a view or window that has no nickname of its own.
+If include-everything is T, the list does contain the autogenerated name of
+content views of windows or boxes, it does contain NIL for views named NIL,
+and the second value will always be NIL."
+  (do (chain
+       nickname
+       (outermost view (view-container outermost)))
+      ((or (null outermost)
+           (and (null (setf nickname (view-nick-name outermost)))
+                (not include-everything)))                
+       (values chain outermost))
+    (when (or include-everything (not (eq nickname '%CONTENT-OF-CONTENT-VIEW%)))
+      (push (view-nick-name outermost) chain))))
+
+; ----------------------
+
+(defclass check-box-view (view view-text-via-title-mixin action-view-mixin decline-menu-mixin)
+  ((checked :initarg :checked :initform nil)))
+
+(defmethod check-box-check ((self check-box-view) &optional perform)
+  (running-on-this-thread ()
+    (unless (eql (dcc (#/state (cocoa-ref self))) #$NSOnState)
+      (if perform
+        (dcc (#/performClick: (cocoa-ref self) nil))
+        (dcc (#/setState: (cocoa-ref self) #$NSOnState)))
+      t)))
+
+(defmethod initialize-view :after ((view check-box-view))
+  (when (cocoa-ref view)
+    (dcc (#/setButtonType: (cocoa-ref view) #$NSSwitchButton))
+    (when (slot-value view 'checked) (check-box-check view))
+    (setf (slot-value (cocoa-ref view) 'easygui-view) view)))
+
+(defmethod check-box-uncheck ((self check-box-view) &optional perform)
+  (running-on-this-thread ()
+    (unless (eql (dcc (#/state (cocoa-ref self))) #$NSOffState)
+      (if perform
+        (dcc (#/performClick: (cocoa-ref self) nil))
+        (dcc (#/setState: (cocoa-ref self) #$NSOffState)))
+      t)))
+
+(defmethod check-box-checked-p ((self check-box-view))
+  (eql (dcc (#/state (cocoa-ref self))) #$NSOnState))
+
+(defmethod (setf check-box-checked-p) (new (self check-box-view))
+  (if new
+    (check-box-check self)
+    (check-box-uncheck self))
+  new)
+
+; -------------------------
+(defclass radio-button-view (view view-text-via-title-mixin action-view-mixin decline-menu-mixin)
+  ((selected :initarg :selected :reader radio-button-selected-p :initform nil)
+   (cluster  :initarg :cluster  :initform '#:default-cluster))
+  (:default-initargs :action #'(lambda () nil)))
+
+(defun deselect-radio-button-cohorts (radio-button-view)
+  (when (view-container radio-button-view)
+    (dolist (sibling (view-subviews (view-container radio-button-view)))
+      (when (and (not (eq sibling radio-button-view))
+                 (typep sibling 'radio-button-view)
+                 (eq (slot-value radio-button-view 'cluster) (slot-value sibling 'cluster))
+                 (eql (dcc (#/state (cocoa-ref sibling))) #$NSOnState))
+        (setf (slot-value sibling 'selected) nil)
+        (dcc (#/setState: (cocoa-ref sibling) #$NSOffState))))))
+  
+(defmethod radio-button-select ((self radio-button-view) &optional perform)
+  (running-on-this-thread ()
+    (if perform
+      (dcc (#/performClick: (cocoa-ref self) nil))
+      (progn
+        (deselect-radio-button-cohorts self)
+        (setf (slot-value self 'selected) t)
+        (dcc (#/setState: (cocoa-ref self) #$NSOnState))))))
+
+(defmethod initialize-view :after ((self radio-button-view))
+  (when (cocoa-ref self)
+    (dcc (#/setButtonType: (cocoa-ref self) #$NSRadioButton))
+    (when (slot-value self 'selected) (radio-button-select self))
+    (setf (slot-value (cocoa-ref self) 'easygui-view) self)))
+
+(defmethod radio-button-deselect ((self radio-button-view))
+  (running-on-this-thread ()
+    (dcc (#/setState: (cocoa-ref self) #$NSOffState))
+    (prog1
+      (radio-button-selected-p self)
+      (setf (slot-value self 'selected) nil))))
+
+(defmethod (setf action) (handler (view radio-button-view))
+  (call-next-method
+   (lambda ()
+     (deselect-radio-button-cohorts view)
+     (setf (slot-value view 'selected) t)
+     (funcall handler))
+   view)
+  handler)
+
+; ----------------------------------------------------------------------
+; INVALIDATE-VIEW
+; ----------------------------------------------------------------------
+
+(defmethod invalidate-view ((view view) &optional total)
+  (declare (ignorable total))
+  (let ((cview (cocoa-ref view)))
+    (dcc (#/setNeedsDisplay: cview #$YES))))
+
+(defmethod invalidate-view ((window window) &optional total)
+  (declare (ignorable total))
+  (let* ((cocoaview (cocoa-ref window))
+         (contentview (dcc (#/contentView cocoaview))))
+    (dcc (#/setNeedsDisplay: contentview #$YES))))
+
+; ----------------------------------------------------------------------
+; Methods to    GET- & SET-    FORE- & BACK-    COLOR
+; ----------------------------------------------------------------------
+
+(defmethod set-fore-color ((view view) (color ns:ns-color))
+  (setf (slot-value view 'foreground) color))
+
+(defmethod set-fore-color :before ((view view-text-via-stringvalue-mixin) (color ns:ns-color))
+  (dcc (#/setTextColor: (cocoa-ref view) color)))
+
+(defmethod set-fore-color ((view cocoa-extension-mixin) (color ns:ns-color))
+  (set-fore-color (easygui-view-of view) color))
+
+(defmethod set-back-color ((view view) (color ns:ns-color) &optional redisplay-p)
+  (setf (slot-value view 'background) color)
+  (when redisplay-p (invalidate-view view)))
+
+(defmethod set-back-color :after ((view static-text-view) (color ns:ns-color) &optional redisplay-p)
+  (dcc (#/setBackgroundColor: (cocoa-ref view) color))
+  (when redisplay-p (invalidate-view view)))
+
+(defmethod set-back-color ((view cocoa-extension-mixin) (color ns:ns-color) &optional redisplay-p)
+  (set-back-color (easygui-view-of view) color redisplay-p))
+
+(defmethod get-fore-color ((view view))
+  (slot-value view 'foreground))
+
+(defmethod get-fore-color ((view cocoa-extension-mixin))
+  (get-fore-color (easygui-view-of view)))
+
+(defmethod get-back-color ((view view))
+  (slot-value view 'background))
+
+(defmethod get-back-color ((view cocoa-extension-mixin))
+  (get-back-color (easygui-view-of view)))
+
+; --------------------- Menus Begin ---------------------
+
+(defmethod view-text ((self ns:ns-menu))
+  (lisp-string-from-nsstring (dcc (#/title self))))
+
+(defmethod (setf view-text) (new (self ns:ns-menu))
+  (running-on-this-thread ()
+    (dcc (#/setTitle: self (ccl::%make-nsstring new)))
+    new))
+
+(defclass menu-view (view view-text-via-title-mixin decline-menu-mixin)
+  ((selection   :initarg :selection   :reader menu-selection :initform nil)
+   (menu-kind   :initarg :menu-kind   :reader menu-kind      :initform :pull-down-menu)
+   (menu-items  :initarg :menu-items  :reader menu-items     :initform nil)
+   ns-menu
+   %result))
+
+(defclass menu-item-view (view view-text-via-title-mixin action-view-mixin decline-menu-mixin)
+  (parent-menu
+   action
+   submenu)
+  (:default-initargs :action #'(lambda () nil)))
+
+;(defmethod (setf view-text) :after (new (menu menu-view))
+;  (declare (ignorable new))
+;  (dcc (#/setNeedsDisplay: (cocoa-ref menu) t)))
+
+(defmethod initialize-instance :after ((self menu-view) &rest args &key menu-items selection)
+  (declare (ignorable args selection))
+  (let ((ns-menu nil))
+    (if (slot-boundp self 'ns-menu)
+      (setf ns-menu (slot-value self 'ns-menu))
+      (setf ns-menu (dcc (#/menu (cocoa-ref self)))
+            (slot-value self 'ns-menu) ns-menu))
+    ;(format t "~&Initializing menu ~a with ~a items~%" self (length menu-items))
+    (dolist (item menu-items)
+      ;(format t "~&Adding ~a to menu ~a~%" item self)
+      (cond
+       ((typep item 'menu-view)
+        (let ((intermediary (make-instance 'menu-item-view
+                              :title (view-text item))))
+          (setf (slot-value intermediary 'submenu) item)
+          (dcc (#/setSubmenu: (cocoa-ref intermediary) (slot-value item 'ns-menu)))
+          (dcc (#/addItem: ns-menu (cocoa-ref intermediary)))))
+       ((not (typep item 'menu-item-view))
+        (warn "Ignoring so-called menu item ~s" item))
+       ((slot-boundp item 'parent-menu)
+        (warn "Ignoring menu item ~s, which is already an item in some menu" item))
+       (t (let ((coco (cocoa-ref item)))
+            (dcc (#/addItem: ns-menu coco))
+            (setf (slot-value item 'parent-menu) self)))))))
+
+(defmethod (setf action) (new (menu-item menu-item-view))
+  (call-next-method
+   #'(lambda ()
+       (if (slot-boundp menu-item 'parent-menu)
+         (let ((parent (slot-value menu-item 'parent-menu)))
+           (setf (slot-value parent 'selection) menu-item)
+           (setf (slot-value parent '%result) (funcall new)))
+         (funcall new)))
+   menu-item)
+  new)
+
+(defmethod set-menu-item-title ((menu-item menu-item-view) title)
+  (running-on-this-thread ()
+    (dcc (#/setTitle: (cocoa-ref menu-item) (ccl::%make-nsstring title)))))
+
+(defmethod set-menu-item-title ((menu-item ns:ns-menu-item) title)
+  (running-on-this-thread ()
+    (dcc (#/setTitle: menu-item (ccl::%make-nsstring title)))))
+
+; -------------------
+(defclass pop-up-menu (menu-view)
+  ()
+  (:default-initargs :menu-kind :pop-up-menu))
+
+(defmethod initialize-instance :after ((self pop-up-menu) &rest args &key selection)
+  (declare (ignorable args))
+  (with-slots (ns-menu menu-items) self
+    (setf (view-text self)
+          (cond
+           ((null menu-items)
+            "<No Items>")
+           ((null selection)
+            (setf (slot-value self 'selection) (first menu-items))
+            (view-text (first menu-items)))
+           ((stringp selection)
+            selection)
+           ((member selection menu-items)
+            (setf (slot-value self 'selection) selection)
+            (view-text selection))
+           (t "<Selection Invalid>"))))
+  (setf (slot-value (cocoa-ref self) 'easygui-view) self))
+
+; ----------------------
+(defclass pull-down-menu (menu-view)
+  ()
+  (:default-initargs :menu-kind :pull-down-menu))
+
+(defmethod initialize-instance :after ((self pull-down-menu) &rest args &key title)
+  (declare (ignorable args))
+  (running-on-this-thread ()
+    (dcc (#/insertItemWithTitle:atIndex: (cocoa-ref self) (ccl::%make-nsstring (or title "<No Title>")) 0))))
+
+(defmethod initialize-view :after ((self pull-down-menu))
+  (running-on-this-thread ()
+    (when (cocoa-ref self)
+      (dcc (#/setPullsDown: (cocoa-ref self) #$YES))
+      (setf (slot-value (cocoa-ref self) 'easygui-view) self))))
+
+; -----------------------
+(defclass contextual-menu (menu-view)
+  ()
+  (:default-initargs :menu-kind :contextual-menu))
+
+(defgeneric add-contextual-menu (container menu &optional subviews))
+
+(defmethod add-contextual-menu ((window window) (menu menu-view) &optional subviews)
+  (add-contextual-menu (content-view window) menu subviews))
+
+(defmethod add-contextual-menu ((view view) (menu menu-view) &optional subviews)
+  (running-on-this-thread ()
+    (dcc (#/setMenu: (cocoa-ref view) (slot-value menu 'ns-menu)))
+    (when subviews
+      (dolist (sub (view-subviews view))
+        (unless (or (not (cocoa-null (dcc (#/menu (cocoa-ref sub)))))
+                    (typep sub 'decline-menu-mixin))
+          (add-contextual-menu sub menu subviews))))))
+
+(defmethod add-contextual-menu ((view menu-view) (refusenik decline-menu-mixin) &optional subviews)
+  (declare (ignore subviews))
+  (error "Cannot add a contextual menu to a view of class ~s" (type-of refusenik)))
+
+; -------------------------
+(defun application-object nil
+  (dcc (#/sharedApplication ns:ns-application)))
+
+(defun application-main-menu nil
+  (dcc (#/mainMenu (application-object))))
+
+(defgeneric navigate-menu (titles menu))
+
+(defmethod navigate-menu ((titles list) (menu menu-view))
+;; Returns NIL if the path of titles leads nowhere, when no appropriately titled menu-item or submenu exists;
+;; Returns a EasyGui MENU-ITEM if the path of titles leads to a leaf item;
+;; Returns a EasyGui MENU-VIEW if the path of titles leads to a submenu.
+  (cond
+   ((null titles) menu)
+   (t (let ((it (find (first titles) (menu-items menu) :test #'equalp :key #'view-text)))
+        (when it (navigate-menu (rest titles) it))))))
+
+(defun navigate-native-menu (titles menu)
+;; Returns a NIL or a NS:NS-MENU-ITEM or a NS:NS-MENU
+;; Returns a NS:NS-MENU when the title path leads to a submenu,
+;; Returns a NS;NS-MENU-ITEM when the title path leads to a leaf menu item,
+;; Returns NIL when the title path leads nowhere.
+  (running-on-this-thread ()
+    (if (null titles)
+      menu
+      (do ((number (dcc (#/numberOfItems menu)))
+           (index 0 (1+ index))
+           item found)
+          ((or found (>= index number))
+           (cond
+            ((or (null found) (null (rest titles))) found)
+            ((null (dcc (#/hasSubmenu found))) nil)
+            (t (navigate-native-menu (rest titles) (dcc (#/submenu found))))))
+        (setf item (dcc (#/itemAtIndex: menu index)))
+        (if (or (equalp (first titles) (lisp-string-from-nsstring (dcc (#/title item))))
+                ; The Apple menu item has title "" but its submenu has title "Apple", hence ...
+                (and (dcc (#/hasSubmenu item))
+                     (equalp (first titles) (lisp-string-from-nsstring (dcc (#/title (dcc (#/submenu item))))))))
+          (setf found item))))))
+
+(defmethod navigate-topbar ((titles list))
+  (navigate-native-menu titles (application-main-menu)))
+
+(defun add-menu-item (menu titles &optional action)
+;; Adds a chain of submenus and a final leaf item with the indicated action.
+;; If the final leaf item already exists, its action will be changed. Perhaps this is too dangerous.
+;; The Apple submenu may not be altered; the application's submenu cannot be found.
+  (cond
+   ((null titles)
+    (cerror "Return NIL" "No title path supplied"))
+   ((not (and (consp titles) (stringp (first titles))))
+    (cerror "Return NIL, some empty submenus may have been created" "Title path is not a list of strings"))
+   ((not (typep menu 'ns:ns-menu))
+    (cerror "Return NIL" "Not a Cocoa menu: ~s" menu))
+   (t (let* ((ns-title (ccl::%make-nsstring (first titles)))
+             (item (dcc (#/itemWithTitle: menu ns-title)))
+             (ns-nullstring (ccl::%make-nsstring "")))
+        (flet ((linkup (leaf action) ;; Modelled on code in easygui/action-targets.lisp
+                 (let ((target (make-instance 'generic-easygui-target :handler (or action #'(lambda () nil)) :shooter leaf)))
+                   (dcc (#/setTarget: leaf target))
+                   (dcc (#/setAction: leaf (\@selector #/activateAction))))))
+          (cond
+           ((equalp (first titles) "-")
+            (if (rest titles)
+              (cerror "Leave menu unchanged" "A menu separator (an item having title \"-\") may not have a submenu")
+              (dcc (#/addItem: menu (dcc (#/separatorItem ns:ns-menu-item))))))
+           ((cocoa-null item) ;; No such item, something must be added
+            (if (rest titles)
+              (let ((number (dcc (#/numberOfItems menu)))
+                    (submenu (make-instance 'ns:ns-menu)))
+                (running-on-this-thread ()
+                  (dcc (#/addItemWithTitle:action:keyEquivalent: menu ns-title ccl:+null-ptr+ ns-nullstring))
+                  (setf item (dcc (#/itemAtIndex: menu number))) ;; That's where it got put
+                  (dcc (#/initWithTitle: submenu ns-title))
+                  (dcc (#/setSubmenu: item submenu)))
+                (add-menu-item submenu (rest titles) action))
+              (let ((number (dcc (#/numberOfItems menu))))
+                (running-on-this-thread ()
+                  (dcc (#/addItemWithTitle:action:keyEquivalent: menu ns-title ccl:+null-ptr+ ns-nullstring))
+                  (setf item (dcc (#/itemAtIndex: menu number))))
+                (linkup item action))))
+           ((and (null (rest titles)) (dcc (#/hasSubmenu item)))
+            (cerror "Leave menu unchanged" "An Action may not be added to any item with a submenu"))
+           ((and (rest titles) (dcc (#/hasSubmenu item)))
+            (add-menu-item (dcc (#/submenu item)) (rest titles) action))
+           ((rest titles)
+            (cerror "Leave menu unchanged" "An existing menu item cannot be converted to have a submenu"))
+           (t (linkup item action)))))))) ;; Change the action of an existing item: desirable, or dangerous?            
+
+(defun add-topbar-item (titles &optional action)
+  (if (and (consp titles) (rest titles))
+    (add-menu-item (application-main-menu) titles action)
+    (cerror "Return NIL" "Title path must be a list with at least two elements: ~s" titles)))
+
+(defun remove-menu-item (menu titles retain-if-empty)
+  (if (not (and (consp titles) (stringp (first titles))))
+    (cerror "Return NIL" "Title path is not a list of strings")
+    (do ((number (dcc (#/numberOfItems menu)))
+         (index 0 (1+ index))
+         item found)
+        ((or found (>= index number))
+         (when found
+           (if (rest titles)
+             (when (dcc (#/hasSubmenu found))
+               (remove-menu-item (dcc (#/submenu found)) (rest titles) retain-if-empty)
+               (unless (or retain-if-empty (> (dcc (#/numberOfItems (dcc (#/submenu found)))) 0))
+                 (dcc (#/removeItem: menu found))))
+             (dcc (#/removeItem: menu found)))))
+      (setf item (dcc (#/itemAtIndex: menu index)))
+      (when (equalp (first titles) (lisp-string-from-nsstring (dcc (#/title item))))
+        (setf found item)))))
+
+(defun remove-topbar-item (titles &key retain-if-empty)
+  (when (and (consp titles)
+             (not (member (first titles) '("" "Apple") :test #'equalp)))
+    (remove-menu-item (application-main-menu) titles retain-if-empty)))
+
+(defun add-application-submenu (title &rest trees) "
+Adds a menu to the topbar application-menu with the given title.
+Its menu-items names are got from the CARs of the trees.
+The CDRs of these trees may consist either of further trees, allowing arbitrarily
+deep menu structures, or of a one-element list that is expected to be a parameterless
+function to be used as the Action of a leaf menu item.
+Example:
+  (add-application-submenu \"Beeps\"
+     '(\"Normal\" #'normal-beep)
+     '(\"Stupid\" #'stupid-beep)
+     '(\"Choose\" (\"Custom beep 1\" #'custom-beep-1-not-implemented)
+                (\"Custom beep 2\" #'custom-beep-2-not-implemented)))
+"
+  (labels ((valid-tree (tree)
+             (and (consp tree) (stringp (first tree))))
+           (prepending (seq tree)
+             (cond
+              ((every #'valid-tree (rest tree))
+               (dolist (subtree (rest tree))
+                 (prepending (append seq (list (first subtree))) (rest subtree))))
+              ((and (consp tree) (stringp (first tree)) (consp (rest tree)) (null (cddr tree)))
+               (add-topbar-item (append seq (list (first tree))) (second tree)))
+              (t (cerror "Ignore this tree" "Malformed tree ~s" tree)))))
+    (if (every #'valid-tree trees)
+      (dolist (subtree trees) (prepending (list title) subtree))
+      (cerror "Return NIL" "Malformed top-level trees"))))
+
+; ---------------
+; Keyboard input handling
+
+(defmethod view-key-event-handler ((view window) char)
+  (declare (ignorable char))
+  nil)
+
+(objc:define-objc-method ((:void :key-down (:id event)) cocoa-window)
+  (let ((*cocoa-event* event)
+        (*modifier-key-pattern* (#/modifierFlags event)))
+    (view-key-event-handler
+     (easygui-window-of self)
+     (schar (lisp-string-from-nsstring (dcc (#/charactersIgnoringModifiers event))) 0))))
+
+(defun shift-key-p nil
+  (not (zerop (logand *modifier-key-pattern* (key-mask :shift)))))
+
+(defun control-key-p nil
+  (not (zerop (logand *modifier-key-pattern* (key-mask :control)))))
+
+(defun alt-key-p nil
+  (not (zerop (logand *modifier-key-pattern* (key-mask :alt)))))
+
+(defun command-key-p nil
+  (not (zerop (logand *modifier-key-pattern* (key-mask :command)))))
+
+(defmacro with-modifier-key-information (parameterless-function)
+;; NOT TESTED YET!
+"Wraps the function into a context where control-key-p &c will get their current values.
+To be used primarily when placing a call to a function in another process."
+  (let ((gvar (gensym)))
+    `(let ((,gvar *modifier-key-pattern*))
+       (function (lambda nil
+                   (let ((*modifier-key-pattern* ,gvar))
+                     (funcall ,parameterless-function)))))))
+
+(defun view-mouse-position (view)
+  (let* ((w (cocoa-ref (easygui-window-of view)))
+         (mouselocation (dcc (#/mouseLocationOutsideOfEventStream w)))
+         (cview (if (typep view 'window) (content-view view) view))
+         (nspt (dcc (#/convertPoint:fromView: (cocoa-ref cview) mouselocation NIL))))
+    ;; todo: check point is inside bounds, lest negative coords
+    (point (ns:ns-point-x nspt) (ns:ns-point-y nspt))))
Index: /branches/new-random/examples/cocoa/interface-databases/HOWTO.html
===================================================================
--- /branches/new-random/examples/cocoa/interface-databases/HOWTO.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/interface-databases/HOWTO.html	(revision 13309)
@@ -0,0 +1,371 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>Interface Databases HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="HOWTO_files/stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Interface Databases HOWTO</h1>
+    </div>
+
+
+    <div class="section-head">
+      <h2>About Interface Databases</h2>
+    </div>
+
+    <div class="body-text">
+      <p>This HOWTO guide explains how to build interface databases
+        for Clozure CL (formerly OpenMCL).</p> 
+
+      <p>Clozure CL's <strong>interface databases</strong> are
+        descriptions of foreign data structures and functions. Clozure
+        CL uses the interface databases to call C and Objective-C
+        functions, and to use C and Objective-C data
+        structures. Clozure CL provides the interface databases you
+        are most likely to need when writing Cocoa applications, but
+        it doesn't provide databases for every foreign library and
+        framework. For some applications, you may need to generate
+        interface databases yourself. This HOWTO shows how to do
+        that.</p>
+    </div>
+
+    <div class="section-head">
+      <h4>Online Documentation</h4>
+    </div>
+
+    <div class="body-text">
+      <p>The concepts explained here are also discussed in depth in
+        the OpenMCL online
+        documentation. See <a href="http://www.openmcl.org/Doc/index.html#The-Interface-Translator">this
+          page</a> for an explanation of how to generate interface
+        databases.</p>
+    </div>
+    
+    <div class="section-head">
+      <h4>Interface Databases and the Foreign Function Interface</h4>
+    </div>
+    
+    <div class="body-text">
+      <p>Clozure CL provides an integrated foreign function interface
+        that can call external C and Objective-C functions and methods,
+        define and instantiate Objective-C classes, and read and write
+        fields of C data structures. Using these features, a Lisp
+        program can interoperate freely with external libraries and
+        frameworks. Of special interest to Mac OS X programmers, Lisp
+        programs can link Mac OS X frameworks and use the features they
+        provide, including standard OS X features such as the AppKit,
+        CoreAudio, OpenGL, CoreAnimation, and so on.</p>
+    </div>
+
+    <div class="section-head">
+      <h4>Interface Databases and Frameworks</h4>
+    </div>
+
+    <div class="body-text">
+      <p>In order to use externally-defined functions and data
+        structures, Clozure CL needs descriptions of the entry points
+        and data fields, including their names and types. It reads
+        this information from the interface databases. A separate tool
+        called ffigen parses the header files that describe foreign
+        libraries and frameworks, such as the ones provided with
+        Apple's SDKs, to produce descriptions readable by Clozure CL's
+        parse-ffi subsystem. The parse-ffi subsystem then reads these
+        descriptions and writes the results of its processing to
+        files. These files, written by parse-ffi, are what we refer to
+        as interface databases.</p>
+    </div>
+
+    <div class="section-head">
+      <h1>Adding New Interface Databases</h1>
+    </div>
+
+    <div class="body-text">
+      <p>In order to generate a new set of interface databases, you
+      must follow these steps, explained in the following
+      sections:</p>
+
+      <ol>
+        <li><p>Obtain and install the ffigen tool</p></li>
+        <li><p>Create an appropriately-named and -structured
+        subdirectory of the interfaces directory for your
+        platform</p></li>
+        <li><p>Write a script ("populate.sh") and then run it to populate the new interface
+        subdirectory</p></li>
+        <li><p>Using the parse-ffi subsystem, convert the ".ffi" files
+        created in the previous step to interface databases</p></li>
+      </ol>
+    </div>
+
+    <div class="section-head">
+      <h2>1. Obtain and install ffigen</h2>
+    </div>
+
+    <div class="body-text">
+      <p>ffigen is a command-line tool, available from Clozure, that
+        parses C and Objective-C header files for use by the Clozure
+        CL parse-ffi subsystem. A "populate.sh" script drives the
+        ffigen tool to parse library or framework headers, and then
+        the Clozure CL parse-ffi subsystem converts the ffigen output
+        to interface databases. In order to generate interface
+        databases you must first obtain the latest version of ffigen
+        for the platform you are using.</p>
+
+      <p>ffigen is available from the Clozure ftp server
+      at <a href="ftp://clozure.com/pub/testing/">clozure.com/pub/testing/</a>. A
+      separate version of ffigen is available for each supported
+      platform. Make sure to get the latest version available for the
+      platform you are using. For example,</p>
+
+      <pre>
+      ffigen-apple-gcc-5465-x86-64-2007-11-06-00-00-59 
+      </pre>
+
+      <p>supports Apple's C compiler ("gcc") on the 64-bit Intel
+      platform ("x86-64").</p>
+
+      <p>Once you have the appropriate version of ffigen, unpack and
+      install it in a location where it will be convenient to
+      use. You might, for example, install it in /usr/local/ffigen,
+      or in ~/ffigen.</p>
+
+      <p>The ffigen distribution unpacks into a directory with the
+        following structure:</p>
+      
+      <p>bin/</p>
+      <p style="margin-left: 2em; line-height: 0em">h-to-ffi.sh</p>
+      <p style="; line-height: 0em">ffigen/</p>
+      <p style="margin-left: 2em; line-height: 0em">bin/</p>
+      <p style="margin-left: 4em; line-height: 0em">ffigen</p>
+      <p style="margin-left: 2em; line-height: 0em">include/</p>
+      
+      <p>To install ffigen, unpack the distribution, then move the
+      unpacked directory to its install location. For example, to
+      install it in /usr/local/ffigen:</p>
+
+      <pre>
+      tar zxf ffigen-apple-gcc-5465-x86-64-2007-11-06-00-00-59.tar.gz
+
+      mv ffigen-apple-gcc-5465-x86-64-2007-11-06-00-00-59\
+         /usr/local/ffigen
+      </pre>
+
+      <p>You can now add a line to your shell's init script to add the
+        h-to-ffi.sh script to your PATH, and the script will find the
+        ffigen tool automatically.</p>
+      
+      <p>For example, if your shell is bash, you can add this line to
+        your .bashrc or .bash_profile:</p>
+      
+      <p><code>PATH="/usr/local/ffigen/bin:${PATH}"</code></p>
+
+    </div>
+
+    <div class="section-head">
+      <h2>2. Create An Interfaces Subdirectory</h2>
+    </div>
+
+    <div class="body-text">
+      <p>Clozure CL finds interface databases by consulting a
+        search-list. It initializes the search list when starting up,
+        and the exact contents of the search list depend on the
+        platform Clozure CL is running on. For example, a Mac OS X
+        version of Clozure CL running on the 64-bit Intel platform
+        searches "ccl/darwin-x86-headers64/", but a Mac OS X version
+        running on the 32-bit PowerPC platform searches
+        "ccl/darwin-headers/". We'll call this search directory
+        the <strong>interfaces directory</strong>. For the rest of this
+        discussion we'll assume we are running Clozure CL on Mac OS X
+        on the 64-bit Intel platform.</p>
+
+      <p>Each supported foreign library or framework has a
+      corresponding subdirectory of the interfaces directory. For
+      example, we can find a "cocoa" subdrectory of
+      "ccl/darwin-x86-headers64/"; it contains the interface databases
+      for the Cocoa framework. Similarly, the "gl" subdirectory
+      contains the interface databases for OpenGL.</p>
+
+      <p>In order to add support for a new framework, we must first
+      add a subdirectory for the framework to the interfaces
+      directory. For example, suppose we want to add support for the
+      TWAIN framework. This framework is one of the standard frameworks
+      provided in Mac OS X 10.5, but not one of those supported
+      out-of-the-box by Clozure CL.</p>
+
+      <p>To add TWAIN interfaces for use by Clozure CL, follow these
+      steps:</p>
+
+      <ol>
+        <li><p>Create a subdirectory called "twain" in the interfaces directory</p></li>
+        <li>
+          <p>Create a subdirectory of "twain" called "C".</p>
+          <p>If you look inside any of the existing interfaces
+          subdirectories, you see that each one contains a similar
+          "C" subdirectory. The ffigen tool populates these "C"
+          subdirectories with ".ffi" files when it parses the
+          framework or library headers.</p>
+        </li>
+        <li>
+          <p>Inside the "C" subdirectory, create a file called
+          "populate.sh"</p>
+          <p>Again, you can see that the existing interfaces
+          subdirectories contain "populate.sh" files in their "C"
+          subdirectories. This file is the script that drives the
+          ffigen tool for the particular interface databases we are
+          creating. The next section explains what to put in the
+          "populate.sh" file.</p>
+        </li>
+      </ol>
+
+    </div>
+
+    <div class="section-head">
+      <h2>3. Write and Run a "populate.sh" Script</h2>
+    </div>
+
+      <div class="body-text">
+        <p>If you look in the directory</p>
+      
+      <p>ccl/darwin-x86-headers64/cocoa/C/</p>
+      
+      <p>for example, you'll find a script named populate.sh. The
+        script sets up flags for the C compiler, and then calls
+        h-to-ffi.sh on each of several header files that define the
+        Objective-C data structures and entry points used by the Cocoa
+        framework. The first step in generating or regenerating the
+        interface databases is to run one of these populate.sh
+        scripts.</p>
+
+      <p>You can create a populate.sh script by copying an existing
+        one from another set of interfaces, then replacing the
+        references to the libraries or frameworks that the
+        populate.sh script processes. A good place to start is with
+        an existing populate.sh script that processes a library or
+        framework that is similar to, or related to, the one you want
+        to add.</p>
+
+      <p>For example, for our TWAIN interfaces, we can copy the
+        populate.sh script from the existing qtkit subdirectory. The
+        contents of the qtkit script are:</p>
+
+
+      <pre>
+#!/bin/sh
+# For now, things earlier than the 10.5 sdk are pointless
+rm -rf System Developer usr
+SDK=/Developer/SDKs/MacOSX10.5.sdk
+CFLAGS="-m64 -fobjc-abi-version=2 -isysroot ${SDK} -mmacosx-version-min=10.5"; export CFLAGS
+h-to-ffi.sh ${SDK}/System/Library/Frameworks/QTKit.framework/Headers/QTKit.h
+      </pre>
+
+
+      <p>Now we just need to change the reference to the QTKit header
+      file so that it refers instead to the TWAIN header file:</p>
+
+      <pre>
+#!/bin/sh
+# For now, things earlier than the 10.5 sdk are pointless
+rm -rf System Developer usr
+SDK=/Developer/SDKs/MacOSX10.5.sdk
+CFLAGS="-m64 -fobjc-abi-version=2 -isysroot ${SDK} -mmacosx-version-min=10.5"; export CFLAGS
+h-to-ffi.sh ${SDK}/System/Library/Frameworks/TWAIN.framework/Headers/TWAIN.h
+      </pre>
+
+      <p>Next you must run the script to generate the ".ffi" files
+      that will be used in the next step. Assuming you installed
+      ffigen as described in step 1, and made sure that it's on your
+      PATH, all you have to do is cd to the directory that contains
+      your new populate.sh script and execute it:</p>
+
+      <pre>
+$ ./populate.sh
++++ /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/TWAIN.framework/Headers/TWAIN.h
+      </pre>
+
+      <p>Now, if you look inside the C subdirectory of your twain
+      directory, you should find that it has been populated with
+      ".ff" files:</p>
+
+      <pre>
+oshirion:C mikel$ ls
+./           ../          Developer/   populate.sh*
+
+oshirion:C mikel$ ls Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/TWAIN.framework/Headers/
+./         ../        TWAIN.ffi
+        
+      </pre>
+    </div>
+
+    <div class="section-head">
+      <h2>4. Use parse-ffi to Generate Interface Databases</h2>
+    </div>
+
+    <div class="body-text">
+      <p>The ".ffi" files, created in the prevoius step, contain a
+        series of s-expressions readable by the Clozure CL parse-ffi
+        subsystem. Each s-expression describes a datastructure or
+        entry point in the foreign library.</p>
+
+      <p>Once you have created a set of these ".ffi" files by running
+        a populate.sh script, you must next use Clozure CL to convert
+        the ".ffi" files into interface database files.</p>
+
+      <ol>
+        <li><p>First, launch Clozure CL</p></li>
+        <li>
+          <p>Next, evaluate this form to load the parse-ffi subsystem:</p>
+          <p><code>(require "PARSE-FFI")</code></p>
+        </li>
+        <li>
+          <p>Next, supposing you want to parse the TWAIN files
+            created in the previous section, evaluate the following form:</p>
+          <p><code>(ccl::parse-standard-ffi-files :twain)</code></p>
+          <p>The parse-ffi subsystem looks for a subdirectory named
+            "twain" in the interface databases directory for the
+            current platform.</p>
+
+          <p>The first time you run this expression, you'll see
+          warnings like this one:</p>
+          <pre>
+; Warning: Interface file #P"ccl:darwin-x86-headers64;twain;types.cdb.newest" does not exist.
+          </pre>
+          <p>These warnings are normal.</p>
+        </li>
+        <li>
+          <p>Finally, evaluate the following form once more:</p>
+          <p><code>(ccl::parse-standard-ffi-files :twain)</code></p>
+          <p>In order to correctly describe some foreign definitions,
+            the parse-ffi subsystem needs information provided by the
+            first parse. Thus, to produce a complete and corrrect set of
+            interface databases, you should always evaluate
+            the <code>parse-standard-ffi-files</code> form twice.</p>
+        </li>
+      </ol>
+
+    </div>
+
+
+    <div class="section-head">
+      <h2>Conclusion</h2>
+    </div>
+
+    <div class="body-text">
+      <p>Assuming all went well, you should now find a new set of
+        interface database files in the twain subdirectory of the
+        interface databases directory for your current
+        platform. Congratulations! You have added a new set of
+        interface databases to your Clozure CL installation.</p>
+
+      <p>For more information about ffigen and the interface
+        translation process, refer to the online documentation for the
+        <a href="http://www.openmcl.org/Doc/index.html#The-Interface-Translator">Interface
+          Translator</a>.</p>
+    </div>
+
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/interface-databases/HOWTO_files/stylesheets/styles.css
===================================================================
--- /branches/new-random/examples/cocoa/interface-databases/HOWTO_files/stylesheets/styles.css	(revision 13309)
+++ /branches/new-random/examples/cocoa/interface-databases/HOWTO_files/stylesheets/styles.css	(revision 13309)
@@ -0,0 +1,55 @@
+body {
+	background-color: white;
+	font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
+}
+
+.title {
+	text-align: center;
+	font-size: 16pt;
+}
+
+.subtitle {
+	font-size: medium;
+	font-weight: bold;
+	text-align: center;
+}
+
+.byline {
+	text-align: center;
+	font-weight: bold;
+	font-size: small;
+}
+
+.section-head {
+	padding-top: 2em;
+	padding-left: 1em;
+}
+
+.body-text {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 4em;
+	margin-right: 4em;
+	text-indent: 3em;
+}
+
+.note {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 6em;
+	margin-right: 6em;
+	text-indent: 0em;
+}
+
+.inline-image {
+	text-align: center;
+}
+
+.nav {
+	text-align: center;
+	font-size: large;
+	font-weight: bold;
+	padding-top: 4em;
+}
+
+li, pre {
+	text-indent: 0;
+}
Index: /branches/new-random/examples/cocoa/nib-loading/HOWTO.html
===================================================================
--- /branches/new-random/examples/cocoa/nib-loading/HOWTO.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/nib-loading/HOWTO.html	(revision 13309)
@@ -0,0 +1,441 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>Nib-Loading HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="HOWTO_files/stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>Nib-Loading HOWTO</h1>
+    </div>
+
+    <div class="body-text">
+      <p>This HOWTO shows how you can load <strong>nibfiles</strong>
+        into a running copy of Clozure CL by evaluating Lisp forms. You
+        might want to load nibfiles this way to test user-interface
+        elements that you are working on for an application project, or
+        to enable an application to dynamically load optional
+        user-interface elements.</p>
+
+    </div>
+
+    <div class="section-head">
+      <h2>Nibfiles</h2>
+    </div>
+
+    <div class="body-text">
+      <p>A large part of developing Cocoa applications is creating
+        user-interface elements using the Cocoa frameworks. Although
+        it's perfectly possible to create any user-interface element
+        just by making method calls against the frameworks, the more
+        standard way to design a user interface is to use Apple's
+        InterfaceBuilder application to
+        create <strong>nibfiles</strong>&mdash;files of archived
+        Objective-C objects that implement the user-interface
+        elements.</p>
+      
+      <p>InterfaceBuilder is an application that ships with Apple's
+        Developer Tools. The Developer Tools are an optional install
+        that comes with Mac OS X. Before you can use this HOWTO, you'll
+        need to make sure that Apple's Developer Tools are installed on
+        your system. Members of Apple's developer programs may download
+        the tools for free from
+        Apple's <href="http://developer.apple.com">developer
+          website</href>, but normally there is no need. You can simply
+        use the optional Developer Tools installer on the Mac OS X
+        system disks to install the tools.</p>
+    </div>
+
+    <div class="section-head">
+      <h2>Using Nibfiles</h2> 
+    </div>
+
+    <div class="body-text">
+      <p>Using InterfaceBuilder, you can quickly and easily create
+        windows, dialog boxes, text fields, buttons, and other
+        user-interface elements. The elements you create with
+        InterfaceBuilder have the standard appearance and behavior
+        specified by Apple's Human Interface Guidelines.</p>
+
+      <p>InterfaceBuilder saves descriptions of these objects
+        in <strong>nibfiles</strong>. These files contain archived
+        representations of Objective-C classes and objects. When you
+        launch an application and it loads a nibfile, the Cocoa runtime
+        creates these Objective-C objects in memory, complete with any
+        instance-variable references to other objects that might have
+        been saved in the nibfile. In short, a nibfile is an archived
+        collection of user-interface objects that Cocoa can quickly and
+        easily revive in memory.</p>
+
+      <p>The normal way that Objective-C programmers use nibfiles is
+        by storing them in an application bundle. The application's
+        Info.plist file (also stored in the bundle) specifies which
+        nibfile is the application's main nibfile, and that file is
+        loaded automatically when the application starts up. The
+        application can dynamically load other nibfiles from the bundle
+        by making method calls.</p>
+
+      <p>Lisp applications written with Clozure CL can also use
+        nibfiles in this same fashion (see the "currency-converter"
+        HOWTO in the "cocoa" examples folder), but Lisp programmers are
+        accustomed to highly interactive development, and might want to
+        simply load an arbitrary nibfile into a running Clozure CL
+        session. Fortunately, this is easy to do.</p>
+    </div>
+
+    <div class="section-head">
+      <h2>How To Load a Nibfile</h2> 
+    </div>
+
+    <div class="body-text">
+      <p>Let's start by loading a very simple nibfile from the Clozure
+        CL Listener window. Start by launching the Clozure CL
+        application.</p>
+
+      <p>In the same directory as this HOWTO file, you'll find a
+        nibfile named "hello.nib". This is an extremely simple nibfile
+        that creates a single Cocoa window with a greeting in it. We'll
+        use forms typed into the Listener window to load it.</p>
+
+      <p>We're going to call the Objective-C class
+        method <code>loadNibFile:externalNameTable:withZone:</code> to
+        load the nibfile into memory, creating the window that is
+        described in the file. First, though, we need to set up some
+        data structures that we'll pass to this method.</p>
+
+      <p>The arguments
+        to <code>loadNibFile:externalNameTable:withZone:</code> are a
+        pathname, a dictionary object, and a memory zone. As with every
+        Objective-C method call, we also pass the object that receives
+        the message, which in this case is the class NSBundle.</p>
+
+      <p>The pathname is just a reference to the nibfile we want to
+        load. The dictionary holds references to objects. In this
+        first simple example, we'll use it only to identify the
+        nibfile's owner, which in this case is the application
+        itself. The zone is a reference to the area of memory where
+        the nibfile objects will be allocated.</p>
+
+      <p>Don't worry if none of this makes sense to you; the code to
+        create these objects is simple and straightforward, and should
+        help clarify what's going on.</p>
+
+      <div class="section-head">
+        <h3>1. Get the Zone</h3> 
+      </div>
+
+      <p>First, we'll get a memory zone. We'll tell Cocoa to allocate
+        the nibfile objects in the same zone that the application
+        uses, so getting a zone is a simple matter of asking the
+        application for the one it's using.</p>
+
+      <p>Before we can ask the application anything, we need a
+        reference to it.  When the Clozure CL application starts up,
+        it stores a reference to the Cocoa application object into
+        the special variable *NSApp*.</p>
+
+      <p>Start by changing to the CCL package; most of the utility
+        functions we'll use are defined in that package:</p>
+
+      <pre>
+        ? (in-package :ccl)
+        #&lt;Package "CCL"&gt;
+      </pre>
+
+      <p>We have a reference to the running Clozure CL application
+        object in the special variable *NSApp*.  We can ask it for its
+        zone, where it allocates objects in memory:</p>
+
+      <pre>
+        ? (setf *my-zone* (#/zone *NSApp*))
+        #&lt;A Foreign Pointer #x8B000&gt;
+      </pre>
+
+      <p>Now we have a reference to the application's zone, which is
+        one of the parameters we need to pass
+        to <code>loadNibFile:externalNameTable:withZone:</code>.</p>
+
+      <div class="section-head">
+        <h3>2. Make a Dictionary</h3> 
+      </div>
+
+      <p>The dictionary argument
+        to <code>loadNibFile:externalNameTable:withZone:</code> is
+        used for two purposes: to identify the nibfile's owner, and
+        to collect toplevel objects.</p>
+
+      <p>The nibfile's owner becomes the owner of all the toplevel
+        objects created when the nibfile is loaded, objects such as
+        windows, buttons, and so on. A nibfile's owner manages the
+        objects created when the nibfile is loaded, and provides a
+        way for your code to get references to those objects. You
+        supply an owner object in the dictionary, under the
+        key <code>"NSNibOwner"</code>.</p>
+
+      <p>The toplevel objects are objects, such as windows, that are
+        created when the nibfile is loaded. To collect these, you
+        can pass an <code>NSMutableArray</code> object under the
+        key <code>NSNibTopLevelObjects</code>.</p>
+
+      <p>For this first example, we'll pass an owner object (the
+        application object), but we don't need to collect toplevel
+        objects, so we'll omit
+        the <code>NSNibTopLevelObjects</code> key.</p>
+
+      <pre>
+        ? (setf *my-dict* 
+        (#/dictionaryWithObject:forKey: ns:ns-mutable-dictionary
+        *my-app* 
+        #@"NSNibOwner"))
+        #&lt;NS-MUTABLE-DICTIONARY {
+        NSNibOwner = &lt;LispApplication: 0x1b8e10&gt;;
+        } (#x137F3DD0)&gt;
+        
+      </pre>
+
+      <div class="section-head">
+        <h3>3. Load the Nibfile</h3> 
+      </div>
+
+      <p>Now that we have the zone and the dictionary we need, we
+        can load the nibfile. We just need to create an NSString with
+        the proper pathname first:</p>
+
+      <pre>
+        ? (setf *nib-path* 
+        (%make-nsstring 
+        (namestring "/usr/local/openmcl/ccl/examples/cocoa/nib-loading/hello.nib")))
+        #&lt;NS-MUTABLE-STRING "/usr/local/openmcl/ccl/examples/cocoa/nib-loading/hello.nib" (#x13902C10)&gt;
+      </pre>
+
+      <p>Now we can actually load the nibfile, passing the method
+        the objects we've created:</p>
+
+      <pre>
+        ? (#/loadNibFile:externalNameTable:withZone: 
+        ns:ns-bundle
+        *nib-path*
+        *my-dict*
+        *my-zone*)
+        T
+      </pre>
+
+      <p>The window defined in the "hello.nib" file should appear
+        on the
+        screen. The <code>loadNibFile:externalNameTable:withZone:</code>
+        method returns <code>T</code> to indicate it loaded the
+        nibfile successfully; if it had failed, it would have
+        returned <code>NIL</code>.</p>
+
+      <p>At this point we no longer need the pathname and
+        dictionary objects.  The *nib-path* we must release:</p>
+
+      <pre>
+        ? (setf *nib-path* (#/release *nib-path*))
+        NIL
+      </pre>
+
+      <p>The *my-dict* instance was not created with #/alloc (or with
+      MAKE-INSTANCE), so it is already autoreleased, and we don't need
+      to release it again.
+
+      <div class="section-head">
+        <h2>Making a Nib-loading Function</h2> 
+      </div>
+
+      <p>Loading a nibfile seems like something we might want to do
+        repeatedly, and so it makes sense to make it as easy as possible
+        to do. Let's make a single function we can call to load a nib as
+        needed.</p>
+
+      <p>The nib-loading function can take the file to be loaded as a
+      parameter, and then perform the sequence of steps covered in the
+      previous section. If we just literally do that, the result will
+      look something like this:</p>
+
+      <pre>
+(defun load-nibfile (nib-path)
+  (let* ((app-zone (#/zone *NSApp*))
+         (nib-name (%make-nsstring (namestring nib-path)))
+         (dict (#/dictionaryWithObject:forKey: 
+                 ns-mutable-dictionary app #@"NSNibOwner")))
+    (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
+                                               nib-name
+                                               dict
+                                               app-zone
+                                             )))
+      </pre>
+
+      <p>The trouble with this function is that it leaks a string
+      every time we call it. We need to release the
+      <code>nib-name</code> before returning. So how about this
+      version instead?</p>
+
+      <pre>
+(defun load-nibfile (nib-path)
+  (let* ((app-zone (#/zone *NSApp*))
+         (nib-name (%make-nsstring (namestring nib-path)))
+         (dict (#/dictionaryWithObject:forKey: 
+                ns-mutable-dictionary app #@"NSNibOwner"))
+         (result (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
+                                                            nib-name
+                                                            dict
+                                                            app-zone)))
+    (#/release nib-name)
+    result))
+      </pre>
+
+      <p>This version solves the leaking problem by binding the result
+      of the load call to <code>result</code>, then releasing the
+      <code>nib-name</code> before returning the result of the
+      load.</p>
+
+      <p>There's just one more problem: what if we want to use the
+      dictionary to collect the nibfile's toplevel objects, so that we
+      can get access to them from our code? We'll need another version
+      of our function.</p>
+
+      <p>In order to collect toplevel objects, we'll want to pass an
+      NSMutableArray object in the dictionary, stored under the key
+      <code>NSNibTopLevelObjects</code>. So we first need to create such an
+      array object in the <code>let</code> form:</p>
+
+      <pre>
+(let* (...
+       (objects-array (#/arrayWithCapacity: ns:ns-mutable-array 16))
+       ...)
+  ...)
+      </pre>
+
+      <p>Now that we have the array in which to store the nibfile's
+      toplevel objects, we need to change the code that creates the
+      dictionary, so that it contains not only the owner object, but
+      also the array we just created:</p>
+
+      <pre>
+  (let* (...
+         (dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
+                    app #@"NSNibOwner"
+                    objects-array #&amp;NSNibTopLevelObjects
+                    +null-ptr+))
+         ...)
+    ...)
+  
+      </pre>
+
+      <p>We now want to collect the objects in it. We'll do that by
+      making a local variable to store them, then iterating over the
+      array object to get them all.  (Normally, when we want to keep
+      an object from an array, we have to retain it.  Top-level nib
+      objects are a special case: they are created by the nib loading
+      process with a retain count of 1, and we are responsible for releasing
+      them when we're through with them.)</p>
+
+      <pre>
+  (let* (...
+         (toplevel-objects (list))
+         ...)
+    (dotimes (i (#/count objects-array))
+      (setf toplevel-objects 
+            (cons (#/objectAtIndex: objects-array i)
+                  toplevel-objects)))
+    ...)
+      </pre>
+
+      <p>After collecting the objects, we can release the array, then
+      return the list of objects. It's still possible we might want
+      to know whether the load succeeded, so we
+      use <code>values</code> to return both the toplevel objects and
+      the success or failure of the load.</p>
+
+      <p>The final version of the nib-loading code looks like
+      this:</p>
+
+      <pre>
+(defun load-nibfile (nib-path)
+  (let* ((app-zone (#/zone *NSApp*))
+         (nib-name (%make-nsstring (namestring nib-path)))
+         (objects-array (#/arrayWithCapacity: ns:ns-mutable-array 16))
+         (dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
+                    *NSApp* #@"NSNibOwner"
+                    objects-array #&NSNibTopLevelObjects
+		    +null-ptr+))
+         (toplevel-objects (list))
+         (result (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
+                                                            nib-name
+                                                            dict
+                                                            app-zone)))
+    (dotimes (i (#/count objects-array))
+      (setf toplevel-objects 
+            (cons (#/objectAtIndex: objects-array i)
+                  toplevel-objects)))
+    (#/release nib-name)
+    (values toplevel-objects result)))
+      </pre>
+
+      <p>Now we can call this function with some suitable nibfile,
+      such as simple "hello.nib" that comes with this HOWTO:</p>
+
+      <pre>
+? (ccl::load-nibfile "hello.nib")
+(#&lt;LISP-APPLICATION &lt;LispApplication: 0x1b8da0&gt; (#x1B8DA0)&gt;
+ #&lt;NS-WINDOW &lt;NSWindow: 0x171344d0&gt; (#x171344D0)&gt;)
+T
+
+      </pre>
+
+      <p>The "Hello!" window appears on the screen, and two values are
+      returned. The first value is the list of toplevel objects that
+      were loaded. The second value, <code>T</code> indicates that the
+      nibfile was loaded successfully.</p>
+
+      <div class="section-head">
+        <h2>What About Unloading Nibfiles?</h2> 
+      </div>
+      
+      <p>Cocoa provides no general nibfile-unloading API. Instead, if
+      you want to unload a nib, the accepted approach is to close all
+      the windows associated with a nibfile and release all the
+      toplevel objects. This is one reason that you might want to use
+      the <code>"NSNibTopLevelObjects"</code> key with the dictionary
+      object that you pass
+      to <code>loadNibFile:externalNameTable:withZone:</code>&mdash;to
+      obtain a collection of toplevel objects that you release when
+      the nibfile is no longer needed.</p>
+
+      <p>In document-based Cocoa applications, the main nibfile is
+      usually owned by the application object, and is never unloaded
+      while the application runs. Auxliliary nibfiles are normally
+      owned by controller objects, usually instances of
+      <code>NSWindowController</code> subclasses. When you
+      use <code>NSWindowController</code> objects to load nibfiles,
+      they take responsibility for loading and unloading nibfile
+      objects.</p>
+
+      <p>When you're experimenting interactively with nibfile loading,
+      you may not start out by
+      creating <code>NSWindowController</code> objects to load
+      nibfiles, and so you may need to do more of the object
+      management yourself. On the one hand, loading nibfiles by hand
+      is not likely to be the source of major application problems. On
+      the other hand, if you experiment with nib-loading for a long
+      time in an interactive session, it's possible that you'll end up
+      with numerous discarded objects cluttering memory, along with
+      various references to live and possibly released objects. Keep
+      this in mind when using the Listener to explore Cocoa. You can
+      always restore your Lisp system to a clean state by restarting
+      it, but of course you then lose whatever state you have built up
+      in your explorations. It's often a good idea to work from a text
+      file rather than directly in the Listener, so that you have a
+      record of the experimenting you've done. That way, if you need
+      to start fresh (or if you accidentally cause the application to
+      crash), you don't lose all the information you gained.</p>
+
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/nib-loading/HOWTO_files/stylesheets/styles.css
===================================================================
--- /branches/new-random/examples/cocoa/nib-loading/HOWTO_files/stylesheets/styles.css	(revision 13309)
+++ /branches/new-random/examples/cocoa/nib-loading/HOWTO_files/stylesheets/styles.css	(revision 13309)
@@ -0,0 +1,55 @@
+body {
+	background-color: white;
+	font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
+}
+
+.title {
+	text-align: center;
+	font-size: 16pt;
+}
+
+.subtitle {
+	font-size: medium;
+	font-weight: bold;
+	text-align: center;
+}
+
+.byline {
+	text-align: center;
+	font-weight: bold;
+	font-size: small;
+}
+
+.section-head {
+	padding-top: 2em;
+	padding-left: 1em;
+}
+
+.body-text {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 4em;
+	margin-right: 4em;
+	text-indent: 3em;
+}
+
+.note {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 6em;
+	margin-right: 6em;
+	text-indent: 0em;
+}
+
+.inline-image {
+	text-align: center;
+}
+
+.nav {
+	text-align: center;
+	font-size: large;
+	font-weight: bold;
+	padding-top: 4em;
+}
+
+li, pre {
+	text-indent: 0;
+}
Index: /branches/new-random/examples/cocoa/nib-loading/hello.nib/designable.nib
===================================================================
--- /branches/new-random/examples/cocoa/nib-loading/hello.nib/designable.nib	(revision 13309)
+++ /branches/new-random/examples/cocoa/nib-loading/hello.nib/designable.nib	(revision 13309)
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.01">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9B18</string>
+		<string key="IBDocument.InterfaceBuilderVersion">629</string>
+		<string key="IBDocument.AppKitVersion">949</string>
+		<string key="IBDocument.HIToolboxVersion">343.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="2"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string id="870287340">com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">NSObject</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">271</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 453}, {201, 57}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Hello!</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="271518147">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 20}, {167, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSWindow"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="496854791">
+								<int key="NSCellFlags">67239488</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Hello from the nib loader!</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="271518147"/>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName" id="170108980">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<reference key="NSCatalogName" ref="170108980"/>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{201, 57}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="271518147"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="271518147"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="496854791"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="496854791"/>
+						<reference key="parent" ref="271518147"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>2.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<reference ref="870287340"/>
+					<reference ref="870287340"/>
+					<reference ref="870287340"/>
+					<reference ref="870287340"/>
+					<string>{{513, 516}, {201, 57}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{513, 516}, {201, 57}}</string>
+					<reference ref="870287340"/>
+					<string id="640133108">com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<reference ref="640133108"/>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">4</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableData" key="IBDocument.RunnableNib">
+			<bytes key="NS.bytes">YnBsaXN0MDDUAAEAAgADAAQABQAGAAkAClgkdmVyc2lvblQkdG9wWSRhcmNoaXZlclgkb2JqZWN0cxIA
+AYag0QAHAAhdSUIub2JqZWN0ZGF0YYABXxAPTlNLZXllZEFyY2hpdmVyrxBCAAsADAAxADUANgA7ADwA
+QQBVAFYAVwBYAAsAZQBpAHUAdgCGAIcAjwCQAJMAnACdAJ4AowClAKoAqwCuALIAuAC8AAsAvQC/AMAA
+wwDHAMoA0gDVANYA2ADgAOkA8gDzAPQA9QD2APcA+AD7AP4BBwBSAKEBEAERARIBEwEUARcBGgEdVSRu
+dWxs3xASAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAn
+ACgAKQAqACsALAAtAC4ALwAwVk5TUm9vdFYkY2xhc3NdTlNPYmplY3RzS2V5c18QD05TQ2xhc3Nlc1Zh
+bHVlc18QGU5TQWNjZXNzaWJpbGl0eU9pZHNWYWx1ZXNdTlNDb25uZWN0aW9uc1tOU05hbWVzS2V5c1tO
+U0ZyYW1ld29ya11OU0NsYXNzZXNLZXlzWk5TT2lkc0tleXNdTlNOYW1lc1ZhbHVlc18QGU5TQWNjZXNz
+aWJpbGl0eUNvbm5lY3RvcnNdTlNGb250TWFuYWdlcl8QEE5TVmlzaWJsZVdpbmRvd3NfEA9OU09iamVj
+dHNWYWx1ZXNfEBdOU0FjY2Vzc2liaWxpdHlPaWRzS2V5c1lOU05leHRPaWRcTlNPaWRzVmFsdWVzgAKA
+QYAngDWAQIAmgCyABYA0gDaALYA+gACABoArgD8QBoA30gAOADIAMwA0W05TQ2xhc3NOYW1lgASAA1hO
+U09iamVjdNIANwA4ADkAOlgkY2xhc3Nlc1okY2xhc3NuYW1logA6ADVeTlNDdXN0b21PYmplY3RfEBBJ
+QkNvY29hRnJhbWV3b3Jr0gAOAD0APgA/Wk5TLm9iamVjdHOAJaEAQIAH2gBCAA4AQwBEAEUARgBHAEgA
+SQBKAEsATABNAE4ATwBQAFEAUgBTACtcTlNXaW5kb3dWaWV3XE5TU2NyZWVuUmVjdF1OU1dpbmRvd1Rp
+dGxlWU5TV1RGbGFnc11OU1dpbmRvd0NsYXNzXE5TV2luZG93UmVjdF8QD05TV2luZG93QmFja2luZ18Q
+EU5TV2luZG93U3R5bGVNYXNrW05TVmlld0NsYXNzgAuAJIAjgAkSIAAAAIAKgAgQAhEBD4AAXxAXe3sx
+OTYsIDQ1M30sIHsyMDEsIDU3fX1WSGVsbG8hWE5TV2luZG931wBZAA4AWgBbAFwAVwBdAF4AXwBgAGEA
+YgBeAGRfEA9OU05leHRSZXNwb25kZXJaTlNTdWJ2aWV3c1hOU3ZGbGFnc1tOU0ZyYW1lU2l6ZVtOU1N1
+cGVydmlld4AMgCKADREBAIAggAyAIdIADgA9AGYAZ4AfoQBogA7YAFkADgBqAGsAWwBsAFcAXQBLAG4A
+bwBwAHEAcgBeAEtXTlNGcmFtZVZOU0NlbGxZTlNFbmFibGVkgAuAHoAPgBARAQwJgAyAC18QFXt7MTcs
+IDIwfSwgezE2NywgMTd9fdgAdwAOAHgAeQB6AHsAfAB9AH4AfwCAAIEAggBoAIQAhVtOU0NlbGxGbGFn
+c18QEU5TQmFja2dyb3VuZENvbG9yWk5TQ29udGVudHNZTlNTdXBwb3J0XU5TQ29udHJvbFZpZXdcTlND
+ZWxsRmxhZ3MyW05TVGV4dENvbG9yEgQB/kCAHYAVgBGAEoAOEhBABACAGl8QGkhlbGxvIGZyb20gdGhl
+IG5pYiBsb2FkZXIh1AAOAIgAiQCKAIsAjACNAI5WTlNTaXplVk5TTmFtZVhOU2ZGbGFnc4AUI0AqAAAA
+AAAAgBMRBBRcTHVjaWRhR3JhbmRl0gA3ADgAkQCSogCSADVWTlNGb2501QAOAJQAlQCWAJcAmACZAC8A
+mgCbV05TQ29sb3JcTlNDb2xvclNwYWNlW05TQ29sb3JOYW1lXU5TQ2F0YWxvZ05hbWWAGYAYgBeAFlZT
+eXN0ZW1cY29udHJvbENvbG9y0wAOAJUAnwCYAKEAoldOU1doaXRlgBkQA0swLjY2NjY2NjY5ANIANwA4
+AKQAlKIAlAA11QAOAJQAlQCWAJcAmACnAC8AqACbgBmAHIAbgBZfEBBjb250cm9sVGV4dENvbG9y0wAO
+AJUAnwCYAKEArYAZQjAA0gA3ADgArwCwpACwALEAawA1XxAPTlNUZXh0RmllbGRDZWxsXE5TQWN0aW9u
+Q2VsbNIANwA4ALMAtKUAtAC1ALYAtwA1W05TVGV4dEZpZWxkWU5TQ29udHJvbFZOU1ZpZXdbTlNSZXNw
+b25kZXLSADcAOAC5ALqjALoAuwA1Xk5TTXV0YWJsZUFycmF5V05TQXJyYXlZezIwMSwgNTd90gA3ADgA
+vgC2owC2ALcANV8QFnt7MCwgMH0sIHsxOTIwLCAxMTc4fX3SADcAOADBAMKiAMIANV8QEE5TV2luZG93
+VGVtcGxhdGXSADcAOADEAMWjAMUAxgA1XE5TTXV0YWJsZVNldFVOU1NldNIADgA9AGYAyYAfoNIADgA9
+AMsAzIAqpQBLAGgAzwBAAHCAC4AOgCiAB4AQ0gAOADIAMwDUgASAKV1OU0FwcGxpY2F0aW9u0gA3ADgA
+1wC7ogC7ADXSAA4APQDLANqAKqUAQABLAB8AHwBogAeAC4ACgAKADtIADgA9AMsA4oAqpgBLAGgAzwBA
+AB8AcIALgA6AKIAHgAKAENIADgA9AMsA64AqpgDsAO0A7gDvAPAA8YAugC+AMIAxgDKAM1xDb250ZW50
+IFZpZXdfEChTdGF0aWMgVGV4dCAoSGVsbG8gZnJvbSB0aGUgbmliIGxvYWRlciEpW0FwcGxpY2F0aW9u
+XxAPV2luZG93IChIZWxsbyEpXEZpbGUncyBPd25lcl8QLFRleHQgRmllbGQgQ2VsbCAoSGVsbG8gZnJv
+bSB0aGUgbmliIGxvYWRlciEp0gAOAD0AywD6gCqg0gAOAD0AywD9gCqg0gAOAD0AywEAgCqmAEsAaADP
+AEAAHwBwgAuADoAogAeAAoAQ0gAOAD0AywEJgCqmAQoBCwEMAQ0BDgEPgDiAOYA6gDuAPIA9E///////
+///9EAEQBRAE0gAOAD0AZgEWgB+g0gAOAD0AywEZgCqg0gAOAD0AywEcgCqg0gA3ADgBHgEfogEfADVe
+TlNJQk9iamVjdERhdGEACAAZACIAJwAxADoAPwBEAFIAVABmAO0A8wE+AUUBTAFaAWwBiAGWAaIBrgG8
+AccB1QHxAf8CEgIkAj4CSAJVAlcCWQJbAl0CXwJhAmMCZQJnAmkCawJtAm8CcQJzAnUCdwJ5AoICjgKQ
+ApICmwKkAq0CuAK9AswC3wLoAvMC9QL4AvoDIwMwAz0DSwNVA2MDcAOCA5YDogOkA6YDqAOqA68DsQOz
+A7UDuAO6A9QD2wPkBAEEEwQeBCcEMwQ/BEEEQwRFBEgESgRMBE4EVwRZBFwEXgR/BIcEjgSYBJoEnASe
+BKAEowSkBKYEqATABOEE7QUBBQwFFgUkBTEFPQVCBUQFRgVIBUoFTAVRBVMFcAWBBYgFjwWYBZoFowWl
+BagFtQW+BcMFygXfBecF9AYABg4GEAYSBhQGFgYdBioGNwY/BkEGQwZPBlgGXQZyBnQGdgZ4BnoGjQaa
+BpwGnwaoBrEGwwbQBtkG5AbwBvoHAQcNBxYHHQcsBzQHPgdHB04HZwdwB3UHiAeRB5gHpQerB7QHtge3
+B8AHwgfNB88H0QfTB9UH1wfgB+IH5AfyB/sIAAgJCAsIFggYCBoIHAgeCCAIKQgrCDgIOgg8CD4IQAhC
+CEQITQhPCFwIXghgCGIIZAhmCGgIdQigCKwIvgjLCPoJAwkFCQYJDwkRCRIJGwkdCSoJLAkuCTAJMgk0
+CTYJPwlBCU4JUAlSCVQJVglYCVoJYwllCWcJaQlyCXQJdQl+CYAJgQmKCYwJjQmWCZsAAAAAAAACAgAA
+AAAAAAEgAAAAAAAAAAAAAAAAAAAJqg</bytes>
+		</object>
+	</data>
+</archive>
Index: /branches/new-random/examples/cocoa/nib-loading/nib-loading.lisp
===================================================================
--- /branches/new-random/examples/cocoa/nib-loading/nib-loading.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/nib-loading/nib-loading.lisp	(revision 13309)
@@ -0,0 +1,37 @@
+;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: cl-user -*-
+;;;; ***********************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          nib-loading.lisp
+;;;; Version:       0.1
+;;;; Project:       cocoa examples
+;;;; Purpose:       examples of loading nibs dynamically in the IDE
+;;;;
+;;;; ***********************************************************************
+
+(in-package :ccl)
+
+(defun load-nibfile (nib-path)
+  (let* ((app-zone (#/zone *NSApp*))
+         (nib-name (%make-nsstring (namestring nib-path)))
+         (objects-array (#/arrayWithCapacity: ns:ns-mutable-array 16))
+         (dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
+                    *NSApp* #&NSNibOwner
+                    objects-array #&NSNibTopLevelObjects
+		    +null-ptr+))
+         (toplevel-objects (list))
+         (result (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
+                                                            nib-name
+                                                            dict
+                                                            app-zone)))
+    (dotimes (i (#/count objects-array))
+      (setf toplevel-objects 
+            (cons (#/objectAtIndex: objects-array i)
+                  toplevel-objects)))
+    (#/release nib-name)
+    (values toplevel-objects result)))
+
+#|
+(ccl::load-nibfile "/usr/local/openmcl/trunk/source/examples/cocoa/nib-loading/hello.nib")
+|#
+
Index: /branches/new-random/examples/cocoa/qtvidcapture/QTVidCapture.nib/classes.nib
===================================================================
--- /branches/new-random/examples/cocoa/qtvidcapture/QTVidCapture.nib/classes.nib	(revision 13309)
+++ /branches/new-random/examples/cocoa/qtvidcapture/QTVidCapture.nib/classes.nib	(revision 13309)
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>startRecording</key>
+				<string>id</string>
+				<key>stopRecording</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>MyRecorderController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>mCaptureView</key>
+				<string>QTCaptureView</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
Index: /branches/new-random/examples/cocoa/qtvidcapture/QTVidCapture.nib/info.nib
===================================================================
--- /branches/new-random/examples/cocoa/qtvidcapture/QTVidCapture.nib/info.nib	(revision 13309)
+++ /branches/new-random/examples/cocoa/qtvidcapture/QTVidCapture.nib/info.nib	(revision 13309)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>677</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>21</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>10A354</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
Index: /branches/new-random/examples/cocoa/qtvidcapture/qtvidcapture.lisp
===================================================================
--- /branches/new-random/examples/cocoa/qtvidcapture/qtvidcapture.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/qtvidcapture/qtvidcapture.lisp	(revision 13309)
@@ -0,0 +1,285 @@
+(in-package "CL-USER")
+
+
+;;; This is supposed to be a (close) translation of Apple's "MyRecorder"
+;;; example, which shows a simple use of QTKit's QTCaptureView, which
+;;; was introduced in Leopard.  The example requires a companion nib
+;;; file - "QTVidCapture.nib" - which is basically identical to the
+;;; "MainMenu.nib" from Apple's example (with the "MainMenu" menu removed
+;;; and the window's title and position changed.)  There's a little
+;;; utility function at the bottom of this file that runs an "Open" panel
+;;; that lets you select this nib file and tries to open a video capture
+;;; window.
+
+;;; Apple's MyRecorder example is at:
+;;; <http://developer.apple.com/samplecode/MYRecorder/index.html>
+;;;
+;;; Related guides/tutorials are available at:
+;;; <http://developer.apple.com/documentation/QuickTime/Conceptual/QTKitCaptureProgrammingGuide/>
+
+
+;;; I tried to point out some issues of syntax and bridge arcana that
+;;; people new to Cocoa programming in CCL might need help with (I'm
+;;; sure that I missed some of that.)  I know very little about QTKit
+;;; and QT video capture; the hope is that people looking to do
+;;; something more ambituous will find Apple's guides and tutorials
+;;; easier to understand after reading this.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "COCOA"))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  ;; Some of this requires OSX 10.5, which is software-version 9
+  ;; as far as we're concerned.
+  (if (< (parse-integer (software-version) :junk-allowed t) 9)
+    (error "This code requires OSX 10.5 or later"))
+  ;; 
+  ;; Many class names in QTKit are prefixed with "QT".  Persuade the
+  ;; bridge that it should treat "QT" specially when mapping from
+  ;; ObjC class names to lisp.
+  (ccl::define-special-objc-word "QT")
+  (objc:load-framework "QTKit" :qtkit))
+
+
+;;; The .nib file refers to this class via the name
+;;; "MyRecorderController"; in lisp, that's basically any symbol whose
+;;; pname is "MY-RECORDER-CONTROLLER".  Likewise, there are references
+;;; to the slot "m-capture-view" - or "mCaptureView" in ObjC - in
+;;; the nib file.
+;;;
+;;; If you open the "QTVidCapture.nib" file in IB 3.0, select the
+;;; "My Recorder" object in the main view, then choose the "Connections
+;;; Inspector" item (cmd-5) from the "Tools" menu, you'll see that
+;;; there's an "outlet" from the mCaptureView slot to the window's
+;;; Capture View.  This basically means that this slot in the
+;;; MY-WINDOW-CONTROLLER instance will be initialized to refer to
+;;; the window's QTCaptureView when the .nib file is loaded (if and
+;;; only if there's a slot with that name.  Changing the name of the
+;;; outlet in the nib file - or the name of the slot in the class
+;;; definition below - could keep this initialization from working.
+
+(defclass my-recorder-controller (ns:ns-object)
+  ((m-capture-view :foreign-type :id)
+   (m-capture-session :foreign-type :id)
+   (m-capture-movie-file-output :foreign-type :id)
+   (m-capture-video-device-input :foreign-type :id)
+   (m-capture-audio-device-input :foreign-type :id))
+  (:metaclass ns:+ns-object))
+
+
+;;; This method will be called (if it's defined) on all objects
+;;; in the .nib file have been initialized in ways specified in
+;;; the init file (i.e., "outlet" instance variables are set up,
+;;; "action" messages are associated with the objects that implement
+;;; them, etc.)  The order in which #/awakeFromNib methods are
+;;; called isn't specified, but we can count on the m-capture-view
+;;; slot being initialized to the QTCaptureView in the window.
+;;; For a better explanation of what this code does, see the
+;;; Apple tutorial.
+;;; The Apple sample code from which this was derived was pretty
+;;; casual about reporting errors; this code is equally casual.
+;;; Most of the things that can cause errors (missing devices
+;;; or resources, etc.) will store an NSError object in the
+;;; location that the "perror" pointer points to; this NSError
+;;; object can be used to report error conditons and (in some
+;;; cases) try to recover from them.  Real code should certainly
+;;; try to address those issues.
+
+(objc:defmethod (#/awakeFromNib :void) ((self my-recorder-controller))
+  (rlet ((perror (:* :id) +null-ptr+))
+    ;; In ObjC, it's generally possible to refer to a class's slots
+    ;; as if they were simple variables in a method specialized on
+    ;; that class.  OBJC:DEFMETHOD doesn't do that for us, but if
+    ;; we want to do that we can use WITH-SLOTS to get a similar
+    ;; effect.  (I tend to use SETQ whenever its legal to do so;
+    ;; other people use SETF.)
+    (with-slots (m-capture-view
+                 m-capture-session 
+                 m-capture-movie-file-output
+                 m-capture-video-device-input
+                 m-capture-audio-device-input) self
+      ;; Using MAKE-INSTANCE (with no initargs) to create an instance
+      ;; of an ObjC class is entirely equivalent to calling #/init
+      ;; on the value returned by calling #/alloc on the class,
+      (setq m-capture-session (make-instance 'ns:qt-capture-session))
+      
+      ;; Some of the values below are (non-constant) ObjC variables.
+      ;; The #& reader macro lets us access those ObjC variables
+      ;; more-or-less as if they were lisp global variables.
+      (let* ((video-device (#/defaultInputDeviceWithMediaType:
+                            ns:qt-capture-device
+                            #&QTMediaTypeVideo))
+             (success (#/open: video-device perror)))
+        (unless success
+          (setq video-device (#/defaultInputDeviceWithMediaType:
+                              ns:qt-capture-device
+                              #&QTMediaTypeMuxed)
+                success (#/open: video-device perror)))
+        (when success
+          ;; (MAKE-INSTANCE objc-class-or-class-name :with-WHATEVER ...)
+          ;; is basically the same as using #/initWithWhatever:
+          ;; to initialize a newly-allocated instance of that class.
+          ;; MAKE-INSTANCE can also deal with the case where a class
+          ;; has a mixture of ObjC and Lisp slots.)
+          (setq m-capture-video-device-input 
+                (make-instance 'ns:qt-capture-device-input
+                               :with-device video-device))
+          (setq success (#/addInput:error: m-capture-session m-capture-video-device-input
+                                           perror)))
+        (when success
+          (unless (or (#/hasMediaType: video-device #&QTMediaTypeSound)
+                      (#/hasMediaType: video-device #&QTMediaTypeMuxed))
+            (let* ((audio-device (#/defaultInputDeviceWithMediaType:
+                                  ns:qt-capture-device
+                                  #&QTMediaTypeSound)))
+              (setq success (#/open: audio-device perror))
+              (when success
+                (setq m-capture-audio-device-input
+                      (make-instance 'ns:qt-capture-device-input
+                                     :with-device audio-device)
+                      success (#/addInput:error: m-capture-session
+                                                 m-capture-audio-device-input
+                                                 perror))))))
+        (when success
+          (setq m-capture-movie-file-output 
+                (make-instance 'ns:qt-capture-movie-file-output)
+                success (#/addOutput:error: m-capture-session m-capture-movie-file-output perror)))
+        (when success
+          (#/setDelegate: m-capture-movie-file-output self)
+          (let* ((connection-enumerator 
+                  (#/objectEnumerator (#/connections m-capture-movie-file-output))))
+            (do* ((connection (#/nextObject connection-enumerator)
+                              (#/nextObject connection-enumerator)))
+                 ((%null-ptr-p connection))
+              (let* ((media-type (#/mediaType connection))
+                     (compression-options
+                      (cond ((#/isEqualToString: media-type #&QTMediaTypeVideo)
+                             (#/compressionOptionsWithIdentifier:
+                              ns:qt-compression-options
+                              #@"QTCompressionOptions240SizeH264Video"))
+                            ((#/isEqualToString: media-type #&QTMediaTypeSound)
+                             (#/compressionOptionsWithIdentifier:
+                              ns:qt-compression-options
+                              #@"QTCompressionOptionsHighQualityAACAudio"))
+                            (t +null-ptr+))))
+                (#/setCompressionOptions:forConnection: m-capture-movie-file-output
+                                                       compression-options
+                                                       connection))))
+          (#/setCaptureSession: m-capture-view m-capture-session)
+          (#/startRunning m-capture-session)
+          )))))
+
+;;; Similarly, we use WITH-SLOTS here so that we can access slots
+;;; as if they were simple variables.  We're basically just trying
+;;; to close/free resources that have been associated with this
+;;; MY-WINDOW-CONTROLLER instance.
+;;; This method is called because the MY-RECORDER-CONTROLLER was
+;;; specified as the "delegate" of the window in the nib file.
+(objc:defmethod (#/windowWillClose: :void) ((self my-recorder-controller)
+                                           notification)
+  (declare (ignorable notification))
+  (with-slots (m-capture-session
+               m-capture-video-device-input
+               m-capture-audio-device-input) self
+    (unless (%null-ptr-p m-capture-session)
+      (#/stopRunning m-capture-session))
+    (unless (%null-ptr-p m-capture-video-device-input)
+      (if (#/isOpen (#/device m-capture-video-device-input))
+        (#/close (#/device m-capture-video-device-input))))
+    (unless (%null-ptr-p m-capture-audio-device-input)
+      (if (#/isOpen (#/device m-capture-audio-device-input))
+        (#/close (#/device m-capture-video-device-input))))))
+
+;;; This method is called when the MY-RECORDER-INSTANCE has had
+;;; its reference count go to 0   It basically decrements the
+;;; reference counts of the things it has allocated (possibly
+;;; causing #/dealloc to be invoked on them), then calls the
+;;; superclass method to deallocate itself.
+;;; A lisp pointer to the MY-WINDOW-CONTROLLER object might
+;;; continue to believe that the object its pointing to is
+;;; still a MY-WINDOW-CONTROLLER, even after the actual object
+;;; has been deallocated (basically, "deallocated" means "turned
+;;; into free memory.)  There isn't currently a good solution
+;;; to this problem (such a solution involves deeper integration
+;;; between the Lisp and its GC and the ObjC memory-management
+;;; system.)  It's a little hard to do this and the issue doesn't
+;;; come up that often, but it's worth remembering that there is
+;;; an issue here.
+(objc:defmethod (#/dealloc :void) ((self my-recorder-controller))
+  (with-slots (m-capture-session
+               m-capture-video-device-input
+               m-capture-audio-device-input
+               m-capture-movie-file-output) self
+    (#/release m-capture-session)
+    (#/release m-capture-video-device-input)
+    (#/release m-capture-audio-device-input)
+    (#/release m-capture-movie-file-output)
+    (call-next-method)))
+
+;;; This is an "action" method (specified in the nib file) that's
+;;; invoked whenever the "start" button is pressed.  "action" methods
+;;; recieve the object that invoked the method as a "sender" argument.
+;;; (In this case, the "sender" is the "start" button.)  We don't
+;;; care who sent the message and might ordinarily declare "sender"
+;;; to be ignored.  It's hard to know when the bridge might cause
+;;; objc:defmethod to expand into code that includes incidental
+;;; references to an argument, so it's generally best to say that
+;;; something that we don't use is "ignorable": we don't intend to
+;;; reference the variable, but don't really care if there are
+;;; incidental references to it in the macroexpansion of OBJC:DEFMETHOD.
+
+(objc:defmethod (#/startRecording: :void) ((self my-recorder-controller) sender)
+  (declare (ignorable sender))
+  (#/recordToOutputFileURL: (slot-value self 'm-capture-movie-file-output)
+                            (#/fileURLWithPath: ns:ns-url
+                                                #@"/Users/Shared/My Recorded Movie.mov")))
+
+;;; Likewise, another action method here.
+(objc:defmethod (#/stopRecording: :void) ((self my-recorder-controller) sender)
+  (declare (ignorable sender))
+  (#/recordToOutputFileURL: (slot-value self 'm-capture-movie-file-output)
+                            +null-ptr+))
+
+;;; This message is sent to us because we're the delegate object of
+;;; our output-capture object
+(objc:defmethod
+    (#/captureOutput:didFinishRecordingToOutputFileAtURL:forConnections:dueToError: :void)
+    ((self my-recorder-controller) captureoutput output-file-url connections error)
+  (declare (ignorable captureoutput connections error))
+  (#/openURL: (#/sharedWorkspace ns:ns-workspace) output-file-url))
+
+
+;;; That's the end of the transliterated code.  Here's a little function
+;;; that runs an "Open" panel to allow the selection of a nib file, then
+;;; tries to use a standard NSWindowController object to create and
+;;; show a window using that nib file.
+
+
+(defun open-window-using-selected-nib (&optional (prompt "Pick a nib file.  Any nib file"))
+  ;;; There are a bunch of issues that make it easier to do all of the
+  ;;; work on the main Cocoa event thread, which is the value of
+  ;;; GUI:::*COCOA-EVENT-PROCESS*.  
+  (process-interrupt
+   gui::*cocoa-event-process*
+   (lambda ()
+     (let* ((panel (#/openPanel ns:ns-open-panel)))
+       ;; CCL::%MAKE-NSSTRING should probably be moved to some
+       ;; other package and exported from there.
+       (#/setTitle: panel (ccl::%make-nsstring prompt))
+       (#/setAllowsMultipleSelection: panel nil)
+       (let* ((types (#/arrayWithObject: ns:ns-array #@"nib"))
+              (button (#/runModalForTypes: panel types)))
+         (when (eql button #$NSOKButton)
+           (let* ((filenames (#/filenames panel)))
+             (when (eql 1 (#/count filenames))
+               (let* ((wc (make-instance 'ns:ns-window-controller
+                                         :with-window-nib-path
+                                         (#/objectAtIndex: filenames 0)
+                                         :owner (#/sharedApplication ns:ns-application))))
+                 (unless (%null-ptr-p wc)
+                   (#/showWindow: wc +null-ptr+)))))))))))
+
+                       
+
+           
+                                                  
Index: /branches/new-random/examples/cocoa/tiny.lisp
===================================================================
--- /branches/new-random/examples/cocoa/tiny.lisp	(revision 13309)
+++ /branches/new-random/examples/cocoa/tiny.lisp	(revision 13309)
@@ -0,0 +1,91 @@
+;;;; -*- Mode: Lisp; Package: CCL -*-
+;;;; tiny.lisp 
+;;;;
+;;;; A fairly direct translation into Lisp of the Tiny application (Chapter 4) 
+;;;; from "Building Cocoa Applications" by Garfinkel and Mahoney 
+;;;;
+;;;; The original Tiny example was meant to illustrate the programmatic use of
+;;;; Cocoa without Interface Builder.  Its purpose here is to illustrate the
+;;;; programmatic use of the Cocoa bridge. 
+;;;;
+;;;; Copyright (c) 2003 Randall D. Beer
+;;;; 
+;;;; This software is licensed under the terms of the Lisp Lesser GNU Public
+;;;; License , known as the LLGPL.  The LLGPL consists of a preamble and 
+;;;; the LGPL. Where these conflict, the preamble takes precedence.  The 
+;;;; LLGPL is available online at http://opensource.franz.com/preamble.html.
+;;;;
+;;;; Please send comments and bug reports to <beer@eecs.cwru.edu>
+
+;;; Temporary package and module stuff 
+
+(in-package "CCL")
+
+(require "COCOA")
+
+
+;;; Define the DemoView class 
+
+(defclass demo-view (ns:ns-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+
+;;; Define the drawRect: method for DemoView 
+;;; NOTE: The (THE NS-COLOR ...) forms are currently necessary for full
+;;;       optimization because the SET message has a nonunique type signature 
+;;; NOTE: This will be replaced by a DEFMETHOD once ObjC objects have been
+;;;       integrated into CLOS
+;;; NOTE: The (@class XXX) forms will probably be replaced by 
+;;;       (find-class 'XXX) once ObjC objects have been integrated into CLOS
+
+(defconstant short-pi (coerce pi 'short-float))
+(defconstant numsides 12)
+
+(objc:defmethod (#/drawRect: :void) ((self demo-view) (rect :<NSR>ect))
+  (declare (ignorable rect))
+  (let* ((bounds (#/bounds self))
+         (width (ns:ns-rect-width bounds))
+         (height (ns:ns-rect-height bounds)))
+    (macrolet ((X (tt) `(* (1+ (sin ,tt)) width 0.5))
+               (Y (tt) `(* (1+ (cos ,tt)) height 0.5)))
+      ;; Fill the view with white
+      (#/set (#/whiteColor ns:ns-color))
+      (#_NSRectFill bounds)
+      ;; Trace two polygons with N sides and connect all of the vertices 
+      ;; with lines
+      (#/set (#/blackColor ns:ns-color))
+      (loop 
+        for f from 0.0 below (* 2 short-pi) by (* 2 (/ short-pi numsides))
+        do
+        (loop 
+          for g from 0.0 below (* 2 short-pi) by (* 2 (/ short-pi numsides))
+          do
+          (#/strokeLineFromPoint:toPoint: ns:ns-bezier-path (ns:make-ns-point (X f) (Y f)) (ns:make-ns-point (X g) (Y g))))))))
+
+
+;;; This performs the actions that would normally be performed by loading
+;;; a nib file. 
+
+(defun tiny-setup ()
+  (with-autorelease-pool
+    (let* ((r (ns:make-ns-rect 100 350 400 400))
+           (w (make-instance 
+		   'ns:ns-window
+		   :with-content-rect r
+		   :style-mask (logior #$NSTitledWindowMask 
+				       #$NSClosableWindowMask 
+				       #$NSMiniaturizableWindowMask)
+		   :backing #$NSBackingStoreBuffered
+		   :defer t)))
+      (#/setTitle: w #@"Tiny Window Application")
+      (let ((my-view (make-instance 'demo-view :with-frame r)))
+        (#/setContentView: w my-view)
+        (#/setDelegate: w my-view))
+      (#/performSelectorOnMainThread:withObject:waitUntilDone:
+       w (objc:@selector "makeKeyAndOrderFront:") nil nil)
+      w)))
+
+
+;;; Neither the windowWillClose method nor the main from the original Tiny
+;;; application is necessary here 
Index: /branches/new-random/examples/cocoa/ui-elements/HOWTO.html
===================================================================
--- /branches/new-random/examples/cocoa/ui-elements/HOWTO.html	(revision 13309)
+++ /branches/new-random/examples/cocoa/ui-elements/HOWTO.html	(revision 13309)
@@ -0,0 +1,366 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>UI Elements HOWTO</title>
+    <link rel="stylesheet" type="text/css" href="HOWTO_files/stylesheets/styles.css" />
+  </head>
+
+  <body>
+
+    <div class="title">
+      <h1>UI Elements HOWTO</h1>
+    </div>
+
+    <div class="body-text">
+      <p>This HOWTO shows how you can create Cocoa user-interface
+      elements by making lisp calls to instantiate and initialize
+      Objective-C objects.</p>
+
+      <p>Cocoa programmers usually create UI elements using Apple's
+      InterfaceBuilder application, and then load those elements from
+      a <strong>nibfile</strong>, but Cocoa supports creating all the
+      same UI elements by making Objective-C method calls. In fact,
+      that's how it loads nibfiles: by making method calls to
+      instantiate the objects described in them.</p>
+
+      <p>For Lisp programmers, accustomed to working incrementally and
+      interactively, it may sometimes make more sense to create
+      user-interface elements by making method calls interactively,
+      rather than by constructing a complete user interface in
+      InterfaceBuilder. This HOWTO shows how you can use Objective-C
+      method calls to create and display windows and other UI
+      elements.</p>
+
+      <p>For more information about how to load nibfiles from Lisp,
+      see the "nib-loading" example. For a complete discussion of how
+      to construct a Cocoa application using nibfiles created with
+      InterfaceBuilder, see the "currency-converter" example.</p>
+
+    <div class="title">
+      <h2>Creating a Window</h2>
+    </div>
+
+    <p>Every user-interface element under Mac OS X appears either in
+    a window or in a menu. We'll begin by exploring how to create and
+    display windows.</p>
+
+    <p>First, switch to the <code>CCL</code> package, for
+    convenience. Most of Clozure CL's Objective-C utilities are in
+    the <code>CCL</code> package:</p>
+
+    <pre>
+? (in-package :ccl)
+#&lt;Package "CCL"&gt;
+    </pre>
+
+    <p>Creating a Cocoa window follows the common Objective-C pattern
+    of allocating an object and then initializing it with some
+    starting data. To allocate a window, just call
+    the <code>alloc</code> method of the <code>NSWindow</code>
+    class:</p>
+
+    <pre>
+? (setf my-window (#/alloc (@class ns-window)))
+#&lt;NS-WINDOW &lt;NSWindow: 0x13b68580&gt; (#x13B68580)&gt;
+    </pre>
+
+    <p>The above expression creates a new window, but doesn't display
+    it. Before it shows up on the screen we must initialize it with
+    some appropriate values. For that, we'll use the
+    method <code>initWithContentRect:styleMask:backing:defer:</code>.</p>
+
+    <p>As always in Objective-C, the name of the method reveals
+    something about the arguments it expects. The <code>NSRect</code>
+    that we pass for the <code>initWithContentRect:</code> segment of
+    the method name describes the shape of the window. The mask
+    for <code>styleMask:</code> is a sequence of bits that specify
+    which window features are turned on. The <code>backing:</code>
+    argument is a constant of type <code>NSBackingStoreType</code>
+    that specifies how Cocoa will draw the contents of the
+    window. Finally, the <code>defer:</code> argument is a Boolean
+    that determines whether to display the window as soon as it's
+    created.</p>
+
+    <p>Next, we'll create data values to pass in these parameters, so
+    that we can display our new window on the screen. We'll build the
+    proper initialization form up piece-by-piece.</p>
+
+    <p>The first argument, of course, is the window object to be
+    initialized. We pass the window that we created before:</p>
+
+    <pre>
+(#/initWithContentRect:styleMask:backing:defer: my-window ...)
+    </pre>
+
+    <p>The next argument, the <code>NSRect</code>, is a structure
+    that we need only temporarily. Because <code>NSRect</code> values
+    appear so often in Cocoa code, Clozure CL provides a handy way to
+    allocate them temporarily, disposing of them
+    automatically. The <code>with-ns-rect</code> macro (in
+    the <code>NS</code> package) creates an <code>NSRect</code> value,
+    and then disposes of it when control leaves the scope of the
+    macro; for example:</p>
+
+    <pre>
+(ns:with-ns-rect (r 100 100 400 300)
+   ...)
+    </pre>
+
+    <p>We can use this rectangle to initialize the shape of our new
+    window:</p>
+
+    <pre>
+(ns:with-ns-rect (r 100 100 400 300)
+   (#/initWithContentRect:styleMask:backing:defer: 
+    my-window 
+    r 
+    ...))
+    </pre>
+
+    <p>To specify the window features we want, we must combine
+    several flags to form the proper style mask. Cocoa provides named
+    constants for each of the various window features. To create the
+    syle mask that describes a new window, use inclusive-or to
+    combine the named flags into a style mask:</p>
+
+    <pre>
+(logior  #$NSTitledWindowMask 
+         #$NSClosableWindowMask  
+         #$NSMiniaturizableWindowMask 
+         #$NSResizableWindowMask)
+    </pre>
+
+    <p>You can find definitions for all the window masks in the Apple
+    Developer documentation
+    for <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindow_Class/Reference/Reference.html#//apple_ref/doc/uid/20000013-89097">NSWindow
+    Constants</a>.</p>
+
+    <p>Passing the window mask as the next argument gives us this
+    expression:</p>
+
+    <pre>
+(ns:with-ns-rect (r 100 100 400 300)
+  (#/initWithContentRect:styleMask:backing:defer: 
+   my-window 
+   r 
+   (logior  #$NSTitledWindowMask 
+            #$NSClosableWindowMask  
+            #$NSMiniaturizableWindowMask 
+            #$NSResizableWindowMask)
+   ...))
+    </pre>
+
+    <p>Like the style masks, the <code>NSBackingStoreType</code> value
+    is a named constant that describes which drawing strategy Cocoa
+    should use for the contents of the window. The value can
+    be <code>NSBackingStoreRetained</code>, <code>NSBackingStoreNonretained</code>,
+    or <code>NSBackingStoreBuffered</code>. For this example, we'll
+    use <code>NSBackingStoreBuffered</code>:</p>
+
+    <pre>
+(ns:with-ns-rect (r 100 100 400 300)
+  (#/initWithContentRect:styleMask:backing:defer: 
+   my-window 
+   r 
+   (logior  #$NSTitledWindowMask 
+            #$NSClosableWindowMask  
+            #$NSMiniaturizableWindowMask 
+            #$NSResizableWindowMask)
+   #$NSBackingStoreBuffered
+   ...))
+    </pre>
+
+    <p>Finally, the <code>defer</code> argument is just a Boolean. If
+    we pass a true value, Cocoa will defer displaying the window until
+    we explicitly tell it to. If we pass a False value, it will
+    instead display the window right away. We can pass the Lisp
+    values <code>T</code> or <code>NIL</code>, and the Objective-C
+    bridge automatically converts them for us, but in the spirit of
+    using Objective-C values for Objective-C operations, let's use the
+    Objective-C constants <code>#$YES</code>
+    and <code>#$NO</code>:</p>
+
+    <pre>
+(ns:with-ns-rect (r 100 100 400 300)
+  (#/initWithContentRect:styleMask:backing:defer: 
+   my-window 
+   r 
+   (logior  #$NSTitledWindowMask 
+            #$NSClosableWindowMask  
+            #$NSMiniaturizableWindowMask 
+            #$NSResizableWindowMask)
+   #$NSBackingStoreBuffered
+   #$NO))
+    </pre>
+
+    <p>There; the expression to initialize our window object is
+    finally complete. We can evaluate it in the Listener to
+    initialize the window:</p>
+
+    <pre>
+(ns:with-ns-rect (r 100 100 400 300)
+  (#/initWithContentRect:styleMask:backing:defer: 
+   my-window 
+   r 
+   (logior  #$NSTitledWindowMask 
+            #$NSClosableWindowMask  
+            #$NSMiniaturizableWindowMask 
+            #$NSResizableWindowMask)
+   #$NSBackingStoreBuffered
+   #$NO))
+    </pre>
+
+    <p>Then we can call <code>makeKeyAndOrderFront:</code> to display the window:</p>
+
+    <pre>
+(#/makeKeyAndOrderFront: my-window nil)
+    </pre>
+
+    <p>The window, empty, but with the shape and features we
+    specified, appears on the left lower corner of the screen.</p>
+
+    <div class="title">
+      <h2>Adding a Button</h2>
+    </div>
+
+    <p>Once we have a window on the screen, we might like to put
+    something in it. Let's start by adding a button.</p>
+
+    <p>Creating a button object is as simple as creating a window
+    object; we simply allocate one:</p>
+
+    <pre>
+(setf my-button (#/alloc ns:ns-button))
+#&lt;NS-BUTTON &lt;NSButton: 0x13b7bec0&gt; (#x13B7BEC0)&gt;
+    </pre>
+
+    <p>As with the window, most of the interesting work is in
+    configuring the allocated button after it's allocated.</p>
+
+    <p>Instances of NSButton include pushbuttons with either text or
+    image labels (or both), checkboxes, and radio buttons. In order to
+    make a text pushbutton, we need to tell our button to use a
+    button-type of <code>NSMomentaryPushInButton</code>, an image
+    position of <code>NSNoImage</code>, and a border style
+    of <code>NSRoundedBezelStyle</code>. These style options are
+    represented by Cocoa constants.</p>
+    
+    <p>We also need to give the button a frame rectangle that defines
+    its size and position. We can once again
+    use <code>ns:with-ns-rect</code> to specify a temporary rectangle
+    for the purpose of initializing our button:</p>
+
+    <pre>
+(ns:with-ns-rect (frame 10 10 72 32)
+  (#/initWithFrame: my-button frame)
+  (#/setButtonType: my-button #$NSMomentaryPushInButton)
+  (#/setImagePosition: my-button #$NSNoImage)
+  (#/setBezelStyle: my-button #$NSRoundedBezelStyle))
+;Compiler warnings :
+;   Undeclared free variable MY-BUTTON (4 references), in an anonymous lambda form
+NIL
+    </pre>
+
+    <p>Now we just need to add the button to the window. This we do by
+    asking the window for its content view, and asking that view to
+    add the button as a subview:</p>
+
+    <pre>
+(#/addSubview: (#/contentView my-window) my-button)
+    </pre>
+
+    <p>The button appears in the window with the rather uninspired
+    title "Button". Clicking it highlights the button but, since we
+    didn't give it any action to perform, does nothing else.</p>
+
+    <p>We can give the button a more interesting title and, perhaps
+    more importantly, an action to perform, by passing a string and an
+    action to it. First, let's set the button title:</p>
+
+    <pre>
+(let ((label (%make-nsstring "Hello!")))
+  (#/setTitle: my-button label)
+  (#/release label))
+;Compiler warnings :
+;   Undeclared free variable MY-BUTTON, in an anonymous lambda form
+NIL
+    </pre>
+
+    <p>The button changes to display the text "Hello!". Notice that we
+    are careful to save a reference to the button text and release it
+    after changing the button title. The normal memory-management
+    policy in Cocoa is that if we allocate an object (like the
+    NSString "Hello!") we are responsible for releasing it. Unlike
+    Lisp, Cocoa does not automatically garbage-collect all allocated
+    objects by default.</p>
+
+    <p>Giving the button an action is slightly more
+    complicated. Clicking a button causes the button object to send a
+    message to a target object. We haven't given our button a message
+    to send, nor a target object to send it to, so it doesn't do
+    anything. In order to get it do perform some kind of action, we
+    need to give it a target object and a message to send. Then, when
+    we click the button, it will send the message we specify to the
+    target we provide. Naturally, the target object had better be able
+    to respond to the message, or else we'll just see a runtime
+    error.</p>
+
+    <p>Let's define a class that knows how to respond to a greeting
+    message, and then make an object of that class to serve as our
+    button's target.</p>
+
+    <p>We can define a subclass of <code>NSObject</code> to handle
+    our button's message:</p>
+
+    <pre>
+(defclass greeter (ns:ns-object)
+  ()
+  (:metaclass ns:+ns-object))
+#&lt;OBJC:OBJC-CLASS GREETER (#x13BAF810)&gt;
+    </pre>
+
+    <p>We'll need to define a method to execute in response to the
+    button's message. Action methods accept one argument (in addition
+    to the receiver): a sender. Normally Cocoa passes the button
+    object itself as the sender argument; the method can do anything
+    it likes (or nothing at all) with the sender.</p>
+
+    <p>Here's a method that displays an alert dialog:</p>
+
+    <pre>
+(objc:defmethod #/greet: ((self greeter) (sender :id))
+  (declare (ignore sender))
+  (let ((title (%make-nsstring "Hello!"))
+        (msg (%make-nsstring "Hello, World!"))
+        (default-button (%make-nsstring "Hi!"))
+        (alt-button (%make-nsstring "Hello!"))
+        (other-button (%make-nsstring "Go Away")))
+    (#_NSRunAlertPanel title msg default-button alt-button other-button)
+    (#/release title)
+    (#/release msg)
+    (#/release default-button)
+    (#/release other-button)))
+    </pre>
+
+    <p>Now we can create an instance of the Greeter class and use it
+    as the button's target:</p>
+
+    <pre>
+(setf my-greeter (#/init (#/alloc greeter)))
+#&lt;GREETER &lt;Greeter: 0x136c58e0&gt; (#x136C58E0)&gt;
+
+(#/setTarget: my-button my-greeter)
+NIL
+
+(#/setAction: my-button (@SELECTOR "greet:"))
+NIL
+    </pre>
+
+    <p>Now, if you click the button, an Alert panel appears.</p>
+
+    </div>
+
+  </body>
+</html>
+
Index: /branches/new-random/examples/cocoa/ui-elements/HOWTO_files/stylesheets/styles.css
===================================================================
--- /branches/new-random/examples/cocoa/ui-elements/HOWTO_files/stylesheets/styles.css	(revision 13309)
+++ /branches/new-random/examples/cocoa/ui-elements/HOWTO_files/stylesheets/styles.css	(revision 13309)
@@ -0,0 +1,55 @@
+body {
+	background-color: white;
+	font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
+}
+
+.title {
+	text-align: center;
+	font-size: 16pt;
+}
+
+.subtitle {
+	font-size: medium;
+	font-weight: bold;
+	text-align: center;
+}
+
+.byline {
+	text-align: center;
+	font-weight: bold;
+	font-size: small;
+}
+
+.section-head {
+	padding-top: 2em;
+	padding-left: 1em;
+}
+
+.body-text {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 4em;
+	margin-right: 4em;
+	text-indent: 3em;
+}
+
+.note {
+	font: 12pt Georgia, "Times New Roman", Times, serif;
+	margin-left: 6em;
+	margin-right: 6em;
+	text-indent: 0em;
+}
+
+.inline-image {
+	text-align: center;
+}
+
+.nav {
+	text-align: center;
+	font-size: large;
+	font-weight: bold;
+	padding-top: 4em;
+}
+
+li, pre {
+	text-indent: 0;
+}
Index: /branches/new-random/examples/gtk-minesweeper.lisp
===================================================================
--- /branches/new-random/examples/gtk-minesweeper.lisp	(revision 13309)
+++ /branches/new-random/examples/gtk-minesweeper.lisp	(revision 13309)
@@ -0,0 +1,991 @@
+;;;-*-Mode: LISP; Package: (MINESWEEPER :USE (CL CCL)) -*-
+;;;
+;;;   Copyright (C) 2001 Clozure Associates
+;;; 
+;;; This is a GTK+-based MineSweeper game, derived from a C program
+;;; developed by Eric Harlow and published in "Developing Linux Programs
+;;; with GTK+ and GDK", (c) 1999 New Riders Publishing.
+;;;
+;;; Anyone who wants to use this code for any purpose is free to do so.
+;;; In doing so, the user acknowledges that this code is provided "as is",
+;;; without warranty of any kind, and that no other party is legally or
+;;; otherwise responsible for any consequences of its use.
+
+(defpackage "MINESWEEPER"
+  (:use "CL" "CCL")
+  (:export "MINESWEEPER"))
+
+(in-package "MINESWEEPER")
+
+;;; 
+;;; Make GTK+ interface info available.
+(eval-when (:compile-toplevel :execute)
+  (use-interface-dir :GTK2))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "OPENMCL-GTK-SUPPORT"))
+
+
+(defconstant max-rows 35)
+(defconstant max-cols 35)
+
+(defconstant button-width 24)
+(defconstant button-height 26)
+
+
+(defvar *nrows* 10)
+(defvar *ncols* 10)
+(defvar *ntotalbombs* 0)
+
+(defvar *bgameover* nil)
+(defvar *bresetgame* nil)
+(defvar *nbombsleft* nil)
+
+(defvar *table* nil)
+(defvar *start-button* nil)
+(defvar *bombs-label* nil)
+(defvar *time-label* nil)
+(defvar *vbox* nil)
+
+(defstruct cell
+  (buttonstate :button-unknown
+	       :type (member :button-down :button-unknown :button-flagged))
+  button
+  (bombsnearby 0)
+  (has-bomb nil)
+  row
+  col)
+
+;;; The original C Minesweeper example uses GtkToggleButtons to
+;;; represent the cells on the grid.  They seem to work reasonably
+;;; well except for one minor (but annoying) feature: "enter" and
+;;; "leave" events cause the cells under the mouse to be highlighted,
+;;; making it difficult to distinguish "unpressed buttons" from "the
+;;; button under the mouse".
+;;;
+;;; This defines a GtkQuietToggleButton class that's exactly like
+;;; GtkToggleButton except for the fact that it does nothing on
+;;; "enter" and "leave" events.  It's not necessarily the most
+;;; interesting example of subclassing a Gtk widget, but it -is- an
+;;; example of doing so.
+;;;
+;;; GtkQuietToggleButtons seem to be better, but there is still some
+;;; room for improvement.
+
+(defcallback enter-or-leave-quietly (:address widget :void)
+  (let* ((id (with-cstrs ((cell-id "cell-id"))
+	       (#_gtk_object_get_data widget cell-id)))
+	 (cell (cell-id->cell id))
+	 (desired-state 
+	  (if (member (cell-buttonstate cell)
+		      '(:button-unknown :button-flagged))
+	    #$GTK_STATE_NORMAL
+	    #$GTK_STATE_ACTIVE))
+	 (current-state (pref widget :<G>tk<W>idget.state)))
+    (unless (eql current-state desired-state)
+      (#_gtk_widget_set_state widget desired-state))))
+
+(defcallback gtk_quiet_toggle_button_class_init (:address classptr :void)
+  (setf (pref classptr :<G>tk<B>utton<C>lass.enter) enter-or-leave-quietly
+	(pref classptr :<G>tk<B>utton<C>lass.leave) enter-or-leave-quietly))
+
+
+(defcallback gtk_quiet_toggle_button_init (:address widget :void)
+  (declare (ignore widget)))
+
+
+;;; CCL::DEFLOADVAR behaves like DEFPARAMETER, but arranges to
+;;; initialize the variable whenever a saved image start up
+;;; as well as when the DEFLOADVAR is executed.
+(ccl::defloadvar *gtk-quiet-toggle-button-type-info*
+    (let* ((p (#_malloc (ccl::%foreign-type-or-record-size :<G>tk<T>ype<I>nfo :bytes))))
+      (setf
+       (pref p :<G>tk<T>ype<I>nfo.type_name)
+       (with-cstrs ((name "GtkQuietToggleButton")) (#_g_strdup name))
+       (pref p :<G>tk<T>ype<I>nfo.object_size)
+       (ccl::%foreign-type-or-record-size :<G>tk<T>oggle<B>utton :bytes)
+       (pref p :<G>tk<T>ype<I>nfo.class_size)
+       (ccl::%foreign-type-or-record-size :<G>tk<T>oggle<B>utton<C>lass :bytes)
+       (pref p :<G>tk<T>ype<I>nfo.class_init_func) gtk_quiet_toggle_button_class_init
+       (pref p :<G>tk<T>ype<I>nfo.object_init_func) gtk_quiet_toggle_button_init
+       (pref p :<G>tk<T>ype<I>nfo.reserved_1) (%null-ptr)
+       (pref p :<G>tk<T>ype<I>nfo.reserved_2) (%null-ptr)
+       (pref p :<G>tk<T>ype<I>nfo.base_class_init_func) (%null-ptr))
+      p))
+
+(ccl::defloadvar *gtk-quiet-toggle-button-type* nil)
+
+(defun gtk-quiet-toggle-button-get-type ()
+  (or *gtk-quiet-toggle-button-type*
+      (setq *gtk-quiet-toggle-button-type*
+	    (#_gtk_type_unique (#_gtk_toggle_button_get_type)
+			       *gtk-quiet-toggle-button-type-info*))))
+
+(defcallback gtk_quiet_toggle_button_get_type (:unsigned-fullword)
+  (gtk-quiet-toggle-button-get-type))
+
+(defun gtk-quiet-toggle-button-new ()
+  (#_gtk_type_new (gtk-quiet-toggle-button-get-type)))
+
+(defcallback gtk_quiet_toggle_button_new (:address)
+  (gtk-quiet-toggle-button-new))
+
+(defparameter *minesweeper-use-quiet-toggle-buttons* t)
+
+;;; Display message dialogs (as for the About... box).
+
+;;; A dialog widget has "grabbed" the focus.  Call back here when
+;;; the dialog is to be closed; yield the focus.
+(defcallback close-show-message
+    (:address container :address data :void)
+  (declare (ignore container))
+  (let* ((dialog-widget data))
+    (#_gtk_grab_remove dialog-widget)
+    (#_gtk_widget_destroy dialog-widget)))
+
+(defcallback clear-show-message
+    (:address widget  :address data :void)
+  (declare (ignore data))
+  (#_gtk_grab_remove widget))
+
+(defun show-message (title message)
+  (let* ((dialog-window (#_gtk_dialog_new)))
+    (with-cstrs ((destroy-name "destroy"))
+      (#_gtk_signal_connect_full dialog-window destroy-name clear-show-message
+			    (%null-ptr) (%null-ptr) (%null-ptr) 0 0))
+    (with-cstrs ((title title))
+      (#_gtk_window_set_title dialog-window title))
+    (#_gtk_container_set_border_width dialog-window 0)
+
+    (let* ((button (with-cstrs ((ok "OK"))
+		     (#_gtk_button_new_with_label ok))))
+      (with-cstrs ((clicked "clicked"))
+	(#_gtk_signal_connect_full button clicked close-show-message (%null-ptr) dialog-window (%null-ptr) 0 0))
+      (setf (pref button :<G>tk<O>bject.flags)
+	    (logior (pref button :<G>tk<O>bject.flags) #$GTK_CAN_DEFAULT))
+      (#_gtk_box_pack_start (pref dialog-window :<G>tk<D>ialog.action_area)
+			    button #$TRUE #$TRUE 0)
+      (#_gtk_widget_grab_default button)
+      (#_gtk_widget_show button))
+
+    (let* ((label (with-cstrs ((message message))
+		    (#_gtk_label_new message))))
+      (#_gtk_misc_set_padding label 10 10)
+      (#_gtk_box_pack_start (pref dialog-window :<G>tk<D>ialog.vbox)
+			    label #$TRUE #$TRUE 0)
+      (#_gtk_widget_show label))
+
+    (#_gtk_widget_show dialog-window)
+    (#_gtk_grab_add dialog-window)))
+
+
+(defun show-about ()
+  (show-message "About ..."
+		"Minesweeper OpenMCL GTK+ example
+Copyright 2001 Clozure Associates
+Derived from Minesweeper v0.6 by Eric Harlow"))
+
+(defvar *win-main* ())
+(defvar *accel-group* ())
+(defvar *tooltips* ())
+
+(defun reset-minesweeper-globals ()
+  (setq *win-main* nil
+	*accel-group* nil
+	*tooltips* nil
+	*vbox* nil
+	*time-label* nil
+	*bombs-label* nil
+	*start-button* nil
+	*table* nil
+	*bgameover* nil
+	*bresetgame* nil))
+	
+(defun create-widget-from-xpm (window xpm-string-list)
+  (rlet ((mask (* :<G>dk<B>itmap)))
+   (with-string-vector (xpm-data xpm-string-list)
+     (let* ((pixmap-data (#_gdk_pixmap_create_from_xpm_d
+			  (pref window :<G>tk<W>idget.window)
+			  mask
+			  (%null-ptr)
+			  xpm-data))
+	    (pixmap-widget (#_gtk_pixmap_new pixmap-data (%get-ptr mask))))
+       (#_gtk_widget_show pixmap-widget)
+       pixmap-widget))))
+
+(defun create-menu-item (menu item-name accel tip func data)
+  ;; A null or zero-length item-name indicates a separator.
+  (let* ((menuitem nil))
+    (if (and item-name (length item-name))
+      (with-cstrs ((item-name item-name)
+		   (activate "activate"))
+	(setq menuitem (#_gtk_menu_item_new_with_label item-name))
+	(#_gtk_signal_connect_full menuitem activate func (%null-ptr) (or data (%null-ptr)) (%null-ptr) 0 0))
+      (setq menuitem (#_gtk_menu_item_new)))
+    (#_gtk_menu_shell_append menu menuitem)
+    (#_gtk_widget_show menuitem)
+
+    (unless *accel-group*
+      (setq *accel-group*
+	    (#_gtk_accel_group_new))
+      (#_gtk_window_add_accel_group *win-main* *accel-group*))
+
+    (if (and accel (char= (schar accel 0) #\^))
+      (with-cstrs ((activate "activate"))
+	(#_gtk_widget_add_accelerator
+	 menuitem activate *accel-group* (char-code (schar accel 1))
+	 #$GDK_CONTROL_MASK #$GTK_ACCEL_VISIBLE)))
+
+    (if (and tip (length tip))
+      (with-cstrs ((tip tip))
+	(#_gtk_tooltips_set_tip
+	 (or *tooltips*
+	     (setq *tooltips* (#_gtk_tooltips_new)))
+	 menuitem
+	 tip
+	 (%null-ptr))))
+    menuitem))
+    
+(defun create-radio-menu-item (menu item-name group-ptr func data)
+  (with-cstrs ((item-name item-name)
+	       (toggled "toggled"))
+    (let* ((menuitem (#_gtk_radio_menu_item_new_with_label
+		      (%get-ptr group-ptr)
+		      item-name)))
+      (setf (%get-ptr group-ptr)
+	    (#_gtk_radio_menu_item_get_group menuitem))
+      (#_gtk_menu_shell_append menu menuitem)
+      (#_gtk_widget_show menuitem)
+      (#_gtk_signal_connect_full menuitem toggled func (%null-ptr) (or data (%null-ptr)) (%null-ptr) 0 0)
+      menuitem)))
+
+(defun create-bar-sub-menu (menu name)
+  (with-cstrs ((name name))
+    (let* ((menuitem (#_gtk_menu_item_new_with_label name)))
+      (#_gtk_menu_shell_append menu menuitem)
+      (#_gtk_widget_show menuitem)
+      (let* ((submenu (#_gtk_menu_new)))
+	(#_gtk_menu_item_set_submenu menuitem submenu)
+	submenu))))
+
+;;; Represent xpm string vectors as lists of strings.  WITH-STRING-VECTOR
+;;; will produce a foreign vector of C strings out of such a list.
+(defvar *xpm-one*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #3333CC"
+    "            "
+    "     XX     "
+    "    XXX     "
+    "   X XX     "
+    "     XX     "
+    "     XX     "
+    "     XX     "
+    "     XX     "
+    "     XX     "
+    "   XXXXXX   "
+    "            "
+    "            "
+    ))
+
+(defvar *xpm-two*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #009900"
+    "            "
+    "   XXXXXX   "
+    "  X      X  "
+    "        XX  "
+    "       XX   "
+    "      XX    "
+    "     XX     "
+    "    XX      "
+    "   XX       "
+    "  XXXXXXXX  "
+    "            "
+    "            "
+    ))
+
+
+(defvar *xpm-three*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #AA0000"
+    "            "
+    "   XXXXX    "
+    "        XX  "
+    "        XX  "
+    "   XXXXXX   "
+    "        XX  "
+    "        XX  "
+    "        XX  "
+    "        XX  "
+    "  XXXXXX    "
+    "            "
+    "            "
+    ))
+
+
+(defvar *xpm-four*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #000066"
+    "            "
+    "  XX    XX  "
+    "  XX    XX  "
+    "  XX    XX  "
+    "  XX    XX  "
+    "  XXXXXXXX  "
+    "        XX  "
+    "        XX  "
+    "        XX  "
+    "        XX  "
+    "            "
+    "            "
+    ))
+
+
+
+(defvar *xpm-five*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #992299"
+    "            "
+    "  XXXXXXXX  "
+    "  XX        "
+    "  XX        "
+    "  XXXXXXX   "
+    "        XX  "
+    "        XX  "
+    "        XX  "
+    "  XX    XX  "
+    "  XXXXXXX   "
+    "            "
+    "            "
+    ))
+
+
+(defvar *xpm-six*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #550055"
+    "            "
+    "   XXXXXX   "
+    "  XX        "
+    "  XX        "
+    "  XXXXXXX   "
+    "  XX    XX  "
+    "  XX    XX  "
+    "  XX    XX  "
+    "  XX    XX  "
+    "   XXXXXX   "
+    "            "
+    "            "
+    ))
+
+
+
+(defvar *xpm-seven*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #550000"
+    "            "
+    "  XXXXXXXX  "
+    "        XX  "
+    "       XX   "
+    "       XX   "
+    "      XX    "
+    "      XX    "
+    "     WX     "
+    "     XX     "
+    "     XX     "
+    "            "
+    "            "
+    ))
+
+
+
+(defvar *xpm-eight*
+  '(
+    "12 12 2 1"
+    "  c None"
+    "X c #441144"
+    "            "
+    "   XXXXXX   "
+    "  XX    XX  "
+    "  XX    XX  "
+    "   XXXXXX   "
+    "  XX    XX  "
+    "  XX    XX  "
+    "  XX    XX  "
+    "  XX    XX  "
+    "   XXXXXX   "
+    "            "
+    "            "
+    ))
+
+(defvar *xpm-flag*
+  '(
+    "12 12 4 1"
+    "  c None"
+    "X c #000000"
+    "R c #FF0000"
+    "r c #AA0000"
+    "            "
+    "  RRRRRRR   "
+    "  RRRRRrr   "
+    "  RRRrrrr   "
+    "  Rrrrrrr   "
+    "        X   "
+    "        X   "
+    "        X   "
+    "        X   "
+    "        X   "
+    "       XXX  "
+    "            "
+    ))
+
+
+;;;
+;;; --- A bomb.  Ooops, you're not as smart as you thought.
+;;;
+(defvar *xpm-bomb*
+  '(
+    "12 12 4 1"
+    "  c None"
+    "X c #000000"
+    "R c #FF0000"
+    "r c #AA0000"
+    "            "
+    "     X      "
+    "  X  X  X   "
+    "   XXXXX    "
+    "   XXXXX    "
+    " XXXXXXXXX  "
+    "   XXXXX    "
+    "   XXXXX    "
+    "  X  X  X   "
+    "     X      "
+    "            "
+    "            "
+    ))
+
+
+;;;
+;;; --- Wrong move!
+;;;
+(defvar *xpm-bigx*
+  '(
+    "12 12 4 1"
+    "  c None"
+    "X c #000000"
+    "R c #FF0000"
+    "r c #AA0000"
+    "RRR      RRR"
+    " RRR    RRR "
+    "  RRR  RRR  "
+    "   RRRRRR   "
+    "    RRRR    "
+    "    RRRR    "
+    "    RRRR    "
+    "   RRRRRR   "
+    "  RRR  RRR  "
+    " RRR    RRR "
+    "RRR      RRR"
+    "            "
+    ))
+
+
+;;;
+;;; --- Bitmap of a smile
+;;;
+(defvar *xpm-smile*
+  '(
+    "16 16 4 1"
+    "  c None"
+    ". c #000000"
+    "X c #FFFF00"
+    "r c #AA0000"
+    "     ......     "
+    "   ..XXXXXX..   "
+    " ..XXXXXXXXXX.  "
+    " .XXXXXXXXXXXX. "
+    " .XX..XXXX..XX. "
+    ".XXX..XXXX..XXX."
+    ".XXXXXXXXXXXXXX."
+    ".XXXXXXXXXXXXXX."
+    ".XXXXXXXXXXXXXX."
+    ".XXXXXXXXXXXXXX."
+    " .XX.XXXXXX.XX. "
+    " .XXX......XXX. "
+    "  .XXXXXXXXXX.  "
+    "   ..XXXXXX..   "
+    "     ......     "
+    "                "
+    ))
+
+
+;;;
+;;; --- frown.  You lost.
+;;;
+(defvar *xpm-frown*
+  '(
+    "16 16 4 1"
+    "  c None"
+    ". c #000000"
+    "X c #FFFF00"
+    "r c #AA0000"
+    "     ......     "
+    "   ..XXXXXX..   "
+    " ..XXXXXXXXXX.  "
+    " .XXXXXXXXXXXX. "
+    " .XX.X.XX.X.XX. "
+    ".XXXX.XXXX.XXXX."
+    ".XXX.X.XX.X.XXX."
+    ".XXXXXXXXXXXXXX."
+    ".XXXXXXXXXXXXXX."
+    ".XXXXXXXXXXXXXX."
+    " .XXX......XXX. "
+    " .XX.XXXXXX.XX. "
+    "  .XXXXXXXXXX.  "
+    "   ..XXXXXX..   "
+    "     ......     "
+    "                "
+    ))
+
+
+;;;
+;;; --- We have a winner
+;;; 
+(defvar *xpm-winner*
+  '(
+    "16 16 4 1"
+    "  c None"
+    ". c #000000"
+    "X c #FFFF00"
+    "r c #AA0000"
+    "     ......     "
+    "   ..XXXXXX..   "
+    " ..XXXXXXXXXX.  "
+    " .XXXXXXXXXXXX. "
+    " .XX...XX...XX. "
+    ".XX..........XX."
+    ".X.X...XX...X.X."
+    "..XXXXXXXXXXXX.."
+    ".XXXXXXXXXXXXXX."
+    ".XXXXXXXXXXXXXX."
+    " .XX.XXXXXX.XX. "
+    " .XXX......XXX. "
+    "  .XXXXXXXXXX.  "
+    "   ..XXXXXX..   "
+    "     ......     "
+    "                "
+    ))
+
+(defvar *digits*
+  (vector nil *xpm-one* *xpm-two* *xpm-three* *xpm-four* *xpm-five*
+	  *xpm-six* *xpm-seven* *xpm-eight*))
+
+(defun set-grid (ncols nrows nbombs)
+  (when *table*
+    (#_gtk_widget_destroy *table*))
+  (setq *table* (#_gtk_table_new ncols nrows #$FALSE))
+  (#_gtk_box_pack_start *vbox* *table* #$FALSE #$FALSE 0)
+  (#_gtk_widget_realize *table*)
+  (reset-game ncols nrows nbombs t)
+  (#_gtk_widget_show *table*))
+
+
+;;; Menu callbacks.
+
+;;; This is called both when the start button is pressed and when
+;;; the "New" menu item is selected.
+(defcallback start-button-clicked (:address widget :address data :void)
+  (declare (ignore widget data))
+  (set-start-button-icon *xpm-smile*)
+  (reset-game *ncols* *nrows* *ntotalbombs* nil))
+
+(defcallback action-beginner 
+    (:address widget :address data :void)
+  (declare (ignore data))
+  (unless (zerop (pref widget :<G>tk<C>heck<M>enu<I>tem.active))
+    (set-grid 10 10 10)))
+
+(defcallback action-intermediate 
+    (:address widget :address data :void)
+  (declare (ignore data))
+  (unless (zerop (pref widget :<G>tk<C>heck<M>enu<I>tem.active))
+    (set-grid 20 15 40)))
+
+(defcallback action-advanced
+    (:address widget :address data :void)
+  (declare (ignore data))
+  (unless (zerop (pref widget :<G>tk<C>heck<M>enu<I>tem.active))
+    (set-grid 30 20 100)))
+
+(defcallback action-quit (:address widget :address data :void)
+  (declare (ignore widget))
+  (stop-timer)
+  (#_gtk_widget_destroy data)
+  (reset-minesweeper-globals))
+
+(defcallback action-about (:void)
+  (show-about))
+
+(defun create-menu (window vbox-main)
+  (setq *win-main* window)
+  (setq *accel-group* (#_gtk_accel_group_new))
+  (#_gtk_window_add_accel_group *win-main* *accel-group*)
+  (let* ((menubar (#_gtk_menu_bar_new)))
+    (#_gtk_box_pack_start vbox-main menubar #$FALSE #$TRUE 0)
+    (#_gtk_widget_show menubar)
+    (let* ((game-menu (create-bar-sub-menu menubar "Game")))
+      (create-menu-item game-menu
+			"New" "^N" "New Game" start-button-clicked nil)
+      (create-menu-item game-menu nil nil nil nil nil)
+      (rlet ((group (* t)))
+	(setf (%get-ptr group) (%null-ptr))
+	(with-macptrs ((group-ptr group))
+	  (create-radio-menu-item game-menu "Beginner" group-ptr
+				  action-beginner nil)
+	  (create-radio-menu-item game-menu "Intermediate" group-ptr
+				  action-intermediate nil)
+	  (create-radio-menu-item game-menu "Advanced" group-ptr
+				  action-advanced nil)))
+      (create-menu-item game-menu nil nil nil nil nil)
+      (create-menu-item game-menu "Quit" nil "Quit game"
+			action-quit  *win-main*))
+    (let* ((help-menu (create-bar-sub-menu menubar "Help")))
+      (create-menu-item help-menu "About Minesweeper" nil "Gory Details"
+			action-about nil))))
+    
+
+
+
+(defparameter *cells*
+  (let* ((a (make-array (list max-cols max-rows))))
+    (dotimes (row max-rows a)
+      (dotimes (col max-cols)
+	(setf (aref a col row)
+	      (make-cell :row row :col col))))))
+
+;;; Callbacks can receive (foreign) pointer arguments.  Since we'd
+;;; rather keep information in lisp structures/arrays, that's not
+;;; directly helpful.
+
+;;; We can identify a cell by its row and column and
+;;; can easily pack the row and column into a fixnum.  This function's
+;;; caller can coerce that fixnum into a pointer (via ccl::%int-to-ptr).
+
+(defun cell->cell-id (cell)
+  (dpb (cell-row cell)
+       (byte 8 8)
+       (cell-col cell)))
+
+;;; The inverse operation: the caller (a callback) will generally have
+;;; a foreign pointer; it can coerce that to a fixnum and obtain the
+;;; corresponding cell by unpacking its indices from that fixnum.
+
+(defun cell-id->cell (cell-id)
+  (let* ((id (if (typep cell-id 'macptr)
+	       (%ptr-to-int cell-id)
+	       cell-id))
+	 (row (ldb (byte 8 8) id))
+	 (col (ldb (byte 8 0) id)))
+    (declare (fixnum id row col))
+    (aref *cells* col row)))
+
+;;; Free widget.
+(defcallback FreeChildCallback (:address widget :void)
+  (#_gtk_widget_destroy widget))
+
+;;; Free all of the widgets contained in this one.
+(defun free-children (widget)
+  (#_gtk_container_foreach
+   (#_g_type_check_instance_cast widget (#_gtk_container_get_type))
+   FreeChildCallback (%null-ptr)))
+
+(defun add-image-to-mine (cell xpm-data)
+  (let* ((widget (create-widget-from-xpm *table* xpm-data)))
+    (#_gtk_container_add (cell-button cell) widget)
+    (#_gdk_drawable_unref widget)
+    nil))
+
+(defun open-nearby-squares (col row)
+  (declare (fixnum col row))
+  (let* ((mincol (max (1- col) 0))
+	 (maxcol (min (1+ col) (1- *ncols*)))
+	 (minrow (max (1- row) 0))
+	 (maxrow (min (1+ row) (1- *nrows*))))
+    (declare (fixnum mincol maxcol minrow maxrow))
+    (do* ((i mincol (1+ i)))
+	 ((> i maxcol))
+      (declare (fixnum i))
+      (do* ((j minrow (1+ j)))
+	   ((> j maxrow))
+	(declare (fixnum j))
+	(display-hidden-info (aref *cells* i j))))))
+    
+(defun display-hidden-info (cell)
+  (case (cell-buttonstate cell)
+    (:button-down
+     (#_gtk_toggle_button_set_active (cell-button cell) #$TRUE))
+    (:button-flagged
+     (#_gtk_toggle_button_set_active (cell-button cell) #$FALSE))
+    (t
+     (setf (cell-buttonstate cell) :button-down)
+     (#_gtk_toggle_button_set_active (cell-button cell) #$TRUE)
+     (setf (pref (cell-button cell) :<G>tk<B>utton.button_down) #$TRUE)
+     (if (cell-has-bomb cell)
+       (add-image-to-mine cell *xpm-bomb*)
+       (let* ((nearby-bombs (cell-bombsnearby cell)))
+	 (declare (fixnum nearby-bombs))
+	 (if (> nearby-bombs 0)
+	   (add-image-to-mine cell (svref *digits* nearby-bombs))
+	   (open-nearby-squares (cell-col cell) (cell-row cell))))))))
+
+(defun show-bombs ()
+  (dotimes (i *ncols*)
+    (dotimes (j *nrows*)
+      (let* ((cell (aref *cells* i j))
+	     (buttonstate (cell-buttonstate cell))
+	     (has-bomb (cell-has-bomb cell)))
+	(if (and (eq buttonstate :button-unknown) has-bomb)
+	  (display-hidden-info cell)
+	  (when (and (eq buttonstate :button-flagged) (not has-bomb))
+	    (free-children (cell-button cell))
+	    (add-image-to-mine cell *xpm-bigx*)))))))
+
+	      
+  
+(defcallback cell-toggled (:address widget :address data :void)
+  (let* ((cell (cell-id->cell data))
+	 (state (cell-buttonstate cell)))
+    (unless (eq state :button-flagged)
+      (if *bgameover*
+	(#_gtk_toggle_button_set_active widget
+					(if (eq state
+						:button-down)
+					  #$TRUE
+					  #$FALSE))
+	(unless *bresetgame*
+	  (start-timer)
+	  (cond ((cell-has-bomb cell)
+		 (setq *bgameover* t)
+		 (set-start-button-icon *xpm-frown*)
+		 (stop-timer)
+		 (show-bombs))
+		(t
+		 (display-hidden-info cell)
+		 (check-for-win))))))))
+
+
+
+(defcallback button-press (:address widget :address event :address data :void)
+  (unless *bgameover*
+    (when (and (eql (pref event :<G>dk<E>vent<B>utton.type) #$GDK_BUTTON_PRESS)
+	       (eql (pref event :<G>dk<E>vent<B>utton.button) 3))
+      (let* ((cell (cell-id->cell data)))
+	(case (cell-buttonstate cell)
+	  (:button-unknown
+	   (free-children widget)
+	   (setf (cell-buttonstate cell) :button-flagged)
+	   (add-image-to-mine cell *xpm-flag*)
+	   (decf *nbombsleft*))
+	  (:button-flagged
+	   (free-children widget)
+	   (setf (cell-buttonstate cell) :button-unknown)
+	   (incf *nbombsleft*)))
+	(display-bomb-count)
+	(check-for-win)))))
+
+
+
+
+(defun set-start-button-icon (xpm-list)
+  (let* ((widget (create-widget-from-xpm *start-button* xpm-list)))
+    (free-children *start-button*)
+    (#_gtk_container_add *start-button* widget)))
+    
+(defun check-for-win ()
+  (let* ((nmines 0))
+    (declare (fixnum nmines))
+    (dotimes (col *ncols*)
+      (declare (fixnum col))
+      (dotimes (row *nrows*)
+	(declare (fixnum row))
+	(when (member (cell-buttonstate (aref *cells* col row))
+		      '(:button-unknown :button-flagged))
+	  (incf nmines))))
+    (when (= nmines (the fixnum *ntotalbombs*))
+      (stop-timer)
+      (set-start-button-icon *xpm-winner*)
+      (setq *bgameover* t))))
+
+
+(defun create-button (table cell row column)
+  (let* ((button
+	  (if *minesweeper-use-quiet-toggle-buttons*
+	    (let* ((b (gtk-quiet-toggle-button-new))
+		   (id (cell->cell-id (aref *cells* column row))))
+	      (with-cstrs ((cell-id "cell-id"))
+		(#_gtk_object_set_data b cell-id (%int-to-ptr id)))
+	      b)
+	    (#_gtk_toggle_button_new)))
+	 (cell-id (cell->cell-id cell)))
+    (with-cstrs ((toggled "toggled")
+		 (button-press-event "button_press_event"))
+      (#_gtk_signal_connect_full button toggled cell-toggled
+                                 (%null-ptr) (%int-to-ptr cell-id) (%null-ptr) 0 0)
+      (#_gtk_signal_connect_full button button-press-event
+			    button-press (%null-ptr) (%int-to-ptr cell-id) (%null-ptr) 0 0))
+    (#_gtk_table_attach table button
+			column (1+ column)
+			(1+ row) (+ row 2)
+			(logior #$GTK_FILL #$GTK_EXPAND)
+			(logior #$GTK_FILL #$GTK_EXPAND)
+			0 0)
+    (#_gtk_widget_set_usize button button-width button-height)
+    (#_gtk_widget_show button)
+    button))
+
+    
+(defun count-nearby-bombs (col row)
+  (declare (fixnum col row))
+  (let* ((mincol (max (1- col) 0))
+	 (maxcol (min (1+ col) (1- *ncols*)))
+	 (minrow (max (1- row) 0))
+	 (maxrow (min (1+ row) (1- *nrows*)))
+	 (ncount 0))
+    (declare (fixnum mincol maxcol minrow maxrow ncount))
+    (do* ((i mincol (1+ i)))
+	 ((> i maxcol) ncount)
+      (declare (fixnum i))
+      (do* ((j minrow (1+ j)))
+	   ((> j maxrow))
+	(declare (fixnum j))
+	(if (cell-has-bomb (aref *cells* i j))
+	  (incf ncount))))))
+
+(defun display-bomb-count ()
+  (with-cstrs ((buf (format nil "Bombs: ~d" *nbombsleft*)))
+    (#_gtk_label_set_text *bombs-label* buf)))
+
+(defun update-seconds (seconds)
+  (with-cstrs ((buf (format nil "Time: ~d" seconds)))
+    (#_gtk_label_set_text *time-label* buf)))
+  
+(defun create-minesweeper-buttons (table ngridcols ngridrows bnewbuttons)
+  (setq *nrows* ngridrows
+	*ncols* ngridcols
+	*bgameover* nil
+	*bresetgame* t)
+  (display-bomb-count)
+  (dotimes (ci *ncols*)
+    (declare (fixnum ci))
+    (dotimes (ri *nrows*)
+      (declare (fixnum ri))
+      (let* ((cell (aref *cells* ci ri)))
+	(setf (cell-has-bomb cell) nil
+	      (cell-buttonstate cell) :button-unknown)
+	(if bnewbuttons
+	  (setf (cell-button cell) (create-button table cell ri ci))
+	  (progn
+	    (free-children (cell-button cell))
+	    (#_gtk_toggle_button_set_active (cell-button cell) #$FALSE))))))
+  (do* ((nbombs *ntotalbombs*)
+	(state (make-random-state t)))
+       ((zerop nbombs))
+    (declare (fixnum nbombs))
+    (let* ((cell (aref *cells* (random *ncols* state) (random *nrows* state))))
+      (unless (cell-has-bomb cell)
+	(setf (cell-has-bomb cell) t)
+	(decf nbombs))))
+  (dotimes (ci *ncols*)
+    (declare (fixnum ci))
+    (dotimes (ri *nrows*)
+      (declare (fixnum ri))
+      (setf (cell-bombsnearby (aref *cells* ci ri))
+	    (count-nearby-bombs ci ri))))
+  (setq *bresetgame* nil))
+		   
+(defun reset-game (ncols nrows nbombs bnewbuttons)
+  (setq *ntotalbombs* nbombs
+	*nbombsleft* nbombs)
+  (create-minesweeper-buttons *table* ncols nrows bnewbuttons)
+  (stop-timer)
+  (update-seconds 0)
+  (set-start-button-icon *xpm-smile*))
+
+
+	     
+;;; Timer stuff.
+
+(defvar *timer* nil)
+(defvar *nseconds* 0)
+
+(defcallback timer-callback (:address data :void)
+  (declare (ignore data))
+  (incf *nseconds*)
+  (update-seconds *nseconds*))
+
+(defun start-timer ()
+  (unless *timer*
+    (setq *nseconds* 0
+	  *timer* (#_gtk_timeout_add 1000 timer-callback *win-main*))))
+
+(defun stop-timer ()
+  (when *timer*
+    (#_gtk_timeout_remove *timer*)
+    (setq *timer* nil)))
+
+
+;;; Finally ...
+
+(defun minesweeper ()
+  (when *win-main*
+    (cerror
+     "Close current minesweeper game and start a new one"
+     "It seems that a minesweeper game is already active.")
+    (do* ()
+	 ((null *win-main*))
+      (#_gtk_widget_destroy *win-main*)
+      (sleep 1)))
+  (let* ((window (#_gtk_window_new #$GTK_WINDOW_TOPLEVEL)))
+    (#_gtk_window_set_policy window #$FALSE #$FALSE #$TRUE)
+    (with-cstrs ((window-title "Minesweeper"))
+      (#_gtk_window_set_title window window-title)
+      (setq *vbox* (#_gtk_vbox_new #$FALSE 1))
+      (#_gtk_widget_show *vbox*)
+      (create-menu window *vbox*)
+      (let* ((hbox (#_gtk_hbox_new #$TRUE 1)))
+	(#_gtk_widget_show hbox)
+	(#_gtk_box_pack_start *vbox* hbox #$FALSE #$FALSE 0)
+	(with-cstrs ((len0-string ""))
+	  (setq *bombs-label* (#_gtk_label_new len0-string)
+		*time-label* (#_gtk_label_new len0-string)))
+	(#_gtk_box_pack_start hbox *bombs-label* #$FALSE #$FALSE 0)
+	(#_gtk_widget_show *bombs-label*)
+	(setq *start-button* (#_gtk_button_new))
+	(with-cstrs ((clicked "clicked"))
+	  (#_gtk_signal_connect_full *start-button* clicked start-button-clicked
+				(%null-ptr) (%null-ptr) (%null-ptr) 0 0))
+	(#_gtk_box_pack_start hbox *start-button* #$FALSE #$FALSE 0)
+	(#_gtk_widget_show *start-button*)
+	(#_gtk_box_pack_start hbox *time-label* #$FALSE #$FALSE 0)
+	(#_gtk_widget_show *time-label*)
+	(#_gtk_widget_show hbox)
+	(#_gtk_container_add window *vbox*)
+	(with-cstrs ((destroy "destroy"))
+	  (#_gtk_signal_connect_full window destroy action-quit (%null-ptr) window (%null-ptr) 0 0))
+	(#_gtk_widget_show window)
+
+	(set-start-button-icon *xpm-smile*)
+	(set-grid 10 10 10)))))
Index: /branches/new-random/examples/gtk2-clock.lisp
===================================================================
--- /branches/new-random/examples/gtk2-clock.lisp	(revision 13309)
+++ /branches/new-random/examples/gtk2-clock.lisp	(revision 13309)
@@ -0,0 +1,274 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006 Clozure Associates
+;;;   This file is part of OpenMCL.  
+;;;
+;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with OpenMCL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CL-USER")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (use-interface-dir :gtk2))
+
+
+;;; Loading "libgnomeui-2.so" seems to be the easiest way to force all of
+;;; its dependent libraries to be loaded
+(open-shared-library "libgnomeui-2.so")
+
+(defloadvar *gdk-threads-inited* nil)
+(defloadvar *gthread-inited* nil)
+
+
+;;; Set things up so that GDK will use lisp locks internally.
+;;; There are a few advantages to this, including the fact
+;;; that lisp locks are that newfangled recursive kind (a thread
+;;; that owns the lock can lock it agains, which is slightly
+;;; better than waiting forever for it to be released.)
+(defvar *gdk-lock* (make-lock))
+
+
+;;; Callbacks called by #_gdk_threads_enter and #_gdk_threads_leave.
+(defcallback lock-gdk-lock (:void)
+  (grab-lock *gdk-lock*))
+
+(defcallback unlock-gdk-lock (:void)
+  (release-lock *gdk-lock*))
+
+
+(defmacro with-gdk-lock-grabbed (&body body)
+  `(with-lock-grabbed (*gdk-lock*)
+    ,@body))
+
+;;; gtk_signal_connect is a C macro. Emulate it.
+(defmacro gtk-signal-connect (object name function user-data)
+  `(external-call "gtk_signal_connect_full"
+    :address ,object
+    :address ,name
+    :address ,function
+    :<G>tk<C>allback<M>arshal (%null-ptr)
+    :gpointer ,user-data
+    :<G>tk<D>estroy<N>otify (%null-ptr)
+    :gint 0
+    :gint 0
+    :gulong))
+
+(defcallback window-destroy-handler (:address window :void)
+  (declare (ignore window))
+  (#_gtk_main_quit))
+
+
+
+(defconstant single-float-pi (coerce pi 'single-float))
+
+;;; A global alist mapping clock windows to their offscreen pixmaps.
+(defvar *gtk-clock-window-pixmaps* ())
+
+
+(defun draw-tick-at (pixmap gc nhour cx cy radius)
+  (let* ((radians (/ (* single-float-pi nhour) 6.0))
+	 (sin-radians (sin radians))
+	 (cos-radians (cos radians))
+	 (95%radius (* radius .95)))
+    (#_gdk_draw_line pixmap gc
+		     (+ cx (floor (* 95%radius sin-radians)))
+		     (+ cy (floor (* 95%radius cos-radians)))
+		     (+ cx (floor (* radius sin-radians)))
+		     (+ cy (floor (* radius cos-radians))))))
+
+;;; It seems like this can get called when the drawing area's in the
+;;; process of being destroyed.  Try not to segfault in that case.
+(defcallback gtk-clock-repaint (:address data :signed-fullword)
+  (if (or (%null-ptr-p data)
+	  (%null-ptr-p (pref data :<G>tk<W>idget.style)))
+    #$FALSE
+    (let* ((drawing-area data)
+	   (radius 0)
+	   (white-gc (pref drawing-area :<G>tk<W>idget.style.white_gc))
+	   (black-gc (pref drawing-area :<G>tk<W>idget.style.black_gc))
+	   (area-width  (pref drawing-area :<G>tk<W>idget.allocation.width))
+	   (area-height (pref drawing-area :<G>tk<W>idget.allocation.height))
+	   (dradians)
+	   (midx 0)
+	   (midy 0)
+	   (vbox (pref drawing-area :<G>tk<W>idget.parent))
+	   (window (pref vbox :<G>tk<W>idget.parent))
+	   (pixmap (cdr (assoc window *gtk-clock-window-pixmaps*))))
+      (rlet ((update-rect :<G>dk<R>ectangle))
+	    ;; Clear pixmap (background image)
+	    (#_gdk_draw_rectangle
+	     pixmap white-gc #$TRUE 0 0 area-width area-height)
+	    
+	    ;; Calculate midpoint of clock.
+	    (setq midx (ash area-width -1)
+		  midy (ash area-height -1))
+	    
+	    ;; Calculate radius
+	    (setq radius (min midx midy))
+
+	    ;; Draw circle
+	    (#_gdk_draw_arc pixmap black-gc 0 0 0
+			    (+ midx midx) (+ midy midy) 0 (* 360 64))
+      
+	    ;; Draw tickmarks on clock face.
+	    (do* ((nhour 1 (1+ nhour)))
+		 ((> nhour 12))
+	      (draw-tick-at pixmap black-gc nhour midx midy radius))
+	    (multiple-value-bind (seconds minutes hours)
+                (get-decoded-time)
+	      
+	      ;; Get radians from seconds
+	      (setq dradians (/ (* seconds single-float-pi) 30.0))
+	      
+	      ;; Draw second hand.
+	      (#_gdk_draw_line
+	       pixmap black-gc midx midy
+	       (+ midx (floor (* 0.9 radius (sin dradians))))
+	       (- midy (floor (* 0.9 radius (cos dradians)))))
+	      
+	      ;; Get radians from minutes & seconds.
+	      (setq dradians (+ (/ (* minutes single-float-pi) 30.0)
+				(/ (* seconds single-float-pi) 1800.0)))
+	      
+	      ;; Draw minute hand.
+	      (#_gdk_draw_line
+	       pixmap black-gc midx midy
+	       (+ midx (floor (* 0.7 radius (sin dradians))))
+	       (- midy (floor (* 0.7 radius (cos dradians)))))
+	      
+	      ;; Get radians from hours & minutes.
+	      (setq dradians (+ (/ (* (mod hours 12) pi) 6.0)
+				(/ (* minutes pi) 360.0)))
+	      
+	      ;; Draw hour hand.
+	      (#_gdk_draw_line
+	       pixmap black-gc midx midy
+	       (+ midx (floor (* 0.5 radius (sin dradians))))
+	       (- midy (floor (* 0.5 radius (cos dradians)))))
+	      
+	      ;; Setup the update rectangle; this will force an expose event.
+	      ;; The expose event handler will then copy the pixmap to the
+	      ;; window.
+	      
+	      (setf (pref update-rect :<G>dk<R>ectangle.x) 0
+		    (pref update-rect :<G>dk<R>ectangle.y) 0
+		    (pref update-rect :<G>dk<R>ectangle.width) area-width
+		    (pref update-rect :<G>dk<R>ectangle.height) area-height)
+	      
+	      ;; Draw the update rectangle.
+	      (#_gtk_widget_draw drawing-area update-rect)
+	      #$TRUE)))))
+
+
+;;; This is called when the window's created and whenever it's
+;;; resized.  Create a new pixmap of appropriate
+;;; size; free the old one (if it's non-null).
+(defcallback gtk-clock-configure-event
+    (:address widget :address event :address window :signed-fullword)
+  (declare (ignore event))
+  (let* ((pair (assoc window *gtk-clock-window-pixmaps*)))
+    (if (cdr pair)
+      (#_gdk_drawable_unref (cdr pair)))
+    (setf (cdr pair)
+	  (#_gdk_pixmap_new (pref widget :<G>tk<W>idget.window)
+			    (pref widget :<G>tk<W>idget.allocation.width)
+			    (pref widget :<G>tk<W>idget.allocation.height)
+			    -1)))
+  #$TRUE)
+
+;;; Copy the window's pixmap to the exposed region of the window.
+(defcallback gtk-clock-expose-event
+    (:address widget :address event :address window :signed-fullword)
+  (let* ((state (pref widget :<G>tk<W>idget.state))
+	 (pixmap (cdr (assoc window *gtk-clock-window-pixmaps*)))
+	 (fg-gc (pref widget :<G>tk<W>idget.style.fg_gc))
+	 (x (pref event :<G>dk<E>vent<E>xpose.area.x))
+	 (y (pref event :<G>dk<E>vent<E>xpose.area.y))
+	 (width (pref event :<G>dk<E>vent<E>xpose.area.width))
+	 (height (pref event :<G>dk<E>vent<E>xpose.area.height)))
+    (#_gdk_draw_drawable
+     (pref widget :<G>tk<W>idget.window)
+     (%get-ptr fg-gc (ash state target::word-shift))
+     pixmap
+     x y
+     x y
+     width height)
+    #$FALSE))
+
+;;; When the window's destroyed, delete its entry from the
+;;; *gtk-clock-window-pixmaps* alist.
+
+(defcallback gtk-clock-close (:address window :void)
+  (let* ((pair (assoc window *gtk-clock-window-pixmaps*)))
+    (if pair
+      (if (null (setq *gtk-clock-window-pixmaps*
+                      (delete pair *gtk-clock-window-pixmaps*)))
+        (#_gtk_main_quit))
+      (break "No entry for window!"))))
+
+(defun gtk-clock ()
+  (let* ((window (#_gtk_window_new #$GTK_WINDOW_TOPLEVEL))
+	 (vbox (#_gtk_vbox_new #$FALSE 0)))
+    (push (cons window nil) *gtk-clock-window-pixmaps*)
+    (#_gtk_container_add window vbox)
+    (#_gtk_widget_show vbox)
+    (let* ((drawing-area (#_gtk_drawing_area_new)))
+      (#_gtk_drawing_area_size drawing-area 200 200)
+      (#_gtk_box_pack_start vbox drawing-area #$TRUE #$TRUE 0)
+      (#_gtk_widget_show drawing-area)
+      (with-cstrs ((expose-name "expose_event")
+		   (configure-name "configure_event")
+		   (destroy-name "destroy")
+		   (window-title
+		     "Takes a licking.  Keeps on ticking."))
+	(#_gtk_window_set_title window window-title)
+	(gtk-signal-connect drawing-area
+			      expose-name
+			      gtk-clock-expose-event
+			      window)
+	(gtk-signal-connect drawing-area
+                            configure-name
+                            gtk-clock-configure-event
+                            window)
+	(gtk-signal-connect window
+                            destroy-name
+                            gtk-clock-close
+                            (%null-ptr)))
+      (#_gtk_widget_show window)
+      (#_gtk_timeout_add 1000 gtk-clock-repaint drawing-area)
+      (values))))
+
+
+(defun main (&rest args)
+  (unless *gthread-inited*
+    (#_g_thread_init (%null-ptr))
+    (setq *gthread-inited* t))
+  (unless *gdk-threads-inited*
+    ;; Tell GDK to use our locks.
+    (#_gdk_threads_set_lock_functions lock-gdk-lock unlock-gdk-lock)
+    (#_gdk_threads_init)
+    (setq *gdk-threads-inited* t))
+  (process-run-function "GTK Event thread"
+                        #'(lambda ()
+                            (#_gdk_threads_enter)
+                            (rlet ((argc :int)
+                                   (argvp (:* t)))
+                              (with-string-vector (argv args)
+                                (setf (pref argc :int) (length args)
+                                      (%get-ptr argvp ) argv)
+                                (#_gtk_init argc argvp)))
+                            (gtk-clock)
+                            (#_gtk_main)
+                            (#_gdk_threads_leave))))
+
+;;; calling (MAIN) starts an event thread and displays a clock.
+;;; subsequent calls to (GTK-CLOCK) display additional clocks,
+;;;  if/when they can get a word in edgewise ...
Index: /branches/new-random/examples/jfli/CPL.TXT
===================================================================
--- /branches/new-random/examples/jfli/CPL.TXT	(revision 13309)
+++ /branches/new-random/examples/jfli/CPL.TXT	(revision 13309)
@@ -0,0 +1,94 @@
+Common Public License Version 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+
+1. DEFINITIONS 
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and 
+
+b) in the case of each subsequent Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program. 
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement. 
+
+"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 
+
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
+
+
+3. REQUIREMENTS 
+
+A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: 
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; 
+
+ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; 
+
+iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and 
+
+iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. 
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program. 
+
+Contributors may not remove or alter any copyright notices contained within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 
+
+
+4. COMMERCIAL DISTRIBUTION 
+
+Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. 
+
+For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 
+
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 
+
+
+6. DISCLAIMER OF LIABILITY 
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 
+
+If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. 
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. 
+
+This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
Index: /branches/new-random/examples/jfli/com/richhickey/jfli/LispInvocationHandler.java
===================================================================
--- /branches/new-random/examples/jfli/com/richhickey/jfli/LispInvocationHandler.java	(revision 13309)
+++ /branches/new-random/examples/jfli/com/richhickey/jfli/LispInvocationHandler.java	(revision 13309)
@@ -0,0 +1,17 @@
+package com.richhickey.jfli;
+
+//    Copyright (c) Rich Hickey. All rights reserved.
+//    The use and distribution terms for this software are covered by the
+//    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+//    which can be found in the file CPL.TXT at the root of this distribution.
+//    By using this software in any fashion, you are agreeing to be bound by
+//    the terms of this license.
+//    You must not remove this notice, or any other, from this software.
+
+import java.lang.*;
+import java.lang.reflect.*;
+
+public class LispInvocationHandler implements InvocationHandler
+{
+public native Object invoke(Object proxy,Method method, Object[] args) throws Throwable;
+}
Index: /branches/new-random/examples/jfli/docs/jfli.css
===================================================================
--- /branches/new-random/examples/jfli/docs/jfli.css	(revision 13309)
+++ /branches/new-random/examples/jfli/docs/jfli.css	(revision 13309)
@@ -0,0 +1,126 @@
+img {
+  border: 0;
+}
+body {
+  margin: 5px 10% 5px 55px;
+  padding: 5px;
+  border: 0;
+  background: #fff url(jfli_bkgrnd.gif) top left repeat-y;
+  color: #222;
+  font: small/1.6em "Lucida Grande", "Trebuchet MS", "Bitstream Vera Sans", Verdana, Helvetica, sans-serif;
+}
+
+
+a:link {
+  color: #339;
+  text-decoration: none;
+  border-bottom: 2px solid #ccf;
+}
+a:visited {
+  color: #339;
+  text-decoration: none;
+  border-bottom: 2px solid #ddd;
+}
+a:hover {
+  color: #66c;
+  text-decoration: none;
+  border-bottom: 2px solid #ccf;
+}
+a:active {
+  color: #339;
+  text-decoration: none;
+  border-bottom: 2px solid #ccf;
+}
+
+p {
+  margin: 0 0 1em 0;
+  line-height: 140%;
+}
+
+
+h1 {
+  text-indent: -9999px;
+  margin: 0;
+  padding: 0;
+  border: 0;
+}
+	
+h1 a:link, h1 a:visited {
+  display: block;	
+  width: 539px;
+  height: 86px;
+  background: #fff url(jfli_new.gif) top left no-repeat;
+  margin: 0;
+  padding: 0;
+  border: 0;
+  text-decoration: none;
+}
+	
+h1 a:hover {
+  background: #fff url(jfli_new.gif) top left no-repeat;
+  border: 0;
+}
+
+h2 {
+  margin: .75em 0 .25em;
+  font: 170%/1.7em Georgia, serif;
+  color: #66c;
+}
+h3 {
+  margin: 1em 0 .25em;
+  font: 130%/1.4em Georgia, serif;
+  color: #339;
+}
+h4 {
+  margin: 1em 0 .25em;
+  font: 120%/1.3em Georgia, serif;
+  color: #888;
+}
+
+pre, code {
+  color: #404;
+  /*
+  font-family: monaco, "Bitstream Vera Sans Mono", "Courier New", courier, monospace;
+  font-weight: normal;
+  font-size: small;
+  */
+  font: small/1.6em monaco, "Bitstream Vera Sans Mono", "Courier New", courier, monospace;
+  line-height: 1.4em;
+}
+pre {
+  margin: 1em 0 1.4em;
+  margin-left: 3%;
+  width: 77%;
+  border-left: 4px solid #eee;
+  padding: 2px;
+  padding-left: 10px;
+}
+
+ol li {
+  list-style: decimal outside;
+  line-height: 150%;
+  margin: 0 5px 5px 0;
+  padding: 0 0 0 5px;
+}
+
+ul {
+  margin: 3px 0;
+  padding: 0 0 5px 0;
+}
+	
+ul li	{
+  line-height: 150%;
+  margin-bottom: 5px;
+  padding-bottom: 0;
+  padding-left: 18px;
+  padding-top: 2px;
+  margin-left: 5px;
+  list-style: none;
+  background:url("bullet.gif") no-repeat 0px .5em;
+}
+	
+ul ul li {
+  margin-top: 4px;
+  list-style: none;
+  background:url("bullet2.gif") no-repeat 0px .5em;
+}
Index: /branches/new-random/examples/jfli/docs/jfli.html
===================================================================
--- /branches/new-random/examples/jfli/docs/jfli.html	(revision 13309)
+++ /branches/new-random/examples/jfli/docs/jfli.html	(revision 13309)
@@ -0,0 +1,620 @@
+<html>
+<head>
+	<link rel="stylesheet" type="text/css" media="screen" href="jfli.css">
+</head>
+	<body>
+	<h1><a href="/" title="Rich Hickey's jfli - a Java Foreign Language Interface for Common Lisp">jfli 
+	- a Java Foreign Language Interface for Common Lisp</a></h1>
+
+	<h5>Copyright (c) Rich Hickey. All rights reserved.</h5>
+
+	<p>
+	The use and distribution terms for this software are covered by the <a href="http://opensource.org/licenses/cpl.php">Common 
+	Public License 1.0</a>, which can be found in the file CPL.TXT at the root of 
+	this distribution. By using this software in any fashion, you are agreeing to be 
+	bound by the terms of this license. You must not remove this notice, or any 
+	other, from this software.
+	</p>
+
+	<h2>Contents</h2>
+
+	<ul>
+		<li>
+			<a href="#intro">Introduction</a>
+		</li>
+		<li>
+			<a href="#download">Download</a>
+		</li>
+		<li>
+			<a href="#setup">Setup and Configuration</a>
+		</li>
+		<li>
+			<a href="#quickstart">Quick Start</a>
+		</li>
+		<li>
+			<a href="#api">API Reference</a>
+			<ul>
+				<li>
+					<a href="#jvmcreation">JVM Creation and Initialization</a>
+				</li>
+				<li>
+					<a href="#wrappergen">Wrapper Generation</a>
+				</li>
+				<li>
+					<a href="#objects">Object Creation</a>
+				</li>
+				<li>
+					<a href="#arrays">Arrays</a>
+				</li>
+				<li>
+					<a href="#proxies">Proxies - Java calling back to Lisp</a>
+				</li>
+				<li>
+					<a href="#utilities">Utilities</a>
+				</li>
+			</ul>
+		</li>
+		<li>
+			<a href="#summary">Summary</a>
+		</li>
+	</ul>
+
+
+	<a name="intro"></a> <h3>Introduction</h3>
+
+	<p>
+	My objective was to provide comprehensive, safe, dynamic and Lisp-y access to 
+	Java and Java libraries as if they were Lisp libraries, for use in Lisp programs, 
+	i.e.  with an emphasis on working in Lisp rather than in Java.
+	</p>
+
+	<p>
+	The approach I took was to embed a JVM instance in the Lisp process using JNI. I 
+	was able to do this using LispWorks' own FLI and no C (or Java! *) code, which 
+	is a tribute to the LW FLI.  On top of the JNI layer (essentially a wrapper 
+	around the entire JNI API), I built this user-level API using Java Reflection. 
+	This first version was built with, and contains code specific to, Xanalys <a
+								 href="http://www.lispworks.com/">LispWorks</a>.
+	</p>
+
+
+	<p>
+	<em>jfli</em> ("jay fly") provides:
+	</p>
+
+	<ul>
+
+		<li>
+			Automatic function generation for constructors, fields and methods, either by 
+			named class, or entire package (sub)trees given a jar file.
+		</li>
+
+		<li>
+			Java -> Lisp package and name mapping with an eye towards lack of surprise, lack 
+			of conflict, and useful editor completion.
+		</li>
+
+		<li>
+			setf-able setter generation for fields as well as for methods that follow the 
+			JavaBeans property protocol.
+		</li>
+
+		<li>
+			Java array creation and aref-like access to Java arrays.
+		</li>
+
+		<li>
+			A 'new' macro that allows for keyword-style field and property initialization.
+		</li>
+
+		<li>
+			Typed references to Java objects with an inheritance hierarchy on the Lisp side 
+			mirroring that on the Java side - allowing for Lisp methods specialized on Java 
+			class and interface types.
+		</li>
+
+		<li>
+			Implementation of arbitrary Java interfaces in Lisp, and callbacks from Java to 
+			Lisp via those interfaces.  (* this required a single 5-line dummy Java proxy 
+			stub, provided with jfli)
+		</li>
+
+		<li>
+			Automatic lifetime maintenance of Lisp-referenced Java objects, boxing/unboxing 
+			of primitive args/returns, string conversions, Java exception handling, overload 
+			resolution etc.
+		</li>
+	</ul>
+
+	<p>
+	I built jfli using LWM and LWW (using Apple's and Sun's JVMs respectively), and 
+	it works fine on both.  Should be a trivial port to other LispWorks, and a 
+	possible port to any Common Lisp with a robust FLI. Should also work with any 
+	JVM with a conformant JNI implementation.
+	</p>
+
+	<a name="download"></a> <h3>Download</h3>
+
+	<p>
+	jfli is hosted on <a href="http://sourceforge.net/projects/jfli/">SourceForge</a>
+	</p>
+
+	<a name="setup"></a> <h3>Setup and Configuration</h3>
+
+	<p>
+	jfli is supplied in 2 Lisp files and an optional Java .jar file.  The first Lisp 
+	file, jni.lisp, defines a low-level API to the Java Native Interface, and is not 
+	documented here. The second, jfli.lisp, depends upon jni.lisp, and provides the 
+	user API documented here. Simply compile and load jni.lisp, then compile and 
+	load jfli.lisp. <code>(use-package :jfli)</code> and you are ready to use the 
+	API. Note that prior to creating the JVM you must tell the library how to find 
+	the Java JNI library by setting <a
+								  href="#jnilibpath"><code>*jni-lib-path*</code></a>.
+	</p>
+	<p>
+	If you wish to allow for callbacks from Java to Lisp, you must place jfli.jar in 
+	your classpath when <a href="#jvmcreation">creating the JVM</a>.
+	</p>
+
+
+	<a name="quickstart"></a> <h3>Quick Start</h3>
+	<p>
+	This sample session presumes you have already compiled jni.lisp and jfli.lisp into fasl files.
+	</p>
+	<pre>
+CL-USER 4 > (load "/lisp/jni")
+; Loading fasl file C:\lisp\jni.fsl
+#P"C:/lisp/jni.fsl"
+
+CL-USER 5 > (load "/lisp/jfli")
+; Loading fasl file C:\lisp\jfli.fsl
+#P"C:/lisp/jfli.fsl"
+
+;The user API is entirely in the jfli package
+CL-USER 6 > (use-package :jfli)
+T
+
+;tell the library where Java is located
+CL-USER 7 > (setf *jni-lib-path* "/j2sdk1.4.2_01/jre/bin/client/jvm.dll")
+"/j2sdk1.4.2_01/jre/bin/client/jvm.dll"
+
+;this starts the VM - note how you can set the classpath
+CL-USER 8 > (create-jvm "-Djava.class.path=/lisp/jfli.jar")
+0
+#&lt;Pointer: JNI:PVM = #x081022A0>
+#&lt;Pointer: JNI:PENV = #x0086A858>
+
+;define wrappers for the members of Object
+CL-USER 9 > (def-java-class "java.lang.Object")
+NIL
+
+;and of Properties, a Hashtable-like class
+CL-USER 10 > (def-java-class "java.util.Properties")
+#&lt;STANDARD-CLASS |java.util|:PROPERTIES. 2066B964>
+
+;the above will create these packages if they do not already exist
+;use the packages for easy name access
+
+CL-USER 11 > (use-package "java.lang")
+T
+
+CL-USER 12 > (use-package "java.util")
+T
+
+;create a Properties instance, note keyword-style member inits, string conversion etc
+;also note typed return value
+CL-USER 13 > (setf p (new properties. :getproperty "fred" "ethel"))
+#&lt;PROPERTIES. 20664A94>
+
+;virtual functions work as normal
+CL-USER 14 > (object.tostring p)
+"{fred=ethel}"
+
+;setter was generated for member function because it follows the JavaBeans property protocol
+CL-USER 15 > (setf (properties.getproperty p "ricky") "lucy")
+"lucy"
+
+CL-USER 16 > (object.tostring p)
+"{ricky=lucy, fred=ethel}"
+
+CL-USER 17 > (properties.size p)
+2
+
+;totally dynamic access, create wrappers as you need
+CL-USER 18 > (def-java-class "java.lang.Class")
+#&lt;STANDARD-CLASS CLASS. 20680EC4>
+
+CL-USER 19 > (class.getname (object.getclass p))
+"java.util.Properties"
+
+CL-USER 20 > (def-java-class "java.util.Enumeration")
+#&lt;STANDARD-CLASS ENUMERATION. 20669274>
+
+;no need to wait for the vendor to enhance the language - you use Lisp!
+CL-USER 21 > (defmacro doenum ((e enum) &body body)
+               (let ((genum (gensym)))
+                 `(let ((,genum ,enum))
+                    (do ()
+                        ((not (enumeration.hasmoreelements ,genum)))
+                      (let ((,e (enumeration.nextelement ,genum)))
+                        ,@body)))))
+DOENUM
+
+;can't do this in Java yet
+CL-USER 22 > (doenum (prop (properties.elements p)) (print (object.tostring prop)))
+
+"lucy"
+"ethel"
+NIL
+
+;doc strings are created giving original Java signatures and indicating
+overloads
+CL-USER 23 > (documentation 'properties.getproperty 'function)
+"java.lang.String getProperty(java.lang.String,java.lang.String)
+java.lang.String getProperty(java.lang.String)
+"
+
+CL-USER 24 > (documentation 'properties.new 'function)
+"java.util.Properties()
+java.util.Properties(java.util.Properties)
+"
+	</pre>
+
+	<a name="api"></a> <h2>API Reference</h2>
+
+	<a name="jvmcreation"></a> <h3>JVM Creation and Initialization</h3>
+	<ul>
+
+		<li>
+			<a name="jnilibpath"></a><code>*jni-lib-path*</code>
+			<p>
+			Set this to point to your jvm dll prior to calling create-jvm.
+			</p>
+		</li>
+
+		<li>
+			<strong>Function</strong> <code>(create-jvm &rest option-strings) -> unspecified</code>
+			<p>
+			Creates/starts the JVM. This can only be done once (a Java limitation). <em>You 
+			must call this prior to calling any other jfli function.</em> The option strings 
+			can be used to control the JVM, esp. the classpath:
+			</p>
+			<p>
+			<pre>(create-jvm "-Djava.class.path=/Lisp/jfli.jar")</pre>
+			</p>
+			<p>
+			See the JNI documentation for other initialization options.
+			</p>
+		</li>
+
+		<li>
+			<a name="enableproxies"></a> <strong>Function</strong> <code>(enable-java-proxies) 
+			-> unspecified</code>
+			<p>
+			Sets up the Java->Lisp callback support. Must be called (once) before any calls 
+			to new-proxy, and requires jfli.jar be in the classpath.
+			</p>
+		</li>
+	</ul>
+
+	<a name="wrappergen"></a> <h3>Wrapper Generation</h3>
+
+	<ul>
+		<li>
+			<strong>Macro</strong> <code>(def-java-class full-class-name) -> unspecified</code>
+			<p>
+			Given the package-qualified, case-correct name of a Java class as a string, will 
+			generate wrapper functions for its public constructors, fields and methods.
+			</p>
+			<p>
+			The core API for generation interfaces to Java is the def-java-class macro. This 
+			macro will, at expansion time, use Java reflection to find all of the public 
+			constructors, fields and methods of the given class and generate functions to 
+			access them.
+			</p>
+			<h4>The Generated API</h4> When you e.g. <code>(def-java-class "java.lang.ClassName 
+			 ")</code> you get several symbols/functions:
+			<ul>
+				<li>
+					A package named <code>|java.lang|</code> (note case)<br>
+					from which the following are exported:
+				</li>
+				<li>
+					A class-symbol: <code>classname.</code> (note the dot is part of the name)<br>
+					which can usually be used where a typename is required. It also serves as the 
+					name of the Lisp typed reference class.
+				</li>
+				<li>
+					Every non-interface class with a public constructor will get;
+					<ul>
+						<li>
+							A constructor, <code>(classname.new &rest args) -> typed-reference</code>, which 
+							returns a typed reference to the newly created object
+						</li>
+						<li>
+							A method defined on <a href=#makenew><code>make-new</code></a>, ultimately 
+							calling <code>classname.new</code>, specialized on (the value of) the class-symbol
+						</li>
+					</ul>
+					Note that if the constructor is overloaded, there is just one function generated, 
+					which handles overload resolution. The function documentation string describes 
+					the constructor signature(s) from the Java perspective. The same argument 
+					conversions are performed as are for fields (see below).
+				</li>
+				<li>
+					All public fields will get a getter function:<br>
+					<code>(classname.fieldname [instance]) -> field value</code><br>
+					and a setter:<br>
+					<code>(setf classname.fieldname [instance])</code><br>
+					Instance field wrappers take a first arg which is the instance. Static fields 
+					get a symbol-macro <code>*classname.fieldname*</code>
+					<p>
+					If the type of the field is primitive, the field value will be converted to a 
+					native Lisp value. If it is a Java String, it will be converted to a Lisp string. 
+					Otherwise, a generic reference to the Java object is returned. Similarly, when 
+					setting, Lisp values will be accepted for primitives, Lisp strings for Strings, 
+					or (generic or typed) references for reference types.
+					</p>
+				</li>
+				<li>
+					Every public method will get a wrapper function:<br>
+					<code>(classname.methodname &rest args) -> return-value</code><br>
+					As with constructors, if a method is overloaded a single wrapper is created that 
+					handles overload resolution. If a method follows the JavaBeans property protocol 
+					(i.e. it is called <code>getSomething</code> or <code>isSomething</code> and 
+					there is a corresponding <code>setSomething</code>), then a <code>(setf 
+					classname.methodname)</code> will be defined that calls the latter.
+					<p>
+					The same argument and return value conversions are performed as are for fields. 
+					The function documentation string describes the method signature(s) from the 
+					Java perspective.
+					</p>
+
+				</li>
+				<li>
+					A Lisp class with the class-symbol as its name. It will have as its superclasses 
+					other Lisp classes corresponding to the Java superclass/superinterfaces, some of 
+					which may be forward-referenced-classes.  An instance of this class will be 
+					returned by classname.new/make-new/new, at which point the entire hierarchy will 
+					consist of finalized standard-classes.
+				</li>
+				<li>
+					Note that, due to the need to reference other Java types during the definition 
+					of a class wrapper, symbols, classes, and packages relating to those other types 
+					may also be created. In all cases they will be created with names and 
+					packages as described above.
+				</li>
+			</ul>
+		</li>
+
+		<li>
+			<strong>Function</strong> <code>(get-jar-classnames jar-file-name &rest packages) 
+			-> list-of-strings</code>
+			<p>
+			Returns a list of class name strings. Packages should be strings of the form "java/lang 
+			 " for recursive lookup and "java/util/" (note trailing slash) for non-recursive.
+			</p>
+		</li>
+		<li>
+			<strong>Function</strong> <code>(dump-wrapper-defs-to-file filename classnames)  -> 
+			unspecified</code>
+			<p>
+			Given a list of classnames (say from <code>get-jar-classnames</code>), writes 
+			calls to <code>def-java-class</code> to a file:
+			</p>
+			<pre>
+(dump-wrapper-defs-to-file "/lisp/java-lang.lisp"
+  (get-jar-classnames "/j2sdk1.4.2_01/jre/lib/rt.jar " "java/lang/"))
+(compile-file "/lisp/java-lang")
+(load "/lisp/java-lang")
+(use-package "java.lang")
+;Wrappers for all of java.lang are now available
+</pre>
+		</li>
+	</ul>
+
+	<a name="objects"></a> <h3>Object Creation</h3>
+	<ul>
+		<li>
+			<strong><a name="makenew"></a>Generic Function</strong> <code>(make-new class-symbol 
+			&rest args) -> typed-reference</code>
+			<p>
+			Allows for definition of before/after methods on constructors. Calls <code>classname.new</code>. 
+			The new macro expands into a call to this.
+			</p>
+		</li>
+		<li>
+			<strong>Macro</strong> <code>(new class-spec &rest args) -> typed-reference</code>
+			<br>
+			<p>
+			class-spec -> class-name | (class-name this-name)<br>
+			class-name -> "package.qualified.ClassName" | classname.<br>
+			args -> [actual-arg]* [init-arg-spec]*<br>
+			init-arg-spec -> init-arg | (init-arg)<br>
+			init-arg -> :settable-field-or-method [params]* value (note keyword)<br>
+			| .method-name [args]* (note leading dot)<br>
+			</p>
+
+			<p>
+			Creates a new instance of class-name, by expanding into a call to the make-new 
+			generic function, then initializes it by setting fields or accessors and/or 
+			calling member functions. If this-name is supplied, it will be bound to the 
+			newly-allocated object and available to the init-args:
+			</p>
+			<pre>
+(new (button. this) shell *SWT.CENTER*   ;the actual args
+       :gettext "Call Lisp"               ;a javabean property
+       (.addlistener *swt.selection*      ;a method call
+         (new-proxy (listener.
+                     (handleevent (event)
+                       (declare (ignore event))
+                       (setf (button.gettext this)   ;this is bound to new instance
+                             (format nil "~A ~A"
+                                   (lisp-implementation-type)
+                                   (lisp-implementation-version)))
+                       nil))))
+      .setsize 200 100                    ;can omit parens
+      (.setlocation 40 40))
+			</pre>
+			Expands into:
+			<pre>
+(LET* ((#:G598 (MAKE-NEW BUTTON. SHELL *SWT.CENTER*)) (THIS #:G598))
+  (SETF (BUTTON.GETTEXT #:G598) "Call Lisp")
+  (BUTTON.ADDLISTENER #:G598
+                      *SWT.SELECTION*
+                      (NEW-PROXY (LISTENER.
+                                  (HANDLEEVENT
+                                   (EVENT)
+                                   (DECLARE (IGNORE EVENT))
+                                   (SETF (BUTTON.GETTEXT THIS)
+                                         (FORMAT NIL
+                                                 "~A ~A"
+                                                 (LISP-IMPLEMENTATION-TYPE)
+                                                 (LISP-IMPLEMENTATION-VERSION)))
+                                   NIL))))
+  (BUTTON.SETSIZE #:G598 200 100)
+  (BUTTON.SETLOCATION #:G598 40 40)
+  #:G598)
+			</pre>
+
+		</li>
+	</ul>
+	<a name="arrays"></a> <h3>Array Support</h3>
+	<ul>
+		<li>
+			<strong>Generic Function</strong> <code>(make-new-array type &rest dimensions) -> 
+			reference to new array</code>
+			<p>
+			Generic function with methods defined for all Java class designators:
+			<ul>
+				<li>
+					A "package.qualified.ClassName" string
+				</li>
+				<li>
+					(the value of) A class-symbol - classname.
+				</li>
+				<li>
+					A primitive designator keyword - :boolean|:byte|:char|:double|:float|:int|:long|:short
+				</li>
+			</ul>
+			</p>
+			<p>
+			Creates a Java array of the requested type with the requested dimensions.
+			</p>
+		</li>
+		<li>
+			<strong>Function</strong> <code>(jlength array) -> integer</code>
+			<p>
+			Like length, for Java arrays
+			</p>
+		</li>
+
+		<li>
+			<strong>Function</strong> <code>(jref array &rest subscripts) -> reference</code>
+			<p>
+			Like aref, for Java arrays of non-primitive (reference) types, settable.
+			</p>
+		</li>
+		<li>
+			<strong>Function</strong> <code>(jref-xxx array &rest subscripts) -> value</code>
+			<p>
+			Where xxx = boolean|byte|char|double|float|int|long|short. Like jref, for Java 
+			arrays of primitive types, settable.
+			</p>
+		</li>
+
+	</ul>
+
+	<a name="proxies"></a> <h3>Proxies - Java calling back to Lisp</h3>
+	<ul>
+		<p>
+		Proxies allow the creation of Java objects that implement one or more interfaces 
+		in Lisp, and thus callbacks from Java to Lisp. You must call <a href=#enableproxies>
+		<code>enable-java-proxies</code></a> before using this proxy API. A significant 
+		limitation is that LispWorks appears to not support calls back into Lisp other 
+		than from threads initiated by Lisp, so you must ensure that the proxy will not 
+		be called from an arbitrary Java thread!
+		</p>
+		<li>
+			<strong>Macro</strong> <code>(new-proxy &rest interface-defs) -> reference</code>
+			<p>
+			interface-def -> (interface-name method-defs+)<br>
+			interface-name -> "package.qualified.ClassName" | classname. (must name a Java 
+			interface type)<br>
+			method-def -> (method-name arg-defs* body) <br>
+			arg-def -> arg-name | (arg-name arg-type) arg-type -> "package.qualified.ClassName 
+			 " | classname. | :primitive <br>
+			method-name -> symbol | string (matched case-insensitively)
+			</p>
+
+			<p>
+			Creates, registers and returns a Java object that implements the supplied 
+			interfaces
+			</p>
+		</li>
+		<li>
+			<strong>Function</strong> <code>(unregister-proxy proxy) -> unspecified</code>
+			<p>
+			Stops handling for the proxy (which must have been created by <code>new-proxy</code>) 
+			and removes references from the Lisp side. Make sure it is no longer referenced 
+			from Java first!
+			</p>
+		</li>
+	</ul>
+
+	<a name="utilities"></a> <h3>Utilities</h3>
+	<ul>
+
+		<li>
+			<strong>Function</strong> <code>(jeq obj1 obj2) -> boolean</code>
+			<p>
+			Are the 2 java objects the same object? Note that this is not the same as Object.equals()
+			<p>
+		</li>
+		<li>
+			<strong>Function</strong> <code>(find-java-class class-sym-or-string) -> 
+			reference to Java Class object</code>
+			<p>
+			Given a Java class designator, returns the Java Class object. Use this in 
+			preference to Class.forName() when using jfli.
+			</p>
+		</li>
+
+		<li>
+			<strong>Function</strong> <code>(make-typed-ref java-ref) -> typed-reference</code>
+			<p>
+			Given a generic Java reference, determines the full type of the object and 
+			returns an instance of a typed reference wrapper. classname.new/make-new/new always return typed 
+			references, but since Java methods might return Object or some interface type, 
+			and we don't want to always incur the cost of type determination, field and 
+			method wrapper functions return generic references. Use this function to create 
+			a typed reference corresponding to the full actual type of the object when 
+			desired.
+			</p>
+		 </li>
+		<li>
+			<strong>Function</strong> <code>(box-xxx value) -> reference to Java primitive wrapper class</code>
+			<p>Where xxx = boolean|byte|char|double|float|int|long|short|string. 
+			Given a compatible Lisp value, creates an instance of the corresponding Java primitive wrapper class,
+			e.g. Integer. This should rarely be needed, but can be used to force overloading resolution</p>
+		</li>
+		<li>
+			<strong>Function</strong> <code>(unbox-xxx ref) -> Lisp value</code>
+			<p>Where xxx = boolean|byte|char|double|float|int|long|short|string. 
+			Given an instance of a Java primitive wrapper class, creates an instance of the corresponding 
+			compatible Lisp value. This should rarely be needed, but can be used to unbox values returned by Java
+			Object-based APIs.</p>
+		</li>
+ 	</ul>
+	
+	<a name="summary"></a> <h3>Summary</h3>
+<p>
+I hope you find jfli useful. It is my sincere intent that it enhance the utility and interoperability of Common Lisp,
+a language with which I am still becoming familiar, and grow to appreciate more every day. I welcome comments
+and code contributions.
+</p>
+<p>
+Rich Hickey, July 2004
+</p>
+	</body>
+</html>
Index: /branches/new-random/examples/jfli/examples/session.lisp
===================================================================
--- /branches/new-random/examples/jfli/examples/session.lisp	(revision 13309)
+++ /branches/new-random/examples/jfli/examples/session.lisp	(revision 13309)
@@ -0,0 +1,104 @@
+;this presumes you have already compiled jni.lisp and jfli.lisp into fasl files
+
+CL-USER 4 > (load "/lisp/jni")
+; Loading fasl file C:\lisp\jni.fsl
+#P"C:/lisp/jni.fsl"
+
+CL-USER 5 > (load "/lisp/jfli")
+; Loading fasl file C:\lisp\jfli.fsl
+#P"C:/lisp/jfli.fsl"
+
+;The user API is entirely in the jfli package
+CL-USER 6 > (use-package :jfli)
+T
+
+;tell the library where Java is located
+CL-USER 7 > (setf *jni-lib-path* "/j2sdk1.4.2_01/jre/bin/client/jvm.dll")
+"/j2sdk1.4.2_01/jre/bin/client/jvm.dll"
+
+;this starts the VM - note how you can set the classpath
+CL-USER 8 > (create-jvm "-Djava.class.path=/lisp/jfli.jar")
+0
+#<Pointer: JNI:PVM = #x081022A0>
+#<Pointer: JNI:PENV = #x0086A858>
+
+;define wrappers for the members of Object
+CL-USER 9 > (def-java-class "java.lang.Object")
+NIL
+
+;and of Properties, a Hashtable-like class
+CL-USER 10 > (def-java-class "java.util.Properties")
+#<STANDARD-CLASS |java.util|:PROPERTIES. 2066B964>
+
+;the above will create these packages if they do not already exist
+;use the packages for easy name access
+
+CL-USER 11 > (use-package "java.lang")
+T
+
+CL-USER 12 > (use-package "java.util")
+T
+
+;create a Properties instance, note keyword-style member inits, string conversion etc
+;also note typed return value
+CL-USER 13 > (setf p (new properties. :getproperty "fred" "ethel"))
+#<PROPERTIES. 20664A94>
+
+;virtual functions work as normal
+CL-USER 14 > (object.tostring p)
+"{fred=ethel}"
+
+;setter was generated for member function because it follows the JavaBeans property protocol
+CL-USER 15 > (setf (properties.getproperty p "ricky") "lucy")
+"lucy"
+
+CL-USER 16 > (object.tostring p)
+"{ricky=lucy, fred=ethel}"
+
+CL-USER 17 > (properties.size p)
+2
+
+;totally dynamic access, create wrappers as you need
+CL-USER 18 > (def-java-class "java.lang.Class")
+#<STANDARD-CLASS CLASS. 20680EC4>
+
+CL-USER 19 > (class.getname (object.getclass p))
+"java.util.Properties"
+
+CL-USER 20 > (def-java-class "java.util.Enumeration")
+#<STANDARD-CLASS ENUMERATION. 20669274>
+
+;no need to wait for the vendor to enhance the language - you use Lisp!
+CL-USER 21 > (defmacro doenum ((e enum) &body body)
+  (let ((genum (gensym)))
+    `(let ((,genum ,enum))
+       (do ()
+           ((not (enumeration.hasmoreelements ,genum)))
+         (let ((,e (enumeration.nextelement ,genum)))
+           ,@body)))))(defmacro doenum ((e enum) &body body)
+               (let ((genum (gensym)))
+                 `(let ((,genum ,enum))
+                    (do ()
+                        ((not (enumeration.hasmoreelements ,genum)))
+                      (let ((,e (enumeration.nextelement ,genum)))
+                        ,@body)))))
+DOENUM
+
+;can't do this in Java yet can in Lisp
+CL-USER 22 > (doenum (prop (properties.elements p)) (print (object.tostring prop)))
+
+"lucy" 
+"ethel" 
+NIL
+
+;doc strings are created giving original Java signatures and indicating overloads
+CL-USER 23 > (documentation 'properties.getproperty 'function)
+"java.lang.String getProperty(java.lang.String,java.lang.String)
+java.lang.String getProperty(java.lang.String)
+"
+
+CL-USER 24 > (documentation 'properties.new 'function)
+"java.util.Properties()
+java.util.Properties(java.util.Properties)
+"
+
Index: /branches/new-random/examples/jfli/examples/swtdemo.lisp
===================================================================
--- /branches/new-random/examples/jfli/examples/swtdemo.lisp	(revision 13309)
+++ /branches/new-random/examples/jfli/examples/swtdemo.lisp	(revision 13309)
@@ -0,0 +1,51 @@
+;Just load this from LispWorks menu
+;note works on Windows, some issues on OS X due to windowing conflict w/IDE
+(load "ccl:examples;jfli;jni")
+(load "ccl:examples;jfli;jfli")
+(use-package :jfli)
+(create-jvm
+ "-Djava.class.path=/cygwin/home/gb/swt/swt.jar;/;/cygwin/usr/local/src/ccl-dev/examples/jfli/jfli.jar"
+ )
+(enable-java-proxies)
+
+
+
+(def-java-class "org.eclipse.swt.widgets.Display")
+(def-java-class "org.eclipse.swt.widgets.Button")
+(def-java-class "org.eclipse.swt.widgets.Shell")
+(def-java-class "org.eclipse.swt.widgets.Listener")
+(def-java-class "org.eclipse.swt.SWT")
+
+(use-package "org.eclipse.swt")
+(use-package "org.eclipse.swt.widgets")
+
+
+(defun swt-demo ()
+  (let* ((display (new display.))
+         (shell (new shell. display
+                     :gettext "Using SWT from Lisp"
+                     (.setsize 300 200)
+                     (.setlocation 100 100)))
+         (button (new (button. this) shell *SWT.CENTER*
+                      :gettext "Call Lisp"
+                      (.addlistener *swt.selection*
+                       (new-proxy (listener.
+                                   (handleevent (event)
+                                     (declare (ignore event))
+                                     (setf (button.gettext this)
+                                           (format nil "~A ~A"
+                                                   (lisp-implementation-type)
+                                                   (lisp-implementation-version)))
+                                     nil))))
+                      (.setsize 200 100)
+                      (.setlocation 40 40))))
+    (declare (ignore button))
+    (shell.open shell)
+    (do ()
+        ((shell.isdisposed shell))
+      (unless (display.readanddispatch display)
+        (display.sleep display)))
+    (display.dispose display)))
+
+(mp:process-run-function "swt-proc" '() #'swt-demo)
+
Index: /branches/new-random/examples/jfli/jfli-lw.lisp
===================================================================
--- /branches/new-random/examples/jfli/jfli-lw.lisp	(revision 13309)
+++ /branches/new-random/examples/jfli/jfli-lw.lisp	(revision 13309)
@@ -0,0 +1,1390 @@
+;    Copyright (c) Rich Hickey. All rights reserved.
+;    The use and distribution terms for this software are covered by the
+;    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+;    which can be found in the file CPL.TXT at the root of this distribution.
+;    By using this software in any fashion, you are agreeing to be bound by
+;    the terms of this license.
+;    You must not remove this notice, or any other, from this software.
+
+#|
+
+jfli is a library that provides access to Java from Lisp
+It depends on the jni package (included)
+Callbacks from Java to Lisp also require jfli.jar (included)
+
+|#
+
+(defpackage :jfli
+  (:use :common-lisp :lispworks :jni)
+  (:export
+
+   ;jvm creation
+   :*jni-lib-path*  ;exposed from jni
+   :create-jvm      ;exposed from jni, you must call this prior to calling any other jfli function
+   :enable-java-proxies
+
+   ;wrapper generation
+   :def-java-class
+   :get-jar-classnames
+   :dump-wrapper-defs-to-file
+
+   ;object creation etc
+   :find-java-class
+   :new
+   :make-new
+   :make-typed-ref
+   :jeq
+
+   ;array support
+   :make-new-array
+   :jlength
+   :jref
+   :jref-boolean
+   :jref-byte
+   :jref-char
+   :jref-double
+   :jref-float
+   :jref-int
+   :jref-short
+   :jref-long
+
+   ;proxy support
+   :new-proxy
+   :unregister-proxy
+
+   ;conversions
+   :box-boolean
+   :box-byte
+   :box-char
+   :box-double
+   :box-float
+   :box-integer
+   :box-long
+   :box-short
+   :box-string
+   :unbox-boolean
+   :unbox-byte
+   :unbox-char
+   :unbox-double
+   :unbox-float
+   :unbox-integer
+   :unbox-long
+   :unbox-short
+   :unbox-string
+
+;   :ensure-package
+;   :member-symbol
+;   :class-symbol
+;   :constructor-symbol
+   ))
+
+(in-package :jfli)
+
+#|
+bootstrap the implementation of reflection wrappers with 
+a few (primitive, less safe and maybe faster) jni wrappers
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (def-jni-functions "java.lang.Object"
+                     ("getClass" () "Class")
+                     ("hashCode" () "int")
+                     ("toString" () "String")
+                     ("equals" ((obj "Object")) "boolean"))
+
+  (def-jni-functions "java.lang.Class"
+                   ;should be :overloaded t, but we only use this version
+                     ("forName" ((className "String")) "Class"  :static t)
+                     ("getConstructors" () "java.lang.reflect.Constructor<>")
+                     ("getFields" () "java.lang.reflect.Field<>")
+                     ("getMethods" () "java.lang.reflect.Method<>")
+
+                     ("getConstructor" ((parameter-types "Class<>")) "java.lang.reflect.Constructor")
+                     ("getField" ((name "String"))
+                                 "java.lang.reflect.Field")
+                     ("getMethod" ((name "String") (parameter-types "Class<>"))
+                                  "java.lang.reflect.Method")
+
+                     ("getSuperclass" () "Class")
+                     ("getInterfaces" () "Class<>")
+
+                     ("getName" () "String")
+                     ("isArray" () "boolean")
+                     ("isPrimitive" () "boolean"))
+
+  (def-jni-functions "java.lang.reflect.Field"
+                     ("getName" () "java.lang.String")
+                     ("getType" () "java.lang.Class")
+                     ("getModifiers" () "int")
+
+                     ("get" ((obj "java.lang.Object")) "java.lang.Object" :raw-return t)
+                     ("getBoolean" ((obj "java.lang.Object")) "boolean")
+                     ("getByte" ((obj "java.lang.Object")) "byte")
+                     ("getChar" ((obj "java.lang.Object")) "char")
+                     ("getDouble" ((obj "java.lang.Object")) "double")
+                     ("getFloat" ((obj "java.lang.Object")) "float")
+                     ("getInt" ((obj "java.lang.Object")) "int")
+                     ("getLong" ((obj "java.lang.Object")) "long")
+                     ("getShort" ((obj "java.lang.Object")) "short")
+
+                     ("set" ((obj "java.lang.Object") (value "java.lang.Object")) "void")
+                     ("setBoolean" ((obj "java.lang.Object") (b "boolean")) "void")
+                     ("setByte" ((obj "java.lang.Object") (b "byte")) "void")
+                     ("setChar" ((obj "java.lang.Object") (c "char")) "void")
+                     ("setDouble" ((obj "java.lang.Object") (d "double")) "void")
+                     ("setFloat" ((obj "java.lang.Object") (f "float")) "void")
+                     ("setInt" ((obj "java.lang.Object") ( i "int")) "void")
+                     ("setLong" ((obj "java.lang.Object") (l "long")) "void")
+                     ("setShort" ((obj "java.lang.Object") (s "short")) "void"))
+
+  (def-jni-functions "java.lang.reflect.Constructor"
+                     ("getParameterTypes" () "java.lang.Class<>")
+                     ("newInstance" ((initargs "java.lang.Object<>")) "java.lang.Object"))
+
+  (def-jni-functions "java.lang.reflect.Method"
+                     ("getName" () "java.lang.String")
+                     ("getParameterTypes" () "java.lang.Class<>")
+                     ("getReturnType" () "java.lang.Class")
+                     ("getModifiers" () "int")
+                     ("invoke" ((object "java.lang.Object")
+                                (args "java.lang.Object<>")) "java.lang.Object"
+                               :raw-return t))
+
+  (def-jni-functions "java.lang.reflect.Array"
+                     ("get" ((array "java.lang.Object") (index "int")) "java.lang.Object" :static t)
+                     ("getBoolean"
+                      ((array "java.lang.Object") (index "int")) "boolean" :static t)
+                     ("getByte"
+                      ((array "java.lang.Object") (index "int")) "byte" :static t)
+                     ("getChar"
+                      ((array "java.lang.Object") (index "int")) "char" :static t)
+                     ("getDouble"
+                      ((array "java.lang.Object") (index "int")) "double" :static t)
+                     ("getFloat"
+                      ((array "java.lang.Object") (index "int")) "float" :static t)
+                     ("getInt"
+                      ((array "java.lang.Object") (index "int")) "int" :static t)
+                     ("getShort"
+                      ((array "java.lang.Object") (index "int")) "short" :static t)
+                     ("getLong"
+                      ((array "java.lang.Object") (index "int")) "long" :static t)
+                     ("getLength" ((array "java.lang.Object")) "int" :static t)
+                     ("newInstance" ((componentType "java.lang.Class")
+                                     (length "int")) "java.lang.Object" :static t :overloaded t)
+                     ("newInstance" ((componentType "java.lang.Class")
+                                     (dimensions "int<>")) "java.lang.Object" :static t :overloaded t)
+                     ("set" ((array "java.lang.Object") (index "int") (value "java.lang.Object"))
+                            "void" :static t))
+
+
+  (def-jni-function "java.lang.reflect.Modifier"
+                    "isStatic" ((mod "int")) "boolean" :static t)
+
+  (def-jni-constructor "java.lang.Boolean" ((value "boolean")))
+  (def-jni-constructor "java.lang.Byte" ((value "byte")))
+  (def-jni-constructor "java.lang.Character" ((value "char")))
+  (def-jni-constructor "java.lang.Double" ((value "double")))
+  (def-jni-constructor "java.lang.Float" ((value "float")))
+  (def-jni-constructor "java.lang.Integer" ((value "int")))
+  (def-jni-constructor "java.lang.Short" ((value "short")))
+
+  (def-jni-function "java.lang.Boolean" "booleanValue" () "boolean")
+  (def-jni-function "java.lang.Byte" "byteValue" () "byte")
+  (def-jni-function "java.lang.Character" "charValue" () "char")
+  (def-jni-function "java.lang.Double" "doubleValue" () "double")
+  (def-jni-function "java.lang.Float" "floatValue" () "float")
+  (def-jni-function "java.lang.Integer" "intValue" () "int")
+  (def-jni-function "java.lang.Short" "shortValue" () "short")
+
+  (def-jni-constructor "java.util.jar.JarFile" ((filename "java.lang.String")))
+  (def-jni-function "java.util.jar.JarFile"
+                    "entries" () "java.util.Enumeration")
+  (def-jni-functions "java.util.Enumeration"
+                     ("hasMoreElements" () "boolean")
+                     ("nextElement" () "java.lang.Object"))
+  (def-jni-functions "java.util.zip.ZipEntry"
+                     ("isDirectory" () "boolean")
+                     ("getName" () "java.lang.String"))
+
+
+  (def-jni-functions "java.lang.Long"
+                     ("valueOf" ((s "String")) "java.lang.Long" :static t)
+                     ("intValue" () "int"))
+
+  (def-jni-field "java.lang.Boolean" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Byte" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Character" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Float" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Integer" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Double" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Short" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Long" "TYPE" "Class" :static t)
+
+  (def-jni-constructor "com.richhickey.jfli.LispInvocationHandler" ())
+  (def-jni-function "java.lang.reflect.Proxy"
+                    "newProxyInstance" ((loader "java.lang.ClassLoader")
+                                        (interfaces "java.lang.Class<>")
+                                        (h "InvocationHandler")) "java.lang.Object" :static t)
+
+  (def-jni-function "java.lang.ClassLoader"
+                    "getSystemClassLoader" () "ClassLoader" :static t)
+
+  ) ;eval-when
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;; utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when (:compile-toplevel :load-toplevel)
+  (defun ensure-package (name)
+    "find the package or create it if it doesn't exist"
+    (or (find-package name)
+        (make-package name :use '())))
+  (intern "Object" (ensure-package "java.lang"))
+  (intern "String" (ensure-package "java.lang")))
+
+(defmacro do-jarray ((x array) &body body)
+  "jni-based, so not safe and not exported, but used by the implementation"
+  (let ((gcount (gensym))
+        (gi (gensym))
+        (garray (gensym)))
+    `(let* ((,garray ,array)
+            (,gcount (jni:get-array-length ,garray)))
+       (dotimes (,gi ,gcount)
+         (let ((,x (jaref ,garray ,gi)))
+           ,@body)))))
+
+
+(defmacro doenum ((e enum) &body body)
+  "jni-based, so not safe and not exported, but used by the implementation"
+  (let ((genum (gensym)))
+    `(let ((,genum ,enum))
+       (do ()
+           ((not (enumeration.hasmoreelements ,genum)))
+         (let ((,e (enumeration.nextelement ,genum)))
+           ,@body)))))
+
+;probably insufficiently general, works as used here
+(defmacro get-or-init (place init-form)
+  `(or ,place
+       (setf ,place ,init-form)))
+
+;from c.l.l.
+(defmacro case-equal (exp &body clauses)
+  (let ((temp (gensym)))
+    `(let ((,temp ,exp))
+       (cond ,@(mapcar #'(lambda (clause)
+                           (destructuring-bind (keys . clause-forms) clause
+                             (cond ((eq keys 'otherwise)
+                                    `(t ,@clause-forms))
+                                   (t
+                                    (if (atom keys) (setq keys (list keys)))
+                                    `((member ,temp ',keys :test #'equal)
+                                      ,@clause-forms)))))
+                       clauses)))))
+
+;create object. to bootstrap the hierarchy
+(defclass |java.lang|::object. ()
+  ((ref :reader ref :initarg :ref)
+   (lisp-allocated :reader lisp-allocated-p :initarg :lisp-allocated :initform nil))
+  (:documentation "the superclass of all Java typed reference classes"))
+
+(defun get-ref (x)
+  "any function taking an object can be passed a raw java-ref ptr or a typed reference instance.
+Will also convert strings for use as objects"
+  (etypecase x
+    (java-ref x)
+    (|java.lang|::object. (ref x))
+    (string (convert-to-java-string x))
+    (null nil)))
+
+(defun jeq (obj1 obj2)
+  "are these 2 java objects the same object? Note that is not the same as Object.equals()"
+  (is-same-object (get-ref obj1) (get-ref obj2)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;; names and symbols ;;;;;;;;;;;;;;;;;;;;;;;
+#|
+The library does a lot with names and symbols, needing at various times to:
+ - find stuff in Java - full names w/case required
+ - create hopefully non-conflicting packages and member names
+
+When you (def-java-class "java.lang.String") you get a bunch of symbols/names:
+a package named '|java.lang|
+a class-symbol '|java.lang|:STRING. (note the dot and case), 
+   which can usually be used where a typename is required
+   it also serves as the name of the Lisp typed reference class for string
+   its symbol-value is the canonic-class-symbol (see below)
+a canonic-class-symbol '|java.lang|::|String|
+   can be used to reconstitute the full class name
+
+I've started trying to flesh out the notion of a Java class designator, which can either be
+the full class name as a string, the class-symbol, or one of :boolean, :int etc
+|#
+
+(defun canonic-class-symbol (full-class-name)
+  "(\"java.lang.Object\") -> '|java.lang|:|Object|"
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (intern class (ensure-package package))))
+
+(defun class-symbol (full-class-name)
+  "(\"java.lang.Object\") -> '|java.lang|:object."
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (intern (string-upcase (string-append class ".")) (ensure-package package))))
+
+(defun java-class-name (class-sym)
+  "inverse of class-symbol, only valid on class-syms created by def-java-class"
+  (let ((canonic-class-symbol (symbol-value class-sym)))
+    (string-append (package-name (symbol-package canonic-class-symbol))
+                                                "."
+                                                canonic-class-symbol)))
+
+(defun member-symbol (full-class-name member-name)
+  "members are defined case-insensitively in case-sensitive packages,
+prefixed by 'classname.' -
+(member-symbol \"java.lang.Object\" \"toString\") -> '|java.lang|::OBJECT.TOSTRING"
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (intern (string-upcase (string-append class "." member-name)) (ensure-package package))))
+
+(defun constructor-symbol (full-class-name)
+  (member-symbol full-class-name "new"))
+
+(defun get-java-class-ref (canonic-class-symbol)
+  "class-ref is cached on the plist of the canonic class symbol"
+  (get-or-init (get canonic-class-symbol :class-ref)
+               (let ((class-name (string-append (package-name
+                                                 (symbol-package canonic-class-symbol))
+                                                "."
+                                                canonic-class-symbol)))
+                 (try-null (jni-find-class (nsubstitute #\/ #\. class-name))))))
+
+(defun find-java-class (class-sym-or-string)
+  "Given a Java class designator, returns the Java Class object."
+  (ctypecase class-sym-or-string
+    (symbol (case class-sym-or-string
+              (:int integer.type)
+              (:char character.type)
+              (:long long.type)
+              (:float float.type)
+              (:boolean boolean.type)
+              (:short short.type)
+              (:double double.type)
+              (:byte byte.type)
+              (otherwise (get-java-class-ref class-sym-or-string))))
+    (string (get-java-class-ref (canonic-class-symbol class-sym-or-string)))))
+
+;;;;;;;;;;;;;;;;;;;;;; typed reference support ;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+The library maintains a hierarchy of typed reference classes that parallel the
+class hierarchy on the Java side
+new returns a typed reference, but other functions that return objects
+return raw references (for efficiency) 
+make-typed-ref can create fully-typed wrappers when desired
+|#
+
+(defun get-superclass-names (full-class-name)
+  (let* ((class (get-java-class-ref (canonic-class-symbol full-class-name)))
+         (super (class.getsuperclass class))
+         (interfaces (class.getinterfaces class))
+         (supers ()))
+    (do-jarray (i interfaces)
+      (push i supers))
+    ;hmmm - where should the base class go in the precedence list?
+    ;is it more important than the interfaces? this says no
+    (if super
+        (push super supers)
+      (push (find-java-class "java.lang.Object") supers))
+    (setf supers (nreverse supers))
+    ;now we need to fix up order so more derived classes are first
+    ;but don't have a total ordering, so merge one at a time
+    (let (result)
+      (dolist (s supers)
+        (setf result (merge 'list result (list s)
+                            (lambda (x y)
+                              (is-assignable-from x y)))))
+      (mapcar #'class.getname result))))
+#|
+(defun get-superclass-names (full-class-name)
+  (let* ((class (get-java-class-ref (canonic-class-symbol full-class-name)))
+         (super (class.getsuperclass class))
+         (interfaces (class.getinterfaces class))
+         (supers ()))
+    (do-jarray (i interfaces)
+      (push (class.getname i) supers))
+    ;hmmm - where should the base class go in the precedence list?
+    ;is it more important than the interfaces? this says no
+    (if super
+        (push (class.getname super) supers)
+      (push "java.lang.Object" supers))
+    (nreverse supers)))
+|#
+
+(defun ensure-java-class (full-class-name)
+  "walks the superclass hierarchy and makes sure all the classes are fully defined
+(they may be undefined or just forward-referenced-class)
+caches this has been done on the class-symbol's plist"
+  (let* ((class-sym (class-symbol full-class-name))
+         (class (find-class class-sym nil)))
+    (if (or (eql class-sym '|java.lang|::object.)
+            (get class-sym :ensured))
+        class
+      (let ((supers (get-superclass-names full-class-name)))
+        (dolist (super supers)
+          (ensure-java-class super))
+        (unless (and class (subtypep class 'standard-object))
+          (setf class
+                (clos:ensure-class class-sym :direct-superclasses (mapcar #'class-symbol supers))))
+        (setf (get class-sym :ensured) t)
+        class))))
+
+(defun ensure-java-hierarchy (class-sym)
+  "Works off class-sym for efficient use in new
+This will only work on class-syms created by def-java-class,
+as it depends upon symbol-value being the canonic class symbol"
+  (unless (get class-sym :ensured)
+    (ensure-java-class (java-class-name class-sym))))
+
+(defun make-typed-ref (java-ref)
+  "Given a raw java-ref, determines the full type of the object
+and returns an instance of a typed reference wrapper"
+  (when java-ref
+    (let ((class (object.getclass (get-ref java-ref))))
+      (if (class.isarray class)
+          (error "typed refs not supported for arrays (yet)")
+        (make-instance (ensure-java-class (class.getname class)) :ref (get-ref java-ref) )))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;; Wrapper Generation ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+In an effort to reduce the volume of stuff generated when wrapping entire libraries,
+the wrappers just generate minimal stubs, which, if and when invoked at runtime,
+complete the work of building thunking closures, so very little code is generated for
+things never called (Java libraries have huge numbers of symbols).
+Not sure if this approach matters, but that's how it works
+|#
+
+(defmacro def-java-class (full-class-name)
+  "Given the package-qualified, case-correct name of a java class, will generate
+wrapper functions for its constructors, fields and methods."
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (declare (ignore class))
+    (let* ((class-sym (class-symbol full-class-name))
+           (defs
+            (list*
+             `(ensure-package ,package)
+          ;build a path from the simple class symbol to the canonic
+             `(defconstant ,class-sym ',(canonic-class-symbol full-class-name))
+             `(export ',class-sym (symbol-package ',class-sym))
+             `(def-java-constructors ,full-class-name)
+             `(def-java-methods ,full-class-name)
+             `(def-java-fields ,full-class-name)
+             (unless (string= full-class-name "java.lang.Object")
+               (let ((supers (mapcar #'class-symbol (get-superclass-names full-class-name))))
+                 (append (mapcar (lambda (p)
+                                   `(ensure-package ,(package-name p)))
+                                 (remove (symbol-package class-sym)
+                                         (remove-duplicates (mapcar #'symbol-package supers))))
+                         (list `(defclass ,(class-symbol full-class-name)
+                                          ,supers ()))))))))
+      `(locally ,@defs))))
+
+(defun get-jar-classnames (jar-file-name &rest packages)
+  "returns a list of strings, packages should be of the form \"java/lang\"
+  for recursive lookup and \"java/util/\" for non-recursive"
+  (let* ((jar (jarfile.new jar-file-name))
+         (entries (jarfile.entries jar))
+         (names ()))
+    (doenum (e entries)
+      (unless (zipentry.isdirectory e)
+        (let ((ename (zipentry.getname e)))
+          (flet ((matches (package)
+                   (and (eql 0 (search package ename))
+                        (or (not (eql #\/ (schar package (1- (length package))))) ;recursive
+                            (not (find #\/ ename :start (length package))))))) ;non-subdirectory
+            (when (and (eql (search ".class" ename)
+                            (- (length ename) 6)) ;classname
+                       ;don't grab anonymous inner classes
+                       (not (and (find #\$ ename)
+                                 (digit-char-p (schar ename (1+ (position #\$ ename))))))
+                       (some #'matches packages))
+              (push (nsubstitute #\. #\/ (subseq ename 0 (- (length ename) 6)))
+                    names))))))
+    names))
+
+(defun dump-wrapper-defs-to-file (filename classnames)
+  "given a list of classnames (say from get-jar-classnames), writes
+calls to def-java-class to a file"
+  (with-open-file (s filename :direction :output :if-exists :supersede)
+    (dolist (name (sort classnames #'string-lessp))
+      (format s "(def-java-class ~S)~%" name))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;; constructors and new ;;;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+
+Every non-interface class with a public ctor will get;
+  a constructor, classname.new
+  a method defined on make-new, ultimately calling classname.new,
+   specialized on (the value of) it's class-symbol (e.g. canonic sym)
+
+Note that if the ctor is overloaded, there is just one function (taking a rest arg), 
+which handles overload resolution
+
+The new macro expands into a call to make-new
+|#
+
+(defgeneric make-new (class-sym &rest args)
+  (:documentation "Allows for definition of before/after methods on ctors.
+The new macro expands into call to this"))
+
+(defun build-ctor-doc-string (name ctors)
+  (with-output-to-string (s)
+    (dolist (c ctors)
+      (format s "~A(~{~#[~;~A~:;~A,~]~})~%"
+              name
+              (mapcar #'class-name-for-doc (jarray-to-list (constructor.getparametertypes c)))))))
+
+(defmacro def-java-constructors (full-class-name)
+"creates and exports a ctor func classname.new, defines a method of 
+make-new specialized on the class-symbol"
+  (let ((ctor-list (get-ctor-list full-class-name)))
+    (when ctor-list
+      (let ((ctor-sym (constructor-symbol full-class-name))
+            (class-sym (class-symbol full-class-name)))
+        `(locally
+           (defun ,ctor-sym (&rest args)
+             ,(build-ctor-doc-string full-class-name ctor-list)
+             (apply #'install-constructors-and-call ,full-class-name args))
+           (export ',ctor-sym (symbol-package ',ctor-sym))
+           (defmethod make-new ((class-sym (eql ,class-sym)) &rest args)
+             (apply (function ,ctor-sym) args)))))))
+
+(defun get-ctor-list (full-class-name)
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (ctor-array (class.getconstructors class))
+         (ctor-list (jarray-to-list ctor-array)))
+    ctor-list))
+
+(defun install-constructors-and-call (full-class-name &rest args)
+  "initially the constructor symbol for a class is bound to this function,
+when first called it will replace itself with the appropriate direct thunk,
+then call the requested ctor - subsequent calls will be direct"
+  (install-constructors full-class-name)
+  (apply (constructor-symbol full-class-name) args))
+
+(defun install-constructors (full-class-name)
+  (let* ((ctor-list (get-ctor-list full-class-name)))
+    (when ctor-list
+      (setf (fdefinition (constructor-symbol full-class-name))
+            (make-ctor-thunk ctor-list (class-symbol full-class-name))))))
+
+(defun make-ctor-thunk (ctors class-sym)
+  (if (rest ctors) ;overloaded
+      (make-overloaded-ctor-thunk ctors class-sym)
+    (make-non-overloaded-ctor-thunk (first ctors) class-sym)))
+
+(defun make-non-overloaded-ctor-thunk (ctor class-sym)
+  (let ((arg-boxers (get-arg-boxers (constructor.getparametertypes ctor))))
+    (lambda (&rest args)
+      (let ((arg-array (build-arg-array args arg-boxers)))
+        (ensure-java-hierarchy class-sym)
+        (prog1
+            (make-instance class-sym
+                           :ref (constructor.newinstance ctor arg-array)
+                           :lisp-allocated t)
+            ;(constructor.newinstance ctor arg-array)
+          (when arg-array
+            (delete-local-ref arg-array)))))))
+
+(defun make-overloaded-ctor-thunk (ctors class-sym)
+  (let ((thunks (make-ctor-thunks-by-args-length ctors class-sym)))
+    (lambda (&rest args)
+      (let ((fn (cdr (assoc (length args) thunks))))
+        (if fn
+            (apply fn
+                   args)
+          (error "invalid arity"))))))
+
+(defun make-ctor-thunks-by-args-length (ctors class-sym)
+  "returns an alist of thunks keyed by number of args"
+  (let ((ctors-by-args-length (make-hash-table))
+        (thunks-by-args-length nil))
+    (dolist (ctor ctors)
+      (let ((params-len (get-array-length (constructor.getparametertypes ctor))))
+        (push ctor (gethash params-len ctors-by-args-length))))
+    (maphash #'(lambda (args-len ctors)
+                 (push (cons args-len
+                             (if (rest ctors);truly overloaded
+                                 (make-type-overloaded-ctor-thunk ctors class-sym)
+                               ;only one ctor with this number of args
+                               (make-non-overloaded-ctor-thunk (first ctors) class-sym)))
+                       thunks-by-args-length))
+             ctors-by-args-length)
+    thunks-by-args-length))
+
+(defun make-type-overloaded-ctor-thunk (ctors class-sym)
+  "these methods have the same number of args and must be distinguished by type"
+  (let ((thunks (mapcar #'(lambda (ctor)
+                            (list (make-non-overloaded-ctor-thunk ctor class-sym)
+                                  (jarray-to-list (constructor.getparametertypes ctor))))
+                        ctors)))
+    (lambda (&rest args)
+      (block fn
+        (let ((arg-types (get-types-of-args args)))
+          (dolist (thunk-info thunks)
+            (destructuring-bind (thunk param-types) thunk-info
+              (when (is-congruent-type-list param-types arg-types)
+                (return-from fn (apply thunk args)))))
+          (error "No matching constructor"))))))
+
+(defmacro new (class-spec &rest args)
+"new class-spec args
+class-spec -> class-name | (class-name this-name)
+class-name -> \"package.qualified.ClassName\" | classname.
+args -> [actual-arg]* [init-arg-spec]*
+init-arg-spec -> init-arg | (init-arg)
+init-arg -> :settable-field-or-method [params]* value ;note keyword
+            | 
+            .method-name [args]*                      ;note dot
+
+Creates a new instance of class-name, using make-new generic function,
+then initializes it by setting fields or accessors and/or calling member functions
+If this-name is supplied it will be bound to the newly-allocated object and available
+to the init-args"
+  (labels ((mem-sym? (x)
+             (or (keywordp x)
+                 (and (symbolp x) (eql 0 (position #\. (symbol-name x))))))
+           (mem-form? (x)
+             (and (listp x) (mem-sym? (first x))))
+           (mem-init? (x)
+             (or (mem-sym? x) (mem-form? x)))
+           (init-forms (x)
+             (if x
+                 (if (mem-form? (first x))
+                     (cons (first x) (init-forms (rest x)))
+                   (let ((more (member-if #'mem-init? (rest x))))
+                     (cons (ldiff x more) (init-forms more)))))))
+    (let* ((inits (member-if #'mem-init? args))
+           (real-args (ldiff args inits))
+           (class-atom (if (atom class-spec)
+                           class-spec
+                         (first class-spec)))
+           (class-sym (if (symbolp class-atom)
+                          ;(find-symbol (string-append (symbol-name class-atom) "."))
+                          class-atom
+                        (multiple-value-bind (package class) (jni::split-package-and-class class-atom)
+                          (find-symbol (string-append (string-upcase class) ".") package))))
+           (class-name (subseq (symbol-name class-sym) 0 (1- (length (symbol-name class-sym)))))
+           (gthis (gensym)))
+      (flet ((expand-init (x)
+               (if (keywordp (first x)) ;setf field or property
+                   `(setf (,(find-symbol (string-append class-name "." (symbol-name (first x))))
+                           ,gthis ,@(butlast (rest x)))
+                          ,@(last (rest x)))
+                 ;.memfunc
+                 `(,(find-symbol (string-append class-name (symbol-name (first x))))
+                   ,gthis
+                   ,@(rest x)))))
+        `(let* ((,gthis (make-new ,class-sym ,@real-args))
+                ,@(when (listp class-spec)
+                    `((,(second class-spec) ,gthis))))
+           ,@(mapcar #'expand-init (init-forms inits))
+           ,gthis)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#|
+all public fields will get a getter function classname.fieldname and a setter - (setf classname.fieldname)
+instance fields take an first arg which is the instance
+static fields also get a symbol-macro *classname.fieldname*
+|#
+
+(defmacro def-java-fields (full-class-name)
+"fields will get a getter function classname.fieldname and a setter - (setf classname.fieldname)
+instance fields take an first arg which is the instance
+static fields also get a symbol-macro *classname.fieldname*"
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (fields (jarray-to-list (class.getfields class)))
+         (defs nil))
+    (dolist (field fields)
+      (let* ((field-name (field.getname field))
+             (field-sym (member-symbol full-class-name field-name))
+             (is-static (modifier.isstatic (field.getmodifiers field))))
+        (if is-static
+            (let ((macsym (intern (string-append "*" (symbol-name field-sym) "*")
+                                  (symbol-package field-sym))))
+              (push `(defun ,field-sym ()
+                       (install-static-field-and-get ,full-class-name ,field-name))
+                    defs)
+              (push `(defun (setf ,field-sym) (val)
+                       (install-static-field-and-set ,full-class-name ,field-name val))
+                    defs)
+              (push `(export ',field-sym (symbol-package ',field-sym)) defs)
+              (push `(define-symbol-macro ,macsym (,field-sym)) defs)
+              (push `(export ',macsym (symbol-package ',macsym)) defs))
+          (progn
+            (push `(defun ,field-sym (obj)
+                     (install-field-and-get ,full-class-name ,field-name obj))
+                  defs)
+            (push `(defun (setf ,field-sym) (val obj)
+                     (install-field-and-set ,full-class-name ,field-name val obj))
+                  defs)
+            (push `(export ',field-sym (symbol-package ',field-sym)) defs)))))
+    `(locally ,@(nreverse defs))))
+
+(defun install-field-and-get (full-class-name field-name obj)
+  (install-field full-class-name field-name)
+  (funcall (member-symbol full-class-name field-name) obj))
+
+(defun install-field-and-set (full-class-name field-name val obj)
+  (install-field full-class-name field-name)
+  (funcall (fdefinition `(setf ,(member-symbol full-class-name field-name))) val obj))
+
+(defun install-static-field-and-get (full-class-name field-name)
+  (install-field full-class-name field-name)
+  (funcall (member-symbol full-class-name field-name)))
+
+(defun install-static-field-and-set (full-class-name field-name val)
+  (install-field full-class-name field-name)
+  (funcall (fdefinition `(setf ,(member-symbol full-class-name field-name))) val))
+
+(defun install-field (full-class-name field-name)
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (field (class.getfield class field-name))
+         (field-sym (member-symbol full-class-name field-name))
+         (is-static (modifier.isstatic (field.getmodifiers field)))
+         (field-type-name (class.getname (field.gettype field)))
+         (boxer (get-boxer-fn field-type-name))
+         (unboxer (get-unboxer-fn field-type-name)))
+    (if is-static
+        (progn
+          (setf (fdefinition field-sym)
+                (lambda ()
+                  (funcall unboxer (field.get field nil) t)))
+          (setf (fdefinition `(setf ,field-sym))
+                (lambda (arg)
+                  (field.set field nil
+                             (get-ref (if (and boxer (not (boxed? arg)))
+                                          (funcall boxer arg)
+                                        arg)))
+                  arg)))
+      (progn
+        (setf (fdefinition field-sym)
+              (lambda (obj)
+                (funcall unboxer (field.get field (get-ref obj)) t)))
+        (setf (fdefinition `(setf ,field-sym))
+              (lambda (arg obj)
+                (field.set field (get-ref obj)
+                           (get-ref (if (and boxer (not (boxed? arg)))
+                                        (funcall boxer arg)
+                                      arg)))
+                arg))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;; methods ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+defines wrappers for all public methods of the class
+As with ctors, if a method is overloaded a single wrapper is created that handles
+overload resolution.
+The wrappers have the name classname.methodname
+If a method follows the JavaBeans property protocol (i.e. it is called getSomething or isSomething
+and there is a corresponding setSomething, then a (setf classname.methodname) will be defined
+that calls the latter
+|#
+
+(defun class-name-for-doc (class)
+  (let ((name (class.getname class)))
+    (if (class.isarray class)
+        (decode-array-name name)
+      name)))
+
+(defun build-method-doc-string (name methods)
+  (with-output-to-string (s)
+    (dolist (m methods)
+      (format s "~A~A ~A(~{~#[~;~A~:;~A,~]~})~%"
+              (if (modifier.isstatic (method.getmodifiers m))
+                  "static "
+                "")
+              (class.getname (method.getreturntype m))
+              name
+              (mapcar #'class-name-for-doc (jarray-to-list (method.getparametertypes m)))))))
+
+(defmacro def-java-methods (full-class-name)
+  (let ((methods-by-name (get-methods-by-name full-class-name))
+        (defs nil))
+    (maphash (lambda (name methods)
+               (let ((method-sym (member-symbol full-class-name name)))
+                 (push `(defun ,method-sym (&rest args)
+                          ,(build-method-doc-string name methods)
+                          (apply #'install-methods-and-call ,full-class-name ,name args))
+                       defs)
+                 (push `(export ',method-sym (symbol-package ',method-sym))
+                       defs)
+                 ;build setters when finding beans property protocol
+                 (flet ((add-setter-if (prefix)
+                          (when (eql 0 (search prefix name))
+                            (let ((setname (string-append "set" (subseq name (length prefix)))))
+                              (when (gethash setname methods-by-name)
+                                (push `(defun (setf ,method-sym) (val &rest args)
+                                         (progn
+                                           (apply #',(member-symbol full-class-name setname)
+                                                  (append args (list val)))
+                                           val))
+                                      defs))))))
+                   (add-setter-if "get")
+                   (add-setter-if "is"))))
+             methods-by-name)
+    `(locally ,@(nreverse defs))))
+
+(defun install-methods-and-call (full-class-name method &rest args)
+  "initially all the member function symbols for a class are bound to this function,
+when first called it will replace them with the appropriate direct thunks,
+then call the requested method - subsequent calls via those symbols will be direct"
+  (install-methods full-class-name)
+  (apply (member-symbol full-class-name method) args))
+
+(defun decode-array-name (tn)
+  (let ((prim (assoc tn
+                     '(("Z" . "boolean")
+                       ("B" . "byte")
+                       ("C" . "char")
+                       ("S" . "short")
+                       ("I" . "int")
+                       ("J" . "long")
+                       ("F" . "float")
+                       ("D" . "double")
+                       ("V" . "void"))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      (let ((array-depth (count #\[ tn)))
+        (if (= 0 array-depth)
+            (subseq tn 1 (1- (length tn))) ;strip leading L and trailing ;
+          (with-output-to-string (s)
+            (write-string (decode-array-name (subseq tn array-depth)) s)
+            (dotimes (x array-depth)
+              (write-string "[]" s))))))))
+
+(defun jarray-to-list (array)
+  (let (ret)
+    (do-jarray (x array)
+      (push x ret))
+    (nreverse ret)))
+
+(defun get-methods-by-name (full-class-name)
+  "returns an #'equal hashtable of lists of java.lang.Method refs keyed by name"
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (method-array (class.getmethods class))
+         (methods-by-name (make-hash-table :test #'equal)))
+    (do-jarray (method method-array)
+      (push method (gethash (method.getName method) methods-by-name)))
+    methods-by-name))
+
+(defun install-methods (full-class-name)
+  (let ((methods-by-name (get-methods-by-name full-class-name)))
+    (maphash
+     (lambda (name methods)
+       (setf (fdefinition (member-symbol full-class-name name))
+             (make-method-thunk methods)))
+     methods-by-name)))
+
+(defun make-method-thunk (methods)
+  (if (rest methods) ;overloaded
+      (make-overloaded-thunk methods)
+    (make-non-overloaded-thunk (first methods))))
+
+(defun make-non-overloaded-thunk (method)
+  (let ((unboxer-fn (get-unboxer-fn (class.getname (method.getreturntype method))))
+        (arg-boxers (get-arg-boxers (method.getparametertypes method)))
+        (is-static (modifier.isstatic (method.getmodifiers method))))
+    (lambda (&rest args)
+      (let ((arg-array (build-arg-array (if is-static args (rest args)) arg-boxers)))
+        (prog1
+            (funcall unboxer-fn
+                     (method.invoke method
+                                    (if is-static nil (get-ref (first args)))
+                                    arg-array) t)
+          (when arg-array
+            (delete-local-ref arg-array)))))))
+
+(defun make-overloaded-thunk (methods)
+  (let ((thunks (make-thunks-by-args-length methods)))
+    (lambda (&rest args)
+      (let ((fn (cdr (assoc (length args) thunks))))
+        (if fn
+            (apply fn
+                   args)
+          (error "invalid arity"))))))
+
+(defun make-thunks-by-args-length (methods)
+  "returns an alist of thunks keyed by number of args"
+  (let ((methods-by-args-length (make-hash-table))
+        (thunks-by-args-length nil))
+    (dolist (method methods)
+      (let ((is-static (modifier.isstatic (method.getmodifiers method)))
+            (params-len (get-array-length (method.getparametertypes method))))
+        (push method (gethash (if is-static params-len (1+ params-len))
+                              methods-by-args-length))))
+    (maphash #'(lambda (args-len methods)
+                 (push (cons args-len
+                             (if (rest methods);truly overloaded
+                                 (make-type-overloaded-thunk methods)
+                               ;only one method with this number of args
+                               (make-non-overloaded-thunk (first methods))))
+                       thunks-by-args-length))
+             methods-by-args-length)
+    thunks-by-args-length))
+
+(defun make-type-overloaded-thunk (methods)
+  "these methods have the same number of args and must be distinguished by type"
+  (let ((thunks (mapcar #'(lambda (method)
+                            (list (make-non-overloaded-thunk method)
+                                  (modifier.isstatic (method.getmodifiers method))
+                                  (jarray-to-list (method.getparametertypes method))))
+                        methods)))
+    (lambda (&rest args)
+      (block fn
+        (let ((arg-types (get-types-of-args args)))
+          (dolist (thunk-info thunks)
+            (destructuring-bind (thunk is-static param-types) thunk-info
+              (when (is-congruent-type-list param-types (if is-static arg-types (rest arg-types)))
+                (return-from fn (apply thunk args)))))
+          (error "No matching method"))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;; array support ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun jref (array &rest subscripts)
+  "like aref, for Java arrays of non-primitive/reference types, settable"
+  (assert (every #'integerp subscripts))
+  (do*
+       ((sub subscripts (rest sub))
+        (a (get-ref array) (get-ref (array.get a (first sub)))))
+       ((null (rest sub))
+        (array.get a (first sub)))))
+
+(defun (setf jref) (val array &rest subscripts)
+  (assert (every #'integerp subscripts))
+  (do*
+       ((sub subscripts (rest sub))
+        (a (get-ref array) (get-ref (array.get a (first sub)))))
+       ((null (rest sub))
+        (array.set a (first sub) (get-ref val))
+        val)))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro def-refs (&rest types)
+    `(locally
+       ,@(mapcan
+          (lambda (type)
+            (let ((ref-sym (intern (string-upcase (string-append "jref-" (symbol-name type))))))
+              (list 
+               `(defun ,ref-sym (array &rest subscripts)
+                  ,(format nil "like aref, for Java arrays of ~A, settable" (symbol-name type))
+                  (assert (every #'integerp subscripts))
+                  (do*
+                       ((sub subscripts (rest sub))
+                        (a (get-ref array) (get-ref (array.get a (first sub)))))
+                       ((null (rest sub))
+                        (,(intern (string-upcase (string-append "array.get" (symbol-name type))))
+                         a (first sub)))))
+
+               `(defun (setf ,ref-sym) (val array &rest subscripts)
+                  (assert (every #'integerp subscripts))
+                  (do*
+                       ((sub subscripts (rest sub))
+                        (a (get-ref array) (get-ref (array.get a (first sub)))))
+                       ((null (rest sub))
+                        (array.set a (first sub)
+                                   (,(intern (string-upcase (string-append "box-"
+                                                                           (symbol-name type))))
+                                    val))
+                        val))))))
+          types))))
+
+;arrays of primitives have their own accessors
+(def-refs boolean byte char double float int short long)
+
+(defun jlength (array)
+  "like length, for Java arrays"
+  (array.getlength (get-ref array)))
+
+(defgeneric make-new-array (type &rest dimensions)
+  (:documentation "generic function, with methods for all Java class designators")
+  (:method (type &rest dims)
+   (assert (every #'integerp dims))
+   (if (rest dims)
+       (let* ((ndim (length dims))
+              (dim-array (new-int-array ndim)))
+         (dotimes (i ndim)
+           (array.set dim-array i (box-int (nth i dims))))
+         (array.newinstance<java.lang.class-int<>> type dim-array))
+     (array.newinstance<java.lang.class-int> type (first dims)))))
+
+(defmethod make-new-array ((type symbol) &rest dimensions)
+  (apply #'make-new-array (get-java-class-ref type) dimensions))
+
+(defmethod make-new-array ((type string) &rest dimensions)
+  (apply #'make-new-array (find-java-class type) dimensions))
+
+(defmethod make-new-array ((type (eql :char)) &rest dimensions)
+  (apply #'make-new-array character.type dimensions))
+
+(defmethod make-new-array ((type (eql :int)) &rest dimensions)
+  (apply #'make-new-array integer.type dimensions))
+
+(defmethod make-new-array ((type (eql :boolean)) &rest dimensions)
+  (apply #'make-new-array boolean.type dimensions))
+
+(defmethod make-new-array ((type (eql :double)) &rest dimensions)
+  (apply #'make-new-array double.type dimensions))
+
+(defmethod make-new-array ((type (eql :byte)) &rest dimensions)
+  (apply #'make-new-array byte.type dimensions))
+
+(defmethod make-new-array ((type (eql :float)) &rest dimensions)
+  (apply #'make-new-array float.type dimensions))
+
+(defmethod make-new-array ((type (eql :short)) &rest dimensions)
+  (apply #'make-new-array short.type dimensions))
+
+(defmethod make-new-array ((type (eql :long)) &rest dimensions)
+  (apply #'make-new-array long.type dimensions))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;; arg/param helpers ;;;;;;;;;;;;;;;;;;;;;;
+
+(defun get-arg-boxers (param-types)
+  "returns a list with one entry per param, either nil or a function that boxes the arg"
+  (let (ret)
+    (do-jarray (param-type param-types)
+      (push (get-boxer-fn (class.getname param-type))
+            ret))
+    (nreverse ret)))
+
+(defun build-arg-array (args arg-boxers)
+  (when args
+    (let* ((arg-array (new-object-array (length args)
+                                      ;duplication of class-symbol logic
+                                      ;but must be fast
+                                        (get-java-class-ref '|java.lang|::|Object|)
+                                        nil)))
+      (do ((i 0 (incf i))
+           (args args (rest args))
+           (boxers arg-boxers (rest boxers)))
+          ((null args))
+        (let ((arg (first args))
+              (boxer (first boxers)))
+          (setf (jaref arg-array i)
+                (get-ref (if (and boxer (not (boxed? arg)))
+                             (funcall boxer arg)
+                           arg)))))
+      arg-array)))
+
+(defun get-types-of-args (args)
+  (let (ret)
+    (dolist (arg args)
+      (push (infer-box-type arg)
+            ret))
+    (nreverse ret)))
+
+(defun is-congruent-type-list (param-types arg-types)
+  (every #'(lambda (arg-type param-type)
+             (if arg-type
+                 (is-assignable-from arg-type param-type)
+               ;nil was passed - must be boolean or non-primitive target type
+               (or (not (class.isprimitive param-type))
+                   (is-assignable-from boolean.type param-type))))
+         arg-types param-types))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;; argument conversion and boxing ;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun box-string (s)
+"Given a string or symbol, returns reference to a Java string"
+  (local-ref-to-global-ref (convert-to-java-string s)))
+
+(defun unbox-string (ref &optional delete-local)
+  "Given a reference to a Java string, returns a Lisp string" 
+  (declare (ignore delete-local))
+  (convert-from-java-string (get-ref ref)))
+
+(defun get-boxer-fn (class-name)
+  (case-equal class-name
+    ("int" #'box-int)
+    ("boolean" #'box-boolean)
+    ("double" #'box-double)
+    ("java.lang.String" #'convert-to-java-string)
+    ("char" #'box-char)
+    ("byte" #'box-byte)
+    ("float" #'box-float)
+    ("long" #'box-long)
+    ("short" #'box-short)
+    (otherwise nil)))
+
+(defun get-boxer-fn-sym (class-name)
+  (case-equal class-name
+    ("int" 'box-int)
+    ("boolean" 'box-boolean)
+    ("double" 'box-double)
+    ("java.lang.String" 'convert-to-java-string)
+    ("char" 'box-char)
+    ("byte" 'box-byte)
+    ("float" 'box-float)
+    ("long" 'box-long)
+    ("short" 'box-short)
+    ("void" 'box-void)
+    (otherwise 'identity)))
+
+(defun boxed? (x)
+  (or (java-ref-p x)
+      (typep x '|java.lang|::object.)))
+
+(defun infer-box-type (x)
+  (cond
+   ((null x) nil)
+   ((boxed? x) (object.getclass (get-ref x)))
+   ((integerp x) integer.type)
+   ((numberp x) double.type)
+   ((eq x t) boolean.type)
+   ((or (stringp x) (symbolp x))
+    (get-java-class-ref '|java.lang|::|String|))
+   (t (error "can't infer box type"))))
+
+(defun get-unboxer-fn (class-name)
+  (case-equal class-name
+    ("int" #'unbox-int)
+    ("boolean" #'unbox-boolean)
+    ("double" #'unbox-double)
+    ("java.lang.String" #'unbox-string)
+    ("void" #'unbox-void)
+    ("char" #'unbox-char)
+    ("byte" #'unbox-byte)
+    ("float" #'unbox-float)
+    ("long" #'unbox-long)
+    ("short" #'unbox-short)
+    (otherwise  #'unbox-ref)))
+
+(defun get-unboxer-fn-sym (class-name)
+  (case-equal class-name
+    ("int" 'unbox-int)
+    ("boolean" 'unbox-boolean)
+    ("double" 'unbox-double)
+    ("java.lang.String" 'unbox-string)
+    ("void" 'unbox-void)
+    ("char" 'unbox-char)
+    ("byte" 'unbox-byte)
+    ("float" 'unbox-float)
+    ("long" 'unbox-long)
+    ("short" 'unbox-short)
+    (otherwise  'unbox-ref)))
+
+(defun unbox-ref (x &optional delete-local)
+  (declare (ignore delete-local))
+  (local-ref-to-global-ref x))
+
+(defun unbox-void (x &optional delete-local)
+  (declare (ignore x delete-local))
+  nil)
+
+(defun box-void (x)
+  (declare (ignore x))
+  nil)
+
+(defun box-boolean (x)
+  (boolean.new x))
+
+(defun unbox-boolean (obj &optional delete-local)
+  (prog1
+      (boolean.booleanvalue (get-ref obj))
+    (when delete-local (delete-local-ref obj))))
+
+(defun box-byte (x)
+  (assert (integerp x))
+  (byte.new x))
+
+(defun unbox-byte (x &optional delete-local)
+  (prog1
+      (byte.bytevalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-char (x)
+  (character.new x))
+
+(defun unbox-char (x &optional delete-local)
+  (prog1
+      (character.charvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-double (x)
+  (assert (floatp x))
+  (double.new (coerce x 'double-float)))
+
+(defun unbox-double (x &optional delete-local)
+  (prog1
+      (double.doublevalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-float (x)
+  (assert (floatp x))
+  (float.new x))
+
+(defun unbox-float (x &optional delete-local)
+  (prog1
+      (float.floatvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-int (x)
+  (assert (integerp x))
+  (integer.new x))
+
+(defun unbox-int (x &optional delete-local)
+  (prog1
+      (integer.intvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+;can't directly construct Long because LW doesn't support long long fli on 32 bit platforms
+(defun box-long (x)
+  (assert (integerp x))
+  (long.valueof (princ-to-string x)))
+
+;here too, can only get an ints worth - aargh
+(defun unbox-long (obj &optional delete-local)
+  (prog1
+      (parse-integer (object.tostring (get-ref obj)))
+    (when delete-local (delete-local-ref obj))))
+
+(defun box-short (x)
+  (assert (integerp x))
+  (short.new x))
+
+(defun unbox-short (x &optional delete-local)
+  (prog1
+      (short.shortvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;; proxy support ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun proxy-hashcode (proxy)
+  ;use the hashcode of the proxy's class, 
+  ;because hashcode() on the proxy flows through to the invocation handler
+  ;is this rem guaranteed to be a fixnum?
+  (rem (object.hashcode (object.getclass proxy)) most-positive-fixnum))
+
+(defvar *proxy-table* (make-hash-table :test #'jeq :hash-function #'proxy-hashcode))
+
+;(defvar *proxy-list* nil)
+
+(defun store-proxy (proxy method-fn-alist)
+  ;(push (cons proxy method-fn-alist) *proxy-list*)
+  (setf (gethash proxy *proxy-table*) method-fn-alist))
+
+(defun recall-proxy (proxy)
+  ;(cdr (assoc proxy *proxy-list* :test #'jeq))
+  (gethash proxy *proxy-table*))
+
+(defun unregister-proxy (proxy)
+"Stops handling for the proxy and removes references from the Lisp side.
+Make sure it is no longer referenced from Java first!"
+  (remhash proxy *proxy-table*))
+
+(defun invocation-handler (proxy method args)
+  (let* ((method-fn-alist (recall-proxy proxy))
+         (fn (and method-fn-alist (second (assoc (object.tostring method) method-fn-alist
+                                                 :test #'equal)))))
+    (if fn
+        (funcall fn args)
+      (progn
+        ;(throw-new  (find-java-class "java.lang.UnsupportedOperationException")
+        ;            "No function registered in Lisp proxy object")
+        nil))))
+
+(defun enable-java-proxies ()
+  "must be called before any call to new-proxy, and requires jfli.jar be in the classpath"
+  (jni:register-invocation-handler #'invocation-handler))
+
+(defun make-proxy-instance (&rest interface-defs)
+  (let* ((interfaces (mapcar #'first interface-defs))
+         (method-fn-alist (mapcan #'second interface-defs))
+         (len (length interfaces))
+         (iarray (array.newinstance<java.lang.class-int> (get-java-class-ref '|java.lang|::|Class|)
+                                                         len)))
+    (dotimes (x len)
+      (setf (jref iarray x) (nth x interfaces)))
+    (let ((proxy (proxy.newproxyinstance (classloader.getsystemclassloader)
+                                         iarray
+                                         (lispinvocationhandler.new))))
+      (store-proxy proxy method-fn-alist)
+      proxy)))
+
+(defun find-java-class-in-macro (name)
+  (find-java-class
+   (if (symbolp name)
+       (symbol-value name)
+     name)))
+
+(defmacro new-proxy (&rest interface-defs)
+"interface-def -> (interface-name method-defs+)
+interface-name -> \"package.qualified.ClassName\" | classname. (must name a Java interface type)
+method-def -> (method-name arg-defs* body)
+arg-def -> arg-name | (arg-name arg-type)
+arg-type -> \"package.qualified.ClassName\" | classname. | :primitive
+method-name -> symbol | string (matched case-insensitively)
+
+Creates, registers and returns a Java object that implements the supplied interfaces"
+
+  (labels ((process-idefs (idefs)
+             (when idefs
+               (cons (process-idef (first idefs))
+                     (process-idefs (rest idefs)))))
+           (process-idef (idef)
+             (destructuring-bind (interface-name &rest method-defs) idef
+               (let* ((methods (class.getmethods (find-java-class-in-macro interface-name)))
+                      (ret `(list (find-java-class ,interface-name)
+                                  (list ,@(mapcar (lambda (method-def)
+                                                    (process-method-def method-def methods))
+                                                  method-defs)))))
+                 ;check to make sure every function is defined
+                 (do-jarray (method methods)
+                   (let ((mname (object.tostring method)))
+                     (unless (member mname (rest (third ret)) :key #'second :test #'equal)
+                       (warn (format nil "proxy doesn't define:~%~A" mname)))))
+                 ret)))
+           (process-method-def (method-def methods)
+             (destructuring-bind (method-name (&rest arg-defs) &body body) method-def
+               (let ((method (matching-method method-name arg-defs methods))
+                     (gargs (gensym)))
+                 `(list ,(object.tostring method)
+                        (lambda (,gargs)
+                          (,(get-boxer-fn-sym (class.getname (method.getreturntype method)))
+                           (let ,(arg-lets arg-defs
+                                           (jarray-to-list (method.getparametertypes method))
+                                           gargs
+                                           0)
+                             ,@body)))))))
+           (arg-lets (arg-defs params gargs idx)
+             (when arg-defs
+               (let ((arg (first arg-defs))
+                     (param (first params)))
+                 (cons `(,(if (atom arg) arg (first arg))
+                         (,(get-unboxer-fn-sym (class.getname param))
+                          (jref ,gargs ,idx) t))
+                       (arg-lets (rest arg-defs) (rest params) gargs (1+ idx))))))
+           (matching-method (method-name arg-defs methods)
+             (let (match)
+               (do-jarray (method methods)
+                 (when (method-matches method-name arg-defs method)
+                   (if match
+                       (error (format nil "more than one method matches ~A" method-name))
+                     (setf match method))))
+               (or match (error (format nil "no method matches ~A" method-name)))))
+           (method-matches (method-name arg-defs method)
+             (when (string-equal method-name (method.getname method))
+               (let ((params (method.getparametertypes method)))
+                 (when (= (length arg-defs) (jlength params))
+                   (is-congruent arg-defs params)))))
+           (is-congruent (arg-defs params)
+             (every (lambda (arg param)
+                      (or (atom arg) ;no type spec matches anything
+                          (jeq (find-java-class-in-macro (second arg)) param)))
+                    arg-defs (jarray-to-list params))))
+    `(make-proxy-instance ,@(process-idefs interface-defs))))
Index: /branches/new-random/examples/jfli/jfli.lisp
===================================================================
--- /branches/new-random/examples/jfli/jfli.lisp	(revision 13309)
+++ /branches/new-random/examples/jfli/jfli.lisp	(revision 13309)
@@ -0,0 +1,1390 @@
+;    Copyright (c) Rich Hickey. All rights reserved.
+;    The use and distribution terms for this software are covered by the
+;    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+;    which can be found in the file CPL.TXT at the root of this distribution.
+;    By using this software in any fashion, you are agreeing to be bound by
+;    the terms of this license.
+;    You must not remove this notice, or any other, from this software.
+
+#|
+
+jfli is a library that provides access to Java from Lisp
+It depends on the jni package (included)
+Callbacks from Java to Lisp also require jfli.jar (included)
+
+|#
+
+(defpackage :jfli
+  (:use :common-lisp :jni)
+  (:export
+
+   ;jvm creation
+   :*jni-lib-path*  ;exposed from jni
+   :create-jvm      ;exposed from jni, you must call this prior to calling any other jfli function
+   :enable-java-proxies
+
+   ;wrapper generation
+   :def-java-class
+   :get-jar-classnames
+   :dump-wrapper-defs-to-file
+
+   ;object creation etc
+   :find-java-class
+   :new
+   :make-new
+   :make-typed-ref
+   :jeq
+
+   ;array support
+   :make-new-array
+   :jlength
+   :jref
+   :jref-boolean
+   :jref-byte
+   :jref-char
+   :jref-double
+   :jref-float
+   :jref-int
+   :jref-short
+   :jref-long
+
+   ;proxy support
+   :new-proxy
+   :unregister-proxy
+
+   ;conversions
+   :box-boolean
+   :box-byte
+   :box-char
+   :box-double
+   :box-float
+   :box-integer
+   :box-long
+   :box-short
+   :box-string
+   :unbox-boolean
+   :unbox-byte
+   :unbox-char
+   :unbox-double
+   :unbox-float
+   :unbox-integer
+   :unbox-long
+   :unbox-short
+   :unbox-string
+
+;   :ensure-package
+;   :member-symbol
+;   :class-symbol
+;   :constructor-symbol
+   ))
+
+(in-package :jfli)
+
+#|
+bootstrap the implementation of reflection wrappers with 
+a few (primitive, less safe and maybe faster) jni wrappers
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (def-jni-functions "java.lang.Object"
+                     ("getClass" () "Class")
+                     ("hashCode" () "int")
+                     ("toString" () "String")
+                     ("equals" ((obj "Object")) "boolean"))
+
+  (def-jni-functions "java.lang.Class"
+                   ;should be :overloaded t, but we only use this version
+                     ("forName" ((className "String")) "Class"  :static t)
+                     ("getConstructors" () "java.lang.reflect.Constructor<>")
+                     ("getFields" () "java.lang.reflect.Field<>")
+                     ("getMethods" () "java.lang.reflect.Method<>")
+
+                     ("getConstructor" ((parameter-types "Class<>")) "java.lang.reflect.Constructor")
+                     ("getField" ((name "String"))
+                                 "java.lang.reflect.Field")
+                     ("getMethod" ((name "String") (parameter-types "Class<>"))
+                                  "java.lang.reflect.Method")
+
+                     ("getSuperclass" () "Class")
+                     ("getInterfaces" () "Class<>")
+
+                     ("getName" () "String")
+                     ("isArray" () "boolean")
+                     ("isPrimitive" () "boolean"))
+
+  (def-jni-functions "java.lang.reflect.Field"
+                     ("getName" () "java.lang.String")
+                     ("getType" () "java.lang.Class")
+                     ("getModifiers" () "int")
+
+                     ("get" ((obj "java.lang.Object")) "java.lang.Object" :raw-return t)
+                     ("getBoolean" ((obj "java.lang.Object")) "boolean")
+                     ("getByte" ((obj "java.lang.Object")) "byte")
+                     ("getChar" ((obj "java.lang.Object")) "char")
+                     ("getDouble" ((obj "java.lang.Object")) "double")
+                     ("getFloat" ((obj "java.lang.Object")) "float")
+                     ("getInt" ((obj "java.lang.Object")) "int")
+                     ("getLong" ((obj "java.lang.Object")) "long")
+                     ("getShort" ((obj "java.lang.Object")) "short")
+
+                     ("set" ((obj "java.lang.Object") (value "java.lang.Object")) "void")
+                     ("setBoolean" ((obj "java.lang.Object") (b "boolean")) "void")
+                     ("setByte" ((obj "java.lang.Object") (b "byte")) "void")
+                     ("setChar" ((obj "java.lang.Object") (c "char")) "void")
+                     ("setDouble" ((obj "java.lang.Object") (d "double")) "void")
+                     ("setFloat" ((obj "java.lang.Object") (f "float")) "void")
+                     ("setInt" ((obj "java.lang.Object") ( i "int")) "void")
+                     ("setLong" ((obj "java.lang.Object") (l "long")) "void")
+                     ("setShort" ((obj "java.lang.Object") (s "short")) "void"))
+
+  (def-jni-functions "java.lang.reflect.Constructor"
+                     ("getParameterTypes" () "java.lang.Class<>")
+                     ("newInstance" ((initargs "java.lang.Object<>")) "java.lang.Object"))
+
+  (def-jni-functions "java.lang.reflect.Method"
+                     ("getName" () "java.lang.String")
+                     ("getParameterTypes" () "java.lang.Class<>")
+                     ("getReturnType" () "java.lang.Class")
+                     ("getModifiers" () "int")
+                     ("invoke" ((object "java.lang.Object")
+                                (args "java.lang.Object<>")) "java.lang.Object"
+                               :raw-return t))
+
+  (def-jni-functions "java.lang.reflect.Array"
+                     ("get" ((array "java.lang.Object") (index "int")) "java.lang.Object" :static t)
+                     ("getBoolean"
+                      ((array "java.lang.Object") (index "int")) "boolean" :static t)
+                     ("getByte"
+                      ((array "java.lang.Object") (index "int")) "byte" :static t)
+                     ("getChar"
+                      ((array "java.lang.Object") (index "int")) "char" :static t)
+                     ("getDouble"
+                      ((array "java.lang.Object") (index "int")) "double" :static t)
+                     ("getFloat"
+                      ((array "java.lang.Object") (index "int")) "float" :static t)
+                     ("getInt"
+                      ((array "java.lang.Object") (index "int")) "int" :static t)
+                     ("getShort"
+                      ((array "java.lang.Object") (index "int")) "short" :static t)
+                     ("getLong"
+                      ((array "java.lang.Object") (index "int")) "long" :static t)
+                     ("getLength" ((array "java.lang.Object")) "int" :static t)
+                     ("newInstance" ((componentType "java.lang.Class")
+                                     (length "int")) "java.lang.Object" :static t :overloaded t)
+                     ("newInstance" ((componentType "java.lang.Class")
+                                     (dimensions "int<>")) "java.lang.Object" :static t :overloaded t)
+                     ("set" ((array "java.lang.Object") (index "int") (value "java.lang.Object"))
+                            "void" :static t))
+
+
+  (def-jni-function "java.lang.reflect.Modifier"
+                    "isStatic" ((mod "int")) "boolean" :static t)
+
+  (def-jni-constructor "java.lang.Boolean" ((value "boolean")))
+  (def-jni-constructor "java.lang.Byte" ((value "byte")))
+  (def-jni-constructor "java.lang.Character" ((value "char")))
+  (def-jni-constructor "java.lang.Double" ((value "double")))
+  (def-jni-constructor "java.lang.Float" ((value "float")))
+  (def-jni-constructor "java.lang.Integer" ((value "int")))
+  (def-jni-constructor "java.lang.Short" ((value "short")))
+
+  (def-jni-function "java.lang.Boolean" "booleanValue" () "boolean")
+  (def-jni-function "java.lang.Byte" "byteValue" () "byte")
+  (def-jni-function "java.lang.Character" "charValue" () "char")
+  (def-jni-function "java.lang.Double" "doubleValue" () "double")
+  (def-jni-function "java.lang.Float" "floatValue" () "float")
+  (def-jni-function "java.lang.Integer" "intValue" () "int")
+  (def-jni-function "java.lang.Short" "shortValue" () "short")
+
+  (def-jni-constructor "java.util.jar.JarFile" ((filename "java.lang.String")))
+  (def-jni-function "java.util.jar.JarFile"
+                    "entries" () "java.util.Enumeration")
+  (def-jni-functions "java.util.Enumeration"
+                     ("hasMoreElements" () "boolean")
+                     ("nextElement" () "java.lang.Object"))
+  (def-jni-functions "java.util.zip.ZipEntry"
+                     ("isDirectory" () "boolean")
+                     ("getName" () "java.lang.String"))
+
+
+  (def-jni-functions "java.lang.Long"
+                     ("valueOf" ((s "String")) "java.lang.Long" :static t)
+                     ("intValue" () "int"))
+
+  (def-jni-field "java.lang.Boolean" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Byte" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Character" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Float" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Integer" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Double" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Short" "TYPE" "Class" :static t)
+  (def-jni-field "java.lang.Long" "TYPE" "Class" :static t)
+
+  (def-jni-constructor "com.richhickey.jfli.LispInvocationHandler" ())
+  (def-jni-function "java.lang.reflect.Proxy"
+                    "newProxyInstance" ((loader "java.lang.ClassLoader")
+                                        (interfaces "java.lang.Class<>")
+                                        (h "InvocationHandler")) "java.lang.Object" :static t)
+
+  (def-jni-function "java.lang.ClassLoader"
+                    "getSystemClassLoader" () "ClassLoader" :static t)
+
+  ) ;eval-when
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;; utilities ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun ensure-package (name)
+    "find the package or create it if it doesn't exist"
+    (or (find-package name)
+        (make-package name :use '())))
+  (intern "Object" (ensure-package "java.lang"))
+  (intern "String" (ensure-package "java.lang")))
+
+(defmacro do-jarray ((x array) &body body)
+  "jni-based, so not safe and not exported, but used by the implementation"
+  (let ((gcount (gensym))
+        (gi (gensym))
+        (garray (gensym)))
+    `(let* ((,garray ,array)
+            (,gcount (jni:get-array-length ,garray)))
+       (dotimes (,gi ,gcount)
+         (let ((,x (jaref ,garray ,gi)))
+           ,@body)))))
+
+
+(defmacro doenum ((e enum) &body body)
+  "jni-based, so not safe and not exported, but used by the implementation"
+  (let ((genum (gensym)))
+    `(let ((,genum ,enum))
+       (do ()
+           ((not (enumeration.hasmoreelements ,genum)))
+         (let ((,e (enumeration.nextelement ,genum)))
+           ,@body)))))
+
+;probably insufficiently general, works as used here
+(defmacro get-or-init (place init-form)
+  `(or ,place
+       (setf ,place ,init-form)))
+
+;from c.l.l.
+(defmacro case-equal (exp &body clauses)
+  (let ((temp (gensym)))
+    `(let ((,temp ,exp))
+       (cond ,@(mapcar #'(lambda (clause)
+                           (destructuring-bind (keys . clause-forms) clause
+                             (cond ((eq keys 'otherwise)
+                                    `(t ,@clause-forms))
+                                   (t
+                                    (if (atom keys) (setq keys (list keys)))
+                                    `((member ,temp ',keys :test #'equal)
+                                      ,@clause-forms)))))
+                       clauses)))))
+
+;create object. to bootstrap the hierarchy
+(defclass |java.lang|::object. ()
+  ((ref :reader ref :initarg :ref)
+   (lisp-allocated :reader lisp-allocated-p :initarg :lisp-allocated :initform nil))
+  (:documentation "the superclass of all Java typed reference classes"))
+
+(defun get-ref (x)
+  "any function taking an object can be passed a raw java-ref ptr or a typed reference instance.
+Will also convert strings for use as objects"
+  (etypecase x
+    (java-ref x)
+    (|java.lang|::object. (ref x))
+    (string (convert-to-java-string x))
+    (null nil)))
+
+(defun jeq (obj1 obj2)
+  "are these 2 java objects the same object? Note that is not the same as Object.equals()"
+  (is-same-object (get-ref obj1) (get-ref obj2)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;; names and symbols ;;;;;;;;;;;;;;;;;;;;;;;
+#|
+The library does a lot with names and symbols, needing at various times to:
+ - find stuff in Java - full names w/case required
+ - create hopefully non-conflicting packages and member names
+
+When you (def-java-class "java.lang.String") you get a bunch of symbols/names:
+a package named '|java.lang|
+a class-symbol '|java.lang|:STRING. (note the dot and case), 
+   which can usually be used where a typename is required
+   it also serves as the name of the Lisp typed reference class for string
+   its symbol-value is the canonic-class-symbol (see below)
+a canonic-class-symbol '|java.lang|::|String|
+   can be used to reconstitute the full class name
+
+I've started trying to flesh out the notion of a Java class designator, which can either be
+the full class name as a string, the class-symbol, or one of :boolean, :int etc
+|#
+
+(defun canonic-class-symbol (full-class-name)
+  "(\"java.lang.Object\") -> '|java.lang|:|Object|"
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (intern class (ensure-package package))))
+
+(defun class-symbol (full-class-name)
+  "(\"java.lang.Object\") -> '|java.lang|:object."
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (intern (string-upcase (jni::string-append class ".")) (ensure-package package))))
+
+(defun java-class-name (class-sym)
+  "inverse of class-symbol, only valid on class-syms created by def-java-class"
+  (let ((canonic-class-symbol (symbol-value class-sym)))
+    (jni::string-append (package-name (symbol-package canonic-class-symbol))
+                        "." 
+                        canonic-class-symbol)))
+
+(defun member-symbol (full-class-name member-name)
+  "members are defined case-insensitively in case-sensitive packages,
+prefixed by 'classname.' -
+ (member-symbol \"java.lang.Object\" \"toString\") -> '|java.lang|::OBJECT.TOSTRING"
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (intern (string-upcase (jni::string-append class "." member-name)) (ensure-package package))))
+
+(defun constructor-symbol (full-class-name)
+  (member-symbol full-class-name "new"))
+
+(defun get-java-class-ref (canonic-class-symbol)
+  "class-ref is cached on the plist of the canonic class symbol"
+  (get-or-init (get canonic-class-symbol :class-ref)
+               (let ((class-name (jni::string-append (package-name
+                                                 (symbol-package canonic-class-symbol))
+                                                "."
+                                                canonic-class-symbol)))
+                 (try-null (jni-find-class (nsubstitute #\/ #\. class-name))))))
+
+(defun find-java-class (class-sym-or-string)
+  "Given a Java class designator, returns the Java Class object."
+  (ctypecase class-sym-or-string
+    (symbol (case class-sym-or-string
+              (:int integer.type)
+              (:char character.type)
+              (:long long.type)
+              (:float float.type)
+              (:boolean boolean.type)
+              (:short short.type)
+              (:double double.type)
+              (:byte byte.type)
+              (otherwise (get-java-class-ref class-sym-or-string))))
+    (string (get-java-class-ref (canonic-class-symbol class-sym-or-string)))))
+
+;;;;;;;;;;;;;;;;;;;;;; typed reference support ;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+The library maintains a hierarchy of typed reference classes that parallel the
+class hierarchy on the Java side
+new returns a typed reference, but other functions that return objects
+return raw references (for efficiency) 
+make-typed-ref can create fully-typed wrappers when desired
+|#
+
+(defun get-superclass-names (full-class-name)
+  (let* ((class (get-java-class-ref (canonic-class-symbol full-class-name)))
+         (super (class.getsuperclass class))
+         (interfaces (class.getinterfaces class))
+         (supers ()))
+    (do-jarray (i interfaces)
+      (push i supers))
+    ;hmmm - where should the base class go in the precedence list?
+    ;is it more important than the interfaces? this says no
+    (if super
+        (push super supers)
+      (push (find-java-class "java.lang.Object") supers))
+    (setf supers (nreverse supers))
+    ;now we need to fix up order so more derived classes are first
+    ;but don't have a total ordering, so merge one at a time
+    (let (result)
+      (dolist (s supers)
+        (setf result (merge 'list result (list s)
+                            (lambda (x y)
+                              (is-assignable-from x y)))))
+      (mapcar #'class.getname result))))
+#||
+(defun get-superclass-names (full-class-name)
+  (let* ((class (get-java-class-ref (canonic-class-symbol full-class-name)))
+         (super (class.getsuperclass class))
+         (interfaces (class.getinterfaces class))
+         (supers ()))
+    (do-jarray (i interfaces)
+      (push (class.getname i) supers))
+    ;hmmm - where should the base class go in the precedence list?
+    ;is it more important than the interfaces? this says no
+    (if super
+        (push (class.getname super) supers)
+      (push "java.lang.Object" supers))
+    (nreverse supers)))
+||#
+
+(defun ensure-java-class (full-class-name)
+  "walks the superclass hierarchy and makes sure all the classes are fully defined
+ (they may be undefined or just forward-referenced-class)
+caches this has been done on the class-symbol's plist"
+  (let* ((class-sym (class-symbol full-class-name))
+         (class (find-class class-sym nil)))
+    (if (or (eql class-sym '|java.lang|::object.)
+            (get class-sym :ensured))
+        class
+      (let ((supers (get-superclass-names full-class-name)))
+        (dolist (super supers)
+          (ensure-java-class super))
+        (unless (and class (subtypep class 'standard-object))
+          (setf class
+                (ccl:ensure-class class-sym :direct-superclasses (mapcar #'class-symbol supers))))
+        (setf (get class-sym :ensured) t)
+        class))))
+
+(defun ensure-java-hierarchy (class-sym)
+  "Works off class-sym for efficient use in new
+This will only work on class-syms created by def-java-class,
+as it depends upon symbol-value being the canonic class symbol"
+  (unless (get class-sym :ensured)
+    (ensure-java-class (java-class-name class-sym))))
+
+(defun make-typed-ref (java-ref)
+  "Given a raw java-ref, determines the full type of the object
+and returns an instance of a typed reference wrapper"
+  (when java-ref
+    (let ((class (object.getclass (get-ref java-ref))))
+      (if (class.isarray class)
+          (error "typed refs not supported for arrays (yet)")
+        (make-instance (ensure-java-class (class.getname class)) :ref (get-ref java-ref) )))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;; Wrapper Generation ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+In an effort to reduce the volume of stuff generated when wrapping entire libraries,
+the wrappers just generate minimal stubs, which, if and when invoked at runtime,
+complete the work of building thunking closures, so very little code is generated for
+things never called (Java libraries have huge numbers of symbols).
+Not sure if this approach matters, but that's how it works
+|#
+
+(defmacro def-java-class (full-class-name)
+  "Given the package-qualified, case-correct name of a java class, will generate
+wrapper functions for its constructors, fields and methods."
+  (multiple-value-bind (package class) (split-package-and-class full-class-name)
+    (declare (ignore class))
+    (let* ((class-sym (class-symbol full-class-name))
+           (defs
+            (list*
+             `(ensure-package ,package)
+          ;build a path from the simple class symbol to the canonic
+             `(defconstant ,class-sym ',(canonic-class-symbol full-class-name))
+             `(export ',class-sym (symbol-package ',class-sym))
+             `(def-java-constructors ,full-class-name)
+             `(def-java-methods ,full-class-name)
+             `(def-java-fields ,full-class-name)
+             (unless (string= full-class-name "java.lang.Object")
+               (let ((supers (mapcar #'class-symbol (get-superclass-names full-class-name))))
+                 (append (mapcar (lambda (p)
+                                   `(ensure-package ,(package-name p)))
+                                 (remove (symbol-package class-sym)
+                                         (remove-duplicates (mapcar #'symbol-package supers))))
+                         (list `(defclass ,(class-symbol full-class-name)
+                                          ,supers ()))))))))
+      `(locally ,@defs))))
+
+(defun get-jar-classnames (jar-file-name &rest packages)
+  "returns a list of strings, packages should be of the form \"java/lang\"
+  for recursive lookup and \"java/util/\" for non-recursive"
+  (let* ((jar (jarfile.new jar-file-name))
+         (entries (jarfile.entries jar))
+         (names ()))
+    (doenum (e entries)
+      (unless (zipentry.isdirectory e)
+        (let ((ename (zipentry.getname e)))
+          (flet ((matches (package)
+                   (and (eql 0 (search package ename))
+                        (or (not (eql #\/ (schar package (1- (length package))))) ;recursive
+                            (not (find #\/ ename :start (length package))))))) ;non-subdirectory
+            (when (and (eql (search ".class" ename)
+                            (- (length ename) 6)) ;classname
+                       ;don't grab anonymous inner classes
+                       (not (and (find #\$ ename)
+                                 (digit-char-p (schar ename (1+ (position #\$ ename))))))
+                       (some #'matches packages))
+              (push (nsubstitute #\. #\/ (subseq ename 0 (- (length ename) 6)))
+                    names))))))
+    names))
+
+(defun dump-wrapper-defs-to-file (filename classnames)
+  "given a list of classnames (say from get-jar-classnames), writes
+calls to def-java-class to a file"
+  (with-open-file (s filename :direction :output :if-exists :supersede)
+    (dolist (name (sort classnames #'string-lessp))
+      (format s "(def-java-class ~S)~%" name))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;; constructors and new ;;;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+
+Every non-interface class with a public ctor will get;
+  a constructor, classname.new
+  a method defined on make-new, ultimately calling classname.new,
+   specialized on (the value of) it's class-symbol (e.g. canonic sym)
+
+Note that if the ctor is overloaded, there is just one function (taking a rest arg), 
+which handles overload resolution
+
+The new macro expands into a call to make-new
+|#
+
+(defgeneric make-new (class-sym &rest args)
+  (:documentation "Allows for definition of before/after methods on ctors.
+The new macro expands into call to this"))
+
+(defun build-ctor-doc-string (name ctors)
+  (with-output-to-string (s)
+    (dolist (c ctors)
+      (format s "~A(~{~#[~;~A~:;~A,~]~})~%"
+              name
+              (mapcar #'class-name-for-doc (jarray-to-list (constructor.getparametertypes c)))))))
+
+(defmacro def-java-constructors (full-class-name)
+"creates and exports a ctor func classname.new, defines a method of 
+make-new specialized on the class-symbol"
+  (let ((ctor-list (get-ctor-list full-class-name)))
+    (when ctor-list
+      (let ((ctor-sym (constructor-symbol full-class-name))
+            (class-sym (class-symbol full-class-name)))
+        `(locally
+           (defun ,ctor-sym (&rest args)
+             ,(build-ctor-doc-string full-class-name ctor-list)
+             (apply #'install-constructors-and-call ,full-class-name args))
+           (export ',ctor-sym (symbol-package ',ctor-sym))
+           (defmethod make-new ((class-sym (eql ,class-sym)) &rest args)
+             (apply (function ,ctor-sym) args)))))))
+
+(defun get-ctor-list (full-class-name)
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (ctor-array (class.getconstructors class))
+         (ctor-list (jarray-to-list ctor-array)))
+    ctor-list))
+
+(defun install-constructors-and-call (full-class-name &rest args)
+  "initially the constructor symbol for a class is bound to this function,
+when first called it will replace itself with the appropriate direct thunk,
+then call the requested ctor - subsequent calls will be direct"
+  (install-constructors full-class-name)
+  (apply (constructor-symbol full-class-name) args))
+
+(defun install-constructors (full-class-name)
+  (let* ((ctor-list (get-ctor-list full-class-name)))
+    (when ctor-list
+      (setf (fdefinition (constructor-symbol full-class-name))
+            (make-ctor-thunk ctor-list (class-symbol full-class-name))))))
+
+(defun make-ctor-thunk (ctors class-sym)
+  (if (rest ctors) ;overloaded
+      (make-overloaded-ctor-thunk ctors class-sym)
+    (make-non-overloaded-ctor-thunk (first ctors) class-sym)))
+
+(defun make-non-overloaded-ctor-thunk (ctor class-sym)
+  (let ((arg-boxers (get-arg-boxers (constructor.getparametertypes ctor))))
+    (lambda (&rest args)
+      (let ((arg-array (build-arg-array args arg-boxers)))
+        (ensure-java-hierarchy class-sym)
+        (prog1
+            (make-instance class-sym
+                           :ref (constructor.newinstance ctor arg-array)
+                           :lisp-allocated t)
+            ;(constructor.newinstance ctor arg-array)
+          (when arg-array
+            (delete-local-ref arg-array)))))))
+
+(defun make-overloaded-ctor-thunk (ctors class-sym)
+  (let ((thunks (make-ctor-thunks-by-args-length ctors class-sym)))
+    (lambda (&rest args)
+      (let ((fn (cdr (assoc (length args) thunks))))
+        (if fn
+            (apply fn
+                   args)
+          (error "invalid arity"))))))
+
+(defun make-ctor-thunks-by-args-length (ctors class-sym)
+  "returns an alist of thunks keyed by number of args"
+  (let ((ctors-by-args-length (make-hash-table))
+        (thunks-by-args-length nil))
+    (dolist (ctor ctors)
+      (let ((params-len (get-array-length (constructor.getparametertypes ctor))))
+        (push ctor (gethash params-len ctors-by-args-length))))
+    (maphash #'(lambda (args-len ctors)
+                 (push (cons args-len
+                             (if (rest ctors);truly overloaded
+                                 (make-type-overloaded-ctor-thunk ctors class-sym)
+                               ;only one ctor with this number of args
+                               (make-non-overloaded-ctor-thunk (first ctors) class-sym)))
+                       thunks-by-args-length))
+             ctors-by-args-length)
+    thunks-by-args-length))
+
+(defun make-type-overloaded-ctor-thunk (ctors class-sym)
+  "these methods have the same number of args and must be distinguished by type"
+  (let ((thunks (mapcar #'(lambda (ctor)
+                            (list (make-non-overloaded-ctor-thunk ctor class-sym)
+                                  (jarray-to-list (constructor.getparametertypes ctor))))
+                        ctors)))
+    (lambda (&rest args)
+      (block fn
+        (let ((arg-types (get-types-of-args args)))
+          (dolist (thunk-info thunks)
+            (destructuring-bind (thunk param-types) thunk-info
+              (when (is-congruent-type-list param-types arg-types)
+                (return-from fn (apply thunk args)))))
+          (error "No matching constructor"))))))
+
+(defmacro new (class-spec &rest args)
+"new class-spec args
+class-spec -> class-name | (class-name this-name)
+class-name -> \"package.qualified.ClassName\" | classname.
+args -> [actual-arg]* [init-arg-spec]*
+init-arg-spec -> init-arg | (init-arg)
+init-arg -> :settable-field-or-method [params]* value ;note keyword
+            | 
+            .method-name [args]*                      ;note dot
+
+Creates a new instance of class-name, using make-new generic function,
+then initializes it by setting fields or accessors and/or calling member functions
+If this-name is supplied it will be bound to the newly-allocated object and available
+to the init-args"
+  (labels ((mem-sym? (x)
+             (or (keywordp x)
+                 (and (symbolp x) (eql 0 (position #\. (symbol-name x))))))
+           (mem-form? (x)
+             (and (listp x) (mem-sym? (first x))))
+           (mem-init? (x)
+             (or (mem-sym? x) (mem-form? x)))
+           (init-forms (x)
+             (if x
+                 (if (mem-form? (first x))
+                     (cons (first x) (init-forms (rest x)))
+                   (let ((more (member-if #'mem-init? (rest x))))
+                     (cons (ldiff x more) (init-forms more)))))))
+    (let* ((inits (member-if #'mem-init? args))
+           (real-args (ldiff args inits))
+           (class-atom (if (atom class-spec)
+                           class-spec
+                         (first class-spec)))
+           (class-sym (if (symbolp class-atom)
+                          ;(find-symbol (jni::string-append (symbol-name class-atom) "."))
+                          class-atom
+                        (multiple-value-bind (package class) (jni::split-package-and-class class-atom)
+                          (find-symbol (jni::string-append (string-upcase class) ".") package))))
+           (class-name (subseq (symbol-name class-sym) 0 (1- (length (symbol-name class-sym)))))
+           (gthis (gensym)))
+      (flet ((expand-init (x)
+               (if (keywordp (first x)) ;setf field or property
+                   `(setf (,(find-symbol (jni::string-append class-name "." (symbol-name (first x))))
+                           ,gthis ,@(butlast (rest x)))
+                          ,@(last (rest x)))
+                 ;.memfunc
+                 `(,(find-symbol (jni::string-append class-name (symbol-name (first x))))
+                   ,gthis
+                   ,@(rest x)))))
+        `(let* ((,gthis (make-new ,class-sym ,@real-args))
+                ,@(when (listp class-spec)
+                    `((,(second class-spec) ,gthis))))
+           ,@(mapcar #'expand-init (init-forms inits))
+           ,gthis)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#|
+all public fields will get a getter function classname.fieldname and a setter - (setf classname.fieldname)
+instance fields take an first arg which is the instance
+static fields also get a symbol-macro *classname.fieldname*
+|#
+
+(defmacro def-java-fields (full-class-name)
+"fields will get a getter function classname.fieldname and a setter - (setf classname.fieldname)
+instance fields take an first arg which is the instance
+static fields also get a symbol-macro *classname.fieldname*"
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (fields (jarray-to-list (class.getfields class)))
+         (defs nil))
+    (dolist (field fields)
+      (let* ((field-name (field.getname field))
+             (field-sym (member-symbol full-class-name field-name))
+             (is-static (modifier.isstatic (field.getmodifiers field))))
+        (if is-static
+            (let ((macsym (intern (jni::string-append "*" (symbol-name field-sym) "*")
+                                  (symbol-package field-sym))))
+              (push `(defun ,field-sym ()
+                       (install-static-field-and-get ,full-class-name ,field-name))
+                    defs)
+              (push `(defun (setf ,field-sym) (val)
+                       (install-static-field-and-set ,full-class-name ,field-name val))
+                    defs)
+              (push `(export ',field-sym (symbol-package ',field-sym)) defs)
+              (push `(define-symbol-macro ,macsym (,field-sym)) defs)
+              (push `(export ',macsym (symbol-package ',macsym)) defs))
+          (progn
+            (push `(defun ,field-sym (obj)
+                     (install-field-and-get ,full-class-name ,field-name obj))
+                  defs)
+            (push `(defun (setf ,field-sym) (val obj)
+                     (install-field-and-set ,full-class-name ,field-name val obj))
+                  defs)
+            (push `(export ',field-sym (symbol-package ',field-sym)) defs)))))
+    `(locally ,@(nreverse defs))))
+
+(defun install-field-and-get (full-class-name field-name obj)
+  (install-field full-class-name field-name)
+  (funcall (member-symbol full-class-name field-name) obj))
+
+(defun install-field-and-set (full-class-name field-name val obj)
+  (install-field full-class-name field-name)
+  (funcall (fdefinition `(setf ,(member-symbol full-class-name field-name))) val obj))
+
+(defun install-static-field-and-get (full-class-name field-name)
+  (install-field full-class-name field-name)
+  (funcall (member-symbol full-class-name field-name)))
+
+(defun install-static-field-and-set (full-class-name field-name val)
+  (install-field full-class-name field-name)
+  (funcall (fdefinition `(setf ,(member-symbol full-class-name field-name))) val))
+
+(defun install-field (full-class-name field-name)
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (field (class.getfield class field-name))
+         (field-sym (member-symbol full-class-name field-name))
+         (is-static (modifier.isstatic (field.getmodifiers field)))
+         (field-type-name (class.getname (field.gettype field)))
+         (boxer (get-boxer-fn field-type-name))
+         (unboxer (get-unboxer-fn field-type-name)))
+    (if is-static
+        (progn
+          (setf (fdefinition field-sym)
+                (lambda ()
+                  (funcall unboxer (field.get field nil) t)))
+          (setf (fdefinition `(setf ,field-sym))
+                (lambda (arg)
+                  (field.set field nil
+                             (get-ref (if (and boxer (not (boxed? arg)))
+                                          (funcall boxer arg)
+                                        arg)))
+                  arg)))
+      (progn
+        (setf (fdefinition field-sym)
+              (lambda (obj)
+                (funcall unboxer (field.get field (get-ref obj)) t)))
+        (setf (fdefinition `(setf ,field-sym))
+              (lambda (arg obj)
+                (field.set field (get-ref obj)
+                           (get-ref (if (and boxer (not (boxed? arg)))
+                                        (funcall boxer arg)
+                                      arg)))
+                arg))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;; methods ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#|
+defines wrappers for all public methods of the class
+As with ctors, if a method is overloaded a single wrapper is created that handles
+overload resolution.
+The wrappers have the name classname.methodname
+If a method follows the JavaBeans property protocol (i.e. it is called getSomething or isSomething
+and there is a corresponding setSomething, then a (setf classname.methodname) will be defined
+that calls the latter
+|#
+
+(defun class-name-for-doc (class)
+  (let ((name (class.getname class)))
+    (if (class.isarray class)
+        (decode-array-name name)
+      name)))
+
+(defun build-method-doc-string (name methods)
+  (with-output-to-string (s)
+    (dolist (m methods)
+      (format s "~A~A ~A(~{~#[~;~A~:;~A,~]~})~%"
+              (if (modifier.isstatic (method.getmodifiers m))
+                  "static "
+                "")
+              (class.getname (method.getreturntype m))
+              name
+              (mapcar #'class-name-for-doc (jarray-to-list (method.getparametertypes m)))))))
+
+(defmacro def-java-methods (full-class-name)
+  (let ((methods-by-name (get-methods-by-name full-class-name))
+        (defs nil))
+    (maphash (lambda (name methods)
+               (let ((method-sym (member-symbol full-class-name name)))
+                 (push `(defun ,method-sym (&rest args)
+                          ,(build-method-doc-string name methods)
+                          (apply #'install-methods-and-call ,full-class-name ,name args))
+                       defs)
+                 (push `(export ',method-sym (symbol-package ',method-sym))
+                       defs)
+                 ;build setters when finding beans property protocol
+                 (flet ((add-setter-if (prefix)
+                          (when (eql 0 (search prefix name))
+                            (let ((setname (jni::string-append "set" (subseq name (length prefix)))))
+                              (when (gethash setname methods-by-name)
+                                (push `(defun (setf ,method-sym) (val &rest args)
+                                         (progn
+                                           (apply #',(member-symbol full-class-name setname)
+                                                  (append args (list val)))
+                                           val))
+                                      defs))))))
+                   (add-setter-if "get")
+                   (add-setter-if "is"))))
+             methods-by-name)
+    `(locally ,@(nreverse defs))))
+
+(defun install-methods-and-call (full-class-name method &rest args)
+  "initially all the member function symbols for a class are bound to this function,
+when first called it will replace them with the appropriate direct thunks,
+then call the requested method - subsequent calls via those symbols will be direct"
+  (install-methods full-class-name)
+  (apply (member-symbol full-class-name method) args))
+
+(defun decode-array-name (tn)
+  (let ((prim (assoc tn
+                     '(("Z" . "boolean")
+                       ("B" . "byte")
+                       ("C" . "char")
+                       ("S" . "short")
+                       ("I" . "int")
+                       ("J" . "long")
+                       ("F" . "float")
+                       ("D" . "double")
+                       ("V" . "void"))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      (let ((array-depth (count #\[ tn)))
+        (if (= 0 array-depth)
+            (subseq tn 1 (1- (length tn))) ;strip leading L and trailing ;
+          (with-output-to-string (s)
+            (write-string (decode-array-name (subseq tn array-depth)) s)
+            (dotimes (x array-depth)
+              (write-string "[]" s))))))))
+
+(defun jarray-to-list (array)
+  (let (ret)
+    (do-jarray (x array)
+      (push x ret))
+    (nreverse ret)))
+
+(defun get-methods-by-name (full-class-name)
+  "returns an #'equal hashtable of lists of java.lang.Method refs keyed by name"
+  (let* ((class-sym (canonic-class-symbol full-class-name))
+         (class (get-java-class-ref class-sym))
+         (method-array (class.getmethods class))
+         (methods-by-name (make-hash-table :test #'equal)))
+    (do-jarray (method method-array)
+      (push method (gethash (method.getName method) methods-by-name)))
+    methods-by-name))
+
+(defun install-methods (full-class-name)
+  (let ((methods-by-name (get-methods-by-name full-class-name)))
+    (maphash
+     (lambda (name methods)
+       (setf (fdefinition (member-symbol full-class-name name))
+             (make-method-thunk methods)))
+     methods-by-name)))
+
+(defun make-method-thunk (methods)
+  (if (rest methods) ;overloaded
+      (make-overloaded-thunk methods)
+    (make-non-overloaded-thunk (first methods))))
+
+(defun make-non-overloaded-thunk (method)
+  (let ((unboxer-fn (get-unboxer-fn (class.getname (method.getreturntype method))))
+        (arg-boxers (get-arg-boxers (method.getparametertypes method)))
+        (is-static (modifier.isstatic (method.getmodifiers method))))
+    (lambda (&rest args)
+      (let ((arg-array (build-arg-array (if is-static args (rest args)) arg-boxers)))
+        (prog1
+            (funcall unboxer-fn
+                     (method.invoke method
+                                    (if is-static nil (get-ref (first args)))
+                                    arg-array) t)
+          (when arg-array
+            (delete-local-ref arg-array)))))))
+
+(defun make-overloaded-thunk (methods)
+  (let ((thunks (make-thunks-by-args-length methods)))
+    (lambda (&rest args)
+      (let ((fn (cdr (assoc (length args) thunks))))
+        (if fn
+            (apply fn
+                   args)
+          (error "invalid arity"))))))
+
+(defun make-thunks-by-args-length (methods)
+  "returns an alist of thunks keyed by number of args"
+  (let ((methods-by-args-length (make-hash-table))
+        (thunks-by-args-length nil))
+    (dolist (method methods)
+      (let ((is-static (modifier.isstatic (method.getmodifiers method)))
+            (params-len (get-array-length (method.getparametertypes method))))
+        (push method (gethash (if is-static params-len (1+ params-len))
+                              methods-by-args-length))))
+    (maphash #'(lambda (args-len methods)
+                 (push (cons args-len
+                             (if (rest methods);truly overloaded
+                                 (make-type-overloaded-thunk methods)
+                               ;only one method with this number of args
+                               (make-non-overloaded-thunk (first methods))))
+                       thunks-by-args-length))
+             methods-by-args-length)
+    thunks-by-args-length))
+
+(defun make-type-overloaded-thunk (methods)
+  "these methods have the same number of args and must be distinguished by type"
+  (let ((thunks (mapcar #'(lambda (method)
+                            (list (make-non-overloaded-thunk method)
+                                  (modifier.isstatic (method.getmodifiers method))
+                                  (jarray-to-list (method.getparametertypes method))))
+                        methods)))
+    (lambda (&rest args)
+      (block fn
+        (let ((arg-types (get-types-of-args args)))
+          (dolist (thunk-info thunks)
+            (destructuring-bind (thunk is-static param-types) thunk-info
+              (when (is-congruent-type-list param-types (if is-static arg-types (rest arg-types)))
+                (return-from fn (apply thunk args)))))
+          (error "No matching method"))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;; array support ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun jref (array &rest subscripts)
+  "like aref, for Java arrays of non-primitive/reference types, settable"
+  (assert (every #'integerp subscripts))
+  (do*
+       ((sub subscripts (rest sub))
+        (a (get-ref array) (get-ref (array.get a (first sub)))))
+       ((null (rest sub))
+        (array.get a (first sub)))))
+
+(defun (setf jref) (val array &rest subscripts)
+  (assert (every #'integerp subscripts))
+  (do*
+       ((sub subscripts (rest sub))
+        (a (get-ref array) (get-ref (array.get a (first sub)))))
+       ((null (rest sub))
+        (array.set a (first sub) (get-ref val))
+        val)))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro def-refs (&rest types)
+    `(locally
+       ,@(mapcan
+          (lambda (type)
+            (let ((ref-sym (intern (string-upcase (jni::string-append "jref-" (symbol-name type))))))
+              (list 
+               `(defun ,ref-sym (array &rest subscripts)
+                  ,(format nil "like aref, for Java arrays of ~A, settable" (symbol-name type))
+                  (assert (every #'integerp subscripts))
+                  (do*
+                       ((sub subscripts (rest sub))
+                        (a (get-ref array) (get-ref (array.get a (first sub)))))
+                       ((null (rest sub))
+                        (,(intern (string-upcase (jni::string-append "array.get" (symbol-name type))))
+                         a (first sub)))))
+
+               `(defun (setf ,ref-sym) (val array &rest subscripts)
+                  (assert (every #'integerp subscripts))
+                  (do*
+                       ((sub subscripts (rest sub))
+                        (a (get-ref array) (get-ref (array.get a (first sub)))))
+                       ((null (rest sub))
+                        (array.set a (first sub)
+                                   (,(intern (string-upcase (jni::string-append "box-"
+                                                                           (symbol-name type))))
+                                    val))
+                        val))))))
+          types))))
+
+;arrays of primitives have their own accessors
+(def-refs boolean byte char double float int short long)
+
+(defun jlength (array)
+  "like length, for Java arrays"
+  (array.getlength (get-ref array)))
+
+(defgeneric make-new-array (type &rest dimensions)
+  (:documentation "generic function, with methods for all Java class designators")
+  (:method (type &rest dims)
+   (assert (every #'integerp dims))
+   (if (rest dims)
+       (let* ((ndim (length dims))
+              (dim-array (new-int-array ndim)))
+         (dotimes (i ndim)
+           (array.set dim-array i (box-int (nth i dims))))
+         (array.newinstance<java.lang.class-int<>> type dim-array))
+     (array.newinstance<java.lang.class-int> type (first dims)))))
+
+(defmethod make-new-array ((type symbol) &rest dimensions)
+  (apply #'make-new-array (get-java-class-ref type) dimensions))
+
+(defmethod make-new-array ((type string) &rest dimensions)
+  (apply #'make-new-array (find-java-class type) dimensions))
+
+(defmethod make-new-array ((type (eql :char)) &rest dimensions)
+  (apply #'make-new-array character.type dimensions))
+
+(defmethod make-new-array ((type (eql :int)) &rest dimensions)
+  (apply #'make-new-array integer.type dimensions))
+
+(defmethod make-new-array ((type (eql :boolean)) &rest dimensions)
+  (apply #'make-new-array boolean.type dimensions))
+
+(defmethod make-new-array ((type (eql :double)) &rest dimensions)
+  (apply #'make-new-array double.type dimensions))
+
+(defmethod make-new-array ((type (eql :byte)) &rest dimensions)
+  (apply #'make-new-array byte.type dimensions))
+
+(defmethod make-new-array ((type (eql :float)) &rest dimensions)
+  (apply #'make-new-array float.type dimensions))
+
+(defmethod make-new-array ((type (eql :short)) &rest dimensions)
+  (apply #'make-new-array short.type dimensions))
+
+(defmethod make-new-array ((type (eql :long)) &rest dimensions)
+  (apply #'make-new-array long.type dimensions))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;; arg/param helpers ;;;;;;;;;;;;;;;;;;;;;;
+
+(defun get-arg-boxers (param-types)
+  "returns a list with one entry per param, either nil or a function that boxes the arg"
+  (let (ret)
+    (do-jarray (param-type param-types)
+      (push (get-boxer-fn (class.getname param-type))
+            ret))
+    (nreverse ret)))
+
+(defun build-arg-array (args arg-boxers)
+  (when args
+    (let* ((arg-array (new-object-array (length args)
+                                      ;duplication of class-symbol logic
+                                      ;but must be fast
+                                        (get-java-class-ref '|java.lang|::|Object|)
+                                        nil)))
+      (do ((i 0 (incf i))
+           (args args (rest args))
+           (boxers arg-boxers (rest boxers)))
+          ((null args))
+        (let ((arg (first args))
+              (boxer (first boxers)))
+          (setf (jaref arg-array i)
+                (get-ref (if (and boxer (not (boxed? arg)))
+                             (funcall boxer arg)
+                           arg)))))
+      arg-array)))
+
+(defun get-types-of-args (args)
+  (let (ret)
+    (dolist (arg args)
+      (push (infer-box-type arg)
+            ret))
+    (nreverse ret)))
+
+(defun is-congruent-type-list (param-types arg-types)
+  (every #'(lambda (arg-type param-type)
+             (if arg-type
+                 (is-assignable-from arg-type param-type)
+               ;nil was passed - must be boolean or non-primitive target type
+               (or (not (class.isprimitive param-type))
+                   (is-assignable-from boolean.type param-type))))
+         arg-types param-types))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;; argument conversion and boxing ;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun box-string (s)
+"Given a string or symbol, returns reference to a Java string"
+  (local-ref-to-global-ref (convert-to-java-string s)))
+
+(defun unbox-string (ref &optional delete-local)
+  "Given a reference to a Java string, returns a Lisp string" 
+  (declare (ignore delete-local))
+  (convert-from-java-string (get-ref ref)))
+
+(defun get-boxer-fn (class-name)
+  (case-equal class-name
+    ("int" #'box-int)
+    ("boolean" #'box-boolean)
+    ("double" #'box-double)
+    ("java.lang.String" #'convert-to-java-string)
+    ("char" #'box-char)
+    ("byte" #'box-byte)
+    ("float" #'box-float)
+    ("long" #'box-long)
+    ("short" #'box-short)
+    (otherwise nil)))
+
+(defun get-boxer-fn-sym (class-name)
+  (case-equal class-name
+    ("int" 'box-int)
+    ("boolean" 'box-boolean)
+    ("double" 'box-double)
+    ("java.lang.String" 'convert-to-java-string)
+    ("char" 'box-char)
+    ("byte" 'box-byte)
+    ("float" 'box-float)
+    ("long" 'box-long)
+    ("short" 'box-short)
+    ("void" 'box-void)
+    (otherwise 'identity)))
+
+(defun boxed? (x)
+  (or (java-ref-p x)
+      (typep x '|java.lang|::object.)))
+
+(defun infer-box-type (x)
+  (cond
+   ((null x) nil)
+   ((boxed? x) (object.getclass (get-ref x)))
+   ((integerp x) integer.type)
+   ((numberp x) double.type)
+   ((eq x t) boolean.type)
+   ((or (stringp x) (symbolp x))
+    (get-java-class-ref '|java.lang|::|String|))
+   (t (error "can't infer box type"))))
+
+(defun get-unboxer-fn (class-name)
+  (case-equal class-name
+    ("int" #'unbox-int)
+    ("boolean" #'unbox-boolean)
+    ("double" #'unbox-double)
+    ("java.lang.String" #'unbox-string)
+    ("void" #'unbox-void)
+    ("char" #'unbox-char)
+    ("byte" #'unbox-byte)
+    ("float" #'unbox-float)
+    ("long" #'unbox-long)
+    ("short" #'unbox-short)
+    (otherwise  #'unbox-ref)))
+
+(defun get-unboxer-fn-sym (class-name)
+  (case-equal class-name
+    ("int" 'unbox-int)
+    ("boolean" 'unbox-boolean)
+    ("double" 'unbox-double)
+    ("java.lang.String" 'unbox-string)
+    ("void" 'unbox-void)
+    ("char" 'unbox-char)
+    ("byte" 'unbox-byte)
+    ("float" 'unbox-float)
+    ("long" 'unbox-long)
+    ("short" 'unbox-short)
+    (otherwise  'unbox-ref)))
+
+(defun unbox-ref (x &optional delete-local)
+  (declare (ignore delete-local))
+  (local-ref-to-global-ref x))
+
+(defun unbox-void (x &optional delete-local)
+  (declare (ignore x delete-local))
+  nil)
+
+(defun box-void (x)
+  (declare (ignore x))
+  nil)
+
+(defun box-boolean (x)
+  (boolean.new x))
+
+(defun unbox-boolean (obj &optional delete-local)
+  (prog1
+      (boolean.booleanvalue (get-ref obj))
+    (when delete-local (delete-local-ref obj))))
+
+(defun box-byte (x)
+  (assert (integerp x))
+  (byte.new x))
+
+(defun unbox-byte (x &optional delete-local)
+  (prog1
+      (byte.bytevalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-char (x)
+  (character.new x))
+
+(defun unbox-char (x &optional delete-local)
+  (prog1
+      (character.charvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-double (x)
+  (assert (floatp x))
+  (double.new (coerce x 'double-float)))
+
+(defun unbox-double (x &optional delete-local)
+  (prog1
+      (double.doublevalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-float (x)
+  (assert (floatp x))
+  (float.new x))
+
+(defun unbox-float (x &optional delete-local)
+  (prog1
+      (float.floatvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+(defun box-int (x)
+  (assert (integerp x))
+  (integer.new x))
+
+(defun unbox-int (x &optional delete-local)
+  (prog1
+      (integer.intvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+;can't directly construct Long because LW doesn't support long long fli on 32 bit platforms
+(defun box-long (x)
+  (assert (integerp x))
+  (long.valueof (princ-to-string x)))
+
+;here too, can only get an ints worth - aargh
+(defun unbox-long (obj &optional delete-local)
+  (prog1
+      (parse-integer (object.tostring (get-ref obj)))
+    (when delete-local (delete-local-ref obj))))
+
+(defun box-short (x)
+  (assert (integerp x))
+  (short.new x))
+
+(defun unbox-short (x &optional delete-local)
+  (prog1
+      (short.shortvalue (get-ref x))
+    (when delete-local (delete-local-ref x))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;; proxy support ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun proxy-hashcode (proxy)
+  ;use the hashcode of the proxy's class, 
+  ;because hashcode() on the proxy flows through to the invocation handler
+  ;is this rem guaranteed to be a fixnum?
+  (rem (object.hashcode (object.getclass proxy)) most-positive-fixnum))
+
+(defvar *proxy-table* (make-hash-table :test 'jeq :hash-function 'proxy-hashcode))
+
+;(defvar *proxy-list* nil)
+
+(defun store-proxy (proxy method-fn-alist)
+  ;(push (cons proxy method-fn-alist) *proxy-list*)
+  (setf (gethash proxy *proxy-table*) method-fn-alist))
+
+(defun recall-proxy (proxy)
+  ;(cdr (assoc proxy *proxy-list* :test #'jeq))
+  (gethash proxy *proxy-table*))
+
+(defun unregister-proxy (proxy)
+"Stops handling for the proxy and removes references from the Lisp side.
+Make sure it is no longer referenced from Java first!"
+  (remhash proxy *proxy-table*))
+
+(defun invocation-handler (proxy method args)
+  (let* ((method-fn-alist (recall-proxy proxy))
+         (fn (and method-fn-alist (second (assoc (object.tostring method) method-fn-alist
+                                                 :test #'equal)))))
+    (if fn
+        (funcall fn args)
+      (progn
+        ;(throw-new  (find-java-class "java.lang.UnsupportedOperationException")
+        ;            "No function registered in Lisp proxy object")
+        nil))))
+
+(defun enable-java-proxies ()
+  "must be called before any call to new-proxy, and requires jfli.jar be in the classpath"
+  (jni:register-invocation-handler #'invocation-handler))
+
+(defun make-proxy-instance (&rest interface-defs)
+  (let* ((interfaces (mapcar #'first interface-defs))
+         (method-fn-alist (mapcan #'second interface-defs))
+         (len (length interfaces))
+         (iarray (array.newinstance<java.lang.class-int> (get-java-class-ref '|java.lang|::|Class|)
+                                                         len)))
+    (dotimes (x len)
+      (setf (jref iarray x) (nth x interfaces)))
+    (let ((proxy (proxy.newproxyinstance (classloader.getsystemclassloader)
+                                         iarray
+                                         (lispinvocationhandler.new))))
+      (store-proxy proxy method-fn-alist)
+      proxy)))
+
+(defun find-java-class-in-macro (name)
+  (find-java-class
+   (if (symbolp name)
+       (symbol-value name)
+     name)))
+
+(defmacro new-proxy (&rest interface-defs)
+"interface-def -> (interface-name method-defs+)
+interface-name -> \"package.qualified.ClassName\" | classname. (must name a Java interface type)
+method-def -> (method-name arg-defs* body)
+arg-def -> arg-name | (arg-name arg-type)
+arg-type -> \"package.qualified.ClassName\" | classname. | :primitive
+method-name -> symbol | string (matched case-insensitively)
+
+Creates, registers and returns a Java object that implements the supplied interfaces"
+
+  (labels ((process-idefs (idefs)
+             (when idefs
+               (cons (process-idef (first idefs))
+                     (process-idefs (rest idefs)))))
+           (process-idef (idef)
+             (destructuring-bind (interface-name &rest method-defs) idef
+               (let* ((methods (class.getmethods (find-java-class-in-macro interface-name)))
+                      (ret `(list (find-java-class ,interface-name)
+                                  (list ,@(mapcar (lambda (method-def)
+                                                    (process-method-def method-def methods))
+                                                  method-defs)))))
+                 ;check to make sure every function is defined
+                 (do-jarray (method methods)
+                   (let ((mname (object.tostring method)))
+                     (unless (member mname (rest (third ret)) :key #'second :test #'equal)
+                       (warn (format nil "proxy doesn't define:~%~A" mname)))))
+                 ret)))
+           (process-method-def (method-def methods)
+             (destructuring-bind (method-name (&rest arg-defs) &body body) method-def
+               (let ((method (matching-method method-name arg-defs methods))
+                     (gargs (gensym)))
+                 `(list ,(object.tostring method)
+                        (lambda (,gargs)
+                          (,(get-boxer-fn-sym (class.getname (method.getreturntype method)))
+                           (let ,(arg-lets arg-defs
+                                           (jarray-to-list (method.getparametertypes method))
+                                           gargs
+                                           0)
+                             ,@body)))))))
+           (arg-lets (arg-defs params gargs idx)
+             (when arg-defs
+               (let ((arg (first arg-defs))
+                     (param (first params)))
+                 (cons `(,(if (atom arg) arg (first arg))
+                         (,(get-unboxer-fn-sym (class.getname param))
+                          (jref ,gargs ,idx) t))
+                       (arg-lets (rest arg-defs) (rest params) gargs (1+ idx))))))
+           (matching-method (method-name arg-defs methods)
+             (let (match)
+               (do-jarray (method methods)
+                 (when (method-matches method-name arg-defs method)
+                   (if match
+                       (error (format nil "more than one method matches ~A" method-name))
+                     (setf match method))))
+               (or match (error (format nil "no method matches ~A" method-name)))))
+           (method-matches (method-name arg-defs method)
+             (when (string-equal method-name (method.getname method))
+               (let ((params (method.getparametertypes method)))
+                 (when (= (length arg-defs) (jlength params))
+                   (is-congruent arg-defs params)))))
+           (is-congruent (arg-defs params)
+             (every (lambda (arg param)
+                      (or (atom arg) ;no type spec matches anything
+                          (jeq (find-java-class-in-macro (second arg)) param)))
+                    arg-defs (jarray-to-list params))))
+    `(make-proxy-instance ,@(process-idefs interface-defs))))
Index: /branches/new-random/examples/jfli/jni-lw.lisp
===================================================================
--- /branches/new-random/examples/jfli/jni-lw.lisp	(revision 13309)
+++ /branches/new-random/examples/jfli/jni-lw.lisp	(revision 13309)
@@ -0,0 +1,1239 @@
+;    Copyright (c) Rich Hickey. All rights reserved.
+;    The use and distribution terms for this software are covered by the
+;    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+;    which can be found in the file CPL.TXT at the root of this distribution.
+;    By using this software in any fashion, you are agreeing to be bound by
+;    the terms of this license.
+;    You must not remove this notice, or any other, from this software.
+
+#|
+This is a straight wrapper around the JNI API
+Originally I intended to expose this API directly, but it turns out
+that JNI is very sensitive to errors, and, given bad args, wrong types etc
+causes the JVM (and Lisp) to crash, not very much in the spirit of safe, robust,
+interactive development offered by Lisp
+
+So, now this just forms the substrate under jfli, which uses the Reflection API, and is much
+more robust and error tolerant, at some cost in speed I guess.
+
+Bottom line is you shouldn't be using this API directly unless you are extending jfli,
+and then you must take care not to allow bad end-user data to pass through to JNI. 
+
+Caveat emptor.
+
+I have tried to limit LispWorks FLI code to this file.
+|#
+
+(defpackage :jni
+  (:export
+   :*jni-lib-path*
+   :*pvm*
+   :*penv*
+   :register-invocation-handler
+   :create-jvm
+   :JNI-VERSION-1-2
+   :JNI-VERSION-1-4
+   :JNI-OK
+   :java-ref
+   :jvoid :jboolean :jbyte :jchar :jshort :jint :jlong :jfloat :jdouble :jsize
+   :jobject :jclass :jthrowable :jstring :jarray
+   :jboolean-array :jbyte-array :jchar-array :jshort-array :jint-array :jlong-array
+   :jfloat-array :jdouble-array :jobject-array
+   :jfield-id :jmethod-id :jweak
+   :pvm :penv
+   :jvalue
+   :arg-array
+   :jni-native-method :jni-env
+   :java-vm :java-vm-option :jdk-1-1-init-args
+   :jni-get-default-java-vm-init-args :java-vm-inits-args
+   :jni-create-java-vm :jni-get-created-java-vms
+   :try :try-null :try-neg
+   :local-ref-to-global-ref :local-ref-to-string
+   :def-jni-function :def-jni-functions :def-jni-constructor :def-jni-field
+   :jaref :convert-to-java-string :convert-from-java-string :java-ref-p
+   :is-name-of-primitive :split-package-and-class))
+
+(in-package :jni)
+
+(defvar *jni-lib-path*
+#+:MACOSX "/System/Library/Frameworks/JavaVM.framework/JavaVM"
+#+:WIN32 "C:/j2sdk1.4.2_01/jre/bin/client/jvm.dll"
+"Set this to point to your jvm dll prior to calling create-jvm")
+
+(defparameter *pvm* nil)
+(defparameter *penv* nil)
+
+(defparameter *process-envs* nil)
+
+(defconstant JNI-VERSION-1-2 #X10002)
+(defconstant JNI-VERSION-1-4 #X10004)
+(defconstant JNI-OK 0)
+
+(defun load-jni-lib (&optional (libpath *jni-lib-path*))
+  (fli:register-module :jni-lib
+                     :real-name libpath
+                     :connection-style :immediate))
+
+(fli:define-c-typedef pvoid (:ptr :void))
+(fli:define-c-typedef const-char-* (:reference-pass :ef-mb-string))
+(fli:define-c-typedef const-jchar-* (:reference-pass :ef-wc-string))
+(fli:define-foreign-pointer (java-ref (:allow-null t) (:predicate java-ref-p)) pvoid)
+
+(fli:define-c-typedef jvoid :void)
+(fli:define-c-typedef jboolean (:boolean (:unsigned :byte)))
+(fli:define-c-typedef jbyte :byte)
+(fli:define-c-typedef jchar :wchar-t)
+(fli:define-c-typedef jshort :short)
+(fli:define-c-typedef jint :int)
+(fli:define-c-typedef jlong :long-long)
+(fli:define-c-typedef jfloat :float)
+(fli:define-c-typedef jdouble :double)
+(fli:define-c-typedef jsize jint)
+(fli:define-c-typedef jobject java-ref)
+(fli:define-c-typedef jclass java-ref)
+(fli:define-c-typedef jthrowable java-ref)
+(fli:define-c-typedef jstring java-ref)
+(fli:define-c-typedef jarray java-ref)
+(fli:define-c-typedef jboolean-array java-ref)
+(fli:define-c-typedef jbyte-array java-ref)
+(fli:define-c-typedef jchar-array java-ref)
+(fli:define-c-typedef jshort-array java-ref)
+(fli:define-c-typedef jint-array java-ref)
+(fli:define-c-typedef jlong-array java-ref)
+(fli:define-c-typedef jfloat-array java-ref)
+(fli:define-c-typedef jdouble-array java-ref)
+(fli:define-c-typedef jobject-array java-ref)
+(fli:define-c-typedef jfield-id pvoid)
+(fli:define-c-typedef jmethod-id pvoid)
+(fli:define-c-typedef jweak java-ref)
+
+(fli:define-c-typedef pvm (:ptr (:ptr java-vm)))
+(fli:define-c-typedef penv (:ptr (:ptr jni-env)))
+(fli:define-foreign-type pfunc (&rest fargs)
+  `(:ptr (:function ,@fargs)))
+
+(fli:define-c-union jvalue
+  (:z jboolean)
+  (:b jbyte)
+  (:c jchar)
+  (:s jshort)
+  (:i jint)
+  (:j jlong)
+  (:f jfloat)
+  (:d jdouble)
+  (:l jobject))
+
+(fli:define-c-typedef arg-array (:c-array jvalue))
+
+(eval-when (:compile-toplevel)
+  (defun build-struct-entries (name members)
+    (mapcar #'(lambda (member)
+                (if (= 2 (length member)) ;padding or other non-function entry
+                    member
+                  (destructuring-bind (func args ret &key lambda-list) member
+                    (declare (ignore lambda-list))
+                    `(,func (pfunc ,(cons `(:ptr (:ptr ,name))
+                                          (mapcar #'second args))
+                                   ,ret)))))
+            members)))
+
+(eval-when (:compile-toplevel)
+  (defun build-access-functions (name global members)
+    (mapcar #'(lambda (member)
+                (if (= 2 (length member)) ;padding or other non-function entry
+                    ()
+                  (destructuring-bind (func args ret &key lambda-list) member
+                    (let ((thunk (intern (concatenate 'string (symbol-name func) "-thunk")))
+                          (genv (gensym))
+                        ;(func (intern (symbol-name f)))
+                          )
+                      `(locally
+                         (fli:define-foreign-funcallable
+                          ,thunk
+                          ,(cons `(this (:ptr (:ptr ,name))) args)
+                          :result-type ,ret)
+                         (defun ,func ,(if lambda-list
+                                           lambda-list
+                                         (mapcar #'first args))
+                           (let ((,genv ,global))
+                             (,thunk
+                              (fli:foreign-slot-value (fli:dereference ,genv) ',func)
+                              ,genv
+                              ,@(mapcar #'first args))))
+                         (export ',func))))))
+            members)))
+
+(defmacro defvtable (name global &rest members)
+  `(locally
+     (fli:define-c-struct ,name ,@(build-struct-entries name members))
+     ,@(build-access-functions name global members)))
+
+(fli:define-c-struct jni-native-method
+  (name (:ptr :char))
+  (signature (:ptr :char))
+  (fn-ptr pvoid)
+  )
+
+(defun current-env ()
+  "memoizes attach-current-thread per process"
+  (or
+   *penv*
+   (cdr (assoc mp:*current-process* *process-envs*))
+   (multiple-value-bind (ret env) (attach-current-thread)
+     (declare (ignore ret))
+     (push (cons mp:*current-process* env) *process-envs*)
+     env)))
+
+(defvtable jni-env (current-env)
+           (reserved-0 pvoid)                                              ;0
+           (reserved-1 pvoid)                                              ;1
+           (reserved-2 pvoid)                                              ;2
+           (reserved-3 pvoid)                                              ;3
+  ;some mac nonsense requires this non-portable padding, so much for a binary spec
+           #+:MACOSX  (cfm-padding (:foreign-array pvoid (225)))
+           (get-version () jint)                                           ;4
+           (define-class ((name const-char-*)                              ;5
+                          (loader jobject)
+                          (buf (:ptr jbyte))
+                          (len jsize)) jclass) 
+           (jni-find-class ((name const-char-*)) jclass)                       ;6
+           (from-reflected-method ((method jobject)) jmethod-id)           ;7
+           (from-reflected-field ((field jobject)) jfield-id)              ;8
+           (to-reflected-method ((cls jclass)                              ;9
+                                 (method-id jmethod-id)
+                                 (is-static jboolean)) jobject)
+           (get-superclass ((clazz jclass)) jclass)                        ;10
+           (is-assignable-from ((sub jclass)                               ;11
+                                (sup jclass)) jboolean)
+           (to-reflected-field ((cls jclass)                               ;12
+                                (field-id jfield-id)
+                                (is-static jboolean)) jobject)
+           (jni-throw ((obj jthrowable)) jint)                                 ;13
+           (throw-new ((clazz jclass)                                      ;14
+                       (msg const-char-*)) jint)
+           (exception-occurred () jthrowable)                              ;15
+           (exception-describe () :void)                                   ;16
+           (exception-clear () :void)                                      ;17
+           (fatal-error ((msg const-char-*)) :void)                        ;18
+           (push-local-frame ((capacity jint)) jint)                       ;19
+           (pop-local-frame ((result jobject)) jobject)                    ;20
+           (new-global-ref ((lobj jobject)) jobject)                       ;21
+           (delete-global-ref ((gref jobject)) :void)                      ;22
+           (delete-local-ref ((lref jobject)) :void)                       ;23
+           (is-same-object ((obj1 jobject)                                 ;24
+                            (obj2 jobject)) jboolean)
+           (new-local-ref ((ref jobject)) jobject)                         ;25
+           (ensure-local-capacity ((capacity jint)) jint)                  ;26
+           (alloc-object ((clazz jclass)) jobject)                         ;27
+           (new-object pvoid)                                              ;28
+           (new-object-v pvoid)                                            ;29
+           (new-object-a ((clazz jclass)                                   ;30
+                          (method-id jmethod-id)
+                          (args arg-array)) jobject)
+           (get-object-class ((obj jobject)) jclass)                       ;31
+           (is-instance-of ((obj jobject)                                  ;32
+                            (clazz jclass)) jboolean)
+           (get-method-id ((clazz jclass)                                  ;33
+                           (name const-char-*)
+                           (sig const-char-*)) jmethod-id)
+
+           (call-object-method pvoid)                                      ;34
+           (call-object-method-v pvoid)                                    ;35
+           (call-object-method-a ((obj jobject)                            ;36
+                                  (method-id jmethod-id)
+                                  (args arg-array)) jobject)
+           (call-boolean-method pvoid)                                     ;37
+           (call-boolean-method-v pvoid)                                   ;38
+           (call-boolean-method-a ((obj jobject)                           ;39
+                                   (method-id jmethod-id)                  
+                                   (args arg-array)) jboolean)
+           (call-byte-method pvoid)                                        ;40
+           (call-byte-method-v pvoid)                                      ;41
+           (call-byte-method-a ((obj jobject)                              ;42
+                                (method-id jmethod-id)
+                                (args arg-array)) jbyte)
+           (call-char-method pvoid)                                        ;43
+           (call-char-method-v pvoid)                                      ;44
+           (call-char-method-a ((obj jobject)                              ;45
+                                (method-id jmethod-id)
+                                (args arg-array)) jchar)
+           (call-short-method pvoid)                                       ;46
+           (call-short-method-v pvoid)                                     ;47
+           (call-short-method-a ((obj jobject)                             ;48
+                                 (method-id jmethod-id)
+                                 (args arg-array)) jshort)
+           (call-int-method pvoid)                                         ;49
+           (call-int-method-v pvoid)                                       ;50
+           (call-int-method-a ((obj jobject)                               ;51
+                               (method-id jmethod-id)
+                               (args arg-array)) jint)
+           (call-long-method pvoid)                                        ;52
+           (call-long-method-v pvoid)                                      ;53
+           (call-long-method-a ((obj jobject)                              ;54
+                                (method-id jmethod-id)
+                                (args arg-array)) jlong)
+           (call-float-method pvoid)                                       ;55
+           (call-float-method-v pvoid)                                     ;56
+           (call-float-method-a ((obj jobject)                             ;57
+                                 (method-id jmethod-id)
+                                 (args arg-array)) jfloat)
+           (call-double-method pvoid)                                      ;58
+           (call-double-method-v pvoid)                                    ;59
+           (call-double-method-a ((obj jobject)                            ;60
+                                  (method-id jmethod-id)
+                                  (args arg-array)) jdouble)
+           (call-void-method pvoid)                                        ;61
+           (call-void-method-v pvoid)                                      ;62
+           (call-void-method-a ((obj jobject)                              ;63
+                                (method-id jmethod-id)
+                                (args arg-array)) jvoid)
+
+           (call-nonvirtual-object-method pvoid)                           ;64
+           (call-nonvirtual-object-method-v pvoid)                         ;65
+           (call-nonvirtual-object-method-a ((obj jobject)                 ;66
+                                             (clazz jclass)
+                                             (method-id jmethod-id)
+                                             (args arg-array)) jobject)
+           (call-nonvirtual-boolean-method pvoid)                          ;67
+           (call-nonvirtual-boolean-method-v pvoid)                        ;68
+           (call-nonvirtual-boolean-method-a ((obj jobject)                ;69
+                                              (clazz jclass)
+                                              (method-id jmethod-id)
+                                              (args arg-array)) jboolean)
+           (call-nonvirtual-byte-method pvoid)                             ;70
+           (call-nonvirtual-byte-method-v pvoid)                           ;71
+           (call-nonvirtual-byte-method-a ((obj jobject)                   ;72
+                                           (clazz jclass)
+                                           (method-id jmethod-id)
+                                           (args arg-array)) jbyte)
+           (call-nonvirtual-char-method pvoid)                             ;73
+           (call-nonvirtual-char-method-v pvoid)                           ;74
+           (call-nonvirtual-char-method-a ((obj jobject)                   ;75
+                                           (clazz jclass)
+                                           (method-id jmethod-id)
+                                           (args arg-array)) jchar)
+           (call-nonvirtual-short-method pvoid)                            ;76
+           (call-nonvirtual-short-method-v pvoid)                          ;77
+           (call-nonvirtual-short-method-a ((obj jobject)                  ;78
+                                            (clazz jclass)
+                                            (method-id jmethod-id)
+                                            (args arg-array)) jshort)
+           (call-nonvirtual-int-method pvoid)                              ;79
+           (call-nonvirtual-int-method-v pvoid)                            ;80
+           (call-nonvirtual-int-method-a ((obj jobject)                    ;81
+                                          (clazz jclass)
+                                          (method-id jmethod-id)
+                                          (args arg-array)) jint)
+           (call-nonvirtual-long-method pvoid)                             ;82
+           (call-nonvirtual-long-method-v pvoid)                           ;83
+           (call-nonvirtual-long-method-a ((obj jobject)                   ;84
+                                           (clazz jclass)
+                                           (method-id jmethod-id)
+                                           (args arg-array)) jlong)
+           (call-nonvirtual-float-method pvoid)                            ;85
+           (call-nonvirtual-float-method-v pvoid)                          ;86
+           (call-nonvirtual-float-method-a ((obj jobject)                  ;87
+                                            (clazz jclass)
+                                            (method-id jmethod-id)
+                                            (args arg-array)) jfloat)
+           (call-nonvirtual-double-method pvoid)                           ;88
+           (call-nonvirtual-double-method-v pvoid)                         ;89
+           (call-nonvirtual-double-method-a ((obj jobject)                 ;90
+                                             (clazz jclass)
+                                             (method-id jmethod-id)
+                                             (args arg-array)) jdouble)
+           (call-nonvirtual-void-method pvoid)                             ;91
+           (call-nonvirtual-void-method-v pvoid)                           ;92
+           (call-nonvirtual-void-method-a ((obj jobject)                   ;93
+                                           (clazz jclass)
+                                           (method-id jmethod-id)
+                                           (args arg-array)) jvoid)
+           (get-field-id ((clazz jclass)                                   ;94
+                          (name const-char-*)
+                          (sig const-char-*)) jfield-id)
+
+           (get-object-field ((obj jobject)                                ;95
+                              (field-id jfield-id)) jobject)
+           (get-boolean-field ((obj jobject)                               ;96
+                               (field-id jfield-id)) jboolean)  
+           (get-byte-field ((obj jobject)                                  ;97
+                            (field-id jfield-id)) jbyte)  
+           (get-char-field ((obj jobject)                                  ;98
+                            (field-id jfield-id)) jchar)  
+           (get-short-field ((obj jobject)                                 ;99
+                             (field-id jfield-id)) jshort)  
+           (get-int-field ((obj jobject)                                   ;100
+                           (field-id jfield-id)) jint)  
+           (get-long-field ((obj jobject)                                  ;101
+                            (field-id jfield-id)) jlong)  
+           (get-float-field ((obj jobject)                                 ;102
+                             (field-id jfield-id)) jfloat)  
+           (get-double-field ((obj jobject)                                ;103
+                              (field-id jfield-id)) jdouble)  
+
+           (set-object-field ((obj jobject)                                ;104
+                              (field-id jfield-id)
+                              (val jobject)) jvoid)
+           (set-boolean-field ((obj jobject)                               ;105
+                               (field-id jfield-id)
+                               (val jboolean)) jvoid)
+           (set-byte-field ((obj jobject)                                  ;106
+                            (field-id jfield-id)
+                            (val jbyte)) jvoid)
+           (set-char-field ((obj jobject)                                  ;107
+                            (field-id jfield-id)
+                            (val jchar)) jvoid)
+           (set-short-field ((obj jobject)                                 ;108
+                             (field-id jfield-id)
+                             (val jshort)) jvoid)
+           (set-int-field ((obj jobject)                                   ;109
+                           (field-id jfield-id)
+                           (val jint)) jvoid)
+           (set-long-field ((obj jobject)                                  ;110
+                            (field-id jfield-id)
+                            (val jlong)) jvoid)
+           (set-float-field ((obj jobject)                                 ;111
+                             (field-id jfield-id)
+                             (val jfloat)) jvoid)
+           (set-double-field ((obj jobject)                                ;112
+                              (field-id jfield-id)
+                              (val jdouble)) jvoid)
+
+           (get-static-method-id ((clazz jclass)                           ;113
+                                  (name const-char-*)
+                                  (sig const-char-*)) jmethod-id)
+
+           (call-static-object-method pvoid)                               ;114
+           (call-static-object-method-v pvoid)                             ;115
+           (call-static-object-method-a ((clazz jclass)                    ;116
+                                         (method-id jmethod-id)
+                                         (args arg-array)) jobject)
+           (call-static-boolean-method pvoid)                              ;117
+           (call-static-boolean-method-v pvoid)                            ;118
+           (call-static-boolean-method-a ((clazz jclass)                   ;119
+                                          (method-id jmethod-id)
+                                          (args arg-array)) jboolean)
+           (call-static-byte-method pvoid)                                 ;120
+           (call-static-byte-method-v pvoid)                               ;121
+           (call-static-byte-method-a ((clazz jclass)                      ;122
+                                       (method-id jmethod-id)
+                                       (args arg-array)) jbyte)
+           (call-static-char-method pvoid)                                 ;123
+           (call-static-char-method-v pvoid)                               ;124
+           (call-static-char-method-a ((clazz jclass)                      ;125
+                                       (method-id jmethod-id)
+                                       (args arg-array)) jchar)
+           (call-static-short-method pvoid)                                ;126
+           (call-static-short-method-v pvoid)                              ;127
+           (call-static-short-method-a ((clazz jclass)                     ;128
+                                        (method-id jmethod-id)
+                                        (args arg-array)) jshort)
+           (call-static-int-method pvoid)                                  ;129
+           (call-static-int-method-v pvoid)                                ;130
+           (call-static-int-method-a ((clazz jclass)                       ;131
+                                      (method-id jmethod-id)
+                                      (args arg-array)) jint)
+           (call-static-long-method pvoid)                                 ;132
+           (call-static-long-method-v pvoid)                               ;133
+           (call-static-long-method-a ((clazz jclass)                      ;134
+                                       (method-id jmethod-id)
+                                       (args arg-array)) jlong)
+           (call-static-float-method pvoid)                                ;135
+           (call-static-float-method-v pvoid)                              ;136
+           (call-static-float-method-a ((clazz jclass)                     ;137
+                                        (method-id jmethod-id)
+                                        (args arg-array)) jfloat)
+           (call-static-double-method pvoid)                               ;138
+           (call-static-double-method-v pvoid)                             ;139
+           (call-static-double-method-a ((clazz jclass)                    ;140
+                                         (method-id jmethod-id)
+                                         (args arg-array)) jdouble)
+           (call-static-void-method pvoid)                                 ;141
+           (call-static-void-method-v pvoid)                               ;142
+           (call-static-void-method-a ((clazz jclass)                      ;143
+                                       (method-id jmethod-id)
+                                       (args arg-array)) jvoid)
+
+           (get-static-field-id ((clazz jclass)                            ;144
+                                 (name const-char-*)
+                                 (sig const-char-*)) jfield-id)
+
+           (get-static-object-field ((clazz jclass)                        ;145
+                                     (field-id jfield-id)) jobject)
+           (get-static-boolean-field ((clazz jclass)                       ;146
+                                      (field-id jfield-id)) jboolean)
+           (get-static-byte-field ((clazz jclass)                          ;147
+                                   (field-id jfield-id)) jbyte)
+           (get-static-char-field ((clazz jclass)                          ;148
+                                   (field-id jfield-id)) jchar)
+           (get-static-short-field ((clazz jclass)                         ;149
+                                    (field-id jfield-id)) jshort)
+           (get-static-int-field ((clazz jclass)                           ;150
+                                  (field-id jfield-id)) jint)
+           (get-static-long-field ((clazz jclass)                          ;151
+                                   (field-id jfield-id)) jlong)
+           (get-static-float-field ((clazz jclass)                         ;152
+                                    (field-id jfield-id)) jfloat)
+           (get-static-double-field ((clazz jclass)                        ;153
+                                     (field-id jfield-id)) jdouble)
+
+           (set-static-object-field ((clazz jclass)                        ;154
+                                     (field-id jfield-id)
+                                     (val jobject)) jvoid)
+           (set-static-boolean-field ((clazz jclass)                       ;155
+                                      (field-id jfield-id)
+                                      (val jboolean)) jvoid)
+           (set-static-byte-field ((clazz jclass)                          ;156
+                                   (field-id jfield-id)
+                                   (val jbyte)) jvoid)
+           (set-static-char-field ((clazz jclass)                          ;157
+                                   (field-id jfield-id)
+                                   (val jchar)) jvoid)
+           (set-static-short-field ((clazz jclass)                         ;158
+                                    (field-id jfield-id)
+                                    (val jshort)) jvoid)
+           (set-static-int-field ((clazz jclass)                           ;159
+                                  (field-id jfield-id)
+                                  (val jint)) jvoid)
+           (set-static-long-field ((clazz jclass)                          ;160
+                                   (field-id jfield-id)
+                                   (val jlong)) jvoid)
+           (set-static-float-field ((clazz jclass)                         ;161
+                                    (field-id jfield-id)
+                                    (val jfloat)) jvoid)
+           (set-static-double-field ((clazz jclass)                        ;162
+                                     (field-id jfield-id)
+                                     (val jdouble)) jvoid)
+
+           (new-string ((uchars (:reference-pass :ef-wc-string))               ;163
+                        (len jsize)) jstring)
+           (get-string-length ((str jstring)) jsize)                       ;164
+           (get-string-chars ((str jstring)                                ;165
+                              (is-copy (:reference-return jboolean)))
+                             ;(:c-array jchar 1000)
+                             (:ptr :wchar-t)
+                             ;(:ef-wc-string :external-format :unicode)
+                             :lambda-list (str &optional is-copy))
+           (release-string-chars ((str jstring)                            ;166
+                                  (chars (:ptr jchar))) jvoid)
+
+           (new-string-utf ((chars const-char-*)) jstring)                 ;167
+           (get-string-utf-length ((str jstring)) jsize)                   ;168
+           (get-string-utf-chars ((str jstring)                            ;169
+                                  (is-copy (:reference-return jboolean)))
+                                 ;(:c-array :char 1000)
+                                 (:ptr :char)
+                                 :lambda-list (str &optional is-copy))
+           (release-string-utf-chars ((str jstring)                        ;170
+                                      (chars (:ptr :char))) jvoid)
+
+           (get-array-length ((array jarray)) jsize)                       ;171
+           
+           (new-object-array ((len jsize)                                  ;172
+                              (element-type jclass)
+                              (initial-element jobject)) jarray)
+           (get-object-array-element ((array jobject-array)                ;173
+                                      (index jsize)) jobject)
+           (set-object-array-element ((array jobject-array)                ;174
+                                      (index jsize)
+                                      (val jobject)) jvoid)
+
+           (new-boolean-array ((len jsize)) jboolean-array)                ;175
+           (new-byte-array ((len jsize)) jbyte-array)                      ;176
+           (new-char-array ((len jsize)) jchar-array)                      ;177
+           (new-short-array ((len jsize)) jshort-array)                    ;178
+           (new-int-array ((len jsize)) jint-array)                        ;179
+           (new-long-array ((len jsize)) jlong-array)                      ;180
+           (new-float-array ((len jsize)) jfloat-array)                    ;181
+           (new-double-array ((len jsize)) jdouble-array)                  ;182
+
+           (get-boolean-array-elements ((array jboolean-array)             ;183
+                                        (is-copy (:reference-return jboolean)))
+                                       (:ptr jboolean)
+                                       :lambda-list (array &optional is-copy))
+           (get-byte-array-elements ((array jbyte-array)                   ;184
+                                     (is-copy (:reference-return jboolean)))
+                                    (:ptr jbyte)
+                                    :lambda-list (array &optional is-copy))
+           (get-char-array-elements ((array jchar-array)                   ;185
+                                     (is-copy (:reference-return jboolean)))
+                                    (:ptr jchar)
+                                    :lambda-list (array &optional is-copy))
+           (get-short-array-elements ((array jshort-array)                 ;186
+                                      (is-copy (:reference-return jboolean)))
+                                     (:ptr jshort)
+                                     :lambda-list (array &optional is-copy))
+           (get-int-array-elements ((array jint-array)                     ;187
+                                    (is-copy (:reference-return jboolean)))
+                                   (:ptr jint)
+                                   :lambda-list (array &optional is-copy))
+           (get-long-array-elements ((array jlong-array)                   ;188
+                                     (is-copy (:reference-return jboolean)))
+                                    (:ptr jlong)
+                                    :lambda-list (array &optional is-copy))
+           (get-float-array-elements ((array jfloat-array)                 ;189
+                                      (is-copy (:reference-return jboolean)))
+                                     (:ptr jfloat)
+                                     :lambda-list (array &optional is-copy))
+           (get-double-array-elements ((array jdouble-array)               ;190
+                                       (is-copy (:reference-return jboolean)))
+                                      (:ptr jdouble)
+                                      :lambda-list (array &optional is-copy))
+
+           (release-boolean-array-elements ((array jboolean-array)         ;191
+                                            (elems (:ptr jboolean))
+                                            (mode jint)) jvoid
+                                           :lambda-list (array elems &optional (mode 0)))
+           (release-byte-array-elements ((array jbyte-array)               ;192
+                                         (elems (:ptr jbyte))
+                                         (mode jint)) jvoid
+                                        :lambda-list (array elems &optional (mode 0)))
+           (release-char-array-elements ((array jchar-array)               ;193
+                                         (elems (:ptr jchar))
+                                         (mode jint)) jvoid
+                                        :lambda-list (array elems &optional (mode 0)))
+           (release-short-array-elements ((array jshort-array)             ;194
+                                          (elems (:ptr jshort))
+                                          (mode jint)) jvoid
+                                         :lambda-list (array elems &optional (mode 0)))
+           (release-int-array-elements ((array jint-array)                 ;195
+                                        (elems (:ptr jint))
+                                        (mode jint)) jvoid
+                                       :lambda-list (array elems &optional (mode 0)))
+           (release-long-array-elements ((array jlong-array)               ;196
+                                         (elems (:ptr jlong))
+                                         (mode jint)) jvoid
+                                        :lambda-list (array elems &optional (mode 0)))
+           (release-float-array-elements ((array jfloat-array)             ;197
+                                          (elems (:ptr jfloat))
+                                          (mode jint)) jvoid
+                                         :lambda-list (array elems &optional (mode 0)))
+           (release-double-array-elements ((array jdouble-array)           ;198
+                                           (elems (:ptr jdouble))
+                                           (mode jint)) jvoid
+                                          :lambda-list (array elems &optional (mode 0)))
+
+           (get-boolean-array-region ((array jboolean-array)               ;199
+                                      (start jsize)
+                                      (len jsize)
+                                      (buf (:ptr jboolean))) jvoid)
+           (get-byte-array-region ((array jbyte-array)                     ;200
+                                   (start jsize)
+                                   (len jsize)
+                                   (buf (:ptr jbyte))) jvoid)
+           (get-char-array-region ((array jchar-array)                     ;201
+                                   (start jsize)
+                                   (len jsize)
+                                   (buf (:ptr jchar))) jvoid)
+           (get-short-array-region ((array jshort-array)                   ;202
+                                    (start jsize)
+                                    (len jsize)
+                                    (buf (:ptr jshort))) jvoid)
+           (get-int-array-region ((array jint-array)                       ;203
+                                  (start jsize)
+                                  (len jsize)
+                                  (buf (:ptr jint))) jvoid)
+           (get-long-array-region ((array jlong-array)                     ;204
+                                   (start jsize)
+                                   (len jsize)
+                                   (buf (:ptr jlong))) jvoid)
+           (get-float-array-region ((array jfloat-array)                   ;205
+                                    (start jsize)
+                                    (len jsize)
+                                    (buf (:ptr jfloat))) jvoid)
+           (get-double-array-region ((array jdouble-array)                 ;206
+                                     (start jsize)
+                                     (len jsize)
+                                     (buf (:ptr jdouble))) jvoid)
+
+           (set-boolean-array-region ((array jboolean-array)               ;207
+                                      (start jsize)
+                                      (len jsize)
+                                      (buf (:ptr jboolean))) jvoid)
+           (set-byte-array-region ((array jbyte-array)                     ;208
+                                   (start jsize)
+                                   (len jsize)
+                                   (buf (:ptr jbyte))) jvoid)
+           (set-char-array-region ((array jchar-array)                     ;209
+                                   (start jsize)
+                                   (len jsize)
+                                   (buf (:ptr jchar))) jvoid)
+           (set-short-array-region ((array jshort-array)                   ;210
+                                    (start jsize)
+                                    (len jsize)
+                                    (buf (:ptr jshort))) jvoid)
+           (set-int-array-region ((array jint-array)                       ;211
+                                  (start jsize)
+                                  (len jsize)
+                                  (buf (:ptr jint))) jvoid)
+           (set-long-array-region ((array jlong-array)                     ;212
+                                   (start jsize)
+                                   (len jsize)
+                                   (buf (:ptr jlong))) jvoid)
+           (set-float-array-region ((array jfloat-array)                   ;213
+                                    (start jsize)
+                                    (len jsize)
+                                    (buf (:ptr jfloat))) jvoid)
+           (set-double-array-region ((array jdouble-array)                 ;214
+                                     (start jsize)
+                                     (len jsize)
+                                     (buf (:ptr jdouble))) jvoid)
+
+           (register-natives ((clazz jclass)                               ;215
+                              (methods (:ptr jni-native-method))
+                              (n-methods jsize)) jint)
+           (unregister-natives ((clazz jclass)) jint)                      ;216
+           (monitor-enter ((obj jobject)) jint)                            ;217
+           (monitor-exit ((obj jobject)) jint)                             ;218
+
+           (get-java-vm ((vm (:reference-return pvm))) jint                ;219
+                        :lambda-list (&optional (vm t)))
+
+           (get-string-region ((str jstring)                               ;220
+                               (start jsize)
+                               (len jsize)
+                               (buf (:ptr jchar))) jvoid)
+           (get-string-utf-region ((str jstring)                           ;221
+                               (start jsize)
+                               (len jsize)
+                               (buf (:ptr :char))) jvoid)
+
+           (get-primitive-array-critical ((array jarray)                   ;222
+                                          (is-copy (:reference-return jboolean))) pvoid
+                                         :lambda-list (array &optional is-copy))
+           (release-primitive-array-critical ((array jarray)               ;223
+                                            (carray pvoid)
+                                            (mode jint)) jvoid
+                                           :lambda-list (array carray &optional (mode 0)))
+           
+           (get-string-critical ((str jstring)                             ;224
+                                 (is-copy (:reference-return jboolean)))
+                                (:ptr jchar)
+                                :lambda-list (str &optional is-copy))
+           (release-string-critical ((str jstring)                         ;225
+                                     (cstring (:ptr jchar))) jvoid)
+           (new-weak-global-ref ((obj jobject)) jweak)                     ;226
+           (delete-weak-global-ref ((ref jweak)) jvoid)                    ;227
+           (exception-check () jboolean)                                   ;228
+           )
+
+(defun get-pvm ()
+  (or *pvm*
+      (error "JVM not loaded")))
+
+(defvtable java-vm (get-pvm)
+  (reserved-0 pvoid)
+  (reserved-1 pvoid)
+  (reserved-2 pvoid)
+#+:MACOSX  (cfm-padding (:foreign-array pvoid (4)))
+  (destroy-java-vm () jint)
+  (attach-current-thread ((penv (:reference-return penv)) (args pvoid)) jint
+                         :lambda-list (&optional args (penv t)))
+  (detach-current-thread () jint)
+  (get-env ((penv (:reference-return penv)) (interface-id jint)) jint
+           :lambda-list (interface-id &optional (penv t))))
+  
+(fli:define-c-struct java-vm-option
+  (option-string (:ptr :char))
+  (extra-info pvoid))
+
+(fli:define-c-struct jdk-1-1-init-args
+  (version jint)
+  (properties (:ptr (:ptr char)))
+  (check-source jint)
+  (native-stack-size jint)
+  (java-stack-size jint)
+  (min-heap-size jint)
+  (max-heap-size jint)
+  (verify-mode jint)
+  (class-path (:ptr :char))
+  (vprintf pvoid)
+  (exit pvoid)
+  (abort pvoid)
+  (enable-class-gc jint)
+  (enable-verbose-gc jint)
+  (disable-async-gc jint)
+  (reserved-0 jint)
+  (reserved-1 jint)
+  (reserved-2 jint))
+  
+(fli:define-foreign-function (jni-get-default-java-vm-init-args "JNI_GetDefaultJavaVMInitArgs")
+    ((init-args (:ptr jdk-1-1-init-args)))
+  :result-type jint)
+
+(fli:define-c-struct java-vm-init-args
+  (version jint)
+  (n-options jint)
+  (options (:ptr java-vm-option))
+  (ignore-unrecognized jboolean))
+
+(fli:define-foreign-function (jni-create-java-vm "JNI_CreateJavaVM" :source)
+    ((pvm (:reference-return pvm))
+     (penv (:reference-return penv))
+     (vm-args (:ptr java-vm-init-args)))
+  :result-type jint
+  :lambda-list (vm-args &optional (pvm t) (penv t))
+;  :module :jni-lib ;refused on Mac OSX, even though register-module is supported
+  )
+
+(fli:define-foreign-function (jni-get-created-java-vms "JNI_GetCreatedJavaVMs" :source)
+    ((vm-buf (:c-array pvm))
+     (buf-len jsize)
+     (n-vms (:reference-return jsize)))
+  :result-type jint)
+
+(defun cleanup-jni-gref (gref)
+  "set as a special free action to free java classes when no longer used by Lisp"
+  (when (java-ref-p gref)
+    (delete-global-ref gref)))
+
+(defun create-jvm (&rest option-strings)
+  "Creates the JVM, this can only be done once.
+The option strings can be used to control the JVM, esp. the classpath:
+\"-Djava.class.path=/Users/rich/Lisp/jfli.jar\""
+  (when *pvm*
+    (error "JVM already created, can only be started once"))
+  (load-jni-lib)
+  (let ((nopts (length option-strings))
+         (option-array nil))
+    (fli:with-dynamic-foreign-objects ((ia java-vm-init-args))
+      (when option-strings
+        (setf option-array (fli:allocate-dynamic-foreign-object :type 'java-vm-option :nelems nopts))
+        (dotimes (n nopts)
+          (setf (fli:foreign-slot-value (fli:dereference option-array
+                                                         :index n
+                                                         :copy-foreign-object nil) 'option-string)
+                (fli:convert-to-dynamic-foreign-string (nth n option-strings)))))
+      (fli:with-foreign-slots (VERSION N-OPTIONS OPTIONS IGNORE-UNRECOGNIZED) ia
+        (setf version JNI-VERSION-1-4
+              n-options nopts
+              OPTIONS option-array
+              IGNORE-UNRECOGNIZED nil)
+        (multiple-value-bind (ret vm env)
+            (jni-create-java-vm ia)
+          (setf *pvm* vm)
+          (add-special-free-action #'cleanup-jni-gref)
+          (values ret vm env))))))
+
+;this is the FLI side of proxy support
+
+(defvar *invocation-handler* nil
+  "this will be set by jfli:enable-java-proxies to a function of 3 args")
+
+;this will be set as the implementation of a native java function
+(fli:define-foreign-callable ("LispInvocationHandler_invoke" :result-type jobject)
+    ((env penv) (obj jobject) (proxy jobject) (method jobject) (args jobject))
+  (do-invoke env obj proxy method args))
+
+(defun do-invoke (env obj proxy method args)
+  ;(declare (ignore env))
+  (when *invocation-handler*
+    (let ((*penv* env))
+      (prog1
+          (funcall *invocation-handler* proxy method args)
+        ;(jfli::invocation-handler proxy method args)
+        (delete-local-ref obj)))))
+
+(defun register-invocation-handler (invocation-handler)
+  "sets up the Lisp handler and binds the native function - jfli.jar must be in the classpath"
+  (setf *invocation-handler* invocation-handler)
+  (fli:with-dynamic-foreign-objects ((method jni-native-method))
+    (let ((lih (try-null (jni-find-class "com/richhickey/jfli/LispInvocationHandler"))))
+      (fli:with-foreign-slots (name signature fn-ptr) method
+        (setf name (fli:convert-to-dynamic-foreign-string "invoke")
+              signature (fli:convert-to-dynamic-foreign-string "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;")
+              fn-ptr (fli:make-pointer :symbol-name "LispInvocationHandler_invoke")))
+      (register-natives lih method 1))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;the code below provides for the generation of wrapper functions that use JNI to access
+;methods and fields. This low-level interface is unsafe, in that JNI will not 
+;check arg types etc on calls, and therefore should only be used to build safer high-level interfaces
+;i.e. use jfli!
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;found on c.l.l
+(eval-when (:compile-toplevel :load-toplevel)
+(defun replace-substrings (string substring replacement)
+  (declare (optimize (speed 3))
+           (type simple-string string substring replacement))
+  (assert (> (length substring) 0) (substring)
+    "Substring ~A must be of length ~D > 0"
+    substring (length substring))
+  (with-output-to-string (stream)
+    (loop with substring-length = (length substring)
+          for index = 0 then (+ match-index substring-length)
+          for match-index = (search substring string :start2 index)
+          do
+          (write-string string stream :start index :end match-index)
+          (when match-index
+            (write-string replacement stream))
+          while match-index)))
+
+
+(defun local-ref-to-global-ref (lref)
+  (when lref
+    (let ((gref (new-global-ref lref)))
+      (flag-special-free-action gref)
+      (delete-local-ref lref)
+      gref)))
+
+(defun local-ref-to-string (lref)
+  (prog1
+      (convert-from-java-string lref)
+    (delete-local-ref lref)))
+
+(defun convert-to-java-string (s)
+  (when s
+    (try-null (new-string-utf (string s)))))
+
+(defun convert-from-java-string (s)
+  (when s
+    (let ((chars (try-null (get-string-utf-chars s))))
+      (prog1
+          (fli:convert-from-foreign-string chars :external-format :utf-8)
+        (release-string-utf-chars s chars)))))
+
+(defun jaref (array index)
+  (try (get-object-array-element array index)))
+
+(defun (setf jaref) (val array index)
+  (try (set-object-array-element array index val)))
+
+(defun convert-string-arg (s)
+  "if s is stringp, make into java string, else presume it is a java string and return it"
+  ;presumably faster than checking if s is a foreign pointer?
+  (if (or (stringp s) (symbolp s))
+      (convert-to-java-string s)
+    s))
+
+(defun process-arg (val type)
+  (if (string-equal "java.lang.String" type)
+                 `(convert-string-arg ,val)
+                 val))
+
+(defmacro set-arg (args i val type)
+  `(setf (fli:foreign-slot-value (fli:dereference (fli:foreign-array-pointer ,args ,i)
+                                                     :copy-foreign-object nil)
+                                    ',(slot-from-typename type))
+            ,(process-arg val type)))
+
+(defmacro with-arg-array (arg-array-name args &body body)
+  (let ((i -1))
+  `(fli:with-dynamic-foreign-objects ()
+     (let ((,arg-array-name
+            (fli:allocate-dynamic-foreign-object :type
+                                                 '(:c-array jvalue ,(length args)))))
+       ,@(mapcar #'(lambda (arg)
+                     (list 'set-arg arg-array-name (incf i) (first arg) (second arg))) 
+                 args)
+
+       ,@body))))
+
+(defun build-descriptor (params return-type)
+  (string-append
+   "("
+   (apply #'string-append (mapcar #'(lambda (p)
+                                      (type-descriptor-from-typename (second p)))
+                                  params))
+   ")"
+   (type-descriptor-from-typename return-type)))
+
+(defun get-class-and-method-id (class-name method-name descriptor is-static)
+  (let ((class (local-ref-to-global-ref
+                (try-null (jni-find-class class-name)))))
+    (values class
+            (if is-static
+                (try-null (get-static-method-id class method-name descriptor))
+              (try-null (get-method-id class method-name descriptor))))))
+
+
+(defun get-class-and-field-id (class-name field-name descriptor is-static)
+  (let ((class (local-ref-to-global-ref
+                (try-null (jni-find-class class-name)))))
+    (values class
+            (if is-static
+                (try-null (get-static-field-id class field-name descriptor))
+              (try-null (get-field-id class field-name descriptor))))))
+
+(defun is-name-of-primitive (s)
+  (member s '("boolean" "byte" "char" "short" "int" "long" "float" "double" "void")
+          :test #'string-equal))
+
+(defun package-qualified-name (classname packagename)
+  (cond
+   ((is-name-of-primitive (subseq classname 0 (position #\< classname))) classname)
+   ((find #\. classname) classname)     ;already qualified, presumably by another package
+   (t (string-append packagename "." classname)))) 
+
+(defun split-package-and-class (name)
+    (let ((p (position #\. name :from-end t)))
+      (unless p (error "must supply package-qualified classname"))
+      (values (subseq name 0 p)
+              (subseq name (1+ p)))))
+
+(defun slot-from-typename (tn)
+  (let ((prim (assoc tn
+                     '(("boolean" . :z)
+                       ("byte" . :b)
+                       ("char" . :c)
+                       ("short" . :s)
+                       ("int" . :i)
+                       ("long" . :j)
+                       ("float" . :f)
+                       ("double" . :d))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      :l)))
+
+(defun name-component-from-typename (tn)
+  (if (is-name-of-primitive tn)
+      tn
+    "object"))
+
+(defun type-descriptor-from-typename (tn)
+  (let ((prim (assoc tn
+                     '(("boolean" . "Z")
+                       ("byte" . "B")
+                       ("char" . "C")
+                       ("short" . "S")
+                       ("int" . "I")
+                       ("long" . "J")
+                       ("float" . "F")
+                       ("double" . "D")
+                       ("void" . "V"))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      (let ((array-depth (count #\< tn))
+            (tn-with-slashes (replace-substrings tn "." "/")))
+        (if (= 0 array-depth)
+            (string-append "L" tn-with-slashes ";")
+          (with-output-to-string (s)
+            (dotimes (x array-depth)
+              (write-string "[" s))
+            (write-string (type-descriptor-from-typename
+                           (subseq tn-with-slashes 0 (position #\< tn-with-slashes))) s)))))))
+
+;not an exact reciprocal of type-descriptor-from-typename since reflection uses . not / as separator
+(defun typename-from-reflection-type-descriptor (tn)
+  (let ((prim (assoc tn
+                     '(("Z" . "boolean")
+                       ("B" . "byte")
+                       ("C" . "char")
+                       ("S" . "short")
+                       ("I" . "int")
+                       ("J" . "long")
+                       ("F" . "float")
+                       ("D" . "double")
+                       ("V" . "void"))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      (let ((array-depth (count #\[ tn)))
+        (if (= 0 array-depth)
+            (subseq tn 1 (1- (length tn))) ;strip leading L and trailing ;
+          (with-output-to-string (s)
+            (write-string (typename-from-reflection-type-descriptor (subseq tn array-depth)) s)
+            (dotimes (x array-depth)
+              (write-string "<>" s))))))))
+
+(defun method-name-from-typename (tn static)
+    (find-symbol (string-upcase (string-append "call-"
+                                               (if static "static-" "")
+                                             (name-component-from-typename tn)
+                                             "-method-a")) :jni))
+
+(defun field-get-name-from-typename (tn static)
+    (find-symbol (string-upcase (string-append "get-"
+                                               (if static "static-" "")
+                                             (name-component-from-typename tn)
+                                             "-field")) :jni))
+
+(defun field-set-name-from-typename (tn static)
+    (find-symbol (string-upcase (string-append "set-"
+                                               (if static "static-" "")
+                                             (name-component-from-typename tn)
+                                             "-field")) :jni))
+(defun process-return (return-type f &key raw-return)
+  (cond
+   ((or raw-return (is-name-of-primitive return-type)) f)
+   ((string-equal "java.lang.String" return-type) `(local-ref-to-string ,f))
+   (t `(local-ref-to-global-ref ,f))))
+
+;JNI wrapper generators - will create functions in current package
+;this needs more docs
+(defmacro define-java-function (fname class-name return-type method-name params &key static raw-return)
+  (let ((this (gensym))
+        (class (gensym))
+        (id (gensym))
+        (args (gensym)))
+    `(let (,class ,id)
+       (defun ,fname ,(if static (mapcar #'first params)
+                        (cons this (mapcar #'first params)))
+         (when (null ,class)
+           (multiple-value-setq (,class ,id)
+               (get-class-and-method-id ,(replace-substrings class-name "." "/")
+                                        ,method-name ,(build-descriptor params return-type) ,static)))
+         (with-arg-array ,args ,(mapcar #'(lambda (param)
+                                           (list (first param) (second param)))
+                                       params)
+           ,(process-return return-type
+                            `(try (,(method-name-from-typename return-type static)
+                                   ,(if static class this) ,id ,args))
+                            :raw-return raw-return))))))
+
+(defmacro define-java-field (getname class-name field-type field-name &key static)
+  (let ((this (gensym))
+        (class (gensym))
+        (id (gensym))
+        (val (gensym)))
+    `(let (,class ,id)
+       (flet ((load-ids ()
+                (when (null ,class)
+                  (multiple-value-setq (,class ,id)
+                      (get-class-and-field-id ,(replace-substrings class-name "." "/")
+                                              ,field-name ,(type-descriptor-from-typename field-type)
+                                              ,static)))))
+         (defun ,getname ,(if static () (list this))
+           (load-ids)
+           ,(process-return field-type
+                            `(try (,(field-get-name-from-typename field-type static)
+                                   ,(if static class this) ,id))))
+         (defun (setf ,getname) ,(if static (list val) (list this val))
+           (load-ids)
+           (try (,(field-set-name-from-typename field-type static)
+                 ,(if static class this) ,id ,(process-arg val field-type)))
+           ,val)))))
+
+(defmacro define-java-constructor (fname class-name params)
+  (let ((class (gensym))
+        (id (gensym))
+        (args (gensym)))
+    `(let (,class ,id)
+       (defun ,fname ,(mapcar #'first params)
+         (when (null ,class)
+           (multiple-value-setq (,class ,id)
+               (get-class-and-method-id ,(replace-substrings class-name "." "/")
+                                        "<init>" ,(build-descriptor params "void") nil)))
+         (with-arg-array ,args ,(mapcar #'(lambda (param)
+                                           (list (first param) (second param)))
+                                       params)
+           (local-ref-to-global-ref (try-null (new-object-a ,class ,id ,args))))))))
+
+(defun make-func-name (class method params append-param-types)
+  ;probably a format one-liner that can do this
+    (let ((base (string-append class "." method)))
+      (if append-param-types
+          (string-append base
+                         (let ((param-types (mapcar #'second params)))
+                           (if param-types
+                               (string-append "<"
+                                              (reduce #'(lambda (x y)
+                                                          (string-append x "-" y)) param-types)
+                                              ">")
+                             "<>")))
+        base)))
+
+;these just do some name twiddling before calling define-java-xxx above
+(defmacro def-jni-function (package-and-class method params return-typename
+                                               &key static overloaded raw-return)
+  (multiple-value-bind (package class) (split-package-and-class package-and-class)
+    (let* ((fname (make-func-name class method params overloaded))
+           (fsym (read-from-string fname)))
+      `(locally ,(list 'define-java-function
+                     fsym
+                     package-and-class
+                     (package-qualified-name return-typename package)
+                     method
+                     (mapcar #'(lambda (p)
+                                 (list (first p) (package-qualified-name (second p) package)))
+                             params)
+                     :static static :raw-return raw-return)))))
+
+(defmacro def-jni-functions (package-and-class &rest decls)
+  `(locally ,@(mapcar #'(lambda (decl)
+                          (list* 'def-jni-function package-and-class decl))
+                      decls)))
+
+(defmacro def-jni-constructor (package-and-class params &key overloaded)
+  (multiple-value-bind (package class) (split-package-and-class package-and-class)
+    (let* ((fname (make-func-name class "new" params overloaded))
+           (fsym (read-from-string fname)))
+      `(locally ,(list 'define-java-constructor
+                     fsym 
+                     package-and-class 
+                     (mapcar #'(lambda (p)
+                                 (list (first p) (package-qualified-name (second p) package)))
+                             params))))))
+
+(defmacro def-jni-field (package-and-class field typename &key static)
+  (multiple-value-bind (package class) (split-package-and-class package-and-class)
+    (let ((getsym (read-from-string (string-append class "." field
+                                                   (if static "-accessor" ""))))
+          (macsym (read-from-string (string-append class "." field))))
+      `(locally 
+         ,(list 'define-java-field getsym package-and-class
+                (package-qualified-name typename package) field :static static)
+         ,(when static
+            `(define-symbol-macro ,macsym (,getsym)))))))
+
+;we're going to use a little Java to do exception handling below
+(def-jni-function "java.lang.Object"
+                   "toString" () "String")
+
+(def-jni-function "java.lang.reflect.InvocationTargetException"
+                  "getTargetException" () "java.lang.Throwable")
+
+(def-jni-functions "java.lang.Throwable"
+                   ("getMessage" () "String")
+                   ("getStackTrace" () "StackTraceElement<>"))
+
+(defmacro do-jarray ((x array) &body body)
+  (let ((gcount (gensym))
+        (gi (gensym))
+        (garray (gensym)))
+    `(let* ((,garray ,array)
+            (,gcount (get-array-length ,garray)))
+       (dotimes (,gi ,gcount)
+         (let ((,x (jaref ,garray ,gi)))
+           ,@body)))))
+
+#|
+It is critical that if you call a JNI function that might throw an exception that you clear it,
+otherwise the next Java call you make will cause a crash
+|#
+(defun handle-exception ()
+  (let ((e (exception-occurred)))
+    (when (not (fli:null-pointer-p e)) ;allow for safe calling in non-exceptional state
+      (exception-clear)
+      ;if the exception occurs in the reflection target, we really want that
+      (when (is-instance-of e (jni-find-class "java/lang/reflect/InvocationTargetException"))
+        (setf e (invocationtargetexception.gettargetexception e)))
+      (error "~A" (with-output-to-string (s)
+                    (format s "~A~%" (object.tostring e))
+                    (do-jarray (x (throwable.getstacktrace e))
+                      (format s "~A~%" (object.tostring x))))))))
+
+(defun try (result)
+  (if (exception-check)
+      (handle-exception)
+    result))
+
+;JNI will sometimes indicate theere is an exception via a return value
+;so take advantage of that when possible vs. the call back to exception-check
+(defun try-null (result)
+  (if (fli:null-pointer-p result)
+      (handle-exception)
+    result))
+
+(defun try-neg (result)
+  (if (minusp result)
+      (handle-exception)
+    result))
+
+
+)
+
Index: /branches/new-random/examples/jfli/jni.lisp
===================================================================
--- /branches/new-random/examples/jfli/jni.lisp	(revision 13309)
+++ /branches/new-random/examples/jfli/jni.lisp	(revision 13309)
@@ -0,0 +1,1617 @@
+;    Copyright (c) Rich Hickey. All rights reserved.
+;    The use and distribution terms for this software are covered by the
+;    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+;    which can be found in the file CPL.TXT at the root of this distribution.
+;    By using this software in any fashion, you are agreeing to be bound by
+;    the terms of this license.
+;    You must not remove this notice, or any other, from this software.
+
+#|
+This is a straight wrapper around the JNI API
+Originally I intended to expose this API directly, but it turns out
+that JNI is very sensitive to errors, and, given bad args, wrong types etc
+causes the JVM (and Lisp) to crash, not very much in the spirit of safe, robust,
+interactive development offered by Lisp
+
+So, now this just forms the substrate under jfli, which uses the Reflection API, and is much
+more robust and error tolerant, at some cost in speed I guess.
+
+Bottom line is you shouldn't be using this API directly unless you are extending jfli,
+and then you must take care not to allow bad end-user data to pass through to JNI. 
+
+Caveat emptor.
+
+I have tried to limit LispWorks FLI code to this file.
+|#
+
+(defpackage :jni
+  (:export
+   :*jni-lib-path*
+   :*pvm*
+   :*penv*
+   :register-invocation-handler
+   :create-jvm
+   :JNI-VERSION-1-2
+   :JNI-VERSION-1-4
+   :JNI-OK
+   :java-ref
+   :jvoid :jboolean :jbyte :jchar :jshort :jint :jlong :jfloat :jdouble :jsize
+   :jobject :jclass :jthrowable :jstring :jarray
+   :jboolean-array :jbyte-array :jchar-array :jshort-array :jint-array :jlong-array
+   :jfloat-array :jdouble-array :jobject-array
+   :jfield-id :jmethod-id :jweak
+   :pvm :penv
+   :jvalue
+   :arg-array
+   :jni-native-method :jni-env
+   :java-vm :java-vm-option :jdk-1-1-init-args
+   :jni-get-default-java-vm-init-args :java-vm-inits-args
+   :jni-create-java-vm :jni-get-created-java-vms
+   :try :try-null :try-neg
+   :local-ref-to-global-ref :local-ref-to-string
+   :def-jni-function :def-jni-functions :def-jni-constructor :def-jni-field
+   :jaref :convert-to-java-string :convert-from-java-string :java-ref-p
+   :is-name-of-primitive :split-package-and-class
+   ;; Export JNIEnv function names, too
+   :get-array-length :is-same-object :jni-find-class :is-assignable-from
+   :delete-local-ref :new-object-array :new-int-array
+   ))
+
+(in-package :jni)
+
+(defclass java-object (ccl::foreign-standard-object)
+    ())
+
+(ccl::defloadvar *java-object-domain* nil)
+
+(or *java-object-domain*
+    (setq *java-object-domain*
+          (ccl::register-foreign-object-domain :java
+                                               :recognize #'ccl::false
+                                               :class-of (lambda (x)
+                                                           (declare (ignore x))
+                                                           (find-class 'java-object))
+                                               :classp #'ccl::false
+                                               :instance-class-wrapper
+                                               (lambda (x)
+                                                 (declare (ignore x))
+                                                 (ccl::class-own-wrapper
+                                                  (find-class 'java-object)))
+                                               :class-own-wrapper
+                                               #'ccl::false
+                                               :slots-vector #'ccl::false
+                                               :class-ordinal #'ccl::false
+                                               :set-class-ordinal
+                                               #'ccl::false)))
+
+(deftype java-ref () 'java-object)
+
+(defun java-ref-p (x)
+  (and (eql (ccl::typecode x) target::subtag-macptr)
+       (eql (ccl::%macptr-domain x) *java-object-domain*)))
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ccl:use-interface-dir :jni))
+
+(defun string-append (&rest args)
+  (declare (dynamic-extent args))
+  (do* ((a args (cdr a)))
+     ((null a) (apply #'concatenate 'string args))
+    (let* ((arg (car a)))
+      (unless (typep arg 'string)
+        (setf (car a) (string arg))))))
+
+(defvar *jni-lib-path*
+#+:darwin-target "/System/Library/Frameworks/JavaVM.framework/JavaVM"
+#+:win32-target "C:/Program Files/Java/jre6/bin/client/jvm.dll"
+"Set this to point to your jvm dll prior to calling create-jvm")
+
+(ccl::defloadvar *pvm* nil)
+
+;;; Map between lisp and Java booleans
+(eval-when (:compile-toplevel)
+  (declaim (inline jboolean-arg jboolean-result jobject-result jobject-arg)))
+
+(defun jboolean-arg (val)
+  (if (and val (not (eql val #$JNI_FALSE)))
+    #$JNI_TRUE
+    #$JNI_FALSE))
+
+(defun jobject-arg (val)
+  (or val ccl::+null-ptr+))
+
+
+(defun jboolean-result (val)
+  (not (eql val #$JNI_FALSE)))
+
+;;; Might also want to register p for termination (finalization).
+(defun jobject-result (val)
+  (unless (ccl::%null-ptr-p val)
+    (ccl::%set-macptr-domain val *java-object-domain*)
+    val))
+
+
+
+(defconstant JNI-VERSION-1-2 #$JNI_VERSION_1_2)
+(defconstant JNI-VERSION-1-4 #$JNI_VERSION_1_4)
+(defconstant JNI-OK #$JNI_OK)
+
+(defun load-jni-lib (&optional (libpath *jni-lib-path*))
+  (ccl:open-shared-library libpath))
+
+(defun current-env ()
+  "return a pointer to the current thread's JNIEnv, creating that environment
+if necessary."
+  (rlet ((pjnienv :address))
+    (let* ((jvm (get-pvm)))
+      (unless (eql jni-ok
+                   (ff-call (pref jvm #>JavaVM.GetEnv)
+                            :address jvm
+                            :address pjnienv
+                            :jint jni-version-1-4
+                            :jint))
+        ;; On Darwin, attaching the current thread to a JVM instance
+        ;; overwrites the thread's Mach exception ports, which CCL
+        ;; happens to be using.  We can work around this by calling
+        ;; a function in the CCL kernel and having that function
+        ;; call the vm's AttachCurrentThread function and then restore
+        ;; the thread's exception ports before returning.  Yes, that
+        ;; -is- total nonsense.
+        (unless (eql jni-ok
+                     (ff-call
+                      (ccl::%kernel-import target::kernel-import-jvm-init)
+                      :address (pref jvm #>JavaVM.AttachCurrentThread)
+                      :address jvm
+                      :address pjnienv
+                      :address (ccl::%null-ptr)
+                      :jint))
+          (error "Can't attach thread to JVM ~s" jvm)))
+      (let* ((result (pref pjnienv :address)))
+        (ccl::%set-macptr-type result (load-time-value (ccl::foreign-type-ordinal (ccl::foreign-pointer-type-to (ccl::parse-foreign-type #>JNIEnv)))))
+        result))))
+
+
+;;; JNIEnv functions.
+
+(defun process-jnienv-call-args (specs)
+  (ccl::collect ((args))
+    (do* ((specs specs (cddr specs)))
+         ((null specs) (args))
+      (let* ((type (car specs))
+             (valform (cadr specs)))
+        (args type)
+        (case type
+          (:jboolean (args `(jboolean-arg ,valform)))
+          ((:jobject :jclass :jstring :jthrowable :jarray #>jbooleanArray
+                     #>jbyteArray #>jcharArray #>jshortArray #>jintArray
+                     #>jlongArray #>jfloatArray #>jdoubleArray #>jobjectArray)
+           (args `(jobject-arg ,valform)))
+          (t (args valform)))))))
+  
+(defmacro jnienv-call ((slot result-type) &rest specs)
+  ;; We might want to special-case some result-types for finalization.
+  (let* ((env (gensym))
+         (accessor (ccl::escape-foreign-name (concatenate 'string "JNIEnv." slot)))
+         (form
+          `(let* ((,env (current-env)))
+            (ff-call (pref ,env ,accessor) :address ,env ,@(process-jnienv-call-args specs) ,result-type))))
+    (case result-type
+      (:jboolean `(jboolean-result ,form))
+      ((:jobject :jclass :jstring :jthrowable :jarray #>jbooleanArray
+                 #>jbyteArray #>jcharArray #>jshortArray #>jintArray
+                 #>jlongArray #>jfloatArray #>jdoubleArray #>jobjectArray)
+       `(jobject-result ,form))
+      (t form))))
+                 
+
+(defun get-version ()
+  (jnienv-call ("GetVersion" :jint)))
+
+(defun define-class (name loader buf len)
+  (ccl::with-utf-8-cstrs ((cname name))
+    (jnienv-call ("DefineClass" :jclass) 
+                 :address cname
+                 :jobject loader
+                 (:* :jbyte) buf
+                 :jsize len)))
+
+(defun jni-find-class (name)
+  (ccl::with-utf-8-cstrs ((cname name))
+    (jnienv-call ("FindClass" :jclass) :address cname)))
+
+
+(defun from-reflected-method (method)
+  (jnienv-call ("FromReflectedMethod" #>jmethodID) :jobject method))
+
+(defun from-reflected-field (field)
+  (jnienv-call ("FromReflectedField" #>jfieldID) :jobject field))
+
+(defun to-reflected-method (cls method-id is-static)
+  
+  (jnienv-call ("ToReflectedMethod" :jobject)
+               :jclass cls
+               #>jmethodID method-id
+               :jboolean is-static))
+
+(defun get-superclass (sub)
+  (jnienv-call ("GetSuperclass" :jclass) :jclass sub))
+
+(defun is-assignable-from (sub sup)
+  
+  (jnienv-call ("IsAssignableFrom" :jboolean) :jclass sub :jclass sup))
+
+(defun to-reflected-field (cls field-id is-static)
+  
+  (jnienv-call ("ToReflectedField" :jobject)
+               :jclass cls
+               #>jfieldID field-id
+               :jboolean is-static))
+
+(defun jni-throw (obj)
+  (jnienv-call ("Throw" :jint) :jthrowable obj))
+
+(defun throw-new (clazz msg)
+  (ccl::with-utf-8-cstrs ((cmsg msg))
+    (jnienv-call ("ThrowNew" :jint) :jclass clazz :address cmsg)))
+
+(defun exception-occurred ()
+  (jnienv-call ("ExceptionOccurred" :jthrowable)))
+
+(defun exception-describe ()
+  (jnienv-call ("ExceptionDescribe" :void)))
+
+(defun exception-clear ()
+  (jnienv-call ("ExceptionClear" :void)))
+
+(defun fatal-error (msg)
+  (ccl::with-utf-8-cstrs ((cmsg msg))
+    (jnienv-call ("FatalError" :void) :address cmsg)))
+  
+(defun push-local-frame (capacity)
+  (jnienv-call ("PushLocalFrame" :jint) :jint capacity))
+
+(defun pop-local-frame (result)
+  
+  (jnienv-call ("PopLocalFrame" :jobject) :jobject result))
+
+(defun new-global-ref (lobj)
+  (jnienv-call ("NewGlobalRef" :jobject) :jobject lobj))
+
+(defun delete-global-ref (gref)
+  (jnienv-call ("DeleteGlobalRef" :void) :jobject gref))
+  
+(defun delete-local-ref (obj)
+  (jnienv-call ("DeleteLocalRef" :void) :jobject obj))
+
+(defun is-same-object (obj1 obj2)
+  
+  (jnienv-call ("IsSameObject" :jboolean) :jobject obj1 :jobject obj2))
+
+(defun new-local-ref (ref)
+  
+  (jnienv-call ("NewLocalRef" :jobject) :jobject ref))
+
+(defun ensure-local-capacity (capacity)
+  (jnienv-call ("EnsureLocalCapacity" :jint) :jint capacity))
+
+(defun alloc-object (clazz)
+  (jnienv-call ("AllocObject" :jobject) :jclass clazz))
+
+;;; We probably can't get very far with NewObject or NewObjectV, which
+;;; depend on the underlying varargs mechanism.  NewObjectA is more
+;;; tractable.
+
+(defun new-object-a (clazz method-id args)
+  
+  (jnienv-call ("NewObjectA" :jobject) :jclass clazz #>jmethodID method-id (:* :jvalue) args))
+
+(defun get-object-class (obj)
+  (jnienv-call ("GetObjectClass" :jclass) :jobject obj))
+
+(defun is-instance-of (obj clazz)
+  
+  (jnienv-call ("IsInstanceOf" :jboolean) :jobject obj :jclass clazz))
+
+(defun get-method-id (clazz name sig)
+  (ccl::with-utf-8-cstrs ((cname name)
+                          (csig sig))
+    (jnienv-call ("GetMethodID" #>jmethodID)
+                 :jclass clazz :address cname :address csig)))
+
+;;; Likewise for Call*Method and Call*MethodV vs Call*MethodA.
+
+(defun call-object-method-a (obj method-id args)
+  (jnienv-call ("CallObjectMethodA" :jobject)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-boolean-method-a (obj method-id args)
+  
+  (jnienv-call ("CallBooleanMethodA" :jboolean)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-byte-method-a (obj method-id args)
+  (jnienv-call ("CallByteMethodA" :jbyte)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-byte-method-a (obj method-id args)
+  (jnienv-call ("CallCharMethodA" :jchar)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-short-method-a (obj method-id args)
+  (jnienv-call ("CallShortMethodA" :jshort)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-int-method-a (obj method-id args)
+  (jnienv-call ("CallIntMethodA" :jint)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-long-method-a (obj method-id args)
+  (jnienv-call ("CallLongMethodA" :jlong)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-float-method-a (obj method-id args)
+  (jnienv-call ("CallFloatMethodA" :jfloat)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-double-method-a (obj method-id args)
+  (jnienv-call ("CallDoubleMethodA" :jdouble)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-void-method-a (obj method-id args)
+  (jnienv-call ("CallVoidMethodA" :void)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+;;; Nonvirtual method calls.
+(defun call-nonvirtual-object-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualObjectMethodA" :jobject)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-boolean-method-a (obj method-id args)
+  
+  (jnienv-call ("CallNonvirtualBooleanMethodA" :jboolean)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-byte-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualByteMethodA" :jbyte)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-char-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualCharMethodA" :jchar)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-short-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualShortMethodA" :jshort)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+
+(defun call-nonvirtual-int-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualIntMethodA" :jint)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-long-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualLongMethodA" :jlong)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-float-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualFloatMethodA" :jfloat)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-double-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualDoubleMethodA" :jdouble)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-nonvirtual-void-method-a (obj method-id args)
+  (jnienv-call ("CallNonvirtualVoidMethodA" :void)
+               :jobject obj
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun get-field-id (clazz name sig)
+  (ccl::with-utf-8-cstrs ((cname name)
+                          (csig sig))
+    (jnienv-call ("GetFieldID" #>jfieldID)
+                 :jclass clazz
+                 :address cname
+                 :address csig)))
+
+(defun get-object-field (obj field-id)
+  
+  (jnienv-call ("GetObjectField" :jobject)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun get-boolean-field (obj field-id)
+  
+  (jnienv-call ("GetBooleanField" :jboolean)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun get-byte-field (obj field-id)
+  (jnienv-call ("GetByteField" :jbyte)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun get-char-field (obj field-id)
+  (jnienv-call ("GetCharField" :jchar)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun get-short-field (obj field-id)
+  (jnienv-call ("GetShortField" :jshort)
+               :jobject obj
+               #>jfieldID field-id))
+
+
+(defun get-int-field (obj field-id)
+  (jnienv-call ("GetIntField" :jint)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun get-long-field (obj field-id)
+  (jnienv-call ("GetLongField" :jlong)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun get-float-field (obj field-id)
+  (jnienv-call ("GetFloatField" :jfloat)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun get-double-field (obj field-id)
+  (jnienv-call ("GetDoubleField" :jdouble)
+               :jobject obj
+               #>jfieldID field-id))
+
+(defun set-object-field (obj field-id val)
+  (jnienv-call ("SetObjectField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jobject val))
+
+(defun set-boolean-field (obj field-id val)
+  (jnienv-call ("SetBooleanField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jboolean val))
+
+(defun set-byte-field (obj field-id val)
+  (jnienv-call ("SetByteField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jbyte val))
+
+(defun set-char-field (obj field-id val)
+  (jnienv-call ("SetCharField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jchar val))
+
+(defun set-short-field (obj field-id val)
+  (jnienv-call ("SetShortField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jshort val))
+
+(defun set-int-field (obj field-id val)
+  (jnienv-call ("SetIntField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jint val))
+
+(defun set-long-field (obj field-id val)
+  (jnienv-call ("SetLongField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jlong val))
+
+(defun set-float-field (obj field-id val)
+  (jnienv-call ("SetFloatField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jfloat val))
+
+(defun set-double-field (obj field-id val)
+  (jnienv-call ("SetDoubleField" :void)
+               :jobject obj
+               #>jfieldID field-id
+               :jdouble val))
+
+(defun get-static-method-id (clazz name sig)
+  (ccl::with-utf-8-cstrs ((cname name)
+                          (csig sig))
+    (jnienv-call ("GetStaticMethodID" #>jmethodID)
+                 :jclass clazz
+                 :address cname
+                 :address csig)))
+
+(defun call-static-object-method-a (clazz method-id args)
+  
+  (jnienv-call ("CallStaticObjectMethodA" :jobject)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-boolean-method-a (clazz method-id args)
+  
+  (jnienv-call ("CallStaticBooleanMethodA" :jboolean)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-byte-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticByteMethodA" :jbyte)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-char-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticCharMethodA" :jchar)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-short-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticShortMethodA" :jshort)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-int-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticIntMethodA" :jint)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-long-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticLongMethodA" :jlong)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-float-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticFloatMethodA" :jfloat)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-double-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticDoubleMethodA" :jdouble)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun call-static-void-method-a (clazz method-id args)
+  (jnienv-call ("CallStaticVoidMethodA" :void)
+               :jclass clazz
+               #>jmethodID method-id
+               (:* :jvalue) args))
+
+(defun get-static-field-id (clazz name sig)
+  (ccl::with-utf-8-cstrs ((cname name)
+                          (csig sig))
+    (jnienv-call ("GetStaticFieldID" #>jfieldID)
+                 :jclass clazz
+                 :address cname
+                 :address csig)))
+
+(defun get-static-object-field (clazz field-id)
+  (jnienv-call ("GetStaticObjectField" :jobject)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-boolean-field (clazz field-id)
+  
+  (jnienv-call ("GetStaticBooleanField" :jboolean)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-byte-field (clazz field-id)
+  (jnienv-call ("GetStaticByteField" :jbyte)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-char-field (clazz field-id)
+  (jnienv-call ("GetStaticCharField" :jchar)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-short-field (clazz field-id)
+  (jnienv-call ("GetStaticShortField" :jshort)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-int-field (clazz field-id)
+  (jnienv-call ("GetStaticIntField" :jint)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-long-field (clazz field-id)
+  (jnienv-call ("GetStaticLongField" :jlong)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-float-field (clazz field-id)
+  (jnienv-call ("GetStaticFloatField" :jfloat)
+               :jclass clazz
+               #>jfieldID field-id))
+
+(defun get-static-double-field (clazz field-id)
+  (jnienv-call ("GetStaticDoubleField" :jdouble)
+               :jclass clazz
+               #>jfieldID field-id))
+
+
+(defun set-static-object-field (clazz field-id value)
+  (jnienv-call ("SetStaticObjectField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jobject value))
+
+(defun set-static-boolean-field (clazz field-id value)
+  (jnienv-call ("SetStaticBooleanField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jboolean value))
+
+(defun set-static-byte-field (clazz field-id value)
+  (jnienv-call ("SetStaticByteField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jbyte value))
+
+(defun set-static-char-field (clazz field-id value)
+  (jnienv-call ("SetStaticCharField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jchar value))
+
+(defun set-static-short-field (clazz field-id value)
+  (jnienv-call ("SetStaticShortField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jshort value))
+
+(defun set-static-int-field (clazz field-id value)
+  (jnienv-call ("SetStaticIntField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jint value))
+
+(defun set-static-long-field (clazz field-id value)
+  (jnienv-call ("SetStaticLongField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jlong value))
+
+(defun set-static-float-field (clazz field-id value)
+  (jnienv-call ("SetStaticFloatField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jfloat value))
+
+(defun set-static-double-field (clazz field-id value)
+  (jnienv-call ("SetStaticDoubleField" :void)
+               :jclass clazz
+               #>jfieldID field-id
+               :jdouble value))
+
+(defun new-string (unicode len)
+  (ccl::with-native-utf-16-cstrs ((cstring unicode))
+    (jnienv-call ("NewString" :jstring)
+                 (:* :jchar) cstring
+                 :jsize len)))
+
+(defun get-string-length (str)
+  (jnienv-call ("GetStringLength" :jsize)
+               :jstring str))
+
+(defun get-string-chars (str is-copy)
+  (jnienv-call ("GetStringChars" (:* :jchar))
+               :jstring str
+               (:* :jboolean) is-copy))
+
+(defun release-string-chars (str chars)
+  (jnienv-call ("ReleaseStringChars" :void)
+               :jstring str
+               (:* :jchar) chars))
+
+(defun new-string-utf (string)
+  (ccl::with-utf-8-cstrs ((cstring string))
+    (jnienv-call ("NewStringUTF" :jstring)
+                 :address cstring)))
+
+(defun get-string-utf-chars (str)
+  (rlet ((is-copy :jboolean))
+    (let* ((chars (jnienv-call ("GetStringUTFChars" (:* :char))
+                               :jstring str
+                               (:* :jboolean) is-copy)))
+      (values chars  (pref is-copy :jboolean)))))
+
+(defun release-string-utf-chars (str chars)
+  (jnienv-call ("ReleaseStringUTFChars" :void)
+               :jstring str
+               (:* :char) chars))
+
+(defun get-array-length (array)
+  (jnienv-call ("GetArrayLength" :jsize)
+               :jArray array))
+
+(defun new-object-array (len clazz init)
+  (jnienv-call ("NewObjectArray" #>jobjectArray)
+               :jsize len
+               :jclass clazz
+               :jobject init))
+
+(defun get-object-array-element (array index)
+  (jnienv-call ("GetObjectArrayElement" :jobject)
+               #>jobjectArray array
+               :jsize index))
+
+(defun set-object-array-element (array index val)
+  (jnienv-call ("SetObjectArrayElement" :void)
+               #>jobjectArray array
+               :jsize index
+               :jobject val))
+
+(defun new-boolean-array (len)
+  (jnienv-call ("NewBooleanArray" #>jbooleanArray)
+               :jsize len))
+
+(defun new-byte-array (len)
+  (jnienv-call ("NewByteArray" #>jbyteArray)
+               :jsize len))
+
+(defun new-char-array (len)
+  (jnienv-call ("NewCharArray" #>jcharArray)
+               :jsize len))
+
+(defun new-short-array (len)
+  (jnienv-call ("NewShortArray" #>jshortArray)
+               :jsize len))
+
+(defun new-int-array (len)
+  (jnienv-call ("NewIntArray" #>jintArray)
+               :jsize len))
+
+(defun new-long-array (len)
+  (jnienv-call ("NewLongArray" #>jlongArray)
+               :jsize len))
+
+(defun new-float-array (len)
+  (jnienv-call ("NewFloatArray" #>jfloatArray)
+               :jsize len))
+
+(defun new-double-array (len)
+  (jnienv-call ("NewDoubleArray" #>jdoubleArray)
+               :jsize len))
+
+
+(defun get-boolean-array-elements (array is-copy)
+  (jnienv-call ("GetBooleanArrayElements" (:* :jboolean))
+               #>jbooleanArray array
+               (:* :jboolean) is-copy))
+
+(defun get-byte-array-elements (array is-copy)
+  (jnienv-call ("GetByteArrayElements" (:* :jbyte))
+               #>jbyteArray array
+               (:* :jboolean) is-copy))
+
+(defun get-char-array-elements (array is-copy)
+  (jnienv-call ("GetCharArrayElements" (:* :jchar))
+               #>jcharArray array
+               (:* :jboolean) is-copy))
+
+(defun get-short-array-elements (array is-copy)
+  (jnienv-call ("GetShortArrayElements" (:* :jshort))
+               #>jshortArray array
+               (:* :jboolean) is-copy))
+
+(defun get-int-array-elements (array is-copy)
+  (jnienv-call ("GetIntArrayElements" (:* :jint))
+               #>jintArray array
+               (:* :jboolean) is-copy))
+
+(defun get-long-array-elements (array is-copy)
+  (jnienv-call ("GetLongArrayElements" (:* :jlong))
+               #>jlongArray array
+               (:* :jboolean) is-copy))
+
+(defun get-float-array-elements (array is-copy)
+  (jnienv-call ("GetFloatArrayElements" (:* :jfloat))
+               #>jfloatArray array
+               (:* :jboolean) is-copy))
+
+(defun get-double-array-elements (array is-copy)
+  (jnienv-call ("GetDoubleArrayElements" (:* :jdouble))
+               #>jdoubleArray array
+               (:* :jboolean) is-copy))
+
+(defun release-boolean-array-elements (array elems mode)
+  (jnienv-call ("ReleaseBooleanArrayElements" :void)
+               #>jbooleanArray array
+               (:* jboolean) elems
+               :jint mode))
+
+(defun release-byte-array-elements (array elems mode)
+  (jnienv-call ("ReleaseByteArrayElements" :void)
+               #>jbyteArray array
+               (:* jbyte) elems
+               :jint mode))
+
+(defun release-char-array-elements (array elems mode)
+  (jnienv-call ("ReleaseCharArrayElements" :void)
+               #>jcharArray array
+               (:* jchar) elems
+               :jint mode))
+
+(defun release-short-array-elements (array elems mode)
+  (jnienv-call ("ReleaseShortArrayElements" :void)
+               #>jshortArray array
+               (:* jshort) elems
+               :jint mode))
+
+(defun release-int-array-elements (array elems mode)
+  (jnienv-call ("ReleaseIntArrayElements" :void)
+               #>jintArray array
+               (:* jint) elems
+               :jint mode))
+
+(defun release-long-array-elements (array elems mode)
+  (jnienv-call ("ReleaseLongArrayElements" :void)
+               #>jlongArray array
+               (:* jlong) elems
+               :jint mode))
+
+(defun release-float-array-elements (array elems mode)
+  (jnienv-call ("ReleaseFloatArrayElements" :void)
+               #>jfloatArray array
+               (:* jfloat) elems
+               :jint mode))
+
+(defun release-double-array-elements (array elems mode)
+  (jnienv-call ("ReleaseDoubleArrayElements" :void)
+               #>jdoubleArray array
+               (:* jdouble) elems
+               :jint mode))
+
+
+(defun get-boolean-array-region (array start len buf)
+  (jnienv-call ("GetBooleanArrayRegion" :void)
+               #>jbooleanArray array
+               :jsize start
+               :jsize len
+               (:* :jboolean) buf))
+
+(defun get-byte-array-region (array start len buf)
+  (jnienv-call ("GetByteArrayRegion" :void)
+               #>jbyteArray array
+               :jsize start
+               :jsize len
+               (:* :jbyte) buf))
+
+(defun get-char-array-region (array start len buf)
+  (jnienv-call ("GetCharArrayRegion" :void)
+               #>jcharArray array
+               :jsize start
+               :jsize len
+               (:* :jchar) buf))
+
+(defun get-short-array-region (array start len buf)
+  (jnienv-call ("GetShortArrayRegion" :void)
+               #>jshortArray array
+               :jsize start
+               :jsize len
+               (:* :jshort) buf))
+
+(defun get-int-array-region (array start len buf)
+  (jnienv-call ("GetIntArrayRegion" :void)
+               #>jintArray array
+               :jsize start
+               :jsize len
+               (:* :jint) buf))
+
+(defun get-long-array-region (array start len buf)
+  (jnienv-call ("GetLongArrayRegion" :void)
+               #>jlongArray array
+               :jsize start
+               :jsize len
+               (:* :jlong) buf))
+
+(defun get-float-array-region (array start len buf)
+  (jnienv-call ("GetFloatArrayRegion" :void)
+               #>jfloatArray array
+               :jsize start
+               :jsize len
+               (:* :jfloat) buf))
+
+(defun get-double-array-region (array start len buf)
+  (jnienv-call ("GetDoubleArrayRegion" :void)
+               #>jdoubleArray array
+               :jsize start
+               :jsize len
+               (:* :jdouble) buf))
+
+(defun set-boolean-array-region (array start len buf)
+  (jnienv-call ("SetBooleanArrayRegion" :void)
+               #>jbooleanArray array
+               :jsize start
+               :jsize len
+               (:* :jboolean) buf))
+
+(defun set-byte-array-region (array start len buf)
+  (jnienv-call ("SetByteArrayRegion" :void)
+               #>jbyteArray array
+               :jsize start
+               :jsize len
+               (:* :jbyte) buf))
+
+(defun set-char-array-region (array start len buf)
+  (jnienv-call ("SetCharArrayRegion" :void)
+               #>jcharArray array
+               :jsize start
+               :jsize len
+               (:* :jchar) buf))
+
+(defun set-short-array-region (array start len buf)
+  (jnienv-call ("SetShortArrayRegion" :void)
+               #>jshortArray array
+               :jsize start
+               :jsize len
+               (:* :jshort) buf))
+
+(defun set-int-array-region (array start len buf)
+  (jnienv-call ("SetIntArrayRegion" :void)
+               #>jintArray array
+               :jsize start
+               :jsize len
+               (:* :jint) buf))
+
+(defun set-long-array-region (array start len buf)
+  (jnienv-call ("SetLongArrayRegion" :void)
+               #>jlongArray array
+               :jsize start
+               :jsize len
+               (:* :jlong) buf))
+
+(defun set-float-array-region (array start len buf)
+  (jnienv-call ("SetFloatArrayRegion" :void)
+               #>jfloatArray array
+               :jsize start
+               :jsize len
+               (:* :jfloat) buf))
+
+(defun set-double-array-region (array start len buf)
+  (jnienv-call ("SetDoubleArrayRegion" :void)
+               #>jdoubleArray array
+               :jsize start
+               :jsize len
+               (:* :jdouble) buf))
+
+
+(defun register-natives (clazz methods nmethods)
+  (jnienv-call ("RegisterNatives":jint)
+               :jclass clazz
+               (:* #>JNINativeMethod) methods
+               :jint nmethods))
+
+
+(defun unregister-natives (clazz)
+  (jnienv-call ("UnregisterNatives" :jint)
+               :jclass clazz))
+
+(defun monitor-enter (obj)
+  (jnienv-call ("MonitorEnter" :jint)
+               :jobject obj))
+
+(defun monitor-exit (obj)
+  (jnienv-call ("MonitorExit" :jint)
+               :jobject obj))
+
+(defun get-java-vm (vm)
+  (jnienv-call ("GetJavaVM" :jint)
+               (:* (:* #>JavaVM)) vm))
+
+(defun get-string-region (str start len buf)
+  (jnienv-call ("GetStringRegion" :void)
+               :jstring str
+               :jsize start
+               :jsize len
+               (:* :jchar) buf))
+
+(defun get-string-utf-region (str start len buf)
+  (jnienv-call ("GetStringUTFRegion" :void)
+               :jstring str
+               :jsize start
+               :jsize len
+               (:* :char) buf))
+
+(defun get-primitive-array-critical (array is-copy)
+  (jnienv-call ("GetPrimitiveArrayCritical" (:* :void))
+               :jarray array
+               (:* :jboolean) is-copy))
+
+(defun release-primitive-array-critical(jarray carray mode)
+  (jnienv-call ("ReleasePrimitiveArrayCritical" :void)
+               :jarray jarray
+               (:* :void) carray
+               :jint mode))
+
+(defun get-string-critical (string is-copy)
+  (jnienv-call ("GetStringCritical" (:* :jchar))
+               :jstring string
+               (:* :jboolean) is-copy))
+
+(defun release-string-critical (string cstring)
+  (jnienv-call ("ReleaseStringCritical" :void)
+               :jstring string
+               (:* :jchar) cstring))
+
+(defun new-weak-global-ref (obj)
+  (jnienv-call ("NewWeakGlobalRef" :jweak)
+               :jobject obj))
+
+(defun delete-weak-global-ref (ref)
+  (jnienv-call ("DeleteWeakGlobalRef" :void)
+               :jweak ref))
+
+(defun exception-check ()
+  (jnienv-call ("ExceptionCheck" :jboolean)))
+               
+
+(defun new-direct-byte-buffer (address capacity)
+  (jnienv-call ("NewDirectByteBuffer" :jobject)
+               :address address
+               :jlong capacity))
+
+(defun get-direct-buffer-address (buf)
+  (jnienv-call ("GetDirectBufferAddress" :address)
+               :jobject buf))
+
+(defun get-direct-buffer-capacity (buf)
+  (jnienv-call ("GetDirectBufferCapacity" :jlong)
+               :jobject buf))
+
+;;; End of jnienv functions.  (Finally.)
+
+(defun get-pvm ()
+  (or *pvm*
+      (error "JVM not loaded")))
+
+#+later
+(defun cleanup-jni-gref (gref)
+  "set as a special free action to free java classes when no longer used by Lisp"
+  (when (java-ref-p gref)
+    (delete-global-ref gref)))
+
+(defun create-jvm (&rest args)
+  (declare (dynamic-extent args))
+  "Creates the JVM, this can only be done once.
+The option strings can be used to control the JVM, esp. the classpath:
+\"-Djava.class.path=/Users/rich/Lisp/jfli.jar\""
+  (when *pvm*
+    (error "JVM already created, can only be started once"))
+  (load-jni-lib)
+  (ccl::call-with-string-vector
+   (lambda (argv)
+     (let* ((nargs (length args)))
+       (rlet ((initargs :<J>ava<VMI>nit<A>rgs)
+              (env (:* :<JNIE>nv))
+              (vm (:* :<J>ava<VM>)))
+         (%stack-block ((options (* nargs (ccl::record-length :<J>ava<VMO>ption))))
+           (do* ((i 0 (1+ i))
+                 (p options (%inc-ptr p (ccl::record-length :<J>ava<VMO>ption))))
+                ((= i nargs))
+             (setf (pref p :<J>ava<VMO>ption.option<S>tring)
+                   (paref argv (:* (:* :char)) i)))
+           (setf (pref initargs :<J>ava<VMI>nit<A>rgs.version) #$JNI_VERSION_1_4
+                 (pref initargs :<J>ava<VMI>nit<A>rgs.n<O>ptions) nargs
+                 (pref initargs :<J>ava<VMI>nit<A>rgs.options) options
+                 (pref initargs :<J>ava<VMI>nit<A>rgs.ignore<U>nrecognized) #$JNI_TRUE)
+           ;; In Darwin, JNI_CreateJavaVM will clobber the calling thread's
+           ;; Mach exception ports, despite the fact that CCL is using them.
+           ;; To work around this, call a function in the lisp kernel which
+           ;; restores the thread's exception ports after calling
+           ;; JNI_CreateJavaVM for us.
+           (let* ((result
+                   (ff-call (ccl::%kernel-import target::kernel-import-jvm-init)
+                            :address (foreign-symbol-address "JNI_CreateJavaVM")
+                            :address vm
+                            :address env
+                            :address initargs
+                            :int)))
+             (if (>= result 0)
+               (progn
+                 (setq *pvm* (%get-ptr vm))
+                 (values result (%get-ptr vm) (%get-ptr env)))
+               (error "Can't create Java VM: result = ~d" result)))))))
+   args))
+
+
+;;;this is the FLI side of proxy support
+
+(defvar *invocation-handler* nil
+  "this will be set by jfli:enable-java-proxies to a function of 3 args")
+
+
+
+;;;this will be set as the implementation of a native java function
+
+(defcallback |LispInvocationHandler_invoke|
+    (:address env :jobject obj :jobject proxy :jobject method :jobject args :jobject)
+  (jobject-result obj)
+  (jobject-result proxy)
+  (jobject-result method)
+  (jobject-result args)
+  (jobject-arg 
+   (do-invoke env obj proxy method args)))
+
+
+(defun do-invoke (env obj proxy method args)
+  (declare (ignore env))                ;it's not like we're on another thread
+  (when *invocation-handler*
+    (prog1
+        (funcall *invocation-handler* proxy method args)
+      ;;(jfli::invocation-handler proxy method args)
+      (delete-local-ref obj))))
+
+(defun try (result)
+  (if (exception-check)
+      (handle-exception)
+    result))
+
+;JNI will sometimes indicate theere is an exception via a return value
+;so take advantage of that when possible vs. the call back to exception-check
+(defun try-null (result)
+  (if (or (null result) (ccl:%null-ptr-p result))
+      (handle-exception)
+    result))
+
+(defun register-invocation-handler (invocation-handler)
+  "sets up the Lisp handler and binds the native function - jfli.jar must be in the classpath"
+  (setf *invocation-handler* invocation-handler)
+  (rlet ((method #>JNINativeMethod))
+    (let ((lih (try-null (jni-find-class "com/richhickey/jfli/LispInvocationHandler"))))
+      (with-cstrs ((name "invoke")
+                   (signature "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"))
+        (setf (pref method #>JNINativeMethod.name) name
+              (pref method #>JNINativeMethod.signature) signature
+              (pref method #>JNINativeMethod.fnPtr) |LispInvocationHandler_invoke|)
+      (register-natives lih method 1)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;the code below provides for the generation of wrapper functions that use JNI to access
+;methods and fields. This low-level interface is unsafe, in that JNI will not 
+;check arg types etc on calls, and therefore should only be used to build safer high-level interfaces
+;i.e. use jfli!
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;found on c.l.l
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defun replace-substrings (string substring replacement)
+  (declare (optimize (speed 3))
+           (type simple-string string substring replacement))
+  (assert (> (length substring) 0) (substring)
+    "Substring ~A must be of length ~D > 0"
+    substring (length substring))
+  (with-output-to-string (stream)
+    (loop with substring-length = (length substring)
+          for index = 0 then (+ match-index substring-length)
+          for match-index = (search substring string :start2 index)
+          do
+          (write-string string stream :start index :end match-index)
+          (when match-index
+            (write-string replacement stream))
+          while match-index)))
+
+
+(defun local-ref-to-global-ref (lref)
+  (when lref
+    (let ((gref (new-global-ref lref)))
+      #+laster
+      (flag-special-free-action gref)
+      (delete-local-ref lref)
+      gref)))
+
+(defun local-ref-to-string (lref)
+  (prog1
+      (convert-from-java-string lref)
+    (delete-local-ref lref)))
+
+(defun convert-to-java-string (s)
+  (when s
+    (try-null (new-string-utf (string s)))))
+
+(defun convert-from-java-string (s)
+  (when s
+    (let ((chars (try-null (get-string-utf-chars s))))
+      (prog1
+          (ccl::%get-utf-8-cstring chars)
+        (release-string-utf-chars s chars)))))
+
+(defun jaref (array index)
+  (try (get-object-array-element array index)))
+
+(defun (setf jaref) (val array index)
+  (try (set-object-array-element array index val)))
+
+(defun convert-string-arg (s)
+  "if s is stringp, make into java string, else presume it is a java string and return it"
+  ;presumably faster than checking if s is a foreign pointer?
+  (if (or (stringp s) (symbolp s))
+      (convert-to-java-string s)
+    s))
+
+(defun process-arg (val type)
+  (if (string-equal "java.lang.String" type)
+    `(convert-string-arg ,val)
+    `(or ,val ccl::+null-ptr+)))
+
+(defmacro set-arg (args i val type)
+  `(setf (pref (paref ,args (:* :jvalue) ,i)
+          ,(jvalue-accessor-from-typename type))
+    ,(process-arg val type)))
+
+(defmacro with-arg-array (arg-array-name args &body body)
+  (let ((i -1))
+  `(%stack-block ((,arg-array-name (*  ,(length args) (ccl::record-length :jvalue))))
+       ,@(mapcar #'(lambda (arg)
+                     (list 'set-arg arg-array-name (incf i) (first arg) (second arg))) 
+                 args)
+
+       ,@body)))
+
+(defun build-descriptor (params return-type)
+  (string-append
+   "("
+   (apply #'string-append (mapcar #'(lambda (p)
+                                      (type-descriptor-from-typename (second p)))
+                                  params))
+   ")"
+   (type-descriptor-from-typename return-type)))
+
+(defun get-class-and-method-id (class-name method-name descriptor is-static)
+  (let ((class (local-ref-to-global-ref
+                (try-null (jni-find-class class-name)))))
+    (values class
+            (if is-static
+                (try-null (get-static-method-id class method-name descriptor))
+              (try-null (get-method-id class method-name descriptor))))))
+
+
+(defun get-class-and-field-id (class-name field-name descriptor is-static)
+  (let ((class (local-ref-to-global-ref
+                (try-null (jni-find-class class-name)))))
+    (values class
+            (if is-static
+                (try-null (get-static-field-id class field-name descriptor))
+              (try-null (get-field-id class field-name descriptor))))))
+
+(defun is-name-of-primitive (s)
+  (member s '("boolean" "byte" "char" "short" "int" "long" "float" "double" "void")
+          :test #'string-equal))
+
+(defun package-qualified-name (classname packagename)
+  (cond
+   ((is-name-of-primitive (subseq classname 0 (position #\< classname))) classname)
+   ((find #\. classname) classname)     ;already qualified, presumably by another package
+   (t (string-append packagename "." classname)))) 
+
+(defun split-package-and-class (name)
+    (let ((p (position #\. name :from-end t)))
+      (unless p (error "must supply package-qualified classname"))
+      (values (subseq name 0 p)
+              (subseq name (1+ p)))))
+
+(defun slot-from-typename (tn)
+  (let ((prim (assoc tn
+                     '(("boolean" . :z)
+                       ("byte" . :b)
+                       ("char" . :c)
+                       ("short" . :s)
+                       ("int" . :i)
+                       ("long" . :j)
+                       ("float" . :f)
+                       ("double" . :d))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      :l)))
+
+(defun jvalue-accessor-from-typename (tn)
+  (let ((prim (assoc tn
+                     '(("boolean" . :jvalue.z)
+                       ("byte" . :jvalue.b)
+                       ("char" . :jvalue.c)
+                       ("short" . :jvalue.s)
+                       ("int" . :jvalue.i)
+                       ("long" . :jvalue.j)
+                       ("float" . :jvalue.f)
+                       ("double" . :jvalue.d))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      :jvalue.l)))
+
+(defun name-component-from-typename (tn)
+  (if (is-name-of-primitive tn)
+      tn
+    "object"))
+
+(defun type-descriptor-from-typename (tn)
+  (let ((prim (assoc tn
+                     '(("boolean" . "Z")
+                       ("byte" . "B")
+                       ("char" . "C")
+                       ("short" . "S")
+                       ("int" . "I")
+                       ("long" . "J")
+                       ("float" . "F")
+                       ("double" . "D")
+                       ("void" . "V"))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      (let ((array-depth (count #\< tn))
+            (tn-with-slashes (replace-substrings tn "." "/")))
+        (if (= 0 array-depth)
+            (string-append "L" tn-with-slashes ";")
+          (with-output-to-string (s)
+            (dotimes (x array-depth)
+              (write-string "[" s))
+            (write-string (type-descriptor-from-typename
+                           (subseq tn-with-slashes 0 (position #\< tn-with-slashes))) s)))))))
+
+;not an exact reciprocal of type-descriptor-from-typename since reflection uses . not / as separator
+(defun typename-from-reflection-type-descriptor (tn)
+  (let ((prim (assoc tn
+                     '(("Z" . "boolean")
+                       ("B" . "byte")
+                       ("C" . "char")
+                       ("S" . "short")
+                       ("I" . "int")
+                       ("J" . "long")
+                       ("F" . "float")
+                       ("D" . "double")
+                       ("V" . "void"))
+                     :test #'string-equal)))
+    (if prim
+        (rest prim)
+      (let ((array-depth (count #\[ tn)))
+        (if (= 0 array-depth)
+            (subseq tn 1 (1- (length tn))) ;strip leading L and trailing ;
+          (with-output-to-string (s)
+            (write-string (typename-from-reflection-type-descriptor (subseq tn array-depth)) s)
+            (dotimes (x array-depth)
+              (write-string "<>" s))))))))
+
+(defun method-name-from-typename (tn static)
+    (find-symbol (string-upcase (string-append "call-"
+                                               (if static "static-" "")
+                                             (name-component-from-typename tn)
+                                             "-method-a")) :jni))
+
+(defun field-get-name-from-typename (tn static)
+    (find-symbol (string-upcase (string-append "get-"
+                                               (if static "static-" "")
+                                             (name-component-from-typename tn)
+                                             "-field")) :jni))
+
+(defun field-set-name-from-typename (tn static)
+    (find-symbol (string-upcase (string-append "set-"
+                                               (if static "static-" "")
+                                             (name-component-from-typename tn)
+                                             "-field")) :jni))
+(defun process-return (return-type f &key raw-return)
+  (cond
+   ((or raw-return (is-name-of-primitive return-type)) f)
+   ((string-equal "java.lang.String" return-type) `(local-ref-to-string ,f))
+   (t `(local-ref-to-global-ref ,f))))
+
+;JNI wrapper generators - will create functions in current package
+;this needs more docs
+(defmacro define-java-function (fname class-name return-type method-name params &key static raw-return)
+  (let ((this (gensym))
+        (class (gensym))
+        (id (gensym))
+        (args (gensym)))
+    `(let (,class ,id)
+       (defun ,fname ,(if static (mapcar #'first params)
+                        (cons this (mapcar #'first params)))
+         (when (null ,class)
+           (multiple-value-setq (,class ,id)
+               (get-class-and-method-id ,(replace-substrings class-name "." "/")
+                                        ,method-name ,(build-descriptor params return-type) ,static)))
+         (with-arg-array ,args ,(mapcar #'(lambda (param)
+                                           (list (first param) (second param)))
+                                       params)
+           ,(process-return return-type
+                            `(try (,(method-name-from-typename return-type static)
+                                   ,(if static class this) ,id ,args))
+                            :raw-return raw-return))))))
+
+(defmacro define-java-field (getname class-name field-type field-name &key static)
+  (let ((this (gensym))
+        (class (gensym))
+        (id (gensym))
+        (val (gensym)))
+    `(let (,class ,id)
+       (flet ((load-ids ()
+                (when (null ,class)
+                  (multiple-value-setq (,class ,id)
+                      (get-class-and-field-id ,(replace-substrings class-name "." "/")
+                                              ,field-name ,(type-descriptor-from-typename field-type)
+                                              ,static)))))
+         (defun ,getname ,(if static () (list this))
+           (load-ids)
+           ,(process-return field-type
+                            `(try (,(field-get-name-from-typename field-type static)
+                                   ,(if static class this) ,id))))
+         (defun (setf ,getname) ,(if static (list val) (list this val))
+           (load-ids)
+           (try (,(field-set-name-from-typename field-type static)
+                 ,(if static class this) ,id ,(process-arg val field-type)))
+           ,val)))))
+
+(defmacro define-java-constructor (fname class-name params)
+  (let ((class (gensym))
+        (id (gensym))
+        (args (gensym)))
+    `(let (,class ,id)
+       (defun ,fname ,(mapcar #'first params)
+         (when (null ,class)
+           (multiple-value-setq (,class ,id)
+               (get-class-and-method-id ,(replace-substrings class-name "." "/")
+                                        "<init>" ,(build-descriptor params "void") nil)))
+         (with-arg-array ,args ,(mapcar #'(lambda (param)
+                                           (list (first param) (second param)))
+                                       params)
+           (local-ref-to-global-ref (try-null (new-object-a ,class ,id ,args))))))))
+
+(defun make-func-name (class method params append-param-types)
+  ;probably a format one-liner that can do this
+    (let ((base (string-append class "." method)))
+      (if append-param-types
+          (string-append base
+                         (let ((param-types (mapcar #'second params)))
+                           (if param-types
+                               (string-append "<"
+                                              (reduce #'(lambda (x y)
+                                                          (string-append x "-" y)) param-types)
+                                              ">")
+                             "<>")))
+        base)))
+
+;these just do some name twiddling before calling define-java-xxx above
+(defmacro def-jni-function (package-and-class method params return-typename
+                                               &key static overloaded raw-return)
+  (multiple-value-bind (package class) (split-package-and-class package-and-class)
+    (let* ((fname (make-func-name class method params overloaded))
+           (fsym (read-from-string fname)))
+      `(locally ,(list 'define-java-function
+                     fsym
+                     package-and-class
+                     (package-qualified-name return-typename package)
+                     method
+                     (mapcar #'(lambda (p)
+                                 (list (first p) (package-qualified-name (second p) package)))
+                             params)
+                     :static static :raw-return raw-return)))))
+
+(defmacro def-jni-functions (package-and-class &rest decls)
+  `(locally ,@(mapcar #'(lambda (decl)
+                          (list* 'def-jni-function package-and-class decl))
+                      decls)))
+
+(defmacro def-jni-constructor (package-and-class params &key overloaded)
+  (multiple-value-bind (package class) (split-package-and-class package-and-class)
+    (let* ((fname (make-func-name class "new" params overloaded))
+           (fsym (read-from-string fname)))
+      `(locally ,(list 'define-java-constructor
+                     fsym 
+                     package-and-class 
+                     (mapcar #'(lambda (p)
+                                 (list (first p) (package-qualified-name (second p) package)))
+                             params))))))
+
+(defmacro def-jni-field (package-and-class field typename &key static)
+  (multiple-value-bind (package class) (split-package-and-class package-and-class)
+    (let ((getsym (read-from-string (string-append class "." field
+                                                   (if static "-accessor" ""))))
+          (macsym (read-from-string (string-append class "." field))))
+      `(locally 
+         ,(list 'define-java-field getsym package-and-class
+                (package-qualified-name typename package) field :static static)
+         ,(when static
+            `(define-symbol-macro ,macsym (,getsym)))))))
+
+;we're going to use a little Java to do exception handling below
+(def-jni-function "java.lang.Object"
+                   "toString" () "String")
+
+(def-jni-function "java.lang.reflect.InvocationTargetException"
+                  "getTargetException" () "java.lang.Throwable")
+
+(def-jni-functions "java.lang.Throwable"
+                   ("getMessage" () "String")
+                   ("getStackTrace" () "StackTraceElement<>"))
+
+(defmacro do-jarray ((x array) &body body)
+  (let ((gcount (gensym))
+        (gi (gensym))
+        (garray (gensym)))
+    `(let* ((,garray ,array)
+            (,gcount (get-array-length ,garray)))
+       (dotimes (,gi ,gcount)
+         (let ((,x (jaref ,garray ,gi)))
+           ,@body)))))
+
+#||
+It is critical that if you call a JNI function that might throw an exception that you clear it,
+otherwise the next Java call you make will cause a crash
+||#
+
+(defun handle-exception ()
+  (let ((e (exception-occurred)))
+    (when (not (ccl:%null-ptr-p e)) ;allow for safe calling in non-exceptional state
+      (exception-clear)
+      ;if the exception occurs in the reflection target, we really want that
+      (when (is-instance-of e (jni-find-class "java/lang/reflect/InvocationTargetException"))
+        (setf e (invocationtargetexception.gettargetexception e)))
+      (error "~A" (with-output-to-string (s)
+                    (format s "~A~%" (object.tostring e))
+                    (do-jarray (x (throwable.getstacktrace e))
+                      (format s "~A~%" (object.tostring x))))))))
+
+
+
+
+
+(defun try-neg (result)
+  (if (minusp result)
+      (handle-exception)
+    result))
+
+
+)
+
+
Index: /branches/new-random/examples/mswin.lisp
===================================================================
--- /branches/new-random/examples/mswin.lisp	(revision 13309)
+++ /branches/new-random/examples/mswin.lisp	(revision 13309)
@@ -0,0 +1,207 @@
+;;;-*-Mode: LISP; Package: ccl -*-
+;;;
+;;;   Copyright (C) 2008, Clozure Associates and contributors
+;;;   This file is part of OpenMCL.  
+;;;
+;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with OpenMCL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; This is very preliminary and very much a work-in-progress.
+
+(in-package "CL-USER")
+
+;;; This is a simple demo that creates an almost totally uninteresting
+;;; window and does limited event handling.  It's intended to excercise
+;;; Clozure CL's FFI a little and to serve as a proof of the concept
+;;; that Windows GUI programming is possible.  It's not necessarily
+;;; a good way to create or manage a window or a good way to structure
+;;; a program or much of anything else ...
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (open-shared-library "user32.dll"))
+
+;;; This function is called by Windows to process events ("messages")
+;;; for a given class of window.  (It's specified when the window
+;;; class is registered; see below.)  Note that - on Win32 -most
+;;; Windows API functions and the functions that they call follow an
+;;; unusual calling sequence in which the callee pops its arguments
+;;; off of the stack before returning; this is indicated by the
+;;; keyword :DISCARD-STACK-ARGS in the DEFCALLBACK argument list.
+
+(defcallback simple-wndproc (;; See comment above.
+                             :discard-stack-args
+                             ;: the window to which this message is directed,
+                             ;; of a null pointer if the message isn't
+                             ;; directed to a window:
+                             #>HWND hwnd
+                             ;; An integer which idenfifies the type
+                             ;; of message, usually matching a
+                             ;; predefined constant whose name starts
+                             ;; with WM_ :
+                             #>UINT msg
+                             ;; A parameter to the message.  In 16-bit
+                             ;; Windows, this was a 16-bit integer and
+                             ;; therefore couldn't convey much information.
+                             ;; On 32 and 64-bit Windows, it's a 32-bit
+                             ;; integer and therefore -could- contain
+                             ;; more information, but usually doesn't ...
+                             ;; Its value (and how it should be interpreted)
+                             ;; depend on the value of "msg":
+                             #>WPARAM wparam
+                             ;; Another parameter, as wide as a pointer
+                             ;; is (and sometimes used as a pointer.):
+                             #>LPARAM lparam
+                             ;; The callback function should return a
+                             ;; pointer-sized (32/64-bit) integer: 0
+                             ;; to indicate that the message was
+                             ;; handled, and non-zero otherwise.
+                             #>LRESULT)
+  ;; At a bare minimum, a windows message procedure (wndproc) like this
+  ;; one should handle the the WM_DESTROY message; if we actually did
+  ;; any drawing of the window's content, we should handle WM_PAINT
+  ;; messages, ...
+  ;; There are a fairly large number of other message constants that
+  ;; we could receive; if we don't want to handle them ourselves - and
+  ;; in this simple example, we don't - we can just pass all of our
+  ;; arguments to the default window procedure and return whatever it
+  ;; returns.
+  #+debug (format t "~& hwnd = ~s, msg = ~s, wparam = ~s, lparam = ~x"
+                  hwnd msg wparam lparam)
+  (cond ((eql msg #$WM_DESTROY)
+         ;; If there were resources attached to the window - bitmaps,
+         ;; etc. - we'd want to free them here.  Posting a quit message
+         ;; (WM_QUIT) will arrange that we receive a WM_QUIT messsage
+         ;; in very short order.
+         (#_PostQuitMessage 0)          ; exit status 0: all is well.
+         0)                             ; and we'll return 0
+        (t
+         ;; In a more realistic example, we'd handle more cases here.
+         ;; Like many functions that deal with characters and strings,
+         ;; DefWindowProc is actually implemented as two functions:
+         ;; DefWindowProcA is the "ANSI" (8-bit character) version,
+         ;; and DefWindowProcW is the wide-character (UTF-16LE)
+         ;; version.
+         (#_DefWindowProcA hwnd msg wparam lparam))))
+                             
+
+;;; Register a named window class. ("class" in this sense has nothing to
+;;; do with CLOS or any other object system: windows of the same class
+;;; share a common window procedure callback and other attributes, which
+;;; we define here.)
+;;; If the registration attempt is succesful, it'll return an "atom"
+;;; (a small integer that identifies the registered class); otherwise,
+;;;  it returns 0.
+(defvar *simple-window-class-atom* nil)
+
+(defun register-simple-window-class (class-name)
+  ;; We'll use an ANSI version that accepts a simple C string as the
+  ;; class name.
+  (or *simple-window-class-atom*
+      (setq *simple-window-class-atom*
+            (with-cstrs ((cname class-name))
+              (rlet ((wc #>WNDCLASSEX)) ; an "extended" WNDCLASS structure
+                (setf (pref wc #>WNDCLASSEX.cbSize) (ccl::record-length #>WNDCLASSEX)
+                      (pref wc #>WNDCLASSEX.style) (logior #$CS_HREDRAW #$CS_VREDRAW)
+                      (pref wc #>WNDCLASSEX.lpfnWndProc) simple-wndproc
+                      (pref wc #>WNDCLASSEX.cbClsExtra) 0
+                      (pref wc #>WNDCLASSEX.cbWndExtra) 0
+                      (pref wc #>WNDCLASSEX.hInstance) (#_GetModuleHandleA (%null-ptr))
+                      (pref wc #>WNDCLASSEX.hIcon) (%null-ptr)
+                      (pref wc #>WNDCLASSEX.hCursor) (#_LoadCursorA (%null-ptr) #$IDC_ARROW)
+                      (pref wc #>WNDCLASSEX.hbrBackground) (#_GetStockObject #$WHITE_BRUSH)
+                      (pref wc #>WNDCLASSEX.lpszMenuName) (%null-ptr)
+                      (pref wc #>WNDCLASSEX.lpszClassName) cname
+                      (pref wc #>WNDCLASSEX.hIconSm) (%null-ptr))
+                (let* ((atom (#_RegisterClassExA wc)))
+                  (if (eql 0 atom)
+                    (let* ((err (#_GetLastError)))
+                      (error "Error registering windows class ~s: ~d (~a)" class-name
+                             err
+                             (ccl::%windows-error-string err))))
+                  atom))))))
+
+;;; Main function: register a window class, make an instance of that
+;;; class, handle events for that window until it's closed.
+(defun make-simple-ms-window ()
+  (let* ((class-atom (register-simple-window-class "very-simple")))
+    (with-cstrs ((title "Look! A window!"))
+      (let* ((hwnd (#_CreateWindowExA 0 ;extended style
+                                      (%int-to-ptr class-atom) ; class name/atom
+                                      title 
+                                      (logior #$WS_EX_COMPOSITED #$WS_OVERLAPPEDWINDOW) ; style
+                                      #$CW_USEDEFAULT ; x pos
+                                      #$CW_USEDEFAULT ; y pos
+                                      #$CW_USEDEFAULT ; width
+                                      #$CW_USEDEFAULT ; height
+                                      (%null-ptr) ;parent window
+                                      (%null-ptr) ; menu handle
+                                      (#_GetModuleHandleA (%null-ptr)) ; us
+                                      (%null-ptr)))) ;info for MDI parents/children
+        (when (%null-ptr-p hwnd)
+          (error "CreateWindow failed: ~a" (ccl::%windows-error-string (#_GetLastError))))
+	;; Depending on how the lisp process was created, the first call
+	;; to #_ShowWindow in that process might ignore its argument
+	;; (and instead use an argument specified in the STARTUPINFO
+	;; structure passed to #_CreateProcess.)  SLIME under FSF Emacs
+	;; runs the lisp with this flag set, and it's possible to waste
+	;; a week or two trying to track this down.  (Trust me.)
+        (#_ShowWindow hwnd #$SW_SHOW)
+	;; In case the parent process said to ignore #_ShowWindow's argument
+	;; the first time it's called, call #_ShowWindow again.  This seems
+	;; to be harmless, if a little strange ...
+        (#_ShowWindow hwnd #$SW_SHOW)
+        (#_UpdateWindow hwnd)
+        ;; Loop, fetching messages, translating virtual key events
+        ;; into character-oriented events and dispatching each
+        ;; message until #_GetMessageA returns 0.
+        (rlet ((msg #>MSG))
+          (do* ((result (#_GetMessageA msg
+                                       (%null-ptr) ; for any window created by this thread)
+                                       0
+                                       0)
+                        (#_GetMessageA msg (%null-ptr) 0 0)))
+               ((eql 0 result)          ; message was WM_QUIT
+                (pref msg #>MSG.wParam))
+	    (cond ((< result 0)
+		   (let* ((error (#_GetLastError)))
+		     (format t "~& GetMessage: error = ~d (~a)" error
+			     (ccl::%windows-error-string error)))
+		   (return))
+		  (t
+		   (#_TranslateMessage msg)
+		   (#_DispatchMessageA msg)))))))))
+                                      
+        
+#||
+
+;;; At the moment, attempts to create a window when running under SLIME
+;;; fail for unknown reasons.  If those reasons have anything to do with
+;;; the lisp process's "WindowStation" or the current thread's "Desktop"
+;;; objects, these functions (which return information about those objects)
+;;; may be useful.
+
+(defun get-ws-info (ws)
+  (rlet ((flags #>USEROBJECTFLAGS))
+    (unless (eql 0 (#_GetUserObjectInformationA ws #$UOI_FLAGS flags (ccl::record-length #>USEROBJECTFLAGS) (%null-ptr)))
+      (pref flags #>USEROBJECTFLAGS.dwFlags))))
+
+;;; This only works on Vista or later.
+(defun get-desktop-info (desktop)
+  (rlet ((pbool #>BOOLEAN #$false))
+    (if (eql 0 (#_GetUserObjectInformationA desktop 6 pbool (ccl::record-length #>BOOLEAN) (%null-ptr)))
+      (ccl::%windows-error-string (#_GetLastError))
+      (pref pbool #>BOOLEAN))))
+
+(defun get-ui-object-name (handle)
+  (%stack-block ((name 1000))
+    (unless (eql 0 (#_GetUserObjectInformationA handle #$UOI_NAME name 1000 (%null-ptr)))
+      (%get-cstring name))))
+||#
Index: /branches/new-random/examples/opengl-ffi.lisp
===================================================================
--- /branches/new-random/examples/opengl-ffi.lisp	(revision 13309)
+++ /branches/new-random/examples/opengl-ffi.lisp	(revision 13309)
@@ -0,0 +1,160 @@
+;;; Example openmcl FFI by hamlink
+;;;
+;;; 2d Gasket example taken from
+;;;  "Interactive Computer Graphics:
+;;;   A Top-Down Approach with OpenGL" by Ed Angel
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ccl:use-interface-dir :GL))
+
+(defpackage "2DGASKET")
+(defpackage "OPENGL"
+    (:nicknames :opengl :gl)
+    (:export "INITIALIZE-GLUT"
+	     "WITH-MATRIX-MODE"))
+
+;;; Opening "libglut.so" should also open "libGL.so", "libGLU.so",
+;;; and other libraries that they depend on.
+;;; It seems that it does on some platforms and not on others;
+;;; explicitly open what we require here.
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  #+linux-target
+  (dolist (lib '("libGL.so" "libGLU.so" "libglut.so"))
+    (open-shared-library lib))
+  #+darwin-target
+  (let* ((s (make-semaphore)))
+    (process-interrupt ccl::*initial-process*
+		       (lambda ()
+			 (open-shared-library "GLUT.framework/GLUT")
+			 (signal-semaphore s)))
+    (wait-on-semaphore s))
+  )
+
+(in-package :opengl)
+
+;; glut complains if it's initialized redundantly
+(let ((glut-initialized-p nil))
+  (defun initialize-glut ()
+    (let ((command-line-strings (list "ccl")))
+      (when (not glut-initialized-p)
+        (ccl::with-string-vector (argv command-line-strings)
+          (rlet ((argvp (* t))    ; glutinit takes (* (:signed 32)) and (* (* (:unsigned 8)))
+		 (argcp :signed)) ; so why are these declared as (* t) and :signed?
+	    (setf (%get-long argcp) (length command-line-strings)
+		  (%get-ptr argvp) argv)
+	    (#_glutInit argcp argvp)))
+	(setf glut-initialized-p t))))
+  ;; When a saved image is restarted, it needs to know that glut
+  ;; hasn't been initialized yet.
+  (defun uninitialize-glut ()
+    (setf glut-initialized-p nil))
+  )
+
+(pushnew #'uninitialize-glut ccl::*save-exit-functions*
+	 :key #'ccl::function-name)
+
+(defparameter *matrix-mode* #$GL_MODELVIEW)
+(defmacro with-matrix-mode (mode &body body)
+  `(unwind-protect
+       (let ((*matrix-mode* ,mode))
+	 (#_glMatrixMode *matrix-mode*)
+	 ,@body)
+     (#_glMatrixMode *matrix-mode*)))
+
+(in-package :2dgasket)
+
+(defun myinit ()
+  (#_glClearColor 1.0 1.0 1.0 0.0) ; white background
+  (#_glColor3f 1.0 0.0 0.0) ; red pen color
+
+  (opengl:with-matrix-mode #$GL_PROJECTION
+    (#_glLoadIdentity)
+    (#_gluOrtho2D 0.0D0 500.0D0 0.0D0 500.0D0))
+
+  ; (#_glEnable #$GL_DEPTH_TEST) ; for 3d only
+
+  (#_srand (#_time (%null-ptr)))
+  )
+
+;; 2d gasket using points
+
+(ccl::defcallback display-cb (:void)
+  (let ((bounds #2a((0.0 0.0) (250.0 500.0) (500.0 0.0)))
+	(point #(75.0 50.0)))
+    (#_glClear #$GL_COLOR_BUFFER_BIT)
+    (#_glBegin #$GL_POINTS)
+    (dotimes (i 5000)
+      (let ((j (random 3)))
+	(setf (aref point 0) (/ (+ (aref point 0) (aref bounds j 0)) 2.0)
+	      (aref point 1) (/ (+ (aref point 1) (aref bounds j 1)) 2.0))
+	(#_glVertex2f (aref point 0) (aref point 1))))
+    (#_glEnd)
+    (#_glFlush)))
+
+(defun main () ; no int argc or char **argv
+  (opengl:initialize-glut)
+  (#_glutInitDisplayMode (logior #$GLUT_RGB
+				 #$GLUT_SINGLE
+				 #+ignore #$GLUT_DEPTH))
+  (#_glutInitWindowSize 500 500)
+  (#_glutInitWindowPosition 0 0)
+  (ccl::with-cstrs ((title "simple OpenGL example"))
+    (#_glutCreateWindow title))
+  (#_glutDisplayFunc display-cb)
+  (myinit)
+
+  ;; It appears that glut provides no mechanism for doing the event loop
+  ;; yourself -- if you want to do that, you should use some other set of
+  ;; libraries and make your own GUI toolkit.
+  
+  (#_glutMainLoop) ; this never returns
+  )
+
+
+;;; With native threads, #_glutMainLoop doesn't necessarily interfere
+;;; with scheduling: we can just run all of the OpenGL code in a
+;;; separate thread (which'll probably spend most of its time blocked
+;;; in GLUT's event loop.)  On OSX (especially) it may work best to
+;;; force the GLUT event loop to run on the main thread, which
+;;; ordinarily does period "housekeeping" tasks.  Start another thread
+;;; to do those tasks, and force the initial/main thread to run the
+;;; GLUT event loop.
+;;;
+
+;;; Try to detect cases where we're already running some sort of event
+;;; loop on OSX.  There are other ways to lose, of course.
+
+#+darwin-target
+(progn
+  (eval-when (:compile-toplevel :execute)
+    (use-interface-dir :cocoa))
+  ;; If the current (window system) process is visible (has a UI),
+  ;; we can't possibly win.
+  (rlet ((psn #>ProcessSerialNumber))
+    (and (eql 0 (#_GetCurrentProcess psn))
+         (not (eql #$false (#_IsProcessVisible psn)))
+         (error "This is a GLUT example; it can't possibly work ~
+                 in a GUI environment."))))
+(progn
+  (ccl:process-run-function
+   "housekeeping"
+   #'ccl::housekeeping-loop)
+  (ccl:process-interrupt
+   ccl::*initial-process*
+   (lambda ()
+     ;; CCL::%SET-TOPLEVEL is sort of like PROCESS-PRESET for the
+     ;; initial process; CCL::TOPLEVEL is sort of like PROCESS-RESET
+     ;; for that process.
+     (ccl::%set-toplevel
+      (lambda ()
+       ;;; Set the OSX Window Server's notion of the name of the
+       ;;; current process.
+       (rlet ((psn #>ProcessSerialNumber))
+         (#_GetCurrentProcess psn)
+         (with-cstrs ((name "simple OpenGL example"))
+           (ccl::external-call "_CPSSetProcessName" :address psn :address name :void)))
+       (ccl::%set-toplevel nil)
+       (main)))
+     (ccl::toplevel))))
+
+
Index: /branches/new-random/examples/rubix/.cvsignore
===================================================================
--- /branches/new-random/examples/rubix/.cvsignore	(revision 13309)
+++ /branches/new-random/examples/rubix/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/examples/rubix/blocks.lisp
===================================================================
--- /branches/new-random/examples/rubix/blocks.lisp	(revision 13309)
+++ /branches/new-random/examples/rubix/blocks.lisp	(revision 13309)
@@ -0,0 +1,410 @@
+(in-package :cl-user)
+
+(defparameter *cube* nil)
+
+(defparameter *camera-pos* #(10.0 5.0 12.0))
+
+(defparameter *selection-buffer-size* 256)
+
+;; some things have no scale or rotation, such as point light sources
+;; (note lights use a 4d vector to hold both positoin and pointsourceness)
+(defclass positioned-object ()
+  ((location :initform nil :initarg :location :accessor location))
+  (:default-initargs :location (make-array 3 :initial-element 0.0)))
+
+(defmethod move-relative ((obj positioned-object) v)
+  (add-vectors (location obj) v (location obj))
+  (location obj))
+(defmethod move-relative-3 ((obj positioned-object) dx dy dz)
+  (incf (elt (location obj) 0) dx)
+  (incf (elt (location obj) 1) dy)
+  (incf (elt (location obj) 2) dz)
+  (location obj))
+(defmethod move-absolute ((obj positioned-object) p)
+  (dotimes (i 3) (setf (elt (location obj) i) (elt p i)))
+  (location obj))
+(defmethod move-absolute-3 ((obj positioned-object) x y z)
+  (setf (elt (location obj) 0) x
+        (elt (location obj) 1) y
+        (elt (location obj) 2) z)
+  (location obj))
+
+(defmethod gl-translate ((obj positioned-object))
+  (#_glTranslatef (elt (location obj) 0)
+                  (elt (location obj) 1)
+                  (elt (location obj) 2)))
+
+(defclass rotated-object ()
+  ((quaternion :initform nil :initarg :quaternion :accessor quaternion))
+  (:default-initargs :quaternion (make-instance 'quaternion)))
+
+(defmethod rotate-relative ((obj rotated-object) quaternion)
+  ;; recall mulquats applies q2's rotation first...
+  (mulquats quaternion (quaternion obj) (quaternion obj))
+  (quaternion obj))
+(defmethod rotate-absolute ((obj rotated-object) quaternion)
+  (setf (w (quaternion obj)) (w quaternion))
+  (dotimes (i 3)
+    (setf (elt (xyz (quaternion obj)) i) (elt quaternion i)))
+  (quaternion obj))
+
+(defmethod gl-rotate ((obj rotated-object))
+  (let ((axis-angle (quat->axis-angle (quaternion obj))))
+    (#_glRotatef (cdr axis-angle)
+                 (elt (car axis-angle) 0)
+                 (elt (car axis-angle) 1)
+                 (elt (car axis-angle) 2))))
+
+(defclass scaled-object ()
+  ((dilation :initform nil :initarg :dilation :accessor dilation))
+  (:default-initargs :dilation (make-array 3 :initial-element 1.0)))
+
+(defmethod gl-scale ((obj scaled-object))
+  (#_glScalef (elt (dilation obj) 0)
+              (elt (dilation obj) 1)
+              (elt (dilation obj) 2)))
+
+(defclass transformed-object (positioned-object
+                              rotated-object
+                              scaled-object)
+  ())
+
+(defmacro with-transformation ((transformed-object) &body body)
+  (let ((tobj-sym (gensym)))
+    `(let ((,tobj-sym ,transformed-object))
+       (#_glPushMatrix)
+       (gl-translate ,tobj-sym)
+       (gl-rotate ,tobj-sym)
+       (gl-scale ,tobj-sym)
+       ,@body
+       (#_glPopMatrix))))
+
+(defmethod render ((obj transformed-object)) ; should this be on something else?
+  (#_glMatrixMode #$GL_MODELVIEW)
+  (with-transformation (obj)
+    (render-children obj)))
+
+(defclass block (transformed-object)
+  (;; need to generate matrices of this form so that copy-ivector-etc will work
+   (vertices :initform (coerce
+                        (list (make-array 3 :initial-contents '(-0.5 -0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5 -0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5  0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '(-0.5  0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '(-0.5 -0.5 -0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5 -0.5 -0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5  0.5 -0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '(-0.5  0.5 -0.5)
+                                          :element-type 'single-float))
+                        'vector)
+             :initarg :vertices :accessor vertices
+             ;; :allocation :class
+             )))
+
+;; I expect that especially with the FFI overhead, one call to render
+;; a static object's prefabbed display list will beat out a lot of
+;; calls to render the various portions... this will be an interesting
+;; conversionn and test going from code to DL, and good prep for
+;; moving from DL-creating code to DL file readers
+#+ignore
+(defmethod render-children ((obj block))
+  (let ((curve-radius 0.1)) ; 90-degree curve in 3 sections for edges and for corners
+    ;; strip for faces 0134 and their edges
+    ;; strip for face 2 and edges to 0 and 3
+    ;; strip for face 5 and edges to 0 and 3
+    ;; edges 15, 54, 42, and 21
+    ;; corner
+    ))
+
+(defmethod render-children ((obj block))
+  (flet ((norm (axis) (#_glNormal3f (aref axis 0) (aref axis 1) (aref axis 2)))
+         (material (color)
+           (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 double-floats
+             (ccl::%copy-ivector-to-ptr color
+               0 ; offset to first element (alignment padding)
+               foreign-float-vector ; destination
+               0 ; byte offset in destination
+               (* 4 4)) ; number of bytes to copy
+             (#_glMaterialfv #$GL_FRONT_AND_BACK
+                             #$GL_AMBIENT_AND_DIFFUSE
+                             foreign-float-vector)))
+         (quad (a b c d)
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices obj) a) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices obj) b) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices obj) c) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices obj) d) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           t))
+    (opengl:with-gl (#$GL_QUADS)
+      (norm *x-axis*)     (material *hel-orange*) (quad 1 2 6 5)
+      (norm *y-axis*)     (material *hel-yellow*) (quad 2 3 7 6)
+      (norm *z-axis*)     (material *hel-green*)  (quad 0 3 2 1)
+      (norm *neg-x-axis*) (material *hel-red*)    (quad 0 4 7 3)
+      (norm *neg-y-axis*) (material *hel-white*)  (quad 0 1 5 4)
+      (norm *neg-z-axis*) (material *hel-blue*)   (quad 4 5 6 7))))
+
+(defclass rubix-cube (transformed-object)
+  ((blocks :initform nil :initarg :blocks :accessor blocks)
+   (faces :initform nil :initarg :faces :accessor faces)
+   (faces-axes :initform (coerce (list *neg-x-axis* *neg-y-axis* *neg-z-axis*
+                                       *x-axis* *y-axis* *z-axis*) 'vector)
+               :initarg :faces-axes :reader faces-axes
+               ;; :allocation :class
+               )
+   (face-turning-p :initform nil :initarg :face-turning-p :accessor face-turning-p)
+   (turning-face :initform nil :initarg :turning-face :accessor turning-face)
+   (face-theta :initform nil :initarg :face-theta :accessor face-theta)
+   ;; vertices for rendering full cube's faces for selection
+   (vertices :initform (coerce
+                        (list (make-array 3 :initial-contents '(-0.5 -0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5 -0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5  0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '(-0.5  0.5  0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '(-0.5 -0.5 -0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5 -0.5 -0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '( 0.5  0.5 -0.5)
+                                          :element-type 'single-float)
+                              (make-array 3 :initial-contents '(-0.5  0.5 -0.5)
+                                          :element-type 'single-float))
+                        'vector)
+             :initarg :vertices :reader vertices
+             ;; :allocation :class
+             ))
+  (:default-initargs
+      :blocks (let ((list nil))
+                (loop for x from -1.0 to 1.0 do
+                     (loop for y from -1.0 to 1.0 do
+                          (loop for z from -1.0 to 1.0 do
+                               (push (make-instance 'block
+                                       :location (coerce (list (/ x 3.0)
+                                                               (/ y 3.0)
+                                                               (/ z 3.0)) 'vector)
+                                       :dilation (coerce (list (/ 1.0 3.0)
+                                                               (/ 1.0 3.0)
+                                                               (/ 1.0 3.0)) 'vector))
+                                     list))))
+                (coerce list 'vector))))
+
+(defparameter *child-positions* (let ((list nil))
+				  (loop for x from -1.0 to 1.0 do
+					(loop for y from -1.0 to 1.0 do
+					      (loop for z from -1.0 to 1.0 do
+						    (push (coerce (list (/ x 3.0)
+									(/ y 3.0)
+									(/ z 3.0)) 'vector)
+							  list))))
+				  (coerce list 'vector)))
+
+;; blocks in faces start at a corner, go clockwise around the face,
+;; and finish in the center; blocks in the cube are numbered to
+;; correspond to *child-positions*; faces that share blocks are
+;; associated in faces-neighbors -- all 3 of these variables depend on
+;; each other
+(defparameter *initial-blocks-in-faces* #2a((0 1 2 5 8 7 6 3 4)
+					    (0 9 18 19 20 11 2 1 10)
+					    (0 3 6 15 24 21 18 9 12)
+					    (26 23 20 19 18 21 24 25 22)
+					    (26 25 24 15 6 7 8 17 16)
+					    (26 17 8 5 2 11 20 23 14)))
+
+(defmethod shared-initialize :after ((obj rubix-cube) slot-names &key)
+  (declare (ignore slot-names))
+  (setf (faces obj) (make-array (list 6 9)))
+  (dotimes (face 6)
+    (dotimes (blok 9)
+      (setf (aref (faces obj) face blok)
+	    (aref (blocks obj) (aref *initial-blocks-in-faces* face blok))))))
+
+(let ((faces-neighbors #2a((1 5 4 2)
+                           (2 3 5 0)
+                           (0 4 3 1)
+                           (5 1 2 4)
+                           (3 2 0 5)
+                           (4 0 1 3))))
+  (defun faces-neighbor (face neighbor)
+    (aref faces-neighbors face neighbor))
+  (defun faces-index-from-neighbor (face neighbor)
+    (loop for i from 0 to 3 do
+      (when (= face (faces-neighbor (faces-neighbor face neighbor) i))
+        (return i))))
+  )
+
+(defmethod turnfaceclockwise ((cube rubix-cube) face &aux temp)
+  (with-slots (faces) cube
+    ;; rotate blocks through adjacent faces
+    (dotimes (neighbor 4)
+      (let* ((neighbors-face (faces-neighbor face neighbor))
+             (my-index (faces-index-from-neighbor face neighbor))
+             (my-block-index (* 2 my-index))
+             (his-new-block-index (* 2 (mod (+ neighbor 3) 4))))
+        (setf (aref faces neighbors-face (mod my-block-index 8))
+              (aref faces face (mod (+ 2 his-new-block-index) 8)))
+        (setf (aref faces neighbors-face (mod (1+ my-block-index) 8))
+              (aref faces face (mod (1+ his-new-block-index) 8)))
+        (setf (aref faces neighbors-face (mod (+ 2 my-block-index) 8))
+              (aref faces face (mod his-new-block-index 8)))))
+    ;; rotate blocks in this face
+    (setf temp (aref faces face 0)
+          (aref faces face 0) (aref faces face 6)
+          (aref faces face 6) (aref faces face 4)
+          (aref faces face 4) (aref faces face 2)
+          (aref faces face 2) temp
+          temp (aref faces face 1)
+          (aref faces face 1) (aref faces face 7)
+          (aref faces face 7) (aref faces face 5)
+          (aref faces face 5) (aref faces face 3)
+          (aref faces face 3) temp)
+    ;; update positions and orientation of blocks in this face
+    (dotimes (i 9)
+      (move-absolute (aref faces face i)
+		     (elt *child-positions* (aref *initial-blocks-in-faces* face i)))
+      (rotate-relative (aref faces face i)
+		       (axis-angle->quat (aref (faces-axes cube) face)
+					 90.0)))
+    ))
+
+(defmethod turnfacecounterclockwise ((cube rubix-cube) face &aux temp)
+  (with-slots (faces) cube
+    ;; rotate blocks through adjacent faces
+    (dotimes (neighbor 4)
+      (let* ((neighbors-face (faces-neighbor face neighbor))
+             (my-index (faces-index-from-neighbor face neighbor))
+             (my-block-index (* 2 my-index))
+             (his-new-block-index (* 2 (mod (+ neighbor 1) 4))))
+        (setf (aref faces neighbors-face (mod my-block-index 8))
+              (aref faces face (mod (+ 2 his-new-block-index) 8)))
+        (setf (aref faces neighbors-face (mod (1+ my-block-index) 8))
+              (aref faces face (mod (1+ his-new-block-index) 8)))
+        (setf (aref faces neighbors-face (mod (+ 2 my-block-index) 8))
+              (aref faces face (mod his-new-block-index 8)))))
+    ;; rotate blocks in this face
+    (setf temp (aref faces face 0)
+          (aref faces face 0) (aref faces face 2)
+          (aref faces face 2) (aref faces face 4)
+          (aref faces face 4) (aref faces face 6)
+          (aref faces face 6) temp
+          temp (aref faces face 1)
+          (aref faces face 1) (aref faces face 3)
+          (aref faces face 3) (aref faces face 5)
+          (aref faces face 5) (aref faces face 7)
+          (aref faces face 7) temp)
+    ;; update positions and orientation of blocks in this face
+    (dotimes (i 9)
+      (move-absolute (aref faces face i)
+		     (elt *child-positions* (aref *initial-blocks-in-faces* face i)))
+      (rotate-relative (aref faces face i)
+		       (axis-angle->quat (aref (faces-axes cube) face)
+					 -90.0)))
+    ))
+
+(defmethod render-children ((obj rubix-cube))
+  (flet ((in-face-p (face blok)
+	   (dotimes (i 9)
+	     (when (eq (aref (blocks obj) blok)
+		       (aref (faces obj) face i))
+	       (return t)))))
+    (cond ((not (face-turning-p obj))
+	   (dotimes (blok 27)
+	     (render (aref (blocks obj) blok))))
+	  (t
+	   (dotimes (blok 27)
+	     (unless (in-face-p (turning-face obj) blok)
+	       (render (aref (blocks obj) blok))))
+	   (opengl:with-rotation ((face-theta obj)
+				  (aref (faces-axes obj) (turning-face obj)))
+	     (dotimes (blok 9)
+	       (render (aref (faces obj) (turning-face obj) blok))))))))
+
+
+(defmethod render-for-selection ((objc rubix-cube) picked-point)
+  (let ((gl-uint-size (ccl::foreign-size :<GL>uint :bytes)) ; 4, as it turns out...
+	(selection-buffer-size 256))
+    (ccl::%stack-block ((selection-buffer (* gl-uint-size selection-buffer-size)))
+      (#_glSelectBuffer selection-buffer-size selection-buffer)
+      (let (;; FYI - this loses a lot of structure and becomes a lot
+	    ;; longer in C++ for lack of macros
+	    (hits (opengl:with-render-mode (#$GL_SELECT)
+		    (#_glInitNames)
+		    (#_glPushName 0)
+		    (opengl:with-culling (#$GL_FRONT)
+		      ;; set up the modified camera looking around the mouse's region
+		      (opengl:with-matrix-mode (#$GL_PROJECTION)
+		        (opengl:with-matrix (t)
+		          (#_glFrustum -0.01d0 0.01d0 -0.01d0 0.01d0 10.0d0 20.0d0)
+			  (opengl:with-matrix-mode (#$GL_MODELVIEW)
+			    (opengl:with-matrix (t)
+			      (mylookat *camera-pos* picked-point *y-axis*)
+			      ;; NOW render the cube like we were doing before
+			      (opengl:with-matrix-mode (#$GL_MODELVIEW)
+				(with-transformation (objc)
+				  (render-children-for-selection objc)))))))
+		      (#_glFlush)))))
+	(when (and (numberp hits)
+		   (< 0 hits))
+	  ;; the first hit name is at selectBuf[3], though i don't recall why
+	  (ccl::%get-unsigned-long selection-buffer (* 3 4)))))))
+
+(defmethod render-children-for-selection ((objc rubix-cube))
+  (flet ((norm (axis) (#_glNormal3f (aref axis 0) (aref axis 1) (aref axis 2)))
+         (material (color)
+           (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 single-floats
+             (ccl::%copy-ivector-to-ptr color
+               0 ; offset to first element (alignment padding)
+               foreign-float-vector ; destination
+               0 ; byte offset in destination
+               (* 4 4)) ; number of bytes to copy
+             (#_glMaterialfv #$GL_FRONT_AND_BACK
+                             #$GL_AMBIENT_AND_DIFFUSE
+                             foreign-float-vector)))
+         (quad (a b c d)
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices objc) a) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices objc) b) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices objc) c) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           (ccl::%stack-block ((ffv (* 4 3)))
+             (ccl::%copy-ivector-to-ptr (aref (vertices objc) d) 0 ffv 0 (* 4 3))
+             (#_glVertex3fv ffv))
+           t))
+    (#_glLoadName 0)
+    (opengl:with-gl (#$GL_QUADS)
+      (norm *x-axis*)     (material *hel-orange*) (quad 1 2 6 5))
+    (#_glLoadName 1)
+    (opengl:with-gl (#$GL_QUADS)
+      (norm *y-axis*)     (material *hel-yellow*) (quad 2 3 7 6))
+    (#_glLoadName 2)
+    (opengl:with-gl (#$GL_QUADS)
+      (norm *z-axis*)     (material *hel-green*)  (quad 0 3 2 1))
+    (#_glLoadName 3)
+    (opengl:with-gl (#$GL_QUADS)
+      (norm *neg-x-axis*) (material *hel-red*)    (quad 0 4 7 3))
+    (#_glLoadName 4)
+    (opengl:with-gl (#$GL_QUADS)
+      (norm *neg-y-axis*) (material *hel-white*)  (quad 0 1 5 4))
+    (#_glLoadName 5)
+    (opengl:with-gl (#$GL_QUADS)
+      (norm *neg-z-axis*) (material *hel-blue*)   (quad 4 5 6 7))))
Index: /branches/new-random/examples/rubix/lights.lisp
===================================================================
--- /branches/new-random/examples/rubix/lights.lisp	(revision 13309)
+++ /branches/new-random/examples/rubix/lights.lisp	(revision 13309)
@@ -0,0 +1,79 @@
+(in-package :cl-user)
+
+;; ah, lights, one of my favorite subjects in OpenGL -- because they way
+;; they work when you're using C++ stinks! I seem to recall i have extensive
+;; discussions of how i would rather deal with TL&M if i was using lisp in
+;; one of my code files somewhere, but first let me get it working then i can
+;; get it working properly
+
+(defclass light ()
+  ((lightid :initform 0 :initarg :lightid :accessor lightid)
+   (on-p :initform nil :accessor on-p)
+   (pointsourcep :initform nil :initarg :pointsourcep :accessor pointsourcep)
+   (location :initform nil :initarg :location :accessor location)
+   (ambient :initform nil :initarg :ambient :accessor ambient)
+   (diffuse :initform nil :initarg :diffuse :accessor diffuse)
+   (specular :initform nil :initarg :specular :accessor specular))
+  (:default-initargs :location (make-array 4 :initial-element 0.0 ; lights are special!
+                                           :element-type 'single-float)
+                     :ambient (make-array 4 :initial-element 0.0
+                                           :element-type 'single-float)
+                     :diffuse (make-array 4 :initial-element 0.0
+                                           :element-type 'single-float)
+                     :specular (make-array 4 :initial-element 0.0
+                                           :element-type 'single-float)))
+
+(defmethod on ((light light))
+  (#_glEnable (lightid light))
+  (setf (on-p light) t))
+(defmethod off ((light light))
+  (#_glDisable (lightid light))
+  (setf (on-p light) nil))
+
+(defmethod setlocation ((light light) pos)
+  (dotimes (i 3) (setf (elt (location light) i) (elt pos i)))
+  (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 single-floats
+    (ccl::%copy-ivector-to-ptr (location light) ; source
+      0     ; offset to first element (alignment padding)
+      foreign-float-vector ; destination
+      0                    ; byte offset in destination
+      (* 4 4))             ; number of bytes to copy
+    (#_glLightfv (lightid light) #$GL_POSITION foreign-float-vector)))
+(defmethod setpointsource ((light light) bool)
+  (setf (pointsourcep light) (if bool t nil) ; <- don't hang on to non-nils
+        (elt (location light) 3) (if bool 1.0 0.0))
+  (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 single-floats
+    (ccl::%copy-ivector-to-ptr (location light) ; source
+      0     ; offset to first element (alignment padding)
+      foreign-float-vector ; destination
+      0                    ; byte offset in destination
+      (* 4 4))             ; number of bytes to copy
+    (#_glLightfv (lightid light) #$GL_POSITION foreign-float-vector)))
+
+(defmethod setambient ((light light) color)
+  (dotimes (i 4) (setf (elt (ambient light) i) (elt color i)))
+  (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 single-floats
+    (ccl::%copy-ivector-to-ptr (ambient light) ; source
+      0     ; offset to first element (alignment padding)
+      foreign-float-vector ; destination
+      0                    ; byte offset in destination
+      (* 4 4))             ; number of bytes to copy
+    (#_glLightfv (lightid light) #$GL_AMBIENT foreign-float-vector)))
+(defmethod setdiffuse ((light light) color)
+  (dotimes (i 4) (setf (elt (diffuse light) i) (elt color i)))
+  (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 single-floats
+    (ccl::%copy-ivector-to-ptr (diffuse light) ; source
+      0     ; offset to first element (alignment padding)
+      foreign-float-vector ; destination
+      0                    ; byte offset in destination
+      (* 4 4))             ; number of bytes to copy
+    (#_glLightfv (lightid light) #$GL_DIFFUSE foreign-float-vector)))
+(defmethod setspecular ((light light) color)
+  (dotimes (i 4) (setf (elt (specular light) i) (elt color i)))
+  (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 single-floats
+    (ccl::%copy-ivector-to-ptr (specular light) ; source
+      0     ; offset to first element (alignment padding)
+      foreign-float-vector ; destination
+      0                    ; byte offset in destination
+      (* 4 4))             ; number of bytes to copy
+    (#_glLightfv (lightid light) #$GL_SPECULAR foreign-float-vector)))
Index: /branches/new-random/examples/rubix/loader.lisp
===================================================================
--- /branches/new-random/examples/rubix/loader.lisp	(revision 13309)
+++ /branches/new-random/examples/rubix/loader.lisp	(revision 13309)
@@ -0,0 +1,15 @@
+(in-package :cl-user)
+
+(require "COCOA")
+
+(let* ((containing-dir (make-pathname :directory (pathname-directory *load-truename*) :defaults nil)))
+  (flet ((load-relative (path)
+           (load (merge-pathnames path containing-dir))))
+    (load-relative "opengl.lisp")
+    (load-relative "vectors.lisp")
+    (load-relative "lights.lisp")
+    (load-relative "blocks.lisp")
+    (load-relative "rubix.lisp")))
+
+
+; (gui::execute-in-gui #'run-rubix-demo)
Index: /branches/new-random/examples/rubix/opengl.lisp
===================================================================
--- /branches/new-random/examples/rubix/opengl.lisp	(revision 13309)
+++ /branches/new-random/examples/rubix/opengl.lisp	(revision 13309)
@@ -0,0 +1,173 @@
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ccl:use-interface-dir :GL))
+
+;;; Cocoa-based OpenGL package, for handy macros and classes of common
+;;; things like transformations, lights, cameras, quaternions, etc.
+;;; (note not all of this has been consolidated into this package yet)
+
+#|
+
+To use this functionality from cocoa, subclass NSOpenGLView,
+specialize drawRect on your class to render whatever you like,
+and make an intance in a window.
+
+|#
+
+#|
+;;; Some design notes for OpenGL programming in lisp...
+
+OpenGL is a very stateful API. with-X macros are invaluable for
+managing OpenGL's stacks and modes.
+
+The rubix demo is not set up this way, but really the main
+objects in a scene need to contain references to their structure,
+so that the structure can be reused between identical objects.
+For large objects that are not always going to be present, the
+structure could be compiled into a fasl and loaded only when
+necessary using a sentinel in place of the structure reference.
+
+Objects should capture the instance-specific state of objects in
+a scene and be used to parameterize the drawing of skeleton-based
+things. This can get tricky, but generic functions that draw
+skeleton structures when passed specific data about the object's
+state and the object's structure are probably the way to go.
+
+Display lists are handy for static models. Something that loaded
+easily-edited display list descriptions and turned them into fasl
+data that rebuilt the display lists would be useful... if I can
+find some EBNF and regexp forms my parser would build the ASTs
+that could be turned into objects easily enough and from there
+fasl data is easy to generate and save. If the file created a
+fasl that set a hash entry from a structure id to a usable opengl
+display list that would be good. A function that requested a
+structure by id that loaded a file if there was no hash entry
+would be slick.
+
+Since this is lisp, it should be possible to create a display
+list or an analogous lexical closure depending on what you want
+from the same model information (to be later rendered as a static
+object or rendered with a instance-state-driven function). I
+don't know how many DLs OpenGL can have at one time or how big
+they can be, it'd be good to know.
+
+|#
+
+(defpackage "OPENGL"
+  (:nicknames :opengl :gl)
+  (:export ;; Cocoa helpers
+           "WITH-OPENGL-CONTEXT"
+	   "NEW-PIXEL-FORMAT"
+	   ;; OpenGL helpers
+	   "WITH-MATRIX-MODE"
+	   "WITH-RENDER-MODE"
+	   "WITH-ROTATION"
+	   "WITH-GL"
+	   "WITH-CULLING"
+	   "WITH-MATRIX"
+	   "UNPROJECT"
+	   ))
+
+(in-package :opengl)
+
+;; WITH-OPENGL-CONTEXT is not needed in the PREPARE-OPENGL
+;; and DRAW-RECT functions of a specialized NS-OPENGL-VIEW
+(defparameter *opengl-context* nil)
+(defmacro with-opengl-context (context &body body)
+  (let ((contextsym (gensym)))
+    `(let ((,contextsym ,context))
+       (unwind-protect
+	   (let ((*opengl-context* ,contextsym))
+             (#/makeCurrentContext ,contextsym)
+	     ,@body)
+	 ;; the following resets the current context to what it was
+	 ;; previously as far as the special bindings are concerned
+	 (if *opengl-context*
+           (#/makeCurrentContext *opengl-context*)
+           (#/clearCurrentConext ns:ns-opengl-context))))))
+
+(defun new-pixel-format (&rest attributes)
+  ;; take a list of opengl pixel format attributes (enums and other
+  ;; small ints), make an array (character array?), and create and
+  ;; return an NSOpenGLPixelFormat
+  (let* ((attribute-size (ccl::foreign-size :<NSO>pen<GLP>ixel<F>ormat<A>ttribute :bytes))
+         (nattributes (length attributes)))
+    (ccl::%stack-block ((objc-attributes (* attribute-size (1+ nattributes))))
+      (loop for i from 0 to nattributes
+	    for attribute in attributes do
+	    (setf (ccl:paref objc-attributes (:* :<NSO>pen<GLP>ixel<F>ormat<A>ttribute) i) attribute) ; <- autocoerced?
+	    finally (setf (ccl:paref objc-attributes (:* :<NSO>pen<GLP>ixel<F>ormat<A>ttribute) nattributes) 0)) ; <- objc nil = null ptr
+      (make-instance ns:ns-opengl-pixel-format :with-attributes objc-attributes))))
+
+#|
+(setf pf (opengl:new-pixel-format #$NSOpenGLPFADoubleBuffer #$NSOpenGLPFADepthSize 32))
+(%stack-block ((a-long 4))
+  (#/getValues:forAttribute:forVirtualScreen: pf a-long #$NSOpenGLPFADepthSize 0)
+  (%get-long a-long))
+|#
+
+(defparameter *matrix-mode* #$GL_MODELVIEW)
+(defmacro with-matrix-mode ((mode) &body body)
+  `(unwind-protect
+       (let ((*matrix-mode* ,mode))
+	 (#_glMatrixMode *matrix-mode*)
+	 ,@body)
+     (#_glMatrixMode *matrix-mode*)))
+
+(defparameter *render-mode* #$GL_RENDER)
+(defmacro with-render-mode ((mode) &body body)
+  `(block nil
+     (unwind-protect
+	 (let ((*render-mode* ,mode))
+	   (#_glRenderMode *render-mode*)
+	   ,@body)
+       (return (#_glRenderMode *render-mode*)))))
+
+(defmacro with-rotation ((angle axis) &body body)
+  (let ((anglesym (gensym))
+	(axissym (gensym)))
+    `(let ((,anglesym ,angle)
+	   (,axissym ,axis))
+       (unwind-protect
+	   (with-matrix-mode (#$GL_MODELVIEW)
+	     (#_glPushMatrix)
+	     (#_glRotatef ,anglesym (aref ,axissym 0) (aref ,axissym 1) (aref ,axissym 2))
+	     ,@body)
+	 (#_glPopMatrix)))))
+
+(defmacro with-gl ((value) &body body)
+  `(progn (#_glBegin ,value)
+          ,@body
+          (#_glEnd)))
+
+(defmacro with-culling ((cull-face) &body body)
+  `(progn (#_glEnable #$GL_CULL_FACE)
+	  (#_glCullFace ,cull-face)
+	  ,@body
+	  (#_glDisable #$GL_CULL_FACE)))
+
+(defmacro with-matrix ((load-identity-p) &body body)
+  `(progn (#_glPushMatrix)
+	  ,@(when load-identity-p `((#_glLoadIdentity)))
+	  ,@body
+	  (#_glPopMatrix)))
+
+(defun unproject (x y)
+  (let (;; yeah, yeah... I think I know how big these are...
+	(gl-int-size (ccl::foreign-size :<GL>int :bytes))
+	(gl-double-size (ccl::foreign-size :<GL>double :bytes)))
+    (ccl::%stack-block ((viewport (* gl-int-size 4))
+			(modelview-matrix (* gl-double-size 16))
+			(projection-matrix (* gl-double-size 16))
+			(wx gl-double-size)
+			(wy gl-double-size)
+			(wz gl-double-size))
+      (#_glGetIntegerv #$GL_VIEWPORT viewport)
+      (#_glGetDoublev #$GL_MODELVIEW_MATRIX modelview-matrix)
+      (#_glGetDoublev #$GL_PROJECTION_MATRIX projection-matrix)
+      (#_gluUnProject (ccl::%double-float x) (ccl::%double-float y) 0.0d0
+		      modelview-matrix projection-matrix viewport
+		      wx wy wz)
+      (coerce (list (ccl::%get-double-float wx)
+		    (ccl::%get-double-float wy)
+		    (ccl::%get-double-float wz))
+	      'vector))))
Index: /branches/new-random/examples/rubix/rubix.lisp
===================================================================
--- /branches/new-random/examples/rubix/rubix.lisp	(revision 13309)
+++ /branches/new-random/examples/rubix/rubix.lisp	(revision 13309)
@@ -0,0 +1,245 @@
+(in-package :cl-user)
+
+
+(defparameter light0 nil)
+(defparameter light0-pos (make-array 3 :initial-contents '(5.0 3.0 0.0) ;; default to distant light source
+                                     :element-type 'single-float))
+(defparameter diffuse0 (make-array 4 :initial-contents '(0.0 0.0 0.0 1.0)
+                                   :element-type 'single-float))
+(defparameter ambient0 (make-array 4 :initial-contents '(1.0 1.0 1.0 1.0)
+                                   :element-type 'single-float))
+(defparameter specular0 (make-array 4 :initial-contents '(0.0 0.0 0.0 1.0)
+                                   :element-type 'single-float))
+
+(defparameter global-ambient (make-array 4 :initial-contents '(1.0 1.0 1.0 1.0) :element-type 'single-float)) ;; really really dim grey light
+
+(defclass rubix-opengl-view (ns:ns-opengl-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/prepareOpenGL :void) ((self rubix-opengl-view))
+  (declare (special *the-origin* *y-axis*))
+  (opengl:with-matrix-mode (#$GL_PROJECTION) ;; default is GL_MODELVIEW
+    (#_glLoadIdentity)
+    (#_glFrustum -0.6d0 0.6d0 -0.6d0 0.6d0 10.0d0 20.0d0))
+  (#_glLoadIdentity)
+  (mylookat *camera-pos* *the-origin* *y-axis*)
+
+  (#_glShadeModel #$GL_SMOOTH)
+  (#_glClearColor 0.05 0.05 0.05 0.0)
+  ;; these next three are all needed to enable the z-buffer
+  (#_glClearDepth 1.0d0)
+  (#_glEnable #$GL_DEPTH_TEST)
+  (#_glDepthFunc #$GL_LEQUAL)
+  (#_glHint #$GL_PERSPECTIVE_CORRECTION_HINT #$GL_NICEST)
+
+  (setf *cube* (make-instance 'rubix-cube))
+
+  (#_glEnable #$GL_LIGHTING)
+
+  (setf light0 (make-instance 'light :lightid #$GL_LIGHT0))
+  (setpointsource light0 t)
+  (setlocation light0 light0-pos)
+  (setdiffuse light0 diffuse0)
+  (setambient light0 ambient0)
+  (setspecular light0 specular0)
+  (on light0)
+
+  (ccl::%stack-block ((foreign-float-vector (* 4 4))) ; make room for 4 single-floats
+    (ccl::%copy-ivector-to-ptr global-ambient ; source
+      0     ; offset to first element (alignment padding)
+      foreign-float-vector ; destination
+      0                    ; byte offset in destination
+      (* 4 4))             ; number of bytes to copy
+    (#_glLightModelfv #$GL_LIGHT_MODEL_AMBIENT foreign-float-vector)) ;; <- coersion issue
+
+  (#_glFlush))
+
+(objc:defmethod (#/drawRect: :void) ((self rubix-opengl-view) (a-rect :ns-rect))
+  (declare (ignorable a-rect))
+  ;; drawing callback
+  (#_glClear (logior #$GL_COLOR_BUFFER_BIT #$GL_DEPTH_BUFFER_BIT))
+  (render *cube*)
+  (#_glFlush))
+
+;; want to be able to send keystrokes to the rubix cube
+#+ignore
+(objc:defmethod (#/acceptsFirstResponder :<BOOL>) ((self rubix-opengl-view))
+  t)
+
+;; want to be able to click and start dragging (without moving the window)
+(objc:defmethod (#/acceptsFirstMouse: :<BOOL>) ((self rubix-opengl-view)
+                                                event)
+  (declare (ignore event))
+  t)
+
+
+(defparameter *rubix-face-snap* 8.0) ; degrees
+
+(objc:defmethod (#/mouseDown: :void) ((self rubix-opengl-view) the-event)
+  ;; this makes dragging spin the cube
+  (cond ((zerop (logand #$NSControlKeyMask (#/modifierFlags the-event))) ; not ctrl-click
+	 (let ((dragging-p t))
+           (let ((last-loc (#/locationInWindow the-event)))
+             (loop while dragging-p do
+                   (let ((the-event (#/nextEventMatchingMask:
+                                     (#/window self)
+                                     (logior #$NSLeftMouseUpMask
+                                             #$NSLeftMouseDraggedMask))))
+                     (let ((mouse-loc (#/locationInWindow the-event)))
+                       (cond ((eq #$NSLeftMouseDragged (#/type the-event))
+                              (let ((deltax (float
+                                             (- (pref mouse-loc :<NSP>oint.x)
+                                                (pref last-loc :<NSP>oint.x))
+                                             0.0f0))
+                                    (deltay (float
+                                             (- (pref last-loc :<NSP>oint.y)
+                                                (pref mouse-loc :<NSP>oint.y))
+                                             0.0f0))
+                                    (vert-rot-axis (cross *y-axis* *camera-pos*)))
+                                (setf (pref last-loc :<NSP>oint.x) (pref mouse-loc :<NSP>oint.x)
+                                      (pref last-loc :<NSP>oint.y) (pref mouse-loc :<NSP>oint.y))
+                                (rotate-relative *cube*
+                                                 (mulquats (axis-angle->quat vert-rot-axis deltay)
+                                                           (axis-angle->quat *y-axis* deltax))))
+                              (#/setNeedsDisplay: self t))
+                             (t
+                              (setf dragging-p nil))))))
+             (#/setNeedsDisplay: self t))))
+	(t;; ctrl-click, do what right-click does... note that once
+         ;; ctrl-click is done dragging will not require ctrl be held down
+
+	 ;; NOTE THE GRATUITOUS CUT-AND-PASTE, debug the right-mouse-down
+	 ;; version preferentially and update this one with fixes as needed
+         (let* ((first-loc (#/locationInWindow the-event))
+                (pick-loc (#/convertPoint:fromView: self first-loc +null-ptr+)))
+           (let ((dragging-p t)
+                 (reference-snap 0))
+             (setf (turning-face *cube*) (render-for-selection
+                                          *cube*
+                                          (opengl:unproject (pref pick-loc :<NSP>oint.x)
+                                                            (pref pick-loc :<NSP>oint.y)))
+                   (face-turning-p *cube*) (when (numberp (turning-face *cube*)) t)
+                   (face-theta *cube*) 0.0)
+             (loop while (and dragging-p (face-turning-p *cube*)) do
+                   (let ((the-event (#/nextEventMatchingMask:
+                                               (#/window self)
+                                               (logior #$NSLeftMouseUpMask
+                                                       #$NSLeftMouseDraggedMask))))
+                     (let ((mouse-loc (#/locationInWindow the-event)))
+                       (cond ((eq #$NSLeftMouseDragged (#/type the-event))
+                              (let ((deltax (float
+                                             (- (ns:ns-point-x mouse-loc)
+                                                (ns:ns-point-x first-loc))
+                                             0.0f0)))
+                                (multiple-value-bind (snap-to snap-dist) (round deltax 90.0)
+                                  (cond ((>= *rubix-face-snap* (abs snap-dist)) ; snap
+                                         ;; update cube structure
+                                         (let ((rotations (- snap-to reference-snap)))
+                                           (cond ((zerop rotations) nil)
+                                                 ((< 0 rotations)
+                                                  (dotimes (i rotations)
+                                                    (turnfaceclockwise *cube* (turning-face *cube*)))
+                                                  (setf reference-snap snap-to))
+                                                 ((> 0 rotations)
+                                                  (dotimes (i (abs rotations))
+                                                    (turnfacecounterclockwise *cube* (turning-face *cube*)))
+                                                  (setf reference-snap snap-to))))
+                                         ;; determine where face will be drawn
+                                         (setf (face-theta *cube*) 0.0))
+                                        (t ; no snap
+                                         (setf (face-theta *cube*) (- deltax (* 90.0 reference-snap))))
+                                        )))
+                              (#/setNeedsDisplay: self t))
+                             (t
+                              (setf (face-turning-p *cube*) nil
+                                    (turning-face *cube*) nil
+                                    (face-theta *cube*) nil
+                                    dragging-p nil))))))
+             (#/setNeedsDisplay: self t)))
+	 )))
+
+(objc:defmethod (#/rightMouseDown: :void) ((self rubix-opengl-view) the-event)
+  ;; this makes dragging left/right turn a face counterclockwise/clockwise
+  ;; ... clicked-on face determines face turned
+  ;; ... with an n-degree "snap"
+  ;; ... with the snap updating the data structure
+  ;; ... releasing the mouse clears rotation angle (face will snap to last position)
+  (let* ((first-loc (#/locationInWindow the-event))
+         (pick-loc (#/convertPoint:fromView: self first-loc +null-ptr+)))
+    (let ((dragging-p t)
+	  (reference-snap 0))
+      (setf (turning-face *cube*) (render-for-selection
+                                   *cube*
+                                   (opengl:unproject (pref pick-loc :<NSP>oint.x)
+                                                     (pref pick-loc :<NSP>oint.y)))
+	    (face-turning-p *cube*) (when (numberp (turning-face *cube*)) t)
+	    (face-theta *cube*) 0.0)
+      (loop while (and dragging-p (face-turning-p *cube*)) do
+	    (let ((the-event (#/nextEventMatchingMask:
+                              (#/window self)
+                              (logior #$NSRightMouseUpMask
+                                      #$NSRightMouseDraggedMask))))
+	      (let ((mouse-loc (#/locationInWindow the-event)))
+		(cond ((eq #$NSRightMouseDragged (#/type the-event))
+		       (let ((deltax (float
+                                      (- (pref mouse-loc :<NSP>oint.x)
+                                         (pref first-loc :<NSP>oint.x))
+                                      0.0f0)))
+			 (multiple-value-bind (snap-to snap-dist) (round deltax 90.0)
+			   (cond ((>= *rubix-face-snap* (abs snap-dist)) ; snap
+				  ;; update cube structure
+				  (let ((rotations (- snap-to reference-snap)))
+				    (cond ((zerop rotations) nil)
+					  ((< 0 rotations)
+					   (dotimes (i rotations)
+					     (turnfaceclockwise *cube* (turning-face *cube*)))
+					   (setf reference-snap snap-to))
+					  ((> 0 rotations)
+					   (dotimes (i (abs rotations))
+					     (turnfacecounterclockwise *cube* (turning-face *cube*)))
+					   (setf reference-snap snap-to))))
+				  ;; determine where face will be drawn
+				  (setf (face-theta *cube*) 0.0))
+				 (t     ; no snap
+				  (setf (face-theta *cube*) (- deltax (* 90.0 reference-snap))))
+				 )))
+		       (#/setNeedsDisplay: self t))
+		      (t
+		       (setf (face-turning-p *cube*) nil
+			     (turning-face *cube*) nil
+			     (face-theta *cube*) nil
+			     dragging-p nil))))))
+      (#/setNeedsDisplay: self t))))
+
+(defclass rubix-window (ns:ns-window)
+  ()
+  (:metaclass ns:+ns-object))
+
+(defparameter *aluminum-margin* 5.0f0)
+
+(defun run-rubix-demo ()
+  (let* ((w (gui::new-cocoa-window :class (find-class 'rubix-window)
+				   :title "Rubix Cube"
+				   :height 250
+				   :width 250
+				   :expandable nil))
+	 (w-content-view (#/contentView w)))
+    (let ((w-frame (#/frame w-content-view)))
+      (ns:with-ns-rect (glview-rect *aluminum-margin*
+                                    *aluminum-margin*
+                                    (- (pref w-frame :<NSR>ect.size.width)
+                                       (* 2 *aluminum-margin*))
+                                    (- (pref w-frame :<NSR>ect.size.height)
+                                       *aluminum-margin*))
+	;; Q: why make-objc-instance here?
+	(let ((glview (make-instance 'rubix-opengl-view
+			    :with-frame glview-rect
+			    :pixel-format #+ignore
+			                  (#/defaultPixelFormat nsLns-opengl-view)
+					  (opengl:new-pixel-format ;#$NSOpenGLPFADoubleBuffer
+								   #$NSOpenGLPFAAccelerated
+								   #$NSOpenGLPFAColorSize 32
+								   #$NSOpenGLPFADepthSize 32))))
+	  (#/addSubview: w-content-view glview)
+	  w)))))
Index: /branches/new-random/examples/rubix/vectors.lisp
===================================================================
--- /branches/new-random/examples/rubix/vectors.lisp	(revision 13309)
+++ /branches/new-random/examples/rubix/vectors.lisp	(revision 13309)
@@ -0,0 +1,170 @@
+(in-package :cl-user)
+
+;; A stylistic ideosynchracy of C++ was passing result pointers into functions
+;; to reduce the impact of the lack of garbage collection. It reduces consing
+;; and allows functions to modify wrapped vectors and the like in place, so
+;; it's laudable to keep around, but in general I've made such things an
+;; optional final argument.
+
+;; To-do list:
+;; When i make foreign function calls in to glut, glu, or opengl, i should
+;; do type checking to trap errors in lisp.
+
+(defparameter *x-axis*     (make-array 3 :initial-contents '( 1.0  0.0  0.0)
+                                       :element-type 'single-float))
+(defparameter *y-axis*     (make-array 3 :initial-contents '( 0.0  1.0  0.0)
+                                       :element-type 'single-float))
+(defparameter *z-axis*     (make-array 3 :initial-contents '( 0.0  0.0  1.0)
+                                       :element-type 'single-float))
+(defparameter *neg-x-axis* (make-array 3 :initial-contents '(-1.0  0.0  0.0)
+                                       :element-type 'single-float))
+(defparameter *neg-y-axis* (make-array 3 :initial-contents '( 0.0 -1.0  0.0)
+                                       :element-type 'single-float))
+(defparameter *neg-z-axis* (make-array 3 :initial-contents '( 0.0  0.0 -1.0)
+                                       :element-type 'single-float))
+(defparameter *the-origin* (make-array 3 :initial-contents '( 0.0  0.0  0.0)
+                                       :element-type 'single-float))
+
+(defparameter *hel-white*   (make-array 4 :initial-contents '(1.0 1.0  1.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-grey*    (make-array 4 :initial-contents '(0.3 0.3  0.3 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-black*   (make-array 4 :initial-contents '(0.0 0.0  0.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-red*     (make-array 4 :initial-contents '(1.0 0.0  0.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-green*   (make-array 4 :initial-contents '(0.0 0.33 0.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-blue*    (make-array 4 :initial-contents '(0.0 0.0  1.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-yellow*  (make-array 4 :initial-contents '(1.0 1.0  0.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-cyan*    (make-array 4 :initial-contents '(0.0 1.0  1.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-magenta* (make-array 4 :initial-contents '(1.0 0.0  1.0 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-peach*   (make-array 4 :initial-contents '(1.0 0.3  0.2 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-pink*    (make-array 4 :initial-contents '(1.0 0.3  0.3 1.0)
+                                        :element-type 'single-float))
+(defparameter *hel-orange*  (make-array 4 :initial-contents '(1.0 0.3  0.0 1.0)
+                                        :element-type 'single-float))
+
+(defun radians (degrees)
+  (/ (* 3.14159 degrees) 180.0))
+(defun degrees (radians)
+  (/ (* 180.0 radians) 3.14159))
+(defun mag (p)
+  (let ((p0 (elt p 0))
+        (p1 (elt p 1))
+        (p2 (elt p 2)))
+    (+ (* p0 p0) (* p1 p1) (* p2 p2))))
+(defun normalize (p)
+  (let ((d 0.0))
+    (dotimes (i 3) (incf d (expt (elt p i) 2)))
+    (when (< 0.0 d)
+      (setf d (sqrt d))
+      (dotimes (i 3) (setf (elt p i) (/ (elt p i) d))))
+    p))
+
+(defun add-vectors (a b &optional result)
+  (or result (setf result (make-array 3)))
+  (dotimes (i 3)
+    (setf (elt result i) (+ (elt a i) (elt b i))))
+  result)
+(defun scale-vector (a n &optional result)
+  (or result (setf result (make-array 3)))
+  (dotimes (i 3)
+    (setf (elt result i) (* (elt a i) n)))
+  result)
+#+ignore ; overridden by lower defn anyway
+(defun cross (a b c &optional norm)
+  (or norm (setf norm (make-array 3)))
+  (let ((a0 (elt a 0)) (a1 (elt a 1)) (a2 (elt a 2))
+        (b0 (elt b 0)) (b1 (elt b 1)) (b2 (elt b 2))
+        (c0 (elt c 0)) (c1 (elt c 1)) (c2 (elt c 2)))
+    (setf (elt norm 0) (- (* (- b1 a1) (- c2 a2)) (* (- b2 a2) (- c1 a1)))
+          (elt norm 1) (- (* (- b2 a2) (- c0 a0)) (* (- b0 a0) (- c2 a2)))
+          (elt norm 2) (- (* (- b0 a0) (- c1 a1)) (* (- b1 a1) (- c0 a0)))))
+  norm)
+(defun cross (v1 v2 &optional crossproduct)
+  (or crossproduct (setf crossproduct (make-array 3)))
+  (setf (elt crossproduct 0) (- (* (elt v1 1) (elt v2 2))
+                                (* (elt v1 2) (elt v2 1)))
+        (elt crossproduct 1) (- (* (elt v1 2) (elt v2 0))
+                                (* (elt v1 0) (elt v2 2)))
+        (elt crossproduct 2) (- (* (elt v1 0) (elt v2 1))
+                                (* (elt v1 1) (elt v2 0))))
+  crossproduct)
+(defun dot (v1 v2)
+  (+ (* (elt v1 0) (elt v2 0))
+     (* (elt v1 1) (elt v2 1))
+     (* (elt v1 2) (elt v2 2))))
+
+
+;; quaterion class (note that in my c++ code i use a type for this,
+;; but since the quaternions aren't ever going to be in the C world
+;; the lisp representation doesn't matter)
+(defclass quaternion ()
+  ((w :initform 1.0 :initarg :w :accessor w)
+   (xyz :initform nil :initarg :xyz :accessor xyz))
+  (:default-initargs :xyz (make-array 3 :initial-element 0.0)))
+(defmethod addquats ((q1 quaternion) (q2 quaternion) &optional result)
+  (or result (setf result (make-instance 'quaternion)))
+  (setf (w result) (+ (w q1) (w q2)))
+  (add-vectors (xyz q1) (xyz q2) (xyz result))
+  result)
+;; this computes q1*q2 not the other way around, so it does q2's rotation first
+(defmethod mulquats ((q1 quaternion) (q2 quaternion) &optional result)
+  (or result (setf result (make-instance 'quaternion)))
+  (let ((t1 (make-array 3 :initial-element 0.0))
+        (t2 (make-array 3 :initial-element 0.0))
+        (t3 (make-array 3 :initial-element 0.0)))
+    (scale-vector (xyz q1) (w q2) t1)
+    (scale-vector (xyz q2) (w q1) t2)
+    (cross (xyz q1) (xyz q2) t3)
+
+    (setf (w result) (- (* (w q1) (w q2)) (dot (xyz q1) (xyz q2))))
+    (add-vectors t1 t2 (xyz result))
+    (add-vectors t3 (xyz result) (xyz result))
+    result))
+
+;; unit quaternions are made up of the axis of rotation (xyz) as a vector with
+;; magnitude sin(theta/2) and a scalar (w) with magnitude cos(theta/2);
+(defun axis-angle->quat (axis angle &optional q)
+  (or q (setf q (make-instance 'quaternion)))
+  (let ((theta (radians angle)))
+    (setf (w q) (cos (/ theta 2.0)))
+    (dotimes (i 3) (setf (elt (xyz q) i) (elt axis i)))
+    (normalize (xyz q))
+    (scale-vector (xyz q) (sin (/ theta 2.0)) (xyz q))
+    q))
+(defun quat->axis-angle (q &optional axis-angle) ; <- cons pair, bleah
+  (or axis-angle (setf axis-angle (cons (make-array 3 :initial-element 0.0)
+                                        0.0)))
+  (let ((len (mag (xyz q))))
+    (cond ((> len 0.0001)
+           (setf (cdr axis-angle) (degrees (* 2.0 (acos (w q)))))
+           (dotimes (i 3) (setf (elt (car axis-angle) i)
+                                (/ (elt (xyz q) i) len))))
+          (t ;; if len is near 0, angle of rotation is too, which can cause
+             ;; trouble elsewhere, so just return zero
+           (setf (cdr axis-angle) 0.0)
+           (setf (elt (car axis-angle) 0) 0.0
+                 (elt (car axis-angle) 1) 0.0
+                 (elt (car axis-angle) 2) 1.0)))
+    axis-angle))
+
+;; this wraps a 9-number function with a point/point/vector function
+;; note that this could REALLY stand to do some type checking...
+(defun myLookAt (camera-position target-position upvector)
+  (#_gluLookAt
+   (coerce (elt camera-position 0) 'double-float)
+   (coerce (elt camera-position 1) 'double-float)
+   (coerce (elt camera-position 2) 'double-float)
+   (coerce (elt target-position 0) 'double-float)
+   (coerce (elt target-position 1) 'double-float)
+   (coerce (elt target-position 2) 'double-float)
+   (coerce (elt upvector 0) 'double-float)
+   (coerce (elt upvector 1) 'double-float)
+   (coerce (elt upvector 2) 'double-float)))
Index: /branches/new-random/examples/webkit.lisp
===================================================================
--- /branches/new-random/examples/webkit.lisp	(revision 13309)
+++ /branches/new-random/examples/webkit.lisp	(revision 13309)
@@ -0,0 +1,86 @@
+
+;;;-*-Mode: LISP; Package: CCL -*-
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "COCOA"))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (objc:load-framework "WebKit" :webkit))
+
+
+(defun pathname-to-file-url (pathname)
+  ;; NATIVE-TRANSLATED-NAMESTRING returns a simple string that can be
+  ;; passed to a filesystem function.  (It may be exactly the same as
+  ;; what NAMESTRING returns, or it may differ if special characters
+  ;; were escaped in NAMESTRING's result.)
+  (with-autorelease-pool
+    (#/retain
+     (#/fileURLWithPath: ns:ns-url (%make-nsstring
+                                    (native-translated-namestring pathname))))))
+
+(defun url-from-string (s)
+  (with-autorelease-pool
+    (#/retain (#/URLWithString: ns:ns-url (%make-nsstring (string s))))))
+		  
+
+(defun %browser-window (urlspec)
+  (gui::assume-cocoa-thread)
+  ;; Content rect for window, bounds rect for view.
+  (ns:with-ns-rect (r 100.0 100.0 800.0 600.0)
+    (with-autorelease-pool 
+      (let* ((url (if (typep urlspec 'pathname)
+                    (pathname-to-file-url urlspec)
+                    (url-from-string urlspec)))
+             ;; Create a window with titlebar, close & iconize buttons
+             (w (make-instance
+                 'ns:ns-window
+                 :with-content-rect r
+                 :style-mask (logior #$NSTitledWindowMask
+                                     #$NSClosableWindowMask
+                                     #$NSMiniaturizableWindowMask
+                                     #$NSResizableWindowMask)
+                 ;; Backing styles other than #$NSBackingStoreBuffered
+                 ;; don't work at all in Cocoa.
+                 :backing #$NSBackingStoreBuffered
+                 :defer t)))
+        (#/setTitle: w (#/absoluteString url))
+        ;; Create a web-view instance,
+        (let* ((v (make-instance
+                   'ns:web-view
+                   :with-frame r
+                   :frame-name #@"frame" ; could be documented a bit better ...
+                   :group-name #@"group"))) ; as could this
+          ;; Make the view be the window's content view.
+          (#/setContentView: w v)
+          ;; Start a URL request.  The request is processed
+          ;; asynchronously, but apparently needs to be initiated
+          ;; from the event-handling thread.
+          (let* ((webframe (#/mainFrame v))
+                 (request (#/requestWithURL: ns:ns-url-request url)))
+            ;; Failing to wait until the main thread has
+            ;; initiated the request seems to cause
+            ;; view-locking errors.  Maybe that's just
+            ;; an artifact of some other problem.
+            (#/loadRequest: webframe request)
+            ;; Make the window visible & activate it
+            ;; The view knows how to draw itself and respond
+            ;; to events.
+            (#/makeKeyAndOrderFront: w +null-ptr+))
+          v)))))
+
+(defun browser-window (urlspec)
+  (let* ((ip ccl::*initial-process*))
+    (if (eq ccl::*current-process* ip)
+      (%browser-window urlspec)
+      (let* ((s (make-semaphore))
+             (v nil))
+        (process-interrupt ip (lambda ()
+                                (setq v (%browser-window urlspec))
+                                (signal-semaphore s)))
+        (wait-on-semaphore s)
+        v))))
+
+	
+;;; (browser-window "http://openmcl.clozure.com")
Index: /branches/new-random/l1-fasls/.cvsignore
===================================================================
--- /branches/new-random/l1-fasls/.cvsignore	(revision 13309)
+++ /branches/new-random/l1-fasls/.cvsignore	(revision 13309)
@@ -0,0 +1,3 @@
+*fsl
+
+
Index: /branches/new-random/level-0/.cvsignore
===================================================================
--- /branches/new-random/level-0/.cvsignore	(revision 13309)
+++ /branches/new-random/level-0/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*fsl
+*~.*
Index: /branches/new-random/level-0/PPC/.cvsignore
===================================================================
--- /branches/new-random/level-0/PPC/.cvsignore	(revision 13309)
+++ /branches/new-random/level-0/PPC/.cvsignore	(revision 13309)
@@ -0,0 +1,6 @@
+*.pfsl
+*.p64fsl
+*.dfsl
+*.d64fsl
+
+*~.*
Index: /branches/new-random/level-0/PPC/PPC32/.cvsignore
===================================================================
--- /branches/new-random/level-0/PPC/PPC32/.cvsignore	(revision 13309)
+++ /branches/new-random/level-0/PPC/PPC32/.cvsignore	(revision 13309)
@@ -0,0 +1,6 @@
+*.pfsl
+*.p64fsl
+*.dfsl
+*.d64fsl
+
+*~.*
Index: /branches/new-random/level-0/PPC/PPC32/ppc32-bignum.lisp
===================================================================
--- /branches/new-random/level-0/PPC/PPC32/ppc32-bignum.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/PPC32/ppc32-bignum.lisp	(revision 13309)
@@ -0,0 +1,1786 @@
+;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "PPC32-ARCH")
+  (require "PPC-LAPMACROS")
+
+    ;; Set RES to 1 if (u< x y), to 0 otherwise.
+  (defppclapmacro sltu (res x y)
+    `(progn
+      (subfc ,res ,x ,y)
+      (subfe ,res ,res ,res)
+      (neg ,res ,res)))
+
+    (defppclapmacro 48x32-divide (x-hi16 x-lo y freg temp-freg freg2 immx)
+    `(let ((temp 16)
+           (temp.h 16)
+           (temp.l 20)
+           (zero 8)
+           (zero.h 8)
+           (zero.l 12))
+      (stwu tsp -24 tsp)
+      (stw tsp 4 tsp)
+      (lwi ,immx #x43300000)  ; 1075 = 1022+53 
+      (stw ,immx zero.h tsp)
+      (stw rzero zero.l tsp)
+      (lfd ,temp-freg zero tsp)
+      (rlwimi ,immx ,x-hi16 0 16 31)           
+      (stw ,immx temp.h tsp)
+      (stw ,x-lo temp.l tsp)
+      (lfd ,freg temp tsp)
+      
+      (fsub ,freg ,freg ,temp-freg)
+      (lwi ,immx #x43300000)
+      (stw ,immx temp.h tsp)
+      (stw ,y temp.l tsp)
+      (lfd ,freg2 temp tsp)
+      (lwz tsp 0 tsp)
+      (fsub ,freg2 ,freg2 ,temp-freg)
+      (fdiv ,freg ,freg ,freg2)
+      ))
+    
+  )
+
+;;; %BIGNUM-REF needs to access bignums as obviously as possible, and it needs
+;;; to be able to return 32 bits somewhere no one looks for real objects.
+;;;
+;;; The easiest thing to do is to store the 32 raw bits in two fixnums
+;;; and return multiple values.
+(defppclapfunction %bignum-ref ((bignum arg_y) (i arg_z))
+  (vref32 imm0 bignum i imm1)
+  (digit-h temp0 imm0)
+  (digit-l temp1 imm0)
+  (vpush temp0)
+  (vpush temp1)
+  (la temp0 8 vsp)                      ; ?? why not (mr temp0 vsp) before vpushing?
+  (set-nargs 2)                         ; that doesn't make any difference.  And, in this case,
+                                        ; we can get away without setting nargs (since the caller
+                                        ; called us with 2 args, but that's horrible style.)
+  (ba .SPvalues))
+
+
+;;; Set the 0th element of DEST (a bignum or some other 32-bit ivector)
+;;; to the Ith element of the bignum SRC.
+(defppclapfunction %ref-digit ((bignum arg_x) (i arg_y) (dest arg_z))
+  (la imm1 ppc32::misc-data-offset i)
+  (lwzx imm0 bignum imm1)
+  (stw imm0 ppc32::misc-data-offset dest)
+  (blr))
+
+;;; BIGNUM[I] := DIGIT[0]
+(defppclapfunction %set-digit ((bignum arg_x) (i arg_y) (digit arg_z))
+  (la imm1 ppc32::misc-data-offset i)
+  (lwz imm0 ppc32::misc-data-offset digit)
+  (stwx imm0 bignum imm1)
+  (blr))
+
+;;; Return 0 if the 0th digit in X is 0.
+(defppclapfunction %digit-zerop ((x arg_z))
+  (lwz imm0 ppc32::misc-data-offset x)
+  (cntlzw imm0 imm0)
+  (srwi imm0 imm0 5)
+  (rlwimi imm0 imm0 4 27 27)
+  (addi arg_z imm0 (target-nil-value))
+  (blr))
+
+;;; store the sign of bignum (0 or -1) in the one-word bignum "digit".
+(defppclapfunction %bignum-sign-digit ((bignum arg_y) (digit arg_z))
+  (vector-length imm0 bignum imm0)
+  (la imm0 (- ppc32::misc-data-offset 4) imm0) ; Reference last (most significant) digit
+  (lwzx imm0 bignum imm0)
+  (srawi imm0 imm0 31)			;propagate sign bit
+  (stw imm0 ppc32::misc-data-offset digit)
+  (blr))
+
+;;; Return the sign of bignum (0 or -1) as a fixnum
+(defppclapfunction %bignum-sign ((bignum arg_z))
+  (vector-length imm0 bignum imm0)
+  (la imm0 (- ppc32::misc-data-offset 4) imm0) ; Reference last (most significant) digit
+  (lwzx imm0 bignum imm0)
+  (srawi imm0 imm0 31)			;propagate sign bit
+  (box-fixnum arg_z imm0)
+  (blr))
+
+;;; Count the sign bits in the most significant digit of bignum;
+;;; return fixnum count.
+(defppclapfunction %bignum-sign-bits ((bignum arg_z))
+  (vector-length imm0 bignum imm0)
+  (la imm0 (- ppc32::misc-data-offset 4) imm0) ; Reference last (most significant) digit
+  (lwzx imm0 bignum imm0)
+  (cmpwi imm0 0)
+  (not imm0 imm0)
+  (blt @wasneg)
+  (not imm0 imm0)
+  @wasneg
+  (cntlzw imm0 imm0)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %digit-0-or-plusp ((bignum arg_y) (idx arg_z))
+  (la imm0 ppc32::misc-data-offset idx)
+  (lwzx imm0 bignum imm0)
+  (xoris imm0 imm0 #x8000)		; invert sign bit
+  (srwi imm0 imm0 31)
+  (bit0->boolean arg_z imm0 imm0)	; return T if sign bit was clear before inversion
+  (blr))
+
+;;; For oddp, evenp
+(defppclapfunction %bignum-oddp ((bignum arg_z))
+  (lwz imm0 ppc32::misc-data-offset bignum)
+  (clrlwi imm0 imm0 31)
+  (bit0->boolean arg_z imm0 imm0)
+  (blr))
+  
+(defppclapfunction bignum-plusp ((bignum arg_z))
+  (vector-length imm0 bignum imm0)
+  (la imm0 (- ppc32::misc-data-offset 4) imm0) ; Reference last (most significant) digit
+  (lwzx imm0 bignum imm0)
+  (xoris imm0 imm0 #x8000)		; invert sign bit
+  (srwi imm0 imm0 31)
+  (bit0->boolean arg_z imm0 imm0)	; return T if sign bit was clear before inversion
+  (blr))
+
+(defppclapfunction %fixnum-to-bignum-set ((bignum arg_y) (fixnum arg_z))
+  (unbox-fixnum imm0 fixnum)
+  (stw imm0 ppc32::misc-data-offset bignum)
+  (blr))
+
+(defppclapfunction bignum-minusp ((bignum arg_z))
+  (vector-length imm0 bignum imm0)
+  (la imm0 (- ppc32::misc-data-offset 4) imm0) ; Reference last (most significant) digit
+  (lwzx imm0 bignum imm0)
+  (srwi imm0 imm0 31)
+  (rlwimi imm0 imm0 4 27 27)
+  (addi arg_z imm0 (target-nil-value))	; return T if sign bit was clear before inversion
+  (blr))
+
+
+;;; Add the digits A[I] and B[J], and the incoming carry C (a fixnum).
+;;; Store the result in R[K], and return the outgoing carry.
+;;; If I is NIL, A is a fixnum.  If J is NIL, B is a fixnum.
+
+(defppclapfunction %add-with-carry ((r 12) (k 8) (c 4) (a 0) (i arg_x) (b arg_y) (j arg_z))
+  (cmpwi cr1 j (target-nil-value))
+  (cmpwi cr0 i (target-nil-value))
+  (lwz temp0 a vsp)
+  (unbox-fixnum imm1 temp0)
+  (unbox-fixnum imm2 b)
+  (beq cr0 @got-a)
+  (la imm1 ppc32::misc-data-offset i)
+  (lwzx imm1 temp0 imm1)
+  @got-a
+  (beq cr1 @got-b)
+  (la imm2 ppc32::misc-data-offset j)
+  (lwzx imm2 b imm2)
+  @got-b
+  (lwz temp0 c vsp)
+  (unbox-fixnum imm0 temp0)
+  (addic imm0 imm0 -1)
+  (lwz temp1 r vsp)
+  (lwz temp0 k vsp)
+  (la vsp 16 vsp)  
+  (adde imm0 imm1 imm2)
+  (la imm2 ppc32::misc-data-offset temp0)
+  (stwx imm0 temp1 imm2)
+  (addze imm0 rzero)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+
+
+
+    
+;;; Store the result of A[I] - B[J] - borrow into R[K], returning the borrow.
+;;; If I is NIL, A is a fixnum; likewise for J and B.
+(defppclapfunction %subtract-with-borrow ((r 12) (k 8) (borrow 4) (a 0) (i arg_x) (b arg_y) (j arg_z))
+  (cmpwi cr0 i (target-nil-value))
+  (cmpwi cr1 j (target-nil-value))
+  (lwz temp0 a vsp)
+  (unbox-fixnum imm2 b)
+  (unbox-fixnum imm1 temp0)
+  (beq cr1 @got-b)
+  (la imm2 ppc32::misc-data-offset j)
+  (lwzx imm2 b imm2)
+  @got-b
+  (beq cr0 @got-a)
+  (la imm1 ppc32::misc-data-offset i)
+  (lwzx imm1 temp0 imm1)
+  @got-a
+  (lwz temp0 borrow vsp)
+  (unbox-fixnum imm0 temp0)
+  (addic imm0 imm0 -1)
+  (lwz temp0 r vsp)
+  (lwz temp1 k vsp)
+  (la vsp 16 vsp)  
+  (subfe imm0 imm2 imm1)
+  (la imm1 ppc32::misc-data-offset temp1)
+  (stwx imm0 temp0 imm1)
+  (addze imm0 rzero)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+;; multiply i'th digit of x by y and add to result starting at digit i
+(defppclapfunction %multiply-and-add-harder-loop-2
+    ((x-ptr 4) (y-ptr 0) (resptr arg_x)(residx arg_y) (count arg_z))  
+  (let ((tem imm0)
+        (y imm1)
+        (prod-h imm2)
+        (prod-l imm3)
+        (x imm4)
+        (xptr temp2)
+        (yidx temp1)
+        (yptr temp0))
+    (lwz xptr x-ptr vsp)
+    (la tem ppc32::misc-data-offset residx)
+    (lwzx x xptr tem)
+    (lwz yptr y-ptr vsp)
+    (li yidx 0) ; init yidx 0 
+    (addc prod-h rzero rzero) ; init carry 0, mumble 0
+    @loop
+    (subi count count '1)
+    (cmpwi count 0)
+    (la tem ppc32::misc-data-offset yidx)   ; get yidx
+    (lwzx y yptr tem) 
+    (mullw prod-l x y)
+    (addc prod-l prod-l prod-h)
+    (mulhwu prod-h x y)
+    (addze prod-h prod-h)
+    (la tem ppc32::misc-data-offset residx)
+    (lwzx y resptr tem)    
+    (addc prod-l prod-l y)
+    (addze prod-h prod-h)
+    (stwx prod-l resptr tem)    
+    (addi residx residx '1)
+    (addi yidx yidx '1)
+    (bgt @loop)
+    (la tem ppc32::misc-data-offset residx)
+    (stwx prod-h resptr tem)
+    (la vsp 8 vsp)      
+    (blr)))
+
+
+
+;;; Multiply X[I] by the unboxed value of the (non-negative) fixnum Y;
+;;; add the incoming carry from CARRY[0] to the 64-bit product.  Store
+;;; the low word of the 64-bit sum in R[0] and the high word in
+;;; CARRY[0].
+
+(defppclapfunction %multiply-and-add ((r 4) (carry 0) (x arg_y) (i arg_x) (y arg_z))
+  (unbox-fixnum imm0 arg_z)
+  (la imm1 ppc32::misc-data-offset i)
+  (lwzx imm1 x imm1)
+  (mulhwu imm2 imm0 imm1)
+  (mullw imm1 imm0 imm1)
+  (lwz temp0 carry vsp)
+  (lwz imm0 ppc32::misc-data-offset temp0)
+  (addc imm1 imm1 imm0)
+  (addze imm2 imm2)
+  (stw imm2 ppc32::misc-data-offset temp0)
+  (lwz arg_z r vsp)
+  (la vsp 8 vsp)    
+  (stw imm1 ppc32::misc-data-offset arg_z)
+  (blr))
+  
+(defppclapfunction %floor ((q 4) (r 0) (num-high arg_x) (num-low arg_y) (denom-arg arg_z))
+  (let ((rem imm0)
+	(rem-low imm1)
+	(quo imm2)
+	(temp imm3)
+	(denom imm4))
+    (lwz denom ppc32::misc-data-offset denom)
+    (lwz rem ppc32::misc-data-offset num-high)
+    (lwz rem-low ppc32::misc-data-offset num-low)
+    (mr temp denom)
+    (sltu quo rem denom)
+    (subi temp temp quo)
+    (and temp temp denom)
+    (sub rem temp rem)
+    (li temp0 '32)
+    @loop
+    (subi temp0 temp0 '1)
+    (cmpwi temp0 0)
+    (slwi rem rem 1)
+    (srwi temp rem-low 31)
+    (or rem rem temp)
+    (slwi rem-low rem-low 1)
+    (sltu rem rem denom)
+    (slwi quo quo 1)
+    (or quo quo temp)
+    (subi temp temp 1)
+    (and temp temp denom)
+    (sub rem rem temp)
+    (bne @loop)
+    (not quo quo)
+    (lwz temp0 q vsp)
+    (stw quo ppc32::misc-data-offset temp0)
+    (lwz arg_z r vsp)
+    (la vsp 8 vsp)  
+    (stw rem ppc32::misc-data-offset arg_z)
+    (blr)))
+
+(defppclapfunction %bignum-ref-hi ((bignum arg_y) (i arg_z))
+  (la imm1 ppc32::misc-data-offset i)
+  (lhzx imm0 bignum imm1)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+
+(defppclapfunction %bignum-set ((bignum 0) (i arg_x) (high arg_y) (low arg_z))
+  (compose-digit imm0 high low)
+  (lwz arg_z bignum vsp)
+  (vset32 imm0 arg_z i imm1)
+  (la vsp 4 vsp)
+  (blr))
+
+
+
+
+; this is silly 
+(defppclapfunction %add-the-carry ((b-h arg_x) (b-l arg_y) (carry-in arg_z))
+  (let ((a imm0)
+        (b imm1)
+        (temp imm2)
+        (c imm3))    
+    (compose-digit b b-h b-l)
+    (unbox-fixnum c carry-in)
+    (add b c b)
+    (digit-h temp0 b)
+    (digit-l temp1 b)
+    (vpush temp0)
+    (vpush temp1)
+    (la temp0 8 vsp)
+    (set-nargs 2)
+    (ba .SPvalues)))
+
+
+
+
+;;; %SUBTRACT-WITH-BORROW -- Internal.
+;;;
+;;; This should be in assembler, and should not cons intermediate results.  It
+;;; returns a 32bit digit and a borrow resulting from subtracting b from a, and
+;;; subtracting a possible incoming borrow.
+;;;
+;;; We really do:  a - b - 1 + borrow, where borrow is either 0 or 1.
+;;; 
+
+(defppclapfunction %subtract-with-borrow-1 ((a-h 4) (a-l 0) (b-h arg_x) (b-l
+arg_y) (borrow-in arg_z))
+  (let ((a imm0)
+        (b imm1)
+        (temp imm2)
+        (c imm3))
+    (lwz temp0 a-h vsp)
+    (lwz temp1 a-l vsp)
+    (compose-digit a temp0 temp1)
+    (compose-digit b b-h b-l)
+    (unbox-fixnum c borrow-in)
+    (li temp -1)
+    (addc temp c temp)
+    (subfe a b a)
+    (addze c rzero)
+    (box-fixnum c c)
+    (digit-h temp0 a)
+    (digit-l temp1 a)
+    (vpush temp0)
+    (vpush temp1)
+    (vpush c)
+    (la temp0 20 vsp)
+    (set-nargs 3)
+    (ba .SPvalues)))
+
+
+
+(defppclapfunction %subtract-one ((a-h arg_y)(a-l arg_z))
+  (let ((a imm0))
+    (compose-digit a a-h a-l)
+    (subi a a 1)
+    (digit-h temp0 a)
+    (vpush temp0)
+    (digit-l temp0 a)
+    (vpush temp0)
+    (la temp0 8 vsp)
+    (set-nargs 2)
+    (ba .spvalues)))
+
+
+
+
+;;; %MULTIPLY-AND-ADD  --  Internal.
+;;;
+;;; This multiplies x-digit and y-digit, producing high and low digits
+;;; manifesting the result.  Then it adds the low digit, res-digit, and
+;;; carry-in-digit.  Any carries (note, you still have to add two digits at a
+;;; time possibly producing two carries) from adding these three digits get
+;;; added to the high digit from the multiply, producing the next carry digit.
+;;; Res-digit is optional since two uses of this primitive multiplies a single
+;;; digit bignum by a multiple digit bignum, and in this situation there is no
+;;; need for a result buffer accumulating partial results which is where the
+;;; res-digit comes from.
+;;; [slh] I assume that the returned carry "digit" can only be 0, 1 or 2
+
+
+(defppclapfunction %multiply-and-add-1 ((x-high 8)
+					(x-low 4)
+					(y-high 0)
+					(y-low arg_x)
+					(carry-in-high arg_y)
+					(carry-in-low arg_z))
+  (let ((x imm0)
+	(y imm1)
+	(carry-in imm2)
+	(lo imm3)
+	(hi imm4))
+    (compose-digit carry-in carry-in-high carry-in-low)
+    (vpop temp0)
+    (compose-digit y temp0 y-low)
+    (vpop temp0)
+    (vpop temp1)
+    (compose-digit x temp1 temp0)
+    (mullw lo x y)
+    (mulhwu hi x y)
+    (addc lo lo carry-in)
+    (addze hi hi)
+    (digit-h temp0 hi)
+    (digit-l temp1 hi)
+    (digit-h temp2 lo)
+    (digit-l temp3 lo)
+    (vpush temp0)
+    (vpush temp1)
+    (vpush temp2)
+    (vpush temp3)
+    (set-nargs 4)
+    (la temp0 16 vsp)
+    (ba .SPvalues)))
+
+
+(defppclapfunction %logcount-complement ((bignum arg_y) (idx arg_z))
+  (let ((arg imm0)
+        (shift imm1)
+        (temp imm2))
+    (la arg ppc32::misc-data-offset idx)
+    (lwzx arg bignum arg)
+    (not. shift arg)
+    (li arg_z 0)
+    (if ne
+      (progn
+        @loop
+        (la temp -1 shift)
+        (and. shift shift temp)
+        (la arg_z '1 arg_z)
+        (bne @loop)))
+    (blr)))
+
+(defppclapfunction %logcount ((bignum arg_y) (idx arg_z))
+  (let ((arg imm0)
+        (shift imm1)
+        (temp imm2))
+    (la arg ppc32::misc-data-offset idx)
+    (lwzx arg bignum arg)
+    (mr. shift arg)
+    (li arg_z 0)
+    (if ne
+      (progn
+        @loop
+        (la temp -1 shift)
+        (and. shift shift temp)
+        (la arg_z '1 arg_z)
+        (bne @loop)))
+    (blr)))
+
+; return res
+(defppclapfunction bignum-add-loop-2 ((aptr arg_x)(bptr arg_y) (result arg_z))
+  (let ((idx imm0)
+        (count imm1)
+        (x imm2)
+        (y imm3)        
+        (len-a temp0)
+        (len-b temp1)
+        (tem temp2))
+    (li idx ppc32::misc-data-offset)    
+    (lwz imm4 ppc32::misc-header-offset aptr)
+    (header-length len-a imm4)
+    (lwz imm4 ppc32::misc-header-offset bptr)
+    (header-length len-b imm4)
+    ; make a be shorter one
+    (cmpw len-a len-b)
+    (li count 0)
+    ; initialize carry 0
+    (addc x rzero rzero)
+    (ble @loop)
+    ; b shorter - swap em
+    (mr tem len-a)
+    (mr len-a len-b)
+    (mr len-b tem)
+    (mr tem aptr)
+    (mr aptr bptr)
+    (mr bptr tem)    
+    @loop
+    (lwzx y aptr idx)
+    (lwzx x bptr idx)    
+    (addi count count '1)
+    (cmpw count len-a)
+    (adde x x y)
+    (stwx x result idx)
+    (addi idx idx '1)
+    (blt @loop)
+    ; now propagate carry thru longer (b) using sign of shorter    
+    ;(SUBI imm4 idx '1) ; y has hi order word of a
+    ;(lwzx y aptr imm4)
+    (cmpw len-a len-b)
+    (adde imm4 rzero rzero) ; get carry
+    (srawi y y 31)  ; p.o.s clobbers carry 
+    (addic imm4 imm4 -1)  ; restore carry
+    (beq @l3)  ; unless equal
+    @loop2
+    (lwzx x bptr idx)
+    (adde x x y)
+    (stwx x result idx)
+    (addi count count '1)
+    (cmpw count len-b)
+    (addi idx idx '1)
+    (blt @loop2)
+    ; y has sign of shorter - get sign of longer to x
+    @l3
+    (subi imm4 idx '1)
+    (lwzx x bptr imm4)
+    (adde imm4 rzero rzero) ; get carry
+    (srawi x x 31)  ; clobbers carry 
+    (addic imm4 imm4 -1)
+    (adde x x y)
+    (stwx x result idx)
+    (blr)))
+
+;; same as above but with initial a index and finishes
+(defppclapfunction bignum-add-loop-+ ((init-a 0)(aptr arg_x)(bptr arg_y)(length arg_z))
+  (let ((idx imm0)        
+        (count imm1)
+        (x imm2)
+        (y imm3)
+        (aidx imm4))
+    (li idx ppc32::misc-data-offset)
+    (lwz aidx init-a vsp)
+    (addi aidx aidx ppc32::misc-data-offset)
+    (li count 0)
+    ; initialize carry 0
+    (addc x rzero rzero)
+    @loop
+    (lwzx x aptr aidx)
+    (lwzx y bptr idx)
+    (adde x x y)
+    (stwx x aptr aidx)
+    (addi count count '1)
+    (cmpw count length)
+    (addi idx idx '1)
+    (addi aidx aidx '1)
+    (blt @loop)
+    (lwzx x aptr aidx)  ; add carry into next one
+    (adde x x  rzero)
+    (stwx x aptr aidx)
+    (la vsp 4 vsp)
+    (blr)))
+
+
+
+(defppclapfunction bignum-negate-loop-really ((big arg_x) (len arg_y) (result arg_z))
+  (let ((idx imm0)
+        (one imm1)
+        (x imm2))
+    (li idx ppc32::misc-data-offset)
+    (li one '1)
+    ; initialize carry 1
+    (li x -1)
+    (addic x x 1)
+    @loop        
+    ;(addi count count '1)    
+    ;(cmpw count len)
+    (subf. len one len)
+    (lwzx x big idx)
+    (not x x)
+    (adde x x rzero)
+    (stwx x result idx)    
+    (addi idx idx '1)
+    (bgt @loop)
+    ; return carry
+    (li x 0)
+    (adde x x  rzero)
+    (box-fixnum arg_z x)
+    (blr)))
+
+(defppclapfunction bignum-negate-to-pointer ((big arg_x) (len arg_y) (result arg_z))
+  (let ((idx imm0)
+        (one imm1)
+        (x imm2)
+        (oidx imm3)
+        (ptr imm4))
+    (li idx ppc32::misc-data-offset)
+    (li oidx 0)
+    (macptr-ptr ptr result)
+    (li one '1)
+    ; initialize carry 1
+    (li x -1)
+    (addic x x 1)
+    @loop        
+    ;(addi count count '1)    
+    ;(cmpw count len)
+    (subf. len one len)
+    (lwzx x big idx)
+    (not x x)
+    (adde x x rzero)
+    (stwx x ptr oidx)    
+    (addi idx idx '1)
+    (addi oidx oidx 4)
+    (bgt @loop)
+    ; return carry
+    (li x 0)
+    (adde x x  rzero)
+    (box-fixnum arg_z x)
+    (blr)))
+
+;; she do tolerate len = jidx
+(defppclapfunction bignum-shift-left-loop ((nbits 4)(result 0) (bignum arg_x) (len arg_y) (jidx arg_z))
+  (let ((y imm0)
+        (idx imm1)
+        (bits imm2)
+        (rbits imm3)
+        (x imm4)
+        (iidx temp0)
+        (resptr temp1))
+    (li iidx 0)
+    (lwz bits nbits vsp)
+    (lwz resptr result vsp)
+    (unbox-fixnum bits bits)
+    (subfic rbits bits 32)    
+    ;(dbg)
+    (lwz imm4 ppc32::misc-data-offset bignum)
+    (slw imm4 imm4 bits)
+    (la y (+ ppc32::misc-data-offset -4) jidx)  
+    (stwx imm4 y resptr) 
+     
+    (cmpw len jidx)
+    (beq @done)
+    @loop
+    (addi idx iidx ppc32::misc-data-offset)
+    (lwzx x bignum idx)
+    (srw x x rbits)
+    (addi idx idx '1)
+    (lwzx y bignum idx)
+    (slw y y bits)
+    (or x x y)
+    (addi idx jidx ppc32::misc-data-offset)
+    (stwx x resptr idx)
+    (addi jidx jidx '1)    
+    (cmpw jidx len)
+    (addi iidx iidx '1)
+    (blt @loop)    
+    @done
+    ; do first - lo order
+       
+    ; do last - hi order    
+    (addi idx iidx ppc32::misc-data-offset)
+    ;(dbg t)
+    (lwzx y bignum idx)
+    (sraw y y rbits)
+    (addi idx len ppc32::misc-data-offset)
+    (stwx y resptr idx)
+    (la vsp 8 vsp)
+    (blr)))
+
+
+
+(defppclapfunction bignum-shift-right-loop-1 ((nbits 4)(result 0) (bignum arg_x) (len arg_y) (iidx arg_z))
+  (let ((y imm0)
+        (idx imm1)
+        (bits imm2)
+        (rbits imm3)
+        (x imm4)
+        (jidx temp0)
+        (resptr temp1))
+    (li jidx 0)
+    (lwz bits nbits vsp)
+    (lwz resptr result vsp)
+    (unbox-fixnum bits bits)
+    (cmpw jidx len)
+    (subfic rbits bits 32)    
+    (bge @done)
+    @loop
+    (addi idx iidx ppc32::misc-data-offset)
+    (lwzx x bignum idx)
+    (srw x x bits)
+    (addi idx idx '1)
+    (lwzx y bignum idx)
+    (slw y y rbits)
+    (or x x y)
+    (addi idx jidx ppc32::misc-data-offset)
+    (stwx x resptr idx)
+    (addi jidx jidx '1)    
+    (cmpw jidx len)
+    (addi iidx iidx '1)
+    (blt @loop)
+    @done
+    (addi idx iidx ppc32::misc-data-offset)
+    (lwzx x bignum idx)
+    (sraw x x bits)
+    (addi idx jidx ppc32::misc-data-offset)
+    (stwx x resptr idx)
+    (la vsp 8 vsp)
+    (blr)))
+
+
+(defppclapfunction %compare-digits ((a arg_x) (b arg_y) (idx arg_z))
+  (la imm0 ppc32::misc-data-offset idx)
+  (lwzx imm1 a imm0)
+  (lwzx imm0 b imm0)
+  (cmplw imm1 imm0)
+  (li arg_z '0)
+  (beqlr)
+  (li arg_z '1)
+  (bgtlr)
+  (li arg_z '-1)
+  (blr))
+
+
+  
+;; returns number of bits in digit-hi,digit-lo that are sign bits
+;; 32 - digits-sign-bits is integer-length
+
+(defppclapfunction %digits-sign-bits ((hi arg_y) (lo arg_z))
+  (rlwinm. imm1 hi (- 16 ppc32::fixnumshift) 0 15)
+  (rlwimi imm1 lo (- 32 ppc32::fixnumshift) 16 31)
+  (not imm1 imm1)
+  (blt @wasneg)
+  (not imm1 imm1)
+  @wasneg
+  (cntlzw imm1 imm1)
+  (box-fixnum arg_z imm1)
+  (blr))
+
+(defppclapfunction bignum-logtest-loop ((count arg_x) (s1 arg_y) (s2 arg_z))  
+  (addi imm1 rzero ppc32::misc-data-offset)
+  @loop
+  (lwzx imm2 s1 imm1)
+  (lwzx imm3 s2 imm1)
+  (and. imm2 imm3 imm2)  
+  (addi imm1 imm1 4)
+  (bne @true)
+  (subic. count count 4)
+  (bgt  @loop)
+  (li arg_z (target-nil-value))
+  (blr)
+  @true
+  (li arg_z (+ (target-nil-value)  ppc32::t-offset))
+  (blr))
+
+;;; dest[idx] <- (lognot src[idx])
+(defppclapfunction %bignum-lognot ((idx arg_x) (src arg_y) (dest arg_z))
+  (la imm1 ppc32::misc-data-offset idx)
+  (lwzx imm0 src imm1)
+  (not imm0 imm0)
+  (stwx imm0 dest imm1)
+  (blr))
+
+;;; dest[idx] <- (logand x[idx] y[idx])
+(defppclapfunction %bignum-logand ((idx 0) (x arg_x) (y arg_y) (dest arg_z))
+  (vpop temp0)
+  (la imm1 ppc32::misc-data-offset temp0)
+  (lwzx imm0 x imm1)
+  (lwzx imm2 y imm1)
+  (and imm0 imm0 imm2)
+  (stwx imm0 dest imm1)
+  (blr))
+
+;;; dest[idx] <- (logandc2 x[idx] y[idx])
+(defppclapfunction %bignum-logandc2 ((idx 0) (x arg_x) (y arg_y) (dest arg_z))
+  (vpop temp0)
+  (la imm1 ppc32::misc-data-offset temp0)
+  (lwzx imm0 x imm1)
+  (lwzx imm2 y imm1)
+  (andc imm0 imm0 imm2)
+  (stwx imm0 dest imm1)
+  (blr))
+
+;;; dest[idx] <- (logandc1 x[idx] y[idx])
+(defppclapfunction %bignum-logandc1 ((idx 0) (x arg_x) (y arg_y) (dest arg_z))
+  (vpop temp0)
+  (la imm1 ppc32::misc-data-offset temp0)
+  (lwzx imm0 x imm1)
+  (lwzx imm2 y imm1)
+  (andc imm0 imm2 imm0)
+  (stwx imm0 dest imm1)
+  (blr))
+
+
+
+(defppclapfunction digit-lognot-move ((index arg_x) (source arg_y) (dest arg_z))
+  (let ((scaled-index imm1))
+    (vref32 imm0 source index scaled-index) ; imm1 has c(index) + data-offset
+    (not imm0 imm0)
+    (stwx imm0 dest scaled-index)
+    (blr)))
+
+; if dest not nil store unboxed result in dest(0), else return boxed result
+(defppclapfunction fix-digit-logandc2 ((fix arg_x) (big arg_y) (dest arg_z)) ; index 0
+  (let ((w1 imm0)
+        (w2 imm1))
+    (unbox-fixnum  w1 fix)
+    (lwz w2 ppc32::misc-data-offset big)
+    (cmpwi dest (target-nil-value))
+    (not w2 w2)
+    (and w1 w1 w2)
+    (bne @store)
+    (box-fixnum arg_z w1)
+    (blr)
+    @store
+    (stw w1 ppc32::misc-data-offset dest)
+    (blr)))
+
+
+
+(defppclapfunction fix-digit-logand ((fix arg_x) (big arg_y) (dest arg_z)) ; index 0
+  (let ((w1 imm0)
+        (w2 imm1))
+    (unbox-fixnum  w1 fix)
+    (lwz w2 ppc32::misc-data-offset big)
+    (cmpwi dest (target-nil-value))
+    (and w1 w1 w2)
+    (bne @store)
+    (box-fixnum arg_z w1)
+    (blr)
+    @store
+    (stw w1 ppc32::misc-data-offset dest)
+    (blr)))
+
+
+
+(defppclapfunction fix-digit-logandc1 ((fix arg_x) (big arg_y) (dest arg_z)) ; index 0
+  (let ((w1 imm0)
+        (w2 imm1))
+    (unbox-fixnum  w1 fix)
+    (lwz w2 ppc32::misc-data-offset big)
+    (cmpwi dest (target-nil-value))
+    (not w1 w1)
+    (and w1 w1 w2)
+    (bne @store)
+    (box-fixnum arg_z w1)
+    (blr)
+    @store
+    (stw w1 ppc32::misc-data-offset dest)
+    (blr)))
+
+;;; dest[idx] <- (logior x[idx] y[idx])
+(defppclapfunction %bignum-logior ((idx 0) (x arg_x) (y arg_y) (dest arg_z))
+  (vpop temp0)
+  (la imm1 ppc32::misc-data-offset temp0)
+  (lwzx imm0 x imm1)
+  (lwzx imm2 y imm1)
+  (or imm0 imm0 imm2)
+  (stwx imm0 dest imm1)
+  (blr))
+
+;;; dest[idx] <- (logxor x[idx] y[idx])
+(defppclapfunction %bignum-logxor ((idx 0) (x arg_x) (y arg_y) (dest arg_z))
+  (vpop temp0)
+  (la imm1 ppc32::misc-data-offset temp0)
+  (lwzx imm0 x imm1)
+  (lwzx imm2 y imm1)
+  (xor imm0 imm0 imm2)
+  (stwx imm0 dest imm1)
+  (blr))
+
+
+
+(defppclapfunction bignum-xor-loop ((count 0) (s1 arg_x) (s2 arg_y) (dest arg_z))
+  (lwz imm0 count vsp)
+  (addi imm1 rzero ppc32::misc-data-offset)
+  @loop
+  (lwzx imm2 s1 imm1)
+  (lwzx imm3 s2 imm1)
+  (xor imm2 imm3 imm2)
+  (subic. imm0 imm0 4)
+  (stwx imm2 dest imm1)
+  (addi imm1 imm1 4)
+  (bgt @loop)
+  @out
+  (la vsp 4 vsp)
+  (blr))
+
+#+nomore
+(defppclapfunction try-guess-loop-1 ((guess-h 8)(guess-l 4)(len-y 0)
+                                     (xidx arg_x) (xptr arg_y) (yptr arg_z))
+  (let ((guess imm0)
+        (carry imm1)
+        (y imm2)
+        (x imm2)
+        (prod-l imm3)
+        (prod-h imm4)
+        (tem imm4)
+        (yidx temp0)
+        (end-y temp1)
+        (carry-bit temp2))
+    (lwz x guess-h vsp)
+    (lwz tem guess-l vsp)
+    (compose-digit guess x tem)
+    (lwz end-y len-y vsp)
+    (li yidx 0)
+    (li carry 0) 
+    (li carry-bit '1)
+    @loop
+    ; multiply guess by ydigit, add carry to lo, hi is new carry
+    ; then get an xdigit subtract prod-lo from it and store result in x (remember carry)
+    (addi tem yidx ppc32::misc-data-offset)   ; get yidx
+    (lwzx y yptr tem)
+    (mullw prod-l guess y)
+    (mulhwu prod-h guess y)    
+    (addc prod-l prod-l carry) 
+    (adde carry prod-h rzero)
+    ; get back saved carry
+    (li tem '-1)
+    (addc tem carry-bit tem)
+    (addi tem xidx ppc32::misc-data-offset)
+    (lwzx x xptr tem)    
+    (subfe x prod-l x)        
+    (stwx x xptr tem)
+    ; save carry
+    (adde prod-l rzero rzero)
+    (box-fixnum carry-bit prod-l)
+    (addi yidx yidx '1)
+    (cmpw yidx end-y)
+    (addi xidx xidx '1)
+    (blt @loop)
+    ; finally subtract carry from last x digit
+    @done
+    (li prod-l '-1)  ; get back saved carry again - box clobbered it?
+    (addc prod-l carry-bit prod-l)
+    (addi tem xidx ppc32::misc-data-offset) ; maybe still there - nope
+    (lwzx x xptr tem)
+    (subfe x carry x)
+    (stwx x xptr tem)
+    (la vsp 12 vsp)
+    (blr)))
+
+;; x0 is at index, x1 at index-1, x2 at index-2
+;; y1 is at index, y2 at index-1
+;; this doesnt help much
+(defppclapfunction truncate-guess-loop ((guess-h 8)(guess-l 4)(x 0)
+                                        (xidx arg_x)(yptr arg_y) (yidx arg_z))
+  (let ((guess imm0)
+        (y1 imm1)
+        (y2 imm1)
+        (gy1-lo imm2) ; look out below
+        (gy1-hi imm2)
+        (gy2-lo imm2)
+        (gy2-hi imm2)
+        (xptr temp0)
+        (m imm3)
+        (tem imm4)
+        (y1-idx 28)
+        (y2-idx 24)
+        (x0-idx 20)
+        (x1-idx 16)
+        (x2-idx 12))
+    (stwu tsp -32 tsp)
+    (stw tsp 4 tsp)
+    (lwz y1 guess-h vsp)
+    (lwz tem guess-l vsp)
+    (compose-digit guess y1 tem)
+    (addi tem yidx ppc32::misc-data-offset)
+    (lwzx y1 yptr tem)
+    (stw y1 y1-idx tsp)
+    (subi tem tem 4)
+    (lwzx y2 yptr tem)
+    (stw y2 y2-idx tsp)
+    (lwz xptr x vsp)
+    (addi tem xidx ppc32::misc-data-offset)
+    (lwzx y1 xptr tem) ; its x0
+    (stw y1 x0-idx tsp)
+    (subi tem tem 4)
+    (lwzx y1 xptr tem)
+    (stw y1 x1-idx tsp)
+    (subi tem tem 4)
+    (lwzx y1 xptr tem)
+    (stw y1 x2-idx tsp)
+    @loop
+    (lwz y1 y1-idx tsp)     ; get y1
+    (mullw gy1-lo guess y1)
+    (lwz m x1-idx tsp)      ; get x1
+    (subc m m gy1-lo)      ; x1 - gy1-lo => m
+    (mulhwu gy1-hi guess y1)
+    (lwz tem x0-idx tsp)    ; get x0
+    (subfe. tem gy1-hi tem)      ; - val not used just cr
+    (lwz y2 y2-idx tsp)     ; get y2
+    (mulhwu gy2-hi guess y2)   ; does it pay to do this now even tho may not need?
+    (bne @done)
+    (cmpl :cr0 gy2-hi m)       ; if > or = and foo then more - L means logical means unsigned
+    (blt @done)           ; if < done
+    (bne @more)           ; if = test lo
+    (mullw gy2-lo guess y2)
+    (lwz tem x2-idx tsp) ; get x2
+    (cmpl :cr0 gy2-lo tem)
+    (ble @done)
+    @more
+    (subi guess guess 1)
+    (b @loop)
+    @done
+    (digit-h temp0 guess)
+    (vpush temp0)
+    (digit-l temp0 guess)
+    (vpush temp0)
+    (la temp0 20 vsp)
+    (lwz tsp 0 tsp)
+    (set-nargs 2)
+    (ba .spvalues)))
+
+(defppclapfunction normalize-bignum-loop ((sign arg_x)(res arg_y)(len arg_z))
+  (let ((idx imm0)
+        (usign imm1)
+        (val imm2))      
+    (unbox-fixnum usign sign)
+    (cmpwi len 0)
+    (addi idx len (- ppc32::misc-data-offset 4))  
+    (beqlr) ; huh - can this ever happen?
+    @loop
+    (lwzx val res idx)
+    (cmpw  val usign)    
+    (subi idx idx '1)
+    (bne @neq)    
+    (subic. len len '1)
+    (bgt @loop)
+    ; fall through - its all sign - return 1
+    (li arg_z '1)
+    (blr)
+    @neq
+    (rlwinm usign usign 0 0 0) ; hi bit
+    (rlwinm val val 0 0 0)
+    (cmpw usign val)  ; is hi bit = sign, if so then done   
+    (beqlr)
+    (addi len len '1) ; if not, need 1 more
+    (blr)))
+
+(defppclapfunction %normalize-bignum-2 ((fixp arg_y)(res arg_z))
+  (let ((idx imm0)
+        (usign imm1)
+        (val imm2)
+        (len arg_x)
+        (oldlen temp0))
+    (lwz imm4 (- ppc32::fulltag-misc) res)
+    (header-length len imm4)
+    (cmpwi len 0)
+    (mr oldlen len)
+    (addi idx len (- ppc32::misc-data-offset 4))  
+    (beqlr) ; huh - can this ever happen?
+    (lwzx val res idx) ; high order word
+    (srawi usign val 31) ; get sign
+    @loop
+    (lwzx val res idx)
+    (cmpw  val usign)    
+    (subi idx idx '1)
+    (bne @neq)    
+    (subic. len len '1)
+    (bgt @loop)
+    ; fall through - its all sign - return 1
+    (li len '1)
+    (rlwinm usign usign 0 0 0) ; hi bit
+    (b @more)
+    @neq
+    (rlwinm usign usign 0 0 0) ; hi bit
+    (rlwinm val val 0 0 0)
+    (cmpw usign val)  ; is hi bit = sign, if so then done   
+    (beq @more)
+    (addi len len '1) ; if not, need 1 more
+    (b @big)
+    @more
+    (cmpwi :cr1 fixp (target-nil-value))
+    (cmpwi len '1)
+    (beq :cr1 @big)  ; dont return fixnum
+    (bgt @big)
+    ;; stuff for maybe fixnum
+    ;(dbg t)
+    (lwz val ppc32::misc-data-offset res)
+    (rlwinm imm4 val 0 0 2) ; hi 3 bits same? - we assume fixnumshift is 2
+    (srawi usign usign 2)
+    (cmpw usign imm4)
+    (bne @big)    
+    (box-fixnum arg_z val)
+    (blr)
+    @big
+    (cmpw oldlen len)
+    (beqlr) ; same length - done
+    (li imm4 ppc32::subtag-bignum) ; set new length
+    (rlwimi imm4 len (- ppc32::num-subtag-bits ppc32::fixnumshift) 0 (- 31 ppc32::num-subtag-bits))
+    (stw imm4 ppc32::misc-header-offset res)
+    ; 0 to tail if negative
+    (cmpwi usign 0)
+    (beqlr) 
+     ; zero from len inclusive to oldlen exclusive
+    ;(dbg t)
+    (addi idx len ppc32::misc-data-offset)
+    @loop2
+    (stwx rzero idx res)
+    (addi len len '1)
+    (cmpw len oldlen)
+    (addi idx idx '1)
+    (blt @loop2)
+    (blr)))
+
+(defppclapfunction %count-digit-leading-zeros ((high arg_y) (low arg_z))
+  (compose-digit imm0 high low)
+  (cntlzw imm0 imm0)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %count-digit-trailing-zeros ((high arg_y) (low arg_z))
+  (compose-digit imm0 high low)
+  (neg imm1 imm0)
+  (and imm0 imm0 imm1)
+  (cntlzw imm0 imm0)
+  (subfic imm0 imm0 31)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+
+(defppclapfunction %bignum-count-trailing-zero-bits ((bignum arg_z))
+  (let ((ndigits arg_x)
+	(nbits arg_y)
+	(digit imm0)
+	(ptr imm1))
+    (li ptr ppc32::misc-data-offset)
+    (li ndigits '-32)
+    @next
+    (lwzx digit bignum ptr)
+    (cmpwi digit 0)
+    (la ptr 4 ptr)
+    (addi ndigits ndigits '32)
+    (beq @next)
+    (neg ptr digit)
+    (and digit digit ptr)
+    (cntlzw digit digit)
+    (subfic digit digit 31)
+    (box-fixnum nbits digit)
+    (add arg_z nbits ndigits)
+    (blr)))
+
+
+(defppclapfunction %bignum-trim-leading-zeros ((bignum arg_x)
+					       (start arg_y)
+					       (len arg_z))
+  (add imm1 start len)
+  (la imm1 (- ppc32::misc-data-offset 4) imm1)
+  @loop
+  (cmpwi cr0 len '1)
+  (lwzx imm0 bignum imm1)
+  (cmpwi cr1 imm0 0)
+  (la imm1 -4 imm1)
+  (bnelr cr1)
+  (la len '-1 len)
+  (bne @loop)
+  (blr))
+  
+;;; Set length of bignum to new-len (zeroing out any trailing words between
+;;; the old length and the new.
+(defppclapfunction %shrink-bignum ((new-len arg_y) (bignum arg_z))
+  (let ((old-len temp0)
+	(old-idx imm0)
+	(new-idx imm2)
+	(header imm1))
+    (getvheader header bignum)
+    (header-length old-len header)
+    (cmpw old-len new-len)
+    (la old-idx ppc32::misc-data-offset old-len)
+    (la new-idx ppc32::misc-data-offset new-len)
+    (beqlr)
+    @loop
+    (subi old-idx old-idx 4)
+    (cmpw old-idx new-idx)
+    (stwx ppc32::rzero bignum old-idx)
+    (bne @loop)
+    (slwi header new-len (- ppc32::num-subtag-bits ppc32::fixnumshift))
+    (ori header header ppc32::subtag-bignum)
+    (stw header ppc32::misc-header-offset bignum)
+    (blr)))
+    
+;;; Especially when large operands are involved, the GNU Multiple Precision
+;;; library's algorithm's are often faster than Clozure CL's.  GMP's MPN
+;;; library defines operations on "limb vectors", which are basically
+;;; just sequences of 32-bit digits (least-significant digit first), which
+;;; is just about exactly the same way that Clozure CL stores bignums.
+;;; We might want to (eventually) link some or all of GMP into Clozure CL;
+;;; in the meantime, it seems that we get some performance benefit from
+;;; using GMP representation and algorithms in some mixture of LAP and Lisp.
+;;; To approximate the "limb vector" representation, we copy operands to
+;;; (and results from) stack-allocated macptrs.  Since those macptrs are
+;;; word-aligned, we can use fixnums to represent word-aligned pointers.
+;;; Obviously, it costs a little to copy back and forth like this; we
+;;; only win when operands are fairly large, and when we can replace an
+;;; N^2 algorithm with something cheaper.
+
+;;; Macptr MUST be word-aligned (low 2 bits must be 0).  Extract
+;;; such an address, return it as a fixnum.
+(defppclapfunction macptr->fixnum ((ptr arg_z))
+  (macptr-ptr arg_z ptr)
+  (blr))
+
+;;; Copy the limb SRC points to to where DEST points.
+(defppclapfunction copy-limb ((src arg_y) (dest arg_z))
+  (lwz imm0 0 src)
+  (stw imm0 0 dest)
+  (blr))
+
+;;; Return T iff LIMB contains 0.
+(defppclapfunction limb-zerop ((limb arg_z))
+  (lwz imm0 0 limb)
+  (cntlzw imm0 imm0)
+  (srwi imm0 imm0 5)
+  (bit0->boolean arg_z imm0 imm0)
+  (blr))
+
+;;; Return -1,0,1 according to whether the contents of Y are
+;;; <,=,> the contents of Z.
+(defppclapfunction compare-limbs ((y arg_y) (z arg_z))
+  (lwz imm1 0 z)
+  (lwz imm0 0 y)
+  (cmplw imm0 imm1)
+  (li arg_z 0)
+  (beqlr)
+  (li arg_z '1)
+  (bgtlr)
+  (li arg_z '-1)
+  (blr))
+
+;;; Add a fixnum to the limb LIMB points to.  Ignore overflow.
+(defppclapfunction add-fixnum-to-limb ((fixnum arg_y) (limb arg_z))
+  (unbox-fixnum imm0 fixnum)
+  (lwz imm1 0 limb)
+  (add imm1 imm1 imm0)
+  (stw imm1 0 limb)
+  (blr))
+
+;;; Store a fixnum value where LIMB points.
+(defppclapfunction copy-fixnum-to-limb ((fixnum arg_y) (limb arg_z))
+  (unbox-fixnum imm0 fixnum)
+  (stwu imm0 0 limb)
+  (blr))
+
+;;; Increment a "LIMB VECTOR" (bignum) by a small amount.  The caller
+;;; knows that carries will only propagate for a word or two.
+(defppclapfunction mpn-incr-u ((limb arg_y) (fixby arg_z))
+  (let ((by imm0)
+	(sum imm1))
+    (unbox-fixnum by fixby)
+    @loop
+    (lwz sum 0 limb)
+    (add sum sum by)
+    (cmplw sum by)
+    (stw sum 0 limb)
+    (li by 1)
+    (la limb 4 limb)
+    (blt @loop)
+    (blr)))
+
+;;; Store XP-YP at WP; return carry (0 or 1).
+;;; wp, xp, yp: word-aligned, unboxed ptrs (fixnums)
+;;; size: boxed fixnum
+;;; returns boxed carry 
+(defppclapfunction mpn-sub-n ((wp 0) (xp arg_x) (yp arg_y) (size arg_z))
+  (vpop imm0)
+  (subi size size '1)
+  (cmpwi size 0)
+  (lwz imm3 0 xp)
+  (lwz imm4 0 yp)
+  (sub imm1 xp imm0)			; imm1 = xp-wp
+  (sub imm2 yp imm0)			; imm2 = yp-wp
+  (addi imm1 imm1 4)			; imm1 = xp-wp+4
+  (addi imm2 imm2 4)			; imm2 = yp-wp+4
+  (subfc imm3 imm4 imm3)
+  (stw imm3 0 imm0)			; wp[0]
+  (beq @done)
+  @top
+  (subi size size '1)
+  (cmpwi size 0)
+  (lwzx imm3 imm1 imm0)			; imm3 = xp[i]
+  (lwzx imm4 imm2 imm0)			; imm4 = xp[i]
+  (subfe imm3 imm4 imm3)
+  (stwu imm3 4 imm0)
+  (bne @top)
+  @done
+  (subfe imm0 rzero rzero)
+  (subfic imm0 imm0 0)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+;;; Store XP+YP at WP; return carry (0 or 1).
+;;; wp, xp, yp = word-aligned, unboxed macptrs (fixnums).
+;;; size = boxed fixnum
+;;; result = boxed carry
+(defppclapfunction mpn-add-n ((wp 0) (xp arg_x) (yp arg_y) (size arg_z))
+  (vpop imm0)
+  (subi size size '1)
+  (cmpwi size 0)
+  (lwz imm3 0 xp)
+  (lwz imm4 0 yp)
+  (sub imm1 xp imm0)			; imm1 = xp-wp
+  (sub imm2 yp imm0)			; imm2 = yp-wp
+  (addi imm1 imm1 4)			; imm1 = xp-wp+4
+  (addi imm2 imm2 4)			; imm2 = yp-wp+4
+  (addc imm3 imm3 imm4)
+  (stw imm3 0 imm0)			; wp[0]
+  (beq @done)
+  @top
+  (subi size size '1)
+  (cmpwi size 0)
+  (lwzx imm3 imm1 imm0)			; imm3 = xp[i]
+  (lwzx imm4 imm2 imm0)			; imm4 = xp[i]
+  (adde imm3 imm4 imm3)
+  (stwu imm3 4 imm0)
+  (bne @top)
+  @done
+  (addze imm0 rzero)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+;;; Add the single limb LIMB to S1P (propagating carry.)  Store the
+;;; result at RP.  RP and S1P may be the same place, so check for
+;;; that and do nothing after carry stops propagating.  Return carry.
+(defppclapfunction mpn-add-1 ((rp-offset 0) (s1p arg_x) (size arg_y) (limb arg_z))
+  (let ((rp temp0))
+    (vpop rp)
+    (subi size size '1)
+    (cmpwi cr2 size 0)
+    (cmpw cr1 rp s1p)			;a common case
+    (subi rp rp 4)
+    (subi s1p s1p 4)
+    (lwz imm0 0 limb)
+    (lwzu imm1 4 s1p)
+    (addc imm1 imm1 imm0)
+    (addze. imm0 rzero)
+    (stwu imm1 4 rp)
+    (beq cr2 @done)
+    @top
+    (beq cr0 @finish)			; branch if  no more carry
+    (subi size size '1)
+    (cmpwi cr2 size 0)
+    (lwzu imm1 4 s1p)
+    (addc imm1 imm1 imm0)
+    (addze. imm0 rzero)
+    (stwu imm1 4 rp)
+    (bne cr2 @top)
+    (box-fixnum arg_z imm0)
+    (blr)
+    @finish
+    (beq cr1 @done)
+    @loop
+    (subi size size '1)
+    (cmpwi cr2 size 0)
+    (lwzu imm1 4 s1p)
+    (stwu imm1 4 rp)
+    (bne cr2 @loop)
+    @done
+    (box-fixnum arg_z imm0)
+    (blr)))
+;;; Multiply the limb vector S1 by the single limb at LIMBPTR, storing
+;;; the result at RES.  Store the "carry out" (high word of last 64-bit
+;;; partial product) at the limb RESULT.
+;;; res, s1, limbptr, result:
+;;;   unboxed, word-aligned ptrs (fixnums).  size: boxed fixnum
+;;; It'd be hard to transliterate the GMP code here; the GMP version
+;;; uses lots more immediate registers than we can easily use in LAP
+;;; (and is much more aggressively pipelined).
+(defppclapfunction mpn-mul-1 ((res-offset 4)
+			      (s1-offset 0)
+			      (size arg_x)
+			      (limbptr arg_y)
+			      (result arg_z))
+  (let ((limb imm0)
+	(resptr temp0)
+	(s1 temp1)
+	(src imm1)
+	(prod-low imm2)
+	(prod-high imm3)
+	(carry imm4))
+    (lwz resptr res-offset vsp)
+    (lwz s1 s1-offset vsp)
+    (la vsp 8 vsp)
+    (la resptr -4 resptr)		; pre-decrement
+    (la s1 -4 s1)
+    (addic carry carry 0)
+    (li carry 0)
+    (lwz limb 0 limbptr)
+    @loop
+    (subi size size '1)
+    (cmpwi size 0)
+    (lwzu src 4 s1)
+    (mulhwu prod-high src limb)
+    (mullw prod-low src limb)
+    (addc prod-low prod-low carry)
+    (addze carry prod-high)
+    (stwu prod-low 4 resptr)
+    (bne @loop)
+    (stw carry 0 result)
+    (blr)))
+
+;;; multiply s1*limb and add result to res
+;;; res, s1, limbptr, result:
+;;;   unboxed, word-aligned ptrs (fixnums).
+;;; size: boxed fixnum
+;;; limbptr: source "limb".
+;;; result: carry out (high word of product).
+(defppclapfunction mpn-addmul-1 ((res-offset 4)
+				 (s1-offset 0)
+				 (size arg_x)
+				 (limbptr arg_y)
+				 (result arg_z))
+  (let ((limb imm0)
+	(resptr temp0)
+	(s1 temp1)
+	(src imm1)
+	(prod-low imm2)
+	(prod-high imm3)
+	(carry imm4)
+	(prev imm4))
+    (lwz resptr res-offset vsp)
+    (lwz s1 s1-offset vsp)
+    (la vsp 8 vsp)
+    (la resptr -4 resptr)		; pre-decrement
+    (la s1 -4 s1)
+    (addic carry carry 0)
+    (li carry 0)
+    (lwz limb 0 limbptr)
+    @loop
+    (subi size size '1)
+    (cmpwi size 0)
+    (lwzu src 4 s1)
+    (mulhwu prod-high src limb)
+    (mullw prod-low src limb)
+    (addc prod-low prod-low carry)
+    (addze prod-high prod-high)
+    (lwz prev 4 resptr)
+    (addc prev prev prod-low)
+    (stwu prev 4 resptr)
+    (addze carry prod-high)
+    (bne @loop)
+    (stw carry 0 result)
+    (blr)))  
+
+;;; Multiply the UN-word limb vector at UP and the VN-word limb vector
+;;; at VP, store the result at RP.
+(defppclapfunction mpn-mul-basecase ((rp-offset 4)
+				     (up-offset 0)
+				     (un arg_x)
+				     (vp arg_y)
+				     (vn arg_z))
+  (let ((resptr temp0)
+	(s1 temp1)
+	(up temp2)
+	(rp temp3)
+	(size nargs)
+	(limb imm0)
+	(src imm1)
+	(prod-low imm2)
+	(prod-high imm3)
+	(prev imm4)
+	(carry imm4))
+    (lwz resptr rp-offset vsp)
+    (la rp -4 resptr)
+    (lwz up up-offset vsp)
+    (la s1 -4 up)
+    (la vsp 8 vsp)
+    (mr size un)
+    (lwz limb 0 vp)
+    (subi vn vn '1)
+    (cmpwi cr2 vn 0)
+    (li carry 0)
+    @mul-1-loop
+    (subi size size '1)
+    (cmpwi size 0)
+    (lwzu src 4 s1)
+    (mulhwu prod-high src limb)
+    (mullw prod-low src limb)
+    (addc prod-low prod-low carry)
+    (addze carry prod-high)
+    (stwu prod-low 4 rp)
+    (bne @mul-1-loop)
+    (stw carry 4 rp)
+    @again
+    (beq cr2 @done)
+    (subi vn vn '1)
+    (cmpwi cr2 vn 0)
+    (mr rp resptr)
+    (la resptr 4 resptr)
+    (la s1 -4 up)
+    (lwzu limb 4 vp)
+    (mr size un)
+    (addic carry carry 0)
+    (li carry 0)
+    @addmul-1-loop
+    (subi size size '1)
+    (cmpwi size 0)
+    (lwzu src 4 s1)
+    (mulhwu prod-high src limb)
+    (mullw prod-low src limb)
+    (addc prod-low prod-low carry)
+    (addze prod-high prod-high)
+    (lwz prev 4 rp)
+    (addc prev prev prod-low)
+    (stwu prev 4 rp)
+    (addze carry prod-high)
+    (bne @addmul-1-loop)
+    (stw carry 4 rp)
+    (b @again)
+    @done
+    (li arg_z (target-nil-value))
+    (blr)))
+
+;;; left-shift src by 1 bit, storing result at res.  Return
+;;; the bit that was shifted out.
+(defppclapfunction mpn-lshift-1 ((resptr arg_x) (s1ptr arg_y) (size-arg arg_z))
+  (let ((size temp0)
+	(last-bit imm0)
+	(prev imm1)
+	(curr imm2)
+	(sleft imm3)
+	(sright imm4))
+    (subi size size-arg '1)
+    (cmpwi size 0)
+    (add resptr resptr size-arg)
+    (add s1ptr s1ptr size-arg)
+    (lwzu prev -4 s1ptr)
+    (srwi last-bit prev 31)
+    (box-fixnum arg_z last-bit)
+    (beq @end1)
+    @loop
+    (subi size size '1)
+    (cmpwi size 0)
+    (lwzu curr -4 s1ptr)
+    (slwi sleft prev 1)
+    (srwi sright curr 31)
+    (or sright sright sleft)
+    (stwu sright -4 resptr)
+    (beq @end2)
+    (subi size size '1)
+    (cmpwi size 0)
+    (lwzu prev -4 s1ptr)
+    (slwi sleft curr 1)
+    (srwi sright prev 31)
+    (or sright sright sleft)
+    (stwu sright -4 resptr)
+    (bne @loop)
+    @end1
+    (slwi sleft prev 1)
+    (stwu sleft -4 resptr)
+    (blr)
+    @end2
+    (slwi sleft curr 1)
+    (stwu sleft -4 resptr)
+    (blr)))
+
+;;; Do a 32x32=64 unsigned multiply of the words at X and Y.  Store
+;;; result (low word first) at RESULT.
+(defppclapfunction umulppm ((x arg_x) (y arg_y) (result arg_z))
+  (lwz imm0 0 x)
+  (lwz imm1 0 y)
+  (mullw imm2 imm0 imm1)
+  (mulhwu imm3 imm0 imm1)
+  (stw imm2 0 result)
+  (stw imm3 4 result)
+  (blr))
+
+
+;;; for truncate-by-fixnum etal
+;;; doesnt store quotient - just returns rem in 2 halves
+(defppclapfunction %floor-loop-no-quo ((q arg_x)(yhi arg_y)(ylo arg_z))
+  (let ((a imm1)
+        (b imm2)
+        (y imm3)
+        (quo imm0)
+        (qidx temp0)
+        (qlen temp1))
+    (lwz imm4 (- ppc32::fulltag-misc) q)
+    (header-length qlen imm4)
+    (subi qidx qlen 4)
+    (mr b rzero)
+    (compose-digit y yhi ylo)
+    @loop
+    (rlwinm a b -16 16 31)
+    (rlwinm b b 16 0 15)
+    (la imm4 ppc32::misc-data-offset q)
+    (lwzx imm4 qidx imm4) ; q contents
+    (rlwimi b imm4 16 16 31) ; hi 16 to lo b
+    ;(dbg)         
+    (48x32-divide a b y fp0 fp1 fp2 imm4)
+    (fctiwz fp0 fp0)
+    (stwu tsp -32 tsp)
+    (stw tsp 4 tsp)
+    (stfd fp0 24 tsp)
+    (lwz quo (+ 24 4) tsp) ; 16 quo bits above stuff used by 48x32
+    ; now mul quo by y
+    (mullw imm4 y quo)
+    ; and subtract from a,b
+    (subfc b imm4 b)
+    ; new a and b are low 2 digits of this (b) and last digit in array
+    ; and do it again on low 3 digits
+    ;(dbg)
+    (rlwinm a b -16 16 31)
+    (rlwinm b b 16 0 15)
+    (la imm4 ppc32::misc-data-offset q)
+    (lwzx imm4 qidx imm4)
+    (rlwimi b imm4 0 16 31)
+    (48x32-divide a b y fp0 fp1 fp2 imm4)
+    (fctiwz fp0 fp0)
+    (stfd fp0 16 tsp)  ; quo lo
+    (subi qidx qidx 4)
+    (cmpwi :cr1 qidx 0)
+    (lwz quo (+ 16 4) tsp)
+    (lwz tsp 0 tsp)
+    (mullw imm4 y quo)
+    (subfc b imm4 b)  ; b is remainder
+    (bge :cr1 @loop)
+    (digit-h temp0 b)
+    (vpush temp0)
+    (digit-l temp0 b)
+    (vpush temp0)
+    (la temp0 8 vsp)
+    (set-nargs 2)
+    (ba .SPvalues)))
+    
+
+; store result in dest, return rem in 2 halves
+(defppclapfunction %floor-loop-quo ((q-stk 0)(dest arg_x)(yhi arg_y)(ylo arg_z))
+  (let ((a imm1)
+        (b imm2)
+        (y imm3)
+        (quo imm0)
+        (qidx temp0)
+        (qlen temp1)
+        (q temp2))
+    (vpop q)
+    (lwz imm4 (- ppc32::fulltag-misc) q)
+    (header-length qlen imm4)
+    (subi qidx qlen 4)
+    (mr b rzero)
+    (compose-digit y yhi ylo)
+    @loop
+    (rlwinm a b -16 16 31)
+    (rlwinm b b 16 0 15)
+    (la imm4 ppc32::misc-data-offset q)
+    (lwzx imm4 qidx imm4) ; q contents
+    (rlwimi b imm4 16 16 31) ; hi 16 to lo b        
+    (48x32-divide a b y fp0 fp1 fp2 imm4)
+    (fctiwz fp0 fp0)
+    (stwu tsp -32 tsp)
+    (stw tsp 4 tsp)
+    (stfd fp0 24 tsp)
+    (lwz quo (+ 24 4) tsp) ; 16 quo bits above stuff used by 48x32
+    ; now mul quo by y
+    (mullw imm4 y quo)
+    ; and subtract from a,b
+    (subfc b imm4 b)
+    ; new a and b are low 2 digits of this (b) and last digit in array
+    ; and do it again on low 3 digits
+    ;(dbg)
+    (rlwinm a b -16 16 31)
+    (rlwinm b b 16 0 15)
+    (la imm4 ppc32::misc-data-offset q)
+    (lwzx imm4 qidx imm4)
+    (rlwimi b imm4 0 16 31)
+    (48x32-divide a b y fp0 fp1 fp2 imm4)
+    (fctiwz fp0 fp0)
+    (stfd fp0 16 tsp)  ; quo lo
+    (lwz quo (+ 16 4) tsp)
+    (mullw imm4 y quo)
+    (subfc b imm4 b)  ; b is remainder    
+    (lwz quo (+ 24 4) tsp) ; quo-hi
+    (rlwinm quo quo 16 0 15)
+    (lwz imm4 (+ 16 4) tsp) ; quo lo
+    (lwz tsp 0 tsp)
+    (rlwimi quo imm4 0 16 31)    
+    (la imm4 ppc32::misc-data-offset dest)
+    (stwx quo qidx imm4)
+    (subic. qidx qidx 4)
+    (bge @loop)
+    (digit-h temp0 b)
+    (vpush temp0)
+    (digit-l temp0 b)
+    (vpush temp0)
+    (la temp0 8 vsp)
+    (set-nargs 2)
+    (ba .SPvalues)))
+
+;;; get xidx thing from x, yidx thing from y if same return #xffff
+;;; #xffff otherwise get another thing from x and 1- xidx and do as
+;;; %floor of xthing otherx ything
+;;; Huh?
+(defppclapfunction %floor-99 ((x-stk 0)(xidx arg_x)(yptr arg_y)(yidx arg_z))
+  (let ((xptr temp0)
+        (a imm1)
+        (b imm2)
+        (y imm3)
+        (quo imm0)) 
+    (vpop xptr)
+    (la imm4 ppc32::misc-data-offset XIDX)
+    (lwzx a xptr imm4)
+    (la imm4 ppc32::misc-data-offset YIDX)
+    (lwzx y yptr imm4)
+    (cmpw a y)
+    (bne @more)
+    (li imm4 #xffff)
+    (rlwinm imm4 imm4 ppc32::fixnumshift (- 16 ppc32::fixnumshift) (- 31 ppc32::fixnum-shift))
+    (vpush imm4)
+    (vpush imm4)
+    (la temp0 8 vsp)
+    (set-nargs 2)
+    (ba .spvalues)
+    @MORE
+    ;  a has 16 bits from ahi, bhi gets alo blo gets bhi
+    (la imm4 (- ppc32::misc-data-offset 4) xidx)
+    (lwzx b xptr imm4)
+    (rlwinm b b 16 16 31)  ; bhi to blo 
+    (rlwimi b a 16 0 15)   ; alo to bhi
+    (rlwinm a a 16 16 31)  ; a gets alo 
+    (48x32-divide a b y fp0 fp1 fp2 imm4)
+    (fctiwz fp0 fp0)
+    (stwu tsp -32 tsp)
+    (stw tsp 4 tsp)
+    (stfd fp0 24 tsp)
+    (lwz quo (+ 24 4) tsp) ; 16 quo bits above stuff used by 48x32
+    ; now mul quo by y
+    (mullw imm4 y quo)
+    ; and subtract from a,b
+    (subfc b imm4 b)
+    ; AND AGAIN
+    (rlwinm a b -16 16 31) ; a gets b hi
+    (rlwinm b b 16 0 15)   ; b lo to b hi
+    (la imm4 (- ppc32::misc-data-offset 4) xidx) 
+    (lwzx imm4 imm4 xptr)
+    (rlwimi b imm4 0 16 31)
+    (48x32-divide a b y fp0 fp1 fp2 imm4)
+    (fctiwz fp0 fp0)
+    (stfd fp0 16 tsp)  ; quo lo
+    (lwz quo (+ 24 4) tsp) ; quo-hi
+    (box-fixnum temp0 quo)
+    (vpush temp0)
+    (lwz quo (+ 16 4) tsp) ; quo lo
+    (lwz tsp 0 tsp)
+    (box-fixnum temp0 quo)
+    (vpush temp0)    
+    (la temp0 8 vsp)
+    (set-nargs 2)
+    (ba .SPvalues)))
+
+; End of ppc32-bignum.lisp
Index: /branches/new-random/level-0/PPC/PPC64/.cvsignore
===================================================================
--- /branches/new-random/level-0/PPC/PPC64/.cvsignore	(revision 13309)
+++ /branches/new-random/level-0/PPC/PPC64/.cvsignore	(revision 13309)
@@ -0,0 +1,6 @@
+*.pfsl
+*.p64fsl
+*.dfsl
+*.d64fsl
+
+*~.*
Index: /branches/new-random/level-0/PPC/PPC64/ppc64-bignum.lisp
===================================================================
--- /branches/new-random/level-0/PPC/PPC64/ppc64-bignum.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/PPC64/ppc64-bignum.lisp	(revision 13309)
@@ -0,0 +1,340 @@
+;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+;;; The caller has allocated a two-digit bignum (quite likely on the stack).
+;;; If we can fit in a single digit (if the high word is just a sign
+;;; extension of the low word), truncate the bignum in place (the
+;;; trailing words should already be zeroed.
+(defppclapfunction %fixnum-to-bignum-set ((bignum arg_y) (fixnum arg_z))
+  (unbox-fixnum imm0 fixnum)
+  (srdi imm1 imm0 32)
+  (srawi imm2 imm0 31)
+  (cmpw imm2 imm1)
+  (stw imm0 ppc64::misc-data-offset bignum)
+  (li imm2 ppc64::one-digit-bignum-header)
+  (beq @chop)
+  (stw imm1 (+ ppc64::misc-data-offset 4) bignum)
+  (blr)
+  @chop
+  (std imm2 ppc64::misc-header-offset bignum)
+  (blr))
+  
+(defppclapfunction %multiply-and-add-loop
+    ((x 8) (y 0)  (r arg_x) (idx arg_y) (ylen arg_z))
+  (let ((cc nargs)
+	(xx imm2)
+	(yy imm3)
+	(rr imm4)
+	(i imm0)
+	(j imm1))
+    (srdi i idx 1)
+    (la i ppc64::misc-data-offset i)
+    (ld temp0 x vsp)
+    (lwzx xx temp0 i)			;x[i]
+    (ld temp0 y vsp)
+    (mr temp1 r)
+    (li cc 0)
+    (li j ppc64::misc-data-offset)
+    @loop
+    (lwzx yy temp0 j)
+    (mulld yy xx yy)
+    ;; 64-bit product now in %yy
+    (lwzx rr temp1 i)
+    ;; add in digit from r[i]
+    (add rr rr yy)
+    ;; add in carry
+    (add rr rr cc)
+    (stwx rr temp1 i)
+    (srdi cc rr 32) 		;get carry digit into low word
+    (cmpdi ylen '1)
+    (la i 4 i)
+    (la j 4 j)
+    (subi ylen ylen '1)
+    (bne  @loop)
+    (stwx cc temp1 i)
+    (set-nargs 0)
+    (la vsp 16 vsp)
+    (blr)))
+
+(defppclapfunction %multiply-and-add-loop64
+    ((x 8) (y 0) (r arg_x) (idx arg_y) (ylen arg_z))
+  (let ((i imm0)
+	(j imm1)
+	(xx imm2)
+	(yy imm3)
+	(rr imm4)
+	(dd imm5)
+	(cc nargs))
+    (ld temp0 x vsp)
+    (la i ppc64::misc-data-offset idx)
+    (ldx xx temp0 i)			;x[i]
+    (rotldi xx xx 32)
+    (ld temp0 y vsp)
+    (li cc 0)
+    (li j ppc64::misc-data-offset)
+    @loop
+    (ldx yy temp0 j)			;y[j]
+    (rotldi yy yy 32)
+    (mulld dd xx yy)  ;low
+    (ldx rr r i)			;r[i]
+    (rotldi rr rr 32)
+    (addc rr rr dd)			;r[i] = r[i] + low
+    (mulhdu dd xx yy)			;high
+    (addze dd dd)			;carry from addding in low
+    (addc rr rr cc)			;add in carry digit
+    (addze cc dd)
+    (rotldi rr rr 32)
+    (stdx rr r i)			;update r[i]
+    (cmpdi ylen '1)
+    (la i 8 i)
+    (la j 8 j)
+    (subi ylen ylen '1)
+    (bne @loop)
+    (rotldi cc cc 32)
+    (stdx cc r i)
+    (set-nargs 0)
+    (la vsp 16 vsp)
+    (blr)))
+
+;;; Multiply the (32-bit) digits X and Y, producing a 64-bit result.
+;;; Add the 32-bit "prev" digit and the 32-bit carry-in digit to that 64-bit
+;;; result; return the halves as (VALUES high low).
+(defppclapfunction %multiply-and-add4 ((x 0) (y arg_x) (prev arg_y) (carry-in arg_z))
+  (let ((unboxed-x imm0)
+        (unboxed-y imm1)
+        (unboxed-prev imm2)
+        (unboxed-carry-in imm3)
+        (result64 imm4)
+        (high arg_y)
+        (low arg_z))
+    (ld temp0 x vsp)
+    (unbox-fixnum unboxed-x temp0)
+    (unbox-fixnum unboxed-y y)
+    (unbox-fixnum unboxed-prev prev)
+    (unbox-fixnum unboxed-carry-in carry-in)
+    (mulld result64 unboxed-x unboxed-y)
+    (add result64 result64 unboxed-prev)
+    (add result64 result64 unboxed-carry-in)
+    (clrlsldi low result64 32 ppc64::fixnumshift)
+    (clrrdi high result64 32)
+    (srdi high high (- 32 ppc64::fixnumshift))
+    (std high 0 vsp)
+    (set-nargs 2)
+    (vpush low)
+    (la temp0 '2 vsp)
+    (ba .SPvalues)))
+
+(defppclapfunction %multiply-and-add3 ((x arg_x) (y arg_y) (carry-in arg_z))
+  (let ((unboxed-x imm0)
+        (unboxed-y imm1)
+        (unboxed-carry-in imm2)
+        (result64 imm3)
+        (high arg_y)
+        (low arg_z))
+    (unbox-fixnum unboxed-x arg_x)
+    (unbox-fixnum unboxed-y y)
+    (unbox-fixnum unboxed-carry-in carry-in)
+    (mulld result64 unboxed-x unboxed-y)
+    (add result64 result64 unboxed-carry-in)
+    (clrlsldi low result64 32 ppc64::fixnumshift)
+    (clrrdi high result64 32)
+    (srdi high high (- 32 ppc64::fixnumshift))
+    (vpush high)
+    (set-nargs 2)
+    (vpush low)
+    (la temp0 '2 vsp)
+    (ba .SPvalues)))
+
+;;; Return the (possibly truncated) 32-bit quotient and remainder
+;;; resulting from dividing hi:low by divisor.
+(defppclapfunction %floor ((num-high arg_x) (num-low arg_y) (divisor arg_z))
+  (let ((unboxed-num imm0)
+        (unboxed-low imm1)
+        (unboxed-divisor imm2)
+        (unboxed-quo imm3)
+        (unboxed-rem imm4))
+    (sldi unboxed-num num-high (- 32 ppc64::fixnumshift))
+    (unbox-fixnum unboxed-low num-low)
+    (unbox-fixnum unboxed-divisor divisor)
+    (or unboxed-num unboxed-low unboxed-num)
+    (divdu unboxed-quo unboxed-num unboxed-divisor)
+    (mulld unboxed-rem unboxed-quo unboxed-divisor)
+    (sub unboxed-rem unboxed-num unboxed-rem)
+    (clrlsldi arg_y unboxed-quo 32 ppc64::fixnumshift)
+    (clrlsldi arg_z unboxed-rem 32 ppc64::fixnumshift)
+    (mr temp0 vsp)
+    (vpush arg_y)
+    (vpush arg_z)
+    (set-nargs 2)
+    (ba .SPvalues)))
+
+;;; Multiply two (UNSIGNED-BYTE 32) arguments, return the high and
+;;; low halves of the 64-bit result
+(defppclapfunction %multiply ((x arg_y) (y arg_z))
+  (let ((unboxed-x imm0)
+        (unboxed-y imm1)
+        (unboxed-high imm2)
+        (unboxed-low imm3))
+    (unbox-fixnum unboxed-x x)
+    (unbox-fixnum unboxed-y y)
+    (mulld imm2 unboxed-x unboxed-y)
+    (clrlsldi arg_y imm2 32 ppc64::fixnumshift) ; arg_y = low32
+    (srdi imm2 imm2 32)
+    (box-fixnum arg_z imm2)             ; arg_z = high32
+    (mr temp0 vsp)
+    (vpush arg_z)
+    (set-nargs 2)
+    (vpush arg_y)
+    (ba .SPvalues)))
+
+;;; Any words in the "tail" of the bignum should have been
+;;; zeroed by the caller.
+(defppclapfunction %set-bignum-length ((newlen arg_y) (bignum arg_z))
+  (sldi imm0 newlen (- ppc64::num-subtag-bits ppc64::fixnumshift))
+  (ori imm0 imm0 ppc64::subtag-bignum)
+  (std imm0 ppc64::misc-header-offset bignum)
+  (blr))
+
+;;; Count the sign bits in the most significant digit of bignum;
+;;; return fixnum count.
+(defppclapfunction %bignum-sign-bits ((bignum arg_z))
+  (vector-size imm0 bignum imm0)
+  (sldi imm0 imm0 2)
+  (la imm0 (- ppc64::misc-data-offset 4) imm0) ; Reference last (most significant) digit
+  (lwzx imm0 bignum imm0)
+  (cmpwi imm0 0)
+  (not imm0 imm0)
+  (blt @wasneg)
+  (not imm0 imm0)
+  @wasneg
+  (cntlzw imm0 imm0)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %signed-bignum-ref ((bignum arg_y) (index arg_z))
+  (srdi imm0 index 1)
+  (la imm0 ppc64::misc-data-offset imm0)
+  (lwax imm0 bignum imm0)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+
+;;; If the bignum is a one-digit bignum, return the value of the
+;;; single digit as a fixnum.  Otherwise, if it's a two-digit-bignum
+;;; and the two words of the bignum can be represented in a fixnum,
+;;; return that fixnum; else return nil.
+(defppclapfunction %maybe-fixnum-from-one-or-two-digit-bignum ((bignum arg_z))
+  (ld imm1 ppc64::misc-header-offset bignum)
+  (cmpdi cr1 imm1 ppc64::one-digit-bignum-header)
+  (cmpdi cr2 imm1 ppc64::two-digit-bignum-header)
+  (beq cr1 @one)
+  (bne cr2 @no)
+  (ld imm0 ppc64::misc-data-offset bignum)
+  (rotldi imm0 imm0 32)
+  (box-fixnum arg_z imm0)
+  (unbox-fixnum imm1 arg_z)
+  (cmpd imm0 imm1)
+  (beqlr)
+  @no
+  (li arg_z nil)
+  (blr)
+  @one
+  (lwa imm0 ppc64::misc-data-offset bignum)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+
+(defppclapfunction %digit-logical-shift-right ((digit arg_y) (count arg_z))
+  (unbox-fixnum imm0 digit)
+  (unbox-fixnum imm1 count)
+  (srw imm0 imm0 imm1)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %ashr ((digit arg_y) (count arg_z))
+  (unbox-fixnum imm0 digit)
+  (unbox-fixnum imm1 count)
+  (sraw imm0 imm0 imm1)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %ashl ((digit arg_y) (count arg_z))
+  (unbox-fixnum imm0 digit)
+  (unbox-fixnum imm1 count)
+  (slw imm0 imm0 imm1)
+  (clrlsldi arg_z imm0 32 ppc64::fixnumshift)
+  (blr))
+
+(defppclapfunction macptr->fixnum ((ptr arg_z))
+  (macptr-ptr imm0 ptr)
+  (andi. imm1 imm0 7)
+  (li arg_z nil)
+  (bne @done)
+  (mr arg_z imm0)
+  @done
+  (blr))
+
+(defppclapfunction fix-digit-logand ((fix arg_x) (big arg_y) (dest arg_z)) ; index 0
+  (let ((w1 imm0)
+        (w2 imm1))
+    (ld w2 ppc64::misc-data-offset big)
+    (unbox-fixnum  w1 fix)
+    (rotldi w2 w2 32)
+    (cmpdi dest nil)
+    (and w1 w1 w2)
+    (bne @store)
+    (box-fixnum arg_z w1)
+    (blr)
+    @store
+    (rotldi w1 w1 32)
+    (std w1 ppc64::misc-data-offset dest)
+    (blr)))
+
+
+
+(defppclapfunction fix-digit-logandc2 ((fix arg_x) (big arg_y) (dest arg_z))
+  (cmpdi dest nil)
+  (ld imm1 ppc64::misc-data-offset big)
+  (unbox-fixnum imm0 fix)
+  (rotldi imm1 imm1 32)
+  (andc imm1 imm0 imm1)
+  (bne @store)
+  (box-fixnum arg_z imm1)
+  (blr)
+  @store
+  (rotldi imm1 imm1 32)
+  (std imm1 ppc64::misc-data-offset dest)
+  (blr))
+
+(defppclapfunction fix-digit-logandc1 ((fix arg_x) (big arg_y) (dest arg_z))
+  (cmpdi dest nil)
+  (ld imm1 ppc64::misc-data-offset big)
+  (unbox-fixnum imm0 fix)
+  (rotldi imm1 imm1 32)
+  (andc imm1 imm1 imm0)
+  (bne @store)
+  (box-fixnum arg_z imm1)
+  (blr)
+  @store
+  (rotldi imm1 imm1 32)
+  (std imm1 ppc64::misc-data-offset dest)
+  (blr))
+
+
Index: /branches/new-random/level-0/PPC/ppc-array.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-array.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-array.lisp	(revision 13309)
@@ -0,0 +1,848 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  #+ppc32-target
+  (require "PPC32-ARCH")
+  #+ppc64-target
+  (require "PPC64-ARCH")
+  (require "PPC-LAPMACROS"))
+
+
+;;; Users of this shouldn't make assumptions about return value.
+
+
+#+ppc32-target
+(eval-when (:compile-toplevel :execute)
+;;; Assumptions made by %init-misc
+  (assert (and (< ppc32::max-32-bit-ivector-subtag
+                  ppc32::max-8-bit-ivector-subtag
+                  ppc32::max-16-bit-ivector-subtag)
+               (eql ppc32::max-32-bit-ivector-subtag ppc32::subtag-simple-base-string)
+               (eql ppc32::max-16-bit-ivector-subtag ppc32::subtag-s16-vector)
+               (eql ppc32::max-8-bit-ivector-subtag 223))))
+
+#+ppc32-target
+(defppclapfunction %init-misc ((val arg_y)
+                               (miscobj arg_z))
+  (getvheader imm0 miscobj)
+  (header-size imm3 imm0)
+  (cmpwi cr3 imm3 0)
+  (extract-fulltag imm1 imm0)
+  (cmpwi cr0 imm1 ppc32::fulltag-nodeheader)
+  (extract-lowbyte imm2 imm0)
+  (beqlr cr3)                           ; Silly 0-length case
+  (li imm4 ppc32::misc-data-offset)
+  (bne cr0 @imm)
+  ; Node vector.  Don't need to memoize, since initial value is
+  ; older than vector.
+  @node-loop
+  (cmpwi cr0 imm3 1)
+  (subi imm3 imm3 1)
+  (stwx val miscobj imm4)
+  (la imm4 4 imm4)
+  (bne cr0 @node-loop)
+  (blr)
+  @imm
+  (cmpwi cr0 imm2 ppc32::subtag-double-float-vector)
+  (cmpwi cr1 imm2 ppc32::max-32-bit-ivector-subtag)
+  (cmpwi cr2 imm2 ppc32::max-8-bit-ivector-subtag)
+  (cmpwi cr3 imm2 ppc32::max-16-bit-ivector-subtag)
+  (extract-typecode imm0 val :CR6)		; don't clobber CR0
+  (cmpwi cr7 imm0 ppc32::tag-fixnum)
+  (beq cr0 @dfloat)
+  (ble cr1 @32)
+  (ble cr2 @8)
+  (ble cr3 @16)
+  ; Bit vector.
+  (cmplwi cr0 val '1)
+  (la imm3 31 imm3)
+  (srwi imm3 imm3 5)
+  (unbox-fixnum imm0 val)
+  (neg imm0 imm0)
+  (ble+ cr0 @set-32)
+  @bad
+  (li arg_x '#.$xnotelt)
+  (save-lisp-context)
+  (set-nargs 3)
+  (call-symbol %err-disp)
+  @dfloat
+  (cmpwi cr0 imm0 ppc32::subtag-double-float)
+  (li imm4 ppc32::misc-dfloat-offset)
+  (bne- cr0 @bad)
+  (lfd fp0 ppc32::double-float.value val)
+  @dfloat-loop
+  (cmpwi cr0 imm3 1)
+  (subi imm3 imm3 1)
+  (stfdx fp0 miscobj imm4)
+  (la imm4 8 imm4)
+  (bne cr0 @dfloat-loop)
+  (blr)
+  @32
+  (cmpwi cr4 imm2 ppc32::subtag-s32-vector)
+  (cmpwi cr0 imm2 ppc32::subtag-single-float-vector)
+  (cmpwi cr2 imm0 ppc32::subtag-bignum)
+  (cmpwi cr3 imm2 ppc32::subtag-fixnum-vector)
+  (beq cr1 @char32)                      ; ppc32::max-32-bit-ivector-subtag
+  (beq cr4 @s32)
+  (beq cr3 @fixnum)
+  (bne cr0 @u32)
+  ;@sfloat
+  (cmpwi cr0 imm0 ppc32::subtag-single-float)
+  (bne- cr0 @bad)
+  (lwz imm0 ppc32::single-float.value val)
+  (b @set-32)
+  @fixnum
+  (unbox-fixnum imm0 val)
+  (beq+ cr7 @set-32)
+  (b @bad)
+  @char32
+  (unbox-base-char imm0 val cr0)
+  (b @set-32)
+  @s32
+  (unbox-fixnum imm0 val)
+  (beq+ cr7 @set-32)
+  (bne- cr2 @bad)
+  (getvheader imm0 val)
+  (cmpwi cr0 imm0 (logior (ash 1 ppc32::num-subtag-bits) ppc32::subtag-bignum))
+  (lwz imm0 ppc32::misc-data-offset val)
+  (beq+ cr0 @set-32)
+  (b @bad)
+  @u32
+  (extract-unsigned-byte-bits. imm0 val 30)
+  (unbox-fixnum imm0 val)
+  (beq cr0 @set-32)
+  (bne- cr2 @bad)
+  ; a one-digit bignum is ok if that digit is positive.
+  ; a two-digit bignum is ok if the sign-digit is 0.
+  (getvheader imm0 val)
+  (cmpwi cr2 imm0 (logior (ash 2 ppc32::num-subtag-bits) ppc32::subtag-bignum))
+  (lwz imm0 ppc32::misc-data-offset val)
+  (cmpwi cr3 imm0 0)
+  (bgt- cr2 @bad)                       ; more than two digits.
+  (beq cr2 @two-digits)
+  (bgt+ cr3 @set-32)
+  (b @bad)
+  @two-digits
+  (lwz imm1 (+ 4 ppc32::misc-data-offset) val)
+  (cmpwi cr0 imm1 0)
+  (bne- cr0 @bad)
+  (b @set-32)
+  @16
+  (cmpwi cr0 imm2 ppc32::subtag-u16-vector)
+  (la imm3 1 imm3)
+  (srwi imm3 imm3 1)
+  (beq cr3 @s16)                        ; ppc32::max-16-bit-ivector-subtag
+  (extract-unsigned-byte-bits. imm0 val 16)
+  (unbox-fixnum imm0 val)
+  (beq+ cr0 @set-16)
+  (b @bad)
+  @s16
+  (slwi imm0 val (- 32 (+ 16 ppc32::fixnumshift)))
+  (srawi imm0 imm0 (- 32 (+ 16 ppc32::fixnumshift)))
+  (cmpw cr0 imm0 val)
+  (unbox-fixnum imm0 val)
+  (bne- cr7 @bad)
+  (beq+ cr0 @set-16)
+  (b @bad)
+  @8
+  (cmpwi cr0 imm0 ppc32::subtag-s8-vector)
+  (la imm3 3 imm3)
+  (srwi imm3 imm3 2)
+  (beq cr2 @char8)                      ; ppc32::max-8-bit-ivector-subtag
+  (beq cr0 @s8)
+  (extract-unsigned-byte-bits. imm0 val 8)
+  (unbox-fixnum imm0 val)
+  (beq+ cr0 @set-8)
+  (b @bad)
+  @s8
+  (slwi imm0 val (- 32 (+ 8 ppc32::fixnumshift)))
+  (srawi imm0 imm0 (- 32 (+ 8 ppc32::fixnumshift)))
+  (cmpw cr0 imm0 val)
+  (unbox-fixnum imm0 val)
+  (bne- cr7 @bad)
+  (beq+ cr0 @set-8)
+  (b @bad)
+  @char8
+  (unbox-base-char imm0 val cr0)   ; this type checks val
+  @set-8                                ; propagate low 8 bits into low 16
+  (rlwimi imm0 imm0 8 (- 32 16) (- 31 8))
+  @set-16                               ; propagate low 16 bits into high 16
+  (rlwimi imm0 imm0 16 0 (- 31 16))
+  @set-32
+  (cmpwi cr0 imm3 1)
+  (subi imm3 imm3 1)
+  (stwx imm0 miscobj imm4)
+  (la imm4 4 imm4)
+  (bne cr0 @set-32)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %init-misc ((val arg_y)
+                               (miscobj arg_z))
+  (getvheader imm0 miscobj)
+  ;(extract-lowtag imm2 imm0)
+  (clrldi imm2 imm0 (- 64 ppc64::nlowtagbits))
+  (header-size imm3 imm0)
+  (cmpdi cr3 imm3 0)
+  (extract-fulltag imm1 imm0)
+  (cmpdi cr0 imm2 ppc64::lowtag-nodeheader)
+  (extract-lowbyte imm2 imm0)
+  (beqlr cr3)                           ; Silly 0-length case
+  (li imm4 ppc64::misc-data-offset)
+  (bne cr0 @imm)
+  ;; Node vector.  Don't need to memoize, since initial value is
+  ;; older than vector.
+  @node-loop
+  (cmpdi cr0 imm3 1)
+  (subi imm3 imm3 1)
+  (stdx val miscobj imm4)
+  (la imm4 ppc64::node-size imm4)
+  (bne cr0 @node-loop)
+  (blr)
+  @imm
+  (extract-typecode imm0 val)		
+  (cmpdi cr0 imm1 ppc64::ivector-class-64-bit)
+  (cmpdi cr1 imm1 ppc64::ivector-class-32-bit)
+  (cmpdi cr2 imm1 ppc64::ivector-class-8-bit)
+  (cmpwi cr7 imm0 ppc64::tag-fixnum)
+  (beq cr0 @64)
+  (beq cr1 @32)
+  (beq cr2 @8)
+  ;; u16, s16, or bit-vector.  Val must be a fixnum.
+  (cmpdi cr0 imm2 ppc64::subtag-u16-vector)
+  (cmpdi cr1 imm2 ppc64::subtag-s16-vector)
+  (bne cr7 @bad)                        ; not a fixnum
+  (beq cr0 @u16)
+  (beq cr1 @s16)
+  ; Bit vector.
+  (cmpldi cr0 val '1)
+  (la imm3 31 imm3)
+  (srdi imm3 imm3 5)
+  (unbox-fixnum imm0 val)
+  (neg imm0 imm0)
+  (ble+ cr0 @set-32)
+  @bad
+  (li arg_x '#.$xnotelt)
+  (save-lisp-context)
+  (set-nargs 3)
+  (call-symbol %err-disp)
+  @64
+  (cmpdi cr3 imm2 ppc64::subtag-fixnum-vector)
+  (cmpdi cr1 imm2 ppc64::subtag-double-float-vector)
+  (cmpdi cr2 imm2 ppc64::subtag-s64-vector)
+  (beq cr3 @fixnum)
+  (beq cr1 @dfloat)
+  (beq cr2 @u64)
+  ;; s64
+  (unbox-fixnum imm0 val)
+  (beq cr7 @set-64)                     ; all fixnums are (SIGNED-BYTE 64)
+  (bne cr3 @bad)                        ; as are 2-digit bignums
+  (getvheader imm1 val)
+  (ld imm0 ppc64::misc-data-offset val)
+  (cmpdi imm1 ppc64::two-digit-bignum-header)
+  (rotldi imm0 imm0 32)
+  (beq @set-64)
+  (b @bad)
+@fixnum
+  (unbox-fixnum imm0 val)
+  (beq cr7 @set-64)                     ; all fixnums are (SIGNED-BYTE 64)
+  (b  @bad)                        ; as are 2-digit bignums
+   ;; u64 if fixnum and positive, 2-digit bignum and positive, or
+  ;; 3-digit bignum with most-significant digit 0.
+  @u64
+  (cmpdi cr2 val 0)
+  (bne cr7 @u64-maybe-bignum)
+  (bge cr2 @set-64)
+  (b @bad)
+  @u64-maybe-bignum
+  (bne cr3 @bad)
+  (ld imm0 ppc64::misc-data-offset val)
+  (getvheader imm1 val)
+  (rotldi imm0 imm0 32)
+  (cmpdi cr2 imm1 ppc64::two-digit-bignum-header)
+  (cmpdi cr3 imm1 ppc64::three-digit-bignum-header)
+  (cmpdi cr0 imm0 0)
+  (beq cr2 @u32-two-digit)
+  (bne cr3 @bad)
+  (lwz imm1 (+ 8 ppc64::misc-data-offset) val)
+  (cmpwi imm0 0)
+  (beq @set-64)
+  (b @bad)
+  @u32-two-digit
+  (bgt cr0 @set-64)
+  (b @bad)
+  @dfloat
+  (cmpdi cr0 imm0 ppc64::subtag-double-float)
+  (bne- cr0 @bad)
+  (ld imm0 ppc64::double-float.value val)
+  (b @set-64)
+  @32
+  (cmpdi cr3 imm2 ppc64::subtag-simple-base-string)
+  (cmpdi cr2 imm2 ppc64::subtag-s32-vector)
+  (cmpdi cr0 imm2 ppc64::subtag-single-float-vector)
+  (beq cr3 @char32)
+  (beq cr2 @s32)
+  (bne cr0 @u32)
+  ;@sfloat
+  (cmpdi cr0 imm0 ppc64::subtag-single-float)
+  (srdi imm0 val 32)
+  (bne- cr0 @bad)
+  (b @set-32)
+  @s32
+  ;; Must be a fixnum (and a (SIGNED-BYTE 32)).
+  (bne cr7 @bad)
+  (unbox-fixnum imm0 val)
+  (sldi imm1 imm0 32)
+  (sradi imm1 imm1 32)
+  (cmpd imm1 imm0)
+  (bne @bad)
+  (b @set-32)
+  @char32
+  (unbox-base-char imm0 val cr0)   ; this type checks val
+  (b @set-32)
+  @u32
+  ;; Also has to be a fixnum (and an (UNSIGNED-BYTE 32)).
+  (unbox-fixnum imm0 val)
+  (clrrdi. imm1 imm0 32)                ; ~Z if any high bits set
+  (bne cr7 @bad)
+  (bne cr0 @bad)
+  (b @set-32)
+  @u16
+  (unbox-fixnum imm0 val)
+  (clrrdi. imm1 imm0 16)
+  (bne cr7 @bad)
+  (bne cr0 @bad)
+  (b @set-16)
+  @s16
+  (sldi imm0 val (- 64 (+ 16 ppc64::fixnumshift)))
+  (sradi imm0 imm0 (- 64 (+ 16 ppc64::fixnumshift)))
+  (cmpw cr0 imm0 val)
+  (unbox-fixnum imm0 val)
+  (bne- cr7 @bad)
+  (beq+ cr0 @set-16)
+  (b @bad)
+  @8
+  (cmpdi cr0 imm2 ppc64::subtag-s8-vector)
+  (beq cr0 @s8)
+  (extract-unsigned-byte-bits. imm0 val 8)
+  (unbox-fixnum imm0 val)
+  (beq+ cr0 @set-8)
+  (b @bad)
+  @s8
+  (sldi imm0 val (- 64 (+ 8 ppc64::fixnumshift)))
+  (sradi imm0 imm0 (- 64 (+ 8 ppc64::fixnumshift)))
+  (cmpd cr0 imm0 val)
+  (unbox-fixnum imm0 val)
+  (bne- cr7 @bad)
+  (beq+ cr0 @set-8)
+  (b @bad)
+  @char8
+  (unbox-base-char imm0 val cr0)   ; this type checks val
+  @set-8                                ; propagate low 8 bits into low 16
+  (la imm3 1 imm3)
+  (rlwimi imm0 imm0 8 (- 32 16) (- 31 8))
+  (srdi imm3 imm3 1)
+  @set-16                               ; propagate low 16 bits into high 16
+  (la imm3 1 imm3)
+  (rlwimi imm0 imm0 16 0 (- 31 16))
+  (srdi imm3 imm3 1) 
+  @set-32                               ; propagate low 32 bits into high 32
+  (la imm3 1 imm3)
+  (rldimi imm0 imm0 32 0)
+  (srdi imm3 imm3 1)
+  @set-64
+  (cmpdi cr0 imm3 1)
+  (subi imm3 imm3 1)
+  (stdx imm0 miscobj imm4)
+  (la imm4 8 imm4)
+  (bne cr0 @set-64)
+  (blr))
+
+;;; Make a new vector of size newsize whose subtag matches that of oldv-arg.
+;;; Blast the contents of the old vector into the new one as quickly as
+;;; possible; leave remaining elements of new vector undefined (0).
+;;; Return new-vector.
+#+ppc32-target
+(defppclapfunction %extend-vector ((start-arg arg_x) (oldv-arg arg_y) (newsize arg_z))
+  (let ((oldv save0)
+        (oldsize save1)
+        (oldsubtag save2)
+        (start-offset save3))
+    (save-lisp-context)
+    (:regsave save3 0)
+    (vpush save0)
+    (vpush save1)
+    (vpush save2)
+    (vpush save3)
+    (mr oldv oldv-arg)
+    (mr start-offset start-arg)
+    (getvheader imm0 oldv)
+    (header-length oldsize imm0)
+    (header-subtag[fixnum] oldsubtag imm0)
+    (mr arg_y newsize)
+    (mr arg_z oldsubtag)
+    (bla .SPmisc-alloc)
+    (extrwi imm0 oldsubtag ppc32::ntagbits (- 32 (+  ppc32::fixnumshift ppc32::ntagbits)))
+    (cmpwi cr0 oldsize 0)
+    (cmpwi cr1 imm0 ppc32::fulltag-nodeheader)
+    (cmpwi cr2 oldsubtag '#.ppc32::max-32-bit-ivector-subtag)
+    (la imm1 ppc32::misc-data-offset start-offset)
+    (li imm3 ppc32::misc-data-offset)
+    (beq cr0 @done)
+    (bne cr1 @imm)
+    ;; copy nodes.  New vector is "new", so no memoization required.
+    @node-loop
+    (cmpwi cr0 oldsize '1)
+    (lwzx temp0 oldv imm1)
+    (addi imm1 imm1 4)
+    (subi oldsize oldsize '1)
+    (stwx temp0 arg_z imm3)
+    (addi imm3 imm3 4)
+    (bne cr0 @node-loop)
+    ;;Restore registers.  New vector's been in arg_z all this time.
+    @done
+    (lwz save3 0 vsp)
+    (lwz save2 4 vsp)
+    (lwz save1 8 vsp)
+    (lwz save0 12 vsp)
+    (restore-full-lisp-context)
+    (blr)
+    @imm
+    (unbox-fixnum imm2 oldsize)
+    (unbox-fixnum imm3 start-offset)
+    (li imm1 ppc32::misc-data-offset)
+    (la imm4 ppc32::misc-data-offset start-offset)
+    (cmpwi cr1 oldsubtag '#.ppc32::max-8-bit-ivector-subtag)
+    (cmpwi cr0 oldsubtag '#.ppc32::max-16-bit-ivector-subtag)
+    (ble cr2 @fullword-loop)
+    (cmpwi cr2 oldsubtag '#.ppc32::subtag-bit-vector)
+    (ble cr1 @8-bit)
+    (ble cr0 @16-bit)
+    (beq cr2 @1-bit)
+    ;; 64-bit (double-float) vectors.  There's a different
+    ;; initial offset, but we're always word-aligned, so that
+    ;; part's easy.
+    (li imm1 ppc32::misc-dfloat-offset)   ; scaled destination pointer
+    (slwi imm2 imm2 1)                  ; twice as many fullwords
+    (slwi imm3 imm3 3)                  ; convert dword count to byte offset
+    (la imm4 ppc32::misc-dfloat-offset imm3)      ; scaled source pointer
+    (b @fullword-loop)
+    ;; The bitvector case is hard if START-OFFSET isn't on an 8-bit boundary,
+    ;;  and can be turned into the 8-bit case otherwise.
+    ;; The 8-bit case is hard if START-OFFSET isn't on a 16-bit boundary, 
+    ;;  and can be turned into the 16-bit case otherwise.
+    ;; The 16-bit case is hard if START-OFFSET isn't on a 32-bit boundary, 
+    ;;  and can be turned into the 32-bit case otherwise.
+    ;; Hmm.
+    @1-bit
+    (clrlwi. imm0 imm3 (- 32 3))
+    (bne- cr0 @hard-1-bit)
+    (srwi imm3 imm3 3)                  ; bit offset to byte offset
+    (addi imm2 imm2 7)
+    (srwi imm2 imm2 3)                  ; bit count to byte count
+    @8-bit
+    ; If the byte offset's even, copy half as many halfwords
+    (clrlwi. imm0 imm3 (- 32 1))
+    (bne- cr0 @hard-8-bit)
+    (addi imm2 imm2 1)
+    (srwi imm2 imm2 1)                  ; byte count to halfword count
+    (srwi imm3 imm3 1)                  ; byte offset to halfword offset
+    @16-bit
+    ; If the halfword offset's even, copy half as many fullwords
+    (clrlwi. imm0 imm3 (- 32 1))
+    (bne- cr0 @hard-16-bit)
+    (addi imm2 imm2 1)
+    (srwi imm2 imm2 1)                  ; halfword count to fullword count
+    (li imm1 ppc32::misc-data-offset)   
+    @fullword-loop
+    (cmpwi cr0 imm2 1)
+    (lwzx imm0 oldv imm4)
+    (addi imm4 imm4 4)
+    (subi imm2 imm2 1)
+    (stwx imm0 arg_z imm1)
+    (addi imm1 imm1 4)
+    (bne cr0 @fullword-loop)
+    (b @done)
+    ;;; This can just do a uvref/uvset loop.  Cases that can
+    ;;; cons (x32, double-float) have already been dealt with.
+    @hard-1-bit
+    @hard-8-bit
+    @hard-16-bit
+    (let ((newv save4)
+          (outi save5)
+          (oldlen save6))
+      (vpush save4)
+      (vpush save5)
+      (vpush save6)
+      (mr newv arg_z)
+      (sub oldlen oldsize start-offset)
+      (li outi 0)
+      @hard-loop
+      (mr arg_y oldv)
+      (mr arg_z start-offset)
+      (bla .SPmisc-ref)
+      (mr arg_x newv)
+      (mr arg_y outi)
+      (bla .SPmisc-set)
+      (la outi '1 outi)
+      (cmpw cr0 outi oldlen)
+      (la start-offset '1 start-offset)
+      (bne @hard-loop)
+      (mr arg_z newv)
+      (vpop save6)
+      (vpop save5)
+      (vpop save4)
+      (b @done))))
+
+#+ppc64-target
+(defppclapfunction %extend-vector ((start-arg arg_x) (oldv-arg arg_y) (newsize arg_z))
+  (let ((oldv save0)
+        (oldsize save1)
+        (oldsubtag save2)
+        (start-offset save3))
+    (save-lisp-context)
+    (:regsave save3 0)
+    (vpush save0)
+    (vpush save1)
+    (vpush save2)
+    (vpush save3)
+    (mr oldv oldv-arg)
+    (mr start-offset start-arg)
+    (getvheader imm0 oldv)
+    (header-length oldsize imm0)
+    (header-subtag[fixnum] oldsubtag imm0)
+    (mr arg_y newsize)
+    (mr arg_z oldsubtag)
+    (bla .SPmisc-alloc)
+    (unbox-fixnum imm0 oldsubtag)
+    (extract-lowtag imm1 imm0)
+    (extract-fulltag imm2 imm0)
+    (cmpdi cr0 oldsize 0)
+    (cmpdi cr1 imm1 ppc64::lowtag-nodeheader)
+    (cmpdi cr2 imm2 ppc64::ivector-class-8-bit)
+    (cmpdi cr3 imm2 ppc64::ivector-class-32-bit)
+    (cmpdi cr4 imm2 ppc64::ivector-class-64-bit)
+    (cmpdi cr5 imm0 ppc64::subtag-bit-vector)
+    (li imm3 ppc64::misc-data-offset)
+    (beq cr0 @done)
+    (bne cr1 @imm)
+    (la imm1 ppc64::misc-data-offset start-offset)
+    ;; copy nodes.  New vector is "new", so no memoization required.
+    @node-loop
+    (cmpdi cr0 oldsize '1)
+    (ldx temp0 oldv imm1)
+    (addi imm1 imm1 8)
+    (subi oldsize oldsize '1)
+    (stdx temp0 arg_z imm3)
+    (addi imm3 imm3 8)
+    (bne cr0 @node-loop)
+    ;;Restore registers.  New vector's been in arg_z all this time.
+    @done
+    (ld save3 0 vsp)
+    (ld save2 8 vsp)
+    (ld save1 16 vsp)
+    (ld save0 24 vsp)
+    (restore-full-lisp-context)
+    (blr)
+    @imm
+    (beq cr2 @8-bit)
+    (beq cr3 @32-bit)
+    (beq cr4 @64-bit)
+    (beq cr5 @1-bit)
+    (srdi imm1 start-offset 2)
+    (la imm1 ppc64::misc-data-offset imm1)
+    @16-loop
+    (cmpdi cr0 oldsize '1)
+    (lhzx imm4 oldv imm1)
+    (addi imm1 imm1 2)
+    (subi oldsize oldsize '1)
+    (sthx imm4 arg_z imm3)
+    (addi imm3 imm3 2)
+    (bne cr0 @16-loop)
+    (b @done)
+    @8-bit
+    (srdi imm1 start-offset 3)
+    (la imm1 ppc64::misc-data-offset imm1)
+    @8-loop
+    (cmpdi cr0 oldsize '1)
+    (lbzx imm4 oldv imm1)
+    (addi imm1 imm1 1)
+    (subi oldsize oldsize '1)
+    (stbx imm4 arg_z imm3)
+    (addi imm3 imm3 1)
+    (bne cr0 @8-loop)
+    (b @done)
+    @32-bit
+    (srdi imm1 start-offset 1)
+    (la imm1 ppc64::misc-data-offset imm1)
+    @32-loop
+    (cmpdi cr0 oldsize '1)
+    (lwzx imm4 oldv imm1)
+    (addi imm1 imm1 4)
+    (subi oldsize oldsize '1)
+    (stwx imm4 arg_z imm3)
+    (addi imm3 imm3 4)
+    (bne cr0 @32-loop)
+    (b @done)
+    @64-bit
+    (la imm1 ppc64::misc-data-offset start-offset)
+    @64-loop
+    (cmpdi cr0 oldsize '1)
+    (ldx imm4 oldv imm1)
+    (addi imm1 imm1 8)
+    (subi oldsize oldsize '1)
+    (stdx imm4 arg_z imm3)
+    (addi imm3 imm3 8)
+    (bne cr0 @64-loop)
+    (b @done)
+    @1-bit
+    (let ((newv save4)
+          (outi save5)
+          (oldlen save6))
+      (vpush save4)
+      (vpush save5)
+      (vpush save6)
+      (mr newv arg_z)
+      (sub oldlen oldsize start-offset)
+      (li outi 0)
+      @hard-loop
+      (mr arg_y oldv)
+      (mr arg_z start-offset)
+      (bla .SPmisc-ref)
+      (mr arg_x newv)
+      (mr arg_y outi)
+      (bla .SPmisc-set)
+      (la outi '1 outi)
+      (cmpd cr0 outi oldlen)
+      (la start-offset '1 start-offset)
+      (bne @hard-loop)
+      (mr arg_z newv)
+      (vpop save6)
+      (vpop save5)
+      (vpop save4)
+      (b @done))))
+
+
+;;; argument is a vector header or an array header.  Or else.
+(defppclapfunction %array-header-data-and-offset ((a arg_z))
+  (let ((offset arg_y)
+        (disp arg_x)
+        (temp temp0))
+    (li offset 0)
+    (mr temp a)
+    @loop
+    (ldr a target::arrayH.data-vector temp)
+    (lbz imm0 target::misc-subtag-offset a)
+    (cmpri cr0 imm0 target::subtag-vectorH)
+    (ldr disp target::arrayH.displacement temp)
+    (mr temp a)
+    (add offset offset disp)
+    (ble cr0 @loop)
+    (vpush a)
+    (vpush offset)
+    (set-nargs 2)
+    (la temp0 (* 2 (ash 1 target::word-shift)) vsp)
+    (ba .SPvalues)))
+
+
+;;; If the bit-arrays are all simple-bit-vectorp, we can do the operations
+;;; 32 bits at a time.  (other case have to worry about alignment/displacement.)
+#+ppc32-target
+(defppclapfunction %simple-bit-boole ((op 0) (b1 arg_x) (b2 arg_y) (result arg_z))
+  (la imm0 4 vsp)
+  (save-lisp-context imm0)
+  (vector-size imm4 result imm4)
+  (srwi. imm3 imm4 5)
+  (clrlwi imm4 imm4 27)
+  (bl @get-dispatch)
+  (cmpwi cr1 imm4 0)
+  (mflr loc-pc)
+  (lwz temp0 op vsp)
+  (add loc-pc loc-pc temp0)
+  (add loc-pc loc-pc temp0)
+  (mtctr loc-pc)
+  (li imm0 ppc32::misc-data-offset)
+  (b @testw)
+  @nextw
+  (cmpwi cr0 imm3 1)
+  (subi imm3 imm3 1)
+  (lwzx imm1 b1 imm0)
+  (lwzx imm2 b2 imm0)
+  (bctrl)
+  (stwx imm1 result imm0)
+  (addi imm0 imm0 4)
+  @testw
+  (bne cr0 @nextw)
+  (beq cr1 @done)
+  ;; Not sure if we need to make this much fuss about the partial word
+  ;; in this simple case, but what the hell.
+  (lwzx imm1 b1 imm0)
+  (lwzx imm2 b2 imm0)
+  (bctrl)
+  (lwzx imm2 result imm0)
+  (slw imm2 imm2 imm4)
+  (srw imm2 imm2 imm4)
+  (subfic imm4 imm4 32)
+  (srw imm1 imm1 imm4)
+  (slw imm1 imm1 imm4)
+  (or imm1 imm1 imm2)
+  (stwx imm1 result imm0)
+  @done
+  (restore-full-lisp-context)
+  (blr)
+
+  @get-dispatch 
+  (blrl)
+  @disptach
+  (li imm1 0)                           ; boole-clr
+  (blr)
+  (li imm1 -1)                          ; boole-set
+  (blr)
+  (blr)                                 ; boole-1
+  (blr)                             
+  (mr imm1 imm2)                        ; boole-2
+  (blr)
+  (not imm1 imm1)                       ; boole-c1
+  (blr)
+  (not imm1 imm2)                       ; boole-c2
+  (blr)
+  (and imm1 imm1 imm2)                  ; boole-and
+  (blr)
+  (or imm1 imm1 imm2)                   ; boole-ior
+  (blr)
+  (xor imm1 imm1 imm2)                  ; boole-xor
+  (blr)
+  (eqv imm1 imm1 imm2)                  ; boole-eqv
+  (blr)
+  (nand imm1 imm1 imm2)                 ; boole-nand
+  (blr)
+  (nor imm1 imm1 imm2)                  ; boole-nor
+  (blr)
+  (andc imm1 imm2 imm1)                 ; boole-andc1
+  (blr)
+  (andc imm1 imm1 imm2)                 ; boole-andc2
+  (blr)
+  (orc imm1 imm2 imm1)                  ; boole-orc1
+  (blr)
+  (orc imm1 imm1 imm2)                  ; boole-orc2
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %simple-bit-boole ((op 0) (b1 arg_x) (b2 arg_y) (result arg_z))
+  (la imm0 8 vsp)
+  (save-lisp-context imm0)
+  (vector-size imm4 result imm4)
+  (srdi. imm3 imm4 6)
+  (clrldi imm4 imm4 (- 64 6))
+  (bl @get-dispatch)
+  (cmpdi cr1 imm4 0)                    ; at most low 6 bits set in imm4
+  (mflr loc-pc)
+  (ld temp0 op vsp)
+  (add loc-pc loc-pc temp0)
+  (mtctr loc-pc)
+  (li imm0 ppc64::misc-data-offset)
+  (b @testd)
+  @nextd
+  (cmpdi cr0 imm3 1)
+  (subi imm3 imm3 1)
+  (ldx imm1 b1 imm0)
+  (ldx imm2 b2 imm0)
+  (bctrl)
+  (stdx imm1 result imm0)
+  (addi imm0 imm0 8)
+  @testd
+  (bne cr0 @nextd)
+  (beq cr1 @done)
+  ;; Not sure if we need to make this much fuss about the partial word
+  ;; in this simple case, but what the hell.
+  (ldx imm1 b1 imm0)
+  (ldx imm2 b2 imm0)
+  (bctrl)
+  (ldx imm2 result imm0)
+  (sld imm2 imm2 imm4)
+  (srd imm2 imm2 imm4)
+  (subfic imm4 imm4 64)
+  (srd imm1 imm1 imm4)
+  (sld imm1 imm1 imm4)
+  (or imm1 imm1 imm2)
+  (stdx imm1 result imm0)
+  @done
+  (restore-full-lisp-context)
+  (blr)
+
+  @get-dispatch 
+  (blrl)
+  @disptach
+  (li imm1 0)                           ; boole-clr
+  (blr)
+  (li imm1 -1)                          ; boole-set
+  (blr)
+  (blr)                                 ; boole-1
+  (blr)                             
+  (mr imm1 imm2)                        ; boole-2
+  (blr)
+  (not imm1 imm1)                       ; boole-c1
+  (blr)
+  (not imm1 imm2)                       ; boole-c2
+  (blr)
+  (and imm1 imm1 imm2)                  ; boole-and
+  (blr)
+  (or imm1 imm1 imm2)                   ; boole-ior
+  (blr)
+  (xor imm1 imm1 imm2)                  ; boole-xor
+  (blr)
+  (eqv imm1 imm1 imm2)                  ; boole-eqv
+  (blr)
+  (nand imm1 imm1 imm2)                 ; boole-nand
+  (blr)
+  (nor imm1 imm1 imm2)                  ; boole-nor
+  (blr)
+  (andc imm1 imm2 imm1)                 ; boole-andc1
+  (blr)
+  (andc imm1 imm1 imm2)                 ; boole-andc2
+  (blr)
+  (orc imm1 imm2 imm1)                  ; boole-orc1
+  (blr)
+  (orc imm1 imm1 imm2)                  ; boole-orc2
+  (blr))
+
+
+(defppclapfunction %aref2 ((array arg_x) (i arg_y) (j arg_z))
+  (check-nargs 3)
+  (ba .SParef2))
+
+(defppclapfunction %aref3 ((array 0) (i arg_x) (j arg_y) (k arg_z))
+  (check-nargs 4)
+  (vpop temp0)
+  (ba .SParef3))
+
+
+(defppclapfunction %aset2 ((array 0) (i arg_x) (j arg_y) (newval arg_z))
+  (check-nargs 4)
+  (vpop temp0)
+  (ba .SPaset2))
+
+(defppclapfunction %aset3 ((array #.target::node-size) (i 0) (j arg_x) (k arg_y)  (newval arg_z))
+  (check-nargs 5)
+  (vpop temp0)
+  (vpop temp1)
+  (ba .SPaset3))
+  
+
Index: /branches/new-random/level-0/PPC/ppc-clos.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-clos.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-clos.lisp	(revision 13309)
@@ -0,0 +1,331 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; It's easier to keep this is LAP; we want to play around with its
+;;; constants.
+
+;;; This just maps a SLOT-ID to a SLOT-DEFINITION or NIL.
+;;; The map is a vector of (UNSIGNED-BYTE 8); this should
+;;; be used when there are less than 255 slots in the class.
+(defppclapfunction %small-map-slot-id-lookup ((slot-id arg_z))
+  (ldr temp1 'map nfn)
+  (svref arg_x slot-id.index slot-id)
+  (getvheader imm0 temp1)
+  (header-length imm3 imm0)
+  (ldr temp0 'table nfn)
+  (cmplr arg_x imm3)
+  (srri imm0 arg_x target::word-shift)
+  (la imm0 target::misc-data-offset imm0)
+  (li imm1 target::misc-data-offset)
+  (bge @have-scaled-table-index)
+  (lbzx imm1 temp1 imm0)
+  (slri imm1 imm1 target::word-shift)
+  (la imm1 target::misc-data-offset imm1)
+  @have-scaled-table-index
+  (ldrx arg_z temp0 imm1)
+  (blr))
+
+;;; The same idea, only the map is a vector of (UNSIGNED-BYTE 32).
+(defppclapfunction %large-map-slot-id-lookup ((slot-id arg_z))
+  (ldr temp1 'map nfn)
+  (svref arg_x slot-id.index slot-id)
+  (getvheader imm0 temp1)
+  (header-length imm3 imm0)
+  (ldr temp0 'table nfn)
+  (cmplr arg_x imm3)
+  #+ppc64-target
+  (progn
+    (srdi imm0 imm0 1)
+    (la imm0 target::misc-data-offset imm0))
+  #+pp32-target
+  (progn
+    (la imm0 target::misc-data-offset arg_x))
+  (li imm1 target::misc-data-offset)
+  (bge @have-scaled-table-index)
+  (lwzx imm1 temp1 imm0)
+  (slri imm1 imm1 target::word-shift)
+  (la imm1 target::misc-data-offset imm1)
+  @have-scaled-table-index
+  (ldrx arg_z temp0 imm1)
+  (blr))
+
+(defppclapfunction %small-slot-id-value ((instance arg_y) (slot-id arg_z))
+  (ldr temp1 'map nfn)
+  (svref arg_x slot-id.index slot-id)
+  (getvheader imm0 temp1)
+  (ldr temp0 'table nfn)
+  (header-length imm3 imm0)
+  (cmplr arg_x imm3)
+  (srri imm0 arg_x target::word-shift)
+  (la imm0 target::misc-data-offset imm0)
+  (bge @missing)
+  (lbzx imm1 temp1 imm0)
+  (cmpri imm1 0)
+  (slri imm1 imm1 target::word-shift)
+  (la imm1 target::misc-data-offset imm1)
+  (beq @missing)
+  (ldrx arg_z temp0 imm1)
+  (ldr arg_x 'class nfn)
+  (ldr nfn '%maybe-std-slot-value nfn)
+  (ldr temp0 target::misc-data-offset nfn)
+  (set-nargs 3)
+  (mtctr temp0)
+  (bctr)
+  @missing                              ; (%slot-id-ref-missing instance id)
+  (ldr nfn '%slot-id-ref-missing nfn)
+  (set-nargs 2)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+
+(defppclapfunction %large-slot-id-value ((instance arg_y) (slot-id arg_z))
+  (ldr temp1 'map nfn)
+  (svref arg_x slot-id.index slot-id)
+  (getvheader imm0 temp1)
+  (ldr temp0 'table nfn)
+  (header-length imm3 imm0)
+  (cmplr arg_x imm3)
+  #+ppc64-target
+  (progn
+    (srdi imm0 arg_x 1)
+    (la imm0 target::misc-data-offset imm0))
+  #+ppc32-target
+  (progn
+    (la imm0 target::misc-data-offset arg_x))
+  (bge @missing)
+  (lwzx imm1 temp1 imm0)
+  (cmpri imm1 0)
+  (slri imm1 imm1 target::word-shift)
+  (la imm1 target::misc-data-offset imm1)
+  (beq @missing)
+  @have-scaled-table-index
+  (ldr arg_x 'class nfn)
+  (ldr nfn '%maybe-std-slot-value-using-class nfn)
+  (ldrx arg_z temp0 imm1)
+  (ldr temp0 target::misc-data-offset nfn)
+  (set-nargs 3)
+  (mtctr temp0)
+  (bctr)
+  @missing                              ; (%slot-id-ref-missing instance id)
+  (ldr nfn '%slot-id-ref-missing nfn)
+  (set-nargs 2)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+  
+(defppclapfunction %small-set-slot-id-value ((instance arg_x)
+                                             (slot-id arg_y)
+                                             (new-value arg_z))
+  (ldr temp1 'map nfn)
+  (svref imm3 slot-id.index slot-id)
+  (getvheader imm0 temp1)
+  (ldr temp0 'table nfn)
+  (header-length imm5 imm0)
+  (cmplr imm3 imm5)
+  (srri imm0 imm3 target::word-shift)
+  (la imm0 target::misc-data-offset imm0)
+  (bge @missing)
+  (lbzx imm1 temp1 imm0)
+  (cmpwi imm1 0)
+  (slri imm1 imm1 target::word-shift)
+  (la imm1 target::misc-data-offset imm1)
+  (beq @missing)
+  @have-scaled-table-index
+  (ldr temp1 'class nfn)
+  (ldrx arg_y temp0 imm1)
+  (ldr nfn '%maybe-std-setf-slot-value-using-class nfn)
+  (set-nargs 4)
+  (ldr temp0 target::misc-data-offset nfn)
+  (vpush temp1)
+  (mtctr temp0)
+  (bctr)
+  @missing                              ; (%slot-id-set-missing instance id new-value)
+  (ldr nfn '%slot-id-set-missing nfn)
+  (set-nargs 3)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+
+(defppclapfunction %large-set-slot-id-value ((instance arg_x)
+                                             (slot-id arg_y)
+                                             (new-value arg_z))
+  (ldr temp1 'map nfn)
+  (svref imm3 slot-id.index slot-id)
+  (getvheader imm0 temp1)
+  (ldr temp0 'table nfn)
+  (header-length imm5 imm0)
+  (cmplr imm3 imm5)
+  #+ppc64-target (srdi imm3 imm3 1)
+  (la imm0 target::misc-data-offset imm3)
+  (bge @missing)
+  (lwzx imm1 temp1 imm0)
+  (cmpwi imm1 0)
+  (slri imm1 imm1 target::word-shift)
+  (la imm1 target::misc-data-offset imm1)
+  (beq @missing)
+  @have-scaled-table-index
+  (ldr temp1 'class nfn)
+  (ldrx arg_y temp0 imm1)
+  (ldr nfn '%maybe-std-setf-slot-value-using-class nfn)
+  (set-nargs 4)
+  (svref temp0 0 nfn)
+  (vpush temp1)
+  (mtctr temp0)
+  (bctr)
+  @missing                              ; (%slot-id-set-missing instance id new-value)
+  (ldr nfn '%slot-id-ref-missing nfn)
+  (set-nargs 3)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+
+#-dont-use-lexprs
+(defparameter *gf-proto*
+  (nfunction
+   gag
+   (lambda (&lap &lexpr args)
+     (ppc-lap-function 
+      gag 
+      ()
+      (mflr loc-pc)
+      (vpush-argregs)
+      (vpush nargs)
+      (add imm0 vsp nargs)
+      (la imm0 (ash 1 target::word-shift) imm0)                  ; caller's vsp
+      (bla .SPlexpr-entry)
+      (mtlr loc-pc)                     ; return to kernel
+      (mr arg_z vsp)                    ; lexpr
+      (svref arg_y gf.dispatch-table nfn) ; dispatch table
+      (set-nargs 2)
+      (svref nfn gf.dcode nfn)		; dcode function
+      (ldr temp0 target::misc-data-offset nfn)
+      (mtctr temp0)
+      (bctr)))))
+
+#+dont-use-lexprs
+(defparameter *gf-proto*
+  (nfunction
+   gag
+   (lambda (&lap &rest args)
+     (ppc-lap-function
+      gag
+      ()
+      ;;(bkpt)
+      (mflr loc-pc)
+      (bla .SPstack-rest-arg)
+      (vpop arg_z)
+      (stru sp (- target::lisp-frame.size) sp)
+      (str fn target::lisp-frame.savefn sp)
+      (str loc-pc target::lisp-frame.savelr sp)
+      (str vsp target::lisp-frame.savevsp sp)
+      (mr fn nfn)
+      ;; If we were called for multiple values, call the dcode
+      ;; for multiple values.
+      (ref-global imm0 ret1valaddr)
+      (cmpr imm0 loc-pc)
+      (svref arg_y gf.dispatch-table fn) ; dispatch table
+      (set-nargs 2)
+      (svref nfn gf.dcode fn)		; dcode function
+      (beq @multiple)
+      (ldr temp0 target::misc-data-offset nfn)
+      (mtctr temp0)
+      (bctrl)
+      (ldr tsp 0 tsp)
+      (restore-full-lisp-context)
+      (blr)
+      @multiple
+      (bl @getback)
+      (mflr loc-pc)
+      (stru sp (- target::lisp-frame.size) sp)
+      (str fn target::lisp-frame.savefn sp)
+      (str loc-pc target::lisp-frame.savelr sp)
+      (str vsp target::lisp-frame.savevsp sp)
+      (mtlr imm0)
+      (li fn 0)
+      (ldr temp0 target::misc-data-offset nfn)
+      (mtctr temp0)
+      (bctr)
+      @getback
+      (blrl)
+      @back
+      (ldr tsp 0 tsp)
+      (ba .SPnvalret)))))
+      
+      
+
+(defppclapfunction funcallable-trampoline ()
+  (svref nfn gf.dcode nfn)
+  (svref temp0 0 nfn)
+  (mtctr temp0)
+  (bctr))
+
+;;; This can't reference any of the function's constants.
+(defppclapfunction unset-fin-trampoline ()
+  (mflr loc-pc)
+  (bla .SPheap-rest-arg)                ; cons up an &rest arg, vpush it
+  (vpop arg_z)                          ; whoops, didn't really want to
+  (bla .SPsavecontextvsp)
+  (li arg_x '#.$XNOFINFUNCTION)
+  (mr arg_y nfn)
+  (set-nargs 3)
+  (bla .SPksignalerr)
+  (li arg_z nil)
+  (ba .SPpopj))
+
+;;; is a winner - saves ~15%
+(defppclapfunction gag-one-arg ((arg arg_z))
+  (check-nargs 1)  
+  (svref arg_y gf.dispatch-table nfn) ; mention dt first
+  (set-nargs 2)
+  (svref nfn gf.dcode nfn)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+
+
+(defppclapfunction gag-two-arg ((arg0 arg_y) (arg1 arg_z))
+  (check-nargs 2)  
+  (svref arg_x gf.dispatch-table nfn) ; mention dt first
+  (set-nargs 3)
+  (svref nfn gf.dcode nfn)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+
+(defparameter *cm-proto*
+  (nfunction
+   gag
+   (lambda (&lap &lexpr args)
+     (ppc-lap-function 
+      gag 
+      ()
+      (mflr loc-pc)
+      (vpush-argregs)
+      (vpush nargs)
+      (add imm0 vsp nargs)
+      (la imm0 target::node-size imm0)                  ; caller's vsp
+      (bla .SPlexpr-entry)
+      (mtlr loc-pc)                     ; return to kernel
+      (mr arg_z vsp)                    ; lexpr
+      (svref arg_y combined-method.thing nfn) ; thing
+      (set-nargs 2)
+      (svref nfn combined-method.dcode nfn) ; dcode function
+      (ldr temp0 target::misc-data-offset nfn)
+      (mtctr temp0)
+      (bctr)))))
Index: /branches/new-random/level-0/PPC/ppc-def.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-def.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-def.lisp	(revision 13309)
@@ -0,0 +1,1281 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Do an FF-CALL to MakeDataExecutable so that the data cache gets flushed.
+;;; If the GC moves this function while we're trying to flush the cache,
+;;; it'll flush the cache: no harm done in that case.
+(defppclapfunction %make-code-executable ((codev arg_z))
+  (let ((len imm2)
+	(word-offset imm0))
+    (save-lisp-context)
+    (getvheader word-offset codev)
+    (header-size len word-offset)
+    ;; The idea is that if we GC here, no harm is done (since the GC
+    ;; will do any necessary cache-flushing.)  The idea may be
+    ;; incorrect: if we pass an address that's not mapped anymore,
+    ;; could we fault ?
+    (stru sp (- (+ #+eabi-target ppc32::eabi-c-frame.minsize
+		   #+poweropen-target target::c-frame.minsize target::lisp-frame.size)) sp)	; make an FFI frame.
+    (la imm0 target::misc-data-offset codev)
+    (slri len len 2)
+    (str imm0 #+eabi-target ppc32::eabi-c-frame.param0 #+poweropen-target target::c-frame.param0  sp)
+    (str len #+eabi-target ppc32::eabi-c-frame.param1 #+poweropen-target target::c-frame.param1 sp)
+    (ref-global imm3 kernel-imports)
+    (ldr arg_z target::kernel-import-MakeDataExecutable imm3)
+    (bla #+eabi-target .SPeabi-ff-call #+poweropen-target .SPpoweropen-ffcall)
+    (li arg_z nil)
+    (restore-full-lisp-context)
+    (blr)))
+
+(defppclapfunction %get-kernel-global-from-offset ((offset arg_z))
+  (check-nargs 1)
+  (unbox-fixnum imm0 offset)
+  (addi imm0 imm0 (target-nil-value))
+  (ldr arg_z 0 imm0)
+  (blr))
+
+(defppclapfunction %set-kernel-global-from-offset ((offset arg_y) (new-value arg_z))
+  (check-nargs 2)
+  (unbox-fixnum imm0 offset)
+  (addi imm0 imm0 (target-nil-value))
+  (str new-value 0 imm0)
+  (blr))
+
+
+
+(defppclapfunction %get-kernel-global-ptr-from-offset ((offset arg_y)
+						       (ptr arg_z))
+  (check-nargs 2)
+  (unbox-fixnum imm0 offset)
+  (addi imm0 imm0 (target-nil-value))
+  (ldr imm0 0 imm0)
+  (str imm0 target::macptr.address ptr)
+  (blr))
+
+
+
+
+(defppclapfunction %fixnum-ref ((fixnum arg_y) #| &optional |# (offset arg_z))
+  (cmpri cr0 nargs '1)
+  (check-nargs 1 2)
+  (bne cr0 @2-args)
+  (mr fixnum offset)
+  (li offset 0)
+  @2-args
+  (unbox-fixnum imm0 offset)
+  (ldrx arg_z imm0 fixnum)
+  (blr))
+
+
+#+ppc32-target
+(defppclapfunction %fixnum-ref-natural ((fixnum arg_y) #| &optional |# (offset arg_z))
+  (cmpri cr0 nargs '1)
+  (check-nargs 1 2)
+  (bne cr0 @2-args)
+  (mr fixnum offset)
+  (li offset 0)
+  @2-args
+  (unbox-fixnum imm0 offset)
+  (lwzx imm0 imm0 fixnum)
+  (ba .SPmakeu32))
+
+#+ppc64-target
+(defppclapfunction %fixnum-ref-natural ((fixnum arg_y) #| &optional |# (offset arg_z))
+  (cmpdi cr0 nargs '1)
+  (check-nargs 1 2)
+  (bne cr0 @2-args)
+  (mr fixnum offset)
+  (li offset 0)
+  @2-args
+  (unbox-fixnum imm0 offset)
+  (ldx imm0 imm0 fixnum)
+  (ba .SPmakeu64))
+
+(defppclapfunction %fixnum-set ((fixnum arg_x) (offset arg_y) #| &optional |# (new-value arg_z))
+  (cmpi cr0 nargs '2)
+  (check-nargs 2 3)
+  (bne cr0 @3-args)
+  (mr fixnum offset)
+  (li offset 0)
+  @3-args
+  (unbox-fixnum imm0 offset)
+  (strx new-value imm0 fixnum)
+  (mr arg_z new-value)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %fixnum-set-natural ((fixnum arg_x) (offset arg_y) #| &optional |# (new-value arg_z))
+  (cmpwi cr0 nargs '2)
+  (check-nargs 2 3)
+  (bne cr0 @3-args)
+  (mr fixnum offset)
+  (li offset 0)
+  @3-args
+  (unbox-fixnum imm0 offset)
+  (extract-typecode imm1 new-value)
+  (cmpwi cr0 imm1 ppc32::tag-fixnum)
+  (cmpwi cr1 imm1 ppc32::subtag-bignum)
+  (srwi imm2 new-value ppc32::fixnumshift)
+  (beq cr0 @store)
+  (beq cr1 @bignum)
+  @notu32
+  (uuo_interr arch::error-object-not-unsigned-byte-32 new-value)
+  @bignum
+  (getvheader imm0 new-value)
+  (cmpwi cr1 imm0 ppc32::one-digit-bignum-header)
+  (cmpwi cr2 imm0 ppc32::two-digit-bignum-header)
+  (lwz imm2 ppc32::misc-data-offset new-value)
+  (cmpwi cr0 imm2 0)
+  (beq cr1 @one)
+  (bne cr2 @notu32)
+  (lwz imm1 (+ 4 ppc32::misc-data-offset) new-value)
+  (cmpwi cr1 imm1 0)
+  (bgt cr0 @notu32)
+  (beq cr1 @store)
+  (b @notu32)
+  @one
+  (blt cr0 @notu32)
+  @store
+  (stwx imm2 imm0 fixnum)
+  (mr arg_z new-value)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %fixnum-set-natural ((fixnum arg_x) (offset arg_y) #| &optional |# (new-value arg_z))
+  (cmpdi cr0 nargs '2)
+  (check-nargs 2 3)
+  (bne cr0 @3-args)
+  (mr fixnum offset)
+  (li offset 0)
+  @3-args
+  (unbox-fixnum imm0 offset)
+  (extract-typecode imm1 new-value)
+  (cmpdi cr0 imm1 ppc64::tag-fixnum)
+  (cmpdi cr1 imm1 ppc64::subtag-bignum)
+  (srdi imm2 new-value ppc64::fixnumshift)
+  (beq cr0 @store)
+  (beq cr1 @bignum)
+  @notu64
+  (uuo_interr arch::error-object-not-unsigned-byte-64 new-value)
+  @bignum
+  (ld imm2 ppc64::misc-data-offset new-value)
+  (getvheader imm0 new-value)
+  (cmpdi cr1 imm0 ppc64::two-digit-bignum-header)
+  (rotldi imm2 imm2 32)
+  (cmpdi cr2 imm0 ppc64::three-digit-bignum-header)
+  (cmpdi cr0 imm2 0)
+  (beq cr1 @two)
+  (bne cr2 @notu64)
+  (lwz imm1 (+ 8 ppc64::misc-data-offset) new-value)
+  (cmpwi cr1 imm1 0)
+  (bgt cr0 @notu64)
+  (beq cr1 @store)
+  (b @notu64)
+  @two
+  (blt cr0 @notu64)
+  @store
+  (stdx imm2 imm0 fixnum)
+  (mr arg_z new-value)
+  (blr))
+
+
+(defppclapfunction %current-frame-ptr ()
+  (check-nargs 0)
+  (mr arg_z sp)
+  (blr))
+
+(defppclapfunction %current-vsp ()
+  (check-nargs 0)
+  (mr arg_z vsp)
+  (blr))
+
+
+
+
+(defppclapfunction %set-current-vsp ((new-vsp arg_z))
+  (check-nargs 1)
+  (mr vsp new-vsp)
+  (blr))
+
+(defppclapfunction %current-tsp ()
+  (check-nargs 0)
+  (mr arg_z tsp)
+  (blr))
+
+
+
+(defppclapfunction %set-current-tsp ((new-tsp arg_z))
+  (check-nargs 1)
+  (mr tsp new-tsp)
+  (blr))
+
+(defppclapfunction %%frame-backlink ((p arg_z))
+  (check-nargs 1)
+  (ldr arg_z target::lisp-frame.backlink arg_z)
+  (blr))
+
+
+
+
+
+(defppclapfunction %%frame-savefn ((p arg_z))
+  (check-nargs 1)
+  (ldr arg_z target::lisp-frame.savefn arg_z)
+  (blr))
+
+(defppclapfunction %cfp-lfun ((p arg_z))
+  (ldr arg_y target::lisp-frame.savefn p)
+  (extract-typecode imm0 arg_y)
+  (cmpri imm0 target::subtag-function)
+  (ldr loc-pc target::lisp-frame.savelr p)
+  (bne @no)
+  (ldr arg_x target::misc-data-offset arg_y)
+  (sub imm1 loc-pc arg_x)
+  (la imm1 (- target::misc-data-offset) imm1)
+  (getvheader imm0 arg_x)
+  (header-length imm0 imm0)
+  (cmplr imm1 imm0)
+  (box-fixnum imm1 imm1)
+  (bge @no)
+  (vpush arg_y)
+  (vpush imm1)
+  @go
+  (set-nargs 2)
+  (la temp0 '2 vsp)
+  (ba .SPvalues)
+  @no
+  (li imm0 nil)
+  (vpush imm0)
+  (vpush imm0)
+  (b @go))
+
+
+
+
+(defppclapfunction %%frame-savevsp ((p arg_z))
+  (check-nargs 1)
+  (ldr arg_z target::lisp-frame.savevsp arg_z)
+  (blr))
+
+
+
+
+
+#+ppc32-target
+(eval-when (:compile-toplevel :execute)
+  (assert (eql ppc32::t-offset #x11)))
+
+(defppclapfunction %uvector-data-fixnum ((uv arg_z))
+  (check-nargs 1)
+  (trap-unless-fulltag= arg_z target::fulltag-misc)
+  (la arg_z target::misc-data-offset arg_z)
+  (blr))
+
+(defppclapfunction %catch-top ((tcr arg_z))
+  (check-nargs 1)
+  (ldr arg_z target::tcr.catch-top tcr)
+  (cmpri cr0 arg_z 0)
+  (bne @ret)
+  (li arg_z nil)
+ @ret
+  (blr))
+
+(defppclapfunction %catch-tsp ((catch arg_z))
+  (check-nargs 1)
+  (la arg_z (- (+ target::fulltag-misc
+                                 (ash 1 (1+ target::word-shift)))) arg_z)
+  (blr))
+
+
+
+;;; Same as %address-of, but doesn't cons any bignums
+;;; It also left shift fixnums just like everything else.
+(defppclapfunction %fixnum-address-of ((x arg_z))
+  (check-nargs 1)
+  (box-fixnum arg_z x)
+  (blr))
+
+
+
+(defppclapfunction %save-standard-binding-list ((bindings arg_z))
+  (ldr imm0 target::tcr.vs-area target::rcontext)
+  (ldr imm1 target::area.high imm0)
+  (push bindings imm1)
+  (blr))
+
+(defppclapfunction %saved-bindings-address ()
+  (ldr imm0 target::tcr.vs-area target::rcontext)
+  (ldr imm1 target::area.high imm0)
+  (la arg_z (- target::node-size) imm1)
+  (blr))
+
+(defppclapfunction %code-vector-pc ((code-vector arg_y) (pcptr arg_z))
+  (macptr-ptr imm0 pcptr)
+  (ldr loc-pc 0 imm0)
+  (sub imm0 loc-pc code-vector)
+  (subi imm0 imm0 target::misc-data-offset)
+  (getvheader imm1 code-vector)
+  (header-size imm1 imm1)
+  (slri imm1 imm1 2)
+  (cmplr imm0 imm1)
+  (li arg_z nil)
+  (bgelr)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+;;; FF-call, in LAP.
+#+eabi-target
+(progn
+  (defppclapfunction %%ff-call ((fploads 8)
+                                (single-offset 4)
+                                (double-offset 0)
+                                (framesize arg_x) ;always even, negative, includes frame overhead
+                                (buf arg_y)
+                                (entry arg_z))
+    (check-nargs 6)
+    (la imm0 12 vsp)
+    (save-lisp-context imm0)
+    (stwux sp sp framesize)
+    (stw sp 4 sp)
+    (macptr-ptr imm2 buf)
+    (mr imm1 imm2)
+    (la imm3 ppc32::eabi-c-frame.param0 sp)
+    (li imm0 0)
+    (lwz temp1 single-offset vsp)
+    (lwz temp2 double-offset vsp)
+    @copy
+    (addi imm0 imm0 8)
+    (cmpw imm0 temp1)
+    (lfd fp0 0 imm2)
+    (la imm2 8 imm2)
+    (stfd fp0 0 imm3)
+    (la imm3 8 imm3)
+    (blt @copy)
+    ;; We've copied the gpr-save area and the "other" arg words.
+    ;; Sadly, we may still need to load up to 8 FPRs, and we have
+    ;; to use some pretty ugly code to do so.
+    (add temp1 temp1 imm1)
+    (add temp2 temp2 imm1)
+    (lwz temp0 fploads vsp)
+    @load-fp1
+    (lbz imm0 (+ ppc32::misc-data-offset 0) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp1-double)
+    (lfs fp1 0 temp1)
+    (la temp1 4 temp1)
+    (b @load-fp2)
+    @load-fp1-double
+    (lfd fp1 0 temp2)
+    (la temp2 8 temp2)
+    @load-fp2
+    (lbz imm0 (+ ppc32::misc-data-offset 1) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp2-double)
+    (lfs fp2 0 temp1)
+    (la temp1 4 temp1)
+    (b @load-fp3)
+    @load-fp2-double
+    (lfd fp2 0 temp2)
+    (la temp2 8 temp2)
+    @load-fp3
+    (lbz imm0 (+ ppc32::misc-data-offset 2) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp3-double)
+    (lfs fp3 0 temp1)
+    (la temp1 4 temp1)
+    (b @load-fp4)
+    @load-fp3-double
+    (lfd fp3 0 temp2)
+    (la temp2 8 temp2)
+    @load-fp4
+    (lbz imm0 (+ ppc32::misc-data-offset 3) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp4-double)
+    (lfs fp4 0 temp1)
+    (la temp1 4 temp1)
+    (b @load-fp5)
+    @load-fp4-double
+    (lfd fp4 0 temp2)
+    (la temp2 8 temp2)
+    @load-fp5
+    (lbz imm0 (+ ppc32::misc-data-offset 4) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp5-double)
+    (lfs fp5 0 temp1)
+    (la temp1 4 temp1)
+    (b @load-fp6)
+    @load-fp5-double
+    (lfd fp5 0 temp2)
+    (la temp2 8 temp2)
+    @load-fp6
+    (lbz imm0 (+ ppc32::misc-data-offset 5) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp6-double)
+    (lfs fp6 0 temp1)
+    (la temp1 4 temp1)
+    (b @load-fp7)
+    @load-fp6-double
+    (lfd fp6 0 temp2)
+    (la temp2 8 temp2)
+    @load-fp7
+    (lbz imm0 (+ ppc32::misc-data-offset 6) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp7-double)
+    (lfs fp7 0 temp1)
+    (la temp1 4 temp1)
+    (b @load-fp8)
+    @load-fp7-double
+    (lfd fp7 0 temp2)
+    (la temp2 8 temp2)
+    @load-fp8
+    (lbz imm0 (+ ppc32::misc-data-offset 0) temp0)
+    (cmpwi imm0 1)
+    (blt @loaded)
+    (bne @load-fp8-double)
+    (lfs fp8 0 temp1)
+    (b @loaded)
+    @load-fp8-double
+    (lfd fp8 0 temp2)
+    @loaded
+    (vpush buf)
+    (bla .SPeabi-ff-call)
+    (vpop buf)
+    (macptr-ptr imm2 buf)
+    (stw imm0 0 imm2)
+    (stw imm1 4 imm2)
+    (stfs fp1 8 imm2)
+    (stfd fp1 16 imm2)
+    (restore-full-lisp-context)
+    (li arg_z (target-nil-value))
+    (blr))
+  
+  (defun %ff-call (entry &rest specs-and-vals)
+    "Call the foreign function at address entrypoint passing the values of
+each arg as a foreign argument of type indicated by the corresponding
+arg-type-keyword. Returns the foreign function result (coerced to a Lisp
+object of type indicated by result-type-keyword), or NIL if
+result-type-keyword is :VOID or NIL"
+    (declare (dynamic-extent specs-and-vals))
+    (let* ((len (length specs-and-vals))
+           (other-offset 8)
+           (single-float-offset 8)
+           (double-float-offset 0)
+           (nsingle-floats 0)
+           (ndouble-floats 0)
+           (nother-words 0)
+           (nfpr-args 0)
+           (ngpr-args 0))
+      (declare (fixnum len  other-offset single-float-offset double-float-offset
+                       nsingle-floats ndouble-floats nother-words nfpr-args ngpr-args))
+      (unless (oddp len)
+        (error "Length of ~s is even.  Missing result ?" specs-and-vals))
+
+      (let* ((result-spec (or (car (last specs-and-vals)) :void))
+             (nargs (ash (the fixnum (1- len)) -1))
+             (fpr-reloads (make-array 8 :element-type '(unsigned-byte 8))))
+        (declare (fixnum nargs) (dynamic-extent fpr-reloads))
+        (do* ((i 0 (1+ i))
+              (specs specs-and-vals (cddr specs))
+              (spec (car specs) (car specs)))
+             ((= i nargs))
+          (declare (fixnum i))
+          (ecase spec
+            (:double-float (incf nfpr-args)
+                           (if (<= nfpr-args 8)
+                             (incf ndouble-floats)
+                             (progn
+                               (if (oddp nother-words)
+                                 (incf nother-words))
+                               (incf nother-words 2))))
+            (:single-float (incf nfpr-args)
+                           (if (<= nfpr-args 8)
+                             (incf nsingle-floats)
+                             (incf nother-words)))
+	    ((:signed-doubleword :unsigned-doubleword)
+	     (if (oddp ngpr-args)
+	       (incf ngpr-args))
+	     (incf ngpr-args 2)
+	     (when (> ngpr-args 8)
+	       (if (oddp nother-words)
+		 (incf nother-words))
+	       (incf nother-words 2)))
+            ((:signed-byte :unsigned-byte :signed-halfword :unsigned-halfword
+                           :signed-fullword :unsigned-fullword :address)
+	     (incf ngpr-args)
+             (if (> ngpr-args 8)
+               (incf nother-words)))))
+        (let* ((single-words (+ 8 nother-words nsingle-floats))
+               (total-words (if (zerop ndouble-floats)
+                              single-words
+                              (+ (the fixnum (+ ndouble-floats ndouble-floats))
+                                 (the fixnum (logand (lognot 1)
+                                                     (the fixnum (1+ single-words))))))))
+          (declare (fixnum total-words single-words))
+          (%stack-block
+              ((buf (ash total-words 2)))
+            (setq single-float-offset (+ other-offset nother-words))
+            (setq double-float-offset
+                  (logand (lognot 1)
+                          (the fixnum (1+ (the fixnum (+ single-float-offset nsingle-floats))))))
+           ;;; Make another pass through the arg/value pairs, evaluating each arg into
+           ;;; the buffer.
+            (do* ((i 0 (1+ i))
+                  (specs specs-and-vals (cddr specs))
+                  (spec (car specs) (car specs))
+                  (val (cadr specs) (cadr specs))
+                  (ngpr 0)
+                  (nfpr 0)
+                  (gpr-byte-offset 0)
+                  (other-byte-offset (ash other-offset 2))
+                  (single-byte-offset (ash single-float-offset 2))
+                  (double-byte-offset (ash double-float-offset 2)))
+                 ((= i nargs))
+              (declare (fixnum i gpr-byte-offset single-byte-offset double-byte-offset
+                               ngpr nfpr))
+              (case spec
+                (:double-float
+                 (cond ((< nfpr 8)
+                        (setf (uvref fpr-reloads nfpr) 2
+                              (%get-double-float buf double-byte-offset) val
+                              double-byte-offset (+ double-byte-offset 8)))
+                       (t
+                        (setq other-byte-offset (logand (lognot 7)
+                                                        (the fixnum (+ other-byte-offset 4))))
+                        (setf (%get-double-float buf other-byte-offset) val)
+                        (setq other-byte-offset (+ other-byte-offset 8))))
+                 (incf nfpr))
+                (:single-float
+                 (cond ((< nfpr 8)
+                        (setf (uvref fpr-reloads nfpr) 1
+                              (%get-single-float buf single-byte-offset) val
+                              single-byte-offset (+ single-byte-offset 4)))
+                             
+                       (t
+                        (setf (%get-single-float buf other-byte-offset) val
+                              other-byte-offset (+ other-byte-offset 4))))
+                 (incf nfpr))
+                (:address
+                 (cond ((< ngpr 8)
+                        (setf (%get-ptr buf gpr-byte-offset) val
+                              gpr-byte-offset (+ gpr-byte-offset 4)))
+                       (t
+                        (setf (%get-ptr buf other-byte-offset) val
+                              other-byte-offset (+ other-byte-offset 4))))
+                 (incf ngpr))
+                ((:signed-doubleword :unsigned-doubleword)
+                 (when (oddp ngpr)
+                   (incf ngpr)
+                   (incf gpr-byte-offset 4))
+                 (cond ((< ngpr 8)
+                        (if (eq spec :signed-doubleword)
+                          (setf (%get-signed-long-long buf gpr-byte-offset) val)
+                          (setf (%get-unsigned-long-long buf gpr-byte-offset) val))
+                        (incf gpr-byte-offset 8))
+                       (t
+                        (when (logtest other-byte-offset 7)
+                          (incf other-byte-offset 4))
+                        (if (eq spec :signed-doubleword)
+                          (setf (%get-signed-long-long buf other-byte-offset) val)
+                          (setf (%get-unsigned-long-long buf other-byte-offset) val))
+                        (incf other-byte-offset 8)))
+                 (incf ngpr 2))
+		((:unsigned-byte :unsigned-halfword :unsigned-fullword)
+                 (cond ((< ngpr 8)
+                        (setf (%get-unsigned-long buf gpr-byte-offset) val
+                              gpr-byte-offset (+ gpr-byte-offset 4)))
+                       (t
+                        (setf (%get-unsigned-long buf other-byte-offset) val
+                              other-byte-offset (+ other-byte-offset 4))))
+		 (incf ngpr))
+                (t
+                 (cond ((< ngpr 8)
+                        (setf (%get-long buf gpr-byte-offset) val
+                              gpr-byte-offset (+ gpr-byte-offset 4)))
+                       (t
+                        (setf (%get-long buf other-byte-offset) val
+                              other-byte-offset (+ other-byte-offset 4))))
+                 (incf ngpr))))
+            (%%ff-call fpr-reloads
+                       single-float-offset
+                       double-float-offset
+                       (the fixnum (-
+                                    (ash (the fixnum
+                                           (+ 6
+                                              (the fixnum (logand
+                                                           (lognot 1)
+                                                           (the fixnum (1+ total-words))))))
+                                         2)))
+                       buf
+                       entry)
+            (ecase result-spec
+              (:void nil)
+              (:single-float (%get-single-float buf 8))
+              (:double-float (%get-double-float buf 16))
+              (:address (%get-ptr buf))
+              (:signed-doubleword (%get-signed-long-long buf 0))
+              (:unsigned-doubleword (%get-unsigned-long-long buf 0))
+              (:signed-fullword (%get-signed-long buf))
+              (:unsigned-fullword (%get-unsigned-long buf))
+              (:signed-halfword (%get-signed-word buf 2))
+              (:unsigned-halfword (%get-unsigned-word buf 2))
+              (:signed-byte (%get-signed-byte buf 3))
+              (:unsigned-byte (%get-unsigned-byte buf 3))))))))
+  )
+
+
+
+
+
+;;; In the PowerOpen ABI, all arguments are passed in a contiguous
+;;; block.  The first 13 (!) FP args are passed in FP regs; doubleword
+;;; arguments are aligned on word boundaries.
+#+poweropen-target
+(progn
+  #+ppc32-target
+  (progn
+    (defun %ff-call (entry &rest specs-and-vals)
+      (declare (dynamic-extent specs-and-vals))
+      (let* ((len (length specs-and-vals))
+             (total-words 0))
+        (declare (fixnum len total-words))
+        (unless (oddp len)
+          (error "Length of ~s is even.  Missing result ?" specs-and-vals))
+        (let* ((result-spec (or (car (last specs-and-vals)) :void))
+               (nargs (ash (the fixnum (1- len)) -1))
+               (fpr-reload-sizes (make-array 13 :element-type '(unsigned-byte 8)))
+               (fpr-reload-offsets (make-array 13 :element-type '(unsigned-byte 16))))
+          (declare (fixnum nargs) (dynamic-extent fpr-reload-sizes fpr-reload-offsets))
+          (do* ((i 0 (1+ i))
+                (specs specs-and-vals (cddr specs))
+                (spec (car specs) (car specs)))
+               ((= i nargs))
+            (declare (fixnum i))
+            (case spec
+              ((:double-float :signed-doubleword :unsigned-doubleword)
+               (incf total-words 2))
+              ((:single-float :signed-byte :unsigned-byte :signed-halfword
+                              :unsigned-halfword :signed-fullword
+                              :unsigned-fullword :address)
+               (incf total-words))
+              (t (if (typep spec 'unsigned-byte)
+                   (incf total-words spec)
+                   (error "Invalid argument spec ~s" spec)))))
+          (%stack-block ((buf (ash (logand (lognot 1) (1+ (max 6  total-words))) 2)))
+            (do* ((i 0 (1+ i))
+                  (fpr 0)
+                  (offset 0 (+ offset 4))
+                  (specs specs-and-vals (cddr specs))
+                  (spec (car specs) (car specs))
+                  (val (cadr specs) (cadr specs)))
+                 ((= i nargs))
+              (declare (fixnum i offset fpr))
+              (case spec
+                (:double-float
+                 (when (< fpr 13)
+                   (setf (uvref fpr-reload-sizes fpr) 2
+                         (uvref fpr-reload-offsets fpr) offset))
+                 (incf fpr)
+                 (setf (%get-double-float buf offset) val)
+                 (incf offset 4))
+                (:single-float
+                 (when (< fpr 13)
+                   (setf (uvref fpr-reload-sizes fpr) 1
+                         (uvref fpr-reload-offsets fpr) offset))
+                 (incf fpr)
+                 (setf (%get-single-float buf offset) val))
+                (:signed-doubleword
+                 (setf (%get-signed-long-long buf offset) val)
+                 (incf offset 4))
+                (:unsigned-doubleword
+                 (setf (%get-unsigned-long-long buf offset) val)
+                 (incf offset 4))
+                (:address
+                 (setf (%get-ptr buf offset) val))
+		((:unsigned-byte :unsigned-halfword :unsigned-fullword)
+		 (setf (%get-unsigned-long buf offset) val))
+                (t
+                 (if (typep spec 'unsigned-byte)
+                   (dotimes (i spec (decf offset 4))
+                     (setf (%get-ptr buf offset)
+                           (%get-ptr val (* i 4)))
+                     (incf offset 4))
+                   (setf (%get-long buf offset) val)))))
+            (let* ((frame-size (if (<= total-words 8)
+                                 (ash
+                                  (+ ppc32::c-frame.size ppc32::lisp-frame.size)
+                                  -2)
+                                 (+
+                                  (ash
+                                   (+ ppc32::c-frame.size ppc32::lisp-frame.size)
+                                   -2)
+                                  (logand (lognot 1)
+                                          (1+ (- total-words 8)))))))
+              
+              (%%ff-call
+               fpr-reload-sizes
+               fpr-reload-offsets
+               (- (logandc2 (+ frame-size 3) 3))
+               total-words
+               buf
+               entry))
+            (ecase result-spec
+              (:void nil)
+              (:single-float (%get-single-float buf 8))
+              (:double-float (%get-double-float buf 16))
+              (:address (%get-ptr buf))
+              (:signed-doubleword (%get-signed-long-long buf 0))
+              (:unsigned-doubleword (%get-unsigned-long-long buf 0))
+              (:signed-fullword (%get-signed-long buf))
+              (:unsigned-fullword (%get-unsigned-long buf))
+              (:signed-halfword (%get-signed-word buf 2))
+              (:unsigned-halfword (%get-unsigned-word buf 2))
+              (:signed-byte (%get-signed-byte buf 3))
+              (:unsigned-byte (%get-unsigned-byte buf 3)))))))
+
+
+    (defppclapfunction %%ff-call ((reload-sizes 8)
+                                  (reload-offsets 4)
+                                  (frame-size 0)			     
+                                  (total-words arg_x)
+                                  (buf arg_y)
+                                  (entry arg_z))
+      (check-nargs 6)
+      (la imm0 12 vsp)
+      (save-lisp-context imm0)
+      (lwz imm0 frame-size vsp)
+      (stwux sp sp imm0)
+      (stw sp ppc32::c-frame.savelr sp)
+      (macptr-ptr imm2 buf)
+      (mr imm1 imm2)
+      (la imm3 ppc32::c-frame.param0 sp)
+      (li temp1 0)
+      @copy
+      (addi temp1 temp1 '1)
+      (cmpw temp1 total-words)
+      (lwz imm0 0 imm2)
+      (la imm2 4 imm2)
+      (stw imm0 0 imm3)
+      (la imm3 4 imm3)
+      (blt @copy)
+      (lwz temp0 reload-sizes vsp)
+      (lwz temp1 reload-offsets vsp)
+      @load-fp1
+      (lbz imm0 (+ ppc32::misc-data-offset 0) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 0) temp1)
+      (blt @loaded)
+      (bne @load-fp1-double)
+      (lfsx fp1 imm1 imm2)
+      (b @load-fp2)
+      @load-fp1-double
+      (lfdx fp1 imm1 imm2)
+
+      @load-fp2
+      (lbz imm0 (+ ppc32::misc-data-offset 1) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 2) temp1)
+      (blt @loaded)
+      (bne @load-fp2-double)
+      (lfsx fp2 imm1 imm2)
+      (b @load-fp3)
+      @load-fp2-double
+      (lfdx fp2 imm1 imm2)
+
+      @load-fp3
+      (lbz imm0 (+ ppc32::misc-data-offset 2) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 4) temp1)
+      (blt @loaded)
+      (bne @load-fp3-double)
+      (lfsx fp3 imm1 imm2)
+      (b @load-fp4)
+      @load-fp3-double
+      (lfdx fp3 imm1 imm2)
+
+      @load-fp4
+      (lbz imm0 (+ ppc32::misc-data-offset 3) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 6) temp1)
+      (blt @loaded)
+      (bne @load-fp4-double)
+      (lfsx fp4 imm1 imm2)
+      (b @load-fp5)
+      @load-fp4-double
+      (lfdx fp4 imm1 imm2)
+
+      @load-fp5
+      (lbz imm0 (+ ppc32::misc-data-offset 4) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 8) temp1)
+      (blt @loaded)
+      (bne @load-fp5-double)
+      (lfsx fp5 imm1 imm2)
+      (b @load-fp6)
+      @load-fp5-double
+      (lfdx fp5 imm1 imm2)
+
+      @load-fp6
+      (lbz imm0 (+ ppc32::misc-data-offset 5) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 10) temp1)
+      (blt @loaded)
+      (bne @load-fp1-double)
+      (lfsx fp6 imm1 imm2)
+      (b @load-fp7)
+      @load-fp6-double
+      (lfdx fp6 imm1 imm2)
+
+      @load-fp7
+      (lbz imm0 (+ ppc32::misc-data-offset 6) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 12) temp1)
+      (blt @loaded)
+      (bne @load-fp1-double)
+      (lfsx fp7 imm1 imm2)
+      (b @load-fp8)
+      @load-fp7-double
+      (lfdx fp7 imm1 imm2)
+
+      @load-fp8
+      (lbz imm0 (+ ppc32::misc-data-offset 7) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 14) temp1)
+      (blt @loaded)
+      (bne @load-fp8-double)
+      (lfsx fp8 imm1 imm2)
+      (b @load-fp9)
+      @load-fp8-double
+      (lfdx fp8 imm1 imm2)
+
+      @load-fp9
+      (lbz imm0 (+ ppc32::misc-data-offset 8) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 16) temp1)
+      (blt @loaded)
+      (bne @load-fp9-double)
+      (lfsx fp9 imm1 imm2)
+      (b @load-fp10)
+      @load-fp9-double
+      (lfdx fp9 imm1 imm2)
+
+      @load-fp10
+      (lbz imm0 (+ ppc32::misc-data-offset 9) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 18) temp1)
+      (blt @loaded)
+      (bne @load-fp10-double)
+      (lfsx fp10 imm1 imm2)
+      (b @load-fp11)
+      @load-fp10-double
+      (lfdx fp10 imm1 imm2)
+
+      @load-fp11
+      (lbz imm0 (+ ppc32::misc-data-offset 10) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 20) temp1)
+      (blt @loaded)
+      (bne @load-fp11-double)
+      (lfsx fp11 imm1 imm2)
+      (b @load-fp12)
+      @load-fp11-double
+      (lfdx fp11 imm1 imm2)
+
+      @load-fp12
+      (lbz imm0 (+ ppc32::misc-data-offset 11) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 22) temp1)
+      (blt @loaded)
+      (bne @load-fp12-double)
+      (lfsx fp12 imm1 imm2)
+      (b @load-fp13)
+      @load-fp12-double
+      (lfdx fp12 imm1 imm2)
+
+      @load-fp13
+      (lbz imm0 (+ ppc32::misc-data-offset 12) temp0)
+      (cmpwi imm0 1)
+      (lhz imm2 (+ ppc32::misc-data-offset 24) temp1)
+      (blt @loaded)
+      (bne @load-fp13-double)
+      (lfsx fp13 imm1 imm2)
+      (b @loaded)
+      @load-fp13-double
+      (lfdx fp13 imm1 imm2)
+      @loaded
+      (vpush buf)
+      (bla .SPpoweropen-ffcall)
+      @called
+      (vpop buf)
+      (macptr-ptr imm2 buf)
+      (stw imm0 0 imm2)
+      (stw imm1 4 imm2)
+      (stfs fp1 8 imm2)
+      (stfd fp1 16 imm2)
+      (restore-full-lisp-context)
+      (li arg_z (target-nil-value))
+      (blr))
+    )
+
+  #+ppc64-target
+  (progn
+  ;;; There are a few funky, non-obvious things going on here.
+  ;;; The main %FF-CALL function uses WITH-VARIABLE-C-FRAME;
+  ;;; the compiler will generate code to pop that frame off
+  ;;; of the C/control stack, but the subprim that implements
+  ;;; %ff-call has already popped it off.  To put things back
+  ;;; in balance, the LAP function %%FF-RESULT pushes an
+  ;;; extra frame on the cstack.
+  ;;; %FF-CALL calls %%FF-RESULT to box the result, which may
+  ;;; be in r3/imm0 or in fp1.  It's critical that the call
+  ;;; to %%FF-RESULT not be compiled as "multiple-value returning",
+  ;;; since the MV machinery may clobber IMM0.
+    (defppclapfunction %%ff-result ((spec arg_z))
+      (stdu sp -160 sp)
+      (ld arg_y ':void nfn)
+      (cmpd cr0 spec arg_y)
+      (ld arg_x ':address nfn)
+      (cmpd cr1 spec arg_x)
+      (ld temp3 ':single-float nfn)
+      (cmpd cr2 spec temp3)
+      (ld arg_y ':double-float nfn)
+      (cmpd cr3 spec arg_y)
+      (ld arg_x ':unsigned-doubleword nfn)
+      (cmpd cr4 spec arg_x)
+      (ld temp3 ':signed-doubleword nfn)
+      (cmpd cr5 spec temp3)
+      (beq cr0 @void)
+      (beq cr1 @address)
+      (beq cr2 @single-float)
+      (beq cr3 @double-float)
+      (beq cr4 @unsigned-doubleword)
+      (beq cr5 @signed-doubleword)
+      (box-fixnum arg_z imm0)
+      (blr)
+      @void
+      (li arg_z nil)
+      (blr)
+      @address
+      (li imm1 ppc64::macptr-header)
+      (subi allocptr allocptr (- ppc64::macptr.size ppc64::fulltag-misc))
+      (tdlt allocptr allocbase)
+      (std imm1 ppc64::misc-header-offset allocptr)
+      (mr arg_z allocptr)
+      (clrrdi allocptr allocptr 4)
+      (std imm0 ppc64::macptr.address arg_z)
+      (blr)
+      @single-float
+      (put-single-float fp1 arg_z)
+      (blr)
+      @double-float
+      (li imm1 ppc64::double-float-header)
+      (subi allocptr allocptr (- ppc64::double-float.size ppc64::fulltag-misc))
+      (tdlt allocptr allocbase)
+      (std imm1 ppc64::misc-header-offset allocptr)
+      (mr arg_z allocptr)
+      (clrrdi allocptr allocptr 4)
+      (stfd fp1 ppc64::macptr.address arg_z)
+      (blr)
+      @unsigned-doubleword
+      (ba .SPmakeu64)
+      @signed-doubleword
+      (ba .SPmakes64))
+
+  ;;; This is just here so that we can jump to a subprim from lisp.
+    (defppclapfunction %do-ff-call ((regbuf arg_y) (entry arg_z))
+      (cmpdi cr0 regbuf nil)
+      (bnea cr0 .SPpoweropen-ffcall-return-registers)
+      (ba .SPpoweropen-ffcall))
+  
+    (defun %ff-call (entry &rest specs-and-vals)
+      (declare (dynamic-extent specs-and-vals))
+      (let* ((len (length specs-and-vals))
+             (total-words 0)
+             (registers nil))
+        (declare (fixnum len total-words))
+        (let* ((result-spec (or (car (last specs-and-vals)) :void))
+               (nargs (ash (the fixnum (1- len)) -1)))
+          (declare (fixnum nargs))
+          (ecase result-spec
+            ((:address :unsigned-doubleword :signed-doubleword
+                       :single-float :double-float
+                       :signed-fullword :unsigned-fullword
+                       :signed-halfword :unsigned-halfword
+                       :signed-byte :unsigned-byte
+                       :void)
+             (do* ((i 0 (1+ i))
+                   (specs specs-and-vals (cddr specs))
+                   (spec (car specs) (car specs)))
+                  ((= i nargs))
+               (declare (fixnum i))
+               (case spec
+                 (:registers nil)
+                 ((:address :unsigned-doubleword :signed-doubleword
+                            :single-float :double-float
+                            :signed-fullword :unsigned-fullword
+                            :signed-halfword :unsigned-halfword
+                            :signed-byte :unsigned-byte
+                            :hybrid-int-float :hybrid-float-float
+                            :hybrid-float-int)
+                  (incf total-words))
+                 (t (if (typep spec 'unsigned-byte)
+                      (incf total-words spec)
+                      (error "unknown arg spec ~s" spec)))))
+             (%stack-block ((fp-args (* 13 8)))
+               (with-variable-c-frame
+                   total-words frame
+                   (with-macptrs ((argptr))
+                     (%setf-macptr-to-object argptr frame)
+                     (let* ((offset ppc64::c-frame.param0)
+                            (n-fp-args 0))
+                       (declare (fixnum offset n-fp-args))
+                       (do* ((i 0 (1+ i))
+                             (specs specs-and-vals (cddr specs))
+                             (spec (car specs) (car specs))
+                             (val (cadr specs) (cadr specs)))
+                            ((= i nargs))
+                         (declare (fixnum i))
+                         (case spec
+                           (:registers (setq registers val))
+                           (:address (setf (%get-ptr argptr offset) val)
+                                     (incf offset 8))
+                           ((:signed-doubleword :signed-fullword :signed-halfword
+                                                :signed-byte)
+                          
+                            (setf (%%get-signed-longlong argptr offset) val)
+                            (incf offset 8))
+                           ((:unsigned-doubleword :unsigned-fullword :unsigned-halfword
+                                                  :unsigned-byte)
+                            (setf (%%get-unsigned-longlong argptr offset) val)
+                            (incf offset 8))
+                           (:hybrid-int-float
+                            (setf (%%get-unsigned-longlong argptr offset) val)
+                            (when (< n-fp-args 13)
+                              (setf (%get-double-float fp-args (* n-fp-args 8))
+                                    (%double-float (%get-single-float argptr (+ offset 4)))))
+                            (incf n-fp-args)
+                            (incf offset 8))
+                           (:hybrid-float-int
+                            (setf (%%get-unsigned-longlong argptr offset) val)
+                            (when (< n-fp-args 13)
+                              (setf (%get-double-float fp-args (* n-fp-args 8))
+                                    (%double-float (%get-single-float argptr offset))))
+                            (incf n-fp-args)
+                            (incf offset 8))
+                           (:hybrid-float-float
+                            (setf (%%get-unsigned-longlong argptr offset) val)
+                            (when (< n-fp-args 13)
+                              (setf (%get-double-float fp-args (* n-fp-args 8))
+                                    (%double-float (%get-single-float argptr offset))))
+                            (incf n-fp-args)
+                            (when (< n-fp-args 13)
+                              (setf (%get-double-float fp-args (* n-fp-args 8))
+                                    (%double-float (%get-single-float argptr (+ offset 4)))))
+                            (incf n-fp-args)
+                            (incf offset 8))
+                           (:double-float
+                            (setf (%get-double-float argptr offset) val)
+                            (when (< n-fp-args 13)
+                              (setf (%get-double-float fp-args (* n-fp-args 8)) val))
+                            (incf n-fp-args)
+                            (incf offset 8))
+                           (:single-float
+                            (setf (%get-single-float argptr offset) val)
+                            (when (< n-fp-args 13)
+                              (setf (%get-double-float fp-args (* n-fp-args 8))
+                                    (%double-float val)))
+                            (incf n-fp-args)
+                            (incf offset 8))
+                           (t
+                            (let* ((p 0))
+                              (declare (fixnum p))
+                              (dotimes (i (the fixnum spec))
+                                (setf (%get-ptr argptr offset) (%get-ptr val p))
+                                (incf p 8)
+                                (incf offset 8))))))
+                       (%load-fp-arg-regs n-fp-args fp-args)
+                       (%do-ff-call registers entry)
+                       (values (%%ff-result result-spec)))))))))))
+
+    )
+  )
+
+
+
+(defppclapfunction %get-object ((macptr arg_y) (offset arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= arg_y target::subtag-macptr)
+  (macptr-ptr imm0 arg_y)
+  (trap-unless-lisptag= arg_z target::tag-fixnum imm1)
+  (unbox-fixnum imm1 arg_z)
+  (ldrx arg_z imm0 imm1)
+  (blr))
+
+
+(defppclapfunction %set-object ((macptr arg_x) (offset arg_y) (value arg_z))
+  (check-nargs 3)
+  (trap-unless-typecode= arg_x target::subtag-macptr)
+  (macptr-ptr imm0 arg_x)
+  (trap-unless-lisptag= arg_y target::tag-fixnum imm1)
+  (unbox-fixnum imm1 arg_y)
+  (strx arg_z imm0 imm1)
+  (blr))
+
+
+(defppclapfunction %apply-lexpr-with-method-context ((magic arg_x)
+                                                     (function arg_y)
+                                                     (args arg_z))
+  ;; Somebody's called (or tail-called) us.
+  ;; Put magic arg in ppc::next-method-context (= ppc::temp1).
+  ;; Put function in ppc::nfn (= ppc::temp2).
+  ;; Set nargs to 0, then spread "args" on stack (clobbers arg_x, arg_y, arg_z,
+  ;;   but preserves ppc::nfn/ppc::next-method-context.
+  ;; Jump to the function in ppc::nfn.
+  (mr ppc::next-method-context magic)
+  (mr ppc::nfn function)
+  (set-nargs 0)
+  (mflr loc-pc)
+  (bla .SPspread-lexpr-z)
+  (mtlr loc-pc)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+
+
+(defppclapfunction %apply-with-method-context ((magic arg_x)
+                                               (function arg_y)
+                                               (args arg_z))
+  ;; Somebody's called (or tail-called) us.
+  ;; Put magic arg in ppc::next-method-context (= ppc::temp1).
+  ;; Put function in ppc::nfn (= ppc::temp2).
+  ;; Set nargs to 0, then spread "args" on stack (clobbers arg_x, arg_y, arg_z,
+  ;;   but preserves ppc::nfn/ppc::next-method-context.
+  ;; Jump to the function in ppc::nfn.
+  (mr ppc::next-method-context magic)
+  (mr ppc::nfn function)
+  (set-nargs 0)
+  (mflr loc-pc)
+  (bla .SPspreadargZ)
+  (mtlr loc-pc)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (bctr))
+
+
+
+
+(defppclapfunction %apply-lexpr-tail-wise ((method arg_y) (args arg_z))
+  ;; This assumes
+  ;; a) that "args" is a lexpr made via the .SPlexpr-entry mechanism
+  ;; b) That the LR on entry to this function points to the lexpr-cleanup
+  ;;    code that .SPlexpr-entry set up
+  ;; c) That there weren't any required args to the lexpr, e.g. that
+  ;;    (%lexpr-ref args (%lexpr-count args) 0) was the first arg to the gf.
+  ;; The lexpr-cleanup code will be EQ to either (lisp-global ret1valaddr)
+  ;; or (lisp-global lexpr-return1v).  In the former case, discard a frame
+  ;; from the cstack (multiple-value tossing).  Restore FN and LR from
+  ;; the first frame that .SPlexpr-entry pushed, restore vsp from (+
+  ;; args node-size), pop the argregs, and jump to the function.
+  (mflr loc-pc)
+  (ref-global imm0 ret1valaddr)
+  (cmpr cr2 loc-pc imm0)
+  (ldr nargs 0 args)
+  (mr imm5 nargs)
+  (cmpri cr0 nargs 0)
+  (cmpri cr1 nargs '2)
+  (mr nfn method)
+  (ldr temp0 target::misc-data-offset nfn)
+  (mtctr temp0)
+  (if (:cr2 :eq)
+    (la sp target::lisp-frame.size sp))
+  (ldr loc-pc target::lisp-frame.savelr sp)
+  (ldr fn target::lisp-frame.savefn sp)
+  (ldr imm0 target::lisp-frame.savevsp sp)
+  (sub vsp imm0 nargs)
+  (mtlr loc-pc)
+  (la sp target::lisp-frame.size sp)
+  (beqctr)
+  (vpop arg_z)
+  (bltctr cr1)
+  (vpop arg_y)
+  (beqctr cr1)
+  (vpop arg_x)
+  (bctr))
+
+
+(defun %copy-function (proto &optional target)
+  (let* ((total-size (uvsize proto))
+         (new (or target (allocate-typed-vector :function total-size))))
+    (declare (fixnum total-size))
+    (when target
+      (unless (eql total-size (uvsize target))
+        (error "Wrong size target ~s" target)))
+    (%copy-gvector-to-gvector proto 0 new 0 total-size)
+    new))
+
+(defun replace-function-code (target-fn proto-fn)
+  (if (typep target-fn 'function)
+    (if (typep proto-fn 'function)
+      (setf (uvref target-fn 0)
+            (uvref proto-fn 0))
+      (report-bad-arg proto-fn 'function))
+    (report-bad-arg target-fn 'function)))
+
+(defun closure-function (fun)
+  (while (and (functionp fun)  (not (compiled-function-p fun)))
+    (setq fun (%svref fun 1))
+    (when (vectorp fun)
+      (setq fun (svref fun 0))))
+  fun)
+
+
+;;; For use by (setf (apply ...) ...)
+;;; (apply+ f butlast last) = (apply f (append butlast (list last)))
+#+ppc-target
+(defun apply+ (&lap function arg1 arg2 &rest other-args)
+  (ppc-lap-function apply+ ()
+   (check-nargs 3 nil)
+   (vpush arg_x)
+   (mr temp0 arg_z)                     ; last
+   (mr arg_z arg_y)                     ; butlast
+   (subi nargs nargs '2)                ; remove count for butlast & last
+   (mflr loc-pc)
+   (bla .SPspreadargz)
+   (cmpri cr0 nargs '3)
+   (mtlr loc-pc)
+   (addi nargs nargs '1)                ; count for last
+   (blt cr0 @nopush)
+   (vpush arg_x)
+@nopush
+   (mr arg_x arg_y)
+   (mr arg_y arg_z)
+   (mr arg_z temp0)
+   (ldr temp0 'funcall nfn)
+   (ba .SPfuncall)))
+
+(lfun-bits #'apply+ (logior $lfbits-rest-bit
+                            (dpb 3 $lfbits-numreq 0)))
+
+;;; end of ppc-def.lisp
Index: /branches/new-random/level-0/PPC/ppc-float.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-float.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-float.lisp	(revision 13309)
@@ -0,0 +1,731 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS")
+  (require :number-case-macro))
+
+
+;;; make a float from hi - high 24 bits mantissa (ignore implied higher bit)
+;;;                   lo -  low 28 bits mantissa
+;;;                   exp  - take low 11 bits
+;;;                   sign - sign(sign) => result
+;;; hi result - 1 bit sign: 11 bits exp: 20 hi bits of hi arg
+;;; lo result - 4 lo bits of hi arg: 28 lo bits of lo arg
+;;; no error checks, no tweaks, no nuthin 
+
+#+ppc32-target
+(defppclapfunction %make-float-from-fixnums ((float 4)(hi 0) (lo arg_x) (exp arg_y) (sign arg_z))
+  (rlwinm imm0 sign 0 0 0)  ; just leave sign bit 
+  (rlwimi imm0 exp (- 20 ppc32::fixnumshift)  1 11) ;  exp left 20 right 2 keep 11 bits
+  (lwz imm1 hi vsp)
+  (srawi imm1 imm1 ppc32::fixnumshift)   ; fold into below? nah keep for later
+  (rlwimi imm0 imm1 (- 32 4) 12 31)   ; right 4 - keep  20 - stuff into hi result
+  (rlwinm imm1 imm1 28 0 3)  ; hi goes left 28 - keep 4 hi bits
+  (rlwimi imm1 lo (- 32 ppc32::fixnumshift) 4 31) ; stuff in 28 bits of lo
+  (lwz temp0 float vsp)         ; the float
+  (stw imm0 ppc32::double-float.value temp0)
+  (stw imm1 ppc32::double-float.val-low temp0)
+  (la vsp 8 vsp)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %make-float-from-fixnums ((float 8)(hi 0) (lo arg_x) (exp arg_y) (sign arg_z))
+  (rlwinm imm0 sign 0 0 0)  ; just leave sign bit 
+  (rlwimi imm0 exp (- 20 ppc64::fixnumshift)  1 11) ;  exp left 20 right 2 keep 11 bits
+  (ld imm1 hi vsp)
+  (srawi imm1 imm1 ppc64::fixnumshift)   ; fold into below? nah keep for later
+  (rlwimi imm0 imm1 (- 32 4) 12 31)   ; right 4 - keep  20 - stuff into hi result
+  (rlwinm imm1 imm1 28 0 3)  ; hi goes left 28 - keep 4 hi bits
+  (rlwimi imm1 lo (- 32 ppc64::fixnumshift) 4 31) ; stuff in 28 bits of lo
+  (ld temp0 float vsp)         ; the float
+  (stw imm0 ppc64::double-float.value temp0)
+  (stw imm1 ppc64::double-float.val-low temp0)
+  (la vsp '2 vsp)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %make-short-float-from-fixnums ((float 0) (sig arg_x) (exp arg_y) (sign arg_z))
+  (unbox-fixnum imm0 sig)
+  (rlwimi imm0 exp (- 29 8) 1 8)
+  (inslwi imm0 sign 1 0)
+  (vpop arg_z)
+  (stw imm0 ppc32::single-float.value arg_z)
+  (blr))
+
+
+(defppclapfunction %%double-float-abs! ((n arg_y)(val arg_z))
+  (get-double-float fp1 n)
+  (fabs fp1 fp1)
+  (put-double-float fp1 val)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %%short-float-abs! ((n arg_y) (val arg_z))
+  (get-single-float fp1 n)
+  (fabs fp0 fp1)
+  (put-single-float fp0 val)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %short-float-abs ((n arg_z))
+  (get-single-float fp1 n)
+  (fabs fp0 fp1)
+  (put-single-float fp0 arg_z)
+  (blr))
+
+(defppclapfunction %double-float-negate! ((src arg_y) (res arg_z))
+  (get-double-float fp0 src)
+  (fneg fp1 fp0)
+  (put-double-float fp1 res)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %short-float-negate! ((src arg_y) (res arg_z))
+  (get-single-float fp0 src)
+  (fneg fp1 fp0)
+  (put-single-float fp1 res)
+  (blr))
+
+#+ppc64-target
+;;; Non-destructive.
+(defppclapfunction %short-float-negate ((src arg_z))
+  (get-single-float fp0 src)
+  (fneg fp1 fp0)
+  (put-single-float fp1 arg_z)
+  (blr))
+
+
+;;; rets hi (25 bits) lo (28 bits) exp sign
+#+ppc32-target
+(defppclapfunction %integer-decode-double-float ((n arg_z))
+  (lwz imm0  ppc32::double-float.value n)
+  (rlwinm imm1 imm0 (+ 1 ppc32::fixnumshift) (- 32 ppc32::fixnumshift 1) ; sign boxed
+          				   (- 32 ppc32::fixnumshift 1))
+  (add imm1 imm1 imm1)  ; imm1 = (fixnum 2) (neg) or 0 (pos)
+  (subfic temp0 imm1 '1)  ; sign boxed
+  (rlwinm. imm2 imm0 (- 32 20)  21  31)   ; right 20, keep 11 bits exp - test for 0
+  ;(subi imm2 imm2 (+ 53 1022))            ; unbias and scale
+  (slwi imm2 imm2 ppc32::fixnumshift)      ; box
+  (mr temp1 imm2)                        ; boxed unbiased exponent
+  (rlwinm imm0 imm0 12  0 19)            ; 20 bits of hi float left 12
+  (beq @denorm)                          ; cr set way back
+  (addi imm0 imm0 1)                     ;  add implied 1
+  @denorm
+  (rlwinm imm0 imm0 (+ (- 32 12) 4 ppc32::fixnumshift) 0 31)
+  (lwz imm1 ppc32::double-float.val-low n) ; 
+  (rlwimi imm0 imm1 (+ 4 ppc32::fixnumshift)
+                    (1+ (- 31 4 ppc32::fixnumshift))
+                    (- 31 ppc32::fixnumshift))  ; high 4 bits in fixnum pos
+  (rlwinm imm1 imm1 (- 4 ppc32::fixnumshift) 
+                    (- 4 ppc32::fixnumshift)
+                    (- 31 ppc32::fixnum-shift)) ; 28 bits  thats 2 2 29
+  (vpush imm0)   ; hi 25 bits of mantissa (includes implied 1)
+  (vpush imm1)   ; lo 28 bits of mantissa
+  (vpush temp1)  ; exp
+  (vpush temp0)  ; sign
+  (set-nargs 4)
+  (la temp0 '4 vsp)
+  (ba .SPvalues))
+
+
+;;; hi is 25 bits lo is 28 bits
+;;; big is 32 lo, 21 hi right justified
+#+ppc32-target
+(defppclapfunction make-big-53 ((hi arg_x)(lo arg_y)(big arg_z))
+  (rlwinm imm0 lo (- 32 ppc32::fixnumshift) 4 31)
+  (rlwimi imm0 hi (- 32 4 ppc32::fixnumshift) 0 3)
+  (stw imm0 (+ ppc32::misc-data-offset 0) big)   ; low goes in 1st wd
+  (rlwinm imm0 hi (- 32 (+ ppc32::fixnumshift 4)) 11 31)  ; high in second
+  (stw imm0 (+ ppc32::misc-data-offset 4) big)
+  (blr))
+
+
+
+(defppclapfunction dfloat-significand-zeros ((dfloat arg_z))
+  (lwz imm1 target::double-float.value dfloat)
+  (rlwinm. imm1 imm1 12 0 19)
+  (cntlzw imm1 imm1)
+  (beq @golo)
+  (box-fixnum arg_z imm1)
+  (blr)
+  @golo
+  (lwz imm1 target::double-float.val-low dfloat)
+  (cntlzw imm1 imm1)
+  (addi imm1 imm1 20)
+  (box-fixnum arg_z imm1)
+  (blr))
+
+(defppclapfunction sfloat-significand-zeros ((sfloat arg_z))
+  #+ppc32-target (lwz imm1 ppc32::single-float.value sfloat)
+  #+ppc64-target (srdi imm1 sfloat 32)
+  (rlwinm imm1 imm1 9 0 22)
+  (cntlzw imm1 imm1)
+  (box-fixnum arg_z imm1)
+  (blr))
+
+
+
+#+ppc32-target
+(defppclapfunction %%scale-dfloat! ((float arg_x)(int arg_y)(result arg_z))
+  (let ((fl.h 8)
+        (fl.l 12)
+        (sc.h 16)
+        (sc.l 20))
+    (clear-fpu-exceptions)
+    (lwz imm0 ppc32::double-float.value float)
+    (lwz imm1 ppc32::double-float.val-low float)
+    (stwu tsp -24 tsp)
+    (stw tsp 4 tsp)
+    (stw imm0 fl.h tsp)
+    (stw imm1 fl.l tsp)
+    (unbox-fixnum imm0 int)
+    ;(addi imm0 imm0 1022)  ; bias exponent - we assume no ovf
+    (slwi imm0 imm0 20)     ; more important - get it in right place
+    (stw imm0 sc.h tsp)
+    (stw rzero sc.l tsp)
+    (lfd fp0 fl.h tsp)
+    (lfd fp1 sc.h tsp)
+    (lwz tsp 0 tsp)
+    (fmul fp2 fp0 fp1)
+    (stfd fp2 ppc32::double-float.value result)
+    (blr)))
+
+#+ppc64-target
+(defppclapfunction %%scale-dfloat! ((float arg_x)(int arg_y)(result arg_z))
+  (let ((fl.h 16)
+        (fl.l 20)
+        (sc.h 24)
+        (sc.l 28))
+    (clear-fpu-exceptions)
+    (lwz imm0 ppc64::double-float.value float)
+    (lwz imm1 ppc64::double-float.val-low float)
+    (stdu tsp -32 tsp)
+    (std tsp 8 tsp)
+    (stw imm0 fl.h tsp)
+    (stw imm1 fl.l tsp)
+    (unbox-fixnum imm0 int)
+    ;(addi imm0 imm0 1022)  ; bias exponent - we assume no ovf
+    (slwi imm0 imm0 20)     ; more important - get it in right place
+    (stw imm0 sc.h tsp)
+    (stw rzero sc.l tsp)
+    (lfd fp0 fl.h tsp)
+    (lfd fp1 sc.h tsp)
+    (la tsp 32 tsp)
+    (fmul fp2 fp0 fp1)
+    (stfd fp2 ppc64::double-float.value result)
+    (blr)))
+
+#+ppc32-target
+(defppclapfunction %%scale-sfloat! ((float arg_x)(int arg_y)(result arg_z))
+  (let ((sc.h 12))
+    (clear-fpu-exceptions)
+    (lfs fp0 ppc32::single-float.value float)
+    (unbox-fixnum imm0 int)
+    (slwi imm0 imm0 IEEE-single-float-exponent-offset)
+    (stwu tsp -16 tsp)
+    (stw tsp 4 tsp)
+    (stw imm0 sc.h tsp)
+    (lfs fp1 sc.h tsp)
+    (lwz tsp 0 tsp)
+    (fmuls fp2 fp0 fp1)
+    (stfs fp2 ppc32::single-float.value result)
+    (blr)))
+                   
+
+#+ppc64-target
+(defppclapfunction %%scale-sfloat! ((float arg_y)(int arg_z))
+  (let ((sc.h 16))
+    (clear-fpu-exceptions)
+    (get-single-float fp0 float)
+    (unbox-fixnum imm0 int)
+    (slwi imm0 imm0 IEEE-single-float-exponent-offset)
+    (stwu tsp -32 tsp)
+    (stw tsp 8 tsp)
+    (stw imm0 sc.h tsp)
+    (lfs fp1 sc.h tsp)
+    (la tsp 32 tsp)
+    (fmuls fp2 fp0 fp1)
+    (put-single-float fp2 arg_z)
+    (blr)))
+
+(defppclapfunction %copy-double-float ((f1 arg_y) (f2 arg_z))
+  (lfd fp0 target::double-float.value f1)
+  (stfd fp0 target::double-float.value f2)
+  (blr))
+                   
+
+#+ppc32-target
+(defppclapfunction %copy-short-float ((f1 arg_y) (f2 arg_z))
+  (lfs fp0 ppc32::single-float.value f1)
+  (stfs fp0 ppc32::single-float.value f2)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %double-float-exp ((n arg_z))
+  (lwz imm1 target::double-float.value n)
+  (rlwinm arg_z imm1 (- 32 (- 20 target::fixnumshift)) 19  29) ; right 20 left 2 = right 18 = left 14
+  (blr))
+
+
+
+#+ppc32-target
+(defppclapfunction set-%double-float-exp ((float arg_y) (exp arg_z))
+  (lwz imm1 target::double-float.value float)
+  (rlwimi imm1 exp (- 20 target::fixnumshift) 1 11)
+  (stw imm1 target::double-float.value float) ; hdr - tag = 8 - 2
+  (blr))
+
+
+
+#+ppc32-target
+(defppclapfunction %short-float-exp ((n arg_z))
+  (lwz imm1 ppc32::single-float.value n)
+  (rlwinm arg_z imm1 (- 32 (- 23 ppc32::fixnumshift)) 22 29)
+  (blr))
+
+
+
+#+ppc32-target
+(defppclapfunction set-%short-float-exp ((float arg_y) (exp arg_z))
+  (lwz imm1 ppc32::single-float.value float)
+  (rlwimi imm1 exp (- 23 ppc32::fixnumshift) 1 8)
+  (stw imm1 ppc32::single-float.value float)
+  (blr))
+
+  
+(defppclapfunction %short-float->double-float ((src arg_y) (result arg_z))
+  (get-single-float fp0 src)
+  (put-double-float fp0 result)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %double-float->short-float ((src arg_y) (result arg_z))
+  ;(clear-fpu-exceptions)
+  (get-double-float fp0 src)
+  (frsp fp1 fp0)
+  (put-single-float fp1 result)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %double-float->short-float ((src arg_z))
+  ;(clear-fpu-exceptions)
+  (get-double-float fp0 src)
+  (frsp fp1 fp0)
+  (put-single-float fp1 arg_z)
+  (blr))
+  
+
+
+#+ppc32-target
+(defppclapfunction %int-to-sfloat! ((int arg_y) (sfloat arg_z))
+  (int-to-freg int fp0 imm0)
+  (frsp fp1 fp0)
+  (stfs fp1 ppc32::single-float.value sfloat)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %int-to-sfloat ((int arg_z))
+  (int-to-freg int fp0 imm0)
+  (frsp fp1 fp0)
+  (stfs fp1 ppc64::tcr.single-float-convert ppc64::rcontext)
+  (ld arg_z ppc64::tcr.single-float-convert ppc64::rcontext)
+  (blr))
+  
+
+(defppclapfunction %int-to-dfloat ((int arg_y) (dfloat arg_z))
+  (int-to-freg int fp0 imm0)
+  (stfd fp0 target::double-float.value dfloat)
+  (blr))
+
+
+
+
+; Manipulating the FPSCR.
+; This  returns the bottom 8 bits of the FPSCR
+(defppclapfunction %get-fpscr-control ()
+  (mffs fp0)
+  (stfd fp0 target::tcr.lisp-fpscr-high target::rcontext)
+  (lbz imm0 (+ target::tcr.lisp-fpscr-high 7) target::rcontext)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+; Returns the high 24 bits of the FPSCR
+(defppclapfunction %get-fpscr-status ()
+  (mffs fp0)
+  (stfd fp0 target::tcr.lisp-fpscr-high target::rcontext)
+  (lwz imm0 target::tcr.lisp-fpscr-low tsp)
+  (clrrwi imm0 imm0 8)
+  (srwi arg_z imm0 (- 8 target::fixnumshift))
+  (blr))
+
+; Set the high 24 bits of the FPSCR; leave the low 8 unchanged
+(defppclapfunction %set-fpscr-status ((new arg_z))
+  (slwi imm0 new (- 8 target::fixnumshift))
+  (stw imm0 target::tcr.lisp-fpscr-low target::rcontext)
+  (lfd fp0 target::tcr.lisp-fpscr-high target::rcontext)
+  (mtfsf #xfc fp0)                      ; set status fields [0-5]
+  (blr))
+
+; Set the low 8 bits of the FPSCR.  Zero the upper 24 bits
+(defppclapfunction %set-fpscr-control ((new arg_z))
+  (unbox-fixnum imm0 new)
+  (clrlwi imm0 imm0 24)                 ; ensure that "status" fields are clear
+  (stw imm0 target::tcr.lisp-fpscr-low target::rcontext)
+  (lfd fp0 target::tcr.lisp-fpscr-high target::rcontext)
+  (mtfsf #xff fp0)                      ; set all fields [0-7]
+  (blr))
+
+
+(defppclapfunction %ffi-exception-status ()
+  (ldr imm0  target::tcr.ffi-exception target::rcontext)
+  (mtcrf #xfc imm0)
+  (mcrfs :cr6 :cr6)
+  (mcrfs :cr7 :cr7)
+  (crand ppc::fpscr-fex-bit ppc::fpscr-oe-bit ppc::fpscr-ox-bit)
+  (bt ppc::fpscr-fex-bit @set)
+  (crand ppc::fpscr-fex-bit ppc::fpscr-ve-bit ppc::fpscr-vx-bit)
+  (bt ppc::fpscr-fex-bit @set)
+  (crand ppc::fpscr-fex-bit ppc::fpscr-ue-bit ppc::fpscr-ux-bit)
+  (bt ppc::fpscr-fex-bit @set)
+  (crand ppc::fpscr-fex-bit ppc::fpscr-ze-bit ppc::fpscr-zx-bit)
+  (bt ppc::fpscr-fex-bit @set)
+  (crand ppc::fpscr-fex-bit ppc::fpscr-xe-bit ppc::fpscr-xx-bit)
+  (bf ppc::fpscr-fex-bit @ret)
+  @set
+  (oris imm0 imm0 #xc000)
+  @ret
+  (srwi arg_z imm0 (- 8 target::fixnumshift))
+  (blr))
+  
+
+; See if the binary double-float operation OP set any enabled
+; exception bits in the fpscr
+(defun %df-check-exception-2 (operation op0 op1 fp-status)
+  (declare (type (unsigned-byte 24) fp-status))
+  (when (logbitp (- 23 ppc::fpscr-fex-bit) fp-status)
+    (%set-fpscr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+			   (%get-fpscr-control)
+			   operation 
+			   (%copy-double-float op0 (%make-dfloat)) 
+			   (%copy-double-float op1 (%make-dfloat)))))
+
+(defun %sf-check-exception-2 (operation op0 op1 fp-status)
+  (declare (type (unsigned-byte 24) fp-status))
+  (when (logbitp (- 23 ppc::fpscr-fex-bit) fp-status)
+    (%set-fpscr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+			   (%get-fpscr-control)
+			   operation
+			   #+ppc32-target
+			   (%copy-short-float op0 (%make-sfloat))
+			   #+ppc64-target op0
+			   #+ppc32-target
+			   (%copy-short-float op1 (%make-sfloat))
+			   #+ppc64-target op1)))
+
+(defun %df-check-exception-1 (operation op0 fp-status)
+  (declare (fixnum fp-status))
+  (when (logbitp (- 23 ppc::fpscr-fex-bit) fp-status)
+    (%set-fpscr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+                              (%get-fpscr-control)
+                              operation 
+                              (%copy-double-float op0 (%make-dfloat)))))
+
+(defun %sf-check-exception-1 (operation op0 fp-status)
+  (declare (type (unsigned-byte 24) fp-status))
+  (when (logbitp (- 23 ppc::fpscr-fex-bit) fp-status)
+    (%set-fpscr-status 0)
+					; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+			   (%get-fpscr-control)
+			   operation
+			   #+ppc32-target
+			   (%copy-short-float op0 (%make-sfloat))
+			   #+ppc64-target op0)))
+
+
+(defun fp-condition-from-fpscr (status-bits control-bits)
+  (declare (fixnum status-bits control-bits))
+  (cond 
+   ((and (logbitp (- 23 ppc::fpscr-vx-bit) status-bits)
+         (logbitp (- 31 ppc::fpscr-ve-bit) control-bits))
+    'floating-point-invalid-operation)
+   ((and (logbitp (- 23 ppc::fpscr-ox-bit) status-bits)
+         (logbitp (- 31 ppc::fpscr-oe-bit) control-bits))
+    'floating-point-overflow)
+   ((and (logbitp (- 23 ppc::fpscr-ux-bit) status-bits)
+         (logbitp (- 31 ppc::fpscr-ue-bit) control-bits))
+    'floating-point-underflow)
+   ((and (logbitp (- 23 ppc::fpscr-zx-bit) status-bits)
+         (logbitp (- 31 ppc::fpscr-ze-bit) control-bits))
+    'division-by-zero)
+   ((and (logbitp (- 23 ppc::fpscr-xx-bit) status-bits)
+         (logbitp (- 31 ppc::fpscr-xe-bit) control-bits))
+    'floating-point-inexact)))
+
+;;; This assumes that the FEX and one of {VX OX UX ZX XX} is set.
+(defun %fp-error-from-status (status-bits control-bits operation &rest operands)
+  (declare (type (unsigned-byte 16) status-bits))
+  (case operation
+    (sqrt (setq operands (cdr operands))))
+  (let* ((condition-class (fp-condition-from-fpscr status-bits control-bits)))
+    (if condition-class
+      (error (make-instance condition-class
+               :operation operation
+               :operands operands)))))
+
+(defun fp-minor-opcode-operation (minor-opcode)
+  (case minor-opcode
+    (25 '*)
+    (18 '/)
+    (20 '-)
+    (21 '+)
+    (22 'sqrt)
+    (t 'unknown)))
+
+;;; Don't we already have about 20 versions of this ?
+(defppclapfunction %double-float-from-macptr! ((ptr arg_x) (byte-offset arg_y) (dest arg_z))
+  (ldr imm0 target::macptr.address ptr)
+  (unbox-fixnum imm1 byte-offset)
+  (lfdx fp1 imm0 imm1)
+  (put-double-float fp1 dest)
+  (blr))
+
+
+(defvar *rounding-mode-alist*
+  '((:nearest . 0) (:zero . 1) (:positive . 2) (:negative . 3)))
+
+(defun get-fpu-mode (&optional (mode nil mode-p))
+  (let* ((flags (%get-fpscr-control)))
+    (declare (type (unsigned-byte 8) flags))
+    (if mode-p
+      (ecase mode
+        (:rounding-mode (car (nth (logand flags 3) *rounding-mode-alist*)))
+        (:overflow (logbitp (- 31 ppc::fpscr-oe-bit) flags))
+        (:underflow (logbitp (- 31 ppc::fpscr-ue-bit) flags))
+        (:division-by-zero (logbitp (- 31 ppc::fpscr-ze-bit) flags))
+        (:invalid (logbitp (- 31 ppc::fpscr-ve-bit) flags))
+        (:inexact (logbitp (- 31 ppc::fpscr-xe-bit) flags)))
+      `(:rounding-mode ,(car (nth (logand flags 3) *rounding-mode-alist*))
+        :overflow ,(logbitp (- 31 ppc::fpscr-oe-bit) flags)
+        :underflow ,(logbitp (- 31 ppc::fpscr-ue-bit) flags)
+        :division-by-zero ,(logbitp (- 31 ppc::fpscr-ze-bit) flags)
+        :invalid ,(logbitp (- 31 ppc::fpscr-ve-bit) flags)
+        :inexact ,(logbitp (- 31 ppc::fpscr-xe-bit) flags)))))
+
+;;; did we document this?
+(defun set-fpu-mode (&key (rounding-mode :nearest rounding-p)
+                          (overflow t overflow-p)
+                          (underflow t underflow-p)
+                          (division-by-zero t zero-p)
+                          (invalid t invalid-p)
+                          (inexact t inexact-p))
+  (let* ((mask (logior (if rounding-p #x03 #x00)
+                       (if invalid-p
+                         (ash 1 (- 31 ppc::fpscr-ve-bit))
+                         #x00)
+                       (if overflow-p
+                         (ash 1 (- 31 ppc::fpscr-oe-bit))
+                         #x00)
+                       (if underflow-p
+                         (ash 1 (- 31 ppc::fpscr-ue-bit))
+                         #x00)
+                       (if zero-p
+                         (ash 1 (- 31 ppc::fpscr-ze-bit))
+                         #x00)
+                       (if inexact-p
+                         (ash 1 (- 31 ppc::fpscr-xe-bit))
+                         #x00)))
+         (new (logior (or (cdr (assoc rounding-mode *rounding-mode-alist*))
+                          (error "Unknown rounding mode: ~s" rounding-mode))
+                      (if invalid (ash 1 (- 31 ppc::fpscr-ve-bit)) 0)
+                      (if overflow (ash 1 (- 31 ppc::fpscr-oe-bit)) 0)
+                      (if underflow (ash 1 (- 31 ppc::fpscr-ue-bit))  0)
+                      (if division-by-zero (ash 1 (- 31 ppc::fpscr-ze-bit)) 0)
+                      (if inexact (ash 1 (- 31 ppc::fpscr-xe-bit)) 0))))
+    (declare (type (unsigned-byte 8) new mask))
+    (%set-fpscr-control (logior (logand new mask)
+                                (logandc2 (%get-fpscr-control) mask)))))
+
+
+;;; Copy a single float pointed at by the macptr in single
+;;; to a double float pointed at by the macptr in double
+
+(defppclapfunction %single-float-ptr->double-float-ptr ((single arg_y) (double arg_z))
+  (check-nargs 2)
+  (macptr-ptr imm0 single)
+  (lfs fp0 0 imm0)
+  (macptr-ptr imm0 double)
+  (stfd fp0 0 imm0)
+  (blr))
+
+;;; Copy a double float pointed at by the macptr in double
+;;; to a single float pointed at by the macptr in single.
+(defppclapfunction %double-float-ptr->single-float-ptr ((double arg_y) (single arg_z))
+  (check-nargs 2)
+  (macptr-ptr imm0 double)
+  (lfd fp0 0 imm0)
+  (macptr-ptr imm0 single)
+  (stfs fp0 0 imm0)
+  (blr))
+
+
+(defppclapfunction %set-ieee-single-float-from-double ((src arg_y) (macptr arg_z))
+  (check-nargs 2)
+  (macptr-ptr imm0 macptr)
+  (get-double-float fp1 src)
+  (stfs fp1 0 imm0)
+  (blr))
+
+#+ppc32-target
+(defun host-single-float-from-unsigned-byte-32 (u32)
+  (let* ((f (%make-sfloat)))
+    (setf (uvref f ppc32::single-float.value-cell) u32)
+    f))
+
+#+ppc64-target
+(defppclapfunction host-single-float-from-unsigned-byte-32 ((u32 arg_z))
+  (sldi arg_z arg_z (- 32 ppc64::fixnumshift))
+  (ori arg_z arg_z ppc64::subtag-single-float)
+  (blr))
+
+
+#+ppc32-target
+(defun single-float-bits (f)
+  (uvref f ppc32::single-float.value-cell))
+
+#+ppc64-target
+(defppclapfunction single-float-bits ((f arg_z))
+  (srdi arg_z f (- 32 ppc64::fixnumshift))
+  (blr))
+
+(defun double-float-bits (f)
+  (values (uvref f target::double-float.value-cell)
+          (uvref f target::double-float.val-low-cell)))
+
+(defun double-float-from-bits (high low)
+  (let* ((f (%make-dfloat)))
+    (setf (uvref f target::double-float.value-cell) high
+          (uvref f target::double-float.val-low-cell) low)
+    f))
+
+(defppclapfunction %double-float-sign ((n arg_z))
+  (lwz imm0 target::double-float.value n)
+  (cmpwi imm0 0)
+  (li arg_z nil)
+  (bgelr)
+  (li arg_z t)
+  (blr))
+
+(defppclapfunction %short-float-sign ((n arg_z))
+  #+ppc32-target (lwz imm0 ppc32::single-float.value n)
+  #+ppc64-target (srdi imm0 n 32)
+  (cmpwi imm0 0)
+  (li arg_z nil)
+  (bgelr)
+  (li arg_z t)
+  (blr))
+
+#+32-bit-target
+(defppclapfunction %single-float-sqrt! ((src arg_y) (dest arg_z))
+  (get-single-float fp1 src)
+  (fsqrts fp2 fp1)
+  (put-single-float fp2 dest)
+  (blr))
+
+#+64-bit-target
+(defppclapfunction %single-float-sqrt ((arg arg_z))
+  (get-single-float fp1 arg)
+  (fsqrts fp2 fp1)
+  (put-single-float fp2 arg_z)
+  (blr))
+
+(defppclapfunction %double-float-sqrt! ((src arg_y) (dest arg_z))
+  (get-double-float fp1 src)
+  (fsqrt fp2 fp1)
+  (put-double-float fp2 dest)
+  (blr))
+
+#+poweropen-target
+(defppclapfunction %get-fp-arg-regs ((ptr arg_z))
+  (macptr-ptr imm0 ptr)
+  (stfd fp1 0 imm0)
+  (stfd fp2 8 imm0)
+  (stfd fp3 16 imm0)
+  (stfd fp4 24 imm0)
+  (stfd fp5 32 imm0)
+  (stfd fp6 40 imm0)
+  (stfd fp7 48 imm0)
+  (stfd fp8 56 imm0)
+  (stfd fp9 64 imm0)
+  (stfd fp10 72 imm0)
+  (stfd fp11 80 imm0)
+  (stfd fp12 88 imm0)
+  (stfd fp13 96 imm0)
+  (blr))
+
+#+poweropen-target
+(defppclapfunction %load-fp-arg-regs ((n arg_y) (ptr arg_z))
+  (cmpdi cr0 n '0)
+  (cmpdi cr1 n '1)
+  (cmpdi cr2 n '2)
+  (cmpdi cr3 n '3)
+  (cmpdi cr4 n '4)
+  (cmpdi cr5 n '5)
+  (cmpdi cr6 n '6)
+  (cmpdi cr7 n '7)
+  (beqlr cr0)
+  (macptr-ptr imm0 ptr)
+  (cmpdi cr0 n '8)
+  (lfd fp1 0 imm0)
+  (beqlr cr1)
+  (cmpdi cr1 n '9)
+  (lfd fp2 8 imm0)
+  (beqlr cr2)
+  (cmpdi cr2 n '10)
+  (lfd fp3 16 imm0)
+  (beqlr cr3)
+  (cmpdi cr3 n '11)
+  (lfd fp4 24 imm0)
+  (beqlr cr4)
+  (cmpdi cr4 n '12)
+  (lfd fp5 32 imm0)
+  (beqlr cr5)
+  (lfd fp6 40 imm0)
+  (beqlr cr6)
+  (lfd fp7 48 imm0)
+  (beqlr cr7)
+  (lfd fp8 56 imm0)
+  (beqlr cr0)
+  (lfd fp9 64 imm0)
+  (beqlr cr1)
+  (lfd fp10 72 imm0)
+  (beqlr cr2)
+  (lfd fp11 80 imm0)
+  (beqlr cr3)
+  (lfd fp12 88 imm0)
+  (beqlr cr4)
+  (lfd fp13 96 imm0)
+  (blr))
Index: /branches/new-random/level-0/PPC/ppc-hash.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-hash.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-hash.lisp	(revision 13309)
@@ -0,0 +1,168 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; level-0;ppc;ppc-hash.lisp
+
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "HASHENV" "ccl:xdump;hashenv"))
+
+
+
+
+;;; This should stay in LAP so that it's fast
+;;; Equivalent to cl:mod when both args are positive fixnums
+(defppclapfunction fast-mod ((number arg_y) (divisor arg_z))
+  #+ppc32-target
+  (progn
+    (divwu imm0 number divisor)
+    (mullw arg_z imm0 divisor))
+  #+ppc64-target
+  (progn
+    (divdu imm0 number divisor)
+    (mulld arg_z imm0 divisor))
+  (subf arg_z arg_z number)
+  (blr))
+
+
+(defppclapfunction fast-mod-3 ((number arg_x) (divisor arg_y) (recip arg_z))
+  #+ppc32-target
+  (progn
+    (srwi imm0 number ppc32::fixnumshift)
+    (mulhw imm1 imm0 recip)
+    (mullw imm0 imm1 divisor))
+  #+ppc64-target
+  (progn
+    (srdi imm0 number ppc64::fixnumshift)
+    (mulhd imm1 imm0 recip)
+    (mulld imm0 imm1 divisor))
+  (sub number number imm0)
+  (sub number number divisor)
+  (srari imm0 number (1- target::nbits-in-word))
+  (and divisor divisor imm0)
+  (add arg_z number divisor)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %dfloat-hash ((key arg_z))
+  (lwz imm0 ppc32::double-float.value key)
+  (lwz imm1 ppc32::double-float.val-low key)
+  (add imm0 imm0 imm1)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %dfloat-hash ((key arg_z))
+  (ld imm0 ppc64::double-float.value key)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %sfloat-hash ((key arg_z))
+  (lwz imm0 ppc32::single-float.value key)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %sfloat-hash ((key arg_z))
+  (lis imm0 #x8000)
+  (srdi imm1 key 32)
+  (cmpw imm0 imm1)
+  (srdi arg_z key (- 32 ppc64::fixnumshift))
+  (bnelr)
+  (li arg_z 0)
+  (blr))
+
+(defppclapfunction %macptr-hash ((key arg_z))
+  (ldr imm0 target::macptr.address key)
+  (slri imm1 imm0 24)
+  (add imm0 imm0 imm1)
+  (clrrri arg_z imm0 target::fixnumshift)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %bignum-hash ((key arg_z))
+  (let ((header imm3)
+        (offset imm2)
+        (ndigits imm1)
+        (immhash imm0))
+    (li immhash 0)
+    (li offset ppc32::misc-data-offset)
+    (getvheader header key)
+    (header-size ndigits header)
+    (let ((next header))
+      @loop
+      (cmpwi cr0 ndigits 1)
+      (subi ndigits ndigits 1)
+      (lwzx next key offset)
+      (addi offset offset 4)
+      (rotlwi immhash immhash 13)
+      (add immhash immhash next)
+      (bne cr0 @loop))
+    (clrrwi arg_z immhash ppc32::fixnumshift)
+    (blr)))
+
+#+ppc64-target
+(defppclapfunction %bignum-hash ((key arg_z))
+  (let ((header imm3)
+        (offset imm2)
+        (ndigits imm1)
+        (immhash imm0))
+    (li immhash 0)
+    (li offset ppc64::misc-data-offset)
+    (getvheader header key)
+    (header-size ndigits header)
+    (let ((next header))
+      @loop
+      (cmpdi cr0 ndigits 1)
+      (subi ndigits ndigits 1)
+      (lwzx next key offset)
+      (rotldi immhash immhash 13)
+      (addi offset offset 4)
+      (add immhash immhash next)
+      (bne cr0 @loop))
+    (clrrdi arg_z immhash ppc64::fixnumshift)
+    (blr)))
+
+
+(defppclapfunction %get-fwdnum ()
+  (ref-global arg_z target::fwdnum)
+  (blr))
+
+
+(defppclapfunction %get-gc-count ()
+  (ref-global arg_z target::gc-count)
+  (blr))
+
+
+;;; Setting a key in a hash-table vector needs to 
+;;; ensure that the vector header gets memoized as well
+(defppclapfunction %set-hash-table-vector-key ((vector arg_x) (index arg_y) (value arg_z))
+  (ba .SPset-hash-key))
+
+(defppclapfunction %set-hash-table-vector-key-conditional ((offset 0) (vector arg_x) (old arg_y) (new arg_z))
+  (ba .SPset-hash-key-conditional))
+
+;;; Strip the tag bits to turn x into a fixnum
+(defppclapfunction strip-tag-to-fixnum ((x arg_z))
+  (unbox-fixnum imm0 x)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+;;; end of ppc-hash.lisp
Index: /branches/new-random/level-0/PPC/ppc-io.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-io.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-io.lisp	(revision 13309)
@@ -0,0 +1,32 @@
+;;; -*- Mode: Lisp; Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+(in-package "CCL")
+
+;;; not very smart yet
+
+(defppclapfunction %get-errno ()
+  (ldr imm1 target::tcr.errno-loc target::rcontext)
+  (lwz imm0 0 imm1)
+  (stw rzero 0 imm1)
+  (neg imm0 imm0)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+; end
Index: /branches/new-random/level-0/PPC/ppc-misc.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-misc.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-misc.lisp	(revision 13309)
@@ -0,0 +1,1066 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; level-0;x86;x86-misc.lisp
+
+
+(in-package "CCL")
+
+;;; Copy N bytes from pointer src, starting at byte offset src-offset,
+;;; to ivector dest, starting at offset dest-offset.
+;;; It's fine to leave this in lap.
+;;; Depending on alignment, it might make sense to move more than
+;;; a byte at a time.
+;;; Does no arg checking of any kind.  Really.
+
+(defppclapfunction %copy-ptr-to-ivector ((src (* 1 target::node-size) )
+                                         (src-byte-offset 0) 
+                                         (dest arg_x)
+                                         (dest-byte-offset arg_y)
+                                         (nbytes arg_z))
+  (let ((src-reg imm0)
+        (src-byteptr imm1)
+        (src-node-reg temp0)
+        (dest-byteptr imm2)
+        (val imm3)
+        (node-temp temp1))
+    (cmpri cr0 nbytes 0)
+    (ldr src-node-reg src vsp)
+    (macptr-ptr src-reg src-node-reg)
+    (ldr src-byteptr src-byte-offset vsp)
+    (unbox-fixnum src-byteptr src-byteptr)
+    (unbox-fixnum dest-byteptr dest-byte-offset)
+    (la dest-byteptr target::misc-data-offset dest-byteptr)
+    (b @test)
+    @loop
+    (subi nbytes nbytes '1)
+    (cmpri cr0 nbytes '0)
+    (lbzx val src-reg src-byteptr)
+    (la src-byteptr 1 src-byteptr)
+    (stbx val dest dest-byteptr)
+    (la dest-byteptr 1 dest-byteptr)
+    @test
+    (bne cr0 @loop)
+    (mr arg_z dest)
+    (la vsp '2 vsp)
+    (blr)))
+
+(defppclapfunction %copy-ivector-to-ptr ((src (* 1 target::node-size))
+                                         (src-byte-offset 0) 
+                                         (dest arg_x)
+                                         (dest-byte-offset arg_y)
+                                         (nbytes arg_z))
+  (ldr temp0 src vsp)
+  (cmpri cr0 nbytes 0)
+  (ldr imm0 src-byte-offset vsp)
+  (unbox-fixnum imm0 imm0)
+  (la imm0 target::misc-data-offset imm0)
+  (unbox-fixnum imm2 dest-byte-offset)
+  (ldr imm1 target::macptr.address dest)
+  (b @test)
+  @loop
+  (subi nbytes nbytes '1)
+  (cmpri cr0 nbytes 0)
+  (lbzx imm3 temp0 imm0)
+  (addi imm0 imm0 1)
+  (stbx imm3 imm1 imm2)
+  (addi imm2 imm2 1)
+  @test
+  (bne cr0 @loop)
+  (mr arg_z dest)
+  (la vsp '2 vsp)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %copy-ivector-to-ivector ((src 4) 
+                                             (src-byte-offset 0) 
+                                             (dest arg_x)
+                                             (dest-byte-offset arg_y)
+                                             (nbytes arg_z))
+  (lwz temp0 src vsp)
+  (cmpwi cr0 nbytes 0)
+  (cmpw cr2 temp0 dest)   ; source and dest same?
+  (rlwinm imm3 nbytes 0 (- 30 target::fixnum-shift) 31)  
+  (lwz imm0 src-byte-offset vsp)
+  (rlwinm imm1 imm0 0 (- 30 target::fixnum-shift) 31)
+  (or imm3 imm3 imm1)
+  (unbox-fixnum imm0 imm0)
+  (la imm0 target::misc-data-offset imm0)
+  (unbox-fixnum imm2 dest-byte-offset)
+  (rlwimi imm1 imm2 0 30 31)
+  (or imm3 imm3 imm1)
+  (cmpwi cr1 imm3 0)  ; is everybody multiple of 4?
+  (la imm2 target::misc-data-offset imm2)
+  (beq cr2 @SisD)   ; source and dest same
+  @fwd
+  (beq :cr1 @wtest)
+  (b @test)
+
+  @loop
+  (subi nbytes nbytes '1)
+  (cmpwi cr0 nbytes 0)
+  (lbzx imm3 temp0 imm0)
+  (addi imm0 imm0 1)
+  (stbx imm3 dest imm2)
+  (addi imm2 imm2 1)
+  @test
+  (bne cr0 @loop)
+  (mr arg_z dest)
+  (la vsp 8 vsp)
+  (blr)
+
+  @words      ; source and dest different - words 
+  (subi nbytes nbytes '4)  
+  (cmpwi cr0 nbytes 0)
+  (lwzx imm3 temp0 imm0)
+  (addi imm0 imm0 4)
+  (stwx imm3 dest imm2)
+  (addi imm2 imm2 4)
+  @wtest
+  (bgt cr0 @words)
+  @done
+  (mr arg_z dest)
+  (la vsp 8 vsp)
+  (blr)
+
+  @SisD
+  (cmpw cr2 imm0 imm2) ; cmp src and dest
+  (bgt cr2 @fwd)
+  ;(B @bwd) 
+  
+
+  ; Copy backwards when src & dest are the same and we're sliding down
+  @bwd ; ok
+  (unbox-fixnum imm3 nbytes)
+  (add imm0 imm0 imm3)
+  (add imm2 imm2 imm3)
+  (b @test2)
+  @loop2
+  (subi nbytes nbytes '1)
+  (cmpwi cr0 nbytes 0)
+  (subi imm0 imm0 1)
+  (lbzx imm3 temp0 imm0)
+  (subi imm2 imm2 1)
+  (stbx imm3 dest imm2)
+  @test2
+  (bne cr0 @loop2)
+  (b @done))
+
+#+ppc64-target
+(defppclapfunction %copy-ivector-to-ivector ((src-offset 8) 
+                                             (src-byte-offset-offset 0) 
+                                             (dest arg_x)
+                                             (dest-byte-offset arg_y)
+                                             (nbytes arg_z))
+  (let ((src temp0)
+        (src-byte-offset imm0))
+    (subi nbytes nbytes '1)
+    (ld src-byte-offset src-byte-offset-offset vsp)
+    (cmpdi nbytes 0 )
+    (ld src src-offset vsp)
+    (la vsp '2 vsp)
+    (cmpd cr1 src dest)
+    (cmpdi cr2 src-byte-offset dest-byte-offset)
+    (unbox-fixnum src-byte-offset src-byte-offset)
+    (unbox-fixnum imm1 dest-byte-offset)
+    (la imm0 target::misc-data-offset src-byte-offset)
+    (la imm1 target::misc-data-offset imm1)
+    (bne cr1 @test)
+    ;; Maybe overlap, or maybe nothing to do.
+    (beq cr2 @done)                       ; same vectors, same offsets
+    (blt cr2 @back)                       ; copy backwards, avoid overlap
+    (b @test)
+    @loop
+    (subi nbytes nbytes '1)
+    (lbzx imm3 src imm0)
+    (cmpdi nbytes 0)
+    (addi imm0 imm0 1)
+    (stbx imm3 dest imm1)
+    (addi imm1 imm1 1)
+    @test
+    (bge @loop)
+    @done
+    (mr arg_z dest)
+    (blr)
+    @back
+    ;; nbytes was predecremented above
+    (unbox-fixnum imm2 nbytes)
+    (add imm0 imm2 imm0)
+    (add imm1 imm2 imm1)
+    (b @back-test)
+    @back-loop
+    (subi nbytes nbytes '1)
+    (lbzx imm3 src imm0)
+    (cmpdi nbytes 0)
+    (subi imm0 imm0 1)
+    (stbx imm3 dest imm1)
+    (subi imm1 imm1 1)
+    @back-test
+    (bge @back-loop)
+    (mr arg_z dest)
+    (blr)))
+  
+
+(defppclapfunction %copy-gvector-to-gvector ((src (* 1 target::node-size))
+					     (src-element 0)
+					     (dest arg_x)
+					     (dest-element arg_y)
+					     (nelements arg_z))
+  (subi nelements nelements '1)
+  (cmpri nelements 0)
+  (ldr imm0 src-element vsp)
+  (ldr temp0 src vsp)
+  (la vsp '2 vsp)
+  (cmpr cr1 temp0 dest)
+  (cmpri cr2 src-element dest-element)
+  (la imm0 target::misc-data-offset imm0)
+  (la imm1 target::misc-data-offset dest-element)
+  (bne cr1 @test)
+  ;; Maybe overlap, or maybe nothing to do.
+  (beq cr2 @done)                       ; same vectors, same offsets
+  (blt cr2 @back)                       ; copy backwards, avoid overlap
+  (b @test)
+  @loop
+  (subi nelements nelements '1)
+  (cmpri nelements 0)
+  (ldrx temp1 temp0 imm0)
+  (addi imm0 imm0 '1)
+  (strx temp1 dest imm1)
+  (addi imm1 imm1 '1)
+  @test
+  (bge @loop)
+  @done
+  (mr arg_z dest)
+  (blr)
+  @back
+  ;; We decremented NELEMENTS by 1 above.
+  (add imm1 nelements imm1)
+  (add imm0 nelements imm0)
+  (b @back-test)
+  @back-loop
+  (subi nelements nelements '1)
+  (cmpri nelements 0)
+  (ldrx temp1 temp0 imm0)
+  (subi imm0 imm0 '1)
+  (strx temp1 dest imm1)
+  (subi imm1 imm1 '1)
+  @back-test
+  (bge @back-loop)
+  (mr arg_z dest)
+  (blr))
+  
+  
+
+
+
+#+ppc32-target
+(defppclapfunction %heap-bytes-allocated ()
+  (lwz imm2 target::tcr.last-allocptr ppc32::rcontext)
+  (cmpwi cr1 imm2 0)
+  (cmpwi allocptr -8)			;void_allocptr
+  (lwz imm0 target::tcr.total-bytes-allocated-high ppc32::rcontext)
+  (lwz imm1 target::tcr.total-bytes-allocated-low ppc32::rcontext)
+  (sub imm2 imm2 allocptr)
+  (beq cr1 @go)
+  (beq @go)
+  (addc imm1 imm1 imm2)
+  (addze imm0 imm0)
+  @go
+  (ba .SPmakeu64))
+
+#+ppc64-target
+(defppclapfunction %heap-bytes-allocated ()
+  (ld imm2 target::tcr.last-allocptr ppc64::rcontext)
+  (cmpri cr1 imm2 0)
+  (cmpri allocptr -16)			;void_allocptr
+  (ld imm0 target::tcr.total-bytes-allocated-high ppc64::rcontext)
+  (sub imm2 imm2 allocptr)
+  (beq cr1 @go)
+  (beq @go)
+  (add imm0 imm0 imm2)
+  @go
+  (ba .SPmakeu64))
+
+
+(defppclapfunction values ()
+  (:arglist (&rest values))
+  (vpush-argregs)
+  (add temp0 nargs vsp)
+  (ba .SPvalues))
+
+;; It would be nice if (%setf-macptr macptr (ash (the fixnum value) ash::fixnumshift))
+;; would do this inline.
+#+ppc-target
+(defppclapfunction %setf-macptr-to-object ((macptr arg_y) (object arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= arg_y target::subtag-macptr)
+  (str arg_z target::macptr.address arg_y)
+  (blr))
+
+(defppclapfunction %fixnum-from-macptr ((macptr arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= arg_z target::subtag-macptr)
+  (ldr imm0 target::macptr.address arg_z)
+  (trap-unless-lisptag= imm0 target::tag-fixnum imm1)
+  (mr arg_z imm0)
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %%get-unsigned-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr ppc32::subtag-macptr)
+  (macptr-ptr imm1 ptr)
+  (unbox-fixnum imm2 offset)
+  (add imm2 imm2 imm1)
+  (lwz imm0 0 imm2)
+  (lwz imm1 4 imm2)
+  (ba .SPmakeu64))
+
+#+ppc64-target
+(defppclapfunction %%get-unsigned-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr ppc64::subtag-macptr)
+  (macptr-ptr imm1 ptr)
+  (unbox-fixnum imm2 offset)
+  (ldx imm0 imm2 imm1)
+  (ba .SPmakeu64))
+
+#+ppc32-target
+(defppclapfunction %%get-signed-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr ppc32::subtag-macptr)
+  (macptr-ptr imm1 ptr)
+  (unbox-fixnum imm2 offset)
+  (add imm2 imm2 imm1)
+  (lwz imm0 0 imm2)
+  (lwz imm1 4 imm2)
+  (ba .SPmakes64))
+
+#+ppc64-target
+(defppclapfunction %%get-signed-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr ppc64::subtag-macptr)
+  (macptr-ptr imm1 ptr)
+  (unbox-fixnum imm2 offset)
+  (ldx imm0 imm2 imm1)
+  (ba .SPmakes64))
+
+#+ppc32-target
+(defppclapfunction %%set-unsigned-longlong ((ptr arg_x)
+					      (offset arg_y)
+					      (val arg_z))
+  (save-lisp-context)
+  (trap-unless-typecode= ptr ppc32::subtag-macptr)
+  (bla .SPgetu64)
+  (macptr-ptr imm2 ptr)
+  (unbox-fixnum imm3 offset)
+  (add imm2 imm3 imm2)
+  (stw imm0 0 imm2)
+  (stw imm1 4 imm2)
+  (ba .SPpopj))
+
+#+ppc64-target
+(defppclapfunction %%set-unsigned-longlong ((ptr arg_x)
+                                            (offset arg_y)
+                                            (val arg_z))
+  (save-lisp-context)
+  (trap-unless-typecode= ptr ppc64::subtag-macptr)
+  (bla .SPgetu64)
+  (macptr-ptr imm2 ptr)
+  (unbox-fixnum imm3 offset)
+  (stdx imm0 imm3 imm2)
+  (ba .SPpopj))
+
+#+ppc32-target
+(defppclapfunction %%set-signed-longlong ((ptr arg_x)
+					    (offset arg_y)
+					    (val arg_z))
+  (save-lisp-context)
+  (trap-unless-typecode= ptr ppc32::subtag-macptr)
+  (bla .SPgets64)
+  (macptr-ptr imm2 ptr)
+  (unbox-fixnum imm3 offset)
+  (add imm2 imm3 imm2)
+  (stw imm0 0 imm2)
+  (stw imm1 4 imm2)
+  (ba .SPpopj))
+
+#+ppc64-target
+(defppclapfunction %%set-signed-longlong ((ptr arg_x)
+                                          (offset arg_y)
+                                          (val arg_z))
+  (save-lisp-context)
+  (trap-unless-typecode= ptr target::subtag-macptr)
+  (bla .SPgets64)
+  (macptr-ptr imm2 ptr)
+  (unbox-fixnum imm3 offset)
+  (stdx imm0 imm3 imm2)
+  (ba .SPpopj))
+
+(defppclapfunction interrupt-level ()
+  (ldr arg_z target::tcr.tlb-pointer target::rcontext)
+  (ldr arg_z target::interrupt-level-binding-index arg_z)
+  (blr))
+
+
+(defppclapfunction disable-lisp-interrupts ()
+  (li imm0 '-1)
+  (ldr imm1 target::tcr.tlb-pointer target::rcontext)
+  (ldr arg_z target::interrupt-level-binding-index imm1)
+  (str imm0 target::interrupt-level-binding-index imm1)
+  (blr))
+
+(defppclapfunction set-interrupt-level ((new arg_z))
+  (ldr imm1 target::tcr.tlb-pointer target::rcontext)
+  (trap-unless-lisptag= new target::tag-fixnum imm0)
+  (str new target::interrupt-level-binding-index imm1)
+  (blr))
+
+;;; If we're restoring the interrupt level to 0 and an interrupt
+;;; was pending, restore the level to 1 and zero the pending status.
+(defppclapfunction restore-interrupt-level ((old arg_z))
+  (cmpri :cr1 old 0)
+  (ldr imm0 target::tcr.interrupt-pending target::rcontext)
+  (ldr imm1 target::tcr.tlb-pointer target::rcontext)
+  (cmpri :cr0 imm0 0)
+  (bne :cr1 @store)
+  (beq :cr0 @store)
+  (str rzero target::tcr.interrupt-pending target::rcontext)
+  (li old '1)
+  @store
+  (str old target::interrupt-level-binding-index imm1)
+  (blr))
+
+
+
+(defppclapfunction %current-tcr ()
+  (mr arg_z target::rcontext)
+  (blr))
+
+(defppclapfunction %tcr-toplevel-function ((tcr arg_z))
+  (check-nargs 1)
+  (cmpr tcr target::rcontext)
+  (mr imm0 vsp)
+  (ldr temp0 target::tcr.vs-area tcr)
+  (ldr imm1 target::area.high temp0)
+  (beq @room)
+  (ldr imm0 target::area.active temp0)
+  @room
+  (cmpr imm1 imm0)
+  (li arg_z nil)
+  (beqlr)
+  (ldr arg_z (- target::node-size) imm1)
+  (blr))
+
+(defppclapfunction %set-tcr-toplevel-function ((tcr arg_y) (fun arg_z))
+  (check-nargs 2)
+  (cmpr tcr target::rcontext)
+  (mr imm0 vsp)
+  (ldr temp0 target::tcr.vs-area tcr)
+  (ldr imm1 target::area.high temp0)
+  (beq @check-room)
+  (ldr imm0 target::area.active temp0)
+  @check-room
+  (cmpr imm1 imm0)
+  (push rzero imm1)
+  (bne @have-room)
+  (str imm1 target::area.active temp0)
+  (str imm1 target::tcr.save-vsp tcr)
+  @have-room
+  (str fun 0 imm1)
+  (blr))
+
+;;; This needs to be done out-of-line, to handle EGC memoization.
+(defppclapfunction %store-node-conditional ((offset 0) (object arg_x) (old arg_y) (new arg_z))
+  (ba .SPstore-node-conditional))
+
+(defppclapfunction %store-immediate-conditional ((offset 0) (object arg_x) (old arg_y) (new arg_z))
+  (vpop temp0)
+  (unbox-fixnum imm0 temp0)
+  (let ((current temp1))
+    @again
+    (lrarx current object imm0)
+    (cmpr current old)
+    (bne @lose)
+    (strcx. new object imm0)
+    (bne @again)
+    (isync)
+    (li arg_z (+ target::t-offset (target-nil-value)))
+    (blr)
+    @lose
+    (li imm0 target::reservation-discharge)
+    (strcx. rzero rzero imm0)
+    (li arg_z nil)
+    (blr)))
+
+(defppclapfunction set-%gcable-macptrs% ((ptr target::arg_z))
+  (li imm0 (+ (target-nil-value) (target::kernel-global gcable-pointers)))
+  @again
+  (lrarx arg_y rzero imm0)
+  (str arg_y target::xmacptr.link ptr)
+  (strcx. ptr rzero imm0)
+  (bne @again)
+  (isync)
+  (blr))
+
+;;; Atomically increment or decrement the gc-inhibit-count kernel-global
+;;; (It's decremented if it's currently negative, incremented otherwise.)
+(defppclapfunction %lock-gc-lock ()
+  (li imm0 (+ (target-nil-value) (target::kernel-global gc-inhibit-count)))
+  @again
+  (lrarx arg_y rzero imm0)
+  (cmpri cr1 arg_y 0)
+  (addi arg_z arg_y '1)
+  (bge cr1 @store)
+  (subi arg_z arg_y '1)
+  @store
+  (strcx. arg_z rzero imm0)
+  (bne @again)
+;;  (isync)
+  (blr))
+
+;;; Atomically decrement or increment the gc-inhibit-count kernel-global
+;;; (It's incremented if it's currently negative, incremented otherwise.)
+;;; If it's incremented from -1 to 0, try to GC (maybe just a little.)
+(defppclapfunction %unlock-gc-lock ()
+;;  (sync)
+  (li imm0 (+ (target-nil-value) (target::kernel-global gc-inhibit-count)))
+  @again
+  (lrarx arg_y rzero imm0)
+  (cmpri cr1 arg_y -1)
+  (subi arg_z arg_y '1)
+  (bgt cr1 @store)
+  (addi arg_z arg_y '1)
+  @store
+  (strcx. arg_z rzero imm0)
+  (bne @again)
+  (bnelr cr1)
+  ;; The GC tried to run while it was inhibited.  Unless something else
+  ;; has just inhibited it, it should be possible to GC now.
+  (li imm0 arch::gc-trap-function-immediate-gc)
+  (trlgei allocptr 0)
+  (blr))
+
+
+
+(defppclapfunction %atomic-incf-node ((by arg_x) (node arg_y) (disp arg_z))
+  (check-nargs 3)
+  (unbox-fixnum imm1 disp)
+  @again
+  (lrarx arg_z node imm1)
+  (add arg_z arg_z by)
+  (strcx. arg_z node imm1)
+  (bne- @again)
+  (isync)
+  (blr))
+
+(defppclapfunction %atomic-incf-ptr ((ptr arg_z))
+  (macptr-ptr imm1 ptr)
+  @again
+  (lrarx imm0 0 imm1)
+  (addi imm0 imm0 1)
+  (strcx. imm0 0 imm1)
+  (bne @again)
+  (isync)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %atomic-incf-ptr-by ((ptr arg_y) (by arg_z))
+  (macptr-ptr imm1 ptr)
+  (unbox-fixnum imm2 by)
+  @again
+  (lrarx imm0 0 imm1)
+  (add imm0 imm0 imm2)
+  (strcx. imm0 0 imm1)
+  (bne @again)
+  (isync)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %atomic-decf-ptr ((ptr arg_z))
+  (macptr-ptr imm1 ptr)
+  @again
+  (lrarx imm0 0 imm1)
+  (subi imm0 imm0 1)
+  (strcx. imm0 0 imm1)
+  (bne @again)
+  (isync)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %atomic-decf-ptr-if-positive ((ptr arg_z))
+  (macptr-ptr imm1 ptr)
+  @again
+  (lrarx imm0 0 imm1)
+  (cmpri cr1 imm0 0)
+  (subi imm0 imm0 1)
+  (beq @done)
+  (strcx. imm0 0 imm1)
+  (bne @again)
+  (isync)
+  (box-fixnum arg_z imm0)
+  (blr)
+  @done
+  (li imm1 target::reservation-discharge)
+  (box-fixnum arg_z imm0)
+  (strcx. rzero rzero imm1)
+  (blr))
+
+(defppclapfunction %atomic-swap-ptr ((ptr arg_y) (newval arg_z))
+  (sync)
+  (macptr-ptr imm1 ptr)
+  (unbox-fixnum imm2 arg_z)
+  @again
+  (lrarx imm0 0 imm1)
+  (strcx. imm2 0 imm1)
+  (bne @again)
+  (isync)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+;;; Try to store the fixnum NEWVAL at PTR, if and only if the old value
+;;; was equal to OLDVAL.  Return the old value
+(defppclapfunction %ptr-store-conditional ((ptr arg_x) (expected-oldval arg_y) (newval arg_z))
+  (macptr-ptr imm0 ptr)
+  (unbox-fixnum imm1 expected-oldval)
+  (unbox-fixnum imm2 newval)
+  @again
+  (lrarx imm3 0 imm0)
+  (cmpr imm3 imm1)
+  (bne- @done)
+  (strcx. imm2 0 imm0)
+  (bne- @again)
+  (isync)
+  (box-fixnum arg_z imm3)
+  (blr)
+  @done
+  (li imm0 target::reservation-discharge)
+  (box-fixnum arg_z imm3)
+  (strcx. rzero 0 imm0)
+  (blr))
+
+(defppclapfunction %ptr-store-fixnum-conditional ((ptr arg_x) (expected-oldval arg_y) (newval arg_z))
+  (let ((address imm0)
+        (actual-oldval imm1))
+    (macptr-ptr address ptr)
+    @again
+    (lrarx actual-oldval 0 address)
+    (cmpr actual-oldval expected-oldval)
+    (bne- @done)
+    (strcx. newval 0 address)
+    (bne- @again)
+    (isync)
+    (mr arg_z actual-oldval)
+    (blr)
+    @done
+    (li address target::reservation-discharge)
+    (mr arg_z actual-oldval)
+    (strcx. rzero 0 address)
+    (blr)))
+
+
+
+
+(defppclapfunction %macptr->dead-macptr ((macptr arg_z))
+  (check-nargs 1)
+  (li imm0 target::subtag-dead-macptr)
+  (stb imm0 target::misc-subtag-offset macptr)
+  (blr))
+
+(defppclapfunction %%apply-in-frame ((catch-count imm0) (srv temp0) (tsp-count imm0) (db-link imm0)
+                                     (parent arg_x) (function arg_y) (arglist arg_z))
+  (check-nargs 7)
+
+  ; Throw through catch-count catch frames
+  (lwz imm0 12 vsp)                      ; catch-count
+  (vpush parent)
+  (vpush function)
+  (vpush arglist)
+  (bla .SPnthrowvalues)
+
+  ; Pop tsp-count TSP frames
+  (lwz tsp-count 16 vsp)
+  (cmpi cr0 tsp-count 0)
+  (b @test)
+@loop
+  (subi tsp-count tsp-count '1)
+  (cmpi cr0 tsp-count 0)
+  (lwz tsp 0 tsp)
+@test
+  (bne cr0 @loop)
+
+  ; Pop dynamic bindings until we get to db-link
+  (lwz imm0 12 vsp)                     ; db-link
+  (lwz imm1 target::tcr.db-link target::rcontext)
+  (cmp cr0 imm0 imm1)
+  (beq cr0 @restore-regs)               ; .SPunbind-to expects there to be something to do
+  (bla .SPunbind-to)
+
+@restore-regs
+  ; restore the saved registers from srv
+  (lwz srv 20 vsp)
+@get0
+  (svref imm0 1 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @get1)
+  (lwz save0 0 imm0)
+@get1
+  (svref imm0 2 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @get2)
+  (lwz save1 0 imm0)
+@get2
+  (svref imm0 3 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @get3)
+  (lwz save2 0 imm0)
+@get3
+  (svref imm0 4 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @get4)
+  (lwz save3 0 imm0)
+@get4
+  (svref imm0 5 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @get5)
+  (lwz save4 0 imm0)
+@get5
+  (svref imm0 6 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @get6)
+  (lwz save5 0 imm0)
+@get6
+  (svref imm0 7 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @get7)
+  (lwz save6 0 imm0)
+@get7
+  (svref imm0 8 srv)
+  (cmpwi cr0 imm0 (target-nil-value))
+  (beq @got)
+  (lwz save7 0 imm0)
+@got
+
+  (vpop arg_z)                          ; arglist
+  (vpop temp0)                          ; function
+  (vpop parent)                         ; parent
+  (extract-lisptag imm0 parent)
+  (cmpi cr0 imm0 target::tag-fixnum)
+  (if (:cr0 :ne)
+    ; Parent is a fake-stack-frame. Make it real
+    (progn
+      (svref sp %fake-stack-frame.sp parent)
+      (stwu sp (- target::lisp-frame.size) sp)
+      (svref fn %fake-stack-frame.fn parent)
+      (stw fn target::lisp-frame.savefn sp)
+      (svref temp1 %fake-stack-frame.vsp parent)
+      (stw temp1 target::lisp-frame.savevsp sp)
+      (svref temp1 %fake-stack-frame.lr parent)
+      (extract-lisptag imm0 temp1)
+      (cmpi cr0 imm0 target::tag-fixnum)
+      (if (:cr0 :ne)
+        ;; must be a macptr encoding the actual link register
+        (macptr-ptr loc-pc temp1)
+        ;; Fixnum is offset from start of function vector
+        (progn
+          (svref temp2 0 fn)        ; function vector
+          (unbox-fixnum temp1 temp1)
+          (add loc-pc temp2 temp1)))
+      (stw loc-pc target::lisp-frame.savelr sp))
+    ;; Parent is a real stack frame
+    (mr sp parent))
+  (set-nargs 0)
+  (bla .SPspreadargz)
+  (ba .SPtfuncallgen))
+
+#+ppc32-target
+;;; Easiest to do this in lap, to avoid consing bignums and/or 
+;;; multiple-value hair.
+;;; Bang through code-vector until the end or a 0 (traceback table
+;;; header) is found.  Return high-half, low-half of last instruction
+;;; and index where found.
+(defppclapfunction %code-vector-last-instruction ((cv arg_z))
+  (let ((previ imm0)
+        (nexti imm1)
+        (idx imm2)
+        (offset imm3)
+        (len imm4))
+    (vector-length len cv len)
+    (li idx 0)
+    (cmpw cr0 idx len)
+    (li offset target::misc-data-offset)
+    (li nexti 0)
+    (b @test)
+    @loop
+    (mr previ nexti)
+    (lwzx nexti cv offset)
+    (cmpwi cr1 nexti 0)
+    (addi idx idx '1)
+    (cmpw cr0 idx len)
+    (addi offset offset '1)
+    (beq cr1 @done)
+    @test
+    (bne cr0 @loop)
+    (mr previ nexti)
+    @done
+    (digit-h temp0 previ)
+    (digit-l temp1 previ)
+    (subi idx idx '1)
+    (vpush temp0)
+    (vpush temp1)
+    (vpush idx)
+    (set-nargs 3)
+    (la temp0 '3 vsp)
+    (ba .SPvalues)))
+
+#+ppc64-target
+(defun %code-vector-last-instruction (cv)
+  (do* ((i 1 (1+ i))
+        (instr nil)
+        (n (uvsize cv)))
+       ((= i n) instr)
+    (declare (fixnum i n))
+    (let* ((next (uvref cv i)))
+      (declare (type (unsigned-byte 32) next))
+      (if (zerop next)
+        (return instr)
+        (setq instr next)))))
+
+        
+
+  
+(defppclapfunction %%save-application ((flags arg_y) (fd arg_z))
+  (unbox-fixnum imm0 flags)
+  (ori imm0 imm0 arch::gc-trap-function-save-application)
+  (unbox-fixnum imm1 fd)
+  (trlgei allocptr 0)
+  (blr))
+
+
+
+(defppclapfunction %misc-address-fixnum ((misc-object arg_z))
+  (check-nargs 1)
+  (la arg_z target::misc-data-offset misc-object)
+  (blr))
+
+
+#+ppc32-target
+(defppclapfunction fudge-heap-pointer ((ptr arg_x) (subtype arg_y) (len arg_z))
+  (check-nargs 3)
+  (macptr-ptr imm1 ptr) ; address in macptr
+  (addi imm0 imm1 9)     ; 2 for delta + 7 for alignment
+  (clrrwi imm0 imm0 3)   ; Clear low three bits to align
+  (subf imm1 imm1 imm0)  ; imm1 = delta
+  (sth imm1 -2 imm0)     ; save delta halfword
+  (unbox-fixnum imm1 subtype)  ; subtype at low end of imm1
+  (rlwimi imm1 len (- target::num-subtag-bits target::fixnum-shift) 0 (- 31 target::num-subtag-bits))
+  (stw imm1 0 imm0)       ; store subtype & length
+  (addi arg_z imm0 target::fulltag-misc) ; tag it, return it
+  (blr))
+
+#+ppc64-target
+(defppclapfunction fudge-heap-pointer ((ptr arg_x) (subtype arg_y) (len arg_z))
+  (check-nargs 3)
+  (macptr-ptr imm1 ptr) ; address in macptr
+  (addi imm0 imm1 17)     ; 2 for delta + 15 for alignment
+  (clrrdi imm0 imm0 4)   ; Clear low four bits to align
+  (subf imm1 imm1 imm0)  ; imm1 = delta
+  (sth imm1 -2 imm0)     ; save delta halfword
+  (unbox-fixnum imm1 subtype)  ; subtype at low end of imm1
+  (sldi imm2 len (- target::num-subtag-bits target::fixnum-shift))
+  (or imm1 imm2 imm1)
+  (std imm1 0 imm0)       ; store subtype & length
+  (addi arg_z imm0 target::fulltag-misc) ; tag it, return it
+  (blr))
+
+(defppclapfunction %%make-disposable ((ptr arg_y) (vector arg_z))
+  (check-nargs 2)
+  (subi imm0 vector target::fulltag-misc) ; imm0 is addr = vect less tag
+  (lhz imm1 -2 imm0)   ; get delta
+  (sub imm0 imm0 imm1)  ; vector addr (less tag)  - delta is orig addr
+  (str imm0 target::macptr.address ptr) 
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %vect-data-to-macptr ((vect arg_y) (ptr arg_z))
+  ;; put address of vect data in macptr.  For all vector types
+  ;; other than DOUBLE-FLOAT (or vectors thereof), the first byte
+  ;; of data is at PPC32::MISC-DATA-OFFSET; for the double-float
+  ;; types, it's at PPC32::MISC-DFLOAT-OFFSET.
+  (extract-subtag imm0 vect)
+  (cmpwi cr0 imm0 ppc32::subtag-double-float-vector)
+  (cmpwi cr1 imm0 ppc32::subtag-double-float)
+  (addi temp0 vect ppc32::misc-data-offset)
+  (beq cr0 @dfloat)
+  (beq cr1 @dfloat)
+  (stw temp0 ppc32::macptr.address arg_z)
+  (blr)
+  @dfloat
+  (addi temp0 vect ppc32::misc-dfloat-offset)
+  (stw temp0 ppc32::macptr.address arg_z)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %vect-data-to-macptr ((vect arg_y) (ptr arg_z))
+  (la imm0 ppc64::misc-data-offset vect)
+  (std imm0 ppc64::macptr.address ptr)
+  (blr))
+
+(defppclapfunction get-saved-register-values ()
+  (vpush save0)
+  (vpush save1)
+  (vpush save2)
+  (vpush save3)
+  (vpush save4)
+  (vpush save5)
+  (vpush save6)
+  (vpush save7)
+  (la temp0 (* 8 target::node-size) vsp)
+  (set-nargs 8)
+  (ba .SPvalues))
+
+
+(defppclapfunction %current-db-link ()
+  (ldr arg_z target::tcr.db-link target::rcontext)
+  (blr))
+
+(defppclapfunction %no-thread-local-binding-marker ()
+  (li arg_z target::subtag-no-thread-local-binding)
+  (blr))
+
+
+(defppclapfunction pending-user-interrupt ()
+  (ref-global arg_z target::intflag)
+  ;; If another signal happens now, it will get ignored, same as if it happened
+  ;; before whatever signal is in arg_z.  But then these are async signals, so
+  ;; who can be sure it didn't actually happen just before...
+  (set-global rzero target::intflag)
+  (blr))
+
+
+;;; Should be called with interrupts disabled.
+(defppclapfunction %safe-get-ptr ((src arg_y) (dest arg_z))
+  (check-nargs 2)
+  (macptr-ptr imm0 src)
+  (str imm0 target::tcr.safe-ref-address target::rcontext)
+  (ldr imm0 0 imm0)                     ; may fault
+  (str imm0 target::macptr.address dest)
+  (blr))
+
+
+
+;;; r13 contains thread context on Linux/Darwin PPC64.
+;;; That's maintained in r2 on LinuxPPC32, and not maintained
+;;; in a GPR on DarwinPPC32
+(defppclapfunction %get-os-context ()
+  #+ppc64-target (mr arg_z 13)
+  #+linuxppc32-target (mr arg_z 2)
+  #+darinppc32-target (mr arg_z 0)
+  (blr))
+
+(defppclapfunction %check-deferred-gc ()
+  (ldr imm0 target::tcr.flags target::rcontext)
+  (slri. imm0 imm0 (- (1- target::nbits-in-word) (+ arch::tcr-flag-bit-pending-suspend target::fixnumshift)))
+  (li arg_z nil)
+  (bgelr)
+  (uuo_interr arch::error-propagate-suspend rzero)
+  (li arg_z t)
+  (blr))
+
+(defppclapfunction %%tcr-interrupt ((target arg_z))
+  (check-nargs 1)
+  (uuo_interr arch::error-interrupt rzero)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %suspend-tcr ((target arg_z))
+  (check-nargs 1)
+  (uuo_interr arch::error-suspend rzero)
+  (ne0->boolean arg_z imm0 imm1)
+  (blr))
+
+(defppclapfunction %suspend-other-threads ()
+  (check-nargs 0)
+  (uuo_interr arch::error-suspend-all rzero)
+  (li arg_z nil)
+  (blr))
+
+(defppclapfunction %resume-tcr ((target arg_z))
+  (check-nargs 1)
+  (uuo_interr arch::error-resume rzero)
+  (ne0->boolean arg_z imm0 imm1)
+  (blr))
+
+(defppclapfunction %resume-other-threads ()
+  (check-nargs 0)
+  (uuo_interr arch::error-resume-all rzero)
+  (li arg_z nil)
+  (blr))
+
+(defppclapfunction %kill-tcr ((target arg_z))
+  (check-nargs 1)
+  (uuo_interr arch::error-kill rzero)
+  (ne0->boolean arg_z imm0 imm1)
+  (blr))
+
+(defppclapfunction %atomic-pop-static-cons ()
+  (li imm0 (+ (target-nil-value) (target::kernel-global static-conses)))
+  @again
+  (lrarx arg_z rzero imm0)
+  (cmpri arg_z (target-nil-value))
+  (beq @lose)
+  (%cdr arg_y arg_z)
+  (strcx. arg_y rzero imm0)
+  (bne @again)
+  (li imm0 (+ (target-nil-value) (target::kernel-global free-static-conses)))
+  @decf
+  (lrarx imm1 rzero imm0)
+  (subi imm1 imm1 '1)
+  (strcx. imm1 rzero imm0)
+  (bne @decf)
+  (isync)
+  (blr)
+  @lose
+  (li imm0 target::reservation-discharge)
+  (strcx. rzero rzero imm0)
+  (blr))
+
+
+
+(defppclapfunction %staticp ((x arg_z))
+  (check-nargs 1)
+  (ref-global temp0 static-cons-area)
+  (ldr imm1 target::area.low temp0)
+  (sub imm0 x imm1)
+  (ldr imm1 target::area.ndnodes temp0)
+  (srri imm0 imm0 target::dnode-shift)
+  (li arg_z nil)
+  (sub imm1 imm1 imm0)
+  (cmplri imm1 0)
+  (la imm1 128 imm1)
+  (blelr)
+  (box-fixnum arg_z imm1)
+  (blr))
+
+(defppclapfunction %static-inverse-cons ((n arg_z))
+  (check-nargs 1)
+  (ref-global temp0 static-cons-area)
+  (la n '-128 n)
+  (ldr imm1 target::area.high temp0)
+  (sub imm1 imm1 n)
+  (sub imm1 imm1 n)
+  (la arg_z target::fulltag-cons imm1)
+  (blr))
+  
+
+; end of ppc-misc.lisp
Index: /branches/new-random/level-0/PPC/ppc-numbers.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-numbers.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-numbers.lisp	(revision 13309)
@@ -0,0 +1,444 @@
+;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+(in-package "CCL")
+
+;(push (cons 'number-case 1) *fred-special-indent-alist*) do later
+
+
+
+(defppclapfunction %fixnum-signum ((number arg_z))
+  (cmpri :cr0 number '0)
+  (li arg_z '0)
+  (beqlr :cr0)
+  (li arg_z '1)               ; assume positive
+  (bgtlr :cr0)
+  (li arg_z '-1)
+  (blr))
+
+; see %logcount (ppc-bignum.lisp)
+(defppclapfunction %ilogcount ((number arg_z))
+  (let ((arg imm0)
+        (shift imm1)
+        (temp imm2))
+    (unbox-fixnum arg number)
+    (mr. shift arg)
+    (li arg_z 0)
+    (b @test)
+    @next
+    (la temp -1 shift)
+    (and. shift shift temp)
+    (la arg_z '1 arg_z)
+    @test
+    (bne @next)
+    (blr)))
+
+(defppclapfunction %iash ((number arg_y) (count arg_z))
+  (unbox-fixnum imm1 count)
+  (unbox-fixnum imm0 number)
+  (neg. imm2 imm1)
+  (blt @left)
+  (srar imm0 imm0 imm2)
+  (box-fixnum arg_z imm0)
+  (blr)
+  @left
+  (slr arg_z number imm1)
+  (blr))
+
+(defparameter *double-float-zero* 0.0d0)
+(defparameter *short-float-zero* 0.0s0)
+
+
+#+ppc32-target
+(defppclapfunction %sfloat-hwords ((sfloat arg_z))
+  (lwz imm0 ppc32::single-float.value sfloat)
+  (digit-h temp0 imm0)
+  (digit-l temp1 imm0)
+  (vpush temp0)
+  (vpush temp1)
+  (la temp0 8 vsp)
+  (set-nargs 2)
+  (ba .SPvalues))
+
+
+; (integer-length arg) = (- 32 (cntlz (if (>= arg 0) arg (lognot arg))))
+#+ppc32-target
+(defppclapfunction %fixnum-intlen ((number arg_z))  
+  (unbox-fixnum imm0 arg_z)
+  (cntlzw. imm1 imm0)			; testing result of cntlzw? - ah no zeros if neg
+  (bne @nonneg)
+  (not imm1 imm0)
+  (cntlzw imm1 imm1)
+  @nonneg
+  (subfic imm1 imm1 32)
+  (box-fixnum arg_z imm1)
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %fixnum-intlen ((number arg_z))  
+  (unbox-fixnum imm0 arg_z)
+  (cntlzd. imm1 imm0)
+  (bne @nonneg)
+  (not imm1 imm0)
+  (cntlzd imm1 imm1)
+  @nonneg
+  (subfic imm1 imm1 64)
+  (box-fixnum arg_z imm1)
+  (blr))
+
+
+
+
+;;; Caller guarantees that result fits in a fixnum.
+#+ppc32-target
+(defppclapfunction %truncate-double-float->fixnum ((arg arg_z))
+  (get-double-float fp0 arg)
+  (fctiwz fp0 fp0)
+  (stwu tsp -16 tsp)
+  (stw tsp 4 tsp)
+  (stfd fp0 8 tsp)
+  (lwz imm0 (+ 8 4) tsp)
+  (lwz tsp 0 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %truncate-double-float->fixnum ((arg arg_z))
+  (get-double-float fp0 arg)
+  (fctidz fp0 fp0)
+  (stdu tsp -32 tsp)
+  (std tsp 8 tsp)
+  (stfd fp0 16 tsp)
+  (ld imm0 16 tsp)
+  (la tsp 32 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %truncate-short-float->fixnum ((arg arg_z))
+  (get-single-float fp0 arg)
+  (fctiwz fp0 fp0)
+  (stwu tsp -16 tsp)
+  (stw tsp 4 tsp)
+  (stfd fp0 8 tsp)
+  (lwz imm0 (+ 8 4) tsp)
+  (lwz tsp 0 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %truncate-short-float->fixnum ((arg arg_z))
+  (get-single-float fp0 arg)
+  (fctidz fp0 fp0)
+  (stdu tsp -32 tsp)
+  (std tsp 8 tsp)
+  (stfd fp0 16 tsp)
+  (ld imm0 16 tsp)
+  (la tsp 32 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+;;; DOES round to even
+#+ppc32-target
+(defppclapfunction %round-nearest-double-float->fixnum ((arg arg_z))
+  (get-double-float fp0 arg)
+  (fctiw fp0 fp0)
+  (stwu tsp -16 tsp)
+  (stw tsp 4 tsp)
+  (stfd fp0 8 tsp)
+  (lwz imm0 (+ 8 4) tsp)
+  (lwz tsp 0 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %round-nearest-double-float->fixnum ((arg arg_z))
+  (get-double-float fp0 arg)
+  (fctid fp0 fp0)
+  (stdu tsp -32 tsp)
+  (std tsp 8 tsp)
+  (stfd fp0 16 tsp)
+  (ld imm0 16 tsp)
+  (la tsp 32 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+#+ppc32-target
+(defppclapfunction %round-nearest-short-float->fixnum ((arg arg_z))
+  (get-single-float fp0 arg)
+  (fctiw fp0 fp0)
+  (stwu tsp -16 tsp)
+  (stw tsp 4 tsp)
+  (stfd fp0 8 tsp)
+  (lwz imm0 (+ 8 4) tsp)
+  (lwz tsp 0 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+#+ppc64-target
+(defppclapfunction %round-nearest-short-float->fixnum ((arg arg_z))
+  (get-single-float fp0 arg)
+  (fctid fp0 fp0)
+  (stdu tsp -32 tsp)
+  (std tsp 8 tsp)
+  (stfd fp0 16 tsp)
+  (ld imm0 16 tsp)
+  (la tsp 32 tsp)
+  (box-fixnum arg_z imm0)  
+  (blr))
+
+
+
+
+;;;; maybe this could be smarter but frankly scarlett I dont give a damn
+#+ppc32-target
+(defppclapfunction %fixnum-truncate ((dividend arg_y) (divisor arg_z))
+  (let ((unboxed-quotient imm0)
+        (unboxed-dividend imm1)
+        (unboxed-divisor imm2)
+        (unboxed-product imm3)
+        (product temp0)
+        (boxed-quotient temp1)
+        (remainder temp2))
+    (unbox-fixnum unboxed-dividend dividend)
+    (unbox-fixnum unboxed-divisor divisor)
+    (divwo. unboxed-quotient unboxed-dividend unboxed-divisor)          ; set OV if divisor = 0
+    (box-fixnum boxed-quotient unboxed-quotient)
+    (mullw unboxed-product unboxed-quotient unboxed-divisor)
+    (bns+ @ok)
+    (mtxer rzero)
+    (save-lisp-context)
+    (set-nargs 3)
+    (load-constant arg_x truncate)
+    (call-symbol divide-by-zero-error)
+    @not-0
+    @ok
+    (subf imm0 unboxed-product unboxed-dividend)
+    (vpush boxed-quotient)
+    (box-fixnum remainder imm0)
+    (vpush remainder)
+    (set-nargs 2)
+    (la temp0 8 vsp)
+    (ba .SPvalues)))
+
+#+ppc64-target
+(defppclapfunction %fixnum-truncate ((dividend arg_y) (divisor arg_z))
+  (let ((unboxed-quotient imm0)
+        (unboxed-dividend imm1)
+        (unboxed-divisor imm2)
+        (unboxed-product imm3)
+        (product temp0)
+        (boxed-quotient temp1)
+        (remainder temp2))
+    (unbox-fixnum unboxed-dividend dividend)
+    (unbox-fixnum unboxed-divisor divisor)
+    (divdo. unboxed-quotient unboxed-dividend unboxed-divisor)          ; set OV if divisor = 0
+    (box-fixnum boxed-quotient unboxed-quotient)
+    (mulld unboxed-product unboxed-quotient unboxed-divisor)
+    (bns+ @ok)
+    (mtxer rzero)
+    (save-lisp-context)
+    (set-nargs 3)
+    (load-constant arg_x truncate)
+    (call-symbol divide-by-zero-error)
+    @not-0
+    @ok
+    (subf imm0 unboxed-product unboxed-dividend)
+    (vpush boxed-quotient)
+    (box-fixnum remainder imm0)
+    (vpush remainder)
+    (set-nargs 2)
+    (la temp0 '2 vsp)
+    (ba .SPvalues)))
+
+
+(defppclapfunction called-for-mv-p ()
+  (ref-global imm0 ret1valaddr)
+  (ldr imm1 target::lisp-frame.savelr sp)
+  (eq->boolean arg_z imm0 imm1 imm0)
+  (blr))
+  
+
+
+
+
+
+
+
+#|
+Date: Mon, 3 Feb 1997 10:04:08 -0500
+To: info-mcl@digitool.com, wineberg@franz.scs.carleton.ca
+From: dds@flavors.com (Duncan Smith)
+Subject: Re: More info on the random number generator
+Sender: owner-info-mcl@digitool.com
+Precedence: bulk
+
+The generator is a Linear Congruential Generator:
+
+   X[n+1] = (aX[n] + c) mod m
+
+where: a = 16807  (Park&Miller recommend 48271)
+       c = 0
+       m = 2^31 - 1
+
+See: Knuth, Seminumerical Algorithms (Volume 2), Chapter 3.
+
+The period is: 2^31 - 2  (zero is excluded).
+
+What makes this generator so simple is that multiplication and addition mod
+2^n-1 is easy.  See Knuth Ch. 4.3.2 (2nd Ed. p 272).
+
+    ab mod m = ...
+
+If         m = 2^n-1
+           u = ab mod 2^n
+           v = floor( ab / 2^n )
+
+    ab mod m = u + v                   :  u+v < 2^n
+    ab mod m = ((u + v) mod 2^n) + 1   :  u+v >= 2^n
+
+What we do is use 2b and 2^n so we can do arithemetic mod 2^32 instead of
+2^31.  This reduces the whole generator to 5 instructions on the 680x0 or
+80x86, and 8 on the 60x.
+
+-Duncan
+
+|#
+; Use the two fixnums in state to generate a random fixnum >= 0 and < 65536
+; Scramble those fixnums up a bit.
+
+#+ppc32-target
+(defppclapfunction %next-random-pair ((high arg_y) (low arg_z))
+  (slwi imm0 high (- 16 ppc32::fixnumshift))
+  (rlwimi imm0 low (- 32 ppc32::fixnumshift) 16 31)
+  (lwi imm1 48271)
+  (clrlwi imm0 imm0 1)
+  (mullw imm0 imm1 imm0)
+  (clrrwi arg_y imm0 16 )
+  (srwi arg_y arg_y (- 16 ppc32::fixnumshift))
+  (clrlslwi arg_z imm0 16 ppc32::fixnumshift)
+  (mr temp0 vsp)
+  (vpush arg_y)
+  (vpush arg_z)
+  (set-nargs 2)
+  (ba .SPvalues))
+
+
+
+
+
+
+
+
+
+;;; n1 and n2 must be positive (esp non zero)
+#+ppc32-target
+(defppclapfunction %fixnum-gcd ((n1 arg_y)(n2 arg_z))
+  (let ((temp imm0)
+	(u imm1)
+	(v imm2)
+	(ut0 imm3)
+	(vt0 imm4))
+    (unbox-fixnum u n1)
+    (unbox-fixnum v n2)
+    (neg temp u)
+    (and temp temp u)
+    (cntlzw ut0 temp)
+    (subfic ut0 ut0 31)
+    (neg temp v)
+    (and temp temp v)
+    (cntlzw vt0 temp)
+    (subfic vt0 vt0 31)
+    (cmpw cr2 ut0 vt0)
+    (srw u u ut0)
+    (srw v v vt0)
+    (addi ut0 ut0 ppc32::fixnum-shift)
+    (addi vt0 vt0 ppc32::fixnum-shift)
+    @loop
+    (cmpw cr0 u v)
+    (slw arg_z u ut0)
+    (bgt cr0 @u>v)
+    (blt cr0 @u<v)
+    (blelr cr2)
+    (slw arg_z u vt0)
+    (blr)
+    @u>v
+    (sub u u v)
+    @shiftu
+    (andi. temp u (ash 1 1))
+    (srwi u u 1)
+    (beq cr0 @shiftu)
+    (b @loop)
+    @u<v
+    (sub v v u)
+    @shiftv
+    (andi. temp v (ash 1 1))
+    (srwi v v 1)
+    (beq cr0 @shiftv)
+    (b @loop)))
+
+#+ppc64-target
+(defppclapfunction %fixnum-gcd ((n1 arg_y)(n2 arg_z))
+  (let ((temp imm0)
+	(u imm1)
+	(v imm2)
+	(ut0 imm3)
+	(vt0 imm4))
+    (unbox-fixnum u n1)
+    (unbox-fixnum v n2)
+    (neg temp u)
+    (and temp temp u)
+    (cntlzd ut0 temp)
+    (subfic ut0 ut0 63)
+    (neg temp v)
+    (and temp temp v)
+    (cntlzd vt0 temp)
+    (subfic vt0 vt0 63)
+    (cmpw cr2 ut0 vt0)
+    (srd u u ut0)
+    (srd v v vt0)
+    (addi ut0 ut0 ppc64::fixnum-shift)
+    (addi vt0 vt0 ppc64::fixnum-shift)
+    @loop
+    (cmpd cr0 u v)
+    (sld arg_z u ut0)
+    (bgt cr0 @u>v)
+    (blt cr0 @u<v)
+    (blelr cr2)
+    (sld arg_z u vt0)
+    (blr)
+    @u>v
+    (sub u u v)
+    @shiftu
+    (andi. temp u (ash 1 1))
+    (srdi u u 1)
+    (beq cr0 @shiftu)
+    (b @loop)
+    @u<v
+    (sub v v u)
+    @shiftv
+    (andi. temp v (ash 1 1))
+    (srdi v v 1)
+    (beq cr0 @shiftv)
+    (b @loop)))
+    
+
+
+
+; End of ppc-numbers.lisp
Index: /branches/new-random/level-0/PPC/ppc-pred.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-pred.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-pred.lisp	(revision 13309)
@@ -0,0 +1,358 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "PPC-LAPMACROS"))
+
+#+ppc32-target
+(defppclapfunction eql ((x arg_y) (y arg_z))
+  "Return T if OBJ1 and OBJ2 represent the same object, otherwise NIL."
+  (check-nargs 2)
+  @tail
+  (cmpw cr0 x y)
+  (extract-lisptag imm0 x)
+  (extract-lisptag imm1 y)
+  (cmpwi cr1 imm0 ppc32::tag-misc)
+  (cmpwi cr2 imm1 ppc32::tag-misc)
+  (beq cr0 @win)
+  (bne cr1 @lose)
+  (bne cr2 @lose)
+  ;; Objects are both of tag-misc.  Headers must match exactly;
+  ;; dispatch on subtag.
+  (getvheader imm0 x)
+  (getvheader imm1 y)
+  (cmpw cr0 imm0 imm1)
+  (extract-lowbyte imm1 imm1)
+  (cmpwi cr1 imm1 ppc32::subtag-macptr)
+  (cmpwi cr2 imm1 ppc32::max-numeric-subtag)
+  (beq cr1 @macptr)
+  (bne cr0 @lose)
+  (bgt cr2 @lose)
+  (cmpwi cr0 imm1 ppc32::subtag-ratio)
+  (cmpwi cr1 imm1 ppc32::subtag-complex)
+  (beq cr0 @node)
+  (beq cr1 @node)
+  ; A single-float looks a lot like a macptr to me.
+  ; A double-float is simple, a bignum involves a loop.
+  (cmpwi cr0 imm1 ppc32::subtag-bignum)
+  (cmpwi cr1 imm1 ppc32::subtag-double-float)
+  (beq cr0 @bignum)
+  (bne cr1 @one-unboxed-word)                     ; single-float case
+  ; This is the double-float case.
+  (lwz imm0 ppc32::double-float.value x)
+  (lwz imm1 ppc32::double-float.value y)
+  (cmpw cr0 imm0 imm1)
+  (lwz imm0 ppc32::double-float.val-low x)
+  (lwz imm1 ppc32::double-float.val-low y)
+  (cmpw cr1 imm0 imm1)
+  (bne cr0 @lose)
+  (bne cr1 @lose)
+  @win
+  (li arg_z (+ ppc32::t-offset (target-nil-value)))
+  (blr)
+  @macptr
+  (extract-lowbyte imm0 imm0)
+  (cmpw cr0 imm1 imm0)
+  (bne- cr0 @lose)
+  @one-unboxed-word
+  (lwz imm0 ppc32::misc-data-offset x)
+  (lwz imm1 ppc32::misc-data-offset y)
+  (cmpw cr0 imm0 imm1)
+  (beq cr0 @win)
+  @lose
+  (li arg_z (target-nil-value))
+  (blr)
+  @bignum
+  ;; Way back when, we got x's header into imm0.  We know that y's
+  ;; header is identical.  Use the element-count from imm0 to control
+  ;; the loop.  There's no such thing as a 0-element bignum, so the
+  ;; loop must always execute at least once.
+  (header-size imm0 imm0)
+  (li imm1 ppc32::misc-data-offset)
+  @bignum-next
+  (cmpwi cr1 imm0 1)                    ; last time through ?
+  (lwzx imm2 x imm1)
+  (lwzx imm3 y imm1)
+  (cmpw cr0 imm2 imm3)
+  (subi imm0 imm0 1)
+  (la imm1 4 imm1)
+  (bne cr0 @lose)
+  (bne cr1 @bignum-next)
+  (li arg_z (+ ppc32::t-offset (target-nil-value)))
+  (blr)
+  @node
+  ;; Have either a ratio or a complex.  In either case, corresponding
+  ;; elements of both objects must be EQL.  Recurse on the first
+  ;; elements.  If true, tail-call on the second, else fail.
+  (vpush x)
+  (vpush y)
+  (save-lisp-context)
+  (lwz x ppc32::misc-data-offset x)
+  (lwz y ppc32::misc-data-offset y)
+  (bl @tail)
+  (cmpwi cr0 arg_z (target-nil-value))
+  (restore-full-lisp-context)
+  (vpop y)
+  (vpop x)
+  (beq cr0 @lose)
+  (lwz x (+ 4 ppc32::misc-data-offset) x)
+  (lwz y (+ 4 ppc32::misc-data-offset) y)
+  (b @tail))
+
+#+ppc64-target
+(defppclapfunction eql ((x arg_y) (y arg_z))
+  "Return T if OBJ1 and OBJ2 represent the same object, otherwise NIL."
+  (check-nargs 2)
+  @tail
+  (cmpd cr0 x y)
+  (extract-fulltag imm0 x)
+  (extract-fulltag imm1 y)
+  (cmpri cr1 imm0 ppc64::fulltag-misc)
+  (cmpri cr2 imm1 ppc64::fulltag-misc)
+  (beq cr0 @win)
+  (bne cr1 @lose)
+  (bne cr2 @lose)
+  ;; Objects are both of tag-misc.  Headers must match exactly;
+  ;; dispatch on subtag.
+  (getvheader imm0 x)
+  (getvheader imm1 y)
+  (cmpd cr0 imm0 imm1)
+  (extract-lowbyte imm1 imm1)
+  (cmpdi cr1 imm1 ppc64::subtag-macptr)
+  (cmpdi cr2 imm1 ppc64::subtag-bignum)
+  (cmpdi cr3 imm1 ppc64::subtag-double-float)
+  (beq cr1 @macptr)
+  (cmpdi cr4 imm1 ppc64::subtag-complex)
+  (cmpdi cr5 imm1 ppc64::subtag-ratio)
+  (bne cr0 @lose)
+  (beq cr2 @bignum)
+  (beq cr3 @double-float)
+  (beq cr4 @complex)
+  (beq cr5 @ratio)
+  @lose
+  (li arg_z nil)
+  (blr)
+  @double-float
+  (ld imm0 ppc64::double-float.value x)
+  (ld imm1 ppc64::double-float.value y)
+  @test  
+  (cmpd imm0 imm1)
+  (bne @lose)
+  @win
+  (li arg_z (+ (target-nil-value) ppc64::t-offset))
+  (blr)
+  ;; Macptr objects can have different lengths, but their subtags must
+  ;; match
+  @macptr
+  (extract-lowbyte imm0 imm0)
+  (cmpd imm0 imm1)
+  (bne @lose)
+  (ld imm0 ppc64::macptr.address x)
+  (ld imm1 ppc64::macptr.address y)
+  (b @test)
+  @ratio
+  @complex
+  (vpush x)
+  (vpush y)
+  (save-lisp-context)
+  (ld x ppc64::ratio.numer x)       ; aka complex.realpart
+  (ld y ppc64::ratio.numer y)       ; aka complex.imagpart
+  (bl @tail)
+  (cmpdi cr0 arg_z nil)
+  (restore-full-lisp-context)
+  (vpop y)
+  (vpop x)
+  (beq cr0 @lose)
+  (ld x ppc64::ratio.denom x)
+  (ld y ppc64::ratio.denom y)
+  (b @tail)
+  @bignum
+  ;; Way back when, we got x's header into imm0.  We know that y's
+  ;; header is identical.  Use the element-count from imm0 to control
+  ;; the loop.  There's no such thing as a 0-element bignum, so the
+  ;; loop must always execute at least once.
+  (header-size imm0 imm0)
+  (li imm1 ppc64::misc-data-offset)
+  @bignum-next
+  (cmpwi cr1 imm0 1)                    ; last time through ?
+  (lwzx imm2 x imm1)
+  (lwzx imm3 y imm1)
+  (cmpw cr0 imm2 imm3)
+  (subi imm0 imm0 1)
+  (la imm1 4 imm1)
+  (bne cr0 @lose)
+  (bne cr1 @bignum-next)
+  (li arg_z t)
+  (blr))
+  
+
+#+ppc32-target
+(defppclapfunction equal ((x arg_y) (y arg_z))
+  "Return T if X and Y are EQL or if they are structured components
+  whose elements are EQUAL. Strings and bit-vectors are EQUAL if they
+  are the same length and have identical components. Other arrays must be
+  EQ to be EQUAL.  Pathnames are EQUAL if their components are."
+  (check-nargs 2)
+  @top
+  (cmpw cr0 x y)
+  (extract-fulltag imm0 x)
+  (extract-fulltag imm1 y)
+  (cmpw cr1 imm0 imm1)
+  (cmpwi cr2 imm0 ppc32::fulltag-cons)
+  (cmpwi cr3 imm0 ppc32::fulltag-misc)
+  (beq cr0 @win)
+  (bne cr1 @lose)
+  (beq cr2 @cons)
+  (bne cr3 @lose)
+  (extract-subtag imm0 x)
+  (extract-subtag imm1 y)
+  (cmpwi cr0 imm0 ppc32::subtag-macptr)
+  (cmpwi cr2 imm0 ppc32::subtag-istruct)
+  (cmpwi cr1 imm0 ppc32::subtag-vectorH)
+  (cmpw cr3 imm0 imm1)
+  (ble cr0 @eql)
+  (cmplwi cr0 imm1 ppc32::subtag-vectorH)
+  (beq cr2 @same)
+  (blt cr1 @lose)
+  (bge cr0 @go)
+  @lose
+  (li arg_z (target-nil-value))
+  (blr)
+  @same
+  (bne cr3 @lose)
+  @go
+  (set-nargs 2)
+  (lwz fname 'hairy-equal nfn)
+  (ba .SPjmpsym)
+  @eql
+  (set-nargs 2)
+  (lwz fname 'eql nfn)
+  (ba .SPjmpsym)
+  @cons
+  (%car temp0 x)
+  (%car temp1 y)
+  (cmpw temp0 temp1)
+  (bne @recurse)
+  (%cdr x x)
+  (%cdr y y)
+  (b @top)
+  @recurse
+  (vpush x)
+  (vpush y)
+  (save-lisp-context)
+  (lwz imm0 ppc32::tcr.cs-limit ppc32::rcontext) ; stack probe
+  (twllt ppc32::sp imm0)
+  (mr x temp0)
+  (mr y temp1)
+  (bl @top)
+  (cmpwi :cr0 arg_z (target-nil-value))  
+  (mr nfn fn)
+  (restore-full-lisp-context)           ; gets old fn to fn  
+  (vpop y)
+  (vpop x)
+  (beq cr0 @lose)
+  (%cdr x x)
+  (%cdr y y)
+  (b @top)
+  @win
+  (li arg_z (+ ppc32::t-offset (target-nil-value)))
+  (blr))
+
+#+ppc64-target
+(defppclapfunction equal ((x arg_y) (y arg_z))
+  "Return T if X and Y are EQL or if they are structured components
+  whose elements are EQUAL. Strings and bit-vectors are EQUAL if they
+  are the same length and have identical components. Other arrays must be
+  EQ to be EQUAL.  Pathnames are EQUAL if their components are."
+  (check-nargs 2)
+  @top
+  (cmpd cr0 x y)
+  (extract-fulltag imm0 x)
+  (extract-fulltag imm1 y)
+  (cmpd cr1 imm0 imm1)
+  (cmpdi cr2 imm0 ppc64::fulltag-cons)
+  (cmpdi cr3 imm0 ppc64::fulltag-misc)
+  (beq cr0 @win)
+  (bne cr1 @lose)
+  (beq cr2 @cons)
+  (beq cr3 @misc)
+  @lose
+  (li arg_z nil)
+  (blr)
+  @win
+  (li arg_z (+ (target-nil-value) ppc64::t-offset))
+  (blr)
+  @cons
+  ;; Check to see if the CARs are EQ.  If so, we can avoid saving
+  ;; context, and can just tail call ourselves on the CDRs.
+  (%car temp0 x)
+  (%car temp1 y)
+  (cmpd temp0 temp1)
+  (bne @recurse)
+  (%cdr x x)
+  (%cdr y y)
+  (b @top)
+  @recurse
+  (vpush x)
+  (vpush y)
+  (save-lisp-context)
+  (ld imm0 ppc64::tcr.cs-limit ppc64::rcontext) ; stack probe
+  (tdllt ppc32::sp imm0)
+  (mr x temp0)
+  (mr y temp1)
+  (bl @top)
+  (cmpdi :cr0 arg_z nil)  
+  (mr nfn fn)
+  (restore-full-lisp-context)           ; gets old fn to fn  
+  (vpop y)
+  (vpop x)
+  (beq cr0 @lose)
+  (%cdr x x)
+  (%cdr y y)
+  (b @top)
+  @misc
+  ;; Both objects are uvectors of some sort.  Try EQL; if that fails,
+  ;; call HAIRY-EQUAL.
+  (vpush x)
+  (vpush y)
+  (save-lisp-context)
+  (set-nargs 2)
+  (ld fname 'eql nfn)
+  (set-nargs 2)
+  (bla .SPjmpsym)
+  (cmpdi arg_z nil)
+  (mr nfn fn)
+  (restore-full-lisp-context)
+  (vpop y)
+  (vpop x)
+  (bne @win)
+  (set-nargs 2)
+  (ld fname 'hairy-equal nfn)
+  (ba .SPjmpsym))
+
+
+
+      
+
+
+
+
+
+
+
Index: /branches/new-random/level-0/PPC/ppc-symbol.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-symbol.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-symbol.lisp	(revision 13309)
@@ -0,0 +1,179 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  #+ppc32-target
+  (require "PPC32-ARCH")
+  #+ppc64-target
+  (require "PPC64-ARCH")
+  (require "PPC-LAPMACROS"))
+
+;;; This assumes that macros & special-operators
+;;; have something that's not FUNCTIONP in their
+;;; function-cells.
+#+ppc32-target
+(defppclapfunction %function ((sym arg_z))
+  (check-nargs 1)
+  (cmpwi cr1 sym (target-nil-value))
+  (let ((symptr temp0)
+        (symbol temp1)
+        (def arg_z))
+    (li symptr (+ ppc32::nilsym-offset (target-nil-value)))
+    (mr symbol sym)
+    (if (:cr1 :ne)
+      (progn
+        (trap-unless-typecode= sym ppc32::subtag-symbol)
+        (mr symptr sym)))
+    (lwz def ppc32::symbol.fcell symptr)
+    (extract-typecode imm0 def)
+    (cmpwi cr0 imm0 ppc32::subtag-function)
+    (beqlr+)
+    (uuo_interr arch::error-udf symbol)))
+
+#+ppc64-target
+(defppclapfunction %function ((sym arg_z))
+  (check-nargs 1)
+  (let ((symbol temp1)
+        (def arg_z))
+    (mr symbol sym)
+    (trap-unless-typecode= sym ppc64::subtag-symbol)
+    (mr symbol sym)
+    (ld def ppc64::symbol.fcell symbol)
+    (extract-typecode imm0 def)
+    (cmpdi cr0 imm0 ppc64::subtag-function)
+    (beqlr+)
+    (uuo_interr arch::error-udf symbol)))
+
+;;; Traps unless sym is NIL or some other symbol.
+;;; On PPC32, NIL isn't really a symbol; this function maps from NIL
+;;; to an internal proxy symbol ("nilsym").
+;;; On PPC64, NIL is a real symbol, so this function just does a
+;;; little bit of type checking.
+(defppclapfunction %symbol->symptr ((sym arg_z))
+  #+ppc32-target
+  (progn
+    (cmpwi cr0 arg_z (target-nil-value))
+    (if (:cr0 :eq)
+      (progn
+        (li arg_z (+ ppc32::nilsym-offset (target-nil-value)))
+        (blr))))
+  (trap-unless-typecode= arg_z target::subtag-symbol)
+  (blr))
+
+;;; Traps unless symptr is a symbol; on PPC32, returns NIL if symptr
+;;; is NILSYM.
+(defppclapfunction %symptr->symbol ((symptr arg_z))
+  #+ppc32-target
+  (progn
+    (li imm1 (+ ppc32::nilsym-offset (target-nil-value)))
+    (cmpw cr0 imm1 symptr)
+    (if (:cr0 :eq)
+      (progn 
+        (li arg_z nil)
+        (blr))))
+  (trap-unless-typecode= symptr target::subtag-symbol imm0)
+  (blr))
+
+(defppclapfunction %symptr-value ((symptr arg_z))
+  (ba .SPspecref))
+
+(defppclapfunction %set-symptr-value ((symptr arg_y) (val arg_z))
+  (ba .SPspecset))
+
+(defppclapfunction %symptr-binding-address ((symptr arg_z))
+  (ldr imm3 target::symbol.binding-index symptr)
+  (ldr imm2 target::tcr.tlb-limit target::rcontext)
+  (ldr imm4 target::tcr.tlb-pointer target::rcontext)
+  (cmplr imm3 imm2)
+  (bge @sym)
+  (ldrx temp0 imm4 imm3)
+  (cmpdi temp0 target::subtag-no-thread-local-binding)
+  (slri imm3 imm3 target::fixnumshift)
+  (beq @sym)
+  (vpush imm4)
+  (vpush imm3)
+  (set-nargs 2)
+  (la temp0 '2 vsp)
+  (ba .SPvalues)
+  @sym
+  (li arg_y '#.target::symbol.vcell)
+  (vpush arg_z)
+  (vpush arg_y)
+  (set-nargs 2)
+  (la temp0 '2 vsp)
+  (ba .SPvalues))
+
+(defppclapfunction %tcr-binding-location ((tcr arg_y) (sym arg_z))
+  (ldr imm3 target::symbol.binding-index sym)
+  (ldr imm2 target::tcr.tlb-limit tcr)
+  (ldr imm4 target::tcr.tlb-pointer tcr)
+  (li arg_z nil)
+  (cmplr imm3 imm2)
+  (bgelr)
+  (ldrx temp0 imm4 imm3)
+  (cmpri temp0 target::subtag-no-thread-local-binding)
+  (beqlr)
+  (add arg_z imm4 imm3)
+  (blr))
+
+  
+(defppclapfunction %pname-hash ((str arg_y) (len arg_z))
+  (let ((nextw imm1)
+        (accum imm0)
+        (offset imm2))
+    (cmpwi cr0 len 0)
+    (li offset target::misc-data-offset)
+    (li accum 0)
+    (beqlr- cr0)    
+    @loop
+    (cmpri cr1 len '1)
+    (subi len len '1)
+    (lwzx nextw str offset)
+    (addi offset offset 4)
+    (rotlwi accum accum 5)
+    (xor accum accum nextw)
+    (bne cr1 @loop)
+    (slri accum accum 5)
+    (srri arg_z accum (- 5 target::fixnumshift))
+    (blr)))
+
+(defppclapfunction %string-hash ((start arg_x) (str arg_y) (len arg_z))
+  (let ((nextw imm1)
+        (accum imm0)
+        (offset imm2))
+    (cmpwi cr0 len 0)
+    #+32-bit-target
+    (la offset target::misc-data-offset start)
+    #+64-bit-target
+    (progn
+      (srwi offset start 1)
+      (la offset target::misc-data-offset offset))
+    (li accum 0)
+    (beqlr- cr0)    
+    @loop
+    (cmpri cr1 len '1)
+    (subi len len '1)
+    (lwzx nextw str offset)
+    (addi offset offset 4)
+    (rotlwi accum accum 5)
+    (xor accum accum nextw)
+    (bne cr1 @loop)
+    (slri accum accum 5)
+    (srri arg_z accum (- 5 target::fixnumshift))
+    (blr)))
Index: /branches/new-random/level-0/PPC/ppc-utils.lisp
===================================================================
--- /branches/new-random/level-0/PPC/ppc-utils.lisp	(revision 13309)
+++ /branches/new-random/level-0/PPC/ppc-utils.lisp	(revision 13309)
@@ -0,0 +1,692 @@
+;;; -*- Mode: Lisp; Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+#+ppc32-target
+(defppclapfunction %address-of ((arg arg_z))
+  ;; %address-of a fixnum is a fixnum, just for spite.
+  ;; %address-of anything else is the address of that thing as an integer.
+  (clrlwi. imm0 arg (- 32 ppc32::nlisptagbits))
+  (beqlr cr0)
+  (mr imm0 arg_z)
+  ;; set cr0_eq if result fits in a fixnum
+  (clrrwi. imm1 imm0 (- ppc32::least-significant-bit ppc32::nfixnumtagbits))
+  (box-fixnum arg_z imm0)               ; assume it did
+  (beqlr+ cr0)                          ; else arg_z tagged ok, but missing bits
+  (ba .SPmakeu32)         ; put all bits in bignum.
+)
+
+#+ppc64-target
+(defppclapfunction %address-of ((arg arg_z))
+  ;; %address-of a fixnum is a fixnum, just for spite.
+  ;; %address-of anything else is the address of that thing as an integer.
+  (clrldi. imm0 arg (- 64 ppc64::nlisptagbits))
+  (beqlr cr0)
+  (mr imm0 arg_z)
+  ;; set cr0_eq if result fits in a fixnum
+  (clrrdi. imm1 imm0 (- ppc64::least-significant-bit ppc64::nfixnumtagbits))
+  (box-fixnum arg_z imm0)               ; assume it did
+  (beqlr+ cr0)                          ; else arg_z tagged ok, but missing bits
+  (ba .SPmakeu64)         ; put all bits in bignum.
+)
+
+;;; "areas" are fixnum-tagged and, for the most part, so are their
+;;; contents.
+
+;;; The nilreg-relative global all-areas is a doubly-linked-list header
+;;; that describes nothing.  Its successor describes the current/active
+;;; dynamic heap.  Return a fixnum which "points to" that area, after
+;;; ensuring that the "active" pointers associated with the current thread's
+;;; stacks are correct.
+
+
+
+(defppclapfunction %normalize-areas ()
+  (let ((address imm0)
+        (temp imm2))
+
+    ; update active pointer for tsp area.
+    (ldr address target::tcr.ts-area target::rcontext)
+    (str tsp target::area.active address)
+    
+    ;; Update active pointer for vsp area.
+    (ldr address target::tcr.vs-area target::rcontext)
+    (str vsp target::area.active address)
+    
+    ; Update active pointer for SP area
+    (ldr arg_z target::tcr.cs-area target::rcontext)
+    (str sp target::area.active arg_z)
+
+
+    (ref-global arg_z all-areas)
+    (ldr arg_z target::area.succ arg_z)
+
+    (blr)))
+
+(defppclapfunction %active-dynamic-area ()
+  (ref-global arg_z all-areas)
+  (ldr arg_z target::area.succ arg_z)
+  (blr))
+
+  
+(defppclapfunction %object-in-stack-area-p ((object arg_y) (area arg_z))
+  (ldr imm0 target::area.active area)
+  (cmplr cr0 object imm0)
+  (ldr imm1 target::area.high area)
+  (cmplr cr1 object imm1)
+  (li arg_z nil)
+  (bltlr cr0)
+  (bgelr cr1)
+  (la arg_z target::t-offset arg_z)
+  (blr))
+
+(defppclapfunction %object-in-heap-area-p ((object arg_y) (area arg_z))
+  (ldr imm0 target::area.low area)
+  (cmplr cr0 object imm0)
+  (ldr imm1 target::area.active area)
+  (cmplr cr1 object imm1)
+  (li arg_z nil)
+  (bltlr cr0)
+  (bgelr cr1)
+  (la arg_z target::t-offset arg_z)
+  (blr))
+
+
+#+ppc32-target
+(defppclapfunction walk-static-area ((a arg_y) (f arg_z))
+  (let ((fun save0)
+        (obj save1)
+        (limit save2)
+        (header imm0)
+        (tag imm1)
+        (subtag imm2)
+        (bytes imm3)
+        (elements imm0))
+    (save-lisp-context)
+    (:regsave limit 0)
+    (vpush fun)
+    (vpush obj)
+    (vpush limit)
+    (mr fun f)
+    (lwz limit ppc32::area.active a)
+    (lwz obj ppc32::area.low a)
+    (b @test)
+    @loop
+    (lwz header 0 obj)
+    (extract-fulltag tag header)
+    (cmpwi cr0 tag ppc32::fulltag-immheader)
+    (cmpwi cr1 tag ppc32::fulltag-nodeheader)
+    (beq cr0 @misc)
+    (beq cr1 @misc)
+    (la arg_z ppc32::fulltag-cons obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (bla .SPFuncall)
+    (la obj ppc32::cons.size obj)
+    (b @test)
+    @misc
+    (la arg_z ppc32::fulltag-misc obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (bla .SPFuncall)
+    (lwz header 0 obj)
+    (extract-fulltag tag header)
+    (cmpwi cr1 tag ppc32::fulltag-nodeheader)
+    (clrlwi subtag header (- 32 ppc32::num-subtag-bits))
+    (cmpwi cr2 subtag ppc32::max-32-bit-ivector-subtag)
+    (cmpwi cr3 subtag ppc32::max-8-bit-ivector-subtag)
+    (cmpwi cr4 subtag ppc32::max-16-bit-ivector-subtag)
+    (cmpwi cr5 subtag ppc32::subtag-double-float-vector)
+    (header-size elements header)
+    (slwi bytes elements 2)
+    (beq cr1 @bump)
+    (ble cr2 @bump)
+    (mr bytes elements)
+    (ble cr3 @bump)
+    (slwi bytes elements 1)
+    (ble cr4 @bump)
+    (slwi bytes elements 3)
+    (beq cr5 @bump)
+    (la elements 7 elements)
+    (srwi bytes elements 3)
+    @bump
+    (la bytes (+ 4 7) bytes)
+    (clrrwi bytes bytes 3)
+    (add obj obj bytes)
+    @test
+    (cmplw :cr0 obj limit)
+    (blt cr0 @loop)
+    (vpop limit)
+    (vpop obj)
+    (vpop fun)
+    (restore-full-lisp-context)
+    (blr)))
+
+#+ppc64-target
+(defppclapfunction walk-static-area ((a arg_y) (f arg_z))
+  (let ((fun save0)
+        (obj save1)
+        (limit save2)
+        (header imm0)
+        (tag imm1)
+        (subtag imm2)
+        (bytes imm3)
+        (elements imm0))
+    (save-lisp-context)
+    (:regsave limit 0)
+    (vpush fun)
+    (vpush obj)
+    (vpush limit)
+    (mr fun f)
+    (ld limit ppc64::area.active a)
+    (ld obj ppc64::area.low a)
+    (b @test)
+    @loop
+    (ld header 0 obj)
+    (extract-lowtag tag header)
+    (cmpri cr0 tag ppc64::lowtag-immheader)
+    (cmpri cr1 tag ppc64::lowtag-nodeheader)
+    (beq cr0 @misc)
+    (beq cr1 @misc)
+    (la arg_z ppc64::fulltag-cons obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (bla .SPFuncall)
+    (la obj ppc64::cons.size obj)
+    (b @test)
+    @misc
+    (la arg_z ppc64::fulltag-misc obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (bla .SPFuncall)
+    (ldr header 0 obj)
+    (extract-lowtag tag header)
+    (extract-fulltag subtag header)
+    (cmpri cr1 tag ppc64::lowtag-nodeheader)
+    (extract-lowbyte tag header)
+    (cmpri cr2 subtag ppc64::ivector-class-64-bit)
+    (cmpri cr3 subtag ppc64::ivector-class-8-bit)
+    (cmpri cr4 subtag ppc64::ivector-class-32-bit)
+    (cmpri cr5 tag ppc64::subtag-bit-vector)
+    (header-size elements header)
+    (sldi bytes elements 3)
+    (beq cr1 @bump)
+    (beq cr2 @bump)
+    (mr bytes elements)
+    (beq cr3 @bump)
+    (sldi bytes elements 2)
+    (beq cr4 @bump)
+    (sldi bytes elements 1)
+    (bne cr5 @bump)
+    (la elements 7 elements)
+    (srdi bytes elements 3)
+    @bump
+    (la bytes (+ 8 15) bytes)
+    (clrrdi bytes bytes 4)
+    (add obj obj bytes)
+    @test
+    (cmpld :cr0 obj limit)
+    (blt cr0 @loop)
+    (vpop limit)
+    (vpop obj)
+    (vpop fun)
+    (restore-full-lisp-context)
+    (blr)))
+
+;;; This walks the active "dynamic" area.  Objects might be moving around
+;;; while we're doing this, so we have to be a lot more careful than we 
+;;; are when walking a static area.
+;;; There's the vague notion that we can't take an interrupt when
+;;; "initptr" doesn't equal "freeptr", though what kind of hooks into a
+;;; preemptive scheduler we'd need to enforce this is unclear.  We use
+;;; initptr as an untagged pointer here (and set it to freeptr when we've
+;;; got a tagged pointer to the current object.)
+;;; There are a couple of approaches to termination:
+;;;  a) Allocate a "sentinel" cons, and terminate when we run into it.
+;;;  b) Check the area limit (which is changing if we're consing) and
+;;;     terminate when we hit it.
+;;; (b) loses if the function conses.  (a) conses.  I can't think of anything
+;;; better than (a).
+;;; This, of course, assumes that any GC we're doing does in-place compaction
+;;; (or at least preserves the relative order of objects in the heap.)
+
+#+ppc32-target
+(defppclapfunction %walk-dynamic-area ((a arg_y) (f arg_z))
+  (let ((fun save0)
+        (obj save1)
+        (sentinel save2)
+        (header imm0)
+        (tag imm1)
+        (subtag imm2)
+        (bytes imm3)
+        (elements imm4))
+    (save-lisp-context)
+    (:regsave sentinel 0)
+    (vpush fun)
+    (vpush obj)
+    (vpush sentinel)
+    (ref-global imm0 tenured-area)
+    (cmpwi cr0 imm0 0)
+    (li allocbase #xfff8)
+    (la allocptr (- ppc32::fulltag-cons ppc32::cons.size) allocptr)
+    (twllt allocptr allocbase)
+    (mr sentinel allocptr)
+    (clrrwi allocptr allocptr ppc32::ntagbits)
+    (mr fun f)
+    (if :ne
+      (mr a imm0))    
+    (lwz imm5 ppc32::area.low a)
+    @loop
+    (lwz header 0 imm5)
+    (extract-fulltag tag header)
+    (cmpwi cr0 tag ppc32::fulltag-immheader)
+    (cmpwi cr1 tag ppc32::fulltag-nodeheader)
+    (beq cr0 @misc)
+    (beq cr1 @misc)
+    (la obj ppc32::fulltag-cons imm5)
+    (cmpw cr0 obj sentinel)
+    (mr arg_z obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (beq cr0 @done)
+    (bla .SPfuncall)
+    (la imm5 (- ppc32::cons.size ppc32::fulltag-cons) obj)
+    (b @loop)
+    @misc
+    (la obj ppc32::fulltag-misc imm5)
+    (mr arg_z obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (bla .SPFuncall)
+    (getvheader header obj)
+    (extract-fulltag tag header)
+    (cmpwi cr1 tag ppc32::fulltag-nodeheader)
+    (cmpwi cr7 tag ppc32::fulltag-immheader)
+    (clrlwi subtag header (- 32 ppc32::num-subtag-bits))
+    (cmpwi cr2 subtag ppc32::max-32-bit-ivector-subtag)
+    (cmpwi cr3 subtag ppc32::max-8-bit-ivector-subtag)
+    (cmpwi cr4 subtag ppc32::max-16-bit-ivector-subtag)
+    (cmpwi cr5 subtag ppc32::subtag-double-float-vector)
+    (header-size elements header)
+    (slwi bytes elements 2)
+    (beq cr1 @bump)
+    (if (:cr7 :ne)
+      (twle 0 0))
+    (ble cr2 @bump)
+    (mr bytes elements)
+    (ble cr3 @bump)
+    (slwi bytes elements 1)
+    (ble cr4 @bump)
+    (slwi bytes elements 3)
+    (beq cr5 @bump)
+    (la elements 7 elements)
+    (srwi bytes elements 3)
+    @bump
+    (la bytes (+ 4 7) bytes)
+    (clrrwi bytes bytes 3)
+    (subi imm5 obj ppc32::fulltag-misc)
+    (add imm5 imm5 bytes)
+    (cmpw cr0 imm5  sentinel)
+    (blt cr0 @loop)
+    (uuo_interr 0 0)
+    (b @loop)
+    @done
+    (li arg_z nil)
+    (vpop sentinel)
+    (vpop obj)
+    (vpop fun)
+    (restore-full-lisp-context)
+    (blr)))
+
+#+ppc64-target
+(defppclapfunction %walk-dynamic-area ((a arg_y) (f arg_z))
+  (let ((fun save0)
+        (obj save1)
+        (sentinel save2)
+        (header imm0)
+        (tag imm1)
+        (subtag imm2)
+        (bytes imm3)
+        (elements imm4))
+    (save-lisp-context)
+    (:regsave sentinel 0)
+    (vpush fun)
+    (vpush obj)
+    (vpush sentinel)
+    (ref-global imm0 tenured-area)
+    (cmpdi cr0 imm0 0)
+    (lwi allocbase #x8000)
+    (sldi allocbase allocbase 32)
+    (subi allocbase allocbase 16)
+    (la allocptr (- ppc64::fulltag-cons ppc64::cons.size) allocptr)
+    (tdlt allocptr allocbase)
+    (mr sentinel allocptr)
+    (clrrdi allocptr allocptr ppc64::ntagbits)
+    (mr fun f)
+    (if :ne
+      (mr a imm0))    
+    (ld imm5 ppc64::area.low a)
+    @loop
+    (ld header 0 imm5)
+    (extract-lowtag tag header)
+    (cmpdi cr0 tag ppc64::lowtag-immheader)
+    (cmpdi cr1 tag ppc64::lowtag-nodeheader)
+    (beq cr0 @misc)
+    (beq cr1 @misc)
+    (la obj ppc64::fulltag-cons imm5)
+    (cmpd cr0 obj sentinel)
+    (mr arg_z obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (beq cr0 @done)
+    (bla .SPfuncall)
+    (la imm5 (- ppc64::cons.size ppc64::fulltag-cons) obj)
+    (b @loop)
+    @misc
+    (la obj ppc64::fulltag-misc imm5)
+    (mr arg_z obj)
+    (set-nargs 1)
+    (mr temp0 fun)
+    (bla .SPFuncall)
+    (getvheader header obj)
+    (extract-lowtag tag header)    
+    (extract-fulltag subtag header)
+    (cmpdi cr1 tag ppc64::lowtag-nodeheader)
+    (extract-lowbyte tag header)
+    (cmpri cr2 subtag ppc64::ivector-class-64-bit)
+    (cmpri cr3 subtag ppc64::ivector-class-8-bit)
+    (cmpri cr4 subtag ppc64::ivector-class-32-bit)
+    (cmpri cr5 tag ppc64::subtag-bit-vector)
+    (header-size elements header)
+    (sldi bytes elements 3)
+    (beq cr1 @bump)
+    (beq cr2 @bump)
+    (mr bytes elements)
+    (beq cr3 @bump)
+    (sldi bytes elements 2)
+    (beq cr4 @bump)
+    (sldi bytes elements 1)
+    (bne cr5 @bump)
+    (la elements 7 elements)
+    (srdi bytes elements 3)
+    @bump
+    (la bytes (+ 8 15) bytes)
+    (clrrdi bytes bytes 4)
+    (subi imm5 obj ppc64::fulltag-misc)
+    (add imm5 imm5 bytes)
+    (b @loop)
+    @done
+    (li arg_z nil)
+    (vpop sentinel)
+    (vpop obj)
+    (vpop fun)
+    (restore-full-lisp-context)
+    (blr)))
+
+(defun walk-dynamic-area (area func)
+  (with-other-threads-suspended
+      (%walk-dynamic-area area func)))
+
+
+
+(defppclapfunction %class-of-instance ((i arg_z))
+  (svref arg_z instance.class-wrapper i)
+  (svref arg_z %wrapper-class arg_z)
+  (blr))
+
+(defppclapfunction class-of ((x arg_z))
+  (check-nargs 1)
+  (extract-fulltag imm0 x)
+  (cmpri imm0 target::fulltag-misc)
+  (beq @misc)
+  (extract-lowbyte imm0 x)
+  (b @done)
+  @misc
+  (extract-subtag imm0 x)
+  @done
+  (slri imm0 imm0 target::word-shift)
+  (ldr temp1 '*class-table* nfn)
+  (addi imm0 imm0 target::misc-data-offset)
+  (ldr temp1 target::symbol.vcell temp1)
+  (ldrx temp0 temp1 imm0) ; get entry from table
+  (cmpri cr0 temp0 nil)
+  (beq @bad)
+  ;; functionp?
+  (extract-typecode imm1 temp0)
+  (cmpri imm1 target::subtag-function)
+  (bne @ret)  ; not function - return entry
+  ;; else jump to the fn
+  (mr nfn temp0)
+  (ldr temp0 target::misc-data-offset temp0)
+  (SET-NARGS 1)
+  (mtctr temp0)
+  (bctr)
+  @bad
+  (ldr fname 'no-class-error nfn)
+  (ba .spjmpsym)
+  @ret
+  (mr arg_z temp0)  ; return frob from table
+  (blr))
+
+(defppclapfunction full-gccount ()
+  (ref-global arg_z tenured-area)
+  (cmpri cr0 arg_z 0)
+  (if :eq
+    (ref-global arg_z gc-count)
+    (ldr arg_z target::area.gc-count arg_z))
+  (blr))
+
+
+(defppclapfunction gc ()
+  (check-nargs 0)
+  (li imm0 arch::gc-trap-function-gc)
+  (trlgei allocptr 0)
+  (li arg_z (target-nil-value))
+  (blr))
+
+
+(defppclapfunction egc ((arg arg_z))
+  "Enable the EGC if arg is non-nil, disables the EGC otherwise. Return
+the previous enabled status. Although this function is thread-safe (in
+the sense that calls to it are serialized), it doesn't make a whole lot
+of sense to be turning the EGC on and off from multiple threads ..."
+  (check-nargs 1)
+  (subi imm1 arg nil)
+  (li imm0 arch::gc-trap-function-egc-control)
+  (trlgei allocptr 0)
+  (blr))
+
+
+
+(defppclapfunction %configure-egc ((e0size arg_x)
+				   (e1size arg_y)
+				   (e2size arg_z))
+  (check-nargs 3)
+  (li imm0 arch::gc-trap-function-configure-egc)
+  (trlgei allocptr 0)
+  (blr))
+
+(defppclapfunction purify ()
+  (li imm0 arch::gc-trap-function-purify)
+  (trlgei allocptr 0)
+  (li arg_z nil)
+  (blr))
+
+
+(defppclapfunction impurify ()
+  (li imm0 arch::gc-trap-function-impurify)
+  (trlgei allocptr 0)
+  (li arg_z nil)
+  (blr))
+
+(defppclapfunction lisp-heap-gc-threshold ()
+  "Return the value of the kernel variable that specifies the amount
+of free space to leave in the heap after full GC."
+  (check-nargs 0)
+  (li imm0 arch::gc-trap-function-get-lisp-heap-threshold)
+  (trlgei allocptr 0)
+  #+ppc32-target
+  (ba .SPmakeu32)
+  #+ppc64-target
+  (ba .SPmakeu64))
+
+(defppclapfunction set-lisp-heap-gc-threshold ((new arg_z))
+  "Set the value of the kernel variable that specifies the amount of free
+space to leave in the heap after full GC to new-value, which should be a
+non-negative fixnum. Returns the value of that kernel variable (which may
+be somewhat larger than what was specified)."
+  (check-nargs 1)
+  (mflr loc-pc)
+  #+ppc32-target
+  (bla .SPgetu32)
+  #+ppc64-target
+  (bla .SPgetu64)
+  (mtlr loc-pc)
+  (mr imm1 imm0)
+  (li imm0 arch::gc-trap-function-set-lisp-heap-threshold)
+  (trlgei allocptr 0)
+  #+ppc32-target
+  (ba .SPmakeu32)
+  #+ppc64-target
+  (ba .SPmakeu64))
+
+
+(defppclapfunction use-lisp-heap-gc-threshold ()
+  "Try to grow or shrink lisp's heap space, so that the free space is(approximately) equal to the current heap threshold. Return NIL"
+  (check-nargs 0) 
+  (li imm0 arch::gc-trap-function-use-lisp-heap-threshold)
+  (trlgei allocptr 0)
+  (li arg_z nil)
+  (blr))
+
+
+(defppclapfunction freeze ()
+  "Do a full GC, then consider all heap-allocated objects which survive to be non-relocatable."
+  (check-nargs 0)
+  (li imm0 arch::gc-trap-function-freeze)
+  (trlgei allocptr 0)
+  #+64-bit-target
+  (ba .SPmakeu64)
+  #+32-bit-target
+  (ba .SPmakeu32))
+
+(defppclapfunction flash-freeze ()
+  "Like FREEZE, but don't GC first."
+  (check-nargs 0)
+  (li imm0 arch::gc-trap-function-flash-freeze)
+  (trlgei allocptr 0)
+  #+64-bit-target
+  (ba .SPmakeu64)
+  #+32-bit-target
+  (ba .SPmakeu32))
+
+(defun %watch (uvector)
+  (declare (ignore uvector))
+  (error "watching objects not supported on PPC yet"))
+
+(defun %unwatch (watched new)
+  (declare (ignore watched new))
+  (error "watching objects not supported on PPC yet"))
+
+;;; Make a list.  This can be faster than doing so by doing CONS
+;;; repeatedly, since the latter strategy might triger the GC several
+;;; times if N is large.
+(defppclapfunction %allocate-list ((initial-element arg_y) (nconses arg_z))
+  (check-nargs 2)
+  (save-lisp-context)
+  (uuo_interr arch::error-allocate-list rzero)
+  (vpush arg_z)
+  (vpush arg_y)
+  (set-nargs 2)
+  (ba .SPnvalret))
+  
+(defppclapfunction %ensure-static-conses ()
+  (check-nargs 0)
+  (li imm0 arch::gc-trap-function-ensure-static-conses)
+  (trlgei allocptr 0)
+  (li arg_z nil)
+  (blr))
+
+;;; offset is a fixnum, one of the target::kernel-import-xxx constants.
+;;; Returns that kernel import, a fixnum.
+(defppclapfunction %kernel-import ((offset arg_z))
+  (ref-global imm0 kernel-imports)
+  (unbox-fixnum imm1 arg_z)
+  (ldrx arg_z imm0 imm1)
+  (blr))
+
+(defppclapfunction %get-unboxed-ptr ((macptr arg_z))
+  (macptr-ptr imm0 arg_z)
+  (ldr arg_z 0 imm0)
+  (blr))
+
+
+(defppclapfunction %revive-macptr ((p arg_z))
+  (li imm0 target::subtag-macptr)
+  (stb imm0 target::misc-subtag-offset p)
+  (blr))
+
+(defppclapfunction %macptr-type ((p arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= p target::subtag-macptr)
+  (svref imm0 target::macptr.type-cell p)
+  (box-fixnum arg_z imm0)
+  (blr))
+  
+(defppclapfunction %macptr-domain ((p arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= p target::subtag-macptr)
+  (svref imm0 target::macptr.domain-cell p)
+  (box-fixnum arg_z imm0)
+  (blr))
+
+(defppclapfunction %set-macptr-type ((p arg_y) (new arg_z))
+  (check-nargs 2)
+  (unbox-fixnum imm1 new)
+  (trap-unless-typecode= p target::subtag-macptr)
+  (svset imm1 target::macptr.type-cell p)
+  (blr))
+
+(defppclapfunction %set-macptr-domain ((p arg_y) (new arg_z))
+  (check-nargs 2)
+  (unbox-fixnum imm1 new)
+  (trap-unless-typecode= p target::subtag-macptr)
+  (svset imm1 target::macptr.domain-cell p)
+  (blr))
+
+(defppclapfunction true ()
+  (cmplri nargs '3)
+  (li arg_z t)
+  (blelr)
+  (subi imm0 nargs '3)
+  (add vsp vsp imm0)
+  (blr))
+
+(defppclapfunction false ()
+  (cmplri nargs '3)
+  (li arg_z nil)
+  (blelr)
+  (subi imm0 nargs '3)
+  (add vsp vsp imm0)
+  (blr))
+
+(lfun-bits #'true #.(encode-lambda-list '(&lap &rest ignore)))
+(lfun-bits #'false #.(encode-lambda-list '(&lap &rest ignore)))
+
+;;; end
Index: /branches/new-random/level-0/X86/.cvsignore
===================================================================
--- /branches/new-random/level-0/X86/.cvsignore	(revision 13309)
+++ /branches/new-random/level-0/X86/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*fsl
+*~.*
Index: /branches/new-random/level-0/X86/X8632/x8632-array.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-array.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-array.lisp	(revision 13309)
@@ -0,0 +1,242 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "X8632-ARCH")
+  (require "X86-LAPMACROS"))
+
+;; rewrite in LAP someday (soon).
+(defun %init-misc (val uvector)
+  (dotimes (i (uvsize uvector) uvector)
+    (setf (uvref uvector i) val)))
+
+;;; Make a new vector of size newsize whose subtag matches that of oldv-arg.
+;;; Blast the contents of the old vector into the new one as quickly as
+;;; possible; leave remaining elements of new vector undefined (0).
+;;; Return new-vector.
+(defun %extend-vector (start oldv newsize)
+  (declare (fixnum start))
+  (let* ((new (%alloc-misc newsize (typecode oldv)))
+         (oldsize (uvsize oldv)))
+    (declare (fixnum oldsize))
+    (do* ((i 0 (1+ i))
+          (j start (1+ j)))
+         ((= i oldsize) new)
+      (declare (fixnum i j))
+      (setf (uvref new j) (uvref oldv i)))))
+    
+;;; argument is a vector header or an array header.  Or else.
+(defx8632lapfunction %array-header-data-and-offset ((a arg_z))
+  (let ((offset arg_y)
+        (temp temp1))
+    (movl (% esp) (% temp0))
+    (movl ($ '0) (%l offset))
+    (movl (% a) (% temp))
+    @loop
+    (movl (@ target::arrayH.data-vector (% temp)) (% a))
+    (extract-subtag a imm0)
+    (addl (@ target::arrayH.displacement (% temp)) (% offset))
+    (rcmp (% imm0) ($ target::subtag-vectorH))
+    (movl (% a) (% temp))
+    (jle @loop)
+    (push (% a))
+    (push (% offset))
+    (set-nargs 2)
+    (jmp-subprim  .SPvalues)))
+
+(defx8632lapfunction %boole-clr ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl ($ 0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-set ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl ($ -1) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-1 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-2 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-c1 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-c2 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-and ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (andl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-ior ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (orl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-xor ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (xorl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-eqv ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (xorl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-nand ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (andl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-nor ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (orl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-andc1 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (andl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-andc2 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (andl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-orc1 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (orl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defx8632lapfunction %boole-orc2 ((idx 8) (b0 4) #|(ra 0)|# (b1 arg_y) (dest arg_z))
+  (movl (@ idx (% esp)) (% temp0))
+  (movl (@ b0 (% esp)) (% temp1))
+  (movl (@ x8632::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notl (% imm0))
+  (orl (@ x8632::misc-data-offset (% temp1) (% temp0)) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 4))
+
+(defparameter *simple-bit-boole-functions* ())
+
+(setq *simple-bit-boole-functions*
+      (vector
+       #'%boole-clr
+       #'%boole-set
+       #'%boole-1
+       #'%boole-2
+       #'%boole-c1
+       #'%boole-c2
+       #'%boole-and
+       #'%boole-ior
+       #'%boole-xor
+       #'%boole-eqv
+       #'%boole-nand
+       #'%boole-nor
+       #'%boole-andc1
+       #'%boole-andc2
+       #'%boole-orc1
+       #'%boole-orc2))
+
+(defun %simple-bit-boole (op b1 b2 result)
+  (let* ((f (svref *simple-bit-boole-functions* op)))
+    (dotimes (i (ash (the fixnum (+ (length result) 31)) -5) result)
+      (funcall f i b1 b2 result))))
+
+(defx8632lapfunction %aref2 ((array 4) #|(ra 0)|# (i arg_y) (j arg_z))
+  (check-nargs 3)
+  (popl (@ 8 (% esp)))			;ra to first word of reserved frame
+  (pop (% temp0))
+  (addl ($ '1) (% esp))			;discard other word of reserved frame
+  (jmp-subprim .SParef2))
+
+(defx8632lapfunction %aref3 ((array 8) (i 4) #|(ra 0)|# (j arg_y) (k arg_z))
+  (check-nargs 4)
+  (popl (@ 12 (% esp)))
+  (pop (% temp0))
+  (pop (% temp1))
+  (addl ($ '1) (% esp))
+  (jmp-subprim .SParef3))
+
+(defx8632lapfunction %aset2 ((array 8) (i 4) #|(ra 0)|# (j arg_y) (newval arg_z))
+  (check-nargs 4)
+  (popl (@ 12 (% esp)))
+  (pop (% temp0))
+  (pop (% temp1))
+  (addl ($ '1) (% esp))
+  (jmp-subprim .SPaset2))
+
+;;; We're out of registers.  Put i on the stack.
+(defx8632lapfunction %aset3 ((array 12) (i 8) (j 4) #|(ra 0)|# (k arg_y) (newval arg_z))
+  (check-nargs 5)
+  (popl (@ 16 (% esp)))
+  (pop (% temp0))
+  (popl (@ 4 (% esp)))
+  (pop (% temp1))
+  (jmp-subprim .SPaset3))
+
Index: /branches/new-random/level-0/X86/X8632/x8632-bignum.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-bignum.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-bignum.lisp	(revision 13309)
@@ -0,0 +1,1170 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; %BIGNUM-REF needs to access bignums as obviously as possible, and it needs
+;;; to be able to return 32 bits somewhere no one looks for real objects.
+;;;
+;;; The easiest thing to do is to store the 32 raw bits in two fixnums
+;;; and return multiple values.
+;;;
+(defx8632lapfunction %bignum-ref ((bignum arg_y) (i arg_z))
+  (movl (% esp) (% temp0))		;ptr to return addr on stack in temp0
+  (movzwl (@ (+ 2 x8632::misc-data-offset) (% bignum) (% i)) (% imm0))
+  (box-fixnum imm0 temp1)
+  (push (% temp1))			;high
+  (movzwl (@ x8632::misc-data-offset (% bignum) (% i)) (% imm0))
+  (box-fixnum imm0 temp1)
+  (push (% temp1))			;low
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+
+(defx8632lapfunction %bignum-ref-hi ((bignum arg_y) (i arg_z))
+  (movzwl (@ (+ 2 x8632::misc-data-offset) (% bignum) (% i)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+;;; BIGNUM[I] := DIGIT[0]
+(defx8632lapfunction %set-digit ((bignum 4) #|(ra 0)|# (i arg_y) (digit arg_z))
+  (movl (@ bignum (% esp)) (% temp0))
+  (svref digit 0 imm0)
+  (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% i)))
+  (single-value-return 3))
+
+;;; Return the sign of bignum (0 or -1) as a fixnum
+(defx8632lapfunction %bignum-sign ((bignum arg_z))
+  (vector-length bignum imm0)
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
+  (sarl ($ 31) (% imm0))		;propagate sign bit
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+;;; Count the sign bits in the most significant digit of bignum;
+;;; return fixnum count.
+(defx8632lapfunction %bignum-sign-bits ((bignum arg_z))
+  (vector-length bignum imm0)
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
+  (mark-as-imm temp0)
+  (movl (% imm0) (% temp0))
+  (notl (% imm0))
+  (testl (% temp0) (% temp0))
+  (js @wasneg)
+  (notl (% imm0))
+  @wasneg
+  (bsrl (% imm0) (% imm0))
+  (sete (% temp0.b))
+  (xorl ($ 31) (% imm0))
+  (addb (% temp0.b) (% imm0.b))
+  (box-fixnum imm0 arg_z)
+  (mark-as-node temp0)
+  (single-value-return))
+
+(defx8632lapfunction %digit-0-or-plusp ((bignum arg_y) (idx arg_z))
+  (movl (@ x8632::misc-data-offset (% bignum) (% idx)) (% imm0))
+  (movl ($ (target-nil-value)) (% temp0))
+  (leal (@ x8632::t-offset (% temp0)) (% arg_z))
+  (testl (% imm0) (% imm0))
+  (cmovll (% temp0) (% arg_z))
+  (single-value-return))
+
+;;; For oddp, evenp
+(defx8632lapfunction %bignum-oddp ((bignum arg_z))
+  (movl (@ x8632::misc-data-offset (% bignum)) (% imm0))
+  (movl ($ (target-nil-value)) (% temp0))
+  (leal (@ x8632::t-offset (% temp0)) (% arg_z))
+  (testb ($ 1) (% imm0.b))
+  (cmovzl (% temp0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction bignum-plusp ((bignum arg_z))
+  (vector-length bignum imm0)
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (lea (@ x8632::t-offset (% arg_z)) (% temp0))
+  (testl (% imm0) (% imm0))
+  (cmovnsl (% temp0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction bignum-minusp ((bignum arg_z))
+  (vector-length bignum imm0)
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (lea (@ x8632::t-offset (% arg_z)) (% temp0))
+  (testl (% imm0) (% imm0))
+  (cmovsl (% temp0) (% arg_z))
+  (single-value-return))
+
+;;; Add the digits A[I] and B[J], and the incoming carry C (a fixnum,
+;;; either 0 or 1).  Store the result in R[K], and return the outgoing
+;;; carry.  If I is NIL, A is a fixnum.  If J is NIL, B is a fixnum.
+(defx8632lapfunction %add-with-carry ((r 20) (k 16) (c 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
+  (mark-as-imm temp0)
+  (unbox-fixnum b imm0)
+  (cmpl ($ (target-nil-value)) (% j))
+  ;; if j not nil, get b[j]
+  (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
+  (movl (@ a (% esp)) (% arg_y))
+  (unbox-fixnum arg_y temp0)
+  (movl (@ i (% esp)) (% arg_z))
+  (cmpl ($ (target-nil-value)) (% arg_z))
+  ;; if i not nil, get a[i]
+  (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% temp0))
+  (xorl (% arg_z) (% arg_z))
+  ;; I can't think of a better way to set CF at the moment.
+  ;; NEG would be ideal, but we don't have a free imm reg.
+  (btl ($ x8632::fixnumshift) (@ c (% esp))) ;CF = lsb of carry fixnum 
+  (adc (% temp0) (% imm0))
+  (setc (% arg_z.bh))
+  (sarl ($ (- 8 x8632::fixnumshift)) (% arg_z)) ;outgoing carry
+  (mark-as-node temp0)
+  (movl (@ r (% esp)) (% temp0))
+  (movl (@ k (% esp)) (% temp1))
+  (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
+  (single-value-return 7))
+
+;;; Add the digits A[I] and B[J], and the incoming carry C (a fixnum).
+;;; Store the result in R[K], and return the outgoing carry.  If I is
+;;; NIL, A is a fixnum.  If J is NIL, B is a fixnum.
+#+sse2
+(defx8632lapfunction %add-with-carry ((r 20) (k 16) (c 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
+  (let ((aa mm2)
+	(bb mm3)
+	(cc mm4))
+    (unbox-fixnum b imm0)		;assume j will be nil
+    (cmpl ($ (target-nil-value)) (% j))
+    ;; if j not nil, get b[j]
+    (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
+    (movd (% imm0) (% bb))
+    (movl (@ a (% esp)) (% arg_y))
+    (movl (@ i (% esp)) (% arg_z))
+    (movl (@ c (% esp)) (% temp0))
+    (unbox-fixnum arg_y imm0)		;assume i will be nil
+    (cmpl ($ (target-nil-value)) (% arg_z))
+    ;; if i not nil, get a[i]
+    (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% imm0))
+    (movd (% imm0) (% aa))
+    (unbox-fixnum temp0 imm0)
+    (movd (% imm0) (% cc))
+    (paddq (% xx) (% yy))
+    (paddq (% cc) (% yy))
+    (movl (@ r (% esp)) (% temp0))
+    (movl (@ k (% esp)) (% temp1))
+    (movd (% yy) (@ x8632::misc-data-offset (% temp0) (% temp1)))
+    (psrlq ($ 32) (% yy))		;carry bit
+    (movd (% yy) (% imm0))
+    (box-fixnum imm0 arg_z)
+    (single-value-return 7)))
+
+;;; Store the result of A[I] - B[J] - borrow into R[K], returning the borrow.
+;;; If I is NIL, A is a fixnum; likewise for J and B.
+;;;
+;;; (a - b) - (1 - borrow), or equivalently, (a - b) + borrow - 1
+;;; 
+;;; Note: borrow is 1 for no borrow and 0 for a borrow.
+(defx8632lapfunction %subtract-with-borrow ((r 20) (k 16) (borrow 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
+  (mark-as-imm temp0)
+  (unbox-fixnum b imm0)
+  (cmpl ($ (target-nil-value)) (% j))
+  (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
+  (movl (@ a (% esp)) (% arg_y))
+  (unbox-fixnum arg_y temp0)
+  (movl (@ i (% esp)) (% arg_z))
+  (cmpl ($ (target-nil-value)) (% arg_z))
+  (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% temp0))
+  ;; unboxed a or a[i] in temp0, unboxed b or b[j] in imm0
+  (cmpl ($ '1) (@ borrow (% esp)))	;CF = 1 if borrow is 0 else CF = 0
+  (sbb (% imm0) (% temp0))
+  (movl ($ 1) (% imm0))
+  (sbb ($ 0) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (movl (% temp0) (% imm0))
+  (mark-as-node temp0)
+  (movl (@ r (% esp)) (% temp0))
+  (movl (@ k (% esp)) (% temp1))
+  (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
+  (single-value-return 7))
+
+#+sse2
+(defx8632lapfunction %subtract-with-borrow ((r 20) (k 16) (borrow 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
+  (let ((aa mm2)
+	(bb mm3)
+	(ww mm4))
+    (unbox-fixnum b imm0)
+    (cmpl ($ (target-nil-value)) (% j))
+    ;; if j not nil, get b[j]
+    (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
+    (movd (% imm0) (% bb))
+    (movl (@ a (% esp)) (% arg_y))
+    (movl (@ i (% esp)) (% arg_z))
+    (movl (@ borrow (% esp)) (% temp0))
+    (unbox-fixnum arg_y imm0)
+    (cmpl ($ (target-nil-value)) (% arg_z))
+    ;; if i not nil, get a[i]
+    (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% imm0))
+    (movd (% imm0) (% aa))
+    (unbox-fixnum temp0 imm0)
+    (subl ($ 1) (% imm0))
+    (movd (% imm0) (% ww))
+    (psubq (% bb) (% aa))
+    (paddq (% ww) (% aa))
+    (movl (@ r (% esp)) (% temp0))
+    (movl (@ k (% esp)) (% temp1))
+    (movd (% aa) (@ x8632::misc-data-offset (% temp0) (% temp1)))
+    (psrlq ($ 32) (% aa))		;carry digit
+    (movd (% aa) (% imm0))
+    (xorl (% arg_z) (% arg_z))
+    (test ($ 1) (% imm0))
+    (cmovzl ($ '1) (% arg_z))
+    (single-value-return 7)))
+
+(defx8632lapfunction %subtract-one ((high arg_y) (low arg_z))
+  (shll ($ (- 16 x8632::fixnumshift)) (% arg_y))
+  (unbox-fixnum low imm0)
+  ;; high half should always be clear...
+  ;;(movzwl (% imm0.w) (% imm0))
+  (orl (% arg_y) (% imm0))
+  (decl (% imm0))
+  (movl (% esp) (% temp0))
+  ;; extract and push high half
+  (movl ($ (- #x10000)) (% arg_y))
+  (andl (% imm0) (% arg_y))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% arg_y))
+  (push (% arg_y))
+  ;; low half
+  (andl ($ #xffff) (% imm0))
+  (shll ($ x8632::fixnumshift) (% imm0))
+  (push (% imm0))
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+
+;;; %SUBTRACT-WITH-BORROW -- Internal.
+;;;
+;;; This should be in assembler, and should not cons intermediate results.  It
+;;; returns a 32bit digit and a borrow resulting from subtracting b from a, and
+;;; subtracting a possible incoming borrow.
+;;;
+;;; We really do:  a - b - 1 + borrow, where borrow is either 0 or 1.
+;;; 
+
+(defx8632lapfunction %subtract-with-borrow-1 ((a-h 12) (a-l 8) (b-h 4) #|(ra 0)|# (b-l arg_y) (borrow arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (unbox-fixnum b-l temp0)
+  (movl (@ b-h (% esp)) (% imm0))
+  (sarl ($ x8632::fixnumshift) (% imm0))
+  (shll ($ 16) (% imm0))
+  (orl (% imm0) (% temp0))		;b in temp0
+  (movl (@ a-l (% esp)) (% temp1))
+  (sarl ($ x8632::fixnumshift) (% temp1))
+  (movl (@ a-h (% esp)) (% imm0))
+  (sarl ($ x8632::fixnumshift) (% imm0))
+  (shll ($ 16) (% imm0))
+  (orl (% imm0) (% temp1))	    ;a in temp1
+
+  (unbox-fixnum borrow imm0)
+  (subl ($ 1) (% imm0))			;sets carry appropriately
+  (sbbl (% temp0) (% temp1))
+  (setae (%b imm0))			;resulting borrow (1 for no, 0 for yes)
+  (movzbl (%b imm0) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (movl (% temp1) (% imm0))
+  (andl ($ (- #x10000)) (% imm0))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% imm0))
+  (popl (% arg_y))			;return address
+  (addl ($ '5) (% esp))			;discard reserved frame & stack args
+  (pushl (% arg_y))
+  (push (% imm0))			;high
+  (andl ($ #xffff) (% temp1))
+  (box-fixnum temp1 imm0)
+  (mark-as-node temp0)
+  (mark-as-node temp1)
+  (push (% imm0))			;low
+  (push (% arg_z))			;borrow
+  (set-nargs 3)
+  (leal (@ '3 (% esp)) (% temp0))
+  (jmp-subprim .SPvalues))
+  
+
+;;; To normalize a bignum is to drop "trailing" digits which are
+;;; redundant sign information.  When return-fixnum-p is non-nil, make
+;;; the resultant bignum into a fixnum if it fits.
+(defx8632lapfunction %normalize-bignum-2 ((return-fixnum-p arg_y) (bignum arg_z))
+  (push (% return-fixnum-p))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (let ((len arg_y)
+	(sign temp0)
+	(next temp1))
+    (vector-length bignum len)
+    (cmpl ($ '1) (% len))
+    (jle @maybe-return-fixnum)
+    ;; Zero trailing sign digits.
+    (push (% len))
+    ;; next-to-last digit
+    (movl (@ (- x8632::misc-data-offset 8) (% bignum) (% len)) (% next))
+    ;; last digit
+    (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% len)) (% sign))
+    (jmp @test)
+    @loop
+    (subl ($ '1) (% len))
+    (movl ($ 0) (@ x8632::misc-data-offset (% bignum) (% len)))
+    (cmpl ($ '1) (% len))		;any more digits?
+    (je @adjust-length)
+    (movl (% next) (% sign))
+    ;; (bignum-ref bignum (- len 2))
+    (movl (@ (- x8632::misc-data-offset 8) (% bignum) (% len)) (% next))
+    @test
+    (movl (% next) (% imm0))
+    (sarl ($ 31) (% imm0))		;propagate sign bit
+    (xorl (% sign) (% imm0))		;whole digit only sign?
+    (jz @loop)
+    ;; New length now in len.
+    @adjust-length
+    (pop (% imm0))			;original length
+    (cmpl (% len) (% imm0))
+    ;; If the new length is the same as the original length, we know
+    ;; that the bignum is at least two digits long (because if it was
+    ;; shorter, we would have branched directly to
+    ;; @maybe-return-fixnum), and thus won't fit in a fixnum.
+    ;; Therefore, there's no need to do either of the tests at
+    ;; @maybe-return-fixnum.
+    (je @done)
+    (movl (% len) (% imm0))
+    (shll ($ (- x8632::num-subtag-bits x8632::fixnumshift)) (% imm0))
+    (movb ($ x8632::subtag-bignum) (% imm0.b))
+    (movl (% imm0) (@ x8632::misc-header-offset (% bignum)))
+    @maybe-return-fixnum
+    ;; could use SETcc here to avoid one branch
+    (cmpl ($ (target-nil-value)) (@ 0 (% esp))) ;return-fixnum-p
+    (je @done)
+    (cmpl ($ x8632::one-digit-bignum-header)
+	  (@ x8632::misc-header-offset (% bignum)))
+    (jne @done)
+    ;; Bignum has one digit.  If it fits in a fixnum, return a fixnum.
+    (movl (@ x8632::misc-data-offset (% bignum)) (% imm0))
+    (box-fixnum imm0 arg_y)
+    (unbox-fixnum arg_y temp0)
+    (cmpl (% temp0) (% imm0))
+    (cmovel (% arg_y) (% arg_z))
+    @done
+    (pop (% imm0))			;discard saved return-fixnum-p
+    (mark-as-node temp0)
+    (mark-as-node temp1)
+    (single-value-return)))
+
+;;; Multiply X[I] by the unboxed value of the (non-negative) fixnum Y;
+;;; add the incoming carry from CARRY[0] to the 64-bit product.  Store
+;;; the low word of the 64-bit sum in R[0] and the high word in
+;;; CARRY[0].
+(defx8632lapfunction %multiply-and-add ((r 12) (carry 8) (x 4) #|(ra 0)|# (i arg_y) (y arg_z))
+  (let ((xx mm2)
+	(yy mm3)
+	(cc mm4))
+    (movl (@ x (% esp)) (% imm0))
+    (movd (@ x8632::misc-data-offset (% imm0) (% i)) (% xx))
+    (unbox-fixnum y imm0)
+    (movd (% imm0) (% yy))
+    (pmuludq (% xx) (% yy))		;64 bit product
+    (movl (@ carry (% esp)) (% arg_y))
+    (movd (@ x8632::misc-data-offset (% arg_y)) (% cc))
+    (paddq (% cc) (% yy))		;add in 32 bit carry digit
+    (movl (@ r (% esp)) (% arg_z))
+    (movd (% yy) (@ x8632::misc-data-offset (% arg_z)))
+    (psrlq ($ 32) (% yy))
+    (movd (% yy) (@ x8632::misc-data-offset (% arg_y)))
+    (single-value-return 5)))
+
+;; multiply x[i] by y and add to result starting at digit i
+(defx8632lapfunction %multiply-and-add-harder-loop-2
+    ((x 12) (y 8) (r 4) #|(ra 0)|# (i arg_y) (ylen arg_z))
+  (let ((cc mm2)
+	(xx mm3)
+	(yy mm4)
+	(rr mm5)
+	(j imm0))
+    (movl (@ x (% esp)) (% temp0))
+    (movd (@ x8632::misc-data-offset (% temp0) (% i)) (% xx)) ;x[i]
+    (movl (@ y (% esp)) (% temp0))
+    (movl (@ r (% esp)) (% temp1))
+    (pxor (% cc) (% cc))
+    (xorl (% j) (% j))
+    @loop
+    (movd (@ x8632::misc-data-offset (% temp0) (% j)) (% yy)) ;y[j]
+    (pmuludq (% xx) (% yy))
+    ;; 64-bit product now in %yy
+    (movd (@ x8632::misc-data-offset (% temp1) (% i)) (% rr))
+    ;; add in digit from r[i]
+    (paddq (% yy) (% rr))
+    ;; add in carry
+    (paddq (% cc) (% rr))
+    (movd (% rr) (@ x8632::misc-data-offset (% temp1) (% i))) ;update r[i]
+    (movq (% rr) (% cc))
+    (psrlq ($ 32) (% cc))		;get carry digit into low word
+    (addl ($ '1) (% i))
+    (addl ($ '1) (% j))
+    (subl ($ '1) (% ylen))
+    (jg @loop)
+    (movd (% cc) (@ x8632::misc-data-offset (% temp1) (% i)))
+    (single-value-return 5)))
+
+;; this is silly  
+(defx8632lapfunction %add-the-carry ((high 4) #|(ra 0)|# (low arg_y) (c arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0)
+	(imm1.w temp0.w))
+    (pop (% temp1))
+    (popl (% imm1))			;high
+    (discard-reserved-frame)
+    (push (% temp1))
+    (shll ($ (- 16 x8632::fixnumshift)) (% temp0))
+    (unbox-fixnum low imm0)
+    (orl (% imm0) (% imm1))
+    (unbox-fixnum c imm0)
+    (addl (% imm0) (% imm1))
+    (movzwl (% imm1.w) (% imm0))
+    (box-fixnum imm0 temp1)
+    (sarl ($ 16) (% imm1))
+    (shll ($ x8632::fixnumshift) (% imm1))
+    (push (% imm1))			;high
+    (push (% temp1)))			;low
+  (mark-as-node temp0)
+  (set-nargs 2)
+  (leal (@ '2 (% esp)) (% temp0))
+  (jmp-subprim .SPvalues))
+
+(defx8632lapfunction %bignum-count-trailing-zero-bits ((bignum arg_z))
+  (let ((i arg_y)
+	(len temp0)
+	(zeros temp1))
+    (vector-length bignum temp0)
+    (xorl (% i) (% i))
+    (xorl (% zeros) (% zeros))
+    @loop
+    (movl (@ x8632::misc-data-offset (% bignum) (% i)) (% imm0))
+    (testl (% imm0) (% imm0))
+    (jnz @last)
+    (addl ($ '32) (% zeros))
+    (addl ($ '1) (% i))
+    (cmpl (% len) (% i))
+    (jb @loop)
+    @last
+    ;; now count zero bits in digit
+    (bsfl (% imm0) (% imm0))
+    (shll ($ x8632::fixnumshift) (% imm0))
+    (addl (% imm0) (% zeros))
+    (movl (% zeros) (% arg_z))
+    (single-value-return)))
+
+;;; dest[i] = (logand x[i] y[i])
+(defx8632lapfunction %bignum-logand ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
+  (let ((i temp0)
+	(xx temp1)
+	(yy arg_y))
+    (movl (@ idx (% esp)) (% i))
+    (movl (@ x (% esp)) (% xx))
+    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
+    (andl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
+    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
+    (single-value-return 4)))
+
+;;; dest[i] = (logandc1 x[i] y[i])
+(defx8632lapfunction %bignum-logandc1 ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
+  (let ((i temp0)
+	(xx temp1)
+	(yy arg_y))
+    (movl (@ idx (% esp)) (% i))
+    (movl (@ x (% esp)) (% xx))
+    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
+    (not (% imm0))
+    (andl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
+    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
+    (single-value-return 4)))
+
+;;; dest[i] = (logandc2 x[i] y[i])
+(defx8632lapfunction %bignum-logandc2 ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
+  (let ((i temp0)
+	(xx temp1)
+	(yy arg_y))
+    (movl (@ idx (% esp)) (% i))
+    (movl (@ x (% esp)) (% xx))
+    (movl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
+    (not (% imm0))
+    (andl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
+    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
+    (single-value-return 4)))
+
+;;; dest[i] = (logior x[i] y[i])
+(defx8632lapfunction %bignum-logior ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
+  (let ((i temp0)
+	(xx temp1)
+	(yy arg_y))
+    (movl (@ idx (% esp)) (% i))
+    (movl (@ x (% esp)) (% xx))
+    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
+    (orl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
+    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
+    (single-value-return 4)))
+
+;;; dest[i] = (lognot x[i])
+(defx8632lapfunction %bignum-lognot ((idx 4) #|(ra 0)|# (x arg_y) (dest arg_z))
+  (let ((i temp0))
+    (movl (@ idx (% esp)) (% i))
+    (movl (@ x8632::misc-data-offset (% x) (% i)) (% imm0))
+    (not (% imm0))
+    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
+    (single-value-return 3)))
+
+;;; dest[i] = (logxor x[i] y[i])
+(defx8632lapfunction %bignum-logxor ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
+  (let ((i temp0)
+	(xx temp1)
+	(yy arg_y))
+    (movl (@ idx (% esp)) (% i))
+    (movl (@ x (% esp)) (% xx))
+    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
+    (xorl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
+    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
+    (single-value-return 4)))
+
+;;; 0 if a[i] = b[i]; 1 if a[i] > b[i]; -1 if a[i] < b[i]
+(defx8632lapfunction %compare-digits ((a 4) #|(ra 0)|# (b arg_y) (i arg_z))
+  (movl (@ a (% esp)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% temp0) (% i)) (% imm0))
+  (movl ($ '1) (% temp0))
+  (movl ($ '-1) (% temp1))
+  (subl (@ x8632::misc-data-offset (% b) (% i)) (% imm0))
+  (cmoval (% temp0) (% imm0))
+  (cmovbl (% temp1) (% imm0))
+  (movl (% imm0) (% arg_z))
+  (single-value-return 3))
+
+;; returns number of bits in digit-hi,digit-lo that are sign bits
+;; 32 - digits-sign-bits is integer-length
+(defx8632lapfunction %digits-sign-bits ((hi arg_y) (lo arg_z))
+  (mark-as-imm temp0)
+  (shll ($ (- 16 x8632::fixnumshift)) (% hi))
+  (unbox-fixnum lo imm0)
+  (orl (% hi) (% imm0))
+  (movl (% imm0) (% temp0))
+  (not (% imm0))
+  (testl (% temp0) (% temp0))
+  (js @wasneg)
+  (not (% imm0))
+  @wasneg
+  (bsrl (% imm0) (% imm0))
+  (sete (% temp0.b))
+  (xorl ($ 31) (% imm0))
+  (addb (% temp0.b) (% imm0.b))
+  (box-fixnum imm0 arg_z)
+  (mark-as-node temp0)
+  (single-value-return))
+
+(defx8632lapfunction macptr->fixnum ((ptr arg_z))
+  (macptr-ptr arg_z ptr)
+  (single-value-return))
+
+; if dest not nil store unboxed result in dest(0), else return a fixnum
+(defx8632lapfunction fix-digit-logandc2 ((fix 4) #|(ra 0)|# (big arg_y) (dest arg_z)) ; index 0
+  (mark-as-imm temp0)
+  (movl (@ fix (% esp)) (% temp0))
+  (unbox-fixnum temp0 temp0)
+  (movl (@ x8632::misc-data-offset (% big)) (% imm0))
+  (not (% imm0))
+  (andl (% temp0) (% imm0))
+  (mark-as-node temp0)
+  (cmpl ($ (target-nil-value)) (% dest))
+  (jne @store)
+  (box-fixnum imm0 arg_z)
+  (single-value-return 3)
+  @store
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest)))
+  (single-value-return 3))
+
+(defx8632lapfunction fix-digit-logandc1 ((fix 4) #|(ra 0)|# (big arg_y) (dest arg_z)) ; index 0
+  (mark-as-imm temp0)
+  (movl (@ fix (% esp)) (% temp0))
+  (unbox-fixnum temp0 temp0)
+  (movl (@ x8632::misc-data-offset (% big)) (% imm0))
+  (not (% temp0))
+  (andl (% temp0) (% imm0))
+  (mark-as-node temp0)
+  (cmpl ($ (target-nil-value)) (% dest))
+  (jne @store)
+  (box-fixnum imm0 arg_z)
+  (single-value-return 3)
+  @store
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest)))
+  (single-value-return 3))
+
+(defx8632lapfunction fix-digit-logand ((fix 4) #|(ra 0)|# (big arg_y) (dest arg_z)) ; index 0
+  (mark-as-imm temp0)
+  (movl (@ fix (% esp)) (% temp0))
+  (sarl ($ x8632::fixnumshift) (% temp0))
+  (movl (@ x8632::misc-data-offset (% big)) (% imm0))
+  (andl (% temp0) (% imm0))
+  (mark-as-node temp0)
+  (cmpl ($ (target-nil-value)) (% dest))
+  (jne @store)
+  (box-fixnum imm0 arg_z)
+  (single-value-return 3)
+  @store
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest)))
+  (single-value-return 3))
+
+
+(defx8632lapfunction digit-lognot-move ((index 4) #|(ra 0)|# (source arg_y) (dest arg_z))
+  (movl (@ index (% esp)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% source) (% temp0)) (% imm0))
+  (not (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+;; Add b to a starting at a[i]
+;; might want not to use SSE2 for this.  use lea to update loop counter
+;; variables so that the flags don't get set.
+(defx8632lapfunction bignum-add-loop-+ ((i 8) (a 4) #|(ra 0)|# (b arg_y) (blen arg_z))
+  (let ((aa mm2)
+	(bb mm3)
+	(cc mm4))
+    (movl (@ a (% esp)) (% temp0))
+    (movl (@ i (% esp)) (% temp1))
+    (xorl (% imm0) (% imm0))
+    (pxor (% cc) (% cc))
+    @loop
+    (movd (@ x8632::misc-data-offset (% temp0) (% temp1)) (% aa))
+    (movd (@ x8632::misc-data-offset (% b) (% imm0)) (% bb))
+    (paddq (% bb) (% aa))
+    (paddq (% cc) (% aa))
+    (movd (% aa) (@ x8632::misc-data-offset (% temp0) (% temp1)))
+    (psrlq ($ 32) (% aa))
+    (movq (% aa) (% cc))
+    (addl ($ '1) (% temp1))
+    (addl ($ '1) (% imm0))
+    (subl ($ '1) (% blen))
+    (jg @loop)
+    ;; add in final carry
+    (movd (% cc) (% imm0))
+    (addl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
+    (single-value-return 4)))
+
+(defx8632lapfunction bignum-logtest-loop ((count 4) #|(ra 0)|# (s1 arg_y) (s2 arg_z))
+  (let ((i temp1)
+	(c temp0))
+    (movl (@ count (% esp)) (% c))
+    (xorl (% i) (% i))
+    @loop
+    (movl (@ x8632::misc-data-offset (% s1) (% i)) (% imm0))
+    (test (@ x8632::misc-data-offset (% s2) (% i)) (% imm0))
+    (jnz @true)
+    (addl ($ '1) (% i))
+    (cmpl (% i) (% c))
+    (jg @loop)
+    (movl ($ (target-nil-value)) (% arg_z))
+    (single-value-return 3)
+    @true
+    (movl ($ (target-t-value)) (% arg_z))
+    (single-value-return 3)))
+
+;;; shift bignum left by nbits bits (1 <= nbits < 32)
+;;; start storing into result at digit j
+(defx8632lapfunction bignum-shift-left-loop ((nbits 12) (result 8)
+					     (bignum 4) #|(ra 0)|#
+					     (res-len-1 arg_y) (j arg_z))
+  (movl (% ebp) (@ 16 (% esp)))
+  (leal (@ 16 (% esp)) (% ebp))
+  (popl (@ 4 (% ebp)))
+  (push (% arg_y))			;ebp - 16
+  (push (% arg_z))			;ebp - 20
+
+  (movl (@ -4 (% ebp)) (% imm0))
+  (sarl ($ x8632::fixnumshift) (% imm0))
+  (movd (% imm0) (% mm7))		;shift count
+  (negl (% imm0))
+  (addl ($ 32) (% imm0))
+  (movd (% imm0) (% mm6))		;remaining bits
+
+  (let ((rl-1 -16)
+	(r temp0)
+	(b temp1)
+	(i arg_y)
+	(i+1 imm0))
+    (movl (@ -8 (% ebp)) (% r))
+    (movl (@ -12 (% ebp)) (% b))
+    (xorl (% i) (% i))
+    (movl ($ '1) (% i+1))
+    ;; j (in arg_z) is already (1+ digits)
+    (jmp @test)
+    @loop
+    (movd (@ x8632::misc-data-offset (% b) (% i)) (% mm0))
+    (psrlq (% mm6) (% mm0))
+    (movd (@ x8632::misc-data-offset (% b) (% i+1)) (% mm1))
+    (psllq (% mm7) (% mm1))
+    (por (% mm1) (% mm0))
+    (movd (% mm0) (@ x8632::misc-data-offset (% r) (% j)))
+    (movl (% i+1) (% i))
+    (addl ($ '1) (% i+1))
+    (addl ($ '1) (% j))
+    @test
+    (cmpl (@ rl-1 (% ebp)) (% j))
+    (jne @loop)
+    (movd (@ x8632::misc-data-offset (% b)) (% mm0))
+    (psllq (% mm7) (% mm0))
+    (movl (@ -20 (% ebp)) (% imm0))	;digits + 1 (that is, the original j)
+    (subl ($ '1) (% imm0))		;digits
+    (movd (% mm0) (@ x8632::misc-data-offset (% r) (% imm0)))
+    (movd (@ x8632::misc-data-offset (% b) (% i)) (% mm0))
+    (psrad (% mm6) (% mm0))
+    (movd (% mm0) (@ x8632::misc-data-offset (% r) (% j))))
+  (leave)
+  (ret))
+
+;;; shift bignum right by i words plus nbits bits.
+(defx8632lapfunction bignum-shift-right-loop-1 ((nbits 12) (result 8)
+						(bignum 4) #|(ra 0)|#
+						(res-len-1 arg_y)
+						(i arg_z))
+  (movl (@ nbits (% esp)) (% imm0))
+  (sarl ($ x8632::fixnumshift) (% imm0))
+  (movd (% imm0) (% mm7))		;shift count
+
+  (movl (@ result (% esp)) (% temp0))
+  (movl (@ bignum (% esp)) (% temp1))
+  (push (% res-len-1))
+  (xorl (% arg_y) (% arg_y))		;index into result
+  (jmp @test)
+  @loop
+  (movq (@ x8632::misc-data-offset (% temp1) (% i)) (% mm0)) ;b[i+1] || b[i]
+  (psrlq (% mm7) (% mm0))
+  (movd (% mm0) (@ x8632::misc-data-offset (% temp0) (% arg_y)))
+  (addl ($ '1) (% i))
+  (addl ($ '1) (% arg_y))
+  @test
+  (cmpl (@ (% esp)) (% arg_y))		;compare to res-len-1
+  (jne @loop)
+  (addl ($ x8632::node-size) (% esp))
+  @finish
+  (movd (@ x8632::misc-data-offset (% temp1) (% i)) (% mm0)) ;last digit of b
+  (psrad (% mm7) (% mm0))
+  (movd (% mm0) (@ x8632::misc-data-offset (% temp0) (% arg_y)))
+  (single-value-return 5))
+
+(defx8632lapfunction %logcount-complement ((bignum arg_y) (i arg_z))
+  (mark-as-imm temp0)
+  (let ((rshift imm0)
+	(temp temp0))
+    (movl (@ x8632::misc-data-offset (% bignum) (% i)) (% rshift))
+    (notl (% rshift))
+    (xorl (% arg_z) (% arg_z))
+    (testl (% rshift) (% rshift))
+    (jmp @test)
+    @next
+    (lea (@ -1 (% rshift)) (% temp))
+    (and (% temp) (% rshift))		;sets flags
+    (lea (@ '1 (% arg_z)) (% arg_z))	;doesn't set flags
+    @test
+    (jne @next)
+    (mark-as-node temp0)
+    (single-value-return)))
+
+(defx8632lapfunction %logcount ((bignum arg_y) (i arg_z))
+  (mark-as-imm temp0)
+  (let ((rshift imm0)
+	(temp temp0))
+    (movl (@ x8632::misc-data-offset (% bignum) (% i)) (% rshift))
+    (xorl (% arg_z) (% arg_z))
+    (testl (% rshift) (% rshift))
+    (jmp @test)
+    @next
+    (lea (@ -1 (% rshift)) (% temp))
+    (and (% temp) (% rshift))		;sets flags
+    (lea (@ '1 (% arg_z)) (% arg_z))	;doesn't set flags
+    @test
+    (jne @next)
+    (mark-as-node temp0)
+    (single-value-return)))
+
+
+;;; Divide bignum x by single digit y (passed as two halves).
+;;; The quotient in stored in q, and the remainder is returned
+;;; in two halves.  (cf. Knuth, 4.3.1, exercise 16)
+(defx8632lapfunction %floor-loop-quo ((x 8) (res 4) #|(ra 0)|# (yhi arg_y) (ylo arg_z))
+  (compose-digit yhi ylo imm0)
+  (movl (% imm0) (:rcontext x8632::tcr.unboxed0))
+  (pop (% temp0))
+  (pop (% arg_z))			;res
+  (pop (% arg_y))			;x
+  (discard-reserved-frame)
+  (push (% temp0))
+  (mark-as-imm edx)			;aka temp1
+  (let ((bignum arg_y)			;bignum dividend
+	(result arg_z))			;bignum result (quotient)
+    (xorl (% edx) (% edx))
+    (vector-length bignum temp0)
+    (jmp @next)
+    @loop
+    (movl (@ x8632::misc-data-offset (% bignum) (% temp0)) (% eax))
+    (divl (:rcontext x8632::tcr.unboxed0))
+    (movl (% eax) (@ x8632::misc-data-offset (% result) (% temp0)))
+    @next
+    (subl ($ '1) (% temp0))
+    (jge @loop))
+  (movl (% esp) (% temp0))
+  ;; extract and push high half of remainder
+  (movl ($ (- #x10000)) (% arg_y))
+  (andl (% edx) (% arg_y))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% arg_y))
+  (push (% arg_y))
+  ;; extract and push low half
+  (andl ($ #xffff) (% edx))
+  (shll ($ x8632::fixnumshift) (% edx))
+  (push (% edx))
+  (mark-as-node edx)
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+
+;;; For TRUNCATE-BY-FIXNUM et al.
+;;; Doesn't store quotient: just returns rem in 2 halves.
+;;; Could avoid using tcr.unboxed0 if it matters...
+(defx8632lapfunction %floor-loop-no-quo ((x 4) #|(ra 0)|# (yhi arg_y) (ylo arg_z))
+  (compose-digit yhi ylo imm0)
+  (movl (% imm0) (:rcontext x8632::tcr.unboxed0))
+  (pop (% temp0))
+  (pop (% arg_y))
+  (discard-reserved-frame)
+  (push (% temp0))
+  (mark-as-imm edx)			;aka temp1
+  (let ((bignum arg_y)			;bignum dividend
+	(result arg_z))			;bignum result (quotient)
+    (xorl (% edx) (% edx))
+    (vector-length bignum temp0)
+    (jmp @next)
+    @loop
+    (movl (@ x8632::misc-data-offset (% bignum) (% temp0)) (% eax))
+    (divl (:rcontext x8632::tcr.unboxed0))
+    ;;(movl (% eax) (@ x8632::misc-data-offset (% result) (% temp0)))
+    @next
+    (subl ($ '1) (% temp0))
+    (jge @loop))
+  (movl (% esp) (% temp0))
+  ;; extract and push high half of remainder
+  (movl ($ (- #x10000)) (% arg_y))
+  (andl (% edx) (% arg_y))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% arg_y))
+  (push (% arg_y))
+  ;; extract and push low half
+  (andl ($ #xffff) (% edx))
+  (shll ($ x8632::fixnumshift) (% edx))
+  (push (% edx))
+  (mark-as-node edx)
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+
+;;; transliterated from bignum-truncate-guess in l0-bignum64.lisp
+;;; this is not beautiful...
+(defx8632lapfunction truncate-guess-loop ((guess-h 16) (guess-l 12) (x 8)
+					  (xidx 4) #|(ra 0)|#
+					  (yptr arg_y) (yidx arg_z))
+  (save-stackargs-frame 4)
+  (push (% arg_y))
+  (push (% arg_z))
+
+  (movl (@ -4 (% ebp)) (% temp0))	;guess-h
+  (movl (@ -8 (% ebp)) (% temp1))	;guess-l
+  (compose-digit temp0 temp1 imm0)
+  (movd (% imm0) (% mm0))		;save guess
+
+  @loop
+  (movl (@ (% esp)) (% yidx))
+  (movl (@ 4 (% esp)) (% yptr))
+  (movd (@ (- x8632::misc-data-offset 0) (% yptr) (% yidx)) (% mm1)) ;y1 (high)
+  ;; (%multiply guess y1)
+  (pmuludq (% mm0) (% mm1))
+  ;; (%multiply guess y2)
+  (movd (@ (- x8632::misc-data-offset 4) (% yptr) (% yidx)) (% mm2)) ;y2 (low)
+  (pmuludq (% mm0) (% mm2))
+
+  (movl (@ -12 (% ebp)) (% temp0))	 ;x
+  (movl (@ -16 (% ebp)) (% arg_y))	 ;xidx
+  (mark-as-imm temp1)			 ;edx now unboxed
+
+  ;; (%subtract-with-borrow x-i-1 low-guess*y1 1)
+  (movl (@ (- x8632::misc-data-offset 4) (% temp0) (% arg_y)) (% edx)) ;x-i-1
+  (movd (% mm1) (% eax))		;low part of y1*guess
+  (subl (% eax) (% edx))
+  (movd (% edx) (% mm6))		;save middle digit
+  ;; (%subtract-with-borrow x-i high-guess*y1 borrow)
+  (movl (@ (- x8632::misc-data-offset 0) (% temp0) (% arg_y)) (% edx)) ;x-i
+  (movq (% mm1) (% mm3))
+  (psrlq ($ 32) (% mm3))		;get high part into low half
+  (movd (% mm3) (% eax))		;high part of y1*guess
+  (sbbl (% eax) (% edx))
+  (movd (% edx) (% mm7))		;save high digit
+  ;; see if guess is suitable
+  ;; if (and (= high-digit 0)
+  (test (% edx) (% edx))
+  (jne @return)
+  ;;         (or (> high-guess*y2 middle-digit)
+  (movq (% mm2) (% mm3))
+  (psrlq ($ 32) (% mm3))
+  (movd (% mm3) (% eax))		;high part of y2*guess
+  (movd (% mm6) (% edx))		;middle-digit
+  (cmpl (% edx) (% eax))
+  (ja @decrement)
+  ;;             (and (= middle-digit high-guess*y2)
+  (jne @return)
+  ;;                  (> low-guess*y2 x-i-2)
+  (movd (% mm2) (% eax))		;low part of y2*guess
+  (movl (@ (- x8632::misc-data-offset 8) (% temp0) (% arg_y)) (% edx)) ;x-i-2
+  (cmpl (% edx) (% eax))
+  (ja @decrement)
+  @return
+  (mark-as-node edx)
+  (leave)
+  (movl (% esp) (% temp0))
+  (movd (% mm0) (% imm0))
+  (shrl ($ 16) (% imm0))
+  (shll ($ x8632::fixnumshift) (% imm0)) ;high half
+  (push (% imm0))
+  (movd (% mm0) (% imm0))
+  (andl ($ #xffff) (% imm0))
+  (shll ($ x8632::fixnumshift) (% imm0))
+  (push (% imm0))			;low half
+  (set-nargs 2)
+  (jmp-subprim .SPvalues)
+  @decrement
+  (movd (% mm0) (% imm0))		;guess
+  (subl ($ 1) (% imm0))
+  (movd (% imm0) (% mm0))
+  (jmp @loop))
+
+;;; If x[i] = y[j], return the all ones digit (as two halves).
+;;; Otherwise, compute floor x[i]x[i-1] / y[j].
+(defx8632lapfunction %floor-99 ((x-stk 8) (xidx 4) #|(ra 0)|#
+				(yptr arg_y) (yidx arg_z))
+  (pop (% temp1))
+  (pop (% imm0))
+  (pop (% temp0))
+  (discard-reserved-frame)
+  (push (% temp1))
+  (movl (% imm0) (% temp1))
+  (movl (@ x8632::misc-data-offset (% temp0) (% temp1)) (% imm0)) ;x[i]
+  (cmpl (% imm0) (@ x8632::misc-data-offset (% yptr) (% yidx)))	  ;y[j]
+  (jne @more)
+  (pushl ($ '#xffff))
+  (pushl ($ '#xffff))
+  (lea (@ '2 (% esp)) (% temp0))
+  (set-nargs 2)
+  (jmp-subprim .SPvalues)
+  @more
+  (mark-as-imm edx)			;aka temp1 (contains a fixnum)
+  (movl (@ (- x8632::misc-data-offset 4) (% temp0) (% temp1)) (% eax)) ;low
+  (movl (@ x8632::misc-data-offset (% temp0) (% temp1)) (% edx))    ;high digit
+  (divl (@ x8632::misc-data-offset (% yptr) (% yidx)))
+  (mark-as-node edx)
+  ;; extract and push high half of quotient
+  (movl ($ (- #x10000)) (% arg_y))
+  (andl (% eax) (% arg_y))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% arg_y))
+  (push (% arg_y))
+  ;; extract and push low half
+  (andl ($ #xffff) (% eax))
+  (shll ($ x8632::fixnumshift) (% eax))
+  (push (% eax))
+  (set-nargs 2)
+  (lea (@ '2 (% esp)) (% temp0))
+  (jmp-subprim .SPvalues))
+
+;;; x * y + carry
+(defx8632lapfunction %multiply-and-add-1 ((x-high 16)
+					  (x-low 12)
+					  (y-high 8)
+					  (y-low 4)
+					  #|(ra 0)|#
+					  (carry-in-high arg_y)
+					  (carry-in-low arg_z))
+  (movl (@ x-high (% esp)) (% temp0))
+  (movl (@ x-low (% esp)) (% temp1))
+  (compose-digit temp0 temp1 imm0)
+  (movd (% imm0) (% mm0))
+  (movl (@ y-high (% esp)) (% temp0))
+  (movl (@ y-low (% esp)) (% temp1))
+  (compose-digit temp0 temp1 imm0)
+  (movd (% imm0) (% mm1))
+  (pmuludq (% mm1) (% mm0))		;x * y
+  (compose-digit arg_y arg_z imm0)
+  (movd (% imm0) (% mm1))
+  (paddq (% mm1) (% mm0))		;add in carry digit
+  (movq (% mm0) (% mm1))
+  (psrlq ($ 32) (% mm1))		;resultant carry digit
+  ;; clean up stack
+  (pop (% temp0))
+  (addl ($ '6) (% esp))
+  (push (% temp0))
+  ;; return (values carry-h carry-l result-h result-l) 
+  (movl (% esp) (% temp0))
+  (movd (% mm1) (% imm0))
+  (shrl ($ 16) (% imm0))
+  (shll ($ x8632::fixnumshift) (% imm0)) ;carry-h
+  (push (% imm0))
+  (movd (% mm1) (% imm0))
+  (shll ($ 16) (% imm0))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% imm0)) ;carry-l
+  (push (% imm0))
+  (movd (% mm0) (% imm0))
+  (shrl ($ 16) (% imm0))
+  (shll ($ x8632::fixnumshift) (% imm0)) ;result-h
+  (push (% imm0))
+  (movd (% mm0) (% imm0))
+  (shll ($ 16) (% imm0))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% imm0)) ;result-l
+  (push (% imm0))
+  (set-nargs 4)
+  (jmp-subprim .SPvalues))
+
+;;; Copy the limb SRC points to to where DEST points.
+(defx8632lapfunction copy-limb ((src arg_y) (dest arg_z))
+  (int ($ 3)))
+
+;;; Return T iff LIMB contains 0.
+(defx8632lapfunction limb-zerop ((limb arg_z))
+  (int ($ 3)))
+
+;;; Return -1,0,1 according to whether the contents of Y are
+;;; <,=,> the contents of Z.
+(defx8632lapfunction compare-limbs ((y arg_y) (z arg_z))
+  (int ($ 3)))
+
+;;; Add a fixnum to the limb LIMB points to.  Ignore overflow.
+(defx8632lapfunction add-fixnum-to-limb ((fixnum arg_y) (limb arg_z))
+  (int ($ 3)))
+
+;;; Store a fixnum value where LIMB points.
+(defx8632lapfunction copy-fixnum-to-limb ((fixnum arg_y) (limb arg_z))
+  (int ($ 3)))
+
+;;; Increment a "LIMB VECTOR" (bignum) by a small amount.  The caller
+;;; knows that carries will only propagate for a word or two.
+(defx8632lapfunction mpn-incr-u ((limb arg_y) (fixby arg_z))
+  (int ($ 3)))
+
+;;; Store XP-YP at WP; return carry (0 or 1).
+;;; wp, xp, yp: word-aligned, unboxed ptrs (fixnums)
+;;; size: boxed fixnum
+;;; returns boxed carry
+(defx8632lapfunction mpn-sub-n ((wp 8) (xp 4) #|(ra 0)|#
+				(yp arg_y) (size arg_z))
+  (int ($ 3)))
+
+;;; Store XP+YP at WP; return carry (0 or 1).
+;;; wp, xp, yp = word-aligned, unboxed macptrs (fixnums).
+;;; size = boxed fixnum
+;;; result = boxed carry
+(defx8632lapfunction mpn-add-n ((wp 8) (xp 4) #|(ra 0)|#
+				(yp arg_y) (size arg_z))
+  (int ($ 3)))
+
+;;; Add the single limb LIMB to S1P (propagating carry.)  Store the
+;;; result at RP.  RP and S1P may be the same place, so check for
+;;; that and do nothing after carry stops propagating.  Return carry.
+(defx8632lapfunction mpn-add-1 ((rp-offset 8) (s1p 4) #|(ra 0)|#
+				(size arg_y) (limb arg_z))
+  (int ($ 3)))
+
+;;; Multiply the limb vector S1 by the single limb at LIMBPTR, storing
+;;; the result at RES.  Store the "carry out" (high word of last 64-bit
+;;; partial product) at the limb RESULT.
+;;; res, s1, limbptr, result:
+;;;   unboxed, word-aligned ptrs (fixnums).  size: boxed fixnum
+;;; It'd be hard to transliterate the GMP code here; the GMP version
+;;; uses lots more immediate registers than we can easily use in LAP
+;;; (and is much more aggressively pipelined).
+(defx8632lapfunction mpn-mul-1 ((res-offset 12)
+				(s1-offset 8)
+				(size 4)
+				#|(ra 0)|#
+				(limbptr arg_y)
+				(result arg_z))
+  (int ($ 3)))
+
+;;; multiply s1*limb and add result to res
+;;; res, s1, limbptr, result:
+;;;   unboxed, word-aligned ptrs (fixnums).
+;;; size: boxed fixnum
+;;; limbptr: source "limb".
+;;; result: carry out (high word of product).
+(defx8632lapfunction mpn-addmul-1 ((res-offset 12)
+				   (s1-offset 8)
+				   (size 4)
+				   #|(ra 0)|#
+				   (limbptr arg_y)
+				   (result arg_z))
+  (int ($ 3)))
+
+;;; Multiply the UN-word limb vector at UP and the VN-word limb vector
+;;; at VP, store the result at RP.
+(defx8632lapfunction mpn-mul-basecase ((rp-offset 12)
+				       (up-offset 8)
+				       (un 4)
+				       #|(ra 0)|#
+				       (vp arg_y)
+				       (vn arg_z))
+  (int ($ 3)))
+
+;;; left-shift src by 1 bit, storing result at res.  Return
+;;; the bit that was shifted out.
+(defx8632lapfunction mpn-lshift-1 ((resptr 4) #|(ra 0)|#
+				   (s1ptr arg_y) (size-arg arg_z))
+  (int ($ 3)))
+
+;;; Do a 32x32=64 unsigned multiply of the words at X and Y.  Store
+;;; result (low word first) at RESULT.
+(defx8632lapfunction umulppm ((x 4) #|(ra 0)|# (y arg_y) (result arg_z))
+  (int ($ 3)))
+
+(defx8632lapfunction %fixnum-to-bignum-set ((bignum arg_y) (fixnum arg_z))
+  (unbox-fixnum fixnum imm0)
+  (movl (% imm0) (@ x8632::misc-data-offset (% bignum)))
+  (single-value-return))
+
+(defx8632lapfunction bignum-negate-loop-really ((bignum 4) #|(ra 0)|# 
+						(len arg_y) (result arg_z))
+  (mark-as-imm edx)			;aka %temp1
+  (unbox-fixnum arg_y edx)
+  (movl (@ bignum (% esp)) (% arg_y))
+  (xorl (% temp0) (% temp0))
+  (stc)
+  @loop
+  (movl (@ x8632::misc-data-offset (% arg_y) (% temp0)) (% imm0))
+  (not (% imm0))
+  (adc ($ 0) (% imm0))
+  (movl (% imm0) (@ x8632::misc-data-offset (% arg_z) (% temp0)))
+  (lea (@ x8632::node-size (% temp0)) (% temp0))
+  (decl (% edx))			;preserves carry flag
+  (jg @loop)
+  ;; return carry
+  (setc (% imm0.b))
+  (movzbl (% imm0.b) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (mark-as-node edx)
+  (single-value-return 3))
+
+(defx8632lapfunction %bignum-set ((bignum 8) (i 4) #|(ra 0)|#
+				  (high arg_y) (low arg_z))
+  (compose-digit high low imm0)
+  (movl (@ bignum (% esp)) (% arg_z))
+  (movl (@ i (% esp)) (% arg_y))
+  (movl (% imm0) (@ x8632::misc-data-offset (% arg_z) (% arg_y)))
+  (single-value-return 4))
+
Index: /branches/new-random/level-0/X86/X8632/x8632-clos.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-clos.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-clos.lisp	(revision 13309)
@@ -0,0 +1,258 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; This just maps a SLOT-ID to a SLOT-DEFINITION or NIL.
+;;; The map is a vector of (UNSIGNED-BYTE 8); this should
+;;; be used when there are fewer than 255 slots in the class.
+(defx8632lapfunction %small-map-slot-id-lookup ((slot-id arg_z))
+  (movl (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index arg_y)
+  (vector-length temp1 temp0)
+  (xorl (%l imm0) (%l imm0))
+  (rcmpl (% arg_y) (% temp0))
+  (ja @have-table-index)
+  (movl (% arg_y) (% imm0))
+  (shrl ($ x8632::word-shift) (% imm0))
+  (movzbl (@ x8632::misc-data-offset (% temp1) (% imm0)) (%l imm0))
+  ;(shll ($ x8632::word-shift) (% imm0))
+  @have-table-index
+  (movl (@ 'table (% fn)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% temp0) (% imm0) 4) (% arg_z))
+  (single-value-return))
+
+;;; The same idea, only the map is a vector of (UNSIGNED-BYTE 32).
+(defx8632lapfunction %large-map-slot-id-lookup ((slot-id arg_z))
+  (movl (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index arg_y)
+  (vector-length temp1 temp0)
+  (xorl (%l imm0) (%l imm0))
+  (rcmpl (% arg_y) (% temp0))
+  (ja @have-table-index)
+  (movl (% arg_y) (% imm0))
+  (movl (@ x8632::misc-data-offset (% temp1) (% imm0)) (%l imm0))
+  @have-table-index
+  (movl (@ 'table (% fn)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% temp0) (% imm0) 4) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %small-slot-id-value ((instance arg_y) (slot-id arg_z))
+  (movl (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index temp0)
+  (vector-length temp1 imm0)
+  (rcmpl (% temp0) (% imm0))
+  (movl ($ 0) (% imm0))			;don't disturb flags
+  (ja @missing)
+  (movl (% temp0) (% imm0))
+  (shrl ($ x8632::word-shift) (% imm0))
+  (movzbl (@ x8632::misc-data-offset (% temp1) (% imm0)) (% imm0))
+  (testl (% imm0) (% imm0))
+  (je @missing)
+  (movl (@ 'table (% fn)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% temp0) (% imm0) 4) (% arg_z))
+  (popl (% ra0))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl (@ 'class (% fn)))
+  (set-nargs 3)
+  (pushl (% ra0))
+  (jmp (@ '%maybe-std-slot-value-using-class (% fn)))
+  @missing                              ; (%slot-id-ref-missing instance id)
+  (set-nargs 2)
+  (jmp (@'%slot-id-ref-missing (% fn))))
+
+(defx8632lapfunction %large-slot-id-value ((instance arg_y) (slot-id arg_z))  
+  (movl (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index temp0)
+  (vector-length temp1 imm0)
+  (rcmp (% temp0) (% imm0))
+  (movl ($ 0) (% imm0))
+  (ja @missing)
+  (movl (% temp0) (% imm0))
+  (movl (@ x8632::misc-data-offset (% temp1) (% imm0)) (% imm0))
+  (test (% imm0) (% imm0))
+  (je @missing)
+  (movl (@ 'table (% fn)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% temp0) (% imm0) 4) (% arg_z))
+  (popl (% ra0))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl (@ 'class (% fn)))
+  (set-nargs 3)
+  (pushl (% ra0))
+  (jmp (@ '%maybe-std-slot-value-using-class (% fn)))
+  @missing                              ; (%slot-id-ref-missing instance id)
+  (set-nargs 2)
+  (jmp (@'%slot-id-ref-missing (% fn))))
+
+(defx86lapfunction %small-set-slot-id-value ((instance 4)
+					     #|(ra 0)|#
+                                             (slot-id arg_y)
+                                             (new-value arg_z))
+  (movl (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index imm0)
+  (vector-length temp1 temp0)
+  (rcmpl (% imm0) (% temp0))
+  (ja @missing)
+  (shrl ($ x8632::word-shift) (% imm0))
+  (movzbl (@ x8632::misc-data-offset (% temp1) (% imm0)) (% imm0))
+  (testl (% imm0) (% imm0))
+  (je @missing)
+  (movl (@ 'table (% fn)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% temp0) (% imm0) 4) (% arg_y))
+  (popl (% temp0))			;return address
+  (popl (% temp1))			;instance
+  ;; use existing frame
+  (pushl (@ 'class (% fn)))
+  (pushl (% temp1))
+  (pushl (% temp0))
+  (set-nargs 4)
+  ;; (%maybe-std-setf-slot-value-using-class class instance slotd new)
+  (jmp (@ '%maybe-std-setf-slot-value-using-class (% fn)))
+  @missing
+  (set-nargs 3)
+  ;; (%slot-id-set-missing instance id new)
+  (jmp (@ '%slot-id-set-missing (% fn))))
+
+(defx8632lapfunction %large-set-slot-id-value ((instance 4)
+					       #|(ra 0)|#
+					       (slot-id arg_y)
+					       (new-value arg_z))
+  (movl (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index imm0)
+  (vector-length temp1 temp0)
+  (rcmpl (% imm0) (% temp0))
+  (ja @missing)
+  (movl (@ x8632::misc-data-offset (% temp1) (% imm0)) (%l imm0))
+  (testl (%l imm0) (%l imm0))
+  (je @missing)
+  (movl (@ 'table (% fn)) (% temp0))
+  (movl (@ x8632::misc-data-offset (% temp0) (% imm0) 4) (% arg_y))
+  (popl (% temp0))			;return addr
+  (popl (% temp1))			;instance
+  (pushl (@ 'class (% fn)))
+  (pushl (% temp1))
+  (pushl (% temp0))
+  (set-nargs 4)
+  (jmp (@ '%maybe-std-setf-slot-value-using-class (% fn)))
+  @missing                              ; (%slot-id-set-missing instance id new-value)
+  (set-nargs 3)
+  (jmp (@'%slot-id-ref-missing (% fn))))
+
+;;; All of the generic function trampoline functions have to be
+;;; exactly the same size (x8632::gf-code-size) in words.  The largest
+;;; of these - the general-case *GF-PROTO* - is currently about 27
+;;; words, so X8632::GF-CODE-SIZE is just a little bigger than that.
+;;; (Note that x8632::gf-code-size has to include space for the
+;;; self-reference table, which takes up another couple of words in
+;;; addition to the machine instructions.)
+(defparameter *gf-proto*
+  (nfunction
+   gag
+   (lambda (&lap &lexpr args)
+     (x86-lap-function 
+      gag 
+      ()
+      (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+      (:code-size x8632::gf-code-size)
+      (movl (@ (% esp)) (% ra0))
+      (save-frame-variable-arg-count)
+      (push-argregs)
+      (pushl (%l nargs))
+      (movl (% esp) (% arg_z))
+      (ref-global.l ret1valaddr imm0)
+      (cmpl (% ra0) (% imm0))
+      (je @multiple)
+      (ref-global.l lexpr-return1v ra0)
+      (jmp @call)
+      @multiple
+      (pushl (@ (+ (target-nil-value) (x8632::%kernel-global 'lexpr-return))))
+      (movl (% imm0) (% ra0))
+      @call
+      (push (% ra0))
+      (movl (@ 'dispatch-table (% fn)) (% arg_y))
+      (set-nargs 2)
+      (jmp (@ 'dcode (% fn)))  ; dcode function
+      ))))
+
+(defx8632lapfunction gag-one-arg ((arg arg_z))
+  (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+  (:code-size x8632::gf-code-size)
+  (check-nargs 1)
+  (movl (@ 'dispatch-table (% fn)) (% arg_y))
+  (set-nargs 2)
+  (jmp (@ 'dcode (% fn))))
+
+(defx8632lapfunction gag-two-arg ((arg0 arg_y) (arg1 arg_z))
+  (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+  (:code-size x8632::gf-code-size)
+  (check-nargs 2)
+  (pop (% ra0))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl (@ 'dispatch-table (% fn)))
+  (push (% ra0))
+  (set-nargs 3)
+  (jmp (@ 'dcode (% fn))))
+
+(defx8632lapfunction funcallable-trampoline ()
+  (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+  (:code-size x8632::gf-code-size)
+  (jmp (@ 'dcode (% fn))))
+
+;;; This is in LAP so that it can reference itself in the error message.
+;;; (It needs to be cloned, so %fn will be unique to each copy.)
+;;; It can't work for this to reference any of its own constants.
+(defx8632lapfunction unset-fin-trampoline ()
+  (:code-size x8632::gf-code-size)
+  (save-frame-variable-arg-count)
+  (call-subprim .SPheap-rest-arg)
+  (pop (% arg_z))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl ($ '#.$XNOFINFUNCTION))
+  (movl (% fn) (% arg_y))
+  (set-nargs 3)
+  (call-subprim .SPksignalerr)
+  ;(movl ($ (target-nil-value)) (% arg_z))
+  (leave)
+  (single-value-return))
+
+(defparameter *cm-proto*
+  (nfunction
+   gag
+   (lambda (&lap &lexpr args)
+     (x86-lap-function 
+      gag 
+      ()
+      (:fixed-constants (thing dcode gf bits))
+      (movl (@ (% esp)) (% ra0))
+      (save-frame-variable-arg-count)
+      (push-argregs)
+      (pushl (% nargs))
+      (movl (% esp) (% arg_z))
+      (ref-global ret1valaddr imm0)
+      (cmpl (% ra0) (% imm0))
+      (je @multiple)
+      (ref-global lexpr-return1v ra0)
+      (jmp @call)
+      @multiple
+      (pushl (@ (+ (target-nil-value) (x8632::%kernel-global 'lexpr-return))))
+      (movl (% imm0) (% ra0))
+      @call
+      (push (% ra0))
+      (movl (@ 'thing (% fn)) (% arg_y))
+      (set-nargs 2)
+      (jmp (@ 'dcode (% fn)))))))
Index: /branches/new-random/level-0/X86/X8632/x8632-def.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-def.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-def.lisp	(revision 13309)
@@ -0,0 +1,691 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Use the offsets in a function's self-reference table to replace
+;;; the :self in (movl ($ :self) (% fn)) wih the function's actual
+;;; address.
+(defx8632lapfunction %update-self-references ((fun arg_z))
+  (movzwl (@ x8632::misc-data-offset (% fun)) (% imm0)) ;imm word count
+  (btr ($ 15) (% imm0))
+  (jnc @proceed)
+  (imm-word-count fun imm0 temp0)
+  (subl ($ '2) (% temp0))
+  (jmp @load-offset)
+  @proceed
+  (subl ($ 2) (% imm0))
+  (box-fixnum imm0 temp0)		;byte offset of first self-ref offset
+  (jmp @load-offset)
+  @loop
+  (movl (% fun) (@ x8632::misc-header-offset (% fun) (% imm0)))
+  (subl ($ '1) (% temp0))
+  @load-offset
+  (movl (@ x8632::misc-data-offset (% fun) (% temp0)) (% imm0))
+  (test (% imm0) (% imm0))
+  (jne @loop)
+  (single-value-return))
+
+(defx8632lapfunction %function-code-words ((fun arg_z))
+  (trap-unless-typecode= fun x8632::subtag-function)
+  (movzwl (@ x8632::misc-data-offset (% fun)) (% imm0))
+  (btr ($ 15) (% imm0))
+  (jnc @proceed)
+  (imm-word-count fun imm0 temp0)
+  (movl (% temp0) (% arg_z))
+  (single-value-return)
+  @proceed
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %nth-immediate ((fun arg_y) (n arg_z))
+  (trap-unless-typecode= fun x8632::subtag-function)
+  (movzwl (@ x8632::misc-data-offset (% fun)) (% imm0))
+  (btr ($ 15) (% imm0))
+  (jnc @proceed)
+  (imm-word-count fun imm0 temp0)
+  (unbox-fixnum temp0 imm0)
+  @proceed
+  (lea (@ (% n) (% imm0) 4) (% imm0))
+  (movl (@ x8632::misc-data-offset (% fun) (% imm0)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %set-nth-immediate ((fun 4) #|(ra 0)|# (n arg_y) (new arg_z))
+  (popl (@ 8 (% esp)))
+  (popl (% temp0))
+  (addl ($ 4) (% esp))
+  (trap-unless-typecode= temp0 x8632::subtag-function)
+  (movzwl (@ x8632::misc-data-offset (% temp0)) (% imm0))
+  (lea (@ (% n) (% imm0) 4) (% arg_y))
+  ;; expects gvector in temp0
+  (jmp-subprim .SPgvset))
+
+(defx8632lapfunction %function-code-byte ((fun arg_y) (pc arg_z))
+  (unbox-fixnum pc imm0)
+  (movzbl (@ (% fun) (% imm0)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %function-register-usage ((f arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= f x8632::subtag-function)
+  (movl (% esp) (% temp0))
+  (pushl ($ nil))
+  (pushl ($ nil))
+  (jmp-subprim .SPvalues))
+
+;;; XXX probably should unify these next two with the x8664 versions.
+
+;;; Make a new function, with PROTO's code and the specified immediates.
+;;; IMMEDIATES should contain lfun-bits as the last element.
+(defun %clone-x86-function (proto &rest immediates)
+  (declare (dynamic-extent immediates))
+  (let* ((protov (function-to-function-vector proto))
+         (code-words (%function-code-words proto))
+         (numimms (length immediates))
+         (newv (allocate-typed-vector :function (the fixnum (+ code-words numimms)))))
+    (declare (fixnum code-words numimms))
+    (%copy-ivector-to-ivector protov 0 newv 0 (the fixnum (ash code-words target::word-shift)))
+    #||
+    ;; XXX bootstrapping
+    (setf (ldb (byte 16 0) (uvref newv 0)) (logior #x8000 numimms))
+    ||#
+    (%update-self-references newv)
+    (do* ((k code-words (1+ k))
+          (imms immediates (cdr imms)))
+         ((null imms) (function-vector-to-function newv))
+      (declare (fixnum k) (list imms))
+      (setf (%svref newv k) (car imms)))))
+
+(defun %copy-function (proto &optional target)
+  (let* ((protov (function-to-function-vector proto))
+         (code-words (%function-code-words proto))
+         (total-words (uvsize protov))
+         (newv (if target
+                 (function-to-function-vector target)
+                 (allocate-typed-vector :function total-words))))
+    (declare (fixnum code-words total-words))
+    (when target
+      (unless (and (eql code-words (%function-code-words target))
+                   (eql total-words (uvsize newv)))
+        (error "Wrong size target ~s" target)))
+    (%copy-ivector-to-ivector protov 0 newv 0 (the fixnum (ash code-words target::word-shift)))
+    (loop for k fixnum from code-words below total-words
+      do (setf (%svref newv k) (%svref protov k)))
+    #||
+    (setf (ldb (byte 16 0) (uvref newv 0))
+	  (logior #x8000 (- total-words code-words)))
+    ||#
+    (%update-self-references (function-vector-to-function newv))))
+
+(defun replace-function-code (target proto)
+  (let* ((target-words (%function-code-words target))
+         (proto-words (%function-code-words proto)))
+    (declare (fixnum target-words proto-words))
+    (if (= target-words proto-words)
+      (progn
+        (%copy-ivector-to-ivector (function-to-function-vector proto)
+                                  0
+                                  (function-to-function-vector target)
+                                  0
+                                  (the fixnum (ash target-words
+                                                   target::word-shift)))
+	(%update-self-references target)
+        target)
+      (error "Code size mismatch: target = ~s, proto = ~s"
+             target-words proto-words))))
+
+(defx8632lapfunction %get-kernel-global-from-offset ((offset arg_z))
+  (check-nargs 1)
+  (unbox-fixnum offset imm0)
+  (movl (@ (target-nil-value) (% imm0)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %set-kernel-global-from-offset ((offset arg_y)
+						     (new-value arg_z))
+  (check-nargs 2)
+  (unbox-fixnum offset imm0)
+  (movl (% arg_z) (@ (target-nil-value) (% imm0)))
+  (single-value-return))
+
+(defx8632lapfunction %get-kernel-global-ptr-from-offset ((offset arg_y)
+							 (ptr arg_z))
+  (check-nargs 2)
+  (unbox-fixnum offset imm0)
+  (movl (@ (target-nil-value) (% imm0)) (% imm0))
+  (movl (% imm0) (@ x8632::macptr.address (% ptr)))
+  (single-value-return))
+
+(defx8632lapfunction %fixnum-ref ((fixnum arg_y) #| &optional |# (offset arg_z))
+  (:arglist (fixnum &optional offset))
+  (check-nargs 1 2)
+  (cmpl ($ x8632::fixnumone) (% nargs))
+  (jne @2-args)
+  (movl (% offset) (% fixnum))
+  (xorl (%l offset) (%l offset))
+  @2-args
+  (unbox-fixnum offset imm0)
+  (movl (@ (% fixnum) (% imm0)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %fixnum-ref-natural ((fixnum arg_y) #| &optional |# (offset arg_z))
+  (:arglist (fixnum &optional offset))
+  (check-nargs 1 2)
+  (cmpl ($ x8632::fixnumone) (% nargs))
+  (jne @2-args)
+  (movl (% offset) (% fixnum))
+  (xorl (%l offset) (%l offset))
+  @2-args
+  (unbox-fixnum offset imm0)
+  (movl (@ (% fixnum) (% imm0)) (% imm0))
+  (jmp-subprim .SPmakeu32))
+
+(defx8632lapfunction %fixnum-set ((fixnum 4) #|(ra 0)|# (offset arg_y) #| &optional |# (new-value arg_z))
+  (:arglist (fixnum offset &optional newval))
+  (check-nargs 2 3)
+  (cmpl ($ '2) (% nargs))
+  (jne @3-args)
+  (movl (% new-value) (% offset))
+  (single-value-return)
+  @3-args
+  (movl (@ fixnum (% esp)) (% temp0))
+  (unbox-fixnum offset imm0)
+  (movl (% new-value) (@ (% temp0) (% imm0)))
+  (single-value-return 3))
+
+
+(defx8632lapfunction %fixnum-set-natural ((fixnum 4) #|(ra 0)|# (offset arg_y) #| &optional |# (new-value arg_z))
+  (:arglist (fixnum offsnet &optional newval))
+  (check-nargs 2 3)
+  (cmpl ($ '2) (% nargs))
+  (jne @3-args)
+  (save-simple-frame)
+  (movl (% offset) (% temp0))
+  (xorl (% offset) (% offset))
+  (jmp @common)
+  @3-args
+  (movl (% ebp) (@ 8 (% esp)))
+  (lea (@ 8 (% esp)) (% ebp))
+  (popl (@ 4 (% ebp)))
+  (popl (% temp0))
+  @common
+  (call-subprim .SPgetu32)		;puts u32 in imm0
+  (mark-as-imm temp1)
+  (unbox-fixnum offset temp1)
+  (movl (% imm0) (@ (% temp0) (% temp1)))
+  (mark-as-node temp1)
+  (restore-simple-frame)
+  (single-value-return))
+
+
+(defx8632lapfunction %current-frame-ptr ()
+  (check-nargs 0)
+  (movl (% ebp) (% arg_z))
+  (single-value-return))
+
+
+(defx8632lapfunction %current-tsp ()
+  (check-nargs 0)
+  (movl (:rcontext x8632::tcr.save-tsp) (% arg_z))
+  (single-value-return))
+
+
+(defx8632lapfunction %%frame-backlink ((p arg_z))
+  (check-nargs 1)
+  (movl (@ (% arg_z)) (% arg_z))
+  (single-value-return))
+
+;;; Look for "movl $imm32,%fn at the tra;  if present, then $imm32 is
+;;; the address of the function.
+;;;
+;;; That is: #b10111111 <imm32>
+;;;                ^^^^
+;;;   operand size || register number (%fn/%edi)
+
+(defx8632lapfunction %return-address-function ((r arg_z))
+  (extract-fulltag r imm0)
+  (cmpb ($ x8632::fulltag-tra) (% imm0.b))
+  (jne @fail)
+  (cmpb ($ x8632::recover-fn-opcode-byte) (@ (% r)))
+  (jne @fail)
+  (movl (@ x8632::recover-fn-address-offset (% r)) (% arg_z))
+  (single-value-return)
+  @fail
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %return-address-offset ((r arg_z))
+  (extract-fulltag r imm0)
+  (cmpb ($ x8632::fulltag-tra) (% imm0.b))
+  (jne @fail)
+  (cmpb ($ x8632::recover-fn-opcode-byte) (@ (% r)))
+  (jne @fail)
+  (movl (@ x8632::recover-fn-address-offset (% r)) (% imm0))
+  (subl (% arg_z) (% imm0))
+  (negl (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return)
+  @fail
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return))
+
+;;; It's always been the case that the function associated with a
+;;; frame pointer is the caller of the function that "uses" that frame.
+(defun %cfp-lfun (p)
+  (let* ((ra (%fixnum-ref p x8632::lisp-frame.return-address)))
+    (if (eq ra (%get-kernel-global ret1valaddr))
+      (setq ra (%fixnum-ref p x8632::lisp-frame.xtra)))
+    (values (%return-address-function ra) (%return-address-offset ra))))
+
+(defx8632lapfunction %uvector-data-fixnum ((uv arg_z))
+  (check-nargs 1)
+  (trap-unless-fulltag= arg_z x8632::fulltag-misc)
+  (addl ($ x8632::misc-data-offset) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %catch-top ((tcr arg_z))
+  (check-nargs 1)
+  (movl ($ (target-nil-value)) (% arg_y))
+  (movl (:rcontext x8632::tcr.catch-top) (% arg_z))
+  (testb (%b arg_z) (%b arg_z))
+  (cmovel (% arg_y) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %catch-tsp ((catch arg_z))
+  (check-nargs 1)
+  (lea (@  (- (+ x8632::fulltag-misc
+		 (ash 1 (1+ x8632::word-shift)))) (% arg_z))
+       (% arg_z))
+  (single-value-return))
+
+;;; Same as %address-of, but doesn't cons any bignums
+;;; It also left shift fixnums just like everything else.
+(defx8632lapfunction %fixnum-address-of ((x arg_z))
+  (check-nargs 1)
+  (box-fixnum x arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %save-standard-binding-list ((bindings arg_z))
+  (mark-as-imm temp0)
+  (movl (:rcontext x8632::tcr.vs-area) (% imm0))
+  (movl (@ x8632::area.high (% imm0)) (% temp0))
+  (subl ($ x8632::node-size) (% temp0))
+  (movl (% bindings) (@ (% temp0)))
+  (mark-as-node temp0)
+  (single-value-return))
+
+(defx8632lapfunction %saved-bindings-address ()
+  (mark-as-imm temp0)
+  (movl (:rcontext x8632::tcr.vs-area) (% imm0))
+  (movl (@ x8632::area.high (% imm0)) (% temp0))
+  (leal (@ (- x8632::node-size) (% temp0)) (% arg_z))
+  (mark-as-node temp0)
+  (single-value-return))
+
+(defx8632lapfunction %get-object ((macptr arg_y) (offset arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= macptr x8632::subtag-macptr)
+  (trap-unless-lisptag= offset x8632::tag-fixnum)
+  (macptr-ptr macptr imm0)
+  (mark-as-imm temp0)
+  (unbox-fixnum offset temp0)
+  (movl (@ (% imm0) (% temp0)) (% arg_z))
+  (mark-as-node temp0)
+  (single-value-return))
+
+(defx8632lapfunction %set-object ((macptr 4) #|(ra 0)|# (offset arg_y) (value arg_z))
+  (check-nargs 3)
+  (movl (@ macptr (% esp)) (% temp1))
+  (trap-unless-typecode= temp1 x8632::subtag-macptr)
+  (trap-unless-lisptag= offset x8632::tag-fixnum)
+  (macptr-ptr temp1 imm0)
+  (mark-as-imm temp0)
+  (unbox-fixnum offset temp0)
+  (movl (% arg_z) (@ (% imm0) (% temp0)))
+  (mark-as-node temp0)
+  (single-value-return 3))
+
+(defx8632lapfunction %apply-lexpr-with-method-context ((magic 4)
+						       #|(ra 0)|#
+						       (function arg_y)
+						       (args arg_z))
+  ;; Somebody's called (or tail-called) us.
+  ;; * Put magic arg in %rcontext:tcr.next-method-context
+  ;; * Put function somewhere safe until we're ready to jump to it
+  ;; * Set nargs to 0, then spread "args" on stack (clobbers regs)
+  ;; * Jump to function (saved previously)
+  (popl (:rcontext x8632::tcr.save0))	;return address
+  (popl (:rcontext x8632::tcr.next-method-context)) ;magic arg
+  (discard-reserved-frame)
+  (movl (% function) (:rcontext x8632::tcr.save1))
+  (set-nargs 0)
+  (movl (@ (% args)) (% temp0))		;lexpr-count
+  (movl (% temp0) (% nargs))
+  (leal (@ x8632::node-size (% arg_z) (% temp0)) (% imm0))
+  (subl ($ '2) (% temp0))
+  (jbe @reg-only)
+  ;; Some args will be pushed; reserve a frame.
+  (pushl ($ x8632::reserved-frame-marker))
+  (pushl ($ x8632::reserved-frame-marker))
+  @pushloop
+  (pushl (@ (- x8632::node-size) (% imm0)))
+  (subl ($ x8632::node-size) (% imm0))
+  (subl ($ x8632::node-size) (% temp0))
+  (jne @pushloop)
+  @two
+  (movl (@ (* x8632::node-size 2) (% arg_z)) (% arg_y))
+  @one
+  (movl (@ (* x8632::node-size 1) (% arg_z)) (% arg_z))
+  (jmp @go)
+  @reg-only
+  (rcmp (% nargs) ($ '1))
+  (je @one)
+  (jb @go)
+  (jmp @two)
+  @go
+  (pushl (:rcontext x8632::tcr.save0))	 ;return address
+  (movl (:rcontext x8632::tcr.save1) (% temp0)) ;function
+  (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear spill area
+  (jmp (% temp0)))
+
+(defx8632lapfunction %apply-with-method-context ((magic 4)
+						 #|(ra 0)|#
+						 (function arg_y)
+						 (args arg_z))
+  ;; Similar to above.
+  (popl (:rcontext x8632::tcr.save0))	;save return address
+  (popl (:rcontext x8632::tcr.next-method-context))	;
+  (discard-reserved-frame)
+  (movl (% args) (:rcontext x8632::tcr.save2))	;in case of error
+  (set-nargs 0)
+  (pushl ($ target::reserved-frame-marker))		;reserve frame (might discard it
+  (pushl ($ target::reserved-frame-marker))		;if nothing is passed on stack)
+  (cmp-reg-to-nil arg_z)
+  (je @done)
+  @loop
+  (extract-fulltag arg_z imm0)
+  (cmpb ($ x8632::fulltag-cons) (% imm0.b)) ;nil is a cons on x8632, but we
+  (jne @bad)				     ; checked for it already.
+  (add ($ '1) (% nargs))			;shorter than lea (imm0 is eax)
+  (pushl (@ target::cons.car (% arg_z)))
+  (%cdr arg_z arg_z)
+  (cmp-reg-to-nil arg_z)
+  (jne @loop)
+  @done
+  ;; arg_y about to get clobbered; put function into temp0
+  (movl (% function) (% temp0))
+  ;; temp1 (aka nargs) contains number of args just pushed
+  (test (% nargs) (% nargs))
+  (jne @pop)
+  @discard-and-go
+  (discard-reserved-frame)
+  (jmp @go)
+  @pop
+  (cmpl ($ '1) (% nargs))
+  (pop (% arg_z))
+  (je @discard-and-go)
+  (cmpl ($ '2) (% nargs))
+  (pop (% arg_y))
+  (je @discard-and-go)
+  @go
+  (pushl (:rcontext x8632::tcr.save0))	 ;return address
+  (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
+  (jmp (% temp0))
+  @bad
+  (addl (% nargs) (% esp))
+  (movl (:rcontext x8632::tcr.save1) (% arg_z)) ;saved args
+  (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
+  (movl ($ '#.$XNOSPREAD) (% arg_y))
+  (set-nargs 2)
+  (jmp-subprim .SPksignalerr))
+
+;;; The idea here is to call METHOD in the same stack frame in
+;;; which the lexpr was originally called.  The lexpr can't
+;;; have had any required arguments, %APPLY-LEXPR-TAIL-WISE
+;;; must have been tail-called, and the frame built on lexpr
+;;; entry must be in %rbp.
+(defx8632lapfunction %apply-lexpr-tail-wise ((method arg_y) (args arg_z))
+  (addl ($ x8632::node-size) (% esp))   ; discard extra return address
+  (movl (% method) (% xfn))		;temp1
+  (movl (% args) (% esp))
+  (popl (% imm0))			;nargs
+  (movl (@ x8632::lisp-frame.return-address (% ebp)) (% temp0))
+  (movl (@ 0 (% ebp)) (% ebp))
+  (rcmpl (% imm0) ($ '2))
+  (jbe @pop-regs)
+  ;; More than 2 args; some must have been pushed by caller,
+  ;; so retain the reserved frame.
+  (pop (% arg_z))
+  (pop (% arg_y))
+  (jmp @popped)
+  @pop-regs
+  (rcmpl (% imm0) ($ '1))
+  (jb @discard)
+  (ja @pop2)
+  (pop (% arg_z))
+  (jmp @discard)
+  @pop2
+  (pop (% arg_z))
+  (pop (% arg_y))
+  @discard
+  (discard-reserved-frame)
+  @popped
+  (push (% temp0))			;return address
+  (movl (% xfn) (% temp0))		;temp1 is also nargs
+  (movl (% imm0) (% nargs))
+  (jmp (% temp0)))
+
+(defun closure-function (fun)
+  (while (and (functionp fun) (not (compiled-function-p fun)))
+    (setq fun (%nth-immediate fun 0))
+    (when (vectorp fun)
+      (setq fun (svref fun 0))))
+  fun)
+
+;;; For use by (setf (apply ...) ...)
+;;; (apply+ f butlast last) = (apply f (append butlast (list last)))
+
+(defun apply+ (&lap function arg1 arg2 &rest other-args)
+  (x86-lap-function apply+ ()
+   (:arglist (function arg1 arg2 &rest other-args))
+   (check-nargs 3 nil)
+   (popl (:rcontext x8632::tcr.save0))	;save return address
+   ;; only two arg regs on x8632, so the caller will always push a frame
+   (movl (% arg_z) (% temp0))           ; last
+   (movl (% arg_y) (% arg_z))           ; butlast
+   (subl ($ '2) (% nargs))              ; remove count for butlast & last
+   (movd (% temp1) (% mm0))		;save nargs (aka temp1) for later
+   ;; Do .SPspreadargz inline here
+   (xorl (%l temp1) (%l temp1))
+   (movl (% arg_z) (:rcontext x8632::tcr.save1)) ; save in case of error
+   (cmp-reg-to-nil arg_z)
+   (je @done)
+   ;;(mark-as-imm temp1)
+   @loop
+   (extract-fulltag arg_z imm0)
+   (cmpb ($ x8632::fulltag-cons) (%b imm0))
+   (jne @bad)
+   (%car arg_z arg_y)
+   (%cdr arg_z arg_z)
+   (addl ($ '1) (%l temp1))
+   (cmp-reg-to-nil arg_z)   
+   (push (% arg_y))
+   (jne @loop)
+   @done
+   ;; nargs was at least 1 when we started spreading, and can't have gotten
+   ;; any smaller. 
+   (movd (% mm0) (% arg_y))		;nargs from before loop
+   (addl (% arg_y) (% temp1))		;did I mention nargs is temp1?
+   (movl (% temp0) (% arg_z))
+   (pop (% arg_y))
+   (addl ($ '1) (% nargs))
+   (load-constant funcall temp0)
+   (pushl (:rcontext x8632::tcr.save0))	;return address
+   (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
+   (jmp-subprim .SPfuncall)
+   @bad				      ;error spreading list.
+   (add (% temp1) (% esp))	      ;discard whatever's been pushed
+   (movl (:rcontext x8632::tcr.save1) (% arg_z))
+   (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
+   (movl ($ '#.$XNOSPREAD) (% arg_y))
+   (set-nargs 2)
+   (jmp-subprim .SPksignalerr) ))
+
+
+
+;;; This needs to:
+;;; (a) call the .SPffcall subprimitive, which will discard the foreign
+;;;     stack frame allocated by WITH-VARIABLE-C-FRAME in %FF-CALL
+;;; (b) re-establish the same foreign stack frame and store the results
+;;;     there.
+;;;
+;;; The flags argument tells us what/where the result is:
+;;;
+;;;; flags   meaning
+;;;    0     32-bit value in EAX
+;;;    1     single-float value on x87 stack
+;;;    2     double-float value on x87 stack
+;;;    3     64-bit value with low half in EAX, high half in tcr.unboxed1
+
+(defx8632lapfunction %do-ff-call ((flags 4) #|(ra 0)|# (frame arg_y) (entry arg_z))
+  (save-stackargs-frame 1)
+  (push (% arg_y))
+  (push (% arg_z))
+  (call-subprim .SPffcall)
+  ;; there might be an fp result on x87 stack, so don't use
+  ;; any mmx instructions until the result has been read.
+  (movd (:rcontext x8632::tcr.foreign-sp) (% xmm0))
+  (movd (% xmm0) (@ (% frame)))
+  (movl (% frame) (:rcontext x8632::tcr.foreign-sp))
+  (cmpl ($ 0) (@ -4 (% ebp)))
+  (jne @fp-or-doubleword)
+  (movl (% eax) (@ 4 (% frame)))
+  @done
+  (movl ($ nil) (% arg_z))
+  (restore-simple-frame)
+  (single-value-return)
+  @fp-or-doubleword
+  (cmpl ($ '2) (@ -4 (% ebp)))
+  (jl @single)
+  (je @double)
+  ;; high 32 bits in tcr.unboxed1 (see .SPffcall)
+  (movl (% eax) (@ 4 (% frame)))
+  (movl (:rcontext x8632::tcr.unboxed1) (% eax))
+  (movl (% eax) (@ 8 (% frame)))
+  (jmp @done)
+  @single
+  (fstps (@ 4 (% frame)))
+  (jmp @done)
+  @double
+  (fstpl (@ 4 (% frame)))
+  (jmp @done))
+
+(defun %ff-call (entry &rest specs-and-vals)
+  (declare (dynamic-extent specs-and-vals))
+  (let* ((len (length specs-and-vals))
+         (total-words 0))
+    (declare (fixnum len total-words))
+    (let* ((result-spec (or (car (last specs-and-vals)) :void))
+           (nargs (ash (the fixnum (1- len)) -1)))
+      (declare (fixnum nargs))
+      (ecase result-spec
+	((:address :unsigned-doubleword :signed-doubleword
+		   :single-float :double-float
+		   :signed-fullword :unsigned-fullword
+		   :signed-halfword :unsigned-halfword
+		   :signed-byte :unsigned-byte
+		   :void)
+	 (do* ((i 0 (1+ i))
+	       (specs specs-and-vals (cddr specs))
+	       (spec (car specs) (car specs)))
+	      ((= i nargs))
+	   (declare (fixnum i))
+	   (case spec
+	     (:registers
+	      (error "don't know what to do with argspec ~s" spec))
+	     ((:double-float :unsigned-doubleword :signed-doubleword)
+	      (incf total-words 2))
+	     ((:address :single-float
+			:signed-fullword :unsigned-fullword
+			:signed-halfword :unsigned-halfword
+			:signed-byte :unsigned-byte)
+              (incf total-words))
+	     (t (if (typep spec 'unsigned-byte)
+		  (incf total-words spec)
+		  (error "Invalid argument spec ~s" spec)))))
+	 ;; It's necessary to ensure that the C frame is the youngest thing on
+	 ;; the foreign stack here.
+	 (with-macptrs ((argptr))
+	   (with-variable-c-frame
+	       total-words frame
+	       (%setf-macptr-to-object argptr frame)
+	       (let* ((offset 8))
+		 (do* ((i 0 (1+ i))
+		       (specs specs-and-vals (cddr specs))
+		       (spec (car specs) (car specs))
+		       (val (cadr specs) (cadr specs)))
+		      ((= i nargs))
+		   (declare (fixnum i))
+		   (case spec
+		     (:double-float
+		      (setf (%get-double-float argptr offset) val)
+		      (incf offset 8))
+		     (:single-float
+		      (setf (%get-single-float argptr offset) val)
+		      (incf offset 4))
+		     (:signed-doubleword
+		      (setf (%%get-signed-longlong argptr offset) val)
+		      (incf offset 8))
+		     (:unsigned-doubleword
+		      (setf (%%get-unsigned-longlong argptr offset) val)
+		      (incf offset 8))
+		     (:address
+		      (setf (%get-ptr argptr offset) val)
+		      (incf offset 4))
+		     ((:signed-fullword :signed-halfword :signed-byte)
+		      (setf (%get-signed-natural argptr offset) val)
+		      (incf offset 4))
+		     ((:unsigned-fullword :unsigned-halfword :unsigned-byte)
+		      (setf (%get-natural argptr offset) val)
+		      (incf offset 4))
+		     (t
+		      (let* ((p 0))
+			(declare (fixnum p))
+			(dotimes (i (the fixnum spec))
+			  (setf (%get-ptr argptr offset) (%get-ptr val p))
+			  (incf p 4)
+			  (incf offset 4))))))
+		 (let ((flags (case result-spec
+				(:single-float 1)
+				(:double-float 2)
+				((:signed-doubleword :unsigned-doubleword) 3)
+				(t 0))))
+		   (%do-ff-call flags frame entry))
+		 (ecase result-spec
+		   (:void nil)
+		   (:address (%get-ptr argptr 4))
+		   (:unsigned-byte (%get-unsigned-byte argptr 4))
+		   (:signed-byte (%get-signed-byte argptr 4))
+		   (:unsigned-halfword (%get-unsigned-word argptr 4))
+		   (:signed-halfword (%get-signed-word argptr 4))
+		   (:unsigned-fullword (%get-natural argptr 4))
+		   (:signed-fullword (%get-signed-natural argptr 4))
+		   (:unsigned-doubleword (%%get-unsigned-longlong argptr 4))
+		   (:signed-doubleword (%%get-signed-longlong argptr 4))
+		   (:single-float (%get-single-float argptr 4))
+		   (:double-float (%get-double-float argptr 4)))))))))))
+
+;;; end of x86-def.lisp
Index: /branches/new-random/level-0/X86/X8632/x8632-float.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-float.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-float.lisp	(revision 13309)
@@ -0,0 +1,584 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS")
+  (require "NUMBER-CASE-MACRO"))
+
+;;; make a float from hi - high 24 bits mantissa (ignore implied higher bit)
+;;;                   lo -  low 28 bits mantissa
+;;;                   exp  - take low 11 bits
+;;;                   sign - sign(sign) => result
+;;; hi result - 1 bit sign: 11 bits exp: 20 hi bits of hi arg
+;;; lo result - 4 lo bits of hi arg: 28 lo bits of lo arg
+;;; no error checks, no tweaks, no nuthin 
+
+;;; sign is -1, 1, maybe zero
+
+(defx8632lapfunction %make-float-from-fixnums ((dfloat 12) (hi 8) (lo 4) #|(ra 0)|# (exp arg_y) (sign arg_z))
+  (mov (% sign) (% imm0))
+  (movl (@ dfloat (% esp)) (% arg_z))
+  (sar ($ 31) (% imm0))
+  (shl ($ 31) (% imm0))			;insert sign
+  (shl ($ (- 20 x8632::fixnumshift)) (% exp))
+  (orl (% exp) (% imm0))		;insert biased exponent
+  (movl (% imm0) (@ x8632::double-float.val-high (% arg_z)))
+  (movl (@ hi (% esp)) (% arg_y))
+  (andl ($ (ash (1- (ash 1 24)) x8632::fixnumshift)) (% arg_y))
+  (movl (% arg_y) (% imm0))
+  (shrl ($ (+ 4 x8632::fixnumshift)) (% imm0))              ;top 20 bits of hi
+  (orl (% imm0) (@ x8632::double-float.val-high (% arg_z))) ; into high word
+  ;; do low half
+  (movl (@ lo (% esp)) (% imm0))
+  (sar ($ x8632::fixnumshift) (% imm0))
+  (andl ($ (1- (ash 1 28))) (% imm0))
+  (shl ($ (- 28 x8632::fixnumshift)) (% arg_y)) ;position low 4 bits of hi
+  (orl (% arg_y) (% imm0))
+  (movl (% imm0) (@ x8632::double-float.value (% arg_z)))
+  (single-value-return 5))
+
+(defx8632lapfunction %make-short-float-from-fixnums ((sfloat 8) (significand 4) #|(ra 0)|# (biased-exp arg_y) (sign arg_z))
+  (movl (% sign) (% imm0))
+  (movl (@ sfloat (% esp)) (% arg_z))
+  (sarl ($ 31) (% imm0))
+  (shll ($ 31) (% imm0))		;insert sign
+  (shll ($ (- ieee-single-float-exponent-offset x8632::fixnumshift)) (% biased-exp))
+  (or (% biased-exp) (% imm0))		;insert biased exponent
+  (movl (% imm0) (@ x8632::single-float.value (% arg_z)))
+  (movl (@ significand (% esp)) (% imm0))
+  (sar ($ x8632::fixnumshift) (% imm0))
+  (andl ($ (1- (ash 1 ieee-single-float-hidden-bit))) (% imm0))
+  (or (% imm0) (@ x8632::single-float.value (% arg_z)))
+  (single-value-return 4))
+
+;;; Maybe we should trap - or something - on NaNs.
+(defx8632lapfunction %%double-float-abs! ((n arg_y) (val arg_z))
+  (get-double-float n fp1)
+  (put-double-float fp1 val)
+  (btrl ($ 31) (@ x8632::double-float.val-high (% val)))
+  (single-value-return))
+
+(defx8632lapfunction %%short-float-abs! ((n arg_y) (val arg_z))
+  (movl (@ x8632::single-float.value (% n)) (% imm0))
+  (btr ($ 31) (% imm0))
+  (movl (% imm0) (@ x8632::single-float.value (% val)))
+  (single-value-return))
+
+(defx8632lapfunction %double-float-negate! ((src arg_y) (res arg_z))
+  (get-double-float src fp1)
+  (put-double-float fp1 res)
+  (btcl ($ 31) (@ x8632::double-float.val-high (% res)))
+  (single-value-return))
+
+(defx8632lapfunction %short-float-negate! ((src arg_y) (res arg_z))
+  (movl (@ x8632::single-float.value (% src)) (% imm0))
+  (btcl ($ 31) (% imm0))
+  (movl (% imm0) (@ x8632::single-float.value (% res)))
+  (single-value-return))
+
+;;; return hi (25 bits) lo (28 bits) exp sign
+(defx8632lapfunction %integer-decode-double-float ((n arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0)
+	(sign 0)
+	(exp 4)
+	(lo 8)
+	(hi 12))
+    (pushl ($ 0))			;hi
+    (pushl ($ 0))			;lo
+    (pushl ($ 0))			;exp
+    (pushl ($ 0))			;sign
+
+    (movl (@ x8632::double-float.val-high (% n)) (% imm1))
+    (movl ($ '1) (% arg_y))
+    (movl ($ '-1) (% imm0))
+    (btl ($ 31) (% imm1))
+    (cmovcl (% imm0) (% arg_y))
+    (movl (% arg_y) (@ sign (% esp)))
+
+    (movl (% imm1) (% imm0))
+    (andl ($ #x7ff00000) (% imm0))	;exponent
+    (shrl ($ (- 20 x8632::fixnumshift)) (% imm0))
+    (movl (% imm0) (@ exp (% esp)))
+
+    (movl (@ x8632::double-float.value (% n)) (% imm0))
+    (andl ($ #x000fffff) (% imm1))	;high 20 bits of fraction
+    (shldl ($ 4) (% imm0) (% imm1))	;shift in 4 bits from low word
+    (cmpl ($ 0) (@ exp (% esp)))
+    (je @denorm)
+    (or ($ (ash 1 (- ieee-double-float-hidden-bit 28))) (% imm1))
+    @denorm
+    (box-fixnum imm1 arg_y)
+    (movl (% arg_y) (@ hi (% esp)))
+
+    (shll ($ 4) (% imm0))		;shift out bits included in hi
+    (shrl ($ x8632::fixnumshift) (% imm0)) ;and box 28 low bits
+    (movl (% imm0) (@ lo (% esp))))
+  (mark-as-node temp0)
+  (set-nargs 4)
+  (leal (@ '4 (% esp)) (% temp0))
+  (jmp-subprim .SPvalues))
+
+;;; hi is 25 bits lo is 28 bits
+;;; big is 32 lo, 21 hi right justified
+(defx8632lapfunction make-big-53 ((hi 4) #|(ra 0)|# (lo arg_y) (big arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (movl (@ hi (% esp)) (% temp1))
+    (movl (% temp1) (% imm0))
+    (shll ($ (- 28 x8632::fixnumshift)) (% imm0))
+    (unbox-fixnum lo imm1)
+    (orl (% imm0) (% imm1))
+    (movl (% imm1) (@ x8632::misc-data-offset (% big))) ;low 32 bits
+    (movl (% temp1) (% imm0))
+    (sarl ($ (+ 4 x8632::fixnumshift)) (% imm0))
+    (movl (% imm0) (@ (+ 4 x8632::misc-data-offset) (% big)))) ;high 21 bits
+  (mark-as-node temp0)
+  (single-value-return 3))
+
+;;; dfloat must be non-zero
+(defx8632lapfunction dfloat-significand-zeros ((dfloat arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (movl (@ x8632::double-float.value (% dfloat)) (% imm0))
+    (movl (@ x8632::double-float.val-high (% dfloat)) (% imm1))
+    ;; shift imm1 left by count, shifting bits from imm0 in from the right
+    (shldl ($ (1+ ieee-double-float-exponent-width)) (% imm0) (% imm1))
+    (testl (% imm1) (% imm1))
+    (jz @low)
+    (bsrl (% imm1) (% imm0))
+    (xorl ($ (1- x8632::nbits-in-word)) (% imm0))
+    (jmp @done)
+    @low
+    (bsrl (% imm0) (% imm0))
+    (xorl ($ (1- x8632::nbits-in-word)) (% imm0))
+    ;; if we're here, the upper part of the fraction was all zeros,
+    ;; so add the count for those in.
+    (add ($ (- ieee-double-float-mantissa-width 32)) (% imm0))
+    @done
+    (box-fixnum imm0 arg_z))
+  (mark-as-node temp0)
+  (single-value-return))
+
+;;; sfloat must be non-zero
+(defx8632lapfunction sfloat-significand-zeros ((sfloat arg_z))
+  (movl (@ x8632::single-float.value (% sfloat)) (% imm0))
+  (shl ($ (1+ IEEE-single-float-exponent-width)) (% imm0))
+  (bsrl (% imm0) (% imm0))
+  (xorl ($ (1- x8632::nbits-in-word)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %%scale-dfloat! ((dfloat 4) #|(ra 0)|# (int arg_y) (result arg_z))
+  (unbox-fixnum int imm0)
+  (movl (@ dfloat (% esp)) (% temp0))
+  (get-double-float temp0 fp1)
+  (shl ($ (- ieee-double-float-exponent-offset 32)) (% imm0))
+  (movl ($ 0) (@ x8632::double-float.value (% result)))
+  (movl (% imm0) (@ x8632::double-float.val-high (% result)))
+  (get-double-float result fp2)
+  (mulsd (% fp2) (% fp1))
+  (put-double-float fp1 result)
+  (single-value-return 3))
+
+(defx8632lapfunction %%scale-sfloat! ((sfloat 4) #|(ra 0)|# (int arg_y) (result arg_z))
+  (unbox-fixnum int imm0)
+  (movl (@ sfloat (% esp)) (% temp0))
+  (get-single-float temp0 fp1)
+  (shl ($ ieee-single-float-exponent-offset) (% imm0))
+  (movd (% imm0) (% fp2))
+  (mulss (% fp2) (% fp1))
+  (put-single-float fp1 arg_z)
+  (single-value-return 3))
+
+(defx8632lapfunction %copy-double-float ((f1 arg_y) (f2 arg_z))
+  (get-double-float f1 fp1)
+  (put-double-float fp1 f2)
+  (single-value-return))
+
+(defx8632lapfunction %copy-short-float ((f1 arg_y) (f2 arg_z))
+  (get-single-float f1 fp1)
+  (put-single-float fp1 f2)
+  (single-value-return))
+
+(defx8632lapfunction %double-float-exp ((n arg_z))
+  (movl (@ x8632::double-float.val-high (% n)) (% imm0))
+  (shll ($ 1) (% imm0))
+  (shrl ($ (1+ (- ieee-double-float-exponent-offset 32))) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction set-%double-float-exp ((dfloat arg_y) (exp arg_z))
+  (movl (% exp) (% temp0))
+  (shll ($ (1+ (- 20 x8632::fixnumshift))) (% temp0))
+  (shrl ($ 1) (% temp0))
+  (movl (@ x8632::double-float.val-high (% dfloat)) (% imm0))
+  (andl ($ #x800fffff) (% imm0))
+  (orl (% temp0) (% imm0))
+  (movl (% imm0) (@ x8632::double-float.val-high (% dfloat)))
+  (single-value-return))
+
+(defx8632lapfunction %short-float-exp ((n arg_z))
+  (movl (@ x8632::single-float.value (% n)) (% imm0))
+  (shll ($ 1) (% imm0))
+  (shrl ($ (1+ ieee-single-float-exponent-offset)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction set-%short-float-exp ((sfloat arg_y) (exp arg_z))
+  (movl (% exp) (% temp0))
+  (shll ($ (1+ (- ieee-single-float-exponent-offset x8632::fixnumshift))) (% temp0))
+  (shrl ($ 1) (% temp0))
+  (movl (@ x8632::single-float.value (% sfloat)) (% imm0))
+  (andl ($ #x807fffff) (% imm0))
+  (orl (% temp0) (% imm0))
+  (movl (% imm0) (@ x8632::single-float.value (% sfloat)))
+  (single-value-return))
+
+(defx8632lapfunction %short-float->double-float ((src arg_y) (result arg_z))
+  (get-single-float src fp1)
+  (cvtss2sd (% fp1) (% fp1))
+  (put-double-float fp1 result)
+  (single-value-return))
+
+(defx8632lapfunction %double-float->short-float ((src arg_y) (result arg_z))
+  (get-double-float src fp1)
+  (cvtsd2ss (% fp1) (% fp1))
+  (put-single-float fp1 result)
+  (single-value-return))
+
+(defx8632lapfunction %int-to-sfloat! ((int arg_y) (sfloat arg_z))
+  (int-to-single int imm0 fp1)
+  (put-single-float fp1 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %int-to-dfloat ((int arg_y) (dfloat arg_z))
+  (int-to-double int imm0 fp1)
+  (put-double-float fp1 arg_z)
+  (single-value-return))
+
+
+
+
+;;; Manipulate the MXCSR.  It'll fit in a fixnum, but we have to
+;;; load and store it through memory.  On x8664, we can hide the
+;;; 32-bit MXCSR value in a fixnum on the stack; on a 32-bit x86,
+;;; we might need to use a scratch location in the TCR or something.
+
+;;; Return the MXCSR as a fixnum
+(defx8632lapfunction %get-mxcsr ()
+  (stmxcsr (:rcontext x8632::tcr.scratch-mxcsr))
+  (movl (:rcontext x8632::tcr.scratch-mxcsr) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+;;; Store the fixnum in arg_z in the MXCSR.  Just to be
+;;; on the safe side, mask the arg with X86::MXCSR-WRITE-MASK,
+;;; so that only known control and status bits are written to.
+(defx8632lapfunction %set-mxcsr ((val arg_z))
+  (unbox-fixnum val imm0)
+  (andl ($ x86::mxcsr-write-mask) (% imm0))
+  (movl (% imm0) (:rcontext x8632::tcr.scratch-mxcsr))
+  (ldmxcsr (:rcontext x8632::tcr.scratch-mxcsr))
+  (single-value-return))
+
+
+;;; Get the bits that contain exception masks and rounding mode.
+
+(defun %get-mxcsr-control ()
+  (logand x86::mxcsr-control-and-rounding-mask (the fixnum (%get-mxcsr))))
+
+;;; Get the bits that describe current exceptions.
+(defun %get-mxcsr-status ()
+  (logand x86::mxcsr-status-mask (the fixnum (%get-mxcsr))))
+
+;;; Set the bits that describe current exceptions, presumably to clear them.
+(defun %set-mxcsr-status (arg)
+  (%set-mxcsr
+   (logior (logand x86::mxcsr-status-mask arg)
+           (logandc2 (%get-mxcsr) x86::mxcsr-status-mask)))
+  arg)
+
+;;; Set the bits that mask/unmask exceptions and control rounding.
+;;; Clear the bits which describe current exceptions.
+(defun %set-mxcsr-control (arg)
+  (%set-mxcsr (logand x86::mxcsr-control-and-rounding-mask arg)))
+
+;;; Return the MXCSR value in effect after the last ff-call.
+(defx8632lapfunction %get-post-ffi-mxcsr ()
+  (xor (% arg_z) (% arg_z))
+  (movl (:rcontext x8632::tcr.ffi-exception) (%l imm0))
+  (movl (%l arg_z) (:rcontext x8632::tcr.ffi-exception))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+;;; The next several defuns are copied verbatim from x8664-float.lisp.
+;;; It will probably be desirable to factor this code out into a new
+;;; x86-float.lisp, perhaps conditionalized via #+sse2 or something.
+;;; (Some day we may want to support x87 fp and we'll need
+;;; x87-specific versions of these functions.)
+
+;;; start duplicated code
+
+;;; Return the status bits from the last ff-call that represent
+;;; unmasked exceptions
+(defun %ffi-exception-status ()
+  (logior (%get-mxcsr-control)
+          (logand x86::mxcsr-status-mask (the fixnum (%get-post-ffi-mxcsr)))))
+
+;;; See if the binary double-float operation OP set any enabled
+;;; exception bits in the mxcsr
+(defun %df-check-exception-2 (operation op0 op1 fp-status)
+  (declare (type (unsigned-byte 6) fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status
+			   operation 
+			   (%copy-double-float op0 (%make-dfloat)) 
+			   (%copy-double-float op1 (%make-dfloat)))))
+
+(defun %sf-check-exception-2 (operation op0 op1 fp-status)
+  (declare (type (unsigned-byte 6) fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+			   operation
+			   #+32-bit-target
+			   (%copy-short-float op0 (%make-sfloat))
+			   #+64-bit-target op0
+			   #+32-bit-target
+			   (%copy-short-float op1 (%make-sfloat))
+			   #+64-bit-target op1)))
+
+(defun %df-check-exception-1 (operation op0 fp-status)
+  (declare (fixnum fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+                           operation 
+                           (%copy-double-float op0 (%make-dfloat)))))
+
+(defun %sf-check-exception-1 (operation op0 fp-status)
+  (declare (type (unsigned-byte 6) fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+			   operation
+			   #+32-bit-target
+			   (%copy-short-float op0 (%make-sfloat))
+			   #+64-bit-target op0)))
+
+
+(defun fp-condition-from-mxcsr (status-bits control-bits)
+  (declare (fixnum status-bits control-bits))
+  (cond 
+   ((and (logbitp x86::mxcsr-ie-bit status-bits)
+         (not (logbitp x86::mxcsr-im-bit control-bits)))
+    'floating-point-invalid-operation)
+   ((and (logbitp x86::mxcsr-oe-bit status-bits)
+         (not (logbitp x86::mxcsr-om-bit control-bits)))
+    'floating-point-overflow)
+   ((and (logbitp x86::mxcsr-ue-bit status-bits)
+         (not (logbitp x86::mxcsr-um-bit control-bits)))
+    'floating-point-underflow)
+   ((and (logbitp x86::mxcsr-ze-bit status-bits)
+         (not (logbitp x86::mxcsr-zm-bit control-bits)))
+    'division-by-zero)
+   ((and (logbitp x86::mxcsr-pe-bit status-bits)
+         (not (logbitp x86::mxcsr-pm-bit control-bits)))
+    'floating-point-inexact)))
+
+(defun %fp-error-from-status (status-bits  operation op0 &optional op1)
+  (declare (type (unsigned-byte 6) status-bits))
+  (let* ((condition-class (fp-condition-from-mxcsr status-bits (%get-mxcsr-control))))
+    (if condition-class
+      (let* ((operands (if op1 (list op0 op1) (list op0))))
+        (error (make-instance condition-class
+                              :operation operation
+                              :operands operands))))))
+
+(defvar *rounding-mode-alist*
+  '((:nearest . 0) (:zero . 1) (:positive . 2) (:negative . 3)))
+
+(defun get-fpu-mode (&optional (mode nil mode-p))
+  (let* ((flags (%get-mxcsr-control)))
+    (declare (fixnum flags))
+    (let* ((rounding-mode
+            (car (nth (+ (if (logbitp x86::mxcsr-rc0-bit flags) 1 0)
+                         (if (logbitp x86::mxcsr-rc1-bit flags) 2 0))
+                      *rounding-mode-alist*)))
+           (overflow (not (logbitp x86::mxcsr-om-bit flags)))
+           (underflow (not (logbitp x86::mxcsr-um-bit flags)))
+           (division-by-zero (not (logbitp x86::mxcsr-zm-bit flags)))
+           (invalid (not (logbitp x86::mxcsr-im-bit flags)))
+           (inexact (not (logbitp x86::mxcsr-pm-bit flags))))
+    (if mode-p
+      (ecase mode
+        (:rounding-mode rounding-mode)
+        (:overflow overflow)
+        (:underflow underflow)
+        (:division-by-zero division-by-zero)
+        (:invalid invalid)
+        (:inexact inexact))
+      `(:rounding-mode ,rounding-mode
+        :overflow ,overflow
+        :underflow ,underflow
+        :division-by-zero ,division-by-zero
+        :invalid ,invalid
+        :inexact ,inexact)))))
+
+;;; did we document this?
+(defun set-fpu-mode (&key (rounding-mode :nearest rounding-p)
+                          (overflow t overflow-p)
+                          (underflow t underflow-p)
+                          (division-by-zero t zero-p)
+                          (invalid t invalid-p)
+                          (inexact t inexact-p))
+  (let* ((current (%get-mxcsr-control))
+         (new current))
+    (declare (fixnum current new))
+    (when rounding-p
+      (let* ((rc-bits (or
+                       (cdr (assoc rounding-mode *rounding-mode-alist*))
+                       (error "Unknown rounding mode: ~s" rounding-mode))))
+        (declare (fixnum rc-bits))
+        (if (logbitp 0 rc-bits)
+          (bitsetf x86::mxcsr-rc0-bit new)
+          (bitclrf x86::mxcsr-rc0-bit new))
+        (if (logbitp 1 rc-bits)
+          (bitsetf x86::mxcsr-rc1-bit new)
+          (bitclrf x86::mxcsr-rc1-bit new))))
+    (when invalid-p
+      (if invalid
+        (bitclrf x86::mxcsr-im-bit new)
+        (bitsetf x86::mxcsr-im-bit new)))
+    (when overflow-p
+      (if overflow
+        (bitclrf x86::mxcsr-om-bit new)
+        (bitsetf x86::mxcsr-om-bit new)))
+    (when underflow-p
+      (if underflow
+        (bitclrf x86::mxcsr-um-bit new)
+        (bitsetf x86::mxcsr-um-bit new)))
+    (when zero-p
+      (if division-by-zero
+        (bitclrf x86::mxcsr-zm-bit new)
+        (bitsetf x86::mxcsr-zm-bit new)))
+    (when inexact-p
+      (if inexact
+        (bitclrf x86::mxcsr-pm-bit new)
+        (bitsetf x86::mxcsr-pm-bit new)))
+    (unless (= current new)
+      (%set-mxcsr-control new))
+    (%get-mxcsr)))
+
+;;; end duplicated code
+
+;;; Don't we already have about 20 versions of this ?
+(defx8632lapfunction %double-float-from-macptr! ((ptr 4) #|(ra 0)|# (byte-offset arg_y) (dest arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (movl (@ ptr (% esp)) (% temp1))
+    (macptr-ptr temp1 imm0)
+    (unbox-fixnum byte-offset imm1)
+    (movsd (@ (% imm0) (% imm1)) (% fp1))
+    (put-double-float fp1 dest))
+  (mark-as-node temp0)
+  (single-value-return 3))
+
+;;; Copy a single float pointed at by the macptr in single
+;;; to a double float pointed at by the macptr in double
+(defx8632lapfunction %single-float-ptr->double-float-ptr ((single arg_y) (double arg_z))
+  (check-nargs 2)
+  (macptr-ptr single imm0)
+  (movss (@ (% imm0)) (% fp1))
+  (cvtss2sd (% fp1) (% fp1))
+  (macptr-ptr double imm0)
+  (movsd (% fp1) (@ (% imm0)))
+  (single-value-return))
+
+;;; Copy a double float pointed at by the macptr in double
+;;; to a single float pointed at by the macptr in single.
+(defx8632lapfunction %double-float-ptr->single-float-ptr ((double arg_y) (single arg_z))
+  (check-nargs 2)
+  (macptr-ptr double imm0)
+  (movsd (@ (% imm0)) (% fp1))
+  (cvtsd2ss (% fp1) (% fp1))
+  (macptr-ptr single imm0)
+  (movss (% fp1) (@ (% imm0)))
+  (single-value-return))
+
+(defx8632lapfunction %set-ieee-single-float-from-double ((src arg_y) (macptr arg_z))
+  (check-nargs 2)
+  (macptr-ptr macptr imm0)
+  (get-double-float src fp1)
+  (cvtsd2ss (% fp1) (% fp1))
+  (movss (% fp1) (@ (% imm0)))
+  (single-value-return))
+
+(defun host-single-float-from-unsigned-byte-32 (u32)
+  (let* ((f (%make-sfloat)))
+    (setf (uvref f x8632::single-float.value-cell) u32)
+    f))
+
+(defun single-float-bits (f)
+  (uvref f x8632::single-float.value-cell))
+
+(defun double-float-bits (f)
+  (values (uvref f target::double-float.val-high-cell)
+          (uvref f target::double-float.value-cell)))
+
+(defun double-float-from-bits (high low)
+  (let* ((f (%make-dfloat)))
+    (setf (uvref f target::double-float.val-high-cell) high
+          (uvref f target::double-float.value-cell) low)
+    f))
+
+;;; Return T if n is negative, else NIL.
+(defx8632lapfunction %double-float-sign ((n arg_z))
+  (movl (@ x8632::double-float.val-high (% n)) (% imm0))
+  (testl (% imm0) (% imm0))
+  (movl ($ (target-t-value)) (% imm0))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (cmovll (% imm0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %short-float-sign ((n arg_z))
+  (movl (@ x8632::single-float.value (% n)) (% imm0))
+  (testl (% imm0) (% imm0))
+  (movl ($ (target-t-value)) (% imm0))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (cmovll (% imm0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %double-float-sqrt! ((n arg_y) (result arg_z))
+  (get-double-float n fp0)
+  (sqrtsd (% fp0) (% fp0))
+  (put-double-float fp0 result)
+  (single-value-return))
+
+(defx8632lapfunction %single-float-sqrt! ((n arg_y) (result arg_z))
+  (get-single-float n fp0)
+  (sqrtss (% fp0) (% fp0))
+  (put-single-float fp0 arg_z)
+  (single-value-return))
+
+
+
Index: /branches/new-random/level-0/X86/X8632/x8632-hash.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-hash.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-hash.lisp	(revision 13309)
@@ -0,0 +1,127 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "HASHENV" "ccl:xdump;hashenv"))
+
+;;; This should stay in LAP so that it's fast
+;;; Equivalent to cl:mod when both args are positive fixnums
+(defx8632lapfunction fast-mod ((number arg_y) (divisor arg_z))
+  (xorl (% edx) (% edx))		;aka temp1
+  (mov (% number) (% imm0))
+  (div (% divisor))			;boxed remainder goes into edx/temp1
+  (mov (% edx) (% arg_z))
+  (single-value-return))
+
+;; Faster mod based on Bruce Hoult's Dylan version, modified to use a
+;; branch-free max.
+(defx8632lapfunction fast-mod-3 ((number 4) #|(ra 0)|# (divisor arg_y) (recip arg_z))
+  (std)					;temp1 now unboxed
+  (let ((imm1 temp1)
+	(n temp0))
+    (movl (@ number (% esp)) (% n))
+    (movl (% n) (% imm0))
+    (shrl ($ target::fixnumshift) (% imm0)) ;logical shift is intentional
+    (mov (% recip) (% imm1))
+    (mul (% imm1)) ;; -> hi word in imm1 (unboxed)
+    (mov (% divisor) (% imm0))
+    (mul (% imm1)) ;; -> lo word in imm0 (boxed)
+    (subl (% imm0) (% n))
+    (subl (% divisor) (% n))
+    (mov (% n) (% arg_z))
+    (mov (% n) (% imm0))
+    (sar ($ (1- target::nbits-in-word)) (% imm0))
+    (andl (% imm0) (% divisor))
+    (addl (% divisor) (% arg_z)))
+  (xorl (% temp1) (% temp1))
+  (cld)					;temp1 now boxed
+  (single-value-return 3))
+
+(defx8632lapfunction %dfloat-hash ((key arg_z))
+  (movl (@ x8632::double-float.value (% key)) (% imm0))
+  (addl (@ x8632::double-float.val-high (% key)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %sfloat-hash ((key arg_z))
+  (movl (@ x8632::single-float.value (% key)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %macptr-hash ((key arg_z))
+  (movl (@ x8632::macptr.address (% key)) (% imm0))
+  (box-fixnum imm0 temp0)
+  (shll ($ (- 24 x8632::fixnumshift)) (% temp0))
+  (addl (% temp0) (% imm0))
+  (movl ($ (lognot x8632::fixnummask)) (% arg_z))
+  (andl (% imm0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %bignum-hash ((key arg_z))
+  (mark-as-imm temp1)
+  (let ((header imm0)
+	(offset temp1)
+	(ndigits temp0))
+    (getvheader key header)
+    (header-length header ndigits)
+    (xorl (% offset) (% offset))
+    (let ((immhash header))
+      @loop
+      (roll ($ 13) (% immhash))
+      (addl (@ x8632::misc-data-offset (% key) (% offset)) (% immhash))
+      (addl ($ 4) (% offset))
+      (subl ($ '1) (% ndigits))
+      (jne @loop)
+      (box-fixnum immhash arg_z)))
+  (mark-as-node temp1)
+  (single-value-return))
+
+(defx8632lapfunction %get-fwdnum ()
+  (ref-global target::fwdnum arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %get-gc-count ()
+  (ref-global target::gc-count arg_z)
+  (single-value-return))
+
+;;; Setting a key in a hash-table vector needs to 
+;;; ensure that the vector header gets memoized as well
+(defx8632lapfunction %set-hash-table-vector-key ((vector 4) #|(ra 0)|# (index arg_y) (value arg_z))
+  (pop (% temp1))			;return address
+  (pop (% temp0))			;.SPset-hash-key wants arg in temp0
+  (discard-reserved-frame)
+  (push (% temp1))
+  (jmp-subprim .SPset-hash-key))
+
+;;; This needs to be done out-of-line, to handle EGC memoization.
+(defx8632lapfunction %set-hash-table-vector-key-conditional ((offset 8)
+                                                             (vector 4)
+                                                             #|(ra 0)|#
+                                                             (old arg_y)
+                                                             (new arg_z))
+  (movl (@ offset (% esp)) (% temp0))
+  (movl (@ vector (% esp)) (% temp1))
+  (save-simple-frame)
+  (call-subprim .SPset-hash-key-conditional)
+  (restore-simple-frame)
+  (single-value-return 4))
+
+
+;;; Strip the tag bits to turn x into a fixnum
+(defx8632lapfunction strip-tag-to-fixnum ((x arg_z))
+  (andb ($ (lognot x8632::fixnummask)) (%b x))
+  (single-value-return))
+
Index: /branches/new-random/level-0/X86/X8632/x8632-misc.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-misc.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-misc.lisp	(revision 13309)
@@ -0,0 +1,852 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Copy N bytes from pointer src, starting at byte offset src-offset,
+;;; to ivector dest, starting at offset dest-offset.
+;;; It's fine to leave this in lap.
+;;; Depending on alignment, it might make sense to move more than
+;;; a byte at a time.
+;;; Does no arg checking of any kind.  Really.
+
+;;; I went ahead and used the INC and DEC instructions here, since
+;;; they're shorter than the equivalent ADD/SUB.  Intel's optimization
+;;; manual advises avoiding INC and DEC because they might cause
+;;; dependencies on earlier instructions that set the flags.  So, if
+;;; these functions end up being hot, replacing the inc/dec insns
+;;; might be worth a try.
+
+(defx8632lapfunction %copy-ptr-to-ivector ((src 12)
+					   (src-byte-offset 8)
+					   (dest 4)
+					   #|(ra 0)|#
+					   (dest-byte-offset arg_y)
+					   (nbytes arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm arg_y)
+  (let ((foreign-ptr temp0)		;raw foreign pointer
+	(ivector temp1)			;destination ivector
+	(j arg_y))			;unboxed index into ivector
+    (movl (@ src (% esp)) (% temp1))
+    (macptr-ptr temp1 foreign-ptr)
+    (movl (@ src-byte-offset (% esp)) (% temp1))
+    (unbox-fixnum temp1 imm0)
+    (addl (% imm0) (% foreign-ptr))	;point to starting byte in src
+    (movl (@ dest (% esp)) (% ivector))
+    (sarl ($ x8632::fixnumshift) (% j))	;unbox dest-byte-offset
+    (testl (% nbytes) (% nbytes))
+    (jmp @test)
+    @loop
+    (movb (@ (% foreign-ptr)) (%b imm0))
+    (incl (% foreign-ptr))
+    (movb (%b imm0) (@ x8632::misc-data-offset (% ivector) (% j)))
+    (incl (% j))
+    (subl ($ '1) (% nbytes))
+    @test
+    (jne @loop)
+    (movl (% ivector) (% arg_z)))
+  (mark-as-node temp0)
+  (mark-as-node arg_y)
+  (single-value-return 5))
+
+(defx8632lapfunction %copy-ivector-to-ptr ((src 12)
+					   (src-byte-offset 8)
+					   (dest 4)
+					   #|(ra 0)|#
+					   (dest-byte-offset arg_y)
+					   (nbytes arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm arg_y)
+  (let ((foreign-ptr temp0)		;raw foreign pointer
+	(ivector temp1)			;source ivector
+	(j arg_y))			;unboxed index into ivector
+    (movl (@ dest (% esp)) (% temp1))
+    (macptr-ptr temp1 foreign-ptr)
+    (unbox-fixnum dest-byte-offset imm0)
+    (addl (% imm0) (% foreign-ptr))	;point to starting byte in dest
+    (movl (@ src (% esp)) (% ivector))
+    (movl (@ src-byte-offset (% esp)) (% j))
+    (sarl ($ x8632::fixnumshift) (% j))	;unbox src-byte-offset
+    (test (% nbytes) (% nbytes))
+    (jmp @test)
+    @loop
+    (movb (@ x8632::misc-data-offset (% ivector) (% j)) (%b imm0))
+    (incl (% j))
+    (movb (%b imm0) (@ (% foreign-ptr)))
+    (incl (% foreign-ptr))
+    (subl ($ '1) (% nbytes))
+    @test
+    (jne @loop)
+    (movl (@ dest (% esp)) (% arg_z)))
+  (mark-as-node temp0)
+  (mark-as-node arg_y)
+  (single-value-return 5))
+
+(defx8632lapfunction %copy-ivector-to-ivector ((src 12) 
+					       (src-byte-offset 8)
+					       (dest 4)
+					       #|(ra 0)|#
+					       (dest-byte-offset arg_y)
+					       (nbytes arg_z))
+  (movl (@ src (% esp)) (% temp0))
+  (movl (@ src-byte-offset (% esp)) (% temp1))
+  (unbox-fixnum nbytes imm0)		;will be used below
+  (push (% nbytes))			;put loop counter on stack
+  (movl (@ (+ 4 dest) (% esp)) (% arg_z))
+  (mark-as-imm temp1)
+  (mark-as-imm arg_y)
+  (sarl ($ x8632::fixnumshift) (% temp1)) ;unboxed src index
+  (sarl ($ x8632::fixnumshift) (% arg_y)) ;unboxed dest index
+  (let ((a temp0)
+	(i temp1)
+	(b arg_z)
+	(j arg_y))
+    ;; copy nbytes starting at a[i] to b[j]
+    (cmpl (% b) (% a))
+    (jne @front)
+    (cmpl (% i) (% j))
+    (jg @back)
+    @front
+    (testl (% imm0) (% imm0))		;test nbytes
+    (jmp @front-test)
+    @front-loop
+    (movb (@ x8632::misc-data-offset (% a) (% i)) (%b imm0))
+    (movb (%b imm0) (@ x8632::misc-data-offset (% b) (% j)))
+    (incl (% i))
+    (incl (% j))
+    (subl ($ '1) (@ (% esp)))
+    @front-test
+    (jne @front-loop)
+    (jmp @done)
+    @back
+    ;; unboxed nbytes in imm0
+    (addl (% imm0) (% i))
+    (addl (% imm0) (% j))
+    (testl (% imm0) (% imm0))
+    (jmp @back-test)
+    @back-loop
+    (decl (% i))
+    (decl (% j))
+    (movb (@ x8632::misc-data-offset (% a) (% i)) (%b imm0))
+    (movb (%b imm0) (@ x8632::misc-data-offset (% b) (% j)))
+    (subl ($ '1) (@ (% esp)))
+    @back-test
+    (jne @back-loop)
+    @done
+    ;; dest already in arg_z
+    (addl ($ 4) (% esp))		;pop nbytes
+    (mark-as-node temp1)
+    (mark-as-node arg_y)
+    (single-value-return 5)))
+
+(defx8632lapfunction %copy-gvector-to-gvector ((src 12)
+					       (src-element 8)
+					       (dest 4)
+					       #|(ra 0)|#
+					       (dest-element arg_y)
+					       (nelements arg_z))
+  (let ((a temp0)
+	(i imm0)
+	(b arg_z)
+	(j arg_y)
+	(val temp1))
+    (movl (% nelements) (% val))     ;will be used below
+    (push (% nelements))	     ;loop counter on stack (use ebp?)
+    (movl (@ (+ 4 src) (% esp)) (% a))
+    (movl (@ (+ 4 src-element) (% esp)) (% i))
+    (movl (@ (+ 4 dest) (% esp)) (% b))
+    ;; j/arg_y already set
+    (cmpl (% a) (% b))
+    (jne @front)
+    (rcmp (% i) (% j))
+    (jl @back)
+    @front
+    (testl (% val) (% val))		;test nelements
+    (jmp @front-test)
+    @front-loop
+    (movl (@ x8632::misc-data-offset (% a) (% i)) (% val))
+    (movl (% val) (@ x8632::misc-data-offset (% b) (% j)))
+    (addl ($ '1) (% i))
+    (addl ($ '1) (% j))
+    (subl ($ '1) (@ (% esp)))
+    @front-test
+    (jne @front-loop)
+    (jmp @done)
+    @back
+    ;; nelements in val (from above)
+    (addl (% val) (% i))
+    (addl (% val) (% j))
+    (testl (% val) (% val))
+    (jmp @back-test)
+    @back-loop
+    (subl ($ '1) (% i))
+    (subl ($ '1) (% j))
+    (movl (@ x8632::misc-data-offset (% a) (% i)) (% val))
+    (movl (% val) (@ x8632::misc-data-offset (% b) (% j)))
+    (subl ($ '1) (@ (% esp)))
+    @back-test
+    (jne @back-loop)
+    @done
+    ;; dest already in arg_z
+    (addl ($ 4) (% esp))		;pop loop counter
+    (single-value-return 5)))
+
+(defx8632lapfunction %heap-bytes-allocated ()
+  (movl (@ (% :rcontext) x8632::tcr.save-allocptr) (% temp1))
+  (movl (@ (% :rcontext) x8632::tcr.last-allocptr) (% temp0))
+  (cmpl ($ -8) (% temp1))		;void_allocptr
+  (movq (@ (% :rcontext) x8632::tcr.total-bytes-allocated-low) (% mm0))
+  (jz @go)
+  (movl (% temp0) (% arg_y))
+  (subl (% temp1) (% temp0))
+  (testl (% arg_y) (% arg_y))
+  (jz @go)
+  (movd (% temp0) (% mm1))
+  (paddq (% mm1) (% mm0))
+  @go
+  (jmp-subprim .SPmakeu64))
+
+(defx8632lapfunction values ()
+  (:arglist (&rest values))
+  (save-frame-variable-arg-count)
+  (push-argregs)
+  (jmp-subprim .SPnvalret))
+
+(defx8632lapfunction rdtsc ()
+  (mark-as-imm temp1)			;aka edx
+  (:byte #x0f)                          ;two-byte rdtsc opcode
+  (:byte #x31)                          ;is #x0f #x31
+  (box-fixnum imm0 arg_z)
+  (mark-as-node temp1)
+  (single-value-return))
+
+;;; Return all 64 bits of the time-stamp counter as an unsigned integer.
+(defx8632lapfunction rdtsc64 ()
+  (mark-as-imm temp1)			;aka edx
+  (:byte #x0f)                          ;two-byte rdtsc opcode
+  (:byte #x31)                          ;is #x0f #x31
+  (movd (% eax) (% mm0))
+  (movd (% edx) (% mm1))
+  (psllq ($ 32) (% mm1))
+  (por (% mm1) (% mm0))
+  (mark-as-node temp1)
+  (jmp-subprim .SPmakeu64))
+
+;;; It would be nice if (%setf-macptr macptr (ash (the fixnum value)
+;;; ash::fixnumshift)) would do this inline.
+
+(defx8632lapfunction %setf-macptr-to-object ((macptr arg_y) (object arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= macptr x8632::subtag-macptr)
+  (movl (% object) (@ x8632::macptr.address (% macptr)))
+  (single-value-return))
+
+(defx8632lapfunction %fixnum-from-macptr ((macptr arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= arg_z x8632::subtag-macptr)
+  (movl (@ x8632::macptr.address (% arg_z)) (% imm0))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (trap-unless-lisptag= imm0 x8632::tag-fixnum imm1))
+  (mark-as-node temp0)
+  (movl (% imm0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %%get-unsigned-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr x8632::subtag-macptr)
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (macptr-ptr ptr imm1)
+    (unbox-fixnum offset imm0)
+    (movq (@ (% imm1) (% imm0)) (% mm0)))
+  (mark-as-node temp0)
+  (jmp-subprim .SPmakeu64))
+
+(defx8632lapfunction %%get-signed-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr x8632::subtag-macptr)
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (macptr-ptr ptr imm1)
+    (unbox-fixnum offset imm0)
+    (movq (@ (% imm1) (% imm0)) (% mm0)))
+  (mark-as-node temp0)
+  (jmp-subprim .SPmakes64))
+
+(defx8632lapfunction %%set-unsigned-longlong ((ptr 4)
+					      #|(ra 0)|#
+					      (offset arg_y)
+					      (val arg_z))
+  (let ((rptr temp0)
+	(imm1 temp1)
+        (ptr-in-frame -4))
+    (save-stackargs-frame 1)
+    (movl (@ ptr-in-frame (% ebp)) (% rptr))
+    (trap-unless-typecode= rptr x8632::subtag-macptr)
+    (call-subprim .SPgetu64)
+    (macptr-ptr rptr imm0)
+    (mark-as-imm temp1)
+    (unbox-fixnum offset imm1)
+    (movq (% mm0) (@ (% imm0) (% imm1)))
+    (mark-as-node temp1)
+    (restore-simple-frame)
+    (single-value-return)))
+
+(defx8632lapfunction %%set-signed-longlong ((ptr 4)
+					    #|(ra 0)|#
+                                            (offset arg_y)
+                                            (val arg_z))
+  (let ((rptr temp0)
+	(imm1 temp1)
+        (ptr-in-frame -4))
+    (save-stackargs-frame 1)
+    (movl (@ ptr-in-frame (% ebp)) (% rptr))
+    (trap-unless-typecode= rptr x8632::subtag-macptr)
+    (call-subprim .SPgets64)
+    (macptr-ptr rptr imm0)
+    (mark-as-imm temp1)
+    (unbox-fixnum offset imm1)
+    (movq (% mm0) (@ (% imm0) (% imm1)))
+    (mark-as-node temp1)
+    (restore-simple-frame)
+    (single-value-return)))
+
+(defx8632lapfunction interrupt-level ()
+  (movl (@ (% :rcontext) x8632::tcr.tlb-pointer) (% imm0))
+  (movl (@ x8632::interrupt-level-binding-index (% imm0)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction set-interrupt-level ((new arg_z))
+  (movl (@ (% :rcontext) x8632::tcr.tlb-pointer) (% imm0))
+  (trap-unless-fixnum new)
+  (movl (% new) (@ x8632::interrupt-level-binding-index (% imm0)))
+  (single-value-return))
+
+(defx8632lapfunction %current-tcr ()
+  (movl (@ (% :rcontext) x8632::tcr.linear) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %tcr-toplevel-function ((tcr arg_z))
+  (check-nargs 1)
+  (movl (@ x8632::tcr.vs-area (% tcr)) (% temp0))
+  (movl (@ x8632::area.high (% temp0)) (% imm0)) ;bottom of vstack
+  (cmpl (% tcr) (@ (% :rcontext) x8632::tcr.linear))
+  (jz @myself)
+  (cmpl (% imm0) (@ x8632::area.active (% temp0)))
+  (jmp @finish)
+  @myself
+  (cmpl (% imm0) (% esp))
+  @finish
+  (movl ($ (target-nil-value)) (% arg_z))
+  (cmovnel (@ (- x8632::node-size) (% imm0)) (% arg_z))
+  (single-value-return))
+  
+(defx8632lapfunction %set-tcr-toplevel-function ((tcr arg_y) (fun arg_z))
+  (check-nargs 2)
+  (movl (@ x8632::tcr.vs-area (% tcr)) (% temp0))
+  (movl (@ x8632::area.high (% temp0)) (% imm0))
+  (cmpl (% tcr) (@ (% :rcontext) x8632::tcr.linear))
+  (jz @myself)
+  (cmpl (% imm0) (@ x8632::area.active (% temp0))) ;vstack empty?
+  (jmp @room)
+  @myself
+  (cmpl (% imm0) (% esp))
+  @room
+  (leal (@ (- x8632::node-size) (% imm0)) (% imm0))
+  (movl ($ 0) (@ (% imm0)))
+  (jne @have-room)
+  (movl (% imm0) (@ x8632::area.active (% temp0)))
+  (movl (% imm0) (@ x8632::tcr.save-vsp (% tcr)))
+  (jmp @have-room)
+  @have-room
+  (movl (% fun) (@ (% imm0)))
+  (single-value-return))
+
+;;; This needs to be done out-of-line, to handle EGC memoization.
+(defx8632lapfunction %store-node-conditional ((offset 8)
+					      (object 4)
+					      #|(ra 0)|#
+					      (old arg_y)
+					      (new arg_z))
+  (movl (@ offset (% esp)) (% temp0))
+  (movl (@ object (% esp)) (% temp1))
+  (save-simple-frame)
+  (call-subprim .SPstore-node-conditional)
+  (restore-simple-frame)
+  (single-value-return 4))
+
+(defx8632lapfunction %store-immediate-conditional ((offset 8)
+						   (object 4)
+						   #|(ra 0)|#
+						   (old arg_y)
+						   (new arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0)
+	(robject temp1))
+    (movl (@ offset (% esp)) (% imm1))
+    (sarl ($ x8632::fixnumshift) (% imm1))
+    (movl (@ object (% esp)) (% robject))
+    @again
+    (movl (@ (% robject) (% imm1)) (% eax))
+    (cmpl (% eax) (% old))
+    (jne @lose)
+    (lock)
+    (cmpxchgl (% new) (@ (% robject) (% imm1)))
+    (jne @again)
+    (movl ($ (target-t-value)) (% arg_z))
+    (mark-as-node temp0)
+    (single-value-return 4)
+    @lose
+    (movl ($ (target-nil-value)) (% arg_z))
+    (mark-as-node temp0)
+    (single-value-return 4)))
+
+(defx8632lapfunction set-%gcable-macptrs% ((ptr arg_z))
+  @again
+  (movl (@ (+ (target-nil-value) (x8632::kernel-global gcable-pointers))) (% eax))
+  (movl (% eax) (@ x8632::xmacptr.link (% ptr)))
+  (lock)
+  (cmpxchgl (% ptr) (@ (+ (target-nil-value) (x8632::kernel-global gcable-pointers))))
+  (jne @again)
+  (single-value-return))
+
+;;; Atomically increment or decrement the gc-inhibit-count kernel-global
+;;; (It's decremented if it's currently negative, incremented otherwise.)
+(defx8632lapfunction %lock-gc-lock ()
+  @again
+  (movl (@ (+ (target-nil-value) (x8632::kernel-global gc-inhibit-count))) (% eax))
+  (lea (@ '-1 (% eax)) (% temp0))
+  (lea (@ '1 (% eax)) (% arg_z))
+  (test (% eax) (% eax))
+  (cmovsl (% temp0) (% arg_z))
+  (lock)
+  (cmpxchgl (% arg_z) (@ (+ (target-nil-value) (x8632::kernel-global gc-inhibit-count))))
+  (jnz @again)
+  (single-value-return))
+
+;;; Atomically decrement or increment the gc-inhibit-count kernel-global
+;;; (It's incremented if it's currently negative, incremented otherwise.)
+;;; If it's incremented from -1 to 0, try to GC (maybe just a little.)
+(defx8632lapfunction %unlock-gc-lock ()
+  @again
+  (movl (@ (+ (target-nil-value) (x8632::kernel-global gc-inhibit-count)))
+        (% eax))
+  (lea (@ '1 (% eax)) (% temp0))
+  (cmpl ($ -1) (% eax))
+  (lea (@ '-1 (% eax)) (% arg_z))
+  (cmovlel (% temp0) (% arg_z))
+  (lock)
+  (cmpxchgl (% arg_z) (@ (+ (target-nil-value) (x8632::kernel-global gc-inhibit-count))))
+  (jne @again)
+  (cmpl ($ '-1) (% eax))
+  (jne @done)
+  ;; The GC tried to run while it was inhibited.  Unless something else
+  ;; has just inhibited it, it should be possible to GC now.
+  (mov ($ arch::gc-trap-function-immediate-gc) (% imm0))
+  (uuo-gc-trap)
+  @done
+  (single-value-return))
+
+(defx8632lapfunction %atomic-incf-node ((by 4) #|(ra 0)|# (node arg_y) (disp arg_z))
+  (check-nargs 3)
+  (mark-as-imm temp0)
+  (let ((imm1 temp0)
+	(rby temp1))
+    (movl (@ by (% esp)) (% rby))
+    (unbox-fixnum disp imm1)
+    @again
+    (movl (@ (% node) (% imm1)) (% eax))
+    (lea (@ (% eax) (% rby)) (% arg_z))
+    (lock)
+    (cmpxchgl (% arg_z) (@ (% node) (% imm1)))
+    (jne @again))
+  (mark-as-node temp0)
+  (single-value-return 3))
+
+(defx8632lapfunction %atomic-incf-ptr ((ptr arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (let ((imm1 temp0)
+	(imm2 temp1))
+    (macptr-ptr ptr imm2)
+    @again
+    (movl (@ (% imm2)) (% eax))
+    (lea (@ 1 (% eax)) (% imm1))
+    (lock)
+    (cmpxchgl (% imm1) (@ (% imm2)))
+    (jne @again)
+    (box-fixnum imm1 arg_z))
+  (mark-as-node temp0)
+  (mark-as-node temp1)
+  (single-value-return))
+
+(defx8632lapfunction %atomic-incf-ptr-by ((ptr arg_y) (by arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (let ((imm1 temp0)
+	(imm2 temp1))
+    (macptr-ptr ptr imm2)
+    @again
+    (movl (@ (% imm2)) (% eax))
+    (unbox-fixnum by imm1)
+    (add (% eax) (% imm1))
+    (lock)
+    (cmpxchgl (% imm1) (@ (% imm2)))
+    (jnz @again)
+    (box-fixnum imm1 arg_z))
+  (mark-as-node temp0)
+  (mark-as-node temp1)
+  (single-value-return))
+
+(defx8632lapfunction %atomic-decf-ptr ((ptr arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (let ((imm1 temp0)
+	(imm2 temp1))
+    (macptr-ptr ptr imm2)
+    @again
+    (movl (@ (% imm2)) (% eax))
+    (lea (@ -1 (% eax)) (% imm1))
+    (lock)
+    (cmpxchgl (% imm1) (@ (% imm2)))
+    (jne @again)
+    (box-fixnum imm1 arg_z))
+  (mark-as-node temp0)
+  (mark-as-node temp1)
+  (single-value-return))
+
+(defx8632lapfunction %atomic-decf-ptr-if-positive ((ptr arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (let ((imm1 temp0)
+	(imm2 temp1))
+    (macptr-ptr ptr imm2)
+    @again
+    (movl (@ (% imm2)) (% eax))
+    (testl (% eax) (% eax))
+    (lea (@ -1 (% eax)) (% imm1))
+    (jz @done)
+    (lock)
+    (cmpxchgl (% imm1) (@ (% imm2)))
+    (jnz @again)
+    @done
+    (box-fixnum imm1 arg_z))
+  (mark-as-node temp0)
+  (mark-as-node temp1)
+  (single-value-return))
+
+(defx8632lapfunction %atomic-swap-ptr ((ptr arg_y) (newval arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (macptr-ptr arg_y imm1)
+    (unbox-fixnum newval imm0)
+    (lock)
+    (xchgl (% imm0) (@ (% imm1)))
+    (box-fixnum imm0 arg_z))
+  (mark-as-node temp0)
+  (single-value-return))
+
+;;; Try to store the fixnum NEWVAL at PTR, if and only if the old value
+;;; was equal to OLDVAL.  Return the old value
+(defx8632lapfunction %ptr-store-conditional ((ptr 4) #|(ra 0)|# (expected-oldval arg_y) (newval arg_z))
+  (mark-as-imm temp1)
+  (let ((imm2 temp1))
+    (movl (@ ptr (% esp)) (% temp0))
+    (macptr-ptr temp0 imm2)
+    (mark-as-imm temp0)
+    (let ((imm1 temp0))
+      @again
+      (movl (@ (% imm2)) (% imm0))
+      (box-fixnum imm0 imm0)
+      (cmpl (% imm0) (% expected-oldval))
+      (jne @done)
+      (unbox-fixnum newval imm1)
+      (lock)
+      (cmpxchgl (% imm1) (@ (% imm2)))
+      (jne @again)
+      @done
+      (movl (% imm0) (% arg_z)))
+    (mark-as-node temp0))
+  (mark-as-node temp1)
+  (single-value-return 3))
+
+(defx8632lapfunction %ptr-store-fixnum-conditional ((ptr 4) #|(ra 0)|# (expected-oldval arg_y) (newval arg_z))
+  (mark-as-imm temp0)
+  (let ((address temp0))
+    (movl (@ ptr (% esp)) (% temp1))
+    (macptr-ptr temp1 address)
+    @again
+    (movl (@ (% address)) (% imm0))
+    (cmpl (% imm0) (% expected-oldval))
+    (jne @done)
+    (lock)
+    (cmpxchgl (% newval) (@ (% address)))
+    (jne @again)
+    @done
+    (movl (% imm0) (% arg_z)))
+  (mark-as-node temp0)
+  (single-value-return 3))
+
+(defx8632lapfunction xchgl ((newval arg_y) (ptr arg_z))
+  (unbox-fixnum newval imm0)
+  (macptr-ptr ptr arg_y)		;better be aligned
+  (xchgl (% imm0) (@ (% arg_y)))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %macptr->dead-macptr ((macptr arg_z))
+  (check-nargs 1)
+  (movb ($ x8632::subtag-dead-macptr) (@ x8632::misc-subtag-offset (% macptr)))
+  (single-value-return))
+
+;;; %%apply-in-frame
+
+(defx8632lapfunction %%save-application ((flags arg_y) (fd arg_z))
+  (unbox-fixnum fd imm0)
+  (movd (% imm0) (% mm0))
+  (unbox-fixnum flags imm0)
+  (orl ($ arch::gc-trap-function-save-application) (% imm0))
+  (uuo-gc-trap)
+  (single-value-return))
+
+(defx8632lapfunction %misc-address-fixnum ((misc-object arg_z))
+  (check-nargs 1)
+  (lea (@ x8632::misc-data-offset (% misc-object)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction fudge-heap-pointer ((ptr 4) #|(ra 0)|# (subtype arg_y) (len arg_z))
+  (check-nargs 3)
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (movl (@ ptr (% esp)) (% temp1))
+    (macptr-ptr temp1 imm1)	      ; address in macptr
+    (lea (@ 9 (% imm1)) (% imm0))     ; 2 for delta + 7 for alignment
+    (andb ($ -8) (%b  imm0))	      ; Clear low three bits to align
+    (subl (% imm0) (% imm1))	      ; imm1 = -delta
+    (negw (%w imm1))
+    (movw (%w imm1) (@  -2 (% imm0)))	; save delta halfword
+    (unbox-fixnum subtype imm1)		; subtype at low end of imm1
+    (shll ($ (- x8632::num-subtag-bits x8632::fixnum-shift)) (% len))
+    (orl (% len) (% imm1))
+    (movl (% imm1) (@ (% imm0)))	; store subtype & length
+    (lea (@ x8632::fulltag-misc (% imm0)) (% arg_z))) ; tag it, return it
+  (mark-as-node temp0)
+  (single-value-return 3))
+
+(defx8632lapfunction %%make-disposable ((ptr arg_y) (vector arg_z))
+  (check-nargs 2)
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (lea (@ (- x8632::fulltag-misc) (% vector)) (% imm0)) ; imm0 is addr = vect less tag
+    (movzwl (@ -2 (% imm0)) (% imm1))     ; get delta
+    (subl (% imm1) (% imm0))              ; vector addr (less tag)  - delta is orig addr
+    (movl (% imm0) (@ x8632::macptr.address (% ptr))))
+  (mark-as-node temp0)
+  (single-value-return))
+
+(defx8632lapfunction %vect-data-to-macptr ((vect arg_y) (ptr arg_z))
+  (lea (@ x8632::misc-data-offset (% vect)) (% imm0))
+  (movl (% imm0) (@ x8632::macptr.address (% ptr)))
+  (single-value-return))
+
+;;; Sadly, we have no NVRs on x8632.
+(defun get-saved-register-values ()
+  (values))
+
+(defx8632lapfunction %current-db-link ()
+  (movl (@ (% :rcontext) x8632::tcr.db-link) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %no-thread-local-binding-marker ()
+  (movl ($ x8632::subtag-no-thread-local-binding) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction pending-user-interrupt ()
+  (xorl (% temp0) (% temp0))
+  (ref-global x8632::intflag arg_z)
+  ;; If another signal happens now, it will get ignored, same as if it happened
+  ;; before whatever signal is in arg_z.  But then these are async signals, so
+  ;; who can be sure it didn't actually happen just before...
+  (set-global temp0 x8632::intflag)
+  (single-value-return))
+
+(defx8632lapfunction debug-trap-with-string ((arg arg_z))
+  (check-nargs 1)
+  (uuo-error-debug-trap-with-string)
+  (single-value-return))
+
+(defx8632lapfunction %safe-get-ptr ((src arg_y) (dest arg_z))
+  (check-nargs 2)
+  (save-simple-frame)
+  (macptr-ptr src imm0)
+  (leal (@ (:^ done) (% fn)) (% ra0))
+  (movl (% imm0) (@ (% :rcontext) x8632::tcr.safe-ref-address))
+  (movl (@ (% imm0)) (% imm0))
+  (jmp done)
+  (:tra done)
+  (recover-fn)
+  (movl ($ 0) (@ (% :rcontext) x8632::tcr.safe-ref-address))
+  (movl (% imm0) (@ x8632::macptr.address (% dest)))
+  (restore-simple-frame)
+  (single-value-return))
+
+(defx8632lapfunction %%tcr-interrupt ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 4)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %suspend-tcr ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 5)
+  (movzbl (%b imm0) (%l imm0))
+  (testl (%l imm0) (%l imm0))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (cmovnel (@ (+ target::t-offset target::symbol.vcell) (% arg_z)) (%l arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %suspend-other-threads ()
+  (check-nargs 0)
+  (ud2a)
+  (:byte 6)
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %resume-tcr ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 7)
+  (movzbl (%b imm0) (%l imm0))
+  (testl (%l imm0) (%l imm0))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (cmovnel (@ (+ target::t-offset target::symbol.vcell) (% arg_z)) (%l arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %resume-other-threads ()
+  (check-nargs 0)
+  (ud2a)
+  (:byte 8)
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (single-value-return))
+
+
+(defx8632lapfunction %kill-tcr ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 9)
+  (testb (%b imm0) (%b imm0))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (cmovnel (@ (+ target::t-offset target::symbol.vcell) (% arg_z)) (%l arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %get-spin-lock ((p arg_z))
+  (check-nargs 1)
+  (save-simple-frame)
+  (push (% arg_z))
+  @again
+  (mark-as-imm temp1)
+  (movl (@ -4 (% ebp)) (% arg_z))
+  (macptr-ptr arg_z temp1)
+  (movl (@ '*spin-lock-tries* (% fn)) (% arg_y))
+  (movl (@ '*spin-lock-timeouts* (% fn)) (% arg_z))
+  (movl (@ target::symbol.vcell (% arg_y)) (% arg_y))
+  (movl (@ (% :rcontext) x8632::tcr.linear) (% temp0))
+  @try-swap
+  (xorl (% eax) (% eax))
+  (lock)
+  (cmpxchgl (% temp0) (@ (% temp1)))
+  (je @done)
+  @spin
+  (pause)
+  (cmpl ($ 0) (@ (% temp1)))
+  (je @try-swap)
+  (subl ($ '1) (% arg_y))
+  (jne @spin)
+  @wait
+  (addl ($ x8632::fixnumone) (@ x8632::symbol.vcell (% arg_z)))
+  (mark-as-node temp1)
+  (call-symbol yield 0)
+  (jmp @again)
+  @done
+  (mark-as-node temp1)
+  (movl (@ -4 (% ebp)) (% arg_z))
+  (restore-simple-frame)
+  (single-value-return))
+
+;; tbd
+(defx8632lapfunction %%apply-in-frame-proto ()
+  (hlt))
+
+(defx8632lapfunction %atomic-pop-static-cons ()
+  @again
+  (movl (@ (+ (target-nil-value) (x8632::kernel-global static-conses))) (% eax))
+  (cmpl ($ (target-nil-value)) (% eax))
+  (jz @lose)
+  (%cdr eax temp0)
+  (lock)
+  (cmpxchgl (% temp0) (@ (+ (target-nil-value) (x8632::kernel-global static-conses))))
+  (jnz @again)
+  (lock)
+  (subl ($ '1) (@ (+ (target-nil-value) (x8632::kernel-global free-static-conses))))
+  @lose
+  (movl (% eax) (% arg_z))
+  (single-value-return))
+
+
+
+(defx8632lapfunction %staticp ((x arg_z))
+  (check-nargs 1)
+  (ref-global static-cons-area temp0)
+  (movl (% x) (% imm0))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (subl (@ target::area.low (% temp0)) (% imm0))
+  (shrl ($ target::dnode-shift) (% imm0))
+  (mark-as-imm temp1)
+  (movl (@ target::area.ndnodes (% temp0)) (% temp1))
+  (subl (% imm0) (% temp1))
+  (lea (@ 128 (% temp1)) (% temp1))
+  (leal (@ (% temp1) target::fixnumone) (% temp1))
+  (cmoval (% temp1) (% arg_z))
+  (mark-as-node temp1)
+  (single-value-return))
+
+(defx8632lapfunction %static-inverse-cons ((n arg_z))
+  (check-nargs 1)
+  (subl ($ '128) (% arg_z))
+  (ref-global static-cons-area temp0)
+  (movl (@ target::area.high (% temp0)) (% imm0))
+  (subl (% arg_z) (% imm0))
+  (subl (% arg_z) (% imm0))
+  (lea (@ x8632::fulltag-cons (% imm0)) (% arg_z))
+  (single-value-return))
+
+;;; Get the thread-specific value of %fs.
+(defx8632lapfunction %get-fs-register ()
+  (xorl (% imm0) (% imm0))
+  (:byte #x66)                          ;movw %fs,%ax
+  (:byte #x8c)
+  (:byte #xe0)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %get-gs-register ()
+  (xorl (% imm0) (% imm0))
+  (:byte #x66)                          ;movw %gs,%ax
+  (:byte #x8c)
+  (:byte #xe8)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+  
Index: /branches/new-random/level-0/X86/X8632/x8632-numbers.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-numbers.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-numbers.lisp	(revision 13309)
@@ -0,0 +1,220 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defx8632lapfunction %fixnum-signum ((number arg_z))
+  (mov ($ '-1) (% temp0))
+  (mov ($ '1) (% temp1))
+  (test (% number) (% number))
+  (cmovs (% temp0) (% arg_z))
+  (cmovns (% temp1) (% arg_z))
+  (single-value-return))
+
+;;; see %logcount.
+(defx86lapfunction %ilogcount ((number arg_z))
+  (mark-as-imm temp0)
+  (let ((rshift imm0)
+        (temp temp0))
+    (unbox-fixnum number rshift)
+    (xor (% arg_z) (% arg_z))
+    (test (% rshift) (% rshift))
+    (jmp @test)
+    @next
+    (lea (@ -1 (% rshift)) (% temp))
+    (and (% temp) (% rshift))		;sets flags
+    (lea (@ '1 (% arg_z)) (% arg_z))    ;doesn't set flags
+    @test
+    (jne @next))
+  (mark-as-node temp0)
+  (single-value-return))
+
+;;; might be able to get away with not marking ecx as imm.
+(defx8632lapfunction %iash ((number arg_y) (count arg_z))
+  (mark-as-imm ecx)			;aka temp0
+  (unbox-fixnum count ecx)
+  (test (% count) (% count))
+  (jge @left)
+  (negb (% cl))
+  (unbox-fixnum number imm0)
+  (sar (% cl) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (mark-as-node ecx)
+  (single-value-return)
+  @left
+  (shl (% cl) (% number))
+  (movl (% number) (% arg_z))
+  (mark-as-node ecx)
+  (single-value-return))
+
+(defparameter *double-float-zero* 0.0d0)
+(defparameter *short-float-zero* 0.0s0)
+
+(defx8632lapfunction %sfloat-hwords ((sfloat arg_z))
+  (movl (% esp) (% temp0))
+  (movzwl (@ (+ 2 x8632::misc-data-offset) (% sfloat)) (% imm0))
+  (box-fixnum imm0 temp1)
+  (pushl (% temp1))			;high
+  (movzwl (@ x8632::misc-data-offset (% sfloat)) (% imm0))
+  (box-fixnum imm0 temp1)
+  (pushl (% temp1))			;low
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+
+(defx8632lapfunction %fixnum-intlen ((number arg_z))
+  (mark-as-imm temp0)
+  (let ((imm1 temp0))
+    (unbox-fixnum arg_z imm0)
+    (mov (% imm0) (% imm1))
+    (not (% imm1))
+    (test (% imm0) (% imm0))
+    (cmovs (% imm1) (% imm0))
+    (bsrl (% imm0) (% imm0))
+    (setne (%b imm1))
+    (addb (%b imm1) (%b imm0))
+    (box-fixnum imm0 arg_z))
+  (mark-as-node temp0)
+  (single-value-return))
+
+;;; Caller guarantees that result fits in a fixnum.
+(defx8632lapfunction %truncate-double-float->fixnum ((arg arg_z))
+  (get-double-float arg fp1)
+  (cvttsd2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+(defx8632lapfunction %truncate-short-float->fixnum ((arg arg_z))
+  (get-single-float arg fp1)
+  (cvttss2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+;;; DOES round to even
+(defx8632lapfunction %round-nearest-double-float->fixnum ((arg arg_z))
+  (get-double-float arg fp1)
+  (cvtsd2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+(defx8632lapfunction %round-nearest-short-float->fixnum ((arg arg_z))
+  (get-single-float arg fp1)
+  (cvtss2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+;;; We'll get a SIGFPE if divisor is 0.
+(defx8632lapfunction %fixnum-truncate ((dividend arg_y) (divisor arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (let ((imm2 temp0)
+	(imm1 temp1))			;edx
+    (unbox-fixnum dividend imm0)
+    (unbox-fixnum divisor imm2)
+    (cltd)				;edx:eax = sign_extend(eax)
+    (idivl (% imm2))
+    (box-fixnum imm0 arg_z)		;quotient
+    (box-fixnum imm1 arg_y))		;remainder
+  (mark-as-node temp0)
+  (mark-as-node temp1)
+  (movl (% esp) (% temp0))
+  (push (% arg_z))
+  (push (% arg_y))
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+
+(defx8632lapfunction called-for-mv-p ()
+  (movl (@ x8632::lisp-frame.return-address (% ebp)) (% imm0))
+  (cmpl (% imm0) (@ (+ (target-nil-value) (x8632::kernel-global ret1valaddr))))
+  (movl ($ (target-t-value)) (% imm0))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (cmove (% imm0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %next-random-pair ((high arg_y) (low arg_z))
+  ;; high: (unsigned-byte 15)
+  ;; low: (unsigned-byte 16)
+  (unbox-fixnum low imm0)
+  ;; clear most significant bit
+  (shll ($ (1+ (- 16 x8632::fixnumshift))) (% high))
+  (shrl ($ 1) (% high))
+  (orl (% high) (% imm0))
+  (mark-as-imm edx)
+  (movl ($ 48271) (% edx))
+  (mul (% edx))
+  (mark-as-node edx)
+  (movl ($ (- #x10000)) (% high))	;#xffff0000
+  (andl (% imm0) (% high))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% high))
+  (shll ($ 16) (% imm0))
+  (shrl ($ (- 16 x8632::fixnumshift)) (% imm0))
+  (movl (% imm0) (% low))
+  (movl (% esp) (% temp0))
+  (push (% high))
+  (push (% low))
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+	
+;;; n1 and n2 must be positive (esp non zero)
+(defx86lapfunction %fixnum-gcd ((boxed-u arg_y) (boxed-v arg_z))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  (let ((u imm0)
+	(v temp1)
+	(k temp0))			;temp0 = ecx
+    (xorl (% k) (% k))
+    (bsfl (% boxed-u) (% u))
+    (bsfl (% boxed-v) (% v))
+    (rcmp (% u) (% v))
+    (cmovlel (%l u) (%l k))
+    (cmovgl (%l v) (%l k))
+    (unbox-fixnum boxed-u u)
+    (unbox-fixnum boxed-v v)
+    (subb ($ x8632::fixnumshift) (%b k))
+    (jz @start)
+    (shrl (% cl) (% u))
+    (shrl (% cl) (% v))
+    @start
+    ;; At least one of u or v is odd at this point
+    @loop
+    ;; if u is even, shift it right one bit
+    (testb ($ 1) (%b u))
+    (jne @u-odd)
+    (shrl ($ 1) (% u))
+    (jmp @test)
+    @u-odd
+    ;; if v is even, shift it right one bit
+    (testb ($ 1) (%b v))
+    (jne @both-odd)
+    (shrl ($ 1) (% v))
+    (jmp @test-u)
+    @both-odd
+    (cmpl (% v) (% u))
+    (jb @v>u)
+    (subl (% v) (% u))
+    (shrl ($ 1) (% u))
+    (jmp @test)
+    @v>u
+    (subl (% u) (% v))
+    (shrl ($ 1) (% v))
+    @test-u
+    (testl (% u) (% u))
+    @test
+    (ja @loop)
+    (shll (% cl) (% v))
+    (movb ($ 0) (% cl))
+    (box-fixnum v arg_z))
+  (mark-as-node temp0)
+  (mark-as-node temp1)
+  (single-value-return))
+
Index: /branches/new-random/level-0/X86/X8632/x8632-pred.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-pred.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-pred.lisp	(revision 13309)
@@ -0,0 +1,199 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "X86-LAPMACROS"))
+
+(defx8632lapfunction eql ((x arg_y) (y arg_z))
+  "Return T if OBJ1 and OBJ2 represent either the same object or
+numbers with the same type and value."
+  (check-nargs 2)
+  @top
+  @tail
+  (cmpl (% x) (% y))
+  (je @win)
+  (movl (% x) (% imm0))
+  (andb ($ x8632::fulltagmask) (% al))
+  (movb (% arg_z.b) (% ah))
+  (andb ($ x8632::fulltagmask) (% ah))
+  (cmpb (% al) (% ah))
+  (jnz @lose)
+  (cmpb ($ x8632::fulltag-misc) (% al))
+  (jnz @lose)
+  (cmpb ($ x8632::fulltag-misc) (% ah))
+  (jnz @lose)
+  ;; Objects are both of tag-misc.  Headers must match exactly;
+  ;; dispatch on subtag.
+  (getvheader x imm0)
+  ;;(getvheader y imm1)
+  (cmpb ($ x8632::subtag-macptr) (% imm0.b))
+  (je @macptr)				; will need to check subtag of %y
+  (cmp (% imm0) (@ x8632::misc-header-offset (% y)))
+  (jne @lose)
+  (cmpb ($ x8632::subtag-bignum) (% imm0.b))
+  (je @bignum)
+  (cmpb ($ x8632::subtag-single-float) (% imm0.b))
+  (je @one-unboxed-word)
+  (cmpb ($ x8632::subtag-double-float) (% imm0.b))
+  (je @double-float)
+  (cmpb ($ x8632::subtag-complex) (% imm0.b))
+  (je @complex)
+  (cmpb ($ x8632::subtag-ratio) (% imm0.b))
+  (je @ratio)
+  @lose
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return)
+  @double-float
+  ;; use UCOMISD here, maybe?
+  (movl (@ x8632::double-float.val-high (% x)) (% imm0))
+  (cmpl (% imm0) (@ x8632::double-float.val-high (% y)))
+  (jne @lose)
+  (movl (@ x8632::double-float.value (% x)) (% imm0))
+  (cmpl (% imm0) (@ x8632::double-float.value (% y)))
+  (jne @lose)
+  (movl ($ (target-t-value)) (% arg_z))
+  (single-value-return)
+  @macptr
+  (cmpb ($ x8632::subtag-macptr) (@ x8632::misc-subtag-offset (% y)))
+  (jne @lose)
+  @one-unboxed-word
+  (movl (@ x8632::misc-data-offset (% x)) (% imm0))
+  @test
+  (cmpl (% imm0) (@ x8632::misc-data-offset (% y)))
+  (movl ($ (target-t-value)) (%l imm0))
+  (lea (@ (- x8632::t-offset) (% imm0)) (% arg_z))
+  (cmovel (%l imm0) (%l arg_z))
+  (single-value-return)
+  @win
+  (movl ($ (target-t-value)) (% arg_z))
+  (single-value-return)
+  @ratio
+  @complex
+  ;; Have either a ratio or a complex.  In either case, corresponding
+  ;; elements of both objects must be EQL.  Recurse on the first
+  ;; elements.  If true, tail-call on the second, else fail.
+  (save-simple-frame)
+  (pushl (@ x8632::ratio.denom (% x)))  ; aka complex.imagpart
+  (pushl (@ x8632::ratio.denom (% y)))
+  (movl (@ x8632::ratio.numer (% x)) (% x))       ; aka complex.realpart
+  (movl (@ x8632::ratio.numer (% y)) (% y))       ; aka complex.realpart
+  (:talign 5)
+  (call @top)
+  (recover-fn)
+  (cmp-reg-to-nil arg_z)
+  (pop (% y))
+  (pop (% x))
+  (restore-simple-frame)
+  (jnz @tail)
+  ;; lose, again
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return)
+  @bignum
+  ;; Way back when, we got x's header into imm0.  We know that y's
+  ;; header is identical.  Use the element-count from imm0 to control
+  ;; the loop.  There's no such thing as a 0-element bignum, so the
+  ;; loop must always execute at least once.
+  (header-length imm0 temp0)
+  (xor (% temp1) (% temp1))
+  @bignum-next
+  (movl (@ x8632::misc-data-offset (% x) (% temp1)) (% imm0))
+  (cmpl (@ x8632::misc-data-offset (% y) (% temp1)) (% imm0))
+  (jne @lose)
+  (addl ($ '1) (% temp1))
+  (sub ($ '1) (% temp0))
+  (jnz @bignum-next)
+  (movl ($ (target-t-value)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction equal ((x arg_y) (y arg_z))
+  "Return T if X and Y are EQL or if they are structured components
+  whose elements are EQUAL. Strings and bit-vectors are EQUAL if they
+  are the same length and have identical components. Other arrays must be
+  EQ to be EQUAL.  Pathnames are EQUAL if their components are."
+  (check-nargs 2)
+  @top
+  @tail
+  (cmp (% x) (% y))
+  (je @win)
+  (movl (% x) (% imm0))
+  (andb ($ x8632::fulltagmask) (% al))
+  (movb (% arg_z.b) (% ah))
+  (andb ($ x8632::fulltagmask) (% ah))
+  (cmpb (% al) (% ah))
+  (jnz @lose)
+  (cmpb ($ x8632::fulltag-cons) (% imm0.b))
+  (je @cons)
+  (cmpb ($ x8632::fulltag-misc) (% imm0.b))
+  (je @misc)
+  @lose
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return)
+  @win
+  (movl ($ (target-t-value)) (% arg_z))
+  (single-value-return)
+  @cons
+  ;; If either X or Y is NIL, lose.
+  (cmp-reg-to-nil x)
+  (je @lose)
+  (cmp-reg-to-nil y)
+  (je @lose)
+  ;; Check to see if the CARs are EQ.  If so, we can avoid saving
+  ;; context, and can just tail call ourselves on the CDRs.
+  (%car x temp0)
+  (%car y temp1)
+  (cmpl (% temp0) (% temp1))
+  (jne @recurse)
+  (%cdr x x)
+  (%cdr y y)
+  (jmp @tail)
+  @recurse
+  (save-simple-frame)
+  (pushl (@ x8632::cons.cdr (% x)))
+  (pushl (@ x8632::cons.cdr (% y)))
+  (movl (% temp0) (% x))
+  (movl (% temp1) (% y))
+  (:talign 5)
+  (call @top)
+  (recover-fn)
+  (cmp-reg-to-nil arg_z)
+  (pop (% y))
+  (pop (% x))
+  (restore-simple-frame)         
+  (jnz @top)
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return)
+  @misc
+  ;; Both objects are uvectors of some sort.  Try EQL; if that fails,
+  ;; call HAIRY-EQUAL.
+  (save-simple-frame)
+  (pushl (% x))
+  (pushl (% y))
+  (call-symbol eql 2)
+  (cmp-reg-to-nil arg_z)
+  (jne @won-with-eql)
+  (popl (% y))
+  (popl (% x))
+  (restore-simple-frame)
+  (jump-symbol hairy-equal 2)
+  @won-with-eql
+  (restore-simple-frame)                ; discards pushed args
+  (movl ($ (target-t-value)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %lisp-lowbyte-ref ((thing arg_z))
+  (box-fixnum thing arg_z)
+  (andl ($ '#xff) (%l arg_z))
+  (single-value-return))
Index: /branches/new-random/level-0/X86/X8632/x8632-symbol.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-symbol.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-symbol.lisp	(revision 13309)
@@ -0,0 +1,142 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "X8632-ARCH")
+  (require "X86-LAPMACROS"))
+
+;;; This assumes that macros & special-operators
+;;; have something that's not FUNCTIONP in their
+;;; function-cells.  It also assumes that NIL
+;;; isn't a true symbol, but that NILSYM is.
+(defx8632lapfunction %function ((sym arg_z))
+  (check-nargs 1)
+  (let ((symaddr temp0))
+    (movl ($ (+ (target-nil-value) x8632::nilsym-offset)) (% symaddr))
+    (cmp-reg-to-nil sym)
+    (cmovne (% sym) (% symaddr))
+    (trap-unless-typecode= symaddr x8632::subtag-symbol)
+    (movl (% sym) (% arg_y))
+    (movl (@ x8632::symbol.fcell (% symaddr)) (% arg_z))
+    (extract-typecode arg_z imm0)
+    (cmpb ($ x8632::subtag-function) (%b imm0))
+    (je.pt @ok)
+    (uuo-error-udf (% arg_y))
+    @ok
+    (single-value-return)))
+
+;;; Traps unless sym is NIL or some other symbol.  If NIL, return
+;;; nilsym
+(defx8632lapfunction %symbol->symptr ((sym arg_z))
+  (let ((tag imm0))
+    (movl ($ (+ (target-nil-value) x8632::nilsym-offset)) (% tag))
+    (cmp-reg-to-nil sym)
+    (cmove (% tag) (% sym))
+    (je :done)
+    (trap-unless-typecode= sym x8632::subtag-symbol)
+    :done
+    (single-value-return)))
+
+;;; If symptr is NILSYM, return NIL; else typecheck and return symptr
+(defx8632lapfunction %symptr->symbol ((symptr arg_z))
+  (cmpl ($ (+ (target-nil-value) x8632::nilsym-offset)) (% symptr))
+  (jne @typecheck)
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return)
+  @typecheck
+  (trap-unless-typecode= symptr x8632::subtag-symbol)
+  (single-value-return))
+
+(defx8632lapfunction %symptr-value ((symptr arg_z))
+  (jmp-subprim .SPspecref))
+
+(defx8632lapfunction %set-symptr-value ((symptr arg_y) (val arg_z))
+  (jmp-subprim .SPspecset))
+
+;;; This gets a tagged symbol as an argument.
+;;; If there's no thread-local binding, it should return
+;;; the underlying symbol vector as a first return value.
+(defx8632lapfunction %symptr-binding-address ((symptr arg_z))
+  (movl (@ x8632::symbol.binding-index (% symptr)) (% arg_y))
+  (rcmp (% arg_y) (:rcontext x8632::tcr.tlb-limit))
+  (movl (:rcontext x8632::tcr.tlb-pointer) (% temp0))
+  (jae @sym)
+  (cmpb ($ x8632::subtag-no-thread-local-binding) (@ (% temp0) (% arg_y)))
+  (je @sym)
+  (shl ($ x8632::word-shift) (% arg_y))
+  (push (% temp0))
+  (push (% arg_y))
+  (set-nargs 2)
+  (lea (@ '2 (% esp)) (% temp0))
+  (jmp-subprim .SPvalues)
+  @sym
+  (push (% arg_z))
+  (pushl ($ '#.x8632::symbol.vcell))
+  (set-nargs 2)
+  (lea (@ '2 (% esp)) (% temp0))
+  (jmp-subprim .SPvalues))
+
+(defx8632lapfunction %tcr-binding-location ((tcr arg_y) (sym arg_z))
+  (movl (@ x8632::symbol.binding-index (% sym)) (% temp0))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (rcmp (% temp0) (@ x8632::tcr.tlb-limit (% tcr)))
+  (movl (@ x8632::tcr.tlb-pointer (% tcr)) (% arg_y))
+  (jae @done)
+  (lea (@ (% arg_y) (% temp0)) (% arg_y))
+  ;; We're little-endian, so the tag is at the EA with no
+  ;; displacement
+  (cmpb ($ x8632::subtag-no-thread-local-binding) (@ (% arg_y)))
+  (cmovnel (% arg_y) (% arg_z))
+  @done
+  (single-value-return))
+
+(defx86lapfunction %pname-hash ((str arg_y) (len arg_z))
+  (let ((accum imm0)
+        (offset temp0))
+    (xor (% offset) (% offset))
+    (xor (% accum) (% accum))
+    (testl (% len) (% len))
+    (jz.pn @done)
+    @loop8
+    (roll ($ 5) (%l accum))
+    (xorl (@ x8632::misc-data-offset (% str) (% offset)) (%l accum))
+    (addl ($ '1) (% offset))
+    (subl ($ '1) (% len))
+    (jnz @loop8)
+    (shll ($ 5) (% accum))
+    (shrl ($ (- 5 x8632::fixnumshift)) (% accum))
+    (movl (% accum) (% arg_z))
+    @done
+    (single-value-return)))
+
+(defx8632lapfunction %string-hash ((start 4) #|(ra 0)|# (str arg_y) (len arg_z))
+  (let ((accum imm0)
+        (offset temp0))
+    (movl (@ start (% esp)) (% offset))
+    (xorl (% accum) (% accum))
+    (testl (% len) (% len))
+    (jz @done)
+    @loop8
+    (roll ($ 5) (%l accum))
+    (xorl (@ x8632::misc-data-offset (% str) (% offset)) (%l accum))
+    (addl ($ '1) (% offset))
+    (subl ($ '1) (% len))
+    (jnz @loop8)
+    (shll ($ 5) (% accum))
+    (shrl ($ (- 5 x8632::fixnumshift)) (% accum))
+    (movl (% accum) (% arg_z))
+    @done
+    (single-value-return 3)))
Index: /branches/new-random/level-0/X86/X8632/x8632-utils.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8632/x8632-utils.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8632/x8632-utils.lisp	(revision 13309)
@@ -0,0 +1,503 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defx8632lapfunction %address-of ((arg arg_z))
+  ;; %address-of a fixnum is a fixnum, just for spite.
+  ;; %address-of anything else is the address of that thing as an integer.
+  (testb ($ x8632::fixnummask) (%b arg))
+  (je @done)
+  (movl (% arg) (% imm0))
+  (jmp-subprim .SPmakeu32)
+  @done
+  (single-value-return))
+
+;;; "areas" are fixnum-tagged and, for the most part, so are their
+;;; contents.
+
+;;; The nilreg-relative global all-areas is a doubly-linked-list header
+;;; that describes nothing.  Its successor describes the current/active
+;;; dynamic heap.  Return a fixnum which "points to" that area, after
+;;; ensuring that the "active" pointers associated with the current thread's
+;;; stacks are correct.
+
+(defx8632lapfunction %normalize-areas ()
+  (let ((address temp0)
+        (temp temp1))
+
+    ; update active pointer for tsp area.
+    (movl (:rcontext x8632::tcr.ts-area) (% address))
+    (movl (:rcontext x8632::tcr.save-tsp) (% temp))
+    (movl (% temp) (@ x8632::area.active (% address)))
+    
+    ;; Update active pointer for vsp area.
+    (movl (:rcontext x8632::tcr.vs-area) (% address))
+    (movl (% esp) (@ x8632::area.active (% address)))
+
+    (ref-global all-areas arg_z)
+    (movl (@ x8632::area.succ (% arg_z)) (% arg_z))
+
+    (single-value-return)))
+
+(defx8632lapfunction %active-dynamic-area ()
+  (ref-global all-areas arg_z)
+  (movl (@ x8632::area.succ (% arg_z)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %object-in-stack-area-p ((object arg_y) (area arg_z))
+  (rcmp (% object) (@ x8632::area.active (% area)))
+  (movl ($ nil) (% temp0))
+  (movl ($ t) (% imm0))
+  (jb @done)
+  (rcmp (% object) (@ x8632::area.high (% area)))
+  (cmovbl (% imm0) (% temp0))
+  @done
+  (movl (% temp0) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %object-in-heap-area-p ((object arg_y) (area arg_z))
+  (rcmp (% object) (@ x8632::area.low (% area)))
+  (movl ($ nil) (% temp0))
+  (movl ($ t) (% imm0))
+  (jb @done)
+  (rcmp (% object) (@ x8632::area.active (% area)))
+  (cmovbl (% imm0) (% temp0))
+  @done
+  (movl (% temp0) (% arg_z))
+  (single-value-return))
+
+;;; In these heap-walking functions, all other threads should be
+;;; suspended; the only consing that should happen is any consing
+;;; that the function (the "f" argument) does when we call it.
+;;;
+;;; We can therefore basically walk dnode-aligned addresses (but we
+;;; have to be careful, especially in the %WALK-DYNAMIC-AREA case,
+;;; to hold onto only tagged pointers when we call the funtion, since
+;;; consing by the called function could cause a gc).
+
+(defx8632lapfunction walk-static-area ((a arg_y) (f arg_z))
+  (let ((obj temp0)
+	(fun -4)
+	(limit -8))
+    (save-simple-frame)
+    (push (% f))
+    (pushl (@ x8632::area.active (% a)))
+    (movl (@ x8632::area.low (% a)) (% obj))
+    (jmp @test)
+    @loop
+    (movb (@ (% obj)) (% imm0.b))
+    (andb ($ x8632::fulltagmask) (% imm0.b))
+    (cmpb ($ x8632::fulltag-immheader) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8632::fulltag-nodeheader) (% imm0.b))
+    (je @misc)
+    ;; not a header, so must be a cons
+    (add ($ x8632::fulltag-cons) (% obj))
+    (mov (% obj) (% arg_z))
+    (set-nargs 1)
+    (push (% obj))
+    (:talign 5)
+    (call (@ fun (% ebp)))
+    (recover-fn)
+    (pop (% obj))
+    (add ($ (- x8632::cons.size x8632::fulltag-cons)) (% obj))
+    (jmp @test)
+    @misc
+    (lea (@ x8632::fulltag-misc (% obj)) (% arg_z))
+    (set-nargs 1)
+    (push (% obj))
+    (:talign 5)
+    (call (@ fun (% ebp)))
+    (recover-fn)
+    (pop (% obj))
+    (mov (@ (% obj)) (% imm0))
+    (andb ($ x8632::fulltagmask) (% imm0.b))
+    (cmpb ($ x8632::fulltag-nodeheader) (% imm0.b))
+    (mov (@ (% obj)) (% imm0))
+    (je @32)
+    (cmpb ($ x8632::max-32-bit-ivector-subtag) (% imm0.b))
+    (jbe @32)
+    (cmpb ($ x8632::max-8-bit-ivector-subtag) (% imm0.b))
+    (jbe @8)
+    (cmpb ($ x8632::max-16-bit-ivector-subtag) (% imm0.b))
+    (jbe @16)
+    (cmpb ($ x8632::subtag-double-float-vector) (% imm0.b))
+    (je @double-float)
+    ;; if we get here, it's a bit vector
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (add ($ 7) (% imm0))
+    (shrl ($ 3) (% imm0))
+    (jmp @uvector-next)
+    @double-float
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (shll ($ 3) (% imm0))
+    (jmp @uvector-next)
+    @8
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (jmp @uvector-next)
+    @16
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (shll ($ 1) (% imm0))
+    (jmp @uvector-next)
+    @32
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (shll ($ 2) (% imm0))
+    ;; size of obj in bytes (without header or alignment padding)
+    ;; is in imm0
+    @uvector-next
+    (add ($ (+ x8632::node-size (1- x8632::dnode-size))) (% imm0))
+    (andb ($ (lognot (1- x8632::dnode-size))) (% imm0.b))
+    (add (% imm0) (% obj))
+    @test
+    (cmpl (@ limit (% ebp)) (% obj))
+    (jb @loop)
+    (movl ($ (target-nil-value)) (% arg_z))
+    (restore-simple-frame)
+    (single-value-return)))
+
+;;; This walks the active "dynamic" area.  Objects might be moving around
+;;; while we're doing this, so we have to be a lot more careful than we 
+;;; are when walking a static area.
+;;; There are a couple of approaches to termination:
+;;;  a) Allocate a "sentinel" cons, and terminate when we run into it.
+;;;  b) Check the area limit (which is changing if we're consing) and
+;;;     terminate when we hit it.
+;;; (b) loses if the function conses.  (a) conses.  I can't think of anything
+;;; better than (a).
+;;; This, of course, assumes that any GC we're doing does in-place compaction
+;;; (or at least preserves the relative order of objects in the heap.)
+
+(defx8632lapfunction %walk-dynamic-area ((a arg_y) (f arg_z))
+  (let ((obj temp0)
+	(fun -4)
+	(sentinel -8))
+    (save-simple-frame)
+    (push (% f))
+    (subl ($ (- x8632::cons.size x8632::fulltag-cons))
+	  (:rcontext x8632::tcr.save-allocptr))
+    (movl (:rcontext x8632::tcr.save-allocptr) (% allocptr)) ;aka temp0
+    (cmpl (:rcontext x8632::tcr.save-allocbase) (% allocptr))
+    (ja @ok)
+    (uuo-alloc)
+    @ok
+    (andb ($ (lognot x8632::fulltagmask))
+	  (:rcontext x8632::tcr.save-allocptr))
+    (push (% allocptr))			;sentinel
+    (ref-global tenured-area a)
+    (movl (@ x8632::area.low (% a)) (% obj))
+    (jmp @test)
+    @loop
+    (movb (@ (% obj)) (% imm0.b))
+    (andb ($ x8632::fulltagmask) (% imm0.b))
+    (cmpb ($ x8632::fulltag-immheader) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8632::fulltag-nodeheader) (% imm0.b))
+    (je @misc)
+    ;; not a header, so must be a cons
+    (add ($ x8632::fulltag-cons) (% obj))
+    (mov (% obj) (% arg_z))
+    (set-nargs 1)
+    (push (% obj))
+    (:talign 5)
+    (call (@ fun (% ebp)))
+    (recover-fn)
+    (pop (% obj))
+    (add ($ (- x8632::cons.size x8632::fulltag-cons)) (% obj))
+    (jmp @test)
+    @misc
+    (add ($ x8632::fulltag-misc) (% obj))
+    (mov (% obj) (% arg_z))
+    (set-nargs 1)
+    (push (% obj))
+    (:talign 5)
+    (call (@ fun (% ebp)))
+    (recover-fn)
+    (pop (% obj))
+    (sub ($ x8632::fulltag-misc) (% obj))
+    (mov (@ (% obj)) (% imm0))
+    (andb ($ x8632::fulltagmask) (% imm0.b))
+    (cmpb ($ x8632::fulltag-nodeheader) (% imm0.b))
+    (mov (@ (% obj)) (% imm0))
+    (je @32)
+    (cmpb ($ x8632::max-32-bit-ivector-subtag) (% imm0.b))
+    (jbe @32)
+    (cmpb ($ x8632::max-8-bit-ivector-subtag) (% imm0.b))
+    (jbe @8)
+    (cmpb ($ x8632::max-16-bit-ivector-subtag) (% imm0.b))
+    (jbe @16)
+    (cmpb ($ x8632::subtag-double-float-vector) (% imm0.b))
+    (je @double-float)
+    ;; if we get here, it's a bit vector
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (add ($ 7) (% imm0))
+    (shrl ($ 3) (% imm0))
+    (jmp @uvector-next)
+    @double-float
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (shll ($ 3) (% imm0))
+    (jmp @uvector-next)
+    @8
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (jmp @uvector-next)
+    @16
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (shll ($ 1) (% imm0))
+    (jmp @uvector-next)
+    @32
+    (shrl ($ x8632::num-subtag-bits) (% imm0))
+    (shll ($ 2) (% imm0))
+    ;; size of obj in bytes (without header or alignment padding)
+    ;; is in imm0
+    @uvector-next
+    (add ($ (+ x8632::node-size (1- x8632::dnode-size))) (% imm0))
+    (andb ($ (lognot (1- x8632::dnode-size))) (% imm0.b))
+    (add (% imm0) (% obj))
+    @test
+    (cmpl (@ sentinel (% ebp)) (% obj))
+    (jb @loop)
+    @done
+    (movl ($ (target-nil-value)) (% arg_z))
+    (restore-simple-frame)
+    (single-value-return)))
+
+;;; xxx duplicated in level-0/x86-utils.lisp
+(defun walk-dynamic-area (area func)
+  (with-other-threads-suspended
+      (%walk-dynamic-area area func)))
+
+(defx8632lapfunction %class-of-instance ((i arg_z))
+  (svref i instance.class-wrapper arg_z)
+  (svref arg_z %wrapper-class arg_z)
+  (single-value-return))
+
+(defx8632lapfunction class-of ((x arg_z))
+  (check-nargs 1)
+  (extract-fulltag x imm0)
+  (cmpb ($ x8632::fulltag-misc) (% imm0.b))
+  (movl (% arg_z) (% imm0))
+  (jne @have-tag)
+  (extract-subtag x imm0)
+  @have-tag
+  (movl (@ '*class-table* (% fn)) (% temp1))
+  (movl (@ x8632::symbol.vcell (% temp1)) (% temp1))
+  (movzbl (% imm0.b) (% imm0))
+  (movl (@ x8632::misc-data-offset (% temp1) (% imm0) 4) (% temp0))
+  (cmpl ($ (target-nil-value)) (% temp0))
+  (je @bad)
+  ;; functionp?
+  (extract-typecode temp0 imm0)
+  (cmpb ($ x8632::subtag-function) (% imm0.b))
+  (jne @ret)
+  ;; jump to the function
+  (set-nargs 1)
+  (jmp (% temp0))
+  @bad
+  (load-constant no-class-error fname)
+  (set-nargs 1)
+  (jmp (@ x8632::symbol.fcell (% fname)))
+  @ret
+  (movl (% temp0) (% arg_z))		;return frob from table
+  (single-value-return))
+
+(defx8632lapfunction gc ()
+  (check-nargs 0)
+  (movl ($ arch::gc-trap-function-gc) (% imm0))
+  (uuo-gc-trap)
+  (movl ($ nil) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction full-gccount ()
+  (ref-global tenured-area arg_z)
+  (test (% arg_z) (% arg_z))
+  (cmovel (@ (+ (target-nil-value) (x8632::%kernel-global 'gc-count))) (% arg_z))
+  (cmovnel (@ x8632::area.gc-count (% arg_z)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction egc ((arg arg_z))
+  "Enable the EGC if arg is non-nil, disables the EGC otherwise. Return
+the previous enabled status. Although this function is thread-safe (in
+the sense that calls to it are serialized), it doesn't make a whole lot
+of sense to be turning the EGC on and off from multiple threads ..."
+  (check-nargs 1)
+  (clrl imm0)
+  (cmp-reg-to-nil arg)
+  (setne (% imm0.b))
+  (movd (% imm0) (% mm0))
+  (movl ($ arch::gc-trap-function-egc-control) (% imm0))
+  (uuo-gc-trap)
+  (single-value-return))
+
+(defx8632lapfunction %configure-egc ((e0size 4)
+				     #|(ra 0)|#
+				     (e1size arg_y)
+				     (e2size arg_z))
+  (check-nargs 3)
+  (movl (@ e0size (% esp)) (% temp0))
+  (movl ($ arch::gc-trap-function-configure-egc) (% imm0))
+  (uuo-gc-trap)
+  (single-value-return 3))
+
+(defx8632lapfunction purify ()
+  (check-nargs 0)
+  (movl ($ arch::gc-trap-function-purify) (% imm0))
+  (uuo-gc-trap)
+  (movl ($ nil) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction impurify ()
+  (check-nargs 0)
+  (movl ($ arch::gc-trap-function-impurify) (% imm0))
+  (uuo-gc-trap)
+  (movl ($ nil) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction lisp-heap-gc-threshold ()
+  "Return the value of the kernel variable that specifies the amount
+of free space to leave in the heap after full GC."
+  (check-nargs 0)
+  (movl ($ arch::gc-trap-function-get-lisp-heap-threshold) (% imm0))
+  (uuo-gc-trap)
+  (jmp-subprim .SPmakeu32))
+
+(defx8632lapfunction set-lisp-heap-gc-threshold ((new arg_z))
+  "Set the value of the kernel variable that specifies the amount of free
+space to leave in the heap after full GC to new-value, which should be a
+non-negative fixnum. Returns the value of that kernel variable (which may
+be somewhat larger than what was specified)."
+  (check-nargs 1)
+  (save-simple-frame)
+  (call-subprim .SPgetu32)
+  (movd (% imm0) (% mm0))
+  (movl ($ arch::gc-trap-function-set-lisp-heap-threshold) (% imm0))
+  (uuo-gc-trap)
+  (restore-simple-frame)
+  (jmp-subprim .SPmakeu32))
+
+(defx8632lapfunction use-lisp-heap-gc-threshold ()
+  "Try to grow or shrink lisp's heap space, so that the free space is (approximately) equal to the current heap threshold. Return NIL"
+  (check-nargs 0) 
+  (movl ($ arch::gc-trap-function-use-lisp-heap-threshold) (% imm0))
+  (uuo-gc-trap)
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (single-value-return))
+
+(defx8632lapfunction freeze ()
+  "Do a full GC, then consider all heap-allocated objects which survive to be non-relocatable."
+  (movl ($ arch::gc-trap-function-freeze) (% imm0))
+  (uuo-gc-trap)
+  (jmp-subprim .SPmakeu32))
+
+(defx8632lapfunction flash-freeze ()
+  "Like FREEZE, without the GC."
+  (movl ($ arch::gc-trap-function-flash-freeze) (% imm0))
+  (uuo-gc-trap)
+  (jmp-subprim .SPmakeu32))
+
+(defx8632lapfunction %watch ((uvector arg_z))
+  (check-nargs 1)
+  (movl ($ arch::watch-trap-function-watch) (%l imm0))
+  (uuo-watch-trap)
+  (single-value-return))
+
+(defx8632lapfunction %unwatch ((watched arg_y) (new arg_z))
+  (check-nargs 2)
+  (movl ($ arch::watch-trap-function-unwatch) (%l imm0))
+  (uuo-watch-trap)
+  (single-value-return))
+
+(defx8632lapfunction %allocate-list ((initial-element arg_y) (nconses arg_z))
+  (check-nargs 2)
+  (save-simple-frame)
+  (ud2a)
+  (:byte 10)
+  (push (% arg_z))
+  (push (% allocptr))
+  (set-nargs 2)
+  (jmp-subprim .SPnvalret))
+
+(defx8632lapfunction %ensure-static-conses ()
+  (check-nargs 0)
+  (movl ($ arch::gc-trap-function-ensure-static-conses) (% imm0))
+  (uuo-gc-trap)
+  (movl ($ (target-nil-value)) (% arg_z))
+  (single-value-return))
+
+;;; offset is a fixnum, one of the x8632::kernel-import-xxx constants.
+;;; Returns that kernel import, a fixnum.
+(defx8632lapfunction %kernel-import ((offset arg_z))
+  (unbox-fixnum arg_z imm0)
+  (addl (@ (+ (target-nil-value) (x8632::%kernel-global 'kernel-imports))) (% imm0))
+  (movl (@ (% imm0)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %get-unboxed-ptr ((macptr arg_z))
+  (macptr-ptr arg_z imm0)
+  (movl (@ (% imm0)) (% arg_z))
+  (single-value-return))
+
+(defx8632lapfunction %revive-macptr ((p arg_z))
+  (movb ($ x8632::subtag-macptr) (@ x8632::misc-subtag-offset (% p)))
+  (single-value-return))
+
+(defx86lapfunction %macptr-type ((p arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= p x8632::subtag-macptr)
+  (svref p x8632::macptr.type-cell imm0)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+  
+(defx86lapfunction %macptr-domain ((p arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= p x8632::subtag-macptr)
+  (svref p x8632::macptr.domain-cell imm0)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx8632lapfunction %set-macptr-type ((p arg_y) (new arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= p x8632::subtag-macptr)
+  (unbox-fixnum new imm0)
+  (svset p x8632::macptr.type-cell imm0)
+  (single-value-return))
+
+(defx8632lapfunction %set-macptr-domain ((p arg_y) (new arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= p x8632::subtag-macptr)
+  (unbox-fixnum new imm0)
+  (svset p x8632::macptr.domain-cell imm0)
+  (single-value-return))
+
+(defx8632lapfunction true ()
+  (pop (% temp0))
+  (subl ($ '2) (% nargs))
+  (leal (@ '2 (% esp) (% nargs)) (% imm0))
+  (cmoval (% imm0) (% esp))
+  (movl ($ (target-t-value)) (% arg_z))
+  (push (% temp0))
+  (single-value-return))
+
+(defx8632lapfunction false ()
+  (pop (% temp0))
+  (subl ($ '2) (% nargs))
+  (leal (@ '2 (% esp) (% nargs)) (% imm0))
+  (cmoval (% imm0) (% esp))
+  (movl ($ (target-nil-value)) (% arg_z))
+  (push (% temp0))
+  (single-value-return))
+
+(defx8632lapfunction int3 ()
+  (int ($ 3))
+  (single-value-return))
Index: /branches/new-random/level-0/X86/X8664/.cvsignore
===================================================================
--- /branches/new-random/level-0/X86/X8664/.cvsignore	(revision 13309)
+++ /branches/new-random/level-0/X86/X8664/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*fsl
+*~.*
Index: /branches/new-random/level-0/X86/X8664/x8664-bignum.lisp
===================================================================
--- /branches/new-random/level-0/X86/X8664/x8664-bignum.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/X8664/x8664-bignum.lisp	(revision 13309)
@@ -0,0 +1,335 @@
+;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+;;; The caller has allocated a two-digit bignum (quite likely on the stack).
+;;; If we can fit in a single digit (if the high word is just a sign
+;;; extension of the low word), truncate the bignum in place (the
+;;; trailing words should already be zeroed.
+(defx86lapfunction %fixnum-to-bignum-set ((bignum arg_y) (fixnum arg_z))
+  (movq (% fixnum) (% arg_x))
+  (shl ($ (- 32 x8664::fixnumshift)) (% arg_x))
+  (sar ($ (- 32 x8664::fixnumshift)) (% arg_x))
+  (unbox-fixnum fixnum imm0)
+  (cmp (% arg_x) (% fixnum))
+  (je @chop)
+  (movq (% imm0)  (@ x8664::misc-data-offset (% bignum)))
+  (single-value-return)
+  @chop
+  (movq ($ x8664::one-digit-bignum-header) (@ x8664::misc-header-offset (% bignum)))
+  (movl (% imm0.l) (@ x8664::misc-data-offset (% bignum)))
+  (single-value-return))
+  
+;; multiply x[i] by y and add to result starting at digit idx
+(defx86lapfunction %multiply-and-add-loop
+    ((x 16) (y 8) #|(ra 0)|# (r arg_x) (idx arg_y) (ylen arg_z))
+  (let ((cc mm2)
+	(xx mm3)
+	(yy mm4)
+	(rr mm5)
+	(i imm0)
+	(j imm1))
+    (unbox-fixnum idx i)
+    (movq (@ x (% rsp)) (% temp0))
+    (movd (@ x8664::misc-data-offset (% temp0) (% i) 4) (% xx)) ;x[i]
+    (movq (@ y (% rsp)) (% temp0))
+    (movq (% r) (% temp1))
+    (pxor (% cc) (% cc))
+    (xorq (% j) (% j))
+    @loop
+    (movd (@ x8664::misc-data-offset (% temp0) (% j) 4) (% yy)) ;y[j]
+    (pmuludq (% xx) (% yy))
+    ;; 64-bit product now in %yy
+    (movd (@ x8664::misc-data-offset (% temp1) (% i) 4) (% rr))
+    ;; add in digit from r[i]
+    (paddq (% yy) (% rr))
+    ;; add in carry
+    (paddq (% cc) (% rr))
+    (movd (% rr) (@ x8664::misc-data-offset (% temp1) (% i) 4)) ;update r[i]
+    (movq (% rr) (% cc))
+    (psrlq ($ 32) (% cc))		;get carry digit into low word
+    (addq ($ 1) (% i))
+    (addq ($ 1) (% j))
+    (subq ($ '1) (% ylen))
+    (jg @loop)
+    (movd (% cc) (@ x8664::misc-data-offset (% temp1) (% i) 4))
+    (single-value-return 4)))
+
+(defx86lapfunction %multiply-and-add-loop64
+    ((xs 16) (ys 8) #|(ra 0)|# (r arg_x) (i arg_y) (ylen arg_z))
+  (let ((y temp2)
+	(j temp0)
+	(c imm2))
+    (movq (@ xs (% rsp)) (% temp0))
+    (movq (@ x8664::misc-data-offset (% temp0) (% i)) (% mm0)) ;x[i]
+    (movq (@ ys (% rsp)) (% y))
+    (xorl (%l j) (%l j))
+    (xorl (%l c) (%l c))
+    @loop
+    ;; It's a pity to have to reload this every time, but there's no
+    ;; imm3.  (Give him 16 registers, and he still complains...)
+    (movd (% mm0) (% rax))
+    (mulq (@ x8664::misc-data-offset (% y) (% j))) ;128-bit x * y[j] in rdx:rax
+    (addq (@ x8664::misc-data-offset (% r) (% i)) (% rax)) ;add in r[i]
+    (adcq ($ 0) (% rdx))
+    ;; add in carry digit
+    (addq (% c) (% rax))
+    (movl ($ 0) (%l c))
+    (adcq (% rdx) (% c))				   ;new carry digit
+    (movq (% rax) (@ x8664::misc-data-offset (% r) (% i))) ;update r[i]
+    (addq ($ '1) (% i))
+    (addq ($ '1) (% j))
+    (subq ($ '1) (% ylen))
+    (ja @loop)
+    (movq (% c) (@ x8664::misc-data-offset (% r) (% i)))
+    (single-value-return 4)))
+
+;;; Multiply the (32-bit) digits X and Y, producing a 64-bit result.
+;;; Add the 32-bit "prev" digit and the 32-bit carry-in digit to that 64-bit
+;;; result; return the halves as (VALUES high low).
+(defx86lapfunction %multiply-and-add4 ((x 8) #|(ra 0)|# (y arg_x) (prev arg_y) (carry-in arg_z))
+  (let ((unboxed-x imm0)
+        (unboxed-y imm1)
+        (unboxed-prev imm0)
+        (unboxed-carry-in imm0)
+        (unboxed-low imm0)
+        (high arg_y)
+        (low arg_z))
+    (pop (% ra0))
+    (popq (% temp0))
+    (discard-reserved-frame)
+    (push (% ra0))
+    (unbox-fixnum temp0 unboxed-x)
+    (unbox-fixnum y unboxed-y)
+    (mull (%l unboxed-y))
+    (shlq ($ 32) (% unboxed-y))
+    (orq (% unboxed-x) (% unboxed-y))   ; I got yer 64-bit product right here
+    (unbox-fixnum prev unboxed-prev)
+    (addq (% unboxed-prev) (% unboxed-y))
+    (unbox-fixnum carry-in unboxed-carry-in)
+    (addq (% unboxed-carry-in) (% unboxed-y))
+    (movl (%l unboxed-y) (%l unboxed-low))
+    (box-fixnum unboxed-low low)
+    (shr ($ 32) (% unboxed-y))
+    (box-fixnum unboxed-y high)
+    (movq (% rsp) (% temp0))
+    (pushq (% high))
+    (pushq (% low))
+    (set-nargs 2)
+    (jmp-subprim .SPvalues)))
+
+(defx86lapfunction %multiply-and-add3 ((x arg_x) (y arg_y) (carry-in arg_z))
+  (let ((unboxed-x imm0)
+        (unboxed-y imm1)
+        (unboxed-carry-in imm0)
+        (unboxed-low imm0)
+        (high arg_y)
+        (low arg_z))
+    (unbox-fixnum arg_x unboxed-x)
+    (unbox-fixnum y unboxed-y)
+    (mull (%l unboxed-y))
+    (shlq ($ 32) (% unboxed-y))
+    (orq (% unboxed-x) (% unboxed-y))
+    (unbox-fixnum carry-in unboxed-carry-in)
+    (addq (% unboxed-carry-in) (% unboxed-y))
+    (movl (%l unboxed-y) (%l unboxed-low))
+    (box-fixnum unboxed-low low)
+    (shr ($ 32) (% unboxed-y))
+    (box-fixnum unboxed-y high)
+    (movq (% rsp) (% temp0))
+    (pushq (% high))
+    (pushq (% low))
+    (set-nargs 2)
+    (jmp-subprim .SPvalues)))
+
+;;; Return the (possibly truncated) 32-bit quotient and remainder
+;;; resulting from dividing hi:low by divisor.
+(defx86lapfunction %floor ((num-high arg_x) (num-low arg_y) (divisor arg_z))
+  (let ((unboxed-high imm1)
+        (unboxed-low imm0)
+        (unboxed-quo imm0)
+        (unboxed-rem imm1)
+        (unboxed-divisor imm2))
+    (unbox-fixnum divisor unboxed-divisor)
+    (unbox-fixnum num-high unboxed-high)
+    (unbox-fixnum num-low unboxed-low)
+    (divl (%l unboxed-divisor))
+    (box-fixnum unboxed-quo arg_y)
+    (box-fixnum unboxed-rem arg_z)
+    (movq (% rsp) (% temp0))
+    (pushq (% arg_y))
+    (pushq (% arg_z))
+    (set-nargs 2)
+    (jmp-subprim .SPvalues)))
+
+;;; Multiply two (UNSIGNED-BYTE 32) arguments, return the high and
+;;; low halves of the 64-bit result
+(defx86lapfunction %multiply ((x arg_y) (y arg_z))
+  (let ((unboxed-x imm0)
+        (unboxed-y imm1)
+        (unboxed-high imm1)
+        (unboxed-low imm0))
+    (unbox-fixnum x unboxed-x)
+    (unbox-fixnum y unboxed-y)
+    (mull (%l unboxed-y))
+    (box-fixnum unboxed-high arg_y)
+    (box-fixnum unboxed-low arg_z)
+    (movq (% rsp) (% temp0))
+    (pushq (% arg_y))
+    (pushq (% arg_z))
+    (set-nargs 2)
+    (jmp-subprim .SPvalues)))
+
+;;; Any words in the "tail" of the bignum should have been
+;;; zeroed by the caller.
+(defx86lapfunction %set-bignum-length ((newlen arg_y) (bignum arg_z))
+  (movq (% newlen) (% imm0))
+  (shl ($ (- x8664::num-subtag-bits x8664::fixnumshift)) (% imm0))
+  (movb ($ x8664::subtag-bignum) (%b imm0))
+  (movq (% imm0) (@ x8664::misc-header-offset (% bignum)))
+  (single-value-return))
+
+;;; Count the sign bits in the most significant digit of bignum;
+;;; return fixnum count.
+(defx86lapfunction %bignum-sign-bits ((bignum arg_z))
+  (vector-size bignum imm0 imm0)
+  (movl (@ (- x8664::misc-data-offset 4) (% bignum) (% imm0) 4) (%l imm0))
+  (movl (% imm0.l) (% imm1.l))
+  (notl (% imm0.l))
+  (testl (% imm1.l) (% imm1.l))
+  (js @wasneg)
+  (notl (% imm0.l))  
+  @wasneg
+  (bsrl (% imm0.l) (% imm0.l))
+  (sete (% imm1.b))
+  (xorl ($ 31) (% imm0))
+  (addb (% imm1.b) (% imm0.b))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %signed-bignum-ref ((bignum arg_y) (index arg_z))
+  (uuo-error-debug-trap)
+  (unbox-fixnum index imm0)
+  (movslq (@ x8664::misc-data-offset (% bignum) (% imm0) 4) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+
+;;; If the bignum is a one-digit bignum, return the value of the
+;;; single digit as a fixnum.  Otherwise, if it's a two-digit-bignum
+;;; and the two words of the bignum can be represented in a fixnum,
+;;; return that fixnum; else return nil.
+(defx86lapfunction %maybe-fixnum-from-one-or-two-digit-bignum ((bignum arg_z))
+  (getvheader bignum imm1)
+  (cmpq ($ x8664::one-digit-bignum-header) (% imm1))
+  (je @one)
+  (cmpq ($ x8664::two-digit-bignum-header) (% imm1))
+  (jne @no)
+  (movq (@ x8664::misc-data-offset (% bignum)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (unbox-fixnum arg_z imm1)
+  (cmpq (% imm0) (% imm1))
+  (je @done)
+  @no
+  (movq ($ nil) (% arg_z))
+  (single-value-return)
+  @one
+  (movslq (@ x8664::misc-data-offset (% bignum)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  @done
+  (single-value-return))
+
+;;; Again, we're out of imm regs: a variable shift count has to go in %cl.
+;;; Make sure that the rest of %rcx is 0, to keep the GC happy.
+;;; %rcx == temp2
+(defx86lapfunction %digit-logical-shift-right ((digit arg_y) (count arg_z))
+  (unbox-fixnum digit imm0)
+  (unbox-fixnum count imm2)
+  (shrq (% imm2.b) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+
+
+(defx86lapfunction %ashr ((digit arg_y) (count arg_z))
+  (unbox-fixnum digit imm0)
+  (unbox-fixnum count imm2)
+  (movslq (%l imm0) (% imm0))
+  (sarq (% imm2.b) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %ashl ((digit arg_y) (count arg_z))
+  (unbox-fixnum digit imm0)
+  (unbox-fixnum count imm2)
+  (shlq (% imm2.b) (% imm0))
+  (movl (%l imm0) (%l imm0))            ;zero-extend
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction macptr->fixnum ((ptr arg_z))
+  (macptr-ptr arg_z ptr)
+  (single-value-return))
+
+(defx86lapfunction fix-digit-logand ((fix arg_x) (big arg_y) (dest arg_z)) ; index 0
+  (let ((w1 imm0)
+        (w2 imm1))
+    (movq (@ x8664::misc-data-offset (% big)) (% w2))
+    (unbox-fixnum  fix w1)
+    (andq (% w2) (% w1))
+    (cmp-reg-to-nil dest)
+    (jne @store)
+    (box-fixnum w1 arg_z)
+    (single-value-return)
+    @store
+    (movq (% w1) (@ x8664::misc-data-offset (% dest)))
+    (single-value-return)))
+
+(defx86lapfunction fix-digit-logandc2 ((fix arg_x) (big arg_y) (dest arg_z))
+  (let ((w1 imm0)
+        (w2 imm1))
+    (movq (@ x8664::misc-data-offset (% big)) (% w2))
+    (unbox-fixnum  fix w1)
+    (notq (% w2))
+    (andq (% w2) (% w1))
+    (cmp-reg-to-nil dest)
+    (jne @store)
+    (box-fixnum w1 arg_z)
+    (single-value-return)
+    @store
+    (movq (% w1) (@ x8664::misc-data-offset (% dest)))
+    (single-value-return)))
+
+
+(defx86lapfunction fix-digit-logandc1 ((fix arg_x) (big arg_y) (dest arg_z))
+  (let ((w1 imm0)
+        (w2 imm1))
+    (movq (@ x8664::misc-data-offset (% big)) (% w2))
+    (unbox-fixnum  fix w1)
+    (notq (% w1))
+    (andq (% w2) (% w1))
+    (cmp-reg-to-nil dest)
+    (jne @store)
+    (box-fixnum w1 arg_z)
+    (single-value-return)
+    @store
+    (movq (% w1) (@ x8664::misc-data-offset (% dest)))
+    (single-value-return)))
+
+
+
Index: /branches/new-random/level-0/X86/x86-array.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-array.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-array.lisp	(revision 13309)
@@ -0,0 +1,403 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+#+x8664-target
+(progn
+
+(eval-when (:compile-toplevel :execute)
+  #+x8632-target
+  (require "X8632-ARCH")
+  #+x8664-target
+  (require "X8664-ARCH")
+  (require "X86-LAPMACROS"))
+
+
+
+#+x8664-target
+(progn
+;;; None of the stores in here can be intergenerational; the vector
+;;; is known to be younger than the initial value
+(defx86lapfunction %init-gvector ((len arg_x) (value arg_y) (vector arg_z))
+  (jmp @test)
+  @loop
+  (movq (% value) (@ x8664::misc-data-offset (% vector) (% len)))
+  @test
+  (subq ($ x8664::fixnumone) (% len))
+  (jns @loop)
+  (single-value-return))
+
+;;; "val" is either a fixnum or a uvector with 64-bits of data
+;;; (small bignum, DOUBLE-FLOAT).
+(defx86lapfunction %%init-ivector64 ((len arg_x) (value arg_y) (vector arg_z))
+  (unbox-fixnum value imm0)
+  (testb ($ x8664::fixnummask) (%b value))
+  (je @test)
+  (movq (@ x8664::misc-data-offset (% value)) (% imm0))
+  (jmp @test)
+  @loop
+  (movq (% imm0) (@ x8664::misc-data-offset (% vector) (% len)))
+  @test
+  (subq ($ x8664::fixnumone) (% len))
+  (jns @loop)
+  (single-value-return))
+
+(defun %init-ivector64 (typecode len val uvector)
+  (declare (type (mod 256) typecode))
+  (%%init-ivector64 len
+                    (case typecode
+                      (#.x8664::subtag-fixnum-vector
+                       (require-type val 'fixnum))
+                      (#.x8664::subtag-double-float-vector
+                       (if (typep val 'double-float)
+                         val
+                         (require-type val 'double-float)))
+                      (#.x8664::subtag-s64-vector
+                       (require-type val '(signed-byte 64)))
+                      (#.x8664::subtag-u64-vector
+                       (require-type val '(unsigned-byte 64)))
+                      (t (report-bad-arg uvector
+                                         '(or (simple-array fixnum (*))
+                                           (simple-array double-float (*))
+                                           (simple-array (signed-byte 64) (*))
+                                           (simple-array (unsigned-byte 64) (*))))))
+                    uvector))
+  
+
+(eval-when (:compile-toplevel :execute)
+  (declaim (inline %init-ivector-u32)))
+
+(defun %init-ivector-u32 (len u32val uvector)
+  (declare (type index len)
+           (type (unsigned-byte 32) u32val)
+           (type (simple-array (unsigned-byte 32) (*)) uvector)
+           (optimize (speed 3) (safety 0)))
+  (dotimes (i len uvector)
+    (setf (aref uvector i) u32val)))
+
+(eval-when (:compile-toplevel :execute)
+  (declaim (inline %init-ivector-u16)))
+
+(defun %init-ivector-u16 (len val uvector)
+  (declare (type index len)
+           (type (unsigned-byte 16) val)
+           (type (simple-array (unsigned-byte 16) (*)) uvector)
+           (optimize (speed 3) (safety 0)))
+  (dotimes (i len uvector)
+    (setf (aref uvector i) val)))
+
+                              
+
+(defun %init-ivector32 (typecode len val uvector)
+  (declare (type (unsigned-byte 32) typecode)
+           (type index len))
+  (let* ((u32val (case typecode
+                   (#.x8664::subtag-s32-vector
+                    (logand (the (signed-byte 32)
+                              (require-type val '(signed-byte 32)))
+                            #xffffffff))
+                   (#.x8664::subtag-single-float-vector
+                    (single-float-bits (require-type val 'single-float)))
+                   (#.x8664::subtag-simple-base-string
+                    (char-code val))
+                   (t
+                    (require-type val '(unsigned-byte 32))))))
+    (declare (type (unsigned-byte 32) u32val))
+    (%init-ivector-u32 len u32val uvector)))
+
+(defun %init-misc (val uvector)
+  (let* ((len (uvsize uvector))
+         (typecode (typecode uvector))
+         (fulltag (logand x8664::fulltagmask typecode)))
+    (declare (type index len)
+             (type (unsigned-byte 8) typecode)
+             (type (mod 16) fulltag))
+    (if (or (= fulltag x8664::fulltag-nodeheader-0)
+            (= fulltag x8664::fulltag-nodeheader-1))
+      (%init-gvector len val uvector)
+      (if (= fulltag x8664::ivector-class-64-bit)
+        (%init-ivector64 typecode len val uvector)
+        (if (= fulltag x8664::ivector-class-32-bit)
+          (%init-ivector32 typecode len val uvector)
+          ;; Value must be a fixnum, 1, 8, 16 bits
+          (case typecode
+            (#.x8664::subtag-u16-vector
+             (%init-ivector-u16 len
+                                (require-type val '(unsigned-byte 16))
+                                uvector))
+            (#.x8664::subtag-s16-vector
+             (%init-ivector-u16 len
+                                (logand (the (signed-byte 16)
+                                          (require-type val '(signed-byte 16)))
+                                        #xffff)
+                                uvector))
+            (#.x8664::subtag-u8-vector
+             (let* ((v0 (require-type val '(unsigned-byte 8)))
+                    (l0 (ash (the fixnum (1+ len)) -1)))
+               (declare (type (unsigned-byte 8) v0)
+                        (type index l0))
+               (%init-ivector-u16 l0
+                                  (logior (the (unsigned-byte 16) (ash v0 8))
+                                          v0)
+                                  uvector)))
+            (#.x8664::subtag-s8-vector
+             (let* ((v0 (logand #xff
+                                (the (signed-byte 8)
+                                  (require-type val '(signed-byte 8)))))
+                    (l0 (ash (the fixnum (1+ len)) -1)))
+               (declare (type (unsigned-byte 8) v0)
+                        (type index l0))
+               (%init-ivector-u16 l0
+                                  (logior (the (unsigned-byte 16) (ash v0 8))
+                                          v0)
+                                  uvector)))
+            (#.x8664::subtag-bit-vector
+               (let* ((v0 (case val
+                            (1 -1)
+                            (0 0)
+                            (t (report-bad-arg val 'bit))))
+                      (l0 (ash (the fixnum (+ len 63)) -6)))
+                 (declare (type (unsigned-byte 8) v0)
+                          (type index l0))
+                 (%%init-ivector64  l0 v0 uvector)))
+            (t (report-bad-arg uvector
+                               '(or simple-bit-vector
+                                   (simple-array (signed-byte 8) (*))
+                                   (simple-array (unsigned-byte 8) (*))
+                                   (simple-array (signed-byte 16) (*))
+                                   (simple-array (unsigned-byte 16) (*)))))))))))
+             
+
+)
+
+#-x8664-target
+(defun %init-misc (val uvector)
+  (dotimes (i (uvsize uvector) uvector)
+    (setf (uvref uvector i) val)))
+          
+
+;;; Make a new vector of size newsize whose subtag matches that of oldv-arg.
+;;; Blast the contents of the old vector into the new one as quickly as
+;;; possible; leave remaining elements of new vector undefined (0).
+;;; Return new-vector.
+(defun %extend-vector (start oldv newsize)
+  (declare (fixnum start))
+  (let* ((new (%alloc-misc newsize (typecode oldv)))
+         (oldsize (uvsize oldv)))
+    (declare (fixnum oldsize))
+    (do* ((i 0 (1+ i))
+          (j start (1+ j)))
+         ((= i oldsize) new)
+      (declare (fixnum i j))
+      (setf (uvref new j) (uvref oldv i)))))
+    
+
+
+
+
+;;; argument is a vector header or an array header.  Or else.
+(defx86lapfunction %array-header-data-and-offset ((a arg_z))
+  (let ((offset arg_y)
+        (temp temp1))
+    (movq (% rsp) (% temp0))
+    (movl ($ '0) (%l offset))
+    (movq (% a) (% temp))
+    @loop
+    (movq (@ target::arrayH.data-vector (% temp)) (% a))
+    (extract-subtag a imm0)
+    (addq (@ target::arrayH.displacement (% temp)) (% offset))
+    (rcmp (% imm0) ($ target::subtag-vectorH))
+    (movq (% a) (% temp))
+    (jle @loop)
+    (push (% a))
+    (push (% offset))
+    (set-nargs 2)
+    (jmp-subprim  .SPvalues)))
+
+
+
+(defx86lapfunction %boole-clr ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq ($ 0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-set ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq ($ -1) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-1 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-2 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-c1 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-c2 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-and ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (andq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-ior ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (orq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-xor ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (xorq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-eqv ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (xorq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-nand ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (andq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-nor ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (orq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-andc1 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (andq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-andc2 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (andq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-orc1 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (orq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defx86lapfunction %boole-orc2 ((idx 8) #|(ra 0)|# (b0 arg_x) (b1 arg_y) (dest arg_z))
+  (movq (@ idx (% rsp)) (% temp0))
+  (movq (@ x8664::misc-data-offset (% b1) (% temp0)) (% imm0))
+  (notq (% imm0))
+  (orq (@ x8664::misc-data-offset (% b0) (% temp0)) (% imm0))
+  (movq (% imm0) (@ x8664::misc-data-offset (% dest) (% temp0)))
+  (single-value-return 3))
+
+(defparameter *simple-bit-boole-functions* ())
+
+(setq *simple-bit-boole-functions*
+      (vector
+       #'%boole-clr
+       #'%boole-set
+       #'%boole-1
+       #'%boole-2
+       #'%boole-c1
+       #'%boole-c2
+       #'%boole-and
+       #'%boole-ior
+       #'%boole-xor
+       #'%boole-eqv
+       #'%boole-nand
+       #'%boole-nor
+       #'%boole-andc1
+       #'%boole-andc2
+       #'%boole-orc1
+       #'%boole-orc2))
+
+(defun %simple-bit-boole (op b1 b2 result)
+  (let* ((f (svref *simple-bit-boole-functions* op)))
+    (dotimes (i (ash (the fixnum (+ (length result) 63)) -6) result)
+      (funcall f i b1 b2 result))))
+
+(defx86lapfunction %aref2 ((array arg_x) (i arg_y) (j arg_z))
+  (check-nargs 3)
+  (jmp-subprim .SParef2))
+
+(defx86lapfunction %aref3 ((array 8) #|(ra 0)|# (i arg_x) (j arg_y) (k arg_z))
+  (check-nargs 4)
+  (pop (% ra0))
+  (pop (% temp0))
+  (discard-reserved-frame)
+  (push (% ra0))
+  (jmp-subprim .SParef3))
+
+(defx86lapfunction %aset2 ((array 8) #|(ra 0)|# (i arg_x) (j arg_y) (newval arg_z))
+  (check-nargs 4)
+  (pop (% ra0))
+  (pop (% temp0))
+  (discard-reserved-frame)
+  (push (% ra0))
+  (jmp-subprim .SPaset2))
+
+(defx86lapfunction %aset3 ((array 16) (i 8) #|(ra 0)|# (j arg_x) (k arg_y) (newval arg_z))
+  (check-nargs 5)
+  (pop (% ra0))
+  (pop (% temp0))
+  (pop (% temp1))
+  (discard-reserved-frame)
+  (push (% ra0))
+  (jmp-subprim .SPaset3))
+
+)  ; #+x8664-target
+
Index: /branches/new-random/level-0/X86/x86-clos.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-clos.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-clos.lisp	(revision 13309)
@@ -0,0 +1,274 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+#+x8664-target
+(progn
+
+;;; It's easier to keep this is LAP; we want to play around with its
+;;; constants.
+
+
+;;; This just maps a SLOT-ID to a SLOT-DEFINITION or NIL.
+;;; The map is a vector of (UNSIGNED-BYTE 8); this should
+;;; be used when there are fewer than 255 slots in the class.
+(defx86lapfunction %small-map-slot-id-lookup ((slot-id arg_z))
+  (movq (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index arg_x)
+  (vector-length temp1 imm0)
+  (xorl (%l imm1) (%l imm1))
+  (rcmpq (% arg_x) (% imm0))
+  (movq (@ 'table (% fn)) (% temp0))
+  (ja @have-table-index)
+  (movq (% arg_x) (% imm1))
+  (shrq ($ x8664::word-shift) (% imm1))
+  (movzbl (@ x8664::misc-data-offset (% temp1) (% imm1)) (%l imm1))
+  @have-table-index
+  (movq (@ x8664::misc-data-offset (% temp0) (% imm1) 8) (% arg_z))
+  (single-value-return))
+
+;;; The same idea, only the map is a vector of (UNSIGNED-BYTE 32).
+(defx86lapfunction %large-map-slot-id-lookup ((slot-id arg_z))
+  (movq (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index arg_x)
+  (vector-length temp1 imm0)
+  (xorl (%l imm1) (%l imm1))
+  (rcmpq (% arg_x) (% imm0))
+  (movq (@ 'table (% fn)) (% temp0))
+  (ja @have-table-index)
+  (movq (% arg_x) (% imm1))
+  (shrq ($ 1) (% imm1))
+  (movl (@ x8664::misc-data-offset (% temp1) (% imm1)) (%l imm1))
+  @have-table-index
+  (movq (@ x8664::misc-data-offset (% temp0) (% imm1) 8) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %small-slot-id-value ((instance arg_y) (slot-id arg_z))
+  (movq (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index arg_x)
+  (vector-length temp1 imm0)
+  (xorl (%l imm1) (%l imm1))
+  (rcmpq (% arg_x) (% imm0))
+  (movq (@ 'table (% fn)) (% temp0))
+  (ja @missing)
+  (movq (% arg_x) (% imm1))
+  (shrq ($ x8664::word-shift) (% imm1))
+  (movzbl (@ x8664::misc-data-offset (% temp1) (% imm1)) (%l imm1))
+  (testl (%l imm1) (%l imm1))
+  (je @missing)
+  (movq (@ x8664::misc-data-offset (% temp0) (% imm1) 8) (% arg_z))
+  (movq (@ 'class (% fn)) (% arg_x))
+  (set-nargs 3)
+  (jmp (@ '%maybe-std-slot-value-using-class (% fn)))
+  @missing                              ; (%slot-id-ref-missing instance id)
+  (set-nargs 2)
+  (jmp (@'%slot-id-ref-missing (% fn))))
+
+(defx86lapfunction %large-slot-id-value ((instance arg_y) (slot-id arg_z))  
+  (movq (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index arg_x)
+  (vector-length temp1 imm0)
+  (xorl (%l imm1) (%l imm1))
+  (rcmpq (% arg_x) (% imm0))
+  (movq (@ 'table (% fn)) (% temp0))
+  (ja @missing)
+  (movq (% arg_x) (% imm1))
+  (shrq ($ 1) (% imm1))
+  (movl (@ x8664::misc-data-offset (% temp1) (% imm1)) (%l imm1))
+  (testl (%l imm1) (%l imm1))
+  (je @missing)
+  (movq (@ x8664::misc-data-offset (% temp0) (% imm1) 8) (% arg_z))
+  (movq (@ 'class (% fn)) (% arg_x))
+  (set-nargs 3)
+  (jmp (@ '%maybe-std-slot-value-using-class (% fn)))
+  @missing                              ; (%slot-id-ref-missing instance id)
+  (set-nargs 2)
+  (jmp (@'%slot-id-ref-missing (% fn))))
+
+  
+(defx86lapfunction %small-set-slot-id-value ((instance arg_x)
+                                             (slot-id arg_y)
+                                             (new-value arg_z))
+  (movq (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index imm1)
+  (vector-length temp1 imm0)
+  (rcmpq (% imm1) (% imm0))
+  (movq (@ 'table (% fn)) (% temp0))
+  (ja @missing)
+  (shrq ($ x8664::word-shift) (% rdx))
+  (movzbl (@ x8664::misc-data-offset (% temp1) (% imm1)) (%l imm1))
+  (testl (%l imm1) (%l imm1))
+  (je @missing)
+  (popq (% ra0))
+  (pushq ($ 0))                         ; reserve frame
+  (pushq ($ 0))
+  (pushq (@ 'class (% fn)))
+  (movq (@ x8664::misc-data-offset (% temp0) (% imm1) 8) (% arg_y))
+  (set-nargs 4)
+  (pushq (% ra0))
+  (jmp (@ '%maybe-std-setf-slot-value-using-class (% fn)))
+  @missing                              ; (%slot-id-set-missing instance id new-value)
+  (set-nargs 3)
+  (jmp (@ '%slot-id-set-missing (% fn))))
+
+
+(defx86lapfunction %large-set-slot-id-value ((instance arg_x)
+                                             (slot-id arg_y)
+                                             (new-value arg_z))
+  (movq (@ 'map (% fn)) (% temp1))
+  (svref slot-id slot-id.index imm1)
+  (vector-length temp1 imm0)
+  (rcmpq (% imm1) (% imm0))
+  (movq (@ 'table (% fn)) (% temp0))
+  (ja @missing)
+  (shrq ($ 1) (% rdx))
+  (movl (@ x8664::misc-data-offset (% temp1) (% imm1)) (%l imm1))
+  (testl (%l imm1) (%l imm1))
+  (je @missing)
+  (popq (% ra0))
+  (pushq ($ 0))                         ; reserve frame
+  (pushq ($ 0))
+  (pushq (@ 'class (% fn)))
+  (pushq (% ra0))
+  (movq (@ x8664::misc-data-offset (% temp0) (% imm1) 8) (% arg_y))
+  (set-nargs 4)
+  (jmp (@ '%maybe-std-setf-slot-value-using-class (% fn)))
+  @missing                              ; (%slot-id-set-missing instance id new-value)
+  (set-nargs 3)
+  (jmp (@'%slot-id-ref-missing (% fn))))
+
+
+;;; All of the generic function trampoline functions have to be
+;;; exactly the same size (x8664::gf-code-size) in words.  The
+;;; largest of these - the general-case *GF-PROTO* - is currently
+;;; "really" a little under 15 words, so X8664::GF-CODE-SIZE is
+;;; just a little bigger than that.
+(defparameter *gf-proto*
+  (nfunction
+   gag
+   (lambda (&lap &lexpr args)
+     (x86-lap-function 
+      gag 
+      ()
+      (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+      (:code-size x8664::gf-code-size)
+      #+count-gf-calls
+      (progn
+        (lock)
+        (addq ($ x8664::fixnumone) (@ 'hash (% fn))))
+      (movq (@ (% rsp)) (% ra0))
+      (save-frame-variable-arg-count)
+      (push-argregs)
+      (pushq (%q nargs))
+      (movq (% rsp) (% arg_z))
+      (ref-global.l ret1valaddr imm0)
+      (cmpq (% ra0) (% imm0))
+      (je @multiple)
+      (ref-global.l lexpr-return1v ra0)
+      (jmp @call)
+      @multiple
+      (pushq (@ (+ (target-nil-value) (x8664::%kernel-global 'lexpr-return))))
+      (movq (% imm0) (% ra0))
+      @call
+      (push (% ra0))
+      (movq (@ 'dispatch-table (% fn)) (% arg_y))
+      (set-nargs 2)
+      (jmp (@ 'dcode (% fn)))  ; dcode function
+      ))))
+
+;;; is a winner - saves ~15%
+(defx86lapfunction gag-one-arg ((arg arg_z))
+  (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+  (:code-size x8664::gf-code-size)
+  #+count-gf-calls
+  (progn
+    (lock)
+    (addq ($ x8664::fixnumone) (@ 'hash (% fn))))
+  (check-nargs 1)
+  (movq (@ 'dispatch-table (% fn)) (% arg_y))
+  (set-nargs 2)
+  (jmp (@ 'dcode (% fn))))
+
+(defx86lapfunction gag-two-arg ((arg0 arg_y) (arg1 arg_z))
+  (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+  (:code-size x8664::gf-code-size)
+  #+count-gf-calls
+  (progn
+    (lock)
+    (addq ($ x8664::fixnumone) (@ 'hash (% fn))))
+  (check-nargs 2)
+  (movq (@ 'dispatch-table (% fn)) (% arg_x))
+  (set-nargs 3)
+  (jmp (@ 'dcode (% fn))))
+
+
+(defx86lapfunction funcallable-trampoline ()
+  (:fixed-constants (class-wrapper slots dispatch-table dcode hash))
+  (:code-size x8664::gf-code-size)
+  (jmp (@ 'dcode (% fn))))
+
+
+;;; This is in LAP so that it can reference itself in the error message.
+;;; (It needs to be cloned, so %fn will be unique to each copy.)
+;;; It can't work for this to reference any of its own constants.
+(defx86lapfunction unset-fin-trampoline ()
+  (:code-size x8664::gf-code-size)
+  (save-frame-variable-arg-count)
+  (call-subprim .SPheap-rest-arg)
+  (pop (% arg_z))
+  (movq ($ '#.$XNOFINFUNCTION) (% arg_x))
+  (movq (% fn) (% arg_y))
+  (set-nargs 3)
+  (call-subprim .SPksignalerr)
+  ;(movq ($ (target-nil-value)) (% arg_z))
+  (leave)
+  (single-value-return))
+
+
+
+(defparameter *cm-proto*
+  (nfunction
+   gag
+   (lambda (&lap &lexpr args)
+     (x86-lap-function 
+      gag 
+      ()
+      (:fixed-constants (thing dcode gf bits))
+      (movq (@ (% rsp)) (% ra0))
+      (save-frame-variable-arg-count)
+      (push-argregs)
+      (pushq (%q nargs))
+      (movq (% rsp) (% arg_z))
+      (ref-global ret1valaddr imm0)
+      (cmpq (% ra0) (% imm0))
+      (je @multiple)
+      (ref-global lexpr-return1v ra0)
+      (jmp @call)
+      @multiple
+      (pushq (@ (+ (target-nil-value) (x8664::%kernel-global 'lexpr-return))))
+      (movq (% imm0) (% ra0))
+      @call
+      (push (% ra0))
+      (movq (@ 'thing (% fn)) (% arg_y))
+      (set-nargs 2)
+      (jmp (@ 'dcode (% fn)))))))
+
+
+
+
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-def.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-def.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-def.lisp	(revision 13309)
@@ -0,0 +1,736 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+(defx86lapfunction %function-vector-to-function ((arg arg_z))
+  (trap-unless-typecode= arg x8664::subtag-function)
+  (addb ($ (- x8664::fulltag-function x8664::fulltag-misc)) (% arg_z.b))
+  (single-value-return))
+
+(defx86lapfunction %function-to-function-vector  ((arg arg_z))
+  (trap-unless-fulltag= arg x8664::fulltag-function)
+  (subb ($ (- x8664::fulltag-function x8664::fulltag-misc)) (% arg_z.b))
+  (single-value-return))
+
+(defx86lapfunction %function-code-words ((fun arg_z))
+  (trap-unless-fulltag= fun x8664::fulltag-function)
+  (movl (@ (- x8664::node-size x8664::fulltag-function) (% fun)) (% imm0.l))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %nth-immediate ((fun arg_y) (n arg_z))
+  (trap-unless-fulltag= fun x8664::fulltag-function)
+  (movl (@ (- x8664::node-size x8664::fulltag-function) (% fun)) (% imm0.l))
+  (lea (@ (% n) (% imm0) 8) (% imm0))
+  (movq (@ (- x8664::node-size x8664::fulltag-function) (% fun) (% imm0))
+        (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %set-nth-immediate ((fun arg_x) (n arg_y) (new arg_z))
+  (trap-unless-fulltag= fun x8664::fulltag-function)
+  (movl (@ (- x8664::node-size x8664::fulltag-function) (% fun)) (% imm0.l))
+  (lea (@ (% n) (% imm0) 8) (% arg_y))
+  (subb ($ (- x8664::fulltag-function x8664::fulltag-misc)) (%b arg_x))
+  (jmp-subprim .SPgvset))
+
+(defx86lapfunction %function-code-byte ((fun arg_y) (pc arg_z))
+  (unbox-fixnum pc imm0)
+  (movzbl (@ (% fun) (% imm0)) (% imm0.l))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+
+;;; Returns 3 values: mask of registers used in the function, stack location
+;;; from which they'd be restored, relative PC at which they're saved. If
+;;; the mask is 0, the values NIL NIL NIL are returned. If either the stack
+;;; location or relative PC is #xff, both of those values will be returned
+;;; as NIL.
+(defx86lapfunction %function-register-usage ((f arg_z))
+  (check-nargs 1)
+  (trap-unless-fulltag= f x8664::fulltag-function)
+  (movzbl (@ -1 (% f)) (% imm0.l))
+  (shll ($ 8) (% imm0.l))
+  (box-fixnum imm0 arg_x)
+  (movq (% rsp) (% temp0))
+  (set-nargs 3)
+  (je @no-regs)
+  (movzbl (@ -2 (% f)) (% imm0.l))
+  (movzbl (@ -3 (% f)) (% imm1.l))
+  (cmpb ($ #xff) (% imm0.b))
+  (je @unencodable)
+  (cmpb ($ #xff) (% imm1.b))
+  (je @unencodable)
+  (box-fixnum imm0 arg_y)
+  (box-fixnum imm1 arg_z)
+  (push (% arg_x))
+  (push (% arg_y))
+  (push (% arg_z))
+  (jmp-subprim .SPvalues)
+  @unencodable
+  (push (% arg_x))
+  (pushq ($ nil))
+  (pushq ($ nil))
+  (jmp-subprim .SPvalues)
+  @no-regs
+  (pushq ($ nil))
+  (pushq ($ nil))
+  (pushq ($ nil))
+  (jmp-subprim .SPvalues))
+  
+        
+
+(defx86lapfunction %make-code-executable ((codev arg_z))
+  (single-value-return))
+
+;;; Make a new function, with PROTO's code and the specified immediates.
+;;; IMMEDIATES should contain lfun-bits as the last element.
+(defun %clone-x86-function (proto &rest immediates)
+  (declare (dynamic-extent immediates))
+  (let* ((protov (%function-to-function-vector proto))
+         (code-words (%function-code-words proto))
+         (numimms (length immediates))
+         (newv (allocate-typed-vector :function (the fixnum (+ code-words numimms)))))
+    (declare (fixnum code-words numimms))
+    (%copy-ivector-to-ivector protov 0 newv 0 (the fixnum (ash code-words target::word-shift)))
+    (do* ((k code-words (1+ k))
+          (imms immediates (cdr imms)))
+         ((null imms) (%function-vector-to-function newv))
+      (declare (fixnum k) (list imms))
+      (setf (%svref newv k) (car imms)))))
+
+(defun %copy-function (proto &optional target)
+  (let* ((protov (%function-to-function-vector proto))
+         (code-words (%function-code-words proto))
+         (total-words (uvsize protov))
+         (newv (if target
+                 (%function-to-function-vector target)
+                 (allocate-typed-vector :function total-words))))
+    (declare (fixnum code-words total-words))
+    (when target
+      (unless (and (eql code-words (%function-code-words target))
+                   (eql total-words (uvsize newv)))
+        (error "Wrong size target ~s" target)))
+    (%copy-ivector-to-ivector protov 0 newv 0 (the fixnum (ash code-words target::word-shift)))
+    (loop for k fixnum from code-words below total-words
+      do (setf (%svref newv k) (%svref protov k)))
+    (%function-vector-to-function newv)))
+
+(defun replace-function-code (target proto)
+  (let* ((target-words (%function-code-words target))
+         (proto-words (%function-code-words proto)))
+    (declare (fixnum target-words proto-words))
+    (if (= target-words proto-words)
+      (progn
+        (%copy-ivector-to-ivector (%function-to-function-vector proto)
+                                  0
+                                  (%function-to-function-vector target)
+                                  0
+                                  (the fixnum (ash target-words
+                                                   target::word-shift)))
+        target)
+      (error "Code size mismatch: target = ~s, proto = ~s"
+             target-words proto-words))))
+         
+
+(defx86lapfunction %get-kernel-global-from-offset ((offset arg_z))
+  (check-nargs 1)
+  (unbox-fixnum offset imm0)
+  (movq (@ (target-nil-value) (% imm0)) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %set-kernel-global-from-offset ((offset arg_y) (new-value arg_z))
+  (check-nargs 2)
+  (unbox-fixnum offset imm0)
+  (movq (% arg_z) (@ (target-nil-value) (% imm0)))
+  (single-value-return))
+
+
+(defx86lapfunction %get-kernel-global-ptr-from-offset ((offset arg_y)
+						       (ptr arg_z))
+  (check-nargs 2)
+  (unbox-fixnum offset imm0)
+  (movq (@ (target-nil-value) (% imm0)) (% imm0))
+  (movq (% imm0) (@ x8664::macptr.address (% ptr)))
+  (single-value-return))
+
+
+
+
+(defx86lapfunction %fixnum-ref ((fixnum arg_y) #| &optional |# (offset arg_z))
+  (:arglist (fixnum &optional offset))
+  (check-nargs 1 2)
+  (cmpl ($ x8664::fixnumone) (% nargs))
+  (jne @2-args)
+  (movq (% offset) (% fixnum))
+  (xorl (%l offset) (%l offset))
+  @2-args
+  (unbox-fixnum offset imm0)
+  (movq (@ (% fixnum) (% imm0)) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %fixnum-ref-natural ((fixnum arg_y) #| &optional |# (offset arg_z))
+  (:arglist (fixnum &optional offset))
+  (check-nargs 1 2)
+  (cmpl ($ x8664::fixnumone) (% nargs))
+  (jne @2-args)
+  (movq (% offset) (% fixnum))
+  (xorl (%l offset) (%l offset))
+  @2-args
+  (unbox-fixnum offset imm0)
+  (movq (@ (% fixnum) (% imm0)) (% imm0))
+  (jmp-subprim .SPmakeu64))
+
+(defx86lapfunction %fixnum-set ((fixnum arg_x) (offset arg_y) #| &optional |# (new-value arg_z))
+  (:arglist (fixnum offset &optional newval))
+  (check-nargs 2 3)
+  (cmpl ($ '2) (% nargs))
+  (jne @3-args)
+  (movq (% offset) (% fixnum))
+  (xorl (%l offset) (%l offset))
+  @3-args
+  (unbox-fixnum offset imm0)
+  (movq (% new-value) (@ (% fixnum) (% imm0)))
+  (movq (% new-value) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %fixnum-set-natural ((fixnum arg_x) (offset arg_y) #| &optional |# (new-value arg_z))
+  (:arglist (fixnum offset &optional newval))
+  (check-nargs 2 3)
+  (save-simple-frame)
+  (cmpl ($ '2) (% nargs))
+  (jne @3-args)
+  (movq (% offset) (% fixnum))
+  (xorl (%l offset) (%l offset))
+  @3-args
+  (call-subprim .SPgetu64)
+  (unbox-fixnum offset imm1)
+  (movq (% imm0) (@ (% fixnum) (% imm1)))
+  (restore-simple-frame)
+  (single-value-return))
+
+
+(defx86lapfunction %current-frame-ptr ()
+  (check-nargs 0)
+  (movq (% rbp) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %current-tsp ()
+  (check-nargs 0)
+  (movq (:rcontext x8664::tcr.save-tsp) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %%frame-backlink ((p arg_z))
+  (check-nargs 1)
+  (movq (@ (% arg_z)) (% arg_z))
+  (single-value-return))
+
+;;; Look for "lea -nnnn(%rip),%fn" AT the tra; if that's present, use
+;;; the dispacement -nnnn to find the function.  The end of the
+;;; encoded displacement is
+;;; x8664::recover-fn-from-rip-disp-offset (= 7) bytes from the tra.
+(defx86lapfunction %return-address-function ((r arg_z))
+  (extract-lisptag r imm0)
+  (cmpb ($ x8664::tag-tra) (% imm0.b))
+  (jne @fail)
+  (cmpw ($ x8664::recover-fn-from-rip-word0) (@ (% r)))
+  (jne @fail)
+  (cmpb ($ x8664::recover-fn-from-rip-byte2) (@ 2 (% r)))
+  (movslq (@ x8664::recover-fn-from-rip-disp-offset (% r)) (% imm0))
+  (jne @fail)
+  (lea (@ x8664::recover-fn-from-rip-length (% imm0) (% r)) (% arg_z))
+  (single-value-return)
+  @fail
+  (movl ($ (target-nil-value)) (% arg_z.l))
+  (single-value-return))
+
+(defx86lapfunction %return-address-offset ((r arg_z))
+  (extract-lisptag r imm0)
+  (cmpb ($ x8664::tag-tra) (% imm0.b))
+  (jne @fail)
+  (cmpw ($ x8664::recover-fn-from-rip-word0) (@ (% r)))
+  (jne @fail)
+  (cmpb ($ x8664::recover-fn-from-rip-byte2) (@ 2 (% r)))
+  (movslq (@ x8664::recover-fn-from-rip-disp-offset (% r)) (% imm0))
+  (jne @fail)
+  (negq (% imm0))
+  (leaq (@ (- (ash x8664::recover-fn-from-rip-length x8664::fixnumshift)) (% imm0) 8) (% arg_z))
+  (single-value-return)
+  @fail
+  (movl ($ (target-nil-value)) (% arg_z.l))
+  (single-value-return))
+
+;;; It's always been the case that the function associated with a
+;;; frame pointer is the caller of the function that "uses" that frame.
+(defun %cfp-lfun (p)
+  (let* ((ra (%fixnum-ref p x8664::lisp-frame.return-address)))
+    (if (eq ra (%get-kernel-global ret1valaddr))
+      (setq ra (%fixnum-ref p x8664::lisp-frame.xtra)))
+    (values (%return-address-function ra) (%return-address-offset ra))))
+
+
+
+(defx86lapfunction %uvector-data-fixnum ((uv arg_z))
+  (check-nargs 1)
+  (trap-unless-fulltag= arg_z x8664::fulltag-misc)
+  (addq ($ x8664::misc-data-offset) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %catch-top ((tcr arg_z))
+  (check-nargs 1)
+  (movl ($ (target-nil-value)) (%l arg_y))
+  (movq (:rcontext x8664::tcr.catch-top) (% arg_z))
+  (testb (%b arg_z) (%b arg_z))
+  (cmoveq (% arg_y) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %catch-tsp ((catch arg_z))
+  (check-nargs 1)
+  (lea (@  (- (+ target::fulltag-misc
+                                 (ash 1 (1+ target::word-shift)))) (% arg_z))
+       (% arg_z))
+  (single-value-return))
+
+
+
+;;; Same as %address-of, but doesn't cons any bignums
+;;; It also left shift fixnums just like everything else.
+(defx86lapfunction %fixnum-address-of ((x arg_z))
+  (check-nargs 1)
+  (box-fixnum x arg_z)
+  (single-value-return))
+
+(defx86lapfunction %save-standard-binding-list ((bindings arg_z))
+  (movq (:rcontext x8664::tcr.vs-area) (% imm0))
+  (movq (@ x8664::area.high (% imm0)) (% imm1))
+  (subq ($ x8664::node-size) (% imm1))
+  (movq (% bindings) (@ (% imm1)))
+  (single-value-return))
+
+(defx86lapfunction %saved-bindings-address ()
+  (movq (:rcontext x8664::tcr.vs-area) (% imm0))
+  (movq (@ x8664::area.high (% imm0)) (% imm1))
+  (lea (@ (- x8664::node-size) (% imm1)) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %get-object ((macptr arg_y) (offset arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= macptr x8664::subtag-macptr)
+  (macptr-ptr macptr imm0)
+  (trap-unless-lisptag= offset target::tag-fixnum imm1)
+  (unbox-fixnum offset imm1)
+  (movq (@ (% imm0) (% imm1)) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %set-object ((macptr arg_x) (offset arg_y) (value arg_z))
+  (check-nargs 3)
+  (trap-unless-typecode= macptr target::subtag-macptr)
+  (macptr-ptr macptr imm0)
+  (trap-unless-lisptag= offset target::tag-fixnum imm1)
+  (unbox-fixnum offset imm1)
+  (movq (% arg_z) (@ (% imm0) (% imm1)))
+  (single-value-return))
+
+(defx86lapfunction %apply-lexpr-with-method-context ((magic arg_x)
+                                                     (function arg_y)
+                                                     (args arg_z))
+  ;; Somebody's called (or tail-called) us.
+  ;; Put magic arg in x8664::next-method-context (= x8664::temp0).
+  ;; Put function in x8664::xfn until we're ready to jump to it.
+  ;; Set nargs to 0, then spread "args" on stack (clobbers arg_x, arg_y, arg_z,
+  ;;   but preserves x866::xfn/x8664::next-method-context.
+  ;; Jump to the function in x8664::xfn.
+  (popq (% ra0))
+  (movq (% magic) (% next-method-context))
+  (movq (% function) (% xfn))
+  (set-nargs 0)
+  (movq (@ (% args)) (% imm0))          ;lexpr-count
+  (movl (%l imm0) (% nargs))
+  (leaq (@ x8664::node-size (% arg_z) (% imm0)) (% imm1))
+  (subl ($ '3) (% imm0))
+  (jbe @reg-only)
+  ;; Some args will be pushed; reserve a frame
+  (pushq ($ x8664::reserved-frame-marker))
+  (pushq ($ x8664::reserved-frame-marker))
+  @pushloop
+  (pushq (@ (- x8664::node-size) (% imm1)))
+  (subq ($ x8664::node-size) (% imm1))
+  (subq ($ x8664::node-size) (% imm0))
+  (jne @pushloop)
+  @three
+  (movq (@ (* x8664::node-size 3) (% arg_z)) (% arg_x))
+  @two
+  (movq (@ (* x8664::node-size 2) (% arg_z)) (% arg_y))
+  @one
+  (movq (@ (* x8664::node-size 1) (% arg_z)) (% arg_z))
+  (jmp @go)
+  @reg-only
+  (testl (% nargs) (% nargs))
+  (je @go)
+  (rcmpl (% nargs) ($ '2))
+  (je @two)
+  (jb @one)
+  (jmp @three)
+  @go
+  (push (% ra0))
+  (jmp (% xfn)))
+
+(defx86lapfunction %apply-with-method-context ((magic arg_x)
+                                               (function arg_y)
+                                               (args arg_z))
+  ;; Somebody's called (or tail-called) us.
+  ;; Put magic arg in x8664::next-method-context (= x8664::temp0).
+  ;; Put function in x8664::xfn (= x8664::temp1).
+  ;; Set nargs to 0, then spread "args" on stack (clobbers arg_x, arg_y, arg_z,
+  ;;   but preserves x8664::xfn/x8664::next-method-context.
+  ;; Jump to the function in x8664::xfn.
+  (pop (% ra0))  
+  (movq (% magic) (% x8664::next-method-context))
+  (movq (% function) (% x8664::xfn))
+  (movq (% args) (% arg_y))             ; in case of error
+  (set-nargs 0)
+  (xorl (% imm0.l) (% imm0.l))
+  (push (% imm0))                       ; reserve frame (might discard
+  (push (% imm0))                       ; it if nothing is passed on stack.)
+  (cmp-reg-to-nil arg_z)
+  (je @done)
+  @loop
+  (extract-fulltag arg_z imm1)
+  (cmpb ($ x8664::fulltag-cons) (%b imm1))
+  (jne @bad)
+  (%car arg_z arg_x)
+  (%cdr arg_z arg_z)
+  (lea (@ x8664::node-size (% imm0)) (% imm0))
+  (cmp-reg-to-nil arg_z)
+  (push (% arg_x))
+  (jne @loop)
+  @done
+  (addl (%l imm0) (% nargs))
+  (jne @pop)
+  @discard-and-go
+  (discard-reserved-frame)
+  (jmp @go)
+  @pop
+  (cmpl($ '1) (% nargs))
+  (pop (% arg_z))
+  (je @discard-and-go)
+  (cmpl ($ '2) (% nargs))
+  (pop (% arg_y))
+  (je @discard-and-go)
+  (cmpl ($ '3) (% nargs))
+  (pop (% arg_x))
+  (je @discard-and-go)
+  @go
+  (push (% ra0))
+  (jmp (% xfn))
+  @bad
+  (addq (% imm0) (% rsp))
+  (movq (% arg_y) (% arg_z))
+  (movq ($ (ash $XNOSPREAD x8664::fixnumshift)) (% arg_y))
+  (set-nargs 2)
+  (jmp-subprim .SPksignalerr))
+
+
+;;; The idea here is to call METHOD in the same stack frame in
+;;; which the lexpr was originally called.  The lexpr can't
+;;; have had any required arguments, %APPLY-LEXPR-TAIL-WISE
+;;; must have been tail-called, and the frame built on lexpr
+;;; entry must be in %rbp.
+(defx86lapfunction %apply-lexpr-tail-wise ((method arg_y) (args arg_z))
+  (addq ($ x8664::node-size) (% rsp))   ; discard extra return address
+  (movq (% method) (% xfn))
+  (movq (% args) (% rsp))
+  (pop (%q nargs))
+  (movq (@ x8664::lisp-frame.return-address (% rbp)) (% ra0))
+  (movq (@ 0 (% rbp)) (% rbp))
+  (rcmpl (% nargs) ($ '3))
+  (jbe @pop-regs)
+  ;; More than 3 args; some must have been pushed by caller,
+  ;; so retain the reserved frame.
+  (pop (% arg_z))
+  (pop (% arg_y))
+  (pop (% arg_x))
+  (jmp @popped)
+  @pop-regs
+  (je @pop3)
+  (rcmpl (% nargs) ($ '1))
+  (jb @discard)
+  (ja @pop2)
+  (pop (% arg_z))
+  (jmp @discard)
+  @pop3
+  (pop (% arg_z))
+  (pop (% arg_y))
+  (pop (% arg_x))
+  (jmp @discard)
+  @pop2
+  (pop (% arg_z))
+  (pop (% arg_y))
+  @discard
+  (discard-reserved-frame)
+  @popped
+  (push (% ra0))
+  (jmp (% xfn)))
+
+
+
+(defun closure-function (fun)
+  (while (and (functionp fun)  (not (compiled-function-p fun)))
+    (setq fun (%nth-immediate fun 0))
+    (when (vectorp fun)
+      (setq fun (svref fun 0))))
+  fun)
+
+;;; For use by (setf (apply ...) ...)
+;;; (apply+ f butlast last) = (apply f (append butlast (list last)))
+
+(defun apply+ (&lap function arg1 arg2 &rest other-args)
+  (x86-lap-function apply+ ()
+   (:arglist (function arg1 arg2 &rest other-args))
+   (check-nargs 3 nil)
+   (cmpl ($ '3) (% nargs))
+   (pop (% ra0))
+   (ja @no-frame)
+   (pushq ($ x8664::reserved-frame-marker))
+   (pushq ($ x8664::reserved-frame-marker))
+@no-frame         
+   (push (% arg_x))
+   (movq (% arg_z) (% temp0))           ; last
+   (movq (% arg_y) (% arg_z))           ; butlast
+   (subl ($ '2) (% nargs))              ; remove count for butlast & last
+   ;; Do .SPspreadargz inline here
+   (xorl (%l imm0) (%l imm0))
+   (movq (% arg_z) (% arg_y))           ; save in case of error
+   (cmp-reg-to-nil arg_z)
+   (je @done)
+   @loop
+   (extract-fulltag arg_z imm1)
+   (cmpb ($ x8664::fulltag-cons) (%b imm1))
+   (jne @bad)
+   (%car arg_z arg_x)
+   (%cdr arg_z arg_z)
+   (addl ($ '1) (%l imm0))
+   (cmp-reg-to-nil arg_z)   
+   (push (% arg_x))
+   (jne @loop)
+   @done
+   ;; nargs was at least 1 when we started spreading, and can't have gotten
+   ;; any smaller. 
+   (addl (%l imm0) (% nargs))
+   (movq (% temp0) (% arg_z))
+   (pop (% arg_y))
+   (pop (% arg_x))
+   (addl ($ '1) (% nargs))
+   (cmpl ($ '3) (% nargs))
+   (jne @no-discard)
+   (discard-reserved-frame)
+   @no-discard
+   (load-constant funcall temp0)
+   (push (% ra0))
+   (jmp-subprim .SPfuncall)
+   @bad                                 ; error spreading list.
+   (add (% imm0) (% rsp))               ; discard whatever's been pushed
+   (movq (% arg_y) (% arg_z))
+   (movl ($ '#.$XNOSPREAD) (%l arg_y))
+   (set-nargs 2)
+   (jmp-subprim .SPksignalerr) ))
+
+
+
+;;; This needs to:
+;;; (a) load FP arg regs from the FP-REGS argument
+;;; (b) call the .SPffcall subprimitive, which will discard the foreign stack frame
+;;;     allocated by WITH-VARIABLE-C-FRAME in %FF-CALL
+;;; (c) re-establish the same foreign stack frame and store the result regs
+;;;     (%rax/%xmm0) there
+(defx86lapfunction %do-ff-call ((nfp 0) (frame arg_x) (fp-regs arg_y) (entry arg_z))
+  (popq (% ra0))
+  (popq (% rax))
+  (movq (% rbp) (@  (% rsp)))
+  (movq (% rsp) (% rbp))
+  (movq (% ra0) (@ 8 (% rbp)))
+  (macptr-ptr fp-regs temp0)
+  (sarq ($ x8664::fixnumshift) (% rax))
+  (movq (@ (% temp0)) (% fp0))
+  (movq (@ 8 (% temp0)) (% fp1))
+  (movq (@ 16 (% temp0)) (% fp2))
+  (movq (@ 24 (% temp0)) (% fp3))
+  (movq (@ 32 (% temp0)) (% fp4))
+  (movq (@ 40 (% temp0)) (% fp5))
+  (movq (@ 48 (% temp0)) (% fp6))
+  (movq (@ 56 (% temp0)) (% fp7))
+  (call-subprim .SPffcall)
+  (movq (:rcontext x8664::tcr.foreign-sp) (% mm5))
+  (movq (% mm5) (@ (% frame)))
+  (movq (% frame) (:rcontext x8664::tcr.foreign-sp))
+  (movq (% rax) (@ 8 (% frame)))
+  (movq (% fp0) (@ 16 (% frame)))
+  (movl ($ nil) (%l arg_z))
+  (restore-simple-frame)
+  (single-value-return))
+
+(defx86lapfunction %do-ff-call-return-registers ((fp-regs 8)(nfp 0) (frame arg_x) (regbuf arg_y) (entry arg_z))
+  (popq (% ra0))
+  (popq (% rax))
+  (popq (% temp0))
+  (movq (% rbp) (@  (% rsp)))
+  (movq (% rsp) (% rbp))
+  (movq (% ra0) (@ 8 (% rbp)))
+  (macptr-ptr temp0 temp0)
+  (sarq ($ x8664::fixnumshift) (% rax))
+  (movq (@ (% temp0)) (% fp0))
+  (movq (@ 8 (% temp0)) (% fp1))
+  (movq (@ 16 (% temp0)) (% fp2))
+  (movq (@ 24 (% temp0)) (% fp3))
+  (movq (@ 32 (% temp0)) (% fp4))
+  (movq (@ 40 (% temp0)) (% fp5))
+  (movq (@ 48 (% temp0)) (% fp6))
+  (movq (@ 56 (% temp0)) (% fp7))
+  (call-subprim .SPffcall-return-registers)
+  (movq (:rcontext x8664::tcr.foreign-sp) (% mm5))
+  (movq (% mm5) (@ (% frame)))
+  (movq (% frame) (:rcontext x8664::tcr.foreign-sp))
+  (movl ($ nil) (%l arg_z))
+  (restore-simple-frame)
+  (single-value-return))
+  
+
+(defun %ff-call (entry &rest specs-and-vals)
+  (declare (dynamic-extent specs-and-vals))
+  (let* ((len (length specs-and-vals))
+         (total-words 0)
+         (regbuf nil))
+    (declare (fixnum len total-words))
+    (let* ((result-spec (or (car (last specs-and-vals)) :void))
+           (nargs (ash (the fixnum (1- len)) -1))
+           (n-fp-args 0))
+      (declare (fixnum nargs n-fp-args))
+      (ecase result-spec
+        ((:address :unsigned-doubleword :signed-doubleword
+                   :single-float :double-float
+                   :signed-fullword :unsigned-fullword
+                   :signed-halfword :unsigned-halfword
+                   :signed-byte :unsigned-byte
+                   :void)
+         (do* ((i 0 (1+ i))
+               (specs specs-and-vals (cddr specs))
+               (spec (car specs) (car specs)))
+              ((= i nargs))
+           (declare (fixnum i))
+           (case spec
+             ((:address :unsigned-doubleword :signed-doubleword
+                        :single-float :double-float
+                        :signed-fullword :unsigned-fullword
+                        :signed-halfword :unsigned-halfword
+                        :signed-byte :unsigned-byte)
+              (incf total-words))
+             (:registers )
+             (t (if (typep spec 'unsigned-byte)
+                  (incf total-words spec)
+                  (error "unknown arg spec ~s" spec)))))
+         ;; It's necessary to ensure that the C frame is the youngest thing on
+         ;; the foreign stack here.
+         (%stack-block ((fp-args (* 8 8)))
+           (with-macptrs ((argptr))
+             (with-variable-c-frame
+                 total-words frame
+                 (%setf-macptr-to-object argptr frame)
+                 (let* ((gpr-offset 16)
+                        (other-offset (+ gpr-offset (* 6 8))))
+                   (declare (fixnum gpr-offset other-offset))
+                   (do* ((i 0 (1+ i))
+                         (ngpr-args 0)
+                         (specs specs-and-vals (cddr specs))
+                         (spec (car specs) (car specs))
+                         (val (cadr specs) (cadr specs)))
+                        ((= i nargs))
+                     (declare (fixnum i))
+                     (case spec
+                       (:address
+                        (incf ngpr-args)
+                        (cond ((<= ngpr-args 6)
+                               (setf (%get-ptr argptr gpr-offset) val)
+                               (incf gpr-offset 8))
+                              (t
+                               (setf (%get-ptr argptr other-offset) val)
+                               (incf other-offset 8))))
+                       ((:signed-doubleword :signed-fullword :signed-halfword
+                                            :signed-byte)
+                        (incf ngpr-args)
+                        (cond ((<= ngpr-args 6)
+                               (setf (%%get-signed-longlong argptr gpr-offset) val)
+                               (incf gpr-offset 8))
+                              (t
+                               (setf (%%get-signed-longlong argptr other-offset) val)
+                               (incf other-offset 8))))
+                       ((:unsigned-doubleword :unsigned-fullword :unsigned-halfword
+                                              :unsigned-byte)
+                        (incf ngpr-args)
+                        (cond ((<= ngpr-args 6)
+                               (setf (%%get-unsigned-longlong argptr gpr-offset) val)
+                               (incf gpr-offset 8))
+                              (t
+                               (setf (%%get-unsigned-longlong argptr other-offset) val)
+                               (incf other-offset 8))))
+                       (:double-float
+                        (cond ((< n-fp-args 8)
+                               (setf (%get-double-float fp-args (* n-fp-args 8)) val)
+                               (incf n-fp-args))
+                              (t
+                               (setf (%get-double-float argptr other-offset) val)
+                               (incf other-offset 8))))
+                       (:single-float
+                        (cond ((< n-fp-args 8)
+                               (setf (%get-single-float fp-args (* n-fp-args 8))
+                                     val)
+                               (incf n-fp-args))
+                              (t 
+                               (setf (%get-single-float argptr other-offset) val)
+                               (incf other-offset 8))))
+                       (:registers (setq regbuf val))
+                       (t
+                        (let* ((p 0))
+                          (declare (fixnum p))
+                          (dotimes (i (the fixnum spec))
+                            (setf (%get-ptr argptr other-offset) (%get-ptr val p))
+                            (incf p 8)
+                            (incf other-offset 8)))))))
+                 (if regbuf
+                   (%do-ff-call-return-registers fp-args (min n-fp-args 8) frame regbuf entry)
+                   (%do-ff-call (min n-fp-args 8) frame fp-args entry))
+                 (ecase result-spec
+                   (:void nil)
+                   (:address (%get-ptr argptr 8))
+                   (:unsigned-byte (%get-unsigned-byte argptr 8))
+                   (:signed-byte (%get-signed-byte argptr 8))
+                   (:unsigned-halfword (%get-unsigned-word argptr 8))
+                   (:signed-halfword (%get-signed-word argptr 8))
+                   (:unsigned-fullword (%get-unsigned-long argptr 8))
+                   (:signed-fullword (%get-signed-long argptr 8))
+                   (:unsigned-doubleword (%get-natural argptr 8))
+                   (:signed-doubleword (%get-signed-natural argptr 8))
+                   (:single-float (%get-single-float argptr 16))
+                   (:double-float (%get-double-float argptr 16)))))))))))
+                                 
+
+;;; end of x86-def.lisp
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-float.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-float.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-float.lisp	(revision 13309)
@@ -0,0 +1,460 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS")
+  (require :number-case-macro))
+
+
+;;; make a float from hi - high 24 bits mantissa (ignore implied higher bit)
+;;;                   lo -  low 28 bits mantissa
+;;;                   exp  - take low 11 bits
+;;;                   sign - sign(sign) => result
+;;; hi result - 1 bit sign: 11 bits exp: 20 hi bits of hi arg
+;;; lo result - 4 lo bits of hi arg: 28 lo bits of lo arg
+;;; no error checks, no tweaks, no nuthin 
+
+;;; sign is -1, 1, maybe zero
+
+
+
+(defx86lapfunction %make-float-from-fixnums ((float 16 )(hi 8) #|(ra 0)|#(lo arg_x) (exp arg_y) (sign arg_z))
+  (mov (% sign) (% imm1))
+  (sar ($ 63) (% imm1))
+  (shl ($ 63) (% imm1))
+  (movq (@ hi (% rsp)) (% imm0))                        ;hi
+  (andl ($ (ash (1- (ash 1 24)) x8664::fixnumshift)) (%l imm0))
+  (shl ($ (- 28 x8664::fixnumshift)) (% imm0))
+  (or (% imm0) (% imm1))
+  (unbox-fixnum lo imm0)
+  (andl ($ (1- (ash 1 28))) (%l imm0))
+  (or (% imm0) (% imm1))
+  (mov (% exp) (% imm0))
+  (shl ($ (- ieee-double-float-exponent-offset x8664::fixnumshift)) (% imm0))
+  (or (% imm0) (% imm1))
+  (movq (@ float (% rsp)) (% arg_z))
+  (mov (% imm1) (@ x8664::double-float.value (% arg_z)))
+  (single-value-return 4))
+
+
+;;; Maybe we should trap - or something - on NaNs.
+(defx86lapfunction %%double-float-abs! ((n arg_y)(val arg_z))
+  (mov (@ x8664::double-float.value (% n)) (% imm0))
+  (btr ($ 63) (% imm0))
+  (mov (% imm0) (@ x8664::double-float.value (% val)))
+  (single-value-return))
+
+
+(defx86lapfunction %short-float-abs ((n arg_z))
+  (btr ($ 63) (% n))
+  (single-value-return))
+
+
+(defx86lapfunction %double-float-negate! ((src arg_y) (res arg_z))
+  (movq (@ x8664::double-float.value (% src)) (% imm0))
+  (btcq ($ 63) (% imm0))
+  (movq (% imm0) (@ x8664::double-float.value (% res)))
+  (single-value-return))
+
+
+(defx86lapfunction %short-float-negate ((src arg_z))
+  (btcq ($ 63) (% arg_z))
+  (single-value-return))
+
+
+
+(defx86lapfunction dfloat-significand-zeros ((dfloat arg_z))
+  (movq (@ target::double-float.value (% dfloat)) (% imm1))
+  (shl ($ (1+ IEEE-double-float-exponent-width)) (% imm1))
+  (bsrq (% imm1) (% imm0))
+  (xorq ($ (1- target::nbits-in-word)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+;;; This exploits the fact that the single float is already
+;;; shifted left 32 bits.  We don't want to count the tag
+;;; bit as significant, so bash the argument into a fixnum
+;;; first.
+(defx86lapfunction sfloat-significand-zeros ((sfloat arg_z))
+  (xorb (%b sfloat) (%b sfloat))
+  (shl ($ (1+ IEEE-single-float-exponent-width)) (% sfloat))
+  (bsrq (% sfloat) (% imm0))
+  (xorq ($ (1- target::nbits-in-word)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %%scale-dfloat! ((float arg_x)(int arg_y)(result arg_z))
+  (unbox-fixnum int imm0)
+  (get-double-float float fp1)
+  (shl ($ IEEE-double-float-exponent-offset) (% imm0))
+  (movd (% imm0) (% fp2))
+  (mulsd (% fp2) (% fp1))
+  (put-double-float fp1 result)
+  (single-value-return))
+
+(defx86lapfunction %%scale-sfloat! ((float arg_y)(int arg_z))
+  (unbox-fixnum int imm0)
+  (shl ($ IEEE-double-float-exponent-offset) (% imm0))
+  (movd (% imm0) (% fp2))
+  (get-single-float float fp1)
+  (mulss (% fp2) (% fp1))
+  (put-single-float fp1 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %copy-double-float ((f1 arg_y) (f2 arg_z))
+  (get-double-float f1 fp1)
+  (put-double-float fp1 f2)
+  (single-value-return))
+
+(defx86lapfunction %short-float->double-float ((src arg_y) (result arg_z))
+  (get-single-float src fp1)
+  (cvtss2sd (% fp1) (% fp1))
+  (put-double-float fp1 result)
+  (single-value-return))
+
+(defx86lapfunction %double-float->short-float ((src arg_z))
+  (get-double-float src fp1)
+  (cvtsd2ss (% fp1) (% fp1))
+  (put-single-float fp1 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %int-to-sfloat ((int arg_z))
+  (int-to-single int imm0 fp1)
+  (put-single-float fp1 arg_z)
+  (single-value-return))
+  
+
+(defx86lapfunction %int-to-dfloat ((int arg_y) (dfloat arg_z))
+  (int-to-double int imm0 fp1)
+  (put-double-float fp1 arg_z)
+  (single-value-return))
+
+
+
+
+;;; Manipulate the MXCSR.  It'll fit in a fixnum, but we have to
+;;; load and store it through memory.  On x8664, we can hide the
+;;; 32-bit MXCSR value in a fixnum on the stack; on a 32-bit x86,
+;;; we might need to use a scratch location in the TCR or something.
+
+;;; Return the MXCSR as a fixnum
+(defx86lapfunction %get-mxcsr ()
+  (pushq ($ '0))
+  (stmxcsr (@ 4 (% rsp)))
+  (pop (% arg_z))
+  (shr ($ (- 32 x8664::fixnumshift)) (% arg_z))
+  (single-value-return))
+
+;;; Store the fixnum in arg_z in the MXCSR.  Just to be
+;;; on the safe side, mask the arg with X86::MXCSR-WRITE-MASK,
+;;; so that only known control and status bits are written to.
+(defx86lapfunction %set-mxcsr ((val arg_z))
+  (mov (% val) (% temp0))
+  (andl ($ '#.x86::mxcsr-write-mask) (%l temp0))
+  (shl ($ (- 32 x8664::fixnumshift)) (% temp0))
+  (push (% temp0))
+  (ldmxcsr (@ 4 (% rsp)))
+  (add ($ '1) (% rsp))
+  (single-value-return))
+
+
+;;; Get the bits that contain exception masks and rounding mode.
+
+(defun %get-mxcsr-control ()
+  (logand x86::mxcsr-control-and-rounding-mask (the fixnum (%get-mxcsr))))
+
+;;; Get the bits that describe current exceptions.
+(defun %get-mxcsr-status ()
+  (logand x86::mxcsr-status-mask (the fixnum (%get-mxcsr))))
+
+;;; Set the bits that describe current exceptions, presumably to clear them.
+(defun %set-mxcsr-status (arg)
+  (%set-mxcsr
+   (logior (logand x86::mxcsr-status-mask arg)
+           (logandc2 (%get-mxcsr) x86::mxcsr-status-mask)))
+  arg)
+
+;;; Set the bits that mask/unmask exceptions and control rounding.
+;;; Clear the bits which describe current exceptions.
+(defun %set-mxcsr-control (arg)
+  (%set-mxcsr (logand x86::mxcsr-control-and-rounding-mask arg)))
+
+;;; Return the MXCSR value in effect after the last ff-call.
+(defx86lapfunction %get-post-ffi-mxcsr ()
+  (xor (% arg_z) (% arg_z))
+  (movl (:rcontext x8664::tcr.ffi-exception) (%l imm0))
+  (movl (%l arg_z) (:rcontext x8664::tcr.ffi-exception))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+;;; Return the status bits from the last ff-call that represent
+;;; unmasked exceptions
+(defun %ffi-exception-status ()
+  (logior (%get-mxcsr-control)
+          (logand x86::mxcsr-status-mask (the fixnum (%get-post-ffi-mxcsr)))))
+
+
+  
+
+;;; See if the binary double-float operation OP set any enabled
+;;; exception bits in the mxcsr
+(defun %df-check-exception-2 (operation op0 op1 fp-status)
+  (declare (type (unsigned-byte 6) fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status
+			   operation 
+			   (%copy-double-float op0 (%make-dfloat)) 
+			   (%copy-double-float op1 (%make-dfloat)))))
+
+(defun %sf-check-exception-2 (operation op0 op1 fp-status)
+  (declare (type (unsigned-byte 6) fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+			   operation
+			   #+32-bit-target
+			   (%copy-short-float op0 (%make-sfloat))
+			   #+64-bit-target op0
+			   #+32-bit-target
+			   (%copy-short-float op1 (%make-sfloat))
+			   #+64-bit-target op1)))
+
+(defun %df-check-exception-1 (operation op0 fp-status)
+  (declare (fixnum fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+                           operation 
+                           (%copy-double-float op0 (%make-dfloat)))))
+
+(defun %sf-check-exception-1 (operation op0 fp-status)
+  (declare (type (unsigned-byte 6) fp-status))
+  (unless (zerop fp-status)
+    (%set-mxcsr-status 0)
+    ;; Ensure that operands are heap-consed
+    (%fp-error-from-status fp-status 
+			   operation
+			   #+32-bit-target
+			   (%copy-short-float op0 (%make-sfloat))
+			   #+64-bit-target op0)))
+
+
+(defun fp-condition-from-mxcsr (status-bits control-bits)
+  (declare (fixnum status-bits control-bits))
+  (cond 
+   ((and (logbitp x86::mxcsr-ie-bit status-bits)
+         (not (logbitp x86::mxcsr-im-bit control-bits)))
+    'floating-point-invalid-operation)
+   ((and (logbitp x86::mxcsr-oe-bit status-bits)
+         (not (logbitp x86::mxcsr-om-bit control-bits)))
+    'floating-point-overflow)
+   ((and (logbitp x86::mxcsr-ue-bit status-bits)
+         (not (logbitp x86::mxcsr-um-bit control-bits)))
+    'floating-point-underflow)
+   ((and (logbitp x86::mxcsr-ze-bit status-bits)
+         (not (logbitp x86::mxcsr-zm-bit control-bits)))
+    'division-by-zero)
+   ((and (logbitp x86::mxcsr-pe-bit status-bits)
+         (not (logbitp x86::mxcsr-pm-bit control-bits)))
+    'floating-point-inexact)))
+
+(defun %fp-error-from-status (status-bits  operation op0 &optional op1)
+  (declare (type (unsigned-byte 6) status-bits))
+  (let* ((condition-class (fp-condition-from-mxcsr status-bits (%get-mxcsr-control))))
+    (if condition-class
+      (let* ((operands (if op1 (list op0 op1) (list op0))))
+        (error (make-instance condition-class
+                              :operation operation
+                              :operands operands))))))
+
+
+
+;;; Don't we already have about 20 versions of this ?
+(defx86lapfunction %double-float-from-macptr! ((ptr arg_x) (byte-offset arg_y) (dest arg_z))
+  (macptr-ptr ptr imm0)
+  (unbox-fixnum byte-offset imm1)
+  (movsd (@ (% imm0) (% imm1)) (% fp1))
+  (put-double-float fp1 dest)
+  (single-value-return))
+
+
+(defvar *rounding-mode-alist*
+  '((:nearest . 0) (:zero . 1) (:positive . 2) (:negative . 3)))
+
+(defun get-fpu-mode (&optional (mode nil mode-p))
+  (let* ((flags (%get-mxcsr-control)))
+    (declare (fixnum flags))
+    (let* ((rounding-mode
+            (car (nth (+ (if (logbitp x86::mxcsr-rc0-bit flags) 1 0)
+                         (if (logbitp x86::mxcsr-rc1-bit flags) 2 0))
+                      *rounding-mode-alist*)))
+           (overflow (not (logbitp x86::mxcsr-om-bit flags)))
+           (underflow (not (logbitp x86::mxcsr-um-bit flags)))
+           (division-by-zero (not (logbitp x86::mxcsr-zm-bit flags)))
+           (invalid (not (logbitp x86::mxcsr-im-bit flags)))
+           (inexact (not (logbitp x86::mxcsr-pm-bit flags))))
+    (if mode-p
+      (ecase mode
+        (:rounding-mode rounding-mode)
+        (:overflow overflow)
+        (:underflow underflow)
+        (:division-by-zero division-by-zero)
+        (:invalid invalid)
+        (:inexact inexact))
+      `(:rounding-mode ,rounding-mode
+        :overflow ,overflow
+        :underflow ,underflow
+        :division-by-zero ,division-by-zero
+        :invalid ,invalid
+        :inexact ,inexact)))))
+
+;;; did we document this?
+(defun set-fpu-mode (&key (rounding-mode :nearest rounding-p)
+                          (overflow t overflow-p)
+                          (underflow t underflow-p)
+                          (division-by-zero t zero-p)
+                          (invalid t invalid-p)
+                          (inexact t inexact-p))
+  (let* ((current (%get-mxcsr-control))
+         (new current))
+    (declare (fixnum current new))
+    (when rounding-p
+      (let* ((rc-bits (or
+                       (cdr (assoc rounding-mode *rounding-mode-alist*))
+                       (error "Unknown rounding mode: ~s" rounding-mode))))
+        (declare (fixnum rc-bits))
+        (if (logbitp 0 rc-bits)
+          (bitsetf x86::mxcsr-rc0-bit new)
+          (bitclrf x86::mxcsr-rc0-bit new))
+        (if (logbitp 1 rc-bits)
+          (bitsetf x86::mxcsr-rc1-bit new)
+          (bitclrf x86::mxcsr-rc1-bit new))))
+    (when invalid-p
+      (if invalid
+        (bitclrf x86::mxcsr-im-bit new)
+        (bitsetf x86::mxcsr-im-bit new)))
+    (when overflow-p
+      (if overflow
+        (bitclrf x86::mxcsr-om-bit new)
+        (bitsetf x86::mxcsr-om-bit new)))
+    (when underflow-p
+      (if underflow
+        (bitclrf x86::mxcsr-um-bit new)
+        (bitsetf x86::mxcsr-um-bit new)))
+    (when zero-p
+      (if division-by-zero
+        (bitclrf x86::mxcsr-zm-bit new)
+        (bitsetf x86::mxcsr-zm-bit new)))
+    (when inexact-p
+      (if inexact
+        (bitclrf x86::mxcsr-pm-bit new)
+        (bitsetf x86::mxcsr-pm-bit new)))
+    (unless (= current new)
+      (%set-mxcsr-control new))
+    (%get-mxcsr)))
+
+
+
+;;; Copy a single float pointed at by the macptr in single
+;;; to a double float pointed at by the macptr in double
+
+(defx86lapfunction %single-float-ptr->double-float-ptr ((single arg_y) (double arg_z))
+  (check-nargs 2)
+  (macptr-ptr single imm0)
+  (movss (@ (% imm0)) (% fp1))
+  (cvtss2sd (% fp1) (% fp1))
+  (macptr-ptr double imm0)
+  (movsd (% fp1) (@ (% imm0)))
+  (single-value-return))
+
+;;; Copy a double float pointed at by the macptr in double
+;;; to a single float pointed at by the macptr in single.
+(defx86lapfunction %double-float-ptr->single-float-ptr ((double arg_y) (single arg_z))
+  (check-nargs 2)
+  (macptr-ptr double imm0)
+  (movsd (@ (% imm0)) (% fp1))
+  (cvtsd2ss (% fp1) (% fp1))
+  (macptr-ptr single imm0)
+  (movss (% fp1) (@ (% imm0)))
+  (single-value-return))
+
+
+(defx86lapfunction %set-ieee-single-float-from-double ((src arg_y) (macptr arg_z))
+  (check-nargs 2)
+  (macptr-ptr macptr imm0)
+  (get-double-float src fp1)
+  (cvtsd2ss (% fp1) (% fp1))
+  (movss (% fp1) (@ (% imm0)))
+  (single-value-return))
+
+(defx86lapfunction host-single-float-from-unsigned-byte-32 ((u32 arg_z))
+  (shl ($ (- 32 x8664::fixnumshift)) (% arg_z))
+  (movb ($ x8664::subtag-single-float) (% arg_z.b))
+  (single-value-return))
+
+(defx86lapfunction single-float-bits ((f arg_z))
+  (shr ($ (- 32 x8664::fixnumshift)) (% f))
+  (single-value-return))
+
+(defun double-float-bits (f)
+  (values (uvref f target::double-float.val-high-cell)
+          (uvref f target::double-float.val-low-cell)))
+
+(defun double-float-from-bits (high low)
+  (let* ((f (%make-dfloat)))
+    (setf (uvref f target::double-float.val-high-cell) high
+          (uvref f target::double-float.val-low-cell) low)
+    f))
+
+;;; Return T if n is negative, else NIL.
+(defx86lapfunction %double-float-sign ((n arg_z))
+  (movl (@ x8664::double-float.val-high (% n)) (% imm0.l))
+  (testl (% imm0.l) (% imm0.l))
+  (movl ($ (target-t-value)) (% imm0.l))
+  (movl ($ (target-nil-value)) (% arg_z.l))
+  (cmovlq (% imm0) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %short-float-sign ((n arg_z))
+  (testq (% n) (% n))
+  (movl ($ (target-t-value)) (% imm0.l))
+  (movl ($ (target-nil-value)) (% arg_z.l))
+  (cmovlq (% imm0) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %double-float-sqrt! ((n arg_y) (result arg_z))
+  (get-double-float n fp0)
+  (sqrtsd (% fp0) (% fp0))
+  (put-double-float fp0 result)
+  (single-value-return))
+
+(defx86lapfunction %single-float-sqrt ((n arg_z))
+  (get-single-float n fp0)
+  (sqrtss (% fp0) (% fp0))
+  (put-single-float fp0 arg_z)
+  (single-value-return))
+
+;;; end of x86-float.lisp
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-hash.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-hash.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-hash.lisp	(revision 13309)
@@ -0,0 +1,131 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; level-0;ppc;ppc-hash.lisp
+
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+(eval-when (:compile-toplevel :execute)
+  (require "HASHENV" "ccl:xdump;hashenv"))
+
+
+
+
+;;; This should stay in LAP so that it's fast
+;;; Equivalent to cl:mod when both args are positive fixnums
+
+
+(defx86lapfunction fast-mod ((number arg_y) (divisor arg_z))
+  (xorq (% imm1) (% imm1))
+  (mov (% number) (% imm0))
+  (div (% divisor))
+  (mov (% imm1) (% arg_z))
+  (single-value-return))
+
+
+;; Faster mod based on Bruce Hoult's Dylan version, modified to use a branch-free max.
+(defx86lapfunction fast-mod-3 ((number arg_x) (divisor arg_y) (recip arg_z))
+  (mov (% number) (% imm0))
+  (shrq ($ target::fixnumshift) (% imm0))
+  (mov (% recip) (% imm1))
+  (mul (% imm1)) ;; -> hi word in imm1 (unboxed)
+  (mov (% divisor) (% imm0))
+  (mul (% imm1)) ;; -> lo word in imm0 (boxed)
+  (subq (% imm0) (% number))
+  (subq (% divisor) (% number))
+  (mov (% number) (% arg_z))
+  (mov (% number) (% imm0))
+  (sar ($ (1- target::nbits-in-word)) (% imm0))
+  (andq (% imm0) (% divisor))
+  (addq (% divisor) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %dfloat-hash ((key arg_z))
+  (movq (@ x8664::double-float.value (% key)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %sfloat-hash ((key arg_z))
+  (mov (% key) (% imm1))
+  (movl ($ #x-80000000) (%l imm0))
+  (shr ($ 32) (% imm1))
+  (xorq (% arg_y) (% arg_y))
+  (shr ($ (- 32 x8664::fixnumshift)) (% key))
+  (rcmp (%l imm0) (%l imm1))
+  (cmoveq (% arg_y) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %macptr-hash ((key arg_z))
+  (movq (@ target::macptr.address (% key)) (% imm0))
+  (movq (% imm0) (% imm1))
+  (shlq ($ 24) (% imm1))
+  (addq (% imm1) (% imm0))
+  (movq ($ (lognot target::fixnummask)) (% arg_z))
+  (andq (% imm0) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %bignum-hash ((key arg_z))
+  (let ((header imm0)
+        (offset imm1)
+        (ndigits temp0))
+    (getvheader key header)
+    (header-length header ndigits)
+    (xorq (% offset) (% offset))
+    (let ((immhash header))
+      @loop
+      (rolq ($ 13) (% immhash))
+      (addl (@ x8664::misc-data-offset (% key) (% offset)) (%l immhash))
+      (addq ($ 4) (% offset))
+      (subq ($ '1) (% ndigits))
+      (jne  @loop)
+      (box-fixnum immhash arg_z))
+    (single-value-return)))
+
+
+(defx86lapfunction %get-fwdnum ()
+  (ref-global target::fwdnum arg_z)
+  (single-value-return))
+
+
+(defx86lapfunction %get-gc-count ()
+  (ref-global target::gc-count arg_z)
+  (single-value-return))
+
+
+;;; Setting a key in a hash-table vector needs to 
+;;; ensure that the vector header gets memoized as well
+(defx86lapfunction %set-hash-table-vector-key ((vector arg_x) (index arg_y) (value arg_z))
+  (jmp-subprim .SPset-hash-key))
+
+;;; This needs to be done out-of-line, to handle EGC memoization.
+(defx86lapfunction %set-hash-table-vector-key-conditional ((offset 8) #|(ra 0)|# (vector arg_x) (old arg_y) (new arg_z))
+  (movq (@ offset (% rsp)) (% temp0))
+  (save-simple-frame)
+  (call-subprim .SPset-hash-key-conditional)
+  (restore-simple-frame)
+  (single-value-return 3))
+
+;;; Strip the tag bits to turn x into a fixnum
+(defx86lapfunction strip-tag-to-fixnum ((x arg_z))
+  (andb ($ (lognot x8664::fixnummask)) (%b x))
+  (single-value-return))
+
+;;; end of x86-hash.lisp
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-io.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-io.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-io.lisp	(revision 13309)
@@ -0,0 +1,42 @@
+;;; -*- Mode: Lisp; Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+(in-package "CCL")
+
+;;; not very smart yet
+
+#+x8664-target
+(defx86lapfunction %get-errno ()
+  (movq (:rcontext x8664::tcr.errno-loc) (% imm1))
+  (movslq (@ (% imm1)) (% imm0))
+  (movss (% fpzero) (@ (% imm1)))
+  (negq (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+#+x8632-target
+(defx8632lapfunction %get-errno ()
+  (movl (:rcontext x8632::tcr.errno-loc) (% imm0))
+  (movl (@ (% imm0)) (% imm0))
+  (neg (% imm0))
+  (box-fixnum imm0 arg_z)
+  (movl (:rcontext x8632::tcr.errno-loc) (% imm0))
+  (movss (% fpzero) (@ (% imm0)))
+  (single-value-return))
+
Index: /branches/new-random/level-0/X86/x86-misc.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-misc.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-misc.lisp	(revision 13309)
@@ -0,0 +1,924 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; level-0;x86;x86-misc.lisp
+
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+;;; Copy N bytes from pointer src, starting at byte offset src-offset,
+;;; to ivector dest, starting at offset dest-offset.
+;;; It's fine to leave this in lap.
+;;; Depending on alignment, it might make sense to move more than
+;;; a byte at a time.
+;;; Does no arg checking of any kind.  Really.
+
+(defx86lapfunction %copy-ptr-to-ivector ((src (* 2 x8664::node-size) )
+                                         (src-byte-offset (* 1 x8664::node-size))
+                                         #|(ra 0)|#
+                                         (dest arg_x)
+                                         (dest-byte-offset arg_y)
+                                         (nbytes arg_z))
+  (let ((rsrc temp0)
+        (rsrc-byte-offset temp1))
+    (testq (% nbytes) (% nbytes))
+    (movq (@ src-byte-offset (% rsp)) (% rsrc-byte-offset))         ; boxed src-byte-offset
+    (movq (@ src (% rsp)) (% rsrc))     ; src macptr
+    (jmp @test)
+    @loop
+    (unbox-fixnum rsrc-byte-offset imm0)
+    (addq ($ '1) (% rsrc-byte-offset))
+    (addq (@ x8664::macptr.address (% rsrc)) (% imm0))
+    (movb (@ (% imm0)) (%b imm0))
+    (unbox-fixnum dest-byte-offset imm1)
+    (addq ($ '1) (% dest-byte-offset))
+    (movb (%b imm0) (@ x8664::misc-data-offset (% dest) (% imm1)))
+    (subq ($ '1) (% nbytes))
+    @test
+    (jne @loop)
+    (movq (% dest) (% arg_z))
+    (single-value-return 4)))
+
+(defx86lapfunction %copy-ivector-to-ptr ((src (* 2 x8664::node-size))
+                                         (src-byte-offset (* 1 x8664::node-size))
+                                         #|(ra 0)|#
+                                         (dest arg_x)
+                                         (dest-byte-offset arg_y)
+                                         (nbytes arg_z))
+  (let ((rsrc temp0)
+        (rsrc-byte-offset temp1))
+    (testq (% nbytes) (% nbytes))
+    (movq (@ src-byte-offset (% rsp)) (% rsrc-byte-offset))
+    (movq (@ src (% rsp)) (% rsrc))
+    (jmp @test)
+    @loop
+    (unbox-fixnum rsrc-byte-offset imm0)
+    (addq ($ '1) (% rsrc-byte-offset))
+    (movb (@ x8664::misc-data-offset (% rsrc) (% imm0)) (%b imm0))
+    (unbox-fixnum dest-byte-offset imm1)
+    (addq ($ '1) (% dest-byte-offset))
+    (addq (@ x8664::macptr.address (%q dest)) (% imm1))
+    (movb (%b imm0) (@ (% imm1)))
+    (subq ($ '1) (% nbytes))
+    @test
+    (jne @loop)
+    (movq (% dest) (% arg_z))
+    (single-value-return 4)))
+
+
+(defun %copy-ivector-to-ivector (src src-byte-offset dest dest-byte-offset nbytes)
+  (declare (fixnum src-byte-offset dest-byte-offset nbytes))
+  (if (or (eq src dest)
+          (not (eql 0 src-byte-offset))
+          (not (eql 0 dest-byte-offset))
+          (< nbytes 8))
+    (%copy-ivector-to-ivector-bytes src src-byte-offset dest dest-byte-offset nbytes)
+    (%copy-ivector-to-ivector-words src dest (ash nbytes -3) (logand nbytes 7))))
+
+(defx86lapfunction %copy-ivector-to-ivector-words ((src 8)
+                                                   #|(ra 0)|#
+                                                   (dest arg_x)
+                                                   (nwords arg_y)
+                                                   (nbytes arg_z))
+  (let ((rsrc temp0)
+         (ridx imm1)
+         (rval imm0))
+    (xorl (%l ridx) (%l ridx))
+    (movq (@ src (% rsp)) (% rsrc))
+    (jmp @word-test)
+    @word-loop
+    (movq (@ x8664::misc-data-offset (% rsrc) (% ridx)) (% rval))
+    (movq (% rval) (@ x8664::misc-data-offset (% dest) (% ridx)))
+    (addq ($ 8) (% ridx))
+    @word-test
+    (cmpq (% ridx) (% nwords))
+    (jne @word-loop)
+    (jmp @byte-test)
+    @byte-loop
+    (movb (@ x8664::misc-data-offset (% rsrc) (% ridx)) (%b rval))
+    (movb (%b rval) (@ x8664::misc-data-offset (% dest) (% ridx)))
+    (addq ($ 1) (% ridx))
+    @byte-test
+    (subq ($ '1) (% nbytes))
+    (jns @byte-loop)
+    (movq (% dest) (% arg_z))
+    (single-value-return 3)))
+          
+    
+    
+
+(defx86lapfunction %copy-ivector-to-ivector-bytes ((src-offset 16) 
+                                                   (src-byte-offset 8)
+                                                   #|(ra 0)|#
+                                                   (dest arg_x)
+                                                   (dest-byte-offset arg_y)
+                                                   (nbytes arg_z))
+  (let ((rsrc temp0)
+        (rsrc-byte-offset temp1))
+    (movq (@ src-byte-offset (% rsp)) (% rsrc-byte-offset))
+    (movq (@ src-offset (% rsp)) (% rsrc))
+    (cmpq (% dest) (% rsrc))
+    (jne @front)
+    (cmpq (% src-byte-offset) (% dest-byte-offset))
+    (jg @back)
+    @front
+    (testq (% nbytes) (% nbytes))
+    (jmp @front-test)
+    @front-loop
+    (unbox-fixnum rsrc-byte-offset imm0)
+    (addq ($ '1) (% rsrc-byte-offset))
+    (movb (@ x8664::misc-data-offset (% rsrc) (% imm0)) (%b imm0))
+    (unbox-fixnum dest-byte-offset imm1)
+    (addq ($ '1) (% dest-byte-offset))
+    (movb (%b imm0) (@ x8664::misc-data-offset (% dest) (% imm1)))
+    (subq ($ '1) (% nbytes))
+    @front-test
+    (jne @front-loop)
+    (movq (% dest) (% arg_z))
+    (single-value-return 4)
+    @back
+    (addq (% nbytes) (% rsrc-byte-offset))
+    (addq (% nbytes) (% dest-byte-offset))
+    (testq (% nbytes) (% nbytes))
+    (jmp @back-test)
+    @back-loop
+    (subq ($ '1) (% rsrc-byte-offset))
+    (unbox-fixnum rsrc-byte-offset imm0)
+    (movb (@ x8664::misc-data-offset (% rsrc) (% imm0)) (%b imm0))
+    (subq ($ '1) (% dest-byte-offset))
+    (unbox-fixnum dest-byte-offset imm1)
+    (subq ($ '1) (% nbytes))
+    (movb (%b imm0) (@ x8664::misc-data-offset (% dest) (% imm1)))
+    @back-test
+    (jne @back-loop)
+    (movq (% dest) (% arg_z))
+    (single-value-return 4)))
+  
+
+(defx86lapfunction %copy-gvector-to-gvector ((src (* 2 x8664::node-size))
+					     (src-element (* 1 x8664::node-size))
+                                             #|(ra 0)|#
+					     (dest arg_x)
+					     (dest-element arg_y)
+					     (nelements arg_z))
+  (let ((rsrc temp0)
+        (rsrc-element imm1)
+        (val temp1))
+    (movq (@ src-element (% rsp)) (% rsrc-element))
+    (movq (@ src (% rsp)) (% rsrc))
+    (cmpq (% rsrc) (% dest))
+    (jne @front)
+    (rcmp (% rsrc-element) (% dest-element))
+    (jl @back)
+    @front
+    (testq (% nelements) (% nelements))
+    (jmp @front-test)
+    @front-loop
+    (movq (@ x8664::misc-data-offset (% rsrc) (% rsrc-element)) (% val))
+    (addq ($ '1) (% rsrc-element))
+    (movq (% val) (@ x8664::misc-data-offset (% dest) (% dest-element)))
+    (addq ($ '1) (% dest-element))
+    (subq ($ '1) (% nelements))
+    @front-test
+    (jne @front-loop)
+    (movq (% dest) (% arg_z))
+    (single-value-return 4)
+    @back
+    (addq (% nelements) (% rsrc-element))
+    (addq (% nelements) (% dest-element))
+    (testq (% nelements) (% nelements))
+    (jmp @back-test)
+    @back-loop
+    (subq ($ '1) (% rsrc-element))
+    (movq (@ x8664::misc-data-offset (% rsrc) (% rsrc-element)) (% val))
+    (subq ($ '1) (% dest-element))
+    (movq (% val) (@ x8664::misc-data-offset (% dest) (% dest-element)))
+    (subq ($ '1) (% nelements))
+    @back-test
+    (jne @back-loop)
+    (movq (% dest) (% arg_z))
+    (single-value-return 4)))
+
+(defx86lapfunction %heap-bytes-allocated ()
+  (movq (:rcontext x8664::tcr.save-allocptr) (% temp1))
+  (movq (:rcontext x8664::tcr.last-allocptr) (% temp0))
+  (cmpq ($ -16) (% temp1))
+  (movq (:rcontext x8664::tcr.total-bytes-allocated) (% imm0))
+  (jz @go)
+  (movq (% temp0) (% temp2))
+  (subq (% temp1) (% temp0))
+  (testq (% temp2) (% temp2))
+  (jz @go)
+  (add (% temp0) (% imm0))
+  @go
+  (jmp-subprim .SPmakeu64))
+
+
+(defx86lapfunction values ()
+  (:arglist (&rest values))
+  (save-frame-variable-arg-count)
+  (push-argregs)
+  (jmp-subprim .SPnvalret))
+
+(defx86lapfunction rdtsc ()
+  (:byte #x0f)                          ;two-byte rdtsc opcode
+  (:byte #x31)                          ;is #x0f #x31
+  (shlq ($ 32) (% rdx))
+  (orq (% rdx) (% rax))
+  (imul ($ (* 2 target::node-size)) (% rax) (% arg_z))
+  (shrq ($ 1) (% arg_z))
+  (single-value-return))
+
+;;; Return all 64 bits of the time-stamp counter as an unsigned integer.
+(defx86lapfunction rdtsc64 ()
+  (:byte #x0f)                          ;two-byte rdtsc opcode
+  (:byte #x31)                          ;is #x0f #x31
+  (shlq ($ 32) (% rdx))
+  (orq (% rdx) (% rax))
+  (jmp-subprim .SPmakeu64))
+
+;;; It would be nice if (%setf-macptr macptr (ash (the fixnum value)
+;;; ash::fixnumshift)) would do this inline.
+
+(defx86lapfunction %setf-macptr-to-object ((macptr arg_y) (object arg_z))
+  (check-nargs 2)
+  (trap-unless-typecode= macptr x8664::subtag-macptr)
+  (movq (% object) (@ x8664::macptr.address (% macptr)))
+  (single-value-return))
+
+(defx86lapfunction %fixnum-from-macptr ((macptr arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= arg_z x8664::subtag-macptr)
+  (movq (@ x8664::macptr.address (% arg_z)) (% imm0))
+  (trap-unless-lisptag= imm0 x8664::tag-fixnum imm1)
+  (movq (% imm0) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %%get-unsigned-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr x8664::subtag-macptr)
+  (macptr-ptr ptr imm1)
+  (unbox-fixnum offset imm0)
+  (movq (@ (% imm1) (% imm0)) (% imm0))
+  (jmp-subprim .SPmakeu64))
+
+
+(defx86lapfunction %%get-signed-longlong ((ptr arg_y) (offset arg_z))
+  (trap-unless-typecode= ptr x8664::subtag-macptr)
+  (macptr-ptr ptr imm1)
+  (unbox-fixnum offset imm0)
+  (movq (@ (% imm1) (% imm0)) (% imm0))
+  (jmp-subprim .SPmakes64))
+
+
+
+
+(defx86lapfunction %%set-unsigned-longlong ((ptr arg_x)
+                                            (offset arg_y)
+                                            (val arg_z))
+  (save-simple-frame)
+  (trap-unless-typecode= ptr x8664::subtag-macptr)
+  (call-subprim .SPgetu64)
+  (macptr-ptr ptr imm2)
+  (unbox-fixnum offset imm1)
+  (movq (% imm0) (@ (% imm2) (% imm1)))
+  (restore-simple-frame)
+  (single-value-return))
+
+
+(defx86lapfunction %%set-signed-longlong ((ptr arg_x)
+                                          (offset arg_y)
+                                          (val arg_z))
+  (save-simple-frame)
+  (trap-unless-typecode= ptr x8664::subtag-macptr)
+  (call-subprim .SPgets64)
+  (macptr-ptr ptr imm2)
+  (unbox-fixnum offset imm1)
+  (movq (% imm0) (@ (% imm2) (% imm1)))
+  (restore-simple-frame)
+  (single-value-return))
+
+(defx86lapfunction interrupt-level ()
+  (movq (:rcontext x8664::tcr.tlb-pointer) (% imm1))
+  (movq (@ x8664::interrupt-level-binding-index (% imm1)) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction set-interrupt-level ((new arg_z))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (% imm1))
+  (trap-unless-fixnum new)
+  (movq (% new) (@ x8664::interrupt-level-binding-index (% imm1)))
+  (single-value-return))
+
+(defx86lapfunction %current-tcr ()
+  (movq (:rcontext x8664::tcr.linear) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %tcr-toplevel-function ((tcr arg_z))
+  (check-nargs 1)
+  (cmpq (% tcr) (:rcontext x8664::tcr.linear))
+  (movq (% rsp) (% imm0))
+  (movq (@ x8664::tcr.vs-area (% tcr)) (% temp0))
+  (movq (@ x8664::area.high (% temp0)) (% imm1))
+  (jz @room)
+  (movq (@ x8664::area.active (% temp0)) (% imm0))
+  @room
+  (cmpq (% imm1) (% imm0))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (cmovneq (@ (- x8664::node-size) (% imm1)) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %set-tcr-toplevel-function ((tcr arg_y) (fun arg_z))
+  (check-nargs 2)
+  (cmpq (% tcr) (:rcontext x8664::tcr.linear))
+  (movq (% rsp) (% imm0))
+  (movq (@ x8664::tcr.vs-area (% tcr)) (% temp0))
+  (movq (@ x8664::area.high (% temp0)) (% imm1))
+  (jz @room)
+  (movq (@ x8664::area.active (% temp0)) (% imm0))
+  @room
+  (cmpq (% imm1) (% imm0))
+  (leaq (@ (- x8664::node-size) (% imm1)) (% imm1))
+  (movq ($ 0) (@ (% imm1)))
+  (jne @have-room)
+  (movq (% imm1) (@ x8664::area.active (% temp0)))
+  (movq (% imm1) (@ x8664::tcr.save-vsp (% tcr)))
+  @have-room
+  (movq (% fun) (@ (% imm1)))
+  (single-value-return))
+
+;;; This needs to be done out-of-line, to handle EGC memoization.
+(defx86lapfunction %store-node-conditional ((offset 8) #|(ra 0)|# (object arg_x) (old arg_y) (new arg_z))
+  (movq (@ offset (% rsp)) (% temp0))
+  (save-simple-frame)
+  (call-subprim .SPstore-node-conditional)
+  (restore-simple-frame)
+  (single-value-return 3))
+
+(defx86lapfunction %store-immediate-conditional ((offset 8) #|(ra 0)|# (object arg_x) (old arg_y) (new arg_z))
+  (movq (@ offset (% rsp)) (% temp0))
+  (unbox-fixnum temp0 imm1)
+  @again
+  (movq (@ (% object) (% imm1)) (% rax))
+  (cmpq (% rax) (% old))
+  (jne @lose)
+  (lock)
+  (cmpxchgq (% new) (@ (% object) (% imm1)))
+  (jne @again)
+  (movl ($ (target-t-value)) (%l arg_z))
+  (single-value-return 3)
+  @lose
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (single-value-return 3))
+
+(defx86lapfunction set-%gcable-macptrs% ((ptr x8664::arg_z))
+  @again
+  (movq (@ (+ (target-nil-value) (x8664::kernel-global gcable-pointers)))
+        (% rax))
+  (movq (% rax) (@ x8664::xmacptr.link (% ptr)))
+  (lock)
+  (cmpxchgq (% ptr) (@ (+ (target-nil-value) (x8664::kernel-global gcable-pointers))))
+  (jne @again)
+  (single-value-return))
+
+;;; Atomically increment or decrement the gc-inhibit-count kernel-global
+;;; (It's decremented if it's currently negative, incremented otherwise.)
+(defx86lapfunction %lock-gc-lock ()
+  @again
+  (movq (@ (+ (target-nil-value) (x8664::kernel-global gc-inhibit-count))) (% rax))
+  (lea (@ '-1 (% rax)) (% temp0))
+  (lea (@ '1 (% rax)) (% arg_z))
+  (testq (% rax) (% rax))
+  (cmovsq (% temp0) (% arg_z))
+  (lock)
+  (cmpxchgq (% arg_z) (@ (+ (target-nil-value) (x8664::kernel-global gc-inhibit-count))))
+  (jnz @again)
+  (single-value-return))
+
+;;; Atomically decrement or increment the gc-inhibit-count kernel-global
+;;; (It's incremented if it's currently negative, incremented otherwise.)
+;;; If it's incremented from -1 to 0, try to GC (maybe just a little.)
+(defx86lapfunction %unlock-gc-lock ()
+  @again
+  (movq (@ (+ (target-nil-value) (x8664::kernel-global gc-inhibit-count)))
+        (% rax))
+  (lea (@ '1 (% rax)) (% arg_x))
+  (cmpq ($ -1) (% rax))
+  (lea (@ '-1 (% rax)) (% arg_z))
+  (cmovleq (% arg_x) (% arg_z))
+  (lock)
+  (cmpxchgq (% arg_z) (@ (+ (target-nil-value) (x8664::kernel-global gc-inhibit-count))))
+  (jne @again)
+  (cmpq ($ '-1) (% rax))
+  (jne @done)
+  ;; The GC tried to run while it was inhibited.  Unless something else
+  ;; has just inhibited it, it should be possible to GC now.
+  (mov ($ arch::gc-trap-function-immediate-gc) (% imm0))
+  (uuo-gc-trap)
+  @done
+  (single-value-return))
+
+;;; Return true iff we were able to increment a non-negative
+;;; lock._value
+
+
+
+
+(defx86lapfunction %atomic-incf-node ((by arg_x) (node arg_y) (disp arg_z))
+  (check-nargs 3)
+  (unbox-fixnum disp imm1)
+  @again
+  (movq (@ (% node) (% imm1)) (% rax))
+  (lea (@ (% rax) (% by)) (% arg_z))
+  (lock)
+  (cmpxchgq (% arg_z) (@ (% node) (% imm1)))
+  (jne @again)
+  (single-value-return))
+
+(defx86lapfunction %atomic-incf-ptr ((ptr arg_z))
+  (macptr-ptr ptr imm2)
+  @again
+  (movq (@ (% imm2)) (% rax))
+  (lea (@ 1 (% rax)) (% imm1))
+  (lock)
+  (cmpxchgq (% imm1) (@ (% imm2)))
+  (jne @again)
+  (box-fixnum imm1 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %atomic-incf-ptr-by ((ptr arg_y) (by arg_z))
+  (macptr-ptr ptr imm2)
+  @again
+  (movq (@ (% imm2)) (% rax))
+  (unbox-fixnum by imm1)
+  (add (% rax) (% imm1))
+  (lock)
+  (cmpxchgq (% imm1) (@ (% imm2)))
+  (jnz @again)
+  (box-fixnum imm1 arg_z)
+  (single-value-return))
+
+
+(defx86lapfunction %atomic-decf-ptr ((ptr arg_z))
+  (macptr-ptr ptr imm2)
+  @again
+  (movq (@ (% imm2)) (% rax))
+  (lea (@ -1 (% rax)) (% imm1))
+  (lock)
+  (cmpxchgq (% imm1) (@ (% imm2)))
+  (jnz @again)
+  (box-fixnum imm1 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %atomic-decf-ptr-if-positive ((ptr arg_z))
+  (macptr-ptr ptr imm2)
+  @again
+  (movq (@ (% imm2)) (% rax))
+  (testq (% rax) (% rax))
+  (lea (@ -1 (% rax)) (% imm1))
+  (jz @done)
+  (lock)
+  (cmpxchgq (% imm1) (@ (% imm2)))
+  (jnz @again)
+  @done
+  (box-fixnum imm1 arg_z)
+  (single-value-return))
+
+
+(defx86lapfunction %atomic-swap-ptr ((ptr arg_y) (newval arg_z))
+  (macptr-ptr arg_y imm1)
+  (unbox-fixnum newval imm0)
+  (lock)
+  (xchgq (% imm0) (@ (% imm1)))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+;;; Try to store the fixnum NEWVAL at PTR, if and only if the old value
+;;; was equal to OLDVAL.  Return the old value
+(defx86lapfunction %ptr-store-conditional ((ptr arg_x) (expected-oldval arg_y) (newval arg_z))
+  (macptr-ptr ptr imm2)
+  @again
+  (movq (@ (% imm2)) (% imm0))
+  (box-fixnum imm0 temp0)
+  (cmpq (% temp0) (% expected-oldval))
+  (jne @done)
+  (unbox-fixnum newval imm1)
+  (lock)
+  (cmpxchgq (% imm1) (@ (% imm2)))
+  (jne @again)
+  @done
+  (movq (% temp0) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %ptr-store-fixnum-conditional ((ptr arg_x) (expected-oldval arg_y) (newval arg_z))
+  (let ((address imm1))
+    (macptr-ptr ptr address)
+    @again
+    (movq (@ (% address)) (% imm0))
+    (cmpq (% imm0) (% expected-oldval))
+    (jne @done)
+    (lock)
+    (cmpxchgq (% newval) (@ (% address)))
+    (jne @again)
+    @done
+    (movq (% imm0) (% arg_z))
+    (single-value-return)))
+
+(defx86lapfunction xchgl ((newval arg_y) (ptr arg_z))
+  (unbox-fixnum newval imm0)
+  (macptr-ptr ptr imm1)
+  (lock)                                ; implicit ?
+  (xchgl (% imm0.l) (@ (% imm1)))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+  
+                          
+
+
+(defx86lapfunction %macptr->dead-macptr ((macptr arg_z))
+  (check-nargs 1)
+  (movb ($ x8664::subtag-dead-macptr) (@ x8664::misc-subtag-offset (% macptr)))
+  (single-value-return))
+
+
+
+
+  
+(defx86lapfunction %%save-application ((flags arg_y) (fd arg_z))
+  (unbox-fixnum flags imm0)
+  (orq ($ arch::gc-trap-function-save-application) (% imm0))
+  (unbox-fixnum fd imm1)
+  (uuo-gc-trap)
+  (single-value-return))
+
+
+
+(defx86lapfunction %misc-address-fixnum ((misc-object arg_z))
+  (check-nargs 1)
+  (lea (@ x8664::misc-data-offset (% misc-object)) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction fudge-heap-pointer ((ptr arg_x) (subtype arg_y) (len arg_z))
+  (check-nargs 3)
+  (macptr-ptr ptr imm1) ; address in macptr
+  (lea (@ 17 (% imm1)) (% imm0))     ; 2 for delta + 15 for alignment
+  (andb ($ -16) (%b  imm0))   ; Clear low four bits to align
+  (subq (% imm0) (% imm1))  ; imm1 = -delta
+  (negw (%w imm1))
+  (movw (%w imm1) (@  -2 (% imm0)))     ; save delta halfword
+  (unbox-fixnum subtype imm1)  ; subtype at low end of imm1
+  (shlq ($ (- x8664::num-subtag-bits x8664::fixnum-shift)) (% len ))
+  (orq (% len) (% imm1))
+  (movq (% imm1) (@ (% imm0)))       ; store subtype & length
+  (lea (@ x8664::fulltag-misc (% imm0)) (% arg_z)) ; tag it, return it
+  (single-value-return))
+
+(defx86lapfunction %%make-disposable ((ptr arg_y) (vector arg_z))
+  (check-nargs 2)
+  (lea (@ (- x8664::fulltag-misc) (% vector)) (% imm0)) ; imm0 is addr = vect less tag
+  (movzwq (@ -2 (% imm0)) (% imm1))     ; get delta
+  (subq (% imm1) (% imm0))              ; vector addr (less tag)  - delta is orig addr
+  (movq (% imm0) (@ x8664::macptr.address (% ptr)))
+  (single-value-return))
+
+
+(defx86lapfunction %vect-data-to-macptr ((vect arg_y) (ptr arg_z))
+  (lea (@ x8664::misc-data-offset (% vect)) (% imm0))
+  (movq (% imm0) (@ x8664::macptr.address (% ptr)))
+  (single-value-return))
+
+(defx86lapfunction get-saved-register-values ()
+  (movq (% rsp) (% temp0))
+  (push (% save0))
+  (push (% save1))
+  (push (% save2))
+  (push (% save3))                      ; this'd be the TCR on Win64.
+  (set-nargs 4)
+  (jmp-subprim .SPvalues))
+
+
+(defx86lapfunction %current-db-link ()
+  (movq (:rcontext x8664::tcr.db-link) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %no-thread-local-binding-marker ()
+  (movq ($ x8664::subtag-no-thread-local-binding) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction pending-user-interrupt ()
+  (xorq (% imm0) (% imm0))
+  (ref-global x8664::intflag arg_z)
+  ;; If another signal happens now, it will get ignored, same as if it happened
+  ;; before whatever signal is in arg_z.  But then these are async signals, so
+  ;; who can be sure it didn't actually happen just before...
+  (set-global imm0 x8664::intflag)
+  (single-value-return))
+
+
+(defx86lapfunction debug-trap-with-string ((arg arg_z))
+  (check-nargs 1)
+  (uuo-error-debug-trap-with-string)
+  (single-value-return))
+
+(defx86lapfunction %safe-get-ptr ((src arg_y) (dest arg_z))
+  (check-nargs 2)
+  (save-simple-frame)
+  (macptr-ptr src imm0)
+  (leaq (@ (:^ done) (% fn)) (% ra0))
+  (movq (% imm0) (:rcontext x8664::tcr.safe-ref-address))
+  (movq (@ (% imm0)) (% imm0))
+  (jmp done)
+  (:tra done)
+  (recover-fn-from-rip)
+  (movq ($ 0) (:rcontext x8664::tcr.safe-ref-address))
+  (movq (% imm0) (@ x8664::macptr.address (% dest)))
+  (restore-simple-frame)
+  (single-value-return))
+
+;;; This was intentded to work around a bug in #_nanosleep in early
+;;; Leopard test releases.  It's probably not necessary any more; is
+;;; it still called ?
+
+(defx86lapfunction %check-deferred-gc ()
+  (btq ($ (+ arch::tcr-flag-bit-pending-suspend target::fixnumshift)) (:rcontext x8664::tcr.flags))
+  (movl ($ (target-nil-value)) (% arg_z.l))
+  (jae @done)
+  (ud2a)
+  (:byte 3)
+  (movl ($ (target-t-value)) (% arg_z.l))
+  @done
+  (single-value-return))
+
+(defx86lapfunction %%tcr-interrupt ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 4)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %suspend-tcr ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 5)
+  (movzbl (%b imm0) (%l imm0))
+  (testl (%l imm0) (%l imm0))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (cmovnel (@ (+ target::t-offset target::symbol.vcell) (% arg_z)) (%l arg_z))
+  (single-value-return))
+
+(defx86lapfunction %suspend-other-threads ()
+  (check-nargs 0)
+  (ud2a)
+  (:byte 6)
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (single-value-return))
+
+(defx86lapfunction %resume-tcr ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 7)
+  (movzbl (%b imm0) (%l imm0))
+  (testl (%l imm0) (%l imm0))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (cmovnel (@ (+ target::t-offset target::symbol.vcell) (% arg_z)) (%l arg_z))
+  (single-value-return))
+
+(defx86lapfunction %resume-other-threads ()
+  (check-nargs 0)
+  (ud2a)
+  (:byte 8)
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (single-value-return))
+
+(defx86lapfunction %kill-tcr ((target arg_z))
+  (check-nargs 1)
+  (ud2a)
+  (:byte 9)
+  (testb (%b imm0) (%b imm0))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (cmovnel (@ (+ target::t-offset target::symbol.vcell) (% arg_z)) (%l arg_z))
+  (single-value-return))
+  
+
+(defx86lapfunction %get-spin-lock ((p arg_z))
+  (check-nargs 1)
+  (save-simple-frame)
+  @again
+  (macptr-ptr arg_z imm1)
+  (movq (@ '*spin-lock-tries* (% fn)) (% temp0))
+  (movq (@ '*spin-lock-timeouts* (% fn)) (% temp1))
+  (movq (@ target::symbol.vcell (% temp0)) (% temp0))
+  (movq (:rcontext x8664::tcr.linear) (% arg_y))
+  @try-swap
+  (xorq (% rax) (% rax))
+  (lock)
+  (cmpxchgq (% arg_y) (@ (% imm1)))
+  (je @done)
+  @spin
+  (pause)
+  (cmpq ($ 0) (@ (% imm1)))
+  (je @try-swap)
+  (subq ($ '1) (% temp0))
+  (jne @spin)
+  @wait
+  (addq ($ x8664::fixnumone) (@ x8664::symbol.vcell (% temp1)))
+  (pushq (% arg_z))
+  (call-symbol yield 0)
+  (popq (% arg_z))
+  (jmp @again)
+  @done
+  (restore-simple-frame)
+  (single-value-return))
+
+;;; This is a prototype; it can't easily keep its arguments on the stack,
+;;; or in registers, because its job involves unwinding the stack and
+;;; restoring registers.  Its parameters are thus kept in constants,
+;;; and this protoype is cloned (with the right parameters).
+
+;;; For win64 (which doesn't really have a "save3" register), the code
+;;; which instantiates this should always set save3-offset to 0.
+(defx86lapfunction %%apply-in-frame-proto ()
+  (:fixed-constants (target-frame target-catch target-db-link target-xcf target-tsp target-foreign-sp save0-offset save1-offset save2-offset save3-offset function args))
+  (check-nargs 0)
+  ;;(uuo-error-debug-trap)
+  (movq (@ 'target-catch (% fn)) (% temp0))
+  (xorl (%l imm0) (%l imm0))
+  (cmpb ($ x8664::fulltag-nil) (%b temp0))
+  (movq (:rcontext target::tcr.catch-top) (% arg_z))
+  (jz @did-catch)
+  @find-catch
+  (testq (% arg_z) (% arg_z))
+  (jz @did-catch)                       ; never found target catch
+  (addq ($ '1)  (% imm0))
+  (cmpq (% temp0) (% arg_z))
+  (je @found-catch)
+  (movq (@ target::catch-frame.link (% arg_z)) (% arg_z))
+  (jmp @find-catch)
+  @found-catch
+  (set-nargs 0)                         ; redundant, but ...
+  (lea (@ (:^ @back-from-nthrow) (% fn)) (% ra0))
+  (:talign 4)
+  (jmp-subprim .SPnthrowvalues)
+  @back-from-nthrow
+  (recover-fn-from-rip)
+  @did-catch
+  ;; Restore special bindings
+  (movq (@ 'target-db-link (% fn)) (% imm0))
+  (cmpb ($ x8664::fulltag-nil) (%b imm0))
+  (jz @no-unbind)
+  (call-subprim .SPunbind-to)
+  @no-unbind
+  ;; If there's at least one exception frame between the target
+  ;; frame and the last catch (or the point of departure), restore
+  ;; the NVRs and foreign sp from the oldest such frame
+  (movq (@ 'target-xcf (% fn)) (% arg_z))
+  (cmpb ($ x8664::fulltag-nil) (%b arg_z))
+  (jz @no-xcf)
+  (movq (@ target::xcf.xp (% arg_z)) (% arg_y))
+  ;; arg_y points to a "portable" ucontext.  Find the platform-specifc
+  ;; "gpr vector" in the uc_mcontext, load the NVRs and stack/frame
+  ;; pointer from there.
+  #+linuxx8664-target
+  (progn
+    (addq ($ gp-regs-offset) (% arg_y))
+    (movq (@ (* #$REG_R15 8) (% arg_y)) (% r15))
+    (movq (@ (* #$REG_R14 8) (% arg_y)) (% r14))
+    (movq (@ (* #$REG_R12 8) (% arg_y)) (% r12))
+    (movq (@ (* #$REG_R11 8) (% arg_y)) (% r11))
+    (movq (@ (* #$REG_RBP 8) (% arg_y)) (% rbp))
+    (movq (@ (* #$REG_RSP 8) (% arg_y)) (% rsp)))
+  #+freebsdx8664-target
+  (progn
+    ;; If you think that this is ugly, just wait until you see the Darwin
+    ;; version.
+    (addq ($ gp-regs-offset) (% arg_y))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__mcontext)) :mc_r15)) -3) (% arg_y)) (% r15))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__mcontext)) :mc_r14)) -3) (% arg_y)) (% r14))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__mcontext)) :mc_r12)) -3) (% arg_y)) (% r12))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__mcontext)) :mc_r11)) -3) (% arg_y)) (% r11))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__mcontext)) :mc_rbp)) -3) (% arg_y)) (% rbp))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__mcontext)) :mc_rsp)) -3) (% arg_y)) (% rsp)))
+  #+darwinx8664-target
+  (progn
+    ;; Yes, this is ugly.
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_ucontext)) :uc_mcontext)) -3) (% arg_y)) (% arg_y))
+    (addq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_mcontext64)) :__ss)) -3)) (% arg_y))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_x86_thread_state64)) :__r15)) -3) (% arg_y)) (% r15))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_x86_thread_state64)) :__r14)) -3) (% arg_y)) (% r14))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_x86_thread_state64)) :__r12)) -3) (% arg_y)) (% r12))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_x86_thread_state64)) :__r11)) -3) (% arg_y)) (% r11))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_x86_thread_state64)) :__rbp)) -3) (% arg_y)) (% rbp))
+    (movq (@ (ash (foreign-record-field-offset (%find-foreign-record-type-field (parse-foreign-type '(:struct :__darwin_x86_thread_state64)) :__rsp)) -3) (% arg_y)) (% rsp)))
+  ;; This is our best (possibly only) chance to get
+  ;; the foreign sp right.
+  (movq (@ target::xcf.prev-xframe (% arg_z)) (% temp0))
+  (movq (@ target::xcf.foreign-sp (% arg_z)) (% imm0))
+  (movq (% temp0) (:rcontext target::tcr.xframe))
+  (movq (% imm0) (:rcontext target::tcr.foreign-sp))
+  ;; All done processing the xcf.  NVRs may have been
+  ;; saved between the last catch/last xcf and the
+  ;; target frame.  The save-n-offset parameter/constants
+  ;; are either 0 or negative offsets from the target frame
+  ;; of the stack location where the corresponding GPR
+  ;; was saved.
+  @no-xcf
+  (movq (@ 'target-tsp (% fn)) (% imm0))
+  (cmpb ($ x8664::fulltag-nil) (%b imm0))
+  (movq (@ 'target-foreign-sp (% fn)) (% temp0))
+  (je @no-tsp)
+  (movq (% imm0) (:rcontext target::tcr.save-tsp))
+  (movq (% imm0) (:rcontext target::tcr.next-tsp))
+  @no-tsp
+  (cmpb ($ x8664::fulltag-nil) (%b temp0))
+  (je @no-sp)
+  (movq (% temp0) (:rcontext target::tcr.foreign-sp))
+  @no-sp
+  (movq (@ 'target-frame (% fn)) (% rbp))
+  (movq (@ 'save0-offset (% fn)) (% arg_x))
+  (movq (@ 'save1-offset (% fn)) (% arg_y))
+  (movq (@ 'save2-offset (% fn)) (% arg_z))
+  (movq (@ 'save3-offset (% fn)) (% temp0))
+  (testq (% arg_x) (% arg_x))
+  (cmovneq (@ (% rbp) (% arg_x)) (% save0))
+  (testq (% arg_y) (% arg_y))
+  (cmovneq (@ (% rbp) (% arg_x)) (% save1))
+  (testq (% arg_z) (% arg_z))
+  (cmovneq (@ (% rbp) (% arg_x)) (% save2))
+  (testq (% temp0) (% temp0))
+  (cmovneq (@ (% rbp) (% arg_x)) (% save3))
+  (leave)
+  (pop (% temp0))                       ; return address, not used by subprim
+  (set-nargs 0)
+  (movq (@ 'args (% fn)) (% arg_z))
+  (lea (@ (:^ @back-from-spread) (% fn)) (% ra0))
+  (:talign 4)
+  (jmp-subprim .SPspreadargz)
+  @back-from-spread
+  (recover-fn-from-rip)                 ; .SPspreadargz preserves %fn, but ...
+  (push (% temp0))                      ; return address
+  (jmp (@ 'function (% fn))))
+  
+
+(defx86lapfunction %atomic-pop-static-cons ()
+  @again
+  (movq (@ (+ (target-nil-value) (x8664::kernel-global static-conses))) (% rax))
+  (cmpq ($ (target-nil-value)) (% rax))
+  (jz @lose)
+  (%cdr rax temp0)
+  (lock)
+  (cmpxchgq (% temp0) (@ (+ (target-nil-value) (x8664::kernel-global static-conses))))
+  (jnz @again)
+  (lock)
+  (subq ($ x8664::fixnumone) (@ (+ (target-nil-value) (x8664::kernel-global free-static-conses))))
+  @lose
+  (movq (% rax) (% arg_z))
+  (single-value-return))
+
+
+  
+(defx86lapfunction %staticp ((x arg_z))
+  (check-nargs 1)
+  (ref-global static-cons-area temp0)
+  (movq (% x) (% imm0))
+  (movl ($ (target-nil-value)) (% arg_z.l))
+  (subq (@ target::area.low (% temp0)) (% imm0))
+  (shrq ($ target::dnode-shift) (% imm0))
+  (movq (@ target::area.ndnodes (% temp0)) (% imm1))
+  (subq (% imm0) (% imm1))
+  (lea (@ 128 (% imm1)) (% imm1))
+  (leaq (@ (% imm1) target::fixnumone) (% imm1))
+  (cmovaq (% imm1) (% arg_z))
+  (single-value-return))
+
+(defx86lapfunction %static-inverse-cons ((n arg_z))
+  (check-nargs 1)
+  (subq ($ '128) (% arg_z))
+  (ref-global static-cons-area temp0)
+  (movq (@ target::area.high (% temp0)) (% imm0))
+  (subq (% arg_z) (% imm0))
+  (subq (% arg_z) (% imm0))
+  (lea (@ x8664::fulltag-cons (% imm0)) (% arg_z))
+  (single-value-return))
+
+
+  
+
+;;; end of x86-misc.lisp
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-numbers.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-numbers.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-numbers.lisp	(revision 13309)
@@ -0,0 +1,195 @@
+;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+
+
+(defx86lapfunction %fixnum-signum ((number arg_z))
+  (movq ($ '-1) (% arg_x))
+  (movq ($ '1) (% arg_y))
+  (testq (% number) (% number))
+  (cmovsq (% arg_x) (% arg_z))
+  (cmovnsq (% arg_y) (% arg_z))
+  (single-value-return))
+
+;;; see %logcount.
+(defx86lapfunction %ilogcount ((number arg_z))
+  (let ((rshift imm0)
+        (temp imm1))
+    (unbox-fixnum number rshift)
+    (xorq (% arg_z) (% arg_z))
+    (testq (% rshift) (% rshift))
+    (jmp @test)
+    @next
+    (lea (@ -1 (% rshift)) (% temp))
+    (and (% temp) (% rshift))            ; sets flags
+    (lea (@ '1 (% arg_z)) (% arg_z))    ; doesn't set flags
+    @test
+    (jne @next)
+    (single-value-return)))
+
+(defx86lapfunction %iash ((number arg_y) (count arg_z))
+  (unbox-fixnum count imm1)
+  (unbox-fixnum number imm0)
+  (xorq (% rcx) (% rcx))                ;rcx = imm2
+  (testq (% count) (% count))
+  (jge @left)
+  (subb (% imm1.b) (% cl))
+  (sar (% cl) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return)
+  @left
+  (movb (% imm1.b) (% cl))
+  (shl (% cl) (% number))
+  (movq (% number) (% arg_z))
+  (single-value-return))
+
+(defparameter *double-float-zero* 0.0d0)
+(defparameter *short-float-zero* 0.0s0)
+
+
+(defx86lapfunction %fixnum-intlen ((number arg_z))
+  (unbox-fixnum arg_z imm0)
+  (movq (% imm0) (% imm1))
+  (notq (% imm1))
+  (testq (% imm0) (% imm0))
+  (cmovsq (% imm1) (% imm0))
+  (bsrq (% imm0) (% imm0))
+  (setne (% imm1.b))
+  (addb (% imm1.b) (% imm0.b))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+
+;;; Caller guarantees that result fits in a fixnum.
+
+(defx86lapfunction %truncate-double-float->fixnum ((arg arg_z))
+  (get-double-float arg fp1)
+  (cvttsd2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+
+(defx86lapfunction %truncate-short-float->fixnum ((arg arg_z))
+  (get-single-float arg fp1)
+  (cvttss2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+;;; DOES round to even
+
+(defx86lapfunction %round-nearest-double-float->fixnum ((arg arg_z))
+  (get-double-float arg fp1)
+  (cvtsd2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+
+(defx86lapfunction %round-nearest-short-float->fixnum ((arg arg_z))
+  (get-single-float arg fp1)
+  (cvtss2si (% fp1) (% imm0))
+  (box-fixnum imm0 arg_z)  
+  (single-value-return))
+
+
+;;; We'll get a SIGFPE if divisor is 0.
+;;; Don't use %rbp.  Trust callback_for_interrupt() to preserve
+;;; the word below the stack pointer
+(defx86lapfunction %fixnum-truncate ((dividend arg_y) (divisor arg_z))
+  (save-simple-frame)
+  (unbox-fixnum divisor imm0)
+  (movq (% imm0) (% imm2))
+  (unbox-fixnum dividend imm0)
+  (cqto)                                ; imm1 := sign_extend(imm0)
+  (idivq (% imm2))
+  (pop (% rbp))
+  (movq (% rsp) (% temp0))
+  (box-fixnum imm1 arg_y)
+  (box-fixnum imm0 arg_z)
+  (pushq (% arg_z))
+  (pushq (% arg_y))
+  (set-nargs 2)
+  (jmp-subprim .SPvalues))
+
+(defx86lapfunction called-for-mv-p ()
+  (ref-global ret1valaddr imm0)
+  (movq (@ x8664::lisp-frame.return-address (% rbp)) (% imm1))
+  (cmpq (% imm0) (% imm1))
+  (movq ($ t) (% imm0))
+  (movq ($ nil) (% arg_z))
+  (cmoveq (% imm0) (% arg_z))
+  (single-value-return))
+
+
+;;; n1 and n2 must be positive (esp non zero)
+(defx86lapfunction %fixnum-gcd ((boxed-u arg_y) (boxed-v arg_z))
+  (let ((u imm0)
+        (v imm1)
+        (k imm2))
+    (xorl (% imm2.l) (% imm2.l))
+    (bsfq (% boxed-u) (% u))
+    (bsfq (% boxed-v) (% v))
+    (rcmp (% u) (% v))
+    (cmovlel (%l u) (%l k))
+    (cmovgl (%l v) (%l k))
+    (unbox-fixnum boxed-u u)
+    (unbox-fixnum boxed-v v)
+    (subb ($ x8664::fixnumshift) (%b k))
+    (jz @start)
+    (shrq (% cl) (% u))
+    (shrq (% cl) (% v))
+    @start
+    ;; At least one of u or v is odd at this point
+    @loop
+    ;; if u is even, shift it right one bit
+    (testb ($ 1) (%b u))
+    (jne @u-odd)
+    (shrq ($ 1) (% u))
+    (jmp @test)
+    @u-odd
+    ;; if v is even, shift it right one bit
+    (testb ($ 1) (%b v))
+    (jne @both-odd)
+    (shrq ($ 1) (% v))
+    (jmp @test-u)
+    @both-odd
+    (cmpq (% v) (% u))
+    (jb @v>u)
+    (subq (% v) (% u))
+    (shrq ($ 1) (% u))
+    (jmp @test)
+    @v>u
+    (subq (% u) (% v))
+    (shrq ($ 1) (% v))
+    @test-u
+    (testq (% u) (% u))
+    @test
+    (ja @loop)
+    (shlq (% cl) (% v))
+    (movb ($ 0) (% cl))
+    (box-fixnum v arg_z)
+    (single-value-return)))
+
+
+
+;;; End of x86-numbers.lisp
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-pred.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-pred.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-pred.lisp	(revision 13309)
@@ -0,0 +1,191 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+(eval-when (:compile-toplevel :execute)
+  (require "X86-LAPMACROS"))
+
+
+(defx86lapfunction eql ((x arg_y) (y arg_z))
+  "Return T if OBJ1 and OBJ2 represent either the same object or
+numbers with the same type and value."
+  (check-nargs 2)
+  @top
+  @tail
+  (cmpq (% x) (% y))
+  (je @win)
+  (extract-fulltag x imm0)
+  (extract-fulltag y imm1)
+  (cmpb (% imm0.b) (% imm1.b))
+  (jnz @lose)
+  (cmpb ($ x8664::fulltag-misc) (% imm0.b))
+  (jnz @lose)
+  (getvheader x imm0)
+  (getvheader y imm1)
+  (cmpb ($ x8664::subtag-macptr) (% imm0.b))
+  (je @macptr)                          ; will need to check %imm1.b
+  (cmpq (% imm0) (% imm1))
+  (jne @lose)
+  (cmpb ($ x8664::subtag-bignum) (% imm0.b))
+  (je @bignum)
+  (cmpb ($ x8664::subtag-double-float) (% imm0.b))
+  (je @double-float)
+  (cmpb ($ x8664::subtag-complex) (% imm0.b))
+  (je @complex)
+  (cmpb ($ x8664::subtag-ratio) (% imm0.b))
+  (je @ratio)
+  @lose
+  (movq ($ nil) (% arg_z))
+  (single-value-return)
+  @macptr
+  (cmpb ($ x8664::subtag-macptr) (% imm1.b))
+  (jne @lose)
+  @double-float
+  (movq  (@ x8664::misc-data-offset (% x)) (% imm0))
+  (movq  (@ x8664::misc-data-offset (% y)) (% imm1))
+  @test
+  (cmpq (% imm0) (% imm1))
+  (movl ($ (target-t-value)) (%l imm0))
+  (lea (@ (- x8664::t-offset) (% imm0)) (% arg_z))
+  (cmovel (%l imm0) (%l arg_z))
+  (single-value-return)
+  @win
+  (movq ($ t) (% arg_z))
+  (single-value-return)
+  @ratio
+  @complex
+  (save-simple-frame)
+  (pushq (@ x8664::ratio.denom (% x)))  ; aka complex.imagpart
+  (pushq (@ x8664::ratio.denom (% y)))
+  (movq (@ x8664::ratio.numer (% x)) (% x))       ; aka complex.realpart
+  (movq (@ x8664::ratio.numer (% y)) (% y))       ; aka complex.realpart
+  (:talign 3)
+  (call @top)
+  (recover-fn-from-rip)
+  (cmp-reg-to-nil arg_z)
+  (pop (% y))
+  (pop (% x))
+  (restore-simple-frame)
+  (jnz @tail)
+  ;; lose, again
+  (movq ($ nil) (% arg_z))
+  (single-value-return)
+  @bignum
+  ;; Way back when, we got x's header into imm0.  We know that y's
+  ;; header is identical.  Use the element-count from imm0 to control
+  ;; the loop.  There's no such thing as a 0-element bignum, so the
+  ;; loop must always execute at least once.
+  (header-length imm0 temp0)
+  (xorq (% imm1) (% imm1))
+  @bignum-next
+  (movl (@ x8664::misc-data-offset (% x) (% imm1)) (% imm0.l))
+  (cmpl (@ x8664::misc-data-offset (% y) (% imm1)) (% imm0.l))
+  (jne @lose)
+  (addq ($ 4) (% imm1))
+  (sub ($ '1) (% temp0))
+  (jnz @bignum-next)
+  (movq ($ t) (% arg_z))
+  (single-value-return))
+  
+
+
+(defx86lapfunction equal ((x arg_y) (y arg_z))
+  "Return T if X and Y are EQL or if they are structured components
+  whose elements are EQUAL. Strings and bit-vectors are EQUAL if they
+  are the same length and have identical components. Other arrays must be
+  EQ to be EQUAL.  Pathnames are EQUAL if their components are."
+  (check-nargs 2)
+  @top
+  @tail
+  (cmpq (% x) (% y))
+  (je @win)
+  (extract-fulltag x imm0)
+  (extract-fulltag y imm1)
+  (cmpb (% imm0.b) (% imm1.b))
+  (jne @lose)
+  (cmpb ($ x8664::fulltag-cons) (% imm0.b))
+  (je @cons)
+  (cmpb ($ x8664::fulltag-misc) (% imm0.b))
+  (je @misc)
+  @lose
+  (movq ($ nil) (% arg_z))
+  (single-value-return)
+  @win
+  (movq ($ t) (% arg_z))
+  (single-value-return)
+  @cons
+  ;; Check to see if the CARs are EQ.  If so, we can avoid saving
+  ;; context, and can just tail call ourselves on the CDRs.
+  (%car x temp0)
+  (%car y temp1)
+  (cmpq (% temp0) (% temp1))
+  (jne @recurse)
+  (%cdr x x)
+  (%cdr y y)
+  (jmp @tail)
+  @recurse
+  (save-simple-frame)
+  (pushq (@ x8664::cons.cdr (% x)))
+  (pushq (@ x8664::cons.cdr (% y)))
+  (movq (% temp0) (% x))
+  (movq (% temp1) (% y))
+  (:talign 4)
+  (call @top)
+  (recover-fn-from-rip)
+  (cmp-reg-to-nil arg_z)
+  (pop (% y))
+  (pop (% x))
+  (restore-simple-frame)         
+  (jnz @top)
+  (movl ($ nil) (% arg_z.l))
+  (single-value-return)
+  @misc
+  ;; Both objects are uvectors of some sort.  Try EQL; if that fails,
+  ;; call HAIRY-EQUAL.
+  (save-simple-frame)
+  (pushq (% x))
+  (pushq (% y))
+  (call-symbol eql 2)
+  (cmp-reg-to-nil arg_z)
+  (jne @won-with-eql)
+  (popq (% y))
+  (popq (% x))
+  (restore-simple-frame)
+  (jump-symbol hairy-equal 2)
+  @won-with-eql
+  (restore-simple-frame)                ; discards pushed args
+  (movl ($ t) (% arg_z.l))
+  (single-value-return))
+
+(defx86lapfunction %lisp-lowbyte-ref ((thing arg_z))
+  (box-fixnum thing arg_z)
+  (andl ($ '#xff) (%l arg_z))
+  (single-value-return))
+
+
+      
+
+
+
+
+
+
+
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-symbol.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-symbol.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-symbol.lisp	(revision 13309)
@@ -0,0 +1,166 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+(eval-when (:compile-toplevel :execute)
+  (require "X8664-ARCH")
+  (require "X86-LAPMACROS"))
+
+;;; This assumes that macros & special-operators
+;;; have something that's not FUNCTIONP in their
+;;; function-cells.  It also assumes that NIL
+;;; isn't a true symbol, but that NILSYM is.
+(defx86lapfunction %function ((sym arg_z))
+  (check-nargs 1)
+  (let ((symaddr temp0))
+    (movq ($ (+ (target-nil-value) x8664::nilsym-offset)) (% symaddr))
+    (cmp-reg-to-nil sym)
+    (cmovneq (% sym) (% symaddr))
+    (trap-unless-fulltag= symaddr x8664::fulltag-symbol)
+    (movq (% sym) (% arg_y))
+    (movq (@ x8664::symbol.fcell (% symaddr)) (% arg_z))
+    (extract-fulltag arg_z imm0)
+    (cmpb ($ x8664::fulltag-function) (%b imm0))
+    (je.pt @ok)
+    (uuo-error-udf (% arg_y))
+    @ok
+    (single-value-return)))
+
+;;; Traps unless sym is NIL or some other symbol.  If NIL, return
+;;; nilsym
+(defx86lapfunction %symbol->symptr ((sym arg_z))
+  (let ((tag imm0))
+    (movq ($ (+ (target-nil-value) x8664::nilsym-offset)) (% tag))
+    (cmp-reg-to-nil sym)
+    (cmoveq (% tag) (% sym))
+    (je :done)
+    (trap-unless-fulltag= sym x8664::fulltag-symbol)
+    :done
+    (single-value-return)))
+
+;;; If symptr is NILSYM, return NIL; else typecheck and return symptr
+(defx86lapfunction %symptr->symbol ((symptr arg_z))
+  (movw ($ (ash 1 x8664::fulltag-symbol)) (% imm0.w))
+  (btw (%w symptr) (% imm0.w))
+  (jb.pt @ok)
+  (uuo-error-reg-not-tag (% symptr) ($ x8664::fulltag-symbol))
+  @ok
+  (cmpq ($ (+ (target-nil-value) x8664::nilsym-offset)) (% symptr))
+  (sete (% imm0.b))
+  (negb (% imm0.b))
+  (andl ($ x8664::nilsym-offset) (% imm0.l))
+  (subq (% imm0) (% symptr))
+  (single-value-return))
+
+
+;;; Given something whose fulltag is FULLTAG-SYMBOL, return the
+;;; underlying uvector.  This function and its inverse would
+;;; be good candidates for inlining.
+(defx86lapfunction %symptr->symvector ((symptr arg_z))
+  (subb ($ (- x8664::fulltag-symbol x8664::fulltag-misc)) (% arg_z.b))
+  (single-value-return))
+
+(defx86lapfunction %symvector->symptr ((symbol-vector arg_z))
+  (addb ($ (- x8664::fulltag-symbol x8664::fulltag-misc)) (% arg_z.b))
+  (single-value-return))
+    
+(defx86lapfunction %symptr-value ((symptr arg_z))
+  (jmp-subprim .SPspecref))
+
+(defx86lapfunction %set-symptr-value ((symptr arg_y) (val arg_z))
+  (jmp-subprim .SPspecset))
+
+;;; This gets a tagged symbol as an argument.
+;;; If there's no thread-local binding, it should return
+;;; the underlying symbol vector as a first return value.
+(defx86lapfunction %symptr-binding-address ((symptr arg_z))
+  (movq (@ x8664::symbol.binding-index (% symptr)) (% arg_y))
+  (rcmp (% arg_y) (:rcontext x8664::tcr.tlb-limit))
+  (movq (:rcontext x8664::tcr.tlb-pointer) (% arg_x))
+  (jae @sym)
+  (cmpb ($ x8664::no-thread-local-binding-marker) (@ (% arg_x) (% arg_y)))
+  (je @sym)
+  (shl ($ x8664::word-shift) (% arg_y))
+  (push (% arg_x))
+  (push (% arg_y))
+  (set-nargs 2)
+  (lea (@ '2 (% rsp)) (% temp0))
+  (jmp-subprim .SPvalues)
+  @sym
+  (subb ($ (- x8664::fulltag-symbol x8664::fulltag-misc)) (% arg_z.b))
+  (push (% arg_z))
+  (pushq ($ '#.x8664::symptr.vcell))
+  (set-nargs 2)
+  (lea (@ '2 (% rsp)) (% temp0))
+  (jmp-subprim .SPvalues))
+
+(defx86lapfunction %tcr-binding-location ((tcr arg_y) (sym arg_z))
+  (movq (@ x8664::symbol.binding-index (% sym)) (% arg_x))
+  (movl ($ nil) (% arg_z.l))
+  (rcmp (% arg_x) (@ x8664::tcr.tlb-limit (% tcr)))
+  (movq (@ x8664::tcr.tlb-pointer (% tcr)) (% arg_y))
+  (jae @done)
+  (lea (@ (% arg_y) (% arg_x)) (% arg_y))
+  ;; We're little-endian, so the tag is at the EA with no
+  ;; displacement
+  (cmpb ($ x8664::subtag-no-thread-local-binding) (@ (% arg_y)))
+  (cmovneq (% arg_y) (% arg_z))
+  @done
+  (single-value-return))
+
+  
+(defx86lapfunction %pname-hash ((str arg_y) (len arg_z))
+  (let ((accum imm0)
+        (offset imm1))
+    (xorq (% offset) (% offset))
+    (xorq (% accum) (% accum))
+    (testq (% len) (% len))
+    (jz @done)
+    @loop8
+    (roll ($ 5) (%l accum))
+    (xorl (@ x8664::misc-data-offset (% str) (% offset) 4) (%l accum))
+    (addq ($ 1) (% offset))    
+    (subq ($ '1) (% len))
+    (jnz @loop8)
+    (shlq ($ 5) (% accum))
+    (shrq ($ (- 5 x8664::fixnumshift)) (% accum))
+    (movq (% accum) (% arg_z))
+    @done
+    (single-value-return)))
+
+(defx86lapfunction %string-hash ((start arg_x) (str arg_y) (len arg_z))
+  (let ((accum imm0)
+        (offset imm1))
+    (unbox-fixnum start offset)
+    (xorq (% accum) (% accum))
+    (testq (% len) (% len))
+    (jz @done)
+    @loop8
+    (roll ($ 5) (%l accum))
+    (xorl (@ x8664::misc-data-offset (% str) (% offset) 4) (%l accum))
+    (addq ($ 1) (% offset))    
+    (subq ($ '1) (% len))
+    (jnz @loop8)
+    (shlq ($ 5) (% accum))
+    (shrq ($ (- 5 x8664::fixnumshift)) (% accum))
+    (movq (% accum) (% arg_z))
+    @done
+    (single-value-return)))
+) ; #+x8664-target
Index: /branches/new-random/level-0/X86/x86-utils.lisp
===================================================================
--- /branches/new-random/level-0/X86/x86-utils.lisp	(revision 13309)
+++ /branches/new-random/level-0/X86/x86-utils.lisp	(revision 13309)
@@ -0,0 +1,548 @@
+; -*- Mode: Lisp; Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+#+x8664-target
+(progn
+
+(defx86lapfunction %address-of ((arg arg_z))
+  ;; %address-of a fixnum is a fixnum, just for spite.
+  ;; %address-of anything else is the address of that thing as an integer.
+  (testb ($ x8664::fixnummask) (%b arg))
+  (je @done)
+  (movq (% arg) (% imm0))
+  (jmp-subprim .SPmakeu64)
+  @done
+  (single-value-return))
+
+;;; "areas" are fixnum-tagged and, for the most part, so are their
+;;; contents.
+
+;;; The nilreg-relative global all-areas is a doubly-linked-list header
+;;; that describes nothing.  Its successor describes the current/active
+;;; dynamic heap.  Return a fixnum which "points to" that area, after
+;;; ensuring that the "active" pointers associated with the current thread's
+;;; stacks are correct.
+
+
+
+(defx86lapfunction %normalize-areas ()
+  (let ((address temp0)
+        (temp temp1))
+
+    ; update active pointer for tsp area.
+    (movq (:rcontext x8664::tcr.ts-area) (% address))
+    (movq (:rcontext x8664::tcr.save-tsp) (% temp))
+    (movq (% temp) (@ x8664::area.active (% address)))
+    
+    ;; Update active pointer for vsp area.
+    (movq (:rcontext x8664::tcr.vs-area) (% address))
+    (movq (% rsp) (@ x8664::area.active (% address)))
+
+    (ref-global all-areas arg_z)
+    (movq (@ x8664::area.succ (% arg_z)) (% arg_z))
+
+    (single-value-return)))
+
+(defx86lapfunction %active-dynamic-area ()
+  (ref-global all-areas arg_z)
+  (movq (@ x8664::area.succ (% arg_z)) (% arg_z))
+  (single-value-return))
+
+  
+(defx86lapfunction %object-in-stack-area-p ((object arg_y) (area arg_z))
+  (movq (@ x8664::area.active (% area)) (% imm0))
+  (movq (@ x8664::area.high (% area)) (% imm1))
+  (rcmp (% object) (% imm0))
+  (movq ($ nil) (% arg_z))
+  (movq ($ t) (% imm0))
+  (jb @done)
+  (rcmp (% object) (% imm1))
+  (cmovbq (% imm0) (% arg_z))
+  @done
+  (single-value-return))
+
+(defx86lapfunction %object-in-heap-area-p ((object arg_y) (area arg_z))
+  (rcmp (% object) (@ x8664::area.low (% area)))
+  (setae (%b imm0))
+  (rcmp (% object) (@ x8664::area.low (% area)))
+  (setb (%b imm1))
+  (andb (% imm1.b) (% imm0.b))
+  (andl ($ x8664::t-offset) (%l imm0))
+  (lea (@ (target-nil-value) (% imm0)) (% arg_z))
+  (single-value-return))
+
+
+
+
+(defx86lapfunction walk-static-area ((a arg_y) (f arg_z))
+  (let ((fun save0)
+        (obj save1)
+        (limit save2))
+    (save-simple-frame)
+    (push (% fun))
+    (push (% obj))
+    (push (% limit))
+    (movq (% f) (% fun))
+    (movq (@ x8664::area.active (% a)) (% limit))
+    (movq (@ x8664::area.low (% a)) (% obj))
+    (jmp @test)
+    @loop
+    (movb (@ (% obj)) (% imm0.b))
+    (andb ($ x8664::fulltagmask) (% imm0.b))
+    (cmpb ($ x8664::fulltag-nodeheader-0) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-nodeheader-1) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-immheader-0) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-immheader-2) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-immheader-1) (% imm0.b))
+    (jne @cons)
+    @misc
+    (lea (@ x8664::fulltag-misc (% obj)) (% obj))
+    (movq (% obj) (% arg_z))
+    (set-nargs 1)
+    (:talign 4)
+    (call (% fun))
+    (recover-fn-from-rip)
+    (getvheader obj imm1)
+    (movb (% imm1.b) (% imm0.b))
+    (andb ($ x8664::fulltagmask) (% imm0.b))
+    (cmpb ($ x8664::fulltag-nodeheader-0) (% imm0.b))
+    (je @64)
+    (cmpb ($ x8664::fulltag-nodeheader-1) (% imm0.b))
+    (je @64)
+    (cmpb ($ x8664::ivector-class-64-bit) (% imm0.b))
+    (jne @not64)
+    @64
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (shlq ($ x8664::word-shift) (% imm1))
+    (jmp @uvector-next)
+    @not64
+    (cmpb ($ x8664::ivector-class-32-bit) (% imm0.b))
+    (jne @not32)
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (shlq ($ 2) (% imm1))
+    (jmp @uvector-next)
+    @not32
+    (cmpb ($ (- x8664::subtag-bit-vector 256)) (% imm1.b))
+    (jne @not-bit)
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (addq ($ 7) (% imm1))
+    (shrq ($ 3) (% imm1))
+    (jmp @uvector-next)
+    @not-bit
+    (rcmpb (% imm1.b) ($ (- x8664::min-8-bit-ivector-subtag 256)))
+    (jb @16)
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (jmp @uvector-next)
+    @16
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (shlq ($ 1) (% imm1))
+    (jmp @uvector-next)
+    @cons
+    (addq ($ x8664::fulltag-cons) (% obj))
+    (movq (% obj) (% arg_z))
+    (set-nargs 1)
+    (:talign 4)
+    (call (% fun))
+    (recover-fn-from-rip)
+    (addq ($ (- x8664::cons.size x8664::fulltag-cons)) (% obj))
+    (jmp @test)
+    ;; size of OBJ in bytes (without header or alignment padding)
+    ;; in imm1.
+    @uvector-next
+    (addq ($ (+ x8664::node-size (1- x8664::dnode-size))) (% imm1))
+    (andb ($ (lognot (1- x8664::dnode-size))) (% imm1.b))
+    (lea (@ (- x8664::fulltag-misc) (% obj) (% imm1)) (% obj))
+    @test
+    (cmpq (% limit) (% obj))
+    (jb @loop)
+    (pop (% limit))
+    (pop (% obj))
+    (pop (% fun))
+    (movl ($ (target-nil-value)) (% arg_z.l))
+    (restore-simple-frame)
+    (single-value-return)))
+
+
+
+;;; This walks the active "dynamic" area.  Objects might be moving around
+;;; while we're doing this, so we have to be a lot more careful than we 
+;;; are when walking a static area.
+;;; There are a couple of approaches to termination:
+;;;  a) Allocate a "sentinel" cons, and terminate when we run into it.
+;;;  b) Check the area limit (which is changing if we're consing) and
+;;;     terminate when we hit it.
+;;; (b) loses if the function conses.  (a) conses.  I can't think of anything
+;;; better than (a).
+;;; This, of course, assumes that any GC we're doing does in-place compaction
+;;; (or at least preserves the relative order of objects in the heap.)
+
+(defx86lapfunction %walk-dynamic-area ((a arg_y) (f arg_z))
+  (let ((fun save0)
+        (obj save1)
+        (limit save2))
+    (save-simple-frame)
+    (push (% fun))
+    (push (% obj))
+    (push (% limit))
+    (movq (% f) (% fun))
+    (ref-global tenured-area a)
+    (movq (@ x8664::area.low (% a)) (% obj))
+    (subq ($ (- x8664::cons.size x8664::fulltag-cons))
+          (:rcontext x8664::tcr.save-allocptr))
+    (movq (:rcontext x8664::tcr.save-allocptr) (% allocptr))
+    (cmpq (:rcontext x8664::tcr.save-allocbase) (% allocptr))
+    (ja @ok)
+    (uuo-alloc)
+    @ok
+    (andb ($ (lognot x8664::fulltagmask))
+          (:rcontext x8664::tcr.save-allocptr))
+    (movq (% allocptr) (% limit))
+    (jmp @test)
+    @loop
+    (movb (@ (% obj)) (% imm0.b))
+    (andb ($ x8664::fulltagmask) (% imm0.b))
+    (cmpb ($ x8664::fulltag-nodeheader-0) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-nodeheader-1) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-immheader-0) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-immheader-2) (% imm0.b))
+    (je @misc)
+    (cmpb ($ x8664::fulltag-immheader-1) (% imm0.b))
+    (jne @cons)
+    @misc
+    (lea (@ x8664::fulltag-misc (% obj)) (% obj))
+    (movq (% obj) (% arg_z))
+    (set-nargs 1)
+    (:talign 4)
+    (call (% fun))
+    (recover-fn-from-rip)
+    (getvheader obj imm1)
+    (movb (% imm1.b) (% imm0.b))
+    (andb ($ x8664::fulltagmask) (% imm0.b))
+    (cmpb ($ x8664::fulltag-nodeheader-0) (% imm0.b))
+    (je @64)
+    (cmpb ($ x8664::fulltag-nodeheader-1) (% imm0.b))
+    (je @64)
+    (cmpb ($ x8664::ivector-class-64-bit) (% imm0.b))
+    (jne @not64)
+    @64
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (shlq ($ x8664::word-shift) (% imm1))
+    (jmp @uvector-next)
+    @not64
+    (cmpb ($ x8664::ivector-class-32-bit) (% imm0.b))
+    (jne @not32)
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (shlq ($ 2) (% imm1))
+    (jmp @uvector-next)
+    @not32
+    (cmpb ($ (- x8664::subtag-bit-vector 256)) (% imm1.b))
+    (jne @not-bit)
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (addq ($ 7) (% imm1))
+    (shrq ($ 3) (% imm1))
+    (jmp @uvector-next)
+    @not-bit
+    (rcmpb (% imm1.b) ($ (- x8664::min-8-bit-ivector-subtag 256)))
+    (jb @16)
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (jmp @uvector-next)
+    @16
+    (shrq ($ x8664::num-subtag-bits) (% imm1))
+    (shlq ($ 1) (% imm1))
+    (jmp @uvector-next)
+    @cons
+    (addq ($ x8664::fulltag-cons) (% obj))
+    (cmpq (% obj) (% limit))
+    (movq (% obj) (% arg_z))
+    (je @done)
+    (set-nargs 1)
+    (:talign 4)
+    (call (% fun))
+    (recover-fn-from-rip)
+    (addq ($ (- x8664::cons.size x8664::fulltag-cons)) (% obj))
+    (jmp @test)
+    ;; size of OBJ in bytes (without header or alignment padding)
+    ;; in imm1.
+    @uvector-next
+    (addq ($ (+ x8664::node-size (1- x8664::dnode-size))) (% imm1))
+    (andb ($ (lognot (1- x8664::dnode-size))) (% imm1.b))
+    (lea (@ (- x8664::fulltag-misc) (% obj) (% imm1)) (% obj))
+    @test
+    (cmpq (% limit) (% obj))
+    (jb @loop)
+    @done
+    (pop (% limit))
+    (pop (% obj))
+    (pop (% fun))
+    (movl ($ (target-nil-value)) (% arg_z.l))
+    (restore-simple-frame)
+    (single-value-return)))
+
+(defun walk-dynamic-area (area func)
+  (with-other-threads-suspended
+      (%walk-dynamic-area area func)))
+
+
+
+(defx86lapfunction %class-of-instance ((i arg_z))
+  (svref i instance.class-wrapper arg_z)
+  (svref arg_z %wrapper-class arg_z)
+  (single-value-return))
+
+(defx86lapfunction class-of ((x arg_z))
+  (check-nargs 1)
+  (movw ($ (logior (ash 1 x8664::tag-list)
+                   (ash 1 x8664::tag-imm-1)))
+        (%w imm1))
+  (extract-lisptag x imm0)
+  (btw (% imm0.w) (% imm1.w))
+  (cmovbl (% arg_z.l) (% imm0.l))
+  (movq (@ '*class-table* (% fn)) (% temp1))
+  (cmpb ($ x8664::tag-misc) (% imm0.b))
+  (jne @have-tag)
+  (extract-subtag x imm0)
+  @have-tag
+  (movq (@ x8664::symbol.vcell (% temp1)) (% temp1))
+  (movzbl (% imm0.b) (% imm0.l))
+  (movq (@ x8664::misc-data-offset (% temp1) (% imm0) 8) (% temp0))
+  (cmpb ($ x8664::fulltag-nil) (%b temp0))
+  (je @bad)
+  (extract-fulltag temp0 imm0)
+  (cmpb ($ x8664::fulltag-function) (%b imm0))
+  (jne @ret)
+  (set-nargs 1)
+  (jmp (% temp0))
+  @bad
+  (load-constant no-class-error fname)
+  (set-nargs 1)
+  (jmp  (@ x8664::symbol.fcell (% fname)))
+  @ret
+  (movq (% temp0) (% arg_z))  ; return frob from table
+  (single-value-return))
+
+(defx86lapfunction full-gccount ()
+  (ref-global tenured-area arg_z)
+  (testq (% arg_z) (% arg_z))
+  (cmoveq (@ (+ (target-nil-value) (x8664::%kernel-global 'gc-count))) (% arg_z))
+  (cmovneq (@ x8664::area.gc-count (% arg_z)) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction gc ()
+  (check-nargs 0)
+  (movq ($ arch::gc-trap-function-gc) (% imm0))
+  (uuo-gc-trap)
+  (movq ($ nil) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction egc ((arg arg_z))
+  "Enable the EGC if arg is non-nil, disables the EGC otherwise. Return
+the previous enabled status. Although this function is thread-safe (in
+the sense that calls to it are serialized), it doesn't make a whole lot
+of sense to be turning the EGC on and off from multiple threads ..."
+  (check-nargs 1)
+  (clrq imm1)
+  (cmp-reg-to-nil arg)
+  (setne (% imm1.b))
+  (movq ($ arch::gc-trap-function-egc-control) (% imm0))
+  (uuo-gc-trap)
+  (single-value-return))
+
+
+
+
+(defx86lapfunction %configure-egc ((e0size arg_x)
+				   (e1size arg_y)
+				   (e2size arg_z))
+  (check-nargs 3)
+  (movq ($ arch::gc-trap-function-configure-egc) (% imm0))
+  (uuo-gc-trap)
+  (single-value-return))
+
+(defx86lapfunction purify ()
+  (check-nargs 0)
+  (movq ($ arch::gc-trap-function-purify) (% imm0))
+  (uuo-gc-trap)
+  (movq ($ nil) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction impurify ()
+  (check-nargs 0)
+  (movq ($ arch::gc-trap-function-impurify) (% imm0))
+  (uuo-gc-trap)
+  (movq ($ nil) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction lisp-heap-gc-threshold ()
+  "Return the value of the kernel variable that specifies the amount
+of free space to leave in the heap after full GC."
+  (check-nargs 0)
+  (movq ($ arch::gc-trap-function-get-lisp-heap-threshold) (% imm0))
+  (uuo-gc-trap)
+  #+x8632-target
+  (jmp-subprim .SPmakeu32)
+  #+x8664-target
+  (jmp-subprim .SPmakeu64))
+
+(defx86lapfunction set-lisp-heap-gc-threshold ((new arg_z))
+  "Set the value of the kernel variable that specifies the amount of free
+space to leave in the heap after full GC to new-value, which should be a
+non-negative fixnum. Returns the value of that kernel variable (which may
+be somewhat larger than what was specified)."
+  (check-nargs 1)
+  (save-simple-frame)
+  (call-subprim .SPgetu64)
+  (movq (% imm0) (% imm1))
+  (movq ($ arch::gc-trap-function-set-lisp-heap-threshold) (% imm0))
+  (uuo-gc-trap)
+  (restore-simple-frame)
+  (jmp-subprim .SPmakeu64))
+
+
+(defx86lapfunction use-lisp-heap-gc-threshold ()
+  "Try to grow or shrink lisp's heap space, so that the free space is (approximately) equal to the current heap threshold. Return NIL"
+  (check-nargs 0) 
+  (movq ($ arch::gc-trap-function-use-lisp-heap-threshold) (% imm0))
+  (uuo-gc-trap)
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (single-value-return))
+
+(defx86lapfunction freeze ()
+  "Do a full GC, then consider all heap-allocated objects which survive to be non-relocatable."
+  (movl ($ arch::gc-trap-function-freeze) (% imm0.l))
+  (uuo-gc-trap)
+  (jmp-subprim .SPmakeu64))
+
+(defx86lapfunction flash-freeze ()
+  "Like FREEZE, without the GC."
+  (movl ($ arch::gc-trap-function-flash-freeze) (% imm0.l))
+  (uuo-gc-trap)
+  (jmp-subprim .SPmakeu64))
+
+(defx86lapfunction %watch ((thing arg_z))
+  (check-nargs 1)
+  (movl ($ arch::watch-trap-function-watch) (%l imm0))
+  (uuo-watch-trap)
+  (single-value-return))
+
+(defx86lapfunction %unwatch ((watched arg_y) (new arg_z))
+  (check-nargs 2)
+  (movl ($ arch::watch-trap-function-unwatch) (%l imm0))
+  (uuo-watch-trap)
+  (single-value-return))
+
+(defx86lapfunction %allocate-list ((initial-element arg_y) (nconses arg_z))
+  (check-nargs 2)
+  (save-simple-frame)
+  (ud2a)
+  (:byte 10)
+  (push (% arg_z))
+  (push (% allocptr))
+  (set-nargs 2)
+  (jmp-subprim .SPnvalret))
+
+
+(defx86lapfunction %ensure-static-conses ()
+  (check-nargs 0)
+  (movl ($ arch::gc-trap-function-ensure-static-conses) (% imm0.l))
+  (uuo-gc-trap)
+  (movl ($ (target-nil-value)) (% arg_z.l))
+  (single-value-return))
+
+
+
+;;; offset is a fixnum, one of the x8664::kernel-import-xxx constants.
+;;; Returns that kernel import, a fixnum.
+(defx86lapfunction %kernel-import ((offset arg_z))
+  (ref-global kernel-imports imm0)
+  (unbox-fixnum arg_z imm1)
+  (movq (@ (% imm0) (% imm1)) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %get-unboxed-ptr ((macptr arg_z))
+  (macptr-ptr arg_z imm0)
+  (movq (@ (% imm0)) (% arg_z))
+  (single-value-return))
+
+
+(defx86lapfunction %revive-macptr ((p arg_z))
+  (movb ($ x8664::subtag-macptr) (@ x8664::misc-subtag-offset (% p)))
+  (single-value-return))
+
+(defx86lapfunction %macptr-type ((p arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= p x8664::subtag-macptr)
+  (svref p x8664::macptr.type-cell imm0)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+  
+(defx86lapfunction %macptr-domain ((p arg_z))
+  (check-nargs 1)
+  (trap-unless-typecode= p x8664::subtag-macptr)
+  (svref p x8664::macptr.domain-cell imm0)
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+(defx86lapfunction %set-macptr-type ((p arg_y) (new arg_z))
+  (check-nargs 2)
+  (unbox-fixnum new imm1)
+  (trap-unless-typecode= p x8664::subtag-macptr)
+  (svset p x8664::macptr.type-cell imm1)
+  (single-value-return))
+
+(defx86lapfunction %set-macptr-domain ((p arg_y) (new arg_z))
+  (check-nargs 2)
+  (unbox-fixnum new imm1)
+  (trap-unless-typecode= p x8664::subtag-macptr)
+  (svset p x8664::macptr.domain-cell imm1)
+  (single-value-return))
+
+(defx86lapfunction true ()
+  (pop (% ra0))
+  (subq ($ '3) (% nargs.q))
+  (leaq (@ '2 (% rsp) (% nargs.q)) (% imm0))
+  (cmovaq (% imm0) (% rsp))
+  (movl ($ (target-t-value)) (%l arg_z))
+  (push (% ra0))
+  (single-value-return))
+
+(defx86lapfunction false ()
+  (pop (% ra0))
+  (subq ($ '3) (% nargs.q))
+  (leaq (@ '2 (% rsp) (% nargs.q)) (% imm0))
+  (cmovaq (% imm0) (% rsp))
+  (movl ($ (target-nil-value)) (%l arg_z))
+  (push (% ra0))
+  (single-value-return))
+
+
+
+;;; end
+) ; #+x8664-target
Index: /branches/new-random/level-0/l0-aprims.lisp
===================================================================
--- /branches/new-random/level-0/l0-aprims.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-aprims.lisp	(revision 13309)
@@ -0,0 +1,223 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+; l0-aprims.lisp
+
+;;; This weak list is used to track semaphores as well as locks.
+(defvar %system-locks% nil)
+
+
+(defun record-system-lock (l)
+  (atomic-push-uvector-cell %system-locks% population.data l)
+  l)
+
+;;; This has to run very early in the initial thread.
+(defun %revive-system-locks ()
+  (dolist (s (population-data %system-locks%))
+    (%revive-macptr s)
+    (%setf-macptr s
+                  (case (uvref s target::xmacptr.flags-cell)
+                    (#.$flags_DisposeRecursiveLock
+                     (ff-call
+                      (%kernel-import target::kernel-import-new-recursive-lock)
+                      :address))
+                    (#.$flags_DisposeRwlock
+                     (ff-call
+                      (%kernel-import target::kernel-import-rwlock-new)
+                      :address))
+		    (#.$flags_DisposeSemaphore
+		     (ff-call
+		      (%kernel-import target::kernel-import-new-semaphore)
+		      :signed-fullword 0
+		      :address))))
+    (set-%gcable-macptrs% s)))
+
+(dolist (p %all-packages%)
+  (setf (pkg.lock p) (make-read-write-lock)))
+
+(defparameter %all-packages-lock% nil)
+
+
+
+(defun %cstr-pointer (string pointer &optional (nul-terminated t))
+  (if (typep string 'simple-base-string)
+    (locally (declare (simple-base-string string)
+                      (optimize (speed 3) (safety 0)))
+      (let* ((n (length string)))
+        (declare (fixnum n))
+        (dotimes (i n)
+          (setf (%get-unsigned-byte pointer i)
+                (let* ((code (%scharcode string i)))
+                  (declare (type (mod #x110000) code))
+                  (if (< code 256)
+                    code
+                    (char-code #\Sub)))))
+        (when nul-terminated
+          (setf (%get-byte pointer n) 0)))
+      nil)
+    (%cstr-segment-pointer string pointer 0 (length string) nul-terminated)))
+
+(defun %cstr-segment-pointer (string pointer start end &optional (nul-terminated t))
+  (declare (fixnum start end))
+  (let* ((n (- end start)))
+    (multiple-value-bind (s o) (dereference-base-string string)
+      (declare (fixnum o))
+      (do* ((i 0 (1+ i))
+            (o (the fixnum (+ o start)) (1+ o)))
+           ((= i n))
+        (declare (fixnum i o))
+        (setf (%get-unsigned-byte pointer i)
+              (let* ((code (char-code (schar s o))))
+                (declare (type (mod #x110000) code))
+                (if (< code 256)
+                  code
+                  (char-code #\Sub))))))
+    (when nul-terminated
+      (setf (%get-byte pointer n) 0))
+    nil))
+
+(defun string (thing)
+  "Coerces X into a string. If X is a string, X is returned. If X is a
+   symbol, X's pname is returned. If X is a character then a one element
+   string containing that character is returned. If X cannot be coerced
+   into a string, an error occurs."
+  (etypecase thing
+    (string thing)
+    (symbol (symbol-name thing))
+    (character (make-string 1 :initial-element thing))))
+
+
+(defun dereference-base-string (s)
+  (multiple-value-bind (vector offset) (array-data-and-offset s)
+    (unless (typep vector 'simple-base-string) (report-bad-arg s 'base-string))
+    (values vector offset (length s))))
+
+(defun make-gcable-macptr (flags)
+  (let ((v (%alloc-misc target::xmacptr.element-count target::subtag-macptr)))
+    (setf (uvref v target::xmacptr.address-cell) 0) ; ?? yup.
+    (setf (uvref v target::xmacptr.flags-cell) flags)
+    (set-%gcable-macptrs% v)
+    v))
+
+(defun %make-recursive-lock-ptr ()
+  (record-system-lock
+   (%setf-macptr
+    (make-gcable-macptr $flags_DisposeRecursiveLock)
+    (ff-call (%kernel-import target::kernel-import-new-recursive-lock)
+             :address))))
+
+(defun %make-rwlock-ptr ()
+  (record-system-lock
+   (%setf-macptr
+    (make-gcable-macptr $flags_DisposeRwLock)
+    (ff-call (%kernel-import target::kernel-import-rwlock-new)
+             :address))))
+  
+(defun make-recursive-lock ()
+  (make-lock nil))
+
+(defun %make-lock (pointer name)
+  (gvector :lock pointer 'recursive-lock 0 name nil nil))
+
+(defun make-lock (&optional name)
+  "Create and return a lock object, which can be used for synchronization
+between threads."
+  (%make-lock (%make-recursive-lock-ptr) name))
+
+(defun lock-name (lock)
+  (uvref (require-type lock 'lock) target::lock.name-cell))
+
+(defun recursive-lock-ptr (r)
+  (if (and (eq target::subtag-lock (typecode r))
+           (eq (%svref r target::lock.kind-cell) 'recursive-lock))
+    (%svref r target::lock._value-cell)
+    (report-bad-arg r 'recursive-lock)))
+
+(defun recursive-lock-whostate (r)
+  (if (and (eq target::subtag-lock (typecode r))
+           (eq (%svref r target::lock.kind-cell) 'recursive-lock))
+    (or (%svref r target::lock.whostate-cell)
+        (setf (%svref r target::lock.whostate-cell)
+              (%lock-whostate-string "Lock wait" r)))
+    (report-bad-arg r 'recursive-lock)))
+
+
+(defun read-write-lock-ptr (rw)
+  (if (and (eq target::subtag-lock (typecode rw))
+           (eq (%svref rw target::lock.kind-cell) 'read-write-lock))
+    (%svref rw target::lock._value-cell)
+    (report-bad-arg rw 'read-write-lock)))
+
+(defun make-read-write-lock ()
+  "Create and return a read-write lock, which can be used for
+synchronization between threads."
+  (gvector :lock (%make-rwlock-ptr) 'read-write-lock 0 nil nil nil))
+
+(defun rwlock-read-whostate (rw)
+  (if (and (eq target::subtag-lock (typecode rw))
+           (eq (%svref rw target::lock.kind-cell) 'read-write-lock))
+    (or (%svref rw target::lock.whostate-cell)
+        (setf (%svref rw target::lock.whostate-cell)
+              (%lock-whostate-string "Read lock wait" rw)))
+    (report-bad-arg rw 'read-write-lock)))
+
+(defun rwlock-write-whostate (rw)
+  (if (and (eq target::subtag-lock (typecode rw))
+           (eq (%svref rw target::lock.kind-cell) 'read-write-lock))
+    (or (%svref rw target::lock.whostate-2-cell)
+        (setf (%svref rw target::lock.whostate-2-cell)
+              (%lock-whostate-string "Write lock wait" rw)))
+    (report-bad-arg rw 'read-write-lock)))
+  
+
+(defun %make-semaphore-ptr ()
+  (let* ((p (ff-call (%kernel-import target::kernel-import-new-semaphore)
+	     :signed-fullword 0
+             :address)))
+    (if (%null-ptr-p p)
+      (error "Can't create semaphore.")
+      (record-system-lock
+       (%setf-macptr
+	(make-gcable-macptr $flags_DisposeSemaphore)
+	p)))))
+
+(defun make-semaphore ()
+  "Create and return a semaphore, which can be used for synchronization
+between threads."
+  (%istruct 'semaphore (%make-semaphore-ptr)))
+
+(defun semaphorep (x)
+  (istruct-typep x 'semaphore))
+
+(setf (type-predicate 'semaphore) 'semaphorep)
+
+(defun make-list (size &key initial-element)
+  "Constructs a list with size elements each set to value"
+  (unless (and (typep size 'fixnum)
+               (>= (the fixnum size) 0))
+    (report-bad-arg size '(and fixnum unsigned-byte)))
+  (locally (declare (fixnum size))
+    (if (>= size (ash 1 16))
+      (values (%allocate-list initial-element size))
+      (do* ((result '() (cons initial-element result)))
+           ((zerop size) result)
+        (decf size)))))
+
+; end
Index: /branches/new-random/level-0/l0-array.lisp
===================================================================
--- /branches/new-random/level-0/l0-array.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-array.lisp	(revision 13309)
@@ -0,0 +1,852 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+
+
+; Return T if array or vector header, NIL if (simple-array * *), else
+; error.
+
+(defun %array-is-header (array)
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (or (= typecode target::subtag-arrayH)
+          (= typecode target::subtag-vectorH)))))
+
+(defun %set-fill-pointer (vectorh new)
+  (setf (%svref vectorh target::vectorh.logsize-cell) new))
+
+(defun %array-header-subtype (header)
+  (the fixnum 
+    (ldb target::arrayH.flags-cell-subtag-byte (the fixnum (%svref header target::arrayH.flags-cell)))))
+
+(defun array-element-subtype (array)
+  (if (%array-is-header array)
+    (%array-header-subtype array)
+    (typecode array)))
+  
+#+ppc32-target
+(defconstant ppc32::*immheader-array-types*
+  '#(short-float
+     (unsigned-byte 32)
+     (signed-byte 32)
+     fixnum
+     character
+     (unsigned-byte 8)
+     (signed-byte 8)
+     unused
+     (unsigned-byte 16)
+     (signed-byte 16)
+     double-float
+     bit))
+
+#+ppc64-target
+(defconstant ppc64::*immheader-array-types*
+  '#(unused
+     unused
+     unused
+     unused
+     (signed-byte 8)
+     (signed-byte 16)
+     (signed-byte 32)
+     (signed-byte 64)
+     (unsigned-byte 8)
+     (unsigned-byte 16)
+     (unsigned-byte 32)
+     (unsigned-byte 64)
+     unused
+     unused
+     short-float
+     fixnum
+     unused
+     unused
+     unused
+     double-float
+     unused
+     unused
+     character
+     unused
+     unused
+     unused
+     unused
+     unused
+     unused
+     bit
+     unused
+     unused))
+
+#+x8632-target
+(defconstant x8632::*immheader-array-types*
+  '#(short-float
+     (unsigned-byte 32)
+     (signed-byte 32)
+     fixnum
+     character
+     (unsigned-byte 8)
+     (signed-byte 8)
+     unused
+     (unsigned-byte 16)
+     (signed-byte 16)
+     double-float
+     bit))
+
+#+x8664-target
+(progn
+(defconstant x8664::*immheader-0-array-types*
+  ;; ivector-class-other-bit
+  #(unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    (signed-byte 16)
+    (unsigned-byte 16)
+    character
+    (signed-byte 8)
+    (unsigned-byte 8)
+    bit
+    ))
+
+(defconstant x8664::*immheader-1-array-types*
+    ;; ivector-class-32-bit
+  #(
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    character
+    (signed-byte 32)
+    (unsigned-byte 32)
+    single-float))
+
+(defconstant x8664::*immheader-2-array-types*
+  ;; ivector-class-64-bit
+  #(
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    unused
+    fixnum
+    (signed-byte 64)
+    (unsigned-byte 64)
+    double-float))
+    
+)
+
+
+(defun array-element-type (array)
+  "Return the type of the elements of the array"
+  (let* ((subtag (if (%array-is-header array)
+                   (%array-header-subtype array)
+                   (typecode array))))
+    (declare (fixnum subtag))
+    (if (= subtag target::subtag-simple-vector)
+      t                                 ; only node CL array type
+      #+ppc-target
+      (svref target::*immheader-array-types*
+             #+ppc32-target
+             (ash (the fixnum (- subtag ppc32::min-cl-ivector-subtag)) -3)
+             #+ppc64-target
+             (ash (the fixnum (logand subtag #x7f)) (- ppc64::nlowtagbits)))
+      #+x8632-target
+      (svref x8632::*immheader-array-types*
+	     (ash (the fixnum (- subtag x8632::min-cl-ivector-subtag))
+		  (- x8632::ntagbits)))
+      #+x8664-target
+      (let* ((class (logand subtag x8664::fulltagmask))
+             (idx (ash subtag (- x8664::ntagbits))))
+        (declare (fixnum class idx))
+        (cond ((= class x8664::ivector-class-64-bit)
+               (%svref x8664::*immheader-2-array-types* idx))
+              ((= class x8664::ivector-class-32-bit)
+               (%svref x8664::*immheader-1-array-types* idx))
+              (t
+               (%svref x8664::*immheader-0-array-types* idx))))
+      )))
+
+
+
+(defun adjustable-array-p (array)
+  "Return T if (ADJUST-ARRAY ARRAY...) would return an array identical
+   to the argument, this happens for complex arrays."
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (if (or (= typecode target::subtag-arrayH)
+              (= typecode target::subtag-vectorH))
+        (logbitp $arh_adjp_bit (the fixnum (%svref array target::arrayH.flags-cell)))))))
+
+(defun array-displacement (array)
+  "Return the values of :DISPLACED-TO and :DISPLACED-INDEX-offset
+   options to MAKE-ARRAY, or NIL and 0 if not a displaced array."
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (if (and (<= typecode target::subtag-vectorH)
+	       (logbitp $arh_exp_disp_bit
+			(the fixnum (%svref array target::arrayH.flags-cell))))
+	  (values (%svref array target::arrayH.data-vector-cell)
+		  (%svref array target::arrayH.displacement-cell))
+	  (values nil 0)))))
+
+(defun array-data-and-offset (array)
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (if (<= typecode target::subtag-vectorH)
+        (%array-header-data-and-offset array)
+        (values array 0)))))
+
+(defun array-data-offset-subtype (array)
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (if (<= typecode target::subtag-vectorH)
+        (do* ((header array data)
+              (offset (%svref header target::arrayH.displacement-cell)
+                      (+ offset 
+                         (the fixnum 
+                              (%svref header target::arrayH.displacement-cell))))
+              (data (%svref header target::arrayH.data-vector-cell)
+                    (%svref header target::arrayH.data-vector-cell)))
+             ((> (the fixnum (typecode data)) target::subtag-vectorH)
+              (values data offset (typecode data)))
+          (declare (fixnum offset)))
+        (values array 0 typecode)))))
+  
+
+(defun array-has-fill-pointer-p (array)
+  "Return T if the given ARRAY has a fill pointer, or NIL otherwise."
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (>= typecode target::min-array-subtag)
+      (and (= typecode target::subtag-vectorH)
+             (logbitp $arh_fill_bit (the fixnum (%svref array target::vectorH.flags-cell))))
+      (report-bad-arg array 'array))))
+
+
+(defun fill-pointer (array)
+  "Return the FILL-POINTER of the given VECTOR."
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (and (= typecode target::subtag-vectorH)
+             (logbitp $arh_fill_bit (the fixnum (%svref array target::vectorH.flags-cell))))
+      (%svref array target::vectorH.logsize-cell)
+      (report-bad-arg array '(and array (satisfies array-has-fill-pointer-p))))))
+
+(defun set-fill-pointer (array value)
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (and (= typecode target::subtag-vectorH)
+             (logbitp $arh_fill_bit (the fixnum (%svref array target::vectorH.flags-cell))))
+      (let* ((vlen (%svref array target::vectorH.physsize-cell)))
+        (declare (fixnum vlen))
+        (if (eq value t)
+          (setq value vlen)
+          (unless (and (fixnump value)
+                     (>= (the fixnum value) 0)
+                     (<= (the fixnum value) vlen))
+            (%err-disp $XARROOB value array)))
+        (setf (%svref array target::vectorH.logsize-cell) value))
+      (%err-disp $XNOFILLPTR array))))
+
+(eval-when (:compile-toplevel)
+  (assert (eql target::vectorH.physsize-cell target::arrayH.physsize-cell)))
+
+(defun array-total-size (array)
+  "Return the total number of elements in the Array."
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (if (or (= typecode target::subtag-arrayH)
+              (= typecode target::subtag-vectorH))
+        (%svref array target::vectorH.physsize-cell)
+        (uvsize array)))))
+
+      
+
+(defun array-dimension (array axis-number)
+  "Return the length of dimension AXIS-NUMBER of ARRAY."
+  (unless (typep axis-number 'fixnum) (report-bad-arg axis-number 'fixnum))
+  (locally
+    (declare (fixnum axis-number))
+    (let* ((typecode (typecode array)))
+      (declare (fixnum typecode))
+      (if (< typecode target::min-array-subtag)
+        (report-bad-arg array 'array)
+        (if (= typecode target::subtag-arrayH)
+          (let* ((rank (%svref array target::arrayH.rank-cell)))
+            (declare (fixnum rank))
+            (unless (and (>= axis-number 0)
+                         (< axis-number rank))
+              (%err-disp $XNDIMS array axis-number))
+            (%svref array (the fixnum (+ target::arrayH.dim0-cell axis-number))))
+          (if (neq axis-number 0)
+            (%err-disp $XNDIMS array axis-number)
+            (if (= typecode target::subtag-vectorH)
+              (%svref array target::vectorH.physsize-cell)
+              (uvsize array))))))))
+
+(defun array-dimensions (array)
+  "Return a list whose elements are the dimensions of the array"
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (if (= typecode target::subtag-arrayH)
+        (let* ((rank (%svref array target::arrayH.rank-cell))
+               (dims ()))
+          (declare (fixnum rank))        
+          (do* ((i (1- rank) (1- i)))
+               ((< i 0) dims)
+            (declare (fixnum i))
+            (push (%svref array (the fixnum (+ target::arrayH.dim0-cell i))) dims)))
+        (list (if (= typecode target::subtag-vectorH)
+                (%svref array target::vectorH.physsize-cell)
+                (uvsize array)))))))
+
+
+(defun array-rank (array)
+  "Return the number of dimensions of ARRAY."
+  (let* ((typecode (typecode array)))
+    (declare (fixnum typecode))
+    (if (< typecode target::min-array-subtag)
+      (report-bad-arg array 'array)
+      (if (= typecode target::subtag-arrayH)
+        (%svref array target::arrayH.rank-cell)
+        1))))
+
+(defun vector-push (elt vector)
+  "Attempt to set the element of ARRAY designated by its fill pointer
+   to NEW-EL, and increment the fill pointer by one. If the fill pointer is
+   too large, NIL is returned, otherwise the index of the pushed element is
+   returned."
+  (let* ((fill (fill-pointer vector))
+         (len (%svref vector target::vectorH.physsize-cell)))
+    (declare (fixnum fill len))
+    (when (< fill len)
+      (multiple-value-bind (data offset) (%array-header-data-and-offset vector)
+        (declare (fixnum offset))
+        (setf (%svref vector target::vectorH.logsize-cell) (the fixnum (1+ fill))
+              (uvref data (the fixnum (+ fill offset))) elt)
+        fill))))
+
+;;; Implement some of the guts of REPLACE, where the source and target
+;;; sequence have the same type (and we might be able to BLT things
+;;; around more quickly because of that.)
+;;; Both TARGET and SOURCE are (SIMPLE-ARRAY (*) *), and all of the
+;;; indices are fixnums and in bounds.
+(defun %uvector-replace (target target-start source source-start n typecode)
+  (declare (fixnum target-start n source-start n typecode)
+           (optimize (speed 3) (safety 0)))
+  (ecase typecode
+    (#.target::subtag-simple-vector
+     (if (and (eq source target)
+              (> target-start source-start))
+       (do* ((i 0 (1+ i))
+             (source-pos (1- (the fixnum (+ source-start n)))
+                         (1- source-pos))
+             (target-pos (1- (the fixnum (+ target-start n)))
+                         (1- target-pos)))
+            ((= i n))
+         (declare (fixnum i source-pos target-pos))
+         (setf (svref target target-pos) (svref source source-pos)))
+       (dotimes (i n)
+         (setf (svref target target-start) (svref source source-start))
+         (incf target-start)
+         (incf source-start))))
+    (#.target::subtag-bit-vector
+     (if (and (eq source target)
+              (> target-start source-start))
+       (do* ((i 0 (1+ i))
+             (source-pos (1- (the fixnum (+ source-start n)))
+                         (1- source-pos))
+             (target-pos (1- (the fixnum (+ target-start n)))
+                         (1- target-pos)))
+            ((= i n))
+         (declare (fixnum i source-pos target-pos))
+         (setf (sbit target target-pos) (sbit source source-pos)))
+       (dotimes (i n)
+         (setf (sbit target target-start) (sbit source source-start))
+         (incf target-start)
+         (incf source-start))))
+    ;; All other cases can be handled with %COPY-IVECTOR-TO-IVECTOR,
+    ;; which knows how to handle overlap
+    ((#.target::subtag-s8-vector
+      #.target::subtag-u8-vector)
+     (%copy-ivector-to-ivector source
+                               source-start
+                               target
+                               target-start
+                               n))
+    ((#.target::subtag-s16-vector
+      #.target::subtag-u16-vector)
+     (%copy-ivector-to-ivector source
+                               (the fixnum (* source-start 2))
+                               target
+                               (the fixnum (* target-start 2))
+                               (the fixnum (* n 2))))
+    ((#.target::subtag-s32-vector
+      #.target::subtag-u32-vector
+      #.target::subtag-single-float-vector
+      #.target::subtag-simple-base-string
+      #+32-bit-target #.target::subtag-fixnum-vector)
+     (%copy-ivector-to-ivector source
+                               (the fixnum (* source-start 4))
+                               target
+                               (the fixnum (* target-start 4))
+                               (the fixnum (* n 4))))
+    ((#.target::subtag-double-float-vector
+      #+64-bit-target #.target::subtag-s64-vector
+      #+64-bit-target #.target::subtag-u64-vector
+      #+64-bit-target #.target::subtag-fixnum-vector)
+     (%copy-ivector-to-ivector source
+                               (the fixnum
+                                 (+ (the fixnum (- target::misc-dfloat-offset
+                                                   target::misc-data-offset))
+                                    (the fixnum (* source-start 8))))
+                               target
+                               (the fixnum
+                                 (+ (the fixnum (- target::misc-dfloat-offset
+                                                   target::misc-data-offset))
+                                    (the fixnum (* target-start 8))))
+                               (the fixnum (* n 8)))))
+  target)
+
+(defun vector-push-extend (elt vector &optional (extension nil extp))
+  "Attempt to set the element of VECTOR designated by its fill pointer
+to ELT, and increment the fill pointer by one. If the fill pointer is
+too large, VECTOR is extended using adjust-array.  EXTENSION is the
+minimum number of elements to add if it must be extended."
+  (when extp
+    (unless (and (typep extension 'fixnum)
+                 (> (the fixnum extension) 0))
+      (setq extension (require-type extension 'unsigned-byte))))
+  (let* ((fill (fill-pointer vector))
+         (len (%svref vector target::vectorH.physsize-cell)))
+    (declare (fixnum fill len))
+    (multiple-value-bind (data offset) (%array-header-data-and-offset vector)
+      (declare (fixnum offset))
+      (if (= fill len)
+        (let* ((flags (%svref vector target::arrayH.flags-cell)))
+          (declare (fixnum flags))
+          (unless (logbitp $arh_adjp_bit flags)
+            (%err-disp $XMALADJUST vector))
+          (let* ((new-size (max
+                            (+ len (the fixnum (or extension
+                                                  len)))
+                            4))
+                 (typecode (typecode data))
+                 (new-vector (%alloc-misc new-size typecode)))
+            (%uvector-replace new-vector 0 data offset fill typecode)
+            (setf (%svref vector target::vectorH.data-vector-cell) new-vector
+                  (%svref vector target::vectorH.displacement-cell) 0
+                  (%svref vector target::vectorH.physsize-cell) new-size
+                  (%svref vector target::vectorH.flags-cell) (bitclr $arh_exp_disp_bit flags)
+                  (uvref new-vector fill) elt)))
+        (setf (uvref data (the fixnum (+ offset fill))) elt))
+      (setf (%svref vector target::vectorH.logsize-cell) (the fixnum (1+ fill))))
+    fill))
+
+;;; Could avoid potential memoization somehow
+(defun vector (&lexpr vals)
+  "Construct a SIMPLE-VECTOR from the given objects."
+  (let* ((n (%lexpr-count vals))
+         (v (allocate-typed-vector :simple-vector n)))
+    (declare (fixnum n))
+    (dotimes (i n v) (setf (%svref v i) (%lexpr-ref vals n i)))))
+
+;;; CALL-ARGUMENTS-LIMIT.
+(defun list-to-vector (elts)
+  (let* ((n (length elts)))
+    (declare (fixnum n))
+    (if (< n (floor #x8000 target::node-size))
+      (apply #'vector elts)
+      (make-array n :initial-contents elts))))
+
+             
+    
+(defun %gvector (subtag &lexpr vals)
+  (let* ((n (%lexpr-count vals))
+         (v (%alloc-misc n subtag)))
+    (declare (fixnum n))
+    (dotimes (i n v) (setf (%svref v i) (%lexpr-ref vals n i)))))
+
+(defun %aref1 (v i)
+  (let* ((typecode (typecode v)))
+    (declare (fixnum typecode))
+    (if (> typecode target::subtag-vectorH)
+      (uvref v i)
+      (if (= typecode target::subtag-vectorH)
+        (multiple-value-bind (data offset)
+                             (%array-header-data-and-offset v)
+          (unless (typep i 'fixnum)
+            (report-bad-arg i 'fixnum))
+          (unless (and (typep i 'fixnum)
+                       (>= (the fixnum i) 0)
+                       (< (the fixnum i) (the fixnum (%svref v target::vectorH.physsize-cell))))
+            (if (not (typep i 'fixnum))
+              (report-bad-arg i 'fixnum)
+              (%err-disp $XARROOB i v)))
+          (uvref data (+ offset i)))
+        (if (= typecode target::subtag-arrayH)
+          (%err-disp $XNDIMS v 1)
+          (report-bad-arg v 'array))))))
+
+(defun %aset1 (v i new)
+  (let* ((typecode (typecode v)))
+    (declare (fixnum typecode))
+    (if (> typecode target::subtag-vectorH)
+      (setf (uvref v i) new)
+      (if (= typecode target::subtag-vectorH)
+        (multiple-value-bind (data offset)
+                             (%array-header-data-and-offset v)
+          (unless (and (typep i 'fixnum)
+                       (>= (the fixnum i) 0)
+                       (< (the fixnum i) (the fixnum (%svref v target::vectorH.physsize-cell))))
+            (if (not (typep i 'fixnum))
+              (report-bad-arg i 'fixnum)
+              (%err-disp $XARROOB i v)))
+          (setf (uvref data (+ offset i)) new))
+        (if (= typecode target::subtag-arrayH)
+          (%err-disp $XNDIMS v 1)
+          (report-bad-arg v 'array))))))
+
+;;; Validate the N indices in the lexpr L against the
+;;; array-dimensions of L.  If anything's out-of-bounds,
+;;; error out (unless NO-ERROR is true, in which case
+;;; return NIL.)
+;;; If everything's OK, return the "row-major-index" of the array.
+;;; We know that A's an array-header of rank N.
+
+(defun %array-index (a l n &optional no-error)
+  (declare (fixnum n))
+  (let* ((count (%lexpr-count l)))
+    (declare (fixnum count))
+    (do* ((axis (1- n) (1- axis))
+          (chunk-size 1)
+          (result 0))
+         ((< axis 0) result)
+      (declare (fixnum result axis chunk-size))
+      (let* ((index (%lexpr-ref l count axis))
+             (dim (%svref a (the fixnum (+ target::arrayH.dim0-cell axis)))))
+        (declare (fixnum dim))
+        (unless (and (typep index 'fixnum)
+                     (>= (the fixnum index) 0)
+                     (< (the fixnum index) dim))
+          (if no-error
+            (return-from %array-index nil)
+            (%err-disp $XARROOB index a)))
+        (incf result (the fixnum (* chunk-size (the fixnum index))))
+        (setq chunk-size (* chunk-size dim))))))
+
+(defun aref (a &lexpr subs)
+  "Return the element of the ARRAY specified by the SUBSCRIPTS."
+  (let* ((n (%lexpr-count subs)))
+    (declare (fixnum n))
+    (if (= n 1)
+      (%aref1 a (%lexpr-ref subs n 0))
+      (if (= n 2)
+        (%aref2 a (%lexpr-ref subs n 0) (%lexpr-ref subs n 1))
+        (if (= n 3)
+          (%aref3 a (%lexpr-ref subs n 0) (%lexpr-ref subs n 1) (%lexpr-ref subs n 2))
+          (let* ((typecode (typecode a)))
+            (declare (fixnum typecode))
+            (if (>= typecode target::min-vector-subtag)
+              (%err-disp $XNDIMS a n)
+              (if (< typecode target::min-array-subtag)
+                (report-bad-arg a 'array)
+                ;;  This typecode is Just Right ...
+                (progn
+                  (unless (= (the fixnum (%svref a target::arrayH.rank-cell)) n)
+                    (%err-disp $XNDIMS a n))
+                  (let* ((rmi (%array-index a subs n)))
+                    (declare (fixnum rmi))
+                    (multiple-value-bind (data offset) (%array-header-data-and-offset a)
+                      (declare (fixnum offset))
+                      (uvref data (the fixnum (+ offset rmi))))))))))))))
+
+
+
+
+
+(defun aset (a &lexpr subs&val)
+  (let* ((count (%lexpr-count subs&val))
+         (nsubs (1- count)))
+    (declare (fixnum nsubs count))
+    (if (eql count 0)
+      (%err-disp $xneinps)
+      (let* ((val (%lexpr-ref subs&val count nsubs)))
+        (if (= nsubs 1)
+          (%aset1 a (%lexpr-ref subs&val count 0) val)
+          (if (= nsubs 2)
+            (%aset2 a (%lexpr-ref subs&val count 0) (%lexpr-ref subs&val count 1) val)
+            (if (= nsubs 3)
+              (%aset3 a (%lexpr-ref subs&val count 0) (%lexpr-ref subs&val count 1) (%lexpr-ref subs&val count 2) val)
+              (let* ((typecode (typecode a)))
+                (declare (fixnum typecode))
+                (if (>= typecode target::min-vector-subtag)
+                  (%err-disp $XNDIMS a nsubs)
+                  (if (< typecode target::min-array-subtag)
+                    (report-bad-arg a 'array)
+                                        ;  This typecode is Just Right ...
+                    (progn
+                      (unless (= (the fixnum (%svref a target::arrayH.rank-cell)) nsubs)
+                        (%err-disp $XNDIMS a nsubs))
+                      (let* ((rmi (%array-index a subs&val nsubs)))
+                        (declare (fixnum rmi))
+                        (multiple-value-bind (data offset) (%array-header-data-and-offset a)
+                          (setf (uvref data (the fixnum (+ offset rmi))) val))))))))))))))
+
+
+
+(defun schar (s i)
+  "SCHAR returns the character object at an indexed position in a string
+   just as CHAR does, except the string must be a simple-string."
+  (let* ((typecode (typecode s)))
+    (declare (fixnum typecode))
+    (if (= typecode target::subtag-simple-base-string)
+      (aref (the simple-string s) i)
+      (report-bad-arg s 'simple-string))))
+
+
+(defun %scharcode (s i)
+  (let* ((typecode (typecode s)))
+    (declare (fixnum typecode))
+    (if (= typecode target::subtag-simple-base-string)
+      (locally
+        (declare (optimize (speed 3) (safety 0)))
+        (aref (the (simple-array (unsigned-byte 32) (*)) s) i))
+        (report-bad-arg s 'simple-string))))
+
+
+(defun set-schar (s i v)
+  (let* ((typecode (typecode s)))
+    (declare (fixnum typecode))
+    (if (= typecode target::subtag-simple-base-string)
+      (setf (aref (the simple-string s) i) v)
+        (report-bad-arg s 'simple-string))))
+
+ 
+(defun %set-scharcode (s i v)
+  (let* ((typecode (typecode s)))
+    (declare (fixnum typecode))
+    (if (= typecode target::subtag-simple-base-string)
+      (locally
+        (declare (optimize (speed 3) (safety 0)))
+        (setf (aref (the simple-string s) i) v))
+        (report-bad-arg s 'simple-string))))
+  
+
+; Strings are simple-strings, start & end values are sane.
+(defun %simple-string= (str1 str2 start1 start2 end1 end2)
+  (declare (fixnum start1 start2 end1 end2))
+  (when (= (the fixnum (- end1 start1))
+           (the fixnum (- end2 start2)))
+    (locally (declare (type simple-base-string str1 str2))
+            (do* ((i1 start1 (1+ i1))
+                  (i2 start2 (1+ i2)))
+                 ((= i1 end1) t)
+              (declare (fixnum i1 i2))
+              (unless (eq (schar str1 i1) (schar str2 i2))
+                (return))))))
+
+(defun copy-uvector (src)
+  (%extend-vector 0 src (uvsize src)))
+
+#+ppc32-target
+(defun subtag-bytes (subtag element-count)
+  (declare (fixnum subtag element-count))
+  (unless (= #.ppc32::fulltag-immheader (logand subtag #.ppc32::fulltagmask))
+    (error "Not an ivector subtag: ~s" subtag))
+  (let* ((element-bit-shift
+          (if (<= subtag ppc32::max-32-bit-ivector-subtag)
+            5
+            (if (<= subtag ppc32::max-8-bit-ivector-subtag)
+              3
+              (if (<= subtag ppc32::max-16-bit-ivector-subtag)
+                4
+                (if (= subtag ppc32::subtag-double-float-vector)
+                  6
+                  0)))))
+         (total-bits (ash element-count element-bit-shift)))
+    (ash (+ 7 total-bits) -3)))
+
+#+ppc64-target
+(defun subtag-bytes (subtag element-count)
+  (declare (fixnum subtag element-count))
+  (unless (= ppc64::lowtag-immheader (logand subtag ppc64::lowtagmask))
+    (error "Not an ivector subtag: ~s" subtag))
+  (let* ((ivector-class (logand subtag ppc64::fulltagmask))
+         (element-bit-shift
+          (if (= ivector-class ppc64::ivector-class-32-bit)
+            5
+            (if (= ivector-class ppc64::ivector-class-8-bit)
+              3
+              (if (= ivector-class ppc64::ivector-class-64-bit)
+                6
+                (if (= subtag ppc64::subtag-bit-vector)
+                  0
+                  4)))))
+         (total-bits (ash element-count element-bit-shift)))
+    (declare (fixnum ivector-class element-bit-shift total-bits))
+    (ash (the fixnum (+ 7 total-bits)) -3)))
+
+#+x8632-target
+(defun subtag-bytes (subtag element-count)
+  (declare (fixnum subtag element-count))
+  (unless (= #.x8632::fulltag-immheader (logand subtag #.x8632::fulltagmask))
+    (error "Not an ivector subtag: ~s" subtag))
+  (let* ((element-bit-shift
+          (if (<= subtag x8632::max-32-bit-ivector-subtag)
+            5
+            (if (<= subtag x8632::max-8-bit-ivector-subtag)
+              3
+              (if (<= subtag x8632::max-16-bit-ivector-subtag)
+                4
+                (if (= subtag x8632::subtag-double-float-vector)
+                  6
+                  0)))))
+         (total-bits (ash element-count element-bit-shift)))
+    (ash (+ 7 total-bits) -3)))
+
+#+x8664-target
+(defun subtag-bytes (subtag element-count)
+  (declare (fixnum subtag element-count))
+  (unless (logbitp (the (mod 16) (logand subtag x8664::fulltagmask))
+                   (logior (ash 1 x8664::fulltag-immheader-0)
+                           (ash 1 x8664::fulltag-immheader-1)
+                           (ash 1 x8664::fulltag-immheader-2)))
+    (error "Not an ivector subtag: ~s" subtag))
+  (let* ((ivector-class (logand subtag x8664::fulltagmask))
+         (element-bit-shift
+          (if (= ivector-class x8664::ivector-class-32-bit)
+            5
+            (if (= ivector-class x8664::ivector-class-64-bit)
+                6
+                (if (= subtag x8664::subtag-bit-vector)
+                  0
+                  (if (>= subtag x8664::min-8-bit-ivector-subtag)
+                    3
+                    4)))))
+         (total-bits (ash element-count element-bit-shift)))
+    (declare (fixnum ivector-class element-bit-shift total-bits))
+    (ash (the fixnum (+ 7 total-bits)) -3)))
+
+(defun element-type-subtype (type)
+  "Convert element type specifier to internal array subtype code"
+  (ctype-subtype (specifier-type type)))
+
+(defun ctype-subtype (ctype)
+  (typecase ctype
+    (class-ctype
+     (if (or (eq (class-ctype-class ctype) *character-class*)
+	     (eq (class-ctype-class ctype) *base-char-class*)
+             (eq (class-ctype-class ctype) *standard-char-class*))
+       target::subtag-simple-base-string
+       target::subtag-simple-vector))
+    (numeric-ctype
+     (if (eq (numeric-ctype-complexp ctype) :complex)
+       target::subtag-simple-vector
+       (case (numeric-ctype-class ctype)
+	 (integer
+	  (let* ((low (numeric-ctype-low ctype))
+		 (high (numeric-ctype-high ctype)))
+	    (cond ((or (null low) (null high)) target::subtag-simple-vector)
+		  ((and (>= low 0) (<= high 1)) target::subtag-bit-vector)
+		  ((and (>= low 0) (<= high 255))
+                   target::subtag-u8-vector)
+		  ((and (>= low 0) (<= high 65535))
+                   target::subtag-u16-vector)
+		  ((and (>= low 0) (<= high #xffffffff))
+                   target::subtag-u32-vector)
+                  #+64-bit-target
+                  ((and (>= low 0) (<= high (1- (ash 1 64))))
+                   target::subtag-u64-vector)
+		  ((and (>= low -128) (<= high 127)) target::subtag-s8-vector)
+		  ((and (>= low -32768) (<= high 32767)) target::subtag-s16-vector)
+                  #+32-bit-target
+                  ((and (>= low target::target-most-negative-fixnum)
+                        (<= high target::target-most-positive-fixnum))
+                   target::subtag-fixnum-vector)
+		  ((and (>= low (ash -1 31)) (<= high (1- (ash 1 31))))
+		   target::subtag-s32-vector)
+                  #+64-bit-target
+                  ((and (>= low target::target-most-negative-fixnum)
+                        (<= high target::target-most-positive-fixnum))
+                   target::subtag-fixnum-vector)                  
+                  #+64-bit-target
+                  ((and (>= low (ash -1 63)) (<= high (1- (ash 1 63))))
+                   target::subtag-s64-vector)
+		  (t target::subtag-simple-vector))))
+	 (float
+	  (case (numeric-ctype-format ctype)
+	    ((double-float long-float) target::subtag-double-float-vector)
+	    ((single-float short-float) target::subtag-single-float-vector)
+	    (t target::subtag-simple-vector)))
+	 (t target::subtag-simple-vector))))
+    (named-ctype ; *, T, etc.
+     target::subtag-simple-vector)
+    (t
+     (harder-ctype-subtype ctype))))
+
+(defun %set-simple-array-p (array)
+  (setf (%svref array  target::arrayh.flags-cell)
+        (bitset  $arh_simple_bit (%svref array target::arrayh.flags-cell))))
+
+(defun  %array-header-simple-p (array)
+  (logbitp $arh_simple_bit (%svref array target::arrayh.flags-cell)))
+
+(defun %misc-ref (v i)
+  (%misc-ref v i))
+
+(defun %misc-set (v i new)
+  (%misc-set v i new))
+
+
+
+; end of l0-array.lisp
Index: /branches/new-random/level-0/l0-bignum32.lisp
===================================================================
--- /branches/new-random/level-0/l0-bignum32.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-bignum32.lisp	(revision 13309)
@@ -0,0 +1,2141 @@
+;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+#+32-bit-target                         ; the whole shebang
+(eval-when (:compile-toplevel :execute)
+  (require "ARCH")
+  (require "NUMBER-MACROS")
+  (require "NUMBER-CASE-MACRO")
+  
+  (defconstant digit-size 32)
+  (defconstant half-digit-size (/ digit-size 2))
+  
+  (defconstant maximum-bignum-length (1- (ash 1 24)))
+
+  (deftype bignum-index () `(integer 0 (,maximum-bignum-length)))
+  (deftype bignum-element-type () `(unsigned-byte ,digit-size))
+  (deftype bignum-half-element-type () `(unsigned-byte ,half-digit-size))
+  (deftype bignum-type () 'bignum)
+  (defmacro %bignum-digits (bignum)`(uvsize ,bignum))
+
+  (defmacro digit-bind ((&rest digits) form &body body)
+    `(multiple-value-bind ,digits
+                          ,form
+       (declare (type bignum-half-element-type ,@digits))
+       ,@body))
+
+  (defmacro digit-set ((&rest digits) form)
+    `(multiple-value-setq ,digits
+                          ,form))
+
+  (defmacro digit-zerop (h l)
+    `(and (zerop ,h) (zerop ,l)))
+ 
+
+
+  ;;;; BIGNUM-REPLACE and WITH-BIGNUM-BUFFERS.
+
+  ;;; BIGNUM-REPLACE -- Internal.
+  ;;;
+  (defmacro bignum-replace (dest src &key (start1 '0) end1 (start2 '0) end2
+                                 from-end)
+    (once-only ((n-dest dest)
+		 (n-src src))
+      (if (and (eq start1 0)(eq start2 0)(null end1)(null end2)(null from-end))
+        ; this is all true for some uses today <<
+        `(%copy-ivector-to-ivector ,n-src 0 ,n-dest 0 (%ilsl 2 (min (the fixnum (%bignum-length ,n-src))
+                                                                    (the fixnum (%bignum-length ,n-dest)))))
+        (let* ((n-start1 (gensym))
+               (n-end1 (gensym))
+               (n-start2 (gensym))
+               (n-end2 (gensym)))
+          `(let ((,n-start1 ,start1)
+                 (,n-start2 ,start2)
+                 (,n-end1 ,(or end1 `(%bignum-length ,n-dest)))
+                 (,n-end2 ,(or end2 `(%bignum-length ,n-src))))
+             ,(if (null from-end)            
+                `(%copy-ivector-to-ivector
+                  ,n-src (%i* 4 ,n-start2) 
+                  ,n-dest (%i* 4 ,n-start1)
+                  (%i* 4 (min (%i- ,n-end2 ,n-start2) 
+                              (%i- ,n-end1 ,n-start1))))
+                `(let ((nwds (min (%i- ,n-end2 ,n-start2)
+                                  (%i- ,n-end1 ,n-start1))))
+                   (%copy-ivector-to-ivector
+                    ,n-src (%ilsl 2 (%i- ,n-end2 nwds))
+                    ,n-dest (%ilsl 2 (%i- ,n-end1 nwds))
+                    (%i* 4 nwds))))))))) 
+  
+
+  ;;;; Shifting.
+  
+  (defconstant all-ones-half-digit #xFFFF)  
+  
+
+  
+
+  
+  (defmacro %logxor (h1 l1 h2 l2)
+    (once-only ((h1v h1)(l1v l1)(h2v h2)(l2v l2))
+      `(values (%ilogxor ,h1v ,h2v)(%ilogxor ,l1v ,l2v))))
+  
+  
+  (defmacro %lognot (h l)
+    (once-only ((h1v h)(l1v l))
+      `(values (%ilognot ,h1v)(%ilognot ,l1v))))
+
+  (defmacro %allocate-bignum (ndigits)
+    `(%alloc-misc ,ndigits target::subtag-bignum))
+
+  (defmacro %normalize-bignum-macro (big)
+    `(%normalize-bignum-2 t ,big))
+
+  (defmacro %mostly-normalize-bignum-macro (big)
+    `(%normalize-bignum-2 nil ,big))
+
+
+;;; %ALLOCATE-BIGNUM must zero all elements.
+;;;
+  (declaim (inline  %bignum-length))
+
+;;; Temp space needed to (Karatsuba)-square N-digit argument
+  (defmacro mpn-kara-mul-n-tsize (n)
+    `(* 8 (+ ,n 32)))
+;;; Need the same amount of space to do Karatsuba multiply.
+  (defmacro mpn-kara-sqr-n-tsize (n)
+    `(mpn-kara-mul-n-tsize ,n))
+  
+)
+
+
+
+
+#+32-bit-target
+(progn
+;;; Extract the length of the bignum.
+;;; 
+(defun %bignum-length (bignum)
+  (uvsize bignum)) 
+
+
+
+
+
+
+;;;; Addition.
+(defun add-bignums (a b)
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b)))
+    (declare (bignum-index len-a len-b))
+    (when (> len-b len-a)
+      (rotatef a b)
+      (rotatef len-a len-b))
+    (let* ((len-res (1+ len-a))
+	   (res (%allocate-bignum len-res))
+	   (carry 0)
+	   (sign-b (%bignum-sign b)))
+	(dotimes (i len-b)
+	  (setq carry (%add-with-carry res i carry a i b i)))
+	(if (/= len-a len-b)
+	  (finish-bignum-add  res carry a sign-b len-b len-a)
+	  (%add-with-carry res len-a carry (%bignum-sign a) nil sign-b nil))
+	(%normalize-bignum-macro res))))
+
+;;; Could do better than this, surely.
+(defun add-bignum-and-fixnum (bignum fixnum)
+  (with-small-bignum-buffers ((bigfix fixnum))
+    (add-bignums bignum bigfix)))
+
+
+
+;;; B was shorter than A; keep adding B's sign digit to each remaining
+;;; digit of A, propagating the carry.
+(defun finish-bignum-add (result carry a sign-b start end)
+  (declare (type bignum-index start end))
+  (do* ((i start (1+ i)))
+       ((= i end)
+	(%add-with-carry result end carry (%bignum-sign a) nil sign-b nil))
+    (setq carry (%add-with-carry result i carry a i sign-b nil))))
+
+
+
+
+
+
+
+;;;; Subtraction.
+(defun subtract-bignum (a b)
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (len-res (1+ (max len-a len-b)))
+	 (res (%allocate-bignum len-res)))
+    (declare (bignum-index len-a len-b len-res))
+    (bignum-subtract-loop a len-a b len-b res)
+    (%normalize-bignum-macro res)))
+
+(defun bignum-subtract-loop (a len-a b len-b res)
+  (declare (bignum-index len-a len-b ))
+  (let* ((len-res (%bignum-length res)))
+    (declare (bignum-index len-res))
+    (let* ((borrow 1)
+	   (sign-a (%bignum-sign a))
+	   (sign-b (%bignum-sign b)))
+      (dotimes (i (the bignum-index (min len-a len-b)))
+	(setq borrow (%subtract-with-borrow res i borrow a i b i)))
+      (if (< len-a len-b)
+	(do* ((i len-a (1+ i)))
+	     ((= i len-b)
+	      (if (< i len-res)
+		(%subtract-with-borrow res i borrow sign-a nil sign-b nil)))
+	  (setq borrow (%subtract-with-borrow res i borrow sign-a nil b i)))
+	(do* ((i len-b (1+ i)))
+	     ((= i len-a)
+	      (if (< i len-res)
+		(%subtract-with-borrow res i borrow sign-a nil sign-b nil)))
+	  (setq borrow (%subtract-with-borrow res i borrow a i sign-b nil)))))))
+
+
+
+;;;; Multiplication.
+
+;;; These parameters match GMP's.
+(defvar *sqr-basecase-threshold* 5)
+(defvar *sqr-karatsuba-threshold* 22)
+(defvar *mul-karatsuba-threshold* 10)
+
+;;; Squaring is often simpler than multiplication.  This should never
+;;; be called with (>= N *sqr-karatsuba-threshold*).
+(defun mpn-sqr-basecase (prodp up n)
+  (declare (fixnum prodp up n))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (umulppm up up prodp)
+  (when (> n 1)
+    (%stack-block ((tarr (* 4 (* 2 *sqr-karatsuba-threshold*))))
+      (let* ((tp (macptr->fixnum tarr)))
+	(mpn-mul-1 tp
+		   (the fixnum (1+ up))
+		   (the fixnum (1- n))
+		   up
+		   (the fixnum (+ tp (the fixnum (1- n)))))
+	(do* ((i 2 (1+ i)))
+	     ((= i n))
+	  (declare (fixnum i))
+	  (mpn-addmul-1 (the fixnum (- (the fixnum (+ tp (the fixnum (+ i i))))
+				       2))
+			(the fixnum (+ up i))
+			(the fixnum (- n i))
+			(the fixnum (+ up (the fixnum (1- i))))
+			(the fixnum (+ tp (the fixnum (+ n (the fixnum (- i 2))))))))
+	(do* ((i 1 (1+ i))
+	      (ul (1+ up) (1+ ul)))
+	     ((= i n))
+	  (declare (fixnum i ul))
+	  (umulppm ul ul (the fixnum (+ prodp (the fixnum (+ i i))))))
+	(let* ((2n-2 (- (the fixnum (+ n n)) 2))
+	       (carry (mpn-lshift-1 tp tp 2n-2)))
+	  (declare (fixnum 2n-2 carry))
+	  (setq carry
+                (+ carry
+                   (the fixnum (mpn-add-n (the fixnum (1+ prodp))
+                                          (the fixnum (1+ prodp))
+                                          tp
+                                          2n-2))))
+	  (add-fixnum-to-limb carry (the fixnum (+ prodp
+						   (the fixnum (1-
+								(the fixnum
+								  (+ n n))))))))))))
+
+;;; For large enough values of N, squaring via Karatsuba-style
+;;; divide&conquer is faster than in the base case.
+(defun mpn-kara-sqr-n (p a n ws)
+  (declare (fixnum p a n ws))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (%stack-block ((limbs 16))
+    (let* ((w (macptr->fixnum limbs))
+	   (w0 (1+ w))
+	   (w1 (1+ w0))
+	   (xx (1+ w1))
+	   (n2 (ash n -1))
+	   (x 0)
+	   (y 0)
+	   (i 0))
+      (declare (fixnum w w0 w1 xx n2 x y i))
+      (cond ((logbitp 0 n)
+	     ;; Odd length
+	     (let* ((n3 (- n n2))
+		    (n1 0)
+		    (nm1 0))
+	       (declare (fixnum n3 n1 nm1))
+	       (copy-limb (the fixnum (+ a n2)) w)
+	       (if (not (limb-zerop w))
+		 (add-fixnum-to-limb
+		  (the fixnum
+		    (- (the fixnum (mpn-sub-n p a (the fixnum (+ a n3)) n2))))
+		  w)
+		 (progn
+		   (setq i n2)
+		   (loop
+		     (decf i)
+		     (copy-limb (the fixnum (+ a i)) w0)
+		     (copy-limb (the fixnum (+ a (the fixnum (+ n3 i)))) w1)
+		     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+			     (= i 0))
+		       (return)))
+		   (if (< (the fixnum (compare-limbs w0 w1)) 0)
+		     (setq x (+ a n3)
+			   y a)
+		     (setq y (+ a n3)
+			   x a))
+		   (mpn-sub-n p x y n2)))
+	       (copy-limb w (the fixnum (+ p n2)))
+	       (setq n1 (1+ n))
+	       (cond ((< n3 *sqr-basecase-threshold*)
+		      (mpn-mul-basecase ws p n3 p n3)
+		      (mpn-mul-basecase p a n3 a n3))
+		     ((< n3 *sqr-karatsuba-threshold*)
+		      (mpn-sqr-basecase ws p n3)
+		      (mpn-sqr-basecase p a n3))
+		     (t
+		      (mpn-kara-sqr-n ws p n3 (the fixnum (+ ws n1)))
+		      (mpn-kara-sqr-n p  a n3 (the fixnum (+ ws n1)))))
+	       (cond ((< n2 *sqr-basecase-threshold*)
+		      (mpn-mul-basecase (the fixnum (+ p n1))
+					(the fixnum (+ a n3))
+					n2
+					(the fixnum (+ a n3))
+					n2))
+		     ((< n2 *sqr-karatsuba-threshold*)
+		      (mpn-sqr-basecase (the fixnum (+ p n1))
+					(the fixnum (+ a n3))
+					n2))
+		     (t
+		      (mpn-kara-sqr-n (the fixnum (+ p n1))
+				      (the fixnum (+ a n3))
+				      n2
+				      (the fixnum (+ ws n1)))))
+	       (mpn-sub-n ws p ws n1)
+	       (setq nm1 (1- n))
+	       (unless (zerop (the fixnum
+				(mpn-add-n ws
+					   (the fixnum (+ p n1))
+					   ws
+					   nm1)))
+		 (copy-limb (the fixnum (+ ws nm1)) xx)
+		 (add-fixnum-to-limb 1 xx)
+		 (copy-limb xx (the fixnum (+ ws nm1)))
+		 (if (limb-zerop xx)
+		   (add-fixnum-to-limb 1 (the fixnum (+ ws n)))))
+	       (unless (zerop
+			(the fixnum
+			  (mpn-add-n (the fixnum (+ p n3))
+				     (the fixnum (+ p n3))
+				     ws
+				     n1)))
+		 (mpn-incr-u (the fixnum (+ p (the fixnum (+ n1 n3))))
+			     1))))
+	    (t ; N is even
+	     (setq i n2)
+	     (loop
+	       (decf i)
+	       (copy-limb (the fixnum (+ a i)) w0)
+	       (copy-limb (the fixnum (+ a (the fixnum (+ n2 i)))) w1)
+	       (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+		       (= i 0))
+		 (return)))
+	     (if (< (the fixnum (compare-limbs w0 w1)) 0)
+	       (setq x (+ a n2)
+		     y a)
+	       (setq y (+ a n2)
+		     x a))
+	     (mpn-sub-n p x y n2)
+	     (cond ((< n2 *sqr-basecase-threshold*)
+		    (mpn-mul-basecase ws p n2 p n2)
+		    (mpn-mul-basecase p a n2 a n2)
+		    (mpn-mul-basecase (the fixnum (+ p n))
+				      (the fixnum (+ a n2))
+				      n2
+				      (the fixnum (+ a n2))
+				      n2))
+		   ((< n2 *sqr-karatsuba-threshold*)
+		    (mpn-sqr-basecase ws p n2)
+		    (mpn-sqr-basecase p a n2)
+		    (mpn-sqr-basecase (the fixnum (+ p n))
+				      (the fixnum (+ a n2))
+				      n2))
+		   (t
+		    (mpn-kara-sqr-n ws p n2 (the fixnum (+ ws n)))
+		    (mpn-kara-sqr-n p  a n2 (the fixnum (+ ws n)))
+		    (mpn-kara-sqr-n (the fixnum (+ p n))
+				    (the fixnum (+ a n2))
+				    n2
+				    (the fixnum (+ ws n)))))
+	     (let* ((ww (- (the fixnum (mpn-sub-n ws p ws n)))))
+	       (declare (fixnum ww))
+               (setq ww (+ ww (mpn-add-n ws (the fixnum (+ p n)) ws n)))
+	       (setq ww (+ ww (mpn-add-n (the fixnum (+ p n2))
+                                         (the fixnum (+ p n2))
+                                         ws
+                                         n)))
+	       (mpn-incr-u (the fixnum (+ p (the fixnum (+ n2 n)))) ww)))))))
+
+;;; Karatsuba subroutine: multiply A and B, store result at P, use WS
+;;; as scrach space.  Treats A and B as if they were both of size N;
+;;; if that's not true, caller must fuss around the edges.
+(defun mpn-kara-mul-n (p a b n ws)
+  (declare (fixnum p a b n ws))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (%stack-block ((limbs 16))
+    (let* ((w (macptr->fixnum limbs))
+	   (w0 (1+ w))
+	   (w1 (1+ w0))
+	   (xx (1+ w1))
+	   (x 0)
+	   (y 0)
+	   (i 0)
+	   (n2 (ash n -1))
+	   (sign 0))
+      (declare (fixnum w w0 w1 xx x y i n2 sign))
+      (cond ((logbitp 0 n)
+	     (let* ((n1 0)
+		    (n3 (- n n2))
+		    (nm1 0))
+	       (declare (fixnum n1 n3 nm1))
+	       (copy-limb (the fixnum (+ a n2)) w)
+	       (if (not (limb-zerop w))
+		 (add-fixnum-to-limb
+		  (the fixnum (- (mpn-sub-n p a (the fixnum (+ a n3)) n2))) w)
+		 (progn
+		   (setq i n2)
+		   (loop
+		     (decf i)
+		     (copy-limb (the fixnum (+ a i)) w0)
+		     (copy-limb (the fixnum (+ a (the fixnum (+ n3 i)))) w1)
+		     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+			     (zerop i))
+		       (return)))
+		   (if (< (the fixnum (compare-limbs w0 w1)) 0)
+		     (setq x (+ a n3)
+			   y a
+			   sign -1)
+		     (setq x a
+			   y (+ a n3)))
+		   (mpn-sub-n p x y n2)))
+	       (copy-limb w (the fixnum (+ p n2)))
+	       (copy-limb (the fixnum (+ b n2)) w)
+	       (if (not (limb-zerop w))
+		 (add-fixnum-to-limb
+		  (the fixnum (- (the fixnum (mpn-sub-n (the fixnum (+ p n3))
+							b
+							(the fixnum (+ b n3))
+							n2))))
+		  w)
+		 (progn
+		   (setq i n2)
+		   (loop
+		     (decf i)
+		     (copy-limb (the fixnum (+ b i)) w0)
+		     (copy-limb (the fixnum (+ b (the fixnum (+ n3 i)))) w1)
+		     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+			     (zerop i))
+		       (return)))
+		   (if (< (the fixnum (compare-limbs w0 w1)) 0)
+		     (setq x (+ b n3)
+			   y b
+			   sign (lognot sign))
+		     (setq x b
+			   y (+ b n3)))
+		   (mpn-sub-n (the fixnum (+ p n3)) x y n2)))
+	       (copy-limb w (the fixnum (+ p n)))
+	       (setq n1 (1+ n))
+	       (cond
+		 ((< n2 *mul-karatsuba-threshold*)
+		  (cond
+		    ((< n3 *mul-karatsuba-threshold*)
+		     (mpn-mul-basecase ws p n3 (the fixnum (+ p n3)) n3)
+		     (mpn-mul-basecase p a n3 b n3))
+		    (t
+		     (mpn-kara-mul-n ws p (the fixnum (+ p n3)) n3 (the fixnum (+ ws n1)))
+		     (mpn-kara-mul-n p a b n3 (the fixnum (+ ws n1)))))
+		  (mpn-mul-basecase (the fixnum (+ p n1))
+				    (the fixnum (+ a n3))
+				    n2
+				    (the fixnum (+ b n3))
+				    n2))
+		 (t
+		  (mpn-kara-mul-n ws p (the fixnum (+ p n3)) n3 (the fixnum (+ ws n1)))
+		  (mpn-kara-mul-n p a b n3 (the fixnum (+ ws n1)))
+		  (mpn-kara-mul-n (the fixnum (+ p n1))
+				  (the fixnum (+ a n3))
+				  (the fixnum (+ b n3))
+				  n2
+				  (the fixnum (+ ws n1)))))
+	       (if (not (zerop sign))
+		 (mpn-add-n ws p ws n1)
+		 (mpn-sub-n ws p ws n1))
+	       (setq nm1 (1- n))
+	       (unless (zerop (the fixnum (mpn-add-n ws
+						     (the fixnum (+ p n1))
+						     ws
+						     nm1)))
+		 (copy-limb (the fixnum (+ ws nm1)) xx)
+		 (add-fixnum-to-limb 1 xx)
+		 (copy-limb xx (the fixnum (+ ws nm1)))
+		 (if (limb-zerop xx)
+		   (add-fixnum-to-limb 1 (the fixnum (+ ws n)))))
+	       (unless (zerop (the fixnum
+				(mpn-add-n (the fixnum (+ p n3))
+					   (the fixnum (+ p n3))
+					   ws
+					   n1)))
+		 (mpn-incr-u (the fixnum
+			       (+ p (the fixnum (+ n1 n3)))) 1))))
+	    (t				; even length
+	     (setq i n2)
+	     (loop
+	       (decf i)
+	       (copy-limb (the fixnum (+ a i)) w0)
+	       (copy-limb (the fixnum (+ a (the fixnum (+ n2 i)))) w1)
+	       (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+		       (zerop i))
+		 (return)))
+	     (setq sign 0)
+	     (if (< (the fixnum (compare-limbs w0 w1)) 0)
+	       (setq x (+ a n2)
+		     y a
+		     sign -1)
+	       (setq x a
+		     y (+ a n2)))
+	     (mpn-sub-n p x y n2)
+	     (setq i n2)
+	     (loop
+	       (decf i)
+	       (copy-limb (the fixnum (+ b i)) w0)
+	       (copy-limb (the fixnum (+ b (the fixnum (+ n2 i)))) w1)
+	       (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+		       (zerop i))
+		 (return)))	      
+	     (if (< (the fixnum (compare-limbs w0 w1)) 0)
+	       (setq x (+ b n2)
+		     y b
+		     sign (lognot sign))
+	       (setq x b
+		     y (+ b n2)))
+	     (mpn-sub-n (the fixnum (+ p n2)) x y n2)
+	     (cond
+	       ((< n2 *mul-karatsuba-threshold*)
+		(mpn-mul-basecase ws p n2 (the fixnum (+ p n2)) n2)
+		(mpn-mul-basecase p a n2 b n2)
+		(mpn-mul-basecase (the fixnum (+ p n))
+				  (the fixnum (+ a n2))
+				  n2
+				  (the fixnum (+ b n2))
+				  n2))
+	       (t
+		(mpn-kara-mul-n ws p (the fixnum (+ p n2)) n2
+				(the fixnum (+ ws n)))
+		(mpn-kara-mul-n p a b n2 (the fixnum (+ ws n)))
+		(mpn-kara-mul-n (the fixnum (+ p n))
+				(the fixnum (+ a n2))
+				(the fixnum (+ b n2))
+				n2
+				(the fixnum (+ ws n)))))
+	     (let* ((ww (if (not (zerop sign))
+			  (mpn-add-n ws p ws n)
+			  (- (the fixnum (mpn-sub-n ws p ws n))))))
+	       (declare (fixnum ww))
+	       (setq ww (+ ww (mpn-add-n ws (the fixnum (+ p n)) ws n)))
+	       (setq ww (+ ww (mpn-add-n (the fixnum (+ p n2))
+                                         (the fixnum (+ p n2))
+                                         ws
+                                         n)))
+	       (mpn-incr-u (the fixnum (+ p (the fixnum (+ n2 n)))) ww)))))))
+
+;;; Square UP, of length UN.  I wonder if a Karatsuba multiply might be
+;;; faster than a basecase square.
+(defun mpn-sqr-n (prodp up un)
+  (declare (fixnum prodp up un))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (if (< un *sqr-basecase-threshold*)
+    (mpn-mul-basecase prodp up un up un)
+    (if (< un *sqr-karatsuba-threshold*)
+      (mpn-sqr-basecase prodp up un)
+      (%stack-block ((wsptr (mpn-kara-sqr-n-tsize un)))
+	(mpn-kara-sqr-n prodp up un (macptr->fixnum wsptr))))))
+
+;;; Subroutine: store AxB at P.  Assumes A & B to be of length N
+(defun mpn-mul-n (p a b n)
+  (declare (fixnum p a b n))
+  (declare (optimize (speed 3) (safety 0) (space 0)))  
+  (if (< n *mul-karatsuba-threshold*)
+    (mpn-mul-basecase p a n b n)
+    (%stack-block ((wsptr (mpn-kara-mul-n-tsize n)))
+      (mpn-kara-mul-n p a b n (macptr->fixnum wsptr)))))
+
+
+;;; Multiply [UP,UN] by [VP,VN].  UN must not be less than VN.
+;;; This does Karatsuba if operands are big enough; if they are
+;;; and they differ in size, this computes the product of the
+;;; smaller-size slices, then fixes up the resut.
+(defun mpn-mul (prodp up un vp vn)
+  (declare (fixnum prodp up un vp vn))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  ;(assert (>= un vn 1))
+  (if (and (= up vp) (= un vn))
+    (mpn-sqr-n prodp up un)
+    (if (< vn *mul-karatsuba-threshold*)
+      (mpn-mul-basecase prodp up un vp vn)
+      (let* ((l vn))
+	(declare (fixnum l))
+	(mpn-mul-n prodp up vp vn)
+	(unless (= un vn)
+	  (incf prodp vn)
+	  (incf up vn)
+	  (decf un vn)
+	  (if (< un vn)
+	    (psetq un vn vn un up vp vp up))
+	  (%stack-block ((wsptr
+			  (the fixnum
+			    (+ 8
+			       (the fixnum
+				 (* 4
+				    (the fixnum
+				      (+ vn
+					 (if (>= vn *mul-karatsuba-threshold*)
+					   vn
+					   un)))))))))
+	    (setf (%get-unsigned-long wsptr 0) 0
+		  (%get-unsigned-long wsptr 4) 0)
+	    (let* ((tt (macptr->fixnum wsptr))
+		   (c (1+ tt))
+		   (ws (1+ c)))
+	      (declare (fixnum tt c ws ))
+	      (do* ()
+		   ((< vn *mul-karatsuba-threshold*))
+		(mpn-mul-n ws up vp vn)
+		(cond ((<= l (the fixnum (+ vn vn)))
+		       (add-fixnum-to-limb (mpn-add-n prodp prodp ws l) tt)
+		       (unless (= l (the fixnum (+ vn vn)))
+			 (copy-fixnum-to-limb
+			  (mpn-add-1 (the fixnum (+ prodp l))
+				     (the fixnum (+ ws l))
+				     (the fixnum (- (the fixnum (+ vn vn)) l))
+				     tt)
+			  tt)
+			 (setq l (the fixnum (+ vn vn)))))
+		      (t
+		       (copy-fixnum-to-limb
+			(mpn-add-n prodp prodp ws (the fixnum (+ vn vn))) c)
+		       (add-fixnum-to-limb
+			(mpn-add-1 (the fixnum (+ prodp (the fixnum (+ vn vn))))
+				   (the fixnum (+ prodp (the fixnum (+ vn vn))))
+				   (the fixnum (- l (the fixnum (+ vn vn))))
+				   c)
+			tt)))
+		(incf prodp vn)
+		(decf l vn)
+		(incf up vn)
+		(decf un vn)
+		(if (< un vn)
+		  (psetq up vp vp up un vn vn un)))
+	      (unless (zerop vn)
+		(mpn-mul-basecase ws up un vp vn)
+		(cond ((<= l (the fixnum (+ un vn)))
+		       (add-fixnum-to-limb
+			(mpn-add-n prodp prodp ws l)
+			tt)
+		       (unless (= l (the fixnum (+ un vn)))
+			 (copy-fixnum-to-limb
+			  (mpn-add-1 (the fixnum (+ prodp l))
+				     (the fixnum (+ ws l))
+				     (the fixnum (- (the fixnum (+ un vn)) l))
+				     tt)
+			  tt)))
+		      (t
+		       (copy-fixnum-to-limb
+			(mpn-add-n prodp prodp ws (the fixnum (+ un vn)))
+			c)
+		       (add-fixnum-to-limb
+			(mpn-add-1
+			 (the fixnum (+ prodp (the fixnum (+ un vn))))
+			 (the fixnum (+ prodp (the fixnum (+ un vn))))
+			 (the fixnum (- (the fixnum (- l un)) vn))
+			 c)
+			tt)))))))))))
+
+(defun multiply-bignums (a b)
+  (let* ((signs-differ (not (eq (bignum-minusp a) (bignum-minusp b)))))
+    (flet ((multiply-unsigned-bignums (a b)
+	     (let* ((len-a (%bignum-length a))
+		    (len-b (%bignum-length b))
+		    (len-res (+ len-a len-b))
+		    (res (%allocate-bignum len-res)) )
+	       (declare (bignum-index len-a len-b len-res))
+	       (if (and (>= len-a 16)
+			(>= len-b 16)
+			#+x8632-target
+			nil)
+		 (let* ((ubytes (* len-a 4))
+			(vbytes (* len-b 4))
+			(rbytes (* len-res 4)))
+		   (declare (fixnum ubytes vbytes rbytes))
+		   (%stack-block ((uptr ubytes)
+				  (vptr vbytes)
+				  (rptr rbytes))
+		     (let* ((up (macptr->fixnum uptr))
+			    (vp (macptr->fixnum vptr))
+			    (rp (macptr->fixnum rptr)))
+		       (declare (fixnum up vp rp))
+		       (%copy-ivector-to-ptr a 0 uptr 0 ubytes)
+		       (if (eq a b)	; maybe try eql ..
+			 (mpn-mul rp up len-a up len-a)
+			 (progn
+			   (%copy-ivector-to-ptr b 0 vptr 0 vbytes)
+			   (if (< len-a len-b)
+			     (mpn-mul rp vp len-b up len-a)
+			     (mpn-mul rp up len-a vp len-b)))))
+		     (%copy-ptr-to-ivector rptr 0 res 0 rbytes)))
+		 (dotimes (i len-a)
+		   (declare (type bignum-index i))
+		   (%multiply-and-add-harder-loop-2 a b res i len-b)))
+		 res)))
+      (let* ((res (with-negated-bignum-buffers a b multiply-unsigned-bignums)))
+	(if signs-differ (negate-bignum-in-place res))
+	(%normalize-bignum-macro res)))))
+
+
+(defun multiply-bignum-and-fixnum (bignum fixnum)
+  (declare (type bignum-type bignum) (fixnum fixnum))
+  (let* ((bignum-len (%bignum-length bignum))
+         (bignum-plus-p (bignum-plusp bignum))
+	 (fixnum-plus-p (not (minusp fixnum)))
+         (negate-res (neq bignum-plus-p fixnum-plus-p)))
+    (declare (type bignum-type bignum)
+	     (type bignum-index bignum-len))
+    (flet ((do-it (bignum fixnum  negate-res)
+             (let* ((bignum-len (%bignum-length bignum))
+                    (result (%allocate-bignum (the fixnum (1+ bignum-len)))))
+               (declare (type bignum-type bignum)
+	                (type bignum-index bignum-len))
+	       (with-small-bignum-buffers ((carry-digit)
+					   (result-digit))
+		 (dotimes (i bignum-len (%set-digit result bignum-len carry-digit))
+		   (%set-digit result i
+			       (%multiply-and-add result-digit carry-digit bignum i fixnum))))
+               (when negate-res
+                 (negate-bignum-in-place result))
+               (%normalize-bignum-macro result ))))
+      (declare (dynamic-extent #'do-it))
+      (if bignum-plus-p
+        (do-it bignum (if fixnum-plus-p fixnum (- fixnum))  negate-res)
+        (with-bignum-buffers ((b1 (the fixnum (1+ bignum-len))))
+          (negate-bignum bignum nil b1)
+          (do-it b1 (if fixnum-plus-p fixnum (- fixnum))  negate-res))))))
+
+;; assume we already know result won't fit in a fixnum
+;; only caller is fixnum-*-2
+;;
+
+(defun multiply-fixnums (a b)
+  (declare (fixnum a b))
+  (* a b))
+
+
+;;;; GCD.
+
+
+;;; Both args are > 0.
+(defun bignum-fixnum-gcd (bignum fixnum)
+  (let* ((rem (bignum-truncate-by-fixnum-no-quo bignum fixnum)))
+    (declare (fixnum rem))
+    (if (zerop rem)
+      fixnum
+      (%fixnum-gcd rem fixnum))))
+
+
+
+
+;;; NEGATE-BIGNUM -- Public.
+;;;
+;;; Fully-normalize is an internal optional.  It cause this to always return
+;;; a bignum, without any extraneous digits, and it never returns a fixnum.
+;;;
+(defun negate-bignum (x &optional (fully-normalize t) res)
+  (declare (type bignum-type x))
+  (let* ((len-x (%bignum-length x))
+	 (len-res (1+ len-x))
+         (minusp (bignum-minusp x)))
+    (declare (type bignum-index len-x len-res))
+    (if (not res) (setq res (%allocate-bignum len-res))) ;Test len-res for range?
+    (let ((carry (bignum-negate-loop-really x len-x res)))  ; i think carry is always 0
+      (if (eq carry 0)
+        (if minusp (%bignum-set res len-x 0 0)(%bignum-set res len-x #xffff #xffff))
+        (digit-bind (h l)
+                    (if minusp 
+                      (%add-the-carry 0 0 carry)
+                      (%add-the-carry #xffff #xffff carry))
+                    
+          (%bignum-set res len-x h l))))
+    (if fully-normalize
+      (%normalize-bignum-macro res)
+      (%mostly-normalize-bignum-macro res))))
+
+;;; NEGATE-BIGNUM-IN-PLACE -- Internal.
+;;;
+;;; This assumes bignum is positive; that is, the result of negating it will
+;;; stay in the provided allocated bignum.
+;;;
+(defun negate-bignum-in-place (bignum)
+  (bignum-negate-loop-really bignum (%bignum-length bignum) bignum)
+  bignum)
+
+
+  
+
+(defun copy-bignum (bignum)
+  (let ((res (%allocate-bignum (%bignum-length bignum))))
+    (bignum-replace res bignum)
+    res))
+
+
+
+
+;;; BIGNUM-ASHIFT-RIGHT -- Public.
+;;;
+;;; First compute the number of whole digits to shift, shifting them by
+;;; skipping them when we start to pick up bits, and the number of bits to
+;;; shift the remaining digits into place.  If the number of digits is greater
+;;; than the length of the bignum, then the result is either 0 or -1.  If we
+;;; shift on a digit boundary (that is, n-bits is zero), then we just copy
+;;; digits.  The last branch handles the general case which uses a macro that a
+;;; couple other routines use.  The fifth argument to the macro references
+;;; locals established by the macro.
+;;;
+
+
+(defun bignum-ashift-right (bignum x)
+  (declare (type bignum-type bignum)
+           (fixnum x))
+  (let ((bignum-len (%bignum-length bignum)))
+    (declare (type bignum-index bignum-len))
+    (multiple-value-bind (digits n-bits) (truncate x digit-size)
+      (declare (type bignum-index digits)(fixnum n-bits))
+      (cond
+       ((>= digits bignum-len)
+        (if (bignum-plusp bignum) 0 -1))
+       ((eql 0 n-bits)
+        (bignum-ashift-right-digits bignum digits))
+       (t
+        (let* ((res-len (- bignum-len digits))
+               (res (%allocate-bignum res-len))
+               (len-1 (1- res-len)))
+          (declare (fixnum res-len len-1))
+          (bignum-shift-right-loop-1 n-bits res bignum len-1 digits)          
+          (%normalize-bignum-macro res )))))))
+
+			       
+
+
+
+;;; BIGNUM-ASHIFT-RIGHT-DIGITS -- Internal.
+;;;
+(defun bignum-ashift-right-digits (bignum digits)
+  (declare (type bignum-type bignum)
+	   (type bignum-index digits))
+  (let* ((res-len (- (%bignum-length bignum) digits))
+	 (res (%allocate-bignum res-len)))
+    (declare (type bignum-index res-len)
+	     (type bignum-type res))
+    (bignum-replace res bignum :start2 digits)
+    (%normalize-bignum-macro res)))
+
+
+;;; BIGNUM-BUFFER-ASHIFT-RIGHT -- Internal.
+;;;
+;;; GCD uses this for an in-place shifting operation.  This is different enough
+;;; from BIGNUM-ASHIFT-RIGHT that it isn't worth folding the bodies into a
+;;; macro, but they share the basic algorithm.  This routine foregoes a first
+;;; test for digits being greater than or equal to bignum-len since that will
+;;; never happen for its uses in GCD.  We did fold the last branch into a macro
+;;; since it was duplicated a few times, and the fifth argument to it
+;;; references locals established by the macro.
+;;;
+#|
+(defun bignum-buffer-ashift-right (bignum bignum-len x)
+  (declare (type bignum-index bignum-len) (fixnum x))
+  (multiple-value-bind (digits n-bits)
+		       (truncate x digit-size)
+    (declare (type bignum-index digits))
+    (cond
+     ((zerop n-bits)
+      (let ((new-end (- bignum-len digits)))
+	(bignum-replace bignum bignum :end1 new-end :start2 digits
+			:end2 bignum-len)
+	(%normalize-bignum-buffer bignum new-end)))
+     (t
+      (shift-right-unaligned bignum digits n-bits (- bignum-len digits)
+			     ((= j res-len-1)
+                              (digit-bind (h l) (%bignum-ref bignum i)
+                                (digit-set (h l) (%ashr h l n-bits))
+			        (%bignum-set bignum j h l))
+			      (%normalize-bignum-buffer bignum res-len)))))))
+|#
+#|
+(defun bignum-buffer-ashift-right (bignum bignum-len x)
+  (declare (type bignum-index bignum-len) (fixnum x))
+  (multiple-value-bind (digits n-bits) (truncate x digit-size)
+    (declare (type bignum-index digits)(fixnum n-bits))
+    (macrolet ((clear-high-digits ()
+                 `(do* ((i (1- (the fixnum (%bignum-length bignum))) (1- i))
+                        (j digits (1- j)))
+                       ((= 0 j))
+                    (declare (fixnum i j))
+                    (%bignum-set bignum i 0 0))))
+      (cond
+       ((zerop n-bits)
+        (let* ((new-end (- bignum-len digits)))
+          (declare (fixnum new-end))
+          (bignum-replace bignum bignum :end1 new-end :start2 digits
+                          :end2 bignum-len)
+          (clear-high-digits)
+          (%normalize-bignum-buffer bignum new-end)))
+       (t
+        (let* ((res-len (- bignum-len digits))
+               (len-1 (1- res-len)))
+          (declare (fixnum res-len len-1))
+          (bignum-shift-right-loop-1 n-bits bignum bignum len-1 digits)
+          ; clear the old high order digits - assume always positive
+          ; (when (neq 0 digits)(push digits poof))
+          (clear-high-digits)
+          (%normalize-bignum-buffer bignum res-len)))))))
+|#
+
+ 
+
+;;; BIGNUM-ASHIFT-LEFT -- Public.
+;;;
+;;; This handles shifting a bignum buffer to provide fresh bignum data for some
+;;; internal routines.  We know bignum is safe when called with bignum-len.
+;;; First we compute the number of whole digits to shift, shifting them
+;;; starting to store farther along the result bignum.  If we shift on a digit
+;;; boundary (that is, n-bits is zero), then we just copy digits.  The last
+;;; branch handles the general case.
+;;;
+(defun bignum-ashift-left (bignum x &optional bignum-len)
+  (declare (type bignum-type bignum)
+	   (fixnum x)
+	   (type (or null bignum-index) bignum-len))
+  (multiple-value-bind (digits n-bits)
+		       (truncate x digit-size)
+    (declare (fixnum digits n-bits))
+    (let* ((bignum-len (or bignum-len (%bignum-length bignum)))
+	   (res-len (+ digits bignum-len 1)))
+      (declare (fixnum bignum-len res-len))
+      (when (> res-len maximum-bignum-length)
+	(error "Can't represent result of left shift."))
+      (if (zerop n-bits)
+        (bignum-ashift-left-digits bignum bignum-len digits)
+        (bignum-ashift-left-unaligned bignum digits n-bits res-len)))))
+
+;;; BIGNUM-ASHIFT-LEFT-DIGITS -- Internal.
+;;;
+(defun bignum-ashift-left-digits (bignum bignum-len digits)
+  (declare (type bignum-index bignum-len digits))
+  (let* ((res-len (+ bignum-len digits))
+	 (res (%allocate-bignum res-len)))
+    (declare (type bignum-index res-len))
+    (bignum-replace res bignum :start1 digits :end1 res-len :end2 bignum-len
+		    :from-end t)
+    res))
+
+;;; BIGNUM-ASHIFT-LEFT-UNALIGNED -- Internal.
+;;;
+;;; BIGNUM-TRUNCATE uses this to store into a bignum buffer by supplying res.
+;;; When res comes in non-nil, then this foregoes allocating a result, and it
+;;; normalizes the buffer instead of the would-be allocated result.
+;;;
+;;; We start storing into one digit higher than digits, storing a whole result
+;;; digit from parts of two contiguous digits from bignum.  When the loop
+;;; finishes, we store the remaining bits from bignum's first digit in the
+;;; first non-zero result digit, digits.  We also grab some left over high
+;;; bits from the last digit of bignum.
+;;;
+
+(defun bignum-ashift-left-unaligned (bignum digits n-bits res-len
+                                              &optional (res nil resp))
+  (declare (type bignum-index digits res-len)
+           (type (mod #.digit-size) n-bits))
+  (let* (;(remaining-bits (- digit-size n-bits))
+         (res-len-1 (1- res-len))
+         (res (or res (%allocate-bignum res-len))))
+    (declare (type bignum-index res-len res-len-1))
+    (bignum-shift-left-loop n-bits res bignum res-len-1 (the fixnum (1+ digits)))
+    ; if resp provided we don't care about returned value
+    (if (not resp) (%normalize-bignum-macro res))))
+
+
+
+
+
+;;;; Relational operators.
+
+
+
+;;; BIGNUM-COMPARE -- Public.
+;;;
+;;; This compares two bignums returning -1, 0, or 1, depending on whether a
+;;; is less than, equal to, or greater than b.
+;;;
+;(proclaim '(function bignum-compare (bignum bignum) (integer -1 1)))
+(defun bignum-compare (a b)
+  (declare (type bignum-type a b))
+  (let* ((a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (if (eq a-plusp b-plusp)
+      (let* ((len-a (%bignum-length a))
+	     (len-b (%bignum-length b)))
+	(declare (type bignum-index len-a len-b))
+	(cond ((= len-a len-b)
+	       (do* ((i (1- len-a) (1- i)))
+		    ((zerop i) (%compare-digits a b 0))
+		 (declare (fixnum i))
+		 (let* ((signum (%compare-digits a b i)))
+		   (declare (fixnum signum))
+		   (unless (zerop signum)
+		     (return signum)))))
+	      ((> len-a len-b)
+	       (if a-plusp 1 -1))
+	      (t (if a-plusp -1 1))))
+      (if a-plusp 1 -1))))
+
+
+
+
+
+
+
+;;;; Integer length and logcount
+
+
+(defun bignum-integer-length (big)
+  (the fixnum (- (the fixnum (ash (the fixnum (%bignum-length big)) 5))
+		 (the fixnum (%bignum-sign-bits big)))))
+
+; (not (zerop (logand integer1 integer2)
+
+(defun bignum-logtest (num1 num2)
+  (let* ((length1 (%bignum-length num1))
+         (length2 (%bignum-length num2))
+         (n1-minusp (bignum-minusp num1))
+         (n2-minusp (bignum-minusp num2)))
+    (declare (fixnum length1 length2))
+    (if (and n1-minusp n2-minusp) ; both neg, get out quick
+      T        
+      (let ((val (bignum-logtest-loop (min length1 length2) num1 num2)))
+                 #|(do* ((index 0 (1+ index)))
+	              ((= index (min length1 length2)) nil)
+                   ; maybe better to start from high end of shorter?
+                   (multiple-value-bind (hi1 lo1)(%bignum-ref num1 index)
+                     (multiple-value-bind (hi2 lo2)(%bignum-ref num2 index)
+                       (when (or (not (zerop (%ilogand hi1 hi2)))
+                                 (not (zerop (%ilogand lo1 lo2))))
+                         (return t)))))))|#
+        (or val
+            (when (not (eql length1 length2)) ; lengths same => value nil
+              (if (< length1 length2)
+                n1-minusp
+                n2-minusp)))))))
+
+
+
+(defun logtest-fix-big (fix big)
+  (declare (fixnum fix))
+  (if (eql 0 (the fixnum fix))
+    nil
+    (if (> (the fixnum fix) 0) 
+      (let ()
+        (multiple-value-bind (hi lo)(%bignum-ref big 0)
+          (declare (fixnum hi lo))
+          (or (not (zerop (logand fix lo)))
+              (not (zerop (logand (ash fix (- 16)) hi))))))
+      t)))
+
+
+(defun bignum-logcount (bignum)
+  (declare (type bignum-type bignum))
+  (let* ((length (%bignum-length bignum))
+	 (plusp (bignum-plusp bignum))
+	 (result 0))
+    (declare (type bignum-index length)
+	     (fixnum result))
+    (if plusp
+      (dotimes (index length result)
+	(incf result (the fixnum (%logcount bignum index))))
+      (dotimes (index length result)
+	(incf result (the fixnum (%logcount-complement bignum index)))))))
+
+
+
+;;;; Logical operations.
+
+;;; NOT.
+;;;
+
+;;; BIGNUM-LOGICAL-NOT -- Public.
+;;;
+(defun bignum-logical-not (a)
+  (declare (type bignum-type a))
+  (let* ((len (%bignum-length a))
+	 (res (%allocate-bignum len)))
+    (declare (type bignum-index len))
+    (dotimes (i len res)
+      (%bignum-lognot i a res))))
+
+
+
+
+;;; AND.
+;;;
+
+;;; BIGNUM-LOGICAL-AND -- Public.
+;;;
+(defun bignum-logical-and (a b)
+  (declare (type bignum-type a b))
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (declare (type bignum-index len-a len-b))
+    (cond
+      ((< len-a len-b)
+       (if a-plusp
+	 (logand-shorter-positive a len-a b (%allocate-bignum len-a))
+	 (logand-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
+      ((< len-b len-a)
+       (if b-plusp
+	 (logand-shorter-positive b len-b a (%allocate-bignum len-b))
+	 (logand-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
+      (t (logand-shorter-positive a len-a b (%allocate-bignum len-a))))))
+
+;;; LOGAND-SHORTER-POSITIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is positive.  Because this
+;;; is AND, we don't care about any bits longer than a's since its infinite 0
+;;; sign bits will mask the other bits out of b.  The result is len-a big.
+;;;
+(defun logand-shorter-positive (a len-a b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a))
+  (dotimes (i len-a)
+    (%bignum-logand i a b res))
+  (%normalize-bignum-macro res))
+
+;;; LOGAND-SHORTER-NEGATIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is negative.  Because this
+;;; is AND, we just copy any bits longer than a's since its infinite 1 sign
+;;; bits will include any bits from b.  The result is len-b big.
+;;;
+(defun logand-shorter-negative (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (%bignum-logand i a b res))
+  (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b)
+  (%normalize-bignum-macro res))
+
+
+
+;;;
+;;;
+;;; bignum-logandc2
+
+(defun bignum-logandc2 (a b)
+  (declare (type bignum-type a b))
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (declare (type bignum-index len-a len-b))
+    (cond
+     ((< len-a len-b)
+      (logandc2-shorter-any a len-a b len-b (if a-plusp (%allocate-bignum len-a) (%allocate-bignum len-b))))
+     ((< len-b len-a) ; b shorter 
+      (logandc1-shorter-any b len-b a len-a (if b-plusp (%allocate-bignum len-a)(%allocate-bignum len-b))))
+     (t (logandc2-shorter-any a len-a b len-b (%allocate-bignum len-a))))))
+
+(defun logandc2-shorter-any (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+           (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (%bignum-logandc2 i a b res))
+  (if (bignum-minusp a)
+    (do ((i len-a (1+ i)))
+          ((= i len-b))
+        (declare (type bignum-index i))
+        (digit-bind (h l) (%bignum-ref b i)
+          (%bignum-set res i (%ilognot h) (%ilognot l)))))
+  (%normalize-bignum-macro res))
+
+
+
+(defun logandc1-shorter-any (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+           (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (%bignum-logandc1 i a b res))
+  (if (bignum-plusp a)
+    (if (neq len-a len-b)
+      (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b)))
+  (%normalize-bignum-macro res))
+
+
+
+(defun fix-big-logand (fix big)
+  (let* ((len-b (%bignum-length big))
+         (res (if (< fix 0)(%allocate-bignum len-b))))
+    (declare (fixnum fix len-b))        
+    (let ((val (fix-digit-logand fix big res)))
+      (if res
+        (progn
+          (bignum-replace res big :start1 1 :start2 1 :end1 len-b :end2 len-b)
+          (%normalize-bignum-macro res))
+        val))))
+  
+
+(defun fix-big-logandc2 (fix big)
+  (let* ((len-b (%bignum-length big))
+         (res (if (< fix 0)(%allocate-bignum len-b))))
+    (declare (fixnum fix len-b))        
+    (let ((val (fix-digit-logandc2 fix big res)))
+      (if res
+        (progn
+          (do ((i 1 (1+ i)))
+              ((= i len-b))
+            (declare (type bignum-index i))
+            (digit-lognot-move i big res))
+          (%normalize-bignum-macro res))
+        val))))
+
+(defun fix-big-logandc1 (fix big)
+  (let* ((len-b (%bignum-length big))
+         (res (if (>= fix 0)(%allocate-bignum len-b))))
+    (declare (fixnum fix len-b))        
+    (let ((val (fix-digit-logandc1 fix big res)))
+      (if res
+        (progn  
+          (bignum-replace res big :start1 1 :start2 1 :end1 len-b :end2 len-b)
+          (%normalize-bignum-macro res))
+        val))))
+
+
+
+
+
+
+
+;;; IOR.
+;;;
+
+;;; BIGNUM-LOGICAL-IOR -- Public.
+;;;
+(defun bignum-logical-ior (a b)
+  (declare (type bignum-type a b))
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (declare (type bignum-index len-a len-b))
+    (cond
+     ((< len-a len-b)
+      (if a-plusp
+	  (logior-shorter-positive a len-a b len-b (%allocate-bignum len-b))
+	  (logior-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
+     ((< len-b len-a)
+      (if b-plusp
+	  (logior-shorter-positive b len-b a len-a (%allocate-bignum len-a))
+	  (logior-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
+     (t (logior-shorter-positive a len-a b len-b (%allocate-bignum len-a))))))
+
+;;; LOGIOR-SHORTER-POSITIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is positive.  Because this
+;;; is IOR, we don't care about any bits longer than a's since its infinite
+;;; 0 sign bits will mask the other bits out of b out to len-b.  The result
+;;; is len-b long.
+;;;
+(defun logior-shorter-positive (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (%bignum-logior i a b res))
+  (if (not (eql len-a len-b))
+    (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b))
+  (%normalize-bignum-macro res))
+
+;;; LOGIOR-SHORTER-NEGATIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is negative.  Because this
+;;; is IOR, we just copy any bits longer than a's since its infinite 1 sign
+;;; bits will include any bits from b.  The result is len-b long.
+;;;
+(defun logior-shorter-negative (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (%bignum-logior i a b res))
+  ; silly to propagate sign and then normalize it away
+  ; but may need to do at least once - but we are only normalizing from len-a?
+  ; ah but the sign needs to be correct
+  (do ((i len-a (1+ i)))
+      ((= i len-b))
+    (declare (type bignum-index i))
+    (%bignum-set res i #xffff #xffff))
+  (%normalize-bignum-macro res))
+
+
+
+
+;;; XOR.
+;;;
+
+;;; BIGNUM-LOGICAL-XOR -- Public.
+;;;
+(defun bignum-logical-xor (a b)
+  (declare (type bignum-type a b))
+  (let ((len-a (%bignum-length a))
+	(len-b (%bignum-length b)))
+    (declare (type bignum-index len-a len-b))
+    (if (< len-a len-b)
+	(bignum-logical-xor-aux a len-a b len-b (%allocate-bignum len-b))
+	(bignum-logical-xor-aux b len-b a len-a (%allocate-bignum len-a)))))
+
+;;; BIGNUM-LOGICAL-XOR-AUX -- Internal.
+;;;
+;;; This takes the the shorter of two bignums in a and len-a.  Res is len-b
+;;; long.  Do the XOR.
+;;;
+(defun bignum-logical-xor-aux (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (%bignum-logxor i a b res))
+  (unless (= len-a len-b)
+    (let ((sign (if (bignum-minusp a) #xffff 0)))
+      (do ((i len-a (1+ i)))
+          ((= i len-b))
+        (declare (type bignum-index i))
+        (digit-bind (h l) (%bignum-ref b i)
+          (%bignum-set res i (%ilogxor sign h)(%ilogxor sign l))))))
+  (%normalize-bignum-macro res))
+
+
+
+
+
+
+;;;; LDB (load byte)
+
+; [slh] 'twas all commented out - thank gawd
+
+
+
+;;;; TRUNCATE.
+
+;;; This is the original sketch of the algorithm from which I implemented this
+;;; TRUNCATE, assuming both operands are bignums.  I should modify this to work
+;;; with the documentation on my functions, as a general introduction.  I've
+;;; left this here just in case someone needs it in the future.  Don't look
+;;; at this unless reading the functions' comments leaves you at a loss.
+;;; Remember this comes from Knuth, so the book might give you the right general
+;;; overview.
+;;; 
+;;;
+;;; (truncate x y):
+;;;
+;;; If X's magnitude is less than Y's, then result is 0 with remainder X.
+;;;
+;;; Make x and y positive, copying x if it is already positive.
+;;;
+;;; Shift y left until there's a 1 in the 30'th bit (most significant, non-sign
+;;;       digit)
+;;;    Just do most sig digit to determine how much to shift whole number.
+;;; Shift x this much too.
+;;; Remember this initial shift count.
+;;;
+;;; Allocate q to be len-x minus len-y quantity plus 1.
+;;;
+;;; i = last digit of x.
+;;; k = last digit of q.
+;;;
+;;; LOOP
+;;;
+;;; j = last digit of y.
+;;;
+;;; compute guess.
+;;; if x[i] = y[j] then g = #xFFFFFFFF
+;;; else g = x[i]x[i-1]/y[j].
+;;;
+;;; check guess.
+;;; %UNSIGNED-MULTIPLY returns b and c defined below.
+;;;    a = x[i-1] - (logand (* g y[j]) #xFFFFFFFF).
+;;;       Use %UNSIGNED-MULTIPLY taking low-order result.
+;;;    b = (logand (ash (* g y[j-1]) -32) #xFFFFFFFF).
+;;;    c = (logand (* g y[j-1]) #xFFFFFFFF).
+;;; if a < b, okay.
+;;; if a > b, guess is too high
+;;;    g = g - 1; go back to "check guess".
+;;; if a = b and c > x[i-2], guess is too high
+;;;    g = g - 1; go back to "check guess".
+;;; GUESS IS 32-BIT NUMBER, SO USE THING TO KEEP IN SPECIAL REGISTER
+;;; SAME FOR A, B, AND C.
+;;;
+;;; Subtract g * y from x[i - len-y+1]..x[i].  See paper for doing this in step.
+;;; If x[i] < 0, guess is fucked.
+;;;    negative g, then add 1
+;;;    zero or positive g, then subtract 1
+;;; AND add y back into x[len-y+1..i].
+;;;
+;;; q[k] = g.
+;;; i = i - 1.
+;;; k = k - 1.
+;;;
+;;; If k>=0, goto LOOP.
+;;;
+;;;
+;;; Now quotient is good, but remainder is not.
+;;; Shift x right by saved initial left shifting count.
+;;;
+;;; Check quotient and remainder signs.
+;;; x pos y pos --> q pos r pos
+;;; x pos y neg --> q neg r pos
+;;; x neg y pos --> q neg r neg
+;;; x neg y neg --> q pos r neg
+;;;
+;;; Normalize quotient and remainder.  Cons result if necessary.
+;;;
+
+
+
+;;; These are used by BIGNUM-TRUNCATE and friends in the general case.
+;;;
+(defvar *truncate-x* nil)
+(defvar *truncate-y* nil)
+
+;;; BIGNUM-TRUNCATE -- Public.
+;;;
+;;; This divides x by y returning the quotient and remainder.  In the general
+;;; case, we shift y to setup for the algorithm, and we use two buffers to save
+;;; consing intermediate values.  X gets destructively modified to become the
+;;; remainder, and we have to shift it to account for the initial Y shift.
+;;; After we multiple bind q and r, we first fix up the signs and then return
+;;; the normalized results.
+;;;
+
+
+(defun bignum-truncate (x1 y1 &optional no-rem)
+  (declare (type bignum-type x1 y1))
+  (let* ((x-plusp (bignum-plusp x1))
+	 (y-plusp (bignum-plusp y1)))
+    (flet 
+      ((do-it (x y) 
+         (let* ((len-x (%bignum-length x))
+                (len-y (%bignum-length y)))
+           (declare (fixnum len-x len-y))
+           
+           (let ((c (bignum-compare y x)))
+             (cond 
+              ((eql c 1)  ; >
+               (return-from bignum-truncate (values 0 x1)))
+              ((eql c 0)(values 1 0))  ; =  might as well since did compare anyway
+              ((< len-y 2)
+               (multiple-value-bind (q r)
+                                    (bignum-truncate-single-digit x len-x y no-rem)
+                 (values q
+                         (unless no-rem
+                           (cond (x-plusp r)
+                                 ((typep r 'fixnum) (the fixnum (- (the fixnum r))))
+                                 (t (negate-bignum-in-place r)
+                                    (%normalize-bignum-macro r )))))))
+              (t
+               (let* ((len-x+1 (1+ len-x)))
+                 (declare (fixnum len-x+1))
+                 (with-bignum-buffers ((*truncate-x* len-x+1)
+                                       (*truncate-y* (the fixnum (1+ len-y))))
+                   (let ((y-shift (shift-y-for-truncate y)))
+                     (shift-and-store-truncate-buffers x len-x y len-y y-shift)
+                     (values (do-truncate len-x+1 len-y)
+                             ;; DO-TRUNCATE must execute first.
+                             (when (not no-rem)                               
+                               (when (not (eql 0 y-shift))                                  
+                                 (let* ((res-len-1 (1- len-y)))
+                                   (declare (fixnum res-len-1))
+                                   (bignum-shift-right-loop-1 y-shift *truncate-x* *truncate-x* res-len-1 0)))                                
+                               (let ((the-res (%normalize-bignum-macro *truncate-x* )))
+                                 (if (not (fixnump the-res))
+                                   (if x-plusp (copy-bignum the-res) (negate-bignum the-res))
+                                   (if x-plusp the-res (the fixnum (- (the fixnum the-res)))))
+                                     ))))))))))))
+      (multiple-value-bind (q r)(with-negated-bignum-buffers x1 y1 do-it)
+        (let ((quotient (cond ((eq x-plusp y-plusp) q)
+                              ((typep q 'fixnum) (the fixnum (- (the fixnum q))))
+                              (t (negate-bignum-in-place q)
+                                 (%normalize-bignum-macro q )))))
+          (if no-rem
+            quotient            
+            (values quotient r)))))))
+
+(defun bignum-rem (x1 y1)
+  (declare (type bignum-type x1 y1))  
+  (let* ((x-plusp (bignum-plusp x1)))
+    (flet 
+      ((do-it (x y) 
+         (let* ((len-x (%bignum-length x))
+                (len-y (%bignum-length y)))
+           (declare (fixnum len-x len-y))           
+           (let ((c (bignum-compare y x)))
+             (cond 
+              ((eql c 1) (return-from bignum-rem x1))
+              ((eql c 0) 0)  ; =  might as well since did compare anyway
+              ((< len-y 2)
+               (let ((r (bignum-truncate-single-digit-no-quo x len-x y)))  ; phooey 
+                 (cond (x-plusp r)
+                       ((typep r 'fixnum) (the fixnum (- (the fixnum r))))
+                       (t (negate-bignum-in-place r)
+                          (%normalize-bignum-macro r )))))
+              (t
+               (let* ((len-x+1 (1+ len-x)))
+                 (declare (fixnum len-x+1))
+                 (with-bignum-buffers ((*truncate-x* len-x+1)
+                                       (*truncate-y* (the fixnum (1+ len-y))))
+                   (let ((y-shift (shift-y-for-truncate y)))
+                     (shift-and-store-truncate-buffers x len-x y len-y y-shift)
+                     (do-truncate-no-quo len-x+1 len-y)
+                     (when (not (eql 0 y-shift))                                 
+                       (let* ((res-len-1 (1- len-y)))
+                         (declare (fixnum res-len-1))
+                         (bignum-shift-right-loop-1 y-shift *truncate-x* *truncate-x* res-len-1 0)))
+                     (let ((the-res (%normalize-bignum-macro *truncate-x*)))
+                       (if (not (fixnump the-res))
+                         (if x-plusp (copy-bignum the-res) (negate-bignum the-res))
+                         (if x-plusp the-res (the fixnum (- (the fixnum the-res)))))))))))))))
+      (declare (dynamic-extent #'do-it))
+      (with-negated-bignum-buffers x1 y1 do-it))))
+
+
+
+;;; BIGNUM-TRUNCATE-SINGLE-DIGIT -- Internal.
+;;;
+;;; This divides x by y when y is a single bignum digit.  BIGNUM-TRUNCATE fixes
+;;; up the quotient and remainder with respect to sign and normalization.
+;;;
+;;; We don't have to worry about shifting y to make its most significant digit
+;;; sufficiently large for %FLOOR to return 32-bit quantities for the q-digit
+;;; and r-digit.  If y is a single digit bignum, it is already large enough
+;;; for %FLOOR.  That is, it has some bits on pretty high in the digit.
+;;;
+;;; x is positive
+(defun bignum-truncate-single-digit (x len-x y &optional no-rem)
+  (declare (type bignum-index len-x))
+  (let* ((maybe-q (%allocate-bignum 2))
+         (q (if (<= len-x 2) maybe-q (%allocate-bignum len-x)))
+	 (r-h 0)
+         (r-l 0))
+    (declare (dynamic-extent maybe-q))
+    (digit-bind (y-h y-l) (%bignum-ref y 0)
+      (multiple-value-setq (r-h r-l)(%floor-loop-quo x q y-h y-l))      
+      (if (eq q maybe-q)
+        (progn 
+          (setq q (%normalize-bignum-macro q))
+          (if (not (fixnump q)) (setq q (copy-bignum q))))
+        (setq q (%normalize-bignum-macro q )))
+      ;; might as well make a fixnum if possible
+      (if no-rem
+        q
+        (if (> (%digits-sign-bits r-h r-l)  target::fixnumshift)
+          (values q (%ilogior (%ilsl 16 r-h) r-l))
+          (let ((rem (%allocate-bignum 1)))
+            (%bignum-set rem 0 r-h r-l)
+            (values q rem)))))))
+
+;;; aka rem
+(defun bignum-truncate-single-digit-no-quo (x len-x y)
+  (declare (type bignum-index len-x))
+  (declare (ignore len-x))
+  (let (;(q (%allocate-bignum len-x))
+	(r-h 0)
+        (r-l 0))
+    (progn
+      (digit-bind (y-h y-l) (%bignum-ref y 0)
+        (multiple-value-setq (r-h r-l)(%floor-loop-no-quo x y-h y-l))
+        ; might as well make a fixnum if possible
+        (if (> (%digits-sign-bits r-h r-l)  target::fixnumshift)
+          (%ilogior (%ilsl 16 r-h) r-l)
+          (let ((rem (%allocate-bignum 1)))
+            (%bignum-set rem 0 r-h r-l)
+            rem))))))
+
+;; so big deal - we save a one digit bignum for y 
+;; and bigger deal if x is negative - we copy or negate x, computing result destructively
+;;  - thus avoiding making a negated x in addition to result
+;; 
+(defun bignum-truncate-by-fixnum (x y)
+  (declare (fixnum y))
+  (when (eql y 0)(error (make-condition 'division-by-zero :operation 'truncate :operands (list x y))))
+  (let* ((len-x (%bignum-length x))
+         (x-minus (bignum-minusp x))
+         (maybe-q (%allocate-bignum 3))
+         (q (if x-minus
+              (if (<= len-x 2)
+                (dotimes (i 3 (negate-bignum-in-place maybe-q))
+                  (if (< i len-x)
+                    (multiple-value-bind (hi lo) (%bignum-ref x i)
+                      (%bignum-set maybe-q i hi lo))
+                    (%bignum-set maybe-q i 65535 65535)))
+                (negate-bignum x))
+              (if (<= len-x 2) ; this was broken if negative because bignum-replace just copies min len-a len-b digits
+                (progn
+                  (bignum-replace maybe-q x)                
+                  maybe-q)
+                (%allocate-bignum len-x))))      ;  q is new big or -x
+         ;(len-q (%bignum-length q))
+         (y-minus (minusp y))         
+         (y (if y-minus (- y) y)))
+    (declare (fixnum y))
+    (declare (type bignum-index len-x))
+    (declare (dynamic-extent maybe-q))
+    (let* ((r-h 0)
+           (r-l 0)
+           (y-h (%ilogand #xffff (%iasr 16 y)))
+           (y-l (%ilogand #xffff y)))
+      (multiple-value-setq (r-h r-l)(%floor-loop-quo (if x-minus q x) q y-h y-l))      
+      (let* ((r (%ilogior (%ilsl 16 r-h) r-l)))
+        (declare (fixnum r))
+        (when (neq x-minus y-minus)(negate-bignum-in-place q))
+        (setq q (%normalize-bignum-macro q ))
+        (values (if (eq q maybe-q) (copy-bignum q) q)
+                (if x-minus (the fixnum (- r)) r))))))
+
+(defun bignum-truncate-by-fixnum-no-quo (x y)
+  (declare (fixnum y))
+  (when (eql y 0)(error (make-condition 'division-by-zero :operation 'truncate :operands (list x Y))))
+  (let* ((len-x (%bignum-length x))
+         (x-minus (bignum-minusp x))
+         (y-minus (minusp y))         
+         (y (if y-minus (- y) y)))
+    (declare (fixnum y))
+    (declare (type bignum-index len-x))
+      (let* (;(LEN-Q (%BIGNUM-LENGTH Q))
+             (r-h 0)
+             (r-l 0)
+             (y-h (%ilogand #xffff (%iasr 16 y)))
+             (y-l (%ilogand #xffff y)))
+        (if x-minus
+          (with-bignum-buffers ((q (the fixnum (1+ len-x))))
+            (negate-bignum x nil q)
+            (multiple-value-setq (r-h r-l)(%floor-loop-no-quo q y-h y-l)))
+          (multiple-value-setq (r-h r-l)(%floor-loop-no-quo x y-h y-l)))        
+        (let* ((r (%ilogior (%ilsl 16 r-h) r-l)))
+          (declare (fixnum r))
+          (if x-minus (the fixnum (- r)) r)))))
+
+
+;;; DO-TRUNCATE -- Internal.
+;;;
+;;; This divides *truncate-x* by *truncate-y*, and len-x and len-y tell us how
+;;; much of the buffers we care about.  TRY-BIGNUM-TRUNCATE-GUESS modifies
+;;; *truncate-x* on each interation, and this buffer becomes our remainder.
+;;;
+;;; *truncate-x* definitely has at least three digits, and it has one more than
+;;; *truncate-y*.  This keeps i, i-1, i-2, and low-x-digit happy.  Thanks to
+;;; SHIFT-AND-STORE-TRUNCATE-BUFFERS.
+;;;
+
+
+(defun do-truncate (len-x len-y)
+  (declare (type bignum-index len-x len-y))
+  (let* ((len-q (- len-x len-y))
+	 ;; Add one for extra sign digit in case high bit is on.
+         (len-res (1+ len-q))
+         (maybe-q (%allocate-bignum 2))         
+	 (q (if (<= len-res 2) maybe-q (%allocate-bignum len-res)))
+	 (k (1- len-q))
+	 (i (1- len-x))
+	 (low-x-digit (- i len-y)))
+    (declare (type bignum-index len-q len-res k i  low-x-digit))
+    (declare (dynamic-extent maybe-q))
+    (loop
+      (digit-bind (h l)
+                  (digit-bind (guess-h guess-l)
+                              (bignum-truncate-guess-2 *truncate-x* i *truncate-y* (the fixnum (1- len-y)))                                  
+                    (try-bignum-truncate-guess guess-h guess-l len-y low-x-digit))
+        (%bignum-set q k h l))
+      (cond ((zerop k) (return))
+            (t (decf k)
+               (decf low-x-digit)
+               (setq i (1- i)))))
+    (if (eq q maybe-q)
+      (progn 
+        (setq q (%normalize-bignum-macro q))
+        (if (fixnump q) q (copy-bignum q)))
+      (%normalize-bignum-macro q))))
+
+(defun do-truncate-no-quo (len-x len-y)
+  (declare (type bignum-index len-x len-y))
+  (let* ((len-q (- len-x len-y))
+	 (k (1- len-q))
+	 (i (1- len-x))
+	 (low-x-digit (- i len-y)))
+    (declare (type bignum-index len-q k i  low-x-digit))
+    (loop
+      (digit-bind (guess-h guess-l) (bignum-truncate-guess-2 *truncate-x* i *truncate-y* (the fixnum (1- len-y)))                                 
+        (try-bignum-truncate-guess guess-h guess-l len-y low-x-digit)
+        (cond ((zerop k) (return))
+              (t (decf k)
+                 (decf low-x-digit)
+                 (setq i (1- i))))))
+    nil))
+
+;;; TRY-BIGNUM-TRUNCATE-GUESS -- Internal.
+;;;
+;;; This takes a digit guess, multiplies it by *truncate-y* for a result one
+;;; greater in length than len-y, and subtracts this result from *truncate-x*.
+;;; Low-x-digit is the first digit of x to start the subtraction, and we know x
+;;; is long enough to subtract a len-y plus one length bignum from it.  Next we
+;;; check the result of the subtraction, and if the high digit in x became
+;;; negative, then our guess was one too big.  In this case, return one less
+;;; than guess passed in, and add one value of y back into x to account for
+;;; subtracting one too many.  Knuth shows that the guess is wrong on the order
+;;; of 3/b, where b is the base (2 to the digit-size power) -- pretty rarely.
+;;;
+
+(defun try-bignum-truncate-guess (guess-h guess-l len-y low-x-digit)
+  (declare (type bignum-index low-x-digit len-y))
+
+  (let ((carry-digit-h 0)
+        (carry-digit-l 0)
+	(borrow 1)
+	(i low-x-digit))
+    (declare (type bignum-index i)
+	     (fixnum borrow carry-digit-h carry-digit-l))
+    ;; Multiply guess and divisor, subtracting from dividend simultaneously.
+    (dotimes (j len-y)
+      (multiple-value-bind (y-h y-l) (%bignum-ref *truncate-y* j)
+	(multiple-value-bind (high-h high-l low-h low-l)
+	    (%multiply-and-add-1 guess-h
+			       guess-l
+			       y-h
+			       y-l
+			       carry-digit-h
+			       carry-digit-l)
+	  (setq carry-digit-h high-h
+		carry-digit-l high-l)
+	  (multiple-value-bind (tx-h tx-l) (%bignum-ref *truncate-x* i)
+	    (multiple-value-bind (x-h x-l temp-borrow)
+		(%subtract-with-borrow-1 tx-h tx-l low-h low-l borrow)
+	      (%bignum-set *truncate-x* i x-h x-l)
+	      (setq borrow temp-borrow)))))
+      (incf i))
+    (multiple-value-bind (tx-h tx-l) (%bignum-ref *truncate-x* i)
+      (multiple-value-bind (x-h x-l)
+	  (%subtract-with-borrow-1 tx-h tx-l carry-digit-h carry-digit-l borrow)
+	(%bignum-set *truncate-x* i x-h x-l)))
+    ;; See if guess is off by one, adding one Y back in if necessary.
+
+
+    (cond ((%digit-0-or-plusp *truncate-x* i)
+	   (values guess-h guess-l))
+	  (t
+	   ;; If subtraction has negative result, add one divisor value back
+	   ;; in.  The guess was one too large in magnitude.
+           ;; hmm - happens about 1.6% of the time
+           (bignum-add-loop-+ low-x-digit *truncate-x* *truncate-y* len-y)
+           (%subtract-one guess-h guess-l)
+	   ;(%subtract-with-borrow guess-h guess-l 0 1 1)
+           ))))
+
+
+
+;;; BIGNUM-TRUNCATE-GUESS -- Internal.
+;;;
+;;; This returns a guess for the next division step.  Y1 is the highest y
+;;; digit, and y2 is the second to highest y digit.  The x... variables are
+;;; the three highest x digits for the next division step.
+;;;
+;;; From Knuth, our guess is either all ones or x-i and x-i-1 divided by y1,
+;;; depending on whether x-i and y1 are the same.  We test this guess by
+;;; determining whether guess*y2 is greater than the three high digits of x
+;;; minus guess*y1 shifted left one digit:
+;;;    ------------------------------
+;;;   |    x-i    |   x-i-1  | x-i-2 |
+;;;    ------------------------------
+;;;    ------------------------------
+;;; - | g*y1 high | g*y1 low |   0   |
+;;;    ------------------------------
+;;;                ...                   <   guess*y2     ???
+;;; If guess*y2 is greater, then we decrement our guess by one and try again.
+;;; This returns a guess that is either correct or one too large.
+;;;
+;;; the y's come from *truncate-y*, x's from *truncate-x*
+;;; doing this in lap is not screamingly difficult - x's at i, i-1, i-2
+
+
+
+
+
+(defun bignum-truncate-guess-2 (x xidx y yidx)
+  (digit-bind (guess-h guess-l)
+              (%floor-99 x xidx y yidx)
+    (truncate-guess-loop guess-h guess-l x xidx y yidx)))
+
+
+
+    
+
+;;; SHIFT-Y-FOR-TRUNCATE -- Internal.
+;;;
+;;; This returns the amount to shift y to place a one in the second highest
+;;; bit.  Y must be positive.  If the last digit of y is zero, then y has a
+;;; one in the previous digit's sign bit, so we know it will take one less
+;;; than digit-size to get a one where we want.  Otherwise, we count how many
+;;; right shifts it takes to get zero; subtracting this value from digit-size
+;;; tells us how many high zeros there are which is one more than the shift
+;;; amount sought.
+;;;
+;;; Note: This is exactly the same as one less than the integer-length of the
+;;; last digit subtracted from the digit-size.
+;;; 
+;;; We shift y to make it sufficiently large that doing the 64-bit by 32-bit
+;;; %FLOOR calls ensures the quotient and remainder fit in 32-bits.
+;;;
+(defun shift-y-for-truncate (y)
+  (the fixnum (1- (the fixnum (%bignum-sign-bits y)))))
+
+;;; SHIFT-AND-STORE-TRUNCATE-BUFFERS -- Internal.
+;;;
+;;; Stores two bignums into the truncation bignum buffers, shifting them on the
+;;; way in.  This assumes x and y are positive and at least two in length, and
+;;; it assumes *truncate-x* and *truncate-y* are one digit longer than x and y.
+;;;
+(defun shift-and-store-truncate-buffers (x len-x y len-y shift)
+  (declare (type bignum-index len-x len-y)
+	   (type (integer 0 (#.digit-size)) shift))
+  (cond ((eql 0 shift)
+	 (bignum-replace *truncate-x* x :end1 len-x)
+	 (bignum-replace *truncate-y* y :end1 len-y))
+	(t
+	 (bignum-ashift-left-unaligned x 0 shift (the fixnum (1+ len-x)) *truncate-x*)
+	 (bignum-ashift-left-unaligned y 0 shift (the fixnum (1+ len-y)) *truncate-y*))))
+
+
+
+
+
+;;;; General utilities.
+
+
+;;; %NORMALIZE-BIGNUM-BUFFER -- Internal.
+;;;
+;;; Internal in-place operations use this to fixup remaining digits in the
+;;; incoming data, such as in-place shifting.  This is basically the same as
+;;; the first form in %NORMALIZE-BIGNUM, but we return the length of the buffer
+;;; instead of shrinking the bignum.
+;;;
+
+
+
+    
+
+
+
+
+;;; %NORMALIZE-BIGNUM -- Internal.
+;;;
+;;; This drops the last digit if it is unnecessary sign information.  It
+;;; repeats this as needed, possibly ending with a fixnum.  If the resulting
+;;; length from shrinking is one, see if our one word is a fixnum.  Shift the
+;;; possible fixnum bits completely out of the word, and compare this with
+;;; shifting the sign bit all the way through.  If the bits are all 1's or 0's
+;;; in both words, then there are just sign bits between the fixnum bits and
+;;; the sign bit.  If we do have a fixnum, shift it over for the two low-tag
+;;; bits.
+;;;
+
+(defun %normalize-bignum (res)
+  ;(declare (optimize (speed 3)(safety 0)))
+  (%normalize-bignum-2 t res))
+
+;;; %MOSTLY-NORMALIZE-BIGNUM -- Internal.
+;;;
+;;; This drops the last digit if it is unnecessary sign information.  It
+;;; repeats this as needed, possibly ending with a fixnum magnitude but never
+;;; returning a fixnum.
+;;;
+
+(defun %mostly-normalize-bignum (res &optional len)
+  (declare (ignore len))
+  (%normalize-bignum-2 nil res))
+
+
+
+
+; think its ok
+(defun ldb32 (hi-data lo-data size pos)
+  (declare (fixnum hi-data lo-data size pos))
+  (let* ((hi-bit (+ pos size))
+         (mask (%i- (%ilsl size 1) 1)))
+    (declare (fixnum hi-bit mask))    
+    (%ilogand mask (if (< hi-bit 16)
+                     (%iasr pos lo-data)
+                     (if (>= pos 16)
+                       (%ilsr (the fixnum (- pos 16)) hi-data)
+                       (%ilogior 
+                         (%iasr pos lo-data)
+                         (%ilsl (the fixnum (- 16 pos)) hi-data)))))))
+
+
+
+
+
+; this was wrong for negative bigs when byte includes or exceeds sign
+(defun %ldb-fixnum-from-bignum (bignum size position)
+  (declare (fixnum size position))
+  (let* ((low-idx (ash position -5))
+         (low-bit (logand position 31))
+         (hi-bit (+ low-bit size))
+         (len (%bignum-length bignum))
+         (minusp (bignum-minusp bignum)))
+    (declare (fixnum size position low-bit hi-bit low-idx len))
+    (if (>= low-idx len)
+      (if minusp (1- (ash 1 size)) 0)      
+      (multiple-value-bind (hi lo)(%bignum-ref bignum low-idx)
+        (let ((chunk-lo (ldb32 hi lo (min size (%i- 32 low-bit)) low-bit)))
+          (let ((val
+                 (if (< hi-bit 32) 
+                   chunk-lo
+                   (progn
+                     (setq low-idx (1+ low-idx))
+                     (multiple-value-setq (hi lo)
+                       (if (>= low-idx len)
+                         (if minusp (values #xffff #xffff)(values 0 0))
+                         (%bignum-ref bignum low-idx)))
+                     (let ((chunk-hi (ldb32 hi lo (%i- size (%i- 32 low-bit)) 0)))
+                       (%ilogior (ash chunk-hi (%i- 32 low-bit)) chunk-lo))))))
+            val))))))
+
+(defun load-byte (size position integer)
+  (if (and (bignump integer)
+           (<= size (- 31 target::fixnumshift))
+           (fixnump position))
+    (%ldb-fixnum-from-bignum integer size position)
+    (let ((mask (byte-mask size)))
+      (if (and (fixnump mask) (fixnump integer)(fixnump position))
+        (%ilogand mask (%iasr position integer))
+        (logand mask (ash integer (- position)))))))    
+
+
+#+safe-but-slow
+(defun %bignum-bignum-gcd (u v)
+  (setq u (abs u) v (abs v))
+  (do* ((g 1 (ash g 1)))
+       ((or (oddp u) (oddp v))
+	(do* ()
+	     ((zerop u) (* g v))
+	  (cond ((evenp u) (setq u (ash u -1)))
+		((evenp v) (setq v (ash v -1)))
+		(t (let* ((temp (ash (abs (- u v)) -1)))
+		     (if (< u v)
+		       (setq v temp)
+		       (setq u temp)))))))
+    (setq u (ash u -1) v (ash v -1))))
+
+
+(defun %positive-bignum-bignum-gcd (u0 v0)
+  (let* ((u-len (%bignum-length u0))
+	 (v-len (%bignum-length v0)))
+    (declare (fixnum u-len v-len))
+    (if (or (< u-len v-len)
+	    (and (= u-len v-len)
+		 (< (bignum-compare u0 v0) 0)))
+      (psetq u0 v0 v0 u0 u-len v-len v-len u-len))
+    (with-bignum-buffers ((u u-len)
+			  (u2 u-len)
+			  (v v-len)
+			  (v2 v-len))
+      (bignum-replace u u0)
+      (bignum-replace v v0)
+      (let* ((u-trailing-0-bits (%bignum-count-trailing-zero-bits u))
+	     (u-trailing-0-digits (ash u-trailing-0-bits -5))
+	     (v-trailing-0-bits (%bignum-count-trailing-zero-bits v))
+	     (v-trailing-0-digits (ash v-trailing-0-bits -5)))
+	(declare (fixnum u-trailing-0-bits v-trailing-0-bits))
+	(unless (zerop u-trailing-0-bits)
+	  (bignum-shift-right-loop-1
+	   (logand u-trailing-0-bits 31)
+	   u2
+	   u
+	   (the fixnum (1- (the fixnum (- u-len u-trailing-0-digits ))))
+	   u-trailing-0-digits)
+	  (rotatef u u2)
+	  (%mostly-normalize-bignum-macro u)
+	  (setq u-len (%bignum-length u)))
+	(unless (zerop v-trailing-0-bits)
+	  (bignum-shift-right-loop-1
+	   (logand v-trailing-0-bits 31)
+	   v2
+	   v
+	   (the fixnum (1- (the fixnum (- v-len v-trailing-0-digits))))
+	   v-trailing-0-digits)
+	  (rotatef v v2)
+	  (%mostly-normalize-bignum-macro v)
+	  (setq v-len (%bignum-length v)))
+	(let* ((shift (min u-trailing-0-bits
+			   v-trailing-0-bits)))
+	  (loop
+            (let* ((fix-u (and (= u-len 1)
+                               (let* ((hi-u (%bignum-ref-hi u 0)))
+                                 (declare (fixnum hi-u))
+                                 (= hi-u (the fixnum
+                                           (logand hi-u (ash target::target-most-positive-fixnum -16)))))
+                               (uvref u 0)))
+                   (fix-v (and (= v-len 1)
+                               (let* ((hi-v (%bignum-ref-hi v 0)))
+                                 (declare (fixnum hi-v))
+                                 (= hi-v (the fixnum
+                                           (logand hi-v (ash target::target-most-positive-fixnum -16)))))
+                               (uvref v 0))))
+              (if fix-v
+                (if fix-u
+                  (return (ash (%fixnum-gcd fix-u fix-v) shift))
+                  (return (ash (bignum-fixnum-gcd u fix-v) shift)))
+                (if fix-u
+                  (return (ash (bignum-fixnum-gcd v fix-u) shift)))))
+	      
+            (let* ((signum (if (> u-len v-len)
+                             1
+                             (if (< u-len v-len)
+                               -1
+                               (bignum-compare u v)))))
+              (declare (fixnum signum))
+              (case signum
+                (0			; (= u v)
+                 (if (zerop shift)
+                   (let* ((copy (%allocate-bignum u-len)))
+                     (bignum-replace copy u)
+                     (return copy))
+                   (return (ash u shift))))
+                (1			; (> u v)
+                 (bignum-subtract-loop u u-len v v-len u)
+                 (%mostly-normalize-bignum-macro u)
+                 (setq u-len (%bignum-length u))
+                 (setq u-trailing-0-bits
+                       (%bignum-count-trailing-zero-bits u)
+                       u-trailing-0-digits
+                       (ash u-trailing-0-bits -5))
+                 (unless (zerop u-trailing-0-bits)
+		   (%init-misc 0 u2)
+		   (bignum-shift-right-loop-1
+		    (logand u-trailing-0-bits 31)
+		    u2
+		    u
+		    (the fixnum (1- (the fixnum (- u-len
+						   u-trailing-0-digits))))
+		    u-trailing-0-digits)
+		   (rotatef u u2)
+		   (%mostly-normalize-bignum-macro u)
+		   (setq u-len (%bignum-length u))))
+                (t			; (> v u)
+                 (bignum-subtract-loop v v-len u u-len v)
+                 (%mostly-normalize-bignum-macro v)
+                 (setq v-len (%bignum-length v))
+                 (setq v-trailing-0-bits
+                       (%bignum-count-trailing-zero-bits v)
+                       v-trailing-0-digits
+                       (ash v-trailing-0-bits -5))
+                 (unless (zerop v-trailing-0-bits)
+		   (%init-misc 0 v2)
+		   (bignum-shift-right-loop-1
+		    (logand v-trailing-0-bits 31)
+		    v2
+		    v
+		    (the fixnum (1- (the fixnum (- v-len v-trailing-0-digits))))
+		    v-trailing-0-digits)
+		   (rotatef v v2)
+		   (%mostly-normalize-bignum-macro v)
+		   (setq v-len (%bignum-length v))))))))))))
+
+(defun %bignum-bignum-gcd (u v)
+  (with-negated-bignum-buffers u v %positive-bignum-bignum-gcd))
+
+(defun unsignedwide->integer (uwidep)
+  (with-bignum-buffers ((b 3))
+    (setf (uvref b 0) (%get-unsigned-long uwidep 4)
+	  (uvref b 1) (%get-unsigned-long uwidep 0))
+    (let* ((n (%normalize-bignum b)))
+      (if (typep n 'bignum)
+        (copy-bignum n)
+        n))))
+
+(defun one-bignum-factor-of-two (a)  
+  (declare (type bignum-type a))
+  (let ((len (%bignum-length a)))
+    (declare (fixnum len))
+    (dotimes (i len)
+      (multiple-value-bind (a-h a-l) (%bignum-ref a i)
+        (declare (fixnum a-h a-l))
+        (unless (and (= a-h 0)(= a-l 0))
+          (return (+ (%ilsl 5 i)
+                     (let* ((j 0)
+                            (a a-l))
+                       (declare (fixnum a j))
+                       (if (= a-l 0) (setq j 16 a a-h))
+                       (dotimes (i 16)            
+                         (if (oddp a)
+                           (return (%i+ j i))
+                           (setq a (%iasr 1 a))))))))))))
+
+(defun logbitp (index integer)
+  "Predicate returns T if bit index of integer is a 1."
+  (number-case index
+    (fixnum
+     (if (minusp (the fixnum index))(report-bad-arg index '(integer 0))))
+    (bignum
+     ;; assuming bignum cant have more than most-positive-fixnum bits
+     ;; (2 expt 24 longs)
+     (if (bignum-minusp index)(report-bad-arg index '(integer 0)))
+     ;; should error if integer isn't
+     (return-from logbitp (minusp (require-type integer 'integer)))))
+  (number-case integer
+    (fixnum
+     (if (%i< index (- target::nbits-in-word target::fixnumshift))
+       (%ilogbitp index integer)
+       (minusp (the fixnum integer))))
+    (bignum
+     (let ((bidx (%iasr 5 index))
+           (bbit (%ilogand index 31)))
+       (declare (fixnum bidx bbit))
+       (if (>= bidx (%bignum-length integer))
+         (bignum-minusp integer)
+         (multiple-value-bind (hi lo) (%bignum-ref integer bidx)
+           (declare (fixnum hi lo))
+           (if (> bbit 15)
+             (%ilogbitp (%i- bbit 16) hi)
+             (%ilogbitp bbit lo))))))))
+
+) ; #+32-bit-target
Index: /branches/new-random/level-0/l0-bignum64.lisp
===================================================================
--- /branches/new-random/level-0/l0-bignum64.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-bignum64.lisp	(revision 13309)
@@ -0,0 +1,2264 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+#+64-bit-target
+(eval-when (:compile-toplevel :execute)
+  (require "ARCH")
+  (require "NUMBER-MACROS")
+  (require "NUMBER-CASE-MACRO")
+
+  (defsetf bignum-ref bignum-set)
+  
+  (defconstant digit-size 32)
+  (defconstant half-digit-size (/ digit-size 2))
+  
+  (defconstant maximum-bignum-length (1- (ash 1 56)))
+  (defconstant all-ones-digit #xffffffff)
+  (deftype bignum-index () `(integer 0 (,maximum-bignum-length)))
+  (deftype bignum-element-type () `(unsigned-byte ,digit-size))
+  (deftype bignum-half-element-type () `(unsigned-byte ,half-digit-size))
+  (deftype bignum-type () 'bignum)
+  (defmacro %normalize-bignum-macro (big)
+    `(%normalize-bignum-2 t ,big))
+
+  (defmacro %mostly-normalize-bignum-macro (big)
+    `(%normalize-bignum-2 nil ,big))
+  (defmacro %lognot (x)
+    `(logand #xffffffff (lognot (the fixnum ,x))))
+  (defmacro %logior (x y)
+    `(logior (the fixnum ,x) (the fixnum ,y)))
+  (defmacro %logxor (x y)
+    `(logand #xffffffff (logxor (the fixnum ,x) (the fixnum ,y))))
+  
+  ;;; BIGNUM-REPLACE -- Internal.
+  ;;;
+  (defmacro bignum-replace (dest src &key (start1 '0) end1 (start2 '0) end2
+                                 from-end)
+    (once-only ((n-dest dest)
+                (n-src src))
+               (if (and (eq start1 0)(eq start2 0)(null end1)(null end2)(null from-end))
+                 ;; this is all true for some uses today <<
+                 `(%copy-ivector-to-ivector ,n-src 0 ,n-dest 0 (%ilsl 2 (min (the fixnum (%bignum-length ,n-src))
+                                                                         (the fixnum (%bignum-length ,n-dest)))))
+                 (let* ((n-start1 (gensym))
+                        (n-end1 (gensym))
+                        (n-start2 (gensym))
+                        (n-end2 (gensym)))
+                   `(let ((,n-start1 ,start1)
+                          (,n-start2 ,start2)
+                          (,n-end1 ,(or end1 `(%bignum-length ,n-dest)))
+                          (,n-end2 ,(or end2 `(%bignum-length ,n-src))))
+                     ,(if (null from-end)            
+                          `(%copy-ivector-to-ivector
+                            ,n-src (%i* 4 ,n-start2) 
+                            ,n-dest (%i* 4 ,n-start1)
+                            (%i* 4 (min (%i- ,n-end2 ,n-start2) 
+                                    (%i- ,n-end1 ,n-start1))))
+                          `(let ((nwds (min (%i- ,n-end2 ,n-start2)
+                                            (%i- ,n-end1 ,n-start1))))
+                            (%copy-ivector-to-ivector
+                             ,n-src (%ilsl 2 (%i- ,n-end2 nwds))
+                             ,n-dest (%ilsl 2 (%i- ,n-end1 nwds))
+                             (%i* 4 nwds))))))))) 
+  
+
+  ;;;; Shifting.
+  
+  (defconstant all-ones-half-digit #xFFFF)  
+  
+
+;;; %ALLOCATE-BIGNUM must zero all elements.
+;;;
+  (defmacro %allocate-bignum (ndigits)
+    `(%alloc-misc ,ndigits target::subtag-bignum))
+
+  (declaim (inline  %bignum-length))
+
+;;; This macro is used by BIGNUM-ASHIFT-RIGHT,
+;;; BIGNUM-BUFFER-ASHIFT-RIGHT, and BIGNUM-LDB-BIGNUM-RES. They supply
+;;; a termination form that references locals established by this
+;;; form. Source is the source bignum. Start-digit is the first digit
+;;; in source from which we pull bits. Start-pos is the first bit we
+;;; want. Res-len-form is the form that computes the length of the
+;;; resulting bignum. Termination is a DO termination form with a test
+;;; and body. When result is supplied, it is the variable to which
+;;; this binds a newly allocated bignum.
+;;;
+;;; Given start-pos, 1-31 inclusively, of shift, we form the j'th resulting
+;;; digit from high bits of the i'th source digit and the start-pos number of
+;;; bits from the i+1'th source digit.
+  (defmacro shift-right-unaligned (source
+                                   start-digit
+                                   start-pos
+                                   res-len-form
+                                   termination
+                                   &optional result)
+    `(let* ((high-bits-in-first-digit (- digit-size ,start-pos))
+            (res-len ,res-len-form)
+            (res-len-1 (1- res-len))
+            ,@(if result `((,result (%allocate-bignum res-len)))))
+      (declare (type bignum-index res-len res-len-1))
+      (do ((i ,start-digit i+1)
+           (i+1 (1+ ,start-digit) (1+ i+1))
+           (j 0 (1+ j)))
+          ,termination
+        (declare (type bignum-index i i+1 j))
+        (setf (bignum-ref ,(if result result source) j)
+              (%logior (%digit-logical-shift-right (bignum-ref ,source i)
+                                                   ,start-pos)
+                       (%ashl (bignum-ref ,source i+1)
+                              high-bits-in-first-digit))))))
+
+
+  )
+
+
+#+64-bit-target
+(progn
+
+;;; Extract the length of the bignum.
+;;; 
+(defun %bignum-length (bignum)
+  (uvsize bignum)) 
+
+
+
+;;; We can probably do better than UVREF here, but
+;;; a) it's not -that- bad
+;;; b) it does some bounds/sanity checking, which isn't a bad idea.
+
+(defmacro bignum-ref (b i)
+  `(%typed-miscref :bignum ,b ,i))
+
+(defmacro bignum-set (b i val)
+  `(%typed-miscset :bignum ,b ,i ,val))
+
+
+(defun bignum-plusp (b)
+  (not (logbitp (1- digit-size) (the bignum-element-type (bignum-ref b (1- (%bignum-length b)))))))
+
+;;; Return T if digit is positive, or NIL if negative.
+(defun %digit-0-or-plusp (digit)
+  (declare (type bignum-element-type digit))
+  (not (logbitp (1- digit-size) digit)))
+
+(defun %bignum-0-or-plusp (bignum len)
+  (declare (type bignum-type bignum)
+	   (type bignum-index len))
+  (%digit-0-or-plusp (bignum-ref bignum (1- len))))
+
+(defun bignum-minusp (b)
+  (logbitp 31 (the fixnum (bignum-ref b (1- (%bignum-length b))))))
+
+(defun %sign-digit (b i)
+  (%ashr (bignum-ref b (1- i)) (1- digit-size)))
+
+;;; Return the sign of bignum (0 or -1) as a fixnum
+(defun %bignum-sign (b)
+  (if (logbitp 31 (the fixnum (bignum-ref b (1- (%bignum-length b)))))
+    -1
+    0))
+
+         
+(defun %add-with-carry (a-digit b-digit carry-in)
+  (declare (fixnum a-digit b-digit carry-in))
+  (setq a-digit (logand all-ones-digit a-digit)
+        b-digit (logand all-ones-digit b-digit))
+  (let* ((sum (+ carry-in (the fixnum (+ a-digit b-digit)))))
+    (declare (fixnum sum))
+    (values (logand all-ones-digit sum) (logand 1 (the fixnum (ash sum -32))))))
+
+(defun %subtract-with-borrow (a-digit b-digit borrow-in)
+  (declare (fixnum a-digit b-digit borrow-in))
+  (setq a-digit (logand all-ones-digit a-digit)
+        b-digit (logand all-ones-digit b-digit))
+  (let* ((diff (- (the fixnum (- a-digit b-digit))
+                  (the fixnum (- 1 borrow-in)))))
+    (declare (fixnum diff))
+    (values (logand all-ones-digit diff)
+            (- 1 (logand (the fixnum (ash diff -32)) 1)))))
+
+
+
+(defun %compare-digits (bignum-a bignum-b idx)
+  (let* ((a (bignum-ref bignum-a idx))
+         (b (bignum-ref bignum-b idx)))
+    (declare (fixnum a b))
+    (if (= a b)
+      0
+      (if (> a b)
+        1
+        -1))))
+
+
+
+;;;; Addition.
+(defun add-bignums (a b)
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b)))
+    (declare (bignum-index len-a len-b)
+             (optimize (speed 3) (safety 0)))
+    (when (> len-b len-a)
+      (rotatef a b)
+      (rotatef len-a len-b))
+    (let* ((len-res (1+ len-a))
+	   (res (%allocate-bignum len-res))
+	   (carry 0)
+	   (sign-b (%bignum-sign b)))
+	(dotimes (i len-b)
+          (let* ((sum (+
+                       (the fixnum (+ (the bignum-element-type (bignum-ref a i))
+                                      (the bignum-element-type (bignum-ref b i))))
+                       carry)))
+            (declare (fixnum sum))
+            (setf (bignum-ref res i) sum)
+            (setq carry (logand 1 (the fixnum (ash sum -32))))))
+	(if (/= len-a len-b)
+	  (finish-bignum-add  res carry a sign-b len-b len-a)
+          (setf (bignum-ref res len-a)
+                (+ (the fixnum carry)
+                   (the fixnum (+ (the bignum-element-type (%bignum-sign a))
+                                  sign-b)))))
+	(%normalize-bignum-macro res))))
+
+(defun add-bignum-and-fixnum (bignum fixnum)
+  (declare (bignum-type bignum)
+           (fixnum fixnum)
+           (optimize (speed 3) (safety 0)))
+  (let* ((len-bignum (%bignum-length bignum))
+         (len-res (1+ len-bignum))
+         (res (%allocate-bignum len-res))
+         (low (logand all-ones-digit fixnum))
+         (high (logand all-ones-digit (the fixnum (ash fixnum -32)))))
+    (declare (bignum-index len-bignum)
+             (bignum-type res)
+             (bignum-element-type low high))
+    (let* ((sum0 (+ (the bignum-element-type (bignum-ref bignum 0)) low))
+           (sum1 (+ (the fixnum (+ (the bignum-element-type (bignum-ref bignum 1))
+                                   high))
+                    (the fixnum (logand 1 (ash sum0 -32)))))
+           (carry (logand 1 (ash sum1 -32))))
+      (declare (fixnum sum0 sum1) (bignum-element-type carry))
+      (setf (bignum-ref res 0) sum0
+            (bignum-ref res 1) sum1)
+      (if (> len-bignum 2)
+        (finish-bignum-add  res carry bignum (ash fixnum (- (- target::nbits-in-word target::fixnumshift))) 2 len-bignum)
+        (setf (bignum-ref res 2)
+              (+ (the fixnum carry)
+                 (the fixnum (+ (the bignum-element-type (%bignum-sign bignum))
+                                (the fixnum (ash fixnum (- (- target::nbits-in-word target::fixnumshift)))))))))
+      (%normalize-bignum-macro res))))
+
+
+
+
+
+;;; B was shorter than A; keep adding B's sign digit to each remaining
+;;; digit of A, propagating the carry.
+(defun finish-bignum-add (result carry a sign-b start end)
+  (declare (type bignum-index start end)
+           (bignum-element-type sign-b carry)
+           (optimize (speed 3) (safety 0)))
+  (do* ((i start (1+ i))
+        (sign-b (logand all-ones-digit sign-b)))
+       ((= i end)
+        (setf (bignum-ref result end)
+              (the fixnum (+
+                           (the fixnum (+ (the fixnum
+                                            (logand all-ones-digit
+                                                    (the fixnum
+                                                      (%sign-digit a end))))
+                                          sign-b))
+                           carry))))
+    (declare (fixnum i) (bignum-element-type sign-b))
+    (let* ((sum (the fixnum (+ (the fixnum (+ (bignum-ref a i)
+                                              sign-b))
+                               carry))))
+      (declare (fixnum sum))
+      (setf (bignum-ref result i) sum)
+      (setq carry (logand 1 (the fixnum (ash sum -32)))))))
+
+
+
+
+
+;;;; Subtraction.
+(defun subtract-bignum (a b)
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (len-res (1+ (max len-a len-b)))
+	 (res (%allocate-bignum len-res)))
+    (declare (bignum-index len-a len-b len-res))
+    (bignum-subtract-loop a len-a b len-b res)
+    (%normalize-bignum-macro res)))
+
+(defun bignum-subtract-loop (a len-a b len-b res)
+  (declare (bignum-index len-a len-b )
+           (optimize (speed 3) (safety 0)))
+  (let* ((len-res (%bignum-length res)))
+    (declare (bignum-index len-res))
+    (let* ((borrow 1)
+	   (sign-a (%bignum-sign a))
+	   (sign-b (%bignum-sign b)))
+      (declare (bignum-element-type borrow sign-a sign-b))
+      (dotimes (i (the bignum-index len-res))
+        (multiple-value-bind (result-digit borrow-out)
+            (%subtract-with-borrow
+             (if (< i len-a)
+               (bignum-ref a i)
+               sign-a)
+             (if (< i len-b)
+               (bignum-ref b i)
+               sign-b)
+             borrow)
+          (setf (bignum-ref res i) result-digit
+                borrow borrow-out))))))
+
+
+
+;;;; Multiplication.
+
+#||
+;;; These parameters match GMP's.
+(defvar *sqr-basecase-threshold* 5)
+(defvar *sqr-karatsuba-threshold* 22)
+(defvar *mul-karatsuba-threshold* 10)
+
+;;; Squaring is often simpler than multiplication.  This should never
+;;; be called with (>= N *sqr-karatsuba-threshold*).
+(defun mpn-sqr-basecase (prodp up n)
+  (declare (fixnum prodp up n))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (umulppm up up prodp)
+  (when (> n 1)
+    (%stack-block ((tarr (* 4 (* 2 *sqr-karatsuba-threshold*))))
+      (let* ((tp (macptr->fixnum tarr)))
+	(mpn-mul-1 tp
+		   (the fixnum (1+ up))
+		   (the fixnum (1- n))
+		   up
+		   (the fixnum (+ tp (the fixnum (1- n)))))
+	(do* ((i 2 (1+ i)))
+	     ((= i n))
+	  (declare (fixnum i))
+	  (mpn-addmul-1 (the fixnum (- (the fixnum (+ tp (the fixnum (+ i i))))
+				       2))
+			(the fixnum (+ up i))
+			(the fixnum (- n i))
+			(the fixnum (+ up (the fixnum (1- i))))
+			(the fixnum (+ tp (the fixnum (+ n (the fixnum (- i 2))))))))
+	(do* ((i 1 (1+ i))
+	      (ul (1+ up) (1+ ul)))
+	     ((= i n))
+	  (declare (fixnum i ul))
+	  (umulppm ul ul (the fixnum (+ prodp (the fixnum (+ i i))))))
+	(let* ((2n-2 (- (the fixnum (+ n n)) 2))
+	       (carry (mpn-lshift-1 tp tp 2n-2)))
+	  (declare (fixnum 2n-2 carry))
+	  (incf carry (the fixnum (mpn-add-n (the fixnum (1+ prodp))
+					     (the fixnum (1+ prodp))
+					     tp
+					     2n-2)))
+	  (add-fixnum-to-limb carry (the fixnum (+ prodp
+						   (the fixnum (1-
+								(the fixnum
+								  (+ n n))))))))))))
+
+;;; For large enough values of N, squaring via Karatsuba-style
+;;; divide&conquer is faster than in the base case.
+(defun mpn-kara-sqr-n (p a n ws)
+  (declare (fixnum p a n ws))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (%stack-block ((limbs 16))
+    (let* ((w (macptr->fixnum limbs))
+	   (w0 (1+ w))
+	   (w1 (1+ w0))
+	   (xx (1+ w1))
+	   (n2 (ash n -1))
+	   (x 0)
+	   (y 0)
+	   (i 0))
+      (declare (fixnum w w0 w1 xx n2 x y i))
+      (cond ((logbitp 0 n)
+	     ;; Odd length
+	     (let* ((n3 (- n n2))
+		    (n1 0)
+		    (nm1 0))
+	       (declare (fixnum n3 n1 nm1))
+	       (copy-limb (the fixnum (+ a n2)) w)
+	       (if (not (limb-zerop w))
+		 (add-fixnum-to-limb
+		  (the fixnum
+		    (- (the fixnum (mpn-sub-n p a (the fixnum (+ a n3)) n2))))
+		  w)
+		 (progn
+		   (setq i n2)
+		   (loop
+		     (decf i)
+		     (copy-limb (the fixnum (+ a i)) w0)
+		     (copy-limb (the fixnum (+ a (the fixnum (+ n3 i)))) w1)
+		     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+			     (= i 0))
+		       (return)))
+		   (if (< (the fixnum (compare-limbs w0 w1)) 0)
+		     (setq x (+ a n3)
+			   y a)
+		     (setq y (+ a n3)
+			   x a))
+		   (mpn-sub-n p x y n2)))
+	       (copy-limb w (the fixnum (+ p n2)))
+	       (setq n1 (1+ n))
+	       (cond ((< n3 *sqr-basecase-threshold*)
+		      (mpn-mul-basecase ws p n3 p n3)
+		      (mpn-mul-basecase p a n3 a n3))
+		     ((< n3 *sqr-karatsuba-threshold*)
+		      (mpn-sqr-basecase ws p n3)
+		      (mpn-sqr-basecase p a n3))
+		     (t
+		      (mpn-kara-sqr-n ws p n3 (the fixnum (+ ws n1)))
+		      (mpn-kara-sqr-n p  a n3 (the fixnum (+ ws n1)))))
+	       (cond ((< n2 *sqr-basecase-threshold*)
+		      (mpn-mul-basecase (the fixnum (+ p n1))
+					(the fixnum (+ a n3))
+					n2
+					(the fixnum (+ a n3))
+					n2))
+		     ((< n2 *sqr-karatsuba-threshold*)
+		      (mpn-sqr-basecase (the fixnum (+ p n1))
+					(the fixnum (+ a n3))
+					n2))
+		     (t
+		      (mpn-kara-sqr-n (the fixnum (+ p n1))
+				      (the fixnum (+ a n3))
+				      n2
+				      (the fixnum (+ ws n1)))))
+	       (mpn-sub-n ws p ws n1)
+	       (setq nm1 (1- n))
+	       (unless (zerop (the fixnum
+				(mpn-add-n ws
+					   (the fixnum (+ p n1))
+					   ws
+					   nm1)))
+		 (copy-limb (the fixnum (+ ws nm1)) xx)
+		 (add-fixnum-to-limb 1 xx)
+		 (copy-limb xx (the fixnum (+ ws nm1)))
+		 (if (limb-zerop xx)
+		   (add-fixnum-to-limb 1 (the fixnum (+ ws n)))))
+	       (unless (zerop
+			(the fixnum
+			  (mpn-add-n (the fixnum (+ p n3))
+				     (the fixnum (+ p n3))
+				     ws
+				     n1)))
+		 (mpn-incr-u (the fixnum (+ p (the fixnum (+ n1 n3))))
+			     1))))
+	    (t ; N is even
+	     (setq i n2)
+	     (loop
+	       (decf i)
+	       (copy-limb (the fixnum (+ a i)) w0)
+	       (copy-limb (the fixnum (+ a (the fixnum (+ n2 i)))) w1)
+	       (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+		       (= i 0))
+		 (return)))
+	     (if (< (the fixnum (compare-limbs w0 w1)) 0)
+	       (setq x (+ a n2)
+		     y a)
+	       (setq y (+ a n2)
+		     x a))
+	     (mpn-sub-n p x y n2)
+	     (cond ((< n2 *sqr-basecase-threshold*)
+		    (mpn-mul-basecase ws p n2 p n2)
+		    (mpn-mul-basecase p a n2 a n2)
+		    (mpn-mul-basecase (the fixnum (+ p n))
+				      (the fixnum (+ a n2))
+				      n2
+				      (the fixnum (+ a n2))
+				      n2))
+		   ((< n2 *sqr-karatsuba-threshold*)
+		    (mpn-sqr-basecase ws p n2)
+		    (mpn-sqr-basecase p a n2)
+		    (mpn-sqr-basecase (the fixnum (+ p n))
+				      (the fixnum (+ a n2))
+				      n2))
+		   (t
+		    (mpn-kara-sqr-n ws p n2 (the fixnum (+ ws n)))
+		    (mpn-kara-sqr-n p  a n2 (the fixnum (+ ws n)))
+		    (mpn-kara-sqr-n (the fixnum (+ p n))
+				    (the fixnum (+ a n2))
+				    n2
+				    (the fixnum (+ ws n)))))
+	     (let* ((ww (- (the fixnum (mpn-sub-n ws p ws n)))))
+	       (declare (fixnum ww))
+	       (setq ww (+ ww (mpn-add-n ws (the fixnum (+ p n)) ws n)))
+	       (setq ww (+ ww (mpn-add-n (the fixnum (+ p n2))
+                                         (the fixnum (+ p n2))
+                                         ws
+                                         n)))
+	       (mpn-incr-u (the fixnum (+ p (the fixnum (+ n2 n)))) ww)))))))
+
+;;; Karatsuba subroutine: multiply A and B, store result at P, use WS
+;;; as scrach space.  Treats A and B as if they were both of size N;
+;;; if that's not true, caller must fuss around the edges.
+(defun mpn-kara-mul-n (p a b n ws)
+  (declare (fixnum p a b n ws))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (%stack-block ((limbs 16))
+    (let* ((w (macptr->fixnum limbs))
+	   (w0 (1+ w))
+	   (w1 (1+ w0))
+	   (xx (1+ w1))
+	   (x 0)
+	   (y 0)
+	   (i 0)
+	   (n2 (ash n -1))
+	   (sign 0))
+      (declare (fixnum w w0 w1 xx x y i n2 sign))
+      (cond ((logbitp 0 n)
+	     (let* ((n1 0)
+		    (n3 (- n n2))
+		    (nm1 0))
+	       (declare (fixnum n1 n3 nm1))
+	       (copy-limb (the fixnum (+ a n2)) w)
+	       (if (not (limb-zerop w))
+		 (add-fixnum-to-limb
+		  (the fixnum (- (mpn-sub-n p a (the fixnum (+ a n3)) n2))) w)
+		 (progn
+		   (setq i n2)
+		   (loop
+		     (decf i)
+		     (copy-limb (the fixnum (+ a i)) w0)
+		     (copy-limb (the fixnum (+ a (the fixnum (+ n3 i)))) w1)
+		     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+			     (zerop i))
+		       (return)))
+		   (if (< (the fixnum (compare-limbs w0 w1)) 0)
+		     (setq x (+ a n3)
+			   y a
+			   sign -1)
+		     (setq x a
+			   y (+ a n3)))
+		   (mpn-sub-n p x y n2)))
+	       (copy-limb w (the fixnum (+ p n2)))
+	       (copy-limb (the fixnum (+ b n2)) w)
+	       (if (not (limb-zerop w))
+		 (add-fixnum-to-limb
+		  (the fixnum (- (the fixnum (mpn-sub-n (the fixnum (+ p n3))
+							b
+							(the fixnum (+ b n3))
+							n2))))
+		  w)
+		 (progn
+		   (setq i n2)
+		   (loop
+		     (decf i)
+		     (copy-limb (the fixnum (+ b i)) w0)
+		     (copy-limb (the fixnum (+ b (the fixnum (+ n3 i)))) w1)
+		     (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+			     (zerop i))
+		       (return)))
+		   (if (< (the fixnum (compare-limbs w0 w1)) 0)
+		     (setq x (+ b n3)
+			   y b
+			   sign (lognot sign))
+		     (setq x b
+			   y (+ b n3)))
+		   (mpn-sub-n (the fixnum (+ p n3)) x y n2)))
+	       (copy-limb w (the fixnum (+ p n)))
+	       (setq n1 (1+ n))
+	       (cond
+		 ((< n2 *mul-karatsuba-threshold*)
+		  (cond
+		    ((< n3 *mul-karatsuba-threshold*)
+		     (mpn-mul-basecase ws p n3 (the fixnum (+ p n3)) n3)
+		     (mpn-mul-basecase p a n3 b n3))
+		    (t
+		     (mpn-kara-mul-n ws p (the fixnum (+ p n3)) n3 (the fixnum (+ ws n1)))
+		     (mpn-kara-mul-n p a b n3 (the fixnum (+ ws n1)))))
+		  (mpn-mul-basecase (the fixnum (+ p n1))
+				    (the fixnum (+ a n3))
+				    n2
+				    (the fixnum (+ b n3))
+				    n2))
+		 (t
+		  (mpn-kara-mul-n ws p (the fixnum (+ p n3)) n3 (the fixnum (+ ws n1)))
+		  (mpn-kara-mul-n p a b n3 (the fixnum (+ ws n1)))
+		  (mpn-kara-mul-n (the fixnum (+ p n1))
+				  (the fixnum (+ a n3))
+				  (the fixnum (+ b n3))
+				  n2
+				  (the fixnum (+ ws n1)))))
+	       (if (not (zerop sign))
+		 (mpn-add-n ws p ws n1)
+		 (mpn-sub-n ws p ws n1))
+	       (setq nm1 (1- n))
+	       (unless (zerop (the fixnum (mpn-add-n ws
+						     (the fixnum (+ p n1))
+						     ws
+						     nm1)))
+		 (copy-limb (the fixnum (+ ws nm1)) xx)
+		 (add-fixnum-to-limb 1 xx)
+		 (copy-limb xx (the fixnum (+ ws nm1)))
+		 (if (limb-zerop xx)
+		   (add-fixnum-to-limb 1 (the fixnum (+ ws n)))))
+	       (unless (zerop (the fixnum
+				(mpn-add-n (the fixnum (+ p n3))
+					   (the fixnum (+ p n3))
+					   ws
+					   n1)))
+		 (mpn-incr-u (the fixnum
+			       (+ p (the fixnum (+ n1 n3)))) 1))))
+	    (t				; even length
+	     (setq i n2)
+	     (loop
+	       (decf i)
+	       (copy-limb (the fixnum (+ a i)) w0)
+	       (copy-limb (the fixnum (+ a (the fixnum (+ n2 i)))) w1)
+	       (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+		       (zerop i))
+		 (return)))
+	     (setq sign 0)
+	     (if (< (the fixnum (compare-limbs w0 w1)) 0)
+	       (setq x (+ a n2)
+		     y a
+		     sign -1)
+	       (setq x a
+		     y (+ a n2)))
+	     (mpn-sub-n p x y n2)
+	     (setq i n2)
+	     (loop
+	       (decf i)
+	       (copy-limb (the fixnum (+ b i)) w0)
+	       (copy-limb (the fixnum (+ b (the fixnum (+ n2 i)))) w1)
+	       (if (or (not (zerop (the fixnum (compare-limbs w0 w1))))
+		       (zerop i))
+		 (return)))	      
+	     (if (< (the fixnum (compare-limbs w0 w1)) 0)
+	       (setq x (+ b n2)
+		     y b
+		     sign (lognot sign))
+	       (setq x b
+		     y (+ b n2)))
+	     (mpn-sub-n (the fixnum (+ p n2)) x y n2)
+	     (cond
+	       ((< n2 *mul-karatsuba-threshold*)
+		(mpn-mul-basecase ws p n2 (the fixnum (+ p n2)) n2)
+		(mpn-mul-basecase p a n2 b n2)
+		(mpn-mul-basecase (the fixnum (+ p n))
+				  (the fixnum (+ a n2))
+				  n2
+				  (the fixnum (+ b n2))
+				  n2))
+	       (t
+		(mpn-kara-mul-n ws p (the fixnum (+ p n2)) n2
+				(the fixnum (+ ws n)))
+		(mpn-kara-mul-n p a b n2 (the fixnum (+ ws n)))
+		(mpn-kara-mul-n (the fixnum (+ p n))
+				(the fixnum (+ a n2))
+				(the fixnum (+ b n2))
+				n2
+				(the fixnum (+ ws n)))))
+	     (let* ((ww (if (not (zerop sign))
+			  (mpn-add-n ws p ws n)
+			  (- (the fixnum (mpn-sub-n ws p ws n))))))
+	       (declare (fixnum ww))
+	       (setq ww (+ ww (mpn-add-n ws (the fixnum (+ p n)) ws n)))
+	       (setq ww (+ ww (mpn-add-n (the fixnum (+ p n2))
+                                         (the fixnum (+ p n2))
+                                         ws
+                                         n)))
+	       (mpn-incr-u (the fixnum (+ p (the fixnum (+ n2 n)))) ww)))))))
+
+;;; Square UP, of length UN.  I wonder if a Karatsuba multiply might be
+;;; faster than a basecase square.
+(defun mpn-sqr-n (prodp up un)
+  (declare (fixnum prodp up un))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  (if (< un *sqr-basecase-threshold*)
+    (mpn-mul-basecase prodp up un up un)
+    (if (< un *sqr-karatsuba-threshold*)
+      (mpn-sqr-basecase prodp up un)
+      (%stack-block ((wsptr (mpn-kara-sqr-n-tsize un)))
+	(mpn-kara-sqr-n prodp up un (macptr->fixnum wsptr))))))
+
+;;; Subroutine: store AxB at P.  Assumes A & B to be of length N
+(defun mpn-mul-n (p a b n)
+  (declare (fixnum p a b n))
+  (declare (optimize (speed 3) (safety 0) (space 0)))  
+  (if (< n *mul-karatsuba-threshold*)
+    (mpn-mul-basecase p a n b n)
+    (%stack-block ((wsptr (mpn-kara-mul-n-tsize n)))
+      (mpn-kara-mul-n p a b n (macptr->fixnum wsptr)))))
+
+
+;;; Multiply [UP,UN] by [VP,VN].  UN must not be less than VN.
+;;; This does Karatsuba if operands are big enough; if they are
+;;; and they differ in size, this computes the product of the
+;;; smaller-size slices, then fixes up the resut.
+(defun mpn-mul (prodp up un vp vn)
+  (declare (fixnum prodp up un vp vn))
+  (declare (optimize (speed 3) (safety 0) (space 0)))
+  ;(assert (>= un vn 1))
+  (if (and (= up vp) (= un vn))
+    (mpn-sqr-n prodp up un)
+    (if (< vn *mul-karatsuba-threshold*)
+      (mpn-mul-basecase prodp up un vp vn)
+      (let* ((l vn))
+	(declare (fixnum l))
+	(mpn-mul-n prodp up vp vn)
+	(unless (= un vn)
+	  (incf prodp vn)
+	  (incf up vn)
+	  (decf un vn)
+	  (if (< un vn)
+	    (psetq un vn vn un up vp vp up))
+	  (%stack-block ((wsptr
+			  (the fixnum
+			    (+ 8
+			       (the fixnum
+				 (* 4
+				    (the fixnum
+				      (+ vn
+					 (if (>= vn *mul-karatsuba-threshold*)
+					   vn
+					   un)))))))))
+	    (setf (%get-unsigned-long wsptr 0) 0
+		  (%get-unsigned-long wsptr 4) 0)
+	    (let* ((tt (macptr->fixnum wsptr))
+		   (c (1+ tt))
+		   (ws (1+ c)))
+	      (declare (fixnum tt c ws ))
+	      (do* ()
+		   ((< vn *mul-karatsuba-threshold*))
+		(mpn-mul-n ws up vp vn)
+		(cond ((<= l (the fixnum (+ vn vn)))
+		       (add-fixnum-to-limb (mpn-add-n prodp prodp ws l) tt)
+		       (unless (= l (the fixnum (+ vn vn)))
+			 (copy-fixnum-to-limb
+			  (mpn-add-1 (the fixnum (+ prodp l))
+				     (the fixnum (+ ws l))
+				     (the fixnum (- (the fixnum (+ vn vn)) l))
+				     tt)
+			  tt)
+			 (setq l (the fixnum (+ vn vn)))))
+		      (t
+		       (copy-fixnum-to-limb
+			(mpn-add-n prodp prodp ws (the fixnum (+ vn vn))) c)
+		       (add-fixnum-to-limb
+			(mpn-add-1 (the fixnum (+ prodp (the fixnum (+ vn vn))))
+				   (the fixnum (+ prodp (the fixnum (+ vn vn))))
+				   (the fixnum (- l (the fixnum (+ vn vn))))
+				   c)
+			tt)))
+		(incf prodp vn)
+		(decf l vn)
+		(incf up vn)
+		(decf un vn)
+		(if (< un vn)
+		  (psetq up vp vp up un vn vn un)))
+	      (unless (zerop vn)
+		(mpn-mul-basecase ws up un vp vn)
+		(cond ((<= l (the fixnum (+ un vn)))
+		       (add-fixnum-to-limb
+			(mpn-add-n prodp prodp ws l)
+			tt)
+		       (unless (= l (the fixnum (+ un vn)))
+			 (copy-fixnum-to-limb
+			  (mpn-add-1 (the fixnum (+ prodp l))
+				     (the fixnum (+ ws l))
+				     (the fixnum (- (the fixnum (+ un vn)) l))
+				     tt)
+			  tt)))
+		      (t
+		       (copy-fixnum-to-limb
+			(mpn-add-n prodp prodp ws (the fixnum (+ un vn)))
+			c)
+		       (add-fixnum-to-limb
+			(mpn-add-1
+			 (the fixnum (+ prodp (the fixnum (+ un vn))))
+			 (the fixnum (+ prodp (the fixnum (+ un vn))))
+			 (the fixnum (- (the fixnum (- l un)) vn))
+			 c)
+			tt)))))))))))
+||#
+
+(defun multiply-bignums (a b)
+  (let* ((signs-differ (not (eq (bignum-minusp a) (bignum-minusp b)))))
+    (flet ((multiply-unsigned-bignums (a b)
+	     (let* ((len-a (%bignum-length a))
+		    (len-b (%bignum-length b))
+		    (len-res (+ len-a len-b))
+		    (res (%allocate-bignum len-res)))
+	       (declare (bignum-index len-a len-b len-res))
+	       (dotimes (i len-a)
+		 (declare (type bignum-index i))
+		 (%multiply-and-add-loop a b res i len-b))
+	       res))
+	   (multiply-unsigned-bignums64 (a b)
+	     (let* ((len-a (ceiling (%bignum-length a) 2))
+		    (len-b (ceiling (%bignum-length b) 2))
+		    (len-res (+ len-a len-b))
+		    (res (%allocate-bignum (+ len-res len-res))))
+	       (declare (bignum-index len-a len-b len-res))
+	       (dotimes (i len-a)
+		 (declare (type bignum-index i))
+		 (%multiply-and-add-loop64 a b res i len-b))
+	       res)))
+      (let* ((res (with-negated-bignum-buffers a b
+					       multiply-unsigned-bignums64)))
+	(if signs-differ (negate-bignum-in-place res))
+	(%normalize-bignum-macro res)))))
+
+(defun multiply-bignum-and-fixnum (bignum fixnum)
+  (declare (type bignum-type bignum) (fixnum fixnum))
+  (if (eql fixnum 1)
+    bignum
+    (with-small-bignum-buffers ((big-fix fixnum))
+      (multiply-bignums bignum big-fix))))
+
+#+slower
+(defun multiply-bignum-and-fixnum (bignum fixnum)
+  (declare (type bignum-type bignum) (fixnum fixnum))
+  (if (eql fixnum 1)
+    bignum
+    (if (eql fixnum target::target-most-negative-fixnum)
+      (with-small-bignum-buffers ((big-fix fixnum))
+        (multiply-bignums bignum big-fix))
+      (let* ((big-len (%bignum-length bignum))
+             (big-neg (bignum-minusp bignum))
+             (signs-differ (not (eq big-neg (minusp fixnum)))))
+        (flet ((multiply-unsigned-bignum-and-2-digit-fixnum (a len-a high low)
+                 (declare (bignum-type a)
+                          (bignum-element-type high low)
+                          (bignum-index len-a)
+                          (optimize (speed 3) (safety 0)))
+                 (let* ((len-res (+ len-a 2))
+                        (res (%allocate-bignum len-res)) )
+                   (declare (bignum-index len-a  len-res))
+                   (dotimes (i len-a)
+                     (declare (type bignum-index i))
+                     (let* ((carry-digit 0)
+                            (x (bignum-ref a i))
+                            (k i))
+                       (declare (fixnum k))
+                       (multiple-value-bind (big-carry res-digit)
+                           (%multiply-and-add4 x
+                                               low
+                                               (bignum-ref res k)
+                                               carry-digit)
+                         (setf (bignum-ref res k) res-digit
+                               carry-digit big-carry
+                               k (1+ k)))
+                       (multiple-value-bind (big-carry res-digit)
+                           (%multiply-and-add4 x
+                                               high
+                                               (bignum-ref res k)
+                                               carry-digit)
+                         (setf (bignum-ref res k) res-digit
+                               carry-digit big-carry
+                               k (1+ k)))
+                       (setf (bignum-ref res k) carry-digit)))
+                   res))
+               (multiply-unsigned-bignum-and-1-digit-fixnum (a len-a fix)
+                 (declare (bignum-type a)
+                          (bignum-element-type fix)
+                          (bignum-index len-a)
+                          (optimize (speed 3) (safety 0)))
+                 (let* ((len-res (+ len-a 1))
+                        (res (%allocate-bignum len-res)) )
+                   (declare (bignum-index len-a  len-res))
+                   (dotimes (i len-a)
+                     (declare (type bignum-index i))
+                     (let* ((carry-digit 0)
+                            (x (bignum-ref a i))
+                            (k i))
+                       (declare (fixnum k))
+                       (multiple-value-bind (big-carry res-digit)
+                           (%multiply-and-add4 x
+                                               fix
+                                               (bignum-ref res k)
+                                               carry-digit)
+                         (setf (bignum-ref res k) res-digit
+                               carry-digit big-carry
+                               k (1+ k)))
+                       (setf (bignum-ref res k) carry-digit)))
+                   res)))
+          (let* ((fixnum (if (< fixnum 0) (- fixnum) fixnum))
+                 (low (logand (1- (ash 1 32)) fixnum))
+                 (high (unless (<= (%fixnum-intlen fixnum) 32)
+                         (ldb (byte 32 32) fixnum)))
+                 (res (if big-neg
+                        (let* ((neg-len (1+ big-len)))
+                          (declare (type bignum-index neg-len))
+                          (with-bignum-buffers ((neg neg-len))
+                            (negate-bignum bignum nil neg)
+                            (setq neg-len (%bignum-length bignum))
+                            (if high
+                              (multiply-unsigned-bignum-and-2-digit-fixnum
+                               neg
+                               neg-len
+                               high
+                               low)
+                              (multiply-unsigned-bignum-and-1-digit-fixnum
+                               neg
+                               neg-len
+                               low))))
+                        (if high
+                          (multiply-unsigned-bignum-and-2-digit-fixnum
+                           bignum
+                           big-len
+                           high
+                           low)
+                          (multiply-unsigned-bignum-and-1-digit-fixnum
+                           bignum
+                           big-len
+                           low)))))
+            (if signs-differ (negate-bignum-in-place res))
+            (%normalize-bignum-macro res)))))))
+
+
+;; assume we already know result won't fit in a fixnum
+;; only caller is fixnum-*-2
+;;
+
+(defun multiply-fixnums (a b)
+  (declare (fixnum a b))
+  (* a b))
+
+
+;;;; GCD.
+
+
+;;; Both args are > 0.
+(defun bignum-fixnum-gcd (bignum fixnum)
+  (let* ((rem (bignum-truncate-by-fixnum-no-quo bignum fixnum)))
+    (declare (fixnum rem))
+    (if (zerop rem)
+      fixnum
+      (%fixnum-gcd rem fixnum))))
+
+
+
+
+;;; NEGATE-BIGNUM -- Public.
+;;;
+;;; Fully-normalize is an internal optional.  It cause this to always return
+;;; a bignum, without any extraneous digits, and it never returns a fixnum.
+;;;
+(defun negate-bignum (x &optional (fully-normalize t) res)
+  (declare (type bignum-type x))
+  (let* ((len-x (%bignum-length x))
+	 (len-res (1+ len-x))
+         (minusp (bignum-minusp x))
+	 (res (or res (%allocate-bignum len-res))))
+    (declare (type bignum-index len-x len-res)) ;Test len-res for range?
+    (let ((carry (bignum-negate-loop-really x len-x res)))
+      (declare (fixnum carry))
+      (if (zerop carry)
+        (setf (bignum-ref res len-x) (if minusp 0 all-ones-digit))
+        (setf (bignum-ref res len-x) (if minusp 1 0))))
+    (if fully-normalize
+      (%normalize-bignum-macro res)
+      (%mostly-normalize-bignum-macro res))))
+
+;;; NEGATE-BIGNUM-IN-PLACE -- Internal.
+;;;
+;;; This assumes bignum is positive; that is, the result of negating it will
+;;; stay in the provided allocated bignum.
+;;;
+(defun negate-bignum-in-place (bignum)
+  (bignum-negate-loop-really bignum (%bignum-length bignum) bignum)
+  bignum)
+
+
+  
+
+(defun copy-bignum (bignum)
+  (let ((res (%allocate-bignum (%bignum-length bignum))))
+    (bignum-replace res bignum)
+    res))
+
+
+
+
+;;; BIGNUM-ASHIFT-RIGHT -- Public.
+;;;
+;;; First compute the number of whole digits to shift, shifting them by
+;;; skipping them when we start to pick up bits, and the number of bits to
+;;; shift the remaining digits into place.  If the number of digits is greater
+;;; than the length of the bignum, then the result is either 0 or -1.  If we
+;;; shift on a digit boundary (that is, n-bits is zero), then we just copy
+;;; digits.  The last branch handles the general case which uses a macro that a
+;;; couple other routines use.  The fifth argument to the macro references
+;;; locals established by the macro.
+;;;
+
+
+(defun bignum-ashift-right (bignum x)
+  (declare (type bignum-type bignum)
+           (fixnum x)
+           (optimize (speed 3) (safety 0)))
+  (let ((bignum-len (%bignum-length bignum)))
+    (declare (type bignum-index bignum-len))
+    (multiple-value-bind (digits n-bits) (truncate x digit-size)
+      (declare (type bignum-index digits)(fixnum n-bits))
+      (cond
+       ((>= digits bignum-len)
+        (if (bignum-plusp bignum) 0 -1))
+       ((eql 0 n-bits)
+        (bignum-ashift-right-digits bignum digits))
+       (t
+        (shift-right-unaligned bignum digits n-bits (- bignum-len digits)
+				      ((= j res-len-1)
+				       (setf (bignum-ref res j)
+					     (%ashr (bignum-ref bignum i) n-bits))
+				       (%normalize-bignum-macro res))
+				      res))))))
+
+			       
+
+
+
+;;; BIGNUM-ASHIFT-RIGHT-DIGITS -- Internal.
+;;;
+(defun bignum-ashift-right-digits (bignum digits)
+  (declare (type bignum-type bignum)
+	   (type bignum-index digits))
+  (let* ((res-len (- (%bignum-length bignum) digits))
+	 (res (%allocate-bignum res-len)))
+    (declare (type bignum-index res-len)
+	     (type bignum-type res))
+    (bignum-replace res bignum :start2 digits)
+    (%normalize-bignum-macro res)))
+
+
+;;; BIGNUM-BUFFER-ASHIFT-RIGHT -- Internal.
+;;;
+;;; GCD uses this for an in-place shifting operation.  This is different enough
+;;; from BIGNUM-ASHIFT-RIGHT that it isn't worth folding the bodies into a
+;;; macro, but they share the basic algorithm.  This routine foregoes a first
+;;; test for digits being greater than or equal to bignum-len since that will
+;;; never happen for its uses in GCD.  We did fold the last branch into a macro
+;;; since it was duplicated a few times, and the fifth argument to it
+;;; references locals established by the macro.
+;;;
+ 
+
+;;; BIGNUM-ASHIFT-LEFT -- Public.
+;;;
+;;; This handles shifting a bignum buffer to provide fresh bignum data for some
+;;; internal routines.  We know bignum is safe when called with bignum-len.
+;;; First we compute the number of whole digits to shift, shifting them
+;;; starting to store farther along the result bignum.  If we shift on a digit
+;;; boundary (that is, n-bits is zero), then we just copy digits.  The last
+;;; branch handles the general case.
+;;;
+(defun bignum-ashift-left (bignum x &optional bignum-len)
+  (declare (type bignum-type bignum)
+	   (fixnum x)
+	   (type (or null bignum-index) bignum-len))
+  (multiple-value-bind (digits n-bits)
+		       (truncate x digit-size)
+    (declare (fixnum digits n-bits))
+    (let* ((bignum-len (or bignum-len (%bignum-length bignum)))
+	   (res-len (+ digits bignum-len 1)))
+      (declare (fixnum bignum-len res-len))
+      (when (> res-len maximum-bignum-length)
+	(error "Can't represent result of left shift."))
+      (if (zerop n-bits)
+        (bignum-ashift-left-digits bignum bignum-len digits)
+        (bignum-ashift-left-unaligned bignum digits n-bits res-len)))))
+
+;;; BIGNUM-ASHIFT-LEFT-DIGITS -- Internal.
+;;;
+(defun bignum-ashift-left-digits (bignum bignum-len digits)
+  (declare (type bignum-index bignum-len digits))
+  (let* ((res-len (+ bignum-len digits))
+	 (res (%allocate-bignum res-len)))
+    (declare (type bignum-index res-len))
+    (bignum-replace res bignum :start1 digits :end1 res-len :end2 bignum-len
+		    :from-end t)
+    res))
+
+
+
+;;; BIGNUM-ASHIFT-LEFT-UNALIGNED -- Internal.
+;;;
+;;; BIGNUM-TRUNCATE uses this to store into a bignum buffer by supplying res.
+;;; When res comes in non-nil, then this foregoes allocating a result, and it
+;;; normalizes the buffer instead of the would-be allocated result.
+;;;
+;;; We start storing into one digit higher than digits, storing a whole result
+;;; digit from parts of two contiguous digits from bignum.  When the loop
+;;; finishes, we store the remaining bits from bignum's first digit in the
+;;; first non-zero result digit, digits.  We also grab some left over high
+;;; bits from the last digit of bignum.
+;;;
+
+(defun bignum-ashift-left-unaligned (bignum digits n-bits res-len
+                                            &optional (res nil resp))
+  (declare (type bignum-index digits res-len)
+	   (type (mod #.digit-size) n-bits))
+  (let* ((remaining-bits (- digit-size n-bits))
+	 (res-len-1 (1- res-len))
+	 (res (or res (%allocate-bignum res-len))))
+    (declare (type bignum-index res-len res-len-1)
+             (optimize (speed 3) (safety 0)))
+    (do ((i 0 i+1)
+	 (i+1 1 (1+ i+1))
+	 (j (1+ digits) (1+ j)))
+	((= j res-len-1)
+	 (setf (bignum-ref res digits)
+	       (%ashl (bignum-ref bignum 0) n-bits))
+	 (setf (bignum-ref res j)
+	       (%ashr (bignum-ref bignum i) remaining-bits))
+	 (if resp
+           (%zero-trailing-sign-digits res res-len)
+           (%mostly-normalize-bignum-macro res)))
+      (declare (type bignum-index i i+1 j))
+      (setf (bignum-ref res j)
+	    (%logior (%digit-logical-shift-right (bignum-ref bignum i)
+						 remaining-bits)
+		     (%ashl (bignum-ref bignum i+1) n-bits))))))
+
+
+
+
+
+
+
+
+;;;; Relational operators.
+
+
+
+;;; BIGNUM-COMPARE -- Public.
+;;;
+;;; This compares two bignums returning -1, 0, or 1, depending on whether a
+;;; is less than, equal to, or greater than b.
+;;;
+;(proclaim '(function bignum-compare (bignum bignum) (integer -1 1)))
+(defun bignum-compare (a b)
+  (declare (type bignum-type a b))
+  (let* ((a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (if (eq a-plusp b-plusp)
+      (let* ((len-a (%bignum-length a))
+	     (len-b (%bignum-length b)))
+	(declare (type bignum-index len-a len-b))
+	(cond ((= len-a len-b)
+	       (do* ((i (1- len-a) (1- i)))
+		    ((zerop i) (%compare-digits a b 0))
+		 (declare (fixnum i))
+		 (let* ((signum (%compare-digits a b i)))
+		   (declare (fixnum signum))
+		   (unless (zerop signum)
+		     (return signum)))))
+	      ((> len-a len-b)
+	       (if a-plusp 1 -1))
+	      (t (if a-plusp -1 1))))
+      (if a-plusp 1 -1))))
+
+
+
+
+
+
+
+;;;; Integer length and logcount
+
+
+(defun bignum-integer-length (big)
+  (the fixnum (- (the fixnum (ash (the fixnum (%bignum-length big)) 5))
+		 (the fixnum (%bignum-sign-bits big)))))
+
+; (not (zerop (logand integer1 integer2)
+
+(defun bignum-logtest (num1 num2)
+  (let* ((length1 (%bignum-length num1))
+         (length2 (%bignum-length num2))
+         (n1-minusp (bignum-minusp num1))
+         (n2-minusp (bignum-minusp num2)))
+    (declare (fixnum length1 length2))
+    (if (and n1-minusp n2-minusp) ; both neg, get out quick
+      T        
+      (or (dotimes (i (min length1 length2))
+            (unless (zerop (the fixnum
+                             (logand (the fixnum (bignum-ref num1 i))
+                                     (the fixnum (bignum-ref num2 i)))))
+              (return t)))
+          (if (< length1 length2)
+            n1-minusp
+            (if (< length1 length2)
+              n2-minusp))))))
+
+(defun logtest-fix-big (fix big)
+  (declare (fixnum fix))
+  (unless (zerop fix)
+    (if (plusp fix)
+      (or
+       (not (eql 0 (the fixnum (logand (the fixnum (bignum-ref big 0)) fix))))
+       (and (> (%bignum-length big) 1)
+            (not (eql 0 (the fixnum (logand (the fixnum (bignum-ref big 1))
+                                            (the fixnum (ash fix -32))))))))
+      t)))
+
+
+(defun bignum-logcount (bignum)
+  (declare (type bignum-type bignum))
+  (let* ((length (%bignum-length bignum))
+	 (plusp (bignum-plusp bignum))
+	 (result 0))
+    (declare (type bignum-index length)
+	     (fixnum result))
+    (if plusp
+      (dotimes (index length result)
+	(incf result (the fixnum (%logcount bignum index))))
+      (dotimes (index length result)
+	(incf result (the fixnum (%logcount-complement bignum index)))))))
+
+
+
+;;;; Logical operations.
+
+;;; NOT.
+;;;
+
+;;; BIGNUM-LOGICAL-NOT -- Public.
+;;;
+(defun bignum-logical-not (a)
+  (declare (type bignum-type a))
+  (let* ((len (%bignum-length a))
+	 (res (%allocate-bignum len)))
+    (declare (type bignum-index len))
+    (dotimes (i len res)
+      (bignum-set res i (%lognot (the fixnum (bignum-ref a i)))))))
+
+
+
+
+;;; AND.
+;;;
+
+;;; BIGNUM-LOGICAL-AND -- Public.
+;;;
+(defun bignum-logical-and (a b)
+  (declare (type bignum-type a b))
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (declare (type bignum-index len-a len-b))
+    (cond
+      ((< len-a len-b)
+       (if a-plusp
+	 (logand-shorter-positive a len-a b (%allocate-bignum len-a))
+	 (logand-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
+      ((< len-b len-a)
+       (if b-plusp
+	 (logand-shorter-positive b len-b a (%allocate-bignum len-b))
+	 (logand-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
+      (t (logand-shorter-positive a len-a b (%allocate-bignum len-a))))))
+
+;;; LOGAND-SHORTER-POSITIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is positive.  Because this
+;;; is AND, we don't care about any bits longer than a's since its infinite 0
+;;; sign bits will mask the other bits out of b.  The result is len-a big.
+;;;
+(defun logand-shorter-positive (a len-a b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a))
+  (dotimes (i len-a)
+    (setf (bignum-ref res i)
+          (logand (the fixnum (bignum-ref a i))
+                  (the fixnum (bignum-ref b i)))))
+  (%normalize-bignum-macro res))
+
+;;; LOGAND-SHORTER-NEGATIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is negative.  Because this
+;;; is AND, we just copy any bits longer than a's since its infinite 1 sign
+;;; bits will include any bits from b.  The result is len-b big.
+;;;
+(defun logand-shorter-negative (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (setf (bignum-ref res i)
+          (logand (the fixnum (bignum-ref a i))
+                              (the fixnum (bignum-ref b i)))))
+  (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b)
+  (%normalize-bignum-macro res))
+
+
+
+;;;
+;;;
+;;; bignum-logandc2
+
+(defun bignum-logandc2 (a b)
+  (declare (type bignum-type a b))
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (declare (type bignum-index len-a len-b))
+    (cond
+     ((< len-a len-b)
+      (logandc2-shorter-any a len-a b len-b (if a-plusp (%allocate-bignum len-a) (%allocate-bignum len-b))))
+     ((< len-b len-a) ; b shorter 
+      (logandc1-shorter-any b len-b a len-a (if b-plusp (%allocate-bignum len-a)(%allocate-bignum len-b))))
+     (t (logandc2-shorter-any a len-a b len-b (%allocate-bignum len-a))))))
+
+(defun logandc2-shorter-any (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+           (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (setf (bignum-ref res i)
+          (logand (the fixnum (bignum-ref a i))
+                  (the fixnum (%lognot (the fixnum (bignum-ref b i)))))))
+  (if (bignum-minusp a)
+    (do ((i len-a (1+ i)))
+          ((= i len-b))
+        (declare (type bignum-index i))
+      (setf (bignum-ref res i)
+            (%lognot (the fixnum (bignum-ref b i))))))
+  (%normalize-bignum-macro res))
+
+
+
+(defun logandc1-shorter-any (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+           (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (setf (bignum-ref res i)
+          (logand
+           (the fixnum (%lognot (the fixnum (bignum-ref a i))))
+           (the fixnum (bignum-ref b i)))))
+  (when (bignum-plusp a)
+    (unless (= len-a len-b)
+      (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b)))
+  (%normalize-bignum-macro res))
+
+
+
+(defun fix-big-logand (fix big)
+  (let* ((len-b (%bignum-length big))
+         (res (if (< fix 0)(%allocate-bignum len-b))))
+    (declare (fixnum fix len-b))        
+    (let ((val (fix-digit-logand fix big res)))
+      (if res
+        (progn
+          (bignum-replace res big :start1 2 :start2 2 :end1 len-b :end2 len-b)
+          (%normalize-bignum-macro res))
+        val))))
+
+
+(defun fix-big-logandc2 (fix big)
+  (let* ((len-b (%bignum-length big))
+         (res (if (< fix 0)(%allocate-bignum len-b))))
+    (declare (fixnum fix len-b))        
+    (let ((val (fix-digit-logandc2 fix big res)))
+      (if res
+        (progn
+          (do ((i 2 (1+ i)))
+              ((= i len-b))
+            (declare (type bignum-index i))
+            (setf (bignum-ref res i)
+                  (%lognot (bignum-ref big i))))
+          (%normalize-bignum-macro res))
+        val))))
+
+(defun fix-big-logandc1 (fix big)
+  (let* ((len-b (%bignum-length big))
+         (res (if (>= fix 0)(%allocate-bignum len-b))))
+    (declare (fixnum fix len-b))        
+    (let ((val (fix-digit-logandc1 fix big res)))
+      (if res
+        (progn  
+          (bignum-replace res big :start1 2 :start2 2 :end1 len-b :end2 len-b)
+          (%normalize-bignum-macro res))
+        val))))
+
+
+;;; IOR.
+;;;
+
+;;; BIGNUM-LOGICAL-IOR -- Public.
+;;;
+(defun bignum-logical-ior (a b)
+  (declare (type bignum-type a b))
+  (let* ((len-a (%bignum-length a))
+	 (len-b (%bignum-length b))
+	 (a-plusp (bignum-plusp a))
+	 (b-plusp (bignum-plusp b)))
+    (declare (type bignum-index len-a len-b))
+    (cond
+     ((< len-a len-b)
+      (if a-plusp
+	  (logior-shorter-positive a len-a b len-b (%allocate-bignum len-b))
+	  (logior-shorter-negative a len-a b len-b (%allocate-bignum len-b))))
+     ((< len-b len-a)
+      (if b-plusp
+	  (logior-shorter-positive b len-b a len-a (%allocate-bignum len-a))
+	  (logior-shorter-negative b len-b a len-a (%allocate-bignum len-a))))
+     (t (logior-shorter-positive a len-a b len-b (%allocate-bignum len-a))))))
+
+;;; LOGIOR-SHORTER-POSITIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is positive.  Because this
+;;; is IOR, we don't care about any bits longer than a's since its infinite
+;;; 0 sign bits will mask the other bits out of b out to len-b.  The result
+;;; is len-b long.
+;;;
+(defun logior-shorter-positive (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (setf (bignum-ref res i)
+          (logior (the fixnum (bignum-ref a i))
+                  (the fixnum (bignum-ref b i)))))
+  (if (not (eql len-a len-b))
+    (bignum-replace res b :start1 len-a :start2 len-a :end1 len-b :end2 len-b))
+  (%normalize-bignum-macro res))
+
+;;; LOGIOR-SHORTER-NEGATIVE -- Internal.
+;;;
+;;; This takes a shorter bignum, a and len-a, that is negative.  Because this
+;;; is IOR, we just copy any bits longer than a's since its infinite 1 sign
+;;; bits will include any bits from b.  The result is len-b long.
+;;;
+(defun logior-shorter-negative (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (setf (bignum-ref res i)
+          (logior (the fixnum (bignum-ref a i))
+                  (the fixnum (bignum-ref b i)))))
+  (do ((i len-a (1+ i)))
+      ((= i len-b))
+    (declare (type bignum-index i))
+    (setf (bignum-ref res i) #xffffffff))
+  (%normalize-bignum-macro res))
+
+
+
+
+;;; XOR.
+;;;
+
+;;; BIGNUM-LOGICAL-XOR -- Public.
+;;;
+(defun bignum-logical-xor (a b)
+  (declare (type bignum-type a b))
+  (let ((len-a (%bignum-length a))
+	(len-b (%bignum-length b)))
+    (declare (type bignum-index len-a len-b))
+    (if (< len-a len-b)
+	(bignum-logical-xor-aux a len-a b len-b (%allocate-bignum len-b))
+	(bignum-logical-xor-aux b len-b a len-a (%allocate-bignum len-a)))))
+
+;;; BIGNUM-LOGICAL-XOR-AUX -- Internal.
+;;;
+;;; This takes the the shorter of two bignums in a and len-a.  Res is len-b
+;;; long.  Do the XOR.
+;;;
+(defun bignum-logical-xor-aux (a len-a b len-b res)
+  (declare (type bignum-type a b res)
+	   (type bignum-index len-a len-b))
+  (dotimes (i len-a)
+    (setf (bignum-ref res i)
+          (%logxor (the fixnum (bignum-ref a i))
+                  (the fixnum (bignum-ref b i)))))
+  (unless (= len-a len-b)
+    (let ((sign (if (bignum-minusp a) all-ones-digit 0)))
+      (declare (fixnum sign))
+      (do ((i len-a (1+ i)))
+          ((= i len-b))
+        (declare (type bignum-index i))
+        (setf (bignum-ref res i)
+              (%logxor (bignum-ref b i) sign)))))
+  (%normalize-bignum-macro res))
+
+
+
+;;;; TRUNCATE
+
+;;; Divide X by Y when Y is a single bignum digit. BIGNUM-TRUNCATE
+;;; fixes up the quotient and remainder with respect to sign and
+;;; normalization.
+;;;
+;;; We don't have to worry about shifting Y to make its most
+;;; significant digit sufficiently large for %FLOOR to return
+;;; digit-size quantities for the q-digit and r-digit. If Y is
+;;; a single digit bignum, it is already large enough for
+;;; %FLOOR. That is, it has some bits on pretty high in the
+;;; digit.
+
+(defun bignum-truncate-single-digit (x len-x y)
+  (declare (type bignum-index len-x))
+  (let ((q (%allocate-bignum len-x))
+        (r 0)
+        (y (bignum-ref y 0)))
+    (declare (type bignum-element-type r y))
+    (do ((i (1- len-x) (1- i)))
+        ((minusp i))
+      (multiple-value-bind (q-digit r-digit)
+          (%floor r (bignum-ref x i) y)
+        (declare (type bignum-element-type q-digit r-digit))
+        (setf (bignum-ref q i) q-digit)
+        (setf r r-digit)))
+    (let ((rem (%allocate-bignum 1)))
+      (setf (bignum-ref rem 0) r)
+      (values q rem))))
+
+;;; This returns a guess for the next division step. Y1 is the
+;;; highest y digit, and y2 is the second to highest y
+;;; digit. The x... variables are the three highest x digits
+;;; for the next division step.
+;;;
+;;; From Knuth, our guess is either all ones or x-i and x-i-1
+;;; divided by y1, depending on whether x-i and y1 are the
+;;; same. We test this guess by determining whether guess*y2
+;;; is greater than the three high digits of x minus guess*y1
+;;; shifted left one digit:
+;;;    ------------------------------
+;;;   |    x-i    |   x-i-1  | x-i-2 |
+;;;    ------------------------------
+;;;    ------------------------------
+;;; - | g*y1 high | g*y1 low |   0   |
+;;;    ------------------------------
+;;;		...		  <   guess*y2     ???	 
+;;; If guess*y2 is greater, then we decrement our guess by one
+;;; and try again.  This returns a guess that is either
+;;; correct or one too large.
+(defun bignum-truncate-guess (y1 y2 x-i x-i-1 x-i-2)
+  (declare (type bignum-element-type y1 y2 x-i x-i-1 x-i-2))
+  (let ((guess (if (= x-i y1)
+                 all-ones-digit
+                 (%floor x-i x-i-1 y1))))
+    (declare (type bignum-element-type guess))
+    (loop
+      (multiple-value-bind (high-guess*y1 low-guess*y1)
+          (%multiply guess y1)
+        (declare (type bignum-element-type low-guess*y1
+                       high-guess*y1))
+        (multiple-value-bind (high-guess*y2 low-guess*y2)
+            (%multiply guess y2)
+          (declare (type bignum-element-type high-guess*y2
+                         low-guess*y2))
+          (multiple-value-bind (middle-digit borrow)
+              (%subtract-with-borrow x-i-1 low-guess*y1 1)
+            (declare (type bignum-element-type middle-digit)
+                     (fixnum borrow))
+            ;; Supplying borrow of 1 means there was no
+            ;; borrow, and we know x-i-2 minus 0 requires
+            ;; no borrow.
+            (let ((high-digit (%subtract-with-borrow x-i
+                                                     high-guess*y1
+                                                     borrow)))
+              (declare (type bignum-element-type high-digit))
+              (if (and (= high-digit 0)
+                       (or (> high-guess*y2
+                              middle-digit)
+                           (and (= middle-digit
+                                   high-guess*y2)
+                                (> low-guess*y2
+                                   x-i-2))))
+                (setf guess (%subtract-with-borrow guess 1 1))
+                (return guess)))))))))
+
+
+;;; This returns the amount to shift y to place a one in the
+;;; second highest bit. Y must be positive. If the last digit
+;;; of y is zero, then y has a one in the previous digit's
+;;; sign bit, so we know it will take one less than digit-size
+;;; to get a one where we want. Otherwise, we count how many
+;;; right shifts it takes to get zero; subtracting this value
+;;; from digit-size tells us how many high zeros there are
+;;; which is one more than the shift amount sought.
+;;;
+;;; Note: This is exactly the same as one less than the
+;;; integer-length of the last digit subtracted from the
+;;; digit-size.
+;;;
+;;; We shift y to make it sufficiently large that doing the
+;;; 2*digit-size by digit-size %FLOOR calls ensures the quotient and
+;;; remainder fit in digit-size.
+(defun shift-y-for-truncate (y)
+  (the fixnum (1- (the fixnum (%bignum-sign-bits y)))))
+
+;;; Stores two bignums into the truncation bignum buffers,
+;;; shifting them on the way in. This assumes x and y are
+;;; positive and at least two in length, and it assumes
+;;; truncate-x and truncate-y are one digit longer than x and
+;;; y.
+(defun shift-and-store-truncate-buffers (truncate-x truncate-y x len-x y len-y shift)
+  (declare (type bignum-index len-x len-y)
+           (type (integer 0 (#.digit-size)) shift))
+  (cond ((zerop shift)
+         (bignum-replace truncate-x x :end1 len-x)
+         (bignum-replace truncate-y y :end1 len-y))
+        (t
+         (bignum-ashift-left-unaligned x 0 shift (1+ len-x)
+                                       truncate-x)
+         (bignum-ashift-left-unaligned y 0 shift (1+ len-y)
+                                       truncate-y))))
+
+;;; Divide TRUNCATE-X by TRUNCATE-Y, returning the quotient
+;;; and destructively modifying TRUNCATE-X so that it holds
+;;; the remainder.
+;;;
+;;; LEN-X and LEN-Y tell us how much of the buffers we care about.
+;;;
+;;; TRUNCATE-X definitely has at least three digits, and it has one
+;;; more than TRUNCATE-Y. This keeps i, i-1, i-2, and low-x-digit
+;;; happy. Thanks to SHIFT-AND-STORE-TRUNCATE-BUFFERS.
+
+(defun do-truncate (truncate-x truncate-y len-x len-y)
+  (declare (type bignum-index len-x len-y))
+  (let* ((len-q (- len-x len-y))
+         ;; Add one for extra sign digit in case high bit is on.
+         (q (%allocate-bignum (1+ len-q)))
+         (k (1- len-q))
+         (y1 (bignum-ref truncate-y (1- len-y)))
+         (y2 (bignum-ref truncate-y (- len-y 2)))
+         (i (1- len-x))
+         (i-1 (1- i))
+         (i-2 (1- i-1))
+         (low-x-digit (- i len-y)))
+    (declare (type bignum-index len-q k i i-1 i-2 low-x-digit)
+             (type bignum-element-type y1 y2))
+    (loop
+      (setf (bignum-ref q k)
+            (try-bignum-truncate-guess
+             truncate-x truncate-y
+             ;; This modifies TRUNCATE-X. Must access
+             ;; elements each pass.
+             (bignum-truncate-guess y1 y2
+                                    (bignum-ref truncate-x i)
+                                    (bignum-ref truncate-x i-1)
+                                    (bignum-ref truncate-x i-2))
+             len-y low-x-digit))
+      (cond ((zerop k) (return))
+            (t (decf k)
+               (decf low-x-digit)
+               (shiftf i i-1 i-2 (1- i-2)))))
+    q))
+
+#+notyet
+(defun do-truncate-no-quo (truncate-x truncate-y len-x len-y)
+  (declare (type bignum-index len-x len-y))
+  (let* ((len-q (- len-x len-y))
+	 (k (1- len-q))
+	 (i (1- len-x))
+	 (low-x-digit (- i len-y)))
+    (declare (type bignum-index len-q k i  low-x-digit))
+    (loop
+      (let* ((guess (bignum-truncate-guess truncate-x i truncate-y (the fixnum (1- len-y)))                                 
+        (try-bignum-truncate-guess guess len-y low-x-digit)
+        (cond ((zerop k) (return))
+              (t (decf k)
+                 (decf low-x-digit)
+                 (setq i (1- i))))))
+    nil))))
+
+;;; This takes a digit guess, multiplies it by TRUNCATE-Y for a
+;;; result one greater in length than LEN-Y, and subtracts this result
+;;; from TRUNCATE-X. LOW-X-DIGIT is the first digit of X to start
+;;; the subtraction, and we know X is long enough to subtract a LEN-Y
+;;; plus one length bignum from it. Next we check the result of the
+;;; subtraction, and if the high digit in X became negative, then our
+;;; guess was one too big. In this case, return one less than GUESS
+;;; passed in, and add one value of Y back into X to account for
+;;; subtracting one too many. Knuth shows that the guess is wrong on
+;;; the order of 3/b, where b is the base (2 to the digit-size power)
+;;; -- pretty rarely.
+
+(defun try-bignum-truncate-guess (truncate-x truncate-y guess len-y low-x-digit)
+  (declare (type bignum-index low-x-digit len-y)
+           (type bignum-element-type guess))
+  (let ((carry-digit 0)
+        (borrow 1)
+        (i low-x-digit))
+    (declare (type bignum-element-type carry-digit)
+             (type bignum-index i)
+             (fixnum borrow))
+    ;; Multiply guess and divisor, subtracting from dividend
+    ;; simultaneously.
+    (dotimes (j len-y)
+      (multiple-value-bind (high-digit low-digit)
+          (%multiply-and-add3 guess
+                              (bignum-ref truncate-y j)
+                              carry-digit)
+        (declare (type bignum-element-type high-digit low-digit))
+        (setf carry-digit high-digit)
+        (multiple-value-bind (x temp-borrow)
+            (%subtract-with-borrow (bignum-ref truncate-x i)
+                                   low-digit
+                                   borrow)
+          (declare (type bignum-element-type x)
+                   (fixnum temp-borrow))
+          (setf (bignum-ref truncate-x i) x)
+          (setf borrow temp-borrow)))
+      (incf i))
+    (setf (bignum-ref truncate-x i)
+          (%subtract-with-borrow (bignum-ref truncate-x i)
+                                 carry-digit borrow))
+    ;; See whether guess is off by one, adding one
+    ;; Y back in if necessary.
+    (cond ((%digit-0-or-plusp (bignum-ref truncate-x i))
+           guess)
+          (t
+           ;; If subtraction has negative result, add one
+           ;; divisor value back in. The guess was one too
+           ;; large in magnitude.
+           (let ((i low-x-digit)
+                 (carry 0))
+             (dotimes (j len-y)
+               (multiple-value-bind (v k)
+                   (%add-with-carry (bignum-ref truncate-y j)
+                                    (bignum-ref truncate-x i)
+                                    carry)
+                 (declare (type bignum-element-type v))
+                 (setf (bignum-ref truncate-x i) v)
+                 (setf carry k))
+               (incf i))
+             (setf (bignum-ref truncate-x i)
+                   (%add-with-carry (bignum-ref truncate-x i)
+                                    0 carry)))
+           (%subtract-with-borrow guess 1 1)))))
+
+;;; Someone (from the original CMUCL or SPICE Lisp project, perhaps)
+;;; is the "I" who implemented the original version of this.
+
+;;; This is the original sketch of the algorithm from which I implemented this
+;;; TRUNCATE, assuming both operands are bignums. I should modify this to work
+;;; with the documentation on my functions, as a general introduction. I've
+;;; left this here just in case someone needs it in the future. Don't look at
+;;; this unless reading the functions' comments leaves you at a loss. Remember
+;;; this comes from Knuth, so the book might give you the right general
+;;; overview.
+;;;
+;;; (truncate x y):
+;;;
+;;; If X's magnitude is less than Y's, then result is 0 with remainder X.
+;;;
+;;; Make x and y positive, copying x if it is already positive.
+;;;
+;;; Shift y left until there's a 1 in the 30'th bit (most significant, non-sign
+;;;       digit)
+;;;    Just do most sig digit to determine how much to shift whole number.
+;;; Shift x this much too.
+;;; Remember this initial shift count.
+;;;
+;;; Allocate q to be len-x minus len-y quantity plus 1.
+;;;
+;;; i = last digit of x.
+;;; k = last digit of q.
+;;;
+;;; LOOP
+;;;
+;;; j = last digit of y.
+;;;
+;;; compute guess.
+;;; if x[i] = y[j] then g = (1- (ash 1 digit-size))
+;;; else g = x[i]x[i-1]/y[j].
+;;;
+;;; check guess.
+;;; %UNSIGNED-MULTIPLY returns b and c defined below.
+;;;    a = x[i-1] - (logand (* g y[j]) #xFFFFFFFF).
+;;;       Use %UNSIGNED-MULTIPLY taking low-order result.
+;;;    b = (logand (ash (* g y[j-1]) (- digit-size)) (1- (ash 1 digit-size))).
+;;;    c = (logand (* g y[j-1]) (1- (ash 1 digit-size))).
+;;; if a < b, okay.
+;;; if a > b, guess is too high
+;;;    g = g - 1; go back to "check guess".
+;;; if a = b and c > x[i-2], guess is too high
+;;;    g = g - 1; go back to "check guess".
+;;; GUESS IS 32-BIT NUMBER, SO USE THING TO KEEP IN SPECIAL REGISTER
+;;; SAME FOR A, B, AND C.
+;;;
+;;; Subtract g * y from x[i - len-y+1]..x[i]. See paper for doing this in step.
+;;; If x[i] < 0, guess is screwed up.
+;;;    negative g, then add 1
+;;;    zero or positive g, then subtract 1
+;;; AND add y back into x[len-y+1..i].
+;;;
+;;; q[k] = g.
+;;; i = i - 1.
+;;; k = k - 1.
+;;;
+;;; If k>=0, goto LOOP.
+;;;
+;;; Now quotient is good, but remainder is not.
+;;; Shift x right by saved initial left shifting count.
+;;;
+;;; Check quotient and remainder signs.
+;;; x pos y pos --> q pos r pos
+;;; x pos y neg --> q neg r pos
+;;; x neg y pos --> q neg r neg
+;;; x neg y neg --> q pos r neg
+;;;
+;;; Normalize quotient and remainder. Cons result if necessary.
+
+
+(defun bignum-truncate (x y &optional no-rem)
+  (declare (type bignum-type x y))
+  (DECLARE (IGNORE NO-REM))
+  ;; Divide X by Y returning the quotient and remainder. In the
+  ;; general case, we shift Y to set up for the algorithm, and we
+  ;; use two buffers to save consing intermediate values. X gets
+  ;; destructively modified to become the remainder, and we have
+  ;; to shift it to account for the initial Y shift. After we
+  ;; multiple bind q and r, we first fix up the signs and then
+  ;; return the normalized results.
+  (let* ((x-plusp (%bignum-0-or-plusp x (%bignum-length x)))
+         (y-plusp (%bignum-0-or-plusp y (%bignum-length y)))
+         (x (if x-plusp x (negate-bignum x nil)))
+         (y (if y-plusp y (negate-bignum y nil)))
+         (len-x (%bignum-length x))
+         (len-y (%bignum-length y)))
+    (multiple-value-bind (q r)
+        (cond ((< len-y 2)
+               (bignum-truncate-single-digit x len-x y))
+              ((plusp (bignum-compare y x))
+               (let ((res (%allocate-bignum len-x)))
+                 (dotimes (i len-x)
+                   (setf (bignum-ref res i) (bignum-ref x i)))
+                 (values 0 res)))
+              (t
+               (let ((len-x+1 (1+ len-x)))
+                 (with-bignum-buffers ((truncate-x len-x+1)
+                                       (truncate-y (1+ len-y)))
+                   (let ((y-shift (shift-y-for-truncate y)))
+                     (shift-and-store-truncate-buffers truncate-x
+                                                       truncate-y
+                                                       x len-x
+                                                       y len-y
+                                                       y-shift)
+                     (values
+                      (do-truncate truncate-x
+                        truncate-y
+                        len-x+1
+                        len-y)
+                      ;; Now DO-TRUNCATE has executed, we just
+                      ;; tidy up the remainder (in TRUNCATE-X)
+                      ;; and return it.
+                      (cond
+                        ((zerop y-shift)
+                         (let ((res (%allocate-bignum len-y)))
+                           (declare (type bignum-type res))
+                           (bignum-replace res truncate-x :end2 len-y)
+                           (%normalize-bignum-macro res)))
+                        (t
+                         (shift-right-unaligned
+                          truncate-x 0 y-shift len-y
+                          ((= j res-len-1)
+                           (setf (bignum-ref res j)
+                                 (%ashr (bignum-ref truncate-x i)
+                                        y-shift))
+                           (%normalize-bignum-macro res))
+                          res)))))))))
+      (let ((quotient (cond ((eq x-plusp y-plusp) q)
+                            ((typep q 'fixnum) (the fixnum (- q)))
+                            (t (negate-bignum-in-place q))))
+            (rem (cond (x-plusp r)
+                       ((typep r 'fixnum) (the fixnum (- r)))
+                       (t (negate-bignum-in-place r)))))
+        (values (if (typep quotient 'fixnum)
+                  quotient
+                  (%normalize-bignum-macro quotient))
+                (if (typep rem 'fixnum)
+                  rem
+                  (%normalize-bignum-macro rem)))))))
+
+(defun bignum-truncate-by-fixnum (bignum fixnum)
+  (with-small-bignum-buffers ((y fixnum))
+    (bignum-truncate bignum y)))
+
+(defun bignum-truncate-by-fixnum-no-quo (bignum fixnum)
+  (nth-value 1 (bignum-truncate-by-fixnum bignum fixnum)))
+
+;;; This may do unnecessary computation in some cases.
+(defun bignum-rem (x y)
+  (nth-value 1 (bignum-truncate x y)))
+
+
+
+
+;;;; General utilities.
+
+(defun %zero-trailing-sign-digits (bignum len)
+  (declare (fixnum len))
+  (unless (<= len 1)
+    (do ((next (bignum-ref bignum (the fixnum (- len 2)))
+               (bignum-ref bignum (the fixnum (- len 2))))
+         (sign (bignum-ref bignum (the fixnum (- len 1)))
+               next))
+        ((not (zerop (the fixnum (%logxor sign (%ashr next 31))))))
+      (decf len)
+      (setf (bignum-ref bignum len) 0)
+      ;; Return, unless we've already done so (having found significant
+      ;; digits earlier.)
+      (when (= len 1)
+        (return))))
+  len)
+
+
+(defun %normalize-bignum-2 (return-fixnum-p bignum)
+  (let* ((len (%bignum-length bignum))
+         (newlen (%zero-trailing-sign-digits bignum len)))
+    (declare (fixnum len newlen))
+    (unless (= len newlen)
+      (%set-bignum-length newlen bignum))
+    (or (and return-fixnum-p
+             (%maybe-fixnum-from-one-or-two-digit-bignum bignum))
+        bignum)))
+           
+    
+;;; %MOSTLY-NORMALIZE-BIGNUM -- Internal.
+;;;
+;;; This drops the last digit if it is unnecessary sign information.  It
+;;; repeats this as needed, possibly ending with a fixnum magnitude but never
+;;; returning a fixnum.
+;;;
+
+(defun %mostly-normalize-bignum (res &optional len)
+  (declare (ignore len))
+  (%normalize-bignum-2 nil res))
+
+
+
+
+
+(defun load-byte (size position integer)
+  (if (and (bignump integer)
+           (<= size (- 63 target::fixnumshift))
+           (fixnump position))
+    (%ldb-fixnum-from-bignum integer size position)
+    (let ((mask (byte-mask size)))
+      (if (and (fixnump mask) (fixnump integer)(fixnump position))
+        (%ilogand mask (%iasr position integer))
+        (logand mask (ash integer (- position)))))))
+
+
+#+safe-but-slow
+;;; This is basically the same algorithm as the "destructive"
+;;; version below; while it may be more readable, it's often
+;;; slower and conses too much to be at all viable.
+(defun %bignum-bignum-gcd (u v)
+  (setq u (abs u) v (abs v))
+  (do* ((g 1 (ash g 1)))
+       ((or (oddp u) (oddp v))
+	(do* ()
+	     ((zerop u) (* g v))
+	  (cond ((evenp u) (setq u (ash u -1)))
+		((evenp v) (setq v (ash v -1)))
+		(t (let* ((temp (ash (abs (- u v)) -1)))
+		     (if (< u v)
+		       (setq v temp)
+		       (setq u temp)))))))
+    (setq u (ash u -1) v (ash v -1))))
+
+
+
+
+#-safe-but-slow
+(progn
+(defun %positive-bignum-bignum-gcd (u0 v0)
+  (let* ((u-len (%bignum-length u0))
+	 (v-len (%bignum-length v0)))
+    (declare (fixnum u-len v-len))
+    (if (or (< u-len v-len)
+	    (and (= u-len v-len)
+		 (< (bignum-compare u0 v0) 0)))
+      (psetq u0 v0 v0 u0 u-len v-len v-len u-len))
+    (with-bignum-buffers ((u u-len)
+			  (u2 u-len)
+			  (v v-len)
+			  (v2 v-len))
+      (bignum-replace u u0)
+      (bignum-replace v v0)
+      (let* ((u-trailing-0-bits (%bignum-count-trailing-zero-bits u))
+	     (u-trailing-0-digits (ash u-trailing-0-bits -5))
+	     (v-trailing-0-bits (%bignum-count-trailing-zero-bits v))
+	     (v-trailing-0-digits (ash v-trailing-0-bits -5)))
+	(declare (fixnum u-trailing-0-bits v-trailing-0-bits))
+	(unless (zerop u-trailing-0-bits)
+	  (bignum-shift-right-loop-1
+	   (logand u-trailing-0-bits 31)
+	   u2
+	   u
+	   (the fixnum (1- (the fixnum (- u-len u-trailing-0-digits ))))
+	   u-trailing-0-digits)
+	  (rotatef u u2)
+	  (%mostly-normalize-bignum-macro u)
+	  (setq u-len (%bignum-length u)))
+	(unless (zerop v-trailing-0-bits)
+	  (bignum-shift-right-loop-1
+	   (logand v-trailing-0-bits 31)
+	   v2
+	   v
+	   (the fixnum (1- (the fixnum (- v-len v-trailing-0-digits))))
+	   v-trailing-0-digits)
+	  (rotatef v v2)
+	  (%mostly-normalize-bignum-macro v)
+	  (setq v-len (%bignum-length v)))
+	(let* ((shift (min u-trailing-0-bits
+			   v-trailing-0-bits)))
+	  (loop
+	      (let* ((fix-u (and (<= u-len 2)
+                                 (%maybe-fixnum-from-one-or-two-digit-bignum u)))
+		     (fix-v (and (<= v-len 2)
+                                 (%maybe-fixnum-from-one-or-two-digit-bignum v))))
+		(if fix-v
+		  (if fix-u
+		    (return (ash (%fixnum-gcd fix-u fix-v) shift))
+		    (return (ash (bignum-fixnum-gcd u fix-v) shift)))
+		  (if fix-u
+		    (return (ash (bignum-fixnum-gcd v fix-u) shift)))))
+	      (let* ((signum (if (> u-len v-len)
+			       1
+			       (if (< u-len v-len)
+				 -1
+				 (bignum-compare u v)))))
+		(declare (fixnum signum))
+		(case signum
+		  (0			; (= u v)
+		   (if (zerop shift)
+		     (let* ((copy (%allocate-bignum u-len)))
+		       (bignum-replace copy u)
+		       (return copy))
+		     (return (ash u shift))))
+		  (1			; (> u v)
+		   (bignum-subtract-loop u u-len v v-len u)
+		   (%mostly-normalize-bignum-macro u)
+		   (setq u-len (%bignum-length u))
+		   (setq u-trailing-0-bits
+			 (%bignum-count-trailing-zero-bits u)
+			 u-trailing-0-digits
+			 (ash u-trailing-0-bits -5))
+                   (unless (zerop u-trailing-0-bits)
+                     (%init-misc 0 u2)
+                     (bignum-shift-right-loop-1
+                      (logand u-trailing-0-bits 31)
+                      u2
+                      u
+                      (the fixnum (1- (the fixnum (- u-len
+                                                     u-trailing-0-digits))))
+                      u-trailing-0-digits)
+                     (rotatef u u2)
+                     (%mostly-normalize-bignum-macro u)
+                     (setq u-len (%bignum-length u))))
+		  (t			; (> v u)
+		   (bignum-subtract-loop v v-len u u-len v)
+		   (%mostly-normalize-bignum-macro v)
+		   (setq v-len (%bignum-length v))
+		   (setq v-trailing-0-bits
+			 (%bignum-count-trailing-zero-bits v)
+			 v-trailing-0-digits
+			 (ash v-trailing-0-bits -5))
+                   (unless (zerop v-trailing-0-bits)
+                     (%init-misc 0 v2)
+                     (bignum-shift-right-loop-1
+                      (logand v-trailing-0-bits 31)
+                      v2
+                      v
+                      (the fixnum (1- (the fixnum (- v-len v-trailing-0-digits))))
+                      v-trailing-0-digits)
+                     (rotatef v v2)
+                     (%mostly-normalize-bignum-macro v)
+                     (setq v-len (%bignum-length v))))))))))))
+
+(defun %bignum-bignum-gcd (u v)
+  (with-negated-bignum-buffers u v %positive-bignum-bignum-gcd))
+)
+
+
+(defun bignum-shift-right-loop-1 (nbits result source len idx)
+  (declare (type bignum-type result source)
+           (type (mod 32) nbits)
+           (type bignum-index idx len))
+  (let* ((rbits (- 32 nbits)))
+    (declare (type (mod 33) rbits))
+    (dotimes (j len)
+      (let* ((x (bignum-ref source idx)))
+        (declare (type bignum-element-type x))
+        (setq x (%ilsr nbits x))
+        (incf idx)
+        (let* ((y (bignum-ref source idx)))
+          (declare (type bignum-element-type y))
+          (setq y (%ashl y rbits))
+          (setf (bignum-ref result j)
+                (%logior x y)))))
+    (setf (bignum-ref result len)
+          (%ilsr nbits (bignum-ref source idx)))
+    idx))
+    
+
+(defun %logcount (bignum idx)
+  (%ilogcount (bignum-ref bignum idx)))
+
+(defun %logcount-complement (bignum idx)
+  (- 32 (the fixnum (%ilogcount (bignum-ref bignum idx)))))
+
+(defun %bignum-evenp (bignum)
+  (not (logbitp 0 (the fixnum (bignum-ref bignum 0)))))
+
+(defun %bignum-oddp (bignum)
+  (logbitp 0 (the fixnum (bignum-ref bignum 0))))
+
+(defun %ldb-fixnum-from-bignum (bignum size position)
+  (declare (fixnum size position))
+  (let* ((low-idx (ash position -5))
+         (low-bit (logand position 31))
+         (hi-bit (+ low-bit size))
+         (len (%bignum-length bignum))
+         (minusp (bignum-minusp bignum)))
+    (declare (fixnum size position low-bit hi-bit low-idx len))
+    (if (>= low-idx len)
+      (if minusp (1- (ash 1 size)) 0)
+      (flet ((ldb32 (digit size pos)
+               (declare (fixnum digit size pos))
+               (logand (the fixnum (1- (ash 1 size)))
+                       (the fixnum (ash digit (the fixnum (- pos)))))))
+        (let* ((low-digit (bignum-ref bignum low-idx))
+               (chunk-lo (ldb32 low-digit (min size (%i- 32 low-bit)) low-bit)))
+          (if (< hi-bit 32) 
+            chunk-lo
+            (let* ((have (- 32 low-bit))
+                   (remain (- size have)))
+              (declare (fixnum have remain))
+              (setq low-idx (1+ low-idx))
+              (when (> remain 32)
+                (setq chunk-lo
+                      (logior (ash (if (< low-idx len)
+                                     (bignum-ref bignum low-idx)
+                                     (if minusp all-ones-digit 0))
+                                   have)
+                              chunk-lo))
+                (incf have 32)
+                (decf remain 32)
+                (incf low-idx))
+              (let* ((high-digit
+                      (if (>= low-idx len)
+                        (if minusp all-ones-digit 0)
+                        (bignum-ref bignum low-idx)))
+                     (chunk-hi (ldb32 high-digit remain 0)))
+                (%ilogior (ash chunk-hi have) chunk-lo)))))))))
+
+
+
+(defun bignum-negate-loop-really (big len res)
+  (declare (fixnum len))
+  (let* ((carry 1))
+    (dotimes (i len carry)
+      (multiple-value-bind (result-digit carry-out)
+          (%add-with-carry (%lognot (bignum-ref big i)) 0 carry)
+        (setf (bignum-ref res i) result-digit
+              carry carry-out)))))
+
+(defun bignum-negate-to-pointer (big len res)
+  (declare (fixnum len))
+  (let* ((carry 1))
+    (do* ((i 0 (1+ i))
+          (j 0 (+ j 4)))
+         ((= i len) carry)
+      (declare (fixnum i))
+      (multiple-value-bind (result-digit carry-out)
+          (%add-with-carry (%lognot (bignum-ref big i)) 0 carry)
+        (setf (%get-unsigned-long res j) result-digit
+              carry carry-out)))))
+  
+
+(defun %bignum-count-trailing-zero-bits (bignum)
+  (let* ((count 0))
+    (dotimes (i (%bignum-length bignum))
+      (let* ((digit (bignum-ref bignum i)))
+        (declare (type bignum-element-type digit))
+        (if (zerop digit)
+          (incf count 32)
+          (progn
+            (dotimes (bit 32)
+              (declare (type (mod 32) bit))
+              (if (logbitp bit digit)
+                (return)
+                (incf count)))
+            (return)))))
+    count))
+                  
+
+(defun one-bignum-factor-of-two (a)  
+  (declare (type bignum-type a))
+  (let ((len (%bignum-length a)))
+    (declare (fixnum len))
+    (dotimes (i len)
+      (let* ((x (bignum-ref a i)))
+        (declare (fixnum x))
+        (unless (zerop x)
+          (return (+ (ash i 5)
+                     (dotimes (j 32)
+                       (if (logbitp j x)
+                         (return j))))))))))
+
+
+(defun %bignum-random (number state)
+  (let* ((ndigits (%bignum-length number))
+         (sign-index (1- ndigits)))
+    (declare (fixnum ndigits sign-index))
+    (with-bignum-buffers ((bignum ndigits))
+      (dotimes (i sign-index)
+        (setf (bignum-ref bignum i) (%next-random-seed state)))
+      (setf (bignum-ref bignum sign-index)
+            (logand #x7fffffff (the (unsigned-byte 32)
+                                 (%next-random-seed state))))
+      (let* ((result (mod bignum number)))
+        (if (eq result bignum)
+          (copy-uvector bignum)
+          result)))))
+
+
+
+(defun logbitp (index integer)
+  "Predicate returns T if bit index of integer is a 1."
+  (number-case index
+    (fixnum
+     (if (minusp (the fixnum index))(report-bad-arg index '(integer 0))))
+    (bignum
+     ;; assuming bignum cant have more than most-positive-fixnum bits
+     ;; (2 expt 24 longs)
+     (if (bignum-minusp index)(report-bad-arg index '(integer 0)))
+     ;; should error if integer isn't
+     (return-from logbitp (minusp (require-type integer 'integer)))))
+  (number-case integer
+    (fixnum
+     (if (%i< index (- target::nbits-in-word target::fixnumshift))
+       (%ilogbitp index integer)
+       (minusp (the fixnum integer))))
+    (bignum
+     (let ((bidx (%iasr 5 index))
+           (bbit (%ilogand index 31)))
+       (declare (fixnum bidx bbit))
+       (if (>= bidx (%bignum-length integer))
+         (bignum-minusp integer)
+         (logbitp bbit (bignum-ref integer bidx)))))))
+
+) ; #+64-bit-target
Index: /branches/new-random/level-0/l0-cfm-support.lisp
===================================================================
--- /branches/new-random/level-0/l0-cfm-support.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-cfm-support.lisp	(revision 13309)
@@ -0,0 +1,992 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+; l0-cfm-support.lisp
+
+(in-package "CCL")
+
+#+windows-target
+(progn
+  (defvar *windows-invalid-handle* nil)
+  (setq *windows-invalid-handle* (%int-to-ptr #+64-bit-target #xffffffffffffffff #+32-bit-target #xffffffff)))
+
+
+;;; We have several different conventions for representing an
+;;; "entry" (a foreign symbol address, possibly represented as
+;;; something cheaper than a MACPTR.)  Destructively modify
+;;; ADDR so that it points to where ENTRY points.
+(defun entry->addr (entry addr)
+  #+ppc32-target
+  ;; On PPC32, all function addresses have their low 2 bits clear;
+  ;; so do fixnums.
+  (%setf-macptr-to-object addr entry)
+  #+ppc64-target
+  ;; On PPC64, some addresses can use the fixnum trick.  In other
+  ;; cases, an "entry" is just a MACPTR.
+  (if (typep entry 'fixnum)
+    (%setf-macptr-to-object addr entry)
+    (%setf-macptr addr entry))
+  ;; On x86, an "entry" is just an integer.  There might elswehere be
+  ;; some advantage in treating those integers as signed (they might
+  ;; be more likely to be fixnums, for instance), so ensure that they
+  ;; aren't.
+  #+x86-target
+  (%setf-macptr addr (%int-to-ptr
+                      (if (< entry 0)
+                        (logand entry (1- (ash 1 target::nbits-in-word)))
+                        entry)))
+  #-(or ppc-target x86-target) (dbg "Fix entry->addr"))
+
+
+
+
+;;; Bootstrapping. Real version is in l1-aprims.
+;;; Called by expansion of with-pstrs
+
+(defun byte-length (string &optional script start end)
+    (declare (ignore script))
+    (when (or start end)
+      (error "Don't support start or end args yet"))
+    (if (base-string-p string)
+      (length string)
+      (error "Don't support non base-string yet.")))
+
+
+
+
+(defun external-entry-point-p (x)
+  (istruct-typep x 'external-entry-point))
+
+;;; On both Linux and FreeBSD, RTLD_NEXT and RTLD_DEFAULT behave
+;;; the same way wrt symbols defined somewhere other than the lisp
+;;; kernel.  On Solaris, RTLD_DEFAULT will return the address of
+;;; an imported symbol's procedure linkage table entry if the symbol
+;;; has a plt entry (e.g., if it happens to be referenced by the
+;;; lisp kernel.)  *RTLD-NEXT* is therefore a slightly better
+;;; default; we've traditionaly used *RTLD-DEFAULT*.  
+(defvar *rtld-next*)
+(defvar *rtld-default*)
+(defvar *rtld-use*)
+(setq *rtld-next* (%incf-ptr (%null-ptr) -1)
+      *rtld-default* (%int-to-ptr #+(or linux-target darwin-target windows-target)  0
+				  #-(or linux-target darwin-target windows-target)  -2)
+      *rtld-use* #+solaris-target *rtld-next* #-solaris-target *rtld-default*)
+
+#+(or linux-target freebsd-target solaris-target)
+(progn
+
+(defvar *dladdr-entry*)
+  
+;;; I can't think of a reason to change this.
+(defvar *dlopen-flags* nil)
+(setq *dlopen-flags* (logior #$RTLD_GLOBAL #$RTLD_NOW))
+)
+
+(defvar *eeps* nil)
+
+(defvar *fvs* nil)
+
+(defun eeps ()
+  (or *eeps*
+      (setq *eeps* (make-hash-table :test #'equal))))
+
+(defun fvs ()
+  (or *fvs*
+      (setq *fvs* (make-hash-table :test #'equal))))
+
+(defun unload-foreign-variables (lib)
+  (let* ((fvs (fvs)))
+    (when fvs
+      (maphash #'(lambda (k fv)
+                   (declare (ignore k))
+                   (when (eq (fv.container fv) lib)
+                     (setf (fv.addr fv) nil)))
+               fvs))))
+
+(defun generate-external-functions (path)
+  (let* ((names ()))
+    (maphash #'(lambda (k ignore)
+		 (declare (ignore ignore))
+		 (push k names)) (eeps))
+    (with-open-file (stream path
+			    :direction :output
+			    :if-exists :supersede
+			    :if-does-not-exist :create)
+      (dolist (k names) (format stream "~&extern void * ~a();" k))
+     
+      (format stream "~&external_function external_functions[] = {")
+      (dolist (k names) (format stream "~&~t{~s,~a}," k k))
+      (format stream "~&~t{0,0}~&};"))))
+
+    
+(defvar *shared-libraries* nil)
+
+#+(or linux-target freebsd-target solaris-target)
+(progn
+
+(defun soname-ptr-from-link-map (map)
+  (let* ((path (pref map :link_map.l_name)))
+    (if (%null-ptr-p path)
+      (let* ((p (malloc 1)))
+        (setf (%get-unsigned-byte p 0) 0)
+        p)
+      (if (eql (%get-unsigned-byte path 0) 0)
+        path
+        (with-macptrs ((dyn-strings)
+                       (dynamic-entries (pref map :link_map.l_ld)))
+          (let* ((soname-offset nil))
+            ;; Walk over the entries in the file's dynamic segment; the
+            ;; last such entry will have a tag of #$DT_NULL.  Note the
+            ;; (loaded,on Linux; relative to link_map.l_addr on FreeBSD)
+            ;; address of the dynamic string table and the offset of the
+            ;; #$DT_SONAME string in that string table.
+            ;; Actually, the above isn't quite right; there seem to
+            ;; be cases (involving vDSO) where the address of a library's
+            ;; dynamic string table is expressed as an offset relative
+            ;; to link_map.l_addr as well.
+            (loop
+              (case #+32-bit-target (pref dynamic-entries :<E>lf32_<D>yn.d_tag)
+                    #+64-bit-target (pref dynamic-entries :<E>lf64_<D>yn.d_tag)
+                    (#. #$DT_NULL (return))
+                    (#. #$DT_SONAME
+                        (setq soname-offset
+                              #+32-bit-target (pref dynamic-entries
+                                                    :<E>lf32_<D>yn.d_un.d_val)
+                              #+64-bit-target (pref dynamic-entries
+                                                    :<E>lf64_<D>yn.d_un.d_val)))
+                    (#. #$DT_STRTAB
+                        (%setf-macptr dyn-strings
+                                      ;; Try to guess whether we're dealing
+                                      ;; with a displacement or with an
+                                      ;; absolute address.  There may be
+                                      ;; a better way to determine this,
+                                      ;; but for now we assume that absolute
+                                      ;; addresses aren't negative and that
+                                      ;; displacements are.
+                                      (let* ((disp (%get-signed-natural
+                                                    dynamic-entries
+                                                    target::node-size)))
+                                        #+(or freebsd-target solaris-target)
+                                        (%inc-ptr (pref map :link_map.l_addr) disp)
+                                        #-(or freebsd-target solaris-target)
+                                        (let* ((udisp #+32-bit-target (pref dynamic-entries
+                                                                            :<E>lf32_<D>yn.d_un.d_val)
+                                                      #+64-bit-target (pref dynamic-entries
+                                                                            :<E>lf64_<D>yn.d_un.d_val)))
+                                          (if (and (> udisp (pref map :link_map.l_addr))
+                                                   (< udisp (%ptr-to-int dynamic-entries)))
+                                            (%int-to-ptr udisp)
+                                            (%int-to-ptr 
+                                             (if (< disp 0) 
+                                               (+ disp (pref map :link_map.l_addr))
+                                               disp))))))))
+              (%setf-macptr dynamic-entries
+                            (%inc-ptr dynamic-entries
+                                      #+32-bit-target
+                                      (record-length :<E>lf32_<D>yn)
+                                      #+64-bit-target
+                                      (record-length :<E>lf64_<D>yn))))
+            (if (and soname-offset
+                     (not (%null-ptr-p dyn-strings)))
+              (%inc-ptr dyn-strings soname-offset)
+              ;; Use the full pathname of the library.
+             (pref map :link_map.l_name))))))))
+
+(defun shared-library-at (base)
+  (dolist (lib *shared-libraries*)
+    (when (eql (shlib.base lib) base)
+      (return lib))))
+
+(defun shared-library-with-name (name)
+  (let* ((namelen (length name)))
+    (dolist (lib *shared-libraries*)
+      (let* ((libname (shlib.soname lib)))
+	(when (%simple-string= name libname 0 0 namelen (length libname))
+	  (return lib))))))
+
+(defun shlib-from-map-entry (m)
+  (let* ((base (%int-to-ptr (pref m :link_map.l_addr))))
+    ;; On relatively modern Linux systems, this is often NULL.
+    ;; I'm not sure what (SELinux ?  Pre-binding ?  Something else ?)
+    ;; counts as being "relatively modern" in this case.
+    ;; The link-map's l_ld field is a pointer to the .so's dynamic
+    ;; section, and #_dladdr seems to recognize that as being an
+    ;; address within the library and returns a reasonable "base address".
+    (when (%null-ptr-p base)
+      (let* ((addr (%library-base-containing-address (pref m :link_map.l_ld))))
+        (if addr (setq base addr))))
+    (or (let* ((existing-lib (shared-library-at base)))
+	  (when (and existing-lib (null (shlib.map existing-lib)))
+	    (setf (shlib.map existing-lib) m
+		  (shlib.pathname existing-lib)
+		  (%get-cstring (pref m :link_map.l_name))
+		  (shlib.base existing-lib) base))
+	  existing-lib)
+        (let* ((soname-ptr (soname-ptr-from-link-map m))
+               (soname (unless (%null-ptr-p soname-ptr) (%get-cstring soname-ptr)))
+               (pathname (%get-cstring (pref m :link_map.l_name)))
+	       (shlib (shared-library-with-name soname)))
+	  (if shlib
+	    (setf (shlib.map shlib) m
+		  (shlib.base shlib) base
+		  (shlib.pathname shlib) pathname)
+	    (push (setq shlib (%cons-shlib soname pathname m base))
+		  *shared-libraries*))
+          shlib))))
+
+
+(defun %get-r-debug ()
+  (let* ((addr (ff-call (%kernel-import target::kernel-import-get-r-debug)
+			address)))
+    (unless (%null-ptr-p addr)
+      addr)))
+
+(defun %link-map-address ()
+  (let* ((r_debug (%get-r-debug)))
+    (if r_debug
+      (pref r_debug :r_debug.r_map)
+      (let* ((p (or (foreign-symbol-address "_dl_loaded")
+		    (foreign-symbol-address "_rtld_global"))))
+	(if p
+	  (%get-ptr p))))))
+
+(defun %walk-shared-libraries (f)
+  (let* ((loaded (%link-map-address)))
+    (do* ((map (pref loaded :link_map.l_next) (pref map :link_map.l_next)))
+         ((%null-ptr-p map))
+      (funcall f map))))
+
+
+(defun %dlopen-shlib (l)
+  (with-cstrs ((n (shlib.soname l)))
+    (ff-call (%kernel-import target::kernel-import-GetSharedLibrary)
+	     :address n
+	     :unsigned-fullword *dlopen-flags*
+	     :void)))
+  
+(defun init-shared-libraries ()
+  (setq *dladdr-entry* (foreign-symbol-entry "dladdr"))
+  (when (null *shared-libraries*)
+    (%walk-shared-libraries #'shlib-from-map-entry)
+      ;;; On Linux, it seems to be necessary to open each of these
+      ;;; libraries yet again, specifying the RTLD_GLOBAL flag.
+      ;;; On FreeBSD, it seems desirable -not- to do that.
+    #+linux-target
+    (dolist (l *shared-libraries*)
+      (%dlopen-shlib l))))
+
+(init-shared-libraries)
+
+;;; Walk over all registered entrypoints, invalidating any whose container
+;;; is the specified library.  Return true if any such entrypoints were
+;;; found.
+(defun unload-library-entrypoints (lib)
+  (let* ((count 0))
+    (declare (fixnum count))
+    (maphash #'(lambda (k eep)
+		 (declare (ignore k))
+		 (when (eq (eep.container eep) lib)
+		   (setf (eep.address eep) nil)
+		   (incf count)))
+	     (eeps))    
+    (not (zerop count))))
+
+
+                     
+                     
+
+(defun open-shared-library (name)
+  "If the library denoted by name can be loaded by the operating system,
+return an object of type SHLIB that describes the library; if the library
+is already open, increment a reference count. If the library can't be
+loaded, signal a SIMPLE-ERROR which contains an often-cryptic message from
+the operating system."
+  (let* ((handle (with-cstrs ((name name))
+                        (ff-call
+                         (%kernel-import target::kernel-import-GetSharedLibrary)
+                         :address name
+                         :unsigned-fullword *dlopen-flags*
+                         :address)))
+         (link-map #-(or freebsd-target solaris-target) handle
+                   #+(or freebsd-target solaris-target)
+                   (if (%null-ptr-p handle)
+                     handle
+                     (rlet ((p :address))
+                       (if (eql 0 (ff-call
+                                   (foreign-symbol-entry "dlinfo")
+                                   :address handle
+                                   :int #$RTLD_DI_LINKMAP
+                                   :address p
+                                   :int))
+                         (pref p :address)
+                         (%null-ptr))))))
+    (if (%null-ptr-p link-map)
+      (error "Error opening shared library ~s: ~a" name (dlerror))
+      (prog1 (let* ((lib (shlib-from-map-entry link-map)))
+	       (incf (shlib.opencount lib))
+               (setf (shlib.handle lib) handle)
+	       lib)
+	(%walk-shared-libraries
+	 #'(lambda (map)
+	     (unless (shared-library-at
+		      (%int-to-ptr (pref map :link_map.l_addr)))
+	       (let* ((new (shlib-from-map-entry map)))
+		 (%dlopen-shlib new)))))))))
+
+)
+
+
+#+darwin-target
+(progn
+
+(defun shared-library-with-header (header)
+  (dolist (lib *shared-libraries*)
+    (when (eql (shlib.map lib) header)
+      (return lib))))
+
+(defun shared-library-with-module (module)
+  (dolist (lib *shared-libraries*)
+    (when (eql (shlib.base lib) module)
+      (return lib))))
+
+(defun shared-library-with-name (name &optional (is-unloaded nil))
+  (let* ((namelen (length name)))
+    (dolist (lib *shared-libraries*)
+      (let* ((libname (shlib.soname lib)))
+	(when (and (%simple-string= name libname 0 0 namelen (length libname))
+		   (or (not is-unloaded) (and (null (shlib.map lib))
+					      (null (shlib.base lib)))))
+	  (return lib))))))
+
+;;;    
+;;; maybe we could fix this up name to get the "real name"
+;;; this is might be possible for dylibs but probably not for modules
+;;; for now soname and pathname are just the name that the user passed in
+;;; if the library is "discovered" later, it is the name the system gave
+;;; to it -- usually a full pathname
+;;;
+;;; header and module are ptr types
+;;;
+(defun shared-library-from-header-module-or-name (header module name)
+  ;; first try to find the library based on its address
+  (let ((found-lib (if (%null-ptr-p module)
+		       (shared-library-with-header header)
+		     (shared-library-with-module module))))
+    
+    (unless found-lib
+      ;; check if the library name is still on our list but has been unloaded
+      (setq found-lib (shared-library-with-name name t))
+      (if found-lib
+	(setf (shlib.map found-lib) header
+	      (shlib.base found-lib) module)
+	;; otherwise add it to the list
+	(push (setq found-lib (%cons-shlib name name header module))
+	      *shared-libraries*)))
+    found-lib))
+
+
+(defun open-shared-library (name)
+  "If the library denoted by name can be loaded by the operating system,
+return an object of type SHLIB that describes the library; if the library
+is already open, increment a reference count. If the library can't be
+loaded, signal a SIMPLE-ERROR which contains an often-cryptic message from
+the operating system."
+  (rlet ((type :signed))
+    (let ((result (with-cstrs ((cname name))
+		    (ff-call (%kernel-import target::kernel-import-GetSharedLibrary)
+			     :address cname
+			     :address type
+			     :address))))
+	(cond
+	 ((= 1 (pref type :signed))
+	  ;; dylib
+	  (shared-library-from-header-module-or-name result (%null-ptr) name))
+	 ((= 2 (pref type :signed))
+	  ;; bundle
+	  (shared-library-from-header-module-or-name (%null-ptr) result name))
+	 ((= 0 (pref type :signed))
+	  ;; neither a dylib nor bundle was found
+	  (error "Error opening shared library ~s: ~a" name
+		 (%get-cstring result)))
+	 (t (error "Unknown error opening shared library ~s." name))))))
+
+;;; Walk over all registered entrypoints, invalidating any whose container
+;;; is the specified library.  Return true if any such entrypoints were
+;;; found.
+;;;
+;;; SAME AS LINUX VERSION
+;;;
+(defun unload-library-entrypoints (lib)
+  (let* ((count 0))
+    (declare (fixnum count))
+    (maphash #'(lambda (k eep)
+		 (declare (ignore k))
+		 (when (eq (eep.container eep) lib)
+		   (setf (eep.address eep) nil)
+		   (incf count)))
+	     (eeps))    
+    (not (zerop count))))
+
+;;;
+;;; When restarting from a saved image
+;;;
+(defun reopen-user-libraries ()
+  (dolist (lib *shared-libraries*)
+    (setf (shlib.map lib) nil
+	  (shlib.base lib) nil))
+  (loop
+      (let* ((win nil)
+	     (lose nil))
+	(dolist (lib *shared-libraries*)
+	  (let* ((header (shlib.map lib))
+		 (module (shlib.base lib)))
+	    (unless (and header module)
+	      (rlet ((type :signed))
+		(let ((result (with-cstrs ((cname (shlib.soname lib)))
+				(ff-call (%kernel-import target::kernel-import-GetSharedLibrary)
+					 :address cname
+					 :address type
+					 :address))))
+		  (cond
+		   ((= 1 (pref type :signed))
+		    ;; dylib
+		    (setf (shlib.map lib) result
+			  (shlib.base lib) (%null-ptr)
+			  win t))
+		   ((= 2 (pref type :signed))
+		    ;; bundle
+		    (setf (shlib.map lib) (%null-ptr)
+			  (shlib.base lib) result
+			  win t))
+		   (t
+		    ;; neither a dylib nor bundle was found
+		    (setq lose t))))))))
+	(when (or (not lose) (not win)) (return)))))
+
+;;; end darwin-target
+  )  
+
+#+windows-target
+(progn
+  (defvar *current-process-handle*)
+  (defvar *enum-process-modules-addr*)
+  (defvar *get-module-file-name-addr*)
+  (defvar *get-module-base-name-addr*)
+  (defvar *get-module-handle-ex-addr*)
+
+
+  (defun init-windows-ffi ()
+    (%revive-macptr *windows-invalid-handle*)
+    (setq *current-process-handle* (ff-call (foreign-symbol-entry "GetCurrentProcess") :address)) 
+    (setq *enum-process-modules-addr* (foreign-symbol-entry "EnumProcessModules"))   
+    (setq *get-module-file-name-addr* (foreign-symbol-entry "GetModuleFileNameA"))
+    (setq *get-module-base-name-addr* (foreign-symbol-entry "GetModuleBaseNameA"))
+    (setq *get-module-handle-ex-addr* (foreign-symbol-entry "GetModuleHandleExA")))
+
+  (init-windows-ffi)
+  
+  (defun hmodule-pathname (hmodule)
+    (do* ((bufsize 64))
+         ()
+      (%stack-block ((name bufsize))
+        (let* ((needed (ff-call *get-module-file-name-addr*
+                                :address *current-process-handle*
+                                :address hmodule
+                                :address name
+                                :signed-fullword bufsize
+                                :signed-fullword)))
+          (if (eql 0 needed)
+            (return nil)
+            (if (< bufsize needed)
+              (setq bufsize needed)
+              (return (%str-from-ptr name needed))))))))
+
+  (defun hmodule-basename (hmodule)
+    (do* ((bufsize 64))
+         ()
+      (%stack-block ((name bufsize))
+        (let* ((needed (ff-call *get-module-base-name-addr*
+                                :address *current-process-handle*
+                                :address hmodule
+                                :address name
+                                :signed-fullword bufsize
+                                :signed-fullword)))
+          (if (eql 0 needed)
+            (return nil)
+            (if (< bufsize needed)
+              (setq bufsize needed)
+              (return (%str-from-ptr name needed))))))))
+
+  (defun existing-shlib-for-hmodule (hmodule)
+    (dolist (shlib *shared-libraries*)
+      (when (eql hmodule (shlib.map shlib)) (return shlib))))
+      
+  
+  (defun shared-library-from-hmodule (hmodule)
+    (or (existing-shlib-for-hmodule hmodule)
+        (let* ((shlib (%cons-shlib (hmodule-basename hmodule)
+                                   (hmodule-pathname hmodule)
+                                   hmodule
+                                   hmodule)))
+          (push shlib *shared-libraries*)
+          shlib)))
+
+  (defun for-each-loaded-module (f)
+    (let* ((have (* 16 (record-length #>HMODULE))))
+      (rlet ((pneed #>DWORD))
+        (loop
+          (%stack-block ((modules have))
+            (ff-call *enum-process-modules-addr*
+                     :address *current-process-handle*
+                     :address modules
+                     #>DWORD have
+                     :address pneed)
+            (let* ((need (pref pneed #>DWORD)))
+              (if (> need have)
+                (setq have need)
+                (return
+                  (do* ((i 0 (+ i (record-length #>HMODULE))))
+                       ((= i need))
+                    (funcall f (%get-ptr modules i)))))))))))
+
+  (defun init-shared-libraries ()
+    (for-each-loaded-module #'shared-library-from-hmodule))
+  
+  (defun shlib-containing-entry (addr &optional name)
+    (with-macptrs ((p (%int-to-ptr addr)))
+      (shlib-containing-address p name)))
+
+  (defun shlib-containing-address (addr &optional name)
+    (declare (ignore name))
+    (rlet ((phmodule :address (%null-ptr)))
+      (let* ((found (ff-call *get-module-handle-ex-addr*
+                             #>DWORD (logior
+                                      #$GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+                                      #$GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)
+                             :address addr
+                             :address phmodule
+                             #>BOOL)))
+        (unless (eql 0 found)
+          (let* ((hmodule (pref phmodule :address)))
+            (dolist (lib *shared-libraries*)
+              (when (eql (shlib.map lib)  hmodule)
+                (return lib))))))))
+
+
+  (defun open-shared-library (name)
+    "If the library denoted by name can be loaded by the operating system,
+return an object of type SHLIB that describes the library; if the library
+is already open, increment a reference count. If the library can't be
+loaded, signal a SIMPLE-ERROR which contains an often-cryptic message from
+the operating system."
+    (let* ((hmodule (with-cstrs ((name name))
+                      (ff-call
+                       (%kernel-import target::kernel-import-GetSharedLibrary)
+                       :address name
+                       :unsigned-fullword 0
+                       :address)))
+           (shlib (unless (%null-ptr-p hmodule)
+                    (shared-library-from-hmodule hmodule))))
+      (if shlib
+        (progn
+          (incf (shlib.opencount shlib))
+          (setf (shlib.handle shlib) hmodule)
+          shlib)
+        (error "Can't open shared library ~s" name))))
+
+(init-shared-libraries)
+
+;;; end windows-target
+)  
+
+
+(defun ensure-open-shlib (c force)
+  (if (or (shlib.map c) (not force))
+    *rtld-use*
+    (error "Shared library not open: ~s" (shlib.soname c))))
+
+(defun resolve-container (c force)
+  (if c
+    (ensure-open-shlib c force)
+    *rtld-use*
+    ))
+
+
+
+
+;;; An "entry" can be fixnum (the low 2 bits are clear) which represents
+;;; a (32-bit word)-aligned address.  That convention covers all
+;;; function addresses on ppc32 and works for addresses that are
+;;; 0 mod 8 on PPC64, but can't work for things that're byte-aligned
+;;; (x8664 and other non-RISC platforms.)
+;;; For PPC64, we may have to cons up a macptr if people use broken
+;;; linkers.  (There are usually cache advantages to aligning ppc
+;;; function addresses on at least a 16-byte boundary, but some
+;;; linkers don't quite get the concept ...)
+
+(defun foreign-symbol-entry (name &optional (handle *rtld-use*))
+  "Try to resolve the address of the foreign symbol name. If successful,
+return a fixnum representation of that address, else return NIL."
+  (with-cstrs ((n name))
+    #+ppc-target
+    (with-macptrs (addr)      
+      (%setf-macptr addr
+		    (ff-call (%kernel-import target::kernel-import-FindSymbol)
+			     :address handle
+			     :address n
+			     :address))
+      (unless (%null-ptr-p addr)	; No function can have address 0
+	(or (macptr->fixnum addr) (%inc-ptr addr 0))))
+    #+x8632-target
+    (let* ((addr (ff-call (%kernel-import target::kernel-import-FindSymbol)
+			  :address handle
+			  :address n
+			  :unsigned-fullword)))
+      (unless (eql 0 addr) addr))
+    #+x8664-target
+    (let* ((addr (ff-call (%kernel-import target::kernel-import-FindSymbol)
+                          :address handle
+                          :address n
+                          :unsigned-doubleword)))
+      (unless (eql 0 addr) addr))))
+
+(defvar *statically-linked* nil)
+
+#+(or linux-target freebsd-target solaris-target)
+(progn
+
+(defun %library-base-containing-address (address)
+  (rletZ ((info :<D>l_info))
+    (let* ((status (ff-call *dladdr-entry*
+                            :address address
+                            :address info :signed-fullword)))
+      (declare (integer status))
+      (unless (zerop status)
+        (pref info :<D>l_info.dli_fbase)))))
+  
+(defun shlib-containing-address (address &optional name)
+  (declare (ignore name))
+  (let* ((base (%library-base-containing-address address)))
+    (if base
+      (shared-library-at base))))
+
+
+(defun shlib-containing-entry (entry &optional name)
+  (unless *statically-linked*
+    (with-macptrs (p)
+      (entry->addr entry p)
+      (shlib-containing-address p name))))
+)
+
+#+darwin-target
+(progn
+(defvar *dyld-image-count*)
+(defvar *dyld-get-image-header*)
+(defvar *dyld-get-image-name*)
+(defvar *nslookup-symbol-in-image*)
+(defvar *nsaddress-of-symbol*)
+(defvar *nsmodule-for-symbol*)
+(defvar *ns-is-symbol-name-defined-in-image*)
+(defvar *dladdr-entry* 0)
+
+(defun setup-lookup-calls ()
+  #+notyet
+  (setq *dladdr-entry* (foreign-symbol-entry "_dladdr"))
+  (setq *dyld-image-count* (foreign-symbol-entry "__dyld_image_count"))
+  (setq *dyld-get-image-header* (foreign-symbol-entry "__dyld_get_image_header"))
+  (setq *dyld-get-image-name* (foreign-symbol-entry "__dyld_get_image_name"))
+  (setq *nslookup-symbol-in-image* (foreign-symbol-entry "_NSLookupSymbolInImage"))
+  (setq *nsaddress-of-symbol* (foreign-symbol-entry "_NSAddressOfSymbol"))
+  (setq *nsmodule-for-symbol* (foreign-symbol-entry "_NSModuleForSymbol"))
+  (setq *ns-is-symbol-name-defined-in-image* (foreign-symbol-entry "_NSIsSymbolNameDefinedInImage")))
+
+(setup-lookup-calls)
+
+;;;
+;;; given an entry address (a number) and a symbol name (lisp string)
+;;; find the associated dylib or module
+;;; if the dylib or module is not found in *shared-libraries* list it is added
+;;; if not found in the OS list it returns nil
+;;;
+;;; got this error before putting in the call to
+;;; NSIsObjectNameDefinedInImage dyld: /usr/local/lisp/ccl/dppccl dead
+;;; lock (dyld operation attempted in a thread already doing a dyld
+;;; operation)
+;;;
+
+(defun legacy-shlib-containing-address (addr name)
+  (dotimes (i (ff-call *dyld-image-count* :unsigned-fullword))
+    (let ((header (ff-call *dyld-get-image-header* :unsigned-fullword i :address)))
+      (when (and (not (%null-ptr-p header))
+                 (or (eql (pref header :mach_header.filetype) #$MH_DYLIB)
+                     (eql (pref header :mach_header.filetype) #$MH_BUNDLE)))
+        ;; make sure the image is either a bundle or a dylib
+        ;; (otherwise we will crash, likely OS bug, tested OS X 10.1.5)
+        (with-cstrs ((cname name))
+          ;; also we must check is symbol name is defined in the
+          ;; image otherwise in certain cases there is a crash,
+          ;; another likely OS bug happens in the case where a
+          ;; bundle imports a dylib and then we call
+          ;; nslookupsymbolinimage on the bundle image
+          (when (/= 0
+                    (ff-call *ns-is-symbol-name-defined-in-image* :address header
+                             :address cname :unsigned))
+            (let ((symbol (ff-call *nslookup-symbol-in-image* :address header :address cname
+                                   :unsigned-fullword #$NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+                                   :address)))
+              (unless (%null-ptr-p symbol)
+                ;; compare the found address to the address we are looking for
+                (let ((foundaddr (ff-call *nsaddress-of-symbol* :address symbol :address)))
+                  ;; (format t "Foundaddr ~s~%" foundaddr)
+                  ;; (format t "Compare to addr ~s~%" addr)
+                  (when (eql foundaddr addr)
+                    (let* ((imgname (ff-call *dyld-get-image-name* :unsigned-fullword i :address))
+                           (libname (unless (%null-ptr-p imgname) (%get-cstring imgname)))
+                           (libmodule (%int-to-ptr 0))
+                           (libheader (%int-to-ptr 0)))
+                      (if (eql (pref header :mach_header.filetype) #$MH_BUNDLE)
+                        (setf libmodule (ff-call *nsmodule-for-symbol* :address symbol :address))
+                        (setf libheader header))
+                      ;; make sure that this shared library is on *shared-libraries*
+                      (return (shared-library-from-header-module-or-name libheader libmodule libname)))))))))))))
+
+(defun shlib-containing-address (address name)
+  (if (zerop *dladdr-entry*)
+    (legacy-shlib-containing-address address name)
+    ;; Bootstrapping.  RLET might be clearer here.
+    (%stack-block ((info (record-length #>Dl_info) :clear t))
+      (unless (zerop (ff-call *dladdr-entry*
+                              :address address
+                              :address info
+                              :signed-fullword))
+        (let* ((addr (pref info #>Dl_info.dli_fbase)))
+          (format t "~&name = ~s" (pref info  #>Dl_info.dli_fname))
+          
+          (dolist (lib *shared-libraries*)
+            (when (eql (shlib.base lib) addr)
+              (return lib))))))))
+
+(defun shlib-containing-entry (entry &optional name)
+  (unless name
+    (error "foreign name must be non-NIL."))
+  (with-macptrs (addr)
+    (entry->addr entry addr)
+    (shlib-containing-address addr name)))
+
+;; end Darwin progn
+)
+
+#-(or linux-target darwin-target freebsd-target solaris-target windows-target)
+(defun shlib-containing-entry (entry &optional name)
+  (declare (ignore entry name))
+  *rtld-default*)
+
+
+(defun resolve-eep (e &optional (require-resolution t))
+  (or (eep.address e)
+      (let* ((name (eep.name e))
+	     (container (eep.container e))
+             (handle (resolve-container container require-resolution))
+	     (addr (foreign-symbol-entry name handle)))
+	(if addr
+	  (progn
+	    (unless container
+	      (setf (eep.container e) (shlib-containing-entry addr name)))
+	    (setf (eep.address e) addr))
+	  (if require-resolution
+	    (error "Can't resolve foreign symbol ~s" name))))))
+
+
+
+(defun foreign-symbol-address (name &optional (map *rtld-use*))
+  "Try to resolve the address of the foreign symbol name. If successful,
+return that address encapsulated in a MACPTR, else returns NIL."
+  (with-cstrs ((n name))
+    (let* ((addr (ff-call (%kernel-import target::kernel-import-FindSymbol) :address map :address n :address)))
+      (unless (%null-ptr-p addr)
+        addr))))
+
+(defun resolve-foreign-variable (fv &optional (require-resolution t))
+  (or (fv.addr fv)
+      (let* ((name (fv.name fv))
+	     (container (fv.container fv))
+             (handle (resolve-container container require-resolution))
+	     (addr (foreign-symbol-address name handle)))
+	(if addr
+	  (progn
+	    (unless container
+	      (setf (fv.container fv) (shlib-containing-address addr name)))
+	    (setf (fv.addr fv) addr))
+	  (if require-resolution
+	    (error "Can't resolve foreign symbol ~s" name))))))
+
+(defun load-eep (name)
+  (let* ((eep (or (gethash name (eeps)) (setf (gethash name *eeps*) (%cons-external-entry-point name)))))
+    (resolve-eep eep nil)
+    eep))
+
+(defun load-fv (name type)
+  (let* ((fv (or (gethash name (fvs)) (setf (gethash name *fvs*) (%cons-foreign-variable name type)))))
+    (resolve-foreign-variable fv nil)
+    fv))
+
+         
+
+
+
+
+#+(or linux-target freebsd-target solaris-target)
+(progn
+
+;;; Return the position of the last dot character in name, if that
+;;; character is followed by one or more decimal digits (e.g., the
+;;; start of a numeric suffix on a library name.)  Return NIL if
+;;; there's no such suffix.
+(defun last-dot-pos (name)
+  (do* ((i (1- (length name)) (1- i))
+        (default i)
+        (trailing-digits nil))
+       ((<= i 0) default)
+    (declare (fixnum i))
+    (let* ((code (%scharcode name i)))
+      (declare (type (mod #x110000) code))
+      (if (and (>= code (char-code #\0))
+               (<= code (char-code #\9)))
+        (setq trailing-digits t)
+        (if (= code (char-code #\.))
+          (return (if trailing-digits i))
+          (return default))))))
+  
+;;; It's assumed that the set of libraries that the OS has open
+;;; (accessible via the _dl_loaded global variable) is a subset of
+;;; the libraries on *shared-libraries*.
+
+(defun revive-shared-libraries ()
+  (dolist (lib *shared-libraries*)
+    (setf (shlib.map lib) nil
+	  (shlib.pathname lib) nil
+	  (shlib.base lib) nil)
+    (let* ((soname (shlib.soname lib))
+           (last-dot (if soname (last-dot-pos soname))))
+      (when soname
+	(with-cstrs ((soname soname))
+	  (let* ((map (block found
+			(%walk-shared-libraries
+			 #'(lambda (m)
+			     (with-macptrs (libname)
+			       (%setf-macptr libname
+					     (soname-ptr-from-link-map m))
+			       (unless (%null-ptr-p libname)
+				 (when (or (%cstrcmp soname libname)
+                                           (and last-dot
+                                                (%cnstrcmp soname libname (1+ last-dot))))
+				   (return-from found  m)))))))))
+	    (when map
+	      ;;; Sigh.  We can't reliably lookup symbols in the library
+	      ;;; unless we open the library (which is, of course,
+	      ;;; already open ...)  ourselves, passing in the
+	      ;;; #$RTLD_GLOBAL flag.
+              #+linux-target
+	      (ff-call (%kernel-import target::kernel-import-GetSharedLibrary)
+		       :address soname
+		       :unsigned-fullword *dlopen-flags*
+		       :void)
+	      (setf (shlib.base lib) (%int-to-ptr (pref map :link_map.l_addr))
+		    (shlib.pathname lib) (%get-cstring
+					  (pref map :link_map.l_name))
+                    (shlib.soname lib) (%get-cstring (soname-ptr-from-link-map map))
+		    (shlib.map lib) map))))))))
+
+;;; Repeatedly iterate over shared libraries, trying to open those
+;;; that weren't already opened by the kernel.  Keep doing this until
+;;; we reach stasis (no failures or no successes.)
+
+(defun %reopen-user-libraries ()
+  (loop
+      (let* ((win nil)
+	     (lose nil))
+	(dolist (lib *shared-libraries*)
+	  (let* ((map (shlib.map lib))
+                 (handle (shlib.handle lib)))
+	    (unless map
+	      (with-cstrs ((soname (shlib.soname lib)))
+		(setq handle
+                      (ff-call
+                       (%kernel-import target::kernel-import-GetSharedLibrary)
+                       :address soname
+                       :unsigned-fullword *dlopen-flags*
+                       :address))
+                #-(or freebsd-target solaris-target) (setq map handle)
+                #+(or freebsd-target solaris-target)
+                (setq map
+                      (if (%null-ptr-p handle)
+                        handle
+                        (rlet ((p :address))
+                          (if (eql 0 (ff-call
+                                      (foreign-symbol-entry "dlinfo")
+                                      :address handle
+                                      :int #$RTLD_DI_LINKMAP
+                                      :address p
+                                      :int))
+                            (pref p :address)
+                            (%null-ptr)))))
+		(if (%null-ptr-p map)
+		  (setq lose t)
+		  (setf (shlib.pathname lib)
+			(%get-cstring (pref map :link_map.l_name))
+			(shlib.base lib)
+			(%int-to-ptr (pref map :link_map.l_addr))
+			(shlib.map lib) map
+                        (shlib.handle lib) handle
+			win t))))))
+	(when (or (not lose) (not win)) (return)))))
+)
+
+
+(defun refresh-external-entrypoints ()
+  #+linux-target
+  (setq *statically-linked* (not (eql 0 (%get-kernel-global 'statically-linked))))
+  (%revive-macptr *rtld-next*)
+  (%revive-macptr *rtld-default*)
+  #+(or linux-target freebsd-target solaris-target)
+  (unless *statically-linked*
+    (setq *dladdr-entry* (foreign-symbol-entry "dladdr"))
+    (revive-shared-libraries)
+    (%reopen-user-libraries))
+  #+darwin-target
+  (progn
+    (setup-lookup-calls)
+    (reopen-user-libraries))
+  #+windows-target
+  (init-windows-ffi)
+  (when *eeps*
+    (without-interrupts 
+     (maphash #'(lambda (k v) 
+                  (declare (ignore k)) 
+                  (setf (eep.address v) nil) 
+                  (resolve-eep v nil))
+              *eeps*)))
+  (when *fvs*
+    (without-interrupts
+     (maphash #'(lambda (k v)
+                  (declare (ignore k))
+                  (setf (fv.addr v) nil)
+                  (resolve-foreign-variable v nil))
+              *fvs*))))
+
+
Index: /branches/new-random/level-0/l0-complex.lisp
===================================================================
--- /branches/new-random/level-0/l0-complex.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-complex.lisp	(revision 13309)
@@ -0,0 +1,34 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel)
+  (require "NUMBER-MACROS"))
+
+(defun coerce-to-complex-type (num type)
+  (cond ((complexp num)
+         (let ((real (%realpart num))
+               (imag (%imagpart num)))
+           (if (and (typep real type)
+                    (typep imag type))
+             num
+             (complex (coerce real type)
+                      (coerce imag type)))))
+        (t (complex (coerce num type)))))
+
+;;; end of l0-complex.lisp
Index: /branches/new-random/level-0/l0-def.lisp
===================================================================
--- /branches/new-random/level-0/l0-def.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-def.lisp	(revision 13309)
@@ -0,0 +1,251 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; primitives that manipulate function & variable definitions.
+
+
+
+
+
+(defun functionp (arg)
+  "Return true if OBJECT is a FUNCTION, and NIL otherwise."
+  (functionp arg))
+
+(defun lfunp (arg)
+  (functionp arg))
+
+(defun %proclaim-special (sym &optional initp)
+  (let* ((oldbits (%symbol-bits sym)))
+    (declare (fixnum oldbits))
+    (%symbol-bits sym (bitset $sym_vbit_special oldbits))
+    initp))
+
+(setq *lfun-names* (make-hash-table :test 'eq :weak t))
+
+(defun lookup-lfun-name (lfun) 
+  (gethash lfun *lfun-names*))
+
+
+(defun function-name (fun)
+  (or (and (functionp fun) (lfun-name fun))
+      (if (compiled-function-p (setq fun (closure-function fun)))
+        (lfun-name fun))))
+
+
+(defun bootstrapping-fmakunbound (name)
+  (when (consp name)
+    (unless (eq (%car name) 'setf)
+      (error "Function spec handler not loaded yet"))
+    (setq name (setf-function-name (cadr name))))
+  (%unfhave name)
+  name)
+
+;;; redefined in sysutils.
+(%fhave 'fmakunbound #'bootstrapping-fmakunbound)
+
+(defun bootstrapping-fset (name fn)
+  (fmakunbound name)
+  (%fhave name fn)
+  fn)
+
+;Redefined in sysutils.
+(%fhave 'fset #'bootstrapping-fset)
+
+(defun bootstrapping-record-source-file (fn &optional type)
+  (declare (ignore fn type))
+  nil)
+
+;Redefined in l1-utils.
+(%fhave 'record-source-file #'bootstrapping-record-source-file)
+
+
+(setq *fasload-print* nil)
+(setq *save-doc-strings* t)
+
+
+
+(%fhave '%defun-encapsulated-maybe ;Redefined in encapsulate
+        (qlfun bootstrapping-defun-encapsulated (name fn)
+          (declare (ignore name fn))
+          nil))
+
+(%fhave 'encapsulated-function-name  ;Redefined in encapsulate - used in l1-io
+        (qlfun bootstrapping-encapsulated-function-name (fn)
+          (declare (ignore fn))
+          nil))
+
+(%fhave 'set-function-info (qlfun set-function-info  (name info)
+                                  (if (typep info 'string)
+                                    (set-documentation name 'function info))
+                                  name))
+
+(defun %defun (named-fn &optional info)
+  (unless (typep named-fn 'function)
+    (dbg named-fn))
+  (let* ((name (function-name named-fn)))
+    (unless (and name
+                 (or (symbolp name)
+                     (setf-function-name-p name)))
+      (dbg named-fn))
+  (record-source-file name 'function)
+  (if (not (%defun-encapsulated-maybe name named-fn))
+    (fset name named-fn))
+  (set-function-info name info)
+  (when *fasload-print* (format t "~&~S~%" name))
+  name))
+
+(defun validate-function-name (name)
+  (if (symbolp name)
+    name
+    (if (setf-function-name-p name)
+      (setf-function-name (cadr name))
+      (report-bad-arg name 'function-name))))
+
+;;;    There are three kinds of things which can go in the function
+;;;    cell of a symbol: 1) A function.  2) The thing which is the
+;;;    value of %unbound-function%: a 1-element vector whose 0th
+;;;    element is a code vector which causes an "undefined function"
+;;;    error to be signalled.  3) A macro or special-form definition,
+;;;    which is a 2-element vector whose 0th element is a code vector
+;;;    which signals a "can't apply macro or special form" error when
+;;;    executed and whose 1st element is a macro or special-operator
+;;;    name.  It doesn't matter what type of gvector cases 2 and 3
+;;;    are.  Once that's decided, it wouldn't hurt if %FHAVE
+;;;    typechecked its second arg.
+
+(defun %fhave (name def)
+  (let* ((fname (validate-function-name name)))
+    (setf (%svref (symptr->symvector (%symbol->symptr fname)) target::symbol.fcell-cell) def)))
+
+;;; FBOUNDP is true of any symbol whose function-cell contains something other
+;;; than %unbound-function%; we expect FBOUNDP to return that something.
+(defun fboundp (name)
+  "Return true if name has a global function definition."
+  (let* ((fname (validate-function-name name))
+         (def (%svref (symptr->symvector (%symbol->symptr fname)) target::symbol.fcell-cell)))
+    (unless (eq def %unbound-function%)
+      def)))
+
+;;; %UNFHAVE doesn't seem to want to deal with SETF names or function specs.
+;;; Who does ?
+
+(defun %unfhave (sym)
+  (let* ((symvec (symptr->symvector (%symbol->symptr sym)))
+         (old (%svref symvec target::symbol.fcell-cell))
+         (unbound %unbound-function%))
+    (setf (%svref symvec target::symbol.fcell-cell) unbound)
+    (not (eq old unbound))))
+
+;;; It's guaranteed that lfun-bits is a fixnum.  Might be a 30-bit fixnum ...
+
+
+
+
+
+(defun lfun-vector-name (fun &optional (new-name nil set-name-p))
+  (let* ((bits (lfun-bits fun)))
+    (declare (fixnum bits))
+    (if (and (logbitp $lfbits-gfn-bit bits)
+	     (not (logbitp $lfbits-method-bit bits)))
+      (progn
+        (if set-name-p
+          (%gf-name fun new-name)
+          (%gf-name fun)))
+      (let* ((has-name-cell (not (logbitp $lfbits-noname-bit bits))))
+	(if has-name-cell
+	  (let* ((lfv (lfun-vector fun))
+                 (name-idx (- (the fixnum (uvsize lfv)) 2))
+		 (old-name (%svref lfv name-idx)))
+	    (declare (fixnum name-idx))
+	    (if (and set-name-p (not (eq old-name new-name)))
+	      (setf (%svref lfv name-idx) new-name))
+	    old-name))))))
+
+(defun lfun-name (fun &optional (new-name nil set-name-p))
+  (multiple-value-bind (stored-name stored?) (lookup-lfun-name fun)
+    (unless stored?
+      (setq stored-name (lfun-vector-name fun)))
+    (when (and set-name-p (neq new-name stored-name))
+      (if (and stored? (eq new-name (lfun-vector-name fun)))
+        (remhash fun *lfun-names*)
+        (if (logbitp $lfbits-noname-bit (the fixnum (lfun-bits fun)))   ; no name-cell in function vector.
+          (puthash fun *lfun-names* new-name)
+          (lfun-vector-name fun new-name))))
+    stored-name))
+
+(defun lfun-bits (function &optional new)
+  (unless (functionp function)
+    (setq function (require-type function 'function)))
+  (let* ((lfv (lfun-vector function))
+         (idx (1- (the fixnum (uvsize lfv))))
+         (old (%svref lfv idx)))
+    (declare (fixnum idx))
+    (if new
+      (setf (%svref lfv idx) new))
+    old))
+    
+(defun %macro-have (symbol macro-function)
+  (declare (special %macro-code%))      ; magically set by xloader.
+  (%fhave symbol (vector %macro-code% macro-function)))
+
+
+(defun special-operator-p (symbol)
+  "If the symbol globally names a special form, return T, otherwise NIL."
+  (let ((def (fboundp symbol)))
+    (and (typep def 'simple-vector)
+         (not (lfunp (svref def 1))))))
+
+(defun special-form-p (x) (special-operator-p x))
+
+(defun setf-function-name-p (thing)
+  (and (consp thing)
+       (consp (%cdr thing))
+       (null (%cddr thing))
+       (eq (%car thing) 'setf)
+       (symbolp (%cadr thing))))
+
+(defun macro-function (form &optional env)
+  "If SYMBOL names a macro in ENV, returns the expansion function,
+   else returns NIL. If ENV is unspecified or NIL, use the global
+   environment only."
+  (setq form (require-type form 'symbol))
+  (when env
+    ; A definition-environment isn't a lexical environment, but it can
+    ; be an ancestor of one.
+    (unless (istruct-typep env 'lexical-environment)
+        (report-bad-arg env 'lexical-environment))
+      (let ((cell nil))
+        (tagbody
+          top
+          (if (setq cell (%cdr (assq form (lexenv.functions env))))
+            (return-from macro-function 
+              (if (eq (car cell) 'macro) (%cdr cell))))
+          (unless (listp (setq env (lexenv.parent-env env)))
+            (go top)))))
+      ; Not found in env, look in function cell.
+  (%global-macro-function form))
+
+(defun %fixnum-ref-macptr (fixnum &optional (offset 0))
+  (%int-to-ptr (%fixnum-ref-natural fixnum offset)))
+
+(defun %fixnum-set-macptr (fixnum offset &optional (newval offset newval-p))
+  (%fixnum-set-natural fixnum (if newval-p offset 0) (%ptr-to-int newval))
+  newval)
+
+;;; end of l0-def.lisp
Index: /branches/new-random/level-0/l0-error.lisp
===================================================================
--- /branches/new-random/level-0/l0-error.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-error.lisp	(revision 13309)
@@ -0,0 +1,141 @@
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defparameter *error-format-strings* 
+  '((1 . "Unbound variable: ~S .")
+    (2 . "Invalid reference to ~s at index ~s.")
+    (3 . "Too many arguments.")
+    (4 . "Too few arguments.")
+    (5 . "Argument ~S is not of the required type.")
+    (6 . "Undefined function: ~S .")
+    (7 . "Invalid assignnnt of ~s at index ~s, to ~s.")
+    (8 . "Can't coerce ~S to ~S")
+    (9 . "Funcallable instance ~S was called with args ~s, but has no FUNCALLABLE-INSTANCE-FUNCTION")
+    (10 . "Out of memory.")
+    (11 . "Default image file not found.")
+    (12 . "No translation for ~S")
+    (13 . "~S can't be FUNCALLed or APPLYed.")
+    (14 . "~S is not a symbol or lambda expression")
+    (15 . "Declaration ~S in unexpected position")
+    (16 . "Can't setq constant ~S")
+    (17 . "Odd number of forms to setq in ~S")
+    (18 . "Illegal arg to setq ~S")
+    (19 . "~S is not a symbol.")
+    (20 . "~S is a constant.")
+    (21 . "Bad initialization form: ~S")
+    (22 . "Symbol macro ~S is declared or proclaimed special")
+    (23 . "Too many arguments in ~S")
+    (24 . "Local macro cannot reference lexically defined variable ~S")
+    (25 . "Local macro cannot reference lexically defined function ~S")
+    (26 . "Local macro cannot reference lexically defined tag ~S")
+    (27 . "Local macro cannot reference lexically defined block ~S")
+    (28 . "Can't find tag ~S")
+    (29 . "Duplicate tag ~S")
+    (30 . "Can't find block ~S")
+    (31 . "Bad lambda list  ~S.")
+    (32 . "~S is not a valid lambda expression.")
+    (33 . "Can't throw to tag ~S .")
+    (34 . "Object ~S is not of type ~S.")
+    (35 . "FUNCTION can't reference lexically defined macro ~S")
+    (36 . "Unimplemented FPU instruction ~^~S.")
+    (41 . "Unmatched ')'.")
+    (42 . "~S and ~S must be on the same volume.")
+    (43 . "Filename ~S contains illegal character ~S")
+    (44 . "Illegal use of wildcarded filename ~S")
+    (45 . "~S is not a FASL or TEXT file.")
+    (46 . "Cannot rename directory to file ~S")
+    (47 . "Found a directory instead of a file or vice versa ~S")
+    (48 . "Cannot copy directories: ~S")
+    (49 . "String too long for pascal record")
+    (50 . "Cannot create ~S")
+    (64 . "Floating point overflow")
+    (66 . "Can't divide by zero.")
+    (75 . "Stack overflow. Bytes requested: ~d")
+    (76 . "Memory allocation request failed.")
+    (77 . "~S exceeds array size limit of ~S bytes.")
+    (94. "Printer error.")
+    (95. "Can't load printer.")
+    (96. "Can't get printer parameters.")
+    (97. "Can't start up printer job.")
+    (98. "Floating point exception.")
+    (111 . "Unexpected end of file encountered.")
+    (112 . "Array index ~S out of bounds for ~S .")
+    (113 . "Reader error: ~S encountered.")
+    (114 . "Reader error: Unknown reader macro character ~S .")
+    (115 . "Can't redefine constant ~S .")
+    (116 . "Reader error: Illegal character ~S .")
+    (117 . "Reader error: Illegal symbol syntax.")
+    (118 . "Reader error: Dot context error.")
+    (119 . "Reader error: Bad value ~S for *READ-BASE*.")
+    (120 . "Can't construct argument list from ~S.")
+    (121 . "Wrong FASL version.")
+    (122 . "Not a FASL file.")
+    (123 . "Undefined function ~s called with arguments ~s.")
+    (124 . "Image file incompatible with current version of Lisp.")
+    (127 .   "Using ~S in ~S ~%would cause name conflicts with symbols inherited by that package: ~%~:{~S  ~S~%~}")
+    (128 .   "Importing ~S to ~S would conflict with inherited symbol ~S ." )
+    (129 .   "Reader error: Malformed number in a #b/#o/#x/#r macro." )
+    (130 .   "There is no package named ~S ." )
+    (131 .   "Reader error: No external symbol named ~S in package ~S ." )
+    (132 .   "Bad FASL file: internal inconsistency detected." )
+    (133 .   "Importing ~S to ~S would conflict with symbol ~S ." )
+    (134 .   "Uninterning ~S from ~S would cause conflicts among ~S ." )
+    (135 .   "~S is not accessible in ~S ." )
+    (136 .   "Exporting ~S in ~S would cause a name conflict with ~S in ~S ." )
+    (137 .   "Using ~S in ~S ~%would cause name conflicts with symbols already present in that package: ~%~:{~S  ~S~%~}")
+    (139 .   "Reader macro function ~S called outside of reader." )
+    (140 .   "Reader error: undefined character ~S in a ~S dispatch macro." )
+    (141 .   "Reader dispatch macro character ~S doesn't take an argument." )
+    (142 .   "Reader dispatch macro character ~S requires an argument." )
+    (143 .   "Reader error: Bad radix in #R macro." )
+    (144 .   "Reader error: Duplicate #~S= label." )
+    (145 .   "Reader error: Missing #~S# label." )
+    (146 .   "Reader error: Illegal font number in #\\ macro." )
+    (147 .   "Unknown character name ~S in #\\ macro." )
+    (148 .   "~S cannot be accessed with ~S subscripts." )
+    (149 .   "Requested size is too large to displace to ~S ." )
+    (150 .   "Too many elements in argument list ~S ." )
+    (151 .    "Arrays are not of the same size" )
+    (152 . "Conflicting keyword arguments : ~S ~S, ~S ~S .")
+    (153 . "Incorrect keyword arguments in ~S .")
+    (154 . "Two few arguments in form ~S .")
+    (155 . "Too many arguments in form ~S .")
+    (157 . "value ~S is not of the expected type ~S.")
+    (158 . "~S is not a structure.")
+    (159 . "Access to slot ~S of structure ~S is out of bounds.")
+    (160 . "Form ~S does not match lambda list ~A .")
+    (161 . "Temporary number space exhausted.")
+    (163 . "Illegal #+/- expression ~S.")
+    (164 . "File ~S does not exist.")
+    (165 . "~S argument ~S is not of the required type.")
+    (166 . "~S argument ~S is not of type ~S.")
+    (167 . "Too many arguments in ~S.")
+    (168 . "Too few arguments in ~S.")
+    (169 . "Arguments don't match lambda list in ~S.")
+    (170 . "~S is not a proper list.")
+    (171 . "~S is not an array with a fill pointer.")
+    (172 . "~S is not an adjustable array.")
+    (173 . "Can't access component ~D of ~S.")
+    (174 . "~S doesn't match array element type of ~S.")
+    (175 . "Stack group ~S is exhausted.")
+    (176 . "Stack group ~S called with arguments ~:S; exactly 1 argument accepted.")
+    (177 . "Attempt to return too many values.")
+    (178 . "Can't dynamically bind ~S. ")
+    (200 . "Foreign exception: ~S. ")))
+  
+
Index: /branches/new-random/level-0/l0-float.lisp
===================================================================
--- /branches/new-random/level-0/l0-float.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-float.lisp	(revision 13309)
@@ -0,0 +1,1062 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+;;;
+;;; level-0;l0-float.lisp
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS")
+  (require :number-case-macro) 
+)
+
+;;; used by float reader
+(defun make-float-from-fixnums (hi lo exp sign &optional result)
+  ;;(require-null-or-double-float-sym result)
+  ;; maybe nuke all these require-types?
+  ;;(setq hi (require-type hi 'fixnum))
+  ;;(setq lo (require-type lo 'fixnum))
+  ;;(setq exp (require-type exp 'fixnum))
+  ;;(setq sign (require-type sign 'fixnum))
+  (let ((the-float (or result (%make-dfloat))))
+    (%make-float-from-fixnums the-float hi lo exp sign)
+    the-float))
+
+
+#+32-bit-target
+(defun make-short-float-from-fixnums (significand biased-exp sign &optional result)
+  (%make-short-float-from-fixnums (or result (%make-sfloat)) significand biased-exp sign))
+
+#+64-bit-target
+(defun make-short-float-from-fixnums (significand biased-exp sign)
+  (declare (fixnum significand biased-exp sign))
+  (host-single-float-from-unsigned-byte-32
+   (logior
+    (the fixnum (if (< sign 0) (ash 1 31) 0))
+    (the fixnum (ash biased-exp IEEE-single-float-exponent-offset))
+    (the fixnum (logand significand
+                        (1- (ash 1 IEEE-single-float-hidden-bit)))))))
+
+
+(defun float-sign (n1 &optional n2) ; second arg silly
+  "Return a floating-point number that has the same sign as
+   FLOAT1 and, if FLOAT2 is given, has the same absolute value
+   as FLOAT2."
+  (if (and n2 (not (typep n2 'float)))
+    (setq n2 (require-type n2 'float)))
+  (number-case n1
+    (double-float                       
+     (if (%double-float-sign n1) 
+       (if n2
+         (if (if (typep n2 'double-float) (%double-float-minusp n2) (%short-float-minusp n2)) n2 (- n2))
+         -1.0d0)
+       (if n2
+         (if (if (typep n2 'double-float) (%double-float-minusp n2) (%short-float-minusp n2)) (- n2) n2)
+         1.0d0)))
+    (short-float
+     (if (%short-float-sign n1)
+       (if n2
+         (if (if (typep n2 'double-float) (%double-float-minusp n2) (%short-float-minusp n2)) n2 (- n2))
+         -1.0s0)
+       (if n2
+         (if (if (typep n2 'double-float) (%double-float-minusp n2) (%short-float-minusp n2)) (- n2) n2)
+         1.0s0)))))
+
+
+
+(defun %double-float-minusp (n)
+  (and (%double-float-sign n)(not (%double-float-zerop n))))
+
+(defun %short-float-minusp (n)
+  (and (%short-float-sign n) (not (%short-float-zerop n))))
+
+(defun %double-float-abs (n)
+  (if (not (%double-float-sign n))
+    n 
+    (%%double-float-abs! n (%make-dfloat))))
+
+#+32-bit-target
+(defun %short-float-abs (n)
+  (if (not (%short-float-sign n))
+    n 
+    (%%short-float-abs! n (%make-sfloat))))
+
+(defun fixnum-decode-float (n)
+  (etypecase n
+    (double-float (%integer-decode-double-float n))))
+
+(defun nan-or-infinity-p (n)
+  (etypecase n
+    (double-float (eq 2047 (%double-float-exp n)))
+    (short-float (eq 255 (%short-float-exp n)))))
+
+; not sure this is right
+(defun infinity-p (n)
+  (etypecase n
+    (double-float (multiple-value-bind (hi lo exp)(fixnum-decode-float n)
+                    (and (eq 2047 exp)
+                         (eq #x1000000 hi)
+                         (eq 0 lo))))
+    (short-float
+     #+32-bit-target
+     (multiple-value-bind (high low)(%sfloat-hwords n)
+                  (let*  ((mantissa (%ilogior2 low (%ilsl 16 (%ilogand2 high #x007F))))
+                          (exp (%ilsr 7 (%ilogand2 high #x7F80))))
+                    (and (eq exp 255)
+                         (eq 0 mantissa))))
+     #+64-bit-target
+     (let* ((bits (single-float-bits n))
+            (exp (ldb (byte IEEE-single-float-exponent-width
+                            IEEE-single-float-exponent-offset)
+                      bits))
+            (mantissa (ldb (byte IEEE-single-float-mantissa-width
+                            IEEE-single-float-mantissa-offset)
+                           bits)))
+       (declare (fixnum bits exp mantissa))
+       (and (= exp 255)
+            (zerop mantissa))))))
+
+#+32-bit-target
+(defun fixnum-decode-short-float (float)
+  (multiple-value-bind (high low)(%sfloat-hwords float)
+    (let*  ((mantissa (%ilogior2 low (%ilsl 16 (%ilogand2 high #x007F))))
+            (exp (%ilsr 7 (%ilogand2 high #x7F80))))
+      (if (and (neq exp 0)(neq exp 255))(setq mantissa (%ilogior mantissa #x800000)))
+      (values mantissa exp (%ilsr 15 high)))))
+
+#+64-bit-target
+(defun fixnum-decode-short-float (float)
+  (let* ((bits (single-float-bits float)))
+    (declare (fixnum bits))
+    (let* ((mantissa (ldb (byte IEEE-single-float-mantissa-width
+                                IEEE-single-float-mantissa-offset)
+                          bits))
+           (exp (ldb (byte IEEE-single-float-exponent-width
+                           IEEE-single-float-exponent-offset)
+                     bits))
+           (sign (lsh bits -31)))
+      (declare (fixnum mantissa exp sign))
+      (unless (or (= exp 0) (= exp 255))
+        (setq mantissa (logior mantissa (ash 1 IEEE-single-float-hidden-bit))))
+      (values mantissa exp sign))))
+                  
+                   
+
+#+32-bit-target
+(defun integer-decode-double-float (n)
+  (multiple-value-bind (hi lo exp sign)(%integer-decode-double-float n)
+    ; is only 53 bits and positive so should be easy
+    ;(values (logior (ash hi 28) lo) exp sign)))
+    ; if denormalized, may fit in a fixnum
+    (setq exp (- exp (if (< hi #x1000000) 
+                       (+ IEEE-double-float-mantissa-width IEEE-double-float-bias)
+                       (+ IEEE-double-float-mantissa-width (1+ IEEE-double-float-bias)))))
+    (if (< hi (ash 1 (1- target::fixnumshift))) ; aka 2
+      (values (logior (ash hi 28) lo) exp sign)
+      ; might fit in 1 word?
+      (let ((big (%alloc-misc 2 target::subtag-bignum)))
+        (make-big-53 hi lo big)
+        (if (< hi #x1000000) (%normalize-bignum big))
+        (values big exp sign)))))
+
+#+64-bit-target
+(defun integer-decode-double-float (n)
+  (multiple-value-bind (hi lo exp sign)(%integer-decode-double-float n)
+    (setq exp (- exp (if (< hi #x1000000) 
+                       (+ IEEE-double-float-mantissa-width IEEE-double-float-bias)
+                       (+ IEEE-double-float-mantissa-width (1+ IEEE-double-float-bias)))))
+    (values (logior (ash hi 28) lo) exp sign)))
+    
+
+;;; actually only called when magnitude bigger than a fixnum
+#+32-bit-target
+(defun %truncate-double-float (n)
+  (multiple-value-bind (hi lo exp sign)(%integer-decode-double-float n)
+    (if (< exp (1+ IEEE-double-float-bias)) ; this is false in practice
+      0
+      (progn
+        (setq exp (- exp (+ IEEE-double-float-mantissa-width (1+ IEEE-double-float-bias))))
+        (if (eq sign 1)  ; positive
+          (logior (ash hi (+ 28 exp))(ash lo exp))
+          (if (<= exp 0) ; exp positive - negate before shift - else after
+            (let ((poo (logior (ash hi (+ 28 exp))(ash lo exp))))
+              (- poo))
+            (let ((poo (logior (ash hi 28) lo)))
+              (ash (- poo) exp))))))))
+
+#+64-bit-target
+(defun %truncate-double-float (n)
+  (multiple-value-bind (mantissa exp sign) (integer-decode-float n)
+    (* sign (ash mantissa exp))))
+
+
+
+; actually only called when bigger than a fixnum
+(defun %truncate-short-float (n)
+  (multiple-value-bind (mantissa exp sign)(fixnum-decode-short-float n)
+    (if (< exp (1+ IEEE-single-float-bias)) ; is magnitude less than 1 - false in practice
+      0
+      (progn
+        (setq exp (- exp (+ IEEE-single-float-mantissa-width (1+ IEEE-single-float-bias))))
+        (ash (if (eq sign 0) mantissa (- mantissa)) exp)))))
+
+(defun decode-float (n)
+  "Return three values:
+   1) a floating-point number representing the significand. This is always
+      between 0.5 (inclusive) and 1.0 (exclusive).
+   2) an integer representing the exponent.
+   3) -1.0 or 1.0 (i.e. the sign of the argument.)"
+  (number-case n
+    (double-float
+     (let* ((old-exp (%double-float-exp n))
+            (sign (if (%double-float-sign n) -1.0d0 1.0d0)))    
+       (if (eq 0 old-exp)
+         (if (%double-float-zerop n)
+           (values 0.0d0 0 sign)
+           (let* ((val (%make-dfloat))
+                  (zeros (dfloat-significand-zeros n)))
+	     (%%double-float-abs! n val)
+             (%%scale-dfloat! val (+ 2 IEEE-double-float-bias zeros) val) ; get it normalized
+             (set-%double-float-exp val IEEE-double-float-bias)      ; then bash exponent
+             (values val (- old-exp zeros IEEE-double-float-bias) sign)))
+         (if (> old-exp IEEE-double-float-normal-exponent-max)
+           (error "Can't decode NAN or infinity ~s" n)
+           (let ((val (%make-dfloat)))
+             (%%double-float-abs! n val)
+             (set-%double-float-exp val IEEE-double-float-bias)
+             (values val (- old-exp IEEE-double-float-bias) sign))))))
+    (short-float
+     (let* ((old-exp (%short-float-exp n))
+            (sign (if (%short-float-sign n) -1.0s0 1.0s0)))
+       (if (eq 0 old-exp)
+         (if (%short-float-zerop n)
+           (values 0.0s0 0 sign)
+           #+32-bit-target
+           (let* ((val (%make-sfloat))
+                  (zeros (sfloat-significand-zeros n)))
+	     (%%short-float-abs! n val)
+             (%%scale-sfloat! val (+ 2 IEEE-single-float-bias zeros) val) ; get it normalized
+             (set-%short-float-exp val IEEE-single-float-bias)      ; then bash exponent
+             (values val (- old-exp zeros IEEE-single-float-bias) sign))
+           #+64-bit-target
+           (let* ((zeros (sfloat-significand-zeros n))
+                  (val (%%scale-sfloat (%short-float-abs n)
+				       (+ 2 IEEE-single-float-bias zeros))))
+             (values (set-%short-float-exp val IEEE-single-float-bias)
+                     (- old-exp zeros IEEE-single-float-bias) sign)))
+         (if (> old-exp IEEE-single-float-normal-exponent-max)
+           (error "Can't decode NAN or infinity ~s" n)
+           #+32-bit-target
+           (let ((val (%make-sfloat)))
+             (%%short-float-abs! n val)
+             (set-%short-float-exp val IEEE-single-float-bias)
+             (values val (- old-exp IEEE-single-float-bias) sign))
+           #+64-bit-target
+	   (values (set-%short-float-exp (%short-float-abs n)
+					 IEEE-single-float-bias)
+		   (- old-exp IEEE-single-float-bias) sign)))))))
+
+; (* float (expt 2 int))
+(defun scale-float (float int)
+  "Return the value (* f (expt (float 2 f) ex)), but with no unnecessary loss
+  of precision or overflow."
+  (unless (fixnump int)(setq int (require-type int 'fixnum)))
+  (number-case float
+    (double-float
+     (let* ((float-exp (%double-float-exp float))
+            (new-exp (+ float-exp int)))
+       (if (eq 0 float-exp) ; already denormalized?
+         (if (%double-float-zerop float)
+           float 
+           (let ((result (%make-dfloat)))
+             (%%scale-dfloat! float (+ (1+ IEEE-double-float-bias) int) result)))
+         (if (<= new-exp 0)  ; maybe going denormalized        
+           (if (<= new-exp (- IEEE-double-float-digits))
+             0.0d0 ; should this be underflow? - should just be normal and result is fn of current fpu-mode
+             ;(error "Can't scale ~s by ~s." float int) ; should signal something                      
+             (let ((result (%make-dfloat)))
+               (%copy-double-float float result)
+               (set-%double-float-exp result 1) ; scale by float-exp -1
+               (%%scale-dfloat! result (+ IEEE-double-float-bias (+ float-exp int)) result)              
+               result))
+           (if (> new-exp IEEE-double-float-normal-exponent-max) 
+             (error (make-condition 'floating-point-overflow
+                                    :operation 'scale-float
+                                    :operands (list float int)))
+             (let ((new-float (%make-dfloat)))
+               (%copy-double-float float new-float)
+               (set-%double-float-exp new-float new-exp)
+               new-float))))))
+    (short-float
+     (let* ((float-exp (%short-float-exp float))
+            (new-exp (+ float-exp int)))
+       (if (eq 0 float-exp) ; already denormalized?
+         (if (%short-float-zerop float)
+           float
+           #+32-bit-target
+           (let ((result (%make-sfloat)))
+             (%%scale-sfloat! float (+ (1+ IEEE-single-float-bias) int) result))
+           #+64-bit-target
+           (%%scale-sfloat float (+ (1+ IEEE-single-float-bias) int)))
+         (if (<= new-exp 0)  ; maybe going denormalized        
+           (if (<= new-exp (- IEEE-single-float-digits))
+             ;; should this be underflow? - should just be normal and
+             ;; result is fn of current fpu-mode (error "Can't scale
+             ;; ~s by ~s." float int) ; should signal something
+             0.0s0
+             #+32-bit-target
+             (let ((result (%make-sfloat)))
+               (%copy-short-float float result)
+               (set-%short-float-exp result 1) ; scale by float-exp -1
+               (%%scale-sfloat! result (+ IEEE-single-float-bias (+ float-exp int)) result)              
+               result)
+             #+64-bit-target
+             (%%scale-sfloat (set-%short-float-exp float 1)
+                             (+ IEEE-single-float-bias (+ float-exp int))))
+           (if (> new-exp IEEE-single-float-normal-exponent-max) 
+             (error (make-condition 'floating-point-overflow
+                                    :operation 'scale-float
+                                    :operands (list float int)))
+             #+32-bit-target
+             (let ((new-float (%make-sfloat)))
+               (%copy-short-float float new-float)
+               (set-%short-float-exp new-float new-exp)
+               new-float)
+             #+64-bit-target
+             (set-%short-float-exp float new-exp))))))))
+
+(defun %copy-float (f)
+  ;Returns a freshly consed float.  float can also be a macptr.
+  (cond ((double-float-p f) (%copy-double-float f (%make-dfloat)))
+        ((macptrp f)
+         (let ((float (%make-dfloat)))
+           (%copy-ptr-to-ivector f 0 float (* 4 target::double-float.value-cell) 8)
+           float))
+        (t (error "Illegal arg ~s to %copy-float" f))))
+
+(defun float-precision (float)     ; not used - not in cltl2 index ?
+  "Return a non-negative number of significant digits in its float argument.
+  Will be less than FLOAT-DIGITS if denormalized or zero."
+  (number-case float
+     (double-float
+      (if (eq 0 (%double-float-exp float))
+        (if (not (%double-float-zerop float))
+        ; denormalized
+          (- IEEE-double-float-mantissa-width (dfloat-significand-zeros float))
+          0)
+        IEEE-double-float-digits))
+     (short-float 
+      (if (eq 0 (%short-float-exp float))
+        (if (not (%short-float-zerop float))
+        ; denormalized
+          (- IEEE-single-float-mantissa-width (sfloat-significand-zeros float))
+          0)
+        IEEE-single-float-digits))))
+
+
+(defun %double-float (number &optional result)
+  ;(require-null-or-double-float-sym result)
+  ; use number-case when macro is common
+  (number-case number
+    (double-float
+     (if result 
+       (%copy-double-float number result)
+         number))
+    (short-float
+     (%short-float->double-float number (or result (%make-dfloat))))
+    (fixnum
+     (%fixnum-dfloat number (or result (%make-dfloat))))
+    (bignum (%bignum-dfloat number result))
+    (ratio 
+     (if (not result)(setq result (%make-dfloat)))
+     (let* ((num (%numerator number))
+            (den (%denominator number)))
+       ; dont error if result is floatable when either top or bottom is not.
+       ; maybe do usual first, catching error
+       (if (not (or (bignump num)(bignump den)))
+         (with-stack-double-floats ((fnum num)
+                                        (fden den))       
+             (%double-float/-2! fnum fden result))
+         (let* ((numlen (integer-length num))
+                (denlen (integer-length den))
+                (exp (- numlen denlen))
+                (minusp (minusp num)))
+           (if (and (<= numlen IEEE-double-float-bias)
+                    (<= denlen IEEE-double-float-bias)
+                    #|(not (minusp exp))|# 
+                    (<= (abs exp) IEEE-double-float-mantissa-width))
+             (with-stack-double-floats ((fnum num)
+                                            (fden den))
+       
+               (%double-float/-2! fnum fden result))
+             (if (> exp IEEE-double-float-mantissa-width)
+               (progn  (%double-float (round num den) result))               
+               (if (>= exp 0)
+                 ; exp between 0 and 53 and nums big
+                 (let* ((shift (- IEEE-double-float-digits exp))
+                        (num (if minusp (- num) num))
+                        (int (round (ash num shift) den)) ; gaak
+                        (intlen (integer-length int))
+                        (new-exp (+ intlen (- IEEE-double-float-bias shift))))
+                   
+                   (when (> intlen IEEE-double-float-digits)
+                     (setq shift (1- shift))
+                     (setq int (round (ash num shift) den))
+                     (setq intlen (integer-length int))
+                     (setq new-exp (+ intlen (- IEEE-double-float-bias shift))))
+                   (when (> new-exp 2046)
+                     (error (make-condition 'floating-point-overflow
+                                            :operation 'double-float
+                                            :operands (list number))))
+		   (make-float-from-fixnums (ldb (byte 25 (- intlen 25)) int)
+					    (ldb (byte 28 (max (- intlen 53) 0)) int)
+					    new-exp ;(+ intlen (- IEEE-double-float-bias 53))
+					    (if minusp -1 1)
+					    result))
+                 ; den > num - exp negative
+                 (progn  
+                   (float-rat-neg-exp num den (if minusp -1 1) result)))))))))))
+
+
+#+32-bit-target
+(defun %short-float-ratio (number &optional result)
+  (if (not result)(setq result (%make-sfloat)))
+  (let* ((num (%numerator number))
+         (den (%denominator number)))
+    ;; dont error if result is floatable when either top or bottom is
+    ;; not.  maybe do usual first, catching error
+    (if (not (or (bignump num)(bignump den)))
+      (target::with-stack-short-floats ((fnum num)
+				       (fden den))       
+        (%short-float/-2! fnum fden result))
+      (let* ((numlen (integer-length num))
+             (denlen (integer-length den))
+             (exp (- numlen denlen))
+             (minusp (minusp num)))
+        (if (and (<= numlen IEEE-single-float-bias)
+                 (<= denlen IEEE-single-float-bias)
+                 #|(not (minusp exp))|# 
+                 (<= (abs exp) IEEE-single-float-mantissa-width))
+          (target::with-stack-short-floats ((fnum num)
+					   (fden den))
+            (%short-float/-2! fnum fden result))
+          (if (> exp IEEE-single-float-mantissa-width)
+            (progn  (%short-float (round num den) result))               
+            (if (>= exp 0)
+              ; exp between 0 and 23 and nums big
+              (let* ((shift (- IEEE-single-float-digits exp))
+                     (num (if minusp (- num) num))
+                     (int (round (ash num shift) den)) ; gaak
+                     (intlen (integer-length int))
+                     (new-exp (+ intlen (- IEEE-single-float-bias shift))))
+		(when (> intlen IEEE-single-float-digits)
+                  (setq shift (1- shift))
+                  (setq int (round (ash num shift) den))
+                  (setq intlen (integer-length int))
+                  (setq new-exp (+ intlen (- IEEE-single-float-bias shift))))
+                (when (> new-exp IEEE-single-float-normal-exponent-max)
+                  (error (make-condition 'floating-point-overflow
+                                         :operation 'short-float
+                                         :operands (list number))))
+                (make-short-float-from-fixnums 
+                   (ldb (byte IEEE-single-float-digits  (- intlen  IEEE-single-float-digits)) int)
+                   new-exp
+                   (if minusp -1 1)
+                   result))
+              ; den > num - exp negative
+              (progn  
+                (float-rat-neg-exp num den (if minusp -1 1) result t)))))))))
+
+#+64-bit-target
+(defun %short-float-ratio (number)
+  (let* ((num (%numerator number))
+         (den (%denominator number)))
+    ;; dont error if result is floatable when either top or bottom is
+    ;; not.  maybe do usual first, catching error
+    (if (not (or (bignump num)(bignump den)))
+      (/ (the short-float (%short-float num))
+         (the short-float (%short-float den)))
+      (let* ((numlen (integer-length num))
+             (denlen (integer-length den))
+             (exp (- numlen denlen))
+             (minusp (minusp num)))
+        (if (and (<= numlen IEEE-single-float-bias)
+                 (<= denlen IEEE-single-float-bias)
+                 #|(not (minusp exp))|# 
+                 (<= (abs exp) IEEE-single-float-mantissa-width))
+          (/ (the short-float (%short-float num))
+             (the short-float (%short-float den)))
+          (if (> exp IEEE-single-float-mantissa-width)
+            (progn  (%short-float (round num den)))
+            (if (>= exp 0)
+              ; exp between 0 and 23 and nums big
+              (let* ((shift (- IEEE-single-float-digits exp))
+                     (num (if minusp (- num) num))
+                     (int (round (ash num shift) den)) ; gaak
+                     (intlen (integer-length int))
+                     (new-exp (+ intlen (- IEEE-single-float-bias shift))))
+		(when (> intlen IEEE-single-float-digits)
+                  (setq shift (1- shift))
+                  (setq int (round (ash num shift) den))
+                  (setq intlen (integer-length int))
+                  (setq new-exp (+ intlen (- IEEE-single-float-bias shift))))
+                (when (> new-exp IEEE-single-float-normal-exponent-max)
+                  (error (make-condition 'floating-point-overflow
+                                         :operation 'short-float
+                                         :operands (list number))))
+                (make-short-float-from-fixnums 
+                   (ldb (byte IEEE-single-float-digits  (- intlen  IEEE-single-float-digits)) int)
+                   new-exp
+                   (if minusp 1 0)))
+              ; den > num - exp negative
+              (progn  
+                (float-rat-neg-exp num den (if minusp -1 1) nil t)))))))))
+
+
+#+32-bit-target
+(defun %short-float (number &optional result)
+  (number-case number
+    (short-float
+     (if result (%copy-short-float number result) number))
+    (double-float
+     (%double-float->short-float number (or result (%make-sfloat))))
+    (fixnum
+     (%fixnum-sfloat number (or result (%make-sfloat))))
+    (bignum
+     (%bignum-sfloat number (or result (%make-sfloat))))
+    (ratio
+     (%short-float-ratio number result))))
+
+#+64-bit-target
+(defun %short-float (number)
+  (number-case number
+    (short-float number)
+    (double-float (%double-float->short-float number))
+    (fixnum (%fixnum-sfloat number))
+    (bignum (%bignum-sfloat number))
+    (ratio (%short-float-ratio number))))
+
+
+(defun float-rat-neg-exp (integer divisor sign &optional result short)
+  (if (minusp sign)(setq integer (- integer)))       
+  (let* ((integer-length (integer-length integer))
+         ;; make sure we will have enough bits in the quotient
+         ;; (and a couple extra for rounding)
+         (shift-factor (+ (- (integer-length divisor) integer-length) (if short 28 60))) ; fix
+         (scaled-integer integer))
+    (if (plusp shift-factor)
+      (setq scaled-integer (ash integer shift-factor))
+      (setq divisor (ash divisor (- shift-factor)))  ; assume div > num
+      )
+    ;(pprint (list shift-factor scaled-integer divisor))
+    (multiple-value-bind (quotient remainder)(floor scaled-integer divisor)
+      (unless (zerop remainder) ; whats this - tells us there's junk below
+        (setq quotient (logior quotient 1)))
+      ;; why do it return 2 values?
+      (values (float-and-scale-and-round sign quotient (- shift-factor)  short result)))))
+
+
+
+;;; when is (negate-bignum (bignum-ashift-right big)) ; can't negate
+;;; in place cause may get bigger cheaper than (negate-bignum big) - 6
+;;; 0r 8 digits ; 8 longs so win if digits > 7 or negate it on the
+;;; stack
+
+(defun %bignum-dfloat (big &optional result)  
+  (let* ((minusp (bignum-minusp big)))
+    (flet 
+      ((doit (new-big)
+         (let* ((int-len (bignum-integer-length new-big)))
+           (when (>= int-len (- 2047 IEEE-double-float-bias)) ; args?
+             (error (make-condition 'floating-point-overflow 
+                                    :operation 'float :operands (list big))))
+           (if (> int-len 53)
+             (let* ((hi (ldb (byte 25  (- int-len  25)) new-big))
+                    (lo (ldb (byte 28 (- int-len 53)) new-big)))
+               ;(print (list new-big hi lo))
+               (when (and (logbitp (- int-len 54) new-big)  ; round bit
+                          (or (%ilogbitp 0 lo)    ; oddp
+                              ;; or more bits below round
+                              (%i< (one-bignum-factor-of-two new-big) (- int-len 54))))
+                 (if (eq lo #xfffffff)
+                   (setq hi (1+ hi) lo 0)
+                   (setq lo (1+ lo)))
+                 (when (%ilogbitp 25 hi) ; got bigger
+                   (setq int-len (1+ int-len))
+                   (let ((bit (%ilogbitp 0 hi)))
+                     (setq hi (%ilsr 1 hi))
+                     (setq lo (%ilsr 1 lo))
+                     (if bit (setq lo (%ilogior #x8000000 lo))))))
+               (make-float-from-fixnums hi lo (+ IEEE-double-float-bias int-len)(if minusp -1 1) result))
+             (let* ((hi (ldb (byte 25  (- int-len  25)) new-big))
+                    (lobits (min (- int-len 25) 28))
+                    (lo (ldb (byte lobits (- int-len (+ lobits 25))) new-big)))
+               (if (< lobits 28) (setq lo (ash lo (- 28 lobits))))
+               (make-float-from-fixnums hi lo (+ IEEE-double-float-bias int-len) (if minusp -1 1) result))))))
+      (declare (dynamic-extent #'doit))
+      (with-one-negated-bignum-buffer big doit))))
+
+#+32-bit-target
+(defun %bignum-sfloat (big &optional result)  
+  (let* ((minusp (bignum-minusp big)))
+    (flet 
+      ((doit (new-big)
+         (let* ((int-len (bignum-integer-length new-big)))
+           (when (>= int-len (- 255 IEEE-single-float-bias)) ; args?
+             (error (make-condition 'floating-point-overflow 
+                                    :operation 'float :operands (list big 1.0s0))))
+           (if t ;(> int-len IEEE-single-float-digits) ; always true
+             (let* ((lo (ldb (byte IEEE-single-float-digits  (- int-len  IEEE-single-float-digits)) new-big)))
+               (when (and (logbitp (- int-len 25) new-big)  ; round bit
+                          (or (%ilogbitp 0 lo)    ; oddp
+                              ; or more bits below round
+                              (%i< (one-bignum-factor-of-two new-big) (- int-len 25))))
+                 (setq lo (1+ lo))
+                 (when (%ilogbitp 24 lo) ; got bigger
+                   (setq int-len (1+ int-len))
+                   (setq lo (%ilsr 1 lo))))
+               (make-short-float-from-fixnums  lo (+ IEEE-single-float-bias int-len)(if minusp -1 1) result))
+             ))))
+      (declare (dynamic-extent #'doit))
+      (with-one-negated-bignum-buffer big doit))))
+
+
+#+64-bit-target
+(defun %bignum-sfloat (big)  
+  (let* ((minusp (bignum-minusp big)))
+    (flet 
+      ((doit (new-big)
+         (let* ((int-len (bignum-integer-length new-big)))
+           (when (>= int-len (- 255 IEEE-single-float-bias)) ; args?
+             (error (make-condition 'floating-point-overflow 
+                                    :operation 'float :operands (list big 1.0s0))))
+           (if t ;(> int-len IEEE-single-float-digits) ; always true
+             (let* ((lo (ldb (byte IEEE-single-float-digits  (- int-len  IEEE-single-float-digits)) new-big)))
+               (when (and (logbitp (- int-len 25) new-big)  ; round bit
+                          (or (%ilogbitp 0 lo)    ; oddp
+                              ; or more bits below round
+                              (%i< (one-bignum-factor-of-two new-big) (- int-len 25))))
+                 (setq lo (1+ lo))
+                 (when (%ilogbitp 24 lo) ; got bigger
+                   (setq int-len (1+ int-len))
+                   (setq lo (%ilsr 1 lo))))
+               (make-short-float-from-fixnums  lo (+ IEEE-single-float-bias int-len)(if minusp -1 1)))
+             ))))
+      (declare (dynamic-extent #'doit))
+      (with-one-negated-bignum-buffer big doit))))
+
+
+
+
+(defun %fixnum-dfloat (fix &optional result)  
+  (if (eq 0 fix) 
+    (if result (%copy-double-float 0.0d0 result) 0.0d0)
+    (progn
+      (when (not result)(setq result (%make-dfloat)))
+      ; it better return result
+      (%int-to-dfloat fix result))))
+
+
+#+32-bit-target
+(defun %fixnum-sfloat (fix &optional result)
+  (if (eq 0 fix)
+    (if result (%copy-short-float 0.0s0 result) 0.0s0)
+    (%int-to-sfloat! fix (or result (%make-sfloat)))))
+
+#+64-bit-target
+(defun %fixnum-sfloat (fix)
+  (if (eq 0 fix)
+    0.0s0
+    (%int-to-sfloat fix)))
+
+;;; Transcendental functions.
+(defun sin (x)
+  "Return the sine of NUMBER."
+  (if (complexp x)
+    (let* ((r (realpart x))
+           (i (imagpart x)))
+      (complex (* (sin r) (cosh i))
+               (* (cos r) (sinh i))))
+    (if (typep x 'double-float)
+      (%double-float-sin! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+        (%single-float-sin! sx (%make-sfloat)))
+      #+64-bit-target
+      (%single-float-sin (%short-float x)))))
+
+(defun cos (x)
+  "Return the cosine of NUMBER."
+  (if (complexp x)
+    (let* ((r (realpart x))
+           (i (imagpart x)))
+      (complex (* (cos r) (cosh i))
+               (- (* (sin r) (sinh i)))))
+    (if (typep x 'double-float)
+      (%double-float-cos! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+        (%single-float-cos! sx (%make-sfloat)))
+      #+64-bit-target
+      (%single-float-cos (%short-float x)))))
+
+(defun tan (x)
+  "Return the tangent of NUMBER."
+  (if (complexp x)
+    (/ (sin x) (cos x))
+    (if (typep x 'double-float)
+      (%double-float-tan! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+        (%single-float-tan! sx (%make-sfloat)))
+      #+64-bit-target
+      (%single-float-tan (%short-float x))
+      )))
+
+
+
+
+(defun atan (y &optional (x nil x-p))
+  "Return the arc tangent of Y if X is omitted or Y/X if X is supplied."
+  (if x-p
+    (if (or (typep x 'double-float)
+            (typep y 'double-float))
+      (with-stack-double-floats ((dy y)
+                                 (dx x))
+        (%df-atan2 dy dx))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sy y)
+                                (sx x))
+        (%sf-atan2! sy sx))
+      #+64-bit-target
+      (%sf-atan2 (%short-float y) (%short-float x)))
+    (if (typep y 'complex)
+      (let* ((iy (* (sqrt -1) y)))
+             (/ (- (log (+ 1 iy)) (log (- 1 iy)))
+                #c(0 2)))
+      (if (typep y 'double-float)
+        (%double-float-atan! y (%make-dfloat))
+        #+32-bit-target
+        (target::with-stack-short-floats ((sy y))
+          (%single-float-atan! sy (%make-sfloat)))
+        #+64-bit-target
+        (%single-float-atan (%short-float y))
+        ))))
+
+
+
+(defun log (x &optional (b nil b-p))
+  "Return the logarithm of NUMBER in the base BASE, which defaults to e."
+  (if b-p
+    (if (zerop b)
+      (if (zerop x)
+        (report-bad-arg x '(not (satisfies zerop) ))
+        (if (floatp x) (float 0.0d0 x) 0))
+      (/ (log-e x) (log-e b)))
+    (log-e x)))
+
+(defun log-e (x)
+  (cond 
+    ((bignump x)
+     (if (minusp x)
+       (complex (log-e (- x)) pi)
+       (let* ((base1 3)
+              (guess (floor (1- (integer-length x))
+                            (log base1 2)))
+              (guess1 (* guess (log-e base1))))
+         (+ guess1 (log-e (/ x (expt base1 guess)))))))
+    ((and (ratiop x)  
+          (or (> x most-positive-short-float)
+              (< x most-negative-short-float)))
+     (- (log-e (%numerator x)) (log-e (%denominator x))))
+    ((typep x 'complex)
+     (complex (log-e (abs x)) (phase x)))
+    ((typep x 'double-float)
+     (with-stack-double-floats ((dx x))
+       (if (minusp x)
+         (complex (%double-float-log! (%%double-float-abs! dx dx) (%make-dfloat)) pi)
+         (%double-float-log! dx (%make-dfloat)))))
+    (t
+     #+32-bit-target
+     (target::with-stack-short-floats ((sx x))
+       (if (minusp x)
+         (complex (%single-float-log! (%%short-float-abs! sx sx) (%make-sfloat))
+                  #.(coerce pi 'short-float))
+         (%single-float-log! sx (%make-sfloat))))
+     #+64-bit-target
+     (if (minusp x)
+       (complex (%single-float-log (%short-float-abs (%short-float x))) #.(coerce pi 'single-float))
+       (%single-float-log (%short-float x)))
+     )))
+
+
+
+(defun exp (x)
+  "Return e raised to the power NUMBER."
+  (typecase x
+    (complex (* (exp (realpart x)) (cis (imagpart x))))
+    (double-float (%double-float-exp! x (%make-dfloat)))
+    (t
+     #+32-bit-target
+     (target::with-stack-short-floats ((sx x))
+       (%single-float-exp! sx (%make-sfloat)))
+     #+64-bit-target
+     (%single-float-exp (%short-float x)))))
+
+
+
+(defun expt (b e)
+  "Return BASE raised to the POWER."
+  (cond ((zerop e) (1+ (* b e)))
+	((integerp e)
+         (if (minusp e) (/ 1 (%integer-power b (- e))) (%integer-power b e)))
+        ((zerop b)
+         (if (plusp (realpart e)) b (report-bad-arg e '(number (0) *))))
+        ((and (realp b) (plusp b) (realp e))
+         (if (or (typep b 'double-float)
+                 (typep e 'double-float))
+           (with-stack-double-floats ((b1 b)
+                                      (e1 e))
+             (%double-float-expt! b1 e1 (%make-dfloat)))
+           #+32-bit-target
+           (target::with-stack-short-floats ((b1 b)
+                                     (e1 e))
+             (%single-float-expt! b1 e1 (%make-sfloat)))
+           #+64-bit-target
+           (%single-float-expt (%short-float b) (%short-float e))
+           ))
+        (t (exp (* e (log b))))))
+
+
+
+(defun sqrt (x &aux a b)
+  "Return the square root of NUMBER."
+  (cond ((zerop x) x)
+        ((complexp x) (* (sqrt (abs x)) (cis (/ (phase x) 2))))          
+        ((minusp x) (complex 0 (sqrt (- x))))
+        ((floatp x)
+         (fsqrt x))
+        ((and (integerp x) (eql x (* (setq a (isqrt x)) a))) a)
+        ((and (ratiop x)
+              (let ((n (numerator x))
+                    d)
+                (and (eql n (* (setq a (isqrt n)) a))
+                     (eql (setq d (denominator x))
+                          (* (setq b (isqrt d)) b)))))
+         (/ a b))          
+        (t
+         #+32-bit-target
+         (target::with-stack-short-floats ((f1))
+           (fsqrt (%short-float x f1)))
+         #+64-bit-target
+         (fsqrt (%short-float x)))))
+
+
+
+(defun asin (x)
+  "Return the arc sine of NUMBER."
+  (number-case x
+    (complex
+      (let ((sqrt-1-x (sqrt (- 1 x)))
+            (sqrt-1+x (sqrt (+ 1 x))))
+        (complex (atan (/ (realpart x)
+                          (realpart (* sqrt-1-x sqrt-1+x))))
+                 (asinh (imagpart (* (conjugate sqrt-1-x)
+                                     sqrt-1+x))))))
+    (double-float
+     (locally (declare (type double-float x))
+       (if (and (<= -1.0d0 x)
+		(<= x 1.0d0))
+	 (%double-float-asin! x (%make-dfloat))
+	 (let* ((temp (+ (complex -0.0d0 x)
+			 (sqrt (- 1.0d0 (the double-float (* x x)))))))
+	   (complex (phase temp) (- (log (abs temp))))))))
+    ((short-float rational)
+     #+32-bit-target
+     (let* ((x1 (%make-sfloat)))
+       (declare (dynamic-extent x1))
+       (if (and (realp x) 
+		(<= -1.0s0 (setq x (%short-float x x1)))
+		(<= x 1.0s0))
+	 (%single-float-asin! x1 (%make-sfloat))
+	 (progn
+	   (setq x (+ (complex (- (imagpart x)) (realpart x))
+		      (sqrt (- 1 (* x x)))))
+	   (complex (phase x) (- (log (abs x)))))))
+     #+64-bit-target
+     (if (and (realp x) 
+              (<= -1.0s0 (setq x (%short-float x)))
+              (<= x 1.0s0))
+	 (%single-float-asin x)
+	 (progn
+	   (setq x (+ (complex (- (imagpart x)) (realpart x))
+		      (sqrt (- 1 (* x x)))))
+	   (complex (phase x) (- (log (abs x))))))
+     )))
+
+
+(eval-when (:execute :compile-toplevel)
+  (defconstant double-float-half-pi (asin 1.0d0))
+  (defconstant single-float-half-pi (asin 1.0f0))
+)
+
+
+
+(defun acos (x)
+  "Return the arc cosine of NUMBER."
+  (number-case x
+    (complex
+     (let ((sqrt-1+x (sqrt (+ 1 x)))
+	   (sqrt-1-x (sqrt (- 1 x))))
+       (complex (* 2 (atan (/ (realpart sqrt-1-x)
+			      (realpart sqrt-1+x))))
+		(asinh (imagpart (* (conjugate sqrt-1+x)
+				    sqrt-1-x))))))
+    
+    (double-float
+     (locally (declare (type double-float x))
+       (if (and (<= -1.0d0 x)
+		(<= x 1.0d0))
+	 (%double-float-acos! x (%make-dfloat))
+	 (- double-float-half-pi (asin x)))))
+    ((short-float rational)
+     #+32-bit-target
+     (target::with-stack-short-floats ((sx x))
+	(locally
+	    (declare (type short-float sx))
+	  (if (and (<= -1.0s0 sx)
+		   (<= sx 1.0s0))
+	    (%single-float-acos! sx (%make-sfloat))
+	    (- single-float-half-pi (asin sx)))))
+     #+64-bit-target
+     (let* ((sx (%short-float x)))
+       (declare (type short-float sx))
+       (if (and (<= -1.0s0 sx)
+                (<= sx 1.0s0))
+         (%single-float-acos sx)
+         (- single-float-half-pi (asin sx))))
+     )))
+
+
+(defun fsqrt (x)
+  (etypecase x
+    (double-float (%double-float-sqrt! x (%make-dfloat)))
+    (single-float
+     #+32-bit-target
+     (%single-float-sqrt! x (%make-sfloat))
+     #+64-bit-target
+     (%single-float-sqrt x))))
+
+
+
+(defun %df-atan2 (y x &optional result)
+  (if (zerop x)
+    (if (zerop y)
+      (if (plusp (float-sign x))
+        y
+        (float-sign y pi))
+      (float-sign y double-float-half-pi))
+    (%double-float-atan2! y x (or result (%make-dfloat)))))
+
+#+32-bit-target
+(defun %sf-atan2! (y x &optional result)
+  (if (zerop x)
+    (if (zerop y)
+      (if (plusp (float-sign x))
+        y
+        (float-sign y pi))
+      (float-sign y single-float-half-pi))
+    (%single-float-atan2! y x (or result (%make-sfloat)))))
+
+#+64-bit-target
+(defun %sf-atan2 (y x)
+  (if (zerop x)
+    (if (zerop y)
+      (if (plusp (float-sign x))
+        y
+        (float-sign y pi))
+      (float-sign y single-float-half-pi))
+    (%single-float-atan2 y x)))
+
+#+64-bit-target
+(defun %short-float-exp (n)
+  (let* ((bits (single-float-bits n)))
+    (declare (type (unsigned-byte 32) bits))
+    (ldb (byte IEEE-single-float-exponent-width IEEE-single-float-exponent-offset) bits)))
+
+
+#+64-bit-target
+(defun set-%short-float-exp (float exp)
+  (host-single-float-from-unsigned-byte-32
+   (dpb exp
+        (byte IEEE-single-float-exponent-width
+              IEEE-single-float-exponent-offset)
+        (the (unsigned-byte 32) (single-float-bits float)))))
+
+#+64-bit-target
+(defun %%scale-sfloat (float int)
+  (* (the single-float float)
+     (the single-float (host-single-float-from-unsigned-byte-32
+                        (dpb int
+                             (byte IEEE-single-float-exponent-width
+                                   IEEE-single-float-exponent-offset)
+                             0)))))
+
+#+64-bit-target
+(defun %double-float-exp (n)
+  (let* ((highword (double-float-bits n)))
+    (declare (fixnum highword))
+    (logand (1- (ash 1 IEEE-double-float-exponent-width))
+            (ash highword (- (- IEEE-double-float-exponent-offset 32))))))
+
+#+64-bit-target
+(defun set-%double-float-exp (float exp)
+  (let* ((highword (double-float-bits float)))
+    (declare (fixnum highword))
+    (setf (uvref float target::double-float.val-high-cell)
+          (dpb exp
+               (byte IEEE-double-float-exponent-width
+                     (- IEEE-double-float-exponent-offset 32))
+               highword))
+    exp))
+
+#+64-bit-target
+(defun %integer-decode-double-float (f)
+  (multiple-value-bind (hiword loword) (double-float-bits f)
+    (declare (type (unsigned-byte 32) hiword loword))
+    (let* ((exp (ldb (byte IEEE-double-float-exponent-width
+                           (- IEEE-double-float-exponent-offset 32))
+                     hiword))
+           (mantissa (logior
+                      (the fixnum
+                        (dpb (ldb (byte (- IEEE-double-float-mantissa-width 32)
+                                        IEEE-double-float-mantissa-offset)
+                                  hiword)
+                             (byte (- IEEE-double-float-mantissa-width 32)
+                                   32)
+                             loword))
+                      (if (zerop exp)
+                        0
+                        (ash 1 IEEE-double-float-hidden-bit))))
+           (sign (if (logbitp 31 hiword) -1 1)))
+      (declare (fixnum exp mantissa sign))
+      (values (ldb (byte 25 28) mantissa)
+              (ldb (byte 28 0) mantissa)
+              exp
+              sign))))
+
+;;; end of l0-float.lisp
Index: /branches/new-random/level-0/l0-hash.lisp
===================================================================
--- /branches/new-random/level-0/l0-hash.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-hash.lisp	(revision 13309)
@@ -0,0 +1,1996 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;;;;;;;;;;;;
+;;
+;; See hash.lisp for documentation
+
+
+(eval-when (:compile-toplevel :execute)
+  (require "HASHENV" "ccl:xdump;hashenv")
+  (require :number-case-macro)
+  (define-symbol-macro deleted-hash-key-marker (%slot-unbound-marker))
+  (define-symbol-macro free-hash-marker (%unbound-marker))
+  (define-symbol-macro rehashing-value-marker (%slot-unbound-marker))
+  (declaim (inline nhash.vector-size))
+  (declaim (inline mixup-hash-code))
+  (declaim (inline hash-table-p))
+  (declaim (inline %%eqhash))
+  (declaim (inline index->vector-index vector-index->index swap))
+  (declaim (inline %already-rehashed-p %set-already-rehashed-p))
+  (declaim (inline need-use-eql))
+  (declaim (inline %needs-rehashing-p))
+  (declaim (inline compute-hash-code))
+  (declaim (inline eq-hash-find eq-hash-find-for-put))
+  (declaim (inline read-lock-hash-table write-lock-hash-table  unlock-hash-table))
+  (declaim (inline %hash-symbol))
+  (declaim (inline hash-mod))
+  (declaim (inline set-hash-key-conditional set-hash-value-conditional))
+  (declaim (inline hash-lock-free-p lock-free-gethash)))
+
+
+
+(defun %cons-hash-table (keytrans-function compare-function vector
+                         threshold rehash-ratio rehash-size find find-new owner &optional lock-free-p)
+  (%istruct
+   'HASH-TABLE                          ; type
+   keytrans-function                    ; nhash.keytransF
+   compare-function                     ; nhash.compareF
+   nil                                  ; nhash.rehash-bits
+   vector                               ; nhash.vector
+   (if lock-free-p $nhash.lock-free 0)  ; nhash.lock
+   owner                                ; nhash.owner 
+   threshold                            ; nhash.grow-threshold
+   rehash-ratio                         ; nhash.rehash-ratio
+   rehash-size                          ; nhash.rehash-size
+   0                                    ; nhash.puthash-count
+   (if lock-free-p
+     (make-lock)
+     (unless owner (make-read-write-lock))) ; nhash.exclusion-lock
+   find                                 ; nhash.find
+   find-new                             ; nhash.find-new
+   nil                                  ; nhash.read-only
+   ))
+
+(defun nhash.vector-size (vector)
+  (nhash.vector.size vector))
+
+(defun hash-mod (hash entries vector)
+  (fast-mod-3 hash entries (nhash.vector.size-reciprocal vector)))
+
+;; For lock-free hash tables
+(defun set-hash-key-conditional (index vector old new)
+  (%set-hash-table-vector-key-conditional (%i+ target::misc-data-offset
+                                               (ash (the fixnum index) target::word-shift))
+                                          vector
+                                          old
+                                          new))
+
+(defun set-hash-value-conditional (index vector old new)
+  (store-gvector-conditional (%i+ index 1) vector old new))
+
+(defun hash-lock-free-p (hash)
+  (logtest $nhash.lock-free (the fixnum (nhash.lock hash))))
+ 
+;;; Is KEY something which can be EQL to something it's not EQ to ?
+;;; (e.g., is it a number or macptr ?)
+;;; This can be more general than necessary but shouldn't be less so.
+(defun need-use-eql (key)
+  (let* ((typecode (typecode key)))
+    (declare (fixnum typecode))
+    (or (= typecode target::subtag-macptr)
+        #+(or ppc32-target x8632-target)
+        (and (>= typecode target::min-numeric-subtag)
+             (<= typecode target::max-numeric-subtag))
+        #+64-bit-target
+        (or (= typecode target::subtag-bignum)
+            (= typecode target::subtag-double-float)
+            (= typecode target::subtag-ratio)
+            (= typecode target::subtag-complex)))))
+
+;;; Don't rehash at all, unless some key is address-based (directly or
+;;; indirectly.)
+(defun %needs-rehashing-p (vector)
+  (let* ((flags (nhash.vector.flags vector)))
+    (declare (fixnum flags))
+    (if (logbitp $nhash_track_keys_bit flags)
+      ;; GC is tracking key movement
+      (logbitp $nhash_key_moved_bit flags)
+      ;; GC is not tracking key movement
+      (if (logbitp $nhash_component_address_bit flags)
+        (not (eql (the fixnum (%get-gc-count)) (the fixnum (nhash.vector.gc-count vector))))))))
+
+(defun %set-does-not-need-rehashing (vector)
+  (let* ((flags (nhash.vector.flags vector)))
+    (declare (fixnum flags))
+    (setf (nhash.vector.gc-count vector) (%get-gc-count))
+    (when (logbitp $nhash_track_keys_bit flags)
+      (setf (nhash.vector.flags vector)
+            (logand (lognot (ash 1 $nhash_key_moved_bit)) flags)))))
+
+
+;;; Tempting though it may be to remove this, a hash table loaded from
+;;; a fasl file likely needs to be rehashed, and the MAKE-LOAD-FORM
+;;; for hash tables needs to be able to call this or something similar.
+(defun %set-needs-rehashing (hash)
+  (let* ((vector (nhash.vector hash))
+         (flags (nhash.vector.flags vector)))
+    (declare (fixnum flags))
+    (setf (nhash.vector.gc-count vector) (the fixnum (1- (the fixnum (%get-gc-count)))))
+    (when (logbitp $nhash_track_keys_bit flags)
+      (setf (nhash.vector.flags vector) (logior (ash 1 $nhash_key_moved_bit) flags)))))
+
+#+32-bit-target
+(defun mixup-hash-code (fixnum)
+  (declare (fixnum fixnum))
+  (the fixnum
+    (+ fixnum
+       (the fixnum (%ilsl (- 32 8)
+                          (logand (1- (ash 1 (- 8 3))) fixnum))))))
+
+#+64-bit-target
+(defun mixup-hash-code (fixnum)
+  (declare (fixnum fixnum))
+  (the fixnum
+    (+ fixnum
+       (the fixnum (%ilsl 50
+                          (logand (1- (ash 1 (- 8 3))) fixnum))))))
+
+
+(defun rotate-hash-code (fixnum)
+  (declare (fixnum fixnum))
+  (let* ((low-3 (logand 7 fixnum))
+         (but-low-3 (%ilsr 3 fixnum))
+         (low-3*64K (%ilsl 13 low-3))
+         (low-3-in-high-3 (%ilsl (- 32 3 3) low-3)))
+    (declare (fixnum low-3 but-low-3 low-3*64K low-3-in-high-3))
+    (the fixnum (+ low-3-in-high-3
+                   (the fixnum (logxor low-3*64K but-low-3))))))
+
+
+
+
+(defconstant $nhash-track-keys-mask
+  #.(- (ash 1 $nhash_track_keys_bit)))
+
+(defconstant $nhash-clear-key-bits-mask #xfffff)
+
+
+(defun %hash-symbol (sym)
+  (if sym    
+    (let* ((vector (%symptr->symvector sym))
+           (cell (%svref vector target::symbol.plist-cell))
+           (consp (consp cell)))
+      (or (if consp (%car cell) cell)
+          (let* ((pname (%svref vector target::symbol.pname-cell))
+                 (hash (mixup-hash-code (%pname-hash pname (uvsize pname)))))
+            (declare (type simple-string pname) (fixnum hash))
+            (if consp
+              (setf (%car cell) hash)
+              (setf (%svref vector target::symbol.plist-cell) hash)))))
+    +nil-hash+))
+              
+;;; Hash on address, or at least on some persistent, immutable
+;;; attribute of the key.  If all keys are fixnums or immediates (or if
+;;; that attribute exists), rehashing won't ever be necessary.
+(defun %%eqhash (key)
+  (let* ((typecode (typecode key)))
+    (if (eq typecode target::tag-fixnum)
+      (values (mixup-hash-code key) nil)
+      (if (eq typecode target::subtag-instance)
+        (values (mixup-hash-code (instance.hash key)) nil)
+        (if (symbolp key)
+          (values (%hash-symbol key) nil)
+          (let ((hash (mixup-hash-code (strip-tag-to-fixnum key))))
+            (if (immediate-p-macro key)
+              (values hash nil)
+              (values hash :key ))))))))
+
+
+#+32-bit-target
+(defun swap (num)
+  (declare (fixnum num))
+  (the fixnum (+ (the fixnum (%ilsl 16 num))(the fixnum (%ilsr 13 num)))))
+
+#+64-bit-target
+(defun swap (num)
+  (declare (fixnum num))
+  (the fixnum (+ (the fixnum (%ilsl 32 num))(the fixnum (%ilsr 29 num)))))
+
+;;; teeny bit faster when nothing to do
+(defun %%eqlhash-internal (key)
+  (number-case key
+    (fixnum (mixup-hash-code key)) ; added this 
+    (double-float (%dfloat-hash key))
+    (short-float (%sfloat-hash key))
+    (bignum (%bignum-hash key))
+    (ratio (logxor (swap (%%eqlhash-internal (numerator key)))
+                   (%%eqlhash-internal (denominator key))))
+    (complex
+     (logxor (swap (%%eqlhash-internal (realpart key)))
+             (%%eqlhash-internal (imagpart key))))
+    (t (cond ((macptrp key)
+              (%macptr-hash key))
+             (t key)))))
+
+               
+
+
+;;; new function
+
+(defun %%eqlhash (key)
+  ;; if key is a macptr, float, bignum, ratio, or complex, convert it
+  ;; to a fixnum
+  (if (hashed-by-identity key)
+    (%%eqhash key)
+    (let ((primary  (%%eqlhash-internal key)))
+      (if (eq primary key)
+        (%%eqhash key)
+        (mixup-hash-code (strip-tag-to-fixnum primary))))))
+
+
+(defun %%equalhash (key)
+  (let* ((id-p (hashed-by-identity key))
+         (hash (if (and key (not id-p)) (%%eqlhash-internal key)))
+         addressp)
+    (cond ((null key) (mixup-hash-code 17))
+          #+64-bit-target
+          ((and (typep key 'single-float)
+                (zerop (the single-float key)))
+           0)
+          ((immediate-p-macro key) (mixup-hash-code (strip-tag-to-fixnum key)))
+          ((and hash (neq hash key)) hash)  ; eql stuff
+          (t (typecase key
+                (simple-string (%pname-hash key (length key)))
+                (string
+                 (let ((length (length key)))
+                   (multiple-value-bind (data offset) (array-data-and-offset key)
+                     (%string-hash offset data length))))
+                (bit-vector (bit-vector-hash key))
+                (cons
+                 (let ((hash 0))
+                   (do* ((i 0 (1+ i))
+                         (list key (cdr list)))
+                        ((or (not (consp list)) (> i 11))) ; who figured 11?
+                     (declare (fixnum i))
+                     (multiple-value-bind (h1 a1) (%%equalhash (%car list))
+                       (when a1 (setq addressp t))
+                       ; fix the case of lists of same stuff in different order
+                       ;(setq hash (%ilogxor (fixnum-rotate h1 i) hash))
+                       (setq hash (%i+ (rotate-hash-code hash) h1))
+                       ))
+                   (values hash addressp)))
+                (pathname (%%equalphash key))
+                (t (%%eqlhash key)))))))
+
+(defun update-hash-flags (hash vector addressp)
+  (when addressp
+    (flet ((new-flags (flags addressp)
+             (declare (fixnum flags))
+             (if (eq :key addressp)
+               ;; hash code depended on key's address
+               (if (logbitp $nhash_component_address_bit flags)
+                 flags
+                 (logior $nhash-track-keys-mask
+                         (if (logbitp $nhash_track_keys_bit flags)
+                           flags
+                           (bitclr $nhash_key_moved_bit flags))))
+               ;; hash code depended on component address
+               (bitset $nhash_component_address_bit
+                       (logand (lognot $nhash-track-keys-mask) flags)))))
+      (declare (inline new-flags))
+      (if (hash-lock-free-p hash)
+        (loop
+          (let* ((flags (nhash.vector.flags vector))
+                 (new-flags (new-flags flags addressp)))
+            (when (or (eq flags new-flags)
+                      (store-gvector-conditional nhash.vector.flags vector flags new-flags))
+              (return))))
+        (setf (nhash.vector.flags vector)
+              (new-flags (nhash.vector.flags vector) addressp))))))
+
+(defun compute-hash-code (hash key update-hash-flags &optional
+                               (vector (nhash.vector hash))) ; vectorp))
+  (let ((keytransF (nhash.keytransF hash))
+        primary addressp)
+    (if (not (fixnump keytransF))
+      ;; not EQ or EQL hash table
+      (progn
+        (multiple-value-setq (primary addressp) (funcall keytransF key))
+        (let ((immediate-p (immediate-p-macro primary)))
+          (setq primary (strip-tag-to-fixnum primary))
+          (unless immediate-p
+            (setq primary (mixup-hash-code primary))
+            (setq addressp :key))))
+      ;; EQ or EQL hash table
+      (if (and (not (eql keytransF 0))
+	       (need-use-eql key))
+	;; EQL hash table
+	(setq primary (%%eqlhash-internal key))
+	;; EQ hash table - or something eql doesn't do
+	(multiple-value-setq (primary addressp) (%%eqhash key))))
+    (when update-hash-flags
+      (when addressp
+        (update-hash-flags hash vector addressp)))
+    (let* ((entries (nhash.vector-size vector)))
+      (declare (fixnum entries))
+      (values primary
+              (hash-mod primary entries vector)
+              entries))))
+
+(defun %already-rehashed-p (primary rehash-bits)
+  (declare (optimize (speed 3)(safety 0)))
+  (declare (type (simple-array bit (*)) rehash-bits))
+  (eql 1 (sbit rehash-bits primary)))
+
+(defun %set-already-rehashed-p (primary rehash-bits)
+  (declare (optimize (speed 3)(safety 0)))
+  (declare (type (simple-array bit (*)) rehash-bits))
+  (setf (sbit rehash-bits primary) 1))
+
+
+(defun hash-table-p (hash)
+  (istruct-typep hash 'hash-table))
+
+(defun %normalize-hash-table-count (hash)
+  (let* ((vector (nhash.vector hash))
+	 (weak-deletions-count (nhash.vector.weak-deletions-count vector)))
+    (declare (fixnum weak-deletions-count))
+    (unless (eql 0 weak-deletions-count)
+      (setf (nhash.vector.weak-deletions-count vector) 0)
+      ;; lock-free hash tables don't maintain deleted-count, since would need to
+      ;; lock and it's not worth it.
+      (unless (hash-lock-free-p hash)
+	(let ((deleted-count (the fixnum
+			       (+ (the fixnum (nhash.vector.deleted-count vector))
+				  weak-deletions-count)))
+	      (count (the fixnum (- (the fixnum (nhash.vector.count vector)) weak-deletions-count))))
+          (setf (nhash.vector.deleted-count vector) deleted-count
+                (nhash.vector.count vector) count))))))
+
+
+(defparameter *shared-hash-table-default* t
+  "Be sure that you understand the implications of changing this
+before doing so.")
+
+(defparameter *lock-free-hash-table-default* :shared
+  "If NIL, hash tables default to using the standard algorithms, with locks for shared tables.
+   If :SHARED, shared hash tables default to using the \"lock-free\" algorithm,
+   which is faster for typical access but slower for rehashing or growing the table.
+   Otherwise, all hash tables default to the lock-free algorithm")
+
+(defun make-hash-table (&key (test 'eql)
+                             (size 60)
+                             (rehash-size 1.5)
+                             (rehash-threshold .85)
+                             (hash-function nil)
+                             (weak nil)
+                             (finalizeable nil)
+                             (address-based t)  ;; Ignored
+                             (lock-free *lock-free-hash-table-default*)
+                             (shared *shared-hash-table-default*))
+  "Create and return a new hash table. The keywords are as follows:
+     :TEST -- Indicates what kind of test to use.
+     :SIZE -- A hint as to how many elements will be put in this hash
+       table.
+     :REHASH-SIZE -- Indicates how to expand the table when it fills up.
+       If an integer, add space for that many elements. If a floating
+       point number (which must be greater than 1.0), multiply the size
+       by that amount.
+     :REHASH-THRESHOLD -- Indicates how dense the table can become before
+       forcing a rehash. Can be any positive number <=1, with density
+       approaching zero as the threshold approaches 0. Density 1 means an
+       average of one entry per bucket."
+  (declare (ignore address-based)) ;; TODO: could reinterpret as "warn if becomes address-based"
+  (unless (and test (or (functionp test) (symbolp test)))
+    (report-bad-arg test '(and (not null) (or symbol function))))
+  (unless (or (functionp hash-function) (symbolp hash-function))
+    (report-bad-arg hash-function '(or symbol function)))
+  (unless (and (realp rehash-threshold) (<= 0.0 rehash-threshold) (<= rehash-threshold 1.0))
+    (report-bad-arg rehash-threshold '(real 0 1)))
+  (unless (or (fixnump rehash-size) (and (realp rehash-size) (< 1.0 rehash-size)))
+    (report-bad-arg rehash-size '(or fixnum (real 1 *))))
+  (unless (fixnump size) (report-bad-arg size 'fixnum))
+  (setq rehash-threshold (/ 1.0 (max 0.01 rehash-threshold)))
+  (let* ((default-hash-function
+             (cond ((or (eq test 'eq) (eq test #'eq)) 
+                    (setq test 0))
+                   ((or (eq test 'eql) (eq test #'eql)) 
+                    (setq test -1))
+                   ((or (eq test 'equal) (eq test #'equal))
+                    (setq test #'equal) #'%%equalhash)
+                   ((or (eq test 'equalp) (eq test #'equalp))
+                    (setq test #'equalp) #'%%equalphash)
+                   (t (setq test (require-type test 'symbol))
+                      (or hash-function 
+                          (error "non-standard test specified without hash-function")))))
+         (find-function
+          (case test
+            (0 #'eq-hash-find)
+            (-1 #'eql-hash-find)
+            (t #'general-hash-find)))
+         (find-put-function
+          (case test
+            (0 #'eq-hash-find-for-put)
+            (-1 #'eql-hash-find-for-put)
+            (t #'general-hash-find-for-put))))
+    (setq hash-function
+          (if hash-function
+            (require-type hash-function 'symbol)
+            default-hash-function))
+    (when (and weak (neq weak :value) (neq test 0))
+      (error "Only EQ hash tables can be weak."))
+    (when (and finalizeable (not weak))
+      (error "Only weak hash tables can be finalizeable."))
+    (when (and (eq lock-free :shared) (not shared))
+      (setq lock-free nil))
+    (multiple-value-bind (grow-threshold total-size)
+        (compute-hash-size (1- size) 1 rehash-threshold)
+      (let* ((flags (+ (if weak (ash 1 $nhash_weak_bit) 0)
+                       (ecase weak
+                         ((t nil :key) 0)
+                         (:value (ash 1 $nhash_weak_value_bit)))
+                       (if finalizeable (ash 1 $nhash_finalizeable_bit) 0)
+                       (if lock-free (ash 1 $nhash_keys_frozen_bit) 0)))
+             (hash (%cons-hash-table 
+                    hash-function test
+                    (%cons-nhash-vector total-size flags)
+                    grow-threshold rehash-threshold rehash-size
+                    find-function find-put-function
+                    (unless shared *current-process*)
+                    lock-free)))
+        (setf (nhash.vector.hash (nhash.vector hash)) hash)
+        hash))))
+
+(defun compute-hash-size (size rehash-size rehash-ratio)
+  (let* ((new-size size))
+    (declare (fixnum size new-size))
+    (setq new-size (max 30 (if (fixnump rehash-size)
+                             (%i+ size rehash-size)
+                             (ceiling (* size rehash-size)))))
+    (if (<= new-size size)
+      (setq new-size (1+ size)))        ; God save you if you make this happen
+    
+    (let ((vector-size (%hash-size (max (+ new-size 2) (ceiling (* new-size rehash-ratio))))))
+      ; TODO: perhaps allow more entries, based on actual size:
+      ;  (values (min (floor vector-size rehash-ratio) (%i- vector-size 2)) vector-size))
+      (values new-size vector-size)
+      )))
+
+;;;  Suggested size is a fixnum: number of pairs.  Return a fixnum >=
+;;;  that size that is relatively prime to all secondary keys.
+(defun %hash-size (suggestion)
+  (declare (fixnum suggestion))
+  (declare (optimize (speed 3)(safety 0)))
+  (if (<= suggestion #.(aref secondary-keys 7))
+    (setq suggestion (+ 2 #.(aref secondary-keys 7)))
+     (setq suggestion (logior 1 suggestion)))
+  (loop
+    (dovector (key secondary-keys (return-from %hash-size suggestion))
+      (when (eql 0 (fast-mod suggestion key))
+        (return)))
+    (incf suggestion 2)))
+
+
+(defvar *continue-from-readonly-hashtable-lock-error* t)
+
+(defun signal-read-only-hash-table-error (hash)
+  (cond ((hash-lock-free-p hash)
+         ;; We don't really do anything different if this is set, so no problem
+         (cerror "Modify it anyway"
+                 "Attempt to modify readonly hash table ~s" hash))
+        (*continue-from-readonly-hashtable-lock-error*
+         (cerror "Make the hash-table writable. DANGEROUS! This could damage your lisp if another thread is acccessing this table. CONTINUE ONLY IF YOU KNOW WHAT YOU'RE DOING!"
+                 "Hash-table ~s is readonly" hash)
+         (assert-hash-table-writeable hash)
+         (write-lock-hash-table hash))
+        (t (error "Hash-table ~s is readonly" hash))))
+
+(defun read-lock-hash-table (hash)
+  (if (nhash.read-only hash)
+    :readonly
+    (let* ((lock (nhash.exclusion-lock hash)))
+      (if lock
+        (read-lock-rwlock lock)
+        (unless (eq (nhash.owner hash) *current-process*)
+          (error "Not owner of hash table ~s" hash))))))
+
+(defun write-lock-hash-table (hash)
+  (if (nhash.read-only hash)
+    (signal-read-only-hash-table-error hash)
+    (let* ((lock (nhash.exclusion-lock hash)))
+      (if lock
+        (write-lock-rwlock lock)
+        (unless (eq (nhash.owner hash) *current-process*)
+          (error "Not owner of hash table ~s" hash))))))
+
+
+(defun unlock-hash-table (hash was-readonly)
+  (unless was-readonly
+    (let* ((lock (nhash.exclusion-lock hash)))
+      (if lock
+        (unlock-rwlock lock)))))
+
+(defun index->vector-index (index)
+  (declare (fixnum index))
+  (the fixnum (+ $nhash.vector_overhead (the fixnum (+ index index)))))
+
+(defun vector-index->index (index)
+  (declare (fixnum index))
+  (the fixnum (ash (the fixnum (- index $nhash.vector_overhead)) -1)))
+
+(defun hash-table-count (hash)
+  "Return the number of entries in the given HASH-TABLE."
+  (setq hash (require-type hash 'hash-table))
+  (when (hash-lock-free-p hash)
+    ;; We don't try to maintain a running total, so just count.
+    (return-from hash-table-count (lock-free-count-entries hash)))
+  (%normalize-hash-table-count hash)
+  (the fixnum (nhash.vector.count (nhash.vector hash))))
+
+(defun hash-table-rehash-size (hash)
+  "Return the rehash-size HASH-TABLE was created with."
+  (nhash.rehash-size (require-type hash 'hash-table)))
+
+(defun hash-table-rehash-threshold (hash)
+  "Return the rehash-threshold HASH-TABLE was created with."
+  (/ 1.0 (nhash.rehash-ratio (require-type hash 'hash-table))))
+
+(defun hash-table-size (hash)
+  "Return a size that can be used with MAKE-HASH-TABLE to create a hash
+   table that can hold however many entries HASH-TABLE can hold without
+   having to be grown."
+  (let* ((hash (require-type hash 'hash-table))
+         (vector (nhash.vector hash)))
+    (values (floor (nhash.vector.size vector) (nhash.rehash-ratio hash)))))
+
+(defun hash-table-test (hash)
+  "Return the test HASH-TABLE was created with."
+  (let ((f (nhash.compareF (require-type hash 'hash-table))))
+    (if (fixnump f)
+      (if (eql 0 f) 'eq 'eql)
+      (let ((name (if (symbolp f) f (function-name f))))
+        (if (memq name '(equal equalp)) name f)))))
+
+;;; sometimes you'd rather have the function than the symbol.
+(defun hash-table-test-function (hash)
+  (let ((f (nhash.compareF (require-type hash 'hash-table))))
+    (if (fixnump f)
+      (if (eql 0 f) #'eq #'eql)
+      f)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; nearly-lock-free hash tables
+;;
+;; A modification of the lock-free hash table algorithm described by Cliff Click Jr.  in
+;; http://blogs.azulsystems.com/cliff/2007/03/a_nonblocking_h.html.
+;;
+;; The modifications have to do with the fact that our goal is just to minimize the
+;; performance impact of thread-safety, by eliminating the need for locking on every
+;; read.  I don't bother with aspects of his algorithm that aren't relevant to that goal.
+;;
+;; The main difference from Click's algorithm is that I don't try to do rehashing
+;; concurrently.  Instead, rehashing grabs a lock, so that only one thread can be
+;; rehashing at any given time, and readers/writers will block waiting for the rehashing
+;; to finish.
+;;
+;; In addition, I don't have a separate state for partially inserted key, I reuse the
+;; DELETED state for that.  So in our implementation the following are the possible states
+;; of a hash table entry (where "object" means any object other than the special markers):
+;;
+;; State      Key               Value
+;; DELETED1   object            free-hash-marker
+;; DELETED2   deleted-marker    free-hash-marker
+;; IN-USE     object            object
+;; FREE       free-hash-marker  free-hash-marker
+;; REHASHING  object            rehashing-value-marker
+;; REHASHING  free-hash-marker  rehashing-value-marker
+;; REHASHING  deleted-marker    rehashing-value-marker
+;;
+;; No other states are allowed - at no point in time can a hash table entry be in any
+;; other state.   In addition, the only transitions allowed on the key slot are
+;; free-hash-marker -> object/deleted-marker -> deleted-marker.  Once a key slot
+;; is claimed, it must never change to free or another key value (even after the hash
+;; vector has been discarded after rehashing, because there some process might still
+;; be looking at it).
+;; In particular, rehashing in place is not an option.  All rehashing creates a new
+;; vector and copies into it.  This means it's kinda risky to use lock-free hash
+;; tables with address-based keys, because they will thrash in low-memory situations,
+;; but we don't disallow it because a particular use might not have this problem.
+;;
+;; The following operations may take place:
+;;
+;; * gethash: find matching key - if no match, return not found.  Else fetch value,
+;;   if value is rehashing-value-marker then maybe-rehash and try again;
+;;   if value is free-hash-marker, return not found, else return found value.
+;;
+;; * puthash: find matching key or FREE slot.
+;;   ** If found key, fetch value.
+;;      if value is rehashing-value-marker then maybe-rehash and try again;
+;;      else store-conditional the value -> new value, if fails try again.
+;;   ** Else have FREE slot, store-key-conditional free-hash-marker -> key,
+;;      and if that succeeds, store-conditional free-hash-marker -> new value,
+;;      if either fails, maybe-rehash and try again.
+;;
+;; * remhash: find matching key - if no match, done.  Else fetch value,
+;;   if value is rehashing-value-marker then maybe-rehash and try again;
+;;   else store-conditional the value -> free-hash-marker, if fails try again.
+;;
+;; * rehash: grab a lock, estimate number of entries, make a new vector.  loop over
+;; old vector, at each entry fetch the old value with atomic swap of
+;; rehashing-value-marker.  This prevents any further state changes involving the
+;; value.  It doesn't prevent state changes involving the key, but the only ones that
+;; can happen is FREE -> DELETED, and DELETED1 <-> DELETED2, all of which are
+;; equivalent from the point of view of rehashing.  Anyway, if the old value was
+;; rehashing-value-marker then bug (because we have a lock).  If the old value is
+;; free-hash-marker then do nothing, else get the entry key and rehash into the new
+;; vector -- if no more room, start over.  When done, store the new vector in the
+;; hash table and release lock.
+;;
+;; * gc: for weak tables, gc may convert IN-USE states to DELETED2 states.
+;;   Even for non-weak tables, gc could convert DELETED1 states to DELETED2.
+
+
+(defun lock-free-rehash (hash)
+  ;;(break "We think we need to rehash ~s" (nhash.vector hash))
+  (with-lock-context
+    (without-interrupts ;; not re-entrant
+      (let ((lock (nhash.exclusion-lock hash)))
+        (%lock-recursive-lock-object lock)
+        ;; TODO: might also want to rehash if deleted entries are a large percentage
+        ;; of all entries, more or less.
+        (when (or (%i<= (nhash.grow-threshold hash) 0) ;; no room
+                  (%needs-rehashing-p (nhash.vector hash))) ;; or keys moved
+          (%lock-free-rehash hash))
+        (%unlock-recursive-lock-object lock)))))
+
+
+;; TODO: This is silly.  We're implementing atomic swap using store-conditional,
+;; but internally store-conditional is probably implemented using some kind of
+;; an atomic swap!!
+(defun atomic-swap-gvector (index gvector value)
+  (loop
+    (let ((old-value (%svref gvector index)))
+      (when (store-gvector-conditional index gvector old-value value)
+        (return old-value)))))
+
+;; Interrupts are disabled and caller has the hash lock on the table, blocking other
+;; threads attempting a rehash.
+;; Other threads might be reading/writing/deleting individual entries, but they
+;; will block if they see a value = rehashing-value-marker.
+;; GC may run, updating the needs-rehashing flags and deleting weak entries in both
+;; old and new vectors.
+(defun %lock-free-rehash (hash)
+  (let* ((old-vector (nhash.vector hash))
+         (inherited-flags (logand $nhash_weak_flags_mask (nhash.vector.flags old-vector)))
+         (grow-threshold (nhash.grow-threshold hash))
+         count new-vector vector-size)
+    ;; Prevent puthash from adding new entries.  Note this doesn't keep it from undeleting
+    ;; existing entries, so we might still lose, but this makes the odds much smaller.
+    (setf (nhash.grow-threshold hash) 0)
+    (setq count (lock-free-count-entries hash))
+    (multiple-value-setq (grow-threshold vector-size)
+      (if (%i<= grow-threshold 0) ; if ran out of room, grow, else get just enough.
+        (compute-hash-size count (nhash.rehash-size hash) (nhash.rehash-ratio hash))
+        (compute-hash-size count 1 (nhash.rehash-ratio hash))))
+    (setq new-vector (%cons-nhash-vector vector-size inherited-flags))
+    (loop with full-count = grow-threshold
+          for i from $nhash.vector_overhead below (uvsize old-vector) by 2
+          do (let* ((value (atomic-swap-gvector (%i+ i 1) old-vector rehashing-value-marker))
+                    (key (%svref old-vector i)))
+               (when (eq value rehashing-value-marker) (error "Who else is doing this?"))
+               (unless (or (eq value free-hash-marker) (eq key deleted-hash-key-marker))
+                 (let* ((new-index (%growhash-probe new-vector hash key))
+                        (new-vector-index (index->vector-index new-index)))
+                   (%set-hash-table-vector-key new-vector new-vector-index key)
+                   (setf (%svref new-vector (%i+ new-vector-index 1)) value)
+                   (decf grow-threshold)
+                   (when (%i<= grow-threshold 0)
+                     ;; Too many entries got undeleted while we were rehashing (that's the
+                     ;; only way we could end up with more than COUNT entries, as adding
+                     ;; new entries is blocked).  Grow the output vector.
+                     (multiple-value-bind (bigger-threshold bigger-vector-size)
+                         (compute-hash-size full-count (nhash.rehash-size hash) (nhash.rehash-ratio hash))
+                       (assert (> bigger-vector-size vector-size))
+                       (let ((bigger-vector (%cons-nhash-vector bigger-vector-size 0)))
+                         (%copy-gvector-to-gvector new-vector
+                                                   $nhash.vector_overhead
+                                                   bigger-vector
+                                                   $nhash.vector_overhead
+                                                   (%i- (uvsize new-vector) $nhash.vector_overhead))
+                         (setf (nhash.vector.flags bigger-vector) (nhash.vector.flags new-vector))
+                         (%lock-free-rehash-in-place hash bigger-vector)
+                         (setq grow-threshold (- bigger-threshold full-count))
+                         (setq full-count bigger-threshold)
+                         (setq new-vector bigger-vector)
+                         (setq vector-size bigger-vector-size))))))))
+    (when (%needs-rehashing-p new-vector) ;; keys moved, but at least can use the same new-vector.
+      (%lock-free-rehash-in-place hash new-vector))
+    (setf (nhash.vector.hash new-vector) hash)
+    (setf (nhash.grow-threshold hash) grow-threshold)
+    ;; At this point, another thread might decrement the threshold while they're looking at the old
+    ;; vector. That's ok, just means it will be too small and we'll rehash sooner than planned,
+    ;; no big deal.
+    (setf (nhash.vector hash) new-vector)))
+
+;; This is called on a new vector that hasn't been installed yet, so no other thread is
+;; accessing it.  However, gc might be deleting stuff from it, which is why it tests
+;; key for deleted-hash-key-marker in addition to free-hash-marker value
+(defun %lock-free-rehash-in-place (hash vector)
+  (let* ((vector-index (- $nhash.vector_overhead 2))
+         (size (nhash.vector-size vector))
+         (rehash-bits (%make-rehash-bits hash size))
+         (index -1))
+    (declare (fixnum size index vector-index))
+    (%set-does-not-need-rehashing vector)
+    (loop
+      (when (>= (incf index) size) (return))
+      (setq vector-index (+ vector-index 2))
+      (unless (%already-rehashed-p index rehash-bits)
+        (let* ((value (%svref vector (%i+ vector-index 1)))
+               (key (%svref vector vector-index)))
+          (if (or (eq value free-hash-marker)
+                  (eq key deleted-hash-key-marker))
+            (unless (eq key free-hash-marker)
+              (setf (%svref vector vector-index) free-hash-marker))
+            (let* ((last-index index)
+                   (first t))
+              (loop
+                (let ((found-index (%rehash-probe rehash-bits hash key vector)))
+                  (%set-already-rehashed-p found-index rehash-bits)
+                  (when (eq last-index found-index)
+                    (return))
+                  (let* ((found-vector-index (index->vector-index found-index))
+                         (newvalue (%svref vector (the fixnum (1+ found-vector-index))))
+                         (newkey (%svref vector found-vector-index)))
+                    (declare (fixnum found-vector-index))
+                    (when first         ; or (eq last-index index) ?
+                      (setq first nil)
+                      (setf (%svref vector (the fixnum (1+ vector-index))) free-hash-marker)
+                      (setf (%svref vector vector-index) free-hash-marker))
+                    (%set-hash-table-vector-key vector found-vector-index key)
+                    (setf (%svref vector (the fixnum (1+ found-vector-index))) value)
+                    (when (or (eq newkey deleted-hash-key-marker)
+                              (eq newvalue free-hash-marker))
+                      (return))
+                    (when (eq key newkey)
+                      (cerror "Delete one of the entries." "Duplicate key: ~s in ~s ~s ~s ~s ~s"
+                              key hash value newvalue index found-index)                       
+                      (return))
+                    (setq key newkey
+                          value newvalue
+                          last-index found-index))))))))))
+  t )
+
+
+(defun lock-free-gethash (key hash default)
+  (declare (optimize (speed 3) (safety 0) (debug 0)))
+  (loop
+    (let* ((vector (nhash.vector hash))
+           (vector-index (funcall (the function (nhash.find hash)) hash key)))
+      (declare (fixnum vector-index))
+      ;; Need to punt if vector changed because no way to know whether nhash.find was
+      ;; using old or new vector.
+      (when (eq vector (nhash.vector hash))
+        (cond ((eql vector-index -1)
+               (unless (%needs-rehashing-p vector)
+                 (return-from lock-free-gethash (values default nil))))
+              (t (let ((value (%svref vector (%i+ vector-index 1))))
+                   (unless (eq value rehashing-value-marker)
+                     (if (eq value free-hash-marker)
+                       (return-from lock-free-gethash (values default nil))
+                       (return-from lock-free-gethash (values value t)))))))))
+    ;; We're here because the table needs rehashing or it was getting rehashed while we
+    ;; were searching. Take care of it and try again.
+    (lock-free-rehash hash)))
+
+(defun lock-free-remhash (key hash)
+  (declare (optimize (speed 3) (safety 0) (debug 0)))
+  (when (nhash.read-only hash)
+    (signal-read-only-hash-table-error hash)) ;; continuable
+  (loop
+    (let* ((vector (nhash.vector hash))
+           (vector-index (funcall (the function (nhash.find hash)) hash key)))
+      (declare (fixnum vector-index))
+      ;; Need to punt if vector changed because no way to know whether nhash.find was
+      ;; using old or new vector.
+      (when (eq vector (nhash.vector hash))
+        (cond ((eql vector-index -1)
+               (unless (%needs-rehashing-p vector)
+                 (return-from lock-free-remhash nil)))
+              (t (let ((old-value (%svref vector (%i+ vector-index 1))))
+                   (unless (eq old-value rehashing-value-marker)
+                     (when (eq old-value free-hash-marker)
+                       (return-from lock-free-remhash nil))
+                     (when (set-hash-value-conditional vector-index vector old-value free-hash-marker)
+                       ;; We just use this as a flag - tell gc to scan the vector for deleted keys.
+                       ;; It's just a hint, so don't worry about sync'ing
+                       (setf (nhash.vector.deleted-count vector) 1)
+                       (return-from lock-free-remhash t)))))))
+      ;; We're here because the table needs rehashing or it was getting rehashed while we
+      ;; were searching.  Take care of it and try again.
+      (lock-free-rehash hash))))
+
+(defun lock-free-clrhash (hash)
+  (when (nhash.read-only hash)
+    (signal-read-only-hash-table-error hash)) ;;continuable
+  (with-lock-context
+    (without-interrupts
+     (let ((lock (nhash.exclusion-lock hash)))
+       (%lock-recursive-lock-object lock) ;; disallow rehashing.
+       (loop
+         with vector = (nhash.vector hash)
+         for i1 fixnum from (%i+ $nhash.vector_overhead 1) below (uvsize vector) by 2
+         do (setf (%svref vector i1) free-hash-marker)
+         ;; We just use this as a flag - tell gc to scan the vector for deleted keys.
+         ;; It's just a hint, so don't worry about sync'ing
+         finally (setf (nhash.vector.deleted-count vector) 1))
+       (%unlock-recursive-lock-object lock))))
+  hash)
+
+(defun lock-free-puthash (key hash value)
+  (declare (optimize (speed 3) (safety 0) (debug 0)))
+  (when (or (eq value rehashing-value-marker)
+            (eq value free-hash-marker))
+    (error "Illegal value ~s for storing in a hash table" value))
+  (when (nhash.read-only hash)
+    (signal-read-only-hash-table-error hash)) ;;continuable
+  (loop
+    (let* ((vector (nhash.vector  hash))
+           (vector-index (funcall (nhash.find-new hash) hash key)))
+      ;; Need to punt if vector changed because no way to know whether nhash.find-new was
+      ;; using old or new vector.
+      (when (eq vector (nhash.vector hash))
+        (cond ((or (eql vector-index -1)
+                   (eq (%svref vector vector-index) free-hash-marker))
+               (unless (or (%needs-rehashing-p vector)
+                           (%i<= (nhash.grow-threshold hash) 0))
+                 ;; Note if the puthash fails, grow-threshold will end up too small. This
+                 ;; just means we might rehash sooner than absolutely necessary, no real
+                 ;; harm done (the most likely cause of failing is that somebody is
+                 ;; already rehashing anyway).  DON'T try to incf it back on failure --
+                 ;; that risks grow-threshold ending up too big (e.g. if somebody rehashes
+                 ;; before the incf), which _could_ be harmful.
+                 (atomic-decf (nhash.grow-threshold hash))
+                 (if (set-hash-key-conditional vector-index vector free-hash-marker key)
+                   (when (set-hash-value-conditional vector-index vector free-hash-marker value)
+                     (return-from lock-free-puthash value)))))
+              (t (let ((old-value (%svref vector (%i+ vector-index 1))))
+                   (unless (eq old-value rehashing-value-marker)
+                     (when (set-hash-value-conditional vector-index vector old-value value)
+                       (return-from lock-free-puthash value))))))))
+    ;; We're here because the table needs rehashing or it was getting rehashed while we
+    ;; were searching, or no room for new entry, or somebody else claimed the key from
+    ;; under us (that last case doesn't need to retry, but it's unlikely enough that
+    ;; it's not worth checking for).  Take care of it and try again.
+    (lock-free-rehash hash)))
+
+(defun lock-free-count-entries (hash)
+  ;; Other threads could be adding/removing entries while we count, some of
+  ;; which will be included in the count (i.e. will be treated as if they
+  ;; happened after counting) and some won't (i.e. will be treated as if
+  ;; they happened before counting), but not necessarily in correlation
+  ;; with their temporal relationship.
+  (loop
+    with vector = (nhash.vector hash)
+    for i fixnum from $nhash.vector_overhead below (uvsize vector) by 2
+    count (let ((value (%svref vector (%i+ i 1))))
+            (when (eq value rehashing-value-marker)
+              ;; This table is being rehashed.  Wait for it to be
+              ;; done and try again.
+              (lock-free-rehash hash)
+              (return-from lock-free-count-entries (lock-free-count-entries hash)))
+            (neq value free-hash-marker))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(defun gethash (key hash &optional default)
+  "Finds the entry in HASH-TABLE whose key is KEY and returns the associated
+   value and T as multiple values, or returns DEFAULT and NIL if there is no
+   such entry. Entries can be added using SETF."
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (when (or (eq key free-hash-marker)
+            (eq key deleted-hash-key-marker))
+    (return-from gethash (values default nil)))
+  (when (hash-lock-free-p hash)
+    (return-from gethash (lock-free-gethash key hash default)))
+  (let* ((value nil)
+         (gc-locked nil)
+         (readonly nil)
+         (foundp nil))
+    (with-lock-context
+      (without-interrupts
+        (setq readonly (eq (read-lock-hash-table hash) :readonly))
+        (let* ((vector (nhash.vector hash)))
+          (if (and (eq key (nhash.vector.cache-key vector))
+                   ;; Check twice: the GC might nuke the cached key/value pair
+                   (progn (setq value (nhash.vector.cache-value vector))
+                          (eq key (nhash.vector.cache-key vector))))
+            (setq foundp t)
+            (loop
+              (let* ((vector-index (funcall (nhash.find hash) hash key)))
+                (declare (fixnum vector-index))
+                (cond ((setq foundp (not (eql vector-index -1)))
+                       ;; Referencing both key and value here - and referencing
+                       ;; value first - is an attempt to compensate for the
+                       ;; possibility that the GC deletes a weak-on-key pair.
+                       (setq value (%svref vector (%i+ vector-index 1)))
+                       (when (nhash.owner hash)
+                         (setf (nhash.vector.cache-key vector)
+                               (%svref vector vector-index)
+                               (nhash.vector.cache-value vector)
+                               value
+                               (nhash.vector.cache-idx vector)
+                               (vector-index->index (the fixnum vector-index))))
+                       (return))
+                      ((%needs-rehashing-p vector)
+                       (%lock-gc-lock)
+                       (setq gc-locked t)
+                       (unless readonly
+                         (let* ((lock (nhash.exclusion-lock hash)))
+                           (when lock (%promote-rwlock lock))))
+                       (when (%needs-rehashing-p vector)
+                         (%rehash hash)))
+                      (t (return)))))))
+        (when gc-locked (%unlock-gc-lock))
+        (unlock-hash-table hash readonly)))
+    (if foundp
+      (values value t)
+      (values default nil))))
+
+(defun remhash (key hash)
+  "Remove the entry in HASH-TABLE associated with KEY. Return T if there
+   was such an entry, or NIL if not."
+  (unless (typep hash 'hash-table)
+    (setq hash (require-type hash 'hash-table)))
+  (when (hash-lock-free-p hash)
+    (return-from remhash (lock-free-remhash key hash)))
+  (let* ((foundp nil))
+    (with-lock-context
+      (without-interrupts
+       (write-lock-hash-table hash)
+       (%lock-gc-lock)
+       (let* ((vector (nhash.vector hash)))
+         (when (%needs-rehashing-p vector)
+           (%rehash hash))
+         (if (eq key (nhash.vector.cache-key vector))
+           (progn
+             (setf (nhash.vector.cache-key vector) free-hash-marker
+                   (nhash.vector.cache-value vector) nil)
+             (let ((vidx (index->vector-index (nhash.vector.cache-idx vector))))
+               (setf (%svref vector vidx) deleted-hash-key-marker)
+               (setf (%svref vector (the fixnum (1+ vidx))) nil))
+             (incf (the fixnum (nhash.vector.deleted-count vector)))
+             (decf (the fixnum (nhash.vector.count vector)))
+             (setq foundp t))
+           (let* ((vector-index (funcall (nhash.find hash) hash key)))
+             (declare (fixnum vector-index))
+             (unless (eql vector-index -1)
+               ;; always clear the cache cause I'm too lazy to call the
+               ;; comparison function and don't want to keep a possibly
+               ;; deleted key from being GC'd
+               (setf (nhash.vector.cache-key vector) free-hash-marker
+                     (nhash.vector.cache-value vector) nil)
+               ;; Update the count
+               (incf (the fixnum (nhash.vector.deleted-count vector)))
+               (decf (the fixnum (nhash.vector.count vector)))
+               ;; Delete the value from the table.
+               (setf (%svref vector vector-index) deleted-hash-key-marker
+                     (%svref vector (the fixnum (1+ vector-index))) nil)
+               (setq foundp t))))
+         (when (and foundp
+                    (zerop (the fixnum (nhash.vector.count vector))))
+           (do* ((i $nhash.vector_overhead (1+ i))
+                 (n (uvsize vector)))
+                ((= i n))
+             (declare (fixnum i n))
+             (setf (%svref vector i) free-hash-marker))
+           (setf (nhash.grow-threshold hash)
+                 (+ (nhash.vector.deleted-count vector)
+                    (nhash.vector.weak-deletions-count vector)
+                    (nhash.grow-threshold hash))
+                 (nhash.vector.deleted-count vector) 0
+                 (nhash.vector.weak-deletions-count vector) 0)))
+       ;; Return T if we deleted something
+       (%unlock-gc-lock)
+       (unlock-hash-table hash nil)))
+    foundp))
+
+;;; what if somebody is mapping, growing, rehashing? 
+(defun clrhash (hash)
+  "This removes all the entries from HASH-TABLE and returns the hash table
+   itself."
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (when (hash-lock-free-p hash)
+    (return-from clrhash (lock-free-clrhash hash)))
+  (with-lock-context
+    (without-interrupts
+     (write-lock-hash-table hash)
+     (let* ((vector (nhash.vector hash))
+            (size (nhash.vector-size vector))
+            (count (+ size size))
+            (index $nhash.vector_overhead))
+       (declare (fixnum size count index))
+       (dotimes (i count)
+         (setf (%svref vector index) free-hash-marker)
+         (incf index))
+       (incf (the fixnum (nhash.grow-threshold hash))
+             (the fixnum (+ (the fixnum (nhash.vector.count vector))
+                            (the fixnum (nhash.vector.deleted-count vector)))))
+       (setf (nhash.vector.count vector) 0
+             (nhash.vector.cache-key vector) free-hash-marker
+             (nhash.vector.cache-value vector) nil
+             (nhash.vector.finalization-alist vector) nil
+             (nhash.vector.free-alist vector) nil
+             (nhash.vector.weak-deletions-count vector) 0
+             (nhash.vector.deleted-count vector) 0
+             (nhash.vector.flags vector) (logand $nhash_weak_flags_mask
+                                                 (nhash.vector.flags vector))))
+     (unlock-hash-table hash nil)
+     hash)))
+
+
+(defun puthash (key hash default &optional (value default))
+  (declare (optimize (speed 3) (space 0)))
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (when (or (eq key free-hash-marker)
+            (eq key deleted-hash-key-marker))
+    (error "Can't use ~s as a hash-table key" key))
+  (when (hash-lock-free-p hash)
+    (return-from puthash (lock-free-puthash key hash value)))
+  (with-lock-context
+    (without-interrupts
+     (block protected
+       (tagbody
+          (write-lock-hash-table hash)
+        AGAIN
+          (%lock-gc-lock)
+          (let ((vector (nhash.vector hash)))
+            (when (%needs-rehashing-p vector)
+              (%rehash hash))
+            (when (eq key (nhash.vector.cache-key vector))
+              (let* ((idx (nhash.vector.cache-idx vector)))
+                (declare (fixnum idx))
+                (setf (%svref vector (the fixnum (1+ (the fixnum (index->vector-index idx)))))
+                      value)
+                (setf (nhash.vector.cache-value vector) value)
+                (return-from protected)))               
+            (let* ((vector-index (funcall (nhash.find-new hash) hash key))
+                   (old-value (%svref vector vector-index)))
+              (declare (fixnum vector-index))
+
+              (cond ((eq old-value deleted-hash-key-marker)
+                     (%set-hash-table-vector-key vector vector-index key)
+                     (setf (%svref vector (the fixnum (1+ vector-index))) value)
+                     (incf (the fixnum (nhash.vector.count vector)))
+                     ;; Adjust deleted-count
+                     (when (> 0 (the fixnum
+                                  (decf (the fixnum
+                                          (nhash.vector.deleted-count vector)))))
+                       (%normalize-hash-table-count hash)))
+                    ((eq old-value free-hash-marker)
+                     (when (eql 0 (nhash.grow-threshold hash))
+                       (%unlock-gc-lock)
+                       (%grow-hash-table hash)
+                       (go AGAIN))
+                     (%set-hash-table-vector-key vector vector-index key)
+                     (setf (%svref vector (the fixnum (1+ vector-index))) value)
+                     (decf (the fixnum (nhash.grow-threshold hash)))
+                     (incf (the fixnum (nhash.vector.count vector))))
+                    (t
+                     ;; Key was already there, update value.
+                     (setf (%svref vector (the fixnum (1+ vector-index))) value)))
+              (setf (nhash.vector.cache-idx vector) (vector-index->index vector-index)
+                    (nhash.vector.cache-key vector) key
+                    (nhash.vector.cache-value vector) value)))))
+     (%unlock-gc-lock)
+     (unlock-hash-table hash nil)))
+  value)
+
+
+(defun count-entries (hash)
+  (if (hash-lock-free-p hash)
+    (lock-free-count-entries hash)
+    (let* ((vector (nhash.vector hash))
+           (size (uvsize vector))
+           (idx $nhash.vector_overhead)
+           (count 0))
+      (loop
+        (when (neq (%svref vector idx) free-hash-marker)
+          (incf count))
+        (when (>= (setq idx (+ idx 2)) size)
+          (return count))))))
+
+
+
+
+
+     
+
+(defun grow-hash-table (hash)
+  (unless (typep hash 'hash-table)
+    (setq hash (require-type hash 'hash-table)))
+  (%grow-hash-table hash))
+
+;;; Interrupts are disabled, and the caller has an exclusive
+;;; lock on the hash table.
+(defun %grow-hash-table (hash)
+  (block grow-hash-table
+    (%normalize-hash-table-count hash)
+    (let* ((old-vector (nhash.vector hash))
+           (old-size (nhash.vector.count old-vector))
+           (old-total-size (nhash.vector.size old-vector))
+           (flags 0)
+           (flags-sans-weak 0)
+           (weak-flags nil))
+      (declare (fixnum old-total-size flags flags-sans-weak))
+      (when (> (nhash.vector.deleted-count old-vector) 0)
+        ;; There are enough deleted entries. Rehash to get rid of them
+        (%rehash hash)
+        (return-from grow-hash-table))
+      (multiple-value-bind (size total-size)
+                           (compute-hash-size 
+                            old-size (nhash.rehash-size hash) (nhash.rehash-ratio hash))
+        (unless (eql 0 (nhash.grow-threshold hash))       ; maybe it's done already - shouldnt happen                
+          (return-from grow-hash-table ))
+        (progn
+          (unwind-protect
+            (let ((gc-count (%get-gc-count))
+                  vector)
+              (setq flags (nhash.vector.flags old-vector)
+                    flags-sans-weak (logand flags (logxor -1 $nhash_weak_flags_mask))
+                    weak-flags (logand flags $nhash_weak_flags_mask))
+              (setf (nhash.vector.flags old-vector) flags-sans-weak)      ; disable GC weak stuff
+              (%normalize-hash-table-count hash)
+              (when (> (nhash.vector.deleted-count old-vector) 0)
+                (setf (nhash.vector.flags old-vector) flags)
+                (setq weak-flags nil)
+                (return-from grow-hash-table (%rehash hash)))
+              (setq vector (%cons-nhash-vector total-size 0))
+              (do* ((index 0 (1+ index))
+                    (vector-index (index->vector-index 0) (+ vector-index 2)))
+                   ((>= index old-total-size))
+                (declare (fixnum index vector-index))
+                
+                 (let ((key (%svref old-vector vector-index)))
+                   (unless (or (eq key free-hash-marker)
+                               (eq key deleted-hash-key-marker))
+                     (let* ((new-index (%growhash-probe vector hash key))
+                            (new-vector-index (index->vector-index new-index)))
+                       (setf (%svref vector new-vector-index) key)
+                       (setf (%svref vector (the fixnum (1+ new-vector-index)))
+                             (%svref old-vector (the fixnum (1+ vector-index))))))))
+              (progn
+               (setf (nhash.vector.finalization-alist vector)
+                     (nhash.vector.finalization-alist old-vector)
+                     (nhash.vector.free-alist vector)
+                     (nhash.vector.free-alist old-vector)
+                     (nhash.vector.count vector) old-size
+                     (nhash.vector.flags vector)
+                     (logior (the fixnum weak-flags)
+                             (the fixnum (nhash.vector.flags vector))))
+               (setf (nhash.rehash-bits hash) nil
+                     (nhash.vector hash) vector
+                     (nhash.vector.hash vector) hash
+                     (nhash.vector.cache-key vector) free-hash-marker
+                     (nhash.vector.cache-value vector) nil
+                     (nhash.vector.gc-count vector) gc-count
+                     (nhash.grow-threshold hash) (- size old-size))
+               (setq weak-flags nil)       ; tell clean-up form we finished the loop
+               ;; If the old vector's in some static heap, zero it
+               ;; so that less garbage is retained.
+	       (%init-misc 0 old-vector)))
+            (when weak-flags
+              (setf (nhash.vector.flags old-vector)
+                    (logior (the fixnum weak-flags)
+                            (the fixnum (nhash.vector.flags old-vector)))))))))))
+
+
+
+(defun general-hash-find (hash key)
+  (%hash-probe hash key nil))
+
+(defun general-hash-find-for-put (hash key)
+  (%hash-probe hash key (if (hash-lock-free-p hash) :free :reuse)))
+
+;;; returns a single value:
+;;;   index - the index in the vector for key (where it was or where
+;;;           to insert if the current key at that index is deleted-hash-key-marker
+;;;           or free-hash-marker)
+
+
+
+(defun %hash-probe (hash key for-put-p)
+  (declare (optimize (speed 3) (space 0)))
+  (multiple-value-bind (hash-code index entries)
+                       (compute-hash-code hash key for-put-p)
+    (locally (declare (fixnum hash-code index entries))
+      (let* ((compareF (nhash.compareF hash))
+             (vector (nhash.vector hash))
+             (vector-index 0)
+             table-key
+             (first-deleted-index nil))
+        (declare (fixnum vector-index))
+        (macrolet ((return-it (form)
+                     `(return-from %hash-probe ,form)))
+          (macrolet ((test-it (predicate)
+                       (unless (listp predicate) (setq predicate (list predicate)))
+                       `(progn
+                          (setq vector-index (index->vector-index index)
+                                table-key (%svref vector vector-index))
+                          (cond ((eq table-key free-hash-marker)
+                                 (return-it (if for-put-p
+                                              (or first-deleted-index
+                                                  vector-index)
+                                              -1)))
+                                ((eq table-key deleted-hash-key-marker)
+                                 (when (and (eq for-put-p :reuse)
+                                            (null first-deleted-index))
+                                   (setq first-deleted-index vector-index)))
+                                ((,@predicate key table-key)
+                                 (return-it vector-index))))))
+            (macrolet ((do-it (predicate)
+                         `(progn
+                            (test-it ,predicate)
+                            ; First probe failed. Iterate on secondary key
+                            (let ((initial-index index)
+                                  (secondary-hash (%svref secondary-keys (logand 7 hash-code))))
+                              (declare (fixnum secondary-hash initial-index))
+                              (loop
+                                (incf index secondary-hash)
+                                (when (>= index entries)
+                                  (decf index entries))
+                                (when (eql index initial-index)
+                                  (return-it (if for-put-p
+                                               (or first-deleted-index
+                                                   (error "Bug: no room in table"))
+                                               -1)))
+                                (test-it ,predicate))))))
+              (if (fixnump comparef)
+                ;; EQ or EQL hash table
+                (if (or (eql 0 comparef)
+                        (immediate-p-macro key)
+                        (not (need-use-eql key)))
+                  ;; EQ hash table or EQL == EQ for KEY
+                  (do-it eq)
+                  (do-it eql))
+                ;; general compare function
+                (do-it (funcall comparef))))))))))
+
+(defun eq-hash-find (hash key)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((vector (nhash.vector hash))
+         (hash-code
+          (let* ((typecode (typecode key)))
+            (if (eq typecode target::tag-fixnum)
+              (mixup-hash-code key)
+              (if (eq typecode target::subtag-instance)
+                (mixup-hash-code (instance.hash key))
+                (if (symbolp key)
+                  (%hash-symbol key)
+                  (mixup-hash-code (strip-tag-to-fixnum key)))))))
+         (entries (nhash.vector-size vector))
+         (vector-index (index->vector-index (hash-mod hash-code entries vector)))
+         (table-key (%svref vector vector-index)))
+    (declare (fixnum hash-code  entries vector-index))
+    (if (eq table-key key)
+      vector-index
+      (if (eq table-key free-hash-marker)
+        -1
+        (let* ((secondary-hash (%svref secondary-keys-*-2
+                                       (logand 7 hash-code)))
+               (initial-index vector-index)             
+               (count (+ entries entries))
+               (length (+ count $nhash.vector_overhead)))
+          (declare (fixnum secondary-hash initial-index count length))
+          (loop
+            (incf vector-index secondary-hash)
+            (when (>= vector-index length)
+              (decf vector-index count))
+            (setq table-key (%svref vector vector-index))
+            (when (= vector-index initial-index)
+              (return -1))
+            (if (eq table-key key)
+              (return vector-index)
+              (when (eq table-key free-hash-marker)
+                (return -1)))))))))
+
+;;; As above, but note whether the key is in some way address-based
+;;; and update the hash-vector's flags word if so.
+;;; This only needs to be done by PUTHASH, and it only really needs
+;;; to be done if we're adding a new key.
+(defun eq-hash-find-for-put (hash key)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((vector (nhash.vector hash))
+         (hash-code
+          (let* ((typecode (typecode key)))
+            (if (eq typecode target::tag-fixnum)
+              (mixup-hash-code key)
+              (if (eq typecode target::subtag-instance)
+                (mixup-hash-code (instance.hash key))
+                (if (symbolp key)
+                  (%hash-symbol key)
+                  (progn
+                    (unless (immediate-p-macro key)
+                      (update-hash-flags hash vector :key))
+                    (mixup-hash-code (strip-tag-to-fixnum key))))))))
+         (entries (nhash.vector-size vector))
+         (vector-index (index->vector-index (hash-mod hash-code entries vector)))
+         (table-key (%svref vector vector-index))
+         (reuse (not (hash-lock-free-p hash))))
+    (declare (fixnum hash-code vector-index))
+    (if (or (eq key table-key)
+            (eq table-key free-hash-marker))
+      vector-index
+      (let* ((secondary-hash (%svref secondary-keys-*-2
+                                     (logand 7 hash-code)))
+             (initial-index vector-index)             
+             (first-deleted-index (and reuse
+                                       (eq table-key deleted-hash-key-marker)
+                                       vector-index))
+             (count (+ entries entries))
+             (length (+ count $nhash.vector_overhead)))
+        (declare (fixnum secondary-hash initial-index count length))
+        (loop
+          (incf vector-index secondary-hash)
+          (when (>= vector-index length)
+            (decf vector-index count))
+          (setq table-key (%svref vector vector-index))
+          (when (= vector-index initial-index)
+            (return (or first-deleted-index
+                        (error "Bug: no room in table"))))
+          (if (eq table-key key)
+            (return vector-index)
+            (if (eq table-key free-hash-marker)
+              (return (or first-deleted-index vector-index))
+              (if (and reuse
+                       (null first-deleted-index)
+                       (eq table-key deleted-hash-key-marker))
+                (setq first-deleted-index vector-index)))))))))
+
+(defun eql-hash-find (hash key)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (need-use-eql key)
+    (let* ((vector (nhash.vector hash))
+           (hash-code (%%eqlhash-internal key))
+           (entries (nhash.vector-size vector))
+           (vector-index (index->vector-index (hash-mod hash-code entries vector)))
+           (table-key (%svref vector vector-index)))
+      (declare (fixnum hash-code entries vector-index))
+      (if (eql key table-key)
+        vector-index
+        (if (eq table-key free-hash-marker)
+          -1
+          (let* ((secondary-hash (%svref secondary-keys-*-2
+                                         (logand 7 hash-code)))
+                 (initial-index vector-index)
+                 (count (+ entries entries))
+                 (length (+ count $nhash.vector_overhead)))
+            (declare (fixnum secondary-hash initial-index count length))
+            (loop
+              (incf vector-index secondary-hash)
+              (when (>= vector-index length)
+                (decf vector-index count))
+              (setq table-key (%svref vector vector-index))
+              (when (= vector-index initial-index)
+                (return -1))
+              (if (eql table-key key)
+                (return vector-index)
+                (when (eq table-key free-hash-marker)
+                  (return -1))))))))
+    (eq-hash-find hash key)))
+
+(defun eql-hash-find-for-put (hash key)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (need-use-eql key)
+    (let* ((vector (nhash.vector hash))
+           (hash-code (%%eqlhash-internal key))
+           (entries (nhash.vector-size vector))
+           (vector-index (index->vector-index (hash-mod hash-code entries vector)))
+           (table-key (%svref vector vector-index))
+           (reuse (not (hash-lock-free-p hash))))
+      (declare (fixnum hash-code entries vector-index))
+      (if (or (eql key table-key)
+              (eq table-key free-hash-marker))
+        vector-index
+        (let* ((secondary-hash (%svref secondary-keys-*-2
+                                       (logand 7 hash-code)))
+               (initial-index vector-index)
+               (first-deleted-index (and reuse
+                                         (eq table-key deleted-hash-key-marker)
+                                         vector-index))
+               (count (+ entries entries))
+               (length (+ count $nhash.vector_overhead)))
+          (declare (fixnum secondary-hash initial-index count length))
+          (loop
+            (incf vector-index secondary-hash)
+            (when (>= vector-index length)
+              (decf vector-index count))
+            (setq table-key (%svref vector vector-index))
+            (when (= vector-index initial-index)
+              (return (or first-deleted-index
+                          (error "Bug: no room in table"))))
+            (if (eql table-key key)
+              (return vector-index)
+              (if (eq table-key free-hash-marker)
+                (return (or first-deleted-index vector-index))
+                (if (and reuse
+                         (null first-deleted-index)
+                         (eq table-key deleted-hash-key-marker))
+                  (setq first-deleted-index vector-index))))))))
+    (eq-hash-find-for-put hash key)))
+
+(defun %make-rehash-bits (hash &optional (size (nhash.vector-size (nhash.vector hash))))
+  (declare (fixnum size))
+  (let ((rehash-bits (nhash.rehash-bits hash)))
+    (unless (and rehash-bits
+                 (>= (uvsize rehash-bits) size))
+      (return-from %make-rehash-bits
+        (setf (nhash.rehash-bits hash) (make-array size :element-type 'bit :initial-element 0))))
+    (fill (the simple-bit-vector rehash-bits) 0)))
+
+;;; Rehash.  Caller should have exclusive access to the hash table
+;;; and have disabled interrupts.
+(defun %rehash (hash)
+  (when (hash-lock-free-p hash)
+    (error "How did we get here?"))
+  (let* ((vector (nhash.vector hash))
+         (flags (nhash.vector.flags vector))
+         (vector-index (- $nhash.vector_overhead 2))
+         (size (nhash.vector-size vector))
+         (rehash-bits (%make-rehash-bits hash size))
+         (index -1))
+    (declare (fixnum size index vector-index))
+    (setf (nhash.vector.flags vector)
+          (logand flags $nhash-clear-key-bits-mask))
+    (setf (nhash.vector.cache-key vector) free-hash-marker
+          (nhash.vector.cache-value vector) nil)
+    (%set-does-not-need-rehashing vector)
+    (loop
+      (when (>= (incf index) size) (return))
+      (setq vector-index (+ vector-index 2))
+      (unless (%already-rehashed-p index rehash-bits)
+        (let* ((key (%svref vector vector-index))
+               (deleted (eq key deleted-hash-key-marker)))
+          (unless
+            (when (or deleted (eq key free-hash-marker))
+              (if deleted  ; one less deleted entry
+                (let ((count (1- (nhash.vector.deleted-count vector))))
+                  (declare (fixnum count))
+                  (setf (nhash.vector.deleted-count vector) count)
+                  (if (< count 0)
+                    (let ((wdc (nhash.vector.weak-deletions-count vector)))
+                      (setf (nhash.vector.weak-deletions-count vector) 0)
+                      (incf (nhash.vector.deleted-count vector) wdc)
+                      (decf (nhash.vector.count vector) wdc)))
+                  (incf (nhash.grow-threshold hash))
+                  ;; Change deleted to free
+                  (setf (%svref vector vector-index) free-hash-marker)))
+              t)
+            (let* ((last-index index)
+                   (value (%svref vector (the fixnum (1+ vector-index))))
+                   (first t))
+                (loop
+                  (let ((vector (nhash.vector hash))
+                        (found-index (%rehash-probe rehash-bits hash key)))
+                    (%set-already-rehashed-p found-index rehash-bits)
+                    (if (eq last-index found-index)
+                      (return)
+                      (let* ((found-vector-index (index->vector-index found-index))
+                             (newkey (%svref vector found-vector-index))
+                             (newvalue (%svref vector (the fixnum (1+ found-vector-index)))))
+			(declare (fixnum found-vector-index))
+                        (when first ; or (eq last-index index) ?
+                          (setq first nil)
+                          (setf (%svref vector vector-index) free-hash-marker)
+                          (setf (%svref vector (the fixnum (1+ vector-index))) free-hash-marker))
+                        (%set-hash-table-vector-key vector found-vector-index key)
+                        (setf (%svref vector (the fixnum (1+ found-vector-index))) value)                       
+                        (when (or (eq newkey free-hash-marker)
+                                  (setq deleted (eq newkey deleted-hash-key-marker)))
+                          (when deleted
+                            (let ((count (1- (nhash.vector.deleted-count vector))))
+                              (declare (fixnum count))
+                              (setf (nhash.vector.deleted-count vector) count)
+                              (if (< count 0)
+                                (let ((wdc (nhash.vector.weak-deletions-count vector)))
+                                  (setf (nhash.vector.weak-deletions-count vector) 0)
+                                  (incf (nhash.vector.deleted-count vector) wdc)
+                                  (decf (nhash.vector.count vector) wdc)))
+                              (incf (nhash.grow-threshold hash))))
+                          (return))
+                        (when (eq key newkey)
+                          (cerror "Delete one of the entries." "Duplicate key: ~s in ~s ~s ~s ~s ~s"
+                                  key hash value newvalue index found-index)                       
+                          (decf (nhash.vector.count vector))
+                          (incf (nhash.grow-threshold hash))
+                          (return))
+                        (setq key newkey
+                              value newvalue
+                              last-index found-index)))))))))))
+    t )
+
+;;; Hash to an index that is not set in rehash-bits
+  
+(defun %rehash-probe (rehash-bits hash key &optional (vector (nhash.vector hash)))
+  (declare (optimize (speed 3)(safety 0)))  
+  (multiple-value-bind (hash-code index entries)(compute-hash-code hash key t vector)
+    (declare (fixnum hash-code index entries))
+    (when (null hash-code)(cerror "nuts" "Nuts"))
+    (let* ((vector-index (index->vector-index index)))
+      (if (or (not (%already-rehashed-p index rehash-bits))
+              (eq key (%svref vector vector-index)))
+        (return-from %rehash-probe index)
+        (let ((second (%svref secondary-keys (%ilogand 7 hash-code))))
+          (declare (fixnum second))
+          (loop
+            (setq index (+ index second))
+            (when (>= index entries)
+              (setq index (- index entries)))
+            (when (or (not (%already-rehashed-p index rehash-bits))
+                      (eq key (%svref vector (index->vector-index index))))
+              (return-from %rehash-probe index))))))))
+
+;;; Returns one value: the index of the entry in the vector
+;;; Since we're growing, we don't need to compare and can't find a key that's
+;;; already there.
+(defun %growhash-probe (vector hash key)
+  (declare (optimize (speed 3)(safety 0)))
+  (multiple-value-bind (hash-code index entries)(compute-hash-code hash key t vector)
+    (declare (fixnum hash-code index entries))
+    (let* ((vector-index (index->vector-index  index))
+           (vector-key nil))
+      (declare (fixnum vector-index))
+      (if (or (eq free-hash-marker
+                  (setq vector-key (%svref vector vector-index)))
+              (eq deleted-hash-key-marker vector-key))
+        (return-from %growhash-probe index)
+        (let ((second (%svref secondary-keys (%ilogand 7 hash-code))))
+          (declare (fixnum second))
+          (loop
+            (setq index (+ index second))
+            (when (>= index entries)
+              (setq index (- index entries)))
+            (when (or (eq free-hash-marker
+                          (setq vector-key (%svref vector (index->vector-index index))))
+                      (eq deleted-hash-key-marker vector-key))
+              (return-from %growhash-probe index))))))))
+
+;;;;;;;;;;;;;
+;;
+;; Mapping functions are in "ccl:lib;hash"
+;;
+
+
+
+;;;;;;;;;;;;;
+;;
+;; Hashing functions
+;; EQ & the EQ part of EQL are done in-line.
+;;
+
+
+
+
+
+
+
+
+
+;;; so whats so special about bit vectors as opposed to any other vectors of bytes
+;;; For starters, it's guaranteed that they exist in the implementation; that may
+;;; not be true of other immediate vector types.
+(defun bit-vector-hash (bv)
+  (declare (optimize (speed 3)(safety 0)))
+  (let ((length (length bv)))
+    (declare (fixnum length)) ;will this always be true? it's true of all vectors.
+    (multiple-value-bind (data offset) (array-data-and-offset bv)
+      (declare (type simple-bit-vector data) (fixnum offset))
+      (let* ((hash 0)
+             (limit (+ length offset))
+             (nbytes (ash (the fixnum (+ length 7)) -3)))
+        (declare (fixnum hash limit nbytes))
+        (dotimes (i nbytes (mixup-hash-code hash))
+          (let* ((w 0))
+            (declare (fixnum w))
+            (dotimes (j 8 (setq hash (+ (the fixnum (ash hash -3))  w)))
+              (setq w (the fixnum
+                        (logxor
+                         (the fixnum
+                           (ash (if (< offset limit) 
+                                  (the fixnum (sbit data offset))
+                                  0)
+                                (the fixnum j)))
+                         w)))
+              (incf offset))))))))
+
+#|
+(defun bit-vector-hash (bv)
+  (declare (optimize (speed 3)(safety 0)))
+  (let ((length (length bv)))
+    (declare (fixnum length))
+    (let* ((all (+ length 15))
+           (nwds (ash all -4))
+           (rem (logand all 15))
+           (hash 0)
+           (mask (ash (the fixnum (1- (the fixnum (expt 2 rem))))(the fixnum(- 16 rem)))))
+      (declare (fixnum all nwds rem hash mask))
+      (multiple-value-bind (data offset)
+                           (array-data-and-offset bv)
+        (declare (fixnum offset))
+        (locally (declare (type (simple-array (unsigned-byte 16) (*)) data))
+          (dotimes (i nwds)
+            (setq hash (%i+ hash (aref data (the fixnum (+ i offset))))))
+          (when (neq 0 mask)            
+            (setq hash (%i+ hash (%ilogand mask (aref data (the fixnum (+ offset nwds)))))))
+          (mixup-hash-code hash))))))
+|#
+
+
+;;; Same as %%equalhash, but different:
+;;;  1) Real numbers are hashed as if they were double-floats.  The real components of complex numbers
+;;;     are hashed as double-floats and XORed together.
+;;;  2) Characters and strings are hashed in a case-insensitive manner.
+;;;  3) Hash tables are hashed based on their size and type.
+;;;  4) Structures and CL array types are hashed based on their content.
+
+
+;;; check fixnum befor immediate-p. call %%eqlhash
+
+(defun %%equalphash (key)
+  (cond ((or (fixnump key)(short-float-p key))
+         (%dfloat-hash (float key 1.0d0))) 
+        ((immediate-p-macro key)
+         (mixup-hash-code (strip-tag-to-fixnum (if (characterp key)(char-upcase key) key))))
+        ((bignump key)
+         (if (<= most-negative-double-float key most-positive-double-float)
+           (%dfloat-hash (float key 1.0d0))  ; with-stack-double-floats
+           (%%eqlhash-internal key)))
+        ((double-float-p key)
+         (%dfloat-hash key))
+        ((ratiop key)
+         (%ilogxor (%%equalphash (numerator key)) (%%equalphash (denominator key))))
+        ((complexp key)
+         (%ilogxor (%%equalphash (realpart key)) (%%equalphash (imagpart key))))
+        ((hash-table-p key)
+         (equalphash-hash-table key))
+        ((or (istructp key)
+             (structurep key))  ; was (gvectorp key)
+         (%%equalphash-structure 11 key))
+        ((or (arrayp key)) ;(uvectorp key)) ;??
+         (%%equalphash-array 11 key))
+        ((consp key)
+         (%%equalphash-aux 11 key))
+        (t (%%eqlhash key))))
+
+
+(defun equalphash-hash-table (hash-table)
+  (let ((hash (%%equalhash "HASH-TABLE"))
+        addressp)
+    (declare (fixnum hash))
+    (incf hash (the fixnum (%%eqhash (hash-table-count hash-table))))
+    (multiple-value-bind (h ap) (%%eqhash (nhash.comparef hash-table))
+      (declare (fixnum h))
+      (incf hash h)
+      (if ap (setq addressp t)))
+    (multiple-value-bind (h ap) (%%eqhash (nhash.keytransF hash-table))
+      (declare (fixnum h))
+      (incf hash h)
+      (if ap (setq addressp t)))
+    (values hash addressp)))
+
+(defun %%equalphash-structure (limit key)
+  (let* ((size (uvsize key))
+         (hash (mixup-hash-code size))
+         addressp)
+    (declare (fixnum limit size hash))
+    (dotimes (i size)
+      (multiple-value-bind (h ap) (%%equalphash-aux limit (%svref key i))
+        (declare (fixnum h))
+        (setq hash (the fixnum (+ (the fixnum (rotate-hash-code hash)) h)))
+        (if ap (setq addressp t)))
+      (when (<= (decf limit) 0)
+        (setq hash (the fixnum (+ (the fixnum (rotate-hash-code hash))
+                                  (the fixnum (mixup-hash-code 11)))))
+        (return)))
+    (values hash addressp)))
+
+(defun %%equalphash-array (limit key)
+  (multiple-value-bind (array offset) (array-data-and-offset key)
+    (let* ((rank (array-rank key))
+           (vectorp (eql rank 1))
+           (size (if vectorp (length key) (array-total-size key)))
+           (hash (mixup-hash-code rank))
+           addressp)
+      (declare (fixnum size hash limit rank))
+      (if vectorp
+        (setq hash
+              (the fixnum
+                   (+ (the fixnum (rotate-hash-code hash))
+                      (the fixnum (mixup-hash-code size)))))
+        (dotimes (i rank)
+          (declare (fixnum i))
+          (setq hash
+                (the fixnum 
+                     (+ (the fixnum (rotate-hash-code hash))
+                        (the fixnum
+                             (mixup-hash-code (array-dimension key i))))))))      
+      (dotimes (i size)
+        (declare (fixnum i))
+        (multiple-value-bind (h ap) (%%equalphash-aux limit (uvref array offset))
+          (declare (fixnum h))
+          (setq hash (the fixnum (+ (the fixnum (rotate-hash-code hash)) h)))
+          (if ap (setq addressp t)))
+        (when (<= (decf limit) 0)
+          (setq hash (the fixnum (+ (the fixnum (rotate-hash-code hash))
+                                    (the fixnum (mixup-hash-code 11)))))
+          (return))
+        (incf offset))
+      (values hash addressp))))
+
+(defun %%equalphash-aux (limit key)
+  (if (<= limit 0) 
+    (mixup-hash-code 11)
+    (if (null key) (mixup-hash-code 17)
+        (cond ((consp key)
+               (let ((hash 0)
+                     address-p)
+                 (do ((l limit (1- l)))
+                     ((eq l 0)(values hash address-p))
+                   (multiple-value-bind (ahash ap)
+                                        (%%equalphash-aux l (if (consp key)(car key) key))
+                     (setq hash (mixup-hash-code (logxor ahash hash)))
+                     (if ap (setq address-p t)))
+                   (when (not (consp key))
+                     (return (values hash address-p)))
+                   (setq key (cdr key)))))
+              ((typep key 'hash-table)
+               (equalphash-hash-table key))
+              ; what are the dudes called that contain bits? they are uvectors but not gvectors?
+              ; ivectors.
+              ((or (istructp key)
+                   (structurep key))    ;was (gvectorp key)
+               (%%equalphash-structure limit key))
+              ((or (arrayp key))  ; (uvectorp key))
+               (%%equalphash-array limit key))
+              (t (%%equalphash key))))))
+
+(defun alist-hash-table (alist &rest hash-table-args)
+  (declare (dynamic-extent hash-table-args))
+  (if (typep alist 'hash-table)
+    alist
+    (let ((hash-table (apply #'make-hash-table hash-table-args)))
+      (dolist (cons alist) (puthash (car cons) hash-table (cdr cons)))
+      hash-table)))
+
+(defun %hash-table-equalp (x y)
+  ;; X and Y are both hash tables
+  (and (eq (hash-table-test x)
+           (hash-table-test y))
+       (eql (hash-table-count x)
+            (hash-table-count y))
+       (block nil
+         (let* ((default (cons nil nil))
+                (foo #'(lambda (k v)
+                         (let ((y-value (gethash k y default)))
+                           (unless (and (neq default y-value)
+                                        (equalp v y-value))
+                             (return nil))))))
+           (declare (dynamic-extent foo default))
+           (maphash foo x))
+         t)))
+
+(defun sxhash (s-expr)
+  "Computes a hash code for S-EXPR and returns it as an integer."
+  (logand (sxhash-aux s-expr 7 17) target::target-most-positive-fixnum))
+
+(defun sxhash-aux (expr counter key)
+  (declare (fixnum counter))
+  (if (> counter 0)
+    (typecase expr
+      ((or string bit-vector number character)  (+ key (%%equalhash expr)))
+      (logical-pathname
+       (dotimes (i (uvsize expr) key)
+         (declare (fixnum i))
+         (setq key (+ key (sxhash-aux (%svref expr i) (1- counter) key)))))
+      (pathname
+       ;; Don't consider %PHYSICAL-PATHNAME-VERSION to be significant
+       (dotimes (i (uvsize expr) key)
+         (declare (fixnum i))
+         (unless (= i %physical-pathname-version)
+           (setq key (+ key (sxhash-aux (%svref expr i) (1- counter) key))))))
+      (symbol (+ key (%%equalhash (symbol-name expr))))
+      (cons (sxhash-aux
+             (cdr expr)
+             (the fixnum (1- counter))             
+             (+ key (sxhash-aux (car expr) (the fixnum (1- counter)) key))))
+      (t (+  key (%%equalhash (symbol-name (%type-of expr))))))
+    key))
+
+
+
+#+(or ppc32-target x8632-target)
+(defun immediate-p (thing)
+  (let* ((tag (lisptag thing)))
+    (declare (fixnum tag))
+    (or (= tag target::tag-fixnum)
+        (= tag target::tag-imm))))
+
+#+ppc64-target
+(defun immediate-p (thing)
+  (let* ((tag (lisptag thing)))
+    (declare (fixnum tag))
+    (or (= tag ppc64::tag-fixnum)
+        (= (logand tag ppc64::lowtagmask) ppc64::lowtag-imm))))
+
+#+x8664-target
+(defun immediate-p (thing)
+  (let* ((tag (lisptag thing)))
+    (declare (type (unsigned-byte 3) tag))
+    (logbitp tag
+             (logior (ash 1 x8664::tag-fixnum)
+                     (ash 1 x8664::tag-imm-0)
+                     (ash 1 x8664::tag-imm-1)))))
+
+
+
+(defun %cons-nhash-vector (size &optional (flags 0))
+  (declare (fixnum size))
+  (let* ((vector (%alloc-misc (+ (+ size size) $nhash.vector_overhead) target::subtag-hash-vector free-hash-marker)))
+    (%init-nhash-vector vector flags)
+    vector))
+
+(defun %init-nhash-vector (vector flags)
+  (let ((size (vector-index->index (uvsize vector))))
+    (declare (fixnum size))
+    (setf (nhash.vector.link vector) 0
+          (nhash.vector.flags vector) flags
+          (nhash.vector.gc-count vector) (%get-gc-count)
+          (nhash.vector.free-alist vector) nil
+          (nhash.vector.finalization-alist vector) nil
+          (nhash.vector.weak-deletions-count vector) 0
+          (nhash.vector.hash vector) nil
+          (nhash.vector.deleted-count vector) 0
+          (nhash.vector.count vector) 0
+          (nhash.vector.cache-key vector) free-hash-marker
+          (nhash.vector.cache-value vector) nil
+          (nhash.vector.cache-idx vector) nil
+          (nhash.vector.size vector) size
+          (nhash.vector.size-reciprocal vector) (floor (ash 1 (- target::nbits-in-word target::fixnumshift)) size))))
+
+(defun assert-hash-table-readonly (hash)
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (or (nhash.read-only hash)
+      (when (nhash.owner hash)
+        (error "Hash~table ~s is thread-private and can't be made read-only for that reason" hash))
+      (if (hash-lock-free-p hash)
+        (setf (nhash.read-only hash) t)
+        (with-lock-context
+          (without-interrupts
+           (write-lock-hash-table hash)
+           (let* ((flags (nhash.vector.flags (nhash.vector hash))))
+             (declare (fixnum flags))
+             (when (or (logbitp $nhash_track_keys_bit flags)
+                       (logbitp $nhash_component_address_bit flags))
+               (format t "~&Hash-table ~s uses address-based hashing and can't yet be made read-only for that reason." hash)
+               (unlock-hash-table hash nil)
+               (return-from assert-hash-table-readonly nil))
+             (setf (nhash.read-only hash) t)
+             (unlock-hash-table hash nil)
+             t))))))
+
+;; This is dangerous, if multiple threads are accessing a read-only
+;; hash table. Use it responsibly.
+(defun assert-hash-table-writeable (hash)
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (when (nhash.read-only hash)
+    (setf (nhash.read-only hash) nil)
+    t))
+
+(defun readonly-hash-table-p (hash)
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (nhash.read-only hash))
+
+(defun hash-table-owner (hash)
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (nhash.owner hash))
+
+(defun claim-hash-table (hash &optional steal)
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (let* ((owner (nhash.owner hash)))
+    (if owner
+      (or (eq owner *current-process*)
+          (when steal
+            (setf (nhash.owner hash) *current-process*)))
+      (progn
+        (unless (hash-lock-free-p hash)
+          (write-lock-hash-table hash)
+          (setf (nhash.exclusion-lock hash) nil))
+        (setf (nhash.owner hash) *current-process*)
+        t))))
+
+  
+;; ** TODO: for lock-free hash tables, we don't need to copy,
+;; we could map over the actual hash table vector, because it's
+;; always valid.
+(defun lock-free-enumerate-hash-keys-and-values (hash keys values)
+  (do* ((in (nhash.vector hash))
+        (in-idx $nhash.vector_overhead (+ in-idx 2))
+        (insize (uvsize in))
+        (outsize (length (or keys values)))
+        (out-idx 0))
+       ((or (= in-idx insize)
+            (= out-idx outsize))
+        out-idx)
+    (declare (fixnum in-idx insize out-idx outsize))
+    (let* ((key (%svref in in-idx)))
+      (unless (eq key free-hash-marker)
+        (let ((val (%svref in (%i+ in-idx 1))))
+          (when (eq val rehashing-value-marker)
+            ;; This table is being rehashed.  Wait to finish and try again
+            (lock-free-rehash hash)
+            (return-from lock-free-enumerate-hash-keys-and-values
+                         (lock-free-enumerate-hash-keys-and-values hash keys values)))
+          (unless (eq val free-hash-marker)
+            (when (eql key deleted-hash-key-marker)
+              (error "Bug: deleted key but not value?"))
+            (when keys (setf (%svref keys out-idx) key))
+            (when values (setf (%svref values out-idx) val))
+            (incf out-idx)))))))
+
+(defun enumerate-hash-keys-and-values (hash keys values)
+  (unless (typep hash 'hash-table)
+    (report-bad-arg hash 'hash-table))
+  (when (hash-lock-free-p hash)
+    (return-from enumerate-hash-keys-and-values
+                 (lock-free-enumerate-hash-keys-and-values hash keys values)))
+  (with-lock-context
+    (without-interrupts
+     (let* ((readonly (eq (read-lock-hash-table hash) :readonly)))
+       (do* ((in (nhash.vector hash))
+             (in-idx $nhash.vector_overhead (+ in-idx 2))
+             (insize (uvsize in))
+             (outsize (length (or keys values)))
+             (out-idx 0))
+           ((or (= in-idx insize)
+                (= out-idx outsize))
+              (unlock-hash-table hash readonly)
+              out-idx)
+         (declare (fixnum in-idx insize out-idx outsize))
+         (let* ((key (%svref in in-idx)))
+           (unless (or (eq key free-hash-marker)
+                       (eq key deleted-hash-key-marker))
+             (when keys
+               (setf (%svref keys out-idx) key))
+             (when values
+               (setf (%svref values out-idx) (%svref in (%i+ in-idx 1))))
+             (incf out-idx))))))))
+
+(defun enumerate-hash-keys (hash out)
+  (enumerate-hash-keys-and-values hash out nil))
Index: /branches/new-random/level-0/l0-init.lisp
===================================================================
--- /branches/new-random/level-0/l0-init.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-init.lisp	(revision 13309)
@@ -0,0 +1,172 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defconstant array-total-size-limit
+  #.(expt 2 (- target::nbits-in-word target::num-subtag-bits))
+  "the exclusive upper bound on the total number of elements in an array")
+
+
+;Features for #+/- conditionalization:
+(defparameter *features*
+  '(:common-lisp
+    :openmcl
+    :ccl
+    :ccl-1.2
+    :ccl-1.3
+    :ccl-1.4
+    :clozure
+    :clozure-common-lisp
+    :ansi-cl
+    #-windows-target :unix
+    :openmcl-unicode-strings
+    ;; Threads and MOP stuff is pretty redundant.
+    :openmcl-native-threads
+    :openmcl-partial-mop
+    :mcl-common-mop-subset
+    :openmcl-mop-2
+    ;; Thread-private hash-tables were introduced in version 1.0
+    :openmcl-private-hash-tables
+    ;; Hash-consing support (special primitives for allocating
+    ;; and managing statically allocated CONS cells) will be
+    ;; added in 1.1
+    ;; Was dropped in 1.2
+    ;; :openmcl-hash-consing
+    #+eabi-target :eabi-target
+    #+ppc-target :powerpc
+    #+ppc-target :ppc-target
+    #+ppc-target :ppc-clos              ; used in encapsulate
+    #+ppc32-target :ppc32-target
+    #+ppc32-target :ppc32-host
+    #+ppc64-target :ppc64-target
+    #+ppc64-target :ppc64-host
+    #+x8632-target :x8632-target
+    #+x8632-target :x8632-host
+    #+x8664-target :x86-64
+    #+x8664-target :x86_64
+    #+x8632-target :x86
+    #+x86-target :x86-target
+    #+x86-target :x86-host
+    #+x8664-target :x8664-target
+    #+x8664-target :x8664-host
+    #+linux-target :linux-host
+    #+linux-target :linux-target
+    #+linuxppc-target :linuxppc-target
+    #+linuxppc-target :linuxppc-host
+    #+linuxx86-target :linuxx86-target
+    #+linuxx8664-target :linuxx8664-target
+    #+linuxx8664-target :linuxx8664-host
+    #+linuxx8632-target :linuxx8632-target
+    #+linuxx8632-target :linuxx8632-host
+    #+darwinppc-target :darwinppc-target
+    #+darwinppc-target :darwinppc-host
+    #+darwinppc-target :darwin-target
+    #+freebsd-target :freebsd-host
+    #+freebsd-target :freebsd-target
+    #+freebsdx86-target :freebsdx86-target
+    #+freebsdx8664-target :freebsdx8664-target
+    #+freebsdx8664-target :freebsdx8664-host
+    #+freebsdx8632-target :freebsdx8632-target
+    #+freebsdx8632-target :freebsdx8632-host
+    #+darwin-target :darwin-host
+    #+darwin-target :darwin-target
+    #+darwinx86-target :darwinx86-target
+    #+darwinx8632-target :darwinx8632-target
+    #+darwinx8632-target :darwinx8632-host
+    #+darwinx8664-target :darwinx8664-target
+    #+darwinx8664-target :darwinx8664-host
+    #+windows-target :windows-host
+    #+windows-target :windows-target
+    #+win64-target :win64-target
+    #+win64-target :win64-host
+    #+win32-target :win32-target
+    #+win32-target :win32-host
+    #+solaris-target :solaris-host
+    #+solaris-target :solaris-target
+    #+solarisx86-target :solarisx86-target
+    #+solarisx8664-target :solarisx8664-target
+    #+solarisx8664-target :solarisx8664-host
+    #+solarisx8632-target :solarisx8632-target
+    #+solarisx8632-target :solarisx8632-host
+    #+(and ppc-target poweropen-target) :poweropen-target
+    #+64-bit-target :64-bit-target
+    #+64-bit-target :64-bit-host
+    #+32-bit-target :32-bit-target
+    #+32-bit-target :32-bit-host
+    #+ppc-target :big-endian-target
+    #+ppc-target :big-endian-host
+    #+x86-target :little-endian-target
+    #+x86-target :little-endian-host
+    #+darwin-target :darwin
+    #+linux-target :linux
+    #+freebsd-target :freebsd
+    #+solaris-target :solaris
+    #+windows-target :windows
+    )
+  "a list of symbols that describe features provided by the
+   implementation")
+
+(defparameter *optional-features* () "Set by build process")
+
+(defparameter *load-verbose* nil
+  "the default for the :VERBOSE argument to LOAD")
+
+;All Lisp package variables... Dunno if this still matters, but it
+;used to happen in the kernel...
+(dolist (x '(* ** *** *APPLYHOOK* *DEBUG-IO*
+             *DEFAULT-PATHNAME-DEFAULTS* *ERROR-OUTPUT* *EVALHOOK*
+             *FEATURES* *LOAD-VERBOSE* *MACROEXPAND-HOOK* *MODULES*
+             *PACKAGE* *PRINT-ARRAY* *PRINT-BASE* *PRINT-CASE* *PRINT-CIRCLE*
+             *PRINT-ESCAPE* *PRINT-GENSYM* *PRINT-LENGTH* *PRINT-LEVEL*
+             *PRINT-PRETTY* *PRINT-RADIX* *QUERY-IO* *RANDOM-STATE* *READ-BASE*
+             *READ-DEFAULT-FLOAT-FORMAT* *READ-SUPPRESS* *READTABLE*
+             *STANDARD-INPUT* *STANDARD-OUTPUT* *TERMINAL-IO* *TRACE-OUTPUT*
+             + ++ +++ - / // /// ARRAY-DIMENSION-LIMIT ARRAY-RANK-LIMIT
+             ARRAY-TOTAL-SIZE-LIMIT BOOLE-1 BOOLE-2 BOOLE-AND BOOLE-ANDC1
+             BOOLE-ANDC2 BOOLE-C1 BOOLE-C2 BOOLE-CLR BOOLE-EQV BOOLE-IOR
+             BOOLE-NAND BOOLE-NOR BOOLE-ORC1 BOOLE-ORC2 BOOLE-SET BOOLE-XOR
+             CALL-ARGUMENTS-LIMIT CHAR-CODE-LIMIT
+             DOUBLE-FLOAT-EPSILON DOUBLE-FLOAT-NEGATIVE-EPSILON
+             INTERNAL-TIME-UNITS-PER-SECOND LAMBDA-LIST-KEYWORDS
+             LAMBDA-PARAMETERS-LIMIT LEAST-NEGATIVE-DOUBLE-FLOAT
+             LEAST-NEGATIVE-LONG-FLOAT LEAST-NEGATIVE-SHORT-FLOAT
+             LEAST-NEGATIVE-SINGLE-FLOAT LEAST-POSITIVE-DOUBLE-FLOAT
+             LEAST-POSITIVE-LONG-FLOAT LEAST-POSITIVE-SHORT-FLOAT
+             LEAST-POSITIVE-SINGLE-FLOAT LONG-FLOAT-EPSILON
+             LONG-FLOAT-NEGATIVE-EPSILON MOST-NEGATIVE-DOUBLE-FLOAT
+             MOST-NEGATIVE-FIXNUM MOST-NEGATIVE-LONG-FLOAT
+             MOST-NEGATIVE-SHORT-FLOAT MOST-NEGATIVE-SINGLE-FLOAT
+             MOST-POSITIVE-DOUBLE-FLOAT MOST-POSITIVE-FIXNUM
+             MOST-POSITIVE-LONG-FLOAT MOST-POSITIVE-SHORT-FLOAT
+             MOST-POSITIVE-SINGLE-FLOAT MULTIPLE-VALUES-LIMIT PI
+             SHORT-FLOAT-EPSILON SHORT-FLOAT-NEGATIVE-EPSILON
+             SINGLE-FLOAT-EPSILON SINGLE-FLOAT-NEGATIVE-EPSILON))
+  (%symbol-bits x (%ilogior2 (%symbol-bits x) (ash 1 $sym_bit_special))))
+
+(defparameter *loading-file-source-file* nil)
+(defparameter *loading-toplevel-location* nil)
+
+(defvar *nx-speed* 1)
+(defvar *nx-space* 1)
+(defvar *nx-safety* 1)
+(defvar *nx-cspeed* 1)
+(defvar *nx-debug* 1)
+
+(defparameter *case-sensitive-filesystem* t)
+
+;;; end
Index: /branches/new-random/level-0/l0-int.lisp
===================================================================
--- /branches/new-random/level-0/l0-int.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-int.lisp	(revision 13309)
@@ -0,0 +1,189 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS")
+  (require "NUMBER-CASE-MACRO")
+)
+
+
+(defun lsh (fixnum count)
+  (require-type fixnum 'fixnum)
+  (require-type count 'fixnum)
+  (if (> count 0) 
+    (%ilsl count fixnum)
+    (%ilsr (- count) fixnum)))
+
+; this called with fixnum
+(defun %iabs  (n)
+  (declare (fixnum n))
+  (if (minusp  n) (- n) n))
+
+; called with any integer - is there a cmu version of integer/bignum-abs?
+(defun %integer-abs (n)
+  (number-case n
+    (fixnum
+     (locally
+	 (declare (fixnum n))
+       (if (minusp n) (- n) n)))
+    (bignum
+     (if (minusp n) (- n) n))))
+
+
+(eval-when (:compile-toplevel :execute)
+  (assert (< (char-code #\9) (char-code #\A) (char-code #\a))))
+
+(defun token2int (string start len radix)
+  ; simple minded in case you hadn't noticed
+  (let* ((n start)
+         (end (+ start len))
+         (char0 (schar string n))
+         (val 0)
+         minus)
+    (declare (fixnum n end start len radix)) ; as if it mattered
+    (when (or (eq char0 #\+)(eq char0 #\-))
+      (setq n (1+ n))
+      (if (eq char0 #\-)(setq minus t)))
+    (while (< n end)
+      (let ((code (%scharcode string n)))
+        (if (<= code (char-code #\9)) 
+          (setq code (- code (char-code #\0)))
+          (progn
+            (when (>= code (char-code #\a))
+              (setq code (- code (- (char-code #\a) (char-code #\A)))))
+            (setq code (- code (- (char-code #\A) 10)))))
+        (setq val (+ (* val radix) code))
+        (setq n (1+ n))))
+    (if minus (- val) val)))
+  
+
+(defun %integer-to-string (int &optional (radix 10))
+  (%pr-integer int radix nil t))
+
+
+;;; it may be hard to believe, but this is much faster than the lap
+;;; version (3 or 4X) for fixnums that is (stream-write-string vs
+;;; stream-tyo ???)
+
+(defun %pr-integer (int &optional (radix 10) (stream *standard-output*) return-it  negate-it)
+  (declare (fixnum radix)) ; assume caller has checked
+  (if stream 
+    (if (eq stream t) (setq stream *terminal-io*))
+    (setq stream *standard-output*))
+  (let ((digit-string "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"))    
+    (cond ((fixnump int)  ; ugh                      
+           (let ((temstring (make-string (- target::nbits-in-word target::fixnumshift) :element-type 'base-char))
+                 (i (- target::nbits-in-word  target::fixnumshift 1))
+                 (neg (< int 0))
+                 (rem 0))
+             (declare (fixnum i rem))
+             (declare (dynamic-extent temstring))
+             (when neg (setq int (- int)))
+             (when (not (fixnump int))
+               (return-from %pr-integer (%pr-integer int radix stream return-it t)))
+             (locally (declare (fixnum int))  
+               (loop
+                 (multiple-value-setq  (int rem) (%fixnum-truncate int radix))                 
+                 (setf (%schar temstring i)(%schar digit-string rem))
+                 (when (eq 0 int)
+                   (return))
+                 (setq i (1- i)))
+               (when neg 
+                 (setf (%schar temstring (setq i (1- i))) #\-))
+               (if return-it
+                 (%substr temstring i (- target::nbits-in-word
+                                         target::fixnumshift))
+                 (write-string temstring stream :start i :end (- target::nbits-in-word target::fixnumshift))))))          
+          (t (let* ((size-vect #(nil nil 32 21 16 14 13 12 11
+                                 11   10 10  9  9  9  9  8  8
+                                 8     8  8  8  8  8  7  7  7
+                                 7     7  7  7  7  7  7  7  7 7))
+                    ;; overestimate # digits by a little for weird
+                    ;; radix
+                    (bigwords (uvsize int))
+                    (strlen (1+ (* bigwords (svref size-vect radix))))
+                    (temstring (make-string strlen :element-type 'base-char))
+                    (i (1- strlen))
+                    (neg (< int 0))
+                    ; ;(rem 0)
+                    ;; ;better-bignum-print?
+                    )  ; warn
+               (declare (dynamic-extent temstring)
+                        (fixnum i strlen))
+               (flet ((do-it (newbig)
+                        (print-bignum-2 newbig radix temstring digit-string)))
+                 (declare (dynamic-extent #'do-it))
+                 (setq i (with-one-negated-bignum-buffer int do-it)))                            
+               (when (or neg negate-it) 
+                 (setf (%schar temstring (setq i (1- i))) #\-))
+               (if return-it
+                 (%substr temstring i strlen)
+                 (write-string temstring stream :start i :end strlen)))))))
+
+
+
+;;; *BASE-POWER* holds the number that we keep dividing into the bignum for
+;;; each *print-base*.  We want this number as close to *most-positive-fixnum*
+;;; as possible, i.e. (floor (log most-positive-fixnum *print-base*)).
+;;; 
+(defparameter *base-power* ())
+
+;;; *FIXNUM-POWER--1* holds the number of digits for each *print-base* that
+;;; fit in the corresponding *base-power*.
+;;; 
+(defparameter *fixnum-power--1* ())
+
+(do* ((b (make-array 37 :initial-element nil))
+      (f (make-array 37 :initial-element nil))
+      (base 2 (1+ base)))
+     ((= base 37) (setq *base-power* b *fixnum-power--1* f))
+  (do ((power-1 -1 (1+ power-1))
+       (new-divisor base (* new-divisor base))
+       (divisor 1 new-divisor))
+      ((not (fixnump new-divisor))
+       (setf (aref b base) divisor)
+       (setf (aref f base) power-1))))
+
+
+(defun print-bignum-2 (big radix string digit-string)
+  (declare (optimize (speed 3) (safety 0))
+           (simple-base-string string digit-string))
+  (let* ((divisor (aref *base-power* radix))
+         (power (aref *fixnum-power--1* radix))
+         (index (1- (length string)))
+         (rem 0))
+    (declare (fixnum index divisor power))
+    ;;(print index)
+    (loop
+      (multiple-value-setq (big rem) (truncate big divisor))
+      (let* ((int rem)
+             (rem 0)
+             (final-index (- index power 1)))
+        (loop
+          (multiple-value-setq (int rem) (%fixnum-truncate int radix))
+          (setf (schar string index)(schar digit-string rem))
+          (when (eql 0 int)
+            (return index))
+          (setq index (1- index)))
+        (if (zerop big)
+          (return index)
+          (dotimes (i (- index final-index) index)
+            (declare (fixnum i))
+            (setq index (1- index))
+            (setf (schar string index) #\0)))))))
Index: /branches/new-random/level-0/l0-io.lisp
===================================================================
--- /branches/new-random/level-0/l0-io.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-io.lisp	(revision 13309)
@@ -0,0 +1,316 @@
+; -*- Mode: Lisp; Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+
+
+(defun utf-8-octets-in-string (string start end)
+  (if (>= end start)
+    (do* ((noctets 0)
+          (i start (1+ i)))
+         ((= i end) noctets)
+      (declare (fixnum noctets))
+      (let* ((code (char-code (schar string i))))
+        (declare (type (mod #x110000) code))
+        (incf noctets
+              (if (< code #x80)
+                1
+                (if (< code #x800)
+                  2
+                  (if (< code #x10000)
+                    3
+                    4))))))
+    0))
+
+(defun utf-16-octets-in-string (string start end)
+  (if (>= end start)
+    (do* ((noctets 0)
+          (i start (1+ i)))
+         ((= i end) noctets)
+      (declare (fixnum noctets))
+      (let* ((code (char-code (schar string i))))
+        (declare (type (mod #x110000) code))
+        (incf noctets
+              (if (< code #x10000)
+                2
+                4))))
+    0))
+
+(defun utf-8-memory-encode (string pointer idx start end)
+  (declare (fixnum idx))
+  (do* ((i start (1+ i)))
+       ((>= i end) idx)
+    (let* ((code (char-code (schar string i))))
+      (declare (type (mod #x110000) code))
+      (cond ((< code #x80)
+             (setf (%get-unsigned-byte pointer idx) code)
+             (incf idx))
+            ((< code #x800)
+             (setf (%get-unsigned-byte pointer idx)
+                   (logior #xc0 (the fixnum (ash code -6))))
+             (setf (%get-unsigned-byte pointer (the fixnum (1+ idx)))
+                   (logior #x80 (the fixnum (logand code #x3f))))
+             (incf idx 2))
+            ((< code #x10000)
+             (setf (%get-unsigned-byte pointer idx)
+                   (logior #xe0 (the fixnum (ash code -12))))
+             (setf (%get-unsigned-byte pointer (the fixnum (1+ idx)))
+                   (logior #x80 (the fixnum (logand #x3f (the fixnum (ash code -6))))))
+             (setf (%get-unsigned-byte pointer (the fixnum (+ idx 2)))
+                   (logior #x80 (the fixnum (logand code #x3f))))
+             (incf idx 3))
+            (t
+             (setf (%get-unsigned-byte pointer idx)
+                   (logior #xf0
+                           (the fixnum (logand #x7 (the fixnum (ash code -18))))))
+             (setf (%get-unsigned-byte pointer (the fixnum (1+ idx)))
+                   (logior #x80 (the fixnum (logand #x3f (the fixnum (ash code -12))))))
+             (setf (%get-unsigned-byte pointer (the fixnum (+ idx 2)))
+                   (logior #x80 (the fixnum (logand #x3f (the fixnum (ash code -6))))))
+             (setf (%get-unsigned-byte pointer (the fixnum (+ idx 3)))
+                   (logior #x80 (logand #x3f code)))
+             (incf idx 4))))))
+
+(defun native-utf-16-memory-encode (string pointer idx start end)
+  (declare (fixnum idx))
+  (do* ((i start (1+ i)))
+       ((>= i end) idx)
+    (let* ((code (char-code (schar string i)))
+           (highbits (- code #x10000)))
+      (declare (type (mod #x110000) code)
+               (fixnum  highbits))
+      (cond ((< highbits 0)
+             (setf (%get-unsigned-word pointer idx) code)
+             (incf idx 2))
+            (t
+             (setf (%get-unsigned-word pointer idx) (logior #xd800 (the fixnum (ash highbits -10))))
+             (incf idx 2)
+             (setf (%get-unsigned-word pointer idx) (logior #xdc00 (the fixnum (logand highbits #x3ff))))
+             (incf idx 2))))))
+
+(defun utf-8-memory-decode (pointer noctets idx string)
+  (declare (fixnum noctets idx))
+  (do* ((i 0 (1+ i))
+        (end (+ idx noctets))
+        (index idx (1+ index)))
+       ((>= index end) (if (= index end) index 0))
+    (let* ((1st-unit (%get-unsigned-byte pointer index)))
+      (declare (type (unsigned-byte 8) 1st-unit))
+      (let* ((char (if (< 1st-unit #x80)
+                     (code-char 1st-unit)
+                     (if (>= 1st-unit #xc2)
+                       (let* ((2nd-unit (%get-unsigned-byte pointer (incf index))))
+                         (declare (type (unsigned-byte 8) 2nd-unit))
+                         (if (< 1st-unit #xe0)
+                           (if (< (the fixnum (logxor 2nd-unit #x80)) #x40)
+                             (code-char
+                              (logior
+                               (the fixnum (ash (the fixnum (logand #x1f 1st-unit)) 6))
+                               (the fixnum (logxor 2nd-unit #x80)))))
+                           (let* ((3rd-unit (%get-unsigned-byte pointer (incf index))))
+                             (declare (type (unsigned-byte 8) 3rd-unit))
+                             (if (< 1st-unit #xf0)
+                               (if (and (< (the fixnum (logxor 2nd-unit #x80)) #x40)
+                                        (< (the fixnum (logxor 3rd-unit #x80)) #x40)
+                                        (or (>= 1st-unit #xe1)
+                                            (>= 2nd-unit #xa0)))
+                                 (code-char (the fixnum
+                                              (logior (the fixnum
+                                                        (ash (the fixnum (logand 1st-unit #xf))
+                                                             12))
+                                                      (the fixnum
+                                                        (logior
+                                                         (the fixnum
+                                                           (ash (the fixnum (logand 2nd-unit #x3f))
+                                                                6))
+                                                         (the fixnum (logand 3rd-unit #x3f))))))))
+                               (if (< 1st-unit #xf8)
+                                 (let* ((4th-unit (%get-unsigned-byte pointer (incf index))))
+                                   (declare (type (unsigned-byte 8) 4th-unit))
+                                   (if (and (< (the fixnum (logxor 2nd-unit #x80)) #x40)
+                                            (< (the fixnum (logxor 3rd-unit #x80)) #x40)
+                                            (< (the fixnum (logxor 4th-unit #x80)) #x40)
+                                            (or (>= 1st-unit #xf1)
+                                                (>= 2nd-unit #x90)))
+                                     (code-char
+                                      (logior
+                                       (the fixnum
+                                         (logior
+                                          (the fixnum
+                                            (ash (the fixnum (logand 1st-unit 7)) 18))
+                                          (the fixnum
+                                            (ash (the fixnum (logxor 2nd-unit #x80)) 12))))
+                                       (the fixnum
+                                         (logior
+                                          (the fixnum
+                                            (ash (the fixnum (logxor 3rd-unit #x80)) 6))
+                                          (the fixnum (logxor 4th-unit #x80)))))))))))))))))
+        (setf (schar string i) (or char #\Replacement_Character))))))
+
+(defun utf-8-length-of-memory-encoding (pointer noctets start)
+  (do* ((i start)
+        (end (+ start noctets))
+        (nchars 0 (1+ nchars)))
+       ((= i end) (values nchars (- i start)))
+    (let* ((code (%get-unsigned-byte pointer i))
+           (nexti (+ i (cond ((< code #xc2) 1)
+                             ((< code #xe0) 2)
+                             ((< code #xf0) 3)
+                             ((< code #xf8) 4)
+                             (t 1)))))
+      (declare (type (unsigned-byte 8) code))
+      (if (> nexti end)
+        (return (values nchars (- i start)))
+        (setq i nexti)))))
+
+
+
+;;; write nbytes bytes from buffer buf to file-descriptor fd.
+(defun fd-write (fd buf nbytes)
+  (ignoring-eintr
+   (int-errno-ffcall
+    (%kernel-import target::kernel-import-lisp-write)
+             :int fd :address buf :ssize_t nbytes :ssize_t)))
+
+(defun fd-read (fd buf nbytes)
+  (ignoring-eintr
+   (int-errno-ffcall
+    (%kernel-import target::kernel-import-lisp-read)
+             :int fd :address buf :ssize_t nbytes :ssize_t)))
+
+
+(let* ((pathname-encoding-name ()))
+  (declare (ignorable pathname-encoding-name))
+  (defun pathname-encoding-name ()
+    #+darwin-target :utf-8
+    #+windows-target :utf-16le
+    #-(or darwin-target windows-target) pathname-encoding-name)
+  (defun set-pathname-encoding-name (new)
+    #+(or darwin-target windows-target) (declare (ignore new))
+    #+darwin-target :utf-8
+    #+windows-target :utf-16le
+    #-(or darwin-target windows-target)
+    (let* ((encoding (ensure-character-encoding new)))
+      (setq pathname-encoding-name
+            (unless (eq encoding (get-character-encoding nil))
+              (character-encoding-name encoding))))))
+
+
+(defun fd-open-path (p flags create-mode)
+  (let* ((fd (int-errno-ffcall
+              (%kernel-import target::kernel-import-lisp-open)
+              :address p :int flags :mode_t create-mode :int)))
+    (declare (fixnum fd))
+    (when (or (= fd (- #$EMFILE))
+              (= fd (- #$ENFILE)))
+      (gc)
+      (drain-termination-queue)
+      (setq fd (int-errno-ffcall
+                (%kernel-import target::kernel-import-lisp-open)
+                :address p :int flags :mode_t create-mode :int)))
+    fd))
+
+(defun fd-open (path flags &optional (create-mode #o666))
+  #+darwin-target (with-utf-8-cstrs ((p path))
+                    (fd-open-path p flags create-mode))
+  #+windows-target (with-native-utf-16-cstrs ((p path))
+                     (fd-open-path p flags create-mode))
+  #-(or darwin-target windows-target)
+  (let* ((encoding (pathname-encoding-name)))
+    (if encoding
+      (with-encoded-cstrs encoding ((p path))
+        (fd-open-path p flags create-mode))
+      (with-cstrs ((p path))
+        (fd-open-path p flags create-mode)))))
+
+(defun fd-chmod (fd mode)
+  (int-errno-ffcall (%kernel-import target::kernel-import-lisp-fchmod)
+                    :int fd
+                    :mode_t mode
+                    :int))
+
+(defun fd-lseek (fd offset whence)
+  (int-errno-ffcall
+   (%kernel-import target::kernel-import-lisp-lseek)
+   :int fd
+   :signed-doubleword offset
+   :int whence
+   :signed-doubleword))
+
+(defun fd-close (fd)
+  (int-errno-ffcall (%kernel-import target::kernel-import-lisp-close)
+                    :int fd
+                    :int)) 
+
+(defun fd-tell (fd)
+  (fd-lseek fd 0 #$SEEK_CUR))
+
+;;; Kernels prior to 2.4 don't seem to have a "stat" variant
+;;; that handles 64-bit file offsets.
+(defun fd-size (fd)
+  (rlet ((stat #+win64-target #>_stat64 #+win32-target #>__stat64 #-windows-target :stat))
+    (if (eql 0 (ff-call (%kernel-import target::kernel-import-lisp-fstat)
+                        :int fd
+                        :address stat
+                        :int))
+      (pref stat
+            #-windows-target :stat.st_size
+            #+win64-target #>_stat64.st_size
+            #+win32-target #>__stat64.st_size)
+      -1)))
+
+
+(defun fd-ftruncate (fd new)
+  (int-errno-ffcall (%kernel-import target::kernel-import-lisp-ftruncate)
+                    :int fd :off_t new :int))
+
+(defun %string-to-stderr (str)
+  (with-cstrs ((s str))
+    (fd-write 2 s (length str))))
+
+(defun pdbg (string)
+  (%string-to-stderr string)
+  (%string-to-stderr #.(string #\LineFeed)))
+
+
+
+;;; Not really I/O, but ...
+(defun malloc (size)
+  (ff-call 
+   (%kernel-import target::kernel-import-malloc)
+   :unsigned-fullword size :address))
+
+(defun free (ptr)
+  (let* ((size (uvsize ptr))
+         (flags (if (= size target::xmacptr.size)
+                  (uvref ptr target::xmacptr.flags-cell)
+                  $flags_DisposPtr)))
+    (declare (fixnum size flags))
+    (if (= flags $flags_DisposPtr)
+      (with-macptrs ((addr ptr))
+        (when (= size target::xmacptr.size)
+          (%setf-macptr ptr (%null-ptr))
+          (setf (uvref ptr target::xmacptr.flags-cell) $flags_Normal))
+        (ff-call 
+         (%kernel-import target::kernel-import-free)
+         :address addr :void)))))
+
+
+
+
Index: /branches/new-random/level-0/l0-misc.lisp
===================================================================
--- /branches/new-random/level-0/l0-misc.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-misc.lisp	(revision 13309)
@@ -0,0 +1,1142 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+;;; Bootstrapping for futexes
+#+(and linux-target x86-target)
+(eval-when (:compile-toplevel :execute)
+  (pushnew :futex *features*))
+
+#+futex
+(eval-when (:compile-toplevel :execute)
+  ;; We only need a few constants from <linux/futex.h>, which may
+  ;; not have been included in the :libc .cdb files.
+  (defconstant FUTEX-WAIT 0)
+  (defconstant FUTEX-WAKE 1)
+  (defconstant futex-avail 0)
+  (defconstant futex-locked 1)
+  (defconstant futex-contended 2)
+  (declaim (inline %lock-futex %unlock-futex)))
+
+;;; Miscellany.
+
+(defun memq (item list)
+  (do* ((tail list (%cdr tail)))
+       ((null tail))
+    (if (eq item (car tail))
+      (return tail))))
+
+(defun %copy-u8-to-string (u8-vector source-idx string dest-idx n)
+  (declare (optimize (speed 3) (safety 0))
+           (fixnum source-idx dest-idx n)
+           (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (simple-base-string string))
+  (do* ((i 0 (1+ i)))
+       ((= i n) string)
+    (declare (fixnum i))
+    (setf (%scharcode string dest-idx) (aref u8-vector source-idx))
+    (incf source-idx)
+    (incf dest-idx)))
+
+(defun %copy-string-to-u8 (string source-idx u8-vector dest-idx n)
+  (declare (optimize (speed 3) (safety 0))
+           (fixnum source-idx dest-idx n)
+           (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (simple-base-string string))
+  (do* ((i 0 (1+ i)))
+       ((= i n) u8-vector)
+    (declare (fixnum i))
+    (let* ((code (%scharcode string source-idx)))
+      (declare (type (mod #x11000) code))
+      (if (> code #xff)
+        (setq code (char-code #\Sub)))
+      (setf (aref u8-vector dest-idx) code)
+      (incf source-idx)
+      (incf dest-idx))))
+    
+        
+
+
+(defun append-2 (y z)
+  (if (null y)
+    z
+    (let* ((new (cons (car y) nil))
+           (tail new))
+      (declare (list new tail))
+      (dolist (head (cdr y))
+        (setq tail (cdr (rplacd tail (cons head nil)))))
+      (rplacd tail z)
+      new)))
+
+
+
+
+
+
+
+
+
+(defun dbg (&optional arg)
+  (dbg arg))
+
+
+; This takes a simple-base-string and passes a C string into
+; the kernel "Bug" routine.  Not too fancy, but neither is #_DebugStr,
+; and there's a better chance that users would see this message.
+(defun bug (arg)
+  (if (typep arg 'simple-base-string)
+    #+x86-target
+    (debug-trap-with-string arg)
+    #-x86-target
+    (let* ((len (length arg)))
+      (%stack-block ((buf (1+ len)))
+        (%cstr-pointer arg buf)
+        (ff-call 
+         (%kernel-import target::kernel-import-lisp-bug)
+         :address buf
+         :void)))
+    (bug "Bug called with non-simple-base-string.")))
+
+(defun total-bytes-allocated ()
+  (%heap-bytes-allocated)
+  #+not-any-more
+  (+ (unsignedwide->integer *total-bytes-freed*)
+     (%heap-bytes-allocated)))
+
+(defun %freebytes ()
+  (with-macptrs (p)
+    (%setf-macptr-to-object p
+                            (%fixnum-ref (%get-kernel-global 'all-areas)
+                                         target::area.succ))
+    (- (%get-natural p target::area.high)
+       (%get-natural p target::area.active))))
+
+(defun %reservedbytes ()
+  (with-macptrs (p)
+    (%setf-macptr-to-object p (%get-kernel-global 'all-areas))
+    (- #+32-bit-target
+       (%get-unsigned-long p target::area.high)
+       #+64-bit-target
+       (%%get-unsigned-longlong p target::area.high)
+       #+32-bit-target
+       (%get-unsigned-long p target::area.low)
+       #+64-bit-target
+       (%%get-unsigned-longlong p target::area.low))))
+
+(defun object-in-application-heap-p (address)
+  (declare (ignore address))
+  t)
+
+(defun frozen-space-dnodes ()
+  "Returns the current size of the frozen area."
+  (%fixnum-ref-natural (%get-kernel-global 'tenured-area)
+                       target::area.static-dnodes))
+(defun %usedbytes ()
+  (with-lock-grabbed (*kernel-exception-lock*)
+    (with-lock-grabbed (*kernel-tcr-area-lock*)
+      (%normalize-areas)
+      (let ((static 0)
+            (dynamic 0)
+            (library 0))
+        (do-consing-areas (area)
+          (let* ((active (%fixnum-ref area target::area.active))
+                 (bytes (ash (- active
+                                (%fixnum-ref area target::area.low))
+                             target::fixnumshift))
+                 (code (%fixnum-ref area target::area.code)))
+            (when (object-in-application-heap-p active)
+              (if (eql code area-dynamic)
+                (incf dynamic bytes)
+                (if (eql code area-managed-static)
+                  (incf library bytes)
+                  (incf static bytes))))))
+        (let* ((frozen-size (ash (frozen-space-dnodes) target::dnode-shift)))
+          (decf dynamic frozen-size)
+          (values dynamic static library frozen-size))))))
+
+
+
+(defun %stack-space ()
+  (%normalize-areas)
+  (let ((free 0)
+        (used 0))
+    (with-macptrs (p)
+      (do-gc-areas (area)
+	(when (member (%fixnum-ref area target::area.code)
+		      '(#.area-vstack
+			#.area-cstack
+                      #.area-tstack))
+	  (%setf-macptr-to-object p area)
+	  (let ((active
+                 #+32-bit-target
+                  (%get-unsigned-long p target::area.active)
+                  #+64-bit-target
+                  (%%get-unsigned-longlong p target::area.active))
+		(high
+                 #+32-bit-target
+                  (%get-unsigned-long p target::area.high)
+                  #+64-bit-target
+                  (%%get-unsigned-longlong p target::area.high))
+		(low
+                 #+32-bit-target
+                 (%get-unsigned-long p target::area.low)
+                 #+64-bit-target
+                 (%%get-unsigned-longlong p target::area.low)))
+	    (incf used (- high active))
+	    (incf free (- active low))))))
+    (values (+ free used) used free)))
+
+
+
+; Returns an alist of the form:
+; ((thread cstack-free cstack-used vstack-free vstack-used tstack-free tstack-used)
+;  ...)
+(defun %stack-space-by-lisp-thread ()
+  (let* ((res nil))
+    (without-interrupts
+     (dolist (p (all-processes))
+       (let* ((thread (process-thread p)))
+         (when thread
+           (push (cons thread (multiple-value-list (%thread-stack-space thread))) res)))))
+    res))
+
+
+
+;;; Returns six values.
+;;;   sp free
+;;;   sp used
+;;;   vsp free
+;;;   vsp used
+;;;   tsp free
+;;;   tsp used
+(defun %thread-stack-space (&optional (thread *current-lisp-thread*))
+  (when (eq thread *current-lisp-thread*)
+    (%normalize-areas))
+  (labels ((free-and-used (area)
+	     (with-macptrs (p)
+	       (%setf-macptr-to-object p area)
+	       (let* ((low
+                       #+32-bit-target
+                       (%get-unsigned-long p target::area.low)
+                       #+64-bit-target
+                       (%%get-unsigned-longlong p target::area.low))
+		      (high
+                       #+32-bit-target
+                        (%get-unsigned-long p target::area.high)
+                        #+64-bit-target
+                        (%%get-unsigned-longlong p target::area.high))
+		      (active
+                       #+32-bit-target
+                       (%get-unsigned-long p target::area.active)
+                       #+64-bit-target
+                       (%%get-unsigned-longlong p target::area.active))
+		      (free (- active low))
+		      (used (- high active)))
+		 (loop
+		     (setq area (%fixnum-ref area target::area.older))
+		     (when (eql area 0) (return))
+		   (%setf-macptr-to-object p area)
+		   (let ((low
+                          #+32-bit-target
+                           (%get-unsigned-long p target::area.low)
+                           #+64-bit-target
+                           (%%get-unsigned-longlong p target::area.low))
+			 (high
+                          #+32-bit-target
+                           (%get-unsigned-long p target::area.high)
+                           #+64-bit-target
+                           (%%get-unsigned-longlong p target::area.high)))
+		     (declare (fixnum low high))
+		     (incf used (- high low))))
+		 (values free used)))))
+    (let* ((tcr (lisp-thread.tcr thread)))
+      (if (or (null tcr)
+	      (zerop (%fixnum-ref (%fixnum-ref tcr target::tcr.cs-area))))
+	(values 0 0 0 0 0 0)
+	(multiple-value-bind (cf cu) (free-and-used (%fixnum-ref tcr target::tcr.cs-area))
+	  (multiple-value-bind (vf vu) (free-and-used (%fixnum-ref tcr target::tcr.vs-area))
+	    (multiple-value-bind (tf tu) (free-and-used (%fixnum-ref tcr target::tcr.ts-area ))
+	      (values cf cu vf vu tf tu))))))))
+
+
+(defun room (&optional (verbose :default))
+  "Print to *STANDARD-OUTPUT* information about the state of internal
+  storage and its management. The optional argument controls the
+  verbosity of output. If it is T, ROOM prints out a maximal amount of
+  information. If it is NIL, ROOM prints out a minimal amount of
+  information. If it is :DEFAULT or it is not supplied, ROOM prints out
+  an intermediate amount of information."
+  (let* ((freebytes nil)
+         (usedbytes nil)
+         (static-used nil)
+         (staticlib-used nil)
+         (frozen-space-size nil)
+         (lispheap nil)
+         (reserved nil)
+         (static nil)
+         (stack-total)
+         (stack-used)
+         (stack-free)
+         (static-cons-reserved nil)
+         (stack-used-by-thread nil))
+    (progn
+      (progn
+        (setq freebytes (%freebytes))
+        (when verbose
+          (multiple-value-setq (usedbytes static-used staticlib-used frozen-space-size)
+            (%usedbytes))
+          (setq lispheap (+ freebytes usedbytes)
+                reserved (%reservedbytes)
+                static (+ static-used staticlib-used frozen-space-size))
+          (multiple-value-setq (stack-total stack-used stack-free)
+            (%stack-space))
+          (unless (eq verbose :default)
+            (setq stack-used-by-thread (%stack-space-by-lisp-thread))))))
+    (format t "~&Approximately ~:D bytes of memory can be allocated ~%before the next full GC is triggered. ~%" freebytes)
+    (when verbose
+      (flet ((k (n) (round n 1024)))
+        (princ "
+                   Total Size             Free                 Used")
+        (format t "~&Lisp Heap:~15t~10D (~DK)~35t~10D (~DK)~55t~10D (~DK)"
+                lispheap (k lispheap)
+                freebytes (k freebytes)
+                usedbytes (k usedbytes))
+        (format t "~&Stacks:~15t~10D (~DK)~35t~10D (~DK)~55t~10D (~DK)"
+                stack-total (k stack-total)
+                stack-free (k stack-free)
+                stack-used (k stack-used))
+        (format t "~&Static:~15t~10D (~DK)~35t~10D (~DK)~55t~10D (~DK)"
+                static (k static)
+                0 0
+                static (k static))
+        (when (and frozen-space-size (not (zerop frozen-space-size)))
+          (setq static-cons-reserved (ash (reserved-static-conses) target::dnode-shift)
+                frozen-space-size (- frozen-space-size static-cons-reserved))
+          (unless (zerop static-cons-reserved)
+            (format t "~&~,3f MB of reserved static conses (~d free, ~d reserved)"
+                    (/ static-cons-reserved (float (ash 1 20)))
+                    (free-static-conses)
+                    (reserved-static-conses)))
+
+          (unless (zerop frozen-space-size)
+                  (format t "~&~,3f MB of static memory is \"frozen\" dynamic memory"
+                          (/ frozen-space-size (float (ash 1 20))))))
+        (format t "~&~,3f MB reserved for heap expansion."
+                (/ reserved (float (ash 1 20))))
+        (unless (eq verbose :default)
+          (terpri)
+          (let* ((processes (all-processes)))
+            (dolist (thread-info stack-used-by-thread)
+              (destructuring-bind (thread sp-free sp-used vsp-free vsp-used tsp-free tsp-used)
+                  thread-info
+                (let* ((process (dolist (p processes)
+                                  (when (eq (process-thread p) thread)
+                                    (return p)))))
+                  (when process
+                    (let ((sp-total (+ sp-used sp-free))
+                          (vsp-total (+ vsp-used vsp-free))
+                          (tsp-total (+ tsp-used tsp-free)))
+                      (format t "~%~a(~d)~%  cstack:~12T~10D (~DK)  ~33T~10D (~DK)  ~54T~10D (~DK)~
+                               ~%  vstack:~12T~10D (~DK)  ~33T~10D (~DK)  ~54T~10D (~DK)~
+                               ~%  tstack:~12T~10D (~DK)  ~33T~10D (~DK)  ~54T~10D (~DK)"
+                              (process-name process)
+                              (process-serial-number process)
+                              sp-total (k sp-total) sp-free (k sp-free) sp-used (k sp-used)
+                              vsp-total (k vsp-total) vsp-free (k vsp-free) vsp-used (k vsp-used)
+                              tsp-total (k tsp-total) tsp-free (k tsp-free) tsp-used (k tsp-used)))))))))))))
+
+
+(defun list-length (l)
+  "Return the length of the given LIST, or NIL if the LIST is circular."
+  (do* ((n 0 (+ n 2))
+        (fast l (cddr fast))
+        (slow l (cdr slow)))
+       ((null fast) n)
+    (declare (fixnum n))
+    (if (null (cdr fast))
+      (return (the fixnum (1+ n)))
+      (if (and (eq fast slow)
+               (> n 0))
+        (return nil)))))
+
+(defun proper-list-p (l)
+  (and (typep l 'list)
+       (do* ((n 0 (+ n 2))
+             (fast l (if (and (listp fast) (listp (cdr fast)))
+                       (cddr fast)
+                       (return-from proper-list-p nil)))
+             (slow l (cdr slow)))
+            ((null fast) n)
+         (declare (fixnum n))
+         (if (atom fast)
+           (return nil)
+           (if (null (cdr fast))
+             (return t)
+             (if (and (eq fast slow)
+                      (> n 0))
+               (return nil)))))))
+
+(defun proper-sequence-p (x)
+  (cond ((typep x 'vector))
+	((typep x 'list) (not (null (list-length x))))))
+
+
+(defun length (seq)
+  "Return an integer that is the length of SEQUENCE."
+  (seq-dispatch
+   seq
+   (or (list-length seq)
+       (%err-disp $XIMPROPERLIST seq))
+   (if (= (the fixnum (typecode seq)) target::subtag-vectorH)
+     (%svref seq target::vectorH.logsize-cell)
+     (uvsize seq))))
+
+(defun %str-from-ptr (pointer len &optional (dest (make-string len)))
+  (declare (fixnum len)
+           (optimize (speed 3) (safety 0)))
+  (dotimes (i len dest)
+    (setf (%scharcode dest i) (%get-unsigned-byte pointer i))))
+
+(defun %get-cstring (pointer)
+  (do* ((end 0 (1+ end)))
+       ((zerop (the (unsigned-byte 8) (%get-unsigned-byte pointer end)))
+        (%str-from-ptr pointer end))
+    (declare (fixnum end))))
+
+(defun %get-utf-8-cstring (pointer)
+  (do* ((end 0 (1+ end)))
+       ((zerop (the (unsigned-byte 8) (%get-unsigned-byte pointer end)))
+        (let* ((len (utf-8-length-of-memory-encoding pointer end 0))
+               (string (make-string len)))
+          (utf-8-memory-decode pointer end 0 string)
+          string))
+    (declare (fixnum end))))
+
+;;; Assumes that pointer is terminated by a 0-valued 16-bit word
+;;; and that it points to a valid utf-16 string with native endianness.
+(defun %get-native-utf-16-cstring (pointer)
+  (do* ((nchars 0 (1+ nchars))
+        (i 0 (+ i 2))
+        (code (%get-unsigned-word pointer i) (%get-unsigned-word pointer i)))
+       ((zerop code)
+        (do* ((string (make-string nchars))
+              (out 0 (1+ out))
+              (i 0 (+ i 2)))
+             ((= out nchars) string)
+          (declare (fixnum i out))
+          (let* ((code (%get-unsigned-word pointer i)))
+            (declare (type (unsigned-byte 16) code))
+            (when (and (>= code #xd800)
+                       (< code #xdc00))
+              (incf i 2)
+              (let* ((code2 (%get-unsigned-word pointer i)))
+                (declare (type (unsigned-byte 16) code2))
+                (setq code (utf-16-combine-surrogate-pairs code code2))))
+            (setf (schar string out) (code-char code)))))
+    (when (and (>= code #xd800) (< code #xdc00))
+      (incf i 2))))
+
+
+;;; This is mostly here so we can bootstrap shared libs without
+;;; having to bootstrap #_strcmp.
+;;; Return true if the cstrings are equal, false otherwise.
+(defun %cstrcmp (x y)
+  (do* ((i 0 (1+ i))
+	(bx (%get-byte x i) (%get-byte x i))
+	(by (%get-byte y i) (%get-byte y i)))
+       ((not (= bx by)))
+    (declare (fixnum i bx by))
+    (when (zerop bx)
+      (return t))))
+
+(defun %cnstrcmp (x y n)
+  (declare (fixnum n))
+  (do* ((i 0 (1+ i))
+	(bx (%get-byte x i) (%get-byte x i))
+	(by (%get-byte y i) (%get-byte y i)))
+       ((= i n) t)
+    (declare (fixnum i bx by))
+    (unless (= bx by)
+      (return))))
+
+(defvar %documentation nil)
+
+(defvar %documentation-lock% nil)
+
+(setq %documentation
+  (make-hash-table :weak t :size 100 :test 'eq :rehash-threshold .95)
+  %documentation-lock% (make-lock))
+
+(defun %put-documentation (thing doc-id doc)
+  (with-lock-grabbed (%documentation-lock%)
+    (let* ((info (gethash thing %documentation))
+	   (pair (assoc doc-id info)))
+      (if doc
+        (progn
+          (unless (typep doc 'string)
+            (report-bad-arg doc 'string))
+          (if pair
+            (setf (cdr pair) doc)
+            (setf (gethash thing %documentation) (cons (cons doc-id doc) info))))
+	(when pair
+	  (if (setq info (nremove pair info))
+	    (setf (gethash thing %documentation) info)
+	    (remhash thing %documentation))))))
+  doc)
+
+(defun %get-documentation (object doc-id)
+  (cdr (assoc doc-id (gethash object %documentation))))
+
+;;; This pretends to be (SETF DOCUMENTATION), until that generic function
+;;; is defined.  It handles a few common cases.
+(defun %set-documentation (thing doc-id doc-string)
+  (case doc-id
+    (function 
+     (if (typep thing 'function)
+       (%put-documentation thing t doc-string)
+       (if (typep thing 'symbol)
+         (let* ((def (fboundp thing)))
+           (if def
+             (%put-documentation def t doc-string)))
+         (if (setf-function-name-p thing)
+           (%set-documentation
+            (setf-function-name thing) doc-id doc-string)))))
+    (variable
+     (if (typep thing 'symbol)
+       (%put-documentation thing doc-id doc-string)))
+    (t (%put-documentation thing doc-id doc-string)))
+  doc-string)
+
+
+(%fhave 'set-documentation #'%set-documentation)
+
+
+
+;;; This is intended for use by debugging tools.  It's a horrible thing
+;;; to do otherwise.  The caller really needs to hold the heap-segment
+;;; lock; this grabs the tcr queue lock as well.
+
+
+(defparameter *spin-lock-tries* 1)
+(defparameter *spin-lock-timeouts* 0)
+
+#+(and (not futex) (not x86-target))
+(defun %get-spin-lock (p)
+  (let* ((self (%current-tcr))
+         (n *spin-lock-tries*))
+    (declare (fixnum n))
+    (loop
+      (dotimes (i n)
+        (when (eql 0 (%ptr-store-fixnum-conditional p 0 self))
+          (return-from %get-spin-lock t)))
+      (%atomic-incf-node 1 '*spin-lock-timeouts* target::symbol.vcell)
+      (yield))))
+
+(eval-when (:compile-toplevel :execute)
+  (declaim (inline note-lock-wait note-lock-held note-lock-released)))
+
+
+
+
+
+#-futex
+(defun %lock-recursive-lock-object (lock &optional flag)
+  (let* ((ptr (recursive-lock-ptr lock)))
+    (with-macptrs ((p)
+                   (owner (%get-ptr ptr target::lockptr.owner))
+                   (signal (%get-ptr ptr target::lockptr.signal))
+                   (spin (%inc-ptr ptr target::lockptr.spinlock)))
+      (%setf-macptr-to-object p (%current-tcr))
+      (if (istruct-typep flag 'lock-acquisition)
+        (setf (lock-acquisition.status flag) nil)
+        (if flag (report-bad-arg flag 'lock-acquisition)))
+      (loop
+        (without-interrupts
+         (when (eql p owner)
+           (incf (%get-natural ptr target::lockptr.count))
+           (when flag
+             (setf (lock-acquisition.status flag) t))
+           (return t))
+         (%get-spin-lock spin)
+         (when (eql 1 (incf (%get-natural ptr target::lockptr.avail)))
+           (setf (%get-ptr ptr target::lockptr.owner) p
+                 (%get-natural ptr target::lockptr.count) 1)
+           (setf (%get-natural spin 0) 0)
+           (if flag
+             (setf (lock-acquisition.status flag) t))
+           (return t))
+         (setf (%get-natural spin 0) 0))
+        (%process-wait-on-semaphore-ptr signal 1 0 (recursive-lock-whostate lock))))))
+
+
+
+#+futex
+(progn
+  #-monitor-futex-wait
+  (defun futex-wait (p val whostate)
+    (with-process-whostate (whostate)
+      (int-errno-ffcall
+       (%kernel-import target::kernel-import-lisp-futex)
+       :address p :int FUTEX-WAIT :int val :address (%null-ptr) :address (%null-ptr) :int 0 :int)))
+  #+monitor-futex-wait
+  (progn
+    (defparameter *total-futex-wait-calls* 0)
+    (defparameter *total-futex-wait-times* 0)
+    (defun futex-wait (p val whostate)
+      (with-process-whostate (whostate)
+        (let* ((start (get-internal-real-time)))
+          (incf *total-futex-wait-calls*)
+          (int-errno-ffcall
+           (%kernel-import target::kernel-import-lisp-futex)
+           :address p :int FUTEX-WAIT :int val :address (%null-ptr) :address (%null-ptr) :int 0 :int)
+          (incf *total-futex-wait-times* (- (get-internal-real-time) start)))))))
+    
+
+
+
+#+futex
+(defun futex-wake (p n)
+  (int-errno-ffcall (%kernel-import target::kernel-import-lisp-futex)
+                    :address p :int FUTEX-WAKE :int n :address (%null-ptr) :address (%null-ptr) :int 0 :int))
+
+#+futex
+(defun %lock-futex (p wait-level lock fwhostate)
+  (let* ((val (%ptr-store-conditional p futex-avail futex-locked)))
+    (declare (fixnum val))
+    (or (eql val futex-avail)
+        (loop
+          (if (eql val futex-contended)
+            (let* ((*interrupt-level* wait-level))
+              (futex-wait p val (if fwhostate (funcall fwhostate lock) "futex wait")))
+            (setq val futex-contended))
+          (when (eql futex-avail (xchgl val p))
+            (return t))))))
+
+#+futex
+(defun %unlock-futex (p)
+  (unless (eql futex-avail (%atomic-decf-ptr p))
+    (setf (%get-natural p target::lockptr.avail) futex-avail)
+    (futex-wake p #$INT_MAX)))
+
+
+
+
+#+futex
+(defun %lock-recursive-lock-object (lock &optional flag)
+  (if (istruct-typep flag 'lock-acquisition)
+    (setf (lock-acquisition.status flag) nil)
+    (if flag (report-bad-arg flag 'lock-acquisition)))
+  (let* ((self (%current-tcr))
+         (level *interrupt-level*)
+         (ptr (recursive-lock-ptr lock)))
+    (declare (fixnum self))
+    (without-interrupts
+     (cond ((eql self (%get-object ptr target::lockptr.owner))
+            (incf (%get-natural ptr target::lockptr.count)))
+           (t (%lock-futex ptr level lock #'recursive-lock-whostate)
+              (%set-object ptr target::lockptr.owner self)
+              (setf (%get-natural ptr target::lockptr.count) 1)))
+     (when flag
+       (setf (lock-acquisition.status flag) t))
+     t)))
+
+          
+
+
+
+
+#-futex
+(defun %try-recursive-lock-object (lock &optional flag)
+  (let* ((ptr (recursive-lock-ptr lock)))
+    (with-macptrs ((p)
+                   (owner (%get-ptr ptr target::lockptr.owner))
+                   (spin (%inc-ptr ptr target::lockptr.spinlock)))
+      (%setf-macptr-to-object p (%current-tcr))
+      (if flag
+        (if (istruct-typep flag 'lock-acquisition)
+          (setf (lock-acquisition.status flag) nil)
+          (report-bad-arg flag 'lock-acquisition)))
+      (without-interrupts
+       (cond ((eql p owner)
+              (incf (%get-natural ptr target::lockptr.count))
+              (if flag (setf (lock-acquisition.status flag) t))
+              t)
+             (t
+              (let* ((win nil))
+                (%get-spin-lock spin)
+                (when (setq win (eql 1 (incf (%get-natural ptr target::lockptr.avail))))
+                  (setf (%get-ptr ptr target::lockptr.owner) p
+                        (%get-natural ptr target::lockptr.count) 1)
+                  (if flag (setf (lock-acquisition.status flag) t)))
+                (setf (%get-ptr spin) (%null-ptr))
+                win)))))))
+
+
+
+#+futex
+(defun %try-recursive-lock-object (lock &optional flag)
+  (let* ((self (%current-tcr))
+         (ptr (recursive-lock-ptr lock)))
+    (declare (fixnum self))
+    (if flag
+      (if (istruct-typep flag 'lock-acquisition)
+        (setf (lock-acquisition.status flag) nil)
+        (report-bad-arg flag 'lock-acquisition)))
+    (without-interrupts
+     (cond ((eql (%get-object ptr target::lockptr.owner) self)
+            (incf (%get-natural ptr target::lockptr.count))
+            (if flag (setf (lock-acquisition.status flag) t))
+            t)
+           (t
+            (when (eql 0 (%ptr-store-conditional ptr futex-avail futex-locked))
+              (%set-object ptr target::lockptr.owner self)
+              (setf (%get-natural ptr target::lockptr.count) 1)
+              (if flag (setf (lock-acquisition.status flag) t))
+              t))))))
+
+
+
+
+
+#-futex
+(defun %unlock-recursive-lock-object (lock)
+  (let* ((ptr (%svref lock target::lock._value-cell)))
+    (with-macptrs ((signal (%get-ptr ptr target::lockptr.signal))
+                   (spin (%inc-ptr ptr target::lockptr.spinlock)))
+      (unless (eql (%get-object ptr target::lockptr.owner) (%current-tcr))
+        (error 'not-lock-owner :lock lock))
+      (without-interrupts
+       (when (eql 0 (decf (the fixnum
+                            (%get-natural ptr target::lockptr.count))))
+         (%get-spin-lock spin)
+         (setf (%get-ptr ptr target::lockptr.owner) (%null-ptr))
+         (let* ((pending (+ (the fixnum
+                              (1- (the fixnum (%get-fixnum ptr target::lockptr.avail))))
+                            (the fixnum (%get-fixnum ptr target::lockptr.waiting)))))
+           (declare (fixnum pending))
+           (setf (%get-natural ptr target::lockptr.avail) 0
+                 (%get-natural ptr target::lockptr.waiting) 0)
+           (decf pending)
+           (if (> pending 0)
+             (setf (%get-natural ptr target::lockptr.waiting) pending))
+           (setf (%get-ptr spin) (%null-ptr))
+           (if (>= pending 0)
+             (%signal-semaphore-ptr signal)))))))
+  nil)
+
+
+
+#+futex
+(defun %unlock-recursive-lock-object (lock)
+  (let* ((ptr (%svref lock target::lock._value-cell)))
+    (unless (eql (%get-object ptr target::lockptr.owner) (%current-tcr))
+      (error 'not-lock-owner :lock lock))
+    (without-interrupts
+     (when (eql 0 (decf (the fixnum
+                          (%get-natural ptr target::lockptr.count))))
+    (setf (%get-natural ptr target::lockptr.owner) 0)
+    (%unlock-futex ptr))))
+  nil)
+
+
+
+
+(defun %%lock-owner (lock)
+  "Intended for debugging only; ownership may change while this code
+   is running."
+  (let* ((tcr (%get-object (recursive-lock-ptr lock) target::lockptr.owner)))
+    (unless (zerop tcr)
+      (tcr->process tcr))))
+
+ 
+  
+
+
+
+
+(defun %rplaca-conditional (cons-cell old new)
+  (%store-node-conditional target::cons.car cons-cell old new))
+
+(defun %rplacd-conditional (cons-cell old new)
+  (%store-node-conditional target::cons.cdr cons-cell old new))
+
+;;; Atomically push NEW onto the list in the I'th cell of uvector V.
+
+(defun atomic-push-uvector-cell (v i new)
+  (let* ((cell (cons new nil))
+         (offset (+ target::misc-data-offset (ash i target::word-shift))))
+    (loop
+      (let* ((old (%svref v i)))
+        (rplacd cell old)
+        (when (%store-node-conditional offset v old cell)
+          (return cell))))))
+
+(defun atomic-pop-uvector-cell (v i)
+  (let* ((offset (+ target::misc-data-offset (ash i target::word-shift))))
+    (loop
+      (let* ((old (%svref v i)))
+        (if (null old)
+          (return (values nil nil))
+          (let* ((tail (cdr old)))
+            (when (%store-node-conditional offset v old tail)
+              (return (values (car old) t)))))))))
+
+
+(defun store-gvector-conditional (index gvector old new)
+  (%store-node-conditional (+ target::misc-data-offset
+			      (ash index target::word-shift))
+			   gvector
+			   old
+			   new))
+
+(defun %atomic-incf-car (cell &optional (by 1))
+  (%atomic-incf-node (require-type by 'fixnum)
+		     (require-type cell 'cons)
+		     target::cons.car))
+
+(defun %atomic-incf-cdr (cell &optional (by 1))
+  (%atomic-incf-node (require-type by 'fixnum)
+		     (require-type cell 'cons)
+		     target::cons.cdr))
+
+(defun %atomic-incf-gvector (v i &optional (by 1))
+  (setq v (require-type v 'gvector))
+  (setq i (require-type i 'fixnum))
+  (%atomic-incf-node by v (+ target::misc-data-offset (ash i target::word-shift))))
+
+(defun %atomic-incf-symbol-value (s &optional (by 1))
+  (setq s (require-type s 'symbol))
+  (multiple-value-bind (base offset) (%symbol-binding-address s)
+    (%atomic-incf-node by base offset)))
+
+;;; What happens if there are some pending readers and another writer,
+;;; and we abort out of the semaphore wait ?  If the writer semaphore is
+;;; signaled before we abandon interest in it
+#-futex
+(defun %write-lock-rwlock-ptr (ptr lock &optional flag)
+  (with-macptrs ((write-signal (%get-ptr ptr target::rwlock.writer-signal)) )
+    (if (istruct-typep flag 'lock-acquisition)
+      (setf (lock-acquisition.status flag) nil)
+      (if flag (report-bad-arg flag 'lock-acquisition)))
+    (let* ((level *interrupt-level*)
+           (tcr (%current-tcr)))
+      (declare (fixnum tcr))
+      (without-interrupts
+       (%get-spin-lock ptr)               ;(%get-spin-lock (%inc-ptr ptr target::rwlock.spin))
+       (if (eq (%get-object ptr target::rwlock.writer) tcr)
+         (progn
+           (incf (%get-signed-natural ptr target::rwlock.state))
+           (setf (%get-natural ptr target::rwlock.spin) 0)
+           (if flag
+             (setf (lock-acquisition.status flag) t))
+           t)
+         (do* ()
+              ((eql 0 (%get-signed-natural ptr target::rwlock.state))
+               ;; That wasn't so bad, was it ?  We have the spinlock now.
+               (setf (%get-signed-natural ptr target::rwlock.state) 1
+                     (%get-natural ptr target::rwlock.spin) 0)
+               (%set-object ptr target::rwlock.writer tcr)
+               (if flag
+                 (setf (lock-acquisition.status flag) t))
+               t)
+           (incf (%get-natural ptr target::rwlock.blocked-writers))
+           (setf (%get-natural ptr target::rwlock.spin) 0)
+           (let* ((*interrupt-level* level))
+                  (%process-wait-on-semaphore-ptr write-signal 1 0 (rwlock-write-whostate lock)))
+           (%get-spin-lock ptr)))))))
+#+futex
+(defun %write-lock-rwlock-ptr (ptr lock &optional flag)
+  (with-macptrs ((write-signal (%INC-ptr ptr target::rwlock.writer-signal)) )
+    (if (istruct-typep flag 'lock-acquisition)
+      (setf (lock-acquisition.status flag) nil)
+      (if flag (report-bad-arg flag 'lock-acquisition)))
+    (let* ((level *interrupt-level*)
+           (tcr (%current-tcr)))
+      (declare (fixnum tcr))
+      (without-interrupts
+       (%lock-futex ptr level lock nil)
+       (if (eq (%get-object ptr target::rwlock.writer) tcr)
+         (progn
+           (incf (%get-signed-natural ptr target::rwlock.state))
+           (%unlock-futex ptr)
+           (if flag
+             (setf (lock-acquisition.status flag) t))
+           t)
+         (do* ()
+              ((eql 0 (%get-signed-natural ptr target::rwlock.state))
+               ;; That wasn't so bad, was it ?  We have the spinlock now.
+               (setf (%get-signed-natural ptr target::rwlock.state) 1)
+               (%unlock-futex ptr)
+               (%set-object ptr target::rwlock.writer tcr)
+               (if flag
+                 (setf (lock-acquisition.status flag) t))
+               t)
+           (incf (%get-natural ptr target::rwlock.blocked-writers))
+           (let* ((waitval (%get-natural write-signal 0)))
+             (%unlock-futex ptr)
+             (with-process-whostate ((rwlock-write-whostate lock))
+               (let* ((*interrupt-level* level))
+                 (futex-wait write-signal waitval (rwlock-write-whostate lock)))))
+           (%lock-futex ptr level lock nil)
+           (decf (%get-natural ptr target::rwlock.blocked-writers))))))))
+
+
+
+(defun write-lock-rwlock (lock &optional flag)
+  (%write-lock-rwlock-ptr (read-write-lock-ptr lock) lock flag))
+
+#-futex
+(defun %read-lock-rwlock-ptr (ptr lock &optional flag)
+  (with-macptrs ((read-signal (%get-ptr ptr target::rwlock.reader-signal)))
+    (if (istruct-typep flag 'lock-acquisition)
+      (setf (lock-acquisition.status flag) nil)
+      (if flag (report-bad-arg flag 'lock-acquisition)))
+    (let* ((level *interrupt-level*)
+           (tcr (%current-tcr)))
+      (declare (fixnum tcr))
+      (without-interrupts
+       (%get-spin-lock ptr)             ;(%get-spin-lock (%inc-ptr ptr target::rwlock.spin))
+       (if (eq (%get-object ptr target::rwlock.writer) tcr)
+         (progn
+           (setf (%get-natural ptr target::rwlock.spin) 0)
+           (error 'deadlock :lock lock))
+         (do* ((state
+                (%get-signed-natural ptr target::rwlock.state)
+                (%get-signed-natural ptr target::rwlock.state)))
+              ((<= state 0)
+               ;; That wasn't so bad, was it ?  We have the spinlock now.
+               (setf (%get-signed-natural ptr target::rwlock.state)
+                     (the fixnum (1- state))
+                     (%get-natural ptr target::rwlock.spin) 0)
+               (if flag
+                 (setf (lock-acquisition.status flag) t))
+               t)
+           (declare (fixnum state))
+           (incf (%get-natural ptr target::rwlock.blocked-readers))
+           (setf (%get-natural ptr target::rwlock.spin) 0)
+           (let* ((*interrupt-level* level))
+             (%process-wait-on-semaphore-ptr read-signal 1 0 (rwlock-read-whostate lock)))
+           (%get-spin-lock ptr)))))))
+
+#+futex
+(defun %read-lock-rwlock-ptr (ptr lock &optional flag) 
+  (with-macptrs ((reader-signal (%INC-ptr ptr target::rwlock.reader-signal)))
+    (if (istruct-typep flag 'lock-acquisition)
+      (setf (lock-acquisition.status flag) nil)
+      (if flag (report-bad-arg flag 'lock-acquisition)))
+    (let* ((level *interrupt-level*)
+           (tcr (%current-tcr)))
+      (declare (fixnum tcr))
+      (without-interrupts
+       (%lock-futex ptr level lock nil)
+       (if (eq (%get-object ptr target::rwlock.writer) tcr)
+         (progn
+           (%unlock-futex ptr)
+           (error 'deadlock :lock lock))
+         (do* ((state
+                (%get-signed-natural ptr target::rwlock.state)
+                (%get-signed-natural ptr target::rwlock.state)))
+              ((<= state 0)
+               ;; That wasn't so bad, was it ?  We have the spinlock now.
+               (setf (%get-signed-natural ptr target::rwlock.state)
+                     (the fixnum (1- state)))
+               (%unlock-futex ptr)
+               (if flag
+                 (setf (lock-acquisition.status flag) t))
+               t)
+           (declare (fixnum state))
+           (incf (%get-natural ptr target::rwlock.blocked-readers))
+           (let* ((waitval (%get-natural reader-signal 0)))
+             (%unlock-futex ptr)
+             (let* ((*interrupt-level* level))
+               (futex-wait reader-signal waitval (rwlock-read-whostate lock))))
+           (%lock-futex ptr level lock nil)
+           (decf (%get-natural ptr target::rwlock.blocked-readers))))))))
+
+
+
+(defun read-lock-rwlock (lock &optional flag)
+  (%read-lock-rwlock-ptr (read-write-lock-ptr lock) lock flag))
+
+
+
+#-futex
+(defun %unlock-rwlock-ptr (ptr lock)
+  (with-macptrs ((reader-signal (%get-ptr ptr target::rwlock.reader-signal))
+                 (writer-signal (%get-ptr ptr target::rwlock.writer-signal)))
+    (without-interrupts
+     (%get-spin-lock ptr)
+     (let* ((state (%get-signed-natural ptr target::rwlock.state))
+            (tcr (%current-tcr)))
+       (declare (fixnum state tcr))
+       (cond ((> state 0)
+              (unless (eql tcr (%get-object ptr target::rwlock.writer))
+                (setf (%get-natural ptr target::rwlock.spin) 0)
+                (error 'not-lock-owner :lock lock))
+              (decf state))
+             ((< state 0) (incf state))
+             (t (setf (%get-natural ptr target::rwlock.spin) 0)
+                (error 'not-locked :lock lock)))
+       (setf (%get-signed-natural ptr target::rwlock.state) state)
+       (when (zerop state)
+         ;; We want any thread waiting for a lock semaphore to
+         ;; be able to wait interruptibly.  When a thread waits,
+         ;; it increments either the "blocked-readers" or "blocked-writers"
+         ;; field, but since it may get interrupted before obtaining
+         ;; the semaphore that's more of "an expression of interest"
+         ;; in taking the lock than it is "a firm commitment to take it."
+         ;; It's generally (much) better to signal the semaphore(s)
+         ;; too often than it would be to not signal them often
+         ;; enough; spurious wakeups are better than deadlock.
+         ;; So: if there are blocked writers, the writer-signal
+         ;; is raised once for each apparent blocked writer.  (At most
+         ;; one writer will actually succeed in taking the lock.)
+         ;; If there are blocked readers, the reader-signal is raised
+         ;; once for each of them.  (It's possible for both the
+         ;; reader and writer semaphores to be raised on the same
+         ;; unlock; the writer semaphore is raised first, so in that
+         ;; sense, writers still have priority but it's not guaranteed.)
+         ;; Both the "blocked-writers" and "blocked-readers" fields
+         ;; are cleared here (they can't be changed from another thread
+         ;; until this thread releases the spinlock.)
+         (setf (%get-signed-natural ptr target::rwlock.writer) 0)
+         (let* ((nwriters (%get-natural ptr target::rwlock.blocked-writers))
+                (nreaders (%get-natural ptr target::rwlock.blocked-readers)))
+           (declare (fixnum nreaders nwriters))
+           (when (> nwriters 0)
+             (setf (%get-natural ptr target::rwlock.blocked-writers) 0)
+             (dotimes (i nwriters)
+               (%signal-semaphore-ptr writer-signal)))
+           (when (> nreaders 0)
+             (setf (%get-natural ptr target::rwlock.blocked-readers) 0)
+             (dotimes (i nreaders)
+               (%signal-semaphore-ptr reader-signal)))))
+       (setf (%get-natural ptr target::rwlock.spin) 0)
+       t))))
+
+#+futex
+(defun %unlock-rwlock-ptr (ptr lock)
+  (with-macptrs ((reader-signal (%INC-ptr ptr target::rwlock.reader-signal))
+                 (writer-signal (%INC-ptr ptr target::rwlock.writer-signal)))
+    (let* ((signal nil)
+           (wakeup 0))
+    (without-interrupts
+     (%lock-futex ptr -1 lock nil)
+     (let* ((state (%get-signed-natural ptr target::rwlock.state))
+            (tcr (%current-tcr)))
+       (declare (fixnum state tcr))
+       (cond ((> state 0)
+              (unless (eql tcr (%get-object ptr target::rwlock.writer))
+                (%unlock-futex ptr)
+                (error 'not-lock-owner :lock lock))
+              (decf state))
+             ((< state 0) (incf state))
+             (t (%unlock-futex ptr)
+                (error 'not-locked :lock lock)))
+       (setf (%get-signed-natural ptr target::rwlock.state) state)
+       (when (zerop state)
+         (setf (%get-signed-natural ptr target::rwlock.writer) 0)
+         (let* ((nwriters (%get-natural ptr target::rwlock.blocked-writers))
+                (nreaders (%get-natural ptr target::rwlock.blocked-readers)))
+           (declare (fixnum nreaders nwriters))
+           (if (> nwriters 0)
+             (setq signal writer-signal wakeup 1)
+             (if (> nreaders 0)
+               (setq signal reader-signal wakeup #$INT_MAX)))))
+       (when signal (incf (%get-signed-natural signal 0)))
+       (%unlock-futex ptr)
+       (when signal (futex-wake signal wakeup))
+       t)))))
+
+
+(defun unlock-rwlock (lock)
+  (%unlock-rwlock-ptr (read-write-lock-ptr lock) lock))
+
+;;; There are all kinds of ways to lose here.
+;;; The caller must have read access to the lock exactly once,
+;;; or have write access.
+;;; there's currently no way to detect whether the caller has
+;;; read access at all.
+;;; If we have to block and get interrupted, cleanup code may
+;;; try to unlock a lock that we don't hold. (It might be possible
+;;; to circumvent that if we use the same notifcation object here
+;;; that controls that cleanup process.)
+
+(defun %promote-rwlock (lock &optional flag)
+  (let* ((ptr (read-write-lock-ptr lock)))
+    (if (istruct-typep flag 'lock-acquisition)
+      (setf (lock-acquisition.status flag) nil)
+      (if flag (report-bad-arg flag 'lock-acquisition)))
+    (let* ((level *interrupt-level*)
+           (tcr (%current-tcr)))
+      (without-interrupts
+       #+futex
+       (%lock-futex ptr level lock nil)
+       #-futex
+       (%get-spin-lock ptr)
+       (let* ((state (%get-signed-natural ptr target::rwlock.state)))
+         (declare (fixnum state))
+         (cond ((> state 0)
+                (unless (eql (%get-object ptr target::rwlock.writer) tcr)
+                  #+futex
+                  (%unlock-futex ptr)
+                  #-futex
+                  (setf (%get-natural ptr target::rwlock.spin) 0)
+                  (error :not-lock-owner :lock lock)))
+               ((= state 0)
+                #+futex (%unlock-futex ptr)
+                #-futex (setf (%get-natural ptr target::rwlock.spin) 0)
+                (error :not-locked :lock lock))
+               (t
+                (if (= state -1)
+                  (progn
+                    (setf (%get-signed-natural ptr target::rwlock.state) 1)
+                    (%set-object ptr target::rwlock.writer tcr)
+                    #+futex
+                    (%unlock-futex ptr)
+                    #-futex
+                    (setf (%get-natural ptr target::rwlock.spin) 0)
+                    (if flag
+                      (setf (lock-acquisition.status flag) t))
+                    t)
+                  (progn                    
+                    #+futex
+                    (%unlock-futex ptr)
+                    #-futex
+                    (setf (%get-natural ptr target::rwlock.spin) 0)
+                    (%unlock-rwlock-ptr ptr lock)
+                    (let* ((*interrupt-level* level))
+                      (%write-lock-rwlock-ptr ptr lock flag)))))))))))
+                      
+
+
+(defun safe-get-ptr (p &optional dest)
+  (if (null dest)
+    (setq dest (%null-ptr))
+    (unless (typep dest 'macptr)
+      (check-type dest macptr)))
+  (without-interrupts                   ;reentrancy
+   (%safe-get-ptr p dest)))
+
+
+;;; Useless for anything but using RLET in early level-1 code without
+;;; having to bootstrap canonical type ordinals.
+(%fhave 'parse-foreign-type (lambda (spec) (declare (ignore spec))))
+(%fhave 'foreign-type-ordinal (lambda (thing) (declare (ignore thing)) 0))
+(%fhave '%foreign-type-or-record (lambda (x) (declare (ignore x))))
Index: /branches/new-random/level-0/l0-numbers.lisp
===================================================================
--- /branches/new-random/level-0/l0-numbers.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-numbers.lisp	(revision 13309)
@@ -0,0 +1,2035 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;;
+;;; level-0;l0-numbers.lisp
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "ARCH")
+  (require "LISPEQU")
+  (require "NUMBER-MACROS")
+  (require "NUMBER-CASE-MACRO")
+
+
+
+  (defvar *dfloat-dops* '((* . %double-float*-2!)(/ . %double-float/-2!)
+			  (+ . %double-float+-2!)(- . %double-float--2!)))
+  
+  (defvar *sfloat-dops* '((* . %short-float*-2!)(/ . %short-float/-2!)
+			  (+ . %short-float+-2!)(- . %short-float--2!)))
+
+  (defmacro dfloat-rat (op x y &optional (destructive-op (cdr (assq op *dfloat-dops*))))
+    (if destructive-op
+	(let ((f2 (gensym)))
+	  `(let ((,f2 (%double-float ,y (%make-dfloat))))
+	    (,destructive-op ,x ,f2 ,f2)))          
+	`(,op (the double-float ,x) (the double-float (%double-float ,y)))))
+
+  (defmacro rat-dfloat (op x y &optional (destructive-op (cdr (assq op *dfloat-dops*))))
+    (if destructive-op
+	(let ((f1 (gensym)))
+	  `(let ((,f1 (%double-float ,x (%make-dfloat)))) 
+	    (,destructive-op ,f1 ,y ,f1)))
+	`(,op (the double-float (%double-float ,x)) (the double-float ,y))))
+
+  (defmacro sfloat-rat (op x y &optional (destructive-op (cdr (assq op *sfloat-dops*))))
+    (let* ((use-destructive-op
+            (target-word-size-case
+             (32 destructive-op)
+             (64 nil))))
+      (if use-destructive-op
+	(let ((f2 (gensym)))
+	  `(let ((,f2 (%short-float ,y (%make-sfloat)))) 
+	    (,destructive-op ,x ,f2 ,f2)))
+	`(,op (the short-float ,x) (the short-float (%short-float ,y))))))
+
+  (defmacro rat-sfloat (op x y &optional (destructive-op (cdr (assq op *sfloat-dops*))))
+    (let* ((use-destructive-op
+            (target-word-size-case
+             (32 destructive-op)
+             (64 nil))))
+      (if use-destructive-op
+        (let ((f1 (gensym)))
+          `(let ((,f1 (%short-float ,x (%make-sfloat)))) 
+            (,destructive-op ,f1 ,y ,f1)))
+        `(,op (the short-float (%short-float ,x)) (the short-float ,y)))))
+
+
+  
+
+
+  (declaim (inline  %make-complex %make-ratio))
+  (declaim (inline canonical-complex))
+  (declaim (inline build-ratio))
+  (declaim (inline maybe-truncate)))
+
+
+
+(defun %make-complex (realpart imagpart)
+  (gvector :complex realpart imagpart))
+
+(defun %make-ratio (numerator denominator)
+  (gvector :ratio numerator denominator))
+ 
+
+
+; this is no longer used
+(defun %integer-signum (num)
+  (if (fixnump num)
+    (%fixnum-signum num)
+    ; there is no such thing as bignum zero we hope
+    (if (bignum-minusp num) -1 1)))
+
+
+; Destructive primitives.
+(macrolet ((defdestructive-df-op (non-destructive-name destructive-name op)
+             `(progn
+                (defun ,non-destructive-name (x y)
+                  (,destructive-name x y (%make-dfloat)))
+                (defun ,destructive-name (x y result)
+                  (declare (double-float x y result))
+                  (%setf-double-float result (the double-float (,op x y)))))))
+  (defdestructive-df-op %double-float+-2 %double-float+-2! +)
+  (defdestructive-df-op %double-float--2 %double-float--2! -)
+  (defdestructive-df-op %double-float*-2 %double-float*-2! *)
+  (defdestructive-df-op %double-float/-2 %double-float/-2! /))
+
+#-64-bit-target
+(macrolet ((defdestructive-sf-op (non-destructive-name destructive-name op)
+             `(progn
+                (defun ,non-destructive-name (x y)
+                  (,destructive-name x y (%make-sfloat)))
+                (defun ,destructive-name (x y result)
+                  (declare (short-float x y result))
+                  (%setf-short-float result (the short-float (,op x y)))))))
+  (defdestructive-sf-op %short-float+-2 %short-float+-2! +)
+  (defdestructive-sf-op %short-float--2 %short-float--2! -)
+  (defdestructive-sf-op %short-float*-2 %short-float*-2! *)
+  (defdestructive-sf-op %short-float/-2 %short-float/-2! /))
+
+
+(defun %negate (x)
+  (number-case x
+    (fixnum  (- (the fixnum x)))
+    (double-float  (%double-float-negate! x (%make-dfloat)))
+    (short-float
+     #+32-bit-target (%short-float-negate! x (%make-sfloat))
+     #+64-bit-target (%short-float-negate x))
+    (bignum (negate-bignum x))
+    (ratio (%make-ratio (%negate (%numerator x)) (%denominator x)))
+    (complex (%make-complex (%negate (%realpart X))(%negate (%imagpart X))) )))
+
+(defun %double-float-zerop (n)
+  (zerop (the double-float n)))
+
+(defun %short-float-zerop (n)
+  (zerop (the single-float n)))
+
+(defun zerop (number)
+  "Is this number zero?"
+  (number-case number
+    (integer (eq number 0))
+    (short-float (%short-float-zerop number))
+    (double-float (%double-float-zerop number))
+    (ratio nil)
+    (complex
+     (number-case (%realpart number)
+       (short-float (and (%short-float-zerop (%realpart number))
+                         (%short-float-zerop (%imagpart number))))
+       (double-float (and (%double-float-zerop (%realpart number))
+                          (%double-float-zerop (%imagpart number))))
+       (t (and (eql 0 (%realpart number))(eql 0 (%imagpart number))))))))
+
+(defun %short-float-plusp (x)
+  (> (the single-float x) 0.0f0))
+
+(defun %double-float-plusp (x)
+  (> (the double-float x) 0.0d0))
+
+(defun plusp (number)
+  "Is this real number strictly positive?"
+  (number-case number
+    (fixnum (%i> number 0))
+    (bignum (bignum-plusp number))
+    (short-float (%short-float-plusp number))
+    (double-float (%double-float-plusp number))
+    (ratio (plusp (%numerator number)))))
+
+
+(defun minusp (number)
+  "Is this real number strictly negative?"
+  (number-case number
+    (fixnum (%i< number 0))
+    (bignum (bignum-minusp number))
+    (short-float (%short-float-minusp number))
+    (double-float (%double-float-minusp number))
+    (ratio (minusp (%numerator number)))))
+
+
+(defun oddp (n)
+  "Is this integer odd?"
+  (case (typecode n)
+    (#.target::tag-fixnum (logbitp 0 (the fixnum n)))
+    (#.target::subtag-bignum (%bignum-oddp n))
+    (t (report-bad-arg n 'integer))))
+
+(defun evenp (n)
+  "Is this integer even?"
+  (case (typecode n)
+    (#.target::tag-fixnum (not (logbitp 0 (the fixnum n))))
+    (#.target::subtag-bignum (not (%bignum-oddp n)))
+    (t (report-bad-arg n 'integer))))
+
+;; expansion slightly changed
+(defun =-2 (x y)
+  (number-case x
+    (fixnum (number-case y
+              (fixnum (eq x y))
+              (double-float (eq 0 (fixnum-dfloat-compare x y)))
+              (short-float (eq 0 (fixnum-sfloat-compare x y)))
+              ((bignum ratio) nil)
+              (complex (and (zerop (%imagpart y)) (= x (%realpart y))))))
+    (double-float (number-case y ; x
+                    (double-float (= (the double-float x)(the double-float y))) ;x 
+                    (short-float (with-stack-double-floats ((dy y))
+                                   (= (the double-float x) (the double-float dy))))
+                    (fixnum (eq 0 (fixnum-dfloat-compare  y x)))
+                    (bignum (eq 0 (bignum-dfloat-compare y x)))
+                    (ratio (= (rational x) y))
+                    (complex (and (zerop (%imagpart y)) (= x (%realpart y))))))
+    (short-float (number-case y
+                   (short-float (= (the short-float x) (the short-float y)))
+                   (double-float (with-stack-double-floats ((dx x))
+                                   (= (the double-float dx) (the double-float y))))
+                   (fixnum (eq 0 (fixnum-sfloat-compare y x)))
+                   (bignum (eq 0 (bignum-sfloat-compare y x)))
+                   (ratio (= (rational x) y))
+                   (complex (and (zerop (%imagpart y)) (= x (%realpart y))))))
+    (bignum (number-case y 
+              (bignum (eq 0 (bignum-compare x y)))
+              ((fixnum ratio) nil)
+              (double-float (eq 0 (bignum-dfloat-compare x y)))
+              (short-float (eq 0 (bignum-sfloat-compare x y)))
+              (complex (and (zerop (%imagpart y)) (= x (%realpart y))))))
+    (ratio (number-case y
+             (integer nil)
+             (ratio
+              (and (eql (%numerator x) (%numerator y))
+                   (eql (%denominator x) (%denominator y))))
+             (float (= x (rational y)))
+             (complex (and (zerop (%imagpart y)) (= x (%realpart y))))))
+    (complex (number-case y
+               (complex (and (= (%realpart x) (%realpart y))
+                             (= (%imagpart x) (%imagpart y))))
+               ((float rational)
+                (and (zerop (%imagpart x)) (= (%realpart x) y)))))))
+
+(defun /=-2 (x y)
+  (declare (notinline =-2))
+  (not (= x y)))
+
+
+; true iff (< x y) is false.
+(defun >=-2 (x y)
+  (declare (notinline <-2))
+  (not (< x y)))
+
+
+
+(defun <=-2 (x y)
+  (declare (notinline >-2))
+  (not (> x y)))
+
+(defun <-2 (x y)
+  (number-case x
+    (fixnum (number-case y
+              (fixnum (< (the fixnum x) (the fixnum y)))
+              (double-float (eq -1 (fixnum-dfloat-compare x y)))
+              (short-float (eq -1 (fixnum-sfloat-compare x y)))
+              (bignum (bignum-plusp y))
+              (ratio (< x (ceiling (%numerator y)(%denominator y))))))
+    (double-float (number-case y ; x
+                    (double-float (< (the double-float x)(the double-float y))) ;x
+                    (short-float (with-stack-double-floats ((dy y))
+                                   (< (the double-float x) (the double-float dy))))
+                    (fixnum (eq 1 (fixnum-dfloat-compare  y x)))
+                    (bignum (eq 1 (bignum-dfloat-compare y x)))
+                    (ratio (< (rational x) y))))
+    (short-float (number-case y
+                    (short-float (< (the short-float x) (the short-float y)))
+                    (double-float (with-stack-double-floats ((dx x))
+                                    (< (the double-float dx) (the double-float y))))
+                    (fixnum (eq 1 (fixnum-sfloat-compare y x)))
+                    (bignum (eq 1 (bignum-sfloat-compare y x)))
+                    (ratio (< (rational x) y))))
+    (bignum (number-case y 
+              (bignum (EQ -1 (bignum-compare x y)))
+              (fixnum (not (bignum-plusp x)))
+              (ratio (< x (ceiling (%numerator y)(%denominator y))))
+              (double-float (eq -1 (bignum-dfloat-compare x y)))
+              (short-float (eq -1 (bignum-sfloat-compare x y)))))
+    (ratio (number-case y
+             (integer (< (floor (%numerator x)(%denominator x)) y))
+             (ratio
+              (< (* (%numerator (the ratio x))
+                    (%denominator (the ratio y)))
+                 (* (%numerator (the ratio y))
+                    (%denominator (the ratio x)))))
+             (float (< x (rational y)))))))
+
+
+
+(defun >-2 (x y)
+  ;(declare (optimize (speed 3)(safety 0)))
+  (number-case x
+    (fixnum (number-case y
+              (fixnum (> (the fixnum x) (the fixnum y)))
+              (bignum (not (bignum-plusp y)))
+              (double-float (eq 1 (fixnum-dfloat-compare x y)))
+              (short-float (eq 1 (fixnum-sfloat-compare x y)))
+              ;; or (> (* x denom) num) ?
+              (ratio (> x (floor (%numerator y) (%denominator y))))))
+    (double-float (number-case y
+                    (double-float (> (the double-float x) (the double-float y)))
+                    (short-float (with-stack-double-floats ((dy y))
+                                   (> (the double-float x) (the double-float dy))))
+                    (fixnum (eq -1 (fixnum-dfloat-compare  y x)))
+                    (bignum (eq -1 (bignum-dfloat-compare y x)))
+                    (ratio (> (rational x) y))))
+    (short-float (number-case y
+                    (short-float (> (the short-float x) (the short-float y)))
+                    (double-float (with-stack-double-floats ((dx x))
+                                   (> (the double-float dx) (the double-float y))))
+                    (fixnum (eq -1 (fixnum-sfloat-compare  y x)))
+                    (bignum (eq -1 (bignum-sfloat-compare y x)))
+                    (ratio (> (rational x) y))))
+    (bignum (number-case y
+              (fixnum (bignum-plusp x))
+              (bignum (eq 1 (bignum-compare x y)))
+              ;; or (> (* x demon) num)
+              (ratio (> x (floor (%numerator y) (%denominator y))))
+              (double-float (eq 1 (bignum-dfloat-compare x y)))
+              (short-float (eq 1 (bignum-sfloat-compare x y)))))
+    (ratio (number-case y
+             ;; or (> num (* y denom))
+             (integer (> (ceiling (%numerator x) (%denominator x)) y))
+             (ratio
+              (> (* (%numerator (the ratio x))
+                    (%denominator (the ratio y)))
+                 (* (%numerator (the ratio y))
+                    (%denominator (the ratio x)))))
+             (float (> x (rational y)))))))
+
+
+; t if any bits set after exp (unbiased)
+(defun hi-lo-fraction-p (hi lo exp)
+  (declare (fixnum hi lo exp))
+  (if (> exp 24)
+    (not (eql 0 (%ilogand lo (%ilsr (- exp 25) #xfffffff))))
+    (or (not (zerop lo))(not (eql 0 (%ilogand hi (%ilsr exp #x1ffffff)))))))
+
+
+
+(defun negate-hi-lo (hi lo)
+  (setq hi (%ilogxor hi #x3ffffff))
+  (if (eq 0 lo)    
+    (setq hi (+ hi 1))
+    (setq lo (+ (%ilogxor lo #xfffffff) 1)))
+  (values hi lo))
+
+
+
+(defun fixnum-dfloat-compare (int dfloat)
+  (declare (double-float dfloat) (fixnum int))
+  (if (and (eq int 0)(= dfloat 0.0d0))
+    0
+    (with-stack-double-floats ((d1 int))
+      (locally (declare (double-float d1))
+        (if (eq int (%truncate-double-float->fixnum d1))
+          (cond ((< d1 dfloat) -1)
+                ((= d1 dfloat) 0)
+                (t 1))
+          ;; Whatever we do here should have the effect
+          ;; of comparing the integer to the result of calling
+          ;; RATIONAL on the float.  We could probably
+          ;; skip the call to RATIONAL in more cases,
+          ;; but at least check the obvious ones here
+          ;; (e.g. different signs)
+          (multiple-value-bind (mantissa exponent sign)
+              (integer-decode-double-float dfloat)
+            (declare (type (integer -1 1) sign)
+                     (fixnum exponent))
+            (cond ((zerop int)
+                   (- sign))
+                  ((and (< int 0) (eql sign 1)) -1)
+                  ((and (> int 0) (eql sign -1)) 1)
+                  (t
+                   ;; See RATIONAL.  Can probably avoid this if
+                   ;; magnitudes are clearly dissimilar.
+                   (if (= sign -1) (setq mantissa (- mantissa)))
+                   (let* ((rat (if (< exponent 0)
+                                 (/ mantissa (ash 1 (the fixnum (- exponent))))
+                                 (ash mantissa exponent))))
+                     (if (< int rat)
+                       -1
+                       (if (eq int rat)
+                         0
+                         1)))))))))))
+
+
+
+(defun fixnum-sfloat-compare (int sfloat)
+  (declare (short-float sfloat) (fixnum int))
+  (if (and (eq int 0)(= sfloat 0.0s0))
+    0
+    (#+32-bit-target target::with-stack-short-floats #+32-bit-target ((s1 int))
+     #-32-bit-target let* #-32-bit-target ((s1 (%int-to-sfloat int)))
+                     (locally
+                         (declare (short-float s1))
+                       (if (eq (%truncate-short-float->fixnum s1) int)
+                         (cond ((< s1 sfloat) -1)
+                               ((= s1 sfloat) 0)
+                               (t 1))
+                         ;; Whatever we do here should have the effect
+                         ;; of comparing the integer to the result of calling
+                         ;; RATIONAL on the float.  We could probably
+                         ;; skip the call to RATIONAL in more cases,
+                         ;; but at least check the obvious ones here
+                         ;; (e.g. different signs)
+                         (multiple-value-bind (mantissa exponent sign)
+                             (integer-decode-short-float sfloat)
+                           (declare (type (integer -1 1) sign)
+                                    (fixnum exponent))
+                           (cond ((zerop int)
+                                  (- sign))
+                                 ((and (< int 0) (eql sign 1)) -1)
+                                 ((and (> int 0) (eql sign -1)) 1)
+                                 (t
+                                  ;; See RATIONAL.  Can probably avoid this if
+                                  ;; magnitudes are clearly dissimilar.
+                                  (if (= sign -1) (setq mantissa (- mantissa)))
+                                  (let* ((rat (if (< exponent 0)
+                                                (/ mantissa (ash 1 (the fixnum (- exponent))))
+                                                (ash mantissa exponent))))
+                                    (if (< int rat)
+                                      -1
+                                      (if (eq int rat)
+                                        0
+                                        1)))))))))))
+
+
+        
+;;; lotta stuff to avoid making a rational from a float
+;;; returns -1 less, 0 equal, 1 greater
+(defun bignum-dfloat-compare (int float)
+  (cond 
+   ((and (eq int 0)(= float 0.0d0)) 0)
+   (t
+    (let* ((fminus  (%double-float-minusp float))
+           (iminus (minusp int))
+           (gt (if iminus -1 1)))
+      (declare (fixnum gt))
+      (if (neq fminus iminus)
+        gt  ; if different signs, done
+        (let ((intlen (integer-length int)) 
+              (exp (- (the fixnum (%double-float-exp float)) 1022)))
+          (declare (fixnum intlen exp))
+          (cond 
+           ((and (not fminus) (< intlen exp)) -1)
+           ((> intlen exp)  gt)   ; if different exp, done
+           ((and fminus (or (< (1+ intlen) exp)
+                            (and (= (1+ intlen) exp)
+                                 (neq (one-bignum-factor-of-two int) intlen))))
+            ;(print 'zow)
+            (the fixnum (- gt)))  ; ; integer-length is strange for neg powers of 2            
+           (t (multiple-value-bind (hi lo)(fixnum-decode-float float)
+                (declare (fixnum hi lo)) 
+                (when fminus (multiple-value-setq (hi lo)(negate-hi-lo hi lo)))
+                (let* ((sz 26)  ; exp > 28 always
+                       (pos (- exp 25))
+                       (big-bits (%ldb-fixnum-from-bignum int sz pos)))
+                  (declare (fixnum pos big-bits sz))
+                  ;(print (list big-bits hi sz pos))
+                  (cond 
+                   ((< big-bits hi) -1)
+                   ((> big-bits hi) 1)
+                   (t (let* ((sz (min (- exp 25) 28))
+                             (pos (- exp 25 sz)) ; ?
+                             (ilo (if (< exp 53) (ash lo (- exp 53)) lo))                                    
+                             (big-bits (%ldb-fixnum-from-bignum int sz pos)))
+                        (declare (fixnum pos sz ilo big-bits))
+                        ;(PRINT (list big-bits ilo))
+                        (cond
+                         ((< big-bits ilo) -1)
+                         ((> big-bits ilo) 1)
+                         ((eq exp 53) 0)
+                         ((< exp 53)
+                          (if (not (hi-lo-fraction-p hi lo exp)) 0 -1)) ; -1 if pos 
+                         (t (if (%i< (one-bignum-factor-of-two int) (- exp 53)) 1 0)))))))
+                )))))))))
+
+
+
+;;; I don't know if it's worth doing a more "real" version of this.
+(defun bignum-sfloat-compare (int float)
+  (with-stack-double-floats ((df float))
+    (bignum-dfloat-compare int df)))
+
+;;;; Canonicalization utilities:
+
+;;; CANONICAL-COMPLEX  --  Internal
+;;;
+;;;    If imagpart is 0, return realpart, otherwise make a complex.  This is
+;;; used when we know that realpart and imagpart are the same type, but
+;;; rational canonicalization might still need to be done.
+;;;
+
+(defun canonical-complex (realpart imagpart)
+  (if (eql imagpart 0)
+    realpart
+    (%make-complex realpart imagpart)))
+
+
+
+
+(defun +-2 (x y)     
+  (number-case x
+    (fixnum (number-case y
+              (fixnum (+ (the fixnum x) (the fixnum y)))
+              (double-float (rat-dfloat + x y))
+              (short-float (rat-sfloat + x y))
+              (bignum (add-bignum-and-fixnum y x))
+              (complex (complex (+ x (%realpart y))
+                                (%imagpart y)))
+              (ratio (let* ((dy (%denominator y)) 
+                            (n (+ (* x dy) (%numerator y))))
+                       (%make-ratio n dy)))))
+    (double-float (number-case y
+                    (double-float (+ (the double-float x) (the double-float y)))
+                    (short-float (with-stack-double-floats ((dy y))
+                                   (+ (the double-float x) (the double-float dy))))
+                    (rational (dfloat-rat + x y))
+                    (complex (complex (+ x (%realpart y)) 
+                                      (%imagpart y)))))
+    (short-float (number-case y                                
+                   (short-float (+ (the short-float x) (the short-float y)))
+                   (double-float (with-stack-double-floats ((dx x))
+                                   (+ (the double-float dx) (the double-float y))))
+                   (rational (sfloat-rat + x y))
+                   (complex (complex (+ x (%realpart y))
+                                     (%imagpart y)))))
+    (bignum (number-case y
+              (bignum (add-bignums x y))
+              (fixnum (add-bignum-and-fixnum x y))
+              (double-float (rat-dfloat + x y))
+              (short-float (rat-sfloat + x y))
+              (complex (complex (+ x (realpart y)) 
+                                (%imagpart y)))
+              (ratio
+               (let* ((dy (%denominator y))
+                      (n (+ (* x dy) (%numerator y))))
+                 (%make-ratio n dy)))))
+    (complex (number-case y
+               (complex (canonical-complex (+ (%realpart x) (%realpart y))
+                                           (+ (%imagpart x) (%imagpart y))))
+               ((rational float) (complex (+ (%realpart x) y) (%imagpart x)))))
+    (ratio (number-case y
+             (ratio
+              (let* ((nx (%numerator x))
+                     (dx (%denominator x))
+                     (ny (%numerator y))
+                     (dy (%denominator y))
+                     (g1 (gcd dx dy)))
+                (if (eql g1 1)
+                  (%make-ratio (+ (* nx dy) (* dx ny)) (* dx dy))
+                  (let* ((t1 (+ (* nx (truncate dy g1)) (* (truncate dx g1) ny)))
+                         (g2 (gcd t1 g1))
+                         (t2 (truncate dx g1)))
+                    (cond ((eql t1 0) 0)
+                          ((eql g2 1) (%make-ratio t1 (* t2 dy)))
+                          (t
+                           (let* ((nn (truncate t1 g2))
+                                  (t3 (truncate dy g2))
+                                  (nd (if (eql t2 1) t3 (* t2 t3))))
+                             (if (eql nd 1) nn (%make-ratio nn nd)))))))))
+             (integer
+              (let* ((dx (%denominator x)) (n (+ (%numerator x) (* y dx))))
+                (%make-ratio n dx)))
+             (double-float (rat-dfloat + x y))
+             (short-float (rat-sfloat + x y))
+             (complex (complex (+ x (%realpart y)) 
+                               (%imagpart y)))))))
+
+(defun --2 (x y)     
+  (number-case x
+    (fixnum (number-case y
+              (fixnum (- (the fixnum x) (the fixnum y)))
+              (double-float (rat-dfloat - x y))
+              (short-float (rat-sfloat - x y))
+              (bignum 
+               (with-small-bignum-buffers ((bx x))
+                        (subtract-bignum bx y)))
+              (complex (complex (- x (%realpart y))
+                                (- (%imagpart y))))
+              (ratio (let* ((dy (%denominator y)) 
+                            (n (- (* x dy) (%numerator y))))
+                       (%make-ratio n dy)))))
+    (double-float (number-case y
+                    (double-float (- (the double-float x) (the double-float y)))
+                    (short-float (with-stack-double-floats ((dy y))
+                                   (- (the double-float x) (the double-float dy))))
+                    (rational (dfloat-rat - x y))
+                    (complex (complex (- x (%realpart y)) 
+                                      (- (%imagpart y))))))
+    (short-float (number-case y                                
+                   (short-float (- (the short-float x) (the short-float y)))
+                   (double-float (with-stack-double-floats ((dx x))
+                                   (- (the double-float dx) (the double-float y))))
+                   (rational (sfloat-rat - x y))
+                   (complex (complex (- x (%realpart y))
+                                     (- (%imagpart y))))))
+    (bignum (number-case y
+              (bignum (subtract-bignum x y))
+              (fixnum (if (eql y target::target-most-negative-fixnum)
+                        (with-small-bignum-buffers ((by y))
+                          (subtract-bignum x by))
+                        (add-bignum-and-fixnum x (- y))))
+              (double-float (rat-dfloat - x y))
+              (short-float (rat-sfloat - x y))
+              (complex (complex (- x (realpart y)) 
+                                (- (%imagpart y))))
+              (ratio
+               (let* ((dy (%denominator y))
+                      (n (- (* x dy) (%numerator y))))
+                 (%make-ratio n dy)))))
+    (complex (number-case y
+               (complex (canonical-complex (- (%realpart x) (%realpart y))
+                                           (- (%imagpart x) (%imagpart y))))
+               ((rational float) (complex (- (%realpart x) y) (%imagpart x)))))
+    (ratio (number-case y
+             (ratio
+              (let* ((nx (%numerator x))
+                     (dx (%denominator x))
+                     (ny (%numerator y))
+                     (dy (%denominator y))
+                     (g1 (gcd dx dy)))
+                (if (eql g1 1)
+                  (%make-ratio (- (* nx dy) (* dx ny)) (* dx dy))
+                  (let* ((t1 (- (* nx (truncate dy g1)) (* (truncate dx g1) ny)))
+                         (g2 (gcd t1 g1))
+                         (t2 (truncate dx g1)))
+                    (cond ((eql t1 0) 0)
+                          ((eql g2 1) (%make-ratio t1 (* t2 dy)))
+                          (t
+                           (let* ((nn (truncate t1 g2))
+                                  (t3 (truncate dy g2))
+                                  (nd (if (eql t2 1) t3 (* t2 t3))))
+                             (if (eql nd 1) nn (%make-ratio nn nd)))))))))
+             (integer
+              (let* ((dx (%denominator x)) (n (- (%numerator x) (* y dx))))
+                (%make-ratio n dx)))
+             (double-float (rat-dfloat - x y))
+             (short-float (rat-sfloat - x y))
+             (complex (complex (- x (%realpart y)) 
+                               (- (%imagpart y))))))))
+
+
+;;; BUILD-RATIO  --  Internal
+;;;
+;;;    Given a numerator and denominator with the GCD already divided out, make
+;;; a canonical rational.  We make the denominator positive, and check whether
+;;; it is 1.
+;;;
+
+(defun build-ratio (num den)
+  (if (minusp den) (setq num (- num) den (- den)))
+  (case den
+    (0 (divide-by-zero-error 'build-ratio num den))
+    (1 num)
+    (t (%make-ratio num den))))
+
+
+
+
+;;; MAYBE-TRUNCATE  --  Internal
+;;;
+;;;    Truncate X and Y, but bum the case where Y is 1.
+;;;
+
+
+(defun maybe-truncate (x y)
+  (if (eql y 1)
+    x
+    (truncate x y)))
+
+(defun *-2 (x y)
+  ;(declare (optimize (speed 3)(safety 0)))
+  (flet ((integer*ratio (x y)
+	   (if (eql x 0) 0
+	       (let* ((ny (%numerator y))
+		      (dy (%denominator y))
+		      (gcd (gcd x dy)))
+		 (if (eql gcd 1)
+		     (%make-ratio (* x ny) dy)
+		     (let ((nn (* (truncate x gcd) ny))
+			   (nd (truncate dy gcd)))
+		       (if (eql nd 1)
+			   nn
+			   (%make-ratio nn nd)))))))
+	 (complex*real (x y)
+	   (canonical-complex (* (%realpart x) y) (* (%imagpart x) y))))
+    (number-case x
+      (double-float (number-case y
+                      (double-float (* (the double-float x)(the double-float y)))
+                      (short-float (with-stack-double-floats ((dy y))
+                                     (* (the double-float x) (the double-float dy))))
+                      (rational (dfloat-rat * x y))
+                      (complex (complex*real y x))))
+      (short-float (number-case y
+                      (double-float (with-stack-double-floats ((dx x))
+                                     (* (the double-float dx) (the double-float y))))
+                      (short-float (* (the short-float x) (the short-float y)))
+                      (rational (sfloat-rat * x y))
+                      (complex (complex*real y x))))
+      (bignum (number-case y
+                (fixnum (multiply-bignum-and-fixnum x y))
+                (bignum (multiply-bignums x y))
+                (double-float (dfloat-rat * y x))
+                (short-float (sfloat-rat * y x))
+                (ratio (integer*ratio x y))
+                (complex (complex*real y x))))
+      (fixnum (number-case y
+                (bignum (multiply-bignum-and-fixnum y x))
+                (fixnum (multiply-fixnums (the fixnum x) (the fixnum y)))
+                (short-float (sfloat-rat * y x))
+                (double-float (dfloat-rat * y x))
+                (ratio (integer*ratio x y))
+                (complex (complex*real y x))))
+      (complex (number-case y
+                 (complex (let* ((rx (%realpart x))
+	                         (ix (%imagpart x))
+	                         (ry (%realpart y))
+	                         (iy (%imagpart y)))
+	                    (canonical-complex (- (* rx ry) (* ix iy)) (+ (* rx iy) (* ix ry)))))
+                 (real (complex*real x y))))
+      (ratio (number-case y
+               (ratio (let* ((nx (%numerator x))
+	                     (dx (%denominator x))
+	                     (ny (%numerator y))
+	                     (dy (%denominator y))
+	                     (g1 (gcd nx dy))
+	                     (g2 (gcd dx ny)))
+	                (build-ratio (* (maybe-truncate nx g1)
+			                (maybe-truncate ny g2))
+		                     (* (maybe-truncate dx g2)
+			                (maybe-truncate dy g1)))))
+               (integer (integer*ratio y x))
+               (double-float (rat-dfloat * x y))
+               (short-float (rat-sfloat * x y))
+               (complex (complex*real y x)))))))
+
+
+
+(defun integer*integer (x y &optional res)
+  (declare (ignore res))
+  (number-case x      
+      (fixnum (number-case y
+                (fixnum (* (the fixnum x) (the fixnum y)))
+                (t (multiply-bignum-and-fixnum y x))))
+      (bignum (number-case y
+                (fixnum (multiply-bignum-and-fixnum x y))
+                (t (multiply-bignums x y))))))
+
+
+
+  
+
+;;; INTEGER-/-INTEGER  --  Internal
+;;;
+;;;    Divide two integers, producing a canonical rational.  If a fixnum, we
+;;; see if they divide evenly before trying the GCD.  In the bignum case, we
+;;; don't bother, since bignum division is expensive, and the test is not very
+;;; likely to suceed.
+;;;
+(defun integer-/-integer (x y)
+  (if (and (typep x 'fixnum) (typep y 'fixnum))
+    (multiple-value-bind (quo rem) (%fixnum-truncate x y)
+      (if (eql 0 rem)
+        quo
+        (let ((gcd (gcd x y)))
+          (declare (fixnum gcd))
+          (if (eql gcd 1)
+            (build-ratio x y)
+            (build-ratio (%fixnum-truncate x gcd) (%fixnum-truncate y gcd))))))
+      (let ((gcd (gcd x y)))
+        (if (eql gcd 1)
+          (build-ratio x y)
+          (build-ratio (truncate x gcd) (truncate y gcd))))))
+
+
+
+(defun /-2 (x y)
+  (number-case x
+    (double-float (number-case y
+                    (double-float (/ (the double-float x) (the double-float y)))
+                    (short-float (with-stack-double-floats ((dy y))
+                                   (/ (the double-float x) (the double-float dy))))
+                    (rational (dfloat-rat / x y))
+                    (complex (let* ((ry (%realpart y))
+                                    (iy (%imagpart y))
+                                    (dn (+ (* ry ry) (* iy iy))))
+                               (canonical-complex (/ (* x ry) dn) (/ (- (* x iy)) dn))))))
+    (short-float (number-case y
+                   (short-float (/ (the short-float x) (the short-float y)))
+                   (double-float (with-stack-double-floats ((dx x))
+                                   (/ (the double-float dx) (the double-float y))))
+                   (rational (sfloat-rat / x y))
+                   (complex (let* ((ry (%realpart y))
+                                    (iy (%imagpart y))
+                                    (dn (+ (* ry ry) (* iy iy))))
+                               (canonical-complex (/ (* x ry) dn) (/ (- (* x iy)) dn))))))                   
+    (integer (number-case y
+               (double-float (rat-dfloat / x y))
+               (short-float (rat-sfloat / x y))
+               (integer (integer-/-integer x y))
+               (complex (let* ((ry (%realpart y))
+                               (iy (%imagpart y))
+                               (dn (+ (* ry ry) (* iy iy))))
+                          (canonical-complex (/ (* x ry) dn) (/ (- (* x iy)) dn))))
+               (ratio
+                (if (eql 0 x)
+                  0
+                  (let* ((ny (%numerator y)) 
+                         (dy (%denominator y)) 
+                         (gcd (gcd x ny)))
+                    (build-ratio (* (maybe-truncate x gcd) dy)
+                                 (maybe-truncate ny gcd)))))))
+    (complex (number-case y
+               (complex (let* ((rx (%realpart x))
+                               (ix (%imagpart x))
+                               (ry (%realpart y))
+                               (iy (%imagpart y))
+                               (dn (+ (* ry ry) (* iy iy))))
+                          (canonical-complex (/ (+ (* rx ry) (* ix iy)) dn)
+                                             (/ (- (* ix ry) (* rx iy)) dn))))
+               ((rational float)
+                (canonical-complex (/ (%realpart x) y) (/ (%imagpart x) y)))))
+    (ratio (number-case y
+             (double-float (rat-dfloat / x y))
+             (short-float (rat-sfloat / x y))
+             (integer
+              (when (eql y 0)
+                (divide-by-zero-error '/ x y))
+              (let* ((nx (%numerator x)) (gcd (gcd nx y)))
+                (build-ratio (maybe-truncate nx gcd)
+                             (* (maybe-truncate y gcd) (%denominator x)))))
+             (complex (let* ((ry (%realpart y))
+                             (iy (%imagpart y))
+                             (dn (+ (* ry ry) (* iy iy))))
+                        (canonical-complex (/ (* x ry) dn) (/ (- (* x iy)) dn))))
+             (ratio
+              (let* ((nx (%numerator x))
+                     (dx (%denominator x))
+                     (ny (%numerator y))
+                     (dy (%denominator y))
+                     (g1 (gcd nx ny))
+                     (g2 (gcd dx dy)))
+                (build-ratio (* (maybe-truncate nx g1) (maybe-truncate dy g2))
+                             (* (maybe-truncate dx g2) (maybe-truncate ny g1)))))))))
+
+
+
+(defun divide-by-zero-error (operation &rest operands)
+  (error (make-condition 'division-by-zero
+           :operation operation
+           :operands operands)))
+
+
+(defun 1+ (number)
+  "Returns NUMBER + 1."
+  (+-2 number 1))
+
+(defun 1- (number)
+  "Returns NUMBER - 1."
+  (--2 number 1))
+
+
+
+
+(defun conjugate (number)
+  "Return the complex conjugate of NUMBER. For non-complex numbers, this is
+  an identity."
+  (number-case number
+    (complex (complex (%realpart number) (- (%imagpart number))))
+    (number number)))
+
+(defun numerator (rational)
+  "Return the numerator of NUMBER, which must be rational."
+  (number-case rational
+    (ratio (%numerator rational))
+    (integer rational)))
+
+(defun denominator (rational)
+  "Return the denominator of NUMBER, which must be rational."
+  (number-case rational
+    (ratio (%denominator rational))
+    (integer 1)))
+
+
+
+(defun abs (number)
+  "Return the absolute value of the number."
+  (number-case number
+   (fixnum
+    (locally (declare (fixnum number))
+      (if (minusp number) (- number) number)))
+   (double-float
+    (%double-float-abs number))
+   (short-float
+    (%short-float-abs number))
+   (bignum
+    (if (bignum-minusp number)(negate-bignum number) number))
+   (ratio
+    (if (minusp number) (- number) number))    
+   (complex
+    (let ((rx (%realpart number))
+          (ix (%imagpart number)))
+      (number-case rx
+        (rational
+         (sqrt (+ (* rx rx) (* ix ix))))
+        (short-float
+         (%short-float (%hypot (%double-float rx)
+                               (%double-float ix))))
+        (double-float
+         (%hypot rx ix)))))))
+
+
+
+(defun phase (number)
+  "Return the angle part of the polar representation of a complex number.
+  For complex numbers, this is (atan (imagpart number) (realpart number)).
+  For non-complex positive numbers, this is 0. For non-complex negative
+  numbers this is PI."
+  (number-case number
+    (rational
+     (if (minusp number)
+       (%short-float pi)
+       0.0f0))
+    (double-float
+     (if (minusp number)
+       (%double-float pi)
+       0.0d0))
+    (complex
+     (atan (%imagpart number) (%realpart number)))
+    (short-float
+     (if (minusp number)
+       (%short-float pi)
+       0.0s0))))
+
+
+
+; from Lib;numbers.lisp, sort of
+(defun float (number &optional other)
+  "Converts any REAL to a float. If OTHER is not provided, it returns a
+  SINGLE-FLOAT if NUMBER is not already a FLOAT. If OTHER is provided, the
+  result is the same float format as OTHER."
+  (if (null other)
+    (if (typep number 'float)
+      number
+      (%short-float number))
+    (if (typep other 'double-float)
+      (%double-float number)
+      (if (typep other 'short-float)
+        (%short-float number)
+        (float number (require-type other 'float))))))
+
+
+
+
+
+;;; If the numbers do not divide exactly and the result of (/ number divisor)
+;;; would be negative then decrement the quotient and augment the remainder by
+;;; the divisor.
+;;;
+(defun floor (number &optional divisor)
+  "Return the greatest integer not greater than number, or number/divisor.
+  The second returned value is (mod number divisor)."
+  (if (null divisor)(setq divisor 1))
+  (multiple-value-bind (tru rem) (truncate number divisor)
+    (if (and (not (zerop rem))
+	     (if (minusp divisor)
+               (plusp number)
+               (minusp number)))
+      (if (called-for-mv-p)
+        (values (1- tru) (+ rem divisor))
+        (1- tru))
+      (values tru rem))))
+
+
+
+(defun %fixnum-floor (number divisor)
+  (declare (fixnum number divisor))
+  (if (eq divisor 1)
+    (values number 0)
+    (multiple-value-bind (tru rem) (truncate number divisor)
+      (if (eq rem 0)
+        (values tru 0)
+        (locally (declare (fixnum tru rem))
+          (if (and ;(not (zerop rem))
+	           (if (minusp divisor)
+                     (plusp number)
+                     (minusp number)))
+            (values (the fixnum (1- tru)) (the fixnum (+ rem divisor)))
+            (values tru rem)))))))
+
+
+
+;;; If the numbers do not divide exactly and the result of (/ number divisor)
+;;; would be positive then increment the quotient and decrement the remainder by
+;;; the divisor.
+;;;
+(defun ceiling (number &optional divisor)
+  "Return the smallest integer not less than number, or number/divisor.
+  The second returned value is the remainder."
+  (if (null divisor)(setq divisor 1))
+  (multiple-value-bind (tru rem) (truncate number divisor)
+    (if (and (not (zerop rem))
+	     (if (minusp divisor)
+               (minusp number)
+               (plusp number)))
+      (if (called-for-mv-p)
+        (values (+ tru 1) (- rem divisor))
+        (+ tru 1))
+      (values tru rem))))
+
+
+
+(defun %fixnum-ceiling (number  divisor)
+  "Returns the smallest integer not less than number, or number/divisor.
+  The second returned value is the remainder."
+  (declare (fixnum number divisor))
+  (multiple-value-bind (tru rem) (%fixnum-truncate number divisor)
+    (if (eq 0 rem)
+      (values tru 0)
+      (locally (declare (fixnum tru rem))
+        (if (and ;(not (zerop rem))
+	     (if (minusp divisor)
+               (minusp number)
+               (plusp number)))
+          (values (the fixnum (+ tru 1))(the fixnum  (- rem divisor)))
+          (values tru rem))))))
+
+
+
+(defun integer-decode-denorm-short-float (mantissa sign)
+  (declare (fixnum mantissa sign))
+  (do* ((bias 0 (1+ bias))
+	(sig mantissa (ash sig 1)))
+       ((logbitp 23 sig)
+	(values sig
+		(- (- IEEE-single-float-bias)
+		   IEEE-single-float-digits
+		   bias)
+		sign))))
+
+
+(defun integer-decode-short-float (sfloat)
+  (multiple-value-bind (mantissa exp sign)(fixnum-decode-short-float sfloat)
+    (let* ((biased (- exp IEEE-single-float-bias IEEE-single-float-digits)))
+      (setq sign (if (eql 0 sign) 1 -1))
+      (if (eq exp 255)
+	(error "Can't decode NAN/Inf: ~s" sfloat))
+      (if (eql 0 exp)
+	(if (eql 0 mantissa)
+	  (values 0 biased sign)
+	  (integer-decode-denorm-short-float (ash mantissa 1) sign))
+	(values (logior #x800000 mantissa) biased sign)))))
+
+
+
+
+;;; INTEGER-DECODE-FLOAT  --  Public
+;;;
+;;;    Dispatch to the correct type-specific i-d-f function.
+;;;
+(defun integer-decode-float (x)
+  "Returns three values:
+   1) an integer representation of the significand.
+   2) the exponent for the power of 2 that the significand must be multiplied
+      by to get the actual value.  This differs from the DECODE-FLOAT exponent
+      by FLOAT-DIGITS, since the significand has been scaled to have all its
+      digits before the radix point.
+   3) -1 or 1 (i.e. the sign of the argument.)"
+  (number-case x
+    (short-float
+     (integer-decode-short-float x))
+    (double-float
+     (integer-decode-double-float x))))
+
+
+;;; %UNARY-TRUNCATE  --  Interface
+;;;
+;;;    This function is called when we are doing a truncate without any funky
+;;; divisor, i.e. converting a float or ratio to an integer.  Note that we do
+;;; *not* return the second value of truncate, so it must be computed by the
+;;; caller if needed.
+;;;
+;;;    In the float case, we pick off small arguments so that compiler can use
+;;; special-case operations.  We use an exclusive test, since (due to round-off
+;;; error), (float most-positive-fixnum) may be greater than
+;;; most-positive-fixnum.
+;;;
+(defun %unary-truncate (number)
+  (number-case number
+    (integer number)
+    (ratio (truncate-no-rem (%numerator number) (%denominator number)))
+    (double-float
+     (if (and (< (the double-float number) 
+                 (float (1- (ash 1 (- (1- target::nbits-in-word) target::fixnumshift))) 0.0d0))
+              (< (float (ash -1 (- (1- target::nbits-in-word) target::fixnumshift)) 0.0d0)
+	         (the double-float number)))
+       (%truncate-double-float->fixnum number)
+       (%truncate-double-float number)))
+    (short-float
+     (if (and (< (the short-float number) 
+                 (float (1- (ash 1 (- (1- target::nbits-in-word) target::fixnumshift))) 0.0s0))
+              (< (float (ash -1 (- (1- target::nbits-in-word) target::fixnumshift)) 0.0s0)
+	         (the short-float number)))
+       (%truncate-short-float->fixnum number)
+       (%truncate-short-float number)))))
+
+
+
+; cmucl:compiler:float-tran.lisp
+(defun xform-truncate (x)
+  (let ((res (%unary-truncate x)))
+    (values res (- x res))))
+
+
+
+(defun truncate (number &optional divisor)
+  "Returns number (or number/divisor) as an integer, rounded toward 0.
+  The second returned value is the remainder."
+  (if (null divisor)(setq divisor 1))
+  (when (not (called-for-mv-p))
+    (return-from truncate (truncate-no-rem number divisor)))
+  (macrolet 
+      ((truncate-rat-dfloat (number divisor)
+         `(with-stack-double-floats ((fnum ,number)
+                                     (f2))
+           (let ((res (%unary-truncate (%double-float/-2! fnum ,divisor f2))))
+             (values res 
+                     (%double-float--2 fnum (%double-float*-2! (%double-float res f2) ,divisor f2))))))
+       (truncate-rat-sfloat (number divisor)
+         #+32-bit-target
+         `(target::with-stack-short-floats ((fnum ,number)
+                                           (f2))
+           (let ((res (%unary-truncate (%short-float/-2! fnum ,divisor f2))))
+             (values res 
+                     (%short-float--2 fnum (%short-float*-2! (%short-float res f2) ,divisor f2)))))
+          #+64-bit-target
+         `(let* ((temp (%short-float ,number))
+                 (res (%unary-truncate (/ (the short-float temp)
+                                          (the short-float ,divisor)))))
+           (values res
+            (- (the short-float temp)
+             (the short-float (* (the short-float (%short-float res))
+                                 (the short-float ,divisor)))))))
+         )
+    (number-case number
+      (fixnum
+       (if (eql number target::target-most-negative-fixnum)
+         (if (zerop divisor)
+           (error 'division-by-zero :operation 'truncate :operands (list number divisor))
+           (with-small-bignum-buffers ((bn number))
+             (multiple-value-bind (quo rem) (truncate bn divisor)
+               (if (eq quo bn)
+                 (values number rem)
+                 (values quo rem)))))
+         (number-case divisor
+           (fixnum (if (eq divisor 1) (values number 0) (%fixnum-truncate number divisor)))
+           (bignum (values 0 number))
+           (double-float (truncate-rat-dfloat number divisor))
+           (short-float (truncate-rat-sfloat number divisor))
+           (ratio (let ((q (truncate (* number (%denominator divisor)) ; this was wrong
+                                     (%numerator divisor))))
+                    (values q (- number (* q divisor))))))))
+      (bignum (number-case divisor
+                (fixnum (if (eq divisor 1) (values number 0)
+                          (if (eq divisor target::target-most-negative-fixnum);; << aargh
+                            (with-small-bignum-buffers ((bd divisor))
+                              (bignum-truncate number bd))
+                            (bignum-truncate-by-fixnum number divisor))))
+                (bignum (bignum-truncate number divisor))
+                (double-float  (truncate-rat-dfloat number divisor))
+                (short-float (truncate-rat-sfloat number divisor))
+                (ratio (let ((q (truncate (* number (%denominator divisor)) ; so was this
+                                          (%numerator divisor))))
+                         (values q (- number (* q divisor)))))))
+      (short-float (if (eql divisor 1)
+                     (let* ((res (%unary-truncate number)))
+                       (values res (- number res)))
+                     (number-case divisor
+                       (short-float
+                        #+32-bit-target
+                        (target::with-stack-short-floats ((f2))
+                          (let ((res (%unary-truncate (%short-float/-2! number divisor f2))))
+                            (values res 
+                                    (%short-float--2
+                                     number 
+                                     (%short-float*-2! (%short-float res f2) divisor f2)))))
+                        #+64-bit-target
+                        (let ((res (%unary-truncate
+                                    (/ (the short-float number)
+                                       (the short-float divisor)))))
+                            (values res
+                                    (- (the short-float number)
+                                       (* (the short-float (%short-float res))
+                                          (the short-float divisor))))))
+                       ((fixnum bignum ratio)
+                        #+32-bit-target
+                        (target::with-stack-short-floats ((fdiv divisor)
+                                                         (f2))
+                          (let ((res (%unary-truncate (%short-float/-2! number fdiv f2))))
+                            (values res 
+                                    (%short-float--2 
+                                     number 
+                                     (%short-float*-2! (%short-float res f2) fdiv f2)))))
+                        #+64-bit-target
+                        (let* ((fdiv (%short-float divisor))
+                               (res (%unary-truncate
+                                     (/ (the short-float number)
+                                        (the short-float fdiv)))))
+                          (values res (- number (* res fdiv))))
+                                     
+                        )
+                       (double-float
+                        (with-stack-double-floats ((fnum number)
+                                                   (f2))
+                          (let* ((res (%unary-truncate (%double-float/-2! fnum divisor f2))))
+                            (values res
+                                    (%double-float--2
+                                     fnum
+                                     (%double-float*-2! (%double-float res f2) divisor f2)))))))))
+      (double-float (if (eql divisor 1)
+                      (let ((res (%unary-truncate number)))
+                        (values res (- number res)))
+                      (number-case divisor
+                        ((fixnum bignum ratio short-float)
+                         (with-stack-double-floats ((fdiv divisor)
+                                                    (f2))
+                           (let ((res (%unary-truncate (%double-float/-2! number fdiv f2))))
+                             (values res 
+                                     (%double-float--2 
+                                      number 
+                                      (%double-float*-2! (%double-float res f2) fdiv f2))))))                        
+                        (double-float
+                         (with-stack-double-floats ((f2))
+                           (let ((res (%unary-truncate (%double-float/-2! number divisor f2))))
+                             (values res 
+                                     (%double-float--2
+                                      number 
+                                      (%double-float*-2! (%double-float res f2) divisor f2)))))))))
+      (ratio (number-case divisor
+               (double-float (truncate-rat-dfloat number divisor))
+               (short-float (truncate-rat-sfloat number divisor))
+               (rational
+                (let ((q (truncate (%numerator number)
+                                   (* (%denominator number) divisor))))
+                  (values q (- number (* q divisor))))))))))
+
+(defun truncate-no-rem (number  divisor)
+  "Returns number (or number/divisor) as an integer, rounded toward 0."
+  (macrolet 
+    ((truncate-rat-dfloat (number divisor)
+       `(with-stack-double-floats ((fnum ,number)
+                                      (f2))
+         (%unary-truncate (%double-float/-2! fnum ,divisor f2))))
+     (truncate-rat-sfloat (number divisor)
+       #+32-bit-target
+       `(target::with-stack-short-floats ((fnum ,number)
+                                      (f2))
+         (%unary-truncate (%short-float/-2! fnum ,divisor f2)))
+       #+64-bit-target
+       `(let ((fnum (%short-float ,number)))
+         (%unary-truncate (/ (the short-float fnum)
+                           (the short-float ,divisor))))))
+    (number-case number
+    (fixnum
+     (if (eql number target::target-most-negative-fixnum)
+       (if (zerop divisor)
+         (error 'division-by-zero :operation 'truncate :operands (list number divisor))
+         (with-small-bignum-buffers ((bn number))
+           (let* ((result (truncate-no-rem bn divisor)))
+             (if (eq result bn)
+               number
+               result))))
+       (number-case divisor
+         (fixnum (if (eq divisor 1) number (values (%fixnum-truncate number divisor))))
+         (bignum 0)
+         (double-float (truncate-rat-dfloat number divisor))
+         (short-float (truncate-rat-sfloat number divisor))
+         (ratio (let ((q (truncate (* number (%denominator divisor))
+                                   (%numerator divisor))))
+                  q)))))
+     (bignum (number-case divisor
+               (fixnum (if (eq divisor 1) number
+                         (if (eq divisor target::target-most-negative-fixnum)
+                           (with-small-bignum-buffers ((bd divisor))
+                             (bignum-truncate number bd :no-rem))
+                           (bignum-truncate-by-fixnum number divisor))))
+               (bignum (bignum-truncate number divisor :no-rem))
+               (double-float  (truncate-rat-dfloat number divisor))
+               (short-float (truncate-rat-sfloat number divisor))
+               (ratio (let ((q (truncate (* number (%denominator divisor))
+                                         (%numerator divisor))))
+                        Q))))
+     (double-float (if (eql divisor 1)
+                     (let ((res (%unary-truncate number)))
+                       RES)
+                     (number-case divisor
+                       ((fixnum bignum ratio)
+                        (with-stack-double-floats ((fdiv divisor)
+                                                   (f2))
+                          (let ((res (%unary-truncate (%double-float/-2! number fdiv f2))))
+                            RES)))
+                       (short-float
+                        (with-stack-double-floats ((ddiv divisor)
+                                                   (f2))
+                          (%unary-truncate (%double-float/-2! number ddiv f2))))
+                       (double-float
+                        (with-stack-double-floats ((f2))
+                          (%unary-truncate (%double-float/-2! number divisor f2)))))))
+     (short-float (if (eql divisor 1)
+                    (let ((res (%unary-truncate number)))
+                      RES)
+                    (number-case divisor
+                      ((fixnum bignum ratio)
+                       #+32-bit-target
+                       (target::with-stack-short-floats ((fdiv divisor)
+                                                 (f2))
+                         (let ((res (%unary-truncate (%short-float/-2! number fdiv f2))))
+                           RES))
+                       #+64-bit-target
+                       (%unary-truncate (/ (the short-float number)
+                                           (the short-float (%short-float divisor)))))
+                      (short-float
+                       #+32-bit-target
+                       (target::with-stack-short-floats ((ddiv divisor)
+                                                      (f2))
+                         (%unary-truncate (%short-float/-2! number ddiv f2)))
+                       #+64-bit-target
+                       (%unary-truncate (/ (the short-float number)
+                                           (the short-float (%short-float divisor)))))
+                      (double-float
+                       (with-stack-double-floats ((n2 number)
+						      (f2))
+                         (%unary-truncate (%double-float/-2! n2 divisor f2)))))))
+    (ratio (number-case divisor
+                  (double-float (truncate-rat-dfloat number divisor))
+                  (short-float (truncate-rat-sfloat number divisor))
+                  (rational
+                   (let ((q (truncate (%numerator number)
+                                      (* (%denominator number) divisor))))
+                     Q)))))))
+
+
+;;; %UNARY-ROUND  --  Interface
+;;;
+;;;    Similar to %UNARY-TRUNCATE, but rounds to the nearest integer.  If we
+;;; can't use the round primitive, then we do our own round-to-nearest on the
+;;; result of i-d-f.  [Note that this rounding will really only happen with
+;;; double floats, since the whole single-float fraction will fit in a fixnum,
+;;; so all single-floats larger than most-positive-fixnum can be precisely
+;;; represented by an integer.]
+;;;
+;;; returns both values today
+
+(defun %unary-round (number)
+  (number-case number
+    (integer (values number 0))
+    (ratio (let ((q (round (%numerator number) (%denominator number))))             
+             (values q (- number q))))
+    (double-float
+     (if (and (< (the double-float number) 
+                 (float (1- (ash 1 (- (1- target::nbits-in-word) target::fixnumshift))) 1.0d0))
+              (< (float (ash -1 (- (1- target::nbits-in-word) target::fixnumshift)) 1.0d0)
+                 (the double-float number)))
+       (let ((round (%unary-round-to-fixnum number)))
+         (values round (- number round)))
+       (multiple-value-bind (trunc rem) (truncate number)         
+         (if (not (%double-float-minusp number))
+           (if (or (> rem 0.5d0)(and (= rem 0.5d0) (oddp trunc)))
+             (values (+ trunc 1) (- rem 1.0d0))
+             (values trunc rem))
+           (if (or (> rem -0.5d0)(and (evenp trunc)(= rem -0.5d0)))
+             (values trunc rem)
+             (values (1- trunc) (+ 1.0d0 rem)))))))
+    (short-float
+     (if (and (< (the short-float number) 
+                 (float (1- (ash 1 (- (1- target::nbits-in-word) target::fixnumshift))) 1.0s0))
+              (< (float (ash -1 (- (1- target::nbits-in-word) target::fixnumshift)) 1.0s0)
+                 (the double-float number)))
+       (let ((round (%unary-round-to-fixnum number)))
+         (values round (- number round)))
+       (multiple-value-bind (trunc rem) (truncate number)         
+         (if (not (%short-float-minusp number))
+           (if (or (> rem 0.5s0)(and (= rem 0.5s0) (oddp trunc)))
+             (values (+ trunc 1) (- rem 1.0s0))
+             (values trunc rem))
+           (if (or (> rem -0.5s0)(and (evenp trunc)(= rem -0.5s0)))
+             (values trunc rem)
+             (values (1- trunc) (+ 1.0s0 rem)))))))))
+
+(defun %unary-round-to-fixnum (number)
+  (number-case number
+    (double-float
+     (%round-nearest-double-float->fixnum number))
+    (short-float
+     (%round-nearest-short-float->fixnum number))))
+
+                         
+                                
+         
+; cmucl:compiler:float-tran.lisp
+#|
+(defun xform-round (x)
+  (let ((res (%unary-round x)))
+    (values res (- x res))))
+|#
+
+#|
+(defun round (number &optional divisor)
+  "Rounds number (or number/divisor) to nearest integer.
+  The second returned value is the remainder."
+  (if (null divisor)(setq divisor 1))
+  (if (eql divisor 1)
+    (xform-round number)
+    (multiple-value-bind (tru rem) (truncate number divisor)
+      (let ((thresh (if (integerp divisor) (ash (abs divisor) -1)(/ (abs divisor) 2)))) ; does this need to be a ratio?
+        (cond ((or (> rem thresh)
+                   (and (= rem thresh) (oddp tru)))
+               (if (minusp divisor)
+                 (values (- tru 1) (+ rem divisor))
+                 (values (+ tru 1) (- rem divisor))))
+              ((let ((-thresh (- thresh)))
+                 (or (< rem -thresh)
+                     (and (= rem -thresh) (oddp tru))))
+               (if (minusp divisor)
+                 (values (+ tru 1) (- rem divisor))
+                 (values (- tru 1) (+ rem divisor))))
+              (t (values tru rem)))))))
+|#
+
+
+(defun %fixnum-round (number divisor)
+  (declare (fixnum number divisor))
+  (multiple-value-bind (quo rem)(truncate number divisor) ; should => %fixnum-truncate
+    (if (= 0 rem)
+      (values quo rem)
+      (locally (declare (fixnum quo rem))
+        (let* ((minusp-num (minusp number))
+               (minusp-div (minusp divisor))
+               (2rem (* rem (if (neq minusp-num minusp-div) -2 2))))
+          ;(declare (fixnum 2rem)) ; no way jose  
+          ;(truncate (1- most-positive-fixnum) most-positive-fixnum)
+          ; 2rem has same sign as divisor
+          (cond (minusp-div              
+                 (if (or (< 2rem divisor)
+                         (and (= 2rem divisor)(logbitp 0 quo)))
+                   (if minusp-num
+                     (values (the fixnum (+ quo 1))(the fixnum (- rem divisor)))
+                     (values (the fixnum (- quo 1))(the fixnum (+ rem divisor))))
+                   (values quo rem)))
+                (t (if (or (> 2rem divisor)
+                           (and (= 2rem divisor)(logbitp 0 quo)))
+                     (if minusp-num
+                       (values (the fixnum (- quo 1))(the fixnum (+ rem divisor)))
+                       (values (the fixnum (+ quo 1))(the fixnum (- rem divisor))))
+                     (values quo rem)))))))))
+#|
+; + + => + +
+; + - => - +
+; - + => - -
+; - - => + -
+(defun %fixnum-round (number divisor)
+  (declare (fixnum number divisor))
+  "Rounds number (or number/divisor) to nearest integer.
+  The second returned value is the remainder."
+  (if (eq divisor 1)
+    (values number 0)
+    (multiple-value-bind (tru rem) (truncate number divisor)
+      (if (= 0 rem)
+        (values tru rem)
+        (locally (declare (fixnum tru rem))
+          (let* ((minusp-num (minusp number))
+                 (minusp-div (minusp divisor))
+                 (half-div (ash (if minusp-div (- divisor) divisor) -1))
+                 (abs-rem (if minusp-num (- rem) rem)))           
+            (declare (fixnum half-div abs-rem)) ; true of abs-rem?
+            (if (or (> abs-rem half-div)
+                    (and 
+                     (not (logbitp 0 divisor))
+                     (logbitp 0 tru) ; oddp
+                     (= abs-rem half-div)))
+              (if (eq minusp-num minusp-div)
+                (values (the fixnum (+ tru 1))(the fixnum (- rem divisor)))
+                (values (the fixnum (- tru 1))(the fixnum (+ rem divisor))))
+              (values tru rem))))))))
+|#
+
+
+
+;; makes 1 piece of garbage instead of average of 2
+(defun round (number &optional divisor)
+  "Rounds number (or number/divisor) to nearest integer.
+  The second returned value is the remainder."
+  (if (null divisor)(setq divisor 1))
+  (if (eql divisor 1)
+    (%unary-round number)
+    (multiple-value-bind (tru rem) (truncate number divisor)
+      (if (= 0 rem)
+        (values tru rem)
+        (let* ((mv-p (called-for-mv-p))
+               (minusp-num (minusp number))
+               (minusp-div (minusp divisor))
+               (2rem (* rem (if (neq minusp-num minusp-div) -2 2))))
+          ; 2rem has same sign as divisor
+          (cond (minusp-div              
+                 (if (or (< 2rem divisor)
+                         (and (= 2rem divisor)(oddp tru)))
+                   (if mv-p
+                     (if minusp-num
+                       (values (+ tru 1)(- rem divisor))
+                       (values (- tru 1)(+ rem divisor)))
+                     (if minusp-num (+ tru 1)(- tru 1)))
+                   (values tru rem)))
+                (t (if (or (> 2rem divisor)
+                           (and (= 2rem divisor)(oddp tru)))
+                     (if mv-p
+                       (if minusp-num
+                         (values (- tru 1)(+ rem divisor))
+                         (values (+ tru 1)(- rem divisor)))
+                       (if minusp-num (- tru 1)(+ tru 1)))
+                     (values tru rem)))))))))
+
+
+;; #-PPC IN L1-NUMBERS.LISP (or implement %%numdiv)
+;; Anyone caught implementing %%numdiv will be summarily executed.
+(defun rem (number divisor)
+  "Returns second result of TRUNCATE."
+  (number-case number
+    (fixnum
+     (number-case divisor
+       (fixnum (nth-value 1 (%fixnum-truncate number divisor)))
+       (bignum number)
+       (t (nth-value 1 (truncate number divisor)))))
+    (bignum
+     (number-case divisor
+       (fixnum
+        (if (eq divisor target::target-most-negative-fixnum)
+          (nth-value 1 (truncate number divisor))
+          (bignum-truncate-by-fixnum-no-quo number divisor)))
+       (bignum
+        (bignum-rem number divisor))
+       (t (nth-value 1 (truncate number divisor)))))
+    (t (nth-value 1 (truncate number divisor)))))
+
+;; #-PPC IN L1-NUMBERS.LISP (or implement %%numdiv)
+;; See above.
+(defun mod (number divisor)
+  "Returns second result of FLOOR."
+  (let ((rem (rem number divisor)))
+    (if (and (not (zerop rem))
+	     (if (minusp divisor)
+		 (plusp number)
+		 (minusp number)))
+	(+ rem divisor)
+	rem)))
+
+(defun cis (theta)
+  "Return cos(Theta) + i sin(Theta), i.e. exp(i Theta)."
+  (if (complexp theta)
+    (error "Argument to CIS is complex: ~S" theta)
+    (complex (cos theta) (sin theta))))
+
+
+(defun complex (realpart &optional (imagpart 0))
+  "Return a complex number with the specified real and imaginary components."
+  (number-case realpart
+    (short-float
+      (number-case imagpart
+         (short-float (canonical-complex realpart imagpart))
+         (double-float (canonical-complex (%double-float realpart) imagpart))
+         (rational (canonical-complex realpart (%short-float imagpart)))))
+    (double-float 
+     (number-case imagpart
+       (double-float (canonical-complex
+                      (the double-float realpart)
+                      (the double-float imagpart)))
+       (short-float (canonical-complex realpart (%double-float imagpart)))
+       (rational (canonical-complex
+                              (the double-float realpart)
+                              (the double-float (%double-float imagpart))))))
+    (rational (number-case imagpart
+                (double-float (canonical-complex
+                               (the double-float (%double-float realpart))
+                               (the double-float imagpart)))
+                (short-float (canonical-complex (%short-float realpart) imagpart))
+                (rational (canonical-complex realpart imagpart))))))  
+
+;; #-PPC IN L1-NUMBERS.LISP
+(defun realpart (number)
+  "Extract the real part of a number."
+  (number-case number
+    (complex (%realpart number))
+    (number number)))
+
+;; #-PPC IN L1-NUMBERS.LISP
+(defun imagpart (number)
+  "Extract the imaginary part of a number."
+  (number-case number
+    (complex (%imagpart number))
+    (float (* 0 number))
+    (rational 0)))
+
+(defun logand-2 (x y)  
+  (number-case x
+    (fixnum (number-case y
+              (fixnum
+               (%ilogand (the fixnum x)(the fixnum y)))
+              (bignum (fix-big-logand x y))))
+    (bignum (number-case y
+              (fixnum (fix-big-logand y x))
+              (bignum (bignum-logical-and x y))))))
+
+(defun logior-2 (x y)
+  (number-case x
+    (fixnum (number-case y
+              (fixnum (%ilogior2 x y))
+              (bignum
+               (if (zerop x)
+                 y
+                 (with-small-bignum-buffers ((bx x))
+                   (bignum-logical-ior bx y))))))
+    (bignum (number-case y
+              (fixnum (if (zerop y)
+                        x
+                        (with-small-bignum-buffers ((by y))
+                          (bignum-logical-ior x by))))
+              (bignum (bignum-logical-ior x y))))))
+
+(defun logxor-2 (x y)
+  (number-case x
+    (fixnum (number-case y
+              (fixnum (%ilogxor2 x y))
+              (bignum
+               (with-small-bignum-buffers ((bx x))
+                 (bignum-logical-xor bx y)))))
+    (bignum (number-case y
+              (fixnum (with-small-bignum-buffers ((by y))
+                        (bignum-logical-xor x by)))
+              (bignum (bignum-logical-xor x y))))))
+
+               
+
+; see cmucl:compiler:srctran.lisp for transforms
+
+(defun lognand (integer1 integer2)
+  "Complement the logical AND of INTEGER1 and INTEGER2."
+  (lognot (logand integer1 integer2)))
+
+(defun lognor (integer1 integer2)
+  "Complement the logical AND of INTEGER1 and INTEGER2."
+  (lognot (logior integer1 integer2)))
+
+(defun logandc1 (x y)
+  "Return the logical AND of (LOGNOT integer1) and integer2."
+  (number-case x
+    (fixnum (number-case y               
+              (fixnum (%ilogand (%ilognot x) y))
+              (bignum  (fix-big-logandc1 x y))))    ; (%ilogand-fix-big (%ilognot x) y))))
+    (bignum (number-case y
+              (fixnum  (fix-big-logandc2 y x))      ; (%ilogandc2-fix-big y x))
+              (bignum (bignum-logandc2 y x))))))    ;(bignum-logical-and (bignum-logical-not x)  y))))))
+
+
+#| ; its in numbers
+(defun logandc2 (integer1 integer2)
+  "Returns the logical AND of integer1 and (LOGNOT integer2)."
+  (logand integer1 (lognot integer2)))
+|#
+
+(defun logorc1 (integer1 integer2)
+  "Return the logical OR of (LOGNOT integer1) and integer2."
+  (logior (lognot integer1) integer2))
+
+#|
+(defun logorc2 (integer1 integer2)
+  "Returns the logical OR of integer1 and (LOGNOT integer2)."
+  (logior integer1 (lognot integer2)))
+|#
+
+(defun logtest (integer1 integer2)
+  "Predicate which returns T if logand of integer1 and integer2 is not zero."
+ ; (not (zerop (logand integer1 integer2)))
+  (number-case integer1
+    (fixnum (number-case integer2
+              (fixnum (not (= 0 (%ilogand integer1 integer2))))
+              (bignum (logtest-fix-big integer1 integer2))))
+    (bignum (number-case integer2
+              (fixnum (logtest-fix-big integer2 integer1))
+              (bignum (bignum-logtest integer1 integer2)))))) 
+
+
+
+(defun lognot (number)
+  "Return the bit-wise logical not of integer."
+  (number-case number
+    (fixnum (%ilognot number))
+    (bignum (bignum-logical-not number))))
+
+(defun logcount (integer)
+  "Count the number of 1 bits if INTEGER is positive, and the number of 0 bits
+  if INTEGER is negative."
+  (number-case integer
+    (fixnum
+     (%ilogcount (if (minusp (the fixnum integer))
+                   (%ilognot integer)
+                   integer)))
+    (bignum
+     (bignum-logcount integer))))
+
+
+
+(defun ash (integer count)
+  "Shifts integer left by count places preserving sign. - count shifts right."
+  (etypecase integer
+    (fixnum
+     (etypecase count
+       (fixnum
+	(if (eql integer 0)
+	  0
+	  (if (eql count 0)
+	    integer
+	    (let ((length (integer-length (the fixnum integer))))
+	      (declare (fixnum length count))
+	      (cond ((and (plusp count)
+			  (> (+ length count)
+			     (- (1- target::nbits-in-word) target::fixnumshift)))
+		     (with-small-bignum-buffers ((bi integer))
+		       (bignum-ashift-left bi count)))
+		    ((and (minusp count) (< count (- (1- target::nbits-in-word))))
+		     (if (minusp integer) -1 0))
+		    (t (%iash (the fixnum integer) count)))))))
+       (bignum
+	(if (minusp count)
+	  (if (minusp integer) -1 0)          
+	  (error "Count ~s too large for ASH" count)))))
+    (bignum
+     (etypecase count
+       (fixnum
+        (if (eql count 0) 
+          integer
+          (if (plusp count)
+            (bignum-ashift-left integer count)
+            (bignum-ashift-right integer (- count)))))
+       (bignum
+        (if (minusp count)
+          (if (minusp integer) -1 0)
+          (error "Count ~s too large for ASH" count)))))))
+
+(defun integer-length (integer)
+  "Return the number of significant bits in the absolute value of integer."
+  (number-case integer
+    (fixnum
+     (%fixnum-intlen (the fixnum integer)))
+    (bignum
+     (bignum-integer-length integer))))
+
+
+; not CL, used below
+(defun byte-mask (size)
+  (1- (ash 1 (the fixnum size))))
+
+(defun byte-position (bytespec)
+  "Return the position part of the byte specifier bytespec."
+  (if (> bytespec 0)
+    (- (integer-length bytespec) (logcount bytespec))
+    (- bytespec)))
+
+
+; CMU CL returns T.
+(defun upgraded-complex-part-type (type)
+  "Return the element type of the most specialized COMPLEX number type that
+   can hold parts of type SPEC."
+  (declare (ignore type))
+  'real)
+
+
+
+(defun init-random-state-seeds ()
+  (let* ((ticks (ldb (byte 32 0) (+ (mixup-hash-code (%current-tcr))
+                                    (let* ((iface(primary-ip-interface)))
+                                      (or (and iface (ip-interface-addr iface))
+                                          0))
+                                    (mixup-hash-code
+                                     (logand (get-internal-real-time)
+                                             (1- target::target-most-positive-fixnum))))))
+	 (high (ldb (byte 16 16) (if (zerop ticks) #x10000 ticks)))
+	 (low (ldb (byte 16 0) ticks)))
+    (declare (fixnum high low))
+    (values high low)))
+
+
+#+32-bit-target
+(defun random (number &optional (state *random-state*))
+  (if (not (typep state 'random-state)) (report-bad-arg state 'random-state))
+  (cond
+     ((and (fixnump number) (> (the fixnum number) 0))
+      (locally (declare (fixnum number))
+        (if (< number 65536)
+          (fast-mod (%next-random-seed state) number)
+          (let* ((n 0)
+                 (nhalf (ash (+ 15 (integer-length number)) -4)))
+            (declare (fixnum n nhalf))
+            (dotimes (i nhalf (fast-mod n number))
+              (setq n (logior (the fixnum (ash n 16))
+                              (the fixnum (%next-random-seed state)))))))))
+     ((and (typep number 'double-float) (> (the double-float number) 0.0))
+      (%float-random number state))
+     ((and (typep number 'short-float) (> (the short-float number) 0.0s0))
+      (%float-random number state))
+     ((and (bignump number) (> number 0))
+      (%bignum-random number state))
+     (t (report-bad-arg number '(or (integer (0)) (float (0.0)))))))
+
+#+64-bit-target
+(defun random (number &optional (state *random-state*))
+  (if (not (typep state 'random-state)) (report-bad-arg state 'random-state))
+  (cond
+    ((and (fixnump number) (> (the fixnum number) 0))
+     (locally (declare (fixnum number))
+       (let* ((n 0)
+              (n32 (ash (+ 31 (integer-length number)) -5)))
+         (declare (fixnum n n32))
+         (dotimes (i n32 (fast-mod n number))
+           (setq n (logior (the fixnum (ash n 32))
+                           (the fixnum (%next-random-seed state))))))))
+    ((and (typep number 'double-float) (> (the double-float number) 0.0))
+     (%float-random number state))
+    ((and (typep number 'short-float) (> (the short-float number) 0.0s0))
+     (%float-random number state))
+    ((and (bignump number) (> number 0))
+     (%bignum-random number state))
+    (t (report-bad-arg number '(or (integer (0)) (float (0.0)))))))
+
+
+#|
+Date: Mon, 3 Feb 1997 10:04:08 -0500
+To: info-mcl@digitool.com, wineberg@franz.scs.carleton.ca
+From: dds@flavors.com (Duncan Smith)
+Subject: Re: More info on the random number generator
+Sender: owner-info-mcl@digitool.com
+Precedence: bulk
+
+The generator is a Linear Congruential Generator:
+
+   X[n+1] = (aX[n] + c) mod m
+
+where: a = 16807  (Park&Miller recommend 48271)
+       c = 0
+       m = 2^31 - 1
+
+See: Knuth, Seminumerical Algorithms (Volume 2), Chapter 3.
+
+The period is: 2^31 - 2  (zero is excluded).
+
+What makes this generator so simple is that multiplication and addition mod
+2^n-1 is easy.  See Knuth Ch. 4.3.2 (2nd Ed. p 272).
+
+    ab mod m = ...
+
+If         m = 2^n-1
+           u = ab mod 2^n
+           v = floor( ab / 2^n )
+
+    ab mod m = u + v                   :  u+v < 2^n
+    ab mod m = ((u + v) mod 2^n) + 1   :  u+v >= 2^n
+
+What we do is use 2b and 2^n so we can do arithemetic mod 2^32 instead of
+2^31.  This reduces the whole generator to 5 instructions on the 680x0 or
+80x86, and 8 on the 60x.
+
+-Duncan
+
+|#
+
+#+64-bit-target
+(defun %next-random-seed (state)
+  (let* ((n (the fixnum (* (the fixnum (random.seed-1 state)) 48271))))
+    (declare (fixnum n))
+    (setf (random.seed-1 state) (fast-mod n (1- (expt 2 31))))
+    (logand n (1- (ash 1 32)))))
+
+#+32-bit-target
+(defun %next-random-seed (state)
+  (multiple-value-bind (high low) (%next-random-pair (random.seed-1 state)
+                                                     (random.seed-2 state))
+    (declare (type (unsigned-byte 15) high)
+             (type (unsigned-byte 16) low))
+    (setf (random.seed-1 state) high
+          (random.seed-2 state) low)
+    (logior high (the fixnum (logand low (ash 1 15))))))
+
+#+32-bit-target
+(defun %bignum-random (number state)
+  (let* ((bits (+ (integer-length number) 8))
+         (half-words (ash (the fixnum (+ bits 15)) -4))
+         (long-words (ash (+ half-words 1) -1))
+         (dividend (%alloc-misc long-words target::subtag-bignum))
+         (16-bit-dividend dividend)
+         (index 1))
+    (declare (fixnum long-words index bits)
+             (dynamic-extent dividend)
+             (type (simple-array (unsigned-byte 16) (*)) 16-bit-dividend) ;lie
+             (optimize (speed 3) (safety 0)))
+    (loop
+       ;; This had better inline due to the lie above, or it will error
+       #+big-endian-target
+       (setf (aref 16-bit-dividend index) (%next-random-seed state))
+       #+little-endian-target
+       (setf (aref 16-bit-dividend (the fixnum (1- index)))
+	     (%next-random-seed state))
+       (decf half-words)
+       (when (<= half-words 0) (return))
+       #+big-endian-target
+       (setf (aref 16-bit-dividend (the fixnum (1- index)))
+	     (%next-random-seed state))
+       #+little-endian-target
+       (setf (aref 16-bit-dividend index) (%next-random-seed state))
+       (decf half-words)
+       (when (<= half-words 0) (return))
+       (incf index 2))
+    ;; The bignum code expects normalized bignums
+    (let* ((result (mod dividend number)))
+      (if (eq dividend result)
+	(copy-uvector result)
+	result))))
+
+(defun %float-random (number state)
+  (let ((ratio (gvector :ratio (random target::target-most-positive-fixnum state) target::target-most-positive-fixnum)))
+    (declare (dynamic-extent ratio))
+    (* number ratio)))
+
+(eval-when (:compile-toplevel :execute)
+  (defmacro bignum-abs (nexp)
+    (let ((n (gensym)))
+      `(let ((,n ,nexp))
+         (if  (bignum-minusp ,n) (negate-bignum ,n) ,n))))
+  
+  (defmacro fixnum-abs (nexp)
+    (let ((n (gensym)))
+      `(let ((,n ,nexp))
+         (if (minusp (the fixnum ,n))
+           (if (eq ,n target::target-most-negative-fixnum)
+             (- ,n)
+             (the fixnum (- (the fixnum ,n))))
+           ,n))))
+  )
+  
+
+;;; TWO-ARG-GCD  --  Internal
+;;;
+;;;    Do the GCD of two integer arguments.  With fixnum arguments, we use the
+;;; binary GCD algorithm from Knuth's seminumerical algorithms (slightly
+;;; structurified), otherwise we call BIGNUM-GCD.  We pick off the special case
+;;; of 0 before the dispatch so that the bignum code doesn't have to worry
+;;; about "small bignum" zeros.
+;;;
+(defun gcd-2 (n1 n2)
+  ;(declare (optimize (speed 3)(safety 0)))
+  (cond 
+   ((eql n1 0) (%integer-abs n2))
+   ((eql n2 0) (%integer-abs n1))
+   (t (number-case n1
+        (fixnum 
+         (number-case n2
+          (fixnum
+	   (if (eql n1 target::target-most-negative-fixnum)
+	     (if (eql n2 target::target-most-negative-fixnum)
+	       (- target::target-most-negative-fixnum)
+	       (bignum-fixnum-gcd (- target::target-most-negative-fixnum) (abs n2)))
+	     (if (eql n2 target::target-most-negative-fixnum)
+	       (bignum-fixnum-gcd (- target::target-most-negative-fixnum) (abs n1))
+	       (locally
+		   (declare (optimize (speed 3) (safety 0))
+			    (fixnum n1 n2))
+		 (if (minusp n1)(setq n1 (the fixnum (- n1))))
+		 (if (minusp n2)(setq n2 (the fixnum (- n2))))
+               (%fixnum-gcd n1 n2)))))
+           (bignum (if (eql n1 target::target-most-negative-fixnum)
+		     (%bignum-bignum-gcd n2 (- target::target-most-negative-fixnum))
+		     (bignum-fixnum-gcd (bignum-abs n2)(fixnum-abs n1))))))
+	(bignum
+	 (number-case n2
+	   (fixnum
+            (if (eql n2 target::target-most-negative-fixnum)
+              (%bignum-bignum-gcd (bignum-abs n1)(fixnum-abs n2))
+              (bignum-fixnum-gcd (bignum-abs n1)(fixnum-abs n2))))
+	   (bignum (%bignum-bignum-gcd n1 n2))))))))
+
+#|
+(defun fixnum-gcd (n1 n2)
+  (declare (optimize (speed 3) (safety 0))
+           (fixnum n1 n2))                    
+  (do* ((k 0 (%i+ 1 k))
+        (n1 n1 (%iasr 1 n1))
+        (n2 n2 (%iasr 1 n2)))
+       ((oddp (logior n1 n2))
+        (do ((temp (if (oddp n1) (the fixnum (- n2)) (%iasr 1 n1))
+                   (%iasr 1 temp)))
+            (nil)
+          (declare (fixnum temp))
+          (when (oddp temp)
+            (if (plusp temp)
+              (setq n1 temp)
+              (setq n2 (- temp)))
+            (setq temp (the fixnum (- n1 n2)))
+            (when (zerop temp)
+              (let ((res (%ilsl k n1)))
+                (return res))))))
+    (declare (fixnum n1 n2 k))))
+|#
+
+
+
+(defun %quo-1 (n)
+  (/ 1 n))
+
+; x & y must both be double floats
+(defun %hypot (x y)
+  (with-stack-double-floats ((x**2) (y**2))
+    (let ((res**2 x**2))
+      (%double-float*-2! x x x**2)
+      (%double-float*-2! y y y**2)
+      (%double-float+-2! x**2 y**2 res**2)
+      (fsqrt res**2))))
+
+
Index: /branches/new-random/level-0/l0-pred.lisp
===================================================================
--- /branches/new-random/level-0/l0-pred.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-pred.lisp	(revision 13309)
@@ -0,0 +1,1115 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;; Non-portable type-predicates & such.
+
+
+;; bootstrapping defs - real ones in l1-typesys, l1-clos, sysutils
+
+(defun find-builtin-cell (type &optional create)
+  (declare (ignore create))
+  (cons type nil))
+
+
+(defun builtin-typep (form cell)
+  (typep form (class-cell-name cell)))
+
+(defun class-cell-typep (arg class-cell)
+  (typep arg (class-cell-name class-cell)))
+
+(defun class-cell-find-class (class-cell errorp)
+  (declare (ignore errorp)) ; AARGH can't be right
+  ;(dbg-paws #x100)
+  (let ((class (and class-cell (class-cell-class class-cell))))
+    (or class 
+        (if  (fboundp 'find-class)
+          (find-class (class-cell-name class-cell) nil)))))
+
+(defun %require-type-builtin (form foo)
+  (declare (ignore foo))
+  form)
+
+(defun %require-type-class-cell (form cell)
+  (declare (ignore cell))
+  form)
+  
+(defun non-nil-symbol-p (x)
+  (if (symbolp x) x))
+
+(defun pathnamep (thing)
+  (or (istruct-typep thing 'pathname) (istruct-typep thing 'logical-pathname)))
+
+(defun compiled-function-p (form)
+  "Return true if OBJECT is a COMPILED-FUNCTION, and NIL otherwise."
+  (and (functionp form)
+       (not (logbitp $lfbits-trampoline-bit (the fixnum (lfun-bits form))))))
+
+;;; all characters are base-chars.
+(defun extended-char-p (c)
+  (declare (ignore c)))
+
+
+;;; Some of these things are probably open-coded.
+;;; The functions have to exist SOMEWHERE ...
+(defun fixnump (x)
+  (= (the fixnum (lisptag x)) target::tag-fixnum))
+
+(defun bignump (x)
+  (= (the fixnum (typecode x)) target::subtag-bignum))
+
+(defun integerp (x)
+  "Return true if OBJECT is an INTEGER, and NIL otherwise."
+  (let* ((typecode (typecode x)))
+    (declare (fixnum typecode))
+    (or (= typecode target::tag-fixnum)
+        (= typecode target::subtag-bignum))))
+
+(defun ratiop (x)
+  (= (the fixnum (typecode x)) target::subtag-ratio))
+
+
+(defun rationalp (x)
+  "Return true if OBJECT is a RATIONAL, and NIL otherwise."
+  (or (fixnump x)
+      (let* ((typecode (typecode x)))
+        (declare (fixnum typecode))
+        #+(or ppc32-target x8632-target)
+        (and (>= typecode target::min-numeric-subtag)
+             (<= typecode target::max-rational-subtag))
+        #+(or ppc64-target x8664-target)
+        (cond ((= typecode target::subtag-bignum) t)
+              ((= typecode target::subtag-ratio) t)))))
+
+(defun short-float-p (x)
+  (= (the fixnum (typecode x)) target::subtag-single-float))
+
+
+(defun double-float-p (x)
+  (= (the fixnum (typecode x)) target::subtag-double-float))
+
+(defun floatp (x)
+  "Return true if OBJECT is a FLOAT, and NIL otherwise."
+  (let* ((typecode (typecode x)))
+    (declare (fixnum typecode))
+    (or (= typecode target::subtag-single-float)
+        (= typecode target::subtag-double-float))))
+
+(defun realp (x)
+  "Return true if OBJECT is a REAL, and NIL otherwise."
+  (let* ((typecode (typecode x)))
+    (declare (fixnum typecode))
+    #+(or ppc32-target x8632-target)
+    (or (= typecode target::tag-fixnum)
+        (and (>= typecode target::min-numeric-subtag)
+             (<= typecode target::max-real-subtag)))
+    #+ppc64-target
+    (if (<= typecode ppc64::subtag-double-float)
+      (logbitp (the (integer 0 #.ppc64::subtag-double-float) typecode)
+               (logior (ash 1 ppc64::tag-fixnum)
+                       (ash 1 ppc64::subtag-single-float)
+                       (ash 1 ppc64::subtag-double-float)
+                       (ash 1 ppc64::subtag-bignum)
+                       (ash 1 ppc64::subtag-ratio))))
+    #+x8664-target
+    (if (<= typecode x8664::subtag-double-float)
+      (logbitp (the (integer 0 #.x8664::subtag-double-float) typecode)
+               (logior (ash 1 x8664::tag-fixnum)
+                       (ash 1 x8664::subtag-bignum)
+                       (ash 1 x8664::tag-single-float)
+                       (ash 1 x8664::subtag-double-float)
+                       (ash 1 x8664::subtag-ratio))))))
+
+(defun complexp (x)
+  "Return true if OBJECT is a COMPLEX, and NIL otherwise."
+  (= (the fixnum (typecode x)) target::subtag-complex))
+
+(defun numberp (x)
+  "Return true if OBJECT is a NUMBER, and NIL otherwise."
+  (let* ((typecode (typecode x)))
+    (declare (fixnum typecode))
+    #+(or ppc32-target x8632-target)
+    (or (= typecode target::tag-fixnum)
+        (and (>= typecode target::min-numeric-subtag)
+             (<= typecode target::max-numeric-subtag)))
+    #+ppc64-target
+    (if (<= typecode ppc64::subtag-double-float)
+      (logbitp (the (integer 0 #.ppc64::subtag-double-float) typecode)
+               (logior (ash 1 ppc64::tag-fixnum)
+                       (ash 1 ppc64::subtag-bignum)
+                       (ash 1 ppc64::subtag-single-float)
+                       (ash 1 ppc64::subtag-double-float)
+                       (ash 1 ppc64::subtag-ratio)
+                       (ash 1 ppc64::subtag-complex))))
+    #+x8664-target
+    (if (< typecode x8664::nbits-in-word)
+      (logbitp (the (integer 0 #.x8664::subtag-double-float) typecode)
+               (logior (ash 1 x8664::tag-fixnum)
+                       (ash 1 x8664::subtag-bignum)
+                       (ash 1 x8664::tag-single-float)
+                       (ash 1 x8664::subtag-double-float)
+                       (ash 1 x8664::subtag-ratio)
+                       (ash 1 x8664::subtag-complex))))
+    
+    ))
+
+(defun arrayp (x)
+  "Return true if OBJECT is an ARRAY, and NIL otherwise."
+  (>= (the fixnum (typecode x)) target::min-array-subtag))
+
+(defun vectorp (x)
+  "Return true if OBJECT is a VECTOR, and NIL otherwise."
+  (>= (the fixnum (typecode x)) target::min-vector-subtag))
+
+
+(defun stringp (x)
+  "Return true if OBJECT is a STRING, and NIL otherwise."
+  (let* ((typecode (typecode x)))
+    (declare (fixnum typecode))
+    (if (= typecode target::subtag-vectorH)
+      (setq typecode (ldb target::arrayH.flags-cell-subtag-byte (the fixnum (%svref x target::arrayH.flags-cell)))))
+    (= typecode target::subtag-simple-base-string)))
+
+
+(defun simple-base-string-p (x)
+  (= (the fixnum (typecode x)) target::subtag-simple-base-string))
+
+(defun simple-string-p (x)
+  "Return true if OBJECT is a SIMPLE-STRING, and NIL otherwise."
+  (= (the fixnum (typecode x)) target::subtag-simple-base-string))
+
+(defun complex-array-p (x)
+  (let* ((typecode (typecode x)))
+    (declare (fixnum typecode))
+    (if (or (= typecode target::subtag-arrayH)
+            (= typecode target::subtag-vectorH))
+      (not (%array-header-simple-p x)))))
+
+(defun simple-array-p (thing)
+  "Returns T if the object is a simple array, else returns NIL.
+   That's why it's called SIMPLE-ARRAY-P.  Get it ?
+   A simple-array may have no fill-pointer, may not be displaced,
+   and may not be adjustable."
+  (let* ((typecode (typecode thing)))
+    (declare (fixnum typecode))
+    (if (or (= typecode target::subtag-arrayH)
+            (= typecode target::subtag-vectorH))
+      (%array-header-simple-p thing)
+      (> typecode target::subtag-vectorH))))
+
+(defun macptrp (x)
+  (= (the fixnum (typecode x)) target::subtag-macptr))
+
+(defun dead-macptr-p (x)
+  (= (the fixnum (typecode x)) target::subtag-dead-macptr))
+
+
+;;; Note that this is true of symbols and functions and many other
+;;; things that it wasn't true of on the 68K.
+(defun gvectorp (x)
+  #+(or ppc32-target x8632-target)
+  (= (the fixnum (logand (the fixnum (typecode x)) target::fulltagmask)) target::fulltag-nodeheader)
+  #+ppc64-target
+  (= (the fixnum (logand (the fixnum (typecode x)) ppc64::lowtagmask)) ppc64::lowtag-nodeheader)
+  #+x8664-target
+  (let* ((fulltag (logand (the fixnum (typecode x)) x8664::fulltagmask)))
+    (declare (fixnum fulltag))
+    (or (= fulltag x8664::fulltag-nodeheader-0)
+        (= fulltag x8664::fulltag-nodeheader-1)))
+  )
+
+
+(setf (type-predicate 'gvector) 'gvectorp)
+
+(defun ivectorp (x)
+  #+(or ppc32-target x8632-target)
+  (= (the fixnum (logand (the fixnum (typecode x)) target::fulltagmask))
+     target::fulltag-immheader)
+  #+ppc64-target
+  (= (the fixnum (logand (the fixnum (typecode x)) ppc64::lowtagmask)) ppc64::lowtag-immheader)
+  #+x8664-target
+  (let* ((fulltag (logand (the fixnum (typecode x)) x8664::fulltagmask)))
+    (declare (fixnum fulltag))
+    (or (= fulltag x8664::fulltag-immheader-0)
+        (= fulltag x8664::fulltag-immheader-1)
+        (= fulltag x8664::fulltag-immheader-2)))
+  )
+
+(setf (type-predicate 'ivector) 'ivectorp)
+
+(defun miscobjp (x)
+  #+(or ppc32-target x8632-target x8664-target)
+  (= (the fixnum (lisptag x)) target::tag-misc)
+  #+ppc64-target
+  (= (the fixnum (fulltag x)) ppc64::fulltag-misc)
+  )
+
+(defun simple-vector-p (x)
+  "Return true if OBJECT is a SIMPLE-VECTOR, and NIL otherwise."
+  (= (the fixnum (typecode x)) target::subtag-simple-vector))
+
+(defun base-string-p (thing)
+  (let* ((typecode (typecode thing)))
+    (declare (fixnum typecode))
+    (or (= typecode target::subtag-simple-base-string)
+        (and (= typecode target::subtag-vectorh)
+             (= (the fixnum 
+                  (ldb target::arrayH.flags-cell-subtag-byte (the fixnum (%svref thing target::arrayH.flags-cell))))
+                target::subtag-simple-base-string)))))
+
+(defun simple-bit-vector-p (form)
+  "Return true if OBJECT is a SIMPLE-BIT-VECTOR, and NIL otherwise."
+  (= (the fixnum (typecode form)) target::subtag-bit-vector))
+
+(defun bit-vector-p (thing)
+  "Return true if OBJECT is a BIT-VECTOR, and NIL otherwise."
+  (let* ((typecode (typecode thing)))
+    (declare (fixnum typecode))
+    (or (= typecode target::subtag-bit-vector)
+        (and (= typecode target::subtag-vectorh)
+             (= (the fixnum 
+                  (ldb target::arrayH.flags-cell-subtag-byte (the fixnum (%svref thing target::arrayH.flags-cell))))
+                target::subtag-bit-vector)))))
+
+(defun displaced-array-p (array)
+  (if (%array-is-header array)
+    (do* ((disp (%svref array target::arrayH.displacement-cell)
+		(+ disp (the fixnum (%svref target target::arrayH.displacement-cell))))
+	  (target (%svref array target::arrayH.data-vector-cell)
+		  (%svref target target::arrayH.data-vector-cell)))
+	 ((not (%array-is-header target))
+	  (values target disp)))
+    (values nil 0)))
+
+
+
+(defun eq (x y)
+  "Return T if OBJ1 and OBJ2 are the same object, otherwise NIL."
+  (eq x y))
+
+
+(defun cons-equal (x y)
+  (declare (cons x y))
+  (if (equal (car x) (car y))
+    (equal (cdr x) (cdr y))))
+
+(defun hairy-equal (x y)
+  (declare (optimize (speed 3)))
+  ;; X and Y are not EQL, and are both of tag target::fulltag-misc.
+  (let* ((x-type (typecode x))
+	 (y-type (typecode y)))
+    (declare (fixnum x-type y-type))
+    (if (and (>= x-type target::subtag-vectorH)
+	     (>= y-type target::subtag-vectorH))
+	(let* ((x-simple (if (= x-type target::subtag-vectorH)
+			     (ldb target::arrayH.flags-cell-subtag-byte 
+				  (the fixnum (%svref x target::arrayH.flags-cell)))
+			     x-type))
+	       (y-simple (if (= y-type target::subtag-vectorH)
+			     (ldb target::arrayH.flags-cell-subtag-byte 
+				  (the fixnum (%svref y target::arrayH.flags-cell)))
+			     y-type)))
+	  (declare (fixnum x-simple y-simple))
+	  (if (= x-simple target::subtag-simple-base-string)
+	      (if (= y-simple target::subtag-simple-base-string)
+		  (locally
+                      (declare (optimize (speed 3) (safety 0)))
+		    (let* ((x-len (if (= x-type target::subtag-vectorH) 
+                                      (%svref x target::vectorH.logsize-cell)
+                                      (uvsize x)))
+			   (x-pos 0)
+			   (y-len (if (= y-type target::subtag-vectorH) 
+                                      (%svref y target::vectorH.logsize-cell)
+                                      (uvsize y)))
+			   (y-pos 0))
+		      (declare (fixnum x-len x-pos y-len y-pos))
+		      (when (= x-type target::subtag-vectorH)
+			(multiple-value-setq (x x-pos) (array-data-and-offset x)))
+		      (when (= y-type target::subtag-vectorH)
+			(multiple-value-setq (y y-pos) (array-data-and-offset y)))
+		      (%simple-string= x y x-pos y-pos (the fixnum (+ x-pos x-len)) (the fixnum (+ y-pos y-len))))))
+	      ;;Bit-vector case or fail.
+	      (and (= x-simple target::subtag-bit-vector)
+		   (= y-simple target::subtag-bit-vector)
+		   (locally
+		       (declare (optimize (speed 3) (safety 0)))
+		     (let* ((x-len (if (= x-type target::subtag-vectorH) 
+				       (%svref x target::vectorH.logsize-cell)
+				       (uvsize x)))
+			    (x-pos 0)
+			    (y-len (if (= y-type target::subtag-vectorH) 
+				       (%svref y target::vectorH.logsize-cell)
+				       (uvsize y)))
+			    (y-pos 0))
+		       (declare (fixnum x-len x-pos y-len y-pos))
+		       (when (= x-len y-len)
+			 (when (= x-type target::subtag-vectorH)
+			   (multiple-value-setq (x x-pos) (array-data-and-offset x)))
+			 (when (= y-type target::subtag-vectorH)
+			   (multiple-value-setq (y y-pos) (array-data-and-offset y)))
+			 (do* ((i 0 (1+ i)))
+			      ((= i x-len) t)
+			   (declare (fixnum i))
+			   (unless (= (the bit (sbit x x-pos)) (the bit (sbit y y-pos)))
+			     (return))
+			   (incf x-pos)
+			   (incf y-pos))))))))
+	(if (= x-type y-type)
+	    (if (= x-type target::subtag-istruct)
+		(and (let* ((structname (istruct-cell-name (%svref x 0))))
+		       (and (eq structname (istruct-cell-name (%svref y 0)))
+			    (or (eq structname 'pathname)
+				(eq structname 'logical-pathname)))
+                       (locally
+                           (declare (optimize (speed 3) (safety 0)))
+                         (let* ((x-size (uvsize x))
+                                (skip (if (eq structname 'pathname)
+                                        %physical-pathname-version
+                                        -1)))
+                           (declare (fixnum x-size skip))
+                           (when (= x-size (the fixnum (uvsize y)))
+                             (if *case-sensitive-filesystem*
+                               (do* ((i 1 (1+ i)))
+                                    ((= i x-size) t)
+                                 (declare (fixnum i))
+                                 (unless (or (= i skip)
+                                             (equal (%svref x i) (%svref y i)))
+                                   (return)))
+                                                              (do* ((i 1 (1+ i)))
+                                    ((= i x-size) t)
+                                 (declare (fixnum i))
+                                 (unless (or (= i skip)
+                                             (equalp (%svref x i) (%svref y i)))
+                                   (return))))))))))))))
+
+#+ppc32-target
+(progn
+(defparameter *nodeheader-types*
+  #(bogus                               ; 0
+    ratio                               ; 1
+    bogus                               ; 2
+    complex                             ; 3
+    catch-frame                         ; 4
+    function                            ; 5
+    basic-stream                         ; 6
+    symbol                              ; 7
+    lock                                ; 8
+    hash-table-vector                   ; 9
+    pool                                ; 10
+    population                          ; 11
+    package                             ; 12
+    slot-vector				; 13
+    standard-instance                   ; 14
+    structure                           ; 15
+    internal-structure                  ; 16
+    value-cell                          ; 17
+    xfunction                           ; 18
+    array-header                        ; 19
+    vector-header                       ; 20
+    simple-vector                       ; 21
+    bogus                               ; 22
+    bogus                               ; 23
+    bogus                               ; 24
+    bogus                               ; 25
+    bogus                               ; 26
+    bogus                               ; 27
+    bogus                               ; 28
+    bogus                               ; 29
+    bogus                               ; 30
+    bogus                               ; 31
+    ))
+
+
+(defparameter *immheader-types*
+  #(bignum                              ; 0
+    short-float                         ; 1
+    double-float                        ; 2
+    macptr                              ; 3
+    dead-macptr                         ; 4
+    code-vector                         ; 5
+    creole-object                       ; 6
+    ;; 8-19 are unused
+    xcode-vector                        ; 7
+    bogus                               ; 8
+    bogus                               ; 9
+    bogus                               ; 10
+    bogus                               ; 11
+    bogus                               ; 12
+    bogus                               ; 13
+    bogus                               ; 14
+    bogus                               ; 15
+    bogus                               ; 16
+    bogus                               ; 17
+    bogus                               ; 18
+    bogus                               ; 19
+    simple-short-float-vector           ; 20
+    simple-unsigned-long-vector         ; 21
+    simple-signed-long-vector           ; 22
+    simple-fixnum-vector                ; 23
+    simple-base-string                  ; 24
+    simple-unsigned-byte-vector         ; 25
+    simple-signed-byte-vector           ; 26
+    bogus                               ; 27
+    simple-unsigned-word-vector         ; 28
+    simple-signed-word-vector           ; 29
+    simple-double-float-vector          ; 30
+    simple-bit-vector                   ; 31
+    ))
+
+(defun %type-of (thing)
+  (let* ((typecode (typecode thing)))
+    (declare (fixnum typecode))
+    (if (= typecode ppc32::tag-fixnum)
+      'fixnum
+      (if (= typecode ppc32::tag-list)
+        (if thing 'cons 'null)
+        (if (= typecode ppc32::tag-imm)
+          (if (base-char-p thing)
+            'base-char
+            'immediate)
+	  (if (= typecode ppc32::subtag-macptr)
+	    (if (classp thing)
+	      (class-name thing)
+	      'macptr)
+	    (let* ((tag-type (logand typecode ppc32::full-tag-mask))
+		   (tag-val (ash typecode (- ppc32::ntagbits))))
+	      (declare (fixnum tag-type tag-val))
+	      (if (/= tag-type ppc32::fulltag-nodeheader)
+		(%svref *immheader-types* tag-val)
+		(let ((type (%svref *nodeheader-types* tag-val)))
+		  (if (eq type 'function)
+		    (let ((bits (lfun-bits thing)))
+		      (declare (fixnum bits))
+		      (if (logbitp $lfbits-trampoline-bit bits)
+			(let ((inner-fn (closure-function thing)))
+                          (if (neq inner-fn thing)
+                            (let ((inner-bits (lfun-bits inner-fn)))
+                              (if (logbitp $lfbits-method-bit inner-bits)
+                                'compiled-lexical-closure
+                                (if (logbitp $lfbits-gfn-bit inner-bits)
+                                  'standard-generic-function ; not precisely - see class-of
+                                  (if (logbitp  $lfbits-cm-bit inner-bits)
+                                    'combined-method
+                                    'compiled-lexical-closure))))
+                            'compiled-lexical-closure))
+                        (if (logbitp  $lfbits-method-bit bits)
+                          'method-function          
+                          'compiled-function)))
+		    (if (eq type 'lock)
+		      (or (uvref thing ppc32::lock.kind-cell)
+			  type)
+		      type)))))))))))
+
+);#+ppc32-target
+
+#+ppc64-target
+(progn
+(defparameter *immheader-types*
+  #(bogus
+    bogus
+    code-vector
+    bogus
+    bogus
+    bogus
+    xcode-vector
+    macptr
+    bogus
+    bogus
+    bignum
+    dead-macptr
+    bogus
+    bogus
+    double-float
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    simple-signed-byte-vector
+    simple-signed-word-vector
+    simple-signed-long-vector
+    simple-signed-doubleword-vector
+    simple-unsigned-byte-vector
+    simple-unsigned-word-vector
+    simple-unsigned-long-vector
+    simple-unsigned-doubleword-vector
+    bogus
+    bogus
+    simple-short-float-vector
+    simple-fixnum-vector
+    bogus
+    bogus
+    bogus
+    simple-double-float-vector
+    bogus
+    bogus
+    simple-base-string
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    simple-bit-vector
+    bogus
+    bogus))
+
+(defparameter *nodeheader-types*
+    #(function
+      catch-frame
+      slot-vector
+      ratio
+      symbol
+      basic-stream
+      standard-instance
+      complex
+      bogus
+      lock
+      structure
+      bogus
+      bogus
+      hash-vector
+      internal-structure
+      bogus
+      bogus
+      pool
+      value-cell
+      bogus
+      bogus
+      population
+      xfunction
+      bogus
+      bogus
+      package
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      array-header
+      vector-header
+      simple-vector
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      )
+  )
+
+
+(defun %type-of (thing)
+  (if (null thing)
+    'null
+    (let* ((typecode (typecode thing)))
+      (declare (fixnum typecode))
+      (cond ((= typecode ppc64::tag-fixnum) 'fixnum)
+            ((= typecode ppc64::fulltag-cons) 'cons)
+            ((= typecode ppc64::subtag-character) 'character)
+            ((= typecode ppc64::subtag-single-float) 'short-float)
+            (t (let* ((lowtag (logand typecode ppc64::lowtagmask)))
+                 (declare (fixnum lowtag))
+                 (cond ((= lowtag ppc64::lowtag-immheader)
+                        (%svref *immheader-types* (ash typecode -2)))
+                       ((= lowtag ppc64::lowtag-nodeheader)
+                        (let* ((type (%svref *nodeheader-types*
+                                             (ash typecode -2))))
+                          (cond ((eq type 'function)
+                                 (let ((bits (lfun-bits thing)))
+                                   (declare (fixnum bits))
+                                   (if (logbitp $lfbits-trampoline-bit bits)
+                                     (let ((inner-fn (closure-function thing)))
+                                         (if (neq inner-fn thing)
+                                           (let ((inner-bits (lfun-bits inner-fn)))
+                                             (if (logbitp $lfbits-method-bit inner-bits)
+                                               'compiled-lexical-closure
+                                               (if (logbitp $lfbits-gfn-bit inner-bits)
+                                                 'standard-generic-function ; not precisely - see class-of
+                                                 (if (logbitp  $lfbits-cm-bit inner-bits)
+                                                   'combined-method
+                                                   'compiled-lexical-closure))))
+                                           'compiled-lexical-closure))
+                                     (if (logbitp  $lfbits-method-bit bits)
+                                       'method-function          
+                                       'compiled-function))))
+                                ((eq type 'lock)
+                                 (or (uvref thing ppc64::lock.kind-cell)
+                                     type))
+                                (t type))))
+                       (t 'immediate))))))))
+);#+ppc64-target
+
+
+#+x8632-target
+(progn
+(defparameter *nodeheader-types*
+  #(bogus                               ; 0
+    ratio                               ; 1
+    bogus                               ; 2
+    complex                             ; 3
+    catch-frame                         ; 4
+    function                            ; 5
+    basic-stream			; 6
+    symbol                              ; 7
+    lock                                ; 8
+    hash-table-vector                   ; 9
+    pool                                ; 10
+    population                          ; 11 (weak?)
+    package                             ; 12
+    slot-vector				; 13
+    standard-instance                   ; 14
+    structure                           ; 15
+    internal-structure                  ; 16
+    value-cell                          ; 17
+    xfunction                           ; 18
+    array-header                        ; 19
+    vector-header                       ; 20
+    simple-vector                       ; 21
+    bogus                               ; 22
+    bogus                               ; 23
+    bogus                               ; 24
+    bogus                               ; 25
+    bogus                               ; 26
+    bogus                               ; 27
+    bogus                               ; 28
+    bogus                               ; 29
+    bogus                               ; 30
+    bogus                               ; 31
+    ))
+
+
+(defparameter *immheader-types*
+  #(bignum                              ; 0
+    short-float                         ; 1
+    double-float                        ; 2
+    macptr                              ; 3
+    dead-macptr                         ; 4
+    code-vector                         ; 5
+    creole-object                       ; 6
+    xcode-vector                        ; 7
+    bogus                               ; 8
+    bogus                               ; 9
+    bogus                               ; 10
+    bogus                               ; 11
+    bogus                               ; 12
+    bogus                               ; 13
+    bogus                               ; 14
+    bogus                               ; 15
+    bogus                               ; 16
+    bogus                               ; 17
+    bogus                               ; 18
+    bogus                               ; 19
+    simple-short-float-vector           ; 20
+    simple-unsigned-long-vector         ; 21
+    simple-signed-long-vector           ; 22
+    simple-fixnum-vector                ; 23
+    simple-base-string                  ; 24
+    simple-unsigned-byte-vector         ; 25
+    simple-signed-byte-vector           ; 26
+    bogus                               ; 27
+    simple-unsigned-word-vector         ; 28
+    simple-signed-word-vector           ; 29
+    simple-double-float-vector          ; 30
+    simple-bit-vector                   ; 31
+    ))
+
+(defun %type-of (thing)
+  (let* ((typecode (typecode thing)))
+    (declare (fixnum typecode))
+    (if (= typecode x8632::tag-fixnum)
+      'fixnum
+      (if (= typecode x8632::tag-list)	;a misnomer on x8632...
+	(if (= (fulltag thing) x8632::fulltag-cons)
+	  (if thing 'cons 'null)
+	  'tagged-return-address)
+        (if (= typecode x8632::tag-imm)
+          (if (base-char-p thing)
+            'base-char
+            'immediate)
+	  (if (= typecode x8632::subtag-macptr)
+	    (if (classp thing)
+	      (class-name thing)
+	      'macptr)
+	    (let* ((tag-type (logand typecode x8632::fulltagmask))
+		   (tag-val (ash typecode (- x8632::ntagbits))))
+	      (declare (fixnum tag-type tag-val))
+	      (if (/= tag-type x8632::fulltag-nodeheader)
+		(%svref *immheader-types* tag-val)
+		(let ((type (%svref *nodeheader-types* tag-val)))
+		  (if (eq type 'function)
+		    (let ((bits (lfun-bits thing)))
+		      (declare (fixnum bits))
+		      (if (logbitp $lfbits-trampoline-bit bits)
+			(let ((inner-fn (closure-function thing)))
+                          (if (neq inner-fn thing)
+                            (let ((inner-bits (lfun-bits inner-fn)))
+                              (if (logbitp $lfbits-method-bit inner-bits)
+                                'compiled-lexical-closure
+                                (if (logbitp $lfbits-gfn-bit inner-bits)
+                                  'standard-generic-function ; not precisely - see class-of
+                                  (if (logbitp  $lfbits-cm-bit inner-bits)
+                                    'combined-method
+                                    'compiled-lexical-closure))))
+                            'compiled-lexical-closure))
+                        (if (logbitp  $lfbits-method-bit bits)
+                          'method-function          
+                          'compiled-function)))
+		    (if (eq type 'lock)
+		      (or (uvref thing x8632::lock.kind-cell)
+			  type)
+		      type)))))))))))
+
+) ;x8632-target
+
+#+x8664-target
+(progn
+(defparameter *nodeheader-0-types*
+  #(bogus
+    symbol-vector
+    catch-frame
+    hash-vector
+    pool
+    population
+    package
+    slot-vector
+    basic-stream
+    function-vector                                        ;8
+    array-header
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    ))
+
+(defparameter *nodeheader-1-types*
+  #(bogus
+    ratio
+    complex
+    structure
+    internal-structure
+    value-cell
+    xfunction
+    lock
+    instance
+    bogus
+    vector-header
+    simple-vector
+    bogus
+    bogus
+    bogus
+    bogus
+    ))
+
+(defparameter *immheader-0-types*
+  #(bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    simple-signed-word-vector
+    simple-unsigned-word-vector
+    bogus
+    simple-signed-byte-vector
+    simple-unsigned-byte-vector
+    bit-vector))
+
+(defparameter *immheader-1-types*
+  #(bogus
+    bignum
+    double-float
+    xcode-vector
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    simple-base-string
+    simple-signed-long-vector
+    simple-unsigned-long-vector
+    single-float-vector))
+
+(defparameter *immheader-2-types*
+  #(bogus
+    macptr
+    dead-macptr
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    simple-fixnum-vector
+    simple-signed-doubleword-vector
+    simple-unsigned-doubleword-vector
+    double-float-vector))
+
+
+(defparameter *x8664-%type-of-functions* nil)
+
+(let* ((fixnum (lambda (x) (declare (ignore x)) 'fixnum))
+       (tra (lambda (x) (declare (ignore x)) 'tagged-return-address))
+       (bogus (lambda (x) (declare (ignore x)) 'bogus)))
+  (setq *x8664-%type-of-functions*
+        (vector
+         fixnum                         ;0
+         (lambda (x) (declare (ignore x)) 'short-float) ;1
+         (lambda (x) (if (characterp x) 'character 'immediate)) ;2
+         (lambda (x) (declare (ignore x)) 'cons) ;3
+         tra                            ;4
+         bogus                          ;5
+         bogus                          ;6
+         bogus                          ;7
+         fixnum                         ;8
+         bogus                          ;9
+         bogus                          ;10
+         (lambda (x) (declare (ignore x)) 'null) ;11
+         tra                            ;12
+         (lambda (x) (let* ((typecode (typecode x)) 
+                            (low4 (logand typecode x8664::fulltagmask))
+                            (high4 (ash typecode (- x8664::ntagbits))))
+                       (declare (type (unsigned-byte 8) typecode)
+                                (type (unsigned-byte 4) low4 high4))
+                       (let* ((name
+                               (cond ((= low4 x8664::fulltag-immheader-0)
+                                      (%svref *immheader-0-types* high4))
+                                     ((= low4 x8664::fulltag-immheader-1)
+                                      (%svref *immheader-1-types* high4))
+                                     ((= low4 x8664::fulltag-immheader-2)
+                                      (%svref *immheader-2-types* high4))
+                                     ((= low4 x8664::fulltag-nodeheader-0)
+                                      (%svref *nodeheader-0-types* high4))
+                                     ((= low4 x8664::fulltag-nodeheader-1)
+                                      (%svref *nodeheader-1-types* high4))
+                                     (t 'bogus))))
+                         (or (and (eq name 'lock)
+                                  (uvref x x8664::lock.kind-cell))
+                             name)))) ;13
+         (lambda (x) (declare (ignore x)) 'symbol) ;14
+         (lambda (thing)
+           (let ((bits (lfun-bits thing)))
+             (declare (fixnum bits))
+             (if (logbitp $lfbits-trampoline-bit bits)
+               (let ((inner-fn (closure-function thing)))
+                 (if (neq inner-fn thing)
+                   (let ((inner-bits (lfun-bits inner-fn)))
+                     (if (logbitp $lfbits-method-bit inner-bits)
+                       'compiled-lexical-closure
+                       (if (logbitp $lfbits-gfn-bit inner-bits)
+                         'standard-generic-function ; not precisely - see class-of
+                         (if (logbitp  $lfbits-cm-bit inner-bits)
+                           'combined-method
+                           'compiled-lexical-closure))))
+                   'compiled-lexical-closure))
+               (if (logbitp  $lfbits-method-bit bits)
+                 'method-function          
+                 'compiled-function))))))) ;15
+                                      
+       
+
+
+  
+(defun %type-of (thing)
+  (let* ((f (fulltag thing)))
+    (funcall (%svref *x8664-%type-of-functions* f) thing)))
+
+        
+
+);#+x8664-target
+      
+
+;;; real machine specific huh
+(defun consp (x)
+  "Return true if OBJECT is a CONS, and NIL otherwise."
+  (consp x))
+
+(defun characterp (arg)
+  "Return true if OBJECT is a CHARACTER, and NIL otherwise."
+  (characterp arg))
+
+(defun base-char-p (c)
+  (base-char-p c))
+
+
+
+
+(defun structurep (form)
+  "True if the given object is a named structure, Nil otherwise."
+  (= (the fixnum (typecode form)) target::subtag-struct))
+
+(defun istructp (form)
+  (= (the fixnum (typecode form)) target::subtag-istruct))
+
+
+;;; Not to be conused with STRUCTURE-TYPE-P, defined in ccl:lib;pprint.lisp.
+;;; (If you've ever been "conused", I'm sure you know just how painful
+;;; that can be.)
+(defun structure-typep (thing type)
+  (if (= (the fixnum (typecode thing)) target::subtag-struct)
+    (let* ((types (%svref thing 0)))
+      (if (typep type 'symbol)
+        (dolist (x types)
+          (when (eq (class-cell-name x) type)
+            (return t)))
+        (dolist (x types)
+          (when (eq x type)
+            (return t)))))))
+
+
+
+(defun istruct-typep (thing type)
+  (if (= (the fixnum (typecode thing)) target::subtag-istruct)
+    (eq (istruct-cell-name (%svref thing 0)) type)))
+
+(defun istruct-type-name (thing)
+  (if (= (the fixnum (typecode thing)) target::subtag-istruct)
+    (istruct-cell-name (%svref thing 0))))
+
+
+;;; This is actually set to an alist in the xloader.
+(defparameter *istruct-cells* nil)
+
+;;; This should only ever push anything on the list in the cold
+;;; load (e.g., when running single-threaded.)
+(defun register-istruct-cell (name)
+  (or (assq name *istruct-cells*)
+      (let* ((pair (cons name nil)))
+        (push pair *istruct-cells*)
+        pair)))
+
+(defun set-istruct-cell-info (cell info)
+  (etypecase cell
+    (cons (%rplacd cell info)))
+  info)
+
+
+(defun symbolp (thing)
+  "Return true if OBJECT is a SYMBOL, and NIL otherwise."
+  #+(or ppc32-target x8632-target)
+  (if thing
+    (= (the fixnum (typecode thing)) target::subtag-symbol)
+    t)
+  #+ppc64-target
+  (= (the fixnum (typecode thing)) ppc64::subtag-symbol)
+  #+x8664-target
+  (if thing
+    (= (the fixnum (lisptag thing)) x8664::tag-symbol)
+    t)
+  )
+      
+(defun packagep (thing)
+  (= (the fixnum (typecode thing)) target::subtag-package))
+
+;;; 1 if by land, 2 if by sea.
+(defun sequence-type (x)
+  (unless (>= (the fixnum (typecode x)) target::min-vector-subtag)
+    (or (listp x)
+        (report-bad-arg x 'sequence))))
+
+(defun uvectorp (x)
+  (= (the fixnum (fulltag x)) target::fulltag-misc))
+
+(setf (type-predicate 'uvector) 'uvectorp)
+
+(defun listp (x)
+  (listp x))
+
+(defparameter *type-cells* nil)
+
+
+
+(defparameter *type-cells-lock* nil)
+
+
+;;; The weird handling to the special variables here has to do with
+;;; xload issues.
+(defun register-type-cell (specifier)
+  (with-lock-grabbed ((or *type-cells-lock*
+                         (setq *type-cells-lock* (make-lock))))
+    (unless *type-cells*
+      (setq *type-cells* (make-hash-table :test 'equal)))
+    (or (values (gethash specifier *type-cells*))
+        (setf (gethash specifier *type-cells*)
+              (make-type-cell specifier)))))
+
+
+(defvar %find-classes% nil)
+
+(setq %find-classes% (make-hash-table :test 'eq))
+
+
+(defun find-class-cell (name create?)
+  (unless %find-classes%
+    (dbg name))
+  (let ((cell (gethash name %find-classes%)))
+    (or cell
+        (and create?
+             (setf (gethash name %find-classes%) (make-class-cell name))))))
+
Index: /branches/new-random/level-0/l0-symbol.lisp
===================================================================
--- /branches/new-random/level-0/l0-symbol.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-symbol.lisp	(revision 13309)
@@ -0,0 +1,271 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; No error checking, no interrupts, no protect_caller, no nuthin.
+;;; No error, no cons.  No problem.
+(defun %progvrestore (saved)
+  (declare (optimize (speed 3) (safety 0)))
+  (dolist (pair saved)
+    (%set-sym-value (car pair) (cdr pair))))
+
+;;; Check that something that's supposed to be a proper list of
+;;; symbols is; error otherwise.
+;;; This is called only by the compiler output of a PROGV form.
+;;; It checks for the maximum length that the progvsave subprim
+;;; can handle.
+
+(defun check-symbol-list (l &optional (max-length
+                                        (floor (- 4096 20) (* target::node-size 3))
+                                       ))
+  (let ((len (list-length l)))
+    (if (and len
+             (or (null max-length)
+                 (< len max-length))
+             (dolist (s l t) 
+               (unless (and (symbolp s)
+                            (not (constant-symbol-p s))
+                            (not (logbitp $sym_vbit_global (the fixnum (%symbol-bits s))))
+                            (ensure-binding-index s))
+                 (return nil))))
+      l
+      (error "~s is not a proper list of bindable symbols~@[ of length < ~s~]." l max-length))))
+
+;;; The type-checking done on the "plist" arg shouldn't be removed.
+(defun set-symbol-plist (sym plist)
+  (when plist
+    (let* ((len (list-length plist)))
+      (unless (and len (evenp len))
+        (error "Bad plist: ~s" plist))))
+  (let* ((vector (symptr->symvector (%symbol->symptr sym)))
+         (cell (%svref vector target::symbol.plist-cell))
+         (consp (consp cell)))
+    (if plist
+      (if consp
+        (setf (cdr cell) plist)
+        (cdr (setf (%svref vector target::symbol.plist-cell) (cons nil plist))))
+      (progn
+        (if consp
+          (setf (%svref vector target::symbol.plist-cell) (%car cell)))
+        nil))))
+
+
+(eval-when (:compile-toplevel :execute)
+  (declaim (inline %pl-search)))
+
+(defun %pl-search (l key)
+  (declare (list l) (optimize (speed 3)))
+  (loop
+    (if (eq (car l) key)
+      (return)
+      (if l
+        (setq l (cdr (the list (cdr l))))
+        (return))))
+  l)
+
+
+(defun symbol-plist (sym)
+  "Return SYMBOL's property list."
+  (let* ((cell (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.plist-cell)))
+    (if (consp cell)
+      (cdr cell))))
+
+
+(defun get (sym key &optional default)
+  "Look on the property list of SYMBOL for the specified INDICATOR. If this
+  is found, return the associated value, else return DEFAULT."
+  (let* ((cell (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.plist-cell))
+         (tail (if (consp cell)
+                 (%pl-search (cdr cell ) key))))
+    (if tail (%cadr tail) default)))
+
+(defun put (sym key value)
+  (let* ((symptr (%symbol->symptr sym))
+         (vector (symptr->symvector symptr))
+         (cell  (%svref vector target::symbol.plist-cell))
+         (plist (if (consp cell) (cdr cell)))
+         (tail (%pl-search plist key)))
+    (if tail 
+      (%rplaca (%cdr tail) value)
+      (progn
+        (setq plist (cons key (cons value plist)))
+        (if (consp cell)
+          (setf (cdr cell) plist)
+          (setf (%svref vector target::symbol.plist-cell) (cons nil plist)))))
+    value))
+
+
+(defun get-type-predicate (name)
+  (let* ((symvec (symptr->symvector (%symbol->symptr name)))
+         (pp (%svref symvec target::symbol.package-predicate-cell)))
+    (if (consp pp)
+      (%cdr pp))))
+
+(defun set-type-predicate (name function)
+  (let* ((bits (%symbol-bits name))
+         (symvec (symptr->symvector (%symbol->symptr name)))
+         (spp (%svref symvec target::symbol.package-predicate-cell)))
+    (declare (fixnum bits))
+    (if (logbitp $sym_vbit_typeppred bits)
+      (%rplacd spp function)
+      (progn
+        (%symbol-bits name (the fixnum (bitset $sym_vbit_typeppred bits)))
+        (setf (%svref symvec target::symbol.package-predicate-cell) (cons spp function))))
+    function))
+
+(defun symbol-value (sym)
+  "Return SYMBOL's current bound value."
+  (let* ((val (%sym-value sym)))
+    (if (eq val (%unbound-marker))
+      (%kernel-restart $xvunbnd sym)
+      val)))
+
+(defun set (sym value)
+  "Set SYMBOL's value cell to NEW-VALUE."
+  (let* ((bits (%symbol-bits sym)))
+    (declare (fixnum bits))
+    (if (logbitp $sym_vbit_const bits)
+      (%err-disp $XCONST sym)
+      (%set-sym-value sym value))))
+
+(defun constant-symbol-p (sym)
+  (and (symbolp sym)
+       (%ilogbitp $sym_vbit_const (%symbol-bits sym))))
+
+;;; This leaves the SPECIAL bit alone, clears the others.
+(defun makunbound (sym)
+  "Make SYMBOL unbound, removing any value it may currently have."
+  (if (and *warn-if-redefine-kernel*
+           (constant-symbol-p sym))
+    (cerror "Make ~S be unbound anyway."
+            "~S is a constant; making it unbound might be a bad idea." sym))
+  (%symbol-bits sym (the fixnum (logand (logior #xff00 (ash 1 $sym_bit_special))
+                                        (the fixnum (%symbol-bits sym)))))
+  (%set-sym-value sym (%unbound-marker))
+  sym)
+
+(defun non-nil-symbolp (x)
+  "Returns symbol if true"
+  (if (symbolp x) x))
+
+(defun symbol-package (sym)
+  "Return the package SYMBOL was interned in, or NIL if none."
+  (let* ((pp (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.package-predicate-cell)))
+    (if (consp pp) (car pp) pp)))
+
+(defun boundp (sym)
+  "Return non-NIL if SYMBOL is bound to a value."
+  (not (eq (%sym-value sym) (%unbound-marker))))
+
+(defun make-symbol (name)
+  "Make and return a new symbol with the NAME as its print name."
+  (symvector->symptr
+   (%gvector target::subtag-symbol
+             (ensure-simple-string name) ; pname
+             (%unbound-marker)          ; value cell
+             %unbound-function%         ; function cell
+             nil                        ; package&predicate
+             0                          ; flags
+             nil                        ; plist
+             0)))                       ; binding-index
+
+(defun %symbol-bits (sym &optional new)
+  (let* ((p (%symbol->symptr sym))
+         (bits (%svref (symptr->symvector p) target::symbol.flags-cell)))
+    (if new
+      (setf (%svref (symptr->symvector p) target::symbol.flags-cell) new))
+    bits))
+
+(defun %sym-value (name)
+  (%symptr-value (%symbol->symptr name)))
+
+(defun %set-sym-value (name val)
+  (%set-symptr-value (%symbol->symptr name) val))
+    
+(defun %sym-global-value (name)
+  (%svref (symptr->symvector (%symbol->symptr name)) target::symbol.vcell-cell))
+
+(defun %set-sym-global-value (name val)
+  (setf (%svref (symptr->symvector (%symbol->symptr name)) target::symbol.vcell-cell) val))
+
+(defun symbol-name (sym)
+  "Return SYMBOL's name as a string."
+  #+(or ppc32-target x8632-target x8664-target)
+  (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.pname-cell)
+  #+ppc64-target
+  (if sym                               ;NIL's pname is implicit
+    (%svref (%symbol->symptr sym) ppc64::symbol.pname-cell)
+    "NIL")
+  )
+
+
+
+
+(defun %global-macro-function (symbol)
+  (let* ((fbinding (fboundp symbol)))
+    (if (and (typep fbinding 'simple-vector)
+             (= (the fixnum (uvsize fbinding)) 2))
+      (let* ((fun (%svref fbinding 1)))
+        (if (functionp fun) fun)))))
+
+(defun %symbol-binding-address (sym)
+  (%symptr-binding-address (%symbol->symptr sym)))
+
+(defun symbol-binding-index (sym)
+  (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.binding-index-cell))
+
+(defvar *interrupt-level* -1)
+
+;;; Special binding indices, and the inverse mapping between indices
+;;; and symbols
+(let* ((binding-index-lock (make-lock))
+       (binding-index-reverse-map (make-hash-table :test #'eq :weak :value))
+       (next-binding-index 0))
+  (defun %set-binding-index (val) (setq next-binding-index val))
+  (defun next-binding-index () (1+ next-binding-index))
+  (defun ensure-binding-index (sym)
+    (with-lock-grabbed (binding-index-lock)
+      (let* ((symvec (symptr->symvector (%symbol->symptr sym)))
+             (idx (%svref symvec target::symbol.binding-index-cell))
+             (bits (%symbol-bits sym)))
+        (declare (fixnum idx bits))
+        (if (or (logbitp $sym_vbit_global bits)
+                (logbitp $sym_vbit_const bits))
+          (unless (zerop idx)
+            (remhash idx binding-index-reverse-map)
+            (setf (%svref symvec target::symbol.binding-index-cell) 0))
+          (if (zerop idx)
+            (let* ((new-idx (incf next-binding-index)))
+              (setf (%svref symvec target::symbol.binding-index-cell) new-idx)
+              (setf (gethash new-idx binding-index-reverse-map) sym))))
+        sym)))
+  (defun binding-index-symbol (idx)
+    (with-lock-grabbed (binding-index-lock)
+      (gethash idx binding-index-reverse-map)))
+  (defun cold-load-binding-index (sym)
+    ;; Index may have been assigned via xloader.  Update
+    ;; reverse map
+    (with-lock-grabbed (binding-index-lock)
+      (let* ((idx (%svref (symptr->symvector (%symbol->symptr sym))
+                          target::symbol.binding-index-cell)))
+        (declare (fixnum idx))
+        (unless (zerop idx)
+          (setf (gethash idx binding-index-reverse-map) sym))))))
+
+       
+
Index: /branches/new-random/level-0/l0-utils.lisp
===================================================================
--- /branches/new-random/level-0/l0-utils.lisp	(revision 13309)
+++ /branches/new-random/level-0/l0-utils.lisp	(revision 13309)
@@ -0,0 +1,197 @@
+; -*- Mode: Lisp;  Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+; l0-utils.lisp
+
+
+(in-package "CCL")
+
+(defun %proclaim-notspecial (sym)
+  (%symbol-bits sym (logandc2 (%symbol-bits sym) (ash 1 $sym_bit_special))))
+
+
+(defun heap-area-name (code)
+  (cond ((eq code area-void) :void)
+        ((eq code area-cstack) :cstack)
+        ((eq code area-vstack) :vstack)
+        ((eq code area-tstack) :tstack)
+        ((eq code area-readonly) :readonly)
+        ((eq code area-watched) :watched)
+        ((eq code area-managed-static) :managed-static)
+        ((eq code area-static) :static)
+        ((eq code area-dynamic) :dynamic)
+        (t code)))
+
+(defun heap-area-code (name)
+  (case name
+    (:void area-void)
+    (:cstack area-cstack)
+    (:vstack area-vstack)
+    (:tstack area-tstack)
+    (:readonly area-readonly)
+    (:watched area-watched)
+    (:managed-static area-managed-static)
+    (:static area-static)
+    (:dynamic area-dynamic)
+    (t (if (and (fixnump name)
+                (<= area-readonly name area-dynamic))
+         name
+         (heap-area-code (require-type name '(member :void :cstack :vstack :tstack
+                                                     :readonly :managed-static :static :dynamic)))))))
+
+
+;;; We MAY need a scheme for finding all of the areas in a lisp library.
+(defun %map-areas (function &optional area)
+  (let* ((area (cond ((or (eq area t) (eq area nil)) nil)
+                     ((consp area) (mapcar #'heap-area-code area)) ;; list of areas
+                     (t (heap-area-code area))))
+         (mincode area-readonly)
+         (maxcode area-dynamic))
+  (declare (fixnum maxcode mincode))
+  (do* ((a (%normalize-areas) (%lisp-word-ref a (ash target::area.succ (- target::fixnumshift))))
+        (code area-dynamic (%lisp-word-ref a (ash target::area.code (- target::fixnumshift))))
+        (dynamic t nil))
+       ((= code area-void))
+    (declare (fixnum code))
+    (if (and (<= code maxcode)
+             (>= code mincode)
+             (or (null area)
+                 (eql code area)
+                 (and (consp area) (member code area))))
+      (if dynamic 
+        (walk-dynamic-area a function)
+        (unless (= code area-dynamic)        ; ignore egc areas, 'cause walk-dynamic-area sees them.
+          (walk-static-area a function)))))))
+
+
+;;; there'll be functions in static lib areas.
+;;; (Well, there would be if there were really static lib areas.)
+
+(defun %map-lfuns (f)
+  (let* ((filter #'(lambda (obj) (when (= (the fixnum (typecode obj))
+                                          target::subtag-function)
+                                   (funcall f (lfun-vector-lfun obj))))))
+    (declare (dynamic-extent filter))
+    (%map-areas filter '(:dynamic :static :managed-static :readonly))))
+
+
+(defun ensure-simple-string (s)
+  (cond ((simple-string-p s) s)
+        ((stringp s)
+         (let* ((len (length s))
+                (new (make-string len :element-type 'base-char)))
+           (declare (fixnum len)(optimize (speed 3)(safety 0)))
+           (multiple-value-bind (ss offset) (array-data-and-offset s)
+             (%copy-ivector-to-ivector ss (ash offset 2) new 0 (ash len 2)))
+           new))
+        (t (report-bad-arg s 'string))))
+
+(defun nremove (elt list)
+  (let* ((handle (cons nil list))
+         (splice handle))
+    (declare (dynamic-extent handle))
+    (loop
+      (if (eq elt (car (%cdr splice)))
+        (unless (setf (%cdr splice) (%cddr splice)) (return))
+        (unless (cdr (setq splice (%cdr splice)))
+          (return))))
+    (%cdr handle)))
+
+
+(eval-when (:compile-toplevel :execute)
+  #+32-bit-target
+  (defmacro need-use-eql-macro (key)
+    `(let* ((typecode (typecode ,key)))
+       (declare (fixnum typecode))
+       (or (= typecode target::subtag-macptr)
+           (and (>= typecode target::min-numeric-subtag)
+                (<= typecode target::max-numeric-subtag)))))
+  #+64-bit-target
+  (defmacro need-use-eql-macro (key)
+    `(let* ((typecode (typecode ,key)))
+       (declare (fixnum typecode))
+      (cond ((= typecode target::tag-fixnum) t)
+            ((= typecode target::subtag-single-float) t)
+            ((= typecode target::subtag-bignum) t)
+            ((= typecode target::subtag-double-float) t)
+            ((= typecode target::subtag-ratio) t)
+            ((= typecode target::subtag-complex) t)
+            ((= typecode target::subtag-macptr) t))))
+
+)
+
+(defun asseql (item list)
+  (if (need-use-eql-macro item)
+    (dolist (pair list)
+      (if pair
+	(if (eql item (car pair))
+	  (return pair))))
+    (assq item list)))
+
+(defun assequal (item list)
+  (dolist (pair list)
+    (if pair
+      (if (equal item (car pair))
+        (return pair)))))
+
+
+;;; (memeql item list) <=> (member item list :test #'eql :key #'identity)
+(defun memeql (item list)
+  (if (need-use-eql-macro item)
+    (do* ((l list (%cdr l)))
+         ((endp l))
+      (when (eql (%car l) item) (return l)))
+    (memq item list)))
+
+(defun memequal (item list)
+  (do* ((l list (%cdr l)))
+       ((endp l))
+    (when (equal (%car l) item) (return l))))
+
+
+; (member-test item list test-fn) 
+;   <=> 
+;     (member item list :test test-fn :key #'identity)
+(defun member-test (item list test-fn)
+  (if (or (eq test-fn 'eq)(eq test-fn  #'eq)
+          (and (or (eq test-fn 'eql)(eq test-fn  #'eql))
+               (not (need-use-eql-macro item))))
+    (do* ((l list (cdr l)))
+         ((null l))
+      (when (eq item (car l))(return l)))
+    (if (or (eq test-fn 'eql)(eq test-fn  #'eql))
+      (do* ((l list (cdr l)))
+           ((null l))
+        (when (eql item (car l))(return l)))    
+      (do* ((l list (cdr l)))
+           ((null l))
+        (when (funcall test-fn item (car l)) (return l))))))
+
+(defun s32->u32 (s32)
+  (%stack-block ((buf 4))
+    (setf (%get-signed-long buf) s32)
+    (%get-unsigned-long buf)))
+
+(defun u32->s32 (u32)
+  (%stack-block ((buf 4))
+    (setf (%get-unsigned-long buf) u32)
+    (%get-signed-long buf)))
+
+
+; end
Index: /branches/new-random/level-0/nfasload.lisp
===================================================================
--- /branches/new-random/level-0/nfasload.lisp	(revision 13309)
+++ /branches/new-random/level-0/nfasload.lisp	(revision 13309)
@@ -0,0 +1,1207 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+
+(require "FASLENV" "ccl:xdump;faslenv")
+
+
+(defconstant $primsizes (make-array 23
+                                    :element-type '(unsigned-byte 16)
+                                    :initial-contents
+                                    '(41 61 97 149 223 337 509 769 887 971 1153 1559 1733
+                                      2609 2801 3917 5879 8819 13229 19843 24989 29789 32749)))
+(defconstant $hprimes (make-array 8 
+                                  :element-type '(unsigned-byte 16)
+                                  :initial-contents '(5 7 11 13 17 19 23 29)))
+
+;;; Symbol hash tables: (htvec . (hcount . hlimit))
+
+(defmacro htvec (htab) `(%car ,htab))
+(defmacro htcount (htab) `(%cadr ,htab))
+(defmacro htlimit (htab) `(%cddr ,htab))
+)
+
+(eval-when (:execute :compile-toplevel)
+  (assert (= 80 numfaslops)))
+
+
+
+
+
+(defvar *fasl-dispatch-table* #80(%bad-fasl))
+
+
+
+
+
+(defun %bad-fasl (s)
+  (error "bad opcode near position ~d in FASL file ~s"
+         (%fasl-get-file-pos s)
+         (faslstate.faslfname s)))
+
+(defun %cant-epush (s)
+  (if (faslstate.faslepush s)
+    (%bad-fasl s)))
+
+(defun %epushval (s val)
+  (setf (faslstate.faslval s) val)
+  (when (faslstate.faslepush s)
+    (setf (svref (faslstate.faslevec s) (faslstate.faslecnt s)) val)
+    (incf (the fixnum (faslstate.faslecnt s))))
+  val)
+
+(defun %simple-fasl-read-buffer (s)
+  (let* ((fd (faslstate.faslfd s))
+         (buffer (faslstate.iobuffer s))
+         (bufptr (%get-ptr buffer)))
+    (declare (dynamic-extent bufptr)
+             (type macptr buffer bufptr))
+    (%setf-macptr bufptr (%inc-ptr buffer target::node-size))
+    (setf (%get-ptr buffer) bufptr)
+    (let* ((n (fd-read fd bufptr $fasl-buf-len)))
+      (declare (fixnum n))
+      (if (> n 0)
+        (setf (faslstate.bufcount s) n)
+        (error "Fix this: look at errno, EOF")))))
+
+ 
+(defun %simple-fasl-read-byte (s)
+  (loop
+    (let* ((buffer (faslstate.iobuffer s))
+           (bufptr (%get-ptr buffer)))
+      (declare (dynamic-extent bufptr)
+               (type macptr buffer bufptr))
+      (if (>= (the fixnum (decf (the fixnum (faslstate.bufcount s))))
+              0)
+        (return
+         (prog1
+           (%get-unsigned-byte bufptr)
+           (setf (%get-ptr buffer)
+                 (%incf-ptr bufptr))))
+        (%fasl-read-buffer s)))))
+
+(defun %fasl-read-word (s)
+  (the fixnum 
+    (logior (the fixnum (ash (the fixnum (%fasl-read-byte s)) 8))
+            (the fixnum (%fasl-read-byte s)))))
+
+
+(defun %fasl-read-long (s)
+  (logior (ash (%fasl-read-word s) 16) (%fasl-read-word s)))
+
+(defun %fasl-read-signed-long (s)
+  (logior (ash (%word-to-int (%fasl-read-word s)) 16)
+          (%fasl-read-word s)))
+
+
+(defun %fasl-read-count (s)
+  (do* ((val 0)
+        (shift 0 (+ shift 7))
+        (done nil))
+       (done val)
+    (let* ((b (%fasl-read-byte s)))
+      (declare (type (unsigned-byte 8) b))
+      (setq done (logbitp 7 b) val (logior val (ash (logand b #x7f) shift))))))
+
+(defun %simple-fasl-read-n-bytes (s ivector byte-offset n)
+  (declare (fixnum byte-offset n))
+  (do* ()
+       ((= n 0))
+    (let* ((count (faslstate.bufcount s))
+           (buffer (faslstate.iobuffer s))
+           (bufptr (%get-ptr buffer))
+           (nthere (if (< count n) count n)))
+      (declare (dynamic-extent bufptr)
+               (type macptr buffer bufptr)
+               (fixnum count nthere))
+      (if (= nthere 0)
+        (%fasl-read-buffer s)
+        (progn
+          (decf n nthere)
+          (decf (the fixnum (faslstate.bufcount s)) nthere)
+          (%copy-ptr-to-ivector bufptr 0 ivector byte-offset nthere)
+          (incf byte-offset nthere)
+          (setf (%get-ptr buffer)
+                (%incf-ptr bufptr nthere)))))))
+        
+
+(defun %fasl-read-utf-8-string (s string nchars nextra)
+  (declare (fixnum nchars nextra))
+  (if (eql 0 nextra)
+    (dotimes (i nchars)
+      (setf (%scharcode string i) (%fasl-read-byte s)))
+    (flet ((trailer-byte ()
+             (when (> nextra 0)
+               (decf nextra)
+               (let* ((b (%fasl-read-byte s)))
+                 (declare ((unsigned-byte 8) b))
+                 (and (>= b #x80)
+                      (< b #xc0)
+                      (logand b #x3f))))))
+      (declare (inline trailer-byte))
+      (dotimes (i nchars)
+        (let* ((b0 (%fasl-read-byte s)))
+          (declare ((unsigned-byte 8) b0))
+          (setf (%scharcode string i)
+                (or
+                 (cond ((< b0 #x80) b0)
+                       ((and (>= b0 #xc2)
+                             (< b0 #xe0))
+                        (let* ((b1 (trailer-byte)))
+                          (and b1 (logior (ash (logand b0 #x1f) 6) b1))))
+                       ((and (>= b0 #xe0)
+                             (< b0 #xf0))
+                        (let* ((b1 (trailer-byte))
+                               (b2 (trailer-byte)))
+                          (and b1 b2 (logior (ash (logand b0 #x0f) 12)
+                                             (logior (ash b1 6)
+                                                     b2)))))
+                       ((and (>= b0 #xf0)
+                             (< b0 #xf5))
+                        (let* ((b1 (trailer-byte))
+                               (b2 (trailer-byte))
+                               (b3 (trailer-byte)))
+                          (and b1
+                               b2
+                               b3
+                               (logior (ash (logand b0 #x7) 18)
+                                       (logior (ash b1 12)
+                                               (logior (ash b2 6)
+                                                       b3)))))))
+                 (char-code #\Replacement_Character))))))))
+
+
+(defun %fasl-vreadstr (s)
+  (let* ((nchars (%fasl-read-count s))
+         (nextra (%fasl-read-count s))
+         (copy t)
+         (n nchars)
+         (str (faslstate.faslstr s)))
+    (declare (fixnum nchars n nextra))
+    (if (> n (length str))
+      (setq str (make-string n :element-type 'base-char))
+      (setq copy nil))
+    (%fasl-read-utf-8-string s str nchars nextra)
+    (values str nchars copy)))
+
+
+(defun %fasl-read-n-string (s string start n)
+  (declare (fixnum start n))
+  (do* ((i start (1+ i))
+        (n n (1- n)))
+       ((<= n 0))
+    (declare (fixnum i n))
+    (setf (%scharcode string i) (%fasl-read-byte s))))
+
+(defun %fasl-nvreadstr (s)
+  (let* ((nchars (%fasl-read-count s))
+         (copy t)
+         (n nchars)
+         (str (faslstate.faslstr s)))
+    (declare (fixnum n nchars))
+    (if (> n (length str))
+        (setq str (make-string n :element-type 'base-char))
+        (setq copy nil))
+    (%fasl-read-n-string  s str 0 nchars)
+    (values str n copy)))
+
+(defun %fasl-copystr (str len)
+  (declare (fixnum len))
+  (let* ((new (make-string len :element-type 'base-char)))
+    (declare (simple-base-string new))
+    (declare (optimize (speed 3)(safety 0)))
+    (dotimes (i len new)
+      (setf (schar new i) (schar str i)))))
+
+(defun %fasl-dispatch (s op)
+  (declare (fixnum op)) 
+  (setf (faslstate.faslepush s) (logbitp $fasl-epush-bit op))
+  #+debug
+  (format t "~& dispatch: op = ~d at ~x" (logand op (lognot (ash 1 $fasl-epush-bit)))
+          (1- (%fasl-get-file-pos s)))
+  (funcall (svref (faslstate.fasldispatch s) (logand op (lognot (ash 1 $fasl-epush-bit)))) 
+           s))
+
+(defun %fasl-expr (s)
+  (%fasl-dispatch s (%fasl-read-byte s))
+  (faslstate.faslval s))
+
+(defun %fasl-expr-preserve-epush (s)
+  (let* ((epush (faslstate.faslepush s))
+         (val (%fasl-expr s)))
+    (setf (faslstate.faslepush s) epush)
+    val))
+
+
+(defun %fasl-vmake-symbol (s &optional idx)
+  (let* ((n (%fasl-read-count s))
+         (nextra (%fasl-read-count s))
+         (str (make-string n :element-type 'base-char)))
+    (declare (fixnum n))
+    (%fasl-read-utf-8-string s str n nextra)
+    (let* ((sym (make-symbol str)))
+      (when idx (ensure-binding-index sym))
+      (%epushval s sym))))
+
+(defun %fasl-nvmake-symbol (s &optional idx)
+  (let* ((n (%fasl-read-count s))
+         (str (make-string n :element-type 'base-char)))
+    (declare (fixnum n))
+    (%fasl-read-n-string s str 0 n)
+    (let* ((sym (make-symbol str)))
+      (when idx (ensure-binding-index sym))
+      (%epushval s sym))))
+
+(defun %fasl-vintern (s package &optional binding-index)
+  (multiple-value-bind (str len new-p) (%fasl-vreadstr s)
+    (with-package-lock (package)
+      (multiple-value-bind (symbol access internal-offset external-offset)
+          (%find-symbol str len package)
+        (unless access
+          (unless new-p (setq str (%fasl-copystr str len)))
+          (setq symbol (%add-symbol str package internal-offset external-offset)))
+        (when binding-index
+          (ensure-binding-index symbol))
+        (%epushval s symbol)))))
+
+(defun %fasl-nvintern (s package &optional binding-index)
+  (multiple-value-bind (str len new-p) (%fasl-nvreadstr s)
+    (with-package-lock (package)
+      (multiple-value-bind (symbol access internal-offset external-offset)
+          (%find-symbol str len package)
+        (unless access
+          (unless new-p (setq str (%fasl-copystr str len)))
+          (setq symbol (%add-symbol str package internal-offset external-offset)))
+        (when binding-index
+          (ensure-binding-index symbol))
+        (%epushval s symbol)))))
+
+(defvar *package-refs*)
+(setq *package-refs* (make-hash-table :test #'equal))
+(defvar *package-refs-lock*)
+(setq *package-refs-lock* (make-lock))
+
+(defun register-package-ref (name)
+  (unless (typep name 'string)
+    (report-bad-arg name 'string))
+  (let* ((ref
+          (or (gethash name *package-refs*)
+              (with-lock-grabbed (*package-refs-lock*)
+                (or
+                 (gethash name *package-refs*) ; check again
+                 (let* ((r (make-package-ref name)))
+                   (setf (gethash name *package-refs*) r)))))))
+    (unless (package-ref.pkg ref)
+      (setf (package-ref.pkg ref) (find-package name)))
+    ref))
+
+
+(dolist (p %all-packages%)
+  (dolist (name (pkg.names p))
+    (setf (package-ref.pkg (register-package-ref name)) p)))
+
+
+(defun find-package (name)
+  (if (typep  name 'package)
+    name
+    (%find-pkg (string name))))
+
+(defun %pkg-ref-find-package (ref)
+  (package-ref.pkg ref))
+
+(defun set-package (name &aux (pkg (find-package name)))
+  (if pkg
+    (setq *package* pkg)
+    (set-package (%kernel-restart $xnopkg name))))
+
+  
+(defun %find-pkg (name &optional (len (length name)))
+  (declare (fixnum len))
+  (with-package-list-read-lock
+      (dolist (p %all-packages%)
+        (if (dolist (pkgname (pkg.names p))
+              (when (and (= (the fixnum (length pkgname)) len)
+                         (dotimes (i len t)
+                           ;; Aref: allow non-simple strings
+                           (unless (eq (aref name i) (schar pkgname i))
+                             (return))))
+                (return t)))
+          (return p)))))
+
+
+
+(defun pkg-arg (thing &optional deleted-ok)
+  (let* ((xthing (cond ((or (symbolp thing) (typep thing 'character))
+                        (string thing))
+                       ((typep thing 'string)
+                        (ensure-simple-string thing))
+                       (t
+                        thing))))
+    (let* ((typecode (typecode xthing)))
+        (declare (fixnum typecode))
+        (cond ((= typecode target::subtag-package)
+               (if (or deleted-ok (pkg.names xthing))
+                 xthing
+                 (error "~S is a deleted package ." thing)))
+              ((= typecode target::subtag-simple-base-string)
+               (or (%find-pkg xthing)
+                   (%kernel-restart $xnopkg xthing)))
+              (t (report-bad-arg thing 'simple-string))))))
+
+(defun %fasl-vpackage (s)
+  (multiple-value-bind (str len new-p) (%fasl-vreadstr s)
+    (let* ((p (%find-pkg str len)))
+      (%epushval s (or p (%kernel-restart $XNOPKG (if new-p str (%fasl-copystr str len))))))))
+
+
+(defun %fasl-nvpackage (s)
+  (multiple-value-bind (str len new-p) (%fasl-nvreadstr s)
+    (let* ((p (%find-pkg str len)))
+      (%epushval s (or p  (%kernel-restart $XNOPKG (if new-p str (%fasl-copystr str len))))))))
+
+(defun %fasl-vlistX (s dotp)
+  (let* ((len (%fasl-read-count s)))
+    (declare (fixnum len))
+    (let* ((val (%epushval s (cons nil nil)))
+           (tail val))
+      (declare (type cons val tail))
+      (setf (car val) (%fasl-expr s))
+      (dotimes (i len)
+        (setf (cdr tail) (setq tail (cons (%fasl-expr s) nil))))
+      (if dotp
+        (setf (cdr tail) (%fasl-expr s)))
+      (setf (faslstate.faslval s) val))))
+
+(deffaslop $fasl-noop (s)
+  (%cant-epush s))
+
+
+(deffaslop $fasl-vetab-alloc (s)
+  (%cant-epush s)
+  (setf (faslstate.faslevec s) (make-array (the fixnum (%fasl-read-count s)))
+        (faslstate.faslecnt s) 0))
+
+(deffaslop $fasl-platform (s)
+  (%cant-epush s)
+  (let* ((platform (%fasl-expr s))
+         (host-platform (%get-kernel-global 'host-platform)))
+    (declare (fixnum platform host-platform))
+    (unless (= platform host-platform)
+      (error "Not a native fasl file : ~s" (faslstate.faslfname s)))))
+
+
+(deffaslop $fasl-veref (s)
+  (let* ((idx (%fasl-read-count s)))
+    (declare (fixnum idx))
+    (if (>= idx (the fixnum (faslstate.faslecnt s)))
+      (%bad-fasl s))
+    (%epushval s (svref (faslstate.faslevec s) idx))))
+
+#+x86-target
+;;; Read a "concatenated" lisp function, in which the machine code
+;;; and constants are both contained in the same underlying uvector.
+(deffaslop $fasl-clfun (s)
+  (let* ((size-in-elements (%fasl-read-count s))
+         (size-of-code (%fasl-read-count s))
+         (vector (%alloc-misc size-in-elements target::subtag-function))
+         (function (function-vector-to-function vector)))
+    (declare (fixnum size-in-elements size-of-code))
+    (%epushval s function)
+    (%fasl-read-n-bytes s vector 0 (ash size-of-code target::word-shift))
+    #+x8632-target
+    (%update-self-references vector)
+    (do* ((numconst (- size-in-elements size-of-code))
+          (i 0 (1+ i))
+          (constidx size-of-code (1+ constidx)))
+         ((= i numconst)
+          (setf (faslstate.faslval s) function))
+      (declare (fixnum i numconst constidx))
+      (setf (%svref vector constidx) (%fasl-expr s)))))
+    
+    
+(deffaslop $fasl-lfuncall (s)
+  (let* ((fun (%fasl-expr-preserve-epush s)))
+    ;(break "fun = ~s" fun)
+     (%epushval s (funcall fun))))
+
+(deffaslop $fasl-globals (s)
+  (setf (faslstate.faslgsymbols s) (%fasl-expr s)))
+
+(deffaslop $fasl-char (s)
+  (%epushval s (code-char (%fasl-read-count s))))
+
+;;; Deprecated
+(deffaslop $fasl-fixnum (s)
+  (%epushval
+   s
+   (logior (the fixnum (ash (the fixnum (%word-to-int (%fasl-read-word s)))
+                            16))
+           (the fixnum (%fasl-read-word s))) ))
+
+(deffaslop $fasl-s32 (s)
+  (%epushval s (%fasl-read-signed-long s)))
+
+(deffaslop $fasl-s64 (s)
+  (%epushval s (logior (ash (%fasl-read-signed-long s) 32)
+                       (%fasl-read-long s))))
+
+(deffaslop $fasl-dfloat (s)
+  ;; A double-float is a 3-element "misc" object.
+  ;; Element 0 is always 0 and exists solely to keep elements 1 and 2
+  ;; aligned on a 64-bit boundary.
+  (%epushval s (double-float-from-bits (%fasl-read-long s) (%fasl-read-long s))))
+
+(deffaslop $fasl-sfloat (s)
+  (%epushval s (host-single-float-from-unsigned-byte-32 (%fasl-read-long s))))
+
+(deffaslop $fasl-vstr (s)
+  (let* ((nchars (%fasl-read-count s))
+         (nextra (%fasl-read-count s))
+         (str (make-string (the fixnum nchars) :element-type 'base-char)))
+    (%epushval s str)
+    (%fasl-read-utf-8-string s str nchars nextra)))
+
+
+(deffaslop $fasl-nvstr (s)
+  (let* ((n (%fasl-read-count s))
+         (str (make-string (the fixnum n) :element-type 'base-char)))
+    (%epushval s str)
+    (%fasl-read-n-string s str 0 n)))
+
+(deffaslop $fasl-word-fixnum (s)
+  (%epushval s (%word-to-int (%fasl-read-word s))))
+
+(deffaslop $fasl-vmksym (s)
+  (%fasl-vmake-symbol s))
+
+(deffaslop $fasl-nvmksym (s)
+  (%fasl-nvmake-symbol s))
+
+(deffaslop $fasl-vmksym-special (s)
+  (%fasl-vmake-symbol s t))
+
+(deffaslop $fasl-nvmksym-special (s)
+  (%fasl-nvmake-symbol s t))
+
+(deffaslop $fasl-vintern (s)
+  (%fasl-vintern s *package*))
+
+(deffaslop $fasl-nvintern (s)
+  (%fasl-nvintern s *package*))
+
+(deffaslop $fasl-vintern-special (s)
+  (%fasl-vintern s *package* t))
+
+(deffaslop $fasl-nvintern-special (s)
+  (%fasl-nvintern s *package* t))
+
+
+
+
+(deffaslop $fasl-vpkg-intern (s)
+  (let* ((pkg (%fasl-expr-preserve-epush s)))
+    #+paranoia
+    (setq pkg (pkg-arg pkg))
+    (%fasl-vintern s pkg)))
+
+(deffaslop $fasl-nvpkg-intern (s)
+  (let* ((pkg (%fasl-expr-preserve-epush s)))
+    #+paranoia
+    (setq pkg (pkg-arg pkg))
+    (%fasl-nvintern s pkg)))
+
+(deffaslop $fasl-vpkg-intern-special (s)
+  (let* ((pkg (%fasl-expr-preserve-epush s)))
+    #+paranoia
+    (setq pkg (pkg-arg pkg))
+    (%fasl-vintern s pkg t)))
+
+(deffaslop $fasl-nvpkg-intern-special (s)
+  (let* ((pkg (%fasl-expr-preserve-epush s)))
+    #+paranoia
+    (setq pkg (pkg-arg pkg))
+    (%fasl-nvintern s pkg t)))
+
+(deffaslop $fasl-vpkg (s)
+  (%fasl-vpackage s))
+
+(deffaslop $fasl-nvpkg (s)
+  (%fasl-nvpackage s))
+
+(deffaslop $fasl-cons (s)
+  (let* ((cons (%epushval s (cons nil nil))))
+    (declare (type cons cons))
+    (setf (car cons) (%fasl-expr s)
+          (cdr cons) (%fasl-expr s))
+    (setf (faslstate.faslval s) cons)))
+
+(deffaslop $fasl-vlist (s)
+  (%fasl-vlistX s nil))
+
+(deffaslop $fasl-vlist* (s)
+  (%fasl-vlistX s t))
+
+(deffaslop $fasl-nil (s)
+  (%epushval s nil))
+
+(deffaslop $fasl-timm (s)
+  (rlet ((p :int))
+    (setf (%get-long p) (%fasl-read-long s))
+    (%epushval s (%get-unboxed-ptr p))))
+
+(deffaslop $fasl-symfn (s)
+  (%epushval s (%function (%fasl-expr-preserve-epush s))))
+    
+(deffaslop $fasl-eval (s)
+  (%epushval s (eval (%fasl-expr-preserve-epush s))))
+
+;;; For bootstrapping. The real version is cheap-eval in l1-readloop
+(when (not (fboundp 'eval))
+  (defun eval (form)
+    (if (and (listp form)
+             (let ((f (%car form)))
+               (and (symbolp f)
+                    (functionp (fboundp f)))))
+      (do* ((tail (%cdr form) (%cdr tail)))
+           ((null tail) (apply (%car form) (%cdr form)))
+        (let* ((head (car tail)))
+          (when (and (consp head) (eq (car head) 'quote))
+            (setf (car tail) (cadr head)))))
+      (error "Can't eval yet: ~s" form))))
+
+
+(deffaslop $fasl-vivec (s)
+  (let* ((subtag (%fasl-read-byte s))
+         (element-count (%fasl-read-count s))
+         (size-in-bytes (subtag-bytes subtag element-count))
+         (vector (%alloc-misc element-count subtag))
+         (byte-offset (or #+32-bit-target (if (= subtag target::subtag-double-float-vector) 4) 0)))
+    (declare (fixnum subtag element-count size-in-bytes))
+    (%epushval s vector)
+    (%fasl-read-n-bytes s vector byte-offset size-in-bytes)
+    vector))
+
+(defun fasl-read-ivector (s subtag)
+  (let* ((element-count (%fasl-read-count s))
+         (size-in-bytes (subtag-bytes subtag element-count))
+         (vector (%alloc-misc element-count subtag)))
+    (declare (fixnum subtag element-count size-in-bytes))
+    (%epushval s vector)
+    (%fasl-read-n-bytes s vector 0 size-in-bytes)
+    vector))
+  
+(deffaslop $fasl-u8-vector (s)
+  (fasl-read-ivector s target::subtag-u8-vector))
+
+(deffaslop $fasl-s8-vector (s)
+  (fasl-read-ivector s target::subtag-s8-vector))
+
+(deffaslop $fasl-u16-vector (s)
+  (fasl-read-ivector s target::subtag-u16-vector))
+
+(deffaslop $fasl-s16-vector (s)
+  (fasl-read-ivector s target::subtag-s16-vector))
+
+(deffaslop $fasl-u32-vector (s)
+  (fasl-read-ivector s target::subtag-u32-vector))
+
+(deffaslop $fasl-s32-vector (s)
+  (fasl-read-ivector s target::subtag-s32-vector))
+
+#+64-bit-target
+(deffaslop $fasl-u64-vector (s)
+  (fasl-read-ivector s target::subtag-u64-vector))
+
+#+64-bit-target
+(deffaslop $fasl-u64-vector (s)
+  (fasl-read-ivector s target::subtag-s64-vector))
+
+(deffaslop $fasl-bit-vector (s)
+  (fasl-read-ivector s target::subtag-bit-vector))
+
+(deffaslop $fasl-bignum32 (s)
+  (let* ((element-count (%fasl-read-count s))
+         (size-in-bytes (* element-count 4))
+         (num (%alloc-misc element-count target::subtag-bignum)))
+    (declare (fixnum element-count size-in-bytes))
+    (%fasl-read-n-bytes s num 0 size-in-bytes)
+    (setq num (%normalize-bignum-2 t num))
+    (%epushval s num)
+    num))
+
+(deffaslop $fasl-single-float-vector (s)
+  (fasl-read-ivector s target::subtag-single-float-vector))
+
+(deffaslop $fasl-double-float-vector (s)
+  #+64-bit-target
+  (fasl-read-ivector s target::subtag-double-float-vector)
+  #+32-bit-target
+  (let* ((element-count (%fasl-read-count s))
+         (size-in-bytes (subtag-bytes target::subtag-double-float-vector
+                                      element-count))
+         (vector (%alloc-misc element-count
+                              target::subtag-double-float-vector)))
+    (declare (fixnum element-count size-in-bytes))
+    (%epushval s vector)
+    (%fasl-read-n-bytes s vector (- target::misc-dfloat-offset
+                                    target::misc-data-offset)
+                        size-in-bytes)
+    vector))
+
+
+
+#-x86-target
+(deffaslop $fasl-code-vector (s)
+  (let* ((element-count (%fasl-read-count s))
+         (size-in-bytes (* 4 element-count))
+         (vector (allocate-typed-vector :code-vector element-count)))
+    (declare (fixnum element-count size-in-bytes))
+    (%epushval s vector)
+    (%fasl-read-n-bytes s vector 0 size-in-bytes)
+    (%make-code-executable vector)
+    vector))
+
+(defun fasl-read-gvector (s subtype)
+  (let* ((n (%fasl-read-count s))
+         (vector (%alloc-misc n subtype)))
+    (declare (fixnum n subtype))
+    (%epushval s vector)
+    (dotimes (i n (setf (faslstate.faslval s) vector))
+      (setf (%svref vector i) (%fasl-expr s)))))
+
+(deffaslop $fasl-vgvec (s)
+  (let* ((subtype (%fasl-read-byte s)))
+    (fasl-read-gvector s subtype)))
+  
+(deffaslop $fasl-ratio (s)
+  (let* ((r (%alloc-misc target::ratio.element-count target::subtag-ratio)))
+    (%epushval s r)
+    (setf (%svref r target::ratio.numer-cell) (%fasl-expr s)
+          (%svref r target::ratio.denom-cell) (%fasl-expr s))
+    (setf (faslstate.faslval s) r)))
+
+(deffaslop $fasl-complex (s)
+  (let* ((c (%alloc-misc target::complex.element-count
+                         target::subtag-complex)))
+    (%epushval s c)
+    (setf (%svref c target::complex.realpart-cell) (%fasl-expr s)
+          (%svref c target::complex.imagpart-cell) (%fasl-expr s))
+    (setf (faslstate.faslval s) c)))
+
+(deffaslop $fasl-t-vector (s)
+  (fasl-read-gvector s target::subtag-simple-vector))
+
+(deffaslop $fasl-function (s)
+  (fasl-read-gvector s target::subtag-function))
+
+(deffaslop $fasl-istruct (s)
+  (fasl-read-gvector s target::subtag-istruct))
+
+(deffaslop $fasl-vector-header (s)
+  (fasl-read-gvector s target::subtag-vectorH))
+
+(deffaslop $fasl-array-header (s)
+  (fasl-read-gvector s target::subtag-arrayH))
+
+
+(deffaslop $fasl-defun (s)
+  (%cant-epush s)
+  (%defun (%fasl-expr s) (%fasl-expr s)))
+
+(deffaslop $fasl-macro (s)
+  (%cant-epush s)
+  (%macro (%fasl-expr s) (%fasl-expr s)))
+
+(deffaslop $fasl-defconstant (s)
+  (%cant-epush s)
+  (%defconstant (%fasl-expr s) (%fasl-expr s) (%fasl-expr s)))
+
+(deffaslop $fasl-defparameter (s)
+  (%cant-epush s)
+  (let* ((sym (%fasl-expr s))
+         (val (%fasl-expr s)))
+    (%defvar sym (%fasl-expr s))
+    (set sym val)))
+
+;;; (defvar var)
+(deffaslop $fasl-defvar (s)
+  (%cant-epush s)
+  (%defvar (%fasl-expr s)))
+
+;;; (defvar var initfom doc)
+(deffaslop $fasl-defvar-init (s)
+  (%cant-epush s)
+  (let* ((sym (%fasl-expr s))
+         (val (%fasl-expr s)))
+    (unless (%defvar sym (%fasl-expr s))
+      (set sym val))))
+
+
+(deffaslop $fasl-prog1 (s)
+  (let* ((val (%fasl-expr s)))
+    (%fasl-expr s)
+    (setf (faslstate.faslval s) val)))
+
+
+
+(deffaslop $fasl-src (s)
+  (%cant-epush s)
+  (let* ((source-file (%fasl-expr s)))
+    ; (format t "~& source-file = ~s" source-file)
+    (setq *loading-file-source-file* source-file)))
+
+(deffaslop $fasl-toplevel-location (s)
+  (%cant-epush s)
+  (setq *loading-toplevel-location* (%fasl-expr s)))
+
+(defvar *modules* nil)
+
+;;; Bootstrapping version
+(defun provide (module-name)
+  (push (string module-name) *modules*))
+
+(deffaslop $fasl-provide (s)
+  (provide (%fasl-expr s)))
+
+(deffaslop $fasl-istruct-cell (s)
+  (%epushval s (register-istruct-cell (%fasl-expr-preserve-epush s))))
+
+
+
+;;; files compiled with code coverage do this
+;; list of lfuns and (source-fn-name . vector-of-lfuns), the latter put there by fasloading.
+(defvar *code-covered-functions* nil)
+
+(defun register-code-covered-functions (functions)
+  ;; unpack the parent-note references - see comment at fcomp-digest-code-notes
+  (labels ((reg (lfun refs)
+	     (unless (memq lfun refs)
+	       (let* ((lfv (function-to-function-vector lfun))
+		      (start #+ppc-target 0 #+x86-target (%function-code-words lfun))
+		      (refs (cons lfun refs)))
+		 (declare (dynamic-extent refs))
+		 (loop for i from start below (uvsize lfv) as imm = (uvref lfv i)
+		       do (typecase imm
+			    (code-note
+			     (let ((parent (code-note-parent-note imm)))
+			       (when (integerp parent)
+				 (setf (code-note-parent-note imm) (uvref lfv parent)))))
+			    (function (reg imm refs))))))))
+    (loop for fn across functions do (reg fn nil)))
+  (let ((a (assoc (pathname *loading-file-source-file*)
+                  *code-covered-functions*
+                  :test #'(lambda (p q)
+			    (and (equalp (pathname-name p) (pathname-name q))
+				 ;; same name, so worth trying harder to match 'em up.
+				 (or (equal p q)
+				     (let ((p (full-pathname p)) (q (full-pathname q)))
+				       (and p q (equalp p q)))
+				     (let ((p (probe-file p)) (q (probe-file q)))
+				       (and p q (equalp p q)))))))))
+    (when (null a)
+      (push (setq a (list nil nil)) *code-covered-functions*))
+    (setf (car a) *loading-file-source-file* (cdr a) functions))
+  nil)
+
+;;; The loader itself
+
+(defun %simple-fasl-set-file-pos (s new)
+  (let* ((fd (faslstate.faslfd s))
+         (posoffset (fd-tell fd)))
+    (if (>= (decf posoffset new) 0)
+      (let* ((count (faslstate.bufcount s)))
+        (if (>= (decf count posoffset ) 0)
+          (progn
+            (setf (faslstate.bufcount s) posoffset)
+            (incf #+32-bit-target (%get-long (faslstate.iobuffer s))
+                  #+64-bit-target (%%get-signed-longlong (faslstate.iobuffer s)
+                                                        0)
+                  count)
+            (return-from %simple-fasl-set-file-pos nil)))))
+    (progn
+      (setf (faslstate.bufcount s) 0)
+      (fd-lseek fd new #$SEEK_SET))))
+
+(defun %simple-fasl-get-file-pos (s)
+  (- (fd-tell (faslstate.faslfd s)) (faslstate.bufcount s)))
+
+(defparameter *%fasload-verbose* t)
+
+;;; the default fasl file opener sets up the fasl state and checks the header
+(defun %simple-fasl-open (string s)
+  (let* ((ok nil)
+	 (fd (fd-open string #$O_RDONLY))
+	 (err 0))
+    (declare (fixnum fd))
+    (if (>= fd 0)
+      (if (< (fd-lseek fd 0 #$SEEK_END) 4)
+        (setq err $xnotfasl)
+        (progn
+          (setq err 0)
+          (setf (faslstate.bufcount s) 0
+                (faslstate.faslfd s) fd)
+          (fd-lseek fd 0 #$SEEK_SET)
+          (multiple-value-setq (ok err) (%fasl-check-header s))))
+      (setq err fd))
+    (unless (eql err 0) (setf (faslstate.faslerr s) err))
+    ok))
+
+;;; once the fasl state is set up, this checks the fasl header and
+;;; returns (values ok err)
+(defun %fasl-check-header (s)
+  (let* ((signature (%fasl-read-word s)))
+    (declare (fixnum signature))
+    (if (= signature $fasl-file-id)
+	(values t 0)
+      (if (= signature $fasl-file-id1)
+	  (progn
+	    (%fasl-set-file-pos s (%fasl-read-long s))
+	    (values t 0))
+	(values nil $xnotfasl)))))
+
+(defun %simple-fasl-close (s)
+  (let* ((fd (faslstate.faslfd s)))
+    (when fd (fd-close fd))))
+
+(defun %simple-fasl-init-buffer (s)
+  (declare (ignore s))
+  nil)
+
+(defvar *fasl-api* nil)
+(setf *fasl-api* (%istruct 'faslapi
+			   #'%simple-fasl-open
+			   #'%simple-fasl-close
+			   #'%simple-fasl-init-buffer
+			   #'%simple-fasl-set-file-pos
+			   #'%simple-fasl-get-file-pos
+			   #'%simple-fasl-read-buffer
+			   #'%simple-fasl-read-byte
+			   #'%simple-fasl-read-n-bytes))
+
+(defun %fasl-open (string s)
+  (funcall (faslapi.fasl-open *fasl-api*) string s))
+(defun %fasl-close (s)
+  (funcall (faslapi.fasl-close *fasl-api*) s))
+(defun %fasl-init-buffer (s)
+  (funcall (faslapi.fasl-init-buffer *fasl-api*) s))
+(defun %fasl-set-file-pos (s new)
+  (funcall (faslapi.fasl-set-file-pos *fasl-api*) s new))
+(defun %fasl-get-file-pos (s)
+  (funcall (faslapi.fasl-get-file-pos *fasl-api*) s))
+(defun %fasl-read-buffer (s)
+  (funcall (faslapi.fasl-read-buffer *fasl-api*) s))
+(defun %fasl-read-byte (s)
+  (funcall (faslapi.fasl-read-byte *fasl-api*) s))
+(defun %fasl-read-n-bytes (s ivector byte-offset n)
+  (funcall (faslapi.fasl-read-n-bytes *fasl-api*) s ivector byte-offset n))
+
+(defun %fasload (string &optional (table *fasl-dispatch-table*))
+  ;;(dbg string) 
+  (when (and *%fasload-verbose*
+	     (not *load-verbose*))
+    (%string-to-stderr ";Loading ") (pdbg string))
+  (let* ((s (%istruct
+             'faslstate
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil
+             nil)))
+    (declare (dynamic-extent s))
+    (setf (faslstate.faslfname s) string)
+    (setf (faslstate.fasldispatch s) table)
+    (setf (faslstate.faslversion s) 0)
+    (%stack-block ((buffer (+ target::node-size $fasl-buf-len)))
+      (setf (faslstate.iobuffer s) buffer)
+      (%fasl-init-buffer s)
+      (let* ((parse-string (make-string 255 :element-type 'base-char)))
+        (declare (dynamic-extent parse-string))
+        (setf (faslstate.oldfaslstr s) nil
+              (faslstate.faslstr s) parse-string)
+	(unwind-protect
+             (when (%fasl-open string s)
+               (let* ((nblocks (%fasl-read-word s)))
+                 (declare (fixnum nblocks))
+                 (unless (= nblocks 0)
+                   (let* ((pos (%fasl-get-file-pos s)))
+                     (dotimes (i nblocks)
+                       (%fasl-set-file-pos s pos)
+                       (%fasl-set-file-pos s (%fasl-read-long s))
+                       (incf pos 8)
+                       (let* ((version (%fasl-read-word s)))
+                         (declare (fixnum version))
+                         (if (or (> version (+ #xff00 $fasl-vers))
+                                 (< version (+ #xff00 $fasl-min-vers)))
+                           (%err-disp (if (>= version #xff00) $xfaslvers $xnotfasl))
+                           (progn
+                             (setf (faslstate.faslversion s) version)
+                             (%fasl-read-word s) 
+                             (%fasl-read-word s) ; Ignore kernel version stuff
+                             (setf (faslstate.faslevec s) nil
+                                   (faslstate.faslecnt s) 0)
+                             (do* ((op (%fasl-read-byte s) (%fasl-read-byte s)))
+                                  ((= op $faslend))
+                               (declare (fixnum op))
+                               (%fasl-dispatch s op))))))))))
+	  (%fasl-close s))
+	(let* ((err (faslstate.faslerr s)))
+	  (if err
+            (progn
+              (when *%fasload-verbose*
+                (let* ((herald ";!!Error loading ")
+                       (hlen (length herald))
+                       (len (length string))
+                       (msg (make-string (+ hlen len))))
+                  (declare (dynamic-extent msg))
+                  (%copy-ivector-to-ivector herald 0 msg 0 (* hlen 4))
+                  (%copy-ivector-to-ivector string 0 msg (* hlen 4) (* len 4))
+                  (bug msg)))
+              (values nil err))
+            (values t nil)))))))
+
+
+(defun %new-package-hashtable (size)
+  (%initialize-htab (cons nil (cons 0 0)) size))
+
+(defun %initialize-htab (htab size)
+  (declare (fixnum size))
+  ;; Ensure that "size" is relatively prime to all secondary hash values.
+  ;; If it's small enough, pick the next highest known prime out of the
+  ;; "primsizes" array.  Otherwize, iterate through all all of "hprimes"
+  ;; until we find something relatively prime to all of them.
+  (setq size
+        (if (> size 32749)
+          (do* ((nextsize (logior 1 size) (+ nextsize 2)))
+               ()
+            (declare (fixnum nextsize))
+            (when (dotimes (i 8 t)
+                    (unless (eql 1 (gcd nextsize (uvref #.$hprimes i)))
+                      (return)))
+              (return nextsize)))
+          (dotimes (i (the fixnum (length #.$primsizes)))
+            (let* ((psize (uvref #.$primsizes i)))
+              (declare (fixnum psize))
+              (if (>= psize size) 
+                (return psize))))))
+  (setf (htvec htab) (make-array size #|:initial-element 0|#))
+  (setf (htcount htab) 0)
+  (setf (htlimit htab) (the fixnum (- size (the fixnum (ash size -3)))))
+  htab)
+
+
+(defun %resize-htab (htab)
+  (declare (optimize (speed 3) (safety 0)))
+  (without-interrupts
+   (let* ((old-vector (htvec htab))
+          (old-len (length old-vector)))
+     (declare (fixnum old-len)
+              (simple-vector old-vector))
+     (let* ((nsyms 0))
+       (declare (fixnum nsyms))
+       (dovector (s old-vector)
+         (when (symbolp s) (incf nsyms)))
+       (%initialize-htab htab 
+                         (the fixnum (+ 
+                                      (the fixnum 
+                                        (+ nsyms (the fixnum (ash nsyms -2))))
+                                      2)))
+       (let* ((new-vector (htvec htab))
+              (nnew 0))
+         (declare (fixnum nnew)
+                  (simple-vector new-vector))
+         (dotimes (i old-len (setf (htcount htab) nnew))
+           (let* ((s (svref old-vector i)))
+               (if (symbolp s)
+                 (let* ((pname (symbol-name s)))
+                   (setf (svref 
+                          new-vector 
+                          (nth-value 
+                           2
+                           (%get-htab-symbol 
+                            pname
+                            (length pname)
+                            htab)))
+                         s)
+                   (incf nnew)))))
+         htab)))))
+        
+(defun hash-pname (str len)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((primary (%pname-hash str len)))
+    (declare (fixnum primary))
+    (values primary (aref (the (simple-array (unsigned-byte 16) (8)) $hprimes) (logand primary 7)))))
+    
+
+
+(defun %get-hashed-htab-symbol (str len htab primary secondary)
+  (declare (optimize (speed 3) (safety 0))
+           (fixnum primary secondary len))
+  (let* ((vec (htvec htab))
+         (vlen (length vec)))
+    (declare (fixnum vlen))
+    (do* ((idx (fast-mod primary vlen) (+ i secondary))
+          (i idx (if (>= idx vlen) (- idx vlen) idx))
+          (elt (svref vec i) (svref vec i)))
+         ((eql elt 0) (values nil nil i))
+      (declare (fixnum i idx))
+      (when (symbolp elt)
+        (let* ((pname (symbol-name elt)))
+          (if (and 
+               (= (the fixnum (length pname)) len)
+               (dotimes (j len t)
+                 (unless (eq (aref str j) (schar pname j))
+                   (return))))
+            (return (values t (%symptr->symbol elt) i))))))))
+
+(defun %get-htab-symbol (string len htab)
+  (declare (optimize (speed 3) (safety 0)))
+  (multiple-value-bind (p s) (hash-pname string len)
+    (%get-hashed-htab-symbol string len htab p s)))
+
+(defun %find-symbol (string len package)
+  (declare (optimize (speed 3) (safety 0)))
+  (multiple-value-bind (found-p sym internal-offset)
+                       (%get-htab-symbol string len (pkg.itab package))
+    (if found-p
+      (values sym :internal internal-offset nil)
+      (multiple-value-bind (found-p sym external-offset)
+                           (%get-htab-symbol string len (pkg.etab package))
+        (if found-p
+          (values sym :external internal-offset external-offset)
+          (dolist (p (pkg.used package) (values nil nil internal-offset external-offset))
+            (multiple-value-bind (found-p sym)
+                                 (%get-htab-symbol string len (pkg.etab p))
+              (when found-p
+                (return (values sym :inherited internal-offset external-offset))))))))))
+          
+(defun %htab-add-symbol (symbol htab idx)
+  (declare (optimize (speed 3) (safety 0)))
+  (setf (svref (htvec htab) idx) (%symbol->symptr symbol))
+  (if (>= (incf (the fixnum (htcount htab)))
+          (the fixnum (htlimit htab)))
+    (%resize-htab htab))
+  symbol)
+
+(defun %set-symbol-package (symbol package-or-nil)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((symvec (symptr->symvector (%symbol->symptr symbol)))
+         (old-pp (%svref symvec target::symbol.package-predicate-cell)))
+    (if (consp old-pp)
+      (setf (car old-pp) package-or-nil)
+      (setf (%svref symvec target::symbol.package-predicate-cell) package-or-nil))))
+
+
+(let* ((force-export-packages (list *keyword-package*))
+       (force-export-packages-lock (make-lock)))
+  (defun force-export-packages ()
+    (with-lock-grabbed (force-export-packages-lock)
+      (copy-list force-export-packages)))
+  (defun package-force-export (p)
+    (let* ((pkg (pkg-arg p)))
+      (with-lock-grabbed (force-export-packages-lock)
+        (pushnew pkg force-export-packages))
+    pkg))
+  (defun force-export-package-p (pkg)
+    (with-lock-grabbed (force-export-packages-lock)
+      (if (memq pkg force-export-packages)
+        t))))
+
+
+(defun %insert-symbol (symbol package internal-idx external-idx &optional force-export)
+  (let* ((symvec (symptr->symvector (%symbol->symptr symbol)))
+         (package-predicate (%svref symvec target::symbol.package-predicate-cell))
+         (keyword-package (eq package *keyword-package*)))
+    ;; Set home package
+    (if package-predicate
+      (if (listp package-predicate)
+        (unless (%car package-predicate) (%rplaca package-predicate package)))
+      (setf (%svref symvec target::symbol.package-predicate-cell) package))
+    (if (or force-export (force-export-package-p package))
+      (progn
+        (%htab-add-symbol symbol (pkg.etab package) external-idx)
+        (if keyword-package
+          ;;(define-constant symbol symbol)
+          (progn
+            (%set-sym-global-value symbol symbol)
+            (%symbol-bits symbol 
+                          (logior (ash 1 $sym_vbit_special) 
+                                  (ash 1 $sym_vbit_const)
+                                  (the fixnum (%symbol-bits symbol)))))))
+      (%htab-add-symbol symbol (pkg.itab package) internal-idx))
+    (let* ((hook (pkg.intern-hook package)))
+      (when hook (funcall hook symbol)))
+    symbol))
+
+;;; PNAME must be a simple string!
+(defun %add-symbol (pname package internal-idx external-idx &optional force-export)
+  (let* ((sym (make-symbol pname)))
+    (%insert-symbol sym package internal-idx external-idx force-export)))
+
+
+
+
+;;; The initial %toplevel-function% sets %toplevel-function% to NIL;
+;;; if the %fasload call fails, the lisp should exit (instead of
+;;; repeating the process endlessly ...
+
+
+(defvar %toplevel-function%
+  #'(lambda ()
+      (declare (special *xload-cold-load-functions*
+                        *xload-cold-load-documentation*
+                        *xload-startup-file*
+                        *early-class-cells*))
+      (%set-tcr-toplevel-function (%current-tcr) nil) ; should get reset by l1-boot.
+      (setq %system-locks% (%cons-population nil))
+      ;; Need to make %ALL-PACKAGES-LOCK% early, so that we can casually
+      ;; do SET-PACKAGE in cold load functions.
+      (setq %all-packages-lock% (make-read-write-lock))
+      (dolist (f (prog1 *xload-cold-load-functions* (setq *xload-cold-load-functions* nil)))
+        (funcall f))
+      (dolist (pair (prog1 *early-class-cells* (setq *early-class-cells* nil)))
+        (setf (gethash (car pair) %find-classes%) (cdr pair)))
+      (dolist (p %all-packages%)
+        (%resize-htab (pkg.itab p))
+        (%resize-htab (pkg.etab p)))
+      (dolist (f (prog1 *xload-cold-load-documentation* (setq *xload-cold-load-documentation* nil)))
+        (apply 'set-documentation f))
+      ;; Can't bind any specials until this happens
+      (let* ((max 0))
+        (%map-areas #'(lambda (symvec)
+                        (when (= (the fixnum (typecode symvec))
+                                 target::subtag-symbol)
+                          (let* ((s (symvector->symptr symvec))
+				 (idx (symbol-binding-index s)))
+                            (when (> idx 0)
+                              (cold-load-binding-index s))
+                            (when (> idx max)
+                              (setq max idx))))))
+        (%set-binding-index max))
+      (%fasload *xload-startup-file*)))
+
Index: /branches/new-random/level-1/.cvsignore
===================================================================
--- /branches/new-random/level-1/.cvsignore	(revision 13309)
+++ /branches/new-random/level-1/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/level-1/l1-application.lisp
===================================================================
--- /branches/new-random/level-1/l1-application.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-application.lisp	(revision 13309)
@@ -0,0 +1,314 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Portions Copyright (C) 2001-2009, Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;; Application classes
+
+(defstruct command-line-argument
+  keyword
+  help-string
+  option-char
+  long-name
+  may-take-operand
+  allow-multiple			; option can appear multiple times
+)
+
+(defvar *standard-help-argument*
+  (make-command-line-argument
+   :keyword :help
+   :help-string "this text"
+   :option-char #\h
+   :long-name "help"))
+
+(defvar *standard-version-argument*
+  (make-command-line-argument
+   :keyword :version
+   :help-string "print (LISP-IMPLEMENTATION-VERSION) and exit"
+   :option-char #\V
+   :long-name "version"))
+
+(defvar *standard-terminal-encoding-argument*
+  (make-command-line-argument
+   :option-char #\K
+   :long-name "terminal-encoding"
+   :help-string "specify character encoding to use for *TERMINAL-IO*"
+   :may-take-operand t
+   :keyword :terminal-encoding
+   :allow-multiple nil))
+
+(defclass application ()
+    ((command-line-arguments
+      :initform
+      (list *standard-help-argument* *standard-version-argument*))
+     (ui-object :initform nil :initarg :ui-object :accessor application-ui-object)))
+       
+(defclass ui-object ()
+    ())
+
+;;; It's intended that this be specialized ...
+(defmethod ui-object-do-operation ((u ui-object) operation &rest args)
+  (declare (ignore operation args)))
+
+
+(defun %usage-exit (banner exit-status other-args)
+  (with-cstrs ((banner banner)
+	       (other-args other-args))
+    (ff-call (%kernel-import target::kernel-import-usage-exit)
+	     :address banner
+	     :signed-fullword exit-status
+	     :address other-args
+	     :void)))
+
+(defloadvar *unprocessed-command-line-arguments* ())
+
+;;; Returns four values: error-flag, options-alist, non-option-arguments, unprocessed arguments
+(defmethod parse-application-arguments ((a application))
+  (let* ((cla (slot-value a 'command-line-arguments))
+	 (vals (cdr *command-line-argument-list*))
+	 (options ())
+	 (non-options ())
+         (rest-arg nil))
+    (do* ()
+	 ((null vals)
+	  (values nil (nreverse options) (nreverse non-options) rest-arg))
+      (let* ((val (pop vals))
+	     (val-len (length val))
+	     (short-p nil)
+	     (option
+	      (if (and (>= val-len 2)
+		       (eql (schar val 0) #\-))
+		(if (eql (schar val 1) #\-)
+		  (find val cla
+			:key #'command-line-argument-long-name
+			:test #'(lambda (k v) (string= k v :start1 2)))
+		  (progn
+		    (setq short-p t)
+		    (find (schar val 1) cla
+			  :key #'command-line-argument-option-char))))))
+	(if (null option)
+	  (if (and (>= val-len 1)
+		   (eql (schar val 0) #\-))
+            (if (and (= val-len 2)
+                     (eql (schar val 1) #\-))
+              (setq rest-arg vals
+                    vals nil)
+              (return (values :unknown-option val nil nil)))
+	    (push val non-options))	;non-option argument
+	  ;; We recognized the option.  Is it a duplicate of
+	  ;; something already seen?
+	  (let* ((key (command-line-argument-keyword option))
+		 (operand nil))
+	    (when (and (assoc key options)
+		       (not (command-line-argument-allow-multiple option)))
+	      (return (values :duplicate-option val nil)))
+	    (when (command-line-argument-may-take-operand option)
+	      ;; A short option name can be followed by the operand,
+	      ;; without intervening whitespace.
+	      (if (and short-p (> val-len 2))
+		(setq operand (subseq val 2))
+		(if vals
+		  (setq operand (pop vals))
+		  (return (values :missing-operand val nil)))))
+	    (push (cons key operand) options)))))))
+
+(defmethod summarize-option-syntax ((a application))
+  (flet ((summarize-option (o)
+	   (format nil "~8t-~a, --~a : ~a~%"
+		   (command-line-argument-option-char o)
+		   (command-line-argument-long-name o)
+		   (command-line-argument-help-string o))))
+    (format nil "~{~a~}" (mapcar #'summarize-option
+				 (slot-value a 'command-line-arguments)))))
+
+  
+;;; Process the "help" and "version" options, report parsing errors.
+(defmethod process-application-arguments ((a application) error-flag opts args)
+  (declare (ignore args))
+  (if (null error-flag)
+    (if (assoc :help opts)
+      (%usage-exit "" 0 (summarize-option-syntax a))
+      (if (assoc :version opts)
+        ;; Can't use lisp streams yet.
+	(progn
+          (with-cstrs ((s (format nil "~&~a~&" (application-version-string a))))
+            (fd-write 1 s (%cstrlen s)))
+	  (#_ _exit 0))
+        (let* ((encoding (assoc :terminal-encoding opts)))
+          (when (cdr encoding)
+            (let* ((encoding-name
+                    (let* ((*package* (find-package "KEYWORD")))
+                      (ignore-errors (read-from-string (cdr encoding))))))
+              (when encoding-name
+                (let* ((character-encoding (lookup-character-encoding encoding-name)))
+                  (when character-encoding
+                    (setq *terminal-character-encoding-name*
+                          (character-encoding-name character-encoding))))))))))
+    (%usage-exit
+     (format nil
+	     (case error-flag
+	       (:missing-argument "Missing argument to ~a option")
+	       (:duplicate-argument "Duplicate ~a option")
+	       (:unknown-option "Unknown option: ~a")
+	       (t "~a"))
+	     opts)
+     #-windows-target #$EX_USAGE #+windows-target #$EXIT_FAILURE
+     (summarize-option-syntax a))))
+	       
+
+;;; an example method to base a specialization on
+(defmethod toplevel-function  ((a application) init-file)
+  (declare (ignore init-file))
+  nil )
+
+(defmethod toplevel-function :before ((a application) init-file)
+  (declare (ignore init-file))
+  (multiple-value-bind (error-flag options args rest-arg)
+      (parse-application-arguments a)
+    (setq *unprocessed-command-line-arguments* rest-arg)
+    (process-application-arguments a error-flag options args)
+    (let* ((encoding (lookup-character-encoding *terminal-character-encoding-name*)))
+      (when encoding
+         (set-terminal-encoding (character-encoding-name encoding))))))
+
+(defmethod repl-function-name ((a application))
+  "Return the name of a function that should be run in a TTY-like
+listener thread (if that concept makes sense); return NIL otherwise."
+  nil)
+
+(defmethod application-version-string ((a application))
+  "Return a string which (arbitrarily) represents the application version.
+Default version returns Clozure CL version info."
+  (lisp-implementation-version))
+
+(defmethod application-ui-operation ((a application) operation &rest args)
+  (let* ((ui-object (application-ui-object a)))
+    (when ui-object
+      (apply #'ui-object-do-operation ui-object operation args))))
+
+
+
+
+(defmethod application-init-file     ((app application)) nil)
+
+
+(defclass lisp-development-system (application) 
+  ((command-line-arguments
+    :initform
+    (list *standard-help-argument*
+	  *standard-version-argument*
+          *standard-terminal-encoding-argument*
+	  (make-command-line-argument
+	   :option-char #\n
+	   :long-name "no-init"
+	   :keyword :noinit
+	   :help-string "suppress loading of init file")
+	  (make-command-line-argument
+	   :option-char #\e
+	   :long-name "eval"
+	   :keyword :eval
+	   :help-string "evaluate <form> (may need to quote <form> in shell)"
+	   :may-take-operand t
+	   :allow-multiple t)
+	  (make-command-line-argument
+	   :option-char #\l
+	   :long-name "load"
+	   :keyword :load
+	   :help-string "load <file>"
+	   :may-take-operand t
+	   :allow-multiple t)
+	  (make-command-line-argument
+	   :option-char #\T
+	   :long-name "set-lisp-heap-gc-threshold"
+	   :help-string "set lisp-heap-gc-threshold to <n>"
+	   :keyword :gc-threshold
+	   :may-take-operand t
+	   :allow-multiple nil)
+          (make-command-line-argument
+           :option-char #\Q
+           :long-name "quiet"
+           :help-string "if --batch, also suppress printing of heralds, prompts"
+           :keyword :quiet
+           :may-take-operand nil
+           :allow-multiple nil)
+          ))
+   (initial-listener-process :initform nil)))
+
+(defparameter *application*
+  (make-instance 'lisp-development-system))
+
+(defvar *load-lisp-init-file* t)
+(defvar *lisp-startup-parameters* ())
+
+(defmethod process-application-arguments ((a lisp-development-system)
+					  error-flag options args)
+  (declare (ignorable error-flag))
+  (call-next-method)			; handle help, errors
+  (if args
+    (%usage-exit (format nil "Unrecognized non-option arguments: ~a" args)
+		 #-windows-target #$EX_USAGE #+windows-target #$EXIT_FAILURE
+		 (summarize-option-syntax a))
+    (progn
+      (setq *load-lisp-init-file* (not (assoc :noinit options))
+            *quiet-flag* (if *batch-flag*
+                           (not (null (assoc :quiet options))))
+            *lisp-startup-parameters*
+            (mapcan #'(lambda (x)
+                        (and (member (car x) '(:load :eval :gc-threshold)) (list x)))
+                    options)))))
+	
+
+(defmethod repl-function-name ((a lisp-development-system))
+  'listener-function)
+
+(defmethod toplevel-function ((a lisp-development-system) init-file)
+  (let* ((sr (input-stream-shared-resource *terminal-input*))
+         (f (or (repl-function-name a) 'listener-function)))
+    (with-slots (initial-listener-process) a
+      (setq initial-listener-process
+            (make-mcl-listener-process
+             "listener"
+             *terminal-input*
+             *terminal-output*
+             #'(lambda () (when sr (setf (shared-resource-primary-owner sr)
+                                         *initial-process*)))
+             :initial-function
+             #'(lambda ()
+                 (startup-ccl (and *load-lisp-init-file* init-file))
+                 (funcall f)
+                 nil)
+             :close-streams nil
+             :control-stack-size *initial-listener-default-control-stack-size*
+             :value-stack-size *initial-listener-default-value-stack-size*
+             :temp-stack-size *initial-listener-default-temp-stack-size*
+             :class 'tty-listener
+             :process initial-listener-process))))
+  (%set-toplevel #'housekeeping-loop)
+  (toplevel))
+
+(defun housekeeping-loop ()
+  (with-standard-abort-handling nil 
+    (loop
+      #+windows-target (#_SleepEx 333 #$true)
+      #-windows-target (%nanosleep *periodic-task-seconds* *periodic-task-nanoseconds*)
+      (housekeeping))))
+  
+
+(defmethod application-init-file ((app lisp-development-system))
+  ;; This is the init file loaded before cocoa.
+  #+unix '("home:ccl-init" "home:\\.ccl-init")
+  #+windows "home:ccl-init")
Index: /branches/new-random/level-1/l1-aprims.lisp
===================================================================
--- /branches/new-random/level-1/l1-aprims.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-aprims.lisp	(revision 13309)
@@ -0,0 +1,3636 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; L1-aprims.lisp
+
+
+(in-package "CCL")
+
+
+(let* ((standard-initial-bindings ())
+       (standard-initial-bindings-lock (make-read-write-lock)))
+
+  (defun standard-initial-bindings ()
+    (with-read-lock (standard-initial-bindings-lock)
+      (copy-list standard-initial-bindings)))
+
+  (defun define-standard-initial-binding (symbol initform)
+    (setq symbol (require-type symbol 'symbol))
+    (%proclaim-special symbol)
+    (unless (boundp symbol)
+      (set symbol (funcall initform)))
+    (with-write-lock (standard-initial-bindings-lock)
+      (let* ((pair (assoc symbol standard-initial-bindings)))
+	(if pair
+	  (setf (cdr pair) initform)
+	  (push (cons symbol initform) standard-initial-bindings))))
+    (record-source-file symbol 'variable)
+    symbol))
+
+(defstatic *kernel-tcr-area-lock* (%make-lock (%null-ptr) "Kernel tcr-area-lock"))
+
+(defstatic *kernel-exception-lock* (%make-lock (%null-ptr) "Kernel exception-lock"))
+  
+(def-ccl-pointers kernel-locks ()
+  (let* ((p (recursive-lock-ptr *kernel-tcr-area-lock*))
+         (q (recursive-lock-ptr *kernel-exception-lock*)))
+    (%revive-macptr p)
+    (%revive-macptr q)
+    (%get-kernel-global-ptr area-lock p)
+    (%get-kernel-global-ptr exception-lock q)))
+
+(def-standard-initial-binding *package*)
+(def-standard-initial-binding *gensym-counter* 0)
+(def-standard-initial-binding *random-state* (initialize-random-state #xFBF1 9))
+(def-standard-initial-binding *whostate* "Reset")
+(setq *whostate* "Reset")
+(def-standard-initial-binding *error-print-length* 20)
+(def-standard-initial-binding *error-print-level* 8)
+
+(defun %badarg (arg type)
+  (%err-disp $XWRONGTYPE arg type))
+
+(defun atom (arg)
+  "Return true if OBJECT is an ATOM, and NIL otherwise."
+  (not (consp arg)))
+
+(defun list (&rest args)
+  "Return constructs and returns a list of its arguments."
+  args)
+
+(%fhave '%temp-list #'list)
+
+(defun list* (arg &rest others)
+  "Return a list of the arguments with last cons a dotted pair"
+  (cond ((null others) arg)
+	((null (cdr others)) (cons arg (car others)))
+	(t (do ((x others (cdr x)))
+	       ((null (cddr x)) (rplacd x (cadr x))))
+	   (cons arg others))))
+
+
+
+(defun funcall (fn &rest args)
+  "Call FUNCTION with the given ARGUMENTS."
+  (declare (dynamic-extent args))
+  (apply fn args))
+
+
+(defun apply (function arg &rest args)
+  "Apply FUNCTION to a list of arguments produced by evaluating ARGUMENTS in
+   the manner of LIST*. That is, a list is made of the values of all but the
+   last argument, appended to the value of the last argument, which must be a
+   list."
+  (declare (dynamic-extent args))
+  (cond ((null args)
+	 (apply function arg))
+	((null (cdr args))
+	 (apply function arg (car args)))
+	(t (do* ((a1 args a2)
+		 (a2 (cdr args) (cdr a2)))
+		((atom (cdr a2))
+		 (rplacd a1 (car a2))
+		 (apply function arg args))))))
+
+
+;;; This is not fast, but it gets the functionality that
+;;; Wood and possibly other code depend on.
+(defun applyv (function arg &rest other-args)
+  (declare (dynamic-extent other-args))
+  (let* ((other-args (cons arg other-args))
+	 (last-arg (car (last other-args)))
+	 (last-arg-length (length last-arg))
+	 (butlast-args (nbutlast other-args))
+	 (rest-args (make-list last-arg-length))
+	 (rest-args-tail rest-args))
+    (declare (dynamic-extent other-args rest-args))
+    (dotimes (i last-arg-length)
+      (setf (car rest-args-tail) (aref last-arg i))
+      (pop rest-args-tail))
+    (apply function (nconc butlast-args rest-args))))
+
+;;; This is slow, and since %apply-lexpr isn't documented either,
+;;; nothing in the world should depend on it.  This is just being
+;;; anal retentive.  VERY anal retentive.
+
+(defun %apply-lexpr (function arg &rest args)
+  (cond ((null args) (%apply-lexpr function arg))
+        (t (apply function arg (nconc (nbutlast args)
+                                      (collect-lexpr-args (car (last args)) 0))))))
+
+
+(defun values-list (arg)
+  "Return all of the elements of LIST, in order, as values."
+  (apply #'values arg))
+
+
+
+
+
+
+; copy-list
+
+(defun copy-list (list)
+  "Return a new list which is EQUAL to LIST."
+  (if list
+    (let ((result (cons (car list) '()) ))
+      (do ((x (cdr list) (cdr x))
+           (splice result
+                   (%cdr (%rplacd splice (cons (%car x) '() ))) ))
+          ((atom x) (unless (null x)
+                      (%rplacd splice x)) result)))))
+
+(defun alt-list-length (l)
+  "Detect (and complain about) cirucular lists; allow any atom to
+terminate the list"
+  (do* ((n 0 (1+ n))
+        (fast l)
+        (slow l))
+       ((atom fast) n)
+    (declare (fixnum n))
+    (setq fast (cdr fast))
+    (if (logbitp 0 n)
+      (if (eq (setq slow (cdr slow)) fast)
+	(%err-disp $XIMPROPERLIST l)))))
+
+
+(defun last (list &optional (n 1))
+  "Return the last N conses (not the last element!) of a list."
+  (if (and (typep n 'fixnum)
+	   (>= (the fixnum n) 0))
+    (locally (declare (fixnum n))
+      (do* ((checked-list list (cdr checked-list))
+	    (returned-list list)
+	    (index 0 (1+ index)))
+	   ((atom checked-list) returned-list)
+	(declare (type fixnum index))
+	(if (>= index n)
+	  (pop returned-list))))
+    (if (and (typep n 'bignum)
+	     (> n 0))
+      (require-type list 'list)
+      (report-bad-arg  n 'unsigned-byte))))
+
+
+
+
+
+(defun nthcdr (index list)
+  "Performs the cdr function n times on a list."
+  (setq list (require-type list 'list))
+  (if (and (typep index 'fixnum)
+	   (>= (the fixnum index) 0))
+      (locally (declare (fixnum index))
+	(dotimes (i index list)
+	  (when (null (setq list (cdr list))) (return))))
+      (progn
+	(unless (typep index 'unsigned-byte)
+	  (report-bad-arg index 'unsigned-byte))
+	(do* ((n index (- n target::target-most-positive-fixnum)))
+	     ((typep n 'fixnum) (nthcdr n list))
+	  (unless (setq list (nthcdr target::target-most-positive-fixnum list))
+	    (return))))))
+
+
+(defun nth (index list)
+  "Return the nth object in a list where the car is the zero-th element."
+  (car (nthcdr index list)))
+
+
+(defun nconc (&rest lists)
+  (declare (dynamic-extent lists))
+  "Concatenates the lists given as arguments (by changing them)"
+  (do* ((top lists (cdr top)))
+       ((null top) nil)
+    (let* ((top-of-top (car top)))
+      (cond
+       ((consp top-of-top)
+        (let* ((result top-of-top)
+               (splice result))
+          (do* ((elements (cdr top) (cdr elements)))
+	         ((endp elements))
+            (let ((ele (car elements)))
+              (typecase ele
+                (cons (rplacd (last splice) ele)
+                      (setf splice ele))
+                (null (rplacd (last splice) nil))
+                (atom (if (cdr elements)
+                        (report-bad-arg ele 'list)
+                        (rplacd (last splice) ele)))
+                (t (report-bad-arg ele 'list)))))
+          (return result)))
+       ((null top-of-top) nil)
+       (t
+        (if (cdr top)
+          (report-bad-arg top-of-top 'list)
+          (return top-of-top)))))))
+
+
+(defvar %setf-function-names% (make-hash-table :weak t :test 'eq))
+(defvar %setf-function-name-inverses% (make-hash-table :weak t :test 'eq))
+
+(defun setf-function-name (sym)
+  "Returns the symbol in the SETF package that holds the binding of (SETF sym)"
+   (or (gethash sym %setf-function-names%)
+       (progn
+         (let* ((setf-package-sym (construct-setf-function-name sym)))
+           (setf (gethash setf-package-sym %setf-function-name-inverses%) sym
+                 (gethash sym %setf-function-names%) setf-package-sym)))))
+
+(defun existing-setf-function-name (sym)
+  (gethash sym %setf-function-names%))
+
+(defun maybe-setf-name (sym)
+  (let* ((other (gethash sym %setf-function-name-inverses%)))
+    (if other
+      `(setf ,other)
+      sym)))
+
+                     
+
+(defconstant *setf-package* (or (find-package "SETF") (make-package "SETF" :use nil :external-size 1)))
+
+(defun construct-setf-function-name (sym)
+  (let ((pkg (symbol-package sym)))
+    (setq sym (symbol-name sym))
+    (if (null pkg)
+      (gentemp sym *setf-package*)
+      (values
+       (intern
+        ;;I wonder, if we didn't check, would anybody report it as a bug?
+        (if (not (%str-member #\: (setq pkg (package-name pkg))))
+          (%str-cat pkg "::" sym)
+          (%str-cat (prin1-to-string pkg) "::" (princ-to-string sym)))
+        *setf-package*)))))
+
+(defun setf-function-name-p (name)
+  (and (consp name)
+             (consp (%cdr name))
+             (null (%cddr name))
+             (symbolp (%cadr name))
+             (eq (car name) 'setf)))
+
+(defun valid-function-name-p (name)
+  (if (symbolp name)                    ; Nil is a valid function name.  I guess.
+    (values t name)
+    (if (setf-function-name-p name)
+      (values t (setf-function-name (%cadr name)))
+      ; What other kinds of function names do we care to support ?
+      (values nil nil))))
+
+;;; Why isn't this somewhere else ?
+(defun ensure-valid-function-name (name)
+  (multiple-value-bind (valid-p nm) (valid-function-name-p name)
+    (if valid-p nm (error "Invalid function name ~s." name))))
+
+
+(defun maybe-setf-function-name (name)
+  (if (setf-function-name-p name)
+    (setf-function-name (cadr name))
+    name))
+
+
+;;; Returns index if char appears in string, else nil.
+
+(defun %str-member (char string &optional start end)
+  (let* ((base-string-p (typep string 'simple-base-string)))
+    (unless base-string-p
+      (setq string (require-type string 'simple-string)))
+    (unless (characterp char)
+      (setq char (require-type char 'character)))
+    (do* ((i (or start 0) (1+ i))
+            (n (or end (uvsize string))))
+           ((= i n))
+        (declare (fixnum i n) (optimize (speed 3) (safety 0)))
+        (if (eq (schar (the simple-base-string string) i) char)
+          (return i)))))
+
+
+
+;;; Returns index of elt in vector, or nil if it's not there.
+(defun %vector-member (elt vector)
+  (unless (typep vector 'simple-vector)
+    (report-bad-arg vector 'simple-vector))
+  (dotimes (i (the fixnum (length vector)))
+    (when (eq elt (%svref vector i)) (return i))))
+
+(defun logical-pathname-p (thing) (istruct-typep thing 'logical-pathname))
+
+(progn
+;;; It's back ...
+(defun list-nreverse (list)
+  (nreconc list nil))
+
+;;; We probably want to make this smarter so that less boxing
+;;; (and bignum/double-float consing!) takes place.
+
+(defun vector-nreverse (v)
+  (let* ((len (length v))
+         (middle (ash (the fixnum len) -1)))
+    (declare (fixnum middle len))
+    (do* ((left 0 (1+ left))
+          (right (1- len) (1- right)))
+         ((= left middle) v)
+      (declare (fixnum left right))
+      (rotatef (aref v left) (aref v right)))))
+    
+(defun nreverse (seq)
+  "Return a sequence of the same elements in reverse order; the argument
+   is destroyed."
+  (when seq
+    (seq-dispatch seq
+                  (list-nreverse seq)
+                  (vector-nreverse seq)))))
+
+(defun nreconc (x y)
+  "Return (NCONC (NREVERSE X) Y)."
+  (do ((1st (cdr x) (if (endp 1st) 1st (cdr 1st)))
+       (2nd x 1st)		;2nd follows first down the list.
+       (3rd y 2nd))		;3rd follows 2nd down the list.
+      ((atom 2nd) 3rd)
+    (rplacd 2nd 3rd)))
+
+;;; The two-arg case is maybe a bit faster.  We -don't- want to
+;;; do the two-arg case repeatedly to implement the N-arg case.
+(defun append (&rest lists)
+  (declare (dynamic-extent lists))
+  "Construct a new list by concatenating the list arguments"
+  (if lists
+    (let* ((head (cons nil nil))
+           (tail head))
+      (declare (dynamic-extent head)
+               (cons head tail))
+      (do* ()
+           ((null lists) (cdr head))
+        (let* ((list (pop lists)))
+          (if (null lists)
+            (rplacd tail list)
+            (dolist (element list)
+                (setq tail (cdr (rplacd tail (cons element nil)))))))))))
+
+
+
+                     
+
+
+
+
+
+
+
+(progn
+(defun list-reverse (l)
+  (do* ((new ()))
+       ((null l) new)
+    (push (pop l) new)))
+
+; Again, it's worth putting more work into this when the dust settles.
+(defun vector-reverse (v)
+  (let* ((len (length v))
+         (new (make-array (the fixnum len) :element-type (array-element-type v))))   ; a LOT more work ...
+    (declare (fixnum len))
+    (do* ((left 0 (1+ left))
+          (right (1- len) (1- right)))
+         ((= left len) new)
+      (declare (fixnum left right))
+      (setf (uvref new left)
+            (aref v right)))))
+
+(defun reverse (seq)
+  "Return a new sequence containing the same elements but in reverse order."
+  (seq-dispatch seq (list-reverse seq) (vector-reverse seq)))
+)
+
+
+(defun check-sequence-bounds (seq start end)
+  (flet ((bad-sequence-interval (seq start end)
+           (unless (typep start 'unsigned-byte)
+             (report-bad-arg start 'unsigned-byte))
+           (if (and end (not (typep end 'unsigned-byte)))
+             (report-bad-arg end '(or null unsigned-byte)))
+           (error "Bad interval for sequence operation on ~s : start = ~s, end = ~s" seq start end)))
+  (let* ((length (length seq)))
+    (declare (fixnum length))
+    (if (and (typep start 'fixnum)
+             (<= 0 (the fixnum start))
+             (if (null end)
+               (<= (the fixnum start) (the fixnum (setq end length)))
+               (and (typep end 'fixnum)
+                    (<= (the fixnum start) (the fixnum end))
+                    (<= (the fixnum end) (the fixnum length)))))
+
+      end
+      (bad-sequence-interval seq start end)))))
+
+  
+
+(defun byte-length (string &optional  (start 0) end)
+  (setq end (check-sequence-bounds string start end))
+  (- end start))
+
+
+
+(defun make-cstring (string)
+  (let* ((len (length string)))
+    (declare (fixnum len))
+    (let* ((s (malloc (the fixnum (1+ len)))))
+      (setf (%get-byte s len) 0)
+      (multiple-value-bind (data offset) (array-data-and-offset string)
+        (dotimes (i len s)
+          (setf (%get-unsigned-byte s i) (%scharcode data (+ offset i))))
+	s))))
+
+(defun move-string-bytes (source dest off1 off2 n)
+  (declare (fixnum off1 off2 n)
+           (simple-base-string source dest)
+           (optimize (speed 3) (safety 0)))
+  (dotimes (i n dest)
+    (setf (schar dest off2) (schar source off1))
+    (incf off1)
+    (incf off2)))
+
+
+(defun %str-cat (s1 s2 &rest more)
+  (declare (dynamic-extent more))
+  (require-type s1 'simple-string)
+  (require-type s2 'simple-string)
+  (let* ((len1 (length s1))
+         (len2 (length s2))
+         (len (%i+ len2 len1)))
+    (declare (optimize (speed 3)(safety 0)))
+    (dolist (s more)
+      (require-type s 'simple-string)
+      (setq len (+ len (length s))))
+    (let ((new-string (make-string len :element-type 'base-char)))
+      (move-string-bytes s1 new-string 0 0 len1)
+      (move-string-bytes s2 new-string 0 len1 len2)
+      (dolist (s more)
+        (setq len2 (%i+ len1 len2))
+        (move-string-bytes s new-string 0 len2 (setq len1 (length s))))
+      new-string)))
+
+
+(defun %substr (str start end)
+  (require-type start 'fixnum)
+  (require-type end 'fixnum)
+  (require-type str 'string)
+  (let ((len (length str)))
+    (multiple-value-bind (str strb)(array-data-and-offset str)
+      (let ((newlen (%i- end start)))
+        (when (%i> end len)(error "End ~S exceeds length ~S." end len))
+        (when (%i< start 0)(error "Negative start"))
+        (let ((new (make-string newlen)))
+          (do* ((i 0 (1+ i))
+                (pos (%i+ start strb) (1+ pos)))
+               ((= i newlen) new)
+            (declare (fixnum i pos))
+            (setf (schar new i) (schar str pos))))))))
+
+
+
+;;; 3 callers
+(defun %list-to-uvector (subtype list)   ; subtype may be nil (meaning simple-vector
+  (let* ((n (length list))
+         (new (%alloc-misc n (or subtype target::subtag-simple-vector))))  ; yech
+    (dotimes (i n)
+      (declare (fixnum i))
+      (uvset new i (%car list))
+      (setq list (%cdr list)))
+    new))
+
+
+; appears to be unused
+(defun upgraded-array-element-type (type &optional env)
+  "Return the element type that will actually be used to implement an array
+   with the specifier :ELEMENT-TYPE Spec."
+  (declare (ignore env))
+  (element-subtype-type (element-type-subtype type)))
+
+(defun upgraded-complex-part-type (type &optional env)
+  (declare (ignore env))
+  (declare (ignore type))               ; Ok, ok.  So (upgraded-complex-part-type 'bogus) is 'REAL. So ?
+  'real)
+
+
+#+ppc32-target
+(progn
+  (defparameter array-element-subtypes
+    #(single-float 
+      (unsigned-byte 32)
+      (signed-byte 32)
+      fixnum
+      base-char                         ;ucs4
+      (unsigned-byte 8)
+      (signed-byte 8)
+      base-char
+      (unsigned-byte 16)
+      (signed-byte 16)
+      double-float
+      bit))
+  
+  ;; given uvector subtype - what is the corresponding element-type
+  (defun element-subtype-type (subtype)
+    (declare (fixnum subtype))
+    (if  (= subtype ppc32::subtag-simple-vector) t
+        (svref array-element-subtypes 
+               (ash (- subtype ppc32::min-cl-ivector-subtag) (- ppc32::ntagbits)))))
+  )
+
+#+x8632-target
+(progn
+  (defparameter array-element-subtypes
+    #(single-float 
+      (unsigned-byte 32)
+      (signed-byte 32)
+      fixnum
+      base-char                         ;ucs4
+      (unsigned-byte 8)
+      (signed-byte 8)
+      base-char
+      (unsigned-byte 16)
+      (signed-byte 16)
+      double-float
+      bit))
+  
+  ;; given uvector subtype - what is the corresponding element-type
+  (defun element-subtype-type (subtype)
+    (declare (fixnum subtype))
+    (if  (= subtype x8632::subtag-simple-vector) t
+        (svref array-element-subtypes 
+               (ash (- subtype x8632::min-cl-ivector-subtag) (- x8632::ntagbits)))))
+  )
+
+#+ppc64-target
+(progn
+
+(defparameter array-element-subtypes
+  #(bogus
+    bogus
+    bogus
+    bogus
+    (signed-byte 8)
+    (signed-byte 16)
+    (signed-byte 32)
+    (signed-byte 64)
+    (unsigned-byte 8)
+    (unsigned-byte 16)
+    (unsigned-byte 32)
+    (unsigned-byte 64)
+    bogus
+    bogus
+    single-float
+    fixnum
+    bogus
+    bogus
+    bogus
+    double-float
+    bogus
+    bogus
+    base-char
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bogus
+    bit
+    bogus
+    bogus))  
+
+  
+  ;;; given uvector subtype - what is the corresponding element-type
+  (defun element-subtype-type (subtype)
+    (declare (fixnum subtype))
+    (if  (= subtype ppc64::subtag-simple-vector)
+      t
+      (svref array-element-subtypes 
+             (ash (- subtype 128) -2))))
+  )
+
+#+x8664-target
+(progn
+
+  ;;; 1, 8, 16-bit element types
+  (defparameter *immheader-0-array-element-types*
+    #(bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      (signed-byte 16)
+      (unsigned-byte 16)
+      base-char
+      (signed-byte 8)
+      (unsigned-byte 8)
+      bit))
+
+  ;;; 32-bit element types
+  (defparameter *immheader-1-array-element-types*
+    #(bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      base-char
+      (signed-byte 32)
+      (unsigned-byte 32)
+      single-float))
+
+  ;;; 64-bit element types
+  (defparameter *immheader-2-array-element-types*
+    #(bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      bogus
+      fixnum
+      (signed-byte 64)
+      (unsigned-byte 64)
+      double-float))  
+      
+  
+  (defun element-subtype-type (subtype)
+    (declare (type (unsigned-byte 8) subtype))
+    (if (= subtype x8664::subtag-simple-vector)
+      t
+      (let* ((class (ash subtype (- x8664::ntagbits)))
+             (tag (logand subtype x8664::fulltagmask)))
+        (declare (type (unsigned-byte 4) class tag))
+        (cond ((= tag x8664::fulltag-immheader-0)
+               (%svref *immheader-0-array-element-types* class))
+              ((= tag x8664::fulltag-immheader-1)
+               (%svref *immheader-1-array-element-types* class))
+              ((= tag x8664::fulltag-immheader-2)
+               (%svref *immheader-2-array-element-types* class))
+              (t 'bogus)))))
+  )
+
+
+;;; %make-displaced-array assumes the following
+
+(eval-when (:compile-toplevel)
+  (assert (eql target::arrayH.flags-cell target::vectorH.flags-cell))
+  (assert (eql target::arrayH.displacement-cell target::vectorH.displacement-cell))
+  (assert (eql target::arrayH.data-vector-cell target::vectorH.data-vector-cell)))
+
+
+(defun %make-displaced-array (dimensions displaced-to
+                                         &optional fill adjustable
+					 offset explicitp)
+  (if offset 
+    (unless (and (fixnump offset) (>= (the fixnum offset) 0))
+      (setq offset (require-type offset '(and fixnum (integer 0 *)))))
+    (setq offset 0))
+  (locally (declare (fixnum offset))
+    (let* ((disp-size (array-total-size displaced-to))
+           (rank (if (listp dimensions)(length dimensions) 1))
+           (new-size (if (fixnump dimensions)
+                       dimensions
+                       (if (listp dimensions)
+                         (if (eql rank 1)
+                           (car dimensions)
+                           (if (eql rank 0) 1 ; why not 0?
+                           (apply #'* dimensions))))))
+           (vect-subtype (typecode displaced-to))
+           (target displaced-to)
+           (real-offset offset)
+           (flags 0))
+      (declare (fixnum disp-size rank flags vect-subtype real-offset))
+      (when explicitp
+	(setq flags (bitset $arh_exp_disp_bit flags)))
+      (if (not (fixnump new-size))(error "Bad array dimensions ~s." dimensions)) 
+      (locally (declare (fixnum new-size))
+        ; (when (> (+ offset new-size) disp-size) ...), but don't cons bignums
+        (when (or (> new-size disp-size)
+                  (let ((max-offset (- disp-size new-size)))
+                    (declare (fixnum max-offset))
+                    (> offset max-offset)))
+          (%err-disp $err-disp-size displaced-to))
+        (if adjustable  (setq flags (bitset $arh_adjp_bit flags)))
+        (when fill
+          (if (eq fill t)
+            (setq fill new-size)
+            (unless (and (eql rank 1)
+                         (fixnump fill)
+                         (locally (declare (fixnum fill))
+                           (and (>= fill 0) (<= fill new-size))))
+              (error "Bad fill pointer ~s" fill)))
+          (setq flags (bitset $arh_fill_bit flags))))
+      ; If displaced-to is an array or vector header and is either
+      ; adjustable or its target is a header, then we need to set the
+      ; $arh_disp_bit. If displaced-to is not adjustable, then our
+      ; target can be its target instead of itself.
+      (when (or (eql vect-subtype target::subtag-arrayH)
+                (eql vect-subtype target::subtag-vectorH))
+        (let ((dflags (%svref displaced-to target::arrayH.flags-cell)))
+          (declare (fixnum dflags))
+          (when (or (logbitp $arh_adjp_bit dflags)
+		    t
+                    (progn
+		      #+nope
+                      (setq target (%svref displaced-to target::arrayH.data-vector-cell)
+                            real-offset (+ offset (%svref displaced-to target::arrayH.displacement-cell)))
+                      (logbitp $arh_disp_bit dflags)
+		      #-nope t))
+            (setq flags (bitset $arh_disp_bit flags))))
+        (setq vect-subtype (%array-header-subtype displaced-to)))
+      ; assumes flags is low byte
+      (setq flags (dpb vect-subtype target::arrayH.flags-cell-subtag-byte flags))
+      (if (eq rank 1)
+        (%gvector target::subtag-vectorH 
+                      (if (fixnump fill) fill new-size)
+                      new-size
+                      target
+                      real-offset
+                      flags)
+        (let ((val (%alloc-misc (+ target::arrayh.dim0-cell rank) target::subtag-arrayH)))
+          (setf (%svref val target::arrayH.rank-cell) rank)
+          (setf (%svref val target::arrayH.physsize-cell) new-size)
+          (setf (%svref val target::arrayH.data-vector-cell) target)
+          (setf (%svref val target::arrayH.displacement-cell) real-offset)
+          (setf (%svref val target::arrayH.flags-cell) flags)
+          (do* ((dims dimensions (cdr dims))
+                (i 0 (1+ i)))              
+               ((null dims))
+            (declare (fixnum i)(list dims))
+            (setf (%svref val (%i+ target::arrayH.dim0-cell i)) (car dims)))
+          val)))))
+
+(defun make-array (dims &key (element-type t element-type-p)
+                        displaced-to
+                        displaced-index-offset
+                        adjustable
+                        fill-pointer
+                        (initial-element nil initial-element-p)
+                        (initial-contents nil initial-contents-p))
+  (when (and initial-element-p initial-contents-p)
+        (error "Cannot specify both ~S and ~S" :initial-element-p :initial-contents-p))
+  (make-array-1 dims element-type element-type-p
+                displaced-to
+                displaced-index-offset
+                adjustable
+                fill-pointer
+                initial-element initial-element-p
+                initial-contents initial-contents-p
+                nil))
+
+
+
+
+
+(defun vector-pop (vector)
+  "Decrease the fill pointer by 1 and return the element pointed to by the
+  new fill pointer."
+  (let* ((fill (fill-pointer vector)))
+    (declare (fixnum fill))
+    (if (zerop fill)
+      (error "Fill pointer of ~S is 0 ." vector)
+      (progn
+        (decf fill)
+        (%set-fill-pointer vector fill)
+        (aref vector fill)))))
+
+
+
+
+(defun elt (sequence idx)
+  "Return the element of SEQUENCE specified by INDEX."
+  (seq-dispatch
+   sequence
+   (let* ((cell (nthcdr idx sequence)))
+     (if (consp cell)
+       (car (the cons cell))
+       (if cell
+         (report-bad-arg sequence '(satisfies proper-list-p))
+         (%err-disp $XACCESSNTH idx sequence))))
+       
+   (progn
+     (unless (and (typep idx 'fixnum) (>= (the fixnum idx) 0))
+       (report-bad-arg idx 'unsigned-byte))
+     (locally 
+       (if (>= idx (length sequence))
+         (%err-disp $XACCESSNTH idx sequence)
+         (aref sequence idx))))))
+
+
+
+
+(defun set-elt (sequence idx value)
+  (seq-dispatch
+   sequence
+   (let* ((cell (nthcdr idx sequence)))
+     (if (consp cell)
+       (setf (car (the cons cell)) value)
+       (if cell
+         (report-bad-arg sequence '(satisfies proper-list-p))
+         (%err-disp $XACCESSNTH idx sequence))))
+   (progn
+     (unless (and (typep idx 'fixnum) (>= (the fixnum idx) 0))
+       (report-bad-arg idx 'unsigned-byte))
+     (locally 
+       (declare (fixnum idx))
+       (if (>= idx (length sequence))
+         (%err-disp $XACCESSNTH idx sequence)
+         (setf (aref sequence idx) value))))))
+
+
+
+
+(%fhave 'equalp #'equal)                ; bootstrapping
+
+(defun copy-tree (tree)
+  "Recursively copy trees of conses."
+  (if (atom tree)
+    tree
+    (locally (declare (type cons tree))
+      (do* ((tail (cdr tree) (cdr tail))
+            (result (cons (copy-tree (car tree)) nil))
+            (ptr result (cdr ptr)))
+           ((atom tail)
+            (setf (cdr ptr) tail)
+            result)
+        (declare (type cons ptr result))
+        (locally 
+          (declare (type cons tail))
+          (setf (cdr ptr) (cons (copy-tree (car tail)) nil)))))))
+
+
+
+
+(defvar *periodic-task-interval* 0.3)
+(defvar *periodic-task-seconds* 0)
+(defvar *periodic-task-nanoseconds* 300000000)
+
+(defun set-periodic-task-interval (n)
+  (multiple-value-setq (*periodic-task-seconds* *periodic-task-nanoseconds*)
+    (nanoseconds n))
+  (setq *periodic-task-interval* n))
+
+(defun periodic-task-interval ()
+  *periodic-task-interval*)
+
+
+
+(defun char-downcase (c)
+  "Return CHAR converted to lower-case if that is possible."
+  (declare (optimize (speed 3))) ; open-code the %CHAR-CODE-DOWNCASE here.
+  (code-char (the valid-char-code (%char-code-downcase (char-code c)))))
+
+
+
+(defun digit-char-p (char &optional radix)
+  "If char is a digit in the specified radix, returns the fixnum for
+  which that digit stands, else returns NIL."
+  (let* ((code (char-code char))
+         (r (if radix (if (and (typep radix 'fixnum)
+                               (%i>= radix 2)
+                               (%i<= radix 36))
+                        radix
+                        (%validate-radix radix)) 10))
+         (weight (if (and (<= code (char-code #\9))
+                          (>= code (char-code #\0)))
+                   (the fixnum (- code (char-code #\0)))
+                   (if (and (<= code (char-code #\Z))
+                            (>= code (char-code #\A)))
+                     (the fixnum (+ 10 (the fixnum (- code (char-code #\A)))))
+                   (if (and (<= code (char-code #\z))
+                            (>= code (char-code #\a)))
+                     (the fixnum (+ 10 (the fixnum (- code (char-code #\a))))))))))
+    (declare (fixnum code r))
+    (and weight (< (the fixnum weight) r) weight)))
+
+
+
+
+
+
+
+(defun string-start-end (string start end)
+  (setq string (string string))
+  (let ((len (length (the string string))))
+    (flet ((are (a i)(error "Array index ~S out of bounds for ~S." i a)))    
+      (if (and end (> end len))(are string end))
+      (if (and start (or (< start 0)(> start len)))(are string start))
+      (setq start (or start 0) end (or end len))
+      (if (%i> start end)
+        (error "Start ~S exceeds end ~S." start end))
+      (if (typep string 'simple-string)
+        (values string start end)
+        (multiple-value-bind (str off)(array-data-and-offset string)
+          (values str (%i+ off start)(%i+ off end)))))))
+
+(defun get-properties (place indicator-list)
+  "Like GETF, except that INDICATOR-LIST is a list of indicators which will
+  be looked for in the property list stored in PLACE. Three values are
+  returned, see manual for details."
+  (do ((plist place (cddr plist)))
+      ((null plist) (values nil nil nil))
+    (cond ((atom (cdr plist))
+	   (report-bad-arg place '(satisfies proper-list-p)))
+	  ((memq (car plist) indicator-list) ;memq defined in kernel
+	   (return (values (car plist) (cadr plist) plist))))))
+
+(defun string= (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings (string1 and string2), and optional integers start1,
+  start2, end1 and end2, compares characters in string1 to characters in
+  string2 (using char=)."
+    (locally (declare (optimize (speed 3)(safety 0)))
+      (if (and (simple-string-p string1)(null start1)(null end1))
+        (setq start1 0 end1 (length string1))
+        (multiple-value-setq (string1 start1 end1)(string-start-end string1 start1 end1)))
+      (if (and (simple-string-p string2)(null start2)(null end2))
+        (setq start2 0 end2 (length string2))
+        (multiple-value-setq (string2 start2 end2)(string-start-end string2 start2 end2)))    
+      (%simple-string= string1 string2 start1 start2 end1 end2)))
+
+
+(defun lfun-keyvect (lfun)
+  (let ((bits (lfun-bits lfun)))
+    (declare (fixnum bits))
+    (and (logbitp $lfbits-keys-bit bits)
+         (or (logbitp $lfbits-method-bit bits)
+             (and (not (logbitp $lfbits-gfn-bit bits))
+                  (not (logbitp $lfbits-cm-bit bits))))
+	 (nth-immediate lfun 1))))
+
+
+(defun function-entry-code-note (fn)
+  (let ((bits (lfun-bits (setq fn (require-type fn 'function)))))
+    (declare (fixnum bits))
+    (and (logbitp $lfbits-code-coverage-bit bits)
+	 (loop for i upfrom 1 as imm = (nth-immediate fn i)
+	       when (code-note-p imm) do (return imm)))))
+
+
+(defun function-lambda-expression (fn)
+  "Return (VALUES DEFINING-LAMBDA-EXPRESSION CLOSURE-P NAME), where
+  DEFINING-LAMBDA-EXPRESSION is NIL if unknown, or a suitable argument
+  to COMPILE otherwise, CLOSURE-P is non-NIL if the function's definition
+  might have been enclosed in some non-null lexical environment, and
+  NAME is some name (for debugging only) or NIL if there is no name."
+  ;(declare (values def env-p name))
+  (let* ((bits (lfun-bits (setq fn (require-type fn 'function)))))
+    (declare (fixnum bits))
+    (if (logbitp $lfbits-trampoline-bit bits)
+      (function-lambda-expression (nth-immediate fn 1))
+      (values (uncompile-function fn)
+              (logbitp $lfbits-nonnullenv-bit bits)
+              (function-name fn)))))
+
+; env must be a lexical-environment or NIL.
+; If env contains function or variable bindings or SPECIAL declarations, return t.
+; Else return nil
+(defun %non-empty-environment-p (env)
+  (loop
+    (when (or (null env) (istruct-typep env 'definition-environment))
+      (return nil))
+    (when (or (consp (lexenv.variables env))
+              (consp (lexenv.functions env))
+              (dolist (vdecl (lexenv.vdecls env))
+                (when (eq (cadr vdecl) 'special)
+                  (return t))))
+      (return t))
+    (setq env (lexenv.parent-env env))))
+
+;(coerce object 'compiled-function)
+(defun coerce-to-compiled-function (object)
+  (setq object (coerce-to-function object))
+  (unless (typep object 'compiled-function)
+    (multiple-value-bind (def envp) (function-lambda-expression object)
+      (when (or envp (null def))
+        (%err-disp $xcoerce object 'compiled-function))
+      (setq object (compile-user-function def nil))))
+  object)
+
+
+
+(defun %set-toplevel (&optional (fun nil fun-p))
+  ;(setq fun (require-type fun '(or symbol function)))
+  (let* ((tcr (%current-tcr)))
+    (prog1 (%tcr-toplevel-function tcr)
+      (when fun-p
+	(%set-tcr-toplevel-function tcr fun)))))
+
+
+(defun gccounts ()
+  (let* ((total (%get-gc-count))
+         (full (full-gccount))
+         (g2-count 0)
+         (g1-count 0)
+         (g0-count 0))
+    (when (egc-enabled-p)
+      (let* ((a (%active-dynamic-area)))
+        (setq g0-count (%fixnum-ref a target::area.gc-count) a (%fixnum-ref a target::area.older))
+        (setq g1-count (%fixnum-ref a target::area.gc-count) a (%fixnum-ref a target::area.older))
+        (setq g2-count (%fixnum-ref a target::area.gc-count))))
+    (values total full g2-count g1-count g0-count)))
+
+      
+
+
+
+(defstatic %pascal-functions%
+    #(NIL NIL NIL NIL NIL NIL NIL NIL
+      NIL NIL NIL NIL NIL NIL NIL NIL
+      NIL NIL NIL NIL NIL NIL NIL NIL
+      NIL NIL NIL NIL NIL NIL NIL NIL))
+
+
+(defun gc-retain-pages (arg)
+  "Try to influence the GC to retain/recycle the pages allocated between
+GCs if arg is true, and to release them otherwise. This is generally a
+gtradeoff between paging and other VM considerations."
+  (setq *gc-event-status-bits*
+        (if arg
+          (bitset $gc-retain-pages-bit *gc-event-status-bits*)
+          (bitclr $gc-retain-pages-bit *gc-event-status-bits*)))
+  (not (null arg)))
+
+(defun gc-retaining-pages ()
+  "Return T if the GC tries to retain pages between full GCs and NIL if
+it's trying to release them to improve VM paging performance."
+  (logbitp $gc-retain-pages-bit *gc-event-status-bits*))  
+
+
+(defun gc-verbose (on-full-gc &optional (egc-too on-full-gc))
+  "If the first (required) argument is non-NIL, configures the GC to print
+informational messages on entry and exit to each full GC; if the first argument
+is NIL, suppresses those messages.  The second (optional) argument controls printing of messages on entry and exit to an ephemeral GC.  Returns values as per GC-VERBOSE-P."
+  (let* ((bits *gc-event-status-bits*))
+    (if on-full-gc
+      (bitsetf $gc-verbose-bit bits)
+      (bitclrf $gc-verbose-bit bits))
+    (if egc-too
+      (bitsetf $egc-verbose-bit bits)
+      (bitclrf $egc-verbose-bit bits))
+    (setq *gc-event-status-bits* bits)
+    (values on-full-gc egc-too)))
+
+
+(defun gc-verbose-p ()
+  "Returns two values: the first is true if the GC is configured to
+print messages on each full GC; the second is true if the GC is configured
+to print messages on each ephemeral GC."
+  (let* ((bits *gc-event-status-bits*))
+    (values (logbitp $gc-verbose-bit bits)
+            (logbitp $egc-verbose-bit bits))))
+
+(defun egc-active-p ()
+  "Return T if the EGC was active at the time of the call, NIL otherwise.
+Since this is generally a volatile piece of information, it's not clear
+whether this function serves a useful purpose when native threads are
+involved."
+  (and (egc-enabled-p)
+       (not (eql 0 (%get-kernel-global 'oldest-ephemeral)))))
+
+; this IS effectively a passive way of inquiring about enabled status.
+(defun egc-enabled-p ()
+  "Return T if the EGC was enabled at the time of the call, NIL otherwise."
+  (not (eql 0 (%fixnum-ref (%active-dynamic-area) target::area.older))))
+
+(defun egc-configuration ()
+  "Return as multiple values the sizes in kilobytes of the thresholds
+associated with the youngest ephemeral generation, the middle ephemeral
+generation, and the oldest ephemeral generation."
+  (let* ((ta (%get-kernel-global 'tenured-area))
+         (g2 (%fixnum-ref ta target::area.younger))
+         (g1 (%fixnum-ref g2 target::area.younger))
+         (g0 (%fixnum-ref g1 target::area.younger)))
+    (values (ash (the fixnum (%fixnum-ref g0 target::area.threshold)) (- (- 10 target::fixnum-shift)))
+            (ash (the fixnum (%fixnum-ref g1 target::area.threshold)) (- (- 10 target::fixnum-shift)))
+            (ash (the fixnum (%fixnum-ref g2 target::area.threshold)) (- (- 10 target::fixnum-shift))))))
+
+
+(defun configure-egc (e0size e1size e2size)
+  "If the EGC is currently disabled, put the indicated threshold sizes in
+effect and returns T, otherwise, returns NIL.  The provided threshold sizes
+are rounded up to a multiple of 64Kbytes."
+  (let* ((was-enabled (egc-active-p))
+         (e2size (require-type e2size '(unsigned-byte 18)))
+         (e1size (require-type e1size '(unsigned-byte 18)))
+         (e0size (require-type e0size '(integer 1 #.(ash 1 18)))))
+    (unless (<= e0size e1size e2size)
+      (error "Generation ~s threshold cannot be smaller than generation ~s threshold"
+             (if (> e0size e1size) 1 2) (if (> e0size e1size) 0 1)))
+    (unwind-protect
+         (progn
+           (egc nil)
+           (setq e2size (logand (lognot #xffff) (+ #xffff (ash e2size 10)))
+                 e1size (logand (lognot #xffff) (+ #xffff (ash e1size 10)))
+                 e0size (logand (lognot #xffff) (+ #xffff (ash e0size 10))))
+           (%configure-egc e0size e1size e2size))
+      (egc was-enabled))))
+
+
+
+(defun macptr-flags (macptr)
+  (if (eql (uvsize (setq macptr (require-type macptr 'macptr))) 1)
+    0
+    (uvref macptr TARGET::XMACPTR.FLAGS-CELL)))
+
+
+; This doesn't really make the macptr be gcable (now has to be
+; on linked list), but we might have other reasons for setting
+; other flag bits.
+(defun set-macptr-flags (macptr value) 
+  (unless (eql (uvsize (setq macptr (require-type macptr 'macptr))) 1)
+    (setf (%svref macptr TARGET::XMACPTR.FLAGS-CELL) value)
+    value))
+
+(defun %new-gcable-ptr (size &optional clear-p)
+  (let ((p (make-gcable-macptr $flags_DisposPtr)))
+    (%setf-macptr p (malloc size))
+    (if clear-p
+      (#_memset p 0 size))
+    p))
+
+(defun %gcable-ptr-p (p)
+  (and (typep p 'macptr)
+       (= (uvsize p) target::xmacptr.element-count)))
+
+(defstatic *upper-to-lower* nil)
+(defstatic *lower-to-upper*  nil)
+
+;;; "address" should be the address (as returned by FOREIGN-SYMBOL-ADDRESS)
+;;; of a foreign function that accepts a pointer as an argument and does
+;;; whatever's needed to dispose of it.  That function can be called from
+;;; the GC, so it shouldn't call back into lisp.
+(defun register-xmacptr-dispose-function (address)
+  (ff-call (%kernel-import target::kernel-import-register-xmacptr-dispose-function)
+           :address address
+           :int))
+
+
+;;; This alist is automatically (and not too cleverly ...) generated.
+;;;
+;;; NB: it was generated from Unicode 5.0 character tables, check to
+;;; see if anything's changed in 5.1 or later versions.
+;;;
+;;; The (upper . lower) pairs have the property that UPPER is the
+;;; value "simple uppercase equivalent" entry for LOWER in the
+;;; UnicodeData.txt file and LOWER is the corresponding entry for
+;;; UPPER,
+(let* ((mapping
+        '((#\Latin_Capital_Letter_A_With_Grave . #\Latin_Small_Letter_A_With_Grave)
+          (#\Latin_Capital_Letter_A_With_Acute . #\Latin_Small_Letter_A_With_Acute)
+          (#\Latin_Capital_Letter_A_With_Circumflex
+           . #\Latin_Small_Letter_A_With_Circumflex)
+          (#\Latin_Capital_Letter_A_With_Tilde . #\Latin_Small_Letter_A_With_Tilde)
+          (#\Latin_Capital_Letter_A_With_Diaeresis
+           . #\Latin_Small_Letter_A_With_Diaeresis)
+          (#\Latin_Capital_Letter_A_With_Ring_Above
+           . #\Latin_Small_Letter_A_With_Ring_Above)
+          
+          (#\Latin_Capital_Letter_Ae . #\Latin_Small_Letter_Ae)
+          
+          (#\Latin_Capital_Letter_C_With_Cedilla . #\Latin_Small_Letter_C_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_E_With_Grave . #\Latin_Small_Letter_E_With_Grave)
+          
+          (#\Latin_Capital_Letter_E_With_Acute . #\Latin_Small_Letter_E_With_Acute)
+          
+          (#\Latin_Capital_Letter_E_With_Circumflex
+           . #\Latin_Small_Letter_E_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_E_With_Diaeresis
+           . #\Latin_Small_Letter_E_With_Diaeresis)
+          
+          (#\Latin_Capital_Letter_I_With_Grave . #\Latin_Small_Letter_I_With_Grave)
+          
+          (#\Latin_Capital_Letter_I_With_Acute . #\Latin_Small_Letter_I_With_Acute)
+          
+          (#\Latin_Capital_Letter_I_With_Circumflex
+           . #\Latin_Small_Letter_I_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_I_With_Diaeresis
+           . #\Latin_Small_Letter_I_With_Diaeresis)
+          
+          (#\Latin_Capital_Letter_Eth . #\Latin_Small_Letter_Eth)
+          
+          (#\Latin_Capital_Letter_N_With_Tilde . #\Latin_Small_Letter_N_With_Tilde)
+          
+          (#\Latin_Capital_Letter_O_With_Grave . #\Latin_Small_Letter_O_With_Grave)
+          
+          (#\Latin_Capital_Letter_O_With_Acute . #\Latin_Small_Letter_O_With_Acute)
+          
+          (#\Latin_Capital_Letter_O_With_Circumflex
+           . #\Latin_Small_Letter_O_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_O_With_Tilde . #\Latin_Small_Letter_O_With_Tilde)
+          
+          (#\Latin_Capital_Letter_O_With_Diaeresis
+           . #\Latin_Small_Letter_O_With_Diaeresis)
+          
+          (#\Latin_Capital_Letter_O_With_Stroke . #\Latin_Small_Letter_O_With_Stroke)
+          
+          (#\Latin_Capital_Letter_U_With_Grave . #\Latin_Small_Letter_U_With_Grave)
+          
+          (#\Latin_Capital_Letter_U_With_Acute . #\Latin_Small_Letter_U_With_Acute)
+          
+          (#\Latin_Capital_Letter_U_With_Circumflex
+           . #\Latin_Small_Letter_U_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_U_With_Diaeresis
+           . #\Latin_Small_Letter_U_With_Diaeresis)
+          
+          (#\Latin_Capital_Letter_Y_With_Acute . #\Latin_Small_Letter_Y_With_Acute)
+          
+          (#\Latin_Capital_Letter_Thorn . #\Latin_Small_Letter_Thorn)
+          
+          (#\Latin_Capital_Letter_A_With_Macron . #\Latin_Small_Letter_A_With_Macron)
+          
+          (#\Latin_Capital_Letter_A_With_Breve . #\Latin_Small_Letter_A_With_Breve)
+          
+          (#\Latin_Capital_Letter_A_With_Ogonek . #\Latin_Small_Letter_A_With_Ogonek)
+          
+          (#\Latin_Capital_Letter_C_With_Acute . #\Latin_Small_Letter_C_With_Acute)
+          
+          (#\Latin_Capital_Letter_C_With_Circumflex
+           . #\Latin_Small_Letter_C_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_C_With_Dot_Above
+           . #\Latin_Small_Letter_C_With_Dot_Above)
+          
+          (#\Latin_Capital_Letter_C_With_Caron . #\Latin_Small_Letter_C_With_Caron)
+          
+          (#\Latin_Capital_Letter_D_With_Caron . #\Latin_Small_Letter_D_With_Caron)
+          
+          (#\Latin_Capital_Letter_D_With_Stroke . #\Latin_Small_Letter_D_With_Stroke)
+          
+          (#\Latin_Capital_Letter_E_With_Macron . #\Latin_Small_Letter_E_With_Macron)
+          
+          (#\Latin_Capital_Letter_E_With_Breve . #\Latin_Small_Letter_E_With_Breve)
+          
+          (#\Latin_Capital_Letter_E_With_Dot_Above
+           . #\Latin_Small_Letter_E_With_Dot_Above)
+          
+          (#\Latin_Capital_Letter_E_With_Ogonek . #\Latin_Small_Letter_E_With_Ogonek)
+          
+          (#\Latin_Capital_Letter_E_With_Caron . #\Latin_Small_Letter_E_With_Caron)
+          
+          (#\Latin_Capital_Letter_G_With_Circumflex
+           . #\Latin_Small_Letter_G_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_G_With_Breve . #\Latin_Small_Letter_G_With_Breve)
+          
+          (#\Latin_Capital_Letter_G_With_Dot_Above
+           . #\Latin_Small_Letter_G_With_Dot_Above)
+          
+          (#\Latin_Capital_Letter_G_With_Cedilla . #\Latin_Small_Letter_G_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_H_With_Circumflex
+           . #\Latin_Small_Letter_H_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_H_With_Stroke . #\Latin_Small_Letter_H_With_Stroke)
+          
+          (#\Latin_Capital_Letter_I_With_Tilde . #\Latin_Small_Letter_I_With_Tilde)
+          
+          (#\Latin_Capital_Letter_I_With_Macron . #\Latin_Small_Letter_I_With_Macron)
+          
+          (#\Latin_Capital_Letter_I_With_Breve . #\Latin_Small_Letter_I_With_Breve)
+          
+          (#\Latin_Capital_Letter_I_With_Ogonek . #\Latin_Small_Letter_I_With_Ogonek)
+          
+          (#\Latin_Capital_Ligature_Ij . #\Latin_Small_Ligature_Ij)
+          
+          (#\Latin_Capital_Letter_J_With_Circumflex
+           . #\Latin_Small_Letter_J_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_K_With_Cedilla . #\Latin_Small_Letter_K_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_L_With_Acute . #\Latin_Small_Letter_L_With_Acute)
+          
+          (#\Latin_Capital_Letter_L_With_Cedilla . #\Latin_Small_Letter_L_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_L_With_Caron . #\Latin_Small_Letter_L_With_Caron)
+          
+          (#\Latin_Capital_Letter_L_With_Middle_Dot
+           . #\Latin_Small_Letter_L_With_Middle_Dot)
+          
+          (#\Latin_Capital_Letter_L_With_Stroke . #\Latin_Small_Letter_L_With_Stroke)
+          
+          (#\Latin_Capital_Letter_N_With_Acute . #\Latin_Small_Letter_N_With_Acute)
+          
+          (#\Latin_Capital_Letter_N_With_Cedilla . #\Latin_Small_Letter_N_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_N_With_Caron . #\Latin_Small_Letter_N_With_Caron)
+          
+          (#\Latin_Capital_Letter_Eng . #\Latin_Small_Letter_Eng)
+          
+          (#\Latin_Capital_Letter_O_With_Macron . #\Latin_Small_Letter_O_With_Macron)
+          
+          (#\Latin_Capital_Letter_O_With_Breve . #\Latin_Small_Letter_O_With_Breve)
+          
+          (#\Latin_Capital_Letter_O_With_Double_Acute
+           . #\Latin_Small_Letter_O_With_Double_Acute)
+          
+          (#\Latin_Capital_Ligature_Oe . #\Latin_Small_Ligature_Oe)
+          
+          (#\Latin_Capital_Letter_R_With_Acute . #\Latin_Small_Letter_R_With_Acute)
+          
+          (#\Latin_Capital_Letter_R_With_Cedilla . #\Latin_Small_Letter_R_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_R_With_Caron . #\Latin_Small_Letter_R_With_Caron)
+          
+          (#\Latin_Capital_Letter_S_With_Acute . #\Latin_Small_Letter_S_With_Acute)
+          
+          (#\Latin_Capital_Letter_S_With_Circumflex
+           . #\Latin_Small_Letter_S_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_S_With_Cedilla . #\Latin_Small_Letter_S_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_S_With_Caron . #\Latin_Small_Letter_S_With_Caron)
+          
+          (#\Latin_Capital_Letter_T_With_Cedilla . #\Latin_Small_Letter_T_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_T_With_Caron . #\Latin_Small_Letter_T_With_Caron)
+          
+          (#\Latin_Capital_Letter_T_With_Stroke . #\Latin_Small_Letter_T_With_Stroke)
+          
+          (#\Latin_Capital_Letter_U_With_Tilde . #\Latin_Small_Letter_U_With_Tilde)
+          
+          (#\Latin_Capital_Letter_U_With_Macron . #\Latin_Small_Letter_U_With_Macron)
+          
+          (#\Latin_Capital_Letter_U_With_Breve . #\Latin_Small_Letter_U_With_Breve)
+          
+          (#\Latin_Capital_Letter_U_With_Ring_Above
+           . #\Latin_Small_Letter_U_With_Ring_Above)
+          
+          (#\Latin_Capital_Letter_U_With_Double_Acute
+           . #\Latin_Small_Letter_U_With_Double_Acute)
+          
+          (#\Latin_Capital_Letter_U_With_Ogonek . #\Latin_Small_Letter_U_With_Ogonek)
+          
+          (#\Latin_Capital_Letter_W_With_Circumflex
+           . #\Latin_Small_Letter_W_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_Y_With_Circumflex
+           . #\Latin_Small_Letter_Y_With_Circumflex)
+          
+          (#\Latin_Capital_Letter_Y_With_Diaeresis
+           . #\Latin_Small_Letter_Y_With_Diaeresis)
+          
+          (#\Latin_Capital_Letter_Z_With_Acute . #\Latin_Small_Letter_Z_With_Acute)
+          
+          (#\Latin_Capital_Letter_Z_With_Dot_Above
+           . #\Latin_Small_Letter_Z_With_Dot_Above)
+          
+          (#\Latin_Capital_Letter_Z_With_Caron . #\Latin_Small_Letter_Z_With_Caron)
+          
+          (#\Latin_Capital_Letter_B_With_Hook . #\Latin_Small_Letter_B_With_Hook)
+          
+          (#\Latin_Capital_Letter_B_With_Topbar . #\Latin_Small_Letter_B_With_Topbar)
+          
+          (#\Latin_Capital_Letter_Tone_Six . #\Latin_Small_Letter_Tone_Six)
+          
+          (#\Latin_Capital_Letter_Open_O . #\Latin_Small_Letter_Open_O)
+          
+          (#\Latin_Capital_Letter_C_With_Hook . #\Latin_Small_Letter_C_With_Hook)
+          
+          (#\Latin_Capital_Letter_African_D . #\Latin_Small_Letter_D_With_Tail)
+          
+          (#\Latin_Capital_Letter_D_With_Hook . #\Latin_Small_Letter_D_With_Hook)
+          
+          (#\Latin_Capital_Letter_D_With_Topbar . #\Latin_Small_Letter_D_With_Topbar)
+          
+          (#\Latin_Capital_Letter_Reversed_E . #\Latin_Small_Letter_Turned_E)
+          
+          (#\Latin_Capital_Letter_Schwa . #\Latin_Small_Letter_Schwa)
+          
+          (#\Latin_Capital_Letter_Open_E . #\Latin_Small_Letter_Open_E)
+          
+          (#\Latin_Capital_Letter_F_With_Hook . #\Latin_Small_Letter_F_With_Hook)
+          
+          (#\Latin_Capital_Letter_G_With_Hook . #\Latin_Small_Letter_G_With_Hook)
+          
+          (#\Latin_Capital_Letter_Gamma . #\Latin_Small_Letter_Gamma)
+          
+          (#\Latin_Capital_Letter_Iota . #\Latin_Small_Letter_Iota)
+          
+          (#\Latin_Capital_Letter_I_With_Stroke . #\Latin_Small_Letter_I_With_Stroke)
+          
+          (#\Latin_Capital_Letter_K_With_Hook . #\Latin_Small_Letter_K_With_Hook)
+          
+          (#\Latin_Capital_Letter_Turned_M . #\Latin_Small_Letter_Turned_M)
+          
+          (#\Latin_Capital_Letter_N_With_Left_Hook
+           . #\Latin_Small_Letter_N_With_Left_Hook)
+          
+          (#\Latin_Capital_Letter_O_With_Middle_Tilde . #\Latin_Small_Letter_Barred_O)
+          
+          (#\Latin_Capital_Letter_O_With_Horn . #\Latin_Small_Letter_O_With_Horn)
+          
+          (#\Latin_Capital_Letter_Oi . #\Latin_Small_Letter_Oi)
+          
+          (#\Latin_Capital_Letter_P_With_Hook . #\Latin_Small_Letter_P_With_Hook)
+          
+          (#\Latin_Letter_Yr . #\Latin_Letter_Small_Capital_R)
+          
+          (#\Latin_Capital_Letter_Tone_Two . #\Latin_Small_Letter_Tone_Two)
+          
+          (#\Latin_Capital_Letter_Esh . #\Latin_Small_Letter_Esh)
+          
+          (#\Latin_Capital_Letter_T_With_Hook . #\Latin_Small_Letter_T_With_Hook)
+          
+          (#\Latin_Capital_Letter_T_With_Retroflex_Hook
+           . #\Latin_Small_Letter_T_With_Retroflex_Hook)
+          
+          (#\Latin_Capital_Letter_U_With_Horn . #\Latin_Small_Letter_U_With_Horn)
+          
+          (#\Latin_Capital_Letter_Upsilon . #\Latin_Small_Letter_Upsilon)
+          
+          (#\Latin_Capital_Letter_V_With_Hook . #\Latin_Small_Letter_V_With_Hook)
+          
+          (#\Latin_Capital_Letter_Y_With_Hook . #\Latin_Small_Letter_Y_With_Hook)
+          
+          (#\Latin_Capital_Letter_Z_With_Stroke . #\Latin_Small_Letter_Z_With_Stroke)
+          
+          (#\Latin_Capital_Letter_Ezh . #\Latin_Small_Letter_Ezh)
+          
+          (#\Latin_Capital_Letter_Ezh_Reversed . #\Latin_Small_Letter_Ezh_Reversed)
+          
+          (#\Latin_Capital_Letter_Tone_Five . #\Latin_Small_Letter_Tone_Five)
+          
+          (#\Latin_Capital_Letter_Dz_With_Caron . #\Latin_Small_Letter_Dz_With_Caron)
+          
+          (#\Latin_Capital_Letter_Lj . #\Latin_Small_Letter_Lj)
+          
+          (#\Latin_Capital_Letter_Nj . #\Latin_Small_Letter_Nj)
+          
+          (#\Latin_Capital_Letter_A_With_Caron . #\Latin_Small_Letter_A_With_Caron)
+          
+          (#\Latin_Capital_Letter_I_With_Caron . #\Latin_Small_Letter_I_With_Caron)
+          
+          (#\Latin_Capital_Letter_O_With_Caron . #\Latin_Small_Letter_O_With_Caron)
+          
+          (#\Latin_Capital_Letter_U_With_Caron . #\Latin_Small_Letter_U_With_Caron)
+          
+          (#\Latin_Capital_Letter_U_With_Diaeresis_And_Macron
+           . #\Latin_Small_Letter_U_With_Diaeresis_And_Macron)
+          
+          (#\Latin_Capital_Letter_U_With_Diaeresis_And_Acute
+           . #\Latin_Small_Letter_U_With_Diaeresis_And_Acute)
+          
+          (#\Latin_Capital_Letter_U_With_Diaeresis_And_Caron
+           . #\Latin_Small_Letter_U_With_Diaeresis_And_Caron)
+          
+          (#\Latin_Capital_Letter_U_With_Diaeresis_And_Grave
+           . #\Latin_Small_Letter_U_With_Diaeresis_And_Grave)
+          
+          (#\Latin_Capital_Letter_A_With_Diaeresis_And_Macron
+           . #\Latin_Small_Letter_A_With_Diaeresis_And_Macron)
+          
+          (#\Latin_Capital_Letter_A_With_Dot_Above_And_Macron
+           . #\Latin_Small_Letter_A_With_Dot_Above_And_Macron)
+          
+          (#\Latin_Capital_Letter_Ae_With_Macron . #\Latin_Small_Letter_Ae_With_Macron)
+          
+          (#\Latin_Capital_Letter_G_With_Stroke . #\Latin_Small_Letter_G_With_Stroke)
+          
+          (#\Latin_Capital_Letter_G_With_Caron . #\Latin_Small_Letter_G_With_Caron)
+          
+          (#\Latin_Capital_Letter_K_With_Caron . #\Latin_Small_Letter_K_With_Caron)
+          
+          (#\Latin_Capital_Letter_O_With_Ogonek . #\Latin_Small_Letter_O_With_Ogonek)
+          
+          (#\Latin_Capital_Letter_O_With_Ogonek_And_Macron
+           . #\Latin_Small_Letter_O_With_Ogonek_And_Macron)
+          
+          (#\Latin_Capital_Letter_Ezh_With_Caron . #\Latin_Small_Letter_Ezh_With_Caron)
+          
+          (#\Latin_Capital_Letter_Dz . #\Latin_Small_Letter_Dz)
+          
+          (#\Latin_Capital_Letter_G_With_Acute . #\Latin_Small_Letter_G_With_Acute)
+          
+          (#\Latin_Capital_Letter_Hwair . #\Latin_Small_Letter_Hv)
+          
+          (#\Latin_Capital_Letter_Wynn . #\Latin_Letter_Wynn)
+          
+          (#\Latin_Capital_Letter_N_With_Grave . #\Latin_Small_Letter_N_With_Grave)
+          
+          (#\Latin_Capital_Letter_A_With_Ring_Above_And_Acute
+           . #\Latin_Small_Letter_A_With_Ring_Above_And_Acute)
+          
+          (#\Latin_Capital_Letter_Ae_With_Acute . #\Latin_Small_Letter_Ae_With_Acute)
+          
+          (#\Latin_Capital_Letter_O_With_Stroke_And_Acute
+           . #\Latin_Small_Letter_O_With_Stroke_And_Acute)
+          
+          (#\Latin_Capital_Letter_A_With_Double_Grave
+           . #\Latin_Small_Letter_A_With_Double_Grave)
+          
+          (#\Latin_Capital_Letter_A_With_Inverted_Breve
+           . #\Latin_Small_Letter_A_With_Inverted_Breve)
+          
+          (#\Latin_Capital_Letter_E_With_Double_Grave
+           . #\Latin_Small_Letter_E_With_Double_Grave)
+          
+          (#\Latin_Capital_Letter_E_With_Inverted_Breve
+           . #\Latin_Small_Letter_E_With_Inverted_Breve)
+          
+          (#\Latin_Capital_Letter_I_With_Double_Grave
+           . #\Latin_Small_Letter_I_With_Double_Grave)
+          
+          (#\Latin_Capital_Letter_I_With_Inverted_Breve
+           . #\Latin_Small_Letter_I_With_Inverted_Breve)
+          
+          (#\Latin_Capital_Letter_O_With_Double_Grave
+           . #\Latin_Small_Letter_O_With_Double_Grave)
+          
+          (#\Latin_Capital_Letter_O_With_Inverted_Breve
+           . #\Latin_Small_Letter_O_With_Inverted_Breve)
+          
+          (#\Latin_Capital_Letter_R_With_Double_Grave
+           . #\Latin_Small_Letter_R_With_Double_Grave)
+          
+          (#\Latin_Capital_Letter_R_With_Inverted_Breve
+           . #\Latin_Small_Letter_R_With_Inverted_Breve)
+          
+          (#\Latin_Capital_Letter_U_With_Double_Grave
+           . #\Latin_Small_Letter_U_With_Double_Grave)
+          
+          (#\Latin_Capital_Letter_U_With_Inverted_Breve
+           . #\Latin_Small_Letter_U_With_Inverted_Breve)
+          
+          (#\Latin_Capital_Letter_S_With_Comma_Below
+           . #\Latin_Small_Letter_S_With_Comma_Below)
+          
+          (#\Latin_Capital_Letter_T_With_Comma_Below
+           . #\Latin_Small_Letter_T_With_Comma_Below)
+          
+          (#\Latin_Capital_Letter_Yogh . #\Latin_Small_Letter_Yogh)
+          
+          (#\Latin_Capital_Letter_H_With_Caron . #\Latin_Small_Letter_H_With_Caron)
+          
+          (#\Latin_Capital_Letter_N_With_Long_Right_Leg
+           . #\Latin_Small_Letter_N_With_Long_Right_Leg)
+          
+          (#\Latin_Capital_Letter_Ou . #\Latin_Small_Letter_Ou)
+          
+          (#\Latin_Capital_Letter_Z_With_Hook . #\Latin_Small_Letter_Z_With_Hook)
+          
+          (#\Latin_Capital_Letter_A_With_Dot_Above
+           . #\Latin_Small_Letter_A_With_Dot_Above)
+          
+          (#\Latin_Capital_Letter_E_With_Cedilla . #\Latin_Small_Letter_E_With_Cedilla)
+          
+          (#\Latin_Capital_Letter_O_With_Diaeresis_And_Macron
+           . #\Latin_Small_Letter_O_With_Diaeresis_And_Macron)
+          
+          (#\Latin_Capital_Letter_O_With_Tilde_And_Macron
+           . #\Latin_Small_Letter_O_With_Tilde_And_Macron)
+          
+          (#\Latin_Capital_Letter_O_With_Dot_Above
+           . #\Latin_Small_Letter_O_With_Dot_Above)
+          
+          (#\Latin_Capital_Letter_O_With_Dot_Above_And_Macron
+           . #\Latin_Small_Letter_O_With_Dot_Above_And_Macron)
+          
+          (#\Latin_Capital_Letter_Y_With_Macron . #\Latin_Small_Letter_Y_With_Macron)
+          
+          (#\Latin_Capital_Letter_A_With_Stroke . #\U+2C65)
+          
+          (#\Latin_Capital_Letter_C_With_Stroke . #\Latin_Small_Letter_C_With_Stroke)
+          
+          (#\Latin_Capital_Letter_L_With_Bar . #\Latin_Small_Letter_L_With_Bar)
+          
+          (#\Latin_Capital_Letter_T_With_Diagonal_Stroke . #\U+2C66)
+          
+          (#\Latin_Capital_Letter_Glottal_Stop . #\Latin_Small_Letter_Glottal_Stop)
+          
+          (#\Latin_Capital_Letter_B_With_Stroke . #\Latin_Small_Letter_B_With_Stroke)
+          
+          (#\Latin_Capital_Letter_U_Bar . #\Latin_Small_Letter_U_Bar)
+          
+          (#\Latin_Capital_Letter_Turned_V . #\Latin_Small_Letter_Turned_V)
+          
+          (#\Latin_Capital_Letter_E_With_Stroke . #\Latin_Small_Letter_E_With_Stroke)
+          
+          (#\Latin_Capital_Letter_J_With_Stroke . #\Latin_Small_Letter_J_With_Stroke)
+          
+          (#\Latin_Capital_Letter_Small_Q_With_Hook_Tail
+           . #\Latin_Small_Letter_Q_With_Hook_Tail)
+          
+          (#\Latin_Capital_Letter_R_With_Stroke . #\Latin_Small_Letter_R_With_Stroke)
+          
+          (#\Latin_Capital_Letter_Y_With_Stroke . #\Latin_Small_Letter_Y_With_Stroke)
+          
+          (#\Greek_Capital_Letter_Alpha_With_Tonos
+           . #\Greek_Small_Letter_Alpha_With_Tonos)
+          
+          (#\Greek_Capital_Letter_Epsilon_With_Tonos
+           . #\Greek_Small_Letter_Epsilon_With_Tonos)
+          
+          (#\Greek_Capital_Letter_Eta_With_Tonos . #\Greek_Small_Letter_Eta_With_Tonos)
+          
+          (#\Greek_Capital_Letter_Iota_With_Tonos
+           . #\Greek_Small_Letter_Iota_With_Tonos)
+          
+          (#\Greek_Capital_Letter_Omicron_With_Tonos
+           . #\Greek_Small_Letter_Omicron_With_Tonos)
+          
+          (#\Greek_Capital_Letter_Upsilon_With_Tonos
+           . #\Greek_Small_Letter_Upsilon_With_Tonos)
+          
+          (#\Greek_Capital_Letter_Omega_With_Tonos
+           . #\Greek_Small_Letter_Omega_With_Tonos)
+          
+          (#\Greek_Capital_Letter_Alpha . #\Greek_Small_Letter_Alpha)
+          
+          (#\Greek_Capital_Letter_Beta . #\Greek_Small_Letter_Beta)
+          
+          (#\Greek_Capital_Letter_Gamma . #\Greek_Small_Letter_Gamma)
+          
+          (#\Greek_Capital_Letter_Delta . #\Greek_Small_Letter_Delta)
+          
+          (#\Greek_Capital_Letter_Epsilon . #\Greek_Small_Letter_Epsilon)
+          
+          (#\Greek_Capital_Letter_Zeta . #\Greek_Small_Letter_Zeta)
+          
+          (#\Greek_Capital_Letter_Eta . #\Greek_Small_Letter_Eta)
+          
+          (#\Greek_Capital_Letter_Theta . #\Greek_Small_Letter_Theta)
+          
+          (#\Greek_Capital_Letter_Iota . #\Greek_Small_Letter_Iota)
+          
+          (#\Greek_Capital_Letter_Kappa . #\Greek_Small_Letter_Kappa)
+          
+          (#\Greek_Capital_Letter_Lamda . #\Greek_Small_Letter_Lamda)
+          
+          (#\Greek_Capital_Letter_Mu . #\Greek_Small_Letter_Mu)
+          
+          (#\Greek_Capital_Letter_Nu . #\Greek_Small_Letter_Nu)
+          
+          (#\Greek_Capital_Letter_Xi . #\Greek_Small_Letter_Xi)
+          
+          (#\Greek_Capital_Letter_Omicron . #\Greek_Small_Letter_Omicron)
+          
+          (#\Greek_Capital_Letter_Pi . #\Greek_Small_Letter_Pi)
+          
+          (#\Greek_Capital_Letter_Rho . #\Greek_Small_Letter_Rho)
+          
+          (#\Greek_Capital_Letter_Sigma . #\Greek_Small_Letter_Sigma)
+          
+          (#\Greek_Capital_Letter_Tau . #\Greek_Small_Letter_Tau)
+          
+          (#\Greek_Capital_Letter_Upsilon . #\Greek_Small_Letter_Upsilon)
+          
+          (#\Greek_Capital_Letter_Phi . #\Greek_Small_Letter_Phi)
+          
+          (#\Greek_Capital_Letter_Chi . #\Greek_Small_Letter_Chi)
+          
+          (#\Greek_Capital_Letter_Psi . #\Greek_Small_Letter_Psi)
+          
+          (#\Greek_Capital_Letter_Omega . #\Greek_Small_Letter_Omega)
+          
+          (#\Greek_Capital_Letter_Iota_With_Dialytika
+           . #\Greek_Small_Letter_Iota_With_Dialytika)
+          
+          (#\Greek_Capital_Letter_Upsilon_With_Dialytika
+           . #\Greek_Small_Letter_Upsilon_With_Dialytika)
+          
+          (#\Greek_Letter_Archaic_Koppa . #\Greek_Small_Letter_Archaic_Koppa)
+          
+          (#\Greek_Letter_Stigma . #\Greek_Small_Letter_Stigma)
+          
+          (#\Greek_Letter_Digamma . #\Greek_Small_Letter_Digamma)
+          
+          (#\Greek_Letter_Koppa . #\Greek_Small_Letter_Koppa)
+          
+          (#\Greek_Letter_Sampi . #\Greek_Small_Letter_Sampi)
+          
+          (#\Coptic_Capital_Letter_Shei . #\Coptic_Small_Letter_Shei)
+          
+          (#\Coptic_Capital_Letter_Fei . #\Coptic_Small_Letter_Fei)
+          
+          (#\Coptic_Capital_Letter_Khei . #\Coptic_Small_Letter_Khei)
+          
+          (#\Coptic_Capital_Letter_Hori . #\Coptic_Small_Letter_Hori)
+          
+          (#\Coptic_Capital_Letter_Gangia . #\Coptic_Small_Letter_Gangia)
+          
+          (#\Coptic_Capital_Letter_Shima . #\Coptic_Small_Letter_Shima)
+          
+          (#\Coptic_Capital_Letter_Dei . #\Coptic_Small_Letter_Dei)
+          
+          (#\Greek_Capital_Letter_Sho . #\Greek_Small_Letter_Sho)
+          
+          (#\Greek_Capital_Lunate_Sigma_Symbol . #\Greek_Lunate_Sigma_Symbol)
+          
+          (#\Greek_Capital_Letter_San . #\Greek_Small_Letter_San)
+          
+          (#\Greek_Capital_Reversed_Lunate_Sigma_Symbol
+           . #\Greek_Small_Reversed_Lunate_Sigma_Symbol)
+          
+          (#\Greek_Capital_Dotted_Lunate_Sigma_Symbol
+           . #\Greek_Small_Dotted_Lunate_Sigma_Symbol)
+          
+          (#\Greek_Capital_Reversed_Dotted_Lunate_Sigma_Symbol
+           . #\Greek_Small_Reversed_Dotted_Lunate_Sigma_Symbol)
+          
+          (#\Cyrillic_Capital_Letter_Ie_With_Grave
+           . #\Cyrillic_Small_Letter_Ie_With_Grave)
+          
+          (#\Cyrillic_Capital_Letter_Io . #\Cyrillic_Small_Letter_Io)
+          
+          (#\Cyrillic_Capital_Letter_Dje . #\Cyrillic_Small_Letter_Dje)
+          
+          (#\Cyrillic_Capital_Letter_Gje . #\Cyrillic_Small_Letter_Gje)
+          
+          (#\Cyrillic_Capital_Letter_Ukrainian_Ie
+           . #\Cyrillic_Small_Letter_Ukrainian_Ie)
+          
+          (#\Cyrillic_Capital_Letter_Dze . #\Cyrillic_Small_Letter_Dze)
+          
+          (#\Cyrillic_Capital_Letter_Byelorussian-Ukrainian_I
+           . #\Cyrillic_Small_Letter_Byelorussian-Ukrainian_I)
+          
+          (#\Cyrillic_Capital_Letter_Yi . #\Cyrillic_Small_Letter_Yi)
+          
+          (#\Cyrillic_Capital_Letter_Je . #\Cyrillic_Small_Letter_Je)
+          
+          (#\Cyrillic_Capital_Letter_Lje . #\Cyrillic_Small_Letter_Lje)
+          
+          (#\Cyrillic_Capital_Letter_Nje . #\Cyrillic_Small_Letter_Nje)
+          
+          (#\Cyrillic_Capital_Letter_Tshe . #\Cyrillic_Small_Letter_Tshe)
+          
+          (#\Cyrillic_Capital_Letter_Kje . #\Cyrillic_Small_Letter_Kje)
+          
+          (#\Cyrillic_Capital_Letter_I_With_Grave
+           . #\Cyrillic_Small_Letter_I_With_Grave)
+          
+          (#\Cyrillic_Capital_Letter_Short_U . #\Cyrillic_Small_Letter_Short_U)
+          
+          (#\Cyrillic_Capital_Letter_Dzhe . #\Cyrillic_Small_Letter_Dzhe)
+          
+          (#\Cyrillic_Capital_Letter_A . #\Cyrillic_Small_Letter_A)
+          
+          (#\Cyrillic_Capital_Letter_Be . #\Cyrillic_Small_Letter_Be)
+          
+          (#\Cyrillic_Capital_Letter_Ve . #\Cyrillic_Small_Letter_Ve)
+          
+          (#\Cyrillic_Capital_Letter_Ghe . #\Cyrillic_Small_Letter_Ghe)
+          
+          (#\Cyrillic_Capital_Letter_De . #\Cyrillic_Small_Letter_De)
+          
+          (#\Cyrillic_Capital_Letter_Ie . #\Cyrillic_Small_Letter_Ie)
+          
+          (#\Cyrillic_Capital_Letter_Zhe . #\Cyrillic_Small_Letter_Zhe)
+          
+          (#\Cyrillic_Capital_Letter_Ze . #\Cyrillic_Small_Letter_Ze)
+          
+          (#\Cyrillic_Capital_Letter_I . #\Cyrillic_Small_Letter_I)
+          
+          (#\Cyrillic_Capital_Letter_Short_I . #\Cyrillic_Small_Letter_Short_I)
+          
+          (#\Cyrillic_Capital_Letter_Ka . #\Cyrillic_Small_Letter_Ka)
+          
+          (#\Cyrillic_Capital_Letter_El . #\Cyrillic_Small_Letter_El)
+          
+          (#\Cyrillic_Capital_Letter_Em . #\Cyrillic_Small_Letter_Em)
+          
+          (#\Cyrillic_Capital_Letter_En . #\Cyrillic_Small_Letter_En)
+          
+          (#\Cyrillic_Capital_Letter_O . #\Cyrillic_Small_Letter_O)
+          
+          (#\Cyrillic_Capital_Letter_Pe . #\Cyrillic_Small_Letter_Pe)
+          
+          (#\Cyrillic_Capital_Letter_Er . #\Cyrillic_Small_Letter_Er)
+          
+          (#\Cyrillic_Capital_Letter_Es . #\Cyrillic_Small_Letter_Es)
+          
+          (#\Cyrillic_Capital_Letter_Te . #\Cyrillic_Small_Letter_Te)
+          
+          (#\Cyrillic_Capital_Letter_U . #\Cyrillic_Small_Letter_U)
+          
+          (#\Cyrillic_Capital_Letter_Ef . #\Cyrillic_Small_Letter_Ef)
+          
+          (#\Cyrillic_Capital_Letter_Ha . #\Cyrillic_Small_Letter_Ha)
+          
+          (#\Cyrillic_Capital_Letter_Tse . #\Cyrillic_Small_Letter_Tse)
+          
+          (#\Cyrillic_Capital_Letter_Che . #\Cyrillic_Small_Letter_Che)
+          
+          (#\Cyrillic_Capital_Letter_Sha . #\Cyrillic_Small_Letter_Sha)
+          
+          (#\Cyrillic_Capital_Letter_Shcha . #\Cyrillic_Small_Letter_Shcha)
+          
+          (#\Cyrillic_Capital_Letter_Hard_Sign . #\Cyrillic_Small_Letter_Hard_Sign)
+          
+          (#\Cyrillic_Capital_Letter_Yeru . #\Cyrillic_Small_Letter_Yeru)
+          
+          (#\Cyrillic_Capital_Letter_Soft_Sign . #\Cyrillic_Small_Letter_Soft_Sign)
+          
+          (#\Cyrillic_Capital_Letter_E . #\Cyrillic_Small_Letter_E)
+          
+          (#\Cyrillic_Capital_Letter_Yu . #\Cyrillic_Small_Letter_Yu)
+          
+          (#\Cyrillic_Capital_Letter_Ya . #\Cyrillic_Small_Letter_Ya)
+          
+          (#\Cyrillic_Capital_Letter_Omega . #\Cyrillic_Small_Letter_Omega)
+          
+          (#\Cyrillic_Capital_Letter_Yat . #\Cyrillic_Small_Letter_Yat)
+          
+          (#\Cyrillic_Capital_Letter_Iotified_E . #\Cyrillic_Small_Letter_Iotified_E)
+          
+          (#\Cyrillic_Capital_Letter_Little_Yus . #\Cyrillic_Small_Letter_Little_Yus)
+          
+          (#\Cyrillic_Capital_Letter_Iotified_Little_Yus
+           . #\Cyrillic_Small_Letter_Iotified_Little_Yus)
+          
+          (#\Cyrillic_Capital_Letter_Big_Yus . #\Cyrillic_Small_Letter_Big_Yus)
+          
+          (#\Cyrillic_Capital_Letter_Iotified_Big_Yus
+           . #\Cyrillic_Small_Letter_Iotified_Big_Yus)
+          
+          (#\Cyrillic_Capital_Letter_Ksi . #\Cyrillic_Small_Letter_Ksi)
+          
+          (#\Cyrillic_Capital_Letter_Psi . #\Cyrillic_Small_Letter_Psi)
+          
+          (#\Cyrillic_Capital_Letter_Fita . #\Cyrillic_Small_Letter_Fita)
+          
+          (#\Cyrillic_Capital_Letter_Izhitsa . #\Cyrillic_Small_Letter_Izhitsa)
+          
+          (#\Cyrillic_Capital_Letter_Izhitsa_With_Double_Grave_Accent
+           . #\Cyrillic_Small_Letter_Izhitsa_With_Double_Grave_Accent)
+          
+          (#\Cyrillic_Capital_Letter_Uk . #\Cyrillic_Small_Letter_Uk)
+          
+          (#\Cyrillic_Capital_Letter_Round_Omega . #\Cyrillic_Small_Letter_Round_Omega)
+          
+          (#\Cyrillic_Capital_Letter_Omega_With_Titlo
+           . #\Cyrillic_Small_Letter_Omega_With_Titlo)
+          
+          (#\Cyrillic_Capital_Letter_Ot . #\Cyrillic_Small_Letter_Ot)
+          
+          (#\Cyrillic_Capital_Letter_Koppa . #\Cyrillic_Small_Letter_Koppa)
+          
+          (#\Cyrillic_Capital_Letter_Short_I_With_Tail
+           . #\Cyrillic_Small_Letter_Short_I_With_Tail)
+          
+          (#\Cyrillic_Capital_Letter_Semisoft_Sign
+           . #\Cyrillic_Small_Letter_Semisoft_Sign)
+          
+          (#\Cyrillic_Capital_Letter_Er_With_Tick
+           . #\Cyrillic_Small_Letter_Er_With_Tick)
+          
+          (#\Cyrillic_Capital_Letter_Ghe_With_Upturn
+           . #\Cyrillic_Small_Letter_Ghe_With_Upturn)
+          
+          (#\Cyrillic_Capital_Letter_Ghe_With_Stroke
+           . #\Cyrillic_Small_Letter_Ghe_With_Stroke)
+          
+          (#\Cyrillic_Capital_Letter_Ghe_With_Middle_Hook
+           . #\Cyrillic_Small_Letter_Ghe_With_Middle_Hook)
+          
+          (#\Cyrillic_Capital_Letter_Zhe_With_Descender
+           . #\Cyrillic_Small_Letter_Zhe_With_Descender)
+          
+          (#\Cyrillic_Capital_Letter_Ze_With_Descender
+           . #\Cyrillic_Small_Letter_Ze_With_Descender)
+          
+          (#\Cyrillic_Capital_Letter_Ka_With_Descender
+           . #\Cyrillic_Small_Letter_Ka_With_Descender)
+          
+          (#\Cyrillic_Capital_Letter_Ka_With_Vertical_Stroke
+           . #\Cyrillic_Small_Letter_Ka_With_Vertical_Stroke)
+          
+          (#\Cyrillic_Capital_Letter_Ka_With_Stroke
+           . #\Cyrillic_Small_Letter_Ka_With_Stroke)
+          
+          (#\Cyrillic_Capital_Letter_Bashkir_Ka . #\Cyrillic_Small_Letter_Bashkir_Ka)
+          
+          (#\Cyrillic_Capital_Letter_En_With_Descender
+           . #\Cyrillic_Small_Letter_En_With_Descender)
+          
+          (#\Cyrillic_Capital_Ligature_En_Ghe . #\Cyrillic_Small_Ligature_En_Ghe)
+          
+          (#\Cyrillic_Capital_Letter_Pe_With_Middle_Hook
+           . #\Cyrillic_Small_Letter_Pe_With_Middle_Hook)
+          
+          (#\Cyrillic_Capital_Letter_Abkhasian_Ha
+           . #\Cyrillic_Small_Letter_Abkhasian_Ha)
+          
+          (#\Cyrillic_Capital_Letter_Es_With_Descender
+           . #\Cyrillic_Small_Letter_Es_With_Descender)
+          
+          (#\Cyrillic_Capital_Letter_Te_With_Descender
+           . #\Cyrillic_Small_Letter_Te_With_Descender)
+          
+          (#\Cyrillic_Capital_Letter_Straight_U . #\Cyrillic_Small_Letter_Straight_U)
+          
+          (#\Cyrillic_Capital_Letter_Straight_U_With_Stroke
+           . #\Cyrillic_Small_Letter_Straight_U_With_Stroke)
+          
+          (#\Cyrillic_Capital_Letter_Ha_With_Descender
+           . #\Cyrillic_Small_Letter_Ha_With_Descender)
+          
+          (#\Cyrillic_Capital_Ligature_Te_Tse . #\Cyrillic_Small_Ligature_Te_Tse)
+          
+          (#\Cyrillic_Capital_Letter_Che_With_Descender
+           . #\Cyrillic_Small_Letter_Che_With_Descender)
+          
+          (#\Cyrillic_Capital_Letter_Che_With_Vertical_Stroke
+           . #\Cyrillic_Small_Letter_Che_With_Vertical_Stroke)
+          
+          (#\Cyrillic_Capital_Letter_Shha . #\Cyrillic_Small_Letter_Shha)
+          
+          (#\Cyrillic_Capital_Letter_Abkhasian_Che
+           . #\Cyrillic_Small_Letter_Abkhasian_Che)
+          
+          (#\Cyrillic_Capital_Letter_Abkhasian_Che_With_Descender
+           . #\Cyrillic_Small_Letter_Abkhasian_Che_With_Descender)
+          
+          (#\Cyrillic_Letter_Palochka . #\Cyrillic_Small_Letter_Palochka)
+          
+          (#\Cyrillic_Capital_Letter_Zhe_With_Breve
+           . #\Cyrillic_Small_Letter_Zhe_With_Breve)
+          
+          (#\Cyrillic_Capital_Letter_Ka_With_Hook
+           . #\Cyrillic_Small_Letter_Ka_With_Hook)
+          
+          (#\Cyrillic_Capital_Letter_El_With_Tail
+           . #\Cyrillic_Small_Letter_El_With_Tail)
+          
+          (#\Cyrillic_Capital_Letter_En_With_Hook
+           . #\Cyrillic_Small_Letter_En_With_Hook)
+          
+          (#\Cyrillic_Capital_Letter_En_With_Tail
+           . #\Cyrillic_Small_Letter_En_With_Tail)
+          
+          (#\Cyrillic_Capital_Letter_Khakassian_Che
+           . #\Cyrillic_Small_Letter_Khakassian_Che)
+          
+          (#\Cyrillic_Capital_Letter_Em_With_Tail
+           . #\Cyrillic_Small_Letter_Em_With_Tail)
+          
+          (#\Cyrillic_Capital_Letter_A_With_Breve
+           . #\Cyrillic_Small_Letter_A_With_Breve)
+          
+          (#\Cyrillic_Capital_Letter_A_With_Diaeresis
+           . #\Cyrillic_Small_Letter_A_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Ligature_A_Ie . #\Cyrillic_Small_Ligature_A_Ie)
+          
+          (#\Cyrillic_Capital_Letter_Ie_With_Breve
+           . #\Cyrillic_Small_Letter_Ie_With_Breve)
+          
+          (#\Cyrillic_Capital_Letter_Schwa . #\Cyrillic_Small_Letter_Schwa)
+          
+          (#\Cyrillic_Capital_Letter_Schwa_With_Diaeresis
+           . #\Cyrillic_Small_Letter_Schwa_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_Zhe_With_Diaeresis
+           . #\Cyrillic_Small_Letter_Zhe_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_Ze_With_Diaeresis
+           . #\Cyrillic_Small_Letter_Ze_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_Abkhasian_Dze
+           . #\Cyrillic_Small_Letter_Abkhasian_Dze)
+          
+          (#\Cyrillic_Capital_Letter_I_With_Macron
+           . #\Cyrillic_Small_Letter_I_With_Macron)
+          
+          (#\Cyrillic_Capital_Letter_I_With_Diaeresis
+           . #\Cyrillic_Small_Letter_I_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_O_With_Diaeresis
+           . #\Cyrillic_Small_Letter_O_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_Barred_O . #\Cyrillic_Small_Letter_Barred_O)
+          
+          (#\Cyrillic_Capital_Letter_Barred_O_With_Diaeresis
+           . #\Cyrillic_Small_Letter_Barred_O_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_E_With_Diaeresis
+           . #\Cyrillic_Small_Letter_E_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_U_With_Macron
+           . #\Cyrillic_Small_Letter_U_With_Macron)
+          
+          (#\Cyrillic_Capital_Letter_U_With_Diaeresis
+           . #\Cyrillic_Small_Letter_U_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_U_With_Double_Acute
+           . #\Cyrillic_Small_Letter_U_With_Double_Acute)
+          
+          (#\Cyrillic_Capital_Letter_Che_With_Diaeresis
+           . #\Cyrillic_Small_Letter_Che_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_Ghe_With_Descender
+           . #\Cyrillic_Small_Letter_Ghe_With_Descender)
+          
+          (#\Cyrillic_Capital_Letter_Yeru_With_Diaeresis
+           . #\Cyrillic_Small_Letter_Yeru_With_Diaeresis)
+          
+          (#\Cyrillic_Capital_Letter_Ghe_With_Stroke_And_Hook
+           . #\Cyrillic_Small_Letter_Ghe_With_Stroke_And_Hook)
+          
+          (#\Cyrillic_Capital_Letter_Ha_With_Hook
+           . #\Cyrillic_Small_Letter_Ha_With_Hook)
+          
+          (#\Cyrillic_Capital_Letter_Ha_With_Stroke
+           . #\Cyrillic_Small_Letter_Ha_With_Stroke)
+          
+          (#\Cyrillic_Capital_Letter_Komi_De . #\Cyrillic_Small_Letter_Komi_De)
+          
+          (#\Cyrillic_Capital_Letter_Komi_Dje . #\Cyrillic_Small_Letter_Komi_Dje)
+          
+          (#\Cyrillic_Capital_Letter_Komi_Zje . #\Cyrillic_Small_Letter_Komi_Zje)
+          
+          (#\Cyrillic_Capital_Letter_Komi_Dzje . #\Cyrillic_Small_Letter_Komi_Dzje)
+          
+          (#\Cyrillic_Capital_Letter_Komi_Lje . #\Cyrillic_Small_Letter_Komi_Lje)
+          
+          (#\Cyrillic_Capital_Letter_Komi_Nje . #\Cyrillic_Small_Letter_Komi_Nje)
+          
+          (#\Cyrillic_Capital_Letter_Komi_Sje . #\Cyrillic_Small_Letter_Komi_Sje)
+          
+          (#\Cyrillic_Capital_Letter_Komi_Tje . #\Cyrillic_Small_Letter_Komi_Tje)
+          
+          (#\Cyrillic_Capital_Letter_Reversed_Ze . #\Cyrillic_Small_Letter_Reversed_Ze)
+          
+          (#\Cyrillic_Capital_Letter_El_With_Hook
+           . #\Cyrillic_Small_Letter_El_With_Hook)
+          
+          (#\Armenian_Capital_Letter_Ayb . #\Armenian_Small_Letter_Ayb)
+          
+          (#\Armenian_Capital_Letter_Ben . #\Armenian_Small_Letter_Ben)
+          
+          (#\Armenian_Capital_Letter_Gim . #\Armenian_Small_Letter_Gim)
+          
+          (#\Armenian_Capital_Letter_Da . #\Armenian_Small_Letter_Da)
+          
+          (#\Armenian_Capital_Letter_Ech . #\Armenian_Small_Letter_Ech)
+          
+          (#\Armenian_Capital_Letter_Za . #\Armenian_Small_Letter_Za)
+          
+          (#\Armenian_Capital_Letter_Eh . #\Armenian_Small_Letter_Eh)
+          
+          (#\Armenian_Capital_Letter_Et . #\Armenian_Small_Letter_Et)
+          
+          (#\Armenian_Capital_Letter_To . #\Armenian_Small_Letter_To)
+          
+          (#\Armenian_Capital_Letter_Zhe . #\Armenian_Small_Letter_Zhe)
+          
+          (#\Armenian_Capital_Letter_Ini . #\Armenian_Small_Letter_Ini)
+          
+          (#\Armenian_Capital_Letter_Liwn . #\Armenian_Small_Letter_Liwn)
+          
+          (#\Armenian_Capital_Letter_Xeh . #\Armenian_Small_Letter_Xeh)
+          
+          (#\Armenian_Capital_Letter_Ca . #\Armenian_Small_Letter_Ca)
+          
+          (#\Armenian_Capital_Letter_Ken . #\Armenian_Small_Letter_Ken)
+          
+          (#\Armenian_Capital_Letter_Ho . #\Armenian_Small_Letter_Ho)
+          
+          (#\Armenian_Capital_Letter_Ja . #\Armenian_Small_Letter_Ja)
+          
+          (#\Armenian_Capital_Letter_Ghad . #\Armenian_Small_Letter_Ghad)
+          
+          (#\Armenian_Capital_Letter_Cheh . #\Armenian_Small_Letter_Cheh)
+          
+          (#\Armenian_Capital_Letter_Men . #\Armenian_Small_Letter_Men)
+          
+          (#\Armenian_Capital_Letter_Yi . #\Armenian_Small_Letter_Yi)
+          
+          (#\Armenian_Capital_Letter_Now . #\Armenian_Small_Letter_Now)
+          
+          (#\Armenian_Capital_Letter_Sha . #\Armenian_Small_Letter_Sha)
+          
+          (#\Armenian_Capital_Letter_Vo . #\Armenian_Small_Letter_Vo)
+          
+          (#\Armenian_Capital_Letter_Cha . #\Armenian_Small_Letter_Cha)
+          
+          (#\Armenian_Capital_Letter_Peh . #\Armenian_Small_Letter_Peh)
+          
+          (#\Armenian_Capital_Letter_Jheh . #\Armenian_Small_Letter_Jheh)
+          
+          (#\Armenian_Capital_Letter_Ra . #\Armenian_Small_Letter_Ra)
+          
+          (#\Armenian_Capital_Letter_Seh . #\Armenian_Small_Letter_Seh)
+          
+          (#\Armenian_Capital_Letter_Vew . #\Armenian_Small_Letter_Vew)
+          
+          (#\Armenian_Capital_Letter_Tiwn . #\Armenian_Small_Letter_Tiwn)
+          
+          (#\Armenian_Capital_Letter_Reh . #\Armenian_Small_Letter_Reh)
+          
+          (#\Armenian_Capital_Letter_Co . #\Armenian_Small_Letter_Co)
+          
+          (#\Armenian_Capital_Letter_Yiwn . #\Armenian_Small_Letter_Yiwn)
+          
+          (#\Armenian_Capital_Letter_Piwr . #\Armenian_Small_Letter_Piwr)
+          
+          (#\Armenian_Capital_Letter_Keh . #\Armenian_Small_Letter_Keh)
+          
+          (#\Armenian_Capital_Letter_Oh . #\Armenian_Small_Letter_Oh)
+          
+          (#\Armenian_Capital_Letter_Feh . #\Armenian_Small_Letter_Feh)
+          
+          (#\U+10A0 . #\U+2D00)
+          (#\U+10A1 . #\U+2D01)
+          (#\U+10A2 . #\U+2D02)
+          
+          (#\U+10A3 . #\U+2D03)
+          (#\U+10A4 . #\U+2D04)
+          (#\U+10A5 . #\U+2D05)
+          
+          (#\U+10A6 . #\U+2D06)
+          (#\U+10A7 . #\U+2D07)
+          (#\U+10A8 . #\U+2D08)
+          
+          (#\U+10A9 . #\U+2D09)
+          (#\U+10AA . #\U+2D0A)
+          (#\U+10AB . #\U+2D0B)
+          
+          (#\U+10AC . #\U+2D0C)
+          (#\U+10AD . #\U+2D0D)
+          (#\U+10AE . #\U+2D0E)
+          
+          (#\U+10AF . #\U+2D0F)
+          (#\U+10B0 . #\U+2D10)
+          (#\U+10B1 . #\U+2D11)
+          
+          (#\U+10B2 . #\U+2D12)
+          (#\U+10B3 . #\U+2D13)
+          (#\U+10B4 . #\U+2D14)
+          
+          (#\U+10B5 . #\U+2D15)
+          (#\U+10B6 . #\U+2D16)
+          (#\U+10B7 . #\U+2D17)
+          
+          (#\U+10B8 . #\U+2D18)
+          (#\U+10B9 . #\U+2D19)
+          (#\U+10BA . #\U+2D1A)
+          
+          (#\U+10BB . #\U+2D1B)
+          (#\U+10BC . #\U+2D1C)
+          (#\U+10BD . #\U+2D1D)
+          
+          (#\U+10BE . #\U+2D1E)
+          (#\U+10BF . #\U+2D1F)
+          (#\U+10C0 . #\U+2D20)
+          
+          (#\U+10C1 . #\U+2D21)
+          (#\U+10C2 . #\U+2D22)
+          (#\U+10C3 . #\U+2D23)
+          
+          (#\U+10C4 . #\U+2D24)
+          (#\U+10C5 . #\U+2D25)
+          (#\U+1E00 . #\U+1E01)
+          
+          (#\U+1E02 . #\U+1E03)
+          (#\U+1E04 . #\U+1E05)
+          (#\U+1E06 . #\U+1E07)
+          
+          (#\U+1E08 . #\U+1E09)
+          (#\U+1E0A . #\U+1E0B)
+          (#\U+1E0C . #\U+1E0D)
+          
+          (#\U+1E0E . #\U+1E0F)
+          (#\U+1E10 . #\U+1E11)
+          (#\U+1E12 . #\U+1E13)
+          
+          (#\U+1E14 . #\U+1E15)
+          (#\U+1E16 . #\U+1E17)
+          (#\U+1E18 . #\U+1E19)
+          
+          (#\U+1E1A . #\U+1E1B)
+          (#\U+1E1C . #\U+1E1D)
+          (#\U+1E1E . #\U+1E1F)
+          
+          (#\U+1E20 . #\U+1E21)
+          (#\U+1E22 . #\U+1E23)
+          (#\U+1E24 . #\U+1E25)
+          
+          (#\U+1E26 . #\U+1E27)
+          (#\U+1E28 . #\U+1E29)
+          (#\U+1E2A . #\U+1E2B)
+          
+          (#\U+1E2C . #\U+1E2D)
+          (#\U+1E2E . #\U+1E2F)
+          (#\U+1E30 . #\U+1E31)
+          
+          (#\U+1E32 . #\U+1E33)
+          (#\U+1E34 . #\U+1E35)
+          (#\U+1E36 . #\U+1E37)
+          
+          (#\U+1E38 . #\U+1E39)
+          (#\U+1E3A . #\U+1E3B)
+          (#\U+1E3C . #\U+1E3D)
+          
+          (#\U+1E3E . #\U+1E3F)
+          (#\U+1E40 . #\U+1E41)
+          (#\U+1E42 . #\U+1E43)
+          
+          (#\U+1E44 . #\U+1E45)
+          (#\U+1E46 . #\U+1E47)
+          (#\U+1E48 . #\U+1E49)
+          
+          (#\U+1E4A . #\U+1E4B)
+          (#\U+1E4C . #\U+1E4D)
+          (#\U+1E4E . #\U+1E4F)
+          
+          (#\U+1E50 . #\U+1E51)
+          (#\U+1E52 . #\U+1E53)
+          (#\U+1E54 . #\U+1E55)
+          
+          (#\U+1E56 . #\U+1E57)
+          (#\U+1E58 . #\U+1E59)
+          (#\U+1E5A . #\U+1E5B)
+          
+          (#\U+1E5C . #\U+1E5D)
+          (#\U+1E5E . #\U+1E5F)
+          (#\U+1E60 . #\U+1E61)
+          
+          (#\U+1E62 . #\U+1E63)
+          (#\U+1E64 . #\U+1E65)
+          (#\U+1E66 . #\U+1E67)
+          
+          (#\U+1E68 . #\U+1E69)
+          (#\U+1E6A . #\U+1E6B)
+          (#\U+1E6C . #\U+1E6D)
+          
+          (#\U+1E6E . #\U+1E6F)
+          (#\U+1E70 . #\U+1E71)
+          (#\U+1E72 . #\U+1E73)
+          
+          (#\U+1E74 . #\U+1E75)
+          (#\U+1E76 . #\U+1E77)
+          (#\U+1E78 . #\U+1E79)
+          
+          (#\U+1E7A . #\U+1E7B)
+          (#\U+1E7C . #\U+1E7D)
+          (#\U+1E7E . #\U+1E7F)
+          
+          (#\U+1E80 . #\U+1E81)
+          (#\U+1E82 . #\U+1E83)
+          (#\U+1E84 . #\U+1E85)
+          
+          (#\U+1E86 . #\U+1E87)
+          (#\U+1E88 . #\U+1E89)
+          (#\U+1E8A . #\U+1E8B)
+          
+          (#\U+1E8C . #\U+1E8D)
+          (#\U+1E8E . #\U+1E8F)
+          (#\U+1E90 . #\U+1E91)
+          
+          (#\U+1E92 . #\U+1E93)
+          (#\U+1E94 . #\U+1E95)
+          (#\U+1EA0 . #\U+1EA1)
+          
+          (#\U+1EA2 . #\U+1EA3)
+          (#\U+1EA4 . #\U+1EA5)
+          (#\U+1EA6 . #\U+1EA7)
+          
+          (#\U+1EA8 . #\U+1EA9)
+          (#\U+1EAA . #\U+1EAB)
+          (#\U+1EAC . #\U+1EAD)
+          
+          (#\U+1EAE . #\U+1EAF)
+          (#\U+1EB0 . #\U+1EB1)
+          (#\U+1EB2 . #\U+1EB3)
+          
+          (#\U+1EB4 . #\U+1EB5)
+          (#\U+1EB6 . #\U+1EB7)
+          (#\U+1EB8 . #\U+1EB9)
+          
+          (#\U+1EBA . #\U+1EBB)
+          (#\U+1EBC . #\U+1EBD)
+          (#\U+1EBE . #\U+1EBF)
+          
+          (#\U+1EC0 . #\U+1EC1)
+          (#\U+1EC2 . #\U+1EC3)
+          (#\U+1EC4 . #\U+1EC5)
+          
+          (#\U+1EC6 . #\U+1EC7)
+          (#\U+1EC8 . #\U+1EC9)
+          (#\U+1ECA . #\U+1ECB)
+          
+          (#\U+1ECC . #\U+1ECD)
+          (#\U+1ECE . #\U+1ECF)
+          (#\U+1ED0 . #\U+1ED1)
+          
+          (#\U+1ED2 . #\U+1ED3)
+          (#\U+1ED4 . #\U+1ED5)
+          (#\U+1ED6 . #\U+1ED7)
+          
+          (#\U+1ED8 . #\U+1ED9)
+          (#\U+1EDA . #\U+1EDB)
+          (#\U+1EDC . #\U+1EDD)
+          
+          (#\U+1EDE . #\U+1EDF)
+          (#\U+1EE0 . #\U+1EE1)
+          (#\U+1EE2 . #\U+1EE3)
+          
+          (#\U+1EE4 . #\U+1EE5)
+          (#\U+1EE6 . #\U+1EE7)
+          (#\U+1EE8 . #\U+1EE9)
+          
+          (#\U+1EEA . #\U+1EEB)
+          (#\U+1EEC . #\U+1EED)
+          (#\U+1EEE . #\U+1EEF)
+          
+          (#\U+1EF0 . #\U+1EF1)
+          (#\U+1EF2 . #\U+1EF3)
+          (#\U+1EF4 . #\U+1EF5)
+          
+          (#\U+1EF6 . #\U+1EF7)
+          (#\U+1EF8 . #\U+1EF9)
+          (#\U+1F08 . #\U+1F00)
+          
+          (#\U+1F09 . #\U+1F01)
+          (#\U+1F0A . #\U+1F02)
+          (#\U+1F0B . #\U+1F03)
+          
+          (#\U+1F0C . #\U+1F04)
+          (#\U+1F0D . #\U+1F05)
+          (#\U+1F0E . #\U+1F06)
+          
+          (#\U+1F0F . #\U+1F07)
+          (#\U+1F18 . #\U+1F10)
+          (#\U+1F19 . #\U+1F11)
+          
+          (#\U+1F1A . #\U+1F12)
+          (#\U+1F1B . #\U+1F13)
+          (#\U+1F1C . #\U+1F14)
+          
+          (#\U+1F1D . #\U+1F15)
+          (#\U+1F28 . #\U+1F20)
+          (#\U+1F29 . #\U+1F21)
+          
+          (#\U+1F2A . #\U+1F22)
+          (#\U+1F2B . #\U+1F23)
+          (#\U+1F2C . #\U+1F24)
+          
+          (#\U+1F2D . #\U+1F25)
+          (#\U+1F2E . #\U+1F26)
+          (#\U+1F2F . #\U+1F27)
+          
+          (#\U+1F38 . #\U+1F30)
+          (#\U+1F39 . #\U+1F31)
+          (#\U+1F3A . #\U+1F32)
+          
+          (#\U+1F3B . #\U+1F33)
+          (#\U+1F3C . #\U+1F34)
+          (#\U+1F3D . #\U+1F35)
+          
+          (#\U+1F3E . #\U+1F36)
+          (#\U+1F3F . #\U+1F37)
+          (#\U+1F48 . #\U+1F40)
+          
+          (#\U+1F49 . #\U+1F41)
+          (#\U+1F4A . #\U+1F42)
+          (#\U+1F4B . #\U+1F43)
+          
+          (#\U+1F4C . #\U+1F44)
+          (#\U+1F4D . #\U+1F45)
+          (#\U+1F59 . #\U+1F51)
+          
+          (#\U+1F5B . #\U+1F53)
+          (#\U+1F5D . #\U+1F55)
+          (#\U+1F5F . #\U+1F57)
+          
+          (#\U+1F68 . #\U+1F60)
+          (#\U+1F69 . #\U+1F61)
+          (#\U+1F6A . #\U+1F62)
+          
+          (#\U+1F6B . #\U+1F63)
+          (#\U+1F6C . #\U+1F64)
+          (#\U+1F6D . #\U+1F65)
+          
+          (#\U+1F6E . #\U+1F66)
+          (#\U+1F6F . #\U+1F67)
+          (#\U+1F88 . #\U+1F80)
+          
+          (#\U+1F89 . #\U+1F81)
+          (#\U+1F8A . #\U+1F82)
+          (#\U+1F8B . #\U+1F83)
+          
+          (#\U+1F8C . #\U+1F84)
+          (#\U+1F8D . #\U+1F85)
+          (#\U+1F8E . #\U+1F86)
+          
+          (#\U+1F8F . #\U+1F87)
+          (#\U+1F98 . #\U+1F90)
+          (#\U+1F99 . #\U+1F91)
+          
+          (#\U+1F9A . #\U+1F92)
+          (#\U+1F9B . #\U+1F93)
+          (#\U+1F9C . #\U+1F94)
+          
+          (#\U+1F9D . #\U+1F95)
+          (#\U+1F9E . #\U+1F96)
+          (#\U+1F9F . #\U+1F97)
+          
+          (#\U+1FA8 . #\U+1FA0)
+          (#\U+1FA9 . #\U+1FA1)
+          (#\U+1FAA . #\U+1FA2)
+          
+          (#\U+1FAB . #\U+1FA3)
+          (#\U+1FAC . #\U+1FA4)
+          (#\U+1FAD . #\U+1FA5)
+          
+          (#\U+1FAE . #\U+1FA6)
+          (#\U+1FAF . #\U+1FA7)
+          (#\U+1FB8 . #\U+1FB0)
+          
+          (#\U+1FB9 . #\U+1FB1)
+          (#\U+1FBA . #\U+1F70)
+          (#\U+1FBB . #\U+1F71)
+          
+          (#\U+1FBC . #\U+1FB3)
+          (#\U+1FC8 . #\U+1F72)
+          (#\U+1FC9 . #\U+1F73)
+          
+          (#\U+1FCA . #\U+1F74)
+          (#\U+1FCB . #\U+1F75)
+          (#\U+1FCC . #\U+1FC3)
+          
+          (#\U+1FD8 . #\U+1FD0)
+          (#\U+1FD9 . #\U+1FD1)
+          (#\U+1FDA . #\U+1F76)
+          
+          (#\U+1FDB . #\U+1F77)
+          (#\U+1FE8 . #\U+1FE0)
+          (#\U+1FE9 . #\U+1FE1)
+          
+          (#\U+1FEA . #\U+1F7A)
+          (#\U+1FEB . #\U+1F7B)
+          (#\U+1FEC . #\U+1FE5)
+          
+          (#\U+1FF8 . #\U+1F78)
+          (#\U+1FF9 . #\U+1F79)
+          (#\U+1FFA . #\U+1F7C)
+          
+          (#\U+1FFB . #\U+1F7D)
+          (#\U+1FFC . #\U+1FF3)
+          (#\U+2132 . #\U+214E)
+          
+          (#\U+2160 . #\U+2170)
+          (#\U+2161 . #\U+2171)
+          (#\U+2162 . #\U+2172)
+          
+          (#\U+2163 . #\U+2173)
+          (#\U+2164 . #\U+2174)
+          (#\U+2165 . #\U+2175)
+          
+          (#\U+2166 . #\U+2176)
+          (#\U+2167 . #\U+2177)
+          (#\U+2168 . #\U+2178)
+          
+          (#\U+2169 . #\U+2179)
+          (#\U+216A . #\U+217A)
+          (#\U+216B . #\U+217B)
+          
+          (#\U+216C . #\U+217C)
+          (#\U+216D . #\U+217D)
+          (#\U+216E . #\U+217E)
+          
+          (#\U+216F . #\U+217F)
+          (#\U+2183 . #\U+2184)
+          (#\U+24B6 . #\U+24D0)
+          
+          (#\U+24B7 . #\U+24D1)
+          (#\U+24B8 . #\U+24D2)
+          (#\U+24B9 . #\U+24D3)
+          
+          (#\U+24BA . #\U+24D4)
+          (#\U+24BB . #\U+24D5)
+          (#\U+24BC . #\U+24D6)
+          
+          (#\U+24BD . #\U+24D7)
+          (#\U+24BE . #\U+24D8)
+          (#\U+24BF . #\U+24D9)
+          
+          (#\U+24C0 . #\U+24DA)
+          (#\U+24C1 . #\U+24DB)
+          (#\U+24C2 . #\U+24DC)
+          
+          (#\U+24C3 . #\U+24DD)
+          (#\U+24C4 . #\U+24DE)
+          (#\U+24C5 . #\U+24DF)
+          
+          (#\U+24C6 . #\U+24E0)
+          (#\U+24C7 . #\U+24E1)
+          (#\U+24C8 . #\U+24E2)
+          
+          (#\U+24C9 . #\U+24E3)
+          (#\U+24CA . #\U+24E4)
+          (#\U+24CB . #\U+24E5)
+          
+          (#\U+24CC . #\U+24E6)
+          (#\U+24CD . #\U+24E7)
+          (#\U+24CE . #\U+24E8)
+          
+          (#\U+24CF . #\U+24E9)
+          (#\U+2C00 . #\U+2C30)
+          (#\U+2C01 . #\U+2C31)
+          
+          (#\U+2C02 . #\U+2C32)
+          (#\U+2C03 . #\U+2C33)
+          (#\U+2C04 . #\U+2C34)
+          
+          (#\U+2C05 . #\U+2C35)
+          (#\U+2C06 . #\U+2C36)
+          (#\U+2C07 . #\U+2C37)
+          
+          (#\U+2C08 . #\U+2C38)
+          (#\U+2C09 . #\U+2C39)
+          (#\U+2C0A . #\U+2C3A)
+          
+          (#\U+2C0B . #\U+2C3B)
+          (#\U+2C0C . #\U+2C3C)
+          (#\U+2C0D . #\U+2C3D)
+          
+          (#\U+2C0E . #\U+2C3E)
+          (#\U+2C0F . #\U+2C3F)
+          (#\U+2C10 . #\U+2C40)
+          
+          (#\U+2C11 . #\U+2C41)
+          (#\U+2C12 . #\U+2C42)
+          (#\U+2C13 . #\U+2C43)
+          
+          (#\U+2C14 . #\U+2C44)
+          (#\U+2C15 . #\U+2C45)
+          (#\U+2C16 . #\U+2C46)
+          
+          (#\U+2C17 . #\U+2C47)
+          (#\U+2C18 . #\U+2C48)
+          (#\U+2C19 . #\U+2C49)
+          
+          (#\U+2C1A . #\U+2C4A)
+          (#\U+2C1B . #\U+2C4B)
+          (#\U+2C1C . #\U+2C4C)
+          
+          (#\U+2C1D . #\U+2C4D)
+          (#\U+2C1E . #\U+2C4E)
+          (#\U+2C1F . #\U+2C4F)
+          
+          (#\U+2C20 . #\U+2C50)
+          (#\U+2C21 . #\U+2C51)
+          (#\U+2C22 . #\U+2C52)
+          
+          (#\U+2C23 . #\U+2C53)
+          (#\U+2C24 . #\U+2C54)
+          (#\U+2C25 . #\U+2C55)
+          
+          (#\U+2C26 . #\U+2C56)
+          (#\U+2C27 . #\U+2C57)
+          (#\U+2C28 . #\U+2C58)
+          
+          (#\U+2C29 . #\U+2C59)
+          (#\U+2C2A . #\U+2C5A)
+          (#\U+2C2B . #\U+2C5B)
+          
+          (#\U+2C2C . #\U+2C5C)
+          (#\U+2C2D . #\U+2C5D)
+          (#\U+2C2E . #\U+2C5E)
+          
+          (#\U+2C60 . #\U+2C61)
+          (#\U+2C62 . #\Latin_Small_Letter_L_With_Middle_Tilde)
+          
+          (#\U+2C63 . #\U+1D7D)
+          (#\U+2C64 . #\Latin_Small_Letter_R_With_Tail)
+          
+          (#\U+2C67 . #\U+2C68)
+          (#\U+2C69 . #\U+2C6A)
+          (#\U+2C6B . #\U+2C6C)
+          
+          (#\U+2C75 . #\U+2C76)
+          (#\U+2C80 . #\U+2C81)
+          (#\U+2C82 . #\U+2C83)
+          
+          (#\U+2C84 . #\U+2C85)
+          (#\U+2C86 . #\U+2C87)
+          (#\U+2C88 . #\U+2C89)
+          
+          (#\U+2C8A . #\U+2C8B)
+          (#\U+2C8C . #\U+2C8D)
+          (#\U+2C8E . #\U+2C8F)
+          
+          (#\U+2C90 . #\U+2C91)
+          (#\U+2C92 . #\U+2C93)
+          (#\U+2C94 . #\U+2C95)
+          
+          (#\U+2C96 . #\U+2C97)
+          (#\U+2C98 . #\U+2C99)
+          (#\U+2C9A . #\U+2C9B)
+          
+          (#\U+2C9C . #\U+2C9D)
+          (#\U+2C9E . #\U+2C9F)
+          (#\U+2CA0 . #\U+2CA1)
+          
+          (#\U+2CA2 . #\U+2CA3)
+          (#\U+2CA4 . #\U+2CA5)
+          (#\U+2CA6 . #\U+2CA7)
+          
+          (#\U+2CA8 . #\U+2CA9)
+          (#\U+2CAA . #\U+2CAB)
+          (#\U+2CAC . #\U+2CAD)
+          
+          (#\U+2CAE . #\U+2CAF)
+          (#\U+2CB0 . #\U+2CB1)
+          (#\U+2CB2 . #\U+2CB3)
+          
+          (#\U+2CB4 . #\U+2CB5)
+          (#\U+2CB6 . #\U+2CB7)
+          (#\U+2CB8 . #\U+2CB9)
+          
+          (#\U+2CBA . #\U+2CBB)
+          (#\U+2CBC . #\U+2CBD)
+          (#\U+2CBE . #\U+2CBF)
+          
+          (#\U+2CC0 . #\U+2CC1)
+          (#\U+2CC2 . #\U+2CC3)
+          (#\U+2CC4 . #\U+2CC5)
+          
+          (#\U+2CC6 . #\U+2CC7)
+          (#\U+2CC8 . #\U+2CC9)
+          (#\U+2CCA . #\U+2CCB)
+          
+          (#\U+2CCC . #\U+2CCD)
+          (#\U+2CCE . #\U+2CCF)
+          (#\U+2CD0 . #\U+2CD1)
+          
+          (#\U+2CD2 . #\U+2CD3)
+          (#\U+2CD4 . #\U+2CD5)
+          (#\U+2CD6 . #\U+2CD7)
+          
+          (#\U+2CD8 . #\U+2CD9)
+          (#\U+2CDA . #\U+2CDB)
+          (#\U+2CDC . #\U+2CDD)
+          
+          (#\U+2CDE . #\U+2CDF)
+          (#\U+2CE0 . #\U+2CE1)
+          (#\U+2CE2 . #\U+2CE3)
+          
+          (#\U+FF21 . #\U+FF41)
+          (#\U+FF22 . #\U+FF42)
+          (#\U+FF23 . #\U+FF43)
+          
+          (#\U+FF24 . #\U+FF44)
+          (#\U+FF25 . #\U+FF45)
+          (#\U+FF26 . #\U+FF46)
+          
+          (#\U+FF27 . #\U+FF47)
+          (#\U+FF28 . #\U+FF48)
+          (#\U+FF29 . #\U+FF49)
+          
+          (#\U+FF2A . #\U+FF4A)
+          (#\U+FF2B . #\U+FF4B)
+          (#\U+FF2C . #\U+FF4C)
+          
+          (#\U+FF2D . #\U+FF4D)
+          (#\U+FF2E . #\U+FF4E)
+          (#\U+FF2F . #\U+FF4F)
+          
+          (#\U+FF30 . #\U+FF50)
+          (#\U+FF31 . #\U+FF51)
+          (#\U+FF32 . #\U+FF52)
+          
+          (#\U+FF33 . #\U+FF53)
+          (#\U+FF34 . #\U+FF54)
+          (#\U+FF35 . #\U+FF55)
+          
+          (#\U+FF36 . #\U+FF56)
+          (#\U+FF37 . #\U+FF57)
+          (#\U+FF38 . #\U+FF58)
+          
+          (#\U+FF39 . #\U+FF59)
+          (#\U+FF3A . #\U+FF5A)
+          (#\U+10400 . #\U+10428)
+          
+          (#\U+10401 . #\U+10429)
+          (#\U+10402 . #\U+1042A)
+          (#\U+10403 . #\U+1042B)
+          
+          (#\U+10404 . #\U+1042C)
+          (#\U+10405 . #\U+1042D)
+          (#\U+10406 . #\U+1042E)
+          
+          (#\U+10407 . #\U+1042F)
+          (#\U+10408 . #\U+10430)
+          (#\U+10409 . #\U+10431)
+          
+          (#\U+1040A . #\U+10432)
+          (#\U+1040B . #\U+10433)
+          (#\U+1040C . #\U+10434)
+          
+          (#\U+1040D . #\U+10435)
+          (#\U+1040E . #\U+10436)
+          (#\U+1040F . #\U+10437)
+          
+          (#\U+10410 . #\U+10438)
+          (#\U+10411 . #\U+10439)
+          (#\U+10412 . #\U+1043A)
+          
+          (#\U+10413 . #\U+1043B)
+          (#\U+10414 . #\U+1043C)
+          (#\U+10415 . #\U+1043D)
+          
+          (#\U+10416 . #\U+1043E)
+          (#\U+10417 . #\U+1043F)
+          (#\U+10418 . #\U+10440)
+          
+          (#\U+10419 . #\U+10441)
+          (#\U+1041A . #\U+10442)
+          (#\U+1041B . #\U+10443)
+          
+          (#\U+1041C . #\U+10444)
+          (#\U+1041D . #\U+10445)
+          (#\U+1041E . #\U+10446)
+          
+          (#\U+1041F . #\U+10447)
+          (#\U+10420 . #\U+10448)
+          (#\U+10421 . #\U+10449)
+          
+          (#\U+10422 . #\U+1044A)
+          (#\U+10423 . #\U+1044B)
+          (#\U+10424 . #\U+1044C)
+          
+          (#\U+10425 . #\U+1044D)
+          (#\U+10426 . #\U+1044E)
+          (#\U+10427 . #\U+1044F)
+          ))
+       (max-upper #\u+0000)
+       (max-lower #\u+0000))
+  (declare (optimize speed)) ;; make sure everything gets inlined that needs to be.
+  (dolist (pair mapping)
+    (destructuring-bind (upper . lower) pair
+      (when (char> upper max-upper)
+        (setq max-upper upper))
+      (when (char> lower max-lower)
+        (setq max-lower lower))))
+  (let* ((upper-to-lower (make-array (the fixnum (1+ (the fixnum (char-code max-upper)))) :element-type '(signed-byte 16)))
+         (lower-to-upper (make-array (the fixnum (1+ (the fixnum (char-code max-lower)))) :element-type '(signed-byte 16))))
+    (dolist (pair mapping)
+      (destructuring-bind (upper . lower) pair
+        (let* ((upper-code (char-code upper))
+               (lower-code (char-code lower))
+               (diff (- lower-code upper-code)))
+          (declare (type (mod #x110000) upper-code lower-code)
+                   (type (signed-byte 16) diff))
+          (setf (aref upper-to-lower upper-code) diff
+                (aref lower-to-upper lower-code) (the fixnum (- diff))))))
+    (do* ((upper (char-code #\A) (1+ upper))
+          (lower (char-code #\a) (1+ lower)))
+         ((> upper (char-code #\Z)))
+      (setf (aref upper-to-lower upper) (- lower upper)
+            (aref lower-to-upper lower) (- upper lower)))
+    (setq *lower-to-upper* lower-to-upper
+          *upper-to-lower* upper-to-lower)
+    nil))
+
+(eval-when (:compile-toplevel)
+  (declaim (inline %char-code-case-fold)))
+
+(defun %char-code-case-fold (code table)
+  (declare (type (mod #x110000) code)
+           (type (simple-array (signed-byte 16) (*)) table))
+  (if (>= code (length table))
+    code
+    (locally (declare (optimize (speed 3) (safety 0)))
+      (the fixnum (+ code (the (signed-byte 16) (aref table code)))))))
+
+(defun %char-code-upcase (code)
+  (%char-code-case-fold code *lower-to-upper*))
+
+(defun char-upcase (c)
+  "Return CHAR converted to upper-case if that is possible.  Don't convert
+   lowercase eszet (U+DF)."
+  (declare (optimize speed))            ; so that %char-code-case-fold inlines
+  (code-char (the valid-char-code (%char-code-case-fold (char-code c) *lower-to-upper*))))
+
+
+
+
+(defun %char-code-downcase (code)
+  (declare (type (mod #x110000) code))
+  (let* ((table *upper-to-lower*))
+    (declare (type (simple-array (signed-byte 16) (*)) table))
+    (if (>= code (length table))
+      code
+      (locally (declare (optimize (speed 3) (safety 0)))
+        (the fixnum (+ code (the (signed-byte 16) (aref table code))))))))
+
+
+;;;True for a-z, and maybe other things.
+(defun lower-case-p (c)
+  "The argument must be a character object; LOWER-CASE-P returns T if the
+   argument is a lower-case character, NIL otherwise."
+  (let* ((code (char-code c))
+         (table *lower-to-upper*))
+    (declare (type (mod #x110000) code)
+             (type (simple-array (signed-byte 16) (*)) table))
+    (if (< code (length table))
+      (not (eql 0 (the (signed-byte 16) (aref table code)))))))
+
+
+
+(defstatic *alpha-char-bits*
+  (let* ((bits (make-array #x2fa1e :element-type 'bit)))
+    (declare (optimize speed)) ;; make sure everything gets inlined that needs to be.
+    (dolist (range '((#x0041 . #x005A)
+                     (#x0061 . #x007A)
+                     #x00AA
+                     #x00B5
+                     #x00BA
+                     (#x00C0 . #x00D6)
+                     (#x00D8 . #x00F6)
+                     (#x00F8 . #x01BA)
+                     #x01BB
+                     (#x01BC . #x01BF)
+                     (#x01C0 . #x01C3)
+                     (#x01C4 . #x0293)
+                     #x0294
+                     (#x0295 . #x02AF)
+                     (#x02B0 . #x02C1)
+                     (#x02C6 . #x02D1)
+                     (#x02E0 . #x02E4)
+                     #x02EC
+                     #x02EE
+                     #x0345
+                     (#x0370 . #x0373)
+                     #x0374
+                     (#x0376 . #x0377)
+                     #x037A
+                     (#x037B . #x037D)
+                     #x0386
+                     (#x0388 . #x038A)
+                     #x038C
+                     (#x038E . #x03A1)
+                     (#x03A3 . #x03F5)
+                     (#x03F7 . #x0481)
+                     (#x048A . #x0523)
+                     (#x0531 . #x0556)
+                     #x0559
+                     (#x0561 . #x0587)
+                     (#x05B0 . #x05BD)
+                     #x05BF
+                     (#x05C1 . #x05C2)
+                     (#x05C4 . #x05C5)
+                     #x05C7
+                     (#x05D0 . #x05EA)
+                     (#x05F0 . #x05F2)
+                     (#x0610 . #x061A)
+                     (#x0621 . #x063F)
+                     #x0640
+                     (#x0641 . #x064A)
+                     (#x064B . #x0657)
+                     (#x0659 . #x065E)
+                     (#x066E . #x066F)
+                     #x0670
+                     (#x0671 . #x06D3)
+                     #x06D5
+                     (#x06D6 . #x06DC)
+                     (#x06E1 . #x06E4)
+                     (#x06E5 . #x06E6)
+                     (#x06E7 . #x06E8)
+                     #x06ED
+                     (#x06EE . #x06EF)
+                     (#x06FA . #x06FC)
+                     #x06FF
+                     #x0710
+                     #x0711
+                     (#x0712 . #x072F)
+                     (#x0730 . #x073F)
+                     (#x074D . #x07A5)
+                     (#x07A6 . #x07B0)
+                     #x07B1
+                     (#x07CA . #x07EA)
+                     (#x07F4 . #x07F5)
+                     #x07FA
+                     (#x0901 . #x0902)
+                     #x0903
+                     (#x0904 . #x0939)
+                     #x093D
+                     (#x093E . #x0940)
+                     (#x0941 . #x0948)
+                     (#x0949 . #x094C)
+                     #x0950
+                     (#x0958 . #x0961)
+                     (#x0962 . #x0963)
+                     #x0971
+                     #x0972
+                     (#x097B . #x097F)
+                     #x0981
+                     (#x0982 . #x0983)
+                     (#x0985 . #x098C)
+                     (#x098F . #x0990)
+                     (#x0993 . #x09A8)
+                     (#x09AA . #x09B0)
+                     #x09B2
+                     (#x09B6 . #x09B9)
+                     #x09BD
+                     (#x09BE . #x09C0)
+                     (#x09C1 . #x09C4)
+                     (#x09C7 . #x09C8)
+                     (#x09CB . #x09CC)
+                     #x09CE
+                     #x09D7
+                     (#x09DC . #x09DD)
+                     (#x09DF . #x09E1)
+                     (#x09E2 . #x09E3)
+                     (#x09F0 . #x09F1)
+                     (#x0A01 . #x0A02)
+                     #x0A03
+                     (#x0A05 . #x0A0A)
+                     (#x0A0F . #x0A10)
+                     (#x0A13 . #x0A28)
+                     (#x0A2A . #x0A30)
+                     (#x0A32 . #x0A33)
+                     (#x0A35 . #x0A36)
+                     (#x0A38 . #x0A39)
+                     (#x0A3E . #x0A40)
+                     (#x0A41 . #x0A42)
+                     (#x0A47 . #x0A48)
+                     (#x0A4B . #x0A4C)
+                     #x0A51
+                     (#x0A59 . #x0A5C)
+                     #x0A5E
+                     (#x0A70 . #x0A71)
+                     (#x0A72 . #x0A74)
+                     #x0A75
+                     (#x0A81 . #x0A82)
+                     #x0A83
+                     (#x0A85 . #x0A8D)
+                     (#x0A8F . #x0A91)
+                     (#x0A93 . #x0AA8)
+                     (#x0AAA . #x0AB0)
+                     (#x0AB2 . #x0AB3)
+                     (#x0AB5 . #x0AB9)
+                     #x0ABD
+                     (#x0ABE . #x0AC0)
+                     (#x0AC1 . #x0AC5)
+                     (#x0AC7 . #x0AC8)
+                     #x0AC9
+                     (#x0ACB . #x0ACC)
+                     #x0AD0
+                     (#x0AE0 . #x0AE1)
+                     (#x0AE2 . #x0AE3)
+                     #x0B01
+                     (#x0B02 . #x0B03)
+                     (#x0B05 . #x0B0C)
+                     (#x0B0F . #x0B10)
+                     (#x0B13 . #x0B28)
+                     (#x0B2A . #x0B30)
+                     (#x0B32 . #x0B33)
+                     (#x0B35 . #x0B39)
+                     #x0B3D
+                     #x0B3E
+                     #x0B3F
+                     #x0B40
+                     (#x0B41 . #x0B44)
+                     (#x0B47 . #x0B48)
+                     (#x0B4B . #x0B4C)
+                     #x0B56
+                     #x0B57
+                     (#x0B5C . #x0B5D)
+                     (#x0B5F . #x0B61)
+                     (#x0B62 . #x0B63)
+                     #x0B71
+                     #x0B82
+                     #x0B83
+                     (#x0B85 . #x0B8A)
+                     (#x0B8E . #x0B90)
+                     (#x0B92 . #x0B95)
+                     (#x0B99 . #x0B9A)
+                     #x0B9C
+                     (#x0B9E . #x0B9F)
+                     (#x0BA3 . #x0BA4)
+                     (#x0BA8 . #x0BAA)
+                     (#x0BAE . #x0BB9)
+                     (#x0BBE . #x0BBF)
+                     #x0BC0
+                     (#x0BC1 . #x0BC2)
+                     (#x0BC6 . #x0BC8)
+                     (#x0BCA . #x0BCC)
+                     #x0BD0
+                     #x0BD7
+                     (#x0C01 . #x0C03)
+                     (#x0C05 . #x0C0C)
+                     (#x0C0E . #x0C10)
+                     (#x0C12 . #x0C28)
+                     (#x0C2A . #x0C33)
+                     (#x0C35 . #x0C39)
+                     #x0C3D
+                     (#x0C3E . #x0C40)
+                     (#x0C41 . #x0C44)
+                     (#x0C46 . #x0C48)
+                     (#x0C4A . #x0C4C)
+                     (#x0C55 . #x0C56)
+                     (#x0C58 . #x0C59)
+                     (#x0C60 . #x0C61)
+                     (#x0C62 . #x0C63)
+                     (#x0C82 . #x0C83)
+                     (#x0C85 . #x0C8C)
+                     (#x0C8E . #x0C90)
+                     (#x0C92 . #x0CA8)
+                     (#x0CAA . #x0CB3)
+                     (#x0CB5 . #x0CB9)
+                     #x0CBD
+                     #x0CBE
+                     #x0CBF
+                     (#x0CC0 . #x0CC4)
+                     #x0CC6
+                     (#x0CC7 . #x0CC8)
+                     (#x0CCA . #x0CCB)
+                     #x0CCC
+                     (#x0CD5 . #x0CD6)
+                     #x0CDE
+                     (#x0CE0 . #x0CE1)
+                     (#x0CE2 . #x0CE3)
+                     (#x0D02 . #x0D03)
+                     (#x0D05 . #x0D0C)
+                     (#x0D0E . #x0D10)
+                     (#x0D12 . #x0D28)
+                     (#x0D2A . #x0D39)
+                     #x0D3D
+                     (#x0D3E . #x0D40)
+                     (#x0D41 . #x0D44)
+                     (#x0D46 . #x0D48)
+                     (#x0D4A . #x0D4C)
+                     #x0D57
+                     (#x0D60 . #x0D61)
+                     (#x0D62 . #x0D63)
+                     (#x0D7A . #x0D7F)
+                     (#x0D82 . #x0D83)
+                     (#x0D85 . #x0D96)
+                     (#x0D9A . #x0DB1)
+                     (#x0DB3 . #x0DBB)
+                     #x0DBD
+                     (#x0DC0 . #x0DC6)
+                     (#x0DCF . #x0DD1)
+                     (#x0DD2 . #x0DD4)
+                     #x0DD6
+                     (#x0DD8 . #x0DDF)
+                     (#x0DF2 . #x0DF3)
+                     (#x0E01 . #x0E30)
+                     #x0E31
+                     (#x0E32 . #x0E33)
+                     (#x0E34 . #x0E3A)
+                     (#x0E40 . #x0E45)
+                     #x0E46
+                     #x0E4D
+                     (#x0E81 . #x0E82)
+                     #x0E84
+                     (#x0E87 . #x0E88)
+                     #x0E8A
+                     #x0E8D
+                     (#x0E94 . #x0E97)
+                     (#x0E99 . #x0E9F)
+                     (#x0EA1 . #x0EA3)
+                     #x0EA5
+                     #x0EA7
+                     (#x0EAA . #x0EAB)
+                     (#x0EAD . #x0EB0)
+                     #x0EB1
+                     (#x0EB2 . #x0EB3)
+                     (#x0EB4 . #x0EB9)
+                     (#x0EBB . #x0EBC)
+                     #x0EBD
+                     (#x0EC0 . #x0EC4)
+                     #x0EC6
+                     #x0ECD
+                     (#x0EDC . #x0EDD)
+                     #x0F00
+                     (#x0F40 . #x0F47)
+                     (#x0F49 . #x0F6C)
+                     (#x0F71 . #x0F7E)
+                     #x0F7F
+                     (#x0F80 . #x0F81)
+                     (#x0F88 . #x0F8B)
+                     (#x0F90 . #x0F97)
+                     (#x0F99 . #x0FBC)
+                     (#x1000 . #x102A)
+                     (#x102B . #x102C)
+                     (#x102D . #x1030)
+                     #x1031
+                     (#x1032 . #x1036)
+                     #x1038
+                     (#x103B . #x103C)
+                     (#x103D . #x103E)
+                     #x103F
+                     (#x1050 . #x1055)
+                     (#x1056 . #x1057)
+                     (#x1058 . #x1059)
+                     (#x105A . #x105D)
+                     (#x105E . #x1060)
+                     #x1061
+                     #x1062
+                     (#x1065 . #x1066)
+                     (#x1067 . #x1068)
+                     (#x106E . #x1070)
+                     (#x1071 . #x1074)
+                     (#x1075 . #x1081)
+                     #x1082
+                     (#x1083 . #x1084)
+                     (#x1085 . #x1086)
+                     #x108E
+                     (#x10A0 . #x10C5)
+                     (#x10D0 . #x10FA)
+                     #x10FC
+                     (#x1100 . #x1159)
+                     (#x115F . #x11A2)
+                     (#x11A8 . #x11F9)
+                     (#x1200 . #x1248)
+                     (#x124A . #x124D)
+                     (#x1250 . #x1256)
+                     #x1258
+                     (#x125A . #x125D)
+                     (#x1260 . #x1288)
+                     (#x128A . #x128D)
+                     (#x1290 . #x12B0)
+                     (#x12B2 . #x12B5)
+                     (#x12B8 . #x12BE)
+                     #x12C0
+                     (#x12C2 . #x12C5)
+                     (#x12C8 . #x12D6)
+                     (#x12D8 . #x1310)
+                     (#x1312 . #x1315)
+                     (#x1318 . #x135A)
+                     #x135F
+                     (#x1380 . #x138F)
+                     (#x13A0 . #x13F4)
+                     (#x1401 . #x166C)
+                     (#x166F . #x1676)
+                     (#x1681 . #x169A)
+                     (#x16A0 . #x16EA)
+                     (#x16EE . #x16F0)
+                     (#x1700 . #x170C)
+                     (#x170E . #x1711)
+                     (#x1712 . #x1713)
+                     (#x1720 . #x1731)
+                     (#x1732 . #x1733)
+                     (#x1740 . #x1751)
+                     (#x1752 . #x1753)
+                     (#x1760 . #x176C)
+                     (#x176E . #x1770)
+                     (#x1772 . #x1773)
+                     (#x1780 . #x17B3)
+                     #x17B6
+                     (#x17B7 . #x17BD)
+                     (#x17BE . #x17C5)
+                     #x17C6
+                     (#x17C7 . #x17C8)
+                     #x17D7
+                     #x17DC
+                     (#x1820 . #x1842)
+                     #x1843
+                     (#x1844 . #x1877)
+                     (#x1880 . #x18A8)
+                     #x18A9
+                     #x18AA
+                     (#x1900 . #x191C)
+                     (#x1920 . #x1922)
+                     (#x1923 . #x1926)
+                     (#x1927 . #x1928)
+                     (#x1929 . #x192B)
+                     (#x1930 . #x1931)
+                     #x1932
+                     (#x1933 . #x1938)
+                     (#x1950 . #x196D)
+                     (#x1970 . #x1974)
+                     (#x1980 . #x19A9)
+                     (#x19B0 . #x19C0)
+                     (#x19C1 . #x19C7)
+                     (#x19C8 . #x19C9)
+                     (#x1A00 . #x1A16)
+                     (#x1A17 . #x1A18)
+                     (#x1A19 . #x1A1B)
+                     (#x1B00 . #x1B03)
+                     #x1B04
+                     (#x1B05 . #x1B33)
+                     #x1B35
+                     (#x1B36 . #x1B3A)
+                     #x1B3B
+                     #x1B3C
+                     (#x1B3D . #x1B41)
+                     #x1B42
+                     #x1B43
+                     (#x1B45 . #x1B4B)
+                     (#x1B80 . #x1B81)
+                     #x1B82
+                     (#x1B83 . #x1BA0)
+                     #x1BA1
+                     (#x1BA2 . #x1BA5)
+                     (#x1BA6 . #x1BA7)
+                     (#x1BA8 . #x1BA9)
+                     (#x1BAE . #x1BAF)
+                     (#x1C00 . #x1C23)
+                     (#x1C24 . #x1C2B)
+                     (#x1C2C . #x1C33)
+                     (#x1C34 . #x1C35)
+                     (#x1C4D . #x1C4F)
+                     (#x1C5A . #x1C77)
+                     (#x1C78 . #x1C7D)
+                     (#x1D00 . #x1D2B)
+                     (#x1D2C . #x1D61)
+                     (#x1D62 . #x1D77)
+                     #x1D78
+                     (#x1D79 . #x1D9A)
+                     (#x1D9B . #x1DBF)
+                     (#x1E00 . #x1F15)
+                     (#x1F18 . #x1F1D)
+                     (#x1F20 . #x1F45)
+                     (#x1F48 . #x1F4D)
+                     (#x1F50 . #x1F57)
+                     #x1F59
+                     #x1F5B
+                     #x1F5D
+                     (#x1F5F . #x1F7D)
+                     (#x1F80 . #x1FB4)
+                     (#x1FB6 . #x1FBC)
+                     #x1FBE
+                     (#x1FC2 . #x1FC4)
+                     (#x1FC6 . #x1FCC)
+                     (#x1FD0 . #x1FD3)
+                     (#x1FD6 . #x1FDB)
+                     (#x1FE0 . #x1FEC)
+                     (#x1FF2 . #x1FF4)
+                     (#x1FF6 . #x1FFC)
+                     #x2071
+                     #x207F
+                     (#x2090 . #x2094)
+                     #x2102
+                     #x2107
+                     (#x210A . #x2113)
+                     #x2115
+                     (#x2119 . #x211D)
+                     #x2124
+                     #x2126
+                     #x2128
+                     (#x212A . #x212D)
+                     (#x212F . #x2134)
+                     (#x2135 . #x2138)
+                     #x2139
+                     (#x213C . #x213F)
+                     (#x2145 . #x2149)
+                     #x214E
+                     (#x2160 . #x2182)
+                     (#x2183 . #x2184)
+                     (#x2185 . #x2188)
+                     (#x24B6 . #x24E9)
+                     (#x2C00 . #x2C2E)
+                     (#x2C30 . #x2C5E)
+                     (#x2C60 . #x2C6F)
+                     (#x2C71 . #x2C7C)
+                     #x2C7D
+                     (#x2C80 . #x2CE4)
+                     (#x2D00 . #x2D25)
+                     (#x2D30 . #x2D65)
+                     #x2D6F
+                     (#x2D80 . #x2D96)
+                     (#x2DA0 . #x2DA6)
+                     (#x2DA8 . #x2DAE)
+                     (#x2DB0 . #x2DB6)
+                     (#x2DB8 . #x2DBE)
+                     (#x2DC0 . #x2DC6)
+                     (#x2DC8 . #x2DCE)
+                     (#x2DD0 . #x2DD6)
+                     (#x2DD8 . #x2DDE)
+                     (#x2DE0 . #x2DFF)
+                     #x2E2F
+                     #x3005
+                     #x3006
+                     #x3007
+                     (#x3021 . #x3029)
+                     (#x3031 . #x3035)
+                     (#x3038 . #x303A)
+                     #x303B
+                     #x303C
+                     (#x3041 . #x3096)
+                     (#x309D . #x309E)
+                     #x309F
+                     (#x30A1 . #x30FA)
+                     (#x30FC . #x30FE)
+                     #x30FF
+                     (#x3105 . #x312D)
+                     (#x3131 . #x318E)
+                     (#x31A0 . #x31B7)
+                     (#x31F0 . #x31FF)
+                     (#x3400 . #x4DB5)
+                     (#x4E00 . #x9FC3)
+                     (#xA000 . #xA014)
+                     #xA015
+                     (#xA016 . #xA48C)
+                     (#xA500 . #xA60B)
+                     #xA60C
+                     (#xA610 . #xA61F)
+                     (#xA62A . #xA62B)
+                     (#xA640 . #xA65F)
+                     (#xA662 . #xA66D)
+                     #xA66E
+                     #xA67F
+                     (#xA680 . #xA697)
+                     (#xA717 . #xA71F)
+                     (#xA722 . #xA76F)
+                     #xA770
+                     (#xA771 . #xA787)
+                     #xA788
+                     (#xA78B . #xA78C)
+                     (#xA7FB . #xA801)
+                     (#xA803 . #xA805)
+                     (#xA807 . #xA80A)
+                     (#xA80C . #xA822)
+                     (#xA823 . #xA824)
+                     (#xA825 . #xA826)
+                     #xA827
+                     (#xA840 . #xA873)
+                     (#xA880 . #xA881)
+                     (#xA882 . #xA8B3)
+                     (#xA8B4 . #xA8C3)
+                     (#xA90A . #xA925)
+                     (#xA926 . #xA92A)
+                     (#xA930 . #xA946)
+                     (#xA947 . #xA951)
+                     #xA952
+                     (#xAA00 . #xAA28)
+                     (#xAA29 . #xAA2E)
+                     (#xAA2F . #xAA30)
+                     (#xAA31 . #xAA32)
+                     (#xAA33 . #xAA34)
+                     (#xAA35 . #xAA36)
+                     (#xAA40 . #xAA42)
+                     #xAA43
+                     (#xAA44 . #xAA4B)
+                     #xAA4C
+                     #xAA4D
+                     (#xAC00 . #xD7A3)
+                     (#xF900 . #xFA2D)
+                     (#xFA30 . #xFA6A)
+                     (#xFA70 . #xFAD9)
+                     (#xFB00 . #xFB06)
+                     (#xFB13 . #xFB17)
+                     #xFB1D
+                     #xFB1E
+                     (#xFB1F . #xFB28)
+                     (#xFB2A . #xFB36)
+                     (#xFB38 . #xFB3C)
+                     #xFB3E
+                     (#xFB40 . #xFB41)
+                     (#xFB43 . #xFB44)
+                     (#xFB46 . #xFBB1)
+                     (#xFBD3 . #xFD3D)
+                     (#xFD50 . #xFD8F)
+                     (#xFD92 . #xFDC7)
+                     (#xFDF0 . #xFDFB)
+                     (#xFE70 . #xFE74)
+                     (#xFE76 . #xFEFC)
+                     (#xFF21 . #xFF3A)
+                     (#xFF41 . #xFF5A)
+                     (#xFF66 . #xFF6F)
+                     #xFF70
+                     (#xFF71 . #xFF9D)
+                     (#xFF9E . #xFF9F)
+                     (#xFFA0 . #xFFBE)
+                     (#xFFC2 . #xFFC7)
+                     (#xFFCA . #xFFCF)
+                     (#xFFD2 . #xFFD7)
+                     (#xFFDA . #xFFDC)
+                     (#x10000 . #x1000B)
+                     (#x1000D . #x10026)
+                     (#x10028 . #x1003A)
+                     (#x1003C . #x1003D)
+                     (#x1003F . #x1004D)
+                     (#x10050 . #x1005D)
+                     (#x10080 . #x100FA)
+                     (#x10140 . #x10174)
+                     (#x10280 . #x1029C)
+                     (#x102A0 . #x102D0)
+                     (#x10300 . #x1031E)
+                     (#x10330 . #x10340)
+                     #x10341
+                     (#x10342 . #x10349)
+                     #x1034A
+                     (#x10380 . #x1039D)
+                     (#x103A0 . #x103C3)
+                     (#x103C8 . #x103CF)
+                     (#x103D1 . #x103D5)
+                     (#x10400 . #x1044F)
+                     (#x10450 . #x1049D)
+                     (#x10800 . #x10805)
+                     #x10808
+                     (#x1080A . #x10835)
+                     (#x10837 . #x10838)
+                     #x1083C
+                     #x1083F
+                     (#x10900 . #x10915)
+                     (#x10920 . #x10939)
+                     #x10A00
+                     (#x10A01 . #x10A03)
+                     (#x10A05 . #x10A06)
+                     (#x10A0C . #x10A0F)
+                     (#x10A10 . #x10A13)
+                     (#x10A15 . #x10A17)
+                     (#x10A19 . #x10A33)
+                     (#x12000 . #x1236E)
+                     (#x12400 . #x12462)
+                     (#x1D400 . #x1D454)
+                     (#x1D456 . #x1D49C)
+                     (#x1D49E . #x1D49F)
+                     #x1D4A2
+                     (#x1D4A5 . #x1D4A6)
+                     (#x1D4A9 . #x1D4AC)
+                     (#x1D4AE . #x1D4B9)
+                     #x1D4BB
+                     (#x1D4BD . #x1D4C3)
+                     (#x1D4C5 . #x1D505)
+                     (#x1D507 . #x1D50A)
+                     (#x1D50D . #x1D514)
+                     (#x1D516 . #x1D51C)
+                     (#x1D51E . #x1D539)
+                     (#x1D53B . #x1D53E)
+                     (#x1D540 . #x1D544)
+                     #x1D546
+                     (#x1D54A . #x1D550)
+                     (#x1D552 . #x1D6A5)
+                     (#x1D6A8 . #x1D6C0)
+                     (#x1D6C2 . #x1D6DA)
+                     (#x1D6DC . #x1D6FA)
+                     (#x1D6FC . #x1D714)
+                     (#x1D716 . #x1D734)
+                     (#x1D736 . #x1D74E)
+                     (#x1D750 . #x1D76E)
+                     (#x1D770 . #x1D788)
+                     (#x1D78A . #x1D7A8)
+                     (#x1D7AA . #x1D7C2)
+                     (#x1D7C4 . #x1D7CB)
+                     (#x20000 . #x2A6D6)
+                     (#x2F800 . #x2FA1D))
+             bits)
+      (let* ((low (if (atom range) range (car range)))
+             (high (1+ (if (atom range) range (cdr range)))))
+        (do* ((i low (1+ i)))
+             ((= i high))
+          (setf (sbit bits i) 1))))))
+
+
+(defun alpha-char-p (c)
+  "The argument must be a character object. ALPHA-CHAR-P returns T if the
+   argument is an alphabetic character; otherwise NIL."
+  (let* ((code (char-code c))
+         (bits *alpha-char-bits*))
+    (declare (type (mod #x110000) code)
+             (simple-bit-vector bits))
+    (and (< code (length bits))
+         (not (eql 0 (sbit bits code))))))
+
+
+;;; def-accessors type-tracking stuff.  Used by inspector
+(defvar *def-accessor-types* nil)
+
+(defun add-accessor-types (types names)
+  (dolist (type types)
+    (let ((cell (or (assq type *def-accessor-types*)
+                    (car (push (cons type nil) *def-accessor-types*)))))
+      (setf (cdr cell) (if (vectorp names) names (%list-to-uvector nil names))))))
+
+
+;;; Some simple explicit storage management for cons cells
+
+(def-standard-initial-binding *cons-pool* (%cons-pool nil))
+
+(defun cheap-cons (car cdr)
+  (let* ((pool *cons-pool*)
+         (cons (pool.data pool)))
+    (if cons
+      (locally (declare (type cons cons))
+        (setf (pool.data pool) (cdr cons)
+              (car cons) car
+              (cdr cons) cdr)
+        cons)
+      (cons car cdr))))
+
+(defun free-cons (cons)
+  (when (consp cons)
+    (locally (declare (type cons cons))
+      (setf (car cons) nil
+            (cdr cons) nil)
+      (let* ((pool *cons-pool*)
+             (freelist (pool.data pool)))
+        (setf (pool.data pool) cons
+              (cdr cons) freelist)))))
+
+(defun cheap-copy-list (list)
+  (let ((l list)
+        res)
+    (loop
+      (when (atom l)
+        (return (nreconc res l)))
+      (setq res (cheap-cons (pop l) res)))))
+
+(defun cheap-list (&rest args)
+  (declare (dynamic-extent args))
+  (cheap-copy-list args))
+
+;;; Works for dotted lists
+(defun cheap-free-list (list)
+  (let ((l list)
+        next-l)
+    (loop
+      (setq next-l (cdr l))
+      (free-cons l)
+      (when (atom (setq l next-l))
+        (return)))))
+
+(defmacro pop-and-free (place)
+  (setq place (require-type place 'symbol))     ; all I need for now.
+  (let ((list (gensym))
+        (cdr (gensym)))
+    `(let* ((,list ,place)
+            (,cdr (cdr ,list)))
+       (prog1
+         (car ,list)
+         (setf ,place ,cdr)
+         (free-cons ,list)))))
+
+;;; Support for defresource & using-resource macros
+(defun make-resource (constructor &key destructor initializer)
+  (%cons-resource constructor destructor initializer))
+
+(defun allocate-resource (resource)
+  (setq resource (require-type resource 'resource))
+  (with-lock-grabbed ((resource.lock resource))
+    (let ((pool (resource.pool resource))
+          res)
+      (let ((data (pool.data pool)))
+        (when data
+          (setf res (car data)
+                (pool.data pool) (cdr (the cons data)))
+          (free-cons data)))
+      (if res
+        (let ((initializer (resource.initializer resource)))
+          (when initializer
+            (funcall initializer res)))
+        (setq res (funcall (resource.constructor resource))))
+      res)))
+
+(defun free-resource (resource instance)
+  (setq resource (require-type resource 'resource))
+  (with-lock-grabbed ((resource.lock resource))
+    (let ((pool (resource.pool resource))
+          (destructor (resource.destructor resource)))
+      (when destructor
+        (funcall destructor instance))
+      (setf (pool.data pool)
+            (cheap-cons instance (pool.data pool)))))
+  resource)
+
+(defun valid-char-code-p (code)
+  (and (typep code 'fixnum)
+       (locally (declare (fixnum code))
+         (and 
+          (>= code 0)
+          (< code #x110000)
+          (or (< code #xfffe)
+              (> code #xffff))
+          (or (< code #xd800)
+              (> code #xdfff))))))
+
+
+(defpackage #.(ftd-interface-package-name
+               (backend-target-foreign-type-data *target-backend*))
+  (:nicknames "OS")
+  (:use "COMMON-LISP"))
+
+
+
Index: /branches/new-random/level-1/l1-boot-1.lisp
===================================================================
--- /branches/new-random/level-1/l1-boot-1.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-boot-1.lisp	(revision 13309)
@@ -0,0 +1,124 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; L1-boot.lisp
+
+(in-package "CCL")
+
+(defparameter *gensym-counter* 0 "counter for generating unique GENSYM symbols")
+
+(defparameter *inhibit-greeting* nil)
+
+;the below 3 variables are expected to be redefined in the user's init file
+(defparameter *short-site-name* nil)
+(defparameter *long-site-name* nil)
+#|
+(defparameter *machine-instance* nil)
+|#
+
+(defun lisp-implementation-type ()
+  #+clozure-common-lisp "Clozure Common Lisp"
+  #-clozure-common-lisp "OpenMCL")
+
+
+(defparameter *platform-os-names*
+  `((,platform-os-vxworks . :vxwork)
+    (,platform-os-linux . :linux)
+    (,platform-os-solaris . :solaris)
+    (,platform-os-darwin . :darwin)
+    (,platform-os-freebsd . :freebsd)
+    (,platform-os-windows . :windows)))
+
+(defparameter *platform-cpu-names*
+  `((,platform-cpu-ppc . :ppc)
+    (,platform-cpu-sparc . :sparc)
+    (,platform-cpu-x86 . :x86)))
+
+(defun host-platform ()
+  (let* ((pf (%get-kernel-global 'host-platform)))
+    (values
+     (or (cdr (assoc (logand pf platform-os-mask)
+                     *platform-os-names*))
+         :unknown)
+     (if (logtest pf platform-word-size-mask)
+       64
+       32)
+     (or (cdr (assoc (logand pf platform-cpu-mask)
+                     *platform-cpu-names*))
+         :unknown))))
+
+
+(defun platform-description ()
+  (multiple-value-bind (os bits cpu) (host-platform)
+    (format nil "~a~a~d" (string-capitalize os) cpu bits)))
+
+(defun lisp-implementation-version ()
+  (%str-cat "Version " (format nil *openmcl-version* (platform-description))))
+
+
+
+
+(defun replace-base-translation (host-dir new-base-dir)
+  (let* ((host (pathname-host host-dir))
+         (device (pathname-device new-base-dir))
+         (host-dir (full-pathname host-dir))
+         (trans (logical-pathname-translations host))
+         (host-wild (merge-pathnames "**/*.*" host-dir)))
+    (setq host-dir (pathname-directory host-dir))
+    (setq new-base-dir (pathname-directory new-base-dir))
+    (setf 
+     (logical-pathname-translations host)
+     (mapcar
+      #'(lambda (pair)
+          (let ((rhs (cadr pair)))
+            (if (and (physical-pathname-p rhs)
+                     (pathname-match-p rhs host-wild))
+              (list (car pair)
+                    (merge-pathnames 
+                     (make-pathname 
+                      :defaults nil
+                      :device device
+                      :directory (append new-base-dir
+                                         (nthcdr (length host-dir) 
+                                                 (pathname-directory rhs))))
+                     rhs))
+              pair)))
+      trans))))
+
+(defun set-ccl-directory (path)
+  (replace-base-translation "ccl:" (translate-logical-pathname path)))
+
+
+
+
+; only do these if exist
+(defun init-logical-directories ()
+  (replace-base-translation "home:"  (user-homedir-pathname))
+  (replace-base-translation "ccl:" (ccl-directory)))
+
+(push #'init-logical-directories *lisp-system-pointer-functions*)
+
+
+(catch :toplevel
+  (init-logical-directories)
+  )
+
+
+
+
+
+
Index: /branches/new-random/level-1/l1-boot-2.lisp
===================================================================
--- /branches/new-random/level-1/l1-boot-2.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-boot-2.lisp	(revision 13309)
@@ -0,0 +1,332 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; l1-boot-2.lisp
+;; Second part of l1-boot
+
+(in-package "CCL")
+
+(macrolet ((l1-load (name)
+	     (let* ((namestring
+		     (concatenate 'simple-base-string
+                                  "./l1-fasls/"
+				  (string name)
+                                  (namestring (backend-target-fasl-pathname
+                                               *target-backend*)))))
+               `(let* ((*loading-file-source-file* *loading-file-source-file*)
+                       (*loading-toplevel-location* *loading-toplevel-location*))
+                  (%fasload ,namestring))))
+	   (bin-load (name)
+	     (let* ((namestring
+		     (concatenate 'simple-base-string
+                                  "./bin/"
+				  (string name)
+                                  (namestring (backend-target-fasl-pathname
+                                               *target-backend*)))))
+               `(let* ((*loading-file-source-file* *loading-file-source-file*)
+                       (*loading-toplevel-location* *loading-toplevel-location*))
+                  (%fasload ,namestring)))))
+
+
+(catch :toplevel
+    #+ppc-target
+    (l1-load "ppc-error-signal")
+    #+x86-target
+    (l1-load "x86-error-signal")
+    (l1-load "l1-error-signal")
+    (l1-load "l1-sockets")
+    (setq *LEVEL-1-LOADED* t))
+
+#+ppc-target
+(defun altivec-available-p ()
+  "Return non-NIL if AltiVec is available."
+  (not (eql (%get-kernel-global 'ppc::altivec-present) 0)))
+
+#+ppc-target
+(defloadvar *altivec-available* (altivec-available-p)
+  "This variable is intitialized each time a Clozure CL session starts based
+on information provided by the lisp kernel. Its value is true if AltiVec is
+present and false otherwise. This variable shouldn't be set by user code.")
+
+       
+(defstatic *auto-flush-streams* ())
+(def-ccl-pointers *auto-flush-streams* () (setq *auto-flush-streams* nil))
+(defstatic *auto-flush-streams-lock* (make-lock))
+
+
+(defvar *batch-flag* (not (eql (%get-kernel-global 'batch-flag) 0)))
+(defloadvar *quiet-flag* nil)
+(defvar *terminal-input* ())
+(defvar *terminal-output* ())
+(defvar *stdin* ())
+(defvar *stdout* ())
+(defvar *stderr* ())
+
+
+(defun set-basic-stream-prototype (class)
+  (when (subtypep class 'basic-stream)
+    (setf (%class.prototype class) (or (%class.prototype class)
+                                       (allocate-basic-stream class)))
+    (dolist (subclass (class-direct-subclasses class))
+      (set-basic-stream-prototype subclass))))
+
+(set-basic-stream-prototype (find-class 'basic-stream))
+
+
+;;; The hard parts here have to do with setting up *TERMINAL-IO*.
+;;; Note that opening /dev/tty can fail, and that failure would
+;;; be reported as a negative return value from FD-OPEN.
+;;; It's pretty important that nothing signals an error here,
+;;; since there may not be any valid streams to write an error
+;;; message to.
+
+(defglobal *interactive-streams-initialized* nil)
+
+(defun initialize-interactive-streams ()
+  (let* ((encoding (lookup-character-encoding *terminal-character-encoding-name*))
+         (encoding-name (if encoding (character-encoding-name encoding))))
+    (setq *stdin* (make-fd-stream #-windows-target 0
+                                  #+windows-target (%ptr-to-int
+                                                    (#_GetStdHandle #$STD_INPUT_HANDLE))
+                                  :basic t
+                                  :sharing :lock
+                                  :direction :input
+                                  :interactive (not *batch-flag*)
+                                  :encoding encoding-name
+                                  #+windows-target :line-termination #+windows-target :cp/m))
+    (setq *stdout* (make-fd-stream #-windows-target 1
+                                   #+windows-target (%ptr-to-int
+                                                     (#_GetStdHandle #$STD_OUTPUT_HANDLE))
+                                   :basic t :direction :output :sharing :lock :encoding encoding-name #+windows-target :line-termination #+windows-target :msdos))
+    (setq *stderr* (make-fd-stream #-windows-target 2
+                                   #+windows-target (%ptr-to-int
+                                                     (#_GetStdHandle #$STD_ERROR_HANDLE))
+                    :basic t :direction :output :sharing :lock :encoding encoding-name #+windows-target :line-termination #+windows-target :crlf))
+    (if *batch-flag*
+      (let* ((tty-fd
+               #-windows-target
+               (let* ((fd (fd-open "/dev/tty" #$O_RDWR)))
+                 (if (>= fd 0) fd)))
+             (can-use-tty #-windows-target (and tty-fd (eql (tcgetpgrp tty-fd) (getpid)))))
+        (if can-use-tty
+          (setq
+           *terminal-input* (make-fd-stream tty-fd
+                                            :basic t
+                                            :direction :input
+                                            :interactive t
+                                            :sharing :lock
+                                            :encoding encoding-name)
+           *terminal-output* (make-fd-stream tty-fd :basic t :direction :output :sharing :lock :encoding encoding-name)
+           *terminal-io* (make-echoing-two-way-stream
+                          *terminal-input* *terminal-output*))
+          (progn
+            (when tty-fd (fd-close tty-fd))
+            (setq *terminal-input* *stdin*
+                  *terminal-output* *stdout*
+                  *terminal-io* (make-two-way-stream
+                                 *terminal-input* *terminal-output*))))
+        (setq *standard-input* *stdin*
+              *standard-output* *stdout*))
+      (progn
+        (setq *terminal-input* *stdin*
+              *terminal-output* *stdout*
+              *terminal-io* (make-echoing-two-way-stream
+                             *terminal-input* *terminal-output*))
+        (setq *standard-input* (make-synonym-stream '*terminal-io*)
+              *standard-output* (make-synonym-stream '*terminal-io*))))
+    (setq *error-output* (if *batch-flag*
+                           (make-synonym-stream '*stderr*)
+                           (make-synonym-stream '*terminal-io*)))
+    (setq *query-io* (make-synonym-stream '*terminal-io*))
+    (setq *debug-io* *query-io*)
+    (setq *trace-output* *standard-output*)
+    (push *stdout* *auto-flush-streams*)
+    (setf (input-stream-shared-resource *terminal-input*)
+          (make-shared-resource "Shared Terminal Input")))
+  (setq *interactive-streams-initialized* t))
+
+(initialize-interactive-streams)
+
+(def-standard-initial-binding *standard-input*)
+(def-standard-initial-binding *standard-output*)
+(def-standard-initial-binding *error-output*)
+(def-standard-initial-binding *trace-output*)
+(def-standard-initial-binding *debug-io*)
+(def-standard-initial-binding *query-io*)
+
+
+(defun set-terminal-encoding (encoding-name)
+  #+windows-target (when (atom encoding-name)
+                     (setq encoding-name `(:character-encoding ,encoding-name
+                                           :line-termination :crlf)))
+  (let* ((exformat (normalize-external-format t encoding-name)))
+    (setf (stream-external-format *stdin*) exformat
+          (stream-external-format *stdout*) exformat
+          (stream-external-format *stderr*) exformat
+          (stream-external-format *terminal-input*) exformat
+          (stream-external-format *terminal-output*) exformat))
+  encoding-name)
+
+(catch :toplevel
+    (macrolet ((l1-load-provide (module path)
+		 `(let* ((*package* *package*))
+		   (l1-load ,path)
+		   (provide ,module)))
+	       (bin-load-provide (module path)
+		 `(let* ((*package* *package*))
+		   (bin-load ,path)
+		   (provide ,module))))
+      (bin-load-provide "SORT" "sort")
+      (bin-load-provide "NUMBERS" "numbers")
+      
+      (bin-load-provide "SUBPRIMS" "subprims")
+      #+ppc32-target
+      (bin-load-provide "PPC32-ARCH" "ppc32-arch") 
+      #+ppc64-target
+      (bin-load-provide "PPC64-ARCH" "ppc64-arch")
+      #+x86-target
+      (bin-load-provide "X8632-ARCH" "x8632-arch")
+      #+x86-target
+      (bin-load-provide "X8664-ARCH" "x8664-arch")
+      (bin-load-provide "VREG" "vreg")
+      
+      #+ppc-target
+      (bin-load-provide "PPC-ASM" "ppc-asm")
+      
+      (bin-load-provide "VINSN" "vinsn")
+      (bin-load-provide "REG" "reg")
+      
+      #+ppc-target
+      (bin-load-provide "PPC-LAP" "ppc-lap")
+      (bin-load-provide "BACKEND" "backend")
+      (bin-load-provide "NX2" "nx2")
+     
+      #+ppc-target
+      (provide "PPC2")                  ; Lie, load the module manually
+
+      #+x86-target
+      (provide "X862")
+      
+      (l1-load-provide "NX" "nx")
+      
+      #+ppc-target
+      (bin-load "ppc2")
+
+      #+x86-target
+      (bin-load "x862")
+      
+      (bin-load-provide "LEVEL-2" "level-2")
+      (bin-load-provide "MACROS" "macros")
+      (bin-load-provide "SETF" "setf")
+      (bin-load-provide "SETF-RUNTIME" "setf-runtime")
+      (bin-load-provide "FORMAT" "format")
+      (bin-load-provide "STREAMS" "streams")
+      (bin-load-provide "OPTIMIZERS" "optimizers")      
+      (bin-load-provide "DEFSTRUCT-MACROS" "defstruct-macros")
+      (bin-load-provide "DEFSTRUCT-LDS" "defstruct-lds")
+      (bin-load-provide "NFCOMP" "nfcomp")
+      (bin-load-provide "BACKQUOTE" "backquote")
+      (bin-load-provide "BACKTRACE-LDS" "backtrace-lds")
+      (bin-load-provide "BACKTRACE" "backtrace")
+      (bin-load-provide "READ" "read")
+      (bin-load-provide "ARRAYS-FRY" "arrays-fry")
+      (bin-load-provide "APROPOS" "apropos")
+      (bin-load-provide "SOURCE-FILES" "source-files")
+      
+      #+ppc-target
+      (progn
+	(bin-load-provide "PPC-DISASSEMBLE" "ppc-disassemble")
+	(bin-load-provide "PPC-LAPMACROS" "ppc-lapmacros"))
+
+      #+x86-target
+      (progn
+	(bin-load-provide "X86-DISASSEMBLE" "x86-disassemble")
+	(bin-load-provide "X86-LAPMACROS" "x86-lapmacros"))
+
+
+      (bin-load-provide "FOREIGN-TYPES" "foreign-types")
+      (install-standard-foreign-types *host-ftd*)
+      
+      #+(and ppc32-target linux-target)
+      (bin-load-provide "FFI-LINUXPPC32" "ffi-linuxppc32")
+      #+(and ppc32-target darwin-target)
+      (bin-load-provide "FFI-DARWINPPC32" "ffi-darwinppc32")
+      #+(and ppc64-target darwin-target)
+      (bin-load-provide "FFI-DARWINPPC64" "ffi-darwinppc64")
+      #+(and ppc64-target linux-target)
+      (bin-load-provide "FFI-LINUXPPC64" "ffi-linuxppc64")
+      #+(and x8632-target darwin-target)
+      (bin-load-provide "FFI-DARWINX8632" "ffi-darwinx8632")
+      #+(and x8664-target linux-target)  
+      (bin-load-provide "FFI-LINUXX8664" "ffi-linuxx8664")
+      #+(and x8664-target darwin-target)  
+      (bin-load-provide "FFI-DARWINX8664" "ffi-darwinx8664")
+      #+(and x8664-target freebsd-target)  
+      (bin-load-provide "FFI-FREEBSDX8664" "ffi-freebsdx8664")
+      #+(and x8664-target solaris-target)
+      (bin-load-provide "FFI-SOLARISX8664" "ffi-solarisx8664")
+      #+win64-target
+      (bin-load-provide "FFI-WIN64" "ffi-win64")
+      #+linuxx8632-target
+      (bin-load-provide "FFI-LINUXX8632" "ffi-linuxx8632")
+      #+win32-target
+      (bin-load-provide "FFI-WIN32" "ffi-win32")
+      #+solarisx8632-target
+      (bin-load-provide "FFI-SOLARISX8632" "ffi-solarisx8632")
+      #+freebsdx8632-target
+      (bin-load-provide "FFI-FREEBSDX8632" "ffi-freebsdx8632")
+
+
+      ;; Knock wood: all standard reader macros and no non-standard
+      ;; reader macros are defined at this point.
+      (setq *readtable* (copy-readtable *readtable*))
+
+      (bin-load-provide "DB-IO" "db-io")
+
+      (canonicalize-foreign-type-ordinals *host-ftd*)
+      
+      (bin-load-provide "CASE-ERROR" "case-error")
+      (bin-load-provide "ENCAPSULATE" "encapsulate")
+      (bin-load-provide "METHOD-COMBINATION" "method-combination")
+      (bin-load-provide "MISC" "misc")
+      (bin-load-provide "PPRINT" "pprint")
+      (bin-load-provide "DUMPLISP" "dumplisp")
+      (bin-load-provide "PATHNAMES" "pathnames")
+      (bin-load-provide "TIME" "time")
+      (bin-load-provide "COMPILE-CCL" "compile-ccl")
+      (bin-load-provide "ARGLIST" "arglist")
+      (bin-load-provide "EDIT-CALLERS" "edit-callers")
+      (bin-load-provide "DESCRIBE" "describe")
+      (bin-load-provide "COVER" "cover")
+      (bin-load-provide "LEAKS" "leaks")
+      (bin-load-provide "CORE-FILES" "core-files")
+      (bin-load-provide "MCL-COMPAT" "mcl-compat")
+      (require "LOOP")
+      (bin-load-provide "CCL-EXPORT-SYMS" "ccl-export-syms")
+      (l1-load-provide "VERSION" "version")
+      (require "JP-ENCODE")
+      (require "LISPEQU") ; Shouldn't need this at load time ...
+      )
+    (setq *%fasload-verbose* nil)
+    )
+)
+
+
+
+
+
+
Index: /branches/new-random/level-1/l1-boot-3.lisp
===================================================================
--- /branches/new-random/level-1/l1-boot-3.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-boot-3.lisp	(revision 13309)
@@ -0,0 +1,33 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; l1-boot-3.lisp
+;;; Third part of l1-boot
+
+(in-package "CCL")
+
+(catch :toplevel
+    (or (find-package "COMMON-LISP-USER")
+        (make-package "COMMON-LISP-USER" :use '("COMMON-LISP" "CCL") :NICKNAMES '("CL-USER")))
+)
+
+(set-periodic-task-interval .33)
+(setq cmain xcmain)
+(setq %err-disp %xerr-disp)
+
+;;;end of l1-boot-3.lisp
+
Index: /branches/new-random/level-1/l1-boot-lds.lisp
===================================================================
--- /branches/new-random/level-1/l1-boot-lds.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-boot-lds.lisp	(revision 13309)
@@ -0,0 +1,123 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+; l1-boot-lds.lisp
+
+(in-package "CCL")
+
+
+
+
+
+(defun command-line-arguments ()
+  *command-line-argument-list*)
+
+(defun startup-ccl (&optional init-file)
+  (with-simple-restart (abort "Abort startup.")
+    (let ((init-files (if (listp init-file) init-file (list init-file))))
+      (dolist (init-file init-files)
+	(with-simple-restart (continue "Skip loading init file.")
+	  (when (load init-file :if-does-not-exist nil :verbose nil)
+	    (return)))))
+    (flet ((eval-string (s)
+	     (with-simple-restart (continue "Skip evaluation of ~a" s)
+	       (eval (read-from-string s))))
+	   (load-file (name)
+	     (with-simple-restart (continue "Skip loading ~s" name)
+	       (load name))))
+      (dolist (p *lisp-startup-parameters*)
+	(let* ((param (cdr p)))
+	  (case (car p)
+	    (:gc-threshold
+	     (multiple-value-bind (n last) (parse-integer param :junk-allowed t)
+	       (when n
+		 (if (< last (length param))
+		   (case (schar param last)
+		     ((#\k #\K) (setq n (ash n 10)))
+		     ((#\m #\M) (setq n (ash n 20)))))
+		 (set-lisp-heap-gc-threshold n)
+		 (use-lisp-heap-gc-threshold))))
+	    (:eval (eval-string param))
+	    (:load (load-file param))))))))
+
+
+(defun listener-function ()
+  (progn
+    (unless (or *inhibit-greeting* *quiet-flag*)
+      (format t "~&Welcome to ~A ~A!~%"
+	      (lisp-implementation-type)
+	      (lisp-implementation-version)))
+    (toplevel-loop)))
+
+
+(defun make-mcl-listener-process (procname
+                                  input-stream
+                                  output-stream
+                                  cleanup-function
+                                  &key
+                                  (initial-function #'listener-function)
+                                  (close-streams t)
+                                  (class 'process)
+                                  (control-stack-size *default-control-stack-size*)
+                                  (auto-flush t)
+                                  (value-stack-size *default-value-stack-size*)
+                                  (temp-stack-size *default-temp-stack-size*)
+                                  (echoing t)
+                                  (process))
+  (let ((p (if (typep process class)
+             (progn
+               (setf (process-thread process)
+                     (new-thread procname control-stack-size value-stack-size  temp-stack-size))
+               process)
+             (make-process procname
+                           :class class
+                           :stack-size control-stack-size
+                           :vstack-size value-stack-size
+                           :tstack-size temp-stack-size))))
+    (process-preset p #'(lambda ()
+                          (let ((*terminal-io*
+                                 (if echoing
+                                   (make-echoing-two-way-stream
+                                    input-stream output-stream)
+                                   (make-two-way-stream
+                                    input-stream output-stream))))
+			    (unwind-protect
+				 (progn
+                                   (when auto-flush
+                                     (add-auto-flush-stream output-stream))
+				   (let* ((shared-input
+					   (input-stream-shared-resource
+					    input-stream)))
+				     (when shared-input
+				       (setf (shared-resource-primary-owner
+					      shared-input)
+					     *current-process*)))
+                                   (application-ui-operation
+                                    *application*
+                                    :note-current-package *package*)
+				   (funcall initial-function))
+                              (remove-auto-flush-stream output-stream)
+			      (funcall cleanup-function)
+			      (when close-streams
+				(close input-stream)
+				(close output-stream))))))
+    (process-enable p)
+    p))
+
+
+; End of l1-boot-lds.lisp
Index: /branches/new-random/level-1/l1-callbacks.lisp
===================================================================
--- /branches/new-random/level-1/l1-callbacks.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-callbacks.lisp	(revision 13309)
@@ -0,0 +1,154 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; l1-callbacks.lisp
+
+(in-package "CCL")
+
+(defstatic *callback-lock* (make-lock))
+
+
+;;; (defcallback ...) expands into a call to this function.
+(defun define-callback-function (lisp-function  &optional doc-string (without-interrupts t) info &aux name trampoline)
+  (unless (functionp lisp-function)
+    (setq lisp-function (require-type lisp-function 'function)))
+  (unless (and (symbolp (setq name (function-name lisp-function)))
+               ;;Might as well err out now before do any _Newptr's...
+               (not (constant-symbol-p name)))
+    (report-bad-arg name '(and symbol (not (satisfies constantp)))))
+  (with-lock-grabbed (*callback-lock*)
+    (let ((len (length %pascal-functions%)))
+      (declare (fixnum len))
+      (when (and name (boundp name))
+        (let ((old-tramp (symbol-value name)))
+          (dotimes (i len)
+            (let ((pfe (%svref %pascal-functions% i)))
+              (when (and (vectorp pfe)
+                         (eql old-tramp (pfe.routine-descriptor pfe)))
+                
+                (setf (pfe.without-interrupts pfe) without-interrupts)
+                (setf (pfe.lisp-function pfe) lisp-function)
+                (setq trampoline old-tramp))))))
+      (unless trampoline
+        (let ((index (dotimes (i (length %pascal-functions%)
+                               (let* ((new-len (if (zerop len) 32 (* len 2)))
+                                      (new-pf (make-array (the fixnum new-len))))
+                                 (declare (fixnum new-len))
+                                 (dotimes (i len)
+                                   (setf (%svref new-pf i) (%svref %pascal-functions% i)))
+                                 (do ((i len (1+ i)))
+                                     ((>= i new-len))
+                                   (declare (fixnum i))
+                                   (setf (%svref new-pf i) nil))
+                                 (setq %pascal-functions% new-pf)
+                                 len))
+                       (unless (%svref %pascal-functions% i)
+                         (return i)))))
+          (setq trampoline (make-callback-trampoline index info))
+          (setf (%svref %pascal-functions% index)
+                (%cons-pfe trampoline info lisp-function name without-interrupts))))))
+  ;;(%proclaim-special name)          ;
+  ;; already done by defpascal expansion
+  (when name (set name trampoline))
+  (record-source-file name 'callback)
+  (when (and doc-string *save-doc-strings*)
+    (setf (documentation name 'variable) doc-string))
+  (when *fasload-print* (format t "~&~S~%" name))
+  (or name trampoline))
+
+(defun %lookup-pascal-function (index)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-lock-grabbed (*callback-lock*)
+    (let* ((pfe (svref %pascal-functions% index)))
+      (values (pfe.lisp-function pfe)
+              (pfe.without-interrupts pfe)
+	      (pfe.trace-p pfe)))))
+
+
+(defun %callback-function (pointer)
+  (if (typep pointer 'symbol)
+    (setq pointer (symbol-value pointer)))
+  (with-lock-grabbed (*callback-lock*)
+    (let* ((index (dotimes (i (length %pascal-functions%))
+                    (when (eql (pfe.routine-descriptor (svref %pascal-functions% i)) pointer)
+                      (return i)))))
+      (when index
+        (let* ((entry (svref %pascal-functions% index)))
+          (pfe.lisp-function entry))))))
+
+  
+(defun %delete-pascal-function (pointer)
+  (with-lock-grabbed (*callback-lock*)
+    (let* ((index (dotimes (i (length %pascal-functions%))
+                    (when (eql (pfe.routine-descriptor (svref %pascal-functions% i)) pointer)
+                      (return i)))))
+      (when index
+        (let* ((entry (svref %pascal-functions% index))
+               (sym (pfe.sym entry)))
+          (setf (svref %pascal-functions% index) nil)
+          (when (and sym
+                     (boundp sym)
+                     (eql (symbol-value sym)
+                          (pfe.routine-descriptor entry)))
+            (set (symbol-value sym) nil))
+          (free (pfe.routine-descriptor entry))
+          t)))))
+
+
+;; The kernel only really knows how to call back to one function,
+;; and you're looking at it ...
+(defun %pascal-functions% (index args-ptr-fixnum)
+  (declare (optimize (speed 3) (safety 0)))
+  (multiple-value-bind (lisp-function without-interrupts *callback-trace-p*)
+      (%lookup-pascal-function index)
+    (declare (special *callback-trace-p*))
+    (if without-interrupts
+	(without-interrupts (funcall lisp-function args-ptr-fixnum))
+      (funcall lisp-function args-ptr-fixnum))))
+
+(defstatic *callback-alloc-lock* (make-lock))
+
+;;; 
+(defun %make-executable-page ()
+  #-windows-target
+  (#_mmap (%null-ptr)
+          (#_getpagesize)
+          (logior #$PROT_READ #$PROT_WRITE #$PROT_EXEC)
+          (logior #$MAP_PRIVATE #$MAP_ANON)
+          -1
+          0)
+  #+windows-target
+  (#_VirtualAlloc (%null-ptr)
+                  (ash 1 16)            ; should use GetSystemInfo
+                  (logior #$MEM_RESERVE #$MEM_COMMIT)
+                  #$PAGE_EXECUTE_READWRITE)
+  )
+
+(defstatic *available-bytes-for-callbacks* 0)
+(defstatic *current-callback-page* nil)
+
+(defun reset-callback-storage ()
+  (setq *available-bytes-for-callbacks* #-windows-target (#_getpagesize) #+windows-target (ash 1 16)
+        *current-callback-page* (%make-executable-page)))
+
+(defun %allocate-callback-pointer (n)
+  (with-lock-grabbed (*callback-alloc-lock*)
+    (when (< *available-bytes-for-callbacks* n)
+      (reset-callback-storage))
+    (decf *available-bytes-for-callbacks* n)
+    (values (%inc-ptr *current-callback-page* *available-bytes-for-callbacks*))))
+
Index: /branches/new-random/level-1/l1-cl-package.lisp
===================================================================
--- /branches/new-random/level-1/l1-cl-package.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-cl-package.lisp	(revision 13309)
@@ -0,0 +1,1022 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; l1-cl-package.lisp
+
+(in-package "CCL")
+
+
+(eval-when (:compile-toplevel :execute)
+  (defconstant %lisp-symbols%  
+    '("&ALLOW-OTHER-KEYS" 
+      "&AUX" 
+      "&BODY" 
+      "&ENVIRONMENT" 
+      "&KEY" 
+      "&OPTIONAL" 
+      "&REST" 
+      "&WHOLE" 
+      "*" 
+      "**" 
+      "***" 
+      "*BREAK-ON-SIGNALS*" 
+      "*COMPILE-FILE-PATHNAME*" 
+      "*COMPILE-FILE-TRUENAME*" 
+      "*COMPILE-PRINT*" 
+      "*COMPILE-VERBOSE*" 
+      "*DEBUG-IO*" 
+      "*DEBUGGER-HOOK*" 
+      "*DEFAULT-PATHNAME-DEFAULTS*" 
+      "*ERROR-OUTPUT*" 
+      "*FEATURES*" 
+      "*GENSYM-COUNTER*" 
+      "*LOAD-PATHNAME*" 
+      "*LOAD-PRINT*" 
+      "*LOAD-TRUENAME*" 
+      "*LOAD-VERBOSE*" 
+      "*MACROEXPAND-HOOK*" 
+      "*MODULES*" 
+      "*PACKAGE*" 
+      "*PRINT-ARRAY*" 
+      "*PRINT-BASE*" 
+      "*PRINT-CASE*" 
+      "*PRINT-CIRCLE*" 
+      "*PRINT-ESCAPE*" 
+      "*PRINT-GENSYM*" 
+      "*PRINT-LENGTH*" 
+      "*PRINT-LEVEL*" 
+      "*PRINT-LINES*" 
+      "*PRINT-MISER-WIDTH*" 
+      "*PRINT-PPRINT-DISPATCH*" 
+      "*PRINT-PRETTY*" 
+      "*PRINT-RADIX*" 
+      "*PRINT-READABLY*" 
+      "*PRINT-RIGHT-MARGIN*" 
+      "*QUERY-IO*" 
+      "*RANDOM-STATE*" 
+      "*READ-BASE*" 
+      "*READ-DEFAULT-FLOAT-FORMAT*" 
+      "*READ-EVAL*" 
+      "*READ-SUPPRESS*" 
+      "*READTABLE*" 
+      "*STANDARD-INPUT*" 
+      "*STANDARD-OUTPUT*" 
+      "*TERMINAL-IO*" 
+      "*TRACE-OUTPUT*" 
+      "+" 
+      "++" 
+      "+++" 
+      "-" 
+      "/" 
+      "//" 
+      "///" 
+      "/=" 
+      "1+" 
+      "1-" 
+      "<" 
+      "<=" 
+      "=" 
+      ">" 
+      ">=" 
+      "ABORT" 
+      "ABS" 
+      "ACONS" 
+      "ACOS" 
+      "ACOSH" 
+      "ADD-METHOD" 
+      "ADJOIN" 
+      "ADJUST-ARRAY" 
+      "ADJUSTABLE-ARRAY-P" 
+      "ALLOCATE-INSTANCE" 
+      "ALPHA-CHAR-P" 
+      "ALPHANUMERICP" 
+      "AND" 
+      "APPEND" 
+      "APPLY" 
+      "APROPOS" 
+      "APROPOS-LIST" 
+      "AREF" 
+      "ARITHMETIC-ERROR" 
+      "ARITHMETIC-ERROR-OPERANDS" 
+      "ARITHMETIC-ERROR-OPERATION" 
+      "ARRAY" 
+      "ARRAY-DIMENSION" 
+      "ARRAY-DIMENSION-LIMIT" 
+      "ARRAY-DIMENSIONS" 
+      "ARRAY-DISPLACEMENT" 
+      "ARRAY-ELEMENT-TYPE" 
+      "ARRAY-HAS-FILL-POINTER-P" 
+      "ARRAY-IN-BOUNDS-P" 
+      "ARRAY-RANK" 
+      "ARRAY-RANK-LIMIT" 
+      "ARRAY-ROW-MAJOR-INDEX" 
+      "ARRAY-TOTAL-SIZE" 
+      "ARRAY-TOTAL-SIZE-LIMIT" 
+      "ARRAYP" 
+      "ASH" 
+      "ASIN" 
+      "ASINH" 
+      "ASSERT" 
+      "ASSOC" 
+      "ASSOC-IF" 
+      "ASSOC-IF-NOT" 
+      "ATAN" 
+      "ATANH" 
+      "ATOM" 
+      "BASE-CHAR" 
+      "BASE-STRING" 
+      "BIGNUM" 
+      "BIT" 
+      "BIT-AND" 
+      "BIT-ANDC1" 
+      "BIT-ANDC2" 
+      "BIT-EQV" 
+      "BIT-IOR" 
+      "BIT-NAND" 
+      "BIT-NOR" 
+      "BIT-NOT" 
+      "BIT-ORC1" 
+      "BIT-ORC2" 
+      "BIT-VECTOR" 
+      "BIT-VECTOR-P" 
+      "BIT-XOR" 
+      "BLOCK" 
+      "BOOLE" 
+      "BOOLE-1" 
+      "BOOLE-2" 
+      "BOOLE-AND" 
+      "BOOLE-ANDC1" 
+      "BOOLE-ANDC2" 
+      "BOOLE-C1" 
+      "BOOLE-C2" 
+      "BOOLE-CLR" 
+      "BOOLE-EQV" 
+      "BOOLE-IOR" 
+      "BOOLE-NAND" 
+      "BOOLE-NOR" 
+      "BOOLE-ORC1" 
+      "BOOLE-ORC2" 
+      "BOOLE-SET" 
+      "BOOLE-XOR" 
+      "BOOLEAN" 
+      "BOTH-CASE-P" 
+      "BOUNDP" 
+      "BREAK" 
+      "BROADCAST-STREAM" 
+      "BROADCAST-STREAM-STREAMS" 
+      "BUILT-IN-CLASS" 
+      "BUTLAST" 
+      "BYTE" 
+      "BYTE-POSITION" 
+      "BYTE-SIZE" 
+      "CAAAAR" 
+      "CAAADR" 
+      "CAAAR" 
+      "CAADAR" 
+      "CAADDR" 
+      "CAADR" 
+      "CAAR" 
+      "CADAAR" 
+      "CADADR" 
+      "CADAR" 
+      "CADDAR" 
+      "CADDDR" 
+      "CADDR" 
+      "CADR" 
+      "CALL-ARGUMENTS-LIMIT" 
+      "CALL-METHOD" 
+      "CALL-NEXT-METHOD" 
+      "CAR" 
+      "CASE" 
+      "CATCH" 
+      "CCASE" 
+      "CDAAAR" 
+      "CDAADR" 
+      "CDAAR" 
+      "CDADAR" 
+      "CDADDR" 
+      "CDADR" 
+      "CDAR" 
+      "CDDAAR" 
+      "CDDADR" 
+      "CDDAR" 
+      "CDDDAR" 
+      "CDDDDR" 
+      "CDDDR" 
+      "CDDR" 
+      "CDR" 
+      "CEILING" 
+      "CELL-ERROR" 
+      "CELL-ERROR-NAME" 
+      "CERROR" 
+      "CHANGE-CLASS" 
+      "CHAR" 
+      "CHAR-CODE" 
+      "CHAR-CODE-LIMIT" 
+      "CHAR-DOWNCASE" 
+      "CHAR-EQUAL" 
+      "CHAR-GREATERP" 
+      "CHAR-INT" 
+      "CHAR-LESSP" 
+      "CHAR-NAME" 
+      "CHAR-NOT-EQUAL" 
+      "CHAR-NOT-GREATERP" 
+      "CHAR-NOT-LESSP" 
+      "CHAR-UPCASE" 
+      "CHAR/=" 
+      "CHAR<" 
+      "CHAR<=" 
+      "CHAR=" 
+      "CHAR>" 
+      "CHAR>=" 
+      "CHARACTER" 
+      "CHARACTERP" 
+      "CHECK-TYPE" 
+      "CIS" 
+      "CLASS" 
+      "CLASS-NAME" 
+      "CLASS-OF" 
+      "CLEAR-INPUT" 
+      "CLEAR-OUTPUT" 
+      "CLOSE" 
+      "CLRHASH" 
+      "CODE-CHAR" 
+      "COERCE" 
+      "COMPILATION-SPEED" 
+      "COMPILE" 
+      "COMPILE-FILE" 
+      "COMPILE-FILE-PATHNAME" 
+      "COMPILED-FUNCTION" 
+      "COMPILED-FUNCTION-P" 
+      "COMPILER-MACRO" 
+      "COMPILER-MACRO-FUNCTION" 
+      "COMPLEMENT" 
+      "COMPLEX" 
+      "COMPLEXP" 
+      "COMPUTE-APPLICABLE-METHODS" 
+      "COMPUTE-RESTARTS" 
+      "CONCATENATE" 
+      "CONCATENATED-STREAM" 
+      "CONCATENATED-STREAM-STREAMS" 
+      "COND" 
+      "CONDITION" 
+      "CONJUGATE" 
+      "CONS" 
+      "CONSP" 
+      "CONSTANTLY" 
+      "CONSTANTP" 
+      "CONTINUE" 
+      "CONTROL-ERROR" 
+      "COPY-ALIST" 
+      "COPY-LIST" 
+      "COPY-PPRINT-DISPATCH" 
+      "COPY-READTABLE" 
+      "COPY-SEQ" 
+      "COPY-STRUCTURE" 
+      "COPY-SYMBOL" 
+      "COPY-TREE" 
+      "COS" 
+      "COSH" 
+      "COUNT" 
+      "COUNT-IF" 
+      "COUNT-IF-NOT" 
+      "CTYPECASE" 
+      "DEBUG" 
+      "DECF" 
+      "DECLAIM" 
+      "DECLARATION" 
+      "DECLARE" 
+      "DECODE-FLOAT" 
+      "DECODE-UNIVERSAL-TIME" 
+      "DEFCLASS" 
+      "DEFCONSTANT" 
+      "DEFGENERIC" 
+      "DEFINE-COMPILER-MACRO" 
+      "DEFINE-CONDITION" 
+      "DEFINE-METHOD-COMBINATION" 
+      "DEFINE-MODIFY-MACRO" 
+      "DEFINE-SETF-EXPANDER" 
+      "DEFINE-SYMBOL-MACRO" 
+      "DEFMACRO" 
+      "DEFMETHOD" 
+      "DEFPACKAGE" 
+      "DEFPARAMETER" 
+      "DEFSETF" 
+      "DEFSTRUCT" 
+      "DEFTYPE" 
+      "DEFUN" 
+      "DEFVAR" 
+      "DELETE" 
+      "DELETE-DUPLICATES" 
+      "DELETE-FILE" 
+      "DELETE-IF" 
+      "DELETE-IF-NOT" 
+      "DELETE-PACKAGE" 
+      "DENOMINATOR" 
+      "DEPOSIT-FIELD" 
+      "DESCRIBE" 
+      "DESCRIBE-OBJECT" 
+      "DESTRUCTURING-BIND" 
+      "DIGIT-CHAR" 
+      "DIGIT-CHAR-P" 
+      "DIRECTORY" 
+      "DIRECTORY-NAMESTRING" 
+      "DISASSEMBLE" 
+      "DIVISION-BY-ZERO" 
+      "DO" 
+      "DO*" 
+      "DO-ALL-SYMBOLS" 
+      "DO-EXTERNAL-SYMBOLS" 
+      "DO-SYMBOLS" 
+      "DOCUMENTATION" 
+      "DOLIST" 
+      "DOTIMES" 
+      "DOUBLE-FLOAT" 
+      "DOUBLE-FLOAT-EPSILON" 
+      "DOUBLE-FLOAT-NEGATIVE-EPSILON" 
+      "DPB" 
+      "DRIBBLE" 
+      "DYNAMIC-EXTENT" 
+      "ECASE" 
+      "ECHO-STREAM" 
+      "ECHO-STREAM-INPUT-STREAM" 
+      "ECHO-STREAM-OUTPUT-STREAM" 
+      "ED" 
+      "EIGHTH" 
+      "ELT" 
+      "ENCODE-UNIVERSAL-TIME" 
+      "END-OF-FILE" 
+      "ENDP" 
+      "ENOUGH-NAMESTRING" 
+      "ENSURE-DIRECTORIES-EXIST" 
+      "ENSURE-GENERIC-FUNCTION" 
+      "EQ" 
+      "EQL" 
+      "EQUAL" 
+      "EQUALP" 
+      "ERROR" 
+      "ETYPECASE" 
+      "EVAL" 
+      "EVAL-WHEN" 
+      "EVENP" 
+      "EVERY" 
+      "EXP" 
+      "EXPORT" 
+      "EXPT" 
+      "EXTENDED-CHAR" 
+      "FBOUNDP" 
+      "FCEILING" 
+      "FDEFINITION" 
+      "FFLOOR" 
+      "FIFTH" 
+      "FILE-AUTHOR" 
+      "FILE-ERROR" 
+      "FILE-ERROR-PATHNAME" 
+      "FILE-LENGTH" 
+      "FILE-NAMESTRING" 
+      "FILE-POSITION" 
+      "FILE-STREAM" 
+      "FILE-STRING-LENGTH" 
+      "FILE-WRITE-DATE" 
+      "FILL" 
+      "FILL-POINTER" 
+      "FIND" 
+      "FIND-ALL-SYMBOLS" 
+      "FIND-CLASS" 
+      "FIND-IF" 
+      "FIND-IF-NOT" 
+      "FIND-METHOD" 
+      "FIND-PACKAGE" 
+      "FIND-RESTART" 
+      "FIND-SYMBOL" 
+      "FINISH-OUTPUT" 
+      "FIRST" 
+      "FIXNUM" 
+      "FLET" 
+      "FLOAT" 
+      "FLOAT-DIGITS" 
+      "FLOAT-PRECISION" 
+      "FLOAT-RADIX" 
+      "FLOAT-SIGN" 
+      "FLOATING-POINT-INEXACT" 
+      "FLOATING-POINT-INVALID-OPERATION" 
+      "FLOATING-POINT-OVERFLOW" 
+      "FLOATING-POINT-UNDERFLOW" 
+      "FLOATP" 
+      "FLOOR" 
+      "FMAKUNBOUND" 
+      "FORCE-OUTPUT" 
+      "FORMAT" 
+      "FORMATTER" 
+      "FOURTH" 
+      "FRESH-LINE" 
+      "FROUND" 
+      "FTRUNCATE" 
+      "FTYPE" 
+      "FUNCALL" 
+      "FUNCTION" 
+      "FUNCTION-KEYWORDS" 
+      "FUNCTION-LAMBDA-EXPRESSION" 
+      "FUNCTIONP" 
+      "GCD" 
+      "GENERIC-FUNCTION" 
+      "GENSYM" 
+      "GENTEMP" 
+      "GET" 
+      "GET-DECODED-TIME" 
+      "GET-DISPATCH-MACRO-CHARACTER" 
+      "GET-INTERNAL-REAL-TIME" 
+      "GET-INTERNAL-RUN-TIME" 
+      "GET-MACRO-CHARACTER" 
+      "GET-OUTPUT-STREAM-STRING" 
+      "GET-PROPERTIES" 
+      "GET-SETF-EXPANSION" 
+      "GET-UNIVERSAL-TIME" 
+      "GETF" 
+      "GETHASH" 
+      "GO" 
+      "GRAPHIC-CHAR-P" 
+      "HANDLER-BIND" 
+      "HANDLER-CASE" 
+      "HASH-TABLE" 
+      "HASH-TABLE-COUNT" 
+      "HASH-TABLE-P" 
+      "HASH-TABLE-REHASH-SIZE" 
+      "HASH-TABLE-REHASH-THRESHOLD" 
+      "HASH-TABLE-SIZE" 
+      "HASH-TABLE-TEST" 
+      "HOST-NAMESTRING" 
+      "IDENTITY" 
+      "IF" 
+      "IGNORABLE" 
+      "IGNORE" 
+      "IGNORE-ERRORS" 
+      "IMAGPART" 
+      "IMPORT" 
+      "IN-PACKAGE" 
+      "INCF" 
+      "INITIALIZE-INSTANCE" 
+      "INLINE" 
+      "INPUT-STREAM-P" 
+      "INSPECT" 
+      "INTEGER" 
+      "INTEGER-DECODE-FLOAT" 
+      "INTEGER-LENGTH" 
+      "INTEGERP" 
+      "INTERACTIVE-STREAM-P" 
+      "INTERN" 
+      "INTERNAL-TIME-UNITS-PER-SECOND" 
+      "INTERSECTION" 
+      "INVALID-METHOD-ERROR" 
+      "INVOKE-DEBUGGER" 
+      "INVOKE-RESTART" 
+      "INVOKE-RESTART-INTERACTIVELY" 
+      "ISQRT" 
+      "KEYWORD" 
+      "KEYWORDP" 
+      "LABELS" 
+      "LAMBDA" 
+      "LAMBDA-LIST-KEYWORDS" 
+      "LAMBDA-PARAMETERS-LIMIT" 
+      "LAST" 
+      "LCM" 
+      "LDB" 
+      "LDB-TEST" 
+      "LDIFF" 
+      "LEAST-NEGATIVE-DOUBLE-FLOAT" 
+      "LEAST-NEGATIVE-LONG-FLOAT" 
+      "LEAST-NEGATIVE-NORMALIZED-DOUBLE-FLOAT" 
+      "LEAST-NEGATIVE-NORMALIZED-LONG-FLOAT" 
+      "LEAST-NEGATIVE-NORMALIZED-SHORT-FLOAT" 
+      "LEAST-NEGATIVE-NORMALIZED-SINGLE-FLOAT" 
+      "LEAST-NEGATIVE-SHORT-FLOAT" 
+      "LEAST-NEGATIVE-SINGLE-FLOAT" 
+      "LEAST-POSITIVE-DOUBLE-FLOAT" 
+      "LEAST-POSITIVE-LONG-FLOAT" 
+      "LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT" 
+      "LEAST-POSITIVE-NORMALIZED-LONG-FLOAT" 
+      "LEAST-POSITIVE-NORMALIZED-SHORT-FLOAT" 
+      "LEAST-POSITIVE-NORMALIZED-SINGLE-FLOAT" 
+      "LEAST-POSITIVE-SHORT-FLOAT" 
+      "LEAST-POSITIVE-SINGLE-FLOAT" 
+      "LENGTH" 
+      "LET" 
+      "LET*" 
+      "LISP-IMPLEMENTATION-TYPE" 
+      "LISP-IMPLEMENTATION-VERSION" 
+      "LIST" 
+      "LIST*" 
+      "LIST-ALL-PACKAGES" 
+      "LIST-LENGTH" 
+      "LISTEN" 
+      "LISTP" 
+      "LOAD" 
+      "LOAD-LOGICAL-PATHNAME-TRANSLATIONS" 
+      "LOAD-TIME-VALUE" 
+      "LOCALLY" 
+      "LOG" 
+      "LOGAND" 
+      "LOGANDC1" 
+      "LOGANDC2" 
+      "LOGBITP" 
+      "LOGCOUNT" 
+      "LOGEQV" 
+      "LOGICAL-PATHNAME" 
+      "LOGICAL-PATHNAME-TRANSLATIONS" 
+      "LOGIOR" 
+      "LOGNAND" 
+      "LOGNOR" 
+      "LOGNOT" 
+      "LOGORC1" 
+      "LOGORC2" 
+      "LOGTEST" 
+      "LOGXOR" 
+      "LONG-FLOAT" 
+      "LONG-FLOAT-EPSILON" 
+      "LONG-FLOAT-NEGATIVE-EPSILON" 
+      "LONG-SITE-NAME" 
+      "LOOP" 
+      "LOOP-FINISH" 
+      "LOWER-CASE-P" 
+      "MACHINE-INSTANCE" 
+      "MACHINE-TYPE" 
+      "MACHINE-VERSION" 
+      "MACRO-FUNCTION" 
+      "MACROEXPAND" 
+      "MACROEXPAND-1" 
+      "MACROLET" 
+      "MAKE-ARRAY" 
+      "MAKE-BROADCAST-STREAM" 
+      "MAKE-CONCATENATED-STREAM" 
+      "MAKE-CONDITION" 
+      "MAKE-DISPATCH-MACRO-CHARACTER" 
+      "MAKE-ECHO-STREAM" 
+      "MAKE-HASH-TABLE" 
+      "MAKE-INSTANCE" 
+      "MAKE-INSTANCES-OBSOLETE" 
+      "MAKE-LIST" 
+      "MAKE-LOAD-FORM" 
+      "MAKE-LOAD-FORM-SAVING-SLOTS" 
+      "MAKE-METHOD" 
+      "MAKE-PACKAGE" 
+      "MAKE-PATHNAME" 
+      "MAKE-RANDOM-STATE" 
+      "MAKE-SEQUENCE" 
+      "MAKE-STRING" 
+      "MAKE-STRING-INPUT-STREAM" 
+      "MAKE-STRING-OUTPUT-STREAM" 
+      "MAKE-SYMBOL" 
+      "MAKE-SYNONYM-STREAM" 
+      "MAKE-TWO-WAY-STREAM" 
+      "MAKUNBOUND" 
+      "MAP" 
+      "MAP-INTO" 
+      "MAPC" 
+      "MAPCAN" 
+      "MAPCAR" 
+      "MAPCON" 
+      "MAPHASH" 
+      "MAPL" 
+      "MAPLIST" 
+      "MASK-FIELD" 
+      "MAX" 
+      "MEMBER" 
+      "MEMBER-IF" 
+      "MEMBER-IF-NOT" 
+      "MERGE" 
+      "MERGE-PATHNAMES" 
+      "METHOD" 
+      "METHOD-COMBINATION" 
+      "METHOD-COMBINATION-ERROR" 
+      "METHOD-QUALIFIERS" 
+      "MIN" 
+      "MINUSP" 
+      "MISMATCH" 
+      "MOD" 
+      "MOST-NEGATIVE-DOUBLE-FLOAT" 
+      "MOST-NEGATIVE-FIXNUM" 
+      "MOST-NEGATIVE-LONG-FLOAT" 
+      "MOST-NEGATIVE-SHORT-FLOAT" 
+      "MOST-NEGATIVE-SINGLE-FLOAT" 
+      "MOST-POSITIVE-DOUBLE-FLOAT" 
+      "MOST-POSITIVE-FIXNUM" 
+      "MOST-POSITIVE-LONG-FLOAT" 
+      "MOST-POSITIVE-SHORT-FLOAT" 
+      "MOST-POSITIVE-SINGLE-FLOAT" 
+      "MUFFLE-WARNING" 
+      "MULTIPLE-VALUE-BIND" 
+      "MULTIPLE-VALUE-CALL" 
+      "MULTIPLE-VALUE-LIST" 
+      "MULTIPLE-VALUE-PROG1" 
+      "MULTIPLE-VALUE-SETQ" 
+      "MULTIPLE-VALUES-LIMIT" 
+      "NAME-CHAR" 
+      "NAMESTRING" 
+      "NBUTLAST" 
+      "NCONC" 
+      "NEXT-METHOD-P" 
+      "NIL" 
+      "NINTERSECTION" 
+      "NINTH" 
+      "NO-APPLICABLE-METHOD" 
+      "NO-NEXT-METHOD" 
+      "NOT" 
+      "NOTANY" 
+      "NOTEVERY" 
+      "NOTINLINE" 
+      "NRECONC" 
+      "NREVERSE" 
+      "NSET-DIFFERENCE" 
+      "NSET-EXCLUSIVE-OR" 
+      "NSTRING-CAPITALIZE" 
+      "NSTRING-DOWNCASE" 
+      "NSTRING-UPCASE" 
+      "NSUBLIS" 
+      "NSUBST" 
+      "NSUBST-IF" 
+      "NSUBST-IF-NOT" 
+      "NSUBSTITUTE" 
+      "NSUBSTITUTE-IF" 
+      "NSUBSTITUTE-IF-NOT" 
+      "NTH" 
+      "NTH-VALUE" 
+      "NTHCDR" 
+      "NULL" 
+      "NUMBER" 
+      "NUMBERP" 
+      "NUMERATOR" 
+      "NUNION" 
+      "ODDP" 
+      "OPEN" 
+      "OPEN-STREAM-P" 
+      "OPTIMIZE" 
+      "OR" 
+      "OTHERWISE" 
+      "OUTPUT-STREAM-P" 
+      "PACKAGE" 
+      "PACKAGE-ERROR" 
+      "PACKAGE-ERROR-PACKAGE" 
+      "PACKAGE-NAME" 
+      "PACKAGE-NICKNAMES" 
+      "PACKAGE-SHADOWING-SYMBOLS" 
+      "PACKAGE-USE-LIST" 
+      "PACKAGE-USED-BY-LIST" 
+      "PACKAGEP" 
+      "PAIRLIS" 
+      "PARSE-ERROR" 
+      "PARSE-INTEGER" 
+      "PARSE-NAMESTRING" 
+      "PATHNAME" 
+      "PATHNAME-DEVICE" 
+      "PATHNAME-DIRECTORY" 
+      "PATHNAME-HOST" 
+      "PATHNAME-MATCH-P" 
+      "PATHNAME-NAME" 
+      "PATHNAME-TYPE" 
+      "PATHNAME-VERSION" 
+      "PATHNAMEP" 
+      "PEEK-CHAR" 
+      "PHASE" 
+      "PI" 
+      "PLUSP" 
+      "POP" 
+      "POSITION" 
+      "POSITION-IF" 
+      "POSITION-IF-NOT" 
+      "PPRINT" 
+      "PPRINT-DISPATCH" 
+      "PPRINT-EXIT-IF-LIST-EXHAUSTED" 
+      "PPRINT-FILL" 
+      "PPRINT-INDENT" 
+      "PPRINT-LINEAR" 
+      "PPRINT-LOGICAL-BLOCK" 
+      "PPRINT-NEWLINE" 
+      "PPRINT-POP" 
+      "PPRINT-TAB" 
+      "PPRINT-TABULAR" 
+      "PRIN1" 
+      "PRIN1-TO-STRING" 
+      "PRINC" 
+      "PRINC-TO-STRING" 
+      "PRINT" 
+      "PRINT-NOT-READABLE" 
+      "PRINT-NOT-READABLE-OBJECT" 
+      "PRINT-OBJECT" 
+      "PRINT-UNREADABLE-OBJECT" 
+      "PROBE-FILE" 
+      "PROCLAIM" 
+      "PROG" 
+      "PROG*" 
+      "PROG1" 
+      "PROG2" 
+      "PROGN" 
+      "PROGRAM-ERROR" 
+      "PROGV" 
+      "PROVIDE" 
+      "PSETF" 
+      "PSETQ" 
+      "PUSH" 
+      "PUSHNEW" 
+      "QUOTE" 
+      "RANDOM" 
+      "RANDOM-STATE" 
+      "RANDOM-STATE-P" 
+      "RASSOC" 
+      "RASSOC-IF" 
+      "RASSOC-IF-NOT" 
+      "RATIO" 
+      "RATIONAL" 
+      "RATIONALIZE" 
+      "RATIONALP" 
+      "READ" 
+      "READ-BYTE" 
+      "READ-CHAR" 
+      "READ-CHAR-NO-HANG" 
+      "READ-DELIMITED-LIST" 
+      "READ-FROM-STRING" 
+      "READ-LINE" 
+      "READ-PRESERVING-WHITESPACE" 
+      "READ-SEQUENCE" 
+      "READER-ERROR" 
+      "READTABLE" 
+      "READTABLE-CASE" 
+      "READTABLEP" 
+      "REAL" 
+      "REALP" 
+      "REALPART" 
+      "REDUCE" 
+      "REINITIALIZE-INSTANCE" 
+      "REM" 
+      "REMF" 
+      "REMHASH" 
+      "REMOVE" 
+      "REMOVE-DUPLICATES" 
+      "REMOVE-IF" 
+      "REMOVE-IF-NOT" 
+      "REMOVE-METHOD" 
+      "REMPROP" 
+      "RENAME-FILE" 
+      "RENAME-PACKAGE" 
+      "REPLACE" 
+      "REQUIRE" 
+      "REST" 
+      "RESTART" 
+      "RESTART-BIND" 
+      "RESTART-CASE" 
+      "RESTART-NAME" 
+      "RETURN" 
+      "RETURN-FROM" 
+      "REVAPPEND" 
+      "REVERSE" 
+      "ROOM" 
+      "ROTATEF" 
+      "ROUND" 
+      "ROW-MAJOR-AREF" 
+      "RPLACA" 
+      "RPLACD" 
+      "SAFETY" 
+      "SATISFIES" 
+      "SBIT" 
+      "SCALE-FLOAT" 
+      "SCHAR" 
+      "SEARCH" 
+      "SECOND" 
+      "SEQUENCE" 
+      "SERIOUS-CONDITION" 
+      "SET" 
+      "SET-DIFFERENCE" 
+      "SET-DISPATCH-MACRO-CHARACTER" 
+      "SET-EXCLUSIVE-OR" 
+      "SET-MACRO-CHARACTER" 
+      "SET-PPRINT-DISPATCH" 
+      "SET-SYNTAX-FROM-CHAR" 
+      "SETF" 
+      "SETQ" 
+      "SEVENTH" 
+      "SHADOW" 
+      "SHADOWING-IMPORT" 
+      "SHARED-INITIALIZE" 
+      "SHIFTF" 
+      "SHORT-FLOAT" 
+      "SHORT-FLOAT-EPSILON" 
+      "SHORT-FLOAT-NEGATIVE-EPSILON" 
+      "SHORT-SITE-NAME" 
+      "SIGNAL" 
+      "SIGNED-BYTE" 
+      "SIGNUM" 
+      "SIMPLE-ARRAY" 
+      "SIMPLE-BASE-STRING" 
+      "SIMPLE-BIT-VECTOR" 
+      "SIMPLE-BIT-VECTOR-P" 
+      "SIMPLE-CONDITION" 
+      "SIMPLE-CONDITION-FORMAT-ARGUMENTS" 
+      "SIMPLE-CONDITION-FORMAT-CONTROL" 
+      "SIMPLE-ERROR" 
+      "SIMPLE-STRING" 
+      "SIMPLE-STRING-P" 
+      "SIMPLE-TYPE-ERROR" 
+      "SIMPLE-VECTOR" 
+      "SIMPLE-VECTOR-P" 
+      "SIMPLE-WARNING" 
+      "SIN" 
+      "SINGLE-FLOAT" 
+      "SINGLE-FLOAT-EPSILON" 
+      "SINGLE-FLOAT-NEGATIVE-EPSILON" 
+      "SINH" 
+      "SIXTH" 
+      "SLEEP" 
+      "SLOT-BOUNDP" 
+      "SLOT-EXISTS-P" 
+      "SLOT-MAKUNBOUND" 
+      "SLOT-MISSING" 
+      "SLOT-UNBOUND" 
+      "SLOT-VALUE" 
+      "SOFTWARE-TYPE" 
+      "SOFTWARE-VERSION" 
+      "SOME" 
+      "SORT" 
+      "SPACE" 
+      "SPECIAL" 
+      "SPECIAL-OPERATOR-P" 
+      "SPEED" 
+      "SQRT" 
+      "STABLE-SORT" 
+      "STANDARD" 
+      "STANDARD-CHAR" 
+      "STANDARD-CHAR-P" 
+      "STANDARD-CLASS" 
+      "STANDARD-GENERIC-FUNCTION" 
+      "STANDARD-METHOD" 
+      "STANDARD-OBJECT" 
+      "STEP" 
+      "STORAGE-CONDITION" 
+      "STORE-VALUE" 
+      "STREAM" 
+      "STREAM-ELEMENT-TYPE" 
+      "STREAM-ERROR" 
+      "STREAM-ERROR-STREAM" 
+      "STREAM-EXTERNAL-FORMAT" 
+      "STREAMP" 
+      "STRING" 
+      "STRING-CAPITALIZE" 
+      "STRING-DOWNCASE" 
+      "STRING-EQUAL" 
+      "STRING-GREATERP" 
+      "STRING-LEFT-TRIM" 
+      "STRING-LESSP" 
+      "STRING-NOT-EQUAL" 
+      "STRING-NOT-GREATERP" 
+      "STRING-NOT-LESSP" 
+      "STRING-RIGHT-TRIM" 
+      "STRING-STREAM" 
+      "STRING-TRIM" 
+      "STRING-UPCASE" 
+      "STRING/=" 
+      "STRING<" 
+      "STRING<=" 
+      "STRING=" 
+      "STRING>" 
+      "STRING>=" 
+      "STRINGP" 
+      "STRUCTURE" 
+      "STRUCTURE-CLASS" 
+      "STRUCTURE-OBJECT" 
+      "STYLE-WARNING" 
+      "SUBLIS" 
+      "SUBSEQ" 
+      "SUBSETP" 
+      "SUBST" 
+      "SUBST-IF" 
+      "SUBST-IF-NOT" 
+      "SUBSTITUTE" 
+      "SUBSTITUTE-IF" 
+      "SUBSTITUTE-IF-NOT" 
+      "SUBTYPEP" 
+      "SVREF" 
+      "SXHASH" 
+      "SYMBOL" 
+      "SYMBOL-FUNCTION" 
+      "SYMBOL-MACROLET" 
+      "SYMBOL-NAME" 
+      "SYMBOL-PACKAGE" 
+      "SYMBOL-PLIST" 
+      "SYMBOL-VALUE" 
+      "SYMBOLP" 
+      "SYNONYM-STREAM" 
+      "SYNONYM-STREAM-SYMBOL" 
+      "T" 
+      "TAGBODY" 
+      "TAILP" 
+      "TAN" 
+      "TANH" 
+      "TENTH" 
+      "TERPRI" 
+      "THE" 
+      "THIRD" 
+      "THROW" 
+      "TIME" 
+      "TRACE" 
+      "TRANSLATE-LOGICAL-PATHNAME" 
+      "TRANSLATE-PATHNAME" 
+      "TREE-EQUAL" 
+      "TRUENAME" 
+      "TRUNCATE" 
+      "TWO-WAY-STREAM" 
+      "TWO-WAY-STREAM-INPUT-STREAM" 
+      "TWO-WAY-STREAM-OUTPUT-STREAM" 
+      "TYPE" 
+      "TYPE-ERROR" 
+      "TYPE-ERROR-DATUM" 
+      "TYPE-ERROR-EXPECTED-TYPE" 
+      "TYPE-OF" 
+      "TYPECASE" 
+      "TYPEP" 
+      "UNBOUND-SLOT" 
+      "UNBOUND-SLOT-INSTANCE" 
+      "UNBOUND-VARIABLE" 
+      "UNDEFINED-FUNCTION" 
+      "UNEXPORT" 
+      "UNINTERN" 
+      "UNION" 
+      "UNLESS" 
+      "UNREAD-CHAR" 
+      "UNSIGNED-BYTE" 
+      "UNTRACE" 
+      "UNUSE-PACKAGE" 
+      "UNWIND-PROTECT" 
+      "UPDATE-INSTANCE-FOR-DIFFERENT-CLASS" 
+      "UPDATE-INSTANCE-FOR-REDEFINED-CLASS" 
+      "UPGRADED-ARRAY-ELEMENT-TYPE" 
+      "UPGRADED-COMPLEX-PART-TYPE" 
+      "UPPER-CASE-P" 
+      "USE-PACKAGE" 
+      "USE-VALUE" 
+      "USER-HOMEDIR-PATHNAME" 
+      "VALUES" 
+      "VALUES-LIST" 
+      "VARIABLE" 
+      "VECTOR" 
+      "VECTOR-POP" 
+      "VECTOR-PUSH" 
+      "VECTOR-PUSH-EXTEND" 
+      "VECTORP" 
+      "WARN" 
+      "WARNING" 
+      "WHEN" 
+      "WILD-PATHNAME-P" 
+      "WITH-ACCESSORS" 
+      "WITH-COMPILATION-UNIT" 
+      "WITH-CONDITION-RESTARTS" 
+      "WITH-HASH-TABLE-ITERATOR" 
+      "WITH-INPUT-FROM-STRING" 
+      "WITH-OPEN-FILE" 
+      "WITH-OPEN-STREAM" 
+      "WITH-OUTPUT-TO-STRING" 
+      "WITH-PACKAGE-ITERATOR" 
+      "WITH-SIMPLE-RESTART" 
+      "WITH-SLOTS" 
+      "WITH-STANDARD-IO-SYNTAX" 
+      "WRITE" 
+      "WRITE-BYTE" 
+      "WRITE-CHAR" 
+      "WRITE-LINE" 
+      "WRITE-SEQUENCE" 
+      "WRITE-STRING" 
+      "WRITE-TO-STRING" 
+      "Y-OR-N-P" 
+      "YES-OR-NO-P" 
+      "ZEROP"
+      )
+    ))
+
+(let* ((pkg *common-lisp-package*)
+       (etab (pkg.etab pkg))
+       (itab (pkg.itab pkg)))
+  (without-interrupts
+   (dolist (name '#.%lisp-symbols%)
+     (let* ((namelen (length name)))
+       (multiple-value-bind (found-int symbol int-offset)
+                            (%get-htab-symbol name namelen itab)
+         (multiple-value-bind (found-ext ignore ext-offset)
+                              (%get-htab-symbol name namelen etab)
+           (declare (ignore ignore))
+           (if found-int                ; This shouldn't happen.
+             (progn
+               (setf (%svref (car itab) int-offset) (%unbound-marker-8))
+               (%htab-add-symbol symbol etab ext-offset))
+             (unless found-ext
+               (%add-symbol name pkg int-offset ext-offset t)))))))))
Index: /branches/new-random/level-1/l1-clos-boot.lisp
===================================================================
--- /branches/new-random/level-1/l1-clos-boot.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-clos-boot.lisp	(revision 13309)
@@ -0,0 +1,3860 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+
+;;; l1-clos-boot.lisp
+
+
+(in-package "CCL")
+
+
+;;; Early accessors.  These functions eventually all get replaced with
+;;; generic functions with "real", official names.
+
+
+(declaim (inline instance-slots %non-standard-instance-slots))
+(defun %non-standard-instance-slots (instance typecode)
+  (cond ((eql typecode target::subtag-macptr) (foreign-slots-vector instance))
+        ((or (typep instance 'standard-generic-function)
+             (typep instance 'funcallable-standard-object))
+         (gf.slots instance))
+        (t  (error "Don't know how to find slots of ~s" instance))))
+
+(defun instance-slots (instance)
+  (let* ((typecode (typecode instance)))
+    (cond ((eql typecode target::subtag-instance) (instance.slots instance))
+          (t (%non-standard-instance-slots instance typecode)))))
+
+
+;;; True if X is a class but not a foreign-class.
+(defun native-class-p (x)
+  (if (%standard-instance-p x)
+    (< (the fixnum (instance.hash x)) max-class-ordinal)))
+
+(defun %class-name (class)
+  (if (native-class-p class)
+    (%class.name class)
+    (class-name class)))
+
+(defun %class-info (class)
+  (if (native-class-p class)
+    (%class.info class)
+    (class-info class)))
+  
+
+(defun %class-kernel-p (class)
+  (car (%class-info class)))
+
+(defun (setf %class-kernel-p) (new class)
+  (setf (car (%class-info class)) new))
+
+(defun %class-proper-name (class)
+  (cdr (%class-info class)))
+
+(defun (setf %class-proper-name) (new class)
+  (setf (cdr (%class-info class)) new))
+
+
+(defun %class-own-wrapper (class)
+  (if (native-class-p class)
+    (%class.own-wrapper class)
+   (class-own-wrapper class)))
+
+(defun (setf %class-own-wrapper) (new class)
+  (setf (%class.own-wrapper class) new))
+
+(defun %class-alist (class)
+  (%class.alist class))
+
+(defun (setf %class-alist) (new class)
+  (if (typep class 'slots-class)
+    (setf (%class.alist class) new)
+    new))
+
+(defun %class-slots (class)
+  (if (native-class-p class)
+    (%class.slots class)
+    (class-slots class)))
+
+(defun (setf %class-slots) (new class)
+  (if (native-class-p class)
+    (setf (%class.slots class) new)
+    (setf (class-slots class) new)))
+
+(defun %class-direct-slots (class)
+  (if (native-class-p class)
+    (%class.direct-slots class)
+    (class-direct-slots class)))
+
+(defun (setf %class-direct-slots) (new class)
+  (if (native-class-p class)
+    (setf (%class.direct-slots class) new)
+    (setf (class-direct-slots class) new)))
+
+
+
+
+
+
+(defun %class-direct-superclasses (class)
+  (%class.local-supers class))
+
+(defun (setf %class-direct-superclasses) (new class)
+  (setf (%class.local-supers class) new))
+
+(defun %class-direct-subclasses (class)
+  (%class.subclasses class))
+
+(defun (setf %class-direct-subclasses) (new class)
+  (setf (%class.subclasses class) new))
+
+(defun %class-direct-default-initargs (class)
+  (if (typep class 'std-class)
+    (%class.local-default-initargs class)))
+
+(defun (setf %class-direct-default-initargs) (new class)
+  (if (typep class 'std-class)
+    (setf (%class.local-default-initargs class) new)
+    new))
+  
+
+(defun %class-default-initargs (class)
+  (if (typep class 'std-class)
+    (%class.default-initargs class)))
+
+
+(defun (setf %class-default-initargs) (new class)
+  (setf (%class.default-initargs class) new))
+
+(defun %slot-definition-name (slotd)
+  (standard-slot-definition.name slotd))
+
+
+(defun %slot-definition-type (slotd)
+  (standard-slot-definition.type slotd))
+
+(defun %slot-definition-initargs (slotd)
+  (standard-slot-definition.initargs slotd))
+
+
+(defun %slot-definition-initform (slotd)
+  (standard-slot-definition.initform slotd))
+
+(defun %slot-definition-initfunction (slotd)
+  (standard-slot-definition.initfunction slotd))
+
+(defun %slot-definition-allocation (slotd)
+  (standard-slot-definition.allocation slotd))
+
+(defun %slot-definition-class (slotd)
+  (standard-slot-definition.class slotd))
+
+;;; Returns (VALUES BOUNDP VALUE).
+(defun %slot-definition-documentation (slotd)
+  (let* ((val (%standard-instance-instance-location-access
+	       slotd
+	       standard-slot-definition.documentation)))
+    (if (eq val (%slot-unbound-marker))
+      (values nil nil)
+      (values t val))))
+
+
+(defun %slot-definition-location (slotd)
+  (standard-effective-slot-definition.location slotd))
+
+(defun (setf %slot-definition-location) (new slotd)
+  (setf (standard-effective-slot-definition.location slotd) new))
+
+(defun %slot-definition-readers (slotd)
+  (standard-direct-slot-definition.readers slotd))
+
+(defun (setf %slot-definition-readers) (new slotd)
+  (setf (standard-direct-slot-definition.readers slotd) new))
+
+(defun %slot-definition-writers (slotd)
+  (standard-direct-slot-definition.writers slotd))
+
+(defun (setf %slot-definition-writers) (new slotd)
+  (setf (standard-direct-slot-definition.writers slotd) new))
+
+(defun %generic-function-name (gf)
+  (sgf.name gf))
+
+(defun %generic-function-method-combination (gf)
+  (sgf.method-combination gf))
+
+(defun %generic-function-method-class (gf)
+  (sgf.method-class gf))
+
+
+(defun %method-qualifiers (m)
+  (%method.qualifiers m))
+
+(defun %method-specializers (m)
+  (%method.specializers m))
+
+(defun %method-function (m)
+  (%method.function m))
+
+(defun (setf %method-function) (new m)
+  (setf (%method.function m) new))
+
+(defun %method-gf (m)
+  (%method.gf m))
+
+(defun (setf %method-gf) (new m)
+  (setf (%method.gf m) new))
+
+(defun %method-name (m)
+  (%method.name m))
+
+(defun %method-lambda-list (m)
+  (%method.lambda-list m))
+
+
+
+;;; Map slot-names (symbols) to SLOT-ID objects (which contain unique indices).
+(let* ((slot-id-lock (make-lock))
+       (next-slot-index 1)              ; 0 is never a valid slot-index
+       (slot-id-hash (make-hash-table :test #'eq :weak t)))
+  (defun ensure-slot-id (slot-name)
+    (setq slot-name (require-type slot-name 'symbol))
+    (with-lock-grabbed (slot-id-lock)
+      (or (gethash slot-name slot-id-hash)
+          (setf (gethash slot-name slot-id-hash)
+                (%istruct 'slot-id slot-name (prog1
+                                                 next-slot-index
+                                               (incf next-slot-index)))))))
+  (defun current-slot-index () (with-lock-grabbed (slot-id-lock)
+                                 next-slot-index))
+  )
+
+
+
+
+(defun %slot-id-lookup-obsolete (instance slot-id)
+  (update-obsolete-instance instance)
+  (funcall (%wrapper-slot-id->slotd (instance.class-wrapper instance))
+           instance slot-id))
+(defun slot-id-lookup-no-slots (instance slot-id)
+  (declare (ignore instance slot-id)))
+
+(defun %slot-id-ref-obsolete (instance slot-id)
+  (update-obsolete-instance instance)
+  (funcall (%wrapper-slot-id-value (instance.class-wrapper instance))
+           instance slot-id))
+(defun %slot-id-ref-missing (instance slot-id)
+  (values (slot-missing (class-of instance) instance (slot-id.name slot-id) 'slot-value)))
+
+(defun %slot-id-set-obsolete (instance slot-id new-value)
+  (update-obsolete-instance instance)
+  (funcall (%wrapper-set-slot-id-value (instance.class-wrapper instance))
+           instance slot-id new-value))
+
+(defun %slot-id-set-missing (instance slot-id new-value)
+  (slot-missing (class-of instance) instance (slot-id.name slot-id) 'setf new-value)
+  new-value
+  )
+
+
+
+
+;;; This becomes (apply #'make-instance <method-class> &rest args).
+(fset '%make-method-instance
+      (nlambda bootstrapping-%make-method-instance (class &key
+                                                          qualifiers
+                                                          specializers
+                                                          function
+                                                          name
+                                                          lambda-list
+                                                          &allow-other-keys)
+        (let* ((method
+                (%instance-vector (%class-own-wrapper class)
+                                  qualifiers
+                                  specializers
+                                  function
+                                  nil
+                                  name
+                                  lambda-list)))
+          (when function
+            (let* ((inner (closure-function function)))
+              (unless (eq inner function)
+                (copy-method-function-bits inner function)))
+            (lfun-name function method))
+          method)))
+  
+       
+		 
+(defun encode-lambda-list (l &optional return-keys?)
+  (multiple-value-bind (ok req opttail resttail keytail auxtail)
+                       (verify-lambda-list l)
+    (when ok
+      (let* ((bits 0)
+             (temp nil)
+             (nreq (length req))
+             (num-opt 0)
+             (rest nil)
+             (lexpr nil)
+             (keyp nil)
+             (key-list nil)
+             (aokp nil)
+             (hardopt nil))
+        (when (> nreq #.(ldb $lfbits-numreq $lfbits-numreq))
+          (return-from encode-lambda-list nil))
+        (when (eq (pop opttail) '&optional)
+          (until (eq opttail resttail)
+            (when (and (consp (setq temp (pop opttail)))
+                       (%cadr temp))
+              (setq hardopt t))
+            (setq num-opt (%i+ num-opt 1))))
+        (when (eq (%car resttail) '&rest)
+          (setq rest t))
+        (when (eq (%car resttail) '&lexpr)
+          (setq lexpr t))
+        (when (eq (pop keytail) '&key)
+          (setq keyp t)
+          (labels ((ensure-symbol (x)
+                     (if (symbolp x) x (return-from encode-lambda-list nil)))
+                   (ensure-keyword (x)
+                     (make-keyword (ensure-symbol x))))
+            (declare (dynamic-extent #'ensure-symbol #'ensure-keyword))
+            (until (eq keytail auxtail)
+              (setq temp (pop keytail))
+              (if (eq temp '&allow-other-keys)
+                (progn
+                  (setq aokp t)
+                  (unless (eq keytail auxtail)
+                    (return-from encode-lambda-list nil)))
+                (when return-keys?
+                  (push (if (consp temp)
+                          (if (consp (setq temp (%car temp))) 
+                            (ensure-symbol (%car temp))
+                            (ensure-keyword temp))
+                          (ensure-keyword temp))
+                        key-list))))))
+        (when (%i> nreq (ldb $lfbits-numreq -1))
+          (setq nreq (ldb $lfbits-numreq -1)))
+        (setq bits (dpb nreq $lfbits-numreq bits))
+        (when (%i> num-opt (ldb $lfbits-numopt -1))
+          (setq num-opt (ldb $lfbits-numopt -1)))
+        (setq bits (dpb num-opt $lfbits-numopt bits))
+        (when hardopt (setq bits (%ilogior (%ilsl $lfbits-optinit-bit 1) bits)))
+        (when rest (setq bits (%ilogior (%ilsl $lfbits-rest-bit 1) bits)))
+        (when lexpr (setq bits (%ilogior (%ilsl $lfbits-restv-bit 1) bits)))
+        (when keyp (setq bits (%ilogior (%ilsl $lfbits-keys-bit 1) bits)))
+        (when aokp (setq bits (%ilogior (%ilsl $lfbits-aok-bit 1) bits)))
+        (if return-keys?
+          (values bits (and keyp (apply #'vector (nreverse key-list))))
+          bits)))))
+
+(defun pair-arg-p (thing &optional lambda-list-ok supplied-p-ok keyword-nesting-ok)
+  (or (symbol-arg-p thing lambda-list-ok) ; nil ok in destructuring case
+      (and (consp thing)
+           (or (null (%cdr thing))
+               (and (consp (%cdr thing))
+                    (or (null (%cddr thing))
+                        (and supplied-p-ok
+                             (consp (%cddr thing))
+                             (null (%cdddr thing))))))
+           (if (not keyword-nesting-ok)
+             (req-arg-p (%car thing) lambda-list-ok)
+             (or (symbol-arg-p (%car thing) lambda-list-ok)
+                 (and (consp (setq thing (%car thing)))
+                      (consp (%cdr thing))
+                      (null (%cddr thing))
+                      (%car thing)
+                      (symbolp (%car thing))
+                      (req-arg-p (%cadr thing) lambda-list-ok)))))))
+
+(defun req-arg-p (thing &optional lambda-list-ok)
+ (or
+  (symbol-arg-p thing lambda-list-ok)
+  (lambda-list-arg-p thing lambda-list-ok)))
+
+(defun symbol-arg-p (thing nil-ok)
+  (and
+   (symbolp thing)
+   (or thing nil-ok)
+   (not (memq thing lambda-list-keywords))))
+
+(defun lambda-list-arg-p (thing lambda-list-ok)
+  (and 
+   lambda-list-ok
+   (listp thing)
+   (if (verify-lambda-list thing t t)
+     (setq *structured-lambda-list* t))))
+
+(defun opt-arg-p (thing &optional lambda-ok)
+  (pair-arg-p thing lambda-ok t nil))
+
+(defun key-arg-p (thing &optional lambda-ok)
+  (pair-arg-p thing lambda-ok t t))
+
+(defun proclaimed-ignore-p (sym)
+  (cdr (assq sym *nx-proclaimed-ignore*)))
+
+(defun verify-lambda-list (l &optional destructure-p whole-p env-p)
+  (let* ((the-keys lambda-list-keywords)
+         opttail
+         resttail
+         keytail
+         allowothertail
+         auxtail
+         safecopy
+         whole
+         m
+         n
+         req
+         sym
+         (*structured-lambda-list* nil))
+  (prog ()
+    (multiple-value-setq (safecopy whole)
+                         (normalize-lambda-list l whole-p env-p))
+    (unless (or destructure-p (eq l safecopy) (go LOSE)))
+    (setq l safecopy)
+    (unless (dolist (key the-keys t)
+              (when (setq m (cdr (memq key l)))
+                (if (memq key m) (return))))
+      (go LOSE))
+    (if (null l) (go WIN))
+    (setq opttail (memq '&optional l))
+    (setq m (or (memq '&rest l)
+                (unless destructure-p (memq '&lexpr l))))
+    (setq n (if destructure-p (memq '&body l)))
+    (if (and m n) (go LOSE) (setq resttail (or m n)))
+    (setq keytail (memq '&key l))
+    (if (and (setq allowothertail (memq '&allow-other-keys l))
+             (not keytail))
+      (go LOSE))
+    (if (and (eq (car resttail) '&lexpr)
+             (or keytail opttail))
+      (go lose))
+    (setq auxtail (memq '&aux l))
+    (loop
+      (when (null l) (go WIN))
+      (when (or (eq l opttail)
+                (eq l resttail)
+                (eq l keytail)
+                (eq l allowothertail)
+                (eq l auxtail))
+        (return))
+      (setq sym (pop l))
+      (unless (and (req-arg-p sym destructure-p)
+                   (or (proclaimed-ignore-p sym)
+                       (and destructure-p (null sym))
+                       (not (memq sym req))))  ; duplicate required args
+        (go LOSE))
+      (push sym req))
+    (when (eq l opttail)
+      (setq l (%cdr l))
+      (loop
+        (when (null l) (go WIN))
+        (when (or (eq l resttail)
+                  (eq l keytail)
+                  (eq l allowothertail)
+                  (eq l auxtail))
+          (return))
+        (unless (opt-arg-p (pop l) destructure-p)
+          (go LOSE))))
+    (when (eq l resttail)
+      (setq l (%cdr l))
+      (when (or (null l)
+                (eq l opttail)
+                (eq l keytail)
+                (eq l allowothertail)
+                (eq l auxtail))
+        (go LOSE))
+      (unless (req-arg-p (pop l) destructure-p) (go LOSE)))
+    (unless (or (eq l keytail)  ; allowothertail is a sublist of keytail if present
+                (eq l auxtail))
+      (go LOSE))
+    (when (eq l keytail)
+      (pop l)
+      (loop
+        (when (null l) (go WIN))
+        (when (or (eq l opttail)
+                  (eq l resttail))
+          (go LOSE))
+        (when (or (eq l auxtail) (setq n (eq l allowothertail)))
+          (if n (setq l (%cdr l)))
+          (return))
+        (unless (key-arg-p (pop l) destructure-p) (go LOSE))))
+    (when (eq l auxtail)
+      (setq l (%cdr l))
+      (loop
+        (when (null l) (go WIN))
+        (when (or (eq l opttail)
+                  (eq l resttail)
+                  (eq l keytail))
+          (go LOSE))
+        (unless (pair-arg-p (pop l)) (go LOSE))))
+    (when l (go LOSE))
+  WIN
+  (return (values
+           t
+           (nreverse req)
+           (or opttail resttail keytail auxtail)
+           (or resttail keytail auxtail)
+           (or keytail auxtail)
+           auxtail
+           safecopy
+           whole
+           *structured-lambda-list*))
+  LOSE
+  (return (values nil nil nil nil nil nil nil nil nil nil)))))
+
+(defun normalize-lambda-list (x &optional whole-p env-p)
+  (let* ((y x) whole env envtail head)
+    (setq
+     x
+     (loop
+       (when (atom y)
+         (if (or (null y) (eq x y))  (return x))
+         (setq x (copy-list x) y x)
+         (return
+          (loop
+            (when (atom (%cdr y))
+              (%rplacd y (list '&rest (%cdr y)))
+              (return x))
+            (setq y (%cdr y)))))
+       (setq y (%cdr y))))
+    (when env-p
+      ;; Trapped in a world it never made ... 
+      (when (setq y (memq '&environment x))
+        (setq envtail (%cddr y)
+              env (%cadr y))
+        (cond ((eq y x)
+               (setq x envtail))
+              (t
+               (dolist (v x)
+                 (if (eq v '&environment)
+                   (return)
+                   (push v head)))
+               (setq x (nconc (nreverse head) envtail) y (%car envtail))))))
+    (when (and whole-p 
+               (eq (%car x) '&whole)
+               (%cadr x))
+      (setq whole (%cadr x) x (%cddr x)))
+    (values x whole env)))
+
+
+
+
+(eval-when (eval compile)
+  (require 'defstruct-macros))
+
+(eval-when (:compile-toplevel :execute)
+  (defmacro make-instance-vector (wrapper len)
+    (let* ((instance (gensym))
+	   (slots (gensym)))
+      `(let* ((,slots (allocate-typed-vector :slot-vector (1+ ,len) (%slot-unbound-marker)))
+	      (,instance (gvector :instance 0 ,wrapper ,slots)))
+	(setf (instance.hash ,instance) (strip-tag-to-fixnum ,instance)
+	      (slot-vector.instance ,slots) ,instance))))
+)
+
+(eval-when (:compile-toplevel :execute)
+  (defmacro make-structure-vector (size)
+    `(%alloc-misc ,size target::subtag-struct nil))
+
+)
+;;;;;;;;;;;;;;;;;;;;;;;;;;; defmethod support ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(%fhave '%move-method-encapsulations-maybe ; Redefined in encapsulate
+        (qlfun boot-%move-method-encapsulations-maybe (m1 m2)
+          (declare (ignore m1 m2))
+          nil))
+
+(%fhave 'find-unencapsulated-definition  ;Redefined in encapsulate
+        (qlfun bootstrapping-find-unencapsulated-definition (fn)
+	  fn))
+
+(%fhave 'function-encapsulated-p  ;Redefined in encapsulate
+        (qlfun bootstrapping-function-encapsulated-p (fn)
+	  (declare (ignore fn))
+          nil))
+
+(defparameter *uniquify-dcode* #+unique-dcode t #-unique-dcode nil
+  "If true, each gf will get its own unique copy of its dcode.  Not recommended for
+   real use (for one thing, it's known to break gf tracing), but may be helpful for
+   profiling")
+
+(let* ((class-wrapper-random-state (make-random-state))
+       (class-wrapper-random-state-lock (make-lock)))
+
+  (defun  new-class-wrapper-hash-index ()
+    ;; mustn't be 0
+    (with-lock-grabbed (class-wrapper-random-state-lock)
+      (the fixnum (1+ (the fixnum (random target::target-most-positive-fixnum class-wrapper-random-state)))))))
+
+
+(defun %inner-method-function (method)
+  (closure-function
+   (find-unencapsulated-definition
+    (%method-function method))))
+
+(defun copy-method-function-bits (from to)
+  (let ((new-bits (logior (logand (logior (lsh 1 $lfbits-method-bit)
+                                          (ash 1 $lfbits-nextmeth-bit)
+                                          (ash 1 $lfbits-nextmeth-with-args-bit)
+                                          $lfbits-args-mask) 
+                                  (lfun-bits from))
+                          (logand (lognot (logior (lsh 1 $lfbits-method-bit)
+                                                  (ash 1 $lfbits-nextmeth-bit)
+                                                  (ash 1 $lfbits-nextmeth-with-args-bit)
+                                                  $lfbits-args-mask))
+                                  (lfun-bits to)))))
+    (lfun-bits to new-bits)
+    new-bits))
+
+(defun %ensure-generic-function-using-class (gf function-name &rest keys
+						&key 
+						&allow-other-keys)
+  (if gf
+    (apply #'%ensure-existing-generic-function-using-class gf function-name keys)
+    (apply #'%ensure-new-generic-function-using-class function-name keys)))
+
+(defun ensure-generic-function (function-name &rest keys &key &allow-other-keys)
+  (let* ((def (fboundp function-name)))
+    (when (and def (not (typep def 'generic-function)))
+      (cerror "Try to remove any global non-generic function or macro definition."
+	      (make-condition 'simple-program-error :format-control "The function ~s is defined as something other than a generic function." :format-arguments (list function-name)))
+      (fmakunbound function-name)
+      (setq def nil))
+    (apply #'%ensure-generic-function-using-class def function-name keys)))
+
+
+(defun %ensure-new-generic-function-using-class
+    (function-name &rest keys &key
+		   (generic-function-class *standard-generic-function-class* gfc-p)
+                   &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (when gfc-p
+    (if (symbolp generic-function-class)
+      (setq generic-function-class (find-class generic-function-class)))
+    (unless (subtypep generic-function-class *standard-generic-function-class*)
+      (error "~s is not a subtype of ~s" generic-function-class *generic-function-class*))
+    (remf keys :generic-function-class))
+  (let* ((gf (apply #'%make-gf-instance generic-function-class keys)))
+    (unless (eq (%gf-method-combination gf) *standard-method-combination*)
+      (register-gf-method-combination gf (%gf-method-combination gf)))
+    (setf (sgf.name gf) (getf keys :name function-name))
+    (setf (fdefinition function-name) gf)))
+
+(defun %ensure-existing-generic-function-using-class
+    (gf function-name &key
+	(generic-function-class *standard-generic-function-class* gfc-p)
+	(method-combination *standard-method-combination* mcomb-p)
+	(method-class *standard-method-class* mclass-p)
+	(argument-precedence-order nil apo-p)
+	declarations
+	(lambda-list nil ll-p)
+	name)
+  (when gfc-p
+    (if (symbolp generic-function-class)
+      (setq generic-function-class (find-class generic-function-class)))
+    (unless (subtypep generic-function-class *standard-generic-function-class*)
+      (error "~s is not a subtype of ~s" generic-function-class *standard-generic-function-class*)))
+  (when mcomb-p
+    (unless (typep method-combination 'method-combination)
+      (report-bad-arg method-combination 'method-combination)))
+  (when mclass-p
+    (if (symbolp method-class)
+      (setq method-class (find-class method-class)))
+    (unless (subtypep method-class *method-class*)
+      (error "~s is not a subtype of ~s." method-class *method-class*)))
+  (when declarations
+    (unless (list-length declarations)
+      (error "~s is not a proper list" declarations)))
+  ;; Fix APO, lambda-list
+  (if apo-p
+    (if (not ll-p)
+      (error "Cannot specify ~s without specifying ~s" :argument-precedence-order
+	     :lambda-list)))
+  (let* ((old-mc (sgf.method-combination gf)))
+    (unless (eq old-mc method-combination)
+      (unless (eq old-mc *standard-method-combination*)
+	(unregister-gf-method-combination gf method-combination))))
+    (setf (sgf.name gf) (or name function-name)
+	  (sgf.decls gf) declarations
+	  (sgf.method-class gf) method-class
+	  (sgf.method-combination gf) method-combination)
+    (unless (eq method-combination *standard-method-combination*)
+      (register-gf-method-combination gf method-combination))
+    (when ll-p
+      (if apo-p
+        (set-gf-arg-info gf :lambda-list lambda-list
+                         :argument-precedence-order argument-precedence-order)
+        (set-gf-arg-info gf :lambda-list lambda-list)))
+    (setf (fdefinition function-name) gf))
+
+(defun canonicalize-specializers (specializers &optional (copy t))
+  (flet ((canonicalize-specializer (spec)
+           (if (specializer-p spec)
+             spec
+             (if (symbolp spec)
+               (find-class spec)
+               (if (and (consp spec)
+                        (eq (car spec) 'eql)
+                        (consp (cdr spec))
+                        (null (cddr spec)))
+                 (intern-eql-specializer (cadr spec))
+                 (error "Unknown specializer form ~s" spec))))))
+    (if (and (not copy)
+             (dolist (s specializers t)
+               (unless (specializer-p s) (return nil))))
+      specializers
+      (mapcar #'canonicalize-specializer specializers))))
+
+(defparameter *sealed-clos-world* nil "When true, class and method definition -at least - are disallowed.")
+
+(defun ensure-method (name specializers &rest keys &key (documentation nil doc-p) qualifiers
+                           &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (if *sealed-clos-world*
+    (error "Method (re)definition is not allowed in this environment.")
+    (progn
+      (setq specializers (canonicalize-specializers specializers))
+      (let* ((gf (ensure-generic-function name))
+             (method (apply #'%make-method-instance
+                            (%gf-method-class gf)
+                            :name name
+                            :specializers specializers
+                            keys))
+             (old-method (when (%gf-methods gf)
+                           (ignore-errors
+                             (find-method gf qualifiers specializers nil)))))
+
+        (%add-method gf method)
+        (when (and doc-p *save-doc-strings*)
+          (set-documentation method t documentation))
+        (record-source-file method 'method)
+        (when old-method (%move-method-encapsulations-maybe old-method method))
+        method))))
+        
+
+(defun %anonymous-method (function specializers qualifiers  lambda-list &optional documentation
+                                   &aux name method-class)
+  (let ((inner-function (closure-function function)))
+    (unless (%method-function-p inner-function)
+      (report-bad-arg inner-function 'method-function))   ; Well, I suppose we'll have to shoot you.
+    (unless (eq inner-function function)   ; must be closed over
+      (copy-method-function-bits inner-function function))
+    (setq name (function-name inner-function))
+    (if (typep name 'standard-method)     ; method-function already installed.
+      (setq name (%method-name name)))
+    (setq method-class *standard-method-class*)
+    (unless (memq *standard-method-class* (or (%class.cpl method-class)
+                                              (%class.cpl (update-class  method-class t))))
+      (%badarg method-class 'standard-method))
+    #|
+    (unless (member qualifiers '(() (:before) (:after) (:around)) :test #'equal)
+    (report-bad-arg qualifiers))
+    ||#
+    (setq specializers (mapcar #'(lambda (s)
+                                   (or (and (consp s)
+                                            (eq (%car s) 'eql)
+                                            (consp (%cdr s))
+                                            (null (%cddr s))
+                                            (intern-eql-specializer (%cadr s)))
+                                       (and (specializer-p s) s)
+                                       (find-class s)))
+                               specializers))
+    (let ((method (%make-method-instance method-class
+                      :name name
+		      :lambda-list lambda-list
+                      :qualifiers qualifiers
+                      :specializers specializers
+                      :function function)))
+      (lfun-name inner-function method)
+      (when documentation
+        (set-documentation method t documentation))
+      method)))
+
+	   
+(defun check-defmethod-congruency (gf method)
+  (unless (congruent-lambda-lists-p gf method)
+    (cerror (format nil
+		    "Remove ~d method~:p from the generic-function and change its lambda list."
+		    (length (%gf-methods gf)))
+	    "Lambda list of method ~S ~%~
+is incompatible with that of the generic function ~S.~%~
+Method's lambda-list : ~s~%~
+Generic-function's   : ~s~%" method (or (generic-function-name gf) gf) (flatten-method-lambda-list (%method-lambda-list method)) (generic-function-lambda-list gf))
+    (loop
+      (let ((methods (%gf-methods gf)))
+        (if methods
+          (remove-method gf (car methods))
+          (return))))
+    (%set-defgeneric-keys gf nil)
+    (inner-lfun-bits gf (%ilogior (%ilsl $lfbits-gfn-bit 1)
+                                  (%ilogand $lfbits-args-mask
+                                            (lfun-bits (%method-function method))))))
+  gf)
+
+
+
+(defun %method-function-method (method-function)
+  (setq method-function
+        (closure-function
+         (find-unencapsulated-definition method-function)))
+  (setq method-function (require-type method-function 'method-function))
+  (lfun-name method-function))
+
+(defstatic %defgeneric-methods% (make-hash-table :test 'eq :weak t))
+
+(defun %defgeneric-methods (gf)
+   (gethash gf %defgeneric-methods%))
+
+(defun %set-defgeneric-methods (gf &rest methods)
+   (if methods
+     (setf (gethash gf %defgeneric-methods%) methods)
+     (remhash gf %defgeneric-methods%)))
+
+(defun %defgeneric-keys (gf)
+  (%gf-dispatch-table-keyvect (%gf-dispatch-table gf)))
+
+(defun %set-defgeneric-keys (gf keyvect)
+  (setf (%gf-dispatch-table-keyvect (%gf-dispatch-table gf)) keyvect))
+
+(defun congruent-lfbits-p (gbits mbits)
+  (and (eq (ldb $lfbits-numreq gbits) (ldb $lfbits-numreq mbits))
+       (eq (ldb $lfbits-numopt gbits) (ldb $lfbits-numopt mbits))
+       (eq (or (logbitp $lfbits-rest-bit gbits)
+               (logbitp $lfbits-restv-bit gbits)
+               (logbitp $lfbits-keys-bit gbits))
+           (or (logbitp $lfbits-rest-bit mbits)
+               (logbitp $lfbits-restv-bit mbits)
+               (logbitp $lfbits-keys-bit mbits)))))
+
+(defun congruent-lambda-lists-p (gf method &optional
+                                    error-p gbits mbits gkeys)
+  (unless gbits (setq gbits (inner-lfun-bits gf)))
+  (unless mbits (setq mbits (lfun-bits (%method-function method))))
+  (and (congruent-lfbits-p gbits mbits)
+       (or (and (or (logbitp $lfbits-rest-bit mbits)
+                    (logbitp $lfbits-restv-bit mbits))
+                (not (logbitp $lfbits-keys-bit mbits)))
+           (logbitp $lfbits-aok-bit mbits)
+           (progn
+             (unless gkeys (setq gkeys (%defgeneric-keys gf)))
+             (or (null gkeys)
+                 (eql 0 (length gkeys))
+                 (let ((mkeys (lfun-keyvect
+                               (%inner-method-function method))))
+                   (dovector (key gkeys t)
+                     (unless (find key mkeys :test 'eq)
+                       (if error-p
+                         (error "~s does not specify keys: ~s" method gkeys))
+                       (return nil)))))))))
+
+(defun %add-method (gf method)
+  (%add-standard-method-to-standard-gf gf method))
+
+;; Redefined in l1-clos.lisp
+(fset 'maybe-remove-make-instance-optimization
+      (nlambda bootstrapping-maybe-remove-make-instance-optimization (gfn method)
+        (declare (ignore gfn method))
+        nil))
+
+(defun %add-standard-method-to-standard-gf (gfn method)
+  (when (%method-gf method)
+    (error "~s is already a method of ~s." method (%method-gf method)))
+  (set-gf-arg-info gfn :new-method method)
+  (let* ((dt (%gf-dispatch-table gfn))
+	 (methods (sgf.methods gfn))
+	 (specializers (%method-specializers method))
+	 (qualifiers (%method-qualifiers method)))
+    (remove-obsoleted-combined-methods method dt specializers)
+    (maybe-remove-make-instance-optimization gfn method)
+    (apply #'invalidate-initargs-vector-for-gf gfn specializers)
+    (dolist (m methods)
+      (when (and (equal specializers (%method-specializers m))
+		 (equal qualifiers (%method-qualifiers m)))
+	(remove-method gfn m)
+	;; There can be at most one match
+	(return)))
+    (push method (sgf.methods gfn))
+    (setf (%gf-dispatch-table-methods dt) (sgf.methods gfn))
+    (setf (%method-gf method) gfn)
+    (%add-direct-methods method)
+    (compute-dcode gfn dt)
+    (when (sgf.dependents gfn)
+      (map-dependents gfn #'(lambda (d)
+			      (update-dependent gfn d 'add-method method)))))
+  gfn)
+
+(defstatic *standard-kernel-method-class* nil)
+
+(defun redefine-kernel-method (method)
+  (when (and *warn-if-redefine-kernel*
+             (or (let ((class *standard-kernel-method-class*))
+                   (and class (typep method class)))
+                 (and (standard-method-p method)
+                      (kernel-function-p (%method-function method)))))
+    (cerror "Replace the definition of ~S."
+            "The method ~S is predefined in Clozure CL." method)))
+
+;;; Called by the expansion of generic-labels.  Which doesn't exist.
+(defun %add-methods (gf &rest methods)
+  (declare (dynamic-extent methods))
+  (dolist (m methods)
+    (add-method gf m)))
+
+(defun methods-congruent-p (m1 m2)
+  (when (and (standard-method-p m1)(standard-method-p m2))
+    (when (equal (%method-qualifiers m1) (%method-qualifiers m2))
+      (let ((specs (%method-specializers m1)))
+        (dolist (msp (%method-specializers m2) t)
+          (let ((spec (%pop specs)))
+            (unless (eq msp spec)
+              (return nil))))))))
+
+(defvar *maintain-class-direct-methods* nil)
+
+
+
+;;; CAR is an EQL hash table for objects whose identity is not used by EQL
+;;; (numbers and macptrs)
+;;; CDR is a weak EQ hash table for other objects.
+(defvar *eql-methods-hashes* (cons (make-hash-table :test 'eql)
+                                   (make-hash-table :test 'eq :weak :key)))
+
+(defun eql-methods-cell (object &optional addp)
+  (let ((hashes *eql-methods-hashes*))
+    (without-interrupts
+     (let* ((hash (cond
+                   ((or (typep object 'number)
+                        (typep object 'macptr))
+                    (car hashes))
+                   (t (cdr hashes))))
+            (cell (gethash object hash)))
+       (when (and (null cell) addp)
+         (setf (gethash object hash) (setq cell (cons nil nil))))
+       cell))))
+
+
+
+
+(defun map-classes (function)
+  (with-hash-table-iterator (m %find-classes%)
+    (loop
+      (multiple-value-bind (found name cell) (m)
+        (declare (optimize speed) (type class-cell cell))
+        (unless found (return))
+        (when cell
+          (funcall function name (class-cell-class cell)))))))
+
+
+
+(defun %class-primary-slot-accessor-info (class accessor-or-slot-name &optional create?)
+  (let ((info-list (%class-get class '%class-primary-slot-accessor-info)))
+    (or (car (member accessor-or-slot-name info-list
+                     :key #'(lambda (x) (%slot-accessor-info.accessor x))))
+        (and create?
+             (let ((info (%cons-slot-accessor-info class accessor-or-slot-name)))
+               (setf (%class-get class '%class-primary-slot-accessor-info)
+                     (cons info info-list))
+               info)))))
+
+;;; Clear the %class.primary-slot-accessor-info for an added or
+;;; removed method's specializers
+(defun clear-accessor-method-offsets (gf method)
+  (when (or (typep method 'standard-accessor-method)
+            (member 'standard-accessor-method
+                    (%gf-methods gf)
+                    :test #'(lambda (sam meth)
+                             (declare (ignore sam))
+                             (typep meth 'standard-accessor-method))))
+    (labels ((clear-class (class)
+               (when (typep class 'standard-class)
+                 (let ((info (%class-primary-slot-accessor-info class gf)))
+                   (when info
+                     (setf (%slot-accessor-info.offset info) nil)))
+                 (mapc #'clear-class (%class.subclasses class)))))
+      (declare (dynamic-extent #'clear-class))
+      (mapc #'clear-class (%method-specializers method)))))
+
+;;; Remove methods which specialize on a sub-class of method's
+;;; specializers from the generic-function dispatch-table dt.
+(defun remove-obsoleted-combined-methods (method &optional dt
+                                                 (specializers (%method-specializers method)))
+  (without-interrupts
+   (unless dt
+     (let ((gf (%method-gf method)))
+       (when gf (setq dt (%gf-dispatch-table gf)))))
+   (when dt
+     (if specializers
+       (let* ((argnum (%gf-dispatch-table-argnum dt)))
+         (when (>= argnum 0)
+           (let ((class (nth argnum specializers))
+                 (size (%gf-dispatch-table-size dt))
+                 (index 0))
+             (clear-accessor-method-offsets (%gf-dispatch-table-gf dt) method)
+             (if (typep class 'eql-specializer)
+                 (setq class (class-of (eql-specializer-object class))))
+             (while (%i< index size)
+               (let* ((wrapper (%gf-dispatch-table-ref dt index))
+                      hash-index-0?
+                      (cpl (and wrapper
+                                (not (setq hash-index-0?
+                                           (eql 0 (%wrapper-hash-index wrapper))))
+                                (%inited-class-cpl
+                                 (require-type (%wrapper-class wrapper) 'class)))))
+                 (when (or hash-index-0? (and cpl (cpl-index class cpl)))
+                   (setf (%gf-dispatch-table-ref dt index) *obsolete-wrapper*
+                         (%gf-dispatch-table-ref dt (%i+ index 1)) *gf-dispatch-bug*))
+                 (setq index (%i+ index 2)))))))
+       (setf (%gf-dispatch-table-ref dt 1) nil)))))   ; clear 0-arg gf cm
+
+;;; SETQ'd below after the GF's exist.
+(defvar *initialization-invalidation-alist* nil)
+
+;;; Called by %add-method, %remove-method
+(defun invalidate-initargs-vector-for-gf (gf &optional first-specializer &rest other-specializers)
+  (declare (ignore other-specializers))
+  (when (and first-specializer (typep first-specializer 'class)) ; no eql methods or gfs with no specializers need apply
+    (let ((indices (cdr (assq gf *initialization-invalidation-alist*))))
+      (when indices
+        (labels ((invalidate (class indices)
+                   (when (std-class-p class) ; catch the class named T
+                     (dolist (index indices)
+                       (setf (standard-instance-instance-location-access class index) nil)))
+                   (dolist (subclass (%class.subclasses class))
+                     (invalidate subclass indices))))
+          (invalidate first-specializer indices))))))
+
+;;; Return two values:
+;;; 1) the index of the first non-T specializer of method, or NIL if
+;;;    all the specializers are T or only the first one is T
+;;; 2) the index of the first non-T specializer
+(defun multi-method-index (method &aux (i 0) index)
+  (dolist (s (%method.specializers method) (values nil index))
+    (unless (eq s *t-class*)
+      (unless index (setq index i))
+      (unless (eql i 0) (return (values index index))))
+    (incf i)))
+
+(defun %remove-standard-method-from-containing-gf (method)
+  (setq method (require-type method 'standard-method))
+  (let ((gf (%method-gf method)))
+    (when gf
+      (let* ((dt (%gf-dispatch-table gf))
+	     (methods (sgf.methods gf)))
+        (setf (%method-gf method) nil)
+	(setq methods (nremove method methods))
+        (setf (%gf-dispatch-table-methods dt) methods
+	      (sgf.methods gf) methods)
+        (%remove-direct-methods method)
+        (remove-obsoleted-combined-methods method dt)
+        (apply #'invalidate-initargs-vector-for-gf gf (%method-specializers method))
+        (compute-dcode gf dt)
+	(when (sgf.dependents gf)
+	  (map-dependents
+	   gf
+	   #'(lambda (d)
+	       (update-dependent gf d 'remove-method method)))))))
+  method)
+
+
+(defvar *reader-method-function-proto*
+  #'(lambda (instance)
+      (slot-value instance 'x)))
+
+
+(defvar *writer-method-function-proto*
+  #'(lambda (new instance)
+      (set-slot-value instance 'x new)))
+
+(defun dcode-for-gf (gf dcode)
+  (if *uniquify-dcode*
+    (let ((new-dcode (%copy-function dcode)))
+      (lfun-name new-dcode (list (lfun-name dcode) (lfun-name gf)))
+      new-dcode)
+    dcode))
+
+(defstatic *non-dt-dcode-functions* () "List of functions which return a dcode function for the GF which is their argument.  The dcode functions will be caled with all of the incoming arguments.")
+
+(defun non-dt-dcode-function (gf)
+  (dolist (f *non-dt-dcode-functions*)
+    (let* ((dcode (funcall f gf)))
+      (when dcode (return dcode)))))
+
+(defun compute-dcode (gf &optional dt)
+  (setq gf (require-type gf 'standard-generic-function))
+  (unless dt (setq dt (%gf-dispatch-table gf)))
+  (let* ((methods (%gf-dispatch-table-methods dt))
+         (bits (inner-lfun-bits gf))
+         (nreq (ldb $lfbits-numreq bits))
+         (0-args? (eql 0 nreq))
+         (other-args? (or (not (eql 0 (ldb $lfbits-numopt bits)))
+                          (logbitp $lfbits-rest-bit bits)
+                          (logbitp $lfbits-restv-bit bits)
+                          (logbitp $lfbits-keys-bit bits)
+                          (logbitp $lfbits-aok-bit bits)))
+         multi-method-index 
+	 min-index)
+    (when methods
+      (unless 0-args?
+        (dolist (m methods)
+          (multiple-value-bind (mm-index index) (multi-method-index m)
+            (when mm-index
+              (if (or (null multi-method-index) (< mm-index multi-method-index))
+                (setq multi-method-index mm-index)))
+            (when index
+              (if (or (null min-index) (< index min-index))
+                (setq min-index index))))))
+      (let* ((non-dt (non-dt-dcode-function gf))
+             (dcode (or non-dt
+                        (if 0-args?
+                          #'%%0-arg-dcode
+                          (or (if multi-method-index
+                                #'%%nth-arg-dcode)
+                              (if (null other-args?)
+                                (if (eql nreq 1)
+                                  #'%%one-arg-dcode
+                                  (if (eql nreq 2)
+                                    #'%%1st-two-arg-dcode
+                                    #'%%1st-arg-dcode))
+                                #'%%1st-arg-dcode))))))
+        (setq multi-method-index
+              (if multi-method-index
+                (if min-index
+                  (min multi-method-index min-index)
+                  multi-method-index)
+                0))
+        (let* ((old-dcode (%gf-dcode (find-unencapsulated-definition gf))))
+          (when (or non-dt
+		    (neq dcode old-dcode)
+                    (neq multi-method-index (%gf-dispatch-table-argnum dt)))
+            (clear-gf-dispatch-table dt)
+            (setf (%gf-dispatch-table-argnum dt) multi-method-index)
+            (if (function-encapsulated-p gf)
+	      (%set-encapsulated-gf-dcode gf dcode)
+	      (setf (%gf-dcode gf) dcode))))
+        (values dcode multi-method-index)))))
+
+(defun inherits-from-standard-generic-function-p (class)
+  (memq *standard-generic-function-class*
+        (%inited-class-cpl (require-type class 'class))))
+
+;;;;;;;;;;; The type system needs to get wedged into CLOS fairly early ;;;;;;;
+
+
+;;; Could check for duplicates, but not really worth it.  They're all
+;;; allocated here
+(defun new-type-class (name)
+  (let* ((class (%istruct 
+                 'type-class 
+                 name
+                 #'missing-type-method
+                 nil
+                 nil
+                 #'(lambda (x y) (hierarchical-union2 x y))
+                 nil
+                 #'(lambda (x y) (hierarchical-intersection2 x y))
+                 nil
+                 #'missing-type-method
+                 nil
+                 #'missing-type-method)))
+    (push (cons name class) *type-classes*)
+    class))
+
+;; There are ultimately about a dozen entries on this alist.
+(defvar *type-classes* nil)
+(declaim (special *wild-type* *empty-type* *universal-type*))
+(defvar *type-kind-info* (make-hash-table :test #'equal))
+
+(defun info-type-kind (name)
+  (gethash name *type-kind-info*))
+
+(defun (setf info-type-kind) (val name)
+  (if val
+    (setf (gethash name *type-kind-info*) val)
+    (remhash name *type-kind-info*)))
+
+(defun missing-type-method (&rest foo)
+  (error "Missing type method for ~S" foo))
+          
+(new-type-class 'values)
+(new-type-class 'function)
+(new-type-class 'constant)
+(new-type-class 'wild)
+(new-type-class 'bottom)
+(new-type-class 'named)
+(new-type-class 'hairy)
+(new-type-class 'unknown)
+(new-type-class 'number)
+(new-type-class 'array)
+(new-type-class 'member)
+(new-type-class 'union)
+(new-type-class 'foreign)
+(new-type-class 'cons)
+(new-type-class 'intersection)
+(new-type-class 'negation)
+(defparameter *class-type-class* (new-type-class 'class))
+
+
+
+
+                        
+;;;;;;;;;;;;;;;;;;;;;;;;  Instances and classes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(declaim (inline non-standard-instance-class-wrapper))
+
+(defun non-standard-instance-class-wrapper (instance)
+  (let* ((typecode (typecode instance)))
+    (declare (type (unsigned-byte 8) typecode))
+    (cond ((eql typecode target::subtag-struct)
+           (%class.own-wrapper
+            (class-cell-class (car (%svref instance 0)))))
+          ((eql typecode target::subtag-istruct)
+           (istruct-cell-info (%svref instance 0)))
+          ((eql typecode target::subtag-basic-stream)
+           (basic-stream.wrapper instance))
+          ((typep instance 'funcallable-standard-object)
+           (gf.instance.class-wrapper instance))
+          ((eql typecode target::subtag-macptr) (foreign-instance-class-wrapper instance))
+          (t (%class.own-wrapper (class-of instance))))))
+
+(defun instance-class-wrapper (instance)
+  (if (= (typecode instance)  target::subtag-instance)
+    (instance.class-wrapper instance)
+    (non-standard-instance-class-wrapper instance)))
+
+
+(defun std-instance-class-cell-typep (form class-cell)
+  (let* ((typecode (typecode form))
+         (wrapper (cond ((= typecode target::subtag-instance)
+                         (instance.class-wrapper form))
+                        ((= typecode target::subtag-basic-stream)
+                         (basic-stream.wrapper form))
+                        (t nil))))
+    (declare (type (unsigned-byte 8) typecode))
+    (when wrapper
+      (loop
+        (let ((class (class-cell-class class-cell)))
+          (if class
+            (let* ((ordinal (%class-ordinal class))
+                   (bits (or (%wrapper-cpl-bits wrapper)
+                             (make-cpl-bits (%inited-class-cpl (%wrapper-class wrapper))))))
+              (declare (fixnum ordinal))
+              (return
+                (if bits
+                  (locally (declare (simple-bit-vector bits)
+                                    (optimize (speed 3) (safety 0)))
+                    (if (< ordinal (length bits))
+                      (not (eql 0 (sbit bits ordinal))))))))
+            (let* ((name (class-cell-name class-cell))
+                   (new-cell (find-class-cell name nil)))
+              (unless
+                  (if (and new-cell (not (eq class-cell new-cell)))
+                    (setq class-cell new-cell class (class-cell-class class-cell))
+                    (return (typep form name)))))))))))
+
+(defun class-cell-typep (form class-cell)
+  (locally (declare (type class-cell  class-cell))
+    (loop
+    (let ((class (class-cell-class class-cell)))
+      (if class
+        (let* ((ordinal (%class-ordinal class))
+               (wrapper (instance-class-wrapper form))
+               (bits (or (%wrapper-cpl-bits wrapper)
+                         (make-cpl-bits (%inited-class-cpl (%wrapper-class wrapper))))))
+          (declare (fixnum ordinal))
+          (return
+            (if bits
+              (locally (declare (simple-bit-vector bits)
+                                (optimize (speed 3) (safety 0)))
+                  (if (< ordinal (length bits))
+                    (not (eql 0 (sbit bits ordinal))))))))
+        (let* ((name (class-cell-name class-cell))
+               (new-cell (find-class-cell name nil)))
+          (unless
+              (if (and new-cell (not (eq class-cell new-cell)))
+                (setq class-cell new-cell class (class-cell-class class-cell))
+                (return (typep form name))))))))))
+
+
+
+(defun %require-type-class-cell (arg class-cell)
+  (if (class-cell-typep arg class-cell)
+    arg
+    (%kernel-restart $xwrongtype arg (car class-cell))))
+
+
+
+
+(defun find-class (name &optional (errorp t) environment)
+  (declare (optimize speed))
+  (let* ((cell (find-class-cell name nil)))
+    (declare (type class-cell cell))
+    (or (and cell (class-cell-class cell))
+        (let ((defenv (and environment (definition-environment environment))))
+          (when defenv
+            (dolist (class (defenv.classes defenv))
+              (when (eq name (%class.name class))
+                (return class)))))
+        (when (or errorp (not (symbolp name)))
+          (cerror "Try finding the class again"
+                  "Class named ~S not found." name)
+          (find-class name errorp environment)))))
+
+(fset 'pessimize-make-instance-for-class-name ;; redefined later
+      (qlfun bootstrapping-pessimize-make-instance-for-class-name (name) name))
+
+(defun update-class-proper-names (name old-class new-class)
+  (when name
+    (pessimize-make-instance-for-class-name name))
+  (when (and old-class
+             (not (eq old-class new-class))
+             (eq (%class-proper-name old-class) name))
+    (setf (%class-proper-name old-class) nil))
+  (when (and new-class (eq (%class-name new-class) name))
+    (setf (%class-proper-name new-class) name)))
+
+
+(fset 'set-find-class (nfunction bootstrapping-set-find-class ; redefined below
+                                 (lambda (name class)
+                                   (clear-type-cache)
+                                   (let* ((cell (find-class-cell name t))
+                                          (old-class (class-cell-class cell)))
+                                     (when class
+                                       (if (eq name (%class.name class))
+                                         (setf (info-type-kind name) :instance)))
+                                     (setf (class-cell-class cell) class)
+                                     (update-class-proper-names name old-class class)
+                                     class))))
+
+
+;;; bootstrapping definition. real one is in "sysutils.lisp"
+(fset 'built-in-type-p (nfunction boostrapping-built-in-typep-p
+                                  (lambda (name)
+                                    (or (type-predicate name)
+                                        (memq name '(signed-byte unsigned-byte mod 
+                                                     values satisfies member and or not))
+                                        (typep (find-class name nil) 'built-in-class)))))
+
+
+
+(defun %compile-time-defclass (name environment)
+  (note-type-info name 'class environment)
+  (unless (find-class name nil environment)
+    (let ((defenv (definition-environment environment)))
+      (when defenv
+        (push (make-instance 'compile-time-class :name name)
+              (defenv.classes defenv)))))
+  name)
+
+(eval-when (:compile-toplevel :execute)
+(declaim (inline standard-instance-p))
+)
+
+
+
+
+(defun standard-instance-p (i)
+  (eq (typecode i) target::subtag-instance))
+
+(defun check-setf-find-class-protected-class (old-class new-class name)
+  (when (and (standard-instance-p old-class)
+	     (%class-kernel-p old-class)
+	     *warn-if-redefine-kernel*
+	     ;; EQL might be necessary on foreign classes
+	     (not (eq new-class old-class)))
+    (cerror "Setf (FIND-CLASS ~s) to the new class."
+	    "The class name ~s currently denotes the class ~s that
+marked as being a critical part of the system; an attempt is being made
+to replace that class with ~s" name old-class new-class)
+    (setf (%class-kernel-p old-class) nil)))
+
+
+(queue-fixup
+ (defun set-find-class (name class)
+   (setq name (require-type name 'symbol))
+   (let* ((cell (find-class-cell name t))
+          (old-class (class-cell-class cell)))
+     (declare (type class-cell cell))
+     (when old-class
+       (when (eq (%class.name old-class) name)
+         (setf (info-type-kind name) nil)
+         (clear-type-cache))
+       (when *warn-if-redefine-kernel*
+         (check-setf-find-class-protected-class old-class class name)))
+     (when (null class)
+       (when cell
+         (setf (class-cell-class cell) nil))
+       (update-class-proper-names name old-class class)
+       (return-from set-find-class nil))
+     (setq class (require-type class 'class))
+     (when (built-in-type-p name)
+       (unless (eq (class-cell-class cell) class)
+         (error "Cannot redefine built-in type name ~S" name)))
+     (when (eq (%class.name class) name)
+       (when (%deftype-expander name)
+         (cerror "set ~S anyway, removing the ~*~S definition"
+                 "Cannot set ~S because type ~S is already defined by ~S"
+                 `(find-class ',name) name 'deftype)
+         (%deftype name nil nil))
+       (setf (info-type-kind name) :instance))
+     (update-class-proper-names name old-class class)
+     (setf (class-cell-class cell) class)))
+ )                                      ; end of queue-fixup
+
+
+
+#||
+; This tended to cluster entries in gf dispatch tables too much.
+(defvar *class-wrapper-hash-index* 0)
+(defun new-class-wrapper-hash-index ()
+  (let ((index *class-wrapper-hash-index*))
+    (setq *class-wrapper-hash-index*
+        (if (< index (- most-positive-fixnum 2))
+          ; Increment by two longwords.  This is important!
+          ; The dispatch code will break if you change this.
+          (%i+ index 3)                 ; '3 = 24 bytes = 6 longwords in lap.
+          1))))
+||#
+
+(defglobal *next-class-ordinal* 0)
+
+(defun %next-class-ordinal ()
+  (%atomic-incf-node 1 '*next-class-ordinal* target::symbol.vcell))
+
+;;; Initialized after built-in-class is made
+(defvar *built-in-class-wrapper* nil)
+
+(defun make-class-ctype (class)
+  (%istruct 'class-ctype *class-type-class* nil class nil))
+
+(defun %class-ordinal (class &optional no-error)
+  (if (standard-instance-p class)
+    (instance.hash class)
+    (if (typep class 'macptr)
+      (foreign-class-ordinal class)
+      (unless no-error
+        (error "Can't determine ordinal of ~s" class)))))
+
+(defun (setf %class-ordinal) (new class &optional no-error)
+  (if (standard-instance-p class)
+    (setf (instance.hash class) new)
+    (if (typep class 'macptr)
+      (setf (foreign-class-ordinal class) new)
+      (unless no-error
+        (error "Can't set ordinal of class ~s to ~s" class new)))))
+
+
+(defvar *t-class* (let* ((class (%cons-built-in-class 't)))
+                    (setf (instance.hash class) 0)
+                    (let* ((cpl (list class))
+                           (wrapper (%cons-wrapper class (new-class-wrapper-hash-index))))
+                      (setf (%class.cpl class) cpl)
+                      (setf (%wrapper-cpl wrapper) cpl
+                            (%class.own-wrapper class) wrapper
+                            (%wrapper-cpl-bits wrapper) #*1)
+                      (setf (%class.ctype class) (make-class-ctype class))
+                      (setf (find-class 't) class)
+                      class)))
+
+(defun compute-cpl (class)
+  (flet ((%real-class-cpl (class)
+           (or (%class-cpl class)
+               (compute-cpl class))))
+    (let* ((predecessors (list (list class))) candidates cpl)
+      (dolist (sup (%class-direct-superclasses class))
+        (when (symbolp sup) (report-bad-arg sup 'class))
+        (dolist (sup (%real-class-cpl sup))
+          (unless (assq sup predecessors) (push (list sup) predecessors))))
+      (labels ((compute-predecessors (class table)
+                 (dolist (sup (%class-direct-superclasses class) table)
+                   (compute-predecessors sup table)
+                   ;(push class (cdr (assq sup table)))
+                   (let ((a (assq sup table))) (%rplacd a (cons class (%cdr a))))
+                   (setq class sup))))
+        (compute-predecessors class predecessors))
+      (setq candidates (list (assq class predecessors)))
+      (while predecessors
+        (dolist (c candidates (error "Inconsistent superclasses for ~d" class))
+          (when (null (%cdr c))
+            (setq predecessors (nremove c predecessors))
+            (dolist (p predecessors) (%rplacd p (nremove (%car c) (%cdr p))))
+            (setq candidates (nremove c candidates))
+            (setq cpl (%rplacd c cpl))
+            (dolist (sup (%class-direct-superclasses (%car c)))
+              (when (setq c (assq sup predecessors)) (push c candidates)))
+            (return))))
+      (setq cpl (nreverse cpl))
+      (do* ((tail cpl (%cdr tail))
+            sup-cpl)
+           ((null (setq sup-cpl (and (cdr tail) (%real-class-cpl (cadr tail))))))
+        (when (equal (%cdr tail) sup-cpl)
+          (setf (%cdr tail) sup-cpl)
+          (return)))
+      cpl)))
+
+(defun make-cpl-bits (cpl)
+  (declare (optimize speed))
+  (when cpl
+    (let* ((max 0))
+      (declare (fixnum max))
+      (dolist (class cpl)
+        (let* ((ordinal (%class-ordinal class)))
+          (declare (fixnum ordinal))
+          (when (> ordinal max)
+            (setq max ordinal))))
+      (let* ((bits (make-array (the fixnum (1+ max)) :element-type 'bit)))
+        (dolist (class cpl bits)
+          (let* ((ordinal (%class-ordinal class)))
+            (setf (sbit bits ordinal) 1)))))))
+
+          
+(defun make-built-in-class (name &rest supers)
+  (if (null supers)
+    (setq supers (list *t-class*))
+    (do ((supers supers (%cdr supers)))
+        ((null supers))
+      (when (symbolp (%car supers)) (%rplaca supers (find-class (%car supers))))))
+  (let ((class (find-class name nil)))
+    (if class
+      (progn
+        ;Must be debugging.  Give a try at redefinition...
+        (dolist (sup (%class.local-supers class))
+          (setf (%class.subclasses sup) (nremove class (%class.subclasses sup)))))
+      (progn
+        (setq class (%cons-built-in-class name))
+        (setf (instance.hash class) (%next-class-ordinal))))
+    (dolist (sup supers)
+      (setf (%class.subclasses sup) (cons class (%class.subclasses sup))))
+    (setf (%class.local-supers class) supers)
+    (let* ((wrapper (%cons-wrapper class (new-class-wrapper-hash-index)))
+           (cpl (compute-cpl class)))
+      (setf (%class.cpl class) cpl)
+      (setf (%class.own-wrapper class) wrapper)
+      (setf (%wrapper-cpl wrapper) cpl
+            (%wrapper-cpl-bits wrapper) (make-cpl-bits cpl)
+            (%wrapper-class-ordinal wrapper) (%class-ordinal class)))
+    (setf (%class.ctype class)  (make-class-ctype class))
+    (setf (find-class name) class)
+    (dolist (sub (%class.subclasses class))   ; Only non-nil if redefining
+      ;Recompute the cpl.
+      (apply #'make-built-in-class (%class.name sub) (%class.local-supers sub)))
+    class))
+
+(defun make-istruct-class (name &rest supers)
+  (let* ((class (apply #'make-built-in-class name supers))
+         (cell (register-istruct-cell name)))
+    (setf (istruct-cell-info cell) (%class.own-wrapper class))
+    class))
+
+;;; This will be filled in below.  Need it defined now as it goes in
+;;; the instance.class-wrapper of all the classes that STANDARD-CLASS
+;;; inherits from.
+(defstatic *standard-class-wrapper* 
+  (%cons-wrapper 'standard-class))
+
+(defun make-standard-class (name &rest supers)
+  (make-class name *standard-class-wrapper* supers))
+
+(defun make-class (name metaclass-wrapper supers &optional own-wrapper)
+  (let ((class (if (find-class name nil)
+                 (error "Attempt to remake standard class ~s" name)
+                 (%cons-standard-class name metaclass-wrapper))))
+    (setf (instance.hash class) (%next-class-ordinal))
+    (if (null supers)
+      (setq supers (list *standard-class-class*))
+      (do ((supers supers (cdr supers))
+           sup)
+          ((null supers))
+        (setq sup (%car supers))
+        (if (symbolp sup) (setf (%car supers) (setq sup (find-class (%car supers)))))
+        #+nil (unless (or (eq sup *t-class*) (std-class-p sup))
+          (error "~a is not of type ~a" sup 'std-class))))
+    (setf (%class.local-supers class) supers)
+    (let ((cpl (compute-cpl class))
+          (wrapper (if own-wrapper
+                     (progn
+                       (setf (%wrapper-class own-wrapper) class)
+                       own-wrapper)
+                     (%cons-wrapper class))))
+      (setf (%class.cpl class) cpl
+            (%wrapper-instance-slots wrapper) (vector)
+            (%class.own-wrapper class) wrapper
+            (%class.ctype class) (make-class-ctype class)
+            (%class.slots class) nil
+            (%wrapper-class-ordinal wrapper) (%class-ordinal class)
+            (%wrapper-cpl wrapper) cpl
+            (%wrapper-cpl-bits wrapper) (make-cpl-bits cpl)
+            (find-class name) class
+            )
+      (dolist (sup supers)
+        (setf (%class.subclasses sup) (cons class (%class.subclasses sup))))
+      class)))
+
+
+
+
+
+(defun standard-object-p (thing)
+  ;; returns thing's class-wrapper or nil if it isn't a standard-object
+  (if (standard-instance-p thing)
+    (instance.class-wrapper thing)
+    (if (typep thing 'macptr)
+      (foreign-instance-class-wrapper thing))))
+
+
+(defun std-class-p (class)
+  ;; (typep class 'std-class)
+  ;; but works at bootstrapping time as well
+  (let ((wrapper (standard-object-p class)))
+    (and wrapper
+         (or (eq wrapper *standard-class-wrapper*)
+             (memq *std-class-class* (%inited-class-cpl (%wrapper-class wrapper) t))))))
+
+(set-type-predicate 'std-class 'std-class-p)
+
+(defun slots-class-p (class)
+  (let ((wrapper (standard-object-p class)))
+    (and wrapper
+         (or (eq wrapper *slots-class-wrapper*)
+             (memq *slots-class* (%inited-class-cpl (%wrapper-class wrapper) t))))))  
+
+(set-type-predicate 'slots-class 'slots-class-p)
+
+(defun specializer-p (thing)
+  (memq *specializer-class* (%inited-class-cpl (class-of thing))))
+
+(defstatic *standard-object-class* (make-standard-class 'standard-object *t-class*))
+
+(defstatic *metaobject-class* (make-standard-class 'metaobject *standard-object-class*))
+
+(defstatic *specializer-class* (make-standard-class 'specializer *metaobject-class*))
+(defstatic *eql-specializer-class* (make-standard-class 'eql-specializer *specializer-class*))
+
+(defstatic *standard-method-combination*
+  (make-instance-vector
+   (%class.own-wrapper
+    (make-standard-class
+     'standard-method-combination
+     (make-standard-class 'method-combination *metaobject-class*)))
+   1))
+
+
+(defun eql-specializer-p (x)
+  (memq *eql-specializer-class* (%inited-class-cpl (class-of x))))
+
+(setf (type-predicate 'eql-specializer) 'eql-specializer-p)
+
+;;; The *xxx-class-class* instances get slots near the end of this file.
+(defstatic *class-class* (make-standard-class 'class *specializer-class*))
+
+(defstatic *slots-class* (make-standard-class 'slots-class *class-class*))
+(defstatic *slots-class-wrapper* (%class.own-wrapper *slots-class*))
+
+
+;;; an implementation class that exists so that
+;;; standard-class & funcallable-standard-class can have a common ancestor not
+;;; shared by anybody but their subclasses.
+
+(defstatic *std-class-class* (make-standard-class 'std-class *slots-class*))
+
+;;; The class of all objects whose metaclass is standard-class. Yow.
+(defstatic *standard-class-class* (make-standard-class 'standard-class *std-class-class*))
+;;; Replace its wrapper and the circle is closed.
+(setf (%class.own-wrapper *standard-class-class*) *standard-class-wrapper*
+      (%wrapper-class *standard-class-wrapper*) *standard-class-class*
+      (%wrapper-class-ordinal *standard-class-wrapper*) (%class-ordinal *standard-class-class*)
+      (%wrapper-instance-slots *standard-class-wrapper*) (vector))
+
+(defstatic *built-in-class-class* (make-standard-class 'built-in-class *class-class*))
+(setf *built-in-class-wrapper* (%class.own-wrapper *built-in-class-class*)
+      (instance.class-wrapper *t-class*) *built-in-class-wrapper*)
+
+(defstatic *structure-class-class* (make-standard-class 'structure-class *slots-class*))
+(defstatic *structure-class-wrapper* (%class.own-wrapper *structure-class-class*))
+(defstatic *structure-object-class* 
+  (make-class 'structure-object *structure-class-wrapper* (list *t-class*)))
+
+(defstatic *forward-referenced-class-class*
+  (make-standard-class 'forward-referenced-class *class-class*))
+
+(defstatic *function-class* (make-built-in-class 'function))
+
+(defun alias-class (name class)
+  (setf (find-class name) class
+        (info-type-kind name) :instance)
+  class)
+
+;;;Right now, all functions are compiled.
+
+
+(defstatic *compiled-function-class* *function-class*)
+(alias-class 'compiled-function *compiled-function-class*)
+
+(defstatic *compiled-lexical-closure-class* 
+  (make-standard-class 'compiled-lexical-closure *function-class*))
+
+
+
+
+
+(defstatic *funcallable-standard-class-class*
+  (make-standard-class 'funcallable-standard-class *std-class-class*))
+
+(defstatic *funcallable-standard-object-class*
+  (make-class 'funcallable-standard-object
+              (%class.own-wrapper *funcallable-standard-class-class*)
+              (list *standard-object-class* *function-class*)))
+
+(defstatic *generic-function-class*
+  (make-class 'generic-function
+              (%class.own-wrapper *funcallable-standard-class-class*)
+              (list *metaobject-class* *funcallable-standard-object-class*)))
+(setq *generic-function-class-wrapper* (%class.own-wrapper *generic-function-class*))
+
+(defstatic *standard-generic-function-class*
+  (make-class 'standard-generic-function
+              (%class.own-wrapper *funcallable-standard-class-class*)
+              (list *generic-function-class*)))
+(setq *standard-generic-function-class-wrapper*
+      (%class.own-wrapper *standard-generic-function-class*))
+
+;;; *standard-method-class* is upgraded to a real class below
+(defstatic *method-class* (make-standard-class 'method *metaobject-class*))
+(defstatic *standard-method-class* (make-standard-class 'standard-method *method-class*))
+(defstatic *accessor-method-class* (make-standard-class 'standard-accessor-method *standard-method-class*))
+(defstatic *standard-reader-method-class* (make-standard-class 'standard-reader-method *accessor-method-class*))
+(defstatic *standard-writer-method-class* (make-standard-class 'standard-writer-method *accessor-method-class*))
+(defstatic *method-function-class* (make-standard-class 'method-function *function-class*))
+
+
+(defstatic *combined-method-class* (make-standard-class 'combined-method *function-class*))
+
+(defstatic *slot-definition-class* (make-standard-class 'slot-definition *metaobject-class*))
+(defstatic direct-slot-definition-class (make-standard-class 'direct-slot-definition
+                                                           *slot-definition-class*))
+(defstatic effective-slot-definition-class (make-standard-class 'effective-slot-definition
+                                                              *slot-definition-class*))
+(defstatic *standard-slot-definition-class* (make-standard-class 'standard-slot-definition
+                                                                 *slot-definition-class*))
+(defstatic *standard-direct-slot-definition-class* (make-class
+                                                    'standard-direct-slot-definition
+                                                    *standard-class-wrapper*
+                                                    (list
+                                                     *standard-slot-definition-class*
+                                                     direct-slot-definition-class)))
+
+(defstatic *standard-effective-slot-definition-class* (make-class
+                                                    'standard-effective-slot-definition
+                                                    *standard-class-wrapper*
+                                                    (list
+                                                     *standard-slot-definition-class*
+                                                     effective-slot-definition-class)
+))
+
+(defstatic *standard-effective-slot-definition-class-wrapper*
+  (%class.own-wrapper *standard-effective-slot-definition-class*))
+
+
+
+
+
+  
+
+(let ((*dont-find-class-optimize* t)
+      (ordinal-type-class-alist ())
+      (ordinal-type-class-alist-lock (make-lock)))
+
+  (declare (optimize speed)) ;; make sure everything gets inlined that needs to be.
+
+;; The built-in classes.
+  (defstatic *array-class* (make-built-in-class 'array))
+  (defstatic *character-class* (make-built-in-class 'character))
+  (make-built-in-class 'number)
+  (make-built-in-class 'sequence)
+  (defstatic *symbol-class* (make-built-in-class 'symbol))
+  (defstatic *immediate-class* (make-built-in-class 'immediate)) ; Random immediate
+  ;; Random uvectors - these are NOT class of all things represented by a uvector
+  ;;type. Just random uvectors which don't fit anywhere else.
+  (make-built-in-class 'ivector)        ; unknown ivector
+  (make-built-in-class 'gvector)        ; unknown gvector
+  (defstatic *istruct-class* (make-built-in-class 'internal-structure)) ; unknown istruct
+  
+  (defstatic *slot-vector-class* (make-built-in-class 'slot-vector (find-class 'gvector)))
+  
+  (defstatic *macptr-class* (make-built-in-class 'macptr))
+  (defstatic *foreign-standard-object-class*
+    (make-standard-class 'foreign-standard-object
+                         *standard-object-class* *macptr-class*))
+
+  (defstatic *foreign-class-class*
+    (make-standard-class 'foreign-class *foreign-standard-object-class* *slots-class*))
+  
+  (make-built-in-class 'population)
+  (make-built-in-class 'pool)
+  (make-built-in-class 'package)
+  (defstatic *lock-class* (make-built-in-class 'lock))
+  (defstatic *recursive-lock-class* (make-built-in-class 'recursive-lock *lock-class*))
+  (defstatic *read-write-lock-class* (make-built-in-class 'read-write-lock *lock-class*))
+  
+  (make-istruct-class 'lock-acquisition *istruct-class*)
+  (make-istruct-class 'semaphore-notification *istruct-class*)
+  (make-istruct-class 'class-wrapper *istruct-class*)
+  ;; Compiler stuff, mostly
+  (make-istruct-class 'faslapi *istruct-class*)
+  (make-istruct-class 'faslstate *istruct-class*)
+  (make-istruct-class 'var *istruct-class*)
+  (make-istruct-class 'afunc *istruct-class*)
+  (make-istruct-class 'lexical-environment *istruct-class*)
+  (make-istruct-class 'definition-environment *istruct-class*)
+  (make-istruct-class 'compiler-policy *istruct-class*)
+  (make-istruct-class 'deferred-warnings *istruct-class*)
+  (make-istruct-class 'ptaskstate *istruct-class*)
+  (make-istruct-class 'entry *istruct-class*)
+  (make-istruct-class 'foreign-object-domain *istruct-class*)
+
+  
+  (make-istruct-class 'slot-id *istruct-class*)
+  (make-built-in-class 'value-cell)
+  (make-istruct-class 'restart *istruct-class*)
+  (make-istruct-class 'hash-table *istruct-class*)
+  (make-istruct-class 'readtable *istruct-class*)
+  (make-istruct-class 'pathname *istruct-class*)
+  (make-istruct-class 'random-state *istruct-class*)
+  (make-istruct-class 'xp-structure *istruct-class*)
+  (make-istruct-class 'lisp-thread *istruct-class*)
+  (make-istruct-class 'resource *istruct-class*)
+  (make-istruct-class 'periodic-task *istruct-class*)
+  (make-istruct-class 'semaphore *istruct-class*)
+  
+  (make-istruct-class 'type-class *istruct-class*)
+  
+  (defstatic *ctype-class* (make-istruct-class 'ctype *istruct-class*))
+  (make-istruct-class 'key-info *istruct-class*)
+  (defstatic *args-ctype* (make-istruct-class 'args-ctype *ctype-class*))
+  (make-istruct-class 'values-ctype *args-ctype*)
+  (make-istruct-class 'function-ctype *args-ctype*)
+  (make-istruct-class 'constant-ctype *ctype-class*)
+  (make-istruct-class 'named-ctype *ctype-class*)
+  (make-istruct-class 'cons-ctype *ctype-class*)
+  (make-istruct-class 'unknown-ctype (make-istruct-class 'hairy-ctype *ctype-class*))
+  (make-istruct-class 'numeric-ctype *ctype-class*)
+  (make-istruct-class 'array-ctype *ctype-class*)
+  (make-istruct-class 'member-ctype *ctype-class*)
+  (make-istruct-class 'union-ctype *ctype-class*)
+  (make-istruct-class 'foreign-ctype *ctype-class*)
+  (make-istruct-class 'class-ctype *ctype-class*)
+  (make-istruct-class 'negation-ctype *ctype-class*)
+  (make-istruct-class 'intersection-ctype *ctype-class*)
+  
+  (make-istruct-class 'class-cell *istruct-class*)
+  (make-istruct-class 'type-cell *istruct-class*)
+  (make-istruct-class 'package-ref *istruct-class*)
+
+  (make-istruct-class 'foreign-variable *istruct-class*)
+  (make-istruct-class 'external-entry-point *istruct-class*)
+  (make-istruct-class 'shlib *istruct-class*)
+
+  (make-built-in-class 'complex (find-class 'number))
+  (make-built-in-class 'real (find-class 'number))
+  (defstatic *float-class* (make-built-in-class 'float (find-class 'real)))
+  (defstatic *double-float-class* (make-built-in-class 'double-float (find-class 'float)))
+  (defstatic *single-float-class*  (make-built-in-class 'single-float (find-class 'float)))
+  (alias-class 'short-float *single-float-class*)
+  (alias-class 'long-float *double-float-class*)
+
+  (make-built-in-class 'rational (find-class 'real))
+  (make-built-in-class 'ratio (find-class 'rational))
+  (make-built-in-class 'integer (find-class 'rational))
+  (defstatic *fixnum-class* (make-built-in-class 'fixnum (find-class 'integer)))
+
+  #+x86-target
+  (defstatic *tagged-return-address-class* (make-built-in-class 'tagged-return-address))
+  (make-built-in-class 'bignum (find-class 'integer))
+  
+  (make-built-in-class 'bit *fixnum-class*)
+  (make-built-in-class 'unsigned-byte (find-class 'integer))
+  (make-built-In-class 'signed-byte (find-class 'integer))
+
+
+  (make-istruct-class 'logical-pathname (find-class 'pathname))
+
+  (make-istruct-class 'destructure-state *istruct-class*)
+  
+  (defstatic *base-char-class* (alias-class 'base-char *character-class*))
+  (defstatic *standard-char-class* (make-built-in-class 'standard-char *base-char-class*))
+  
+  (defstatic *keyword-class* (make-built-in-class 'keyword *symbol-class*))
+  
+  (make-built-in-class 'list (find-class 'sequence))
+  (defstatic *cons-class* (make-built-in-class 'cons (find-class 'list)))
+  (defstatic *null-class* (make-built-in-class 'null *symbol-class* (find-class 'list)))
+  
+  (defstatic *vector-class* (make-built-in-class 'vector *array-class* (find-class 'sequence)))
+  (defstatic *simple-array-class* (make-built-in-class 'simple-array *array-class*))
+  (make-built-in-class 'simple-1d-array *vector-class* *simple-array-class*)
+  
+  ;;Maybe should do *float-array-class* etc?
+  ;;Also, should straighten out the simple-n-dim-array mess...
+  (make-built-in-class 'unsigned-byte-vector *vector-class*)
+  (make-built-in-class 'simple-unsigned-byte-vector (find-class 'unsigned-byte-vector) (find-class 'simple-1d-array))
+  (make-built-in-class 'unsigned-word-vector *vector-class*)
+  (make-built-in-class 'simple-unsigned-word-vector (find-class 'unsigned-word-vector) (find-class 'simple-1d-array))
+  (make-built-in-class 'fixnum-vector *vector-class*)
+  (make-built-in-class 'simple-fixnum-vector (find-class 'fixnum-vector) (find-class 'simple-1d-array))
+
+
+  (progn
+    (make-built-in-class 'double-float-vector *vector-class*)
+    (make-built-in-class 'short-float-vector *vector-class*)
+    (alias-class 'long-float-vector (find-class 'double-float-vector))
+    (alias-class 'single-float-vector (find-class 'short-float-vector))
+    (make-built-in-class 'simple-double-float-vector (find-class 'double-float-vector) (find-class 'simple-1d-array))
+    (make-built-in-class 'simple-short-float-vector (find-class 'short-float-vector) (find-class 'simple-1d-array))
+    (alias-class 'simple-long-float-vector (find-class 'simple-double-float-vector))
+    (alias-class 'simple-single-float-vector (find-class 'simple-short-float-vector))
+    )
+
+  #+x8664-target
+  (progn
+    (make-built-in-class 'symbol-vector (find-class 'gvector))
+    (make-built-in-class 'function-vector (find-class 'gvector)))
+
+  #+64-bit-target
+  (progn
+    (make-built-in-class 'doubleword-vector *vector-class*)
+    (make-built-in-class 'simple-doubleword-vector (find-class 'doubleword-vector) (find-class 'simple-1d-array))
+    (make-built-in-class 'unsigned-doubleword-vector *vector-class*)
+    (make-built-in-class 'simple-unsigned-doubleword-vector (find-class 'unsigned-doubleword-vector) (find-class 'simple-1d-array))
+    )                                   ; #+64-bit-target
+
+  (make-built-in-class 'long-vector *vector-class*)
+  (make-built-in-class 'simple-long-vector (find-class 'long-vector) (find-class 'simple-1d-array))
+  (make-built-in-class 'unsigned-long-vector *vector-class*)
+  (make-built-in-class 'simple-unsigned-long-vector (find-class 'unsigned-long-vector) (find-class 'simple-1d-array))
+  (make-built-in-class 'byte-vector *vector-class*)
+  (make-built-in-class 'simple-byte-vector (find-class 'byte-vector) (find-class 'simple-1d-array))
+  (make-built-in-class 'bit-vector *vector-class*)
+  (make-built-in-class 'simple-bit-vector (find-class 'bit-vector) (find-class 'simple-1d-array))
+  (make-built-in-class 'word-vector *vector-class*)
+  (make-built-in-class 'simple-word-vector (find-class 'word-vector) (find-class 'simple-1d-array))
+  (make-built-in-class 'string *vector-class*)
+  (make-built-in-class 'base-string (find-class 'string))
+  (make-built-in-class 'simple-string (find-class 'string) (find-class 'simple-1d-array))
+  (make-built-in-class 'simple-base-string (find-class 'base-string) (find-class 'simple-string))
+  (make-built-in-class 'general-vector *vector-class*)
+  (make-built-in-class 'simple-vector (find-class 'general-vector) (find-class 'simple-1d-array))
+
+  (make-built-in-class 'hash-table-vector)
+  (make-built-in-class 'catch-frame)
+  (make-built-in-class 'code-vector)
+  #+ppc32-target
+  (make-built-in-class 'creole-object)
+
+  (make-built-in-class 'xfunction)
+  (make-built-in-class 'xcode-vector)
+
+  (defun class-cell-find-class (class-cell errorp)
+    (unless (istruct-typep class-cell 'class-cell)
+      (setq class-cell (%kernel-restart $xwrongtype class-cell 'class-cell)))
+    (locally (declare (type class-cell class-cell))
+      (let ((class (class-cell-class class-cell)))
+        (or class
+            (and 
+             (setq class (find-class (class-cell-name class-cell) nil))
+             (when class 
+               (setf (class-cell-class class-cell) class)
+               class))
+            (if errorp (error "Class ~s not found." (class-cell-name class-cell)) nil)))))
+
+;;; (%wrapper-class (instance.class-wrapper frob))
+
+
+
+  (defstatic *general-vector-class* (find-class 'general-vector))
+
+  #+ppc32-target
+  (defparameter *ivector-vector-classes*
+    (vector (find-class 'short-float-vector)
+            (find-class 'unsigned-long-vector)
+            (find-class 'long-vector)
+            (find-class 'fixnum-vector)
+            (find-class 'base-string)
+            (find-class 'unsigned-byte-vector)
+            (find-class 'byte-vector)
+            *t-class*                   ; old base-string
+            (find-class 'unsigned-word-vector)
+            (find-class 'word-vector)
+            (find-class 'double-float-vector)
+            (find-class 'bit-vector)))
+
+  #+ppc64-target
+  (defparameter *ivector-vector-classes*
+    (vector *t-class*
+            *t-class*
+            *t-class*
+            *t-class*
+            (find-class 'byte-vector)
+            (find-class 'word-vector)
+            (find-class 'long-vector)
+            (find-class 'doubleword-vector)
+            (find-class 'unsigned-byte-vector)
+            (find-class 'unsigned-word-vector)
+            (find-class 'unsigned-long-vector)
+            (find-class 'unsigned-doubleword-vector)
+            *t-class*
+            *t-class*
+            (find-class 'short-float-vector)
+            (find-class 'fixnum-vector)
+            *t-class*
+            *t-class*
+            *t-class*
+            (find-class 'double-float-vector)
+            (find-class 'base-string)
+            *t-class*
+            (find-class 'base-string)
+            *t-class*
+            *t-class*
+            *t-class*
+            *t-class*
+            *t-class*
+            *t-class*
+            (find-class 'bit-vector)
+            *t-class*
+            *t-class*))
+
+  #+x8632-target
+  (defparameter *ivector-vector-classes*
+    (vector (find-class 'short-float-vector)
+            (find-class 'unsigned-long-vector)
+            (find-class 'long-vector)
+            (find-class 'fixnum-vector)
+            (find-class 'base-string)
+            (find-class 'unsigned-byte-vector)
+            (find-class 'byte-vector)
+            *t-class*
+            (find-class 'unsigned-word-vector)
+            (find-class 'word-vector)
+            (find-class 'double-float-vector)
+            (find-class 'bit-vector)))
+
+  #+x8664-target
+  (progn
+    (defparameter *immheader-0-classes*
+      (vector *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              (find-class 'word-vector)
+              (find-class 'unsigned-word-vector)
+              (find-class 'base-string) ;old
+              (find-class 'byte-vector)
+              (find-class 'unsigned-byte-vector)
+              (find-class 'bit-vector)))
+
+    (defparameter *immheader-1-classes*
+      (vector *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              (find-class 'base-string)
+              (find-class 'long-vector)
+              (find-class 'unsigned-long-vector)
+              (find-class 'short-float-vector)))
+
+    (defparameter *immheader-2-classes*
+      (vector *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              *t-class*
+              (find-class 'fixnum-vector)
+              (find-class 'doubleword-vector)
+              (find-class 'unsigned-doubleword-vector)
+              (find-class 'double-float-vector))))
+
+
+
+  (defun make-foreign-object-domain (&key index name recognize class-of classp
+                                          instance-class-wrapper
+                                          class-own-wrapper
+                                          slots-vector class-ordinal
+                                          set-class-ordinal)
+    (%istruct 'foreign-object-domain index name recognize class-of classp
+              instance-class-wrapper class-own-wrapper slots-vector
+              class-ordinal set-class-ordinal))
+  
+  (let* ((n-foreign-object-domains 0)
+         (foreign-object-domains (make-array 10))
+         (foreign-object-domain-lock (make-lock)))
+    (defun register-foreign-object-domain (name
+                                           &key
+                                           recognize
+                                           class-of
+                                           classp
+                                           instance-class-wrapper
+                                           class-own-wrapper
+                                           slots-vector
+                                           class-ordinal
+                                           set-class-ordinal)
+      (with-lock-grabbed (foreign-object-domain-lock)
+        (dotimes (i n-foreign-object-domains)
+          (let* ((already (svref foreign-object-domains i)))
+            (when (eq name (foreign-object-domain-name already))
+              (setf (foreign-object-domain-recognize already) recognize
+                    (foreign-object-domain-class-of already) class-of
+                    (foreign-object-domain-classp already) classp
+                    (foreign-object-domain-instance-class-wrapper already)
+                    instance-class-wrapper
+                    (foreign-object-domain-class-own-wrapper already)
+                    class-own-wrapper
+                    (foreign-object-domain-slots-vector already) slots-vector
+                    (foreign-object-domain-class-ordinal already) class-ordinal
+                    (foreign-object-domain-set-class-ordinal already)
+                    set-class-ordinal)
+              (return-from register-foreign-object-domain i))))
+        (let* ((i n-foreign-object-domains)
+               (new (make-foreign-object-domain :index i
+                                                :name name
+                                                :recognize recognize
+                                                :class-of class-of
+                                                :classp classp
+                                                :instance-class-wrapper
+                                                instance-class-wrapper
+                                                :class-own-wrapper
+                                                class-own-wrapper
+                                                :slots-vector
+                                                slots-vector
+                                                :class-ordinal class-ordinal
+                                                :set-class-ordinal set-class-ordinal)))
+          (incf n-foreign-object-domains)
+          (if (= i (length foreign-object-domains))
+            (setq foreign-object-domains (%extend-vector i foreign-object-domains (* i 2))))
+          (setf (svref foreign-object-domains i) new)
+          i)))
+    (defun foreign-class-of (p)
+      (funcall (foreign-object-domain-class-of (svref foreign-object-domains (%macptr-domain p))) p))
+    (defun foreign-classp (p)
+      (funcall (foreign-object-domain-classp (svref foreign-object-domains (%macptr-domain p))) p))
+    (defun foreign-instance-class-wrapper (p)
+      (funcall (foreign-object-domain-instance-class-wrapper (svref foreign-object-domains (%macptr-domain p))) p))
+    (defun foreign-class-own-wrapper (p)
+      (funcall (foreign-object-domain-class-own-wrapper (svref foreign-object-domains (%macptr-domain p))) p))
+    (defun foreign-slots-vector (p)
+      (funcall (foreign-object-domain-slots-vector (svref foreign-object-domains (%macptr-domain p))) p))
+    (defun foreign-class-ordinal (p)
+      (funcall (foreign-object-domain-class-ordinal (svref foreign-object-domains (%macptr-domain p))) p))
+    (defun (setf foreign-class-ordinal) (new p)
+      (funcall (foreign-object-domain-set-class-ordinal (svref foreign-object-domains (%macptr-domain p))) p new))
+    (defun classify-foreign-pointer (p)
+      (do* ((i (1- n-foreign-object-domains) (1- i)))
+           ((zerop i) (error "this can't happen"))
+        (when (funcall (foreign-object-domain-recognize (svref foreign-object-domains i)) p)
+          (%set-macptr-domain p i)
+          (return p)))))
+
+  (defun constantly (x)
+    "Return a function that always returns VALUE."
+    #'(lambda (&rest ignore)
+        (declare (dynamic-extent ignore)
+                 (ignore ignore))
+        x))
+
+  (defun %register-type-ordinal-class (foreign-type class-name)
+    ;; ordinal-type-class shouldn't already exist
+    (with-lock-grabbed (ordinal-type-class-alist-lock)
+      (or (let* ((class (cdr (assq foreign-type ordinal-type-class-alist))))
+            (if (and class (eq class-name (class-name class)))
+              class))
+          (let* ((class (make-built-in-class class-name 'macptr)))
+            (push (cons foreign-type class) ordinal-type-class-alist)
+            class))))
+
+  (defun %ordinal-type-class-for-macptr (p)
+    (with-lock-grabbed (ordinal-type-class-alist-lock)
+      (or (unless (%null-ptr-p p)
+            (cdr (assoc (%macptr-type p) ordinal-type-class-alist :key #'foreign-type-ordinal)))
+          *macptr-class*)))
+                  
+
+  (register-foreign-object-domain :unclassified
+                                  :recognize #'(lambda (p)
+                                                 (declare (ignore p))
+                                                 (error "Shouldn't happen"))
+                                  :class-of #'(lambda (p)
+                                                (foreign-class-of
+                                                 (classify-foreign-pointer p)))
+                                  :classp #'(lambda (p)
+                                              (foreign-classp
+                                               (classify-foreign-pointer p)))
+                                  :instance-class-wrapper
+                                  #'(lambda (p)
+                                      (foreign-instance-class-wrapper
+                                       (classify-foreign-pointer p)))
+                                  :class-own-wrapper
+                                  #'(lambda (p)
+                                      (foreign-class-own-wrapper 
+                                       (classify-foreign-pointer p)))
+                                  :slots-vector
+                                  #'(lambda (p)
+                                      (foreign-slots-vector
+                                       (classify-foreign-pointer p))))
+
+;;; "Raw" macptrs, that aren't recognized as "standard foreign objects"
+;;; in some other domain, should always be recognized as such (and this
+;;; pretty much has to be domain #1.)
+
+  (register-foreign-object-domain :raw
+                                  :recognize #'true
+                                  :class-of #'%ordinal-type-class-for-macptr
+                                  :classp #'false
+                                  :instance-class-wrapper
+                                  (lambda (p)
+                                    (%class.own-wrapper (%ordinal-type-class-for-macptr p)))
+                                  :class-own-wrapper #'false
+                                  :slots-vector #'false)
+
+  (defstatic *class-table*
+      (let* ((v (make-array 256 :initial-element nil))
+             (class-of-function-function
+              #'(lambda (thing)
+                  (let ((bits (lfun-bits-known-function thing)))
+                    (declare (fixnum bits))
+                    (if (logbitp $lfbits-trampoline-bit bits)
+                      ;; closure
+                      (let ((inner-fn (closure-function thing)))
+                        (if (neq inner-fn thing)
+                          (let ((inner-bits (lfun-bits inner-fn)))
+                            (if (logbitp $lfbits-method-bit inner-bits)
+                              *compiled-lexical-closure-class*
+                              (if (logbitp $lfbits-gfn-bit inner-bits)
+                                (%wrapper-class (gf.instance.class-wrapper thing))
+                                (if (logbitp $lfbits-cm-bit inner-bits)
+                                  *combined-method-class*
+                                  *compiled-lexical-closure-class*))))
+                          *compiled-lexical-closure-class*))
+                      (if (logbitp  $lfbits-method-bit bits)
+                        *method-function-class* 
+                        (if (logbitp $lfbits-gfn-bit bits)
+                          (%wrapper-class (gf.instance.class-wrapper thing))
+                          (if (logbitp $lfbits-cm-bit bits)
+                            *combined-method-class*
+                            *compiled-function-class*))))))))
+        ;; Make one loop through the vector, initializing fixnum & list
+        ;; cells.  Set all immediates to *immediate-class*, then
+        ;; special-case characters later.
+        #+ppc32-target
+        (do* ((slice 0 (+ 8 slice)))
+             ((= slice 256))
+          (declare (type (unsigned-byte 8) slice))
+          (setf (%svref v (+ slice ppc32::fulltag-even-fixnum)) *fixnum-class*
+                (%svref v (+ slice ppc32::fulltag-odd-fixnum))  *fixnum-class*
+                (%svref v (+ slice ppc32::fulltag-cons)) *cons-class*
+                (%svref v (+ slice ppc32::fulltag-nil)) *null-class*
+                (%svref v (+ slice ppc32::fulltag-imm)) *immediate-class*))
+        #+ppc64-target
+        (do* ((slice 0 (+ 16 slice)))
+             ((= slice 256))
+          (declare (type (unsigned-byte 8) slice))
+          (setf (%svref v (+ slice ppc64::fulltag-even-fixnum)) *fixnum-class*
+                (%svref v (+ slice ppc64::fulltag-odd-fixnum))  *fixnum-class*
+                (%svref v (+ slice ppc64::fulltag-cons)) *cons-class*
+                (%svref v (+ slice ppc64::fulltag-imm-0)) *immediate-class*
+                (%svref v (+ slice ppc64::fulltag-imm-1)) *immediate-class*
+                (%svref v (+ slice ppc64::fulltag-imm-2)) *immediate-class*
+                (%svref v (+ slice ppc64::fulltag-imm-3)) *immediate-class*))
+        #+x8632-target
+        (do* ((slice 0 (+ 8 slice))
+	      (cons-fn #'(lambda (x) (if (null x) *null-class* *cons-class*))))
+             ((= slice 256))
+          (declare (type (unsigned-byte 8) slice))
+          (setf (%svref v (+ slice x8632::fulltag-even-fixnum)) *fixnum-class*
+                (%svref v (+ slice x8632::fulltag-odd-fixnum))  *fixnum-class*
+                (%svref v (+ slice x8632::fulltag-cons)) cons-fn
+                (%svref v (+ slice x8632::fulltag-tra)) *tagged-return-address-class*
+                (%svref v (+ slice x8632::fulltag-imm)) *immediate-class*))
+        #+x8664-target
+        (do* ((slice 0 (+ 16 slice)))
+             ((= slice 256))
+          (declare (type (unsigned-byte 8) slice))
+          (setf (%svref v (+ slice x8664::fulltag-even-fixnum)) *fixnum-class*
+                (%svref v (+ slice x8664::fulltag-odd-fixnum))  *fixnum-class*
+                (%svref v (+ slice x8664::fulltag-cons)) *cons-class*
+                (%svref v (+ slice x8664::fulltag-imm-0)) *immediate-class*
+                (%svref v (+ slice x8664::fulltag-imm-1)) *immediate-class*
+                (%svref v (+ slice x8664::fulltag-tra-0)) *tagged-return-address-class*
+                (%svref v (+ slice x8664::fulltag-tra-1)) *tagged-return-address-class*
+                (%svref v (+ slice x8664::fulltag-nil)) *null-class*))
+        (macrolet ((map-subtag (subtag class-name)
+                     `(setf (%svref v ,subtag) (find-class ',class-name))))
+          ;; immheader types map to built-in classes.
+          (map-subtag target::subtag-bignum bignum)
+          (map-subtag target::subtag-double-float double-float)
+          (map-subtag target::subtag-single-float short-float)
+          (map-subtag target::subtag-dead-macptr ivector)
+          #-x86-target
+          (map-subtag target::subtag-code-vector code-vector)
+          #+ppc32-target
+          (map-subtag ppc32::subtag-creole-object creole-object)
+          (map-subtag target::subtag-xcode-vector xcode-vector)
+          (map-subtag target::subtag-xfunction xfunction)
+          (map-subtag target::subtag-single-float-vector simple-short-float-vector)
+          #+64-bit-target
+          (map-subtag target::subtag-u64-vector simple-unsigned-doubleword-vector)
+          #+64-bit-target
+          (map-subtag target::subtag-s64-vector simple-doubleword-vector)
+          (map-subtag target::subtag-fixnum-vector simple-fixnum-vector)
+          (map-subtag target::subtag-u32-vector simple-unsigned-long-vector)
+          (map-subtag target::subtag-s32-vector simple-long-vector)
+          (map-subtag target::subtag-u8-vector simple-unsigned-byte-vector)
+          (map-subtag target::subtag-s8-vector simple-byte-vector)
+          (map-subtag target::subtag-simple-base-string simple-base-string)
+          (map-subtag target::subtag-u16-vector simple-unsigned-word-vector)
+          (map-subtag target::subtag-s16-vector simple-word-vector)
+          (map-subtag target::subtag-double-float-vector simple-double-float-vector)
+          (map-subtag target::subtag-bit-vector simple-bit-vector)
+          ;; Some nodeheader types map to built-in-classes; others require
+          ;; further dispatching.
+          (map-subtag target::subtag-ratio ratio)
+          (map-subtag target::subtag-complex complex)
+          (map-subtag target::subtag-catch-frame catch-frame)
+          (map-subtag target::subtag-hash-vector hash-table-vector)
+          (map-subtag target::subtag-value-cell value-cell)
+          (map-subtag target::subtag-pool pool)
+          (map-subtag target::subtag-weak population)
+          (map-subtag target::subtag-package package)
+          (map-subtag target::subtag-simple-vector simple-vector)
+          (map-subtag target::subtag-slot-vector slot-vector)
+          #+x8664-target (map-subtag x8664::subtag-symbol symbol-vector)
+          #+x8664-target (map-subtag x8664::subtag-function function-vector))
+        (setf (%svref v target::subtag-arrayH)
+              #'(lambda (x)
+                  (if (logbitp $arh_simple_bit
+                               (the fixnum (%svref x target::arrayH.flags-cell)))
+                    *simple-array-class*
+                    *array-class*)))
+        ;; These need to be special-cased:
+        (setf (%svref v target::subtag-macptr) #'foreign-class-of)
+        (setf (%svref v target::subtag-character)
+              #'(lambda (c) (let* ((code (%char-code c)))
+                              (if (or (eq c #\NewLine)
+                                      (and (>= code (char-code #\space))
+                                           (< code (char-code #\rubout))))
+                                *standard-char-class*
+                                *base-char-class*))))
+        (setf (%svref v target::subtag-struct)
+              #'(lambda (s) (%structure-class-of s))) ; need DEFSTRUCT
+        (setf (%svref v target::subtag-istruct)
+              #'(lambda (i)
+                  (let* ((cell (%svref i 0))
+                         (wrapper (istruct-cell-info  cell)))
+                    (if wrapper
+                      (%wrapper-class wrapper)
+                      (or (find-class (istruct-cell-name cell) nil)
+                          *istruct-class*)))))
+        (setf (%svref v target::subtag-basic-stream)
+              #'(lambda (b) (%wrapper-class (basic-stream.wrapper b))))
+        (setf (%svref v target::subtag-instance)
+              #'%class-of-instance)
+        (setf (%svref v #+ppc-target target::subtag-symbol
+		      #+x8632-target target::subtag-symbol
+		      #+x8664-target target::tag-symbol)
+              #-ppc64-target
+              #'(lambda (s) (if (eq (symbol-package s) *keyword-package*)
+                              *keyword-class*
+                              *symbol-class*))
+              #+ppc64-target
+              #'(lambda (s)
+                  (if s
+                    (if (eq (symbol-package s) *keyword-package*)
+                      *keyword-class*
+                      *symbol-class*)
+                    *null-class*)))
+        
+        (setf (%svref v
+                      #+ppc-target target::subtag-function
+                      #+x8632-target target::subtag-function
+                      #+x8664-target target::tag-function) 
+              class-of-function-function)
+        (setf (%svref v target::subtag-vectorH)
+              #'(lambda (v)
+                  (let* ((subtype (%array-header-subtype v)))
+                    (declare (fixnum subtype))
+                    (if (eql subtype target::subtag-simple-vector)
+                      *general-vector-class*
+                      #-x8664-target
+                      (%svref *ivector-vector-classes*
+                              #+ppc32-target
+                              (ash (the fixnum (- subtype ppc32::min-cl-ivector-subtag))
+                                   (- ppc32::ntagbits))
+                              #+ppc64-target
+                              (ash (the fixnum (logand subtype #x7f)) (- ppc64::nlowtagbits))
+			      #+x8632-target
+			      (ash (the fixnum (- subtype x8632::min-cl-ivector-subtag))
+				   (- x8632::ntagbits)))
+                      #+x8664-target
+                      (let* ((class (logand x8664::fulltagmask subtype))
+                             (idx (ash subtype (- x8664::ntagbits))))
+                        (cond ((= class x8664::fulltag-immheader-0)
+                               (%svref *immheader-0-classes* idx))
+                              ((= class x8664::fulltag-immheader-1)
+                               (%svref *immheader-1-classes* idx))
+                              ((= class x8664::fulltag-immheader-2)
+                               (%svref *immheader-2-classes* idx))
+                              (t *t-class*)))
+                               
+                      ))))
+        (setf (%svref v target::subtag-lock)
+              #'(lambda (thing)
+                  (case (%svref thing target::lock.kind-cell)
+                    (recursive-lock *recursive-lock-class*)
+                    (read-write-lock *read-write-lock-class*)
+                    (t *lock-class*))))
+        v))
+
+
+
+
+
+  (defun no-class-error (x)
+    (error "Bug (probably): can't determine class of ~s" x))
+  
+
+                                        ; return frob from table
+
+
+
+
+  )                                     ; end let
+
+
+
+(defun classp (x)
+  (if (%standard-instance-p x)
+    (< (the fixnum (instance.hash x)) max-class-ordinal)
+    (and (typep x 'macptr) (foreign-classp x))))
+
+(set-type-predicate 'class 'classp)
+
+(defun subclassp (c1 c2)
+  (and (classp c1)
+       (classp c2)
+       (not (null (memq c2 (%inited-class-cpl c1 t))))))
+
+(defun %class-get (class indicator &optional default)
+  (let ((cell (assq indicator (%class-alist class))))
+    (if cell (cdr cell) default)))
+
+(defun %class-put (class indicator value)
+  (let ((cell (assq indicator (%class-alist class))))
+    (if cell
+      (setf (cdr cell) value)
+      (push (cons indicator value) (%class-alist class))))
+  value)
+  
+(defsetf %class-get %class-put)
+
+(defun %class-remprop (class indicator)
+  (let* ((handle (cons nil (%class-alist class)))
+         (last handle))
+    (declare (dynamic-extent handle))
+    (while (cdr last)
+      (if (eq indicator (caar (%cdr last)))
+        (progn
+          (setf (%cdr last) (%cddr last))
+          (setf (%class-alist class) (%cdr handle)))
+        (setf last (%cdr last))))))    
+
+
+(pushnew :primary-classes *features*)
+
+(defun %class-primary-p (class)
+  (if (typep class 'slots-class)
+    (%class-get class :primary-p)
+    t))
+
+(defun (setf %class-primary-p) (value class)
+  (if value
+    (setf (%class-get class :primary-p) value)
+    (progn
+      (%class-remprop class :primary-p)
+      nil)))
+
+;;; Returns the first element of the CPL that is primary
+(defun %class-or-superclass-primary-p (class)
+  (unless (class-has-a-forward-referenced-superclass-p class)
+    (dolist (super (%inited-class-cpl class t))
+      (when (and (typep super 'standard-class) (%class-primary-p super))
+	(return super)))))
+
+
+;;; Bootstrapping version of union
+(unless (fboundp 'union)
+  (fset 'union (nlambda bootstrapping-union (l1 l2)
+                 (dolist (e l1)
+                   (unless (memq e l2)
+                     (push e l2)))
+                 l2))
+)
+
+(defun %add-direct-methods (method)
+  (dolist (spec (%method-specializers method))
+    (%do-add-direct-method spec method)))
+
+(defun %do-add-direct-method (spec method)
+  (pushnew method (specializer.direct-methods spec)))
+
+(defun %remove-direct-methods (method)
+  (dolist (spec (%method-specializers method))
+    (%do-remove-direct-method spec method)))
+
+(defun %do-remove-direct-method (spec method)
+  (setf (specializer.direct-methods spec)
+	(nremove method (specializer.direct-methods spec))))
+
+(ensure-generic-function 'initialize-instance
+			 :lambda-list '(instance &rest initargs &key &allow-other-keys))
+
+(defmethod find-method ((generic-function standard-generic-function)
+                        method-qualifiers specializers &optional (errorp t))
+  (dolist (m (%gf-methods generic-function)
+	   (when errorp
+             (cerror "Try finding the method again"
+                     "~s has no method for ~s ~s"
+                     generic-function method-qualifiers specializers)
+             (find-method generic-function method-qualifiers specializers
+                          errorp)))
+    (flet ((err ()
+	     (error "Wrong number of specializers: ~s" specializers)))
+      (let ((ss (%method-specializers m))
+	    (q (%method-qualifiers m))
+	    s)
+	(when (equal q method-qualifiers)
+	  (dolist (spec (canonicalize-specializers specializers nil)
+		   (if (null ss)
+		     (return-from find-method m)
+		     (err)))
+	    (unless (setq s (pop ss))
+	      (err))
+	    (unless (eq s spec)
+	      (return))))))))
+
+(defmethod create-reader-method-function ((class slots-class)
+					  (reader-method-class standard-reader-method)
+					  (dslotd direct-slot-definition))
+  #+ppc-target
+  (gvector :function
+           (uvref *reader-method-function-proto* 0)
+           (ensure-slot-id (%slot-definition-name dslotd))
+           'slot-id-value
+           nil				;method-function name
+           (dpb 1 $lfbits-numreq (ash 1 $lfbits-method-bit)))
+  #+x86-target
+  (%clone-x86-function
+   *reader-method-function-proto*
+   (ensure-slot-id (%slot-definition-name dslotd))
+   'slot-id-value
+   nil				;method-function name
+   (dpb 1 $lfbits-numreq (ash 1 $lfbits-method-bit))))
+
+(defmethod create-writer-method-function ((class slots-class)
+					  (writer-method-class standard-writer-method)
+					  (dslotd direct-slot-definition))
+  #+ppc-target
+  (gvector :function
+           (uvref *writer-method-function-proto* 0)
+           (ensure-slot-id (%slot-definition-name dslotd))
+           'set-slot-id-value
+           nil
+           (dpb 2 $lfbits-numreq (ash 1 $lfbits-method-bit)))
+  #+x86-target
+    (%clone-x86-function
+     *writer-method-function-proto*
+     (ensure-slot-id (%slot-definition-name dslotd))
+     'set-slot-id-value
+     nil
+     (dpb 2 $lfbits-numreq (ash 1 $lfbits-method-bit)))
+  )
+
+
+
+
+
+
+(defun %make-instance (class-cell &rest initargs)
+  (declare (dynamic-extent initargs))
+  (declare (optimize speed)) ;; make sure everything gets inlined that needs to be.
+  (apply #'make-instance
+         (or (class-cell-class class-cell) (class-cell-name  (the class-cell class-cell)))
+         initargs))
+
+
+(defmethod make-instance ((class symbol) &rest initargs)
+  (declare (dynamic-extent initargs))
+  (apply 'make-instance (find-class class) initargs))
+
+
+(defmethod make-instance ((class standard-class) &rest initargs &key &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (%make-std-instance class initargs))
+
+(defmethod make-instance ((class std-class) &rest initargs &key &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (%make-std-instance class initargs))
+
+
+(defun %make-std-instance (class initargs)
+  (setq initargs (default-initargs class initargs))
+  (when initargs
+    (apply #'check-initargs
+           nil class initargs t
+           #'initialize-instance #'allocate-instance #'shared-initialize
+           nil))
+  (let ((instance (apply #'allocate-instance class initargs)))
+    (apply #'initialize-instance instance initargs)
+    instance))
+
+(defun default-initargs (class initargs)
+  (unless (std-class-p class)
+    (setq class (require-type class 'std-class)))
+  (when (null (%class.cpl class)) (update-class class t))
+  (let ((defaults ()))
+    (dolist (key.form (%class-default-initargs class))
+      (unless (pl-search initargs (%car key.form))
+        (setq defaults
+              (list* (funcall (caddr key.form))
+                     (%car key.form)
+                     defaults))))
+    (when defaults
+      (setq initargs (append initargs (nreverse defaults))))
+    initargs))
+
+
+(defun %allocate-std-instance (class)
+  (unless (class-finalized-p class)
+    (finalize-inheritance class))
+  (let* ((wrapper (%class.own-wrapper class))
+         (len (length (%wrapper-instance-slots wrapper))))
+    (declare (fixnum len))
+    (make-instance-vector wrapper len)))
+
+
+
+
+(defmethod copy-instance ((instance standard-object))
+  (let* ((new-slots (copy-uvector (instance.slots instance)))
+	 (copy (gvector :instance 0 (instance-class-wrapper instance) new-slots)))
+    (setf (instance.hash copy) (strip-tag-to-fixnum copy)
+	  (slot-vector.instance new-slots) copy)))
+
+(defmethod initialize-instance ((instance standard-object) &rest initargs)
+  (declare (dynamic-extent initargs))
+  (apply 'shared-initialize instance t initargs))
+
+
+(defmethod reinitialize-instance ((instance standard-object) &rest initargs)
+  (declare (dynamic-extent initargs))
+  (when initargs
+    (check-initargs 
+     instance nil initargs t #'reinitialize-instance #'shared-initialize))
+  (apply 'shared-initialize instance nil initargs))
+
+(defmethod shared-initialize ((instance standard-object) slot-names &rest initargs)
+  (declare (dynamic-extent initargs))
+  (%shared-initialize instance slot-names initargs))
+
+(defmethod shared-initialize ((instance standard-generic-function) slot-names
+                              &rest initargs)
+  (declare (dynamic-extent initargs))
+  (%shared-initialize instance slot-names initargs))
+
+
+
+;;; Slot-value, slot-boundp, slot-makunbound, etc.
+(declaim (inline find-slotd))
+(defun find-slotd (name slots)
+  (dolist (slotd slots)
+    (when (eq name (standard-slot-definition.name slotd))
+      (return slotd))))
+
+(declaim (inline %std-slot-vector-value))
+
+(defun %std-slot-vector-value (slot-vector slotd)
+  (let* ((loc (standard-effective-slot-definition.location slotd)))
+    (symbol-macrolet ((instance (slot-vector.instance slot-vector)))
+      (typecase loc
+	(fixnum
+	 (%slot-ref slot-vector loc))
+	(cons
+	 (let* ((val (%cdr loc)))
+	   (if (eq val (%slot-unbound-marker))
+	     (slot-unbound (class-of instance) instance (standard-effective-slot-definition.name slotd))
+	   val)))
+      (t
+       (error "Slot definition ~s has invalid location ~s (allocation ~s)."
+ 	      slotd loc (slot-definition-allocation slotd)))))))
+
+
+(defmethod slot-value-using-class ((class standard-class)
+				   instance
+				   (slotd standard-effective-slot-definition))
+  (ecase (standard-slot-definition.allocation slotd)
+    ((:instance :class)
+     (%std-slot-vector-value (instance-slots instance) slotd))))
+
+(defun %maybe-std-slot-value-using-class (class instance slotd)
+  (if (and (eql (typecode class) target::subtag-instance)
+	   (eql (typecode slotd) target::subtag-instance)
+	   (eq *standard-effective-slot-definition-class-wrapper*
+	       (instance.class-wrapper slotd))
+	   (eq *standard-class-wrapper* (instance.class-wrapper class))
+           (let* ((allocation (standard-effective-slot-definition.location slotd)))
+             (or (eq allocation :instance) (eq allocation :class))))
+    (%std-slot-vector-value (instance-slots instance) slotd)
+    (if (= (the fixnum (typecode instance)) target::subtag-struct)
+      (struct-ref instance (standard-effective-slot-definition.location slotd))
+      (slot-value-using-class class instance slotd))))
+
+
+(declaim (inline  %set-std-slot-vector-value))
+
+(defun %set-std-slot-vector-value (slot-vector slotd  new)
+  (let* ((loc (standard-effective-slot-definition.location slotd))
+	 (type (standard-effective-slot-definition.type slotd))
+	 (type-predicate (standard-effective-slot-definition.type-predicate slotd)))
+    (unless (or (eq new (%slot-unbound-marker))
+                (null type-predicate)
+		(funcall type-predicate new))
+      (error 'bad-slot-type
+	     :instance (slot-vector.instance slot-vector)
+	     :datum new :expected-type type
+	     :slot-definition slotd))
+    (typecase loc
+      (fixnum
+       (setf (%svref slot-vector loc) new))
+      (cons
+       (setf (%cdr loc) new))
+      (t
+       (error "Slot definition ~s has invalid location ~s (allocation ~s)."
+	      slotd loc (slot-definition-allocation slotd))))))
+  
+  
+(defmethod (setf slot-value-using-class)
+    (new
+     (class standard-class)
+     instance
+     (slotd standard-effective-slot-definition))
+  (ecase (standard-slot-definition.allocation slotd)
+    ((:instance :class)
+     (%set-std-slot-vector-value (instance-slots instance) slotd new))))
+
+
+(defun %maybe-std-setf-slot-value-using-class (class instance slotd new)
+  (if (and (eql (typecode class) target::subtag-instance)
+	   (eql (typecode slotd) target::subtag-instance)
+	   (eq *standard-effective-slot-definition-class-wrapper*
+	       (instance.class-wrapper slotd))
+	   (eq *standard-class-wrapper* (instance.class-wrapper class))
+           (let* ((allocation (standard-effective-slot-definition.allocation slotd)))
+             (or (eq allocation :instance) (eq allocation :class))))
+    ;; Not safe to use instance.slots here, since the instance is not
+    ;; definitely of type SUBTAG-INSTANCE.  (Anyway, INSTANCE-SLOTS
+    ;; should be inlined here.)
+    (%set-std-slot-vector-value (instance-slots instance) slotd new)
+    (if (structurep instance)
+      (setf (struct-ref instance (standard-effective-slot-definition.location slotd))
+            new)
+      (setf (slot-value-using-class class instance slotd) new))))
+
+(defmethod slot-value-using-class ((class funcallable-standard-class)
+				   instance
+				   (slotd standard-effective-slot-definition))
+  (%std-slot-vector-value (gf.slots instance) slotd))
+
+(defmethod (setf slot-value-using-class)
+    (new
+     (class funcallable-standard-class)
+     instance
+     (slotd standard-effective-slot-definition))
+  (%set-std-slot-vector-value (gf.slots instance) slotd new))
+
+(defun slot-value (instance slot-name)
+  (let* ((wrapper
+          (let* ((w (instance-class-wrapper instance)))
+            (if (eql 0 (%wrapper-hash-index w))
+              (instance.class-wrapper (update-obsolete-instance instance))
+              w)))
+         (class (%wrapper-class wrapper))
+         (slotd (find-slotd slot-name (if (%standard-instance-p class)
+                                        (%class.slots class)
+                                        (class-slots class)))))
+    (if slotd
+      (%maybe-std-slot-value-using-class class instance slotd)
+      (if (typep slot-name 'symbol)
+        (restart-case
+         (values (slot-missing class instance slot-name 'slot-value))
+         (continue ()
+                   :report "Try accessing the slot again"
+                   (slot-value instance slot-name))
+         (use-value (value)
+                    :report "Return a value"
+                    :interactive (lambda ()
+                                   (format *query-io* "~&Value to use: ")
+                                   (list (read *query-io*)))
+                    value))
+        (report-bad-arg slot-name 'symbol)))))
+
+
+(defmethod slot-unbound (class instance slot-name)
+  (declare (ignore class))
+  (restart-case (error 'unbound-slot :name slot-name :instance instance)
+    (use-value (value)
+      :report "Return a value"
+      :interactive (lambda ()
+                     (format *query-io* "~&Value to use: ")
+                     (list (read *query-io*)))
+      value)))
+
+
+
+(defmethod slot-makunbound-using-class ((class slots-class)
+					instance
+					(slotd standard-effective-slot-definition))
+  (setf (slot-value-using-class class instance slotd) (%slot-unbound-marker))
+  instance)
+
+(defmethod slot-missing (class object slot-name operation &optional new-value)
+  (declare (ignore class operation new-value))
+  (error "~s has no slot named ~s." object slot-name))
+
+
+(defun set-slot-value (instance name value)
+  (let* ((wrapper
+          (let* ((w (instance-class-wrapper instance)))
+            (if (eql 0 (%wrapper-hash-index w))
+              (instance.class-wrapper (update-obsolete-instance instance))
+              w)))
+         (class (%wrapper-class wrapper))
+         (slotd (find-slotd name (if (%standard-instance-p class)
+                                   (%class.slots class)
+                                   (class-slots class)))))
+    (if slotd
+      (%maybe-std-setf-slot-value-using-class class instance slotd value)
+      (if (typep name 'symbol)
+        (progn	    
+          (slot-missing class instance name 'setf value)
+          value)
+        (report-bad-arg name 'symbol)))))
+
+(defsetf slot-value set-slot-value)
+
+(defun slot-makunbound (instance name)
+  (let* ((class (class-of instance))
+	 (slotd (find-slotd name (%class-slots class))))
+    (if slotd
+      (slot-makunbound-using-class class instance slotd)
+      (slot-missing class instance name 'slot-makunbound))
+    instance))
+
+(defun %std-slot-vector-boundp (slot-vector slotd)
+  (let* ((loc (standard-effective-slot-definition.location slotd)))
+    (typecase loc
+      (fixnum
+       (not (eq (%svref slot-vector loc) (%slot-unbound-marker))))
+      (cons
+       (not (eq (%cdr loc) (%slot-unbound-marker))))
+      (t
+       (error "Slot definition ~s has invalid location ~s (allocation ~s)."
+		slotd loc (slot-definition-allocation slotd))))))
+
+(defun %maybe-std-slot-boundp-using-class (class instance slotd)
+  (if (and (eql (typecode class) target::subtag-instance)
+	   (eql (typecode slotd) target::subtag-instance)
+	   (eq *standard-effective-slot-definition-class-wrapper*
+	       (instance.class-wrapper slotd))
+	   (eq *standard-class-wrapper* (instance.class-wrapper class))
+           (let* ((allocation (standard-slot-definition.allocation slotd)))
+             (or (eq allocation :class)
+                 (eq allocation :instance))))
+    (%std-slot-vector-boundp (instance-slots instance) slotd)
+    (slot-boundp-using-class class instance slotd)))
+
+
+(defmethod slot-boundp-using-class ((class standard-class)
+				    instance
+				    (slotd standard-effective-slot-definition))
+  (ecase (standard-slot-definition.allocation slotd)
+    ((:instance :class)
+     (%std-slot-vector-boundp (instance-slots instance) slotd))))
+
+(defmethod slot-boundp-using-class ((class funcallable-standard-class)
+				    instance
+				    (slotd standard-effective-slot-definition))
+  (%std-slot-vector-boundp (gf.slots instance) slotd))
+
+
+
+(defun slot-boundp (instance name)
+  (let* ((wrapper
+          (let* ((w (instance-class-wrapper instance)))
+            (if (eql 0 (%wrapper-hash-index w))
+              (instance.class-wrapper (update-obsolete-instance instance))
+              w)))
+         (class (%wrapper-class wrapper))
+         (slotd (find-slotd name (if (%standard-instance-p class)
+                                   (%class.slots class)
+                                   (class-slots class)))))
+    (if slotd
+      (%maybe-std-slot-boundp-using-class class instance slotd)
+      (if (typep name 'symbol)
+        (values (slot-missing class instance name 'slot-boundp))
+        (report-bad-arg name 'symbol)))))
+
+(defun slot-value-if-bound (instance name &optional default)
+  (if (slot-boundp instance name)
+    (slot-value instance name)
+    default))
+
+(defun slot-exists-p (instance name)
+  (let* ((class (class-of instance))
+	 (slots  (class-slots class)))
+    (find-slotd name slots)))
+
+
+(defun slot-id-value (instance slot-id)
+  (let* ((wrapper (instance-class-wrapper instance)))
+    (funcall (%wrapper-slot-id-value wrapper) instance slot-id)))
+
+(defun set-slot-id-value (instance slot-id value)
+  (let* ((wrapper (instance-class-wrapper instance)))
+    (funcall (%wrapper-set-slot-id-value wrapper) instance slot-id value)))
+
+(defun slot-id-boundp (instance slot-id)
+  (let* ((wrapper (instance-class-wrapper instance))
+         (class (%wrapper-class wrapper))
+         (slotd (funcall (%wrapper-slot-id->slotd wrapper) instance slot-id)))
+    (if slotd
+      (%maybe-std-slot-boundp-using-class class instance slotd)
+      (values (slot-missing class instance (slot-id.name slot-id) 'slot-boundp)))))
+  
+;;; returns nil if (apply gf args) wil cause an error because of the
+;;; non-existance of a method (or if GF is not a generic function or the name
+;;; of a generic function).
+(defun method-exists-p (gf &rest args)
+  (declare (dynamic-extent args))
+  (when (symbolp gf)
+    (setq gf (fboundp gf)))
+  (when (typep gf 'standard-generic-function)
+    (or (null args)
+        (let* ((methods (sgf.methods gf)))
+          (dolist (m methods)
+            (when (null (%method-qualifiers m))
+              (let ((specializers (%method-specializers m))
+                    (args args))
+                (when (dolist (s specializers t)
+                        (unless (cond ((typep s 'eql-specializer) 
+				       (eql (eql-specializer-object s)
+					    (car args)))
+                                      (t (memq s (%inited-class-cpl
+                                                  (class-of (car args))))))
+                          (return nil))
+                        (pop args))
+                  (return-from method-exists-p m)))))
+          nil))))
+
+(defun funcall-if-method-exists (gf &optional default &rest args)
+  (declare (dynamic-extent args))
+  (if (apply #'method-exists-p gf args)
+    (apply gf args)
+    (if default (apply default args))))
+
+
+(defun find-specializer (specializer)
+  (if (and (listp specializer) (eql (car specializer) 'eql))
+    (intern-eql-specializer (cadr specializer))
+    (find-class specializer)))
+
+(defmethod make-instances-obsolete ((class symbol))
+  (make-instances-obsolete (find-class class)))
+
+(defmethod make-instances-obsolete ((class standard-class))
+  (let ((wrapper (%class-own-wrapper class)))
+    (when wrapper
+      (setf (%class-own-wrapper class) nil)
+      (make-wrapper-obsolete wrapper)))
+  class)
+
+(defmethod make-instances-obsolete ((class funcallable-standard-class))
+  (let ((wrapper (%class.own-wrapper class)))
+    (when wrapper
+      (setf (%class-own-wrapper class) nil)
+      (make-wrapper-obsolete wrapper)))
+  class)
+
+(defmethod make-instances-obsolete ((class structure-class))
+  ;; could maybe warn that instances are obsolete, but there's not
+  ;; much that we can do about that.
+  class)
+
+
+
+;;; A wrapper is made obsolete by setting the hash-index & instance-slots to 0
+;;; The instance slots are saved for update-obsolete-instance
+;;; by consing them onto the class slots.
+;;; Method dispatch looks at the hash-index.
+;;; slot-value & set-slot-value look at the instance-slots.
+;;; Each wrapper may have an associated forwarding wrapper, which must
+;;; also be made obsolete.  The forwarding-wrapper is stored in the
+;;; hash table below keyed on the wrapper-hash-index of the two
+;;; wrappers.
+(defvar *forwarding-wrapper-hash-table* (make-hash-table :test 'eq))  
+
+
+(defun make-wrapper-obsolete (wrapper)
+  (without-interrupts
+   (let ((forwarding-info
+          (unless (eql 0 (%wrapper-instance-slots wrapper))   ; already forwarded or obsolete?
+            (%cons-forwarding-info (%wrapper-instance-slots wrapper)
+                                   (%wrapper-class-slots wrapper)))))
+     (when forwarding-info
+       (setf (%wrapper-hash-index wrapper) 0
+             (%wrapper-cpl wrapper) nil
+             (%wrapper-cpl-bits wrapper) nil
+             (%wrapper-instance-slots wrapper) 0
+             (%wrapper-forwarding-info wrapper) forwarding-info
+	     (%wrapper-slot-id->slotd wrapper) #'%slot-id-lookup-obsolete
+	     (%wrapper-slot-id-value wrapper) #'%slot-id-ref-obsolete
+	     (%wrapper-set-slot-id-value wrapper) #'%slot-id-set-obsolete
+             ))))
+  wrapper)
+
+(defun %clear-class-primary-slot-accessor-offsets (class)
+  (let ((info-list (%class-get class '%class-primary-slot-accessor-info)))
+    (dolist (info info-list)
+      (setf (%slot-accessor-info.offset info) nil))))
+
+(defun primary-class-slot-offset (class slot-name)
+  (dolist (super (%class.cpl class))
+    (let* ((pos (and (typep super 'standard-class)
+                     (%class-primary-p super)
+                     (dolist (slot (%class-slots class))
+		       (when (eq (%slot-definition-allocation slot)
+				 :instance)
+			 (when (eq slot-name (%slot-definition-name slot))
+			   (return (%slot-definition-location slot))))))))
+      (when pos (return pos)))))
+
+;;; Called by the compiler-macro expansion for slot-value
+;;; info is the result of a %class-primary-slot-accessor-info call.
+;;; value-form is specified if this is set-slot-value.
+;;; Otherwise it's slot-value.
+(defun primary-class-slot-value (instance info &optional (value-form nil value-form-p))
+  (let ((slot-name (%slot-accessor-info.slot-name info)))
+    (prog1
+      (if value-form-p
+        (setf (slot-value instance slot-name) value-form)
+        (slot-value instance slot-name))
+      (setf (%slot-accessor-info.offset info)
+            (primary-class-slot-offset (class-of instance) slot-name)))))
+
+(defun primary-class-accessor (instance info &optional (value-form nil value-form-p))
+  (let ((accessor (%slot-accessor-info.accessor info)))
+    (prog1
+      (if value-form-p
+        (funcall accessor value-form instance)
+        (funcall accessor instance))
+      (let ((methods (compute-applicable-methods
+                      accessor
+                      (if value-form-p (list value-form instance) (list instance))))
+            method)
+        (when (and (eql (length methods) 1)
+                   (typep (setq method (car methods)) 'standard-accessor-method))
+          (let* ((slot-name (method-slot-name method)))
+            (setf (%slot-accessor-info.offset info)
+                  (primary-class-slot-offset (class-of instance) slot-name))))))))
+
+(defun exchange-slot-vectors-and-wrappers (a b)
+  (if (typep a 'generic-function)
+    (let* ((temp-wrapper (gf.instance.class-wrapper a))
+           (orig-a-slots (gf.slots a))
+           (orig-b-slots (gf.slots b)))
+      (setf (gf.instance.class-wrapper a) (gf.instance.class-wrapper b)
+            (gf.instance.class-wrapper b) temp-wrapper
+            (gf.slots a) orig-b-slots
+            (gf.slots b) orig-a-slots
+            (slot-vector.instance orig-a-slots) b
+            (slot-vector.instance orig-b-slots) a))    
+    (let* ((temp-wrapper (instance.class-wrapper a))
+           (orig-a-slots (instance.slots a))
+           (orig-b-slots (instance.slots b)))
+      (setf (instance.class-wrapper a) (instance.class-wrapper b)
+            (instance.class-wrapper b) temp-wrapper
+            (instance.slots a) orig-b-slots
+            (instance.slots b) orig-a-slots
+            (slot-vector.instance orig-a-slots) b
+            (slot-vector.instance orig-b-slots) a))))
+
+
+
+
+;;; How slot values transfer (from PCL):
+;;;
+;;; local  --> local        transfer 
+;;; local  --> shared       discard
+;;; local  -->  --          discard
+;;; shared --> local        transfer
+;;; shared --> shared       discard
+;;; shared -->  --          discard
+;;;  --    --> local        added
+;;;  --    --> shared        --
+;;;
+;;; See make-wrapper-obsolete to see how we got here.
+;;; A word about forwarding.  When a class is made obsolete, the
+;;; %wrapper-instance-slots slot of its wrapper is set to 0.
+;;; %wrapper-class-slots = (instance-slots . class-slots)
+;;; Note: this should stack-cons the new-instance if we can reuse the
+;;; old instance or it's forwarded value.
+(defun update-obsolete-instance (instance)
+  (let* ((added ())
+	 (discarded ())
+	 (plist ()))
+    (without-interrupts			; Not -close- to being correct
+     (let* ((old-wrapper (standard-object-p instance)))
+       (unless old-wrapper
+         (when (standard-generic-function-p instance)
+           (setq old-wrapper (gf.instance.class-wrapper instance)))
+         (unless old-wrapper
+           (report-bad-arg instance '(or standard-instance standard-generic-function))))
+       (when (eql 0 (%wrapper-instance-slots old-wrapper))   ; is it really obsolete?
+         (let* ((class (%wrapper-class old-wrapper))
+                (new-wrapper (or (%class.own-wrapper class)
+                                 (progn
+                                   (update-class class t)
+                                   (%class.own-wrapper class))))
+                (forwarding-info (%wrapper-forwarding-info old-wrapper))
+                (old-class-slots (%forwarding-class-slots forwarding-info))
+                (old-instance-slots (%forwarding-instance-slots forwarding-info))
+                (new-instance-slots (%wrapper-instance-slots new-wrapper))
+                (new-class-slots (%wrapper-class-slots new-wrapper))
+		(new-instance (allocate-instance class))
+		(old-slot-vector (instance.slots instance))
+		(new-slot-vector (instance.slots new-instance)))
+             ;; Lots to do.  Hold onto your hat.
+             (let* ((old-size (uvsize old-instance-slots))
+		    (new-size (uvsize new-instance-slots)))
+	       (declare (fixnum old-size new-size))
+               (dotimes (i old-size)
+	         (declare (fixnum i))
+                 (let* ((slot-name (%svref old-instance-slots i))
+                        (pos (%vector-member slot-name new-instance-slots))
+                        (val (%svref old-slot-vector (%i+ i 1))))
+                   (if pos
+                     (setf (%svref new-slot-vector (%i+ pos 1)) val)
+                     (progn
+		       (push slot-name discarded)
+		       (unless (eq val (%slot-unbound-marker))
+			 (setf (getf plist slot-name) val))))))
+               ;; Go through old class slots
+               (dolist (pair old-class-slots)
+                 (let* ((slot-name (%car pair))
+                        (val (%cdr pair))
+                        (pos (%vector-member slot-name new-instance-slots)))
+                   (if pos
+                     (setf (%svref new-slot-vector (%i+ pos 1)) val)
+                     (progn
+		       (push slot-name discarded)
+		       (unless (eq val (%slot-unbound-marker))
+			 (setf (getf plist slot-name) val))))))
+               ; Go through new instance slots
+               (dotimes (i new-size)
+	         (declare (fixnum i))
+                 (let* ((slot-name (%svref new-instance-slots i)))
+                   (unless (or (%vector-member slot-name old-instance-slots)
+                               (assoc slot-name old-class-slots))
+                     (push slot-name added))))
+               ;; Go through new class slots
+               (dolist (pair new-class-slots)
+                 (let ((slot-name (%car pair)))
+                   (unless (or (%vector-member slot-name old-instance-slots)
+                               (assoc slot-name old-class-slots))
+                     (push slot-name added))))
+               (exchange-slot-vectors-and-wrappers new-instance instance))))))
+    ;; run user code with interrupts enabled.
+    (update-instance-for-redefined-class instance added discarded plist))
+  instance)
+            
+          
+(defmethod update-instance-for-redefined-class ((instance standard-object)
+						added-slots
+						discarded-slots
+						property-list
+						&rest initargs)
+  (declare (ignore discarded-slots property-list))
+  (when initargs
+    (check-initargs
+     instance nil initargs t
+     #'update-instance-for-redefined-class #'shared-initialize))
+  (apply #'shared-initialize instance added-slots initargs))
+
+(defmethod update-instance-for-redefined-class ((instance standard-generic-function)
+						added-slots
+						discarded-slots
+						property-list
+						&rest initargs)
+  (declare (ignore discarded-slots property-list))
+  (when initargs
+    (check-initargs
+     instance nil initargs t
+     #'update-instance-for-redefined-class #'shared-initialize))
+  (apply #'shared-initialize instance added-slots initargs))
+
+(defun check-initargs (instance class initargs errorp &rest functions)
+  (declare (dynamic-extent functions))
+  (declare (list functions))
+  (setq class (require-type (or class (class-of instance)) 'std-class))
+  (unless (getf initargs :allow-other-keys)
+    (let ((initvect (initargs-vector instance class functions)))
+      (when (eq initvect t) (return-from check-initargs nil))
+      (do* ((tail initargs (cddr tail))
+	    (initarg (car tail) (car tail))
+	    bad-keys? bad-key)
+	   ((null (cdr tail))
+	    (if bad-keys?
+	      (if errorp
+		(signal-program-error
+		 "~s is an invalid initarg to ~s for ~s.~%~
+                                    Valid initargs: ~s."
+		 bad-key
+		 (function-name (car functions))
+		 class (coerce initvect 'list))
+		(values bad-keys? bad-key))))
+	(if (eq initarg :allow-other-keys)
+	  (if (cadr tail)
+	    (return))                   ; (... :allow-other-keys t ...)
+	  (unless (or bad-keys? (%vector-member initarg initvect))
+	    (setq bad-keys? t
+		  bad-key initarg)))))))
+
+(defun initargs-vector (instance class functions)
+  (let ((index (cadr (assq (car functions) *initialization-invalidation-alist*))))
+    (unless index
+      (error "Unknown initialization function: ~s." (car functions)))
+    (let ((initvect (%svref (instance-slots class) index)))
+      (unless initvect
+        (setf (%svref (instance-slots class) index) 
+              (setq initvect (compute-initargs-vector instance class functions))))
+      initvect)))
+
+
+;; This is used for compile-time defclass option checking.
+(defun class-keyvect (class-arg initargs)
+  (let* ((class (if (typep class-arg 'class) class-arg (find-class class-arg nil)))
+	 (meta-arg (getf initargs :metaclass (if (and class (not (typep class 'forward-referenced-class)))
+					       (class-of class)
+					       *standard-class-class*)))
+	 (meta-spec (if (quoted-form-p meta-arg) (%cadr meta-arg) meta-arg))
+	 (meta (if (typep meta-spec 'class) meta-spec (find-class meta-spec nil))))
+    (if (and meta (not (typep meta 'forward-referenced-class)))
+      (compute-initargs-vector class meta (list #'initialize-instance #'allocate-instance #'shared-initialize) t)
+      t)))
+
+(defun compute-initargs-vector (instance class functions &optional require-rest)
+  (let ((initargs (class-slot-initargs class))
+        (cpl (%inited-class-cpl class)))
+    (dolist (f functions)         ; for all the functions passed
+      #+no
+      (if (logbitp $lfbits-aok-bit (lfun-bits f))
+	(return-from compute-initargs-vector t))
+      (dolist (method (%gf-methods f))   ; for each applicable method
+        (let ((spec (car (%method-specializers method))))
+          (when (if (typep spec 'eql-specializer)
+                  (eql instance (eql-specializer-object spec))
+                  (memq spec cpl))
+            (let* ((func (%inner-method-function method))
+                   (keyvect (if (and (logbitp $lfbits-aok-bit (lfun-bits func))
+				     (or (not require-rest)
+					 (logbitp $lfbits-rest-bit (lfun-bits func))))
+			      (return-from compute-initargs-vector t)
+                              (lfun-keyvect func))))
+              (dovector (key keyvect)
+                (pushnew key initargs)))))))   ; add all of the method's keys
+    (apply #'vector initargs)))
+
+
+
+;;; A useful function
+(defun class-make-instance-initargs (class)
+  (setq class (require-type (if (symbolp class) (find-class class) class)
+                            'std-class))
+  (flet ((iv (class &rest functions)
+           (declare (dynamic-extent functions))
+           (initargs-vector (class-prototype class) class functions)))
+    (let ((initvect (apply #'iv
+                           class
+                           #'initialize-instance #'allocate-instance #'shared-initialize
+                           nil)))
+      (if (eq initvect 't)
+        t
+        (concatenate 'list initvect)))))
+
+                                   
+
+;;; This is part of the MOP
+;;; Maybe it was, at one point in the distant past ...
+(defmethod class-slot-initargs ((class slots-class))
+  (collect ((initargs))
+    (dolist (slot (%class-slots class) (initargs))
+      (dolist (i (%slot-definition-initargs slot))
+        (initargs i)))))
+
+  
+(defun maybe-update-obsolete-instance (instance)
+  (let ((wrapper (standard-object-p instance)))
+    (unless wrapper
+              (when (typep instance 'funcallable-standard-object)
+          (setq wrapper (gf.instance.class-wrapper instance)))
+      
+      (unless wrapper
+        (report-bad-arg instance '(or standard-object funcallable-standard-object))))
+    (when (eql 0 (%wrapper-hash-index wrapper))
+      (update-obsolete-instance instance)))
+  instance)
+
+
+;;; If you ever reference one of these through anyone who might call
+;;; update-obsolete-instance, you will lose badly.
+(defun %maybe-forwarded-instance (instance)
+  (maybe-update-obsolete-instance instance)
+  instance)
+
+
+
+(defmethod change-class (instance
+			 (new-class symbol)
+			 &rest initargs &key &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (apply #'change-class instance (find-class new-class) initargs))
+
+(defmethod change-class ((instance standard-object)
+			 (new-class standard-class)
+			  &rest initargs &key &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (%change-class instance new-class initargs))
+
+
+(defun %change-class (object new-class initargs)
+  (let* ((old-class (class-of object))
+	 (old-wrapper (%class.own-wrapper old-class))
+	 (new-wrapper (or (%class.own-wrapper new-class)
+			  (progn
+			    (update-class new-class t)
+			    (%class.own-wrapper new-class))))
+	 (old-instance-slots-vector (%wrapper-instance-slots old-wrapper))
+	 (new-instance-slots-vector (%wrapper-instance-slots new-wrapper))
+	 (num-new-instance-slots (length new-instance-slots-vector))
+	 (new-object (allocate-instance new-class)))
+    (declare (fixnum num-new-instance-slots)
+	     (simple-vector new-instance-slots-vector old-instance-slots-vector))
+    ;; Retain local slots shared between the new class and the old.
+    (do* ((new-pos 0 (1+ new-pos))
+	  (new-slot-location 1 (1+ new-slot-location)))
+	 ((= new-pos num-new-instance-slots))
+      (declare (fixnum new-pos new-slot-location))
+      (let* ((old-pos (position (svref new-instance-slots-vector new-pos)
+				old-instance-slots-vector :test #'eq)))
+	(when old-pos
+	  (setf (%standard-instance-instance-location-access
+		 new-object
+		 new-slot-location)
+		(%standard-instance-instance-location-access
+		 object
+		 (the fixnum (1+ (the fixnum old-pos))))))))
+    ;; If the new class defines a local slot whos name matches
+    ;; that of a shared slot in the old class, the shared slot's
+    ;; value is used to initialize the new instance's local slot.
+    (dolist (shared-slot (%wrapper-class-slots old-wrapper))
+      (destructuring-bind (name . value) shared-slot
+	(let* ((new-slot-pos (position name new-instance-slots-vector
+				       :test #'eq)))
+	  (if new-slot-pos
+	    (setf (%standard-instance-instance-location-access
+		   new-object
+		   (the fixnum (1+ (the fixnum new-slot-pos))))
+		  value)))))
+    (exchange-slot-vectors-and-wrappers object new-object)
+    (apply #'update-instance-for-different-class new-object object initargs)
+    object))
+
+(defmethod update-instance-for-different-class ((previous standard-object)
+                                                (current standard-object)
+                                                &rest initargs)
+  (declare (dynamic-extent initargs))
+  (%update-instance-for-different-class previous current initargs))
+
+(defun %update-instance-for-different-class (previous current initargs)
+  (when initargs
+    (check-initargs
+     current nil initargs t
+     #'update-instance-for-different-class #'shared-initialize))
+  (let* ((previous-slots (class-slots (class-of previous)))
+	 (current-slots (class-slots (class-of current)))
+	 (added-slot-names ()))
+    (dolist (s current-slots)
+      (let* ((name (%slot-definition-name s)))
+	(unless (find-slotd name previous-slots)
+	  (push name added-slot-names))))
+    (apply #'shared-initialize
+	   current
+	   added-slot-names
+	   initargs)))
+
+
+
+
+;;; Clear all the valid initargs caches.
+(defun clear-valid-initargs-caches ()
+  (map-classes #'(lambda (name class)
+                   (declare (ignore name))
+                   (when (std-class-p class)
+                     (setf (%class.make-instance-initargs class) nil
+                           (%class.reinit-initargs class) nil
+                           (%class.redefined-initargs class) nil
+                           (%class.changed-initargs class) nil)))))
+
+(defun clear-clos-caches ()
+  (clear-all-gf-caches)
+  (clear-valid-initargs-caches))
+
+(defmethod allocate-instance ((class standard-class) &rest initargs)
+  (declare (ignore initargs))
+  (%allocate-std-instance class))
+
+(defmethod allocate-instance ((class funcallable-standard-class) &rest initargs)
+  (declare (ignore initargs))
+  (%allocate-gf-instance class))
+
+(unless *initialization-invalidation-alist*
+  (setq *initialization-invalidation-alist*
+        (list (list #'initialize-instance %class.make-instance-initargs)
+              (list #'allocate-instance %class.make-instance-initargs)
+              (list #'reinitialize-instance %class.reinit-initargs)
+              (list #'shared-initialize 
+                    %class.make-instance-initargs %class.reinit-initargs
+                    %class.redefined-initargs %class.changed-initargs)
+              (list #'update-instance-for-redefined-class
+                    %class.redefined-initargs)
+              (list #'update-instance-for-different-class
+                    %class.changed-initargs))))
+
+
+(defstatic *initialization-function-lists*
+  (list (list #'initialize-instance #'allocate-instance #'shared-initialize)
+        (list #'reinitialize-instance #'shared-initialize)
+        (list #'update-instance-for-redefined-class #'shared-initialize)
+        (list #'update-instance-for-different-class #'shared-initialize)))
+
+
+
+(unless *clos-initialization-functions*
+  (setq *clos-initialization-functions*
+        (list #'initialize-instance #'allocate-instance #'shared-initialize
+              #'reinitialize-instance
+              #'update-instance-for-different-class #'update-instance-for-redefined-class)))
+
+(defun compute-initialization-functions-alist ()
+  (let ((res nil)
+        (lists *initialization-function-lists*))
+    (dolist (cell *initialization-invalidation-alist*)
+      (let (res-list)
+        (dolist (slot-num (cdr cell))
+          (push
+           (ecase slot-num
+             (#.%class.make-instance-initargs 
+              (assq #'initialize-instance lists))
+             (#.%class.reinit-initargs
+              (assq #'reinitialize-instance lists))
+             (#.%class.redefined-initargs
+              (assq #'update-instance-for-redefined-class lists))
+             (#.%class.changed-initargs
+              (assq #'update-instance-for-different-class lists)))
+           res-list))
+        (push (cons (car cell) (nreverse res-list)) res)))
+    (setq *initialization-functions-alist* res)))
+
+(compute-initialization-functions-alist)
+
+                  
+
+
+
+
+;;; Need to define this for all of the BUILT-IN-CLASSes.
+(defmethod class-prototype ((class class))
+  (%class.prototype class))
+
+(defmethod class-prototype ((class std-class))
+  (or (%class.prototype class)
+      (setf (%class.prototype class) (allocate-instance class))))
+
+
+(defun gf-class-prototype (class)
+  (%allocate-gf-instance class))
+
+
+
+(defmethod class-prototype ((class structure-class))
+  (or (%class.prototype class)
+      (setf (%class.prototype class)
+            (let* ((sd (gethash (class-name class) %defstructs%))
+                   (slots (class-slots class))
+                   (proto (allocate-typed-vector :struct (1+ (length slots)))))
+              (setf (uvref proto 0) (sd-superclasses sd))
+              (dolist (slot slots proto)
+                (setf (slot-value-using-class class proto slot)
+                      (funcall (slot-definition-initfunction slot))))))))
+
+
+(defmethod remove-method ((generic-function standard-generic-function)
+                          (method standard-method))
+  (when (eq generic-function (%method-gf method))
+    (%remove-standard-method-from-containing-gf method))
+  generic-function)
+
+
+
+(defmethod function-keywords ((method standard-method))
+  (let ((f (%inner-method-function method)))
+    (values
+     (concatenate 'list (lfun-keyvect f))
+     (%ilogbitp $lfbits-aok-bit (lfun-bits f)))))
+
+(defmethod no-next-method ((generic-function standard-generic-function)
+                           (method standard-method)
+                           &rest args)
+  (error "There is no next method for ~s~%args: ~s" method args))
+
+(defmethod add-method ((generic-function standard-generic-function) (method standard-method))
+  (%add-standard-method-to-standard-gf generic-function method))
+
+(defmethod no-applicable-method (gf &rest args)
+  (cerror "Try calling it again"
+          "There is no applicable method for the generic function:~%  ~s~%when called with arguments:~%  ~s" gf args)
+  (apply gf args))
+
+
+(defmethod no-applicable-primary-method (gf methods)
+  (%method-combination-error "No applicable primary methods for ~s~@
+                              Applicable methods: ~s" gf methods))
+
+(defmethod compute-applicable-methods ((gf standard-generic-function) args)
+  (%compute-applicable-methods* gf args))
+
+(defmethod compute-applicable-methods-using-classes ((gf standard-generic-function) args)
+  (let ((res (%compute-applicable-methods* gf args t)))
+    (if (eq res :undecidable)
+      (values nil nil)
+      (values res t))))
+
+(defun %compute-applicable-methods+ (gf &rest args)
+  (declare (dynamic-extent args))
+  (%compute-applicable-methods* gf args))
+
+(defun %compute-applicable-methods* (gf args &optional using-classes-p)
+  (let* ((methods (%gf-methods gf))
+         (args-length (length args))
+         (bits (inner-lfun-bits gf))
+         arg-count res)
+    (when methods
+      (setq arg-count (length (%method-specializers (car methods))))
+      (unless (<= arg-count args-length)
+        (error "Too few args to ~s" gf))
+      (unless (or (logbitp $lfbits-rest-bit bits)
+                  (logbitp $lfbits-restv-bit bits)
+                  (logbitp $lfbits-keys-bit bits)
+                  (<= args-length 
+                      (+ (ldb $lfbits-numreq bits) (ldb $lfbits-numopt bits))))
+        (error "Too many args to ~s" gf))
+      (let ((cpls (make-list arg-count)))
+        (declare (dynamic-extent cpls))
+        (do* ((args-tail args (cdr args-tail))
+              (cpls-tail cpls (cdr cpls-tail)))
+            ((null cpls-tail))
+          (setf (car cpls-tail)
+                (%class-precedence-list (if using-classes-p
+                                          ;; extension for use in source location support
+                                          (if (typep (car args-tail) 'eql-specializer)
+                                            (class-of (eql-specializer-object (car args-tail)))
+                                            (car args-tail))
+                                          (class-of (car args-tail))))))
+        (dolist (m methods)
+          (let ((appp (%method-applicable-p m args cpls using-classes-p)))
+            (when appp
+              (when (eq appp :undecidable) ;; can only happen if using-classes-p
+                (return-from %compute-applicable-methods* appp))
+              (push m res))))
+        (sort-methods res cpls (%gf-precedence-list gf))))))
+
+
+(defun %method-applicable-p (method args cpls &optional using-classes-p)
+  (do* ((specs (%method-specializers method) (%cdr specs))
+        (args args (%cdr args))
+        (cpls cpls (%cdr cpls)))
+      ((null specs) t)
+    (let ((spec (%car specs))
+          (arg (%car args)))
+      (if (typep spec 'eql-specializer)
+        (if using-classes-p
+          (if (typep arg 'eql-specializer) ;; extension for use in source location support
+            (unless (eql (eql-specializer-object arg) (eql-specializer-object spec))
+              (return nil))
+            (if (typep (eql-specializer-object spec) arg)
+              ;; Can't tell if going to be applicable or not based on class alone
+              ;; Except for the special case of NULL which is a singleton
+              (unless (eq arg *null-class*)
+                (return :undecidable))
+              (return nil)))
+          (unless (eql arg (eql-specializer-object spec))
+            (return nil)))
+        (unless (memq spec (%car cpls))
+          (return nil))))))
+
+
+;;; Need this so that (compute-applicable-methods
+;;; #'class-precedence-list ...)  will not recurse.
+(defun %class-precedence-list (class)
+  (if (eq (class-of class) *standard-class-class*)
+    (%inited-class-cpl class)
+    (class-precedence-list class)))
+
+(defmethod class-precedence-list ((class class))
+  (%inited-class-cpl class))
+
+
+(defun make-all-methods-kernel ()
+  (dolist (f (population.data %all-gfs%))
+    (let ((smc *standard-method-class*))
+      (dolist (method (slot-value-if-bound f 'methods))
+	(when (eq (class-of method) smc)
+	  (change-class method *standard-kernel-method-class*))))))
+
+
+(defun make-all-methods-non-kernel ()
+  (dolist (f (population.data %all-gfs%))
+    (let ((skmc *standard-kernel-method-class*))
+      (dolist (method (slot-value-if-bound f 'methods))
+	(when (eq (class-of method) skmc)
+	  (change-class method *standard-method-class*))))))
+
+
+(defun required-lambda-list-args (l)
+  (multiple-value-bind (ok req) (verify-lambda-list l)
+    (unless ok (error "Malformed lambda-list: ~s" l))
+    req))
+
+
+(defun check-generic-function-lambda-list (ll &optional (errorp t))
+  (multiple-value-bind (ok reqsyms opttail resttail keytail auxtail)
+                       (verify-lambda-list ll)
+    (declare (ignore reqsyms resttail))
+    (when ok 
+      (block checkit
+        (when (eq (car opttail) '&optional)
+          (dolist (elt (cdr opttail))
+            (when (memq elt lambda-list-keywords) (return))
+            (unless (or (symbolp elt)
+                        (and (listp elt)
+                             (non-nil-symbol-p (car elt))
+                             (null (cdr elt))))
+              (return-from checkit (setq ok nil)))))
+        (dolist (elt (cdr keytail))
+          (when (memq elt lambda-list-keywords) (return))
+          (unless (or (symbolp elt)
+                      (and (listp elt)
+                           (or (non-nil-symbol-p (car elt))
+                               (and (listp (car elt))
+                                    (non-nil-symbol-p (caar elt))
+                                    (non-nil-symbol-p (cadar elt))
+                                    (null (cddar elt))))
+                           (null (cdr elt))))
+            (return-from checkit (setq ok nil))))
+        (when auxtail (setq ok nil))))
+    (when (and errorp (not ok))
+      (signal-program-error "Bad generic function lambda list: ~s" ll))
+    ok))
+
+
+(defun canonicalize-argument-precedence-order (apo req)
+  (cond ((equal apo req) nil)
+        ((not (eql (length apo) (length req)))
+         (signal-program-error "Lengths of ~S and ~S differ." apo req))
+        (t (let ((res nil))
+             (dolist (arg apo (nreverse res))
+               (let ((index (position arg req)))
+                 (if (or (null index) (memq index res))
+                   (error "Missing or duplicate arguments in ~s" apo))
+                 (push index res)))))))
+
+
+(defun %defgeneric (function-name lambda-list method-combination generic-function-class
+                                  options)
+  (setq generic-function-class (find-class generic-function-class))
+  (setq method-combination 
+        (find-method-combination
+         (class-prototype generic-function-class)
+         (car method-combination)
+         (cdr method-combination)))
+  (let ((gf (fboundp function-name)))
+    (when gf
+      (dolist (method (%defgeneric-methods gf))
+        (remove-method gf method))))
+  (record-source-file function-name 'function)
+  (record-arglist function-name lambda-list)
+  (apply #'ensure-generic-function 
+         function-name
+         :lambda-list lambda-list
+         :method-combination method-combination
+         :generic-function-class generic-function-class
+         options))
+
+
+
+
+;;; Redefined in lib;method-combination.lisp
+(defmethod find-method-combination ((gf standard-generic-function) type options)
+  (unless (and (eq type 'standard) (null options))
+    (error "non-standard method-combination not supported yet."))
+  *standard-method-combination*)
+
+
+
+(defmethod add-direct-method ((spec specializer) (method method))
+  (pushnew method (specializer.direct-methods spec)))
+
+(setf (fdefinition '%do-add-direct-method) #'add-direct-method)
+
+(defmethod remove-direct-method ((spec specializer) (method method))
+  (setf (specializer.direct-methods spec)
+	(nremove method (specializer.direct-methods spec))))
+
+(setf (fdefinition '%do-remove-direct-method) #'remove-direct-method)
+
+
+
+
+
+				   
+
+
+
+(defvar *make-load-form-saving-slots-hash* (make-hash-table :test 'eq))
+
+(defun make-load-form-saving-slots (object &key
+					   (slot-names nil slot-names-p)
+					   environment)
+  (declare (ignore environment))
+  (let* ((class (class-of object))
+         (class-name (class-name class))
+         (structurep (structurep object))
+         (sd (and structurep (require-type (gethash class-name %defstructs%) 'vector))))
+    (unless (or structurep
+                (standard-instance-p object))
+      (%badarg object '(or standard-object structure-object)))
+    (if slot-names-p
+      (dolist (slot slot-names)
+        (unless (slot-exists-p object slot)
+          (error "~s has no slot named ~s" object slot)))
+      (setq slot-names
+            (if structurep
+              (let ((res nil))
+                (dolist (slot (sd-slots sd))
+                  (unless (fixnump (car slot))
+                    (push (%car slot) res)))
+                (nreverse res))
+              (mapcar '%slot-definition-name
+                      (extract-instance-effective-slotds
+                       (class-of object))))))
+    (values
+     (let* ((form (gethash class-name *make-load-form-saving-slots-hash*)))
+       (or (and (consp form)
+                (eq (car form) 'allocate-instance)
+                form)
+           (setf (gethash class-name *make-load-form-saving-slots-hash*)
+                 `(allocate-instance (find-class ',class-name)))))
+     ;; initform is NIL when there are no slots
+     (when slot-names
+       `(%set-slot-values
+         ',object
+         ',slot-names
+         ',(let ((temp #'(lambda (slot)
+                           (if (slot-boundp object slot)
+                             (slot-value object slot)
+                             (%slot-unbound-marker)))))
+             (declare (dynamic-extent temp))
+             (mapcar temp slot-names)))))))
+
+
+    
+
+(defmethod allocate-instance ((class structure-class) &rest initargs)
+  (declare (ignore initargs))
+  (let* ((class-name (%class-name class))
+         (sd (or (gethash class-name %defstructs%)
+                 (error "Can't find structure named ~s" class-name)))
+         (res (make-structure-vector (sd-size sd))))
+    (setf (%svref res 0) (mapcar (lambda (x)
+                                   (find-class-cell x t)) (sd-superclasses sd)))
+    res))
+
+
+(defun %set-slot-values (object slots values)
+  (dolist (slot slots)
+    (let ((value (pop values)))
+      (if (eq value (%slot-unbound-marker))
+        (slot-makunbound object slot)
+        (setf (slot-value object slot) value)))))
+
+
+(defun %recache-class-direct-methods ()
+  (let ((*maintain-class-direct-methods* t))   ; in case we get an error
+    (dolist (f (population-data %all-gfs%))
+      (when (standard-generic-function-p f)
+        (dolist (method (%gf-methods f))
+          (%add-direct-methods method)))))
+  (setq *maintain-class-direct-methods* t))   ; no error, all is well
+
Index: /branches/new-random/level-1/l1-clos.lisp
===================================================================
--- /branches/new-random/level-1/l1-clos.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-clos.lisp	(revision 13309)
@@ -0,0 +1,2512 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Copyright (C) 2002-2009 Clozure Associates
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+;;;
+
+;;; At this point in the load sequence, the handful of extant basic classes
+;;; exist only in skeletal form (without direct or effective slot-definitions.)
+
+(in-package "CCL")
+
+(defun extract-slotds-with-allocation (allocation slotds)
+  (collect ((right-ones))
+    (dolist (s slotds (right-ones))
+      (if (eq (%slot-definition-allocation s) allocation)
+        (right-ones s)))))
+
+(defun extract-instance-direct-slotds (class)
+  (extract-slotds-with-allocation :instance (%class-direct-slots class)))
+
+(defun extract-class-direct-slotds (class)
+  (extract-slotds-with-allocation :class (%class-direct-slots class)))
+
+(defun extract-instance-effective-slotds (class)
+  (extract-slotds-with-allocation :instance (%class-slots class)))
+
+(defun extract-class-effective-slotds (class)
+  (extract-slotds-with-allocation :class (%class-slots class)))
+
+(defun extract-instance-class-and-other-slotds (slotds)
+  (collect ((instance-slots)
+	    (shared-slots)
+            (other-slots))
+    (dolist (s slotds (values (instance-slots) (shared-slots) (other-slots)))
+      (case (%slot-definition-allocation s)
+        (:instance (instance-slots s))
+        (:class (shared-slots s))
+        (t (other-slots s))))))
+
+
+(defun %early-shared-initialize (instance slot-names initargs)
+  (unless (or (listp slot-names) (eq slot-names t))
+    (report-bad-arg slot-names '(or list (eql t))))
+  ;; Check that initargs contains valid key/value pairs,
+  ;; signal a PROGRAM-ERROR otherwise.  (Yes, this is
+  ;; an obscure way to do so.)
+  (destructuring-bind (&key &allow-other-keys) initargs)
+  (let* ((wrapper (instance-class-wrapper instance))
+         (class (%wrapper-class wrapper)))
+    (when (eql 0 (%wrapper-hash-index wrapper)) ; obsolete
+      (update-obsolete-instance instance)
+      (setq wrapper (instance-class-wrapper instance)))
+    (dolist (slotd (%class-slots class))
+      (let* ((loc (%slot-definition-location slotd)))
+        (multiple-value-bind (ignore new-value foundp)
+            (get-properties initargs
+                            (%slot-definition-initargs slotd))
+          (declare (ignore ignore))
+          (if foundp
+	    (progn
+	      (unless (funcall (standard-effective-slot-definition.type-predicate slotd) new-value)
+		(error 'bad-slot-type-from-initarg
+		       :slot-definition slotd
+		       :instance instance
+		       :datum new-value
+		       :expected-type  (%slot-definition-type slotd)
+		       :initarg-name (car foundp)))
+	      (if (consp loc)
+		(rplacd loc new-value)
+		(setf (standard-instance-instance-location-access instance loc)
+		      new-value)))
+            (if (or (eq slot-names t)
+                    (member (%slot-definition-name slotd)
+                            slot-names
+			    :test #'eq))
+              (let* ((curval (if (consp loc)
+                               (cdr loc)
+                               (%standard-instance-instance-location-access
+				instance loc))))
+                (if (eq curval (%slot-unbound-marker))
+                  (let* ((initfunction (%slot-definition-initfunction slotd)))
+                    (if initfunction
+                      (let* ((newval (funcall initfunction)))
+			(unless (funcall (standard-effective-slot-definition.type-predicate slotd) newval)
+			  (error 'bad-slot-type-from-initform
+				 :slot-definition slotd
+				 :expected-type (%slot-definition-type slotd)
+				 :datum newval
+				 :instance instance))
+                        (if (consp loc)
+                          (rplacd loc newval)
+                          (setf (standard-instance-instance-location-access
+				 instance loc)
+				newval)))))))))))))
+  instance)
+
+(setf (fdefinition '%shared-initialize) #'%early-shared-initialize)
+
+;;; This is redefined (to call MAKE-INSTANCE) below.
+(setf (fdefinition '%make-direct-slotd)
+      #'(lambda (slotd-class &key
+			     name
+			     initfunction
+			     initform
+			     initargs
+			     (allocation :instance)
+			     class
+			     (type t)
+			     (documentation (%slot-unbound-marker))
+			     readers
+			     writers)
+	  (declare (ignore slotd-class))
+	  (%instance-vector
+	   (%class.own-wrapper *standard-direct-slot-definition-class*)
+	   name type initfunction initform initargs allocation
+	   documentation class readers writers)))
+
+;;; Also redefined below, after MAKE-INSTANCE is possible.
+(setf (fdefinition '%make-effective-slotd)
+      #'(lambda (slotd-class &key
+			     name
+			     initfunction
+			     initform
+			     initargs
+			     allocation
+			     class
+			     type
+			     documentation)
+	  (declare (ignore slotd-class))
+	  (%instance-vector
+	   (%class.own-wrapper *standard-effective-slot-definition-class*)
+	   name type initfunction initform initargs allocation
+	   documentation class nil (ensure-slot-id name) #'true)))
+
+
+(defmethod compile-time-class-p ((class class)) nil)
+
+(defmethod direct-slot-definition-class ((class std-class) &key  &allow-other-keys)
+  *standard-direct-slot-definition-class*)
+
+(defmethod effective-slot-definition-class ((class std-class) &key  &allow-other-keys)
+  *standard-effective-slot-definition-class*)
+
+(defun make-direct-slot-definition (class initargs)
+  (apply #'%make-direct-slotd
+	 (apply #'direct-slot-definition-class class initargs)
+	 :class class
+	 initargs))
+
+(defun make-effective-slot-definition (class &rest initargs)
+  (declare (dynamic-extent initargs))
+  (apply #'%make-effective-slotd
+	 (apply #'effective-slot-definition-class class initargs)
+	 initargs))
+
+;; Bootstrapping version, replaced in l1-typesys
+(fset 'standardized-type-specifier
+      (nlambda bootstrapping-standardized-type-specifier (spec)
+        (when (and (consp spec)
+                   (memq (%car spec) '(and or))
+                   (consp (%cdr spec))
+                   (null (%cddr spec)))
+          (setq spec (%cadr spec)))
+        (if (consp spec)
+          (cons (%car spec) (mapcar #'standardized-type-specifier (%cdr spec)))
+          (or (cdr (assoc spec '((string . base-string))))
+              spec))))
+
+;;; The type of an effective slot definition is the intersection of
+;;; the types of the direct slot definitions it's initialized from.
+(defun dslotd-type-intersection (direct-slots)
+  (or (dolist (dslotd direct-slots t)
+        (unless (eq t (%slot-definition-type dslotd))
+          (return)))
+      (standardized-type-specifier
+       (if (cdr direct-slots)
+         `(and ,@(mapcar #'(lambda (d) (or (%slot-definition-type d) t))
+                         direct-slots))
+         (%slot-definition-type (car direct-slots))))))
+
+(defmethod compute-effective-slot-definition ((class slots-class)
+                                              name
+                                              direct-slots)
+  
+  (let* ((initer (dolist (s direct-slots)
+                   (when (%slot-definition-initfunction s)
+                     (return s))))
+         (documentor (dolist (s direct-slots)
+		       (when (%slot-definition-documentation s)
+                         (return s))))
+         (first (car direct-slots))
+         (initargs (let* ((initargs nil))
+                     (dolist (dslot direct-slots initargs)
+                       (dolist (dslot-arg (%slot-definition-initargs  dslot))
+                         (pushnew dslot-arg initargs :test #'eq))))))
+    (make-effective-slot-definition
+     class
+     :name name
+     :allocation (%slot-definition-allocation first)
+     :documentation (when documentor (nth-value
+				      1
+				      (%slot-definition-documentation
+				       documentor)))
+     :class (%slot-definition-class first)
+     :initargs initargs
+     :initfunction (if initer (%slot-definition-initfunction initer))
+     :initform (if initer (%slot-definition-initform initer))
+     :type (dslotd-type-intersection direct-slots))))
+
+(defmethod compute-slots ((class slots-class))
+  (let* ((slot-name-alist ()))
+    (labels ((note-direct-slot (dslot)
+               (let* ((sname (%slot-definition-name dslot))
+                      (pair (assq sname slot-name-alist)))
+                 (if pair
+                   (push dslot (cdr pair))
+                   (push (list sname dslot) slot-name-alist))))
+             (rwalk (tail)
+               (when tail
+                 (rwalk (cdr tail))
+		 (let* ((c (car tail)))
+		   (unless (eq c *t-class*)
+		     (dolist (dslot (%class-direct-slots c))
+		       (note-direct-slot dslot)))))))
+      (rwalk (class-precedence-list class)))
+    (collect ((effective-slotds))
+      (dolist (pair (nreverse slot-name-alist) (effective-slotds))
+        (effective-slotds (compute-effective-slot-definition class (car pair) (cdr pair)))))))
+
+
+(defmethod compute-slots :around ((class std-class))
+  (let* ((cpl (%class.cpl class)))
+    (multiple-value-bind (instance-slots class-slots other-slots)
+        (extract-instance-class-and-other-slotds (call-next-method))
+      (setq instance-slots (sort-effective-instance-slotds instance-slots class cpl))
+      (do* ((loc 1 (1+ loc))
+            (islotds instance-slots (cdr islotds)))
+           ((null islotds))
+        (declare (fixnum loc))
+        (setf (%slot-definition-location (car islotds)) loc))
+      (dolist (eslotd class-slots)
+        (setf (%slot-definition-location eslotd) 
+              (assoc (%slot-definition-name eslotd)
+                     (%class-get (%slot-definition-class eslotd)
+				 :class-slots)
+		     :test #'eq)))
+      (append instance-slots class-slots other-slots))))
+
+(defmethod compute-slots :around ((class structure-class))
+  (let* ((slots (call-next-method))	 )
+      (do* ((loc 1 (1+ loc))
+            (islotds slots (cdr islotds)))
+           ((null islotds) slots)
+        (declare (fixnum loc))
+        (setf (%slot-definition-location (car islotds)) loc))))
+
+;;; Should eventually do something here.
+;(defmethod compute-slots ((s structure-class))
+;  (call-next-method))
+
+(defmethod direct-slot-definition-class ((class structure-class) &rest initargs)
+  (declare (ignore initargs))
+  (find-class 'structure-direct-slot-definition))
+
+(defmethod effective-slot-definition-class ((class structure-class) &rest  initargs)
+  (declare (ignore initargs))
+  (find-class 'structure-effective-slot-definition))
+
+
+(defmethod compute-default-initargs ((class slots-class))
+  (let* ((initargs ()))
+    (dolist (c (%class-precedence-list class) (nreverse initargs))
+      (if (typep c 'forward-referenced-class)
+	(error
+	 "Class precedence list of ~s contains FORWARD-REFERENCED-CLASS ~s ."
+	 class c)
+	(dolist (i (%class-direct-default-initargs c))
+	  (pushnew i initargs :test #'eq :key #'car))))))
+
+
+
+
+(defvar *update-slots-preserve-existing-wrapper* nil)
+
+(defvar *optimized-dependents* (make-hash-table :test 'eq :weak :key)
+  "Hash table mapping a class to a list of all objects that have been optimized to
+   depend in some way on the layout of the class")
+
+(defun note-class-dependent (class gf)
+  (pushnew gf (gethash class *optimized-dependents*)))
+
+(defun unoptimize-dependents (class)
+  (pessimize-make-instance-for-class-name (%class-name class))
+  (loop for obj in (gethash class *optimized-dependents*)
+        do (etypecase obj
+             (standard-generic-function
+	      (clear-gf-dispatch-table (%gf-dispatch-table obj))
+	      (compute-dcode obj)))))
+
+(defun update-slots (class eslotds)
+  (let* ((instance-slots (extract-slotds-with-allocation :instance eslotds))
+         (new-ordering
+          (let* ((v (make-array (the fixnum (length instance-slots))))
+                 (i 0))
+            (declare (simple-vector v) (fixnum i))
+            (dolist (e instance-slots v)
+              (setf (svref v i)
+                    (%slot-definition-name e))
+              (incf i))))
+         (old-wrapper (%class-own-wrapper class))
+         (new-wrapper
+          (cond ((null old-wrapper)
+                 (%cons-wrapper class))
+                ((and old-wrapper *update-slots-preserve-existing-wrapper*)
+                 old-wrapper)
+                (t
+		 (unoptimize-dependents class)
+                 (make-instances-obsolete class)
+                 (%cons-wrapper class)))))
+    (setf (%class-slots class) eslotds)
+    (setf (%wrapper-instance-slots new-wrapper) new-ordering
+          (%wrapper-class-slots new-wrapper) (%class-get class :class-slots)
+          (%class-own-wrapper class) new-wrapper)
+    (setup-slot-lookup new-wrapper eslotds)))
+
+
+  
+(defun setup-slot-lookup (wrapper eslotds)
+  (when eslotds
+    (let* ((nslots (length eslotds))
+	   (total-slot-ids (current-slot-index))
+	   (small (< nslots 255))
+	   (map
+	    (if small
+	      (make-array total-slot-ids :element-type '(unsigned-byte 8))
+	      (make-array total-slot-ids :element-type '(unsigned-byte 32))))
+	   (table (make-array (the fixnum (1+ nslots))))
+	   (i 0))
+      (declare (fixnum nslots total-slot-ids i) (simple-vector table))
+      (setf (svref table 0) nil)
+      (dolist (slotd eslotds)
+	(incf i)
+        (setf (svref table i) slotd)
+        (if small
+          (locally (declare (type (simple-array (unsigned-byte 8) (*)) map))
+            (setf (aref map
+                        (slot-id.index
+                         (standard-effective-slot-definition.slot-id slotd)))
+                  i))
+          (locally (declare (type (simple-array (unsigned-byte 32) (*)) map))
+            (setf (aref map
+                        (slot-id.index
+                         (standard-effective-slot-definition.slot-id slotd)))
+                  i))))
+      (let* ((lookup-f
+              #+ppc-target
+              (gvector :function
+				(%svref (if small
+					  #'%small-map-slot-id-lookup
+					  #'%large-map-slot-id-lookup) 0)
+				map
+				table
+				(dpb 1 $lfbits-numreq
+				     (ash -1 $lfbits-noname-bit)))
+              #+x86-target
+              (%clone-x86-function (if small
+					  #'%small-map-slot-id-lookup
+					  #'%large-map-slot-id-lookup)
+                                   map
+                                   table
+                                   (dpb 1 $lfbits-numreq
+				     (ash -1 $lfbits-noname-bit))))
+	     (class (%wrapper-class wrapper))
+	     (get-f
+              #+ppc-target
+              (gvector :function
+                       (%svref (if small
+                                 #'%small-slot-id-value
+                                 #'%large-slot-id-value) 0)
+                       map
+                       table
+                       class
+                       #'%maybe-std-slot-value-using-class
+                       #'%slot-id-ref-missing
+                       (dpb 2 $lfbits-numreq
+                            (ash -1 $lfbits-noname-bit)))
+              #+x86-target
+              (%clone-x86-function (if small
+                                     #'%small-slot-id-value
+                                     #'%large-slot-id-value)
+                                   map
+                                   table
+                                   class
+                                   #'%maybe-std-slot-value-using-class
+                                   #'%slot-id-ref-missing
+                                   (dpb 2 $lfbits-numreq
+                                        (ash -1 $lfbits-noname-bit))))
+	     (set-f
+              #+ppc-target
+              (gvector :function
+                       (%svref (if small
+                                 #'%small-set-slot-id-value
+                                 #'%large-set-slot-id-value) 0)
+                       map
+                       table
+                       class
+                       #'%maybe-std-setf-slot-value-using-class
+                       #'%slot-id-set-missing
+                       (dpb 3 $lfbits-numreq
+                            (ash -1 $lfbits-noname-bit)))
+              #+x86-target
+              (%clone-x86-function
+               (if small
+                 #'%small-set-slot-id-value
+                 #'%large-set-slot-id-value)
+               map
+               table
+               class
+               #'%maybe-std-setf-slot-value-using-class
+               #'%slot-id-set-missing
+               (dpb 3 $lfbits-numreq
+                    (ash -1 $lfbits-noname-bit)))))
+	(setf (%wrapper-slot-id->slotd wrapper) lookup-f
+	      (%wrapper-slot-id-value wrapper) get-f
+	      (%wrapper-set-slot-id-value wrapper) set-f
+	      (%wrapper-slot-id-map wrapper) map
+	      (%wrapper-slot-definition-table wrapper) table))))
+  wrapper)
+
+                       
+    
+
+(defmethod validate-superclass ((class class) (super class))
+  (or (eq super *t-class*)
+      (let* ((class-of-class (class-of class))
+             (class-of-super (class-of super)))
+        (or (eq class-of-class class-of-super)
+            (and (eq class-of-class *standard-class-class*)
+                 (eq class-of-super *funcallable-standard-class-class*))
+            (and (eq class-of-class *funcallable-standard-class-class*)
+                 (eq class-of-super *standard-class-class*))))))
+
+(defmethod validate-superclass ((class foreign-class) (super standard-class))
+  t)
+
+(defmethod validate-superclass ((class std-class) (super forward-referenced-class))
+  t)
+
+
+(defmethod add-direct-subclass ((class class) (subclass class))
+  (pushnew subclass (%class-direct-subclasses class))
+  subclass)
+
+(defmethod remove-direct-subclass ((class class) (subclass class))
+  (setf (%class-direct-subclasses class)
+        (remove subclass (%class-direct-subclasses class)))
+  subclass)
+
+(defun add-direct-subclasses (class new)
+  (dolist (n new)
+    (unless (memq class (%class-direct-subclasses  class))
+      (add-direct-subclass n class))))
+
+(defun remove-direct-subclasses (class old-supers new-supers)
+  (dolist (o old-supers)
+    (unless (memq o new-supers)
+      (remove-direct-subclass o class))))
+
+;;; Built-in classes are always finalized.
+(defmethod class-finalized-p ((class class))
+  t)
+
+;;; Standard classes are finalized if they have a wrapper and that
+;;; wrapper has an instance-slots vector; that implies that
+;;; both UPDATE-CPL and UPDATE-SLOTS have been called on the class.
+(defmethod class-finalized-p ((class std-class))
+  (let* ((w (%class-own-wrapper class)))
+    (and w (typep (%wrapper-instance-slots w) 'vector))))
+
+(defmethod finalize-inheritance ((class std-class))
+  (update-class class t))
+
+
+(defmethod finalize-inheritance ((class forward-referenced-class))
+  (error "Class ~s can't be finalized." class))
+
+(defmethod class-primary-p ((class slots-class))
+  (%class-primary-p class))
+
+(defmethod (setf class-primary-p) (new (class std-class))
+  (setf (%class-primary-p class) new))
+
+(defmethod class-primary-p ((class class))
+  t)
+
+(defmethod (setf class-primary-p) (new (class class))
+  new)
+
+
+(defun forward-referenced-class-p (class)
+  (and (%standard-instance-p class)
+       (eq (%class-of-instance class) *forward-referenced-class-class*)))
+
+;;; This uses the primary class information to sort the slots of a class.
+(defun sort-effective-instance-slotds (slotds class cpl)
+  (let (primary-slotds
+        primary-slotds-class
+        (primary-slotds-length 0))
+    (declare (fixnum primary-slotds-length))
+    (dolist (sup (cdr cpl))
+      (unless (eq sup *t-class*)      
+        (when (class-primary-p sup)
+          (let ((sup-slotds (extract-instance-effective-slotds sup)))
+            (if (null primary-slotds-class)
+              (setf primary-slotds-class sup
+                    primary-slotds sup-slotds
+                    primary-slotds-length (length sup-slotds))
+              (let ((sup-slotds-length (length sup-slotds)))
+                (do* ((i 0 (1+ i))
+                      (n (min sup-slotds-length primary-slotds-length))
+                      (sup-slotds sup-slotds (cdr sup-slotds))
+                      (primary-slotds primary-slotds (cdr primary-slotds)))
+                     ((= i n))
+                  (unless (eq (%slot-definition-name (car sup-slotds))
+                              (%slot-definition-name (car primary-slotds)))
+                    (error "While initializing ~s:~%~
+                            attempt to mix incompatible primary classes:~%~
+                            ~s and ~s"
+                           class sup primary-slotds-class)))
+                (when (> sup-slotds-length primary-slotds-length)
+                  (setq primary-slotds-class sup
+                        primary-slotds sup-slotds
+                        primary-slotds-length sup-slotds-length))))))))
+    (if (null primary-slotds-class)
+      slotds
+      (flet ((slotd-position (slotd)
+               (let* ((slotd-name (%slot-definition-name slotd)))
+                 (do* ((i 0 (1+ i))
+                       (primary-slotds primary-slotds (cdr primary-slotds)))
+                      ((= i primary-slotds-length) primary-slotds-length)
+                   (declare (fixnum i))
+                   (when (eq slotd-name
+                                (%slot-definition-name (car primary-slotds)))
+                   (return i))))))
+        (declare (dynamic-extent #'slotd-position))
+        (sort-list slotds '< #'slotd-position)))))
+
+
+
+
+(defun update-cpl (class cpl)
+  (if (class-finalized-p class)
+    (unless (equal (%class.cpl class) cpl)
+      (setf (%class.cpl class) cpl)
+      #|(force-cache-flushes class)|#)
+    (setf (%class.cpl class) cpl))
+  cpl)
+
+
+(defun class-has-a-forward-referenced-superclass-p (original)
+  (labels ((scan-forward-refs (class seen)
+             (unless (memq class seen)
+               (or (if (forward-referenced-class-p class) class)
+                   (let ((seen (cons class seen)))
+		     (declare (dynamic-extent seen))
+                     (dolist (s (%class-direct-superclasses class))
+                       (when (eq s original)
+                         (error "circular class hierarchy: the class ~s is a superclass of at least one of its superclasses (~s)." original class))
+                       (let* ((fwdref (scan-forward-refs s seen)))
+                         (when fwdref (return fwdref)))))))))
+    (or (compile-time-class-p original)
+        (scan-forward-refs original ()))))
+
+(defun class-forward-referenced-superclasses (original)
+  (labels ((scan-forward-refs (class seen fwdrefs)
+             (unless (memq class seen)
+	       (if (forward-referenced-class-p class)
+		 (push class fwdrefs)
+		 (let ((seen (cons class seen)))
+		   (declare (dynamic-extent seen))
+		   (dolist (s (%class-direct-superclasses class))
+		     (when (eq s original)
+		       (error "circular class hierarchy: the class ~s is a superclass of at least one of its superclasses (~s)." original class))
+		     (setq fwdrefs (scan-forward-refs s seen fwdrefs))))))
+	     fwdrefs))
+    (scan-forward-refs original () ())))
+  
+
+
+(defmethod compute-class-precedence-list ((class class))
+  (let* ((fwdrefs (class-forward-referenced-superclasses class)))
+    (if fwdrefs
+      (if (cdr fwdrefs)
+	(error "Class ~s can't be finalized because superclasses ~s are not defined yet"
+	       class (mapcar #'%class-name fwdrefs))
+	(error "Class ~s can't be finalized because superclass ~s is not defined yet"
+	       class (%class-name (car fwdrefs))))
+      (compute-cpl class))))
+
+;;; Classes that can't be instantiated via MAKE-INSTANCE have no
+;;; initargs caches.
+(defmethod %flush-initargs-caches ((class class))
+  )
+
+;;; Classes that have initargs caches should flush them when the
+;;; class is finalized.
+(defmethod %flush-initargs-caches ((class std-class))
+  (setf (%class.make-instance-initargs class) nil
+	(%class.reinit-initargs class) nil
+	(%class.redefined-initargs class) nil
+	(%class.changed-initargs class) nil))
+
+(defun update-class (class finalizep)
+  ;;
+  ;; Calling UPDATE-SLOTS below sets the class wrapper of CLASS, which
+  ;; makes the class finalized.  When UPDATE-CLASS isn't called from
+  ;; FINALIZE-INHERITANCE, make sure that this finalization invokes
+  ;; FINALIZE-INHERITANCE as per AMOP.  Note, that we can't simply
+  ;; delay the finalization when CLASS has no forward referenced
+  ;; superclasses because that causes bootstrap problems.
+  (when (and (not (or finalizep (class-finalized-p class)))
+	     (not (class-has-a-forward-referenced-superclass-p class)))
+    (finalize-inheritance class)
+    (return-from update-class))
+  (when (or finalizep (class-finalized-p class))
+    (let* ((cpl (update-cpl class (compute-class-precedence-list  class))))
+      ;; This -should- be made to work for structure classes
+      (update-slots class (compute-slots class))
+      (setf (%class-default-initargs class) (compute-default-initargs class))
+      (%flush-initargs-caches class)
+      (let* ((wrapper (%class-own-wrapper class)))
+        (when wrapper
+          (setf (%wrapper-cpl wrapper) cpl
+                (%wrapper-cpl-bits wrapper) (make-cpl-bits cpl))))))
+  (unless finalizep
+    (dolist (sub (%class-direct-subclasses class))
+      (update-class sub nil))))
+
+(defun add-accessor-methods (class dslotds)
+  (dolist (dslotd dslotds)
+    (dolist (reader (%slot-definition-readers dslotd))
+      (add-reader-method class
+                         (ensure-generic-function reader)
+                         dslotd))
+    (dolist (writer (%slot-definition-writers dslotd))
+      (add-writer-method class
+			 (ensure-generic-function writer)
+			 dslotd))))
+
+(defun remove-accessor-methods (class dslotds)
+  (dolist (dslotd dslotds)
+    (dolist (reader (%slot-definition-readers dslotd))
+      (remove-reader-method class (ensure-generic-function reader :lambda-list '(x))))
+    (dolist (writer (%slot-definition-writers dslotd))
+      (remove-writer-method class (ensure-generic-function writer :lambda-list '(x y))))))
+
+(defmethod reinitialize-instance :before ((class std-class)  &key direct-superclasses)
+  (remove-accessor-methods class (%class-direct-slots class))
+  (remove-direct-subclasses class (%class-direct-superclasses class) direct-superclasses))
+   
+(defmethod shared-initialize :after
+  ((class slots-class)
+   slot-names &key
+   (direct-superclasses nil direct-superclasses-p)
+   (direct-slots nil direct-slots-p)
+   (direct-default-initargs nil direct-default-initargs-p)
+   (documentation nil doc-p)
+   (primary-p nil primary-p-p))
+  (if (or direct-superclasses-p (eq slot-names t))
+    (progn
+      (setq direct-superclasses
+            (or direct-superclasses
+                (list (if (typep class 'funcallable-standard-class)
+                        *funcallable-standard-object-class*
+                        *standard-object-class*))))
+      (dolist (superclass direct-superclasses)
+        (unless (validate-superclass class superclass)
+          (error "The class ~S was specified as a~%super-class of the class ~S;~%~
+                    but the meta-classes ~S and~%~S are incompatible."
+                 superclass class (class-of superclass) (class-of class))))
+      (setf (%class-direct-superclasses class) direct-superclasses))
+    (setq direct-superclasses (%class-direct-superclasses class)))
+  (setq direct-slots
+	(if direct-slots-p
+          (setf (%class-direct-slots class)
+                (mapcar #'(lambda (initargs)
+			    (make-direct-slot-definition class initargs))
+			direct-slots))
+          (%class-direct-slots class)))
+  (if direct-default-initargs-p
+    (setf (%class-direct-default-initargs class)  direct-default-initargs)
+    (setq direct-default-initargs (%class-direct-default-initargs class)))
+  (let* ((new-class-slot-cells ())
+         (old-class-slot-cells (%class-get class :class-slots)))
+    (dolist (slot direct-slots)
+      (when (eq (%slot-definition-allocation slot) :class)
+        (let* ((slot-name (%slot-definition-name slot))
+               (pair (assq slot-name old-class-slot-cells)))
+          ;;; If the slot existed as a class slot in the old
+          ;;; class, retain the definition (even if it's unbound.)
+          (unless pair
+            (let* ((initfunction (%slot-definition-initfunction slot)))
+              (setq pair (cons slot-name
+                               (if initfunction
+                                 (funcall initfunction)
+                                 (%slot-unbound-marker))))))
+          (push pair new-class-slot-cells))))
+    (when new-class-slot-cells
+      (setf (%class-get class :class-slots) new-class-slot-cells)))
+  (when doc-p
+    (set-documentation class 'type documentation))
+  (when primary-p-p
+    (setf (class-primary-p class) primary-p))
+
+  (add-direct-subclasses class direct-superclasses)
+  (update-class class nil)
+  (add-accessor-methods class direct-slots))
+
+(defmethod initialize-instance :before ((class class) &key &allow-other-keys)
+  (setf (%class-ordinal class) (%next-class-ordinal))
+  (setf (%class.ctype class) (make-class-ctype class)))
+
+(defun ensure-class-metaclass-and-initargs (class args)
+  (let* ((initargs (copy-list args))
+         (missing (cons nil nil))
+         (supplied-meta (getf initargs :metaclass missing))
+         (supplied-supers (getf initargs :direct-superclasses missing))
+         (supplied-slots (getf initargs :direct-slots missing))
+         (metaclass (cond ((not (eq supplied-meta missing))
+			   (if (typep supplied-meta 'class)
+			     supplied-meta
+			     (find-class supplied-meta)))
+                          ((or (null class)
+                               (typep class 'forward-referenced-class))
+                           *standard-class-class*)
+                          (t (class-of class)))))
+    (declare (dynamic-extent missing))
+    (flet ((fix-super (s)
+             (cond ((classp s) s)
+                   ((not (and s (symbolp s)))
+                    (error "~s is not a class or a legal class name." s))
+                   (t
+                    (or (find-class s nil)
+			(setf (find-class s)
+			      (make-instance 'forward-referenced-class :name s))))))
+           (excise-all (keys)
+             (dolist (key keys)
+               (loop (unless (remf initargs key) (return))))))
+      (excise-all '(:metaclass :direct-superclasses :direct-slots))
+      (values metaclass
+              `(,@ (unless (eq supplied-supers missing)
+                     `(:direct-superclasses ,(mapcar #'fix-super supplied-supers)))
+                ,@ (unless (eq supplied-slots missing)
+                     `(:direct-slots ,supplied-slots))
+               ,@initargs)))))
+
+
+;;; This defines a new class.
+(defmethod ensure-class-using-class ((class null) name &rest keys &key &allow-other-keys)
+  (multiple-value-bind (metaclass initargs)
+      (ensure-class-metaclass-and-initargs class keys)
+    (let* ((class (apply #'make-instance metaclass :name name initargs)))
+      (setf (find-class name) class))))
+
+(defmethod ensure-class-using-class ((class forward-referenced-class) name &rest keys &key &allow-other-keys)
+  (multiple-value-bind (metaclass initargs)
+      (ensure-class-metaclass-and-initargs class keys)
+    (apply #'change-class class metaclass initargs)
+    (apply #'reinitialize-instance class initargs)
+    (setf (find-class name) class)))
+	   
+;; Can't go with optimize-make-instance-for-class-name because
+;; ensure-class-using-class is called before that is defined.
+(defun pessimize-make-instance-for-class-name (class-name)
+  (let ((cell (find-class-cell class-name nil)))
+    (when cell
+      (init-class-cell-instantiator cell))))
+
+(defun init-class-cell-instantiator (cell)
+  (when cell
+    (setf (class-cell-instantiate cell) '%make-instance)
+    (setf (class-cell-extra cell) nil)))
+
+;;; Redefine an existing (not forward-referenced) class.
+(defmethod ensure-class-using-class ((class class) name &rest keys &key)
+  (multiple-value-bind (metaclass initargs)
+      (ensure-class-metaclass-and-initargs class keys)
+    (unless (eq (class-of class) metaclass)
+      (error "Can't change metaclass of ~s to ~s." class metaclass))
+    (apply #'reinitialize-instance class initargs)
+    (setf (find-class name) class)))
+
+
+(defun ensure-class (name &rest keys &key &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (apply #'ensure-class-using-class (find-class name nil) name keys))
+
+(defparameter *defclass-redefines-improperly-named-classes-pedantically* 
+   t
+  "ANSI CL expects DEFCLASS to redefine an existing class only when
+the existing class is properly named, the MOP function ENSURE-CLASS
+redefines existing classes regardless of their CLASS-NAME.  This variable
+governs whether DEFCLASS makes that distinction or not.")
+
+(defun ensure-class-for-defclass (name &rest keys &key &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (record-source-file name 'class)
+  (let* ((existing-class (find-class name nil)))
+    (when (and *defclass-redefines-improperly-named-classes-pedantically* 
+	       existing-class 
+	       (not (eq (class-name existing-class) name)))
+      ;; Class isn't properly named; act like it didn't exist
+      (setq existing-class nil))
+    (apply #'ensure-class-using-class existing-class name keys)))
+
+
+
+
+(defmethod method-slot-name ((m standard-accessor-method))
+  (standard-direct-slot-definition.name (%accessor-method.slot-definition m)))
+
+
+(defun %ensure-class-preserving-wrapper (&rest args)
+  (declare (dynamic-extent args))
+  (let* ((*update-slots-preserve-existing-wrapper* t))
+    (apply #'ensure-class args)))
+
+(defun %find-direct-slotd (class name)
+  (dolist (dslotd (%class-direct-slots class)
+           (error "Direct slot definition for ~s not found in ~s" name class))
+    (when (eq (%slot-definition-name dslotd) name)
+      (return dslotd))))
+
+(defun %add-slot-readers (class-name pairs)
+  (let* ((class (find-class class-name)))
+    (dolist (pair pairs)
+      (destructuring-bind (slot-name &rest readers) pair
+        (setf (%slot-definition-readers (%find-direct-slotd class slot-name)) readers)))
+    (add-accessor-methods class (%class-direct-slots class))))
+
+(defun %add-slot-writers (class-name pairs)
+  (let* ((class (find-class class-name)))
+    (dolist (pair pairs)
+      (destructuring-bind (slot-name &rest readers) pair
+        (setf (%slot-definition-writers (%find-direct-slotd class slot-name)) readers)))
+    (add-accessor-methods class (%class-direct-slots class))))
+
+
+(%ensure-class-preserving-wrapper
+ 'standard-method
+ :direct-superclasses '(method)
+ :direct-slots `((:name qualifiers :initargs (:qualifiers) :initfunction ,#'false :initform nil)
+                 (:name specializers :initargs (:specializers) :initfunction ,#'false :initform nil)
+                 (:name function :initargs (:function))
+                 (:name generic-function :initargs (:generic-function) :initfunction ,#'false :initform nil)
+                 (:name name :initargs (:name) :initfunction ,#'false :initform nil)
+		 (:name lambda-list :initform nil :initfunction ,#'false
+		  :initargs (:lambda-list)))
+ :primary-p t)
+
+(defmethod shared-initialize :after ((method standard-method)
+                                     slot-names
+                                     &key function &allow-other-keys)
+  (declare (ignore slot-names))
+  (when function
+    (let* ((inner (closure-function function)))
+      (unless (eq inner function)
+	(copy-method-function-bits inner function)))    
+    (lfun-name function method)))
+
+;;; Reader & writer methods classes.
+(%ensure-class-preserving-wrapper
+ 'standard-accessor-method
+ :direct-superclasses '(standard-method)
+ :direct-slots '((:name slot-definition :initargs (:slot-definition)))
+ :primary-p t)
+
+(%ensure-class-preserving-wrapper
+ 'standard-reader-method
+ :direct-superclasses '(standard-accessor-method))
+
+(%ensure-class-preserving-wrapper
+ 'standard-writer-method
+ :direct-superclasses '(standard-accessor-method))
+
+(defmethod reader-method-class ((class standard-class)
+				(dslotd standard-direct-slot-definition)
+				&rest initargs)
+  (declare (ignore initargs))
+  *standard-reader-method-class*)
+
+(defmethod reader-method-class ((class funcallable-standard-class)
+				(dslotd standard-direct-slot-definition)
+				&rest initargs)
+  (declare (ignore  initargs))
+  *standard-reader-method-class*)
+
+(defmethod add-reader-method ((class slots-class) gf dslotd)
+  (let* ((initargs
+	  `(:qualifiers nil
+	    :specializers ,(list class)
+	    :lambda-list (,(or (%class-name class) 'instance))
+	    :name ,(function-name gf)
+	    :slot-definition ,dslotd))
+	 (reader-method-class
+	  (apply #'reader-method-class class dslotd initargs))
+	 (method-function (create-reader-method-function
+			   class (class-prototype reader-method-class) dslotd))
+         (method (apply #'make-instance reader-method-class
+			:function method-function
+			initargs)))
+    (declare (dynamic-extent initargs))
+    (record-source-file method 'reader-method)
+    (add-method gf method)))
+
+(defmethod remove-reader-method ((class std-class) gf)
+  (let* ((method (find-method gf () (list class) nil)))
+    (when method (remove-method gf method))))
+
+(defmethod writer-method-class ((class standard-class)
+				(dslotd standard-direct-slot-definition)
+				&rest initargs)
+  (declare (ignore initargs))
+  *standard-writer-method-class*)
+
+(defmethod writer-method-class ((class funcallable-standard-class)
+				(dslotd standard-direct-slot-definition)
+				&rest initargs)
+  (declare (ignore initargs))
+  *standard-writer-method-class*)
+
+
+(defmethod add-writer-method ((class slots-class) gf dslotd)
+  (let* ((initargs
+	  `(:qualifiers nil
+	    :specializers ,(list *t-class* class)
+	    :lambda-list (new-value ,(or (%class-name class) 'instance))
+	    :name ,(function-name gf)
+	    :slot-definition ,dslotd))
+	 (method-class (apply #'writer-method-class class dslotd initargs))
+	 (method 
+	  (apply #'make-instance
+		 method-class
+		 :function (create-writer-method-function
+			    class
+			    (class-prototype method-class)
+			    dslotd)
+		 initargs)))
+    (declare (dynamic-extent initargs))
+    (record-source-file method 'writer-method)
+    (add-method gf method)))
+
+(defmethod remove-writer-method ((class std-class) gf)
+  (let* ((method (find-method gf () (list *t-class* class) nil)))
+    (when method (remove-method gf method))))
+
+;;; We can now define accessors.  Fix up the slots in the classes defined
+;;; thus far.
+
+(%add-slot-readers 'standard-method '((qualifiers method-qualifiers)
+				      (specializers method-specializers)
+				      (name method-name)
+				      ;(function method-function)
+				      (generic-function method-generic-function)
+				      (lambda-list method-lambda-list)))
+
+(%add-slot-writers 'standard-method '((function (setf method-function))
+				      (generic-function (setf method-generic-function))))
+
+
+(defmethod method-function ((m standard-method))
+  (%method.function m))
+
+
+(%add-slot-readers 'standard-accessor-method
+		   '((slot-definition accessor-method-slot-definition)))
+
+
+(%ensure-class-preserving-wrapper
+ 'specializer
+ :direct-superclasses '(metaobject)
+ :direct-slots `((:name direct-methods
+		  :readers (specializer-direct-methods)
+		  :initform nil :initfunction ,#'false))
+ :primary-p t)
+		  
+(%ensure-class-preserving-wrapper
+ 'eql-specializer
+ :direct-superclasses '(specializer)
+ :direct-slots '((:name object :initargs (:object) :readers (eql-specializer-object)))
+ :primary-p t)
+
+
+(%ensure-class-preserving-wrapper
+ 'class
+ :direct-superclasses '(specializer)
+ :direct-slots
+ `((:name prototype :initform nil :initfunction ,#'false)
+   (:name name :initargs (:name) :initform nil :initfunction ,#'false :readers (class-name))
+   (:name precedence-list :initform nil  :initfunction ,#'false)
+   (:name own-wrapper :initform nil  :initfunction ,#'false :readers (class-own-wrapper) :writers ((setf class-own-wrapper)))
+   (:name direct-superclasses  :initform nil  :initfunction ,#'false :readers (class-direct-superclasses))
+   (:name direct-subclasses  :initform nil  :initfunction ,#'false :readers (class-direct-subclasses))
+   (:name dependents :initform nil :initfunction ,#'false)
+   (:name class-ctype :initform nil :initfunction ,#'false)
+   (:name direct-slots :initform nil :initfunction ,#'false
+                  :readers (class-direct-slots)
+		  :writers ((setf class-direct-slots)))
+   (:name slots :initform nil :initfunction ,#'false
+    :readers (class-slots)
+    :writers ((setf class-slots)))
+   (:name info :initform (cons nil nil) :initfunction ,(lambda () (cons nil nil)) :readers (class-info))
+   (:name direct-default-initargs  :initform nil  :initfunction ,#'false :readers (class-direct-default-initargs))
+   (:name default-initargs :initform nil  :initfunction ,#'false :readers (class-default-initargs)))
+ :primary-p t)
+
+(%ensure-class-preserving-wrapper
+ 'forward-referenced-class
+ :direct-superclasses '(class))
+
+
+
+(%ensure-class-preserving-wrapper
+ 'built-in-class
+ :direct-superclasses '(class))
+
+
+(%ensure-class-preserving-wrapper
+ 'slots-class
+ :direct-superclasses '(class)
+ :direct-slots `((:name alist :initform nil  :initfunction ,#'false))
+ :primary-p t)
+
+;;; This class exists only so that standard-class & funcallable-standard-class
+;;; can inherit its slots.
+(%ensure-class-preserving-wrapper
+ 'std-class
+ :direct-superclasses '(slots-class)
+ :direct-slots `(
+                 (:name make-instance-initargs :initform nil  :initfunction ,#'false)
+                 (:name reinit-initargs :initform nil  :initfunction ,#'false)
+                 (:name redefined-initargs :initform nil :initfunction ,#'false)
+                 (:name changed-initargs :initform nil  :initfunction ,#'false))
+ :primary-p t)
+
+
+
+(%ensure-class-preserving-wrapper
+ 'standard-class
+ :direct-superclasses '(std-class))
+
+(%ensure-class-preserving-wrapper
+ 'funcallable-standard-class
+ :direct-superclasses '(std-class))
+
+
+(%ensure-class-preserving-wrapper
+ 'funcallable-standard-object
+#|| 
+ :direct-superclasses '(standard-object function)
+||#
+ :direct-slots `((:name name :initargs (:name) :readers (generic-function-name)))
+ :metaclass 'funcallable-standard-class)
+
+(%ensure-class-preserving-wrapper
+ 'generic-function
+ :direct-superclasses '(metaobject funcallable-standard-object)
+ :direct-slots `(
+		 (:name method-combination :initargs (:method-combination)
+                  :initform *standard-method-combination*
+                  :initfunction ,#'(lambda () *standard-method-combination*)
+		  :readers (generic-function-method-combination))
+                 (:name method-class :initargs (:method-class)
+                  :initform *standard-method-class*
+                  :initfunction ,#'(lambda () *standard-method-class*)
+		  :readers (generic-function-method-class))
+		 (:name methods :initargs (:methods)
+		  :initform nil :initfunction ,#'false
+		  :readers (generic-function-methods))
+		 (:name declarations
+		  :initargs (:declarations)
+		  :initform nil :initfunction ,#'false
+		  :readers (generic-function-declarations))
+                 (:name %lambda-list
+                  :initform :unspecified
+                  :initfunction ,(constantly :unspecified))
+		 (:name dependents
+		  :initform nil :initfunction ,#'false)) 
+ :metaclass 'funcallable-standard-class)
+
+
+
+(%ensure-class-preserving-wrapper
+ 'standard-generic-function
+ :direct-superclasses '(generic-function)
+
+ :metaclass 'funcallable-standard-class
+ :primary-p t)
+
+(%ensure-class-preserving-wrapper
+ 'standard-generic-function
+ :direct-superclasses '(generic-function)
+
+ :metaclass 'funcallable-standard-class)
+
+(%ensure-class-preserving-wrapper
+ 'structure-class
+ :direct-superclasses '(slots-class))
+
+(%ensure-class-preserving-wrapper
+ 'slot-definition
+ :direct-superclasses '(metaobject)
+  :direct-slots `((:name name :initargs (:name) :readers (slot-definition-name)
+		  :initform nil :initfunction ,#'false)
+		 (:name type :initargs (:type) :readers (slot-definition-type)
+		  :initform t :initfunction ,#'true)
+		 (:name initfunction :initargs (:initfunction) :readers (slot-definition-initfunction)
+		  :initform nil :initfunction ,#'false)
+		 (:name initform :initargs (:initform) :readers (slot-definition-initform)
+		  :initform nil :initfunction ,#'false)
+		 (:name initargs :initargs (:initargs) :readers (slot-definition-initargs)
+		  :initform nil :initfunction ,#'false)
+		 (:name allocation :initargs (:allocation) :readers (slot-definition-allocation)
+		  :initform :instance :initfunction ,(constantly :instance))
+		 (:name documentation :initargs (:documentation) :readers (slot-definition-documentation)
+		  :initform nil :initfunction ,#'false)
+		 (:name class :initargs (:class) :readers (slot-definition-class)))
+  
+ :primary-p t)
+
+(%ensure-class-preserving-wrapper
+ 'direct-slot-definition
+ :direct-superclasses '(slot-definition)
+ :direct-slots `((:name readers :initargs (:readers) :initform nil
+		  :initfunction ,#'false :readers (slot-definition-readers))
+		 (:name writers :initargs (:writers) :initform nil
+		  :initfunction ,#'false :readers (slot-definition-writers))))
+
+(%ensure-class-preserving-wrapper
+ 'effective-slot-definition
+ :direct-superclasses '(slot-definition)
+ :direct-slots `((:name location :initform nil :initfunction ,#'false
+		  :readers (slot-definition-location))
+		 (:name slot-id :initform nil :initfunction ,#'false
+                  :readers (slot-definition-slot-id))
+		 (:name type-predicate :initform nil
+		  :initfunction ,#'false
+		  :readers (slot-definition-predicate))
+		 )
+ 
+ :primary-p t)
+
+(%ensure-class-preserving-wrapper
+ 'standard-slot-definition
+ :direct-superclasses '(slot-definition)
+)
+
+
+
+
+
+
+
+(%ensure-class-preserving-wrapper
+ 'standard-direct-slot-definition
+ :direct-superclasses '(standard-slot-definition direct-slot-definition)
+)
+
+(%ensure-class-preserving-wrapper
+ 'standard-effective-slot-definition
+ :direct-superclasses '(standard-slot-definition effective-slot-definition))
+
+		 
+
+
+      
+                             
+
+
+
+;;; Fake method-combination, redefined in lib;method-combination.
+(unless *type-system-initialized*
+ (defclass method-combination (metaobject) 
+   ((name :initarg :name))))
+
+
+
+
+(defclass standard-method-combination (method-combination) ())
+
+(initialize-instance *standard-method-combination* :name 'standard)
+
+(setq *standard-kernel-method-class*
+  (defclass standard-kernel-method (standard-method)
+    ()))
+
+(unless *standard-method-combination*
+  (setq *standard-method-combination*
+        (make-instance 'standard-method-combination :name 'standard)))
+
+;;; For %compile-time-defclass
+(defclass compile-time-class (class) ())
+
+(defmethod compile-time-class-p ((class compile-time-class))
+  t)
+
+(defmethod class-finalized-p ((class compile-time-class))
+  nil)
+
+
+(defclass structure-slot-definition (slot-definition) ())
+(defclass structure-effective-slot-definition (structure-slot-definition
+					       effective-slot-definition)
+    ())
+
+(defclass structure-direct-slot-definition (structure-slot-definition
+					    direct-slot-definition)
+    ())
+
+(defmethod shared-initialize :after ((class structure-class)
+                                     slot-names
+                                     &key
+                                     (direct-superclasses nil direct-superclasses-p)
+				     &allow-other-keys)
+  (declare (ignore slot-names))
+  (labels ((obsolete (class)
+             (dolist (sub (%class-direct-subclasses class)) (obsolete sub))
+             ;;Need to save old class info in wrapper for obsolete
+             ;;instance access...
+             (setf (%class.cpl class) nil)))
+    (obsolete class)
+    (when direct-superclasses-p
+      (let* ((old-supers (%class-direct-superclasses class))
+             (new-supers direct-superclasses))
+        (dolist (c old-supers)
+          (unless (memq c new-supers)
+            (remove-direct-subclass c class)))
+        (dolist (c new-supers)
+          (unless (memq c old-supers)
+            (add-direct-subclass c class)))
+        (setf (%class.local-supers class) new-supers)))
+    (let* ((wrapper (or (%class-own-wrapper class)
+                        (setf (%class-own-wrapper class) (%cons-wrapper class))))
+           (cpl (compute-cpl class)))
+      (setf (%class.cpl class) cpl)
+      (setf (%wrapper-cpl wrapper) cpl
+            (%wrapper-cpl-bits wrapper) (make-cpl-bits cpl)))))
+              
+
+                                     
+                                     
+;;; Called from DEFSTRUCT expansion.
+(defun %define-structure-class (sd)
+  (let* ((dslots ()))
+    (dolist (ssd (cdr (sd-slots sd)) (setq dslots (nreverse dslots)))
+      (let* ((type (ssd-type ssd))
+	     (refinfo (ssd-refinfo ssd)))
+	(unless (logbitp $struct-inherited refinfo)
+	  (let* ((name (ssd-name ssd))
+		 (initform (cadr ssd))
+		 (initfunction (constantly initform)))
+	    (push `(:name ,name :type ,type :initform ,initform :initfunction ,initfunction :initargs ,(list (make-keyword name))) dslots)))))
+    (ensure-class (sd-name sd)
+		  :metaclass 'structure-class
+		  :direct-superclasses (list (or (cadr (sd-superclasses sd)) 'structure-object))
+		  :direct-slots  dslots 
+		  )))
+
+
+(defun standard-instance-access (instance location)
+  (etypecase location
+    (fixnum (%standard-instance-instance-location-access instance location))
+    (cons (%cdr location))))
+
+(defun (setf standard-instance-access) (new instance location)
+  (etypecase location
+    (fixnum (setf (standard-instance-instance-location-access instance location)
+		  new))
+    (cons (setf (%cdr location) new))))
+
+(defun funcallable-standard-instance-access (instance location)
+  (etypecase location
+    (fixnum (%standard-generic-function-instance-location-access instance location))
+    (cons (%cdr location))))
+
+(defun (setf funcallable-standard-instance-access) (new instance location)
+  (etypecase location
+    (fixnum (setf (%standard-generic-function-instance-location-access instance location) new))
+    (cons (setf (%cdr location) new))))
+
+;;; Handle a trap from %slot-ref
+(defun %slot-unbound-trap (slotv idx frame-ptr)
+  (let* ((instance nil)
+	 (class nil)
+	 (slot nil))
+    (if (and (eq (typecode slotv) target::subtag-slot-vector)
+	     (setq instance (slot-vector.instance slotv))
+	     (setq slot
+		   (find idx (class-slots (setq class (class-of instance)))
+			 :key #'slot-definition-location)))
+      (slot-unbound class instance (slot-definition-name slot))
+      (%error "Unbound slot at index ~d in ~s" (list idx slotv) frame-ptr))))
+
+
+
+;;;
+;;; Now that CLOS is nominally bootstrapped, it's possible to redefine some
+;;; of the functions that really should have been generic functions ...
+(setf (fdefinition '%class-name) #'class-name
+      (fdefinition '%class-default-initargs) #'class-default-initargs
+      (fdefinition '%class-direct-default-initargs) #'class-direct-default-initargs
+      (fdefinition '(setf %class-direct-default-initargs))
+      #'(lambda (new class)
+	  (if (typep class 'slots-class)
+	    (setf (slot-value class 'direct-default-initargs) new)
+	    new))
+      (fdefinition '%class-direct-slots) #'class-direct-slots
+      (fdefinition '(setf %class-direct-slots))
+		   #'(setf class-direct-slots)
+      (fdefinition '%class-slots) #'class-slots
+      (fdefinition '%class-direct-superclasses) #'class-direct-superclasses
+      (fdefinition '(setf %class-direct-superclasses))
+      #'(lambda (new class)
+	  (setf (slot-value class 'direct-superclasses) new))
+      (fdefinition '%class-direct-subclasses) #'class-direct-subclasses
+      ;(fdefinition '%class-own-wrapper) #'class-own-wrapper
+      (fdefinition '(setf %class-own-wrapper)) #'(setf class-own-wrapper)
+)
+
+
+
+(setf (fdefinition '%slot-definition-name) #'slot-definition-name
+      (fdefinition '%slot-definition-type) #'slot-definition-type
+      (fdefinition '%slot-definition-initargs) #'slot-definition-initargs
+      (fdefinition '%slot-definition-allocation) #'slot-definition-allocation
+      (fdefinition '%slot-definition-location) #'slot-definition-location
+      (fdefinition '%slot-definition-readers) #'slot-definition-readers
+      (fdefinition '%slot-definition-writers) #'slot-definition-writers)
+
+
+(setf (fdefinition '%method-qualifiers) #'method-qualifiers
+      (fdefinition '%method-specializers) #'method-specializers
+      (fdefinition '%method-function) #'method-function
+      (fdefinition '(setf %method-function)) #'(setf method-function)
+      (fdefinition '%method-gf) #'method-generic-function
+      (fdefinition '(setf %method-gf)) #'(setf method-generic-function)
+      (fdefinition '%method-name) #'method-name
+      (fdefinition '%method-lambda-list) #'method-lambda-list
+      )
+
+(setf (fdefinition '%add-method) #'add-method)
+		   
+      
+;;; Make a direct-slot-definition of the appropriate class.
+(defun %make-direct-slotd (slotd-class &rest initargs)
+  (declare (dynamic-extent initargs))
+  (apply #'make-instance slotd-class initargs))
+
+;;; Likewise, for an effective-slot-definition.
+(defun %make-effective-slotd (slotd-class &rest initargs)
+  (declare (dynamic-extent initargs))
+  (apply #'make-instance slotd-class initargs))
+
+;;; Likewise, for methods
+(defun %make-method-instance (class &rest initargs)
+  (apply #'make-instance class initargs))
+
+(defmethod initialize-instance :after ((slotd effective-slot-definition) &key name)
+  (setf (standard-effective-slot-definition.slot-id slotd)
+        (ensure-slot-id name)))
+
+  
+(defmethod specializer-direct-generic-functions ((s specializer))
+  (let* ((gfs ())
+	 (methods (specializer-direct-methods s)))
+    (dolist (m methods gfs)
+      (let* ((gf (method-generic-function m)))
+	(when gf (pushnew gf gfs))))))
+
+(defmethod generic-function-lambda-list ((gf standard-generic-function))
+  (%maybe-compute-gf-lambda-list gf (car (generic-function-methods gf))))
+
+(defmethod generic-function-argument-precedence-order
+    ((gf standard-generic-function))
+  (let* ((req (required-lambda-list-args (generic-function-lambda-list gf)))
+	 (apo (%gf-dispatch-table-precedence-list
+	       (%gf-dispatch-table gf))))
+    (if (null apo)
+      req
+      (mapcar #'(lambda (n) (nth n req)) apo))))
+
+(defun normalize-egf-keys (keys gf)
+  (let* ((missing (cons nil nil))
+	 (env (getf keys :environment nil)))
+    (declare (dynamic-extent missing))
+    (remf keys :environment)
+    (let* ((gf-class (getf keys :generic-function-class missing))
+	   (mcomb (getf keys :method-combination missing))
+	   (method-class (getf keys :method-class missing)))
+      (if (eq gf-class missing)
+	(setf gf-class (if gf (class-of gf) *standard-generic-function-class*))
+	(progn
+	  (remf keys :generic-function-class)
+	  (if (typep gf-class 'symbol)
+	    (setq gf-class
+		  (find-class gf-class t env)))
+	  (unless (or (eq gf-class *standard-generic-function-class*)
+		      (subtypep gf-class *generic-function-class*))
+	    (error "Class ~S is not a subclass of ~S"
+                   gf-class *generic-function-class*))))
+      (unless (eq mcomb missing)
+	(unless (typep mcomb 'method-combination)
+	  (setf (getf keys :method-combination)
+		(find-method-combination (class-prototype gf-class)
+					 (car mcomb)
+					 (cdr mcomb)))))
+      (unless (eq method-class missing)
+	(if (typep method-class 'symbol)
+	  (setq method-class (find-class method-class t env)))
+	(unless (subtypep method-class *method-class*)
+	  (error "~s is not a subclass of ~s" method-class *method-class*))
+	(setf (getf keys :method-class) method-class))
+      (values gf-class keys))))
+    
+(defmethod ensure-generic-function-using-class
+    ((gf null)
+     function-name
+     &rest keys
+     &key
+     &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (multiple-value-bind (gf-class initargs)
+      (normalize-egf-keys keys nil)
+    (let* ((gf (apply #'make-instance gf-class
+		      :name function-name
+		      initargs)))
+      (setf (fdefinition function-name) gf))))
+
+(defparameter *error-on-gf-class-redefinition* nil
+  "The MOP spec requires ENSURE-GENERIC-FUNCTION-USING-CLASS of an
+   existing gf to signal an error if the :GENERIC-FUNCTION-CLASS
+   argument specifies a class other than the existing gf's class.
+   ANSI CL allows this kind of redefinition if the classes are
+   \"compatible\", but doesn't define what compatibility means
+   in this case.  When *ERROR-ON-GF-CLASS-REDEFINITION* is true,
+   a continuable error is signaled.
+
+   Historically, Clozure CL CERRORed, but didn't offer a useful
+   CHANGE-CLASS method that would change the GF's class")
+
+(defmethod ensure-generic-function-using-class
+    ((gf generic-function)
+     function-name
+     &rest keys
+     &key
+     &allow-other-keys)
+  (declare (dynamic-extent keys) (ignorable function-name))
+  (multiple-value-bind (gf-class initargs)
+      (normalize-egf-keys keys gf)
+    (unless (eq gf-class (class-of gf))
+      (when *error-on-gf-class-redefinition*
+        (cerror (format nil "Change the class of ~s to ~s." gf gf-class)
+                "The class of the existing generic function ~s is not ~s"
+                gf gf-class))
+      (change-class gf gf-class))
+    (apply #'reinitialize-instance gf initargs)))
+
+
+(defmethod initialize-instance :before ((instance generic-function)
+                                       &key &allow-other-keys)
+  (setf (%gf-dcode instance)  #'%%0-arg-dcode))
+
+(defmethod initialize-instance :after ((gf standard-generic-function)
+				       &key
+				       (lambda-list nil ll-p)
+				       (argument-precedence-order nil apo-p)
+				       &allow-other-keys)
+  (if (and apo-p (not ll-p))
+    (error
+     "Cannot specify :ARGUMENT-PRECEDENCE-ORDER without specifying :LAMBDA-LIST"))
+  (if ll-p
+    (progn
+      (unless (verify-lambda-list lambda-list)
+	(error "~s is not a valid generic function lambda list" lambda-list))
+      (if apo-p
+	(set-gf-arg-info gf :lambda-list lambda-list
+			 :argument-precedence-order argument-precedence-order)
+	(set-gf-arg-info gf :lambda-list lambda-list)))
+    (set-gf-arg-info gf))
+  (if (gf-arg-info-valid-p gf)
+    (compute-dcode gf (%gf-dispatch-table gf)))
+  gf)
+
+(defmethod reinitialize-instance :after ((gf standard-generic-function)
+					 &rest args
+					 &key
+					 (lambda-list nil ll-p)
+					 (argument-precedence-order nil apo-p)
+					 &allow-other-keys)
+  (if (and apo-p (not ll-p))
+    (error
+     "Cannot specify :ARGUMENT-PRECEDENCE-ORDER without specifying :LAMBDA-LIST"))
+  (if ll-p
+    (progn
+      (unless (verify-lambda-list lambda-list)
+	(error "~s is not a valid generic function lambda list" lambda-list))
+      (if apo-p
+	(set-gf-arg-info gf :lambda-list lambda-list
+			 :argument-precedence-order argument-precedence-order)
+	(set-gf-arg-info gf :lambda-list lambda-list)))
+    (set-gf-arg-info gf))
+  (if (and (gf-arg-info-valid-p gf)
+	   args
+	   (or ll-p (cddr args)))
+    (compute-dcode gf (%gf-dispatch-table gf)))
+  (when (sgf.dependents gf)
+    (map-dependents gf #'(lambda (d)
+			   (apply #'update-dependent gf d args))))
+  gf)
+  
+
+(defun decode-method-lambda-list (method-lambda-list)
+  (flet ((bad ()
+	   (error "Invalid lambda-list syntax in ~s" method-lambda-list)))
+    (collect ((specnames)
+                    (required))
+       (do* ((tail method-lambda-list (cdr tail))
+	     (head (car tail) (car tail)))
+	    ((or (null tail) (member head lambda-list-keywords))
+	     (if (verify-lambda-list tail)
+	       (values (required) tail (specnames))
+	       (bad)))
+	 (cond ((atom head)
+		(unless (typep head 'symbol) (bad))
+		(required head)
+		(specnames t))
+	       (t
+		(unless (and (typep (car head) 'symbol)
+			     (consp (cdr head))
+			     (null (cddr head)))
+		  (bad))
+		(required (car head))
+		(specnames (cadr head))))))))
+  
+(defun extract-specializer-names (method-lambda-list)
+  (nth-value 2 (decode-method-lambda-list method-lambda-list)))
+
+(defun extract-lambda-list (method-lambda-list)
+  (multiple-value-bind (required tail)
+      (decode-method-lambda-list method-lambda-list)
+    (nconc required tail)))
+
+(setf (fdefinition '%ensure-generic-function-using-class)
+      #'ensure-generic-function-using-class)
+
+
+(defmethod shared-initialize :after ((gf generic-function) slot-names
+				     &key
+				     (documentation nil doc-p))
+  (declare (ignore slot-names))
+  (when doc-p
+    (if documentation (check-type documentation string))
+    (set-documentation gf t documentation)))
+
+
+
+
+(defmethod allocate-instance ((b built-in-class) &rest initargs)
+  (declare (ignore initargs))
+  (error "Can't allocate instances of BUILT-IN-CLASS."))
+
+(defmethod reinitialize-instance ((m method) &rest initargs)
+  (declare (ignore initargs))
+  (error "Can't reinitialze ~s ~s" (class-of m) m))
+
+(defmethod add-dependent ((class class) dependent)
+  (pushnew dependent (%class.dependents class)))
+
+(defmethod add-dependent ((gf standard-generic-function) dependent)
+  (pushnew dependent (sgf.dependents gf)))
+
+(defmethod remove-dependent ((class class) dependent)
+  (setf (%class.dependents class)
+	(delete dependent (%class.dependents class))))
+
+(defmethod remove-dependent ((gf standard-generic-function) dependent)
+  (setf (sgf.dependents gf)
+	(delete dependent (sgf.dependents gf))))
+
+(defmethod map-dependents ((class class) function)
+  (dolist (d (%class.dependents class))
+    (funcall function d)))
+
+(defmethod map-dependents ((gf standard-generic-function) function)
+  (dolist (d (sgf.dependents gf))
+    (funcall function d)))
+
+(defgeneric update-dependent (metaobject dependent &rest initargs))
+
+(defmethod reinitialize-instance :after ((class std-class) &rest initargs)
+  (map-dependents class #'(lambda (d)
+			    (apply #'update-dependent class d initargs))))
+
+
+(defun %allocate-gf-instance (class)
+  (unless (class-finalized-p class)
+    (finalize-inheritance class))
+  (let* ((wrapper (%class.own-wrapper class))
+         (gf-p (member *generic-function-class* (%class-cpl class)))
+	 (len (length (%wrapper-instance-slots wrapper)))
+	 (dt (if gf-p (make-gf-dispatch-table)))
+	 (slots (allocate-typed-vector :slot-vector (1+ len) (%slot-unbound-marker)))
+	 (fn
+          #+ppc-target
+           (gvector :function
+                    *unset-fin-code*
+                    wrapper
+                    slots
+                    dt
+                    #'false
+                    0
+                    (logior (ash 1 $lfbits-gfn-bit)
+                            (ash 1 $lfbits-aok-bit)))
+           #+x86-target
+           (%clone-x86-function #'unset-fin-trampoline
+                                wrapper
+                                slots
+                                dt
+                                #'false
+                                0
+                                (logior (ash 1 $lfbits-gfn-bit)
+                                        (ash 1 $lfbits-aok-bit)))))
+    (setf 
+	  (slot-vector.instance slots) fn)
+    (when dt
+      (setf (%gf-dispatch-table-gf dt) fn))
+    (if gf-p
+      (push fn (population.data %all-gfs%)))
+    fn))
+
+
+(defmethod slot-value-using-class ((class structure-class)
+				   instance
+				   (slotd structure-effective-slot-definition))
+  (let* ((loc (standard-effective-slot-definition.location slotd)))
+      (typecase loc
+	(fixnum
+	 (struct-ref  instance loc))
+	(t
+	 (error "Slot definition ~s has invalid location ~s (allocation ~s)."
+		slotd loc (slot-definition-allocation slotd))))))
+
+;;; Some STRUCTURE-CLASS leftovers.
+(defmethod (setf slot-value-using-class)
+    (new
+     (class structure-class)
+     instance
+     (slotd structure-effective-slot-definition))
+  (let* ((loc (standard-effective-slot-definition.location slotd))
+	 (type (standard-effective-slot-definition.type slotd)))
+    (if (and type (not (eq type t)))
+      (unless (or (eq new (%slot-unbound-marker))
+		  (typep new type))
+	(setq new (require-type new type))))
+    (typecase loc
+      (fixnum
+       (setf (struct-ref instance loc) new))
+      (t
+       (error "Slot definition ~s has invalid location ~s (allocation ~s)."
+	      slotd loc (slot-definition-allocation slotd))))))
+
+(defmethod slot-boundp-using-class ((class structure-class)
+				    instance
+				    (slotd structure-effective-slot-definition))
+  (declare (ignore instance))
+  t)
+
+;;; This has to be somewhere, so it might as well be here.
+(defmethod make-load-form ((s slot-id) &optional env)
+  (declare (ignore env))
+  `(ensure-slot-id ,(slot-id.name s)))
+
+(defmethod make-load-form ((c class-cell) &optional env)
+  (declare (ignore env))
+  `(find-class-cell ',(class-cell-name c) t))
+
+
+
+(defmethod (setf class-name) (new (class class))
+  (check-type new symbol)
+  (when (and (standard-instance-p class)
+             (%class-kernel-p class)
+             (not (eq new (%class.name class)))
+             *warn-if-redefine-kernel*)
+    (cerror "Change the name of ~s to ~s."
+            "The class ~s may be a critical part of the system;
+changing its name to ~s may have serious consequences." class new))
+  (let* ((old-name (class-name class)))
+    (if (eq (find-class old-name nil) class)
+      (progn
+        (setf (info-type-kind old-name) nil)
+        (clear-type-cache))))
+  (when (eq (find-class new nil) class)
+    (when (%deftype-expander new)
+      (cerror "Change the name of ~S anyway, removing the DEFTYPE definition."
+              "Changing the name of ~S to ~S would conflict with the type defined by DEFTYPE."
+              class new)
+      (%deftype new nil nil))
+    (setf (info-type-kind new) :instance)
+    (clear-type-cache))
+  (reinitialize-instance class :name new)
+  (setf (%class-proper-name class)
+        (if (eq (find-class new nil) class)
+          new))
+  new)
+
+
+;;; From Tim Moore, as part of a set of patches to support funcallable
+;;; instances.
+
+;;; Support for objects with metaclass funcallable-instance-class that are not
+;;; standard-generic-function. The objects still look a lot like generic
+;;; functions, complete with vestigial dispatch
+;;; tables. set-funcallable-instance-function will work on generic functions,
+;;; though after that it won't be much of a generic function.
+
+
+
+
+
+(defun set-funcallable-instance-function (funcallable-instance function)
+  (unless (typep funcallable-instance 'funcallable-standard-object)
+    (error "~S is not a funcallable instance" funcallable-instance))
+  (unless (functionp function)
+    (error "~S is not a function" function))
+  (setf (%gf-dcode funcallable-instance) function))
+
+(defmethod reinitialize-instance ((slotd slot-definition) &key &allow-other-keys)
+  (error "Can't reinitialize ~s" slotd))
+
+(defmethod (setf generic-function-name) (new-name (gf generic-function))
+  (reinitialize-instance gf :name new-name))
+
+;;; Are we CLOS yet ?
+
+(defun %shared-initialize (instance slot-names initargs)
+  (unless (or (listp slot-names) (eq slot-names t))
+    (report-bad-arg slot-names '(or list (eql t))))
+  ;; Check that initargs contains valid key/value pairs,
+  ;; signal a PROGRAM-ERROR otherwise.  (Yes, this is
+  ;; an obscure way to do so.)
+  (destructuring-bind (&key &allow-other-keys) initargs)
+  ;; I'm not sure if there's a more portable way of detecting
+  ;; obsolete instances.  This'll eventually call
+  ;; UPDATE-INSTANCE-FOR-REDEFINED-CLASS if it needs to.
+  (let* ((wrapper (if (eq (typecode instance) target::subtag-instance)
+                    (instance.class-wrapper instance)
+                    (instance-class-wrapper instance)))
+         (class (%wrapper-class wrapper)))
+    (when (eql 0 (%wrapper-hash-index wrapper)) ; obsolete
+      (update-obsolete-instance instance))
+    ;; Now loop over all of the class's effective slot definitions.
+    (dolist (slotd (class-slots class))
+      ;; Anything that inherits from STANDARD-EFFECTIVE-SLOT-DEFINITION
+      ;; in Clozure CL will have a CCL::TYPE-PREDICATE slot.  It's not
+      ;; well-defined to inherit from EFFECTIVE-SLOT-DEFINITION without
+      ;; also inheriting from STANDARD-EFFECTIVE-SLOT-DEFINITION,
+      ;; and I'd rather not check here.  If you really want to
+      ;; create that kind of slot definition, write your own SHARED-INITIALIZE
+      ;; method for classes that use such slot definitions ...
+      (let* ((predicate (slot-definition-predicate slotd)))
+        (multiple-value-bind (ignore new-value foundp)
+            (get-properties initargs (slot-definition-initargs slotd))
+          (declare (ignore ignore))
+          (cond (foundp
+                 ;; an initarg for the slot was passed to this function
+                 ;; Typecheck the new-value, then call
+                 ;; (SETF SLOT-VALUE-USING-CLASS)
+                 (unless (or (null predicate)
+                             (funcall predicate new-value))
+                   (error 'bad-slot-type-from-initarg
+                          :slot-definition slotd
+                          :instance instance
+                          :datum new-value
+                          :expected-type  (slot-definition-type slotd)
+                          :initarg-name (car foundp)))
+                 (setf (slot-value-using-class class instance slotd) new-value))
+                ((and (or (eq slot-names t)
+                          (member (slot-definition-name slotd)
+                                  slot-names
+                                  :test #'eq))
+                      (not (slot-boundp-using-class class instance slotd)))
+                 ;; If the slot name is among the specified slot names, or
+                 ;; we're reinitializing all slots, and the slot is currently
+                 ;; unbound in the instance, set the slot's value based
+                 ;; on the initfunction (which captures the :INITFORM).
+                 (let* ((initfunction (slot-definition-initfunction slotd)))
+                   (if initfunction
+                     (let* ((newval (funcall initfunction)))
+                       (unless (or (null predicate)
+                                   (funcall predicate newval))
+                         (error 'bad-slot-type-from-initform
+                                :slot-definition slotd
+                                :expected-type (slot-definition-type slotd)
+                                :datum newval
+                                :instance instance))
+                       (setf (slot-value-using-class class instance slotd)
+                             newval))))))))))
+  instance)
+
+(defmethod shared-initialize ((struct structure-object) slot-names &rest initargs)
+  (unless (eq slot-names t)
+    (error "Structure instance ~s can't be reinitialized." struct))
+  (dolist (slotd (class-slots (class-cell-class (car (%svref struct 0)))))
+    (let* ((predicate (slot-definition-predicate slotd))
+           (location (slot-definition-location slotd)))
+      (declare (fixnum location))
+      (multiple-value-bind (ignore new-value foundp)
+          (get-properties initargs (slot-definition-initargs slotd))
+        (declare (ignore ignore))
+        (cond (foundp
+               ;; an initarg for the slot was passed to this function
+               ;; Typecheck the new-value, then call
+               ;; (SETF SLOT-VALUE-USING-CLASS)
+               (unless (or (null predicate)
+                           (funcall predicate new-value))
+                 (error 'bad-slot-type-from-initarg
+                        :slot-definition slotd
+                        :instance struct
+                        :datum new-value
+                        :expected-type  (slot-definition-type slotd)
+                          :initarg-name (car foundp)))
+                 (setf (struct-ref struct location) new-value))
+                (t
+                 ;; If the slot name is among the specified slot names, or
+                 ;; we're reinitializing all slots, and the slot is currently
+                 ;; unbound in the instance, set the slot's value based
+                 ;; on the initfunction (which captures the :INITFORM).
+                 (let* ((initfunction (slot-definition-initfunction slotd)))
+                   (if initfunction
+                     (let* ((newval (funcall initfunction)))
+                       (unless (or (null predicate)
+                                   (funcall predicate newval))
+                         (error 'bad-slot-type-from-initform
+                                :slot-definition slotd
+                                :expected-type (slot-definition-type slotd)
+                                :datum newval
+                                :instance struct))
+                       (setf (struct-ref struct location) newval)))))))))
+  struct)
+
+(defmethod initialize-instance ((struct structure-object) &rest initargs &key &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (apply #'shared-initialize struct t initargs))
+
+(defmethod make-instance ((class structure-class)  &rest initargs &key &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (let* ((struct (apply #'allocate-instance class initargs)))
+    (apply #'initialize-instance struct initargs)))
+
+    
+
+;;; Sometimes you can do a lot better at generic function dispatch than the
+;;; default. This supports that for the one-arg-dcode case.
+(defmethod override-one-method-one-arg-dcode ((generic-function t) (method t))
+  nil)
+
+(defun optimize-generic-function-dispatching ()
+  (dolist (gf (population.data %all-gfs%))
+    (optimize-dispatching-for-gf gf)))
+
+(defun optimize-dispatching-for-gf (gf)
+  (let* ((dcode (%gf-dcode gf))
+         (name (function-name dcode)))
+    (when (or (eq name '%%one-arg-dcode)
+              (eq name '%%nth-arg-dcode))
+      (let ((methods (generic-function-methods gf)))
+        (when (and methods (null (cdr methods)))
+          (when (or (eq #'%%one-arg-dcode dcode)
+                    (and (eq #'%%nth-arg-dcode dcode)
+                         (let ((spec (method-specializers (car methods)))
+                               (argnum (%gf-dispatch-table-argnum
+                                        (%gf-dispatch-table gf))))
+                           (and (eql 2 (length spec))
+                                (and (eql argnum 1) (eq (car spec) *t-class*))))))
+            (override-one-method-one-arg-dcode gf (car methods))))))))
+
+(defparameter *unique-reader-dcode-functions* t)
+
+;;; dcode for a GF with a single reader method which accesses
+;;; a slot in a class that has no subclasses (that restriction
+;;; makes typechecking simpler and also ensures that the slot's
+;;; location is correct.)
+(defun singleton-reader-dcode (dt instance)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((wrapper (%svref dt %gf-dispatch-table-first-data))
+         (location (%svref dt (1+ %gf-dispatch-table-first-data))))
+    (if (eq (if (eq (typecode instance) target::subtag-instance)
+              (instance.class-wrapper instance))
+            wrapper)
+      (%slot-ref (instance.slots instance) location)
+      (cond ((and (eq (typecode instance) target::subtag-instance)
+                  (eq 0 (%wrapper-hash-index (instance.class-wrapper instance)))
+                  (progn (update-obsolete-instance instance)
+                         (eq (instance.class-wrapper instance) wrapper)))
+             (%slot-ref (instance.slots instance) location))
+            (t (no-applicable-method (%gf-dispatch-table-gf dt) instance))))))
+(register-dcode-proto #'singleton-reader-dcode *gf-proto-one-arg*)
+
+;;; Dcode for a GF whose methods are all reader-methods which access a
+;;; slot in one or more classes which have multiple subclasses, all of
+;;; which (by luck or design) have the same slot-definition location.
+(defun reader-constant-location-dcode (dt instance)
+  (declare (optimize (speed 3) (safety 0)))
+    (if (memq (if (eq (typecode instance) target::subtag-instance)
+              (%class-of-instance instance))
+              (%svref dt %gf-dispatch-table-first-data))
+      (%slot-ref (instance.slots instance) (%svref dt (1+ %gf-dispatch-table-first-data)))
+      (no-applicable-method (%gf-dispatch-table-gf dt) instance)))
+(register-dcode-proto #'reader-constant-location-dcode *gf-proto-one-arg*)
+
+;;; Dcode for a GF whose methods are all reader-methods which access a
+;;; slot in one or more classes which have multiple subclasses, all of
+;;; which (by luck or design) have the same slot-definition location.
+;;; The number of classes for which the method is applicable is
+;;; potentially large, but all are subclasses of a single class
+(defun reader-constant-location-inherited-from-single-class-dcode (dt instance)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((defining-class-ordinal (%svref dt %gf-dispatch-table-first-data))
+         (bits  (let* ((wrapper
+                        (if (eq (typecode instance) target::subtag-instance)
+                          (instance.class-wrapper instance))))
+                  (when wrapper (or (%wrapper-cpl-bits wrapper)
+                                    (make-cpl-bits (%inited-class-cpl
+                                                    (%wrapper-class wrapper))))))))
+    (declare (fixnum defining-class-ordinal))
+    (if (and bits
+             (< defining-class-ordinal (the fixnum (uvsize bits)))
+             (not (eql 0 (sbit bits defining-class-ordinal))))
+      (%slot-ref (instance.slots instance) (%svref dt (1+ %gf-dispatch-table-first-data)))
+      (no-applicable-method (%gf-dispatch-table-gf dt) instance))))
+(register-dcode-proto #'reader-constant-location-inherited-from-single-class-dcode *gf-proto-one-arg*)
+
+;;; It may be faster to make individual functions that take their
+;;; "parameters" (defining class ordinal, slot location) as constants.
+;;; It may not be.  Use *unique-reader-dcode-functions* to decide
+;;; whether or not to do so.
+(defun make-reader-constant-location-inherited-from-single-class-dcode
+    (defining-class-ordinal location gf)
+  (if *unique-reader-dcode-functions*
+    (let* ((gf-name (function-name gf)))
+      (values
+       (%make-function 
+        `(slot-reader for ,gf-name)
+        `(lambda (instance)
+          (locally (declare (optimize (speed 3) (safety 0)))
+            (let* ((bits (let* ((wrapper
+                                 (if (eq (typecode instance) target::subtag-instance)
+                                   (instance.class-wrapper instance))))
+                           (when wrapper (or (%wrapper-cpl-bits wrapper)
+                                             (make-cpl-bits (%inited-class-cpl
+                                                             (%wrapper-class wrapper))))))))
+              (if (and bits
+                       (< ,defining-class-ordinal (the fixnum (uvsize bits)))
+                       (not (eql 0 (sbit bits ,defining-class-ordinal))))
+                (%slot-ref (instance.slots instance) ,location)
+                (no-applicable-method (function ,gf-name) instance)))))
+        nil)
+       #'funcallable-trampoline))
+    (let* ((dt (gf.dispatch-table gf)))
+      (setf (%svref dt %gf-dispatch-table-first-data)
+            defining-class-ordinal
+            (%svref dt (1+ %gf-dispatch-table-first-data))
+            location)
+      (values
+       (dcode-for-gf gf #'reader-constant-location-inherited-from-single-class-dcode)
+       (cdr (assq #'reader-constant-location-inherited-from-single-class-dcode dcode-proto-alist))))))
+
+;;; Dcode for a GF whose methods are all reader-methods which access a
+;;; slot in one or more classes which have multiple subclasses, all of
+;;; which (by luck or design) have the same slot-definition location.
+;;; The number of classes is for which the method is applicable is
+;;; large, but all are subclasses of one of a (small) set of defining classes.
+(defun reader-constant-location-inherited-from-multiple-classes-dcode (dt instance)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((wrapper (if (eq (typecode instance) target::subtag-instance)
+                    (instance.class-wrapper instance)))
+         (bits (if wrapper (or (%wrapper-cpl-bits wrapper)
+                               (make-cpl-bits (%inited-class-cpl (%wrapper-class wrapper))))))
+         (nbits (if bits (uvsize bits) 0)))
+    (declare (fixnum nbits))
+    (if (dolist (ordinal (%svref dt %gf-dispatch-table-first-data))
+          (declare (fixnum ordinal))
+          (when (and (< ordinal nbits)
+                     (not (eql 0 (sbit bits ordinal))))
+            (return t)))
+      (%slot-ref (instance.slots instance) (%svref dt (1+ %gf-dispatch-table-first-data)))
+      (no-applicable-method (%gf-dispatch-table-gf dt) instance))))
+(register-dcode-proto #'reader-constant-location-inherited-from-multiple-classes-dcode *gf-proto-one-arg*)
+
+
+;;; Similar to the case above, but we use an alist to map classes
+;;; to their non-constant locations.
+(defun reader-variable-location-dcode (dt instance)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((alist (%svref dt %gf-dispatch-table-first-data))
+         (location (cdr
+                    (assq
+                     (if (eq (typecode instance) target::subtag-instance)
+                       (%class-of-instance instance))
+                     alist))))
+    (if location
+      (%slot-ref (instance.slots instance) location)
+      (no-applicable-method (%gf-dispatch-table-gf dt) instance))))
+(register-dcode-proto #'reader-variable-location-dcode *gf-proto-one-arg*)
+
+(defun class-and-slot-location-alist (classes slot-name)
+  (let* ((alist nil))
+    (labels ((add-class (c)
+               (unless (assq c alist)
+                 (let* ((slots (class-slots c)))
+                   (unless slots
+                     (finalize-inheritance c)
+                     (setq slots (class-slots c)))
+                   (push (cons c (slot-definition-location (find-slotd slot-name slots))) alist))
+                 (dolist (sub (class-direct-subclasses c))
+                   (add-class sub)))))
+      (dolist (class classes) (add-class class))
+      ;; Building the alist the way that we have should often approximate
+      ;; this ordering; the idea is that leaf classes are more likely to
+      ;; be instantiated than non-leaves.
+      (sort alist (lambda (c1 c2)
+                    (< (length (class-direct-subclasses c1))
+                       (length (class-direct-subclasses c2))))
+            :key #'car))))
+
+;;; Return a list of all classes in CLASS-LIST that aren't subclasses
+;;; of any other class in the list.
+(defun remove-subclasses-from-class-list (class-list)
+  (if (null (cdr class-list))
+    class-list
+    (collect ((unique))
+      (dolist (class class-list (unique))
+        (when (dolist (other class-list t)
+                (unless (eq class other)
+                  (when (subtypep class other) (return nil))))
+          (unique class))))))
+
+
+;;; Try to replace gf dispatch with something faster in f.
+(defun %snap-reader-method (f &key (redefinable t))
+  (when (slot-boundp f 'methods)
+    (let* ((methods (generic-function-methods f)))
+      (when (and methods
+                 (every (lambda (m) (eq (class-of m) *standard-reader-method-class*)) methods)
+                 (every (lambda (m) (subtypep (class-of (car (method-specializers m))) *standard-class-class*)) methods)
+                 (every (lambda (m) (null (method-qualifiers m))) methods))
+        (let* ((m0 (car methods))
+               (name (slot-definition-name (accessor-method-slot-definition m0))))
+          (when (every (lambda (m)
+                         (eq name (slot-definition-name (accessor-method-slot-definition m))))
+                       (cdr methods))
+            ;; All methods are *STANDARD-READER-METHODS* that
+            ;; access the same slot name.  Build an alist of
+            ;; mapping all subclasses of all classes on which those
+            ;; methods are specialized to the effective slot's
+            ;; location in that subclass.
+            (let* ((classes (mapcar #'(lambda (m) (car (method-specializers m)))
+                                    methods))
+                   (alist (class-and-slot-location-alist classes name))
+                   (loc (cdar alist))
+                   (dt (gf.dispatch-table f)))
+              ;; Only try to handle the case where all slots have
+              ;; :allocation :instance (and all locations - the CDRs
+              ;; of the alist pairs - are small, positive fixnums.
+              (when (every (lambda (pair) (typep (cdr pair) 'fixnum)) alist)
+                (when redefinable
+                  (loop for (c . nil) in alist
+                        do (note-class-dependent c f)))
+                (clear-gf-dispatch-table dt)
+                (setf (%gf-dispatch-table-argnum dt) -1) ;mark as non-standard
+                (cond ((null (cdr alist))
+                       ;; Method is only applicable to a single class.
+                       (destructuring-bind (class . location) (car alist)
+                         (setf (%svref dt %gf-dispatch-table-first-data) (%class.own-wrapper class)
+                               (%svref dt (1+ %gf-dispatch-table-first-data)) location
+                               (gf.dcode f) (dcode-for-gf f #'singleton-reader-dcode))))
+                      ((dolist (other (cdr alist) t)
+                         (unless (eq (cdr other) loc)
+                           (return)))
+                       ;; All classes have the slot in the same location,
+                       ;; by luck or design.
+                       (cond
+                         ((< (length alist) 10)
+                          ;; Only a small number of classes, just do MEMQ
+                          (setf (%svref dt %gf-dispatch-table-first-data)
+                                (mapcar #'car alist)
+                                (%svref dt (1+ %gf-dispatch-table-first-data))
+                                loc
+                                (gf.dcode f) (dcode-for-gf f #'reader-constant-location-dcode)))
+                         ((null (cdr (setq classes (remove-subclasses-from-class-list classes))))
+                          ;; Lots of classes, all subclasses of a single class
+                          (multiple-value-bind (dcode trampoline)
+                              (make-reader-constant-location-inherited-from-single-class-dcode (%class-ordinal (car classes)) loc f)
+                            (setf (gf.dcode f) dcode)
+                            (replace-function-code f trampoline)))
+                         (t
+                          ;; Multple classes.  We should probably check
+                          ;; to see they're disjoint
+                          (setf (%svref dt %gf-dispatch-table-first-data)
+                                (mapcar #'%class-ordinal classes)
+                                (%svref dt (1+ %gf-dispatch-table-first-data))
+                                loc
+                                (gf.dcode f)
+                                (dcode-for-gf f #'reader-constant-location-inherited-from-multiple-classes-dcode)))))
+                      (t
+                       ;; Multiple classes; the slot's location varies.
+                       (setf (%svref dt %gf-dispatch-table-first-data)
+                             alist
+                             
+                             (gf.dcode f) (dcode-for-gf f #'reader-variable-location-dcode))))))))))))
+
+;;; Hack-o-rama: GF has nothing but primary methods, first (and only non-T)
+;;; specializers are all EQL specializers whose objects are symbols.
+;;; The effective method applicable for each symbol is stored on the
+;;; plist of the symbol under a property EQ to the dispatch table (which
+;;; is mostly ignored, otherwise.)
+(defun %%1st-arg-eql-method-hack-dcode (dt args)
+  (let* ((sym (if (listp args) (car args)(%lexpr-ref args (%lexpr-count args) 0)))
+         (mf (if (symbolp sym) (get sym dt))))
+    (if mf
+      (if (listp args)
+        (apply mf args)
+        (%apply-lexpr-tail-wise mf args))
+      ;;; Let %%1st-arg-dcode deal with it.
+      (%%1st-arg-dcode dt args))))
+(register-dcode-proto #'%%1st-arg-eql-method-hack-dcode *gf-proto*)
+
+(defun %%1st-two-arg-eql-method-hack-dcode (dt arg1 arg2)
+  (let* ((mf (if (typep arg1 'symbol) (get arg1 dt))))
+    (if mf
+      (funcall mf arg1 arg2)
+      (%%1st-two-arg-dcode dt arg1 arg2))))
+(register-dcode-proto #'%%1st-two-arg-eql-method-hack-dcode *gf-proto-two-arg*)
+
+(defun %%one-arg-eql-method-hack-dcode (dt arg)
+  (let* ((mf (if (typep arg 'symbol) (get arg dt))))
+    (if mf
+      (funcall mf arg))))
+(register-dcode-proto #'%%one-arg-eql-method-hack-dcode *gf-proto-one-arg*)
+
+(defun install-eql-method-hack-dcode (gf)
+  (let* ((bits (inner-lfun-bits gf))
+         (nreq (ldb $lfbits-numreq bits))
+         (other-args? (or (not (eql 0 (ldb $lfbits-numopt bits)))
+                          (logbitp $lfbits-rest-bit bits)
+                          (logbitp $lfbits-restv-bit bits)
+                          (logbitp $lfbits-keys-bit bits)
+                          (logbitp $lfbits-aok-bit bits))))
+    (setf (%gf-dcode gf)
+          (dcode-for-gf gf
+                        (cond ((and (eql nreq 1) (null other-args?))
+                               #'%%one-arg-eql-method-hack-dcode)
+                              ((and (eql nreq 2) (null other-args?))
+                               #'%%1st-two-arg-eql-method-hack-dcode)
+                              (t
+                               #'%%1st-arg-eql-method-hack-dcode))))))
+
+(defun maybe-hack-eql-methods (gf)
+  (let* ((methods (generic-function-methods gf)))
+    (when (and methods
+               (every #'(lambda (method)
+                          (let* ((specializers (method-specializers method))
+                                      (first (car specializers)))
+                                 (and (typep first 'eql-specializer)
+                                      (typep (eql-specializer-object first) 'symbol)
+                                      (dolist (s (cdr specializers) t)
+                                        (unless (eq s *t-class*)
+                                          (return nil)))
+                                      (null (cdr (compute-applicable-methods gf (cons (eql-specializer-object first) (make-list (length (cdr specializers))))))))))
+                      methods))
+      (let* ((dt (%gf-dispatch-table gf)))
+        (dolist (m methods)
+          (let* ((sym (eql-specializer-object (car (method-specializers m))))
+                 (f (method-function m)))
+            (setf (get sym dt) f)))
+        (install-eql-method-hack-dcode gf)
+        t))))
+
+
+            
+                            
+;;; Return a list of :after methods for INITIALIZE-INSTANCE on the
+;;; class's prototype, and a boolean that's true if no other qualified
+;;; methods are defined and at most one primary one.
+(defun initialize-instance-after-methods (proto class)
+  (let* ((method-list (compute-method-list (sort-methods
+                            (compute-applicable-methods #'initialize-instance (list proto))
+                            (list (class-precedence-list class))))))
+    (if (atom method-list)
+      (values nil t)
+      (if (and (null (car method-list))
+	       (null (cdddr method-list)))
+        (values (cadr method-list) t)
+        ;; :around or :before methods, or more than one primary method, give up
+        (values nil nil)))))
+
+(defparameter *typecheck-slots-in-optimized-make-instance* t)
+
+
+;;; Return a lambda form or NIL.
+(defun make-instantiate-lambda-for-class-cell (cell)
+  (let* ((class (class-cell-class cell))
+         (after-methods nil))
+    (when (and (typep class 'standard-class)
+               (progn (unless (class-finalized-p class)
+                        (finalize-inheritance class))
+                      t)
+               (null (cdr (compute-applicable-methods #'allocate-instance (list class))))
+               (let* ((proto (class-prototype class)))
+                 (and (multiple-value-bind (afters ok)
+                          (initialize-instance-after-methods proto class)
+                        (when ok
+                          (setq after-methods afters)
+                          t))
+                      (null (cdr (compute-applicable-methods #'shared-initialize (list proto t)))))))
+      (let* ((slotds (sort (copy-list (class-slots class))
+                           #'(lambda (x y)
+                               (if (consp x) x (if (consp y) y (< x y))))
+                           :key #'slot-definition-location))
+             (default-initargs (class-default-initargs class)))
+        (collect ((keys)
+                  (binds)
+                  (class-binds)
+                  (ignorable)
+                  (class-slot-inits)
+                  (after-method-forms)
+                  (forms))
+          (flet ((generate-type-check (form type &optional spvar)
+                   (if (or (null *typecheck-slots-in-optimized-make-instance*)
+                           (eq type t)
+                           (and (quoted-form-p type) (eq (cadr type) t)))
+                     form
+                     (if spvar
+                       `(if ,spvar
+                         (require-type ,form ',type)
+                         ,form)
+                       `(require-type ,form ',type)))))
+            (dolist (slot slotds)
+              (let* ((initargs (slot-definition-initargs slot))
+                     (initfunction (slot-definition-initfunction slot))
+                     (initform (slot-definition-initform slot))
+                     (location (slot-definition-location slot))
+                     (location-var nil)
+                     (class-init-p nil)
+                     (one-initarg-p (null (cdr initargs)))
+                     (name (slot-definition-name slot))
+                     (type (slot-definition-type slot)))
+                (when (consp location)
+                  (setq location-var (gensym "LOCATION")))
+                (when initfunction
+                  (setq initform
+                        (if (self-evaluating-p initform)
+                            initform
+                            `(funcall ,initfunction))))
+                (cond ((null initargs)
+                       (let ((initial-value-form
+                              (if initfunction
+                                  (generate-type-check initform type)
+                                  `(%slot-unbound-marker))))
+                         (if location-var
+                             (when initfunction
+                               (setq class-init-p t)
+                               (class-slot-inits
+                                `(when (eq (%slot-unbound-marker) (cdr ,location-var))
+                                   (setf (cdr ,location-var) ,initial-value-form))))
+                             (forms initial-value-form))))
+                      (t (collect ((cond-clauses))
+                           (let ((last-cond-clause nil))
+                             (dolist (initarg initargs)
+                               (let* ((spvar nil)
+                                      (name (if one-initarg-p
+                                                name
+                                                (gensym (string name))))
+                                      (initial-value-form
+                                       (if (and initfunction
+                                                one-initarg-p
+                                                (null location-var))
+                                           initform
+                                           (progn
+                                             (when initarg
+                                               (setq spvar (make-symbol
+                                                            (concatenate
+                                                             'string
+                                                             (string initarg)
+                                                             "-P"))))
+                                             (and one-initarg-p
+                                                  (null location-var)
+                                                  (if initfunction
+                                                      initform
+                                                      `(%slot-unbound-marker))))))
+                                      (default (assq initarg default-initargs))
+                                      (default-value-form nil))
+                                 (when spvar (ignorable spvar))
+                                 (when default
+                                   (destructuring-bind (form function)
+                                       (cdr default)
+                                     (setq default-value-form
+                                           (if (or (quoted-form-p form)
+                                                   (self-evaluating-p form))
+                                               form
+                                               `(funcall ,function)))))
+                                 (keys (list*
+                                        (list initarg name)
+                                        (if (and default one-initarg-p (null location-var))
+                                            default-value-form
+                                            initial-value-form)
+                                        (if spvar (list spvar))))
+                                 (if one-initarg-p
+                                   (if location-var
+                                     (progn
+                                       (setq class-init-p t)
+                                       (class-slot-inits
+                                        `(if ,spvar
+                                           (setf (cdr ,location-var)
+                                                 ,(generate-type-check
+                                                   name type))
+                                           ,(if default
+                                              `(setf (cdr ,location-var)
+                                                     ,(generate-type-check
+                                                       default type))
+                                              (when initfunction
+                                                `(when (eq (%slot-unbound-marker)
+                                                           (cdr ,location-var))
+                                                   (setf (cdr ,location-var)
+                                                         ,(generate-type-check
+                                                           initform type))))))))
+                                     (forms `,(generate-type-check name type spvar)))
+                                     (progn (cond-clauses `(,spvar ,name))
+                                            (when (and default (null last-cond-clause))
+                                              (setq last-cond-clause
+                                                    `(t ,default)))))))
+                             (when (cond-clauses)
+                               (when last-cond-clause
+                                 (cond-clauses last-cond-clause))
+                               (cond ((null location-var)
+                                      (unless last-cond-clause
+                                        (cond-clauses `(t ,initform)))
+                                      (forms (generate-type-check
+                                              `(cond ,@(cond-clauses))
+                                              type)))
+                                     (t
+                                      (let ((initform-p-var
+                                             (unless last-cond-clause
+                                               (make-symbol "INITFORM-P")))
+                                            (value-var (make-symbol "VALUE")))
+                                        (unless last-cond-clause
+                                          (cond-clauses
+                                           `(t (setq ,initform-p-var t)
+                                               ,(if initfunction
+                                                    initform
+                                                    `(%slot-unbound-marker)))))
+                                        (setq class-init-p t)
+                                        (class-slot-inits
+                                         `(let* (,@(and initform-p-var
+                                                        (list `(,initform-p-var nil)))
+                                                 (,value-var
+                                                  ,(generate-type-check
+                                                    `(cond ,@(cond-clauses)) type)))
+                                            (when
+                                                ,(if initform-p-var
+                                                     `(or (null ,initform-p-var)
+                                                          (and (eq (cdr ,location-var)
+                                                                   (%slot-unbound-marker))
+                                                               (not (eq ,value-var
+                                                                        (%slot-unbound-marker)))))
+                                                     t)
+                                                (setf (cdr ,location-var) ,value-var))))))))))))
+                (when class-init-p
+                  (class-binds `(,location-var
+                                 (load-time-value
+                                  (slot-definition-location ',slot))))))))
+          (let* ((cell (make-symbol "CLASS-CELL"))
+                 (args (make-symbol "ARGS"))
+                 (slots (make-symbol "SLOTS"))
+                 (instance (make-symbol "INSTANCE")))
+            (dolist (after after-methods)
+              (after-method-forms `(apply ,(method-function after) ,instance ,args)))
+            (when after-methods
+              (after-method-forms instance))
+            (binds `(,slots (gvector :slot-vector nil ,@(forms))))
+            (binds `(,instance (gvector :instance 0 (class-cell-extra ,cell) ,slots)))
+            `(lambda (,cell ,@(when after-methods `(&rest ,args)) &key ,@(keys) ,@(when after-methods '(&allow-other-keys)))
+              (declare (ignorable ,@(ignorable)))
+              ,@(when after-methods `((declare (dynamic-extent ,args))))
+              (let (,@(class-binds))
+                ,@(class-slot-inits))
+              (let* (,@(binds))
+                (setf (instance.hash ,instance) (strip-tag-to-fixnum ,instance)
+                      (%svref ,slots 0) ,instance)
+                ,@(after-method-forms)))))))))
+
+(defun optimize-make-instance-for-class-cell (cell)
+  (init-class-cell-instantiator cell)
+  (let* ((lambda (make-instantiate-lambda-for-class-cell cell)))
+    (when lambda
+      (setf (class-cell-instantiate cell) (compile nil lambda)
+            (class-cell-extra cell) (%class.own-wrapper
+                                     (class-cell-class cell)))
+      t)))
+
+(defun optimize-make-instance-for-class-name (class-name)
+  (optimize-make-instance-for-class-cell (find-class-cell class-name t)))
+
+(defun optimize-named-class-make-instance-methods ()
+  (maphash (lambda (class-name class-cell)
+             (handler-case (optimize-make-instance-for-class-cell class-cell)
+               (error (c)
+                      (warn "error optimizing make-instance for ~s:~&~a"
+                            class-name c))))
+           %find-classes%))
+
+;; Redefined from bootstrapping verison in l1-clos-boot.lisp
+;; Remove the make-instance optimization if the user is adding
+;; a method on initialize-instance, allocate-instance, or shared-initialize
+(defun maybe-remove-make-instance-optimization (gfn method)
+  (when (or (eq gfn #'allocate-instance)
+            (eq gfn #'initialize-instance)
+            (eq gfn #'shared-initialize))
+    (let ((specializer (car (method-specializers method))))
+      (when (typep specializer 'class)
+	(labels ((clear (class)
+		   (pessimize-make-instance-for-class-name (class-name class))
+		   (dolist (sub (%class-direct-subclasses class))
+		     (clear sub))))
+	  (clear specializer))))))
+
+;;; Iterate over all known GFs; try to optimize their dcode in cases
+;;; involving reader methods.
+
+(defun snap-reader-methods (&key known-sealed-world
+                                 (check-conflicts t)
+                                 (optimize-make-instance t))
+  (declare (ignore check-conflicts)
+	   (ignore known-sealed-world))
+  (when optimize-make-instance
+    (optimize-named-class-make-instance-methods))
+  (let* ((ngf 0)
+         (nwin 0))
+    (dolist (f (population.data %all-gfs%))
+      (incf ngf)
+      (when (%snap-reader-method f)
+        (incf nwin)))
+    (values ngf nwin 0)))
+
+(defun register-non-dt-dcode-function (f)
+  (flet ((symbol-or-function-name (x)
+           (etypecase x
+             (symbol x)
+             (function (function-name x)))))
+    (let* ((already (member (symbol-or-function-name f) *non-dt-dcode-functions* :key #'symbol-or-function-name)))
+      (if already
+        (setf (car already) f)
+        (push f *non-dt-dcode-functions*))
+      f)))
+
+(defun pessimize-clos ()
+  ;; Undo MAKE-INSTANCE optimization
+  (maphash (lambda (class-name class-cell)
+	     (declare (ignore class-name))
+	     (init-class-cell-instantiator class-cell))
+	   %find-classes%)
+  ;; Un-snap reader methods, undo other GF optimizations.
+  (dolist (f (population-data %all-gfs%))
+    (let* ((dt (%gf-dispatch-table f)))
+      (clear-gf-dispatch-table dt)
+      (compute-dcode f))))
+
+;;; If there's a single method (with standard method combination) on
+;;; GF and all of that method's arguments are specialized to the T
+;;; class - and if the method doesn't accept &key or do any
+;;; next-method things - we can just have the generic function call
+;;; the method-function
+(defun dcode-for-universally-applicable-singleton (gf)
+  (when (eq (generic-function-method-combination gf)
+            *standard-method-combination*)
+    (let* ((methods (generic-function-methods gf))
+           (method (car methods)))
+      (when (and method
+                 (null (cdr methods))
+                 (null (method-qualifiers method))
+                 (not (logtest (logior (ash 1 $lfbits-keys-bit)
+                                       (ash 1 $lfbits-nextmeth-bit))
+                                 (lfun-bits (method-function method))))
+                 (dolist (spec (method-specializers method) t)
+                   (unless (eq spec *t-class*)
+                     (return nil))))
+        (method-function method)))))
+
+(register-non-dt-dcode-function #'dcode-for-universally-applicable-singleton)
Index: /branches/new-random/level-1/l1-dcode.lisp
===================================================================
--- /branches/new-random/level-1/l1-dcode.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-dcode.lisp	(revision 13309)
@@ -0,0 +1,1962 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+
+
+
+
+
+(defun %make-gf-instance (class &key
+                                name
+                                (method-combination *standard-method-combination* mcomb-p)
+                                (method-class *standard-method-class* mclass-p)
+                                declarations
+                                (lambda-list nil ll-p)
+                                (argument-precedence-order nil apo-p)
+                                &allow-other-keys)
+  (when mcomb-p
+    (unless (typep method-combination 'method-combination)
+      (report-bad-arg method-combination 'method-combination)))
+  (when mclass-p
+    (if (symbolp method-class)
+      (setq method-class (find-class method-class)))
+    (unless (subtypep method-class *method-class*)
+      (error "~s is not a subtype of ~s." method-class *method-class*)))
+  (when declarations
+    (unless (list-length declarations)
+      (error "~s is not a proper list" declarations)))
+  ;; Fix APO, lambda-list
+  (if apo-p
+    (if (not ll-p)
+      (error "Cannot specify ~s without specifying ~s" :argument-precedence-order
+	     :lambda-list)))
+  (let* ((gf (%allocate-gf-instance class)))
+    (setf (sgf.name gf) name
+          (sgf.method-combination gf) method-combination
+          (sgf.methods gf) nil
+          (sgf.method-class gf) method-class
+          (sgf.decls gf) declarations
+          (sgf.%lambda-list gf) :unspecified
+	  (sgf.dependents gf) nil)
+    (when ll-p
+      (if apo-p
+        (set-gf-arg-info gf :lambda-list lambda-list
+                         :argument-precedence-order argument-precedence-order)
+        (set-gf-arg-info gf :lambda-list lambda-list)))
+    gf))
+
+(defun gf-arg-info-valid-p (gf)
+  (let* ((bits (lfun-bits gf)))
+    (declare (fixnum bits))
+    (not (and (logbitp $lfbits-aok-bit bits)
+	      (not (logbitp $lfbits-keys-bit bits))))))
+
+;;; Derive a GF lambda list from the method's lambda list.
+(defun flatten-method-lambda-list (lambda-list)
+  (collect ((ll))
+    (dolist (x lambda-list (ll))
+      (if (atom x)
+        (if (eq x '&aux)
+          (return (ll))
+          (ll x))
+        (ll (car x))))))
+          
+(defun %maybe-compute-gf-lambda-list (gf method)
+  (let* ((gf-ll (sgf.%lambda-list gf)))
+    (if (eq gf-ll :unspecified)
+      (and method
+           (let* ((method-lambda-list (%method-lambda-list method))
+                  (method-has-&key (member '&key method-lambda-list))
+                  (method-has-&allow-other-keys
+                   (member '&allow-other-keys method-lambda-list)))
+             (if method-has-&key
+               (nconc (ldiff method-lambda-list (cdr method-has-&key))
+                      (if method-has-&allow-other-keys
+                        '(&allow-other-keys)))
+               (flatten-method-lambda-list method-lambda-list))))
+      gf-ll)))
+             
+             
+;;; Borrowed from PCL, sort of.  We can encode required/optional/restp/keyp
+;;; information in the gf's lfun-bits
+(defun set-gf-arg-info (gf &key new-method (lambda-list nil lambda-list-p)
+                           (argument-precedence-order nil apo-p))
+  (let* ((methods (%gf-methods gf))
+         (dt (%gf-dispatch-table gf))
+         (gf-lfun-bits (lfun-bits gf))
+         (first-method-p (and new-method (null methods))))
+    (declare (fixnum gf-lfun-bits))
+    (unless lambda-list-p
+      (setq lambda-list
+            (%maybe-compute-gf-lambda-list gf (or (car (last methods))
+                                                  new-method))))
+    (when (or lambda-list-p
+              (and first-method-p
+                   (eq (%gf-%lambda-list gf) :unspecified)))
+      (multiple-value-bind (newbits keyvect)
+          (encode-lambda-list lambda-list t)
+        (declare (fixnum newbits))
+        (when (and methods (not first-method-p))
+          (unless (and (= (ldb $lfbits-numreq gf-lfun-bits)
+                          (ldb $lfbits-numreq newbits))
+                       (= (ldb $lfbits-numopt gf-lfun-bits)
+                          (ldb $lfbits-numopt newbits))
+                       (eq (or (logbitp $lfbits-keys-bit gf-lfun-bits)
+                               (logbitp $lfbits-rest-bit gf-lfun-bits)
+                               (logbitp $lfbits-restv-bit gf-lfun-bits))
+                           (or (logbitp $lfbits-keys-bit newbits)
+                               (logbitp $lfbits-rest-bit newbits)
+                               (logbitp $lfbits-restv-bit newbits))))
+            (cerror (format nil
+                            "Remove ~d method~:p from the generic-function and ~
+                             change its lambda list."
+                            (length (%gf-methods gf)))
+                    "New lambda list of generic function ~s is not congruent ~
+                     with lambda lists of existing methods.~%~
+                     Generic-function's   : ~s~%~
+                     Method's lambda-list : ~s~%"
+                    gf lambda-list (%method-lambda-list (car methods)))
+            (loop
+               (let ((methods (%gf-methods gf)))
+                 (if methods
+                     (remove-method gf (car methods))
+                     (return))))
+            (%set-defgeneric-keys gf nil)))
+        (when lambda-list-p
+          (setf (%gf-%lambda-list gf) lambda-list
+                (%gf-dispatch-table-keyvect dt) keyvect))
+        (when (and apo-p lambda-list-p)
+          (let* ((old-precedence-list (%gf-dispatch-table-precedence-list dt)))
+            (setf (%gf-dispatch-table-precedence-list dt)
+                  (canonicalize-argument-precedence-order
+                   argument-precedence-order
+                   (required-lambda-list-args lambda-list)))
+            (unless (equal old-precedence-list
+                           (%gf-dispatch-table-precedence-list dt))
+              (clear-gf-dispatch-table dt))))
+        (lfun-bits gf (logior (ash 1 $lfbits-gfn-bit)
+                              (logand $lfbits-args-mask newbits)))))
+    (when new-method
+      (check-defmethod-congruency gf new-method))))
+        
+(defun %gf-name (gf &optional (new-name nil new-name-p))
+  (let* ((old-name (%standard-generic-function-instance-location-access
+                    gf sgf.name)))
+    (if new-name-p
+      (setf (sgf.name gf) new-name))
+    (unless (eq old-name (%slot-unbound-marker))
+      old-name)))
+
+
+
+	     
+(defun make-n+1th-arg-combined-method (methods gf argnum)
+  (let ((table (make-gf-dispatch-table)))
+    (setf (%gf-dispatch-table-methods table) methods
+          (%gf-dispatch-table-argnum table) (%i+ 1 argnum))
+    (let ((self (%cons-combined-method gf table #'%%nth-arg-dcode))) ; <<
+      (setf (%gf-dispatch-table-gf table) self)
+      self)))
+
+;;; Bring the generic function to the smallest possible size by removing
+;;; any cached recomputable info.  Currently this means clearing out the
+;;; combined methods from the dispatch table.
+
+(defun clear-gf-cache (gf)
+  #-bccl (unless t (typep gf 'standard-generic-function) 
+           (report-bad-arg gf 'standard-generic-function))
+  (let ((dt (%gf-dispatch-table gf)))
+    (if (eq (%gf-dispatch-table-size dt) *min-gf-dispatch-table-size*)
+      (clear-gf-dispatch-table dt)
+      (let ((new (make-gf-dispatch-table)))
+        (setf (%gf-dispatch-table-methods new) (%gf-dispatch-table-methods dt))
+        (setf (%gf-dispatch-table-precedence-list new)
+              (%gf-dispatch-table-precedence-list dt))
+        (setf (%gf-dispatch-table-gf new) gf)
+        (setf (%gf-dispatch-table-keyvect new)
+              (%gf-dispatch-table-keyvect dt))
+        (setf (%gf-dispatch-table-argnum new) (%gf-dispatch-table-argnum dt))
+        (setf (%gf-dispatch-table gf) new)))))
+
+(defun %gf-dispatch-table-store-conditional (dt index new)
+  "Returns T if the new value can be stored in DT at INDEX, replacing a NIL.
+   Returns NIL - without storing anything - if the value already in DT
+   at INDEX is non-NIL at the time of the store."
+  (let ((offset (+ (ash (%i+ index %gf-dispatch-table-first-data)
+                        target::word-shift)
+                   target::misc-data-offset)))
+    (or (%store-node-conditional offset dt nil new)
+        (%store-node-conditional offset dt *gf-dispatch-bug* new))))
+
+(defun grow-gf-dispatch-table (gf-or-cm wrapper table-entry &optional obsolete-wrappers-p)
+  ;; Grow the table associated with gf and insert table-entry as the value for
+  ;; wrapper.  Wrapper is a class-wrapper.  Assumes that it is not obsolete.
+  (let* ((dt (if (generic-function-p gf-or-cm)
+               (%gf-dispatch-table gf-or-cm)
+               (%combined-method-methods gf-or-cm)))
+         (size (%gf-dispatch-table-size dt))
+         (new-size (if obsolete-wrappers-p
+                     size
+                     (%i+ size size)))
+         new-dt)
+    (if (> new-size *max-gf-dispatch-table-size*)
+      (progn 
+        (setq new-dt (clear-gf-dispatch-table dt)
+                   *gf-dt-ovf-cnt* (%i+ *gf-dt-ovf-cnt* 1)))
+      (progn
+        (setq new-dt (make-gf-dispatch-table new-size))
+        (setf (%gf-dispatch-table-methods new-dt) (%gf-dispatch-table-methods dt)
+              (%gf-dispatch-table-precedence-list new-dt) (%gf-dispatch-table-precedence-list dt)
+              (%gf-dispatch-table-keyvect new-dt) (%gf-dispatch-table-keyvect dt)
+              (%gf-dispatch-table-gf new-dt) gf-or-cm
+              (%gf-dispatch-table-argnum new-dt) (%gf-dispatch-table-argnum dt))
+        (let ((i 0) index w cm)
+          (dotimes (j (%ilsr 1 (%gf-dispatch-table-size dt)))
+	    (declare (fixnum j))
+            (unless (or (null (setq w (%gf-dispatch-table-ref dt i)))
+                        (eql 0 (%wrapper-hash-index w))
+                        (no-applicable-method-cm-p
+                         (setq cm (%gf-dispatch-table-ref dt (%i+ i 1)))))
+              (setq index (find-gf-dispatch-table-index new-dt w t))
+              (setf (%gf-dispatch-table-ref new-dt index) w)
+              (setf (%gf-dispatch-table-ref new-dt (%i+ index 1)) cm))
+            (setq i (%i+ i 2))))))
+    (let ((index (find-gf-dispatch-table-index new-dt wrapper t)))
+      (setf (%gf-dispatch-table-ref new-dt index) wrapper)
+      (setf (%gf-dispatch-table-ref new-dt (%i+ index 1)) table-entry))
+    (if (generic-function-p gf-or-cm)
+      (setf (%gf-dispatch-table gf-or-cm) new-dt)
+      (setf (%combined-method-methods gf-or-cm) new-dt))))
+
+
+(defun inner-lfun-bits (function &optional value)
+  (lfun-bits (closure-function function) value))
+
+
+
+;;; probably want to use alists vs. hash-tables initially
+
+
+;;; only used if error - well not really
+(defun collect-lexpr-args (args first &optional last) 
+  (if (listp args)
+    (subseq args first (or last (length args)))
+    (let ((res nil))
+      (when (not last)(setq last (%lexpr-count args)))
+      (dotimes (i (- last first))
+        (setq res (push (%lexpr-ref args last (+ first i)) res)))
+      (nreverse res))))
+
+
+
+
+(defmacro with-list-from-lexpr ((list lexpr) &body body)
+  (let ((len (gensym)))
+    `(let* ((,len (%lexpr-count ,lexpr))
+            (,list  (make-list ,len)))
+       (declare (dynamic-extent ,list) (fixnum ,len))       
+       (do* ((i 0 (1+ i))
+             (ls ,list (cdr ls)))
+            ((= i ,len) ,list)
+         (declare (fixnum i) (list ls))
+         (declare (optimize (speed 3)(safety 0)))
+         (%rplaca ls (%lexpr-ref ,lexpr ,len i)))
+       ,@body)))
+
+
+
+(defmacro %standard-instance-p (i)
+  `(eq (typecode ,i) ,(type-keyword-code :instance)))
+
+
+
+(declaim (inline %find-1st-arg-combined-method))
+(declaim (inline %find-nth-arg-combined-method))
+
+
+
+
+(defun %find-1st-arg-combined-method (dt arg)
+  (let ((wrapper (instance-class-wrapper arg)))
+    (when (eql 0 (%wrapper-hash-index wrapper))
+      (update-obsolete-instance arg)
+      (setq wrapper (instance-class-wrapper arg)))
+    (let* ((mask (%gf-dispatch-table-mask dt))
+           (index (%ilsl 1 (%ilogand mask (%wrapper-hash-index wrapper))))
+           table-wrapper flag)
+      (declare (fixnum index mask))
+      (loop 
+        (if (eq (setq table-wrapper (%gf-dispatch-table-ref dt index)) wrapper)
+          (return (%gf-dispatch-table-ref dt  (the fixnum (1+ index))))
+          (progn
+            (when (null (%gf-dispatch-table-ref dt (the fixnum (1+ index))))
+              (if (or (neq table-wrapper (%unbound-marker))
+                      (eql 0 flag))
+                (without-interrupts     ; why?
+                 (return (1st-arg-combined-method-trap (%gf-dispatch-table-gf dt) wrapper arg))) ; the only difference?
+                (setq flag 0 index -2)))
+            (setq index (+ 2 index))))))))
+
+;;; for calls from outside - e.g. stream-reader
+(defun find-1st-arg-combined-method (gf arg)
+  (declare (optimize (speed 3)(safety 0)))
+  (%find-1st-arg-combined-method (%gf-dispatch-table gf) arg))
+
+
+;;; more PC - it it possible one needs to go round more than once? -
+;;; seems unlikely
+(defun %find-nth-arg-combined-method (dt arg args)  
+  (declare (optimize (speed 3)(safety 0)))
+  (let ((wrapper (instance-class-wrapper arg)))
+    (when (eql 0 (%wrapper-hash-index wrapper))
+      (update-obsolete-instance arg)
+      (setq wrapper (instance-class-wrapper arg)))
+    (let* ((mask (%gf-dispatch-table-mask dt))
+           (index (%ilsl 1 (%ilogand mask (%wrapper-hash-index wrapper))))
+           table-wrapper flag)
+      (declare (fixnum index mask))
+      (loop 
+        (if (eq (setq table-wrapper (%gf-dispatch-table-ref dt index)) wrapper)
+          (return (%gf-dispatch-table-ref dt (the fixnum (1+ index))))
+          (progn
+            (when (null (%gf-dispatch-table-ref dt (the fixnum (1+ index))))
+              (if (or (neq table-wrapper (%unbound-marker))
+                      (eql 0 flag))
+                (without-interrupts     ; why?
+                 (let ((gf (%gf-dispatch-table-gf dt)))
+                   (if (listp args)
+                     (return (nth-arg-combined-method-trap-0 gf dt wrapper args))
+                     (with-list-from-lexpr (args-list args)
+                       (return (nth-arg-combined-method-trap-0 gf dt wrapper args-list))))))
+                (setq flag 0 index -2)))
+            (setq index (+ 2 index))))))))
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;; Generic functions and methods ;;;;;;;;;;;;;;;;;;;;
+(defun %class-cpl (class)
+  (if (%standard-instance-p class)
+    (%class.cpl class)
+    (or
+     (and (typep class 'macptr)
+	  (let* ((slots (foreign-slots-vector class)))
+	    (and slots (%slot-ref slots %class.cpl))))
+     (error "Can't determine CPL of class ~s" class))))
+
+
+(defun standard-method-p (thing)
+  (when (%standard-instance-p thing)
+    (let* ((cpl (%class-cpl (%wrapper-class (instance.class-wrapper thing))))
+           (smc *standard-method-class*))
+      (dolist (c cpl)
+        (if (eq c smc)(return t))))))
+
+
+
+(defun %method-function-p (thing)
+  (when (functionp thing)
+    (let ((bits (lfun-bits thing)))
+      (declare (fixnum bits))
+      (logbitp $lfbits-method-bit bits))))
+
+
+
+
+(setf (type-predicate 'standard-generic-function) 'standard-generic-function-p)
+(setf (type-predicate 'combined-method) 'combined-method-p)
+
+(setf (type-predicate 'standard-method) 'standard-method-p)
+
+;; Maybe we shouldn't make this a real type...
+(setf (type-predicate 'method-function) '%method-function-p)
+
+
+(defvar %all-gfs% (%cons-population nil))
+
+
+(eval-when (:compile-toplevel :execute)
+(defconstant $lfbits-numinh-mask (logior (dpb -1 $lfbits-numinh 0)
+                                         (%ilsl $lfbits-nonnullenv-bit 1)))
+)
+
+
+#+ppc-target
+(defvar *fi-trampoline-code* (uvref #'funcallable-trampoline 0))
+
+
+#+ppc-target
+(defvar *unset-fin-code* (uvref #'unset-fin-trampoline 0))
+
+
+
+#+ppc-target
+(defvar *gf-proto-code* (uvref *gf-proto* 0))
+
+;;; The "early" version of %ALLOCATE-GF-INSTANCE.
+(setf (fdefinition '%allocate-gf-instance)
+      #'(lambda (class)
+	  (declare (ignorable class))
+	  (setq class *standard-generic-function-class*)
+	  (let* ((wrapper (%class.own-wrapper class))
+		 (len (length #.(%wrapper-instance-slots (class-own-wrapper
+							  *standard-generic-function-class*))))
+		 (dt (make-gf-dispatch-table))
+		 (slots (allocate-typed-vector :slot-vector (1+ len) (%slot-unbound-marker)))
+		 (fn #+ppc-target
+                   (gvector :function
+			      *gf-proto-code*
+			      wrapper
+			      slots
+			      dt
+			      #'%%0-arg-dcode
+			      0
+			      (%ilogior (%ilsl $lfbits-gfn-bit 1)
+					(%ilogand $lfbits-args-mask 0)))
+                   #+x86-target
+                   (%clone-x86-function *gf-proto*
+                                        wrapper
+                                        slots
+                                        dt
+                                        #'%%0-arg-dcode
+                                        0
+                                        (%ilogior (%ilsl $lfbits-gfn-bit 1)
+                                                  (%ilogand $lfbits-args-mask 0)))))
+	    (setf ;(gf.hash fn) (strip-tag-to-fixnum fn)
+		  (slot-vector.instance slots) fn
+		  (%gf-dispatch-table-gf dt) fn)
+	    (push fn (population.data %all-gfs%))
+	    fn)))
+
+
+
+
+
+
+  
+
+
+(defparameter *gf-proto-one-arg*  #'gag-one-arg)
+(defparameter *gf-proto-two-arg*  #'gag-two-arg)
+
+
+
+
+#+ppc-target
+(defvar *cm-proto-code* (uvref *cm-proto* 0))
+
+(defun %cons-combined-method (gf thing dcode)
+  ;; set bits and name = gf
+  #+ppc-target
+  (gvector :function
+           *cm-proto-code*
+           thing
+           dcode
+           gf
+           (%ilogior (%ilsl $lfbits-cm-bit 1)
+                            (%ilogand $lfbits-args-mask (lfun-bits gf))))
+  #+x86-target
+  (%clone-x86-function *cm-proto*
+                       thing
+                       dcode
+                       gf
+                       (%ilogior (%ilsl $lfbits-cm-bit 1)
+                                 (%ilogand $lfbits-args-mask (lfun-bits gf)))))
+
+(defun %gf-dispatch-table (gf)
+  ;(require-type gf 'standard-generic-function)
+  (gf.dispatch-table gf))
+
+(defun %gf-dcode (gf)
+  ;(require-type gf 'standard-generic-function)
+  (gf.dcode gf))
+
+(defun %set-gf-dcode (gf dcode)
+  (let ((gf (require-type gf 'funcallable-standard-object))
+        (dcode (require-type dcode 'function)))
+    (replace-function-code gf (or (cdr (assq dcode dcode-proto-alist))
+                                  #'funcallable-trampoline))
+    (setf (gf.dcode gf) dcode)))
+
+(defun %set-gf-dispatch-table (gf val)
+  (setf (gf.dispatch-table gf) val))
+
+(defun %combined-method-methods  (cm)
+  ;(require-type cm 'combined-method)
+  (combined-method.thing cm))
+
+(defun %combined-method-dcode (cm)
+  ;(require-type cm 'combined-method)
+  (combined-method.dcode cm))
+
+(defun %set-combined-method-methods (cm val)
+  (setf (combined-method.thing cm) val))
+
+(defun %set-combined-method-dcode (cm val)
+  (setf (combined-method.dcode cm) val))
+
+(declaim (inline funcallable-instance-p))
+(defun funcallable-instance-p (thing)
+  (when (typep thing 'function)
+    (let ((bits (lfun-bits-known-function thing)))
+      (declare (fixnum bits))
+      (eq (ash 1 $lfbits-gfn-bit)
+	  (logand bits (logior (ash 1 $lfbits-gfn-bit)
+			       (ash 1 $lfbits-method-bit)))))))
+
+(setf (type-predicate 'funcallable-standard-object) 'funcallable-instance-p)
+
+(defstatic *generic-function-class-wrapper* nil)
+(defstatic *standard-generic-function-class-wrapper* nil)
+
+(defun generic-function-p (thing)
+  (and (typep thing 'funcallable-standard-object)
+       (let* ((wrapper (gf.instance.class-wrapper thing)))
+         ;; In practice, many generic-functions are standard-generic-functions.
+         (or (eq *standard-generic-function-class-wrapper* wrapper)
+             (eq *generic-function-class-wrapper* wrapper)
+             (let* ((bits (or (%wrapper-cpl-bits wrapper)
+                              (make-cpl-bits (%inited-class-cpl (%wrapper-class wrapper)))))
+                    (ordinal (%wrapper-class-ordinal *generic-function-class-wrapper*)))
+               (and bits ordinal
+                    (locally (declare (simple-bit-vector bits)
+                                      (fixnum ordinal)
+                                      (optimize (speed 3) (safety 0)))
+                      (and (< ordinal (length bits))
+                           (eql 1 (sbit bits ordinal))))))))))
+
+
+(defun standard-generic-function-p (thing)
+  (and (typep thing 'function)
+       (let ((bits (lfun-bits-known-function thing)))
+	 (declare (fixnum bits))
+	 (eq (ash 1 $lfbits-gfn-bit)
+	     (logand bits (logior (ash 1 $lfbits-gfn-bit)
+				  (ash 1 $lfbits-method-bit)))))
+       (or (eq (%class.own-wrapper *standard-generic-function-class*)
+	       (gf.instance.class-wrapper thing))
+	   (memq  *standard-generic-function-class*
+		  (%inited-class-cpl (class-of thing))))))
+
+
+(defun combined-method-p (thing)
+  (when (functionp thing)
+    (let ((bits (lfun-bits-known-function thing)))
+      (declare (fixnum bits))
+      (eq (ash 1 $lfbits-cm-bit)
+	  (logand bits
+		  (logior (ash 1 $lfbits-cm-bit)
+			  (ash 1 $lfbits-method-bit)))))))
+
+(setf (type-predicate 'generic-function) 'generic-function-p)
+
+(setf (type-predicate 'standard-generic-function) 'standard-generic-function-p)
+(setf (type-predicate 'funcallable-standard-object) 'funcallable-instance-p)
+(setf (type-predicate 'combined-method) 'combined-method-p)
+
+
+
+;;; A generic-function looks like:
+;;; 
+;;; header | trampoline |  dispatch-table | dcode | name | bits
+;;; %svref :    0              1              2       3      4
+;;;
+;;; The trampoline is *gf-proto*'s code vector.
+;;; The dispatch-table and dcode are sort of settable closed-over variables.
+
+(defsetf %gf-dispatch-table %set-gf-dispatch-table)
+
+(defun %gf-methods (gf)
+  (sgf.methods gf))
+
+(defun %gf-precedence-list (gf)
+  (%gf-dispatch-table-precedence-list (%gf-dispatch-table gf)))
+
+(defun %gf-%lambda-list (gf)
+  (sgf.%lambda-list gf))
+
+(defun (setf %gf-%lambda-list) (new gf)
+  (setf (sgf.%lambda-list gf) new))
+
+;;; Returns INSTANCE if it is either a standard instance of a
+;;; standard gf, else nil.
+(defun %maybe-gf-instance (instance)
+  (if (or (standard-generic-function-p instance)
+	  (%standard-instance-p instance))
+    instance))
+
+(defsetf %gf-dcode %set-gf-dcode)
+
+(defun %gf-method-class (gf)
+  (sgf.method-class gf))
+
+
+(defun %gf-method-combination (gf)
+  (sgf.method-combination gf))
+
+; need setters too
+
+(defsetf %combined-method-methods %set-combined-method-methods)
+
+(defparameter *min-gf-dispatch-table-size* 2
+  "The minimum size of a generic-function dispatch table")
+
+(defun make-gf-dispatch-table (&optional (size *min-gf-dispatch-table-size*))
+  (when (<= size 0) (report-bad-arg size '(integer 1)))
+  (setq size (%imax (%ilsl (%i- (integer-length (%i+ size size -1))
+                                1)
+                           1)           ; next power of 2
+                    *min-gf-dispatch-table-size*))
+  (let ((res (%cons-gf-dispatch-table size)))
+    (declare (optimize (speed 3) (safety 0)))
+    (setf (%gf-dispatch-table-mask res) (%i- (%ilsr 1 size) 1)
+          (%gf-dispatch-table-argnum res) 0
+          (%gf-dispatch-table-ref res size) (%unbound-marker))
+    res))
+
+;;; I wanted this to be faster - I didn't
+(defun clear-gf-dispatch-table (dt)
+  (let ((i %gf-dispatch-table-first-data))
+    (dotimes (j (%gf-dispatch-table-size dt))
+      (declare (fixnum j))
+      (setf (%svref dt i) nil 
+            i (%i+ i 1)))
+    (setf (%svref dt i) (%unbound-marker)) ; paranoia...
+    (setf (svref dt (%i+ 1 i)) nil))
+  dt)
+
+
+; Remove all combined-methods from the world
+(defun clear-all-gf-caches ()
+  (dolist (f (population-data %all-gfs%))
+    (clear-gf-cache f))
+  (clrhash *combined-methods*)
+  nil)
+
+
+;;; Searches for an empty slot in dt at the hash-index for wrapper.
+;;; Returns nil if the table was full.
+(defun find-gf-dispatch-table-index (dt wrapper &optional skip-full-check?)
+  (let ((contains-obsolete-wrappers-p nil)
+        (mask (%gf-dispatch-table-mask dt)))
+    (declare (fixnum mask))
+    (unless skip-full-check?
+      (let* ((size (1+ mask))
+             (max-count (- size (the fixnum (ash (the fixnum (+ size 3)) -2))))
+             (index 0)
+             (count 0))
+        (declare (fixnum size max-count index count))
+        (dotimes (i size)
+          (declare (fixnum i))
+          (let ((wrapper (%gf-dispatch-table-ref dt index)))
+            (if wrapper
+              (if (eql 0 (%wrapper-hash-index wrapper))
+                (setf contains-obsolete-wrappers-p t
+                      (%gf-dispatch-table-ref dt index) *obsolete-wrapper*
+                      (%gf-dispatch-table-ref dt (1+ index)) *gf-dispatch-bug*)
+                (setq count (%i+ count 1)))))
+          (setq index (%i+ index 2)))
+        (when (> count max-count)
+          (return-from find-gf-dispatch-table-index (values nil contains-obsolete-wrappers-p)))))
+    (let* ((index (ash (logand mask (%wrapper-hash-index wrapper)) 1))
+           (flag nil)
+           table-wrapper)      
+      (values
+       (loop
+         (while (and (neq wrapper
+                          (setq table-wrapper (%gf-dispatch-table-ref dt index)))
+                     (%gf-dispatch-table-ref dt (1+ index))
+                     (neq 0 (%wrapper-hash-index table-wrapper)))
+           (setq index (%i+ index 2)))
+         (if (eq (%unbound-marker) table-wrapper)
+           (if flag
+             (return nil)         ; table full
+             (setq flag 1
+                   index 0))
+           (return index)))
+       contains-obsolete-wrappers-p))))
+
+
+(defvar *obsolete-wrapper* #(obsolete-wrapper 0))
+(defvar *gf-dispatch-bug*
+  #'(lambda (&rest rest)
+      (declare (ignore rest))
+      (error "Generic-function dispatch bug!")))
+
+  
+;;; This maximum is necessary because of the 32 bit arithmetic in
+;;; find-gf-dispatch-table-index.
+(defparameter *max-gf-dispatch-table-size* (expt 2 16))
+(defvar *gf-dt-ovf-cnt* 0)              ; overflow count
+
+(defvar *no-applicable-method-hash* nil)
+
+
+(let* ((eql-specializers-lock (make-lock))
+       (eql-specializers-hash (make-hash-table :test #'eql)))
+  (defun intern-eql-specializer (object)
+    (with-lock-grabbed (eql-specializers-lock)
+      (or (gethash object eql-specializers-hash)
+	  (setf (gethash object eql-specializers-hash)
+		(make-instance 'eql-specializer :object object))))))
+
+
+(setq *no-applicable-method-hash* (make-hash-table :test 'eq :size 0 :weak :key))
+
+
+(defun make-no-applicable-method-function (gf)
+  (if *no-applicable-method-hash*
+    (progn
+      (or (gethash gf *no-applicable-method-hash*))
+      (setf (gethash gf *no-applicable-method-hash*)
+            (%cons-no-applicable-method gf)))
+    (%cons-no-applicable-method gf)))
+
+(defun %cons-no-applicable-method (gf)
+  (%cons-combined-method gf gf #'%%no-applicable-method))
+
+; Returns true if F is a combined-method that calls no-applicable-method
+(defun no-applicable-method-cm-p (f)
+  (and (typep f 'combined-method)
+       (eq '%%no-applicable-method
+           (function-name (%combined-method-dcode f)))))
+
+
+(defun %%no-applicable-method (gf args)
+  (if (listp args)
+    (apply #'no-applicable-method gf args)
+    (%apply-lexpr #'no-applicable-method gf args )))
+
+;;; if obsolete-wrappers-p is true, will rehash instead of grow.
+;;; It would be better to do the rehash in place, but I'm lazy today.
+
+
+(defun arg-wrapper (arg)
+  (or (standard-object-p arg)
+      (%class.own-wrapper (class-of arg))
+      (error "~a has no wrapper" arg)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;; generic-function dcode ;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; dcode functions using other than *gf-proto*
+(defparameter dcode-proto-alist ())
+
+(defun register-dcode-proto (dcode proto)
+  (let ((a (assoc dcode dcode-proto-alist)))
+    (if a
+      (setf (cdr a) proto)
+      (push (cons dcode proto) dcode-proto-alist))))
+
+
+;;; Simple case for generic-functions with no specializers
+;;; Why anyone would want to do this I can't imagine.
+
+(defun %%0-arg-dcode (dispatch-table args) ; need to get gf from table
+  (let ((method (or (%gf-dispatch-table-ref dispatch-table 1)
+                    (0-arg-combined-method-trap
+                     (%gf-dispatch-table-gf dispatch-table)))))
+    (if (not (listp args))
+      (progn
+        (%apply-lexpr-tail-wise method args))
+      (apply method args))))
+
+(register-dcode-proto #'%%0-arg-dcode *gf-proto*)
+
+(defun dcode-too-few-args (arg-count cm-or-gf)
+  (error (make-condition 'too-few-arguments
+                         :nargs arg-count
+                         :fn (combined-method-gf cm-or-gf))))
+
+
+
+(defun %%1st-arg-dcode (dt  args)
+  ;(declare (dynamic-extent args))
+  (if (not (listp args))
+    (let* ((args-len (%lexpr-count args)))
+      (if (neq 0 args-len) 
+        (let ((method (%find-1st-arg-combined-method dt (%lexpr-ref args args-len 0))))
+	  (%apply-lexpr-tail-wise method args))
+        (dcode-too-few-args 0 (%gf-dispatch-table-gf dt))))
+    (let* ()  ; happens if traced
+      (when (null args) (dcode-too-few-args 0 (%gf-dispatch-table-gf dt)))
+      (let ((method (%find-1st-arg-combined-method dt (%car args))))
+        (apply method args)))))
+(register-dcode-proto #'%%1st-arg-dcode *gf-proto*)
+
+(defun %%one-arg-dcode (dt  arg)
+  (let ((method (%find-1st-arg-combined-method dt arg)))
+    (funcall method arg)))
+(register-dcode-proto #'%%one-arg-dcode *gf-proto-one-arg*)
+
+;;; two args - specialized on first
+(defun %%1st-two-arg-dcode (dt arg1 arg2)
+  (let ((method (%find-1st-arg-combined-method dt arg1)))
+    (funcall method arg1 arg2)))
+(register-dcode-proto #'%%1st-two-arg-dcode *gf-proto-two-arg*)
+
+
+;;;  arg is dispatch-table and argnum is in the dispatch table
+(defun %%nth-arg-dcode (dt args)
+  (if (listp args)
+    (let* ((args-len (list-length args))
+           (argnum (%gf-dispatch-table-argnum dt)))
+      (declare (fixnum args-len argnum))
+      (when (>= argnum args-len) (dcode-too-few-args args-len (%gf-dispatch-table-gf dt)))
+      (let ((method (%find-nth-arg-combined-method dt (nth argnum args) args)))
+        (apply method args)))
+    (let* ((args-len (%lexpr-count args))
+           (argnum (%gf-dispatch-table-argnum dt)))
+      (declare (fixnum args-len argnum))
+      (when (>= argnum args-len) (dcode-too-few-args args-len (%gf-dispatch-table-gf dt)))
+      (let ((method (%find-nth-arg-combined-method dt (%lexpr-ref args args-len argnum) args)))
+	(%apply-lexpr-tail-wise method args)))))
+(register-dcode-proto #'%%nth-arg-dcode *gf-proto*)
+
+(defun 0-arg-combined-method-trap (gf)
+  (let* ((methods (%gf-methods gf))
+         (mc (%gf-method-combination gf))
+         (cm (if (eq mc *standard-method-combination*)
+               (make-standard-combined-method methods nil gf)
+               (compute-effective-method-function 
+                gf 
+                mc
+                (sort-methods (copy-list methods) nil)))))
+    (setf (%gf-dispatch-table-ref (%gf-dispatch-table gf) 1) cm)
+    cm))
+
+(defun compute-effective-method-function (gf mc methods)  
+  (if methods
+    (compute-effective-method gf mc methods)
+    (make-no-applicable-method-function gf)))
+
+(defun 1st-arg-combined-method-trap (gf wrapper arg)
+  ;; Here when we can't find the method in the dispatch table.
+  ;; Compute it and add it to the table.  This code will remain in Lisp.
+  (let ((table (%gf-dispatch-table gf))
+        (combined-method (compute-1st-arg-combined-method gf arg wrapper)))
+    (multiple-value-bind (index obsolete-wrappers-p)
+        (find-gf-dispatch-table-index table wrapper)
+      (if index
+          (if (%gf-dispatch-table-store-conditional table (%i+ index 1) combined-method)
+            (setf (%gf-dispatch-table-ref table index) wrapper))
+          (grow-gf-dispatch-table gf wrapper combined-method obsolete-wrappers-p)))
+    combined-method))
+
+(defvar *cpl-classes* nil)
+
+(defun %inited-class-cpl (class &optional initialize-can-fail)
+  (or (%class-cpl class)
+      (if (memq class *cpl-classes*)
+        (compute-cpl class)
+        (let ((*cpl-classes* (cons class *cpl-classes*)))
+          (declare (dynamic-extent *cpl-classes*))
+          (update-class class initialize-can-fail)
+          (%class-cpl class)))))
+
+
+(defun compute-1st-arg-combined-method (gf arg &optional 
+                                           (wrapper (arg-wrapper arg)))
+  (let* ((methods (%gf-dispatch-table-methods (%gf-dispatch-table gf)))
+         (cpl (%inited-class-cpl (%wrapper-class wrapper)))
+         (method-combination (%gf-method-combination gf))
+         applicable-methods eql-methods specializer)
+    (dolist (method methods)
+      (setq specializer (%car (%method.specializers method)))
+      (if (typep specializer 'eql-specializer)
+        (when (cpl-memq (%wrapper-class (arg-wrapper (eql-specializer-object specializer))) cpl)
+          (push method eql-methods))
+        (when (cpl-memq specializer cpl)
+          (push method applicable-methods))))
+    (if (null eql-methods)
+      (if (eq method-combination *standard-method-combination*)
+        (make-standard-combined-method applicable-methods (list cpl) gf)
+        (compute-effective-method-function 
+         gf 
+         method-combination
+         (sort-methods applicable-methods
+                       (list cpl)
+                       (%gf-precedence-list gf))))
+      (make-eql-combined-method  
+       eql-methods applicable-methods (list cpl) gf 0 nil method-combination))))
+      
+
+
+(defvar *combined-methods* (make-hash-table  :test 'equal :weak :value))                          
+
+(defun gethash-combined-method (key)
+  (gethash key *combined-methods*))
+
+(defun puthash-combined-method (key value)
+  (setf (gethash key *combined-methods*) value))
+
+;;; Some statistics on the hash table above
+(defvar *returned-combined-methods* 0)
+(defvar *consed-combined-methods* 0)
+
+;;; Assumes methods are already sorted if cpls is nil
+(defun make-standard-combined-method (methods cpls gf &optional
+                                              (ok-if-no-primaries (null methods)))
+  (unless (null cpls)
+    (setq methods (sort-methods 
+                   methods cpls (%gf-precedence-list (combined-method-gf gf)))))
+  (let* ((keywords (compute-allowable-keywords-vector gf methods))
+         (combined-method (make-standard-combined-method-internal
+                           methods gf keywords ok-if-no-primaries)))
+    (if (and keywords methods)
+      (make-keyword-checking-combined-method gf combined-method keywords)
+      combined-method)))
+
+
+;;; Initialized below after the functions exist.
+(defvar *clos-initialization-functions* nil)
+
+;;; Returns NIL if all keywords allowed, or a vector of the allowable ones.
+(defun compute-allowable-keywords-vector (gf methods)
+  (setq gf (combined-method-gf gf))
+  (unless (memq gf *clos-initialization-functions*)
+    (let* ((gbits (inner-lfun-bits gf))
+           (&key-mentioned-p (logbitp $lfbits-keys-bit gbits)))
+      (unless (or (logbitp $lfbits-aok-bit gbits)
+                  (dolist (method methods)
+                    (let ((mbits (lfun-bits (%method.function method))))
+                      (when (logbitp $lfbits-keys-bit mbits)
+                        (setq &key-mentioned-p t)
+                        (if (logbitp $lfbits-aok-bit mbits)
+                          (return t)))))
+                  (not &key-mentioned-p))
+        (let (keys)
+          (flet ((adjoin-keys (keyvect keys)
+                              (when keyvect
+                                (dovector (key keyvect) (pushnew key keys)))
+                              keys))
+            (when (logbitp $lfbits-keys-bit gbits)
+              (setq keys (adjoin-keys (%defgeneric-keys gf) keys)))
+            (dolist (method methods)
+              (let ((f (%inner-method-function method)))
+                (when (logbitp $lfbits-keys-bit (lfun-bits f))
+                  (setq keys (adjoin-keys (lfun-keyvect f) keys))))))
+          (apply #'vector keys))))))
+
+
+(defun make-keyword-checking-combined-method (gf combined-method keyvect)
+  (let* ((bits (inner-lfun-bits gf))
+         (numreq (ldb $lfbits-numreq bits))
+         (key-index (+ numreq (ldb $lfbits-numopt bits))))
+    (%cons-combined-method 
+     gf       
+     (vector key-index keyvect combined-method)
+     #'%%check-keywords)))
+
+
+
+(defun odd-keys-error (varg l) 
+  (let ((gf (combined-method-gf (%svref varg 2))))
+    (signal-program-error "Odd number of keyword args to ~s~%keyargs: ~s" gf l)))
+
+
+(defun bad-key-error (key varg l)
+  (let* ((keys (%svref varg 1))
+         (gf (combined-method-gf (%svref varg 2)))
+         (*print-array* t)
+         (*print-readably* t)
+         (readable-keys (format nil "~s" keys)))
+    (signal-program-error "Bad keyword ~s to ~s.~%keyargs: ~s~%allowable keys are ~a." key gf l readable-keys)))
+
+; vector arg is (vector key-index keyvect combined-method) ; the next combined method
+
+(defun %%check-keywords (vector-arg args)
+  (flet ((do-it (vector-arg args)
+           (let* ((args-len (length args))
+                  (keyvect (%svref vector-arg 1))
+                  (keyvect-len (length keyvect))
+                  (key-index (%svref vector-arg 0)))
+					; vector arg is (vector key-index keyvect combined-method) ; the next combined method
+             (declare (fixnum args-len key-index keyvect-len))
+             (when (>= args-len key-index)
+               (let* ((keys-in (- args-len key-index)))	; actually * 2
+                 (declare (fixnum  key-index keys-in keyvect-len))
+                 (when (logbitp 0 keys-in) (odd-keys-error vector-arg (collect-lexpr-args args key-index args-len)))
+		 (unless (%cadr (%pl-search (nthcdr key-index args) :allow-other-keys))
+		   (do ((i key-index (+ i 2))
+			(kargs (nthcdr key-index args) (cddr kargs)))
+		       ((eq i args-len))
+		     (declare (fixnum i))
+		     (let ((key (car kargs)))
+		       (when (not (or (eq key :allow-other-keys)
+				      (dotimes (i keyvect-len nil)
+					(if (eq key (%svref keyvect i))
+					  (return t)))))
+			 (bad-key-error key vector-arg (collect-lexpr-args args key-index args-len))
+			 ))))))
+             (let ((method (%svref vector-arg 2)))
+					; magic here ?? not needed
+               (apply method args)))))
+    (if (listp args)
+      (do-it vector-arg args)
+      (with-list-from-lexpr (args-list args)
+        (do-it vector-arg args-list)))))
+
+
+
+  
+
+
+;;; called from %%call-next-method-with-args - its the key-or-init-fn 
+;;; called from call-next-method-with-args - just check the blooming keys
+;;; dont invoke any methods - maybe use x%%check-keywords with last vector elt nil
+; means dont call any methods - but need the gf or method for error message
+(defun x-%%check-keywords (vector-arg ARGS)
+  ;(declare (dynamic-extent args))
+    ; vector arg is (vector key-index keyvect unused)
+  (let* ((ARGS-LEN (length args))
+         (keyvect (%svref vector-arg 1))
+         (keyvect-len (length keyvect))
+         (key-index (%svref vector-arg 0))
+         (keys-in (- args-len key-index))
+         aok)  ; actually * 2
+    (declare (fixnum args-len key-index keys-in keyvect-len))
+    
+    (when (logbitp 0 keys-in) (odd-keys-error vector-arg (collect-lexpr-args args key-index args-len)))
+    (do ((i key-index (+ i 2))
+         (kargs (nthcdr key-index args) (cddr kargs)))
+        ((eq i args-len))
+      (declare (fixnum i))
+      (when aok (return))
+      (let ((key (car kargs)))
+        (when (and (eq key :allow-other-keys)
+                   (cadr kargs))
+          (return))
+        (when (not (dotimes (i keyvect-len nil)
+                     (if (eq key (%svref keyvect i))
+                       (return t))))
+          ; not found - is :allow-other-keys t in rest of user args
+          (when (not (do ((remargs kargs (cddr remargs)))
+                         ((null remargs) nil)
+                       (when (and (eq (car remargs) :allow-other-keys)
+                                  (cadr remargs))
+                         (setq aok t)
+                         (return t))))              
+            (bad-key-error key vector-arg 
+                           (collect-lexpr-args args key-index args-len))))))))
+#| ; testing
+(setq keyvect  #(:a :b ))
+(setq foo (make-array 3))
+(setf (aref foo 0) keyvect (aref foo 1) 2)
+(setf (aref foo 2)(method window-close (window)))
+( %%check-keywords 1 2 :a 3 :c 4 foo)
+( %%check-keywords 1 2 :a 3 :b 4 :d foo)
+|#
+ 
+    
+
+
+
+;;; Map an effective-method to it's generic-function.
+;;; This is only used for effective-method's which are not combined-method's
+;;; (e.g. those created by non-STANDARD method-combination)
+(defvar *effective-method-gfs* (make-hash-table :test 'eq :weak :key))
+
+
+(defun get-combined-method (method-list gf)
+  (let ((cm (gethash-combined-method method-list)))
+    (when cm
+      (setq gf (combined-method-gf gf))
+      (if (combined-method-p cm)
+        (and (eq (combined-method-gf cm) gf) cm)
+        (and (eq (gethash cm *effective-method-gfs*) gf) cm)))))
+
+(defun put-combined-method (method-list cm gf)
+  (unless (%method-function-p cm)       ; don't bother with non-combined methods
+    (puthash-combined-method method-list cm)
+    (unless (combined-method-p cm)
+      (setf (gethash cm *effective-method-gfs*) (combined-method-gf gf))))
+  cm)
+
+(defun make-standard-combined-method-internal (methods gf &optional 
+                                                       keywords
+                                                       (ok-if-no-primaries
+                                                        (null methods)))
+  (let ((method-list (and methods (compute-method-list methods nil))))
+    (if method-list                 ; no applicable primary methods
+      (if (atom method-list)
+        (%method.function method-list)    ; can jump right to the method-function
+        (progn
+          (incf *returned-combined-methods*)  ; dont need this
+          (if (contains-call-next-method-with-args-p method-list)
+            (make-cnm-combined-method gf methods method-list keywords)
+            (or (get-combined-method method-list gf)
+                (progn
+                  (incf *consed-combined-methods*)  ; dont need this
+                  (puthash-combined-method
+                   method-list
+                   (%cons-combined-method
+                    gf method-list #'%%standard-combined-method-dcode)))))))
+      (if ok-if-no-primaries
+        (make-no-applicable-method-function (combined-method-gf gf))
+        (no-applicable-primary-method gf methods)))))
+
+; Initialized after the initialization (generic) functions exist.
+(defvar *initialization-functions-alist* nil)
+
+;;; This could be in-line above, but I was getting confused.
+
+;;; ok
+(defun make-cnm-combined-method (gf methods method-list keywords)
+  (setq gf (combined-method-gf gf))
+  (let ((key (cons methods method-list)))
+    (or (get-combined-method key gf)
+        (let* (key-or-init-arg
+               key-or-init-fn)
+          (if keywords
+            (let* ((bits (inner-lfun-bits gf))
+                   (numreq (ldb $lfbits-numreq bits))
+                   (key-index (+ numreq (ldb $lfbits-numopt bits))))
+              (setq key-or-init-arg (vector key-index keywords gf))
+              (setq key-or-init-fn #'x-%%check-keywords))
+            (let ((init-cell (assq gf *initialization-functions-alist*)))
+              (when init-cell                
+                (setq key-or-init-arg init-cell)
+                (setq key-or-init-fn #'%%cnm-with-args-check-initargs))))
+          (incf *consed-combined-methods*)
+          (let* ((vect (vector gf methods key-or-init-arg key-or-init-fn method-list))
+                 (self (%cons-combined-method
+                        gf vect #'%%cnm-with-args-combined-method-dcode)))
+            ;(setf (svref vect 4) self)
+            (puthash-combined-method ; if  testing 1 2 3 dont put in our real table
+             key
+             self))))))
+
+
+(defparameter *check-call-next-method-with-args* t)
+
+(defun contains-call-next-method-with-args-p (method-list)
+  (when *check-call-next-method-with-args*
+    (let ((methods method-list)
+          method)
+      (loop
+        (setq method (pop methods))
+        (unless methods (return nil))
+        (unless (listp method)
+          (if (logbitp $lfbits-nextmeth-with-args-bit
+                       (lfun-bits (%method.function method)))
+            (return t)))))))
+
+;;; The METHODS arg is a sorted list of applicable methods.  Returns
+;;; the method-list expected by
+;;; %%before-and-after-combined-method-dcode or a single method, or
+;;; NIL if there are no applicable primaries
+(defun compute-method-list (methods &optional (sub-dispatch? t))
+  (let (arounds befores primaries afters qs)
+    (dolist (m methods)
+      (setq qs (%method.qualifiers m))
+      (if qs
+        (if (cdr qs)
+          (%invalid-method-error
+           m "Multiple method qualifiers not allowed in ~s method combination"
+           'standard)
+          (case (car qs)
+            (:before (push m befores))
+            (:after (push m afters))
+            (:around (push m arounds))
+            (t (%invalid-method-error m "~s is not one of ~s, ~s, and ~s."
+                                      (car qs) :before :after :around))))
+        (push m primaries)))
+    (setq primaries (nreverse primaries)
+          arounds (nreverse arounds)
+          befores (nreverse befores))
+    (unless sub-dispatch?
+      (setq primaries (nremove-uncallable-next-methods primaries)
+            arounds (nremove-uncallable-next-methods arounds)))
+    (flet ((next-method-bit-p (method)
+                              (logbitp $lfbits-nextmeth-bit 
+                                       (lfun-bits (%method.function method)))))
+      (unless (null primaries)            ; return NIL if no applicable primary methods
+        (when (and arounds
+                   (not sub-dispatch?)
+                   (not (next-method-bit-p (car (last arounds)))))
+          ;; Arounds don't call-next-method, can't get to befores,
+          ;; afters, or primaries
+          (setq primaries arounds
+                arounds nil
+                befores nil
+                afters nil))
+        (if (and (null befores) (null afters)
+                 (progn
+                   (when arounds
+                     (setq primaries (nconc arounds primaries)
+                           arounds nil)
+                     (unless sub-dispatch?
+                       (setq primaries (nremove-uncallable-next-methods primaries))))
+                   t)
+                 (null (cdr primaries))
+                 (not (next-method-bit-p (car primaries))))
+          (car primaries)                 ; single method, no call-next-method
+          (let ((method-list primaries))
+            (if (or befores afters)
+              (setq method-list (cons befores (cons afters method-list))))
+            (nconc arounds method-list)))))))
+
+
+
+(defun %invalid-method-error (method format-string &rest format-args)
+  (error "~s is an invalid method.~%~?" method format-string format-args))
+
+(defun %method-combination-error (format-string &rest args)
+  (apply #'error format-string args))
+
+
+
+(defun combined-method-gf (gf-or-cm)
+  (let ((gf gf-or-cm))
+    (while (combined-method-p gf)
+      (setq gf (lfun-name gf)))
+    gf))
+
+
+(defun nth-arg-combined-method-trap-0 (gf-or-cm table wrapper args)
+  (let* ((argnum (%gf-dispatch-table-argnum table))
+         (arg (nth argnum args)))
+    (nth-arg-combined-method-trap gf-or-cm table argnum args arg wrapper)))
+
+
+(defun nth-arg-combined-method-trap (gf-or-cm table argnum args &optional
+                                              (arg (nth-or-gf-error 
+                                                    argnum args gf-or-cm))
+                                              (wrapper (arg-wrapper arg)))
+  ;; Here when we can't find the method in the dispatch table.
+  ;; Compute it and add it to the table.  This code will remain in Lisp.
+  (multiple-value-bind (combined-method sub-dispatch?)
+      (compute-nth-arg-combined-method
+       gf-or-cm (%gf-dispatch-table-methods table) argnum args
+       wrapper)
+    (multiple-value-bind (index obsolete-wrappers-p)
+        (find-gf-dispatch-table-index table wrapper)
+      (if index
+        (if (%gf-dispatch-table-store-conditional table (%i+ index 1) combined-method)
+          (setf (%gf-dispatch-table-ref table index) wrapper))
+        (grow-gf-dispatch-table gf-or-cm wrapper combined-method obsolete-wrappers-p)))
+    (if sub-dispatch?
+      (let ((table (%combined-method-methods combined-method)))
+        (nth-arg-combined-method-trap
+         combined-method
+         table
+         (%gf-dispatch-table-argnum table)
+         args))
+      combined-method)))
+
+;;; Returns (values combined-method sub-dispatch?)
+;;; If sub-dispatch? is true, need to compute a combined-method on the
+;;; next arg.
+(defun compute-nth-arg-combined-method (gf methods argnum args &optional 
+                                           (wrapper (arg-wrapper
+                                                     (nth-or-gf-error
+                                                      argnum args gf))))
+  (let* ((cpl (%inited-class-cpl (%wrapper-class wrapper)))
+         (real-gf (combined-method-gf gf))
+         (mc (%gf-method-combination real-gf))
+         (standard-mc? (eq mc *standard-method-combination*))
+         applicable-methods eql-methods specializers specializer sub-dispatch?)
+    (dolist (method methods)
+      ;;(require-type method 'standard-method)   ; for debugging.
+      (setq specializers (nthcdr argnum (%method.specializers method))
+            specializer (%car specializers))
+      (when (if (typep specializer 'eql-specializer)
+              (when (cpl-memq (%wrapper-class
+                                (arg-wrapper (eql-specializer-object specializer))) cpl)
+                (push method eql-methods))
+              (when (cpl-memq specializer cpl)
+                (push method applicable-methods)))
+        (if (contains-non-t-specializer? (%cdr specializers))
+          (setq sub-dispatch? t))))
+    (if (or eql-methods applicable-methods)
+      (if (or (not standard-mc?)
+            (contains-primary-method? applicable-methods)
+            (contains-primary-method? eql-methods))
+        (let ((cpls (args-cpls args)))
+          (if eql-methods
+            (make-eql-combined-method
+             eql-methods applicable-methods cpls gf argnum sub-dispatch? mc)
+            (if sub-dispatch?
+              (values (make-n+1th-arg-combined-method applicable-methods gf argnum)
+                      t)
+              (if standard-mc?
+                (make-standard-combined-method applicable-methods cpls gf)
+                (compute-effective-method-function
+                 real-gf mc (sort-methods applicable-methods
+                                          (args-cpls args)
+                                          (%gf-precedence-list real-gf)))))))
+        (no-applicable-primary-method
+         real-gf
+         (sort-methods (append eql-methods applicable-methods)
+                       (args-cpls args)
+                       (%gf-precedence-list real-gf))))
+       (make-no-applicable-method-function real-gf))))
+
+(defun nth-or-gf-error (n l gf)
+  (declare (fixnum n))
+  (do* ((i 0 (1+ i))
+        (l l (cdr l)))
+       ((null l) (dcode-too-few-args i gf))
+    (declare (fixnum i))
+    (if (= i n)
+      (return (car l)))))
+
+(defun contains-non-t-specializer? (specializer-list)
+  (dolist (s specializer-list nil)
+    (unless (eq *t-class* s)
+      (return t))))
+
+(defun contains-primary-method? (method-list)
+  (dolist (m method-list nil)
+    (if (null (%method.qualifiers m))
+      (return t))))
+
+(defun args-cpls (args &aux res)
+  (dolist (arg args)
+    (push (%inited-class-cpl (%wrapper-class (arg-wrapper arg))) res))
+  (nreverse res))
+
+
+(defun compute-eql-combined-method-hash-table-threshold (&optional (iters 1000000) (max 200))
+  (flet ((time-assq (cnt iters)
+           (let ((alist (loop for i from 1 to cnt collect (cons i i)))
+                 (start-time (get-internal-run-time))
+                 (j 0)
+                 res)
+             (declare (fixnum j))
+             (dotimes (i iters)
+               (declare (fixnum i))
+               (setq res (cdr (assq j alist)))
+               (when (>= (incf j) cnt) (setq j 0)))
+             (values (- (get-internal-run-time) start-time) res)))
+         (time-hash (cnt iters)
+           (let ((hash (make-hash-table :test 'eq))
+                 start-time
+                 (j 0)
+                 res)
+             (declare (fixnum j))
+             (dotimes (i cnt)
+               (setf (gethash i hash) i))
+             (assert-hash-table-readonly hash)
+             (setq start-time (get-internal-run-time))
+             (dotimes (i iters)
+               (declare (fixnum i))
+               (setq res (gethash i hash))
+               (when (>= (incf j) cnt) (setq j 0)))
+             (values (- (get-internal-run-time) start-time) res))))
+    (dotimes (i max)
+      (let ((time-assq (time-assq i iters))
+            (time-hash (time-hash i iters)))
+        (format t "i: ~d, assq: ~d, hash: ~d~%" i time-assq time-hash)
+        (when (> time-assq time-hash) (return i))))))
+
+;; Value computed on a dual-core 2.4 GHz AMD Opteron running FC3
+;; This isn't the result of compute-eql-combined-method-hash-table-threshold,
+;; it's the value at which assq takes 3/4 the time of hash, which weights
+;; towards the worst case of the eql method, not the average for uniform inputs.
+(defparameter *eql-combined-method-hash-table-threshold* 45)
+
+;;; A vector might be a little faster than an alist, but the hash table case
+;;; will speed up large numbers of methods.
+(defun make-eql-combined-method (eql-methods methods cpls gf argnum sub-dispatch? &optional
+                                             (method-combination *standard-method-combination*))
+  (let ((eql-ms (copy-list eql-methods))
+        (precedence-list (%gf-precedence-list (combined-method-gf gf)))
+        (standard-mc? (eq method-combination *standard-method-combination*))
+        (real-gf (combined-method-gf gf))
+        eql-method-alist
+        (can-use-eq? t))
+    (unless sub-dispatch?
+      (setq methods (sort-methods methods cpls precedence-list)))
+    (while eql-ms
+      (let ((eql-element (eql-specializer-object (nth argnum (%method.specializers (car eql-ms)))))
+            (this-element-methods eql-ms)
+            cell last-cell)
+        (if (or (and (numberp eql-element) (not (fixnump eql-element)))
+                (macptrp eql-element))
+          (setq can-use-eq? nil))
+        (setf eql-ms (%cdr eql-ms)
+              (%cdr this-element-methods) nil
+              cell eql-ms)
+        (while cell
+          (if (eql eql-element
+                     (eql-specializer-object (nth argnum (%method.specializers (car cell)))))
+            (let ((cell-save cell))
+              (if last-cell
+                (setf (%cdr last-cell) (cdr cell))
+                (setq eql-ms (cdr eql-ms)))
+              (setf cell (cdr cell)
+                    (%cdr cell-save) this-element-methods
+                    this-element-methods cell-save))
+            (setq last-cell cell
+                  cell (cdr cell))))
+        (let* ((sorted-methods
+                (sort-methods (nreconc (copy-list this-element-methods)
+                                       (copy-list methods))
+                              cpls
+                              precedence-list))
+               (method-list (and standard-mc? (compute-method-list sorted-methods sub-dispatch?))))
+          (when (or (not standard-mc?)
+                    (memq method-list this-element-methods)
+                    (and (consp method-list)
+                         (labels ((member-anywhere (tem mlist)
+                                    (member tem mlist
+                                            :test #'(lambda (tem el)
+                                                      (if (listp el)
+                                                        (member-anywhere tem el)
+                                                        (member el tem))))))
+                           (member-anywhere this-element-methods method-list))))
+            ; Do EQL comparison only if the EQL methods can run
+            ; (e.g. does not come after a primary method that does not call-next-method)
+            (push (cons eql-element
+                        (if sub-dispatch?
+                          (make-n+1th-arg-combined-method
+                           sorted-methods gf argnum)
+                          (if standard-mc?
+                            (make-standard-combined-method sorted-methods nil gf)
+                            (compute-effective-method-function
+                             real-gf method-combination sorted-methods))))
+                  eql-method-alist)))))
+    ;;eql-method-alist has (element . combined-method) pairs.
+    ;;for now, we're going to use assq or assoc
+    (let ((default-method (if sub-dispatch?
+                            (make-n+1th-arg-combined-method
+                             methods gf argnum)
+                            (if standard-mc?
+                              (make-standard-combined-method methods nil gf t)
+                              (compute-effective-method-function
+                               real-gf method-combination methods)))))
+      (if eql-method-alist
+        (if (> (length eql-method-alist) *eql-combined-method-hash-table-threshold*)
+          (let ((hash (make-hash-table :test (if can-use-eq? 'eq 'eql))))
+            (dolist (pair eql-method-alist)
+              (setf (gethash (car pair) hash) (cdr pair)))
+            (assert-hash-table-readonly hash)
+            (%cons-combined-method 
+             gf (cons argnum (cons hash default-method))
+             #'%%hash-table-combined-method-dcode))
+          (%cons-combined-method
+           gf (cons argnum (cons eql-method-alist default-method))
+           (if can-use-eq? 
+               #'%%assq-combined-method-dcode
+               #'%%assoc-combined-method-dcode)))
+        default-method))))
+
+
+(defun %%assq-combined-method-dcode (stuff args)
+  ;; stuff is (argnum eql-method-list . default-method)
+  ;(declare (dynamic-extent args))
+  (if (listp args)
+    (let* ((args-len (list-length args))
+           (argnum (car stuff)))
+      (when (>= argnum args-len)(signal-program-error  "Too few args to ~s." (%method-gf (cddr stuff))))
+      (let* ((arg (nth argnum args))
+             (thing (assq arg (cadr stuff)))) ; are these things methods or method-functions? - fns    
+        (if thing 
+          (apply (cdr thing) args)
+          (apply (cddr stuff) args))))
+    (let* ((args-len (%lexpr-count args))
+           (argnum (car stuff)))
+      (when (>= argnum args-len)(signal-program-error "Too few args to ~s." (%method-gf (cddr stuff))))
+      (let* ((arg (%lexpr-ref args args-len argnum))
+             (thing (assq arg (cadr stuff))))
+        (if thing 
+          (%apply-lexpr (cdr thing) args)
+          (%apply-lexpr (cddr stuff) args))))))
+  
+
+(DEFun %%assoc-combined-method-dcode (stuff args)
+  ;; stuff is (argnum eql-method-list . default-method)
+  ;(declare (dynamic-extent args))
+  (if (listp args)
+    (let* ((args-len (list-length args))
+           (argnum (car stuff)))
+      (when (>= argnum args-len)(signal-program-error "Too few args to ~s." (%method-gf (cddr stuff))))
+      (let* ((arg (nth argnum args))
+             (thing (assoc arg (cadr stuff)))) ; are these things methods or method-functions?    
+        (if thing 
+          (apply (cdr thing) args)
+          (apply (cddr stuff) args))))
+    (let* ((args-len (%lexpr-count args))
+           (argnum (car stuff)))
+      (when (>= argnum args-len)(signal-program-error "Too few args to ~s." (%method-gf (cddr stuff))))
+      (let* ((arg (%lexpr-ref args args-len argnum))
+             (thing (assoc arg (cadr stuff)))) ; are these things methods or method-functions?    
+        (if thing 
+          (%apply-lexpr (cdr thing) args)
+          (%apply-lexpr (cddr stuff) args))))))
+
+
+
+(defun %%hash-table-combined-method-dcode (stuff args)
+  ;; stuff is (argnum eql-hash-table . default-method)
+  ;(declare (dynamic-extent args))
+  (if (listp args)
+    (let* ((args-len (list-length args))
+           (argnum (car stuff)))
+      (when (>= argnum args-len)(signal-program-error "Too few args to ~s." (%method-gf (cddr stuff))))
+      (let* ((arg (nth argnum args)))
+        (apply (gethash arg (cadr stuff) (cddr stuff)) args)))
+    (let* ((args-len (%lexpr-count args))
+           (argnum (car stuff)))
+      (when (>= argnum args-len)(signal-program-error "Too few args to ~s." (%method-gf (cddr stuff))))
+      (let* ((arg (%lexpr-ref args args-len argnum)))
+        (%apply-lexpr (gethash arg (cadr stuff) (cddr stuff)) args)))))
+
+
+;;; Assumes the two methods have the same number of specializers and
+;;; that each specializer of each method is in the corresponding
+;;; element of cpls (e.g. cpls is a list of the cpl's for the classes
+;;; of args for which both method1 & method2 are applicable.
+(defun %method< (method1 method2 cpls)
+  (let ((s1s (%method.specializers method1))
+        (s2s (%method.specializers method2))
+        s1 s2 cpl)
+    (loop
+      (if (null s1s)
+        (return (method-qualifiers< method1 method2)))
+      (setq s1 (%pop s1s)
+            s2 (%pop s2s)
+            cpl (%pop cpls))
+      (cond ((typep s1 'eql-specializer) 
+             (unless (eq s1 s2)
+               (return t)))
+            ((typep s2 'eql-specializer) (return nil))
+            ((eq s1 s2))
+            (t (return (%i< (cpl-index s1 cpl) (cpl-index s2 cpl))))))))
+
+(defun %simple-method< (method1 method2 cpl)
+  (let ((s1 (%car (%method.specializers method1)))
+        (s2 (%car (%method.specializers method2))))
+    (cond ((typep s1 'eql-specializer) 
+           (if (eq s1 s2)
+             (method-qualifiers< method1 method2)
+             t))
+          ((typep s2 'eql-specializer) nil)
+          ((eq s1 s2) (method-qualifiers< method1 method2))
+          (t (%i< (cpl-index s1 cpl) (cpl-index s2 cpl))))))
+
+; Sort methods with argument-precedence-order
+(defun %hairy-method< (method1 method2 cpls apo)
+  (let ((s1s (%method.specializers method1))
+        (s2s (%method.specializers method2))
+        s1 s2 cpl index)
+    (loop
+      (if (null apo)
+        (return (method-qualifiers< method1 method2)))
+      (setq index (pop apo))
+      (setq s1 (nth index s1s)
+            s2 (nth index s2s)
+            cpl (nth index cpls))
+      (cond ((typep s1 'eql-specializer) 
+             (unless (eq s1 s2)
+               (return t)))
+            ((typep s2 'eql-specializer) (return nil))
+            ((eq s1 s2))
+            (t (return (%i< (cpl-index s1 cpl) (cpl-index s2 cpl))))))))
+
+; This can matter if the user removes & reinstalls methods between
+; invoking a generic-function and doing call-next-method with args.
+; Hence, we need a truly canonical sort order for the methods
+; (or a smarter comparison than EQUAL in %%cnm-with-args-check-methods).
+(defun method-qualifiers< (method1 method2)
+  (labels ((qualifier-list< (ql1 ql2 &aux q1 q2)
+              (cond ((null ql1) (not (null ql2)))
+                    ((null ql2) nil)
+                    ((eq (setq q1 (car ql1)) (setq q2 (car ql2)))
+                     (qualifier-list< (cdr ql1) (cdr ql2)))
+                    ((string-lessp q1 q2) t)
+                    ; This isn't entirely correct.
+                    ; two qualifiers with the same pname in different packages
+                    ; are not comparable here.
+                    ; Unfortunately, users can change package names, hence,
+                    ; comparing the package names doesn't work either.
+                    (t nil))))
+    (qualifier-list< (%method.qualifiers method1) (%method.qualifiers method2))))
+       
+(defun sort-methods (methods cpls &optional apo)
+  (cond ((null cpls) methods)
+        ((null (%cdr cpls))
+         (setq cpls (%car cpls))
+         (flet ((simple-sort-fn (m1 m2)
+                  (%simple-method< m1 m2 cpls)))
+           (declare (dynamic-extent #'simple-sort-fn))
+           (%sort-list-no-key methods #'simple-sort-fn)))
+        ((null apo)                     ; no unusual argument-precedence-order
+         (flet ((sort-fn (m1 m2) 
+                  (%method< m1 m2 cpls)))
+           (declare (dynamic-extent #'sort-fn))
+           (%sort-list-no-key methods #'sort-fn)))
+        (t                              ; I guess some people are just plain rude
+         (flet ((hairy-sort-fn (m1 m2)
+                  (%hairy-method< m1 m2 cpls apo)))
+           (declare (dynamic-extent #'hairy-sort-fn))
+           (%sort-list-no-key methods #'hairy-sort-fn)))))
+
+(defun nremove-uncallable-next-methods (methods)
+  (do ((m methods (%cdr m))
+       mbits)
+      ((null m))
+    (setq mbits (lfun-bits (%method.function (%car m))))
+    (unless (logbitp $lfbits-nextmeth-bit mbits)
+      (setf (%cdr m) nil)
+      (return)))
+  methods)
+
+
+(defun cpl-index (superclass cpl)
+  ;; This will be table lookup later.  Also we'll prelookup the tables
+  ;; in compute-1st-arg-combined-methods above.
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (do ((i 0 (%i+ i 1))
+         (cpl cpl (%cdr cpl)))
+        ((null cpl) nil)
+      (if (eq superclass (%car cpl))
+        (return i)))))
+
+(defun cpl-memq (superclass cpl)
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (do ((cpl cpl (%cdr cpl)))
+        ((null cpl) nil)
+      (if (eq superclass (%car cpl))
+        (return cpl)))))
+
+;;; Combined method interpretation
+
+
+;;; magic is a list of (cnm-cm (methods) . args) cnm-cm is the
+;;; argument checker for call-next-method-with-args or nil could make
+;;; it be a cons as a flag that magic has been heap consed - done
+;;; could also switch car and cadr if we do &lexpr business then if
+;;; cddr is lexpr-p (aka (not listp)) thats the clue also would need
+;;; to do lexpr-apply or apply depending on the state.
+
+
+(defun %%standard-combined-method-dcode (methods args)
+  ;; combined-methods as made by make-combined-method are in methods
+  ;; args are as put there by the caller of the gf.
+  (let* ((car-meths (car methods))
+         (cell-2 (cons methods args))
+         (magic (cons nil cell-2)))
+    ;; i.e. magic is nil methods . args
+    (declare (dynamic-extent magic)
+             (dynamic-extent cell-2))    
+    (if (listp car-meths)
+      (%%before-and-after-combined-method-dcode magic)
+      (progn       
+        (if (not (cdr methods))
+          (%rplaca (cdr magic) car-meths)
+          (%rplaca (cdr magic) (cdr methods)))
+        ; so maybe its a combined-method ?? - no
+        (apply-with-method-context magic (%method.function car-meths) args)))))
+
+;;; args is list, old-args may be lexpr
+(defun cmp-args-old-args (args old-args numreq)
+  (declare (optimize (speed 3)(safety 0)))
+  (if (listp old-args)
+    (do ((newl args (cdr newl))
+         (oldl old-args (cdr oldl))
+         (i 0 (1+ i)))
+        ((eql i numreq) t)
+      (when (neq (car newl)(car oldl))(return nil)))
+    (let ((len (%lexpr-count old-args)))
+      (do ((newl args (cdr newl))
+           (i 0 (1+ i)))
+          ((eql i numreq) t)
+        (when (neq (car newl)(%lexpr-ref old-args len i))(return nil))))))        
+
+
+; called from call-next-method-with-args with magic supplied and 1st time around with not
+(defun %%cnm-with-args-combined-method-dcode (thing args &optional magic) ; was &rest args
+  ;(declare (dynamic-extent args))
+  ; now thing is vector of gf orig methods, arg for key or initarg check, key or initarg fnction
+  ; and our job is to do all the arg checking
+  (let ()
+    ;; THING is nil in next-method calls for non-standard method combination.  To enable
+    ;; checking in that case, would need to change %%call-method* to store a vector in (car magic).
+    (when (and magic thing)
+      (flet ((do-it (thing args)
+               (let* ((args-len (length args))
+                      (gf (svref thing 0))  ; could get this from a method
+                      (numreq (ldb $lfbits-numreq (inner-lfun-bits gf)))
+                      (next-methods (cadr magic)))
+                 ;(when (null self)(error "Next method with args context error"))
+                 (when (neq 0 numreq)
+                   ; oh screw it - old-args may be lexpr too
+                   (let ((old-args (cddr magic)))
+                     (when (< args-len numreq) (signal-program-error "Too few args to ~S" gf))
+                     (when (null (cmp-args-old-args args old-args numreq))
+                       ; required args not eq - usually true, we expect
+                       (let ((new-methods (%compute-applicable-methods* gf args))
+                             (old-methods (svref thing 1)))
+                         (when (not (equal new-methods old-methods))
+                           (error '"Applicable-methods changed in call-next-method.~%~
+                                    Should be: ~s~%Was: ~s~%Next-methods: ~s"
+                                  old-methods new-methods next-methods))))))
+                 (let ((key-or-init-fn (svref thing 3)))
+                   (when key-or-init-fn 
+                     ; was apply
+                     (funcall key-or-init-fn (svref thing 2) args))))))
+        (if (listp args)
+          (do-it thing args)
+          (with-list-from-lexpr (args-list args)
+            (do-it thing args-list)))))
+    ; ok done checking - lets do it 
+    (let* ((methods (if magic (cadr magic)(svref thing 4)))  ;<< was 5 this is nil unless cnm with args
+           ; was if magic
+           (car-meths (car methods))
+           (cell-2 (cons methods args))
+           (magic (cons thing cell-2)))
+      (declare (dynamic-extent magic cell-2))
+      ; i.e. magic is thing methods . args
+      ;(%rplaca magic thing)
+      ;(setf (cadr magic) methods)
+      ;(%rplaca (cdr magic) methods)
+      ;(setf (cddr magic) args)
+      ;(%rplacd (cdr magic) args)
+      (if (listp car-meths)
+        (progn
+          (%%before-and-after-combined-method-dcode magic))
+        (progn       
+          (if (not (cdr methods))
+            (%rplaca (cdr magic) car-meths)
+            (%rplaca (cdr magic) (cdr methods)))
+          ; so maybe its a combined-method ?? - no
+          (apply-with-method-context magic (%method.function car-meths) args))))))
+
+
+
+;;; here if car of methods is listp. methods = (befores afters . primaries)
+(defun %%before-and-after-combined-method-dcode (magic) 
+  (declare (list magic))
+  (let* ((methods (cadr magic))         
+         (befores (car methods))         
+         (cdr-meths (cdr methods))
+         (primaries (cdr cdr-meths))
+         (afters (car cdr-meths))
+         (args (cddr magic)))
+    (declare (list befores afters primaries))
+    (when befores 
+      (dolist (method befores)
+        (rplaca (cdr magic) method)
+        (apply-with-method-context magic (%method.function method) args)))
+    (let* ((cdr (cdr primaries))
+           (method-function (%method.function (car primaries))))   ; guaranteed non nil?
+      (rplaca (cdr magic) (if (null cdr)(car primaries) cdr))      
+      (if (null afters)
+        (apply-with-method-context magic method-function args)  ; tail call if possible
+        (multiple-value-prog1
+          (apply-with-method-context magic method-function args)        
+          (dolist (method afters)
+            (rplaca (cdr magic) method)
+            (apply-with-method-context magic (%method.function method) args)))))))
+
+
+; This is called by the compiler expansion of next-method-p
+; I think there's a bug going around... LAP fever! I'm immune
+(defun %next-method-p (magic)
+  (let ((methods (%cadr magic)))
+    (consp methods)))
+
+
+(defun %call-next-method (magic &rest args) ; if args supplied they are new ones
+  (declare (dynamic-extent args)) 
+  (if args
+    (apply #'%call-next-method-with-args magic args)
+    (let* ((next-methods (%cadr magic))) ; don't get this closed magic stuff      
+      (if (not (consp next-methods))
+        ( %no-next-method  magic)            
+        (let ((args (%cddr magic)))  ; get original args
+          ;The unwind-protect is needed in case some hacker in his/her wisdom decides to:
+          ; (defmethod foo (x) (catch 'foo (call-next-method)) (call-next-method))
+          ; where the next-method throws to 'foo.
+          ; The alternative is to make a new magic var with args
+          ; actually not that fancy (call-next-method)(call-next-method) is same problem
+          (let ()
+            (unwind-protect
+              (if (listp (car next-methods))
+                ( %%before-and-after-combined-method-dcode magic)
+                (let ((cdr (cdr next-methods)))
+                  (rplaca (cdr magic)(if (not cdr)(car next-methods) cdr))
+                  (let ((method-function (%method.function (car next-methods))))
+                    (apply-with-method-context magic method-function args))))
+              (rplaca (cdr magic) next-methods))))))))
+
+;; Note: we need to change the compiler to call this when it can prove that
+;; call-next-method cannot be called a second time. I believe thats done.
+
+
+(defun %tail-call-next-method (magic)
+  (let* ((next-methods (%cadr magic))  ; or make it car
+         (args (%cddr magic))) ; get original args        
+    (if (not (consp next-methods)) ; or consp?
+      ( %no-next-method magic)
+      (if (listp (car next-methods))
+        ( %%before-and-after-combined-method-dcode magic)
+        (let ((cdr (cdr next-methods)))
+          (rplaca (cdr magic) (if (not cdr)(car next-methods) cdr))
+          (apply-with-method-context magic (%method.function (car next-methods)) args))))))
+
+;;; may be simpler to blow another cell so magic looks like
+;;; (cnm-cm/nil next-methods . args) - done
+;;; and also use first cell to mean heap-consed if itsa cons
+
+(defun %call-next-method-with-args (magic &rest args)
+  (declare (dynamic-extent args))
+  (if (null args)
+    (%call-next-method magic)
+    (let* ((methods (%cadr magic)))
+      (if (not (consp methods))
+        (%no-next-method  magic)
+        (let* ((cnm-cm (car magic)))
+          ; a combined method
+          (when (consp cnm-cm)(setq cnm-cm (car cnm-cm)))
+          ; could just put the vector in car magic & no self needed in vector?
+          (let ((the-vect cnm-cm)) ;  <<
+            (funcall #'%%cnm-with-args-combined-method-dcode ;(%combined-method-dcode cnm-cm)
+                     the-vect
+                     args
+                     magic)))))))
+
+
+
+; called from x%%call-next-method-with-args - its the key-or-init-fn 
+(defun %%cnm-with-args-check-initargs (init-cell args)
+  ; here we forget the lexpr idea because it wants to cdr
+  ;(declare (dynamic-extent args))
+  (let* ((rest (cdr args))
+         (first-arg (car args)))
+    (declare (list rest))
+    (let* ((initargs rest)
+           (init-function (car init-cell))
+           (instance (cond ((eq init-function #'update-instance-for-different-class)
+                            (setq initargs (cdr rest))
+                            (car rest))
+                           ((eq init-function #'shared-initialize)
+                            (setq initargs (cdr rest))
+                            first-arg)
+                           ((eq init-function #'update-instance-for-redefined-class)
+                            (setq initargs (%cdddr rest))
+                            first-arg)
+                           (t first-arg)))
+           (class (class-of instance))
+           bad-initarg)
+      (dolist (functions (cdr init-cell)
+                         (error "Bad initarg: ~s to call-next-method for ~s~%on ~s"
+                                bad-initarg instance (car init-cell)))
+        (multiple-value-bind 
+          (errorp bad-key)
+          (if (eq (car functions) #'initialize-instance)
+            (apply #'check-initargs instance class initargs nil
+                   #'initialize-instance #'allocate-instance #'shared-initialize
+                   nil)
+            (apply #'check-initargs instance class initargs nil functions))
+          (if errorp
+            (unless bad-initarg (setq bad-initarg bad-key))
+            (return t)))))))
+
+
+
+(defun %no-next-method (magic)
+  (let* ((method (%cadr magic)))
+    (if (consp method) (setq method (car method)))
+    (unless (typep method 'standard-method)
+      (error "call-next-method called outside of generic-function dispatch context.~@
+              Usually indicates an error in a define-method-combination form."))
+    (let ((args (cddr magic))
+          (gf (%method.gf method)))
+      (if (listp args)
+        (apply #'no-next-method gf method args)
+        (%apply-lexpr #'no-next-method gf method args)))))
+
+
+
+
+;;; This makes a consed version of the magic first arg to a method.
+;;; Called when someone closes over the magic arg. (i.e. does (george
+;;; #'call-next-method))
+
+(defun %cons-magic-next-method-arg (magic)
+  ; car is a cons as a flag that its already heap-consed! - else cnm-cm or nil
+  (if (consp (car magic))
+    magic
+    (list* (list (car magic))
+           (if (consp (%cadr magic))
+             (copy-list (%cadr magic)) ; is this copy needed - probably not
+             (cadr magic))
+           (let ((args (%cddr magic)))
+             (if (listp args)
+               (copy-list args)
+               (let* ((len (%lexpr-count args))
+                      (l (make-list len)))
+                 (do ((i 0 (1+ i))
+                      (list l (cdr list)))
+                     ((null list))
+                   (%rplaca list (%lexpr-ref args len i)))
+                 l))))))
+
+
+; Support CALL-METHOD in DEFINE-METHOD-COMBINATION
+(defun %%call-method* (method next-methods args)
+  (let* ((method-function (%method.function method))
+         (bits (lfun-bits method-function)))
+    (declare (fixnum bits))
+    (if (not (and (logbitp $lfbits-nextmeth-bit  bits)
+                  (logbitp  $lfbits-method-bit bits)))
+      (if (listp args)
+        (apply method-function args)
+        (%apply-lexpr method-function args))
+      (let* ((cell-2 (cons next-methods args))
+             (magic (cons nil cell-2)))
+        (declare (dynamic-extent magic)
+                 (dynamic-extent cell-2))  
+        (if (null next-methods)
+          (%rplaca (cdr magic) method))
+        (apply-with-method-context magic method-function args)))))
+
+; Error checking version for user's to call
+(defun %call-method* (method next-methods args)
+  (let* ((method-function (%method.function method))
+         (bits (lfun-bits method-function)))
+    (declare (fixnum bits))
+    (if (not (and (logbitp $lfbits-nextmeth-bit  bits)
+                  (logbitp  $lfbits-method-bit bits)))
+      (progn
+        (require-type method 'standard-method)
+        (if (listp args)
+          (apply method-function args)
+          (%apply-lexpr method-function args)))
+      (progn
+        (do* ((list next-methods (cdr list)))
+             ((null list))
+          (when (not (listp list))
+            (%err-disp $XIMPROPERLIST next-methods))
+          (when (not (standard-method-p (car list)))
+            (report-bad-arg (car list) 'standard-method))) 
+        (let* ((cell-2 (cons next-methods args))
+               (magic (cons nil cell-2)))
+          (declare (dynamic-extent magic)
+                   (dynamic-extent cell-2))  
+          (if (null next-methods)
+            (%rplaca (cdr magic) method))
+          (apply-with-method-context magic method-function args))))))
+
+
+
Index: /branches/new-random/level-1/l1-error-signal.lisp
===================================================================
--- /branches/new-random/level-1/l1-error-signal.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-error-signal.lisp	(revision 13309)
@@ -0,0 +1,158 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defun %kernel-restart (error-type &rest args)
+  (%kernel-restart-internal error-type args (%get-frame-ptr)))
+
+(defun %kernel-restart-internal (error-type args frame-ptr)
+  ;(declare (dynamic-extent args))
+  (dolist (f *kernel-restarts* (%err-disp-internal error-type args frame-ptr))
+    (when (eq (car f) error-type)
+      (return (apply (cdr f) frame-ptr args)))))
+
+;;; this is the def of %err-disp.
+;;; Yup.  That was my first guess.
+(defun %err-disp (err-num &rest errargs)
+  (%err-disp-internal err-num errargs (%get-frame-ptr)))
+
+(defun %errno-disp (errno &rest errargs)
+  (%errno-disp-internal errno errargs (%get-frame-ptr)))
+
+#+windows-target
+(defun %windows-error-disp (errno &rest errargs)
+  (%err-disp-common errno 0 (%windows-error-string errno) errargs (%get-frame-ptr)))
+  
+(defun %errno-disp-internal (errno errargs frame-ptr)
+  (declare (fixnum errno))
+  (let* ((err-type (max (ash errno -16) 0))
+	 (errno (%word-to-int errno))
+	 (error-string (%strerror errno))
+	 (format-string (if errargs
+			  (format nil "~a : ~a" error-string "~s")
+			  error-string)))
+    (%err-disp-common nil err-type  format-string errargs frame-ptr)))
+
+
+(defun %err-disp-internal (err-num errargs frame-ptr)
+  (declare (fixnum err-num))
+  ;;; The compiler (finally !) won't tail-apply error.  But we kind of
+  ;;; expect it to ...
+  (let* ((err-typ (max (ash err-num -16) 0))
+         (err-num (%word-to-int err-num))
+         (format-string (%rsc-string err-num)))
+    (%err-disp-common err-num err-typ format-string errargs frame-ptr)))
+
+(defparameter *foreign-error-condition-recognizers* ())
+
+
+(defun %err-disp-common (err-num err-typ format-string errargs frame-ptr)
+  (let* ((condition-name (or (uvref *simple-error-types* err-typ)
+                             (%cdr (assq err-num *kernel-simple-error-classes*)))))
+    ;;(dbg format-string)
+    (if condition-name      
+      (funcall '%error
+               (case condition-name
+                 (type-error
+                  (if (cdr errargs)
+                    (make-condition condition-name
+                                             :format-control format-string
+                                             :datum (car errargs)
+                                             :expected-type (%type-error-type (cadr errargs)))
+                    (make-condition condition-name
+                                             :format-control format-string
+                                             :datum (car errargs))))
+		 (improper-list (make-condition condition-name
+						:datum (car errargs)))
+                 (simple-file-error (make-condition condition-name
+                                             :pathname (car errargs)
+                                             :error-type format-string
+                                             :format-arguments (cdr errargs)))
+                 (undefined-function (make-condition condition-name
+                                                     :name (car errargs)))
+                 (call-special-operator-or-macro
+                  (make-condition condition-name
+                                  :name (car errargs)
+                                  :function-arguments (cadr errargs)))
+                 (sequence-index-type-error
+                  (make-sequence-index-type-error (car errargs) (cadr errargs)))
+		 (cant-construct-arglist
+		  (make-condition condition-name
+				  :datum (car errargs)
+				  :format-control format-string))
+                 (array-element-type-error
+                  (let* ((array (cadr errargs)))
+                    (make-condition condition-name
+                                    :format-control format-string
+                                    :datum (car errargs)
+                                    :expected-type (array-element-type array)
+                                    :array array)))
+                                  
+                 (t (make-condition condition-name 
+                                    :format-control format-string
+                                    :format-arguments errargs)))
+               nil
+               frame-ptr)
+      (let* ((cond nil))
+        (if (and (eql err-num $XFOREIGNEXCEPTION)
+                 (dolist (recog *foreign-error-condition-recognizers*)
+                   (let* ((c (funcall recog (car errargs))))
+                     (when c (return (setq cond c))))))
+          (funcall '%error cond nil frame-ptr)
+          (funcall '%error format-string errargs frame-ptr))))))
+
+(defun error (condition &rest args)
+  "Invoke the signal facility on a condition formed from DATUM and ARGUMENTS.
+  If the condition is not handled, the debugger is invoked."
+  #|
+  #+ppc-target
+  (with-pstrs ((pstr (if (stringp condition) condition "Error")))
+    (#_DebugStr pstr))
+  |#
+  (%error condition args (%get-frame-ptr)))
+
+(defun cerror (cont-string condition &rest args)
+  (let* ((fp (%get-frame-ptr)))
+    (restart-case (%error condition (if (condition-p condition) nil args) fp)
+      (continue ()
+                :report (lambda (stream) 
+                            (apply #'format stream cont-string args))
+                nil))))
+
+(defun %error (condition args error-pointer)
+  (setq *error-reentry-count* 0)
+  (setq condition (condition-arg condition args 'simple-error))
+  (signal condition)
+  (unless *interactive-streams-initialized*
+    (bug (format nil "Error during early application initialization:~%
+~a" condition))
+    (#_exit #-windows-target #$EX_SOFTWARE #+windows-target #$EXIT_FAILURE))
+  (application-error *application* condition error-pointer)
+  (application-error
+   *application*
+   (condition-arg "~s returned. It shouldn't.~%If it returns again, I'll throw to toplevel."
+                  '(application-error) 'simple-error)
+   error-pointer)
+  (toplevel))
+
+(defun make-sequence-index-type-error (idx sequence)
+  (let* ((upper (length sequence)))
+    (make-condition 'sequence-index-type-error
+                    :datum idx
+                    :sequence sequence
+                    :expected-type `(integer 0 (,upper)))))
Index: /branches/new-random/level-1/l1-error-system.lisp
===================================================================
--- /branches/new-random/level-1/l1-error-system.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-error-system.lisp	(revision 13309)
@@ -0,0 +1,1329 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;;; This file contains the error/condition system.  Functions that
+;;; signal/handle errors are defined later.
+
+(in-package "CCL")
+
+;;;***********************************
+;;; Error System
+;;;***********************************
+
+(defclass condition () ())
+(defclass warning (condition) ())
+(defclass serious-condition (condition) ())
+(defclass error (serious-condition) ())
+
+(define-condition simple-condition (condition)
+  ((format-control :initarg :format-control
+                  :reader simple-condition-format-control)
+   (format-arguments :initarg :format-arguments
+                     :initform nil
+                     :reader simple-condition-format-arguments))
+  (:report (lambda (c stream)  ;; If this were a method, slot value might be faster someday.  Accessors always faster ?
+                               ;; And of course it's terribly important that this be as fast as humanly possible...
+	    ;Use accessors because they're documented and users can specialize them.
+            (apply #'format stream (simple-condition-format-control c)
+                   (simple-condition-format-arguments c)))))
+
+
+(define-condition storage-condition (serious-condition) ())
+
+(define-condition thread-condition (serious-condition) ())
+
+(define-condition process-reset (thread-condition)
+  ((kill :initarg :kill :initform nil :reader process-reset-kill)))
+
+
+(define-condition print-not-readable (error)
+  ((object :initarg :object :reader print-not-readable-object)
+   (stream :initarg :stream :reader print-not-readable-stream))
+  (:report (lambda (c stream)
+             (let* ((*print-readably* nil))
+               (format stream "Attempt to print object ~S on stream ~S ."
+                       (print-not-readable-object c)
+                       (print-not-readable-stream c))))))
+
+(define-condition simple-warning (simple-condition warning) ())
+
+(define-condition compiler-warning (warning)
+  ((function-name :initarg :function-name :initform nil :accessor compiler-warning-function-name)
+   (source-note :initarg :source-note :initform nil :accessor compiler-warning-source-note)
+   (warning-type :initarg :warning-type :reader compiler-warning-warning-type)
+   (args :initarg :args :reader compiler-warning-args)
+   (nrefs :initform () :accessor compiler-warning-nrefs))
+  (:report report-compiler-warning))
+
+;; Backward compatibility
+(defmethod compiler-warning-file-name ((w compiler-warning))
+  (source-note-filename (compiler-warning-source-note w)))
+
+(define-condition style-warning (compiler-warning)
+  ((warning-type :initform :unsure)
+   (args :initform nil)))
+(define-condition undefined-reference (style-warning) ())
+(define-condition undefined-type-reference (undefined-reference) ())
+(define-condition undefined-function-reference (undefined-reference) ())
+(define-condition macro-used-before-definition (compiler-warning) ())
+(define-condition invalid-type-warning (style-warning) ())
+(define-condition invalid-arguments (style-warning) ())
+(define-condition invalid-arguments-global (style-warning) ())
+(define-condition undefined-keyword-reference (undefined-reference invalid-arguments) ())
+
+(define-condition simple-error (simple-condition error) ())
+
+(define-condition simple-storage-condition (simple-condition storage-condition) ())
+(define-condition stack-overflow-condition (simple-storage-condition) ())
+
+(define-condition invalid-memory-access (storage-condition)
+  ((address :initarg :address)
+   (write-p :initform nil :initarg :write-p))
+  (:report (lambda (c s)
+             (with-slots (address write-p) c
+               (format s "Fault during ~a memory address #x~x" (if write-p "write to" "read of") address)))))
+
+(define-condition invalid-memory-operation (storage-condition)
+  ()
+  (:report (lambda (c s)
+             (declare (ignore c))
+             (format s "Invalid memory operation."))))
+
+(define-condition write-to-watched-object (storage-condition)
+  ((object :initform nil :initarg :object
+	   :reader write-to-watched-object-object)
+   (offset :initarg :offset
+	   :reader write-to-watched-object-offset)
+   (instruction :initarg :instruction
+		:reader write-to-watched-object-instruction))
+  (:report report-write-to-watched-object))
+
+(defun report-write-to-watched-object (c s)
+  (with-slots (object offset instruction) c
+    (cond
+      ((uvectorp object)
+       (let* ((count (uvsize object))
+	      (nbytes (if (ivectorp object)
+			(subtag-bytes (typecode object) count)
+			(* count target::node-size)))
+	      (bytes-per-element (/ nbytes count))
+	      (offset (- offset target::misc-data-offset))
+	      (index (/ offset bytes-per-element)))
+	 (format s "Write to watched uvector ~s at " object)
+	 (if (fixnump index)
+	   (format s "index ~s" index)
+	   (format s "an apparently unaligned byte offset ~s" offset))))
+      ((consp object)
+       (format s "Write to ~a watched cons cell ~s"
+               (cond
+		 ((= offset target::cons.cdr) "the CDR of")
+		 ((= offset target::cons.car) "the CAR of")
+		 (t
+		  (format nil "an apparently unaligned byte offset (~s) into"
+			  offset)))
+               object))
+      (t
+       (format s "Write to a strange object ~s at byte offset ~s"
+	       object offset)))
+    (when instruction
+      (format s "~&Faulting instruction: ~s" instruction))))
+
+(define-condition type-error (error)
+  ((datum :initarg :datum)
+   (expected-type :initarg :expected-type :reader type-error-expected-type)
+   (format-control :initarg :format-control  :initform (%rsc-string  $xwrongtype) :reader type-error-format-control))
+  (:report (lambda (c s)
+             (format s (type-error-format-control c)
+                     (type-error-datum c) 
+                     (type-error-expected-type c)))))
+
+(define-condition bad-slot-type (type-error)
+  ((slot-definition :initform nil :initarg :slot-definition)
+   (instance :initform nil :initarg :instance))
+  (:report (lambda (c s)
+	     (format s "The value ~s can not be used to set the value of the slot ~s in ~s, because it is not of type ~s. "
+		     (type-error-datum c)
+		     (slot-definition-name (slot-value c 'slot-definition))
+		     (slot-value c 'instance)
+		     (type-error-expected-type c)))))
+
+(define-condition bad-slot-type-from-initform (bad-slot-type)
+  ()
+  (:report (lambda (c s)
+	     (let* ((slotd (slot-value c 'slot-definition)))
+	       (format s "The value ~s, derived from the initform ~s, can not be used to set the value of the slot ~s in ~s, because it is not of type ~s. "
+		     (type-error-datum c)
+		     (slot-definition-initform slotd)
+		     (slot-definition-name slotd)
+		     (slot-value c 'instance)
+		     (type-error-expected-type c))))))
+
+(define-condition bad-slot-type-from-initarg (bad-slot-type)
+  ((initarg-name :initarg :initarg-name))
+  (:report (lambda (c s)
+	     (let* ((slotd (slot-value c 'slot-definition)))
+	       (format s "The value ~s, derived from the initarg ~s, can not be used to set the value of the slot ~s in ~s, because it is not of type ~s. "
+		     (type-error-datum c)
+		     (slot-value c 'initarg-name)
+		     (slot-definition-name slotd)
+		     (slot-value c 'instance)
+		     (type-error-expected-type c))))))
+  
+
+(define-condition improper-list (type-error)
+  ((expected-type :initform '(satisfies proper-list-p) :reader type-error-expected-type)))
+
+(define-condition cant-construct-arglist (improper-list)
+  ())
+
+
+(let* ((magic-token '("Unbound")))
+  (defmethod type-error-datum ((c type-error))
+    (let* ((datum-slot (slot-value c 'datum)))
+      (if (eq magic-token datum-slot)
+        (%unbound-marker-8)
+        datum-slot)))
+
+; do we need this
+  (defun signal-type-error (datum expected &optional (format-string (%rsc-string  $xwrongtype)))
+    (let ((error #'error))
+      (funcall error (make-condition 'type-error
+                                     :format-control format-string
+                                     :datum (if (eq datum (%unbound-marker-8)) magic-token datum)
+                                     :expected-type (%type-error-type expected)))))
+)
+
+
+(define-condition sequence-index-type-error (type-error)
+  ((sequence :initarg :sequence))
+  (:report (lambda (c s)
+             (format s "~s is not a valid sequence index for ~s"
+                     (type-error-datum c)
+                     (slot-value c 'sequence)))))
+
+
+;;; This is admittedly sleazy; ANSI CL requires TYPE-ERRORs to be
+;;; signalled in cases where a type-specifier is not of an appropriate
+;;; subtype.  The sleazy part is whether it's right to overload TYPE-ERROR
+;;; like this.
+
+(define-condition invalid-subtype-error (type-error)
+  ()
+  (:report (lambda (c s)
+             (format s "The type specifier ~S is not determinably a subtype of the type ~S"
+                     (type-error-datum c)
+                     (type-error-expected-type c)))))
+
+(define-condition simple-type-error (simple-condition type-error) ())
+
+(define-condition array-element-type-error (simple-type-error)
+  ((array :initarg :array :reader array-element-type-error-array))
+  (:report (lambda (c s)
+             (format s (simple-condition-format-control c)
+                     (type-error-datum c)
+                     (array-element-type-error-array c)))))
+                  
+
+
+
+
+(define-condition program-error (error) ())
+(define-condition simple-program-error (simple-condition program-error)
+  ((context :initarg :context :reader simple-program-error-context :initform nil)))
+
+(define-condition invalid-type-specifier (program-error)
+  ((typespec :initarg :typespec :reader invalid-type-specifier-typespec))
+  (:report (lambda (c s)
+             (with-slots (typespec) c
+               (format s "Invalid type specifier: ~s ." typespec)))))
+
+(defun signal-program-error (string &rest args)
+  (let* ((e #'error))
+    (funcall e
+	     (make-condition 'simple-program-error
+			     :format-control (if (fixnump string) (%rsc-string string) string)
+			     :format-arguments args))))
+
+(define-condition simple-destructuring-error (simple-program-error) ())
+
+(define-condition wrong-number-of-arguments (program-error)
+  ((nargs :initform nil
+	  :initarg :nargs :reader wrong-number-of-arguments-nargs)
+   (fn :initform nil :initarg :fn :reader wrong-number-of-arguments-fn))
+  (:report report-argument-mismatch))
+       
+(define-condition too-many-arguments (wrong-number-of-arguments) ())
+
+(define-condition too-few-arguments (wrong-number-of-arguments) ())
+
+(defun report-argument-mismatch (c s)
+  (let* ((nargs-provided (wrong-number-of-arguments-nargs c))
+	 (fn (wrong-number-of-arguments-fn c))
+	 (too-many (typep c 'too-many-arguments)))
+    (multiple-value-bind (min max scaled-nargs)
+	(min-max-actual-args fn nargs-provided)
+      (if (not min)
+	(progn
+	  (format s "Function ~s called with too ~a arguments. "
+                  fn
+                  (if too-many
+                    "many"
+                    "few")))
+	(if too-many
+	  (format s "Too many arguments in call to ~s:~&~d argument~:p provided, at most ~d accepted. " fn scaled-nargs max)
+	  (format s "Too few arguments in call to ~s:~&~d argument~:p provided, at least ~d required. " fn  scaled-nargs min))))))
+
+
+
+(define-condition compile-time-program-error (simple-program-error)
+  nil ;((context :initarg :context :reader compile-time-program-error-context))
+  (:report
+   (lambda (c s)
+     (format s "While compiling ~a :~%~a" 
+             (simple-program-error-context c)
+             (apply #'format nil (simple-condition-format-control c) (simple-condition-format-arguments c))))))
+
+
+
+;;; Miscellaneous error during compilation (caused by macroexpansion, transforms, compile-time evaluation, etc.)
+;;; NOT program-errors.
+(define-condition compile-time-error (simple-error)
+  ((context :initarg :context :reader compile-time-error-context))
+  (:report
+   (lambda (c s)
+     (format s "While compiling ~a :~%~a" 
+             (compile-time-error-context c)
+             (format nil "~a" c)))))
+
+(define-condition control-error (error) ())
+
+(define-condition cant-throw-error (control-error)
+  ((tag :initarg :tag))
+  (:report (lambda (c s)
+             (format s "Can't throw to tag ~s" (slot-value c 'tag)))))
+
+(define-condition inactive-restart (control-error)
+  ((restart-name :initarg :restart-name))
+  (:report (lambda (c s)
+	     (format s "Restart ~s is not active" (slot-value c 'restart-name)))))
+
+(define-condition lock-protocol-error (control-error)
+  ((lock :initarg :lock)))
+
+(define-condition not-lock-owner (lock-protocol-error)
+  ()
+  (:report (lambda (c s)
+	     (format s "Current process ~s does not own lock ~s"
+		     *current-process* (slot-value c 'lock)))))
+
+(define-condition not-locked (lock-protocol-error)
+  ()
+  (:report (lambda (c s)
+	     (format s "Lock ~s isn't locked." (slot-value c 'lock)))))
+
+(define-condition deadlock (lock-protocol-error)
+  ()
+  (:report (lambda (c s)
+	     (format s "Requested operation on ~s would cause deadlock." (slot-value c 'lock)))))
+
+(define-condition package-error (error)
+  ((package :initarg :package :reader package-error-package)))
+(define-condition no-such-package (package-error)
+  ()
+  (:report (lambda (c s) (format s (%rsc-string $xnopkg) (package-error-package c)))))
+(define-condition unintern-conflict-error (package-error)
+  ((sym-to-unintern :initarg :sym)
+   (conflicting-syms :initarg :conflicts))
+  (:report (lambda (c s)
+             (format s (%rsc-string $xunintc) (slot-value c 'sym-to-unintern) (package-error-package c) (slot-value c 'conflicting-syms)))))
+
+(define-condition import-conflict-error (package-error)
+  ((imported-sym :initarg :imported-sym)
+   (conflicting-sym :initarg :conflicting-sym)
+   (conflict-external-p :initarg :conflict-external))
+  (:report (lambda (c s)
+             (format s (%rsc-string (if (slot-value c 'conflict-external-p) $ximprtcx $ximprtc))
+                     (slot-value c 'imported-sym)
+                     (package-error-package c)
+                     (slot-value c 'conflicting-sym)))))
+
+(define-condition use-package-conflict-error (package-error)
+  ((package-to-use :initarg :package-to-use)
+   (conflicts :initarg :conflicts)
+   (external-p :initarg :external-p))
+  (:report (lambda (c s)
+             (format s (%rsc-string (if (slot-value c 'external-p) $xusecX $xusec))
+                     (slot-value c 'package-to-use)
+                     (package-error-package c)
+                     (slot-value c 'conflicts)))))
+
+(define-condition export-conflict-error (package-error)
+  ((conflicts :initarg :conflicts))
+  (:report 
+   (lambda (c s)
+     (format s "Name conflict~p detected by ~A :" (length (slot-value c 'conflicts)) 'export)
+     (let* ((package (package-error-package c)))
+       (dolist (conflict (slot-value c 'conflicts))
+         (destructuring-bind (inherited-p sym-to-export using-package conflicting-sym) conflict
+           (format s "~&~A'ing ~S from ~S would cause a name conflict with ~&~
+                      the ~a symbol ~S in the package ~s, which uses ~S."
+                   'export 
+                   sym-to-export 
+                   package 
+                   (if inherited-p "inherited" "present")
+                   conflicting-sym
+                   using-package
+                   package)))))))
+
+(define-condition export-requires-import (package-error)
+  ((to-be-imported :initarg :to-be-imported))
+  (:report
+   (lambda (c s)
+     (let* ((p (package-error-package c)))
+       (format s "The following symbols need to be imported to ~S before they can be exported ~& from that package:~%~s:" p (slot-value c 'to-be-imported))))))
+
+
+(define-condition package-name-conflict-error (package-error simple-error) ())
+
+(define-condition package-is-used-by (package-error)
+  ((using-packages :initarg :using-packages))
+  (:report (lambda (c s)
+             (format s "~S is used by ~S" (package-error-package c)
+                     (slot-value c 'using-packages)))))
+
+(define-condition symbol-name-not-accessible (package-error)
+  ((symbol-name :initarg :symbol-name))
+  (:report (lambda (c s)
+             (format s "No aymbol named ~S is accessible in package ~s"
+                     (slot-value c 'symbol-name)
+                     (package-error-package c)))))
+
+(define-condition stream-error (error)
+  ((stream :initarg :stream :reader stream-error-stream)))
+
+(defun stream-error-context (condition)
+  (let* ((stream (stream-error-stream condition)))
+    (with-output-to-string (s)
+       (format s "on ~s" stream)
+       (let* ((pos (ignore-errors (stream-position stream))))
+         (when pos
+           (format s ", near position ~d" pos)))
+       (let* ((surrounding (stream-surrounding-characters stream)))
+         (when surrounding
+           (format s ", within ~s" surrounding))))))
+
+(define-condition parse-error (error) ())
+(define-condition parse-integer-not-integer-string (parse-error)
+  ((string :initarg :string))
+  (:report (lambda (c s)
+	     (format s "Not an integer string: ~s" (slot-value c 'string)))))
+
+(define-condition reader-error (parse-error stream-error) ())
+(define-condition end-of-file (stream-error) ()
+  (:report (lambda (c s)
+             (format s "Unexpected end of file ~a" (stream-error-context c)))))
+
+(define-condition io-timeout (stream-error)
+  ())
+
+(define-condition input-timeout (io-timeout)
+  ()
+  (:report (lambda (c s)
+             (format s "Input timeout on ~s" (stream-error-stream c)))))
+(define-condition output-timeout (io-timeout)
+  ()
+  (:report (lambda (c s)
+             (format s "Output timeout on ~s" (stream-error-stream c)))))
+(define-condition communication-deadline-expired (io-timeout)
+  ()
+  (:report (lambda (c s)
+             (format s "Communication deadline timeout on ~s" (stream-error-stream c)))))
+ 
+
+
+
+(define-condition impossible-number (reader-error)
+  ((token :initarg :token :reader impossible-number-token)
+   (condition :initarg :condition :reader impossible-number-condition))
+  (:report (lambda (c s)
+             (format s "Condition of type ~s raised ~&while trying to parse numeric token ~s ~&~s"
+                     (type-of (impossible-number-condition c))
+                     (impossible-number-token c)
+                     (stream-error-context c)))))
+
+
+    
+(define-condition simple-stream-error (stream-error simple-condition) () 
+  (:report (lambda (c s) 
+             (format s "~a : ~&~a" (stream-error-context c) 
+                     (apply #'format
+                            nil
+                            (simple-condition-format-control c)
+                            (simple-condition-format-arguments c))))))
+
+
+
+
+(define-condition file-error (error)
+  ((pathname :initarg :pathname :initform "<unspecified>" :reader file-error-pathname)
+   (error-type :initarg :error-type :initform "File error on file ~S"))
+  (:report (lambda (c s)
+              (format s (slot-value c 'error-type) 
+                     (file-error-pathname c)))))
+
+(define-condition simple-file-error (simple-condition file-error)
+  ()
+  (:report (lambda (c s)
+	     (apply #'format s (slot-value c 'error-type) 
+		    (file-error-pathname c)
+		    (simple-condition-format-arguments c)))))
+
+
+(define-condition namestring-parse-error (error)
+  ((complaint :reader namestring-parse-error-complaint :initarg :complaint)
+   (arguments :reader namestring-parse-error-arguments :initarg :arguments
+	      :initform nil)
+   (namestring :reader namestring-parse-error-namestring :initarg :namestring)
+   (offset :reader namestring-parse-error-offset :initarg :offset))
+  (:report (lambda (condition stream)  
+  (format stream "Parse error in namestring: ~?~%  ~A~%  ~V@T^"
+	  (namestring-parse-error-complaint condition)
+	  (namestring-parse-error-arguments condition)
+	  (namestring-parse-error-namestring condition)
+	  (namestring-parse-error-offset condition)))))
+
+(define-condition cell-error (error)
+  ((name :initarg :name :reader cell-error-name)
+   (error-type :initarg :error-type :initform "Cell error" :reader cell-error-type))
+  (:report (lambda (c s) (format s "~A: ~S" (cell-error-type c) (cell-error-name c)))))
+
+(define-condition unbound-variable (cell-error)
+  ((error-type :initform "Unbound variable")))
+
+(define-condition undefined-function (cell-error)
+  ((error-type :initform "Undefined function")))
+(define-condition undefined-function-call (control-error undefined-function)
+  ((function-arguments :initarg :function-arguments :reader undefined-function-call-arguments))
+  (:report (lambda (c s) (format s "Undefined function ~S called with arguments ~:S ."
+                                 (cell-error-name c)
+                                 (undefined-function-call-arguments c)))))
+
+(define-condition call-special-operator-or-macro (undefined-function-call)
+  ()
+  (:report (lambda (c s) (format s "Special operator or global macro-function ~s can't be FUNCALLed or APPLYed" (cell-error-name c)))))
+
+  
+(define-condition unbound-slot (cell-error)
+  ((instance :initarg :instance :accessor unbound-slot-instance))
+  (:report (lambda (c s) (format s "Slot ~s is unbound in ~s"
+                                 (cell-error-name c)
+                                 (unbound-slot-instance c)))))
+  
+
+(define-condition arithmetic-error (error) 
+  ((operation :initform nil :initarg :operation :reader arithmetic-error-operation)
+   (operands :initform nil :initarg :operands :reader arithmetic-error-operands)
+   (status :initform nil :initarg :status :reader arithmetic-error-status))
+  (:report (lambda (c s)
+             (format s "~S detected" (type-of c))
+             (let* ((operands (arithmetic-error-operands c)))
+               (when operands
+                 (format s "~&performing ~A on ~:S"
+                         (arithmetic-error-operation c) 
+                         operands))))))
+
+(define-condition division-by-zero (arithmetic-error) ())
+  
+(define-condition floating-point-underflow (arithmetic-error) ())
+(define-condition floating-point-overflow (arithmetic-error) ())
+(define-condition floating-point-inexact (arithmetic-error) ())
+(define-condition floating-point-invalid-operation (arithmetic-error) ())
+
+(define-condition compiler-bug (simple-error)
+  ()
+  (:report (lambda (c stream)
+                  (format stream "Compiler bug or inconsistency:~%")
+                  (apply #'format stream (simple-condition-format-control c)
+                         (simple-condition-format-arguments c)))))
+
+(define-condition external-process-creation-failure (serious-condition)
+  ((proc :initarg :proc))
+  (:report (lambda (c stream)
+             (with-slots (proc) c
+               (let* ((code (external-process-%exit-code proc)))
+                 (format stream "Fork failed in ~s: ~a. " proc (if (eql code -1) "random lisp error" (%strerror code))))))))
+   
+                         
+(defun restartp (thing) 
+  (istruct-typep thing 'restart))
+(setf (type-predicate 'restart) 'restartp)
+
+(defmethod print-object ((restart restart) stream)
+  (let ((report (%restart-report restart)))
+    (cond ((or *print-escape* (null report))
+           (print-unreadable-object (restart stream :identity t)
+             (format stream "~S ~S"
+                     'restart (%restart-name restart))))
+          ((stringp report)
+           (write-string report stream))
+          (t
+           (funcall report stream)))))
+
+(defun %make-restart (name action report interactive test)
+  (%cons-restart name action report interactive test))
+
+(defun make-restart (vector name action-function &key report-function interactive-function test-function)
+  (unless vector (setq vector (%cons-restart nil nil nil nil nil)))
+  (setf (%restart-name vector) name
+        (%restart-action vector) (require-type action-function 'function)
+        (%restart-report vector) (if report-function (require-type report-function 'function))
+        (%restart-interactive vector) (if interactive-function (require-type interactive-function 'function))
+        (%restart-test vector) (if test-function (require-type test-function 'function)))
+  vector)
+
+(defun restart-name (restart)
+  "Return the name of the given restart object."
+  (%restart-name (require-type restart 'restart)))
+
+(defun applicable-restart-p (restart condition)
+  (let* ((pair (if condition (assq restart *condition-restarts*)))
+         (test (%restart-test restart)))
+    (and (or (null pair) (eq (%cdr pair) condition))
+         (or (null test) (funcall test condition)))))
+
+(defun compute-restarts (&optional condition &aux restarts)
+  "Return a list of all the currently active restarts ordered from most
+   recently established to less recently established. If CONDITION is
+   specified, then only restarts associated with CONDITION (or with no
+   condition) will be returned."
+  (dolist (cluster %restarts% (nreverse restarts))
+    (dolist (restart cluster)
+      (when (applicable-restart-p restart condition)
+        (push restart restarts)))))
+
+(defun find-restart (name &optional condition)
+  "Return the first active restart named NAME. If NAME names a
+   restart, the restart is returned if it is currently active. If no such
+   restart is found, NIL is returned. It is an error to supply NIL as a
+   name. If CONDITION is specified and not NIL, then only restarts
+   associated with that condition (or with no condition) will be
+   returned."
+  (dolist (cluster %restarts%)
+    (dolist (restart cluster)
+      (when (and (or (eq restart name) (eq (restart-name restart) name))
+                 (applicable-restart-p restart condition))
+	(return-from find-restart restart)))))
+
+(defun %active-restart (name)
+  (dolist (cluster %restarts%)
+    (dolist (restart cluster)
+      (let* ((rname (%restart-name restart))
+	     (rtest (%restart-test restart)))
+	(when (and (or (eq restart name) (eq rname name))
+		   (or (null rtest) (funcall rtest nil)))
+	  (return-from %active-restart (values restart cluster))))))
+  (error 'inactive-restart :restart-name name))
+
+(defun invoke-restart (restart &rest values)
+  "Calls the function associated with the given restart, passing any given
+   arguments. If the argument restart is not a restart or a currently active
+   non-nil restart name, then a CONTROL-ERROR is signalled."
+  (multiple-value-bind (restart tag) (%active-restart restart)
+    (let ((fn (%restart-action restart)))
+      (cond ((null fn)                  ; simple restart
+             (unless (null values) (%err-disp $xtminps))
+             (throw tag nil))
+            ((fixnump fn)               ; restart case
+             (throw tag (cons fn values)))
+            ((functionp fn)		; restart bind
+	     (apply fn values))		
+	    (t				; with-simple-restart
+	     (throw tag (values nil t)))))))
+
+(defun invoke-restart-no-return (restart)
+  (invoke-restart restart)
+  (error 'restart-failure :restart restart))
+
+(defun invoke-restart-interactively (restart)
+  "Calls the function associated with the given restart, prompting for any
+   necessary arguments. If the argument restart is not a restart or a
+   currently active non-NIL restart name, then a CONTROL-ERROR is signalled."
+  (let* ((restart (find-restart restart)))
+    (format *error-output* "~&Invoking restart: ~a~&" restart)
+    (let* ((argfn (%restart-interactive restart))
+           (values (when argfn (funcall argfn))))
+      (apply #'invoke-restart restart values))))
+
+
+
+(defun maybe-invoke-restart (restart value condition)
+  (let ((restart (find-restart restart condition)))
+    (when restart (invoke-restart restart value))))
+
+(defun use-value (value &optional condition)
+  "Transfer control and VALUE to a restart named USE-VALUE, or return NIL if
+   none exists."
+  (maybe-invoke-restart 'use-value value condition))
+
+(defun store-value (value &optional condition)
+  "Transfer control and VALUE to a restart named STORE-VALUE, or return NIL if
+   none exists."
+  (maybe-invoke-restart 'store-value value condition))
+
+(defun condition-arg (thing args type)
+  (cond ((condition-p thing) (if args (%err-disp $xtminps) thing))
+        ((symbolp thing) (apply #'make-condition thing args))
+        (t (make-condition type :format-control thing :format-arguments args))))
+
+(defun make-condition (name &rest init-list)
+  "Make an instance of a condition object using the specified initargs."
+  (declare (dynamic-extent init-list))
+  (if (subtypep name 'condition)
+    (apply #'make-instance name init-list)
+    (let ((class (if (classp name)
+		   name
+		   (find-class name)))) ;; elicit an error if no such class
+      (unless (class-finalized-p class)
+	(finalize-inheritance class)) ;; elicit an error if forward refs.
+      (error "~S is not a condition class" class))))
+
+(defmethod print-object ((c condition) stream)
+  (if *print-escape* 
+    (call-next-method)
+    (report-condition c stream)))
+
+(defmethod report-condition ((c condition) stream)
+  (princ (cond ((typep c 'error) "Error ")
+               ((typep c 'warning) "Warning ")
+               (t "Condition "))
+         stream)
+  ;Here should dump all slots or something.  For now...
+  (let ((*print-escape* t))
+    (print-object c stream)))
+
+(defun signal-simple-condition (class-name format-string &rest args)
+  (let ((e #'error))  ; Never-tail-call.
+    (funcall e (make-condition class-name :format-control format-string :format-arguments args))))
+
+(defun signal-simple-program-error (format-string &rest args)
+  (apply #'signal-simple-condition 'simple-program-error format-string args))
+
+;;getting the function name for error functions.
+
+
+(defun %last-fn-on-stack (&optional (number 0) (s (%get-frame-ptr)))
+  (let* ((fn nil))
+    (let ((p s))
+      (dotimes (i number)
+        (declare (fixnum i))
+        (unless (setq p (parent-frame p nil))
+          (return)))
+      (do* ((i number (1+ i)))
+           ((null p))
+        (if (setq fn (cfp-lfun p))
+          (return (values fn i))
+          (setq p (parent-frame p nil)))))))
+ 
+(defun %err-fn-name (lfun)
+  "given an lfun returns the name or the string \"Unknown\""
+  (if (lfunp lfun) (or (lfun-name lfun) lfun)
+     (or lfun "Unknown")))
+
+(defun %real-err-fn-name (error-pointer)
+  (multiple-value-bind (fn p) (%last-fn-on-stack 0 error-pointer)
+    (let ((name (%err-fn-name fn)))
+      (if (and (memq name '( call-check-regs)) p)
+        (%err-fn-name (%last-fn-on-stack (1+ p) error-pointer))
+        name))))
+
+
+;; Some simple restarts for simple error conditions.  Callable from the kernel.
+
+(defun find-unique-homonyms (name &optional (test (constantly t)))
+  (delete-duplicates
+   (loop
+     with symbol = (if (consp name) (second name) name)
+     with pname = (symbol-name symbol)
+     for package in (list-all-packages)
+     for other-package-symbol = (find-symbol pname package)
+     for canditate = (and other-package-symbol
+                          (neq other-package-symbol symbol)
+                          (if (consp name)
+                            (list (first name) other-package-symbol)
+                            other-package-symbol))
+     when (and canditate
+               (funcall test canditate))
+       collect canditate)
+   :test #'equal))
+
+(def-kernel-restart $xvunbnd %default-unbound-variable-restarts (frame-ptr cell-name)
+  (unless *level-1-loaded*
+    (dbg cell-name))       ;  user should never see this.
+  (let ((condition (make-condition 'unbound-variable :name cell-name))
+	(other-variables (find-unique-homonyms cell-name (lambda (name)
+                                                           (and (not (keywordp name))
+                                                                (boundp name))))))
+    (flet ((new-value ()
+             (catch-cancel
+              (return-from new-value
+                           (list (read-from-string 
+                                  (get-string-from-user
+                                   (format nil "New value for ~s : " cell-name))))))
+             (continue condition))) ; force error again if cancelled, var still not set.
+      (restart-case (%error condition nil frame-ptr)
+        (continue ()
+                  :report (lambda (s) (format s "Retry getting the value of ~S." cell-name))
+                  (symbol-value cell-name))
+        (use-homonym (homonym)
+                     :test (lambda (c) (and (or (null c) (eq c condition)) other-variables))
+                     :report (lambda (s)
+                               (if (= 1 (length other-variables))
+                                 (format s "Use the value of ~s this time." (first other-variables))
+                                 (format s "Use one of the homonyms ~{~S or ~} this time." other-variables)))
+                     :interactive (lambda ()
+                                    (if (= 1 (length other-variables))
+                                      other-variables
+                                      (select-item-from-list other-variables :window-title "Select homonym to use")))
+                     (symbol-value homonym))
+        (use-value (value)
+                   :interactive new-value
+                   :report (lambda (s) (format s "Specify a value of ~S to use this time." cell-name))
+                   value)
+        (store-value (value)
+                     :interactive new-value
+                     :report (lambda (s) (format s "Specify a value of ~S to store and use." cell-name))
+                     (setf (symbol-value cell-name) value))))))
+
+(def-kernel-restart $xnopkg %default-no-package-restart (frame-ptr package-name)
+  (or (and *autoload-lisp-package*
+           (or (string-equal package-name "LISP") 
+               (string-equal package-name "USER"))
+           (progn
+             (require "LISP-PACKAGE")
+             (find-package package-name)))
+      (let* ((alias (or (%cdr (assoc package-name '(("LISP" . "COMMON-LISP")
+                                                    ("USER" . "CL-USER")) 
+                                     :test #'string-equal))
+                        (if (packagep *package*) (package-name *package*))))
+             (condition (make-condition 'no-such-package :package package-name)))
+        (flet ((try-again (p)
+                          (or (find-package p) (%kernel-restart $xnopkg p))))
+          (restart-case
+            (restart-case (%error condition nil frame-ptr)
+              (continue ()
+                        :report (lambda (s) (format s "Retry finding package with name ~S." package-name))
+                        (try-again package-name))
+              (use-value (value)
+                         :interactive (lambda () (block nil 
+                                                   (catch-cancel
+                                                    (return (list (get-string-from-user
+                                                                   "Find package named : "))))
+                                                   (continue condition)))
+                         :report (lambda (s) (format s "Find specified package instead of ~S ." package-name))
+                         (try-again value))
+              (make-nickname ()
+                             :report (lambda (s) (format s "Make ~S be a nickname for package ~S." package-name alias))
+                             (let ((p (try-again alias)))
+                               (push package-name (cdr (pkg.names p)))
+                               p)))
+            (require-lisp-package ()
+                                  :test (lambda (c)
+                                          (and (eq c condition)
+                                               (or (string-equal package-name "LISP") (string-equal package-name "USER"))))
+                                  :report (lambda (s) 
+                                            (format s "(require :lisp-package) and retry finding package ~s"
+                                                    package-name))
+                                  (require "LISP-PACKAGE")
+                                  (try-again package-name)))))))
+
+(def-kernel-restart $xunintc unintern-conflict-restarts (frame-ptr sym package conflicts)
+  (let ((condition (make-condition 'unintern-conflict-error :package package :sym sym :conflicts conflicts)))
+    (restart-case (%error condition nil frame-ptr)
+      (continue ()
+                :report (lambda (s) (format s "Try again to unintern ~s from ~s" sym package))
+                (unintern sym package))
+      (do-shadowing-import (ssym)
+                           :report (lambda (s) (format s "SHADOWING-IMPORT one of ~S in ~S." conflicts package))
+                           :interactive (lambda ()
+                                          (block nil
+                                            (catch-cancel
+                                             (return (select-item-from-list conflicts 
+                                                                            :window-title 
+                                                                            (format nil "Shadowing-import one of the following in ~s" package)
+                                                                            :table-print-function #'prin1)))
+                                            (continue condition)))
+                           (shadowing-import (list ssym) package)))))
+
+
+(def-kernel-restart $xusec blub (frame-ptr package-to-use using-package conflicts)
+  (resolve-use-package-conflict-error frame-ptr package-to-use using-package conflicts nil))
+
+(def-kernel-restart $xusecX blub (frame-ptr package-to-use using-package conflicts)
+  (resolve-use-package-conflict-error frame-ptr package-to-use using-package conflicts t))
+
+(defun resolve-use-package-conflict-error (frame-ptr package-to-use using-package conflicts external-p)
+  (let ((condition (make-condition 'use-package-conflict-error 
+                                   :package using-package
+                                   :package-to-use package-to-use
+                                   :conflicts conflicts
+                                   :external-p external-p)))
+    (flet ((external-test (&rest ignore) (declare (ignore ignore)) external-p)
+           (present-test (&rest ignore) (declare (ignore ignore)) (not external-p)))
+      (declare (dynamic-extent #'present-test #'external-test))
+      (restart-case (%error condition nil frame-ptr)
+        (continue ()
+                  :report (lambda (s) (format s "Try again to use ~s in ~s" package-to-use using-package)))
+        (resolve-by-shadowing-import (&rest shadowing-imports)
+                                     :test external-test
+                                     :interactive (lambda ()
+                                                    (mapcar #'(lambda (pair) 
+                                                                (block nil
+                                                                  (catch-cancel
+                                                                    (return (car (select-item-from-list pair
+                                                                                                        :window-title 
+                                                                                                        (format nil "Shadowing-import one of the following in ~s" using-package)
+                                                                                                        :table-print-function #'prin1))))
+                                                                  (continue condition)))
+                                                            conflicts))
+                                     :report (lambda (s) (format s "SHADOWING-IMPORT one of each pair of conflicting symbols."))
+                                     (shadowing-import shadowing-imports using-package))
+        (unintern-all ()
+                      :test present-test
+                      :report (lambda (s) (format s "UNINTERN all conflicting symbols from ~S" using-package))
+                      (dolist (c conflicts)
+                        (unintern (car c) using-package)))
+        (shadow-all ()
+                      :test present-test
+                      :report (lambda (s) (format s "SHADOW all conflicting symbols in ~S" using-package))
+                      (dolist (c conflicts)
+                        (shadow-1 using-package (car c))))
+        (resolve-by-unintern-or-shadow (&rest dispositions)
+                                       :test present-test
+                                       :interactive (lambda ()
+                                                      (mapcar #'(lambda (pair)
+                                                                  (let* ((present-sym (car pair)))
+                                                                    (block nil
+                                                                      (catch-cancel
+                                                                        (return (car (select-item-from-list (list 'shadow 'unintern) 
+                                                                                                            :window-title
+                                                                                                            (format nil "SHADOW ~S in, or UNINTERN ~S from ~S" 
+                                                                                                                    present-sym 
+                                                                                                                    present-sym
+                                                                                                                    using-package)
+                                                                                                            :table-print-function #'prin1)))
+                                                                        (continue condition)))))
+                                                              conflicts))
+                                       :report (lambda (s) (format s "SHADOW or UNINTERN the conflicting symbols in ~S." using-package))
+                                       (dolist (d dispositions)
+                                         (let* ((sym (car (pop conflicts))))
+                                           (if (eq d 'shadow)
+                                             (shadow-1 using-package sym)
+                                             (unintern sym using-package)))))))))
+
+
+(defun resolve-export-conflicts (conflicts package)
+  (let* ((first-inherited (caar conflicts))
+         (all-same (dolist (conflict (cdr conflicts) t)
+                     (unless (eq (car conflict) first-inherited) (return nil))))
+         (all-inherited (and all-same first-inherited))
+         (all-present (and all-same (not first-inherited)))
+         (condition (make-condition 'export-conflict-error
+                                    :conflicts conflicts
+                                    :package package)))
+    (flet ((check-again () 
+             (let* ((remaining-conflicts (check-export-conflicts (mapcar #'cadr conflicts) package)))
+               (if remaining-conflicts (resolve-export-conflicts remaining-conflicts package)))))
+      (restart-case (%error condition nil (%get-frame-ptr))
+        (resolve-all-by-shadowing-import-inherited 
+         ()
+         :test (lambda (&rest ignore) (declare (ignore ignore)) all-inherited)
+         :report (lambda (s) (format s "SHADOWING-IMPORT all conflicting inherited symbol(s) in using package(s)."))
+         (dolist (conflict conflicts (check-again))
+           (destructuring-bind (using-package inherited-sym) (cddr conflict)
+             (shadowing-import-1 using-package inherited-sym))))
+        (resolve-all-by-shadowing-import-exported 
+         ()
+         :test (lambda (&rest ignore) (declare (ignore ignore)) all-inherited)
+         :report (lambda (s) (format s "SHADOWING-IMPORT all conflicting symbol(s) to be exported in using package(s)."))
+         (dolist (conflict conflicts (check-again))
+           (destructuring-bind (exported-sym using-package ignore) (cdr conflict)
+             (declare (ignore ignore))
+             (shadowing-import-1 using-package exported-sym))))
+        (resolve-all-by-uninterning-present 
+         ()
+         :test (lambda (&rest ignore) (declare (ignore ignore)) all-present)
+         :report (lambda (s) (format s "UNINTERN all present conflicting symbol(s) in using package(s)."))
+         (dolist (conflict conflicts (check-again))
+           (destructuring-bind (using-package inherited-sym) (cddr conflict)
+             (unintern inherited-sym using-package))))
+        (resolve-all-by-shadowing-present 
+         ()
+         :test (lambda (&rest ignore) (declare (ignore ignore)) all-present)
+         :report (lambda (s) (format s "SHADOW all present conflicting symbol(s) in using package(s)."))
+         (dolist (conflict conflicts (check-again))
+           (destructuring-bind (using-package inherited-sym) (cddr conflict)
+             (shadow-1 using-package inherited-sym))))
+        (review-and-resolve 
+         (dispositions)
+         :report (lambda (s) (format s "Review each name conflict and resolve individually."))
+         :interactive (lambda ()
+                        (let* ((disp nil))
+                          (block b
+                            (catch-cancel
+                              (dolist (conflict conflicts (return-from b (list disp)))
+                                (destructuring-bind (inherited-p exported-sym using-package conflicting-sym) conflict
+                                  (let* ((syms (list exported-sym conflicting-sym)))
+                                    (if inherited-p
+                                      (push (list 'shadowing-import
+                                                  (select-item-from-list syms
+                                                                              :window-title 
+                                                                              (format nil "Shadowing-import one of the following in ~s" using-package)
+                                                                              :table-print-function #'prin1)
+                                                  using-package)
+                                            disp)
+                                      (let* ((selection (car (select-item-from-list syms
+                                                                                    :window-title 
+                                                                                    (format nil "Shadow ~S or unintern ~s in ~s"
+                                                                                            exported-sym 
+                                                                                            conflicting-sym using-package)
+                                                                                    :table-print-function #'prin1))))
+                                        (push (if (eq selection 'exported-sym)
+                                                (list 'shadow (list exported-sym) using-package)
+                                                (list 'unintern conflicting-sym using-package))
+                                              disp)))))))
+                            nil)))
+         (dolist (disp dispositions (check-again))
+           (apply (car disp) (cdr disp))))))))
+
+
+(def-kernel-restart $xwrongtype default-require-type-restarts (frame-ptr value typespec)
+  (setq typespec (%type-error-type typespec))
+  (let ((condition (make-condition 'type-error 
+                                   :datum value
+                                   :expected-type typespec)))
+    (restart-case (%error condition nil frame-ptr)
+      (use-value (newval)
+                 :report (lambda (s)
+                           (format s "Use a new value of type ~s instead of ~s." typespec value))
+                 :interactive (lambda ()
+                                (format *query-io* "~&New value of type ~S :" typespec)
+                                (list (read *query-io*)))
+                 (require-type newval typespec)))))
+
+(def-kernel-restart $xudfcall default-undefined-function-call-restarts (frame-ptr function-name args)
+  (unless *level-1-loaded*
+    (dbg function-name))   ; user should never see this
+  (let ((condition (make-condition 'undefined-function-call
+                                   :name function-name
+                                   :function-arguments args))
+	(other-functions (find-unique-homonyms function-name #'fboundp)))
+    (restart-case (%error condition nil frame-ptr)
+      (continue ()
+                :report (lambda (s) (format s "Retry applying ~S to ~S." function-name args))
+                (apply function-name args))
+      (use-homonym (function-name)
+                   :test (lambda (c) (and (or (null c) (eq c condition)) other-functions))
+                   :report (lambda (s)
+                             (if (= 1 (length other-functions))
+                               (format s "Apply ~s to ~S this time." (first other-functions) args)
+                               (format s "Apply one of ~{~S or ~} to ~S this time."
+                                       other-functions args)))
+                   :interactive (lambda ()
+                                  (if (= 1 (length other-functions))
+                                    other-functions
+                                    (select-item-from-list other-functions :window-title "Select homonym to use")))
+                   (apply (fdefinition function-name) args))
+      (use-value (function)
+                 :interactive (lambda ()
+                                (format *query-io* "Function to apply instead of ~s :" function-name)
+                                (let ((f (read *query-io*)))
+                                  (unless (symbolp f) (setq f (eval f))) ; almost-the-right-thing (tm)
+                                  (list (coerce f 'function))))
+                 :report (lambda (s) (format s "Apply specified function to ~S this time." args))
+                 (apply function args))
+      (store-value (function)
+                   :interactive (lambda ()
+                                (format *query-io* "Function to apply as new definition of ~s :" function-name)
+                                (let ((f (read *query-io*)))
+                                  (unless (symbolp f) (setq f (eval f))) ; almost-the-right-thing (tm)
+                                  (list (coerce f 'function))))
+                   :report (lambda (s) (format s "Specify a function to use as the definition of ~S." function-name))
+                   (apply (setf (symbol-function function-name) function) args)))))
+
+
+
+(defun %check-type (value typespec placename typename)
+  (let ((condition (make-condition 'type-error 
+                                   :datum value
+                                   :expected-type typespec)))
+    (if typename
+      (setf (slot-value condition 'format-control)
+            (format nil "value ~~S is not ~A (~~S)." typename)))
+    (restart-case (%error condition nil (%get-frame-ptr))
+                  (store-value (newval)
+                               :report (lambda (s)
+                                         (format s "Assign a new value of type ~a to ~s" typespec placename))
+                               :interactive (lambda ()
+                                              (format *query-io* "~&New value for ~S :" placename)
+                                              (list (eval (read))))
+                               newval))))
+
+
+; This has to be defined fairly early (assuming, of course, that it "has" to be defined at all ...
+
+(defun ensure-value-of-type (value typespec placename &optional typename)
+  (tagbody
+    again
+    (unless (typep value typespec)
+      (let ((condition (make-condition 'type-error 
+                                       :datum value
+                                       :expected-type typespec)))
+        (if typename
+            (setf (slot-value condition 'format-control)
+                  (format nil "value ~~S is not ~A (~~S)." typename)))
+        (restart-case (%error condition nil (%get-frame-ptr))
+          (store-value (newval)
+                       :report (lambda (s)
+                                 (format s "Assign a new value of type ~a to ~s" typespec placename))
+                       :interactive (lambda ()
+                                      (format *query-io* "~&New value for ~S :" placename)
+                                      (list (eval (read))))
+                       (setq value newval)
+                       (go again))))))
+  value)
+
+;;;The Error Function
+
+(defparameter *kernel-simple-error-classes*
+  (list (cons $xcalltoofew 'simple-destructuring-error)
+        (cons $xcalltoomany 'simple-destructuring-error)
+        (cons $xstkover 'stack-overflow-condition)
+        (cons $xmemfull 'simple-storage-condition)
+        (cons $xwrongtype 'type-error) ; this one needs 2 args
+        (cons $xdivzro 'division-by-zero)
+        (cons $xflovfl 'floating-point-overflow)
+        (cons $xfunbnd 'undefined-function)
+	(cons $xbadkeys 'simple-program-error)
+        (cons $xcallnomatch 'simple-program-error)
+        (cons $xnotfun 'call-special-operator-or-macro)
+        (cons $xaccessnth 'sequence-index-type-error)
+	(cons $ximproperlist 'improper-list)
+	(cons $xnospread 'cant-construct-arglist)
+        (cons $xnotelt 'array-element-type-error)
+        ))
+
+
+(defparameter *simple-error-types*
+  (vector nil 'simple-program-error 'simple-file-error))
+
+(defconstant $pgm-err #x10000)
+
+
+
+
+(defparameter %type-error-typespecs%
+  #(array
+    bignum
+    fixnum
+    character
+    integer
+    list
+    number
+    sequence
+    simple-string
+    simple-vector
+    string
+    symbol
+    macptr
+    real
+    cons
+    unsigned-byte
+    (integer 2 36)
+    float
+    rational
+    ratio
+    short-float
+    double-float
+    complex
+    vector
+    simple-base-string
+    function
+    (unsigned-byte 16)
+    (unsigned-byte 8)
+    (unsigned-byte 32)
+    (signed-byte 32)
+    (signed-byte 16)
+    (signed-byte 8)
+    base-char
+    bit
+    (unsigned-byte 24)                  ; (integer 0 (array-total-size-limit))
+    (unsigned-byte 64)
+    (signed-byte 64)
+    (unsigned-byte 56)
+    (simple-array double-float (* *))
+    (simple-array single-float (* *))
+    (mod #x110000)
+    (array * (* *))                     ;2d array
+    (array * (* * *))                   ;3d array
+    (array t)
+    (array bit)
+    (array (signed-byte 8))
+    (array (unsigned-byte 8))
+    (array (signed-byte 16))
+    (array (unsigned-byte 16))
+    (array (signed-byte 32))
+    (array (unsigned-byte 32))
+    (array (signed-byte 64))
+    (array (unsigned-byte 64))
+    (array fixnum)
+    (array single-float)
+    (array double-float)
+    (array character)
+    (array t (* *))
+    (array bit (* *))
+    (array (signed-byte 8) (* *))
+    (array (unsigned-byte 8) (* *))
+    (array (signed-byte 16) (* *))
+    (array (unsigned-byte 16) (* *))
+    (array (signed-byte 32) (* *))
+    (array (unsigned-byte 32) (* *))
+    (array (signed-byte 64) (* *))
+    (array (unsigned-byte 64) (* *))
+    (array fixnum (* *))
+    (array single-float (* *))
+    (array double-float (* *))
+    (array character (* *))
+    (simple-array t (* *))
+    (simple-array bit (* *))
+    (simple-array (signed-byte 8) (* *))
+    (simple-array (unsigned-byte 8) (* *))
+    (simple-array (signed-byte 16) (* *))
+    (simple-array (unsigned-byte 16) (* *))
+    (simple-array (signed-byte 32) (* *))
+    (simple-array (unsigned-byte 32) (* *))
+    (simple-array (signed-byte 64) (* *))
+    (simple-array (unsigned-byte 64) (* *))
+    (simple-array fixnum (* *))
+    (simple-array character (* *))
+    (array t (* * *))
+    (array bit (* * *))
+    (array (signed-byte 8) (* * *))
+    (array (unsigned-byte 8) (* * *))
+    (array (signed-byte 16) (* * *))
+    (array (unsigned-byte 16) (* * *))
+    (array (signed-byte 32) (* * *))
+    (array (unsigned-byte 32) (* * *))
+    (array (signed-byte 64) (* * *))
+    (array (unsigned-byte 64) (* * *))
+    (array fixnum (* * *))
+    (array single-float (* * *))
+    (array double-float (* * *))
+    (array character (* * *))
+    (simple-array t (* * *))
+    (simple-array bit (* * *))
+    (simple-array (signed-byte 8) (* * *))
+    (simple-array (unsigned-byte 8) (* * *))
+    (simple-array (signed-byte 16) (* * *))
+    (simple-array (unsigned-byte 16) (* * *))
+    (simple-array (signed-byte 32) (* * *))
+    (simple-array (unsigned-byte 32) (* * *))
+    (simple-array (signed-byte 64) (* * *))
+    (simple-array (unsigned-byte 64) (* * *))
+    (simple-array fixnum (* * *))
+    (simple-array single-float (* * *))
+    (simple-array double-float (* * *))
+    (simple-array character (* * *))
+
+    (vector t)
+    bit-vector
+    (vector (signed-byte 8))
+    (vector (unsigned-byte 8))
+    (vector (signed-byte 16))
+    (vector (unsigned-byte 16))
+    (vector (signed-byte 32))
+    (vector (unsigned-byte 32))
+    (vector (signed-byte 64))
+    (vector (unsigned-byte 64))
+    (vector fixnum)
+    (vector single-float)
+    (vector double-float)
+
+    ))
+
+
+(defun %type-error-type (type)
+  (if (fixnump type) 
+    (svref %type-error-typespecs% type)
+    type))
+
+(defun %typespec-id (typespec)
+  (flet ((type-equivalent (t1 t2) (ignore-errors (and (subtypep t1 t2) (subtypep t2 t1)))))
+    (position typespec %type-error-typespecs% :test #'type-equivalent)))
+
+
+(defmethod condition-p ((x t)) nil)
+(defmethod condition-p ((x condition)) t)
+
+
+
+(let* ((globals ()))
+
+  (defun %check-error-globals ()
+    (let ((vars ())
+          (valfs ())
+          (oldvals ()))
+      (dolist (g globals (values vars valfs oldvals))
+        (destructuring-bind (sym predicate newvalf) g
+          (let* ((boundp (boundp sym))
+                 (oldval (if boundp (symbol-value sym) (%unbound-marker-8))))
+          (unless (and boundp (funcall predicate oldval))
+            (push sym vars)
+            (push oldval oldvals)
+            (push newvalf valfs)))))))
+
+  (defun check-error-global (sym checkfn newvalfn)
+    (setq sym (require-type sym 'symbol)
+          checkfn (require-type checkfn 'function)
+          newvalfn (require-type newvalfn 'function))
+    (let ((found (assq sym globals)))
+      (if found
+        (setf (cadr found) checkfn (caddr found) newvalfn)
+        (push (list sym checkfn newvalfn) globals))
+      sym))
+)
+
+(check-error-global '*package* #'packagep #'(lambda () (find-package "CL-USER")))
+
+
+(flet ((io-stream-p (x) (and (streamp x) (eq (stream-direction x) :io)))
+       (input-stream-p (x) (and (streamp x) (input-stream-p x)))
+       (output-stream-p (x) (and (streamp x) (output-stream-p x)))
+       (default-terminal-io () (make-echoing-two-way-stream *stdin* *stdout*))
+       (terminal-io () *terminal-io*)
+       (standard-output () *standard-output*))
+
+  ;; Note that order matters.  These need to come out of %check-error-globals with
+  ;; *terminal-io* first and *trace-output* last
+  (check-error-global '*terminal-io* #'io-stream-p #'default-terminal-io)
+  (check-error-global '*query-io* #'io-stream-p #'terminal-io)
+  (check-error-global '*debug-io* #'io-stream-p #'terminal-io)
+  (check-error-global '*standard-input* #'input-stream-p #'terminal-io)
+  (check-error-global '*standard-output* #'output-stream-p #'terminal-io)
+  (check-error-global '*error-output* #'output-stream-p #'standard-output)
+  (check-error-global '*trace-output* #'output-stream-p #'standard-output))
+
Index: /branches/new-random/level-1/l1-events.lisp
===================================================================
--- /branches/new-random/level-1/l1-events.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-events.lisp	(revision 13309)
@@ -0,0 +1,268 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defvar *inhibit-abort* nil)
+
+;;; If any bits in the *periodic-task-mask* are set in the
+;;; ptaskstate.flags word of a periodic task, it will not be run
+(defvar *periodic-task-mask* 0)
+
+(defmethod print-object ((p periodic-task) stream)
+  (print-unreadable-object (p stream :type t :identity t)
+    (format stream "~s ~d"
+	    (ptask.name p)
+	    (ptaskstate.interval (ptask.state p)))))
+
+(defvar *periodic-task-lock* (make-lock))
+
+(defun find-named-periodic-task (name)
+  (dolist (task *%periodic-tasks%*)
+    (when (eq name (ptask.name task))
+      (return task))))
+
+(defun %install-periodic-task (name function interval &optional 
+                                    (flags 0)
+                                    (privatedata (%null-ptr)))
+  (with-lock-grabbed (*periodic-task-lock*)
+   (let* ((already (find-named-periodic-task name))
+          (state (if already (ptask.state already)
+                   (%istruct 'ptaskstate 0 0 0 0)))
+          (task (or already (%istruct 'periodic-task state name nil))))
+     (setf (ptask.function task) function)
+     (setf (ptaskstate.interval state) interval
+           (ptaskstate.flags state ) flags
+           (ptaskstate.privatedata state) privatedata
+           (ptaskstate.nexttick state) (+ (get-tick-count) interval))
+     (unless already (push task *%periodic-tasks%*))
+     (let* ((interval-in-seconds (/ interval (float *ticks-per-second*))))
+       (if (< interval-in-seconds *periodic-task-interval*)
+         (set-periodic-task-interval interval-in-seconds)))
+     task)))
+
+(defmacro with-periodic-task-mask ((mask) &body body)
+  (let ((thunk (gensym)))
+    `(let ((,thunk #'(lambda () ,@body)))
+       (funcall-with-periodic-task-mask ,mask ,thunk))))
+
+(defvar *periodic-task-masks* nil)
+
+; All this hair is so that multiple processes can vote on the *periodic-task-mask*
+(defun funcall-with-periodic-task-mask (mask  thunk)
+  (let* ((cell (list mask)))
+    (declare (dynamic-extent cell))
+    (flet ((logior-list (list)
+             (declare (type list list))
+             (let ((res 0))
+               (declare (fixnum res))
+               (loop
+                 (when (null list) (return res))
+                 (setq res (%ilogior res (pop list)))))))
+      (declare (inline logior-list))
+      (unwind-protect
+        (progn
+          (without-interrupts
+           (setf (cdr cell) *periodic-task-masks*
+                 *periodic-task-masks* cell)
+           (setq *periodic-task-mask* (logior-list *periodic-task-masks*))
+)
+          (funcall thunk))
+        (without-interrupts
+         (let* ((first *periodic-task-masks*)
+                (this first)
+                (last nil))
+           (declare (type cons first this last))
+           (loop
+             (when (eq this cell)
+               (if last
+                 (setf (cdr last) (cdr this))
+                 (pop first))
+               (return (setq *periodic-task-masks* first)))
+             (setq last this
+                   this (cdr this))))
+         (setq *periodic-task-mask* (logior-list *periodic-task-masks*)))))))
+
+(defparameter *invoke-debugger-hook-on-interrupt* nil)
+
+(define-condition interrupt-signal-condition (condition) ()
+  (:report "interrupt signal"))
+
+(defun force-break-in-listener (p)
+  (process-interrupt p
+		     #'(lambda ()
+                         (multiple-value-bind (vars inits old-vals) (%check-error-globals)
+                           (progv vars old-vals
+                             (mapcar (lambda (v f) (set v (funcall f))) vars inits)
+                             (let ((condition (make-condition 'interrupt-signal-condition))
+                                   (*top-error-frame* (%current-exception-frame)))
+                               (ignoring-without-interrupts
+                                 (when *invoke-debugger-hook-on-interrupt*
+                                   (let* ((hook *debugger-hook*)
+                                          (*debugger-hook* nil))
+                                     (when hook
+                                       (funcall hook condition hook))))
+                                 (%break-in-frame *top-error-frame* condition)
+                                 (clear-input *terminal-io*))))))))
+
+(defglobal *quit-interrupt-hook* nil)
+
+(defun force-async-quit (signum)
+  (when *quit-interrupt-hook*
+    (multiple-value-bind (req opt restp) (function-args *quit-interrupt-hook*)
+      (if (and (= req 0) (= opt 0) (not restp))
+        (funcall *quit-interrupt-hook*)
+        (funcall *quit-interrupt-hook* signum))))
+  ;; Exit by resignalling, as per http://www.cons.org/cracauer/sigint.html
+  (quit #'(lambda ()
+            (ff-call (%kernel-import target::kernel-import-lisp-sigexit) :signed signum)
+            ;; Shouldn't get here
+            (#__exit 143))))
+
+(defstatic *running-periodic-tasks* nil)
+
+(defun cmain ()
+  (thread-handle-interrupts))
+
+
+(defvar *select-interactive-process-hook* nil)
+
+(defun select-interactive-abort-process ()
+  (flet ((maybe-proc (proc) (and proc (process-active-p proc) proc)))
+    (or (maybe-proc (and *select-interactive-process-hook*
+                         (funcall *select-interactive-process-hook*)))
+        (maybe-proc *interactive-abort-process*)
+        (let* ((sr (input-stream-shared-resource *terminal-input*)))
+          (when sr
+            (or (maybe-proc (shared-resource-current-owner sr))
+                (maybe-proc (shared-resource-primary-owner sr))))))))
+
+(defun handle-gc-hooks ()
+  (let ((bits *gc-event-status-bits*))
+    (declare (fixnum bits))
+    (cond ((logbitp $gc-postgc-pending-bit bits)
+           (setq *gc-event-status-bits*
+                 (logand (lognot (ash 1 $gc-postgc-pending-bit))
+                         bits))
+           (let ((f *post-gc-hook*))
+             (when (functionp f) (funcall f)))))))
+
+(defconstant $user-interrupt-break 1)
+(defconstant $user-interrupt-quit 2)
+
+(defun housekeeping ()
+  (progn
+    (handle-gc-hooks)
+    (unless *inhibit-abort*
+      (let* ((id (pending-user-interrupt))
+             (kind (logand #xFF id)))
+        (cond ((eql kind $user-interrupt-quit)
+               ;; Try to use a process that has a shot at reporting any problems
+               ;; in case of bugs in user hook.
+               (let* ((proc (or (select-interactive-abort-process)
+                                *initial-process*))
+                      (signum (ash id -8)))
+                 (process-interrupt proc #'force-async-quit signum)))
+              ((eql kind $user-interrupt-break)
+               (let* ((proc (select-interactive-abort-process)))
+                 (if proc
+                   (force-break-in-listener proc)))))))
+    (flet ((maybe-run-periodic-task (task)
+             (let ((now (get-tick-count))
+                   (state (ptask.state task)))
+               (when (and (>= (- now (ptaskstate.nexttick state))
+                              0)
+                          (eql 0 (logand (the fixnum (ptaskstate.flags state))
+                                         (the fixnum *periodic-task-mask*))))
+                 (setf (ptaskstate.nexttick state)
+                       (+ now (ptaskstate.interval state)))
+                 (funcall (ptask.function task))))))
+      (let ((event-dispatch-task *event-dispatch-task*))
+        (maybe-run-periodic-task event-dispatch-task)
+        (with-lock-grabbed (*periodic-task-lock*)
+          (bitclrf $gc-allow-stack-overflows-bit *gc-event-status-bits*)
+          (unless *running-periodic-tasks*
+            (let-globally ((*running-periodic-tasks* t))
+              (dolist (task *%periodic-tasks%*)
+                (unless (eq task event-dispatch-task)
+                  (maybe-run-periodic-task task))))))))))
+
+
+(defun %remove-periodic-task (name)
+  (with-lock-grabbed (*periodic-task-lock*)
+    (let ((task (find-named-periodic-task name)))
+      (when task
+        (if (setq *%periodic-tasks%* (delete task *%periodic-tasks%*))
+          (let* ((min-ticks target::target-most-positive-fixnum))
+            (dolist (other *%periodic-tasks%*
+                     (set-periodic-task-interval (/ min-ticks (float *ticks-per-second*))))
+              (let* ((other-ticks
+                      (ptaskstate.interval (ptask.state other))))
+                (if (< other-ticks min-ticks)
+                  (setq min-ticks other-ticks)))))
+          (set-periodic-task-interval 1)))
+      task)))
+
+
+(defun auto-flush-interactive-streams ()
+  (with-lock-grabbed (*auto-flush-streams-lock*)
+    (dolist (s *auto-flush-streams*)
+      (when (open-stream-p s)
+        (if (or (typep s 'basic-stream)
+                (typep s 'buffered-io-stream-mixin))
+          (if (ioblock-outbuf-lock (stream-ioblock s t))
+            (force-output s)))
+        (force-output s)))))
+
+(defun add-auto-flush-stream (s)
+  (with-lock-grabbed (*auto-flush-streams-lock*)
+    (when (typep s 'output-stream)
+      (pushnew s *auto-flush-streams*))))
+      
+(defun remove-auto-flush-stream (s)
+  (with-lock-grabbed (*auto-flush-streams-lock*)
+    (setq *auto-flush-streams* (delete s *auto-flush-streams*))))
+
+; Is it really necessary to keep this guy in a special variable ?
+(defloadvar *event-dispatch-task* 
+  (%install-periodic-task 
+   'auto-flush-interactive-streams
+   'auto-flush-interactive-streams
+   33
+   (+ $ptask_draw-flag $ptask_event-dispatch-flag)))
+
+
+(defun event-ticks ()
+  (let ((task *event-dispatch-task*))
+    (when task (ptaskstate.interval (ptask.state task)))))
+
+(defun set-event-ticks (n)
+  (setq n (require-type n '(integer 0 32767)))   ;  Why this weird limit ?
+  (let ((task *event-dispatch-task*))
+    (when task (setf (ptaskstate.interval (ptask.state task)) n))))
+
+;; Making the *initial-process* quit will cause an exit(),
+;; though it might be nicer if all processes were shut down
+;; in an orderly manner first.  This is the not-so-nice way
+;; of quitting ...
+(defun %quit ()
+  (quit))
+
+
+
+; end of L1-events.lisp
+
Index: /branches/new-random/level-1/l1-files.lisp
===================================================================
--- /branches/new-random/level-1/l1-files.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-files.lisp	(revision 13309)
@@ -0,0 +1,1478 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Portions copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; L1-files.lisp - Object oriented file stuff
+
+(in-package "CCL")
+
+(defconstant $paramErr -50)   ; put this with the rest when we find the rest
+
+(defconstant pathname-case-type '(member :common :local :studly))
+(defconstant pathname-arg-type '(or string pathname stream))
+
+(defmacro signal-file-error (err-num &optional pathname &rest args)
+  `(%signal-file-error ,err-num
+    ,@(if pathname (list pathname))
+              ,@(if args args)))
+
+(defun %signal-file-error (err-num &optional pathname args)
+  (declare (fixnum err-num))
+  (let* ((err-code (logior (ash 2 16) (the fixnum (logand #xffff (the fixnum err-num))))))
+    (funcall (if (< err-num 0) '%errno-disp '%err-disp)
+	     err-code
+	     pathname
+	     args)))
+
+
+(defvar %logical-host-translations% '())
+(defvar *load-pathname* nil
+  "the defaulted pathname that LOAD is currently loading")
+(defvar *load-truename* nil
+  "the TRUENAME of the file that LOAD is currently loading")
+
+
+(defparameter *default-pathname-defaults*
+  (let* ((hide-from-compile-file (%cons-pathname nil nil nil)))
+    hide-from-compile-file))
+
+;Right now, the only way it's used is that an explicit ";" expands into it.
+;Used to merge with it before going to ROM.  Might be worth to bring that back,
+;it doesn't hurt anything if you don't set it.
+;(defparameter *working-directory* (%cons-pathname nil nil nil))
+
+;These come in useful...  We should use them consistently and then document them,
+;thereby earning the eternal gratitude of any users who find themselves with a
+;ton of "foo.CL" files...
+(defparameter *.fasl-pathname*
+  (%cons-pathname nil nil
+                  #.(pathname-type
+                     (backend-target-fasl-pathname *target-backend*))))
+
+(defparameter *.lisp-pathname* (%cons-pathname nil nil "lisp"))
+
+(defun if-exists (if-exists filename &optional (prompt "Create ..."))
+  (case if-exists
+    (:error (signal-file-error (- #$EEXIST) filename))
+    ((:dialog) (overwrite-dialog filename prompt))
+    ((nil) nil)
+    ((:ignored :overwrite :append :supersede :rename-and-delete :new-version :rename) filename)
+    (t (report-bad-arg if-exists '(member :error :dialog nil :ignored :overwrite :append :supersede :rename-and-delete)))))
+
+(defun if-does-not-exist (if-does-not-exist filename)
+  (case if-does-not-exist 
+    (:error (signal-file-error (- #$ENOENT) filename)) ; (%err-disp $err-no-file filename))
+    (:create filename)
+    ((nil) (return-from if-does-not-exist nil))
+    (t (report-bad-arg if-does-not-exist '(member :error :create nil)))))
+
+
+(defun native-translated-namestring (path)
+  (let ((name (translated-namestring path)))
+    ;; Check that no quoted /'s
+    (when (%path-mem-last-quoted "/" name)
+      (signal-file-error $xbadfilenamechar name #\/))
+    ;; Check that no unquoted wildcards.
+    (when (%path-mem-last "*" name)
+      (signal-file-error $xillwild name))
+    (namestring-unquote name)))
+
+(defun native-untranslated-namestring (path)
+  (let ((name (namestring (translate-logical-pathname path))))
+    ;; Check that no quoted /'s
+    (when (%path-mem-last-quoted "/" name)
+      (signal-file-error $xbadfilenamechar name #\/))
+    ;; Check that no unquoted wildcards.
+    (when (%path-mem-last "*" name)
+      (signal-file-error $xillwild name))
+    (namestring-unquote name)))
+
+;; Reverse of above, take native namestring and make a Lisp pathname.
+(defun native-to-pathname (name)
+  (pathname (%path-std-quotes name nil
+                              #+windows-target "*;"
+                              #-windows-target "*;:")))
+
+(defun native-to-directory-pathname (name)
+  #+windows-target
+  (let* ((len (length name)))
+    (when (and (> len 1) (not (or (eql (schar name (1- len)) #\/)
+                                  (eql (schar name (1- len)) #\\))))
+      (setq name (%str-cat name "/")))
+    (string-to-pathname name))
+  #-windows-target
+  (make-directory-pathname  :device nil :directory (%path-std-quotes name nil "*;:")))
+
+;;; Make a pathname which names the specified directory; use
+;;; explict :NAME, :TYPE, and :VERSION components of NIL.
+(defun make-directory-pathname (&key host device directory)
+  (make-pathname :host host
+		 :device device
+		 :directory directory
+                 :name nil
+                 :type nil
+                 :version nil))
+
+		   
+(defun namestring-unquote (name)
+  #+(and windows-target bogus)
+  (when (and (> (length name) 1)
+             (eql (schar name 1) #\|))
+    (setq name (subseq name 0))
+    (setf (schar name 1) #\:))
+  (let ((esc *pathname-escape-character*))
+    (if (position esc name)
+      (multiple-value-bind (sstr start end) (get-sstring name)
+	(let ((result (make-string (%i- end start) :element-type 'base-char))
+	      (dest 0))
+	  (loop
+	    (let ((pos (or (position esc sstr :start start :end end) end)))
+	      (while (%i< start pos)
+		(setf (%schar result dest) (%schar sstr start)
+		      start (%i+ start 1)
+		      dest (%i+ dest 1)))
+	      (when (eq pos end)
+		(return nil))
+	      (setq start (%i+ pos 1))))
+	  (shrink-vector result dest)))
+      name)))
+
+(defun translated-namestring (path)
+  (namestring (translate-logical-pathname (merge-pathnames path))))
+
+
+(defun truename (path)
+  "Return the pathname for the actual file described by PATHNAME.
+  An error of type FILE-ERROR is signalled if no such file exists,
+  or the pathname is wild.
+
+  Under Unix, the TRUENAME of a broken symlink is considered to be
+  the name of the broken symlink itself."
+  (or (probe-file path)
+      (signal-file-error $err-no-file path)))
+
+(defun check-pathname-not-wild (path)
+  (when (wild-pathname-p path)
+    (error 'file-error :error-type "Inappropriate use of wild pathname ~s"
+	   :pathname path))
+  path)
+
+(defun probe-file (path)
+  "Return a pathname which is the truename of the file if it exists, or NIL
+  otherwise. An error of type FILE-ERROR is signaled if pathname is wild."
+  (check-pathname-not-wild path)
+  (let* ((native (native-translated-namestring path))
+         (realpath (%realpath native))
+         (kind (if realpath (%unix-file-kind realpath))))
+    ;; Darwin's #_realpath will happily return non-nil for
+    ;; files that don't exist.  I don't think that
+    ;; %UNIX-FILE-KIND would do so.
+    (when kind
+      (if (eq kind :directory)
+          (unless (eq (aref realpath (1- (length realpath))) #\/)
+            (setq realpath (%str-cat realpath "/"))))
+      (if realpath
+        (native-to-pathname realpath)
+        nil))))
+
+(defun cwd (path)  
+  (multiple-value-bind (realpath kind) (%probe-file-x (native-translated-namestring path))
+    (if kind
+      (if (eq kind :directory)
+	(let* ((error (%chdir realpath)))
+	  (if (eql error 0)
+	    (mac-default-directory)
+	    (signal-file-error error path)))
+	(error "~S is not a directory pathname." path))
+      (error "Invalid pathname : ~s." path))))
+
+(defun create-file (path &key (if-exists :error) (create-directory t))
+  (let* ((p (%create-file path :if-exists if-exists
+				      :create-directory create-directory)))
+    (and p
+         (native-to-pathname p))))
+
+(defun %create-file (path &key
+			 (if-exists :error)
+			 (create-directory t))
+  (when create-directory
+    (create-directory path))
+  (when (directory-pathname-p path)
+    (return-from %create-file (probe-file-x path)))
+  (assert (or (eql if-exists :overwrite)
+              (null if-exists)
+              (eq if-exists :error)
+              (not (probe-file path))) ()
+	  "~s ~s not implemented yet" :if-exists if-exists)
+  (let* ((unix-name (native-translated-namestring path))
+	 (fd (fd-open unix-name (logior #$O_WRONLY #$O_CREAT #$O_TRUNC
+                                        (if (or (null if-exists)
+                                                (eq if-exists :error))
+                                          #$O_EXCL
+                                          0)))))
+    (if (< fd 0)
+      (if (and (null if-exists)
+               (eql fd (- #$EEXIST)))
+        (return-from %create-file nil)
+        (signal-file-error fd path))
+      (fd-close fd))
+    (%realpath unix-name)))
+
+
+;; The following assumptions are deeply embedded in all our pathname code:
+;; (1) Non-logical pathname host is always :unspecific.
+;; (2) Logical pathname host is never :unspecific.
+;; (3) Logical pathname host can however be NIL, e.g. "foo;bar;baz".
+
+(defun %pathname-host (pathname)
+  (if (logical-pathname-p pathname)
+      (%logical-pathname-host pathname)
+      :unspecific))
+
+(defun %pathname-version (pathname)
+  (if (logical-pathname-p pathname)
+    (%logical-pathname-version pathname)
+    (%physical-pathname-version pathname)))
+
+
+
+(fset 'pathname-host (nfunction bootstrapping-pathname-host   ; redefined later in this file
+                                (lambda (thing)
+                                  (declare (ignore thing))
+                                  :unspecific)))
+
+(fset 'pathname-version (nfunction bootstrapping-pathname-version   ; redefined later in this file
+                                   (lambda (thing)
+                                     (declare (ignore thing))
+                                     nil)))
+
+(defmethod print-object ((pathname pathname) stream)
+  (let ((flags (if (logical-pathname-p pathname) 4
+                   (%i+ (if (eq (%pathname-type pathname) ':unspecific) 1 0)
+                        (if (equal (%pathname-name pathname) "") 2 0))))
+        (name (namestring pathname)))
+    (if (and (not *print-readably*) (not *print-escape*))
+      (write-string name stream)
+      (progn
+        (format stream (if (or *print-escape* (eql flags 0)) "#P" "#~DP") flags)
+        (write-escaped-string name stream #\")))))
+
+
+(defun mac-default-directory ()
+  (let* ((native-name (current-directory-name))
+	 (len (length native-name)))
+    (declare (fixnum len))
+    (when (and (> len 1)
+	       (not (eq #\/ (schar native-name (1- len)))))
+      (setq native-name (%str-cat native-name "/")))
+    (native-to-pathname native-name)))
+
+
+
+
+;;; I thought I wanted to call this from elsewhere but perhaps not
+(defun absolute-directory-list (dirlist)
+  ; just make relative absolute and remove ups where possible
+  (when (or (null dirlist) (eq (car dirlist) :relative))
+    (let ((default (mac-default-directory)) default-dir)
+      (when default
+        (setq default-dir (%pathname-directory default))
+        (when default-dir
+          (setq dirlist (append default-dir (cdr dirlist)))))))
+  (when (memq :up dirlist)
+    (setq dirlist (remove-up (copy-list dirlist))))
+  dirlist)
+
+; destructively mungs dir
+(defun remove-up (dir)
+  (setq dir (delete "." dir  :test #'string=))
+  (let ((n 0)
+        (last nil)
+        (sub dir)
+        has-abs kept-up)
+    ;; from %std-directory-component we get dir with :relative/:absolute stripped
+    (when (memq :up dir)
+      (when (memq (car dir) '(:relative :absolute))
+	(setq sub (cdr dir) n 1 has-abs t))
+      (do () ((null sub))
+	(cond ((eq (car sub) :up)
+	       (cond ((or (eq n 0)
+			  (and (stringp last)(string= last "**"))
+			  (eq last :wild-inferiors)
+			  kept-up
+			  (and has-abs (eq n 1)))
+		      ;; up after "**" stays, initial :up stays, how bout 2 :ups
+		      (setq kept-up t)
+		      )
+		     ((eq n 1) (setq dir (cddr dir) kept-up nil n -1))
+		     (t (rplacd (nthcdr (- n 2) dir) (cdr sub))
+			(setq n (- n 2) kept-up nil))))
+	      (t (setq kept-up nil)))
+	(setq last (car sub)
+	      n (1+ n) 
+	      sub (cdr sub))))
+    dir))
+
+(defun namestring (path)
+  "Construct the full (name)string form of the pathname."
+  (%str-cat (device-namestring path)
+            (host-namestring path)
+	    (directory-namestring path)
+	    (file-namestring path)))
+
+(defun device-namestring (path)
+  (let* ((device (pathname-device path)))
+    (if (and device (not (eq device :unspecific)))
+      (%str-cat device ":")
+      "")))
+
+(defun host-namestring (path)
+  "Return a string representation of the name of the host in the pathname."
+  (let ((host (pathname-host path)))
+    (if (and host (neq host :unspecific)) (%str-cat host ":") "")))
+
+(defun directory-namestring (path)
+  "Return a string representation of the directories used in the pathname."
+  (%directory-list-namestring (pathname-directory path)
+			      (neq (pathname-host path) :unspecific)))
+
+(defun ensure-directory-namestring (string)
+  (namestring (ensure-directory-pathname string)))
+
+(defun ensure-directory-pathname (pathname)
+  (let ((path (pathname pathname)))
+    (if (directory-pathname-p path)
+	path
+	(cons-pathname (append (or (pathname-directory path)
+				   ;; This makes sure "ccl:foo" maps to "ccl:foo;" (not
+				   ;; "ccl:;foo;"), but "foo" maps to "foo/" (not "/foo/").
+				   (if (eq (pathname-host path) :unspecific)
+				       '(:relative)
+				       '(:absolute)))
+			       ;; Don't use file-namestring, because that
+			       ;; includes the version for logical names.
+			       (list (file-namestring-from-parts
+				      (pathname-name path)
+				      (pathname-type path)
+				      nil)))
+		       nil nil (pathname-host path)))))
+
+(defun %directory-list-namestring (list &optional logical-p)
+  (if (null list)
+    ""
+    (let ((len (if (eq (car list) (if logical-p :relative :absolute)) 1 0))
+
+          result)
+      (declare (fixnum len)(optimize (speed 3)(safety 0)))
+      (dolist (s (%cdr list))
+        (case s
+          (:wild (setq len (+ len 2)))
+          (:wild-inferiors (setq len (+ len 3)))
+          (:up (setq len (+ len 3)))
+          (t ;This assumes that special chars in dir components are escaped,
+	     ;otherwise would have to pre-scan for escapes here.
+	   (setq len (+ len 1 (length s))))))
+      (setq result
+	    (make-string len))
+      (let ((i 0)
+            (sep (if logical-p #\; #\/)))
+        (declare (fixnum i))
+        (when (eq (%car list) (if logical-p :relative :absolute))
+          (setf (%schar result 0) sep)
+          (setq i 1))
+        (dolist (s (%cdr list))
+	  (case s
+	    (:wild (setq s "*"))
+	    (:wild-inferiors (setq s "**"))
+	    ;; There is no :up in logical pathnames, so this must be native
+	    (:up (setq s "..")))
+	  (let ((len (length s)))
+	    (declare (fixnum len))
+	    (move-string-bytes s result 0 i len)
+	    (setq i (+ i len)))
+	  (setf (%schar result i) sep)
+	  (setq i (1+ i))))
+      result)))
+
+(defun file-namestring (path)
+  "Return a string representation of the name used in the pathname."
+  (let* ((path (pathname path))
+         (name (pathname-name path))
+         (type (pathname-type path))
+         (version (if (typep path 'logical-pathname) (pathname-version path))))
+    (file-namestring-from-parts name type version)))
+
+(defun file-namestring-from-parts (name type version)
+  (when (eq version :unspecific) (setq version nil))
+  (when (eq type :unspecific) (setq type nil))
+  (%str-cat (case name
+	      ((nil :unspecific) "")
+	      (:wild "*")
+	      (t (%path-std-quotes name "*;:" ".")))
+	    (if (or type version)
+	      (%str-cat (case type
+			  ((nil) ".")
+			  (:wild ".*")
+			  (t (%str-cat "." (%path-std-quotes type "*;:" "."))))
+			(case version
+			  ((nil) "")
+			  (:newest ".newest")
+			  (:wild ".*")
+			  (t (%str-cat "." (if (fixnump version)
+					     (%integer-to-string version)
+					     version)))))
+	      "")))
+
+(defun enough-namestring (path &optional (defaults *default-pathname-defaults*))
+  "Return an abbreviated pathname sufficent to identify the pathname relative
+   to the defaults."
+  (if (null defaults)
+    (namestring path)
+    (let* ((dir (pathname-directory path))
+           (nam (pathname-name path))
+           (typ (pathname-type path))
+           (ver (pathname-version path))
+           (host (pathname-host path))
+           (logical-p (neq host :unspecific))
+           (default-dir (pathname-directory defaults)))
+      ;; enough-host-namestring
+      (setq host (if (and host
+                          (neq host :unspecific)
+                          (not (equalp host (pathname-host defaults))))
+                   (%str-cat host ":")
+                   ""))
+      ;; enough-directory-namestring
+      (cond ((equalp dir default-dir)
+             (setq dir '(:relative)))
+            ((and dir default-dir
+                  (eq (car dir) :absolute) (eq (car default-dir) :absolute))
+             ;; maybe make it relative to defaults             
+             (do ((p1 (cdr dir) (cdr p1))
+                  (p2 (cdr default-dir) (cdr p2)))
+                 ((or (null p2) (null p1) (not (equalp (car p1) (car p2))))
+                  (when (and (null p2) (or t (neq p1 (cdr dir))))
+                    (setq dir (cons :relative p1)))))))
+      (setq dir (%directory-list-namestring dir logical-p))
+      ;; enough-file-namestring
+      (when (or (equalp ver (pathname-version defaults))
+                (not logical-p))
+        (setq ver nil))
+      (when (and (null ver) (equalp typ (pathname-type defaults)))
+        (setq typ nil))
+      (when (and (null typ) (equalp nam (pathname-name defaults)))
+        (setq nam nil))
+      (setq nam (file-namestring-from-parts nam typ ver))
+      (%str-cat host dir nam))))
+
+(defun cons-pathname (dir name type &optional host version device)
+  (if (neq host :unspecific)
+    (%cons-logical-pathname dir name type host version)
+    (%cons-pathname dir name type version device)))
+
+(defun pathname (path)
+  "Convert thing (a pathname, string or stream) into a pathname."
+  (etypecase path
+    (pathname path)
+    (stream (%path-from-stream path))
+    (string (string-to-pathname path))))
+
+(defun %path-from-stream (stream)
+  (or (pathname (stream-filename stream))
+      (error "Can't determine pathname of ~S ." stream)))      ; ???
+
+;Like (pathname stream) except returns NIL rather than error when there's no
+;filename associated with the stream.
+(defun stream-pathname (stream &aux (path (stream-filename stream)))
+  (when path (pathname path)))
+
+(defun get-pathname-sstring (string &optional (start 0) (end (length string)))
+  #-windows-target
+  (get-sstring string start end)
+  #+windows-target
+  (multiple-value-bind (sstr start end)
+      (get-sstring string start end)
+    (declare (fixnum start end)
+             (simple-string sstr))
+    (if (do* ((i start (1+ i)))
+             ((= i end))
+          (declare (fixnum i))
+          (when (eql (schar sstr i) #\\)
+            (return t)))
+      (let* ((len (- end start))
+             (new (make-string len)))
+        (declare (fixnum len) (simple-string new))
+        (dotimes (i len)
+          (let* ((ch (schar sstr start)))
+            (if (eql ch #\\)
+              (setf (schar new i) #\/)
+              (setf (schar new i) ch)))
+          (incf start))
+        (values new 0 len))
+      (values sstr start end))))
+              
+(defun string-to-pathname (string &optional (start 0) (end (length string))
+                                            (reference-host nil)
+                                            (defaults *default-pathname-defaults*))
+  (require-type reference-host '(or null string))
+  (multiple-value-bind (sstr start end) (get-pathname-sstring string start end)
+    #-windows-target
+    (if (and (> end start)
+             (eql (schar sstr start) #\~))
+      (setq sstr (tilde-expand (subseq sstr start end))
+            start 0
+            end (length sstr)))
+    (let (directory name type host version device (start-pos start) (end-pos end) has-slashes)
+      (multiple-value-setq (host start-pos has-slashes) (pathname-host-sstr sstr start-pos end-pos))
+      (cond ((and host (neq host :unspecific))
+             (when (and reference-host (not (string-equal reference-host host)))
+               (error "Host in ~S does not match requested host ~S"
+                      (%substr sstr start end) reference-host)))
+            ((or reference-host
+		 (and defaults
+		      (neq (setq reference-host (pathname-host defaults)) :unspecific)))
+	     ;;If either a reference-host is specified or defaults is a logical pathname
+	     ;; then the string must be interpreted as a logical pathname.
+	     (when has-slashes
+	       (error "Illegal logical namestring ~S" (%substr sstr start end)))
+             (setq host reference-host)))
+      #+windows-target
+      (when (and (eq host :unspecific)
+                 (eql start-pos 0)
+                 (eql (position #\: sstr) 1))
+        (let* ((ch (schar sstr 0)))
+          (when (and (alpha-char-p ch)
+                     (standard-char-p ch))
+            (setq device (make-string 1 :initial-element ch)
+                  start-pos 2))))
+      (multiple-value-setq (directory start-pos) (pathname-directory-sstr sstr start-pos end-pos host))
+      (unless (eq host :unspecific)
+	(multiple-value-setq (version end-pos) (pathname-version-sstr sstr start-pos end-pos)))
+      (multiple-value-setq (type end-pos) (pathname-type-sstr sstr start-pos end-pos))
+      ;; now everything else is the name
+      (unless (eq start-pos end-pos)
+        (setq name (%std-name-component (%substr sstr start-pos end-pos))))
+      (if (eq host :unspecific)
+	(%cons-pathname directory name type (if name :newest) device)
+        (%cons-logical-pathname directory name type host version)))))
+
+(defun parse-namestring (thing &optional host (defaults *default-pathname-defaults*)
+                               &key (start 0) end junk-allowed)
+  (declare (ignore junk-allowed))
+  (unless (typep thing 'string)
+    (let* ((path (pathname thing))
+	   (pathname-host (pathname-host path)))
+      (when (and host pathname-host
+		 (or (eq pathname-host :unspecific) ;physical
+		     (not (string-equal host pathname-host))))
+	(error "Host in ~S does not match requested host ~S" path host))
+      (return-from parse-namestring (values path start))))
+  (when host
+    (verify-logical-host-name host))
+  (setq end (check-sequence-bounds thing start end))
+  (values (string-to-pathname thing start end host defaults) end))
+
+
+
+(defun %std-device-component (device host)
+  (when (and (or (null host) (eq host :unspecific))
+             (and device (not (eq device :unspecific))))
+    #+windows-target
+    (unless (and (typep device 'string)
+                 (eql (length device) 1)
+                 (alpha-char-p (char device 0))
+                 (standard-char-p (char device 0)))
+      (error "Invalid pathname device ~s" device))
+    device))
+    
+(defun make-pathname (&key (host nil host-p) 
+                           (device nil device-p)
+                           (directory nil directory-p)
+                           (name nil name-p)
+                           (type nil type-p)
+                           (version nil version-p)
+                           (defaults nil defaults-p) case
+                           &aux path)
+  "Makes a new pathname from the component arguments. Note that host is
+a host-structure or string."
+  (when case (setq case (require-type case pathname-case-type)))
+  (if (null host-p)
+    (let ((defaulted-defaults (if defaults-p defaults *default-pathname-defaults*)))
+      (setq host (if defaulted-defaults
+		   (pathname-host defaulted-defaults)
+		   :unspecific)))
+    (unless host (setq host :unspecific)))
+  (if directory-p 
+    (setq directory (%std-directory-component directory host)))
+  (if (and defaults (not directory-p))
+    (setq directory (pathname-directory defaults)))
+  (if (and defaults (not device-p))
+    (setq device (pathname-device defaults)))
+  (setq device (%std-device-component device host))
+  (setq name
+        (if name-p
+             (%std-name-component name)
+             (and defaults (pathname-name defaults))))
+  (setq type
+        (if type-p
+             (%std-type-component type)
+             (and defaults (pathname-type defaults))))
+  (setq version (if version-p
+                  (%logical-version-component version)
+		  (if name-p
+		    nil
+		    (and defaults (pathname-version defaults)))))
+  (setq path
+        (if (eq host :unspecific)
+          (%cons-pathname directory name type version device)
+          (%cons-logical-pathname
+	   (or directory
+	       (unless directory-p '(:absolute)))
+	   name type host version)))
+  (when (and (eq (car directory) :absolute)
+	     (member (cadr directory) '(:up :back)))
+    (error 'simple-file-error :pathname path :error-type "Second element of absolute directory component in ~s is ~s" :format-arguments (list (cadr directory))))
+  (let* ((after-wif (cadr (member :wild-inferiors directory))))
+    (when (member after-wif '(:up :back))
+          (error 'simple-file-error :pathname path :error-type "Directory component in ~s contains :WILD-INFERIORS followed by ~s" :format-arguments (list after-wif))))
+	 
+  (when (and case (neq case :local))
+    (setf (%pathname-directory path) (%reverse-component-case (%pathname-directory path) case)
+          (%pathname-name path) (%reverse-component-case (%pathname-name path) case)
+          (%pathname-type path) (%reverse-component-case (%pathname-type path) case)))
+  path)
+
+;;;  In portable CL, if the :directory argument to make pathname is a
+;;;  string, it should be the name of a top-level directory and should
+;;;  not contain any punctuation characters such as "/" or ";".  In
+;;;  MCL a string :directory argument with slashes or semi-colons will
+;;;  be parsed as a directory in the obvious way.
+(defun %std-directory-component (directory host)
+  (cond ((null directory) nil)
+        ((eq directory :wild) '(:absolute :wild-inferiors))
+        ((stringp directory) (%directory-string-list directory 0 (length directory) host))
+        ((listp directory)
+         ;Standardize the directory list, taking care not to cons if nothing
+         ;needs to be changed.
+         (let ((names (%cdr directory)) (new-names ()))
+           (do ((nn names (%cdr nn)))
+               ((null nn) (setq new-names (if new-names (nreverse new-names) names)))
+             (let* ((name (car nn))
+                    (new-name (%std-directory-part name)))
+               (unless (eq name new-name)
+                 (unless new-names
+                   (do ((new-nn names (%cdr new-nn)))
+                       ((eq new-nn nn))
+                     (push (%car new-nn) new-names))))
+               (when (or new-names (neq name new-name))
+                 (push new-name new-names))))
+           (when (memq :up (or new-names names))
+             (setq new-names (remove-up (copy-list (or new-names names)))))
+           (ecase (%car directory)
+             (:relative           
+                  (cond (new-names         ; Just (:relative) is the same as NIL. - no it isnt
+                         (if (eq new-names names)
+                           directory
+                           (cons ':relative new-names)))
+                        (t directory)))
+             (:absolute
+                  (cond ((null new-names) directory)  ; But just (:absolute) IS the same as NIL
+                        ((eq new-names names) directory)
+                        (t (cons ':absolute new-names)))))))
+        (t (report-bad-arg directory '(or string list (member :wild))))))
+
+(defun %std-directory-part (name)
+  (case name
+    ((:wild :wild-inferiors :up) name)
+    (:back :up)
+    (t (cond ((string= name "*") :wild)
+             ((string= name "**") :wild-inferiors)
+	     ((string= name "..") :up)
+             (t (%path-std-quotes name "/:;*" "/:;"))))))
+
+; this will allow creation of garbage pathname "foo:bar;bas:" do we care?
+(defun merge-pathnames (path &optional (defaults *default-pathname-defaults*)
+                                       (default-version :newest))
+  "Construct a filled in pathname by completing the unspecified components
+   from the defaults."
+  ;(declare (ignore default-version))
+  (when (not (pathnamep path))(setq path (pathname path)))
+  (when (and defaults (not (pathnamep defaults)))(setq defaults (pathname defaults)))
+  (let* ((path-dir (pathname-directory path))
+         (path-host (pathname-host path))
+         (path-name (pathname-name path))
+	 (path-type (pathname-type path))
+         (path-device (pathname-device path))
+         (default-dir (and defaults (pathname-directory defaults)))
+         (default-host (and defaults (pathname-host defaults)))
+         (default-device (and defaults (pathname-device defaults)))
+         ; take host from defaults iff path-dir is logical or absent - huh? 
+         (host (cond ((or (null path-host)  ; added 7/96
+                          (and (eq path-host :unspecific)
+                               (or (null path-dir)
+                                   (null (cdr path-dir))
+                                   (and (eq :relative (car path-dir))
+                                        (not (memq default-host '(nil :unspecific)))))))
+                          
+                      default-host)
+                     (t  path-host)))
+         (dir (cond ((null path-dir) default-dir)
+                    ((null default-dir) path-dir)
+                    ((eq (car path-dir) ':relative)
+                     (let ((the-dir (append default-dir (%cdr path-dir))))
+                       (when (memq ':up the-dir)(setq the-dir (remove-up (copy-list the-dir))))
+                       the-dir))
+                    (t path-dir)))
+         (nam (or path-name
+                  (and defaults (pathname-name defaults))))
+         (typ (or path-type
+                  (and defaults (pathname-type defaults))))
+         (version (or (pathname-version path)
+		      (cond ((not path-name)
+			     (or (and defaults (pathname-version defaults))
+                                 default-version))
+			    (t default-version))))
+         (device (or path-device default-device)))
+    (if (and (pathnamep path)
+             (eq dir (%pathname-directory path))
+             (eq nam path-name)
+             (eq typ (%pathname-type path))
+             (eq host path-host)
+             (eq device path-device)
+             (eq version (pathname-version path)))
+      path 
+      (cons-pathname dir nam typ host version device))))
+
+(defun directory-pathname-p (path)
+  (let ((name (pathname-name path))(type (pathname-type path)))
+    (and  (or (null name) (eq name :unspecific) (%izerop (length name)))
+          (or (null type) (eq type :unspecific)))))
+
+;In CCL, a pathname is logical if and only if pathname-host is not :unspecific.
+(defun pathname-host (thing &key case)
+  "Return PATHNAME's host."
+  (when (streamp thing)(setq thing (%path-from-stream thing)))
+  (when case (setq case (require-type case pathname-case-type)))
+  (let ((name
+         (typecase thing    
+           (logical-pathname (%logical-pathname-host thing))
+           (pathname :unspecific)
+           (string (multiple-value-bind (sstr start end) (get-pathname-sstring thing) 
+                     (pathname-host-sstr sstr start end)))
+           (t (report-bad-arg thing pathname-arg-type)))))
+    (if (and case (neq case :local))
+      (progn
+	(when (and (eq case :common) (neq name :unspecific)) (setq case :logical))
+	(%reverse-component-case name case))
+      name)))
+
+(defun pathname-host-sstr (sstr start end &optional no-check)
+  ;; A pathname with any (unescaped) /'s is always a physical pathname.
+  ;; Otherwise, if the pathname has either a : or a ;, then it's always logical.
+  ;; Otherwise, it's probably physical.
+  ;; Return :unspecific for physical, host string or nil for a logical.
+  (let* ((slash (%path-mem "/" sstr start end))
+	 (pos (and (not slash) (%path-mem ":;" sstr start end)))
+	 (pos-char (and pos (%schar sstr pos)))
+	 (host (and (eql pos-char #\:) (%substr sstr start pos))))
+    (cond (host
+	   (unless (or no-check (logical-host-p host))
+	     (error "~S is not a defined logical host" host))
+	   (values host (%i+ pos 1) nil))
+	  ((eql pos-char #\;) ; logical pathname with missing host
+	   (values nil start nil))
+	  (t ;else a physical pathname.
+	   (values :unspecific start slash)))))
+
+
+(defun pathname-device (thing &key case)
+  "Return PATHNAME's device."
+  (declare (ignore case))
+  (let* ((p (pathname thing)))
+    (etypecase p
+      (logical-pathname :unspecific)
+      (pathname (%physical-pathname-device p)))))
+
+
+
+;A directory is either NIL or a (possibly wildcarded) string ending in "/" or ";"
+;Quoted /'s are allowed at this stage, though will get an error when go to the
+;filesystem.
+(defun pathname-directory (path &key case)
+  "Return PATHNAME's directory."
+  (when (streamp path) (setq path (%path-from-stream path)))
+  (when case (setq case (require-type case pathname-case-type)))
+  (let* ((logical-p nil)
+	 (names (typecase path
+		  (logical-pathname (setq logical-p t) (%pathname-directory path))
+		  (pathname (%pathname-directory path))
+		  (string
+		   (multiple-value-bind (sstr start end) (get-pathname-sstring path)
+		     (multiple-value-bind (host pos2) (pathname-host-sstr sstr start end)
+		       (unless (eq host :unspecific) (setq logical-p t))
+                       #+windows-target
+                       (unless logical-p
+                         (if (and (> end 1)
+                                  (eql (schar sstr 1) #\:))
+                           (setq pos2 2)))
+                       (pathname-directory-sstr sstr pos2 end host))))
+		  (t (report-bad-arg path pathname-arg-type)))))
+    (if (and case (neq case :local))
+      (progn
+	(when (and (eq case :common) logical-p) (setq case :logical))
+	(%reverse-component-case names case))
+      names)))
+
+;; Must match pathname-directory-end below
+(defun pathname-directory-sstr (sstr start end host)
+  (if (and (eq host :unspecific)
+           (> end start)
+           (eql (schar sstr start) #\~))
+    (setq sstr (tilde-expand (subseq sstr start end))
+          start 0
+          end (length sstr)))
+  (let ((pos (%path-mem-last (if (eq host :unspecific) "/" ";") sstr start end)))
+    (if pos
+      (values 
+       (%directory-string-list sstr start (setq pos (%i+ pos 1)) host)
+       pos)
+      (values (and (neq host :unspecific)
+		   (neq start end)
+		   '(:absolute))
+	      start))))
+
+;; Must match pathname-directory-sstr above
+(defun pathname-directory-end (sstr start end)
+  (multiple-value-bind (host pos2) (pathname-host-sstr sstr start end)
+    (let ((pos (%path-mem-last (if (eq host :unspecific) "/" ";") sstr pos2 end)))
+      (if pos
+	(values (%i+ pos 1) host)
+	(values pos2 host)))))
+
+(defun %directory-string-list (sstr start &optional (end (length sstr)) host)
+  ;; Should use host to split by / vs. ; but for now suport both for either host,
+  ;; like the mac version. It means that ';' has to be quoted in unix pathnames.
+  (declare (ignore host))
+  ;This must cons up a fresh list, %expand-logical-directory rplacd's it.
+  (labels ((std-part (sstr start end)
+             (%std-directory-part (if (and (eq start 0) (eq end (length sstr)))
+                                    sstr (%substr sstr start end))))
+           (split (sstr start end)
+	     (unless (eql start end)
+	       (let ((pos (%path-mem "/;" sstr start end)))
+		 (if (eq pos start)
+		   (split sstr (%i+ start 1) end) ;; treat multiple ////'s as one.
+                   (cons (std-part sstr start (or pos end))
+                         (when pos
+                           (split sstr (%i+ pos 1) end))))))))
+    (unless (eq start end)
+      (let* ((slash-pos (%path-mem "/" sstr start end))
+	     (semi-pos (%path-mem ";" sstr start end))
+	     (pos (or slash-pos semi-pos)))
+	; this never did anything sensible but did not signal an error
+        (when (and slash-pos semi-pos)
+	  (error "Illegal directory string ~s" (%substr sstr start end)))
+        (if (null pos)
+	  (list :relative (std-part sstr start end))
+	  (let ((pos-char (%schar sstr pos)))
+	    (cons (if (eq pos start)
+		    (if (eq pos-char #\/) ':absolute ':relative)
+		    (if (eq pos-char #\/) ':relative ':absolute))
+		  (split sstr start end))))))))
+
+(defun pathname-version (path)
+  "Return PATHNAME's version."
+  (when (streamp path) (setq path (%path-from-stream path)))
+  (typecase path
+    (logical-pathname (%logical-pathname-version path))
+    (pathname (%physical-pathname-version path))
+    (string
+     (multiple-value-bind (sstr start end) (get-pathname-sstring path)
+       (multiple-value-bind (newstart host) (pathname-directory-end sstr start end)
+	 (if (eq host :unspecific)
+	   nil
+	   (values (pathname-version-sstr sstr newstart end))))))
+    (t (report-bad-arg path pathname-arg-type))))
+
+(defun pathname-version-sstr (sstr start end)
+  (declare (fixnum start end))
+  (let ((pos (%path-mem-last "." sstr start end)))
+    (if (and pos (%i> pos start) (%path-mem "." sstr start (%i- pos 1)))
+      (values (%std-version-component (%substr sstr (%i+ pos 1) end)) pos)
+      (values nil end))))
+
+(defun %std-version-component (v)
+  (cond ((or (null v) (eq v :unspecific)) v)
+	((eq v :wild) "*")
+	((string= v "") :unspecific)
+	((string-equal v "newest") :newest)
+	((every #'digit-char-p v) (parse-integer v))
+	(t (%path-std-quotes v "./:;*" "./:;"))))
+
+
+;A name is either NIL or a (possibly wildcarded, possibly empty) string.
+;Quoted /'s are allowed at this stage, though will get an error if go to the
+;filesystem.
+(defun pathname-name (path &key case)
+  "Return PATHNAME's name."
+  (when (streamp path) (setq path (%path-from-stream path)))
+  (when case (setq case (require-type case pathname-case-type)))
+  (let* ((logical-p nil)
+	 (name (typecase path
+		 (logical-pathname (setq logical-p t) (%pathname-name path))
+		 (pathname (%pathname-name path))
+		 (string
+		  (multiple-value-bind (sstr start end) (get-pathname-sstring path)
+		    (multiple-value-bind (newstart host) (pathname-directory-end sstr start end)
+		      (setq start newstart)
+		      (unless (eq host :unspecific)
+			(setq logical-p t)
+			(setq end (nth-value 1 (pathname-version-sstr sstr start end))))
+		      ;; TODO: -->> Need to make an exception so that ".emacs" is name with no type.
+		      ;;   -->> Need to make an exception so that foo/.. is a directory pathname,
+		      ;; for native.
+		      (setq end (or (%path-mem-last "." sstr start end) end));; strip off type
+		      (unless (eq start end)
+			(%std-name-component (%substr sstr start end))))))
+		 (t (report-bad-arg path pathname-arg-type)))))
+    (if (and case (neq case :local))
+      (progn
+	(when (and (eq case :common) logical-p) (setq case :logical))
+	(%reverse-component-case name case))
+      name)))
+
+(defun %std-name-component (name)
+  (cond ((or (null name) (eq name :unspecific) (eq name :wild)) name)
+        ((equal name "*") :wild)
+        (t (%path-std-quotes name "/:;*" "/:;"))))
+
+;A type is either NIL or a (possibly wildcarded, possibly empty) string.
+;Quoted :'s are allowed at this stage, though will get an error if go to the
+;filesystem.
+(defun pathname-type (path &key case)
+  "Return PATHNAME's type."
+  (when (streamp path) (setq path (%path-from-stream path)))
+  (when case (setq case (require-type case pathname-case-type)))
+  (let* ((logical-p nil)
+	 (name (typecase path
+		 (logical-pathname (setq logical-p t) (%pathname-type path))
+		 (pathname (%pathname-type path))
+		 (string
+		  (multiple-value-bind (sstr start end) (get-pathname-sstring path)
+		    (multiple-value-bind (newstart host) (pathname-directory-end sstr start end)
+		      (setq start newstart)
+		      (unless (eq host :unspecific)
+			(setq logical-p t)
+			(setq end (nth-value 1 (pathname-version-sstr sstr start end))))
+		      ;; TODO: -->> Need to make an exception so that ".emacs" is name with no type.
+		      ;;   -->> Need to make an exception so that foo/.. is a directory pathname,
+		      ;; for native.
+		      (pathname-type-sstr sstr start end))))
+		 (t (report-bad-arg path pathname-arg-type)))))
+    (if (and case (neq case :local))
+      (progn
+	(when (and (eq case :common) logical-p) (setq case :logical))
+	(%reverse-component-case name case))
+      name)))
+
+; assumes dir & version if any has been stripped away
+(defun pathname-type-sstr (sstr start end)
+  (let ((pos (%path-mem-last "." sstr start end)))
+    (if pos
+      (values (%std-type-component (%substr sstr (%i+ 1 pos) end)) pos)
+      (values nil end))))
+
+(defun %std-type-component (type)
+  (cond ((or (null type) (eq type :unspecific) (eq type :wild)) type)
+        ((equal type "*") :wild)
+        (t (%path-std-quotes type "./:;*" "./:;"))))
+
+(defun %std-name-and-type (native)
+  (let* ((end (length native))
+	 (pos (position #\. native :from-end t))
+	 (type (and pos
+		    (%path-std-quotes (%substr native (%i+ 1 pos) end)
+				      nil "/:;*")))
+	 (name (unless (eq (or pos end) 0)
+		 (%path-std-quotes (if pos (%substr native 0 pos) native)
+				   nil "/:;*"))))
+    (values name type)))
+
+(defun %reverse-component-case (name case)
+  (cond ((not (stringp name))
+         (if (listp name)
+           (mapcar #'(lambda (name) (%reverse-component-case name case))  name)
+           name))
+        #+advanced-studlification-feature
+        ((eq case :studly) (string-studlify name))
+	((eq case :logical)
+	 (if (every #'(lambda (ch) (not (lower-case-p ch))) name)
+	   name
+	   (string-upcase name)))
+        (t ; like %read-idiocy but non-destructive - need it be?
+         (let ((which nil)
+               (len (length name)))
+           (dotimes (i len)
+             (let ((c (%schar name i)))
+               (if (alpha-char-p c)
+                 (if (upper-case-p c)
+                   (progn
+                     (when (eq which :lower)(return-from %reverse-component-case name))
+                     (setq which :upper))
+                   (progn
+                     (when (eq which :upper)(return-from %reverse-component-case name))
+                     (setq which :lower))))))
+           (case which
+             (:lower (string-upcase name))
+             (:upper (string-downcase name))
+             (t name))))))
+
+;;;;;;; String-with-quotes utilities
+(defun %path-mem-last-quoted (chars sstr &optional (start 0) (end (length sstr)))
+  (while (%i< start end)
+    (when (and (%%str-member (%schar sstr (setq end (%i- end 1))) chars)
+               (%path-quoted-p sstr end start))
+      (return-from %path-mem-last-quoted end))))
+
+(defun %path-mem-last (chars sstr &optional (start 0) (end (length sstr)))
+  (while (%i< start end)
+    (when (and (%%str-member (%schar sstr (setq end (%i- end 1))) chars)
+               (not (%path-quoted-p sstr end start)))
+      (return-from %path-mem-last end))))
+
+(defun %path-mem (chars sstr &optional (start 0) (end (length sstr)))
+  (let ((one-char (when (eq (length chars) 1) (%schar chars 0))))
+    (while (%i< start end)
+      (let ((char (%schar sstr start)))
+        (when (if one-char (eq char one-char)(%%str-member char chars))
+          (return-from %path-mem start))
+        (when (eq char *pathname-escape-character*)
+          (setq start (%i+ start 1)))
+        (setq start (%i+ start 1))))))
+
+; these for \:  meaning this aint a logical host. Only legal for top level dir
+ 
+(defun %path-unquote-one-quoted (chars sstr &optional (start 0)(end (length sstr)))
+  (let ((pos (%path-mem-last-quoted chars sstr start end)))
+    (when (and pos (neq pos 1))
+      (cond ((or (%path-mem chars sstr start (1- pos))
+                 (%path-mem-last-quoted chars sstr start (1- pos)))
+             nil)
+            (t (%str-cat (%substr sstr start (1- pos))(%substr sstr  pos end)))))))
+
+(defun %path-one-quoted-p (chars sstr &optional (start 0)(end (length sstr)))
+  (let ((pos (%path-mem-last-quoted chars sstr start end)))
+    (when (and pos (neq pos 1))
+      (not (or (%path-mem-last-quoted chars sstr start (1- pos))
+               (%path-mem chars sstr start (1- pos)))))))
+ 
+(defun %path-quoted-p (sstr pos start &aux (esc *pathname-escape-character*) (q nil))
+  (while (and (%i> pos start) (eq (%schar sstr (setq pos (%i- pos 1))) esc))
+    (setq q (not q)))
+  q)
+
+
+
+;Standardize pathname quoting, so can do EQUAL.
+;; Subtle point: when keep-quoted is NIL, arg is assumed native,
+;; and therefore escape characters are made quoted.
+;; if keep-quoted is not NIL, e.g. if it's "", arg is assumed
+;;   to be escaped already, so escape chars are interpreted as quotes.
+;; Note that this can't be used to remove quotes because it
+;; always keeps the escape character quoted.
+(defun %path-std-quotes (arg keep-quoted make-quoted)
+  (when (symbolp arg)
+    (error "Invalid pathname component ~S" arg))
+  (let* ((str arg)
+         (esc *pathname-escape-character*)
+         (end (length str))
+         res-str char)
+    (multiple-value-bind (sstr start)(array-data-and-offset str)
+      (setq end (+ start end))
+      (let ((i start))
+        (until (eq i end)
+          (setq char (%schar sstr i))
+          (cond ((or (%%str-member char make-quoted)
+                     (and (null keep-quoted) (eq char esc)))
+                 (unless res-str
+                   (setq res-str (make-array (%i- end start)
+                                             :element-type (array-element-type sstr)
+                                             :adjustable t :fill-pointer 0))
+                   (do ((j start (%i+ j 1))) ((eq j i))
+                     (vector-push-extend (%schar sstr j) res-str)))
+                 (vector-push-extend esc res-str))
+                ((neq char esc) nil)
+                ((eq (setq i (%i+ i 1)) end)
+                 (error "Malformed pathname component string ~S" str))
+                ((or (eq (setq char (%schar sstr i)) esc)
+                     (%%str-member char keep-quoted))
+                 (when res-str (vector-push-extend esc res-str)))
+                (t
+                 (unless res-str
+                   (setq res-str (make-array (%i- end start)
+                                             :element-type (array-element-type sstr)
+                                             :adjustable t :fill-pointer 0))
+                   (do ((j start (%i+ j 1)) (end (%i- i 1))) ((eq j end))
+                     (vector-push-extend (%schar sstr j) res-str)))))
+          (when res-str (vector-push-extend char res-str))
+          (setq i (%i+ i 1)))
+        (ensure-simple-string (or res-str str))))))
+
+
+
+(defun %%str-member (char string)
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (dotimes (i (the fixnum (length string)))
+      (when (eq (%schar string i) char)
+        (return i)))))
+
+
+(defun file-write-date (path)
+  "Return file's creation date, or NIL if it doesn't exist.
+  An error of type file-error is signaled if file is a wild pathname"
+  (%file-write-date (native-translated-namestring path)))
+
+(defun file-author (path)
+  "Return the file author as a string, or NIL if the author cannot be
+  determined. Signal an error of type FILE-ERROR if FILE doesn't exist,
+  or FILE is a wild pathname."
+  (%file-author (native-translated-namestring path)))
+
+(defun touch (path)
+  (if (not (probe-file path))
+    (progn
+      (ensure-directories-exist path)
+      (if (or (pathname-name path)
+              (pathname-type path))
+        (create-file path)))
+    (%utimes (native-translated-namestring path)))
+  t)
+
+
+;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+; load, require, provide
+
+(defun find-load-file (file-name)
+  (let ((full-name (full-pathname file-name :no-error nil))
+        (kind nil))
+    (when full-name
+      (let ((file-type (pathname-type full-name))
+            (merged (pathname (merge-pathnames file-name))))
+        (if (and file-type (neq file-type :unspecific))
+          (values (probe-file full-name) merged (if (eq (pathname-host file-name) :unspecific) full-name file-name))
+          (let* ((source (merge-pathnames file-name *.lisp-pathname*))
+                 (fasl   (merge-pathnames file-name *.fasl-pathname*))
+                 (true-source (probe-file source))
+                 (true-fasl   (probe-file fasl)))
+            (cond (true-source
+                   (if (and true-fasl
+                            (> (file-write-date true-fasl)
+                               (file-write-date true-source)))
+                     (values true-fasl merged source)
+                     (values true-source merged source)))
+                  (true-fasl
+                   (values true-fasl merged fasl))
+                  ((and (multiple-value-setq (full-name kind)
+                          (let* ((realpath (%realpath (native-translated-namestring full-name))))
+                            (if realpath
+                              (%probe-file-x realpath ))))
+                        (eq kind :file))
+                   (values full-name merged file-name)))))))))
+
+
+
+
+
+(defun load (file-name &key (verbose *load-verbose*)
+                       (print *load-print*)
+                       (if-does-not-exist :error)
+		       (external-format :default))
+  "Load the file given by FILESPEC into the Lisp environment, returning
+   T on success.
+
+   Extension: :PRINT :SOURCE means print source as well as value"
+  (loop
+    (restart-case
+      (return (%load file-name verbose print if-does-not-exist external-format))
+      (retry-load ()
+                  :report (lambda (stream) (format stream "Retry loading ~s" file-name)))
+      (skip-load ()
+                 :report (lambda (stream) (format stream "Skip loading ~s" file-name))
+                 (return nil))
+      (load-other ()
+                  :report (lambda (stream) (format stream "Load other file instead of ~s" file-name))
+                  (return
+                   (load (choose-file-dialog)
+                         :verbose verbose
+                         :print print
+                         :if-does-not-exist if-does-not-exist))))))
+
+
+(defun %load (file-name verbose print if-does-not-exist external-format)
+  (let ((*load-pathname* file-name)
+        (*load-truename* file-name)
+        (source-file file-name)
+        ;; Don't bind these: let OPTIMIZE proclamations/declamations
+        ;; persist, unless debugging.
+        #|
+        (*nx-speed* *nx-speed*)
+        (*nx-space* *nx-space*)
+        (*nx-safety* *nx-safety*)
+        (*nx-debug* *nx-debug*)
+        (*nx-cspeed* *nx-cspeed*)
+        |#
+        )
+    (declare (special *load-pathname* *load-truename*))
+    (when (typep file-name 'string-input-stream)
+      (when verbose
+          (format t "~&;Loading from stream ~S..." file-name)
+          (force-output))
+      (let ((*package* *package*)
+            (*readtable* *readtable*))
+        (load-from-stream file-name print))
+      (return-from %load file-name))
+    (unless (streamp file-name)
+      (multiple-value-setq (*load-truename* *load-pathname* source-file)
+        (find-load-file (merge-pathnames file-name)))
+      (when (not *load-truename*)
+        (return-from %load (if if-does-not-exist
+                             (signal-file-error $err-no-file file-name))))
+      (setq file-name *load-truename*))
+    (let* ((*package* *package*)
+           (*readtable* *readtable*)
+           (*loading-files* (cons file-name (specialv *loading-files*)))
+           ;;reset by fasload to logical name stored in the file
+           (*loading-file-source-file* (namestring source-file))
+           (*loading-toplevel-location* nil))
+      (declare (special *loading-files* *loading-file-source-file*))
+      (when verbose
+	(format t "~&;Loading ~S..." *load-pathname*)
+	(force-output))
+      (cond ((fasl-file-p file-name)
+	     (let ((*fasload-print* print)
+		   (restart-setup nil)
+		   (restart-source nil)
+		   (restart-fasl nil))
+	       (declare (special *fasload-print*))
+	       (flet ((restart-test (c)
+			(unless restart-setup
+			  (setq restart-setup t)
+			  (let ((source *loading-file-source-file*)
+				(fasl *load-pathname*))
+			    (when (and (not (typep c 'file-error))
+				       source
+				       fasl
+				       (setq source (probe-file source))
+				       (setq fasl (probe-file fasl))
+				       (not (equalp source fasl)))
+			      (setq restart-fasl (namestring *load-pathname*)
+				    restart-source *loading-file-source-file*))))
+			(not (null restart-fasl)))
+		      (fname (p)
+			#-versioned-file-system
+			(namestring (make-pathname :version :unspecific :defaults p))
+			#+versioned-file-system
+			(namestring p)))
+		 (restart-case (multiple-value-bind (winp err) 
+				   (%fasload (native-translated-namestring file-name))
+				 (if (not winp) 
+				   (%err-disp err)))
+		   (load-source 
+		    ()
+		    :test restart-test
+		    :report (lambda (s) 
+			      (format s "Load ~s instead of ~s" 
+				      (fname restart-source) (fname restart-fasl)))
+		    (%load source-file verbose print if-does-not-exist external-format))
+		   (recompile
+		    ()
+		    :test restart-test
+		    :report (lambda (s)
+			      (let ((*print-circle* NIL))
+				(format s
+					(if (equalp
+					     restart-source
+					     (make-pathname :type (pathname-type *.lisp-pathname*)
+							    :defaults restart-fasl))
+					  "Compile ~s and then load ~s again"
+					  "Compile ~s into ~s then load ~:*~s again")
+					(fname restart-source) (fname restart-fasl))))
+		    (compile-file restart-source :output-file restart-fasl)
+		    (%load restart-fasl verbose print if-does-not-exist external-format))))))
+	    (t 
+	     (with-open-file (stream file-name
+				     :element-type 'base-char
+				     :external-format external-format)
+	       (load-from-stream stream print))))))
+  file-name)
+
+(defun load-from-stream (stream print &aux (eof-val (list ())) val)
+  (with-compilation-unit (:override nil) ; try this for included files
+    (let ((env (new-lexical-environment (new-definition-environment 'eval)))
+          ;; source note map to use with any compilations.
+          (*nx-source-note-map*  (and *save-source-locations*
+                                      (make-hash-table :test #'eq :shared nil)))
+          (*loading-toplevel-location* nil))
+      (%rplacd (defenv.type (lexenv.parent-env env)) *outstanding-deferred-warnings*)
+      (loop
+        (multiple-value-setq (val *loading-toplevel-location*)
+          (read-recording-source stream
+                                 :eofval eof-val
+                                 :file-name *loading-file-source-file*
+                                 :map *nx-source-note-map*
+                                 :save-source-text (neq *save-source-locations* :no-text)))
+        (when (eq eof-val val)
+          (return))
+        (when (eq print :source) (format t "~&Source: ~S~%" val))
+        (setq val (cheap-eval-in-environment val env))
+        (when print
+          (format t "~&~A~S~%" (if (eq print :source) "Value: " "") val))))))
+
+(defun include (filename)
+  (load
+   (if (null *loading-files*)
+     filename
+     (merge-pathnames filename (directory-namestring (car *loading-files*))))))
+
+(%fhave '%include #'include)
+
+(defun delete-file (path)
+  "Delete the specified FILE."
+  (let* ((namestring (native-translated-namestring path)))
+    (when (%realpath namestring)
+      (let* ((err (%delete-file namestring)))
+        (or (eql 0 err) (signal-file-error err path))))))
+
+(defvar *known-backends* ())
+
+(defun fasl-file-p (pathname)
+  (let* ((type (pathname-type pathname)))
+    (or (and (null *known-backends*)
+	     (equal type (pathname-type *.fasl-pathname*)))
+	(dolist (b *known-backends*)
+	  (when (equal type (pathname-type (backend-target-fasl-pathname b)))
+	    (return t)))
+        (ignore-errors
+          (with-open-file (f pathname
+                             :direction :input
+                             :element-type '(unsigned-byte 8))
+            ;; Assume that (potential) FASL files start with #xFF00 (big-endian),
+            ;; and that source files don't.
+            (and (eql (read-byte f nil nil) #xff)
+                 (eql (read-byte f nil nil) #x00)))))))
+
+(defun provide (module)
+  "Adds a new module name to *MODULES* indicating that it has been loaded.
+   Module-name is a string designator"
+  (pushnew (string module) *modules* :test #'string=)
+  module)
+
+(defparameter *loading-modules* () "Internal. Prevents circularity")
+(defparameter *module-provider-functions* '(module-provide-search-path module-provide-asdf)
+  "A list of functions called by REQUIRE to satisfy an unmet dependency.
+Each function receives a module name as a single argument; if the function knows how to load that module, it should do so, add the module's name as a string to *MODULES* (perhaps by calling PROVIDE) and return non-NIL."
+  )
+
+(defun module-provide-search-path (module)
+  ;; (format *debug-io* "trying module-provide-search-path~%")
+  (let* ((module-name (string module))
+         (pathname (find-module-pathnames module-name)))
+    (when pathname
+      (if (consp pathname)
+        (dolist (path pathname) (load path))
+        (load pathname))
+      (provide module))))
+
+(defun require (module &optional pathname)
+  "Loads a module, unless it already has been loaded. PATHNAMES, if supplied,
+   is a designator for a list of pathnames to be loaded if the module
+   needs to be. If PATHNAMES is not supplied, functions from the list
+   *MODULE-PROVIDER-FUNCTIONS* are called in order with MODULE-NAME
+   as an argument, until one of them returns non-NIL.  User code is
+   responsible for calling PROVIDE to indicate a successful load of the
+   module."
+  (let* ((str (string module))
+	 (original-modules (copy-list *modules*)))
+    (unless (or (member str *modules* :test #'string=)
+		(member str *loading-modules* :test #'string=))
+      ;; The check of (and binding of) *LOADING-MODULES* is a
+      ;; traditional defense against circularity.  (Another
+      ;; defense is not having circularity, of course.)  The
+      ;; effect is that if something's in the process of being
+      ;; REQUIREd and it's REQUIREd again (transitively),
+      ;; the inner REQUIRE is a no-op.
+      (let ((*loading-modules* (cons str *loading-modules*)))
+	(if pathname
+	  (dolist (path (if (atom pathname) (list pathname) pathname))
+	    (load path))
+	  (unless (some (lambda (p) (funcall p module))
+			*module-provider-functions*)
+	    (error "Module ~A was not provided by any function on ~S." module '*module-provider-functions*)))))
+    (values module
+	    (set-difference *modules* original-modules))))
+
+(defun find-module-pathnames (module)
+  "Returns the file or list of files making up the module"
+  (let ((mod-path (make-pathname :name (string-downcase module) :defaults nil)) path)
+        (dolist (path-cand *module-search-path* nil)
+	  (let ((mod-cand (merge-pathnames mod-path path-cand)))
+	    (if (wild-pathname-p path-cand)
+		(let* ((untyped-p (member (pathname-type mod-cand) '(nil :unspecific)))
+		       (matches (if untyped-p
+				    (or (directory (merge-pathnames mod-cand *.lisp-pathname*))
+					(directory (merge-pathnames mod-cand *.fasl-pathname*)))
+				    (directory mod-cand))))
+		  (when (and matches (null (cdr matches)))
+		    (return (if untyped-p
+				(make-pathname :type nil :defaults (car matches))
+				(car matches)))))
+		(when (setq path (find-load-file (merge-pathnames mod-path path-cand)))
+		  (return path)))))))
+
+(defun module-provide-asdf (module)
+  (let* ((asdf-package (find-package "ASDF")))
+    (when asdf-package
+      (let* ((verbose-out (find-symbol "*VERBOSE-OUT*" asdf-package))
+             (find-system (find-symbol "FIND-SYSTEM" asdf-package))
+             (operate (find-symbol "OPERATE" asdf-package))
+             (load-op (find-symbol "LOAD-OP" asdf-package)))
+        (when (and verbose-out find-system operate load-op)
+          (progv (list verbose-out) (list (make-broadcast-stream))
+            (let* ((system (funcall find-system module nil)))
+              (when system
+                (funcall operate load-op module)
+                t))))))))
+
+(defun wild-pathname-p (pathname &optional field-key)
+  "Predicate for determining whether pathname contains any wildcards."
+  (flet ((wild-p (name) (or (eq name :wild)
+                            (eq name :wild-inferiors)
+                            (and (stringp name) (%path-mem "*" name)))))
+    (case field-key
+      ((nil)
+       (or (some #'wild-p (pathname-directory pathname))
+           (wild-p (pathname-name pathname))
+           (wild-p (pathname-type pathname))
+           (wild-p (pathname-version pathname))))
+      (:host nil)
+      (:device nil)
+      (:directory (some #'wild-p (pathname-directory pathname)))
+      (:name (wild-p (pathname-name pathname)))
+      (:type (wild-p (pathname-type pathname)))
+      (:version (wild-p (pathname-version pathname)))
+      (t (wild-pathname-p pathname
+                          (require-type field-key 
+                                        '(member nil :host :device 
+                                          :directory :name :type :version)))))))
Index: /branches/new-random/level-1/l1-format.lisp
===================================================================
--- /branches/new-random/level-1/l1-format.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-format.lisp	(revision 13309)
@@ -0,0 +1,444 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; L1-format.lisp
+;
+; This file contains the definition for SUB-FORMAT, the dispatching part
+; of FORMAT. It also contains an interim definition for FORMAT and a few
+; incompletely implemented directives.
+
+(in-package "CCL")
+
+(eval-when (eval compile #-bccl load)  ;Load-time as well so CCL can use it.
+  (defmacro defformat (char name &rest def)
+    `(progn
+       (add-format-char ,char (nfunction ,name (lambda . ,def)))
+       ',name))
+  )
+
+(defparameter *format-char-table* (let* ((x (make-array 128 :initial-element nil))) x))
+
+(defun add-format-char (char def)
+  (unless (and (characterp char) (%i< (%char-code char) 128))
+    (report-bad-arg char 'standard-char))
+  (setf (svref *format-char-table* (%char-code (char-upcase char))) def))
+
+(proclaim '(special *format-original-arguments*   ;For ~*
+                    *format-arguments*            ;For pop-format-arg
+                    *format-control-string*       ;For ~?, ~{
+                    *format-index*
+                    *format-length*
+                    *format-pprint*               ;~I,~W,~_,~:T seen?
+                    *format-justification-semi*   ;~<..~:;..~> seen?
+            ))
+
+(defun pop-format-arg (&aux (args *format-arguments*))
+  (if (null args)
+    (format-error "Missing argument"))
+  (progn
+    (setq *format-arguments* (cdr args))
+    (%car args)))
+ 
+;SUB-FORMAT parses (a range of) the control string, finding the directives
+;and applying them to their parameters.
+;Implicit arguments to SUB-FORMAT: *format-control-string*, *format-arguments*,
+;*format-original-arguments*, *standard-output*, *format-char-table*
+;*format-control-string* must be a simple string.
+;Directive functions' arglist should be (colon-p atsign-p &rest params)
+;In addition when the directive is called, *format-index* and *format-length*
+;are bound to start and end pos (in *format-control-string*) of the rest of the
+; control string.  The directive may modify *format-index*, but not
+; *format-control-string* and *format-length*, before returning.
+
+(defun sub-format (stream *format-index* *format-length* &aux char)
+  (prog* ((string (require-type *format-control-string* 'simple-string))
+          (length *format-length*)
+          (i *format-index*)
+          (lastpos i))
+    (declare (fixnum i length lastpos) (type simple-string string))
+    (go START)
+    EOF-ERROR
+    (setq *format-index* *format-length*)
+    (format-error "Premature end of control string")
+    START
+    (do* ()
+         ((= i length) (unless (= i lastpos) 
+                         (write-string string stream :start  lastpos :end i)))
+      (setq char (schar string i) i (1+ i))
+      (when (eq char #\~)
+        (let* ((limit (the fixnum (1- i))))
+          (unless (= limit lastpos) 
+            (write-simple-string string stream  lastpos limit)))
+        (let ((params nil) (fn) (colon nil) (atsign nil))
+          (block nil
+            (tagbody
+              NEXT
+              (if (= i length) (go EOF-ERROR))
+              (setq char (schar string i) i (1+ i))
+              (cond ((eq char #\#)
+                     (push (list-length *format-arguments*) params))
+                    ((eq char #\')
+                     (if (= i length) (go EOF-ERROR))
+                     (push (schar string i) params)
+                     (incf i))
+                    ((eq char #\,)
+                     (push nil params)
+                     (go NEXT))
+                    ((or (eq char #\V) (eq char #\v))
+                     (push (pop-format-arg) params))
+                    ((or (eq char #\-) (eq char #\+) (digit-char-p char))
+                     (let ((start (%i- i 1)) n)
+                       (loop
+                         (when (= i length) (go EOF-ERROR))
+                         (unless (digit-char-p (schar string i)) (return))
+                         (incf i))
+                       (when (null (setq n (%parse-number-token string start i)))
+                         (setq *format-index* i)
+                         (format-error "Illegal parameter"))
+                       (push n params)))
+                    (t (return)))
+              (if (= i length) (go EOF-ERROR))
+              (setq char (schar string i) i (1+ i))
+              (when (neq char #\,) (return))
+              (go NEXT)))
+          (cond ((eq char #\:) 
+                 (if (= i length) (go EOF-ERROR))
+                 (setq colon t char (schar string i) i (1+ i))
+                 (when (eq char #\@)
+                   (if (= i length) (go EOF-ERROR))                     
+                   (setq atsign t char (schar string i) i (1+ i))))
+                ((eq char #\@)
+                 (if (= i length) (go EOF-ERROR))
+                 (setq atsign t char (schar string i) i (1+ i))
+                 (when (eq char #\:)
+                   (if (= i length) (go EOF-ERROR))
+                   (setq colon t char (schar string i) i (1+ i)))))
+          (setq *format-index* (%i- i 1))
+          (if (setq fn (svref *format-char-table* (%char-code (char-upcase char))))
+            (apply fn stream colon atsign (nreverse params))
+            (format-error "Unknown directive"))
+          (setq i (%i+ *format-index* 1)
+                lastpos i))))))
+
+
+#||
+(eval-when (load)
+  ;The non-consing version.
+(defun sub-format (stream *format-index* *format-length*)
+  (declare (special *format-index* *format-length*))
+  (old-lap-inline (stream)
+    (preserve_regs #(asave0 asave1 dsave0 dsave1 dsave2))
+    (defreg Control-string asave0 Index dsave0 Length dsave1 NumParams dsave2 Stream asave1)
+    (move.l acc Stream)
+    (move.l (special *format-index*) Index)       ; *format-index*
+    (move.l (special *format-length*) Length)      ; *format-length*
+    (specref *format-control-string*)
+    (move.l acc Control-string)
+
+    ;Make sure everything is in bounds, so don't have to worry about
+    ;boxing, bounds checking, etc.
+start
+    (movereg Control-string arg_z)
+    (jsr_subprim $sp-length)
+    (ccall <= '0 Index Length acc)
+    (cmp.l nilreg acc)
+    (beq done)
+    (move.l Index db)
+    (loop#
+      (if# (eq Length Index)
+        (cmp.l db Index)
+        (beq done)
+        (ccall 'stream-write-string Stream Control-string db Index)
+        (bra done))
+      (move.l Index da)
+      (getint da)
+      (move.l ($ $t_imm_char 0) acc)
+      (move.b (Control-string da.l $v_data) acc)
+      (add.l (fixnum 1) Index)
+      (cmp.b ($ #\~) acc)
+      (beq tilde))
+
+nextchar
+    (if# (eq Length Index)
+      (move.l '"Premature end of format control string" arg_z)
+      (add.w ($ 4) sp)                  ; flush internal bsr.
+      (bra error))
+    (move.l Index da)
+    (getint da)
+    (move.b (Control-string da.l $v_data) acc)
+    (add.l (fixnum 1) Index)
+    (if# (and (ge (cmp.b ($ #\a) acc)) (le (cmp.b ($ #\z) acc)))
+      (sub.b ($ 32) acc))
+    (rts)
+
+tilde
+    (move.l Index da)
+    (sub.l (fixnum 1) da)
+    (if# (not (eq da db))      
+      (ccall 'stream-write-string Stream Control-string db da))
+    (vpush Stream)
+    (vpush nilreg)             ;assume no :
+    (vpush nilreg)             ;assume no @
+    (move.l (fixnum 3) NumParams)
+do-param
+    (bsr nextchar)
+    (if# (or (eq (cmp.b ($ #\+) acc))
+             (eq (cmp.b ($ #\-) acc))
+             (and (ge (cmp.b ($ #\0) acc)) (le (cmp.b ($ #\9) acc))))
+      (move.l Index da)
+      (sub.l (fixnum 1) da)
+      (vpush da)
+      (prog#
+       (bsr nextchar)
+       (until# (or (lt (cmp.b ($ #\0) acc)) (gt (cmp.b ($ #\9) acc)))))
+      (sub.l (fixnum 1) Index)   ;unread the non-digit char
+      (ccall %parse-number-token Control-string vsp@+ Index)
+      (cmp.l nilreg acc)
+      (bne push-param)
+      (move.l '"Illegal format parameter" arg_z)
+      (bra error))
+
+    (if# (eq (cmp.b ($ #\#) acc))
+      (move.l (special *format-arguments*) acc)
+      (jsr_subprim $sp-length)
+      (bra push-param))
+
+    (if# (eq (cmp.b ($ #\') acc))
+      (bsr nextchar)
+      (move.l ($ $t_imm_char 0) acc)
+      (move.b (Control-string da.l $v_data) acc)  ;Get the non-uppercased version...
+      (swap acc)
+      (bra push-param))
+
+    (if# (eq (cmp.b ($ #\,) acc))
+      (sub.l (fixnum 1) Index)   ;Re-read the comma.
+      (move.l nilreg acc)
+      (bra push-param))
+
+    (if# (eq (cmp.b ($ #\V) acc))
+      (ccall 'pop-format-arg)
+      ;(bra push-param)
+     push-param
+      (vpush acc)
+      (add.l (fixnum 1) NumParams)
+      (bsr nextchar)
+      (cmp.b ($ #\,) acc)
+      (beq do-param))
+
+    (move.l NumParams nargs)
+    (vscale.l nargs)
+    (cmp.b ($ #\:) acc)
+    (if# eq
+      (bsr nextchar)
+      (cmp.b ($ #\@) acc)
+      (bne @a)
+      (move.l (a5 $t) (vsp nargs.w -12))
+     else#
+      (cmp.b ($ #\@) acc)
+      (bne @b)
+      (move.l (a5 $t) (vsp nargs.w -12))
+      (bsr nextchar)
+      (cmp.b ($ #\:) acc)
+      (bne @b))
+    (bsr nextchar)
+@a  (move.l (a5 $t) (vsp nargs.w -8))
+@b  (moveq 127 da)
+    (and.w acc da)
+    (bif (ne (cmp.b da acc)) nofun)
+    (lsl.w 2 da)
+    (move.l (special *format-char-table*) atemp0)
+    (move.l (atemp0 da.w $v_data) atemp0)
+    (cmp.l atemp0 nilreg)
+    (beq nofun)
+    (move.l Index da)
+    (sub.l (fixnum 1) da)
+    (move.l da (special *format-index*))
+    (move.l NumParams nargs)
+    (vscale.l nargs)                    ; at least 3 args.
+    (movem.l vsp@+ #(arg_z arg_y arg_x))
+    (jsr_subprim $sp-funcall)
+    (specref '*format-index*)
+    (add.l (fixnum 1) acc)
+    (move.l acc Index)
+    (bra start)
+
+nofun
+    (move.l '"Unknown format directive" acc)
+error
+    (move.l Index (special *format-index*))
+    (fsymevalapply 'format-error 1)
+
+done
+    (restore_regs)
+    ))
+) ;end of eval-when (load)
+
+||#
+
+;;;Interim definitions
+
+;;;This function is shadowed by CCL in order to use ~{ to print error messages.
+(fset 'format 
+      (nlambda bootstrapping-format (stream control-string &rest format-arguments)
+        (declare (dynamic-extent format-arguments))
+        (block format
+          (when (null stream)
+            (return-from format 
+              (with-output-to-string (x)
+                (apply #'format x control-string format-arguments))))
+          (if (eq stream t)
+            (setq stream *standard-output*)
+            (unless (streamp stream) (report-bad-arg stream 'stream)))
+          (if (functionp control-string)
+            (apply control-string stream format-arguments)
+            (progn
+              (setq control-string (ensure-simple-string control-string))
+              (let* ((*format-original-arguments* format-arguments)
+                     (*format-arguments* format-arguments)
+                     (*format-control-string* control-string))
+                (catch 'format-escape
+                  (sub-format stream 0 (length control-string)))
+                nil))))))
+
+(fset 'format-error
+      (nlambda bootstrapping-format-error (&rest args)
+        (format t "~&FORMAT error at position ~A in control string ~S "
+                *format-index* *format-control-string*)
+        (apply #'error args)))
+
+(defun format-no-flags (colon atsign)
+  (cond ((and colon atsign)
+         (format-error "Flags not allowed"))
+        (colon
+         (format-error ": flag not allowed"))
+        (atsign
+         (format-error "@ flag not allowed"))))
+
+;Redefined later
+(defformat #\A format-a (stream colon atsign)
+   (declare (ignore colon atsign))
+   (princ (pop-format-arg) stream))
+
+;Redefined later
+(defformat #\S format-s (stream colon atsign)
+  (declare (ignore colon atsign))
+  (prin1 (pop-format-arg) stream))
+
+;Redefined later
+(defformat #\^ format-escape (stream colon atsign)
+  (declare (ignore stream colon atsign))
+  (throw 'format-escape t))
+
+;Final version
+(defformat #\% format-% (stream colon atsign &optional repeat-count)
+  (format-no-flags colon atsign)
+  (cond ((or (not repeat-count)
+             (and (fixnump repeat-count)
+                  (> repeat-count -1)))
+         (dotimes (i (or repeat-count 1)) (declare (fixnum i)) (terpri stream)))
+        (t (format-error "Bad repeat-count."))))
+
+;Final version
+(defformat #\& format-& (stream colon atsign &optional repeat-count)
+  (format-no-flags colon atsign)
+  (cond ((or (not repeat-count)
+             (and (fixnump repeat-count)
+                  (> repeat-count -1)))
+         (unless (eq repeat-count 0)
+           (fresh-line stream)
+           (dotimes (i (1- (or repeat-count 1))) (declare (fixnum i)) (terpri stream))))
+        (t (format-error "Bad repeat-count."))))
+
+;Final version
+(defformat #\~ format-~ (stream colon atsign &optional repeat-count)
+  (format-no-flags colon atsign)
+  (cond ((or (not repeat-count)
+             (and (fixnump repeat-count)
+                  (> repeat-count -1)))
+         (dotimes (i (or repeat-count 1)) (declare (fixnum i)) (write-char #\~ stream)))
+        (t (format-error "Bad repeat-count."))))
+
+;Final version
+(defformat #\P format-p (stream colon atsign)
+  (when colon
+     (let ((end *format-arguments*) (list *format-original-arguments*))
+        (tagbody loop
+           (if list
+             (when (neq (cdr list) end)
+               (setq list (%cdr list))
+               (go loop))
+             (format-error "No previous argument")))
+        (setq *format-arguments* list)))
+   (%write-string (if (eq (pop-format-arg) 1)
+                    (if atsign "y" "")
+                    (if atsign "ies" "s"))
+                  stream))
+
+;Final version
+(defformat #\* format-* (stream colon atsign &optional count)
+  (declare (ignore stream)(special *circularity-hash-table*))
+  (let* ((orig *format-original-arguments*)
+         (where (- (list-length orig)   ; will error if args circular
+                   (list-length *format-arguments*)))
+         (to (if atsign 
+               (progn
+                 (format-no-flags colon nil)
+                 (or count 0)) ; absolute
+               (progn
+                 (when (null count)(setq count 1))
+                 (when colon (setq count (- count)))
+                 (%i+ where count))))
+         (args (nthcdr-no-overflow to orig)))
+    ; avoid bogus circularity indication
+    (when (and nil (consp args) (<= to where) *circularity-hash-table*)
+      ; copy only from to thru where in case  some real shared structure
+      (let ((l args) new)
+        (dotimes (i (1+  (- where to)))
+          (declare (fixnum i))
+          (push (car l) new)
+          (setq l (cdr l)))
+        (setq args (nreconc new (nthcdr (1+ where) orig))))) ;(copy-list args)))
+    (setq *format-arguments* args)))
+
+; Redefined later.
+(defformat #\Newline format-newline (&rest ignore)
+  (declare (ignore ignore))
+  (do* ((i *format-index* (1+ i))
+        (s *format-control-string*)
+        (n *format-length*))
+       ((or (= i n)
+            (not (whitespacep (schar s i))))
+        (setq *format-index* (1- i)))))
+
+(defun nthcdr-no-overflow (count list)
+  (if (or (> count (list-length list)) (< count 0))
+    (format-error "non-existent target for ~*")
+    (nthcdr count list)))
+
+;Redefined later
+(defformat #\X format-x (stream colon atsign)
+  (declare (ignore colon atsign))
+  (let* ((*print-base* 16.)
+         (*print-radix* nil))
+    (prin1 (pop-format-arg) stream)))
+
+;Redefined later
+(defformat #\D format-d (stream colon atsign &rest ignore)
+  (declare (ignore colon atsign ignore))
+  (let* ((*print-base* 10.)
+         (*print-radix* nil))
+    (prin1 (pop-format-arg) stream)))
Index: /branches/new-random/level-1/l1-init.lisp
===================================================================
--- /branches/new-random/level-1/l1-init.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-init.lisp	(revision 13309)
@@ -0,0 +1,329 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute :load-toplevel)
+
+(defconstant most-positive-short-float (make-short-float-from-fixnums (1- (ash 1 23)) 254 0))
+(defconstant most-negative-short-float (make-short-float-from-fixnums (1- (ash 1 23)) 254 -1))
+(defconstant most-positive-single-float (make-short-float-from-fixnums (1- (ash 1 23)) 254 0))
+(defconstant most-negative-single-float (make-short-float-from-fixnums (1- (ash 1 23)) 254 -1))
+
+
+(defconstant least-positive-short-float (make-short-float-from-fixnums 1 0 0))
+(defconstant least-negative-short-float (make-short-float-from-fixnums 1 0 -1))
+(defconstant least-positive-single-float (make-short-float-from-fixnums 1 0 0))
+(defconstant least-negative-single-float (make-short-float-from-fixnums 1 0 -1))
+
+(defconstant short-float-epsilon (make-short-float-from-fixnums 1 103 0))
+(defconstant short-float-negative-epsilon (make-short-float-from-fixnums 1 102 0))
+(defconstant single-float-epsilon (make-short-float-from-fixnums 1 103 0))
+(defconstant single-float-negative-epsilon (make-short-float-from-fixnums 1 102 0))
+
+(defconstant least-positive-normalized-short-float (make-short-float-from-fixnums 1 1 0))
+(defconstant least-negative-normalized-short-float (make-short-float-from-fixnums 1 1 -1))
+(defconstant least-positive-normalized-single-float (make-short-float-from-fixnums 1 1 0))
+(defconstant least-negative-normalized-single-float (make-short-float-from-fixnums 1 1 -1))
+
+(let ((bigfloat (make-float-from-fixnums #x1ffffff #xfffffff #x7fe 0)))
+  ; do it this way if you want to be able to compile before reading floats works  
+  (defconstant most-positive-double-float bigfloat)
+  (defconstant most-positive-long-float bigfloat)
+  )
+
+(let ((littleposfloat (make-float-from-fixnums 0 1 0 0 )))
+  (defconstant least-positive-double-float littleposfloat)
+  (defconstant least-positive-long-float littleposfloat)
+  )
+
+(let ((littlenegfloat (make-float-from-fixnums 0 1 0 -1)))  
+  (defconstant least-negative-double-float littlenegfloat)
+  (defconstant least-negative-long-float littlenegfloat)
+  )
+
+(let ((bignegfloat (make-float-from-fixnums #x1ffffff #xfffffff #x7fe -1)))
+  (defconstant most-negative-double-float bignegfloat)
+  (defconstant most-negative-long-float bignegfloat)
+  )
+
+(let ((eps (make-float-from-fixnums #x1000000 1 #x3ca 0))) ;was wrong
+  (defconstant double-float-epsilon eps)
+  (defconstant long-float-epsilon eps)
+  )
+
+(let ((eps- (make-float-from-fixnums #x1000000 1 #x3c9 1)))
+  (defconstant double-float-negative-epsilon eps-)
+  (defconstant long-float-negative-epsilon eps-)
+  )
+
+(let ((norm (make-float-from-fixnums 0 0 1 0)))
+  (defconstant least-positive-normalized-double-float norm)
+  (defconstant least-positive-normalized-long-float norm)
+  )
+
+(let ((norm- (make-float-from-fixnums 0 0 1 -1)))
+  (defconstant least-negative-normalized-double-float norm-)
+  (defconstant least-negative-normalized-long-float norm-)
+  )
+
+(defconstant pi (make-float-from-fixnums #x921fb5 #x4442d18 #x400 0))
+
+)
+
+
+
+(defconstant boole-clr 0
+  "Boole function op, makes BOOLE return 0.")
+(defconstant boole-set 1
+  "Boole function op, makes BOOLE return -1.")
+(defconstant boole-1 2
+  "Boole function op, makes BOOLE return integer1.")
+(defconstant boole-2 3
+  "Boole function op, makes BOOLE return integer2.")
+(defconstant boole-c1 4
+  "Boole function op, makes BOOLE return complement of integer1.")
+(defconstant boole-c2 5
+  "Boole function op, makes BOOLE return complement of integer2.")
+(defconstant boole-and 6
+  "Boole function op, makes BOOLE return logand of integer1 and integer2.")
+(defconstant boole-ior 7
+  "Boole function op, makes BOOLE return logior of integer1 and integer2.")
+(defconstant boole-xor 8
+  "Boole function op, makes BOOLE return logxor of integer1 and integer2.")
+(defconstant boole-eqv 9
+  "Boole function op, makes BOOLE return logeqv of integer1 and integer2.")
+(defconstant boole-nand 10
+  "Boole function op, makes BOOLE return log nand of integer1 and integer2.")
+(defconstant boole-nor 11
+  "Boole function op, makes BOOLE return lognor of integer1 and integer2.")
+(defconstant boole-andc1 12
+  "Boole function op, makes BOOLE return logandc1 of integer1 and integer2.")
+(defconstant boole-andc2 13
+  "Boole function op, makes BOOLE return logandc2 of integer1 and integer2.")
+(defconstant boole-orc1 14
+  "Boole function op, makes BOOLE return logorc1 of integer1 and integer2.")
+(defconstant boole-orc2 15
+  "Boole function op, makes BOOLE return logorc2 of integer1 and integer2.")
+
+
+
+(defconstant internal-time-units-per-second #+64-bit-target 1000000 #-64-bit-target 1000
+  "The number of internal time units that fit into a second. See
+  GET-INTERNAL-REAL-TIME and GET-INTERNAL-RUN-TIME.")
+
+(defconstant char-code-limit #.(arch::target-char-code-limit
+                                (backend-target-arch *target-backend*))
+  "the upper exclusive bound on values produced by CHAR-CODE")
+
+(defconstant array-rank-limit (floor #x8000 target::node-size)
+  "the exclusive upper bound on the rank of an array")
+(defconstant multiple-values-limit 200
+  "The exclusive upper bound on the number of multiple VALUES that you can
+  return.")
+(defconstant lambda-parameters-limit (floor #x8000 target::node-size)
+  "The exclusive upper bound on the number of parameters which may be specifed
+  in a given lambda list. This is actually the limit on required and &OPTIONAL
+  parameters. With &KEY and &AUX you can get more.")
+(defconstant call-arguments-limit (floor #x8000 target::node-size)
+  "The exclusive upper bound on the number of arguments which may be passed
+  to a function, including &REST args."
+)
+
+; Currently, vectors can be at most (expt 2 22) bytes, and
+; the largest element (double-float or long-float) is 8 bytes:
+#| to get largest element size...
+(apply #'max (mapcar #'(lambda (type)
+                         (%vect-byte-size (make-array 1 :element-type type)))
+                     *cl-types*))
+|#
+
+(defconstant array-dimension-limit array-total-size-limit
+  "the exclusive upper bound on any given dimension of an array")
+
+(defconstant most-positive-fixnum target::target-most-positive-fixnum
+  "the fixnum closest in value to positive infinity")
+(defconstant most-negative-fixnum target::target-most-negative-fixnum
+  "the fixnum closest in value to negative infinity")
+
+
+(defconstant lambda-list-keywords 
+  '(&OPTIONAL &REST &AUX &KEY &ALLOW-OTHER-KEYS &BODY &ENVIRONMENT &WHOLE)
+  "symbols which are magical in a lambda list")
+
+(defstatic *type-system-initialized* nil)
+
+(defparameter %toplevel-catch% ':toplevel)
+
+(defvar *read-default-float-format* 'single-float)
+
+(defvar *read-suppress* nil
+  "Suppress most interpreting in the reader when T.")
+
+(defvar *read-base* 10.
+  "the radix that Lisp reads numbers in")
+
+
+(defparameter *warn-if-redefine-kernel* nil
+  "When true, attempts to redefine (via DEFUN or DEFMETHOD) functions and
+methods that are marked as being predefined signal continuable errors.")
+
+(defvar *next-screen-context-lines* 2 "Number of lines to show of old screen
+  after a scroll-up or scroll-down.")
+
+(defparameter *compiling-file* nil 
+  "Name of outermost file being compiled or NIL if not compiling a file.")
+
+(defvar *eval-fn-name* nil)
+
+
+(defvar *compile-definitions* t
+  "When non-NIL and the evaluator's lexical environment contains no
+  lexical entities, causes FUNCTION and NFUNCTION forms to be compiled.")
+#|
+(defvar *fast-eval* ()
+  "If non-nil, compile-and-call any forms which would be expensive to evaluate.")
+|#
+(defvar *declaration-handlers* ())
+
+
+(defvar *lisp-system-pointer-functions* nil)
+(defvar *lisp-user-pointer-functions* nil)
+(defvar *lisp-cleanup-functions* nil)   ; list of (0-arg) functions to call before quitting Lisp
+(defvar *lisp-startup-functions* nil)   ; list of funs to call after startup.
+(defvar %lisp-system-fixups% nil)
+
+
+(setf (*%saved-method-var%*) nil)
+
+; The GC expects these to be NIL or a function of no args
+(defvar *pre-gc-hook* nil)
+(defvar *post-gc-hook* nil)
+
+; These are used by add-gc-hook, delete-gc-hook
+(defvar *pre-gc-hook-list* nil)
+(defvar *post-gc-hook-list* nil)
+
+(defvar *backtrace-dialogs* nil)
+;(defvar *stepper-running* nil)
+(defparameter *last-mouse-down-time* 0)
+(defparameter *last-mouse-down-position* 0)
+
+(defvar %handlers% ())
+
+
+#|
+(defvar %restarts% (list (list (%cons-restart 'abort
+                                              #'(lambda (&rest ignore)
+                                                  (declare (ignore ignore))
+                                                  (throw :toplevel nil))
+                                              "Restart the toplevel loop."
+                                              nil
+                                              nil))))
+|#
+
+(defvar %restarts% nil)
+
+(defvar ccl::*kernel-restarts* nil)
+(defvar *condition-restarts* nil "explicit mapping between c & r")
+(declaim (list %handlers% %restarts% ccl::*kernel-restarts* *condition-restarts*))
+
+
+
+
+(defparameter *%periodic-tasks%* nil)
+(defparameter *dribble-stream* nil)
+
+(defconstant *keyword-package* *keyword-package*)
+(defconstant *common-lisp-package* *common-lisp-package*)
+(defconstant *ccl-package* *ccl-package*)
+
+(defparameter *load-print* nil "the default for the :PRINT argument to LOAD")
+(defparameter *loading-files* nil)
+(defparameter *break-level* 0)
+(defparameter *last-break-level* 0)
+(defparameter *warn-if-redefine* nil)
+(defvar *record-source-file*)           ; set in l1-utils.
+(defparameter *level-1-loaded* nil)     ; set t by l1-boot
+(defparameter *save-definitions* nil)
+(defparameter *save-local-symbols* t)
+(defparameter *save-source-locations* T
+  "Controls whether source location information is saved, both for definitions (names) and
+in function objects.
+
+If NIL we don't store any source locations (other than the filename if *record-source-file* is non-NIL).
+
+If T we store as much source location information as we have available.
+
+If :NO-TEXT we don't store a copy of the original source text.  This is a space optimization useful
+for compiling files that are not expected to change.")
+
+(defparameter *record-pc-mapping* t "True to record pc -> source mapping (but only if
+*save-source-locations* is also true)")
+
+(defvar *modules* nil
+  "This is a list of module names that have been loaded into Lisp so far.
+   The names are case sensitive strings.  It is used by PROVIDE and REQUIRE.")
+
+
+
+
+
+(defparameter *eof-value* (cons nil nil))
+
+(defvar *gc-event-status-bits*)         ; also initialized by kernel
+
+(defparameter *top-listener* nil)
+
+
+
+
+
+
+
+(defvar *listener-indent* nil)
+
+(defparameter *autoload-lisp-package* nil)   ; Make 'em suffer
+(defparameter *apropos-case-sensitive-p* nil)
+
+(defloadvar *total-gc-microseconds* (let* ((timeval-size
+                                            #.(%foreign-type-or-record-size
+                                               :timeval :bytes))
+                                           (p (malloc (* 5 timeval-size))))
+                                      (#_memset p 0 (* 5 timeval-size))
+                                      p))
+
+
+(defloadvar *total-bytes-freed* (let* ((p (malloc 8)))
+                                  (setf (%get-long p 0) 0
+                                        (%get-long p 4) 0)
+                                  p))
+
+
+
+(defvar *terminal-character-encoding-name* nil
+  "NIL (implying :ISO-8859-1), or a keyword which names a defined
+character encoding to be used for *TERMINAL-IO* and other predefined
+initial streams.  The value of *TERMINAL-CHARACTER-ENCODING-NAME*
+persists across calls to SAVE-APPLICATION; it can be specified via
+the command-line argument --terminal-encoding (-K)")
+
+
+(defconstant +null-ptr+ (%null-ptr))
+
+;;; end of L1-init.lisp
+
Index: /branches/new-random/level-1/l1-io.lisp
===================================================================
--- /branches/new-random/level-1/l1-io.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-io.lisp	(revision 13309)
@@ -0,0 +1,1968 @@
+;;; -*- Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; L1-io.lisp
+
+(in-package "CCL")
+
+(setf (fdefinition '%new-ptr) (fdefinition '%new-gcable-ptr))
+
+
+;;;; ======================================================================
+;;;; Standard CL IO frobs
+
+
+(declaim (inline %real-print-stream))
+(defun %real-print-stream (&optional (stream nil))
+  (cond ((null stream)
+         *standard-output*)
+        ((eq stream t)
+         *terminal-io*)
+        (t stream)))
+
+;;; OK, EOFP isn't CL ...
+(defun eofp (&optional (stream *standard-input*))
+  (stream-eofp stream))
+
+(defun force-output (&optional stream)
+  (stream-force-output (%real-print-stream stream))
+  nil)
+
+(defun listen (&optional (stream *standard-input*))
+  (let* ((stream (designated-input-stream stream)))
+    (stream-listen stream)))
+
+(defun fresh-line (&optional (output-stream *standard-output*))
+  "Output #\Newline only if the OUTPUT-STREAM is not already at the
+start of a line.  Return T if #\Newline needed."
+  (stream-fresh-line (%real-print-stream output-stream)))
+
+(defun column (&optional stream)
+  (let* ((stream (%real-print-stream stream)))
+    (stream-line-column stream)))
+
+(defun clear-input (&optional input-stream)
+  "Clear any available input from INPUT-STREAM."
+  (stream-clear-input (designated-input-stream input-stream))
+  nil)
+
+(defun write-char (char &optional (output-stream nil))
+  "Output CHAR to OUTPUT-STREAM."
+  (let* ((stream (%real-print-stream output-stream)))
+    (if (typep stream 'basic-stream)
+      (let* ((ioblock (basic-stream-ioblock stream)))
+        (funcall (ioblock-write-char-function ioblock) ioblock char))
+      (stream-write-char stream char))
+    char))
+
+(defun write-string (string &optional output-stream &key (start 0 start-p)
+			    (end nil end-p))
+  "Write the characters of the subsequence of STRING bounded by START
+and END to OUTPUT-STREAM."
+  (let* ((stream (%real-print-stream output-stream)))
+    (if (typep stream 'basic-stream)
+      (let* ((ioblock (basic-stream-ioblock stream)))
+        (with-ioblock-output-locked (ioblock) 
+          (if (and (typep string 'simple-string)
+                   (not start-p) (not end-p))
+            (funcall (ioblock-write-simple-string-function ioblock)
+                     ioblock string 0 (length string))
+            (progn
+              (setq end (check-sequence-bounds string start end))
+              (locally (declare (fixnum start end))
+                (multiple-value-bind (arr offset)
+                    (if (typep string 'simple-string)
+                      (values string 0)
+                      (array-data-and-offset (require-type string 'string)))
+                  (unless (eql 0 offset)
+                    (incf start offset)
+                    (incf end offset))
+                  (funcall (ioblock-write-simple-string-function ioblock)
+                           ioblock arr start (the fixnum (- end start)))))))))
+      (if (and (not start-p) (not end-p))
+        (stream-write-string stream string)
+        (stream-write-string stream string start end)))
+  string))
+
+(defun write-simple-string (string output-stream start end)
+  "Write the characters of the subsequence of simple-string STRING bounded by START
+and END to OUTPUT-STREAM."
+  (let* ((stream (%real-print-stream output-stream))
+         (string (the simple-string string))) ;; typecheck at high safety.
+    (if (typep stream 'basic-stream)
+      (let* ((ioblock (basic-stream-ioblock stream))
+             (start (or start 0)))
+        (with-ioblock-output-locked (ioblock) 
+          (if (and (eq start 0) (null end))
+            (funcall (ioblock-write-simple-string-function ioblock)
+                     ioblock string 0 (length string))
+            (let* ((end (check-sequence-bounds string start end)))
+              (funcall (ioblock-write-simple-string-function ioblock)
+                       ioblock string start  (%i- end start))))))
+      (if (and (not start) (not end))
+        (stream-write-string stream string)
+        (stream-write-string stream string start (or end (length string)))))
+    string))
+
+(defun write-line (string &optional output-stream
+                          &key (start 0) (end (length string)))
+  "Write the characters of the subsequence of STRING bounded by START
+and END to OUTPUT-STREAM then output a #\Newline at end."
+  (write-string string output-stream :start start :end end)
+  (terpri output-stream)
+  string)
+
+(defun terpri (&optional (stream *standard-output*))
+  (let* ((stream (%real-print-stream stream)))
+    (if (typep stream 'basic-stream)
+      (let* ((ioblock (basic-stream-ioblock stream)))
+        (funcall (ioblock-write-char-function ioblock) ioblock #\newline))
+      (stream-write-char stream #\newline))
+    nil))
+
+;;;; ----------------------------------------------------------------------
+
+
+
+;;;; ======================================================================
+;;;; The Lisp Printer
+
+
+;; coral extensions
+(defvar *print-abbreviate-quote* t
+  "Non-NIL means that the normal lisp printer --
+not just the pretty-printer -- should print
+lists whose first element is QUOTE or FUNCTION specially.
+This variable is not part of standard Common Lisp.")
+
+(defvar *print-structure* t
+  "Non-NIL means that lisp structures should be printed using
+\"#S(...)\" syntax.  if nil, structures are printed using \"#<...>\".
+This variable is not part of standard Common Lisp.")
+
+;; things Richard Mlynarik likes.
+(defvar *print-simple-vector* nil
+  "Non-NIL means that simple-vectors whose length is less than
+the value of this variable are printed even if *PRINT-ARRAY* is false.
+this variable is not part of standard Common Lisp.")
+
+(defvar *print-simple-bit-vector* nil
+  "Non-NIL means that simple-bit-vectors whose length is less than
+the value of this variable are printed even if *PRINT-ARRAY* is false.
+This variable is not part of standard Common Lisp.")
+
+(defvar *print-string-length* nil
+  "Non-NIL means that strings longer than this are printed
+using abbreviated #<string ...> syntax.
+This variable is not part of standard Common Lisp.")
+
+(defvar *print-escape* t
+  "Non-NIL means that the lisp printer should -attempt- to output
+expressions `readably.'  When NIL the attempts to produce output
+which is a little more human-readable (for example, pathnames
+are represented by the characters of their namestring.)")
+
+(defvar *print-pretty* nil
+  "Non-NIL means that the lisp printer should insert extra
+indentation and newlines to make output more readable and `prettier.'")
+
+(defvar *print-base* 10.
+  "The output base for integers and rationals.
+Must be an integer between 2 and 36.")
+
+(defvar *print-radix* nil
+  "Non-NIL means that the lisp printer will explicitly indicate
+the output radix (see *PRINT-BASE*) which is used to print
+integers and rational numbers.")
+
+(defvar *print-level* nil
+  "Specifies the depth at which printing of lisp expressions
+should be truncated.  NIL means that no such truncation should occur.
+Truncation is indicated by printing \"#\" instead of the
+representation of the too-deeply-nested structure.
+See also *PRINT-LENGTH*")
+
+(defvar *print-length* nil
+  "Specifies the length at which printing of lisp expressions
+should be truncated.  NIL means that no such truncation should occur.
+truncation is indicated by printing \"...\" instead of the
+rest of the overly-long list or vector.
+See also *PRINT-LEVEL*")
+
+(defvar *print-circle* nil
+  "Non-NIL means that the lisp printer should attempt to detect
+circular structures, indicating them by using \"#n=\" and \"#n#\" syntax.
+If this variable is false then an attempt to
+output circular structure may cause unbounded output.")
+
+(defvar *print-case* ':upcase
+  "Specifies the alphabetic case in which symbols should
+be printed.  Possible values include :UPCASE, :DOWNCASE and :CAPITALIZE") ; and :StuDLy
+
+(defvar *print-array* t
+  "Non-NIL means that arrays should be printed using \"#(...)\" or
+\"=#nA(...)\" syntax to show their contents.
+If NIL, arrays other than strings are printed using \"#<...>\".
+See also the (non-Common Lisp) variables *PRINT-SIMPLE-VECTOR*
+and *PRINT-SIMPLE-BIT-VECTOR*")
+
+(defvar *print-gensym* t
+  "Non-NIL means that symbols with no home package should be
+printed using \"#:\" syntax.  NIL means no prefix is printed.")
+
+(defvar *print-readably* nil
+  "Non-NIL means that attempts to print unreadable objects
+   signal PRINT-NOT-READABLE errors.  NIL doesn't.")
+
+(defvar *PRINT-RIGHT-MARGIN* nil
+  "+#/NIL the right margin for pretty printing")
+
+(defvar *PRINT-MISER-WIDTH* 40.
+  "+#/NIL miser format starts when there is less than this width left")
+
+(defvar *PRINT-LINES* nil
+  "+#/NIL truncates printing after # lines")
+
+(defvar *DEFAULT-RIGHT-MARGIN* 70
+  "Controls default line length;  Must be a non-negative integer")
+
+(defvar *PRINT-PPRINT-DISPATCH* nil) ; We have to support this.
+
+(defvar *xp-current-object* nil)  ; from xp
+
+(defvar *circularity-hash-table* nil) ; ditto
+
+(defvar *current-level* nil)
+
+(defvar *current-length* nil) ; must be nil at top level
+
+(defvar *print-catch-errors* nil)
+
+;;;; ======================================================================
+
+(defclass xp-stream (output-stream)
+   (xp-structure))
+
+(defun %write-string (string stream)
+  (if (characterp string)
+    (stream-write-char stream string)
+    (stream-write-entire-string stream string)))
+
+
+;; *print-simple-vector*
+;; *print-simple-bit-vector*
+;; *print-string-length*
+;; for things like *print-level* which must [no longer] be integers > 0
+(defun get-*print-frob* (symbol
+                         &optional (nil-means target::target-most-positive-fixnum)
+                         (t-means nil))
+  (declare (type symbol symbol))
+  (let ((value (symbol-value symbol)))
+    (when *print-readably*
+      (case symbol
+        ((*print-length* *print-level* *print-lines* *print-string-length*)
+         (setq value nil))
+        ((*print-escape* *print-gensym* *print-array* *print-simple-vector*
+                         *print-simple-bit-vector*)
+         (setq value t))
+        (t nil)))
+    (cond ((null value)
+           nil-means)
+          ((and (integerp value)) ; (> value 0))
+           (min (max value -1) value target::target-most-positive-fixnum))
+          ((and t-means (eq value 't))
+           t-means)
+          (t
+           (setf (symbol-value symbol) nil)
+           (error "~s had illegal value ~s.  reset to ~s"
+                  symbol value 'nil)))))
+
+
+(defun pp-newline (stream kind)
+  (case kind
+    ((:newline)
+     (fresh-line stream))
+    ((:unconditional :mandatory)
+     (stream-write-char stream #\Newline))
+    (t nil)))
+
+
+(defun pp-space (stream &optional (newline-kind ':fill))
+  (stream-write-char stream #\space)
+  (pp-newline stream newline-kind))
+
+(defun pp-start-block (stream &optional prefix)
+  (cond ((null prefix))
+        ((characterp prefix)
+         (stream-write-char stream prefix))
+        ((stringp prefix)
+         (%write-string prefix stream))
+        (t (report-bad-arg prefix '(or character string (eql nil))))))
+
+
+(defun pp-end-block (stream &optional suffix)
+  (cond ((null suffix))
+        ((characterp suffix)
+         (stream-write-char stream suffix))
+        ((stringp suffix)
+         (%write-string suffix stream))
+        (t (report-bad-arg suffix '(or character string (eql nil))))))
+
+
+#|
+(defmethod pp-set-indentation ((stream stream) kind n)
+  (declare (ignore kind n))
+  nil)
+|#
+
+
+;;;; ======================================================================
+;; list-kludge is so that we can simultaneously detect shared list tails
+;;   and avoid printing lists as (foo . (bar . (baz . nil)))
+;; if non-nil, it is the remaining *print-length* and object is
+;;   a list tail
+
+
+
+(defmethod write-internal-1 ((stream t) object level list-kludge)
+  (declare (type fixnum level) (type (or null fixnum) list-kludge))
+  ;;>> Anybody passing in list-kludge had better be internal to the lisp printer.
+  ;(if list-kludge (error "Internal printer error"))
+    (let ((circle *print-circle*)
+          (pretty *print-pretty*))
+      (cond ((or pretty circle)
+             ; what about this level stuff??
+             ; most peculiar
+             (maybe-initiate-xp-printing
+              #'(lambda (s o) (write+ o s)) stream object))
+            ((not list-kludge)
+             (write-a-frob object stream level list-kludge))
+            ((null object))
+            (t
+             (stream-write-char stream #\space)
+             (when (not (consp object))
+               (stream-write-char stream #\.)
+               (stream-write-char stream #\space))
+             (write-a-frob object stream level list-kludge)))))
+
+
+
+(defmethod write-internal-1 ((stream xp-stream) object level list-kludge)
+  (when level
+    (setq *current-level* (if (and *print-level* (not *print-readably*))
+                            (- *print-level* level)
+                            0)))
+  (write+ object (slot-value stream 'xp-structure) list-kludge))
+
+
+(defvar *inside-printer-error* nil)
+
+(defvar *signal-printing-errors* nil)
+(queue-fixup (setq *signal-printing-errors* t))
+
+(defun write-internal (stream object level list-kludge)
+  (if (bogus-thing-p object)
+    (print-unreadable-object
+      (object stream)
+      (princ (%str-cat "BOGUS object @ #x" (%integer-to-string (%address-of object) 16.)) 
+             stream))
+    (progn
+      (flet ((handler (condition)
+               (declare (ignore condition))
+               (unless *signal-printing-errors*
+                 (return-from write-internal
+                   (let ((*print-pretty* nil)
+                         (*print-circle* nil))
+                     (if *inside-printer-error*
+                       (when (eql 1 (incf *inside-printer-error*))
+                         (%write-string "#<Recursive printing error " stream)
+			 (stream-write-char stream #\space)
+                         (%write-address (%address-of object) stream)
+                         (stream-write-char stream #\>))
+                       (let ((*inside-printer-error* 0))
+                         ; using format here considered harmful.
+                         (%write-string "#<error printing " stream)
+                         (write-internal stream (type-of object) (max level 2) nil)
+                         (stream-write-char stream #\space)
+                         (%write-address (%address-of object) stream)
+                         (stream-write-char stream #\>))))))))
+        (declare (dynamic-extent #'handler))
+        (handler-bind
+          ((error #'handler))
+          (write-internal-1 stream object level list-kludge)))
+      object)))
+
+
+;;;; ======================================================================
+;;;; internals of write-internal
+
+;; bd common-lisp (and lisp machine) printer depth counts
+;;  count from 0 upto *print-level* instead of from
+;;  *print-level* down to 0 (which this printer sensibly does.)
+(defun backtranslate-level (level)
+  (let ((print-level (get-*print-frob* '*print-level*)))
+    (if (not (and level print-level))
+      target::target-most-positive-fixnum
+      (if (> level print-level)
+        ;; wtf!
+        1
+        (- print-level level)))))
+
+; so we can print-circle for print-object methods.
+(defvar %current-write-level% nil)
+(defvar %current-write-stream% nil)
+(defun %current-write-level% (stream &optional decrement?)
+  (if (eq stream %current-write-stream%)
+    (if decrement? (1- %current-write-level%) %current-write-level%)
+    (get-*print-frob* '*print-level*)))
+      
+;;>> Some notes:
+;;>> CL defining print-object to be a multmethod dispatching on
+;;>>  both the object and the stream just can't work
+;;>> There are a couple of reasons:
+;;>>  - CL wants *print-circle* structure to be automatically detected
+;;>>    This means that there must be a printing pre-pass to some stream
+;;>>    other than the one specified by the user, which means that any
+;;>>    print-object method which specialises on its second argument is
+;;>>    going to lose big.
+
+;;>>  - CL wants *print-level* truncation to happen automatically
+;;>>    and doesn't pass a level argument to print-object (as it should)
+;;>>    This means that the current level must be associated with the
+;;>>    stream in some fashion.  The quicky kludge Bill uses here
+;;>>    (binding a special variable) loses for
+;;>>    + Entering a break loop whilst printing to a stream
+;;>>      (Should start level from (get-*print-level*) again)
+;;>>    + Performing output to more than one stream in an interleaved fashion
+;;>>      (Say a print-object method which writes to *trace-output*)
+;;>>    The solution, again, is to actually call the print-object methods
+;;>>    on a write-aux-stream, where that stream is responsible for
+;;>>    doing *print-level* truncation.
+;;>>  - BTW The select-method-order should be (stream object) to even have
+;;>>    a chance of winning.  Not that it could win in any case, for the above reasons.
+;;>> It isn't that much work to change the printer to always use an
+;;>> automatically-level-truncating write-aux-stream
+;;>> It is a pity that CL is so BD.
+;;>>
+
+(defun write-a-frob (object stream level list-kludge)
+  (declare (type stream stream) (type fixnum level)
+           (type (or null fixnum) list-kludge))
+  (cond ((not list-kludge)
+         (let ((%current-write-stream% stream)   ;>> SIGH
+               (%current-write-level% level))
+           (print-object object stream)))
+        ((%i< list-kludge 1)
+         ;; *print-length* truncation
+         (stream-write-entire-string stream "..."))
+        ((not (consp object))
+         (write-a-frob object stream level nil))
+        (t
+         (write-internal stream (%car object) level nil)
+         ;;>> must do a tail-call!!
+         (write-internal-1 stream (%cdr object) level (if (consp (%cdr object))
+                                                          (%i- list-kludge 1)
+                                                          list-kludge)))))
+
+(defmethod print-object :around ((object t) stream)
+  (if *print-catch-errors*
+    (handler-case (call-next-method)
+      (error () (write-string "#<error printing object>" stream)))
+    (call-next-method)))
+
+(defmethod print-object ((object t) stream)
+  (let ((level (%current-write-level% stream))   ; what an abortion.  This should be an ARGUMENT!
+        (%type (%type-of object)))
+    (declare (type symbol %type)
+             (type fixnum level))
+    (flet ((depth (stream v)
+             (declare (type fixnum v) (type stream stream))
+             (when (%i<= v 0)
+               ;; *print-level* truncation
+               (stream-write-entire-string stream "#")
+               t)))
+      (cond
+        ((eq %type 'cons)
+         (unless (depth stream level)
+           (write-a-cons object stream level)))
+        ;; Don't do *print-level* truncation for anything between
+        ;; here and the (depth ...) case.
+        ((or (eq %type 'symbol)
+             (null object))
+         (write-a-symbol object stream))
+        ((or (stringp object)
+             (bit-vector-p object))
+         (cond ((or (not (stringp object))
+                    (%i> (length (the string object))
+                         (get-*print-frob* '*print-string-length*)))
+                (write-an-array object stream level))
+               ((or *print-escape* *print-readably*)
+                (write-escaped-string object stream))
+               (t
+                (%write-string object stream))))
+        ((and (eq %type 'structure)
+              (not (null (ccl::struct-def object)))
+              (null (cdr (sd-slots (ccl::struct-def object)))))
+         ;; else fall through to write-a-uvector
+         (write-a-structure object stream level))
+        ((depth stream level))
+        ((eq %type 'package)
+         (write-a-package object stream))
+        ((eq %type 'macptr)
+         (write-a-macptr object stream))
+        ((eq %type 'dead-macptr)
+         (write-a-dead-macptr object stream))
+        ((eq %type 'internal-structure)
+         (write-an-istruct object stream level))        
+        ((and (eq %type 'structure)
+              (not (null (ccl::struct-def object))))
+         ;; else fall through to write-a-uvector
+         (if (and *print-pretty* *print-structure*)
+           (let ((*current-level* (if (and *print-level* (not *print-readably*))
+                                    (- *print-level* level)
+                                    0)))
+             (pretty-structure stream object)) 
+           (write-a-structure object stream level)))
+        ((functionp object)
+         (write-a-function object stream level))
+        ((arrayp object)
+         (cond ((or (not (stringp object))
+                    (%i> (length (the string object))
+                         (get-*print-frob* '*print-string-length*)))
+                (write-an-array object stream level))
+               ((or *print-escape* *print-readably*)
+                (write-escaped-string object stream))
+               (t
+                (%write-string object stream))))
+
+ ; whazzat        
+        ((uvectorp object)  
+         (write-a-uvector object stream level))
+        (t
+         (print-unreadable-object (object stream)
+           (let* ((address (%address-of object)))
+             (cond ((eq object (%unbound-marker-8))
+                    (%write-string "Unbound" stream))
+                   ((eq object (%slot-unbound-marker))
+                    (%write-string "Slot-Unbound" stream))
+                   (t
+                    (cond
+                     (t
+                      (%write-string "Unprintable " stream)
+                      (write-a-symbol %type stream)
+                      (%write-string " : " stream)))
+                    (%write-address address stream))))))))
+    nil))
+
+(defun write-a-dead-macptr (macptr stream)
+  (print-unreadable-object (macptr stream)
+    (%write-string "A Dead Mac Pointer" stream)))
+
+
+;;;; ======================================================================
+;;;; Powerful, wonderful tools for printing unreadable objects.
+
+(defun print-not-readable-error (object stream)
+  (error (make-condition 'print-not-readable :object object :stream stream)))
+
+; Start writing an unreadable OBJECT on STREAM, error out if *PRINT-READABLY* is true.
+(defun write-unreadable-start (object stream)
+  (if *print-readably* 
+    (print-not-readable-error object stream)
+    (pp-start-block stream "#<")))
+
+(defun %print-unreadable-object (object stream type id thunk)
+  (cond ((null stream) (setq stream *standard-output*))
+        ((eq stream t) (setq stream *terminal-io*)))
+  (write-unreadable-start object stream)
+  (when type
+    (princ (type-of object) stream))
+  (when thunk 
+    (when type (stream-write-char stream #\space))
+    (funcall thunk))
+  (if id
+    (%write-address object stream #\>)
+    (pp-end-block stream ">"))
+  nil)
+
+;;;; ======================================================================
+;;;; internals of internals of write-internal
+
+(defmethod print-object ((char character) stream &aux name)
+  (cond ((or *print-escape* *print-readably*) ;print #\ for read-ability
+         (stream-write-char stream #\#)
+         (stream-write-char stream #\\)
+         (if (and (or (eql char #\newline)
+                      (not (standard-char-p char)))
+                  (setq name (char-name char)))
+           (%write-string name stream)
+           (stream-write-char stream char)))
+        (t
+         (stream-write-char stream char))))
+
+(defun get-*print-base* ()
+  (let ((base *print-base*))
+    (unless (and (fixnump base)
+                 (%i< 1 base) (%i< base 37.))
+      (setq *print-base* 10.)
+      (error "~S had illegal value ~S.  Reset to ~S"
+             '*print-base* base 10))
+    base))
+
+(defun write-radix (base stream)
+  (stream-write-char stream #\#)
+  (case base
+    (2 (stream-write-char stream #\b))
+    (8 (stream-write-char stream #\o))
+    (16 (stream-write-char stream #\x))
+    (t (%pr-integer base 10. stream)
+       (stream-write-char stream #\r))))
+
+(defun write-an-integer (num stream
+                         &optional (base (get-*print-base*))
+                                   (print-radix *print-radix*))
+  (when (and print-radix (not (eq base 10)))
+    (write-radix base stream))
+  (%pr-integer num base stream)
+  (when (and print-radix (eq base 10))
+    (stream-write-char stream #\.)))
+
+(defmethod print-object ((num integer) stream)
+  (write-an-integer num stream))
+
+(defun %write-address (object stream &optional foo)
+  (if foo (pp-space stream))
+  (write-an-integer (if (integerp object) object (%address-of object)) stream 16. t)
+  (if foo (pp-end-block stream foo)))
+
+(defmethod print-object ((num ratio) stream)
+  (let ((base (get-*print-base*)))
+    ;;>> What to do when for *print-radix* and *print-base* = 10?
+    (when (and *print-radix* (not (eq base 10)))
+      (write-radix base stream))
+    (%pr-integer (numerator num) base stream)
+    (stream-write-char stream #\/)
+    (%pr-integer (denominator num) base stream)))
+
+;;>> Doesn't do *print-level* truncation
+(defmethod print-object ((c complex) stream)
+  (pp-start-block stream "#C(")
+  (print-object (realpart c) stream)
+  (pp-space stream)
+  (print-object (imagpart c) stream)
+  (pp-end-block stream #\)))
+
+(defmethod print-object ((float float) stream)
+  (print-a-float float stream))
+
+(defun float-exponent-char (float)
+  (if (case *read-default-float-format*
+        (single-float (typep float 'single-float))
+        (double-float (typep float 'double-float))
+        (t (typep float *read-default-float-format*)))
+    #\E  
+    (if (typep float 'double-float)
+      #\D
+      #\S)))
+
+(defun default-float-p (float)
+  (case *read-default-float-format*
+        (single-float (typep float 'single-float))
+        (double-float (typep float 'double-float))
+        (t (typep float *read-default-float-format*))))
+
+
+(defun print-a-nan (float stream)
+  (if (infinity-p float)
+      (output-float-infinity float stream)
+      (output-float-nan float stream)))
+
+(defun output-float-infinity (x stream)
+  (declare (float x) (stream stream))
+  (format stream "~:[-~;~]1~c++0"
+	  (plusp x)
+	  (if (typep x *read-default-float-format*)
+	      #\E
+	      (typecase x
+		(double-float #\D)
+		(single-float #\S)))))
+
+(defun output-float-nan (x stream)
+  (declare (float x) (stream stream))
+  (format stream "1~c+-0 #| not-a-number |#"
+	  (if (typep x *read-default-float-format*)
+	      #\E
+	      (etypecase x
+		(double-float #\D)
+		(single-float #\S)))))
+
+             
+;; nanning => recursive from print-a-nan - don't check again
+(defun print-a-float (float stream &optional exp-p nanning)
+  (let ((strlen 0) (exponent-char (float-exponent-char float)))
+    (declare (fixnum strlen))
+    (setq stream (%real-print-stream stream))
+    (if (and (not nanning)(nan-or-infinity-p float))
+      (print-a-nan float stream)    
+      (multiple-value-bind (string before-pt #|after-pt|#)
+                           (flonum-to-string float)
+        (declare (fixnum before-pt #|after-pt|#))
+        (setq strlen (length string))
+        (when (minusp (float-sign float))
+          (stream-write-char stream #\-))
+        (cond
+         ((and (not exp-p) (zerop strlen))
+          (stream-write-entire-string stream "0.0"))
+         ((and (> before-pt 0)(<= before-pt 7)(not exp-p))
+          (cond ((> strlen before-pt)
+                 (write-string string stream :start  0 :end before-pt)
+                 (stream-write-char stream #\.)
+                 (write-string string stream :start  before-pt :end strlen))
+                (t ; 0's after
+                 (stream-write-entire-string stream string)
+                 (dotimes (i (-  before-pt strlen))
+                   (stream-write-char stream #\0))
+                 (stream-write-entire-string stream ".0"))))
+         ((and (> before-pt -3)(<= before-pt 0)(not exp-p))
+          (stream-write-entire-string stream "0.")
+          (dotimes (i (- before-pt))
+            (stream-write-char stream #\0))
+          (stream-write-entire-string stream string))
+         (t
+          (setq exp-p t)
+          (stream-write-char stream (if (> strlen 0)(char string 0) #\0))
+          (stream-write-char stream #\.)
+          (if (> strlen 1)
+            (write-string string stream :start  1 :end strlen)
+            (stream-write-char stream #\0))
+          (stream-write-char stream exponent-char)
+          (when (and exp-p (not (minusp (1- before-pt))))
+            (stream-write-char stream #\+))
+          (let ((*print-base* 10)
+                (*print-radix* nil))
+            (princ (1- before-pt) stream))))
+        (when (and (not exp-p)
+                   (not (default-float-p float)))
+          (stream-write-char stream exponent-char)
+          (stream-write-char stream #\0))))))
+
+;;>> Doesn't do *print-level* truncation
+(defmethod print-object ((class class) stream)
+  (print-unreadable-object (class stream)
+    (print-object (class-name (class-of class)) stream)
+    (pp-space stream)
+    (print-object (class-name class) stream)))
+
+
+(defmethod print-object ((value-cell value-cell) stream)
+  (print-unreadable-object (value-cell stream :type t :identity t)
+    (prin1 (uvref value-cell target::value-cell.value-cell) stream)))
+
+;(defun symbol-begins-with-vowel-p (sym)
+;  (and (symbolp sym)
+;       (not (%izerop (%str-length (setq sym (symbol-name sym)))))
+;       (%str-member (schar sym 0) "AEIOU")))
+
+;;;; ----------------------------------------------------------------------
+;;;; CLOSsage
+
+(defmethod print-object ((instance standard-object) stream)
+  (if (%i<= %current-write-level% 0)    ; *print-level* truncation
+      (stream-write-entire-string stream "#")
+      (print-unreadable-object (instance stream :identity t)
+        (let* ((class (class-of instance))
+               (class-name (class-name class)))
+          (cond ((not (and (symbolp class-name)
+                           (eq class (find-class class-name nil))))
+                 (%write-string "An instance of" stream)
+                 (pp-space stream)
+                 (print-object class stream))
+                (t
+                 (write-a-symbol class-name stream)))))))
+
+(defmethod print-object ((method standard-method) stream)
+  (print-method method stream (%class.name (class-of method))))
+
+(defmethod print-object ((method-function method-function) stream)
+  (let ((method (%method-function-method method-function)))
+    (if (typep method 'standard-method)
+      (print-method (%method-function-method method-function)
+                    stream
+                    (%class.name (class-of method-function)))
+      (call-next-method))))
+
+
+
+(defun print-method (method stream type-string)
+  (print-unreadable-object (method stream)
+    (let ((name (%method-name method))
+          (qualifiers (%method-qualifiers method))
+          (specializers (mapcar #'(lambda (specializer)
+                                    (if (typep specializer 'eql-specializer)
+				      (list 'eql
+					    (eql-specializer-object specializer))
+				      (or (class-name specializer)
+					  specializer)))
+                                (%method-specializers method)))
+          (level-1 (%i- %current-write-level% 1)))
+      (cond
+       ((< level-1 0)
+        ;; *print-level* truncation
+        (stream-write-entire-string stream "#"))
+       (t 
+        (prin1 type-string stream)
+        (pp-space stream)
+        (write-internal stream name level-1 nil)
+        (pp-space stream)
+        (when qualifiers
+          (write-internal stream (if (cdr qualifiers) qualifiers (car qualifiers))
+                          level-1 nil)
+          (pp-space stream))
+        (write-internal stream specializers level-1 nil))))))
+
+;; Need this stub or we'll get the standard-object method
+(defmethod print-object ((gf standard-generic-function) stream)
+  (write-a-function gf stream (%current-write-level% stream)))
+
+;; This shouldn't ever happen, but if it does, don't want the standard-object method
+(defmethod print-object ((mo metaobject) stream)
+  (print-unreadable-object (mo stream :type t :identity t)))
+
+(defmethod print-object ((cm combined-method) stream)
+  (print-unreadable-object (cm stream :identity t)
+    (%write-string "Combined-Method" stream)
+    (pp-space stream)
+    (let ((name (function-name cm)))
+      (if (and (functionp name) (function-is-current-definition? name))
+        (setq name (function-name name)))
+      (write-internal stream name (%current-write-level% stream) nil))))
+
+(defun print-specializer-names (specializers stream)
+  (flet ((print-specializer (spec stream)
+           (write-1 (if (typep spec 'class) (%class.name spec) spec) stream)))
+    (pp-start-block stream #\()
+    (if (atom specializers)
+        (print-specializer specializers stream)
+      (progn (print-specializer (car specializers) stream)
+             (dolist (spec (cdr specializers))
+               (pp-space stream)
+               (print-specializer spec stream))))
+    (pp-end-block stream #\))))
+
+
+;;;; ----------------------------------------------------------------------
+            
+(defun write-a-cons (cons stream level)
+  (declare (type cons cons) (type stream stream) (type fixnum level))
+  (let ((print-length (get-*print-frob* '*print-length*))
+        (level-1 (%i- level 1))
+        (head (%car cons))
+        (tail (%cdr cons)))
+    (declare (type fixnum print-length) (type fixnum level-1))
+    (unless (and *print-abbreviate-quote*
+                 (write-abbreviate-quote head tail stream level-1))
+        (progn
+          (pp-start-block stream #\()
+          (if (= print-length 0)
+              (%write-string "..." stream)
+              (progn
+                (write-internal stream head level-1 nil)
+                (write-internal stream tail level-1
+                                (if (atom tail)
+                                  print-length
+                                  (%i- print-length 1)))))
+          (pp-end-block stream #\))))))
+
+;;;; hack for quote and backquote
+
+;; for debugging
+;(setq *backquote-expand* nil)
+
+(defvar *backquote-hack* (list '*backquote-hack*)) ;uid
+(defun write-abbreviate-quote (head tail stream level-1)
+  (declare (type stream stream) (type fixnum level-1))
+  (when (symbolp head)
+    (cond ((or (eq head 'quote) (eq head 'function))
+           (when (and (consp tail)
+                      (null (%cdr tail)))
+             (%write-string (if (eq head 'function) "#'" "'") stream)
+             (write-internal stream (%car tail) level-1 nil)
+             t))
+          ((eq head 'backquote-expander)
+           (when (and (consp tail)
+		      (consp (cdr tail))
+		      (consp (cddr tail))
+		      (consp (cdddr tail))
+		      (null (cddddr tail)))
+             (let ((tail tail))
+               (set (%car tail)
+                    *backquote-hack*)  ;,
+               (set (%car (setq tail (%cdr tail)))
+                    *backquote-hack*)  ;,.
+               (set (%car (setq tail (%cdr tail)))
+                    *backquote-hack*)  ;,@
+               (stream-write-char stream #\`)
+               (write-internal stream (%cadr tail) level-1 nil)
+               t)))
+          ((and (boundp head)
+                (eq (symbol-value head) *backquote-hack*))
+           ;;",foo" = (#:|,| . foo)
+           (stream-write-char stream #\,)
+           (let* ((n (symbol-name head))
+                  (l (length n)))
+             (declare (type simple-string n) (type fixnum l))
+             ;; possibilities are #:|`,| #:|,.| and #:|,@|
+             (if (eql l 3)
+               (stream-write-char stream (schar n 2)))
+             (write-internal stream tail level-1 nil)
+             t))
+          (t nil))))
+
+(eval-when (compile eval)
+(defmacro %char-needs-escape-p (char escape &rest losers)
+  (setq losers (remove-duplicates (cons escape losers)))
+  (setq char (require-type char 'symbol))
+  (dolist (c losers)
+    (unless (or (characterp c) (symbolp c)) (report-bad-arg c '(or character symbol))))
+  (cond ((null (cdr losers))
+         `(eq ,char ,escape))
+        ((and (every #'characterp losers)
+              ;(every #'string-char-p losers)
+              (%i> (length losers) 2))
+         `(%str-member ,char ,(concatenate 'string losers)))
+        (t
+         `(or ,@(mapcar #'(lambda (e) `(eq ,char ,e))
+                        losers)))))
+
+(defmacro %write-escaped-char (stream char escape &rest losers)
+  `(progn
+     (when (%char-needs-escape-p ,char ,escape ,@losers)
+       (stream-write-char ,stream ,escape))
+     (stream-write-char ,stream ,char)))
+)
+
+(defun write-escaped-string (string stream &optional (delim #\"))
+  (declare (type string string) (type character delim)
+           (type stream stream))
+  (write-char delim stream)
+  (do* ((limit (length string))
+        (i 0 (1+ i)))
+       ((= i limit))
+    (declare (type fixnum limit) (type fixnum i))
+    (let* ((char (char string i))
+           (needs-escape? (%char-needs-escape-p char #\\ delim)))
+      (if needs-escape?
+          (write-char #\\ stream))
+      (write-char char stream)))
+  (write-char delim stream))
+
+
+;;;; ----------------------------------------------------------------------
+;;;; printing symbols
+
+(defun get-*print-case* ()
+  (let ((case *print-case*))
+    (unless (or (eq case ':upcase) (eq case ':downcase) 
+                (eq case ':capitalize) (eq case ':studly))
+      (setq *print-case* ':upcase)
+      (error "~S had illegal value ~S.  Reset to ~S"
+             '*print-case* case ':upcase))
+    case))
+
+(defun write-a-symbol (symbol stream)
+  (declare (type symbol symbol) (type stream stream))
+  (let ((case (get-*print-case*))
+        (name (symbol-name symbol))
+        (package (symbol-package symbol)))
+    (declare (type simple-string name))
+    (when (or *print-readably* *print-escape*)
+      (cond ((keywordp symbol)
+             (stream-write-char stream #\:))
+            ((null package)
+             (when (or *print-readably* *print-gensym*)
+               (stream-write-char stream #\#)
+               (stream-write-char stream #\:)))
+            (t
+             (multiple-value-bind (s flag)
+                                  (find-symbol name *package*)
+               (unless (and flag (eq s symbol))
+                 (multiple-value-setq (s flag)
+                                      (find-symbol name package))
+                 (unless (and flag (eq s symbol))
+                   (%write-string "#|symbol not found in home package!!|#"
+                                  stream))
+                 (write-pname (package-name package) case stream)
+                 (stream-write-char stream #\:)
+                 (unless (eq flag ':external)
+                   (stream-write-char stream #\:)))))))
+    (write-pname name case stream)))
+
+
+
+(defun write-pname (name case stream)
+  (declare (type simple-string name) (stream stream)
+           (optimize (speed 3)(safety 0)))
+  (let* ((readtable *readtable*)
+         (readcase (readtable-case (if *print-readably*
+                                       %initial-readtable%
+                                       readtable)))
+         (escape? (or *print-readably* *print-escape*)))
+      (flet ((slashify? (char)
+               (declare (type character char))
+               (and escape?
+                    (if (alpha-char-p char) 
+                      (if (eq readcase :upcase)
+                        (lower-case-p char)  ; _tolower
+                        (if (eq readcase :downcase)
+                          (upper-case-p char)))
+                      ; should be using readtable here - but (get-macro-character #\|) is nil
+                      (not (%str-member
+                            char
+                            "!$%&*0123456789.<=>?@[]^_{}~+-/")))))
+             (single-case-p (name)
+               (let ((sofar nil))
+                 (dotimes (i (length name) sofar)
+                   (declare (type fixnum i))
+                   (declare (type simple-string name))
+                   (let* ((c (schar name i))
+                          (c-case (if (upper-case-p c)
+                                    :upcase
+                                    (if (lower-case-p c)
+                                      :downcase))))
+                     (when c-case
+                       (if sofar 
+                         (if (neq sofar c-case)
+                           (return nil))
+                         (setq sofar c-case))))))))
+        (declare (dynamic-extent #'slashify? #'single-case-p))
+        (block alice
+          (let ((len (length name))
+                (slash-count 0)
+                (last-slash-pos 0))
+            (declare (type fixnum len)
+                     (type fixnum slash-count last-slash-pos))                
+            (when escape?
+              (when (or (%izerop len)
+                        ;; if more than a few \, just use |...|
+                        (and (not (memq readcase '(:invert :preserve))) ; these never slashify alpha-p
+                             (let ((m (max (floor len 4) 2)))
+                               (dotimes (i (the fixnum len) nil)
+                                 (declare (type fixnum i))
+                                 (when (slashify? (schar name i))
+                                   (setq slash-count (%i+ slash-count 1))
+                                   (when (or (eql slash-count m)
+                                             (eq i (1+ last-slash-pos)))
+                                     (return t))
+                                   (setq last-slash-pos i)))))
+                        ;; or could be read as a number
+                        (%parse-number-token name 0 len *print-base*)
+                        ;; or symbol consisting entirely of .'s
+                        (dotimes (i len t)
+                          (declare (fixnum i))
+                          (unless (eql (schar name i) #\.)
+                            (return nil))))
+                (return-from alice
+                  (write-escaped-string name stream #\|))))
+            (case readcase
+              (:preserve (return-from alice  (write-string name stream :start  0 :end len)))
+              (:invert (return-from alice
+                         (cond ((single-case-p name)(write-perverted-string name stream len :invert))
+                               (t (write-string name stream :start  0 :end len)))))
+              (t 
+               (when (eql slash-count 0)
+                 (return-from alice
+                   (cond ((eq readcase case)
+                          (write-string name stream :start  0 :end len))
+                         (t (write-perverted-string name stream len case)))))))
+            (let* ((outbuf-len (+ len len))
+                   (outbuf-ptr -1)
+                   (outbuf (make-string outbuf-len)))
+              (declare (fixnum outbuf-ptr outbuf-len)
+                       (dynamic-extent outbuf)
+                       (simple-string outbuf))
+              (dotimes (pos (the fixnum len))
+                (declare (type fixnum pos))
+                (let* ((char (schar name pos))
+                       (slashify? (cond ((eql slash-count 0)
+                                         nil)
+                                        ((eql slash-count 1)
+                                         (eql pos last-slash-pos))
+                                        (t
+                                         (slashify? char)))))
+                  (declare (type character char))
+                  (when slashify?
+                    (setq slash-count (%i- slash-count 1))
+                    (setf (schar outbuf (incf outbuf-ptr)) #\\))
+                  (setf (schar outbuf (incf outbuf-ptr)) char)))
+              (write-string outbuf stream :start  0 :end (1+ outbuf-ptr))))))))
+
+#|
+(defun write-studly-string (string stream)
+  (declare (type string string) (stream stream))
+  (let* ((offset 0)
+         (end (length string))
+         (pool *pname-buffer*)
+         (outbuf-ptr -1)
+         (outbuf (pool.data pool)))
+    (declare (fixnum offset end outbuf-ptr))
+    (setf (pool.data pool) nil)
+    (unless (and outbuf (>= (length outbuf) end))
+      (setq outbuf (make-array end :element-type 'character)))
+    (do ((i 0 (%i+ i 1)))
+        ((%i>= i end))
+      (declare (type fixnum i))
+      (setq offset (%i+ offset (char-int (char string i)))))
+    (do ((i 0 (%i+ i 1)))
+        ((%i>= i end))
+      (declare (type fixnum i))
+      (let ((c (char string i)))
+        (declare (type character c))
+        (cond ((not (and (%i< (%ilogand2
+                                     (%i+ (char-int c) offset)
+                                     15.)
+                                   6.)
+                         (alpha-char-p c))))
+              ((upper-case-p c)
+               (setq c (char-downcase c)))
+              (t
+               (setq c (char-upcase c))))
+        (setf (schar outbuf (incf outbuf-ptr)) c)))
+    (write-string outbuf stream :start  0 :end end)
+    (setf (pool.data pool) outbuf)))
+|#
+
+(defun write-perverted-string (string stream end type)
+  ; type :invert :upcase :downcase :capitalize or :studly
+  (declare (fixnum end))
+  (let* ((readtable *readtable*)
+         (readcase (readtable-case readtable))
+         (outbuf-ptr -1)
+         (outbuf (make-string end))
+         (word-start t)
+         (offset 0))
+    (declare (fixnum offset outbuf-ptr)
+             (dynamic-extent outbuf))
+    (when (eq type :studly)
+      (do ((i 0 (%i+ i 1)))
+          ((%i>= i end))
+        (declare (type fixnum i))
+        (setq offset (%i+ offset (char-int (char string i))))))
+    (do ((i 0 (%i+ i 1)))
+        ((%i>= i end))
+      (declare (type fixnum i))
+      (let ((c (char string i)))
+        (declare (type character c))        
+        (cond ((alpha-char-p c)
+               (case type
+                 (:studly
+                  (cond ((not (%i< (%ilogand2
+                                    (%i+ (char-int c) offset)
+                                    15.)
+                                   6.)))
+                        ((upper-case-p c)
+                         (setq c (char-downcase c)))
+                        (t
+                         (setq c (char-upcase c)))))
+                 (:invert
+                  (setq c (if (upper-case-p c)(char-downcase c)(char-upcase c))))
+                 (:upcase
+                  (setq c (char-upcase c)))
+                 (:downcase
+                  (setq c (char-downcase c)))
+                 (:capitalize (setq c (cond (word-start
+                                             (setq word-start nil)
+                                             (if (eq readcase :upcase)
+                                                 c
+                                                 (char-upcase c)))
+                                            (t
+                                             (if (eq readcase :upcase)
+                                                 (char-downcase c)
+                                                 c)))))))
+              ((digit-char-p c)(setq word-start nil))
+              (t (setq word-start t)))
+        (setf (schar outbuf (incf outbuf-ptr)) c)))
+    (write-string outbuf stream :start  0 :end end)))
+
+
+;;;; ----------------------------------------------------------------------
+;;;; printing arrays
+
+;; *print-array*
+;; *print-simple-vector*
+;; *print-simple-bit-vector*
+;; *print-string-length*
+
+(defun array-readably-printable-p (array)
+  (let ((dims (array-dimensions array)))
+    (and (eq (array-element-type array) t)
+         (let ((zero (position 0 dims))
+               (number (position 0 dims
+                                 :test (complement #'eql)
+                                 :from-end t)))
+           (or (null zero) (null number) (> zero number))))))
+
+(defun write-an-array (array stream level)
+  (declare (type array array) (type stream stream) (type fixnum level))
+  (let* ((rank (array-rank array))
+         (vector? (eql rank 1))
+         (simple? (simple-array-p array))
+         (simple-vector? (simple-vector-p array))
+         ;; non-*print-string-length*-truncated strings are printed by
+         ;;  write-a-frob
+         (string? (stringp array))
+         (bit-vector? (bit-vector-p array))
+         (fill-pointer? (array-has-fill-pointer-p array))
+         (adjustable? (adjustable-array-p array))
+         (displaced? (displaced-array-p array))
+         (total-size (array-total-size array))
+         (length (and vector? (length array)))
+         (print-length (get-*print-frob* '*print-length*))
+         (print-array (get-*print-frob* '*print-array* nil t)))
+    (declare (type fixnum rank) (type fixnum total-size)
+             (type fixnum print-length))
+    (unless
+      (cond (string?
+             nil)
+            ((and bit-vector? print-array)
+             (stream-write-char stream #\#) (stream-write-char stream #\*)
+             (do ((i 0 (%i+ i 1))
+                  (l print-length (%i- l 1)))
+                 (nil)
+               (declare (type fixnum i) (type fixnum l))
+               (cond ((eql i length)
+                      (return))
+                     (t
+                      (stream-write-char stream (if (eql (bit array i) 0) #\0 #\1)))))
+             t)
+            ((and *print-readably*
+                  (not (array-readably-printable-p array)))
+             nil)
+            ((and *print-pretty* print-array)
+             (let ((*current-level* (if (and *print-level* (not *print-readably*))
+                                      (- *print-level* level)
+                                      0)))
+               (pretty-array stream array))
+             t)
+            (vector?
+             (when (or print-array
+                       (and simple-vector?
+                            (%i<= length (get-*print-frob* 
+                                          '*print-simple-vector*
+                                          0
+                                          target::target-most-positive-fixnum))))
+               (pp-start-block stream "#(")
+               (do ((i 0 (%i+ i 1))
+                    (l print-length (%i- l 1)))
+                   (nil)
+                 (declare (type fixnum i) (type fixnum l))
+                 (cond ((eql i length)
+                        (return))
+                       ((eql l 0)
+                        ;; can't use write-abbreviation since there is
+                        ;;  no `object' for the abbreviation to represent
+                        (unless (eql i 0) (pp-space stream))
+                        (%write-string "..." stream)
+                        (return))
+                       (t (unless (eql i 0) (pp-space stream))
+                          (write-internal stream (aref array i) (%i- level 1) nil))))
+               (pp-end-block stream #\))
+               t))
+            ((and print-array (not fill-pointer?))
+             (let ((rank (array-rank array)))
+               (stream-write-char stream #\#)
+               (%pr-integer rank 10. stream)
+               (stream-write-char stream #\A)
+               (if (eql rank 0)
+                 (write-internal stream (aref array) (%i- level 1) nil)
+                 (multiple-value-bind (array-data offset)
+                                      (array-data-and-offset array)
+                   (write-array-elements-1 
+                     stream level
+                     array-data offset
+                     (array-dimensions array)))))
+             t)
+            (t 
+             ;; fall through -- print randomly
+             nil))
+      ;; print array using #<...>
+      (print-unreadable-object (array stream)
+        (if vector?
+          (progn
+            (write-a-symbol (cond (simple-vector?
+                                   'simple-vector)
+                                  (string?
+                                   (if simple? 'simple-string 'string))
+                                  (bit-vector?
+                                   (if simple? 'simple-bit-vector 'bit-vector))
+                                  (t 'vector))
+                            stream)
+            (pp-space stream)
+            (%pr-integer total-size 10. stream)
+            (when fill-pointer?
+              (let ((fill-pointer (fill-pointer array)))
+                (declare (fixnum fill-pointer))
+                (pp-space stream)
+                (%write-string "fill-pointer" stream)
+                (unless (eql fill-pointer total-size)
+                  (stream-write-char stream #\space)
+                  (%pr-integer fill-pointer 10. stream)))))
+          (progn
+            (write-a-symbol 'array stream)
+            (pp-space stream)
+            (if (eql rank 0) (%write-string "0-dimensional" stream))
+            (dotimes (i (the fixnum rank))
+              (unless (eql i 0) (stream-write-char stream #\x))
+              (%pr-integer (array-dimension array i) 10. stream))))
+        (let ((type (array-element-type array)))
+          (unless (or simple-vector? string? bit-vector?   ; already written "#<string" or whatever
+                      (eq type 't))
+            (pp-space stream)
+            (%write-string "type " stream)
+            (write-internal stream type
+                            ;; yes, I mean level, not (1- level)
+                            ;; otherwise we end up printing things
+                            ;; like "#<array 4 type #>"
+                            level nil)))
+        (cond (simple?
+               (unless (or simple-vector? string? bit-vector?)
+                 ;; already written "#<simple-xxx"
+                 (stream-write-char stream #\,)
+                 (pp-space stream)
+                 (%write-string "simple" stream)))
+              (adjustable?
+               (stream-write-char stream #\,)
+               (pp-space stream)
+               (%write-string "adjustable" stream))
+              (displaced?
+               ;; all multidimensional (and adjustable) arrays in ccl are
+               ;;  displaced, even when they are simple-array-p
+               (stream-write-char stream #\,)
+               (pp-space stream)
+               (%write-string "displaced" stream)))
+        ;; (when stack-allocated? ...) etc, etc
+        (when (and string? (%i> length 20))
+          (flet ((foo (stream string start end)
+                      (declare (type fixnum start) (type fixnum end)
+                               (type string string))
+                      (do ((i start (%i+ i 1)))
+                          ((%i>= i end))
+                        (let ((c (char string i)))
+                          (declare (type character c))
+                          (if (not (graphic-char-p c))
+                            (return)
+                            (%write-escaped-char stream c #\\ #\"))))))
+            #|(%write-string " \"" stream)|# (pp-space stream)
+            (foo stream array 0 12)
+            (%write-string "..." stream)
+            (foo stream array (%i- length 6) length)
+              #|(stream-write-char stream #\")|#))))))
+
+(defun write-array-elements-1 (stream level
+                               array-data offset
+                               dimensions)
+  (declare (type stream stream) (type fixnum level) 
+           (type vector array-data) (type fixnum offset)
+           (type list dimensions))
+  (block written
+    (let ((tail (%cdr dimensions))
+          (print-length (get-*print-frob* '*print-length*))
+          (level-1 (%i- level 1))
+          (limit (%car dimensions))
+          (step 1))
+      (when (and (null tail)
+                 (%i> level-1 0)
+                 (or (bit-vector-p array-data)
+                     (and (stringp array-data)
+                          (%i<= limit print-length))))
+        (return-from written
+          ;;>> cons cons.  I was lazy.
+          ;;>>  Should code a loop to write the elements instead
+          (write-an-array (%make-displaced-array
+                            ;; dimensions displaced-to
+                            limit array-data 
+                            ;; fill-pointer adjustable
+                            nil nil
+                            ;; displaced-index-offset
+                            offset)
+                          stream level-1)))
+      (pp-start-block stream #\()
+      (dolist (e tail) (setq step (%i* e step)))
+      (do* ((o offset (%i+ o step))
+            (i 0 (1+ i)))
+           (nil)
+        (declare (type fixnum o) (type fixnum i) (type fixnum limit)
+                 (type fixnum step) (type fixnum print-length) 
+                 (type fixnum level-1))
+        (cond ((eql i print-length)
+               (%write-string " ..." stream)
+               (return))
+              ((eql i limit)
+               (return))
+              ((= i 0))
+              (t
+               (pp-space stream (if (null tail) ':fill ':linear))))
+        (cond ((null tail)
+               (write-internal stream (aref array-data o) level-1 nil))
+              ((eql level-1 0)
+               ;; can't use write-abbreviation since this doesn't really
+               ;;  abbreviate a single object
+               (stream-write-char stream #\#))
+              (t
+               (write-array-elements-1 stream level-1
+                                       array-data o tail))))
+      (pp-end-block stream #\)))))
+    
+;;;; ----------------------------------------------------------------------
+
+; A "0" in the sd-print-function => inherit from superclass.
+(defun structure-print-function (class)
+  (let* ((pf (ccl::sd-print-function class))
+         (supers (cdr (sd-superclasses class))))
+    (do* ()
+         ((neq pf 0) pf)
+      (if supers 
+        (setq pf (sd-print-function (gethash (pop supers) %defstructs%)))
+        (return)))))
+
+(defun write-a-structure (object stream level)
+  (declare (type stream stream) (type fixnum level))
+  (let* ((class (ccl::struct-def object)) ;;guaranteed non-NIL if this function is called
+         (pf (structure-print-function class)))
+    (cond (pf
+	   (if (consp pf)
+	     (funcall (%car pf) object stream)
+	     (funcall pf 
+		      object stream (backtranslate-level level))))
+          ((and (not *print-structure*) (not *print-readably*))
+           (print-unreadable-object (object stream :identity t)
+            (write-a-symbol (ccl::sd-name class) stream)))
+          (t
+           (let ((level-1 (ccl::%i- level 1))
+                 (slots (cdr (ccl::sd-slots class)))
+                 (print-length (get-*print-frob* '*print-length*)))
+             (declare (type fixnum level-1) (type list slots))
+             (%write-string "#S(" stream)
+             (if (%i> print-length 0)
+                 (write-a-symbol (ccl::sd-name class) stream)
+                 (progn (%write-string "...)" stream)
+                        (return-from write-a-structure)))
+             (when (and slots (%i> print-length 1))
+               (pp-start-block stream #\Space))
+             (do ((l (%i- print-length 1) (%i- l 2))
+                  (first? t)
+                  (print-case (get-*print-case*)))
+                 (nil)
+               (declare (type fixnum l))
+               (cond ((null slots)
+                      (return))
+                     ((%i< l 1)
+                      ;; Note write-abbreviation since it isn't abbreviating an object
+                      (%write-string " ..." stream)
+                      (return)))
+               (let* ((slot (prog1 (%car slots)
+                              (setq slots (%cdr slots))))
+                      (symbol (ccl::ssd-name slot)))
+                 (when (symbolp symbol)
+                   (if first?
+                       (setq first? nil)
+                       (pp-space stream ':linear))
+                   (stream-write-char stream #\:)
+                   (write-pname (symbol-name symbol) print-case stream)
+                   (cond ((%i> l 1)
+                          (pp-space stream)
+                          (write-internal stream (uvref object (ccl::ssd-offset slot))
+                                            level-1 nil))
+                         (t (%write-string " ..." stream)
+                            (return)))))))
+           (pp-end-block stream #\))))))
+
+(%fhave 'encapsulated-function-name ;(fn) ;Redefined in encapsulate
+        (qlfun bootstrapping-encapsulated-function-name (fn)
+          (declare (ignore fn))
+          nil))
+
+
+(%fhave '%traced-p ;(fn) ;Redefined in encapsulate
+        (qlfun bootstrapping-%traced-p (fn)
+          (declare (ignore fn))
+          nil))
+
+(%fhave '%advised-p ;(fn) ;Redefined in encapsulate
+        (qlfun bootstrapping-%advised-p (fn)
+          (declare (ignore fn))
+          nil))
+
+
+
+(defun write-a-function (lfun stream level)  ; screwed up
+  (print-unreadable-object (lfun stream :identity t)
+    (let* ((name (function-name lfun))
+           ; actually combined-method has its oun print-object method and doesn't get here.
+           ; standard-generic-function has a print-object method that just calls this.
+           (gf-or-cm (or (standard-generic-function-p lfun) (combined-method-p lfun))))
+      (cond ((and (not (compiled-function-p lfun))
+                  (not gf-or-cm))
+             ; i.e. closures
+             (write-internal stream (%type-of lfun) level nil)
+             (when name
+               (pp-space stream)
+               (write-internal stream name (%i- level 1) nil)))
+            ((not name)
+             (%lfun-name-string lfun stream t))
+            (t
+             (if gf-or-cm
+               (write-internal stream (class-name (class-of lfun)) level nil)
+               (%write-string (cond ((typep lfun 'method-function)
+                                     "Compiled Method-function")
+                                    (t "Compiled-function"))
+                            stream))
+             (stream-write-char stream #\space)
+             (write-internal stream name (%i- level 1) nil)
+             (cond ((and (symbolp name) (eq lfun (macro-function name)))
+                    (%write-string " Macroexpander" stream)) ;What better?                 
+                   ((not (function-is-current-definition? lfun))
+                    ;;>> Nice if it could print (Traced), (Internal), (Superseded), etc
+                    (cond ((%traced-p name)
+                           (%write-string " (Traced Original) " stream))
+                          ((%advised-p name)
+                           (%write-string " (Advised Original) " stream))
+                          (t (%write-string " (Non-Global) " stream))))))))))
+
+
+(defun function-is-current-definition? (function)
+  (let ((name (function-name function)))
+    (and name
+         (valid-function-name-p name)
+         (eq function (fboundp name)))))
+
+;; outputs to stream or returns a string.  Barf!
+;; Making not matters not worse ...
+(defun %lfun-name-string (lfun &optional stream suppress-address)
+  (unless (functionp lfun) (report-bad-arg lfun 'function))
+  (if (null stream)
+    (with-output-to-string (s) (%lfun-name-string lfun s))
+    (let ((name (function-name lfun)))
+      (if name
+	(prin1 name stream)
+	(let* ((fnaddr (%address-of lfun))
+	       (kernel-function-p (kernel-function-p lfun)))
+	  (%write-string (if kernel-function-p
+			   "Internal " "Anonymous ")
+			 stream)
+	  (if (standard-generic-function-p lfun)
+	    (prin1 (class-name (class-of lfun)) stream)
+	    (%write-string "Function" stream))
+	  (unless suppress-address
+	    (stream-write-char stream #\ )
+	    (write-an-integer  fnaddr
+			       stream 16. t)))))))
+
+
+;;;; ----------------------------------------------------------------------
+
+(defun write-a-package (pkg stream)
+  (print-unreadable-object (pkg stream)
+    (if (null (pkg.names pkg))
+      (%write-string "Deleted Package" stream)
+      (progn
+        (%write-string "Package " stream)
+        (write-escaped-string (package-name pkg) stream)))))
+
+
+
+(defun write-a-macptr (macptr stream)
+  (let* ((null (%null-ptr-p macptr)))
+    (print-unreadable-object (macptr stream)
+      (if null
+	(progn
+	  (%write-string "A Null Foreign Pointer" stream))
+	(progn
+	  (pp-start-block stream "A Foreign Pointer")
+	  (%write-macptr-allocation-info macptr stream)
+	  (stream-write-char stream #\ )
+          (%write-macptr-type-info macptr stream)
+	  (write-an-integer (%ptr-to-int macptr) stream 16. t))))))
+
+(defun %macptr-allocation-string (macptr)
+  (if (or (on-any-csp-stack macptr)
+          (on-any-tsp-stack macptr))
+    "[stack-allocated]"
+    (if (eql (uvsize macptr) target::xmacptr.element-count)
+      "[gcable]")))
+
+(defun %write-macptr-allocation-info (macptr stream)
+  (let* ((s (%macptr-allocation-string macptr)))
+    (if s (format stream " ~a" s))))
+
+(defun %write-macptr-type-info (macptr stream)
+  (let* ((ordinal (%macptr-type macptr)))
+    (unless (eql 0 ordinal)
+      (let* ((type (gethash ordinal (ftd-ordinal-types *target-ftd*)))
+             (form
+              (if (typep type 'foreign-record-type)
+                `(:* (,(foreign-record-type-kind type)
+                        ,(foreign-record-type-name type)))
+                `(:* ,(unparse-foreign-type type)))))
+        (when form (format stream "~s " form))))))
+          
+
+
+; This special-casing for wrappers is cheaper than consing a class
+(defun write-an-istruct (istruct stream level)
+  (let* ((type (istruct-cell-name (uvref istruct 0)))
+         (wrapper-p  (eq type 'class-wrapper)))
+    (print-unreadable-object (istruct stream :identity t)
+      (write-internal stream type (%i- level 1) nil)
+      (when wrapper-p
+        (pp-space stream)
+        (print-object (class-name (%wrapper-class istruct)) stream)))))
+
+(defun write-a-uvector (uvec stream level)
+  (declare (ignore level))
+  (print-unreadable-object (uvec stream :identity t :type t)))
+  
+
+(defmethod print-object ((slotdef slot-definition) stream)
+  (print-unreadable-object (slotdef stream :identity t :type t)
+    (format stream "for ~a slot ~s"
+            (string-downcase (slot-definition-allocation slotdef))
+            (standard-slot-definition.name slotdef))))
+
+(defmethod print-object ((spec eql-specializer) stream)
+  (print-unreadable-object (spec stream :identity t :type t)
+    (format stream "~s" (if (slot-boundp spec 'object)
+			  (eql-specializer-object spec)
+			  "<unbound>"))))
+
+
+(defmethod print-object ((slot-id slot-id) stream)
+  (print-unreadable-object (slot-id stream :identity t :type t)
+    (format stream "for ~s/~d"
+            (slot-id.name  slot-id)
+            (slot-id.index  slot-id))))
+
+#+x86-target
+(defmethod print-object ((tra tagged-return-address) stream)
+  (print-unreadable-object (tra stream :identity t :type t)
+    (let* ((f (%return-address-function tra))
+           (offset (if f (%return-address-offset tra))))
+      (when offset
+        (format stream "in function ")
+        (%lfun-name-string f stream)
+        (format stream " (+~d)" offset)))))
+
+#+x8664-target
+(defmethod print-object ((sv symbol-vector) stream)
+  (print-unreadable-object (sv stream :identity t :type t)
+    (format stream "for ~s" (%symptr->symbol (%symvector->symptr sv)))))
+
+#+x8664-target
+(defmethod print-object ((fv function-vector) stream)
+  (print-unreadable-object (fv stream :identity t :type t)
+    (format stream "for ")
+    (%lfun-name-string (%function-vector-to-function fv) stream)))
+
+(defmethod print-object ((c class-cell) stream)
+  (print-unreadable-object (c stream :type t :identity t)
+    (format stream "for ~s" (class-cell-name c))))
+  
+            
+
+;;; ======================================================================
+
+
+(defun real-print-stream (&optional (stream nil))
+  (cond ((null stream)
+         *standard-output*)
+        ((eq stream t)
+         *terminal-io*)
+        ((streamp stream)
+         stream)
+        ;; This never gets called because streamp is true for xp-structure...
+        ((istruct-typep stream 'xp-structure)
+         (get-xp-stream stream))
+        (t
+         (report-bad-arg stream '(or stream (member nil t))))))
+
+(defun write-1 (object stream &optional levels-left)
+  (setq stream (%real-print-stream stream))
+  (when (not levels-left)
+    (setq levels-left
+          (if *current-level* 
+            (if *print-level*
+              (- *print-level* *current-level*)
+              target::target-most-positive-fixnum)
+            (%current-write-level% stream t))))
+  (cond 
+   ((< levels-left 0)
+    ;; *print-level* truncation
+    (stream-write-entire-string stream "#"))
+   (t (write-internal stream
+                      object 
+                      (min levels-left target::target-most-positive-fixnum)
+                      nil)))
+  object)
+
+;;;; ----------------------------------------------------------------------
+;;;; User-level interface to the printer
+
+
+(defun write (object
+              &key (stream *standard-output*)
+                   (escape *print-escape*)
+                   (radix *print-radix*)
+                   (base *print-base*)
+                   (circle *print-circle*)
+                   (pretty *print-pretty*)
+                   (level *print-level*)
+                   (length *print-length*)
+                   (case *print-case*)
+                   (gensym *print-gensym*)
+                   (array *print-array*)
+                   (readably *print-readably*)
+                   (right-margin *print-right-margin*)
+                   (miser-width *print-miser-width*)
+                   (lines *print-lines*)
+                   (pprint-dispatch *print-pprint-dispatch*)
+                   ;;>> Do I really want to add these to WRITE??
+                   (structure *print-structure*)
+                   (simple-vector *print-simple-vector*)
+                   (simple-bit-vector *print-simple-bit-vector*)
+                   (string-length *print-string-length*))
+  "Output OBJECT to the specified stream, defaulting to *STANDARD-OUTPUT*"
+  (let ((*print-escape* escape)
+        (*print-radix* radix)
+        (*print-base* base)
+        (*print-circle* circle)
+        (*print-pretty* pretty)
+        (*print-level* level)
+        (*print-length* length)
+        (*print-case* case)
+        (*print-gensym* gensym)
+        (*print-array* array)
+        (*print-readably* readably)
+        (*print-right-margin* right-margin)
+        (*print-miser-width* miser-width)
+        (*print-lines* lines)
+        (*print-pprint-dispatch* pprint-dispatch)
+        ;;>> Do I really want to add these to WRITE??
+        (*print-structure* structure)
+        (*print-simple-vector* simple-vector)
+        (*print-simple-bit-vector* simple-bit-vector)
+        (*print-string-length* string-length))
+    (write-1 object stream)))
+
+(defun write-to-string (object
+                        &key (escape *print-escape*)
+                             (radix *print-radix*)
+                             (base *print-base*)
+                             (circle *print-circle*)
+                             (pretty *print-pretty*)
+                             (level *print-level*)
+                             (length *print-length*)
+                             (case *print-case*)
+                             (gensym *print-gensym*)
+                             (array *print-array*)
+                             (readably *print-readably*)
+                             (right-margin *print-right-margin*)
+                             (miser-width *print-miser-width*)
+                             (lines *print-lines*)
+                             (pprint-dispatch *print-pprint-dispatch*)
+                             ;;>> Do I really want to add these to WRITE??
+                             (structure *print-structure*)
+                             (simple-vector *print-simple-vector*)
+                             (simple-bit-vector *print-simple-bit-vector*)
+                             (string-length *print-string-length*))
+  "Return the printed representation of OBJECT as a string."
+    (let ((*print-escape* escape)
+          (*print-radix* radix)
+          (*print-base* base)
+          (*print-circle* circle)
+          (*print-pretty* pretty)
+          (*print-level* level)
+          (*print-length* length)
+          (*print-case* case)
+          (*print-gensym* gensym)
+          (*print-array* array)
+          ;; I didn't really wan't to add these, but I had to.
+          (*print-readably* readably)
+          (*print-right-margin* right-margin)
+          (*print-miser-width* miser-width)
+          (*print-lines* lines)
+          (*print-pprint-dispatch* pprint-dispatch)
+          ;;>> Do I really want to add these to WRITE??
+          (*print-structure* structure)
+          (*print-simple-vector* simple-vector)
+          (*print-simple-bit-vector* simple-bit-vector)
+          (*print-string-length* string-length))
+      (with-output-to-string (stream)
+        (write-1 object stream))))
+
+(defun prin1-to-string (object)
+  "Return the printed representation of OBJECT as a string with
+   slashification on."
+  (with-output-to-string (s)
+    (prin1 object s)))
+
+(defun princ-to-string (object)
+  "Return the printed representation of OBJECT as a string with
+  slashification off."
+  (with-output-to-string (s)
+    (princ object s)))
+
+(defun prin1 (object &optional stream)
+  "Output a mostly READable printed representation of OBJECT on the specified
+  STREAM."
+  (let ((*print-escape* t))
+    (write-1 object stream)))
+
+(defun princ (object &optional stream)
+  "Output an aesthetic but not necessarily READable printed representation
+  of OBJECT on the specified STREAM."
+  (let ((*print-escape* nil)
+        (*print-readably* nil))
+    (write-1 object stream)))
+
+(defun print (object &optional stream)
+  "Output a newline, the mostly READable printed representation of OBJECT, and
+  space to the specified STREAM."
+  (terpri stream)
+  (let ((*print-escape* t))
+    (write-1 object stream))
+  (write-char #\Space stream)
+  object)
+
+; redefined by pprint module if loaded
+(defun pprint (object &optional stream)
+  (print object stream)
+  nil)                                  ; pprint returns nil
+
+
+(defun read-sequence (seq stream &key (start 0) end)
+  "Destructively modify SEQ by reading elements from STREAM.
+  That part of SEQ bounded by START and END is destructively modified by
+  copying successive elements into it from STREAM. If the end of file
+  for STREAM is reached before copying all elements of the subsequence,
+  then the extra elements near the end of sequence are not updated, and
+  the index of the next element is returned."
+  (setq end (check-sequence-bounds seq start end))
+  (locally (declare (fixnum start end))
+    (if (= start end)
+      start
+      (seq-dispatch
+       seq
+       (+ start (the fixnum (stream-read-list
+			     stream
+			     (nthcdr start seq)
+			     (the fixnum (- end start)))))
+       (multiple-value-bind (vector offset) (array-data-and-offset seq)
+	 (declare (fixnum offset))
+	 (-
+	  (stream-read-vector
+	   stream
+	   vector
+	   (the fixnum (+ offset start))
+	   (the fixnum (+ offset end)))
+	  offset))))))
+
+
+
+(defun write-sequence (seq stream &key (start 0) end)
+  "Write the elements of SEQ bounded by START and END to STREAM."
+  (setq end (check-sequence-bounds seq start end))
+  (locally (declare (fixnum start end))
+    (seq-dispatch
+     seq
+     (stream-write-list stream (nthcdr start seq) (the fixnum (- end start)))
+     (multiple-value-bind (vector offset) (array-data-and-offset seq)
+       (stream-write-vector
+	stream
+	vector
+	(the fixnum (+ offset start))
+	(the fixnum (+ offset end))))))
+  seq)
+
+(defpackage "GRAY"
+  (:use)
+  (:import-from "CCL"
+                "FUNDAMENTAL-STREAM"
+                "FUNDAMENTAL-INPUT-STREAM"
+                "FUNDAMENTAL-OUTPUT-STREAM"
+                "FUNDAMENTAL-CHARACTER-STREAM"
+                "FUNDAMENTAL-CHARACTER-INPUT-STREAM"
+                "FUNDAMENTAL-CHARACTER-OUTPUT-STREAM"
+                "FUNDAMENTAL-BINARY-STREAM"
+                "FUNDAMENTAL-BINARY-INPUT-STREAM"
+                "FUNDAMENTAL-BINARY-OUTPUT-STREAM"
+
+                "STREAM-READ-CHAR"
+                "STREAM-UNREAD-CHAR"
+                "STREAM-READ-CHAR-NO-HANG"
+                "STREAM-PEEK-CHAR"
+                "STREAM-LISTEN"
+                "STREAM-READ-LINE"
+                "STREAM-CLEAR-INPUT"
+
+                "STREAM-WRITE-CHAR"
+                "STREAM-LINE-COLUMN"
+                "STREAM-START-LINE-P"
+                "STREAM-WRITE-STRING"
+                "STREAM-TERPRI"
+                "STREAM-FRESH-LINE"
+                "STREAM-FORCE-OUTPUT"
+                "STREAM-FINISH-OUTPUT"
+                "STREAM-CLEAR-OUTPUT"
+                "STREAM-ADVANCE-TO-COLUMN"
+
+                "STREAM-READ-BYTE"
+                "STREAM-WRITE-BYTE"
+                )
+  (:export
+   "FUNDAMENTAL-STREAM"
+   "FUNDAMENTAL-INPUT-STREAM"
+   "FUNDAMENTAL-OUTPUT-STREAM"
+   "FUNDAMENTAL-CHARACTER-STREAM"
+   "FUNDAMENTAL-CHARACTER-INPUT-STREAM"
+   "FUNDAMENTAL-CHARACTER-OUTPUT-STREAM"
+   "FUNDAMENTAL-BINARY-STREAM"
+   "FUNDAMENTAL-BINARY-INPUT-STREAM"
+   "FUNDAMENTAL-BINARY-OUTPUT-STREAM"
+
+   "STREAM-READ-CHAR"
+   "STREAM-UNREAD-CHAR"
+   "STREAM-READ-CHAR-NO-HANG"
+   "STREAM-PEEK-CHAR"
+   "STREAM-LISTEN"
+   "STREAM-READ-LINE"
+   "STREAM-CLEAR-INPUT"
+
+   "STREAM-WRITE-CHAR"
+   "STREAM-LINE-COLUMN"
+   "STREAM-START-LINE-P"
+   "STREAM-WRITE-STRING"
+   "STREAM-TERPRI"
+   "STREAM-FRESH-LINE"
+   "STREAM-FORCE-OUTPUT"
+   "STREAM-FINISH-OUTPUT"
+   "STREAM-CLEAR-OUTPUT"
+   "STREAM-ADVANCE-TO-COLUMN"
+
+   "STREAM-READ-BYTE"
+   "STREAM-WRITE-BYTE"
+))
+                
+                
Index: /branches/new-random/level-1/l1-lisp-threads.lisp
===================================================================
--- /branches/new-random/level-1/l1-lisp-threads.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-lisp-threads.lisp	(revision 13309)
@@ -0,0 +1,1116 @@
+;;; -*- Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; l1-lisp-threads.lisp
+
+(in-package "CCL")
+
+(defvar *bind-io-control-vars-per-process* nil
+  "If true, bind I/O control variables per process")
+
+
+	     
+(defun lisp-thread-p (thing)
+  (istruct-typep thing 'lisp-thread))
+
+(setf (type-predicate 'lisp-thread) 'lisp-thread-p)
+
+(defloadvar *ticks-per-second*
+    #+windows-target 1000
+    #-windows-target
+    (#_sysconf #$_SC_CLK_TCK))
+
+(defloadvar *ns-per-tick*
+    (floor 1000000000 *ticks-per-second*))
+
+#-windows-target
+(defun %nanosleep (seconds nanoseconds)
+  (with-process-whostate ("Sleep")
+    (rlet ((a :timespec)
+           (b :timespec))
+      (setf (pref a :timespec.tv_sec) seconds
+            (pref a :timespec.tv_nsec) nanoseconds)
+      (let* ((aptr a)
+             (bptr b))
+        (loop
+          (let* ((result 
+                  (external-call #+darwin-target "_nanosleep"
+                                 #-darwin-target "nanosleep"
+                                 :address aptr
+                                 :address bptr
+                                 :signed-fullword)))
+            (declare (type (signed-byte 32) result))
+            (if (and (< result 0)
+                     (eql (%get-errno) (- #$EINTR)))
+              ;; x86-64 Leopard bug.
+              (let* ((asec (pref aptr :timespec.tv_sec))
+                     (bsec (pref bptr :timespec.tv_sec)))
+                (if (and (>= bsec 0)
+                         (or (< bsec asec)
+                             (and (= bsec asec)
+                                  (< (pref bptr :timespec.tv_nsec)
+                                     (pref aptr :timespec.tv_nsec)))))
+                  (psetq aptr bptr bptr aptr)
+                  (return)))
+              (return))))))))
+
+
+(defun timeval->ticks (tv)
+  (+ (* *ticks-per-second* (pref tv :timeval.tv_sec))
+     (round (pref tv :timeval.tv_usec) (floor 1000000 *ticks-per-second*))))
+
+
+(defun gettimeofday (ptimeval &optional ptz)
+  (int-errno-ffcall (%kernel-import target::kernel-import-lisp-gettimeofday)
+                    :address ptimeval
+                    :address (or ptz (%null-ptr))
+                    :int))
+
+(defloadvar *lisp-start-timeval*
+    (progn
+      (let* ((r (make-record :timeval)))
+        (gettimeofday r)
+        r)))
+
+
+(defloadvar *internal-real-time-session-seconds* nil)
+
+
+(defun get-internal-real-time ()
+  "Return the real time in the internal time format. (See
+  INTERNAL-TIME-UNITS-PER-SECOND.) This is useful for finding elapsed time."
+  (rlet ((tv :timeval))
+    (gettimeofday tv)
+    (let* ((units (truncate (the fixnum (pref tv :timeval.tv_usec)) (/ 1000000 internal-time-units-per-second)))
+           (initial *internal-real-time-session-seconds*))
+      (if initial
+        (locally
+            (declare (type (unsigned-byte 32) initial))
+          (+ (* internal-time-units-per-second
+                (the (unsigned-byte 32)
+                  (- (the (unsigned-byte 32) (pref tv :timeval.tv_sec))
+                     initial)))
+             units))
+        (progn
+          (setq *internal-real-time-session-seconds*
+                (pref tv :timeval.tv_sec))
+          units)))))
+
+(defun get-tick-count ()
+  (values (floor (get-internal-real-time)
+                 (floor internal-time-units-per-second
+                        *ticks-per-second*))))
+
+
+
+
+(defun %kernel-global-offset (name-or-offset)
+  (if (fixnump name-or-offset)
+    name-or-offset
+    (target::%kernel-global name-or-offset)))
+
+
+(defun %kernel-global-offset-form (name-or-offset-form)
+  (cond ((quoted-form-p name-or-offset-form)
+         `(%target-kernel-global ,name-or-offset-form))
+        ((fixnump name-or-offset-form)
+         name-or-offset-form)
+        (t `(%target-kernel-global ',name-or-offset-form))))
+
+
+
+(defmacro %set-kernel-global (name-or-offset new-value)
+  `(%set-kernel-global-from-offset
+    ,(%kernel-global-offset-form name-or-offset)
+    ,new-value))
+
+
+
+; The number of bytes in a consing (or stack) area
+(defun %area-size (area)
+  (ash (- (%fixnum-ref area target::area.high)
+          (%fixnum-ref area target::area.low))
+       target::fixnumshift))
+
+(defun %stack-area-usable-size (area)
+  (ash (- (%fixnum-ref area target::area.high)
+	  (%fixnum-ref area target::area.softlimit))
+       target::fixnum-shift))
+
+(defun %cons-lisp-thread (name &optional tcr)
+  (%istruct 'lisp-thread
+	    tcr
+	    name
+	    0
+	    0
+	    0
+	    nil
+	    nil
+            (make-lock)
+	    nil
+	    :reset
+	    (make-lock)))
+
+(defvar *current-lisp-thread*
+  (%cons-lisp-thread "Initial" (%current-tcr)))
+
+(defstatic *initial-lisp-thread* *current-lisp-thread*)
+
+(defun thread-change-state (thread oldstate newstate)
+  (with-lock-grabbed ((lisp-thread.state-change-lock thread))
+    (when (eq (lisp-thread.state thread) oldstate)
+      (setf (lisp-thread.state thread) newstate))))
+
+(thread-change-state *initial-lisp-thread* :reset :run)
+
+(defun thread-state (thread)
+  (with-lock-grabbed ((lisp-thread.state-change-lock thread))
+    (lisp-thread.state thread)))
+  
+(defun thread-make-startup-function (thread tcr)
+  #'(lambda ()
+      (thread-change-state thread :reset :run)
+      (let* ((*current-lisp-thread* thread)
+	     (initial-function (lisp-thread.initial-function.args thread)))
+	(tcr-clear-preset-state tcr)
+	(%set-tcr-toplevel-function tcr nil)
+	(setf (interrupt-level) 0)
+	(apply (car initial-function) (cdr initial-function))
+	(cleanup-thread-tcr thread tcr))))
+
+(defun init-thread-from-tcr (tcr thread)
+  (let* ((cs-area (%fixnum-ref tcr target::tcr.cs-area))
+         (vs-area (%fixnum-ref tcr target::tcr.vs-area))
+         (ts-area (%fixnum-ref tcr target::tcr.ts-area)))
+    (when (or (zerop cs-area)
+              (zerop vs-area)
+              (zerop ts-area))
+      (error "Can't allocate new thread"))
+    (setf (lisp-thread.tcr thread) tcr
+          (lisp-thread.cs-size thread)
+          (%stack-area-usable-size cs-area)
+          (lisp-thread.vs-size thread)
+          (%stack-area-usable-size vs-area)
+          (lisp-thread.ts-size thread)
+          (%stack-area-usable-size ts-area)
+          (lisp-thread.startup-function thread)
+          (thread-make-startup-function thread tcr)))
+  (thread-change-state thread :exit :reset)
+  thread)
+
+(defun default-allocation-quantum ()
+  (ash 1 (%get-kernel-global 'default-allocation-quantum)))
+
+(defun new-lisp-thread-from-tcr (tcr name)
+  (let* ((thread (%cons-lisp-thread name tcr)))    
+    (init-thread-from-tcr tcr thread)
+    (push thread (population-data *lisp-thread-population*))
+    thread))
+
+(def-ccl-pointers initial-thread ()
+  (init-thread-from-tcr (%current-tcr) *initial-lisp-thread*))
+
+(defmethod print-object ((thread lisp-thread) stream)
+  (print-unreadable-object (thread stream :type t :identity t)
+    (format stream "~a" (lisp-thread.name thread))
+    (let* ((tcr (lisp-thread.tcr thread)))
+      (if (and tcr (not (eql 0 tcr)))
+	(format stream " [tcr @ #x~x]" (ash tcr target::fixnumshift))))))
+
+
+(defvar *lisp-thread-population*
+  (%cons-population (list *initial-lisp-thread*) $population_weak-list nil))
+
+
+
+
+
+(defparameter *default-control-stack-size*
+  #+32-bit-target (ash 1 20)
+  #+64-bit-target (ash 2 20))
+(defparameter *default-value-stack-size*
+  #+32-bit-target (ash 1 20)
+  #+64-bit-target (ash 2 20))
+(defparameter *default-temp-stack-size*
+  #+32-bit-target (ash 1 19)
+  #+64-bit-target (ash 2 19))
+
+
+(defstatic *initial-listener-default-control-stack-size* *default-control-stack-size*)
+(defstatic *initial-listener-default-value-stack-size* *default-value-stack-size*)
+(defstatic *initial-listener-default-temp-stack-size* *default-temp-stack-size*)
+
+
+(def-ccl-pointers listener-stack-sizes ()
+  (let* ((size (%get-kernel-global 'stack-size))) ; set by --thread-stack-size
+    (declare (fixnum size))
+    (when (> size 0)
+      (setq *initial-listener-default-control-stack-size* size
+            *initial-listener-default-value-stack-size* size
+            *initial-listener-default-temp-stack-size* (floor size 2)))))
+
+
+(defmacro with-area-macptr ((var area) &body body)
+  `(with-macptrs (,var)
+     (%setf-macptr-to-object ,var ,area)
+     ,@body))
+
+
+(defun gc-area.return-sp (area)
+  (%fixnum-ref area target::area.gc-count))
+
+
+(defun (setf gc-area.return-sp) (return-sp area)
+  (setf (%fixnum-ref area target::area.gc-count) return-sp))
+
+
+
+(defun shutdown-lisp-threads ()
+  )
+
+(defun %current-xp ()
+  (let ((xframe (%fixnum-ref (%current-tcr) target::tcr.xframe)))
+    (when (eql xframe 0)
+      (error "No current exception frame"))
+    (%fixnum-ref xframe
+                 (get-field-offset :xframe-list.this))))
+
+(defun new-tcr (cs-size vs-size ts-size)
+  (let* ((tcr (macptr->fixnum
+               (ff-call
+                (%kernel-import target::kernel-import-newthread)
+                #+64-bit-target :unsigned-doubleword
+                #+32-bit-target :unsigned-fullword cs-size
+                #+64-bit-target :unsigned-doubleword
+                #+32-bit-target :unsigned-fullword vs-size
+                #+64-bit-target :unsigned-doubleword
+                #+32-bit-target :unsigned-fullword ts-size
+                :address))))
+    (declare (fixnum tcr))
+    (if (zerop tcr)
+      (error "Can't create thread")
+      tcr)))
+
+(defun new-thread (name cstack-size vstack-size tstack-size)
+  (new-lisp-thread-from-tcr (new-tcr cstack-size vstack-size tstack-size) name))
+
+(defun new-tcr-for-thread (thread)
+  (let* ((tcr (new-tcr
+	       (lisp-thread.cs-size thread)
+	       (lisp-thread.vs-size thread)
+	       (lisp-thread.ts-size thread))))
+    (setf (lisp-thread.tcr thread) tcr
+	  (lisp-thread.startup-function thread)
+	  (thread-make-startup-function thread tcr))
+    (thread-change-state thread :exit :reset)
+    tcr))
+  
+	 
+
+
+
+(defconstant cstack-hardprot (ash 100 10))
+(defconstant cstack-softprot (ash 100 10))
+
+
+
+(defun tcr-flags (tcr)
+  (%fixnum-ref tcr target::tcr.flags))
+
+
+
+(defun %tcr-frame-ptr (tcr)
+  (with-macptrs (p)
+    (%setf-macptr-to-object p tcr)
+    (%fixnum-from-macptr
+     (ff-call (%kernel-import target::kernel-import-tcr-frame-ptr)
+              :address p
+              :address))))
+ 
+(defun thread-exhausted-p (thread)
+  (or (null thread)
+      (null (lisp-thread.tcr thread))))
+
+(defun thread-total-run-time (thread)
+  (unless (thread-exhausted-p thread)
+    nil))
+
+(defun %tcr-interrupt (tcr)
+  ;; The other thread's interrupt-pending flag might get cleared
+  ;; right after we look and see it set, but since this is called
+  ;; with the lock on the thread's interrupt queue held, the
+  ;; pending interrupt won't have been taken yet.
+  ;; When a thread dies, it should try to clear its interrupt-pending
+  ;; flag.
+  (if (eql 0 (%fixnum-ref tcr target::tcr.interrupt-pending))
+    (%%tcr-interrupt tcr)
+    0))
+
+
+
+     
+     
+
+(defun thread-interrupt (thread process function &rest args)
+  (with-lock-grabbed ((lisp-thread.state-change-lock thread))
+    (case (lisp-thread.state thread)
+      (:run 
+       (with-lock-grabbed ((lisp-thread.interrupt-lock thread))
+         (let ((tcr (lisp-thread.tcr thread)))
+	   (when tcr
+	     (push (cons function args)
+		   (lisp-thread.interrupt-functions thread))
+	     (eql 0 (%tcr-interrupt tcr))))))
+      (:reset
+       ;; Preset the thread with a function that'll return to the :reset
+       ;; state
+       (let* ((pif (process-initial-form process))
+	      (pif-f (car pif))
+	      (pif-args (cdr pif)))
+	 (process-preset process #'(lambda ()
+				     (%rplaca pif pif-f)
+				     (%rplacd pif pif-args)
+				     (apply function args)
+				     ;; If function returns normally,
+				     ;; return to the reset state
+				     (%process-reset nil)))
+	 (thread-enable thread (process-termination-semaphore process) (1- (integer-length (process-allocation-quantum process))) 0)
+         t)))))
+
+(defun thread-handle-interrupts ()
+  (let* ((thread *current-lisp-thread*))
+    (with-process-whostate ("Active")
+      (loop
+        (let* ((f (with-lock-grabbed ((lisp-thread.interrupt-lock thread))
+                    (pop (lisp-thread.interrupt-functions thread)))))
+          (if f
+            (apply (car f) (cdr f))
+            (return)))))))
+
+
+	
+(defun  thread-preset (thread function &rest args)
+  (setf (lisp-thread.initial-function.args thread)
+	(cons function args)))
+
+(defun thread-enable (thread termination-semaphore allocation-quantum &optional (timeout (* 60 60 24)))
+  (let* ((tcr (or (lisp-thread.tcr thread) (new-tcr-for-thread thread))))
+    (with-macptrs (s)
+      (%setf-macptr-to-object s (%fixnum-ref tcr target::tcr.reset-completion))
+      (when (%timed-wait-on-semaphore-ptr s timeout nil)
+        (%set-tcr-toplevel-function
+         tcr
+         (lisp-thread.startup-function thread))
+        (%activate-tcr tcr termination-semaphore allocation-quantum)
+        thread))))
+			      
+
+(defun cleanup-thread-tcr (thread tcr)
+  (let* ((flags (%fixnum-ref tcr target::tcr.flags)))
+    (declare (fixnum flags))
+    (if (logbitp arch::tcr-flag-bit-awaiting-preset flags)
+      (thread-change-state thread :run :reset)
+      (progn
+	(thread-change-state thread :run :exit)
+	(setf (lisp-thread.tcr thread) nil)))))
+
+(defun kill-lisp-thread (thread)
+  (unless (eq thread *initial-lisp-thread*)
+    (let* ((tcr (lisp-thread.tcr thread)))
+      (when tcr
+        (setf (lisp-thread.tcr thread) nil
+              (lisp-thread.state thread) :exit)
+	(%kill-tcr tcr)))))
+
+;;; This returns the underlying pthread, whatever that is, as an
+;;; unsigned integer.
+(defun lisp-thread-os-thread (thread)
+  (with-macptrs (tcrp)
+    (%setf-macptr-to-object tcrp (lisp-thread.tcr thread))
+    (unless (%null-ptr-p tcrp)
+      (let* ((natural (%get-natural tcrp target::tcr.osid)))
+        (unless (zerop natural) natural)))))
+
+
+                         
+;;; This returns something lower-level than the pthread, if that
+;;; concept makes sense.  On current versions of Linux, it returns
+;;; the pid of the clone()d process; on Darwin, it returns a Mach
+;;; thread.  On some (near)future version of Linux, the concept
+;;; may not apply.
+;;; The future is here: on Linux systems using NPTL, this returns
+;;; exactly the same thing that (getpid) does.
+;;; This should probably be retired; even if it does something
+;;; interesting, is the value it returns useful ?
+
+(defun lisp-thread-native-thread (thread)
+  (with-macptrs (tcrp)
+    (%setf-macptr-to-object tcrp (lisp-thread.tcr thread))
+    (unless (%null-ptr-p tcrp)
+      (#+32-bit-target %get-unsigned-long
+       #+64-bit-target %%get-unsigned-longlong tcrp target::tcr.native-thread-id))))
+
+(defun lisp-thread-suspend-count (thread)
+  (with-macptrs (tcrp)
+    (%setf-macptr-to-object tcrp (lisp-thread.tcr thread))
+    (unless (%null-ptr-p tcrp)
+      (#+32-bit-target %get-unsigned-long
+       #+64-bit-target %%get-unsigned-longlong tcrp target::tcr.suspend-count))))
+
+(defun tcr-clear-preset-state (tcr)
+  (let* ((flags (%fixnum-ref tcr target::tcr.flags)))
+    (declare (fixnum flags))
+    (setf (%fixnum-ref tcr target::tcr.flags)
+	  (bitclr arch::tcr-flag-bit-awaiting-preset flags))))
+
+(defun tcr-set-preset-state (tcr)
+  (let* ((flags (%fixnum-ref tcr target::tcr.flags)))
+    (declare (fixnum flags))
+    (setf (%fixnum-ref tcr target::tcr.flags)
+	  (bitset arch::tcr-flag-bit-awaiting-preset flags))))  
+
+;;; This doesn't quite activate the thread; see PROCESS-TCR-ENABLE.
+(defun %activate-tcr (tcr termination-semaphore allocation-quantum)
+  (declare (ignore termination-semaphore))
+  (if (and tcr (not (eql 0 tcr)))
+    (with-macptrs (tcrp)
+      (%setf-macptr-to-object tcrp tcr)
+      (setf (%get-natural tcrp target::tcr.log2-allocation-quantum)
+            (or allocation-quantum (default-allocation-quantum)))
+      t)))
+                         
+(defvar *canonical-error-value*
+  '(*canonical-error-value*))
+
+
+(defun symbol-value-in-tcr (sym tcr)
+  (if (eq tcr (%current-tcr))
+    (%sym-value sym)
+    (unwind-protect
+         (progn
+           (%suspend-tcr tcr)
+           (let* ((loc (%tcr-binding-location tcr sym)))
+             (if loc
+               (%fixnum-ref loc)
+               (%sym-global-value sym))))
+      (%resume-tcr tcr))))
+
+(defun (setf symbol-value-in-tcr) (value sym tcr)
+  (if (eq tcr (%current-tcr))
+    (%set-sym-value sym value)
+    (unwind-protect
+         (progn
+           (%suspend-tcr tcr)
+           (let* ((loc (%tcr-binding-location tcr sym)))
+             (if loc
+               (setf (%fixnum-ref loc) value)
+               (%set-sym-global-value sym value))))
+      (%resume-tcr tcr))))
+
+;;; Backtrace support
+;;;
+
+
+
+(defmacro do-db-links ((db-link &optional var value) &body body)
+  (let ((thunk (gensym))
+        (var-var (or var (gensym)))
+        (value-var (or value (gensym))))
+    `(block nil
+       (let ((,thunk #'(lambda (,db-link ,var-var ,value-var)
+                         (declare (ignorable ,db-link))
+                         ,@(unless var (list `(declare (ignore ,var-var))))
+                         ,@(unless value (list `(declare (ignore ,value-var))))
+                         ,@body)))
+         (declare (dynamic-extent ,thunk))
+         (map-db-links ,thunk)))))
+
+
+
+
+(defun map-db-links (f)
+  (without-interrupts
+   (let ((db-link (%current-db-link)))
+     (loop
+       (when (eql 0 db-link) (return))
+       (funcall f db-link (%fixnum-ref db-link (* 1 target::node-size)) (%fixnum-ref db-link (* 2 target::node-size)))
+       (setq db-link (%fixnum-ref db-link))))))
+
+(defun %get-frame-ptr ()
+  (%current-frame-ptr))
+
+(defun %current-exception-frame ()
+  #+ppc-target *fake-stack-frames*
+  #+x86-target (or (let* ((xcf (%current-xcf)))
+                     (if xcf
+                       (%%frame-backlink xcf)))
+                   (%current-frame-ptr)))
+
+
+
+
+
+(defun next-catch (catch)
+  (let ((next-catch (uvref catch target::catch-frame.link-cell)))
+    (unless (eql next-catch 0) next-catch)))
+
+
+
+
+; @@@ this needs to load early so errors can work
+(defun next-lisp-frame (p context)
+  (let ((frame p))
+    (loop
+      (let ((parent (%frame-backlink frame context)))
+        (multiple-value-bind (lisp-frame-p bos-p) (lisp-frame-p parent context)
+          (if lisp-frame-p
+            (return parent)
+            (if bos-p
+              (return nil))))
+        (setq frame parent)))))
+
+(defun parent-frame (p context)
+  (loop
+    (let ((parent (next-lisp-frame p context)))
+      (when (or (null parent)
+                (not (catch-csp-p parent context)))
+        (return parent))
+      (setq p parent))))
+
+
+
+
+
+(defun last-frame-ptr (&optional context origin)
+  (let* ((current (or origin
+                      (if context (bt.current context) (%current-frame-ptr))))
+         (last current))
+    (loop
+      (setq current (parent-frame current context))
+      (if current
+        (setq last current)
+        (return last)))))
+
+
+
+(defun child-frame (p context )
+  (let* ((current (if context (bt.current context) (%current-frame-ptr)))
+         (last nil))
+    (loop
+      (when (null current)
+        (return nil))
+      (when (eq current p) (return last))
+      (setq last current
+            current (parent-frame current context)))))
+
+
+
+
+
+; This returns the current head of the db-link chain.
+(defun db-link (&optional context)
+  (if context
+    (bt.db-link context)
+    (%fixnum-ref (%current-tcr)  target::tcr.db-link)))
+
+(defun previous-db-link (db-link start )
+  (declare (fixnum db-link start))
+  (let ((prev nil))
+    (loop
+      (when (or (eql db-link start) (eql 0 start))
+        (return prev))
+      (setq prev start
+            start (%fixnum-ref start 0)))))
+
+(defun count-db-links-in-frame (vsp parent-vsp &optional context)
+  (declare (fixnum vsp parent-vsp))
+  (let ((db (db-link context))
+        (count 0)
+        (first nil)
+        (last nil))
+    (declare (fixnum db count))
+    (loop
+      (cond ((eql db 0)
+             (return (values count (or first 0) (or last 0))))
+            ((and (>= db vsp) (< db parent-vsp))
+             (unless first (setq first db))
+             (setq last db)
+             (incf count)))
+      (setq db (%fixnum-ref db)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; bogus-thing-p support
+;;;
+
+(defun %ptr-in-area-p (ptr area)
+  (declare (optimize (speed 3) (safety 0)) (fixnum ptr area))           ; lie, maybe
+  (and (<= (the fixnum (%fixnum-ref area target::area.low)) ptr)
+       (> (the fixnum (%fixnum-ref area target::area.high)) ptr)))
+
+(defun %active-area (area active)
+  (or (do ((a area (%fixnum-ref a target::area.older)))
+          ((eql a 0))
+        (when (%ptr-in-area-p active a)
+          (return a)))
+      (do ((a (%fixnum-ref area target::area.younger) (%fixnum-ref a target::area.younger)))
+          ((eql a 0))
+        (when (%ptr-in-area-p active a)
+          (return a)))))
+
+(defun %ptr-to-vstack-p (tcr idx)
+  (%ptr-in-area-p idx (%fixnum-ref tcr target::tcr.vs-area)))
+
+(defun %on-tsp-stack (tcr object)
+  (%ptr-in-area-p object (%fixnum-ref tcr target::tcr.ts-area)))
+
+(defun %on-csp-stack (tcr object)
+  (%ptr-in-area-p object (%fixnum-ref tcr target::tcr.cs-area)))
+
+(defparameter *aux-tsp-ranges* ())
+(defparameter *aux-vsp-ranges* ())
+(defparameter *aux-csp-ranges* ())
+
+(defun object-in-range-p (object range)
+  (declare (fixnum object))
+  (when range
+    (destructuring-bind (active . high) range
+      (declare (fixnum active high))
+      (and (< active object)
+           (< object high)))))
+
+(defun object-in-some-range (object ranges)
+  (dolist (r ranges)
+    (when (object-in-range-p object r)
+      (return t))))
+
+
+(defun on-any-tsp-stack (object)
+  (or (%on-tsp-stack (%current-tcr) object)
+      (object-in-some-range object *aux-tsp-ranges*)))
+
+(defun on-any-vstack (idx)
+  (or (%ptr-to-vstack-p (%current-tcr) idx)
+      (object-in-some-range idx *aux-vsp-ranges*)))
+
+(defun on-any-csp-stack (object)
+  (or (%on-csp-stack (%current-tcr) object)
+      (object-in-some-range object *aux-csp-ranges*)))
+
+;;; This MUST return either T or NIL.
+(defun temporary-cons-p (x)
+  (and (consp x)
+       (not (null (or (on-any-vstack x)
+                      (on-any-tsp-stack x))))))
+
+
+
+
+
+
+
+(defun %value-cell-header-at-p (cur-vsp)
+  (eql target::value-cell-header (%fixnum-address-of (%fixnum-ref cur-vsp))))
+
+(defun count-stack-consed-value-cells-in-frame (vsp parent-vsp)
+  (let ((cur-vsp vsp)
+        (count 0))
+    (declare (fixnum cur-vsp count))
+    (loop
+      (when (>= cur-vsp parent-vsp) (return))
+      (when (and (evenp cur-vsp) (%value-cell-header-at-p cur-vsp))
+        (incf count)
+        (incf cur-vsp))                 ; don't need to check value after header
+      (incf cur-vsp))
+    count))
+
+;;; stack consed value cells are one of two forms:
+;;; Well, they were of two forms.  When they existed, that is.
+;;;
+;;; nil             ; n-4
+;;; header          ; n = even address (multiple of 8)
+;;; value           ; n+4
+;;;
+;;; header          ; n = even address (multiple of 8)
+;;; value           ; n+4
+;;; nil             ; n+8
+
+(defun in-stack-consed-value-cell-p (arg-vsp vsp parent-vsp)
+  (declare (fixnum arg-vsp vsp parent-vsp))
+  (if (evenp arg-vsp)
+    (%value-cell-header-at-p arg-vsp)
+    (or (and (> arg-vsp vsp)
+             (%value-cell-header-at-p (the fixnum (1- arg-vsp))))
+        (let ((next-vsp (1+ arg-vsp)))
+          (declare (fixnum next-vsp))
+          (and (< next-vsp parent-vsp)
+               (%value-cell-header-at-p next-vsp))))))
+
+
+
+(defun count-values-in-frame (p context &optional child)
+  (declare (ignore child))
+  (multiple-value-bind (vsp parent-vsp) (vsp-limits p context)
+    (values
+     (- parent-vsp 
+        vsp
+        (* 2 (count-db-links-in-frame vsp parent-vsp context))))))
+
+(defun nth-value-in-frame-loc (sp n context lfun pc vsp parent-vsp)
+  (declare (fixnum sp))
+  (setq n (require-type n 'fixnum))
+  (unless (or (null vsp) (fixnump vsp))
+    (setq vsp (require-type vsp '(or null fixnum))))
+  (unless (or (null parent-vsp) (fixnump parent-vsp))
+    (setq parent-vsp (require-type parent-vsp '(or null fixnum))))
+  (unless (and vsp parent-vsp)
+    (multiple-value-setq (vsp parent-vsp) (vsp-limits sp context)))
+  (locally (declare (fixnum n vsp parent-vsp))
+    (multiple-value-bind (db-count first-db last-db)
+                         (count-db-links-in-frame vsp parent-vsp context)
+      (declare (ignore db-count))
+      (declare (fixnum first-db last-db))
+      (let ((arg-vsp (1- parent-vsp))
+            (cnt n)
+            (phys-cell 0)
+            db-link-p)
+        (declare (fixnum arg-vsp cnt phys-cell))
+        (loop
+          (if (eql (the fixnum (- arg-vsp 2)) last-db)
+            (setq db-link-p t
+                  arg-vsp last-db
+                  last-db (previous-db-link last-db first-db)
+                  phys-cell (+ phys-cell 2))
+            (setq db-link-p nil))
+            (when (< (decf cnt) 0)
+              (return
+               (if db-link-p
+                 (values (+ 2 arg-vsp)
+                         :saved-special
+                         (binding-index-symbol (%fixnum-ref (1+ arg-vsp))))
+                 (multiple-value-bind (type name) (find-local-name phys-cell lfun pc)
+                   (values arg-vsp type name)))))
+          (incf phys-cell)
+          (when (< (decf arg-vsp) vsp)
+            (error "~d out of range" n)))))))
+
+
+
+(defun nth-value-in-frame (sp n context &optional lfun pc vsp parent-vsp)
+  (multiple-value-bind (loc type name)
+                       (nth-value-in-frame-loc sp n context lfun pc vsp parent-vsp)
+    (let* ((val (%fixnum-ref loc)))
+      (when (and (eq type :saved-special)
+		 (eq val (%no-thread-local-binding-marker))
+		 name)
+	(setq val (%sym-global-value name)))
+      (values val  type name))))
+
+(defun set-nth-value-in-frame (sp n context new-value &optional vsp parent-vsp)
+  (multiple-value-bind (loc type name)
+      (nth-value-in-frame-loc sp n context nil nil vsp parent-vsp)
+    (let* ((old-value (%fixnum-ref loc)))
+      (if (and (eq type :saved-special)
+	       (eq old-value (%no-thread-local-binding-marker))
+	       name)
+	;; Setting the (shallow-bound) value of the outermost
+	;; thread-local binding of NAME.  Hmm.
+	(%set-sym-global-value name new-value)
+	(setf (%fixnum-ref loc) new-value)))))
+
+(defun nth-raw-frame (n start-frame context)
+  (declare (fixnum n))
+  (do* ((p start-frame (parent-frame p context))
+	(i 0 (1+ i))
+	(q (last-frame-ptr context)))
+       ((or (null p) (eq p q) (%stack< q p context)))
+    (declare (fixnum i))
+    (if (= i n)
+      (return p))))
+
+;;; True if the object is in one of the heap areas
+(defun %in-consing-area-p (x area)
+  (declare (optimize (speed 3) (safety 0)) (fixnum x))       ; lie
+  (let* ((low (%fixnum-ref area target::area.low))
+         (high (%fixnum-ref area target::area.high))
+)
+    (declare (fixnum low high))
+    (and (<= low x) (< x high))))
+
+
+
+(defun in-any-consing-area-p (x)
+  (do-consing-areas (area)
+    (when (%in-consing-area-p x area)
+      (return t))))
+
+
+
+
+
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; terminate-when-unreachable
+;;;
+
+#|
+Message-Id: <v02130502ad3e6a2f1542@[205.231.144.48]>
+Mime-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Date: Wed, 7 Feb 1996 10:32:55 -0500
+To: pmcldev@digitool.com
+From: bitCraft@taconic.net (Bill St. Clair)
+Subject: terminate-when-unreachable
+
+I propose that we add a general termination mechanism to PPC MCL.
+We need it to properly terminate stack groups, it would be
+a nicer way to do the termination for macptrs than the current
+ad-hoc mechanism (which BTW is not yet part of PPC MCL), and
+it is a nice addition to MCL. I don't think it's hard to make
+the garbage collector support this, and I volunteer to do the
+work unless Gary really wants to.
+
+I see two ways to support termination:
+
+1) Do termination for hash tables. This was our plan for
+   2.0, but Gary got confused about how to mark the objects at
+   the right time (or so I remember).
+
+2) Resurrect weak alists (they're not part of the PPC garbage
+   collector) and add a termination bit to the population type.
+   This allows for termination of weak lists and weak alists,
+   though the termination mechanism really only needs termination
+   for a single weak alist.
+
+I prefer option 2, weak alists, since it avoids the overhead
+necessary to grow and rehash a hash table. It also uses less space,
+since a finalizeable hash table needs to allocate two cons cells
+for each entry so that the finalization code has some place to
+put the deleted entry.
+
+I propose the following interface (slightly modified from what
+Apple Dylan provides):
+
+terminate-when-unreachable object &optional (function 'terminate)
+  When OBJECT becomes unreachable, funcall FUNCTION with OBJECT
+  as a single argument. Each call of terminate-when-unreachable
+  on a single (EQ) object registers a new termination function.
+  All will be called when the object becomes unreachable.
+
+terminate object                                         [generic function]
+  The default termination function
+
+terminate (object t)                                     [method]
+  The default method. Ignores object. Returns nil.
+
+drain-termination-queue                                  [function]
+  Drain the termination queue. I.e. call the termination function
+  for every object that has become unreachable.
+
+*enable-automatic-termination*                           [variable]
+  If true, the default, drain-termination-queue will be automatically
+  called on the first event check after the garbage collector runs.
+  If you set this to false, you are responsible for calling
+  drain-termination-queue.
+
+cancel-terminate-when-unreachable object &optional function
+  Removes the effect of the last call to terminate-when-unreachable
+  for OBJECT & FUNCTION (both tested with EQ). Returns true if
+  it found a match (which it won't if the object has been moved
+  to the termination queue since terminate-when-unreachable was called).
+  If FUNCTION is NIL or unspecified, then it will not be used; the
+  last call to terminate-when-unreachable with the given OBJECT will
+  be undone.
+
+termination-function object
+  Return the function passed to the last call of terminate-when-unreachable
+  for OBJECT. Will be NIL if the object has been put in the
+  termination queue since terminate-when-unreachable was called.
+
+|#
+
+
+(defstatic *termination-population*
+  (%cons-terminatable-alist))
+
+(defstatic *termination-population-lock* (make-lock))
+
+
+(defvar *enable-automatic-termination* t)
+
+(defun terminate-when-unreachable (object &optional (function 'terminate))
+  "The termination mechanism is a way to have the garbage collector run a
+function right before an object is about to become garbage. It is very
+similar to the finalization mechanism which Java has. It is not standard
+Common Lisp, although other Lisp implementations have similar features.
+It is useful when there is some sort of special cleanup, deallocation,
+or releasing of resources which needs to happen when a certain object is
+no longer being used."
+  (let ((new-cell (cons object function))
+        (population *termination-population*))
+    (without-interrupts
+     (with-lock-grabbed (*termination-population-lock*)
+       (atomic-push-uvector-cell population population.data new-cell)))
+    function))
+
+(defmethod terminate ((object t))
+  nil)
+
+(defun drain-termination-queue ()
+  (with-lock-grabbed (*termination-population-lock*)
+    (let* ((population *termination-population*))
+      (loop
+        (multiple-value-bind (cell existed)
+            (atomic-pop-uvector-cell population population.termination-list)
+          (if (not existed)
+            (return)
+          (funcall (cdr cell) (car cell))))))))
+
+(defun cancel-terminate-when-unreachable (object &optional (function nil function-p))
+  (let* ((found nil))
+    (with-lock-grabbed (*termination-population-lock*)
+      ;; We don't really need to be very paranoid here.  Nothing can
+      ;; be added to the termination queue while we hold the lock,
+      ;; and the GC can't splice anything out of the list while
+      ;; we hold a strong reference to that list.
+      (let* ((population *termination-population*)
+             (queue (population.data population)))
+        (do* ((prev nil spine)
+              (spine queue (cdr spine)))
+             ((null spine))
+          (let* ((entry (car spine)))
+            (destructuring-bind (o . f) entry
+              (when (and (eq o object)
+                         (or (null function-p)
+                             (eq function f)))
+                (if prev
+                  (setf (cdr prev) (cdr spine))
+                  (setf (population.data population) (cdr spine)))
+                (setq found t)
+                (return)))))
+      found))))
+
+
+(defun termination-function (object)
+  (without-interrupts
+   (with-lock-grabbed (*termination-population-lock*)
+     (cdr (assq object (population-data *termination-population*))))))
+
+(defun do-automatic-termination ()
+  (when *enable-automatic-termination*
+    (drain-termination-queue)))
+
+(queue-fixup
+ (add-gc-hook 'do-automatic-termination :post-gc))
+
+;;; A callback to handle foreign thread preparation, initialization,
+;;; and termination.
+;;; "preparation" involves telling the kernel to reserve space for
+;;; some initial thread-specific special bindings.  The kernel
+;;; needs to reserve this space on the foreign thread's vstack;
+;;; it needs us to tell it how much space to reserve (enough
+;;; for bindings of *current-thread*, *current-process*, and
+;;; the default initial bindings of *PACKAGE*, etc.)
+;;;
+;;; "initialization" involves making those special bindings in
+;;; the vstack space reserved by the kernel, and setting the
+;;; values of *current-thread* and *current-process* to newly
+;;; created values.
+;;;
+;;; "termination" involves removing the current thread and
+;;; current process from the global thread/process lists.
+;;; "preparation" and "initialization" happen when the foreign
+;;; thread first tries to call lisp code.  "termination" happens
+;;; via the pthread thread-local-storage cleanup mechanism.
+(defcallback %foreign-thread-control (:without-interrupts t :int param :int)
+  (declare (fixnum param))
+  (cond ((< param 0) (%foreign-thread-prepare))
+	((= param 0) (%foreign-thread-initialize) 0)
+	(t (%foreign-thread-terminate) 0)))
+
+
+
+(defun %foreign-thread-prepare ()
+  (let* ((initial-bindings (standard-initial-bindings)))
+    (%save-standard-binding-list initial-bindings)
+    (* 3 (+ 2 (length initial-bindings)))))
+
+
+(defun %foreign-thread-initialize ()
+  ;; Recover the initial-bindings alist.
+  (let* ((bsp (%saved-bindings-address))
+	 (initial-bindings (%fixnum-ref bsp )))
+    (declare (fixnum bsp))
+    ;; Um, this is a little more complicated now that we use
+    ;; thread-local shallow binding
+    (flet ((save-binding (new-value sym prev)
+             (let* ((idx (symbol-binding-index sym))
+                    (byte-idx (ash idx target::fixnum-shift))
+                    (binding-vector (%fixnum-ref (%current-tcr) target::tcr.tlb-pointer))
+                    (old-value (%fixnum-ref  binding-vector byte-idx)))
+	     (setf (%fixnum-ref binding-vector byte-idx) new-value
+                   (%fixnum-ref bsp (ash -1 target::word-shift)) old-value
+		   (%fixnum-ref bsp (ash -2 target::word-shift)) idx
+		   (%fixnum-ref bsp (ash -3 target::word-shift)) prev
+		   bsp (- bsp 3)))))
+      (save-binding nil '*current-lisp-thread* 0)
+      (save-binding nil '*current-process* bsp)
+      (dolist (pair initial-bindings)
+	(save-binding (funcall (cdr pair)) (car pair) bsp))
+      ;; These may (or may not) be the most recent special bindings.
+      ;; If they are, just set the current tcr's db-link to point
+      ;; to BSP; if not, "append" them to the end of the current
+      ;; linked list.
+      (let* ((current-db-link (%fixnum-ref (%current-tcr) target::tcr.db-link)))
+        (declare (fixnum current-db-link))
+        (if (zerop current-db-link)
+          (setf (%fixnum-ref (%current-tcr) target::tcr.db-link) bsp)
+          (do* ((binding current-db-link)
+                (next (%fixnum-ref binding 0)
+                      (%fixnum-ref binding 0)))
+               ()
+            (if (zerop next)
+              (return (setf (%fixnum-ref binding 0) bsp))
+              (setq binding next)))))
+      ;; Ensure that pending unwind-protects (for WITHOUT-INTERRUPTS
+      ;; on the callback) don't try to unwind the binding stack beyond
+      ;; where it was just set.
+      (do* ((catch (%fixnum-ref (%current-tcr) target::tcr.catch-top)
+                   (%fixnum-ref catch target::catch-frame.link)))
+           ((zerop catch))
+        (declare (fixnum catch))
+        (when (eql 0 (%fixnum-ref catch target::catch-frame.db-link))
+          (setf (%fixnum-ref catch target::catch-frame.db-link) bsp)))))
+  (let* ((thread (new-lisp-thread-from-tcr (%current-tcr) "foreign")))
+    (setq *current-lisp-thread* thread
+	  *current-process*
+	  (make-process "foreign" :thread thread)
+          *whostate* "Foreign thread callback")))
+    
+;;; Remove the foreign thread's lisp-thread and lisp process from
+;;; the global lists.
+(defun %foreign-thread-terminate ()
+  (let* ((proc *current-process*))
+    (when proc
+      (remove-from-all-processes proc)
+      (let* ((ts (process-termination-semaphore proc)))
+        (when ts (signal-semaphore ts))))))
+
Index: /branches/new-random/level-1/l1-numbers.lisp
===================================================================
--- /branches/new-random/level-1/l1-numbers.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-numbers.lisp	(revision 13309)
@@ -0,0 +1,917 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS")
+)
+
+(defun %parse-number-token (string &optional start end radix)
+  (if end (require-type end 'fixnum)(setq end (length string)))
+  (if start (require-type start 'fixnum)(setq start 0))
+  (multiple-value-bind (string offset)(array-data-and-offset string)
+    (new-numtoken string (+ start offset)(- end start) (%validate-radix (or radix 10)))))
+
+(defun new-numtoken (string start len radix &optional no-rat no-sign)
+  (declare (fixnum start len radix))
+  (if (eq 0 len)
+    nil
+    (let ((c (%scharcode string start))
+          (nstart start)
+          (end (+ start len))
+          (hic (if (<= radix 10)
+                 (+ (char-code #\0) (1- radix))
+                 (+ (char-code #\A) (- radix 11))))
+          dot dec dgt)
+      (declare (fixnum nstart end hic))
+      (when (or (eq c (char-code #\+))(eq c (char-code #\-)))
+        (if no-sign
+          (return-from new-numtoken nil)
+          (setq nstart (1+ nstart))))
+      (when (eq nstart end)(return-from new-numtoken nil)) ; just a sign
+      (do ((i nstart (1+ i)))
+          ((eq i end))
+        (let ()
+          (setq c (%scharcode string i))
+          (cond
+           ((eq c (char-code #\.))
+            (when dot (return-from new-numtoken nil))
+            (setq dot t)
+            (when dec (return-from new-numtoken nil))
+            (setq hic (char-code #\9)))
+           ((< c (char-code #\0)) 
+            (when (and (eq c (char-code #\/))(not dot)(not no-rat))
+              (let ((top (new-numtoken string start (- i start) radix)))
+                (when top 
+                  (let ((bottom (new-numtoken string (+ start i 1) (- len i 1) radix t t)))
+                    (when bottom 
+                      (return-from new-numtoken (/ top bottom)))))))
+            (return-from new-numtoken nil))
+           ((<= c (char-code #\9))
+            (when (> c hic)
+              ; seen a decimal digit above base.
+              (setq dgt t)))
+           (t (when (>= c (char-code #\a))(setq c (- c 32)))
+              ;; don't care about *read-base* if float
+              (cond ((or (< c (char-code #\A))(> c hic))
+                     (when (and (neq i nstart) ; need some digits first
+                                (memq c '#.(list (char-code #\E)(char-code #\F)
+                                                 (char-code #\D)(char-code #\L)
+                                                 (char-code #\S))))
+                       (return-from new-numtoken (parse-float string len start)))
+                     (return-from new-numtoken nil))
+                    (t     ; seen a "digit" in base that ain't decimal
+                     (setq dec t)))))))
+      (when (and dot (or (and (neq nstart start)(eq len 2))
+                         (eq len 1)))  ;. +. or -.
+        (return-from new-numtoken nil))
+      (when dot 
+        (if (eq c (char-code #\.))
+          (progn (setq len (1- len) end (1- end))
+                 (when dec (return-from new-numtoken nil))
+                 ; make #o9. work (should it)
+                 (setq radix 10 dgt nil))
+          (return-from new-numtoken (parse-float string len start))))
+      (when dgt (return-from new-numtoken nil)) ; so why didnt we quit at first sight of it?
+      ; and we ought to accumulate as we go until she gets too big - maybe
+      (cond (nil ;(or (and (eq radix 10)(< (- end nstart) 9))(and (eq radix 8)(< (- end nstart) 10)))
+             (let ((num 0))
+               (declare (fixnum num))
+               (do ((i nstart (1+ i)))
+                   ((eq i end))
+                 (setq num (%i+ (%i* num radix)(%i- (%scharcode string i) (char-code #\0)))))
+               (if (eq (%scharcode string start) (char-code #\-)) (setq num (- num)))
+               num))                         
+            (t (token2int string start len radix))))))
+
+
+;; Will Clingers number 1.448997445238699
+;; Doug Curries numbers 214748.3646, 1073741823/5000
+;; My number: 12.
+;; Your number:
+
+
+
+
+
+(defun logand (&lexpr numbers)
+  "Return the bit-wise and of its arguments. Args must be integers."
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))
+    (if (zerop count)
+      -1
+      (let* ((n0 (%lisp-word-ref numbers count)))
+        (if (= count 1)
+          (require-type n0 'integer)
+          (do* ((i 1 (1+ i)))
+               ((= i count) n0)
+            (declare (fixnum i))
+            (declare (optimize (speed 3) (safety 0)))
+            (setq n0 (logand (%lexpr-ref numbers count i) n0))))))))
+
+
+(defun logior (&lexpr numbers)
+  "Return the bit-wise or of its arguments. Args must be integers."
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))
+    (if (zerop count)
+      0
+      (let* ((n0 (%lisp-word-ref numbers count)))
+        (if (= count 1)
+          (require-type n0 'integer)
+          (do* ((i 1 (1+ i)))
+               ((= i count) n0)
+            (declare (fixnum i))
+            (declare (optimize (speed 3) (safety 0)))
+            (setq n0 (logior (%lexpr-ref numbers count i) n0))))))))
+
+(defun logxor (&lexpr numbers)
+  "Return the bit-wise exclusive or of its arguments. Args must be integers."
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))
+    (if (zerop count)
+      0
+      (let* ((n0 (%lisp-word-ref numbers count)))
+        (if (= count 1)
+          (require-type n0 'integer)
+          (do* ((i 1 (1+ i)))
+               ((= i count) n0)
+            (declare (fixnum i))
+            (declare (optimize (speed 3) (safety 0)))
+            (setq n0 (logxor (%lexpr-ref numbers count i) n0))))))))
+
+(defun logeqv (&lexpr numbers)
+  "Return the bit-wise equivalence of its arguments. Args must be integers."
+  (let* ((count (%lexpr-count numbers))
+         (result (if (zerop count)
+                   0
+                   (let* ((n0 (%lisp-word-ref numbers count)))
+                     (if (= count 1)
+                       (require-type n0 'integer)
+                       (do* ((i 1 (1+ i)))
+                            ((= i count) n0)
+                         (declare (fixnum i))
+                         (declare (optimize (speed 3) (safety 0)))
+                         (setq n0 (logxor (%lexpr-ref numbers count i) n0))))))))
+    (declare (fixnum count))
+    (if (evenp count)
+      (lognot result)
+      result)))
+
+
+
+
+(defun = (num &lexpr more)
+  "Return T if all of its arguments are numerically equal, NIL otherwise."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (progn
+        (require-type num 'number)
+        t)
+      (dotimes (i count t)
+        (unless (=-2 (%lexpr-ref more count i) num) (return))))))
+
+(defun /= (num &lexpr more)
+  "Return T if no two of its arguments are numerically equal, NIL otherwise."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (progn
+        (require-type num 'number)
+        t)
+      (dotimes (i count t)
+        (declare (fixnum i))
+        (do ((j i (1+ j)))
+            ((= j count))
+          (declare (fixnum j))
+          (when (=-2 num (%lexpr-ref more count j))
+            (return-from /= nil)))
+        (setq num (%lexpr-ref more count i))))))
+
+(defun - (num &lexpr more)
+  "Subtract the second and all subsequent arguments from the first; 
+  or with one argument, negate the first argument."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (- num)
+      (dotimes (i count num)
+        (setq num (--2 num (%lexpr-ref more count i)))))))
+
+(defun / (num &lexpr more)
+  "Divide the first argument by each of the following arguments, in turn.
+  With one argument, return reciprocal."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (%quo-1 num)
+      (dotimes (i count num)
+        (setq num (/-2 num (%lexpr-ref more count i)))))))
+
+(defun + (&lexpr numbers)
+  "Return the sum of its arguments. With no args, returns 0."
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))
+    (if (zerop count)
+      0
+      (let* ((n0 (%lisp-word-ref numbers count)))
+        (if (= count 1)
+          (require-type n0 'number)
+          (do* ((i 1 (1+ i)))
+               ((= i count) n0)
+            (declare (fixnum i))
+            (setq n0 (+-2 (%lexpr-ref numbers count i) n0))))))))
+
+
+
+(defun * (&lexpr numbers)
+  "Return the product of its arguments. With no args, returns 1."
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))
+    (if (zerop count)
+      1
+      (let* ((n0 (%lisp-word-ref numbers count)))
+        (if (= count 1)
+          (require-type n0 'number)
+          (do* ((i 1 (1+ i)))
+               ((= i count) n0)
+            (declare (fixnum i))
+            (declare (optimize (speed 3) (safety 0)))
+            (setq n0 (*-2 (%lexpr-ref numbers count i) n0))))))))
+
+
+(defun < (num &lexpr more)
+  "Return T if its arguments are in strictly increasing order, NIL otherwise."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (progn
+        (require-type num 'real)
+        t)
+      (dotimes (i count t)
+        (declare (optimize (speed 3) (safety 0)))
+        (unless (< num (setq num (%lexpr-ref more count i)))
+          (return))))))
+
+(defun <= (num &lexpr more)
+  "Return T if arguments are in strictly non-decreasing order, NIL otherwise."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (progn
+        (require-type num 'real)
+        t)
+      (dotimes (i count t)
+        (declare (optimize (speed 3) (safety 0)))
+        (unless (<= num (setq num (%lexpr-ref more count i)))
+          (return))))))
+
+
+(defun > (num &lexpr more)
+  "Return T if its arguments are in strictly decreasing order, NIL otherwise."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (progn
+        (require-type num 'real)
+        t)
+      (dotimes (i count t)
+        (declare (optimize (speed 3) (safety 0)))
+        (unless (> num (setq num (%lexpr-ref more count i)))
+          (return))))))
+
+(defun >= (num &lexpr more)
+  "Return T if arguments are in strictly non-increasing order, NIL otherwise."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (progn
+        (require-type num 'real)
+        t)
+      (dotimes (i count t)
+        (declare (optimize (speed 3) (safety 0)))
+        (unless (>= num (setq num (%lexpr-ref more count i)))
+          (return))))))
+
+(defun max-2 (n0 n1)
+  (if (> n0 n1) n0 n1))
+
+(defun max (num &lexpr more)
+  "Return the greatest of its arguments; among EQUALP greatest, return
+   the first."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (require-type num 'real)
+      (dotimes (i count num)
+        (declare (optimize (speed 3) (safety 0)))
+        (setq num (max-2 (%lexpr-ref more count i) num))))))
+
+(defun min-2 (n0 n1)
+  (if (< n0 n1) n0 n1))
+
+(defun min (num &lexpr more)
+  "Return the least of its arguments; among EQUALP least, return
+  the first."
+  (let* ((count (%lexpr-count more)))
+    (declare (fixnum count))
+    (if (zerop count)
+      (require-type num 'real)
+      (dotimes (i count num)
+        (declare (optimize (speed 3) (safety 0)))
+        (setq num (min-2 (%lexpr-ref more count i) num))))))
+ 
+
+
+;Not CL. Used by transforms.
+(defun deposit-byte (value size position integer)
+  (let ((mask (byte-mask size)))
+    (logior (ash (logand value mask) position)
+            (logandc1 (ash mask position) integer))))
+
+(defun deposit-field (value bytespec integer)
+  "Return new integer with newbyte in specified position, newbyte is not right justified."
+  (if (> bytespec 0)    
+    (logior (logandc1 bytespec integer) (logand bytespec value))
+    (progn
+      (require-type value 'integer)
+      (require-type integer 'integer))))
+
+;;;;;;;;;;  Byte field functions ;;;;;;;;;;;;;;;;
+
+;;; Size = 0, position = 0 -> 0
+;;; size = 0, position > 0 -> -position
+;;; else ->  (ash (byte-mask size) position)
+(defun byte (size position)
+  "Return a byte specifier which may be used by other byte functions
+  (e.g. LDB)."
+  (unless (and (typep size 'integer)
+	       (>= size 0))
+    (report-bad-arg size 'unsigned-byte))
+  (unless (and (typep position 'integer)
+	       (>= position 0))
+    (report-bad-arg position 'unsigned-byte))
+  (if (eql 0 size)
+    (if (eql 0 position)
+      0
+      (- position))
+    (ash (byte-mask size) position)))
+
+
+
+(defun byte-size (bytespec)
+  "Return the size part of the byte specifier bytespec."
+  (if (> bytespec 0)
+    (logcount bytespec)
+    0))
+
+(defun ldb (bytespec integer)
+  "Extract the specified byte from integer, and right justify result."
+  (if (and (fixnump bytespec) (> (the fixnum bytespec) 0)  (fixnump integer))
+    (%ilsr (byte-position bytespec) (%ilogand bytespec integer))
+    (let ((size (byte-size bytespec))
+          (position (byte-position bytespec)))
+      (if (eql size 0)
+	(progn
+	  (require-type integer 'integer)
+	  0)
+	(if (and (bignump integer)
+		 (<= size  (- (1- target::nbits-in-word)  target::fixnumshift))
+		 (fixnump position))
+          (%ldb-fixnum-from-bignum integer size position)
+          (ash (logand bytespec integer) (- position)))))))
+
+(defun mask-field (bytespec integer)
+  "Extract the specified byte from integer, but do not right justify result."
+  (if (>= bytespec 0)
+    (logand bytespec integer)
+    (logand integer 0)))
+
+(defun dpb (value bytespec integer)
+  "Return new integer with newbyte in specified position, newbyte is right justified."
+  (if (and (fixnump value)
+	   (fixnump bytespec)
+	   (> (the fixnum bytespec) 0)
+	   (fixnump integer))
+    (%ilogior (%ilogand bytespec (%ilsl (byte-position bytespec) value))
+              (%ilogand (%ilognot bytespec) integer))
+    (deposit-field (ash value (byte-position bytespec)) bytespec integer)))
+
+(defun ldb-test (bytespec integer)
+  "Return T if any of the specified bits in integer are 1's."
+  (if (> bytespec 0)
+    (logtest bytespec integer)
+    (progn
+      (require-type integer 'integer)
+      nil)))
+
+(defun %cons-random-state (seed-1 seed-2)
+  #+32-bit-target
+  (%istruct 'random-state seed-1 seed-2)
+  #+64-bit-target
+  (%istruct 'random-state (the fixnum (+ (the fixnum seed-2)
+                          (the fixnum (ash (the fixnum seed-1) 16))))))
+
+;;; random associated stuff except for the print-object method which
+;;; is still in "lib;numbers.lisp"
+(defun initialize-random-state (seed-1 seed-2)
+  (unless (and (fixnump seed-1) (%i<= 0 seed-1) (%i< seed-1 #x10000))
+    (report-bad-arg seed-1 '(unsigned-byte 16)))
+  (unless (and (fixnump seed-2) (%i<= 0 seed-2) (%i< seed-2 #x10000))
+    (report-bad-arg seed-2 '(unsigned-byte 16)))
+    (%cons-random-state seed-1 seed-2))
+
+(defun make-random-state (&optional state)
+  "Make a random state object. If STATE is not supplied, return a copy
+  of the default random state. If STATE is a random state, then return a
+  copy of it. If STATE is T then return a random state generated from
+  the universal time."
+  (let* ((seed-1 0)
+         (seed-2 0))
+    (if (eq state t)
+      (multiple-value-setq (seed-1 seed-2) (init-random-state-seeds))
+      (progn
+        (setq state (require-type (or state *random-state*) 'random-state))
+        #+32-bit-target
+        (setq seed-1 (random.seed-1 state) seed-2 (random.seed-2 state))
+        #+64-bit-target
+        (let* ((seed (random.seed-1 state)))
+          (declare (type (unsigned-byte 32) seed))
+          (setq seed-1 (ldb (byte 16 16) seed)
+                seed-2 (ldb (byte 16 0) seed)))))
+    (%cons-random-state seed-1 seed-2)))
+
+(defun random-state-p (thing) (istruct-typep thing 'random-state))
+
+;;; transcendental stuff.  Should go in level-0;l0-float
+;;; but shleps don't work in level-0.  Or do they ?
+; Destructively set z to x^y and return z.
+(defun %double-float-expt! (b e result)
+  (declare (double-float b e result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float temp (#_pow b e))
+    (%df-check-exception-2 'expt b e (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+(and 32-bit-target (not win32-target))
+(defun %single-float-expt! (b e result)
+  (declare (single-float b e result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float temp (#_powf b e))
+    (%sf-check-exception-2 'expt b e (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+win32-target
+(defun %single-float-expt! (b e result)
+  (declare (single-float b e result))
+  (with-stack-double-floats ((temp) (db b) (de e))
+    (%setf-double-float temp (#_pow db de))
+    (%df-check-exception-2 'expt b e (%ffi-exception-status))
+    (%double-float->short-float temp result)))
+
+#+64-bit-target
+(defun %single-float-expt (b e)
+  (declare (single-float b e))
+  (let* ((result (#_powf b e)))
+    (%sf-check-exception-2 'expt b e (%ffi-exception-status))
+    result))
+
+(defun %double-float-sin! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_sin n))
+    (%df-check-exception-1 'sin n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-sin! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_sinf n))
+    (%sf-check-exception-1 'sin n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-sin (n)
+  (declare (single-float n))
+  (let* ((result (#_sinf n)))
+    (%sf-check-exception-1 'sin n (%ffi-exception-status))
+    result))
+
+(defun %double-float-cos! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_cos n))
+    (%df-check-exception-1 'cos n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-cos! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_cosf n))
+    (%sf-check-exception-1 'cos n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-cos (n)
+  (declare (single-float n))
+  (let* ((result (#_cosf n)))
+    (%sf-check-exception-1 'cos n (%ffi-exception-status))
+    result))
+
+(defun %double-float-acos! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_acos n))
+    (%df-check-exception-1 'acos n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-acos! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_acosf n))
+    (%sf-check-exception-1 'acos n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-acos (n)
+  (declare (single-float n))
+  (let* ((result (#_acosf n)))
+    (%sf-check-exception-1 'acos n (%ffi-exception-status))
+    result))
+
+(defun %double-float-asin! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_asin n))
+    (%df-check-exception-1 'asin n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-asin! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_asinf n))
+    (%sf-check-exception-1 'asin n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-asin (n)
+  (declare (single-float n))
+  (let* ((result (#_asinf n)))
+    (%sf-check-exception-1 'asin n (%ffi-exception-status))
+    result))
+
+(defun %double-float-cosh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_cosh n))
+    (%df-check-exception-1 'cosh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-cosh! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (external-call "coshf" :single-float n :single-float))
+    (%sf-check-exception-1 'cosh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-cosh (n)
+  (declare (single-float n))
+  (let* ((result (#_coshf n)))
+    (%sf-check-exception-1 'cosh n (%ffi-exception-status))
+    result))
+
+(defun %double-float-log! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_log n))
+    (%df-check-exception-1 'log n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-log! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_logf n))
+    (%sf-check-exception-1 'log n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-log (n)
+  (let* ((result (#_logf n)))
+    (%sf-check-exception-1 'log n (%ffi-exception-status))
+    result))
+
+(defun %double-float-tan! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_tan n))
+    (%df-check-exception-1 'tan n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-tan! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_tanf n))
+    (%sf-check-exception-1 'tan n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-tan (n)
+  (declare (single-float n))
+  (let* ((result (#_tanf n)))
+    (%sf-check-exception-1 'tan n (%ffi-exception-status))
+    result))
+
+(defun %double-float-atan! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_atan n))
+    (%df-check-exception-1 'atan n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+
+#+32-bit-target
+(defun %single-float-atan! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_atanf n))
+    (%sf-check-exception-1 'atan n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-atan (n)
+  (declare (single-float n))
+  (let* ((temp (#_atanf n)))
+    (%sf-check-exception-1 'atan n (%ffi-exception-status))
+    temp))
+
+(defun %double-float-atan2! (x y result)
+  (declare (double-float x y result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_atan2 x y))
+    (%df-check-exception-2 'atan2 x y (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-atan2! (x y result)
+  (declare (single-float x y result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_atan2f x y))
+    (%sf-check-exception-2 'atan2 x y (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-atan2 (x y)
+  (declare (single-float x y))
+  (let* ((result (#_atan2f x y)))
+    (%sf-check-exception-2 'atan2 x y (%ffi-exception-status))
+    result))
+
+(defun %double-float-exp! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_exp n))
+    (%df-check-exception-1 'exp n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+(and 32-bit-target (not windows target))
+(defun %single-float-exp! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_expf n))
+    (%sf-check-exception-1 'exp n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+(and 32-bit-target windows-target)
+(defun %single-float-exp! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (external-call "expf" :single-float n :single-float))
+    (%sf-check-exception-1 'exp n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-exp (n)
+  (declare (single-float n))
+  (let* ((result (#_expf n)))
+    (%sf-check-exception-1 'exp n (%ffi-exception-status))
+    result))
+
+(defun %double-float-sinh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_sinh n))
+    (%df-check-exception-1 'sinh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-sinh! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (external-call "sinhf" :single-float n :single-float))
+    (%sf-check-exception-1 'sinh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-sinh (n)
+  (declare (single-float n))
+  (let* ((result (#_sinhf n)))
+    (%sf-check-exception-1 'sinh n (%ffi-exception-status))
+    result))
+
+(defun %double-float-tanh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_tanh n))
+    (%df-check-exception-1 'tanh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-tanh! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (external-call "tanhf" :single-float n :single-float))
+    (%sf-check-exception-1 'tanh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-tanh (n)
+  (declare (single-float n))
+  (let* ((result (#_tanhf n)))
+    (%sf-check-exception-1 'tanh n (%ffi-exception-status))
+    result))
+
+#+windows-target
+(progn
+(defun %double-float-asinh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (external-call "asinh" :double-float n :double-float))
+    (%df-check-exception-1 'asinh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-asinh! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (external-call "asinhf" :float n :float))
+    (%sf-check-exception-1 'asinh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-asinh (n)
+  (declare (single-float n))
+  (let* ((result (external-call "asinhf" :float n :float)))
+    (%sf-check-exception-1 'asinh n (%ffi-exception-status))
+    result)))
+
+#-windows-target
+(progn
+(defun %double-float-asinh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_asinh n))
+    (%df-check-exception-1 'asinh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+
+#+32-bit-target
+(defun %single-float-asinh! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_asinhf n))
+    (%sf-check-exception-1 'asinh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-asinh (n)
+  (declare (single-float n))
+  (let* ((result (#_asinhf n)))
+    (%sf-check-exception-1 'asinh n (%ffi-exception-status))
+    result))
+)
+
+#+windows-target
+(progn
+(defun %double-float-acosh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (external-call "acosh" :double  n :double))
+    (%df-check-exception-1 'acosh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-acosh! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (external-call "acoshf" :float n :float))
+    (%sf-check-exception-1 'acosh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-acosh (n)
+  (declare (single-float n))
+  (let* ((result (external-call "acoshf" :float n :float)))
+    (%sf-check-exception-1 'acosh n (%ffi-exception-status))
+    result))
+
+)
+
+#-windows-target
+(progn
+(defun %double-float-acosh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_acosh n))
+    (%df-check-exception-1 'acosh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-acosh! (n result)
+  (declare (single-float n result))
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_acoshf n))
+    (%sf-check-exception-1 'acosh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-acosh (n)
+  (declare (single-float n))
+  (let* ((result (#_acoshf n)))
+    (%sf-check-exception-1 'acosh n (%ffi-exception-status))
+    result))
+)
+
+#+windows-target
+(progn
+(defun %double-float-atanh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (external-call "atanh" :double n :double))
+    (%df-check-exception-1 'atanh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-atanh! (n result)
+  (declare (single-float n result)) 
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (external-call "atanhf" :float n :float))
+    (%sf-check-exception-1 'atanh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-atanh (n)
+  (declare (single-float n)) 
+  (let* ((result (external-call "atanhf" :float n :float)))
+    (%sf-check-exception-1 'atanh n (%ffi-exception-status))
+    result))
+
+)
+
+#-windows-target
+(progn
+(defun %double-float-atanh! (n result)
+  (declare (double-float n result))
+  (with-stack-double-floats ((temp))
+    (%setf-double-float TEMP (#_atanh n))
+    (%df-check-exception-1 'atanh n (%ffi-exception-status))
+    (%setf-double-float result TEMP)))
+
+#+32-bit-target
+(defun %single-float-atanh! (n result)
+  (declare (single-float n result)) 
+  (target::with-stack-short-floats ((temp))
+    (%setf-short-float TEMP (#_atanhf n))
+    (%sf-check-exception-1 'atanh n (%ffi-exception-status))
+    (%setf-short-float result TEMP)))
+
+#+64-bit-target
+(defun %single-float-atanh (n)
+  (declare (single-float n)) 
+  (let* ((result (#_atanhf n)))
+    (%sf-check-exception-1 'atanh n (%ffi-exception-status))
+    result))
+)
Index: /branches/new-random/level-1/l1-pathnames.lisp
===================================================================
--- /branches/new-random/level-1/l1-pathnames.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-pathnames.lisp	(revision 13309)
@@ -0,0 +1,708 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Portions copyright (c) 2001-2009 Clozure Associates.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+
+;; L1-pathnames.lisp
+;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+;ANSI CL logical pathnames
+
+(in-package "CCL")
+
+(defun heap-image-name ()
+  (let* ((p (%null-ptr))
+         (string (%get-utf-8-cstring (%get-kernel-global-ptr 'image-name p))))
+    (declare (dynamic-extent p))
+    #+windows-target (nbackslash-to-forward-slash string)
+    #+darwin-target (precompose-simple-string string)
+    #-(or windows-target darwin-target) string))
+
+(defloadvar *heap-image-name* (heap-image-name))
+
+(defloadvar *command-line-argument-list*
+  (let* ((argv (%null-ptr))
+	 (res ()))
+    (declare (dynamic-extent argv))
+    (%get-kernel-global-ptr 'argv argv)
+    (do* ((i 0 (+ i target::node-size))
+	  (arg (%get-ptr argv i) (%get-ptr argv i)))
+	 ((%null-ptr-p arg) (nreverse res))
+      (declare (fixnum i))
+      (push (%get-utf-8-cstring arg) res))))
+
+;These are used by make-pathname
+(defun %verify-logical-component (name type)
+  (when (and name (neq name :unspecific))
+    (setq name (ensure-simple-string name))
+    (when (or (eql 0 (length name))
+              (%str-member *pathname-escape-character* name) ;; Hmm, why?
+              (%path-mem "/;" name))
+      (error "Illegal logical pathname ~A component ~S" type name)))
+  name)
+
+
+(defun verify-logical-host-name (host)
+  (or (and host
+	   (%verify-logical-component host "host")
+	   (%str-assoc host %logical-host-translations%)
+	   host)
+      (host-error host)))
+
+(defun %logical-version-component (version)
+  (if (or (fixnump version)
+          (stringp version)
+          (memq version '(nil :wild :newest :unspecific)))
+    version
+    (require-type version '(or fixnum string (member nil :wild :newest :unspecific)))))
+
+(defun logical-pathname-translations (host)
+  "Return the (logical) host object argument's list of translations."
+  (setq host (verify-logical-host-name host))
+  (let ((translations (%str-assoc host %logical-host-translations%)))
+    (unless translations (host-error host))
+    (%cdr translations)))
+
+(defun logical-host-p (host)
+  (%str-assoc host %logical-host-translations%))
+
+(defun host-error (host) ; supposed to be a type-error
+  (signal-type-error host  '(satisfies logical-host-p) "~S is not a defined logical host"))
+
+(defun set-logical-pathname-translations (host list)
+  (setq host (%verify-logical-component  host "host"))
+  (let ((old (%str-assoc host %logical-host-translations%))
+	(new (let ((%logical-host-translations% (cons (list host) %logical-host-translations%)))
+	       ;; Do this in the context when host is defined, so no errors.
+	       (mapcar #'(lambda (trans)
+			   (destructuring-bind (from to &rest ignored) trans
+			     (declare (ignore ignored))
+			     (let ((from-path (parse-namestring from host))
+				   (to-path (pathname to)))
+			       (list (require-type from-path 'logical-pathname) to-path))))
+		       list))))
+    (if old
+      (progn (%rplaca old host) (%rplacd old new))
+      (push (cons host new) %logical-host-translations%)))
+  list)
+
+(defsetf logical-pathname-translations set-logical-pathname-translations)
+
+;;; doesnt check if already there - adds at front 
+(defun add-logical-pathname-translation (host translation)
+  (let ((trans (%str-assoc host  %logical-host-translations%)))
+    (if (not trans)
+      (set-logical-pathname-translations host (list translation))
+      (let ((new (destructuring-bind (from to &rest ignored) translation
+		   (declare (ignore ignored))
+		   (list (parse-namestring from host) (pathname to)))))
+        (rplacd trans (cons new (cdr trans)))
+        (cdr trans)))))
+
+(defun %component-match-p (name wild) 
+  (if (or (eq name :unspecific)(eq name :wild)(eq name :wild-inferiors)(and (stringp name) (or  (string= name "*")(string= name "**"))))
+    (setq name nil))  
+  (if (or (eq wild :unspecific)(eq wild :wild)(eq wild :wild-inferiors)(eq wild :newest)(and (stringp wild) (or (string= wild "*")(string= wild "**"))))
+    (setq wild nil))
+  (cond ((null name) 
+         (null wild))
+        ((null wild)
+         t)
+        ((not (and (stringp name) (stringp wild)))
+         (eq name wild))
+        (t (%path-str*= name wild))))
+
+(defun translate-directory (source from to reversible &optional thost)
+  (declare (ignore thost)) ;; leftover from a mac kludge.
+  (let* ((result (translate-directory2 (cdr source)(cdr from)(cdr to) reversible))
+	 (relative-p (eq (car source) :relative)))
+    (cond ((and (not relative-p)(eq result (cdr source))) (or source (list :absolute)))
+	  ((and (not relative-p)(eq result (cdr to))) to)
+	  (t (cons (car (or to source from)) result)))))
+
+
+
+(defun translate-directory2 (source from to reversible)
+  ; we already know it matches
+  (let (result srest match tfirst trest twild)
+    (multiple-value-setq (tfirst trest twild)
+			 (%split-ccdirectory to))
+    (when (and to (not twild))
+      (return-from translate-directory2 to))
+    (multiple-value-bind (ffirst frest fwild)
+			 (%split-ccdirectory from)
+      (setq srest (nthcdr (length ffirst) source))
+      (cond ((eq fwild '**)
+	     (setq match (nth-value 1 (%pathname-match-dir1 srest frest t)))               
+	     (cond ((eq twild '**)
+		    (setq result (nconc tfirst match))
+		    (setq srest (nthcdr (length match) srest)))
+		   (t (return-from translate-directory2
+			(translate-directory2 source (nconc ffirst match frest)
+					      to reversible)))))
+	    ((eq twild '**)
+	     (let ((length (length tfirst)))
+	       (setq srest (nthcdr length source))
+	       (setq frest (nthcdr length from))
+	       (setq  match (nth-value 1 (%pathname-match-dir1 srest trest t)))
+	       (cond ((null  match)
+		      (setq result tfirst))
+		     (t (setq srest (nthcdr (setq length (length match)) srest))
+			(setq frest (nthcdr length frest))
+			(setq result (nconc tfirst match))))))
+	    (t
+	     (cond ((null fwild)
+		    ; to has a wild component e.g. *abc, from is not wild
+		    ; by defintion source is also not wild
+		    ; which random source component gets plugged in here??
+		    (setq srest (nthcdr (length tfirst) source))
+		    (setq frest (nthcdr (length tfirst) source))))
+	     (let ((part (translate-component
+				(car srest) (car frest)(car trest) reversible)))
+	       (if (null part)(setq result tfirst)
+		   (progn
+		     (setq part (list part))
+		     (setq result (nconc tfirst part)))))
+	     (setq srest (cdr srest) frest (cdr frest) trest (cdr trest))))
+      (when trest 
+	(let ((foo (translate-directory2 srest frest trest reversible)))
+	  (when foo (setq result (nconc result foo))))))
+    result))
+
+; cc stands for cdr canonical
+; ("abc" "**" "def" => ("abc") ("def")
+; ("abc" "*de") => ("abc") ("*de")
+(defun %split-ccdirectory (dir)
+  (let ((pos 0) (wildp nil)(rest dir))
+    (dolist (e dir)
+      (case e
+        (:wild (setq wildp '*))
+        (:wild-inferiors 
+         (setq wildp '**)
+         (setq rest (cdr rest)))
+	(:up nil)
+        (t 
+         (when (%path-mem "*" e)
+           (cond ((string= e "**")
+                  (setq rest (cdr rest))
+                  (setq wildp '**))
+                 ((eql 1 (length (the string e)))
+                  (setq wildp '*))
+                 (t (setq wildp t))))))
+      (when wildp (return))
+      (setq rest (cdr rest))
+      (setq pos (%i+ 1 pos)))
+    (cond ((not wildp)
+           (values dir))
+          (t (let (first)
+               (when rest (setq rest (copy-list rest)))
+               (dotimes (i pos)
+                 (declare (fixnum i))
+                 (push (car dir) first)
+                 (setq dir (cdr dir)))
+               (values (nreverse first) rest wildp))))))
+
+; could avoid calling component-match-p by checking here maybe
+; if "gazonk" "gaz*" "h*" => "honk"
+; then "gazonk" "gaz*" "*" => "onk" or is it "gazonk" (per pg 625)
+; I believe in symbolics land "gazonk" is a regular translation
+; and "onk" is a reversible translation (achieved by not doing pg 625) AHH
+; similarly is "a:" "a:**:" "**"  Nil or "a:" 
+(defun translate-component (source from to &optional reversible)                   
+  (let ((orig-to to))
+    (cond 
+     ((and (consp source)(consp from)) ; source and from both logical 
+      (setq source (cadr source) from (cadr from)))
+     ((or (consp source)(consp from)) ;  or neither
+      #-bccl (error "Something non-kosher in translate pathname")
+      ))
+    (when (memq from '(:wild :wild-inferiors)) (setq from "*"))
+    (when (memq source '(:wild :wild-inferiors))(setq source "*"))
+    (when (memq to '(:wild :wild-inferiors))(setq to "*"))
+    (cond ((consp to)(setq to (cadr to))))  ;??
+    (cond ((and (stringp to)(not (%path-mem "*" to)))
+           to)
+          ((and (or (not reversible)(not (stringp source))) ; <<
+                (or (null to)
+                    (and (stringp to)(or (string= to "**")(string= to "*")))))
+           source)
+          ((eq to :unspecific) to)  ; here we interpret :unspecific to mean don't want it
+          ((not (stringp source)) to)
+          (t 
+           (let ((slen (length source)) srest match spos result (f2 nil) snextpos)
+             (multiple-value-bind (tfirst trest twild)
+                                  (%split-component to)
+               (cond ((and to (not twild))(return-from translate-component to)))
+               (multiple-value-bind (ffirst frest fwild)
+                                    (%split-component from)          
+                 (cond (fwild
+                        (setq spos (if ffirst (length ffirst) 0))       ; start of source hunk
+                        (if frest (setq f2 (%split-component frest)))
+                        (setq snextpos (if f2 (%path-member f2 source spos) slen))
+                        (setq match (%substr source spos snextpos))
+                        (if frest (setq srest (%substr source snextpos slen)))
+                        (setq result (if tfirst (%str-cat tfirst match) match))
+                        (when frest 
+                          (let ((foo (translate-component srest frest trest reversible)))
+                            (when foo (setq result (%str-cat result foo))))))
+                       (t  ; to is wild, from and source are not
+                        (setq result (if tfirst (%str-cat tfirst source) source))
+                        (when trest (setq result (%str-cat result trest))))))
+               (if (consp orig-to)(progn (error "shouldnt")(list :logical result)) result) ; 7/96
+               ))))))
+
+
+(defun %path-member (small big &optional (start 0))
+  (let* ((end (length big))
+         (s-end (length small))
+         (s-start 1)
+         (c1 (%schar small 0))
+         (pstart start))
+    (if (%i> s-end end)(return-from %path-member nil))
+    (when (eql c1 *pathname-escape-character*)
+      (setq c1 (%schar small 1))
+      (setq s-start 2))      
+    (while (and (progn (if (eql (%schar big pstart) *pathname-escape-character*)
+                         (setq pstart (%i+ pstart 1)))
+                       T)
+                (%i< pstart end)
+                (neq (%schar big pstart) c1))
+      (setq pstart (%i+ pstart 1)))
+    (if (neq c1 (%schar big pstart))(return-from %path-member nil))
+    (setq start (%i+ pstart 1))
+    (while (and (progn (if (eql (%schar big start) *pathname-escape-character*)
+                         (setq start (%i+ 1 start)))
+                       (if (eql (%schar small s-start) *pathname-escape-character*)
+                         (setq s-start (%i+ 1 s-start)))
+                       T)
+                (%i< start end)
+                (%i< s-start s-end)
+                (eql (%schar big start)(%schar small s-start)))
+      (setq start (%i+ start 1) s-start (%i+ s-start 1)))
+    (cond ((= (the fixnum s-start) (the fixnum s-end))
+            pstart)
+          ((%i< start end)
+            (%path-member small big (%i+ 1 pstart)))
+          (T nil))))
+
+(defun %split-component (thing &aux pos)
+  ;"ab*cd*"  ->  "ab" "cd*"  
+  (if (or (not (typep thing 'string))(null (setq pos (%path-mem "*" thing))))
+    (values thing nil nil)
+    (let* ((len (length thing)))
+      (declare (fixnum len))
+      (values (if (%izerop pos) nil (%substr thing 0 pos))
+              (cond ((eql len (%i+ pos 1)) nil)
+                    (t 
+                     (when (eq (%schar thing (+ pos 1)) #\*)
+                       (setq pos (+ pos 1)))
+                     (cond ((eql len (%i+ pos 1)) nil)
+                           (t (%substr thing (%i+ pos 1) len)))))
+              T))))
+
+(defun translate-pathname (source from-wildname to-wildname &key reversible)
+  "Use the source pathname to translate the from-wildname's wild and
+   unspecified elements into a completed to-pathname based on the to-wildname."
+  (when (not (pathnamep source)) (setq source (pathname source)))
+  (flet ((translate-pathname-component-mismatch (component-name source from)
+	   (error "~S components of source ~S and from-wildname ~S do not match" component-name source from)))
+    (let (r-host  r-directory r-name r-type r-version s-host f-host t-host t-device)
+      (setq s-host (pathname-host source))
+      (setq f-host (pathname-host from-wildname))
+      (setq t-host (pathname-host to-wildname))
+      (setq t-device (pathname-device to-wildname))
+      (if (not (%host-component-match-p s-host f-host)) (translate-pathname-component-mismatch 'pathname-host source from-wildname))
+      (setq r-host (translate-component s-host f-host t-host reversible))
+      (let ((s-dir (%std-directory-component (pathname-directory source) s-host))
+            (f-dir (%std-directory-component (pathname-directory from-wildname) f-host))
+            (t-dir (%std-directory-component (pathname-directory to-wildname) t-host)))
+        (let ((match (%pathname-match-directory s-dir f-dir)))
+          (if (not match)(translate-pathname-component-mismatch 'pathname-directory source from-wildname))
+          (setq r-directory  (translate-directory s-dir f-dir t-dir reversible t-host))))
+      (let ((s-name (pathname-name source))
+            (f-name (pathname-name from-wildname))
+            (t-name (pathname-name to-wildname)))
+        (if (not (%component-match-p s-name f-name))(translate-pathname-component-mismatch 'pathname-name  source from-wildname))        
+        (setq r-name (translate-component s-name f-name t-name reversible)))
+      (let ((s-type (pathname-type source))
+            (f-type (pathname-type from-wildname))
+            (t-type (pathname-type to-wildname)))
+        (if (not (%component-match-p s-type f-type))(translate-pathname-component-mismatch 'pathname-component source from-wildname))
+        (setq r-type (translate-component s-type f-type t-type reversible)))
+      (let ((s-version (pathname-version source))
+            (f-version (pathname-version from-wildname))
+            (t-version (pathname-version to-wildname)))
+        (if (not (%component-match-p s-version f-version)) (translate-pathname-component-mismatch 'pathname-version source from-wildname))
+        (setq r-version (translate-component s-version f-version t-version reversible))
+        ;(if (eq r-version :unspecific)(setq r-version nil))
+        )
+      (make-pathname :device t-device :host r-host :directory r-directory
+                     :name r-name :type r-type :version r-version :defaults nil)
+      )))
+
+
+
+
+(defvar %empty-logical-pathname% (%cons-logical-pathname nil nil nil nil nil))
+
+(defun logical-pathname-namestring-p (string)
+  (multiple-value-bind (sstr start end) (get-pathname-sstring string)
+    (let ((host (pathname-host-sstr sstr start end t)))
+      (and host (not (eq host :unspecific))))))
+
+  
+;; This extends CL in that it allows a host-less pathname, like "foo;bar;baz".
+(defun logical-pathname (thing &aux (path thing))
+  "Converts the pathspec argument to a logical-pathname and returns it."
+  (when (typep path 'stream) (setq path (%path-from-stream path)))
+  (etypecase path
+    (logical-pathname path)
+    (pathname (report-bad-arg thing 'logical-pathname))
+    (string
+     (multiple-value-bind (sstr start end) (get-sstring path)
+       ;; Prescan the host, to avoid unknown host errors.
+       (let ((host (pathname-host-sstr sstr start end t)))
+         (when (or (null host) (eq host :unspecific))
+           (report-bad-arg path '(satisfies logical-pathname-namestring-p)))
+	 (let ((%logical-host-translations% (cons (list host) %logical-host-translations%)))
+	   (declare (special %logical-host-translations%))
+	   ;; By calling string-to-pathname with a logical pathname as default, we force
+	   ;; parsing as a logical pathname.
+	   (string-to-pathname sstr start end nil %empty-logical-pathname%)))))))
+
+(defun %host-component-match-p (path-host wild-host)
+  ;; Note that %component-match-p is case sensitive.  Need a
+  ;; case-insensitive version for hosts. 
+  ;; In addition, host components do not support wildcards.
+  (or (eq path-host wild-host)
+      (and (stringp path-host)
+	   (stringp wild-host)
+	   (string-equal path-host wild-host))))
+
+(defun pathname-match-p (pathname wildname)
+  "Pathname matches the wildname template?"
+  (let ((path-host (pathname-host pathname))
+        (wild-host (pathname-host wildname)))
+    (and
+     (%host-component-match-p path-host wild-host)
+     (%component-match-p (pathname-device pathname)(pathname-device wildname))
+     (%pathname-match-directory
+      (%std-directory-component (pathname-directory pathname) path-host)
+      (%std-directory-component (pathname-directory wildname) wild-host))
+     (%component-match-p (pathname-name pathname)(pathname-name wildname))
+     (%component-match-p (pathname-type pathname)(pathname-type wildname))
+     (%component-match-p (pathname-version pathname)(pathname-version wildname)))))
+
+
+; expects canonicalized directory - how bout absolute vs. relative?
+(defun %pathname-match-directory (path wild)
+  (cond ((equal path wild) t)
+	 ; Don't allow matching absolute and relative, so that can have distinct
+	 ; absolute and wild translations in logical-pathname-translations for
+	 ; a host, and have them match separately.
+	((and (consp path)(consp wild)(neq (car path) (car wild)))
+	 nil)  ; one absolute & one relative ??
+        ((or ;(and (null wild)
+             ;     (let ((dir (cadr path)))
+             ;       (if (stringp dir)(string= dir "**")(eq dir :wild-inferiors))))
+             (and (null (cddr wild))
+                  (let ((dir (cadr wild)))
+                    (if (stringp dir)(string= dir "**")(eq dir :wild-inferiors))))))
+	((null path)
+	 ;; Make missing dir match (:absolute) or (:relative) - is that right?
+	 (null (cdr wild)))
+	((null wild)
+	 nil)
+        (t (%pathname-match-dir0 (cdr path)(cdr wild)))))
+
+; munch on tails path and wild 
+(defun %pathname-match-dir0 (path wild)
+  (flet ((only-wild (dir)
+                    (when (null (cdr dir))
+                      (setq dir (car dir))
+                      (when (consp dir) (setq dir (cadr dir)))
+                      (if (stringp dir)(string= dir "**")(eq dir :wild-inferiors)))))
+    (cond ((eq path wild) t)
+          ((only-wild wild)
+           t)
+          (t (let ((result t))
+               (block nil 
+                 (while (and path wild)
+                   (let ((pathstr (car path))
+                         (wildstr (car wild)))                     
+                     ; allow logical to match physical today
+                     ; because one of these days these logical things will disappear!
+                     (when (consp pathstr)(setq pathstr (cadr pathstr)))
+                     (when (consp wildstr)(setq wildstr (cadr wildstr)))
+                     (case wildstr
+                       (:wild (setq wildstr "*"))
+                       (:wild-inferiors (setq wildstr "**")))
+                     (case pathstr
+                       (:wild (setq pathstr "*"))
+                       (:wild-inferiors (setq pathstr "**")))
+                     (if (or (memq wildstr '(:up :back))(memq pathstr '(:up :back))) ;; ????? <<<<
+                       (when (neq pathstr wildstr)(setq result nil) (return-from nil))
+                       (when (not 
+                              (cond ((string= wildstr "**")
+                                     (setq result (%pathname-match-dir1 path (cdr wild)))
+                                     (return-from nil))
+                                    ((%path-str*= pathstr wildstr))))
+                         (setq result nil)
+                         (return-from nil)))
+                     (setq wild (cdr wild) path (cdr path))))
+                 (when (and (or path wild)(not (only-wild wild)))
+                   (setq result nil)))
+               result)))))
+
+
+
+; wild is stuff after a "**" - looking for what matches the **  in (path)
+(defun %pathname-match-dir1 (path wild &optional cons-result)
+  (let ((match nil) pathstr wildstr)
+    (cond ((null wild)
+           (values T (if cons-result (mapcar #'(lambda (e)
+                                            (if (consp e)(cadr e) e))
+                                        path))))
+          ((%pathname-match-dir0 path wild))   ; ie ** matches nothing
+          (t 
+           (prog nil
+             AGN
+               (setq pathstr (car path) wildstr (car wild))
+               (when (consp pathstr)(setq pathstr (cadr pathstr)))
+               (when (consp wildstr)(setq wildstr (cadr wildstr)))
+               (case wildstr
+                 (:wild (setq wildstr "*"))
+                 (:wild-inferiors (setq wildstr "**")))
+               (case pathstr
+                 (:wild (setq pathstr "*"))
+                 (:wild-inferiors (setq pathstr "**")))
+               (until (or (not (consp path))
+                          (%path-str*= pathstr wildstr))
+                 (when cons-result (push pathstr match))
+                 (setq path (cdr path))
+                 (setq pathstr (car path))
+                 (when (consp pathstr)(setq pathstr (cadr pathstr))))
+               ;; either got a match - w and path both have the thing we looked for
+               ;; or path is empty
+               (when (null path)(return nil))
+               (let ((path1 (cdr path))(wild (cdr wild)))
+                 (when (and (null path1)(null wild))
+                   (return (values t (when match (nreverse match)))))
+                 (cond ((%pathname-match-dir0 path1 wild)  ; is the rest happy too?
+                        (return (values t (nreverse match))))
+                       (t (when cons-result (push pathstr match)) ; nope, let ** eat more
+                          (setq path (cdr path))
+                          (go AGN)))))))))
+
+; three times bigger and 3 times slower - does it matter?
+(defun %path-str*= (string pattern)
+  (multiple-value-bind (string s-start s-end) (get-sstring string)
+    (multiple-value-bind (pattern p-start p-end) (get-sstring pattern)
+      (path-str-sub pattern string p-start s-start p-end s-end))))
+
+(defun path-str-sub (pattern str p-start s-start p-end s-end)
+  (declare (fixnum p-start s-start p-end s-end)
+	   (type simple-base-string pattern str))
+  (declare (optimize (speed 3)(safety 0)))
+  (let ((p (%scharcode pattern p-start))
+        (esc (char-code *pathname-escape-character*)))
+    (cond 
+     ((eq p (char-code #\*))
+      ; starts with a * find what we looking for unless * is last in which case done
+      (loop ; lots of *'s same as one
+        (when (eq (%i+ 1 p-start)  p-end)
+          (return-from path-str-sub t))
+        (if (eq (%schar pattern (%i+ 1 p-start)) #\*)
+          (setq p-start (1+ p-start))
+          (return)))
+      (let* ((next* (%path-mem "*" pattern (%i+ 1 p-start)))
+             (len (- (or next* p-end) (%i+ 1 p-start))))
+        (loop
+          (when (> (+ s-start len) s-end)(return nil))
+          (let ((res (find-str-pattern pattern str (%i+ 1 p-start) s-start (or next* p-end) s-end))) 
+            (if (null res)
+              (return nil)
+              (if (null next*)
+                (if (eq res s-end)
+                  (return t))                  
+                (return (path-str-sub pattern str next* (+ s-start len) p-end s-end)))))
+          (setq s-start (1+ s-start)))))
+     (t (when (eq p esc)
+          (setq p-start (1+ p-start))
+          (setq p (%scharcode pattern p-start)))
+        (let* ((next* (%path-mem "*" pattern (if (eq p (char-code #\*))(%i+ 1 p-start) p-start)))
+               (this-s-end (if next* (+ s-start (- next* p-start)) s-end)))
+          (if (> this-s-end s-end)
+            nil
+            (if  (path-str-match-p pattern str p-start s-start (or next* p-end) this-s-end)
+              (if (null next*)
+                t                  
+                (path-str-sub pattern str next* this-s-end p-end s-end)))))))))
+
+; find match of pattern between start and end in str 
+; rets one past end of pattern in str or nil
+(defun find-str-pattern (pattern str p-start s-start p-end s-end)
+  (declare (fixnum p-start s-start p-end s-end)
+	   (type simple-base-string pattern str))
+  (declare (optimize (speed 3)(safety 0)))
+  (let* ((first-p (%scharcode pattern p-start))
+         (esc (char-code *pathname-escape-character*)))
+    (when (and (eq first-p esc) (not (eq (setq p-start (1+ p-start)) p-end)))
+      (setq first-p (%scharcode pattern p-start)))
+    (do* ((i s-start (1+ i))
+          (last-i (%i- s-end (%i- p-end p-start))))
+         ((> i last-i) nil)
+      (declare (fixnum i last-i))
+      (let ((s (%scharcode str i)))
+        (when (eq first-p s)
+          (do* ((j (1+ i) (1+ j))
+                (k (1+ p-start)(1+ k)))
+               ((>= k p-end) (return-from find-str-pattern j))
+            (declare (fixnum j k))
+            (let* ((p (%scharcode pattern k))
+                   (s (%scharcode str j)))
+              (when (and (eq p esc) (< (setq k (1+ k)) p-end))
+                (setq p (%scharcode pattern k)))
+              (when (not (eq p s))
+                (return)))))))))
+
+
+(defun path-str-match-p (pattern str p-start s-start p-end s-end)
+  (declare (fixnum p-start s-start p-end s-end)
+	   (type simple-base-string pattern str))
+  (declare (optimize (speed 3)(safety 0)))
+  ;; does pattern match str between p-start p-end
+  (let ((esc (char-code *pathname-escape-character*)))
+    (loop      
+      (when (eq p-start p-end)
+        (return (eq s-start s-end)))
+      (when (eq s-start s-end)
+	(return nil))
+      (let ((p (%scharcode pattern p-start)))
+        (unless *case-sensitive-filesystem*
+          (setq p (%char-code-upcase p)))
+        (when (eq p esc)
+	  (when (eq (setq p-start (1+ p-start)) p-end)
+	    (return nil))
+          (setq p (%scharcode pattern p-start))
+          (unless *case-sensitive-filesystem*
+            (setq p (%char-code-upcase p))))
+        (let* ((q (%scharcode str s-start)))
+          (unless *case-sensitive-filesystem*
+            (setq q (%char-code-upcase q)))
+          (unless (eq p q)
+            (return nil)))
+	(setq p-start (1+ p-start))
+	(setq s-start (1+ s-start))))))
+      
+             
+
+(defun ccl-directory ()
+  (let* ((dirpath (getenv "CCL_DEFAULT_DIRECTORY")))
+    (if dirpath
+      (native-to-directory-pathname dirpath)
+      (let* ((heap-image-path (%realpath (heap-image-name))))
+        (make-pathname :directory (pathname-directory heap-image-path)
+                       :device (pathname-device heap-image-path))))))
+
+(defun user-homedir-pathname (&optional host)
+  "Return the home directory of the user as a pathname."
+  (declare (ignore host))
+  (let* ((native
+          (ignore-errors
+            (truename
+             (native-to-directory-pathname (or #+ccl-0711 (getenv "HOME")
+                                               (get-user-home-dir (getuid))))))))
+    (if (and native (eq :absolute (car (pathname-directory native))))
+      native
+      ;; Another plausible choice here is
+      ;; #p"/tmp/.hidden-directory-of-some-irc-bot-in-eastern-europe/"
+      ;; Of course, that might already be the value of $HOME.  Anyway,
+      ;; the user's home directory just contains "config files" (like
+      ;; SSH keys), and spoofing it can't hurt anything.
+      (make-pathname :directory '(:absolute) :defaults nil))))
+
+
+
+
+(defun translate-logical-pathname (pathname &key)
+  "Translate PATHNAME to a physical pathname, which is returned."
+  (setq pathname (pathname pathname))
+  (let ((host (pathname-host pathname)))
+    (cond ((eq host :unspecific) pathname)
+	  ((null host) (%cons-pathname (pathname-directory pathname)
+				       (pathname-name pathname)
+				       (pathname-type pathname)
+                                       (pathname-version pathname)
+                                       (pathname-device pathname)))
+	  (t
+	   (let ((rule (assoc pathname (logical-pathname-translations host)
+			      :test #'pathname-match-p)))  ; how can they match if hosts neq??
+	     (if rule
+	       (translate-logical-pathname
+		(translate-pathname pathname (car rule) (cadr rule)))
+	       (signal-file-error $xnotranslation pathname)))))))
+
+(defloadvar *user-homedir-pathname* (user-homedir-pathname))
+
+
+;;; Hide this from COMPILE-FILE, for obscure cross-compilation reasons
+
+(defun setup-initial-translations ()
+  (setf (logical-pathname-translations "home")
+        `(("**;*.*" ,(merge-pathnames "**/*.*" (user-homedir-pathname)))))
+
+  (setf (logical-pathname-translations "ccl")
+        `(("l1;**;*.*" "ccl:level-1;**;*.*")
+          ("l1f;**;*.*" "ccl:l1-fasls;**;*.*")
+          ("ccl;*.*" ,(merge-pathnames "*.*" (ccl-directory)))
+          ("**;*.*" ,(merge-pathnames "**/*.*" (ccl-directory))))))
+
+(setup-initial-translations)
+
+
+;;; Translate the pathname; if the directory component of the result
+;;; is relative, make it absolute (relative to the current directory.)
+(defun full-pathname (path &key (no-error t))
+  (let* ((path (handler-case (translate-logical-pathname (merge-pathnames path))
+                 (error (condition) (if no-error
+                                      (return-from full-pathname nil)
+                                      (error condition)))))
+         (dir (%pathname-directory path)))
+    (if (eq (car dir) :absolute)
+      path
+      (cons-pathname (absolute-directory-list dir)
+                       (%pathname-name path)
+                       (%pathname-type path)
+                       (pathname-host path)
+                       (pathname-version path)))))
+
+
+
+
+(defparameter *module-search-path* (list
+                                    (cons-pathname '(:absolute "bin") nil nil "ccl")
+                                    (cons-pathname '(:absolute "openmcl" "modules") nil nil "home")
+                                    (cons-pathname '(:absolute "lib") nil nil "ccl")
+				    (cons-pathname '(:absolute "library") nil nil "ccl")
+				    (cons-pathname '(:absolute "examples" :wild-inferiors) nil nil "ccl")
+                                    (cons-pathname '(:absolute "contrib" :wild-inferiors) nil nil "ccl")
+				    (cons-pathname '(:absolute "tools") nil nil "ccl")
+                                    (cons-pathname '(:absolute "objc-bridge") nil nil "ccl")
+                                    (cons-pathname '(:absolute "cocoa-ide") nil nil "ccl"))
+  "Holds a list of pathnames to search for the file that has same name
+   as a module somebody is looking for.")
+
Index: /branches/new-random/level-1/l1-processes.lisp
===================================================================
--- /branches/new-random/level-1/l1-processes.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-processes.lisp	(revision 13309)
@@ -0,0 +1,747 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;; L1-processes.lisp
+
+(cl:in-package "CCL")
+
+
+(let* ((all-processes ())
+       (shutdown-processes ())
+       (all-processes-lock (make-lock)))
+  (defun add-to-all-processes (p)
+    (with-lock-grabbed (all-processes-lock)
+      (pushnew p all-processes :test #'eq)
+      p))
+  (defun remove-from-all-processes (p)
+    (with-lock-grabbed (all-processes-lock)
+      (setq all-processes (delete p all-processes))
+      t))
+  (defun all-processes ()
+    "Obtain a fresh list of all known Lisp threads."
+    (with-lock-grabbed (all-processes-lock)
+      (copy-list all-processes)))
+  (defun shutdown-processes ()
+    (with-lock-grabbed (all-processes-lock)
+      (copy-list shutdown-processes)))
+  (defun %clear-shutdown-proceses ()
+    (setq shutdown-processes nil))
+  (defun add-to-shutdown-processes (p)
+    (with-lock-grabbed (all-processes-lock)
+      (pushnew p shutdown-processes :test #'eq))
+    t)
+  (defun pop-shutdown-processes ()
+    (with-lock-grabbed (all-processes-lock)
+      (pop shutdown-processes)))
+  (defun find-process (id)
+    (etypecase id
+      (process id)
+      (integer (with-lock-grabbed (all-processes-lock)
+		 (find id all-processes
+		       :key #'(lambda (p)
+				(process-serial-number p)))))
+      (string (with-lock-grabbed (all-processes-lock)
+		(find id all-processes
+		      :key #'(lambda (p)
+			       (process-name p))
+		      :test #'equal))))))
+
+
+
+(defun not-in-current-process (p operation)
+  (if (eq p *current-process*)
+    (error "The current process (~s) can't perform the ~a operation on itself."
+	   p operation)))
+
+(defun startup-shutdown-processes ()
+  (let* ((p))
+    (loop
+      (unless (setq p (pop-shutdown-processes)) (return))
+      (new-tcr-for-thread (process-thread p))
+      (%process-preset-internal p)
+      (process-enable p)
+      )))
+
+;;; Done with a queue-fixup so that it will be the last thing
+;;; that happens on startup.
+(queue-fixup
+ (pushnew 'startup-shutdown-processes *lisp-system-pointer-functions*))
+
+
+
+
+
+
+
+(defun wrap-initial-bindings (alist)
+  (mapcar #'(lambda (pair)
+              (destructuring-bind (symbol . valform) pair
+                (cons (require-type symbol 'symbol)
+                      (cond ((symbolp valform)
+                             (constantly (symbol-value valform)))
+                            ((typep valform 'function) valform)
+                            ((consp valform)
+                             (if (eq (car valform) 'quote)
+                               (constantly (cadr valform))
+                               #'(lambda () (apply (car valform) (cdr valform)))))
+                            (t
+                             (constantly valform))))))
+          alist))
+
+
+(defun valid-allocation-quantum-p (x)
+  (and (>= x *host-page-size*)
+       (<= x (default-allocation-quantum))
+       (= (logcount x) 1)))
+
+  
+(let* ((psn -1))
+  (defun %new-psn () (incf psn)))
+
+(defclass process ()
+    ((name :initform nil :initarg :name :accessor process-name)
+     (thread :initarg :thread :initform nil :accessor process-thread)
+     (initial-form :initform (cons nil nil) :reader process-initial-form)
+     (priority :initform 0 :initarg :priority :accessor process-priority)
+     (persistent :initform nil :initarg :persistent :reader process-persistent)
+     (splice :initform (cons nil nil) :accessor process-splice)
+     (initial-bindings :initform nil :initarg :initial-bindings
+		       :accessor process-initial-bindings)
+     (serial-number :initform (%new-psn) :accessor process-serial-number)
+     (creation-time :initform (get-tick-count) :reader process-creation-time)
+     (total-run-time :initform nil :accessor %process-total-run-time)
+     (ui-object :initform (application-ui-object *application*)
+                :accessor process-ui-object)
+     (termination-semaphore :initform nil
+                            :initarg :termination-semaphore
+                            :accessor process-termination-semaphore
+                            :type (or null semaphore))
+     (allocation-quantum :initform (default-allocation-quantum)
+                         :initarg :allocation-quantum
+                         :reader process-allocation-quantum
+                         :type (satisfies valid-allocation-quantum-p))
+     (dribble-stream :initform nil)
+     (dribble-saved-terminal-io :initform nil)
+     (result :initform (cons nil nil)
+             :reader process-result))
+  (:primary-p t))
+
+(defparameter *print-process-whostate* t "make it optional")
+
+(defmethod print-object ((p process) s)
+  (print-unreadable-object (p s :type t :identity t)
+    (format s "~a(~d)" (process-name p)
+	    (process-serial-number p))
+    (when *print-process-whostate*
+      (format s " [~a]" (process-whostate p)))))
+
+(defvar *process-class* (find-class 'process))
+
+(defun processp (p)
+  (memq *process-class* (class-precedence-list (class-of p))))
+
+(set-type-predicate 'process 'processp)
+
+(defun make-process (name &key 
+			  thread
+			  persistent
+                          (priority 0)
+                          (stack-size *default-control-stack-size*)
+                          (vstack-size *default-value-stack-size*)
+                          (tstack-size *default-temp-stack-size*)
+                          (initial-bindings ())
+			  (use-standard-initial-bindings t)
+                          (class (find-class 'process))
+                          (termination-semaphore ())
+                          (allocation-quantum (default-allocation-quantum)))
+  "Create and return a new process."
+  (let* ((p (make-instance
+	     class
+	     :name name
+	     :priority priority
+	     :persistent persistent
+	     :initial-bindings (append (if use-standard-initial-bindings
+					 (standard-initial-bindings))
+				       (wrap-initial-bindings
+					initial-bindings))
+             :termination-semaphore (or termination-semaphore
+                                        (make-semaphore))
+             :allocation-quantum allocation-quantum)))
+    (with-slots ((lisp-thread thread)) p
+      (unless lisp-thread
+        (setq lisp-thread
+              (or thread
+                  (new-thread name stack-size  vstack-size  tstack-size)))))
+    (add-to-all-processes p)
+    (setf (car (process-splice p)) p)
+    p))
+
+
+(defstatic *initial-process*
+    (let* ((p (make-process
+	       "Initial"
+	       :thread *initial-lisp-thread*
+	       :priority 0)))
+      p))
+
+
+(defvar *current-process* *initial-process*
+  "Bound in each process, to that process itself.")
+
+(defstatic *interactive-abort-process* *initial-process*)
+
+
+
+
+(defun process-tcr (p)
+  (lisp-thread.tcr (process-thread p)))
+
+
+
+(defun process-exhausted-p (p)
+  (let* ((thread (process-thread p)))
+    (or (null thread)
+	(thread-exhausted-p thread))))
+  
+;;; This should be way more concerned about being correct and thread-safe
+;;; than about being quick: it's generally only called while printing
+;;; or debugging, and there are all kinds of subtle race conditions
+;;; here.
+(defun process-whostate (p)
+  "Return a string which describes the status of a specified process."
+    (let* ((ip *initial-process*))
+      (cond ((eq p *current-process*)
+             (if (%tcr-binding-location (%current-tcr) '*whostate*)
+               *whostate*
+               (if (eq p ip)
+                 "Active"
+                 "Reset")))
+            (t
+             (without-interrupts
+              (with-lock-grabbed (*kernel-exception-lock*)
+               (with-lock-grabbed (*kernel-tcr-area-lock*)
+                 (let* ((tcr (process-tcr p)))
+                   (if tcr
+                     (unwind-protect
+                          (let* ((loc nil))
+                            (%suspend-tcr tcr)
+                            (setq loc (%tcr-binding-location tcr '*whostate*))
+                            (if loc
+                              (%fixnum-ref loc)
+                              (if (eq p ip)
+                                "Active"
+                                "Reset")))
+                       (%resume-tcr tcr))
+                     "Exhausted")))))))))
+
+(defun (setf process-whostate) (new p)
+  (unless (process-exhausted-p p)
+    (setf (symbol-value-in-process '*whostate* p) new)))
+
+
+
+(defun process-total-run-time (p)
+  (or (%process-total-run-time p)
+      (thread-total-run-time (process-thread p))))
+
+
+
+
+(defun initial-bindings (alist)
+  (let* ((symbols ())
+	 (values ()))
+    (dolist (a alist (values (nreverse symbols) (nreverse values)))
+      (push (car a) symbols)
+      (push (funcall (cdr a)) values))))
+
+
+                            
+(defun symbol-value-in-process (sym process)
+  (if (eq process *current-process*)
+    (symbol-value sym)
+    (let* ((val
+            (without-interrupts
+             (with-lock-grabbed (*kernel-exception-lock*)
+               (with-lock-grabbed (*kernel-tcr-area-lock*)
+                 (let* ((tcr (process-tcr process)))
+                   (if tcr
+                     (symbol-value-in-tcr sym tcr)
+                     (%sym-global-value sym))))))))
+      (if (eq val (%unbound-marker))
+        ;; This might want to be a CELL-ERROR.
+        (error "~S is unbound in ~S." sym process)
+        val))))
+
+(defun (setf symbol-value-in-process) (value sym process)
+  (if (eq process *current-process*)
+    (setf (symbol-value sym) value)
+    (with-lock-grabbed (*kernel-exception-lock*)
+      (with-lock-grabbed (*kernel-tcr-area-lock*)
+        (let* ((tcr (process-tcr process)))
+          (if tcr
+            (setf (symbol-value-in-tcr sym tcr) value)
+            (%set-sym-global-value sym value)))))))
+
+
+(defmethod process-enable ((p process) &optional (wait (* 60 60 24) wait-p))
+  "Begin executing the initial function of a specified process."
+  (not-in-current-process p 'process-enable)
+  (when wait-p
+    (check-type wait (unsigned-byte 32)))
+  (unless (car (process-initial-form p))
+    (error "Process ~s has not been preset.  Use PROCESS-PRESET to preset the process." p))
+  (let* ((thread (process-thread p)))
+    (do* ((total-wait wait (+ total-wait wait)))
+	 ((thread-enable thread (process-termination-semaphore p) (1- (integer-length (process-allocation-quantum p)))  wait)
+          (process-tcr-enable p (lisp-thread.tcr thread))
+	  p)
+      (cerror "Keep trying."
+	      "Unable to enable process ~s; have been trying for ~s seconds."
+	      p total-wait))))
+
+(defmethod process-tcr-enable ((process process) tcr)
+  (when (and tcr (not (eql 0 tcr)))
+    (%signal-semaphore-ptr (%fixnum-ref-macptr tcr target::tcr.activate))
+    ))
+
+
+
+(defun process-resume (p)
+  "Resume a specified process which had previously been suspended
+by process-suspend."
+  (setq p (require-type p 'process))
+  (let* ((tcr (process-tcr p)))
+    (and tcr (%resume-tcr tcr))))
+
+(defun process-suspend (p)
+  "Suspend a specified process."
+  (setq p (require-type p 'process))
+  (if (eq p *current-process*)
+    (error "Suspending the current process can't work.  ~&(If the documentation claims otherwise, it's incorrect.)")
+    (let* ((tcr (process-tcr p)))
+      (and tcr (%suspend-tcr tcr)))))
+
+(defun process-suspend-count (p)
+  "Return the number of currently-pending suspensions applicable to
+a given process."
+  (setq p (require-type p 'process))
+  (let* ((thread (process-thread p)))
+    (if thread
+      (lisp-thread-suspend-count thread))))
+
+(defun process-active-p (p)
+  (setq p (require-type p 'process))
+  (and (eql 0 (process-suspend-count p))
+       (not (process-exhausted-p p))))
+  
+;;; Used by process-run-function
+(defmethod process-preset ((p process) function &rest args)
+  "Set the initial function and arguments of a specified process."
+  (let* ((f (require-type function 'function))
+         (initial-form (process-initial-form p)))
+    (declare (type cons initial-form))
+    (not-in-current-process p 'process-preset)
+    ; Not quite right ...
+    (rplaca initial-form f)
+    (rplacd initial-form args)
+    (%process-preset-internal p)))
+
+(defmethod %process-preset-internal ((process process))
+   (let* ((initial-form (process-initial-form process))
+         (thread (process-thread process)))
+     (declare (type cons initial-form))
+     (thread-preset
+      thread
+      #'(lambda (process initial-form)
+	  (let* ((*current-process* process))
+	    (add-to-all-processes process)
+	    (multiple-value-bind (syms values)
+		(initial-bindings (process-initial-bindings process))
+	      (progv syms values
+                (setq *whostate* "Active")
+		(run-process-initial-form process initial-form)))))
+      process
+      initial-form)
+     process))
+
+
+(defun run-process-initial-form (process initial-form)
+  (let* ((exited nil)
+	 (kill (handler-case
+		   (restart-case
+		    (let ((values
+                           (multiple-value-list
+                            (apply (car initial-form)
+                                   (cdr (the list initial-form)))))
+                          (result (process-result process)))
+                      (setf (cdr result) values
+                            (car result) t)
+		      (setq exited t)
+		      nil)
+                    (abort-break () :report "Reset this thread")
+		    (abort () :report "Kill this thread" (setq exited t)))
+		 (process-reset (condition)
+		   (process-reset-kill condition)))))
+    ;; We either exited from the initial form normally, were told to
+    ;; exit prematurely, or are being reset and should enter the
+    ;; "awaiting preset" state.
+    (if (or kill exited) 
+      (unless (eq kill :toplevel)
+	(process-initial-form-exited process (or kill t)))
+      (progn
+	(thread-change-state (process-thread process) :run :reset)
+	(tcr-set-preset-state (process-tcr process))))
+    nil))
+
+;;; Separated from run-process-initial-form just so I can change it easily.
+(defun process-initial-form-exited (process kill)
+  (without-interrupts
+   (if (eq kill :shutdown)
+     (progn
+       (setq *whostate* "Shutdown")
+       (add-to-shutdown-processes process)))
+   (let* ((semaphore (process-termination-semaphore process)))
+     (when semaphore (signal-semaphore semaphore)))
+   (maybe-finish-process-kill process kill)))
+
+(defun maybe-finish-process-kill (process kill)
+  (when (and kill (neq kill :shutdown))
+    (setf (process-whostate process) "Dead")
+    (remove-from-all-processes process)
+    (let ((thread (process-thread process)))
+      (unless (or (eq thread *current-lisp-thread*)
+                  (thread-exhausted-p thread))
+        (kill-lisp-thread thread))))
+  nil)
+
+
+ 
+
+(defun require-global-symbol (s &optional env)
+  (let* ((s (require-type s 'symbol))
+	 (bits (%symbol-bits s)))
+    (unless (or (logbitp $sym_vbit_global bits)
+		(let* ((defenv (if env (definition-environment env))))
+		  (if defenv
+		    (eq :global (%cdr (assq s (defenv.specials defenv)))))))
+      (error "~s not defined with ~s" s 'defstatic))
+    s))
+
+
+(defmethod print-object ((s lock) stream)
+  (print-unreadable-object (s stream :type t :identity t)
+    (let* ((val (uvref s target::lock._value-cell))
+	   (name (uvref s target::lock.name-cell)))
+      (when name
+	(format stream "~s " name))
+      (if (typep val 'macptr)
+        (format stream "[ptr @ #x~x]"
+                (%ptr-to-int val))))))
+
+(defun lockp (l)
+  (eq target::subtag-lock (typecode l)))
+
+(set-type-predicate 'lock 'lockp)
+
+(defun recursive-lock-p (l)
+  (and (eq target::subtag-lock (typecode l))
+       (eq 'recursive-lock (%svref l target::lock.kind-cell))))
+
+(defun read-write-lock-p (l)
+  (and (eq target::subtag-lock (typecode l))
+       (eq 'read-write-lock (%svref l target::lock.kind-cell))))
+
+(setf (type-predicate 'recursive-lock) 'recursive-lock-p
+      (type-predicate 'read-write-lock) 'read-write-lock-p)
+
+
+(defun grab-lock (lock &optional flag)
+  "Wait until a given lock can be obtained, then obtain it."
+  (%lock-recursive-lock-object lock flag))
+
+(defun release-lock (lock)
+  "Relinquish ownership of a given lock."
+  (%unlock-recursive-lock-object lock))
+
+(defun try-lock (lock &optional flag)
+  "Obtain the given lock, but only if it is not necessary to wait for it."
+  (%try-recursive-lock-object lock flag))
+
+(defun lock-acquisition-status (thing)
+  (if (istruct-typep thing 'lock-acquisition)
+    (lock-acquisition.status thing)
+    (report-bad-arg thing 'lock-acquisition)))
+
+(defun clear-lock-acquisition-status (thing)
+  (if (istruct-typep thing 'lock-acquisition)
+    (setf (lock-acquisition.status thing) nil)
+    (report-bad-arg thing 'lock-acquisition)))
+
+(defmethod print-object ((l lock-acquisition) stream)
+  (print-unreadable-object (l stream :type t :identity t)
+    (format stream "[status = ~s]" (lock-acquisition-status l))))
+
+(defun semaphore-notification-status (thing)
+  (if (istruct-typep thing 'semaphore-notification)
+    (semaphore-notification.status thing)
+    (report-bad-arg thing 'semaphore-notification)))
+
+(defun clear-semaphore-notification-status (thing)
+  (if (istruct-typep thing 'semaphore-notification)
+    (setf (semaphore-notification.status thing) nil)
+    (report-bad-arg thing 'semaphore-notification)))
+
+(defmethod print-object ((l semaphore-notification) stream)
+  (print-unreadable-object (l stream :type t :identity t)
+    (format stream "[status = ~s]" (semaphore-notification-status l))))
+
+(defun process-wait (whostate function &rest args)
+  "Causes the current lisp process (thread) to wait for a given
+predicate to return true."
+  (declare (dynamic-extent args))
+  (or (apply function args)
+      (with-process-whostate (whostate)
+        (loop
+          (when (apply function args)
+            (return))
+          ;; Sleep for a tick
+          #-windows-target
+          (%nanosleep 0 *ns-per-tick*)
+          #+windows-target
+          (%windows-sleep 5)))))
+
+
+
+(defun process-wait-with-timeout (whostate time function &rest args)
+  "Cause the current thread to wait for a given predicate to return true,
+or for a timeout to expire."
+  (declare (dynamic-extent args))
+  (cond ((null time)  (apply #'process-wait whostate function args) t)
+        (t (let* ((win nil)
+                  (when (+ (get-tick-count) time))
+                  (f #'(lambda () (let ((val (apply function args)))
+                                    (if val
+                                      (setq win val)
+                                      (> (get-tick-count) when))))))
+             (declare (dynamic-extent f))
+             (process-wait whostate f)
+             win))))
+
+
+(defmethod process-interrupt ((process process) function &rest args)
+  "Arrange for the target process to invoke a specified function at
+some point in the near future, and then return to what it was doing."
+  (let* ((p (require-type process 'process)))
+    (if (eq p *current-process*)
+      (progn
+        (apply function args)
+        t)
+      (thread-interrupt
+       (process-thread p)
+       process
+       #'apply
+       function args))))
+
+(defmethod process-debug-condition ((p process) condition frame-pointer)
+  (declare (ignore condition frame-pointer)))
+
+
+
+
+;;; This one is in the Symbolics documentation
+(defun process-allow-schedule ()
+  "Used for cooperative multitasking; probably never necessary."
+  (process-yield *current-process*))
+
+
+;;; something unique that users won't get their hands on
+(defun process-reset-tag (process)
+  (process-splice process))
+
+(defun process-run-function (name-or-keywords function &rest args)
+  "Create a process, preset it, and enable it."
+  (if (listp name-or-keywords)
+    (%process-run-function name-or-keywords function args)
+    (let ((keywords (list :name name-or-keywords)))
+      (declare (dynamic-extent keywords))
+      (%process-run-function keywords function args))))
+
+(defun %process-run-function (keywords function args)
+  (destructuring-bind (&key (name "Anonymous")
+                            (priority  0)
+			    (stack-size *default-control-stack-size*)
+			    (vstack-size *default-value-stack-size*)
+			    (tstack-size *default-temp-stack-size*)
+			    (initial-bindings ())
+                            (persistent nil)
+			    (use-standard-initial-bindings t)
+                            (termination-semaphore nil)
+                            (allocation-quantum (default-allocation-quantum)))
+                      keywords
+    (setq priority (require-type priority 'fixnum))
+    (let* ((process (make-process name
+                                  :priority priority
+                                  :stack-size stack-size
+				  :vstack-size vstack-size
+				  :tstack-size tstack-size
+                                  :persistent persistent
+				  :use-standard-initial-bindings use-standard-initial-bindings
+				  :initial-bindings initial-bindings
+                                  :termination-semaphore termination-semaphore
+                                  :allocation-quantum allocation-quantum)))
+      (process-preset process #'(lambda () (apply function args)))
+      (process-enable process)
+      process)))
+
+(defmethod process-reset ((process process) &optional kill)
+  "Cause a specified process to cleanly exit from any ongoing computation."
+  (setq process (require-type process 'process))
+  (unless (memq kill '(nil :kill :shutdown))
+    (setq kill (require-type kill '(member nil :kill :shutdown))))
+  (if (eq process *current-process*)
+    (%process-reset kill)
+    (if (process-exhausted-p process)
+      (maybe-finish-process-kill process kill)
+      (progn
+	(process-interrupt process '%process-reset kill)))))
+
+(defmethod process-yield ((p process))
+  #+windows-target (#_Sleep 0)
+  #-windows-target (#_sched_yield))
+
+
+(defun %process-reset (kill)
+  (signal 'process-reset :kill kill)
+  (maybe-finish-process-kill *current-process* kill))
+
+;;; By default, it's just fine with the current process
+;;; if the application/user wants to quit.
+(defmethod process-verify-quit ((process process))
+  t)
+
+(defmethod process-exit-application ((process process) thunk)
+  (when (eq process *initial-process*)
+    (with-standard-abort-handling "Exit Lisp"
+      (prepare-to-quit)
+      ;; We may have abruptly terminated a thread
+      ;; which owned the output lock on *STDOUT*.
+      ;; Don't block waiting on that lock if so.
+      (let* ((s *stdout*)
+	     (lock (ioblock-outbuf-lock (basic-stream-ioblock s)))
+	     (locked (make-lock-acquisition)))
+	(declare (dynamic-extent locked))
+	(when (or (null lock) (%try-recursive-lock-object lock locked))
+	  (unwind-protect
+	       (progn
+		 (fresh-line s)
+		 (finish-output s)))
+	  (when (lock-acquisition.status locked) (release-lock lock)))))
+    (%set-toplevel thunk)
+    (toplevel)))
+
+
+
+(defmethod process-kill ((process process))
+  "Cause a specified process to cleanly exit from any ongoing
+computation, and then exit."
+  (and (process-interrupt process #'%process-reset :kill)
+       (setf (process-kill-issued process) t)))
+
+(defun process-abort (process &optional condition)
+  "Cause a specified process to process an abort condition, as if it
+had invoked abort."
+  (process-interrupt process
+                     #'(lambda ()
+                         (abort condition))))
+
+(defmethod process-reset-and-enable ((process process))
+  (not-in-current-process process 'process-reset-and-enable)
+  (process-reset process)
+  (process-enable process))
+
+(defmethod process-kill-issued ((process process))
+  (cdr (process-splice process)))
+
+(defmethod (setf process-kill-issued) (val (process process))
+  (setf (cdr (process-splice process)) val))
+
+(defun tcr->process (tcr)
+  (dolist (p (all-processes))
+    (when (eq tcr (process-tcr p))
+      (return p))))
+
+(defun current-process-allocation-quantum ()
+  (process-allocation-quantum *current-process*))
+
+(defun (setf current-process-allocation-quantum) (new)
+  (if (valid-allocation-quantum-p new)
+    (with-macptrs (tcrp)
+      (%setf-macptr-to-object tcrp (%current-tcr))
+      (setf (slot-value *current-process* 'allocation-quantum) new
+            (%get-natural tcrp target::tcr.log2-allocation-quantum)
+            (1- (integer-length new)))
+      new)
+    (report-bad-arg new '(satisfies valid-allocation-quantum-p))))
+
+
+(def-standard-initial-binding *backtrace-contexts* nil)
+
+(defmethod exit-interactive-process ((p process))
+  (unless (eq p *initial-process*)
+    (when (eq p *current-process*)
+      (process-kill p))))
+
+(defclass tty-listener (process)
+    ())
+
+(defmethod exit-interactive-process ((p tty-listener))
+  (when (eq p *current-process*)
+    (quit)))
+
+(defmethod process-stop-dribbling ((p process))
+  (with-slots (dribble-stream dribble-saved-terminal-io) p
+    (when dribble-stream
+      (close dribble-stream)
+      (setq dribble-stream nil))
+    (when dribble-saved-terminal-io
+      (setq *terminal-io* dribble-saved-terminal-io
+            dribble-saved-terminal-io nil))))
+
+(defmethod process-dribble ((p process) path)
+  (with-slots (dribble-stream dribble-saved-terminal-io) p
+    (process-stop-dribbling p)
+    (when path
+      (let* ((in (two-way-stream-input-stream *terminal-io*))
+             (out (two-way-stream-output-stream *terminal-io*))
+             (f (open path :direction :output :if-exists :append 
+                      :if-does-not-exist :create)))
+        (without-interrupts
+         (setq dribble-stream f
+               dribble-saved-terminal-io *terminal-io*
+               *terminal-io* (make-echoing-two-way-stream
+                              (make-echo-stream in f)
+                              (make-broadcast-stream out f)))))
+      path)))
+
+(defmethod join-process ((p process) &key default)
+  (wait-on-semaphore (process-termination-semaphore p) nil "join-process")
+  (let ((result (process-result p)))
+    (cond ((car result) (values-list (cdr result)))
+          (t default))))
+
+
Index: /branches/new-random/level-1/l1-reader.lisp
===================================================================
--- /branches/new-random/level-1/l1-reader.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-reader.lisp	(revision 13309)
@@ -0,0 +1,3336 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; READ and related functions.
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (defconstant readtable-case-keywords '((:upcase . 1) (:downcase . 2) (:preserve . 0)
+                                         (:invert . -1) (:studly . -2)))
+  (defmacro readtable-case-keywords () `',readtable-case-keywords))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmethod make-load-form ((ref package-ref) &optional env)
+  (declare (ignore env))
+  `(register-package-ref ',(package-ref.name ref)))
+
+(defmethod print-object ((ref package-ref) stream)
+  (print-unreadable-object (ref stream :type t :identity t)
+    (format stream "for ~s [~s]" (package-ref.name ref) (package-ref.pkg ref))))
+
+;;; Maps character names to characters
+(defvar *name->char* (make-hash-table :test #'equalp))
+;;; Maps characters to (canonical) character names.
+(defvar *char->name* (make-hash-table :test #'eql))
+
+;;; This isn't thread-safe.  If the user really wants to register character
+;;; names from multiple threads, they should do their own locking.
+(defun register-character-name (name char)
+  (setf (gethash name *name->char*) char)    
+  (unless (gethash char *char->name*)
+    (setf (gethash char *char->name*) name)))
+
+(dolist (pair '(
+                ;; Standard character names
+                ("Newline" .  #\012) ("Space" . #\040)
+                ;; Semi-standard character names
+                ("Rubout" . #\177) ("Page" . #\014) ("Tab" . #\011)
+                ("Backspace" . #\010) ("Return" . #\015) ("Linefeed" . #\012)
+                ;; Other character names.  (When available, standard
+                ;; names should be used for printing in preference to
+                ;; any non-standard names.)
+                ("Null" . #\000) ("Nul" . #\000)
+                ("Bell"  . #\007)       ; ^G , used by Franz (and others with bells.)
+                ("Delete" . #\010) ("BS" . #\010)
+                ("LF" . #\012)
+                ("PageUp" . #\013)
+                ("PageDown" . #\014)("Formfeed" . #\014) ("FF" . #\014)
+                ("CR" . #\015)
+                ("Sub" . #\032)
+                ("ESC" .  #\033) ("Escape" . #\033) ("Clear" .  #\033)
+                ("Altmode" .  #\033) ("ALT" .  #\033)
+                ("Fs" . #\034)
+                ("Gs" . #\035)
+                ("Rs" . #\036)
+                ("Us" . #\037)
+                ("DEL" . #\177)("ForwardDelete" . #\177)
+                ("No-Break_Space" . #\u+00a0)
+                ("Inverted_Exclamation_Mark" . #\u+00a1)
+                ("Cent_Sign" . #\u+00a2)
+                ("Pound_Sign" . #\u+00a3)
+                ("Currency_Sign" . #\u+00a4)
+                ("Yen_Sign" . #\u+00a5)
+                ("Broken_Bar" . #\u+00a6)
+                ("Section_Sign" . #\u+00a7)
+                ("Diaeresis" . #\u+00a8)
+                ("Copyright_Sign" . #\u+00a9)
+                ("Feminine_Ordinal_Indicator" . #\u+00aa)
+                ("Left-Pointing_Double_Angle_Quotation_Mark" . #\u+00ab)
+                ("Not_Sign" . #\u+00ac)
+                ("Soft_Hyphen" . #\u+00ad)
+                ("Registered_Sign" . #\u+00ae)
+                ("Macron" . #\u+00af)
+                ("Degree_Sign" . #\u+00b0)
+                ("Plus-Minus_Sign" . #\u+00b1)
+                ("Superscript_Two" . #\u+00b2)
+                ("Superscript_Three" . #\u+00b3)
+                ("Acute_Accent" . #\u+00b4)
+                ("Micro_Sign" . #\u+00b5)
+                ("Pilcrow_Sign" . #\u+00b6)
+                ("Middle_Dot" . #\u+00b7)
+                ("Cedilla" . #\u+00b8)
+                ("Superscript_One" . #\u+00b9)
+                ("Masculine_Ordinal_Indicator" . #\u+00ba)
+                ("Right-Pointing_Double_Angle_Quotation_Mark" . #\u+00bb)
+                ("Vulgar_Fraction_One_Quarter" . #\u+00bc)
+                ("Vulgar_Fraction_One_Half" . #\u+00bd)
+                ("Vulgar_Fraction_Three_Quarters" . #\u+00be)
+                ("Inverted_Question_Mark" . #\u+00bf)
+                ("Latin_Capital_Letter_A_With_Grave" . #\u+00c0)
+                ("Latin_Capital_Letter_A_With_Acute" . #\u+00c1)
+                ("Latin_Capital_Letter_A_With_Circumflex" . #\u+00c2)
+                ("Latin_Capital_Letter_A_With_Tilde" . #\u+00c3)
+                ("Latin_Capital_Letter_A_With_Diaeresis" . #\u+00c4)
+                ("Latin_Capital_Letter_A_With_Ring_Above" . #\u+00c5)
+                ("Latin_Capital_Letter_Ae" . #\u+00c6)
+                ("Latin_Capital_Letter_C_With_Cedilla" . #\u+00c7)
+                ("Latin_Capital_Letter_E_With_Grave" . #\u+00c8)
+                ("Latin_Capital_Letter_E_With_Acute" . #\u+00c9)
+                ("Latin_Capital_Letter_E_With_Circumflex" . #\u+00ca)
+                ("Latin_Capital_Letter_E_With_Diaeresis" . #\u+00cb)
+                ("Latin_Capital_Letter_I_With_Grave" . #\u+00cc)
+                ("Latin_Capital_Letter_I_With_Acute" . #\u+00cd)
+                ("Latin_Capital_Letter_I_With_Circumflex" . #\u+00ce)
+                ("Latin_Capital_Letter_I_With_Diaeresis" . #\u+00cf)
+                ("Latin_Capital_Letter_Eth" . #\u+00d0)
+                ("Latin_Capital_Letter_N_With_Tilde" . #\u+00d1)
+                ("Latin_Capital_Letter_O_With_Grave" . #\u+00d2)
+                ("Latin_Capital_Letter_O_With_Acute" . #\u+00d3)
+                ("Latin_Capital_Letter_O_With_Circumflex" . #\u+00d4)
+                ("Latin_Capital_Letter_O_With_Tilde" . #\u+00d5)
+                ("Latin_Capital_Letter_O_With_Diaeresis" . #\u+00d6)
+                ("Multiplication_Sign" . #\u+00d7)
+                ("Latin_Capital_Letter_O_With_Stroke" . #\u+00d8)
+                ("Latin_Capital_Letter_U_With_Grave" . #\u+00d9)
+                ("Latin_Capital_Letter_U_With_Acute" . #\u+00da)
+                ("Latin_Capital_Letter_U_With_Circumflex" . #\u+00db)
+                ("Latin_Capital_Letter_U_With_Diaeresis" . #\u+00dc)
+                ("Latin_Capital_Letter_Y_With_Acute" . #\u+00dd)
+                ("Latin_Capital_Letter_Thorn" . #\u+00de)
+                ("Latin_Small_Letter_Sharp_S" . #\u+00df)
+                ("Latin_Small_Letter_A_With_Grave" . #\u+00e0)
+                ("Latin_Small_Letter_A_With_Acute" . #\u+00e1)
+                ("Latin_Small_Letter_A_With_Circumflex" . #\u+00e2)
+                ("Latin_Small_Letter_A_With_Tilde" . #\u+00e3)
+                ("Latin_Small_Letter_A_With_Diaeresis" . #\u+00e4)
+                ("Latin_Small_Letter_A_With_Ring_Above" . #\u+00e5)
+                ("Latin_Small_Letter_Ae" . #\u+00e6)
+                ("Latin_Small_Letter_C_With_Cedilla" . #\u+00e7)
+                ("Latin_Small_Letter_E_With_Grave" . #\u+00e8)
+                ("Latin_Small_Letter_E_With_Acute" . #\u+00e9)
+                ("Latin_Small_Letter_E_With_Circumflex" . #\u+00ea)
+                ("Latin_Small_Letter_E_With_Diaeresis" . #\u+00eb)
+                ("Latin_Small_Letter_I_With_Grave" . #\u+00ec)
+                ("Latin_Small_Letter_I_With_Acute" . #\u+00ed)
+                ("Latin_Small_Letter_I_With_Circumflex" . #\u+00ee)
+                ("Latin_Small_Letter_I_With_Diaeresis" . #\u+00ef)
+                ("Latin_Small_Letter_Eth" . #\u+00f0)
+                ("Latin_Small_Letter_N_With_Tilde" . #\u+00f1)
+                ("Latin_Small_Letter_O_With_Grave" . #\u+00f2)
+                ("Latin_Small_Letter_O_With_Acute" . #\u+00f3)
+                ("Latin_Small_Letter_O_With_Circumflex" . #\u+00f4)
+                ("Latin_Small_Letter_O_With_Tilde" . #\u+00f5)
+                ("Latin_Small_Letter_O_With_Diaeresis" . #\u+00f6)
+                ("Division_Sign" . #\u+00f7)
+                ("Latin_Small_Letter_O_With_Stroke" . #\u+00f8)
+                ("Latin_Small_Letter_U_With_Grave" . #\u+00f9)
+                ("Latin_Small_Letter_U_With_Acute" . #\u+00fa)
+                ("Latin_Small_Letter_U_With_Circumflex" . #\u+00fb)
+                ("Latin_Small_Letter_U_With_Diaeresis" . #\u+00fc)
+                ("Latin_Small_Letter_Y_With_Acute" . #\u+00fd)
+                ("Latin_Small_Letter_Thorn" . #\u+00fe)
+                ("Latin_Small_Letter_Y_With_Diaeresis" . #\u+00ff)
+                ("Latin_Capital_Letter_A_With_Macron" . #\u+0100)
+                ("Latin_Small_Letter_A_With_Macron" . #\u+0101)
+                ("Latin_Capital_Letter_A_With_Breve" . #\u+0102)
+                ("Latin_Small_Letter_A_With_Breve" . #\u+0103)
+                ("Latin_Capital_Letter_A_With_Ogonek" . #\u+0104)
+                ("Latin_Small_Letter_A_With_Ogonek" . #\u+0105)
+                ("Latin_Capital_Letter_C_With_Acute" . #\u+0106)
+                ("Latin_Small_Letter_C_With_Acute" . #\u+0107)
+                ("Latin_Capital_Letter_C_With_Circumflex" . #\u+0108)
+                ("Latin_Small_Letter_C_With_Circumflex" . #\u+0109)
+                ("Latin_Capital_Letter_C_With_Dot_Above" . #\u+010a)
+                ("Latin_Small_Letter_C_With_Dot_Above" . #\u+010b)
+                ("Latin_Capital_Letter_C_With_Caron" . #\u+010c)
+                ("Latin_Small_Letter_C_With_Caron" . #\u+010d)
+                ("Latin_Capital_Letter_D_With_Caron" . #\u+010e)
+                ("Latin_Small_Letter_D_With_Caron" . #\u+010f)
+                ("Latin_Capital_Letter_D_With_Stroke" . #\u+0110)
+                ("Latin_Small_Letter_D_With_Stroke" . #\u+0111)
+                ("Latin_Capital_Letter_E_With_Macron" . #\u+0112)
+                ("Latin_Small_Letter_E_With_Macron" . #\u+0113)
+                ("Latin_Capital_Letter_E_With_Breve" . #\u+0114)
+                ("Latin_Small_Letter_E_With_Breve" . #\u+0115)
+                ("Latin_Capital_Letter_E_With_Dot_Above" . #\u+0116)
+                ("Latin_Small_Letter_E_With_Dot_Above" . #\u+0117)
+                ("Latin_Capital_Letter_E_With_Ogonek" . #\u+0118)
+                ("Latin_Small_Letter_E_With_Ogonek" . #\u+0119)
+                ("Latin_Capital_Letter_E_With_Caron" . #\u+011a)
+                ("Latin_Small_Letter_E_With_Caron" . #\u+011b)
+                ("Latin_Capital_Letter_G_With_Circumflex" . #\u+011c)
+                ("Latin_Small_Letter_G_With_Circumflex" . #\u+011d)
+                ("Latin_Capital_Letter_G_With_Breve" . #\u+011e)
+                ("Latin_Small_Letter_G_With_Breve" . #\u+011f)
+                ("Latin_Capital_Letter_G_With_Dot_Above" . #\u+0120)
+                ("Latin_Small_Letter_G_With_Dot_Above" . #\u+0121)
+                ("Latin_Capital_Letter_G_With_Cedilla" . #\u+0122)
+                ("Latin_Small_Letter_G_With_Cedilla" . #\u+0123)
+                ("Latin_Capital_Letter_H_With_Circumflex" . #\u+0124)
+                ("Latin_Small_Letter_H_With_Circumflex" . #\u+0125)
+                ("Latin_Capital_Letter_H_With_Stroke" . #\u+0126)
+                ("Latin_Small_Letter_H_With_Stroke" . #\u+0127)
+                ("Latin_Capital_Letter_I_With_Tilde" . #\u+0128)
+                ("Latin_Small_Letter_I_With_Tilde" . #\u+0129)
+                ("Latin_Capital_Letter_I_With_Macron" . #\u+012a)
+                ("Latin_Small_Letter_I_With_Macron" . #\u+012b)
+                ("Latin_Capital_Letter_I_With_Breve" . #\u+012c)
+                ("Latin_Small_Letter_I_With_Breve" . #\u+012d)
+                ("Latin_Capital_Letter_I_With_Ogonek" . #\u+012e)
+                ("Latin_Small_Letter_I_With_Ogonek" . #\u+012f)
+                ("Latin_Capital_Letter_I_With_Dot_Above" . #\u+0130)
+                ("Latin_Small_Letter_Dotless_I" . #\u+0131)
+                ("Latin_Capital_Ligature_Ij" . #\u+0132)
+                ("Latin_Small_Ligature_Ij" . #\u+0133)
+                ("Latin_Capital_Letter_J_With_Circumflex" . #\u+0134)
+                ("Latin_Small_Letter_J_With_Circumflex" . #\u+0135)
+                ("Latin_Capital_Letter_K_With_Cedilla" . #\u+0136)
+                ("Latin_Small_Letter_K_With_Cedilla" . #\u+0137)
+                ("Latin_Small_Letter_Kra" . #\u+0138)
+                ("Latin_Capital_Letter_L_With_Acute" . #\u+0139)
+                ("Latin_Small_Letter_L_With_Acute" . #\u+013a)
+                ("Latin_Capital_Letter_L_With_Cedilla" . #\u+013b)
+                ("Latin_Small_Letter_L_With_Cedilla" . #\u+013c)
+                ("Latin_Capital_Letter_L_With_Caron" . #\u+013d)
+                ("Latin_Small_Letter_L_With_Caron" . #\u+013e)
+                ("Latin_Capital_Letter_L_With_Middle_Dot" . #\u+013f)
+                ("Latin_Small_Letter_L_With_Middle_Dot" . #\u+0140)
+                ("Latin_Capital_Letter_L_With_Stroke" . #\u+0141)
+                ("Latin_Small_Letter_L_With_Stroke" . #\u+0142)
+                ("Latin_Capital_Letter_N_With_Acute" . #\u+0143)
+                ("Latin_Small_Letter_N_With_Acute" . #\u+0144)
+                ("Latin_Capital_Letter_N_With_Cedilla" . #\u+0145)
+                ("Latin_Small_Letter_N_With_Cedilla" . #\u+0146)
+                ("Latin_Capital_Letter_N_With_Caron" . #\u+0147)
+                ("Latin_Small_Letter_N_With_Caron" . #\u+0148)
+                ("Latin_Small_Letter_N_Preceded_By_Apostrophe" . #\u+0149)
+                ("Latin_Capital_Letter_Eng" . #\u+014a)
+                ("Latin_Small_Letter_Eng" . #\u+014b)
+                ("Latin_Capital_Letter_O_With_Macron" . #\u+014c)
+                ("Latin_Small_Letter_O_With_Macron" . #\u+014d)
+                ("Latin_Capital_Letter_O_With_Breve" . #\u+014e)
+                ("Latin_Small_Letter_O_With_Breve" . #\u+014f)
+                ("Latin_Capital_Letter_O_With_Double_Acute" . #\u+0150)
+                ("Latin_Small_Letter_O_With_Double_Acute" . #\u+0151)
+                ("Latin_Capital_Ligature_Oe" . #\u+0152)
+                ("Latin_Small_Ligature_Oe" . #\u+0153)
+                ("Latin_Capital_Letter_R_With_Acute" . #\u+0154)
+                ("Latin_Small_Letter_R_With_Acute" . #\u+0155)
+                ("Latin_Capital_Letter_R_With_Cedilla" . #\u+0156)
+                ("Latin_Small_Letter_R_With_Cedilla" . #\u+0157)
+                ("Latin_Capital_Letter_R_With_Caron" . #\u+0158)
+                ("Latin_Small_Letter_R_With_Caron" . #\u+0159)
+                ("Latin_Capital_Letter_S_With_Acute" . #\u+015a)
+                ("Latin_Small_Letter_S_With_Acute" . #\u+015b)
+                ("Latin_Capital_Letter_S_With_Circumflex" . #\u+015c)
+                ("Latin_Small_Letter_S_With_Circumflex" . #\u+015d)
+                ("Latin_Capital_Letter_S_With_Cedilla" . #\u+015e)
+                ("Latin_Small_Letter_S_With_Cedilla" . #\u+015f)
+                ("Latin_Capital_Letter_S_With_Caron" . #\u+0160)
+                ("Latin_Small_Letter_S_With_Caron" . #\u+0161)
+                ("Latin_Capital_Letter_T_With_Cedilla" . #\u+0162)
+                ("Latin_Small_Letter_T_With_Cedilla" . #\u+0163)
+                ("Latin_Capital_Letter_T_With_Caron" . #\u+0164)
+                ("Latin_Small_Letter_T_With_Caron" . #\u+0165)
+                ("Latin_Capital_Letter_T_With_Stroke" . #\u+0166)
+                ("Latin_Small_Letter_T_With_Stroke" . #\u+0167)
+                ("Latin_Capital_Letter_U_With_Tilde" . #\u+0168)
+                ("Latin_Small_Letter_U_With_Tilde" . #\u+0169)
+                ("Latin_Capital_Letter_U_With_Macron" . #\u+016a)
+                ("Latin_Small_Letter_U_With_Macron" . #\u+016b)
+                ("Latin_Capital_Letter_U_With_Breve" . #\u+016c)
+                ("Latin_Small_Letter_U_With_Breve" . #\u+016d)
+                ("Latin_Capital_Letter_U_With_Ring_Above" . #\u+016e)
+                ("Latin_Small_Letter_U_With_Ring_Above" . #\u+016f)
+                ("Latin_Capital_Letter_U_With_Double_Acute" . #\u+0170)
+                ("Latin_Small_Letter_U_With_Double_Acute" . #\u+0171)
+                ("Latin_Capital_Letter_U_With_Ogonek" . #\u+0172)
+                ("Latin_Small_Letter_U_With_Ogonek" . #\u+0173)
+                ("Latin_Capital_Letter_W_With_Circumflex" . #\u+0174)
+                ("Latin_Small_Letter_W_With_Circumflex" . #\u+0175)
+                ("Latin_Capital_Letter_Y_With_Circumflex" . #\u+0176)
+                ("Latin_Small_Letter_Y_With_Circumflex" . #\u+0177)
+                ("Latin_Capital_Letter_Y_With_Diaeresis" . #\u+0178)
+                ("Latin_Capital_Letter_Z_With_Acute" . #\u+0179)
+                ("Latin_Small_Letter_Z_With_Acute" . #\u+017a)
+                ("Latin_Capital_Letter_Z_With_Dot_Above" . #\u+017b)
+                ("Latin_Small_Letter_Z_With_Dot_Above" . #\u+017c)
+                ("Latin_Capital_Letter_Z_With_Caron" . #\u+017d)
+                ("Latin_Small_Letter_Z_With_Caron" . #\u+017e)
+                ("Latin_Small_Letter_Long_S" . #\u+017f)
+                ("Latin_Small_Letter_B_With_Stroke" . #\u+0180)
+                ("Latin_Capital_Letter_B_With_Hook" . #\u+0181)
+                ("Latin_Capital_Letter_B_With_Topbar" . #\u+0182)
+                ("Latin_Small_Letter_B_With_Topbar" . #\u+0183)
+                ("Latin_Capital_Letter_Tone_Six" . #\u+0184)
+                ("Latin_Small_Letter_Tone_Six" . #\u+0185)
+                ("Latin_Capital_Letter_Open_O" . #\u+0186)
+                ("Latin_Capital_Letter_C_With_Hook" . #\u+0187)
+                ("Latin_Small_Letter_C_With_Hook" . #\u+0188)
+                ("Latin_Capital_Letter_African_D" . #\u+0189)
+                ("Latin_Capital_Letter_D_With_Hook" . #\u+018a)
+                ("Latin_Capital_Letter_D_With_Topbar" . #\u+018b)
+                ("Latin_Small_Letter_D_With_Topbar" . #\u+018c)
+                ("Latin_Small_Letter_Turned_Delta" . #\u+018d)
+                ("Latin_Capital_Letter_Reversed_E" . #\u+018e)
+                ("Latin_Capital_Letter_Schwa" . #\u+018f)
+                ("Latin_Capital_Letter_Open_E" . #\u+0190)
+                ("Latin_Capital_Letter_F_With_Hook" . #\u+0191)
+                ("Latin_Small_Letter_F_With_Hook" . #\u+0192)
+                ("Latin_Capital_Letter_G_With_Hook" . #\u+0193)
+                ("Latin_Capital_Letter_Gamma" . #\u+0194)
+                ("Latin_Small_Letter_Hv" . #\u+0195)
+                ("Latin_Capital_Letter_Iota" . #\u+0196)
+                ("Latin_Capital_Letter_I_With_Stroke" . #\u+0197)
+                ("Latin_Capital_Letter_K_With_Hook" . #\u+0198)
+                ("Latin_Small_Letter_K_With_Hook" . #\u+0199)
+                ("Latin_Small_Letter_L_With_Bar" . #\u+019a)
+                ("Latin_Small_Letter_Lambda_With_Stroke" . #\u+019b)
+                ("Latin_Capital_Letter_Turned_M" . #\u+019c)
+                ("Latin_Capital_Letter_N_With_Left_Hook" . #\u+019d)
+                ("Latin_Small_Letter_N_With_Long_Right_Leg" . #\u+019e)
+                ("Latin_Capital_Letter_O_With_Middle_Tilde" . #\u+019f)
+                ("Latin_Capital_Letter_O_With_Horn" . #\u+01a0)
+                ("Latin_Small_Letter_O_With_Horn" . #\u+01a1)
+                ("Latin_Capital_Letter_Oi" . #\u+01a2)
+                ("Latin_Small_Letter_Oi" . #\u+01a3)
+                ("Latin_Capital_Letter_P_With_Hook" . #\u+01a4)
+                ("Latin_Small_Letter_P_With_Hook" . #\u+01a5)
+                ("Latin_Letter_Yr" . #\u+01a6)
+                ("Latin_Capital_Letter_Tone_Two" . #\u+01a7)
+                ("Latin_Small_Letter_Tone_Two" . #\u+01a8)
+                ("Latin_Capital_Letter_Esh" . #\u+01a9)
+                ("Latin_Letter_Reversed_Esh_Loop" . #\u+01aa)
+                ("Latin_Small_Letter_T_With_Palatal_Hook" . #\u+01ab)
+                ("Latin_Capital_Letter_T_With_Hook" . #\u+01ac)
+                ("Latin_Small_Letter_T_With_Hook" . #\u+01ad)
+                ("Latin_Capital_Letter_T_With_Retroflex_Hook" . #\u+01ae)
+                ("Latin_Capital_Letter_U_With_Horn" . #\u+01af)
+                ("Latin_Small_Letter_U_With_Horn" . #\u+01b0)
+                ("Latin_Capital_Letter_Upsilon" . #\u+01b1)
+                ("Latin_Capital_Letter_V_With_Hook" . #\u+01b2)
+                ("Latin_Capital_Letter_Y_With_Hook" . #\u+01b3)
+                ("Latin_Small_Letter_Y_With_Hook" . #\u+01b4)
+                ("Latin_Capital_Letter_Z_With_Stroke" . #\u+01b5)
+                ("Latin_Small_Letter_Z_With_Stroke" . #\u+01b6)
+                ("Latin_Capital_Letter_Ezh" . #\u+01b7)
+                ("Latin_Capital_Letter_Ezh_Reversed" . #\u+01b8)
+                ("Latin_Small_Letter_Ezh_Reversed" . #\u+01b9)
+                ("Latin_Small_Letter_Ezh_With_Tail" . #\u+01ba)
+                ("Latin_Letter_Two_With_Stroke" . #\u+01bb)
+                ("Latin_Capital_Letter_Tone_Five" . #\u+01bc)
+                ("Latin_Small_Letter_Tone_Five" . #\u+01bd)
+                ("Latin_Letter_Inverted_Glottal_Stop_With_Stroke" . #\u+01be)
+                ("Latin_Letter_Wynn" . #\u+01bf)
+                ("Latin_Letter_Dental_Click" . #\u+01c0)
+                ("Latin_Letter_Lateral_Click" . #\u+01c1)
+                ("Latin_Letter_Alveolar_Click" . #\u+01c2)
+                ("Latin_Letter_Retroflex_Click" . #\u+01c3)
+                ("Latin_Capital_Letter_Dz_With_Caron" . #\u+01c4)
+                ("Latin_Capital_Letter_D_With_Small_Letter_Z_With_Caron" . #\u+01c5)
+                ("Latin_Small_Letter_Dz_With_Caron" . #\u+01c6)
+                ("Latin_Capital_Letter_Lj" . #\u+01c7)
+                ("Latin_Capital_Letter_L_With_Small_Letter_J" . #\u+01c8)
+                ("Latin_Small_Letter_Lj" . #\u+01c9)
+                ("Latin_Capital_Letter_Nj" . #\u+01ca)
+                ("Latin_Capital_Letter_N_With_Small_Letter_J" . #\u+01cb)
+                ("Latin_Small_Letter_Nj" . #\u+01cc)
+                ("Latin_Capital_Letter_A_With_Caron" . #\u+01cd)
+                ("Latin_Small_Letter_A_With_Caron" . #\u+01ce)
+                ("Latin_Capital_Letter_I_With_Caron" . #\u+01cf)
+                ("Latin_Small_Letter_I_With_Caron" . #\u+01d0)
+                ("Latin_Capital_Letter_O_With_Caron" . #\u+01d1)
+                ("Latin_Small_Letter_O_With_Caron" . #\u+01d2)
+                ("Latin_Capital_Letter_U_With_Caron" . #\u+01d3)
+                ("Latin_Small_Letter_U_With_Caron" . #\u+01d4)
+                ("Latin_Capital_Letter_U_With_Diaeresis_And_Macron" . #\u+01d5)
+                ("Latin_Small_Letter_U_With_Diaeresis_And_Macron" . #\u+01d6)
+                ("Latin_Capital_Letter_U_With_Diaeresis_And_Acute" . #\u+01d7)
+                ("Latin_Small_Letter_U_With_Diaeresis_And_Acute" . #\u+01d8)
+                ("Latin_Capital_Letter_U_With_Diaeresis_And_Caron" . #\u+01d9)
+                ("Latin_Small_Letter_U_With_Diaeresis_And_Caron" . #\u+01da)
+                ("Latin_Capital_Letter_U_With_Diaeresis_And_Grave" . #\u+01db)
+                ("Latin_Small_Letter_U_With_Diaeresis_And_Grave" . #\u+01dc)
+                ("Latin_Small_Letter_Turned_E" . #\u+01dd)
+                ("Latin_Capital_Letter_A_With_Diaeresis_And_Macron" . #\u+01de)
+                ("Latin_Small_Letter_A_With_Diaeresis_And_Macron" . #\u+01df)
+                ("Latin_Capital_Letter_A_With_Dot_Above_And_Macron" . #\u+01e0)
+                ("Latin_Small_Letter_A_With_Dot_Above_And_Macron" . #\u+01e1)
+                ("Latin_Capital_Letter_Ae_With_Macron" . #\u+01e2)
+                ("Latin_Small_Letter_Ae_With_Macron" . #\u+01e3)
+                ("Latin_Capital_Letter_G_With_Stroke" . #\u+01e4)
+                ("Latin_Small_Letter_G_With_Stroke" . #\u+01e5)
+                ("Latin_Capital_Letter_G_With_Caron" . #\u+01e6)
+                ("Latin_Small_Letter_G_With_Caron" . #\u+01e7)
+                ("Latin_Capital_Letter_K_With_Caron" . #\u+01e8)
+                ("Latin_Small_Letter_K_With_Caron" . #\u+01e9)
+                ("Latin_Capital_Letter_O_With_Ogonek" . #\u+01ea)
+                ("Latin_Small_Letter_O_With_Ogonek" . #\u+01eb)
+                ("Latin_Capital_Letter_O_With_Ogonek_And_Macron" . #\u+01ec)
+                ("Latin_Small_Letter_O_With_Ogonek_And_Macron" . #\u+01ed)
+                ("Latin_Capital_Letter_Ezh_With_Caron" . #\u+01ee)
+                ("Latin_Small_Letter_Ezh_With_Caron" . #\u+01ef)
+                ("Latin_Small_Letter_J_With_Caron" . #\u+01f0)
+                ("Latin_Capital_Letter_Dz" . #\u+01f1)
+                ("Latin_Capital_Letter_D_With_Small_Letter_Z" . #\u+01f2)
+                ("Latin_Small_Letter_Dz" . #\u+01f3)
+                ("Latin_Capital_Letter_G_With_Acute" . #\u+01f4)
+                ("Latin_Small_Letter_G_With_Acute" . #\u+01f5)
+                ("Latin_Capital_Letter_Hwair" . #\u+01f6)
+                ("Latin_Capital_Letter_Wynn" . #\u+01f7)
+                ("Latin_Capital_Letter_N_With_Grave" . #\u+01f8)
+                ("Latin_Small_Letter_N_With_Grave" . #\u+01f9)
+                ("Latin_Capital_Letter_A_With_Ring_Above_And_Acute" . #\u+01fa)
+                ("Latin_Small_Letter_A_With_Ring_Above_And_Acute" . #\u+01fb)
+                ("Latin_Capital_Letter_Ae_With_Acute" . #\u+01fc)
+                ("Latin_Small_Letter_Ae_With_Acute" . #\u+01fd)
+                ("Latin_Capital_Letter_O_With_Stroke_And_Acute" . #\u+01fe)
+                ("Latin_Small_Letter_O_With_Stroke_And_Acute" . #\u+01ff)
+                ("Latin_Capital_Letter_A_With_Double_Grave" . #\u+0200)
+                ("Latin_Small_Letter_A_With_Double_Grave" . #\u+0201)
+                ("Latin_Capital_Letter_A_With_Inverted_Breve" . #\u+0202)
+                ("Latin_Small_Letter_A_With_Inverted_Breve" . #\u+0203)
+                ("Latin_Capital_Letter_E_With_Double_Grave" . #\u+0204)
+                ("Latin_Small_Letter_E_With_Double_Grave" . #\u+0205)
+                ("Latin_Capital_Letter_E_With_Inverted_Breve" . #\u+0206)
+                ("Latin_Small_Letter_E_With_Inverted_Breve" . #\u+0207)
+                ("Latin_Capital_Letter_I_With_Double_Grave" . #\u+0208)
+                ("Latin_Small_Letter_I_With_Double_Grave" . #\u+0209)
+                ("Latin_Capital_Letter_I_With_Inverted_Breve" . #\u+020a)
+                ("Latin_Small_Letter_I_With_Inverted_Breve" . #\u+020b)
+                ("Latin_Capital_Letter_O_With_Double_Grave" . #\u+020c)
+                ("Latin_Small_Letter_O_With_Double_Grave" . #\u+020d)
+                ("Latin_Capital_Letter_O_With_Inverted_Breve" . #\u+020e)
+                ("Latin_Small_Letter_O_With_Inverted_Breve" . #\u+020f)
+                ("Latin_Capital_Letter_R_With_Double_Grave" . #\u+0210)
+                ("Latin_Small_Letter_R_With_Double_Grave" . #\u+0211)
+                ("Latin_Capital_Letter_R_With_Inverted_Breve" . #\u+0212)
+                ("Latin_Small_Letter_R_With_Inverted_Breve" . #\u+0213)
+                ("Latin_Capital_Letter_U_With_Double_Grave" . #\u+0214)
+                ("Latin_Small_Letter_U_With_Double_Grave" . #\u+0215)
+                ("Latin_Capital_Letter_U_With_Inverted_Breve" . #\u+0216)
+                ("Latin_Small_Letter_U_With_Inverted_Breve" . #\u+0217)
+                ("Latin_Capital_Letter_S_With_Comma_Below" . #\u+0218)
+                ("Latin_Small_Letter_S_With_Comma_Below" . #\u+0219)
+                ("Latin_Capital_Letter_T_With_Comma_Below" . #\u+021a)
+                ("Latin_Small_Letter_T_With_Comma_Below" . #\u+021b)
+                ("Latin_Capital_Letter_Yogh" . #\u+021c)
+                ("Latin_Small_Letter_Yogh" . #\u+021d)
+                ("Latin_Capital_Letter_H_With_Caron" . #\u+021e)
+                ("Latin_Small_Letter_H_With_Caron" . #\u+021f)
+                ("Latin_Capital_Letter_N_With_Long_Right_Leg" . #\u+0220)
+                ("Latin_Small_Letter_D_With_Curl" . #\u+0221)
+                ("Latin_Capital_Letter_Ou" . #\u+0222)
+                ("Latin_Small_Letter_Ou" . #\u+0223)
+                ("Latin_Capital_Letter_Z_With_Hook" . #\u+0224)
+                ("Latin_Small_Letter_Z_With_Hook" . #\u+0225)
+                ("Latin_Capital_Letter_A_With_Dot_Above" . #\u+0226)
+                ("Latin_Small_Letter_A_With_Dot_Above" . #\u+0227)
+                ("Latin_Capital_Letter_E_With_Cedilla" . #\u+0228)
+                ("Latin_Small_Letter_E_With_Cedilla" . #\u+0229)
+                ("Latin_Capital_Letter_O_With_Diaeresis_And_Macron" . #\u+022a)
+                ("Latin_Small_Letter_O_With_Diaeresis_And_Macron" . #\u+022b)
+                ("Latin_Capital_Letter_O_With_Tilde_And_Macron" . #\u+022c)
+                ("Latin_Small_Letter_O_With_Tilde_And_Macron" . #\u+022d)
+                ("Latin_Capital_Letter_O_With_Dot_Above" . #\u+022e)
+                ("Latin_Small_Letter_O_With_Dot_Above" . #\u+022f)
+                ("Latin_Capital_Letter_O_With_Dot_Above_And_Macron" . #\u+0230)
+                ("Latin_Small_Letter_O_With_Dot_Above_And_Macron" . #\u+0231)
+                ("Latin_Capital_Letter_Y_With_Macron" . #\u+0232)
+                ("Latin_Small_Letter_Y_With_Macron" . #\u+0233)
+                ("Latin_Small_Letter_L_With_Curl" . #\u+0234)
+                ("Latin_Small_Letter_N_With_Curl" . #\u+0235)
+                ("Latin_Small_Letter_T_With_Curl" . #\u+0236)
+                ("Latin_Small_Letter_Dotless_J" . #\u+0237)
+                ("Latin_Small_Letter_Db_Digraph" . #\u+0238)
+                ("Latin_Small_Letter_Qp_Digraph" . #\u+0239)
+                ("Latin_Capital_Letter_A_With_Stroke" . #\u+023a)
+                ("Latin_Capital_Letter_C_With_Stroke" . #\u+023b)
+                ("Latin_Small_Letter_C_With_Stroke" . #\u+023c)
+                ("Latin_Capital_Letter_L_With_Bar" . #\u+023d)
+                ("Latin_Capital_Letter_T_With_Diagonal_Stroke" . #\u+023e)
+                ("Latin_Small_Letter_S_With_Swash_Tail" . #\u+023f)
+                ("Latin_Small_Letter_Z_With_Swash_Tail" . #\u+0240)
+                ("Latin_Capital_Letter_Glottal_Stop" . #\u+0241)
+                ("Latin_Small_Letter_Glottal_Stop" . #\u+0242)
+                ("Latin_Capital_Letter_B_With_Stroke" . #\u+0243)
+                ("Latin_Capital_Letter_U_Bar" . #\u+0244)
+                ("Latin_Capital_Letter_Turned_V" . #\u+0245)
+                ("Latin_Capital_Letter_E_With_Stroke" . #\u+0246)
+                ("Latin_Small_Letter_E_With_Stroke" . #\u+0247)
+                ("Latin_Capital_Letter_J_With_Stroke" . #\u+0248)
+                ("Latin_Small_Letter_J_With_Stroke" . #\u+0249)
+                ("Latin_Capital_Letter_Small_Q_With_Hook_Tail" . #\u+024a)
+                ("Latin_Small_Letter_Q_With_Hook_Tail" . #\u+024b)
+                ("Latin_Capital_Letter_R_With_Stroke" . #\u+024c)
+                ("Latin_Small_Letter_R_With_Stroke" . #\u+024d)
+                ("Latin_Capital_Letter_Y_With_Stroke" . #\u+024e)
+                ("Latin_Small_Letter_Y_With_Stroke" . #\u+024f)
+                ("Latin_Small_Letter_Turned_A" . #\u+0250)
+                ("Latin_Small_Letter_Alpha" . #\u+0251)
+                ("Latin_Small_Letter_Turned_Alpha" . #\u+0252)
+                ("Latin_Small_Letter_B_With_Hook" . #\u+0253)
+                ("Latin_Small_Letter_Open_O" . #\u+0254)
+                ("Latin_Small_Letter_C_With_Curl" . #\u+0255)
+                ("Latin_Small_Letter_D_With_Tail" . #\u+0256)
+                ("Latin_Small_Letter_D_With_Hook" . #\u+0257)
+                ("Latin_Small_Letter_Reversed_E" . #\u+0258)
+                ("Latin_Small_Letter_Schwa" . #\u+0259)
+                ("Latin_Small_Letter_Schwa_With_Hook" . #\u+025a)
+                ("Latin_Small_Letter_Open_E" . #\u+025b)
+                ("Latin_Small_Letter_Reversed_Open_E" . #\u+025c)
+                ("Latin_Small_Letter_Reversed_Open_E_With_Hook" . #\u+025d)
+                ("Latin_Small_Letter_Closed_Reversed_Open_E" . #\u+025e)
+                ("Latin_Small_Letter_Dotless_J_With_Stroke" . #\u+025f)
+                ("Latin_Small_Letter_G_With_Hook" . #\u+0260)
+                ("Latin_Small_Letter_Script_G" . #\u+0261)
+                ("Latin_Letter_Small_Capital_G" . #\u+0262)
+                ("Latin_Small_Letter_Gamma" . #\u+0263)
+                ("Latin_Small_Letter_Rams_Horn" . #\u+0264)
+                ("Latin_Small_Letter_Turned_H" . #\u+0265)
+                ("Latin_Small_Letter_H_With_Hook" . #\u+0266)
+                ("Latin_Small_Letter_Heng_With_Hook" . #\u+0267)
+                ("Latin_Small_Letter_I_With_Stroke" . #\u+0268)
+                ("Latin_Small_Letter_Iota" . #\u+0269)
+                ("Latin_Letter_Small_Capital_I" . #\u+026a)
+                ("Latin_Small_Letter_L_With_Middle_Tilde" . #\u+026b)
+                ("Latin_Small_Letter_L_With_Belt" . #\u+026c)
+                ("Latin_Small_Letter_L_With_Retroflex_Hook" . #\u+026d)
+                ("Latin_Small_Letter_Lezh" . #\u+026e)
+                ("Latin_Small_Letter_Turned_M" . #\u+026f)
+                ("Latin_Small_Letter_Turned_M_With_Long_Leg" . #\u+0270)
+                ("Latin_Small_Letter_M_With_Hook" . #\u+0271)
+                ("Latin_Small_Letter_N_With_Left_Hook" . #\u+0272)
+                ("Latin_Small_Letter_N_With_Retroflex_Hook" . #\u+0273)
+                ("Latin_Letter_Small_Capital_N" . #\u+0274)
+                ("Latin_Small_Letter_Barred_O" . #\u+0275)
+                ("Latin_Letter_Small_Capital_Oe" . #\u+0276)
+                ("Latin_Small_Letter_Closed_Omega" . #\u+0277)
+                ("Latin_Small_Letter_Phi" . #\u+0278)
+                ("Latin_Small_Letter_Turned_R" . #\u+0279)
+                ("Latin_Small_Letter_Turned_R_With_Long_Leg" . #\u+027a)
+                ("Latin_Small_Letter_Turned_R_With_Hook" . #\u+027b)
+                ("Latin_Small_Letter_R_With_Long_Leg" . #\u+027c)
+                ("Latin_Small_Letter_R_With_Tail" . #\u+027d)
+                ("Latin_Small_Letter_R_With_Fishhook" . #\u+027e)
+                ("Latin_Small_Letter_Reversed_R_With_Fishhook" . #\u+027f)
+                ("Latin_Letter_Small_Capital_R" . #\u+0280)
+                ("Latin_Letter_Small_Capital_Inverted_R" . #\u+0281)
+                ("Latin_Small_Letter_S_With_Hook" . #\u+0282)
+                ("Latin_Small_Letter_Esh" . #\u+0283)
+                ("Latin_Small_Letter_Dotless_J_With_Stroke_And_Hook" . #\u+0284)
+                ("Latin_Small_Letter_Squat_Reversed_Esh" . #\u+0285)
+                ("Latin_Small_Letter_Esh_With_Curl" . #\u+0286)
+                ("Latin_Small_Letter_Turned_T" . #\u+0287)
+                ("Latin_Small_Letter_T_With_Retroflex_Hook" . #\u+0288)
+                ("Latin_Small_Letter_U_Bar" . #\u+0289)
+                ("Latin_Small_Letter_Upsilon" . #\u+028a)
+                ("Latin_Small_Letter_V_With_Hook" . #\u+028b)
+                ("Latin_Small_Letter_Turned_V" . #\u+028c)
+                ("Latin_Small_Letter_Turned_W" . #\u+028d)
+                ("Latin_Small_Letter_Turned_Y" . #\u+028e)
+                ("Latin_Letter_Small_Capital_Y" . #\u+028f)
+                ("Latin_Small_Letter_Z_With_Retroflex_Hook" . #\u+0290)
+                ("Latin_Small_Letter_Z_With_Curl" . #\u+0291)
+                ("Latin_Small_Letter_Ezh" . #\u+0292)
+                ("Latin_Small_Letter_Ezh_With_Curl" . #\u+0293)
+                ("Latin_Letter_Glottal_Stop" . #\u+0294)
+                ("Latin_Letter_Pharyngeal_Voiced_Fricative" . #\u+0295)
+                ("Latin_Letter_Inverted_Glottal_Stop" . #\u+0296)
+                ("Latin_Letter_Stretched_C" . #\u+0297)
+                ("Latin_Letter_Bilabial_Click" . #\u+0298)
+                ("Latin_Letter_Small_Capital_B" . #\u+0299)
+                ("Latin_Small_Letter_Closed_Open_E" . #\u+029a)
+                ("Latin_Letter_Small_Capital_G_With_Hook" . #\u+029b)
+                ("Latin_Letter_Small_Capital_H" . #\u+029c)
+                ("Latin_Small_Letter_J_With_Crossed-Tail" . #\u+029d)
+                ("Latin_Small_Letter_Turned_K" . #\u+029e)
+                ("Latin_Letter_Small_Capital_L" . #\u+029f)
+                ("Latin_Small_Letter_Q_With_Hook" . #\u+02a0)
+                ("Latin_Letter_Glottal_Stop_With_Stroke" . #\u+02a1)
+                ("Latin_Letter_Reversed_Glottal_Stop_With_Stroke" . #\u+02a2)
+                ("Latin_Small_Letter_Dz_Digraph" . #\u+02a3)
+                ("Latin_Small_Letter_Dezh_Digraph" . #\u+02a4)
+                ("Latin_Small_Letter_Dz_Digraph_With_Curl" . #\u+02a5)
+                ("Latin_Small_Letter_Ts_Digraph" . #\u+02a6)
+                ("Latin_Small_Letter_Tesh_Digraph" . #\u+02a7)
+                ("Latin_Small_Letter_Tc_Digraph_With_Curl" . #\u+02a8)
+                ("Latin_Small_Letter_Feng_Digraph" . #\u+02a9)
+                ("Latin_Small_Letter_Ls_Digraph" . #\u+02aa)
+                ("Latin_Small_Letter_Lz_Digraph" . #\u+02ab)
+                ("Latin_Letter_Bilabial_Percussive" . #\u+02ac)
+                ("Latin_Letter_Bidental_Percussive" . #\u+02ad)
+                ("Latin_Small_Letter_Turned_H_With_Fishhook" . #\u+02ae)
+                ("Latin_Small_Letter_Turned_H_With_Fishhook_And_Tail" . #\u+02af)
+                ("Modifier_Letter_Small_H" . #\u+02b0)
+                ("Modifier_Letter_Small_H_With_Hook" . #\u+02b1)
+                ("Modifier_Letter_Small_J" . #\u+02b2)
+                ("Modifier_Letter_Small_R" . #\u+02b3)
+                ("Modifier_Letter_Small_Turned_R" . #\u+02b4)
+                ("Modifier_Letter_Small_Turned_R_With_Hook" . #\u+02b5)
+                ("Modifier_Letter_Small_Capital_Inverted_R" . #\u+02b6)
+                ("Modifier_Letter_Small_W" . #\u+02b7)
+                ("Modifier_Letter_Small_Y" . #\u+02b8)
+                ("Modifier_Letter_Prime" . #\u+02b9)
+                ("Modifier_Letter_Double_Prime" . #\u+02ba)
+                ("Modifier_Letter_Turned_Comma" . #\u+02bb)
+                ("Modifier_Letter_Apostrophe" . #\u+02bc)
+                ("Modifier_Letter_Reversed_Comma" . #\u+02bd)
+                ("Modifier_Letter_Right_Half_Ring" . #\u+02be)
+                ("Modifier_Letter_Left_Half_Ring" . #\u+02bf)
+                ("Modifier_Letter_Glottal_Stop" . #\u+02c0)
+                ("Modifier_Letter_Reversed_Glottal_Stop" . #\u+02c1)
+                ("Modifier_Letter_Left_Arrowhead" . #\u+02c2)
+                ("Modifier_Letter_Right_Arrowhead" . #\u+02c3)
+                ("Modifier_Letter_Up_Arrowhead" . #\u+02c4)
+                ("Modifier_Letter_Down_Arrowhead" . #\u+02c5)
+                ("Modifier_Letter_Circumflex_Accent" . #\u+02c6)
+                ("Caron" . #\u+02c7)
+                ("Modifier_Letter_Vertical_Line" . #\u+02c8)
+                ("Modifier_Letter_Macron" . #\u+02c9)
+                ("Modifier_Letter_Acute_Accent" . #\u+02ca)
+                ("Modifier_Letter_Grave_Accent" . #\u+02cb)
+                ("Modifier_Letter_Low_Vertical_Line" . #\u+02cc)
+                ("Modifier_Letter_Low_Macron" . #\u+02cd)
+                ("Modifier_Letter_Low_Grave_Accent" . #\u+02ce)
+                ("Modifier_Letter_Low_Acute_Accent" . #\u+02cf)
+                ("Modifier_Letter_Triangular_Colon" . #\u+02d0)
+                ("Modifier_Letter_Half_Triangular_Colon" . #\u+02d1)
+                ("Modifier_Letter_Centred_Right_Half_Ring" . #\u+02d2)
+                ("Modifier_Letter_Centred_Left_Half_Ring" . #\u+02d3)
+                ("Modifier_Letter_Up_Tack" . #\u+02d4)
+                ("Modifier_Letter_Down_Tack" . #\u+02d5)
+                ("Modifier_Letter_Plus_Sign" . #\u+02d6)
+                ("Modifier_Letter_Minus_Sign" . #\u+02d7)
+                ("Breve" . #\u+02d8)
+                ("Dot_Above" . #\u+02d9)
+                ("Ring_Above" . #\u+02da)
+                ("Ogonek" . #\u+02db)
+                ("Small_Tilde" . #\u+02dc)
+                ("Double_Acute_Accent" . #\u+02dd)
+                ("Modifier_Letter_Rhotic_Hook" . #\u+02de)
+                ("Modifier_Letter_Cross_Accent" . #\u+02df)
+                ("Modifier_Letter_Small_Gamma" . #\u+02e0)
+                ("Modifier_Letter_Small_L" . #\u+02e1)
+                ("Modifier_Letter_Small_S" . #\u+02e2)
+                ("Modifier_Letter_Small_X" . #\u+02e3)
+                ("Modifier_Letter_Small_Reversed_Glottal_Stop" . #\u+02e4)
+                ("Modifier_Letter_Extra-High_Tone_Bar" . #\u+02e5)
+                ("Modifier_Letter_High_Tone_Bar" . #\u+02e6)
+                ("Modifier_Letter_Mid_Tone_Bar" . #\u+02e7)
+                ("Modifier_Letter_Low_Tone_Bar" . #\u+02e8)
+                ("Modifier_Letter_Extra-Low_Tone_Bar" . #\u+02e9)
+                ("Modifier_Letter_Yin_Departing_Tone_Mark" . #\u+02ea)
+                ("Modifier_Letter_Yang_Departing_Tone_Mark" . #\u+02eb)
+                ("Modifier_Letter_Voicing" . #\u+02ec)
+                ("Modifier_Letter_Unaspirated" . #\u+02ed)
+                ("Modifier_Letter_Double_Apostrophe" . #\u+02ee)
+                ("Modifier_Letter_Low_Down_Arrowhead" . #\u+02ef)
+                ("Modifier_Letter_Low_Up_Arrowhead" . #\u+02f0)
+                ("Modifier_Letter_Low_Left_Arrowhead" . #\u+02f1)
+                ("Modifier_Letter_Low_Right_Arrowhead" . #\u+02f2)
+                ("Modifier_Letter_Low_Ring" . #\u+02f3)
+                ("Modifier_Letter_Middle_Grave_Accent" . #\u+02f4)
+                ("Modifier_Letter_Middle_Double_Grave_Accent" . #\u+02f5)
+                ("Modifier_Letter_Middle_Double_Acute_Accent" . #\u+02f6)
+                ("Modifier_Letter_Low_Tilde" . #\u+02f7)
+                ("Modifier_Letter_Raised_Colon" . #\u+02f8)
+                ("Modifier_Letter_Begin_High_Tone" . #\u+02f9)
+                ("Modifier_Letter_End_High_Tone" . #\u+02fa)
+                ("Modifier_Letter_Begin_Low_Tone" . #\u+02fb)
+                ("Modifier_Letter_End_Low_Tone" . #\u+02fc)
+                ("Modifier_Letter_Shelf" . #\u+02fd)
+                ("Modifier_Letter_Open_Shelf" . #\u+02fe)
+                ("Modifier_Letter_Low_Left_Arrow" . #\u+02ff)
+                ("Combining_Grave_Accent" . #\u+0300)
+                ("Combining_Acute_Accent" . #\u+0301)
+                ("Combining_Circumflex_Accent" . #\u+0302)
+                ("Combining_Tilde" . #\u+0303)
+                ("Combining_Macron" . #\u+0304)
+                ("Combining_Overline" . #\u+0305)
+                ("Combining_Breve" . #\u+0306)
+                ("Combining_Dot_Above" . #\u+0307)
+                ("Combining_Diaeresis" . #\u+0308)
+                ("Combining_Hook_Above" . #\u+0309)
+                ("Combining_Ring_Above" . #\u+030a)
+                ("Combining_Double_Acute_Accent" . #\u+030b)
+                ("Combining_Caron" . #\u+030c)
+                ("Combining_Vertical_Line_Above" . #\u+030d)
+                ("Combining_Double_Vertical_Line_Above" . #\u+030e)
+                ("Combining_Double_Grave_Accent" . #\u+030f)
+                ("Combining_Candrabindu" . #\u+0310)
+                ("Combining_Inverted_Breve" . #\u+0311)
+                ("Combining_Turned_Comma_Above" . #\u+0312)
+                ("Combining_Comma_Above" . #\u+0313)
+                ("Combining_Reversed_Comma_Above" . #\u+0314)
+                ("Combining_Comma_Above_Right" . #\u+0315)
+                ("Combining_Grave_Accent_Below" . #\u+0316)
+                ("Combining_Acute_Accent_Below" . #\u+0317)
+                ("Combining_Left_Tack_Below" . #\u+0318)
+                ("Combining_Right_Tack_Below" . #\u+0319)
+                ("Combining_Left_Angle_Above" . #\u+031a)
+                ("Combining_Horn" . #\u+031b)
+                ("Combining_Left_Half_Ring_Below" . #\u+031c)
+                ("Combining_Up_Tack_Below" . #\u+031d)
+                ("Combining_Down_Tack_Below" . #\u+031e)
+                ("Combining_Plus_Sign_Below" . #\u+031f)
+                ("Combining_Minus_Sign_Below" . #\u+0320)
+                ("Combining_Palatalized_Hook_Below" . #\u+0321)
+                ("Combining_Retroflex_Hook_Below" . #\u+0322)
+                ("Combining_Dot_Below" . #\u+0323)
+                ("Combining_Diaeresis_Below" . #\u+0324)
+                ("Combining_Ring_Below" . #\u+0325)
+                ("Combining_Comma_Below" . #\u+0326)
+                ("Combining_Cedilla" . #\u+0327)
+                ("Combining_Ogonek" . #\u+0328)
+                ("Combining_Vertical_Line_Below" . #\u+0329)
+                ("Combining_Bridge_Below" . #\u+032a)
+                ("Combining_Inverted_Double_Arch_Below" . #\u+032b)
+                ("Combining_Caron_Below" . #\u+032c)
+                ("Combining_Circumflex_Accent_Below" . #\u+032d)
+                ("Combining_Breve_Below" . #\u+032e)
+                ("Combining_Inverted_Breve_Below" . #\u+032f)
+                ("Combining_Tilde_Below" . #\u+0330)
+                ("Combining_Macron_Below" . #\u+0331)
+                ("Combining_Low_Line" . #\u+0332)
+                ("Combining_Double_Low_Line" . #\u+0333)
+                ("Combining_Tilde_Overlay" . #\u+0334)
+                ("Combining_Short_Stroke_Overlay" . #\u+0335)
+                ("Combining_Long_Stroke_Overlay" . #\u+0336)
+                ("Combining_Short_Solidus_Overlay" . #\u+0337)
+                ("Combining_Long_Solidus_Overlay" . #\u+0338)
+                ("Combining_Right_Half_Ring_Below" . #\u+0339)
+                ("Combining_Inverted_Bridge_Below" . #\u+033a)
+                ("Combining_Square_Below" . #\u+033b)
+                ("Combining_Seagull_Below" . #\u+033c)
+                ("Combining_X_Above" . #\u+033d)
+                ("Combining_Vertical_Tilde" . #\u+033e)
+                ("Combining_Double_Overline" . #\u+033f)
+                ("Combining_Grave_Tone_Mark" . #\u+0340)
+                ("Combining_Acute_Tone_Mark" . #\u+0341)
+                ("Combining_Greek_Perispomeni" . #\u+0342)
+                ("Combining_Greek_Koronis" . #\u+0343)
+                ("Combining_Greek_Dialytika_Tonos" . #\u+0344)
+                ("Combining_Greek_Ypogegrammeni" . #\u+0345)
+                ("Combining_Bridge_Above" . #\u+0346)
+                ("Combining_Equals_Sign_Below" . #\u+0347)
+                ("Combining_Double_Vertical_Line_Below" . #\u+0348)
+                ("Combining_Left_Angle_Below" . #\u+0349)
+                ("Combining_Not_Tilde_Above" . #\u+034a)
+                ("Combining_Homothetic_Above" . #\u+034b)
+                ("Combining_Almost_Equal_To_Above" . #\u+034c)
+                ("Combining_Left_Right_Arrow_Below" . #\u+034d)
+                ("Combining_Upwards_Arrow_Below" . #\u+034e)
+                ("Combining_Grapheme_Joiner" . #\u+034f)
+                ("Combining_Right_Arrowhead_Above" . #\u+0350)
+                ("Combining_Left_Half_Ring_Above" . #\u+0351)
+                ("Combining_Fermata" . #\u+0352)
+                ("Combining_X_Below" . #\u+0353)
+                ("Combining_Left_Arrowhead_Below" . #\u+0354)
+                ("Combining_Right_Arrowhead_Below" . #\u+0355)
+                ("Combining_Right_Arrowhead_And_Up_Arrowhead_Below" . #\u+0356)
+                ("Combining_Right_Half_Ring_Above" . #\u+0357)
+                ("Combining_Dot_Above_Right" . #\u+0358)
+                ("Combining_Asterisk_Below" . #\u+0359)
+                ("Combining_Double_Ring_Below" . #\u+035a)
+                ("Combining_Zigzag_Above" . #\u+035b)
+                ("Combining_Double_Breve_Below" . #\u+035c)
+                ("Combining_Double_Breve" . #\u+035d)
+                ("Combining_Double_Macron" . #\u+035e)
+                ("Combining_Double_Macron_Below" . #\u+035f)
+                ("Combining_Double_Tilde" . #\u+0360)
+                ("Combining_Double_Inverted_Breve" . #\u+0361)
+                ("Combining_Double_Rightwards_Arrow_Below" . #\u+0362)
+                ("Combining_Latin_Small_Letter_A" . #\u+0363)
+                ("Combining_Latin_Small_Letter_E" . #\u+0364)
+                ("Combining_Latin_Small_Letter_I" . #\u+0365)
+                ("Combining_Latin_Small_Letter_O" . #\u+0366)
+                ("Combining_Latin_Small_Letter_U" . #\u+0367)
+                ("Combining_Latin_Small_Letter_C" . #\u+0368)
+                ("Combining_Latin_Small_Letter_D" . #\u+0369)
+                ("Combining_Latin_Small_Letter_H" . #\u+036a)
+                ("Combining_Latin_Small_Letter_M" . #\u+036b)
+                ("Combining_Latin_Small_Letter_R" . #\u+036c)
+                ("Combining_Latin_Small_Letter_T" . #\u+036d)
+                ("Combining_Latin_Small_Letter_V" . #\u+036e)
+                ("Combining_Latin_Small_Letter_X" . #\u+036f)
+                ("Greek_Numeral_Sign" . #\u+0374)
+                ("Greek_Lower_Numeral_Sign" . #\u+0375)
+                ("Greek_Ypogegrammeni" . #\u+037a)
+                ("Greek_Small_Reversed_Lunate_Sigma_Symbol" . #\u+037b)
+                ("Greek_Small_Dotted_Lunate_Sigma_Symbol" . #\u+037c)
+                ("Greek_Small_Reversed_Dotted_Lunate_Sigma_Symbol" . #\u+037d)
+                ("Greek_Question_Mark" . #\u+037e)
+                ("Greek_Tonos" . #\u+0384)
+                ("Greek_Dialytika_Tonos" . #\u+0385)
+                ("Greek_Capital_Letter_Alpha_With_Tonos" . #\u+0386)
+                ("Greek_Ano_Teleia" . #\u+0387)
+                ("Greek_Capital_Letter_Epsilon_With_Tonos" . #\u+0388)
+                ("Greek_Capital_Letter_Eta_With_Tonos" . #\u+0389)
+                ("Greek_Capital_Letter_Iota_With_Tonos" . #\u+038a)
+                ("Greek_Capital_Letter_Omicron_With_Tonos" . #\u+038c)
+                ("Greek_Capital_Letter_Upsilon_With_Tonos" . #\u+038e)
+                ("Greek_Capital_Letter_Omega_With_Tonos" . #\u+038f)
+                ("Greek_Small_Letter_Iota_With_Dialytika_And_Tonos" . #\u+0390)
+                ("Greek_Capital_Letter_Alpha" . #\u+0391)
+                ("Greek_Capital_Letter_Beta" . #\u+0392)
+                ("Greek_Capital_Letter_Gamma" . #\u+0393)
+                ("Greek_Capital_Letter_Delta" . #\u+0394)
+                ("Greek_Capital_Letter_Epsilon" . #\u+0395)
+                ("Greek_Capital_Letter_Zeta" . #\u+0396)
+                ("Greek_Capital_Letter_Eta" . #\u+0397)
+                ("Greek_Capital_Letter_Theta" . #\u+0398)
+                ("Greek_Capital_Letter_Iota" . #\u+0399)
+                ("Greek_Capital_Letter_Kappa" . #\u+039a)
+                ("Greek_Capital_Letter_Lamda" . #\u+039b)
+                ("Greek_Capital_Letter_Mu" . #\u+039c)
+                ("Greek_Capital_Letter_Nu" . #\u+039d)
+                ("Greek_Capital_Letter_Xi" . #\u+039e)
+                ("Greek_Capital_Letter_Omicron" . #\u+039f)
+                ("Greek_Capital_Letter_Pi" . #\u+03a0)
+                ("Greek_Capital_Letter_Rho" . #\u+03a1)
+                ("Greek_Capital_Letter_Sigma" . #\u+03a3)
+                ("Greek_Capital_Letter_Tau" . #\u+03a4)
+                ("Greek_Capital_Letter_Upsilon" . #\u+03a5)
+                ("Greek_Capital_Letter_Phi" . #\u+03a6)
+                ("Greek_Capital_Letter_Chi" . #\u+03a7)
+                ("Greek_Capital_Letter_Psi" . #\u+03a8)
+                ("Greek_Capital_Letter_Omega" . #\u+03a9)
+                ("Greek_Capital_Letter_Iota_With_Dialytika" . #\u+03aa)
+                ("Greek_Capital_Letter_Upsilon_With_Dialytika" . #\u+03ab)
+                ("Greek_Small_Letter_Alpha_With_Tonos" . #\u+03ac)
+                ("Greek_Small_Letter_Epsilon_With_Tonos" . #\u+03ad)
+                ("Greek_Small_Letter_Eta_With_Tonos" . #\u+03ae)
+                ("Greek_Small_Letter_Iota_With_Tonos" . #\u+03af)
+                ("Greek_Small_Letter_Upsilon_With_Dialytika_And_Tonos" . #\u+03b0)
+                ("Greek_Small_Letter_Alpha" . #\u+03b1)
+                ("Greek_Small_Letter_Beta" . #\u+03b2)
+                ("Greek_Small_Letter_Gamma" . #\u+03b3)
+                ("Greek_Small_Letter_Delta" . #\u+03b4)
+                ("Greek_Small_Letter_Epsilon" . #\u+03b5)
+                ("Greek_Small_Letter_Zeta" . #\u+03b6)
+                ("Greek_Small_Letter_Eta" . #\u+03b7)
+                ("Greek_Small_Letter_Theta" . #\u+03b8)
+                ("Greek_Small_Letter_Iota" . #\u+03b9)
+                ("Greek_Small_Letter_Kappa" . #\u+03ba)
+                ("Greek_Small_Letter_Lamda" . #\u+03bb)
+                ("Greek_Small_Letter_Mu" . #\u+03bc)
+                ("Greek_Small_Letter_Nu" . #\u+03bd)
+                ("Greek_Small_Letter_Xi" . #\u+03be)
+                ("Greek_Small_Letter_Omicron" . #\u+03bf)
+                ("Greek_Small_Letter_Pi" . #\u+03c0)
+                ("Greek_Small_Letter_Rho" . #\u+03c1)
+                ("Greek_Small_Letter_Final_Sigma" . #\u+03c2)
+                ("Greek_Small_Letter_Sigma" . #\u+03c3)
+                ("Greek_Small_Letter_Tau" . #\u+03c4)
+                ("Greek_Small_Letter_Upsilon" . #\u+03c5)
+                ("Greek_Small_Letter_Phi" . #\u+03c6)
+                ("Greek_Small_Letter_Chi" . #\u+03c7)
+                ("Greek_Small_Letter_Psi" . #\u+03c8)
+                ("Greek_Small_Letter_Omega" . #\u+03c9)
+                ("Greek_Small_Letter_Iota_With_Dialytika" . #\u+03ca)
+                ("Greek_Small_Letter_Upsilon_With_Dialytika" . #\u+03cb)
+                ("Greek_Small_Letter_Omicron_With_Tonos" . #\u+03cc)
+                ("Greek_Small_Letter_Upsilon_With_Tonos" . #\u+03cd)
+                ("Greek_Small_Letter_Omega_With_Tonos" . #\u+03ce)
+                ("Greek_Beta_Symbol" . #\u+03d0)
+                ("Greek_Theta_Symbol" . #\u+03d1)
+                ("Greek_Upsilon_With_Hook_Symbol" . #\u+03d2)
+                ("Greek_Upsilon_With_Acute_And_Hook_Symbol" . #\u+03d3)
+                ("Greek_Upsilon_With_Diaeresis_And_Hook_Symbol" . #\u+03d4)
+                ("Greek_Phi_Symbol" . #\u+03d5)
+                ("Greek_Pi_Symbol" . #\u+03d6)
+                ("Greek_Kai_Symbol" . #\u+03d7)
+                ("Greek_Letter_Archaic_Koppa" . #\u+03d8)
+                ("Greek_Small_Letter_Archaic_Koppa" . #\u+03d9)
+                ("Greek_Letter_Stigma" . #\u+03da)
+                ("Greek_Small_Letter_Stigma" . #\u+03db)
+                ("Greek_Letter_Digamma" . #\u+03dc)
+                ("Greek_Small_Letter_Digamma" . #\u+03dd)
+                ("Greek_Letter_Koppa" . #\u+03de)
+                ("Greek_Small_Letter_Koppa" . #\u+03df)
+                ("Greek_Letter_Sampi" . #\u+03e0)
+                ("Greek_Small_Letter_Sampi" . #\u+03e1)
+                ("Coptic_Capital_Letter_Shei" . #\u+03e2)
+                ("Coptic_Small_Letter_Shei" . #\u+03e3)
+                ("Coptic_Capital_Letter_Fei" . #\u+03e4)
+                ("Coptic_Small_Letter_Fei" . #\u+03e5)
+                ("Coptic_Capital_Letter_Khei" . #\u+03e6)
+                ("Coptic_Small_Letter_Khei" . #\u+03e7)
+                ("Coptic_Capital_Letter_Hori" . #\u+03e8)
+                ("Coptic_Small_Letter_Hori" . #\u+03e9)
+                ("Coptic_Capital_Letter_Gangia" . #\u+03ea)
+                ("Coptic_Small_Letter_Gangia" . #\u+03eb)
+                ("Coptic_Capital_Letter_Shima" . #\u+03ec)
+                ("Coptic_Small_Letter_Shima" . #\u+03ed)
+                ("Coptic_Capital_Letter_Dei" . #\u+03ee)
+                ("Coptic_Small_Letter_Dei" . #\u+03ef)
+                ("Greek_Kappa_Symbol" . #\u+03f0)
+                ("Greek_Rho_Symbol" . #\u+03f1)
+                ("Greek_Lunate_Sigma_Symbol" . #\u+03f2)
+                ("Greek_Letter_Yot" . #\u+03f3)
+                ("Greek_Capital_Theta_Symbol" . #\u+03f4)
+                ("Greek_Lunate_Epsilon_Symbol" . #\u+03f5)
+                ("Greek_Reversed_Lunate_Epsilon_Symbol" . #\u+03f6)
+                ("Greek_Capital_Letter_Sho" . #\u+03f7)
+                ("Greek_Small_Letter_Sho" . #\u+03f8)
+                ("Greek_Capital_Lunate_Sigma_Symbol" . #\u+03f9)
+                ("Greek_Capital_Letter_San" . #\u+03fa)
+                ("Greek_Small_Letter_San" . #\u+03fb)
+                ("Greek_Rho_With_Stroke_Symbol" . #\u+03fc)
+                ("Greek_Capital_Reversed_Lunate_Sigma_Symbol" . #\u+03fd)
+                ("Greek_Capital_Dotted_Lunate_Sigma_Symbol" . #\u+03fe)
+                ("Greek_Capital_Reversed_Dotted_Lunate_Sigma_Symbol" . #\u+03ff)
+                ("Cyrillic_Capital_Letter_Ie_With_Grave" . #\u+0400)
+                ("Cyrillic_Capital_Letter_Io" . #\u+0401)
+                ("Cyrillic_Capital_Letter_Dje" . #\u+0402)
+                ("Cyrillic_Capital_Letter_Gje" . #\u+0403)
+                ("Cyrillic_Capital_Letter_Ukrainian_Ie" . #\u+0404)
+                ("Cyrillic_Capital_Letter_Dze" . #\u+0405)
+                ("Cyrillic_Capital_Letter_Byelorussian-Ukrainian_I" . #\u+0406)
+                ("Cyrillic_Capital_Letter_Yi" . #\u+0407)
+                ("Cyrillic_Capital_Letter_Je" . #\u+0408)
+                ("Cyrillic_Capital_Letter_Lje" . #\u+0409)
+                ("Cyrillic_Capital_Letter_Nje" . #\u+040a)
+                ("Cyrillic_Capital_Letter_Tshe" . #\u+040b)
+                ("Cyrillic_Capital_Letter_Kje" . #\u+040c)
+                ("Cyrillic_Capital_Letter_I_With_Grave" . #\u+040d)
+                ("Cyrillic_Capital_Letter_Short_U" . #\u+040e)
+                ("Cyrillic_Capital_Letter_Dzhe" . #\u+040f)
+                ("Cyrillic_Capital_Letter_A" . #\u+0410)
+                ("Cyrillic_Capital_Letter_Be" . #\u+0411)
+                ("Cyrillic_Capital_Letter_Ve" . #\u+0412)
+                ("Cyrillic_Capital_Letter_Ghe" . #\u+0413)
+                ("Cyrillic_Capital_Letter_De" . #\u+0414)
+                ("Cyrillic_Capital_Letter_Ie" . #\u+0415)
+                ("Cyrillic_Capital_Letter_Zhe" . #\u+0416)
+                ("Cyrillic_Capital_Letter_Ze" . #\u+0417)
+                ("Cyrillic_Capital_Letter_I" . #\u+0418)
+                ("Cyrillic_Capital_Letter_Short_I" . #\u+0419)
+                ("Cyrillic_Capital_Letter_Ka" . #\u+041a)
+                ("Cyrillic_Capital_Letter_El" . #\u+041b)
+                ("Cyrillic_Capital_Letter_Em" . #\u+041c)
+                ("Cyrillic_Capital_Letter_En" . #\u+041d)
+                ("Cyrillic_Capital_Letter_O" . #\u+041e)
+                ("Cyrillic_Capital_Letter_Pe" . #\u+041f)
+                ("Cyrillic_Capital_Letter_Er" . #\u+0420)
+                ("Cyrillic_Capital_Letter_Es" . #\u+0421)
+                ("Cyrillic_Capital_Letter_Te" . #\u+0422)
+                ("Cyrillic_Capital_Letter_U" . #\u+0423)
+                ("Cyrillic_Capital_Letter_Ef" . #\u+0424)
+                ("Cyrillic_Capital_Letter_Ha" . #\u+0425)
+                ("Cyrillic_Capital_Letter_Tse" . #\u+0426)
+                ("Cyrillic_Capital_Letter_Che" . #\u+0427)
+                ("Cyrillic_Capital_Letter_Sha" . #\u+0428)
+                ("Cyrillic_Capital_Letter_Shcha" . #\u+0429)
+                ("Cyrillic_Capital_Letter_Hard_Sign" . #\u+042a)
+                ("Cyrillic_Capital_Letter_Yeru" . #\u+042b)
+                ("Cyrillic_Capital_Letter_Soft_Sign" . #\u+042c)
+                ("Cyrillic_Capital_Letter_E" . #\u+042d)
+                ("Cyrillic_Capital_Letter_Yu" . #\u+042e)
+                ("Cyrillic_Capital_Letter_Ya" . #\u+042f)
+                ("Cyrillic_Small_Letter_A" . #\u+0430)
+                ("Cyrillic_Small_Letter_Be" . #\u+0431)
+                ("Cyrillic_Small_Letter_Ve" . #\u+0432)
+                ("Cyrillic_Small_Letter_Ghe" . #\u+0433)
+                ("Cyrillic_Small_Letter_De" . #\u+0434)
+                ("Cyrillic_Small_Letter_Ie" . #\u+0435)
+                ("Cyrillic_Small_Letter_Zhe" . #\u+0436)
+                ("Cyrillic_Small_Letter_Ze" . #\u+0437)
+                ("Cyrillic_Small_Letter_I" . #\u+0438)
+                ("Cyrillic_Small_Letter_Short_I" . #\u+0439)
+                ("Cyrillic_Small_Letter_Ka" . #\u+043a)
+                ("Cyrillic_Small_Letter_El" . #\u+043b)
+                ("Cyrillic_Small_Letter_Em" . #\u+043c)
+                ("Cyrillic_Small_Letter_En" . #\u+043d)
+                ("Cyrillic_Small_Letter_O" . #\u+043e)
+                ("Cyrillic_Small_Letter_Pe" . #\u+043f)
+                ("Cyrillic_Small_Letter_Er" . #\u+0440)
+                ("Cyrillic_Small_Letter_Es" . #\u+0441)
+                ("Cyrillic_Small_Letter_Te" . #\u+0442)
+                ("Cyrillic_Small_Letter_U" . #\u+0443)
+                ("Cyrillic_Small_Letter_Ef" . #\u+0444)
+                ("Cyrillic_Small_Letter_Ha" . #\u+0445)
+                ("Cyrillic_Small_Letter_Tse" . #\u+0446)
+                ("Cyrillic_Small_Letter_Che" . #\u+0447)
+                ("Cyrillic_Small_Letter_Sha" . #\u+0448)
+                ("Cyrillic_Small_Letter_Shcha" . #\u+0449)
+                ("Cyrillic_Small_Letter_Hard_Sign" . #\u+044a)
+                ("Cyrillic_Small_Letter_Yeru" . #\u+044b)
+                ("Cyrillic_Small_Letter_Soft_Sign" . #\u+044c)
+                ("Cyrillic_Small_Letter_E" . #\u+044d)
+                ("Cyrillic_Small_Letter_Yu" . #\u+044e)
+                ("Cyrillic_Small_Letter_Ya" . #\u+044f)
+                ("Cyrillic_Small_Letter_Ie_With_Grave" . #\u+0450)
+                ("Cyrillic_Small_Letter_Io" . #\u+0451)
+                ("Cyrillic_Small_Letter_Dje" . #\u+0452)
+                ("Cyrillic_Small_Letter_Gje" . #\u+0453)
+                ("Cyrillic_Small_Letter_Ukrainian_Ie" . #\u+0454)
+                ("Cyrillic_Small_Letter_Dze" . #\u+0455)
+                ("Cyrillic_Small_Letter_Byelorussian-Ukrainian_I" . #\u+0456)
+                ("Cyrillic_Small_Letter_Yi" . #\u+0457)
+                ("Cyrillic_Small_Letter_Je" . #\u+0458)
+                ("Cyrillic_Small_Letter_Lje" . #\u+0459)
+                ("Cyrillic_Small_Letter_Nje" . #\u+045a)
+                ("Cyrillic_Small_Letter_Tshe" . #\u+045b)
+                ("Cyrillic_Small_Letter_Kje" . #\u+045c)
+                ("Cyrillic_Small_Letter_I_With_Grave" . #\u+045d)
+                ("Cyrillic_Small_Letter_Short_U" . #\u+045e)
+                ("Cyrillic_Small_Letter_Dzhe" . #\u+045f)
+                ("Cyrillic_Capital_Letter_Omega" . #\u+0460)
+                ("Cyrillic_Small_Letter_Omega" . #\u+0461)
+                ("Cyrillic_Capital_Letter_Yat" . #\u+0462)
+                ("Cyrillic_Small_Letter_Yat" . #\u+0463)
+                ("Cyrillic_Capital_Letter_Iotified_E" . #\u+0464)
+                ("Cyrillic_Small_Letter_Iotified_E" . #\u+0465)
+                ("Cyrillic_Capital_Letter_Little_Yus" . #\u+0466)
+                ("Cyrillic_Small_Letter_Little_Yus" . #\u+0467)
+                ("Cyrillic_Capital_Letter_Iotified_Little_Yus" . #\u+0468)
+                ("Cyrillic_Small_Letter_Iotified_Little_Yus" . #\u+0469)
+                ("Cyrillic_Capital_Letter_Big_Yus" . #\u+046a)
+                ("Cyrillic_Small_Letter_Big_Yus" . #\u+046b)
+                ("Cyrillic_Capital_Letter_Iotified_Big_Yus" . #\u+046c)
+                ("Cyrillic_Small_Letter_Iotified_Big_Yus" . #\u+046d)
+                ("Cyrillic_Capital_Letter_Ksi" . #\u+046e)
+                ("Cyrillic_Small_Letter_Ksi" . #\u+046f)
+                ("Cyrillic_Capital_Letter_Psi" . #\u+0470)
+                ("Cyrillic_Small_Letter_Psi" . #\u+0471)
+                ("Cyrillic_Capital_Letter_Fita" . #\u+0472)
+                ("Cyrillic_Small_Letter_Fita" . #\u+0473)
+                ("Cyrillic_Capital_Letter_Izhitsa" . #\u+0474)
+                ("Cyrillic_Small_Letter_Izhitsa" . #\u+0475)
+                ("Cyrillic_Capital_Letter_Izhitsa_With_Double_Grave_Accent" . #\u+0476)
+                ("Cyrillic_Small_Letter_Izhitsa_With_Double_Grave_Accent" . #\u+0477)
+                ("Cyrillic_Capital_Letter_Uk" . #\u+0478)
+                ("Cyrillic_Small_Letter_Uk" . #\u+0479)
+                ("Cyrillic_Capital_Letter_Round_Omega" . #\u+047a)
+                ("Cyrillic_Small_Letter_Round_Omega" . #\u+047b)
+                ("Cyrillic_Capital_Letter_Omega_With_Titlo" . #\u+047c)
+                ("Cyrillic_Small_Letter_Omega_With_Titlo" . #\u+047d)
+                ("Cyrillic_Capital_Letter_Ot" . #\u+047e)
+                ("Cyrillic_Small_Letter_Ot" . #\u+047f)
+                ("Cyrillic_Capital_Letter_Koppa" . #\u+0480)
+                ("Cyrillic_Small_Letter_Koppa" . #\u+0481)
+                ("Cyrillic_Thousands_Sign" . #\u+0482)
+                ("Combining_Cyrillic_Titlo" . #\u+0483)
+                ("Combining_Cyrillic_Palatalization" . #\u+0484)
+                ("Combining_Cyrillic_Dasia_Pneumata" . #\u+0485)
+                ("Combining_Cyrillic_Psili_Pneumata" . #\u+0486)
+                ("Combining_Cyrillic_Hundred_Thousands_Sign" . #\u+0488)
+                ("Combining_Cyrillic_Millions_Sign" . #\u+0489)
+                ("Cyrillic_Capital_Letter_Short_I_With_Tail" . #\u+048a)
+                ("Cyrillic_Small_Letter_Short_I_With_Tail" . #\u+048b)
+                ("Cyrillic_Capital_Letter_Semisoft_Sign" . #\u+048c)
+                ("Cyrillic_Small_Letter_Semisoft_Sign" . #\u+048d)
+                ("Cyrillic_Capital_Letter_Er_With_Tick" . #\u+048e)
+                ("Cyrillic_Small_Letter_Er_With_Tick" . #\u+048f)
+                ("Cyrillic_Capital_Letter_Ghe_With_Upturn" . #\u+0490)
+                ("Cyrillic_Small_Letter_Ghe_With_Upturn" . #\u+0491)
+                ("Cyrillic_Capital_Letter_Ghe_With_Stroke" . #\u+0492)
+                ("Cyrillic_Small_Letter_Ghe_With_Stroke" . #\u+0493)
+                ("Cyrillic_Capital_Letter_Ghe_With_Middle_Hook" . #\u+0494)
+                ("Cyrillic_Small_Letter_Ghe_With_Middle_Hook" . #\u+0495)
+                ("Cyrillic_Capital_Letter_Zhe_With_Descender" . #\u+0496)
+                ("Cyrillic_Small_Letter_Zhe_With_Descender" . #\u+0497)
+                ("Cyrillic_Capital_Letter_Ze_With_Descender" . #\u+0498)
+                ("Cyrillic_Small_Letter_Ze_With_Descender" . #\u+0499)
+                ("Cyrillic_Capital_Letter_Ka_With_Descender" . #\u+049a)
+                ("Cyrillic_Small_Letter_Ka_With_Descender" . #\u+049b)
+                ("Cyrillic_Capital_Letter_Ka_With_Vertical_Stroke" . #\u+049c)
+                ("Cyrillic_Small_Letter_Ka_With_Vertical_Stroke" . #\u+049d)
+                ("Cyrillic_Capital_Letter_Ka_With_Stroke" . #\u+049e)
+                ("Cyrillic_Small_Letter_Ka_With_Stroke" . #\u+049f)
+                ("Cyrillic_Capital_Letter_Bashkir_Ka" . #\u+04a0)
+                ("Cyrillic_Small_Letter_Bashkir_Ka" . #\u+04a1)
+                ("Cyrillic_Capital_Letter_En_With_Descender" . #\u+04a2)
+                ("Cyrillic_Small_Letter_En_With_Descender" . #\u+04a3)
+                ("Cyrillic_Capital_Ligature_En_Ghe" . #\u+04a4)
+                ("Cyrillic_Small_Ligature_En_Ghe" . #\u+04a5)
+                ("Cyrillic_Capital_Letter_Pe_With_Middle_Hook" . #\u+04a6)
+                ("Cyrillic_Small_Letter_Pe_With_Middle_Hook" . #\u+04a7)
+                ("Cyrillic_Capital_Letter_Abkhasian_Ha" . #\u+04a8)
+                ("Cyrillic_Small_Letter_Abkhasian_Ha" . #\u+04a9)
+                ("Cyrillic_Capital_Letter_Es_With_Descender" . #\u+04aa)
+                ("Cyrillic_Small_Letter_Es_With_Descender" . #\u+04ab)
+                ("Cyrillic_Capital_Letter_Te_With_Descender" . #\u+04ac)
+                ("Cyrillic_Small_Letter_Te_With_Descender" . #\u+04ad)
+                ("Cyrillic_Capital_Letter_Straight_U" . #\u+04ae)
+                ("Cyrillic_Small_Letter_Straight_U" . #\u+04af)
+                ("Cyrillic_Capital_Letter_Straight_U_With_Stroke" . #\u+04b0)
+                ("Cyrillic_Small_Letter_Straight_U_With_Stroke" . #\u+04b1)
+                ("Cyrillic_Capital_Letter_Ha_With_Descender" . #\u+04b2)
+                ("Cyrillic_Small_Letter_Ha_With_Descender" . #\u+04b3)
+                ("Cyrillic_Capital_Ligature_Te_Tse" . #\u+04b4)
+                ("Cyrillic_Small_Ligature_Te_Tse" . #\u+04b5)
+                ("Cyrillic_Capital_Letter_Che_With_Descender" . #\u+04b6)
+                ("Cyrillic_Small_Letter_Che_With_Descender" . #\u+04b7)
+                ("Cyrillic_Capital_Letter_Che_With_Vertical_Stroke" . #\u+04b8)
+                ("Cyrillic_Small_Letter_Che_With_Vertical_Stroke" . #\u+04b9)
+                ("Cyrillic_Capital_Letter_Shha" . #\u+04ba)
+                ("Cyrillic_Small_Letter_Shha" . #\u+04bb)
+                ("Cyrillic_Capital_Letter_Abkhasian_Che" . #\u+04bc)
+                ("Cyrillic_Small_Letter_Abkhasian_Che" . #\u+04bd)
+                ("Cyrillic_Capital_Letter_Abkhasian_Che_With_Descender" . #\u+04be)
+                ("Cyrillic_Small_Letter_Abkhasian_Che_With_Descender" . #\u+04bf)
+                ("Cyrillic_Letter_Palochka" . #\u+04c0)
+                ("Cyrillic_Capital_Letter_Zhe_With_Breve" . #\u+04c1)
+                ("Cyrillic_Small_Letter_Zhe_With_Breve" . #\u+04c2)
+                ("Cyrillic_Capital_Letter_Ka_With_Hook" . #\u+04c3)
+                ("Cyrillic_Small_Letter_Ka_With_Hook" . #\u+04c4)
+                ("Cyrillic_Capital_Letter_El_With_Tail" . #\u+04c5)
+                ("Cyrillic_Small_Letter_El_With_Tail" . #\u+04c6)
+                ("Cyrillic_Capital_Letter_En_With_Hook" . #\u+04c7)
+                ("Cyrillic_Small_Letter_En_With_Hook" . #\u+04c8)
+                ("Cyrillic_Capital_Letter_En_With_Tail" . #\u+04c9)
+                ("Cyrillic_Small_Letter_En_With_Tail" . #\u+04ca)
+                ("Cyrillic_Capital_Letter_Khakassian_Che" . #\u+04cb)
+                ("Cyrillic_Small_Letter_Khakassian_Che" . #\u+04cc)
+                ("Cyrillic_Capital_Letter_Em_With_Tail" . #\u+04cd)
+                ("Cyrillic_Small_Letter_Em_With_Tail" . #\u+04ce)
+                ("Cyrillic_Small_Letter_Palochka" . #\u+04cf)
+                ("Cyrillic_Capital_Letter_A_With_Breve" . #\u+04d0)
+                ("Cyrillic_Small_Letter_A_With_Breve" . #\u+04d1)
+                ("Cyrillic_Capital_Letter_A_With_Diaeresis" . #\u+04d2)
+                ("Cyrillic_Small_Letter_A_With_Diaeresis" . #\u+04d3)
+                ("Cyrillic_Capital_Ligature_A_Ie" . #\u+04d4)
+                ("Cyrillic_Small_Ligature_A_Ie" . #\u+04d5)
+                ("Cyrillic_Capital_Letter_Ie_With_Breve" . #\u+04d6)
+                ("Cyrillic_Small_Letter_Ie_With_Breve" . #\u+04d7)
+                ("Cyrillic_Capital_Letter_Schwa" . #\u+04d8)
+                ("Cyrillic_Small_Letter_Schwa" . #\u+04d9)
+                ("Cyrillic_Capital_Letter_Schwa_With_Diaeresis" . #\u+04da)
+                ("Cyrillic_Small_Letter_Schwa_With_Diaeresis" . #\u+04db)
+                ("Cyrillic_Capital_Letter_Zhe_With_Diaeresis" . #\u+04dc)
+                ("Cyrillic_Small_Letter_Zhe_With_Diaeresis" . #\u+04dd)
+                ("Cyrillic_Capital_Letter_Ze_With_Diaeresis" . #\u+04de)
+                ("Cyrillic_Small_Letter_Ze_With_Diaeresis" . #\u+04df)
+                ("Cyrillic_Capital_Letter_Abkhasian_Dze" . #\u+04e0)
+                ("Cyrillic_Small_Letter_Abkhasian_Dze" . #\u+04e1)
+                ("Cyrillic_Capital_Letter_I_With_Macron" . #\u+04e2)
+                ("Cyrillic_Small_Letter_I_With_Macron" . #\u+04e3)
+                ("Cyrillic_Capital_Letter_I_With_Diaeresis" . #\u+04e4)
+                ("Cyrillic_Small_Letter_I_With_Diaeresis" . #\u+04e5)
+                ("Cyrillic_Capital_Letter_O_With_Diaeresis" . #\u+04e6)
+                ("Cyrillic_Small_Letter_O_With_Diaeresis" . #\u+04e7)
+                ("Cyrillic_Capital_Letter_Barred_O" . #\u+04e8)
+                ("Cyrillic_Small_Letter_Barred_O" . #\u+04e9)
+                ("Cyrillic_Capital_Letter_Barred_O_With_Diaeresis" . #\u+04ea)
+                ("Cyrillic_Small_Letter_Barred_O_With_Diaeresis" . #\u+04eb)
+                ("Cyrillic_Capital_Letter_E_With_Diaeresis" . #\u+04ec)
+                ("Cyrillic_Small_Letter_E_With_Diaeresis" . #\u+04ed)
+                ("Cyrillic_Capital_Letter_U_With_Macron" . #\u+04ee)
+                ("Cyrillic_Small_Letter_U_With_Macron" . #\u+04ef)
+                ("Cyrillic_Capital_Letter_U_With_Diaeresis" . #\u+04f0)
+                ("Cyrillic_Small_Letter_U_With_Diaeresis" . #\u+04f1)
+                ("Cyrillic_Capital_Letter_U_With_Double_Acute" . #\u+04f2)
+                ("Cyrillic_Small_Letter_U_With_Double_Acute" . #\u+04f3)
+                ("Cyrillic_Capital_Letter_Che_With_Diaeresis" . #\u+04f4)
+                ("Cyrillic_Small_Letter_Che_With_Diaeresis" . #\u+04f5)
+                ("Cyrillic_Capital_Letter_Ghe_With_Descender" . #\u+04f6)
+                ("Cyrillic_Small_Letter_Ghe_With_Descender" . #\u+04f7)
+                ("Cyrillic_Capital_Letter_Yeru_With_Diaeresis" . #\u+04f8)
+                ("Cyrillic_Small_Letter_Yeru_With_Diaeresis" . #\u+04f9)
+                ("Cyrillic_Capital_Letter_Ghe_With_Stroke_And_Hook" . #\u+04fa)
+                ("Cyrillic_Small_Letter_Ghe_With_Stroke_And_Hook" . #\u+04fb)
+                ("Cyrillic_Capital_Letter_Ha_With_Hook" . #\u+04fc)
+                ("Cyrillic_Small_Letter_Ha_With_Hook" . #\u+04fd)
+                ("Cyrillic_Capital_Letter_Ha_With_Stroke" . #\u+04fe)
+                ("Cyrillic_Small_Letter_Ha_With_Stroke" . #\u+04ff)
+                ("Cyrillic_Capital_Letter_Komi_De" . #\u+0500)
+                ("Cyrillic_Small_Letter_Komi_De" . #\u+0501)
+                ("Cyrillic_Capital_Letter_Komi_Dje" . #\u+0502)
+                ("Cyrillic_Small_Letter_Komi_Dje" . #\u+0503)
+                ("Cyrillic_Capital_Letter_Komi_Zje" . #\u+0504)
+                ("Cyrillic_Small_Letter_Komi_Zje" . #\u+0505)
+                ("Cyrillic_Capital_Letter_Komi_Dzje" . #\u+0506)
+                ("Cyrillic_Small_Letter_Komi_Dzje" . #\u+0507)
+                ("Cyrillic_Capital_Letter_Komi_Lje" . #\u+0508)
+                ("Cyrillic_Small_Letter_Komi_Lje" . #\u+0509)
+                ("Cyrillic_Capital_Letter_Komi_Nje" . #\u+050a)
+                ("Cyrillic_Small_Letter_Komi_Nje" . #\u+050b)
+                ("Cyrillic_Capital_Letter_Komi_Sje" . #\u+050c)
+                ("Cyrillic_Small_Letter_Komi_Sje" . #\u+050d)
+                ("Cyrillic_Capital_Letter_Komi_Tje" . #\u+050e)
+                ("Cyrillic_Small_Letter_Komi_Tje" . #\u+050f)
+                ("Cyrillic_Capital_Letter_Reversed_Ze" . #\u+0510)
+                ("Cyrillic_Small_Letter_Reversed_Ze" . #\u+0511)
+                ("Cyrillic_Capital_Letter_El_With_Hook" . #\u+0512)
+                ("Cyrillic_Small_Letter_El_With_Hook" . #\u+0513)
+                ("Armenian_Capital_Letter_Ayb" . #\u+0531)
+                ("Armenian_Capital_Letter_Ben" . #\u+0532)
+                ("Armenian_Capital_Letter_Gim" . #\u+0533)
+                ("Armenian_Capital_Letter_Da" . #\u+0534)
+                ("Armenian_Capital_Letter_Ech" . #\u+0535)
+                ("Armenian_Capital_Letter_Za" . #\u+0536)
+                ("Armenian_Capital_Letter_Eh" . #\u+0537)
+                ("Armenian_Capital_Letter_Et" . #\u+0538)
+                ("Armenian_Capital_Letter_To" . #\u+0539)
+                ("Armenian_Capital_Letter_Zhe" . #\u+053a)
+                ("Armenian_Capital_Letter_Ini" . #\u+053b)
+                ("Armenian_Capital_Letter_Liwn" . #\u+053c)
+                ("Armenian_Capital_Letter_Xeh" . #\u+053d)
+                ("Armenian_Capital_Letter_Ca" . #\u+053e)
+                ("Armenian_Capital_Letter_Ken" . #\u+053f)
+                ("Armenian_Capital_Letter_Ho" . #\u+0540)
+                ("Armenian_Capital_Letter_Ja" . #\u+0541)
+                ("Armenian_Capital_Letter_Ghad" . #\u+0542)
+                ("Armenian_Capital_Letter_Cheh" . #\u+0543)
+                ("Armenian_Capital_Letter_Men" . #\u+0544)
+                ("Armenian_Capital_Letter_Yi" . #\u+0545)
+                ("Armenian_Capital_Letter_Now" . #\u+0546)
+                ("Armenian_Capital_Letter_Sha" . #\u+0547)
+                ("Armenian_Capital_Letter_Vo" . #\u+0548)
+                ("Armenian_Capital_Letter_Cha" . #\u+0549)
+                ("Armenian_Capital_Letter_Peh" . #\u+054a)
+                ("Armenian_Capital_Letter_Jheh" . #\u+054b)
+                ("Armenian_Capital_Letter_Ra" . #\u+054c)
+                ("Armenian_Capital_Letter_Seh" . #\u+054d)
+                ("Armenian_Capital_Letter_Vew" . #\u+054e)
+                ("Armenian_Capital_Letter_Tiwn" . #\u+054f)
+                ("Armenian_Capital_Letter_Reh" . #\u+0550)
+                ("Armenian_Capital_Letter_Co" . #\u+0551)
+                ("Armenian_Capital_Letter_Yiwn" . #\u+0552)
+                ("Armenian_Capital_Letter_Piwr" . #\u+0553)
+                ("Armenian_Capital_Letter_Keh" . #\u+0554)
+                ("Armenian_Capital_Letter_Oh" . #\u+0555)
+                ("Armenian_Capital_Letter_Feh" . #\u+0556)
+                ("Armenian_Modifier_Letter_Left_Half_Ring" . #\u+0559)
+                ("Armenian_Apostrophe" . #\u+055a)
+                ("Armenian_Emphasis_Mark" . #\u+055b)
+                ("Armenian_Exclamation_Mark" . #\u+055c)
+                ("Armenian_Comma" . #\u+055d)
+                ("Armenian_Question_Mark" . #\u+055e)
+                ("Armenian_Abbreviation_Mark" . #\u+055f)
+                ("Armenian_Small_Letter_Ayb" . #\u+0561)
+                ("Armenian_Small_Letter_Ben" . #\u+0562)
+                ("Armenian_Small_Letter_Gim" . #\u+0563)
+                ("Armenian_Small_Letter_Da" . #\u+0564)
+                ("Armenian_Small_Letter_Ech" . #\u+0565)
+                ("Armenian_Small_Letter_Za" . #\u+0566)
+                ("Armenian_Small_Letter_Eh" . #\u+0567)
+                ("Armenian_Small_Letter_Et" . #\u+0568)
+                ("Armenian_Small_Letter_To" . #\u+0569)
+                ("Armenian_Small_Letter_Zhe" . #\u+056a)
+                ("Armenian_Small_Letter_Ini" . #\u+056b)
+                ("Armenian_Small_Letter_Liwn" . #\u+056c)
+                ("Armenian_Small_Letter_Xeh" . #\u+056d)
+                ("Armenian_Small_Letter_Ca" . #\u+056e)
+                ("Armenian_Small_Letter_Ken" . #\u+056f)
+                ("Armenian_Small_Letter_Ho" . #\u+0570)
+                ("Armenian_Small_Letter_Ja" . #\u+0571)
+                ("Armenian_Small_Letter_Ghad" . #\u+0572)
+                ("Armenian_Small_Letter_Cheh" . #\u+0573)
+                ("Armenian_Small_Letter_Men" . #\u+0574)
+                ("Armenian_Small_Letter_Yi" . #\u+0575)
+                ("Armenian_Small_Letter_Now" . #\u+0576)
+                ("Armenian_Small_Letter_Sha" . #\u+0577)
+                ("Armenian_Small_Letter_Vo" . #\u+0578)
+                ("Armenian_Small_Letter_Cha" . #\u+0579)
+                ("Armenian_Small_Letter_Peh" . #\u+057a)
+                ("Armenian_Small_Letter_Jheh" . #\u+057b)
+                ("Armenian_Small_Letter_Ra" . #\u+057c)
+                ("Armenian_Small_Letter_Seh" . #\u+057d)
+                ("Armenian_Small_Letter_Vew" . #\u+057e)
+                ("Armenian_Small_Letter_Tiwn" . #\u+057f)
+                ("Armenian_Small_Letter_Reh" . #\u+0580)
+                ("Armenian_Small_Letter_Co" . #\u+0581)
+                ("Armenian_Small_Letter_Yiwn" . #\u+0582)
+                ("Armenian_Small_Letter_Piwr" . #\u+0583)
+                ("Armenian_Small_Letter_Keh" . #\u+0584)
+                ("Armenian_Small_Letter_Oh" . #\u+0585)
+                ("Armenian_Small_Letter_Feh" . #\u+0586)
+                ("Armenian_Small_Ligature_Ech_Yiwn" . #\u+0587)
+                ("Armenian_Full_Stop" . #\u+0589)
+                ("Armenian_Hyphen" . #\u+058a)
+                ("Hebrew_Accent_Etnahta" . #\u+0591)
+                ("Hebrew_Accent_Segol" . #\u+0592)
+                ("Hebrew_Accent_Shalshelet" . #\u+0593)
+                ("Hebrew_Accent_Zaqef_Qatan" . #\u+0594)
+                ("Hebrew_Accent_Zaqef_Gadol" . #\u+0595)
+                ("Hebrew_Accent_Tipeha" . #\u+0596)
+                ("Hebrew_Accent_Revia" . #\u+0597)
+                ("Hebrew_Accent_Zarqa" . #\u+0598)
+                ("Hebrew_Accent_Pashta" . #\u+0599)
+                ("Hebrew_Accent_Yetiv" . #\u+059a)
+                ("Hebrew_Accent_Tevir" . #\u+059b)
+                ("Hebrew_Accent_Geresh" . #\u+059c)
+                ("Hebrew_Accent_Geresh_Muqdam" . #\u+059d)
+                ("Hebrew_Accent_Gershayim" . #\u+059e)
+                ("Hebrew_Accent_Qarney_Para" . #\u+059f)
+                ("Hebrew_Accent_Telisha_Gedola" . #\u+05a0)
+                ("Hebrew_Accent_Pazer" . #\u+05a1)
+                ("Hebrew_Accent_Atnah_Hafukh" . #\u+05a2)
+                ("Hebrew_Accent_Munah" . #\u+05a3)
+                ("Hebrew_Accent_Mahapakh" . #\u+05a4)
+                ("Hebrew_Accent_Merkha" . #\u+05a5)
+                ("Hebrew_Accent_Merkha_Kefula" . #\u+05a6)
+                ("Hebrew_Accent_Darga" . #\u+05a7)
+                ("Hebrew_Accent_Qadma" . #\u+05a8)
+                ("Hebrew_Accent_Telisha_Qetana" . #\u+05a9)
+                ("Hebrew_Accent_Yerah_Ben_Yomo" . #\u+05aa)
+                ("Hebrew_Accent_Ole" . #\u+05ab)
+                ("Hebrew_Accent_Iluy" . #\u+05ac)
+                ("Hebrew_Accent_Dehi" . #\u+05ad)
+                ("Hebrew_Accent_Zinor" . #\u+05ae)
+                ("Hebrew_Mark_Masora_Circle" . #\u+05af)
+                ("Hebrew_Point_Sheva" . #\u+05b0)
+                ("Hebrew_Point_Hataf_Segol" . #\u+05b1)
+                ("Hebrew_Point_Hataf_Patah" . #\u+05b2)
+                ("Hebrew_Point_Hataf_Qamats" . #\u+05b3)
+                ("Hebrew_Point_Hiriq" . #\u+05b4)
+                ("Hebrew_Point_Tsere" . #\u+05b5)
+                ("Hebrew_Point_Segol" . #\u+05b6)
+                ("Hebrew_Point_Patah" . #\u+05b7)
+                ("Hebrew_Point_Qamats" . #\u+05b8)
+                ("Hebrew_Point_Holam" . #\u+05b9)
+                ("Hebrew_Point_Holam_Haser_For_Vav" . #\u+05ba)
+                ("Hebrew_Point_Qubuts" . #\u+05bb)
+                ("Hebrew_Point_Dagesh_Or_Mapiq" . #\u+05bc)
+                ("Hebrew_Point_Meteg" . #\u+05bd)
+                ("Hebrew_Punctuation_Maqaf" . #\u+05be)
+                ("Hebrew_Point_Rafe" . #\u+05bf)
+                ("Hebrew_Punctuation_Paseq" . #\u+05c0)
+                ("Hebrew_Point_Shin_Dot" . #\u+05c1)
+                ("Hebrew_Point_Sin_Dot" . #\u+05c2)
+                ("Hebrew_Punctuation_Sof_Pasuq" . #\u+05c3)
+                ("Hebrew_Mark_Upper_Dot" . #\u+05c4)
+                ("Hebrew_Mark_Lower_Dot" . #\u+05c5)
+                ("Hebrew_Punctuation_Nun_Hafukha" . #\u+05c6)
+                ("Hebrew_Point_Qamats_Qatan" . #\u+05c7)
+                ("Hebrew_Letter_Alef" . #\u+05d0)
+                ("Hebrew_Letter_Bet" . #\u+05d1)
+                ("Hebrew_Letter_Gimel" . #\u+05d2)
+                ("Hebrew_Letter_Dalet" . #\u+05d3)
+                ("Hebrew_Letter_He" . #\u+05d4)
+                ("Hebrew_Letter_Vav" . #\u+05d5)
+                ("Hebrew_Letter_Zayin" . #\u+05d6)
+                ("Hebrew_Letter_Het" . #\u+05d7)
+                ("Hebrew_Letter_Tet" . #\u+05d8)
+                ("Hebrew_Letter_Yod" . #\u+05d9)
+                ("Hebrew_Letter_Final_Kaf" . #\u+05da)
+                ("Hebrew_Letter_Kaf" . #\u+05db)
+                ("Hebrew_Letter_Lamed" . #\u+05dc)
+                ("Hebrew_Letter_Final_Mem" . #\u+05dd)
+                ("Hebrew_Letter_Mem" . #\u+05de)
+                ("Hebrew_Letter_Final_Nun" . #\u+05df)
+                ("Hebrew_Letter_Nun" . #\u+05e0)
+                ("Hebrew_Letter_Samekh" . #\u+05e1)
+                ("Hebrew_Letter_Ayin" . #\u+05e2)
+                ("Hebrew_Letter_Final_Pe" . #\u+05e3)
+                ("Hebrew_Letter_Pe" . #\u+05e4)
+                ("Hebrew_Letter_Final_Tsadi" . #\u+05e5)
+                ("Hebrew_Letter_Tsadi" . #\u+05e6)
+                ("Hebrew_Letter_Qof" . #\u+05e7)
+                ("Hebrew_Letter_Resh" . #\u+05e8)
+                ("Hebrew_Letter_Shin" . #\u+05e9)
+                ("Hebrew_Letter_Tav" . #\u+05ea)
+                ("Hebrew_Ligature_Yiddish_Double_Vav" . #\u+05f0)
+                ("Hebrew_Ligature_Yiddish_Vav_Yod" . #\u+05f1)
+                ("Hebrew_Ligature_Yiddish_Double_Yod" . #\u+05f2)
+                ("Hebrew_Punctuation_Geresh" . #\u+05f3)
+                ("Hebrew_Punctuation_Gershayim" . #\u+05f4)
+                ("Arabic_Number_Sign" . #\u+0600)
+                ("Arabic_Sign_Sanah" . #\u+0601)
+                ("Arabic_Footnote_Marker" . #\u+0602)
+                ("Arabic_Sign_Safha" . #\u+0603)
+                ("Afghani_Sign" . #\u+060b)
+                ("Arabic_Comma" . #\u+060c)
+                ("Arabic_Date_Separator" . #\u+060d)
+                ("Arabic_Poetic_Verse_Sign" . #\u+060e)
+                ("Arabic_Sign_Misra" . #\u+060f)
+                ("Arabic_Sign_Sallallahou_Alayhe_Wassallam" . #\u+0610)
+                ("Arabic_Sign_Alayhe_Assallam" . #\u+0611)
+                ("Arabic_Sign_Rahmatullah_Alayhe" . #\u+0612)
+                ("Arabic_Sign_Radi_Allahou_Anhu" . #\u+0613)
+                ("Arabic_Sign_Takhallus" . #\u+0614)
+                ("Arabic_Small_High_Tah" . #\u+0615)
+                ("Arabic_Semicolon" . #\u+061b)
+                ("Arabic_Triple_Dot_Punctuation_Mark" . #\u+061e)
+                ("Arabic_Question_Mark" . #\u+061f)
+                ("Arabic_Letter_Hamza" . #\u+0621)
+                ("Arabic_Letter_Alef_With_Madda_Above" . #\u+0622)
+                ("Arabic_Letter_Alef_With_Hamza_Above" . #\u+0623)
+                ("Arabic_Letter_Waw_With_Hamza_Above" . #\u+0624)
+                ("Arabic_Letter_Alef_With_Hamza_Below" . #\u+0625)
+                ("Arabic_Letter_Yeh_With_Hamza_Above" . #\u+0626)
+                ("Arabic_Letter_Alef" . #\u+0627)
+                ("Arabic_Letter_Beh" . #\u+0628)
+                ("Arabic_Letter_Teh_Marbuta" . #\u+0629)
+                ("Arabic_Letter_Teh" . #\u+062a)
+                ("Arabic_Letter_Theh" . #\u+062b)
+                ("Arabic_Letter_Jeem" . #\u+062c)
+                ("Arabic_Letter_Hah" . #\u+062d)
+                ("Arabic_Letter_Khah" . #\u+062e)
+                ("Arabic_Letter_Dal" . #\u+062f)
+                ("Arabic_Letter_Thal" . #\u+0630)
+                ("Arabic_Letter_Reh" . #\u+0631)
+                ("Arabic_Letter_Zain" . #\u+0632)
+                ("Arabic_Letter_Seen" . #\u+0633)
+                ("Arabic_Letter_Sheen" . #\u+0634)
+                ("Arabic_Letter_Sad" . #\u+0635)
+                ("Arabic_Letter_Dad" . #\u+0636)
+                ("Arabic_Letter_Tah" . #\u+0637)
+                ("Arabic_Letter_Zah" . #\u+0638)
+                ("Arabic_Letter_Ain" . #\u+0639)
+                ("Arabic_Letter_Ghain" . #\u+063a)
+                ("Arabic_Tatweel" . #\u+0640)
+                ("Arabic_Letter_Feh" . #\u+0641)
+                ("Arabic_Letter_Qaf" . #\u+0642)
+                ("Arabic_Letter_Kaf" . #\u+0643)
+                ("Arabic_Letter_Lam" . #\u+0644)
+                ("Arabic_Letter_Meem" . #\u+0645)
+                ("Arabic_Letter_Noon" . #\u+0646)
+                ("Arabic_Letter_Heh" . #\u+0647)
+                ("Arabic_Letter_Waw" . #\u+0648)
+                ("Arabic_Letter_Alef_Maksura" . #\u+0649)
+                ("Arabic_Letter_Yeh" . #\u+064a)
+                ("Arabic_Fathatan" . #\u+064b)
+                ("Arabic_Dammatan" . #\u+064c)
+                ("Arabic_Kasratan" . #\u+064d)
+                ("Arabic_Fatha" . #\u+064e)
+                ("Arabic_Damma" . #\u+064f)
+                ("Arabic_Kasra" . #\u+0650)
+                ("Arabic_Shadda" . #\u+0651)
+                ("Arabic_Sukun" . #\u+0652)
+                ("Arabic_Maddah_Above" . #\u+0653)
+                ("Arabic_Hamza_Above" . #\u+0654)
+                ("Arabic_Hamza_Below" . #\u+0655)
+                ("Arabic_Subscript_Alef" . #\u+0656)
+                ("Arabic_Inverted_Damma" . #\u+0657)
+                ("Arabic_Mark_Noon_Ghunna" . #\u+0658)
+                ("Arabic_Zwarakay" . #\u+0659)
+                ("Arabic_Vowel_Sign_Small_V_Above" . #\u+065a)
+                ("Arabic_Vowel_Sign_Inverted_Small_V_Above" . #\u+065b)
+                ("Arabic_Vowel_Sign_Dot_Below" . #\u+065c)
+                ("Arabic_Reversed_Damma" . #\u+065d)
+                ("Arabic_Fatha_With_Two_Dots" . #\u+065e)
+                ("Arabic-Indic_Digit_Zero" . #\u+0660)
+                ("Arabic-Indic_Digit_One" . #\u+0661)
+                ("Arabic-Indic_Digit_Two" . #\u+0662)
+                ("Arabic-Indic_Digit_Three" . #\u+0663)
+                ("Arabic-Indic_Digit_Four" . #\u+0664)
+                ("Arabic-Indic_Digit_Five" . #\u+0665)
+                ("Arabic-Indic_Digit_Six" . #\u+0666)
+                ("Arabic-Indic_Digit_Seven" . #\u+0667)
+                ("Arabic-Indic_Digit_Eight" . #\u+0668)
+                ("Arabic-Indic_Digit_Nine" . #\u+0669)
+                ("Arabic_Percent_Sign" . #\u+066a)
+                ("Arabic_Decimal_Separator" . #\u+066b)
+                ("Arabic_Thousands_Separator" . #\u+066c)
+                ("Arabic_Five_Pointed_Star" . #\u+066d)
+                ("Arabic_Letter_Dotless_Beh" . #\u+066e)
+                ("Arabic_Letter_Dotless_Qaf" . #\u+066f)
+                ("Arabic_Letter_Superscript_Alef" . #\u+0670)
+                ("Arabic_Letter_Alef_Wasla" . #\u+0671)
+                ("Arabic_Letter_Alef_With_Wavy_Hamza_Above" . #\u+0672)
+                ("Arabic_Letter_Alef_With_Wavy_Hamza_Below" . #\u+0673)
+                ("Arabic_Letter_High_Hamza" . #\u+0674)
+                ("Arabic_Letter_High_Hamza_Alef" . #\u+0675)
+                ("Arabic_Letter_High_Hamza_Waw" . #\u+0676)
+                ("Arabic_Letter_U_With_Hamza_Above" . #\u+0677)
+                ("Arabic_Letter_High_Hamza_Yeh" . #\u+0678)
+                ("Arabic_Letter_Tteh" . #\u+0679)
+                ("Arabic_Letter_Tteheh" . #\u+067a)
+                ("Arabic_Letter_Beeh" . #\u+067b)
+                ("Arabic_Letter_Teh_With_Ring" . #\u+067c)
+                ("Arabic_Letter_Teh_With_Three_Dots_Above_Downwards" . #\u+067d)
+                ("Arabic_Letter_Peh" . #\u+067e)
+                ("Arabic_Letter_Teheh" . #\u+067f)
+                ("Arabic_Letter_Beheh" . #\u+0680)
+                ("Arabic_Letter_Hah_With_Hamza_Above" . #\u+0681)
+                ("Arabic_Letter_Hah_With_Two_Dots_Vertical_Above" . #\u+0682)
+                ("Arabic_Letter_Nyeh" . #\u+0683)
+                ("Arabic_Letter_Dyeh" . #\u+0684)
+                ("Arabic_Letter_Hah_With_Three_Dots_Above" . #\u+0685)
+                ("Arabic_Letter_Tcheh" . #\u+0686)
+                ("Arabic_Letter_Tcheheh" . #\u+0687)
+                ("Arabic_Letter_Ddal" . #\u+0688)
+                ("Arabic_Letter_Dal_With_Ring" . #\u+0689)
+                ("Arabic_Letter_Dal_With_Dot_Below" . #\u+068a)
+                ("Arabic_Letter_Dal_With_Dot_Below_And_Small_Tah" . #\u+068b)
+                ("Arabic_Letter_Dahal" . #\u+068c)
+                ("Arabic_Letter_Ddahal" . #\u+068d)
+                ("Arabic_Letter_Dul" . #\u+068e)
+                ("Arabic_Letter_Dal_With_Three_Dots_Above_Downwards" . #\u+068f)
+                ("Arabic_Letter_Dal_With_Four_Dots_Above" . #\u+0690)
+                ("Arabic_Letter_Rreh" . #\u+0691)
+                ("Arabic_Letter_Reh_With_Small_V" . #\u+0692)
+                ("Arabic_Letter_Reh_With_Ring" . #\u+0693)
+                ("Arabic_Letter_Reh_With_Dot_Below" . #\u+0694)
+                ("Arabic_Letter_Reh_With_Small_V_Below" . #\u+0695)
+                ("Arabic_Letter_Reh_With_Dot_Below_And_Dot_Above" . #\u+0696)
+                ("Arabic_Letter_Reh_With_Two_Dots_Above" . #\u+0697)
+                ("Arabic_Letter_Jeh" . #\u+0698)
+                ("Arabic_Letter_Reh_With_Four_Dots_Above" . #\u+0699)
+                ("Arabic_Letter_Seen_With_Dot_Below_And_Dot_Above" . #\u+069a)
+                ("Arabic_Letter_Seen_With_Three_Dots_Below" . #\u+069b)
+                ("Arabic_Letter_Seen_With_Three_Dots_Below_And_Three_Dots_Above" . #\u+069c)
+                ("Arabic_Letter_Sad_With_Two_Dots_Below" . #\u+069d)
+                ("Arabic_Letter_Sad_With_Three_Dots_Above" . #\u+069e)
+                ("Arabic_Letter_Tah_With_Three_Dots_Above" . #\u+069f)
+                ("Arabic_Letter_Ain_With_Three_Dots_Above" . #\u+06a0)
+                ("Arabic_Letter_Dotless_Feh" . #\u+06a1)
+                ("Arabic_Letter_Feh_With_Dot_Moved_Below" . #\u+06a2)
+                ("Arabic_Letter_Feh_With_Dot_Below" . #\u+06a3)
+                ("Arabic_Letter_Veh" . #\u+06a4)
+                ("Arabic_Letter_Feh_With_Three_Dots_Below" . #\u+06a5)
+                ("Arabic_Letter_Peheh" . #\u+06a6)
+                ("Arabic_Letter_Qaf_With_Dot_Above" . #\u+06a7)
+                ("Arabic_Letter_Qaf_With_Three_Dots_Above" . #\u+06a8)
+                ("Arabic_Letter_Keheh" . #\u+06a9)
+                ("Arabic_Letter_Swash_Kaf" . #\u+06aa)
+                ("Arabic_Letter_Kaf_With_Ring" . #\u+06ab)
+                ("Arabic_Letter_Kaf_With_Dot_Above" . #\u+06ac)
+                ("Arabic_Letter_Ng" . #\u+06ad)
+                ("Arabic_Letter_Kaf_With_Three_Dots_Below" . #\u+06ae)
+                ("Arabic_Letter_Gaf" . #\u+06af)
+                ("Arabic_Letter_Gaf_With_Ring" . #\u+06b0)
+                ("Arabic_Letter_Ngoeh" . #\u+06b1)
+                ("Arabic_Letter_Gaf_With_Two_Dots_Below" . #\u+06b2)
+                ("Arabic_Letter_Gueh" . #\u+06b3)
+                ("Arabic_Letter_Gaf_With_Three_Dots_Above" . #\u+06b4)
+                ("Arabic_Letter_Lam_With_Small_V" . #\u+06b5)
+                ("Arabic_Letter_Lam_With_Dot_Above" . #\u+06b6)
+                ("Arabic_Letter_Lam_With_Three_Dots_Above" . #\u+06b7)
+                ("Arabic_Letter_Lam_With_Three_Dots_Below" . #\u+06b8)
+                ("Arabic_Letter_Noon_With_Dot_Below" . #\u+06b9)
+                ("Arabic_Letter_Noon_Ghunna" . #\u+06ba)
+                ("Arabic_Letter_Rnoon" . #\u+06bb)
+                ("Arabic_Letter_Noon_With_Ring" . #\u+06bc)
+                ("Arabic_Letter_Noon_With_Three_Dots_Above" . #\u+06bd)
+                ("Arabic_Letter_Heh_Doachashmee" . #\u+06be)
+                ("Arabic_Letter_Tcheh_With_Dot_Above" . #\u+06bf)
+                ("Arabic_Letter_Heh_With_Yeh_Above" . #\u+06c0)
+                ("Arabic_Letter_Heh_Goal" . #\u+06c1)
+                ("Arabic_Letter_Heh_Goal_With_Hamza_Above" . #\u+06c2)
+                ("Arabic_Letter_Teh_Marbuta_Goal" . #\u+06c3)
+                ("Arabic_Letter_Waw_With_Ring" . #\u+06c4)
+                ("Arabic_Letter_Kirghiz_Oe" . #\u+06c5)
+                ("Arabic_Letter_Oe" . #\u+06c6)
+                ("Arabic_Letter_U" . #\u+06c7)
+                ("Arabic_Letter_Yu" . #\u+06c8)
+                ("Arabic_Letter_Kirghiz_Yu" . #\u+06c9)
+                ("Arabic_Letter_Waw_With_Two_Dots_Above" . #\u+06ca)
+                ("Arabic_Letter_Ve" . #\u+06cb)
+                ("Arabic_Letter_Farsi_Yeh" . #\u+06cc)
+                ("Arabic_Letter_Yeh_With_Tail" . #\u+06cd)
+                ("Arabic_Letter_Yeh_With_Small_V" . #\u+06ce)
+                ("Arabic_Letter_Waw_With_Dot_Above" . #\u+06cf)
+                ("Arabic_Letter_E" . #\u+06d0)
+                ("Arabic_Letter_Yeh_With_Three_Dots_Below" . #\u+06d1)
+                ("Arabic_Letter_Yeh_Barree" . #\u+06d2)
+                ("Arabic_Letter_Yeh_Barree_With_Hamza_Above" . #\u+06d3)
+                ("Arabic_Full_Stop" . #\u+06d4)
+                ("Arabic_Letter_Ae" . #\u+06d5)
+                ("Arabic_Small_High_Ligature_Sad_With_Lam_With_Alef_Maksura" . #\u+06d6)
+                ("Arabic_Small_High_Ligature_Qaf_With_Lam_With_Alef_Maksura" . #\u+06d7)
+                ("Arabic_Small_High_Meem_Initial_Form" . #\u+06d8)
+                ("Arabic_Small_High_Lam_Alef" . #\u+06d9)
+                ("Arabic_Small_High_Jeem" . #\u+06da)
+                ("Arabic_Small_High_Three_Dots" . #\u+06db)
+                ("Arabic_Small_High_Seen" . #\u+06dc)
+                ("Arabic_End_Of_Ayah" . #\u+06dd)
+                ("Arabic_Start_Of_Rub_El_Hizb" . #\u+06de)
+                ("Arabic_Small_High_Rounded_Zero" . #\u+06df)
+                ("Arabic_Small_High_Upright_Rectangular_Zero" . #\u+06e0)
+                ("Arabic_Small_High_Dotless_Head_Of_Khah" . #\u+06e1)
+                ("Arabic_Small_High_Meem_Isolated_Form" . #\u+06e2)
+                ("Arabic_Small_Low_Seen" . #\u+06e3)
+                ("Arabic_Small_High_Madda" . #\u+06e4)
+                ("Arabic_Small_Waw" . #\u+06e5)
+                ("Arabic_Small_Yeh" . #\u+06e6)
+                ("Arabic_Small_High_Yeh" . #\u+06e7)
+                ("Arabic_Small_High_Noon" . #\u+06e8)
+                ("Arabic_Place_Of_Sajdah" . #\u+06e9)
+                ("Arabic_Empty_Centre_Low_Stop" . #\u+06ea)
+                ("Arabic_Empty_Centre_High_Stop" . #\u+06eb)
+                ("Arabic_Rounded_High_Stop_With_Filled_Centre" . #\u+06ec)
+                ("Arabic_Small_Low_Meem" . #\u+06ed)
+                ("Arabic_Letter_Dal_With_Inverted_V" . #\u+06ee)
+                ("Arabic_Letter_Reh_With_Inverted_V" . #\u+06ef)
+                ("Extended_Arabic-Indic_Digit_Zero" . #\u+06f0)
+                ("Extended_Arabic-Indic_Digit_One" . #\u+06f1)
+                ("Extended_Arabic-Indic_Digit_Two" . #\u+06f2)
+                ("Extended_Arabic-Indic_Digit_Three" . #\u+06f3)
+                ("Extended_Arabic-Indic_Digit_Four" . #\u+06f4)
+                ("Extended_Arabic-Indic_Digit_Five" . #\u+06f5)
+                ("Extended_Arabic-Indic_Digit_Six" . #\u+06f6)
+                ("Extended_Arabic-Indic_Digit_Seven" . #\u+06f7)
+                ("Extended_Arabic-Indic_Digit_Eight" . #\u+06f8)
+                ("Extended_Arabic-Indic_Digit_Nine" . #\u+06f9)
+                ("Arabic_Letter_Sheen_With_Dot_Below" . #\u+06fa)
+                ("Arabic_Letter_Dad_With_Dot_Below" . #\u+06fb)
+                ("Arabic_Letter_Ghain_With_Dot_Below" . #\u+06fc)
+                ("Arabic_Sign_Sindhi_Ampersand" . #\u+06fd)
+                ("Arabic_Sign_Sindhi_Postposition_Men" . #\u+06fe)
+                ("Arabic_Letter_Heh_With_Inverted_V" . #\u+06ff)
+                ("Syriac_End_Of_Paragraph" . #\u+0700)
+                ("Syriac_Supralinear_Full_Stop" . #\u+0701)
+                ("Syriac_Sublinear_Full_Stop" . #\u+0702)
+                ("Syriac_Supralinear_Colon" . #\u+0703)
+                ("Syriac_Sublinear_Colon" . #\u+0704)
+                ("Syriac_Horizontal_Colon" . #\u+0705)
+                ("Syriac_Colon_Skewed_Left" . #\u+0706)
+                ("Syriac_Colon_Skewed_Right" . #\u+0707)
+                ("Syriac_Supralinear_Colon_Skewed_Left" . #\u+0708)
+                ("Syriac_Sublinear_Colon_Skewed_Right" . #\u+0709)
+                ("Syriac_Contraction" . #\u+070a)
+                ("Syriac_Harklean_Obelus" . #\u+070b)
+                ("Syriac_Harklean_Metobelus" . #\u+070c)
+                ("Syriac_Harklean_Asteriscus" . #\u+070d)
+                ("Syriac_Abbreviation_Mark" . #\u+070f)
+                ("Syriac_Letter_Alaph" . #\u+0710)
+                ("Syriac_Letter_Superscript_Alaph" . #\u+0711)
+                ("Syriac_Letter_Beth" . #\u+0712)
+                ("Syriac_Letter_Gamal" . #\u+0713)
+                ("Syriac_Letter_Gamal_Garshuni" . #\u+0714)
+                ("Syriac_Letter_Dalath" . #\u+0715)
+                ("Syriac_Letter_Dotless_Dalath_Rish" . #\u+0716)
+                ("Syriac_Letter_He" . #\u+0717)
+                ("Syriac_Letter_Waw" . #\u+0718)
+                ("Syriac_Letter_Zain" . #\u+0719)
+                ("Syriac_Letter_Heth" . #\u+071a)
+                ("Syriac_Letter_Teth" . #\u+071b)
+                ("Syriac_Letter_Teth_Garshuni" . #\u+071c)
+                ("Syriac_Letter_Yudh" . #\u+071d)
+                ("Syriac_Letter_Yudh_He" . #\u+071e)
+                ("Syriac_Letter_Kaph" . #\u+071f)
+                ("Syriac_Letter_Lamadh" . #\u+0720)
+                ("Syriac_Letter_Mim" . #\u+0721)
+                ("Syriac_Letter_Nun" . #\u+0722)
+                ("Syriac_Letter_Semkath" . #\u+0723)
+                ("Syriac_Letter_Final_Semkath" . #\u+0724)
+                ("Syriac_Letter_E" . #\u+0725)
+                ("Syriac_Letter_Pe" . #\u+0726)
+                ("Syriac_Letter_Reversed_Pe" . #\u+0727)
+                ("Syriac_Letter_Sadhe" . #\u+0728)
+                ("Syriac_Letter_Qaph" . #\u+0729)
+                ("Syriac_Letter_Rish" . #\u+072a)
+                ("Syriac_Letter_Shin" . #\u+072b)
+                ("Syriac_Letter_Taw" . #\u+072c)
+                ("Syriac_Letter_Persian_Bheth" . #\u+072d)
+                ("Syriac_Letter_Persian_Ghamal" . #\u+072e)
+                ("Syriac_Letter_Persian_Dhalath" . #\u+072f)
+                ("Syriac_Pthaha_Above" . #\u+0730)
+                ("Syriac_Pthaha_Below" . #\u+0731)
+                ("Syriac_Pthaha_Dotted" . #\u+0732)
+                ("Syriac_Zqapha_Above" . #\u+0733)
+                ("Syriac_Zqapha_Below" . #\u+0734)
+                ("Syriac_Zqapha_Dotted" . #\u+0735)
+                ("Syriac_Rbasa_Above" . #\u+0736)
+                ("Syriac_Rbasa_Below" . #\u+0737)
+                ("Syriac_Dotted_Zlama_Horizontal" . #\u+0738)
+                ("Syriac_Dotted_Zlama_Angular" . #\u+0739)
+                ("Syriac_Hbasa_Above" . #\u+073a)
+                ("Syriac_Hbasa_Below" . #\u+073b)
+                ("Syriac_Hbasa-Esasa_Dotted" . #\u+073c)
+                ("Syriac_Esasa_Above" . #\u+073d)
+                ("Syriac_Esasa_Below" . #\u+073e)
+                ("Syriac_Rwaha" . #\u+073f)
+                ("Syriac_Feminine_Dot" . #\u+0740)
+                ("Syriac_Qushshaya" . #\u+0741)
+                ("Syriac_Rukkakha" . #\u+0742)
+                ("Syriac_Two_Vertical_Dots_Above" . #\u+0743)
+                ("Syriac_Two_Vertical_Dots_Below" . #\u+0744)
+                ("Syriac_Three_Dots_Above" . #\u+0745)
+                ("Syriac_Three_Dots_Below" . #\u+0746)
+                ("Syriac_Oblique_Line_Above" . #\u+0747)
+                ("Syriac_Oblique_Line_Below" . #\u+0748)
+                ("Syriac_Music" . #\u+0749)
+                ("Syriac_Barrekh" . #\u+074a)
+                ("Syriac_Letter_Sogdian_Zhain" . #\u+074d)
+                ("Syriac_Letter_Sogdian_Khaph" . #\u+074e)
+                ("Syriac_Letter_Sogdian_Fe" . #\u+074f)
+                ("Arabic_Letter_Beh_With_Three_Dots_Horizontally_Below" . #\u+0750)
+                ("Arabic_Letter_Beh_With_Dot_Below_And_Three_Dots_Above" . #\u+0751)
+                ("Arabic_Letter_Beh_With_Three_Dots_Pointing_Upwards_Below" . #\u+0752)
+                ("Arabic_Letter_Beh_With_Three_Dots_Pointing_Upwards_Below_And_Two_Dots_Above" . #\u+0753)
+                ("Arabic_Letter_Beh_With_Two_Dots_Below_And_Dot_Above" . #\u+0754)
+                ("Arabic_Letter_Beh_With_Inverted_Small_V_Below" . #\u+0755)
+                ("Arabic_Letter_Beh_With_Small_V" . #\u+0756)
+                ("Arabic_Letter_Hah_With_Two_Dots_Above" . #\u+0757)
+                ("Arabic_Letter_Hah_With_Three_Dots_Pointing_Upwards_Below" . #\u+0758)
+                ("Arabic_Letter_Dal_With_Two_Dots_Vertically_Below_And_Small_Tah" . #\u+0759)
+                ("Arabic_Letter_Dal_With_Inverted_Small_V_Below" . #\u+075a)
+                ("Arabic_Letter_Reh_With_Stroke" . #\u+075b)
+                ("Arabic_Letter_Seen_With_Four_Dots_Above" . #\u+075c)
+                ("Arabic_Letter_Ain_With_Two_Dots_Above" . #\u+075d)
+                ("Arabic_Letter_Ain_With_Three_Dots_Pointing_Downwards_Above" . #\u+075e)
+                ("Arabic_Letter_Ain_With_Two_Dots_Vertically_Above" . #\u+075f)
+                ("Arabic_Letter_Feh_With_Two_Dots_Below" . #\u+0760)
+                ("Arabic_Letter_Feh_With_Three_Dots_Pointing_Upwards_Below" . #\u+0761)
+                ("Arabic_Letter_Keheh_With_Dot_Above" . #\u+0762)
+                ("Arabic_Letter_Keheh_With_Three_Dots_Above" . #\u+0763)
+                ("Arabic_Letter_Keheh_With_Three_Dots_Pointing_Upwards_Below" . #\u+0764)
+                ("Arabic_Letter_Meem_With_Dot_Above" . #\u+0765)
+                ("Arabic_Letter_Meem_With_Dot_Below" . #\u+0766)
+                ("Arabic_Letter_Noon_With_Two_Dots_Below" . #\u+0767)
+                ("Arabic_Letter_Noon_With_Small_Tah" . #\u+0768)
+                ("Arabic_Letter_Noon_With_Small_V" . #\u+0769)
+                ("Arabic_Letter_Lam_With_Bar" . #\u+076a)
+                ("Arabic_Letter_Reh_With_Two_Dots_Vertically_Above" . #\u+076b)
+                ("Arabic_Letter_Reh_With_Hamza_Above" . #\u+076c)
+                ("Arabic_Letter_Seen_With_Two_Dots_Vertically_Above" . #\u+076d)
+                ("Thaana_Letter_Haa" . #\u+0780)
+                ("Thaana_Letter_Shaviyani" . #\u+0781)
+                ("Thaana_Letter_Noonu" . #\u+0782)
+                ("Thaana_Letter_Raa" . #\u+0783)
+                ("Thaana_Letter_Baa" . #\u+0784)
+                ("Thaana_Letter_Lhaviyani" . #\u+0785)
+                ("Thaana_Letter_Kaafu" . #\u+0786)
+                ("Thaana_Letter_Alifu" . #\u+0787)
+                ("Thaana_Letter_Vaavu" . #\u+0788)
+                ("Thaana_Letter_Meemu" . #\u+0789)
+                ("Thaana_Letter_Faafu" . #\u+078a)
+                ("Thaana_Letter_Dhaalu" . #\u+078b)
+                ("Thaana_Letter_Thaa" . #\u+078c)
+                ("Thaana_Letter_Laamu" . #\u+078d)
+                ("Thaana_Letter_Gaafu" . #\u+078e)
+                ("Thaana_Letter_Gnaviyani" . #\u+078f)
+                ("Thaana_Letter_Seenu" . #\u+0790)
+                ("Thaana_Letter_Daviyani" . #\u+0791)
+                ("Thaana_Letter_Zaviyani" . #\u+0792)
+                ("Thaana_Letter_Taviyani" . #\u+0793)
+                ("Thaana_Letter_Yaa" . #\u+0794)
+                ("Thaana_Letter_Paviyani" . #\u+0795)
+                ("Thaana_Letter_Javiyani" . #\u+0796)
+                ("Thaana_Letter_Chaviyani" . #\u+0797)
+                ("Thaana_Letter_Ttaa" . #\u+0798)
+                ("Thaana_Letter_Hhaa" . #\u+0799)
+                ("Thaana_Letter_Khaa" . #\u+079a)
+                ("Thaana_Letter_Thaalu" . #\u+079b)
+                ("Thaana_Letter_Zaa" . #\u+079c)
+                ("Thaana_Letter_Sheenu" . #\u+079d)
+                ("Thaana_Letter_Saadhu" . #\u+079e)
+                ("Thaana_Letter_Daadhu" . #\u+079f)
+                ("Thaana_Letter_To" . #\u+07a0)
+                ("Thaana_Letter_Zo" . #\u+07a1)
+                ("Thaana_Letter_Ainu" . #\u+07a2)
+                ("Thaana_Letter_Ghainu" . #\u+07a3)
+                ("Thaana_Letter_Qaafu" . #\u+07a4)
+                ("Thaana_Letter_Waavu" . #\u+07a5)
+                ("Thaana_Abafili" . #\u+07a6)
+                ("Thaana_Aabaafili" . #\u+07a7)
+                ("Thaana_Ibifili" . #\u+07a8)
+                ("Thaana_Eebeefili" . #\u+07a9)
+                ("Thaana_Ubufili" . #\u+07aa)
+                ("Thaana_Ooboofili" . #\u+07ab)
+                ("Thaana_Ebefili" . #\u+07ac)
+                ("Thaana_Eybeyfili" . #\u+07ad)
+                ("Thaana_Obofili" . #\u+07ae)
+                ("Thaana_Oaboafili" . #\u+07af)
+                ("Thaana_Sukun" . #\u+07b0)
+                ("Thaana_Letter_Naa" . #\u+07b1)
+                ("Nko_Digit_Zero" . #\u+07c0)
+                ("Nko_Digit_One" . #\u+07c1)
+                ("Nko_Digit_Two" . #\u+07c2)
+                ("Nko_Digit_Three" . #\u+07c3)
+                ("Nko_Digit_Four" . #\u+07c4)
+                ("Nko_Digit_Five" . #\u+07c5)
+                ("Nko_Digit_Six" . #\u+07c6)
+                ("Nko_Digit_Seven" . #\u+07c7)
+                ("Nko_Digit_Eight" . #\u+07c8)
+                ("Nko_Digit_Nine" . #\u+07c9)
+                ("Nko_Letter_A" . #\u+07ca)
+                ("Nko_Letter_Ee" . #\u+07cb)
+                ("Nko_Letter_I" . #\u+07cc)
+                ("Nko_Letter_E" . #\u+07cd)
+                ("Nko_Letter_U" . #\u+07ce)
+                ("Nko_Letter_Oo" . #\u+07cf)
+                ("Nko_Letter_O" . #\u+07d0)
+                ("Nko_Letter_Dagbasinna" . #\u+07d1)
+                ("Nko_Letter_N" . #\u+07d2)
+                ("Nko_Letter_Ba" . #\u+07d3)
+                ("Nko_Letter_Pa" . #\u+07d4)
+                ("Nko_Letter_Ta" . #\u+07d5)
+                ("Nko_Letter_Ja" . #\u+07d6)
+                ("Nko_Letter_Cha" . #\u+07d7)
+                ("Nko_Letter_Da" . #\u+07d8)
+                ("Nko_Letter_Ra" . #\u+07d9)
+                ("Nko_Letter_Rra" . #\u+07da)
+                ("Nko_Letter_Sa" . #\u+07db)
+                ("Nko_Letter_Gba" . #\u+07dc)
+                ("Nko_Letter_Fa" . #\u+07dd)
+                ("Nko_Letter_Ka" . #\u+07de)
+                ("Nko_Letter_La" . #\u+07df)
+                ("Nko_Letter_Na_Woloso" . #\u+07e0)
+                ("Nko_Letter_Ma" . #\u+07e1)
+                ("Nko_Letter_Nya" . #\u+07e2)
+                ("Nko_Letter_Na" . #\u+07e3)
+                ("Nko_Letter_Ha" . #\u+07e4)
+                ("Nko_Letter_Wa" . #\u+07e5)
+                ("Nko_Letter_Ya" . #\u+07e6)
+                ("Nko_Letter_Nya_Woloso" . #\u+07e7)
+                ("Nko_Letter_Jona_Ja" . #\u+07e8)
+                ("Nko_Letter_Jona_Cha" . #\u+07e9)
+                ("Nko_Letter_Jona_Ra" . #\u+07ea)
+                ("Nko_Combining_Short_High_Tone" . #\u+07eb)
+                ("Nko_Combining_Short_Low_Tone" . #\u+07ec)
+                ("Nko_Combining_Short_Rising_Tone" . #\u+07ed)
+                ("Nko_Combining_Long_Descending_Tone" . #\u+07ee)
+                ("Nko_Combining_Long_High_Tone" . #\u+07ef)
+                ("Nko_Combining_Long_Low_Tone" . #\u+07f0)
+                ("Nko_Combining_Long_Rising_Tone" . #\u+07f1)
+                ("Nko_Combining_Nasalization_Mark" . #\u+07f2)
+                ("Nko_Combining_Double_Dot_Above" . #\u+07f3)
+                ("Nko_High_Tone_Apostrophe" . #\u+07f4)
+                ("Nko_Low_Tone_Apostrophe" . #\u+07f5)
+                ("Nko_Symbol_Oo_Dennen" . #\u+07f6)
+                ("Nko_Symbol_Gbakurunen" . #\u+07f7)
+                ("Nko_Comma" . #\u+07f8)
+                ("Nko_Exclamation_Mark" . #\u+07f9)
+                ("Nko_Lajanyalan" . #\u+07fa)
+                ("Line_Separator" . #\u+2028)
+                ("Paragraph_Separator" . #\u+2029)
+                ("Replacement_Character" . #\u+fffd)
+                ("Skull_And_Crossbones" . #\u+2620)))
+  (destructuring-bind (name . char) pair
+    (register-character-name name char)))
+
+
+
+;;;(NAME-CHAR name)
+;;;If name has an entry in the *NAME->CHAR*, return first such entry.
+;;;Otherwise, if it consists of one char, return it.
+;;;Otherwise, if it consists of two chars, the first of which  is ^,
+;;; return %code-char(c xor 64), where c is the uppercased second char.
+;;;Otherwise, if it starts with the prefix "u+" or "U+" followed by
+;;; hex digits, the number denoted by those hex digits is interpreted as the
+;;; unicode code of the character; if this value is less than
+;;; CHAR-CODE-LIMIT, CODE-CHAR of that value is returned.
+;;;Otherwise, if it consists of octal digits, the number denoted by
+;;;  those octal digits is interpreted as per the U+ case above.
+;;;Otherwise return NIL.
+
+
+(defun name-char (name)
+  "Given an argument acceptable to STRING, NAME-CHAR returns a character
+  whose name is that string, if one exists. Otherwise, NIL is returned."
+  (if (characterp name)
+    name
+    (let* ((name (string name)))
+      (let* ((namelen (length name)))
+        (declare (fixnum namelen))
+        (or (gethash name *name->char*)
+            (if (= namelen 1)
+              (char name 0)
+              (if (and (= namelen 2) (eq (char name 0) #\^))
+                (let* ((c1 (char-code (char-upcase (char name 1)))))
+                  (if (and (>= c1 64) (< c1 96))
+                    (code-char (the fixnum (logxor (the fixnum c1) #x40)))))
+                (let* ((n 0)
+                       (start 1))
+                  (declare (fixnum start))
+                  (or
+                   (if (and (> namelen 1)
+                            (or (eql (char name 0) #\U)
+                                (eql (char name 0) #\u))
+                            (or (= namelen 2)
+                                (progn
+                                  (when (eql (char name 1) #\+)
+                                    (incf start))
+                                  t)))
+                     (do* ((i start (1+ i)))
+                          ((= i namelen) (if (< n char-code-limit)
+                                           (code-char n)))
+                       (declare (fixnum i))
+                       (let* ((pos (position (char-upcase (char name i))
+                                             "0123456789ABCDEF")))
+                         (if pos
+                           (setq n (logior (ash n 4) pos))
+                           (progn
+                             (setq n 0)
+                             (return))))))
+                   (dotimes (i namelen (if (< n char-code-limit)
+                                         (code-char n)))
+                     (let* ((code (the fixnum (- (the fixnum (char-code (char name i)))
+                                                 (char-code #\0)))))
+                       (declare (fixnum code))
+                       (if (and (>= code 0)
+                                (<= code 7))
+                         (setq n (logior code (the fixnum (ash n 3))))
+                         (return)))))))))))))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defconstant wsp #.(let ((str (make-string 6  :element-type 'base-char)))
+                      (set-schar str 0 #\Space)
+                      (set-schar str 1 #\^I)
+                      (set-schar str 2 #\^L)
+                      (set-schar str 3 #\^@)
+                      (set-schar str 4 #\^J)
+                      (set-schar str 5 (code-char #xa0))
+                      str))
+
+(defconstant wsp&cr #.(let ((str (make-string 7 :element-type 'base-char)))
+                        (set-schar str 0 #\Space)
+                        (set-schar str 1 #\^M)
+                        (set-schar str 2 #\^I)
+                        (set-schar str 3 #\^L)
+                        (set-schar str 4 #\^@)
+                        (set-schar str 5 #\^J)
+                        (set-schar str 0 #\Space)
+                        (set-schar str 6 (code-char #xa0))
+                        str))
+)
+
+(defun whitespacep (char)
+  (eql $cht_wsp (%character-attribute char (rdtab.ttab *readtable*))))
+	   
+	 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;			Readtables					;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Readtable = istructure with data [1] type-table and [2] macro-char-alist
+;;; Type-table is a 256 byte ivector with a type byte for each char.
+;;; macro-char-alist is a list of (char . defn).  The defn is either a
+;;; cons of (#'read-dispatch . macro-char-alist) for
+;;; dispatch macros, or it is a function or a symbol to call for simple macros.
+
+(defun readtablep (object) (istruct-typep object 'readtable)) 
+
+(defun readtable-arg (object)
+  (if (null object) (setq object *readtable*))
+  (unless (istruct-typep object 'readtable)
+    (report-bad-arg object 'readtable))
+  object)
+
+(eval-when (:compile-toplevel :execute)
+(def-accessors %svref
+  token.string
+  token.ipos
+  token.opos
+  token.len
+)
+
+(defmacro with-token-buffer ((name) &body body &environment env)
+  (multiple-value-bind (body decls) (parse-body body env nil)
+    `(let* ((,name (vector (%get-token-string 16) 0 0 16 nil)))
+       (declare (dynamic-extent ,name))
+       (unwind-protect
+         (locally ,@decls ,@body)
+         (%return-token-string ,name)))))
+)
+
+(defun read-dispatch (stream char)
+  (let* ((info (cdr (assq char (rdtab.alist *readtable*)))))
+    (with-token-buffer (tb)
+      (let* ((subchar nil)
+             (numarg nil))
+        (loop
+            (if (digit-char-p (setq subchar (%read-char-no-eof stream)))
+                (%add-char-to-token subchar tb)
+                (return (setq subchar (char-upcase subchar) 
+                              numarg (%token-to-number tb 10)))))
+        (let* ((dispfun (cdr (assq subchar (cdr info)))))     ; <== WAS char
+          (if dispfun
+              (funcall dispfun stream subchar numarg)
+              (signal-reader-error stream "Undefined character ~S in a ~S dispatch macro." subchar char)))))))
+
+;;; This -really- gets initialized later in the file
+(defvar %standard-readtable%
+  (let* ((ttab (make-array 256 :element-type '(unsigned-byte 8)))
+         (macs `((#\# . (,#'read-dispatch))))
+         (case :upcase))
+    (dotimes (i 256) (declare (fixnum i))(uvset ttab i $cht_cnst))
+    (dotimes (ch (1+ (char-code #\Space)))
+      (uvset ttab ch $cht_wsp))
+    (uvset ttab #xa0 $cht_wsp)
+    (uvset ttab (char-code #\\) $cht_sesc)
+    (uvset ttab (char-code #\|) $cht_mesc)
+    (uvset ttab (char-code #\#) $cht_ntmac)
+    (uvset ttab (char-code #\Backspace) $cht_ill)
+    (uvset ttab (char-code #\Rubout) $cht_ill)
+    (%istruct 'readtable ttab macs case)))
+
+(defvar %initial-readtable%)
+(setq *readtable* %standard-readtable%)
+(def-standard-initial-binding *readtable* )
+(queue-fixup (setq %initial-readtable% (copy-readtable *readtable*)))
+
+(defun copy-readtable (&optional (from *readtable*) to)
+  (setq from (if from (readtable-arg from)  %standard-readtable%))
+  (setq to (if to 
+             (readtable-arg to)
+             (%istruct 'readtable
+                        (make-array 256 :element-type '(unsigned-byte 8))
+                         nil (rdtab.case from))))
+  (setf (rdtab.alist to) (copy-tree (rdtab.alist from)))
+  (setf (rdtab.case to) (rdtab.case from))
+  (let* ((fttab (rdtab.ttab from))
+         (tttab (rdtab.ttab to)))
+    (%copy-ivector-to-ivector fttab 0 tttab 0 256))
+  to)
+
+(declaim (inline %character-attribute))
+
+(defun %character-attribute (char attrtab)
+  (declare (character char)
+           (type (simple-array (unsigned-byte 8) (256)) attrtab)
+           (optimize (speed 3) (safety 0)))
+  (let* ((code (char-code char)))
+    (declare (fixnum code))
+    (if (< code 256)
+      (aref attrtab code)
+      ;; Should probably have an extension mechanism for things
+      ;; like NBS.
+      $cht_cnst)))
+
+;;; returns: (values attrib <aux-info>), where
+;;;           <aux-info> = (char . fn), if terminating macro
+;;;                      = (char . (fn . dispatch-alist)), if dispatching macro
+;;;                      = nil otherwise
+
+
+(defun %get-readtable-char (char &optional (readtable *readtable*))
+  (setq char (require-type char 'character))
+  (let* ((attr (%character-attribute char (rdtab.ttab readtable))))
+    (declare (fixnum attr))
+    (values attr (if (logbitp $cht_macbit attr) (assoc char (rdtab.alist readtable))))))
+
+
+(defun set-syntax-from-char (to-char from-char &optional to-readtable from-readtable)
+  "Causes the syntax of TO-CHAR to be the same as FROM-CHAR in the
+  optional readtable (defaults to the current readtable). The
+  FROM-TABLE defaults to the standard Lisp readtable when NIL."
+  (setq to-char (require-type to-char 'base-char))
+  (setq from-char (require-type from-char 'base-char))
+  (setq to-readtable (readtable-arg to-readtable))
+  (setq from-readtable (readtable-arg (or from-readtable %initial-readtable%)))
+  (multiple-value-bind (from-attr from-info) (%get-readtable-char from-char from-readtable)
+    (let* ((new-tree (copy-tree (cdr from-info)))
+           (old-to-info (nth-value 1 (%get-readtable-char to-char to-readtable))))
+      (without-interrupts
+       (if from-info
+         (if old-to-info
+           (setf (cdr old-to-info) new-tree)
+           (push (cons to-char new-tree) (rdtab.alist to-readtable)))
+         (if old-to-info
+           (setf (rdtab.alist to-readtable) (delq old-to-info (rdtab.alist to-readtable)))))
+       (if (and (= from-attr $cht_cnst)
+                (member to-char '(#\Newline #\Linefeed #\Page #\Return
+                                  #\Space #\Tab #\Backspace #\Rubout)))
+           (setf (uvref (rdtab.ttab to-readtable) (char-code to-char)) $cht_ill)
+           (setf (uvref (rdtab.ttab to-readtable) (char-code to-char)) from-attr)))
+      t)))
+
+(defun get-macro-character (char &optional readtable)
+  "Return the function associated with the specified CHAR which is a macro
+  character, or NIL if there is no such function. As a second value, return
+  T if CHAR is a macro character which is non-terminating, i.e. which can
+  be embedded in a symbol name."
+  (setq readtable (readtable-arg readtable))
+  (multiple-value-bind (attr info) (%get-readtable-char char readtable)
+    (declare (fixnum attr) (list info))
+    (let* ((def (cdr info)))
+      (values (if (consp def) (car def) def)
+              (= attr $cht_ntmac)))))
+
+(defun set-macro-character (char fn &optional non-terminating-p readtable)
+  "Causes CHAR to be a macro character which invokes FUNCTION when seen
+   by the reader. The NON-TERMINATINGP flag can be used to make the macro
+   character non-terminating, i.e. embeddable in a symbol name."
+  (setq char (require-type char 'base-char))
+  (setq readtable (readtable-arg readtable))
+  (when fn
+    (unless (or (symbolp fn) (functionp fn))
+      (setq fn (require-type fn '(or symbol function)))))
+  (let* ((info (nth-value 1 (%get-readtable-char char readtable))))
+    (declare (list info))
+    (without-interrupts
+     (setf (uvref (rdtab.ttab readtable) (char-code char))
+           (if (null fn) $cht_cnst (if non-terminating-p $cht_ntmac $cht_tmac)))
+     (if (and (null fn) info)
+       (setf (rdtab.alist readtable) (delete info (rdtab.alist readtable) :test #'eq)) 
+       (if (null info)
+         (push (cons char fn) (rdtab.alist readtable))
+         (let* ((def (cdr info)))
+           (if (atom def)
+             (setf (cdr info) fn)         ; Non-dispatching
+             (setf (car def) fn))))))     ; Dispatching
+    t))
+
+(defun readtable-case (readtable)
+  (unless (istruct-typep readtable 'readtable)
+    (report-bad-arg readtable 'readtable))
+  (let* ((case (rdtab.case (readtable-arg readtable))))
+    (if (symbolp case)
+      case
+      (%car (rassoc case (readtable-case-keywords) :test #'eq)))))
+
+(defun %set-readtable-case (readtable case)
+  (unless (istruct-typep readtable 'readtable)
+    (report-bad-arg readtable 'readtable))
+  (check-type case (member :upcase :downcase :preserve :invert))
+  (setf (rdtab.case (readtable-arg readtable)) case))
+  
+(defsetf readtable-case %set-readtable-case)
+
+(defun make-dispatch-macro-character (char &optional non-terminating-p readtable)
+  "Cause CHAR to become a dispatching macro character in readtable (which
+   defaults to the current readtable). If NON-TERMINATING-P, the char will
+   be non-terminating."
+  (setq readtable (readtable-arg readtable))
+  (setq char (require-type char 'base-char))
+  (let* ((info (nth-value 1 (%get-readtable-char char readtable))))
+    (declare (list info))
+    (without-interrupts
+     (setf (uvref (rdtab.ttab readtable) (char-code char))
+           (if non-terminating-p $cht_ntmac $cht_tmac))
+     (if info
+       (rplacd (cdr info) nil)
+       (push (cons char (cons #'read-dispatch nil)) (rdtab.alist readtable)))))
+  t)
+
+(defun get-dispatch-macro-character (disp-ch sub-ch &optional (readtable *readtable*))
+  "Return the macro character function for SUB-CHAR under DISP-CHAR
+   or NIL if there is no associated function."
+  (setq readtable (readtable-arg (or readtable %initial-readtable%)))
+  (setq disp-ch (require-type disp-ch 'base-char))
+  (setq sub-ch (char-upcase (require-type sub-ch 'base-char)))
+  (unless (digit-char-p sub-ch 10)
+    (let* ((def (cdr (nth-value 1 (%get-readtable-char disp-ch readtable)))))
+      (if (consp def)
+        (cdr (assq sub-ch (cdr def)))
+        (error "~A is not a dispatching macro character in ~s ." disp-ch readtable)))))
+
+(defun set-dispatch-macro-character (disp-ch sub-ch fn &optional readtable)
+  "Cause FUNCTION to be called whenever the reader reads DISP-CHAR
+   followed by SUB-CHAR."
+  (setq readtable (readtable-arg readtable))
+  (setq disp-ch (require-type disp-ch 'base-char))
+  (setq sub-ch (char-upcase (require-type sub-ch 'base-char)))
+  (when (digit-char-p sub-ch 10)
+    (error "subchar can't be a decimal digit - ~a ." sub-ch))
+  (let* ((info (nth-value 1 (%get-readtable-char disp-ch readtable)))
+         (def (cdr info)))
+    (declare (list info))
+    (unless (consp def)
+      (error "~A is not a dispatching macro character in ~s ." disp-ch readtable))
+    (let* ((alist (cdr def))
+           (pair (assq sub-ch alist)))
+      (if pair
+        (setf (cdr pair) fn)
+        (push (cons sub-ch fn) (cdr def))))
+    t))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;				Reader					;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar *read-eval* t "When nil, #. signals an error.")
+(defvar %read-objects% nil)
+(defvar %keep-whitespace% nil)
+
+
+
+
+(def-standard-initial-binding %token-strings% (%cons-pool nil))
+
+
+(defun %return-token-string (token)
+  (let* ((str (token.string token))
+         (pool %token-strings%))
+    (setf (token.string token) nil)
+    (without-interrupts
+     (setf (pool.data pool)
+           (cheap-cons str (pool.data pool))))))
+
+;;;Look for an exact match, else create a simple-string.
+(defun %get-token-string (len)
+  (declare (fixnum len))
+  (without-interrupts
+   (do* ((pool %token-strings%)
+         (head (cons nil (pool.data pool)))
+         (prev head next)
+         (next (cdr prev) (cdr next)))
+        ((null next)
+         (make-string len :element-type 'base-char))
+     (declare (dynamic-extent head)
+              (list head prev next))
+     (let* ((s (car next)))
+       (when (= len (length s))
+         (rplacd prev (cdr next))
+         (setf (pool.data pool) (cdr head))
+         (free-cons next)
+         (return s))))))
+
+(defun %extend-token-string (token)
+  (let* ((old-string (token.string token))
+         (old-length (token.len token)))
+    (declare (fixnum old-length))
+    (let* ((new-length (the fixnum (ash old-length 1)))
+           (new-string (%get-token-string new-length)))
+      (dotimes (i old-length)
+        (setf (%schar new-string i)
+              (%schar old-string i)))
+      (%return-token-string token)
+      (setf (token.string token) new-string
+            (token.len token) new-length)
+      token)))
+
+(defun %add-char-to-token (char token)
+  (let* ((len (token.len token))
+         (opos (token.opos token)))
+    (declare (fixnum len opos))
+    (when (= opos len)
+      (%extend-token-string token))
+    (setf (token.opos token) (the fixnum (1+ opos))
+          (%schar (token.string token) opos) char)))
+
+(defun %string-from-token (token)
+  (let* ((opos (token.opos token))
+         (ipos (token.ipos token))
+         (tstr (token.string token))
+         (len (the fixnum (- opos ipos)))
+         (string (make-string len :element-type 'base-char)))
+    (do* ((k 0 (1+ k))
+          (i ipos (1+ i)))
+         ((= i opos) string)
+      (declare (fixnum i k))
+      (setf (%schar string k) (%schar tstr i)))))
+
+(defun %next-token-char (token)
+  (let* ((ipos (token.ipos token)))
+    (declare (fixnum ipos))
+    (when (< ipos (the fixnum (token.opos token)))
+      (setf (token.ipos token) (the fixnum (1+ ipos)))
+      (%schar (token.string token) ipos))))
+      
+(defun input-stream-arg (stream)
+  (cond ((null stream) *standard-input*)
+        ((eq stream t) *terminal-io*)
+        ;Otherwise, let ASK complain...
+        (t stream)))
+
+(defun %read-char-no-eof (stream)
+  (read-char stream))
+
+(defun %next-char-and-attr (stream &optional (attrtab (rdtab.ttab *readtable*)))
+  (let* ((ch (read-char stream nil :eof)))
+    (if (eq ch :eof)
+      (values nil nil)
+      (values ch (%character-attribute ch attrtab)))))
+
+(defun %next-non-whitespace-char-and-attr (stream)
+  (let* ((attrtab (rdtab.ttab *readtable*)))
+    (loop
+      (multiple-value-bind (ch attr) (%next-char-and-attr stream attrtab)
+        (if (null ch)
+          (return (values nil nil))
+          (unless (eql attr $cht_wsp)
+            (return (values ch attr))))))))
+
+(defun %next-char-and-attr-no-eof (stream &optional (attrtab (rdtab.ttab *readtable*)))
+  (let* ((ch (%read-char-no-eof stream)))
+    (values ch (%character-attribute ch attrtab))))
+
+(defun %next-non-whitespace-char-and-attr-no-eof (stream)
+  (let* ((attrtab (rdtab.ttab *readtable*)))
+    (loop
+      (multiple-value-bind (ch attr) (%next-char-and-attr-no-eof stream attrtab)
+        (declare (fixnum attr))
+        (unless (= attr $cht_wsp)
+          (return (values ch attr)))))))
+
+;;; "escapes" is a list of escaped character positions, in reverse order
+(defun %casify-token (token escapes)
+  (let* ((case (readtable-case *readtable*))
+         (opos (token.opos token))
+         (string (token.string token)))
+    (declare (fixnum opos))
+    (if (and (null escapes) (eq case :upcase))          ; Most common case, pardon the pun
+      ; %strup is faster - boot probs tho
+      (dotimes (i opos)
+        (setf (%schar string i) (char-upcase (%schar string i))))
+      (unless (eq case :preserve)
+        (when (eq case :invert)
+          (let* ((lower-seen nil)
+                 (upper-seen nil))
+            (do* ((i (1- opos) (1- i))
+                  (esclist escapes)
+                  (nextesc (if esclist (pop esclist) -1)))
+                 ((< i 0) (if upper-seen (unless lower-seen (setq case :downcase))
+                                         (when lower-seen (setq case :upcase))))
+              (declare (fixnum i nextesc))
+              (if (= nextesc i)
+                (setq nextesc (if esclist (pop esclist) -1))
+                (let* ((ch (%schar string i)))
+                  (if (upper-case-p ch)
+                    (setq upper-seen t)
+                    (if (lower-case-p ch)
+                      (setq lower-seen t))))))))
+        (if (eq case :upcase)
+          (do* ((i (1- opos) (1- i))
+                  (nextesc (if escapes (pop escapes) -1)))
+               ((< i 0))
+            (declare (fixnum i nextesc))
+            (if (= nextesc i)
+                (setq nextesc (if escapes (pop escapes) -1))
+                (setf (%schar string i) (char-upcase (%schar string i)))))
+          (if (eq case :downcase)
+            (do* ((i (1- opos) (1- i))
+                  (nextesc (if escapes (pop escapes) -1)))
+               ((< i 0))
+            (declare (fixnum i nextesc))
+            (if (= nextesc i)
+                (setq nextesc (if escapes (pop escapes) -1))
+                (setf (%schar string i) (char-downcase (%schar string i)))))))))))
+
+;;; MCL's reader has historically treated ||:foo as a reference to the
+;;; symbol FOO in the package which has the null string as its name.
+;;; Some other implementations treat it as a keyword.  This takes an
+;;; argument indicating whether or not something was "seen" before the
+;;; first colon was read, even if that thing caused no characters to
+;;; be added to the token.
+
+(defun %token-package (token colonpos seenbeforecolon stream)
+  (if colonpos
+    (if (and (eql colonpos 0) (not seenbeforecolon))
+      *keyword-package*
+      (let* ((string (token.string token)))
+        (or (%find-pkg string colonpos)
+            (signal-reader-error stream "Reference to unknown package ~s." (subseq string 0 colonpos)))))
+    *package*))
+
+;;; Returns 4 values: reversed list of escaped character positions,
+;;; explicit package (if unescaped ":" or "::") or nil, t iff any
+;;; non-dot, non-escaped chars in token, and t if either no explicit
+;;; package or "::"
+
+(defun %collect-xtoken (token stream 1stchar)
+  (let* ((escapes ())
+         (nondots nil)
+         (explicit-package *read-suppress*)
+         (double-colon t)
+         (multi-escaped nil))
+    (do* ((attrtab (rdtab.ttab *readtable*))
+          (char 1stchar (read-char stream nil :eof )))
+         ((eq char :eof))
+      (flet ((add-note-escape-pos (char token escapes)
+               (push (token.opos token) escapes)
+               (%add-char-to-token char token)
+               escapes))
+        (let* ((attr (%character-attribute char attrtab)))
+          (declare (fixnum attr))
+          (when (or (= attr $cht_tmac)
+                    (= attr $cht_wsp))
+            (when (or (not (= attr $cht_wsp)) %keep-whitespace%)
+              (unread-char char stream))
+            (return ))
+          (if (= attr $cht_ill)
+              (signal-reader-error stream "Illegal character ~S." char)
+              (if (= attr $cht_sesc)
+                  (setq nondots t 
+                        escapes (add-note-escape-pos (%read-char-no-eof stream) token escapes))
+                  (if (= attr $cht_mesc)
+                      (progn 
+                        (setq nondots t)
+                        (loop
+                            (multiple-value-bind (nextchar nextattr) (%next-char-and-attr-no-eof stream attrtab)
+                              (declare (fixnum nextattr))
+                              (if (= nextattr $cht_mesc) 
+                                  (return (setq multi-escaped t))
+                                  (if (= nextattr $cht_sesc)
+                                      (setq escapes (add-note-escape-pos (%read-char-no-eof stream) token escapes))
+                            (setq escapes (add-note-escape-pos nextchar token escapes)))))))
+                  (let* ((opos (token.opos token)))         ; Add char to token, note 1st colonpos
+                    (declare (fixnum opos))
+                    (if (and (eq char #\:)       ; (package-delimiter-p char ?)
+                             (not explicit-package))
+                      (let* ((nextch (%read-char-no-eof stream)))
+                        (if (eq nextch #\:)
+                          (setq double-colon t)
+                          (progn
+			    (unread-char nextch stream)
+                            (setq double-colon nil)))
+                        (%casify-token token escapes)
+                        (setq explicit-package (%token-package token opos nondots stream)
+                              nondots t
+                              escapes nil)
+                        (setf (token.opos token) 0))
+                      (progn
+                        (unless (eq char #\.) (setq nondots t))
+                        (%add-char-to-token char token))))))))))
+        (values (or escapes multi-escaped) (if *read-suppress* nil explicit-package) nondots double-colon)))
+          
+(defun %validate-radix (radix)
+  (if (and (typep radix 'fixnum)
+           (>= (the fixnum radix) 2)
+           (<= (the fixnum radix) 36))
+    radix
+    (progn
+      (check-type radix (integer 2 36))
+      radix)))
+
+(defun %token-to-number (token radix &optional no-rat)
+  (new-numtoken (token.string token) (token.ipos token) (token.opos token) radix no-rat))
+
+;;; If we're allowed to have a single "." in this context, DOT-OK is some distinguished
+;;; value that's returned to the caller when exactly one dot is present.
+(defun %parse-token (stream firstchar dot-ok)
+  (with-token-buffer (tb)
+    (multiple-value-bind (escapes explicit-package nondots double-colon) (%collect-xtoken tb stream firstchar)
+      (unless *read-suppress* 
+        (let* ((string (token.string tb))
+               (len (token.opos tb)))
+          (declare (fixnum len))
+          (if (not nondots)
+            (if (= len 1)
+              (or dot-ok
+                  (signal-reader-error stream "Dot context error in ~s." (%string-from-token tb)))
+              (signal-reader-error stream "Illegal symbol syntax in ~s." (%string-from-token tb)))
+            ;; Something other than a buffer full of dots.  Thank god.
+            (let* ((num (if (null escapes)
+                            (handler-case
+                                (%token-to-number tb (%validate-radix *read-base*))
+                              (arithmetic-error (c)
+                                (error 'impossible-number
+                                       :stream stream
+                                       :token (%string-from-token tb)
+                                       :condition c))))))
+              (if (and num (not explicit-package))
+                num
+                (if (and (zerop len) (null escapes))
+                  (%err-disp $XBADSYM)
+                  (progn                  ; Muck with readtable case of extended token.
+                    (%casify-token tb (unless (atom escapes) escapes))
+                    (let* ((pkg (or explicit-package *package*)))
+                      (if (or double-colon (eq pkg *keyword-package*))
+                        (without-interrupts
+                         (multiple-value-bind (symbol access internal-offset external-offset)
+                                              (%find-symbol string len pkg)
+                           (if access
+                             symbol
+                             (%add-symbol (%string-from-token tb) pkg internal-offset external-offset))))
+                        (multiple-value-bind (found symbol) (%get-htab-symbol string len (pkg.etab pkg))
+                          (if found
+                            symbol
+                            (let* ((token (%string-from-token tb))
+                                   (symbol (find-symbol token pkg)))
+                              (with-simple-restart (continue
+                                                    "~:[Create and use the internal symbol ~a::~a~;Use the internal symbol ~:*~s~]"
+                                                    symbol (package-name pkg) token)
+                                (%err-disp $XNOESYM token pkg))
+                              (or symbol (intern token pkg)))))))))))))))))
+                    
+#|
+(defun %parse-token-test (string &key dot-ok (case (readtable-case *readtable*)))
+  (let* ((stream (make-string-input-stream string))
+         (oldcase (readtable-case *readtable*)))
+    (unwind-protect
+      (progn
+        (setf (readtable-case *readtable*) case) 
+        (%parse-token stream (read-char stream t) dot-ok))
+      (setf (readtable-case *readtable*) oldcase))))
+
+(%parse-token-test "ABC")
+(%parse-token-test "TRAPS::_DEBUGGER")
+(%parse-token-test "3.14159")
+(ignore-errors (%parse-token-test "BAD-PACKAGE:WORSE-SYMBOL"))
+(ignore-errors (%parse-token-test "CCL::"))
+(%parse-token-test "TRAPS::_debugger" :case :preserve)
+(%parse-token-test ":foo")
+|#
+
+;;; firstchar must not be whitespace.
+;;; People who think that there's so much overhead in all of
+;;; this (multiple-value-list, etc.) should probably consider
+;;; rewriting those parts of the CLOS and I/O code that make
+;;; using things like READ-CHAR impractical...
+
+;;; mb: the reason multiple-value-list is used here is that we need to distunguish between the
+;;; recursive parse call returning (values nil) and (values).
+(defun %parse-expression (stream firstchar dot-ok)
+  (let* ((readtable *readtable*)
+         (attrtab (rdtab.ttab readtable))
+         (attr (%character-attribute firstchar attrtab))
+         (start-pos (stream-position stream)))
+    (declare (fixnum attr))
+    (when (eql attr $cht_ill)
+      (signal-reader-error stream "Illegal character ~S." firstchar))
+    (let* ((vals (multiple-value-list 
+                     (if (not (logbitp $cht_macbit attr))
+                       (%parse-token stream firstchar dot-ok)
+                       (let* ((def (cdr (assq firstchar (rdtab.alist readtable)))))
+                         (cond ((null def))
+                               ((atom def)
+                                (funcall def stream firstchar))
+                               #+no     ; include if %initial-readtable% broken (see above)
+                               ((and (consp (car def))
+                                     (eq (caar def) 'function))
+                                (funcall (cadar def) stream firstchar))
+                               ((functionp (car def))
+                                (funcall (car def) stream firstchar))
+                               (t (error "Bogus default dispatch fn: ~S" (car def)) nil))))))
+           (end-pos (and start-pos (stream-position stream))))
+      (declare (dynamic-extent vals)
+               (list vals))
+      (if (null vals)
+        (values nil nil)
+        (destructuring-bind (form &optional nested-source-notes)
+                            vals
+          ;; Can't really trust random reader macros to return source notes...
+          (unless (and (consp nested-source-notes)
+                       (source-note-p (car nested-source-notes)))
+            (setq nested-source-notes nil))
+          (values form
+                  t
+                  (and start-pos
+                       (record-source-note :form form
+                                           :stream stream
+                                           :start-pos (1- start-pos)
+                                           :end-pos end-pos
+                                           :subform-notes nested-source-notes))))))))
+
+#|
+(defun %parse-expression-test (string)
+  (let* ((stream (make-string-input-stream string)))
+    (%parse-expression stream (read-char stream t) nil)))
+
+(%parse-expression-test ";hello")
+(%parse-expression-test "#'cdr")
+(%parse-expression-test "#+foo 1 2")
+
+|#
+
+(defun %read-list-expression (stream dot-ok &optional (termch #\)))
+  (loop
+      (let* ((firstch (%next-non-whitespace-char-and-attr-no-eof stream)))
+        (if (eq firstch termch)
+            (return (values nil nil nil))
+            (multiple-value-bind (val val-p source-info)
+                (%parse-expression stream firstch dot-ok)
+              (if val-p
+                  (return (values val t source-info))))))))
+
+(defun read-list (stream &optional nodots (termch #\)))
+  (let* ((dot-ok (cons nil nil))
+         (head (cons nil nil))
+         (tail head)
+         (source-note-list nil))
+    (declare (dynamic-extent dot-ok head)
+             (list head tail))
+    (if nodots (setq dot-ok nil))
+    (multiple-value-bind (firstform firstform-p firstform-source-note)
+        (%read-list-expression stream dot-ok termch)
+      (when firstform-source-note
+        (push firstform-source-note source-note-list))
+      (when firstform-p
+        (if (and dot-ok (eq firstform dot-ok))       ; just read a dot
+            (signal-reader-error stream "Dot context error."))
+        (rplacd tail (setq tail (cons firstform nil)))
+        (loop
+          (multiple-value-bind (nextform nextform-p nextform-source-note)
+              (%read-list-expression stream dot-ok termch)
+            (when nextform-source-note
+              (push nextform-source-note source-note-list))
+            (if (not nextform-p) (return))
+            (if (and dot-ok (eq nextform dot-ok))    ; just read a dot
+                (if (multiple-value-bind (lastform lastform-p lastform-source-note)
+                        (%read-list-expression stream nil termch)
+                      (when lastform-source-note
+                        (push lastform-source-note source-note-list))
+                      (and lastform-p
+                           (progn (rplacd tail lastform)
+                                  (not (nth-value 1 (%read-list-expression stream nil termch))))))
+                    (return)
+                    (signal-reader-error stream "Dot context error."))
+              (rplacd tail (setq tail (cons nextform nil))))))))
+    (values (cdr head) source-note-list)))
+
+#|
+(defun read-list-test (string &optional nodots)
+  (read-list (make-string-input-stream string) nodots))
+
+(read-list-test ")")
+(read-list-test "a b c)" t)
+(read-list-test "a b ;hello
+c)" t)
+
+|#
+
+(set-macro-character
+ #\(
+ #'(lambda (stream ignore)
+     (declare (ignore ignore))
+     (read-list stream nil #\))))
+
+(set-macro-character 
+ #\' 
+ (nfunction |'-reader| 
+            (lambda (stream ignore)
+              (declare (ignore ignore))
+              (multiple-value-bind (form source-note)
+                  (read-internal stream t nil t)
+                (values `(quote ,form) (and source-note (list source-note)))))))
+
+(defparameter *alternate-line-terminator*
+    #+darwin-target #\Return
+    #-darwin-target nil
+    "This variable is currently only used by the standard reader macro
+function for #\; (single-line comments); that function reads successive
+characters until EOF, a #\NewLine is read, or a character EQL to the value
+of *alternate-line-terminator* is read. In Clozure CL for Darwin, the value
+of this variable is initially #\Return ; in Clozure CL for other OSes, it's
+initially NIL.")
+	     
+(set-macro-character
+ #\;
+ (nfunction |;-reader|
+            (lambda (stream ignore)
+              (declare (ignore ignore))
+              (let* ((ch nil))
+                (loop 
+                    (if (or (eq :eof (setq ch (read-char stream nil :eof)))
+                            (eq ch #\NewLine)
+			    (eq ch *alternate-line-terminator*))
+                        (return (values))))))))
+
+(defun read-string (stream termch)
+  (with-token-buffer (tb)
+    (do* ((attrs (rdtab.ttab *readtable*))
+          (ch (%read-char-no-eof stream)
+              (%read-char-no-eof stream)))
+         ((eq ch termch)
+          (%string-from-token tb))
+      (if (= (the fixnum (%character-attribute ch attrs)) $CHT_SESC)
+          (setq ch (%read-char-no-eof stream)))
+      (%add-char-to-token ch tb))))
+
+(set-macro-character #\" #'read-string)
+
+(defparameter *ignore-extra-close-parenthesis* nil)
+
+(set-macro-character 
+ #\)
+ #'(lambda (stream ch)
+     (let* ((pos (if (typep stream 'file-stream)
+                     (file-position stream))))
+       (if *ignore-extra-close-parenthesis*
+           (warn "Ignoring extra \"~c\" ~@[near position ~d~] on ~s ." ch pos stream)
+           (signal-reader-error stream "Unmatched ')' ~@[near position ~d~]." pos)))))
+
+
+
+
+(eval-when (:load-toplevel)             ; But not when mousing around!
+  (make-dispatch-macro-character #\# t))
+
+
+(set-dispatch-macro-character
+ #\#
+ #\(
+ (nfunction 
+  |#(-reader| 
+  (lambda (stream subchar numarg)
+    (declare (ignore subchar))
+    (if (or (null numarg) *read-suppress*)
+      (multiple-value-bind (lst notes) (read-list stream t)
+        (let* ((len (length lst))
+               (vec (make-array len)))
+          (declare (list lst) (fixnum len) (simple-vector vec))
+          (dotimes (i len)
+            (setf (svref vec i) (pop lst)))
+          (values vec notes)))
+      (locally
+          (declare (fixnum numarg))
+        (do* ((vec (make-array numarg))
+              (notes ())
+              (lastform)
+              (i 0 (1+ i)))
+            ((multiple-value-bind (form form-p source-info)
+                 (%read-list-expression stream nil)
+               (if form-p
+                 (progn
+                   (setq lastform form)
+                   (when source-info (push source-info notes)))
+                 (unless (= i numarg)
+                   (if (= i 0) 
+                     (%err-disp $XARROOB -1 vec)
+                     (do* ((j i (1+ j)))
+                         ((= j numarg))
+                       (declare (fixnum j))
+                       (setf (svref vec j) lastform)))))
+               (not form-p))
+               (values vec notes))
+          (declare (fixnum i))
+          (setf (svref vec i) lastform)))))))
+
+(defun %read-rational (stream subchar radix)
+  (declare (ignore subchar))
+  (with-token-buffer (tb)
+      (multiple-value-bind (escapes xpackage)
+                           (%collect-xtoken tb stream (%next-non-whitespace-char-and-attr-no-eof stream))
+        (unless *read-suppress*
+          (let* ((val (%token-to-number tb radix)))
+          (or (and (null escapes)
+                   (null xpackage)
+                   (typep val 'rational)
+                   val)
+              (%err-disp $xbadnum)))))))
+
+(defun require-numarg (subchar numarg)
+  (or numarg *read-suppress*
+      (error "Numeric argument required for #~A reader macro ." subchar)))
+
+(defun require-no-numarg (subchar numarg)
+  (if (and numarg (not *read-suppress*))
+      (error "Spurious numeric argument in #~D~A reader macro ." numarg subchar)))
+
+(defun read-eval (stream subchar numarg)
+  (require-no-numarg subchar numarg)
+  (if *read-eval*
+    (let* ((exp (%read-list-expression stream nil)))
+      (unless *read-suppress*
+        (eval exp)))
+    (signal-reader-error stream "#. reader macro invoked when ~S is false ."
+                         '*read-eval*)))
+
+(set-dispatch-macro-character 
+ #\# 
+ #\C
+ #'(lambda (stream char arg)
+     (require-no-numarg char arg )
+     (multiple-value-bind (form note) (read-internal stream t nil t)
+       (values (unless *read-suppress* (apply #'complex form)) (and note (list note))))))
+
+(set-dispatch-macro-character 
+ #\#
+ #\.
+ #'read-eval)
+
+;;; Read a valid, non-numeric token string from stream; *READ-SUPPRESS*
+;;; is known to be false.
+(defun read-symbol-token (stream)
+  (multiple-value-bind (firstch attr) (%next-non-whitespace-char-and-attr-no-eof stream)
+    (declare (fixnum attr))
+    (with-token-buffer (tb)
+      (if (or (= attr $CHT_ILL)
+              (logbitp $cht_macbit attr)
+              (multiple-value-bind (escapes explicit-package nondots) (%collect-xtoken tb stream firstch)
+                (declare (ignore nondots))
+                (%casify-token tb (unless (atom escapes) escapes))
+                (or explicit-package
+                    (and (not escapes)
+                         (%token-to-number tb (%validate-radix *read-base*))))))
+        (%err-disp $XBADSYM)
+        (%string-from-token tb)))))
+
+(set-dispatch-macro-character
+ #\#
+ #\:
+ #'(lambda (stream subchar numarg)
+     (require-no-numarg subchar numarg)
+     (if (not *read-suppress*)
+       (make-symbol (read-symbol-token stream))
+       (progn
+         (%read-list-expression stream nil)
+         nil))))
+
+(set-dispatch-macro-character 
+ #\# 
+ #\b
+ #'(lambda (stream subchar numarg)
+     (require-no-numarg subchar numarg)
+     (%read-rational stream subchar 2)))
+
+(set-dispatch-macro-character 
+ #\# 
+ #\o
+ #'(lambda (stream subchar numarg)
+     (require-no-numarg subchar numarg)
+     (%read-rational stream subchar 8)))
+
+(set-dispatch-macro-character 
+ #\# 
+ #\x
+ #'(lambda (stream subchar numarg)
+     (require-no-numarg subchar numarg)
+     (%read-rational stream subchar 16)))
+
+(set-dispatch-macro-character 
+ #\# 
+ #\r
+ #'(lambda (stream subchar numarg)
+     (unless *read-suppress*
+       (require-numarg subchar numarg)
+       (check-type numarg (integer 2 36)))
+     (%read-rational stream subchar numarg)))
+
+(set-dispatch-macro-character
+ #\#
+ #\'
+ (nfunction |#'-reader| 
+            (lambda (stream subchar numarg)
+              (require-no-numarg subchar numarg)
+              (multiple-value-bind (form note) (read-internal stream t nil t)
+                (values `(function ,form) (and note (list note)))))))
+
+(set-dispatch-macro-character
+ #\#
+ #\|
+ (nfunction |#\|-reader| 
+            (lambda (stream subchar numarg)
+              (require-no-numarg subchar numarg)
+              (do* ((lastch nil ch)
+                    (ch )
+                    (level 1))
+                   ((= level 0) (values))
+                (declare (fixnum level))
+                (setq ch (%read-char-no-eof stream))
+                (if (and (eq ch #\|)
+                         (eq lastch #\#))
+                    (progn 
+                      (setq ch nil)
+                      (incf level))
+                    (if (and (eq ch #\#)
+                             (eq lastch #\|))
+                        (progn 
+                          (setq ch nil)
+                          (decf level))))))))
+
+(defun %unreadable (stream description)
+  (signal-reader-error stream "~S encountered." description))
+
+(set-dispatch-macro-character
+ #\#
+ #\<
+ #'(lambda (stream &rest ignore)
+     (declare (ignore ignore))
+     (%unreadable stream "#<")))
+
+(dolist (ch '(#\null #\tab #\linefeed #\page #\return #\space #\312))
+  (set-dispatch-macro-character
+   #\#
+   ch
+   #'(lambda (stream &rest ignore)
+       (declare (ignore ignore))
+       (%unreadable stream "#<whitespace>"))))
+
+(set-dispatch-macro-character
+ #\#
+ #\)
+ #'(lambda (stream &rest ignore)
+     (declare (ignore ignore))
+     (%unreadable stream "#)")))
+
+(set-dispatch-macro-character
+ #\#
+ #\\
+ #'(lambda (stream subchar numarg)
+     (require-no-numarg subchar numarg)
+     (with-token-buffer (tb)
+       (%collect-xtoken tb stream #\\)
+       (unless *read-suppress*
+         (let* ((str (%string-from-token tb)))
+           (or (name-char str)
+               (error "Unknown character name - \"~a\" ." str)))))))
+
+
+     
+;;;Since some built-in read macros used to use internal reader entry points
+;;;for efficiency, we couldn't reliably offer a protocol for stream-dependent
+;;;recursive reading.  So recursive reads always get done via tyi's, and streams
+;;;only get to intercept toplevel reads.
+(defun read (&optional stream (eof-error-p t) eof-value recursive-p)
+  (declare (resident))
+  ;; just return the first value of read-internal
+  (values (read-internal stream eof-error-p eof-value recursive-p)))
+
+(defun read-internal (stream eof-error-p eof-value recursive-p)
+  (setq stream (input-stream-arg stream))
+  (if recursive-p
+    (%read-form stream (if eof-error-p 0) nil)
+    (let ((%read-objects% nil) (%keep-whitespace% nil))
+      (%read-form stream (if eof-error-p 0) eof-value))))
+
+(defun read-preserving-whitespace (&optional stream (eof-error-p t) eof-value recursive-p)
+  "Read from STREAM and return the value read, preserving any whitespace
+   that followed the object."
+  (setq stream (input-stream-arg stream))
+  (values
+    (if recursive-p
+      (%read-form stream 0 nil)
+      (let ((%read-objects% nil) (%keep-whitespace% t))
+        (%read-form stream (if eof-error-p 0) eof-value)))))
+
+
+(defun read-delimited-list (char &optional stream recursive-p)
+  "Read Lisp values from INPUT-STREAM until the next character after a
+   value's representation is CHAR, and return the objects as a list."
+  (setq char (require-type char 'character))
+  (setq stream (input-stream-arg stream))
+  (values
+   (let ((%keep-whitespace% nil))
+     (if recursive-p
+       (%read-form stream char nil)
+       (let ((%read-objects% nil))
+         (%read-form stream char nil))))))
+
+(defun read-conditional (stream subchar int)
+  (declare (ignore int))
+  (cond ((eq subchar (read-feature stream))
+         (multiple-value-bind (form note) (read-internal stream t nil t)
+           (values form (and note (list note)))))
+        (t (let* ((*read-suppress* t))
+             (read stream t nil t)
+             (values)))))
+
+(defun read-feature (stream)
+  (let* ((f (let* ((*package* *keyword-package*))
+              (read stream t nil t))))
+    (labels ((eval-feature (form)
+               (cond ((atom form) 
+                      (member form *features*))
+                     ((eq (car form) :not) 
+                      (not (eval-feature (cadr form))))
+                     ((eq (car form) :and) 
+                      (dolist (subform (cdr form) t)
+                        (unless (eval-feature subform) (return))))
+                     ((eq (car form) :or) 
+                      (dolist (subform (cdr form) nil)
+                        (when (eval-feature subform) (return t))))
+                     (t (%err-disp $XRDFEATURE form)))))
+      (if (eval-feature f) #\+ #\-))))
+
+(set-dispatch-macro-character #\# #\+ #'read-conditional)
+(set-dispatch-macro-character #\# #\- #'read-conditional)
+
+(defun %read-form (stream arg eof-val)
+  "Read a lisp form from STREAM
+
+arg=0 : read form, error if eof
+arg=nil : read form, eof-val if eof.
+arg=char : read delimited list"
+  (declare (resident))
+  (check-type *readtable* readtable)
+  (check-type *package* package)
+  (if (and arg (not (eq arg 0)))
+      (read-list stream nil arg)
+      (loop
+        (let* ((ch (%next-non-whitespace-char-and-attr stream)))
+          (if (null ch)
+            (if arg 
+              (error 'end-of-file :stream stream)
+              (return eof-val))
+            (multiple-value-bind (form form-p source-note)
+                (%parse-expression stream ch nil)
+              (when form-p
+                (return
+                 (values (if *read-suppress* nil form)
+                         source-note)))))))))
+
+;;;Until load backquote...
+(set-macro-character #\`
+  #'(lambda (stream char) (declare (ignore stream)) (%err-disp $xbadmac char)))
+(set-macro-character #\, (get-macro-character #\`))
+
+
+
+(set-dispatch-macro-character #\# #\P
+ (qlfun |#P-reader| (stream char flags &aux (invalid-string "Invalid flags (~S) for pathname ~S"))
+   (declare (ignore char))
+   (when (null flags) (setq flags 0))
+   (unless (memq flags '(0 1 2 3 4))
+     (unless *read-suppress* (report-bad-arg flags '(integer 0 4))))
+   (multiple-value-bind (path note) (read-internal stream t nil t)
+     (unless *read-suppress*
+       (unless (stringp path) (report-bad-arg path 'string))
+       (setq path (pathname path))
+       (when (%ilogbitp 0 flags)
+         (when (%pathname-type path) (error invalid-string flags path))
+         (setf (%pathname-type path) :unspecific))
+       (when (%ilogbitp 1 flags)
+         (when (%pathname-name path) (error invalid-string flags path))
+         (setf (%pathname-name path) ""))
+       (values path (and note (list note)))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defstruct (source-note (:conc-name "SOURCE-NOTE.") (:constructor %make-source-note))
+  ;; For an inner source form, the source-note of the outer source form.
+  ;; For outer source note, octets
+  source
+  filename
+  ;; start and end file positions (NOT characters positions)
+  file-range)
+
+(defun make-source-note (&key filename start-pos end-pos source)
+  (%make-source-note :filename filename
+                     :file-range (encode-file-range start-pos end-pos)
+                     :source source))
+
+(defmethod print-object ((sn source-note) stream)
+  (print-unreadable-object (sn stream :type t :identity nil)
+    (print-source-note sn stream)))
+
+(defun print-source-note (sn stream)
+  (let* ((file (source-note-filename sn))
+         (text (ignore-errors (source-note-text sn))))
+    (when file
+      ;; Should fix this when record the name.
+      (when (eq (pathname-version file) :newest)
+	(setq file (namestring (make-pathname :version nil :defaults file)))))
+    (when text
+      (setq text (string-sans-most-whitespace text 121))
+      (when (> (length text) 120)
+        (setq text (concatenate 'string (subseq text 0 120) "..."))))
+    (if file
+      (format stream "*~s:~s-~s ~s" file
+	      (source-note-start-pos sn) (source-note-end-pos sn)
+	      text)
+      (format stream "Interactive ~s" text))))
+
+(defun source-note-filename (source)
+  (if (source-note-p source)
+    (source-note.filename source)
+    ;;  else null or a pathname, as in record-source-file
+    source))
+
+(defun (setf source-note-filename) (filename source-note)
+  (setf (source-note.filename (require-type source-note 'source-note)) filename))
+
+;; Since source notes are optional, it simplifies a lot of code
+;; to have these accessors allow NIL.
+
+(defun source-note-source (source-note)
+  (when source-note
+    (source-note.source (require-type source-note 'source-note))))
+
+(defun source-note-file-range (source-note)
+  (when source-note
+    (source-note.file-range (require-type source-note 'source-note))))
+
+(defun source-note-start-pos (source-note)
+  (let ((range (source-note-file-range source-note)))
+    (when range
+      (if (consp range) (car range) (ash range -14)))))
+
+(defun source-note-end-pos (source-note)
+  (let ((range (source-note-file-range source-note)))
+    (when range
+      (if (consp range) (cdr range) (+ (ash range -14) (logand range #x3FFF))))))
+
+(defun encode-file-range (start-pos end-pos)
+  (let ((len (- end-pos start-pos)))
+    (if (< len (ash 1 14))
+      (+ (ash start-pos 14) len)
+      (cons start-pos end-pos))))
+
+(defun source-note-text (source-note &optional start end)
+  (when source-note
+    (let* ((source (source-note-source source-note))
+	   (start-pos (source-note-start-pos source-note))
+	   (end-pos (source-note-end-pos source-note))
+	   (start (or start start-pos))
+	   (end (or end end-pos)))
+      (etypecase source
+	(source-note
+         (assert (<= (source-note-start-pos source) start end (source-note-end-pos source)))
+         (source-note-text source start end))
+	((simple-array (unsigned-byte 8) (*))
+         (decf start start-pos)
+         (decf end start-pos)
+         (assert (and (<= 0 start end (length source))))
+         (decode-string-from-octets source :start start :end end :external-format :utf-8))
+	(null source)))))
+
+(defun source-note-toplevel-note (source-note)
+  (when source-note
+    (loop for source = (source-note-source source-note)
+          while (source-note-p source)
+          do (setq source-note source))
+    source-note))
+
+(defvar *recording-source-streams* ())
+
+(defun record-source-note (&key form stream start-pos end-pos subform-notes)
+  (let ((recording (assq stream *recording-source-streams*)))
+    (when (and recording (not *read-suppress*))
+      (destructuring-bind (map file-name stream-offset) (cdr recording)
+        (let* ((prev (gethash form map))
+               (note (make-source-note :filename file-name
+                                       :start-pos (+ stream-offset start-pos)
+                                       :end-pos (+ stream-offset end-pos))))
+          (setf (gethash form map)
+                (cond ((null prev) note)
+                      ((consp prev) (cons note prev))
+                      (t (list note prev))))
+          (loop for subnote in subform-notes
+            do (when (source-note-source subnote) (error "Subnote ~s already owned?" subnote))
+            do (setf (source-note.source subnote) note))
+          note)))))
+
+(defun read-recording-source (stream &key eofval file-name start-offset map save-source-text)
+  "Read a top-level form, perhaps recording source locations.
+If MAP is NIL, just reads a form as if by READ.
+If MAP is non-NIL, returns a second value of a source-note object describing the form.
+In addition, if MAP is a hash table, it gets filled with source-note's for all
+non-atomic nested subforms."
+  (when (null start-offset) (setq start-offset 0))
+  (typecase map
+    (null (values (read-internal stream nil eofval nil) nil))
+    (hash-table
+       (let* ((stream (recording-input-stream stream))
+	      (recording (list stream map file-name start-offset))
+              (*recording-source-streams* (cons recording *recording-source-streams*)))
+         (declare (dynamic-extent recording *recording-source-streams*))
+         (multiple-value-bind (form source-note) (read-internal stream nil eofval nil)
+           (when (and source-note (not (eq form eofval)))
+             (assert (null (source-note-source source-note)))
+             (loop for form being the hash-key using (hash-value note) of map
+                   do (cond ((eq note source-note) nil)
+                            ;; Remove entries with multiple source notes, which can happen
+                            ;; for atoms.  If we can't tell which instance we mean, then we
+                            ;; don't have useful source info.
+                            ((listp note) (remhash form map))
+                            ((loop for p = note then (source-note-source p) while (source-note-p p)
+                                   thereis (eq p source-note))
+                             ;; Flatten the backpointers so each subnote points directly
+                             ;; to the toplevel note.
+                             (setf (source-note.source note) source-note))))
+             (when save-source-text
+               (setf (source-note.source source-note)
+                     (fetch-octets-from-stream stream
+                                               (- (source-note-start-pos source-note)
+                                                  start-offset)
+                                               (- (source-note-end-pos source-note)
+                                                  start-offset)))))
+           (values form source-note))))
+    (T ;; not clear if this is ever useful
+       (let* ((start-pos (stream-position stream))
+              (form (read-internal stream nil eofval nil))
+              (end-pos (and start-pos (neq form eofval) (stream-position stream)))
+              (source-note (and end-pos
+                                (make-source-note :filename file-name
+                                                  :start-pos (+ start-offset start-pos)
+                                                  :end-pos (+ start-offset end-pos)))))
+         (when (and source-note save-source-text)
+           (setf (source-note.source source-note) (fetch-octets-from-stream stream start-pos end-pos)))
+         (values form source-note)))))
+
+(defmethod fetch-octets-from-stream ((stream input-stream) start-offset end-offset)
+  ;; We basically want to read the bytes between two positions, but there is no
+  ;; direct interface for that.  So we let the stream decode and then we re-encode.
+  ;; (Just as well, since otherwise we'd have to remember the file's encoding).
+  (declare (fixnum start-offset))
+  (when (< start-offset end-offset)
+    (let* ((cur-pos (stream-position stream))
+           (noctets (- end-offset start-offset))
+           (vec (make-array noctets :element-type '(unsigned-byte 8)))
+           (index 0)
+           (crlfp (eq :crlf
+                      (cdr (assoc (external-format-line-termination
+                                   (stream-external-format stream))
+                                  *canonical-line-termination-conventions*)))))
+      (declare (type fixnum end-offset noctets index)
+               (type (simple-array (unsigned-byte 8) (*)) vec))
+      (macrolet ((out (code)
+                   `(progn
+                      (setf (aref vec index) ,code)
+                      (when (eql (incf index) noctets) (return)))))
+        (stream-position stream start-offset)
+        (loop
+          (let ((code (char-code (read-char stream))))
+            (declare (fixnum code))
+            (cond ((< code #x80)
+                   (when (and crlfp (= code (char-code #\NewLine)))
+                     (out (char-code #\Return)))
+                   (out code))
+                  ((< code #x800)
+                   (out (logior #xc0 (ldb (byte 5 6) code)))
+                   (out (logior #x80 (ldb (byte 6 0) code))))
+                  ((< code #x10000)
+                   (out (logior #xe0 (ldb (byte 4 12) code)))
+                   (out (logior #x80 (ldb (byte 6 6) code)))
+                   (out (logior #x80 (ldb (byte 6 0) code))))
+                  (t
+                   (out (logior #xf0 (ldb (byte 3 18) code)))
+                   (out (logior #xe0 (ldb (byte 6 12) code)))
+                   (out (logior #x80 (ldb (byte 6 6) code)))
+                   (out (logior #x80 (ldb (byte 6 0) code))))))))
+      (stream-position stream cur-pos)
+      vec)))
+
+(defun ensure-source-note-text (source-note &key (if-does-not-exist nil))
+  "Fetch source text from file if don't have it"
+  (setq if-does-not-exist (require-type if-does-not-exist '(member :error nil)))
+  (if source-note
+    (let ((source (source-note-source source-note))
+	  (filename (source-note-filename source-note)))
+      (etypecase source
+	(null
+	 (if filename
+	   (with-open-file (stream filename :if-does-not-exist if-does-not-exist)
+	     (when stream
+	       (let ((start (source-note-start-pos source-note))
+		     (end (source-note-end-pos source-note))
+		     (len (file-length stream)))
+		 (if (<= end len)
+		     (setf (source-note.source source-note)
+			   (fetch-octets-from-stream stream start end))
+		     (when if-does-not-exist
+		       (error 'simple-file-error :pathname filename
+			      :error-type "File ~s changed since source info recorded"))))))
+	   (when if-does-not-exist
+	     (error "Missing source text in internative source note"))))
+	(source-note
+	 (ensure-source-note-text source))
+	((simple-array (unsigned-byte 8) (*))
+	 source)))
+    (when if-does-not-exist
+      (error "Missing source note"))))
+
+
+;; This can be called explicitly by macros that do more complicated transforms
+(defun note-source-transformation (original new)
+  (nx-note-source-transformation original new))
+
+
+;;; Wrapper stream for recording source of non-random-access streams.
+(defclass recording-character-input-stream (fundamental-stream character-input-stream)
+  ((input-stream :initarg :input-stream)
+   (string :initform (make-array 1024 :element-type 'character :fill-pointer 0 :adjustable t))))
+
+(defmethod stream-element-type ((s recording-character-input-stream))
+  (with-slots (input-stream) s
+    (stream-element-type input-stream)))
+
+(defmethod stream-read-char ((s recording-character-input-stream))
+  (with-slots (input-stream string) s
+    (let ((char (stream-read-char input-stream)))
+      (when (and char (neq char :eof))
+	(vector-push-extend char string))
+      char)))
+
+(defmethod stream-read-char-no-hang ((s recording-character-input-stream))
+  (with-slots (input-stream string) s
+    (let ((char (stream-read-char-no-hang input-stream)))
+      (when (and char (neq char :eof))
+	(vector-push-extend char string))
+      char)))
+
+(defmethod stream-peek-char ((s recording-character-input-stream))
+  (with-slots (input-stream) s
+    (stream-peek-char input-stream)))
+
+(defmethod stream-listen ((s recording-character-input-stream))
+  (with-slots (input-stream) s
+    (stream-listen input-stream)))
+
+(defmethod stream-read-line ((s recording-character-input-stream))
+  (generic-read-line s))
+
+(defmethod stream-read-list ((s recording-character-input-stream) list count)
+  (generic-character-read-list s list count))
+
+(defmethod stream-read-vector ((s recording-character-input-stream) vector start end)
+  (generic-character-read-vector s vector start end))
+
+(defmethod stream-unread-char ((s recording-character-input-stream) char)
+  (with-slots (input-stream string) s
+    (vector-pop string)    ;; Error if no characters read since last reset.
+    (stream-unread-char input-stream char)))
+
+(defmethod stream-eofp ((s recording-character-input-stream))
+  (with-slots (input-stream) s
+    (stream-eofp input-stream)))
+
+(defmethod stream-clear-input ((s recording-character-input-stream))
+  (with-slots (input-stream) s
+    (stream-clear-input input-stream)))
+
+(defmethod stream-position ((s recording-character-input-stream) &optional newpos)
+  (with-slots (string) s
+    (unless newpos
+      (fill-pointer string))))
+
+(defun recording-input-stream (stream)
+  (let ((pos (stream-position stream)))
+    (if (and pos (stream-position stream pos))
+      stream
+      (make-instance 'recording-character-input-stream :input-stream stream))))
+
+(defmethod fetch-octets-from-stream ((s recording-character-input-stream) start-offset end-offset)
+  (declare (fixnum start-offset end-offset))
+  (with-slots (string) s
+    (when (< start-offset end-offset)
+      (let* ((sstring (array-data-and-offset string))
+	     (noctets (loop for i fixnum from start-offset below end-offset
+			 as code fixnum = (%char-code (%schar sstring i))
+			 sum (cond ((< code #x80) 1)
+				   ((< code #x800) 2)
+				   ((< code #x10000) 3)
+				   (t 4))
+			 of-type fixnum))
+	     (vec (make-array noctets :element-type '(unsigned-byte 8)))
+	     (index 0))
+	(declare (type fixnum noctets index)
+		 (type simple-base-string sstring)
+		 (type (simple-array (unsigned-byte 8) (*)) vec))
+	(macrolet ((out (octet) `(progn
+				   (setf (aref vec index) ,octet)
+				   (incf index))))
+	  (loop for i fixnum from start-offset below end-offset
+	     as code fixnum = (%char-code (%schar sstring i))
+	     do (cond ((< code #x80)
+		       (out code))
+		      ((< code #x800)
+		       (out (logior #xc0 (ldb (byte 5 6) code)))
+		       (out (logior #x80 (ldb (byte 6 0) code))))
+		      ((< code #x10000)
+		       (out (logior #xe0 (ldb (byte 4 12) code)))
+		       (out (logior #x80 (ldb (byte 6 6) code)))
+		       (out (logior #x80 (ldb (byte 6 0) code))))
+		      (t
+		       (out (logior #xf0 (ldb (byte 3 18) code)))
+		       (out (logior #xe0 (ldb (byte 6 12) code)))
+		       (out (logior #x80 (ldb (byte 6 6) code)))
+		       (out (logior #x80 (ldb (byte 6 0) code)))))))
+	(setf (fill-pointer string) 0) ;; reset
+	vec))))
+
+
+
+
+; end
Index: /branches/new-random/level-1/l1-readloop-lds.lisp
===================================================================
--- /branches/new-random/level-1/l1-readloop-lds.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-readloop-lds.lisp	(revision 13309)
@@ -0,0 +1,727 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; l1-readloop-lds.lisp
+
+(in-package "CCL")
+
+
+
+(defun toplevel-loop ()
+  (loop
+    (if (eq (catch :toplevel 
+              (read-loop :break-level 0 )) $xstkover)
+      (format t "~&;[Stacks reset due to overflow.]")
+      (when (eq *current-process* *initial-process*)
+        (toplevel)))))
+
+
+(defvar *defined-toplevel-commands* ())
+(defvar *active-toplevel-commands* ())
+
+(defun %define-toplevel-command (group-name key name fn doc args)
+  (let* ((group (or (assoc group-name *defined-toplevel-commands*)
+		    (car (push (list group-name)
+			       *defined-toplevel-commands*))))
+	 (pair (assoc key (cdr group) :test #'eq)))
+    (if pair
+      (rplacd pair (list* fn doc args))
+      (push (cons key (list* fn doc args)) (cdr group))))
+  name)
+
+(define-toplevel-command 
+    :global y (&optional p) "Yield control of terminal-input to process
+whose name or ID matches <p>, or to any process if <p> is null"
+    (%%yield-terminal-to (if p (find-process p))))	;may be nil
+
+
+(define-toplevel-command
+    :global kill (p) "Kill process whose name or ID matches <p>"
+    (let* ((proc (find-process p)))
+      (if proc
+	(process-kill proc))))
+
+(define-toplevel-command 
+    :global proc (&optional p) "Show information about specified process <p>/all processes"
+    (flet ((show-process-info (proc)
+	     (format t "~&~d : ~a ~a ~20t[~a] "
+		     (process-serial-number proc)
+		     (if (eq proc *current-process*)
+		       "->"
+		       "  ")
+		     (process-name proc)
+		     (process-whostate proc))
+	     (let* ((suspend-count (process-suspend-count proc)))
+	       (if (and suspend-count (not (eql 0 suspend-count)))
+		 (format t " (Suspended)")))
+	     (let* ((terminal-input-shared-resource
+		     (if (typep *terminal-io* 'two-way-stream)
+		       (input-stream-shared-resource
+			(two-way-stream-input-stream *terminal-io*)))))
+	       (if (and terminal-input-shared-resource
+			(%shared-resource-requestor-p
+			 terminal-input-shared-resource proc))
+		 (format t " (Requesting terminal input)")))
+	     (fresh-line)))
+      (if p
+	(let* ((proc (find-process p)))
+	  (if (null proc)
+	    (format t "~&;; not found - ~s" p)
+	    (show-process-info proc)))
+	(dolist (proc (all-processes) (values))
+	  (show-process-info proc)))))
+
+(define-toplevel-command :global cd (dir) "Change to directory DIR" (setf (current-directory) dir) (toplevel-print (list (current-directory))))
+
+(define-toplevel-command :global pwd () "Print the pathame of the current directory" (toplevel-print (list (current-directory))))
+
+
+
+(defun list-restarts ()
+  (format *debug-io* "~&>   Type (:C <n>) to invoke one of the following restarts:")
+  (display-restarts))
+
+(define-toplevel-command :break pop () "exit current break loop" (abort-break))
+(define-toplevel-command :break a () "exit current break loop" (abort-break))
+(define-toplevel-command :break go () "continue" (continue))
+(define-toplevel-command :break q () "return to toplevel" (toplevel))
+(define-toplevel-command :break r () "list restarts" (list-restarts))
+
+(define-toplevel-command :break set (n frame value) "Set <n>th item of frame <frame> to <value>"
+  (let* ((frame-sp (nth-raw-frame frame *break-frame* nil)))
+    (if frame-sp
+        (toplevel-print (list (set-nth-value-in-frame frame-sp n nil value)))
+        (format *debug-io* "No frame with number ~D~%" frame))))
+
+(define-toplevel-command :break nframes ()
+  "print the number of stack frames accessible from this break loop"
+  (do* ((p *break-frame* (parent-frame p nil))
+        (i 0 (1+ i))
+        (last (last-frame-ptr)))
+      ((eql p last) (toplevel-print (list i)))))
+
+(define-toplevel-command :global ? () "help"
+  (format t "~&The following toplevel commands are available:")
+  (when *default-integer-command*
+    (format t "~& <n>  ~8Tthe same as (~s <n>)" (car *default-integer-command*)))
+  (dolist (g *active-toplevel-commands*)
+    (dolist (c (cdr g))
+      (let* ((command (car c))
+	     (doc (caddr c))
+	     (args (cdddr c)))
+	(if args
+	  (format t "~& (~S~{ ~A~}) ~8T~A" command args doc)
+	  (format t "~& ~S  ~8T~A" command doc)))))
+  (format t "~&Any other form is evaluated and its results are printed out."))
+
+
+(define-toplevel-command :break b (&key start count show-frame-contents) "backtrace"
+  (when *break-frame*
+      (print-call-history :detailed-p show-frame-contents
+                          :origin *break-frame*
+                          :count count
+                          :start-frame-number (or start 0))))
+
+(define-toplevel-command :break c (&optional n) "Choose restart <n>. If no <n>, continue"
+  (if n
+   (select-restart n)
+   (continue)))
+
+(define-toplevel-command :break f (n) "Show backtrace frame <n>"
+   (print-call-history :origin *break-frame*
+                       :start-frame-number n
+                       :count 1
+                       :detailed-p t))
+
+(define-toplevel-command :break return-from-frame (i &rest values) "Return VALUES from the I'th stack frame"
+  (let* ((frame-sp (nth-raw-frame  i *break-frame* nil)))
+    (if frame-sp
+      (apply #'return-from-frame frame-sp values))))
+
+(define-toplevel-command :break apply-in-frame (i function &rest args) "Applies FUNCTION to ARGS in the execution context of the Ith stack frame"
+  (let* ((frame-sp (nth-raw-frame  i *break-frame* nil)))
+    (if frame-sp
+      (apply-in-frame frame-sp function args))))
+                         
+                         
+
+(define-toplevel-command :break raw (n) "Show raw contents of backtrace frame <n>"
+   (print-call-history :origin *break-frame*
+                       :start-frame-number n
+                       :count 1
+                       :detailed-p :raw))
+
+(define-toplevel-command :break v (n frame-number) "Return value <n> in frame <frame-number>"
+  (let* ((frame-sp (nth-raw-frame frame-number *break-frame* nil)))
+    (if frame-sp
+      (toplevel-print (list (nth-value-in-frame frame-sp n nil))))))
+
+(define-toplevel-command :break arg (name frame-number) "Return value of argument named <name> in frame <frame-number>"
+  (let* ((frame-sp (nth-raw-frame frame-number *break-frame* nil)))
+    (when frame-sp
+      (multiple-value-bind (lfun pc) (cfp-lfun frame-sp)
+        (when (and lfun pc)
+          (let* ((unavailable (cons nil nil)))
+            (declare (dynamic-extent unavailable))
+            (let* ((value (arg-value nil frame-sp lfun pc unavailable name)))
+              (if (eq value unavailable)
+                (format *debug-io* "~&;; Can't determine value of ~s in frame ~s." name frame-number)
+                (toplevel-print (list value))))))))))
+
+(define-toplevel-command :break set-arg (name frame-number new) "Set value of argument named <name> in frame <frame-number> to value <new>."
+  (let* ((frame-sp (nth-raw-frame frame-number *break-frame* nil)))
+    (when frame-sp
+      (multiple-value-bind (lfun pc) (cfp-lfun frame-sp)
+        (when (and lfun pc)
+          (or (set-arg-value nil frame-sp lfun pc name new)
+              (format *debug-io* "~&;; Can't change value of ~s in frame ~s." name frame-number)))))))
+   
+
+(define-toplevel-command :break local (name frame-number) "Return value of local denoted by <name> in frame <frame-number> <name> can either be a symbol - in which case the most recent
+binding of that symbol is used - or an integer index into the frame's set of local bindings."
+  (let* ((frame-sp (nth-raw-frame frame-number *break-frame* nil)))
+    (when frame-sp
+      (multiple-value-bind (lfun pc) (cfp-lfun frame-sp)
+        (when (and lfun pc)
+          (let* ((unavailable (cons nil nil)))
+            (declare (dynamic-extent unavailable))
+            (let* ((value (local-value nil frame-sp lfun pc unavailable name)))
+              (if (eq value unavailable)
+                (format *debug-io* "~&;; Can't determine value of ~s in frame ~s." name frame-number)
+                (toplevel-print (list value))))))))))
+
+(define-toplevel-command :break set-local (name frame-number new) "Set value of argument denoted <name> (see :LOCAL) in frame <frame-number> to value <new>."
+  (let* ((frame-sp (nth-raw-frame frame-number *break-frame* nil)))
+    (when frame-sp
+      (multiple-value-bind (lfun pc) (cfp-lfun frame-sp)
+        (when (and lfun pc)
+          (or (set-local-value nil frame-sp lfun pc name new)
+              (format *debug-io* "~&;; Can't change value of ~s in frame ~s." name frame-number)))))))
+
+
+(define-toplevel-command :break form (frame-number)
+   "Return a form which looks like the call which established the stack frame identified by <frame-number>.  This is only well-defined in certain cases: when the function is globally named and not a lexical closure and when it was compiled with *SAVE-LOCAL-SYMBOLS* in effect."
+   (let* ((form (dbg-form frame-number)))
+     (when form
+       (let* ((*print-level* *backtrace-print-level*)
+              (*print-length* *backtrace-print-length*))
+         (toplevel-print (list form))))))
+
+;;; Ordinarily, form follows function.
+(define-toplevel-command :break function (frame-number)
+  "Returns the function invoked in backtrace frame <frame-number>.  This may be useful for, e.g., disassembly"
+  (let* ((cfp (nth-raw-frame frame-number *break-frame* nil)))
+    (when (and cfp (not (catch-csp-p cfp nil)))
+      (let* ((function (cfp-lfun cfp)))
+        (when function
+          (toplevel-print (list function)))))))
+  
+
+
+          
+
+  
+
+(defun %use-toplevel-commands (group-name)
+  ;; Push the whole group
+  (pushnew (assoc group-name *defined-toplevel-commands*)
+	   *active-toplevel-commands*
+	   :key #'(lambda (x) (car x))))  ; #'car not defined yet ...
+
+(%use-toplevel-commands :global)
+
+(defparameter *toplevel-commands-dwim* t
+ "If true, tries to interpret otherwise-erroneous toplevel expressions as commands.
+In addition, will suppress standard error handling for expressions that look like
+commands but aren't")
+
+(defvar *default-integer-command* nil
+  "If non-nil, should be (keyword  min max)), causing integers between min and max to be
+  interpreted as (keyword integer)")
+
+(defun check-toplevel-command (form)
+  (when (and *default-integer-command*
+             (integerp form)
+             (<= (cadr *default-integer-command*) form (caddr *default-integer-command*)))
+    (setq form `(,(car *default-integer-command*) ,form)))
+  (let* ((cmd (if (consp form) (car form) form))
+         (args (if (consp form) (cdr form))))
+    (when (or (keywordp cmd)
+              (and *toplevel-commands-dwim*
+                   (non-nil-symbol-p cmd)
+                   (not (if (consp form)
+                          (fboundp cmd)
+                          (or (boundp cmd)
+                              (nth-value 1 (gethash cmd *symbol-macros*)))))
+                   ;; Use find-symbol so don't make unneeded keywords.
+                   (setq cmd (find-symbol (symbol-name cmd) :keyword))))
+      (when (eq cmd :help) (setq cmd :?))
+      (flet ((run (cmd form)
+               (or (dolist (g *active-toplevel-commands*)
+                     (let* ((pair (assoc cmd (cdr g))))
+                       (when pair 
+                         (apply (cadr pair) args)
+                         (return t))))
+                   ;; Try to detect user mistyping a command
+                   (when (and *toplevel-commands-dwim*
+                              (if (consp form)
+                                (and (keywordp (%car form)) (not (fboundp (%car form))))
+                                (keywordp form)))
+                     (error "Unknown command ~s" cmd)))))
+        (declare (dynamic-extent #'run))
+        (if *toplevel-commands-dwim*
+          (block nil
+            (handler-bind ((error (lambda (c)
+                                    (format t "~&~a" c)
+                                    (return t))))
+              (run cmd form)))
+          (run cmd form))))))
+
+(defparameter *quit-on-eof* nil)
+
+(defparameter *consecutive-eof-limit* 2 "max number of consecutive EOFs at a given break level, before we give up and abruptly exit.")
+
+(defmethod stream-eof-transient-p (stream)
+  (let ((fd (stream-device stream :input)))
+    (and fd (eof-transient-p fd))))
+
+(defvar *save-interactive-source-locations* t)
+
+;;; This is the part common to toplevel loop and inner break loops.
+(defun read-loop (&key (input-stream *standard-input*)
+                       (output-stream *standard-output*)
+                       (break-level *break-level*)
+		       (prompt-function #'(lambda (stream)
+                                            (when (and *show-available-restarts* *break-condition*)
+                                              (list-restarts)
+                                              (setf *show-available-restarts* nil))
+                                            (print-listener-prompt stream t))))
+  (let* ((*break-level* break-level)
+         (*last-break-level* break-level)
+         (*loading-file-source-file* nil)
+         (*loading-toplevel-location* nil)
+         *in-read-loop*
+         *** ** * +++ ++ + /// // / -
+         (eof-value (cons nil nil))
+         (eof-count 0)
+         (*show-available-restarts* (and *show-restarts-on-break* *break-condition*))
+         (map (make-hash-table :test #'eq :shared nil)))
+    (declare (dynamic-extent eof-value))
+    (loop
+      (restart-case
+       (catch :abort                    ;last resort...
+         (loop
+           (catch-cancel
+            (loop                
+              (setq *in-read-loop* nil
+                    *break-level* break-level)
+              (multiple-value-bind (form env print-result)
+                  (toplevel-read :input-stream input-stream
+                                 :output-stream output-stream
+                                 :prompt-function prompt-function
+                                 :eof-value eof-value
+				 :map (when *save-interactive-source-locations*
+                                        (clrhash map)
+                                        map))
+                (if (eq form eof-value)
+                  (progn
+                    (when (> (incf eof-count) *consecutive-eof-limit*)
+                      (#_ _exit 0))
+                    (if (and (not *batch-flag*)
+                             (not *quit-on-eof*)
+                             (stream-eof-transient-p input-stream))
+                      (progn
+                        (stream-clear-input input-stream)
+                        (abort-break))
+                      (exit-interactive-process *current-process*)))
+                  (let ((*nx-source-note-map* (and *save-interactive-source-locations* map)))
+                    (setq eof-count 0)
+                    (or (check-toplevel-command form)
+                        (let* ((values (toplevel-eval form env)))
+                          (if print-result (toplevel-print values)))))))))
+           (format *terminal-io* "~&Cancelled")))
+       (abort () :report (lambda (stream)
+                           (if (eq break-level 0)
+                             (format stream "Return to toplevel.")
+                             (format stream "Return to break level ~D." break-level)))
+              #|                        ; Handled by interactive-abort
+                                        ; go up one more if abort occurred while awaiting/reading input               
+              (when (and *in-read-loop* (neq break-level 0))
+              (abort))
+              |#
+               )
+        (abort-break () 
+                     (unless (eq break-level 0)
+                       (abort))))
+       (clear-input input-stream)
+      (format output-stream "~%"))))
+
+;;; The first non-whitespace character available on INPUT-STREAM is a colon.
+;;; Try to interpret the line as a colon command (or possibly just a keyword.)
+(defun read-command-or-keyword (input-stream eof-value)
+  (let* ((line (read-line input-stream nil eof-value)))
+    (if (eq line eof-value)
+      eof-value
+      (let* ((in (make-string-input-stream line))
+             (keyword (read in nil eof-value)))
+        (if (eq keyword eof-value)
+          eof-value
+          (if (not (keywordp keyword))
+            keyword
+            (collect ((params))
+              (loop
+                (let* ((param (read in nil eof-value)))
+                  (if (eq param eof-value)
+                    (return
+                      (let* ((params (params)))
+                        (if params
+                          (cons keyword params)
+                          keyword)))
+                    (params (eval param))))))))))))
+
+;;; Read a form from the specified stream.
+(defun toplevel-read (&key (input-stream *standard-input*)
+                           (output-stream *standard-output*)
+                           (prompt-function #'print-listener-prompt)
+                           (eof-value *eof-value*)
+		           (map nil))
+  (force-output output-stream)
+  (funcall prompt-function output-stream)
+  (read-toplevel-form input-stream :eof-value eof-value :map map))
+
+(defvar *always-eval-user-defvars* nil)
+
+(defun process-single-selection (form)
+  (if (and *always-eval-user-defvars*
+           (listp form) (eq (car form) 'defvar) (cddr form))
+    `(defparameter ,@(cdr form))
+    form))
+
+(defun toplevel-eval (form &optional env)
+  (destructuring-bind (vars . vals) (or env '(nil . nil))
+    (progv vars vals
+      (setq +++ ++ ++ + + - - form)
+      (unwind-protect
+           (let* ((package *package*)
+                  (values (multiple-value-list (cheap-eval-in-environment form nil))))
+             (unless (eq package *package*)
+               ;; If changing a local value (e.g. buffer-local), not useful to notify app
+               ;; without more info.  Perhaps should have a *source-context* that can send along?
+               (unless (member '*package* vars)
+                 (application-ui-operation *application* :note-current-package *package*)))
+             values)
+        (loop for var in vars as pval on vals
+              do (setf (car pval) (symbol-value var)))))))
+
+
+(defun toplevel-print (values &optional (out *standard-output*))
+  (setq /// // // / / values)
+  (unless (eq (car values) (%unbound-marker))
+    (setq *** ** ** * *  (%car values)))
+  (when values
+    (fresh-line out)
+    (dolist (val values) (write val :stream out) (terpri out))))
+
+(defparameter *listener-prompt-format* "~[?~:;~:*~d >~] ")
+
+  
+(defun print-listener-prompt (stream &optional (force t))
+  (unless *quiet-flag*
+    (when (or force (neq *break-level* *last-break-level*))
+      (let* ((*listener-indent* nil))
+        (fresh-line stream)
+        (format stream *listener-prompt-format* *break-level*))
+      (setq *last-break-level* *break-level*)))
+    (force-output stream))
+
+
+;;; Fairly crude default error-handlingbehavior, and a fairly crude mechanism
+;;; for customizing it.
+
+(defvar *app-error-handler-mode* :quit
+  "one of :quit, :quit-quietly, :listener might be useful.")
+
+(defmethod application-error ((a application) condition error-pointer)
+  (case *app-error-handler-mode*
+    (:listener   (break-loop-handle-error condition error-pointer))
+    (:quit-quietly (quit -1))
+    (:quit  (format t "~&Fatal error in ~s : ~a"
+                    (pathname-name (car *command-line-argument-list*))
+                    condition)
+                    (quit -1))))
+
+(defun make-application-error-handler (app mode)
+  (declare (ignore app))
+  (setq *app-error-handler-mode* mode))
+
+
+; You may want to do this anyway even if your application
+; does not otherwise wish to be a "lisp-development-system"
+(defmethod application-error ((a lisp-development-system) condition error-pointer)
+  (break-loop-handle-error condition error-pointer))
+
+(defun abnormal-application-exit ()
+  (ignore-errors
+    (print-call-history)
+    (force-output *debug-io*)
+    (quit -1))
+  (#__exit -1))
+
+(defvar *top-error-frame* nil)
+
+(defun break-loop-handle-error (condition *top-error-frame*)
+  (multiple-value-bind (bogus-globals newvals oldvals) (%check-error-globals)
+    (dolist (x bogus-globals)
+      (set x (funcall (pop newvals))))
+    (when (and *debugger-hook* *break-on-errors* (not *batch-flag*))
+      (let ((hook *debugger-hook*)
+            (*debugger-hook* nil))
+        (funcall hook condition hook)))
+    (%break-message "Error" condition)
+    (let* ((s *error-output*))
+      (dolist (bogusness bogus-globals)
+        (let ((oldval (pop oldvals)))
+          (format s "~&;  NOTE: ~S was " bogusness)
+          (if (eq oldval (%unbound-marker-8))
+            (format s "unbound")
+            (format s "~s" oldval))
+          (format s ", was reset to ~s ." (symbol-value bogusness)))))
+    (if (and *break-on-errors* (not *batch-flag*))
+      (break-loop condition)
+      (if *batch-flag*
+        (abnormal-application-exit)
+        (abort)))))
+
+(defun break (&optional string &rest args)
+  "Print a message and invoke the debugger without allowing any possibility
+   of condition handling occurring."
+  (if *batch-flag*
+    (apply #'error (or string "BREAK invoked in batch mode") args)
+    (apply #'%break-in-frame (%get-frame-ptr) string args)))
+
+(defun %break-in-frame (fp &optional string &rest args)
+  (flet ((do-break-loop ()
+           (let ((c (if (typep string 'condition)
+                      string
+                      (make-condition 'simple-condition
+                                    :format-control (or string "")
+                                    :format-arguments args))))
+             (cbreak-loop "Break" "Return from BREAK." c fp))))
+    (cond ((%i> *interrupt-level* -1)
+           (do-break-loop))
+          (*break-loop-when-uninterruptable*
+           (format *error-output* "Break while interrupt-level less than zero; binding to 0 during break-loop.")
+           (let ((interrupt-level (interrupt-level)))
+	     (unwind-protect
+		  (progn
+		    (setf (interrupt-level) 0)
+		    (do-break-loop))
+	       (setf (interrupt-level) interrupt-level))))
+          (t (format *error-output* "Break while interrupt-level less than zero; ignored.")))))
+
+
+(defun invoke-debugger (condition &aux (*top-error-frame* (%get-frame-ptr)))
+  "Enter the debugger."
+  (let ((c (require-type condition 'condition)))
+    (when *debugger-hook*
+      (let ((hook *debugger-hook*)
+            (*debugger-hook* nil))
+        (funcall hook c hook)))
+    (%break-message "Debug" c)
+    (break-loop c)))
+
+(defun %break-message (msg condition &optional (error-pointer *top-error-frame*) (prefixchar #\>))
+  (let ((*print-circle* *error-print-circle*)
+        ;(*print-prett*y nil)
+        (*print-array* nil)
+        (*print-escape* t)
+        (*print-gensym* t)
+        (*print-length* *error-print-length*)
+        (*print-level* *error-print-level*)
+        (*print-lines* nil)
+        (*print-miser-width* nil)
+        (*print-readably* nil)
+        (*print-right-margin* nil)
+        (*signal-printing-errors* nil)
+        (s (make-indenting-string-output-stream prefixchar nil)))
+    (format s "~A ~A: " prefixchar msg)
+    (setf (indenting-string-output-stream-indent s) (column s))
+    ;(format s "~A" condition) ; evil if circle
+    (report-condition condition s)
+    (if (not (and (typep condition 'simple-program-error)
+                  (simple-program-error-context condition)))
+      (format *error-output* "~&~A~%~A While executing: ~S"
+              (get-output-stream-string s) prefixchar (%real-err-fn-name error-pointer))
+      (format *error-output* "~&~A"
+              (get-output-stream-string s)))
+    (format *error-output* ", in process ~a(~d).~%" (process-name *current-process*) (process-serial-number *current-process*))
+  (force-output *error-output*)))
+					; returns NIL
+
+(defvar *break-hook* nil)
+
+(defun cbreak-loop (msg cont-string condition *top-error-frame*)
+  (let* ((*print-readably* nil)
+         (hook *break-hook*))
+    (restart-case (progn
+                    (when hook
+                      (let ((*break-hook* nil))
+                        (funcall hook condition hook))
+                      (setq hook nil))
+                    (%break-message msg condition)
+                    (when (and (eq (type-of condition) 'simple-condition)
+                               (equal (simple-condition-format-control condition) ""))
+                      (setq condition (make-condition 'simple-condition
+                                        :format-control "~a"
+                                        :format-arguments (list msg))))
+                    (break-loop condition))
+      (continue () :report (lambda (stream) (write-string cont-string stream))))
+    (unless hook
+      (fresh-line *error-output*))
+    nil))
+
+(defun warn (condition-or-format-string &rest args)
+  "Warn about a situation by signalling a condition formed by DATUM and
+   ARGUMENTS. While the condition is being signaled, a MUFFLE-WARNING restart
+   exists that causes WARN to immediately return NIL."
+  (when (typep condition-or-format-string 'condition)
+    (unless (typep condition-or-format-string 'warning)
+      (report-bad-arg condition-or-format-string 'warning))
+    (when args
+      (error 'type-error :datum args :expected-type 'null
+	     :format-control "Extra arguments in ~s.")))
+  (let ((fp (%get-frame-ptr))
+        (c (require-type (condition-arg condition-or-format-string args 'simple-warning) 'warning)))
+    (when *break-on-warnings*
+      (cbreak-loop "Warning" "Signal the warning." c fp))
+    (restart-case (signal c)
+      (muffle-warning () :report "Skip the warning" (return-from warn nil)))
+    (%break-message (if (typep c 'compiler-warning) "Compiler warning" "Warning") c fp #\;)
+    ))
+
+(declaim (notinline select-backtrace))
+
+(defmacro new-backtrace-info (dialog youngest oldest tcr condition current fake db-link level)
+  (let* ((cond (gensym)))
+  `(let* ((,cond ,condition))
+    (vector ,dialog ,youngest ,oldest ,tcr (cons nil (compute-restarts ,cond)) (%catch-top ,tcr) ,cond ,current ,fake ,db-link ,level))))
+
+(defun select-backtrace ()
+  (declare (notinline select-backtrace))
+  ;(require 'new-backtrace)
+  (require :inspector)
+  (select-backtrace))
+
+(defvar *break-condition* nil "condition argument to innermost break-loop.")
+(defvar *break-frame* nil "frame-pointer arg to break-loop")
+(defvar *break-loop-when-uninterruptable* t)
+(defvar *show-restarts-on-break* #+ccl-0711 t #-ccl-0711 nil)
+(defvar *show-available-restarts* nil)
+
+(defvar *error-reentry-count* 0)
+
+(defun funcall-with-error-reentry-detection (thunk)
+  (let* ((count *error-reentry-count*)
+         (*error-reentry-count* (1+ count)))
+    (cond ((eql count 0) (funcall thunk))
+          ((eql count 1) (error "Error reporting error"))
+          (t (bug "Error reporting error")))))
+
+
+
+
+(defvar %last-continue% nil)
+(defun break-loop (condition &optional (frame-pointer *top-error-frame*))
+  "Never returns"
+  (let* ((%handlers% (last %handlers%)) ; firewall
+         (*break-frame* frame-pointer)
+         (*break-condition* condition)
+         (*compiling-file* nil)
+         (*backquote-stack* nil)
+         (continue (find-restart 'continue))
+         (*continuablep* (unless (eq %last-continue% continue) continue))
+         (%last-continue% continue)
+         (*standard-input* *debug-io*)
+         (*standard-output* *debug-io*)
+         (*signal-printing-errors* nil)
+         (*read-suppress* nil)
+         (*print-readably* nil)
+	 (*default-integer-command* `(:c 0 ,(1- (length (compute-restarts condition)))))
+         (context (new-backtrace-info nil
+                                      frame-pointer
+                                      (if *backtrace-contexts*
+                                        (or (child-frame
+                                             (bt.youngest (car *backtrace-contexts*))
+                                             nil)
+                                            (last-frame-ptr))
+                                        (last-frame-ptr))
+                                      (%current-tcr)
+                                      condition
+                                      (%current-frame-ptr)
+                                      #+ppc-target *fake-stack-frames*
+                                      #+x86-target (%current-frame-ptr)
+                                      (db-link)
+                                      (1+ *break-level*)))
+         (*backtrace-contexts* (cons context *backtrace-contexts*)))
+    (with-terminal-input
+      (with-toplevel-commands :break
+        (if *continuablep*
+          (let* ((*print-circle* *error-print-circle*)
+                 (*print-level* *error-print-level*)
+                 (*print-length* *error-print-length*)
+					;(*print-pretty* nil)
+                 (*print-array* nil))
+            (format t (or (application-ui-operation *application* :break-options-string t)
+                          "~&> Type :GO to continue, :POP to abort, :R for a list of available restarts."))
+            (format t "~&> If continued: ~A~%" continue))
+          (format t (or (application-ui-operation *application* :break-options-string nil)
+                        "~&> Type :POP to abort, :R for a list of available restarts.~%")))
+        (format t "~&> Type :? for other options.")
+        (terpri)
+        (force-output)
+
+        (clear-input *debug-io*)
+        (setq *error-reentry-count* 0)  ; succesfully reported error
+        (ignoring-without-interrupts
+          (unwind-protect
+               (progn
+                 (application-ui-operation *application*
+                                           :enter-backtrace-context context)
+                 (read-loop :break-level (1+ *break-level*)
+                            :input-stream *debug-io*
+                            :output-stream *debug-io*))
+            (application-ui-operation *application* :exit-backtrace-context
+                                      context)))))))
+
+
+
+(defun display-restarts (&optional (condition *break-condition*))
+  (loop
+    for restart in (compute-restarts condition)
+    for count upfrom 0
+    do (format *debug-io* "~&~D. ~A" count restart)
+    finally (fresh-line *debug-io*)))
+
+(defun select-restart (n &optional (condition *break-condition*))
+  (let* ((restarts (compute-restarts condition)))
+    (invoke-restart-interactively
+     (nth (require-type n `(integer 0 (,(length restarts)))) restarts))))
+
+
+
+
+; End of l1-readloop-lds.lisp
Index: /branches/new-random/level-1/l1-readloop.lisp
===================================================================
--- /branches/new-random/level-1/l1-readloop.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-readloop.lisp	(revision 13309)
@@ -0,0 +1,875 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;L1-readloop.lisp
+
+
+(defvar *break-on-signals* nil
+  "When (TYPEP condition *BREAK-ON-SIGNALS*) is true, then calls to SIGNAL will
+   enter the debugger prior to signalling that condition.")
+(defvar *break-on-warnings* nil)
+(defvar *break-on-errors* t "Not CL.")
+(defvar *debugger-hook* nil
+  "This is either NIL or a function of two arguments, a condition and the value
+   of *DEBUGGER-HOOK*. This function can either handle the condition or return
+   which causes the standard debugger to execute. The system passes the value
+   of this variable to the function because it binds *DEBUGGER-HOOK* to NIL
+   around the invocation.")
+(defvar *backtrace-on-break* nil)
+(defvar *** nil
+  "the previous value of **")
+(defvar ** nil
+  "the previous value of *")
+(defvar * nil
+  "the value of the most recent top level EVAL")
+(defvar /// nil
+  "the previous value of //")
+(defvar // nil
+  "the previous value of /")
+(defvar / nil
+  "a list of all the values returned by the most recent top level EVAL")
+(defvar +++ nil
+  "the previous value of ++")
+(defvar ++ nil
+  "the previous value of +")
+(defvar + nil
+  "the value of the most recent top level READ")
+(defvar - nil
+  "the form currently being evaluated")
+
+(defvar *continuablep* nil)
+(defvar *in-read-loop* nil 
+ "Is T if waiting for input in the read loop")
+
+
+(defvar *did-startup* nil)
+
+
+
+(defmacro catch-cancel (&body body)
+  `(catch :cancel ,@body))
+
+(defmacro throw-cancel (&optional value)
+  `(throw :cancel ,value))
+
+;;; Throwing like this works in listeners and in the initial process.
+;;; Can't easily tell if a process is a listener.  Should be able to.
+(defun toplevel ()
+  (throw :toplevel nil))
+
+
+;;; It's not clear that this is the right behavior, but aborting CURRENT-PROCESS -
+;;; when no one's sure just what CURRENT-PROCESS is - doesn't seem right either.
+(defun interactive-abort ()
+  (interactive-abort-in-process *current-process*))
+
+(defun interactive-abort-in-process (p)
+  (if p (process-interrupt p 
+                           #'(lambda ()
+                               (unless *inhibit-abort*
+                                 (if *in-read-loop* 
+                                        (abort-break)
+                                        (abort))
+                                 )))))
+
+
+(defun abort (&optional condition)
+  "Transfer control to a restart named ABORT, signalling a CONTROL-ERROR if
+   none exists."
+  (invoke-restart-no-return (find-restart 'abort condition)))
+
+(defun continue (&optional condition)
+  "Transfer control to a restart named CONTINUE, or return NIL if none exists."
+  (let ((r (find-restart 'continue condition)))
+    (if r (invoke-restart r))))
+
+(defun muffle-warning (&optional condition)
+  "Transfer control to a restart named MUFFLE-WARNING, signalling a
+   CONTROL-ERROR if none exists."
+  (invoke-restart-no-return (find-restart 'muffle-warning condition)))
+
+(defun abort-break ()
+  (invoke-restart-no-return 'abort-break))
+
+
+(defun quit (&optional (exit 0) &key error-handler)
+  "exit must be either a (signed-byte 32) exit status or a function to call to exit lisp
+   error-handler can be a function of one argument, the condition, that will be called if an
+   error occurs while preparing to quit.  The error handler should exit"
+  (if (or (null exit) (typep exit '(signed-byte 32)))
+    (setq exit (let ((exit-status (or exit 0)))
+                 #'(lambda () (#__exit exit-status))))
+    (unless (typep exit 'function)
+      (report-bad-arg exit '(or (signed-byte 32) function))))
+  (let* ((ip *initial-process*)
+	 (cp *current-process*))
+    (when (process-verify-quit ip)
+      (process-interrupt ip
+			 #'(lambda ()
+                             (handler-bind ((error (lambda (c)
+                                                     (when error-handler
+                                                       (funcall error-handler c)))))
+                               (process-exit-application *current-process*
+                                                         #'(lambda ()
+                                                             (%set-toplevel nil)
+                                                             (funcall exit) ;; must exit
+                                                             (bug "Exit function didn't exit"))))))
+      (unless (eq cp ip)
+	(process-kill cp)))))
+
+
+(defloadvar *quitting* nil)
+
+
+(defun prepare-to-quit (&optional part)
+  (let-globally ((*quitting* t))
+    (when (or (null part) (eql 0 part))
+      (dolist (f *lisp-cleanup-functions*)
+	(funcall f)))
+    (let* ((stragglers ()))
+      (dolist (p (all-processes))
+	(unless (or (eq p *initial-process*)
+		    (not (process-active-p p)))
+	  (if (process-persistent p)
+	    (process-reset p :shutdown)
+	    (process-kill p))))
+      (dolist (p (all-processes))
+        (let* ((semaphore (process-termination-semaphore p)))
+          (when semaphore
+            (unless (eq p *initial-process*)
+              (unless (timed-wait-on-semaphore semaphore 0.05)
+                (push p stragglers))))))
+      (dolist (p stragglers)
+        (let* ((semaphore (process-termination-semaphore p)))
+          (maybe-finish-process-kill p :kill)
+          (when semaphore
+            (timed-wait-on-semaphore semaphore 0.10)))))
+    (shutdown-lisp-threads)
+    (loop
+      (let* ((streams (open-file-streams)))
+        (when (null streams) (return))
+        (let* ((ioblock (stream-ioblock (car streams) nil)))
+          (when ioblock
+            (setf (ioblock-inbuf-lock ioblock) nil
+                  (ioblock-outbuf-lock ioblock) nil
+                  (ioblock-owner ioblock) nil)))
+        (close (car streams))))
+    (setf (interrupt-level) -1)         ; can't abort after this
+    )
+  ;; Didn't abort, so really quitting.
+  (setq *quitting* t))
+
+
+(defun signal (condition &rest args)
+  "Invokes the signal facility on a condition formed from DATUM and
+   ARGUMENTS. If the condition is not handled, NIL is returned. If
+   (TYPEP condition *BREAK-ON-SIGNALS*) is true, the debugger is invoked
+   before any signalling is done."
+  (setq condition (condition-arg condition args 'simple-condition))
+  (let* ((*break-on-signals* *break-on-signals*))
+     (let* ((old-bos *break-on-signals*))
+       (when (unknown-ctype-p (let* ((*break-on-signals* nil)) (specifier-type old-bos)))
+	 (setq *break-on-signals* nil)
+	 (warn "~S : Ignoring invalid type specifier ~s." '*break-on-signals* old-bos)))
+	 
+   (when (typep condition *break-on-signals*)
+     (let ((*break-on-signals* nil))
+       (cbreak-loop "Signal" "Signal the condition." condition (%get-frame-ptr)))))
+  (let ((%handlers% %handlers%))
+    (while %handlers%
+      (do* ((tag (pop %handlers%)) (handlers tag (cddr handlers)))
+           ((null handlers))
+        (when (typep condition (car handlers))
+          (let ((fn (cadr handlers)))
+            (cond ((null fn) (throw tag condition))
+                  ((fixnump fn) (throw tag (cons fn condition)))
+                  (t (funcall fn condition)))))))))
+
+(defvar *error-print-circle* nil)   ; reset to T when we actually can print-circle
+
+
+
+;;;***********************************
+;;;Mini-evaluator
+;;;***********************************
+
+(defun new-lexical-environment (&optional parent)
+  (%istruct 'lexical-environment parent nil nil nil nil nil nil))
+
+(defmethod make-load-form ((e lexical-environment) &optional env)
+  (declare (ignore env))
+  nil)
+
+(defun new-definition-environment (&optional (type 'compile-file))
+  (%istruct 'definition-environment (list type)  nil nil nil nil nil nil nil nil nil nil nil nil ))
+
+(defun definition-environment (env &optional clean-only &aux parent)
+  (if (and env (not (istruct-typep env 'lexical-environment))) (report-bad-arg env 'lexical-environment))
+  (do* () 
+       ((or (null env) 
+            (listp (setq parent (lexenv.parent-env env)))
+            (and clean-only (or (lexenv.variables env) (lexenv.functions env)))))
+    (setq env parent))
+  (if (consp parent)
+    env))
+
+(defvar *symbol-macros* (make-hash-table :test #'eq))
+
+(defun %define-symbol-macro (name expansion)
+  (if (or (constant-symbol-p name)
+	  (proclaimed-special-p name))
+      (signal-program-error "Symbol ~s already globally defined as a ~A"
+			    name (if (constant-symbol-p name)
+				     'constant
+				     'variable)))
+  (setf (gethash name *symbol-macros*) expansion)
+  name)
+
+(defvar *macroexpand-hook* 'funcall
+  "The value of this variable must be a designator for a function that can
+  take three arguments, a macro expander function, the macro form to be
+  expanded, and the lexical environment to expand in. The function should
+  return the expanded form. This function is called by MACROEXPAND-1
+  whenever a runtime expansion is needed. Initially this is set to
+  FUNCALL.") ; Should be #'funcall. 
+;(queue-fixup (setq *macroexpand-hook* #'funcall)) ;  No it shouldn't.
+
+(defun %symbol-macroexpand-1 (sym env)
+  (flet ((expand-it (expansion)
+           (funcall *macroexpand-hook*
+                    (constantly expansion)
+                    sym
+                    env)))
+    (if (and env (not (istruct-typep env 'lexical-environment)))
+      (report-bad-arg env 'lexical-environment))
+    (do* ((env env (lexenv.parent-env env)))
+         ((null env))
+      (if (istruct-typep env 'definition-environment)
+	(let* ((info (assq sym (defenv.symbol-macros env))))
+	  (if info
+	    (return-from %symbol-macroexpand-1 (values (expand-it (cdr info)) t))
+	    (return)))
+	(let* ((vars (lexenv.variables env)))
+          (dolist (vdecl (lexenv.vdecls env))
+            (if (and (eq (car vdecl) sym)
+                     (eq (cadr vdecl) 'special))
+              (return-from %symbol-macroexpand-1 (values sym nil))))
+	  (when (consp vars)
+	    (let* ((info (dolist (var vars)
+			   (if (eq (var-name var) sym)
+                             (return var)))))            
+	      (when info
+		(if (and (consp (setq info (var-expansion info)))
+			 (eq (%car info) :symbol-macro))
+                  (return-from %symbol-macroexpand-1 (values (expand-it (%cdr info)) t))
+                  (return-from %symbol-macroexpand-1 (values sym nil)))))))))
+    ;; Look it up globally.
+    (multiple-value-bind (expansion win) (gethash sym *symbol-macros*)
+      (if win (values (expand-it expansion) t) (values sym nil)))))
+
+(defun macroexpand-all (form &optional (env (new-lexical-environment)))
+  "Recursivly expand all macros in FORM."
+  (flet ((mexpand (forms env)
+           (mapcar (lambda (form) (macroexpand-all form env)) forms)))
+    (macrolet ((destructuring-bind-body (binds form &body body)
+                 (if (eql '&body (first (last binds)))
+                   (let ((&body (gensym "&BODY")))
+                     `(destructuring-bind ,(append (butlast binds) (list '&body &body))
+                          ,form
+                        (multiple-value-bind (body decls)
+                            (parse-body ,&body env nil)
+                          ,@body)))
+                   `(destructuring-bind ,binds ,form ,@body))))
+      (multiple-value-bind (expansion win)
+          (macroexpand-1 form env)
+        (if win
+          (macroexpand-all expansion env)
+          (if (atom form)
+            form
+            (case (first form)
+              (macrolet
+               (destructuring-bind-body (macros &body) (rest form)
+                (setf env (augment-environment env
+                                               :macro (mapcar (lambda (macro)
+                                                                (destructuring-bind
+                                                                      (name arglist &body body)
+                                                                    macro
+                                                                  (list name (enclose (parse-macro name arglist body env)))))
+                                                              macros)
+                                               :declare (decl-specs-from-declarations decls)))
+                (let ((body (mexpand body env)))
+                  (if decls
+                    `(locally ,@decls ,@body)
+                    `(progn ,@body)))))
+              (symbol-macrolet
+               (destructuring-bind-body (symbol-macros &body) (rest form)
+                (setf env (augment-environment env :symbol-macro symbol-macros :declare (decl-specs-from-declarations decls)))
+                (let ((body (mexpand body env)))
+                  (if decls
+                    `(locally ,@decls ,@body)
+                    `(progn ,@body)))))
+              ((let let* compiler-let)
+               (destructuring-bind-body (bindings &body) (rest form)
+                `(,(first form)
+                   ,(mapcar (lambda (binding)
+                              
+                              (if (listp binding)
+                                (list (first binding) (macroexpand-all (second binding) env))
+                                binding))
+                            bindings)
+                   ,@decls
+                   ,@(mexpand body env))))
+              ((flet labels)
+               (destructuring-bind-body (bindings &body) (rest form)
+                 (let ((augmented-env
+                        (augment-environment env :function (mapcar #'car bindings))))
+                  `(,(first form)
+                     ,(mapcar (lambda (binding)
+                                (list* (first binding)
+                                       (cdr (macroexpand-all `(lambda ,@(rest binding))
+                                                             (if (eq (first form) 'labels)
+                                                                 augmented-env
+                                                                 env)))))
+                              bindings)
+                     ,@decls
+                     ,@(mexpand body augmented-env)))))
+              (nfunction (list* 'nfunction (second form) (macroexpand-all (third form) env)))
+              (function
+                 (if (and (consp (second form))
+                          (eql 'lambda (first (second form))))
+                   (destructuring-bind (lambda arglist &body body&decls)
+                       (second form)
+                     (declare (ignore lambda))
+                     (multiple-value-bind (body decls)
+                         (parse-body body&decls env)
+                       `(lambda ,arglist ,@decls ,@(mexpand body env))))
+                   form))
+              ((eval-when the locally block return-from)
+                 (list* (first form) (second form) (mexpand (cddr form) env)))
+              (setq
+                 `(setq ,@(loop for (name value) on (rest form) by #'cddr
+                                collect name
+                                collect (macroexpand-all value env))))
+              ((go quote) form)
+              ((fbind with-c-frame with-variable-c-frame ppc-lap-function)
+               (error "Unable to macroexpand ~S." form))
+              ((catch if load-time-value multiple-value-call multiple-value-prog1 progn
+                progv tagbody throw unwind-protect)
+               (cons (first form) (mexpand (rest form) env)))
+              (t
+               ;; need to check that (first form) is either fboundp or a local function...
+               (cons (first form) (mexpand (rest form) env))))))))))
+
+(defun macroexpand-1 (form &optional env &aux fn)
+  "If form is a macro (or symbol macro), expand it once. Return two values,
+   the expanded form and a T-or-NIL flag indicating whether the form was, in
+   fact, a macro. ENV is the lexical environment to expand in, which defaults
+   to the null environment."
+  (declare (resident))
+  (if (and (consp form)
+           (symbolp (%car form)))
+    (if (setq fn (macro-function (%car form) env))
+      (values (funcall *macroexpand-hook* fn form env) t)
+      (values form nil))
+    (if (and form (symbolp form))
+      (%symbol-macroexpand-1 form env)
+      (values form nil))))
+
+(defun macroexpand (form &optional env)
+  "Repetitively call MACROEXPAND-1 until the form can no longer be expanded.
+   Returns the final resultant form, and T if it was expanded. ENV is the
+   lexical environment to expand in, or NIL (the default) for the null
+   environment."
+  (declare (resident))
+  (multiple-value-bind (new win) (macroexpand-1 form env)
+    (do* ((won-at-least-once win))
+         ((null win) (values new won-at-least-once))
+      (multiple-value-setq (new win) (macroexpand-1 new env)))))
+
+(defun %symbol-macroexpand (form env &aux win won)
+  ; Keep expanding until no longer a symbol-macro or no longer a symbol.
+  (loop
+    (unless (and form (symbolp form)) (return))
+    (multiple-value-setq (form win) (macroexpand-1 form env))
+    (if win (setq won t) (return)))
+  (values form won))
+
+(defun retain-lambda-expression (name lambda-expression env)
+  (if (and (let* ((lambda-list (cadr lambda-expression)))
+             (and (not (memq '&lap lambda-list))
+                  (not (memq '&method lambda-list))
+                  (not (memq '&lexpr lambda-list))))
+           (nx-declared-inline-p name env)
+           (not (gethash name *nx1-alphatizers*))
+           ; A toplevel definition defined inside a (symbol-)macrolet should
+           ; be inlineable.  It isn't; call DEFINITION-ENVIRONMENT with a
+           ; "clean-only" argument to ensure that there are no lexically
+           ; bound macros or symbol-macros.
+           (definition-environment env t))
+    lambda-expression))
+
+
+(defun %cons-def-info (type &optional lfbits keyvect data specializers qualifiers)
+  (ecase type
+    (defun nil)
+    (defmacro (setq data '(macro) lfbits nil)) ;; some code assumes lfbits=nil
+    (defgeneric (setq data (list :methods) lfbits (logior (ash 1 $lfbits-gfn-bit) lfbits)))
+    (defmethod (setq data (list :methods
+                                (%cons-def-info-method lfbits keyvect qualifiers specializers))
+                     lfbits (logandc2 lfbits (ash 1 $lfbits-aok-bit))
+                     keyvect nil))
+    (deftype (setq data '(type) lfbits (cons nil *loading-file-source-file*))))
+  (vector lfbits keyvect *loading-file-source-file* data))
+
+(defun def-info.lfbits (def-info)
+  (and def-info
+       (let ((lfbits (svref def-info 0)))
+	 (if (consp lfbits) (%car lfbits) lfbits))))
+
+(defun def-info.keyvect (def-info)
+  (and def-info (svref def-info 1)))
+
+(defun def-info.file (def-info)
+  (and def-info (svref def-info 2)))
+
+(defun def-info.lambda (def-info)
+  (and def-info
+       (let ((data (svref def-info 3)))
+	 (and (eq (car data) 'lambda) data))))
+
+(defun def-info.methods (def-info)
+  (and def-info
+       (let ((data (svref def-info 3)))
+	 (and (eq (car data) :methods) (%cdr data)))))
+
+(defun %cons-def-info-method (lfbits keyvect qualifiers specializers)
+  (cons (cons (and keyvect
+		   (if (logbitp $lfbits-aok-bit lfbits)
+		     (and (not (logbitp $lfbits-rest-bit lfbits))
+			  (list keyvect))
+		     keyvect))
+              *loading-file-source-file*)
+        (cons qualifiers specializers)))
+
+(defun def-info-method.keyvect (def-info-method)
+  (let ((kv (caar def-info-method)))
+    (if (listp kv)
+      (values (car kv) t)
+      (values kv  nil))))
+
+(defun def-info-method.file (def-info-method)
+  (cdar def-info-method))
+
+(defun def-info-with-new-methods (def-info new-bits new-methods)
+  (if (and (eq new-methods (def-info.methods def-info))
+           (eql new-bits (def-info.lfbits def-info)))
+    def-info
+    (let ((new (copy-seq def-info))
+          (old-bits (svref def-info 0)))
+      (setf (svref new 0) (if (consp old-bits) (cons new-bits (cdr old-bits)) old-bits))
+      (setf (svref new 3) (cons :methods new-methods))
+      new)))
+
+(defun def-info.macro-p (def-info)
+  (let ((data (and def-info (svref def-info 3))))
+    (eq (car data) 'macro)))
+
+(defun def-info.function-p (def-info)
+  (not (and def-info (eq (car (svref def-info 3)) 'type))))
+
+(defun def-info.function-type (def-info)
+  (if (null def-info)
+    nil ;; ftype only, for the purposes here, is same as nothing.
+    (let ((data (svref def-info 3)))
+      (ecase (car data)
+	((nil lambda) 'defun)
+	(:methods 'defgeneric)
+	(macro 'defmacro)
+	(ftype nil)
+	(type nil)))))
+
+(defun def-info.deftype (def-info)
+  (and def-info
+       (let ((bits (svref def-info 0)))
+	 ;; bits or (bits . type-source-file)
+	 (and (consp bits) bits))))
+
+(defun def-info.deftype-type (def-info)
+  ;; 'class (for defclass/defstruct) or 'macro (for deftype et. al.)
+  (and def-info
+       (consp (svref def-info 0))
+       (svref def-info 1)))
+
+(defparameter *one-arg-defun-def-info* (%cons-def-info 'defun (encode-lambda-list '(x))))
+
+(defvar *compiler-warn-on-duplicate-definitions* t)
+
+(defun combine-deftype-infos (name def-info old-deftype new-deftype)
+  (when (or new-deftype old-deftype)
+    (when (and old-deftype new-deftype *compiler-warn-on-duplicate-definitions*)
+      (nx1-whine :duplicate-definition
+		 `(type ,name)
+		 (cdr old-deftype)
+		 (cdr new-deftype)))
+    (let ((target (if new-deftype
+		      (or (cdr new-deftype) (cdr old-deftype))
+		      (cdr old-deftype)))
+	  (target-deftype (def-info.deftype def-info)))
+      (unless (and target-deftype (eq (cdr target-deftype) target))
+	(setq def-info (copy-seq (or def-info '#(nil nil nil (ftype)))))
+	(setf (svref def-info 0) (cons (def-info.lfbits def-info) target)))))
+  def-info)
+
+#+debug
+(defun describe-def-info (def-info)
+  (list :lfbits (def-info.lfbits def-info)
+	:keyvect (def-info.keyvect def-info)
+	:macro-p (def-info.macro-p def-info)
+	:function-p (def-info.function-p def-info)
+	:lambda (and (def-info.function-p def-info) (def-info.lambda def-info))
+	:methods (and (def-info.function-p def-info) (def-info.methods def-info))
+	:function-type (def-info.function-type def-info)
+	:deftype (def-info.deftype def-info)
+	:deftype-type (def-info.deftype-type def-info)))
+
+(defun combine-gf-def-infos (name old-info new-info)
+  (let* ((old-bits (def-info.lfbits old-info))
+         (new-bits (def-info.lfbits new-info))
+         (old-methods (def-info.methods old-info))
+         (new-methods (def-info.methods new-info)))
+    (when (and (logbitp $lfbits-gfn-bit old-bits) (logbitp $lfbits-gfn-bit new-bits))
+      (when *compiler-warn-on-duplicate-definitions*
+        (nx1-whine :duplicate-definition
+                   name
+                   (def-info.file old-info)
+                   (def-info.file new-info)))
+      (return-from combine-gf-def-infos new-info))
+    (unless (congruent-lfbits-p old-bits new-bits)
+      (if (logbitp $lfbits-gfn-bit new-bits)
+        ;; A defgeneric, incongruent with previously defined methods
+        (nx1-whine :incongruent-gf-lambda-list name)
+        ;; A defmethod incongruent with previously defined explicit or implicit generic
+        (nx1-whine :incongruent-method-lambda-list
+                   (if new-methods `(:method ,@(cadar new-methods) ,name ,(cddar new-methods)) name)
+                   name))
+      ;; Perhaps once this happens, should just mark it somehow to not complain again
+      (return-from combine-gf-def-infos 
+        (if (logbitp $lfbits-gfn-bit old-bits) old-info new-info)))
+    (loop for new-method in new-methods
+          as old = (member (cdr new-method) old-methods :test #'equal :key #'cdr)
+          do (when old
+               (when *compiler-warn-on-duplicate-definitions*
+                 (nx1-whine :duplicate-definition
+                            `(:method ,@(cadr new-method) ,name ,(cddr new-method))
+                            (def-info-method.file (car old))
+                            (def-info-method.file new-method)))
+               (setq old-methods (remove (car old) old-methods :test #'eq)))
+          do (push new-method old-methods))
+    (cond ((logbitp $lfbits-gfn-bit new-bits)
+           ;; If adding a defgeneric, use its info.
+           (setq old-info new-info old-bits new-bits))
+          ((not (logbitp $lfbits-gfn-bit old-bits))
+           ;; If no defgeneric (yet?) just remember whether any method has &key
+           (setq old-bits (logior old-bits (logand new-bits (ash 1 $lfbits-keys-bit))))))
+    ;; Check that all methods implement defgeneric keys
+    (let ((gfkeys (and (logbitp $lfbits-gfn-bit old-bits) (def-info.keyvect old-info))))
+      (when (> (length gfkeys) 0)
+        (loop for minfo in old-methods
+              do (multiple-value-bind (mkeys aok) (def-info-method.keyvect minfo)
+                   (when (and mkeys
+                              (not aok)
+                              (setq mkeys (loop for gk across gfkeys
+                                                unless (find gk mkeys) collect gk)))
+                     (nx1-whine :gf-keys-not-accepted
+                                `(:method ,@(cadr minfo) ,name ,(cddr minfo))
+                                mkeys))))))
+    (def-info-with-new-methods old-info old-bits old-methods)))
+
+(defun combine-definition-infos (name old-info new-info)
+  (let ((old-type (def-info.function-type old-info))
+	(old-deftype (def-info.deftype old-info))
+        (new-type (def-info.function-type new-info))
+	(new-deftype (def-info.deftype new-info)))
+    (cond ((and (eq old-type 'defgeneric) (eq new-type 'defgeneric))
+           (setq new-info (combine-gf-def-infos name old-info new-info)))
+	  ((or (eq (or old-type 'defun) (or new-type 'defun))
+	       (eq (or old-type 'defgeneric) (or new-type 'defgeneric)))
+           (when (and old-type new-type *compiler-warn-on-duplicate-definitions*)
+             (nx1-whine :duplicate-definition name (def-info.file old-info) (def-info.file new-info)))
+	   (unless new-info (setq new-info old-info)))
+          (t
+	   (when (and (def-info.function-p old-info) (def-info.function-p new-info)
+		      *compiler-warn-on-duplicate-definitions*)
+             (apply #'nx1-whine :duplicate-definition
+                    name
+                    (def-info.file old-info)
+                    (def-info.file new-info)
+                    (cond ((eq old-type 'defmacro) '("macro" "function"))
+                          ((eq new-type 'defmacro) '("function" "macro"))
+                          ((eq old-type 'defgeneric) '("generic function" "function"))
+                          (t '("function" "generic function")))))
+	   (unless new-type (setq new-info old-info))))
+    (combine-deftype-infos name new-info old-deftype new-deftype)))
+
+(defun record-definition-info (name info env)
+  (let* ((definition-env (definition-environment env)))
+    (if definition-env
+      (let* ((defs (defenv.defined definition-env))
+             (already (if (listp defs) (assq name defs) (gethash name defs))))
+        (if already
+          (setf (%cdr already) (combine-definition-infos name (%cdr already) info))
+          (let ((outer (loop for defer = (cdr (defenv.type definition-env))
+                               then (deferred-warnings.parent defer)
+                             while (typep defer 'deferred-warnings)
+                             thereis (gethash name (deferred-warnings.defs defer)))))
+            (when outer
+              (setq info (combine-definition-infos name (%cdr outer) info)))
+            (let ((new (cons name info)))
+              (if (listp defs)
+                (setf (defenv.defined definition-env) (cons new defs))
+                (setf (gethash name defs) new)))))
+        info))))
+
+(defun record-function-info (name info env)
+  (record-definition-info name info env))
+
+;;; This is different from AUGMENT-ENVIRONMENT.
+(defun note-function-info (name lambda-expression env)
+  (let* ((info nil)
+         (name (maybe-setf-function-name name)))
+    (when (lambda-expression-p lambda-expression)
+      (multiple-value-bind (lfbits keyvect) (encode-lambda-list (cadr lambda-expression) t)
+        (setq info (%cons-def-info 'defun lfbits keyvect
+                                   (retain-lambda-expression name lambda-expression env)))))
+    (record-function-info name info env))
+  name)
+
+(defun note-type-info (name kind env)
+  (record-definition-info name (%cons-def-info 'deftype nil kind) env))
+
+
+; And this is different from FUNCTION-INFORMATION.
+(defun retrieve-environment-function-info (name env)
+ (let ((defenv (definition-environment env)))
+   (when defenv
+     (let* ((defs (defenv.defined defenv))
+	    (sym (maybe-setf-function-name name))
+	    (info (if (listp defs) (assq sym defs) (gethash sym defs))))
+       (and info (def-info.function-p (cdr info)) info)))))
+
+;;; Must differ from -something-, but not sure what ... 
+(defun note-variable-info (name info env)
+  (let ((definition-env (definition-environment env)))
+    (if definition-env (push (cons name info) (defenv.specials definition-env)))
+    name))
+
+(defun compile-file-environment-p (env)
+  (let ((defenv (definition-environment env)))
+    (and defenv (eq 'compile-file (car (defenv.type defenv))))))
+
+;; This is EVAL.
+(defun cheap-eval (form)
+  ;; Don't record source locations for explicit calls to EVAL.
+  (let ((*nx-source-note-map* nil))
+    (cheap-eval-in-environment form nil)))
+
+; used by nfcomp too
+; Should preserve order of decl-specs; it sometimes matters.
+(defun decl-specs-from-declarations (declarations)
+  (let ((decl-specs nil))
+    (dolist (declaration declarations decl-specs)
+      ;(unless (eq (car declaration) 'declare) (say "what"))
+      (dolist (decl-spec (cdr declaration))
+        (setq decl-specs (nconc decl-specs (list decl-spec)))))))
+
+(defun cheap-eval-macroexpand-1 (form env)
+  (multiple-value-bind (new win) (macroexpand-1 form env)
+    (when win
+      (note-source-transformation form new))
+    (values new win)))
+
+(defun cheap-eval-transform (original new)
+  (note-source-transformation original new)
+  new)
+
+(defun cheap-eval-function (name lambda env)
+  (multiple-value-bind (lfun warnings)
+                       (compile-named-function lambda
+                                               :name name
+                                               :env env
+                                               :function-note *loading-toplevel-location*
+                                               :keep-lambda *save-definitions*
+                                               :keep-symbols *save-local-symbols*
+                                               :source-notes *nx-source-note-map*)
+    (signal-or-defer-warnings warnings env)
+    lfun))
+
+(fset 'nx-source-note (nlambda bootstrapping-source-note (form) (declare (ignore form)) nil))
+
+(defun cheap-eval-in-environment (form env &aux sym)
+  (declare (resident))
+  ;; records source locations if *nx-source-note-map* is bound by caller
+  (setq *loading-toplevel-location* (or (nx-source-note form) *loading-toplevel-location*))
+  (flet ((progn-in-env (body&decls parse-env base-env)
+           (multiple-value-bind (body decls) (parse-body body&decls parse-env)
+             (setq base-env (augment-environment base-env :declare (decl-specs-from-declarations decls)))
+             (loop with default-location = *loading-toplevel-location*
+               while (cdr body) as form = (pop body)
+               do (cheap-eval-in-environment form base-env)
+               do (setq *loading-toplevel-location* default-location))
+             (cheap-eval-in-environment (car body) base-env))))
+    (if form
+      (cond ((symbolp form) 
+             (multiple-value-bind (expansion win) (cheap-eval-macroexpand-1 form env)
+               (if win 
+                 (cheap-eval-in-environment expansion env)
+                 (let* ((defenv (definition-environment env))
+                        (constant (if defenv (assq form (defenv.constants defenv))))
+                        (constval (%cdr constant)))
+                   (if constant
+                     (if (neq (%unbound-marker-8) constval)
+                       constval
+                       (error "Can't determine value of constant symbol ~s" form))
+                     (if (constant-symbol-p form)
+                       (%sym-global-value form)
+                       (symbol-value form)))))))
+            ((atom form) form)
+            ((eq (setq sym (%car form)) 'quote)
+             (verify-arg-count form 1 1)
+             (%cadr form))
+            ((eq sym 'function)
+             (verify-arg-count form 1 1)
+             (cond ((symbolp (setq sym (%cadr form)))
+                    (multiple-value-bind (kind local-p)
+                        (function-information sym env)
+                      (if (and local-p (eq kind :macro))
+                        (error "~s can't be used to reference lexically defined macro ~S" 'function sym)))
+                    (%function sym))
+                   ((setf-function-name-p sym)
+                    (multiple-value-bind (kind local-p)
+                        (function-information sym env)
+                      (if (and local-p (eq kind :macro))
+                        (error "~s can't be used to reference lexically defined macro ~S" 'function sym)))
+                    (%function (setf-function-name (%cadr sym))))
+                   (t (cheap-eval-function nil sym env))))
+            ((eq sym 'nfunction)
+             (verify-arg-count form 2 2)
+             (cheap-eval-function (%cadr form) (%caddr form) env))
+            ((eq sym 'progn) (progn-in-env (%cdr form) env env))
+            ((eq sym 'setq)
+             (if (not (%ilogbitp 0 (list-length form)))
+               (verify-arg-count form 0 0)) ;Invoke a "Too many args" error.
+             (let* ((sym nil)
+                    (val nil)
+                    (original form))
+               (while (setq form (%cdr form))
+                 (setq sym (require-type (pop form) 'symbol))
+                 (multiple-value-bind (expansion expanded)
+                                      (cheap-eval-macroexpand-1 sym env)
+                   (if expanded
+                     (setq val (cheap-eval-in-environment
+                                (cheap-eval-transform original `(setf ,expansion ,(%car form)))
+                                env))
+                     (set sym (setq val (cheap-eval-in-environment (%car form) env))))))
+               val))
+            ((eq sym 'eval-when)
+             (destructuring-bind (when . body) (%cdr form)
+               (when (or (memq 'eval when) (memq :execute when)) (progn-in-env body env env))))
+            ((eq sym 'if)
+             (destructuring-bind (test true &optional false) (%cdr form)
+               (setq test (let ((*loading-toplevel-location* *loading-toplevel-location*))
+                            (cheap-eval-in-environment test env)))
+               (cheap-eval-in-environment (if test true false) env)))
+            ((eq sym 'locally) (progn-in-env (%cdr form) env env))
+            ((eq sym 'symbol-macrolet)
+	     (multiple-value-bind (body decls) (parse-body (cddr form) env)
+	       (progn-in-env body env (augment-environment env :symbol-macro (cadr form) :declare (decl-specs-from-declarations decls)))))
+            ((eq sym 'macrolet)
+             (let ((temp-env (augment-environment env
+                                                  :macro 
+                                                  (mapcar #'(lambda (m)
+                                                              (destructuring-bind (name arglist &body body) m
+                                                                (list name (enclose (parse-macro name arglist body env)
+                                                                                    env))))
+                                                          (cadr form)))))
+               (progn-in-env (cddr form) temp-env temp-env)))
+            ((and (symbolp sym) 
+                  (compiler-special-form-p sym)
+                  (not (functionp (fboundp sym))))
+             (if (eq sym 'unwind-protect)
+               (destructuring-bind (protected-form . cleanup-forms) (cdr form)
+                 (unwind-protect
+                     (let ((*loading-toplevel-location* *loading-toplevel-location*))
+                       (cheap-eval-in-environment protected-form env))
+                   (progn-in-env cleanup-forms env env)))
+               (let ((fn (cheap-eval-function nil (cheap-eval-transform form `(lambda () (progn ,form))) env)))
+                 (funcall fn))))
+            ((and (symbolp sym) (macro-function sym env))
+             (cheap-eval-in-environment (cheap-eval-macroexpand-1 form env) env))
+            ((or (symbolp sym)
+                 (and (consp sym) (eq (%car sym) 'lambda)))
+             (let ((args nil) (form-location *loading-toplevel-location*))
+               (dolist (elt (%cdr form))
+                 (push (cheap-eval-in-environment elt env) args)
+                 (setq *loading-toplevel-location* form-location))
+               (apply #'call-check-regs (if (symbolp sym) sym (cheap-eval-function nil sym env))
+                      (nreverse args))))
+            (t (signal-simple-condition 'simple-program-error "Car of ~S is not a function name or lambda-expression." form))))))
+
+
+(%fhave 'eval #'cheap-eval)
+
+
+
+  
+(defun call-check-regs (fn &rest args)
+  (declare (dynamic-extent args)
+           (optimize (debug 3)))        ; don't use any saved registers
+  (let ((old-regs (multiple-value-list (get-saved-register-values))))
+    (declare (dynamic-extent old-regs))
+    (multiple-value-prog1 (apply fn args)
+      (let* ((new-regs (multiple-value-list (get-saved-register-values)))
+             (new-regs-tail new-regs))
+        (declare (dynamic-extent new-regs))
+        (unless (dolist (old-reg old-regs t)
+                  (unless (eq old-reg (car new-regs-tail))
+                    (return nil))
+                  (pop new-regs-tail))
+          (apply 'error "Registers clobbered applying ~s to ~s~%~@{~a sb: ~s, Was: ~s~%~}"
+                 fn args
+                 (mapcan 'list
+                         (let ((res nil))
+                           (dotimes (i (length old-regs))
+                             (push (format nil "save~d" i) res))
+                           (nreverse res))
+                         old-regs
+                         new-regs)))))))
+
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Stack frame accessors.
+
+; Kinda scant, wouldn't you say ?
+
+
+;end of L1-readloop.lisp
+
Index: /branches/new-random/level-1/l1-sockets.lisp
===================================================================
--- /branches/new-random/level-1/l1-sockets.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-sockets.lisp	(revision 13309)
@@ -0,0 +1,1510 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+
+;;; basic socket API
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (export '(MAKE-SOCKET
+	    ACCEPT-CONNECTION
+	    DOTTED-TO-IPADDR
+	    IPADDR-TO-DOTTED
+	    IPADDR-TO-HOSTNAME
+	    LOOKUP-HOSTNAME
+	    LOOKUP-PORT
+	    ;;with-pending-connect
+	    RECEIVE-FROM
+	    SEND-TO
+	    SHUTDOWN
+	    ;;socket-control
+	    SOCKET-OS-FD
+	    REMOTE-HOST
+	    REMOTE-PORT
+	    REMOTE-FILENAME
+	    LOCAL-HOST
+	    LOCAL-PORT
+	    LOCAL-FILENAME
+	    SOCKET-ADDRESS-FAMILY
+	    SOCKET-CONNECT
+	    SOCKET-FORMAT
+	    SOCKET-TYPE
+	    SOCKET-ERROR
+	    SOCKET-ERROR-CODE
+	    SOCKET-ERROR-IDENTIFIER
+	    SOCKET-ERROR-SITUATION
+	    WITH-OPEN-SOCKET))
+  #+windows-target
+  (defmacro check-winsock-error (form)
+    (let* ((val (gensym)))
+      `(let* ((,val ,form))
+        (if (< ,val 0)
+          (%get-winsock-error)
+          ,val))))
+  (defmacro check-socket-error (form)
+    #+windows-target `(check-winsock-error ,form)
+    #-windows-target `(int-errno-call ,form))
+  )
+
+
+#+windows-target
+(defun %get-winsock-error ()
+  (- (#_WSAGetLastError)))
+
+;;; The PPC is big-endian (uses network byte order), which makes
+;;; things like #_htonl and #_htonl no-ops.  These functions aren't
+;;; necessarily defined as functions in some header files (I'm sure
+;;; that that either complies with or violates some C standard), and
+;;; it doesn't seem to make much sense to fight that to do ff-calls
+;;; to a couple of identity functions.
+
+#+big-endian-target
+(progn
+  (defmacro HTONL (x) x)
+  (defmacro HTONS (x) x)
+  (defmacro NTOHL (x) x)
+  (defmacro NTOHS (x) x))
+
+#+little-endian-target
+(progn
+  (declaim (inline %bswap32 %bswap16))
+  (defun %bswap32 (x)
+    (declare (type (unsigned-byte 32) x))
+    (%swap-u32 x))
+  (defun %bswap16 (x)
+    (declare (type (unsigned-byte 16) x))
+    (%swap-u16 x))
+  (defmacro HTONL (x) `(%bswap32 ,x))
+  (defmacro HTONS (x) `(%bswap16 ,x))
+  (defmacro NTOHL (x) `(%bswap32 ,x))
+  (defmacro NTOHS (x) `(%bswap16 ,x)))
+
+(defparameter *default-socket-character-encoding*
+  nil)
+
+(defmethod default-character-encoding ((domain (eql :socket)))
+  *default-socket-character-encoding*)
+  
+
+;;; On some (hypothetical) little-endian platform, we might want to
+;;; define HTONL and HTONS to actually swap bytes around.
+
+(defpackage "OPENMCL-SOCKET"
+  (:use "CL")
+  (:import-from "CCL"
+		"MAKE-SOCKET"
+		"ACCEPT-CONNECTION"
+		"DOTTED-TO-IPADDR"
+		"IPADDR-TO-DOTTED"
+		"IPADDR-TO-HOSTNAME"
+		"LOOKUP-HOSTNAME"
+		"LOOKUP-PORT"
+		;;with-pending-connect
+		"RECEIVE-FROM"
+		"SEND-TO"
+		"SHUTDOWN"
+		;;socket-control
+		"SOCKET-OS-FD"
+		"REMOTE-HOST"
+		"REMOTE-PORT"
+		"REMOTE-FILENAME"
+		"LOCAL-HOST"
+		"LOCAL-PORT"
+		"LOCAL-FILENAME"
+		"SOCKET-ADDRESS-FAMILY"
+		"SOCKET-CONNECT"
+		"SOCKET-FORMAT"
+		"SOCKET-TYPE"
+		"SOCKET-ERROR"
+		"SOCKET-ERROR-CODE"
+		"SOCKET-ERROR-IDENTIFIER"
+		"SOCKET-ERROR-SITUATION"
+		"WITH-OPEN-SOCKET")
+  (:export  "MAKE-SOCKET"
+	    "ACCEPT-CONNECTION"
+	    "DOTTED-TO-IPADDR"
+	    "IPADDR-TO-DOTTED"
+	    "IPADDR-TO-HOSTNAME"
+	    "LOOKUP-HOSTNAME"
+	    "LOOKUP-PORT"
+	    ;;with-pending-connect
+	    "RECEIVE-FROM"
+	    "SEND-TO"
+	    "SHUTDOWN"
+	    ;;socket-control
+	    "SOCKET-OS-FD"
+	    "REMOTE-HOST"
+	    "REMOTE-PORT"
+	    "REMOTE-FILENAME"
+	    "LOCAL-HOST"
+	    "LOCAL-PORT"
+	    "LOCAL-FILENAME"
+	    "SOCKET-ADDRESS-FAMILY"
+	    "SOCKET-CONNECT"
+	    "SOCKET-FORMAT"
+	    "SOCKET-TYPE"
+	    "SOCKET-ERROR"
+	    "SOCKET-ERROR-CODE"
+	    "SOCKET-ERROR-IDENTIFIER"
+	    "SOCKET-ERROR-SITUATION"
+	    "WITH-OPEN-SOCKET"))
+
+
+
+(define-condition socket-error (simple-stream-error)
+  ((code :initarg :code :reader socket-error-code)
+   (identifier :initform :unknown :initarg :identifier :reader socket-error-identifier)
+   (Situation :initarg :situation :reader socket-error-situation)))
+
+(define-condition socket-creation-error (simple-error)
+  ((code :initarg :code :reader socket-creation-error-code)
+   (identifier :initform :unknown :initarg :identifier :reader socket-creation-error-identifier)
+   (situation :initarg :situation :reader socket-creation-error-situation)))
+
+(defvar *socket-error-identifiers*
+  #-windows-target
+  (list #$EADDRINUSE :address-in-use
+	#$ECONNABORTED :connection-aborted
+	#$ENOBUFS :no-buffer-space
+	#$ENOMEM :no-buffer-space
+	#$ENFILE :no-buffer-space
+	#$ETIMEDOUT :connection-timed-out
+	#$ECONNREFUSED :connection-refused
+	#$ENETUNREACH :host-unreachable
+	#$EHOSTUNREACH :host-unreachable
+	#$EHOSTDOWN :host-down
+	#$ENETDOWN :network-down
+	#$EADDRNOTAVAIL :address-not-available
+	#$ENETRESET :network-reset
+	#$ECONNRESET :connection-reset
+	#$ESHUTDOWN :shutdown
+	#$EACCES :access-denied
+	#$EPERM :access-denied)
+  #+windows-target
+  (list #$WSAEADDRINUSE :address-in-use
+	#$WSAECONNABORTED :connection-aborted
+	#$WSAENOBUFS :no-buffer-space
+	#$ENOMEM :no-buffer-space
+	#$ENFILE :no-buffer-space
+	#$WSAETIMEDOUT :connection-timed-out
+	#$WSAECONNREFUSED :connection-refused
+	#$WSAENETUNREACH :host-unreachable
+	#$WSAEHOSTUNREACH :host-unreachable
+	#$WSAEHOSTDOWN :host-down
+	#$WSAENETDOWN :network-down
+	#$WSAEADDRNOTAVAIL :address-not-available
+	#$WSAENETRESET :network-reset
+	#$WSAECONNRESET :connection-reset
+	#$WSAESHUTDOWN :shutdown
+	#$EACCES :access-denied
+	#$EPERM :access-denied)
+  )
+
+
+(declaim (inline socket-call))
+(defun socket-call (stream where res)
+  (if (< res 0)
+    (socket-error stream where res)
+    res))
+
+#-windows-target
+(defun %gai-strerror (errno)
+  (let* ((err (abs errno))
+         (p (#_gai_strerror err)))
+    (if (%null-ptr-p p)
+      (format nil "Unknown nameserver error ~d" err)
+      (%get-cstring p))))
+    
+
+
+(defun socket-error (stream where errno &optional nameserver-p)
+  "Creates and signals (via error) one of two socket error 
+conditions, based on the state of the arguments."
+  #+windows-target (declare (ignore nameserver-p))
+  (when (< errno 0)
+    (setq errno (- errno)))
+  (if stream
+    (error (make-condition 'socket-error
+			   :stream stream
+			   :code errno
+			   :identifier (getf *socket-error-identifiers* errno :unknown)
+			   :situation where
+			   ;; TODO: this is a constant arg, there is a way to put this
+			   ;; in the class definition, just need to remember how...
+			   :format-control "~a (error #~d) during ~a"
+			   :format-arguments (list
+                                              #+windows-target
+                                              (%windows-error-string errno)
+                                              #-windows-target
+					      (if nameserver-p
+						(%gai-strerror errno)
+						(%strerror errno))
+					      errno where)))
+    (error (make-condition 'socket-creation-error
+			   :code errno
+			   :identifier (getf *socket-error-identifiers* errno :unknown)
+			   :situation where
+			   ;; TODO: this is a constant arg, there is a way to put this
+			   ;; in the class definition, just need to remember how...
+			   :format-control "~a (error #~d) during socket creation or nameserver operation in ~a"
+			   :format-arguments (list
+                                              #+windows-target
+                                              (%windows-error-string errno)
+                                              #-windows-target
+					      (if nameserver-p
+						(%gai-strerror errno)
+						(%strerror errno))
+					      errno where)))))
+    
+
+
+;; If true, this will try to allow other cooperative processes to run
+;; while socket io is happening.  Since CCL threads are preemptively
+;; scheduled, this isn't particularly meaningful.
+(defvar *multiprocessing-socket-io* nil)
+
+(defclass socket ()
+  ())
+
+(defmacro with-open-socket ((var . args) &body body
+			    &aux (socket (make-symbol "socket"))
+			         (done (make-symbol "done")))
+  "Execute body with var bound to the result of applying make-socket to
+make-socket-args. The socket gets closed on exit."
+  `(let (,socket ,done)
+     (unwind-protect
+	 (multiple-value-prog1
+	   (let ((,var (setq ,socket (make-socket ,@args))))
+	     ,@body)
+	   (setq ,done t))
+       (when ,socket (close ,socket :abort (not ,done))))))
+
+(defgeneric socket-address-family (socket)
+  (:documentation "Return :internet or :file, as appropriate."))
+
+(defclass ip-socket (socket)
+  ())
+
+(defmethod socket-address-family ((socket ip-socket)) :internet)
+
+(defclass file-socket (socket)
+  ())
+
+(defmethod socket-address-family ((socket file-socket)) :file)
+
+(defclass tcp-socket (ip-socket)
+  ())
+
+(defgeneric socket-type (socket)
+  (:documentation
+   "Return :stream for tcp-stream and listener-socket, and :datagram
+for udp-socket."))
+
+(defmethod socket-type ((socket tcp-socket)) :stream)
+
+(defclass stream-file-socket (file-socket)
+  ())
+
+(defmethod socket-type ((socket stream-file-socket)) :stream)
+
+
+;;; An active TCP socket is an honest-to-goodness stream.
+(defclass tcp-stream (tcp-socket)
+  ())
+
+(defclass fundamental-tcp-stream (tcp-stream
+                                  fd-stream
+                                  buffered-binary-io-stream-mixin
+                                  buffered-character-io-stream-mixin)
+    ())
+
+(make-built-in-class 'basic-tcp-stream
+                     'tcp-stream
+                     'basic-binary-io-stream
+                     'basic-character-io-stream)
+
+(defgeneric socket-connect (stream)
+ (:documentation
+   "Return :active for tcp-stream, :passive for listener-socket, and NIL
+for udp-socket"))
+
+(defmethod socket-connect ((stream tcp-stream)) :active)
+
+(defgeneric socket-format (stream)
+  (:documentation
+   "Return the socket format as specified by the :format argument to
+make-socket."))
+
+(defmethod socket-format ((stream tcp-stream))
+  (if (eq (stream-element-type stream) 'character)
+    :text
+    ;; Should distinguish between :binary and :bivalent, but hardly
+    ;; seems worth carrying around an extra slot just for that.
+    :bivalent))
+
+(defmethod socket-device ((stream tcp-stream))
+  (let ((ioblock (stream-ioblock stream nil)))
+    (and ioblock (ioblock-device ioblock))))
+
+(defmethod select-stream-class ((class tcp-stream) in-p out-p char-p)
+  (declare (ignore char-p)) ; TODO: is there any real reason to care about this?
+  ;; Yes, in general.  There is.
+  (assert (and in-p out-p) () "Non-bidirectional tcp stream?")
+  'fundamental-tcp-stream)
+
+(defmethod map-to-basic-stream-class-name ((name (eql 'tcp-stream)))
+  'basic-tcp-stream)
+
+(defmethod select-stream-class ((s (eql 'basic-tcp-stream)) in-p out-p char-p)
+  (declare (ignore char-p))
+  (assert (and in-p out-p) () "Non-bidirectional tcp stream?")
+  'basic-tcp-stream)
+
+;;; A FILE-SOCKET-STREAM is also honest. To goodness.
+(defclass file-socket-stream (stream-file-socket)
+  ())
+
+(defclass fundamental-file-socket-stream (file-socket-stream
+                                          fd-stream
+                                          buffered-binary-io-stream-mixin
+                                          buffered-character-io-stream-mixin)
+    ())
+
+(make-built-in-class 'basic-file-socket-stream
+                     'file-socket-stream
+                     'basic-binary-io-stream
+                     'basic-character-io-stream)
+
+
+(defmethod map-to-basic-stream-class-name ((name (eql 'file-socket-stream)))
+  'basic-file-socket-stream)
+
+(defmethod select-stream-class ((class file-socket-stream) in-p out-p char-p)
+  (declare (ignore char-p)) ; TODO: is there any real reason to care about this?
+  (assert (and in-p out-p) () "Non-bidirectional file-socket stream?")
+  'fundamental-file-socket-stream)
+
+(defmethod select-stream-class ((s (eql 'basic-file-socket-stream)) in-p out-p char-p)
+  (declare (ignore char-p))
+  (assert (and in-p out-p) () "Non-bidirectional file-socket stream?")
+  'basic-file-socket-stream)
+
+(defclass unconnected-socket (socket)
+  ((device :initarg :device :accessor socket-device)
+   (keys :initarg :keys :reader socket-keys)))
+
+(defmethod socket-format ((socket unconnected-socket))
+  (or (getf (socket-keys socket) :format) :text))
+
+(defgeneric close (socket &key abort)
+  (:documentation
+   "The close generic function can be applied to sockets. It releases the
+operating system resources associated with the socket."))
+
+(defmethod close ((socket unconnected-socket) &key abort)
+  (declare (ignore abort))
+  (when (socket-device socket)
+    (fd-close (socket-device socket))
+    (setf (socket-device socket) nil)
+    t))
+
+;; A passive tcp socket just generates connection streams
+(defclass listener-socket (tcp-socket unconnected-socket) ())
+
+(defmethod SOCKET-CONNECT ((stream listener-socket)) :passive)
+
+(defclass file-listener-socket (stream-file-socket unconnected-socket) ())
+
+(defmethod SOCKET-CONNECT ((stream file-listener-socket)) :passive)
+
+;;; A FILE-LISTENER-SOCKET should try to delete the filesystem
+;;; entity when closing.
+
+#-windows-target
+(defmethod close :before ((s file-listener-socket) &key abort)
+  (declare (ignore abort))
+  (let* ((path (local-socket-filename (socket-device s) s)))
+    (when path (%delete-file path))))
+
+
+;; A udp socket just sends and receives packets.
+(defclass udp-socket (ip-socket unconnected-socket) ())
+
+(defmethod socket-type ((stream udp-socket)) :datagram)
+(defmethod socket-connect ((stream udp-socket)) nil)
+
+(defgeneric socket-os-fd (socket)
+  (:documentation
+   "Return the native OS's representation of the socket, or NIL if the
+socket is closed. On Unix, this is the Unix 'file descriptor', a small
+non-negative integer. Note that it is rather dangerous to mess around
+with tcp-stream fd's, as there is all sorts of buffering and asynchronous
+I/O going on above the OS level. listener-socket and udp-socket fd's are
+safer to mess with directly as there is less magic going on."))
+
+;; Returns nil for closed stream...
+(defmethod socket-os-fd ((socket socket))
+  (socket-device socket))
+
+;; Returns nil for closed stream
+(defun local-socket-info (fd type socket)
+  (and fd
+       (rlet ((sockaddr :sockaddr_in)
+	      (namelen :signed))
+	     (setf (pref namelen :signed) (record-length :sockaddr_in))
+	     (socket-call socket "getsockname" (c_getsockname fd sockaddr namelen))
+	     (when (= #$AF_INET (pref sockaddr :sockaddr_in.sin_family))
+	       (ecase type
+		 (:host (ntohl (pref sockaddr
+                                     #-(or solaris-target windows-target) :sockaddr_in.sin_addr.s_addr
+                                     #+(or solaris-target windows-target) #>sockaddr_in.sin_addr.S_un.S_addr)))
+		 (:port (ntohs (pref sockaddr :sockaddr_in.sin_port))))))))
+
+#-windows-target
+(defun path-from-unix-address (addr)
+  (when (= #$AF_UNIX (pref addr :sockaddr_un.sun_family))
+    #+darwin-target
+    (%str-from-ptr (pref addr :sockaddr_un.sun_path)
+		   (- (pref addr :sockaddr_un.sun_len) 2))
+    #-darwin-target
+    (%get-cstring (pref addr :sockaddr_un.sun_path))))
+
+#-windows-target
+(defun local-socket-filename (fd socket)
+  (and fd
+       (rlet ((addr :sockaddr_un)
+              (namelen :signed))
+         (setf (pref namelen :signed) (record-length :sockaddr_un))
+         (socket-call socket "getsockname" (c_getsockname fd addr namelen))
+	 (path-from-unix-address addr))))
+
+(defmacro with-if ((var expr) &body body)
+  `(let ((,var ,expr))
+     (if ,var
+	 (progn
+	   ,@body))))     
+
+(defun remote-socket-info (socket type)
+  (with-if (fd (socket-device socket))
+    (rlet ((sockaddr :sockaddr_in)
+	   (namelen :signed))
+	  (setf (pref namelen :signed) (record-length :sockaddr_in))
+	  (let ((err (c_getpeername fd sockaddr namelen)))
+	    (cond ((eql err (- #+windows-target #$WSAENOTCONN #-windows-target #$ENOTCONN)) nil)
+		  ((< err 0) (socket-error socket "getpeername" err))
+		  (t
+		   (when (= #$AF_INET (pref sockaddr :sockaddr_in.sin_family))
+		     (ecase type
+		       (:host (ntohl (pref sockaddr
+                                           #-(or solaris-target windows-target) :sockaddr_in.sin_addr.s_addr
+                                           #+(or solaris-target windows-target)  #>sockaddr_in.sin_addr.S_un.S_addr)))
+		       (:port (ntohs  (pref sockaddr :sockaddr_in.sin_port)))))))))))
+
+#-windows-target
+(defun remote-socket-filename (socket)
+  (with-if (fd (socket-device socket))
+    (rlet ((addr :sockaddr_un)
+	   (namelen :signed))
+	  (setf (pref namelen :signed) (record-length :sockaddr_un))
+	  (let* ((err (c_getsockname fd addr namelen)))
+	    (cond ((eql err (- #$ENOTCONN)) nil)
+		  ((< err 0) (socket-error socket "getpeername" err))
+		  (t (path-from-unix-address addr)))))))
+
+(defgeneric local-port (socket)
+  (:documentation "Return the local port number."))
+
+(defmethod local-port ((socket socket))
+  (local-socket-info (socket-device socket) :port socket))
+
+(defgeneric local-host (socket)
+  (:documentation
+   "Return 32-bit unsigned IP address of the local host."))
+
+(defmethod local-host ((socket socket))
+  (local-socket-info (socket-device socket) :host socket))
+
+#-windows-target
+(defmethod local-filename ((socket socket))
+  (local-socket-filename (socket-device socket) socket))
+
+(defgeneric remote-host (socket)
+  (:documentation
+   "Return the 32-bit unsigned IP address of the remote host, or NIL if
+the socket is not connected."))
+
+;; Returns NIL if socket is not connected
+(defmethod remote-host ((socket socket))
+  (remote-socket-info socket :host))
+
+(defgeneric remote-port (socket)
+  (:documentation
+   "Return the remote port number, or NIL if the socket is not connected."))
+
+(defmethod remote-port ((socket socket))
+  (remote-socket-info socket :port))
+
+#-windows-target
+(defmethod remote-filename ((socket socket))
+  (remote-socket-filename socket))
+  
+(defun set-socket-fd-blocking (fd block-flag)
+  #+windows-target
+  (rlet ((argp :u_long (if block-flag 0 1)))
+    (#_ioctlsocket fd #$FIONBIO argp))
+  #-windows-target
+  (if block-flag
+    (fd-clear-flag fd #$O_NONBLOCK)
+    (fd-set-flag fd #$O_NONBLOCK)))
+
+(defun get-socket-fd-blocking (fd)
+  "returns T iff socket is in blocking mode"
+  #+windows-target (declare (ignore fd))
+  #+windows-target t
+  #-windows-target
+  (not (logtest #$O_NONBLOCK (fd-get-flags fd))))
+
+(defun set-socket-options (fd-or-socket &key 
+			   keepalive
+			   reuse-address
+			   nodelay
+			   broadcast
+			   linger
+			   address-family
+			   local-port
+			   local-host
+			   local-filename
+			   type
+			   connect
+			   out-of-band-inline
+			   &allow-other-keys)
+  ;; see man socket(7) tcp(7) ip(7)
+  (multiple-value-bind (socket fd) (etypecase fd-or-socket
+				     (socket (values fd-or-socket (socket-device fd-or-socket)))
+				     (integer (values nil fd-or-socket)))
+    
+    (if (null address-family)
+	(setq address-family :internet))
+    (when keepalive
+      (int-setsockopt fd #$SOL_SOCKET #$SO_KEEPALIVE 1))
+    (when reuse-address
+      (int-setsockopt fd #$SOL_SOCKET #$SO_REUSEADDR 1))
+    (when broadcast
+      (int-setsockopt fd #$SOL_SOCKET #$SO_BROADCAST 1))
+    (when out-of-band-inline
+      (int-setsockopt fd #$SOL_SOCKET #$SO_OOBINLINE 1))
+    (when (eq address-family :internet)
+      (when (eq type :stream)
+	(rlet ((plinger :linger))
+	  (setf (pref plinger :linger.l_onoff) (if linger 1 0)
+		(pref plinger :linger.l_linger) (or linger 0))
+	  (socket-call socket "setsockopt"
+		       (c_setsockopt fd #$SOL_SOCKET #$SO_LINGER
+				     plinger (record-length :linger)))))
+      (when nodelay
+	(int-setsockopt fd
+			#+linux-target #$SOL_TCP
+			#-linux-target #$IPPROTO_TCP
+			#$TCP_NODELAY 1))
+      (when (or local-port local-host)
+	(let* ((proto (if (eq type :stream) "tcp" "udp"))
+	       (port-n (if local-port (port-as-inet-port local-port proto) 0))
+	       (host-n (if local-host (host-as-inet-host local-host) #$INADDR_ANY)))
+	  ;; Darwin includes the SIN_ZERO field of the sockaddr_in when
+	  ;; comparing the requested address to the addresses of configured
+	  ;; interfaces (as if the zeros were somehow part of either address.)
+	  ;; "rletz" zeros out the stack-allocated structure, so those zeros
+	  ;; will be 0.
+	  (rletz ((sockaddr :sockaddr_in))
+		 (setf (pref sockaddr :sockaddr_in.sin_family) #$AF_INET
+		       (pref sockaddr :sockaddr_in.sin_port) port-n
+		       (pref sockaddr
+                             #-(or solaris-target windows-target) :sockaddr_in.sin_addr.s_addr
+                             #+(or solaris-target windows-target) #>sockaddr_in.sin_addr.S_un.S_addr
+                             ) host-n)
+		 (socket-call socket "bind" (c_bind fd sockaddr (record-length :sockaddr_in)))))))
+    (when (and (eq address-family :file)
+	       (eq connect :passive)
+	       local-filename)
+      #+windows-target (error "can't create file socket on Windows")
+      #-windows-target (bind-unix-socket fd local-filename))))
+
+;; I hope the inline declaration makes the &rest/apply's go away...
+(declaim (inline make-ip-socket))
+(defun make-ip-socket (&rest keys &key type &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (ecase type
+    ((nil :stream) (apply #'make-tcp-socket keys))
+    ((:datagram) (apply #'make-udp-socket keys))))
+
+(declaim (inline make-file-socket))
+(defun make-file-socket (&rest keys &key type &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (ecase type
+    ((nil :stream) (apply #'make-stream-file-socket keys))
+    (:datagram (apply #'make-datagram-file-socket keys))))
+
+(defun make-socket (&rest keys
+		    &key address-family
+		    ;; List all keys here just for error checking...
+		    ;; &allow-other-keys
+		    type connect remote-host remote-port eol format
+		    keepalive reuse-address nodelay broadcast linger
+		    local-port local-host backlog class out-of-band-inline
+		    local-filename remote-filename sharing basic
+                    external-format (auto-close t)
+                    connect-timeout input-timeout output-timeout deadline
+                    fd)
+  "Create and return a new socket."
+  (declare (dynamic-extent keys))
+  (declare (ignore type connect remote-host remote-port eol format
+		   keepalive reuse-address nodelay broadcast linger
+		   local-port local-host backlog class out-of-band-inline
+		   local-filename remote-filename sharing basic external-format
+                   auto-close connect-timeout input-timeout output-timeout deadline fd))
+  (ecase address-family
+    ((:file) (apply #'make-file-socket keys))
+    ((nil :internet) (apply #'make-ip-socket keys))))
+
+
+
+(defun make-udp-socket (&rest keys &key (fd -1) &allow-other-keys)
+  (unwind-protect
+    (let (socket)
+      (when (< fd 0)
+        (setq fd (socket-call nil "socket"
+                              (c_socket #$AF_INET #$SOCK_DGRAM #$IPPROTO_UDP))))
+      (apply #'set-socket-options fd keys)
+      (setq socket (make-instance 'udp-socket
+				  :device fd
+				  :keys keys))
+      (setq fd -1)
+      socket)
+    (unless (< fd 0)
+      (fd-close fd))))
+
+(defun make-tcp-socket (&rest keys &key connect (fd -1) &allow-other-keys)
+  (unwind-protect
+       (let (socket)
+         (when (< fd 0)
+           (setq fd (socket-call nil "socket"
+                                 (c_socket #$AF_INET #$SOCK_STREAM #$IPPROTO_TCP))))
+         (apply #'set-socket-options fd keys)
+         (setq socket
+               (ecase connect
+                 ((nil :active) (apply #'make-tcp-stream-socket fd keys))
+                 ((:passive) (apply #'make-tcp-listener-socket fd keys))))
+         (setq fd -1)
+         socket)
+    (unless (< fd 0)
+      (fd-close fd))))
+
+(defun make-stream-file-socket (&rest keys &key connect (fd -1) &allow-other-keys)
+  (unwind-protect
+       (let (socket)
+         (when (< fd 0)
+           (setq fd (socket-call nil "socket" (c_socket #$PF_UNIX #$SOCK_STREAM 0))))
+         (apply #'set-socket-options fd keys)
+         (setq socket
+               (ecase connect
+                 ((nil :active) (apply #'make-file-stream-socket fd keys))
+                 ((:passive) (apply #'make-file-listener-socket fd keys))))
+         (setq fd -1)
+         socket)
+    (unless (< fd 0)
+      (fd-close fd))))
+
+(defun make-datagram-file-socket (&rest keys)
+  (declare (ignore keys))
+  (error "Datagram file sockets aren't implemented."))
+
+
+(defun %socket-connect (fd addr addrlen &optional timeout-in-milliseconds)
+  (let* ((err (c_connect fd addr addrlen timeout-in-milliseconds)))
+    (declare (fixnum err))
+    (unless (eql err 0) (fd-close fd) (socket-error nil "connect" err))))
+    
+(defun inet-connect (fd host-n port-n &optional timeout-in-milliseconds)
+  (rlet ((sockaddr :sockaddr_in))
+    (setf (pref sockaddr :sockaddr_in.sin_family) #$AF_INET
+          (pref sockaddr :sockaddr_in.sin_port) port-n
+          (pref sockaddr
+                #-(or solaris-target windows-target) :sockaddr_in.sin_addr.s_addr
+                #+(or solaris-target windows-target)  #>sockaddr_in.sin_addr.S_un.S_addr
+                ) host-n)
+    (%socket-connect fd sockaddr (record-length :sockaddr_in) timeout-in-milliseconds)))
+
+#-windows-target
+(defun file-socket-connect (fd remote-filename)
+  (rletz ((sockaddr :sockaddr_un))
+    (init-unix-sockaddr sockaddr remote-filename)
+    (%socket-connect fd sockaddr (record-length :sockaddr_un))))
+
+#+windows-target
+(defun file-socket-connect (fd remote-filename)
+  (declare (ignore fd))
+  (error "Can't create file socket to ~s on Windows" remote-filename))
+  
+(defun make-tcp-stream-socket (fd &rest keys
+                                  &key remote-host
+				  remote-port
+                                  connect-timeout
+                                  deadline
+				  &allow-other-keys)
+  (let* ((timeout-in-milliseconds
+          (if deadline
+            (max (round (- deadline (get-internal-real-time))
+                        (/ internal-time-units-per-second 1000))
+                 0)
+            (if connect-timeout
+              (round (* connect-timeout 1000))))))
+    (inet-connect fd
+                  (host-as-inet-host remote-host)
+                  (port-as-inet-port remote-port "tcp")
+                  timeout-in-milliseconds)
+    (apply #'make-tcp-stream fd keys)))
+
+(defun make-file-stream-socket (fd &rest keys
+                                   &key remote-filename
+                                   &allow-other-keys)
+  (file-socket-connect fd remote-filename)
+  (apply #'make-file-socket-stream fd keys))
+
+
+(defun make-tcp-stream (fd
+                        &key (format :bivalent)
+                             external-format
+                             (class 'tcp-stream)
+                             sharing
+                             (basic t)
+                             (auto-close t)
+                             input-timeout
+                             output-timeout
+                             deadline
+                        &allow-other-keys)
+  (let* ((external-format (normalize-external-format :socket external-format)))
+    (let ((element-type (ecase format
+                          ((nil :text) 'character)
+                          ((:binary :bivalent) '(unsigned-byte 8)))))
+      ;; TODO: check out fd-stream-advance, -listen, -eofp, -force-output, -close
+      ;; See if should specialize any of 'em.
+      (make-fd-stream fd
+                      :class class
+                      :direction :io
+                      :element-type element-type
+                      :sharing sharing
+                      :character-p (not (eq format :binary))
+                      :encoding (external-format-character-encoding external-format)
+                      :line-termination (external-format-line-termination external-format)
+                      :basic basic
+                      :auto-close auto-close
+                      :input-timeout input-timeout
+                      :output-timeout output-timeout
+                      :deadline deadline))))
+
+(defun make-file-socket-stream (fd
+                                &key (format :bivalent)
+                                external-format
+                                (class 'file-socket-stream)
+                                sharing
+                                basic
+                                (auto-close t)
+                                input-timeout
+                                output-timeout
+                                deadline
+                                &allow-other-keys)
+  (let* ((external-format (normalize-external-format :socket external-format)))
+  
+    (let ((element-type (ecase format
+                          ((nil :text) 'character)
+                          ((:binary :bivalent) '(unsigned-byte 8)))))
+      ;; TODO: check out fd-stream-advance, -listen, -eofp, -force-output, -close
+      ;; See if should specialize any of 'em.
+      (make-fd-stream fd
+                      :class class
+                      :direction :io
+                      :element-type element-type
+                      :encoding (external-format-character-encoding external-format)
+                      :line-termination (external-format-line-termination external-format)
+                      :sharing sharing
+                      :character-p (not (eq format :binary))
+                      :basic basic
+                      :auto-close auto-close
+                      :input-timeout input-timeout
+                      :output-timeout output-timeout
+                      :deadline deadline))))
+
+(defun make-tcp-listener-socket (fd &rest keys &key backlog &allow-other-keys)
+  (socket-call nil "listen" (c_listen fd (or backlog 5)))
+  (make-instance 'listener-socket
+		 :device fd
+		 :keys keys))
+
+(defun make-file-listener-socket (fd &rest keys &key backlog &allow-other-keys)
+  (socket-call nil "listen" (c_listen fd (or backlog 5)))
+  (make-instance 'file-listener-socket
+		 :device fd
+		 :keys keys))
+
+(defun socket-accept (fd wait)
+  (flet ((_accept (fd async)
+	   (let ((res (c_accept fd (%null-ptr) (%null-ptr))))
+	     (declare (fixnum res))
+	     ;; See the inscrutable note under ERROR HANDLING in
+	     ;; man accept(2). This is my best guess at what they mean...
+	     (if (and async (< res 0)
+                      #+windows-target
+                      (= res #$WSAEWOULDBLOCK)
+                      #-windows-target
+		      (or (eql res (- #$ENETDOWN))
+			  (eql res (- #+linux-target #$EPROTO
+				      #-linux-target  #$EPROTOTYPE))
+			  (eql res (- #$ENOPROTOOPT))
+			  (eql res (- #$EHOSTDOWN))
+			  (eql res (- #+linux-target #$ENONET
+				      #-linux-target #$ENETDOWN))
+			  (eql res (- #$EHOSTUNREACH))
+			  (eql res (- #$EOPNOTSUPP))
+			  (eql res (- #$ENETUNREACH))))
+	       (- #$EAGAIN)
+               res))))
+    (cond (wait
+	    (with-eagain fd :input
+	      (_accept fd *multiprocessing-socket-io*)))
+	  (*multiprocessing-socket-io*
+	    (_accept fd t))
+	  (t
+	    (let ((was-blocking (get-socket-fd-blocking fd)))
+	      (unwind-protect
+		  (progn
+                    (set-socket-fd-blocking fd nil)
+		    (_accept fd t))
+		(set-socket-fd-blocking fd was-blocking)))))))
+
+(defun accept-socket-connection (socket wait stream-create-function &optional stream-args)
+  (let ((listen-fd (socket-device socket))
+	(fd -1))
+    (unwind-protect
+      (let ((keys (append stream-args (socket-keys socket))))
+	(setq fd (socket-accept listen-fd wait))
+	(cond ((>= fd 0)
+	       (prog1 (apply stream-create-function fd keys)
+		 (setq fd -1)))
+	      ((eql fd (- #$EAGAIN)) nil)
+	      (t (socket-error socket "accept" fd))))
+      (when (>= fd 0)
+	(fd-close fd)))))
+
+(defgeneric accept-connection (socket &key wait stream-args)
+  (:documentation
+  "Extract the first connection on the queue of pending connections,
+accept it (i.e. complete the connection startup protocol) and return a new
+tcp-stream or file-socket-stream representing the newly established
+connection.  The tcp stream inherits any properties of the listener socket
+that are relevant (e.g. :keepalive, :nodelay, etc.) Additional arguments
+may be specified using STREAM-ARGS. The original listener
+socket continues to be open listening for more connections, so you can call
+accept-connection on it again."))
+
+(defmethod accept-connection ((socket listener-socket) &key (wait t) stream-args)
+  (accept-socket-connection socket wait #'make-tcp-stream stream-args))
+
+(defmethod accept-connection ((socket file-listener-socket) &key (wait t) stream-args)
+  (accept-socket-connection socket wait #'make-file-socket-stream stream-args))
+
+(defun verify-socket-buffer (buf offset size)
+  (unless offset (setq offset 0))
+  (unless (<= (+ offset size) (length buf))
+    (report-bad-arg size `(integer 0 ,(- (length buf) offset))))
+  (multiple-value-bind (arr start) (array-data-and-offset buf)
+    (setq buf arr offset (+ offset start)))
+  ;; TODO: maybe should allow any raw vector
+  (let ((subtype (typecode buf)))
+    (unless #+ppc32-target (and (<= ppc32::min-8-bit-ivector-subtag subtype)
+                                (<= subtype ppc32::max-8-bit-ivector-subtag))
+            #+ppc64-target (= (the fixnum (logand subtype ppc64::fulltagmask))
+                              ppc64::ivector-class-8-bit)
+            #+x8632-target (and (<= x8632::min-8-bit-ivector-subtag subtype)
+                                (<= subtype x8632::max-8-bit-ivector-subtag))
+            #+x8664-target (and (>= subtype x8664::min-8-bit-ivector-subtag)
+                                (<= subtype x8664::max-8-bit-ivector-subtag))
+      (report-bad-arg buf `(or (array character)
+			       (array (unsigned-byte 8))
+			       (array (signed-byte 8))))))
+  (values buf offset))
+
+(defmethod send-to ((socket udp-socket) msg size
+		    &key remote-host remote-port offset)
+  "Send a UDP packet over a socket."
+  (let ((fd (socket-device socket)))
+    (multiple-value-setq (msg offset) (verify-socket-buffer msg offset size))
+    (unless remote-host
+      (setq remote-host (or (getf (socket-keys socket) :remote-host)
+			    (remote-socket-info socket :host))))
+    (unless remote-port
+      (setq remote-port (or (getf (socket-keys socket) :remote-port)
+			    (remote-socket-info socket :port))))
+    (rlet ((sockaddr :sockaddr_in))
+      (setf (pref sockaddr :sockaddr_in.sin_family) #$AF_INET)
+      (setf (pref sockaddr
+                  #-(or solaris-target windows-target) :sockaddr_in.sin_addr.s_addr
+                  #+(or solaris-target windows-target)  #>sockaddr_in.sin_addr.S_un.S_addr)
+	    (if remote-host (host-as-inet-host remote-host) #$INADDR_ANY))
+      (setf (pref sockaddr :sockaddr_in.sin_port)
+	    (if remote-port (port-as-inet-port remote-port "udp") 0))
+      (%stack-block ((bufptr size))
+        (%copy-ivector-to-ptr msg offset bufptr 0 size)
+	(socket-call socket "sendto"
+	  (with-eagain fd :output
+	    (c_sendto fd bufptr size 0 sockaddr (record-length :sockaddr_in))))))))
+
+(defmethod receive-from ((socket udp-socket) size &key buffer extract offset)
+  "Read a UDP packet from a socket. If no packets are available, wait for
+a packet to arrive. Returns four values:
+  The buffer with the data
+  The number of bytes read
+  The 32-bit unsigned IP address of the sender of the data
+  The port number of the sender of the data."
+  (let ((fd (socket-device socket))
+	(vec-offset offset)
+	(vec buffer)
+	(ret-size -1))
+    (when vec
+      (multiple-value-setq (vec vec-offset)
+	(verify-socket-buffer vec vec-offset size)))
+    (rlet ((sockaddr :sockaddr_in)
+	   (namelen :signed))
+      (setf (pref sockaddr :sockaddr_in.sin_family) #$AF_INET)
+      (setf (pref sockaddr
+                  #-(or solaris-target windows-target) :sockaddr_in.sin_addr.s_addr
+                  #+(or solaris-target windows-target) #>sockaddr_in.sin_addr.S_un.S_addr)
+            #$INADDR_ANY)
+      (setf (pref sockaddr :sockaddr_in.sin_port) 0)
+      (setf (pref namelen :signed) (record-length :sockaddr_in))
+      (%stack-block ((bufptr size))
+	(setq ret-size (socket-call socket "recvfrom"
+			 (with-eagain fd :input
+			   (c_recvfrom fd bufptr size 0 sockaddr namelen))))
+	(unless vec
+	  (setq vec (make-array ret-size
+				:element-type
+				(ecase (socket-format socket)
+				  ((:text) 'base-char)
+				  ((:binary :bivalent) '(unsigned-byte 8))))
+		vec-offset 0))
+	(%copy-ptr-to-ivector bufptr 0 vec vec-offset ret-size))
+      (values (cond ((null buffer)
+		     vec)
+		    ((or (not extract)
+			 (and (eql 0 (or offset 0))
+			      (eql ret-size (length buffer))))
+		     buffer)
+		    (t 
+		     (subseq vec vec-offset (+ vec-offset ret-size))))
+	      ret-size
+	      (ntohl (pref sockaddr
+                           #-(or solaris-target windows-target) :sockaddr_in.sin_addr.s_addr
+                           #+(or solaris-target windows-target) #>sockaddr_in.sin_addr.S_un.S_addr))
+	      (ntohs (pref sockaddr :sockaddr_in.sin_port))))))
+
+(defgeneric shutdown (socket &key direction)
+  (:documentation
+   "Shut down part of a bidirectional connection. This is useful if e.g.
+you need to read responses after sending an end-of-file signal."))
+
+(defmethod shutdown (socket &key direction)
+  ;; TODO: should we ignore ENOTCONN error?  (at least make sure it
+  ;; is a distinct, catchable error type).
+  (let ((fd (socket-device socket)))
+    (socket-call socket "shutdown"
+      (c_shutdown fd (ecase direction
+		       (:input 0)
+		       (:output 1))))))
+
+;; Accepts port as specified by user, returns port number in network byte
+;; order.  Protocol should be one of "tcp" or "udp".  Error if not known.
+(defun port-as-inet-port (port proto)
+  (or (etypecase port
+	(fixnum (htons port))
+	(string (_getservbyname port proto))
+	(symbol (_getservbyname (string-downcase (symbol-name port)) proto)))
+      (socket-error nil "getservbyname" (- #$ENOENT))))
+
+(defun lookup-port (port proto)
+  "Find the port number for the specified port and protocol."
+  (if (fixnump port)
+    port
+    (ntohs (port-as-inet-port port proto))))
+
+;; Accepts host as specified by user, returns host number in network byte
+;; order.
+(defun host-as-inet-host (host)
+  (etypecase host
+    (integer (htonl host))
+    (string (or (and (every #'(lambda (c) (position c ".0123456789")) host)
+		     (_inet_aton host))
+		(multiple-value-bind (addr err) (c_gethostbyname host)
+		  (or addr
+		      (socket-error nil "gethostbyname" err t)))))))
+
+
+(defun dotted-to-ipaddr (name &key (errorp t))
+  "Convert a dotted-string representation of a host address to a 32-bit
+unsigned IP address."
+  (let ((addr (_inet_aton name)))
+    (if addr (ntohl addr)
+      (and errorp (error "Invalid dotted address ~s" name)))))
+    
+(defun lookup-hostname (host)
+  "Convert a host spec in any of the acceptable formats into a 32-bit
+unsigned IP address."
+  (if (typep host 'integer)
+    host
+    (ntohl (host-as-inet-host host))))
+
+(defun ipaddr-to-dotted (addr &key values)
+  "Convert a 32-bit unsigned IP address into octets."
+  (let* ((a (ldb (byte 8 24) addr))
+	 (b (ldb (byte 8 16) addr))
+	 (c (ldb (byte 8  8) addr))
+	 (d (ldb (byte 8  0) addr)))
+    (if values
+      (values a b c d)
+      (format nil "~d.~d.~d.~d" a b c d))))
+
+(defun ipaddr-to-hostname (ipaddr &key ignore-cache)
+  "Convert a 32-bit unsigned IP address into a host name string."
+  (declare (ignore ignore-cache))
+  (multiple-value-bind (name err) (c_gethostbyaddr (htonl ipaddr))
+    (or name (socket-error nil "gethostbyaddr" err t))))
+  
+
+
+(defun int-getsockopt (socket level optname)
+  (rlet ((valptr :signed)
+         (vallen :signed))
+    (setf (pref vallen :signed) 4)
+    (let* ((err (c_getsockopt socket level optname valptr vallen)))
+      (if (and (eql 0 err)
+               (eql 4 (pref vallen :signed)))
+        (pref valptr :signed)
+	(socket-error socket "getsockopt" err)))))
+
+(defun timeval-setsockopt (socket level optname timeout)
+    (multiple-value-bind (seconds micros)
+        (microseconds timeout)
+      (rlet ((valptr :timeval :tv_sec seconds :tv_usec micros))
+        (socket-call socket "setsockopt"
+          (c_setsockopt socket level optname valptr (record-length :timeval))))))
+                   
+(defun int-setsockopt (socket level optname optval)
+  (rlet ((valptr :signed))
+    (setf (pref valptr :signed) optval)
+    (socket-call socket "setsockopt"
+      (c_setsockopt socket level optname valptr (record-length :signed)))))
+
+
+
+            
+(defun c_gethostbyaddr (addr-in-net-byte-order)
+  (rletZ ((sin #>sockaddr_in))
+    (setf (pref sin :sockaddr_in.sin_family) #$AF_INET
+          (pref sin
+                #+(or windows-target solaris-target) #>sockaddr_in.sin_addr.S_un.S_addr
+                #-(or windows-target solaris-target) #>sockaddr_in.sin_addr.s_addr) addr-in-net-byte-order)
+    #+darwin-target (setf (pref sin :sockaddr_in.sin_len) (record-length :sockaddr_in))
+    (%stack-block ((namep #$NI_MAXHOST))
+      (let* ((err (#_getnameinfo sin (record-length #>sockaddr_in) namep #$NI_MAXHOST (%null-ptr) 0 #$NI_NAMEREQD)))
+        (if (eql 0 err)
+          (%get-cstring namep)
+          (values nil err))))))
+                
+(defun c_gethostbyname (name)
+  (with-cstrs ((name (string name)))
+    (rletZ ((hints #>addrinfo)
+            (results :address))
+      (setf (pref hints #>addrinfo.ai_family) #$AF_INET)
+      (let* ((err (#_getaddrinfo name (%null-ptr) hints results)))
+        (if (eql 0 err)
+          (let* ((info (pref results :address))
+                 (sin (pref info #>addrinfo.ai_addr)))
+            (prog1
+                #+(or windows-target solaris-target)
+                (pref sin #>sockaddr_in.sin_addr.S_un.S_addr)
+                #-(or windows-target solaris-target)
+                (pref sin #>sockaddr_in.sin_addr.s_addr)
+                (#_freeaddrinfo info)))
+          (values nil err))))))
+      
+  
+
+  
+
+(defun _getservbyname (name proto)
+  (with-cstrs ((name (string name))
+	       (proto (string proto)))
+    (let* ((servent-ptr (%null-ptr)))
+      (declare (dynamic-extent servent-ptr))
+      (%setf-macptr servent-ptr (#_getservbyname name proto))
+      (unless (%null-ptr-p servent-ptr)
+	(pref servent-ptr :servent.s_port)))))
+
+(defun _inet_aton (string)
+  (with-cstrs ((name string))
+    #-windows-target
+    (rlet ((addr :in_addr))
+      (let* ((result #+freebsd-target (#___inet_aton name addr)
+                     #-freebsd-target (#_inet_aton name addr)))
+	(unless (eql result 0)
+	  (pref addr
+                #-solaris-target :in_addr.s_addr
+                #+solaris-target #>in_addr.S_un.S_addr
+                ))))
+    #+windows-target
+    (rlet ((addr :sockaddr_in)
+           (addrlenp :int (record-length :sockaddr_in)))
+      (setf (pref addr :sockaddr_in.sin_family) #$AF_INET)
+      (when (zerop (#_WSAStringToAddressA name #$AF_INET (%null-ptr)  addr addrlenp))
+        (pref addr #>sockaddr_in.sin_addr.S_un.S_addr)))))
+
+(defun c_socket_1 (domain type protocol)
+  #-windows-target (int-errno-call (#_socket domain type protocol))
+  #+windows-target (let* ((handle (#_socket domain type protocol)))
+                     (if (< handle 0)
+                       (%get-winsock-error)
+                       handle)))
+
+
+
+(defun c_socket (domain type protocol)
+  (let* ((fd (c_socket_1 domain type protocol)))
+    (when (or (eql fd (- #$EMFILE))
+              (eql fd (- #$ENFILE)))
+      (gc)
+      (drain-termination-queue)
+      (setq fd (c_socket_1 domain type protocol)))
+    fd))
+      
+
+#-windows-target
+(defun init-unix-sockaddr (addr path)
+  (macrolet ((sockaddr_un-path-len ()
+               (/ (ensure-foreign-type-bits
+                   (foreign-record-field-type 
+                    (%find-foreign-record-type-field
+                     (parse-foreign-type '(:struct :sockaddr_un)) :sun_path)))
+                  8)))
+    (let* ((name (native-translated-namestring path))
+           (namelen (length name))
+           (pathlen (sockaddr_un-path-len))
+           (copylen (min (1- pathlen) namelen)))
+      (setf (pref addr :sockaddr_un.sun_family) #$AF_UNIX)
+      (let* ((sun-path (pref addr :sockaddr_un.sun_path)))
+        (dotimes (i copylen)
+          (setf (%get-unsigned-byte sun-path i)
+                (let* ((code (char-code (schar name i))))
+                  (if (> code 255)
+                    (char-code #\Sub)
+                    code))))))))
+
+#-windows-target
+(defun bind-unix-socket (socketfd path)
+  (rletz ((addr :sockaddr_un))
+    (init-unix-sockaddr addr path)
+    (socket-call
+     nil
+     "bind"
+     (c_bind socketfd
+             addr
+             (+ 2
+                (#_strlen
+                 (pref addr :sockaddr_un.sun_path)))))))
+      
+
+(defun c_bind (sockfd sockaddr addrlen)
+  (check-socket-error (#_bind sockfd sockaddr addrlen)))
+
+
+#+windows-target
+(defun windows-connect-wait (sockfd timeout-in-milliseconds)
+  (if (and timeout-in-milliseconds
+           (< timeout-in-milliseconds 0))
+    (setq timeout-in-milliseconds nil))
+  (rlet ((writefds :fd_set)
+         (exceptfds :fd_set)
+         (tv :timeval :tv_sec 0 :tv_usec 0))
+    (fd-zero writefds)
+    (fd-zero exceptfds)
+    (fd-set sockfd writefds)
+    (fd-set sockfd exceptfds)
+    (when timeout-in-milliseconds
+      (multiple-value-bind (seconds milliseconds)
+          (floor timeout-in-milliseconds 1000)
+        (setf (pref tv :timeval.tv_sec) seconds
+              (pref tv :timeval.tv_usec) (* 1000 milliseconds))))
+    (> (#_select 1 (%null-ptr) writefds exceptfds (if timeout-in-milliseconds tv (%null-ptr))) 0)))
+      
+      
+;;; If attempts to connnect are interrupted, we basically have to
+;;; wait in #_select (or the equivalent).  There's a good rant
+;;; about these issues in:
+;;; <http://www.madore.org/~david/computers/connect-intr.html>
+(defun c_connect (sockfd addr len &optional timeout-in-milliseconds)
+  (let* ((was-blocking (get-socket-fd-blocking sockfd)))
+    (unwind-protect
+         (progn
+           (set-socket-fd-blocking sockfd nil)
+           (let* ((err (check-socket-error (#_connect sockfd addr len))))
+             (cond ((or (eql err (- #+windows-target #$WSAEINPROGRESS
+                                    
+                                    #-windows-target #$EINPROGRESS))
+                        #+windows-target (eql err (- #$WSAEWOULDBLOCK))
+                        (eql err (- #$EINTR)))
+                    (if
+                      #+windows-target (windows-connect-wait sockfd timeout-in-milliseconds)
+                      #-windows-target (process-output-wait sockfd timeout-in-milliseconds)
+                      (- (int-getsockopt sockfd #$SOL_SOCKET #$SO_ERROR))
+                      (- #+windows-target #$WSAETIMEDOUT #-windows-target #$ETIMEDOUT)))
+                   (t err))))
+      (set-socket-fd-blocking sockfd was-blocking))))
+
+(defun c_listen (sockfd backlog)
+  (check-socket-error (#_listen sockfd backlog)))
+
+(defun c_accept (sockfd addrp addrlenp)
+  (ignoring-eintr
+   (check-socket-error (#_accept sockfd addrp addrlenp))))
+
+(defun c_getsockname (sockfd addrp addrlenp)
+  (check-socket-error (#_getsockname sockfd addrp addrlenp)))
+
+(defun c_getpeername (sockfd addrp addrlenp)
+  (check-socket-error (#_getpeername sockfd addrp addrlenp)))
+
+#-windows-target
+(defun c_socketpair (domain type protocol socketsptr)
+  (check-socket-error (#_socketpair domain type protocol socketsptr)))
+
+
+(defun c_sendto (sockfd msgptr len flags addrp addrlen)
+  (ignoring-eintr (check-socket-error (#_sendto sockfd msgptr len flags addrp addrlen))))
+
+(defun c_recvfrom (sockfd bufptr len flags addrp addrlenp)
+  (ignoring-eintr (check-socket-error (#_recvfrom sockfd bufptr len flags addrp addrlenp))))
+
+(defun c_shutdown (sockfd how)
+  (check-socket-error (#_shutdown sockfd how)))
+
+(defun c_setsockopt (sockfd level optname optvalp optlen)
+  (check-socket-error (#_setsockopt sockfd level optname optvalp optlen)))
+
+(defun c_getsockopt (sockfd level optname optvalp optlenp)
+  (check-socket-error (#_getsockopt sockfd level optname optvalp optlenp)))
+
+#-windows-target
+(defun c_sendmsg (sockfd msghdrp flags)
+  (check-socket-error (#_sendmsg sockfd msghdrp flags)))
+
+#-windows-target
+(defun c_recvmsg (sockfd msghdrp flags)
+  (check-socket-error   (#_recvmsg sockfd msghdrp flags)))
+
+
+;;; Return a list of currently configured interfaces, a la ifconfig.
+(defstruct ip-interface
+  name
+  addr
+  netmask
+  flags
+  address-family)
+
+(defun dump-buffer (p n)
+  (dotimes (i n (progn (terpri) (terpri)))
+    (unless (logtest i 15)
+      (format t "~&~8,'0x: " (%ptr-to-int (%inc-ptr p i))))
+    (format t " ~2,'0x" (%get-byte p i))))
+
+#-(or windows-target solaris-target)
+(defun %get-ip-interfaces ()
+  (rlet ((p :address (%null-ptr)))
+    (if (zerop (#_getifaddrs p))
+      (unwind-protect
+           (do* ((q (%get-ptr p) (pref q :ifaddrs.ifa_next))
+                 (res ()))
+                ((%null-ptr-p q) (nreverse res))
+             (let* ((addr (pref q :ifaddrs.ifa_addr)))
+               (when (and (not (%null-ptr-p addr))
+                          (eql (pref addr :sockaddr.sa_family) #$AF_INET))
+                 (push (make-ip-interface
+                        :name (%get-cstring (pref q :ifaddrs.ifa_name))
+                        :addr (ntohl (pref addr :sockaddr_in.sin_addr.s_addr))
+                        :netmask (ntohl
+                                  (pref (pref q :ifaddrs.ifa_netmask)
+                                       :sockaddr_in.sin_addr.s_addr))
+                        :flags (pref q :ifaddrs.ifa_flags)
+                        :address-family #$AF_INET)
+                       res))))
+        (#_freeifaddrs (pref p :address))))))
+
+#+solaris-target
+(progn
+  ;;; Interface translator has trouble with a lot of ioctl constants.
+  (eval-when (:compile-toplevel :execute)
+    (defconstant os::|SIOCGLIFNUM| #xc00c6982)
+    (defconstant os::|SIOCGLIFCONF| #xc01069a5)
+    (defconstant os::|SIOCGLIFADDR| #xc0786971)
+    (defconstant os::|SIOCGLIFFLAGS| #xc0786975)
+    (defconstant os::|SIOCGLIFNETMASK| #xc078697d)
+    )
+
+(defun %get-ip-interfaces ()
+  (let* ((sock (c_socket #$AF_INET #$SOCK_DGRAM #$IPPROTO_UDP))
+         (res nil))
+    (when (>= sock 0)
+      (unwind-protect
+           (let* ((flags (logior #$LIFC_NOXMIT #$LIFC_TEMPORARY #$LIFC_ALLZONES))
+                  (ninterfaces (rlet ((lifnum :lifnum
+                                        :lifn_flags flags
+                                        :lifn_family #$AF_INET
+                                        :lifn_count 0))
+                                 (#_ioctl sock os::SIOCGLIFNUM :address lifnum)
+                                 (pref lifnum :lifnum.lifn_count))))
+             (declare (fixnum ninterfaces))
+             (when (> ninterfaces 0)
+               (let* ((bufsize (* ninterfaces (record-length :lifreq))))
+                 (%stack-block ((buf bufsize :clear t))
+                   (rlet ((lifc :lifconf
+                            :lifc_family #$AF_INET
+                            :lifc_flags flags
+                            :lifc_len bufsize
+                            :lifc_lifcu.lifcu_buf buf))
+                     (when (>= (#_ioctl sock os::SIOCGLIFCONF :address lifc) 0)
+                       (do* ((i 0 (1+ i))
+                             (p (pref lifc :lifconf.lifc_lifcu.lifcu_buf)
+                                (%inc-ptr p (record-length :lifreq))))
+                            ((= i ninterfaces))
+                         (let* ((name (%get-cstring (pref p :lifreq.lifr_name)))
+                                (address-family (pref p :lifreq.lifr_lifru.lifru_addr.ss_family))
+                                (if-flags nil)
+                                (address nil)
+                                (netmask nil))
+                           (if (>= (#_ioctl sock os::SIOCGLIFFLAGS :address p)
+                                   0)
+                             (setq if-flags (pref p :lifreq.lifr_lifru.lifru_flags)))
+                           (if (>= (#_ioctl sock os::SIOCGLIFADDR :address p)
+                                   0)
+                             (setq address (pref
+                                            (pref p :lifreq.lifr_lifru.lifru_addr)
+                                            #>sockaddr_in.sin_addr.S_un.S_addr)))
+                           (if (>= (#_ioctl sock os::SIOCGLIFNETMASK :address p)
+                                   0)
+                             (setq netmask (pref
+                                            (pref p :lifreq.lifr_lifru.lifru_subnet)
+                                            #>sockaddr_in.sin_addr.S_un.S_addr)))
+                             
+                           (push (make-ip-interface
+                                  :name name
+                                  :addr (ntohl address)
+                                  :netmask (ntohl netmask)
+                                  :flags if-flags
+                                  :address-family address-family)
+                                 res)))))))))
+        (fd-close sock)))
+    res))
+)
+
+
+
+
+#+windows-target
+(defun %get-ip-interfaces ()
+  (let* ((socket (#_socket #$AF_INET #$SOCK_DGRAM #$IPPROTO_IP)))
+    (unwind-protect
+    (rlet ((realoutlen #>DWORD 0))
+      (do* ((reservedlen (* 4 (record-length #>INTERFACE_INFO))
+                         (* 2 reservedlen)))
+           ()
+        (%stack-block ((buf reservedlen))
+          (unless (eql 0 (#_WSAIoctl
+                          socket
+                          #$SIO_GET_INTERFACE_LIST
+                          (%null-ptr)
+                          0
+                          buf
+                          reservedlen
+                          realoutlen
+                          (%null-ptr)
+                          (%null-ptr)))
+            (return))
+          (let* ((noutbytes (pref realoutlen #>DWORD)))
+            (when (< noutbytes reservedlen)
+              (let* ((interfaces nil))
+                (do* ((offset 0 (+ offset (record-length #>INTERFACE_INFO)))
+                      (nameidx 0 (1+ nameidx)))
+                     ((>= offset noutbytes))
+                  (with-macptrs ((p (%inc-ptr buf offset)))
+                    (push (make-ip-interface 
+                           :name (format nil "ip~d" nameidx)
+                           :addr (ntohl
+                                  (pref (pref p #>INTERFACE_INFO.iiAddress)
+                                        #>sockaddr_gen.AddressIn.sin_addr.S_un.S_addr))
+                           :netmask (ntohl
+                                     (pref (pref p #>INTERFACE_INFO.iiNetmask)
+                                        #>sockaddr_gen.AddressIn.sin_addr.S_un.S_addr))
+                           :flags (pref p #>INTERFACE_INFO.iiFlags)
+                           :address-family #$AF_INET)
+                          interfaces)))
+                (return interfaces)))))))
+      (#_closesocket socket))))
+
+      
+
+
+(defloadvar *ip-interfaces* ())
+
+(defun ip-interfaces ()
+  (or *ip-interfaces*
+      (setq *ip-interfaces* (%get-ip-interfaces))))
+
+;;; This should presumably happen after a configuration change.
+;;; How do we detect a configuration change ?
+(defun %reset-ip-interfaces ()
+  (setq *ip-interfaces* ()))
+
+;;; Return the first non-loopback interface that's up and whose address
+;;; family is #$AF_INET.  If no such interface exists, return
+;;; the loopback interface.
+(defun primary-ip-interface ()
+  (let* ((ifaces (ip-interfaces)))
+    (or (find-if #'(lambda (i)
+		     (and (eq #$AF_INET (ip-interface-address-family i))
+                          (ip-interface-addr i)
+			  (let* ((flags (ip-interface-flags i)))
+			    (and (not (logtest #$IFF_LOOPBACK flags))
+				 (logtest #$IFF_UP flags)))))
+		 ifaces)
+	(car ifaces))))
+
+(defun primary-ip-interface-address ()
+  (let* ((iface (primary-ip-interface)))
+    (if iface
+      (ip-interface-addr iface)
+      (error "Can't determine primary IP interface"))))
+	  
+	  
+(defmethod stream-io-error ((stream socket) errno where)
+  (socket-error stream where errno))
Index: /branches/new-random/level-1/l1-sort.lisp
===================================================================
--- /branches/new-random/level-1/l1-sort.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-sort.lisp	(revision 13309)
@@ -0,0 +1,167 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Low-level list sorting routines.  Used by CLOS and SORT.
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro apply-key (key value)
+  `(if ,key
+     (funcall ,key ,value)
+     ,value))
+
+)
+
+;; A macro to make predicate & key into lfuns, or maybe NIL.
+(defmacro canonicalize-pred-and-key (&optional (pred 'pred) (key 'key))
+  `(progn (setq ,pred (coerce-to-function ,pred))
+          (unless (null ,key)
+            (setq ,key (coerce-to-function ,key))
+            (if (eq ,key #'identity) (setq ,key nil)))))
+
+
+(defun final-cons (p)
+  (do* ((drag p lead)
+        (lead (cdr p) (cdr lead)))
+       ((null lead)
+        drag)))
+
+;;; 		   modified to return a pointer to the end of the result
+;;; 		      and to not cons header each time its called.
+;;; It destructively merges list-1 with list-2.  In the resulting
+;;; list, elements of list-2 are guaranteed to come after equal elements
+;;; of list-1.
+(defun merge-lists* (list-1 list-2 pred key)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (null key)
+    (merge-lists*-no-key list-1 list-2 pred) 
+    (cond ((null list-1)
+           (values list-2 (final-cons list-2)))
+          ((null list-2)
+           (values list-1 (final-cons list-1)))
+          (t (let* ((result (cons nil nil))
+                    (P result)                  ; P points to last cell of result
+                    (key-1 (apply-key key (car list-1)))
+                    (key-2 (apply-key key (car list-2))))
+               (declare (dynamic-extent result))
+               (declare (type list p))
+               (loop
+                 (cond ((funcall pred key-2 key-1)
+                        (rplacd P list-2)       ; append the lesser list to last cell of
+                        (setq P (cdr P))        ;   result.  Note: test must bo done for
+                        (pop list-2)            ;   list-2 < list-1 so merge will be
+                        (unless list-2          ;   stable for list-1
+                          (rplacd P list-1)
+                          (return (values (cdr result) (final-cons p))))
+                        (setq key-2 (apply-key key (car list-2))))
+                       (T (rplacd P list-1)         
+                          (setq P (cdr P))
+                          (pop list-1)
+                          (unless list-1
+                            (rplacd P list-2)
+                            (return (values (cdr result) (final-cons p))))
+                          (setq key-1 (apply-key key (car list-1)))))))))))
+
+(defun merge-lists*-no-key (list-1 list-2 pred)
+  (declare (optimize (speed 3) (safety 0)))
+  (cond ((null list-1)
+         (values list-2 (final-cons list-2)))
+        ((null list-2)
+         (values list-1 (final-cons list-1)))
+        (t (let* ((result (cons nil nil))
+                  (P result)                  ; P points to last cell of result
+                  (key-1 (car list-1))
+                  (key-2 (car list-2)))
+             (declare (dynamic-extent result))
+             (declare (type list p))
+             (loop
+               (cond ((funcall pred key-2 key-1)
+                      (rplacd P list-2)        ; append the lesser list to last cell of
+                      (setq P (cdr P))         ;   result.  Note: test must bo done for
+                      (pop list-2)             ;   list-2 < list-1 so merge will be
+                      (unless list-2           ;   stable for list-1
+                        (rplacd P list-1)
+                        (return (values (cdr result) (final-cons p))))
+                      (setq key-2 (car list-2)))
+                     (T (rplacd P list-1)
+                        (setq P (cdr P))
+                        (pop list-1)
+                        (unless list-1
+                          (rplacd P list-2)
+                          (return (values (cdr result) (final-cons p))))
+                        (setq key-1 (car list-1)))))))))
+
+(defun sort-list (list pred key)
+  (canonicalize-pred-and-key pred key)
+  (let ((head (cons nil list))          ; head holds on to everything
+	  (n 1)                                ; bottom-up size of lists to be merged
+	  unsorted                             ; unsorted is the remaining list to be
+                                        ;   broken into n size lists and merged
+	  list-1                               ; list-1 is one length n list to be merged
+	  last)                                ; last points to the last visited cell
+    (declare (fixnum n))
+    (declare (dynamic-extent head))
+    (loop
+      ;; start collecting runs of n at the first element
+      (setf unsorted (cdr head))
+      ;; tack on the first merge of two n-runs to the head holder
+      (setf last head)
+      (let ((n-1 (1- n)))
+        (declare (fixnum n-1))
+        (loop
+	    (setf list-1 unsorted)
+	    (let ((temp (nthcdr n-1 list-1))
+	          list-2)
+	      (cond (temp
+		       ;; there are enough elements for a second run
+		       (setf list-2 (cdr temp))
+		       (setf (cdr temp) nil)
+		       (setf temp (nthcdr n-1 list-2))
+		       (cond (temp
+			        (setf unsorted (cdr temp))
+			        (setf (cdr temp) nil))
+		             ;; the second run goes off the end of the list
+		             (t (setf unsorted nil)))
+		       (multiple-value-bind (merged-head merged-last)
+                                            (merge-lists* list-1 list-2 pred key)
+		         (setf (cdr last) merged-head)
+		         (setf last merged-last))
+		       (if (null unsorted) (return)))
+		      ;; if there is only one run, then tack it on to the end
+		      (t (setf (cdr last) list-1)
+		         (return)))))
+        (setf n (ash n 1)) ; (+ n n)
+        ;; If the inner loop only executed once, then there were only enough
+        ;; elements for two runs given n, so all the elements have been merged
+        ;; into one list.  This may waste one outer iteration to realize.
+        (if (eq list-1 (cdr head))
+	    (return list-1))))))
+
+
+;; The no-key version of %sort-list
+;; list had better be a list.
+;; pred had better be functionp.
+(defun %sort-list-no-key (list pred)
+  (sort-list list pred nil))
+
+(defun sort-list-error ()
+  (error "List arg to SORT not a proper list"))
+
+
+
Index: /branches/new-random/level-1/l1-streams.lisp
===================================================================
--- /branches/new-random/level-1/l1-streams.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-streams.lisp	(revision 13309)
@@ -0,0 +1,6075 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Portions copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;;
+
+(defclass stream ()
+  ())
+
+
+(defclass input-stream (stream)
+  ())
+
+
+(defclass output-stream (stream) ())
+
+(defmethod stream-direction ((s stream))
+  )
+
+(defmethod stream-domain ((s stream))
+  t)
+
+
+(defmethod stream-direction ((s input-stream))
+  (if (typep s 'output-stream)
+    :io
+    :input))
+
+(defmethod stream-direction ((s output-stream))
+  (if (typep s 'input-stream)
+    :io
+    :output))
+
+(defun check-io-timeout (timeout)
+  (when timeout
+    (require-type timeout '(real 0 1000000))))
+
+(defmethod stream-input-timeout ((s input-stream))
+  nil)
+
+(defmethod (setf input-stream-timeout) (new (s input-stream))
+  (check-io-timeout new))
+
+(defmethod stream-output-timeout ((s output-stream))
+  nil)
+
+(defmethod (setf stream-output-timeout) (new (s output-stream))
+  (check-io-timeout new))
+
+;;; Try to return a string containing characters that're near the
+;;; stream's current position, if that makes sense.  Return NIL
+;;; if it doesn't make sense.
+;;; Some things (SOCKET-ERRORs) are signaled as STREAM-ERRORs
+;;; whose STREAM args aren't streams.  That's wrong, but
+;;; defining this method on T keeps things from blowing up worse.
+(defmethod stream-surrounding-characters ((s t))
+  (declare (ignore s))
+  nil)
+
+
+;;; The "direction" argument only helps us dispatch on two-way streams:
+;;; it's legal to ask for the :output device of a stream that's only open
+;;; for input, and one might get a non-null answer in that case.
+(defmethod stream-device ((s stream) direction)
+  (declare (ignore direction)))
+
+;;; Some generic stream functions:
+(defmethod stream-length ((x t) &optional new)
+  (declare (ignore new))
+  (report-bad-arg x 'stream))
+
+(defmethod stream-position ((x t) &optional new)
+  (declare (ignore new))
+  (report-bad-arg x 'stream))
+
+(defmethod stream-element-type ((x t))
+  (report-bad-arg x 'stream))
+
+(defmethod stream-force-output ((x t))
+  (report-bad-arg x 'stream))
+
+(defmethod stream-position ((s stream) &optional newpos)
+  (declare (ignore newpos)))
+
+;;; For input streams:
+
+;; From Shannon Spires, slightly modified.
+(defun generic-read-line (s)
+  (let* ((str (make-array 20 :element-type 'base-char
+			  :adjustable t :fill-pointer 0))
+	 (eof nil))
+    (do* ((ch (read-char s nil :eof) (read-char s nil :eof)))
+	 ((or (eq ch #\newline) (setq eof (eq ch :eof)))
+	  (values (ensure-simple-string str) eof))
+      (vector-push-extend ch str))))
+
+(defun generic-character-read-list (stream list count)
+  (declare (fixnum count))
+  (do* ((tail list (cdr tail))
+	(i 0 (1+ i)))
+       ((= i count) count)
+    (declare (fixnum i))
+    (let* ((ch (read-char stream nil :eof)))
+      (if (eq ch :eof)
+	(return i)
+	(rplaca tail ch)))))
+
+(defun generic-binary-read-list (stream list count)
+  (declare (fixnum count))
+  (do* ((tail list (cdr tail))
+	(i 0 (1+ i)))
+       ((= i count) count)
+    (declare (fixnum i))
+    (let* ((ch (stream-read-byte stream)))
+      (if (eq ch :eof)
+	(return i)
+	(rplaca tail ch)))))
+
+(defun generic-character-read-vector (stream vector start end)
+  (declare (fixnum start end))
+  (do* ((i start (1+ i)))
+       ((= i end) end)
+    (declare (fixnum i))
+    (let* ((ch (stream-read-char stream)))
+      (if (eq ch :eof)
+	(return i)
+	(setf (uvref vector i) ch)))))
+
+(defun generic-binary-read-vector (stream vector start end)
+  (declare (fixnum start end))
+  (do* ((i start (1+ i)))
+       ((= i end) end)
+    (declare (fixnum i))
+    (let* ((byte (stream-read-byte stream)))
+      (if (eq byte :eof)
+	(return i)
+	(setf (uvref vector i) byte)))))
+
+
+;;; For output streams:
+
+(defun generic-advance-to-column (s col)
+  (let* ((current (column s)))
+    (unless (null current)
+      (when (< current col)
+	(do* ((i current (1+ i)))
+	     ((= i col))
+	  (write-char #\Space s)))
+      t)))
+
+
+
+(defun generic-stream-write-string (stream string start end)
+  (setq end (check-sequence-bounds string start end))
+  (locally (declare (fixnum start end))
+    (multiple-value-bind (vect offset) (array-data-and-offset string)
+      (declare (fixnum offset))
+      (unless (zerop offset)
+	(incf start offset)
+	(incf end offset))
+      (do* ((i start (1+ i)))
+	   ((= i end) string)
+	(declare (fixnum i))
+	(write-char (schar vect i) stream)))))
+
+
+
+
+
+
+
+
+
+
+
+
+
+(defstatic *heap-ivectors* ())
+(defvar *heap-ivector-lock* (make-lock))
+
+
+
+(defun %make-heap-ivector (subtype size-in-bytes size-in-elts)
+  (with-macptrs ((ptr (malloc (+ size-in-bytes
+                                 #+32-bit-target (+ 4 2 7) ; 4 for header, 2 for delta, 7 for round up
+                                 #+64-bit-target (+ 8 2 15) ; 8 for header, 2 for delta, 15 for round up
+                                 ))))
+    (let ((vect (fudge-heap-pointer ptr subtype size-in-elts))
+          (p (%null-ptr)))
+      (%vect-data-to-macptr vect p)
+      (with-lock-grabbed (*heap-ivector-lock*)
+        (push vect *heap-ivectors*))
+      (values vect p))))
+
+(defun %heap-ivector-p (v)
+  (with-lock-grabbed (*heap-ivector-lock*)
+    (not (null (member v *heap-ivectors* :test #'eq)))))
+
+
+(defun dispose-heap-ivector (v)
+  (if (%heap-ivector-p v)
+    (with-macptrs (p)
+      (with-lock-grabbed (*heap-ivector-lock*)
+        (setq *heap-ivectors* (delq v *heap-ivectors*)))
+      (%%make-disposable p v)
+      (free p))))
+
+(defun %dispose-heap-ivector (v)
+  (dispose-heap-ivector v))
+
+(defun make-heap-ivector (element-count element-type)
+  (require-type element-count `(unsigned-byte ,(- target::nbits-in-word
+						  target::num-subtag-bits)))
+  (let* ((subtag (ccl::element-type-subtype element-type)))
+    (unless
+        #+ppc32-target
+        (= (logand subtag ppc32::fulltagmask)
+               ppc32::fulltag-immheader)
+        #+ppc64-target
+        (= (logand subtag ppc64::lowtagmask)
+           ppc64::lowtag-immheader)
+        #+x8632-target
+        (= (logand subtag x8632::fulltagmask)
+	   x8632::fulltag-immheader)
+        #+x8664-target
+        (logbitp (the (mod 16) (logand subtag x8664::fulltagmask))
+                 (logior (ash 1 x8664::fulltag-immheader-0)
+                         (ash 1 x8664::fulltag-immheader-1)
+                         (ash 1 x8664::fulltag-immheader-2)))
+      (error "~s is not an ivector subtype." element-type))
+    (let* ((size-in-octets (ccl::subtag-bytes subtag element-count)))
+      (multiple-value-bind (pointer vector)
+          (ccl::%make-heap-ivector subtag size-in-octets element-count)
+        (values pointer vector size-in-octets)))))
+
+
+
+
+
+
+
+
+
+(defvar *elements-per-buffer* 2048)  ; default buffer size for file io
+
+(defmethod streamp ((x t))
+  nil)
+
+(defmethod streamp ((x stream))
+  t)
+
+(defmethod stream-io-error ((stream stream) error-number context)
+  (error 'simple-stream-error :stream stream
+	 :format-control (format nil "~a during ~a"
+				 (%strerror error-number) context)))
+
+
+
+(defmethod stream-write-char ((stream stream) char)
+  (declare (ignore char))
+  (error "stream ~S is not capable of output" stream))
+
+(defun stream-write-entire-string (stream string)
+  (stream-write-string stream string))
+
+
+(defmethod stream-read-char ((x t))
+  (report-bad-arg x 'stream))
+
+(defmethod stream-read-char ((stream stream))
+  (error "~s is not capable of input" stream))
+
+(defmethod stream-unread-char ((x t) char)
+  (declare (ignore char))
+  (report-bad-arg x 'stream))
+
+(defmethod stream-unread-char ((stream stream) char)
+  (declare (ignore char))
+  (error "stream ~S is not capable of input" stream))
+
+
+
+(defmethod stream-force-output ((stream output-stream)) nil)
+(defmethod stream-maybe-force-output ((stream stream))
+  (stream-force-output stream))
+
+(defmethod stream-finish-output ((stream output-stream)) nil)
+
+
+
+(defmethod stream-clear-output ((stream output-stream)) nil)
+
+(defmethod close ((stream stream) &key abort)
+  (declare (ignore abort))
+  (open-stream-p stream))
+
+(defmethod close-for-termination ((stream stream) abort)
+  (close stream :abort abort))
+
+
+(defmethod open-stream-p ((x t))
+  (report-bad-arg x 'stream))
+
+(defmethod open-stream-p ((stream stream))
+  t)
+
+(defmethod stream-external-format ((x t))
+  (report-bad-arg x 'stream))
+
+(defmethod stream-external-format ((s stream))
+  nil)
+
+
+(defmethod (setf stream-external-format) (new (s t))
+  (normalize-external-format (stream-domain s) new)
+  (report-bad-arg s 'stream))
+
+
+
+    
+(defmethod stream-fresh-line ((stream output-stream))
+  (terpri stream)
+  t)
+
+(defmethod stream-line-length ((stream stream))
+  "This is meant to be shadowed by particular kinds of streams,
+   esp those associated with windows."
+  80)
+
+(defmethod interactive-stream-p ((x t))
+  (report-bad-arg x 'stream))
+
+(defmethod interactive-stream-p ((stream stream)) nil)
+
+(defmethod stream-clear-input ((x t))
+  (report-bad-arg x 'input-stream))
+
+(defmethod stream-clear-input ((stream input-stream)) nil)
+
+(defmethod stream-listen ((stream input-stream))
+  (not (eofp stream)))
+
+(defmethod stream-filename ((stream stream))
+  (report-bad-arg stream 'file-stream))
+
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; For input streams, the IO-BUFFER-COUNT field denotes the number
+;;; of elements read from the underlying input source (e.g., the
+;;; file system.)  For output streams, it's the high-water mark of
+;;; elements output to the buffer.
+
+(defstruct io-buffer
+               ;; This type is too complex during bootstrapping.
+  (buffer nil #|:type (or (simple-array * (*)) null)|#)
+  (bufptr nil :type (or macptr null))
+  (size 0 :type fixnum)			; size (in octets) of buffer
+  (idx 0 :type fixnum)			; index of next element
+  (count 0 :type fixnum)		; count of active elements
+  (limit 0 :type fixnum)		; size (in elements) of buffer
+  (translate nil)                       ; newline-translation
+  )
+
+(defmethod print-object ((buf io-buffer) out)
+  (print-unreadable-object (buf out :identity t :type t)
+    (let* ((buffer (io-buffer-buffer buf)))
+      (when buffer (format out " ~s " (array-element-type buffer))))
+    (format out "~d/~d/~d"
+	    (io-buffer-idx buf)
+	    (io-buffer-count buf)
+	    (io-buffer-limit buf))))
+
+(defstruct ioblock
+  stream                                ; the stream being buffered
+  untyi-char                            ; nil or last value passed to
+                                        ;  stream-unread-char
+  (inbuf nil :type (or null io-buffer))
+  (outbuf nil :type (or null io-buffer))
+  (element-type 'character)
+  (element-shift 0 :type fixnum)        ;element shift count
+  (charpos 0 :type (or null fixnum))     ;position of cursor
+  (device -1 :type (or null fixnum))     ;file descriptor
+  (advance-function 'ioblock-advance)
+  (listen-function 'ioblock-listen)
+  (eofp-function 'ioblock-eofp)
+  (force-output-function 'ioblock-force-output)
+  (close-function 'ioblock-close)
+  (inbuf-lock nil)
+  (eof nil)
+  (interactive nil)
+  (dirty nil)
+  (outbuf-lock nil)
+  (owner nil)
+  (read-char-function 'ioblock-no-char-input)
+  (read-byte-function 'ioblock-no-binary-input)
+  (write-byte-function 'ioblock-no-binary-output)
+  (write-char-function 'ioblock-no-char-output)
+  (encoding nil)
+  (pending-byte-order-mark nil)
+  (decode-literal-code-unit-limit 256)
+  (encode-output-function nil)
+  (decode-input-function nil)
+  (read-char-when-locked-function 'ioblock-no-char-input)
+  (write-simple-string-function 'ioblock-no-char-output)
+  (character-read-vector-function 'ioblock-no-char-input)
+  (read-line-function 'ioblock-no-char-input)
+  (write-char-when-locked-function 'ioblock-no-char-output)
+  (read-byte-when-locked-function 'ioblock-no-binary-input)
+  (write-byte-when-locked-function 'ioblock-no-binary-output)
+  (peek-char-function 'ioblock-no-char-input)
+  (native-byte-order t)
+  (read-char-without-translation-when-locked-function 'ioblock-no-char-input)
+  (write-char-without-translation-when-locked-function 'iblock-no-char-output)
+  (sharing nil)
+  (line-termination nil)
+  (unread-char-function 'ioblock-no-char-input)
+  (encode-literal-char-code-limit 256)
+  (input-timeout nil)
+  (output-timeout nil)
+  (deadline nil))
+
+
+;;; Functions on ioblocks.  So far, we aren't saying anything
+;;; about how streams use them.
+
+(defun ioblock-no-binary-input (ioblock &rest otters)
+  (declare (ignore otters))
+  (report-bad-arg (ioblock-stream ioblock) '(and binary-stream input-stream)))
+
+(defun ioblock-no-binary-output (ioblock &rest others)
+  (declare (ignore others))
+  (report-bad-arg (ioblock-stream ioblock) '(and binary-stream output-stream)))
+
+(defun ioblock-no-char-input (ioblock &rest others)
+  (declare (ignore others))
+  (report-bad-arg (ioblock-stream ioblock) '(and character-stream input-stream)))
+
+(defun ioblock-no-char-output (ioblock &rest others)
+  (declare (ignore others))
+  (report-bad-arg (ioblock-stream ioblock) '(and character-stream output-stream)))
+
+
+(defun ioblock-octets-to-elements (ioblock octets)
+  (let* ((shift (ioblock-element-shift ioblock)))
+    (declare (fixnum shift))
+    (if (zerop shift)
+      octets
+      (ash octets (- shift)))))
+
+(defun ioblock-elements-to-octets (ioblock elements)
+  (let* ((shift (ioblock-element-shift ioblock)))
+    (declare (fixnum shift))
+    (if (zerop shift)
+      elements
+      (ash elements shift))))
+
+
+
+;;; ioblock must really be an ioblock or you will crash
+;;; Also: the expression "ioblock" is evaluated multiple times.
+
+(declaim (inline check-ioblock-owner))
+(defun check-ioblock-owner (ioblock)
+  (declare (optimize (speed 3)))
+  (let* ((owner (ioblock-owner ioblock)))
+    (if owner
+      (or (eq owner *current-process*)
+          (conditional-store (ioblock-owner ioblock) 0 *current-process*)
+          (error "Stream ~s is private to ~s" (ioblock-stream ioblock) owner)))))
+
+
+
+(declaim (inline %ioblock-advance))
+(defun %ioblock-advance (ioblock read-p)
+  (funcall (ioblock-advance-function ioblock)
+           (ioblock-stream ioblock)
+           ioblock
+           read-p))
+
+
+(defun %ioblock-surrounding-characters (ioblock)
+  (let* ((inbuf (ioblock-inbuf ioblock)))
+    (when inbuf
+      (let* ((encoding (or (ioblock-encoding ioblock)
+                           (get-character-encoding nil)))
+             (size (ash (character-encoding-code-unit-size encoding) -3))
+             (buffer (io-buffer-buffer inbuf))
+             (idx (io-buffer-idx inbuf))
+             (count (io-buffer-count inbuf)))
+        (unless (= count 0)
+          (let* ((start (max (- idx (* 10 size)) 0))
+                 (end (min (+ idx (* 10 size)) count))
+                 (string (make-string (funcall (character-encoding-length-of-vector-encoding-function encoding) buffer start end))))
+            (funcall (character-encoding-vector-decode-function encoding)
+                     buffer
+                     start
+                     (- end start)
+                     string)
+            (if (position #\Replacement_Character string)
+              (string-trim (string #\Replacement_Character) string)
+              string)))))))
+             
+        
+
+
+(defun %bivalent-ioblock-read-u8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (setf (ioblock-untyi-char ioblock) nil)
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %bivalent-ioblock-read-u8-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (unsigned-byte 8) (*))
+              (io-buffer-buffer buf)) idx)))
+
+
+(declaim (inline %ioblock-read-u8-byte))
+(defun %ioblock-read-u8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-u8-byte :eof))
+      (setq idx (io-buffer-idx buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (unsigned-byte 8) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(declaim (inline %ioblock-read-u8-code-unit))
+(defun %ioblock-read-u8-code-unit (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-u8-code-unit :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (unsigned-byte 8) (*))
+              (io-buffer-buffer buf)) idx)))             
+
+(declaim (inline %ioblock-read-s8-byte))
+(defun %ioblock-read-s8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-s8-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (signed-byte 8) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-s8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-s8-byte ioblock))
+
+(defun %locked-ioblock-read-s8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-s8-byte ioblock)))
+
+
+(declaim (inline %ioblock-read-u16-byte))
+(defun %ioblock-read-u16-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-u16-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (unsigned-byte 16) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-u16-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-u16-byte ioblock))
+
+(defun %locked-ioblock-read-u16-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-u16-byte ioblock)))
+
+(declaim (inline %ioblock-read-s16-byte))
+(defun %ioblock-read-s16-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-s16-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (signed-byte 16) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-s16-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-s16-byte ioblock))
+
+(defun %locked-ioblock-read-s16-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-s16-byte ioblock)))
+
+
+(declaim (inline %ioblock-read-u32-byte))
+(defun %ioblock-read-u32-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-u32-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (unsigned-byte 32) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-u32-byte (ioblock)
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-u32-byte ioblock))
+
+(defun %locked-ioblock-read-u32-byte (ioblock)
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-u32-byte ioblock)))
+
+(declaim (inline %ioblock-read-s32-byte))
+(defun %ioblock-read-s32-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-s32-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (signed-byte 32) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-s32-byte (ioblock)
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-s32-byte ioblock))
+
+(defun %locked-ioblock-read-s32-byte (ioblock)
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-s32-byte ioblock)))
+
+#+64-bit-target
+(progn
+(declaim (inline %ioblock-read-u64-byte))
+(defun %ioblock-read-u64-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-u64-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (unsigned-byte 64) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-u64-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-u64-byte ioblock))
+
+(defun %locked-ioblock-read-u64-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-u64-byte ioblock)))
+
+(defun %ioblock-read-s64-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf)))
+    (declare (fixnum idx limit))
+    (when (= idx limit)
+      (unless (%ioblock-advance ioblock t)
+        (return-from %ioblock-read-s64-byte :eof))
+      (setq idx (io-buffer-idx buf)
+            limit (io-buffer-count buf)))
+    (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+    (aref (the (simple-array (signed-byte 64) (*))
+            (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-s64-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-s64-byte ioblock))
+
+(defun %locked-ioblock-read-s64-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-s64-byte ioblock)))
+)
+
+
+;;; Read a 16-bit code element from a stream with element-type
+;;; (UNSIGNED-BYTE 8), in native byte-order.
+
+(declaim (inline %ioblock-read-u16-code-unit))
+(defun %ioblock-read-u16-code-unit (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf))
+         (vector (io-buffer-buffer buf)))
+    (declare (fixnum idx limit)
+             (type (simple-array (unsigned-byte 8) (*)) vector))
+    (if (<= (the fixnum (+ idx 2)) limit)
+      (let* ((b0 (aref vector idx))
+             (b1 (aref vector (the fixnum (1+ idx)))))
+        (declare (type (unsigned-byte 8) b0 b1))
+        (setf (io-buffer-idx buf) (the fixnum (+ idx 2)))
+        #+big-endian-target
+        (logior (the (unsigned-byte 16) (ash b0 8)) b1)
+        #+little-endian-target
+        (logior (the (unsigned-byte 16) (ash b1 8)) b0))
+      (if (< idx limit)
+        (let* ((b0 (aref vector idx))
+               (n (%ioblock-advance ioblock t)))
+          (declare (type (unsigned-byte 8) b0))
+          (if (null n)
+            :eof
+            (let* ((b1 (aref vector 0)))
+              (declare (type (unsigned-byte 8) b1))
+              (setf (io-buffer-idx buf) 1)
+              #+big-endian-target
+              (logior (the (unsigned-byte 16) (ash b0 8)) b1)
+              #+little-endian-target
+              (logior (the (unsigned-byte 16) (ash b1 8)) b0))))
+        (let* ((n (%ioblock-advance ioblock t)))
+          (if (null n)
+            :eof
+            (if (eql n 1)
+              (progn
+                (setf (io-buffer-idx buf) 1)
+                :eof)
+              (let* ((b0 (aref vector 0))
+                     (b1 (aref vector 1)))
+                (declare (type (unsigned-byte 8) b0 b1))
+                (setf (io-buffer-idx buf) 2)
+                #+big-endian-target
+                (logior (the (unsigned-byte 16) (ash b0 8)) b1)
+                #+little-endian-target
+                (logior (the (unsigned-byte 16) (ash b1 8)) b0)))))))))
+  
+(declaim (inline %ioblock-read-swapped-u16-code-unit))
+(defun %ioblock-read-swapped-u16-code-unit (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+    (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf))
+         (vector (io-buffer-buffer buf)))
+    (declare (fixnum idx limit)
+             (type (simple-array (unsigned-byte 8) (*)) vector))
+    (if (<= (the fixnum (+ idx 2)) limit)
+      (let* ((b0 (aref vector idx))
+             (b1 (aref vector (the fixnum (1+ idx)))))
+        (declare (type (unsigned-byte 8) b0 b1))
+        (setf (io-buffer-idx buf) (the fixnum (+ idx 2)))
+        #+little-endian-target
+        (logior (the (unsigned-byte 16) (ash b0 8)) b1)
+        #+big-endian-target
+        (logior (the (unsigned-byte 16) (ash b1 8)) b0))
+      (if (< idx limit)
+        (let* ((b0 (aref vector idx))
+               (n (%ioblock-advance ioblock t)))
+          (declare (type (unsigned-byte 8) b0))
+          (if (null n)
+            :eof
+            (let* ((b1 (aref vector 0)))
+              (declare (type (unsigned-byte 8) b1))
+              (setf (io-buffer-idx buf) 1)
+              #+little-endian-target
+              (logior (the (unsigned-byte 16) (ash b0 8)) b1)
+              #+big-endian-target
+              (logior (the (unsigned-byte 16) (ash b1 8)) b0))))
+        (let* ((n (%ioblock-advance ioblock t)))
+          (if (null n)
+            :eof
+            (if (eql n 1)
+              (progn
+                (setf (io-buffer-idx buf) 1)
+                :eof)
+              (let* ((b0 (aref vector 0))
+                     (b1 (aref vector 1)))
+                (declare (type (unsigned-byte 8) b0 b1))
+                (setf (io-buffer-idx buf) 2)
+                #+little-endian-target
+                (logior (the (unsigned-byte 16) (ash b0 8)) b1)
+                #+big-endian-target
+                (logior (the (unsigned-byte 16) (ash b1 8)) b0)))))))))
+
+
+(declaim (inline %ioblock-read-u32-code-unit))
+(defun %ioblock-read-u32-code-unit (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf))
+         (vector (io-buffer-buffer buf)))
+    (declare (fixnum idx limit)
+             (type (simple-array (unsigned-byte 8) (*)) vector))
+    (cond ((<= (the fixnum (+ idx 4)) limit)
+           (let* ((b0 (aref vector idx))
+                  (b1 (aref vector (the fixnum (1+ idx))))
+                  (b2 (aref vector (the fixnum (+ idx 2))))
+                  (b3 (aref vector (the fixnum (+ idx 3)))))
+             (declare (type (unsigned-byte 8) b0 b1 b2 b3))
+             (setf (io-buffer-idx buf) (the fixnum (+ idx 4)))
+             #+big-endian-target
+             (logior (the (unsigned-byte 32) (ash b0 24))
+                     (the (unsigned-byte 24) (ash b1 16))
+                     (the (unsigned-byte 16) (ash b2 8))
+                     b3)
+             #+little-endian-target
+             (logior (the (unsigned-byte 32) (ash b3 24))
+                     (the (unsigned-byte 24) (ash b2 16))
+                     (the (unsigned-byte 16) (ash b1 8))
+                     b0)))
+          ((= (the fixnum (+ idx 3)) limit)
+           (let* ((b0 (aref vector idx))
+                  (b1 (aref vector (the fixnum (1+ idx))))
+                  (b2 (aref vector (the fixnum (+ idx 2))))
+                  (n (%ioblock-advance ioblock t)))
+             (declare (type (unsigned-byte 8) b0 b1 b2))
+             (if (null n)
+               :eof
+               (let* ((b3 (aref vector 0)))
+                 (declare (type (unsigned-byte 8) b3))
+                 (setf (io-buffer-idx buf) 1)
+                 #+big-endian-target
+                 (logior (the (unsigned-byte 32) (ash b0 24))
+                         (the (unsigned-byte 24) (ash b1 16))
+                         (the (unsigned-byte 16) (ash b2 8))
+                         b3)
+                 #+little-endian-target
+                 (logior (the (unsigned-byte 32) (ash b3 24))
+                         (the (unsigned-byte 24) (ash b2 16))
+                         (the (unsigned-byte 16) (ash b1 8))
+                         b0)))))
+          ((= (the fixnum (+ idx 2)) limit)
+           (let* ((b0 (aref vector idx))
+                  (b1 (aref vector (the fixnum (1+ idx))))
+                  (n (%ioblock-advance ioblock t)))
+             (declare (type (unsigned-byte 8) b0 b1))
+             (if (null n)
+               :eof
+               (if (eql n 1)
+                 (progn
+                   (setf (io-buffer-idx buf) 1)
+                   :eof)
+                 (let* ((b2 (aref vector 0))
+                        (b3 (aref vector 1)))
+                   (declare (type (unsigned-byte 8) b2 b3))
+                   (setf (io-buffer-idx buf) 2)
+                   #+big-endian-target
+                   (logior (the (unsigned-byte 32) (ash b0 24))
+                           (the (unsigned-byte 24) (ash b1 16))
+                           (the (unsigned-byte 16) (ash b2 8))
+                           b3)
+                   #+little-endian-target
+                   (logior (the (unsigned-byte 32) (ash b3 24))
+                           (the (unsigned-byte 24) (ash b2 16))
+                           (the (unsigned-byte 16) (ash b1 8))
+                           b0))))))
+          ((= (the fixnum (1+ idx)) limit)
+           (let* ((b0 (aref vector idx))
+                  (n (%ioblock-advance ioblock t)))
+             (declare (type (unsigned-byte 8) b0))
+             (if (null n)
+               :eof
+               (if (< n 3)
+                 (progn
+                   (setf (io-buffer-idx buf) n)
+                   :eof)
+                 (let* ((b1 (aref vector 0))
+                        (b2 (aref vector 1))
+                        (b3 (aref vector 2)))
+                   (setf (io-buffer-idx buf) 3)
+                   #+big-endian-target
+                   (logior (the (unsigned-byte 32) (ash b0 24))
+                           (the (unsigned-byte 24) (ash b1 16))
+                           (the (unsigned-byte 16) (ash b2 8))
+                           b3)
+                   #+little-endian-target
+                   (logior (the (unsigned-byte 32) (ash b3 24))
+                           (the (unsigned-byte 24) (ash b2 16))
+                           (the (unsigned-byte 16) (ash b1 8))
+                           b0))))))
+          (t
+           (let* ((n (%ioblock-advance ioblock t)))
+             (if (null n)
+               :eof
+               (if (< n 4)
+                 (progn
+                   (setf (io-buffer-idx buf) n)
+                   :eof)
+                 (let* ((b0 (aref vector 0))
+                        (b1 (aref vector 1))
+                        (b2 (aref vector 2))
+                        (b3 (aref vector 3)))
+                (declare (type (unsigned-byte 8) b0 b1 b2 b3))
+                (setf (io-buffer-idx buf) 4)
+                #+big-endian-target
+                (logior (the (unsigned-byte 32) (ash b0 24))
+                        (the (unsigned-byte 24) (ash b1 16))
+                        (the (unsigned-byte 16) (ash b2 8))
+                        b3)
+                #+little-endian-target
+                (logior (the (unsigned-byte 32) (ash b3 24))
+                        (the (unsigned-byte 24) (ash b2 16))
+                        (the (unsigned-byte 16) (ash b1 8))
+                        b0)))))))))
+
+(declaim (inline %ioblock-read-swapped-u32-code-unit))
+(defun %ioblock-read-swapped-u32-code-unit (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx buf))
+         (limit (io-buffer-count buf))
+         (vector (io-buffer-buffer buf)))
+    (declare (fixnum idx limit)
+             (type (simple-array (unsigned-byte 8) (*)) vector))
+    (cond ((<= (the fixnum (+ idx 4)) limit)
+           (let* ((b0 (aref vector idx))
+                  (b1 (aref vector (the fixnum (1+ idx))))
+                  (b2 (aref vector (the fixnum (+ idx 2))))
+                  (b3 (aref vector (the fixnum (+ idx 3)))))
+             (declare (type (unsigned-byte 8) b0 b1 b2 b3))
+             (setf (io-buffer-idx buf) (the fixnum (+ idx 4)))
+             #+little-endian-target
+             (logior (the (unsigned-byte 32) (ash b0 24))
+                     (the (unsigned-byte 24) (ash b1 16))
+                     (the (unsigned-byte 16) (ash b2 8))
+                     b3)
+             #+big-endian-target
+             (logior (the (unsigned-byte 32) (ash b3 24))
+                     (the (unsigned-byte 24) (ash b2 16))
+                     (the (unsigned-byte 16) (ash b1 8))
+                     b0)))
+          ((= (the fixnum (+ idx 3)) limit)
+           (let* ((b0 (aref vector idx))
+                  (b1 (aref vector (the fixnum (1+ idx))))
+                  (b2 (aref vector (the fixnum (+ idx 2))))
+                  (n (%ioblock-advance ioblock t)))
+             (declare (type (unsigned-byte 8) b0 b1 b2))
+             (if (null n)
+               :eof
+               (let* ((b3 (aref vector 0)))
+                 (declare (type (unsigned-byte 8) b3))
+                 (setf (io-buffer-idx buf) 1)
+                 #+little-endian-target
+                 (logior (the (unsigned-byte 32) (ash b0 24))
+                         (the (unsigned-byte 24) (ash b1 16))
+                         (the (unsigned-byte 16) (ash b2 8))
+                         b3)
+                 #+big-endian-target
+                 (logior (the (unsigned-byte 32) (ash b3 24))
+                         (the (unsigned-byte 24) (ash b2 16))
+                         (the (unsigned-byte 16) (ash b1 8))
+                         b0)))))
+          ((= (the fixnum (+ idx 2)) limit)
+           (let* ((b0 (aref vector idx))
+                  (b1 (aref vector (the fixnum (1+ idx))))
+                  (n (%ioblock-advance ioblock t)))
+             (declare (type (unsigned-byte 8) b0 b1))
+             (if (null n)
+               :eof
+               (if (eql n 1)
+                 (progn
+                   (setf (io-buffer-idx buf) 1)
+                   :eof)
+                 (let* ((b2 (aref vector 0))
+                        (b3 (aref vector 1)))
+                   (declare (type (unsigned-byte 8) b2 b3))
+                   (setf (io-buffer-idx buf) 2)
+                   #+little-endian-target
+                   (logior (the (unsigned-byte 32) (ash b0 24))
+                           (the (unsigned-byte 24) (ash b1 16))
+                           (the (unsigned-byte 16) (ash b2 8))
+                           b3)
+                   #+big-endian-target
+                   (logior (the (unsigned-byte 32) (ash b3 24))
+                           (the (unsigned-byte 24) (ash b2 16))
+                           (the (unsigned-byte 16) (ash b1 8))
+                           b0))))))
+          ((= (the fixnum (1+ idx)) limit)
+           (let* ((b0 (aref vector idx))
+                  (n (%ioblock-advance ioblock t)))
+             (declare (type (unsigned-byte 8) b0))
+             (if (null n)
+               :eof
+               (if (< n 3)
+                 (progn
+                   (setf (io-buffer-idx buf) n)
+                   :eof)
+                 (let* ((b1 (aref vector 0))
+                        (b2 (aref vector 1))
+                        (b3 (aref vector 2)))
+                   (setf (io-buffer-idx buf) 3)
+                   #+little-endian-target
+                   (logior (the (unsigned-byte 32) (ash b0 24))
+                           (the (unsigned-byte 24) (ash b1 16))
+                           (the (unsigned-byte 16) (ash b2 8))
+                           b3)
+                   #+big-endian-target
+                   (logior (the (unsigned-byte 32) (ash b3 24))
+                           (the (unsigned-byte 24) (ash b2 16))
+                           (the (unsigned-byte 16) (ash b1 8))
+                           b0))))))
+          (t
+           (let* ((n (%ioblock-advance ioblock t)))
+             (if (null n)
+               :eof
+               (if (< n 4)
+                 (progn
+                   (setf (io-buffer-idx buf) n)
+                   :eof)
+                 (let* ((b0 (aref vector 0))
+                        (b1 (aref vector 1))
+                        (b2 (aref vector 2))
+                        (b3 (aref vector 3)))
+                (declare (type (unsigned-byte 8) b0 b1 b2 b3))
+                (setf (io-buffer-idx buf) 4)
+                #+little-endian-target
+                (logior (the (unsigned-byte 32) (ash b0 24))
+                        (the (unsigned-byte 24) (ash b1 16))
+                        (the (unsigned-byte 16) (ash b2 8))
+                        b3)
+                #+big-endian-target
+                (logior (the (unsigned-byte 32) (ash b3 24))
+                        (the (unsigned-byte 24) (ash b2 16))
+                        (the (unsigned-byte 16) (ash b1 8))
+                        b0)))))))))
+
+
+(defun %bivalent-private-ioblock-read-u8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (setf (ioblock-untyi-char ioblock) nil)
+    (let* ((buf (ioblock-inbuf ioblock))
+	   (idx (io-buffer-idx buf))
+	   (limit (io-buffer-count buf)))
+      (declare (fixnum idx limit))
+      (when (= idx limit)
+	(unless (%ioblock-advance ioblock t)
+	  (return-from %bivalent-private-ioblock-read-u8-byte :eof))
+	(setq idx (io-buffer-idx buf)
+	      limit (io-buffer-count buf)))
+      (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+      (aref (the (simple-array (unsigned-byte 8) (*))
+              (io-buffer-buffer buf)) idx)))
+
+(defun %private-ioblock-read-u8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-u8-byte ioblock))
+
+(defun %bivalent-locked-ioblock-read-u8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (setf (ioblock-untyi-char ioblock) nil)
+    (let* ((buf (ioblock-inbuf ioblock))
+           (idx (io-buffer-idx buf))
+           (limit (io-buffer-count buf)))
+      (declare (fixnum idx limit))
+      (when (= idx limit)
+        (unless (%ioblock-advance ioblock t)
+          (return-from %bivalent-locked-ioblock-read-u8-byte :eof))
+        (setq idx (io-buffer-idx buf)
+              limit (io-buffer-count buf)))
+      (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+      (aref (the (simple-array (unsigned-byte 8) (*))
+              (io-buffer-buffer buf)) idx))))
+
+(defun %locked-ioblock-read-u8-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-u8-byte ioblock)))
+
+(defun %general-ioblock-read-byte (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-locked (ioblock)
+    (let* ((buf (ioblock-inbuf ioblock))
+           (idx (io-buffer-idx buf))
+           (limit (io-buffer-count buf)))
+      (declare (fixnum idx limit))
+      (when (= idx limit)
+        (unless (%ioblock-advance ioblock t)
+          (return-from %general-ioblock-read-byte :eof))
+        (setq idx (io-buffer-idx buf)
+              limit (io-buffer-count buf)))
+      (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+      (uvref (io-buffer-buffer buf) idx))))
+
+
+(declaim (inline %ioblock-tyi))
+(defun %ioblock-tyi (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((ch (ioblock-untyi-char ioblock)))
+    (if ch
+      (prog1 ch
+        (setf (ioblock-untyi-char ioblock) nil))
+      (let* ((buf (ioblock-inbuf ioblock))
+             (idx (io-buffer-idx buf))
+             (limit (io-buffer-count buf)))
+        (declare (fixnum idx limit))
+        (when (= idx limit)
+          (unless (%ioblock-advance ioblock t)
+            (return-from %ioblock-tyi :eof))
+          (setq idx 0))
+        (setf (io-buffer-idx buf) (the fixnum (1+ idx)))
+        (%code-char (aref (the (simple-array (unsigned-byte 8) (*))
+                                       (io-buffer-buffer buf)) idx))))))
+
+(defun %private-ioblock-tyi (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-tyi ioblock))
+
+(defun %locked-ioblock-tyi (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-tyi ioblock)))
+
+;;; Read a character composed of one or more 8-bit code-units.
+(declaim (inline %ioblock-read-u8-encoded-char))
+(defun %ioblock-read-u8-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((ch (ioblock-untyi-char ioblock)))
+    (if ch
+      (prog1 ch
+        (setf (ioblock-untyi-char ioblock) nil))
+      (let* ((1st-unit (%ioblock-read-u8-code-unit ioblock)))
+        (if (eq 1st-unit :eof)
+          1st-unit
+          (locally
+              (declare (type (unsigned-byte 8) 1st-unit))
+            (if (< 1st-unit
+                   (the (mod #x110000) (ioblock-decode-literal-code-unit-limit ioblock)))
+              (%code-char 1st-unit)
+              (funcall (ioblock-decode-input-function ioblock)
+                       1st-unit
+                       #'%ioblock-read-u8-code-unit
+                       ioblock))))))))
+
+(defun %private-ioblock-read-u8-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-u8-encoded-char ioblock))
+
+(defun %locked-ioblock-read-u8-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-u8-encoded-char ioblock)))
+
+(declaim (inline %ioblock-read-u16-encoded-char))
+(defun %ioblock-read-u16-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((ch (ioblock-untyi-char ioblock)))
+    (if ch
+      (prog1 ch
+        (setf (ioblock-untyi-char ioblock) nil))
+      (let* ((1st-unit (%ioblock-read-u16-code-unit ioblock)))
+        (if (eq 1st-unit :eof)
+          1st-unit
+          (locally
+              (declare (type (unsigned-byte 16) 1st-unit))
+            (if (< 1st-unit
+                   (the (mod #x110000) (ioblock-decode-literal-code-unit-limit ioblock)))
+              (code-char 1st-unit)
+              (funcall (ioblock-decode-input-function ioblock)
+                       1st-unit
+                       #'%ioblock-read-u16-code-unit
+                       ioblock))))))))
+
+(defun %private-ioblock-read-u16-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-u16-encoded-char ioblock))
+
+(defun %locked-ioblock-read-u16-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-u16-encoded-char ioblock)))
+
+(declaim (inline %ioblock-read-swapped-u16-encoded-char))
+(defun %ioblock-read-swapped-u16-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((ch (ioblock-untyi-char ioblock)))
+    (if ch
+      (prog1 ch
+        (setf (ioblock-untyi-char ioblock) nil))
+      (let* ((1st-unit (%ioblock-read-swapped-u16-code-unit ioblock)))
+        (if (eq 1st-unit :eof)
+          1st-unit
+          (locally
+              (declare (type (unsigned-byte 16) 1st-unit))
+            (if (< 1st-unit
+                   (the (mod #x110000) (ioblock-decode-literal-code-unit-limit ioblock)))
+              (code-char 1st-unit)
+              (funcall (ioblock-decode-input-function ioblock)
+                       1st-unit
+                       #'%ioblock-read-swapped-u16-code-unit
+                       ioblock))))))))
+
+(defun %private-ioblock-read-swapped-u16-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-swapped-u16-encoded-char ioblock))
+
+(defun %locked-ioblock-read-swapped-u16-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-swapped-u16-encoded-char ioblock)))
+
+(declaim (inline %ioblock-read-u32-encoded-char))
+(defun %ioblock-read-u32-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((ch (ioblock-untyi-char ioblock)))
+    (if ch
+      (prog1 ch
+        (setf (ioblock-untyi-char ioblock) nil))
+      (let* ((1st-unit (%ioblock-read-u32-code-unit ioblock)))
+        (if (eq 1st-unit :eof)
+          1st-unit
+          (locally
+              (declare (type (unsigned-byte 16) 1st-unit))
+            (if (< 1st-unit
+                   (the (mod #x110000) (ioblock-decode-literal-code-unit-limit ioblock)))
+              (code-char 1st-unit)
+              (funcall (ioblock-decode-input-function ioblock)
+                       1st-unit
+                       #'%ioblock-read-u32-code-unit
+                       ioblock))))))))
+
+(defun %private-ioblock-read-u32-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-u32-encoded-char ioblock))
+
+(defun %locked-ioblock-read-u32-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-u32-encoded-char ioblock)))
+
+(declaim (inline %ioblock-read-swapped-u32-encoded-char))
+(defun %ioblock-read-swapped-u32-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((ch (ioblock-untyi-char ioblock)))
+    (if ch
+      (prog1 ch
+        (setf (ioblock-untyi-char ioblock) nil))
+      (let* ((1st-unit (%ioblock-read-swapped-u32-code-unit ioblock)))
+        (if (eq 1st-unit :eof)
+          1st-unit
+          (locally
+              (declare (type (unsigned-byte 16) 1st-unit))
+            (if (< 1st-unit
+                   (the (mod #x110000) (ioblock-decode-literal-code-unit-limit ioblock)))
+              (code-char 1st-unit)
+              (funcall (ioblock-decode-input-function ioblock)
+                       1st-unit
+                       #'%ioblock-read-swapped-u32-code-unit
+                       ioblock))))))))
+
+(defun %private-ioblock-read-swapped-u32-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-swapped-u32-encoded-char ioblock))
+
+(defun %locked-ioblock-read-swapped-u32-encoded-char (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-swapped-u32-encoded-char ioblock)))
+
+(declaim (inline %ioblock-tyi-no-hang))
+(defun %ioblock-tyi-no-hang (ioblock)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (ioblock-untyi-char ioblock)
+    (prog1 (ioblock-untyi-char ioblock)
+      (setf (ioblock-untyi-char ioblock) nil))
+    (let* ((buf (ioblock-inbuf ioblock))
+	   (idx (io-buffer-idx buf))
+	   (limit (io-buffer-count buf)))
+      (declare (fixnum idx limit))
+      (when (= idx limit)
+	(unless (%ioblock-advance ioblock nil)
+	  (return-from %ioblock-tyi-no-hang (if (ioblock-eof ioblock) :eof))))
+      (funcall (ioblock-read-char-when-locked-function ioblock) ioblock))))
+
+;;; :iso-8859-1 only.
+(defun %ioblock-peek-char (ioblock)
+  (or (ioblock-untyi-char ioblock)
+      (let* ((buf (ioblock-inbuf ioblock))
+             (idx (io-buffer-idx buf))
+             (limit (io-buffer-count buf)))
+        (declare (fixnum idx limit))
+        (when (= idx limit)
+          (unless (%ioblock-advance ioblock t)
+            (return-from %ioblock-peek-char :eof))
+          (setq idx (io-buffer-idx buf)
+                limit (io-buffer-count buf)))
+        (%code-char (aref (the (simple-array (unsigned-byte 8) (*)) (io-buffer-buffer buf)) idx)))))
+
+(defun %encoded-ioblock-peek-char (ioblock)
+  (or (ioblock-untyi-char ioblock)
+      (let* ((ch (funcall (ioblock-read-char-when-locked-function ioblock) ioblock)))
+        (unless (eq ch :eof)
+          (setf (ioblock-untyi-char ioblock) ch))
+        ch)))
+
+
+
+
+(defun %ioblock-clear-input (ioblock)    
+    (let* ((buf (ioblock-inbuf ioblock)))
+      (setf (io-buffer-count buf) 0
+	    (io-buffer-idx buf) 0
+	    (ioblock-untyi-char ioblock) nil)))
+
+(defun %ioblock-untyi (ioblock char)
+  (if (ioblock-untyi-char ioblock)
+    (error "Two UNREAD-CHARs without intervening READ-CHAR on ~s"
+	   (ioblock-stream ioblock))
+    (setf (ioblock-untyi-char ioblock) char)))
+
+(declaim (inline ioblock-inpos))
+
+(defun ioblock-inpos (ioblock)
+  (io-buffer-idx (ioblock-inbuf ioblock)))
+
+(declaim (inline ioblock-outpos))
+
+(defun ioblock-outpos (ioblock)
+  (io-buffer-count (ioblock-outbuf ioblock)))
+
+
+
+(declaim (inline %ioblock-force-output))
+
+(defun %ioblock-force-output (ioblock finish-p)
+  (funcall (ioblock-force-output-function ioblock)
+           (ioblock-stream ioblock)
+           ioblock
+           (ioblock-outpos ioblock)
+           finish-p))
+
+;;; ivector should be an ivector.  The ioblock should have an
+;;; element-shift of 0; start-octet and num-octets should of course
+;;; be sane.  This is mostly to give the fasdumper a quick way to
+;;; write immediate data.
+(defun %ioblock-out-ivect (ioblock ivector start-octet num-octets)
+  (unless (= 0 (the fixnum (ioblock-element-shift ioblock)))
+    (error "Can't write vector to stream ~s" (ioblock-stream ioblock)))
+  (let* ((written 0)
+	 (out (ioblock-outbuf ioblock))
+	 (bufsize (io-buffer-size out))
+	 (buffer (io-buffer-buffer out)))
+    (declare (fixnum written bufsize))
+    (do* ((pos start-octet (+ pos written))
+	  (left num-octets (- left written)))
+	 ((= left 0) num-octets)
+      (declare (fixnum pos left))
+      (setf (ioblock-dirty ioblock) t)
+      (let* ((index (io-buffer-idx out))
+	     (count (io-buffer-count out))
+	     (avail (- bufsize index)))
+	(declare (fixnum index avail count))
+	(cond
+	  ((= (setq written avail) 0)
+	   (%ioblock-force-output ioblock nil))
+	  (t
+	   (if (> written left)
+	     (setq written left))
+	   (%copy-ivector-to-ivector ivector pos buffer index written)
+	   (setf (ioblock-dirty ioblock) t)
+	   (incf index written)
+	   (if (> index count)
+	     (setf (io-buffer-count out) index))
+	   (setf (io-buffer-idx out) index)
+	   (if (= index  bufsize)
+	     (%ioblock-force-output ioblock nil))))))))
+
+
+(defun %ioblock-unencoded-write-simple-string (ioblock string start-char num-chars)
+  (declare (fixnum start-char num-chars) (simple-string string))
+  (let* ((written 0)
+	 (col (ioblock-charpos ioblock))
+	 (out (ioblock-outbuf ioblock))
+	 (bufsize (io-buffer-size out))
+	 (buffer (io-buffer-buffer out)))
+    (declare (fixnum written bufsize col)
+	     (type (simple-array (unsigned-byte 8) (*)) buffer)
+	     (optimize (speed 3) (safety 0)))
+    (do* ((pos start-char (+ pos written))
+	  (left num-chars (- left written)))
+	 ((= left 0) (setf (ioblock-charpos ioblock) col)  num-chars)
+      (declare (fixnum pos left))
+      (setf (ioblock-dirty ioblock) t)
+      (let* ((index (io-buffer-idx out))
+	     (count (io-buffer-count out))
+	     (avail (- bufsize index)))
+	(declare (fixnum index avail count))
+	(cond
+	  ((= (setq written avail) 0)
+	   (%ioblock-force-output ioblock nil))
+	  (t
+	   (if (> written left)
+	     (setq written left))
+	   (do* ((p pos (1+ p))
+		 (i index (1+ i))
+		 (j 0 (1+ j)))
+		((= j written))
+	     (declare (fixnum p i j))
+	     (let* ((ch (schar string p))
+                    (code (char-code ch)))
+               (declare (type (mod #x110000) code))
+	       (if (eql ch #\newline)
+		 (setq col 0)
+		 (incf col))
+	       (setf (aref buffer i) (if (>= code 256) (char-code #\Sub) code))))
+	   (setf (ioblock-dirty ioblock) t)
+	   (incf index written)
+	   (if (> index count)
+	     (setf (io-buffer-count out) index))
+	   (setf (io-buffer-idx out) index)
+	   (if (= index  bufsize)
+	     (%ioblock-force-output ioblock nil))))))))
+
+
+
+(defun %ioblock-eofp (ioblock)
+  (let* ((buf (ioblock-inbuf ioblock)))
+   (and (eql (io-buffer-idx buf)
+             (io-buffer-count buf))
+         (locally (declare (optimize (speed 3) (safety 0)))
+           (with-ioblock-input-locked (ioblock)
+             (funcall (ioblock-eofp-function ioblock)
+		      (ioblock-stream ioblock)
+		      ioblock))))))
+
+(defun %ioblock-listen (ioblock)
+  (let* ((buf (ioblock-inbuf ioblock)))
+    (or (< (the fixnum (io-buffer-idx buf))
+           (the fixnum (io-buffer-count buf)))
+	(funcall (ioblock-listen-function ioblock)
+		 (ioblock-stream ioblock)
+		 ioblock))))
+
+(declaim (inline %ioblock-write-element))
+
+(defun %ioblock-write-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (io-buffer-buffer buf) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-u8-element))
+(defun %ioblock-write-u8-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (unsigned-byte 8) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-s8-element))
+(defun %ioblock-write-s8-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (signed-byte 8) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-u16-element))
+(defun %ioblock-write-u16-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (unsigned-byte 16) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-u16-code-unit))
+(defun %ioblock-write-u16-code-unit (ioblock element)
+  (declare (optimize (speed 3) (safety 0))
+           (type (unsigned-byte 16) element))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf))
+         (vector (io-buffer-buffer buf))
+         (b0 #+big-endian-target (ldb (byte 8 8) element)
+             #+little-endian-target (ldb (byte 8 0) element))
+         (b1 #+big-endian-target (ldb (byte 8 0) element)
+             #+little-endian-target (ldb (byte 8 8) element)))
+    (declare (fixnum idx limit count)
+             (type (simple-array (unsigned-byte 8) (*)) vector)
+             (type (unsigned-byte 8) b0 b1))
+   
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b0)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b1)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-swapped-u16-code-unit))
+(defun %ioblock-write-swapped-u16-code-unit (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+(let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf))
+         (vector (io-buffer-buffer buf))
+         (b0 #+big-endian-target (ldb (byte 8 8) element)
+             #+little-endian-target (ldb (byte 8 0) element))
+         (b1 #+big-endian-target (ldb (byte 8 0) element)
+             #+little-endian-target (ldb (byte 8 8) element)))
+    (declare (fixnum idx limit count)
+             (type (simple-array (unsigned-byte 8) (*)) vector)
+             (type (unsigned-byte 8) b0 b1))
+   
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b1)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b0)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-u32-code-unit))
+(defun %ioblock-write-u32-code-unit (ioblock element)
+  (declare (optimize (speed 3) (safety 0))
+           (type (unsigned-byte 16) element))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf))
+         (vector (io-buffer-buffer buf))
+         (b0 #+big-endian-target (ldb (byte 8 24) element)
+             #+little-endian-target (ldb (byte 8 0) element))
+         (b1 #+big-endian-target (ldb (byte 8 16) element)
+             #+little-endian-target (ldb (byte 8 8) element))
+         (b2 #+big-endian-target (ldb (byte 8 8) element)
+             #+little-endian-target (ldb (byte 8 16) element))
+         (b3 #+big-endian-target (ldb (byte 8 0) element)
+             #+little-endian-target (ldb (byte 8 24) element)))
+    (declare (fixnum idx limit count)
+             (type (simple-array (unsigned-byte 8) (*)) vector)
+             (type (unsigned-byte 8) b0 b1 b2 b3))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b0)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b1)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b2)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b3)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-swapped-u32-code-unit))
+(defun %ioblock-write-swapped-u32-code-unit (ioblock element)
+  (declare (optimize (speed 3) (safety 0))
+           (type (unsigned-byte 16) element))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf))
+         (vector (io-buffer-buffer buf))
+         (b0 #+little-endian-target (ldb (byte 8 24) element)
+             #+big-endian-target (ldb (byte 8 0) element))
+         (b1 #+little-endian-target (ldb (byte 8 16) element)
+             #+big-endian-target (ldb (byte 8 8) element))
+         (b2 #+little-endian-target (ldb (byte 8 8) element)
+             #+big-endian-target (ldb (byte 8 16) element))
+         (b3 #+little-endian-target (ldb (byte 8 0) element)
+             #+big-endian-target (ldb (byte 8 24) element)))
+    (declare (fixnum idx limit count)
+             (type (simple-array (unsigned-byte 8) (*)) vector)
+             (type (unsigned-byte 8) b0 b1 b2 b3))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b0)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b1)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b2)
+    (incf idx)
+    (when (= idx limit)
+      (when (> idx count)
+        (setf (io-buffer-count buf) idx))
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref vector idx) b3)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-s16-element))
+(defun %ioblock-write-s16-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (signed-byte 16) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-u32-element))
+(defun %ioblock-write-u32-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (unsigned-byte 32) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-swapped-u32-element))
+(defun %ioblock-write-swapped-u32-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (unsigned-byte 32) (*)) (io-buffer-buffer buf)) idx)
+          (%swap-u32 element))
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-s32-element))
+(defun %ioblock-write-s32-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (signed-byte 32) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+#+64-bit-target
+(progn
+(declaim (inline %ioblock-write-u64-element))
+(defun %ioblock-write-u64-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (unsigned-byte 64) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+
+(declaim (inline %ioblock-write-s64-element))
+(defun %ioblock-write-s64-element (ioblock element)
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((buf (ioblock-outbuf ioblock))
+         (idx (io-buffer-idx buf))
+	 (count (io-buffer-count buf))
+         (limit (io-buffer-limit buf)))
+    (declare (fixnum idx limit count))
+    (when (= idx limit)
+      (%ioblock-force-output ioblock nil)
+      (setq idx 0 count 0))
+    (setf (aref (the (simple-array (signed-byte 64) (*)) (io-buffer-buffer buf)) idx) element)
+    (incf idx)
+    (setf (io-buffer-idx buf) idx)
+    (when (> idx count)
+      (setf (io-buffer-count buf) idx))
+    (setf (ioblock-dirty ioblock) t)
+    element))
+)
+
+(declaim (inline %ioblock-write-char))
+(defun %ioblock-write-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (eq char #\linefeed)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (if (< code 256)
+      (%ioblock-write-u8-element ioblock code)
+      (%ioblock-write-u8-element ioblock (char-code #\Sub)))))
+
+(defun %private-ioblock-write-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-char ioblock char))
+
+(defun %locked-ioblock-write-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-char ioblock char)))
+
+(declaim (inline %ioblock-write-u8-encoded-char))
+(defun %ioblock-write-u8-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (eq char #\linefeed)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (if (< code (the fixnum (ioblock-encode-literal-char-code-limit ioblock)))
+      (%ioblock-write-u8-element ioblock code)
+      (funcall (ioblock-encode-output-function ioblock)
+               char
+               #'%ioblock-write-u8-element
+               ioblock))))
+
+(defun %private-ioblock-write-u8-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-u8-encoded-char ioblock char))
+
+(defun %locked-ioblock-write-u8-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock) 
+    (%ioblock-write-u8-encoded-char ioblock char)))
+
+
+(defun %ioblock-write-u8-encoded-simple-string (ioblock string start-char num-chars)
+  (declare (fixnum start-char num-chars)
+           (simple-base-string string)
+           (optimize (speed 3) (safety 0)))
+  (do* ((i 0 (1+ i))
+        (col (ioblock-charpos ioblock))
+        (limit (ioblock-encode-literal-char-code-limit ioblock))
+        (encode-function (ioblock-encode-output-function ioblock))
+        (start-char start-char (1+ start-char)))
+       ((= i num-chars) (setf (ioblock-charpos ioblock) col) num-chars)
+    (declare (fixnum i start-char limit))
+    (let* ((char (schar string start-char))
+           (code (char-code char)))
+      (declare (type (mod #x110000) code))
+      (if (eq char #\newline)
+        (setq col 0)
+        (incf col))
+      (if (< code limit)
+        (%ioblock-write-u8-element ioblock code)
+        (funcall encode-function char #'%ioblock-write-u8-element ioblock)))))
+
+
+(declaim (inline %ioblock-write-u16-encoded-char))
+(defun %ioblock-write-u16-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (when (ioblock-pending-byte-order-mark ioblock)
+    (setf (ioblock-pending-byte-order-mark ioblock) nil)
+    (%ioblock-write-u16-code-unit ioblock byte-order-mark-char-code))
+  (if (eq char #\linefeed)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (if (< code (the fixnum (ioblock-encode-literal-char-code-limit ioblock)))
+      (%ioblock-write-u16-code-unit ioblock code)
+      (funcall (ioblock-encode-output-function ioblock)
+               char
+               #'%ioblock-write-u16-code-unit
+               ioblock))))
+
+(defun %private-ioblock-write-u16-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-u16-encoded-char ioblock char))
+
+(defun %locked-ioblock-write-u16-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-u16-encoded-char ioblock char)))
+
+
+(defun %ioblock-write-u16-encoded-simple-string (ioblock string start-char num-chars)
+  (declare (fixnum start-char num-chars)
+           (simple-base-string string)
+           (optimize (speed 3) (safety 0)))
+  (when (ioblock-pending-byte-order-mark ioblock)
+    (setf (ioblock-pending-byte-order-mark ioblock) nil)
+    (%ioblock-write-u16-code-unit ioblock byte-order-mark-char-code))
+  (do* ((i 0 (1+ i))
+        (col (ioblock-charpos ioblock))
+        (limit (ioblock-encode-literal-char-code-limit ioblock))
+        (encode-function (ioblock-encode-output-function ioblock))
+        (start-char start-char (1+ start-char)))
+       ((= i num-chars) (setf (ioblock-charpos ioblock) col) num-chars)
+    (declare (fixnum i start-char limit))
+    (let* ((char (schar string start-char))
+           (code (char-code char)))
+      (declare (type (mod #x110000) code))
+      (if (eq char #\newline)
+        (setq col 0)
+        (incf col))
+      (if (< code limit)
+        (%ioblock-write-u16-code-unit ioblock code)
+        (funcall encode-function char #'%ioblock-write-u16-code-unit ioblock)))))
+
+(declaim (inline %ioblock-write-swapped-u16-encoded-char))
+(defun %ioblock-write-swapped-u16-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (eq char #\linefeed)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (if (< code (the fixnum (ioblock-encode-literal-char-code-limit ioblock)))
+      (%ioblock-write-swapped-u16-code-unit ioblock code)
+      (funcall (ioblock-encode-output-function ioblock)
+               char
+               #'%ioblock-write-swapped-u16-code-unit
+               ioblock))))
+
+(defun %private-ioblock-write-swapped-u16-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-swapped-u16-encoded-char ioblock char))
+
+(defun %locked-ioblock-write-swapped-u16-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-swapped-u16-encoded-char ioblock char)))
+
+(defun %ioblock-write-swapped-u16-encoded-simple-string (ioblock string start-char num-chars)
+  (declare (fixnum start-char num-chars)
+           (simple-base-string string)
+           (optimize (speed 3) (safety 0)))
+  (do* ((i 0 (1+ i))
+        (col (ioblock-charpos ioblock))
+        (limit (ioblock-encode-literal-char-code-limit ioblock))
+        (encode-function (ioblock-encode-output-function ioblock))
+        (wcf (ioblock-write-char-when-locked-function ioblock))
+        (start-char start-char (1+ start-char)))
+       ((= i num-chars) (setf (ioblock-charpos ioblock) col) num-chars)
+    (declare (fixnum i start-char limit))
+    (let* ((char (schar string start-char))
+           (code (char-code char)))
+      (declare (type (mod #x110000) code))
+      (cond ((eq char #\newline)
+             (setq col 0)
+             (funcall wcf ioblock char))
+            (t
+             (incf col)
+             (if (< code limit)
+               (%ioblock-write-swapped-u16-code-unit ioblock code)
+               (funcall encode-function char #'%ioblock-write-swapped-u16-code-unit ioblock)))))))
+
+
+(declaim (inline %ioblock-write-u32-encoded-char))
+(defun %ioblock-write-u32-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (when (ioblock-pending-byte-order-mark ioblock)
+    (setf (ioblock-pending-byte-order-mark ioblock) nil)
+    (%ioblock-write-u32-code-unit ioblock byte-order-mark))
+  (if (eq char #\linefeed)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (if (< code (the fixnum (ioblock-encode-literal-char-code-limit ioblock)))
+      (%ioblock-write-u32-code-unit ioblock code)
+      (funcall (ioblock-encode-output-function ioblock)
+               code
+               #'%ioblock-write-u32-code-unit
+               ioblock))))
+
+(defun %private-ioblock-write-u32-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-u32-encoded-char ioblock char))
+
+(defun %locked-ioblock-write-u32-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))  
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-u32-encoded-char ioblock char)))
+
+(defun %ioblock-write-u32-encoded-simple-string (ioblock string start-char num-chars)
+  (declare (fixnum start-char num-chars)
+           (simple-base-string string)
+           (optimize (speed 3) (safety 0)))
+  (when (ioblock-pending-byte-order-mark ioblock)
+    (setf (ioblock-pending-byte-order-mark ioblock) nil)
+    (%ioblock-write-u32-code-unit ioblock byte-order-mark-char-code))
+  (do* ((i 0 (1+ i))
+        (col (ioblock-charpos ioblock))
+        (limit (ioblock-encode-literal-char-code-limit ioblock))
+        (encode-function (ioblock-encode-output-function ioblock))
+        (start-char start-char (1+ start-char)))
+       ((= i num-chars) (setf (ioblock-charpos ioblock) col) num-chars)
+    (declare (fixnum i start-char limit))
+    (let* ((char (schar string start-char))
+           (code (char-code char)))
+      (declare (type (mod #x110000) code))
+      (if (eq char #\newline)
+        (setq col 0)
+        (incf col))
+      (if (< code limit)
+        (%ioblock-write-u32-code-unit ioblock code)
+        (funcall encode-function char #'%ioblock-write-u32-code-unit ioblock)))))
+
+
+(declaim (inline %ioblock-write-swapped-u32-encoded-char))
+(defun %ioblock-write-swapped-u32-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (if (eq char #\linefeed)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (if (< code (the fixnum (ioblock-encode-literal-char-code-limit ioblock)))
+      (%ioblock-write-swapped-u32-code-unit ioblock code)
+      (funcall (ioblock-encode-output-function ioblock)
+               code
+               #'%ioblock-write-swapped-u32-code-unit
+               ioblock))))
+
+(defun %private-ioblock-write-swapped-u32-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-swapped-u32-encoded-char ioblock char))
+
+(defun %locked-ioblock-write-swapped-u32-encoded-char (ioblock char)
+  (declare (optimize (speed 3) (safety 0)))  
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-swapped-u32-encoded-char ioblock char)))
+
+(defun %ioblock-write-swapped-u32-encoded-simple-string (ioblock string start-char num-chars)
+  (declare (fixnum start-char num-chars)
+           (simple-base-string string)
+           (optimize (speed 3) (safety 0)))
+  (do* ((i 0 (1+ i))
+        (col (ioblock-charpos ioblock))
+        (limit (ioblock-encode-literal-char-code-limit ioblock))
+        (encode-function (ioblock-encode-output-function ioblock))
+        (start-char start-char (1+ start-char)))
+       ((= i num-chars) (setf (ioblock-charpos ioblock) col) num-chars)
+    (declare (fixnum i start-char limit))
+    (let* ((char (schar string start-char))
+           (code (char-code char)))
+      (declare (type (mod #x110000) code))
+      (if (eq char #\newline)
+        (setq col 0)
+        (incf col))
+      (if (< code limit)
+        (%ioblock-write-swapped-u32-code-unit ioblock code)
+        (funcall encode-function char #'%ioblock-write-swapped-u32-code-unit ioblock)))))
+
+(declaim (inline %ioblock-write-u8-byte))
+(defun %ioblock-write-u8-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-u8-element ioblock (require-type byte '(unsigned-byte 8))))
+
+(defun %private-ioblock-write-u8-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-u8-byte ioblock byte))
+
+(defun %locked-ioblock-write-u8-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-u8-byte ioblock byte)))
+
+(declaim (inline %ioblock-write-s8-byte))
+(defun %ioblock-write-s8-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-s8-element ioblock (require-type byte '(signed-byte 8))))
+
+(defun %private-ioblock-write-s8-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-s8-byte ioblock byte))
+
+(defun %locked-ioblock-write-s8-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-s8-byte ioblock byte)))
+
+(declaim (inline %ioblock-write-u16-byte))
+(defun %ioblock-write-u16-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-u16-element ioblock (require-type byte '(unsigned-byte 16))))
+
+(defun %private-ioblock-write-u16-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-u16-byte ioblock byte))
+
+(defun %locked-ioblock-write-u16-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-u16-byte ioblock byte)))
+
+(declaim (inline %ioblock-write-s16-byte))
+(defun %ioblock-write-s16-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-s16-element ioblock (require-type byte '(signed-byte 16))))
+
+(defun %private-ioblock-write-s16-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-s16-byte ioblock byte))
+
+(defun %locked-ioblock-write-s16-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-s16-byte ioblock byte)))
+
+(declaim (inline %ioblock-write-u32-byte))
+(defun %ioblock-write-u32-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-u32-element ioblock (require-type byte '(unsigned-byte 32))))
+
+(defun %private-ioblock-write-u32-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-u32-byte ioblock byte))
+
+(defun %locked-ioblock-write-u32-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-u32-byte ioblock byte)))
+
+(declaim (inline %ioblock-write-s32-byte))
+(defun %ioblock-write-s32-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-s32-element ioblock (require-type byte '(signed-byte 32))))
+
+(defun %private-ioblock-write-s32-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-s32-byte ioblock byte))
+
+(defun %locked-ioblock-write-s32-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-s32-byte ioblock byte)))
+
+#+64-bit-target
+(progn
+(declaim (inline %ioblock-write-u64-byte))
+(defun %ioblock-write-u64-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-u64-element ioblock (require-type byte '(unsigned-byte 64))))
+
+(defun %private-ioblock-write-u64-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-u64-byte ioblock byte))
+
+(defun %locked-ioblock-write-u64-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-u64-byte ioblock byte)))
+
+(declaim (inline %ioblock-write-s64-byte))
+(defun %ioblock-write-s64-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (%ioblock-write-s64-element ioblock (require-type byte '(signed-byte 64))))
+
+(defun %private-ioblock-write-s64-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-s64-byte ioblock byte))
+
+(defun %locked-ioblock-write-s64-byte (ioblock byte)
+  (declare (optimize (speed 3) (safety 0)))
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-s64-byte ioblock byte)))
+)                                       ;#+64-bit-target
+
+(defun %ioblock-clear-output (ioblock)
+  (let* ((buf (ioblock-outbuf ioblock)))                      
+    (setf (io-buffer-count buf) 0
+            (io-buffer-idx buf) 0)))
+
+(defun %ioblock-unencoded-read-line (ioblock)
+  (let* ((inbuf (ioblock-inbuf ioblock)))
+    (let* ((string "")
+           (len 0)
+           (eof nil)
+           (buf (io-buffer-buffer inbuf))
+           (newline (char-code #\newline)))
+      (let* ((ch (ioblock-untyi-char ioblock)))
+        (when ch
+          (setf (ioblock-untyi-char ioblock) nil)
+          (if (eql ch #\newline)
+            (return-from %ioblock-unencoded-read-line 
+              (values string nil))
+            (progn
+              (setq string (make-string 1)
+                    len 1)
+              (setf (schar string 0) ch)))))
+      (loop
+        (let* ((more 0)
+               (idx (io-buffer-idx inbuf))
+               (count (io-buffer-count inbuf)))
+          (declare (fixnum idx count more))
+          (if (= idx count)
+            (if eof
+              (return (values string t))
+              (progn
+                (setq eof t)
+                (%ioblock-advance ioblock t)))
+            (progn
+              (setq eof nil)
+              (let* ((pos (position newline buf :start idx :end count)))
+                (when pos
+                  (locally (declare (fixnum pos))
+                    (setf (io-buffer-idx inbuf) (the fixnum (1+ pos)))
+                    (setq more (- pos idx))
+                    (unless (zerop more)
+                      (setq string
+                            (%extend-vector
+                             0 string (the fixnum (+ len more)))))
+                    (%copy-u8-to-string
+                     buf idx string len more)
+                    (return (values string nil))))
+                ;; No #\newline in the buffer.  Read everything that's
+                ;; there into the string, and fill the buffer again.
+                (setf (io-buffer-idx inbuf) count)
+                (setq more (- count idx)
+                      string (%extend-vector
+                              0 string (the fixnum (+ len more))))
+                (%copy-u8-to-string
+                 buf idx string len more)
+                (incf len more)))))))))
+
+;;; There are lots of ways of doing better here, but in the most general
+;;; case we can't tell (a) what a newline looks like in the buffer or (b)
+;;; whether there's a 1:1 mapping between code units and characters.
+(defun %ioblock-encoded-read-line (ioblock)
+  (let* ((str (make-array 20 :element-type 'base-char
+			  :adjustable t :fill-pointer 0))
+         (rcf (ioblock-read-char-when-locked-function ioblock))
+	 (eof nil))
+    (do* ((ch (funcall rcf ioblock) (funcall rcf ioblock)))
+	 ((or (eq ch #\newline) (setq eof (eq ch :eof)))
+	  (values (ensure-simple-string str) eof))
+      (vector-push-extend ch str))))
+	 
+(defun %ioblock-unencoded-character-read-vector (ioblock vector start end)
+  (do* ((i start)
+        (in (ioblock-inbuf ioblock))
+        (inbuf (io-buffer-buffer in))
+        (need (- end start)))
+       ((= i end) end)
+    (declare (fixnum i need))
+    (let* ((ch (%ioblock-tyi ioblock)))
+      (if (eq ch :eof)
+        (return i))
+      (setf (schar vector i) ch)
+      (incf i)
+      (decf need)
+      (let* ((idx (io-buffer-idx in))
+             (count (io-buffer-count in))
+             (avail (- count idx)))
+        (declare (fixnum idx count avail))
+        (unless (zerop avail)
+          (if (> avail need)
+            (setq avail need))
+          (%copy-u8-to-string inbuf idx vector i avail)
+          (setf (io-buffer-idx in) (+ idx avail))
+          (incf i avail)
+          (decf need avail))))))
+
+;;; Also used when newline translation complicates things.
+(defun %ioblock-encoded-character-read-vector (ioblock vector start end)
+  (declare (fixnum start end))
+  (do* ((i start (1+ i))
+        (rcf (ioblock-read-char-when-locked-function ioblock)))
+       ((= i end) end)
+    (declare (fixnum i))
+    (let* ((ch (funcall rcf ioblock)))
+      (if (eq ch :eof)
+	(return i))
+      (setf (schar vector i) ch))))
+
+
+(defun %ioblock-binary-read-vector (ioblock vector start end)
+  (declare (fixnum start end))
+  (let* ((in (ioblock-inbuf ioblock))
+	 (inbuf (io-buffer-buffer in))
+         (rbf (ioblock-read-byte-when-locked-function ioblock)))
+    (setf (ioblock-untyi-char ioblock) nil)
+    (if (not (= (the fixnum (typecode inbuf))
+		(the fixnum (typecode vector))))
+      (do* ((i start (1+ i)))
+	   ((= i end) i)
+	(declare (fixnum i))
+	(let* ((b (funcall rbf ioblock)))
+	  (if (eq b :eof)
+	    (return i)
+	    (setf (uvref vector i) b))))
+      (do* ((i start)
+	    (need (- end start)))
+	   ((= i end) end)
+	(declare (fixnum i need))
+	(let* ((b (funcall rbf ioblock)))
+	  (if (eq b :eof)
+	    (return i))
+	  (setf (uvref vector i) b)
+	  (incf i)
+	  (decf need)
+	  (let* ((idx (io-buffer-idx in))
+		 (count (io-buffer-count in))
+		 (avail (- count idx)))
+	    (declare (fixnum idx count avail))
+	    (unless (zerop avail)
+	      (if (> avail need)
+		(setq avail need))
+	      (%copy-ivector-to-ivector
+	       inbuf
+	       (ioblock-elements-to-octets ioblock idx)
+	       vector
+	       (ioblock-elements-to-octets ioblock i)
+	       (ioblock-elements-to-octets ioblock avail))
+	      (setf (io-buffer-idx in) (+ idx avail))
+	      (incf i avail)
+	      (decf need avail))))))))
+
+;;; About the same, only less fussy about ivector's element-type.
+;;; (All fussiness is about the stream's element-type ...).
+;;; Whatever the element-type is, elements must be 1 octet in size.
+(defun %ioblock-character-in-ivect (ioblock vector start nb)
+  (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+	   (fixnum start nb)
+	   (optimize (speed 3) (safety 0)))
+  (unless (= 0 (the fixnum (ioblock-element-shift ioblock)))
+    (error "Can't read vector from stream ~s" (ioblock-stream ioblock)))
+  (do* ((i start)
+	(in (ioblock-inbuf ioblock))
+	(inbuf (io-buffer-buffer in))
+	(need nb)
+	(end (+ start nb)))
+       ((= i end) end)
+    (declare (fixnum i end need))
+    (let* ((ch (%ioblock-tyi ioblock)))
+      (if (eq ch :eof)
+	(return (- i start)))
+      (setf (aref vector i) (char-code ch))
+      (incf i)
+      (decf need)
+      (let* ((idx (io-buffer-idx in))
+	     (count (io-buffer-count in))
+	     (avail (- count idx)))
+	(declare (fixnum idx count avail))
+	(unless (zerop avail)
+	  (if (> avail need)
+	    (setq avail need))
+          (%copy-u8-to-string inbuf idx vector i avail)
+	  (setf (io-buffer-idx in) (+ idx avail))
+	  (incf i avail)
+	  (decf need avail))))))
+
+(defun %ioblock-binary-in-ivect (ioblock vector start nb)
+  (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+	   (fixnum start nb)
+	   (optimize (speed 3) (safety 0)))
+  (unless (= 0 (the fixnum (ioblock-element-shift ioblock)))
+    (error "Can't read vector from stream ~s" (ioblock-stream ioblock)))
+  (setf (ioblock-untyi-char ioblock) nil)
+  (do* ((i start)
+        (rbf (ioblock-read-byte-when-locked-function ioblock))
+	(in (ioblock-inbuf ioblock))
+	(inbuf (io-buffer-buffer in))
+	(need nb)
+	(end (+ start nb)))
+       ((= i end) nb)
+    (declare (fixnum i end need))
+    (let* ((b (funcall rbf ioblock)))
+      (if (eq b :eof)
+	(return (- i start)))
+      (setf (uvref vector i) b)
+      (incf i)
+      (decf need)
+      (let* ((idx (io-buffer-idx in))
+	     (count (io-buffer-count in))
+	     (avail (- count idx)))
+	(declare (fixnum idx count avail))
+	(unless (zerop avail)
+	  (if (> avail need)
+	    (setq avail need))
+	  (%copy-ivector-to-ivector inbuf idx vector i avail)
+	  (setf (io-buffer-idx in) (+ idx avail))
+	  (incf i avail)
+	  (decf need avail))))))
+
+;;; Thread must own ioblock lock(s).
+(defun %%ioblock-close (ioblock)
+  (when (ioblock-device ioblock)
+    (let* ((stream (ioblock-stream ioblock)))
+      (funcall (ioblock-close-function ioblock) stream ioblock)
+      (setf (ioblock-device ioblock) nil)
+      (setf (stream-ioblock stream) nil)
+      (let* ((in-iobuf (ioblock-inbuf ioblock))
+             (out-iobuf (ioblock-outbuf ioblock))
+             (in-buffer (if in-iobuf (io-buffer-buffer in-iobuf)))
+             (in-bufptr (if in-iobuf (io-buffer-bufptr in-iobuf)))
+             (out-buffer (if out-iobuf (io-buffer-buffer out-iobuf)))
+             (out-bufptr (if out-iobuf (io-buffer-bufptr out-iobuf))))
+        (if (and in-buffer in-bufptr)
+          (%dispose-heap-ivector in-buffer))
+        (unless (eq in-buffer out-buffer)
+          (if (and out-buffer out-bufptr)
+            (%dispose-heap-ivector out-buffer)))
+        (when in-iobuf
+          (setf (io-buffer-buffer in-iobuf) nil
+                (io-buffer-bufptr in-iobuf) nil
+                (ioblock-inbuf ioblock) nil))
+        (when out-iobuf
+          (setf (io-buffer-buffer out-iobuf) nil
+                (io-buffer-bufptr out-iobuf) nil
+                (ioblock-outbuf ioblock) nil))
+        t))))
+
+(defun %ioblock-close (ioblock)
+  (let* ((in-lock (ioblock-inbuf-lock ioblock))
+         (out-lock (ioblock-outbuf-lock ioblock)))
+    (if in-lock
+      (with-lock-grabbed (in-lock)
+        (if (and out-lock (not (eq out-lock in-lock)))
+          (with-lock-grabbed (out-lock)
+            (%%ioblock-close ioblock))
+          (%%ioblock-close ioblock)))
+      (if out-lock
+        (with-lock-grabbed (out-lock)
+          (%%ioblock-close ioblock))
+        (progn
+          (check-ioblock-owner ioblock)
+          (%%ioblock-close ioblock))))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Character-at-a-time line-termination-translation functions.
+;;; It's not always possible to just blast through the buffer, blindly
+;;; replacing #xd with #xa (for example), and it's not always desirable
+;;; to do that (if we support changing encoding on open streams.)
+;;; This is done at a fairly high level; some cases could be done at
+;;; a lower level, and some cases are hard even at that lower level.
+;;; This approach doesn't slow down the simple case (when no line-termination
+;;; translation is used), and hopefully isn't -that- bad.
+
+(declaim (inline %ioblock-read-char-translating-cr-to-newline))
+(defun %ioblock-read-char-translating-cr-to-newline (ioblock)
+  (let* ((ch (funcall
+              (ioblock-read-char-without-translation-when-locked-function
+               ioblock)
+              ioblock)))
+    (if (eql ch #\Return)
+      #\Newline
+      ch)))
+
+(defun %private-ioblock-read-char-translating-cr-to-newline (ioblock)
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-char-translating-cr-to-newline ioblock))
+
+(defun %locked-ioblock-read-char-translating-cr-to-newline (ioblock)
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-char-translating-cr-to-newline ioblock)))
+
+(declaim (inline %ioblock-read-char-translating-crlf-to-newline))
+(defun %ioblock-read-char-translating-crlf-to-newline (ioblock)
+  (let* ((ch (funcall
+              (ioblock-read-char-without-translation-when-locked-function
+               ioblock)
+              ioblock)))
+    (if (eql ch #\Return)
+      (let* ((next (funcall
+                    (ioblock-read-char-without-translation-when-locked-function
+                     ioblock)
+                    ioblock)))
+        (if (eql next #\Linefeed)
+          next
+          (progn
+            (unless (eq next :eof)
+              (setf (ioblock-untyi-char ioblock) next))
+            ch)))
+      ch)))
+    
+(defun %private-ioblock-read-char-translating-crlf-to-newline (ioblock)
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-char-translating-crlf-to-newline ioblock))
+
+(defun %locked-ioblock-read-char-translating-crlf-to-newline (ioblock)
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-char-translating-crlf-to-newline ioblock)))
+
+(declaim (inline %ioblock-read-char-translating-line-separator-to-newline))
+(defun %ioblock-read-char-translating-line-separator-to-newline (ioblock)
+  (let* ((ch (funcall
+              (ioblock-read-char-without-translation-when-locked-function
+               ioblock)
+              ioblock)))
+    (if (eql ch #\Line_Separator)
+      #\Newline
+      ch)))
+
+(defun %private-ioblock-read-char-translating-line-separator-to-newline (ioblock)
+  (check-ioblock-owner ioblock)
+  (%ioblock-read-char-translating-line-separator-to-newline ioblock))
+
+(defun %locked-ioblock-read-char-translating-line-separator-to-newline (ioblock)
+  (with-ioblock-input-lock-grabbed (ioblock)
+    (%ioblock-read-char-translating-line-separator-to-newline ioblock)))
+
+(declaim (inline %ioblock-write-char-translating-newline-to-cr))
+(defun %ioblock-write-char-translating-newline-to-cr (ioblock char)
+  (funcall (ioblock-write-char-without-translation-when-locked-function
+            ioblock)
+           ioblock
+           (if (eql char #\Newline) #\Return char)))
+
+(defun %private-ioblock-write-char-translating-newline-to-cr (ioblock char)
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-char-translating-newline-to-cr ioblock char))
+
+(defun %locked-ioblock-write-char-translating-newline-to-cr (ioblock char)
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-char-translating-newline-to-cr ioblock char)))
+
+(declaim (inline %ioblock-write-char-translating-newline-to-crlf))
+(defun %ioblock-write-char-translating-newline-to-crlf (ioblock char)
+  (when (eql char #\Newline)
+    (funcall (ioblock-write-char-without-translation-when-locked-function
+              ioblock)
+             ioblock
+             #\Return))    
+  (funcall (ioblock-write-char-without-translation-when-locked-function
+            ioblock)
+           ioblock
+           char))
+
+(defun %private-ioblock-write-char-translating-newline-to-crlf (ioblock char)
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-char-translating-newline-to-crlf ioblock char))
+
+(defun %locked-ioblock-write-char-translating-newline-to-crlf (ioblock char)
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-char-translating-newline-to-crlf ioblock char)))
+
+(declaim (inline %ioblock-write-char-translating-newline-to-line-separator))
+(defun %ioblock-write-char-translating-newline-to-line-separator (ioblock char)
+  (funcall (ioblock-write-char-without-translation-when-locked-function
+            ioblock)
+           ioblock
+           (if (eql char #\Newline) #\Line_Separator char)))
+
+(defun %private-ioblock-write-char-translating-newline-to-line-separator (ioblock char)
+  (check-ioblock-owner ioblock)
+  (%ioblock-write-char-translating-newline-to-line-separator ioblock char))
+
+(defun %locked-ioblock-write-char-translating-newline-to-line-separator (ioblock char)
+  (with-ioblock-output-lock-grabbed (ioblock)
+    (%ioblock-write-char-translating-newline-to-line-separator ioblock char)))
+
+;;; If we do newline translation, we probably can't be too clever about reading/writing
+;;; strings.
+(defun %ioblock-write-simple-string-with-newline-translation (ioblock string start-pos num-chars)
+  (declare (fixnum start-pos num-chars) (simple-string string))
+  (let* ((col (ioblock-charpos ioblock))
+         (wcf (ioblock-write-char-when-locked-function ioblock)))
+    (declare (fixnum col))
+    (do* ((i start-pos (1+ i))
+          (n 0 (1+ n)))
+         ((= n num-chars) (setf (ioblock-charpos ioblock) col) num-chars)
+      (let* ((char (schar string i)))
+        (if (eql char #\Newline)
+          (setq col 0)
+          (incf col))
+        (funcall wcf ioblock char)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun setup-ioblock-input (ioblock character-p element-type sharing encoding line-termination)
+  (setf (ioblock-sharing ioblock) sharing)
+  (when character-p
+    (setf (ioblock-unread-char-function ioblock) (select-stream-untyi-function (ioblock-stream ioblock) :input))
+    (setf (ioblock-decode-literal-code-unit-limit ioblock)
+          (if encoding
+            (character-encoding-decode-literal-code-unit-limit encoding)
+            256))    
+    (if encoding
+      (let* ((unit-size (character-encoding-code-unit-size encoding)))
+        (setf (ioblock-peek-char-function ioblock) '%encoded-ioblock-peek-char)
+        (setf (ioblock-read-line-function ioblock)
+              '%ioblock-encoded-read-line)
+        (setf (ioblock-character-read-vector-function ioblock)
+              '%ioblock-encoded-character-read-vector)        
+        (setf (ioblock-decode-input-function ioblock)
+              (character-encoding-stream-decode-function encoding))
+        (setf (ioblock-read-char-function ioblock)
+              (ecase unit-size
+                (8
+                 (setf (ioblock-read-char-when-locked-function ioblock)
+                       '%ioblock-read-u8-encoded-char)
+                 (case sharing
+                   (:private '%private-ioblock-read-u8-encoded-char)
+                   (:lock '%locked-ioblock-read-u8-encoded-char)
+                   (t '%ioblock-read-u8-encoded-char)))
+                (16
+                 (if (character-encoding-native-endianness encoding)
+                   (progn
+                    (setf (ioblock-read-char-when-locked-function ioblock)
+                          '%ioblock-read-u16-encoded-char)
+                    (case sharing
+                      (:private '%private-ioblock-read-u16-encoded-char)
+                      (:lock '%locked-ioblock-read-u16-encoded-char)
+                      (t '%ioblock-read-u16-encoded-char)))
+                   (progn
+                     (setf (ioblock-read-char-when-locked-function ioblock)
+                           '%ioblock-read-swapped-u16-encoded-char)
+                    (case sharing
+                      (:private '%private-ioblock-read-swapped-u16-encoded-char)
+                      (:lock '%locked-ioblock-read-swapped-u16-encoded-char)
+                      (t '%ioblock-read-swapped-u16-encoded-char)))))
+                (32
+                 (if (character-encoding-native-endianness encoding)
+                   (progn
+                    (setf (ioblock-read-char-when-locked-function ioblock)
+                          #'%ioblock-read-u32-encoded-char)
+                    (case sharing
+                      (:private #'%private-ioblock-read-u32-encoded-char)
+                      (:lock #'%locked-ioblock-read-u32-encoded-char)
+                      (t #'%ioblock-read-u32-encoded-char)))
+                   (progn
+                     (setf (ioblock-read-char-when-locked-function ioblock)
+                           #'%ioblock-read-swapped-u32-encoded-char)
+                    (case sharing
+                      (:private '#'%private-ioblock-read-swapped-u16-encoded-char)
+                      (:lock #'%locked-ioblock-read-swapped-u32-encoded-char)
+                      (t #'%ioblock-read-swapped-u32-encoded-char))))))))
+      (progn
+        (setf (ioblock-peek-char-function ioblock) '%ioblock-peek-char)
+        (setf (ioblock-read-char-function ioblock)
+              (case sharing
+                (:private '%private-ioblock-tyi)
+                (:lock '%locked-ioblock-tyi)
+                (t '%ioblock-tyi)))
+        (setf (ioblock-read-char-when-locked-function ioblock)
+              '%ioblock-tyi)
+        (setf (ioblock-character-read-vector-function ioblock)
+              '%ioblock-unencoded-character-read-vector)
+        (setf (ioblock-read-line-function ioblock)
+              '%ioblock-unencoded-read-line)))
+    (when line-termination
+      (install-ioblock-input-line-termination ioblock line-termination))
+    )
+
+  (unless (or (eq element-type 'character)
+              (subtypep element-type 'character))
+    (let* ((subtag (element-type-subtype element-type)))
+      (declare (type (unsigned-byte 8) subtag))
+      (setf (ioblock-read-byte-function ioblock)
+            (cond ((= subtag target::subtag-u8-vector)
+                   (if character-p
+                     ;; The bivalent case, at least for now
+                     (progn
+                       (setf (ioblock-read-byte-when-locked-function ioblock)
+                             '%bivalent-ioblock-read-u8-byte)
+                       (case sharing
+                         (:private '%bivalent-private-ioblock-read-u8-byte)
+                         (:lock '%bivalent-locked-ioblock-read-u8-byte)
+                         (t '%bivalent-ioblock-read-u8-byte)))
+                     (progn
+                       (setf (ioblock-read-byte-when-locked-function ioblock)
+                             '%ioblock-read-u8-byte)
+                       (case sharing
+                         (:private '%private-ioblock-read-u8-byte)
+                         (:lock '%locked-ioblock-read-u8-byte)
+                         (t '%ioblock-read-u8-byte)))))
+                  ((= subtag target::subtag-s8-vector)
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%ioblock-read-s8-byte) 
+                   (case sharing
+                     (:private '%private-ioblock-read-s8-byte)
+                     (:lock '%locked-ioblock-read-s8-byte)
+                     (t '%ioblock-read-s8-byte)))
+                  ((= subtag target::subtag-u16-vector)
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%ioblock-read-u16-byte)
+                   (case sharing
+                     (:private '%private-ioblock-read-u16-byte)
+                     (:lock '%locked-ioblock-read-u16-byte)
+                     (t '%ioblock-read-u16-byte)))
+                  ((= subtag target::subtag-s16-vector)
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%ioblock-read-s16-byte)
+                   (case sharing
+                     (:private '%private-ioblock-read-s16-byte)
+                     (:lock '%locked-ioblock-read-s16-byte)
+                     (t '%ioblock-read-s16-byte)))
+                  ((= subtag target::subtag-u32-vector)
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%ioblock-read-u32-byte)
+                   (case sharing
+                     (:private '%private-ioblock-read-u32-byte)
+                     (:lock '%locked-ioblock-read-u32-byte)
+                     (t '%ioblock-read-u32-byte)))
+                  ((= subtag target::subtag-s32-vector)
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%ioblock-read-s32-byte)                   
+                   (case sharing
+                     (:private '%private-ioblock-read-s32-byte)
+                     (:lock '%locked-ioblock-read-s32-byte)
+                     (t '%ioblock-read-s32-byte)))
+                  #+64-bit-target
+                  ((= subtag target::subtag-u64-vector)
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%ioblock-read-u64-byte)                   
+                   (case sharing
+                     (:private '%private-ioblock-read-u64-byte)
+                     (:lock '%locked-ioblock-read-u64-byte)
+                     (t '%ioblock-read-u64-byte)))
+                  #+64-bit-target
+                  ((= subtag target::subtag-s64-vector)
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%ioblock-read-s64-byte)
+                   (case sharing
+                     (:private '%private-ioblock-read-s64-byte)
+                     (:lock '%locked-ioblock-read-s64-byte)
+                     (t '%ioblock-read-s64-byte)))
+                  ;; Not sure what this means, currently.
+                  (t
+                   (setf (ioblock-read-byte-when-locked-function ioblock)
+                         '%general-ioblock-read-byte)
+                   '%general-ioblock-read-byte))))))
+
+(defun install-ioblock-input-line-termination (ioblock line-termination)
+  (when line-termination
+    (let* ((sharing (ioblock-sharing ioblock)))
+      (setf (ioblock-read-char-without-translation-when-locked-function ioblock)
+            (ioblock-read-char-when-locked-function ioblock)
+            (ioblock-character-read-vector-function ioblock)
+            '%ioblock-encoded-character-read-vector
+            (ioblock-read-line-function ioblock) '%ioblock-encoded-read-line)
+      (ecase line-termination
+        (:cr (setf (ioblock-read-char-when-locked-function ioblock)
+                   '%ioblock-read-char-translating-cr-to-newline
+                   (ioblock-read-char-function ioblock)
+                   (case sharing
+                     (:private
+                      '%private-ioblock-read-char-translating-cr-to-newline)
+                     (:lock
+                      '%locked-ioblock-read-char-translating-cr-to-newline)
+                     (t '%ioblock-read-char-translating-cr-to-newline))))
+        (:crlf (setf (ioblock-read-char-when-locked-function ioblock)
+                     '%ioblock-read-char-translating-crlf-to-newline
+                     (ioblock-read-char-function ioblock)
+                     (case sharing
+                       (:private
+                        '%private-ioblock-read-char-translating-crlf-to-newline)
+                       (:lock
+                        '%locked-ioblock-read-char-translating-crlf-to-newline)
+                       (t '%ioblock-read-char-translating-crlf-to-newline))))
+        (:unicode (setf (ioblock-read-char-when-locked-function ioblock)
+                        '%ioblock-read-char-translating-line-separator-to-newline
+                        (ioblock-read-char-function ioblock)
+                        (case sharing
+                          (:private
+                           '%private-ioblock-read-char-translating-line-separator-to-newline)
+                          (:lock
+                           '%locked-ioblock-read-char-translating-line-separator-to-newline)
+                          (t '%ioblock-read-char-translating-line-separator-to-newline)))))
+      (setf (ioblock-line-termination ioblock) line-termination))))
+  
+(defun setup-ioblock-output (ioblock character-p element-type sharing encoding line-termination)
+  (or (ioblock-sharing ioblock)
+      (setf (ioblock-sharing ioblock) sharing))
+  (when character-p
+    (setf (ioblock-encode-literal-char-code-limit ioblock)
+          (if encoding
+            (character-encoding-encode-literal-char-code-limit encoding)
+            256))    
+    (if encoding
+      (let* ((unit-size (character-encoding-code-unit-size encoding)))
+        (setf (ioblock-encode-output-function ioblock)
+              (character-encoding-stream-encode-function encoding))
+        (setf (ioblock-write-char-function ioblock)
+              (ecase unit-size
+                (8
+                 (setf (ioblock-write-char-when-locked-function ioblock)
+                       '%ioblock-write-u8-encoded-char) 
+                 (case sharing
+                   (:private '%private-ioblock-write-u8-encoded-char)
+                   (:lock '%locked-ioblock-write-u8-encoded-char)
+                   (t '%ioblock-write-u8-encoded-char)))
+                (16
+                 (if (character-encoding-native-endianness encoding)
+                   (progn
+                     (setf (ioblock-write-char-when-locked-function ioblock)
+                           '%ioblock-write-u16-encoded-char) 
+                     (case sharing
+                       (:private '%private-ioblock-write-u16-encoded-char)
+                       (:lock '%locked-ioblock-write-u16-encoded-char)
+                       (t '%ioblock-write-u16-encoded-char)))
+                   (progn
+                     (setf (ioblock-write-char-when-locked-function ioblock)
+                           '%ioblock-write-swapped-u16-encoded-char)
+                     (case sharing
+                       (:private '%private-ioblock-write-swapped-u16-encoded-char)
+                       (:lock '%locked-ioblock-write-swapped-u16-encoded-char)
+                       (t '%ioblock-write-swapped-u16-encoded-char)))))
+                (32
+                 (if (character-encoding-native-endianness encoding)
+                   (progn
+                     (setf (ioblock-write-char-when-locked-function ioblock)
+                           #'%ioblock-write-u32-encoded-char) 
+                     (case sharing
+                       (:private #'%private-ioblock-write-u32-encoded-char)
+                       (:lock #'%locked-ioblock-write-u32-encoded-char)
+                       (t #'%ioblock-write-u32-encoded-char)))
+                   (progn
+                     (setf (ioblock-write-char-when-locked-function ioblock)
+                           #'%ioblock-write-swapped-u32-encoded-char)
+                     (case sharing
+                       (:private #'%private-ioblock-write-swapped-u32-encoded-char)
+                       (:lock #'%locked-ioblock-write-swapped-u32-encoded-char)
+                       (t #'%ioblock-write-swapped-u32-encoded-char)))))))
+        (setf (ioblock-write-simple-string-function ioblock)
+              (ecase unit-size
+                (8 '%ioblock-write-u8-encoded-simple-string)
+                (16
+                 (if (character-encoding-native-endianness encoding)
+                   '%ioblock-write-u16-encoded-simple-string
+                   '%ioblock-write-swapped-u16-encoded-simple-string))
+                (32
+                 (if (character-encoding-native-endianness encoding)
+                   #'%ioblock-write-u32-encoded-simple-string
+                   #'%ioblock-write-swapped-u32-encoded-simple-string))))
+        (when (character-encoding-use-byte-order-mark encoding)
+          (setf (ioblock-pending-byte-order-mark ioblock) t)))
+      (progn
+        (setf (ioblock-write-simple-string-function ioblock)
+              '%ioblock-unencoded-write-simple-string)
+        (setf (ioblock-write-char-when-locked-function ioblock)
+              '%ioblock-write-char)
+        (setf (ioblock-write-char-function ioblock)
+              (case sharing
+                (:private '%private-ioblock-write-char)
+                (:lock '%locked-ioblock-write-char)
+                (t '%ioblock-write-char)))))
+    (when line-termination
+      (install-ioblock-output-line-termination ioblock line-termination)))
+  (unless (or (eq element-type 'character)
+              (subtypep element-type 'character))
+    (let* ((subtag (element-type-subtype element-type)))
+      (declare (type (unsigned-byte 8) subtag))
+      (setf (ioblock-write-byte-function ioblock)
+            (cond ((= subtag target::subtag-u8-vector)
+                   (progn
+                     (setf (ioblock-write-byte-when-locked-function ioblock)
+                           '%ioblock-write-u8-byte)
+                     (case sharing
+                       (:private '%private-ioblock-write-u8-byte)
+                       (:lock '%locked-ioblock-write-u8-byte)
+                       (t '%ioblock-write-u8-byte))))
+                  ((= subtag target::subtag-s8-vector)
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%ioblock-write-s8-byte)                   
+                   (case sharing
+                     (:private '%private-ioblock-write-s8-byte)
+                     (:lock '%locked-ioblock-write-s8-byte)
+                     (t '%ioblock-write-s8-byte)))
+                  ((= subtag target::subtag-u16-vector)
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%ioblock-write-u16-byte)                   
+                   (case sharing
+                     (:private '%private-ioblock-write-u16-byte)
+                     (:lock '%locked-ioblock-write-u16-byte)
+                     (t '%ioblock-write-u16-byte)))
+                  ((= subtag target::subtag-s16-vector)
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%ioblock-write-s16-byte)                                      
+                   (case sharing
+                     (:private '%private-ioblock-write-s16-byte)
+                     (:lock '%locked-ioblock-write-s16-byte)
+                     (t '%ioblock-write-s16-byte)))
+                  ((= subtag target::subtag-u32-vector)
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%ioblock-write-u32-byte)                                      
+                   (case sharing
+                     (:private '%private-ioblock-write-u32-byte)
+                     (:lock '%locked-ioblock-write-u32-byte)
+                     (t '%ioblock-write-u32-byte)))
+                  ((= subtag target::subtag-s32-vector)
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%ioblock-write-s32-byte)
+                   (case sharing
+                     (:private '%private-ioblock-write-s32-byte)
+                     (:lock '%locked-ioblock-write-s32-byte)
+                     (t '%ioblock-write-s32-byte)))
+                  #+64-bit-target
+                  ((= subtag target::subtag-u64-vector)
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%ioblock-write-u64-byte)
+                   (case sharing
+                     (:private '%private-ioblock-write-u64-byte)
+                     (:lock '%locked-ioblock-write-u64-byte)
+                     (t '%ioblock-write-u64-byte)))
+                  #+64-bit-target
+                  ((= subtag target::subtag-s64-vector)
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%ioblock-write-u64-byte)
+                   (case sharing
+                     (:private '%private-ioblock-write-s64-byte)
+                     (:lock '%locked-ioblock-write-s64-byte)
+                     (t '%ioblock-write-s64-byte)))
+                  (t
+                   (setf (ioblock-write-byte-when-locked-function ioblock)
+                         '%general-ioblock-write-byte)                   
+                   '%general-ioblock-write-byte))))))
+
+(defun install-ioblock-output-line-termination (ioblock line-termination)
+  (let* ((sharing (ioblock-sharing ioblock)))
+        (when line-termination
+      (setf (ioblock-write-char-without-translation-when-locked-function ioblock)
+            (ioblock-write-char-when-locked-function ioblock)
+            (ioblock-write-simple-string-function ioblock)
+            '%ioblock-write-simple-string-with-newline-translation)
+      (ecase line-termination
+        (:cr (setf (ioblock-write-char-when-locked-function ioblock)
+                   '%ioblock-write-char-translating-newline-to-cr
+                   (ioblock-read-char-function ioblock)
+                   (case sharing
+                     (:private
+                      '%private-ioblock-write-char-translating-newline-to-cr)
+                     (:lock
+                      '%locked-ioblock-write-char-translating-newline-to-cr)
+                     (t '%ioblock-write-char-translating-newline-to-cr))))
+        (:crlf (setf (ioblock-write-char-when-locked-function ioblock)
+                     '%ioblock-write-char-translating-newline-to-crlf
+                     (ioblock-write-char-function ioblock)
+                     (case sharing
+                       (:private
+                        '%private-ioblock-write-char-translating-newline-to-crlf)
+                       (:lock
+                        '%locked-ioblock-write-char-translating-newline-to-crlf)
+                       (t '%ioblock-write-char-translating-newline-to-crlf))))
+        (:unicode (setf (ioblock-write-char-when-locked-function ioblock)
+                        '%ioblock-write-char-translating-newline-to-line-separator
+                        (ioblock-write-char-function ioblock)
+                        (case sharing
+                          (:private
+                           '%private-ioblock-write-char-translating-newline-to-line-separator)
+                          (:lock
+                           '%locked-ioblock-write-char-translating-newline-to-line-separator)
+                          (t '%ioblock-write-char-translating-newline-to-line-separator)))))
+      (setf (ioblock-line-termination ioblock) line-termination))))
+
+
+(defun ensure-reasonable-element-type (element-type)
+  (let* ((upgraded (upgraded-array-element-type element-type)))
+    (if (eq upgraded 'bit)
+      '(unsigned-byte 8)
+      (if (eq upgraded 'fixnum)
+        #+64-bit-target '(signed-byte 64) #+32-bit-target '(signed-byte 32)
+        (if (eq upgraded t)
+          (error "Stream element-type ~s can't be reasonably supported." element-type)
+          upgraded)))))
+
+(defun init-stream-ioblock (stream
+                            &key
+                            insize      ; integer to allocate inbuf here, nil
+                                        ; otherwise
+                            outsize     ; integer to allocate outbuf here, nil
+                                        ; otherwise
+                            share-buffers-p ; true if input and output
+                                        ; share a buffer
+                            element-type
+                            device
+                            advance-function
+                            listen-function
+                            eofp-function
+                            force-output-function
+                            close-function
+                            element-shift
+                            interactive
+                            (sharing :private)
+                            character-p
+                            encoding
+                            line-termination
+                            input-timeout
+                            output-timeout
+                            deadline
+                            &allow-other-keys)
+  (declare (ignorable element-shift))
+  (setq line-termination (cdr (assoc line-termination *canonical-line-termination-conventions*)))
+  (when encoding
+    (unless (typep encoding 'character-encoding)
+      (setq encoding (get-character-encoding encoding)))
+    (if (eq encoding (get-character-encoding nil))
+      (setq encoding nil)))
+  (when sharing
+    (unless (or (eq sharing :private)
+                (eq sharing :lock))
+      (if (eq sharing :external)
+        (setq sharing nil)
+        (report-bad-arg sharing '(member nil :private :lock :external)))))
+  (let* ((ioblock (or (let* ((ioblock (stream-ioblock stream nil)))
+                        (when ioblock
+                          (setf (ioblock-stream ioblock) stream)
+                          ioblock))
+                      (stream-create-ioblock stream))))
+    (when (eq sharing :private)
+      (setf (ioblock-owner ioblock) 0))
+    (setf (ioblock-encoding ioblock) encoding)
+    (when insize
+      (unless (ioblock-inbuf ioblock)
+        (multiple-value-bind (buffer ptr in-size-in-octets)
+            (make-heap-ivector insize
+                               (if character-p
+                                 '(unsigned-byte 8)
+                                 (setq element-type
+                                       (ensure-reasonable-element-type element-type))))
+          (setf (ioblock-inbuf ioblock)
+                (make-io-buffer :buffer buffer
+                                :bufptr ptr
+                                :size in-size-in-octets
+                                :limit insize))
+          (when (eq sharing :lock)
+            (setf (ioblock-inbuf-lock ioblock) (make-lock)))
+          (setf (ioblock-line-termination ioblock) line-termination)
+          (setup-ioblock-input ioblock character-p element-type sharing encoding line-termination)
+          (setf (ioblock-element-shift ioblock) (max 0 (ceiling (log  (/ in-size-in-octets insize) 2))))
+          )))
+    (if share-buffers-p
+      (if insize
+        (progn (setf (ioblock-outbuf ioblock)
+                     (ioblock-inbuf ioblock))
+               (setf (ioblock-outbuf-lock ioblock)
+                     (ioblock-inbuf-lock ioblock)))
+        (error "Can't share buffers unless insize is non-zero and non-null"))
+      (when outsize
+        (unless (ioblock-outbuf ioblock)
+          (multiple-value-bind (buffer ptr out-size-in-octets)
+              (make-heap-ivector outsize
+                                 (if character-p
+                                   '(unsigned-byte 8)
+                                   (setq element-type (ensure-reasonable-element-type element-type))))
+            (setf (ioblock-outbuf ioblock)
+                  (make-io-buffer :buffer buffer
+                                  :bufptr ptr
+                                  :count 0
+                                  :limit outsize
+                                  :size out-size-in-octets))
+            (when (eq sharing :lock)
+              (setf (ioblock-outbuf-lock ioblock) (make-lock)))
+            (setf (ioblock-element-shift ioblock) (max 0 (ceiling (log (/ out-size-in-octets outsize) 2))))
+            ))))
+    (when (or share-buffers-p outsize)
+      (setup-ioblock-output ioblock character-p element-type sharing encoding line-termination))
+    (when element-type
+      (setf (ioblock-element-type ioblock) (if character-p 'character element-type)))
+;    (when element-shift
+;      (setf (ioblock-element-shift ioblock) element-shift))
+    (when device
+      (setf (ioblock-device ioblock) device))
+    (when advance-function
+      (setf (ioblock-advance-function ioblock) advance-function))
+    (when listen-function
+      (setf (ioblock-listen-function ioblock) listen-function))
+    (when eofp-function
+      (setf (ioblock-eofp-function ioblock) eofp-function))
+    (when force-output-function
+      (setf (ioblock-force-output-function ioblock) force-output-function))
+    (when close-function
+      (setf (ioblock-close-function ioblock) close-function))
+    (when interactive
+      (setf (ioblock-interactive ioblock) interactive))
+    (setf (stream-ioblock stream) ioblock)
+    (when encoding
+      (setf (ioblock-native-byte-order ioblock)
+            (character-encoding-native-endianness encoding)))
+    (let* ((bom-info (and insize encoding (character-encoding-use-byte-order-mark encoding))))
+      (when bom-info
+        (ioblock-check-input-bom ioblock bom-info sharing)))
+    (setf (ioblock-input-timeout ioblock) input-timeout)
+    (setf (ioblock-output-timeout ioblock) output-timeout)
+    (setf (ioblock-deadline ioblock) deadline)
+    ioblock))
+
+;;; If there's a byte-order-mark (or a reversed byte-order-mark) at
+;;; the beginning of the input stream, deal with it.  If there's any
+;;; input present, make sure that we don't write a BOM on output.  If
+;;; this is a little-endian machine, input data was present, and there
+;;; was no BOM in that data, make things big-endian.  If there's a
+;;; leading BOM or swapped BOM, eat it (consume it so that it doesn't
+;;; ordinarily appear as input.)
+;;;
+(defun ioblock-check-input-bom (ioblock swapped-encoding-name sharing)
+  (let* ((n (%ioblock-advance ioblock nil))) ; try to read, don't block
+    (when n
+      (setf (ioblock-pending-byte-order-mark ioblock) nil)
+      (let* ((inbuf (ioblock-inbuf ioblock))
+             (unit-size (character-encoding-code-unit-size (ioblock-encoding ioblock)))
+             (min (ash unit-size -3))
+             (buf (io-buffer-buffer inbuf))
+             (swapped-encoding
+              (and
+               (>= n min)
+               (case (case unit-size
+                       (16 (%native-u8-ref-u16 buf 0))
+                       (32 (%native-u8-ref-u32 buf 0)))
+                 (#.byte-order-mark-char-code
+                  (setf (io-buffer-idx inbuf) min)
+                  nil)
+                 (#.swapped-byte-order-mark-char-code
+                  (setf (io-buffer-idx inbuf) min)
+                  t)
+                 (t #+little-endian-target t))
+               (lookup-character-encoding swapped-encoding-name))))
+        (when swapped-encoding
+          (let* ((output-p (not (null (ioblock-outbuf ioblock)))))
+            (setf (ioblock-native-byte-order ioblock)
+                  (character-encoding-native-endianness swapped-encoding))
+            (ecase unit-size
+              (16
+               (setf (ioblock-read-char-when-locked-function ioblock)
+                     '%ioblock-read-swapped-u16-encoded-char)
+               (case sharing
+                 (:private '%private-ioblock-read-swapped-u16-encoded-char)
+                 (:lock '%locked-ioblock-read-swapped-u16-encoded-char)
+                 (t '%ioblock-read-swapped-u16-encoded-char)))
+              (32
+               (setf (ioblock-read-char-when-locked-function ioblock)
+                     '%ioblock-read-swapped-u32-encoded-char)
+               (case sharing
+                 (:private '%private-ioblock-read-swapped-u32-encoded-char)
+                 (:lock '%locked-ioblock-read-swapped-u32-encoded-char)
+                 (t '%ioblock-read-swapped-u16-encoded-char))))
+            (when output-p
+              (ecase unit-size
+                (16
+                 (setf (ioblock-write-char-when-locked-function ioblock)
+                       '%ioblock-write-swapped-u16-encoded-char)
+                 (case sharing
+                   (:private '%private-ioblock-write-swapped-u16-encoded-char)
+                   (:lock '%locked-ioblock-write-swapped-u16-encoded-char)
+                   (t '%ioblock-write-swapped-u16-encoded-char))
+                 (setf (ioblock-write-simple-string-function ioblock)
+                       '%ioblock-write-swapped-u16-encoded-simple-string))
+                (32
+                 (setf (ioblock-write-char-when-locked-function ioblock)
+                       '%ioblock-write-swapped-u32-encoded-char)
+                 (case sharing
+                   (:private '%private-ioblock-write-swapped-u32-encoded-char)
+                   (:lock '%locked-ioblock-write-swapped-u32-encoded-char)
+                   (t '%ioblock-write-swapped-u32-encoded-char))
+                 (setf (ioblock-write-simple-string-function ioblock)
+                       '%ioblock-write-swapped-u32-encoded-simple-string))))))))))
+
+
+
+;;; We can't define a MAKE-INSTANCE method on STRUCTURE-CLASS subclasses
+;;; in MCL; of course, calling the structure-class's constructor does
+;;; much the same thing (but note that MCL only keeps track of the
+;;; default, automatically generated constructor.)
+;;; (As fascinating as that may be, that has nothing to do with any
+;;; nearby code, though it may have once been relevant.)
+(defun make-ioblock-stream (class
+			    &rest initargs
+			    &key 
+			    &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (let* ((s
+          (if (subtypep class 'basic-stream)
+            (apply #'make-basic-stream-instance class :allow-other-keys t initargs)
+            (apply #'make-instance class :allow-other-keys t initargs))))
+    (apply #'init-stream-ioblock s initargs)
+    s))
+
+
+
+
+
+(defmethod select-stream-class ((s symbol) in-p out-p char-p)
+  (select-stream-class (class-prototype (find-class s)) in-p out-p char-p))
+
+(defmethod select-stream-class ((s structure-class) in-p out-p char-p)
+  (select-stream-class (class-prototype s) in-p out-p char-p))
+
+(defmethod select-stream-class ((s standard-class) in-p out-p char-p)
+  (select-stream-class (class-prototype s) in-p out-p char-p))
+
+
+(defparameter *canonical-line-termination-conventions*
+  '((:unix . nil)
+    (:macos . :cr)
+    (:cr . :cr)
+    (:crlf . :crlf)
+    (:cp/m . :crlf)
+    (:msdos . :crlf)
+    (:dos . :crlf)
+    (:windows . :crlf)
+    (:inferred . nil)
+    (:unicode . :unicode)))
+
+
+(defun optimal-buffer-size (fd element-type)
+  #+windows-target (declare (ignore fd))
+  (let* (#-windows-target (nominal (or (nth-value 6 (%fstat fd)) *elements-per-buffer*))
+         (octets #+windows-target #$BUFSIZ
+                 #-windows-target
+                 (case (%unix-fd-kind fd)
+                   (:pipe (#_fpathconf fd #$_PC_PIPE_BUF))
+                   (:socket
+                    #+linux-target nominal
+                    #-linux-target
+                    (int-getsockopt fd #$SOL_SOCKET
+                                    #+solaris-target #$SO_SNDBUF
+                                    #-solaris-target #$SO_SNDLOWAT))
+                   ((:character-special :tty) (#_fpathconf fd #$_PC_MAX_INPUT))
+                   (t nominal))))
+    (case (subtag-bytes (element-type-subtype element-type) 1)
+      (1 octets)
+      (2 (ash octets -1))
+      (4 (ash octets -2))
+      (8 (ash octets -3)))))
+
+
+
+
+
+(defun milliseconds-until-deadline (deadline ioblock)
+  (let* ((now (get-internal-real-time)))
+    (if (> now deadline)
+      (error 'communication-deadline-expired :stream (ioblock-stream ioblock))
+      (values (round (- deadline now) (/ internal-time-units-per-second 1000))))))
+
+
+;;; Note that we can get "bivalent" streams by specifiying :character-p t
+;;; with a reasonable element-type (e.g. (UNSIGNED-BYTE 8))
+(defun make-fd-stream (fd &key
+			  (direction :input)
+			  (interactive t)
+			  (element-type 'character)
+			  (class 'fd-stream)
+                          (sharing :private)
+                          (character-p (or (eq element-type 'character)
+                                           (subtypep element-type 'character)))
+                          (basic nil)
+                          encoding
+                          line-termination
+                          auto-close
+                          input-timeout
+                          output-timeout
+                          deadline)
+  (let* ((elements-per-buffer (optimal-buffer-size fd element-type)))
+    (when line-termination
+      (setq line-termination
+            (cdr (assoc line-termination *canonical-line-termination-conventions*))))
+    (when basic
+      (setq class (map-to-basic-stream-class-name class))
+      (setq basic (subtypep (find-class class) 'basic-stream)))
+    (let* ((in-p (member direction '(:io :input)))
+           (out-p (member direction '(:io :output)))
+           (class-name (select-stream-class class in-p out-p character-p))
+           (class (find-class class-name))
+           (stream
+            (make-ioblock-stream class
+                                 :insize (if in-p elements-per-buffer)
+                                 :outsize (if out-p elements-per-buffer)
+                                 :device fd
+                                 :interactive interactive
+                                 :element-type element-type
+                                 :advance-function (if in-p
+                                                     (select-stream-advance-function class direction))
+                                 :listen-function (if in-p 'fd-stream-listen)
+                                 :eofp-function (if in-p 'fd-stream-eofp)
+                                 :force-output-function (if out-p
+                                                          (select-stream-force-output-function class direction))
+                                 :close-function 'fd-stream-close
+                                 :sharing sharing
+                                 :character-p character-p
+                                 :encoding encoding
+                                 :line-termination line-termination
+                                 :input-timeout input-timeout
+                                 :output-timeout output-timeout
+                                 :deadline deadline)))
+      (if auto-close
+        (terminate-when-unreachable stream
+                                    (lambda (stream)
+                                      (close-for-termination stream t))))
+      stream)))
+
+  
+;;;  Fundamental streams.
+
+(defclass fundamental-stream (stream)
+    ())
+
+(defclass fundamental-input-stream (fundamental-stream input-stream)
+    ((shared-resource :initform nil :accessor input-stream-shared-resource)))
+
+(defclass fundamental-output-stream (fundamental-stream output-stream)
+    ())
+
+(defmethod input-stream-p ((x t))
+  (report-bad-arg x 'stream))
+			   
+(defmethod input-stream-p ((s input-stream))
+  t)
+
+(defmethod output-stream-p ((x t))
+  (report-bad-arg x 'stream))
+
+(defmethod output-stream-p ((s input-stream))
+  (typep s 'output-stream))
+
+(defmethod output-stream-p ((s output-stream))
+  t)
+
+(defmethod input-stream-p ((s output-stream))
+  (typep s 'input-stream))
+
+(defclass binary-stream (stream)
+    ())
+
+(defclass character-stream (stream)
+    ())
+
+(defmethod stream-external-format ((s character-stream))
+  (make-external-format :character-encoding #+big-endian-target :utf-32be #+little-endian-target :utf-32le :line-termination :unix))
+
+
+(defmethod (setf stream-external-format) (new (s character-stream))
+  (check-type new external-format)
+  (stream-external-format s))
+
+
+(defclass fundamental-character-stream (fundamental-stream character-stream)
+    ())
+
+(defmethod stream-element-type ((s fundamental-character-stream))
+  'character)
+
+(defclass fundamental-binary-stream (fundamental-stream binary-stream)
+    ())
+
+(defclass character-input-stream (input-stream character-stream)
+    ())
+
+(defclass fundamental-character-input-stream (fundamental-input-stream
+                                              fundamental-character-stream
+                                              character-input-stream)
+    ())
+
+(defmethod stream-read-char-no-hang ((s fundamental-character-input-stream))
+  (stream-read-char s))
+
+(defmethod stream-peek-char ((s fundamental-character-input-stream))
+  (let* ((ch (stream-read-char s)))
+    (unless (eq ch :eof)
+      (stream-unread-char s ch))
+    ch))
+
+(defmethod stream-listen ((s fundamental-character-input-stream))
+  (let* ((ch (stream-read-char-no-hang s)))
+    (when (and ch (not (eq ch :eof)))
+      (stream-unread-char s ch))
+    ch))
+
+(defmethod stream-clear-input ((s fundamental-character-input-stream))
+  )
+
+(defmethod stream-read-line ((s character-input-stream))
+  (generic-read-line s))
+
+(defclass character-output-stream (output-stream character-stream)
+    ())
+
+(defclass fundamental-character-output-stream (fundamental-output-stream
+                                               fundamental-character-stream
+                                               character-output-stream)
+    ())
+
+(defclass binary-input-stream (input-stream binary-stream)
+    ())
+
+(defclass fundamental-binary-input-stream (fundamental-input-stream
+                                           fundamental-binary-stream
+                                           binary-input-stream)
+    ())
+
+(defclass binary-output-stream (output-stream binary-stream)
+    ())
+
+(defclass fundamental-binary-output-stream (fundamental-output-stream
+                                            fundamental-binary-stream
+                                            binary-output-stream)
+    ())
+
+
+
+(defmethod stream-read-byte ((s t))
+  (report-bad-arg s '(and input-stream binary-stream)))
+
+(defmethod stream-write-byte ((s t) b)
+  (declare (ignore b))
+  (report-bad-arg s '(and output-stream binary-stream)))
+
+(defmethod stream-length ((s stream) &optional new)
+  (declare (ignore new)))
+
+(defmethod stream-start-line-p ((s character-output-stream))
+  (eql 0 (stream-line-column s)))
+
+(defmethod stream-terpri ((s character-output-stream))
+  (stream-write-char s #\Newline))
+
+(defmethod stream-fresh-line ((s character-output-stream))
+  (unless (stream-start-line-p s)
+    (stream-terpri s)
+    t))
+
+;;; The bad news is that this doesn't even bother to do the obvious
+;;; (calling STREAM-WRITE-STRING with a longish string of spaces.)
+;;; The good news is that this method is pretty useless to (format "~T" ...)
+;;; anyhow.
+(defmethod stream-advance-to-column ((s fundamental-character-output-stream)
+				     col)
+  (generic-advance-to-column s col))
+
+(defmethod stream-write-string ((stream fundamental-character-output-stream) string &optional (start 0) end)
+  (generic-stream-write-string stream string start end))
+
+
+;;; The read-/write-vector methods could be specialized for stream classes
+;;; that expose the underlying buffering mechanism.
+;;; They can assume that the 'vector' argument is a simple one-dimensional
+;;; array and that the 'start' and 'end' arguments are sane.
+
+(defmethod stream-write-vector ((stream character-output-stream)
+				vector start end)
+  (declare (fixnum start end))
+  (do* ((i start (1+ i)))
+       ((= i end))
+    (declare (fixnum i))
+    (write-char (uvref vector i) stream)))
+
+(defmethod stream-write-vector ((stream binary-output-stream)
+				vector start end)
+  (declare (fixnum start end))
+  (do* ((i start (1+ i)))
+       ((= i end))
+    (declare (fixnum i))
+    (write-byte (uvref vector i) stream)))
+
+(defmethod stream-read-vector ((stream character-input-stream)
+			       vector start end)
+  (generic-character-read-vector stream vector start end))
+
+
+(defmethod stream-read-vector ((stream binary-input-stream)
+			       vector start end)
+  (declare (fixnum start end))
+  (do* ((i start (1+ i)))
+       ((= i end) end)
+    (declare (fixnum i))
+    (let* ((b (read-byte stream nil :eof)))
+      (if (eq b :eof)
+	(return i)
+	(setf (uvref vector i) b)))))
+
+
+
+
+
+;;; File streams, in the abstract.
+
+(defclass file-stream (stream)
+    ())
+
+(defmethod stream-domain ((s file-stream))
+  :file)
+
+
+
+
+;;; "Basic" (non-extensible) streams.
+
+
+(declaim (inline basic-stream-p))
+
+(defun basic-stream-p (x)
+  (= (the fixnum (typecode x)) target::subtag-basic-stream))
+
+(setf (type-predicate 'basic-stream) 'basic-stream-p)
+
+(make-built-in-class 'basic-stream 'stream)
+(make-built-in-class 'basic-file-stream 'basic-stream 'file-stream)
+(make-built-in-class 'basic-character-stream 'basic-stream 'character-stream)
+(make-built-in-class 'basic-binary-stream 'basic-stream 'binary-stream)
+
+(make-built-in-class 'basic-input-stream 'basic-stream 'input-stream)
+(make-built-in-class 'basic-output-stream 'basic-stream 'output-stream)
+(make-built-in-class 'basic-io-stream 'basic-input-stream 'basic-output-stream)
+(make-built-in-class 'basic-character-input-stream 'basic-input-stream 'basic-character-stream 'character-input-stream)
+(make-built-in-class 'basic-character-output-stream 'basic-output-stream 'basic-character-stream 'character-output-stream)
+(make-built-in-class 'basic-character-io-stream 'basic-character-input-stream 'basic-character-output-stream)
+(make-built-in-class 'basic-binary-input-stream 'basic-input-stream 'basic-binary-stream 'binary-input-stream)
+(make-built-in-class 'basic-binary-output-stream 'basic-output-stream 'basic-binary-stream 'binary-output-stream)
+(make-built-in-class 'basic-binary-io-stream 'basic-binary-input-stream 'basic-binary-output-stream)
+
+
+(defun %ioblock-external-format (ioblock)
+  (let* ((encoding (or (ioblock-encoding ioblock)
+                       (get-character-encoding nil)))
+         (line-termination (or (ioblock-line-termination ioblock)
+                               :unix)))
+    (make-external-format :character-encoding (character-encoding-name encoding)
+                          :line-termination line-termination)))
+
+(defmethod input-stream-shared-resource ((s basic-input-stream))
+  (getf (basic-stream.info s) :shared-resource))
+
+(defmethod (setf input-stream-shared-resource) (new (s basic-input-stream))
+  (setf (getf (basic-stream.info s) :shared-resource) new))
+
+(defmethod print-object ((s basic-stream) out)
+  (print-unreadable-object (s out :type t :identity t)
+    (let* ((ioblock (basic-stream.state s))
+           (fd (and ioblock (ioblock-device ioblock)))
+           (encoding (and ioblock (encoding-name (ioblock-encoding ioblock)))))
+      (if fd
+        (format out "~a (~a/~d)" encoding (%unix-fd-kind fd) fd)
+        (format out "~s" :closed)))))
+
+(defmethod select-stream-class ((s (eql 'basic-stream)) in-p out-p char-p)
+  (if char-p
+    (if in-p
+      (if out-p
+        'basic-character-io-stream
+        'basic-character-input-stream)
+      'basic-character-output-stream)
+    (if in-p
+      (if out-p
+        'basic-binary-io-stream
+        'basic-binary-input-stream)
+      'basic-binary-output-stream)))
+
+
+(defmethod map-to-basic-stream-class-name (name)
+  name)
+
+(defmethod map-to-basic-stream-class-name ((name (eql 'fd-stream)))
+  'basic-stream)
+
+(defun allocate-basic-stream (class)
+  (if (subtypep class 'basic-file-stream)
+    (gvector :basic-stream (%class-own-wrapper class) 0 nil nil nil nil nil)
+    (gvector :basic-stream (%class-own-wrapper class) 0 nil nil)))
+
+
+(defmethod initialize-basic-stream ((s basic-stream) &key &allow-other-keys)
+  )
+  
+(defmethod initialize-basic-stream :after  ((s basic-input-stream) &key &allow-other-keys)
+  (setf (basic-stream.flags s)
+        (logior (ash 1 basic-stream-flag.open-input) (basic-stream.flags s))))
+
+(defmethod initialize-basic-stream :after ((s basic-output-stream) &key &allow-other-keys)
+  (setf (basic-stream.flags s)
+        (logior (ash 1 basic-stream-flag.open-output) (basic-stream.flags s))))
+
+(defmethod initialize-basic-stream :after ((s basic-binary-stream) &key &allow-other-keys)
+  (setf (basic-stream.flags s)
+        (logior (ash 1 basic-stream-flag.open-binary) (basic-stream.flags s))))
+
+(defmethod initialize-basic-stream :after ((s basic-character-stream) &key &allow-other-keys)
+  (setf (basic-stream.flags s)
+        (logior (ash 1 basic-stream-flag.open-character) (basic-stream.flags s))))
+
+(defun make-basic-stream-instance (class &rest initargs)
+  (let* ((s (allocate-basic-stream class)))
+    (apply #'initialize-basic-stream s initargs)
+    s))
+
+
+
+(defmethod (setf stream-ioblock) (ioblock (s basic-stream))
+  (setf (basic-stream.state s) ioblock))
+
+(defmethod stream-create-ioblock ((stream basic-stream) &rest args &key)
+  (declare (dynamic-extent args))
+  (apply #'make-ioblock :stream stream args))
+
+
+(defmethod stream-write-list ((stream fundamental-character-output-stream)
+			      list count)
+  (declare (fixnum count))
+  (dotimes (i count)
+    (stream-write-char stream (pop list))))
+
+(defmethod stream-write-list ((stream basic-character-output-stream)
+			      list count)
+  (declare (fixnum count))
+  (dotimes (i count)
+    (stream-write-char stream (pop list))))
+
+(defmethod stream-read-list ((stream character-input-stream)
+			     list count)
+  (generic-character-read-list stream list count))
+
+
+(defmethod stream-write-list ((stream fundamental-binary-output-stream)
+			      list count)
+  (declare (fixnum count))
+  (dotimes (i count)
+    (let* ((element (pop list)))
+      (if (typep element 'character)
+        (write-char element stream)
+        (write-byte element stream)))))
+
+(defmethod stream-write-list ((stream basic-binary-output-stream)
+			      list count)
+  (declare (fixnum count))
+  (dotimes (i count)
+    (let* ((element (pop list)))
+      (if (typep element 'character)
+        (write-char element stream)
+        (write-byte element stream)))))
+
+(defmethod stream-read-list ((stream binary-input-stream)
+			     list count)
+  (declare (fixnum count))
+  (do* ((tail list (cdr tail))
+	(i 0 (1+ i)))
+       ((= i count) count)
+    (declare (fixnum i))
+    (let* ((b (read-byte stream nil :eof)))
+      (if (eq b :eof)
+	(return i)
+	(rplaca tail b)))))
+
+
+
+(defun stream-is-closed (s)
+  (error "~s is closed" s))
+
+(defmethod stream-read-char ((s basic-character-input-stream))
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (funcall (ioblock-read-char-function ioblock) ioblock)))
+
+
+(defmethod stream-read-char-no-hang ((stream basic-character-input-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (ioblock)
+      (values
+          (%ioblock-tyi-no-hang ioblock)))))
+       
+(defmethod stream-peek-char ((stream basic-character-input-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (ioblock)
+      (values
+       (funcall (ioblock-peek-char-function ioblock) ioblock)))))
+
+(defmethod stream-clear-input ((stream basic-character-input-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (ioblock)
+      (values
+        (%ioblock-clear-input ioblock)))))
+
+(defmethod stream-unread-char ((s basic-character-input-stream) char)
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-input-locked (ioblock)
+      (values
+       (funcall (ioblock-unread-char-function ioblock) ioblock char)))))
+
+(defmethod stream-read-ivector ((s basic-binary-input-stream)
+				iv start nb)
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-input-locked (ioblock)
+      (values
+       (%ioblock-binary-in-ivect ioblock iv start nb)))))
+
+(defmethod stream-read-vector ((stream basic-character-input-stream)
+			       vector start end)
+  (declare (fixnum start end))
+  (if (not (typep vector 'simple-base-string))
+    (generic-character-read-vector stream vector start end)
+    (let* ((ioblock (basic-stream-ioblock stream)))
+      (with-ioblock-input-locked (ioblock)
+        (values
+         (funcall (ioblock-character-read-vector-function ioblock)
+                  ioblock vector start end))))))
+
+(defmethod stream-read-line ((stream basic-character-input-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (ioblock)
+      (funcall (ioblock-read-line-function ioblock) ioblock))))
+
+                             
+;;; Synonym streams.
+
+(defclass synonym-stream (fundamental-stream)
+    ((symbol :initarg :symbol :reader synonym-stream-symbol)))
+
+(defmethod print-object ((s synonym-stream) out)
+  (print-unreadable-object (s out :type t :identity t)
+    (format out "to ~s" (synonym-stream-symbol s))))
+
+(macrolet ((synonym-method (name &rest args)
+            (let* ((stream (make-symbol "STREAM")))
+              `(defmethod ,name ((,stream synonym-stream) ,@args)
+                (,name (symbol-value (synonym-stream-symbol ,stream)) ,@args)))))
+           (synonym-method stream-read-char)
+           (synonym-method stream-read-byte)
+           (synonym-method stream-unread-char c)
+           (synonym-method stream-read-char-no-hang)
+           (synonym-method stream-peek-char)
+           (synonym-method stream-listen)
+           (synonym-method stream-eofp)
+           (synonym-method stream-clear-input)
+           (synonym-method stream-read-line)
+           (synonym-method stream-read-list l c)
+           (synonym-method stream-read-vector v start end)
+           (synonym-method stream-write-char c)
+           ;(synonym-method stream-write-string str &optional (start 0) end)
+           (synonym-method stream-write-byte b)
+           (synonym-method stream-clear-output)
+           (synonym-method stream-line-column)
+           (synonym-method stream-set-column new)
+           (synonym-method stream-advance-to-column new)
+           (synonym-method stream-start-line-p)
+           (synonym-method stream-fresh-line)
+           (synonym-method stream-terpri)
+           (synonym-method stream-force-output)
+           (synonym-method stream-finish-output)
+           (synonym-method stream-write-list l c)
+           (synonym-method stream-write-vector v start end)
+           (synonym-method stream-element-type)
+           (synonym-method input-stream-p)
+           (synonym-method output-stream-p)
+           (synonym-method interactive-stream-p)
+           (synonym-method stream-direction)
+	   (synonym-method stream-device direction)
+           (synonym-method stream-surrounding-characters)
+           (synonym-method stream-input-timeout)
+           (synonym-method stream-output-timeout)
+           (synonym-method stream-deadline)
+           (synonym-method stream-eof-transient-p))
+
+(defmethod (setf input-stream-timeout) (new (s synonym-stream))
+  (setf (input-stream-timeout (symbol-value (synonym-stream-symbol s))) new))
+
+(defmethod (setf output-stream-timeout) (new (s synonym-stream))
+  (setf (output-stream-timeout (symbol-value (synonym-stream-symbol s))) new))
+
+
+(defmethod stream-write-string ((s synonym-stream) string &optional (start 0) end)
+  (stream-write-string (symbol-value (synonym-stream-symbol s)) string start end))
+
+(defmethod stream-length ((s synonym-stream) &optional new)
+  (stream-length (symbol-value (synonym-stream-symbol s)) new))
+
+(defmethod stream-position ((s synonym-stream) &optional new)
+  (stream-position (symbol-value (synonym-stream-symbol s)) new))
+
+(defun make-synonym-stream (symbol)
+  (make-instance 'synonym-stream :symbol (require-type symbol 'symbol)))
+
+;;;
+(defclass composite-stream-mixin ()
+    ((open-p :initform t)))
+
+(defmethod close :after ((stream composite-stream-mixin) &key abort)
+  (declare (ignore abort))
+  (with-slots (open-p) stream
+    (setq open-p nil)))
+
+(defmethod open-stream-p ((stream composite-stream-mixin))
+  (slot-value stream 'open-p))
+
+
+
+;;; Two-way streams.
+(defclass two-way-stream (composite-stream-mixin fundamental-input-stream fundamental-output-stream)
+    ((input-stream :initarg :input-stream :accessor two-way-stream-input-stream)
+     (output-stream :initarg :output-stream :accessor two-way-stream-output-stream)))
+
+(defmethod stream-eof-transient-p ((stream two-way-stream))
+  (stream-eof-transient-p (two-way-stream-input-stream stream)))
+
+(defmethod print-object ((s two-way-stream) out)
+  (print-unreadable-object (s out :type t :identity t)
+    (format out "input ~s, output ~s" 
+            (two-way-stream-input-stream s)
+            (two-way-stream-output-stream s))))
+
+(macrolet ((two-way-input-method (name &rest args)
+             (let* ((stream (make-symbol "STREAM")))
+               `(defmethod ,name ((,stream two-way-stream) ,@args)
+                 (,name (two-way-stream-input-stream ,stream) ,@args))))
+           (two-way-output-method (name &rest args)
+             (let* ((stream (make-symbol "STREAM")))
+               `(defmethod ,name ((,stream two-way-stream) ,@args)
+                 (,name (two-way-stream-output-stream ,stream) ,@args)))))
+  (two-way-input-method stream-read-char)
+  (two-way-input-method stream-read-byte)
+  (two-way-input-method stream-unread-char c)
+  (two-way-input-method stream-read-char-no-hang)
+  (two-way-input-method stream-peek-char)
+  (two-way-input-method stream-listen)
+  (two-way-input-method stream-eofp)
+  (two-way-input-method stream-clear-input)
+  (two-way-input-method stream-read-line)
+  (two-way-input-method stream-read-list l c)
+  (two-way-input-method stream-read-vector v start end)
+  (two-way-input-method stream-surrounding-characters)
+  (two-way-input-method stream-input-timeout)
+  (two-way-input-method interactive-stream-p)
+  (two-way-output-method stream-write-char c)
+  (two-way-output-method stream-write-byte b)
+  (two-way-output-method stream-clear-output)
+  (two-way-output-method stream-line-column)
+  (two-way-output-method stream-set-column new)
+  (two-way-output-method stream-advance-to-column new)
+  (two-way-output-method stream-start-line-p)
+  (two-way-output-method stream-fresh-line)
+  (two-way-output-method stream-terpri)
+  (two-way-output-method stream-force-output)
+  (two-way-output-method stream-finish-output)
+  (two-way-output-method stream-write-list l c)
+  (two-way-output-method stream-write-vector v start end)
+  (two-way-output-method stream-output-timeout)
+  (two-way-output-method stream-deadline))
+
+(defmethod (setf stream-input-timeout) (new (s two-way-stream))
+  (setf (stream-input-timeout (two-way-stream-input-stream s)) new))
+
+(defmethod (setf stream-output-timeout) (new (s two-way-stream))
+  (setf (stream-output-timeout (two-way-stream-output-stream s)) new))
+
+(defmethod (setf stream-deadline) (new (s two-way-stream))
+  (setf (stream-deadline (two-way-stream-output-stream s)) new))
+
+(defmethod stream-device ((s two-way-stream) direction)
+  (case direction
+    (:input (stream-device (two-way-stream-input-stream s) direction))
+    (:output (stream-device (two-way-stream-output-stream s) direction))))
+    
+(defmethod stream-write-string ((s two-way-stream) string &optional (start 0) end)
+  (stream-write-string (two-way-stream-output-stream s) string start end))
+
+(defmethod stream-element-type ((s two-way-stream))
+  (let* ((in-type (stream-element-type (two-way-stream-input-stream s)))
+         (out-type (stream-element-type (two-way-stream-output-stream s))))
+    (if (equal in-type out-type)
+      in-type
+      `(and ,in-type ,out-type))))
+
+(defun make-two-way-stream (in out)
+  "Return a bidirectional stream which gets its input from INPUT-STREAM and
+   sends its output to OUTPUT-STREAM."
+  (unless (input-stream-p in)
+    (require-type in 'input-stream))
+  (unless (output-stream-p out)
+    (require-type out 'output-stream))
+  (make-instance 'two-way-stream :input-stream in :output-stream out))
+
+;;; This is intended for use with things like *TERMINAL-IO*, where the
+;;; OS echoes interactive input.  Whenever we read a character from
+;;; the underlying input-stream of such a stream, we need to update
+;;; our notion of the underlying output-stream's STREAM-LINE-COLUMN.
+
+(defclass echoing-two-way-stream (two-way-stream)
+    ())
+
+(defmethod stream-read-char ((s echoing-two-way-stream))
+  (let* ((out (two-way-stream-output-stream s))
+         (in (two-way-stream-input-stream s)))
+    (force-output out)
+    (let* ((ch (stream-read-char in)))
+      (unless (eq ch :eof)
+        (if (eq ch #\newline)
+          (stream-set-column out 0)
+          (let* ((cur (stream-line-column out)))
+            (when cur
+              (stream-set-column out (1+ (the fixnum cur)))))))
+      ch)))
+
+(defmethod stream-read-line ((s echoing-two-way-stream))
+  (let* ((out (two-way-stream-output-stream s)))
+    (multiple-value-bind (string eof)
+        (call-next-method)
+      (unless eof
+        (stream-set-column out 0))
+      (values string eof))))
+
+(defun make-echoing-two-way-stream (in out)
+  (make-instance 'echoing-two-way-stream :input-stream in :output-stream out))
+
+;;;echo streams
+
+(defclass echo-stream (two-way-stream)
+    ((did-untyi :initform nil)))
+
+(defmethod echo-stream-input-stream ((s echo-stream))
+  (two-way-stream-input-stream s))
+
+(defmethod echo-stream-output-stream ((s echo-stream))
+  (two-way-stream-output-stream s))
+
+(defmethod stream-read-char ((s echo-stream))
+  (let* ((char (stream-read-char (echo-stream-input-stream s))))
+    (unless (eq char :eof)
+      (if (slot-value s 'did-untyi)
+        (setf (slot-value s 'did-untyi) nil)
+        (stream-write-char (echo-stream-output-stream s) char)))
+    char))
+
+(defmethod stream-unread-char ((s echo-stream) c)
+  (call-next-method s c)
+  (setf (slot-value s 'did-untyi) c))
+
+(defmethod stream-read-char-no-hang ((s echo-stream))
+  (let* ((char (stream-read-char-no-hang (echo-stream-input-stream s))))
+    (unless (eq char :eof)
+      (if (slot-value s 'did-untyi)
+        (setf (slot-value s 'did-untyi) nil)
+        (stream-write-char (echo-stream-output-stream s) char)))
+    char))
+
+(defmethod stream-clear-input ((s echo-stream))
+  (call-next-method)
+  (setf (slot-value s 'did-untyi) nil))
+
+(defmethod stream-read-byte ((s echo-stream))
+  (let* ((byte (stream-read-byte (echo-stream-input-stream s))))
+    (unless (eq byte :eof)
+      (stream-write-byte (echo-stream-output-stream s) byte))
+    byte))
+
+(defmethod stream-read-line ((s echo-stream))
+  (generic-read-line s))
+
+(defmethod stream-read-vector ((s echo-stream) vector start end)
+  (if (subtypep (stream-element-type s) 'character)
+      (generic-character-read-vector s vector start end)
+    (generic-binary-read-vector s vector start end)))
+
+(defun make-echo-stream (input-stream output-stream)
+  "Return a bidirectional stream which gets its input from INPUT-STREAM and
+   sends its output to OUTPUT-STREAM. In addition, all input is echoed to
+   the output stream."
+  (make-instance 'echo-stream
+                 :input-stream input-stream
+                 :output-stream output-stream))
+
+;;;concatenated-streams
+
+(defclass concatenated-stream (composite-stream-mixin fundamental-input-stream)
+    ((streams :initarg :streams :accessor concatenated-stream-streams)))
+
+
+(defun concatenated-stream-current-input-stream (s)
+  (car (concatenated-stream-streams s)))
+
+(defun concatenated-stream-next-input-stream (s)
+  (setf (concatenated-stream-streams s)
+	(cdr (concatenated-stream-streams s)))
+  (concatenated-stream-current-input-stream s))
+
+(defmethod stream-element-type ((s concatenated-stream))
+  (let* ((c (concatenated-stream-current-input-stream s)))
+    (if c
+      (stream-element-type c)
+      nil)))
+
+
+
+(defmethod stream-read-char ((s concatenated-stream))
+  (do* ((c (concatenated-stream-current-input-stream s)
+	   (concatenated-stream-next-input-stream s)))
+       ((null c) :eof)
+    (let* ((ch (stream-read-char c)))
+      (unless (eq ch :eof)
+	(return ch)))))
+
+(defmethod stream-read-char-no-hang ((s concatenated-stream))
+  (do* ((c (concatenated-stream-current-input-stream s)
+	   (concatenated-stream-next-input-stream s)))
+       ((null c) :eof)
+    (let* ((ch (stream-read-char-no-hang c)))
+      (unless (eq ch :eof)
+	(return ch)))))
+
+(defmethod stream-read-byte ((s concatenated-stream))
+  (do* ((c (concatenated-stream-current-input-stream s)
+	   (concatenated-stream-next-input-stream s)))
+       ((null c) :eof)
+    (let* ((b (stream-read-byte c)))
+      (unless (eq b :eof)
+	(return b)))))
+
+(defmethod stream-peek-char ((s concatenated-stream))
+  (do* ((c (concatenated-stream-current-input-stream s)
+       (concatenated-stream-next-input-stream s)))
+       ((null c) :eof)
+    (let* ((ch (stream-peek-char c)))
+      (unless (eq ch :eof)
+        (return ch)))))
+
+(defmethod stream-read-line ((s concatenated-stream))
+  (generic-read-line s))
+
+(defmethod stream-read-list ((s concatenated-stream) list count)
+  (generic-character-read-list s list count))
+
+(defmethod stream-read-vector ((s concatenated-stream) vector start end)
+  (if (subtypep (stream-element-type s) 'character)
+      (generic-character-read-vector s vector start end)
+    (generic-binary-read-vector s vector start end)))
+
+(defmethod stream-unread-char ((s concatenated-stream) char)
+  (let* ((c (concatenated-stream-current-input-stream s)))
+    (if c
+      (stream-unread-char c char))))
+
+(defmethod stream-listen ((s concatenated-stream))
+  (do* ((c (concatenated-stream-current-input-stream s)
+	   (concatenated-stream-next-input-stream s)))
+       ((null c))
+    (when (stream-listen c)
+      (return t))))
+
+(defmethod stream-eofp ((s concatenated-stream))
+  (do* ((c (concatenated-stream-current-input-stream s)
+	   (concatenated-stream-next-input-stream s)))
+       ((null c) t)
+    (when (stream-listen c)
+      (return nil))))
+
+(defmethod stream-clear-input ((s concatenated-stream))
+  (let* ((c (concatenated-stream-current-input-stream s)))
+    (when c (stream-clear-input c))))
+
+
+(defun make-concatenated-stream (&rest streams)
+  "Return a stream which takes its input from each of the streams in turn,
+   going on to the next at EOF."
+  (dolist (s streams (make-instance 'concatenated-stream :streams streams))
+    (unless (input-stream-p s)
+      (error "~S is not an input stream" s))))
+
+;;;broadcast-streams
+
+
+
+(defclass broadcast-stream (fundamental-output-stream)
+    ((streams :initarg :streams :reader broadcast-stream-streams)))
+
+(macrolet ((broadcast-method
+	       (op (stream &rest others )
+                   &optional
+                   (args (cons stream others)))
+	     (let* ((sub (gensym))
+		    (result (gensym)))
+               `(defmethod ,op ((,stream broadcast-stream) ,@others)
+		 (let* ((,result nil))
+		   (dolist (,sub (broadcast-stream-streams ,stream) ,result)
+			     (setq ,result (,op ,@(cons sub (cdr args))))))))))
+	     (broadcast-method stream-write-char (s c))
+	     (broadcast-method stream-write-string
+				      (s str &optional (start 0) end)
+				      (s str start end))
+	     (broadcast-method stream-write-byte (s b))
+	     (broadcast-method stream-clear-output (s))
+	     (broadcast-method stream-line-column (s))
+	     (broadcast-method stream-set-column (s new))
+	     (broadcast-method stream-advance-to-column (s new))
+	     (broadcast-method stream-start-line-p (s))
+	     (broadcast-method stream-terpri (s))
+	     (broadcast-method stream-force-output (s))
+	     (broadcast-method stream-finish-output (s))
+	     (broadcast-method stream-write-list (s l c))
+	     (broadcast-method stream-write-vector (s v start end)))
+
+(defun last-broadcast-stream (s)
+  (car (last (broadcast-stream-streams s))))
+
+(defmethod stream-fresh-line ((s broadcast-stream))
+  (let* ((did-output-newline nil))
+    (dolist (sub (broadcast-stream-streams s) did-output-newline)
+      (setq did-output-newline (stream-fresh-line sub)))))
+
+(defmethod stream-element-type ((s broadcast-stream))
+  (let* ((last (last-broadcast-stream s)))
+    (if last
+      (stream-element-type last)
+      t)))
+
+(defmethod stream-length ((s broadcast-stream) &optional new)
+  (unless new
+    (let* ((last (last-broadcast-stream s)))
+      (if last
+	(stream-length last)
+	0))))
+
+(defmethod stream-position ((s broadcast-stream) &optional new)
+  (unless new
+    (let* ((last (last-broadcast-stream s)))
+      (if last
+	(stream-position last)
+	0))))
+
+(defun make-broadcast-stream (&rest streams)
+  (dolist (s streams (make-instance 'broadcast-stream :streams streams))
+    (unless (output-stream-p s)
+      (report-bad-arg s '(satisfies output-stream-p)))))
+
+
+
+
+;;; String streams.
+(make-built-in-class 'string-stream 'basic-character-stream)
+
+(defmethod print-object ((s string-stream) out)
+  (print-unreadable-object (s out :type t :identity t)
+    (unless (open-stream-p s)  (format out " ~s" :closed))))
+
+
+                 
+
+(defstruct (string-stream-ioblock (:include ioblock))
+  string)
+
+(defstruct (string-output-stream-ioblock (:include string-stream-ioblock))
+  (index 0)
+  freelist)
+
+(defstatic *string-output-stream-class* (make-built-in-class 'string-output-stream 'string-stream 'basic-character-output-stream))
+(defstatic *string-output-stream-class-wrapper* (%class-own-wrapper *string-output-stream-class*))
+
+(defstatic *fill-pointer-string-output-stream-class* (make-built-in-class 'fill-pointer-string-output-stream 'string-output-stream))
+
+(def-standard-initial-binding %string-output-stream-ioblocks% (%cons-pool nil))
+
+(defmethod stream-force-output ((s string-output-stream))
+  nil)
+
+(defmethod stream-finish-output ((s string-output-stream))
+  nil)
+
+(defmethod stream-clear-output ((s string-output-stream))
+  nil)
+
+;;; Should only be used for a stream whose class is exactly
+;;; *string-output-stream-class* 
+(defun %close-string-output-stream (stream ioblock)
+  (let* ((pool %string-output-stream-ioblocks%))
+    (when (and pool
+               (eq (basic-stream.wrapper stream)
+                   *string-output-stream-class-wrapper*)
+               (eq (string-output-stream-ioblock-freelist ioblock) pool))
+    (without-interrupts
+     (setf (ioblock-stream ioblock) (pool.data pool)
+           (pool.data pool) ioblock)))))
+
+;;; If this is the sort of string stream whose ioblock we recycle and
+;;; there's a thread-local binding of the variable we use for a freelist,
+;;; return the value of that binding.
+(defun %string-stream-ioblock-freelist (stream)
+  (and stream
+       (eq (basic-stream.wrapper stream)
+           *string-output-stream-class-wrapper*)
+       (let* ((loc (%tcr-binding-location (%current-tcr) '%string-output-stream-ioblocks%)))
+         (and loc (%fixnum-ref loc)))))
+
+
+(defun create-string-output-stream-ioblock (&rest keys &key stream &allow-other-keys)
+  (declare (dynamic-extent keys))
+  (let* ((recycled (and stream
+                        (eq (basic-stream.wrapper stream)
+                            *string-output-stream-class-wrapper*)
+                        (without-interrupts
+                         (let* ((data (pool.data %string-output-stream-ioblocks%)))
+                           (when data
+                             (setf (pool.data %string-output-stream-ioblocks%)
+                                   (ioblock-stream data)
+                                   (ioblock-stream data) stream
+                                   (ioblock-device data) -1
+                                   (ioblock-charpos data) 0
+                                   (string-output-stream-ioblock-index data) 0))
+                           data)))))
+    (or recycled (apply #'make-string-output-stream-ioblock keys))))
+                        
+
+
+(defun %%make-string-output-stream (class string write-char-function write-string-function)
+  (let* ((stream (allocate-basic-stream class)))
+    (initialize-basic-stream stream :element-type 'character)
+    (let* ((ioblock (create-string-output-stream-ioblock
+                     :stream stream
+                     :string string
+                     :element-type 'character
+                     :write-char-function write-char-function
+                     :write-char-when-locked-function write-char-function
+                     :write-simple-string-function write-string-function
+                     :force-output-function #'false
+                     :freelist (%string-stream-ioblock-freelist stream)
+                     :close-function #'%close-string-output-stream)))
+      (setf (basic-stream.state stream) ioblock)
+      stream)))
+
+(declaim (inline %string-push-extend))
+(defun %string-push-extend (char string)
+  (let* ((fill (%svref string target::vectorH.logsize-cell))
+         (size (%svref string target::vectorH.physsize-cell)))
+    (declare (fixnum fill size))
+    (if (< fill size)
+      (multiple-value-bind (data offset) (array-data-and-offset string)
+        (declare (simple-string data) (fixnum offset))
+        (setf (schar data (the fixnum (+ offset fill))) char
+              (%svref string target::vectorH.logsize-cell) (the fixnum (1+ fill))))
+      (vector-push-extend char string))))
+              
+
+(defun fill-pointer-string-output-stream-ioblock-write-char (ioblock char)
+  ;; can do better (maybe much better) than VECTOR-PUSH-EXTEND here.
+  (if (eql char #\Newline)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (%string-push-extend char (string-stream-ioblock-string ioblock)))
+
+(defun fill-pointer-string-output-stream-ioblock-write-simple-string (ioblock string start-char num-chars)
+  (let* ((end (+ start-char num-chars))
+         (nlpos (position #\Newline string :start start-char :end end :from-end t)))
+    (if nlpos
+      (setf (ioblock-charpos ioblock) (- end nlpos))
+      (incf (ioblock-charpos ioblock) num-chars))
+    (let* ((out (string-stream-ioblock-string ioblock)))
+      (do* ((n 0 (1+ n))
+            (i start-char (1+ i)))
+           ((= n num-chars) num-chars)
+        (%string-push-extend (schar string i) out)))))
+
+(defmethod stream-position ((s fill-pointer-string-output-stream) &optional newpos)
+  (let* ((string (string-stream-string s)))
+    (if newpos
+      (setf (fill-pointer string) newpos)
+      (fill-pointer string))))
+
+;;; If the stream's string is adjustable, it doesn't really have a meaningful
+;;; "maximum size".
+(defmethod stream-length ((s string-output-stream) &optional newlen)
+  (unless newlen
+    (array-total-size (string-stream-string s))))
+
+;;; This creates a FILL-POINTER-STRING-OUTPUT-STREAM.
+(defun %make-string-output-stream (string)
+  (unless (and (typep string 'string)
+               (array-has-fill-pointer-p string))
+    (error "~S must be a string with a fill pointer." string))
+  (%%make-string-output-stream *fill-pointer-string-output-stream-class* string 'fill-pointer-string-output-stream-ioblock-write-char 'fill-pointer-string-output-stream-ioblock-write-simple-string))
+
+(defun string-output-stream-ioblock-write-char (ioblock char)
+  (let* ((string (string-output-stream-ioblock-string ioblock))
+         (index (string-output-stream-ioblock-index ioblock))
+         (len (length string)))
+    (declare (simple-string string)
+             (fixnum index len))
+  (if (eql char #\Newline)
+    (setf (ioblock-charpos ioblock) 0)
+    (incf (ioblock-charpos ioblock)))
+  (if (= index len)
+      (let* ((newlen (if (zerop len) 20 (+ len len)))      ;non-zero !
+             (new (make-string newlen)))
+        (%copy-ivector-to-ivector string 0 new 0 (the fixnum (ash len 2)))
+        (setq string new)
+        (setf (string-output-stream-ioblock-string ioblock) new)))
+    (setf (string-output-stream-ioblock-index ioblock) (the fixnum (1+ index))
+          (schar string index) char)))
+
+(defun string-output-stream-ioblock-write-simple-string (ioblock string start-char num-chars)
+  (declare (simple-string string)
+           (fixnum start-char num-chars)
+           (optimize (speed 3) (safety 0)))
+  (let* ((out (string-output-stream-ioblock-string ioblock))
+         (index (string-output-stream-ioblock-index ioblock))
+         (len (length out))
+         (need (+ index num-chars)))
+    (declare (simple-string out)
+             (fixnum index len need))
+    (if (< len need)
+      (let* ((newlen (+ need need))
+             (new (make-string newlen)))
+        (declare (fixnum newlen) (simple-string new))
+        (dotimes (i len)
+          (setf (schar new i) (schar out i)))
+        (setq out new)
+        (setf (string-output-stream-ioblock-string ioblock) new)))
+    (do* ((src start-char (1+ src))
+          (dest index (1+ dest))
+          (nlpos nil)
+          (end (+ start-char num-chars)))
+         ((= src end)
+          (setf (string-output-stream-ioblock-index ioblock) need)
+          (if nlpos
+            (setf (ioblock-charpos ioblock) (the fixnum (- end (the fixnum nlpos))))
+            (incf (ioblock-charpos ioblock) num-chars))
+          num-chars)
+      (declare (fixnum src dest end))
+      (let* ((char (schar string src)))
+        (if (eql char #\Newline)
+          (setq nlpos (the fixnum (1+ src))))
+        (setf (schar out dest) char)))))
+
+
+(defmethod stream-position ((stream string-output-stream) &optional newpos)
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (if (null newpos)
+      (string-output-stream-ioblock-index ioblock)
+      (if (and (typep newpos 'fixnum)
+               (>= (the fixnum newpos) 0)
+               (<= (the fixnum newpos) (length (string-output-stream-ioblock-string ioblock))))
+        (setf (string-output-stream-ioblock-index ioblock) newpos)))))
+
+(defun make-simple-string-output-stream ()
+  ;; There's a good chance that we'll get a recycled ioblock
+  ;; that already has a string; if not, we defer actually
+  ;; creating a usable string until write-char
+  (%%make-string-output-stream *string-output-stream-class*
+                               ""
+                               'string-output-stream-ioblock-write-char
+                               'string-output-stream-ioblock-write-simple-string))
+
+(defun make-string-output-stream (&key (element-type 'character element-type-p))
+  "Return an output stream which will accumulate all output given it for
+   the benefit of the function GET-OUTPUT-STREAM-STRING."
+  (when (and element-type-p
+             (not (member element-type '(base-character character
+                                         standard-char))))
+    (unless (subtypep element-type 'character)
+      (error "~S argument ~S is not a subtype of ~S."
+             :element-type element-type 'character)))
+  (make-simple-string-output-stream))
+
+
+;;;"Bounded" string output streams.
+(defstatic *truncating-string-output-stream-class* (make-built-in-class 'truncating-string-stream 'string-output-stream))
+
+(defun truncating-string-output-stream-ioblock-write-char (ioblock char)
+  (let* ((stream (ioblock-stream ioblock))
+         (string (string-output-stream-ioblock-string ioblock))
+         (index (string-output-stream-ioblock-index ioblock)))
+    (declare (fixnum index) (simple-string string))
+    (if (< index (the fixnum (length string)))
+      (progn
+        (setf (schar string index) char
+              (string-output-stream-ioblock-index ioblock) (the fixnum (1+ index)))
+        (if (eql char #\Newline)
+          (setf (ioblock-charpos ioblock) 0)
+          (incf (ioblock-charpos ioblock))))
+      (setf (getf (basic-stream.info stream) :truncated) t))))
+
+(defun truncating-string-output-stream-ioblock-write-simple-string (ioblock string start-char num-chars)
+  (let* ((stream (ioblock-stream ioblock)))
+  (do* ((n 0 (1+ n))
+        (i start-char (1+ i)))
+       ((= n num-chars) num-chars)
+    (truncating-string-output-stream-ioblock-write-char ioblock (schar string i))
+    (if (getf (basic-stream.info stream) :truncated)
+      (return n)))))
+
+(defun truncating-string-output-stream-truncated-p (stream)
+  (getf (basic-stream.info stream) :truncated))
+
+(defun make-truncating-string-stream (len)
+  (%%make-string-output-stream *truncating-string-output-stream-class*
+                               (make-string len)
+                               'truncating-string-output-stream-ioblock-write-char
+                               'truncating-string-output-stream-ioblock-write-simple-string))
+                               
+
+;;;One way to indent on newlines:
+
+(defstatic *indenting-string-output-stream-class* (make-built-in-class 'indenting-string-output-stream 'string-output-stream))
+(defstatic *indenting-string-output-stream-class-wrapper* (%class-own-wrapper *indenting-string-output-stream-class*))
+
+
+(defun indenting-string-stream-ioblock-write-char (ioblock c)
+  (string-output-stream-ioblock-write-char ioblock c)
+  (if (eql c #\newline)
+    (let* ((stream (ioblock-stream ioblock))
+           (info (basic-stream.info stream))
+           (indent (getf info 'indent))
+           (prefixlen 0)
+           (prefixchar (getf info 'prefixchar)))
+      (when prefixchar
+        (if (typep prefixchar 'character)
+          (progn
+            (setq prefixlen 1)
+            (string-output-stream-ioblock-write-char ioblock prefixchar))
+          (dotimes (i (setq prefixlen (length prefixchar)))
+            (string-output-stream-ioblock-write-char ioblock (schar prefixchar i)))))
+      (when indent
+        (dotimes (i (the fixnum (- indent prefixlen)))
+          (string-output-stream-ioblock-write-char ioblock #\Space)))))
+  c)
+
+(defun indenting-string-stream-ioblock-write-simple-string (ioblock string start-char num-chars)
+  (do* ((n 0 (1+ n))
+        (i start-char (1+ i)))
+       ((= n num-chars) num-chars)
+    (indenting-string-stream-ioblock-write-char ioblock (schar string i))))
+
+(defun make-indenting-string-output-stream (prefixchar indent)
+  (let* ((stream (%%make-string-output-stream
+                   *indenting-string-output-stream-class*
+                  (make-string 10)
+                  'indenting-string-stream-ioblock-write-char
+                  'indenting-string-stream-ioblock-write-simple-string)))
+    (setf (getf (basic-stream.info stream) 'indent) indent
+          (getf (basic-stream.info stream) 'prefixchar) prefixchar)
+    stream))
+
+(defun (setf indenting-string-output-stream-indent) (new stream)
+  (if (and (typep stream 'basic-stream)
+           (eq (basic-stream.wrapper stream) *indenting-string-output-stream-class-wrapper*))
+    (setf (getf (basic-stream.info stream) 'indent) new)
+    (report-bad-arg stream 'indenting-string-output-stream)))
+
+
+(defun get-output-stream-string (s)
+ (let* ((class (if (typep s 'basic-stream) (%wrapper-class (basic-stream.wrapper s)))))
+    (or (eq class *string-output-stream-class*)
+        (eq class *truncating-string-output-stream-class*)
+        (eq class *indenting-string-output-stream-class*)
+        (eq class *fill-pointer-string-output-stream-class*)
+        (report-bad-arg s 'string-output-stream))
+    (let* ((ioblock (basic-stream-ioblock s))
+           (string (string-stream-ioblock-string ioblock)))
+      (if (eq class *fill-pointer-string-output-stream-class*)
+        (prog1 (ensure-simple-string string)
+          (setf (fill-pointer string) 0))
+        (let* ((index (string-output-stream-ioblock-index ioblock))
+               (result (make-string index)))
+          (declare (fixnum index))
+          (%copy-ivector-to-ivector string 0 result 0 (the fixnum (ash index 2)))
+          (setf (string-output-stream-ioblock-index ioblock) 0)
+          result)))))
+
+;;; String input streams.
+(defstatic *string-input-stream-class* (make-built-in-class 'string-input-stream 'string-stream 'basic-character-input-stream))
+(defstatic *string-input-stream-class-wrapper* (%class-own-wrapper *string-input-stream-class*))
+(defstruct (string-input-stream-ioblock (:include string-stream-ioblock))
+  (start 0)
+  index
+  end
+  (offset 0))
+
+
+
+(defun string-input-stream-index (s)
+  (if (and (typep s 'basic-stream)
+           (eq *string-input-stream-class-wrapper* (basic-stream.wrapper s)))
+    (let* ((ioblock (basic-stream-ioblock s)))
+      (- (string-input-stream-ioblock-index ioblock)
+         (string-input-stream-ioblock-offset ioblock)))
+    (report-bad-arg s 'string-input-stream)))
+
+
+(defmethod stream-surrounding-characters ((s string-input-stream))
+  (let* ((ioblock (basic-stream.state s)))
+    (when ioblock
+      (let* ((start (string-input-stream-ioblock-start ioblock))
+             (idx (string-input-stream-ioblock-index ioblock))
+             (end (string-input-stream-ioblock-end ioblock))
+             (string (string-stream-ioblock-string ioblock)))
+        (subseq string (max (- idx 10) start) (min (+ idx 10) end))))))
+    
+
+(defmethod stream-position ((s string-input-stream) &optional newpos)
+  (let* ((ioblock (basic-stream-ioblock s))
+         (start (string-input-stream-ioblock-start ioblock))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (end (string-input-stream-ioblock-end ioblock)))
+    (declare (fixnum end idx start))
+    (if newpos
+      (let* ((limit (- end start)))
+        (declare (fixnum limit))
+        (if (and (typep newpos 'fixnum)
+                 (>= (the fixnum newpos) 0)
+                 (<= (the fixnum newpos) limit))
+          (progn
+            (setf (string-input-stream-ioblock-index ioblock)
+                  (the fixnum (+ start (the fixnum newpos))))
+            newpos)
+          (report-bad-arg newpos `(integer 0 ,limit))))
+      (the fixnum (- idx start)))))
+    
+  
+
+(defun string-input-stream-ioblock-read-char (ioblock)
+  (let* ((string (string-stream-ioblock-string ioblock))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (end (string-input-stream-ioblock-end ioblock)))
+    (declare (fixnum idx end)
+             (simple-string string))
+    (if (< idx end)
+      (progn (setf (string-input-stream-ioblock-index ioblock)
+                   (the fixnum (1+ idx)))
+             (schar string idx))
+      :eof)))
+
+(defun string-input-stream-ioblock-read-line (ioblock)
+  (let* ((string (string-stream-ioblock-string ioblock))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (end (string-input-stream-ioblock-end ioblock)))
+    (declare (fixnum idx end)
+             (simple-string string))
+    (if (>= idx end)
+      (values "" t)
+      (let* ((pos (position #\Newline string :start idx :end end)))
+        (if pos
+          (locally (declare (type index pos))
+            (let* ((new (make-string (the fixnum (- pos idx)))))
+              (declare (simple-base-string new))
+              (setf (string-input-stream-ioblock-index ioblock)
+                    (the fixnum (1+ pos)))
+              (do* ((src idx (1+ src))
+                    (dest 0 (1+ dest)))
+                   ((= src pos) (values new nil))
+                (declare (fixnum src dest))
+                (setf (schar new dest) (schar string src)))))
+          (let* ((new (make-string (the fixnum (- end idx)))))
+            (declare (simple-base-string new))
+              (setf (string-input-stream-ioblock-index ioblock) end)
+              (do* ((src idx (1+ src))
+                    (dest 0 (1+ dest)))
+                   ((= src end) (values new t))
+                (declare (fixnum src dest))
+                (setf (schar new dest) (schar string src)))))))))
+
+
+(defun string-input-stream-ioblock-peek-char (ioblock)
+  (let* ((string (string-stream-ioblock-string ioblock))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (end (string-input-stream-ioblock-end ioblock)))
+    (declare (fixnum idx end)
+             (simple-string string))
+    (if (< idx end)
+      (schar string idx)
+      :eof)))
+
+(defun string-input-stream-ioblock-unread-char (ioblock char)
+  (let* ((string (string-stream-ioblock-string ioblock))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (start (string-input-stream-ioblock-start ioblock)))
+    (declare (fixnum idx start)
+             (simple-string string))
+    (unless (> idx start)
+      (error "Nothing has been read from ~s yet." (ioblock-stream ioblock)))
+    (decf idx)
+    (unless (eq char (schar string idx))
+      (error "~a was not the last character read from ~s" char (ioblock-stream ioblock)))
+    (setf (string-input-stream-ioblock-index ioblock) idx)
+    char))
+  
+  
+(defmethod stream-eofp ((s string-input-stream))
+  (let* ((ioblock (basic-stream-ioblock s))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (end (string-input-stream-ioblock-end ioblock)))
+    (declare (fixnum idx end))
+    (>= idx end)))
+
+(defmethod stream-listen ((s string-input-stream))
+  (let* ((ioblock (basic-stream-ioblock s))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (end (string-input-stream-ioblock-end ioblock)))
+    (declare (fixnum idx end))
+    (< idx end)))
+
+(defmethod stream-clear-input ((s string-input-stream))
+  (basic-stream-ioblock s)
+  nil)
+
+(defun string-input-stream-character-read-vector (ioblock vector start end)
+  (let* ((string (string-stream-ioblock-string ioblock))
+         (idx (string-input-stream-ioblock-index ioblock))
+         (limit (string-input-stream-ioblock-end ioblock)))
+    (declare (fixnum idx limit))
+    (do* ((i start (1+ i)))
+         ((= i end) (setf (string-input-stream-ioblock-index ioblock) idx) end)
+      (declare (fixnum i))
+      (if (< idx limit)
+        (setf (uvref vector i) (schar string idx)
+              idx (1+ idx))
+        (progn
+          (setf (string-input-stream-ioblock-index ioblock) idx)
+          (return i))))))
+         
+
+
+(defun make-string-input-stream (string &optional (start 0)
+                                        (end nil))
+  "Return an input stream which will supply the characters of STRING between
+  START and END in order."
+  (setq end (check-sequence-bounds string start end))
+  (multiple-value-bind (data offset) (array-data-and-offset string)
+    (unless (typep data 'simple-base-string)
+      (report-bad-arg string 'string))
+    (incf start offset)
+    (incf end offset)
+    (let* ((stream (make-basic-stream-instance
+                    *string-input-stream-class*
+                    :element-type 'character))
+           (ioblock (make-string-input-stream-ioblock
+                     :stream stream
+                     :offset offset
+                     :string data
+                     :start start
+                     :index start
+                     :end end
+                     :read-char-function 'string-input-stream-ioblock-read-char
+                     :read-char-when-locked-function 'string-input-stream-ioblock-read-char
+                     :peek-char-function 'string-input-stream-ioblock-peek-char
+                     :character-read-vector-function 'string-input-stream-character-read-vector
+                     :close-function #'false
+                     :unread-char-function 'string-input-stream-ioblock-unread-char
+                     :read-line-function 'string-input-stream-ioblock-read-line
+                     )))
+      (setf (basic-stream.state stream) ioblock)
+      stream)))
+
+(defun string-stream-string (s)
+  (let* ((class (if (typep s 'basic-stream) (%wrapper-class (basic-stream.wrapper s)))))
+    (or (eq class *string-output-stream-class*)
+        (eq class *truncating-string-output-stream-class*)
+        (eq class *indenting-string-output-stream-class*)
+        (report-bad-arg s 'string-output-stream)))
+  (string-stream-ioblock-string (basic-stream-ioblock s)))
+
+
+
+
+;;; A mixin to be used with FUNDAMENTAL-STREAMs that want to use ioblocks
+;;; to buffer I/O.
+
+(defclass buffered-stream-mixin ()
+  ((ioblock :reader %stream-ioblock :writer (setf stream-ioblock) :initform nil)))
+
+(defmethod open-stream-p ((s buffered-stream-mixin))
+  (with-slots (ioblock) s
+    (not (null ioblock))))
+
+(declaim (inline stream-ioblock))
+
+(defun stream-ioblock (stream error-if-nil)
+  (or (if (typep stream 'basic-stream)
+        (basic-stream.state stream)
+        (%stream-ioblock stream))
+      (when error-if-nil
+        (stream-is-closed stream))))
+
+(defmethod stream-device ((s buffered-stream-mixin) direction)
+  (declare (ignore direction))
+  (let* ((ioblock (stream-ioblock s nil)))
+    (and ioblock (ioblock-device ioblock))))
+
+(defmethod stream-device ((s basic-stream) direction)
+  (declare (ignore direction))
+  (let* ((ioblock (basic-stream.state s)))
+    (and ioblock (ioblock-device ioblock))))
+  
+(defmethod stream-element-type ((s buffered-stream-mixin))
+  (ioblock-element-type (stream-ioblock s t)))
+
+(defmethod stream-element-type ((s basic-stream))
+  (ioblock-element-type (basic-stream-ioblock s)))
+
+
+(defmethod stream-create-ioblock ((stream buffered-stream-mixin) &rest args &key)
+  (declare (dynamic-extent args))
+  (apply #'make-ioblock :stream stream args))
+
+(defmethod stream-owner ((stream stream))
+  )
+
+(defmethod stream-owner ((stream buffered-stream-mixin))
+  (let* ((ioblock (stream-ioblock stream nil)))
+    (and ioblock (let* ((owner (ioblock-owner ioblock)))
+                   (unless (eql owner 0) owner)))))
+
+(defmethod stream-owner ((stream basic-stream))
+  (let* ((ioblock (basic-stream.state stream)))
+    (and ioblock (let* ((owner (ioblock-owner ioblock)))
+                   (unless (eql owner 0) owner)))))
+
+
+(defclass buffered-input-stream-mixin
+          (buffered-stream-mixin fundamental-input-stream)
+  ())
+
+(defclass buffered-output-stream-mixin
+          (buffered-stream-mixin fundamental-output-stream)
+  ())
+
+(defclass buffered-io-stream-mixin
+          (buffered-input-stream-mixin buffered-output-stream-mixin)
+  ())
+
+(defclass buffered-character-input-stream-mixin
+          (buffered-input-stream-mixin fundamental-character-input-stream)
+  ())
+
+(defclass buffered-character-output-stream-mixin
+          (buffered-output-stream-mixin fundamental-character-output-stream)
+  ())
+
+(defclass buffered-character-io-stream-mixin
+          (buffered-character-input-stream-mixin buffered-character-output-stream-mixin)
+  ())
+
+(defclass buffered-binary-input-stream-mixin
+          (buffered-input-stream-mixin fundamental-binary-input-stream)
+  ())
+
+(defclass buffered-binary-output-stream-mixin
+          (buffered-output-stream-mixin fundamental-binary-output-stream)
+  ())
+
+(defclass buffered-binary-io-stream-mixin
+          (buffered-binary-input-stream-mixin
+           buffered-binary-output-stream-mixin)
+  ())
+
+(defmethod close :after ((stream buffered-stream-mixin) &key abort)
+  (declare (ignore abort))
+  (let* ((ioblock (stream-ioblock stream nil)))
+    (when ioblock
+      (%ioblock-close ioblock))))
+
+(defmethod close :before ((stream buffered-output-stream-mixin) &key abort)
+  (unless abort
+    (when (open-stream-p stream)
+      (stream-force-output stream))))
+
+(defmethod close-for-termination ((stream buffered-output-stream-mixin) abort)
+  ;; This method should only be invoked via the termination mechanism,
+  ;; so it can safely assume that there's no contention for the stream.
+  (let* ((ioblock (stream-ioblock stream nil)))
+    (when ioblock (setf (ioblock-owner ioblock) nil)))
+  (close stream :abort abort))
+
+
+(defmethod interactive-stream-p ((stream buffered-stream-mixin))
+  (let* ((ioblock (stream-ioblock stream nil)))
+    (and ioblock (ioblock-interactive ioblock))))
+
+(defmethod interactive-stream-p ((stream basic-stream))
+  (let* ((ioblock (basic-stream.state stream)))
+    (and ioblock (ioblock-interactive ioblock))))
+
+
+(defmethod close :after ((stream basic-stream) &key abort)
+  (declare (ignore abort))
+  (let* ((ioblock (basic-stream.state stream)))
+    (when ioblock
+      (%ioblock-close ioblock))))
+
+(defmethod close-for-termination  ((stream basic-stream) abort)
+  (let* ((ioblock (basic-stream.state stream)))
+    (when ioblock (setf (ioblock-owner ioblock) nil)))
+  (close stream :abort abort))
+
+  
+
+(defmethod open-stream-p ((stream basic-stream))
+  (not (null (basic-stream.state stream))))
+
+(defmethod close :before ((stream basic-output-stream) &key abort)
+  (unless abort
+    (when (open-stream-p stream)
+      (stream-force-output stream))))
+
+(defmethod stream-surrounding-characters ((stream buffered-character-input-stream-mixin))
+    (let* ((ioblock (stream-ioblock stream nil)))
+      (and ioblock (%ioblock-surrounding-characters ioblock))))
+
+(defmethod stream-surrounding-characters ((stream basic-character-input-stream))
+    (let* ((ioblock (basic-stream.state stream)))
+      (and ioblock (%ioblock-surrounding-characters ioblock))))
+
+
+#|
+(defgeneric ioblock-advance (stream ioblock readp)
+  (:documentation
+   "Called when the current input buffer is empty (or non-existent).
+    readp true means the caller expects to return a byte now.
+    Return value is meaningless unless readp is true, in which case
+    it means that there is input ready"))
+
+(defgeneric ioblock-listen (stream ioblock)
+  (:documentation
+   "Called in response to stream-listen when the current
+    input buffer is empty.
+    Returns a boolean"))
+
+(defgeneric ioblock-eofp (stream ioblock)
+  (:documentation
+   "Called in response to stream-eofp when the input buffer is empty.
+    Returns a boolean."))
+
+(defgeneric ioblock-force-output (stream ioblock count finish-p)
+  (:documentation
+   "Called in response to stream-force-output.
+    Write count bytes from ioblock-outbuf.
+    Finish the I/O if finish-p is true."))
+
+(defgeneric ioblock-close (stream ioblock)
+  (:documentation
+   "May free some resources associated with the ioblock."))
+|#
+
+(defmethod ioblock-close ((stream buffered-stream-mixin) ioblock)
+  (declare (ignore ioblock)))
+
+(defmethod ioblock-force-output ((stream buffered-output-stream-mixin)
+                                   ioblock
+                                   count
+                                   finish-p)
+  (declare (ignore ioblock count finish-p)))
+
+
+
+
+(defmethod stream-read-char ((stream buffered-character-input-stream-mixin))
+  (let* ((ioblock (stream-ioblock stream t)))
+    (funcall (ioblock-read-char-function ioblock) ioblock)))
+
+(defmethod stream-read-char-no-hang ((stream buffered-character-input-stream-mixin))
+  (with-stream-ioblock-input (ioblock stream :speedy t)
+    (%ioblock-tyi-no-hang ioblock)))
+
+(defmethod stream-peek-char ((stream buffered-character-input-stream-mixin))
+  (with-stream-ioblock-input (ioblock stream :speedy t)
+    (values
+        (%ioblock-peek-char ioblock))))
+
+(defmethod stream-clear-input ((stream buffered-input-stream-mixin))
+  (with-stream-ioblock-input (ioblock stream :speedy t)
+    (values
+     (%ioblock-clear-input ioblock))))
+
+(defmethod stream-unread-char ((stream buffered-character-input-stream-mixin) char)
+  (with-stream-ioblock-input (ioblock stream :speedy t)
+    (funcall (ioblock-unread-char-function ioblock) ioblock char))
+  char)
+
+(defmethod stream-read-byte ((stream buffered-binary-input-stream-mixin))
+  (let* ((ioblock (stream-ioblock stream t)))
+    (funcall (ioblock-read-byte-function ioblock) ioblock)))
+
+(defmethod stream-read-byte ((stream basic-binary-input-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (funcall (ioblock-read-byte-function ioblock) ioblock)))
+
+(defmethod stream-eofp ((stream buffered-input-stream-mixin))
+  (with-stream-ioblock-input (ioblock stream :speedy t)
+    (values
+     (%ioblock-eofp ioblock))))
+
+(defmethod stream-eofp ((stream basic-input-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (ioblock)
+      (%ioblock-eofp ioblock))))
+
+(defmethod stream-listen ((stream buffered-input-stream-mixin))
+  (with-stream-ioblock-input (ioblock stream :speedy t)
+    (values
+     (%ioblock-listen ioblock))))
+
+(defmethod stream-listen ((stream basic-input-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (ioblock)
+      (values
+       (%ioblock-listen ioblock)))))
+
+
+(defmethod stream-write-byte ((stream buffered-binary-output-stream-mixin)
+                              byte)
+  (let* ((ioblock (stream-ioblock stream t)))
+    (funcall (ioblock-write-byte-function ioblock) ioblock byte)))
+
+(defmethod stream-write-byte ((stream basic-binary-output-stream) byte)
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (funcall (ioblock-write-byte-function ioblock) ioblock byte)))
+
+(defmethod stream-write-char ((stream buffered-character-output-stream-mixin) char)
+  (let* ((ioblock (stream-ioblock stream t)))
+    (funcall (ioblock-write-char-function ioblock) ioblock char)))
+
+(defmethod stream-write-char ((stream basic-character-output-stream) char)
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (funcall (ioblock-write-char-function ioblock) ioblock char)))
+
+
+(defmethod stream-clear-output ((stream buffered-output-stream-mixin))
+  (with-stream-ioblock-output (ioblock stream :speedy t)
+    (%ioblock-clear-output ioblock))
+  nil)
+
+(defmethod stream-clear-output ((stream basic-output-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked (ioblock)
+      (%ioblock-clear-output ioblock))
+    nil))
+
+(defmethod stream-line-column ((stream buffered-character-output-stream-mixin))
+  (let* ((ioblock (stream-ioblock stream nil)))
+    (and ioblock (ioblock-charpos ioblock))))
+
+(defmethod stream-line-column ((stream basic-character-output-stream))
+  (let* ((ioblock (basic-stream.state stream)))
+    (and ioblock (ioblock-charpos ioblock))))
+
+
+
+(defmethod stream-set-column ((stream buffered-character-output-stream-mixin)
+                              new)
+  (let* ((ioblock (stream-ioblock stream nil)))
+    (and ioblock (setf (ioblock-charpos ioblock) new))))
+
+(defmethod stream-set-column ((stream basic-character-output-stream)
+                              new)
+  (let* ((ioblock (basic-stream.state stream)))
+    (and ioblock (setf (ioblock-charpos ioblock) new))))
+
+(defmethod stream-force-output ((stream buffered-output-stream-mixin))
+  (with-stream-ioblock-output (ioblock stream :speedy t)
+    (%ioblock-force-output ioblock nil)
+    nil))
+
+(defmethod stream-force-output ((stream basic-output-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked (ioblock)
+      (%ioblock-force-output ioblock nil)
+      nil)))
+
+(defmethod maybe-stream-force-output ((stream buffered-output-stream-mixin))
+  (with-stream-ioblock-output-maybe (ioblock stream :speedy t)
+    (%ioblock-force-output ioblock nil)
+    nil))
+
+(defmethod maybe-stream-force-output ((stream basic-output-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked-maybe (ioblock)
+      (%ioblock-force-output ioblock nil)
+      nil)))
+
+(defmethod stream-finish-output ((stream buffered-output-stream-mixin))
+  (with-stream-ioblock-output (ioblock stream :speedy t)
+    (%ioblock-force-output ioblock t)
+    nil))
+
+(defmethod stream-finish-output ((stream basic-output-stream))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked (ioblock)
+      (%ioblock-force-output ioblock t)
+      nil)))
+
+
+  
+(defmethod stream-write-string ((stream buffered-character-output-stream-mixin)
+				string &optional (start 0 start-p) end)
+				
+  (with-stream-ioblock-output (ioblock stream :speedy t)
+    (if (and (typep string 'simple-string)
+	     (not start-p))
+      (funcall (ioblock-write-simple-string-function ioblock)
+                   ioblock string 0 (length string))
+      (progn
+        (setq end (check-sequence-bounds string start end))
+        (locally (declare (fixnum start end))
+          (multiple-value-bind (arr offset)
+              (if (typep string 'simple-string)
+                (values string 0)
+                (array-data-and-offset (require-type string 'string)))
+            (unless (eql 0 offset)
+              (incf start offset)
+              (incf end offset))
+            (funcall (ioblock-write-simple-string-function ioblock)
+                     ioblock arr start (the fixnum (- end start))))))))
+  string)
+
+(defmethod stream-write-string ((stream basic-character-output-stream)
+				string &optional (start 0 start-p) end)
+
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked (ioblock) 
+      (if (and (typep string 'simple-string)
+               (not start-p))
+        (values
+         (funcall (ioblock-write-simple-string-function ioblock)
+                  ioblock string 0 (length string)))
+        (progn
+          (setq end (check-sequence-bounds string start end))
+          (locally (declare (fixnum start end))
+            (multiple-value-bind (arr offset)
+                (if (typep string 'simple-string)
+                  (values string 0)
+                  (array-data-and-offset (require-type string 'string)))
+              (unless (eql 0 offset)
+                (incf start offset)
+                (incf end offset))
+              (values
+                  (funcall (ioblock-write-simple-string-function ioblock)
+                           ioblock arr start (the fixnum (- end start))))))))))
+  string)
+
+
+(defmethod stream-write-ivector ((s buffered-output-stream-mixin)
+				 iv start length)
+  (with-stream-ioblock-output (ioblock s :speedy t)
+    (values    
+        (%ioblock-out-ivect ioblock iv start length))))
+
+(defmethod stream-write-ivector ((s basic-output-stream)
+				 iv start length)
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-output-locked (ioblock)
+      (values
+          (%ioblock-out-ivect ioblock iv start length)))))
+
+
+#+bad-idea
+(defmethod stream-read-ivector ((s buffered-character-input-stream-mixin)
+				iv start nb)
+  (with-stream-ioblock-input (ioblock s :speedy t)
+    (values
+     (%ioblock-character-in-ivect ioblock iv start nb))))
+
+(defmethod stream-read-ivector ((s buffered-binary-input-stream-mixin)
+				iv start nb)
+  (with-stream-ioblock-input (ioblock s :speedy t)
+    (values
+     (%ioblock-binary-in-ivect ioblock iv start nb))))
+
+
+(defmethod stream-write-vector ((stream buffered-character-output-stream-mixin)
+				vector start end)
+  (declare (fixnum start end))
+  (if (not (typep vector 'simple-base-string))
+    (call-next-method)
+    (with-stream-ioblock-output (ioblock stream :speedy t)
+      (let* ((total (- end start)))
+	(declare (fixnum total))
+        (values
+            (funcall (ioblock-write-simple-string-function ioblock)
+                     ioblock vector start total))))))
+
+(defmethod stream-write-vector ((stream basic-character-output-stream)
+				vector start end)
+  (declare (fixnum start end))
+  (if (not (typep vector 'simple-base-string))
+    (call-next-method)
+    (let* ((ioblock (basic-stream-ioblock stream))
+           (total (- end start)))
+      (declare (fixnum total))
+      (with-ioblock-output-locked (ioblock)
+        (values
+            (funcall (ioblock-write-simple-string-function ioblock)
+                     ioblock vector start total))))))
+
+;;; bivalence: we don't actually have a "bivalent stream" class;
+;;; all actual (potentially) bivalent streams (sockets) include binary streams
+;;; before character streams in their CPLs.  That effectively means that
+;;; binary-stream methods for reading and writing sequences have to
+;;; handle character I/O in some cases.  That may slow some things down
+;;; (at least in theory), but the case where the stream's element-type
+;;; matches the sequence's element-type isn't affected.
+(defun %ioblock-binary-stream-write-vector (ioblock vector start end)
+  (declare (fixnum start end))
+  (let* ((out (ioblock-outbuf ioblock))
+         (buf (io-buffer-buffer out))
+         (written 0)
+         (limit (io-buffer-limit out))
+         (total (- end start))
+         (buftype (typecode buf)))
+    (declare (fixnum buftype written total limit))
+    (if (not (= (the fixnum (typecode vector)) buftype))
+      (if (typep vector 'string)
+        (funcall (ioblock-write-simple-string-function ioblock)
+                 ioblock
+                 vector
+                 start
+                 (- end start))
+        (do* ((i start (1+ i))
+              (wbf (ioblock-write-byte-when-locked-function ioblock))
+              (wcf (ioblock-write-char-when-locked-function ioblock)))
+             ((= i end))
+          (let ((byte (uvref vector i)))
+            (if (characterp byte)
+              (funcall wcf ioblock byte)
+              (funcall wbf ioblock byte)))))
+      (do* ((pos start (+ pos written))
+            (left total (- left written)))
+           ((= left 0))
+        (declare (fixnum pos left))
+        (setf (ioblock-dirty ioblock) t)
+        (let* ((index (io-buffer-idx out))
+               (count (io-buffer-count out))
+               (avail (- limit index)))
+          (declare (fixnum index avail count))
+          (cond
+            ((= (setq written avail) 0)
+             (%ioblock-force-output ioblock nil))
+            (t
+             (if (> written left)
+               (setq written left))
+             (%copy-ivector-to-ivector
+              vector
+              (ioblock-elements-to-octets ioblock pos)
+              buf
+              (ioblock-elements-to-octets ioblock index)
+              (ioblock-elements-to-octets ioblock written))
+             (setf (ioblock-dirty ioblock) t)
+             (incf index written)
+             (if (> index count)
+               (setf (io-buffer-count out) index))
+             (setf (io-buffer-idx out) index)
+             (if (= index  limit)
+               (%ioblock-force-output ioblock nil)))))))))
+
+(defmethod stream-write-vector ((stream buffered-binary-output-stream-mixin)
+				vector start end)
+  (with-stream-ioblock-output (ioblock stream :speedy t)
+    (%ioblock-binary-stream-write-vector ioblock vector start end)))
+
+
+(defmethod stream-write-vector ((stream basic-binary-output-stream)
+				vector start end)
+  (declare (fixnum start end))
+  (let* ((ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked (ioblock)
+      (%ioblock-binary-stream-write-vector ioblock vector start end))))
+
+
+
+(defmethod stream-read-vector ((stream basic-binary-input-stream)
+			       vector start end)
+  (declare (fixnum start end))
+  (if (typep vector 'simple-base-string)
+    (call-next-method)
+    (let* ((ioblock (basic-stream-ioblock stream)))
+      (with-ioblock-input-locked (ioblock)
+        (values
+            (%ioblock-binary-read-vector ioblock vector start end))))))
+
+(defmethod stream-read-vector ((stream buffered-character-input-stream-mixin)
+			       vector start end)
+  (declare (fixnum start end))
+  (if (not (typep vector 'simple-base-string))
+    (call-next-method)
+    (with-stream-ioblock-input (ioblock stream :speedy t)
+      (values
+       (funcall (ioblock-character-read-vector-function ioblock)
+                ioblock vector start end)))))
+
+
+
+(defmethod stream-read-vector ((stream buffered-binary-input-stream-mixin)
+			       vector start end)
+  (declare (fixnum start end))
+  (if (typep vector 'simple-base-string)
+    (call-next-method)
+    (with-stream-ioblock-input (ioblock stream :speedy t)
+      (values
+       (%ioblock-binary-read-vector ioblock vector start end)))))
+
+
+
+(defloadvar *fd-set-size*
+    (ff-call (%kernel-import target::kernel-import-fd-setsize-bytes)
+             :unsigned-fullword))
+
+(defun unread-data-available-p (fd)
+  #+(or freebsd-target windows-target)
+  (fd-input-available-p fd 0)
+  #-(or freebsd-target windows-target)
+  (rlet ((arg (* :char) (%null-ptr)))
+    (when (zerop (int-errno-call (#_ioctl fd #$FIONREAD :address arg)))
+      (let* ((avail (pref arg :long)))
+	(and (> avail 0) avail)))))
+
+;;; Read and discard any available unread input.
+(defun %fd-drain-input (fd)
+  (%stack-block ((buf 1024))
+    (do* ((avail (unread-data-available-p fd) (unread-data-available-p fd)))
+	 ((or (null avail) (eql avail 0)))
+      (do* ((max (min avail 1024) (min avail 1024)))
+	   ((zerop avail))
+	(let* ((count (fd-read fd buf max)))
+	  (if (< count 0)
+	    (return)
+	    (decf avail count)))))))
+
+(defun fd-zero (fdset)
+  (ff-call (%kernel-import target::kernel-import-do-fd-zero)
+           :address fdset
+           :void))
+
+(defun fd-set (fd fdset)
+  (ff-call (%kernel-import target::kernel-import-do-fd-set)
+           :unsigned-fullword fd
+           :address fdset
+           :void))
+
+(defun fd-clr (fd fdset)
+  (ff-call (%kernel-import target::kernel-import-do-fd-clr)
+           :unsigned-fullword fd
+           :address fdset
+           :void))
+
+(defun fd-is-set (fd fdset)
+  (not (= 0 (the fixnum (ff-call (%kernel-import target::kernel-import-do-fd-is-set)
+                                 :unsigned-fullword fd
+                                 :address fdset
+                                 :unsigned-fullword)))))
+
+(defun process-input-would-block (fd)
+  #+windows-target (declare (ignore fd))
+  #+windows-target t
+  #-windows-target
+  (if (logtest #$O_NONBLOCK (the fixnum (fd-get-flags fd)))
+    (process-input-wait fd)
+    (- #$ETIMEDOUT)))
+    
+(defun process-input-wait (fd &optional timeout)
+  "Wait until input is available on a given file-descriptor."
+  (rlet ((now :timeval))
+    (let* ((wait-end 
+            (when timeout
+              (gettimeofday now)
+              (+ (timeval->milliseconds now) timeout))))
+      (loop
+        (multiple-value-bind (win error)
+            (fd-input-available-p fd (or timeout -1))
+          (when win
+            (return (values t nil nil)))
+          (when (eql error 0)         ;timed out
+            (return (values nil t nil)))
+          ;; If it returned and a timeout was specified, check
+          ;; to see if it's been exceeded.  If so, return NIL;
+          ;; otherwise, adjust the remaining timeout.
+          ;; If there was no timeout, continue to wait forever.
+          (unless (eql error (- #$EINTR))
+            (return (values nil nil error)))
+          (when timeout
+            (gettimeofday now)
+            (setq timeout (- wait-end (timeval->milliseconds now)))
+            (if (<= timeout 0)
+              (return (values nil t nil)))))))))
+
+
+(defun process-output-would-block (fd)
+  #+windows-target (declare (ignore fd))
+  #+windows-target t
+  #-windows-target
+  (if (logtest #$O_NONBLOCK (the fixnum (fd-get-flags fd)))
+    (process-output-wait fd)
+    (- #$ETIMEDOUT)))
+
+(defun process-output-wait (fd &optional timeout)
+  "Wait until output is possible on a given file descriptor."
+  (rlet ((now :timeval))
+    (let* ((wait-end 
+            (when timeout
+              (gettimeofday now)
+              (+ (timeval->milliseconds now) timeout))))
+      (loop
+        (multiple-value-bind (win error)
+            (fd-ready-for-output-p fd (or timeout -1))
+          (when win
+            (return (values t nil nil)))
+          (when (eql error 0)
+            (return (values nil t nil)))
+          (unless (eql error (- #$EINTR))
+            (return (values nil nil error)))
+          ;; If it returned and a timeout was specified, check
+          ;; to see if it's been exceeded.  If so, return NIL;
+          ;; otherwise, adjust the remaining timeout.
+          ;; If there was no timeout, continue to wait forever.
+          (when timeout
+            (gettimeofday now)
+            (setq timeout (- wait-end (timeval->milliseconds now)))
+            (if (<= timeout 0)
+              (return (values nil t nil)))))))))
+
+
+
+(defun ticks-to-timeval (ticks tv)
+  (when ticks
+    (let* ((total-us (* ticks (/ 1000000 *ticks-per-second*))))
+      (multiple-value-bind (seconds us) (floor total-us 1000000)
+	(setf (pref tv :timeval.tv_sec) seconds
+	      (pref tv :timeval.tv_usec) us)))))
+
+(defun fd-input-available-p (fd &optional milliseconds)
+  #+windows-target
+  (case (%unix-fd-kind fd)
+    (:socket
+     (rlet ((infds #>fd_set)
+            (tv :timeval :tv_sec 0 :tv_usec 0))
+       (fd-zero infds)
+       (fd-set fd infds)
+       (when milliseconds
+         (multiple-value-bind (seconds millis)
+             (floor milliseconds 1000)
+        (setf (pref tv :timeval.tv_sec) seconds
+              (pref tv :timeval.tv_usec) (* 1000 millis))))
+       (let* ((result (#_select 1 infds (%null-ptr) (%null-ptr) (if milliseconds tv (%null-ptr)))))
+         (cond ((> result 0) (values t 0))
+               ((= result 0) (values nil 0))
+               (t (values nil (- (#_GetLastError))))))))
+    (:pipe (if (data-available-on-pipe-p fd)
+             (values t 0)
+             (if (and milliseconds (> milliseconds 0))
+               (values (process-wait-with-timeout "input-wait" milliseconds #'data-available-on-pipe-p fd) 0)
+               (values nil 0))))
+    (:file (let* ((curpos (fd-tell fd))
+                  (eofpos (%stack-block ((peofpos 8))
+                            (#_GetFileSizeEx (%int-to-ptr fd) peofpos)
+                            (%%get-unsigned-longlong peofpos 0))))
+             (values (< curpos eofpos) 0)))
+    ;;(:character-special (windows-tty-input-available-p fd milliseconds))
+
+    (t (values nil 0)))
+  #-windows-target
+  (rlet ((pollfds (:array (:struct :pollfd) 1)))
+    (setf (pref (paref pollfds (:* (:struct :pollfd)) 0) :pollfd.fd) fd
+          (pref (paref pollfds (:* (:struct :pollfd)) 0) :pollfd.events) #$POLLIN)
+    (let* ((res (int-errno-call (#_poll pollfds 1 (or milliseconds -1)))))
+      (declare (fixnum res))
+      (values (> res 0) res))))
+
+
+(defun fd-ready-for-output-p (fd &optional milliseconds)
+  #+windows-target
+  (case (%unix-fd-kind fd)
+    (:socket
+     (rlet ((tv :timeval :tv_sec 0 :tv_usec 0)
+            (outfds :fd_set))
+       (fd-zero outfds)
+       (fd-set fd outfds)
+       (when milliseconds
+         (multiple-value-bind (seconds millis)
+             (floor milliseconds 1000)
+           (setf (pref tv #>timeval.tv_sec) seconds
+                 (pref tv #>timeval.tv_usec) (* millis 1000))))
+       (let* ((res (#_select 1 (%null-ptr) outfds (%null-ptr) (if milliseconds tv (%null-ptr)))))
+         (cond ((> res 0) (values t 0))
+               ((= res 0) (values nil 0))
+               (t (values 0 (- (#_GetLastError))))))))
+    (t (values t 0)))
+  #-windows-target
+  (rlet ((pollfds (:array (:struct :pollfd) 1)))
+    (setf (pref (paref pollfds (:* (:struct :pollfd)) 0) :pollfd.fd) fd
+          (pref (paref pollfds (:* (:struct :pollfd)) 0) :pollfd.events) #$POLLOUT)
+    (let* ((res (int-errno-call (#_poll pollfds 1 (or milliseconds -1)))))
+      (declare (fixnum res))
+      (values (> res 0)  res))))
+
+
+
+;;; FD-streams, built on top of the ioblock mechanism.
+(defclass fd-stream (buffered-stream-mixin fundamental-stream) ())
+
+
+(defmethod select-stream-advance-function ((s symbol) direction)
+  (select-stream-advance-function (find-class s) direction))
+
+(defmethod select-stream-advance-function ((c class) direction)
+  (select-stream-advance-function (class-prototype c) direction))
+
+(defmethod select-stream-advance-function ((s fd-stream) (direction t))
+  'fd-stream-advance)
+
+(defmethod select-stream-advance-function ((s basic-stream) (direction t))
+  'fd-stream-advance)
+
+
+(defmethod select-stream-force-output-function ((s symbol) direction)
+  (select-stream-force-output-function (find-class s) direction))
+
+(defmethod select-stream-force-output-function ((c class) direction)
+  (select-stream-force-output-function (class-prototype c) direction))
+
+(defmethod select-stream-force-output-function ((f fd-stream) (direction t))
+  'fd-stream-force-output)
+
+(defmethod select-stream-force-output-function ((f basic-stream) (direction t))
+  'fd-stream-force-output)
+
+(defmethod print-object ((s fd-stream) out)
+  (print-unreadable-object (s out :type t :identity t)
+    (let* ((ioblock (stream-ioblock s nil))
+           (fd (and ioblock (ioblock-device ioblock)))
+           (encoding (and ioblock (encoding-name (ioblock-encoding ioblock)))))
+      (if fd
+        (format out "~s (~a/~d)" encoding (%unix-fd-kind fd) fd)
+        (format out "~s" :closed)))))
+
+(defclass fd-input-stream (fd-stream buffered-input-stream-mixin)
+    ())
+
+(defclass fd-output-stream (fd-stream buffered-output-stream-mixin)
+    ())
+
+(defclass fd-io-stream (fd-stream buffered-io-stream-mixin)
+    ())
+
+(defclass fd-character-input-stream (fd-input-stream
+                                     buffered-character-input-stream-mixin)
+    ())
+
+(defclass fd-character-output-stream (fd-output-stream
+                                      buffered-character-output-stream-mixin)
+    ())
+
+(defclass fd-character-io-stream (fd-io-stream
+                                  buffered-character-io-stream-mixin)
+    ())
+
+(defclass fd-binary-input-stream (fd-input-stream
+                                  buffered-binary-input-stream-mixin)
+    ())
+
+(defclass fd-binary-output-stream (fd-output-stream
+                                   buffered-binary-output-stream-mixin)
+    ())
+
+(defclass fd-binary-io-stream (fd-io-stream buffered-binary-io-stream-mixin)
+    ())
+
+(defun fd-stream-advance (s ioblock read-p)
+  (let* ((fd (ioblock-device ioblock))
+         (buf (ioblock-inbuf ioblock))
+         (bufptr (io-buffer-bufptr buf))
+         (size (io-buffer-size buf))
+         (avail nil))
+    (setf (io-buffer-idx buf) 0
+          (io-buffer-count buf) 0
+          (ioblock-eof ioblock) nil)
+      (when (or read-p (setq avail (stream-listen s)))
+        (unless avail
+          (let* ((deadline (ioblock-deadline ioblock))
+                 (timeout
+                  (if deadline
+                    (milliseconds-until-deadline deadline ioblock)
+                    (ioblock-input-timeout ioblock))))
+            (when timeout
+              (multiple-value-bind (win timedout error)
+                  (process-input-wait fd timeout)
+                (unless win
+                  (if timedout
+                    (error (if deadline
+                             'communication-deadline-expired
+                             'input-timeout)
+                           :stream s)
+                    (stream-io-error s (- error) "read")))))))
+        (let* ((n (with-eagain fd :input
+		    (fd-read fd bufptr size))))
+          (declare (fixnum n))
+          (if (< n 0)
+            (stream-io-error s (- n) "read")
+            (if (> n 0)
+              (setf (io-buffer-count buf)
+		    (ioblock-octets-to-elements ioblock n))
+              (progn (setf (ioblock-eof ioblock) t)
+                     nil)))))))
+
+(defun fd-stream-eofp (s ioblock)
+  (declare (ignore s))
+  (ioblock-eof ioblock))
+  
+(defun fd-stream-listen (s ioblock)
+  (declare (ignore s))
+  (unread-data-available-p (ioblock-device ioblock)))
+
+(defun fd-stream-close (s ioblock)
+  (cancel-terminate-when-unreachable s)
+  (when (ioblock-dirty ioblock)
+    (stream-force-output s))
+  (let* ((fd (ioblock-device ioblock)))
+    (when fd
+      (setf (ioblock-device ioblock) nil)
+      (if (>= fd 0) (fd-close fd)))))
+
+(defun fd-stream-force-output (s ioblock count finish-p)
+  (when (or (ioblock-dirty ioblock) finish-p)
+    (setf (ioblock-dirty ioblock) nil)
+    (let* ((fd (ioblock-device ioblock))
+	   (io-buffer (ioblock-outbuf ioblock))
+	   (buf (%null-ptr))
+	   (octets-to-write (ioblock-elements-to-octets ioblock count))
+	   (octets octets-to-write))
+      (declare (fixnum octets))
+      (declare (dynamic-extent buf))
+      (%setf-macptr buf (io-buffer-bufptr io-buffer))
+      (setf (io-buffer-idx io-buffer) 0
+	    (io-buffer-count io-buffer) 0)
+      (do* ()
+	   ((= octets 0)
+	    (when finish-p
+	      (case (%unix-fd-kind fd)
+		(:file (fd-fsync fd))))
+	    octets-to-write)
+        (let* ((deadline (ioblock-deadline ioblock))
+               (timeout
+                (if deadline
+                  (milliseconds-until-deadline deadline ioblock)
+                  (ioblock-output-timeout ioblock))))
+          (when timeout
+            (multiple-value-bind (win timedout error)
+                (process-output-wait fd timeout)
+              (unless win
+                (if timedout
+                  (error (if deadline
+                           'communication-deadline-expired
+                           'output-timeout)
+                         :stream s)
+                  (stream-io-error s (- error) "write"))))))
+	(let* ((written (with-eagain fd :output
+			  (fd-write fd buf octets))))
+	  (declare (fixnum written))
+	  (if (< written 0)
+	    (stream-io-error s (- written) "write"))
+	  (decf octets written)
+	  (unless (zerop octets)
+	    (%incf-ptr buf written)))))))
+
+(defmethod stream-read-line ((s buffered-input-stream-mixin))
+   (with-stream-ioblock-input (ioblock s :speedy t)
+     (funcall (ioblock-read-line-function ioblock) ioblock)))
+
+(defmethod stream-clear-input ((s fd-input-stream))
+  (call-next-method)
+  (with-stream-ioblock-input (ioblock s :speedy t)
+    (let* ((fd (ioblock-device ioblock)))
+      (when fd (%fd-drain-input fd)))))
+
+(defmethod select-stream-class ((class (eql 'fd-stream)) in-p out-p char-p)
+  (if char-p
+    (if in-p
+      (if out-p
+	'fd-character-io-stream
+	'fd-character-input-stream)
+      'fd-character-output-stream)
+    (if in-p
+      (if out-p
+	'fd-binary-io-stream
+	'fd-binary-input-stream)
+      'fd-binary-output-stream)))
+
+(defstruct (input-selection (:include dll-node))
+  (package nil :type (or null string package))
+  (source-file nil :type (or null string pathname))
+  (string-stream nil :type (or null string-input-stream)))
+
+(defstruct (input-selection-queue (:include locked-dll-header)))
+
+(defclass selection-input-stream (fd-character-input-stream)
+    ((package :initform nil :reader selection-input-stream-package)
+     (pathname :initform nil :reader selection-input-stream-pathname)
+     (peer-fd  :reader selection-input-stream-peer-fd)))
+
+(defmethod select-stream-class ((class (eql 'selection-input-stream))
+                                in-p out-p char-p)
+  (if (and in-p char-p (not out-p))
+    'selection-input-stream
+    (error "Can't create that type of stream.")))
+
+(defun make-selection-input-stream (fd &key peer-fd encoding)
+  (let* ((s (make-fd-stream fd
+                            :class 'selection-input-stream
+                            :sharing :lock
+                            :encoding encoding)))
+    (setf (slot-value s 'peer-fd) peer-fd)
+    s))
+
+
+;;; Very simple protocol:
+;;; ^ppackage-name#\newline
+;;; ^vpathname#\newline
+;;; ^q quotes next character
+;;; else raw data
+(defmethod stream-read-char ((s selection-input-stream))
+  (with-slots (package pathname) s
+    (let* ((quoted nil))
+      (loop
+        (let* ((ch (call-next-method)))
+          (if quoted
+            (return ch)
+            (case ch
+              (#\^p (setq package nil)
+                    (let* ((p (read-line s nil nil)))
+                      (unless (zerop (length p))
+                        (setq package p))))
+              (#\^v (setq pathname nil)
+                    (let* ((p (read-line s nil nil)))
+                      (unless (zerop (length p))
+                        (setq pathname p))))
+              (#\^q (setq quoted t))
+              (t (return ch)))))))))
+
+(defmethod stream-peek-char ((s selection-input-stream))
+  (let* ((ch (stream-read-char s)))
+    (unless (eq ch :eof)
+      (stream-unread-char s ch))
+    ch))
+
+(defmethod stream-read-line ((s selection-input-stream))
+  (generic-read-line s))
+
+(defmethod stream-read-list ((stream selection-input-stream)
+			     list count)
+  (generic-character-read-list stream list count))
+
+(defmethod stream-read-vector ((stream selection-input-stream)
+			       vector start end)
+  (generic-character-read-vector stream vector start end))
+
+
+;;;File streams.
+
+(let* ((open-file-streams ())
+       (open-file-streams-lock (make-lock)))
+  (defun open-file-streams ()
+    (with-lock-grabbed (open-file-streams-lock)
+      (copy-list open-file-streams)))
+  (defun note-open-file-stream (f)
+    (with-lock-grabbed (open-file-streams-lock)
+      (push f open-file-streams))
+    t)
+  (defun remove-open-file-stream (f)
+    (with-lock-grabbed (open-file-streams-lock)
+      (setq open-file-streams (nremove f open-file-streams)))
+    t)
+  (defun clear-open-file-streams ()
+    (with-lock-grabbed (open-file-streams-lock)
+      (setq open-file-streams nil))))
+            
+
+(defun open (filename &key (direction :input)
+                      (element-type 'base-char)
+                      (if-exists (if (eq (pathname-version filename) :newest)
+                                   :new-version
+                                   :error))
+                      (if-does-not-exist (cond ((eq direction :probe)
+                                                nil)
+                                               ((or (eq direction :input)
+                                                    (eq if-exists :overwrite)
+                                                    (eq if-exists :append))
+                                                :error)
+                                               (t :create)))
+                      (external-format :default)
+		      (class 'file-stream)
+                      (sharing :private)
+                      (basic t))
+  "Return a stream which reads from or writes to FILENAME.
+  Defined keywords:
+   :DIRECTION - one of :INPUT, :OUTPUT, :IO, or :PROBE
+   :ELEMENT-TYPE - the type of object to read or write, default BASE-CHAR
+   :IF-EXISTS - one of :ERROR, :NEW-VERSION, :RENAME, :RENAME-AND-DELETE,
+                       :OVERWRITE, :APPEND, :SUPERSEDE or NIL
+   :IF-DOES-NOT-EXIST - one of :ERROR, :CREATE or NIL
+  See the manual for details."
+  (loop
+    (restart-case
+      (return
+	(make-file-stream filename
+			  direction
+			  element-type
+			  if-exists
+			  if-does-not-exist
+			  class
+			  external-format
+                          sharing
+                          basic))
+      (retry-open ()
+                  :report (lambda (stream) (format stream "Retry opening ~s" filename))
+                  nil))))
+
+
+
+
+
+(defun gen-file-name (path)
+  (let* ((date (file-write-date path))
+         (tem-path (merge-pathnames (make-pathname :name (%integer-to-string date) :type "tem" :defaults nil) path)))
+    (loop
+      (when (%create-file tem-path :if-exists nil) (return tem-path))      
+      (setf (%pathname-name tem-path) (%integer-to-string (setq date (1+ date)))))))
+
+(defun probe-file-x (path)
+  (%probe-file-x (native-translated-namestring path)))
+
+(defun file-length (stream)
+  (typecase stream
+    ;; Don't use an OR type here
+    (file-stream (stream-length stream))
+    (synonym-stream (file-length
+		     (symbol-value (synonym-stream-symbol stream))))
+    (broadcast-stream (let* ((last (last-broadcast-stream stream)))
+			(if last
+			  (file-length last)
+			  0)))
+    (otherwise (report-bad-arg stream 'file-stream))))
+  
+(defun file-position (stream &optional position)
+  (when position
+    (if (eq position :start)
+      (setq position 0)
+      (if (eq position :end)
+	(setq position (file-length stream))
+	(unless (typep position 'unsigned-byte)
+	  (report-bad-arg position '(or
+				     null
+				     (eql :start)
+				     (eql :end)
+				     unsigned-byte))))))
+  (stream-position stream position))
+
+
+(defun %request-terminal-input ()
+  (let* ((shared-resource
+	  (if (typep *terminal-io* 'two-way-stream)
+	    (input-stream-shared-resource
+	     (two-way-stream-input-stream *terminal-io*)))))
+    (if shared-resource (%acquire-shared-resource shared-resource t))))
+
+
+
+
+(defun %%yield-terminal-to (&optional process)
+  (let* ((stream (if (typep *terminal-io* 'synonym-stream)
+                   (symbol-value (synonym-stream-symbol *terminal-io*))
+                   *terminal-io*))
+         (shared-resource
+	  (if (typep stream 'two-way-stream)
+	    (input-stream-shared-resource
+	     (two-way-stream-input-stream stream)))))
+    (when shared-resource (%yield-shared-resource shared-resource process))))
+
+(defun %restore-terminal-input (&optional took-it)
+  (let* ((shared-resource
+	  (if took-it
+	    (if (typep *terminal-io* 'two-way-stream)
+	      (input-stream-shared-resource
+	       (two-way-stream-input-stream *terminal-io*))))))
+    (when shared-resource
+      (%release-shared-resource shared-resource))))
+
+;;; Initialize the global streams
+;;; These are defparameters because they replace the ones that were in l1-init
+;;; while bootstrapping.
+
+(defparameter *terminal-io* nil "terminal I/O stream")
+(defparameter *debug-io* nil "interactive debugging stream")
+(defparameter *query-io* nil "query I/O stream")
+(defparameter *error-output* nil "error output stream")
+(defparameter *standard-input* nil "default input stream")
+(defparameter *standard-output* nil "default output stream")
+(defparameter *trace-output* nil "trace output stream")
+
+(proclaim '(stream 
+          *query-io* *debug-io* *error-output* *standard-input* 
+          *standard-output* *trace-output*))
+
+;;; Interaction with the REPL.  READ-TOPLEVEL-FORM should return 3
+;;; values: a form, a (possibly null) pathname, and a boolean that
+;;; indicates whether or not the result(s) of evaluating the form
+;;; should be printed.  (The last value has to do with how selections
+;;; that contain multiple forms are handled; see *VERBOSE-EVAL-SELECTION*
+;;; and the SELECTION-INPUT-STREAM method below.)
+
+(defmethod read-toplevel-form ((stream synonym-stream) &rest keys)
+  (apply #'read-toplevel-form (symbol-value (synonym-stream-symbol stream)) keys))
+
+(defmethod read-toplevel-form ((stream two-way-stream) &rest keys)
+  (if (typep stream 'echo-stream)
+    (call-next-method)
+    (apply #'read-toplevel-form (two-way-stream-input-stream stream) keys)))
+
+(defmethod read-toplevel-form :after ((stream echoing-two-way-stream) &key &allow-other-keys)
+  (stream-set-column (two-way-stream-output-stream stream) 0))
+
+(defmethod read-toplevel-form ((stream input-stream) &key eof-value file-name start-offset map)
+  (loop
+    (let* ((*in-read-loop* nil)
+           (first-char (peek-char t stream nil eof-value))
+           (form
+            (let ((*read-suppress* nil))
+              (cond ((eq first-char #\:)
+                     (read-command-or-keyword stream eof-value))
+                    ((eq first-char eof-value) eof-value)
+                    (t (multiple-value-bind (form note)
+			   (read-recording-source stream :eofval eof-value
+						  :file-name file-name
+						  :start-offset start-offset
+						  :map map
+						  :save-source-text t)
+			 (setq *loading-toplevel-location* note)
+			 form))))))
+      (if (eq form eof-value)
+        (return (values form nil t))
+        (progn
+          (let ((ch))                   ;Trim whitespace
+            (while (and (listen stream)
+                        (setq ch (read-char stream nil nil))
+                        (whitespacep cH))
+              (setq ch nil))
+            (when ch (unread-char ch stream)))
+          (when *listener-indent* 
+            (write-char #\space stream)
+            (write-char #\space stream))
+          (return (values (process-single-selection form) nil t)))))))
+
+(defparameter *verbose-eval-selection* nil
+  "When true, the results of evaluating all forms in an input selection
+are printed.  When false, only the results of evaluating the last form
+are printed.")
+
+(defmethod read-toplevel-form ((stream selection-input-stream)
+                               &key eof-value &allow-other-keys)
+  (if (eq (stream-peek-char stream) :eof)
+    (values eof-value nil t)
+    (let* ((*package* *package*)
+           (pkg-name (selection-input-stream-package stream)))
+      (when pkg-name (setq *package* (pkg-arg pkg-name)))
+      (let* ((form (call-next-method))
+             (last-form-in-selection (not (listen stream))))
+        (values form
+                (selection-input-stream-pathname stream)
+                (or last-form-in-selection *verbose-eval-selection*))))))
+
+
+(defun (setf %ioblock-external-format) (ef ioblock)
+  (let* ((encoding (get-character-encoding (external-format-character-encoding ef)))
+         (line-termination (external-format-line-termination ef)))
+    (when (eq encoding (get-character-encoding nil))
+      (setq encoding nil))
+    (setq line-termination (cdr (assoc line-termination
+                                       *canonical-line-termination-conventions*)))
+    (setf (ioblock-encoding ioblock) encoding)
+    (when (ioblock-inbuf ioblock)
+      (setup-ioblock-input ioblock t (ioblock-element-type ioblock) (ioblock-sharing ioblock) encoding line-termination))
+    (when (ioblock-outbuf ioblock)
+      (setup-ioblock-output ioblock t (ioblock-element-type ioblock) (ioblock-sharing ioblock) encoding line-termination))
+    ef))
+
+(defmethod stream-external-format ((s basic-character-stream))
+  (%ioblock-external-format (basic-stream-ioblock s)))
+
+(defmethod (setf stream-external-format) (new (s basic-character-stream))
+  (setf (%ioblock-external-format (basic-stream-ioblock s))
+        (normalize-external-format (stream-domain s) new)))
+
+(defmethod stream-external-format ((s buffered-stream-mixin))
+  (%ioblock-external-format (stream-ioblock s t)))
+
+(defmethod (setf stream-external-format) (new (s buffered-stream-mixin))
+  (setf (%ioblock-external-format (stream-ioblock s t))
+        (normalize-external-format (stream-domain s) new)))
+
+(defmethod stream-input-timeout ((s basic-input-stream))
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-input-locked (ioblock)
+      (let* ((timeout (ioblock-input-timeout ioblock)))
+        (when timeout
+          (values (floor timeout 1000.0)))))))
+
+(defmethod (setf stream-input-timeout) (new (s basic-input-stream))
+  (setq new (check-io-timeout new))
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-input-locked (ioblock)
+      (setf (ioblock-input-timeout ioblock)
+            (if new (round (* new 1000))))
+      new)))
+
+(defmethod stream-output-timeout ((s basic-output-stream))
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-output-locked (ioblock)
+      (let* ((timeout (ioblock-output-timeout ioblock)))
+        (when timeout
+          (values (floor timeout 1000.0)))))))
+
+(defmethod (setf stream-output-timeout) (new (s basic-output-stream))
+  (setq new (check-io-timeout new))
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-output-locked (ioblock)
+      (setf (ioblock-output-timeout ioblock)
+            (if new (round (* new 1000))))
+      new)))
+
+(defmethod stream-deadline ((s basic-output-stream))
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-output-locked (ioblock)
+      (ioblock-deadline ioblock))))
+ 
+(defmethod (setf stream-deadline) (new (s basic-output-stream))
+  (let* ((ioblock (basic-stream-ioblock s)))
+    (with-ioblock-output-locked (ioblock)
+      (setf (ioblock-deadline ioblock) new)
+      new)))
+
+
+
+(defmethod stream-input-timeout ((s buffered-input-stream-mixin))
+  (let* ((ioblock (stream-ioblock s t)))
+    (with-ioblock-input-locked (ioblock)
+      (let* ((timeout (ioblock-input-timeout ioblock)))
+        (when timeout
+          (values (floor timeout 1000.0)))))))
+
+(defmethod (setf stream-input-timeout) (new (s buffered-input-stream-mixin))
+  (setq new (check-io-timeout new))
+  (let* ((ioblock (stream-ioblock s t)))
+    (with-ioblock-input-locked (ioblock)
+      (setf (ioblock-input-timeout ioblock)
+            (if new (round (* new 1000))))
+      new)))
+
+(defmethod stream-output-timeout ((s buffered-output-stream-mixin))
+  (let* ((ioblock (stream-ioblock s t)))
+    (with-ioblock-output-locked (ioblock)
+      (let* ((timeout (ioblock-output-timeout ioblock)))
+        (when timeout
+          (values (floor timeout 1000.0)))))))
+
+(defmethod (setf stream-output-timeout) (new (s buffered-output-stream-mixin))
+  (setq new (check-io-timeout new))
+  (let* ((ioblock (stream-ioblock s t)))
+    (with-ioblock-output-locked (ioblock)
+      (setf (ioblock-output-timeout ioblock)
+            (if new (round (* new 1000))))
+      new)))
+
+(defmethod stream-deadline ((s buffered-output-stream-mixin))
+  (let* ((ioblock (stream-ioblock s t)))
+    (with-ioblock-output-locked (ioblock)
+      (ioblock-deadline ioblock))))
+ 
+(defmethod (setf stream-deadline) (new (s buffered-output-stream-mixin))
+  (let* ((ioblock (stream-ioblock s t)))
+    (with-ioblock-output-locked (ioblock)
+      (setf (ioblock-deadline ioblock) new)
+      new)))
+
+
+(defmethod select-stream-untyi-function ((s symbol) direction)
+  (select-stream-untyi-function (find-class s) direction))
+
+(defmethod select-stream-untyi-function ((c class) direction)
+  (select-stream-untyi-function (class-prototype c) direction))
+
+(defmethod select-stream-untyi-function ((s fd-stream) (direction t))
+  '%ioblock-untyi)
+
+(defmethod select-stream-untyi-function ((s basic-stream) (direction t))
+  '%ioblock-untyi)
+
+; end of L1-streams.lisp
Index: /branches/new-random/level-1/l1-symhash.lisp
===================================================================
--- /branches/new-random/level-1/l1-symhash.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-symhash.lisp	(revision 13309)
@@ -0,0 +1,865 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(declaim (special %all-packages%))
+(declaim (list %all-package%))
+(declaim (type package *package*))
+
+
+
+(defun dereference-base-string-or-symbol (s)
+  (if (symbolp s)
+    (dereference-base-string (symbol-name s))
+    (dereference-base-string s)))
+
+(defun dereference-base-string-or-symbol-or-char (s)
+  (if (typep s 'character)
+    (values (make-string 1 :element-type 'base-char :initial-element s) 0 1)
+    (dereference-base-string-or-symbol s)))
+
+
+(defun %string= (string1 string2 start1 end1)
+  (declare (optimize (speed 3) (safety 0))
+           (fixnum start1 end1))
+  (when (eq (length string2) (%i- end1 start1))
+    (do* ((i start1 (1+ i))
+          (j 0 (1+ j)))
+         ((>= i end1))
+      (declare (fixnum i j))
+      (when (not (eq (%scharcode string1 i)(%scharcode string2 j)))
+        (return-from %string= nil)))
+    t))
+
+
+
+
+(defun export (sym-or-syms &optional (package *package*))
+  "Exports SYMBOLS from PACKAGE, checking that no name conflicts result."
+  (setq package (pkg-arg package))
+  (if (atom sym-or-syms)
+    (let* ((temp (cons sym-or-syms nil)))
+      (declare (dynamic-extent temp))
+      (export temp package))
+    (progn
+      (dolist (sym sym-or-syms)
+        (unless (symbolp sym) (return (setq sym-or-syms  (mapcar #'(lambda (s) (require-type s 'symbol)) sym-or-syms)))))
+      ;; First, see if any packages used by the package being
+      ;; "exported from" already contain a distinct non-shadowing
+      ;; symbol that conflicts with one of those that we're trying to
+      ;; export.
+      (let* ((conflicts (check-export-conflicts sym-or-syms package)))
+        (if conflicts
+          (progn 
+            (resolve-export-conflicts conflicts package)
+            (export sym-or-syms package))
+          (let* ((missing nil) (need-import nil))
+            (dolist (s sym-or-syms) 
+              (multiple-value-bind (foundsym foundp) (%findsym (symbol-name s) package)
+                (if (not (and foundp (eq s foundsym)))
+                  (push s missing)
+                  (if (eq foundp :inherited)
+                    (push s need-import)))))
+            (when missing
+              (cerror "Import missing symbols before exporting them from ~S."
+                      'export-requires-import
+                      :package  package
+                      :to-be-imported missing)
+              (import missing package))
+            (if need-import (import need-import package))
+            ; Can't lose now: symbols are all directly present in package.
+            ; Ensure that they're all external; do so with interrupts disabled
+            (without-interrupts
+             (let* ((etab (pkg.etab package))
+                    (ivec (car (pkg.itab package))))
+               (dolist (s sym-or-syms t)
+                 (multiple-value-bind (foundsym foundp internal-offset)
+                                      (%findsym (symbol-name s) package)
+                   (when (eq foundp :internal)
+                     (setf (%svref ivec internal-offset) (package-deleted-marker))
+                     (let* ((pname (symbol-name foundsym)))
+                       (%htab-add-symbol foundsym etab (nth-value 2 (%get-htab-symbol pname (length pname) etab)))))))))))))))
+
+(defun check-export-conflicts (symbols package)
+  (let* ((conflicts nil))
+    (with-package-lock (package)
+      (dolist (user (pkg.used-by package) conflicts)
+        (with-package-lock (user)
+          (dolist (s symbols)
+            (multiple-value-bind (foundsym foundp) (%findsym (symbol-name s) user)
+              (if (and foundp (neq foundsym s) (not (memq foundsym (pkg.shadowed user))))
+                (push (list (eq foundp :inherited) s user foundsym) conflicts)))))))))
+  
+
+
+(defun keywordp (x)
+  "Return true if Object is a symbol in the \"KEYWORD\" package."
+  (and (symbolp x) (eq (symbol-package x) *keyword-package*)))
+
+;;;No type/range checking.  For DO-SYMBOLS and friends.
+(defun %htab-symbol (array index)
+  (let* ((sym (%svref array index)))
+    (if (symbolp sym)
+      (values (%symptr->symbol sym) t)
+      (values nil nil))))
+
+(defun find-all-symbols (name)
+  "Return a list of all symbols in the system having the specified name."
+  (let* ((syms ())
+         (pname (ensure-simple-string (string name)))
+         (len (length pname)))
+    (with-package-list-read-lock
+        (dolist (p %all-packages% syms)
+          (with-package-lock (p)
+            (multiple-value-bind (sym foundp) (%find-package-symbol pname p len)
+              (if foundp (pushnew sym syms :test #'eq))))))))
+      
+
+(defun list-all-packages ()
+  "Return a list of all existing packages."
+  (with-package-list-read-lock (copy-list %all-packages%)))
+
+(defun rename-package (package new-name &optional new-nicknames)
+  "Changes the name and nicknames for a package."
+  (setq package (pkg-arg package)
+        new-name (ensure-simple-string (string new-name)))
+  (with-package-lock (package)
+    (let* ((names (pkg.names package)))
+      (declare (type cons names))
+      (dolist (n names)
+        (let* ((ref (register-package-ref n)))
+          (setf (package-ref.pkg ref) nil)))
+      (rplaca names (new-package-name new-name package))
+      (let* ((ref (register-package-ref (car names))))
+        (setf (package-ref.pkg ref) package))
+      (rplacd names nil))
+    (%add-nicknames new-nicknames package)))
+
+;;; Someday, this should become LISP:IN-PACKAGE.
+(defun old-in-package (name &key 
+                        nicknames 
+                        (use nil use-p) 
+                        (internal-size 60)
+                        (external-size 10))
+  (let ((pkg (find-package (setq name (string name)))))
+    (if pkg
+      (progn
+        (use-package use pkg)
+        (%add-nicknames nicknames pkg))
+      (setq pkg
+            (make-package name 
+                          :nicknames nicknames
+                          :use (if use-p use *make-package-use-defaults*)
+                          :internal-size internal-size
+                          :external-size external-size)))
+    (setq *package* pkg)))
+
+
+(defvar *make-package-use-defaults* '("COMMON-LISP" "CCL"))
+
+;;; On principle, this should get exported here.  Unfortunately, we
+;;; can't execute calls to export quite yet.
+
+
+(defun make-package (name &key
+                          nicknames
+                          (use *make-package-use-defaults*)
+                          (internal-size 60)
+                          (external-size 10))
+  "Make a new package having the specified NAME, NICKNAMES, and 
+  USE list. :INTERNAL-SYMBOLS and :EXTERNAL-SYMBOLS are
+  estimates for the number of internal and external symbols which
+  will ultimately be present in the package. The default value of
+  USE is implementation-dependent, and in this implementation
+  it is NIL."
+  (setq internal-size (require-type internal-size 'fixnum)
+        external-size (require-type external-size 'fixnum))
+  (let* ((pkg-name (new-package-name name))
+         (pkg (gvector :package 
+                       (%new-package-hashtable internal-size)
+                       (%new-package-hashtable external-size)
+                       nil
+                       nil
+                       (list pkg-name)
+                       nil
+                       (make-read-write-lock)
+                       nil)))
+    (let* ((ref (register-package-ref pkg-name)))
+      (setf (package-ref.pkg ref) pkg))
+    (use-package use pkg)
+    (%add-nicknames nicknames pkg)
+    (with-package-list-write-lock
+        (push pkg %all-packages%))
+    pkg))
+
+(defun new-package-name (name &optional package)
+  (do* ((prompt "Enter package name to use instead of ~S ."))
+       ((let* ((found (find-package (setq name (ensure-simple-string (string name))))))
+          (or (not found)
+              (eq package found)))
+        name)
+    (restart-case (%error "Package name ~S is already in use." (list name) (%get-frame-ptr))
+      (new-name (new-name)
+                :report (lambda (s) (format s prompt name))
+                :interactive 
+                (lambda () 
+                  (list (block nil (catch-cancel (return (get-string-from-user
+                                                          (format nil prompt name))))
+                               nil)))
+                (if new-name (setq name new-name))))))
+       
+(defun new-package-nickname (name package)
+  (setq name (string name))
+  (let* ((other (find-package name))
+         (prompt "Enter package name to use instead of ~S ."))
+    (if other
+      (unless (eq other package)
+        (let* ((conflict-with-proper-name (string= (package-name other) name))
+               (condition (make-condition 'package-name-conflict-error
+                                          :package package
+                                          :format-arguments (list name other)
+                                          :format-control (%str-cat "~S is already "
+                                                                   (if conflict-with-proper-name
+                                                                     "the "
+                                                                     "a nick")
+                                                                   "name of ~S."))))
+          (restart-case (%error condition nil (%get-frame-ptr))
+            (continue ()
+                      :report (lambda (s) (format s "Don't make ~S a nickname for ~S" name package)))
+            (new-name (new-name)
+                      :report (lambda (s) (format s prompt name))
+                      :interactive 
+                      (lambda () 
+                        (list (block nil (catch-cancel (return (get-string-from-user
+                                                                (format nil prompt name))))
+                                     nil)))
+                      (if new-name (new-package-nickname new-name package)))
+            (remove-conflicting-nickname ()
+                                         :report (lambda (s)
+                                                   (format s "Remove conflicting-nickname ~S from ~S." name other))
+                                         :test (lambda (&rest ignore) (declare (ignore ignore)) (not conflict-with-proper-name))
+                                         (rplacd (pkg.names other)
+                                                 (delete name (cdr (pkg.names other)) :test #'string=))
+                                         name))))
+      name)))
+
+(defun %add-nicknames (nicknames package)
+  (let ((names (pkg.names package)))
+    (dolist (name nicknames package)
+      (let* ((ok-name (new-package-nickname name package)))
+        (when ok-name
+          (let* ((ref (register-package-ref ok-name)))
+            (setf (package-ref.pkg ref) package)
+            (push ok-name (cdr names))))))))
+
+(defun find-symbol (string &optional package)
+  "Return the symbol named STRING in PACKAGE. If such a symbol is found
+  then the second value is :INTERNAL, :EXTERNAL or :INHERITED to indicate
+  how the symbol is accessible. If no symbol is found then both values
+  are NIL."
+  (multiple-value-bind (sym flag)
+      (%findsym (ensure-simple-string string) (pkg-arg (or package *package*)))
+    (values sym flag)))
+
+(defun %pkg-ref-find-symbol (string ref)
+  (multiple-value-bind (sym flag)
+      (%findsym (ensure-simple-string string)
+                (or (package-ref.pkg ref)
+                    (%kernel-restart $xnopkg (package-ref.name ref))))
+    (values sym flag)))
+    
+;;; Somewhat saner interface to %find-symbol
+(defun %findsym (string package)
+  (%find-symbol string (length string) package))
+
+(eval-when (:compile-toplevel)
+  (declaim (inline %intern)))
+
+(defun %intern (str package)
+  (setq str (ensure-simple-string str))
+  (with-package-lock (package)
+   (multiple-value-bind (symbol where internal-offset external-offset) 
+                        (%find-symbol str (length str) package)
+     (if where
+       (values symbol where)
+       (values (%add-symbol str package internal-offset external-offset) nil)))))
+
+
+(defun intern (str &optional (package *package*))
+  "Return a symbol in PACKAGE having the specified NAME, creating it
+  if necessary."
+  (%intern str (pkg-arg package)))
+
+(defun %pkg-ref-intern (str ref)
+  (%intern str (or (package-ref.pkg ref)
+                   (%kernel-restart $xnopkg (package-ref.name ref)))))
+
+(defun unintern (symbol &optional (package *package*))
+  "Makes SYMBOL no longer present in PACKAGE. If SYMBOL was present
+  then T is returned, otherwise NIL. If PACKAGE is SYMBOL's home
+  package, then it is made uninterned."
+  (setq package (pkg-arg package))
+  (setq symbol (require-type symbol 'symbol))
+  (multiple-value-bind (foundsym table index) (%find-package-symbol (symbol-name symbol) package)
+    (when (and table (eq symbol foundsym))
+      (when (memq symbol (pkg.shadowed package))
+        ;; A conflict is possible if more than one distinct
+        ;; similarly-named external symbols exist in the packages used
+        ;; by this one.  Grovel around looking for such conflicts; if
+        ;; any are found, signal an error (via %kernel-restart) which
+        ;; offers to either shadowing-import one of the conflicting
+        ;; symbols into the current package or abandon the attempt to
+        ;; unintern in the first place.
+        (let* ((first nil)
+               (first-p nil)
+               (name (symbol-name symbol))
+               (len (length name))
+               (others nil))
+          (declare (dynamic-extent first))
+          (with-package-lock (package)
+            (dolist (pkg (pkg.used package))
+              (with-package-lock (pkg)
+                (multiple-value-bind (found conflicting-sym) (%get-htab-symbol name len (pkg.etab pkg))
+                  (when found
+                    (if first-p
+                      (unless (or (eq conflicting-sym first)
+                                  (memq conflicting-sym others))
+                        (push conflicting-sym others))
+                      (setq first-p t first conflicting-sym)))))))
+          (when others
+            ;;If this returns, it will have somehow fixed things.
+            (return-from unintern (%kernel-restart $xunintc symbol package (cons first others)))))
+        ;; No conflicts found, but symbol was on shadowing-symbols list.  Remove it atomically.
+        (do* ((head (cons nil (pkg.shadowed package)))
+              (prev head next)
+              (next (cdr prev) (cdr next)))
+             ((null next))              ; Should never happen
+          (declare (dynamic-extent head) 
+                   (list head prev next)
+                   (optimize (speed 3) (safety 0)))
+          (when (eq (car next) symbol)
+            (setf (cdr prev) (cdr next)
+                  (pkg.shadowed package) (cdr head))
+            (return))))
+      ;; Now remove the symbol from package; if package was its home
+      ;; package, set its package to NIL.  If we get here, the "table"
+      ;; and "index" values returned above are still valid.
+      (%svset (car table) index (package-deleted-marker))
+      (when (eq (symbol-package symbol) package)
+        (%set-symbol-package symbol nil))
+      t)))
+
+(defun import-1 (package sym)
+  (multiple-value-bind (conflicting-sym type internal-offset external-offset) (%findsym (symbol-name sym) package)
+    (if (and type (neq conflicting-sym sym))
+      (let* ((external-p (eq type :inherited))
+             (condition (make-condition 'import-conflict-error 
+                                        :package package
+                                        :imported-sym sym
+                                        :conflicting-sym conflicting-sym
+                                        :conflict-external external-p)))
+        (restart-case (error condition)
+          (continue ()
+                    :report (lambda (s) (format s "Ignore attempt to import ~S to ~S." sym package)))
+          (resolve-conflict ()
+                            :report (lambda (s)
+                                      (let* ((package-name (package-name package)))
+                                        (if external-p 
+                                          (format s "~A ~s in package ~s ." 'shadowing-import sym package-name)
+                                          (format s "~A ~s from package ~s ." 'unintern conflicting-sym package-name))))
+                            (if external-p 
+                              (shadowing-import-1 package sym)
+                              (progn
+                                (unintern conflicting-sym package)
+                                (import-1 package sym))))))
+      (unless (or (eq type :external) (eq type :internal))
+        (%insert-symbol sym package internal-offset external-offset)))))
+
+
+(defun import (sym-or-syms &optional package)
+  "Make SYMBOLS accessible as internal symbols in PACKAGE. If a symbol
+  is already accessible then it has no effect. If a name conflict
+  would result from the importation, then a correctable error is signalled."
+  (setq package (pkg-arg (or package *package*)))
+  (if (listp sym-or-syms)
+    (dolist (sym sym-or-syms)
+      (import-1 package sym))
+    (import-1 package sym-or-syms))
+  t)
+
+(defun shadow-1 (package sym)
+  (let* ((pname (ensure-simple-string (string sym)))
+         (len (length pname)))
+    (without-interrupts
+     (multiple-value-bind (symbol where internal-idx external-idx) (%find-symbol pname len package)
+       (if (or (eq where :internal) (eq where :external))
+         (pushnew symbol (pkg.shadowed package))
+         (push (%add-symbol pname package internal-idx external-idx) (pkg.shadowed package)))))
+    nil))
+
+(defun shadow (sym-or-symbols-or-string-or-strings &optional package)
+  "Make an internal symbol in PACKAGE with the same name as each of
+  the specified SYMBOLS. If a symbol with the given name is already
+  present in PACKAGE, then the existing symbol is placed in the
+  shadowing symbols list if it is not already present."
+  (setq package (pkg-arg (or package *package*)))
+  (if (listp sym-or-symbols-or-string-or-strings)
+    (dolist (s sym-or-symbols-or-string-or-strings)
+      (shadow-1 package s))
+    (shadow-1 package sym-or-symbols-or-string-or-strings))
+  t)
+
+(defun unexport (sym-or-symbols &optional package)
+  "Makes SYMBOLS no longer exported from PACKAGE."
+  (setq package (pkg-arg (or package *package*)))
+  (if (listp sym-or-symbols)
+    (dolist (sym sym-or-symbols)
+      (unexport-1 package sym))
+    (unexport-1 package sym-or-symbols))
+  t)
+
+(defun unexport-1 (package sym)
+  (when (eq package *keyword-package*)
+    (error "Can't unexport ~S from ~S ." sym package))
+  (multiple-value-bind (foundsym foundp internal-offset external-offset)
+                       (%findsym (symbol-name sym) package)
+    (unless foundp
+      (error 'symbol-name-not-accessible
+             :symbol-name (symbol-name sym)
+             :package package))
+    (when (eq foundp :external)
+      (let* ((evec (car (pkg.etab package)))
+             (itab (pkg.itab package))
+             (ivec (car itab))
+             (icount&limit (cdr itab)))
+        (declare (type cons itab icount&limit))
+        (setf (svref evec external-offset) (package-deleted-marker))
+        (setf (svref ivec internal-offset) (%symbol->symptr foundsym))
+        (if (eql (setf (car icount&limit)
+                       (the fixnum (1+ (the fixnum (car icount&limit)))))
+                 (the fixnum (cdr icount&limit)))
+          (%resize-htab itab)))))
+  nil)
+
+;;; Both args must be packages.
+(defun %use-package-conflict-check (using-package package-to-use)
+  (let ((already-used (pkg.used using-package)))
+    (unless (or (eq using-package package-to-use)
+                (memq package-to-use already-used))
+      ;; There are two types of conflict that can potentially occur:
+      ;;   1) An external symbol in the package being used conflicts
+      ;;        with a symbol present in the using package
+      ;;   2) An external symbol in the package being used conflicts
+      ;;        with an external symbol in some other package that's
+      ;;        already used.
+      (let* ((ext-ext-conflicts nil)
+             (used-using-conflicts nil)
+             (shadowed-in-using (pkg.shadowed using-package))
+             (to-use-etab (pkg.etab package-to-use)))
+        (without-interrupts
+         (dolist (already already-used)
+           (let ((user (if (memq package-to-use (pkg.used-by already))
+                         package-to-use
+                         (if (memq package-to-use (pkg.used already))
+                           already))))
+             (if user
+               (let* ((used (if (eq user package-to-use) already package-to-use))
+                      (user-etab (pkg.etab user))
+                      (used-etab (pkg.etab used)))
+                 (dolist (shadow (pkg.shadowed user))
+                   (let ((sname (symbol-name shadow)))
+                     (unless (member sname shadowed-in-using :test #'string=)
+                       (let ((len (length sname)))
+                         (when (%get-htab-symbol sname len user-etab)   ; external in user
+                           (multiple-value-bind (external-in-used used-sym) (%get-htab-symbol sname len used-etab)
+                             (when (and external-in-used (neq used-sym shadow))
+                               (push (list shadow used-sym) ext-ext-conflicts)))))))))
+               ;; Remember what we're doing here ?
+               ;; Neither of the two packages use the other.  Iterate
+               ;; over the external symbols in the package that has
+               ;; the fewest external symbols and note conflicts with
+               ;; external symbols in the other package.
+               (let* ((smaller (if (%i< (%cadr to-use-etab) (%cadr (pkg.etab already)))
+                                 package-to-use
+                                 already))
+                      (larger (if (eq smaller package-to-use) already package-to-use))
+                      (larger-etab (pkg.etab larger))
+                      (smaller-v (%car (pkg.etab smaller))))
+                 (dotimes (i (uvsize smaller-v))
+                   (declare (fixnum i))
+                   (let ((symptr (%svref smaller-v i)))
+                     (when (symbolp symptr)
+                       (let* ((sym (%symptr->symbol symptr))
+                              (symname (symbol-name sym)))
+                         (unless (member symname shadowed-in-using :test #'string=)
+                           (multiple-value-bind (found-in-larger sym-in-larger)
+                                                (%get-htab-symbol symname (length symname) larger-etab)
+                             (when (and found-in-larger (neq sym-in-larger sym))
+                               (push (list sym sym-in-larger) ext-ext-conflicts))))))))))))
+         ;; Now see if any non-shadowed, directly present symbols in
+         ;; the using package conflicts with an external symbol in the
+         ;; package being used.  There are two ways of doing this; one
+         ;; of them -may- be much faster than the other.
+         (let* ((to-use-etab-size (%cadr to-use-etab))
+                (present-symbols-size (%i+ (%cadr (pkg.itab using-package)) (%cadr (pkg.etab using-package)))))
+           (unless (eql 0 present-symbols-size)
+             (if (%i< present-symbols-size to-use-etab-size)
+               ;; Faster to look up each present symbol in to-use-etab.
+               (let ((htabvs (list (%car (pkg.etab using-package)) (%car (pkg.itab using-package)))))
+                 (declare (dynamic-extent htabvs))
+                 (dolist (v htabvs)
+                   (dotimes (i (the fixnum (uvsize v)))
+                     (declare (fixnum i))
+                     (let ((symptr (%svref v i)))
+                       (when (symbolp symptr)
+                         (let* ((sym (%symptr->symbol symptr)))
+                           (unless (memq sym shadowed-in-using)
+                             (let* ((name (symbol-name symptr)))
+                               (multiple-value-bind (found-p to-use-sym) (%get-htab-symbol name (length name) to-use-etab)
+                                 (when (and found-p (neq to-use-sym sym))
+                                   (push (list sym to-use-sym) used-using-conflicts)))))))))))
+               ;; See if any external symbol present in the package
+               ;; being used conflicts with any symbol present in the
+               ;; using package.
+               (let ((v (%car to-use-etab)))
+                 (dotimes (i (uvsize v))
+                   (declare (fixnum i))
+                   (let ((symptr (%svref v i)))
+                     (when (symbolp symptr)
+                       (let* ((sym (%symptr->symbol symptr)))
+                         (multiple-value-bind (using-sym found-p) (%find-package-symbol (symbol-name sym) using-package)
+                           (when (and found-p
+                                      (neq sym using-sym)
+                                      (not (memq using-sym shadowed-in-using)))
+                             (push (list using-sym sym) used-using-conflicts))))))))))))
+        (values ext-ext-conflicts used-using-conflicts)))))
+
+(defun use-package-1 (using-package package-to-use)
+  (if (eq (setq package-to-use (pkg-arg package-to-use))
+          *keyword-package*)
+    (error "~S can't use ~S." using-package package-to-use))
+  (do* ((used-external-conflicts nil)
+        (used-using-conflicts nil))
+       ((and (null (multiple-value-setq (used-external-conflicts used-using-conflicts)
+                     (%use-package-conflict-check using-package package-to-use)))
+             (null used-using-conflicts)))
+    (if used-external-conflicts
+      (%kernel-restart $xusecX package-to-use using-package used-external-conflicts)
+      (if used-using-conflicts
+        (%kernel-restart $xusec package-to-use using-package used-using-conflicts))))
+  (unless (memq using-package (pkg.used-by package-to-use))   ;  Not already used in break loop/restart, etc.
+    (push using-package (pkg.used-by package-to-use))
+    (push package-to-use (pkg.used using-package))))
+
+(defun use-package (packages-to-use &optional package)
+  "Add all the PACKAGES-TO-USE to the use list for PACKAGE so that
+  the external symbols of the used packages are accessible as internal
+  symbols in PACKAGE."
+  (setq package (pkg-arg (or package *package*)))
+  (if (listp packages-to-use)
+    (dolist (to-use packages-to-use)
+      (use-package-1 package to-use))
+    (use-package-1 package packages-to-use))
+  t)
+
+(defun shadowing-import-1 (package sym)
+  (let* ((pname (symbol-name sym))
+         (len (length pname))
+         (need-add t))
+    (without-interrupts
+     (multiple-value-bind (othersym htab offset) (%find-package-symbol pname package)
+       (if htab
+         (if (eq othersym sym)
+           (setq need-add nil)
+           (progn                       ; Delete conflicting symbol
+             (if (eq (symbol-package othersym) package)
+               (%set-symbol-package othersym nil))
+             (setf (%svref (car htab) offset) (package-deleted-marker))
+             (setf (pkg.shadowed package) (delete othersym (pkg.shadowed package) :test #'eq)))))
+       (if need-add                   ; No symbols with same pname; intern & shadow
+         (multiple-value-bind (xsym foundp internal-offset external-offset) 
+                              (%find-symbol pname len package)
+           (declare (ignore xsym foundp))
+           (%insert-symbol sym package internal-offset external-offset)))
+       (pushnew sym (pkg.shadowed package))
+       nil))))
+
+(defun shadowing-import (sym-or-syms &optional (package *package*))
+  "Import SYMBOLS into package, disregarding any name conflict. If
+  a symbol of the same name is present, then it is uninterned."
+  (setq package (pkg-arg package))
+  (if (listp sym-or-syms)
+    (dolist (sym sym-or-syms)
+      (shadowing-import-1 package sym))
+    (shadowing-import-1 package sym-or-syms))
+  t)
+
+(defun unuse-package (packages-to-unuse &optional package)
+  "Remove PACKAGES-TO-UNUSE from the USE list for PACKAGE."
+  (let ((p (pkg-arg (or package *package*))))
+    (flet ((unuse-one-package (unuse)
+            (setq unuse (pkg-arg unuse))
+            (setf (pkg.used p) (nremove unuse (pkg.used p))
+                  (pkg.used-by unuse) (nremove p (pkg.used-by unuse)))))
+      (declare (dynamic-extent #'unuse-one-package))
+      (if (listp packages-to-unuse)
+        (dolist (u packages-to-unuse) (unuse-one-package u))
+        (unuse-one-package packages-to-unuse))
+      t)))
+
+(defun delete-package (package)
+  "Delete the package designated by PACKAGE-DESIGNATOR from the package
+  system data structures."
+  (unless (packagep package)
+    (setq package (or (find-package package)
+                      (progn
+                        (cerror "Do nothing" 'no-such-package :package package)
+                        (return-from delete-package nil)))))
+  (with-package-list-read-lock
+    (unless (memq package %all-packages%)
+      (return-from delete-package nil)))
+  (when (pkg.used-by package)
+    (cerror "unuse ~S" 'package-is-used-by :package package
+            :using-packages (pkg.used-by package)))
+  (while (pkg.used-by package)
+    (unuse-package package (car (pkg.used-by package))))
+  (while (pkg.used package)
+    (unuse-package (car (pkg.used package)) package))
+  (setf (pkg.shadowed package) nil)
+  (with-package-list-write-lock
+    (setq %all-packages% (nremove package %all-packages%)))
+  (dolist (n (pkg.names package))
+    (let* ((ref (register-package-ref n)))
+      (setf (package-ref.pkg ref) nil)))
+  (setf (pkg.names package) nil)
+  (let* ((ivec (car (pkg.itab package)))
+         (evec (car (pkg.etab package)))
+         (deleted (package-deleted-marker)))
+    (dotimes (i (the fixnum (length ivec)))
+      (let* ((sym (%svref ivec i)))
+        (setf (%svref ivec i) deleted)          ; in case it's in STATIC space
+        (when (symbolp sym)
+          (if (eq (symbol-package sym) package)
+            (%set-symbol-package sym nil)))))
+    (dotimes (i (the fixnum (length evec)))
+      (let* ((sym (%svref evec i)))
+        (setf (%svref evec i) deleted)          ; in case it's in STATIC space
+        (when (symbolp sym)
+          (if (eq (symbol-package sym) package)
+            (%set-symbol-package sym nil))))))
+  (let ((itab (pkg.itab package)) (etab (pkg.etab package)) (v '#(nil nil nil)))
+    (%rplaca itab v) (%rplaca etab v)
+    (%rplaca (%cdr itab) 0) (%rplaca (%cdr etab) 0)
+    (%rplacd (%cdr itab) #x4000) (%rplacd (%cdr etab) #x4000))
+  t)
+
+(defun %find-package-symbol (string package &optional (len (length string)))
+  (let* ((etab (pkg.etab package))
+         (itab (pkg.itab package)))
+    (multiple-value-bind (foundp sym offset) (%get-htab-symbol string len itab)
+      (if foundp
+        (values sym itab offset)
+        (progn
+          (multiple-value-setq (foundp sym offset)
+          (%get-htab-symbol string len etab))
+          (if foundp
+            (values sym etab offset)
+            (values nil nil nil)))))))
+
+;;;For the inspector, number of symbols in pkg.
+(defun %pkgtab-count (pkgtab)
+  (let* ((n 0))
+    (declare (fixnum n))
+    (dovector (x (pkgtab-table pkgtab) n)
+       (when (symbolp x)
+         (incf n)))))
+
+
+(defun %resize-package (pkg)
+  (%resize-htab (pkg.itab pkg))
+  (%resize-htab (pkg.etab pkg))
+  pkg)
+
+;These allow deleted packages, so can't use pkg-arg which doesn't.
+;Of course, the wonderful world of optional arguments comes in handy.
+(defun pkg-arg-allow-deleted (pkg)
+  (pkg-arg pkg t))
+
+
+(defun package-name (pkg) (%car (pkg.names (pkg-arg-allow-deleted pkg))))
+;;>> Shouldn't these copy-list their result so that the user
+;;>>  can't cause a crash through evil rplacding?
+;Of course that would make rplacding less evil, and then how would they ever learn?
+(defun package-nicknames (pkg) (%cdr (pkg.names (pkg-arg-allow-deleted pkg))))
+(defun package-use-list (pkg) (pkg.used (pkg-arg-allow-deleted pkg)))
+(defun package-used-by-list (pkg) (pkg.used-by (pkg-arg-allow-deleted pkg)))
+(defun package-shadowing-symbols (pkg) (pkg.shadowed (pkg-arg-allow-deleted pkg)))
+
+;;; This assumes that all symbol-names and package-names are strings.
+(defun %define-package (name size 
+                             external-size ; extension (may be nil.)
+                             nicknames
+                             shadow
+                             shadowing-import-from-specs
+                             use
+                             import-from-specs
+                             intern
+                             export
+			     &optional doc)
+  (if (eq use :default) (setq use *make-package-use-defaults*))
+  (let* ((pkg (find-package name)))
+    (if pkg
+      ;; Restarts could offer several ways of fixing this.
+      (unless (string= (package-name pkg) name)
+        (cerror "Redefine ~*~S"
+                "~S is already a nickname for ~S" name pkg))
+      (setq pkg (make-package name
+                              :use nil
+                              :internal-size (or size 60)
+                              :external-size (or external-size
+                                                 (max (length export) 1)))))
+    (unuse-package (package-use-list pkg) pkg)
+    (rename-package pkg name nicknames)
+    (flet ((operation-on-all-specs (function speclist)
+             (let ((to-do nil))
+               (dolist (spec speclist)
+                 (let ((from (pop spec)))
+                   (dolist (str spec)
+                     (multiple-value-bind (sym win) (find-symbol str from)
+                       (if win
+                         (push sym to-do)
+                         ; This should (maybe) be a PACKAGE-ERROR.
+                         (cerror "Ignore attempt to ~s ~s from package ~s"
+                                 "Cannot ~s ~s from package ~s" function str from))))))
+               (when to-do (funcall function to-do pkg)))))
+      
+      (dolist (sym shadow) (shadow sym pkg))
+      (operation-on-all-specs 'shadowing-import shadowing-import-from-specs)
+      (use-package use pkg)
+      (operation-on-all-specs 'import import-from-specs)
+      (dolist (str intern) (intern str pkg))
+      (when export
+        (let* ((syms nil))
+          (dolist (str export)
+            (multiple-value-bind (sym found) (find-symbol str pkg)
+              (unless found (setq sym (intern str pkg)))
+              (push sym syms)))
+          (export syms pkg)))
+      (when (and doc *save-doc-strings*)
+        (set-documentation pkg t doc))
+      pkg)))
+
+(defun %setup-pkg-iter-state (pkg-list types)
+  (collect ((steps))
+    (flet ((cons-pkg-iter-step (package type table &optional shadowed)
+             (steps (vector package type table shadowed nil nil))))
+      (let* ((pkgs (if (listp pkg-list)
+                     (mapcar #'pkg-arg pkg-list)
+                     (list (pkg-arg pkg-list)))))
+        (dolist (pkg pkgs)
+          (dolist (type types)
+            (case type
+              (:internal (cons-pkg-iter-step pkg type (pkg.itab pkg)))
+              (:external (cons-pkg-iter-step pkg type (pkg.etab pkg)))
+              (:inherited
+               (let* ((shadowed (pkg.shadowed pkg))
+                      (used (pkg.used pkg)))
+                 (dolist (u used)
+                   (cons-pkg-iter-step pkg type (pkg.etab u) shadowed)))))))))
+    (vector nil (steps))))
+
+(defun %pkg-iter-next (state)
+  (flet ((get-step ()
+           (let* ((step (pkg-iter.step state)))
+             (loop
+               (if (and step (> (pkg-iter-step.index step) 0))
+                 (return step))
+               (when (setq step (pop (pkg-iter.remaining-steps state)))
+                 (setf (pkg-iter.step state) step)
+                 (setf (pkg-iter-step.index step)
+                       (length (setf (pkg-iter-step.vector step)
+                                     (pkgtab-table  (pkg-iter-step.table step))))))
+               (unless step
+                 (return))))))
+    (loop
+      (let* ((step (get-step)))
+        (when (null step) (return))
+        (multiple-value-bind (symbol found)
+            (%htab-symbol (pkg-iter-step.vector step)
+                          (decf (pkg-iter-step.index step)))
+          (when (and found
+                     (not (member symbol (pkg-iter-step.shadowed step)
+                                  :test #'string=)))
+            (return (values t
+                            symbol
+                            (pkg-iter-step.type step)
+                            (pkg-iter-step.pkg step)))))))))
+
+
+;;; For do-symbols and with-package-iterator
+;;; string must be a simple string
+;;; package must be a package
+;;; Wouldn't it be nice if this distinguished "not found" from "found NIL" ?
+(defun %name-present-in-package-p (string package)
+  (values (%find-package-symbol string package)))
+
+;;; This is supposed to be (somewhat) like the lisp machine's MAKE-PACKAGE.
+;;; Accept and ignore some keyword arguments, accept and process some others.
+
+(defun lispm-make-package (name &key 
+                                (use *make-package-use-defaults*)
+                                nicknames
+                                ;prefix-name
+                                ;invisible
+                                (shadow nil shadow-p)
+                                (export nil export-p)
+                                (shadowing-import nil shadowing-import-p)
+                                (import nil import-p)
+                                (import-from nil import-from-p)
+                                ;relative-names
+                                ;relative-names-for-me
+                                ;size
+                                ;hash-inherited-symbols
+                                ;external-only
+                                ;include
+                                ;new-symbol-function
+                                ;colon-mode
+                                ;prefix-intern-function
+                                &allow-other-keys)
+  ;  (declare (ignore prefix-name invisible relative-names relative-names-for-me
+  ;                   size hash-inherited-symbols external-only include
+  ;                   new-symbol-function colon-mode prefix-intern-function))
+  (let ((pkg (make-package name :use NIL :nicknames nicknames)))
+    (when shadow-p (shadow shadow pkg))
+    (when shadowing-import-p (shadowing-import shadowing-import pkg))
+    (use-package use pkg)
+    (when import-from-p
+      (let ((from-pkg (pop import-from)))
+        (dolist (name import-from)
+          (multiple-value-bind (sym win) (find-symbol (string name) from-pkg)
+            (when win (import-1 pkg sym))))))
+    (when import-p (import import pkg))
+    (when export-p
+      (let* ((syms nil))
+        (dolist (name export)
+          (multiple-value-bind (sym win) (find-symbol (string name) pkg)
+            (unless win (setq sym (intern (string name) pkg)))
+            (push sym syms)))
+        (export syms pkg)))
+    pkg))
+
Index: /branches/new-random/level-1/l1-sysio.lisp
===================================================================
--- /branches/new-random/level-1/l1-sysio.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-sysio.lisp	(revision 13309)
@@ -0,0 +1,928 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defstruct (file-ioblock (:include ioblock))
+  (octet-pos 0 )                       ; current io position in octets
+  (fileeof 0 )                          ; file length in elements
+  )
+
+
+
+
+;;; The file-ioblock-octet-pos field is the (octet) position
+;;; at which the next I/O operation will begin (e.g., where the
+;;; input came from and/or where the output's going.)  There are
+;;; cases (e.g., after a STREAM-CLEAR-INPUT) when this can't be
+;;; determined (based on its previous value and the logical size
+;;; of the buffer) so we'll have to ask the OS.
+
+(defun file-octet-filepos (file-ioblock)
+  (fd-tell (file-ioblock-device file-ioblock)))
+
+(defun synch-file-octet-filepos (file-ioblock)
+  (setf (file-ioblock-octet-pos file-ioblock)
+	(file-octet-filepos file-ioblock)))
+
+(defun infer-line-termination (file-ioblock)
+  (let* ((encoding (or (file-ioblock-encoding file-ioblock)
+                       (get-character-encoding nil)))
+         (inbuf (file-ioblock-inbuf file-ioblock))
+         (buffer (io-buffer-buffer inbuf))
+         (n (io-buffer-count inbuf)))
+    (when (zerop n)
+      (setq n (or (fd-stream-advance (file-ioblock-stream file-ioblock)
+                                     file-ioblock
+                                     t)
+                  0)))
+    (multiple-value-bind (nchars last)
+        (funcall (character-encoding-length-of-vector-encoding-function encoding)
+                 buffer
+                 0
+                 n)
+      (declare (fixnum nchars last))
+      (let* ((string (make-string nchars)))
+        (declare (dynamic-extent string))
+        (decode-character-encoded-vector encoding buffer 0 last string)
+        (let* ((line-termination
+                (do* ((i 0 (1+ i))
+                      (last-was-cr nil))
+                     ((= i nchars) (if last-was-cr :cr))
+                  (declare (fixnum i))
+                  (let* ((char (schar string i)))
+                    (if last-was-cr
+                      (if (eq char #\Linefeed)
+                        (return :crlf)
+                        (return :cr))
+                      (case char
+                        (#\Newline (return nil))
+                        (#\Line_Separator (return :unicode))
+                        (#\Return (setq last-was-cr t))))))))
+          (when line-termination
+            (install-ioblock-input-line-termination file-ioblock line-termination)
+            (when (file-ioblock-outbuf file-ioblock)
+              (install-ioblock-output-line-termination file-ioblock line-termination))))))
+    (when (eq (ioblock-owner file-ioblock) *current-process*)
+      (setf (ioblock-owner file-ioblock) 0))))
+
+
+
+(defvar *default-external-format* :unix)
+
+(defvar *default-file-character-encoding* nil)
+
+(defmethod default-character-encoding ((domain (eql :file)))
+  *default-file-character-encoding*)
+
+(defvar *default-line-termination* :unix
+  "The value of this variable is used when :EXTERNAL-FORMAT is
+unspecified or specified as :DEFAULT. It can meaningfully be given any
+of the values :UNIX, :MACOS, :MSDOS, :UNICODE or :INFERRED, each of which is
+interpreted as described in the documentation.
+
+Because there's some risk that unsolicited newline translation could have
+undesirable consequences, the initial value of this variable in Clozure CL
+is :UNIX.")
+
+(defstruct (external-format (:constructor %make-external-format)
+                            (:copier nil))
+  (character-encoding :default :read-only t)
+  (line-termination :default :read-only t))
+
+(defmethod print-object ((ef external-format) stream)
+  (print-unreadable-object (ef stream :type t :identity t)
+    (format stream "~s/~s" (external-format-character-encoding ef) (external-format-line-termination ef))))
+
+
+
+(defvar *external-formats* (make-hash-table :test #'equal))
+
+(defun make-external-format (&key (domain t)
+                                  (character-encoding :default)
+                                  (line-termination :default))
+  (if (eq line-termination :default)
+    (setq line-termination *default-line-termination*))
+  (unless (assq line-termination *canonical-line-termination-conventions*)
+    (error "~S is not a known line-termination format." line-termination))
+
+  (if (eq character-encoding :default)
+    (setq character-encoding
+          (default-character-encoding domain)))
+  (unless (lookup-character-encoding character-encoding)
+    (error "~S is not the name of a known characer encoding."
+           character-encoding))
+  (let* ((pair (cons character-encoding line-termination)))
+    (declare (dynamic-extent pair))    
+    (or (gethash pair *external-formats*)
+        (setf (gethash (cons character-encoding line-termination) *external-formats*)
+              (%make-external-format :character-encoding character-encoding
+                                     :line-termination line-termination)))))
+
+
+
+(defun normalize-external-format (domain external-format)
+  (cond ((listp external-format)
+         (unless (plistp external-format)
+           (error "External-format ~s is not a property list." external-format))
+         (normalize-external-format domain (apply #'make-external-format :domain domain  external-format)))
+        ((typep external-format 'external-format)
+         external-format)
+        ((eq external-format :default)
+         (normalize-external-format domain *default-external-format*))
+        ((lookup-character-encoding external-format)
+         (normalize-external-format domain `(:character-encoding ,external-format)))
+        ((assq external-format *canonical-line-termination-conventions*)
+         (normalize-external-format domain `(:line-termination ,external-format)))
+        (t
+         (error "Invalid external-format: ~s" external-format))))
+               
+           
+    
+
+
+
+
+;;; Establish a new position for the specified file-stream.
+(defun file-ioblock-seek (file-ioblock newoctetpos)
+  (let* ((result (fd-lseek
+		  (file-ioblock-device file-ioblock) newoctetpos #$SEEK_SET)))
+    (if (< result 0)
+      (error 'simple-stream-error
+	     :stream (file-ioblock-stream file-ioblock)
+	     :format-control (format nil "Can't set file position to ~d: ~a"
+				     newoctetpos (%strerror result)))
+      newoctetpos)))
+
+;;; For input streams, getting/setting the position is fairly simple.
+;;; Getting the position is a simple matter of adding the buffer
+;;; origin to the current position within the buffer.
+;;; Setting the position involves either adjusting the buffer index
+;;; (if the new position is within the current buffer) or seeking
+;;; to a new position.
+
+(defun %ioblock-input-file-position (file-ioblock newpos)
+  (let* ((octet-base (file-ioblock-octet-pos file-ioblock))
+	 (element-base (ioblock-octets-to-elements file-ioblock octet-base))
+	 (inbuf (file-ioblock-inbuf file-ioblock))
+	 (curpos (+ element-base (io-buffer-idx inbuf))))
+    (if (null newpos)
+      curpos
+      (progn
+	(if (and (>= newpos element-base)
+		 (< newpos (+ element-base (io-buffer-count inbuf))))
+	  (setf (io-buffer-idx inbuf) (- newpos element-base))
+	  (file-ioblock-seek-and-reset file-ioblock
+				       (ioblock-elements-to-octets
+					file-ioblock
+					newpos)))
+	newpos))))
+
+;;; For (pure) output streams, it's a little more complicated.  If we
+;;; have to seek to a new origin, we may need to flush the buffer
+;;; first.
+
+(defun %ioblock-output-file-position (file-ioblock newpos)
+  (let* ((octet-base (file-ioblock-octet-pos file-ioblock))
+	 (element-base (ioblock-octets-to-elements file-ioblock octet-base))
+	 (outbuf (file-ioblock-outbuf file-ioblock))
+	 (curpos (+ element-base (io-buffer-idx outbuf)))
+	 (maxpos (+ element-base (io-buffer-count outbuf))))
+    (if (null newpos)
+      curpos
+      (progn
+        (unless (= newpos 0)
+          (setf (ioblock-pending-byte-order-mark file-ioblock) nil))
+	(if (and (>= newpos element-base)
+		 (<= newpos maxpos))
+	  ;; Backing up is easy.  Skipping forward (without flushing
+	  ;; and seeking) would be hard, 'cause we can't tell what
+	  ;; we're skipping over.
+	  (let* ((newidx (- newpos element-base)))
+	    (setf (io-buffer-idx outbuf) newidx))
+	  (progn
+	    (when (file-ioblock-dirty file-ioblock)
+	      (fd-stream-force-output (file-ioblock-stream file-ioblock)
+                                      file-ioblock
+                                      (io-buffer-count outbuf)
+                                      nil)
+	      ;; May have just extended the file; may need to update
+	      ;; fileeof.
+	      (when (> maxpos (file-ioblock-fileeof file-ioblock))
+		(setf (file-ioblock-fileeof file-ioblock) maxpos)))
+	    (file-ioblock-seek-and-reset file-ioblock
+					 (ioblock-elements-to-octets
+					  file-ioblock
+					  newpos))))
+	newpos))))
+
+;;; For I/O file streams, there's an additional complication: if we
+;;; back up within the (shared) buffer and the old position was beyond
+;;; the buffer's input count, we have to set the input count to the
+;;; old position.  (Consider the case of writing a single element at
+;;; the end-of-file, backing up one element, then reading the element
+;;; we wrote.)  We -can- skip forward over stuff that's been read;
+;;; if the buffer's dirty, we'll eventually write it back out.
+
+(defun %ioblock-io-file-position (file-ioblock newpos)
+  (let* ((octet-base (file-ioblock-octet-pos file-ioblock))
+	 (element-base (ioblock-octets-to-elements file-ioblock octet-base))
+	 (outbuf (file-ioblock-outbuf file-ioblock)) ; outbuf = inbuf
+	 (curidx (io-buffer-idx outbuf))
+	 (curpos (+ element-base curidx)))
+    (if (null newpos)
+      curpos
+      (let* ((incount (io-buffer-count outbuf)))
+        (unless (= newpos 0)
+          (setf (ioblock-pending-byte-order-mark file-ioblock) nil))        
+	(cond 
+	  ((and (>= newpos element-base)
+		(<= newpos curpos))
+	   ;; If we've read less than we've written, make what's
+	   ;; been written available for subsequent input.
+	   (when (> curidx incount)
+	     (setf (io-buffer-count outbuf) curidx))
+	   (setf (io-buffer-idx outbuf) (- newpos element-base)))
+	  ((and (>= newpos element-base)
+		(< newpos (+ element-base incount)))
+	   (setf (io-buffer-idx outbuf) (- newpos element-base)))
+	  (t
+	   (let* ((maxpos (+ element-base (io-buffer-count outbuf))))
+	     (when (> maxpos (file-ioblock-fileeof file-ioblock))
+	       (setf (file-ioblock-fileeof file-ioblock) maxpos)))
+	   (when (file-ioblock-dirty file-ioblock)
+	     (file-ioblock-seek file-ioblock octet-base)
+	     (fd-stream-force-output (file-ioblock-stream file-ioblock)
+                                     file-ioblock
+                                     (io-buffer-count outbuf)
+                                     nil))
+	   (file-ioblock-seek-and-reset file-ioblock
+					(ioblock-elements-to-octets
+					 file-ioblock newpos))))
+	newpos))))
+
+;;; Again, it's simplest to define this in terms of the stream's direction.
+;;; Note that we can't change the size of file descriptors open for input
+;;; only.
+
+(defun %ioblock-input-file-length (file-ioblock newlen)
+  (unless newlen
+    (file-ioblock-fileeof file-ioblock)))
+ 
+(defun %ioblock-output-file-length (file-ioblock newlen)
+  (let* ((octet-base (file-ioblock-octet-pos file-ioblock))
+	 (element-base (ioblock-octets-to-elements file-ioblock octet-base))
+	 (outbuf (file-ioblock-outbuf file-ioblock)) 
+	 (curidx (io-buffer-idx outbuf))
+	 (maxpos (+ element-base (io-buffer-count outbuf)))
+	 (curlen (file-ioblock-fileeof file-ioblock)))
+    (if (> maxpos curlen)
+      (setf (file-ioblock-fileeof file-ioblock) (setq curlen maxpos)))
+    (if (null newlen)
+      curlen
+      (let* ((fd (file-ioblock-device file-ioblock))
+	     (new-octet-eof (ioblock-elements-to-octets file-ioblock newlen))
+	     (cur-octet-pos (fd-tell fd)))
+	(cond ((> newlen curlen)
+	       ;; Extend the file; maintain the current position.
+	       ;; ftruncate isn't guaranteed to extend a file past
+	       ;; its current EOF.  Seeking to the new EOF, then
+	       ;; writing, is guaranteed to do so.  Seek to the
+	       ;; new EOF, write a random byte, truncate to the
+	       ;; specified length, then seek back to where we
+	       ;; were and pretend that nothing happened.
+	       (file-ioblock-seek file-ioblock new-octet-eof)
+	       (%stack-block ((buf 1))
+			     (fd-write fd buf 1))
+	       (fd-ftruncate fd new-octet-eof)
+	       (file-ioblock-seek file-ioblock cur-octet-pos))
+	      ((> newlen maxpos)
+	       ;; Make the file shorter.  Doesn't affect
+	       ;; our position or anything that we have buffered.
+	       (fd-ftruncate fd new-octet-eof))
+	      ((< newlen element-base)
+	       ;; Discard any buffered output.  Truncate the
+	       ;; file, then seek to the new EOF.
+	       (fd-ftruncate fd new-octet-eof)
+	       (file-ioblock-seek-and-reset file-ioblock new-octet-eof))
+	      (t
+	       (fd-ftruncate fd new-octet-eof)
+	       (let* ((newidx (- newlen element-base)))
+		 (when (> maxpos newlen)
+		   (setf (io-buffer-count outbuf) newidx))
+		 (when (> curidx newidx)
+		   (setf (io-buffer-idx outbuf) newidx)))))
+	(setf (file-ioblock-fileeof file-ioblock) newlen)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defclass fundamental-file-stream (fd-stream file-stream)
+    ((filename :initform nil :initarg :filename :accessor file-stream-filename)
+     (actual-filename :initform nil :initarg :actual-filename)
+     (external-format :initform :default :initarg :external-format
+		      :accessor file-stream-external-format)))
+
+  
+
+(defmethod stream-filename ((s fundamental-file-stream))
+  (file-stream-filename s))
+
+(defmethod stream-actual-filename ((s file-stream))
+  (slot-value s 'actual-filename))
+
+(defmethod (setf stream-filename) (new (s fundamental-file-stream))
+  (setf (file-stream-filename s) new))
+
+(defmethod (setf stream-actual-filename) (new (s fundamental-file-stream))
+  (setf (slot-value s 'actual-filename) new))
+
+(defun print-file-stream (s out)
+  (print-unreadable-object (s out :type t :identity t)
+    (let* ((file-ioblock (stream-ioblock s nil)))
+      (format out "(~s/" (stream-filename s))
+      (if file-ioblock
+	(format out "~d ~a)" (file-ioblock-device file-ioblock) (encoding-name (ioblock-encoding file-ioblock)))
+	(format out ":closed")))))
+    
+(defmethod print-object ((s fundamental-file-stream) out)
+  (print-file-stream s out))
+
+(make-built-in-class 'basic-file-stream 'file-stream 'basic-stream)
+
+(defmethod stream-filename ((s basic-file-stream))
+  (basic-file-stream.filename s))
+
+(defmethod stream-actual-filename ((s basic-file-stream))
+  (basic-file-stream.actual-filename s))
+
+(defmethod (setf stream-filename) (new (s basic-file-stream))
+  (setf (basic-file-stream.filename s) new))
+
+(defmethod (setf stream-actual-filename) (new (s basic-file-stream))
+  (setf (basic-file-stream.actual-filename s) new))
+
+(defmethod print-object ((s basic-file-stream) out)
+  (print-file-stream s out))
+
+
+(defmethod initialize-basic-stream ((s basic-file-stream) &key element-type external-format &allow-other-keys)
+  (setf (getf (basic-stream.info s) :element-type) element-type)
+  (setf (basic-file-stream.external-format s) external-format))
+
+(defmethod stream-create-ioblock ((stream fundamental-file-stream) &rest args &key)
+  (declare (dynamic-extent args))
+  (apply #'make-file-ioblock :stream stream args))
+
+(defmethod stream-create-ioblock ((stream basic-file-stream) &rest args &key)
+  (declare (dynamic-extent args))
+  (apply #'make-file-ioblock :stream stream args))
+
+(defclass fundamental-file-input-stream (fundamental-file-stream fd-input-stream)
+    ())
+
+(make-built-in-class 'basic-file-input-stream 'basic-file-stream 'basic-input-stream)
+
+
+(defclass fundamental-file-output-stream (fundamental-file-stream fd-output-stream)
+    ())
+
+(make-built-in-class 'basic-file-output-stream 'basic-file-stream 'basic-output-stream)
+
+(defclass fundamental-file-io-stream (fundamental-file-stream fd-io-stream)
+    ())
+
+(make-built-in-class 'basic-file-io-stream 'basic-file-stream 'basic-io-stream)
+
+
+(defclass fundamental-file-character-input-stream (fundamental-file-input-stream
+					  fd-character-input-stream)
+    ())
+
+(make-built-in-class 'basic-file-character-input-stream 'basic-file-input-stream 'basic-character-input-stream)
+
+
+(defclass fundamental-file-character-output-stream (fundamental-file-output-stream
+                                                    fd-character-output-stream)
+    ())
+
+(make-built-in-class 'basic-file-character-output-stream 'basic-file-output-stream 'basic-character-output-stream)
+
+(defclass fundamental-file-character-io-stream (fundamental-file-io-stream
+				       fd-character-io-stream)
+    ())
+
+(make-built-in-class 'basic-file-character-io-stream 'basic-file-io-stream 'basic-character-io-stream)
+
+(defclass fundamental-file-binary-input-stream (fundamental-file-input-stream
+                                                fd-binary-input-stream)
+    ())
+
+(make-built-in-class 'basic-file-binary-input-stream 'basic-file-input-stream 'basic-binary-input-stream)
+
+(defclass fundamental-file-binary-output-stream (fundamental-file-output-stream
+                                                 fd-binary-output-stream)
+    ())
+
+(make-built-in-class 'basic-file-binary-output-stream 'basic-file-output-stream 'basic-binary-output-stream)
+
+(defclass fundamental-file-binary-io-stream (fundamental-file-io-stream fd-binary-io-stream)
+    ())
+
+(make-built-in-class 'basic-file-binary-io-stream 'basic-file-io-stream 'basic-binary-io-stream)
+
+
+
+
+;;; This stuff is a lot simpler if we restrict the hair to the
+;;; case of file streams opened in :io mode (which have to worry
+;;; about flushing the shared buffer before filling it, and things
+;;; like that.)
+
+(defmethod stream-clear-input ((f fundamental-file-input-stream))
+  (with-stream-ioblock-input (file-ioblock f :speedy t)
+    (call-next-method)
+    (synch-file-octet-filepos file-ioblock)
+    nil))
+
+
+(defmethod stream-clear-input ((f basic-file-input-stream))
+  (let* ((file-ioblock (basic-stream-ioblock f)))
+    (with-ioblock-input-locked (file-ioblock)
+      (call-next-method)
+      (synch-file-octet-filepos file-ioblock)
+      nil)))
+
+    
+(defmethod stream-clear-input ((f fundamental-file-io-stream))
+  (with-stream-ioblock-input (file-ioblock f :speedy t)
+    (stream-force-output f)		
+    (call-next-method)
+    (synch-file-octet-filepos file-ioblock)
+    nil))
+
+(defmethod stream-clear-input ((f basic-file-io-stream))
+  (let* ((file-ioblock (basic-stream-ioblock f)))
+    (with-ioblock-input-locked (file-ioblock)
+      (call-next-method)
+      (synch-file-octet-filepos file-ioblock)
+      nil)))
+
+(defmethod stream-clear-output ((f fundamental-file-output-stream))
+  (with-stream-ioblock-output (file-ioblock f :speedy t)
+    (call-next-method)
+    (synch-file-octet-filepos file-ioblock)
+    nil))
+
+(defmethod stream-clear-output ((f basic-file-output-stream))
+  (let* ((file-ioblock (basic-stream-ioblock f)))
+    (with-ioblock-input-locked (file-ioblock)
+      (call-next-method)
+      (synch-file-octet-filepos file-ioblock)
+      nil)))
+
+
+  
+;;; If we've been reading, the file position where we're going
+;;; to read this time is (+ where-it-was-last-time what-we-read-last-time.)
+(defun input-file-ioblock-advance (stream file-ioblock read-p)
+  (let* ((newpos (+ (file-ioblock-octet-pos file-ioblock)
+		    (io-buffer-count (file-ioblock-inbuf file-ioblock)))))
+    (setf (file-ioblock-octet-pos file-ioblock) newpos)
+    (fd-stream-advance stream file-ioblock read-p)))
+
+;;; If the buffer's dirty, we have to back up and rewrite it before
+;;; reading in a new buffer.
+(defun io-file-ioblock-advance (stream file-ioblock read-p)
+  (let* ((curpos (file-ioblock-octet-pos file-ioblock))
+	 (count (io-buffer-count (file-ioblock-inbuf file-ioblock)))
+	 (newpos (+ curpos 
+		    (ioblock-elements-to-octets file-ioblock count))))
+    (when (ioblock-dirty file-ioblock)
+      (file-ioblock-seek file-ioblock curpos)
+      (fd-stream-force-output stream file-ioblock count nil))
+    (unless (eql newpos (file-octet-filepos file-ioblock))
+      (error "Expected newpos to be ~d, fd is at ~d"
+	     newpos (file-octet-filepos file-ioblock)))
+    (setf (file-ioblock-octet-pos file-ioblock) newpos)
+    (fd-stream-advance stream file-ioblock read-p)))
+
+		    
+(defun output-file-force-output (stream file-ioblock count finish-p)
+  (let* ((pos (%ioblock-output-file-position file-ioblock nil))
+         (n (fd-stream-force-output stream file-ioblock count finish-p)))
+    (incf (file-ioblock-octet-pos file-ioblock) (or n 0))
+    (%ioblock-output-file-position file-ioblock pos)
+    n))
+
+;;; Can't be sure where the underlying fd is positioned, so seek first.
+(defun io-file-force-output (stream file-ioblock count finish-p)
+  (let* ((pos (%ioblock-io-file-position file-ioblock nil)))
+    (file-ioblock-seek file-ioblock (file-ioblock-octet-pos file-ioblock))
+    (let* ((n (fd-stream-force-output stream file-ioblock count finish-p)))
+      (incf (file-ioblock-octet-pos file-ioblock) (or n 0))
+      (%ioblock-io-file-position file-ioblock pos)
+      n)))
+
+
+;;; Invalidate both buffers and seek to the new position.  The output
+;;; buffer's been flushed already if it needed to be.
+
+(defun file-ioblock-seek-and-reset (file-ioblock newoctetpos)
+  (let* ((inbuf (file-ioblock-inbuf file-ioblock))
+	 (outbuf (file-ioblock-outbuf file-ioblock)))
+    (setf (file-ioblock-dirty file-ioblock) nil)
+    (when inbuf
+      (setf (io-buffer-count inbuf) 0
+	    (io-buffer-idx inbuf) 0))
+    (when outbuf
+      (setf (io-buffer-count outbuf) 0
+	    (io-buffer-idx outbuf) 0))
+    (setf (file-ioblock-octet-pos file-ioblock) newoctetpos)
+    (file-ioblock-seek file-ioblock newoctetpos)))
+
+(defmethod stream-position ((stream fundamental-file-input-stream) &optional newpos)
+  (with-stream-ioblock-input (file-ioblock stream :speedy t)
+    (%ioblock-input-file-position file-ioblock newpos)))
+
+
+(defmethod stream-position ((stream basic-file-input-stream) &optional newpos)
+  (let* ((file-ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (file-ioblock)
+      (%ioblock-input-file-position file-ioblock newpos))))
+
+(defmethod stream-position ((stream fundamental-file-output-stream) &optional newpos)
+  (with-stream-ioblock-output (file-ioblock stream :speedy t)
+    (%ioblock-output-file-position file-ioblock newpos)))
+
+(defmethod stream-position ((stream basic-file-output-stream) &optional newpos)
+  (let* ((file-ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked (file-ioblock)
+      (%ioblock-output-file-position file-ioblock newpos))))
+
+
+(defmethod stream-position ((stream fundamental-file-io-stream) &optional newpos)
+  (with-stream-ioblock-input (file-ioblock stream :speedy t)
+    (%ioblock-io-file-position file-ioblock newpos)))
+
+(defmethod stream-position ((stream basic-file-io-stream) &optional newpos)
+  (let* ((file-ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (file-ioblock)
+      (%ioblock-io-file-position file-ioblock newpos))))
+
+
+(defmethod stream-length ((stream fundamental-file-input-stream) &optional newlen)
+  (with-stream-ioblock-input (file-ioblock stream :speedy t)
+    (let* ((res (%ioblock-input-file-length file-ioblock newlen)))
+      (and res (>= res 0) res))))
+
+
+(defmethod stream-length ((stream basic-file-input-stream) &optional newlen)
+  (let* ((file-ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (file-ioblock)
+      (let* ((res (%ioblock-input-file-length file-ioblock newlen)))
+        (and res (>= res 0) res)))))
+
+
+(defmethod stream-length ((s fundamental-file-output-stream) &optional newlen)
+  (with-stream-ioblock-output (file-ioblock s :speedy t)
+    (let* ((res (%ioblock-output-file-length file-ioblock newlen)))
+      (and res (>= res 0) res))))
+
+
+(defmethod stream-length ((stream basic-file-output-stream) &optional newlen)
+  (let* ((file-ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-output-locked (file-ioblock)
+      (let* ((res (%ioblock-output-file-length file-ioblock newlen)))
+        (and res (>= res 0) res)))))
+
+(defmethod stream-length ((s fundamental-file-io-stream) &optional newlen)
+  (with-stream-ioblock-input (file-ioblock s :speedy t)
+    (let* ((res (%ioblock-output-file-length file-ioblock newlen)))
+      (and res (>= res 0) res))))
+
+(defmethod stream-length ((stream basic-file-io-stream) &optional newlen)
+  (let* ((file-ioblock (basic-stream-ioblock stream)))
+    (with-ioblock-input-locked (file-ioblock)
+      (let* ((res (%ioblock-output-file-length file-ioblock newlen)))
+        (and res (>= res 0) res)))))
+
+(defun close-file-stream (s abort)
+  (when (open-stream-p s)
+    (let* ((ioblock (stream-ioblock s t))
+	   (filename (stream-filename s))
+	   (actual-filename (stream-actual-filename s)))
+      (when actual-filename ; t => created when opened
+	(if abort
+	  (progn
+	    (setf (ioblock-dirty ioblock) nil)
+	    (fd-stream-close s ioblock)
+            (if (eq actual-filename t)
+              (delete-file filename)
+              (unix-rename (namestring actual-filename) (probe-file-x filename))))
+	  (unless (eq actual-filename t)
+            (delete-file actual-filename))))
+      (remove-open-file-stream s))))
+
+
+(defmethod close ((s fundamental-file-stream) &key abort)
+  (close-file-stream s abort)
+  (call-next-method))
+
+(defmethod close ((s basic-file-stream) &key abort)
+  (close-file-stream s abort)
+  (call-next-method))
+
+(defmethod select-stream-class ((class fundamental-file-stream) in-p out-p char-p)
+  (if char-p
+    (if (and in-p out-p)
+      'fundamental-file-character-io-stream
+      (if in-p
+	'fundamental-file-character-input-stream
+	(if out-p
+	  'fundamental-file-character-output-stream
+	  'fundamental-file-stream)))
+    (if (and in-p out-p)
+      'fundamental-file-binary-io-stream
+      (if in-p
+	'fundamental-file-binary-input-stream
+	(if out-p
+	  'fundamental-file-binary-output-stream
+	  'fundamental-file-stream)))))
+
+(defmethod select-stream-class ((class file-stream) in-p out-p char-p)
+  (if char-p
+    (if (and in-p out-p)
+      'fundamental-file-character-io-stream
+      (if in-p
+	'fundamental-file-character-input-stream
+	(if out-p
+	  'fundamental-file-character-output-stream
+	  'fundamental-file-stream)))
+    (if (and in-p out-p)
+      'fundamental-file-binary-io-stream
+      (if in-p
+	'fundamental-file-binary-input-stream
+	(if out-p
+	  'fundamental-file-binary-output-stream
+	  'fundamental-file-stream)))))
+
+(defmethod map-to-basic-stream-class-name ((name (eql 'fundamental-file-stream)))
+  'basic-file-stream)
+
+(defmethod map-to-basic-stream-class-name ((name (eql 'file-stream)))
+  'basic-file-stream)
+
+(defmethod select-stream-class ((class (eql 'basic-file-stream)) in-p out-p char-p)
+  (if char-p
+    (if (and in-p out-p)
+      'basic-file-character-io-stream
+      (if in-p
+	'basic-file-character-input-stream
+	(if out-p
+	  'basic-file-character-output-stream
+	  'basic-file-stream)))
+    (if (and in-p out-p)
+      'basic-file-binary-io-stream
+      (if in-p
+	'basic-file-binary-input-stream
+	(if out-p
+	  'basic-file-binary-output-stream
+	  'basic-file-stream)))))
+
+
+(defmethod select-stream-advance-function ((s file-stream) direction)
+  (ecase direction
+    (:io 'io-file-ioblock-advance)
+    (:input 'input-file-ioblock-advance)))
+
+(defmethod select-stream-force-output-function ((s file-stream) direction)
+  (ecase direction
+    (:io 'io-file-force-output)
+    (:output 'output-file-force-output)))
+
+(defmethod select-stream-untyi-function ((s file-stream) (direction t))
+  '%file-ioblock-untyi)
+
+;;; Conceptually, decrement the stream's position by the number of octets
+;;; needed to encode CHAR.
+;;; Since we don't use IOBLOCK-UNTYI-CHAR, it's hard to detect the error
+;;; of calling UNREAD-CHAR twice in a row.
+(defun %file-ioblock-untyi (ioblock char)
+  (let* ((inbuf (ioblock-inbuf ioblock))
+         (idx (io-buffer-idx inbuf))
+         (encoding (ioblock-encoding ioblock))
+         (noctets (if encoding
+                    (funcall (character-encoding-character-size-in-octets-function encoding) char)
+                    1)))
+    (declare (fixnum idx noctets))
+    (if (>= idx noctets)
+      (setf (io-buffer-idx inbuf) (the fixnum (- idx noctets)))
+      (let* ((stream (ioblock-stream ioblock))
+             (pos (stream-position stream))
+             (newpos (- pos noctets)))
+        (if (< newpos 0)
+          (error "Invalid attempt to unread ~s on ~s." char (ioblock-stream ioblock))
+          (stream-position stream newpos))))
+    char))
+
+
+
+(defun make-file-stream (filename
+			 direction
+			 element-type
+			 if-exists
+			 if-does-not-exist
+			 class
+			 external-format
+                         sharing
+                         basic)
+  (let* ((temp-name nil)
+         (created nil)
+         (dir (pathname-directory filename))
+         (filename (if (eq (car dir) :relative)
+                     (full-pathname filename)
+                     filename))
+         (pathname (pathname filename))) 
+    (block open
+      (if (or (memq element-type '(:default character base-char))
+	      (subtypep element-type 'character))
+	(if (eq element-type :default)(setq element-type 'character))
+	(progn
+	  (setq element-type (type-expand element-type))
+	  (cond ((equal element-type '#.(type-expand 'signed-byte))
+		 (setq element-type '(signed-byte 8)))
+		((equal element-type '#.(type-expand 'unsigned-byte))
+		 (setq element-type '(unsigned-byte 8))))))
+      (case direction
+	(:probe (setq if-exists :ignored))
+	(:input (setq if-exists :ignored))
+	((:io :output) nil)
+	(t (report-bad-arg direction '(member :input :output :io :probe))))
+      (check-pathname-not-wild filename) ;; probe-file-x misses wild versions....
+      (multiple-value-bind (native-truename kind)(probe-file-x filename)
+	(if native-truename
+	  (if (eq kind :directory)
+	    (if (eq direction :probe)
+	      (return-from open nil)
+	      (signal-file-error (- #$EISDIR)  filename))
+	    (if (setq filename (if-exists if-exists filename "Open ..."))
+	      (progn
+		(multiple-value-setq (native-truename kind) (probe-file-x filename))
+		(cond 
+		  ((not native-truename)
+		   (setq native-truename (%create-file filename)
+                         created t))
+		  ((memq direction '(:output :io))
+		   (when (eq if-exists :supersede)
+		     (let ((truename (native-to-pathname native-truename)))
+		       (setq temp-name (gen-file-name truename))
+		       (unix-rename native-truename (native-untranslated-namestring temp-name))
+		       (%create-file native-truename))))))
+	      (return-from open nil)))
+	  (if (setq filename (if-does-not-exist if-does-not-exist filename))
+            (progn
+              (unless (setq native-truename (%create-file filename :if-exists if-exists))
+                (return-from open nil))
+              (setq created t))
+	    (return-from open nil)))
+	(let* ((fd (fd-open native-truename (case direction
+					      ((:probe :input) #$O_RDONLY)
+					      (:output #$O_WRONLY)
+					      (:io #$O_RDWR)))))
+	  (when (< fd 0)  (signal-file-error fd filename))
+          (let* ((fd-kind (%unix-fd-kind fd)))
+            (if (not (eq fd-kind :file))
+              (make-fd-stream fd :direction direction
+                              :element-type element-type
+                              :sharing sharing
+                              :basic basic)
+              (progn
+                (when basic
+                  (setq class (map-to-basic-stream-class-name class))
+                  (setq basic (subtypep (find-class class) 'basic-stream)))
+                (let* ((in-p (member direction '(:io :input)))
+                       (out-p (member direction '(:io :output)))
+                       (io-p (eq direction :io))
+                       (char-p (or (eq element-type 'character)
+                                   (subtypep element-type 'character)))
+                       (elements-per-buffer (optimal-buffer-size fd element-type))
+                       (real-external-format
+                        (if char-p
+                          (normalize-external-format :file external-format)
+                          ))
+                       (line-termination (if char-p (external-format-line-termination real-external-format)))
+                       (encoding (if char-p (external-format-character-encoding real-external-format)))
+                       (class-name (select-stream-class class in-p out-p char-p))
+                       (class (find-class class-name))
+                       (fstream (make-ioblock-stream
+                                 class
+                                 :insize (if in-p elements-per-buffer)
+                                 :outsize (if (and out-p (not io-p))
+                                            elements-per-buffer)
+                                 :share-buffers-p io-p
+                                 :interactive nil
+                                 :direction direction
+                                 :element-type element-type
+                                 :direction direction
+                                 :listen-function 'fd-stream-listen
+                                 :close-function 'fd-stream-close
+                                 :advance-function
+                                 (if in-p (select-stream-advance-function class direction))
+                                 :force-output-function
+                                 (if out-p (select-stream-force-output-function
+                                           class direction))
+                                 :device fd
+                                 :encoding encoding
+                                 :external-format (or real-external-format :binary)
+                                 :sharing sharing
+                                 :line-termination line-termination
+                                 :character-p (or (eq element-type 'character)
+                                                  (subtypep element-type 'character))))
+                       (ioblock (stream-ioblock fstream t)))
+                  (setf (stream-filename fstream) (namestring pathname)
+                        (stream-actual-filename fstream) (or temp-name created))
+                  (setf (file-ioblock-fileeof ioblock)
+                        (ioblock-octets-to-elements ioblock (fd-size fd)))
+                  (when (and in-p (eq line-termination :inferred))
+                    (infer-line-termination ioblock))
+                  (cond ((eq if-exists :append)
+                         (file-position fstream :end))
+                        ((and (memq direction '(:io :output))
+                              (neq if-exists :overwrite))
+                         (stream-length fstream 0)))
+                  (if (eq direction :probe)
+                    (close fstream)
+                    (note-open-file-stream fstream))
+                  fstream)))))))))
+
+
+
+
+
+
+(defmethod stream-external-format ((s broadcast-stream))
+  (let* ((last (last-broadcast-stream s)))
+    (if last
+        (stream-external-format s)
+        :default)))
+
+;;; Under the circumstances, this is a very slow way of saying
+;;; "we don't support EXTENDED-CHARs".
+(defun file-string-length (stream object)
+  "Return the delta in STREAM's FILE-POSITION that would be caused by writing
+   OBJECT to STREAM. Non-trivial only in implementations that support
+   international character sets."
+  (if (typep stream 'broadcast-stream)
+    (let* ((last (last-broadcast-stream stream)))
+      (if last
+	(file-string-length last object)
+	1))
+    (progn
+      (unless (and (typep stream 'file-stream)
+		   (let* ((eltype (stream-element-type stream)))
+		     (or (eq 'character eltype)
+			 (eq 'base-char eltype)
+			 (subtypep eltype 'character))))
+	(error "~S is not a file stream capable of character output" stream))
+      (if (typep object 'character)
+        (setq object (make-string 1 :initial-element object))
+        (progn
+          (require-type object 'string)))
+      (let* ((start 0)
+             (end (length object)))
+        (multiple-value-bind (data offset) (array-data-and-offset object)
+          (unless (eq data object)
+            (setq object data)
+            (incf start offset)
+            (incf end offset)))
+        (let* ((external-format (stream-external-format stream))
+               (encoding (get-character-encoding (external-format-character-encoding external-format)))
+               (line-termination (external-format-line-termination external-format)))
+          (-
+           (+ (funcall (character-encoding-octets-in-string-function encoding)
+                       object
+                       start
+                       end)
+              (if (eq line-termination :crlf)
+                (* (count #\Newline object :start start :end end)
+                   (file-string-length stream #\Return))
+                0))
+           (if (eql (file-position stream) 0)
+             0
+             (length (character-encoding-bom-encoding encoding)))))))))
+  
Index: /branches/new-random/level-1/l1-typesys.lisp
===================================================================
--- /branches/new-random/level-1/l1-typesys.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-typesys.lisp	(revision 13309)
@@ -0,0 +1,4393 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; This is a hacked-up version of the CMU CL type system.
+
+(in-package "CCL")
+
+
+
+;;; This condition is signalled whenever we make a UNKNOWN-TYPE so that
+;;; compiler warnings can be emitted as appropriate.
+;;;
+(define-condition parse-unknown-type (condition)
+  ((specifier :reader parse-unknown-type-specifier :initarg :specifier))
+  (:report (lambda (c s) (print-unreadable-object (c s :type t)
+			   (format s "unknown type ~A" (parse-unknown-type-specifier c))))))
+
+(defun parse-lambda-list (list)
+  (let* ((required)
+         (optional)
+         (keys)
+         (aux))
+    (let ((restp nil)
+          (rest nil)
+          (keyp nil)
+          (allowp nil)
+          (state :required))
+      (dolist (arg list)
+        (if (and (symbolp arg)
+                 (let ((name (symbol-name arg)))
+                   (and (/= (length name) 0)
+                        (char= (char name 0) #\&))))
+          (case arg
+            (&optional
+             (unless (eq state :required)
+               (error "Misplaced &optional in lambda-list: ~S." list))
+             (setq state '&optional))
+            (&rest
+             (unless (member state '(:required &optional))
+               (error "Misplaced &rest in lambda-list: ~S." list))
+             (setq state '&rest))
+            (&key
+             (unless (member state '(:required &optional :post-rest
+                                     ))
+               (error "Misplaced &key in lambda-list: ~S." list))
+             (setq keyp t)
+             (setq state '&key))
+            (&allow-other-keys
+             (unless (eq state '&key)
+               (error "Misplaced &allow-other-keys in lambda-list: ~S." list))
+             (setq allowp t  state '&allow-other-keys))
+            (&aux
+             (when (member state '(&rest))
+               (error "Misplaced &aux in lambda-list: ~S." list))
+             (setq state '&aux))
+            (t
+             (error "Unknown &keyword in lambda-list: ~S." arg)))
+          (case state
+            (:required (push arg required))
+            (&optional (push arg optional))
+            (&rest
+             (setq restp t  rest arg  state :post-rest))
+            (&key (push arg keys))
+            (&aux (push arg aux))
+            (t
+             (error "Found garbage in lambda-list when expecting a keyword: ~S." arg)))))
+      
+      (values (nreverse required) (nreverse optional) restp rest keyp (nreverse keys) allowp (nreverse aux)))))
+
+(defvar %deftype-expanders% (make-hash-table :test #'eq))
+(defvar *type-translators* (make-hash-table :test #'eq))
+(defvar *builtin-type-info* (make-hash-table :test #'equal))
+(defvar %builtin-type-cells% (make-hash-table :test 'equal))
+
+(defvar *use-implementation-types* t)
+
+(defun info-type-builtin (name)
+  (gethash name *builtin-type-info*))
+
+(defun (setf info-type-builtin) (val name)
+  (setf (gethash name *builtin-type-info*) val))
+
+(defun info-type-translator (name)
+  (gethash name *type-translators*))
+
+
+
+
+;;; Allow bootstrapping: mostly, allow us to bootstrap the type system
+;;; by having DEFTYPE expanders defined on built-in classes (the user
+;;; shouldn't be allowed to do so, at least not easily.
+
+;(defvar *type-system-initialized* nil)
+
+(defun %deftype (name fn doc)
+  (clear-type-cache)
+  (cond ((null fn)
+         (remhash name %deftype-expanders%))
+        ((and *type-system-initialized*
+              (or (built-in-type-p name)
+                  (let ((c (find-class name nil)))
+                    (and c (eq (class-name c) name)))))
+	 (error "Cannot redefine type ~S because ~:[it is the name of a class~;it is a built-in type~]" name (built-in-type-p name)))
+	((memq name *nx-known-declarations*)
+	 (check-declaration-redefinition name 'deftype))
+        (t (setf (gethash name %deftype-expanders%) fn)
+           (record-source-file name 'type)))
+  (set-documentation name 'type doc)   ; nil clears it.
+  name)
+
+(defun %define-type-translator (name fn doc)
+  (declare (ignore doc))
+  (setf (gethash name *type-translators*) fn)
+  name)
+
+;;;(defun %deftype-expander (name)
+;;;  (or (gethash name %deftype-expanders%)
+;;;      (and *compiling-file* (%cdr (assq name *compile-time-deftype-expanders*)))))
+(defun %deftype-expander (name)
+  (gethash name %deftype-expanders%))
+
+(defun process-deftype-arglist (arglist &aux (in-optional? nil))
+  "Returns a NEW list similar to arglist except
+    inserts * as the default default for &optional args."
+  (mapcar #'(lambda (item)
+              (cond ((eq item '&optional) (setq in-optional? t) item)
+                    ((memq item lambda-list-keywords) (setq in-optional? nil) item)
+                    ((and in-optional? (symbolp item)) (list item ''*))
+                    (t item)))
+          arglist))
+
+
+(defun expand-type-macro (definer name arglist body env)
+  (setq name (require-type name 'symbol))
+  (multiple-value-bind (lambda doc)
+      (parse-macro-internal name arglist body env '*)
+    `(progn
+       (eval-when (:compile-toplevel)
+	 (note-type-info ',name 'macro ,env))
+       (eval-when (:compile-toplevel :load-toplevel :execute)
+	 (,definer ',name
+	     (nfunction ,name ,lambda)
+	   ,doc)))))
+
+(defmacro deftype (name arglist &body body &environment env)
+  "Define a new type, with syntax like DEFMACRO."
+  (expand-type-macro '%deftype name arglist body env))
+
+(defmacro def-type-translator (name arglist &body body &environment env)
+  (expand-type-macro '%define-type-translator name arglist body env))
+
+
+(defun type-expand (form &optional env &aux def)
+  (while (setq def (cond ((symbolp form)
+                          (gethash form %deftype-expanders%))
+                         ((and (consp form) (symbolp (%car form)))
+                          (gethash (%car form) %deftype-expanders%))
+                         (t nil)))
+    (setq form (funcall def (if (consp form) form (list form)) env)))
+  form)
+
+(defmethod print-object ((tc type-class) stream)
+  (print-unreadable-object (tc stream :type t :identity t)
+    (format stream "~s" (type-class-name tc))))
+
+(defmethod print-object ((c ctype) stream)
+  (print-unreadable-object (c stream :type t)
+    (format stream "~S" (type-specifier c))))
+
+(defmethod make-load-form ((c ctype) &optional env)
+  (declare (ignore env))
+  `(specifier-type ',(type-specifier c)))
+
+(defmethod make-load-form ((cell type-cell) &optional env)
+  (declare (ignore env))
+  `(register-type-cell `,(type-cell-type-specifier cell)))
+
+(defmethod print-object ((cell type-cell) stream)
+  (print-unreadable-object (cell stream :type t :identity t)
+    (format stream "for ~s" (type-cell-type-specifier cell))))
+
+(defun make-key-info (&key name type)
+  (%istruct 'key-info name type))
+
+(defun type-class-or-lose (name)
+  (or (cdr (assq name *type-classes*))
+      (error "~S is not a defined type class." name)))
+
+(eval-when (:compile-toplevel :execute)
+
+(defconstant type-class-function-slots
+  '((:simple-subtypep . #.type-class-simple-subtypep)
+    (:complex-subtypep-arg1 . #.type-class-complex-subtypep-arg1)
+    (:complex-subtypep-arg2 . #.type-class-complex-subtypep-arg2)
+    (:simple-union . #.type-class-simple-union)
+    (:complex-union . #.type-class-complex-union)
+    (:simple-intersection . #.type-class-simple-intersection)
+    (:complex-intersection . #.type-class-complex-intersection)
+    (:simple-= . #.type-class-simple-=)
+    (:complex-= . #.type-class-complex-=)
+    (:unparse . #.type-class-unparse)))
+
+)
+
+(defun class-typep (form class)
+  (memq class (%inited-class-cpl (class-of form))))
+
+;;; CLASS-FUNCTION-SLOT-OR-LOSE  --  Interface
+;;;
+(defun class-function-slot-or-lose (name)
+  (or (cdr (assoc name type-class-function-slots))
+      (error "~S is not a defined type class method." name)))
+
+
+(eval-when (:compile-toplevel :execute)
+
+;;; INVOKE-TYPE-METHOD  --  Interface
+;;;
+;;;    Invoke a type method on TYPE1 and TYPE2.  If the two types have the same
+;;; class, invoke the simple method.  Otherwise, invoke any complex method.  If
+;;; there isn't a distinct complex-arg1 method, then swap the arguments when
+;;; calling type1's method.  If no applicable method, return DEFAULT.
+;;;
+
+(defmacro invoke-type-method (simple complex-arg2 type1 type2 &key
+                                     (default '(values nil t))
+                                     complex-arg1)
+  (let ((simple (class-function-slot-or-lose simple))
+        (cslot1 (class-function-slot-or-lose (or complex-arg1 complex-arg2)))
+        (cslot2 (class-function-slot-or-lose complex-arg2)))
+    (once-only ((n-type1 type1)
+                (n-type2 type2))
+      (once-only ((class1 `(ctype-class-info ,n-type1))
+                  (class2 `(ctype-class-info ,n-type2)))
+        `(if (eq ,class1 ,class2)
+           (funcall (%svref ,class1 ,simple) ,n-type1 ,n-type2)
+           ,(once-only ((complex1 `(%svref ,class1 ,cslot1))
+                        (complex2 `(%svref ,class2 ,cslot2)))
+              `(cond (,complex2 (funcall ,complex2 ,n-type1 ,n-type2))
+                     (,complex1
+                      ,(if complex-arg1
+                         `(funcall ,complex1 ,n-type1 ,n-type2)
+                         `(funcall ,complex1 ,n-type2 ,n-type1)))
+                     (t ,default))))))))
+
+
+
+;;;; Utilities:
+
+;;; ANY-TYPE-OP, EVERY-TYPE-OP  --  Interface
+;;;
+;;;    Like ANY and EVERY, except that we handle two-arg uncertain predicates.
+;;; If the result is uncertain, then we return Default from the block PUNT.
+;;; If LIST-FIRST is true, then the list element is the first arg, otherwise
+;;; the second.
+;;;
+(defmacro any-type-op (op thing list &key (default '(values nil nil))
+			        list-first)
+  (let ((n-this (gensym))
+	  (n-thing (gensym))
+	  (n-val (gensym))
+	  (n-win (gensym))
+	  (n-uncertain (gensym)))
+    `(let ((,n-thing ,thing)
+	     (,n-uncertain nil))
+       (dolist (,n-this ,list
+			      (if ,n-uncertain
+			        (return-from PUNT ,default)
+			        nil))
+	   (multiple-value-bind (,n-val ,n-win)
+			            ,(if list-first
+				         `(,op ,n-this ,n-thing)
+				         `(,op ,n-thing ,n-this))
+	     (unless ,n-win (setq ,n-uncertain t))
+	     (when ,n-val (return t)))))))
+;;;
+(defmacro every-type-op (op thing list &key (default '(values nil nil))
+			          list-first)
+  (let ((n-this (gensym))
+	  (n-thing (gensym))
+	  (n-val (gensym))
+	  (n-win (gensym)))
+    `(let ((,n-thing ,thing))
+       (dolist (,n-this ,list t)
+	   (multiple-value-bind (,n-val ,n-win)
+			            ,(if list-first
+				         `(,op ,n-this ,n-thing)
+				         `(,op ,n-thing ,n-this))
+	     (unless ,n-win (return-from PUNT ,default))
+	     (unless ,n-val (return nil)))))))
+
+)
+
+  
+;;; VANILLA-INTERSECTION  --  Interface
+;;;
+;;;    Compute the intersection for types that intersect only when one is a
+;;; hierarchical subtype of the other.
+;;;
+(defun vanilla-intersection (type1 type2)
+  (multiple-value-bind (stp1 win1)
+		           (csubtypep type1 type2)
+    (multiple-value-bind (stp2 win2)
+			       (csubtypep type2 type1)
+      (cond (stp1 (values type1 t))
+	      (stp2 (values type2 t))
+	      ((and win1 win2) (values *empty-type* t))
+	      (t
+	       (values type1 nil))))))
+
+
+;;; VANILLA-UNION  --  Interface
+;;;
+(defun vanilla-union (type1 type2)
+  (cond ((csubtypep type1 type2) type2)
+	((csubtypep type2 type1) type1)
+	(t nil)))
+
+(defun hierarchical-intersection2 (type1 type2)
+  (multiple-value-bind (subtypep1 win1) (csubtypep type1 type2)
+    (multiple-value-bind (subtypep2 win2) (csubtypep type2 type1)
+      (cond (subtypep1 type1)
+	    (subtypep2 type2)
+	    ((and win1 win2) *empty-type*)
+	    (t nil)))))
+
+(defun hierarchical-union2 (type1 type2)
+  (cond ((csubtypep type1 type2) type2)
+	((csubtypep type2 type1) type1)
+	(t nil)))
+
+;;; DELEGATE-COMPLEX-{SUBTYPEP-ARG2,INTERSECTION}  --  Interface
+;;;
+;;;    These functions are used as method for types which need a complex
+;;; subtypep method to handle some superclasses, but cover a subtree of the
+;;; type graph (i.e. there is no simple way for any other type class to be a
+;;; subtype.)  There are always still complex ways, namely UNION and MEMBER
+;;; types, so we must give TYPE1's method a chance to run, instead of
+;;; immediately returning NIL, T.
+;;;
+(defun delegate-complex-subtypep-arg2 (type1 type2)
+  (let ((subtypep-arg1
+	 (type-class-complex-subtypep-arg1
+	  (ctype-class-info type1))))
+    (if subtypep-arg1
+	(funcall subtypep-arg1 type1 type2)
+	(values nil t))))
+;;;
+(defun delegate-complex-intersection (type1 type2)
+  (let ((method (type-class-complex-intersection (ctype-class-info type1))))
+    (if (and method (not (eq method #'delegate-complex-intersection)))
+	(funcall method type2 type1)
+	(hierarchical-intersection2 type1 type2))))
+
+;;; HAS-SUPERCLASSES-COMPLEX-SUBTYPEP-ARG1  --  Internal
+;;;
+;;;    Used by DEFINE-SUPERCLASSES to define the SUBTYPE-ARG1 method.  Info is
+;;; a list of conses (SUPERCLASS-CLASS . {GUARD-TYPE-SPECIFIER | NIL}).  Will
+;;; never be called with a hairy type as type2, since the hairy type type2
+;;; method gets first crack.
+;;;
+#|
+(defun has-superclasses-complex-subtypep-arg1 (type1 type2 info)
+  (values
+   (and (typep type2 'class)
+	(dolist (x info nil)
+	  (when (or (not (cdr x))
+		    (csubtypep type1 (specifier-type (cdr x))))
+	    (return
+	     (or (eq type2 (car x))
+		 (let ((inherits (layout-inherits (class-layout (car x)))))
+		   (dotimes (i (length inherits) nil)
+		     (when (eq type2 (layout-class (svref inherits i)))
+		       (return t)))))))))
+   t))
+|#
+
+(eval-when (:compile-toplevel :execute)
+;;; DEFINE-SUPERCLASSES  --  Interface
+;;;
+;;;    Takes a list of specs of the form (superclass &optional guard).
+;;; Consider one spec (with no guard): any instance of type-class is also a
+;;; subtype of SUPERCLASS and of any of its superclasses.  If there are
+;;; multiple specs, then some will have guards.  We choose the first spec whose
+;;; guard is a supertype of TYPE1 and use its superclass.  In effect, a
+;;; sequence of guards G0, G1, G2 is actually G0, (and G1 (not G0)),
+;;; (and G2 (not (or G0 G1))).
+;;;
+#|
+(defmacro define-superclasses (type-class &rest specs)
+  (let ((info
+	 (mapcar #'(lambda (spec)
+		     (destructuring-bind (super &optional guard)
+					 spec
+		       (cons (find-class super) guard)))
+		 specs)))
+    `(progn
+      (setf (type-class-complex-subtypep-arg1
+	     (type-class-or-lose ',type-class))
+	    #'(lambda (type1 type2)
+		(has-superclasses-complex-subtypep-arg1 type1 type2 ',info)))
+       
+       (setf (type-class-complex-subtypep-arg2
+	      (type-class-or-lose ',type-class))
+	     #'delegate-complex-subtypep-arg2)
+       
+       (setf (type-class-complex-intersection
+	      (type-class-or-lose ',type-class))
+	     #'delegate-complex-intersection))))
+|#
+
+); eval-when (compile eval)
+
+
+(defun reparse-unknown-ctype (type)
+  (if (unknown-ctype-p type)
+    (specifier-type (type-specifier type))
+    type))
+
+(defun swapped-args-fun (f)
+  #'(lambda (x y)
+      (funcall f y x)))
+
+(defun equal-but-no-car-recursion (x y)
+  (cond ((eql x y) t)
+	((consp x)
+	 (and (consp y)
+	      (eql (car x) (car y))
+	      (equal-but-no-car-recursion (cdr x) (cdr y))))
+	(t nil)))
+
+(defun any/type (op thing list)
+  (declare (type function op))
+  (let ((certain? t))
+    (dolist (i list (values nil certain?))
+      (multiple-value-bind (sub-value sub-certain?) (funcall op thing i)
+	(if sub-certain?
+	    (when sub-value (return (values t t)))
+	    (setf certain? nil))))))
+
+(defun every/type (op thing list)
+  (declare (type function op))
+  (let ((certain? t))
+    (dolist (i list (if certain? (values t t) (values nil nil)))
+      (multiple-value-bind (sub-value sub-certain?) (funcall op thing i)
+	(if sub-certain?
+	    (unless sub-value (return (values nil t)))
+	    (setf certain? nil))))))
+
+(defun invoke-complex-=-other-method (type1 type2)
+  (let* ((type-class (ctype-class-info type1))
+	 (method-fun (type-class-complex-= type-class)))
+    (if method-fun
+	(funcall (the function method-fun) type2 type1)
+	(values nil t))))
+
+(defun invoke-complex-subtypep-arg1-method (type1 type2 &optional subtypep win)
+  (let* ((type-class (ctype-class-info type1))
+	 (method-fun (type-class-complex-subtypep-arg1 type-class)))
+    (if method-fun
+      (funcall (the function method-fun) type1 type2)
+      (values subtypep win))))
+
+(defun type-might-contain-other-types-p (type)
+  (or (hairy-ctype-p type)
+      (negation-ctype-p type)
+      (union-ctype-p type)
+      (intersection-ctype-p type)))
+
+
+(eval-when (:compile-toplevel :execute)
+
+(defmacro define-type-method ((class method &rest more-methods)
+			            lambda-list &body body)
+  `(progn
+     (let* ((fn (nfunction (,class ,method ,@more-methods)
+                           (lambda ,lambda-list ,@body))))
+       ,@(mapcar #'(lambda (method)
+		         `(setf (%svref
+			           (type-class-or-lose ',class)
+                             ,(class-function-slot-or-lose method))
+			          fn))
+		     (cons method more-methods)))
+     nil))
+
+)
+
+
+(defun ctype-p (x)
+  (and (eql (typecode x) target::subtag-istruct)
+       (memq (istruct-type-name x)
+             '#.(cons 'ctype 
+                      (cons 'unknown-ctype                             
+                            (append (mapcar #'class-name 
+                                            (class-direct-subclasses (find-class 'args-ctype)))
+                                    (mapcar #'class-name 
+                                            (class-direct-subclasses (find-class 'ctype)))))))))
+
+
+(setf (type-predicate 'ctype) 'ctype-p)
+
+
+;;;; Function and Values types.
+;;;
+;;;    Pretty much all of the general type operations are illegal on VALUES
+;;; types, since we can't discriminate using them, do SUBTYPEP, etc.  FUNCTION
+;;; types are acceptable to the normal type operations, but are generally
+;;; considered to be equivalent to FUNCTION.  These really aren't true types in
+;;; any type theoretic sense, but we still parse them into CTYPE structures for
+;;; two reasons:
+;;; -- Parsing and unparsing work the same way, and indeed we can't tell
+;;;    whether a type is a function or values type without parsing it.
+;;; -- Many of the places that can be annotated with real types can also be
+;;;    annotated function or values types.
+
+;; Methods on the VALUES type class.
+
+(defun make-values-ctype (&key
+                          required
+                          optional
+                          rest
+                          keyp
+                          keywords
+                          allowp)
+  (%istruct 'values-ctype
+            (type-class-or-lose 'values)
+            nil
+            required
+            optional
+            rest
+            keyp
+            keywords
+            allowp
+           ))
+
+(defun values-ctype-p (x) (istruct-typep x 'values-ctype))
+(setf (type-predicate 'values-ctype) 'values-ctype-p)
+
+
+(define-type-method (values :simple-subtypep :complex-subtypep-arg1)
+		    (type1 type2)
+  (declare (ignore type2))
+  (error "Subtypep is illegal on this type:~%  ~S" (type-specifier type1)))
+
+(define-type-method (values :complex-subtypep-arg2)
+		    (type1 type2)
+  (declare (ignore type1))
+  (error "Subtypep is illegal on this type:~%  ~S" (type-specifier type2)))
+
+
+(define-type-method (values :unparse) (type)
+  (cons 'values (unparse-args-types type)))
+
+
+;;; TYPE=-LIST  --  Internal
+;;;
+;;;    Return true if List1 and List2 have the same elements in the same
+;;; positions according to TYPE=.  We return NIL, NIL if there is an uncertain
+;;; comparison. 
+;;;
+(defun type=-list (list1 list2)
+  (declare (list list1 list2))
+  (do ((types1 list1 (cdr types1))
+       (types2 list2 (cdr types2)))
+      ((or (null types1) (null types2))
+       (if (or types1 types2)
+	   (values nil t)
+	   (values t t)))
+    (multiple-value-bind (val win)
+			       (type= (first types1) (first types2))
+      (unless win
+	  (return (values nil nil)))
+      (unless val
+	  (return (values nil t))))))
+
+(define-type-method (values :simple-=) (type1 type2)
+  (let ((rest1 (args-ctype-rest type1))
+	(rest2 (args-ctype-rest type2)))
+    (cond ((or (args-ctype-keyp type1) (args-ctype-keyp type2)
+	       (args-ctype-allowp type1) (args-ctype-allowp type2))
+	     (values nil nil))
+	    ((and rest1 rest2 (type/= rest1 rest2))
+	     (type= rest1 rest2))
+	    ((or rest1 rest2)
+	     (values nil t))
+	    (t
+	     (multiple-value-bind (req-val req-win)
+		 (type=-list (values-ctype-required type1)
+			     (values-ctype-required type2))
+	       (multiple-value-bind (opt-val opt-win)
+		   (type=-list (values-ctype-optional type1)
+			       (values-ctype-optional type2))
+	         (values (and req-val opt-val) (and req-win opt-win))))))))
+
+
+;; Methods on the FUNCTION type class.
+
+
+(defun make-function-ctype (&key
+                            required
+                            optional
+                            rest
+                            keyp
+                            keywords
+                            allowp
+                            wild-args
+                            returns)
+  (%istruct 'function-ctype
+            (type-class-or-lose 'function)
+            nil
+            required
+            optional
+            rest
+            keyp
+            keywords
+            allowp
+            wild-args
+            returns
+           ))
+
+(defun function-ctype-p (x) (istruct-typep x 'function-ctype))
+(setf (type-predicate 'function-ctype) 'function-ctype-p)
+
+;;; A flag that we can bind to cause complex function types to be unparsed as
+;;; FUNCTION.  Useful when we want a type that we can pass to TYPEP.
+;;;
+(defvar *unparse-function-type-simplify* nil)
+
+(define-type-method (function :unparse) (type)
+  (if *unparse-function-type-simplify*
+    'function
+    (list 'function
+	    (if (function-ctype-wild-args type)
+		'*
+		(unparse-args-types type))
+	    (type-specifier
+	     (function-ctype-returns type)))))
+
+;;; Since all function types are equivalent to FUNCTION, they are all subtypes
+;;; of each other.
+;;;
+
+(define-type-method (function :simple-subtypep) (type1 type2)
+ (flet ((fun-type-simple-p (type)
+          (not (or (function-ctype-rest type)
+                   (function-ctype-keyp type))))
+        (every-csubtypep (types1 types2)
+          (loop
+             for a1 in types1
+             for a2 in types2
+             do (multiple-value-bind (res sure-p)
+                    (csubtypep a1 a2)
+                  (unless res (return (values res sure-p))))
+             finally (return (values t t)))))
+   (macrolet ((3and (x y)
+                `(multiple-value-bind (val1 win1) ,x
+                   (if (and (not val1) win1)
+                       (values nil t)
+                       (multiple-value-bind (val2 win2) ,y
+                         (if (and val1 val2)
+                             (values t t)
+                             (values nil (and win2 (not val2)))))))))
+     (3and (values-subtypep (function-ctype-returns type1)
+                            (function-ctype-returns type2))
+           (cond ((function-ctype-wild-args type2) (values t t))
+                 ((function-ctype-wild-args type1)
+                  (cond ((function-ctype-keyp type2) (values nil nil))
+                        ((not (function-ctype-rest type2)) (values nil t))
+                        ((not (null (function-ctype-required type2))) (values nil t))
+                        (t (3and (type= *universal-type* (function-ctype-rest type2))
+                                 (every/type #'type= *universal-type*
+                                             (function-ctype-optional type2))))))
+                 ((not (and (fun-type-simple-p type1)
+                            (fun-type-simple-p type2)))
+                  (values nil nil))
+                 (t (multiple-value-bind (min1 max1) (function-type-nargs type1)
+                      (multiple-value-bind (min2 max2) (function-type-nargs type2)
+                        (cond ((or (> max1 max2) (< min1 min2))
+                               (values nil t))
+                              ((and (= min1 min2) (= max1 max2))
+                               (3and (every-csubtypep (function-ctype-required type1)
+                                                      (function-ctype-required type2))
+                                     (every-csubtypep (function-ctype-optional type1)
+                                                      (function-ctype-optional type2))))
+                              (t (every-csubtypep
+                                  (concatenate 'list
+                                               (function-ctype-required type1)
+                                               (function-ctype-optional type1))
+                                  (concatenate 'list
+                                               (function-ctype-required type2)
+                                               (function-ctype-optional type2)))))))))))))
+
+
+                   
+;(define-superclasses function (function))       
+
+
+;;; The union or intersection of two FUNCTION types is FUNCTION.
+;;; (unless the types are type=)
+;;;
+(define-type-method (function :simple-union) (type1 type2)
+  (if (type= type1 type2)
+    type1
+    (specifier-type 'function)))
+
+;;;
+(define-type-method (function :simple-intersection) (type1 type2)
+  (if (type= type1 type2)
+    type1
+    (specifier-type 'function)))
+
+
+(define-type-method (function :complex-intersection) (type1 type2)
+  (declare (type function-ctype type2))
+  (let ((function (specifier-type 'function)))
+    (if (eq type1 function)
+      type2
+      (type-intersection2 type1 function))))
+
+
+
+;;; ### Not very real, but good enough for redefining transforms according to
+;;; type:
+;;;
+(define-type-method (function :simple-=) (type1 type2)
+  (values (equalp type1 type2) t))
+
+;;; The CONSTANT-TYPE structure represents a use of the CONSTANT-ARGUMENT "type
+;;; specifier", which is only meaningful in function argument type specifiers
+;;; used within the compiler.
+;;;
+
+(defun clone-type-class-methods (src-tc dest-tc)
+  (do* ((n (uvsize src-tc))
+        (i 2 (1+ i)))
+       ((= i n) dest-tc)
+    (declare (fixnum i n))
+    (setf (%svref dest-tc i)
+          (%svref src-tc i))))
+
+(clone-type-class-methods (type-class-or-lose 'values) (type-class-or-lose 'constant))
+
+(defun make-constant-ctype (&key type)
+  (%istruct 'constant-ctype
+            (type-class-or-lose 'constant)
+            nil
+            type))
+
+(defun constant-ctype-p (x) (istruct-typep x 'constant-ctype))
+(setf (type-predicate 'constant-ctype) 'constant-ctype-p)
+
+(define-type-method (constant :unparse) (type)
+  `(constant-argument ,(type-specifier (constant-ctype-type type))))
+
+(define-type-method (constant :simple-=) (type1 type2)
+  (type= (constant-ctype-type type1) (constant-ctype-type type2)))
+
+(def-type-translator constant-argument (type &environment env)
+  (make-constant-ctype :type (specifier-type type env)))
+
+
+;;; Parse-Args-Types  --  Internal
+;;;
+;;;    Given a lambda-list like values type specification and a Args-Type
+;;; structure, fill in the slots in the structure accordingly.  This is used
+;;; for both FUNCTION and VALUES types.
+;;;
+
+(defun parse-args-types (lambda-list result &optional env)
+  (multiple-value-bind (required optional restp rest keyp keys allowp aux)
+		           (parse-lambda-list lambda-list)
+    (when aux
+      (error "&Aux in a FUNCTION or VALUES type: ~S." lambda-list))
+    (flet ((parse (spec) (specifier-type spec env)))
+      (setf (args-ctype-required result) (mapcar #'parse required))
+      (setf (args-ctype-optional result) (mapcar #'parse optional))
+      (setf (args-ctype-rest result) (if restp (parse rest) nil))
+      (setf (args-ctype-keyp result) keyp)
+      (let* ((key-info ()))
+        (dolist (key keys)
+	  (when (or (atom key) (/= (length key) 2))
+	    (signal-program-error "Keyword type description is not a two-list: ~S." key))
+	  (let ((kwd (first key)))
+	    (when (member kwd key-info :test #'eq :key #'(lambda (x) (key-info-name x)))
+	      (signal-program-error "Repeated keyword ~S in lambda list: ~S." kwd lambda-list))
+	    (push (make-key-info :name kwd
+                                 :type (parse (second key))) key-info)))
+        (setf (args-ctype-keywords result) (nreverse key-info)))
+      (setf (args-ctype-allowp result) allowp))))
+
+;;; Unparse-Args-Types  --  Internal
+;;;
+;;;    Return the lambda-list like type specification corresponding
+;;; to a Args-Type.
+;;;
+(defun unparse-args-types (type)
+  (let* ((result ()))
+
+    (dolist (arg (args-ctype-required type))
+      (push (type-specifier arg) result))
+
+    (when (args-ctype-optional type)
+      (push '&optional result)
+      (dolist (arg (args-ctype-optional type))
+	  (push (type-specifier arg) result)))
+
+    (when (args-ctype-rest type)
+      (push '&rest result)
+      (push (type-specifier (args-ctype-rest type)) result))
+
+    (when (args-ctype-keyp type)
+      (push '&key result)
+      (dolist (key (args-ctype-keywords type))
+	  (push (list (key-info-name key)
+                    (type-specifier (key-info-type key))) result)))
+
+    (when (args-ctype-allowp type)
+      (push '&allow-other-keys result))
+
+    (nreverse result)))
+
+(def-type-translator function (&optional (args '*) (result '*) &environment env)
+  (let ((res (make-function-ctype
+	        :returns (values-specifier-type result env))))
+    (if (eq args '*)
+	(setf (function-ctype-wild-args res) t)
+	(parse-args-types args res env))
+    res))
+
+(def-type-translator values (&rest values &environment env)
+  (let ((res (make-values-ctype)))
+    (parse-args-types values res env)
+    (when (or (values-ctype-keyp res) (values-ctype-allowp res))
+      (signal-program-error "&KEY or &ALLOW-OTHER-KEYS in values type: ~s"
+			    res))
+    res))
+
+;;; Single-Value-Type  --  Interface
+;;;
+;;;    Return the type of the first value indicated by Type.  This is used by
+;;; people who don't want to have to deal with values types.
+;;;
+(defun single-value-type (type)
+  (declare (type ctype type))
+  (cond ((values-ctype-p type)
+	 (or (car (args-ctype-required type))
+	     (if (args-ctype-optional type)
+                 (type-union (car (args-ctype-optional type))
+			     (specifier-type 'null)))
+	     (args-ctype-rest type)
+	     (specifier-type 'null)))
+	((eq type *wild-type*)
+	 *universal-type*)
+	(t
+	 type)))
+
+
+;;; FUNCTION-TYPE-NARGS  --  Interface
+;;;
+;;;    Return the minmum number of arguments that a function can be called
+;;; with, and the maximum number or NIL.  If not a function type, return
+;;; NIL, NIL.
+;;;
+(defun function-type-nargs (type)
+  (declare (type ctype type))
+  (if (function-ctype-p type)
+    (let ((fixed (length (args-ctype-required type))))
+	(if (or (args-ctype-rest type)
+		  (args-ctype-keyp type)
+		  (args-ctype-allowp type))
+        (values fixed nil)
+        (values fixed (+ fixed (length (args-ctype-optional type))))))
+    (values nil nil)))
+
+
+;;; Values-Types  --  Interface
+;;;
+;;;    Determine if Type corresponds to a definite number of values.  The first
+;;; value is a list of the types for each value, and the second value is the
+;;; number of values.  If the number of values is not fixed, then return NIL
+;;; and :Unknown.
+;;;
+(defun values-types (type)
+  (declare (type ctype type))
+  (cond ((eq type *wild-type*)
+	   (values nil :unknown))
+	  ((not (values-ctype-p type))
+	   (values (list type) 1))
+	  ((or (args-ctype-optional type)
+	       (args-ctype-rest type)
+	       (args-ctype-keyp type)
+	       (args-ctype-allowp type))
+	   (values nil :unknown))
+	  (t
+	   (let ((req (args-ctype-required type)))
+	     (values (mapcar #'single-value-type req) (length req))))))
+
+
+;;; Values-Type-Types  --  Internal
+;;;
+;;;    Return two values:
+;;; 1] A list of all the positional (fixed and optional) types.
+;;; 2] The rest type (if any).  If keywords allowed, *universal-type*.  If no
+;;;    keywords or rest, *empty-type*.
+;;;
+(defun values-type-types (type &optional (default-type *empty-type*))
+  (declare (type values-ctype type))
+  (values (append (args-ctype-required type)
+		  (args-ctype-optional type))
+	    (cond ((args-ctype-keyp type) *universal-type*)
+		  ((args-ctype-rest type))
+		  (t default-type))))
+
+
+;;; Fixed-Values-Op  --  Internal
+;;;
+;;;    Return a list of Operation applied to the types in Types1 and Types2,
+;;; padding with Rest2 as needed.  Types1 must not be shorter than Types2.  The
+;;; second value is T if Operation always returned a true second value.
+;;;
+(defun fixed-values-op (types1 types2 rest2 operation)
+  (declare (list types1 types2) (type ctype rest2) (type function operation))
+  (let ((exact t))
+    (values (mapcar #'(lambda (t1 t2)
+			      (multiple-value-bind (res win)
+				  (funcall operation t1 t2)
+			        (unless win (setq exact nil))
+			        res))
+		        types1
+		        (append types2
+				(make-list (- (length types1) (length types2))
+					   :initial-element rest2)))
+	      exact)))
+
+;;; Coerce-To-Values  --  Internal
+;;;
+;;; If Type isn't a values type, then make it into one:
+;;;    <type>  ==>  (values type &rest t)
+;;;
+(defun coerce-to-values (type)
+  (declare (type ctype type))
+  (if (values-ctype-p type)
+    type
+    (make-values-ctype :required (list type))))
+
+
+;;; Args-Type-Op  --  Internal
+;;;
+;;;    Do the specified Operation on Type1 and Type2, which may be any type,
+;;; including Values types.  With values types such as:
+;;;    (values a0 a1)
+;;;    (values b0 b1)
+;;;
+;;; We compute the more useful result:
+;;;    (values (<operation> a0 b0) (<operation> a1 b1))
+;;;
+;;; Rather than the precise result:
+;;;    (<operation> (values a0 a1) (values b0 b1))
+;;;
+;;; This has the virtue of always keeping the values type specifier outermost,
+;;; and retains all of the information that is really useful for static type
+;;; analysis.  We want to know what is always true of each value independently.
+;;; It is worthless to know that IF the first value is B0 then the second will
+;;; be B1.
+;;;
+;;; If the values count signatures differ, then we produce result with the
+;;; required value count chosen by Nreq when applied to the number of required
+;;; values in type1 and type2.  Any &key values become &rest T (anyone who uses
+;;; keyword values deserves to lose.)
+;;;
+;;; The second value is true if the result is definitely empty or if Operation
+;;; returned true as its second value each time we called it.  Since we
+;;; approximate the intersection of values types, the second value being true
+;;; doesn't mean the result is exact.
+;;;
+(defun args-type-op (type1 type2 operation nreq default-type)
+  (declare (type ctype type1 type2 default-type)
+	   (type function operation nreq))
+  (if (eq type1 type2)
+    (values type1 t)
+    (if (or (values-ctype-p type1) (values-ctype-p type2))
+      (let ((type1 (coerce-to-values type1))
+	    (type2 (coerce-to-values type2)))
+	(multiple-value-bind (types1 rest1)
+	    (values-type-types type1 default-type)
+	  (multiple-value-bind (types2 rest2)
+	      (values-type-types type2 default-type)
+	    (multiple-value-bind (rest rest-exact)
+		(funcall operation rest1 rest2)
+	      (multiple-value-bind
+		  (res res-exact)
+		  (if (< (length types1) (length types2))
+		    (fixed-values-op types2 types1 rest1 operation)
+		    (fixed-values-op types1 types2 rest2 operation))
+		(let* ((req (funcall nreq
+				     (length (args-ctype-required type1))
+				     (length (args-ctype-required type2))))
+		       (required (subseq res 0 req))
+		       (opt (subseq res req))
+		       (opt-last (position rest opt :test-not #'type=
+					   :from-end t)))
+		  (if (find *empty-type* required :test #'type=)
+		    (values *empty-type* t)
+		    (values (make-values-ctype
+			     :required required
+			     :optional (if opt-last
+					 (subseq opt 0 (1+ opt-last))
+					 ())
+			     :rest (if (eq rest *empty-type*) nil rest))
+			    (and rest-exact res-exact)))))))))
+      (funcall operation type1 type2))))
+
+;;; Values-Type-Union, Values-Type-Intersection  --  Interface
+;;;
+;;;    Do a union or intersection operation on types that might be values
+;;; types.  The result is optimized for utility rather than exactness, but it
+;;; is guaranteed that it will be no smaller (more restrictive) than the
+;;; precise result.
+;;;
+
+(defun values-type-union (type1 type2)
+  (declare (type ctype type1 type2))
+  (cond ((or (eq type1 *wild-type*) (eq type2 *wild-type*)) *wild-type*)
+	((eq type1 *empty-type*) type2)
+	((eq type2 *empty-type*) type1)
+	(t
+	 (values (args-type-op type1 type2 #'type-union #'min *empty-type*)))))
+
+(defun values-type-intersection (type1 type2)
+  (declare (type ctype type1 type2))
+  (cond ((eq type1 *wild-type*) (values type2 t))
+	((eq type2 *wild-type*) (values type1 t))
+	(t
+	 (args-type-op type1 type2 #'type-intersection #'max
+		       (specifier-type 'null)))))
+
+
+;;; Values-Types-Intersect  --  Interface
+;;;
+;;;    Like Types-Intersect, except that it sort of works on values types.
+;;; Note that due to the semantics of Values-Type-Intersection, this might
+;;; return {T, T} when there isn't really any intersection (?).
+;;;
+(defun values-types-intersect (type1 type2)
+  (cond ((or (eq type1 *empty-type*) (eq type2 *empty-type*))
+	   (values t t))
+	  ((or (values-ctype-p type1) (values-ctype-p type2))
+	   (multiple-value-bind (res win)
+			            (values-type-intersection type1 type2)
+	     (values (not (eq res *empty-type*))
+		       win)))
+	  (t
+	   (types-intersect type1 type2))))
+
+;;; Values-Subtypep  --  Interface
+;;;
+;;;    A subtypep-like operation that can be used on any types, including
+;;; values types.
+;;;
+
+(defun values-subtypep (type1 type2)
+  (declare (type ctype type1 type2))
+  (cond ((eq type2 *wild-type*) (values t t))
+	((eq type1 *wild-type*)
+	 (values (eq type2 *universal-type*) t))
+	((not (values-types-intersect type1 type2))
+	 (values nil t))
+	(t
+	 (if (or (values-ctype-p type1) (values-ctype-p type2))
+	   (let ((type1 (coerce-to-values type1))
+		 (type2 (coerce-to-values type2)))
+	     (multiple-value-bind (types1 rest1)
+		 (values-type-types type1)
+	       (multiple-value-bind (types2 rest2)
+		   (values-type-types type2)
+		 (cond ((< (length (values-ctype-required type1))
+			   (length (values-ctype-required type2)))
+			(values nil t))
+		       ((< (length types1) (length types2))
+			(values nil nil))
+		       ((or (values-ctype-keyp type1)
+			    (values-ctype-keyp type2))
+			(values nil nil))
+		       (t
+			(do ((t1 types1 (rest t1))
+			     (t2 types2 (rest t2)))
+			    ((null t2)
+			     (csubtypep rest1 rest2))
+			  (multiple-value-bind
+			      (res win-p)
+			      (csubtypep (first t1) (first t2))
+			    (unless win-p
+			      (return (values nil nil)))
+			    (unless res
+			      (return (values nil t))))))))))
+	   (csubtypep type1 type2)))))
+  
+
+
+;;;; Type method interfaces:
+
+;;; Csubtypep  --  Interface
+;;;
+;;;    Like subtypep, only works on Type structures.
+;;;
+(defun csubtypep (type1 type2)
+  (declare (type ctype type1 type2))
+  (unless (typep type1 'ctype)
+    (report-bad-arg type1 'ctype))
+  (unless (typep type2 'ctype)
+    (report-bad-arg type2 'ctype))
+  (cond ((or (eq type1 type2)
+	     (eq type1 *empty-type*)
+	     (eq type2 *wild-type*))
+	 (values t t))
+	(t
+	 (invoke-type-method :simple-subtypep :complex-subtypep-arg2
+			     type1 type2
+			     :complex-arg1 :complex-subtypep-arg1))))
+
+;;; Type1 is a type-epecifier; type2 is a TYPE-CELL which may cache
+;;; a mapping between a type-specifier and a CTYPE.
+(defun cell-csubtypep-2 (type-specifier type-cell)
+  (let* ((type1 (specifier-type type-specifier))
+         (type2 (or (type-cell-ctype type-cell)
+                    (let* ((ctype (specifier-type
+                                   (type-cell-type-specifier type-cell))))
+                      (when (cacheable-ctype-p ctype)
+                        (setf (type-cell-ctype type-cell) ctype))
+                      ctype))))
+    (cond ((or (eq type1 type2)
+               (eq type1 *empty-type*)
+               (eq type2 *wild-type*))
+           (values t t))
+          (t
+           (invoke-type-method :simple-subtypep :complex-subtypep-arg2
+                               type1 type2
+                               :complex-arg1 :complex-subtypep-arg1)))))
+                              
+
+
+;;; Type=  --  Interface
+;;;
+;;;    If two types are definitely equivalent, return true.  The second value
+;;; indicates whether the first value is definitely correct.  This should only
+;;; fail in the presence of Hairy types.
+;;;
+
+(defun type= (type1 type2)
+   (declare (type ctype type1 type2))
+   (if (eq type1 type2)
+     (values t t)
+     (invoke-type-method :simple-= :complex-= type1 type2)))
+
+;;; TYPE/=  --  Interface
+;;;
+;;;    Not exactly the negation of TYPE=, since when the relationship is
+;;; uncertain, we still return NIL, NIL.  This is useful in cases where the
+;;; conservative assumption is =.
+;;;
+(defun type/= (type1 type2)
+  (declare (type ctype type1 type2))
+  (multiple-value-bind (res win)
+      (type= type1 type2)
+    (if win
+	(values (not res) t)
+	(values nil nil))))
+
+;;; Type-Union  --  Interface
+;;;
+;;;    Find a type which includes both types.  Any inexactness is represented
+;;; by the fuzzy element types; we return a single value that is precise to the
+;;; best of our knowledge.  This result is simplified into the canonical form,
+;;; thus is not a UNION type unless there is no other way to represent the
+;;; result.
+;;; 
+
+(defun type-union (&rest input-types)
+  (%type-union input-types))
+
+(defun %type-union (input-types)
+  (let* ((simplified (simplify-unions input-types)))
+    (cond ((null simplified) *empty-type*)
+	  ((null (cdr simplified)) (car simplified))
+	  (t (make-union-ctype simplified)))))
+
+(defun simplify-unions (types)
+  (when types
+    (multiple-value-bind (first rest)
+	(if (union-ctype-p (car types))
+	  (values (car (union-ctype-types (car types)))
+		  (append (cdr (union-ctype-types (car types)))
+			  (cdr types)))
+	  (values (car types) (cdr types)))
+      (let ((rest (simplify-unions rest)) u)
+	(dolist (r rest (cons first rest))
+	  (when (setq u (type-union2 first r))
+	    (return (simplify-unions (nsubstitute u r rest)))))))))
+
+(defun type-union2 (type1 type2)
+  (declare (type ctype type1 type2))
+  (setq type1 (reparse-unknown-ctype type1))
+  (setq type2 (reparse-unknown-ctype type2))
+  (cond ((eq type1 type2) type1)
+	((csubtypep type1 type2) type2)
+	((csubtypep type2 type1) type1)
+	(t
+	 (flet ((1way (x y)
+		  (invoke-type-method :simple-union :complex-union
+				      x y
+				      :default nil)))
+	   (or (1way type1 type2)
+	       (1way type2 type1))))))
+
+;;; Return as restrictive and simple a type as we can discover that is
+;;; no more restrictive than the intersection of TYPE1 and TYPE2. At
+;;; worst, we arbitrarily return one of the arguments as the first
+;;; value (trying not to return a hairy type).
+(defun type-approx-intersection2 (type1 type2)
+  (declare (type ctype type1 type2))
+  (cond ((type-intersection2 type1 type2))
+	((hairy-ctype-p type1) type2)
+	(t type1)))
+
+
+;;; Type-Intersection  --  Interface
+;;;
+;;;    Return as restrictive a type as we can discover that is no more
+;;; restrictive than the intersection of Type1 and Type2.  The second value is
+;;; true if the result is exact.  At worst, we randomly return one of the
+;;; arguments as the first value (trying not to return a hairy type).
+;;;
+
+(defun type-intersection (&rest input-types)
+  (%type-intersection input-types))
+
+(defun %type-intersection (input-types)
+  (let ((simplified (simplify-intersections input-types)))
+    ;;(declare (type (vector ctype) simplified))
+    ;; We want to have a canonical representation of types (or failing
+    ;; that, punt to HAIRY-TYPE). Canonical representation would have
+    ;; intersections inside unions but not vice versa, since you can
+    ;; always achieve that by the distributive rule. But we don't want
+    ;; to just apply the distributive rule, since it would be too easy
+    ;; to end up with unreasonably huge type expressions. So instead
+    ;; we try to generate a simple type by distributing the union; if
+    ;; the type can't be made simple, we punt to HAIRY-TYPE.
+    (if (and (cdr simplified) (some #'union-ctype-p simplified))
+      (let* ((first-union (find-if #'union-ctype-p simplified))
+             (other-types (remove first-union simplified))
+             (distributed (maybe-distribute-one-union first-union other-types)))
+        (if distributed
+          (apply #'type-union distributed)
+          (make-hairy-ctype
+           :specifier `(and ,@(mapcar #'type-specifier simplified)))))
+      (cond
+        ((null simplified) *universal-type*)
+        ((null (cdr simplified)) (car simplified))
+        (t (make-intersection-ctype
+            (some #'(lambda (c) (ctype-enumerable c)) simplified)
+            simplified))))))
+
+(defun simplify-intersections (types)
+  (when types
+    (let ((first (if (typep (car types) 'ctype)
+		   (%car types)
+		   (specifier-type (%car types)))))
+      (multiple-value-bind (first rest)
+	  (if (intersection-ctype-p first)
+	    (values (car (intersection-ctype-types first))
+		    (append (cdr (intersection-ctype-types first))
+			    (cdr types)))
+	    (values first (cdr types)))
+	(let ((rest (simplify-intersections rest)) u)
+	  (dolist (r rest (cons first rest))
+	    (when (setq u (type-intersection2 first r))
+	      (return (simplify-intersections (nsubstitute u r rest))))))))))
+
+(defun type-intersection2 (type1 type2)
+  (declare (type ctype type1 type2))
+  (setq type1 (reparse-unknown-ctype type1))
+  (setq type2 (reparse-unknown-ctype type2))
+  (cond ((eq type1 type2)
+	 type1)
+	((or (intersection-ctype-p type1)
+	     (intersection-ctype-p type2))
+	 ;; Intersections of INTERSECTION-TYPE should have the
+	 ;; INTERSECTION-CTYPE-TYPES values broken out and intersected
+	 ;; separately. The full TYPE-INTERSECTION function knows how
+	 ;; to do that, so let it handle it.
+	 (type-intersection type1 type2))
+	;;
+	;; (AND (FUNCTION (T) T) GENERIC-FUNCTION) for instance, but
+	;; not (AND (FUNCTION (T) T) (FUNCTION (T) T)).
+	((let ((function (specifier-type 'function)))
+	   (or (and (function-ctype-p type1)
+		    (not (function-ctype-p type2))
+		    (neq function type2)
+		    (csubtypep type2 function)
+		    (not (csubtypep function type2)))
+	       (and (function-ctype-p type2)
+		    (not (function-ctype-p type1))
+		    (neq function type1)
+		    (csubtypep type1 function)
+		    (not (csubtypep function type1)))))
+	 nil)
+	(t
+	 (flet ((1way (x y)
+		  (invoke-type-method :simple-intersection
+				      :complex-intersection
+				      x y
+				      :default :no-type-method-found)))
+	   (let ((xy (1way type1 type2)))
+	     (or (and (not (eql xy :no-type-method-found)) xy)
+		 (let ((yx (1way type2 type1)))
+		   (or (and (not (eql yx :no-type-method-found)) yx)
+		       (cond ((and (eql xy :no-type-method-found)
+				   (eql yx :no-type-method-found))
+			      *empty-type*)
+			     (t
+			      nil))))))))))
+
+
+
+(defun maybe-distribute-one-union (union-type types)
+  (let* ((intersection (apply #'type-intersection types))
+	 (union (mapcar (lambda (x) (type-intersection x intersection))
+			(union-ctype-types union-type))))
+    (if (notany (lambda (x)
+		  (or (hairy-ctype-p x)
+		      (intersection-ctype-p x)))
+		union)
+	union
+	nil)))
+
+;;; Types-Intersect  --  Interface
+;;;
+;;;    The first value is true unless the types don't intersect.  The second
+;;; value is true if the first value is definitely correct.  NIL is considered
+;;; to intersect with any type.  If T is a subtype of either type, then we also
+;;; return T, T.  This way we consider hairy types to intersect with T.
+;;;
+(defun types-intersect (type1 type2)
+  (declare (type ctype type1 type2))
+  (if (or (eq type1 *empty-type*) (eq type2 *empty-type*))
+      (values t t)
+      (let ((intersection2 (type-intersection2 type1 type2)))
+	(cond ((not intersection2)
+	       (if (or (csubtypep *universal-type* type1)
+		       (csubtypep *universal-type* type2))
+		   (values t t)
+		   (values t nil)))
+	      ((eq intersection2 *empty-type*) (values nil t))
+	      (t (values t t))))))
+
+;;; Type-Specifier  --  Interface
+;;;
+;;;    Return a Common Lisp type specifier corresponding to this type.
+;;;
+(defun type-specifier (type)
+  (unless (ctype-p type)
+    (setq type (require-type type 'ctype)))
+  (locally 
+      (declare (type ctype type))
+    (funcall (type-class-unparse (ctype-class-info type)) type)))
+
+
+(defconstant compound-only-type-specifiers
+  ;; See CLHS Figure 4-4.
+  '(and mod satisfies eql not values member or))
+
+
+;;; VALUES-SPECIFIER-TYPE  --  Interface
+;;;
+;;;    Return the type structure corresponding to a type specifier.  We pick
+;;; off Structure types as a special case.
+;;;
+
+(defun values-specifier-type-internal (orig env)
+  (or (info-type-builtin orig) ; this table could contain bytes etal and ands ors nots of built-in types - no classes
+      
+      ;; Now that we have our hands on the environment, we could pass it into type-expand,
+      ;; but we'd have no way of knowing whether the expansion depended on the env, so
+      ;; we wouldn't know if the result is safe to cache.   So for now don't let type
+      ;; expanders see the env, which just means they won't see compile-time types.
+      (let ((spec (type-expand orig #+not-yet env)))
+        (cond
+         ((and (not (eq spec orig))
+               (info-type-builtin spec)))
+         ((or (eq (info-type-kind spec) :instance)
+              (and (symbolp spec)
+                   (typep (find-class spec nil env) 'compile-time-class)))
+          (let* ((class-ctype (%class.ctype (find-class spec t env))))
+            (or (class-ctype-translation class-ctype)
+                class-ctype)))
+         ((typep spec 'class)
+          (let* ((class-ctype (%class.ctype spec)))
+            (or (class-ctype-translation class-ctype)
+                class-ctype)))
+         ((let ((cell (find-builtin-cell spec nil)))
+           (and cell (cdr cell))))
+         (t
+          (when (member spec compound-only-type-specifiers)
+            (error 'invalid-type-specifier :typespec spec))
+          (let* ((lspec (if (atom spec) (list spec) spec))
+                 (fun (info-type-translator (car lspec))))
+            (cond (fun (funcall fun lspec env))
+                  ((or (and (consp spec)
+                            (symbolp (car spec))
+                            (not (or (find-class (car spec) nil env)
+                                     (info-type-builtin (car spec)))))
+                       (symbolp spec))
+                   (when *type-system-initialized*
+                     (signal 'parse-unknown-type :specifier spec))
+                   ;;
+                   ;; Inhibit caching...
+                   nil)
+                  (t
+                   (error 'invalid-type-specifier :typespec spec)))))))))
+
+(eval-when (:compile-toplevel :execute)
+  (defconstant type-cache-size (ash 1 12))
+  (defconstant type-cache-mask (1- type-cache-size)))
+
+(defun compile-time-ctype-p (ctype)
+  (and (typep ctype 'class-ctype)
+       (typep (class-ctype-class ctype) 'compile-time-class)))
+
+
+;;; We can get in trouble if we try to cache certain kinds of ctypes,
+;;; notably MEMBER types which refer to objects which might
+;;; be stack-allocated or might be EQUAL without being EQL.
+(defun cacheable-ctype-p (ctype)
+  (case (istruct-cell-name (%svref ctype 0))
+    (member-ctype
+     (dolist (m (member-ctype-members ctype) t)
+       (when (or (typep m 'cons)
+		 (typep m 'array))
+	 (return nil))))
+    (union-ctype
+     (every #'cacheable-ctype-p (union-ctype-types ctype)))
+    (intersection-ctype
+     (every #'cacheable-ctype-p (intersection-ctype-types ctype)))
+    (array-ctype
+     (cacheable-ctype-p (array-ctype-element-type ctype)))
+    ((values-ctype function-ctype)
+     (and (every #'cacheable-ctype-p (values-ctype-required ctype))
+	  (every #'cacheable-ctype-p (values-ctype-optional ctype))
+	  (let* ((rest (values-ctype-rest ctype)))
+	    (or (null rest) (cacheable-ctype-p rest)))
+	  (every #'(lambda (info)
+		     (cacheable-ctype-p (key-info-type info)))
+		 (values-ctype-keywords ctype))
+	  (or (not (eq (istruct-cell-name (%svref ctype 0)) 'function-ctype))
+	      (let* ((result (function-ctype-returns ctype)))
+		(or (null result)
+		    (cacheable-ctype-p result))))))
+    (negation-ctype
+     (cacheable-ctype-p (negation-ctype-type ctype)))
+    (cons-ctype
+     (and (cacheable-ctype-p (cons-ctype-car-ctype ctype))
+	  (cacheable-ctype-p (cons-ctype-cdr-ctype ctype))))
+    (unknown-ctype nil)
+    (class-ctype
+     (not (typep (class-ctype-class ctype) 'compile-time-class)))
+    ;; Anything else ?  Simple things (numbers, classes) can't lose.
+    (t t)))
+		
+      
+    
+
+(defun hash-type-specifier (spec)
+  (logand (sxhash spec) type-cache-mask))
+
+
+(let* ((type-cache-specs (make-array type-cache-size))
+       (type-cache-ctypes (make-array type-cache-size))
+       (probes 0)
+       (hits 0)
+       (ncleared 0)
+       (locked nil)
+       (lock (make-lock)))
+  
+  (defun clear-type-cache ()
+    (with-lock-grabbed (lock)
+      (%init-misc 0 type-cache-specs)
+      (%init-misc 0 type-cache-ctypes)
+      (incf ncleared))
+    nil)
+
+  (defun values-specifier-type (spec &optional env)
+    (if (typep spec 'class)
+      (let* ((class-ctype (%class.ctype spec)))
+        (or (class-ctype-translation class-ctype) class-ctype))
+      (handler-case
+          (with-lock-grabbed (lock)
+            (if locked
+              (or (values-specifier-type-internal spec env)
+                  (make-unknown-ctype :specifier spec))
+              (unwind-protect
+                   (progn
+                     (setq locked t)
+                     (if (or (symbolp spec)
+                             (and (consp spec)
+                                  (symbolp (car spec))
+                                  ;; hashing scheme uses equal, so only use when equivalent to eql
+                                  (not (and (eq (car spec) 'member)
+                                            (some (lambda (x)
+                                                    (typep x '(or cons string bit-vector pathname)))
+                                                  (cdr spec))))))
+                       (let* ((idx (hash-type-specifier spec)))
+                         (incf probes)
+                         (if (equal (svref type-cache-specs idx) spec)
+                           (progn
+                             (incf hits)
+                             (svref type-cache-ctypes idx))
+                           (let* ((ctype (values-specifier-type-internal spec env)))
+                             (if ctype
+                               (progn
+                                 (when (cacheable-ctype-p ctype)
+                                   (setf (svref type-cache-specs idx) (copy-tree spec) ; in case it was stack-consed
+                                         (svref type-cache-ctypes idx) ctype))
+                                 ctype)
+                               (make-unknown-ctype :specifier spec)))))
+                       (values-specifier-type-internal spec env)))
+                (setq locked nil))))
+        (error (condition) (error condition)))))
+  
+  (defun type-cache-hit-rate ()
+    (values hits probes))
+  
+  (defun type-cache-locked-p ()
+    locked)
+
+  (defun lock-type-cache ()
+    (setq locked t)))
+                    
+
+  
+
+;;; SPECIFIER-TYPE  --  Interface
+;;;
+;;;    Like VALUES-SPECIFIER-TYPE, except that we guarantee to never return a
+;;; VALUES type.
+;;; 
+(defun specifier-type (x &optional env)
+  (let ((res (values-specifier-type x env)))
+    (when (values-ctype-p res)
+      (signal-program-error "VALUES type illegal in this context:~%  ~S" x))
+    res))
+
+(defun single-value-specifier-type (x &optional env)
+  (let ((res (specifier-type x env)))
+    (if (eq res *wild-type*)
+        *universal-type*
+        res)))
+
+(defun standardized-type-specifier (spec &optional env)
+  (handler-case
+      (type-specifier (specifier-type spec env))
+    (program-error () spec)
+    (parse-unknown-type () spec)))
+
+(defun modified-numeric-type (base
+			      &key
+			      (class      (numeric-ctype-class      base))
+			      (format     (numeric-ctype-format     base))
+			      (complexp   (numeric-ctype-complexp   base))
+			      (low        (numeric-ctype-low        base))
+			      (high       (numeric-ctype-high       base))
+			      (enumerable (ctype-enumerable base)))
+  (make-numeric-ctype :class class
+		     :format format
+		     :complexp complexp
+		     :low low
+		     :high high
+		     :enumerable enumerable))
+
+;;; Precompute-Types  --  Interface
+;;;
+;;;    Take a list of type specifiers, compute the translation and define it as
+;;; a builtin type.
+;;;
+ 
+(defun precompute-types (specs)
+  (dolist (spec specs)
+    (let ((res (specifier-type spec)))
+      (when (numeric-ctype-p res)
+        (let ((pred (make-numeric-ctype-predicate res)))
+          (when pred (setf (numeric-ctype-predicate res) pred))))
+      (unless (unknown-ctype-p res)
+        (setf (info-type-builtin spec) res)
+        (setf (info-type-kind spec) :primitive)))))
+
+;;;; Builtin types.
+
+;;; The NAMED-TYPE is used to represent *, T and NIL.  These types must be
+;;; super or sub types of all types, not just classes and * & NIL aren't
+;;; classes anyway, so it wouldn't make much sense to make them built-in
+;;; classes.
+;;;
+
+(defun define-named-ctype (name)
+  (let* ((ctype (%istruct 'named-ctype
+                          (type-class-or-lose 'named)
+                          nil
+                          name)))
+    (setf (info-type-kind name) :builtin
+          (info-type-builtin name) ctype)))
+
+
+(defvar *wild-type* (define-named-ctype '*))
+(defvar *empty-type* (define-named-ctype nil))
+(defvar *universal-type* (define-named-ctype t))
+
+(defun named-ctype-p (x)
+  (istruct-typep x 'named-ctype))
+
+(setf (type-predicate 'named-ctype) 'named-ctype-p)
+
+(define-type-method (named :simple-=) (type1 type2)
+  (values (eq type1 type2) t))
+
+(define-type-method (named :complex-=) (type1 type2)
+  (cond
+    ((and (eq type2 *empty-type*)
+	  (intersection-ctype-p type1)
+	  ;; not allowed to be unsure on these... FIXME: keep the list
+	  ;; of CL types that are intersection types once and only
+	  ;; once.
+	  (not (or (type= type1 (specifier-type 'ratio))
+		   (type= type1 (specifier-type 'keyword)))))
+     ;; things like (AND (EQL 0) (SATISFIES ODDP)) or (AND FUNCTION
+     ;; STREAM) can get here.  In general, we can't really tell
+     ;; whether these are equal to NIL or not, so
+     (values nil nil))
+    ((type-might-contain-other-types-p type1)
+     (invoke-complex-=-other-method type1 type2))
+    (t (values nil t))))
+
+
+(define-type-method (named :simple-subtypep) (type1 type2)
+  (values (or (eq type1 *empty-type*) (eq type2 *wild-type*)) t))
+
+(define-type-method (named :complex-subtypep-arg1) (type1 type2)
+  (cond ((eq type1 *empty-type*)
+	 t)
+	(;; When TYPE2 might be the universal type in disguise
+	 (type-might-contain-other-types-p type2)
+	 ;; Now that the UNION and HAIRY COMPLEX-SUBTYPEP-ARG2 methods
+	 ;; can delegate to us (more or less as CALL-NEXT-METHOD) when
+	 ;; they're uncertain, we can't just barf on COMPOUND-TYPE and
+	 ;; HAIRY-TYPEs as we used to. Instead we deal with the
+	 ;; problem (where at least part of the problem is cases like
+	 ;;   (SUBTYPEP T '(SATISFIES FOO))
+	 ;; or
+	 ;;   (SUBTYPEP T '(AND (SATISFIES FOO) (SATISFIES BAR)))
+	 ;; where the second type is a hairy type like SATISFIES, or
+	 ;; is a compound type which might contain a hairy type) by
+	 ;; returning uncertainty.
+	 (values nil nil))
+	(t
+	 ;; By elimination, TYPE1 is the universal type.
+	 (assert (or (eq type1 *wild-type*) (eq type1 *universal-type*)))
+	 ;; This case would have been picked off by the SIMPLE-SUBTYPEP
+	 ;; method, and so shouldn't appear here.
+	 (assert (not (eq type2 *universal-type*)))
+	 ;; Since TYPE2 is not EQ *UNIVERSAL-TYPE* and is not the
+	 ;; universal type in disguise, TYPE2 is not a superset of TYPE1.
+	 (values nil t))))
+
+
+(define-type-method (named :complex-subtypep-arg2) (type1 type2)
+  (assert (not (eq type2 *wild-type*))) ; * isn't really a type.
+  (cond ((eq type2 *universal-type*)
+	 (values t t))
+	((type-might-contain-other-types-p type1)
+	 ;; those types can be *EMPTY-TYPE* or *UNIVERSAL-TYPE* in
+	 ;; disguise.  So we'd better delegate.
+	 (invoke-complex-subtypep-arg1-method type1 type2))
+	(t
+	 ;; FIXME: This seems to rely on there only being 2 or 3
+	 ;; NAMED-TYPE values, and the exclusion of various
+	 ;; possibilities above. It would be good to explain it and/or
+	 ;; rewrite it so that it's clearer.
+	 (values (not (eq type2 *empty-type*)) t))))
+
+
+(define-type-method (named :complex-intersection) (type1 type2)
+  (hierarchical-intersection2 type1 type2))
+
+(define-type-method (named :unparse) (x)
+  (named-ctype-name x))
+
+
+
+;;;; Hairy and unknown types:
+
+;;; The Hairy-Type represents anything too wierd to be described
+;;; reasonably or to be useful, such as SATISFIES.  We just remember
+;;; the original type spec.
+;;;
+
+(defun make-hairy-ctype (&key specifier (enumerable t))
+  (%istruct 'hairy-ctype
+            (type-class-or-lose 'hairy)
+            enumerable
+            specifier))
+
+(defun hairy-ctype-p (x)
+  (or (istruct-typep x 'hairy-ctype)
+      (istruct-typep x 'unknown-ctype)))
+
+(setf (type-predicate 'hairy-ctype) 'hairy-ctype-p)
+
+(define-type-method (hairy :unparse) (x) (hairy-ctype-specifier x))
+
+(define-type-method (hairy :simple-subtypep) (type1 type2)
+  (let ((hairy-spec1 (hairy-ctype-specifier type1))
+	(hairy-spec2 (hairy-ctype-specifier type2)))
+    (cond ((equal-but-no-car-recursion hairy-spec1 hairy-spec2)
+	   (values t t))
+	  (t
+	   (values nil nil)))))
+
+(define-type-method (hairy :complex-subtypep-arg2) (type1 type2)
+  (invoke-complex-subtypep-arg1-method type1 type2))
+
+(define-type-method (hairy :complex-subtypep-arg1) (type1 type2)
+  (declare (ignore type1 type2))
+  (values nil nil))
+
+(define-type-method (hairy :complex-=) (type1 type2)
+  (if (and (unknown-ctype-p type2)
+	   (let* ((specifier2 (unknown-ctype-specifier type2))
+                  (name2 (if (consp specifier2)
+			   (car specifier2)
+			   specifier2)))
+             (info-type-kind name2)))
+      (let ((type2 (specifier-type (unknown-ctype-specifier type2))))
+        (if (unknown-ctype-p type2)
+            (values nil nil)
+            (type= type1 type2)))
+  (values nil nil)))
+
+(define-type-method (hairy :simple-intersection :complex-intersection)
+		    (type1 type2)
+  (if (type= type1 type2)
+    type1
+    nil))
+
+
+(define-type-method (hairy :simple-union) 
+    (type1 type2)
+  (if (type= type1 type2)
+      type1
+      nil))
+
+(define-type-method (hairy :simple-=) (type1 type2)
+  (if (equal-but-no-car-recursion (hairy-ctype-specifier type1)
+				  (hairy-ctype-specifier type2))
+      (values t t)
+      (values nil nil)))
+
+
+
+(def-type-translator satisfies (&whole x fun)
+  (unless (symbolp fun)
+    (report-bad-arg fun 'symbol))
+  (make-hairy-ctype :specifier x))
+
+
+
+;;; Negation Ctypes
+(defun make-negation-ctype (&key type (enumerable t))
+  (%istruct 'negation-ctype
+	    (type-class-or-lose 'negation)
+	    enumerable
+	    type))
+
+(defun negation-ctype-p (x)
+  (istruct-typep x 'negation-ctype))
+
+(setf (type-predicate 'negation-ctype) 'negation-ctype-p)
+
+(define-type-method (negation :unparse) (x)
+  `(not ,(type-specifier (negation-ctype-type x))))
+
+(define-type-method (negation :simple-subtypep) (type1 type2)
+  (csubtypep (negation-ctype-type type2) (negation-ctype-type type1)))
+
+(define-type-method (negation :complex-subtypep-arg2) (type1 type2)
+  (let* ((complement-type2 (negation-ctype-type type2))
+	 (intersection2 (type-intersection type1 complement-type2)))
+    (if intersection2
+	;; FIXME: if uncertain, maybe try arg1?
+	(type= intersection2 *empty-type*)
+	(invoke-complex-subtypep-arg1-method type1 type2))))
+
+(define-type-method (negation :complex-subtypep-arg1) (type1 type2)
+  (block nil
+    ;; (Several logical truths in this block are true as long as
+    ;; b/=T. As of sbcl-0.7.1.28, it seems impossible to construct a
+    ;; case with b=T where we actually reach this type method, but
+    ;; we'll test for and exclude this case anyway, since future
+    ;; maintenance might make it possible for it to end up in this
+    ;; code.)
+    (multiple-value-bind (equal certain)
+	(type= type2 *universal-type*)
+      (unless certain
+	(return (values nil nil)))
+      (when equal
+	(return (values t t))))
+    (let ((complement-type1 (negation-ctype-type type1)))
+      ;; Do the special cases first, in order to give us a chance if
+      ;; subtype/supertype relationships are hairy.
+      (multiple-value-bind (equal certain) 
+	  (type= complement-type1 type2)
+	;; If a = b, ~a is not a subtype of b (unless b=T, which was
+	;; excluded above).
+	(unless certain
+	  (return (values nil nil)))
+	(when equal
+	  (return (values nil t))))
+      ;; KLUDGE: ANSI requires that the SUBTYPEP result between any
+      ;; two built-in atomic type specifiers never be uncertain. This
+      ;; is hard to do cleanly for the built-in types whose
+      ;; definitions include (NOT FOO), i.e. CONS and RATIO. However,
+      ;; we can do it with this hack, which uses our global knowledge
+      ;; that our implementation of the type system uses disjoint
+      ;; implementation types to represent disjoint sets (except when
+      ;; types are contained in other types).  (This is a KLUDGE
+      ;; because it's fragile. Various changes in internal
+      ;; representation in the type system could make it start
+      ;; confidently returning incorrect results.) -- WHN 2002-03-08
+      (unless (or (type-might-contain-other-types-p complement-type1)
+		  (type-might-contain-other-types-p type2))
+	;; Because of the way our types which don't contain other
+	;; types are disjoint subsets of the space of possible values,
+	;; (SUBTYPEP '(NOT AA) 'B)=NIL when AA and B are simple (and B
+	;; is not T, as checked above).
+	(return (values nil t)))
+      ;; The old (TYPE= TYPE1 TYPE2) branch would never be taken, as
+      ;; TYPE1 and TYPE2 will only be equal if they're both NOT types,
+      ;; and then the :SIMPLE-SUBTYPEP method would be used instead.
+      ;; But a CSUBTYPEP relationship might still hold:
+      (multiple-value-bind (equal certain)
+	  (csubtypep complement-type1 type2)
+	;; If a is a subtype of b, ~a is not a subtype of b (unless
+	;; b=T, which was excluded above).
+	(unless certain
+	  (return (values nil nil)))
+	(when equal
+	  (return (values nil t))))
+      (multiple-value-bind (equal certain)
+	  (csubtypep type2 complement-type1)
+	;; If b is a subtype of a, ~a is not a subtype of b.  (FIXME:
+	;; That's not true if a=T. Do we know at this point that a is
+	;; not T?)
+	(unless certain
+	  (return (values nil nil)))
+	(when equal
+	  (return (values nil t))))
+      ;; old CSR comment ca. 0.7.2, now obsoleted by the SIMPLE-CTYPE?
+      ;; KLUDGE case above: Other cases here would rely on being able
+      ;; to catch all possible cases, which the fragility of this type
+      ;; system doesn't inspire me; for instance, if a is type= to ~b,
+      ;; then we want T, T; if this is not the case and the types are
+      ;; disjoint (have an intersection of *empty-type*) then we want
+      ;; NIL, T; else if the union of a and b is the *universal-type*
+      ;; then we want T, T. So currently we still claim to be unsure
+      ;; about e.g. (subtypep '(not fixnum) 'single-float).
+      ;;
+      ;; OTOH we might still get here:
+      (values nil nil))))
+
+(define-type-method (negation :complex-=) (type1 type2)
+  ;; (NOT FOO) isn't equivalent to anything that's not a negation
+  ;; type, except possibly a type that might contain it in disguise.
+  (declare (ignore type2))
+  (if (type-might-contain-other-types-p type1)
+      (values nil nil)
+      (values nil t)))
+
+(define-type-method (negation :simple-intersection) (type1 type2)
+  (let ((not1 (negation-ctype-type type1))
+	(not2 (negation-ctype-type type2)))
+    (cond
+      ((csubtypep not1 not2) type2)
+      ((csubtypep not2 not1) type1)
+      ;; Why no analagous clause to the disjoint in the SIMPLE-UNION2
+      ;; method, below?  The clause would read
+      ;;
+      ;; ((EQ (TYPE-UNION NOT1 NOT2) *UNIVERSAL-TYPE*) *EMPTY-TYPE*)
+      ;;
+      ;; but with proper canonicalization of negation types, there's
+      ;; no way of constructing two negation types with union of their
+      ;; negations being the universal type.
+      (t
+       nil))))
+
+(define-type-method (negation :complex-intersection) (type1 type2)
+  (cond
+    ((csubtypep type1 (negation-ctype-type type2)) *empty-type*)
+    ((eq (type-intersection type1 (negation-ctype-type type2)) *empty-type*)
+     type1)
+    (t nil)))
+
+(define-type-method (negation :simple-union) (type1 type2)
+  (let ((not1 (negation-ctype-type type1))
+	(not2 (negation-ctype-type type2)))
+    (cond
+      ((csubtypep not1 not2) type1)
+      ((csubtypep not2 not1) type2)
+      ((eq (type-intersection not1 not2) *empty-type*)
+       *universal-type*)
+      (t nil))))
+
+(define-type-method (negation :complex-union) (type1 type2)
+  (cond
+    ((csubtypep (negation-ctype-type type2) type1) *universal-type*)
+    ((eq (type-intersection type1 (negation-ctype-type type2)) *empty-type*)
+     type2)
+    (t nil)))
+
+(define-type-method (negation :simple-=) (type1 type2)
+  (type= (negation-ctype-type type1) (negation-ctype-type type2)))
+
+(def-type-translator not (typespec &environment env)
+  (let* ((not-type (specifier-type typespec env))
+	 (spec (type-specifier not-type)))
+    (cond
+      ;; canonicalize (NOT (NOT FOO))
+      ((and (listp spec) (eq (car spec) 'not))
+       (specifier-type (cadr spec) env))
+      ;; canonicalize (NOT NIL) and (NOT T)
+      ((eq not-type *empty-type*) *universal-type*)
+      ((eq not-type *universal-type*) *empty-type*)
+      ((and (numeric-ctype-p not-type)
+	    (null (numeric-ctype-low not-type))
+	    (null (numeric-ctype-high not-type)))
+       (make-negation-ctype :type not-type))
+      ((numeric-ctype-p not-type)
+       (type-union
+	(make-negation-ctype
+	 :type (modified-numeric-type not-type :low nil :high nil))
+	(cond
+	  ((null (numeric-ctype-low not-type))
+	   (modified-numeric-type
+	    not-type
+	    :low (let ((h (numeric-ctype-high not-type)))
+		   (if (consp h) (car h) (list h)))
+	    :high nil))
+	  ((null (numeric-ctype-high not-type))
+	   (modified-numeric-type
+	    not-type
+	    :low nil
+	    :high (let ((l (numeric-ctype-low not-type)))
+		    (if (consp l) (car l) (list l)))))
+	  (t (type-union
+	      (modified-numeric-type
+	       not-type
+	       :low nil
+	       :high (let ((l (numeric-ctype-low not-type)))
+		       (if (consp l) (car l) (list l))))
+	      (modified-numeric-type
+	       not-type
+	       :low (let ((h (numeric-ctype-high not-type)))
+		      (if (consp h) (car h) (list h)))
+	       :high nil))))))
+      ((intersection-ctype-p not-type)
+       (apply #'type-union
+	      (mapcar #'(lambda (x)
+			  (specifier-type `(not ,(type-specifier x)) env))
+		      (intersection-ctype-types not-type))))
+      ((union-ctype-p not-type)
+       (apply #'type-intersection
+	      (mapcar #'(lambda (x)
+			  (specifier-type `(not ,(type-specifier x)) env))
+		      (union-ctype-types not-type))))
+      ((member-ctype-p not-type)
+       (let ((members (member-ctype-members not-type)))
+	 (if (some #'floatp members)
+	   (let (floats)
+	     (dolist (pair '((0.0f0 . -0.0f0) (0.0d0 . -0.0d0)))
+	       (when (member (car pair) members)
+		 (assert (not (member (cdr pair) members)))
+		 (push (cdr pair) floats)
+		 (setf members (remove (car pair) members)))
+	       (when (member (cdr pair) members)
+		 (assert (not (member (car pair) members)))
+		 (push (car pair) floats)
+		 (setf members (remove (cdr pair) members))))
+	     (apply #'type-intersection
+		    (if (null members)
+		      *universal-type*
+		      (make-negation-ctype
+		       :type (make-member-ctype :members members)))
+		    (mapcar
+		     (lambda (x)
+		       (let ((type (ctype-of x)))
+			 (type-union
+			  (make-negation-ctype
+			   :type (modified-numeric-type type
+							  :low nil :high nil))
+			    (modified-numeric-type type
+						   :low nil :high (list x))
+			    (make-member-ctype :members (list x))
+			    (modified-numeric-type type
+						   :low (list x) :high nil))))
+		     floats)))
+	     (make-negation-ctype :type not-type))))
+      ((and (cons-ctype-p not-type)
+	    (eq (cons-ctype-car-ctype not-type) *universal-type*)
+	    (eq (cons-ctype-cdr-ctype not-type) *universal-type*))
+       (make-negation-ctype :type not-type))
+      ((cons-ctype-p not-type)
+       (type-union
+	(make-negation-ctype :type (specifier-type 'cons env))
+	(cond
+	  ((and (not (eq (cons-ctype-car-ctype not-type) *universal-type*))
+		(not (eq (cons-ctype-cdr-ctype not-type) *universal-type*)))
+	   (type-union
+	    (make-cons-ctype
+	     (specifier-type `(not ,(type-specifier
+				     (cons-ctype-car-ctype not-type))) env)
+	     *universal-type*)
+	    (make-cons-ctype
+	     *universal-type*
+	     (specifier-type `(not ,(type-specifier
+				     (cons-ctype-cdr-ctype not-type))) env))))
+	  ((not (eq (cons-ctype-car-ctype not-type) *universal-type*))
+	   (make-cons-ctype
+	    (specifier-type `(not ,(type-specifier
+				    (cons-ctype-car-ctype not-type))) env)
+	    *universal-type*))
+	  ((not (eq (cons-ctype-cdr-ctype not-type) *universal-type*))
+	   (make-cons-ctype
+	    *universal-type*
+	    (specifier-type `(not ,(type-specifier
+				    (cons-ctype-cdr-ctype not-type))) env)))
+	  (t (error "Weird CONS type ~S" not-type)))))
+      (t (make-negation-ctype :type not-type)))))
+
+
+;;;; Numeric types.
+
+;;; A list of all the float formats, in order of decreasing precision.
+;;;
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defconstant float-formats
+    '(long-float double-float single-float short-float)))
+
+;;; The type of a float format.
+;;;
+(deftype float-format () `(member ,@float-formats))
+
+(defun type-bound-number (x)
+  (if (consp x)
+      (destructuring-bind (result) x result)
+      x))
+
+(defun make-numeric-ctype (&key class 
+                                format
+                                (complexp :real)
+                                low
+                                high
+                                enumerable
+                                predicate)
+  ;; if interval is empty
+  (if (and low
+	   high
+	   (if (or (consp low) (consp high)) ; if either bound is exclusive
+	     (>= (type-bound-number low) (type-bound-number high))
+	     (> low high)))
+    *empty-type*
+    (multiple-value-bind (canonical-low canonical-high)
+	(case class
+	  (integer
+	   ;; INTEGER types always have their LOW and HIGH bounds
+	   ;; represented as inclusive, not exclusive values.
+	   (values (if (consp low)
+		     (1+ (type-bound-number low))
+		     low)
+		   (if (consp high)
+		     (1- (type-bound-number high))
+		     high)))
+	  (t 
+	   ;; no canonicalization necessary
+	   (values low high)))
+      (when (and (eq class 'rational)
+		 (integerp canonical-low)
+		 (integerp canonical-high)
+		 (= canonical-low canonical-high))
+	(setf class 'integer))
+      (%istruct 'numeric-ctype
+		(type-class-or-lose 'number)
+		enumerable
+		class
+		format
+		complexp
+		canonical-low
+		canonical-high
+		predicate))))
+    
+
+(defun make-numeric-ctype-predicate (ctype)
+  (let ((class (numeric-ctype-class ctype))
+        (lo (numeric-ctype-low ctype))
+        (hi (numeric-ctype-high ctype)))
+    (if (eq class 'integer)
+      (if (and hi
+               lo
+               (<= hi target::target-most-positive-fixnum)
+               (>= lo target::target-most-negative-fixnum))      
+        #'(lambda (n)
+            (and (fixnump n)
+                 (locally (declare (fixnum n hi lo))
+                   (and (%i>= n lo)
+                        (%i<= n hi)))))))))
+
+(defun numeric-ctype-p (x)
+  (istruct-typep x 'numeric-ctype))
+
+(setf (type-predicate 'numeric-ctype) 'numeric-ctype-p)
+
+(define-type-method (number :simple-=) (type1 type2)
+  (values
+   (and (eq (numeric-ctype-class type1) (numeric-ctype-class type2))
+	(eq (numeric-ctype-format type1) (numeric-ctype-format type2))
+	(eq (numeric-ctype-complexp type1) (numeric-ctype-complexp type2))
+	(equalp (numeric-ctype-low type1) (numeric-ctype-low type2))
+	(equalp (numeric-ctype-high type1) (numeric-ctype-high type2)))
+   t))
+
+(define-type-method (number :unparse) (type)
+  (let* ((complexp (numeric-ctype-complexp type))
+	 (low (numeric-ctype-low type))
+	 (high (numeric-ctype-high type))
+	 (base (case (numeric-ctype-class type)
+		 (integer 'integer)
+		 (rational 'rational)
+		 (float (or (numeric-ctype-format type) 'float))
+		 (t 'real))))
+    (let ((base+bounds
+	   (cond ((and (eq base 'integer) high low)
+		  (let ((high-count (logcount high))
+			(high-length (integer-length high)))
+		    (cond ((= low 0)
+			   (cond ((= high 0) '(integer 0 0))
+				 ((= high 1) 'bit)
+				 ((and (= high-count high-length)
+				       (plusp high-length))
+				  `(unsigned-byte ,high-length))
+				 (t
+				  `(mod ,(1+ high)))))
+			  ((and (= low target::target-most-negative-fixnum)
+				(= high target::target-most-positive-fixnum))
+			   'fixnum)
+			  ((and (= low (lognot high))
+				(= high-count high-length)
+				(> high-count 0))
+			   `(signed-byte ,(1+ high-length)))
+			  (t
+			   `(integer ,low ,high)))))
+		 (high `(,base ,(or low '*) ,high))
+		 (low
+		  (if (and (eq base 'integer) (= low 0))
+		      'unsigned-byte
+		      `(,base ,low)))
+		 (t base))))
+      (ecase complexp
+	(:real
+	 base+bounds)
+	(:complex
+	 (if (eq base+bounds 'real)
+	     'complex
+	     `(complex ,base+bounds)))
+	((nil)
+	 (assert (eq base+bounds 'real))
+	 'number)))))
+
+;;; Numeric-Bound-Test  --  Internal
+;;;
+;;;    Return true if X is "less than or equal" to Y, taking open bounds into
+;;; consideration.  Closed is the predicate used to test the bound on a closed
+;;; interval (e.g. <=), and Open is the predicate used on open bounds (e.g. <).
+;;; Y is considered to be the outside bound, in the sense that if it is
+;;; infinite (NIL), then the test suceeds, whereas if X is infinite, then the
+;;; test fails (unless Y is also infinite).
+;;;
+;;;    This is for comparing bounds of the same kind, e.g. upper and upper.
+;;; Use Numeric-Bound-Test* for different kinds of bounds.
+;;;
+(defmacro numeric-bound-test (x y closed open)
+  `(cond ((not ,y) t)
+	   ((not ,x) nil)
+	   ((consp ,x)
+	    (if (consp ,y)
+	      (,closed (car ,x) (car ,y))
+	      (,closed (car ,x) ,y)))
+	   (t
+	    (if (consp ,y)
+	      (,open ,x (car ,y))
+	      (,closed ,x ,y)))))
+
+;;; Numeric-Bound-Test*  --  Internal
+;;;
+;;;    Used to compare upper and lower bounds.  This is different from the
+;;; same-bound case:
+;;; -- Since X = NIL is -infinity, whereas y = NIL is +infinity, we return true
+;;;    if *either* arg is NIL.
+;;; -- an open inner bound is "greater" and also squeezes the interval, causing
+;;;    us to use the Open test for those cases as well.
+;;;
+(defmacro numeric-bound-test* (x y closed open)
+  `(cond ((not ,y) t)
+         ((not ,x) t)
+         ((consp ,x)
+          (if (consp ,y)
+	      (,open (car ,x) (car ,y))
+	      (,open (car ,x) ,y)))
+         (t
+          (if (consp ,y)
+	      (,open ,x (car ,y))
+	      (,closed ,x ,y)))))
+
+;;; Numeric-Bound-Max  --  Internal
+;;;
+;;;    Return whichever of the numeric bounds X and Y is "maximal" according to
+;;; the predicates Closed (e.g. >=) and Open (e.g. >).  This is only meaningful
+;;; for maximizing like bounds, i.e. upper and upper.  If Max-P is true, then
+;;; we return NIL if X or Y is NIL, otherwise we return the other arg.
+;;;
+(defmacro numeric-bound-max (x y closed open max-p)
+  (once-only ((n-x x)
+	      (n-y y))
+    `(cond
+      ((not ,n-x) ,(if max-p nil n-y))
+      ((not ,n-y) ,(if max-p nil n-x))
+      ((consp ,n-x)
+       (if (consp ,n-y)
+	 (if (,closed (car ,n-x) (car ,n-y)) ,n-x ,n-y)
+	 (if (,open (car ,n-x) ,n-y) ,n-x ,n-y)))
+      (t
+       (if (consp ,n-y)
+	 (if (,open (car ,n-y) ,n-x) ,n-y ,n-x)
+	 (if (,closed ,n-y ,n-x) ,n-y ,n-x))))))
+
+
+(define-type-method (number :simple-subtypep) (type1 type2)
+  (let ((class1 (numeric-ctype-class type1))
+	  (class2 (numeric-ctype-class type2))
+	  (complexp2 (numeric-ctype-complexp type2))
+	  (format2 (numeric-ctype-format type2))
+	  (low1 (numeric-ctype-low type1))
+	  (high1 (numeric-ctype-high type1))
+	  (low2 (numeric-ctype-low type2))
+	  (high2 (numeric-ctype-high type2)))
+    ;;
+    ;; If one is complex and the other isn't, they are disjoint.
+    (cond ((not (or (eq (numeric-ctype-complexp type1) complexp2)
+		        (null complexp2)))
+	     (values nil t))
+	    ;;
+	    ;; If the classes are specified and different, the types are
+	    ;; disjoint unless type2 is rational and type1 is integer.
+	    ((not (or (eq class1 class2) (null class2)
+		        (and (eq class1 'integer) (eq class2 'rational))))
+	     (values nil t))
+	    ;;
+	    ;; If the float formats are specified and different, the types
+	    ;; are disjoint.
+	    ((not (or (eq (numeric-ctype-format type1) format2)
+		        (null format2)))
+	     (values nil t))
+	    ;;
+	    ;; Check the bounds.
+	    ((and (numeric-bound-test low1 low2 >= >)
+		    (numeric-bound-test high1 high2 <= <))
+	     (values t t))
+	    (t
+	     (values nil t)))))
+
+;(define-superclasses number (generic-number))
+
+;;; NUMERIC-TYPES-ADJACENT  --  Internal
+;;;
+;;;    If the high bound of Low is adjacent to the low bound of High, then
+;;; return T, otherwise NIL.
+;;;
+(defun numeric-types-adjacent (low high)
+  (let ((low-bound (numeric-ctype-high low))
+	(high-bound (numeric-ctype-low high)))
+    (cond ((not (and low-bound high-bound)) nil)
+	    ((consp low-bound)
+	     (eql (car low-bound) high-bound))
+	    ((consp high-bound)
+	     (eql (car high-bound) low-bound))
+	    ((and (eq (numeric-ctype-class low) 'integer)
+		    (eq (numeric-ctype-class high) 'integer))
+	     (eql (1+ low-bound) high-bound))
+	    (t
+	     nil))))
+
+;;;
+;;; Return a numeric type that is a supertype for both type1 and type2.
+;;; 
+(define-type-method (number :simple-union) (type1 type2)
+  (declare (type numeric-ctype type1 type2))
+  (cond ((csubtypep type1 type2) type2)
+	((csubtypep type2 type1) type1)
+	(t
+	 (let ((class1 (numeric-ctype-class type1))
+	       (format1 (numeric-ctype-format type1))
+	       (complexp1 (numeric-ctype-complexp type1))
+	       (class2 (numeric-ctype-class type2))
+	       (format2 (numeric-ctype-format type2))
+	       (complexp2 (numeric-ctype-complexp type2)))
+	   (cond
+             ((and (eq class1 class2)
+                   (eq format1 format2)
+                   (eq complexp1 complexp2)
+                   (or (numeric-types-intersect type1 type2)
+                       (numeric-types-adjacent type1 type2)
+                       (numeric-types-adjacent type2 type1)))
+              (make-numeric-ctype
+               :class class1
+               :format format1
+               :complexp complexp1
+               :low (numeric-bound-max (numeric-ctype-low type1)
+                                       (numeric-ctype-low type2)
+                                       <= < t)
+               :high (numeric-bound-max (numeric-ctype-high type1)
+                                        (numeric-ctype-high type2)
+                                        >= > t)))
+             ;; FIXME: These two clauses are almost identical, and the
+             ;; consequents are in fact identical in every respect.
+             ((and (eq class1 'rational)
+                   (eq class2 'integer)
+                   (eq format1 format2)
+                   (eq complexp1 complexp2)
+                   (integerp (numeric-ctype-low type2))
+                   (integerp (numeric-ctype-high type2))
+                   (= (numeric-ctype-low type2) (numeric-ctype-high type2))
+                   (or (numeric-types-adjacent type1 type2)
+                       (numeric-types-adjacent type2 type1)))
+              (make-numeric-ctype
+               :class 'rational
+               :format format1
+               :complexp complexp1
+               :low (numeric-bound-max (numeric-ctype-low type1)
+                                       (numeric-ctype-low type2)
+                                       <= < t)
+               :high (numeric-bound-max (numeric-ctype-high type1)
+                                        (numeric-ctype-high type2)
+                                        >= > t)))
+             ((and (eq class1 'integer)
+                   (eq class2 'rational)
+                   (eq format1 format2)
+                   (eq complexp1 complexp2)
+                   (integerp (numeric-ctype-low type1))
+                   (integerp (numeric-ctype-high type1))
+                   (= (numeric-ctype-low type1) (numeric-ctype-high type1))
+                   (or (numeric-types-adjacent type1 type2)
+                       (numeric-types-adjacent type2 type1)))
+              (make-numeric-ctype
+               :class 'rational
+               :format format1
+               :complexp complexp1
+               :low (numeric-bound-max (numeric-ctype-low type1)
+                                       (numeric-ctype-low type2)
+                                       <= < t)
+               :high (numeric-bound-max (numeric-ctype-high type1)
+                                        (numeric-ctype-high type2)
+                                        >= > t)))
+             (t nil))))))
+
+(setf (info-type-kind 'number) :primitive
+      (info-type-builtin 'number) (make-numeric-ctype :complexp nil))
+
+(def-type-translator complex (&optional spec &environment env)
+  (if (eq spec '*)
+      (make-numeric-ctype :complexp :complex)
+      (labels ((not-numeric ()
+                 (error "Component type for Complex is not numeric: ~S." spec))
+               (not-real ()
+                 (error "Component type for Complex is not a subtype of real: ~S." spec))
+               (complex1 (component-type)
+                 (unless (numeric-ctype-p component-type)
+                   (not-numeric))
+                 (when (eq (numeric-ctype-complexp component-type) :complex)
+                   (not-real))
+                 (let ((res (copy-uvector component-type)))
+                   (setf (numeric-ctype-complexp res) :complex)
+                   (setf (numeric-ctype-predicate res) nil) ; <<
+                   res))
+               (do-complex (ctype)
+                 (cond
+                   ((eq ctype *empty-type*) *empty-type*)
+                   ((eq ctype *universal-type*) (not-real))
+                   ((numeric-ctype-p ctype) (complex1 ctype))
+                   ((union-ctype-p ctype)
+                    (apply #'type-union
+                           (mapcar #'do-complex (union-ctype-types ctype))))
+                   ((member-ctype-p ctype)
+                    (apply #'type-union
+                           (mapcar (lambda (x) (do-complex (ctype-of x)))
+                                   (member-ctype-members ctype))))
+                   ((and (intersection-ctype-p ctype)
+                         ;; just enough to handle simple types like RATIO.
+                         (let ((numbers (remove-if-not
+                                         #'numeric-ctype-p
+                                         (intersection-ctype-types ctype))))
+                           (and (car numbers)
+                                (null (cdr numbers))
+                                (eq (numeric-ctype-complexp (car numbers)) :real)
+                                (complex1 (car numbers))))))
+                   (t                   ; punt on harder stuff for now
+                    (not-real)))))
+        (let ((ctype (specifier-type spec env)))
+          (do-complex ctype)))))
+
+;;; Check-Bound  --  Internal
+;;;
+;;;    Check that X is a well-formed numeric bound of the specified Type.
+;;; If X is *, return NIL, otherwise return the bound.
+;;;
+(defmacro check-bound (x type)
+  `(cond ((eq ,x '*) nil)
+	   ((or (typep ,x ',type)
+	        (and (consp ,x) (typep (car ,x) ',type) (null (cdr ,x))))
+	    ,x)
+	   (t
+	    (error "Bound is not *, a ~A or a list of a ~A: ~S" ',type ',type ,x))))
+
+(def-type-translator integer (&optional low high)
+  (let* ((l (check-bound low integer))
+         (lb (if (consp l) (1+ (car l)) l))
+         (h (check-bound high integer))
+         (hb (if (consp h) (1- (car h)) h)))
+    (if (and hb lb (< hb lb))
+      *empty-type*
+      (make-numeric-ctype :class 'integer  :complexp :real
+                          :enumerable (not (null (and l h)))
+                          :low lb
+                          :high hb))))
+
+(deftype mod (n)
+  (unless (and (integerp n) (> n 0))
+    (error "Bad N specified for MOD type specifier: ~S." n))
+  `(integer 0 ,(1- n)))
+
+
+(defmacro def-bounded-type (type class format)
+  `(def-type-translator ,type (&optional low high)
+     (let ((lb (check-bound low ,type))
+	     (hb (check-bound high ,type)))
+       (unless (numeric-bound-test* lb hb <= <)
+	   (error "Lower bound ~S is not less than upper bound ~S." low high))
+       (make-numeric-ctype :class ',class :format ',format :low lb :high hb))))
+
+(def-bounded-type rational rational nil)
+
+(defun coerce-bound (bound type inner-coerce-bound-fun)
+  (declare (type function inner-coerce-bound-fun))
+  (cond ((eql bound '*)
+	 bound)
+	((consp bound)
+	 (destructuring-bind (inner-bound) bound
+	   (list (funcall inner-coerce-bound-fun inner-bound type))))
+	(t
+	 (funcall inner-coerce-bound-fun bound type))))
+
+(defun inner-coerce-real-bound (bound type)
+  (ecase type
+    (rational (rationalize bound))
+    (float (if (floatp bound)
+	       bound
+	       ;; Coerce to the widest float format available, to
+	       ;; avoid unnecessary loss of precision:
+	       (coerce bound 'long-float)))))
+
+(defun coerced-real-bound (bound type)
+  (coerce-bound bound type #'inner-coerce-real-bound))
+
+(defun coerced-float-bound (bound type)
+  (coerce-bound bound type #'coerce))
+
+#|
+(def-type-translator real (&optional (low '*) (high '*))
+  (specifier-type `(or (float ,(coerced-real-bound  low 'float)
+			      ,(coerced-real-bound high 'float))
+		       (rational ,(coerced-real-bound  low 'rational)
+				 ,(coerced-real-bound high 'rational)))))
+
+(def-type-translator float (&optional (low '*) (high '*))
+  (specifier-type 
+   `(or (single-float ,(coerced-float-bound  low 'single-float)
+		      ,(coerced-float-bound high 'single-float))
+	(double-float ,(coerced-float-bound  low 'double-float)
+		      ,(coerced-float-bound high 'double-float)))))
+|#
+
+(def-bounded-type float float nil)
+(def-bounded-type real nil nil)
+
+(defmacro define-float-format (f)
+  `(def-bounded-type ,f float ,f))
+
+(define-float-format short-float)
+(define-float-format single-float)
+(define-float-format double-float)
+(define-float-format long-float)
+
+(defun numeric-types-intersect (type1 type2)
+  (declare (type numeric-ctype type1 type2))
+  (let* ((class1 (numeric-ctype-class type1))
+	 (class2 (numeric-ctype-class type2))
+	 (complexp1 (numeric-ctype-complexp type1))
+	 (complexp2 (numeric-ctype-complexp type2))
+	 (format1 (numeric-ctype-format type1))
+	 (format2 (numeric-ctype-format type2))
+	 (low1 (numeric-ctype-low type1))
+	 (high1 (numeric-ctype-high type1))
+	 (low2 (numeric-ctype-low type2))
+	 (high2 (numeric-ctype-high type2)))
+    ;;
+    ;; If one is complex and the other isn't, then they are disjoint.
+    (cond ((not (or (eq complexp1 complexp2)
+		    (null complexp1) (null complexp2)))
+	   nil)
+	  ;;
+	  ;; If either type is a float, then the other must either be specified
+	  ;; to be a float or unspecified.  Otherwise, they are disjoint.
+	  ((and (eq class1 'float) (not (member class2 '(float nil)))) nil)
+	  ((and (eq class2 'float) (not (member class1 '(float nil)))) nil)
+	  ;;
+	  ;; If the float formats are specified and different, the types
+	  ;; are disjoint.
+	  ((not (or (eq format1 format2) (null format1) (null format2)))
+	   nil)
+	  (t
+	   ;;
+	   ;; Check the bounds.  This is a bit odd because we must always have
+	   ;; the outer bound of the interval as the second arg.
+	   (if (numeric-bound-test high1 high2 <= <)
+	     (or (and (numeric-bound-test low1 low2 >= >)
+		      (numeric-bound-test* low1 high2 <= <))
+		 (and (numeric-bound-test low2 low1 >= >)
+		      (numeric-bound-test* low2 high1 <= <)))
+	     (or (and (numeric-bound-test* low2 high1 <= <)
+		      (numeric-bound-test low2 low1 >= >))
+		 (and (numeric-bound-test high2 high1 <= <)
+		      (numeric-bound-test* high2 low1 >= >))))))))
+
+;;; Round-Numeric-Bound  --  Internal
+;;;
+;;;    Take the numeric bound X and convert it into something that can be used
+;;; as a bound in a numeric type with the specified Class and Format.  If up-p
+;;; is true, then we round up as needed, otherwise we round down.  Up-p true
+;;; implies that X is a lower bound, i.e. (N) > N.
+;;;
+;;; This is used by Numeric-Type-Intersection to mash the bound into the
+;;; appropriate type number.  X may only be a float when Class is Float.
+;;;
+;;; ### Note: it is possible for the coercion to a float to overflow or
+;;; underflow.  This happens when the bound doesn't fit in the specified
+;;; format.  In this case, we should really return the appropriate
+;;; {Most | Least}-{Positive | Negative}-XXX-Float float of desired format.
+;;; But these conditions aren't currently signalled in any useful way.
+;;;
+;;; Also, when converting an open rational bound into a float we should
+;;; probably convert it to a closed bound of the closest float in the specified
+;;; format.  In general, open float bounds are fucked.
+;;;
+(defun round-numeric-bound (x class format up-p)
+  (if x
+    (let ((cx (if (consp x) (car x) x)))
+	(ecase class
+	  ((nil rational) x)
+	  (integer
+	   (if (and (consp x) (integerp cx))
+	     (if up-p (1+ cx) (1- cx))
+	     (if up-p (ceiling cx) (floor cx))))
+	  (float
+	   (let ((res (if format (coerce cx format) (float cx))))
+	     (if (consp x) (list res) res)))))
+    nil))
+
+;;; Number :Simple-Intersection type method  --  Internal
+;;;
+;;;    Handle the case of Type-Intersection on two numeric types.  We use
+;;; Types-Intersect to throw out the case of types with no intersection.  If an
+;;; attribute in Type1 is unspecified, then we use Type2's attribute, which
+;;; must be at least as restrictive.  If the types intersect, then the only
+;;; attributes that can be specified and different are the class and the
+;;; bounds.
+;;;
+;;;    When the class differs, we use the more restrictive class.  The only
+;;; interesting case is rational/integer, since rational includes integer.
+;;;
+;;;    We make the result lower (upper) bound the maximum (minimum) of the
+;;; argument lower (upper) bounds.  We convert the bounds into the
+;;; appropriate numeric type before maximizing.  This avoids possible confusion
+;;; due to mixed-type comparisons (but I think the result is the same).
+;;;
+(define-type-method (number :simple-intersection) (type1 type2)
+  (declare (type numeric-ctype type1 type2))
+  (if (numeric-types-intersect type1 type2)
+    (let* ((class1 (numeric-ctype-class type1))
+	   (class2 (numeric-ctype-class type2))
+	   (class (ecase class1
+		    ((nil) class2)
+		    ((integer float) class1)
+		    (rational (if (eq class2 'integer) 'integer 'rational))))
+	   (format (or (numeric-ctype-format type1)
+		       (numeric-ctype-format type2))))
+      (make-numeric-ctype
+       :class class
+       :format format
+       :complexp (or (numeric-ctype-complexp type1)
+		     (numeric-ctype-complexp type2))
+       :low (numeric-bound-max
+	     (round-numeric-bound (numeric-ctype-low type1)
+				  class format t)
+	     (round-numeric-bound (numeric-ctype-low type2)
+				  class format t)
+	     > >= nil)
+       :high (numeric-bound-max
+	      (round-numeric-bound (numeric-ctype-high type1)
+				   class format nil)
+	      (round-numeric-bound (numeric-ctype-high type2)
+				   class format nil)
+	      < <= nil)))
+    *empty-type*))
+
+;;; Float-Format-Max  --  Interface
+;;;
+;;;    Given two float formats, return the one with more precision.  If either
+;;; one is null, return NIL.
+;;;
+(defun float-format-max (f1 f2)
+  (when (and f1 f2)
+    (dolist (f float-formats (error "Bad float format: ~S." f1))
+      (when (or (eq f f1) (eq f f2))
+	  (return f)))))
+
+
+;;; Numeric-Contagion  --  Interface
+;;;
+;;;    Return the result of an operation on Type1 and Type2 according to the
+;;; rules of numeric contagion.  This is always NUMBER, some float format
+;;; (possibly complex) or RATIONAL.  Due to rational canonicalization, there
+;;; isn't much we can do here with integers or rational complex numbers.
+;;;
+;;;    If either argument is not a Numeric-Type, then return NUMBER.  This is
+;;; useful mainly for allowing types that are technically numbers, but not a
+;;; Numeric-Type. 
+;;;
+(defun numeric-contagion (type1 type2)
+  (if (and (numeric-ctype-p type1) (numeric-ctype-p type2))
+    (let ((class1 (numeric-ctype-class type1))
+	    (class2 (numeric-ctype-class type2))
+	    (format1 (numeric-ctype-format type1))
+	    (format2 (numeric-ctype-format type2))
+	    (complexp1 (numeric-ctype-complexp type1))
+	    (complexp2 (numeric-ctype-complexp type2)))
+	(cond ((or (null complexp1)
+		   (null complexp2))
+	       (specifier-type 'number))
+	      ((eq class1 'float)
+	       (make-numeric-ctype
+		  :class 'float
+		  :format (ecase class2
+			      (float (float-format-max format1 format2))
+			      ((integer rational) format1)
+			      ((nil)
+			       ;; A double-float with any real number is a
+			       ;; double-float.
+			       (if (eq format1 'double-float)
+				 'double-float
+				 nil)))
+		  :complexp (if (or (eq complexp1 :complex)
+				    (eq complexp2 :complex))
+			      :complex
+			      :real)))
+	      ((eq class2 'float) (numeric-contagion type2 type1))
+	      ((and (eq complexp1 :real) (eq complexp2 :real))
+	       (make-numeric-ctype
+		  :class (and class1 class2 'rational)
+		  :complexp :real))
+	      (t
+	       (specifier-type 'number))))
+    (specifier-type 'number)))
+
+
+
+
+
+;;;; Array types:
+
+;;; The Array-Type is used to represent all array types, including things such
+;;; as SIMPLE-STRING.
+;;;
+
+(defun make-array-ctype (&key
+                         (dimensions '*)
+                         (complexp '*)
+                         element-type
+                         (specialized-element-type *wild-type*))
+  (%istruct 'array-ctype
+            (type-class-or-lose 'array)
+            nil
+            dimensions
+            complexp
+            element-type
+            specialized-element-type
+            (unless (eq specialized-element-type *wild-type*)
+              (ctype-subtype specialized-element-type))))
+
+(defun array-ctype-p (x) (istruct-typep x 'array-ctype))
+(setf (type-predicate 'array-ctype) 'array-ctype-p)
+
+;;; Specialized-Element-Type-Maybe  --  Internal
+;;;
+;;;      What this does depends on the setting of the
+;;; *use-implementation-types* switch.  If true, return the specialized element
+;;; type, otherwise return the original element type.
+;;;
+(defun specialized-element-type-maybe (type)
+  (declare (type array-ctype type))
+  (if *use-implementation-types*
+    (array-ctype-specialized-element-type type)
+    (array-ctype-element-type type)))
+
+(define-type-method (array :simple-=) (type1 type2)
+  (if (or (unknown-ctype-p (array-ctype-element-type type1))
+	  (unknown-ctype-p (array-ctype-element-type type2)))
+    (multiple-value-bind (equalp certainp)
+	(type= (array-ctype-element-type type1)
+	       (array-ctype-element-type type2))
+      (assert (not (and (not equalp) certainp)))
+      (values equalp certainp))
+    (values (and (equal (array-ctype-dimensions type1)
+			(array-ctype-dimensions type2))
+		 (eq (array-ctype-complexp type1)
+		     (array-ctype-complexp type2))
+		 (type= (specialized-element-type-maybe type1)
+			(specialized-element-type-maybe type2)))
+	    t)))
+
+(define-type-method (array :unparse) (type)
+  (let ((dims (array-ctype-dimensions type))
+	  (eltype (type-specifier (array-ctype-element-type type)))
+	  (complexp (array-ctype-complexp type)))
+    (cond ((eq dims '*)
+	     (if (eq eltype '*)
+	       (if complexp 'array 'simple-array)
+	       (if complexp `(array ,eltype) `(simple-array ,eltype))))
+	    ((= (length dims) 1) 
+	     (if complexp
+	       (if (eq (car dims) '*)
+		   (case eltype
+		     (bit 'bit-vector)
+		     ((character base-char) 'base-string)
+		     (* 'vector)
+		     (t `(vector ,eltype)))
+		   (case eltype
+		     (bit `(bit-vector ,(car dims)))
+		     ((character base-char) `(base-string ,(car dims)))
+		     (t `(vector ,eltype ,(car dims)))))
+	       (if (eq (car dims) '*)
+		   (case eltype
+		     (bit 'simple-bit-vector)
+		     ((base-char character) 'simple-base-string)
+		     ((t) 'simple-vector)
+		     (t `(simple-array ,eltype (*))))
+		   (case eltype
+		     (bit `(simple-bit-vector ,(car dims)))
+		     ((base-char character) `(simple-base-string ,(car dims)))
+		     ((t) `(simple-vector ,(car dims)))
+		     (t `(simple-array ,eltype ,dims))))))
+	    (t
+	     (if complexp
+	       `(array ,eltype ,dims)
+	       `(simple-array ,eltype ,dims))))))
+
+(define-type-method (array :simple-subtypep) (type1 type2)
+  (let ((dims1 (array-ctype-dimensions type1))
+	(dims2 (array-ctype-dimensions type2))
+	(complexp2 (array-ctype-complexp type2)))
+    (cond (;; not subtypep unless dimensions are compatible
+	   (not (or (eq dims2 '*)
+		    (and (not (eq dims1 '*))
+			 (= (length (the list dims1))
+			    (length (the list dims2)))
+			 (every (lambda (x y)
+				  (or (eq y '*) (eql x y)))
+				(the list dims1)
+				(the list dims2)))))
+	   (values nil t))
+	  ;; not subtypep unless complexness is compatible
+	  ((not (or (eq complexp2 :maybe)
+		    (eq (array-ctype-complexp type1) complexp2)))
+	   (values nil t))
+	  ;; Since we didn't fail any of the tests above, we win
+	  ;; if the TYPE2 element type is wild.
+	  ((eq (array-ctype-element-type type2) *wild-type*)
+	   (values t t))
+	  (;; Since we didn't match any of the special cases above, we
+	   ;; can't give a good answer unless both the element types
+	   ;; have been defined.
+	   (or (unknown-ctype-p (array-ctype-element-type type1))
+	       (unknown-ctype-p (array-ctype-element-type type2)))
+	   (values nil nil))
+	  (;; Otherwise, the subtype relationship holds iff the
+	   ;; types are equal, and they're equal iff the specialized
+	   ;; element types are identical.
+	   t
+	   (values (type= (specialized-element-type-maybe type1)
+			  (specialized-element-type-maybe type2))
+		   t)))))
+
+; (define-superclasses array (string string) (vector vector) (array))
+
+
+(defun array-types-intersect (type1 type2)
+  (declare (type array-ctype type1 type2))
+  (let ((dims1 (array-ctype-dimensions type1))
+	(dims2 (array-ctype-dimensions type2))
+	(complexp1 (array-ctype-complexp type1))
+	(complexp2 (array-ctype-complexp type2)))
+    ;; See whether dimensions are compatible.
+    (cond ((not (or (eq dims1 '*) (eq dims2 '*)
+		    (and (= (length dims1) (length dims2))
+			 (every (lambda (x y)
+				  (or (eq x '*) (eq y '*) (= x y)))
+				dims1 dims2))))
+	   (values nil t))
+	  ;; See whether complexpness is compatible.
+	  ((not (or (eq complexp1 :maybe)
+		    (eq complexp2 :maybe)
+		    (eq complexp1 complexp2)))
+	   (values nil t))
+	  ((or (eq (array-ctype-specialized-element-type type1) *wild-type*)
+	       (eq (array-ctype-specialized-element-type type2) *wild-type*)
+	       (type= (specialized-element-type-maybe type1)
+		      (specialized-element-type-maybe type2)))
+	   (values t t))
+	  (t
+	   (values nil t)))))
+
+(define-type-method (array :simple-intersection) (type1 type2)
+  (declare (type array-ctype type1 type2))
+  (if (array-types-intersect type1 type2)
+    (let ((dims1 (array-ctype-dimensions type1))
+          (dims2 (array-ctype-dimensions type2))
+          (complexp1 (array-ctype-complexp type1))
+          (complexp2 (array-ctype-complexp type2))
+          (eltype1 (array-ctype-element-type type1))
+          (eltype2 (array-ctype-element-type type2)))
+      (specialize-array-type
+       (make-array-ctype
+        :dimensions (cond ((eq dims1 '*) dims2)
+                          ((eq dims2 '*) dims1)
+                          (t
+                           (mapcar #'(lambda (x y) (if (eq x '*) y x))
+                                   dims1 dims2)))
+        :complexp (if (eq complexp1 :maybe) complexp2 complexp1)
+        :element-type (cond
+                        ((eq eltype1 *wild-type*) eltype2)
+                        ((eq eltype2 *wild-type*) eltype1)
+                        (t (type-intersection eltype1 eltype2))))))
+      *empty-type*))
+
+;;; Check-Array-Dimensions  --  Internal
+;;;
+;;;    Check a supplied dimension list to determine if it is legal.
+;;;
+(defun check-array-dimensions (dims)
+  (typecase dims
+    ((member *) dims)
+    (integer
+     (when (minusp dims)
+       (signal-program-error "Arrays can't have a negative number of dimensions: ~D." dims))
+     (when (>= dims array-rank-limit)
+       (signal-program-error "Array type has too many dimensions: ~S." dims))
+     (make-list dims :initial-element '*))
+    (list
+     (when (>= (length dims) array-rank-limit)
+       (signal-program-error "Array type has too many dimensions: ~S." dims))
+     (dolist (dim dims)
+       (unless (eq dim '*)
+	   (unless (and (integerp dim)
+		          (>= dim 0) (< dim array-dimension-limit))
+	     (signal-program-error "Bad dimension in array type: ~S." dim))))
+     dims)
+    (t
+     (signal-program-error "Array dimensions is not a list, integer or *:~%  ~S"
+			   dims))))
+
+(def-type-translator array (&optional element-type dimensions &environment env)
+  (specialize-array-type
+   (make-array-ctype :dimensions (check-array-dimensions dimensions)
+		     :complexp :maybe
+		     :element-type (specifier-type element-type env))))
+
+(def-type-translator simple-array (&optional element-type dimensions &environment env)
+  (specialize-array-type
+   (make-array-ctype :dimensions (check-array-dimensions dimensions)
+		         :element-type (specifier-type element-type env)
+		         :complexp nil)))
+
+;;; Order matters here.
+(defparameter specialized-array-element-types
+  '(nil bit (unsigned-byte 8) (signed-byte 8) (unsigned-byte 16)
+    (signed-byte 16) (unsigned-byte 32) #+32-bit-target fixnum (signed-byte 32)
+    #+64-bit-target (unsigned-byte 64)
+    #+64-bit-target fixnum
+    #+64-bit-target (signed-byte 64)
+    character  short-float double-float))
+
+(defun specialize-array-type (type)
+  (let* ((eltype (array-ctype-element-type type))
+         (specialized-type (if (eq eltype *wild-type*)
+                             *wild-type*
+                             (dolist (stype-name specialized-array-element-types
+                                      *universal-type*)
+                               (let ((stype (specifier-type stype-name)))
+                                 (when (csubtypep eltype stype)
+                                   (return stype)))))))
+    
+    (setf (array-ctype-specialized-element-type type) specialized-type
+          (array-ctype-typecode type) (unless (eq specialized-type *wild-type*)
+                                        (ctype-subtype specialized-type)))
+    type))
+
+
+
+;;;; Member types.
+
+;;; The Member-Type represents uses of the MEMBER type specifier.  We bother
+;;; with this at this level because MEMBER types are fairly important and union
+;;; and intersection are well defined.
+
+(defun %make-member-ctype (members)
+  (%istruct 'member-ctype
+            (type-class-or-lose 'member)
+            t
+            members))
+
+(defun make-member-ctype (&key members)
+  (let* ((singlep (subsetp '(-0.0f0 0.0f0) members))
+	 (doublep (subsetp '(-0.0d0 0.0d0) members))
+	 (union-types
+	  (if singlep
+	    (if doublep
+	      (list *ctype-of-single-float-0* *ctype-of-double-float-0*)
+	      (list *ctype-of-single-float-0*))
+	    (if doublep
+	      (list *ctype-of-double-float-0*)))))
+    (if union-types
+      (progn
+	(if singlep
+	  (setq members (set-difference '(-0.0f0 0.0f0) members)))
+	(if doublep
+	  (setq members (set-difference '(-0.d00 0.0d0) members)))
+	(make-union-ctype (if (null members)
+			    union-types
+			    (cons (%make-member-ctype members) union-types))))
+      (%make-member-ctype members))))
+	
+
+(defun member-ctype-p (x) (istruct-typep x 'member-ctype))
+(setf (type-predicate 'member-ctype) 'member-ctype-p)
+
+(define-type-method (member :unparse) (type)
+  (if (type= type (specifier-type 'standard-char))
+    'standard-char
+    (let ((members (member-ctype-members type)))
+      (if (equal members '(nil))
+	'null
+	`(member ,@members)))))
+
+(define-type-method (member :simple-subtypep) (type1 type2)
+  (values (subsetp (member-ctype-members type1) (member-ctype-members type2))
+	    t))
+
+
+(define-type-method (member :complex-subtypep-arg1) (type1 type2)
+  (every/type (swapped-args-fun #'ctypep)
+	      type2
+	      (member-ctype-members type1)))
+
+;;; We punt if the odd type is enumerable and intersects with the member type.
+;;; If not enumerable, then it is definitely not a subtype of the member type.
+;;;
+(define-type-method (member :complex-subtypep-arg2) (type1 type2)
+  (cond ((not (ctype-enumerable type1)) (values nil t))
+	  ((types-intersect type1 type2)
+	   (invoke-complex-subtypep-arg1-method type1 type2))
+	  (t
+	   (values nil t))))
+
+(define-type-method (member :simple-intersection) (type1 type2)
+  (let ((mem1 (member-ctype-members type1))
+	(mem2 (member-ctype-members type2)))
+    (values (cond ((subsetp mem1 mem2) type1)
+		  ((subsetp mem2 mem1) type2)
+		  (t
+		   (let ((res (intersection mem1 mem2)))
+		     (if res
+		       (make-member-ctype :members res)
+		       *empty-type*))))
+	    t)))
+
+(define-type-method (member :complex-intersection) (type1 type2)
+  (block PUNT
+    (collect ((members))
+      (let ((mem2 (member-ctype-members type2)))
+        (dolist (member mem2)
+	  (multiple-value-bind (val win) (ctypep member type1)
+	    (unless win
+	      (return-from punt nil))
+	    (when val (members member))))
+	(cond ((subsetp mem2 (members)) type2)
+	      ((null (members)) *empty-type*)
+	      (t
+	       (make-member-ctype :members (members))))))))
+
+;;; We don't need a :COMPLEX-UNION, since the only interesting case is a union
+;;; type, and the member/union interaction is handled by the union type
+;;; method.
+(define-type-method (member :simple-union) (type1 type2)
+  (let ((mem1 (member-ctype-members type1))
+	(mem2 (member-ctype-members type2)))
+    (cond ((subsetp mem1 mem2) type2)
+	  ((subsetp mem2 mem1) type1)
+	  (t
+	   (make-member-ctype :members (union mem1 mem2))))))
+
+
+(define-type-method (member :simple-=) (type1 type2)
+  (let ((mem1 (member-ctype-members type1))
+	(mem2 (member-ctype-members type2)))
+    (values (and (subsetp mem1 mem2) (subsetp mem2 mem1))
+	    t)))
+
+(define-type-method (member :complex-=) (type1 type2)
+  (if (ctype-enumerable type1)
+    (multiple-value-bind (val win)
+			       (csubtypep type2 type1)
+	(if (or val (not win))
+        (values nil nil)
+        (values nil t)))
+    (values nil t)))
+
+(def-type-translator member (&rest members)
+  (if members
+    (collect ((non-numbers) (numbers))
+      (dolist (m (remove-duplicates members))
+	(if (and (numberp m)
+		 (not (and (floatp m) (zerop m))))
+	  (numbers (ctype-of m))
+	  (non-numbers m)))
+      (apply #'type-union
+	     (if (non-numbers)
+	       (make-member-ctype :members (non-numbers))
+	       *empty-type*)
+	     (numbers)))
+    *empty-type*))
+
+
+
+
+;;;; Union types:
+
+;;; The Union-Type represents uses of the OR type specifier which can't be
+;;; canonicalized to something simpler.  Canonical form:
+;;;
+;;; 1] There is never more than one Member-Type component.
+;;; 2] There are never any Union-Type components.
+;;;
+
+(defun make-union-ctype (types)
+  (declare (list types))
+  (%istruct 'union-ctype
+            (type-class-or-lose 'union)
+            (every #'(lambda (x) (ctype-enumerable x)) types)
+            types))
+
+(defun union-ctype-p (x) (istruct-typep x 'union-ctype))
+(setf (type-predicate 'union-ctype) 'union-ctype-p)
+
+
+;;;    If List, then return that, otherwise the OR of the component types.
+;;;
+(define-type-method (union :unparse) (type)
+  (declare (type ctype type))
+    (cond
+      ((type= type (specifier-type 'list)) 'list)
+      ((type= type (specifier-type 'float)) 'float)
+      ((type= type (specifier-type 'real)) 'real)
+      ((type= type (specifier-type 'sequence)) 'sequence)
+      ((type= type (specifier-type 'bignum)) 'bignum)
+      (t `(or ,@(mapcar #'type-specifier (union-ctype-types type))))))
+
+
+
+(define-type-method (union :simple-=) (type1 type2)
+  (multiple-value-bind (subtype certain?)
+      (csubtypep type1 type2)
+    (if subtype
+      (csubtypep type2 type1)
+      (if certain?
+	(values nil t)
+	(multiple-value-bind (subtype certain?)
+	    (csubtypep type2 type1)
+	  (declare (ignore subtype))
+	  (values nil certain?))))))
+
+
+(define-type-method (union :complex-=) (type1 type2)
+  (declare (ignore type1))
+  (if (some #'type-might-contain-other-types-p 
+	    (union-ctype-types type2))
+    (values nil nil)
+    (values nil t)))
+
+
+(defun union-simple-subtypep (type1 type2)
+  (every/type (swapped-args-fun #'union-complex-subtypep-arg2)
+	      type2
+	      (union-ctype-types type1)))
+
+(define-type-method (union :simple-subtypep) (type1 type2)
+  (union-simple-subtypep type1 type2))
+
+(defun union-complex-subtypep-arg1 (type1 type2)
+  (every/type (swapped-args-fun #'csubtypep)
+	      type2
+	      (union-ctype-types type1)))
+
+(define-type-method (union :complex-subtypep-arg1) (type1 type2)
+  (union-complex-subtypep-arg1 type1 type2))
+
+(defun union-complex-subtypep-arg2 (type1 type2)
+  (multiple-value-bind (sub-value sub-certain?)
+      (progn
+	(assert (union-ctype-p type2))
+	(assert (not (union-ctype-p type1)))
+	(type= type1
+	       (apply #'type-union
+		      (mapcar (lambda (x) (type-intersection type1 x))
+			      (union-ctype-types type2)))))
+    (if sub-certain?
+      (values sub-value sub-certain?)
+      (invoke-complex-subtypep-arg1-method type1 type2))))
+
+(define-type-method (union :complex-subtypep-arg2) (type1 type2)
+  (union-complex-subtypep-arg2 type1 type2))
+
+(define-type-method (union :simple-intersection :complex-intersection)
+    (type1 type2)
+  (assert (union-ctype-p type2))
+  (cond ((and (union-ctype-p type1)
+	      (union-simple-subtypep type1 type2)) type1)
+	((and (union-ctype-p type1)
+	      (union-simple-subtypep type2 type1)) type2)
+	((and (not (union-ctype-p type1))
+	      (union-complex-subtypep-arg2 type1 type2))
+	 type1)
+	((and (not (union-ctype-p type1))
+	      (union-complex-subtypep-arg1 type2 type1))
+	 type2)
+	(t 
+	 (let ((accumulator *empty-type*))
+	   (dolist (t2 (union-ctype-types type2) accumulator)
+	     (setf accumulator
+		   (type-union accumulator
+			       (type-intersection type1 t2))))))))
+
+
+
+(def-type-translator or (&rest type-specifiers &environment env)
+  (apply #'type-union
+	 (mapcar #'(lambda (spec) (specifier-type spec env)) type-specifiers)))
+
+
+
+;;; Intersection types
+(defun make-intersection-ctype (enumerable types)
+  (%istruct 'intersection-ctype
+	    (type-class-or-lose 'intersection)
+	    enumerable
+	    types))
+
+(defun intersection-ctype-p (x)
+  (istruct-typep x 'intersection-ctype))
+(setf (type-predicate 'intersection-ctype) 'intersection-ctype-p)
+
+(define-type-method (intersection :unparse) (type)
+  (declare (type ctype type))
+  (or (find type '(ratio keyword) :key #'specifier-type :test #'type=)
+      `(and ,@(mapcar #'type-specifier (intersection-ctype-types type)))))
+
+;;; shared machinery for type equality: true if every type in the set
+;;; TYPES1 matches a type in the set TYPES2 and vice versa
+(defun type=-set (types1 types2)
+  (flet (;; true if every type in the set X matches a type in the set Y
+	 (type<=-set (x y)
+	   (declare (type list x y))
+	   (every (lambda (xelement)
+		    (position xelement y :test #'type=))
+		  x)))
+    (values (and (type<=-set types1 types2)
+		 (type<=-set types2 types1))
+	    t)))
+
+(define-type-method (intersection :simple-=) (type1 type2)
+  (type=-set (intersection-ctype-types type1)
+	     (intersection-ctype-types type2)))
+
+(defun %intersection-complex-subtypep-arg1 (type1 type2)
+  (type= type1 (type-intersection type1 type2)))
+
+(defun %intersection-simple-subtypep (type1 type2)
+  (every/type #'%intersection-complex-subtypep-arg1
+	      type1
+	      (intersection-ctype-types type2)))
+
+(define-type-method (intersection :simple-subtypep) (type1 type2)
+  (%intersection-simple-subtypep type1 type2))
+  
+(define-type-method (intersection :complex-subtypep-arg1) (type1 type2)
+  (%intersection-complex-subtypep-arg1 type1 type2))
+
+(defun %intersection-complex-subtypep-arg2 (type1 type2)
+  (every/type #'csubtypep type1 (intersection-ctype-types type2)))
+
+(define-type-method (intersection :complex-subtypep-arg2) (type1 type2)
+  (%intersection-complex-subtypep-arg2 type1 type2))
+
+(define-type-method (intersection :simple-union :complex-union)
+    (type1 type2)
+  (assert (intersection-ctype-p type2))
+  (cond ((and (intersection-ctype-p type1)
+	      (%intersection-simple-subtypep type1 type2)) type2)
+	((and (intersection-ctype-p type1)
+	      (%intersection-simple-subtypep type2 type1)) type1)
+	((and (not (intersection-ctype-p type1))
+	      (%intersection-complex-subtypep-arg2 type1 type2))
+	 type2)
+	((and (not (intersection-ctype-p type1))
+	      (%intersection-complex-subtypep-arg1 type2 type1))
+	 type1)
+	((and (csubtypep type2 (specifier-type 'ratio))
+	      (numeric-ctype-p type1)
+	      (csubtypep type1 (specifier-type 'integer))
+	      (csubtypep type2
+			 (make-numeric-ctype
+			  :class 'rational
+			  :complexp nil
+			  :low (if (null (numeric-ctype-low type1))
+				 nil
+				 (list (1- (numeric-ctype-low type1))))
+			  :high (if (null (numeric-ctype-high type1))
+				  nil
+				  (list (1+ (numeric-ctype-high type1)))))))
+	 (type-union type1
+		     (apply #'type-intersection
+			    (remove (specifier-type '(not integer))
+				    (intersection-ctype-types type2)
+				    :test #'type=))))
+	(t
+	 (let ((accumulator *universal-type*))
+	   (do ((t2s (intersection-ctype-types type2) (cdr t2s)))
+	       ((null t2s) accumulator)
+	     (let ((union (type-union type1 (car t2s))))
+	       (when (union-ctype-p union)
+		 (if (and (eq accumulator *universal-type*)
+			  (null (cdr t2s)))
+		     (return union)
+		     (return nil)))
+	       (setf accumulator
+		     (type-intersection accumulator union))))))))
+
+(def-type-translator and (&rest type-specifiers &environment env)
+  (apply #'type-intersection
+	 (mapcar #'(lambda (spec) (specifier-type spec env))
+		 type-specifiers)))
+
+;;; cons-ctype
+(defun wild-ctype-to-universal-ctype (c)
+  (if (type= c *wild-type*)
+    *universal-type*
+    c))
+
+(defun make-cons-ctype (car-ctype-value cdr-ctype-value)
+  (if (or (eq car-ctype-value *empty-type*)
+	  (eq cdr-ctype-value *empty-type*))
+    *empty-type*
+    (%istruct 'cons-ctype
+	      (type-class-or-lose 'cons)
+	      nil
+	      (wild-ctype-to-universal-ctype car-ctype-value)
+	      (wild-ctype-to-universal-ctype cdr-ctype-value))))
+
+(defun cons-ctype-p (x)
+  (istruct-typep x 'cons-ctype))
+
+(setf (type-predicate 'cons-ctype) 'cons-ctype-p)
+  
+(def-type-translator cons (&optional (car-type-spec '*) (cdr-type-spec '*) &environment env)
+  (make-cons-ctype (specifier-type car-type-spec env)
+                   (specifier-type cdr-type-spec env)))
+
+(define-type-method (cons :unparse) (type)
+  (let* ((car-spec (type-specifier (cons-ctype-car-ctype type)))
+         (cdr-spec (type-specifier (cons-ctype-cdr-ctype type))))
+    (if (and (member car-spec '(t *))
+             (member cdr-spec '(t *)))
+      'cons
+      `(cons ,car-spec ,cdr-spec))))
+
+(define-type-method (cons :simple-=) (type1 type2)
+  (declare (cons-ctype type1 type2))
+  (and (type= (cons-ctype-car-ctype type1) (cons-ctype-car-ctype type2))
+       (type= (cons-ctype-cdr-ctype type1) (cons-ctype-cdr-ctype type2))))
+
+(define-type-method (cons :simple-subtypep) (type1 type2)
+  (declare (cons-ctype type1 type2))
+  (multiple-value-bind (val-car win-car)
+      (csubtypep (cons-ctype-car-ctype type1) (cons-ctype-car-ctype type2))
+    (multiple-value-bind (val-cdr win-cdr)
+	(csubtypep (cons-ctype-cdr-ctype type1) (cons-ctype-cdr-ctype type2))
+      (if (and val-car val-cdr)
+	(values t (and win-car win-cdr))
+	(values nil (or win-car win-cdr))))))
+
+(define-type-method (cons :simple-union) (type1 type2)
+  (declare (type cons-ctype type1 type2))
+  (let ((car-type1 (cons-ctype-car-ctype type1))
+	(car-type2 (cons-ctype-car-ctype type2))
+	(cdr-type1 (cons-ctype-cdr-ctype type1))
+	(cdr-type2 (cons-ctype-cdr-ctype type2))
+        (car-not1)
+        (car-not2))
+    (macrolet ((frob-car (car1 car2 cdr1 cdr2
+                          &optional (not1 nil not1p))
+		 `(type-union
+		   (make-cons-ctype ,car1 (type-union ,cdr1 ,cdr2))
+		   (make-cons-ctype
+		    (type-intersection
+                     ,car2
+                     ,(if not1p
+                          not1
+                          `(specifier-type
+                            `(not ,(type-specifier ,car1))))) 
+		    ,cdr2))))
+      (cond ((type= car-type1 car-type2)
+	     (make-cons-ctype car-type1
+                              (type-union cdr-type1 cdr-type2)))
+	    ((type= cdr-type1 cdr-type2)
+	     (make-cons-ctype (type-union car-type1 car-type2)
+			      cdr-type1))
+	    ((csubtypep car-type1 car-type2)
+	     (frob-car car-type1 car-type2 cdr-type1 cdr-type2))
+	    ((csubtypep car-type2 car-type1)
+	     (frob-car car-type2 car-type1 cdr-type2 cdr-type1))
+            ;; more general case of the above, but harder to compute
+            ((progn
+               (setf car-not1 (specifier-type
+                               `(not ,(type-specifier car-type1))))
+               (not (csubtypep car-type2 car-not1)))
+             (frob-car car-type1 car-type2 cdr-type1 cdr-type2 car-not1))
+            ((progn
+               (setf car-not2 (specifier-type
+                               `(not ,(type-specifier car-type2))))
+               (not (csubtypep car-type1 car-not2)))
+             (frob-car car-type2 car-type1 cdr-type2 cdr-type1 car-not2))))))
+	    
+(define-type-method (cons :simple-intersection) (type1 type2)
+  (declare (type cons-ctype type1 type2))
+  (let ((car-int2 (type-intersection2 (cons-ctype-car-ctype type1)
+				      (cons-ctype-car-ctype type2)))
+	(cdr-int2 (type-intersection2 (cons-ctype-cdr-ctype type1)
+				      (cons-ctype-cdr-ctype type2))))
+    (cond ((and car-int2 cdr-int2)
+	   (make-cons-ctype car-int2 cdr-int2))
+	  (car-int2
+	   (make-cons-ctype car-int2
+			    (type-intersection (cons-ctype-cdr-ctype type1)
+					       (cons-ctype-cdr-ctype type2))))
+	  (cdr-int2
+	   (make-cons-ctype (type-intersection (cons-ctype-car-ctype type1)
+					       (cons-ctype-car-ctype type2))
+			    cdr-int2)))))
+
+
+
+;;; An UNKNOWN-TYPE is a type not known to the type system (not yet defined).
+;;; We make this distinction since we don't want to complain about types that
+;;; are hairy but defined.
+;;;
+
+(defun make-unknown-ctype (&key specifier (enumerable t))
+  (%istruct 'unknown-ctype
+            (type-class-or-lose 'hairy)
+            enumerable
+            specifier))
+
+(defun unknown-ctype-p (x)
+  (istruct-typep x 'unknown-ctype))
+
+(setf (type-predicate 'unknown-ctype) 'unknown-ctype-p)
+
+
+
+
+
+;;;; foreign-type types
+
+
+(defun %make-foreign-ctype (foreign-type)
+  (%istruct 'foreign-ctype
+            (type-class-or-lose 'foreign)
+            nil
+            foreign-type))
+
+(defun foreign-ctype-p (x) (istruct-typep x 'foreign-ctype))
+(setf (type-predicate 'foreign-ctype) 'foreign-ctype-p)
+
+(define-type-method (foreign :unparse) (type)
+  `(foreign ,(unparse-foreign-type (foreign-ctype-foreign-type type))))
+
+(define-type-method (foreign :simple-subtypep) (type1 type2)
+  (values (foreign-subtype-p (foreign-ctype-foreign-type type1)
+			           (foreign-ctype-foreign-type type2))
+	    t))
+
+;(define-superclasses foreign (foreign-value))
+
+(define-type-method (foreign :simple-=) (type1 type2)
+  (let ((foreign-type-1 (foreign-ctype-foreign-type type1))
+	  (foreign-type-2 (foreign-ctype-foreign-type type2)))
+    (values (or (eq foreign-type-1 foreign-type-2)
+		    (foreign-type-= foreign-type-1 foreign-type-2))
+	      t)))
+
+(def-type-translator foreign (&optional (foreign-type nil))
+  (typecase foreign-type
+    (null
+     (make-foreign-ctype))
+    (foreign-type
+     (make-foreign-ctype foreign-type))
+    (t
+     (make-foreign-ctype (parse-foreign-type foreign-type)))))
+
+(defun make-foreign-ctype (&optional foreign-type)
+  (if foreign-type
+      (let ((lisp-rep-type (compute-lisp-rep-type foreign-type)))
+	(if lisp-rep-type
+	    (specifier-type lisp-rep-type)
+	    (%make-foreign-ctype foreign-type)))
+      *universal-type*))
+
+
+;;; CLASS-CTYPES are supposed to help integrate CLOS and the CMU type system.
+;;; They mostly just contain a backpointer to the CLOS class; the CPL is then
+;;;  used to resolve type relationships.
+
+(defun class-ctype-p (x) (istruct-typep x 'class-ctype))
+(setf (type-predicate 'class-ctype) 'class-ctype-p)
+
+(defun args-ctype-p (x) (and (eql (typecode x) target::subtag-istruct)
+                             (member (istruct-type-name x)
+                                     '(args-ctype values-ctype function-ctype))))
+
+(setf (type-predicate 'args-ctype) 'args-ctype-p
+      (type-predicate 'function-ctype) 'function-ctype-p
+      (type-predicate 'values-ctype) 'values-ctype-p)
+
+
+;;; Simple methods for TYPE= and SUBTYPEP should never be called when the two
+;;; classes are equal, since there are EQ checks in those operations.
+;;;
+(define-type-method (class :simple-=) (type1 type2)
+  (assert (not (eq type1 type2)))
+  (values nil t))
+
+(define-type-method (class :simple-subtypep) (type1 type2)
+  (assert (not (eq type1 type2)))
+  (let* ((class1 (if (class-ctype-p type1) (class-ctype-class type1)))
+         (class2 (if (class-ctype-p type2) (class-ctype-class type2))))
+    (if (and class1 class2)
+      (let* ((ordinal2 (%class-ordinal class2))
+             (wrapper1 (%class.own-wrapper class1))
+             (bits1 (if wrapper1 (%wrapper-cpl-bits wrapper1))))
+        (if bits1
+          (locally (declare (simple-bit-vector bits1)
+                            (optimize (speed 3) (safety 0)))
+            (values (if (< ordinal2 (length bits1))
+                      (not (eql 0 (sbit bits1 ordinal2))))
+                    t))
+          (if (%standard-instance-p class1)
+            (if (memq class2 (%class.local-supers class1))
+              (values t t)
+              (if (eq (%class-of-instance class1)
+                      *forward-referenced-class-class*)
+                (values nil nil)
+                ;; %INITED-CLASS-CPL will return NIL if class1 can't
+                ;; be finalized; in that case, we don't know the answer.
+                (let ((supers (%inited-class-cpl class1)))
+                  (if (memq class2 supers)
+                    (values t t)
+                    (values nil (not (null supers)))))))
+            (values nil t))))
+      (values nil t))))
+
+(defun find-class-intersection (c1 c2)
+  (labels ((walk-subclasses (class f)
+	     (dolist (sub (class-direct-subclasses class))
+	       (walk-subclasses sub f))
+	     (funcall f class)))
+    (let* ((intersection nil))
+      (walk-subclasses c1 #'(lambda (c)
+			      (when (subclassp c c2)
+				(pushnew (%class.ctype c) intersection))))
+      (when intersection
+	(%type-union intersection)))))
+
+(define-type-method (class :simple-intersection) (type1 type2)
+  (assert (not (eq type1 type2)))
+  (let* ((class1 (if (class-ctype-p type1) (class-ctype-class type1)))
+         (class2 (if (class-ctype-p type2) (class-ctype-class type2))))
+    (if (and class1
+             (not (typep class1 'compile-time-class))
+             class2
+             (not (typep class2 'compile-time-class)))
+      (cond ((subclassp class1 class2)
+             type1)
+            ((subclassp class2 class1)
+             type2)
+	    ;;; In the STANDARD-CLASS case where neither's
+	    ;;; a subclass of the other, there may be
+	    ;;; one or mor classes that're a subclass of both.  We
+	    ;;; -could- try to find all such classes, but
+	    ;;; punt instead.
+            (t (or (find-class-intersection class1 class2)
+		 *empty-type*)))
+      nil)))
+
+(define-type-method (class :complex-subtypep-arg2) (type1 class2)
+  (if (and (intersection-ctype-p type1)
+	   (> (count-if #'class-ctype-p (intersection-ctype-types type1)) 1))
+      (values nil nil)
+      (if (function-ctype-p type1)
+	(csubtypep (specifier-type 'function) class2)
+	(invoke-complex-subtypep-arg1-method type1 class2 nil t))))
+
+(define-type-method (class :complex-subtypep-arg1) (type1 type2)
+  (if (and (function-ctype-p type2)
+	   (eq type1 (specifier-type 'function))
+	   (function-ctype-wild-args type2)
+	   (eq *wild-type* (function-ctype-returns type2)))
+      (values t t)
+      (values nil t)))
+
+(define-type-method (class :unparse) (type)
+  (class-name (class-ctype-class type)))
+
+
+
+;;; TYPE-DIFFERENCE  --  Interface
+;;;
+;;;    Return the type that describes all objects that are in X but not in Y.
+;;; If we can't determine this type, then return NIL.
+;;;
+;;;    For now, we only are clever dealing with union and member types.  If
+;;; either type is not a union type, then we pretend that it is a union of just
+;;; one type.  What we do is remove from X all the types that are a subtype any
+;;; type in Y.  If any type in X intersects with a type in Y but is not a
+;;; subtype, then we give up.
+;;;
+;;;    We must also special-case any member type that appears in the union.  We
+;;; remove from X's members all objects that are TYPEP to Y.  If Y has any
+;;; members, we must be careful that none of those members are CTYPEP to any
+;;; of Y's non-member types.  We give up in this case, since to compute that
+;;; difference we would have to break the type from X into some collection of
+;;; types that represents the type without that particular element.  This seems
+;;; too hairy to be worthwhile, given its low utility.
+;;;
+(defun type-difference (x y)
+  (let ((x-types (if (union-ctype-p x) (union-ctype-types x) (list x)))
+	(y-types (if (union-ctype-p y) (union-ctype-types y) (list y))))
+    (collect ((res))
+      (dolist (x-type x-types)
+	(if (member-ctype-p x-type)
+	    (collect ((members))
+	      (dolist (mem (member-ctype-members x-type))
+		(multiple-value-bind (val win) (ctypep mem y)
+		  (unless win (return-from type-difference nil))
+		  (unless val
+		    (members mem))))
+	      (when (members)
+		(res (make-member-ctype :members (members)))))
+	    (dolist (y-type y-types (res x-type))
+	      (multiple-value-bind (val win) (csubtypep x-type y-type)
+		(unless win (return-from type-difference nil))
+		(when val (return))
+		(when (types-intersect x-type y-type)
+		  (return-from type-difference nil))))))
+      (let ((y-mem (find-if #'member-ctype-p y-types)))
+	(when y-mem
+	  (let ((members (member-ctype-members y-mem)))
+	    (dolist (x-type x-types)
+	      (unless (member-ctype-p x-type)
+		(dolist (member members)
+		  (multiple-value-bind (val win) (ctypep member x-type)
+		    (when (or (not win) val)
+		      (return-from type-difference nil)))))))))
+      (apply #'type-union (res)))))
+
+;;; CTypep  --  Interface
+;;;
+;;;    If Type is a type that we can do a compile-time test on, then return the
+;;; whether the object is of that type as the first value and second value
+;;; true.  Otherwise return NIL, NIL.
+;;;
+;;; We give up on unknown types, pick off FUNCTION and UNION types.  For
+;;; structure types, we require that the type be defined in both the current
+;;; and compiler environments, and that the INCLUDES be the same.
+;;;
+(defun ctypep (obj type)
+  (declare (type ctype type))
+  (etypecase type
+    ((or numeric-ctype named-ctype member-ctype array-ctype cons-ctype)
+     (values (%typep obj type) t))
+    (class-ctype
+     (values (not (null (class-typep  obj (class-ctype-class type)))) t)
+)
+    (union-ctype
+     (any/type #'ctypep obj (union-ctype-types type)))
+    (intersection-ctype
+     (every/type #'ctypep obj (intersection-ctype-types type)))
+    (function-ctype
+     (values (functionp obj) t))
+    (unknown-ctype
+     (values nil nil))
+    (foreign-ctype
+     (values (foreign-typep obj (foreign-ctype-foreign-type type)) t))
+    (negation-ctype
+     (multiple-value-bind (res win)
+	 (ctypep obj (negation-ctype-type type))
+       (if win
+	   (values (not res) t)
+	   (values nil nil))))
+    (hairy-ctype
+     ;; Now the tricky stuff.
+     (let* ((hairy-spec (hairy-ctype-specifier type))
+	    (symbol (if (consp hairy-spec) (car hairy-spec) hairy-spec)))
+       (ecase symbol
+	 (and				; how would this get there ?
+	  (if (atom hairy-spec)
+	    (values t t)
+	    (dolist (spec (cdr hairy-spec) (values t t))
+	      (multiple-value-bind (res win)
+		  (ctypep obj (specifier-type spec))
+		(unless win (return (values nil nil)))
+		(unless res (return (values nil t)))))))
+	   (not				; how would this get there ?
+	    (multiple-value-bind
+	      (res win)
+		(ctypep obj (specifier-type (cadr hairy-spec)))
+	      (if win
+		(values (not res) t)
+		(values nil nil))))
+	   (satisfies
+	    (let ((fun (second hairy-spec)))
+	      (cond ((and (symbolp fun) (fboundp fun))
+                     ;; Binding *BREAK-ON-SIGNALS* here is a modularity
+                     ;; violation intended to improve the signal-to-noise
+                     ;; ratio on a mailing list.
+		     (values (not (null (let* ((*break-on-signals* nil))
+                                          (ignore-errors (funcall fun obj))))) t))
+		    (t
+		     (values nil nil))))))))))
+
+;;; %TYPEP -- internal.
+;;;
+;;; The actual typep engine.  The compiler only generates calls to this
+;;; function when it can't figure out anything more intelligent to do.
+;;;
+; lose 1 function call -MAYBE
+(defun %typep (object specifier)
+  (%%typep object
+           (if (typep specifier 'ctype)
+	     specifier
+	     (specifier-type specifier))))
+
+(eval-when (:compile-toplevel)
+  (declaim (inline numeric-%%typep
+                   array-%%typep
+                   member-%%typep
+                   cons-%%typep)))
+
+(defun numeric-%%typep (object type)
+  (let ((pred (numeric-ctype-predicate type)))
+    (if pred
+      (funcall pred object)
+      (and (numberp object)
+           (let ((num (if (complexp object) (realpart object) object)))
+             (ecase (numeric-ctype-class type)
+               (integer (integerp num))
+               (rational (rationalp num))
+               (float
+                (ecase (numeric-ctype-format type)
+                  (single-float (typep num 'single-float))
+                  (double-float (typep num 'double-float))
+                  ((nil) (floatp num))))
+               ((nil) t)))
+           (flet ((bound-test (val)
+                    (let ((low (numeric-ctype-low type))
+                          (high (numeric-ctype-high type)))
+                      (and (cond ((null low) t)
+                                 ((listp low) (> val (car low)))
+                                 (t (>= val low)))
+                           (cond ((null high) t)
+                                 ((listp high) (< val (car high)))
+                                 (t (<= val high)))))))
+             (ecase (numeric-ctype-complexp type)
+               ((nil) t)
+               (:complex
+                (and (complexp object)
+                     (bound-test (realpart object))
+                     (bound-test (imagpart object))))
+               (:real
+                (and (not (complexp object))
+                     (bound-test object)))))))))
+
+(defun array-%%typep (object type)
+  (let* ((typecode (typecode object)))
+    (declare (type (unsigned-byte 8) typecode))
+    (and (>= typecode target::subtag-arrayH)
+         (ecase (array-ctype-complexp type)
+           ((t) (not (simple-array-p object)))
+           ((nil) (simple-array-p object))
+           ((* :maybe) t))
+         (let* ((ctype-dimensions (array-ctype-dimensions type)))
+           (or (eq ctype-dimensions '*)
+	       (if (eql typecode target::subtag-arrayH)
+		   (let* ((rank (%svref object target::arrayH.rank-cell)))
+		     (declare (fixnum rank))
+		     (and (eql rank (length ctype-dimensions))
+			  (do* ((i 0 (1+ i))
+				(dim target::arrayH.dim0-cell (1+ dim))
+				(want (array-ctype-dimensions type) (cdr want))
+				(got (%svref object dim) (%svref object dim)))
+			       ((eql i rank) t)
+			    (unless (or (eq (car want) '*)
+					(eql (%car want) (the fixnum got)))
+			      (return nil)))))
+		   (and (null (cdr ctype-dimensions))
+			(or (eq (%car ctype-dimensions) '*)
+			    (eql (%car ctype-dimensions)
+                                 (if (eql typecode target::subtag-vectorH)
+                                   (%svref object target::vectorH.physsize-cell)
+                                   (uvsize object))))))))
+	 (or (eq (array-ctype-element-type type) *wild-type*)
+	     (eql (array-ctype-typecode type)
+		  (if (> typecode target::subtag-vectorH)
+                      typecode
+                      (ldb target::arrayH.flags-cell-subtag-byte (the fixnum (%svref object target::arrayH.flags-cell)))))
+	     (type= (array-ctype-specialized-element-type type)
+		    (specifier-type (array-element-type object)))))))
+
+
+(defun member-%%typep (object type)
+  (not (null (member object (member-ctype-members type)))))
+
+(defun cons-%%typep (object type) 
+  (and (consp object)
+       (%%typep (car object) (cons-ctype-car-ctype type))
+       (%%typep (cdr object) (cons-ctype-cdr-ctype type)))) 
+
+
+(defun %%typep (object type)
+  ;(if (not (typep type 'ctype))(setq type (specifier-type type)))
+  (locally (declare (type ctype type))
+    (etypecase type
+      (named-ctype
+       (ecase (named-ctype-name type)
+         ((* t) t)
+         ((nil) nil)))
+      (numeric-ctype
+       (numeric-%%typep object type))
+      (array-ctype
+       (array-%%typep object type))
+      (member-ctype
+       (member-%%typep object type))
+      (class-ctype
+       (not (null (class-typep object (class-ctype-class type)))))
+      (union-ctype
+       (dolist (type (union-ctype-types type))
+         (when (%%typep object type)
+           (return t))))
+      (intersection-ctype
+       (dolist (type (intersection-ctype-types type) t)
+         (unless (%%typep object type) (return nil))))
+      (cons-ctype
+       (cons-%%typep object type))
+      (unknown-ctype
+       ;; Parse it again to make sure it's really undefined.
+       (let ((reparse (specifier-type (unknown-ctype-specifier type))))
+         (if (typep reparse 'unknown-ctype)
+           (error "Unknown type specifier: ~S"
+                  (unknown-ctype-specifier reparse))
+           (%%typep object reparse))))
+      (negation-ctype
+       (not (%%typep object (negation-ctype-type type))))
+      (hairy-ctype
+       ;; Now the tricky stuff.
+       (let* ((hairy-spec (hairy-ctype-specifier type))
+              (symbol (if (consp hairy-spec) (car hairy-spec) hairy-spec)))
+         (ecase symbol
+           (and
+            (or (atom hairy-spec)
+                (dolist (spec (cdr hairy-spec) t)
+                  (unless (%%typep object (specifier-type spec))
+                    (return nil)))))
+           (not
+            (unless (and (listp hairy-spec) (= (length hairy-spec) 2))
+              (error "Invalid type specifier: ~S" hairy-spec))
+            (not (%%typep object (specifier-type (cadr hairy-spec)))))
+           (satisfies
+            (unless (and (listp hairy-spec) (= (length hairy-spec) 2))
+              (error "Invalid type specifier: ~S" hairy-spec))
+            (let ((fn (cadr hairy-spec)))
+              (if (funcall (typecase fn
+                             (function fn)
+                             (symbol (symbol-function fn))
+                             (t
+                              (coerce fn 'function)))
+                           object)
+                t
+                nil))))))
+      #|
+    (foreign-ctype
+     (foreign-typep object (foreign-ctype-foreign-type type)))
+|#
+      (function-ctype
+       (error "Function types are not a legal argument to TYPEP:~%  ~S"
+              (type-specifier type))))))
+
+
+;;; Ctype-Of  --  Interface
+;;;
+;;;    Like Type-Of, only returns a Type structure instead of a type
+;;; specifier.  We try to return the type most useful for type checking, rather
+;;; than trying to come up with the one that the user might find most
+;;; informative.
+;;;
+
+(defun float-format-name (x)
+  (declare (float x))
+  (etypecase x
+    (single-float "SINGLE-FLOAT")
+    (double-float "DOUBLE-FLOAT")))
+
+(defun ctype-of-number (x)
+  (let ((num (if (complexp x) (realpart x) x)))
+    (multiple-value-bind (complexp low high)
+	(if (complexp x)
+	    (let ((imag (imagpart x)))
+	      (values :complex (min num imag) (max num imag)))
+	    (values :real num num))
+      (make-numeric-ctype :class (etypecase num
+				   (integer (if (complexp x)
+                                                (if (integerp (imagpart x))
+                                                    'integer
+                                                    'rational)
+                                                'integer))
+				   (rational 'rational)
+				   (float 'float))
+			  :format (and (floatp num)
+				       (if (typep num 'double-float)
+					 'double-float
+					 'single-float))
+			  :complexp complexp
+			  :low low
+			  :high high))))
+
+(defun ctype-of (x)
+  (typecase x
+    (function (specifier-type 'function)) ; GFs ..
+    (symbol
+     (make-member-ctype :members (list x)))
+    (number (ctype-of-number x))
+    (array
+     (let ((etype (specifier-type (array-element-type x))))
+       (make-array-ctype :dimensions (array-dimensions x)
+			 :complexp (not (typep x 'simple-array))
+			 :element-type etype
+			 :specialized-element-type etype)))
+    (t
+     (%class.ctype (class-of x)))))
+
+(defvar *ctype-of-double-float-0* (ctype-of 0.0d0))
+(defvar *ctype-of-single-float-0* (ctype-of 0.0f0))
+
+
+
+
+; These DEFTYPES should only happen while initializing.
+
+(progn
+(let-globally ((*type-system-initialized* nil))
+
+
+(deftype bit () '(integer 0 1))
+
+(deftype eql (val) `(member ,val))
+
+(deftype signed-byte (&optional s)
+  (cond ((eq s '*) 'integer)
+	  ((and (integerp s) (> s 0))
+	   (let ((bound (ash 1 (1- s))))
+	     `(integer ,(- bound) ,(1- bound))))
+	  (t
+	   (signal-program-error "Bad size specified for SIGNED-BYTE type specifier: ~S." s))))
+  
+(deftype unsigned-byte (&optional s)
+  (cond ((eq s '*) '(integer 0))
+	((and (integerp s) (> s 0))
+	 `(integer 0 ,(1- (ash 1 s))))
+	(t
+	 (error "Bad size specified for UNSIGNED-BYTE type specifier: ~S." s))))
+
+(deftype vector (&optional element-type size)
+  `(array ,element-type (,size)))
+
+(deftype simple-vector (&optional size)
+  `(simple-array t (,size)))
+
+(deftype base-string (&optional size)
+  `(array base-char (,size)))
+(deftype simple-base-string (&optional size)
+  `(simple-array base-char (,size)))
+
+
+
+(deftype string (&optional size)
+  `(array character (,size)))
+
+(deftype simple-string (&optional size)
+  `(simple-array character (,size)))
+
+(deftype bit-vector (&optional size)
+  `(array bit (,size)))
+
+(deftype simple-bit-vector (&optional size)
+  `(simple-array bit (,size)))
+
+; TYPE-OF sometimes returns random symbols that aren't really type specifiers.
+
+(deftype simple-unsigned-word-vector (&optional size)
+  `(simple-array (unsigned-byte 16) (,size)))
+
+(deftype simple-unsigned-byte-vector (&optional size)
+  `(simple-array (unsigned-byte 8) (,size)))
+
+(deftype simple-unsigned-long-vector (&optional size)
+  `(simple-array (unsigned-byte 32) (,size)))
+
+(deftype simple-signed-word-vector (&optional size)
+  `(simple-array (signed-byte 16) (,size)))
+
+(deftype simple-signed-byte-vector (&optional size)
+  `(simple-array (signed-byte 8) (,size)))
+
+(deftype simple-signed-long-vector (&optional size)
+  `(simple-array (signed-byte 32) (,size)))
+
+
+
+(deftype simple-short-float-vector (&optional size)
+  `(simple-array short-float (,size)))
+
+(deftype unsigned-word-vector (&optional size)
+  `(vector (unsigned-byte 16) ,size))
+
+(deftype single-float-vector (&optional size)
+  `(vector short-float ,size))
+
+(deftype unsigned-byte-vector (&optional size)
+  `(vector (unsigned-byte 8) ,size))
+
+(deftype unsigned-long-vector (&optional size)
+  `(vector (unsigned-byte 32) ,size))
+
+(deftype long-float-vector (&optional size)
+  `(vector double-float ,size))
+
+(deftype long-vector (&optional size)
+  `(vector (signed-byte 32) ,size))
+
+(deftype double-float-vector (&optional size)
+  `(vector double-float ,size))
+
+(deftype byte-vector (&optional size)
+  `(vector (signed-byte 8) ,size))
+
+(deftype general-vector (&optional size)
+  `(vector t ,size))
+
+(deftype word-vector (&optional size)
+  `(vector (signed-byte 16) ,size))
+
+(deftype short-float-vector (&optional size)
+  `(vector single-float ,size))
+
+(deftype simple-1d-array (&optional size)
+  `(simple-array * (,size)))
+
+(deftype simple-long-vector (&optional size)
+  `(simple-array (signed-byte 32) (,size)))
+
+(deftype simple-word-vector (&optional size)
+  `(simple-array (signed-byte 16) (,size)))
+
+(deftype simple-short-float-vector (&optional size)
+  `(simple-array single-float (,size)))
+
+(deftype simple-byte-vector (&optional size)
+  `(simple-array (signed-byte 8) (,size)))
+
+(deftype simple-double-float-vector (&optional size)
+  `(simple-array double-float (,size)))
+
+(deftype simple-single-float-vector (&optional size)
+  `(simple-array single-float (,size)))
+
+(deftype simple-long-float-vector (&optional size)
+  `(simple-array double-float (,size)))
+
+(deftype simple-fixnum-vector (&optional size)
+  `(simple-array fixnum (,size)))
+
+(deftype fixnum-vector (&optional size)
+  `(array fixnum (,size)))
+
+#+64-bit-target
+(deftype simple-doubleword-vector (&optional size)
+  `(simple-array (signed-byte 64) (,size)))
+
+#+64-bit-target
+(deftype simple-unsigned-doubleword-vector (&optional size)
+  `(simple-array (unsigned-byte 64) (,size)))
+
+
+(deftype short-float (&optional low high)
+  `(single-float ,low ,high))
+
+(deftype long-float (&optional low high)
+  `(double-float ,low ,high))
+
+#||
+;;; As empty a type as you're likely to find ...
+(deftype extended-char ()
+  "Type of CHARACTERs that aren't BASE-CHARs."
+  nil)
+||#
+
+(deftype natural ()
+  `(unsigned-byte ,target::nbits-in-word))
+
+(deftype signed-natural ()
+  `(signed-byte ,target::nbits-in-word))
+)
+
+
+(let* ((builtin-translations 
+        `((array . array)
+          (simple-array . simple-array)
+          (cons . cons)
+          (vector . vector)
+          (null . (member nil))
+          (list . (or cons null))
+          (sequence . (or list vector))
+          (simple-vector . simple-vector)
+          (bit-vector . bit-vector)
+          (simple-bit-vector . simple-bit-vector)
+          (simple-string . simple-string)
+          (simple-base-string . simple-base-string)
+          (string . string)
+          (base-string . base-string)
+          (real . real)
+          (complex . complex)
+          (float . float)
+          (double-float . double-float)
+          (long-float . double-float)
+          (single-float . single-float)
+	  (short-float . single-float)
+
+          (rational . rational)
+          (integer . integer)
+          (ratio . (and rational (not integer)))
+          (fixnum . (integer ,target::target-most-negative-fixnum
+                     ,target::target-most-positive-fixnum))
+          (bignum . (or (integer * (,target::target-most-negative-fixnum))
+                         (integer (,target::target-most-positive-fixnum) *)))
+          
+          )))
+  (dolist (spec builtin-translations)
+    (setf (info-type-kind (car spec)) :primitive
+          (info-type-builtin (car spec)) (specifier-type (cdr spec)))))
+
+
+
+
+
+       
+(precompute-types '((mod 2) (mod 4) (mod 16) (mod #x100) (mod #x10000)
+                    #-cross-compiling
+		    (mod #x100000000)
+		    (unsigned-byte 1) 
+		    (unsigned-byte 8) (unsigned-byte 16) (unsigned-byte 32)
+                    (unsigned-byte 64)
+		    (signed-byte 8) (signed-byte 16) (signed-byte 32)
+                    (signed-byte 64)
+                    (or function symbol)
+                    ))
+
+
+(precompute-types *cl-types*)
+
+;;; Treat CHARACTER and BASE-CHAR as equivalent.
+(setf (info-type-builtin 'character) (info-type-builtin 'base-char))
+;;; And EXTENDED-CHAR as empty.
+(setf (info-type-builtin 'extended-char) *empty-type*)
+
+(defparameter *null-type* (specifier-type 'null))
+
+
+(flet ((set-builtin-class-type-translation (thing)
+         (let* ((class-name (if (atom thing) thing (car thing)))
+                (spec (if (atom thing) thing (cadr thing)))
+                (spectype (specifier-type spec)))
+           (setf (class-ctype-translation
+                  (%class.ctype (find-class class-name))) spectype))))
+  (mapc #'set-builtin-class-type-translation
+        '(
+          ;; Root Of All Evil
+          t
+          ;; Numbers:
+          number real ratio complex rational fixnum
+          ;;  Integers:
+          signed-byte  unsigned-byte bit bignum integer
+          ;;  Floats
+           float  double-float single-float
+          ;; Arrays
+          array
+          ;;  Simple Arrays
+          simple-array
+          ;;  Vectors
+          vector string base-string bit-vector
+          unsigned-byte-vector unsigned-word-vector unsigned-long-vector
+          byte-vector word-vector long-vector
+          single-float-vector double-float-vector
+          general-vector
+          fixnum-vector
+          #+64-bit-target
+          doubleword-vector
+          #+64-bit-target
+          unsigned-doubleword-vector
+          ;;   Simple 1-Dimensional Arrays
+          simple-1d-array  simple-string simple-base-string simple-bit-vector
+          simple-unsigned-byte-vector
+          simple-unsigned-long-vector
+          simple-unsigned-word-vector
+          simple-byte-vector
+          simple-word-vector
+          simple-long-vector 
+          simple-single-float-vector 
+          simple-double-float-vector
+          simple-vector
+          simple-fixnum-vector
+          #+64-bit-target
+          simple-doubleword-vector
+          #+64-bit-target
+          simple-unsigned-doubleword-vector
+          ;; Sequence types
+          sequence list  cons null
+          
+ )
+                                                         
+        ))
+)
+;(setq *type-system-initialized* t)
+
+
+
+
+; These deftypes help the CMUCL compiler; the type system doesn't depend on them.
+
+;;; Since Clozure CL's DEFTYPE tries to globally define the type
+;;; at compile-time as well as load- and execute time, hide
+;;; the definition of these "built-in" types.  (It'd be cleaner
+;;; to make DEFTYPE do something saner at compile-time.)
+(let* ()                                ; make the following be non-toplevel
+(deftype boolean () '(member t nil))
+
+(deftype atom () '(not cons))
+;;;
+;;; A type specifier.
+(deftype type-specifier () '(or list symbol class))
+;;;
+;;; An index into an array.   Also used for sequence index. 
+(deftype index () `(integer 0 (,array-dimension-limit)))
+;;;
+;;; Array rank, total size...
+(deftype array-rank () `(integer 0 (,array-rank-limit)))
+(deftype array-total-size () `(integer 0 (,array-total-size-limit)))
+;;;
+;;; Some thing legal in an evaluated context.
+(deftype form () t)
+;;;
+;;; Maclisp compatibility...
+(deftype stringlike () '(or string symbol))
+(deftype stringable () '(or string symbol character))
+;;;
+;;; Save a little typing...
+(deftype truth () '(member t))
+;;;
+;;; A thing legal in places where we want the name of a file.
+(deftype filename () '(or string pathname))
+;;;
+;;; A legal arg to pathname functions.
+(deftype pathnamelike () '(or string pathname stream))
+;;;
+;;; A thing returned by the irrational functions.  We assume that they never
+;;; compute a rational result.
+(deftype irrational () '(or float (complex float)))
+;;;
+;;; Character components:
+(deftype char-code () `(integer 0 (,char-code-limit)))
+;;;
+;;; A consed sequence result.  If a vector, is a simple array.
+(deftype consed-sequence () '(or list (simple-array * (*))))
+;;;
+;;; The :end arg to a sequence...
+(deftype sequence-end () '(or null index))
+;;;
+;;; A valid argument to a stream function...
+(deftype streamlike () '(or stream (member nil t)))
+;;;
+;;; A thing that can be passed to funcall & friends.
+(deftype callable () '(or function symbol))
+
+;;; Until we decide if and how to wedge this into the type system, make it
+;;; equivalent to t.
+;;;
+(deftype void () t)
+;;;
+;;; An index into an integer.
+(deftype bit-index () `(integer 0 ,target::target-most-positive-fixnum))
+;;;
+;;; Offset argument to Ash (a signed bit index).
+(deftype ash-index () 'fixnum)
+
+;;; Not sure how to do this without SATISFIES.
+(deftype setf-function-name () `(satisfies setf-function-name-p))
+
+;;; Better than nothing, arguably.
+(deftype function-name () `(or symbol setf-function-name))
+
+(deftype valid-char-code () `(satisfies valid-char-code-p))
+
+)                                       ; end of LET* sleaze
+
+(defun array-or-union-ctype-element-type (ctype)
+  (if (typep ctype 'array-ctype)
+    (type-specifier (array-ctype-element-type ctype))
+    (if (typep ctype 'union-ctype)
+      `(or ,@(mapcar #'array-or-union-ctype-element-type 
+                     (union-ctype-types ctype))))))
+
+
+(defvar *simple-predicate-function-prototype*
+  #'(lambda (thing)
+      (%%typep thing #.(specifier-type t))))
+
+(defun make-simple-type-predicate (function datum)
+  #+ppc-target
+  (gvector :function
+           (uvref *simple-predicate-function-prototype* 0)
+           datum
+           function
+           nil
+           (dpb 1 $lfbits-numreq 0))
+  #+x86-target
+  (%clone-x86-function
+   *simple-predicate-function-prototype*
+   datum
+   function
+   nil
+   (dpb 1 $lfbits-numreq 0)))
+
+(defun check-ctypep (thing ctype)
+  (multiple-value-bind (win sure) (ctypep thing ctype)
+    (or win (not sure))))
+
+
+(defun generate-predicate-for-ctype (ctype)
+  (typecase ctype
+    (numeric-ctype
+     (or (numeric-ctype-predicate ctype)
+         (make-simple-type-predicate 'numeric-%%typep ctype)))
+    (array-ctype
+     (make-simple-type-predicate 'array-%%typep ctype))
+    (member-ctype
+     (make-simple-type-predicate 'member-%%typep ctype))
+    (named-ctype
+     (case (named-ctype-name ctype)
+       ((* t) #'true)
+       (t #'false)))
+    (cons-ctype
+     (make-simple-type-predicate 'cons-%%typep ctype))
+    (function-ctype
+     #'functionp)
+    (class-ctype
+     (make-simple-type-predicate 'class-cell-typep (find-class-cell (class-name (class-ctype-class ctype)) t)))
+    (t
+     (make-simple-type-predicate 'check-ctypep ctype))))
+    
+        
+
+   
+
+;;; Ensure that standard EFFECTIVE-SLOT-DEFINITIONs have a meaningful
+;;; type predicate, if we can.
+(defmethod shared-initialize :after ((spec effective-slot-definition)
+				     slot-names
+				     &key 
+				     &allow-other-keys)
+  (declare (ignore slot-names))
+  (let* ((type (slot-definition-type spec)))
+    (setf (slot-value spec 'type-predicate)
+	  (or (and (typep type 'symbol)
+                   (not (eq type 't))
+		   (type-predicate type))
+              (handler-case
+                  (let* ((ctype (specifier-type type)))
+                    (unless (eq ctype *universal-type*)
+                      (generate-predicate-for-ctype ctype)))
+                (program-error ()
+                  (warn "Invalid type specifier ~s in slot definition for ~s in class ~s." type (slot-definition-name spec) (slot-definition-class spec))
+                  (lambda (v)
+                    (cerror "Allow the assignment or initialization."
+                            "Can't determine whether or not the value ~s should be used to initialize or assign to the slot ~&named ~s in an instance of ~s, because the slot is declared ~&to be of the invalid type ~s."
+                            v (slot-definition-name spec) (slot-definition-class spec) (slot-definition-type spec))
+                    ;; Suppress further checking, at least for things that use this effective slotd.
+                    ;; (It's hard to avoid this, and more trouble than it's worth to do better.)
+                    (setf (slot-value spec 'type-predicate) nil)
+                    t))
+                (parse-unknown-type (c)
+                   (declare (ignore c))
+                   #'(lambda (value)
+                       ;; If the type's now known, install a new predicate.
+                       (let* ((nowctype (specifier-type type)))
+                         (unless (typep nowctype 'unknown-ctype)
+                           (setf (slot-value spec 'type-predicate)
+                                 (generate-predicate-for-ctype nowctype)))
+                         (multiple-value-bind (win sure)
+                             (ctypep value nowctype)
+                           (or (not sure) win))))))))))
+
Index: /branches/new-random/level-1/l1-unicode.lisp
===================================================================
--- /branches/new-random/level-1/l1-unicode.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-unicode.lisp	(revision 13309)
@@ -0,0 +1,6402 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;;; Unicode translation stuff, mostly in support of I/O.
+
+(in-package "CCL")
+
+
+(defvar *character-encodings* (make-hash-table :test #'eq))
+
+(defun lookup-character-encoding (name)
+  (gethash name *character-encodings*))
+
+(defun get-character-encoding (name)
+  (or (lookup-character-encoding name)
+      (error "Unknown character encoding: ~s." name)))
+
+(defun (setf get-character-encoding) (new name)
+  (setf (gethash name *character-encodings*) new))
+
+(defun ensure-character-encoding (thing)
+  (if (typep thing 'character-encoding)
+    thing
+    (or (lookup-character-encoding thing)
+        (error "~s is not a character-encoding or the name of a character-encoding."
+               thing))))
+
+
+(defun character-encoded-in-single-octet (c)
+  (declare (ignore c))
+  1)
+
+(defstruct character-encoding
+  (name ())                             ;canonical name
+  (code-unit-size 8)                    ;in bits: 8, 16, 32
+  (native-endianness t)                 ;if nil, need to swap 16,32-bit units
+  (max-units-per-char 1)                ;usually 1-4
+
+  ;; Writes CHAR (or a replacement character if CHAR can't be encoded)
+  ;; to STREAM and returns the number of code-units written.
+  stream-encode-function                ;(CHAR WRITE-FUNCTION STREAM)
+  
+  ;; Returns a charcter (possibly #\Replacement_Character) or :EOF.
+  stream-decode-function                ;(1ST-UNIT NEXT-UNIT STREAM)
+
+  ;; Sets 1 or more units in a vector argument and returns a value 1
+  ;; greater than the index of the last octet written to the vector
+  vector-encode-function                ;(STRING VECTOR INDEX START END)
+  
+  ;; Returns a value 1 greater than the last octet index consumed from
+  ;; the vector argument.
+  vector-decode-function                ;(VECTOR INDEX NOCTETS STRING)
+  
+  ;; Sets one or more units in memory at the address denoted by
+  ;; the pointer and index arguments and returns (+ idx number of
+  ;; units written to memory), else returns NIL if any character
+  ;; can't be encoded.
+  memory-encode-function                ;(STRING POINTER INDEX START END)
+
+  
+  ;; Returns (as multiple values) the  string encoded in memory
+  ;; at the address denoted by the address and index args and the
+  ;; sum of the index arg and the number of octets consumed.
+  memory-decode-function                ;(POINTER NOCTETS INDEX STRING)
+  
+  ;; Returns the number of octets needed to encode STRING between START and END
+  octets-in-string-function              ;(STRING START END)
+
+  ;; Returns the number of (full) characters encoded in VECTOR, and
+  ;; the index the index of the first octet not used to encode
+  ;; them. (The second value may be less than END.
+  length-of-vector-encoding-function    ;(VECTOR START END) 
+
+  ;; Returns the number of (full) characters encoded in memory at (+ POINTER START)
+  ;; and the number of octets used to encode them.  (The second value may be less
+  ;; than NOCTETS.)
+  length-of-memory-encoding-function    ;(POINTER NOCTETS START)
+
+  ;; Code units less than this value map to themselves on input.
+  (decode-literal-code-unit-limit 0)
+
+  ;; Does a byte-order-mark determine the endianness of input ?
+  ;; Should we prepend a BOM to output ?
+  ;; If non-nil, the value should be the name of the an encoding
+  ;; that implements this encoding with swapped byte order.
+  (use-byte-order-mark nil)
+  ;; What alternate line-termination conventions can be encoded ?  (This basically
+  ;; means "can #\Line_Separator be encoded?", since :CR and :CRLF can always
+  ;; be encoded.)
+  (alternate-line-termination-conventions '(:cr :crlf))
+  ;; By what other MIME names is this encoding known ?
+  (aliases nil)
+  (documentation nil)
+  ;; What does a native byte-order-mark look like (as a sequence of octets)
+  ;; in this encoding ? (NIL if a BOM can't be encoded.)
+  (bom-encoding nil)
+  ;; How is #\NUL encoded, as a sequence of octets ?  (Typically, as a minimal-
+  ;; length sequenve of 0s, but there are exceptions.)
+  (nul-encoding #(0))
+  ;; Char-codes less than  this value map to themselves on output.
+  (encode-literal-char-code-limit 0)
+  (character-size-in-octets-function 'character-encoded-in-single-octet)
+  )
+
+(defconstant byte-order-mark #\u+feff)
+(defconstant byte-order-mark-char-code (char-code byte-order-mark))
+(defconstant swapped-byte-order-mark-char-code #xfffe)
+
+
+(defmethod default-character-encoding ((domain t))
+  (character-encoding-name (get-character-encoding nil)))
+
+(defun decode-character-encoded-vector (encoding vector start-index noctets string)
+  (setq encoding (ensure-character-encoding encoding))
+  (unless (= (the (unsigned-byte 8) (typecode vector))
+             target::subtag-u8-vector)
+    (report-bad-arg vector '(simple-array (unsigned-byte 8) (*))))
+  (unless (= (the (unsigned-byte 8) (typecode string))
+             target::subtag-simple-base-string)
+    (report-bad-arg vector 'simple-string))
+  (let* ((len (length vector)))
+    (declare (type index len))
+    (unless (and (typep start-index 'fixnum)
+                 (>= (the fixnum start-index) 0)
+                 (< (the fixnum start-index) len))
+      (error "~s is an invalid start index for ~s" start-index vector))
+    (unless (and (typep noctets 'fixnum)
+                 (>= (the fixnum noctets) 0)
+                 (<= (+ (the fixnum start-index) (the fixnum noctets)) len))
+      (error "~S is an invalid octet count for ~s at ~s" noctets vector start-index))
+    (funcall (character-encoding-vector-decode-function encoding)
+             vector
+             start-index
+             noctets
+             string)))
+
+
+(defmethod print-object ((ce character-encoding) stream)
+  (print-unreadable-object (ce stream :type t :identity t)
+    (format stream "~a" (character-encoding-name ce))))
+
+;;; N.B.  (ccl:nfunction <name> (lambda (...) ...)) is just  like
+;;;       (cl:function (lambda (...) ...)), except that the resulting
+;;; function will have "name" <name> (this is often helpful when debugging.)
+
+(defmacro define-character-encoding (name doc &rest args &key &allow-other-keys)
+  (setq name (intern (string name) "KEYWORD"))
+  (let* ((encoding (gensym))
+         (alias (gensym)))
+  `(let* ((,encoding (make-character-encoding :name ,name :documentation ,doc ,@args)))
+    (setf (get-character-encoding ,name) ,encoding)
+    (dolist (,alias (character-encoding-aliases ,encoding))
+      (setf (get-character-encoding ,alias) ,encoding))
+    ',name)))
+
+(defun encoding-name (encoding)
+  (character-encoding-name (or encoding (get-character-encoding nil))))
+
+;;; ISO-8859-1 is trivial, though of course it can't really encode characters
+;;; whose CHAR-CODE is >= 256
+
+(defun 8-bit-fixed-width-octets-in-string (string start end)
+  (declare (ignore string))
+  (if (>= end start)
+    (- end start)
+    0))
+
+(defun 8-bit-fixed-width-length-of-vector-encoding (vector start end)
+  (declare (ignore vector))
+  (if (>= end start)
+    (values (- end start) end)
+    (values 0 start)))
+
+(defun 8-bit-fixed-width-length-of-memory-encoding (pointer noctets start)
+  (declare (ignore pointer start))
+  (values noctets noctets))
+
+(define-character-encoding :iso-8859-1
+  "An 8-bit, fixed-width character encoding in which all character
+codes map to their Unicode equivalents. Intended to support most
+characters used in most Western European languages."
+
+  ;; The NIL alias is used internally to mean that ISO-8859-1 is
+  ;; the "null" 8-bit encoding
+  :aliases '(nil :iso_8859-1 :latin1 :l1 :ibm819 :cp819 :csISOLatin1)
+  :stream-encode-function
+  (nfunction
+   iso-8859-1-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char)))
+       (declare (type (mod #x110000) code))
+       (if (>= code 256)
+         (setq code (char-code #\Sub)))
+       (funcall write-function stream code)
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-1-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (code-char 1st-unit)))
+  :vector-encode-function
+  (nfunction
+   iso-8859-1-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (if (>= code 256)
+           (setq code (char-code #\Sub)))
+         (progn
+           (setf (aref vector idx) code)
+           (incf idx))))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-1-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (setf (schar string i) (code-char (the (unsigned-byte 8)
+                                             (aref vector index)))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-1-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (if (>= code 256)
+           (setq code (char-code #\Sub)))
+         (setf (%get-unsigned-byte pointer idx) code)
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-1-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+         (setf (schar string i) (code-char (the (unsigned-byte 8)
+                                             (%get-unsigned-byte pointer index)))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit 256
+  :encode-literal-char-code-limit 256
+  )
+
+(define-character-encoding :us-ascii
+  "A 7-bit, fixed-width character encoding in which all character
+codes map to their Unicode equivalents."
+
+  :aliases '(:csASCII :cp637 :IBM637 :us :ISO646-US :ascii :ISO-ir-6)
+  :stream-encode-function
+  (nfunction
+   ascii-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char)))
+       (declare (type (mod #x110000) code))
+       (when (>= code 128)
+         (setq code (char-code #\Sub)))
+       (funcall write-function stream code)
+       1)))
+  :stream-decode-function
+  (nfunction
+   ascii-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit 128)
+       (code-char 1st-unit)
+       #\Replacement_Character)))
+  :vector-encode-function
+  (nfunction
+   ascii-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (if (>= code 128)
+           (setq code (char-code #\Sub)))
+         (setf (aref vector idx) code)
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   ascii-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((code (aref vector index)))
+         (declare (type (unsigned-byte 8) code))
+         (when (>= code 128)
+           (setq code (char-code #\Sub)))
+         (setf (schar string i) (code-char code))))))
+  :memory-encode-function
+  (nfunction
+   ascii-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (if (>= code 128)
+           (setq code (char-code #\Sub)))
+         (setf (%get-unsigned-byte pointer idx) code)
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   ascii-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((code (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) code))
+         (if (>= code 128)
+           (setf (schar string i) #\sub)
+           (setf (schar string i) (code-char code)))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit 128
+  :encode-literal-char-code-limit 128
+  )
+
+
+
+;;; Other 1-byte, fixed-width encodings.  Typically, codes in the range
+;;; #x00-#x9f maps straight through, while codes #xa0-#xff select arbitrary
+;;; Unicode characters that are commonly used in some locale.  (Sometimes
+;;; the break is at #x80 instead of #xa0).
+
+(defstatic *iso-8859-2-to-unicode*
+  #(
+  ;; #xa0
+  #\u+00a0 #\u+0104 #\u+02d8 #\u+0141 #\u+00a4 #\u+013d #\u+015a #\u+00a7
+  #\u+00a8 #\u+0160 #\u+015e #\u+0164 #\u+0179 #\u+00ad #\u+017d #\u+017b
+  ;; #xb0 
+  #\u+00b0 #\u+0105 #\u+02db #\u+0142 #\u+00b4 #\u+013e #\u+015b #\u+02c7
+  #\u+00b8 #\u+0161 #\u+015f #\u+0165 #\u+017a #\u+02dd #\u+017e #\u+017c
+  ;; #xc0 
+  #\u+0154 #\u+00c1 #\u+00c2 #\u+0102 #\u+00c4 #\u+0139 #\u+0106 #\u+00c7
+  #\u+010c #\u+00c9 #\u+0118 #\u+00cb #\u+011a #\u+00cd #\u+00ce #\u+010e
+  ;; #xd0 
+  #\u+0110 #\u+0143 #\u+0147 #\u+00d3 #\u+00d4 #\u+0150 #\u+00d6 #\u+00d7
+  #\u+0158 #\u+016e #\u+00da #\u+0170 #\u+00dc #\u+00dd #\u+0162 #\u+00df
+  ;; #xe0 
+  #\u+0155 #\u+00e1 #\u+00e2 #\u+0103 #\u+00e4 #\u+013a #\u+0107 #\u+00e7
+  #\u+010d #\u+00e9 #\u+0119 #\u+00eb #\u+011b #\u+00ed #\u+00ee #\u+010f
+  ;; #xf0 
+  #\u+0111 #\u+0144 #\u+0148 #\u+00f3 #\u+00f4 #\u+0151 #\u+00f6 #\u+00f7
+  #\u+0159 #\u+016f #\u+00fa #\u+0171 #\u+00fc #\u+00fd #\u+0163 #\u+02d9
+))
+
+(defstatic *unicode-00a0-0180-to-iso-8859-2*
+  #(
+    #xa0 nil nil nil #xa4 nil nil #xa7 ; #xa0-#xa7 
+    #xa8 nil nil nil nil #xad nil nil ; #xa8-#xaf 
+    #xb0 nil nil nil #xb4 nil nil nil ; #xb0-#xb7 
+    #xb8 nil nil nil nil nil nil nil  ; #xb8-#xbf 
+    nil #xc1 #xc2 nil #xc4 nil nil #xc7 ; #xc0-#xc7 
+    nil #xc9 nil #xcb nil #xcd #xce nil ; #xc8-#xcf 
+    nil nil nil #xd3 #xd4 nil #xd6 #xd7 ; #xd0-#xd7 
+    nil nil #xda nil #xdc #xdd nil #xdf ; #xd8-#xdf 
+    nil #xe1 #xe2 nil #xe4 nil nil #xe7 ; #xe0-#xe7 
+    nil #xe9 nil #xeb nil #xed #xee nil ; #xe8-#xef 
+    nil nil nil #xf3 #xf4 nil #xf6 #xf7 ; #xf0-#xf7 
+    nil nil #xfa nil #xfc #xfd nil nil ; #xf8-#xff 
+    ;; #x0100 
+    nil nil #xc3 #xe3 #xa1 #xb1 #xc6 #xe6 ; #x100-#x107 
+    nil nil nil nil #xc8 #xe8 #xcf #xef ; #x108-#x10f 
+    #xd0 #xf0 nil nil nil nil nil nil ; #x110-#x117 
+    #xca #xea #xcc #xec nil nil nil nil ; #x118-#x11f 
+    nil nil nil nil nil nil nil nil     ; #x120-#x127 
+    nil nil nil nil nil nil nil nil     ; #x128-#x12f 
+    nil nil nil nil nil nil nil nil     ; #x130-#x137 
+    nil #xc5 #xe5 nil nil #xa5 #xb5 nil ; #x138-#x13f 
+    nil #xa3 #xb3 #xd1 #xf1 nil nil #xd2 ; #x140-#x147 
+    #xf2 nil nil nil nil nil nil nil  ; #x148-#x14f 
+    #xd5 #xf5 nil nil #xc0 #xe0 nil nil ; #x150-#x157 
+    #xd8 #xf8 #xa6 #xb6 nil nil #xaa #xba ; #x158-#x15f 
+    #xa9 #xb9 #xde #xfe #xab #xbb nil nil ; #x160-#x167 
+    nil nil nil nil nil nil #xd9 #xf9 ; #x168-#x16f 
+    #xdb #xfb nil nil nil nil nil nil ; #x170-#x177 
+    nil #xac #xbc #xaf #xbf #xae #xbe nil ; #x178-#x17f 
+    ))
+
+(defstatic *unicode-00c0-00e0-to-iso-8859-2*
+  #(
+    nil nil nil nil nil nil nil #xb7  ; #xc0-#xc7 
+    nil nil nil nil nil nil nil nil     ; #xc8-#xcf 
+    nil nil nil nil nil nil nil nil     ; #xd0-#xd7 
+    #xa2 #xff nil #xb2 nil #xbd nil nil ; #xd8-#xdf
+    ))
+
+(define-character-encoding :iso-8859-2
+  "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in most
+languages used in Central/Eastern Europe."
+  :aliases '(:iso_8859-2 :latin-2 :l2 :csISOLatin2)
+  :stream-encode-function
+  (nfunction
+   iso-8859-2-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-00a0-0180-to-iso-8859-2*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x2c0) (< code #x2e0))
+                       (svref *unicode-00c0-00e0-to-iso-8859-2*
+                                      (the fixnum (- code #x2c0)))))))
+                      
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-2-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-2-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-2-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                          ((< code #x180)
+                           (svref *unicode-00a0-0180-to-iso-8859-2*
+                                  (the fixnum (- code #xa0))))
+                          ((and (>= code #x2c0) (< code #x2e0))
+                           (svref *unicode-00c0-00e0-to-iso-8859-2*
+                                  (the fixnum (- code #x2c0)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-2-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+           (declare (type (unsigned-byte 8) 1st-unit))
+           (setf (schar string i)
+            (if (< 1st-unit #xa0)
+              (code-char 1st-unit)
+              (svref *iso-8859-2-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-2-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #x180)
+                         (svref *unicode-00a0-0180-to-iso-8859-2*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x2c0) (< code #x2e0))
+                         (svref *unicode-00c0-00e0-to-iso-8859-2*
+                                (the fixnum (- code #x2c0)))))))
+       (declare (type (mod #x110000) code))
+       (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+       (1+ idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-2-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-2-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0
+  )
+
+(defstatic *iso-8859-3-to-unicode*
+  #(
+    ;; #xa0 
+    #\u+00a0 #\u+0126 #\u+02d8 #\u+00a3 #\u+00a4 #\u+fffd #\u+0124 #\u+00a7
+    #\u+00a8 #\u+0130 #\u+015e #\u+011e #\u+0134 #\u+00ad #\u+fffd #\u+017b
+    ;; #xb0 
+    #\u+00b0 #\u+0127 #\u+00b2 #\u+00b3 #\u+00b4 #\u+00b5 #\u+0125 #\u+00b7
+    #\u+00b8 #\u+0131 #\u+015f #\u+011f #\u+0135 #\u+00bd #\u+fffd #\u+017c
+    ;; #xc0 
+    #\u+00c0 #\u+00c1 #\u+00c2 #\u+fffd #\u+00c4 #\u+010a #\u+0108 #\u+00c7
+    #\u+00c8 #\u+00c9 #\u+00ca #\u+00cb #\u+00cc #\u+00cd #\u+00ce #\u+00cf
+    ;; #xd0 
+    #\u+fffd #\u+00d1 #\u+00d2 #\u+00d3 #\u+00d4 #\u+0120 #\u+00d6 #\u+00d7
+    #\u+011c #\u+00d9 #\u+00da #\u+00db #\u+00dc #\u+016c #\u+015c #\u+00df
+    ;; #xe0 
+    #\u+00e0 #\u+00e1 #\u+00e2 #\u+fffd #\u+00e4 #\u+010b #\u+0109 #\u+00e7
+    #\u+00e8 #\u+00e9 #\u+00ea #\u+00eb #\u+00ec #\u+00ed #\u+00ee #\u+00ef
+    ;; #xf0 
+    #\u+fffd #\u+00f1 #\u+00f2 #\u+00f3 #\u+00f4 #\u+0121 #\u+00f6 #\u+00f7
+    #\u+011d #\u+00f9 #\u+00fa #\u+00fb #\u+00fc #\u+016d #\u+015d #\u+02d9
+    ))
+
+(defstatic *unicode-a0-100-to-iso-8859-3*
+  #(
+    #xa0 nil nil #xa3 #xa4 nil nil #xa7 ; #xa0-#xa7 
+    #xa8 nil nil nil nil #xad nil nil   ; #xa8-#xaf 
+    #xb0 nil #xb2 #xb3 #xb4 #xb5 nil #xb7 ; #xb0-#xb7 
+    #xb8 nil nil nil nil #xbd nil nil   ; #xb8-#xbf 
+    #xc0 #xc1 #xc2 nil #xc4 nil nil #xc7 ; #xc0-#xc7 
+    #xc8 #xc9 #xca #xcb #xcc #xcd #xce #xcf ; #xc8-#xcf 
+    nil #xd1 #xd2 #xd3 #xd4 nil #xd6 #xd7 ; #xd0-#xd7 
+    nil #xd9 #xda #xdb #xdc nil nil #xdf ; #xd8-#xdf 
+    #xe0 #xe1 #xe2 nil #xe4 nil nil #xe7 ; #xe0-#xe7 
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #xe8-#xef 
+    nil #xf1 #xf2 #xf3 #xf4 nil #xf6 #xf7 ; #xf0-#xf7 
+    nil #xf9 #xfa #xfb #xfc nil nil nil ; #xf8-#xff 
+    ))
+
+(defstatic *unicode-108-180-to-iso-8859-3*
+  #(
+    #xc6 #xe6 #xc5 #xe5 #x00 #x00 #x00 #x00 ; #x108-#x10f 
+    nil nil nil nil nil nil nil nil     ; #x110-#x117 
+    nil nil nil nil #xd8 #xf8 #xab #xbb ; #x118-#x11f 
+    #xd5 #xf5 nil nil #xa6 #xb6 #xa1 #xb1 ; #x120-#x127 
+    nil nil nil nil nil nil nil nil     ; #x128-#x12f 
+    #xa9 #xb9 nil nil #xac #xbc nil nil ; #x130-#x137 
+    nil nil nil nil nil nil nil nil     ; #x138-#x13f 
+    nil nil nil nil nil nil nil nil     ; #x140-#x147 
+    nil nil nil nil nil nil nil nil     ; #x148-#x14f 
+    nil nil nil nil nil nil nil nil     ; #x150-#x157 
+    nil nil nil nil #xde #xfe #xaa #xba ; #x158-#x15f 
+    nil nil nil nil nil nil nil nil     ; #x160-#x167 
+    nil nil nil nil #xdd #xfd nil nil   ; #x168-#x16f 
+    nil nil nil nil nil nil nil nil     ; #x170-#x177 
+    nil nil nil #xaf #xbf nil nil nil   ; #x178-#x17f 
+    ))
+
+(defstatic *unicode-2d8-2e0-to-iso-8859-3*
+  #(
+    #xa2 #xff nil nil nil nil nil nil   ; #x2d8-#x2df 
+    ))
+
+
+    
+(define-character-encoding :iso-8859-3
+  "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in most
+languages used in Southern Europe."
+
+  :aliases '(:iso_8859-3 :latin3 :l3 :csisolatin3)
+  :stream-encode-function
+  (nfunction
+   iso-8859-3-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x100)
+                       (svref *unicode-a0-100-to-iso-8859-3*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x108) (< code #x180))
+                       (svref *unicode-108-180-to-iso-8859-3*
+                              (the fixnum (- code #x108))))
+                      ((and (>= code #x2d8) (< code #x2e0))
+                       (svref *unicode-2d8-2e0-to-iso-8859-3*
+                              (the fixnum (- code #x2d8)))))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-3-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-3-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-3-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #x100)
+                         (svref *unicode-a0-100-to-iso-8859-3*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x108) (< code #x180))
+                         (svref *unicode-108-180-to-iso-8859-3*
+                                (the fixnum (- code #x108))))
+                        ((and (>= code #x2d8) (< code #x2e0))
+                         (svref *unicode-2d8-2e0-to-iso-8859-3*
+                 
+               (the fixnum (- code #x2d8)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-3-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+         (let* ((1st-unit (aref vector index)))
+           (declare (type (unsigned-byte 8) 1st-unit))
+           (setf (schar string i)
+                 (if (< 1st-unit #xa0)
+                   (code-char 1st-unit)
+                   (svref *iso-8859-3-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-3-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #x100)
+                         (svref *unicode-a0-100-to-iso-8859-3*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x108) (< code #x180))
+                         (svref *unicode-108-180-to-iso-8859-3*
+                                (the fixnum (- code #x108))))
+                        ((and (>= code #x2d8) (< code #x2e0))
+                         (svref *unicode-2d8-2e0-to-iso-8859-3*
+                                (the fixnum (- code #x2d8)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-3-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-3-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+
+(defstatic *iso-8859-4-to-unicode*
+  #(
+    ;; #xa0 
+    #\u+00a0 #\u+0104 #\u+0138 #\u+0156 #\u+00a4 #\u+0128 #\u+013b #\u+00a7
+    #\u+00a8 #\u+0160 #\u+0112 #\u+0122 #\u+0166 #\u+00ad #\u+017d #\u+00af
+    ;; #xb0 
+    #\u+00b0 #\u+0105 #\u+02db #\u+0157 #\u+00b4 #\u+0129 #\u+013c #\u+02c7
+    #\u+00b8 #\u+0161 #\u+0113 #\u+0123 #\u+0167 #\u+014a #\u+017e #\u+014b
+    ;; #xc0 
+    #\u+0100 #\u+00c1 #\u+00c2 #\u+00c3 #\u+00c4 #\u+00c5 #\u+00c6 #\u+012e
+    #\u+010c #\u+00c9 #\u+0118 #\u+00cb #\u+0116 #\u+00cd #\u+00ce #\u+012a
+    ;; #xd0 
+    #\u+0110 #\u+0145 #\u+014c #\u+0136 #\u+00d4 #\u+00d5 #\u+00d6 #\u+00d7
+    #\u+00d8 #\u+0172 #\u+00da #\u+00db #\u+00dc #\u+0168 #\u+016a #\u+00df
+    ;; #xe0 
+    #\u+0101 #\u+00e1 #\u+00e2 #\u+00e3 #\u+00e4 #\u+00e5 #\u+00e6 #\u+012f
+    #\u+010d #\u+00e9 #\u+0119 #\u+00eb #\u+0117 #\u+00ed #\u+00ee #\u+012b
+    ;; #xf0 
+    #\u+0111 #\u+0146 #\u+014d #\u+0137 #\u+00f4 #\u+00f5 #\u+00f6 #\u+00f7
+    #\u+00f8 #\u+0173 #\u+00fa #\u+00fb #\u+00fc #\u+0169 #\u+016b #\u+02d9
+    ))
+
+
+(defstatic *unicode-a0-180-to-iso-8859-4*
+  #(
+    #xa0 nil nil nil #xa4 nil nil #xa7  ; #xa0-#xa7 
+    #xa8 nil nil nil nil #xad nil #xaf  ; #xa8-#xaf 
+    #xb0 nil nil nil #xb4 nil nil nil   ; #xb0-#xb7 
+    #xb8 nil nil nil nil nil nil nil    ; #xb8-#xbf 
+    nil #xc1 #xc2 #xc3 #xc4 #xc5 #xc6 nil ; #xc0-#xc7 
+    nil #xc9 nil #xcb nil #xcd #xce nil ; #xc8-#xcf 
+    nil nil nil nil #xd4 #xd5 #xd6 #xd7 ; #xd0-#xd7 
+    #xd8 nil #xda #xdb #xdc nil nil #xdf ; #xd8-#xdf 
+    nil #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 nil ; #xe0-#xe7 
+    nil #xe9 nil #xeb nil #xed #xee nil ; #xe8-#xef 
+    nil nil nil nil #xf4 #xf5 #xf6 #xf7 ; #xf0-#xf7 
+    #xf8 nil #xfa #xfb #xfc nil nil nil ; #xf8-#xff 
+    #xc0 #xe0 nil nil #xa1 #xb1 nil nil ; #x100-#x107 
+    nil nil nil nil #xc8 #xe8 nil nil   ; #x108-#x10f 
+    #xd0 #xf0 #xaa #xba nil nil #xcc #xec ; #x110-#x117 
+    #xca #xea nil nil nil nil nil nil   ; #x118-#x11f 
+    nil nil #xab #xbb nil nil nil nil   ; #x120-#x127 
+    #xa5 #xb5 #xcf #xef nil nil #xc7 #xe7 ; #x128-#x12f 
+    nil nil nil nil nil nil #xd3 #xf3   ; #x130-#x137 
+    #xa2 nil nil #xa6 #xb6 nil nil nil  ; #x138-#x13f 
+    nil nil nil nil nil #xd1 #xf1 nil   ; #x140-#x147 
+    nil nil #xbd #xbf #xd2 #xf2 nil nil ; #x148-#x14f 
+    nil nil nil nil nil nil #xa3 #xb3   ; #x150-#x157 
+    nil nil nil nil nil nil nil nil     ; #x158-#x15f 
+    #xa9 #xb9 nil nil nil nil #xac #xbc ; #x160-#x167 
+    #xdd #xfd #xde #xfe nil nil nil nil ; #x168-#x16f 
+    nil nil #xd9 #xf9 nil nil nil nil   ; #x170-#x177 
+    nil nil nil nil nil #xae #xbe nil   ; #x178-#x17f 
+    ))
+
+(defstatic *unicode-2c0-2e0-to-iso-8859-4*
+  #(
+    nil nil nil nil nil nil nil #xb7    ; #x2c0-#x2c7
+    nil nil nil nil nil nil nil nil     ; #x2c8-#x2cf
+    nil nil nil nil nil nil nil nil     ; #x2d0-#x2d7
+    nil #xff nil #xb2 nil nil nil nil   ; #x2d8-#x2df
+    ))
+
+
+
+(define-character-encoding :iso-8859-4
+  "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in most
+languages used in Northern Europe."
+
+  :aliases '(:iso_8859-4 :latin4 :l4 :csisolatin4)
+  :stream-encode-function
+  (nfunction
+   iso-8859-4-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-4*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x2d8) (< code #x2e0))
+                       (svref *unicode-2c0-2e0-to-iso-8859-4*
+                              (the fixnum (- code #x2c0)))))))
+                      
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-4-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-4-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-4-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #x180)
+                         (svref *unicode-a0-180-to-iso-8859-4*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x2d8) (< code #x2e0))
+                         (svref *unicode-2c0-2e0-to-iso-8859-4*
+                                (the fixnum (- code #x2c0)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-4-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-4-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-4-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #x180)
+                         (svref *unicode-a0-180-to-iso-8859-4*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x2d8) (< code #x2e0))
+                         (svref *unicode-2c0-2e0-to-iso-8859-4*
+                                (the fixnum (- code #x2c0)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-4-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-4-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *iso-8859-5-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+0401 #\u+0402 #\u+0403 #\u+0404 #\u+0405 #\u+0406 #\u+0407
+    #\u+0408 #\u+0409 #\u+040a #\u+040b #\u+040c #\u+00ad #\u+040e #\u+040f
+    ;; #xb0
+    #\u+0410 #\u+0411 #\u+0412 #\u+0413 #\u+0414 #\u+0415 #\u+0416 #\u+0417
+    #\u+0418 #\u+0419 #\u+041a #\u+041b #\u+041c #\u+041d #\u+041e #\u+041f
+    ;; #xc0
+    #\u+0420 #\u+0421 #\u+0422 #\u+0423 #\u+0424 #\u+0425 #\u+0426 #\u+0427
+    #\u+0428 #\u+0429 #\u+042a #\u+042b #\u+042c #\u+042d #\u+042e #\u+042f
+    ;; #xd0
+    #\u+0430 #\u+0431 #\u+0432 #\u+0433 #\u+0434 #\u+0435 #\u+0436 #\u+0437
+    #\u+0438 #\u+0439 #\u+043a #\u+043b #\u+043c #\u+043d #\u+043e #\u+043f
+    ;; #xe0
+    #\u+0440 #\u+0441 #\u+0442 #\u+0443 #\u+0444 #\u+0445 #\u+0446 #\u+0447
+    #\u+0448 #\u+0449 #\u+044a #\u+044b #\u+044c #\u+044d #\u+044e #\u+044f
+    ;; #xf0
+    #\u+2116 #\u+0451 #\u+0452 #\u+0453 #\u+0454 #\u+0455 #\u+0456 #\u+0457
+    #\u+0458 #\u+0459 #\u+045a #\u+045b #\u+045c #\u+00a7 #\u+045e #\u+045f
+    ))
+
+
+(defstatic *unicode-a0-b0-to-iso-8859-5*
+  #(
+    #xa0 nil nil nil nil nil nil #xfd   ; #xa0-#xa7
+    nil nil nil nil nil #xad nil nil    ; #xa8-#xaf
+    ))
+
+(defstatic *unicode-400-460-to-iso-8859-5*
+  #(
+    nil #xa1 #xa2 #xa3 #xa4 #xa5 #xa6 #xa7 ; #x400-#x407
+    #xa8 #xa9 #xaa #xab #xac nil #xae #xaf ; #x408-#x40f
+    #xb0 #xb1 #xb2 #xb3 #xb4 #xb5 #xb6 #xb7 ; #x410-#x417
+    #xb8 #xb9 #xba #xbb #xbc #xbd #xbe #xbf ; #x418-#x41f
+    #xc0 #xc1 #xc2 #xc3 #xc4 #xc5 #xc6 #xc7 ; #x420-#x427
+    #xc8 #xc9 #xca #xcb #xcc #xcd #xce #xcf ; #x428-#x42f
+    #xd0 #xd1 #xd2 #xd3 #xd4 #xd5 #xd6 #xd7 ; #x430-#x437
+    #xd8 #xd9 #xda #xdb #xdc #xdd #xde #xdf ; #x438-#x43f
+    #xe0 #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 #xe7 ; #x440-#x447
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #x448-#x44f
+    nil #xf1 #xf2 #xf3 #xf4 #xf5 #xf6 #xf7 ; #x450-#x457
+    #xf8 #xf9 #xfa #xfb #xfc nil #xfe #xff ; #x458-#x45f
+    ))
+
+
+(define-character-encoding :iso-8859-5
+  "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in the
+Cyrillic alphabet."
+
+  :aliases '(:iso_8859-5 :cyrillic :csISOLatinCyrillic :iso-ir-144)
+  :stream-encode-function
+  (nfunction
+   iso-8859-5-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #xb0)
+                       (svref *unicode-a0-b0-to-iso-8859-5*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x400) (< code #x460))
+                       (svref *unicode-400-460-to-iso-8859-5*
+                              (the fixnum (- code #x400)))))))
+                      
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-5-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-5-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-5-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #xb0)
+                         (svref *unicode-a0-b0-to-iso-8859-5*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x400) (< code #x460))
+                         (svref *unicode-400-460-to-iso-8859-5*
+                                (the fixnum (- code #x400)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-5-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-5-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-5-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #xb0)
+                         (svref *unicode-a0-b0-to-iso-8859-5*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x400) (< code #x460))
+                         (svref *unicode-400-460-to-iso-8859-5*
+                                (the fixnum (- code #x400)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-5-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-5-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0
+  )
+
+(defstatic *iso-8859-6-to-unicode*
+  #(
+    ;; #xa0 
+    #\u+00a0 #\u+fffd #\u+fffd #\u+fffd #\u+00a4 #\u+fffd #\u+fffd #\u+fffd
+    #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+060c #\u+00ad #\u+fffd #\u+fffd
+    ;; #xb0 
+    #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd
+    #\u+fffd #\u+fffd #\u+fffd #\u+061b #\u+fffd #\u+fffd #\u+fffd #\u+061f
+    ;; #xc0 
+    #\u+fffd #\u+0621 #\u+0622 #\u+0623 #\u+0624 #\u+0625 #\u+0626 #\u+0627
+    #\u+0628 #\u+0629 #\u+062a #\u+062b #\u+062c #\u+062d #\u+062e #\u+062f
+    ;; #xd0 
+    #\u+0630 #\u+0631 #\u+0632 #\u+0633 #\u+0634 #\u+0635 #\u+0636 #\u+0637
+    #\u+0638 #\u+0639 #\u+063a #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd
+    ;; #xe0 
+    #\u+0640 #\u+0641 #\u+0642 #\u+0643 #\u+0644 #\u+0645 #\u+0646 #\u+0647
+    #\u+0648 #\u+0649 #\u+064a #\u+064b #\u+064c #\u+064d #\u+064e #\u+064f
+    ;; #xf0 
+    #\u+0650 #\u+0651 #\u+0652 #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd
+    #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd
+    ))
+
+(defstatic *unicode-a0-b0-to-iso-8859-6*
+  #(
+    0xa0 nil nil nil 0xa4 nil nil nil   ; #xa0-#xa7
+    nil nil nil nil nil #xad nil nil    ; #xa8-#xaf
+    ))
+
+
+(defstatic *unicode-608-658-to-iso-8859-6*
+  #(
+    nil nil nil nil #xac nil nil nil    ; #x608-#x60f
+    nil nil nil nil nil nil nil nil     ; #x610-#x617
+    nil nil nil #xbb nil nil nil #xbf   ; #x618-#x61f
+    nil #xc1 #xc2 #xc3 #xc4 #xc5 #xc6 #xc7 ; #x620-#x627
+    #xc8 #xc9 #xca #xcb #xcc #xcd #xce #xcf ; #x628-#x62f
+    #xd0 #xd1 #xd2 #xd3 #xd4 #xd5 #xd6 #xd7 ; #x630-#x637
+    #xd8 #xd9 #xda nil nil nil nil nil  ; #x638-#x63f
+    #xe0 #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 #xe7 ; #x640-#x647
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #x648-#x64f
+    #xf0 #xf1 #xf2 nil nil nil nil nil  ; #x650-#x657
+    ))
+
+(define-character-encoding :iso-8859-6
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in the
+Arabic alphabet."
+
+  :aliases '(:iso_8859-6 :arabic :csISOLatinArabic :iso-ir-127)
+  :stream-encode-function
+  (nfunction
+   iso-8859-6-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #xb0)
+                       (svref *unicode-a0-b0-to-iso-8859-6*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x608) (< code #x658))
+                       (svref *unicode-608-658-to-iso-8859-6*
+                              (the fixnum (- code #x608)))))))
+                      
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-6-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-6-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-6-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #xb0)
+                         (svref *unicode-a0-b0-to-iso-8859-6*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x608) (< code #x658))
+                         (svref *unicode-608-658-to-iso-8859-6*
+                                (the fixnum (- code #x608)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-6-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-6-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-6-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                        ((< code #xb0)
+                         (svref *unicode-a0-b0-to-iso-8859-6*
+                                (the fixnum (- code #xa0))))
+                        ((and (>= code #x608) (< code #x658))
+                         (svref *unicode-608-658-to-iso-8859-6*
+                                (the fixnum (- code #x608)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-6-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-6-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *iso-8859-7-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+2018 #\u+2019 #\u+00a3 #\u+20ac #\u+20af #\u+00a6 #\u+00a7
+    #\u+00a8 #\u+00a9 #\u+037a #\u+00ab #\u+00ac #\u+00ad #\u+fffd #\u+2015
+    ;; #xb0
+    #\u+00b0 #\u+00b1 #\u+00b2 #\u+00b3 #\u+0384 #\u+0385 #\u+0386 #\u+00b7
+    #\u+0388 #\u+0389 #\u+038a #\u+00bb #\u+038c #\u+00bd #\u+038e #\u+038f
+    ;; #xc0
+    #\u+0390 #\u+0391 #\u+0392 #\u+0393 #\u+0394 #\u+0395 #\u+0396 #\u+0397
+    #\u+0398 #\u+0399 #\u+039a #\u+039b #\u+039c #\u+039d #\u+039e #\u+039f
+    ;; #xd0
+    #\u+03a0 #\u+03a1 #\u+fffd #\u+03a3 #\u+03a4 #\u+03a5 #\u+03a6 #\u+03a7
+    #\u+03a8 #\u+03a9 #\u+03aa #\u+03ab #\u+03ac #\u+03ad #\u+03ae #\u+03af
+    ;; #xe0
+    #\u+03b0 #\u+03b1 #\u+03b2 #\u+03b3 #\u+03b4 #\u+03b5 #\u+03b6 #\u+03b7
+    #\u+03b8 #\u+03b9 #\u+03ba #\u+03bb #\u+03bc #\u+03bd #\u+03be #\u+03bf
+    ;; #xf0
+    #\u+03c0 #\u+03c1 #\u+03c2 #\u+03c3 #\u+03c4 #\u+03c5 #\u+03c6 #\u+03c7
+    #\u+03c8 #\u+03c9 #\u+03ca #\u+03cb #\u+03cc #\u+03cd #\u+03ce #\u+fffd
+    ))
+
+(defstatic *unicode-a0-c0-to-iso-8859-7*
+  #(
+    #xa0 nil nil #xa3 nil nil #xa6 #xa7 ; #xa0-#xa7
+    #xa8 #xa9 nil #xab #xac #xad nil nil ; #xa8-#xaf
+    #xb0 #xb1 #xb2 #xb3 nil nil nil #xb7 ; #xb0-#xb7
+    nil nil nil #xbb nil #xbd nil nil   ; #xb8-#xbf
+    ))
+
+(defstatic *unicode-378-3d0-to-iso-8859-7*
+  #(
+    nil nil #xaa nil nil nil nil nil    ; #x378-#x37f 
+    nil nil nil nil #xb4 #xb5 #xb6 nil  ; #x380-#x387 
+    #xb8 #xb9 #xba nil #xbc nil #xbe #xbf ; #x388-#x38f 
+    #xc0 #xc1 #xc2 #xc3 #xc4 #xc5 #xc6 #xc7 ; #x390-#x397 
+    #xc8 #xc9 #xca #xcb #xcc #xcd #xce #xcf ; #x398-#x39f 
+    #xd0 #xd1 nil #xd3 #xd4 #xd5 #xd6 #xd7 ; #x3a0-#x3a7 
+    #xd8 #xd9 #xda #xdb #xdc #xdd #xde #xdf ; #x3a8-#x3af 
+    #xe0 #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 #xe7 ; #x3b0-#x3b7 
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #x3b8-#x3bf 
+    #xf0 #xf1 #xf2 #xf3 #xf4 #xf5 #xf6 #xf7 ; #x3c0-#x3c7 
+    #xf8 #xf9 #xfa #xfb #xfc #xfd #xfe nil ; #x3c8-#x3cf 
+    ))
+
+(defstatic *unicode-2010-2020-to-iso-8859-7*
+  #(
+    nil nil nil nil nil #xaf nil nil    ; #x2010-#x2017 
+    #xa1 #xa2 nil nil nil nil nil nil   ; #x2018-#x201f 
+    ))
+
+(defstatic *unicode-20ac-20b0-to-iso-8859-7*
+  #(
+    #xa4 nil nil #xa5
+    ))
+
+(define-character-encoding :iso-8859-7
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in the
+Greek alphabet."
+
+  :aliases '(:iso_8859-7 :greek  :greek8 :csISOLatinGreek :iso-ir-126 :ELOT_928 :ecma-118)
+  :stream-encode-function
+  (nfunction
+   iso-8859-7-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #xc0)
+                       (svref *unicode-a0-c0-to-iso-8859-7*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x378) (< code #x3d0))
+                       (svref *unicode-378-3d0-to-iso-8859-7*
+                              (the fixnum (- code #x378))))
+                      ((and (>= code #x2010) (< code #x2020))
+                       (svref *unicode-2010-2020-to-iso-8859-7*
+                              (the fixnum (- code #x2010))))
+                      ((and (>= code #x20ac) (< code #x20b0))
+                       (svref *unicode-20ac-20b0-to-iso-8859-7*
+                              (the fixnum (- code #x20ac)))))))
+              
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-7-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-7-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-7-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #xc0)
+                       (svref *unicode-a0-c0-to-iso-8859-7*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x378) (< code #x3d0))
+                       (svref *unicode-378-3d0-to-iso-8859-7*
+                              (the fixnum (- code #x378))))
+                      ((and (>= code #x2010) (< code #x2020))
+                       (svref *unicode-2010-2020-to-iso-8859-7*
+                              (the fixnum (- code #x2010))))
+                      ((and (>= code #x20ac) (< code #x20b0))
+                       (svref *unicode-20ac-20b0-to-iso-8859-7*
+                              (the fixnum (- code #x20ac)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-7-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-7-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-7-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #xc0)
+                       (svref *unicode-a0-c0-to-iso-8859-7*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x378) (< code #x3d0))
+                       (svref *unicode-378-3d0-to-iso-8859-7*
+                              (the fixnum (- code #x378))))
+                      ((and (>= code #x2010) (< code #x2020))
+                       (svref *unicode-2010-2020-to-iso-8859-7*
+                              (the fixnum (- code #x2010))))
+                      ((and (>= code #x20ac) (< code #x20b0))
+                       (svref *unicode-20ac-20b0-to-iso-8859-7*
+                              (the fixnum (- code #x20ac)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-7-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-7-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *iso-8859-8-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+fffd #\u+00a2 #\u+00a3 #\u+00a4 #\u+00a5 #\u+00a6 #\u+00a7
+    #\u+00a8 #\u+00a9 #\u+00d7 #\u+00ab #\u+00ac #\u+00ad #\u+00ae #\u+00af
+    ;; #xb0
+    #\u+00b0 #\u+00b1 #\u+00b2 #\u+00b3 #\u+00b4 #\u+00b5 #\u+00b6 #\u+00b7
+    #\u+00b8 #\u+00b9 #\u+00f7 #\u+00bb #\u+00bc #\u+00bd #\u+00be #\u+fffd
+    ;; #xc0
+    #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd
+    #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd
+    ;; #xd0
+    #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd
+    #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+fffd #\u+2017
+    ;; #xe0
+    #\u+05d0 #\u+05d1 #\u+05d2 #\u+05d3 #\u+05d4 #\u+05d5 #\u+05d6 #\u+05d7
+    #\u+05d8 #\u+05d9 #\u+05da #\u+05db #\u+05dc #\u+05dd #\u+05de #\u+05df
+    ;; #xf0
+    #\u+05e0 #\u+05e1 #\u+05e2 #\u+05e3 #\u+05e4 #\u+05e5 #\u+05e6 #\u+05e7
+    #\u+05e8 #\u+05e9 #\u+05ea #\u+fffd #\u+fffd #\u+200e #\u+200f #\u+fffd
+    ))
+
+(defstatic *unicode-a0-f8-to-iso-8859-8*
+  #(
+    #xa0 nil #xa2 #xa3 #xa4 #xa5 #xa6 #xa7 ; #xa0-#xa7 
+    #xa8 #xa9 nil #xab #xac #xad #xae #xaf ; #xa8-#xaf 
+    #xb0 #xb1 #xb2 #xb3 #xb4 #xb5 #xb6 #xb7 ; #xb0-#xb7 
+    #xb8 #xb9 nil #xbb #xbc #xbd #xbe nil ; #xb8-#xbf 
+    nil nil nil nil nil nil nil nil     ; #xc0-#xc7 
+    nil nil nil nil nil nil nil nil     ; #xc8-#xcf 
+    nil nil nil nil nil nil nil #xaa    ; #xd0-#xd7 
+    nil nil nil nil nil nil nil nil     ; #xd8-#xdf 
+    nil nil nil nil nil nil nil nil     ; #xe0-#xe7 
+    nil nil nil nil nil nil nil nil     ; #xe8-#xef 
+    nil nil nil nil nil nil nil #xba    ; #xf0-#xf7 
+    ))
+
+(defstatic *unicode-5d0-5f0-to-iso-8859-8*
+  #(
+    #xe0 #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 #xe7 ; #x5d0-#x5d7
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #x5d8-#x5df
+    #xf0 #xf1 #xf2 #xf3 #xf4 #xf5 #xf6 #xf7 ; #x5e0-#x5e7
+    #xf8 #xf9 #xfa nil nil nil nil nil  ; #x5e8-#x5ef
+    ))
+
+(defstatic *unicode-2008-2018-to-iso-8859-8*
+  #(
+    nil nil nil nil nil nil #xfd #xfe   ; #x2008-#x200f 
+    nil nil nil nil nil nil nil #xdf    ; #x2010-#x2017 
+    ))    
+
+(define-character-encoding :iso-8859-8
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in the
+Hebrew alphabet."
+
+  :aliases '(:iso_8859-8 :hebrew :csISOLatinHebrew :iso-ir-138)
+  :stream-encode-function
+  (nfunction
+   iso-8859-8-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #xf8)
+                       (svref *unicode-a0-f8-to-iso-8859-8*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x5d0) (< code #x5f0))
+                       (svref *unicode-5d0-5f0-to-iso-8859-8*
+                              (the fixnum (- code #x5d0))))
+                      ((and (>= code #x2008) (< code #x2018))
+                       (svref *unicode-2008-2018-to-iso-8859-8*
+                              (the fixnum (- code #x2008)))))))
+              
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-8-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-8-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-8-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #xf8)
+                       (svref *unicode-a0-f8-to-iso-8859-8*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x5d0) (< code #x5f0))
+                       (svref *unicode-5d0-5f0-to-iso-8859-8*
+                              (the fixnum (- code #x5d0))))
+                      ((and (>= code #x2008) (< code #x2018))
+                       (svref *unicode-2008-2018-to-iso-8859-8*
+                              (the fixnum (- code #x2008)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-8-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-8-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-8-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #xf8)
+                       (svref *unicode-a0-f8-to-iso-8859-8*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x5d0) (< code #x5f0))
+                       (svref *unicode-5d0-5f0-to-iso-8859-8*
+                              (the fixnum (- code #x5d0))))
+                      ((and (>= code #x2008) (< code #x2018))
+                       (svref *unicode-2008-2018-to-iso-8859-8*
+                              (the fixnum (- code #x2008)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-8-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-8-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *iso-8859-9-to-unicode*
+  #(
+    ;; #xd0
+    #\u+011e #\u+00d1 #\u+00d2 #\u+00d3 #\u+00d4 #\u+00d5 #\u+00d6 #\u+00d7
+    #\u+00d8 #\u+00d9 #\u+00da #\u+00db #\u+00dc #\u+0130 #\u+015e #\u+00df
+    ;; #xe0
+    #\u+00e0 #\u+00e1 #\u+00e2 #\u+00e3 #\u+00e4 #\u+00e5 #\u+00e6 #\u+00e7
+    #\u+00e8 #\u+00e9 #\u+00ea #\u+00eb #\u+00ec #\u+00ed #\u+00ee #\u+00ef
+    ;; #xf0
+    #\u+011f #\u+00f1 #\u+00f2 #\u+00f3 #\u+00f4 #\u+00f5 #\u+00f6 #\u+00f7
+    #\u+00f8 #\u+00f9 #\u+00fa #\u+00fb #\u+00fc #\u+0131 #\u+015f #\u+00ff
+    ))
+
+(defstatic *unicode-d0-100-to-iso-8859-9*
+  #(
+    nil #xd1 #xd2 #xd3 #xd4 #xd5 #xd6 #xd7 ; #xd0-#xd7
+    #xd8 #xd9 #xda #xdb #xdc nil nil #xdf ; #xd8-#xdf
+    #xe0 #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 #xe7 ; #xe0-#xe7
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #xe8-#xef
+    nil #xf1 #xf2 #xf3 #xf4 #xf5 #xf6 #xf7 ; #xf0-#xf7
+    #xf8 #xf9 #xfa #xfb #xfc nil nil #xff ; #xf8-#xff
+    ))
+
+(defstatic *unicode-118-160-to-iso-8859-9*
+  #(
+    nil nil nil nil nil nil #xd0 #xf0   ; #x118-#x11f 
+    nil nil nil nil nil nil nil nil     ; #x120-#x127 
+    nil nil nil nil nil nil nil nil     ; #x128-#x12f 
+    #xdd #xfd nil nil nil nil nil nil   ; #x130-#x137 
+    nil nil nil nil nil nil nil nil     ; #x138-#x13f 
+    nil nil nil nil nil nil nil nil     ; #x140-#x147 
+    nil nil nil nil nil nil nil nil     ; #x148-#x14f 
+    nil nil nil nil nil nil nil nil     ; #x150-#x157 
+    nil nil nil nil nil nil #xde #xfe   ; #x158-#x15f 
+    ))
+
+
+(define-character-encoding :iso-8859-9
+    "An 8-bit, fixed-width character encoding in which codes #x00-#xcf
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in the
+Turkish alphabet."
+
+  :aliases '(:iso_8859-9 :latin5 :csISOLatin5 :iso-ir-148)
+  :stream-encode-function
+  (nfunction
+   iso-8859-9-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xd0) code)
+                      ((< code #x100)
+                       (svref *unicode-d0-100-to-iso-8859-9*
+                              (the fixnum (- code #xd0))))
+                      ((and (>= code #x118) (< code #x160))
+                       (svref *unicode-118-160-to-iso-8859-9*
+                              (the fixnum (- code #x118)))))))
+              
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-9-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-9-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-9-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xd0) code)
+                      ((< code #x100)
+                       (svref *unicode-d0-100-to-iso-8859-9*
+                              (the fixnum (- code #xd0))))
+                      ((and (>= code #x118) (< code #x160))
+                       (svref *unicode-118-160-to-iso-8859-9*
+                              (the fixnum (- code #x118)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-9-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-9-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-9-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xd0) code)
+                      ((< code #x100)
+                       (svref *unicode-d0-100-to-iso-8859-9*
+                              (the fixnum (- code #xd0))))
+                      ((and (>= code #x118) (< code #x160))
+                       (svref *unicode-118-160-to-iso-8859-9*
+                              (the fixnum (- code #x118)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-9-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-9-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xd0
+  :encode-literal-char-code-limit #xa0
+  )
+
+(defstatic *iso-8859-10-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+0104 #\u+0112 #\u+0122 #\u+012a #\u+0128 #\u+0136 #\u+00a7
+    #\u+013b #\u+0110 #\u+0160 #\u+0166 #\u+017d #\u+00ad #\u+016a #\u+014a
+    ;; #xb0
+    #\u+00b0 #\u+0105 #\u+0113 #\u+0123 #\u+012b #\u+0129 #\u+0137 #\u+00b7
+    #\u+013c #\u+0111 #\u+0161 #\u+0167 #\u+017e #\u+2015 #\u+016b #\u+014b
+    ;; #xc0
+    #\u+0100 #\u+00c1 #\u+00c2 #\u+00c3 #\u+00c4 #\u+00c5 #\u+00c6 #\u+012e
+    #\u+010c #\u+00c9 #\u+0118 #\u+00cb #\u+0116 #\u+00cd #\u+00ce #\u+00cf
+    ;; #xd0
+    #\u+00d0 #\u+0145 #\u+014c #\u+00d3 #\u+00d4 #\u+00d5 #\u+00d6 #\u+0168
+    #\u+00d8 #\u+0172 #\u+00da #\u+00db #\u+00dc #\u+00dd #\u+00de #\u+00df
+    ;; #xe0
+    #\u+0101 #\u+00e1 #\u+00e2 #\u+00e3 #\u+00e4 #\u+00e5 #\u+00e6 #\u+012f
+    #\u+010d #\u+00e9 #\u+0119 #\u+00eb #\u+0117 #\u+00ed #\u+00ee #\u+00ef
+    ;; #xf0
+    #\u+00f0 #\u+0146 #\u+014d #\u+00f3 #\u+00f4 #\u+00f5 #\u+00f6 #\u+0169
+    #\u+00f8 #\u+0173 #\u+00fa #\u+00fb #\u+00fc #\u+00fd #\u+00fe #\u+0138
+    ))
+
+(defstatic *unicode-a0-180-to-iso-8859-10*
+  #(
+    #xa0 nil nil nil nil nil nil #xa7   ; #xa0-#xa7 
+    nil nil nil nil nil #xad nil nil    ; #xa8-#xaf 
+    #xb0 nil nil nil nil nil nil #xb7   ; #xb0-#xb7 
+    nil nil nil nil nil nil nil nil     ; #xb8-#xbf 
+    nil #xc1 #xc2 #xc3 #xc4 #xc5 #xc6 nil ; #xc0-#xc7 
+    nil #xc9 nil #xcb nil #xcd #xce #xcf ; #xc8-#xcf 
+    #xd0 nil nil #xd3 #xd4 #xd5 #xd6 nil ; #xd0-#xd7 
+    #xd8 nil #xda #xdb #xdc #xdd #xde #xdf ; #xd8-#xdf 
+    nil #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 nil ; #xe0-#xe7 
+    nil #xe9 nil #xeb nil #xed #xee #xef ; #xe8-#xef 
+    #xf0 nil nil #xf3 #xf4 #xf5 #xf6 nil ; #xf0-#xf7 
+    #xf8 nil #xfa #xfb #xfc #xfd #xfe nil ; #xf8-#xff 
+    #xc0 #xe0 nil nil #xa1 #xb1 nil nil ; #x100-#x107 
+    nil nil nil nil #xc8 #xe8 nil nil   ; #x108-#x10f 
+    #xa9 #xb9 #xa2 #xb2 nil nil #xcc #xec ; #x110-#x117 
+    #xca #xea nil nil nil nil nil nil   ; #x118-#x11f 
+    nil nil #xa3 #xb3 nil nil nil nil   ; #x120-#x127 
+    #xa5 #xb5 #xa4 #xb4 nil nil #xc7 #xe7 ; #x128-#x12f 
+    nil nil nil nil nil nil #xa6 #xb6   ; #x130-#x137 
+    #xff nil nil #xa8 #xb8 nil nil nil  ; #x138-#x13f 
+    nil nil nil nil nil #xd1 #xf1 nil   ; #x140-#x147 
+    nil nil #xaf #xbf #xd2 #xf2 nil nil ; #x148-#x14f 
+    nil nil nil nil nil nil nil nil     ; #x150-#x157 
+    nil nil nil nil nil nil nil nil     ; #x158-#x15f 
+    #xaa #xba nil nil nil nil #xab #xbb ; #x160-#x167 
+    #xd7 #xf7 #xae #xbe nil nil nil nil ; #x168-#x16f 
+    nil nil #xd9 #xf9 nil nil nil nil   ; #x170-#x177 
+    nil nil nil nil nil #xac #xbc nil   ; #x178-#x17f 
+    ))
+
+(define-character-encoding :iso-8859-10
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in Nordic
+alphabets."
+
+  :aliases '(:iso_8859-10 :latin6 :csISOLatin6 :iso-ir-157)
+  :stream-encode-function
+  (nfunction
+   iso-8859-10-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-10*
+                              (the fixnum (- code #xa0)))))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-10-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-10-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-10-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-10*
+                              (the fixnum (- code #xa0)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-10-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-10-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-10-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-10*
+                              (the fixnum (- code #xa0)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-10-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-10-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(define-character-encoding :iso-8859-11
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found the  Thai
+alphabet."
+  :aliases '()
+  :stream-encode-function
+  (nfunction
+   iso-8859-11-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa1) code)
+                      ((and (<= code #xfb)
+                            (not (and (>= code #xdb) (<= code #xde))))
+                       (+ code #x0d60)))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-11-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa1)
+       (code-char 1st-unit)
+       (if (and (>= 1st-unit #xe01)
+                (<= 1st-unit #xe5b)
+                (not (and (>= 1st-unit #xe3b)
+                          (<= 1st-unit #xe3e))))
+         (code-char (- 1st-unit #xd60))
+         #\Replacement_Character))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-11-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa1) code)
+                      ((and (<= code #xfb)
+                            (not (and (>= code #xdb) (<= code #xde))))
+                       (+ code #x0d60)))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-11-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa1)
+                 (code-char 1st-unit)
+                 (if (and (>= 1st-unit #xe01)
+                          (<= 1st-unit #xe5b)
+                          (not (and (>= 1st-unit #xe3b)
+                                    (<= 1st-unit #xe3e))))
+                   (code-char (- 1st-unit #xd60))
+                   #\Replacement_Character)))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-11-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa1) code)
+                      ((and (<= code #xfb)
+                            (not (and (>= code #xdb) (<= code #xde))))
+                       (+ code #x0d60)))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-11-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa1)
+                 (code-char 1st-unit)
+                 (if (and (>= 1st-unit #xe01)
+                          (<= 1st-unit #xe5b)
+                          (not (and (>= 1st-unit #xe3b)
+                                    (<= 1st-unit #xe3e))))
+                   (code-char (- 1st-unit #xd60))
+                   #\Replacement_Character)))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+;;; There is no iso-8859-12 encoding.
+
+(defstatic *iso-8859-13-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+201d #\u+00a2 #\u+00a3 #\u+00a4 #\u+201e #\u+00a6 #\u+00a7
+    #\u+00d8 #\u+00a9 #\u+0156 #\u+00ab #\u+00ac #\u+00ad #\u+00ae #\u+00c6
+    ;; #xb0
+    #\u+00b0 #\u+00b1 #\u+00b2 #\u+00b3 #\u+201c #\u+00b5 #\u+00b6 #\u+00b7
+    #\u+00f8 #\u+00b9 #\u+0157 #\u+00bb #\u+00bc #\u+00bd #\u+00be #\u+00e6
+    ;; #xc0
+    #\u+0104 #\u+012e #\u+0100 #\u+0106 #\u+00c4 #\u+00c5 #\u+0118 #\u+0112
+    #\u+010c #\u+00c9 #\u+0179 #\u+0116 #\u+0122 #\u+0136 #\u+012a #\u+013b
+    ;; #xd0
+    #\u+0160 #\u+0143 #\u+0145 #\u+00d3 #\u+014c #\u+00d5 #\u+00d6 #\u+00d7
+    #\u+0172 #\u+0141 #\u+015a #\u+016a #\u+00dc #\u+017b #\u+017d #\u+00df
+    ;; #xe0
+    #\u+0105 #\u+012f #\u+0101 #\u+0107 #\u+00e4 #\u+00e5 #\u+0119 #\u+0113
+    #\u+010d #\u+00e9 #\u+017a #\u+0117 #\u+0123 #\u+0137 #\u+012b #\u+013c
+    ;; #xf0
+    #\u+0161 #\u+0144 #\u+0146 #\u+00f3 #\u+014d #\u+00f5 #\u+00f6 #\u+00f7
+    #\u+0173 #\u+0142 #\u+015b #\u+016b #\u+00fc #\u+017c #\u+017e #\u+2019
+    ))
+
+(defstatic *unicode-a0-180-to-iso-8859-13*
+  #(
+    #xa0 nil #xa2 #xa3 #xa4 nil #xa6 #xa7 ; #xa0-#xa7
+    nil #xa9 nil #xab #xac #xad #xae nil ; #xa8-#xaf
+    #xb0 #xb1 #xb2 #xb3 nil #xb5 #xb6 #xb7 ; #xb0-#xb7
+    nil #xb9 nil #xbb #xbc #xbd #xbe nil ; #xb8-#xbf
+    nil nil nil nil #xc4 #xc5 #xaf nil ; #xc0-#xc7
+    nil #xc9 nil nil nil nil nil nil ; #xc8-#xcf
+    nil nil nil #xd3 nil #xd5 #xd6 #xd7 ; #xd0-#xd7
+    #xa8 nil nil nil #xdc nil nil #xdf ; #xd8-#xdf
+    nil nil nil nil #xe4 #xe5 #xbf nil ; #xe0-#xe7
+    nil #xe9 nil nil nil nil nil nil ; #xe8-#xef
+    nil nil nil #xf3 nil #xf5 #xf6 #xf7 ; #xf0-#xf7
+    #xb8 nil nil nil #xfc nil nil nil ; #xf8-#xff
+    #xc2 #xe2 nil nil #xc0 #xe0 #xc3 #xe3 ; #x100-#x107
+    nil nil nil nil #xc8 #xe8 nil nil ; #x108-#x10f
+    nil nil #xc7 #xe7 nil nil #xcb #xeb ; #x110-#x117
+    #xc6 #xe6 nil nil nil nil nil nil ; #x118-#x11f
+    nil nil #xcc #xec nil nil nil nil ; #x120-#x127
+    nil nil #xce #xee nil nil #xc1 #xe1 ; #x128-#x12f
+    nil nil nil nil nil nil #xcd #xed ; #x130-#x137
+    nil nil nil #xcf #xef nil nil nil ; #x138-#x13f
+    nil #xd9 #xf9 #xd1 #xf1 #xd2 #xf2 nil ; #x140-#x147
+    nil nil nil nil #xd4 #xf4 nil nil ; #x148-#x14f
+    nil nil nil nil nil nil #xaa #xba ; #x150-#x157
+    nil nil #xda #xfa nil nil nil nil ; #x158-#x15f
+    #xd0 #xf0 nil nil nil nil nil nil ; #x160-#x167
+    nil nil #xdb #xfb nil nil nil nil ; #x168-#x16f
+    nil nil #xd8 #xf8 nil nil nil nil ; #x170-#x177
+    nil #xca #xea #xdd #xfd #xde #xfe nil ; #x178-#x17f
+    ))
+
+(defstatic *unicode-2018-2020-to-iso-8859-13*
+  #(
+    nil #xff nil nil #xb4 #xa1 #xa5 nil ; #x2018-#x201f */
+    ))
+
+
+(define-character-encoding :iso-8859-13
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in Baltic
+alphabets."
+
+  :aliases '()
+  :stream-encode-function
+  (nfunction
+   iso-8859-13-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-13*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x2018)
+                            (< code #x2020))
+                       (svref *unicode-2018-2020-to-iso-8859-13*
+                              (the fixnum (- code #x2018)))))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-13-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-13-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-13-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-13*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x2018)
+                            (< code #x2020))
+                       (svref *unicode-2018-2020-to-iso-8859-13*
+                              (the fixnum (- code #x2018)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-13-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-13-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-13-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-13*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x2018)
+                            (< code #x2020))
+                       (svref *unicode-2018-2020-to-iso-8859-13*
+                              (the fixnum (- code #x2018)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-13-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-13-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *iso-8859-14-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+1e02 #\u+1e03 #\u+00a3 #\u+010a #\u+010b #\u+1e0a #\u+00a7
+    #\u+1e80 #\u+00a9 #\u+1e82 #\u+1e0b #\u+1ef2 #\u+00ad #\u+00ae #\u+0178
+    ;; #xb0
+    #\u+1e1e #\u+1e1f #\u+0120 #\u+0121 #\u+1e40 #\u+1e41 #\u+00b6 #\u+1e56
+    #\u+1e81 #\u+1e57 #\u+1e83 #\u+1e60 #\u+1ef3 #\u+1e84 #\u+1e85 #\u+1e61
+    ;; #xc0
+    #\u+00c0 #\u+00c1 #\u+00c2 #\u+00c3 #\u+00c4 #\u+00c5 #\u+00c6 #\u+00c7
+    #\u+00c8 #\u+00c9 #\u+00ca #\u+00cb #\u+00cc #\u+00cd #\u+00ce #\u+00cf
+    ;; #xd0
+    #\u+0174 #\u+00d1 #\u+00d2 #\u+00d3 #\u+00d4 #\u+00d5 #\u+00d6 #\u+1e6a
+    #\u+00d8 #\u+00d9 #\u+00da #\u+00db #\u+00dc #\u+00dd #\u+0176 #\u+00df
+    ;; #xe0
+    #\u+00e0 #\u+00e1 #\u+00e2 #\u+00e3 #\u+00e4 #\u+00e5 #\u+00e6 #\u+00e7
+    #\u+00e8 #\u+00e9 #\u+00ea #\u+00eb #\u+00ec #\u+00ed #\u+00ee #\u+00ef
+    ;; #xf0
+    #\u+0175 #\u+00f1 #\u+00f2 #\u+00f3 #\u+00f4 #\u+00f5 #\u+00f6 #\u+1e6b
+    #\u+00f8 #\u+00f9 #\u+00fa #\u+00fb #\u+00fc #\u+00fd #\u+0177 #\u+00ff
+    ))
+
+(defstatic *unicode-a0-100-to-iso-8859-14*
+  #(
+    #xa0 nil nil #xa3 nil nil nil #xa7  ; #xa0-#xa7
+    nil #xa9 nil nil nil #xad #xae nil  ; #xa8-#xaf
+    nil nil nil nil nil nil #xb6 nil    ; #xb0-#xb7
+    nil nil nil nil nil nil nil nil     ; #xb8-#xbf
+    #xc0 #xc1 #xc2 #xc3 #xc4 #xc5 #xc6 #xc7 ; #xc0-#xc7
+    #xc8 #xc9 #xca #xcb #xcc #xcd #xce #xcf ; #xc8-#xcf
+    nil #xd1 #xd2 #xd3 #xd4 #xd5 #xd6 nil ; #xd0-#xd7
+    #xd8 #xd9 #xda #xdb #xdc #xdd nil #xdf ; #xd8-#xdf
+    #xe0 #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 #xe7 ; #xe0-#xe7
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #xe8-#xef
+    nil #xf1 #xf2 #xf3 #xf4 #xf5 #xf6 nil ; #xf0-#xf7
+    #xf8 #xf9 #xfa #xfb #xfc #xfd nil #xff ; #xf8-#xff
+    ))
+
+(defstatic *unicode-108-128-to-iso-8859-14*
+  #(
+    nil nil #xa4 #xa5 nil nil nil nil   ; #x108-#x10f
+    nil nil nil nil nil nil nil nil     ; #x110-#x117
+    nil nil nil nil nil nil nil nil     ; #x118-#x11f
+    #xb2 #xb3 nil nil nil nil nil nil   ; #x120-#x127
+    ))
+
+(defstatic *unicode-170-180-to-iso-8859-14*
+  #(
+    nil nil nil nil #xd0 #xf0 #xde #xfe ; #x170-#x177
+    #xaf nil nil nil nil nil nil nil    ; #x178-#x17f
+    ))    
+
+(defstatic *unicode-1e00-1e88-to-iso-8859-14*
+  #(
+    nil nil #xa1 #xa2 nil nil nil nil   ; #x1e00-#x1e07
+    nil nil #xa6 #xab nil nil nil nil   ; #x1e08-#x1e0f
+    nil nil nil nil nil nil nil nil     ; #x1e10-#x1e17
+    nil nil nil nil nil nil #xb0 #xb1   ; #x1e18-#x1e1f
+    nil nil nil nil nil nil nil nil     ; #x1e20-#x1e27
+    nil nil nil nil nil nil nil nil     ; #x1e28-#x1e2f
+    nil nil nil nil nil nil nil nil     ; #x1e30-#x1e37
+    nil nil nil nil nil nil nil nil     ; #x1e38-#x1e3f
+    #xb4 #xb5 nil nil nil nil nil nil   ; #x1e40-#x1e47
+    nil nil nil nil nil nil nil nil     ; #x1e48-#x1e4f
+    nil nil nil nil nil nil #xb7 #xb9   ; #x1e50-#x1e57
+    nil nil nil nil nil nil nil nil     ; #x1e58-#x1e5f
+    #xbb #xbf nil nil nil nil nil nil   ; #x1e60-#x1e67
+    nil nil #xd7 #xf7 nil nil nil nil   ; #x1e68-#x1e6f
+    nil nil nil nil nil nil nil nil     ; #x1e70-#x1e77
+    nil nil nil nil nil nil nil nil     ; #x1e78-#x1e7f
+    #xa8 #xb8 #xaa #xba #xbd #xbe nil nil ; #x1e80-#x1e87
+    ))
+
+(defstatic *unicode-1ef0-1ef8-to-iso-8859-14*
+  #(
+    nil nil #xac #xbc nil nil nil nil   ; #x1ef0-#x1ef7
+    ))
+
+(define-character-encoding :iso-8859-14
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in Celtic
+languages."
+  :aliases '(:iso_8859-14 :iso-ir-199 :latin8 :l8 :iso-celtic)
+  :stream-encode-function
+  (nfunction
+   iso-8859-14-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x100)
+                       (svref *unicode-a0-100-to-iso-8859-14*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x108) (< code #x128))
+                       (svref *unicode-108-128-to-iso-8859-14*
+                              (the fixnum (- code #x108))))
+                      ((and (>= code #x170) (< code #x180))
+                       (svref *unicode-170-180-to-iso-8859-14*
+                              (the fixnum (- code #x170))))
+                      ((and (>= code #x1e00) (< code #x1e88))
+                       (svref *unicode-1e00-1e88-to-iso-8859-14*
+                              (the fixnum (- code #x1e00))))
+                      ((and (>= code #x1ef0) (< code #x1ef8))
+                       (svref *unicode-1ef0-1ef8-to-iso-8859-14*
+                              (the fixnum (- code #x1ef0)))))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-14-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-14-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-14-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x100)
+                       (svref *unicode-a0-100-to-iso-8859-14*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x108) (< code #x128))
+                       (svref *unicode-108-128-to-iso-8859-14*
+                              (the fixnum (- code #x108))))
+                      ((and (>= code #x170) (< code #x180))
+                       (svref *unicode-170-180-to-iso-8859-14*
+                              (the fixnum (- code #x170))))
+                      ((and (>= code #x1e00) (< code #x1e88))
+                       (svref *unicode-1e00-1e88-to-iso-8859-14*
+                              (the fixnum (- code #x1e00))))
+                      ((and (>= code #x1ef0) (< code #x1ef8))
+                       (svref *unicode-1ef0-1ef8-to-iso-8859-14*
+                              (the fixnum (- code #x1ef0)))))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-14-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-14-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-14-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x100)
+                       (svref *unicode-a0-100-to-iso-8859-14*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x108) (< code #x128))
+                       (svref *unicode-108-128-to-iso-8859-14*
+                              (the fixnum (- code #x108))))
+                      ((and (>= code #x170) (< code #x180))
+                       (svref *unicode-170-180-to-iso-8859-14*
+                              (the fixnum (- code #x170))))
+                      ((and (>= code #x1e00) (< code #x1e88))
+                       (svref *unicode-1e00-1e88-to-iso-8859-14*
+                              (the fixnum (- code #x1e00))))
+                      ((and (>= code #x1ef0) (< code #x1ef8))
+                       (svref *unicode-1ef0-1ef8-to-iso-8859-14*
+                              (the fixnum (- code #x1ef0)))))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-14-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-14-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *iso-8859-15-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+00a1 #\u+00a2 #\u+00a3 #\u+20ac #\u+00a5 #\u+0160 #\u+00a7
+    #\u+0161 #\u+00a9 #\u+00aa #\u+00ab #\u+00ac #\u+00ad #\u+00ae #\u+00af
+    ;; #xb0
+    #\u+00b0 #\u+00b1 #\u+00b2 #\u+00b3 #\u+017d #\u+00b5 #\u+00b6 #\u+00b7
+    #\u+017e #\u+00b9 #\u+00ba #\u+00bb #\u+0152 #\u+0153 #\u+0178 #\u+00bf
+    ;; #xc0
+    #\u+00c0 #\u+00c1 #\u+00c2 #\u+00c3 #\u+00c4 #\u+00c5 #\u+00c6 #\u+00c7 
+    ;; #xc8
+    #\u+00c8 #\u+00c9 #\u+00ca #\u+00cb #\u+00cc #\u+00cd #\u+00ce #\u+00cf 
+    ;; #xd0
+    #\u+00d0 #\u+00d1 #\u+00d2 #\u+00d3 #\u+00d4 #\u+00d5 #\u+00d6 #\u+00d7 
+    ;; #xd8
+    #\u+00d8 #\u+00d9 #\u+00da #\u+00db #\u+00dc #\u+00dd #\u+00de #\u+00df 
+    ;; #xe0
+    #\u+00e0 #\u+00e1 #\u+00e2 #\u+00e3 #\u+00e4 #\u+00e5 #\u+00e6 #\u+00e7 
+    ;; #xe8
+    #\u+00e8 #\u+00e9 #\u+00ea #\u+00eb #\u+00ec #\u+00ed #\u+00ee #\u+00ef 
+    ;; #xf0
+    #\u+00f0 #\u+00f1 #\u+00f2 #\u+00f3 #\u+00f4 #\u+00f5 #\u+00f6 #\u+00f7 
+    ;; #xf8
+    #\u+00f8 #\u+00f9 #\u+00fa #\u+00fb #\u+00fc #\u+00fd #\u+00fe #\u+00ff 
+    ))
+
+(defstatic *unicode-a0-100-to-iso-8859-15*
+  #(
+    #xa0 #xa1 #xa2 #xa3 nil #xa5 nil #xa7 ; #xa0-#xa7
+    nil #xa9 #xaa #xab #xac #xad #xae #xaf ; #xa8-#xaf
+    #xb0 #xb1 #xb2 #xb3 nil #xb5 #xb6 #xb7 ; #xb0-#xb7
+    nil #xb9 #xba #xbb nil nil nil #xbf ; #xb8-0xbf
+    #xc0 #xc1 #xc2 #xc3 #xc4 #xc5 #xc6 #xc7 ; #xc0-#xc7
+    #xc8 #xc9 #xca #xcb #xcc #xcd #xce #xcf ; #xc8-#xcf
+    #xd0 #xd1 #xd2 #xd3 #xd4 #xd5 #xd6 #xd7 ; #xd0-#xd7
+    #xd8 #xd9 #xda #xdb #xdc #xdd #xde #xdf ; #xd8-#xdf
+    #xe0 #xe1 #xe2 #xe3 #xe4 #xe5 #xe6 #xe7 ; #xe0-#xe7
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #xe8-#xef
+    #xf0 #xf1 #xf2 #xf3 #xf4 #xf5 #xf6 #xf7 ; #xf0-#xf7
+    #xf8 #xf9 #xfa #xfb #xfc #xfd #xfe #xff ; #xf8-#xff
+    ))
+
+(defstatic *unicode-150-180-to-iso-8859-15*
+  #(
+    nil nil #xbc #xbd nil nil nil nil   ; #x150-#x157
+    nil nil nil nil nil nil nil nil     ; #x158-#x15f
+    #xa6 #xa8 nil nil nil nil nil nil   ; #x160-#x167
+    nil nil nil nil nil nil nil nil     ; #x168-#x16f
+    nil nil nil nil nil nil nil nil     ; #x170-#x177
+    #xbe nil nil nil nil #xb4 #xb8 nil  ; #x178-#x17f
+    ))
+
+(define-character-encoding :iso-8859-15
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in Western
+European languages (including the Euro sign and some other characters
+missing from ISO-8859-1."
+  :aliases '(:iso_8859-15 :latin9)
+  :stream-encode-function
+  (nfunction
+   iso-8859-15-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x100)
+                       (svref *unicode-a0-100-to-iso-8859-15*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x150) (< code #x180))
+                       (svref *unicode-150-180-to-iso-8859-15*
+                              (the fixnum (- code #x150))))
+                      ((= code #x20ac) #xa4))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-15-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-15-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-15-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x100)
+                       (svref *unicode-a0-100-to-iso-8859-15*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x150) (< code #x180))
+                       (svref *unicode-150-180-to-iso-8859-15*
+                              (the fixnum (- code #x150))))
+                      ((= code #x20ac) #xa4))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-15-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-15-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-15-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x100)
+                       (svref *unicode-a0-100-to-iso-8859-15*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x150) (< code #x180))
+                       (svref *unicode-150-180-to-iso-8859-15*
+                              (the fixnum (- code #x150))))
+                      ((= code #x20ac) #xa4))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-15-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-15-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *iso-8859-16-to-unicode*
+  #(
+    ;; #xa0
+    #\u+00a0 #\u+0104 #\u+0105 #\u+0141 #\u+20ac #\u+201e #\u+0160 #\u+00a7
+    #\u+0161 #\u+00a9 #\u+0218 #\u+00ab #\u+0179 #\u+00ad #\u+017a #\u+017b
+    ;; #xb0
+    #\u+00b0 #\u+00b1 #\u+010c #\u+0142 #\u+017d #\u+201d #\u+00b6 #\u+00b7
+    #\u+017e #\u+010d #\u+0219 #\u+00bb #\u+0152 #\u+0153 #\u+0178 #\u+017c
+    ;; #xc0
+    #\u+00c0 #\u+00c1 #\u+00c2 #\u+0102 #\u+00c4 #\u+0106 #\u+00c6 #\u+00c7
+    #\u+00c8 #\u+00c9 #\u+00ca #\u+00cb #\u+00cc #\u+00cd #\u+00ce #\u+00cf
+    ;; #xd0
+    #\u+0110 #\u+0143 #\u+00d2 #\u+00d3 #\u+00d4 #\u+0150 #\u+00d6 #\u+015a
+    #\u+0170 #\u+00d9 #\u+00da #\u+00db #\u+00dc #\u+0118 #\u+021a #\u+00df
+    ;; #xe0
+    #\u+00e0 #\u+00e1 #\u+00e2 #\u+0103 #\u+00e4 #\u+0107 #\u+00e6 #\u+00e7
+    #\u+00e8 #\u+00e9 #\u+00ea #\u+00eb #\u+00ec #\u+00ed #\u+00ee #\u+00ef
+    ;; #xf0
+    #\u+0111 #\u+0144 #\u+00f2 #\u+00f3 #\u+00f4 #\u+0151 #\u+00f6 #\u+015b
+    #\u+0171 #\u+00f9 #\u+00fa #\u+00fb #\u+00fc #\u+0119 #\u+021b #\u+00ff
+    ))
+
+(defstatic *unicode-a0-180-to-iso-8859-16*
+  #(
+    #xa0 nil nil nil nil nil nil #xa7   ; #xa0-#xa7 
+    nil #xa9 nil #xab nil #xad nil nil  ; #xa8-#xaf 
+    #xb0 #xb1 nil nil nil nil #xb6 #xb7 ; #xb0-#xb7 
+    nil nil nil #xbb nil nil nil nil    ; #xb8-#xbf 
+    #xc0 #xc1 #xc2 nil #xc4 nil #xc6 #xc7 ; #xc0-#xc7 
+    #xc8 #xc9 #xca #xcb #xcc #xcd #xce #xcf ; #xc8-#xcf 
+    nil nil #xd2 #xd3 #xd4 nil #xd6 nil ; #xd0-#xd7 
+    nil #xd9 #xda #xdb #xdc nil nil #xdf ; #xd8-#xdf 
+    #xe0 #xe1 #xe2 nil #xe4 nil #xe6 #xe7 ; #xe0-#xe7 
+    #xe8 #xe9 #xea #xeb #xec #xed #xee #xef ; #xe8-#xef 
+    nil nil #xf2 #xf3 #xf4 nil #xf6 nil ; #xf0-#xf7 
+    nil #xf9 #xfa #xfb #xfc nil nil #xff ; #xf8-#xff 
+    nil nil #xc3 #xe3 #xa1 #xa2 #xc5 #xe5 ; #x100-#x107 
+    nil nil nil nil #xb2 #xb9 nil nil   ; #x108-#x10f 
+    #xd0 #xf0 nil nil nil nil nil nil   ; #x110-#x117 
+    #xdd #xfd nil nil nil nil nil nil   ; #x118-#x11f 
+    nil nil nil nil nil nil nil nil     ; #x120-#x127 
+    nil nil nil nil nil nil nil nil     ; #x128-#x12f 
+    nil nil nil nil nil nil nil nil     ; #x130-#x137 
+    nil nil nil nil nil nil nil nil     ; #x138-#x13f 
+    nil #xa3 #xb3 #xd1 #xf1 nil nil nil ; #x140-#x147 
+    nil nil nil nil nil nil nil nil     ; #x148-#x14f 
+    #xd5 #xf5 #xbc #xbd nil nil nil nil ; #x150-#x157 
+    nil nil #xd7 #xf7 nil nil nil nil   ; #x158-#x15f 
+    #xa6 #xa8 nil nil nil nil nil nil   ; #x160-#x167 
+    nil nil nil nil nil nil nil nil     ; #x168-#x16f 
+    #xd8 #xf8 nil nil nil nil nil nil   ; #x170-#x177 
+    #xbe #xac #xae #xaf #xbf #xb4 #xb8 nil ; #x178-#x17f 
+    ))
+
+(defstatic *unicode-218-220-to-iso-8859-16*
+  #(
+    #xaa #xba #xde #xfe nil nil nil nil ; #x218-#x21f
+    ))
+
+(defstatic *unicode-2018-2020-to-iso-8859-16*
+  #(
+    nil nil nil nil nil #xb5 #xa5 nil   ; #x2018-#x201f
+    ))
+  
+
+(define-character-encoding :iso-8859-16
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x9f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Intended to provide most characters found in Southeast
+European languages."
+  :aliases '(:iso_8859-16 :latin10 :l1 :iso-ir-226)
+  :stream-encode-function
+  (nfunction
+   iso-8859-16-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-16*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x218) (< code #x220))
+                       (svref *unicode-218-220-to-iso-8859-16*
+                              (the fixnum (- code #x218))))
+                      ((and (>= code #x2018) (< code #x2020))
+                       (svref *unicode-2018-2020-to-iso-8859-16*
+                              (the fixnum (- code #x2018))))
+                      ((= code #x20ac) #xa4))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   iso-8859-16-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #xa0)
+       (code-char 1st-unit)
+       (svref *iso-8859-16-to-unicode* (the fixnum (- 1st-unit #xa0))))))
+  :vector-encode-function
+  (nfunction
+   iso-8859-16-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-16*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x218) (< code #x220))
+                       (svref *unicode-218-220-to-iso-8859-16*
+                              (the fixnum (- code #x218))))
+                      ((and (>= code #x2018) (< code #x2020))
+                       (svref *unicode-2018-2020-to-iso-8859-16*
+                              (the fixnum (- code #x2018))))
+                      ((= code #x20ac) #xa4))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   iso-8859-16-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-16-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :memory-encode-function
+  (nfunction
+   iso-8859-16-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (c2 (cond ((< code #xa0) code)
+                      ((< code #x180)
+                       (svref *unicode-a0-180-to-iso-8859-16*
+                              (the fixnum (- code #xa0))))
+                      ((and (>= code #x218) (< code #x220))
+                       (svref *unicode-218-220-to-iso-8859-16*
+                              (the fixnum (- code #x218))))
+                      ((and (>= code #x2018) (< code #x2020))
+                       (svref *unicode-2018-2020-to-iso-8859-16*
+                              (the fixnum (- code #x2018))))
+                      ((= code #x20ac) #xa4))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   iso-8859-16-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #xa0)
+                 (code-char 1st-unit)
+                 (svref *iso-8859-16-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #xa0
+  :encode-literal-char-code-limit #xa0  
+  )
+
+(defstatic *macintosh-to-unicode*
+  #(
+    ;; #x80 
+    #\u+00c4 #\u+00c5 #\u+00c7 #\u+00c9 #\u+00d1 #\u+00d6 #\u+00dc #\u+00e1
+    #\u+00e0 #\u+00e2 #\u+00e4 #\u+00e3 #\u+00e5 #\u+00e7 #\u+00e9 #\u+00e8
+    ;; #x90 
+    #\u+00ea #\u+00eb #\u+00ed #\u+00ec #\u+00ee #\u+00ef #\u+00f1 #\u+00f3
+    #\u+00f2 #\u+00f4 #\u+00f6 #\u+00f5 #\u+00fa #\u+00f9 #\u+00fb #\u+00fc
+    ;; #xa0 
+    #\u+2020 #\u+00b0 #\u+00a2 #\u+00a3 #\u+00a7 #\u+2022 #\u+00b6 #\u+00df
+    #\u+00ae #\u+00a9 #\u+2122 #\u+00b4 #\u+00a8 #\u+2260 #\u+00c6 #\u+00d8
+    ;; #xb0 
+    #\u+221e #\u+00b1 #\u+2264 #\u+2265 #\u+00a5 #\u+00b5 #\u+2202 #\u+2211
+    #\u+220f #\u+03c0 #\u+222b #\u+00aa #\u+00ba #\u+2126 #\u+00e6 #\u+00f8
+    ;; #xc0 
+    #\u+00bf #\u+00a1 #\u+00ac #\u+221a #\u+0192 #\u+2248 #\u+2206 #\u+00ab
+    #\u+00bb #\u+2026 #\u+00a0 #\u+00c0 #\u+00c3 #\u+00d5 #\u+0152 #\u+0153
+    ;; #xd0 
+    #\u+2013 #\u+2014 #\u+201c #\u+201d #\u+2018 #\u+2019 #\u+00f7 #\u+25ca
+    #\u+00ff #\u+0178 #\u+2044 #\u+00a4 #\u+2039 #\u+203a #\u+fb01 #\u+fb02
+    ;; #xe0 
+    #\u+2021 #\u+00b7 #\u+201a #\u+201e #\u+2030 #\u+00c2 #\u+00ca #\u+00c1
+    #\u+00cb #\u+00c8 #\u+00cd #\u+00ce #\u+00cf #\u+00cc #\u+00d3 #\u+00d4
+    ;; #xf0 
+    #\u+f8ff #\u+00d2 #\u+00da #\u+00db #\u+00d9 #\u+0131 #\u+02c6 #\u+02dc
+    #\u+00af #\u+02d8 #\u+02d9 #\u+02da #\u+00b8 #\u+02dd #\u+02db #\u+02c7
+    ))
+
+
+(defstatic *unicode-a0-100-to-macintosh*
+  #(
+    #xca #xc1 #xa2 #xa3 #xdb #xb4 nil #xa4 ; #xa0-#xa7 
+    #xac #xa9 #xbb #xc7 #xc2 nil #xa8 #xf8 ; #xa8-#xaf 
+    #xa1 #xb1 nil nil #xab #xb5 #xa6 #xe1 ; #xb0-#xb7 
+    #xfc nil #xbc #xc8 nil nil nil #xc0 ; #xb8-#xbf 
+    #xcb #xe7 #xe5 #xcc #x80 #x81 #xae #x82 ; #xc0-#xc7 
+    #xe9 #x83 #xe6 #xe8 #xed #xea #xeb #xec ; #xc8-#xcf 
+    nil #x84 #xf1 #xee #xef #xcd #x85 nil ; #xd0-#xd7 
+    #xaf #xf4 #xf2 #xf3 #x86 nil nil #xa7 ; #xd8-#xdf 
+    #x88 #x87 #x89 #x8b #x8a #x8c #xbe #x8d ; #xe0-#xe7 
+    #x8f #x8e #x90 #x91 #x93 #x92 #x94 #x95 ; #xe8-#xef 
+    nil #x96 #x98 #x97 #x99 #x9b #x9a #xd6 ; #xf0-#xf7 
+    #xbf #x9d #x9c #x9e #x9f nil nil #xd8 ; #xf8-#xff 
+    ))
+
+(defstatic *unicode-130-198-to-macintosh*
+  #(
+    nil #xf5 nil nil nil nil nil nil ; #x130-#x137 
+    nil nil nil nil nil nil nil nil ; #x138-#x13f 
+    nil nil nil nil nil nil nil nil ; #x140-#x147 
+    nil nil nil nil nil nil nil nil ; #x148-#x14f 
+    nil nil #xce #xcf nil nil nil nil ; #x150-#x157 
+    nil nil nil nil nil nil nil nil ; #x158-#x15f 
+    nil nil nil nil nil nil nil nil ; #x160-#x167 
+    nil nil nil nil nil nil nil nil ; #x168-#x16f 
+    nil nil nil nil nil nil nil nil ; #x170-#x177 
+    #xd9 nil nil nil nil nil nil nil ; #x178-#x17f 
+    nil nil nil nil nil nil nil nil ; #x180-#x187 
+    nil nil nil nil nil nil nil nil ; #x188-#x18f 
+    nil nil #xc4 nil nil nil nil nil ; #x190-#x197 
+    ))
+
+(defstatic *unicode-2c0-2e0-to-macintosh*
+  #(
+    nil nil nil nil nil nil #xf6 #xff   ; #x2c0-#x2c7 
+    nil nil nil nil nil nil nil nil     ; #x2c8-#x2cf 
+    nil nil nil nil nil nil nil nil     ; #x2d0-#x2d7 
+    #xf9 #xfa #xfb #xfe #xf7 #xfd nil nil ; #x2d8-#x2df 
+    ))
+
+(defstatic *unicode-2010-2048-to-macintosh*
+  #(
+  nil nil nil #xd0 #xd1 nil nil nil ; #x2010-#x2017 
+  #xd4 #xd5 #xe2 nil #xd2 #xd3 #xe3 nil ; #x2018-#x201f 
+  #xa0 #xe0 #xa5 nil nil nil #xc9 nil ; #x2020-#x2027 
+  nil nil nil nil nil nil nil nil ; #x2028-#x202f 
+  #xe4 nil nil nil nil nil nil nil ; #x2030-#x2037 
+  nil #xdc #xdd nil nil nil nil nil ; #x2038-#x203f 
+  nil nil nil nil #xda nil nil nil ; #x2040-#x2047 
+    ))
+
+(defstatic *unicode-2120-2128-to-macintosh*
+  #(
+    nil nil #xaa nil nil nil #xbd nil   ; #x2120-#x2127
+    ))
+
+(defstatic *unicode-2200-2268-to-macintosh*
+  #(
+    nil nil #xb6 nil nil nil #xc6 nil   ; #x2200-#x2207 
+    nil nil nil nil nil nil nil #xb8    ; #x2208-#x220f 
+    nil #xb7 nil nil nil nil nil nil    ; #x2210-#x2217 
+    nil nil #xc3 nil nil nil #xb0 nil   ; #x2218-#x221f 
+    nil nil nil nil nil nil nil nil     ; #x2220-#x2227 
+    nil nil nil #xba nil nil nil nil    ; #x2228-#x222f 
+    nil nil nil nil nil nil nil nil     ; #x2230-#x2237 
+    nil nil nil nil nil nil nil nil     ; #x2238-#x223f 
+    nil nil nil nil nil nil nil nil     ; #x2240-#x2247 
+    #xc5 nil nil nil nil nil nil nil    ; #x2248-#x224f 
+    nil nil nil nil nil nil nil nil     ; #x2250-#x2257 
+    nil nil nil nil nil nil nil nil     ; #x2258-#x225f 
+    #xad nil nil nil #xb2 #xb3 nil nil  ; #x2260-#x2267 
+    ))
+
+(defstatic *unicode-fb00-fb08-to-macintosh*
+  #(
+    nil #xde #xdf nil nil nil nil nil ; #xfb00-#xfb07
+    ))
+
+(define-character-encoding :macintosh
+    "An 8-bit, fixed-width character encoding in which codes #x00-#x7f
+map to their Unicode equivalents and other codes map to other Unicode
+character values.  Traditionally used on Classic MacOS to encode characters
+used in western languages."
+  :aliases '(:macos-roman :macosroman :mac-roman :macroman)
+
+  :stream-encode-function
+  (nfunction
+   macintosh-stream-encode
+   (lambda (char write-function stream)
+     (let* ((code (char-code char))
+            (c2 (cond ((< code #x80) code)
+                      ((and (>= code #xa0) (< code #x100)
+                       (svref *unicode-a0-100-to-macintosh*
+                              (the fixnum (- code #xa0)))))
+                      ((and (>= code #x130) (< code #x198))
+                       (svref *unicode-130-198-to-macintosh*
+                              (the fixnum (- code #x130))))
+                      ((and (>= code #x2c0) (< code #x2e0))
+                       (svref *unicode-2c0-2e0-to-macintosh*
+                              (the fixnum (- code #x2c0))))
+                      ((= code #x3c0) #xb9)
+                      ((and (>= code #x2010) (< code #x2048))
+                       (svref *unicode-2010-2048-to-macintosh*
+                              (the fixnum (- code #x2010))))
+                      ((and (>= code #x2120) (< code #x2128))
+                       (svref *unicode-2120-2128-to-macintosh*
+                              (the fixnum (- code #x2120))))
+                      ((and (>= code #x2200) (< code #x2268))
+                       (svref *unicode-2200-2268-to-macintosh*
+                              (the fixnum (- code #x2200))))
+                      ((= code #x25ca) #xd7)
+                      ((and (>= code #xfb00) (< code #xfb08))
+                       (svref *unicode-fb00-fb08-to-macintosh*
+                              (the fixnum (- code #xfb00))))
+                      ((= code #xf8ff) #xf0))))
+       (declare (type (mod #x110000) code))
+       (funcall write-function stream (or c2 (char-code #\Sub)))
+       1)))
+  :stream-decode-function
+  (nfunction
+   macintosh-stream-decode
+   (lambda (1st-unit next-unit-function stream)
+     (declare (ignore next-unit-function stream)
+              (type (unsigned-byte 8) 1st-unit))
+     (if (< 1st-unit #x80)
+       (code-char 1st-unit)
+       (svref *macintosh-to-unicode* (the fixnum (- 1st-unit #x80))))))
+  :vector-encode-function
+  (nfunction
+   macintosh-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char))
+            (c2 (cond ((< code #x80) code)
+                      ((and (>= code #xa0) (< code #x100)
+                       (svref *unicode-a0-100-to-macintosh*
+                              (the fixnum (- code #xa0)))))
+                      ((and (>= code #x130) (< code #x198))
+                       (svref *unicode-130-198-to-macintosh*
+                              (the fixnum (- code #x130))))
+                      ((and (>= code #x2c0) (< code #x2e0))
+                       (svref *unicode-2c0-2e0-to-macintosh*
+                              (the fixnum (- code #x2c0))))
+                      ((= code #x3c0) #xb9)
+                      ((and (>= code #x2010) (< code #x2048))
+                       (svref *unicode-2010-2048-to-macintosh*
+                              (the fixnum (- code #x2010))))
+                      ((and (>= code #x2120) (< code #x2128))
+                       (svref *unicode-2120-2128-to-macintosh*
+                              (the fixnum (- code #x2120))))
+                      ((and (>= code #x2200) (< code #x2268))
+                       (svref *unicode-2200-2268-to-macintosh*
+                              (the fixnum (- code #x2200))))
+                      ((= code #x25ca) #xd7)
+                      ((and (>= code #xfb00) (< code #xfb08))
+                       (svref *unicode-fb00-fb08-to-macintosh*
+                              (the fixnum (- code #xfb00))))
+                      ((= code #xf8ff) #xf0))))
+         (declare (type (mod #x110000) code))
+         (setf (aref vector idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :vector-decode-function
+  (nfunction
+   macintosh-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (aref vector index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #x80)
+                 (code-char 1st-unit)
+                 (svref *macintosh-to-unicode* (the fixnum (- 1st-unit #x80)))))))))
+  :memory-encode-function
+  (nfunction
+   macintosh-memory-encode
+   (lambda (string pointer idx start end)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+            (c2 (cond ((< code #x80) code)
+                      ((and (>= code #xa0) (< code #x100)
+                       (svref *unicode-a0-100-to-macintosh*
+                              (the fixnum (- code #xa0)))))
+                      ((and (>= code #x130) (< code #x198))
+                       (svref *unicode-130-198-to-macintosh*
+                              (the fixnum (- code #x130))))
+                      ((and (>= code #x2c0) (< code #x2e0))
+                       (svref *unicode-2c0-2e0-to-macintosh*
+                              (the fixnum (- code #x2c0))))
+                      ((= code #x3c0) #xb9)
+                      ((and (>= code #x2010) (< code #x2048))
+                       (svref *unicode-2010-2048-to-macintosh*
+                              (the fixnum (- code #x2010))))
+                      ((and (>= code #x2120) (< code #x2128))
+                       (svref *unicode-2120-2128-to-macintosh*
+                              (the fixnum (- code #x2120))))
+                      ((and (>= code #x2200) (< code #x2268))
+                       (svref *unicode-2200-2268-to-macintosh*
+                              (the fixnum (- code #x2200))))
+                      ((= code #x25ca) #xd7)
+                      ((and (>= code #xfb00) (< code #xfb08))
+                       (svref *unicode-fb00-fb08-to-macintosh*
+                              (the fixnum (- code #xfb00))))
+                      ((= code #xf8ff) #xf0))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-byte pointer idx) (or c2 (char-code #\Sub)))
+         (incf idx)))))
+  :memory-decode-function
+  (nfunction
+   macintosh-memory-decode
+   (lambda (pointer noctets idx string)
+     (do* ((i 0 (1+ i))
+           (index idx (1+ index)))
+          ((>= i noctets) index)
+       (let* ((1st-unit (%get-unsigned-byte pointer index)))
+         (declare (type (unsigned-byte 8) 1st-unit))
+         (setf (schar string i)
+               (if (< 1st-unit #x80)
+                 (code-char 1st-unit)
+                 (svref *macintosh-to-unicode* (the fixnum (- 1st-unit #xa0)))))))))
+  :octets-in-string-function
+  #'8-bit-fixed-width-octets-in-string
+  :length-of-vector-encoding-function
+  #'8-bit-fixed-width-length-of-vector-encoding
+  :length-of-memory-encoding-function 
+  #'8-bit-fixed-width-length-of-memory-encoding
+  :decode-literal-code-unit-limit #x80
+  :encode-literal-char-code-limit #x80  
+  )
+
+
+;;; UTF-8.  Decoding checks for malformed sequences; it might be faster (and
+;;; would certainly be simpler) if it didn't.
+(define-character-encoding :utf-8
+    "An 8-bit, variable-length character encoding in which characters
+with CHAR-CODEs in the range #x00-#x7f can be encoded in a single
+octet; characters with larger code values can be encoded in 2 to 4
+bytes."
+    :max-units-per-char 4
+    :stream-encode-function
+    (nfunction
+     utf-8-stream-encode
+     (lambda (char write-function stream)
+       (let* ((code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (cond ((< code #x80)
+                (funcall write-function stream code)
+                1)
+               ((< code #x800)
+                (let* ((y (ldb (byte 5 6) code))
+                       (z (ldb (byte 6 0) code)))
+                  (declare (fixnum y z))
+                  (funcall write-function stream (logior #xc0 y))
+                  (funcall write-function stream (logior #x80 z))
+                  2))
+               ((< code #x10000)
+                (let* ((x (ldb (byte 4 12) code))
+                       (y (ldb (byte 6 6) code))
+                       (z (ldb (byte 6 0) code)))
+                  (declare (fixnum x y z))
+                  (funcall write-function stream (logior #xe0 x))
+                  (funcall write-function stream (logior #x80 y))
+                  (funcall write-function stream (logior #x80 z))
+                  3))
+               (t
+                (let* ((w (ldb (byte 3 18) code))
+                       (x (ldb (byte 6 12) code))
+                       (y (ldb (byte 6 6) code))
+                       (z (ldb (byte 6 0) code)))
+                  (declare (fixnum w x y z))
+                  (funcall write-function stream (logior #xf0 w))
+                  (funcall write-function stream (logior #x80 x))
+                  (funcall write-function stream (logior #x80 y))
+                  (funcall write-function stream (logior #x80 z))
+                  4))))))
+    :stream-decode-function
+    (nfunction
+     utf-8-stream-decode
+     (lambda (1st-unit next-unit-function stream)
+       (declare (type (unsigned-byte 8) 1st-unit))
+       (if (< 1st-unit #x80)
+         (code-char 1st-unit)
+         (if (>= 1st-unit #xc2)
+           (let* ((s1 (funcall next-unit-function stream)))
+             (if (eq s1 :eof)
+               s1
+               (locally
+                   (declare (type (unsigned-byte 8) s1))
+                 (if (< 1st-unit #xe0)
+                   (if (< (the fixnum (logxor s1 #x80)) #x40)
+                     (code-char
+                      (logior
+                       (the fixnum (ash (the fixnum (logand #x1f 1st-unit)) 6))
+                       (the fixnum (logxor s1 #x80))))
+                     #\Replacement_Character)
+                   (let* ((s2 (funcall next-unit-function stream)))
+                     (if (eq s2 :eof)
+                       s2
+                       (locally
+                           (declare (type (unsigned-byte 8) s2))
+                         (if (< 1st-unit #xf0)
+                           (if (and (< (the fixnum (logxor s1 #x80)) #x40)
+                                    (< (the fixnum (logxor s2 #x80)) #x40)
+                                    (or (>= 1st-unit #xe1)
+                                        (>= s1 #xa0)))
+                             (or (code-char (the fixnum
+                                          (logior (the fixnum
+                                                    (ash (the fixnum (logand 1st-unit #xf))
+                                                         12))
+                                                  (the fixnum
+                                                    (logior
+                                                     (the fixnum
+                                                       (ash (the fixnum (logand s1 #x3f))
+                                                            6))
+                                                     (the fixnum (logand s2 #x3f)))))))
+                                 #\Replacement_Character)
+                             #\Replacement_Character)
+                           (if (< 1st-unit #xf8)
+                             (let* ((s3 (funcall next-unit-function stream)))
+                               (if (eq s3 :eof)
+                                 s3
+                                 (locally
+                                     (declare (type (unsigned-byte 8) s3))
+                                   (if (and (< (the fixnum (logxor s1 #x80)) #x40)
+                                            (< (the fixnum (logxor s2 #x80)) #x40)
+                                            (< (the fixnum (logxor s3 #x80)) #x40)
+                                            (or (>= 1st-unit #xf1)
+                                                (>= s1 #x90)))
+                                     (code-char
+                                      (logior
+                                       (the fixnum
+                                         (logior
+                                          (the fixnum
+                                            (ash (the fixnum (logand 1st-unit 7)) 18))
+                                          (the fixnum
+                                            (ash (the fixnum (logxor s1 #x80)) 12))))
+                                       (the fixnum
+                                         (logior
+                                          (the fixnum
+                                            (ash (the fixnum (logxor s2 #x80)) 6))
+                                          (the fixnum (logxor s3 #x80))))))
+                                     #\Replacement_Character))))
+                             #\Replacement_Character)))))))))
+           #\Replacement_Character))))
+    :vector-encode-function
+    (nfunction
+     utf-8-vector-encode
+     (lambda (string vector idx start end)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+                (fixnum idx))
+       (do* ((i start (1+ i)))
+            ((>= i end) idx)
+         (let* ((char (schar string i))
+                (code (char-code char)))
+           (declare (type (mod #x110000) code))
+           (cond ((< code #x80)
+                  (setf (aref vector idx) code)
+                  (incf idx))
+                 ((< code #x800)
+                  (setf (aref vector idx)
+                        (logior #xc0 (the fixnum (ash code -6))))
+                  (setf (aref vector (the fixnum (1+ idx)))
+                        (logior #x80 (the fixnum (logand code #x3f))))
+                  (incf idx 2))
+                 ((< code #x10000)
+                  (setf (aref vector idx)
+                        (logior #xe0 (the fixnum (ash code -12))))
+                  (setf (aref vector (the fixnum (1+ idx)))
+                        (logior #x80 (the fixnum (logand #x3f (the fixnum (ash code -6))))))
+                  (setf (aref vector (the fixnum (+ idx 2)))
+                        (logior #x80 (the fixnum (logand code #x3f))))
+                  (incf idx 3))
+                 (t
+                   (setf (aref vector idx)
+                         (logior #xf0
+                                 (the fixnum (logand #x7 (the fixnum (ash code -18))))))
+                   (setf (aref vector (the fixnum (1+ idx)))
+                         (logior #x80 (the fixnum (logand #x3f (the fixnum (ash code -12))))))
+                   (setf (aref vector (the fixnum (+ idx 2)))
+                         (logior #x80 (the fixnum (logand #x3f (the fixnum (ash code -6))))))
+                   (setf (aref vector (the fixnum (+ idx 3)))
+                         (logior #x80 (logand #x3f code)))
+                   (incf idx 4)))))))
+    :vector-decode-function
+    (nfunction
+     utf-8-vector-decode
+     (lambda (vector idx noctets string)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+                (type index idx))
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx (1+ index)))
+            ((= index end) index)
+           (let* ((1st-unit (aref vector index)))
+             (declare (type (unsigned-byte 8) 1st-unit))
+             (let* ((char 
+                     (if (< 1st-unit #x80)
+                       (code-char 1st-unit)
+                       (if (>= 1st-unit #xc2)
+                           (let* ((2nd-unit (aref vector (incf index))))
+                             (declare (type (unsigned-byte 8) 2nd-unit))
+                             (if (< 1st-unit #xe0)
+                               (if (< (the fixnum (logxor 2nd-unit #x80)) #x40)
+                                 (code-char
+                                  (logior
+                                   (the fixnum (ash (the fixnum (logand #x1f 1st-unit)) 6))
+                                   (the fixnum (logxor 2nd-unit #x80)))))
+                               (let* ((3rd-unit (aref vector (incf index))))
+                                 (declare (type (unsigned-byte 8) 3rd-unit))
+                                 (if (< 1st-unit #xf0)
+                                   (if (and (< (the fixnum (logxor 2nd-unit #x80)) #x40)
+                                            (< (the fixnum (logxor 3rd-unit #x80)) #x40)
+                                            (or (>= 1st-unit #xe1)
+                                                (>= 2nd-unit #xa0)))
+                                     (code-char (the fixnum
+                                                  (logior (the fixnum
+                                                            (ash (the fixnum (logand 1st-unit #xf))
+                                                                 12))
+                                                          (the fixnum
+                                                            (logior
+                                                             (the fixnum
+                                                               (ash (the fixnum (logand 2nd-unit #x3f))
+                                                                    6))
+                                                             (the fixnum (logand 3rd-unit #x3f))))))))
+                                   (let* ((4th-unit (aref vector (incf index))))
+                                     (declare (type (unsigned-byte 8) 4th-unit))
+                                     (if (and (< (the fixnum (logxor 2nd-unit #x80)) #x40)
+                                              (< (the fixnum (logxor 3rd-unit #x80)) #x40)
+                                              (< (the fixnum (logxor 4th-unit #x80)) #x40)
+                                              (or (>= 1st-unit #xf1)
+                                                  (>= 2nd-unit #x90)))
+                                       (code-char
+                                        (logior
+                                         (the fixnum
+                                           (logior
+                                            (the fixnum
+                                              (ash (the fixnum (logand 1st-unit 7)) 18))
+                                            (the fixnum
+                                              (ash (the fixnum (logxor 2nd-unit #x80)) 12))))
+                                         (the fixnum
+                                           (logior
+                                            (the fixnum
+                                              (ash (the fixnum (logxor 3rd-unit #x80)) 6))
+                                            (the fixnum (logxor 4th-unit #x80))))))))))))))))
+               (setf (schar string i) (or char #\Replacement_Character)))))))
+    :memory-encode-function
+    #'utf-8-memory-encode
+    :memory-decode-function
+    #'utf-8-memory-decode
+    :octets-in-string-function
+    #'utf-8-octets-in-string
+    :length-of-vector-encoding-function
+    (nfunction
+     utf-8-length-of-vector-encoding
+     (lambda (vector start end)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+       (do* ((i start)
+             (nchars 0))
+            ((>= i end)
+             (values nchars i))
+         (declare (fixnum i))
+         (let* ((code (aref vector i))
+                (nexti (+ i (cond ((< code #xc2) 1)
+                                  ((< code #xe0) 2)
+                                  ((< code #xf0) 3)
+                                  ((< code #xf8) 4)
+                                  (t 1)))))
+           (declare (type (unsigned-byte 8) code))
+           (if (> nexti end)
+             (return (values nchars i))
+             (setq nchars (1+ nchars) i nexti))))))
+    :length-of-memory-encoding-function
+    #'utf-8-length-of-memory-encoding
+    :decode-literal-code-unit-limit #x80
+    :encode-literal-char-code-limit #x80    
+    :bom-encoding #(#xef #xbb #xbf)
+    :character-size-in-octets-function  (lambda (c)
+                                          (let* ((code (char-code c)))
+                                            (declare (type (mod #x110000) code))
+                                            (if (< code #x80)
+                                              1
+                                              (if (< code #x800)
+                                                2
+                                                (if (< code #x10000)
+                                                  3
+                                                  4)))))
+      
+    )
+
+
+;;; For a code-unit-size greater than 8: the stream-encode function's write-function
+;;; accepts a code-unit in native byte order and swaps it if necessary and the
+;;; stream-decode function receives a first-unit in native byte order and its
+;;; next-unit-function returns a unit in native byte order.  The memory/vector
+;;; functions have to do their own byte swapping.
+
+
+(defmacro utf-16-combine-surrogate-pairs (a b)
+  `(code-char
+    (the (unsigned-byte 21)
+      (+ #x10000
+         (the (unsigned-byte 20)
+           (logior
+            (the (unsigned-byte 20) (ash (the (unsigned-byte 10)
+                                           (- ,a #xd800))
+                                         10))
+            (the (unsigned-byte 10) (- ,b #xdc00))))))))
+    
+(defun utf-16-stream-encode (char write-function stream)
+  (let* ((code (char-code char))
+         (highbits (- code #x10000)))
+    (declare (type (mod #x110000) code)
+             (fixnum highbits))
+    (if (< highbits 0)
+      (progn
+        (funcall write-function stream code)
+        1)
+      (progn
+        (funcall write-function stream (logior #xd800 (the fixnum (ash highbits -10))))
+        (funcall write-function stream (logior #xdc00 (the fixnum (logand highbits #x3ff))))
+        2))))
+
+(defun utf-16-stream-decode (1st-unit next-unit-function stream)
+  (declare (type (unsigned-byte 16) 1st-unit))
+  (if (or (< 1st-unit #xd800)
+          (>= 1st-unit #xe000))
+    (code-char 1st-unit)
+    (if (< 1st-unit #xdc00)
+      (let* ((2nd-unit (funcall next-unit-function stream)))
+        (if (eq 2nd-unit :eof)
+          2nd-unit
+          (locally (declare (type (unsigned-byte 16) 2nd-unit))
+            (if (and (>= 2nd-unit #xdc00)
+                     (< 2nd-unit #xe000))
+              (utf-16-combine-surrogate-pairs 1st-unit 2nd-unit)
+              #\Replacement_Character))))
+      #\Replacement_Character)))
+
+
+
+(declaim (inline %big-endian-u8-ref-u16 %little-endian-u8-ref-u16))
+(defun %big-endian-u8-ref-u16 (u8-vector idx)
+  (declare (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (logior (the (unsigned-byte 16) (ash (the (unsigned-byte 8) (aref u8-vector idx)) 8))
+          (the (unsigned-byte 8) (aref u8-vector (the fixnum (1+ idx))))))
+
+(defun %little-endian-u8-ref-u16 (u8-vector idx)
+  (declare (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (logior (the (unsigned-byte 16) (ash (the (unsigned-byte 8)
+                                         (aref u8-vector (the fixnum (1+ idx)))) 8))
+          (the (unsigned-byte 8) (aref u8-vector idx))))
+
+#+big-endian-target
+(progn
+(defmacro %native-u8-ref-u16 (vector idx)
+  `(%big-endian-u8-ref-u16 ,vector ,idx))
+
+(defmacro %reversed-u8-ref-u16 (vector idx)
+  `(%little-endian-u8-ref-u16 ,vector ,idx))
+)
+
+#+little-endian-target
+(progn
+(defmacro %native-u8-ref-u16 (vector idx)
+  `(%little-endian-u8-ref-u16 ,vector ,idx))
+
+(defmacro %reversed-u8-ref-u16 (vector idx)
+  `(%big-endian-u8-ref-u16 ,vector ,idx))
+)
+
+
+(declaim (inline (setf %big-endian-u8-ref-u16) (setf %little-endian-u8-ref-u16)))
+(defun (setf %big-endian-u8-ref-u16) (val u8-vector idx)
+  (declare (type (unsigned-byte 16) val)
+           (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (setf (aref u8-vector idx) (ldb (byte 8 8) val)
+        (aref u8-vector (the fixnum (1+ idx))) (ldb (byte 8 0) val))
+  val)
+
+(defun (setf %little-endian-u8-ref-u16) (val u8-vector idx)
+  (declare (type (unsigned-byte 16) val)
+           (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (setf (aref u8-vector idx) (ldb (byte 8 0) val)
+        (aref u8-vector (the fixnum (1+ idx))) (ldb (byte 8 8) val))
+  val)
+
+(defun utf-16-character-size-in-octets (c)
+  (let* ((code (char-code c)))
+    (declare (type (mod #x110000) code))
+    (if (< code #x10000)
+      2
+      4)))
+
+;;; utf-16, native byte order.
+(define-character-encoding #+big-endian-target :utf-16be #-big-endian-target :utf-16le
+    #+big-endian-target
+    "A 16-bit, variable-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+big-endian word and characters with larger codes can be encoded in a
+pair of 16-bit big-endian words.  The endianness of the encoded data
+is implicit in the encoding; byte-order-mark characters are not
+interpreted on input or prepended to output."
+    #+little-endian-target
+    "A 16-bit, variable-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+little-endian word and characters with larger codes can be encoded in
+a pair of 16-bit little-endian words.  The endianness of the encoded
+data is implicit in the encoding; byte-order-mark characters are not
+interpreted on input or prepended to output."
+    :max-units-per-char 2
+    :code-unit-size 16
+    :native-endianness t
+    :stream-encode-function
+    #'utf-16-stream-encode
+    :stream-decode-function
+    #'utf-16-stream-decode
+    :vector-encode-function
+    (nfunction
+     native-utf-16-vector-encode
+     (lambda (string vector idx start end)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+                (fixnum idx start end))
+       (do* ((i start (1+ i)))
+            ((>= i end) idx)
+         (declare (fixnum i))
+         (let* ((char (schar string i))
+                (code (char-code char))
+                (highbits (- code #x10000)))
+           (declare (type (mod #x110000) code)
+                    (fixnum highbits))
+           (cond ((< highbits 0)
+                  (setf (%native-u8-ref-u16 vector idx) code)
+                  (incf idx 2))
+                 (t
+                  (let* ((firstword (logior #xd800 (the fixnum (ash highbits -10))))
+                         (secondword (logior #xdc00 (the fixnum (logand highbits #x3ff)))))
+                    (declare (type (unsigned-byte 16) firstword secondword))
+                    (setf (%native-u8-ref-u16 vector idx) firstword
+                          (%native-u8-ref-u16 vector (the fixnum (+ idx 2))) secondword)
+                    (incf idx 4))))))))
+    :vector-decode-function
+    (nfunction
+     native-utf-16-vector-decode
+     (lambda (vector idx noctets string)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+                (type index idx))
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx))
+            ((= index end) index)
+         (declare (fixnum i end index))
+         (let* ((1st-unit (%native-u8-ref-u16 vector index)))
+           (declare (type (unsigned-byte 16) 1st-unit))
+           (incf index 2)
+           (let* ((char
+                   (if (or (< 1st-unit #xd800)
+                           (>= 1st-unit #xe000))
+                     (code-char 1st-unit)
+                     (if (< 1st-unit #xdc00)
+                       (let* ((2nd-unit (%native-u8-ref-u16 vector index)))
+                         (declare (type (unsigned-byte 16) 2nd-unit))
+                         (incf index 2)
+                         (if (and (>= 2nd-unit #xdc00)
+                                  (< 2nd-unit #xe000))
+                           (utf-16-combine-surrogate-pairs 1st-unit 2nd-unit)))))))
+             (setf (schar string i) (or char #\Replacement_Character)))))))
+    :memory-encode-function
+    (nfunction
+     native-utf-16-memory-encode
+     (lambda (string pointer idx start end)
+       (declare (fixnum idx))
+       (do* ((i start (1+ i)))
+            ((>= i end) idx)
+         (let* ((code (char-code (schar string i)))
+                (highbits (- code #x10000)))
+           (declare (type (mod #x110000) code)
+                  (fixnum  highbits))
+         (cond ((< highbits 0)
+                (setf (%get-unsigned-word pointer idx) code)
+                (incf idx 2))
+               (t
+                (setf (%get-unsigned-word pointer idx) (logior #xd800 (the fixnum (ash highbits -10))))
+                (incf idx 2)
+                (setf (%get-unsigned-word pointer idx) (logior #xdc00 (the fixnum (logand highbits #x3ff))))
+                (incf idx 2)))))))
+    :memory-decode-function
+    (nfunction
+     native-utf-16-memory-decode
+     (lambda (pointer noctets idx string)
+       (declare (fixnum noctets idx))
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx))
+            ((>= index end) index)
+         (declare (fixnum i index end))
+         (let* ((1st-unit (%get-unsigned-word pointer index)))
+           (declare (type (unsigned-byte 16) 1st-unit))
+           (incf index 2)
+           (let* ((char
+                   (if (or (< 1st-unit #xd800)
+                           (>= 1st-unit #xe000))
+                     (code-char 1st-unit)
+                     (if (< 1st-unit #xdc00)
+                       (let* ((2nd-unit (%get-unsigned-word pointer index)))
+                           (declare (type (unsigned-byte 16) 2nd-unit))
+                           (incf index)
+                           (if (and (>= 2nd-unit #xdc00)
+                                    (< 2nd-unit #xe000))
+                             (utf-16-combine-surrogate-pairs 1st-unit 2nd-unit)))))))
+            (setf (schar string i) (or char #\Replacement_Character)))))))
+    :octets-in-string-function
+    #'utf-16-octets-in-string
+    :length-of-vector-encoding-function
+    (nfunction
+     native-utf-16-length-of-vector-encoding
+     (lambda (vector start end)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+       (declare (fixnum start end))
+       (do* ((i start)
+             (j (+ 2 i) (+ 2 i))
+             (nchars 0))
+            ((> j end) (values nchars i))
+         (declare (fixnum i j nchars))
+         (let* ((code (%native-u8-ref-u16 vector i))
+                (nexti (+ i (if (or (< code #xd800)
+                                    (>= code #xdc00))
+                              2
+                              4))))
+           (declare (type (unsigned-byte 16) code)
+                    (fixnum nexti))
+           (if (> nexti end)
+             (return (values nchars i))
+             (setq i nexti nchars (1+ nchars)))))))
+    :length-of-memory-encoding-function
+    (nfunction
+     native-utf-16-length-of-memory-encoding
+     (lambda (pointer noctets start)
+       (do* ((i start)
+             (j (+ i 2) (+ i 2))
+             (end (+ start noctets))
+             (nchars 0))
+            ((> j end) (values nchars i))
+         (let* ((code (%get-unsigned-word pointer i))
+                (nexti (+ i (if (or (< code #xd800)
+                                    (>= code #xdc00))
+                              2
+                              4))))
+           (declare (type (unsigned-byte 16) code)
+                    (fixnum nexti))
+           (if (> nexti end)
+             (return (values nchars i))
+             (setq i nexti nchars (1+ nchars)))))))
+    :decode-literal-code-unit-limit #xd800  
+    :encode-literal-char-code-limit #x10000
+    :nul-encoding #(0 0)
+    :character-size-in-octets-function 'utf-16-character-size-in-octets
+    )
+
+;;; utf-16, reversed byte order
+(define-character-encoding #+big-endian-target :utf-16le #-big-endian-target :utf-16be
+   #+little-endian-target
+   "A 16-bit, variable-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+big-endian word and characters with larger codes can be encoded in a
+pair of 16-bit big-endian words.  The endianness of the encoded data
+is implicit in the encoding; byte-order-mark characters are not
+interpreted on input or prepended to output."
+  #+big-endian-target
+  "A 16-bit, variable-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+little-endian word and characters with larger codes can be encoded in
+a pair of 16-bit little-endian words.  The endianness of the encoded
+data is implicit in the encoding; byte-order-mark characters are not
+interpreted on input or prepended to output."
+  :max-units-per-char 2
+  :code-unit-size 16
+  :native-endianness nil
+  :stream-encode-function
+  #'utf-16-stream-encode
+  :stream-decode-function
+  #'utf-16-stream-decode
+  :vector-encode-function
+  (nfunction
+   reversed-utf-16-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx start end))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (declare (fixnum i))
+       (let* ((char (schar string i))
+              (code (char-code char))
+              (highbits (- code #x10000)))
+         (declare (type (mod #x110000) code)
+                  (fixnum highbits))
+         (cond ((< highbits 0)
+                (setf (%reversed-u8-ref-u16 vector idx) code)
+                (incf idx 2))
+               (t
+                (let* ((firstword (logior #xd800 (the fixnum (ash highbits -10))))
+                       (secondword (logior #xdc00 (the fixnum (logand highbits #x3ff)))))
+                  (declare (type (unsigned-byte 16) firstword secondword))
+                  (setf (%reversed-u8-ref-u16 vector idx) firstword
+                        (%reversed-u8-ref-u16 vector (the fixnum (+ idx 2))) secondword)
+                  (incf idx 4))))))))
+  :vector-decode-function
+  (nfunction
+   reversed-utf-16-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (type index idx))
+     (do* ((i 0 (1+ i))
+           (end (+ idx noctets))
+           (index idx))
+          ((= index end) index)
+       (declare (fixnum i end index))
+       (let* ((1st-unit (%reversed-u8-ref-u16 vector index)))
+         (declare (type (unsigned-byte 16) 1st-unit))
+         (incf index 2)
+         (let* ((char
+                 (if (or (< 1st-unit #xd800)
+                         (>= 1st-unit #xe000))
+                   (code-char 1st-unit)
+                   (if (< 1st-unit #xdc00)
+                     (let* ((2nd-unit (%reversed-u8-ref-u16 vector index)))
+                       (declare (type (unsigned-byte 16) 2nd-unit))
+                       (incf index 2)
+                       (if (and (>= 2nd-unit #xdc00)
+                                (< 2nd-unit #xe000))
+                         (utf-16-combine-surrogate-pairs 1st-unit 2nd-unit)))))))
+           (setf (schar string i) (or char #\Replacement_Character)))))))
+  :memory-encode-function
+  (nfunction
+   reversed-utf-16-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (highbits (- code #x10000)))
+         (declare (type (mod #x110000) code)
+                  (fixnum  highbits))
+         (cond ((< highbits 0)
+                (setf (%get-unsigned-word pointer idx) (%swap-u16 code))
+                (incf idx 2))
+               (t
+                (setf (%get-unsigned-word pointer idx) (%swap-u16 (logior #xd800 (the fixnum (ash highbits -10)))))
+                (incf idx 2)
+                (setf (%get-unsigned-word pointer idx) (%swap-u16 (logior #xdc00 (the fixnum (logand highbits #x3ff)))))
+                (incf idx 2)))))))
+  :memory-decode-function
+  (nfunction
+   reversed-utf-16-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (do* ((i 0 (1+ i))
+           (end (+ idx noctets))
+           (index idx))
+          ((>= index end) index)
+       (declare (fixnum i index end))
+       (let* ((1st-unit (%swap-u16 (%get-unsigned-word pointer index))))
+         (declare (type (unsigned-byte 16) 1st-unit))
+         (incf index 2)
+         (let* ((char
+                 (if (or (< 1st-unit #xd800)
+                         (>= 1st-unit #xe000))
+                   (code-char 1st-unit)
+                   (if (< 1st-unit #xdc00)
+                     (let* ((2nd-unit (%swap-u16 (%get-unsigned-word pointer index))))
+                       (declare (type (unsigned-byte 16) 2nd-unit))
+                       (incf index)
+                       (if (and (>= 2nd-unit #xdc00)
+                                (< 2nd-unit #xe000))
+                         (utf-16-combine-surrogate-pairs 1st-unit 2nd-unit)))))))
+           (setf (schar string i) (or char #\Replacement_Character)))))))
+  :octets-in-string-function
+  #'utf-16-octets-in-string
+  :length-of-vector-encoding-function
+  (nfunction
+   reversed-utf-16-length-of-vector-encoding
+   (lambda (vector start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+     (declare (fixnum start end))
+     (do* ((i start)
+           (j (+ 2 i) (+ 2 i))
+           (nchars 0))
+          ((> j end) (values nchars i))
+       (declare (fixnum i j nchars))
+       (let* ((code (%reversed-u8-ref-u16 vector i))
+              (nexti (+ i (if (or (< code #xd800)
+                                  (>= code #xdc00))
+                            2
+                            4))))
+         (declare (type (unsigned-byte 16) code)
+                  (fixnum nexti))
+         (if (> nexti end)
+           (return (values nchars i))
+           (setq i nexti nchars (1+ nchars)))))))
+  :length-of-memory-encoding-function
+  (nfunction
+   reversed-utf-16-length-of-memory-encoding
+   (lambda (pointer noctets start)
+     (do* ((i start)
+           (j (+ i 2) (+ i 2))
+           (end (+ start noctets))
+           (nchars 0))
+          ((> j end) (values nchars i))
+       (let* ((code (%swap-u16 (%get-unsigned-word pointer i)))
+              (nexti (+ i (if (or (< code #xd800)
+                                  (>= code #xdc00))
+                            2
+                            4))))
+         (declare (type (unsigned-byte 16) code)
+                  (fixnum nexti))
+         (if (> nexti end)
+           (return (values nchars i))
+           (setq i nexti nchars (1+ nchars)))))))
+  :decode-literal-code-unit-limit #xd800
+  :encode-literal-char-code-limit #x10000
+  :nul-encoding #(0 0)
+  :character-size-in-octets-function 'utf-16-character-size-in-octets
+  )
+
+;;; UTF-16.  Memory and vector functions determine endianness of
+;;; input by the presence of a byte-order mark (or swapped BOM)
+;;; at the beginning of input, and assume big-endian order
+;;; if this mark is missing; on output, a BOM is prepended and
+;;; things are written in native byte order.
+;;; The endianness of stream-io operations is determined by
+;;; stream content; new output streams are written in native
+;;; endianness with a BOM character prepended.  Input streams
+;;; are read in native byte order if the initial character is
+;;; a BOM, in reversed byte order if the initial character is
+;;; a swapped BOM, and in big-endian order (per RFC 2781) if
+;;; there is no BOM.
+
+(define-character-encoding :utf-16
+    "A 16-bit, variable-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+word and characters with larger codes can be encoded in a
+pair of 16-bit words.  The endianness of the encoded data is
+indicated by the endianness of a byte-order-mark character (#\u+feff)
+prepended to the data; in the absence of such a character on input,
+the data is assumed to be in big-endian order. Output is written
+in native byte-order with a leading byte-order mark."    
+  :max-units-per-char 2
+  :code-unit-size 16
+  :native-endianness t                  ;not necessarily true.
+  :stream-encode-function
+  #'utf-16-stream-encode
+  :stream-decode-function
+  #'utf-16-stream-decode
+  :vector-encode-function
+  (nfunction
+   utf-16-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (setf (%native-u8-ref-u16 vector idx) byte-order-mark-char-code)
+     (incf idx 2)
+     (do* ((i start (1+ i)))
+            ((>= i end) idx)
+         (declare (fixnum i))
+         (let* ((char (schar string i))
+                (code (char-code char))
+                (highbits (- code #x10000)))
+           (declare (type (mod #x110000) code)
+                    (fixnum highbits))
+           (cond ((< highbits 0)
+                  (setf (%native-u8-ref-u16 vector idx) code)
+                  (incf idx 2))
+                 (t
+                  (let* ((firstword (logior #xd800 (the fixnum (ash highbits -10))))
+                         (secondword (logior #xdc00 (the fixnum (logand highbits #x3ff)))))
+                    (declare (type (unsigned-byte 16) firstword secondword))
+                    (setf (%native-u8-ref-u16 vector idx) firstword
+                          (%native-u8-ref-u16 vector (the fixnum (+ idx 2))) secondword)
+                    (incf idx 4))))))))
+  :vector-decode-function
+  (nfunction
+   utf-16-vector-decode 
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 16) (*)) vector)
+              (type index idx))
+     (let* ((origin idx)
+            (swap (if (>= noctets 2)
+                    (case (%native-u8-ref-u16 vector idx)
+                      (#.byte-order-mark-char-code
+                       (incf idx 2) nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf idx 2) t)
+                      (t #+little-endian-target t)))))
+       (do* ((i 0 (1+ i))
+             (end (+ origin noctets))
+             (index idx))
+            ((= index end) index)
+         (declare (fixnum i end index))
+         (let* ((1st-unit (if swap
+                            (%reversed-u8-ref-u16 vector index)
+                            (%native-u8-ref-u16 vector index))))
+           (declare (type (unsigned-byte 16) 1st-unit))
+           (incf index 2)
+           (let* ((char
+                   (if (or (< 1st-unit #xd800)
+                           (>= 1st-unit #xe000))
+                     (code-char 1st-unit)
+                     (if (< 1st-unit #xdc00)
+                       (let* ((2nd-unit (if swap
+                                          (%reversed-u8-ref-u16 vector index)
+                                          (%native-u8-ref-u16 vector index))))
+                         (declare (type (unsigned-byte 16) 2nd-unit))
+                         (incf index 2)
+                         (if (and (>= 2nd-unit #xdc00)
+                                  (< 2nd-unit #xe000))
+                           (utf-16-combine-surrogate-pairs 1st-unit 2nd-unit)))))))
+             (setf (schar string i) (or char #\Replacement_Character))))))))
+  :memory-encode-function
+  (nfunction
+   utf-16-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     ;; Output a BOM.
+     (setf (%get-unsigned-word pointer idx) byte-order-mark-char-code)
+     (incf idx 2)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i)))
+              (highbits (- code #x10000)))
+         (declare (type (mod #x110000) code)
+                  (fixnum highbits))
+         (cond ((< highbits 0)
+                (setf (%get-unsigned-word pointer idx) code)
+                (incf idx 2))
+               (t
+                (setf (%get-unsigned-word pointer idx) (logior #xd800 (the fixnum (ash highbits -10))))
+                (setf (%get-unsigned-word pointer (the fixnum (+ idx 2)))
+                      (logior #xdc00 (the fixnum (logand highbits #x3ff))))
+                (incf idx 4)))))))
+  :memory-decode-function
+  (nfunction
+   utf-16-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (let* ((swap (when (> noctets 1)
+                    (case (%get-unsigned-word pointer idx)
+                      (#.byte-order-mark-char-code
+                       (incf idx 2)
+                       (decf noctets 2)
+                       nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf idx 2)
+                       (decf noctets 2)
+                       t)
+                      (t #+little-endian-target t)))))
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx ))
+            ((>= index end) index)
+         (declare (fixnum i index end))
+         (let* ((1st-unit (%get-unsigned-word pointer index)))
+           (declare (type (unsigned-byte 16) 1st-unit))
+           (incf index 2)
+           (if swap (setq 1st-unit (%swap-u16 1st-unit)))
+           (let* ((char
+                   (if (or (< 1st-unit #xd800)
+                           (>= 1st-unit #xe000))
+                     (code-char 1st-unit)
+                     (if (< 1st-unit #xdc00)
+                       (let* ((2nd-unit (%get-unsigned-byte pointer index)))
+                         (declare (type (unsigned-byte 16) 2nd-unit))
+                         (if swap (setq 2nd-unit (%swap-u16 2nd-unit)))
+                         (incf index 2)
+                         (if (and (>= 2nd-unit #xdc00)
+                                  (< 2nd-unit #xe000))
+                           (utf-16-combine-surrogate-pairs 1st-unit 2nd-unit)))))))
+             (setf (schar string i) (or char #\Replacement_Character))))))))
+  :octets-in-string-function
+  (nfunction
+   utf-16-bom-octets-in-string
+   (lambda (string start end)
+     (+ 2 (utf-16-octets-in-string string start end))))
+  :length-of-vector-encoding-function
+  (nfunction
+   utf-16-length-of-vector-encoding
+   (lambda (vector start end)
+     (declare (type (simple-array (unsigned-byte 16) (*)) vector))
+     (let* ((swap (when (>= end (+ start 2))
+                    (case (%native-u8-ref-u16 vector start)
+                      (#.byte-order-mark-char-code
+                       (incf start 2)
+                       nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf start 2)
+                       t)
+                      (t #+little-endian-target t)))))
+       (do* ((i start)
+             (j (+ 2 i) (+ 2 j))
+             (nchars 0))
+            ((> j end)
+             (values nchars i))
+         (let* ((code (if swap
+                        (%reversed-u8-ref-u16 vector i)
+                        (%native-u8-ref-u16 vector i)))
+                (nexti (+ i (if (or (< code #xd800)
+                                    (>= code #xdc00))
+                              2
+                              4))))
+           (declare (type (unsigned-byte 16) code)
+                    (fixnum nexti))
+           (if (> nexti end)
+             (return (values nchars i))
+             (setq i nexti nchars (1+ nchars))))))))
+  :length-of-memory-encoding-function
+  (nfunction
+   utf-16-length-of-memory-encoding
+   (lambda (pointer noctets start)
+     (declare (fixnum noctets start))
+     (when (oddp noctets)
+       (setq noctets (1- noctets)))
+     (let* ((origin start)
+            (swap (when (>= noctets 2)
+                    (case (%get-unsigned-word pointer (+ start start))
+                      (#.byte-order-mark-char-code
+                       (incf start 2)
+                       nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf start 2)
+                       t)
+                      (t #+little-endian-target t)))))
+       (declare (fixnum origin))
+       (do* ((i start)
+             (j (+ i 2) (+ i 2))
+             (end (+ origin noctets))
+             (nchars 0 (1+ nchars)))
+            ((> j end) (values nchars (- i origin)))
+         (declare (fixnum i j end nchars))
+         (let* ((code (%get-unsigned-word pointer i)))
+           (declare (type (unsigned-byte 16) code))
+           (if swap (setq code (%swap-u16 code)))
+           (let* ((nexti (+ i (if (or (< code #xd800)
+                                      (>= code #xdc00))
+                                2
+                                4))))
+             (declare (fixnum nexti))
+             (if (> nexti end)
+               (return (values nchars (- i origin)))
+               (setq i nexti))))))))
+  :decode-literal-code-unit-limit #xd800
+  :encode-literal-char-code-limit #x10000  
+  :use-byte-order-mark
+  #+big-endian-target :utf-16le
+  #+little-endian-target :utf-16be
+  :bom-encoding #+big-endian-target #(#xfe #xff) #+little-endian-target #(#xff #xfe)
+  :nul-encoding #(0 0)
+  :character-size-in-octets-function 'utf-16-character-size-in-octets  
+  )
+
+
+(defun two-octets-per-character (c)
+  (declare (ignore c))
+  2)
+
+(defun ucs-2-stream-encode (char write-function stream)
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (if (>= code #x10000)
+      (setq code (char-code #\Replacement_Character)))
+    (funcall write-function stream code)
+    1))
+
+(defun ucs-2-stream-decode (1st-unit next-unit-function stream)
+  (declare (type (unsigned-byte 16) 1st-unit)
+           (ignore next-unit-function stream))
+  ;; CODE-CHAR returns NIL on either half of a surrogate pair.
+  (or (code-char 1st-unit)
+      #\Replacement_Character))
+
+
+(defun ucs-2-octets-in-string (string start end)
+  (declare (ignore string))
+  (if (>= end start)
+    (* 2 (- end start))
+    0))
+
+(defun ucs-2-length-of-vector-encoding (vector start end)
+  (declare (ignore vector))
+  (let* ((noctets (max (- end start) 0)))
+    (values (ash noctets -1) (+ start (logandc2 noctets 1)))))
+
+(defun ucs-2-length-of-memory-encoding (pointer noctets start)
+  (declare (ignore pointer start))
+  (values (ash noctets -1) (logandc2 noctets 1)))
+
+
+
+;;; UCS-2, native byte order
+(define-character-encoding #+big-endian-target :ucs-2be #-big-endian-target :ucs-2le
+  #+big-endian-target
+  "A 16-bit, fixed-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+big-endian word. The encoded data is implicitly big-endian;
+byte-order-mark characters are not interpreted on input or prepended
+to output."
+  #+little-endian-target
+  "A 16-bit, fixed-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+little-endian word. The encoded data is implicitly little-endian;
+byte-order-mark characters are not interpreted on input or prepended
+to output."
+  :max-units-per-char 1
+  :code-unit-size 16
+  :native-endianness t
+  :stream-encode-function
+  #'ucs-2-stream-encode
+  :stream-decode-function
+  #'ucs-2-stream-decode
+  :vector-encode-function
+  (nfunction
+   native-ucs-2-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (when (>= code #x10000)
+           (setq code (char-code #\Replacement_Character)))
+         (setf (%native-u8-ref-u16 vector idx) code)
+         (incf idx 2)))))
+  :vector-decode-function
+  (nfunction
+   native-ucs-2-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (type index idx))
+     (do* ((i 0 (1+ i))
+           (end (+ idx noctets))
+           (index idx (+ 2 index)))
+          ((>= index end) index)
+       (declare (fixnum i end index))
+       (setf (schar string i)
+             (or (code-char (%native-u8-ref-u16 vector index))
+                 #\Replacement_Character)))))
+  :memory-encode-function
+  (nfunction
+   native-ucs-2-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-word pointer idx)
+                      (if (>= code #x10000)
+                        (char-code #\Replacement_Character)
+                        code))
+         (incf idx 2)))))
+  :memory-decode-function
+  (nfunction
+   native-ucs-2-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (do* ((i 0 (1+ i))
+           (index idx (+ index 2)))
+          ((>= i noctets) index)
+       (declare (fixnum i index))
+       (let* ((1st-unit (%get-unsigned-word pointer index)))
+         (declare (type (unsigned-byte 16) 1st-unit))
+         (setf (schar string i) (or (char-code 1st-unit) #\Replacement_Character))))))
+  :octets-in-string-function
+  #'ucs-2-octets-in-string
+  :length-of-vector-encoding-function
+  #'ucs-2-length-of-vector-encoding
+  :length-of-memory-encoding-function
+  #'ucs-2-length-of-memory-encoding
+  :decode-literal-code-unit-limit #x10000
+  :encode-literal-char-code-limit #x10000  
+  :nul-encoding #(0 0)
+  :character-size-in-octets-function 'two-octets-per-character
+  )
+
+;;; UCS-2, reversed byte order
+(define-character-encoding #+big-endian-target :ucs-2le #-big-endian-target :ucs-2be
+  #+little-endian-target
+  "A 16-bit, fixed-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+big-endian word. The encoded data is implicitly big-endian;
+byte-order-mark characters are not interpreted on input or prepended
+to output."
+  #+big-endian-target
+  "A 16-bit, fixed-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit
+
+little-endian word. The encoded data is implicitly little-endian;
+byte-order-mark characters are not interpreted on input or prepended
+to output."
+  :max-units-per-char 1
+  :code-unit-size 16
+  :native-endianness nil
+  :stream-encode-function
+  #'ucs-2-stream-encode
+  :stream-decode-function
+  #'ucs-2-stream-decode
+  :vector-encode-function
+  (nfunction
+   reversed-ucs-2-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (when (>= code #x10000)
+           (setq code (char-code #\Replacement_Character)))
+         (setf (%reversed-u8-ref-u16 vector idx) code)
+         (incf idx 2)))))
+  :vector-decode-function
+  (nfunction
+   reversed-ucs-2-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (type index idx))
+     (do* ((i 0 (1+ i))
+           (end (+ idx noctets))
+           (index idx (+ 2 index)))
+          ((>= index end) index)
+       (declare (fixnum i end index))
+       (setf (schar string i)
+             (or (code-char (%reversed-u8-ref-u16 vector index))
+                 #\Replacement_Character)))))
+  :memory-encode-function
+  (nfunction
+   reversed-ucs-2-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-word pointer idx)
+               (if (>= code #x10000)
+                 (%swap-u16 (char-code #\Replacement_Character))
+                 (%swap-u16 code)))
+         (incf idx 2)))))
+  :memory-decode-function
+  (nfunction
+   reversed-ucs-2-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (do* ((i 0 (1+ i))
+           (index idx (+ index 2)))
+          ((>= i noctets) index)
+       (declare (fixnum i index))
+       (let* ((1st-unit (%swap-u16 (%get-unsigned-word pointer index))))
+         (declare (type (unsigned-byte 16) 1st-unit))
+         (setf (schar string i) (or (code-char 1st-unit) #\Replacement_Character))))))
+  :octets-in-string-function
+  #'ucs-2-octets-in-string
+  :length-of-vector-encoding-function
+  #'ucs-2-length-of-vector-encoding
+  :length-of-memory-encoding-function
+  #'ucs-2-length-of-memory-encoding
+  :decode-literal-code-unit-limit #x10000
+  :encode-literal-char-code-limit #x10000
+  :nul-encoding #(0 0)
+  :character-size-in-octets-function 'two-octets-per-character
+  )
+
+(define-character-encoding :ucs-2
+    "A 16-bit, fixed-length encoding in which characters with
+CHAR-CODEs less than #x10000 can be encoded in a single 16-bit word.
+The endianness of the encoded data is indicated by the endianness of a
+byte-order-mark character (#\u+feff) prepended to the data; in the
+absence of such a character on input, the data is assumed to be in
+big-endian order."
+  :max-units-per-char 1
+  :code-unit-size 16
+  :native-endianness t                  ;not necessarily true.
+  :stream-encode-function
+  #'ucs-2-stream-encode
+  :stream-decode-function
+  #'ucs-2-stream-decode
+  :vector-encode-function
+  (nfunction
+   ucs-2-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (setf (%native-u8-ref-u16 vector idx) byte-order-mark-char-code)
+     (incf idx 2)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (when (>= code #x10000)
+           (setq code (char-code #\Replacement_Character)))
+         (setf (%native-u8-ref-u16 vector idx) code)
+         (incf idx 2)))))
+  :vector-decode-function
+  (nfunction
+   ucs-2-vector-decode 
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (type index idx)
+              (fixnum noctets))
+     (let* ((swap (if (> noctets 1)
+                    (case (%native-u8-ref-u16 vector idx)
+                      (#.byte-order-mark-char-code
+                       (incf idx 2) (decf noctets 2) nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf idx 2) (decf noctets 2) t)
+                       (t #+little-endian-target t)))))
+
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx (1+ index)))
+            ((>= index end) index)
+         (declare (fixnum i end index))
+         (let* ((1st-unit (if swap
+                            (%reversed-u8-ref-u16 vector index)
+                            (%native-u8-ref-u16 vector index))))
+             (declare (type (unsigned-byte 16) 1st-unit))
+             (setf (schar string i) (or (code-char 1st-unit) #\Replacement_Character)))))))
+  :memory-encode-function
+  (nfunction
+   ucs-2-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     (setf (%get-unsigned-word pointer idx) byte-order-mark-char-code)
+     (incf idx 2)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-word pointer idx)
+                      (if (>= code #x10000)
+                        (char-code #\Replacement_Character)
+                        code))
+         (incf idx 2)))))
+  :memory-decode-function
+  (nfunction
+   ucs-2-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (let* ((swap (when (> noctets 1)
+                    (case (%get-unsigned-word pointer idx)
+                      (#.byte-order-mark-char-code
+                       (incf idx 2)
+                       (decf noctets 2)
+                       nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf idx 2)
+                       (decf noctets 2)
+                       t)
+                      (t #+little-endian-target t)))))
+       (do* ((i 0 (1+ i))
+           (index idx (+ index 2)))
+          ((>= i noctets) index)
+       (declare (fixnum i index))
+       (let* ((1st-unit (%get-unsigned-word pointer index)))
+         (declare (type (unsigned-byte 16) 1st-unit))
+         (if swap (setq 1st-unit (%swap-u16 1st-unit)))
+         (setf (schar string i) (or (code-char 1st-unit) #\Replacement_Character)))))))
+  :octets-in-string-function
+  (nfunction
+   ucs-2-bom-octets-in-string
+   (lambda (string start end)
+     (+ 2 (ucs-2-octets-in-string string start end))))
+  :length-of-vector-encoding-function
+  (nfunction
+   ucs-2-length-of-vector-encoding
+   (lambda (vector start end)
+     (declare (fixnum start end))
+     (when (>= end (+ start 2))
+       (let* ((maybe-bom (%native-u8-ref-u16 vector start)))
+         (declare (type (unsigned-byte 16) maybe-bom))
+         (when (or (= maybe-bom byte-order-mark-char-code)
+                   (= maybe-bom swapped-byte-order-mark-char-code))
+           (incf start 2))))
+     (do* ((i start j)
+           (j (+ i 2) (+ j 2))
+           (nchars 0 (1+ nchars)))
+          ((> j end) (values nchars i)))))
+  :length-of-memory-encoding-function
+  (nfunction
+   ucs-2-length-of-memory-encoding
+   (lambda (pointer noctets start)
+     (let* ((skip 
+             (when (> noctets 1)
+               (case (%get-unsigned-word pointer start)
+                 (#.byte-order-mark-char-code
+                  2)
+                 (#.swapped-byte-order-mark-char-code
+                  2)))))
+     (values (ash (- noctets skip) -1) (logandc2 noctets 1)))))
+  :decode-literal-code-unit-limit #x10000
+  :encode-literal-char-code-limit #x10000  
+  :use-byte-order-mark
+  #+big-endian-target :ucs-2le
+  #+little-endian-target :ucs-2be
+  :nul-encoding #(0 0)
+  :character-size-in-octets-function 'two-octets-per-character
+  )
+
+
+(defun four-octets-per-character (c)
+  (declare (ignore c))
+  4)
+
+(defun ucs-4-stream-encode (char write-function stream)
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (funcall write-function stream code)
+    1))
+
+(defun ucs-4-stream-decode (1st-unit next-unit-function stream)
+  (declare (type (unsigned-byte 16) 1st-unit)
+           (ignore next-unit-function stream))
+  (code-char 1st-unit))
+
+
+(defun ucs-4-octets-in-string (string start end)
+  (declare (ignore string))
+  (if (>= end start)
+    (* 4 (- end start))
+    0))
+
+
+(declaim (inline %big-endian-u8-ref-u32 %little-endian-u8-ref-u32))
+(defun %big-endian-u8-ref-u32 (u8-vector idx)
+  (declare (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (logior (the (unsigned-byte 32) (ash (the (unsigned-byte 8) (aref u8-vector idx)) 24))
+          (the (unsigned-byte 24)
+            (logior
+             (ash (the (unsigned-byte 8) (aref u8-vector (the fixnum (1+ idx)))) 16)
+             (the (unsigned-byte 16)
+               (logior
+                (ash (the (unsigned-byte 8) (aref u8-vector (the fixnum (+ idx 2)))) 8)
+                (the (unsigned-byte 8) (aref u8-vector (the fixnum (+ idx 3))))))))))
+
+(defun %little-endian-u8-ref-u32 (u8-vector idx)
+  (declare (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (logior (the (unsigned-byte 32) (ash (the (unsigned-byte 8) (aref u8-vector (the fixnum (+ idx 3)))) 24))
+          (the (unsigned-byte 24)
+            (logior
+             (ash (the (unsigned-byte 8) (aref u8-vector (the fixnum (+ idx 2)))) 16)
+             (the (unsigned-byte 16)
+               (logior
+                (ash (the (unsigned-byte 8) (aref u8-vector (the fixnum (1+ idx)))) 8)
+                (the (unsigned-byte 8) (aref u8-vector (the fixnum idx)))))))))
+
+#+big-endian-target
+(progn
+(defmacro %native-u8-ref-u32 (vector idx)
+  `(%big-endian-u8-ref-u32 ,vector ,idx))
+
+(defmacro %reversed-u8-ref-u32 (vector idx)
+  `(%little-endian-u8-ref-u32 ,vector ,idx))
+)
+
+#+little-endian-target
+(progn
+(defmacro %native-u8-ref-u32 (vector idx)
+  `(%little-endian-u8-ref-u32 ,vector ,idx))
+
+(defmacro %reversed-u8-ref-u32 (vector idx)
+  `(%big-endian-u8-ref-u32 ,vector ,idx))
+)
+
+
+(declaim (inline (setf %big-endian-u8-ref-32) (setf %little-endian-u8-ref-u32)))
+(defun (setf %big-endian-u8-ref-u32) (val u8-vector idx)
+  (declare (type (unsigned-byte 32) val)
+           (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (setf (aref u8-vector idx) (ldb (byte 8 24) val)
+        (aref u8-vector (the fixnum (1+ idx))) (ldb (byte 8 16) val)
+        (aref u8-vector (the fixnum (+ idx 2))) (ldb (byte 8 8) val)
+        (aref u8-vector (the fixnum (+ idx 3))) (ldb (byte 8 0) val))
+  val)
+
+(defun (setf %little-endian-u8-ref-u32) (val u8-vector idx)
+  (declare (type (unsigned-byte 32) val)
+           (type (simple-array (unsigned-byte 8) (*)) u8-vector)
+           (fixnum idx))
+  (setf (aref u8-vector idx) (ldb (byte 8 0) val)
+        (aref u8-vector (the fixnum (1+ idx))) (ldb (byte 8 8) val)
+        (aref u8-vector (the fixnum (+ idx 2))) (ldb (byte 8 16) val)
+        (aref u8-vector (the fixnum (+ idx 3))) (ldb (byte 8 24) val))
+  val)
+
+
+;;; UTF-32/UCS-4, native byte order
+(define-character-encoding #+big-endian-target :utf-32be #-big-endian-target :utf-32le
+  #+big-endian-target
+  "A 32-bit, fixed-length encoding in which all Unicode characters
+encoded in a single 32-bit word. The encoded data is implicitly big-endian;
+byte-order-mark characters are not interpreted on input or prepended
+to output."
+  #+little-endian-target
+  "A 32-bit, fixed-length encoding in which all Unicode characters can
+encoded in a single 32-bit word. The encoded data is implicitly
+little-endian; byte-order-mark characters are not interpreted on input
+or prepended to output."
+  :aliases #+big-endian-target '(:ucs-4be) #+little-endian-target '(:ucs-4le)
+  :max-units-per-char 1
+  :code-unit-size 32
+  :native-endianness t
+  :stream-encode-function
+  #'ucs-4-stream-encode
+  :Stream-decode-function
+  #'ucs-4-stream-decode
+  :vector-encode-function
+  (nfunction
+   native-ucs-4-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (setf (%native-u8-ref-u32 vector idx) code)
+         (incf idx 4)))))
+  :vector-decode-function
+  (nfunction
+   native-ucs-4-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (type index idx))
+     (do* ((i 0 (1+ i))
+           (end (+ idx noctets))
+           (index idx (+ 4 index)))
+          ((>= index end) index)
+       (declare (fixnum i end index))
+       (let* ((code (%native-u8-ref-u32 vector index)))
+         (declare (type (unsigned-byte 32) code))
+         (setf (schar string i)
+               (or (if (< code char-code-limit)
+                      (code-char code))
+                   #\Replacement_Character))))))
+  :memory-encode-function
+  (nfunction
+   native-ucs-4-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-long pointer idx) code)
+         (incf idx 4)))))
+  :memory-decode-function
+  (nfunction
+   native-ucs-4-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (do* ((i 0 (1+ i))
+           (index idx (+ index 4)))
+          ((>= i noctets) index)
+       (declare (fixnum i index))
+       (let* ((1st-unit (%get-unsigned-long pointer index)))
+         (declare (type (unsigned-byte 32) 1st-unit))
+         (setf (schar string i) (or (if (< 1st-unit char-code-limit)
+                                      (code-char 1st-unit))
+                                    #\Replacement_Character))))))
+  :octets-in-string-function
+  #'ucs-4-octets-in-string
+  :length-of-vector-encoding-function
+  (nfunction
+   native-ucs-4-length-of-vector-encoding
+   (lambda (vector start end)
+     (declare (ignore vector))
+     (do* ((i start j)
+           (j (+ i 4) (+ j 4))
+           (nchars 0 (1+ nchars)))
+          ((> j end) (values nchars i)))))
+  :length-of-memory-encoding-function
+  (nfunction
+   native-ucs-4-length-of-memory-encoding
+   (lambda (pointer noctets start)
+     (declare (ignore pointer))
+     (values (ash noctets -2) (+ start (logandc2 noctets 3)))))
+  :decode-literal-code-unit-limit #x110000
+  :encode-literal-char-code-limit #x110000
+  :nul-encoding #(0 0 0 0)
+  :character-size-in-octets-function 'four-octets-per-character
+  )
+
+;;; UTF-32/UCS-4, reversed byte order
+(define-character-encoding #+big-endian-target :utf-32le #-big-endian-target :utf-32be
+  #+little-endian-target
+  "A 32-bit, fixed-length encoding in which all Unicode characters
+encoded in a single 32-bit word. The encoded data is implicitly big-endian;
+byte-order-mark characters are not interpreted on input or prepended
+to output."
+  #+big-endian-target
+  "A 32-bit, fixed-length encoding in which all Unicode characters can
+encoded in a single 32-bit word. The encoded data is implicitly
+little-endian; byte-order-mark characters are not interpreted on input
+or prepended to output."
+  :aliases #+big-endian-target '(:ucs-4le) #+little-endian-target '(:ucs-4be)
+  :max-units-per-char 1
+  :code-unit-size 32
+  :native-endianness nil
+  :stream-encode-function
+  #'ucs-4-stream-encode
+  :Stream-decode-function
+  #'ucs-4-stream-decode
+  :vector-encode-function
+  (nfunction
+   native-ucs-4-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (setf (%reversed-u8-ref-u32 vector idx) code)
+         (incf idx 4)))))
+  :vector-decode-function
+  (nfunction
+   native-ucs-4-vector-decode
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (type index idx))
+     (do* ((i 0 (1+ i))
+           (end (+ idx noctets))
+           (index idx (+ 4 index)))
+          ((>= index end) index)
+       (declare (fixnum i end index))
+       (let* ((code (%reversed-u8-ref-u32 vector index)))
+         (declare (type (unsigned-byte 32) code))
+         (setf (schar string i)
+               (or (if (< code char-code-limit)
+                     (code-char code))
+                   #\Replacement_Character))))))
+  :memory-encode-function
+  (nfunction
+   native-ucs-4-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-long pointer idx) (%swap-u32 code))
+         (incf idx 4)))))
+  :memory-decode-function
+  (nfunction
+   reversed-ucs-4-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (do* ((i 0 (1+ i))
+           (index idx (+ index 4)))
+          ((>= i noctets) index)
+       (declare (fixnum i index))
+       (let* ((1st-unit (%swap-u32 (%get-unsigned-long pointer index))))
+         (declare (type (unsigned-byte 32) 1st-unit))
+         (setf (schar string i) (or (if (< 1st-unit char-code-limit)
+                                      (code-char 1st-unit))
+                                    #\Replacement_Character))))))
+
+  :octets-in-string-function
+  #'ucs-4-octets-in-string
+  :length-of-vector-encoding-function
+  (nfunction
+   reversed-ucs-4-length-of-vector-encoding
+   (lambda (vector start end)
+     (declare (ignore vector))
+     (do* ((i start j)
+           (j (+ i 4) (+ j 4))
+           (nchars 0 (1+ nchars)))
+          ((> j end) (values nchars i)))))
+  :length-of-memory-encoding-function
+  (nfunction
+   reversed-ucs-4-length-of-memory-encoding
+   (lambda (pointer noctets start)
+     (declare (ignore pointer))
+     (values (ash noctets -2) (+ start (logandc2 noctets 3)))))
+  :decode-literal-code-unit-limit #x110000
+  :encode-literal-char-code-limit #x110000
+  :nul-encoding #(0 0 0 0)  
+  :character-size-in-octets-function 'four-octets-per-character
+  )
+
+(define-character-encoding :utf-32
+    "A 32-bit, fixed-length encoding in which all Unicode characters
+can be encoded in a single 32-bit word.  The endianness of the encoded
+data is indicated by the endianness of a byte-order-mark
+character (#\u+feff) prepended to the data; in the absence of such a
+character on input, input data is assumed to be in big-endian order.
+Output is written in native byte order with a leading byte-order
+mark."
+    
+  :aliases '(:ucs-4)
+  :max-units-per-char 1
+  :code-unit-size 32
+  :native-endianness t                  ;not necessarily true.
+  :stream-encode-function
+  #+ucs-4-stream-encode
+  :stream-decode-function
+  #'ucs-4-stream-decode
+  :vector-encode-function
+  (nfunction
+   utf-32-vector-encode
+   (lambda (string vector idx start end)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (fixnum idx))
+     (setf (%native-u8-ref-u32 vector idx) byte-order-mark-char-code)
+     (incf idx 4)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((char (schar string i))
+              (code (char-code char)))
+         (declare (type (mod #x110000) code))
+         (setf (%native-u8-ref-u32 vector idx) code)
+         (incf idx 4)))))
+  :vector-decode-function
+  (nfunction
+   utf-32-vector-decode 
+   (lambda (vector idx noctets string)
+     (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+              (type index idx)
+              (fixnum noctets))
+     (let* ((swap (if (> noctets 3)
+                    (case (%native-u8-ref-u32 vector idx)
+                      (#.byte-order-mark-char-code
+                       (incf idx 4) (decf noctets 4) nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf idx 4) (decf noctets 4) t)
+                       (t #+little-endian-target t)))))
+
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx (1+ index)))
+            ((>= index end) index)
+         (declare (fixnum i end index))
+         (let* ((1st-unit (if swap
+                            (%reversed-u8-ref-u32 vector index)
+                            (%native-u8-ref-u32 vector index))))
+             (declare (type (unsigned-byte 32) 1st-unit))
+             (setf (schar string i) (or (if (< 1st-unit char-code-limit)
+                                          (code-char 1st-unit))
+                                        #\Replacement_Character)))))))
+  :memory-encode-function
+  (nfunction
+   utf-32-memory-encode
+   (lambda (string pointer idx start end)
+     (declare (fixnum idx))
+     (setf (%get-unsigned-long pointer idx) byte-order-mark-char-code)
+     (incf idx 4)
+     (do* ((i start (1+ i)))
+          ((>= i end) idx)
+       (let* ((code (char-code (schar string i))))
+         (declare (type (mod #x110000) code))
+         (setf (%get-unsigned-long pointer idx) code)
+         (incf idx 4)))))
+  :memory-decode-function
+  (nfunction
+   utf-32-memory-decode
+   (lambda (pointer noctets idx string)
+     (declare (fixnum noctets idx))
+     (let* ((swap (when (> noctets 3)
+                    (case (%get-unsigned-long pointer idx)
+                      (#.byte-order-mark-char-code
+                       (incf idx 4)
+                       (decf noctets 4)
+                       nil)
+                      (#.swapped-byte-order-mark-char-code
+                       (incf idx 4)
+                       (decf noctets 4)
+                       t)
+                      (t #+little-endian-target t)))))
+       (do* ((i 0 (1+ i))
+           (index idx (+ index 2)))
+          ((>= i noctets) index)
+       (declare (fixnum i index))
+       (let* ((1st-unit (%get-unsigned-long pointer index)))
+         (declare (type (unsigned-byte 32) 1st-unit))
+         (if swap (setq 1st-unit (%swap-u32 1st-unit)))
+         (setf (schar string i) (or (if (< 1st-unit char-code-limit)
+                                      (code-char 1st-unit))
+                                    #\Replacement_Character)))))))
+  :octets-in-string-function
+  (nfunction
+   utf-32-bom-octets-in-string
+   (lambda (string start end)
+     (+ 4 (ucs-4-octets-in-string string start end))))
+  :length-of-vector-encoding-function
+  (nfunction
+   utf-32-length-of-vector-encoding
+   (lambda (vector start end)
+     (when (>= end (+ start 4))
+       (let* ((maybe-bom (%native-u8-ref-u32 vector start)))
+         (declare (type (unsigned-byte 32) maybe-bom))
+         (when (or (= maybe-bom byte-order-mark-char-code)
+                   (= maybe-bom swapped-byte-order-mark-char-code))
+           (incf start 4))))
+     (do* ((i start j)
+           (j (+ i 4) (+ J 4))
+           (nchars 0 (1+ nchars)))
+          ((> j end) (values nchars i)))))
+  :length-of-memory-encoding-function
+  (nfunction
+   utf-32-length-of-memory-encoding
+   (lambda (pointer noctets start)
+     (when (> noctets 3)
+       (case (%get-unsigned-long pointer )
+         (#.byte-order-mark-char-code
+          (incf start 4)
+          (decf noctets 4))
+         (#.swapped-byte-order-mark-char-code
+          (incf start 4)
+          (decf noctets 4))))
+     (values (ash noctets -2) (+ start (logandc2 noctets 3)))))
+  :decode-literal-code-unit-limit #x110000
+  :encode-literal-char-code-limit #x110000  
+  :use-byte-order-mark
+  #+big-endian-target :utf-32le
+  #+little-endian-target :utf-32be
+  :bom-encoding #+big-endian-target #(#x00 #x00 #xfe #xff) #+little-endian-target #(#xff #xfe #x00 #x00)
+  :nul-encoding #(0 0 0 0)  
+  :character-size-in-octets-function 'four-octets-per-character
+  )
+
+(defun describe-character-encoding (name)
+  (let* ((enc (lookup-character-encoding name)))
+    (when enc
+      (let* ((name (character-encoding-name enc))
+             (doc (character-encoding-documentation enc))
+             (aliases (character-encoding-aliases enc)))
+        (format t "~&~s" name)
+        (when (null (car aliases))
+          (pop aliases))
+        (when aliases
+          (format t " [Aliases:~{ ~s~}]" aliases))
+        (format t "~&~a~%~%"  doc)
+        (values)))))
+      
+(defun describe-character-encodings ()
+  (let* ((names nil))
+    (maphash #'(lambda (name enc)
+                 (when (eq name (character-encoding-name enc))
+                   (push name names)))
+             *character-encodings*)
+    (dolist (name (sort names #'string<) (values))
+      (describe-character-encoding name))))
+
+(defmethod make-load-form ((c character-encoding) &optional environment)
+  (declare (ignore environment))
+  `(get-character-encoding ,(character-encoding-name c)))
+
+(defvar *native-newline-string* (make-string 1 :initial-element #\Newline))
+(defvar *unicode-newline-string* (make-string 1 :initial-element #\Line_Separator))
+(defvar *cr-newline-string* (make-string 1 :initial-element #\Return))
+(defvar *crlf-newline-string* (make-array 2 :element-type 'character :initial-contents '(#\Return #\Linefeed)))
+(defvar *nul-string* (make-string 1 :initial-element #\Nul))
+
+(defun string-size-in-octets (string &key
+                                     (start 0)
+                                     end
+                                     external-format
+                                     use-byte-order-mark)
+  (setq end (check-sequence-bounds string start end))
+  (let* ((ef (normalize-external-format t external-format)))
+    (%string-size-in-octets string
+                            start
+                            end
+                            (get-character-encoding
+                             (external-format-character-encoding ef))
+                            (cdr (assoc (external-format-line-termination ef)
+                                        *canonical-line-termination-conventions*))
+                            use-byte-order-mark)))
+  
+
+(defun %string-size-in-octets (string start end encoding line-termination use-byte-order-mark)  
+    (declare (fixnum start end))
+    (multiple-value-bind (simple-string offset)
+        (array-data-and-offset string)
+      (declare (fixnum offset) (simple-string simple-string))
+      (incf start offset)
+      (incf end offset)
+      (let* ((n (if use-byte-order-mark
+                  (length (character-encoding-bom-encoding encoding))
+                  0))
+             (f (character-encoding-octets-in-string-function encoding))
+             (nlpos (if line-termination
+                      (position #\Newline simple-string :start start :end end))))
+        (if (not nlpos)
+          (+ n (funcall f simple-string start end))
+          (let* ((nlstring (case line-termination
+                             (:cr *cr-newline-string*)
+                             (:crlf *crlf-newline-string*)
+                             (:unicode *unicode-newline-string*)))
+                 (nlstring-length (if (eq line-termination :crlf) 2 1)))
+            (do* ()
+                 ((null nlpos) (+ n (funcall f simple-string start end)))
+              (unless (eql nlpos start)
+                (incf n (funcall f simple-string start nlpos)))
+              (incf n (funcall f nlstring 0 nlstring-length))
+              (setq start (1+ nlpos)
+                    nlpos (position #\Newline simple-string :start start :end end))))))))
+
+(defun encode-string-to-octets (string &key
+                                       (start 0)
+                                       end
+                                       external-format
+                                       use-byte-order-mark
+                                       (vector nil vector-p)
+                                       (vector-offset 0))
+  (setq end (check-sequence-bounds string start end))
+  (let* ((ef (normalize-external-format t external-format)) 
+         (encoding (get-character-encoding
+                    (external-format-character-encoding ef)))
+         (line-termination (cdr (assoc (external-format-line-termination ef)
+                                       *canonical-line-termination-conventions*)))
+         (n (%string-size-in-octets string start end encoding line-termination use-byte-order-mark)))
+    (declare (fixnum start end n))
+    (unless (and (typep vector-offset 'fixnum)
+                 (or (not vector-p)
+                     (< vector-offset (length vector))))
+      (error "Invalid vector offset ~s" vector-offset))
+    (if (not vector-p)
+      (setq vector (make-array (+ n vector-offset)
+                               :element-type '(unsigned-byte 8)))
+      (progn
+        (unless (= (typecode vector) target::subtag-u8-vector)
+          (report-bad-arg vector '(simple-array (unsigned-byte 8) (*))))
+        (unless (>= (length vector) (+ vector-offset n))
+          (error "Can't encode ~s into supplied vector ~s; ~&~d octets are needed, but only ~d are available" string vector n (- (length vector) vector-offset)))))
+    (when use-byte-order-mark
+      (let* ((bom (character-encoding-bom-encoding encoding)))
+        (dotimes (i (length bom))
+          (setf (aref vector vector-offset)
+                (aref bom i))
+          (incf vector-offset))))
+    (multiple-value-bind (simple-string offset) (array-data-and-offset string)
+      (incf start offset)
+      (incf end offset)
+      (let* ((f (character-encoding-vector-encode-function encoding))
+             (nlpos (if line-termination
+                      (position #\Newline simple-string :start start :end end))))
+        (if (null nlpos)
+          (setq vector-offset
+                (funcall f simple-string vector vector-offset start end))
+          (let* ((nlstring (case line-termination
+                             (:cr *cr-newline-string*)
+                             (:crlf *crlf-newline-string*)
+                             (:unicode *unicode-newline-string*)))
+                 (nlstring-length (if (eq line-termination :crlf) 2 1)))
+            (do* ()
+                 ((null nlpos)
+                  (setq vector-offset
+                        (funcall f simple-string vector vector-offset start end)))
+              (unless (eql nlpos start)
+                (setq vector-offset (funcall f simple-string vector vector-offset start nlpos)))
+              (setq vector-offset (funcall f nlstring vector vector-offset 0 nlstring-length))
+              (setq start (1+ nlpos)
+                    nlpos (position #\Newline simple-string :start start :end end)))))
+        (values vector vector-offset)))))
+
+
+
+(defun count-characters-in-octet-vector (vector &key
+                                                (start 0)
+                                                end
+                                                external-format)
+  (setq end (check-sequence-bounds vector start end))
+  (%count-characters-in-octet-vector
+   vector
+   start
+   end
+   (get-character-encoding (external-format-character-encoding (normalize-external-format t external-format)))))
+
+(defun %count-characters-in-octet-vector (vector start end encoding)
+  (unless (= (typecode vector) target::subtag-u8-vector)
+    (report-bad-arg vector '(simple-array (unsigned-byte 8) (*))))
+  (funcall (character-encoding-length-of-vector-encoding-function encoding)
+           vector
+           start
+           end))
+                                         
+
+(defun decode-string-from-octets (vector &key
+                                         (start 0)
+                                         end
+                                         external-format
+                                         (string nil string-p))
+  (setq end (check-sequence-bounds vector start end))
+  (unless (= (typecode vector) target::subtag-u8-vector)
+    (multiple-value-bind (array offset)
+        (array-data-and-offset vector)
+      (unless (= (typecode array) target::subtag-u8-vector)
+        (report-bad-arg vector '(array (unsgigned-byte 8) (*))))
+      (setq vector array
+            start (+ start offset)
+            end (+ end offset))))
+  (let* ((encoding (get-character-encoding
+                    (external-format-character-encoding
+                     (normalize-external-format t external-format)))))
+    (multiple-value-bind (nchars last-octet)
+        (%count-characters-in-octet-vector vector start end encoding)
+      (if (not string-p)
+        (setq string (make-string nchars))
+        (progn
+          (unless (= (typecode string) target::subtag-simple-base-string)
+            (report-bad-arg string 'simple-string))
+          (unless (>= (length string) nchars)
+            (error "String ~s is too small; ~d characters are needed."
+                   string nchars))))
+      (funcall (character-encoding-vector-decode-function encoding)
+               vector
+               start
+               (- last-octet start)
+               string)
+      (values string last-octet))))
+      
+                              
+(defun string-encoded-length-in-bytes (encoding string start end)
+  (if (typep string 'simple-base-string)
+    (funcall (character-encoding-octets-in-string-function encoding)
+             string
+             (or start 0)
+             (or end (length string)))
+    (let* ((s (string string)))
+      (multiple-value-bind (data offset) (array-data-and-offset s)
+        (funcall (character-encoding-octets-in-string-function encoding)
+                 data
+                 (+ offset (or start 0))
+                 (+ offset (or end (length s))))))))
+
+;;; Same as above, but add the length of a trailing 0 code-unit.
+(defun cstring-encoded-length-in-bytes (encoding string start end)
+  (+ (ash (character-encoding-code-unit-size encoding) -3) ; NUL terminator
+     (string-encoded-length-in-bytes encoding string start end)))
+
+                   
+
+(defun encode-string-to-memory (encoding pointer offset string start end)
+  (if (typep string 'simple-base-string)
+    (funcall (character-encoding-memory-encode-function encoding)
+             string pointer offset (or start 0) (or end (length string)))
+    (let* ((s (string string)))
+      (multiple-value-bind (data data-offset)
+          (array-data-and-offset s)
+        (funcall (character-encoding-memory-encode-function encoding)
+                 data pointer offset (+ data-offset (or start 0)) (+ data-offset (or end (length s))))))))
+
+(defun get-encoded-string (encoding-name pointer noctets)
+  (let* ((encoding (ensure-character-encoding encoding-name)))
+    (multiple-value-bind (nchars nused)
+        (funcall (character-encoding-length-of-memory-encoding-function encoding)
+                 pointer
+                 noctets
+                 0)
+      (let* ((string (make-string nchars)))
+        (funcall (character-encoding-memory-decode-function encoding)
+                 pointer
+                 nused
+                 0
+                 string)
+        string))))
+
+
+(defun get-encoded-cstring (encoding-name pointer)
+  (let* ((encoding (ensure-character-encoding encoding-name)))
+    (get-encoded-string
+     encoding
+     pointer
+     (ecase (character-encoding-code-unit-size encoding)
+       (8 (%cstrlen pointer))
+       (16 (do* ((i 0 (+ i 2)))
+                ((= 0 (%get-unsigned-word pointer i))
+                 (return i))
+             (declare (fixnum i))))
+       (32 (do* ((i 0 (+ i 4)))
+                ((= 0 (%get-unsigned-long pointer i))
+                 (return i))
+             (declare (fixnum i))))))))
+    
+
+      
+
+
+
+
+;;; This is an array of 256 integers, that (sparsely) encodes 64K bits.
+;;; (There might be as many as 256 significant bits in some of entries
+;;; in this table.)
+(defstatic *bmp-combining-bitmap*
+    #(
+	#x00
+        #x00
+        #x00
+        #xFFFF0000FFFFFFFFFFFFFFFFFFFF
+        #x37800000000000000000000000000000000
+        #x16BBFFFFFBFFFE000000000000000000000000000000000000
+        #x3D9FFFC00000000000000000000000010000003FF8000000000000000000
+        #x1FFC00000000000000000000007FFFFFF000000020000
+        
+	#x00
+        #xC0080399FD00000000000000E0000000C001E3FFFD00000000000000E
+        #x3BBFD00000000000000E0003000000003987D000000000000004
+        #x803DC7C0000000000000040000000000C0398FD00000000000000E
+        #x603DDFC00000000000000C0000000000603DDFC00000000000000E
+        #xC0000FF5F8400000000000000000C0000000000803DCFC00000000000000C
+        #x3F001BF20000000000000000000000007F8007F2000000000000
+        #x401FFFFFFFFEFF00DFFFFE000000000000C2A0000003000000
+        
+        #x3C0000003C7F00000000000
+        #x7FFFFFF0000000000003FFFFE000000000000000000000000
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #xFFFFFFFF0000000000000000C0000000C0000001C0000001C0000        
+        
+        #x2000000000000000000000000000000000000003800
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+        #x7FFFFFF0000000000000000000000000000000000000000000000000000
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+        #x600000000000000000000000000FC0000000000
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        #x00
+        
+	#x00
+        #x00
+        #x00
+        #x40000000
+        #x00
+        #x00
+        #xF0000FFFF
+        #x00))
+
+(defun is-combinable (char)
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    (when (< code #x1000)
+      (logbitp (ldb (byte 8 0) code)
+               (svref *bmp-combining-bitmap* (ldb (byte 8 8) code))))))
+
+(defstatic *bmp-combining-chars*
+  #(#\Combining_Grave_Accent 
+    #\Combining_Acute_Accent 
+    #\Combining_Circumflex_Accent 
+    #\Combining_Tilde 
+    #\Combining_Macron 
+    #\Combining_Breve 
+    #\Combining_Dot_Above 
+    #\Combining_Diaeresis 
+    #\Combining_Hook_Above 
+    #\Combining_Ring_Above 
+    #\Combining_Double_Acute_Accent 
+    #\Combining_Caron 
+    #\Combining_Double_Grave_Accent 
+    #\Combining_Inverted_Breve 
+    #\Combining_Comma_Above 
+    #\Combining_Reversed_Comma_Above 
+    #\Combining_Horn 
+    #\Combining_Dot_Below 
+    #\Combining_Diaeresis_Below 
+    #\Combining_Ring_Below 
+    #\Combining_Comma_Below 
+    #\Combining_Cedilla 
+    #\Combining_Ogonek 
+    #\Combining_Circumflex_Accent_Below 
+    #\Combining_Breve_Below 
+    #\Combining_Tilde_Below 
+    #\Combining_Macron_Below 
+    #\Combining_Long_Solidus_Overlay 
+    #\Combining_Greek_Perispomeni 
+    #\Combining_Greek_Ypogegrammeni 
+    #\Arabic_Maddah_Above 
+    #\Arabic_Hamza_Above 
+    #\Arabic_Hamza_Below 
+    #\U+093C 
+    #\U+09BE 
+    #\U+09D7 
+    #\U+0B3E 
+    #\U+0B56 
+    #\U+0B57 
+    #\U+0BBE 
+    #\U+0BD7 
+    #\U+0C56 
+    #\U+0CC2 
+    #\U+0CD5 
+    #\U+0CD6 
+    #\U+0D3E 
+    #\U+0D57 
+    #\U+0DCA 
+    #\U+0DCF 
+    #\U+0DDF 
+    #\U+102E 
+    #\U+3099 
+    #\U+309A))
+
+(defstatic *bmp-combining-base-chars*
+  #(
+    ;; #\Combining_Grave_Accent
+
+    #(#\A #\E #\I #\N #\O #\U #\W #\Y #\a #\e #\i #\n #\o #\u #\w #\y
+      #\Diaeresis #\Latin_Capital_Letter_A_With_Circumflex
+      #\Latin_Capital_Letter_E_With_Circumflex
+      #\Latin_Capital_Letter_O_With_Circumflex
+      #\Latin_Capital_Letter_U_With_Diaeresis
+      #\Latin_Small_Letter_A_With_Circumflex
+      #\Latin_Small_Letter_E_With_Circumflex
+      #\Latin_Small_Letter_O_With_Circumflex
+      #\Latin_Small_Letter_U_With_Diaeresis
+      #\Latin_Capital_Letter_A_With_Breve #\Latin_Small_Letter_A_With_Breve
+      #\Latin_Capital_Letter_E_With_Macron
+      #\Latin_Small_Letter_E_With_Macron
+      #\Latin_Capital_Letter_O_With_Macron
+      #\Latin_Small_Letter_O_With_Macron #\Latin_Capital_Letter_O_With_Horn
+      #\Latin_Small_Letter_O_With_Horn #\Latin_Capital_Letter_U_With_Horn
+      #\Latin_Small_Letter_U_With_Horn #\Greek_Capital_Letter_Alpha
+      #\Greek_Capital_Letter_Epsilon #\Greek_Capital_Letter_Eta
+      #\Greek_Capital_Letter_Iota #\Greek_Capital_Letter_Omicron
+      #\Greek_Capital_Letter_Upsilon #\Greek_Capital_Letter_Omega
+      #\Greek_Small_Letter_Alpha #\Greek_Small_Letter_Epsilon
+      #\Greek_Small_Letter_Eta #\Greek_Small_Letter_Iota
+      #\Greek_Small_Letter_Omicron #\Greek_Small_Letter_Upsilon
+      #\Greek_Small_Letter_Omega #\Greek_Small_Letter_Iota_With_Dialytika
+      #\Greek_Small_Letter_Upsilon_With_Dialytika
+      #\Cyrillic_Capital_Letter_Ie #\Cyrillic_Capital_Letter_I
+      #\Cyrillic_Small_Letter_Ie #\Cyrillic_Small_Letter_I #\U+1F00 #\U+1F01
+      #\U+1F08 #\U+1F09 #\U+1F10 #\U+1F11 #\U+1F18 #\U+1F19 #\U+1F20
+      #\U+1F21 #\U+1F28 #\U+1F29 #\U+1F30 #\U+1F31 #\U+1F38 #\U+1F39
+      #\U+1F40 #\U+1F41 #\U+1F48 #\U+1F49 #\U+1F50 #\U+1F51 #\U+1F59
+      #\U+1F60 #\U+1F61 #\U+1F68 #\U+1F69 #\U+1FBF #\U+1FFE)
+
+
+    ;; #\Combining_Acute_Accent
+
+    #(#\A #\C #\E #\G #\I #\K #\L #\M #\N #\O #\P #\R #\S #\U #\W #\Y #\Z
+      #\a #\c #\e #\g #\i #\k #\l #\m #\n #\o #\p #\r #\s #\u #\w #\y #\z
+      #\Diaeresis #\Latin_Capital_Letter_A_With_Circumflex
+      #\Latin_Capital_Letter_A_With_Ring_Above #\Latin_Capital_Letter_Ae
+      #\Latin_Capital_Letter_C_With_Cedilla
+      #\Latin_Capital_Letter_E_With_Circumflex
+      #\Latin_Capital_Letter_I_With_Diaeresis
+      #\Latin_Capital_Letter_O_With_Circumflex
+      #\Latin_Capital_Letter_O_With_Tilde
+      #\Latin_Capital_Letter_O_With_Stroke
+      #\Latin_Capital_Letter_U_With_Diaeresis
+      #\Latin_Small_Letter_A_With_Circumflex
+      #\Latin_Small_Letter_A_With_Ring_Above #\Latin_Small_Letter_Ae
+      #\Latin_Small_Letter_C_With_Cedilla
+      #\Latin_Small_Letter_E_With_Circumflex
+      #\Latin_Small_Letter_I_With_Diaeresis
+      #\Latin_Small_Letter_O_With_Circumflex
+      #\Latin_Small_Letter_O_With_Tilde #\Latin_Small_Letter_O_With_Stroke
+      #\Latin_Small_Letter_U_With_Diaeresis
+      #\Latin_Capital_Letter_A_With_Breve #\Latin_Small_Letter_A_With_Breve
+      #\Latin_Capital_Letter_E_With_Macron
+      #\Latin_Small_Letter_E_With_Macron
+      #\Latin_Capital_Letter_O_With_Macron
+      #\Latin_Small_Letter_O_With_Macron #\Latin_Capital_Letter_U_With_Tilde
+      #\Latin_Small_Letter_U_With_Tilde #\Latin_Capital_Letter_O_With_Horn
+      #\Latin_Small_Letter_O_With_Horn #\Latin_Capital_Letter_U_With_Horn
+      #\Latin_Small_Letter_U_With_Horn #\Greek_Capital_Letter_Alpha
+      #\Greek_Capital_Letter_Epsilon #\Greek_Capital_Letter_Eta
+      #\Greek_Capital_Letter_Iota #\Greek_Capital_Letter_Omicron
+      #\Greek_Capital_Letter_Upsilon #\Greek_Capital_Letter_Omega
+      #\Greek_Small_Letter_Alpha #\Greek_Small_Letter_Epsilon
+      #\Greek_Small_Letter_Eta #\Greek_Small_Letter_Iota
+      #\Greek_Small_Letter_Omicron #\Greek_Small_Letter_Upsilon
+      #\Greek_Small_Letter_Omega #\Greek_Small_Letter_Iota_With_Dialytika
+      #\Greek_Small_Letter_Upsilon_With_Dialytika
+      #\Greek_Upsilon_With_Hook_Symbol #\Cyrillic_Capital_Letter_Ghe
+      #\Cyrillic_Capital_Letter_Ka #\Cyrillic_Small_Letter_Ghe
+      #\Cyrillic_Small_Letter_Ka #\U+1F00 #\U+1F01 #\U+1F08 #\U+1F09
+      #\U+1F10 #\U+1F11 #\U+1F18 #\U+1F19 #\U+1F20 #\U+1F21 #\U+1F28
+      #\U+1F29 #\U+1F30 #\U+1F31 #\U+1F38 #\U+1F39 #\U+1F40 #\U+1F41
+      #\U+1F48 #\U+1F49 #\U+1F50 #\U+1F51 #\U+1F59 #\U+1F60 #\U+1F61
+      #\U+1F68 #\U+1F69 #\U+1FBF #\U+1FFE)
+
+
+    ;; #\Combining_Circumflex_Accent
+
+    #(#\A #\C #\E #\G #\H #\I #\J #\O #\S #\U #\W #\Y #\Z #\a #\c #\e #\g
+      #\h #\i #\j #\o #\s #\u #\w #\y #\z #\U+1EA0 #\U+1EA1 #\U+1EB8
+      #\U+1EB9 #\U+1ECC #\U+1ECD)
+
+
+    ;; #\Combining_Tilde
+
+    #(#\A #\E #\I #\N #\O #\U #\V #\Y #\a #\e #\i #\n #\o #\u #\v #\y
+      #\Latin_Capital_Letter_A_With_Circumflex
+      #\Latin_Capital_Letter_E_With_Circumflex
+      #\Latin_Capital_Letter_O_With_Circumflex
+      #\Latin_Small_Letter_A_With_Circumflex
+      #\Latin_Small_Letter_E_With_Circumflex
+      #\Latin_Small_Letter_O_With_Circumflex
+      #\Latin_Capital_Letter_A_With_Breve #\Latin_Small_Letter_A_With_Breve
+      #\Latin_Capital_Letter_O_With_Horn #\Latin_Small_Letter_O_With_Horn
+      #\Latin_Capital_Letter_U_With_Horn #\Latin_Small_Letter_U_With_Horn)
+
+
+    ;; #\Combining_Macron
+
+    #(#\A #\E #\G #\I #\O #\U #\Y #\a #\e #\g #\i #\o #\u #\y
+      #\Latin_Capital_Letter_A_With_Diaeresis #\Latin_Capital_Letter_Ae
+      #\Latin_Capital_Letter_O_With_Tilde
+      #\Latin_Capital_Letter_O_With_Diaeresis
+      #\Latin_Capital_Letter_U_With_Diaeresis
+      #\Latin_Small_Letter_A_With_Diaeresis #\Latin_Small_Letter_Ae
+      #\Latin_Small_Letter_O_With_Tilde
+      #\Latin_Small_Letter_O_With_Diaeresis
+      #\Latin_Small_Letter_U_With_Diaeresis
+      #\Latin_Capital_Letter_O_With_Ogonek
+      #\Latin_Small_Letter_O_With_Ogonek
+      #\Latin_Capital_Letter_A_With_Dot_Above
+      #\Latin_Small_Letter_A_With_Dot_Above
+      #\Latin_Capital_Letter_O_With_Dot_Above
+      #\Latin_Small_Letter_O_With_Dot_Above #\Greek_Capital_Letter_Alpha
+      #\Greek_Capital_Letter_Iota #\Greek_Capital_Letter_Upsilon
+      #\Greek_Small_Letter_Alpha #\Greek_Small_Letter_Iota
+      #\Greek_Small_Letter_Upsilon #\Cyrillic_Capital_Letter_I
+      #\Cyrillic_Capital_Letter_U #\Cyrillic_Small_Letter_I
+      #\Cyrillic_Small_Letter_U #\U+1E36 #\U+1E37 #\U+1E5A #\U+1E5B)
+
+
+    ;; #\Combining_Breve
+
+    #(#\A #\E #\G #\I #\O #\U #\a #\e #\g #\i #\o #\u
+      #\Latin_Capital_Letter_E_With_Cedilla
+      #\Latin_Small_Letter_E_With_Cedilla #\Greek_Capital_Letter_Alpha
+      #\Greek_Capital_Letter_Iota #\Greek_Capital_Letter_Upsilon
+      #\Greek_Small_Letter_Alpha #\Greek_Small_Letter_Iota
+      #\Greek_Small_Letter_Upsilon #\Cyrillic_Capital_Letter_A
+      #\Cyrillic_Capital_Letter_Ie #\Cyrillic_Capital_Letter_Zhe
+      #\Cyrillic_Capital_Letter_I #\Cyrillic_Capital_Letter_U
+      #\Cyrillic_Small_Letter_A #\Cyrillic_Small_Letter_Ie
+      #\Cyrillic_Small_Letter_Zhe #\Cyrillic_Small_Letter_I
+      #\Cyrillic_Small_Letter_U #\U+1EA0 #\U+1EA1)
+
+
+    ;; #\Combining_Dot_Above
+
+    #(#\A #\B #\C #\D #\E #\F #\G #\H #\I #\M #\N #\O #\P #\R #\S #\T #\W
+      #\X #\Y #\Z #\a #\b #\c #\d #\e #\f #\g #\h #\m #\n #\o #\p #\r #\s
+      #\t #\w #\x #\y #\z #\Latin_Capital_Letter_S_With_Acute
+      #\Latin_Small_Letter_S_With_Acute #\Latin_Capital_Letter_S_With_Caron
+      #\Latin_Small_Letter_S_With_Caron #\Latin_Small_Letter_Long_S #\U+1E62
+      #\U+1E63)
+
+
+    ;; #\Combining_Diaeresis
+
+    #(#\A #\E #\H #\I #\O #\U #\W #\X #\Y #\a #\e #\h #\i #\o #\t #\u #\w
+      #\x #\y #\Latin_Capital_Letter_O_With_Tilde
+      #\Latin_Small_Letter_O_With_Tilde #\Latin_Capital_Letter_U_With_Macron
+      #\Latin_Small_Letter_U_With_Macron #\Greek_Capital_Letter_Iota
+      #\Greek_Capital_Letter_Upsilon #\Greek_Small_Letter_Iota
+      #\Greek_Small_Letter_Upsilon #\Greek_Upsilon_With_Hook_Symbol
+      #\Cyrillic_Capital_Letter_Byelorussian-Ukrainian_I
+      #\Cyrillic_Capital_Letter_A #\Cyrillic_Capital_Letter_Ie
+      #\Cyrillic_Capital_Letter_Zhe #\Cyrillic_Capital_Letter_Ze
+      #\Cyrillic_Capital_Letter_I #\Cyrillic_Capital_Letter_O
+      #\Cyrillic_Capital_Letter_U #\Cyrillic_Capital_Letter_Che
+      #\Cyrillic_Capital_Letter_Yeru #\Cyrillic_Capital_Letter_E
+      #\Cyrillic_Small_Letter_A #\Cyrillic_Small_Letter_Ie
+      #\Cyrillic_Small_Letter_Zhe #\Cyrillic_Small_Letter_Ze
+      #\Cyrillic_Small_Letter_I #\Cyrillic_Small_Letter_O
+      #\Cyrillic_Small_Letter_U #\Cyrillic_Small_Letter_Che
+      #\Cyrillic_Small_Letter_Yeru #\Cyrillic_Small_Letter_E
+      #\Cyrillic_Small_Letter_Byelorussian-Ukrainian_I
+      #\Cyrillic_Capital_Letter_Schwa #\Cyrillic_Small_Letter_Schwa
+      #\Cyrillic_Capital_Letter_Barred_O #\Cyrillic_Small_Letter_Barred_O)
+
+
+    ;; #\Combining_Hook_Above
+
+    #(#\A #\E #\I #\O #\U #\Y #\a #\e #\i #\o #\u #\y
+      #\Latin_Capital_Letter_A_With_Circumflex
+      #\Latin_Capital_Letter_E_With_Circumflex
+      #\Latin_Capital_Letter_O_With_Circumflex
+      #\Latin_Small_Letter_A_With_Circumflex
+      #\Latin_Small_Letter_E_With_Circumflex
+      #\Latin_Small_Letter_O_With_Circumflex
+      #\Latin_Capital_Letter_A_With_Breve #\Latin_Small_Letter_A_With_Breve
+      #\Latin_Capital_Letter_O_With_Horn #\Latin_Small_Letter_O_With_Horn
+      #\Latin_Capital_Letter_U_With_Horn #\Latin_Small_Letter_U_With_Horn)
+
+
+    ;; #\Combining_Ring_Above
+
+    #(#\A #\U #\a #\u #\w #\y)
+
+
+    ;; #\Combining_Double_Acute_Accent
+
+    #(#\O #\U #\o #\u #\Cyrillic_Capital_Letter_U
+      #\Cyrillic_Small_Letter_U)
+
+
+    ;; #\Combining_Caron
+
+    #(#\A #\C #\D #\E #\G #\H #\I #\K #\L #\N #\O #\R #\S #\T #\U #\Z #\a
+      #\c #\d #\e #\g #\h #\i #\j #\k #\l #\n #\o #\r #\s #\t #\u #\z
+      #\Latin_Capital_Letter_U_With_Diaeresis
+      #\Latin_Small_Letter_U_With_Diaeresis #\Latin_Capital_Letter_Ezh
+      #\Latin_Small_Letter_Ezh)
+
+
+    ;; #\Combining_Double_Grave_Accent
+
+    #(#\A #\E #\I #\O #\R #\U #\a #\e #\i #\o #\r #\u
+      #\Cyrillic_Capital_Letter_Izhitsa #\Cyrillic_Small_Letter_Izhitsa)
+
+
+    ;; #\Combining_Inverted_Breve
+
+    #(#\A #\E #\I #\O #\R #\U #\a #\e #\i #\o #\r #\u)
+
+
+    ;; #\Combining_Comma_Above
+
+    #(#\Greek_Capital_Letter_Alpha #\Greek_Capital_Letter_Epsilon
+      #\Greek_Capital_Letter_Eta #\Greek_Capital_Letter_Iota
+      #\Greek_Capital_Letter_Omicron #\Greek_Capital_Letter_Omega
+      #\Greek_Small_Letter_Alpha #\Greek_Small_Letter_Epsilon
+      #\Greek_Small_Letter_Eta #\Greek_Small_Letter_Iota
+      #\Greek_Small_Letter_Omicron #\Greek_Small_Letter_Rho
+      #\Greek_Small_Letter_Upsilon #\Greek_Small_Letter_Omega)
+
+
+    ;; #\Combining_Reversed_Comma_Above
+
+    #(#\Greek_Capital_Letter_Alpha #\Greek_Capital_Letter_Epsilon
+      #\Greek_Capital_Letter_Eta #\Greek_Capital_Letter_Iota
+      #\Greek_Capital_Letter_Omicron #\Greek_Capital_Letter_Rho
+      #\Greek_Capital_Letter_Upsilon #\Greek_Capital_Letter_Omega
+      #\Greek_Small_Letter_Alpha #\Greek_Small_Letter_Epsilon
+      #\Greek_Small_Letter_Eta #\Greek_Small_Letter_Iota
+      #\Greek_Small_Letter_Omicron #\Greek_Small_Letter_Rho
+      #\Greek_Small_Letter_Upsilon #\Greek_Small_Letter_Omega)
+
+
+    ;; #\Combining_Horn
+
+    #(#\O #\U #\o #\u)
+
+
+    ;; #\Combining_Dot_Below
+
+    #(#\A #\B #\D #\E #\H #\I #\K #\L #\M #\N #\O #\R #\S #\T #\U #\V #\W
+      #\Y #\Z #\a #\b #\d #\e #\h #\i #\k #\l #\m #\n #\o #\r #\s #\t #\u
+      #\v #\w #\y #\z #\Latin_Capital_Letter_O_With_Horn
+      #\Latin_Small_Letter_O_With_Horn #\Latin_Capital_Letter_U_With_Horn
+      #\Latin_Small_Letter_U_With_Horn)
+
+
+    ;; #\Combining_Diaeresis_Below
+
+    #(#\U #\u)
+
+
+    ;; #\Combining_Ring_Below
+
+    #(#\A #\a)
+
+
+    ;; #\Combining_Comma_Below
+
+    #(#\S #\T #\s #\t)
+
+
+    ;; #\Combining_Cedilla
+
+    #(#\C #\D #\E #\G #\H #\K #\L #\N #\R #\S #\T #\c #\d #\e #\g #\h #\k
+      #\l #\n #\r #\s #\t)
+
+
+    ;; #\Combining_Ogonek
+
+    #(#\A #\E #\I #\O #\U #\a #\e #\i #\o #\u)
+
+
+    ;; #\Combining_Circumflex_Accent_Below
+
+    #(#\D #\E #\L #\N #\T #\U #\d #\e #\l #\n #\t #\u)
+
+
+    ;; #\Combining_Breve_Below
+
+    #(#\H #\h)
+
+
+    ;; #\Combining_Tilde_Below
+
+    #(#\E #\I #\U #\e #\i #\u)
+
+
+    ;; #\Combining_Macron_Below
+
+    #(#\B #\D #\K #\L #\N #\R #\T #\Z #\b #\d #\h #\k #\l #\n #\r #\t #\z)
+
+
+    ;; #\Combining_Long_Solidus_Overlay
+
+    #(#\< #\= #\> #\U+2190 #\U+2192 #\U+2194 #\U+21D0 #\U+21D2 #\U+21D4
+      #\U+2203 #\U+2208 #\U+220B #\U+2223 #\U+2225 #\U+223C #\U+2243
+      #\U+2245 #\U+2248 #\U+224D #\U+2261 #\U+2264 #\U+2265 #\U+2272
+      #\U+2273 #\U+2276 #\U+2277 #\U+227A #\U+227B #\U+227C #\U+227D
+      #\U+2282 #\U+2283 #\U+2286 #\U+2287 #\U+2291 #\U+2292 #\U+22A2
+      #\U+22A8 #\U+22A9 #\U+22AB #\U+22B2 #\U+22B3 #\U+22B4 #\U+22B5)
+
+
+    ;; #\Combining_Greek_Perispomeni
+
+    #(#\Diaeresis #\Greek_Small_Letter_Alpha #\Greek_Small_Letter_Eta
+      #\Greek_Small_Letter_Iota #\Greek_Small_Letter_Upsilon
+      #\Greek_Small_Letter_Omega #\Greek_Small_Letter_Iota_With_Dialytika
+      #\Greek_Small_Letter_Upsilon_With_Dialytika #\U+1F00 #\U+1F01 #\U+1F08
+      #\U+1F09 #\U+1F20 #\U+1F21 #\U+1F28 #\U+1F29 #\U+1F30 #\U+1F31
+      #\U+1F38 #\U+1F39 #\U+1F50 #\U+1F51 #\U+1F59 #\U+1F60 #\U+1F61
+      #\U+1F68 #\U+1F69 #\U+1FBF #\U+1FFE)
+
+
+    ;; #\Combining_Greek_Ypogegrammeni
+
+    #(#\Greek_Capital_Letter_Alpha #\Greek_Capital_Letter_Eta
+      #\Greek_Capital_Letter_Omega #\Greek_Small_Letter_Alpha_With_Tonos
+      #\Greek_Small_Letter_Eta_With_Tonos #\Greek_Small_Letter_Alpha
+      #\Greek_Small_Letter_Eta #\Greek_Small_Letter_Omega
+      #\Greek_Small_Letter_Omega_With_Tonos #\U+1F00 #\U+1F01 #\U+1F02
+      #\U+1F03 #\U+1F04 #\U+1F05 #\U+1F06 #\U+1F07 #\U+1F08 #\U+1F09
+      #\U+1F0A #\U+1F0B #\U+1F0C #\U+1F0D #\U+1F0E #\U+1F0F #\U+1F20
+      #\U+1F21 #\U+1F22 #\U+1F23 #\U+1F24 #\U+1F25 #\U+1F26 #\U+1F27
+      #\U+1F28 #\U+1F29 #\U+1F2A #\U+1F2B #\U+1F2C #\U+1F2D #\U+1F2E
+      #\U+1F2F #\U+1F60 #\U+1F61 #\U+1F62 #\U+1F63 #\U+1F64 #\U+1F65
+      #\U+1F66 #\U+1F67 #\U+1F68 #\U+1F69 #\U+1F6A #\U+1F6B #\U+1F6C
+      #\U+1F6D #\U+1F6E #\U+1F6F #\U+1F70 #\U+1F74 #\U+1F7C #\U+1FB6
+      #\U+1FC6 #\U+1FF6)
+
+
+    ;; #\Arabic_Maddah_Above
+
+    #(#\Arabic_Letter_Alef)
+
+
+    ;; #\Arabic_Hamza_Above
+
+    #(#\Arabic_Letter_Alef #\Arabic_Letter_Waw #\Arabic_Letter_Yeh
+      #\Arabic_Letter_Heh_Goal #\Arabic_Letter_Yeh_Barree
+      #\Arabic_Letter_Ae)
+
+
+    ;; #\Arabic_Hamza_Below
+
+    #(#\Arabic_Letter_Alef)
+
+
+    ;; #\U+093C
+
+    #(#\U+0928 #\U+0930 #\U+0933)
+
+
+    ;; #\U+09BE
+
+    #(#\U+09C7)
+
+
+    ;; #\U+09D7
+
+    #(#\U+09C7)
+
+
+    ;; #\U+0B3E
+
+    #(#\U+0B47)
+
+
+    ;; #\U+0B56
+
+    #(#\U+0B47)
+
+
+    ;; #\U+0B57
+
+    #(#\U+0B47)
+
+
+    ;; #\U+0BBE
+
+    #(#\U+0BC6 #\U+0BC7)
+
+
+    ;; #\U+0BD7
+
+    #(#\U+0B92 #\U+0BC6)
+
+
+    ;; #\U+0C56
+
+    #(#\U+0C46)
+
+
+    ;; #\U+0CC2
+
+    #(#\U+0CC6)
+
+
+    ;; #\U+0CD5
+
+    #(#\U+0CBF #\U+0CC6 #\U+0CCA)
+
+
+    ;; #\U+0CD6
+
+    #(#\U+0CC6)
+
+
+    ;; #\U+0D3E
+
+    #(#\U+0D46 #\U+0D47)
+
+
+    ;; #\U+0D57
+
+    #(#\U+0D46)
+
+
+    ;; #\U+0DCA
+
+    #(#\U+0DD9 #\U+0DDC)
+
+
+    ;; #\U+0DCF
+
+    #(#\U+0DD9)
+
+
+    ;; #\U+0DDF
+
+    #(#\U+0DD9)
+
+
+    ;; #\U+102E
+
+    #(#\U+1025)
+
+
+    ;; #\U+3099
+
+    #(#\U+3046 #\U+304B #\U+304D #\U+304F #\U+3051 #\U+3053 #\U+3055
+      #\U+3057 #\U+3059 #\U+305B #\U+305D #\U+305F #\U+3061 #\U+3064
+      #\U+3066 #\U+3068 #\U+306F #\U+3072 #\U+3075 #\U+3078 #\U+307B
+      #\U+309D #\U+30A6 #\U+30AB #\U+30AD #\U+30AF #\U+30B1 #\U+30B3
+      #\U+30B5 #\U+30B7 #\U+30B9 #\U+30BB #\U+30BD #\U+30BF #\U+30C1
+      #\U+30C4 #\U+30C6 #\U+30C8 #\U+30CF #\U+30D2 #\U+30D5 #\U+30D8
+      #\U+30DB #\U+30EF #\U+30F0 #\U+30F1 #\U+30F2 #\U+30FD)
+
+
+    ;; #\U+309A
+
+    #(#\U+306F #\U+3072 #\U+3075 #\U+3078 #\U+307B #\U+30CF #\U+30D2
+      #\U+30D5 #\U+30D8 #\U+30DB)
+    ))
+
+(defstatic *bmp-precombined-chars*
+  #(
+
+    ;; #\Combining_Grave_Accent
+
+    #(#\Latin_Capital_Letter_A_With_Grave
+      #\Latin_Capital_Letter_E_With_Grave
+      #\Latin_Capital_Letter_I_With_Grave
+      #\Latin_Capital_Letter_N_With_Grave
+      #\Latin_Capital_Letter_O_With_Grave
+      #\Latin_Capital_Letter_U_With_Grave #\U+1E80 #\U+1EF2
+      #\Latin_Small_Letter_A_With_Grave #\Latin_Small_Letter_E_With_Grave
+      #\Latin_Small_Letter_I_With_Grave #\Latin_Small_Letter_N_With_Grave
+      #\Latin_Small_Letter_O_With_Grave #\Latin_Small_Letter_U_With_Grave
+      #\U+1E81 #\U+1EF3 #\U+1FED #\U+1EA6 #\U+1EC0 #\U+1ED2
+      #\Latin_Capital_Letter_U_With_Diaeresis_And_Grave #\U+1EA7 #\U+1EC1
+      #\U+1ED3 #\Latin_Small_Letter_U_With_Diaeresis_And_Grave #\U+1EB0
+      #\U+1EB1 #\U+1E14 #\U+1E15 #\U+1E50 #\U+1E51 #\U+1EDC #\U+1EDD
+      #\U+1EEA #\U+1EEB #\U+1FBA #\U+1FC8 #\U+1FCA #\U+1FDA #\U+1FF8
+      #\U+1FEA #\U+1FFA #\U+1F70 #\U+1F72 #\U+1F74 #\U+1F76 #\U+1F78
+      #\U+1F7A #\U+1F7C #\U+1FD2 #\U+1FE2
+      #\Cyrillic_Capital_Letter_Ie_With_Grave
+      #\Cyrillic_Capital_Letter_I_With_Grave
+      #\Cyrillic_Small_Letter_Ie_With_Grave
+      #\Cyrillic_Small_Letter_I_With_Grave #\U+1F02 #\U+1F03 #\U+1F0A
+      #\U+1F0B #\U+1F12 #\U+1F13 #\U+1F1A #\U+1F1B #\U+1F22 #\U+1F23
+      #\U+1F2A #\U+1F2B #\U+1F32 #\U+1F33 #\U+1F3A #\U+1F3B #\U+1F42
+      #\U+1F43 #\U+1F4A #\U+1F4B #\U+1F52 #\U+1F53 #\U+1F5B #\U+1F62
+      #\U+1F63 #\U+1F6A #\U+1F6B #\U+1FCD #\U+1FDD)
+
+
+    ;; #\Combining_Acute_Accent
+
+    #(#\Latin_Capital_Letter_A_With_Acute
+      #\Latin_Capital_Letter_C_With_Acute
+      #\Latin_Capital_Letter_E_With_Acute
+      #\Latin_Capital_Letter_G_With_Acute
+      #\Latin_Capital_Letter_I_With_Acute #\U+1E30
+      #\Latin_Capital_Letter_L_With_Acute #\U+1E3E
+      #\Latin_Capital_Letter_N_With_Acute
+      #\Latin_Capital_Letter_O_With_Acute #\U+1E54
+      #\Latin_Capital_Letter_R_With_Acute
+      #\Latin_Capital_Letter_S_With_Acute
+      #\Latin_Capital_Letter_U_With_Acute #\U+1E82
+      #\Latin_Capital_Letter_Y_With_Acute
+      #\Latin_Capital_Letter_Z_With_Acute #\Latin_Small_Letter_A_With_Acute
+      #\Latin_Small_Letter_C_With_Acute #\Latin_Small_Letter_E_With_Acute
+      #\Latin_Small_Letter_G_With_Acute #\Latin_Small_Letter_I_With_Acute
+      #\U+1E31 #\Latin_Small_Letter_L_With_Acute #\U+1E3F
+      #\Latin_Small_Letter_N_With_Acute #\Latin_Small_Letter_O_With_Acute
+      #\U+1E55 #\Latin_Small_Letter_R_With_Acute
+      #\Latin_Small_Letter_S_With_Acute #\Latin_Small_Letter_U_With_Acute
+      #\U+1E83 #\Latin_Small_Letter_Y_With_Acute
+      #\Latin_Small_Letter_Z_With_Acute #\Greek_Dialytika_Tonos #\U+1EA4
+      #\Latin_Capital_Letter_A_With_Ring_Above_And_Acute
+      #\Latin_Capital_Letter_Ae_With_Acute #\U+1E08 #\U+1EBE #\U+1E2E
+      #\U+1ED0 #\U+1E4C #\Latin_Capital_Letter_O_With_Stroke_And_Acute
+      #\Latin_Capital_Letter_U_With_Diaeresis_And_Acute #\U+1EA5
+      #\Latin_Small_Letter_A_With_Ring_Above_And_Acute
+      #\Latin_Small_Letter_Ae_With_Acute #\U+1E09 #\U+1EBF #\U+1E2F #\U+1ED1
+      #\U+1E4D #\Latin_Small_Letter_O_With_Stroke_And_Acute
+      #\Latin_Small_Letter_U_With_Diaeresis_And_Acute #\U+1EAE #\U+1EAF
+      #\U+1E16 #\U+1E17 #\U+1E52 #\U+1E53 #\U+1E78 #\U+1E79 #\U+1EDA
+      #\U+1EDB #\U+1EE8 #\U+1EE9 #\Greek_Capital_Letter_Alpha_With_Tonos
+      #\Greek_Capital_Letter_Epsilon_With_Tonos
+      #\Greek_Capital_Letter_Eta_With_Tonos
+      #\Greek_Capital_Letter_Iota_With_Tonos
+      #\Greek_Capital_Letter_Omicron_With_Tonos
+      #\Greek_Capital_Letter_Upsilon_With_Tonos
+      #\Greek_Capital_Letter_Omega_With_Tonos
+      #\Greek_Small_Letter_Alpha_With_Tonos
+      #\Greek_Small_Letter_Epsilon_With_Tonos
+      #\Greek_Small_Letter_Eta_With_Tonos
+      #\Greek_Small_Letter_Iota_With_Tonos
+      #\Greek_Small_Letter_Omicron_With_Tonos
+      #\Greek_Small_Letter_Upsilon_With_Tonos
+      #\Greek_Small_Letter_Omega_With_Tonos
+      #\Greek_Small_Letter_Iota_With_Dialytika_And_Tonos
+      #\Greek_Small_Letter_Upsilon_With_Dialytika_And_Tonos
+      #\Greek_Upsilon_With_Acute_And_Hook_Symbol
+      #\Cyrillic_Capital_Letter_Gje #\Cyrillic_Capital_Letter_Kje
+      #\Cyrillic_Small_Letter_Gje #\Cyrillic_Small_Letter_Kje #\U+1F04
+      #\U+1F05 #\U+1F0C #\U+1F0D #\U+1F14 #\U+1F15 #\U+1F1C #\U+1F1D
+      #\U+1F24 #\U+1F25 #\U+1F2C #\U+1F2D #\U+1F34 #\U+1F35 #\U+1F3C
+      #\U+1F3D #\U+1F44 #\U+1F45 #\U+1F4C #\U+1F4D #\U+1F54 #\U+1F55
+      #\U+1F5D #\U+1F64 #\U+1F65 #\U+1F6C #\U+1F6D #\U+1FCE #\U+1FDE)
+
+
+    ;; #\Combining_Circumflex_Accent
+
+    #(#\Latin_Capital_Letter_A_With_Circumflex
+      #\Latin_Capital_Letter_C_With_Circumflex
+      #\Latin_Capital_Letter_E_With_Circumflex
+      #\Latin_Capital_Letter_G_With_Circumflex
+      #\Latin_Capital_Letter_H_With_Circumflex
+      #\Latin_Capital_Letter_I_With_Circumflex
+      #\Latin_Capital_Letter_J_With_Circumflex
+      #\Latin_Capital_Letter_O_With_Circumflex
+      #\Latin_Capital_Letter_S_With_Circumflex
+      #\Latin_Capital_Letter_U_With_Circumflex
+      #\Latin_Capital_Letter_W_With_Circumflex
+      #\Latin_Capital_Letter_Y_With_Circumflex #\U+1E90
+      #\Latin_Small_Letter_A_With_Circumflex
+      #\Latin_Small_Letter_C_With_Circumflex
+      #\Latin_Small_Letter_E_With_Circumflex
+      #\Latin_Small_Letter_G_With_Circumflex
+      #\Latin_Small_Letter_H_With_Circumflex
+      #\Latin_Small_Letter_I_With_Circumflex
+      #\Latin_Small_Letter_J_With_Circumflex
+      #\Latin_Small_Letter_O_With_Circumflex
+      #\Latin_Small_Letter_S_With_Circumflex
+      #\Latin_Small_Letter_U_With_Circumflex
+      #\Latin_Small_Letter_W_With_Circumflex
+      #\Latin_Small_Letter_Y_With_Circumflex #\U+1E91 #\U+1EAC #\U+1EAD
+      #\U+1EC6 #\U+1EC7 #\U+1ED8 #\U+1ED9)
+
+
+    ;; #\Combining_Tilde
+
+    #(#\Latin_Capital_Letter_A_With_Tilde #\U+1EBC
+      #\Latin_Capital_Letter_I_With_Tilde
+      #\Latin_Capital_Letter_N_With_Tilde
+      #\Latin_Capital_Letter_O_With_Tilde
+      #\Latin_Capital_Letter_U_With_Tilde #\U+1E7C #\U+1EF8
+      #\Latin_Small_Letter_A_With_Tilde #\U+1EBD
+      #\Latin_Small_Letter_I_With_Tilde #\Latin_Small_Letter_N_With_Tilde
+      #\Latin_Small_Letter_O_With_Tilde #\Latin_Small_Letter_U_With_Tilde
+      #\U+1E7D #\U+1EF9 #\U+1EAA #\U+1EC4 #\U+1ED6 #\U+1EAB #\U+1EC5
+      #\U+1ED7 #\U+1EB4 #\U+1EB5 #\U+1EE0 #\U+1EE1 #\U+1EEE #\U+1EEF)
+
+
+    ;; #\Combining_Macron
+
+    #(#\Latin_Capital_Letter_A_With_Macron
+      #\Latin_Capital_Letter_E_With_Macron #\U+1E20
+      #\Latin_Capital_Letter_I_With_Macron
+      #\Latin_Capital_Letter_O_With_Macron
+      #\Latin_Capital_Letter_U_With_Macron
+      #\Latin_Capital_Letter_Y_With_Macron
+      #\Latin_Small_Letter_A_With_Macron #\Latin_Small_Letter_E_With_Macron
+      #\U+1E21 #\Latin_Small_Letter_I_With_Macron
+      #\Latin_Small_Letter_O_With_Macron #\Latin_Small_Letter_U_With_Macron
+      #\Latin_Small_Letter_Y_With_Macron
+      #\Latin_Capital_Letter_A_With_Diaeresis_And_Macron
+      #\Latin_Capital_Letter_Ae_With_Macron
+      #\Latin_Capital_Letter_O_With_Tilde_And_Macron
+      #\Latin_Capital_Letter_O_With_Diaeresis_And_Macron
+      #\Latin_Capital_Letter_U_With_Diaeresis_And_Macron
+      #\Latin_Small_Letter_A_With_Diaeresis_And_Macron
+      #\Latin_Small_Letter_Ae_With_Macron
+      #\Latin_Small_Letter_O_With_Tilde_And_Macron
+      #\Latin_Small_Letter_O_With_Diaeresis_And_Macron
+      #\Latin_Small_Letter_U_With_Diaeresis_And_Macron
+      #\Latin_Capital_Letter_O_With_Ogonek_And_Macron
+      #\Latin_Small_Letter_O_With_Ogonek_And_Macron
+      #\Latin_Capital_Letter_A_With_Dot_Above_And_Macron
+      #\Latin_Small_Letter_A_With_Dot_Above_And_Macron
+      #\Latin_Capital_Letter_O_With_Dot_Above_And_Macron
+      #\Latin_Small_Letter_O_With_Dot_Above_And_Macron #\U+1FB9 #\U+1FD9
+      #\U+1FE9 #\U+1FB1 #\U+1FD1 #\U+1FE1
+      #\Cyrillic_Capital_Letter_I_With_Macron
+      #\Cyrillic_Capital_Letter_U_With_Macron
+      #\Cyrillic_Small_Letter_I_With_Macron
+      #\Cyrillic_Small_Letter_U_With_Macron #\U+1E38 #\U+1E39 #\U+1E5C
+      #\U+1E5D)
+
+
+    ;; #\Combining_Breve
+
+    #(#\Latin_Capital_Letter_A_With_Breve
+      #\Latin_Capital_Letter_E_With_Breve
+      #\Latin_Capital_Letter_G_With_Breve
+      #\Latin_Capital_Letter_I_With_Breve
+      #\Latin_Capital_Letter_O_With_Breve
+      #\Latin_Capital_Letter_U_With_Breve #\Latin_Small_Letter_A_With_Breve
+      #\Latin_Small_Letter_E_With_Breve #\Latin_Small_Letter_G_With_Breve
+      #\Latin_Small_Letter_I_With_Breve #\Latin_Small_Letter_O_With_Breve
+      #\Latin_Small_Letter_U_With_Breve #\U+1E1C #\U+1E1D #\U+1FB8 #\U+1FD8
+      #\U+1FE8 #\U+1FB0 #\U+1FD0 #\U+1FE0
+      #\Cyrillic_Capital_Letter_A_With_Breve
+      #\Cyrillic_Capital_Letter_Ie_With_Breve
+      #\Cyrillic_Capital_Letter_Zhe_With_Breve
+      #\Cyrillic_Capital_Letter_Short_I #\Cyrillic_Capital_Letter_Short_U
+      #\Cyrillic_Small_Letter_A_With_Breve
+      #\Cyrillic_Small_Letter_Ie_With_Breve
+      #\Cyrillic_Small_Letter_Zhe_With_Breve #\Cyrillic_Small_Letter_Short_I
+      #\Cyrillic_Small_Letter_Short_U #\U+1EB6 #\U+1EB7)
+
+
+    ;; #\Combining_Dot_Above
+
+    #(#\Latin_Capital_Letter_A_With_Dot_Above #\U+1E02
+      #\Latin_Capital_Letter_C_With_Dot_Above #\U+1E0A
+      #\Latin_Capital_Letter_E_With_Dot_Above #\U+1E1E
+      #\Latin_Capital_Letter_G_With_Dot_Above #\U+1E22
+      #\Latin_Capital_Letter_I_With_Dot_Above #\U+1E40 #\U+1E44
+      #\Latin_Capital_Letter_O_With_Dot_Above #\U+1E56 #\U+1E58 #\U+1E60
+      #\U+1E6A #\U+1E86 #\U+1E8A #\U+1E8E
+      #\Latin_Capital_Letter_Z_With_Dot_Above
+      #\Latin_Small_Letter_A_With_Dot_Above #\U+1E03
+      #\Latin_Small_Letter_C_With_Dot_Above #\U+1E0B
+      #\Latin_Small_Letter_E_With_Dot_Above #\U+1E1F
+      #\Latin_Small_Letter_G_With_Dot_Above #\U+1E23 #\U+1E41 #\U+1E45
+      #\Latin_Small_Letter_O_With_Dot_Above #\U+1E57 #\U+1E59 #\U+1E61
+      #\U+1E6B #\U+1E87 #\U+1E8B #\U+1E8F
+      #\Latin_Small_Letter_Z_With_Dot_Above #\U+1E64 #\U+1E65 #\U+1E66
+      #\U+1E67 #\U+1E9B #\U+1E68 #\U+1E69)
+
+
+    ;; #\Combining_Diaeresis
+
+    #(#\Latin_Capital_Letter_A_With_Diaeresis
+      #\Latin_Capital_Letter_E_With_Diaeresis #\U+1E26
+      #\Latin_Capital_Letter_I_With_Diaeresis
+      #\Latin_Capital_Letter_O_With_Diaeresis
+      #\Latin_Capital_Letter_U_With_Diaeresis #\U+1E84 #\U+1E8C
+      #\Latin_Capital_Letter_Y_With_Diaeresis
+      #\Latin_Small_Letter_A_With_Diaeresis
+      #\Latin_Small_Letter_E_With_Diaeresis #\U+1E27
+      #\Latin_Small_Letter_I_With_Diaeresis
+      #\Latin_Small_Letter_O_With_Diaeresis #\U+1E97
+      #\Latin_Small_Letter_U_With_Diaeresis #\U+1E85 #\U+1E8D
+      #\Latin_Small_Letter_Y_With_Diaeresis #\U+1E4E #\U+1E4F #\U+1E7A
+      #\U+1E7B #\Greek_Capital_Letter_Iota_With_Dialytika
+      #\Greek_Capital_Letter_Upsilon_With_Dialytika
+      #\Greek_Small_Letter_Iota_With_Dialytika
+      #\Greek_Small_Letter_Upsilon_With_Dialytika
+      #\Greek_Upsilon_With_Diaeresis_And_Hook_Symbol
+      #\Cyrillic_Capital_Letter_Yi
+      #\Cyrillic_Capital_Letter_A_With_Diaeresis
+      #\Cyrillic_Capital_Letter_Io
+      #\Cyrillic_Capital_Letter_Zhe_With_Diaeresis
+      #\Cyrillic_Capital_Letter_Ze_With_Diaeresis
+      #\Cyrillic_Capital_Letter_I_With_Diaeresis
+      #\Cyrillic_Capital_Letter_O_With_Diaeresis
+      #\Cyrillic_Capital_Letter_U_With_Diaeresis
+      #\Cyrillic_Capital_Letter_Che_With_Diaeresis
+      #\Cyrillic_Capital_Letter_Yeru_With_Diaeresis
+      #\Cyrillic_Capital_Letter_E_With_Diaeresis
+      #\Cyrillic_Small_Letter_A_With_Diaeresis #\Cyrillic_Small_Letter_Io
+      #\Cyrillic_Small_Letter_Zhe_With_Diaeresis
+      #\Cyrillic_Small_Letter_Ze_With_Diaeresis
+      #\Cyrillic_Small_Letter_I_With_Diaeresis
+      #\Cyrillic_Small_Letter_O_With_Diaeresis
+      #\Cyrillic_Small_Letter_U_With_Diaeresis
+      #\Cyrillic_Small_Letter_Che_With_Diaeresis
+      #\Cyrillic_Small_Letter_Yeru_With_Diaeresis
+      #\Cyrillic_Small_Letter_E_With_Diaeresis #\Cyrillic_Small_Letter_Yi
+      #\Cyrillic_Capital_Letter_Schwa_With_Diaeresis
+      #\Cyrillic_Small_Letter_Schwa_With_Diaeresis
+      #\Cyrillic_Capital_Letter_Barred_O_With_Diaeresis
+      #\Cyrillic_Small_Letter_Barred_O_With_Diaeresis)
+
+
+    ;; #\Combining_Hook_Above
+
+    #(#\U+1EA2 #\U+1EBA #\U+1EC8 #\U+1ECE #\U+1EE6 #\U+1EF6 #\U+1EA3
+      #\U+1EBB #\U+1EC9 #\U+1ECF #\U+1EE7 #\U+1EF7 #\U+1EA8 #\U+1EC2
+      #\U+1ED4 #\U+1EA9 #\U+1EC3 #\U+1ED5 #\U+1EB2 #\U+1EB3 #\U+1EDE
+      #\U+1EDF #\U+1EEC #\U+1EED)
+
+
+    ;; #\Combining_Ring_Above
+
+    #(#\Latin_Capital_Letter_A_With_Ring_Above
+      #\Latin_Capital_Letter_U_With_Ring_Above
+      #\Latin_Small_Letter_A_With_Ring_Above
+      #\Latin_Small_Letter_U_With_Ring_Above #\U+1E98 #\U+1E99)
+
+
+    ;; #\Combining_Double_Acute_Accent
+
+    #(#\Latin_Capital_Letter_O_With_Double_Acute
+      #\Latin_Capital_Letter_U_With_Double_Acute
+      #\Latin_Small_Letter_O_With_Double_Acute
+      #\Latin_Small_Letter_U_With_Double_Acute
+      #\Cyrillic_Capital_Letter_U_With_Double_Acute
+      #\Cyrillic_Small_Letter_U_With_Double_Acute)
+
+
+    ;; #\Combining_Caron
+
+    #(#\Latin_Capital_Letter_A_With_Caron
+      #\Latin_Capital_Letter_C_With_Caron
+      #\Latin_Capital_Letter_D_With_Caron
+      #\Latin_Capital_Letter_E_With_Caron
+      #\Latin_Capital_Letter_G_With_Caron
+      #\Latin_Capital_Letter_H_With_Caron
+      #\Latin_Capital_Letter_I_With_Caron
+      #\Latin_Capital_Letter_K_With_Caron
+      #\Latin_Capital_Letter_L_With_Caron
+      #\Latin_Capital_Letter_N_With_Caron
+      #\Latin_Capital_Letter_O_With_Caron
+      #\Latin_Capital_Letter_R_With_Caron
+      #\Latin_Capital_Letter_S_With_Caron
+      #\Latin_Capital_Letter_T_With_Caron
+      #\Latin_Capital_Letter_U_With_Caron
+      #\Latin_Capital_Letter_Z_With_Caron #\Latin_Small_Letter_A_With_Caron
+      #\Latin_Small_Letter_C_With_Caron #\Latin_Small_Letter_D_With_Caron
+      #\Latin_Small_Letter_E_With_Caron #\Latin_Small_Letter_G_With_Caron
+      #\Latin_Small_Letter_H_With_Caron #\Latin_Small_Letter_I_With_Caron
+      #\Latin_Small_Letter_J_With_Caron #\Latin_Small_Letter_K_With_Caron
+      #\Latin_Small_Letter_L_With_Caron #\Latin_Small_Letter_N_With_Caron
+      #\Latin_Small_Letter_O_With_Caron #\Latin_Small_Letter_R_With_Caron
+      #\Latin_Small_Letter_S_With_Caron #\Latin_Small_Letter_T_With_Caron
+      #\Latin_Small_Letter_U_With_Caron #\Latin_Small_Letter_Z_With_Caron
+      #\Latin_Capital_Letter_U_With_Diaeresis_And_Caron
+      #\Latin_Small_Letter_U_With_Diaeresis_And_Caron
+      #\Latin_Capital_Letter_Ezh_With_Caron
+      #\Latin_Small_Letter_Ezh_With_Caron)
+
+
+    ;; #\Combining_Double_Grave_Accent
+
+    #(#\Latin_Capital_Letter_A_With_Double_Grave
+      #\Latin_Capital_Letter_E_With_Double_Grave
+      #\Latin_Capital_Letter_I_With_Double_Grave
+      #\Latin_Capital_Letter_O_With_Double_Grave
+      #\Latin_Capital_Letter_R_With_Double_Grave
+      #\Latin_Capital_Letter_U_With_Double_Grave
+      #\Latin_Small_Letter_A_With_Double_Grave
+      #\Latin_Small_Letter_E_With_Double_Grave
+      #\Latin_Small_Letter_I_With_Double_Grave
+      #\Latin_Small_Letter_O_With_Double_Grave
+      #\Latin_Small_Letter_R_With_Double_Grave
+      #\Latin_Small_Letter_U_With_Double_Grave
+      #\Cyrillic_Capital_Letter_Izhitsa_With_Double_Grave_Accent
+      #\Cyrillic_Small_Letter_Izhitsa_With_Double_Grave_Accent)
+
+
+    ;; #\Combining_Inverted_Breve
+
+    #(#\Latin_Capital_Letter_A_With_Inverted_Breve
+      #\Latin_Capital_Letter_E_With_Inverted_Breve
+      #\Latin_Capital_Letter_I_With_Inverted_Breve
+      #\Latin_Capital_Letter_O_With_Inverted_Breve
+      #\Latin_Capital_Letter_R_With_Inverted_Breve
+      #\Latin_Capital_Letter_U_With_Inverted_Breve
+      #\Latin_Small_Letter_A_With_Inverted_Breve
+      #\Latin_Small_Letter_E_With_Inverted_Breve
+      #\Latin_Small_Letter_I_With_Inverted_Breve
+      #\Latin_Small_Letter_O_With_Inverted_Breve
+      #\Latin_Small_Letter_R_With_Inverted_Breve
+      #\Latin_Small_Letter_U_With_Inverted_Breve)
+
+
+    ;; #\Combining_Comma_Above
+
+    #(#\U+1F08 #\U+1F18 #\U+1F28 #\U+1F38 #\U+1F48 #\U+1F68 #\U+1F00
+      #\U+1F10 #\U+1F20 #\U+1F30 #\U+1F40 #\U+1FE4 #\U+1F50 #\U+1F60)
+
+
+    ;; #\Combining_Reversed_Comma_Above
+
+    #(#\U+1F09 #\U+1F19 #\U+1F29 #\U+1F39 #\U+1F49 #\U+1FEC #\U+1F59
+      #\U+1F69 #\U+1F01 #\U+1F11 #\U+1F21 #\U+1F31 #\U+1F41 #\U+1FE5
+      #\U+1F51 #\U+1F61)
+
+
+    ;; #\Combining_Horn
+
+    #(#\Latin_Capital_Letter_O_With_Horn
+      #\Latin_Capital_Letter_U_With_Horn #\Latin_Small_Letter_O_With_Horn
+      #\Latin_Small_Letter_U_With_Horn)
+
+
+    ;; #\Combining_Dot_Below
+
+    #(#\U+1EA0 #\U+1E04 #\U+1E0C #\U+1EB8 #\U+1E24 #\U+1ECA #\U+1E32
+      #\U+1E36 #\U+1E42 #\U+1E46 #\U+1ECC #\U+1E5A #\U+1E62 #\U+1E6C
+      #\U+1EE4 #\U+1E7E #\U+1E88 #\U+1EF4 #\U+1E92 #\U+1EA1 #\U+1E05
+      #\U+1E0D #\U+1EB9 #\U+1E25 #\U+1ECB #\U+1E33 #\U+1E37 #\U+1E43
+      #\U+1E47 #\U+1ECD #\U+1E5B #\U+1E63 #\U+1E6D #\U+1EE5 #\U+1E7F
+      #\U+1E89 #\U+1EF5 #\U+1E93 #\U+1EE2 #\U+1EE3 #\U+1EF0 #\U+1EF1)
+
+
+    ;; #\Combining_Diaeresis_Below
+
+    #(#\U+1E72 #\U+1E73)
+
+
+    ;; #\Combining_Ring_Below
+
+    #(#\U+1E00 #\U+1E01)
+
+
+    ;; #\Combining_Comma_Below
+
+    #(#\Latin_Capital_Letter_S_With_Comma_Below
+      #\Latin_Capital_Letter_T_With_Comma_Below
+      #\Latin_Small_Letter_S_With_Comma_Below
+      #\Latin_Small_Letter_T_With_Comma_Below)
+
+
+    ;; #\Combining_Cedilla
+
+    #(#\Latin_Capital_Letter_C_With_Cedilla #\U+1E10
+      #\Latin_Capital_Letter_E_With_Cedilla
+      #\Latin_Capital_Letter_G_With_Cedilla #\U+1E28
+      #\Latin_Capital_Letter_K_With_Cedilla
+      #\Latin_Capital_Letter_L_With_Cedilla
+      #\Latin_Capital_Letter_N_With_Cedilla
+      #\Latin_Capital_Letter_R_With_Cedilla
+      #\Latin_Capital_Letter_S_With_Cedilla
+      #\Latin_Capital_Letter_T_With_Cedilla
+      #\Latin_Small_Letter_C_With_Cedilla #\U+1E11
+      #\Latin_Small_Letter_E_With_Cedilla
+      #\Latin_Small_Letter_G_With_Cedilla #\U+1E29
+      #\Latin_Small_Letter_K_With_Cedilla
+      #\Latin_Small_Letter_L_With_Cedilla
+      #\Latin_Small_Letter_N_With_Cedilla
+      #\Latin_Small_Letter_R_With_Cedilla
+      #\Latin_Small_Letter_S_With_Cedilla
+      #\Latin_Small_Letter_T_With_Cedilla)
+
+
+    ;; #\Combining_Ogonek
+
+    #(#\Latin_Capital_Letter_A_With_Ogonek
+      #\Latin_Capital_Letter_E_With_Ogonek
+      #\Latin_Capital_Letter_I_With_Ogonek
+      #\Latin_Capital_Letter_O_With_Ogonek
+      #\Latin_Capital_Letter_U_With_Ogonek
+      #\Latin_Small_Letter_A_With_Ogonek #\Latin_Small_Letter_E_With_Ogonek
+      #\Latin_Small_Letter_I_With_Ogonek #\Latin_Small_Letter_O_With_Ogonek
+      #\Latin_Small_Letter_U_With_Ogonek)
+
+
+    ;; #\Combining_Circumflex_Accent_Below
+
+    #(#\U+1E12 #\U+1E18 #\U+1E3C #\U+1E4A #\U+1E70 #\U+1E76 #\U+1E13
+      #\U+1E19 #\U+1E3D #\U+1E4B #\U+1E71 #\U+1E77)
+
+
+    ;; #\Combining_Breve_Below
+
+    #(#\U+1E2A #\U+1E2B)
+
+
+    ;; #\Combining_Tilde_Below
+
+    #(#\U+1E1A #\U+1E2C #\U+1E74 #\U+1E1B #\U+1E2D #\U+1E75)
+
+
+    ;; #\Combining_Macron_Below
+
+    #(#\U+1E06 #\U+1E0E #\U+1E34 #\U+1E3A #\U+1E48 #\U+1E5E #\U+1E6E
+      #\U+1E94 #\U+1E07 #\U+1E0F #\U+1E96 #\U+1E35 #\U+1E3B #\U+1E49
+      #\U+1E5F #\U+1E6F #\U+1E95)
+
+
+    ;; #\Combining_Long_Solidus_Overlay
+
+    #(#\U+226E #\U+2260 #\U+226F #\U+219A #\U+219B #\U+21AE #\U+21CD
+      #\U+21CF #\U+21CE #\U+2204 #\U+2209 #\U+220C #\U+2224 #\U+2226
+      #\U+2241 #\U+2244 #\U+2247 #\U+2249 #\U+226D #\U+2262 #\U+2270
+      #\U+2271 #\U+2274 #\U+2275 #\U+2278 #\U+2279 #\U+2280 #\U+2281
+      #\U+22E0 #\U+22E1 #\U+2284 #\U+2285 #\U+2288 #\U+2289 #\U+22E2
+      #\U+22E3 #\U+22AC #\U+22AD #\U+22AE #\U+22AF #\U+22EA #\U+22EB
+      #\U+22EC #\U+22ED)
+
+
+    ;; #\Combining_Greek_Perispomeni
+
+    #(#\U+1FC1 #\U+1FB6 #\U+1FC6 #\U+1FD6 #\U+1FE6 #\U+1FF6 #\U+1FD7
+      #\U+1FE7 #\U+1F06 #\U+1F07 #\U+1F0E #\U+1F0F #\U+1F26 #\U+1F27
+      #\U+1F2E #\U+1F2F #\U+1F36 #\U+1F37 #\U+1F3E #\U+1F3F #\U+1F56
+      #\U+1F57 #\U+1F5F #\U+1F66 #\U+1F67 #\U+1F6E #\U+1F6F #\U+1FCF
+      #\U+1FDF)
+
+
+    ;; #\Combining_Greek_Ypogegrammeni
+
+    #(#\U+1FBC #\U+1FCC #\U+1FFC #\U+1FB4 #\U+1FC4 #\U+1FB3 #\U+1FC3
+      #\U+1FF3 #\U+1FF4 #\U+1F80 #\U+1F81 #\U+1F82 #\U+1F83 #\U+1F84
+      #\U+1F85 #\U+1F86 #\U+1F87 #\U+1F88 #\U+1F89 #\U+1F8A #\U+1F8B
+      #\U+1F8C #\U+1F8D #\U+1F8E #\U+1F8F #\U+1F90 #\U+1F91 #\U+1F92
+      #\U+1F93 #\U+1F94 #\U+1F95 #\U+1F96 #\U+1F97 #\U+1F98 #\U+1F99
+      #\U+1F9A #\U+1F9B #\U+1F9C #\U+1F9D #\U+1F9E #\U+1F9F #\U+1FA0
+      #\U+1FA1 #\U+1FA2 #\U+1FA3 #\U+1FA4 #\U+1FA5 #\U+1FA6 #\U+1FA7
+      #\U+1FA8 #\U+1FA9 #\U+1FAA #\U+1FAB #\U+1FAC #\U+1FAD #\U+1FAE
+      #\U+1FAF #\U+1FB2 #\U+1FC2 #\U+1FF2 #\U+1FB7 #\U+1FC7 #\U+1FF7)
+
+
+    ;; #\Arabic_Maddah_Above
+
+    #(#\Arabic_Letter_Alef_With_Madda_Above)
+
+
+    ;; #\Arabic_Hamza_Above
+
+    #(#\Arabic_Letter_Alef_With_Hamza_Above
+      #\Arabic_Letter_Waw_With_Hamza_Above
+      #\Arabic_Letter_Yeh_With_Hamza_Above
+      #\Arabic_Letter_Heh_Goal_With_Hamza_Above
+      #\Arabic_Letter_Yeh_Barree_With_Hamza_Above
+      #\Arabic_Letter_Heh_With_Yeh_Above)
+
+
+    ;; #\Arabic_Hamza_Below
+
+    #(#\Arabic_Letter_Alef_With_Hamza_Below)
+
+
+    ;; #\U+093C
+
+    #(#\U+0929 #\U+0931 #\U+0934)
+
+
+    ;; #\U+09BE
+
+    #(#\U+09CB)
+
+
+    ;; #\U+09D7
+
+    #(#\U+09CC)
+
+
+    ;; #\U+0B3E
+
+    #(#\U+0B4B)
+
+
+    ;; #\U+0B56
+
+    #(#\U+0B48)
+
+
+    ;; #\U+0B57
+
+    #(#\U+0B4C)
+
+
+    ;; #\U+0BBE
+
+    #(#\U+0BCA #\U+0BCB)
+
+
+    ;; #\U+0BD7
+
+    #(#\U+0B94 #\U+0BCC)
+
+
+    ;; #\U+0C56
+
+    #(#\U+0C48)
+
+
+    ;; #\U+0CC2
+
+    #(#\U+0CCA)
+
+
+    ;; #\U+0CD5
+
+    #(#\U+0CC0 #\U+0CC7 #\U+0CCB)
+
+
+    ;; #\U+0CD6
+
+    #(#\U+0CC8)
+
+
+    ;; #\U+0D3E
+
+    #(#\U+0D4A #\U+0D4B)
+
+
+    ;; #\U+0D57
+
+    #(#\U+0D4C)
+
+
+    ;; #\U+0DCA
+
+    #(#\U+0DDA #\U+0DDD)
+
+
+    ;; #\U+0DCF
+
+    #(#\U+0DDC)
+
+
+    ;; #\U+0DDF
+
+    #(#\U+0DDE)
+
+
+    ;; #\U+102E
+
+    #(#\U+1026)
+
+
+    ;; #\U+3099
+
+    #(#\U+3094 #\U+304C #\U+304E #\U+3050 #\U+3052 #\U+3054 #\U+3056
+      #\U+3058 #\U+305A #\U+305C #\U+305E #\U+3060 #\U+3062 #\U+3065
+      #\U+3067 #\U+3069 #\U+3070 #\U+3073 #\U+3076 #\U+3079 #\U+307C
+      #\U+309E #\U+30F4 #\U+30AC #\U+30AE #\U+30B0 #\U+30B2 #\U+30B4
+      #\U+30B6 #\U+30B8 #\U+30BA #\U+30BC #\U+30BE #\U+30C0 #\U+30C2
+      #\U+30C5 #\U+30C7 #\U+30C9 #\U+30D0 #\U+30D3 #\U+30D6 #\U+30D9
+      #\U+30DC #\U+30F7 #\U+30F8 #\U+30F9 #\U+30FA #\U+30FE)
+
+
+    ;; #\U+309A
+
+    #(#\U+3071 #\U+3074 #\U+3077 #\U+307A #\U+307D #\U+30D1 #\U+30D4
+      #\U+30D7 #\U+30DA #\U+30DD)
+    ))
+
+(defun search-char-vector (vector char)
+  ;; vector is a SIMPLE-VECTOR of chars sorted by char-code.
+  ;; return the index of char in vector or NIL if not found
+  (let* ((left 0)
+         (right (1- (length vector))))
+    (declare (fixnum left right))
+    (if (and (char>= char (svref vector left))
+             (char<= char (svref vector right)))
+      (do* ()
+           ((> left right))
+        (let* ((mid (ash (the fixnum (+ left right)) -1))
+               (midch (svref vector mid)))
+          (declare (fixnum mid))
+          (if (eql char midch)
+            (return mid)
+            (if (char< char midch)
+              (setq right (1- mid))
+              (setq left (1+ mid)))))))))
+
+
+(defconstant HANGUL-SBASE #xAC00)
+(defconstant HANGUL-LBASE #x1100)
+(defconstant HANGUL-VBASE #x1161)
+(defconstant HANGUL-TBASE #x11A7)
+
+(defconstant HANGUL-SCOUNT 11172)
+(defconstant HANGUL-LCOUNT 19)
+(defconstant HANGUL-VCOUNT 21)
+(defconstant HANGUL-TCOUNT 28)
+(defconstant HANGUL-NCOUNT (* HANGUL-VCOUNT HANGUL-TCOUNT))
+
+(defun combine-bmp-chars (base combiner)
+  (if (and (char>= combiner (code-char hangul-vbase))
+           (char< combiner (code-char (+ hangul-tbase hangul-tcount))))
+    (if (and (char< combiner (code-char (+ hangul-vbase hangul-vcount)))
+             (char>= base (code-char hangul-lbase))
+             (char< base (code-char (+ hangul-lbase hangul-lcount))))
+      (return-from combine-bmp-chars
+        (code-char (+ hangul-lbase
+                      (* hangul-ncount (- (char-code base) hangul-lbase))
+                      (* hangul-tcount (- (char-code combiner) hangul-vbase))))))
+    (if (and (char> combiner (code-char hangul-tbase))
+             (char>= base (code-char hangul-sbase))
+             (char< base (code-char (+ hangul-sbase hangul-scount))))
+      (if (not (zerop (the fixnum (mod (- (char-code base) hangul-sbase) hangul-tcount))))
+        (return-from combine-bmp-chars nil)
+        (return-from combine-bmp-chars
+          (code-char (+ (char-code base) (- (char-code combiner) hangul-tbase)))))))
+    
+  (let* ((idx (search-char-vector *bmp-combining-chars* combiner))
+         (base-table (if idx (svref *bmp-combining-base-chars* idx))))
+    (if base-table
+      (let* ((combined-idx (search-char-vector base-table base)))
+        (if combined-idx
+          (svref (svref *bmp-precombined-chars* idx) combined-idx))))))
+
+(defun precompose-simple-string (s)
+  (let* ((n (length s)))
+    (or (dotimes (i n s)
+          (when (is-combinable (schar s i))
+            (return nil)))
+        (let* ((new (make-string n)))
+          (declare (dynamic-extent new))
+          (do* ((i 0 (1+ i))
+                (nout -1)
+                (lastch nil))
+               ((= i n) (subseq new 0 (1+ nout)))
+            (declare (fixnum nout i))
+            (let* ((ch (schar s i)))
+              (if (or (not lastch)
+                      (not (is-combinable ch)))
+                (setf lastch ch
+                      (schar new (incf nout)) ch)
+                (let* ((combined (combine-bmp-chars lastch ch)))
+                  (if combined
+                    (setf (schar new nout) (setq lastch combined))
+                    (setf lastch ch
+                      (schar new (incf nout)) ch))))))))))
Index: /branches/new-random/level-1/l1-utils.lisp
===================================================================
--- /branches/new-random/level-1/l1-utils.lisp	(revision 13309)
+++ /branches/new-random/level-1/l1-utils.lisp	(revision 13309)
@@ -0,0 +1,1175 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; L1-utils.lisp
+
+(in-package "CCL")
+
+;The following forms (up thru defn of %DEFUN) must come before any DEFUN's.
+;Any (non-kernel) functions must be defined before they're used! 
+;In fact, ALL functions must be defined before they're used!  How about that ?
+
+
+
+(setq %lisp-system-fixups% nil)
+
+
+;;; Kludge for record-source-file bootstrapping
+
+(%fhave 'full-pathname (qlfun bootstrapping-full-pathname (name) name))
+
+
+; real one is  in setf.lisp
+(%fhave '%setf-method (qlfun bootstripping-setf-fsname (spec)
+                                   spec nil))
+
+(fset 'physical-pathname-p (lambda (file)(declare (ignore file)) nil)) ; redefined later
+
+(setq *record-source-file* t)
+
+(fset 'level-1-record-source-file
+      (qlfun level-1-record-source-file (name def-type &optional (source (or *loading-toplevel-location*
+                                                                             *loading-file-source-file*)))
+        ;; Level-0 puts stuff on plist of name.  Once we're in level-1, names can
+        ;; be more complicated than just a symbol, so just collect all calls until
+        ;; the real record-source-file is loaded.
+        (when *record-source-file*
+          (unless (listp *record-source-file*)
+            (setq *record-source-file* nil))
+          (push (list name def-type source) *record-source-file*))))
+
+(fset 'record-source-file #'level-1-record-source-file)
+
+(defun inherit-from-p (ob parent)
+  (memq (if (symbolp parent) (find-class parent nil) parent)
+        (%inited-class-cpl (class-of ob))))
+
+;;; returns new plist with value spliced in or key, value consed on.
+(defun setprop (plist key value &aux loc)
+  (if (setq loc (pl-search plist key))
+    (progn (%rplaca (%cdr loc) value) plist)
+    (cons key (cons value plist))))
+
+(defun getf-test (place indicator test &optional default)
+  (loop
+    (when (null place)
+      (return default))
+    (when (funcall test indicator (car place))
+      (return (cadr place)))
+    (setq place (cddr place))))
+
+(defun setprop-test (plist indicator test value)
+  (let ((tail plist))
+    (loop
+      (when (null tail)
+        (return (cons indicator (cons value plist))))
+      (when (funcall test indicator (car tail))
+        (setf (cadr tail) value)
+        (return plist))
+      (setq tail (cddr tail)))))
+
+(defun plistp (p &aux len)
+  (and (listp p)
+       (setq len (list-length p))
+       (not (%ilogbitp 0 len))))  ; (evenp p)
+
+(defun %imax (i1 i2)
+ (if (%i> i1 i2) i1 i2))
+
+(defun %imin (i1 i2)
+  (if (%i< i1 i2) i1 i2))
+
+
+
+
+;|#
+
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS"))
+
+
+
+
+(defun loading-file-source-file ()
+  *loading-file-source-file*)
+
+(setq *save-local-symbols* t)
+
+(%fhave 'require-type (nfunction bootstrapping-require-type
+                                 (lambda (thing type)
+                                   (declare (ignore type))
+                                   thing)))
+(%fhave '%require-type 
+        (nfunction bootstrapping-%require-type
+                   (lambda (thing predicate)
+                     (declare (ignore predicate))
+                     thing)))
+
+(setf (type-predicate 'macptr) 'macptrp)
+
+
+
+
+
+
+(defun %pop-required-arg-ptr (ptr)
+  (if (atom (destructure-state.current ptr))
+    (signal-program-error "Required arguments in ~s don't match lambda list ~s."
+	   (destructure-state.whole ptr) (destructure-state.lambda ptr))
+    (pop (destructure-state.current ptr))))
+
+(defun %default-optional-value (ptr &optional default)
+  (let* ((tail (destructure-state.current ptr)))
+    (if tail
+      (if (atom tail)
+	(signal-program-error "Optional arguments in ~s don't match lambda list ~s."
+	       (destructure-state.whole ptr) (destructure-state.lambda ptr))
+	(pop (destructure-state.current ptr)))
+      default)))
+
+(defun %check-extra-arguments (ptr)
+  (when (destructure-state.current ptr)
+    (signal-program-error "Extra arguments in ~s don't match lambda list ~s."
+			  (destructure-state.whole ptr) (destructure-state.lambda ptr))))
+
+(defun %keyword-present-p (keys keyword)
+  (let* ((not-there (cons nil nil)))
+    (declare (dynamic-extent not-there))
+    (not (eq (getf keys keyword not-there) not-there))))
+
+(defun check-keywords (keys actual allow-others)
+  (let* ((len (ignore-errors (list-length actual))))
+    (if (null len)
+      (signal-simple-program-error "Circular or dotted keyword list: ~s" actual)
+      (if (oddp len)
+	(signal-simple-program-error "Odd length keyword list: ~s" actual))))
+  (setq allow-others (or allow-others (getf actual :allow-other-keys)))
+  (do* ((a actual (cddr a))
+	(k (car a) (car a)))
+       ((null a))
+    (unless (typep k 'symbol)
+      (signal-simple-program-error
+       "Invalid keyword argument ~s in ~s.  ~&Valid keyword arguments are ~s." k actual keys))
+    (unless (or allow-others
+		(eq k :allow-other-keys)
+		(member k keys))
+      (signal-simple-program-error "Unknown keyword argument ~s in ~s.  ~&Valid keyword arguments are ~s." k actual keys))))
+
+(%fhave 'set-macro-function #'%macro-have)   ; redefined in sysutils.
+
+;;; Define special forms.
+(dolist (sym '(block catch compiler-let eval-when
+               flet function go if labels let let* macrolet
+               multiple-value-call multiple-value-prog1
+               progn progv quote return-from setq tagbody
+               the throw unwind-protect locally load-time-value
+	       symbol-macrolet
+               ;; These are implementation-specific special forms :
+	       nfunction
+	       ppc-lap-function fbind
+               with-c-frame with-variable-c-frame))
+  (%macro-have sym sym))
+
+
+(defun %macro (named-fn &optional doc &aux arglist)
+  ;; "doc" is either a string or a list of the form :
+  ;; (doc-string-or-nil . (body-pos-or-nil . arglist-or-nil))
+  (if (listp doc)
+    (setq arglist (cddr doc)
+          doc (car doc)))
+  (let* ((name (function-name named-fn)))
+    (record-source-file name 'function)
+    (set-macro-function name named-fn)
+    (when (and doc *save-doc-strings*)
+      (set-documentation name 'function doc))
+    (when arglist
+      (record-arglist name arglist))
+    (when *fasload-print* (format t "~&~S~%" name))
+    name))
+
+
+(defun %defvar (var &optional doc)
+  "Returns boundp"
+  (%proclaim-special var)
+  (record-source-file var 'variable)
+  (when (and doc *save-doc-strings*)
+    (set-documentation var 'variable doc))
+  (cond ((not (boundp var))
+         (when *fasload-print* (format t "~&~S~%" var))
+         nil)
+        (t t)))
+
+(defun %defparameter (var value &optional doc)
+  (%proclaim-special var)
+  (record-source-file var 'variable)
+  (when (and doc *save-doc-strings*)
+    (set-documentation var 'variable doc))
+  (when *fasload-print* (format t "~&~S~%" var))
+  (set var value)
+  var)
+
+
+(defun %defglobal (var value &optional doc)
+  (%symbol-bits var (logior (ash 1 $sym_vbit_global) (the fixnum (%symbol-bits var))))
+  (%defparameter var value doc))
+
+;Needed early for member etc.
+(defun identity (x)
+  "This function simply returns what was passed to it."
+  x)
+
+(defun coerce-to-function (arg)
+  (if (functionp arg)
+    arg
+    (if (symbolp arg)
+      (%function arg)
+      (report-bad-arg arg 'function))))
+
+;;; takes arguments in arg_x, arg_y, arg_z, returns "multiple values" 
+;;; Test(-not) arguments are NOT validated beyond what is done
+;;; here.
+;;; if both :test and :test-not supplied, signal error.
+;;; if test provided as #'eq or 'eq, return first value 'eq.
+;;; if test defaulted, provided as 'eql, or provided as #'eql, return
+;;; first value 'eql.
+;;; if test-not provided as 'eql or provided as #'eql, return second
+;;; value 'eql.
+;;; if key provided as either 'identity or #'identity, return third value nil.
+(defun %key-conflict (test-fn test-not-fn key)
+  (let* ((eqfn #'eq)
+         (eqlfn #'eql)
+         (idfn #'identity))
+    (if (or (eq key 'identity) (eq key idfn))
+      (setq key nil))
+    (if test-fn
+      (if test-not-fn
+        (%err-disp $xkeyconflict ':test test-fn ':test-not test-not-fn)
+        (if (eq test-fn eqfn)
+          (values 'eq nil key)
+          (if (eq test-fn eqlfn)
+            (values 'eql nil key)
+            (values test-fn nil key))))
+      (if test-not-fn
+        (if (eq test-not-fn eqfn)
+          (values nil 'eq key)
+          (if (eq test-not-fn eqlfn)
+            (values nil 'eql key)
+            (values nil test-not-fn key)))
+        (values 'eql nil key)))))
+
+
+
+
+
+;;; Assoc.
+
+;;; (asseql item list) <=> (assoc item list :test #'eql :key #'identity)
+
+
+
+;;; (assoc-test item list test-fn) 
+;;;   <=> 
+;;;     (assoc item list :test test-fn :key #'identity)
+;;; test-fn may not be FUNCTIONP, so we coerce it here.
+(defun assoc-test (item list test-fn)
+  (dolist (pair list)
+    (if pair
+      (if (funcall test-fn item (car pair))
+	(return pair)))))
+
+
+
+; (assoc-test-not item list test-not-fn) 
+;   <=> 
+;     (assoc item list :test-not test-not-fn :key #'identity)
+; test-not-fn may not be FUNCTIONP, so we coerce it here.
+(defun assoc-test-not (item list test-not-fn)
+  (dolist (pair list)
+    (if pair
+      (if (not (funcall test-not-fn item (car pair)))
+	(return pair)))))
+
+(defun assoc (item list &key test test-not key)
+  "Return the cons in ALIST whose car is equal (by a given test or EQL) to
+   the ITEM."
+  (multiple-value-bind (test test-not key) (%key-conflict test test-not key)
+    (if (null key)
+      (if (eq test 'eq)
+        (assq item list)
+        (if (eq test 'eql)
+          (asseql item list)
+          (if test
+            (assoc-test item list test)
+            (assoc-test-not item list test-not))))
+      (if test
+        (dolist (pair list)
+          (if pair
+            (if (funcall test item (funcall key (car pair)))
+              (return pair))))
+        (dolist (pair list)
+          (if pair
+            (unless (funcall test-not item (funcall key (car pair)))
+              (return pair))))))))
+
+
+
+;;;; Member.
+
+;;; (member-test-not item list test-not-fn) 
+;;;   <=> 
+;;;     (member item list :test-not test-not-fn :key #'identity)
+(defun member-test-not (item list test-not-fn)
+  (do* ((l list (cdr l)))
+       ((endp l))
+    (unless (funcall test-not-fn item (%car l)) (return l))))
+
+(defun member (item list &key test test-not key)
+  "Return the tail of LIST beginning with first element satisfying EQLity,
+   :TEST, or :TEST-NOT with the given ITEM."
+  (multiple-value-bind (test test-not key) (%key-conflict test test-not key)
+    (if (null key)
+      (if (eq test 'eq)
+        (memq item list)
+        (if (eq test 'eql)
+          (memeql item list)
+          (if test
+            (member-test item list test)
+            (member-test-not item list test-not))))
+      (if test
+        (do* ((l list (cdr l)))
+             ((endp l))
+          (if (funcall test item (funcall key (car l)))
+              (return l)))
+        (do* ((l list (cdr l)))
+             ((null l))
+          (unless (funcall test-not item (funcall key (car l)))
+              (return l)))))))
+
+
+(defun adjoin (item list &key test test-not key)
+  "Add ITEM to LIST unless it is already a member"
+  (if (and (not test)(not test-not)(not key))
+    (if (not (memeql item list))(cons item list) list)
+    (multiple-value-bind (test test-not key) (%key-conflict test test-not key)
+      (if
+        (if (null key)
+          (if (eq test 'eq)
+            (memq item list)
+            (if (eq test 'eql)
+              (memeql item list)
+              (if test
+                (member-test item list test)
+                (member-test-not item list test-not))))
+          (if test
+            (member (funcall key item) list :test test :key key)
+            (member (funcall key item) list :test-not test-not :key key)))
+        list
+        (cons item list)))))
+
+(defun adjoin-eq (elt list)
+  (if (memq elt list)
+    list
+    (cons elt list)))
+
+(defun adjoin-eql (elt list)
+  (if (memeql elt list)
+    list
+    (cons elt list)))
+
+(defun union-eq (list1 list2)
+  (let ((res list2))
+    (dolist (elt list1)
+      (unless (memq elt res)
+        (push elt res)))
+    res))
+
+(defun union-eql (list1 list2)
+  (let ((res list2))
+    (dolist (elt list1)
+      (unless (memeql elt res)
+        (push elt res)))
+    res))
+
+;;; Fix this someday.  Fix EQUALP, while you're at it ...
+(defun similar-as-constants-p (x y)
+  (or (eq x y)                          ; Redefinition of constants to themselves.
+      (if (and (stringp x) (stringp y)) ;The most obvious case where equalp & s-a-c-p need to differ...
+        (string= x y)
+        (equalp x y))))
+
+(defun undefine-constant (var)
+  (%set-sym-global-value var (%unbound-marker-8)))
+
+(defparameter *cerror-on-constant-redefinition* t)
+
+(defun define-constant (var value)
+  (block nil
+    (if (constant-symbol-p var)
+      (let* ((old-value (%sym-global-value var)))
+	(unless (eq old-value (%unbound-marker-8))
+	  (if (or (eql old-value value)
+                  (and (not *strict-checking*) (similar-as-constants-p old-value value)))
+	    (return)
+	    ;; This should really be a cell error, allow options other than
+	    ;; redefining (such as don't redefine and continue)...
+            (when *cerror-on-constant-redefinition*
+              (cerror "Redefine ~S to have new value ~*~s"
+                      "Constant ~S is already defined with a different value (~s)"
+                      var old-value value))))))
+    (%symbol-bits var 
+                  (%ilogior (%ilsl $sym_bit_special 1) (%ilsl $sym_bit_const 1)
+                            (%symbol-bits var)))
+    (%set-sym-global-value var value))
+  var)
+
+(defun %defconstant (var value &optional doc)
+  (%proclaim-special var)
+  (record-source-file var 'constant)
+  (define-constant var value)
+  (when (and doc *save-doc-strings*)
+    (set-documentation var 'variable doc))
+  (when *fasload-print* (format t "~&~S~%" var))
+  var)
+
+(defparameter *nx1-compiler-special-forms* ())
+(defparameter *nx-proclaimed-types* ())
+(defparameter *nx-proclaimed-ftypes* nil)
+
+(defun compiler-special-form-p (sym)
+  (or (eq sym 'quote)
+      (if (memq sym *nx1-compiler-special-forms*) t)))
+
+
+
+(defparameter *nx-known-declarations* ())
+(defparameter *nx-proclaimed-inline* ())
+(defparameter *nx-proclaimed-ignore* ())
+(defparameter *nx-globally-inline* ())
+
+
+
+(defconstant *cl-types* '(
+array
+atom
+base-char
+bignum
+bit
+bit-vector 
+character
+#|
+lisp:common
+|#
+compiled-function 
+complex 
+cons                    
+double-float
+extended-char
+fixnum
+float
+function
+hash-table
+integer
+keyword
+list 
+long-float
+nil 
+null
+number  
+package
+pathname 
+random-state  
+ratio
+rational
+readtable
+real
+sequence 
+short-float
+signed-byte 
+simple-array
+simple-bit-vector
+simple-string 
+simple-base-string
+simple-vector 
+single-float
+standard-char
+stream  
+string
+#|
+lisp:string-char
+|#
+symbol
+t
+unsigned-byte 
+vector
+))
+
+;; Redefined in sysutils.
+(%fhave 'specifier-type-if-known
+        (qlfun bootstrapping-type-specifier-p (name &optional env &key &allow-other-keys)
+          (declare (ignore env))
+          (memq name *cl-types*)))
+
+
+
+(defun proclaim (spec)
+  (case (car spec)
+    (special (apply #'proclaim-special (%cdr spec)))
+    (notspecial (apply #'proclaim-notspecial (%cdr spec)))
+    (optimize (%proclaim-optimize (%cdr spec)))
+    (inline (apply #'proclaim-inline t (%cdr spec)))
+    (notinline (apply #'proclaim-inline nil (%cdr spec)))
+    (declaration (apply #'proclaim-declaration (%cdr spec)))
+    (ignore (apply #'proclaim-ignore t (%cdr spec)))
+    (unignore (apply #'proclaim-ignore nil (%cdr spec)))
+    (type (apply #'proclaim-type (%cdr spec)))
+    (ftype (apply #'proclaim-ftype (%cdr spec)))
+    (function (apply #'proclaim-type spec))
+    (t (unless (memq (%car spec) *nx-known-declarations*)
+         ;; Any type name is now (ANSI CL) a valid declaration.
+         (if (specifier-type-if-known (%car spec))
+           (apply #'proclaim-type spec)
+           (signal-program-error "Unknown declaration specifier ~s in ~S" (%car spec) spec))))))
+
+(defun bad-proclaim-spec (spec)
+  (signal-program-error "Invalid declaration specifier ~s" spec))
+
+(defun proclaim-type (type &rest vars)
+  (declare (dynamic-extent vars))
+  ;; Called too early to use (every #'symbolp vars)
+  (unless (loop for v in vars always (symbolp v)) (bad-proclaim-spec `(,type ,@vars)))
+  (when *type-system-initialized*
+    ;; Check the type.  This will signal program-error's in case of invalid types, let it.
+    ;; Do not signal anything about unknown types though -- it should be ok to have forward
+    ;; references here, before anybody needs the info.
+    (specifier-type type))
+  (dolist (var vars)
+    (let ((spec (assq var *nx-proclaimed-types*)))
+      (if spec
+        (rplacd spec type)
+        (push (cons var type) *nx-proclaimed-types*)))))
+
+(defun proclaim-ftype (ftype &rest names)
+  (declare (dynamic-extent names))
+  (unless (every (lambda (v) (or (symbolp v) (setf-function-name-p v))) names)
+    (bad-proclaim-spec `(ftype ,ftype ,@names)))
+  (unless *nx-proclaimed-ftypes*
+    (setq *nx-proclaimed-ftypes* (make-hash-table :test #'eq)))
+  ;; Check the type.  This will signal program-error's in case of invalid types, let it.
+  ;; Do not signal anything about unknown types though -- it should be ok to have forward
+  ;; references here, before anybody needs the info.
+  (let* ((ctype (specifier-type ftype)))
+    ;; If know enough to complain now, do so.
+    (when (types-disjoint-p ctype (specifier-type 'function))
+      (bad-proclaim-spec `(ftype ,ftype ,@names))))
+  (dolist (name names)
+    (setf (gethash (maybe-setf-function-name name) *nx-proclaimed-ftypes*) ftype)))
+
+
+
+(defun proclaimed-ftype (name)
+  (when *nx-proclaimed-ftypes*
+    (gethash (ensure-valid-function-name name) *nx-proclaimed-ftypes*)))
+
+
+(defun proclaim-special (&rest vars)
+  (declare (dynamic-extent vars))
+  (unless (every #'symbolp vars) (bad-proclaim-spec `(special ,@vars)))
+  (dolist (sym vars) (%proclaim-special sym)))
+
+
+(defun proclaim-notspecial (&rest vars)
+  (declare (dynamic-extent vars))
+  (unless (every #'symbolp vars) (bad-proclaim-spec `(special ,@vars)))
+  (dolist (sym vars) (%proclaim-notspecial sym)))
+
+(defun proclaim-inline (t-or-nil &rest names)
+  (declare (dynamic-extent names))
+  ;;This is just to make it more likely to detect forgetting about the
+  ;;first arg...
+  (unless (or (eq nil t-or-nil) (eq t t-or-nil)) (report-bad-arg t-or-nil '(member t nil)))
+  (unless (loop for v in names always (or (symbolp v) (setf-function-name-p v)))
+    (bad-proclaim-spec `(,(if t-or-nil 'inline 'notinline) ,@names)))
+  (dolist (name names)
+    (setq name (maybe-setf-function-name name))
+    (if (listp *nx-proclaimed-inline*)
+      (setq *nx-proclaimed-inline*
+          (alist-adjoin name
+                        (or t-or-nil (if (compiler-special-form-p name) t))
+                        *nx-proclaimed-inline*))
+      (setf (gethash name *nx-proclaimed-inline*)
+            (or t-or-nil (if (compiler-special-form-p name) t))))))
+
+(defun proclaim-declaration (&rest syms)
+  (declare (dynamic-extent syms))
+  (unless (every #'symbolp syms) (bad-proclaim-spec `(declaration ,@syms)))
+  (dolist (sym syms)
+    (when (type-specifier-p sym)
+      (error "Cannot define declaration ~s because it is the name of a type" sym))
+    (setq *nx-known-declarations* 
+          (adjoin sym *nx-known-declarations* :test 'eq))))
+
+(defun check-declaration-redefinition (name why)
+  (when (memq name *nx-known-declarations*)
+    (cerror "Undeclare the declaration ~*~s"
+	    "Cannot ~a ~s because ~:*~s has been declared as a declaration name" why name)
+    (setq *nx-known-declarations* (remove name *nx-known-declarations*))))
+
+(defun proclaim-ignore (t-or-nil &rest syms)
+  (declare (dynamic-extent syms))
+  ;;This is just to make it more likely to detect forgetting about the
+  ;;first arg...
+  (unless (or (eq nil t-or-nil) (eq t t-or-nil)) (report-bad-arg t-or-nil '(member t nil)))
+  (unless (every #'symbolp syms) (bad-proclaim-spec `(,(if t-or-nil 'ignore 'unignore) ,@syms)))
+  (dolist (sym syms)
+    (setq *nx-proclaimed-ignore*
+          (alist-adjoin sym t-or-nil *nx-proclaimed-ignore*))))
+
+
+(queue-fixup
+ (when (listp *nx-proclaimed-inline*)
+  (let ((table (make-hash-table :size 100 :test #'eq)))
+    (dolist (x *nx-proclaimed-inline*)
+      (let ((name (car x)) (value (cdr x)))
+        (when (symbolp name)
+          (setf (gethash name table) value))))
+    (setq *nx-proclaimed-inline* table))))
+
+(defun proclaimed-special-p (sym)
+  (%ilogbitp $sym_vbit_special (%symbol-bits sym)))
+
+(defun proclaimed-inline-p (sym)
+  (if (listp *nx-proclaimed-inline*)
+    (%cdr (assq sym *nx-proclaimed-inline*))
+    (gethash sym *nx-proclaimed-inline*)))
+
+(defun proclaimed-notinline-p (sym)
+  (if (listp *nx-proclaimed-inline*)
+    (and (setq sym (assq sym *nx-proclaimed-inline*))
+         (null (%cdr sym)))
+    (null (gethash sym *nx-proclaimed-inline* t))))
+
+
+(defun self-evaluating-p (form)
+  (and (atom form)
+       (or (not (non-nil-symbol-p form))
+           (eq form t)
+           (keywordp form))))
+
+(defun constantp (form &optional env)
+  "True of any Lisp object that has a constant value: types that eval to
+  themselves, keywords, constants, and list whose car is QUOTE."
+   (or (self-evaluating-p form)
+       (quoted-form-p form)
+       (constant-symbol-p form)
+       (and env
+	    (symbolp form)
+	    (eq :constant (variable-information form env)))))
+
+
+(defun eval-constant (form)
+  (if (quoted-form-p form) (%cadr form)
+    (if (constant-symbol-p form) (symbol-value form)
+      (if (self-evaluating-p form) form
+	(report-bad-arg form '(satisfies constantp))))))
+
+(defvar *lfun-names*)
+
+
+(defvar %lambda-lists% (make-hash-table :test #'eq :weak t))
+(defparameter *save-arglist-info* t)
+
+
+(defun record-arglist (name args)
+  "Used by defmacro & defgeneric"
+  (when (or *save-arglist-info* *save-local-symbols*)
+    (setf (gethash name %lambda-lists%) args)))
+
+
+;;;Support the simple case of defsetf.
+(%fhave 'store-setf-method
+        (qlfun bootstrapping-store-setf-method (name fn &optional doc)
+          (declare (ignore doc))
+          (put name 'bootstrapping-setf-method (require-type fn 'symbol))))
+(%fhave '%setf-method
+        (qlfun bootstrapping-%setf-method (name)
+          (get name 'bootstrapping-setf-method)))
+
+
+;;; defmacro uses (setf (assq ...) ...) for &body forms.
+(defun adjoin-assq (indicator alist value)
+  (let ((cell (assq indicator alist)))
+    (if cell 
+      (setf (cdr cell) value)
+      (push (cons indicator value) alist)))
+  alist)
+
+(defmacro setf-assq (indicator place value)
+  (let ((res (gensym)))
+    `(let (,res)
+       (setf ,place (adjoin-assq ,indicator ,place (setq ,res ,value)))
+       ,res)))
+
+(defsetf assq setf-assq)
+(defsetf %typed-miscref %typed-miscset)
+
+(defun quoted-form-p (form)
+   (and (consp form)
+        (eq (%car form) 'quote)
+        (consp (%cdr form))
+        (null (%cdr (%cdr form)))))
+
+(defun lambda-expression-p (form)
+  (and (consp form)
+       (eq (%car form) 'lambda)
+       (consp (%cdr form))
+       (listp (%cadr form))))
+
+;;;;;FUNCTION BINDING Functions
+
+;;; A symbol's entrypoint contains:
+;;;  1) something tagged as $t_lfun if the symbol is
+;;;     not fbound as a macro or special form;
+;;;  2) a cons, otherwise, where the cdr is a fixnum
+;;;     whose value happens to be the same bit-pattern
+;;;     as a "jsr_subprim $sp-apply-macro" instruction.
+;;;     The car of this cons is either:
+;;;     a) a function -> macro-function;
+;;;     b) a symbol: special form not redefined as a macro.
+;;;     c) a cons whose car is a function -> macro function defined
+;;;        on a special form.
+
+
+
+
+(defun symbol-function (name)
+  "Return the definition of NAME, even if it is a macro or a special form.
+   Error if NAME doesn't have a definition."
+  (or (fboundp name) ;Our fboundp returns the binding
+      (prog1 (%err-disp $xfunbnd name))))
+
+(%fhave 'fdefinition #'symbol-function)
+
+
+(defun kernel-function-p (f)
+  (declare (ignore f))
+  nil)
+
+(defun %make-function (name fn env)
+  (compile-user-function fn name env))
+    
+;;;;;;;;; VALUE BINDING Functions
+
+(defun gensym (&optional (string-or-integer nil string-or-integer-p))
+  "Creates a new uninterned symbol whose name is a prefix string (defaults
+   to \"G\"), followed by a decimal number. Thing, when supplied, will
+   alter the prefix if it is a string, or be used for the decimal number
+   if it is a number, of this symbol. The default value of the number is
+   the current value of *gensym-counter* which is incremented each time
+   it is used."
+  (let ((prefix "G")
+        (counter nil))
+    (when string-or-integer-p
+      (etypecase string-or-integer
+        (integer (setq counter string-or-integer)) ; & emit-style-warning
+        (string (setq prefix (ensure-simple-string string-or-integer)))))
+    (unless counter
+      (setq *gensym-counter* (1+ (setq counter *gensym-counter*))))
+    (make-symbol (%str-cat prefix (%integer-to-string counter)))))
+
+(defun make-keyword (name)
+  (if (and (symbolp name) (eq (symbol-package name) *keyword-package*))
+    name
+    (values (intern (string name) *keyword-package*))))
+
+
+
+
+; destructive, removes first match only
+(defun remove-from-alist (thing alist)
+ (let ((start alist))
+  (if (eq thing (%caar alist))
+   (%cdr alist)
+   (let* ((prev start)
+          (this (%cdr prev))
+          (next (%cdr this)))
+    (while this
+     (if (eq thing (%caar this))
+      (progn
+       (%rplacd prev next)
+       (return-from remove-from-alist start))
+      (setq prev this
+            this next
+            next (%cdr next))))
+    start))))
+
+;destructive
+(defun add-to-alist (thing val alist &aux (pair (assq thing alist)))
+  (if pair
+    (progn (%rplacd pair thing) alist)
+    (cons (cons thing val) alist)))
+
+;non-destructive...
+(defun alist-adjoin (thing val alist &aux (pair (assq thing alist)))
+  (if (and pair (eq (%cdr pair) val))
+    alist
+    (cons (cons thing val) alist)))
+
+(defun %str-assoc (str alist)
+  (assoc str alist :test #'string-equal))
+
+(defstatic *pathname-escape-character*
+  #+windows-target #\'
+  #-windows-target #\\
+  "Not CL.  A Coral addition for compatibility between CL spec and the shell.")
+
+
+(defun caar (x)
+  "Return the car of the 1st sublist."
+ (car (car x)))
+
+(defun cadr (x)
+  "Return the 2nd object in a list."
+ (car (cdr x)))
+
+(defun cdar (x)
+  "Return the cdr of the 1st sublist."
+ (cdr (car x)))
+
+(defun cddr (x)
+  "Return all but the 1st two objects of a list."
+
+ (cdr (cdr x)))
+
+(defun caaar (x)
+  "Return the 1st object in the caar of a list."
+ (car (car (car x))))
+
+(defun caadr (x)
+  "Return the 1st object in the cadr of a list."
+ (car (car (cdr x))))
+
+(defun cadar (x)
+  "Return the car of the cdar of a list."
+ (car (cdr (car x))))
+
+(defun caddr (x)
+  "Return the 1st object in the cddr of a list."
+ (car (cdr (cdr x))))
+
+(defun cdaar (x)
+  "Return the cdr of the caar of a list."
+ (cdr (car (car x))))
+
+(defun cdadr (x)
+  "Return the cdr of the cadr of a list."
+ (cdr (car (cdr x))))
+
+(defun cddar (x)
+  "Return the cdr of the cdar of a list."
+ (cdr (cdr (car x))))
+
+(defun cdddr (x)
+  "Return the cdr of the cddr of a list."
+ (cdr (cdr (cdr x))))
+
+(defun cadddr (x)
+  "Return the car of the cdddr of a list."
+ (car (cdr (cdr (cdr x)))))
+
+(%fhave 'type-of #'%type-of)
+
+
+
+(defun pointerp (thing &optional errorp)
+  (if (macptrp thing)
+    t
+    (if errorp (error "~S is not a pointer" thing) nil)))
+
+
+;Add an item to a dialog items list handle.  HUH ?
+(defun %rsc-string (n)
+  (or (cdr (assq n *error-format-strings*))
+  (%str-cat "Error #" (%integer-to-string n))))
+
+(defun string-arg (arg)
+ (or (string-argp arg) (error "~S is not a string" arg)))
+
+(defun string-argp (arg)
+  (cond ((symbolp arg) (symbol-name arg))
+        ((typep arg 'character) (string arg))
+        ((stringp arg) (ensure-simple-string arg))
+        (t nil)))
+  
+(defun symbol-arg (arg)
+  (unless (symbolp arg)
+    (report-bad-arg arg 'symbol))
+  arg)
+
+(defun %cstrlen (ptr)
+  ;;(#_strlen ptr)
+  (do* ((i 0 (1+ i)))
+       ((zerop (the fixnum (%get-byte ptr i))) i)
+    (declare (fixnum i))))
+
+
+(defun %set-cstring (ptr string)
+  (%cstr-pointer string ptr)
+  string)
+
+(defsetf %get-cstring %set-cstring)
+
+;;; Deprecated, but used by UFFI.
+(defun %put-cstring (ptr str &optional (offset 0))
+  (setf (%get-cstring (%inc-ptr ptr offset)) str)
+  ;; 0 is the traditional, not-very-useful return value ...
+  0)
+
+
+
+
+
+
+;;; Returns a simple string and adjusted start and end, such that
+;;; 0<= start <= end <= (length simple-string).
+(defun get-sstring (str &optional (start 0) (end (length (require-type str 'string))))
+  (multiple-value-bind (sstr offset) (array-data-and-offset (string str))
+    (setq start (+ start offset) end (+ end offset))
+    (when (< (length sstr) end)(setq end (length sstr)))
+    (when (< end start) (setq start end))
+    (values sstr start end)))
+
+;e.g. (bad-named-arg :key key 'function)
+(defun bad-named-arg (name arg &optional (type nil type-p))
+  (if type-p
+    (%err-disp $err-bad-named-arg-2 name arg type)
+    (%err-disp $err-bad-named-arg name arg)))
+
+(defun verify-arg-count (call min &optional max)
+  "If call contains less than MIN number of args, or more than MAX
+   number of args, error. Otherwise, return call.
+   If Max is NIL, the maximum args for the fn are infinity."
+ (or (verify-call-count (car call) (%cdr call) min max) call))
+
+(defun verify-call-count (sym args min &optional max &aux argcount)
+  (if (%i< (setq argcount  (list-length args)) min)
+    (%err-disp $xtoofew (cons sym args))
+    (if (if max (%i> argcount max))
+      (%err-disp $xtoomany (cons sym args)))))
+
+(defun getf (place key &optional (default ()))
+  "Search the property list stored in Place for an indicator EQ to INDICATOR.
+  If one is found, return the corresponding value, else return DEFAULT."
+  (let ((p (pl-search place key))) (if p (%cadr p) default)))
+
+(defun remprop (symbol key)
+  "Look on property list of SYMBOL for property with specified
+  INDICATOR. If found, splice this indicator and its value out of
+  the plist, and return the tail of the original list starting with
+  INDICATOR. If not found, return () with no side effects.
+
+  NOTE: The ANSI specification requires REMPROP to return true (not false)
+  or false (the symbol NIL). Portable code should not rely on any other value."
+  (do* ((prev nil plist)
+        (plist (symbol-plist symbol) tail)
+        (tail (cddr plist) (cddr tail)))
+       ((null plist))
+    (when (eq (car plist) key)
+      (if prev
+        (rplacd (cdr prev) tail)
+        (setf (symbol-plist symbol) tail))
+      (return t))))
+
+
+
+;;; If this returns non-nil, safe to do %rplaca of %cdr to update.
+(defun pl-search (plist key)
+  (unless (plistp plist)
+    (report-bad-arg plist '(satisfies plistp)))
+  (%pl-search plist key))
+
+
+(defun rassoc (item alist &key (test #'eql test-p) test-not (key #'identity))
+  (declare (list alist))
+  "Return the cons in ALIST whose CDR is equal (by a given test or EQL) to
+   the ITEM."
+  (if (or test-p (not test-not))
+    (progn
+      (if test-not (error "Cannot specify both :TEST and :TEST-NOT."))
+      (dolist (pair alist)
+        (if (atom pair)
+          (if pair (error "Invalid alist containing ~S: ~S" pair alist))
+          (when (funcall test item (funcall key (cdr pair))) (return pair)))))
+    (progn
+      (unless test-not (error "Must specify at least one of :TEST or :TEST-NOT"))
+      (dolist (pair alist)
+        (if (atom pair)
+          (if pair (error "Invalid alist containing ~S: ~S" pair alist))
+          (unless (funcall test-not item (funcall key (cdr pair))) (return pair)))))))
+
+(defun *%saved-method-var%* ()
+  (declare (special %saved-method-var%))
+  %saved-method-var%)
+
+(defun set-*%saved-method-var%* (new-value)
+  (declare (special %saved-method-var%))
+  (setq %saved-method-var% new-value))
+
+(defsetf *%saved-method-var%* set-*%saved-method-var%*)
+
+
+
+
+
+
+(setf (symbol-function 'clear-type-cache) #'false)      ; bootstrapping
+
+(defun make-array-1 (dims element-type element-type-p
+                          displaced-to
+                          displaced-index-offset
+                          adjustable
+                          fill-pointer
+                          initial-element initial-element-p
+                          initial-contents initial-contents-p
+                          size)
+  (let ((subtype (element-type-subtype element-type)))
+    (when (and element-type (null subtype))
+      (error "Unknown element-type ~S" element-type))
+    (when (null size)
+      (cond ((listp dims)
+             (setq size 1)
+             (dolist (dim dims)
+               (when (< dim 0)
+                 (report-bad-arg dim '(integer 0 *)))
+               (setq size (* size dim))))
+            (t (setq size dims)))) ; no need to check vs. array-dimension-limit
+    (cond
+     (displaced-to
+      (when (or initial-element-p initial-contents-p)
+        (error "Cannot specify initial values for displaced arrays"))
+      (when (and element-type-p
+                 (neq (array-element-subtype displaced-to) subtype))
+        (error "The ~S array ~S is not of ~S ~S"
+               :displaced-to displaced-to :element-type element-type))
+      (%make-displaced-array dims displaced-to
+                             fill-pointer adjustable displaced-index-offset t))
+     (t
+      (when displaced-index-offset
+        (error "Cannot specify ~S for non-displaced-array" :displaced-index-offset))
+      (when (null subtype)
+        (error "Cannot make an array of empty type ~S" element-type))
+      (make-uarray-1 subtype dims adjustable fill-pointer 
+                     initial-element initial-element-p
+                     initial-contents initial-contents-p
+                     nil size)))))
+
+(defun %make-simple-array (subtype dims)
+  (let* ((size (if (listp dims) (apply #'* dims) dims))
+         (vector (%alloc-misc size subtype)))
+    (if (and (listp dims)
+             (not (eql (length dims) 1)))
+      (let* ((array (%make-displaced-array dims vector)))
+        (%set-simple-array-p array)
+        array)
+      vector)))
+
+(defun make-uarray-1 (subtype dims adjustable fill-pointer
+                              initial-element initial-element-p
+                              initial-contents initial-contents-p
+                              temporary 
+                              size)
+  (declare (ignore temporary))
+  (when (null size)(setq size (if (listp dims)(apply #'* dims) dims)))
+  (let ((vector (%alloc-misc size subtype)))  ; may not get here in that case
+    (if initial-element-p
+      (dotimes (i (uvsize vector)) (declare (fixnum i))(uvset vector i initial-element))
+      (if initial-contents-p
+        (if (null dims) (uvset vector 0 initial-contents)
+            (init-uvector-contents vector 0 dims initial-contents))))
+    (if (and (null fill-pointer)
+             (not adjustable)
+             dims
+             (or (atom dims) (null (%cdr dims))))
+      vector
+      (let ((array (%make-displaced-array dims vector 
+                                          fill-pointer adjustable nil)))
+        (when (and (null fill-pointer) (not adjustable))
+          (%set-simple-array-p array))
+        array))))
+
+(defun init-uvector-contents (vect offset dims contents
+                              &aux (len (length contents)))
+  "Returns final offset. Assumes dims not ()."
+  (unless (eq len (if (atom dims) dims (%car dims)))
+    (error "~S doesn't match array dimensions of ~S ."  contents vect))
+  (cond ((or (atom dims) (null (%cdr dims)))
+         (if (listp contents)
+           (let ((contents-tail contents))
+             (dotimes (i len)
+               (declare (fixnum i))
+               (uvset vect offset (pop contents-tail))
+               (setq offset (%i+ offset 1))))
+           (dotimes (i len)
+             (declare (fixnum i))
+             (uvset vect offset (elt contents i))
+             (setq offset (%i+ offset 1)))))
+        (t (setq dims (%cdr dims))
+           (if (listp contents)
+             (let ((contents-tail contents))
+               (dotimes (i len)
+                 (declare (fixnum i))
+                 (setq offset
+                       (init-uvector-contents vect offset dims (pop contents-tail)))))
+             (dotimes (i len)
+               (declare (fixnum i))
+               (setq offset
+                     (init-uvector-contents vect offset dims (elt contents i)))))))
+  offset)
+
+(defun %get-signed-long-long (ptr &optional (offset 0))
+  (%%get-signed-longlong ptr offset))
+
+(defun %set-signed-long-long (ptr arg1
+				  &optional
+				  (arg2 (prog1 arg1 (setq arg1 0))))
+  (%%set-signed-longlong ptr arg1 arg2))
+				  
+(defun %get-unsigned-long-long (ptr &optional (offset 0))
+  (%%get-unsigned-longlong ptr offset))
+
+(defun %set-unsigned-long-long (ptr arg1
+				  &optional
+				  (arg2 (prog1 arg1 (setq arg1 0))))
+  (%%set-unsigned-longlong ptr arg1 arg2))
+
+(defun %composite-pointer-ref (size pointer offset)
+  (declare (ignorable size))
+  (%inc-ptr pointer offset))
+
+(defun %set-composite-pointer-ref (size pointer offset new)
+  (#_memmove (%inc-ptr pointer offset)
+             new
+             size))
+
+
+(defsetf %composite-pointer-ref %set-composite-pointer-ref)
+
+
+(defsetf pathname-encoding-name set-pathname-encoding-name)
+
+;end of L1-utils.lisp
+
Index: /branches/new-random/level-1/level-1.lisp
===================================================================
--- /branches/new-random/level-1/level-1.lisp	(revision 13309)
+++ /branches/new-random/level-1/level-1.lisp	(revision 13309)
@@ -0,0 +1,107 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; Level-1.lisp
+
+(in-package "CCL")
+
+(macrolet ((l1-load (name)
+	     (let* ((namestring
+		     (concatenate 'simple-base-string
+                                  "./l1-fasls/"
+				  (string name)
+                                  (namestring (backend-target-fasl-pathname
+                                               *target-backend*)))))
+	       `(%fasload ,namestring)))
+	   (bin-load (name)
+	     (let* ((namestring
+		     (concatenate 'simple-base-string
+                                  "./bin/"
+				  (string name)
+                                  (namestring (backend-target-fasl-pathname
+                                               *target-backend*)))))
+	       `(%fasload ,namestring))))
+
+  (l1-load "l1-cl-package")
+  (l1-load "l1-utils")
+  (l1-load "l1-init")
+  (l1-load "l1-symhash")
+  (l1-load "l1-numbers")
+  (l1-load "l1-aprims")
+  #+ppc-target
+  (l1-load "ppc-callback-support")
+  #+x86-target
+  (l1-load "x86-callback-support")
+  (l1-load "l1-callbacks")
+  (l1-load "l1-sort")
+  (bin-load "lists")
+  (bin-load "sequences")
+  (l1-load "l1-dcode")
+  (l1-load "l1-clos-boot")
+  (bin-load "hash")
+  (l1-load "l1-clos")
+  (bin-load "defstruct")
+  (bin-load "dll-node")
+  (l1-load "l1-unicode")
+  (l1-load "l1-streams")
+  (l1-load "linux-files")
+  (bin-load "chars")
+  (l1-load "l1-files")
+  (provide "SEQUENCES")
+  (provide "DEFSTRUCT")
+  (provide "CHARS")
+  (provide "LISTS")
+  (provide "DLL-NODE")
+  (l1-load "l1-typesys")
+  (l1-load "sysutils")
+  #+ppc-target
+  (l1-load "ppc-threads-utils")
+  #+x86-target
+  (l1-load "x86-threads-utils")
+  (l1-load "l1-lisp-threads")
+  (l1-load "l1-application")
+  (l1-load "l1-processes")
+  (l1-load "l1-io")
+  (l1-load "l1-reader")
+  (l1-load "l1-readloop")
+  (l1-load "l1-readloop-lds")
+  (l1-load "l1-error-system")
+
+  (l1-load "l1-events")
+  #+ppc-target
+  (l1-load "ppc-trap-support")
+  #+x86-target
+  (l1-load "x86-trap-support")
+  (l1-load "l1-format")
+  (l1-load "l1-sysio")
+  (l1-load "l1-pathnames")
+  (l1-load "l1-boot-lds")
+
+  (l1-load "l1-boot-1")
+  (l1-load "l1-boot-2")
+  (l1-load "l1-boot-3")
+
+  )
+
+(require "PREPARE-MCL-ENVIRONMENT")
+(progn
+  (%set-toplevel #'(lambda ()
+                     (setq *loading-file-source-file* nil
+                           *loading-toplevel-location* nil)
+                     (toplevel-loop)))
+  (set-user-environment t)
+  (toplevel))
Index: /branches/new-random/level-1/linux-files.lisp
===================================================================
--- /branches/new-random/level-1/linux-files.lisp	(revision 13309)
+++ /branches/new-random/level-1/linux-files.lisp	(revision 13309)
@@ -0,0 +1,2385 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defconstant unix-to-universal-time 2208988800)
+
+#+windows-target
+(progn
+
+
+            
+
+(defun nbackslash-to-forward-slash (namestring)
+  (dotimes (i (length namestring) namestring)
+    (when (eql (schar namestring i) #\\)
+      (setf (schar namestring i) #\/))))
+
+(defconstant univeral-time-start-in-windows-seconds 9435484800)
+
+(defun windows-filetime-to-universal-time (ft)
+  (let* ((100-ns (dpb (pref ft #>FILETIME.dwHighDateTime) (byte 32 32)
+                      (pref ft #>FILETIME.dwLowDateTime)))
+         (seconds-since-windows-epoch (floor 100-ns 10000000)))
+    (- seconds-since-windows-epoch univeral-time-start-in-windows-seconds)))
+)
+
+(defun get-foreign-namestring (pointer)
+  ;; On Darwin, foreign namestrings are encoded in UTF-8 and
+  ;; are canonically decomposed (NFD).  Use PRECOMPOSE-SIMPLE-STRING
+  ;; to ensure that the string is "precomposed" (NFC), like the
+  ;; rest of the world and most sane people would expect.
+  #+darwin-target
+  (precompose-simple-string (%get-utf-8-cstring pointer))
+  #+windows-target (nbackslash-to-forward-slash
+                     (%get-native-utf-16-cstring pointer))
+  ;; On some other platforms, the namestring is assumed to
+  ;; be encoded according to the current locale's character
+  ;; encoding (though FreeBSD seems to be moving towards
+  ;; precomposed UTF-8.).
+  #-(or darwin-target windows-target)
+  (let* ((encoding-name (pathname-encoding-name)))
+    (if encoding-name
+      (get-encoded-cstring encoding-name pointer)
+      (%get-cstring pointer))))
+
+(defun nanoseconds (n)
+  (unless (and (typep n 'fixnum)
+               (>= (the fixnum n) 0))
+    (check-type n (real 0 #.(1- (ash 1 (1- target::nbits-in-word))))))
+  (multiple-value-bind (q r)
+      (floor n)
+    (if (zerop r)
+      (setq r 0)
+      (setq r (floor (* r 1000000000))))
+    (values q r)))
+
+(defun milliseconds (n)
+  (unless (and (typep n 'fixnum)
+               (>= (the fixnum n) 0))
+    (check-type n (real 0 #.(1- (ash 1 (1- target::nbits-in-word))))))
+  (multiple-value-bind (q r)
+      (floor n)
+    (if (zerop r)
+      (setq r 0)
+      (setq r (floor (* r 1000))))
+    (values q r)))
+
+(defun microseconds (n)
+  (unless (and (typep n 'fixnum)
+               (>= (the fixnum n) 0))
+    (check-type n (real 0 #.(1- (ash 1 (1- target::nbits-in-word))))))
+  (multiple-value-bind (q r)
+      (floor n)
+    (if (zerop r)
+      (setq r 0)
+      (setq r (floor (* r 1000000))))
+    (values q r)))
+
+(defun semaphore-value (s)
+  (if (istruct-typep s 'semaphore)
+    (semaphore.value s)
+    (semaphore-value (require-type s 'semaphore))))
+
+(defun %wait-on-semaphore-ptr (s seconds milliseconds &optional flag)
+  (if flag
+    (if (istruct-typep flag 'semaphore-notification)
+      (setf (semaphore-notification.status flag) nil)
+      (report-bad-arg flag 'semaphore-notification)))
+  (without-interrupts
+   (let* ((status (ff-call
+                   (%kernel-import target::kernel-import-wait-on-semaphore)
+                   :address s
+                   :unsigned seconds
+                   :unsigned milliseconds
+                   :signed))
+          (result (zerop status)))     
+     (declare (fixnum status))
+     (when flag (setf (semaphore-notification.status flag) result))
+     (values result status))))
+
+(defun %process-wait-on-semaphore-ptr (s seconds milliseconds &optional
+                                         (whostate "semaphore wait") flag)
+  (or (%wait-on-semaphore-ptr s 0 0 flag)
+      (with-process-whostate  (whostate)
+        (loop
+          (when (%wait-on-semaphore-ptr s seconds milliseconds flag)
+            (return))))))
+
+  
+(defun wait-on-semaphore (s &optional flag (whostate "semaphore wait"))
+  "Wait until the given semaphore has a positive count which can be
+atomically decremented."
+  (%process-wait-on-semaphore-ptr (semaphore-value s) #xffffff 0 whostate flag)
+  t)
+
+
+(defun %timed-wait-on-semaphore-ptr (semptr duration notification)
+  (or (%wait-on-semaphore-ptr semptr 0 0 notification)
+      (with-process-whostate ("Semaphore timed wait")
+        (multiple-value-bind (secs millis) (milliseconds duration)
+          (let* ((now (get-internal-real-time))
+                 (stop (+ now
+                          (* secs 1000)
+                          millis)))
+            (loop
+              (multiple-value-bind (success err)
+                  (progn
+                    (%wait-on-semaphore-ptr semptr secs millis notification))
+                (when success
+                  (return t))
+                (when (or (not (eql err #$EINTR))
+                          (>= (setq now (get-internal-real-time)) stop))
+                  (return nil))
+                (unless (zerop duration)
+                  (let* ((diff (- stop now)))
+                    (multiple-value-bind (remaining-seconds remaining-millis)
+                        (floor diff 1000)
+                      (setq secs remaining-seconds
+                            millis remaining-millis)))))))))))
+
+(defun timed-wait-on-semaphore (s duration &optional notification)
+  "Wait until the given semaphore has a postive count which can be
+atomically decremented, or until a timeout expires."
+  (%timed-wait-on-semaphore-ptr (semaphore-value s) duration notification))
+
+
+(defun %signal-semaphore-ptr (p)
+  (ff-call
+   (%kernel-import target::kernel-import-signal-semaphore)
+   :address p
+   :signed-fullword))
+
+(defun signal-semaphore (s)
+  "Atomically increment the count of a given semaphore."
+  (%signal-semaphore-ptr (semaphore-value s)))
+
+(defun %os-getcwd (buf noctets)
+  ;; Return N < 0, if error
+  ;;        N < noctets: success, string is of length N (octets).
+  ;;        N >= noctets: buffer needs to be larger.
+  (let* ((p #+windows-target
+           (#__wgetcwd buf (ash noctets -1))
+           #-windows-target
+           (#_getcwd buf noctets)))
+    (declare (dynamic-extent p))
+    (if (%null-ptr-p p)
+      (let* ((err (%get-errno)))
+	(if (eql err (- #$ERANGE))
+	  (+ noctets noctets)
+	  err))
+      #+windows-target
+      (do* ((i 0 (+ i 2)))
+           ((= i noctets) (+ noctets noctets))
+        (when (eql (%get-unsigned-word buf i) 0)
+          (return i)))
+      #-windows-target
+      (dotimes (i noctets (+ noctets noctets))
+	(when (eql 0 (%get-byte buf i))
+	  (return i))))))
+
+(defun temp-pathname ()
+  "Return a suitable pathname for a temporary file.  A different name is returned
+each time this is called in a session.  No file by that name existed when last
+checked, though no guarantee is given that one hasn't been created since."
+  (native-to-pathname
+     #-windows-target (get-foreign-namestring (#_tmpnam (%null-ptr)))
+     #+windows-target (rlet ((buffer (:array :wchar_t #.#$MAX_PATH)))
+                        (#_GetTempPathW #$MAX_PATH buffer)
+                        (with-filename-cstrs ((c-prefix "ccl")) 
+                            (#_GetTempFileNameW buffer c-prefix 0 buffer)
+                              (#_DeleteFileW buffer)
+                                (%get-native-utf-16-cstring buffer)))))
+
+(defun current-directory-name ()
+  "Look up the current working directory of the Clozure CL process; unless
+it has been changed, this is the directory Clozure CL was started in."
+  (flet ((try-getting-dirname (bufsize)
+	   (%stack-block ((buf bufsize))
+	     (let* ((len (%os-getcwd buf bufsize)))
+	       (cond ((< len 0) (%errno-disp len))
+		     ((< len bufsize)
+		      (setf (%get-unsigned-byte buf len) 0)
+		      (values (get-foreign-namestring buf) len))
+		     (t (values nil len)))))))
+    (do* ((string nil)
+	  (len #+windows-target 128 #-windows-target 64)
+	  (bufsize len len))
+	 ((multiple-value-setq (string len) (try-getting-dirname bufsize))
+	  string))))
+
+
+(defun current-directory ()
+  (mac-default-directory))
+
+(defun (setf current-directory) (path)
+  (cwd path)
+  path)
+
+(defun cd (path)
+  (cwd path))
+
+
+
+
+(defun %chdir (dirname)
+  (with-filename-cstrs ((dirname dirname))
+    (int-errno-call (#+windows-target #__wchdir #-windows-target #_chdir dirname))))
+
+(defun %mkdir (name mode)
+  #+windows-target (declare (ignore mode))
+  (let* ((name name)
+         (len (length name)))
+    (when (and (> len 0) (eql (char name (1- len)) #\/))
+      (setq name (subseq name 0 (1- len))))
+    (with-filename-cstrs ((name name))
+      (int-errno-call (#+windows-target #__wmkdir #-windows-target #_mkdir  name #-windows-target mode)))))
+
+(defun %rmdir (name)
+  (let* ((last (1- (length name))))
+    (with-filename-cstrs ((name name))
+      (when (and (>= last 0)
+		 (eql (%get-byte name last) (char-code #\/)))
+	(setf (%get-byte name last) 0))
+      (int-errno-call (#+windows-target #__wrmdir #-windows-target #_rmdir  name)))))
+
+
+(defun getenv (key)
+  "Look up the value of the environment variable named by name, in the
+OS environment."
+  (with-cstrs ((key (string key)))
+    (let* ((env-ptr (%null-ptr)))
+      (declare (dynamic-extent env-ptr))
+      (%setf-macptr env-ptr (#_getenv key))
+      (unless (%null-ptr-p env-ptr)
+	(%get-cstring env-ptr))))
+  )
+
+(defun setenv (key value &optional (overwrite t))
+  "Set the value of the environment variable named by name, in the OS
+environment. If there is no such environment variable, create it."
+  #+windows-target (declare (ignore overwrite))
+  #-windows-target
+  (with-cstrs ((ckey key)
+	       (cvalue value))
+    (#_setenv ckey cvalue (if overwrite 1 0)))
+  #+windows-target
+  (with-cstrs ((pair (format nil "~a=~a" key value)))
+    (#__putenv pair))
+  )
+
+#-windows-target                        ; Windows "impersonation" crap ?
+(defun setuid (uid)
+  "Attempt to change the current user ID (both real and effective);
+fails unless the Clozure CL process has super-user privileges or the ID
+given is that of the current user."
+  (int-errno-call (#_setuid uid)))
+
+#-windows-target
+(defun setgid (uid)
+  "Attempt to change the current group ID (both real and effective);
+fails unless the Clozure CL process has super-user privileges or the ID
+given is that of a group to which the current user belongs."
+  (int-errno-call (#_setgid uid)))
+  
+
+;;; On Linux, "stat" & friends are implemented in terms of deeper,
+;;; darker things that need to know what version of the stat buffer
+;;; they're talking about.
+
+#-windows-target
+(defun %stat-values (result stat)
+  (if (eql 0 (the fixnum result)) 
+      (values
+       t
+       (pref stat :stat.st_mode)
+       (pref stat :stat.st_size)
+       #+(or linux-target solaris-target)
+       (pref stat :stat.st_mtim.tv_sec)
+       #-(or linux-target solaris-target)
+       (pref stat :stat.st_mtimespec.tv_sec)
+       (pref stat :stat.st_ino)
+       (pref stat :stat.st_uid)
+       (pref stat :stat.st_blksize)
+       #+(or linux-target solaris-target)
+       (round (pref stat :stat.st_mtim.tv_nsec) 1000)
+       #-(or linux-target solaris-target)
+       (round (pref stat :stat.st_mtimespec.tv_nsec) 1000)
+       (pref stat :stat.st_gid))
+      (values nil nil nil nil nil nil nil)))
+
+#+win64-target
+(defun %stat-values (result stat)
+  (if (eql 0 (the fixnum result)) 
+      (values
+       t
+       (pref stat :_stat64.st_mode)
+       (pref stat :_stat64.st_size)
+       (pref stat :_stat64.st_mtime)
+       (pref stat :_stat64.st_ino)
+       (pref stat :_stat64.st_uid)
+       #$BUFSIZ
+       (pref stat :_stat64.st_mtime)     ; ???
+       (pref stat :_stat64.st_gid))
+      (values nil nil nil nil nil nil nil nil nil)))
+
+#+win32-target
+(defun %stat-values (result stat)
+  (if (eql 0 (the fixnum result)) 
+      (values
+       t
+       (pref stat :__stat64.st_mode)
+       (pref stat :__stat64.st_size)
+       (pref stat :__stat64.st_mtime)
+       (pref stat :__stat64.st_ino)
+       (pref stat :__stat64.st_uid)
+       #$BUFSIZ
+       (pref stat :__stat64.st_mtime)     ; ???
+       (pref stat :__stat64.st_gid))
+      (values nil nil nil nil nil nil nil nil nil)))
+
+#+windows-target
+(defun windows-strip-trailing-slash (namestring)
+  (do* ((len (length namestring) (length namestring)))
+       ((<= len 3) namestring)
+    (let* ((p (1- len))
+           (ch (char namestring p)))
+      (unless (or (eql ch #\\)
+                  (eql ch #\/))
+        (return namestring))
+      (setq namestring (subseq namestring 0 p)))))
+
+
+(defun %%stat (name stat)
+  (with-filename-cstrs ((cname #+windows-target (windows-strip-trailing-slash name) #-windows-target name))
+    (%stat-values
+     #+linux-target
+     (#_ __xstat #$_STAT_VER_LINUX cname stat)
+     #-linux-target
+     (int-errno-ffcall (%kernel-import target::kernel-import-lisp-stat)
+                       :address cname
+                       :address stat
+                       :int)
+     stat)))
+
+(defun %%fstat (fd stat)
+  (%stat-values
+   #+linux-target
+   (#_ __fxstat #$_STAT_VER_LINUX fd stat)
+   #-linux-target
+   (int-errno-ffcall (%kernel-import target::kernel-import-lisp-fstat)
+                     :int fd
+                     :address stat
+                     :int)
+   stat))
+
+#-windows-target
+(defun %%lstat (name stat)
+  (with-filename-cstrs ((cname name))
+    (%stat-values
+     #+linux-target
+     (#_ __lxstat #$_STAT_VER_LINUX cname stat)
+     #-linux-target
+     (#_lstat cname stat)
+     stat)))
+
+
+;;; Returns: (values t mode size mtime inode uid blksize) on success,
+;;;          (values nil nil nil nil nil nil nil) otherwise
+;;; NAME should be a "native namestring", e.g,, have all lisp pathname
+;;; escaping removed.
+#-windows-target
+(defun %stat (name &optional link-p)
+  (rlet ((stat :stat))
+    (if link-p
+      (%%lstat name stat)
+      (%%stat name stat))))
+
+#+windows-target
+(defun %stat (name &optional link-p)
+  (declare (ignore link-p))
+  (rlet ((stat  #+win64-target #>_stat64 #+win32-target #>__stat64))
+    (%%stat name stat)))
+
+(defun %fstat (fd)
+  (rlet ((stat #+win64-target #>_stat64 #+win32-target #>__stat64 #-windows-target :stat))
+    (%%fstat fd stat)))
+
+
+(defun %file-kind (mode &optional fd)
+  (declare (ignorable fd))
+  (when mode
+    (let* ((kind (logand mode #$S_IFMT)))
+      (cond ((eql kind #$S_IFDIR) :directory)
+	    ((eql kind #$S_IFREG) :file)
+            #-windows-target
+	    ((eql kind #$S_IFLNK) :link)
+	    ((eql kind #$S_IFIFO) 
+	     #-windows-target :pipe
+             ;; Windows doesn't seem to be able to distinguish between
+             ;; sockets and pipes.  Since this function is currently
+             ;; (mostly) used for printing streams and since we've
+             ;; already done something fairly expensive (stat, fstat)
+             ;; to get here.  try to distinguish between pipes and
+             ;; sockets by calling #_getsockopt.  If that succeeds,
+             ;; we've got a socket; otherwise, we're probably got a pipe.
+	     #+windows-target (rlet ((ptype :int)
+				     (plen :int 4))
+				(if (and fd (eql 0 (#_getsockopt fd #$SOL_SOCKET #$SO_TYPE  ptype plen)))
+				    :socket
+				    :pipe)))
+            #-windows-target
+	    ((eql kind #$S_IFSOCK) :socket)
+	    ((eql kind #$S_IFCHR) :character-special)
+	    (t :special)))))
+
+(defun %unix-file-kind (native-namestring &optional check-for-link)
+  (%file-kind (nth-value 1 (%stat native-namestring check-for-link))))
+
+(defun %unix-fd-kind (fd)
+  (if (isatty fd)
+    :tty
+    (%file-kind (nth-value 1 (%fstat fd)) fd)))
+
+#-windows-target
+(defun %uts-string (result idx buf)
+  (if (>= result 0)
+    (%get-cstring (%inc-ptr buf (* #+linux-target #$_UTSNAME_LENGTH
+				   #+darwin-target #$_SYS_NAMELEN
+                                   #+(or freebsd-target solaris-target) #$SYS_NMLN
+                                   idx)))
+    "unknown"))
+
+#-windows-target
+(defun copy-file-attributes (source-path dest-path)
+  "Copy the mode, owner, group and modification time of source-path to dest-path.
+   Returns T if succeeded, NIL if some of the attributes couldn't be copied due to
+   permission problems.  Any other failures cause an error to be signalled"
+  (multiple-value-bind (win mode ignore mtime-sec ignore uid ignore mtime-usec gid)
+                       (%stat (native-translated-namestring source-path) t)
+    (declare (ignore ignore))
+    (unless win
+      (error "Cannot get attributes of ~s" source-path))
+    (with-filename-cstrs ((cnamestr (native-translated-namestring dest-path)))
+      (macrolet ((errchk (form)
+                   `(let ((err ,form))
+                      (unless (eql err 0)
+                        (setq win nil)
+                        (when (eql err -1)
+                          (setq err (- (%get-errno))))
+                        (unless (eql err #$EPERM) (%errno-disp err dest-path))))))
+        (errchk (#_chmod cnamestr mode))
+        (errchk (%stack-block ((times (record-length (:array (:struct :timeval) 2))))
+                  (setf (pref times :timeval.tv_sec) mtime-sec)
+                  (setf (pref times :timeval.tv_usec) mtime-usec)
+                  (%incf-ptr times (record-length :timeval))
+                  (setf (pref times :timeval.tv_sec) mtime-sec)
+                  (setf (pref times :timeval.tv_usec) mtime-usec)
+                  (%incf-ptr times (- (record-length :timeval)))
+                  (#_utimes cnamestr times)))
+        (errchk (#_chown cnamestr uid gid))))
+    win))
+
+#+windows-target
+(defun copy-file-attributes (source-path dest-path)
+  "could at least copy the file times"
+  (declare (ignore source-path dest-path)))
+
+
+#+linux-target
+(defun %uname (idx)
+  (%stack-block ((buf (* #$_UTSNAME_LENGTH 6)))  
+    (%uts-string (#_uname buf) idx buf)))
+
+#+darwin-target
+(defun %uname (idx)
+  (%stack-block ((buf (* #$_SYS_NAMELEN 5)))
+    (%uts-string (#_uname buf) idx buf)))
+
+#+freebsd-target
+(defun %uname (idx)
+  (%stack-block ((buf (* #$SYS_NMLN 5)))
+    (%uts-string (#___xuname #$SYS_NMLN buf) idx buf)))
+
+#+solaris-target
+(defun %uname (idx)
+  (%stack-block ((buf (* #$SYS_NMLN 5)))
+    (%uts-string (#_uname buf) idx buf)))
+
+#-windows-target
+(defun fd-dup (fd)
+  (int-errno-call (#_dup fd)))
+
+#+windows-target
+(defun fd-dup (fd &key direction inheritable)
+  (declare (ignore direction))
+  (rlet ((handle #>HANDLE))
+    (if (eql 0 (#_DuplicateHandle (#_GetCurrentProcess)
+                                  (%int-to-ptr fd)
+                                  (#_GetCurrentProcess) 
+                                  handle
+                                  0
+                                  (if inheritable #$TRUE #$FALSE)
+                                  #$DUPLICATE_SAME_ACCESS))
+      (%windows-error-disp (#_GetLastError))
+      (pref handle #>DWORD))))
+
+
+(defun fd-fsync (fd)
+  #+windows-target (#_FlushFileBuffers (%int-to-ptr fd))
+  #-windows-target
+  (int-errno-call (#_fsync fd)))
+
+#-windows-target
+(progn
+(defun fd-get-flags (fd)
+  (int-errno-call (#_fcntl fd #$F_GETFL)))
+
+(defun fd-set-flags (fd new)
+  (int-errno-call (#_fcntl fd #$F_SETFL :int new)))
+
+(defun fd-set-flag (fd mask)
+  (let* ((old (fd-get-flags fd)))
+    (if (< old 0)
+      old
+      (fd-set-flags fd (logior old mask)))))
+
+(defun fd-clear-flag (fd mask)
+  (let* ((old (fd-get-flags fd)))
+    (if (< old 0) 
+      old
+      (fd-set-flags fd (logandc2 old mask)))))
+)
+
+;;; Assume that any quoting's been removed already.
+(defun tilde-expand (namestring)
+  (let* ((len (length namestring)))
+    (if (or (zerop len)
+            (not (eql (schar namestring 0) #\~)))
+      namestring
+      (if (or (= len 1)
+              (eql (schar namestring 1) #\/))
+        (concatenate 'string (get-user-home-dir (getuid)) (if (= len 1) "/" (subseq namestring 1)))
+        #+windows-target namestring
+        #-windows-target
+        (let* ((slash-pos (position #\/ namestring))
+               (user-name (subseq namestring 1 slash-pos))
+               (uid (or (get-uid-from-name user-name)
+                        (error "Unknown user ~s in namestring ~s" user-name namestring))))
+          (concatenate 'string (get-user-home-dir uid) (if slash-pos (subseq namestring slash-pos) "/")))))))
+
+
+#+windows-target
+(defun %windows-realpath (namestring)
+  (with-filename-cstrs ((path namestring))
+    (do* ((bufsize 256))
+         ()
+      (%stack-block ((buf bufsize))
+        (let* ((nchars (#_GetFullPathNameW path (ash bufsize -1) buf (%null-ptr))))
+          (if (eql 0 nchars)
+            (return nil)
+            (let* ((max (+ nchars nchars 2)))
+              (if (> max bufsize)
+                (setq bufsize max)
+                (let* ((real (get-foreign-namestring buf)))
+                  (return (and (%stat real) real)))))))))))
+
+    
+;;; This doesn't seem to exist on VxWorks.  It's a POSIX
+;;; function AFAIK, so the source should be somewhere ...
+
+(defun %realpath (namestring)
+  ;; It's not at all right to just return the namestring here.
+  (when (zerop (length namestring))
+    (setq namestring (current-directory-name)))
+  #+windows-target (%windows-realpath namestring)
+  #-windows-target
+  (%stack-block ((resultbuf #$PATH_MAX))
+    (with-filename-cstrs ((name namestring #|(tilde-expand namestring)|#))
+      (let* ((result (#_realpath name resultbuf)))
+        (declare (dynamic-extent result))
+        (unless (%null-ptr-p result)
+          (get-foreign-namestring result))))))
+
+;;; Return fully resolved pathname & file kind, or (values nil nil)
+
+(defun %probe-file-x (namestring)
+  (let* ((realpath (%realpath namestring))
+	 (kind (if realpath (%unix-file-kind realpath))))
+    (if kind
+      (values realpath kind)
+      (values nil nil))))
+
+;;; The mingw headers define timeval.tv_sec and timeval.tv_usec to be
+;;; signed 32-bit quantities.
+(macrolet ((timeval-ref (ptr accessor)
+             #+windows-target `(logand #xfffffffff (pref ,ptr ,accessor))
+             #-windows-target `(pref ,ptr ,accessor))
+           (set-timeval-ref (ptr accessor new)
+           `(setf (pref ,ptr ,accessor)
+             #+windows-target (u32->s32 ,new)
+             #-windows-target ,new)))
+  
+(defun timeval->milliseconds (tv)
+    (+ (* 1000 (timeval-ref tv :timeval.tv_sec)) (round (timeval-ref tv :timeval.tv_usec) 1000)))
+
+(defun timeval->microseconds (tv)
+    (+ (* 1000000 (timeval-ref tv :timeval.tv_sec)) (timeval-ref tv :timeval.tv_usec)))
+
+(defun %add-timevals (result a b)
+  (let* ((seconds (+ (timeval-ref a :timeval.tv_sec) (timeval-ref b :timeval.tv_sec)))
+	 (micros (+ (timeval-ref a :timeval.tv_usec) (timeval-ref b :timeval.tv_usec))))
+    (if (>= micros 1000000)
+      (setq seconds (1+ seconds) micros (- micros 1000000)))
+    (set-timeval-ref result :timeval.tv_sec seconds)
+    (set-timeval-ref result :timeval.tv_usec micros)
+    result))
+
+(defun %sub-timevals (result a b)
+  (let* ((seconds (- (timeval-ref a :timeval.tv_sec) (timeval-ref b :timeval.tv_sec)))
+	 (micros (- (timeval-ref a :timeval.tv_usec) (timeval-ref b :timeval.tv_usec))))
+    (if (< micros 0)
+      (setq seconds (1- seconds) micros (+ micros 1000000)))
+    (set-timeval-ref result :timeval.tv_sec  seconds)
+    (set-timeval-ref result :timeval.tv_usec micros)
+    result))
+
+;;; Return T iff the time denoted by the timeval a is not later than the
+;;; time denoted by the timeval b.
+(defun %timeval<= (a b)
+  (let* ((asec (timeval-ref a :timeval.tv_sec))
+         (bsec (timeval-ref b :timeval.tv_sec)))
+    (or (< asec bsec)
+        (and (= asec bsec)
+             (< (timeval-ref a :timeval.tv_usec)
+                (timeval-ref b :timeval.tv_usec))))))
+
+); windows signed nonsense.
+
+#-windows-target
+(defun %%rusage (usage &optional (who #$RUSAGE_SELF))
+  (int-errno-call (#_getrusage who usage)))
+
+
+
+
+(defun %file-write-date (namestring)
+  (let* ((date (nth-value 3 (%stat namestring))))
+    (if date
+      (+ date unix-to-universal-time))))
+
+#-windows-target
+(defun %file-author (namestring)
+  (let* ((uid (nth-value 5 (%stat namestring))))
+    (if uid
+      (with-macptrs ((pw (#_getpwuid uid)))
+        (unless (%null-ptr-p pw)
+          (without-interrupts
+           (%get-cstring (pref pw :passwd.pw_name))))))))
+
+#+windows-target
+(defun %file-author (namestring)
+  (declare (ignore namestring))
+  nil)
+
+#-windows-target
+(defun %utimes (namestring)
+  (with-filename-cstrs ((cnamestring namestring))
+    (let* ((err (#_utimes cnamestring (%null-ptr))))
+      (declare (fixnum err))
+      (or (eql err 0)
+          (%errno-disp err namestring)))))
+
+#+windows-target
+(defun %utimes (namestring)
+  (with-filename-cstrs ((cnamestring namestring))
+    (let* ((handle (#_CreateFileW
+                    cnamestring
+                    #$FILE_WRITE_ATTRIBUTES
+                    (logior #$FILE_SHARE_READ #$FILE_SHARE_WRITE)
+                    (%null-ptr)
+                    #$OPEN_EXISTING
+                    #$FILE_FLAG_BACKUP_SEMANTICS
+                    (%null-ptr))))
+      (if (eql handle *windows-invalid-handle*)
+        (%windows-error-disp (#_GetLastError))
+        (rlet ((st #>SYSTEMTIME)
+               (ft #>FILETIME))
+          (#_GetSystemTime st)
+          (#_SystemTimeToFileTime st ft)
+          (let* ((result (#_SetFileTime handle (%null-ptr) (%null-ptr) ft))
+                 (err (when (eql 0 result) (#_GetLastError))))
+            (#_CloseHandle handle)
+            (if err
+              (%windows-error-disp err)
+              t)))))))
+
+
+             
+
+#-windows-target
+(defun get-uid-from-name (name)
+  (with-cstrs ((name name))
+    (let* ((pwent (#_getpwnam name)))
+      (unless (%null-ptr-p pwent)
+        (pref pwent :passwd.pw_uid)))))
+
+
+(defun isatty (fd)
+  #+windows-target (declare (ignore fd))
+  #+windows-target nil
+  #-windows-target
+  (= 1 (#_isatty fd)))
+
+(defun %open-dir (namestring)
+  (with-filename-cstrs ((name namestring))
+    (let* ((DIR (ff-call (%kernel-import target::kernel-import-lisp-opendir)
+                         :address name
+                         :address)))
+      (unless (%null-ptr-p DIR)
+	DIR))))
+
+(defun close-dir (dir)
+  (ff-call (%kernel-import target::kernel-import-lisp-closedir)
+           :address dir
+           :int))
+
+(defun %read-dir (dir)
+  (let* ((res (ff-call (%kernel-import target::kernel-import-lisp-readdir)
+                       :address dir
+                       :address)))
+    (unless (%null-ptr-p res)
+      (get-foreign-namestring (pref res
+                                    #+windows-target :_wdirent.d_name
+                                    #-windows-target :dirent.d_name)))))
+
+
+#-windows-target
+(defun tcgetpgrp (fd)
+  (#_tcgetpgrp fd))
+
+(defun getpid ()
+  "Return the ID of the Clozure CL OS process."
+  #-windows-target
+  (int-errno-call (#_getpid))
+  #+windows-target (#_GetCurrentProcessId))
+
+
+(defun getuid ()
+  "Return the (real) user ID of the current user."
+  #+windows-target 0
+  #-windows-target (int-errno-call (#_getuid)))
+
+(defun get-user-home-dir (userid)
+  "Look up and return the defined home directory of the user identified
+by uid. This value comes from the OS user database, not from the $HOME
+environment variable. Returns NIL if there is no user with the ID uid."
+  #+windows-target
+  (declare (ignore userid))
+  #+windows-target
+  (dolist (k '(#||"HOME"||# "USERPROFILE")) 
+    (with-native-utf-16-cstrs ((key k))
+      (let* ((p (#__wgetenv key)))
+        (unless (%null-ptr-p p)
+          (return (get-foreign-namestring p))))))
+  #-windows-target
+  (rlet ((pwd :passwd)
+         (result :address pwd))
+    (do* ((buflen 512 (* 2 buflen)))
+         ()
+      (%stack-block ((buf buflen))
+        (let* ((err
+                #-solaris-target
+                 (#_getpwuid_r userid pwd buf buflen result)
+                 #+solaris-target
+                 (external-call "__posix_getpwuid_r"
+                                :uid_t userid
+                                :address pwd
+                                :address buf
+                                :int buflen
+                                :address result
+                                :int)))
+          (if (eql 0 err)
+	    (let* ((rp (%get-ptr result))
+		   (dir (and (not (%null-ptr-p rp))
+			     (get-foreign-namestring (pref rp :passwd.pw_dir)))))
+	      (return (if (and dir (eq (%unix-file-kind dir) :directory))
+			dir)))
+            (unless (eql err #$ERANGE)
+              (return nil))))))))
+
+(defun %delete-file (name)
+  (with-cstrs ((n name))
+    (int-errno-call (#+windows-target #__unlink #-windows-target #_unlink n))))
+
+(defun os-command (string)
+  "Invoke the Posix function system(), which invokes the user's default
+system shell (such as sh or tcsh) as a new process, and has that shell
+execute command-line.
+
+If the shell was able to find the command specified in command-line, then
+exit-code is the exit code of that command. If not, it is the exit code
+of the shell itself."
+  (with-cstrs ((s string))
+    (#_system s)))
+
+(defun %strerror (errno)
+  (declare (fixnum errno))
+  (if (< errno 0)
+    (setq errno (- errno)))
+  (with-macptrs (p)
+    (%setf-macptr p (#_strerror errno))
+    (if (%null-ptr-p p)
+      (format nil "OS Error ~d" errno)
+      (%get-cstring p))))
+
+#+windows-target
+(defun %windows-error-string (error-number)  
+  (rlet ((pbuffer :address (%null-ptr)))
+    (if (eql 0
+             (#_FormatMessageW (logior #$FORMAT_MESSAGE_ALLOCATE_BUFFER
+                                       #$FORMAT_MESSAGE_FROM_SYSTEM
+                                       #$FORMAT_MESSAGE_IGNORE_INSERTS
+                                       #$FORMAT_MESSAGE_MAX_WIDTH_MASK)
+                               (%null-ptr)
+                               (abs error-number)
+                               0                 ; default langid, more-or-less
+                               pbuffer
+                               0
+                               (%null-ptr)))
+      (format nil "Windows error ~d" (abs error-number))
+      (let* ((p (%get-ptr pbuffer))
+             (q (%get-native-utf-16-cstring p)))
+        (#_LocalFree p)
+        q))))
+        
+                      
+
+;;; Kind of has something to do with files, and doesn't work in level-0.
+#+(or linux-target freebsd-target solaris-target)
+(defun close-shared-library (lib &key (completely t))
+  "If completely is T, set the reference count of library to 0. Otherwise,
+decrements it by 1. In either case, if the reference count becomes 0,
+close-shared-library frees all memory resources consumed library and causes
+any EXTERNAL-ENTRY-POINTs known to be defined by it to become unresolved."
+  (let* ((lib (if (typep lib 'string)
+		(or (shared-library-with-name lib)
+		    (error "Shared library ~s not found." lib))
+		(require-type lib 'shlib)))
+	 (handle (shlib.handle lib)))
+      (when handle
+	(let* ((found nil)
+	       (base (shlib.base lib)))
+	  (do* ()
+	       ((progn		  
+		  (#_dlclose handle)
+		  (or (not (setq found (shlib-containing-address base)))
+		      (not completely)))))
+	  (when (not found)
+	    (setf (shlib.pathname lib) nil
+	      (shlib.base lib) nil
+              (shlib.handle lib) nil
+	      (shlib.map lib) nil)
+            (unload-foreign-variables lib)
+	    (unload-library-entrypoints lib))))))
+
+#+darwin-target
+;; completely specifies whether to remove it totally from our list
+(defun close-shared-library (lib &key (completely nil))
+  "If completely is T, set the reference count of library to 0. Otherwise,
+decrements it by 1. In either case, if the reference count becomes 0,
+close-shared-library frees all memory resources consumed library and causes
+any EXTERNAL-ENTRY-POINTs known to be defined by it to become unresolved."
+  (let* ((lib (if (typep lib 'string)
+		  (or (shared-library-with-name lib)
+		      (error "Shared library ~s not found." lib))
+		(require-type lib 'shlib))))
+    ;; no possible danger closing libsystem since dylibs can't be closed
+    (cond
+     ((or (not (shlib.map lib)) (not (shlib.base lib)))
+      (error "Shared library ~s uninitialized." (shlib.soname lib)))
+     ((and (not (%null-ptr-p (shlib.map lib)))
+	   (%null-ptr-p (shlib.base lib)))
+      (warn "Dynamic libraries cannot be closed on Darwin."))
+     ((and (%null-ptr-p (shlib.map lib))
+	   (not (%null-ptr-p (shlib.base lib))))
+      ;; we have a bundle type library not sure what to do with the
+      ;; completely flag when we open the same bundle more than once,
+      ;; Darwin gives back a new module address, so we have multiple
+      ;; entries on *shared-libraries* the best we can do is unlink
+      ;; the module asked for (or our best guess based on name) and
+      ;; invalidate any entries which refer to this container
+      (if (= 0 (#_NSUnLinkModule (shlib.base lib) #$NSUNLINKMODULE_OPTION_NONE))
+	  (error "Unable to close shared library, NSUnlinkModule failed.")
+	(progn
+	  (setf (shlib.map lib) nil
+		(shlib.base lib) nil)
+	  (unload-library-entrypoints lib)
+	  (when completely
+	    (setq *shared-libraries* (delete lib *shared-libraries*)))))))))
+
+
+
+
+;;; Foreign (unix) processes.
+
+(defun call-with-string-vector (function strings)
+  (let ((bufsize (reduce #'+ strings
+			 :key #'(lambda (s) (1+ (length (string s))))))
+	(argvsize (ash (1+ (length strings)) target::word-shift))
+	(bufpos 0)
+	(argvpos 0))
+    (%stack-block ((buf bufsize) (argv argvsize))
+      (flet ((init (s)
+	     (multiple-value-bind (sstr start end) (get-sstring s)
+               (declare (fixnum start end))
+	       (let ((len (- end start)))
+                 (declare (fixnum len))
+                 (do* ((i 0 (1+ i))
+                       (start start (1+ start))
+                       (bufpos bufpos (1+ bufpos)))
+                      ((= i len))
+                   (setf (%get-unsigned-byte buf bufpos)
+                         (logand #xff (%scharcode sstr start))))
+		 (setf (%get-byte buf (%i+ bufpos len)) 0)
+		 (setf (%get-ptr argv argvpos) (%inc-ptr buf bufpos))
+		 (setq bufpos (%i+ bufpos len 1))
+		 (setq argvpos (%i+ argvpos target::node-size))))))
+	(declare (dynamic-extent #'init))
+	(map nil #'init strings))
+      (setf (%get-ptr argv argvpos) (%null-ptr))
+      (funcall function argv))))
+
+(defmacro with-string-vector ((var strings) &body body)
+  `(call-with-string-vector #'(lambda (,var) ,@body) ,strings))
+
+(defloadvar *max-os-open-files* #-windows-target (#_getdtablesize) #+windows-target 32)
+
+(defun pipe ()
+  ;;  (rlet ((filedes (:array :int 2)))
+  (%stack-block ((filedes 8))
+    (let* ((status (ff-call (%kernel-import target::kernel-import-lisp-pipe)
+                            :address filedes :int))
+           (errno (if (eql status 0) 0 (%get-errno))))
+      (unless (zerop status)
+        (when (or (eql errno (- #$EMFILE))
+                  (eql errno (- #$ENFILE)))
+          (gc)
+          (drain-termination-queue)
+          (setq status (ff-call (%kernel-import target::kernel-import-lisp-pipe)
+                            :address filedes :int)
+                errno (if (zerop status) 0 (%get-errno)))))
+      (if (zerop status)
+        (values (paref filedes (:array :int)  0) (paref filedes (:array :int)  1))
+        (%errno-disp errno)))))
+
+#-windows-target
+(progn
+  (defun %execvp (argv)
+    (#_execvp (%get-ptr argv) argv)
+    (#_exit #$EX_OSERR))
+
+  (defun exec-with-io-redirection (new-in new-out new-err argv)
+    (#_setpgid 0 0)
+    (if new-in (#_dup2 new-in 0))
+    (if new-out (#_dup2 new-out 1))
+    (if new-err (#_dup2 new-err 2))
+    (do* ((fd 3 (1+ fd)))
+         ((= fd *max-os-open-files*) (%execvp argv))
+      (declare (fixnum fd))
+      (#_close fd)))
+
+
+
+
+
+  (defstruct external-process
+    pid
+    %status
+    %exit-code
+    pty
+    input
+    output
+    error
+    status-hook
+    plist
+    token                               
+    core
+    args
+    (signal (make-semaphore))
+    (completed (make-semaphore))
+    watched-fds
+    watched-streams
+    external-format
+    )
+
+  (defmethod print-object ((p external-process) stream)
+    (print-unreadable-object (p stream :type t :identity t)
+      (let* ((status (external-process-%status p)))
+        (let* ((*print-length* 3))
+          (format stream "~a" (external-process-args p)))
+        (format stream "[~d] (~a" (external-process-pid p) status)
+        (unless (eq status :running)
+          (format stream " : ~d" (external-process-%exit-code p)))
+        (format stream ")"))))
+
+  (defun get-descriptor-for (object proc close-in-parent close-on-error
+                                    &rest keys
+                                    &key direction (element-type 'character)
+                                    (sharing :private)
+                                    external-format
+                                    &allow-other-keys)
+    (etypecase object
+      ((eql t)
+       (values nil nil close-in-parent close-on-error))
+      (null
+       (let* ((null-device #+windows-target "nul" #-windows-target "/dev/null")
+              (fd (fd-open null-device (case direction
+                                         (:input #$O_RDONLY)
+                                         (:output #$O_WRONLY)
+                                         (t #$O_RDWR)))))
+         (if (< fd 0)
+           (signal-file-error fd null-device))
+         (values fd nil (cons fd close-in-parent) (cons fd close-on-error))))
+      ((eql :stream)
+       (multiple-value-bind (read-pipe write-pipe) (pipe)
+         (case direction
+           (:input
+            (values read-pipe
+                    (make-fd-stream write-pipe
+                                    :direction :output
+                                    :element-type element-type
+                                    :interactive nil
+                                    :sharing sharing
+                                    :basic t
+                                    :encoding (external-format-character-encoding external-format)
+                                    :line-termination (external-format-line-termination external-format)
+                                    :auto-close t)
+                    (cons read-pipe close-in-parent)
+                    (cons write-pipe close-on-error)))
+           (:output
+            (values write-pipe
+                    (make-fd-stream read-pipe
+                                    :direction :input
+                                    :element-type element-type
+                                    :interactive nil
+                                    :basic t
+                                    :sharing sharing
+                                    :encoding (external-format-character-encoding external-format)
+                                    :line-termination (external-format-line-termination external-format)
+                                    :auto-close t)
+                    (cons write-pipe close-in-parent)
+                    (cons read-pipe close-on-error)))
+           (t
+            (fd-close read-pipe)
+            (fd-close write-pipe)
+            (report-bad-arg direction '(member :input :output))))))
+      ((or pathname string)
+       (with-open-stream (file (apply #'open object keys))
+         (let* ((fd (fd-dup (ioblock-device (stream-ioblock file t)))))
+           (values fd
+                   nil
+                   (cons fd close-in-parent)
+                   (cons fd close-on-error)))))
+      #||
+      ;; What's an FD-STREAM ?
+      (fd-stream
+       (let ((fd (fd-dup (ioblock-device (stream-ioblock object t)))))
+         (values fd
+                 nil
+                 (cons fd close-in-parent)
+                 (cons fd close-on-error))))
+      ||#
+      (stream
+       (ecase direction
+         (:input
+          (with-cstrs ((template "/tmp/lisp-tempXXXXXX"))
+            (let* ((fd (#_mkstemp template)))
+              (if (< fd 0)
+                (%errno-disp fd))
+              (#_unlink template)
+              (let* ((out (make-fd-stream (fd-dup fd)
+                                          :direction :output
+                                          :encoding (external-format-character-encoding external-format)
+                                          :line-termination (external-format-line-termination external-format))))
+                (loop
+                  (multiple-value-bind (line no-newline)
+                      (read-line object nil nil)
+                    (unless line
+                      (return))
+                    (if no-newline
+                      (write-string line out)
+                      (write-line line out))))
+                (close out))
+              (fd-lseek fd 0 #$SEEK_SET)
+              (values fd nil (cons fd close-in-parent) (cons fd close-on-error)))))
+         (:output
+          (multiple-value-bind (read-pipe write-pipe) (pipe)
+            (push read-pipe (external-process-watched-fds proc))
+            (push object (external-process-watched-streams proc))
+            (incf (car (external-process-token proc)))
+            (values write-pipe
+                    nil
+                    (cons write-pipe close-in-parent)
+                    (cons read-pipe close-on-error))))))))
+
+  (let* ((external-processes ())
+         (external-processes-lock (make-lock)))
+    (defun add-external-process (p)
+      (with-lock-grabbed (external-processes-lock)
+        (push p external-processes)))
+    (defun remove-external-process (p)
+      (with-lock-grabbed (external-processes-lock)
+        (setq external-processes (delete p external-processes))))
+    ;; Likewise
+    (defun external-processes ()
+      (with-lock-grabbed (external-processes-lock)
+        (copy-list external-processes)))
+    )
+
+
+  (defmacro wtermsig (status)
+    `(ldb (byte 7 0) ,status))
+
+  (defmacro wexitstatus (status)
+    `(ldb (byte 8 8) (the fixnum ,status)))
+
+  (defmacro wstopsig (status)
+    `(wexitstatus ,status))
+
+  (defmacro wifexited (status)
+    `(eql (wtermsig ,status) 0))
+
+  (defmacro wifstopped (status)
+    `(eql #x7f (ldb (byte 7 0) (the fixnum ,status))))
+
+  (defun monitor-external-process (p)
+    (let* ((in-fds (external-process-watched-fds p))
+           (out-streams (external-process-watched-streams p))
+           (token (external-process-token p))
+           (terminated)
+           (changed)
+           (maxfd 0)
+           (external-format (external-process-external-format p))
+           (encoding (external-format-character-encoding external-format))
+           (line-termination (external-format-line-termination external-format))
+           (pairs (pairlis
+                   (mapcar (lambda (fd)
+                             (cons fd
+                                   (make-fd-stream fd
+                                                   :direction :input
+                                                   :sharing :private
+                                                   :encoding encoding
+                                                   :line-termination line-termination)))
+                                     in-fds) out-streams)))
+      (%stack-block ((in-fd-set *fd-set-size*))
+        (rlet ((tv #>timeval))
+          (loop
+            (when changed
+              (setq pairs (delete nil pairs :key #'car)
+                    changed nil))
+            (when (and terminated (null pairs))
+              (signal-semaphore (external-process-completed p))
+              (return))
+            (when pairs
+              (fd-zero in-fd-set)
+              (setq maxfd 0)
+              (dolist (p pairs)
+                (let* ((fd (caar p)))
+                  (when (> fd maxfd)
+                    (setq maxfd fd))
+                  (fd-set fd in-fd-set)))
+              (setf (pref tv #>timeval.tv_sec) 1
+                    (pref tv #>timeval.tv_usec) 0)
+              (when (> (#_select (1+ maxfd) in-fd-set (%null-ptr) (%null-ptr) tv)
+                       0)
+                (dolist (p pairs)
+                  (let* ((in-fd (caar p))
+                         (in-stream (cdar p))
+                         (out-stream (cdr p)))
+                    (when (fd-is-set in-fd in-fd-set)
+                      (let* ((buf (make-string 1024))
+                             (n (ignore-errors (read-sequence buf in-stream))))
+                        (declare (dynamic-extent buf))
+                        (if (or (null n) (eql n 0))
+                          (without-interrupts
+                           (decf (car token))
+                           (close in-stream)
+                           (setf (car p) nil changed t))
+                          (write-sequence buf out-stream :end n))))))))
+            (let* ((statusflags (check-pid (external-process-pid p)
+                                           (logior
+                                            (if in-fds #$WNOHANG 0)
+                                            #$WUNTRACED)))
+                   (oldstatus (external-process-%status p)))
+              (cond ((null statusflags)
+                     (remove-external-process p)
+                     (setq terminated t))
+                    ((eq statusflags t)) ; Running.
+                    (t
+                     (multiple-value-bind (status code core)
+                         (cond ((wifstopped statusflags)
+                                (values :stopped (wstopsig statusflags)))
+                               ((wifexited statusflags)
+                                (values :exited (wexitstatus statusflags)))
+                               (t
+                                (let* ((signal (wtermsig statusflags)))
+                                  (declare (fixnum signal))
+                                  (values
+                                   (if (or (= signal #$SIGSTOP)
+                                           (= signal #$SIGTSTP)
+                                           (= signal #$SIGTTIN)
+                                           (= signal #$SIGTTOU))
+                                     :stopped
+                                     :signaled)
+                                   signal
+                                   (logtest #-solaris-target #$WCOREFLAG
+                                            #+solaris-target #$WCOREFLG
+                                            statusflags)))))
+                       (setf (external-process-%status p) status
+                             (external-process-%exit-code p) code
+                             (external-process-core p) core)
+                       (let* ((status-hook (external-process-status-hook p)))
+                         (when (and status-hook (not (eq oldstatus status)))
+                           (funcall status-hook p)))
+                       (when (or (eq status :exited)
+                                 (eq status :signaled))
+                         (remove-external-process p)
+                         (setq terminated t)))))))))))
+      
+  (defun run-external-process (proc in-fd out-fd error-fd argv &optional env)
+    (let* ((signaled nil))
+      (unwind-protect
+           (let* ((child-pid (#-solaris-target #_fork #+solaris-target #_forkall)))
+             (declare (fixnum child-pid))
+             (cond ((zerop child-pid)
+                    ;; Running in the child; do an exec
+                    (setq signaled t)
+                    (dolist (pair env)
+                      (setenv (string (car pair)) (cdr pair)))
+                    (without-interrupts
+                     (exec-with-io-redirection
+                      in-fd out-fd error-fd argv)))
+                   ((> child-pid 0)
+                    ;; Running in the parent: success
+                    (setf (external-process-pid proc) child-pid)
+                    (add-external-process proc)
+                    (signal-semaphore (external-process-signal proc))
+                    (setq signaled t)
+                    (monitor-external-process proc))
+                   (t
+                    ;; Fork failed
+                    (setf (external-process-%status proc) :error
+                          (external-process-%exit-code proc) (%get-errno))
+                    (signal-semaphore (external-process-signal proc))
+                    (setq signaled t))))
+        (unless signaled
+          (setf (external-process-%status proc) :error
+                (external-process-%exit-code proc) -1)
+          (signal-semaphore (external-process-signal proc))))))
+
+  (defparameter *silently-ignore-catastrophic-failure-in-run-program*
+    #+ccl-0711 t #-ccl-0711 nil
+    "If NIL, signal an error if run-program is unable to start the program.
+If non-NIL, treat failure to start the same as failure from the program
+itself, by setting the status and exit-code fields.")
+
+  (defun run-program (program args &key
+                              (wait t) pty
+                              input if-input-does-not-exist
+                              output (if-output-exists :error)
+                              (error :output) (if-error-exists :error)
+                              status-hook (element-type 'character)
+                              env
+                              (sharing :private)
+                              (external-format `(:character-encoding ,*terminal-character-encoding-name*))
+                              (silently-ignore-catastrophic-failures
+                               *silently-ignore-catastrophic-failure-in-run-program*))
+    "Invoke an external program as an OS subprocess of lisp."
+    (declare (ignore pty))
+    (unless (every #'(lambda (a) (typep a 'simple-string)) args)
+      (error "Program args must all be simple strings : ~s" args))
+    (dolist (pair env)
+      (destructuring-bind (var . val) pair
+        (check-type var (or string symbol character))
+        (check-type val string)))
+    (push (native-untranslated-namestring program) args)
+    (let* ((token (list 0))
+           (in-fd nil)
+           (in-stream nil)
+           (out-fd nil)
+           (out-stream nil)
+           (error-fd nil)
+           (error-stream nil)
+           (close-in-parent nil)
+           (close-on-error nil)
+           (proc
+            (make-external-process
+             :pid nil
+             :args args
+             :%status :running
+             :input nil
+             :output nil
+             :error nil
+             :token token
+             :status-hook status-hook
+             :external-format (setq external-format (normalize-external-format t external-format)))))
+      (unwind-protect
+           (progn
+             (multiple-value-setq (in-fd in-stream close-in-parent close-on-error)
+               (get-descriptor-for input proc  nil nil :direction :input
+                                   :if-does-not-exist if-input-does-not-exist
+                                   :element-type element-type
+                                   :sharing sharing
+                                   :external-format external-format))
+             (multiple-value-setq (out-fd out-stream close-in-parent close-on-error)
+               (get-descriptor-for output proc close-in-parent close-on-error
+                                   :direction :output
+                                   :if-exists if-output-exists
+                                   :element-type element-type
+                                   :sharing sharing
+                                   :external-format external-format))
+             (multiple-value-setq (error-fd error-stream close-in-parent close-on-error)
+               (if (eq error :output)
+                 (values out-fd out-stream close-in-parent close-on-error)
+                 (get-descriptor-for error proc close-in-parent close-on-error
+                                     :direction :output
+                                     :if-exists if-error-exists
+                                     :sharing sharing
+                                     :element-type element-type
+                                     :external-format external-format)))
+             (setf (external-process-input proc) in-stream
+                   (external-process-output proc) out-stream
+                   (external-process-error proc) error-stream)
+             (call-with-string-vector
+              #'(lambda (argv)
+                  (process-run-function
+                   (list :name
+                         (format nil "Monitor thread for external process ~a" args)
+                         :stack-size (ash 128 10)
+                         :vstack-size (ash 128 10)
+                         :tstack-size (ash 128 10))
+                   #'run-external-process proc in-fd out-fd error-fd argv env)
+                  (wait-on-semaphore (external-process-signal proc)))
+              args))
+        (dolist (fd close-in-parent) (fd-close fd))
+        (unless (external-process-pid proc)
+          (dolist (fd close-on-error) (fd-close fd)))
+        (when (and wait (external-process-pid proc))
+          (with-interrupts-enabled
+              (wait-on-semaphore (external-process-completed proc)))))
+      (unless (external-process-pid proc)
+        ;; something is wrong
+        (if (eq (external-process-%status proc) :error)
+          ;; Fork failed
+          (unless silently-ignore-catastrophic-failures
+            (cerror "Pretend the program ran and failed" 'external-process-creation-failure :proc proc))
+          ;; Currently can't happen.
+          (error "Bug: fork failed but status field not set?")))
+      proc))
+
+
+
+  (defmacro wifsignaled (status)
+    (let* ((statname (gensym)))
+      `(let* ((,statname ,status))
+        (and (not (wifstopped ,statname)) (not (wifexited ,statname))))))
+
+
+  (defun check-pid (pid &optional (flags (logior  #$WNOHANG #$WUNTRACED)))
+    (declare (fixnum pid))
+    (rlet ((status :signed))
+      (let* ((retval (ff-call-ignoring-eintr (#_waitpid pid status flags))))
+        (declare (fixnum retval))
+        (if (= retval pid)
+          (pref status :signed)
+          (zerop retval)))))
+
+
+
+
+
+  (defun external-process-wait (proc &optional check-stopped)
+    (process-wait "external-process-wait"
+                  #'(lambda ()
+                      (case (external-process-%status proc)
+                        (:running)
+                        (:stopped
+                         (when check-stopped
+                           t))
+                        (t
+                         (when (zerop (car (external-process-token proc)))
+                           t))))))
+
+
+
+
+
+  (defun external-process-error-stream (proc)
+    "Return the stream which is used to read error output from a given OS
+subprocess, if it has one."
+    (require-type proc 'external-process)
+    (external-process-error proc))
+
+
+  
+  (defun signal-external-process (proc signal)
+    "Send the specified signal to the specified external process.  (Typically,
+it would only be useful to call this function if the EXTERNAL-PROCESS was
+created with :WAIT NIL.) Return T if successful; NIL if the process wasn't
+created successfully, and signal an error otherwise."
+    (require-type proc 'external-process)
+    (let* ((pid (external-process-pid proc)))
+      (when pid
+        (let ((error (int-errno-call (#_kill pid signal))))
+          (or (eql error 0)
+              (%errno-disp error))))))
+
+  )                                     ; #-windows-target (progn
+
+#+windows-target
+(progn
+  (defun temp-file-name (prefix)
+    "Returns a unique name for a temporary file, residing in system temp
+space, and prefixed with PREFIX."
+    (rlet ((buffer (:array :wchar_t #.#$MAX_PATH)))
+      (#_GetTempPathW #$MAX_PATH buffer)
+      (with-filename-cstrs ((c-prefix prefix)) 
+        (#_GetTempFileNameW buffer c-prefix 0 buffer)
+        (%get-native-utf-16-cstring buffer))))
+  
+  (defun get-descriptor-for (object proc close-in-parent close-on-error
+                                    &rest keys
+                                    &key
+                                    direction (element-type 'character)
+                                    (sharing :private)
+                                    external-format
+                                    &allow-other-keys)
+    (etypecase object
+      ((eql t)
+       (values nil nil close-in-parent close-on-error))
+      (null
+       (let* ((null-device "nul")
+              (fd (fd-open null-device (case direction
+                                         (:input #$O_RDONLY)
+                                         (:output #$O_WRONLY)
+                                         (t #$O_RDWR)))))
+         (if (< fd 0)
+           (signal-file-error fd null-device))
+         (values fd nil (cons fd close-in-parent) (cons fd close-on-error))))
+      ((eql :stream)
+       (multiple-value-bind (read-pipe write-pipe) (pipe)
+         (case direction
+           (:input
+            (values read-pipe
+                    (make-fd-stream (fd-uninheritable write-pipe :direction :output)
+                                    :direction :output
+                                    :element-type element-type
+                                    :interactive nil
+                                    :basic t
+                                    :sharing sharing
+                                    :encoding (external-format-character-encoding external-format)
+                                    :line-termination (external-format-line-termination external-format)
+                                    :auto-close t)
+                    (cons read-pipe close-in-parent)
+                    (cons write-pipe close-on-error)))
+           (:output
+            (values write-pipe
+                    (make-fd-stream (fd-uninheritable read-pipe :direction :input)
+                                    :direction :input
+                                    :element-type element-type
+                                    :interactive nil
+                                    :basic t
+                                    :sharing sharing
+                                    :encoding (external-format-character-encoding external-format)
+                                    :line-termination (external-format-line-termination external-format)
+                                    :auto-close t)
+                    (cons write-pipe close-in-parent)
+                    (cons read-pipe close-on-error)))
+           (t
+            (fd-close read-pipe)
+            (fd-close write-pipe)
+            (report-bad-arg direction '(member :input :output))))))
+      ((or pathname string)
+       (with-open-stream (file (apply #'open object keys))
+         (let* ((fd (fd-dup (ioblock-device (stream-ioblock file t)) :direction direction :inheritable t)))
+           (values fd
+                   nil
+                   (cons fd close-in-parent)
+                   (cons fd close-on-error)))))
+      (stream
+       (ecase direction
+         (:input
+          (let* ((tempname (temp-file-name "lisp-temp"))
+                 (fd (fd-open tempname #$O_RDWR)))
+            (if (< fd 0)
+              (%errno-disp fd))
+            (let* ((out (make-fd-stream (fd-dup fd)
+                                        :direction :output
+                                        :encoding (external-format-character-encoding external-format)
+                                        :line-termination (external-format-line-termination external-format))))            
+              (loop
+                (multiple-value-bind (line no-newline)
+                    (read-line object nil nil)
+                  (unless line
+                    (return))
+                  (if no-newline
+                    (write-string line out)
+                    (write-line line out))
+                  ))
+              (close out))
+            (fd-lseek fd 0 #$SEEK_SET)
+            (values fd nil (cons fd close-in-parent) (cons fd close-on-error))))
+         (:output
+          (multiple-value-bind (read-pipe write-pipe) (pipe)
+            (push read-pipe (external-process-watched-fds proc))
+            (push object (external-process-watched-streams proc))
+            (incf (car (external-process-token proc)))
+            (values write-pipe
+                    nil
+                    (cons write-pipe close-in-parent)
+                    (cons read-pipe close-on-error))))))))
+
+  (defstruct external-process
+    pid
+    %status
+    %exit-code
+    pty
+    input
+    output
+    error
+    status-hook
+    plist
+    token
+    core
+    args
+    (signal (make-semaphore))
+    (completed (make-semaphore))
+    watched-fds
+    watched-streams
+    external-format
+    )
+
+
+
+  (defmethod print-object ((p external-process) stream)
+    (print-unreadable-object (p stream :type t :identity t)
+      (let* ((status (external-process-%status p)))
+        (let* ((*print-length* 3))
+          (format stream "~a" (external-process-args p)))
+        (format stream "[~d] (~a" (external-process-pid p) status)
+        (unless (eq status :running)
+          (format stream " : ~d" (external-process-%exit-code p)))
+        (format stream ")"))))
+
+  (defun run-program (program args &key
+                              (wait t) pty
+                              input if-input-does-not-exist
+                              output (if-output-exists :error)
+                              (error :output) (if-error-exists :error)
+                              status-hook (element-type 'character)
+                              (sharing :private)
+                              (external-format `(:character-encoding ,*terminal-character-encoding-name* :line-termination :crlf))
+                              env)
+    "Invoke an external program as an OS subprocess of lisp."
+    (declare (ignore pty))
+    (unless (every #'(lambda (a) (typep a 'simple-string)) args)
+      (error "Program args must all be simple strings : ~s" args))
+    (push program args)
+    (let* ((token (list 0))
+           (in-fd nil)
+           (in-stream nil)
+           (out-fd nil)
+           (out-stream nil)
+           (error-fd nil)
+           (error-stream nil)
+           (close-in-parent nil)
+           (close-on-error nil)
+           (proc
+            (make-external-process
+             :pid nil
+             :args args
+             :%status :running
+             :input nil
+             :output nil
+             :error nil
+             :token token
+             :external-format (setq external-format (normalize-external-format t external-format))
+             :status-hook status-hook)))
+      (unwind-protect
+           (progn
+             (multiple-value-setq (in-fd in-stream close-in-parent close-on-error)
+               (get-descriptor-for input proc  nil nil :direction :input
+                                   :if-does-not-exist if-input-does-not-exist
+                                   :sharing sharing
+                                   :element-type element-type
+                                   :external-format external-format))
+             (multiple-value-setq (out-fd out-stream close-in-parent close-on-error)
+               (get-descriptor-for output proc close-in-parent close-on-error
+                                   :direction :output
+                                   :if-exists if-output-exists
+                                   :sharing sharing
+                                   :element-type element-type
+                                   :external-format external-format))
+             (multiple-value-setq (error-fd error-stream close-in-parent close-on-error)
+               (if (eq error :output)
+                 (values out-fd out-stream close-in-parent close-on-error)
+                 (get-descriptor-for error proc close-in-parent close-on-error
+                                     :direction :output
+                                     :if-exists if-error-exists
+                                     :sharing sharing
+                                     :element-type element-type
+                                     :external-format external-format)))
+             (setf (external-process-input proc) in-stream
+                   (external-process-output proc) out-stream
+                   (external-process-error proc) error-stream)
+             (process-run-function
+              (format nil "Monitor thread for external process ~a" args)
+                    
+              #'run-external-process proc in-fd out-fd error-fd env)
+             (wait-on-semaphore (external-process-signal proc))
+             )
+        (dolist (fd close-in-parent) (fd-close fd))
+        (if (external-process-pid proc)
+          (when (and wait (external-process-pid proc))
+            (with-interrupts-enabled
+                (wait-on-semaphore (external-process-completed proc))))
+          (progn
+            (dolist (fd close-on-error) (fd-close fd)))))
+      proc))
+
+  (let* ((external-processes ())
+         (external-processes-lock (make-lock)))
+    (defun add-external-process (p)
+      (with-lock-grabbed (external-processes-lock)
+        (push p external-processes)))
+    (defun remove-external-process (p)
+      (with-lock-grabbed (external-processes-lock)
+        (setq external-processes (delete p external-processes))))
+    ;; Likewise
+    (defun external-processes ()
+      (with-lock-grabbed (external-processes-lock)
+        (copy-list external-processes)))
+    )
+
+
+
+
+  (defun run-external-process (proc in-fd out-fd error-fd &optional env)
+    (let* ((args (external-process-args proc))
+           (child-pid (exec-with-io-redirection in-fd out-fd error-fd args proc env)))
+      (when child-pid
+        (setf (external-process-pid proc) child-pid)
+        (add-external-process proc)
+        (signal-semaphore (external-process-signal proc))
+        (monitor-external-process proc))))
+
+  (defun join-strings (strings)
+    (reduce (lambda (left right) (concatenate 'string left " " right)) strings))
+
+  (defun create-windows-process (new-in new-out new-err cmdstring env)
+    (declare (ignore env))              ; until we can do better.
+    (with-filename-cstrs ((command cmdstring))
+      (rletz ((proc-info #>PROCESS_INFORMATION)
+              (si #>STARTUPINFO))
+        (setf (pref si #>STARTUPINFO.cb) (record-length #>STARTUPINFO))
+        (setf (pref si #>STARTUPINFO.dwFlags)
+              (logior #$STARTF_USESTDHANDLES #$STARTF_USESHOWWINDOW))
+        (setf (pref si #>STARTUPINFO.wShowWindow) #$SW_HIDE)
+        (setf (pref si #>STARTUPINFO.hStdInput)
+              (if new-in
+                (%int-to-ptr new-in)
+                (#_GetStdHandle #$STD_INPUT_HANDLE)))
+        (setf (pref si #>STARTUPINFO.hStdOutput)
+              (if new-out
+                (%int-to-ptr new-out)
+                (#_GetStdHandle #$STD_OUTPUT_HANDLE)))
+        (setf (pref si #>STARTUPINFO.hStdError)
+              (if new-err
+                (%int-to-ptr new-err)
+                (#_GetStdHandle #$STD_ERROR_HANDLE)))
+        (if (zerop (#_CreateProcessW (%null-ptr)
+                                     command
+                                     (%null-ptr)
+                                     (%null-ptr)
+                                     1
+                                     #$CREATE_NEW_CONSOLE
+                                     (%null-ptr)
+                                     (%null-ptr)
+                                     si
+                                     proc-info))
+          (values nil (#_GetLastError))
+          (progn
+            (#_CloseHandle (pref proc-info #>PROCESS_INFORMATION.hThread))
+            (values t (pref proc-info #>PROCESS_INFORMATION.hProcess)))))))
+
+  (defun exec-with-io-redirection (new-in new-out new-err args proc &optional env)
+    (multiple-value-bind (win handle-to-process-or-error)
+        (create-windows-process new-in new-out new-err (join-strings args) env)
+      (if win
+        handle-to-process-or-error
+        (progn
+          (setf (external-process-%status proc) :error
+                (external-process-%exit-code proc) handle-to-process-or-error)
+          (signal-semaphore (external-process-signal proc))
+          (signal-semaphore (external-process-completed proc))
+          nil))))
+
+  (defun fd-uninheritable (fd &key direction)
+    (let ((new-fd (fd-dup fd :direction direction)))
+      (fd-close fd)
+      new-fd))
+
+  
+  (defun data-available-on-pipe-p (hpipe)
+    (rlet ((navail #>DWORD 0))
+      (unless (eql 0 (#_PeekNamedPipe (if (typep hpipe 'macptr)
+                                        hpipe
+                                        (%int-to-ptr hpipe))
+                                      (%null-ptr)
+                                      0
+                                      (%null-ptr)
+                                      navail
+                                      (%null-ptr)))
+        (not (eql 0 (pref navail #>DWORD))))))
+    
+
+  ;;; There doesn't seem to be any way to wait on input from an
+  ;;; anonymous pipe in Windows (that would, after all, make too
+  ;;; much sense.)  We -can- check for pending unread data on
+  ;;; pipes, and can expect to eventually get EOF on a pipe.
+  ;;; So, this tries to loop until the process handle is signaled and
+  ;;; all data has been read.
+  (defun monitor-external-process (p)
+    (let* ((in-fds (external-process-watched-fds p))
+           (out-streams (external-process-watched-streams p))
+           (token (external-process-token p))
+           (terminated)
+           (changed)
+           (external-format (external-process-external-format p))
+           (encoding (external-format-character-encoding external-format))
+           (line-termination (external-format-line-termination external-format))
+           (pairs (pairlis (mapcar (lambda (fd)
+                                     (cons fd
+                                           (make-fd-stream fd
+                                                           :direction :input
+                                                           :sharing :private
+                                                           :encoding encoding
+                                                           :line-termination line-termination)))
+                                   in-fds)
+                           out-streams))
+           )
+      (loop
+        (when changed
+          (setq pairs (delete nil pairs :key #'car)
+                changed nil))
+        (when (and terminated (null pairs))
+          (without-interrupts
+           (rlet ((code #>DWORD))
+             (loop
+               (#_GetExitCodeProcess (external-process-pid p) code)
+               (unless (eql (pref code #>DWORD) #$STILL_ACTIVE)
+                 (return))
+               (#_SleepEx 10 #$TRUE))
+             (setf (external-process-%exit-code p) (pref code #>DWORD)))
+           (#_CloseHandle (external-process-pid p))
+           (setf (external-process-pid p) nil)
+           (setf (external-process-%status p) :exited)
+           (let ((status-hook (external-process-status-hook p)))
+             (when status-hook
+               (funcall status-hook p)))
+           (remove-external-process p)
+           (signal-semaphore (external-process-completed p))
+           (return)))
+        (dolist (p pairs)
+          (let* ((in-fd (caar p))
+                 (in-stream (cdar p))
+                 (out-stream (cdr p)))
+            (when (or terminated (data-available-on-pipe-p in-fd))
+              (let* ((buf (make-string 1024)))
+                (declare (dynamic-extent buf))
+                (let* ((n (ignore-errors (read-sequence buf in-stream))))
+                  (if (or (null n) (eql n 0))
+                    (progn
+                      (without-interrupts
+                       (decf (car token))
+                       (fd-close in-fd)
+                       (setf (car p) nil changed t)))
+                    (progn
+                      (write-sequence buf out-stream :end n)
+                      (force-output out-stream))))))))
+        (unless terminated
+          (setq terminated (eql (#_WaitForSingleObjectEx
+                                 (external-process-pid p)
+                                 1000
+                                 #$true)
+                                #$WAIT_OBJECT_0))))))
+  
+
+  (defun signal-external-process (proc signal)
+    "Does nothing on Windows"
+    (declare (ignore signal))
+    (require-type proc 'external-process)
+    nil)  
+
+
+  )
+                                        ;#+windows-target (progn
+
+
+(defun external-process-input-stream (proc)
+  "Return the lisp stream which is used to write input to a given OS
+subprocess, if it has one."
+  (require-type proc 'external-process)
+  (external-process-input proc))
+
+(defun external-process-output-stream (proc)
+  "Return the lisp stream which is used to read output from a given OS
+subprocess, if there is one."
+  (require-type proc 'external-process)
+  (external-process-output proc))
+
+
+(defun external-process-id (proc)
+  "Return the process id of an OS subprocess, a positive integer which
+identifies it."
+  (require-type proc 'external-process)
+  (external-process-pid proc))
+
+(defun external-process-status (proc)
+  "Return information about whether an OS subprocess is running; or, if
+not, why not; and what its result code was if it completed."
+  (require-type proc 'external-process)
+  (values (external-process-%status proc)
+          (external-process-%exit-code proc)))
+
+;;; EOF on a TTY is transient, but I'm less sure of other cases.
+(defun eof-transient-p (fd)
+  (case (%unix-fd-kind fd)
+    (:tty t)
+    #+windows-target (:character-special t)
+    (t nil)))
+
+
+(defstruct (shared-resource (:constructor make-shared-resource (name)))
+  (name)
+  (lock (make-lock))
+  (primary-owner *current-process*)
+  (primary-owner-notify (make-semaphore))
+  (current-owner nil)
+  (requestors (make-dll-header)))
+
+(defstruct (shared-resource-request
+	     (:constructor make-shared-resource-request (process))
+	     (:include dll-node))
+  process
+  (signal (make-semaphore)))
+	     
+
+;; Returns NIL if already owned by calling thread, T otherwise
+(defun %acquire-shared-resource (resource  &optional verbose)
+  (let* ((current *current-process*))
+    (with-lock-grabbed ((shared-resource-lock resource))
+      (let* ((secondary (shared-resource-current-owner resource)))
+	(if (or (eq current secondary)
+		(and (null secondary)
+		     (eq current (shared-resource-primary-owner resource))))
+	  (return-from %acquire-shared-resource nil))))
+    (let* ((request (make-shared-resource-request *current-process*)))
+      (when verbose
+	(format t "~%~%;;;~%;;; ~a requires access to ~a~%;;; Type (:y ~D) to yield control to this thread.~%;;;~%"
+		*current-process* (shared-resource-name resource)
+                (process-serial-number *current-process*)))
+      (with-lock-grabbed ((shared-resource-lock resource))
+	(append-dll-node request (shared-resource-requestors resource)))
+      (wait-on-semaphore (shared-resource-request-signal request))
+      (assert (eq current (shared-resource-current-owner resource)))
+      (when verbose
+	(format t "~%~%;;;~%;;; ~a is now owned by ~a~%;;;~%~%"
+		(shared-resource-name resource) current))
+      t)))
+
+;;; If we're the primary owner and there is no secondary owner, do nothing.
+;;; If we're the secondary owner, cease being the secondary owner.
+(defun %release-shared-resource (r)
+  (let* ((not-any-owner ()))
+    (with-lock-grabbed ((shared-resource-lock r))
+      (let* ((current *current-process*)
+	     (primary (shared-resource-primary-owner r))
+	     (secondary (shared-resource-current-owner r)))
+	(unless (setq not-any-owner
+		      (not (or (eq current secondary)
+                               (and (null secondary)
+                                    (eq current primary)))))
+	  (when (eq current secondary)
+	    (setf (shared-resource-current-owner r) nil)
+	    (signal-semaphore (shared-resource-primary-owner-notify r))))))
+    (when not-any-owner
+      (signal-program-error "Process ~a does not own ~a" *current-process*
+			    (shared-resource-name r)))))
+
+;;; The current thread should be the primary owner; there should be
+;;; no secondary owner.  Wakeup the specified (or first) requesting
+;;; process, then block on our semaphore 
+(defun %yield-shared-resource (r &optional to)
+  (let* ((request nil))
+    (with-lock-grabbed ((shared-resource-lock r))
+      (let* ((current *current-process*)
+	     (primary (shared-resource-primary-owner r)))
+	(when (and (eq current primary)
+		   (null (shared-resource-current-owner r)))
+	  (setq request
+		(let* ((header (shared-resource-requestors r)))
+		  (if to 
+		    (do-dll-nodes (node header)
+		      (when (eq to (shared-resource-request-process node))
+			(return node)))
+		    (let* ((first (dll-header-first header)))
+		      (unless (eq first header)
+			first)))))
+	  (when request
+	    (remove-dll-node request)
+            (setf (shared-resource-current-owner r)
+                  (shared-resource-request-process request))
+	    (signal-semaphore (shared-resource-request-signal request))))))
+    (when request
+      (wait-on-semaphore (shared-resource-primary-owner-notify r))
+      (format t "~%;;;~%;;;control of ~a restored to ~a~%;;;~&"
+	      (shared-resource-name r)
+	      *current-process*))))
+
+
+      
+
+(defun %shared-resource-requestor-p (r proc)
+  (with-lock-grabbed ((shared-resource-lock r))
+    (do-dll-nodes (node (shared-resource-requestors r))
+      (when (eq proc (shared-resource-request-process node))
+	(return t)))))
+
+(defparameter *resident-editor-hook* nil
+  "If non-NIL, should be a function that takes an optional argument
+   (like ED) and invokes a \"resident\" editor.")
+
+(defun ed (&optional arg)
+  (if *resident-editor-hook*
+    (funcall *resident-editor-hook* arg)
+    (error "This implementation doesn't provide a resident editor.")))
+
+(defun running-under-emacs-p ()
+  (not (null (getenv "EMACS"))))
+
+(defloadvar *cpu-count* nil)
+
+(defun cpu-count ()
+  (or *cpu-count*
+      (setq *cpu-count*
+            #+darwin-target
+            (rlet ((info :host_basic_info)
+                   (count :mach_msg_type_number_t #$HOST_BASIC_INFO_COUNT))
+              (if (eql #$KERN_SUCCESS (#_host_info (#_mach_host_self)
+                                                   #$HOST_BASIC_INFO
+                                                   info
+                                                   count))
+                (pref info :host_basic_info.max_cpus)
+                1))
+            #+(or linux-target solaris-target)
+            (or
+             (let* ((n (#_sysconf #$_SC_NPROCESSORS_ONLN)))
+               (declare (fixnum n))
+               (if (> n 0) n))
+             #+linux-target
+             (ignore-errors
+               (with-open-file (p "/proc/cpuinfo")
+                 (let* ((ncpu 0)
+                        (match "processor")
+                        (matchlen (length match)))
+                   (do* ((line (read-line p nil nil) (read-line p nil nil)))
+                        ((null line) ncpu)
+                     (let* ((line-length (length line)))
+                       (when (and
+                              (> line-length matchlen)
+                              (string= match line
+                                       :end2 matchlen)
+                              (whitespacep (schar line matchlen)))
+                         (incf ncpu)))))))
+             1)
+            #+freebsd-target
+            (rlet ((ret :uint))
+              (%stack-block ((mib (* (record-length :uint) 2)))
+              (setf (paref mib (:array :uint) 0)
+                    #$CTL_HW
+                    (paref mib (:array :uint) 1)
+                    #$HW_NCPU)
+              (rlet ((oldsize :uint (record-length :uint)))
+                (if (eql 0 (#_sysctl mib 2 ret oldsize (%null-ptr) 0))
+                  (pref ret :uint)
+                  1))))
+            #+windows-target
+            (rlet ((procmask #>DWORD_PTR)
+                   (sysmask #>DWORD_PTR))
+              (if (eql 0 (#_GetProcessAffinityMask (#_GetCurrentProcess) procmask sysmask))
+                1
+                (logcount (pref sysmask #>DWORD_PTR)))))))
+
+(def-load-pointers spin-count ()
+  (if (eql 1 (cpu-count))
+    (%defglobal '*spin-lock-tries* 1)
+    (%defglobal '*spin-lock-tries* 1024))
+  (%defglobal '*spin-lock-timeouts* 0))
+
+(defun yield ()
+  (process-allow-schedule))
+
+(defloadvar *host-page-size*
+    #-windows-target (#_getpagesize)
+    #+windows-target
+    (rlet ((info #>SYSTEM_INFO))
+      (#_GetSystemInfo info)
+      (pref info #>SYSTEM_INFO.dwPageSize))
+    )
+
+;;(assert (= (logcount *host-page-size*) 1))
+
+(defun get-universal-time ()
+  "Return a single integer for the current time of
+   day in universal time format."
+  (rlet ((tv :timeval))
+    (gettimeofday tv)
+    (+ (pref tv :timeval.tv_sec) unix-to-universal-time)))
+
+#+windows-target
+(defloadvar *windows-allocation-granularity*
+    (rlet ((info #>SYSTEM_INFO))
+      (#_GetSystemInfo info)
+      (pref info #>SYSTEM_INFO.dwAllocationGranularity)))
+
+#-windows-target
+(defun %memory-map-fd (fd len bits-per-element)
+  (let* ((nbytes (+ *host-page-size*
+                    (logandc2 (+ len
+                                 (1- *host-page-size*))
+                              (1- *host-page-size*))))         
+         (ndata-elements
+          (ash len
+               (ecase bits-per-element
+                 (1 3)
+                 (8 0)
+                 (16 -1)
+                 (32 -2)
+                 (64 -3))))
+         (nalignment-elements
+          (ash target::nbits-in-word
+               (ecase bits-per-element
+                 (1 0)
+                 (8 -3)
+                 (16 -4)
+                 (32 -5)
+                 (64 -6)))))
+    (if (>= (+ ndata-elements nalignment-elements)
+            array-total-size-limit)
+      (progn
+        (fd-close fd)
+        (error "Can't make a vector with ~s elements in this implementation." (+ ndata-elements nalignment-elements)))
+      (let* ((addr (#_mmap (%null-ptr)
+                           nbytes
+                           #$PROT_NONE
+                           (logior #$MAP_ANON #$MAP_PRIVATE)
+                           -1
+                           0)))              
+        (if (eql addr (%int-to-ptr (1- (ash 1 target::nbits-in-word)))) ; #$MAP_FAILED
+          (let* ((errno (%get-errno)))
+            (fd-close fd)
+            (error "Can't map ~d bytes: ~a" nbytes (%strerror errno)))
+              ;;; Remap the first page so that we can put a vector header
+              ;;; there; use the first word on the first page to remember
+              ;;; the file descriptor.
+          (progn
+            (#_mmap addr
+                    *host-page-size*
+                    (logior #$PROT_READ #$PROT_WRITE)
+                    (logior #$MAP_ANON #$MAP_PRIVATE #$MAP_FIXED)
+                    -1
+                    0)
+            (setf (pref addr :int) fd)
+            (let* ((header-addr (%inc-ptr addr (- *host-page-size*
+                                                            (* 2 target::node-size)))))
+              
+              (when (> len 0)
+                (let* ((target-addr (%inc-ptr header-addr (* 2 target::node-size))))
+                  (unless (eql target-addr
+                               (#_mmap target-addr
+                                       len
+                                       #$PROT_READ
+                                       (logior #$MAP_PRIVATE #$MAP_FIXED)
+                                       fd
+                                       0))
+                    (let* ((errno (%get-errno)))
+                      (fd-close fd)
+                      (#_munmap addr nbytes)
+                      (error "Mapping failed: ~a" (%strerror errno))))))
+              (values header-addr ndata-elements nalignment-elements))))))))
+
+#+windows-target
+(defun %memory-map-fd (fd len bits-per-element)
+  (let* ((nbytes (+ *windows-allocation-granularity*
+                    (logandc2 (+ len
+                                 (1- *windows-allocation-granularity*))
+                              (1- *windows-allocation-granularity*))))         
+         (ndata-elements
+          (ash len
+               (ecase bits-per-element
+                 (1 3)
+                 (8 0)
+                 (16 -1)
+                 (32 -2)
+                 (64 -3))))
+         (nalignment-elements
+          (ash target::nbits-in-word
+               (ecase bits-per-element
+                 (1 0)
+                 (8 -3)
+                 (16 -4)
+                 (32 -5)
+                 (64 -6)))))
+    (if (>= (+ ndata-elements nalignment-elements)
+            array-total-size-limit)
+      (progn
+        (fd-close fd)
+        (error "Can't make a vector with ~s elements in this implementation." (+ ndata-elements nalignment-elements)))
+      (let* ((mapping (#_CreateFileMappingA (%int-to-ptr fd) (%null-ptr) #$PAGE_READONLY 0 0 (%null-ptr))))
+        (if (%null-ptr-p mapping)
+          (let* ((err (#_GetLastError)))
+            (fd-close fd)
+            (error "Couldn't create a file mapping - ~a." (%windows-error-string err)))
+          (loop
+            (let* ((base (#_VirtualAlloc (%null-ptr) nbytes #$MEM_RESERVE #$PAGE_NOACCESS)))
+              (if (%null-ptr-p base)
+                (let* ((err (#_GetLastError)))
+                  (#_CloseHandle mapping)
+                  (fd-close fd)
+                  (error "Couldn't reserve ~d bytes of address space for mapped file - ~a"
+                         nbytes (%windows-error-string err)))
+                ;; Now we have to free the memory and hope that we can reallocate it ...
+                (progn
+                  (#_VirtualFree base 0 #$MEM_RELEASE)
+                  (unless (%null-ptr-p (#_VirtualAlloc base *windows-allocation-granularity* #$MEM_RESERVE #$PAGE_NOACCESS))
+                    (let* ((fptr (%inc-ptr base *windows-allocation-granularity*)))
+                      (if (%null-ptr-p (#_MapViewOfFileEx mapping #$FILE_MAP_READ 0 0 0 fptr))
+                        (#_VirtualFree base 0 #$MEM_RELEASE)
+                        (let* ((prefix-page (%inc-ptr base (- *windows-allocation-granularity*
+                                                              *host-page-size*))))
+                          (#_VirtualAlloc prefix-page *host-page-size* #$MEM_COMMIT #$PAGE_READWRITE)
+                          (setf (paref prefix-page (:* :address) 0) mapping
+                                (paref prefix-page (:* :address) 1) (%int-to-ptr fd))
+                          (return (values
+                                   (%inc-ptr prefix-page (- *host-page-size*
+                                                            (* 2 target::node-size)))
+                                   ndata-elements
+                                   nalignment-elements)))))))))))))))
+                       
+
+
+(defun map-file-to-ivector (pathname element-type)
+  (let* ((upgraded-type (upgraded-array-element-type element-type))
+         (upgraded-ctype (specifier-type upgraded-type)))
+    (unless (and (typep upgraded-ctype 'numeric-ctype)
+                 (eq 'integer (numeric-ctype-class upgraded-ctype)))
+      (error "Invalid element-type: ~s" element-type))
+    (let* ((bits-per-element (integer-length (- (numeric-ctype-high upgraded-ctype)
+                                                (numeric-ctype-low upgraded-ctype))))
+           (fd (fd-open (native-translated-namestring pathname) #$O_RDONLY)))
+      (if (< fd 0)
+        (signal-file-error fd pathname)
+        (let* ((len (fd-size fd)))
+          (if (< len 0)
+            (signal-file-error fd pathname)
+            (multiple-value-bind (header-address ndata-elements nalignment-elements)
+                (%memory-map-fd fd len bits-per-element)
+              (setf (%get-natural header-address 0)
+                    (logior (element-type-subtype upgraded-type)
+                            (ash (+ ndata-elements nalignment-elements) target::num-subtag-bits)))
+              (with-macptrs ((v (%inc-ptr header-address target::fulltag-misc)))
+                          (let* ((vector (rlet ((p :address v)) (%get-object p 0))))
+                            ;; Tell some parts of Clozure CL - notably the
+                            ;; printer - that this thing off in foreign
+                            ;; memory is a real lisp object and not
+                            ;; "bogus".
+                            (with-lock-grabbed (*heap-ivector-lock*)
+                              (push vector *heap-ivectors*))
+                            (make-array ndata-elements
+                                        :element-type upgraded-type
+                                        :displaced-to vector
+                                        :adjustable t
+                                        :displaced-index-offset nalignment-elements))))))))))
+
+(defun map-file-to-octet-vector (pathname)
+  (map-file-to-ivector pathname '(unsigned-byte 8)))
+
+(defun mapped-vector-data-address-and-size (displaced-vector)
+  (let* ((v (array-displacement displaced-vector))
+         (element-type (array-element-type displaced-vector)))
+    (if (or (eq v displaced-vector)
+            (not (with-lock-grabbed (*heap-ivector-lock*)
+                   (member v *heap-ivectors*))))
+      (error "~s doesn't seem to have been allocated via ~s and not yet unmapped" displaced-vector 'map-file-to-ivector))
+    (let* ((pv (rlet ((x :address)) (%set-object x 0 v) (pref x :address)))
+           (ctype (specifier-type element-type))
+           (arch (backend-target-arch *target-backend*)))
+      (values (%inc-ptr pv (- (* 2 target::node-size) target::fulltag-misc))
+              (- (funcall (arch::target-array-data-size-function arch)
+                          (ctype-subtype ctype)
+                          (length v))
+                 target::node-size)))))
+
+
+#-windows-target
+(defun %unmap-file (data-address size-in-octets)
+  (let* ((base-address (%inc-ptr data-address (- *host-page-size*)))
+         (fd (pref base-address :int)))
+    (#_munmap base-address (+ *host-page-size* size-in-octets))
+    (fd-close fd)))
+
+#+windows-target
+(defun %unmap-file (data-address size-in-octets)
+  (declare (ignore size-in-octets))
+  (let* ((prefix-page (%inc-ptr data-address (- *host-page-size*)))
+         (prefix-allocation (%inc-ptr data-address (- *windows-allocation-granularity*)))
+         (mapping (paref prefix-page (:* :address) 0))
+         (fd (%ptr-to-int (paref prefix-page (:* :address) 1))))
+    (#_UnmapViewOfFile data-address)
+    (#_CloseHandle mapping)
+    (#_VirtualFree prefix-allocation 0 #$MEM_RELEASE)
+    (fd-close fd)))
+
+    
+
+;;; Argument should be something returned by MAP-FILE-TO-IVECTOR;
+;;; this should be called at most once for any such object.
+(defun unmap-ivector (displaced-vector)
+  (multiple-value-bind (data-address size-in-octets)
+      (mapped-vector-data-address-and-size displaced-vector)
+  (let* ((v (array-displacement displaced-vector)))
+      (let* ((element-type (array-element-type displaced-vector)))
+        (adjust-array displaced-vector 0
+                      :element-type element-type
+                      :displaced-to (make-array 0 :element-type element-type)
+                      :displaced-index-offset 0))
+      (with-lock-grabbed (*heap-ivector-lock*)
+        (setq *heap-ivectors* (delete v *heap-ivectors*)))
+      (%unmap-file data-address size-in-octets)
+      t)))
+
+(defun unmap-octet-vector (v)
+  (unmap-ivector v))
+
+#-windows-target
+(progn
+(defun lock-mapped-vector (v)
+  (multiple-value-bind (address nbytes)
+      (mapped-vector-data-address-and-size v)
+    (eql 0 (#_mlock address nbytes))))
+
+(defun unlock-mapped-vector (v)
+  (multiple-value-bind (address nbytes)
+      (mapped-vector-data-address-and-size v)
+    (eql 0 (#_munlock address nbytes))))
+
+(defun bitmap-for-mapped-range (address nbytes)
+  (let* ((npages (ceiling nbytes *host-page-size*)))
+    (%stack-block ((vec npages))
+      (when (eql 0 (#_mincore address nbytes vec))
+        (let* ((bits (make-array npages :element-type 'bit)))
+          (dotimes (i npages bits)
+            (setf (sbit bits i)
+                  (logand 1 (%get-unsigned-byte vec i)))))))))
+
+(defun percentage-of-resident-pages (address nbytes)
+  (let* ((npages (ceiling nbytes *host-page-size*)))
+    (%stack-block ((vec npages))
+      (when (eql 0 (#_mincore address nbytes vec))
+        (let* ((nresident 0))
+          (dotimes (i npages (* 100.0 (/ nresident npages)))
+            (when (logbitp 0 (%get-unsigned-byte vec i))
+              (incf nresident))))))))
+
+(defun mapped-vector-resident-pages (v)
+  (multiple-value-bind (address nbytes)
+      (mapped-vector-data-address-and-size v)
+    (bitmap-for-mapped-range address nbytes)))
+
+(defun mapped-vector-resident-pages-percentage (v)
+  (multiple-value-bind (address nbytes)
+      (mapped-vector-data-address-and-size v)
+    (percentage-of-resident-pages address nbytes)))
+)
+
+
+#+windows-target
+(defun cygpath (winpath)
+  "Try to use the Cygwin \"cygpath\" program to map a Windows-style
+   pathname to a POSIX-stype Cygwin pathname."
+  (let* ((posix-path winpath))
+    (with-output-to-string (s)
+      (multiple-value-bind (status exit-code)
+          (external-process-status
+           (run-program "cygpath" (list "-u" winpath) :output s))
+        (when (and (eq status :exited)
+                   (eql exit-code 0))
+          (with-input-from-string (output (get-output-stream-string s))
+            (setq posix-path (read-line output nil nil))))))
+    posix-path))
+
+#-windows-target (defun cygpath (path) path)
+      
+
+
+
+#+x86-target
+(progn
+(defloadvar *last-rdtsc-time* 0)
+
+(defstatic *rdtsc-estimated-increment* 1 "Should be positive ...")
+
+(defun rdtsc-monotonic ()
+  "Return monotonically increasing values, partly compensating for
+   OSes that don't keep the TSCs of all processorsin synch."
+  (loop
+    (let* ((old *last-rdtsc-time*)
+           (new (rdtsc)))
+      (when (< new old)
+        ;; We're running on a CPU whose TSC is behind the one
+        ;; on the last CPU we were scheduled on.
+        (setq new (+ old *rdtsc-estimated-increment*)))
+      (when (%store-node-conditional target::symbol.vcell *last-rdtsc-time* old new)
+        (return new)))))
+
+(defun estimate-rdtsc-skew (&optional (niter 1000000))
+  (do* ((i 0 (1+ i))
+        (last (rdtsc) next)
+        (next (rdtsc) (rdtsc))
+        (skew 1))
+       ((>= i niter) (setq *rdtsc-estimated-increment* skew))
+    (declare (fixnum last next skew))
+    (when (> last next)
+      (let* ((s (- last next)))
+        (declare (fixnum s))
+        (when (> s skew) (setq skew s))))))
+)
+
+
Index: /branches/new-random/level-1/ppc-callback-support.lisp
===================================================================
--- /branches/new-random/level-1/ppc-callback-support.lisp	(revision 13309)
+++ /branches/new-random/level-1/ppc-callback-support.lisp	(revision 13309)
@@ -0,0 +1,64 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; ppc-callback-support.lisp
+;;;
+;;; Support for PPC callbacks
+
+(in-package "CCL")
+
+
+
+;;; This is machine-dependent (it conses up a piece of "trampoline" code
+;;; which calls a subprim in the lisp kernel.)
+#-(and linuxppc-target poweropen-target)
+(defun make-callback-trampoline (index &optional info)
+  (declare (ignorable info))
+  (macrolet ((ppc-lap-word (instruction-form)
+               (uvref (uvref (compile nil `(lambda (&lap 0) (ppc-lap-function () ((?? 0)) ,instruction-form))) 0) #+ppc32-host 0 #+ppc64-host 1)))
+    (let* ((subprim
+	    #+eabi-target
+	     #.(subprim-name->offset '.SPeabi-callback)
+	     #-eabi-target
+             #.(subprim-name->offset '.SPpoweropen-callback))
+           (p (%allocate-callback-pointer 12)))
+      (setf (%get-long p 0) (logior (ldb (byte 8 16) index)
+                                    (ppc-lap-word (lis 11 ??)))   ; unboxed index
+            (%get-long p 4) (logior (ldb (byte 16 0) index)
+                                    (ppc-lap-word (ori 11 11 ??)))
+                                   
+	    (%get-long p 8) (logior subprim
+                                    (ppc-lap-word (ba ??))))
+      (ff-call (%kernel-import #.target::kernel-import-makedataexecutable) 
+               :address p 
+               :unsigned-fullword 12
+               :void)
+      p)))
+
+;;; In the 64-bit LinuxPPC ABI, functions are "transfer vectors":
+;;; two-word vectors that contain the entry point in the first word
+;;; and a pointer to the global variables ("table of contents", or
+;;; TOC) the function references in the second word.  We can use the
+;;; TOC word in the transfer vector to store the callback index.
+#+(and linuxppc-target poweropen-target)
+(defun make-callback-trampoline (index &optional info)
+  (declare (ignorable info))
+  (let* ((p (%allocate-callback-pointer 16)))
+    (setf (%%get-unsigned-longlong p 0) #.(subprim-name->offset '.SPpoweropen-callback)
+          (%%get-unsigned-longlong p 8) index)
+    p))
+
Index: /branches/new-random/level-1/ppc-error-signal.lisp
===================================================================
--- /branches/new-random/level-1/ppc-error-signal.lisp	(revision 13309)
+++ /branches/new-random/level-1/ppc-error-signal.lisp	(revision 13309)
@@ -0,0 +1,157 @@
+;;; PPC-specific code to handle trap and uuo callbacks.
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+
+;;; callback here from C exception handler
+
+(defcallback 
+    %xerr-disp 
+    (:address xp :unsigned-fullword fn-reg :unsigned-fullword pc-or-index :signed-fullword errnum :unsigned-fullword rb :signed-fullword continuable)
+  (block %err-disp
+    (let ((fn (unless (eql fn-reg 0) (xp-gpr-lisp xp fn-reg)))
+	  (err-fn (if (eql continuable 0) '%err-disp-internal '%kernel-restart-internal)))
+      (if (eql errnum arch::error-stack-overflow)
+	(handle-stack-overflow xp fn rb)
+	(with-xp-stack-frames (xp fn frame-ptr)	; execute body with dummy stack frame(s)
+	  (with-error-reentry-detection
+	      (let* ((rb-value (xp-gpr-lisp xp rb))
+		     (res
+		      (cond ((< errnum 0)
+			     (%err-disp-internal errnum nil frame-ptr))
+			    ((logtest errnum arch::error-type-error)
+			     (funcall err-fn 
+				      #.(car (rassoc 'type-error *kernel-simple-error-classes*))
+				      (list rb-value (logandc2 errnum arch::error-type-error))
+				      frame-ptr))
+			    ((eql errnum arch::error-udf)
+			     (funcall err-fn $xfunbnd (list rb-value) frame-ptr))
+			    ((eql errnum arch::error-throw-tag-missing)
+			     (%error (make-condition 'cant-throw-error
+						     :tag rb-value)
+				     nil frame-ptr))
+			    ((eql errnum arch::error-cant-call)
+			     (%error (make-condition 'type-error
+						     :datum  rb-value
+						     :expected-type '(or symbol function)
+						     :format-control
+						     "~S is not of type ~S, and can't be FUNCALLed or APPLYed")
+				     nil frame-ptr))
+			    ((eql errnum arch::error-udf-call)
+			     (return-from %err-disp
+			       (handle-udf-call xp frame-ptr)))
+			    ((eql errnum arch::error-alloc-failed)
+			     (%error (make-condition 
+				      'simple-storage-condition
+				      :format-control (%rsc-string $xmemfull))
+				     nil frame-ptr))
+			    ((eql errnum arch::error-memory-full)
+			     (%error (make-condition 
+				      'simple-storage-condition
+				      :format-control (%rsc-string $xnomem))
+				     nil frame-ptr))
+			    ((or (eql errnum arch::error-fpu-exception-double) 
+				 (eql errnum arch::error-fpu-exception-single))
+			     (let* ((code-vector (and fn  (uvref fn 0)))
+				    (instr (if code-vector 
+					     (uvref code-vector pc-or-index)
+					     (%get-long (%int-to-ptr pc-or-index)))))
+			       (let* ((minor (ldb (byte 5 1) instr))
+				      (fra (ldb (byte 5 16) instr))
+				      (frb (ldb (byte 5 11) instr))
+				      (frc (ldb (byte 5 6) instr)))
+				 (declare (fixnum minor fra frb frc))
+				 (if (= minor 12) ; FRSP
+				   (%err-disp-internal $xcoerce (list (xp-double-float xp frc) 'short-float) frame-ptr)
+				   (flet ((coerce-to-op-type (double-arg)
+					    (if (eql errnum arch::error-fpu-exception-double)
+					      double-arg
+					      (handler-case (coerce double-arg 'short-float)
+						(error (c) (declare (ignore c)) double-arg)))))
+				     (multiple-value-bind (status control) (xp-fpscr-info xp)
+				       (%error (make-condition (fp-condition-from-fpscr status control)
+							       :operation (fp-minor-opcode-operation minor)
+							       :operands
+                                                               (if (= minor 22)
+                                                                 (list (coerce-to-op-type (xp-double-float xp frb)))
+                                                                 (list (coerce-to-op-type 
+                                                                        (xp-double-float xp fra))
+                                                                       (if (= minor 25)
+                                                                         (coerce-to-op-type 
+                                                                          (xp-double-float xp frc))
+                                                                         (coerce-to-op-type 
+                                                                          (xp-double-float xp frb))))))
+					       nil
+					       frame-ptr)))))))
+			    ((eql errnum arch::error-excised-function-call)
+			     (%error "~s: code has been excised." (list (xp-gpr-lisp xp ppc::nfn)) frame-ptr))
+			    ((eql errnum arch::error-too-many-values)
+			     (%err-disp-internal $xtoomanyvalues (list rb-value) frame-ptr))
+			    (t (%error "Unknown error #~d with arg: ~d" (list errnum rb-value) frame-ptr)))))
+		(setf (xp-gpr-lisp xp rb) res) ; munge register for continuation
+		)))))))
+
+
+
+(defun handle-udf-call (xp frame-ptr)
+  (let* ((args (xp-argument-list xp))
+         (values (multiple-value-list
+                  (%kernel-restart-internal
+                   $xudfcall
+                   (list (maybe-setf-name (xp-gpr-lisp xp ppc::fname)) args)
+                   frame-ptr)))
+         (stack-argcnt (max 0 (- (length args) 3)))
+         (vsp (%i+ (xp-gpr-lisp xp ppc::vsp) stack-argcnt))
+         (f #'(lambda (values) (apply #'values values))))
+    (setf (xp-gpr-lisp xp ppc::vsp) vsp
+          (xp-gpr-lisp xp ppc::nargs) 1
+          (xp-gpr-lisp xp ppc::arg_z) values
+          (xp-gpr-lisp xp ppc::nfn) f)
+    ;; handle_uuo() (in the lisp kernel) will not bump the PC here.
+    (setf (xp-gpr-lisp xp #+linuxppc-target #$PT_NIP #+darwinppc-target -2)
+	  (uvref f 0))))
+
+
+
+
+
+
+;;; rb is the register number of the stack that overflowed.
+;;; xp & fn are passed so that we can establish error context.
+(defun handle-stack-overflow (xp fn rb)
+  (unwind-protect
+       (with-xp-stack-frames (xp fn frame-ptr) ; execute body with dummy stack frame(s)
+	 (%error
+	  (make-condition
+	   'stack-overflow-condition 
+	   :format-control "Stack overflow on ~a stack."
+	   :format-arguments (list
+			      (if (eql rb ppc::sp)
+				"control"
+				(if (eql rb ppc::vsp)
+				  "value"
+				  (if (eql rb ppc::tsp)
+				    "temp"
+				    "unknown")))))
+	  nil frame-ptr))
+    (ff-call (%kernel-import target::kernel-import-restore-soft-stack-limit)
+	     :unsigned-fullword rb
+	     :void)))
+
+
Index: /branches/new-random/level-1/ppc-threads-utils.lisp
===================================================================
--- /branches/new-random/level-1/ppc-threads-utils.lisp	(revision 13309)
+++ /branches/new-random/level-1/ppc-threads-utils.lisp	(revision 13309)
@@ -0,0 +1,210 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; low-level support for PPC threads and stack-backtrace printing
+
+(in-package "CCL")
+
+
+;;; Sure would be nice to have &optional in defppclapfunction arglists
+;;; Sure would be nice not to do this at runtime.
+
+(let ((bits (lfun-bits #'(lambda (x &optional y) (declare (ignore x y))))))
+  (lfun-bits #'%fixnum-ref
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-ref)))))
+
+(let ((bits (lfun-bits #'(lambda (x &optional y) (declare (ignore x y))))))
+  (lfun-bits #'%fixnum-ref-natural
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-ref-natural)))))
+
+(let ((bits (lfun-bits #'(lambda (x y &optional z) (declare (ignore x y z))))))
+  (lfun-bits #'%fixnum-set
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-set)))))
+
+(let ((bits (lfun-bits #'(lambda (x y &optional z) (declare (ignore x y z))))))
+  (lfun-bits #'%fixnum-set-natural
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-set-natural)))))
+
+
+  
+				  
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+
+
+
+    
+    
+(defun %frame-backlink (p &optional context)
+  (cond ((fake-stack-frame-p p)
+         (%fake-stack-frame.next-sp p))
+        ((fixnump p)
+         (let ((backlink (%%frame-backlink p))
+               (fake-frame
+                (if context (bt.fake-frames context) *fake-stack-frames*)))
+           (loop
+             (when (null fake-frame) (return backlink))
+             (when (eq backlink (%fake-stack-frame.sp fake-frame))
+               (return fake-frame))
+             (setq fake-frame (%fake-stack-frame.link fake-frame)))))
+        (t (error "~s is not a valid stack frame" p))))
+
+
+
+
+(defun catch-frame-sp (catch)
+  (uvref catch target::catch-frame.csp-cell))
+
+(defun bottom-of-stack-p (p context)
+  (and (fixnump p)
+       (locally (declare (fixnum p))
+	 (let* ((tcr (if context (bt.tcr context) (%current-tcr)))
+                (cs-area (%fixnum-ref tcr target::tcr.cs-area)))
+	   (not (%ptr-in-area-p p cs-area))))))
+
+(defun lisp-frame-p (p context)
+  (or (fake-stack-frame-p p)
+      (locally (declare (fixnum p))
+        (let ((next-frame (%frame-backlink p context)))
+          (when (fake-stack-frame-p next-frame)
+            (setq next-frame (%fake-stack-frame.sp next-frame)))
+          (locally (declare (fixnum next-frame))
+            (if (bottom-of-stack-p next-frame context)
+              (values nil t)
+              (and
+               (eql (ash target::lisp-frame.size (- target::fixnum-shift))
+                    (the fixnum (- next-frame p)))
+               ;; EABI C functions keep their saved LRs where we save FN or 0
+               ;; The saved LR of such a function would be fixnum-tagged and never 0.
+               (let* ((fn (%fixnum-ref p target::lisp-frame.savefn)))
+                 (or (eql fn 0) (typep fn 'function))))))))))
+
+
+
+
+
+#+ppc32-target
+(defun valid-subtag-p (subtag)
+  (declare (fixnum subtag))
+  (let* ((tagval (ldb (byte (- ppc32::num-subtag-bits ppc32::ntagbits) ppc32::ntagbits) subtag)))
+    (declare (fixnum tagval))
+    (case (logand subtag ppc32::fulltagmask)
+      (#. ppc32::fulltag-immheader (not (eq (%svref *immheader-types* tagval) 'bogus)))
+      (#. ppc32::fulltag-nodeheader (not (eq (%svref *nodeheader-types* tagval) 'bogus)))
+      (t nil))))
+
+#+ppc64-target
+(defun valid-subtag-p (subtag)
+  (declare (fixnum subtag))
+  (let* ((tagval (ash subtag (- ppc64::nlowtagbits))))
+    (declare (fixnum tagval))
+    (case (logand subtag ppc64::lowtagmask)
+      (#. ppc64::lowtag-immheader (not (eq (%svref *immheader-types* tagval) 'bogus)))
+      (#. ppc64::lowtag-nodeheader (not (eq (%svref *nodeheader-types* tagval) 'bogus)))
+      (t nil))))
+
+#+ppc32-target
+(defun valid-header-p (thing)
+  (let* ((fulltag (fulltag thing)))
+    (declare (fixnum fulltag))
+    (case fulltag
+      (#.ppc32::fulltag-misc (valid-subtag-p (typecode thing)))
+      ((#.ppc32::fulltag-immheader #.ppc32::fulltag-nodeheader) nil)
+      (t t))))
+
+
+
+#+ppc64-target
+(defun valid-header-p (thing)
+  (let* ((fulltag (fulltag thing)))
+    (declare (fixnum fulltag))
+    (case fulltag
+      (#.ppc64::fulltag-misc (valid-subtag-p (typecode thing)))
+      ((#.ppc64::fulltag-immheader-0
+        #.ppc64::fulltag-immheader-1
+        #.ppc64::fulltag-immheader-2
+        #.ppc64::fulltag-immheader-3
+        #.ppc64::fulltag-nodeheader-0
+        #.ppc64::fulltag-nodeheader-1
+        #.ppc64::fulltag-nodeheader-2
+        #.ppc64::fulltag-nodeheader-3) nil)
+      (t t))))
+
+
+
+
+#+ppc32-target
+(defun bogus-thing-p (x)
+  (when x
+    #+cross-compiling (return-from bogus-thing-p nil)
+    (or (not (valid-header-p x))
+        (let ((tag (lisptag x)))
+          (unless (or (eql tag ppc32::tag-fixnum)
+                      (eql tag ppc32::tag-imm)
+                      (in-any-consing-area-p x))
+            ;; This is terribly complicated, should probably write some LAP
+            (let ((typecode (typecode x)))
+                  (not (or (case typecode
+                             (#.ppc32::tag-list
+                              (temporary-cons-p x))
+                             ((#.ppc32::subtag-symbol #.ppc32::subtag-code-vector)
+                              t)              ; no stack-consed symbols or code vectors
+                             (#.ppc32::subtag-value-cell
+                              (on-any-vstack x))
+                             (t
+                              (on-any-tsp-stack x)))
+                           (%heap-ivector-p x)))))))))
+
+
+
+#+ppc64-target
+(defun bogus-thing-p (x)
+  (when x
+    (or (not (valid-header-p x))
+        (let ((tag (lisptag x)))
+          (unless (or (eql tag ppc64::tag-fixnum)
+                      (eql tag ppc64::tag-imm-0)
+                      (eql tag ppc64::tag-imm-2)
+                      (in-any-consing-area-p x))
+            ;; This is terribly complicated, should probably write some LAP
+            (let ((typecode (typecode x)))
+                  (not (or (case typecode
+                             (#.ppc64::fulltag-cons
+                              (temporary-cons-p x))
+                             ((#.ppc64::subtag-symbol #.ppc64::subtag-code-vector)
+                              t)              ; no stack-consed symbols or code vectors
+                             (#.ppc64::subtag-value-cell
+                              (on-any-vstack x))
+                             (t
+                              (on-any-tsp-stack x)))
+                           (%heap-ivector-p x)))))))))
Index: /branches/new-random/level-1/ppc-trap-support.lisp
===================================================================
--- /branches/new-random/level-1/ppc-trap-support.lisp	(revision 13309)
+++ /branches/new-random/level-1/ppc-trap-support.lisp	(revision 13309)
@@ -0,0 +1,1004 @@
+;;; ppc-trap-support
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Support for PPC traps, this includes the event-poll trap
+;;; and all the trxxx traps for type checks & arg count checks.
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "NUMBER-MACROS")
+
+  
+  (defparameter *ppc-instruction-fields*
+    `((:opcode . ,(byte 6 26))
+      (:rt . ,(byte 5 21))
+      (:to . ,(byte 5 21))
+      (:ra . ,(byte 5 16))
+      (:rb . ,(byte 5 11))
+      (:d . ,(byte 16 0))
+      (:ds . ,(byte 14 2))
+      (:ds-xo . ,(byte 2 0))
+      (:sh . ,(byte 5 11))
+      (:mb . ,(byte 5 6))
+      (:me . ,(byte 5 1))
+      (:mb6 . ,(byte 6 5))
+      (:me6 . ,(byte 6 5))
+      (:sh6 . ,(byte 1 1))
+      (:x-minor . ,(byte 10 1))
+      (:fulltag32 . ,(byte ppc32::ntagbits 0))
+      (:lisptag32 . ,(byte ppc32::nlisptagbits 0))
+      (:fulltag64 . ,(byte ppc64::ntagbits 0))
+      (:lisptag64 . ,(byte ppc64::nlisptagbits 0))
+      (:lowtag64 . ,(byte ppc64::nlowtagbits 0))))
+  
+  (defun ppc-instruction-field (field-name)
+    (or (cdr (assoc field-name *ppc-instruction-fields*))
+	(error "Unknown PPC instruction field: ~s" field-name)))
+  
+  (defun ppc-instruction-field-mask (field-spec)
+    (let* ((name (if (atom field-spec) field-spec (car field-spec)))
+	   (value (if (atom field-spec) -1 (cadr field-spec))))
+      (dpb value (ppc-instruction-field name) 0)))
+
+  #+darwinppc-target
+  (progn
+    (def-foreign-type nil
+        (:struct :darwin-ppc-float-state
+                 (:fpregs (:array :double 32))
+                 (:fpscr-pad (:unsigned 32))
+                 (:fpscr (:unsigned 32))))
+    (def-foreign-type nil
+        (:struct :darwin-ppc-vector-state
+                 (:save-vr (:array (:array (:unsigned 32) 4) 32))
+                 (:save-vscr (:array (:unsigned 32) 4))
+                 (:save-pad5 (:array (:unsigned 32) 4))
+                 (:save-vrvalid (:unsigned 32))
+                 (:save-pad6 (:array (:unsigned 32) 7))))
+    #+ppc64-target
+    (progn
+      (def-foreign-type nil
+          (:struct :darwin-ppc-exception-state64
+                   (:dar (:unsigned 64))
+                   (:dsisr (:unsigned 32))
+                   (:exception (:unsigned 32))
+                   (:pad1 (:array (:unsigned 32) 4))))
+      (def-foreign-type nil
+          ;; The real record type is defined with
+          ;; #pragma pack(4) in effect.
+          ;; The :struct parser should really accept
+          ;; some option to deal with that, but Apple
+          ;; should also stop mis-aligning things.
+          (:struct :darwin-ppc-thread-state64
+                   (:srr0 (:unsigned 64))
+                   (:srr1 (:unsigned 64))
+                   (:r0  (:unsigned 64))
+                   (:r1  (:unsigned 64))
+                   (:r2  (:unsigned 64))
+                   (:r3  (:unsigned 64))
+                   (:r4  (:unsigned 64))
+                   (:r5  (:unsigned 64))
+                   (:r6  (:unsigned 64))
+                   (:r7  (:unsigned 64))
+                   (:r8  (:unsigned 64))
+                   (:r9  (:unsigned 64))
+                   (:r10  (:unsigned 64))
+                   (:r11  (:unsigned 64))
+                   (:r12 (:unsigned 64))
+                   (:r13  (:unsigned 64))
+                   (:r14  (:unsigned 64))
+                   (:r15  (:unsigned 64))
+                   (:r16  (:unsigned 64))
+                   (:r17  (:unsigned 64))
+                   (:r18  (:unsigned 64))
+                   (:r19  (:unsigned 64))
+                   (:r20  (:unsigned 64))
+                   (:r21  (:unsigned 64))
+                   (:r22  (:unsigned 64))
+                   (:r23  (:unsigned 64))
+                   (:r24  (:unsigned 64))
+                   (:r25  (:unsigned 64))
+                   (:r26  (:unsigned 64))
+                   (:r27  (:unsigned 64))
+                   (:r28  (:unsigned 64))
+                   (:r29  (:unsigned 64))
+                   (:r30  (:unsigned 64))
+                   (:r31  (:unsigned 64))
+                   (:cr   (:unsigned 32))
+                   (:xer  (:unsigned 32))
+                   (:xer-low (:unsigned 32))
+                   (:lr   (:unsigned 32))
+                   (:lr-low (:unsigned 32))
+                   (:ctr  (:unsigned 32))
+                   (:ctr-low (:unsigned 32))
+                   (:vrsave (:unsigned 32))))
+      (def-foreign-type nil
+          (:struct :darwin-sigaltstack64
+                   (:ss-sp (:* :void))
+                   (:ss-size (:unsigned 64))
+                   (:ss-flags (:unsigned 32))))
+      (def-foreign-type nil
+          (:struct :darwin-mcontext64
+                   (:es (:struct :darwin-ppc-exception-state64))
+                   (:ss (:struct :darwin-ppc-thread-state64))
+                   (:fs (:struct :darwin-ppc-float-state))
+                   (:vs (:struct :darwin-ppc-vector-state))))
+      (def-foreign-type nil
+          (:struct :darwin-ucontext64
+                   (:uc-onstack (:signed 32))
+                   (:uc-sigmask (:signed 32))
+                   (:uc-stack (:struct :darwin-sigaltstack64))
+                   (:uc-link (:* (:struct :darwin-ucontext64)))
+                   (:uc-mcsize (:signed 64))
+                   (:uc-mcontext64 (:* (:struct :darwin-mcontext64)))))
+      )
+    #+ppc32-target
+    (progn
+      (def-foreign-type nil
+          (:struct :darwin-ppc-exception-state32
+                   (:dar (:unsigned 32))
+                   (:dsisr (:unsigned 32))
+                   (:exception (:unsigned 32))
+                   (:pad0 (:unsigned 32))
+                   (:pad1 (:array (:unsigned 32) 4))))
+      (def-foreign-type nil
+          (:struct :darwin-ppc-thread-state32
+                   (:srr0 (:unsigned 32))
+                   (:srr1 (:unsigned 32))
+                   (:r0  (:unsigned 32))
+                   (:r1  (:unsigned 32))
+                   (:r2  (:unsigned 32))
+                   (:r3  (:unsigned 32))
+                   (:r4  (:unsigned 32))
+                   (:r5  (:unsigned 32))
+                   (:r6  (:unsigned 32))
+                   (:r7  (:unsigned 32))
+                   (:r8  (:unsigned 32))
+                   (:r9  (:unsigned 32))
+                   (:r10  (:unsigned 32))
+                   (:r11  (:unsigned 32))
+                   (:r12 (:unsigned 32))
+                   (:r13  (:unsigned 32))
+                   (:r14  (:unsigned 32))
+                   (:r15  (:unsigned 32))
+                   (:r16  (:unsigned 32))
+                   (:r17  (:unsigned 32))
+                   (:r18  (:unsigned 32))
+                   (:r19  (:unsigned 32))
+                   (:r20  (:unsigned 32))
+                   (:r21  (:unsigned 32))
+                   (:r22  (:unsigned 32))
+                   (:r23  (:unsigned 32))
+                   (:r24  (:unsigned 32))
+                   (:r25  (:unsigned 32))
+                   (:r26  (:unsigned 32))
+                   (:r27  (:unsigned 32))
+                   (:r28  (:unsigned 32))
+                   (:r29  (:unsigned 32))
+                   (:r30  (:unsigned 32))
+                   (:r31  (:unsigned 32))
+                   (:cr   (:unsigned 32))
+                   (:xer  (:unsigned 32))
+                   (:lr   (:unsigned 32))
+                   (:ctr  (:unsigned 32))
+                   (:mq (:unsigned 32)) ; ppc 601!
+                   (:vrsave (:unsigned 32))))
+      (def-foreign-type nil
+          (:struct :darwin-sigaltstack32
+                   (:ss-sp (:* :void))
+                   (:ss-size (:unsigned 32))
+                   (:ss-flags (:unsigned 32))))
+      (def-foreign-type nil
+          (:struct :darwin-mcontext32
+                   (:es (:struct :darwin-ppc-exception-state32))
+                   (:ss (:struct :darwin-ppc-thread-state32))
+                   (:fs (:struct :darwin-ppc-float-state))
+                   (:vs (:struct :darwin-ppc-vector-state))))
+      (def-foreign-type nil
+          (:struct :darwin-ucontext32
+                   (:uc-onstack (:signed 32))
+                   (:uc-sigmask (:signed 32))
+                   (:uc-stack (:struct :darwin-sigaltstack32))
+                   (:uc-link (:* (:struct :darwin-ucontext32)))
+                   (:uc-mcsize (:signed 32))
+                   (:uc-mcontext32 (:* (:struct :darwin-mcontext32)))))
+      )
+    )
+      
+                   
+            
+
+  (defmacro with-xp-registers-and-gpr-offset ((xp register-number) (registers offset) &body body)
+    (let* ((regform  #+linuxppc-target
+                     `(pref ,xp :ucontext.uc_mcontext.regs)
+                     #+darwinppc-target
+                     (target-arch-case
+                      ;; Gak.  Apple gratuitously renamed things
+                      ;; for Leopard.  Hey, it's not as if anyone
+                      ;; has better things to do than to deal with
+                      ;; this crap ...
+                      (:ppc32 `(pref ,xp :darwin-ucontext32.uc-mcontext32.ss))
+                      (:ppc64 `(pref ,xp :darwin-ucontext64.uc-mcontext64.ss)))))
+    `(with-macptrs ((,registers ,regform))
+      (let ((,offset (xp-gpr-offset ,register-number)))
+	,@body))))
+
+  (defmacro RA-field (instr)
+    `(ldb (byte 5 16) ,instr))
+
+  (defmacro RB-field (instr)
+    `(ldb (byte 5 11) ,instr))
+
+  (defmacro D-field (instr)
+    `(ldb (byte 16 0) ,instr))
+
+  (defmacro RS-field (instr)
+    `(ldb (byte 5 21) ,instr))
+  
+  (defmacro lisp-reg-p (reg)
+    `(>= ,reg ppc::fn))
+  
+  (defmacro ppc-lap-word (instruction-form)
+    (uvref (uvref (compile nil
+                           `(lambda (&lap 0)
+			     (ppc-lap-function () ((?? 0))
+			      ,instruction-form)))
+		  
+                  0) #+ppc32-host 0 #+ppc64-host 1))
+  
+  (defmacro ppc-instruction-mask (&rest fields)
+    `(logior ,@(mapcar #'ppc-instruction-field-mask (cons :opcode fields))))
+  
+  )  
+
+
+
+(defun xp-gpr-offset (register-number)
+  (unless (and (fixnump register-number)
+               (<= -2 (the fixnum register-number))
+               (< (the fixnum register-number) 48))
+    (setq register-number (require-type register-number '(integer -2 48))))
+  (the fixnum 
+    (* (the fixnum #+linuxppc-target register-number
+	           #+darwinppc-target (+ register-number 2))
+       target::node-size)))
+
+
+
+(defun xp-gpr-lisp (xp register-number)
+  (with-xp-registers-and-gpr-offset (xp register-number) (registers offset)
+    (values (%get-object registers offset))))
+
+(defun (setf xp-gpr-lisp) (value xp register-number)
+  (with-xp-registers-and-gpr-offset (xp register-number) (registers offset)
+    (%set-object registers offset value)))
+
+(defun xp-gpr-signed-long (xp register-number)
+  (with-xp-registers-and-gpr-offset (xp register-number) (registers offset)
+    (values (%get-signed-long registers offset))))
+
+(defun xp-gpr-signed-doubleword (xp register-number)
+  (with-xp-registers-and-gpr-offset (xp register-number) (registers offset)
+    (values (%%get-signed-longlong registers offset))))
+  
+
+(defun xp-gpr-macptr (xp register-number)
+  (with-xp-registers-and-gpr-offset (xp register-number) (registers offset)
+    (values (%get-ptr registers offset))))
+
+(defun xp-argument-list (xp)
+  (let ((nargs (xp-gpr-lisp xp ppc::nargs))     ; tagged as a fixnum (how convenient)
+        (arg-x (xp-gpr-lisp xp ppc::arg_x))
+        (arg-y (xp-gpr-lisp xp ppc::arg_y))
+        (arg-z (xp-gpr-lisp xp ppc::arg_z)))
+    (cond ((eql nargs 0) nil)
+          ((eql nargs 1) (list arg-z))
+          ((eql nargs 2) (list arg-y arg-z))
+          (t (let ((args (list arg-x arg-y arg-z)))
+               (if (eql nargs 3)
+                 args
+                 (let ((vsp (xp-gpr-macptr xp ppc::vsp)))
+                   (dotimes (i (- nargs 3))
+                     (push (%get-object vsp (* i target::node-size)) args))
+                   args)))))))
+    
+(defun xp-fpscr-info (xp)
+  (let* ((fpscr #+(and linuxppc-target 32-bit-target) (%get-unsigned-long (pref xp :ucontext.uc_mcontext.regs) (ash #$PT_FPSCR 2))
+                #+(and linuxppc-target 64-bit-target)
+                (%get-unsigned-long (pref xp :ucontext.uc_mcontext.fp_regs) (ash 65 2))
+		#+(and darwinppc-target ppc32-target)
+                (pref xp :darwin-ucontext32.uc-mcontext32.fs.fpscr)
+                #+(and darwinppc-target ppc64-target)
+                (pref xp :darwin-ucontext64.uc-mcontext64.fs.fpscr)))
+    (values (ldb (byte 24 8) fpscr) (ldb (byte 8 0) fpscr))))
+
+#+linuxppc-target
+(defun xp-double-float (xp fpr)
+  #+32-bit-target
+  (%get-double-float (pref xp :ucontext.uc_mcontext.regs) (+ (ash #$PT_FPR0 2)  (ash fpr 3)))
+  #+64-bit-target
+  (%get-double-float (pref xp :ucontext.uc_mcontext.fp_regs) (ash fpr 3))
+  )
+
+#+darwinppc-target
+(defun xp-double-float (xp fpr)
+  (%get-double-float
+     #+ppc32-target (pref xp :darwin-ucontext32.uc-mcontext32.fs)
+     #+ppc64-target (pref xp :darwin-ucontext64.uc-mcontext64.fs)
+     (ash fpr 3)))
+
+
+(defparameter *trap-lookup-tries* 5)
+
+
+
+(defun %scan-for-instr (mask opcode fn pc-index tries)
+  (let ((code-vector (and fn (uvref fn 0)))
+        (offset 0))
+    (declare (fixnum offset))
+    (flet ((get-instr ()
+             (if code-vector
+               (let ((index (+ pc-index offset)))
+                 (when (< index 0) (return-from %scan-for-instr nil))
+                 (uvref code-vector index))
+               (%get-long pc-index (the fixnum (* 4 offset))))))
+      (declare (dynamic-extent #'get-instr))
+      (dotimes (i tries)
+        (decf offset)
+        (let ((instr (get-instr)))
+          (when (match-instr instr mask opcode)
+            (return instr))
+          (when (codevec-header-p instr)
+            (return nil)))))))
+
+
+
+
+
+
+(defun return-address-offset (xp fn machine-state-offset)
+  (with-macptrs ((regs (pref xp #+linuxppc-target :ucontext.uc_mcontext.regs
+			        #+(and darwinppc-target ppc32-target)
+                                :darwin-ucontext32.uc-mcontext32
+                                #+(and darwinppc-target ppc64-target)
+                                :darwin-ucontext64.uc-mcontext64)))
+    (if (functionp fn)
+      (or (%code-vector-pc (uvref fn 0) (%inc-ptr regs machine-state-offset))
+           (%get-ptr regs machine-state-offset))
+      (%get-ptr regs machine-state-offset))))
+
+(defconstant lr-offset-in-register-context
+  #+linuxppc-target (ash #$PT_LNK target::word-shift)
+  #+(and darwinppc-target ppc32-target)
+  (+ (get-field-offset :darwin-mcontext32.ss)
+     (get-field-offset :darwin-ppc-thread-state32.lr))
+  #+(and darwinppc-target ppc64-target)
+  (+ (get-field-offset :darwin-mcontext64.ss)
+     (get-field-offset :darwin-ppc-thread-state64.lr)))
+
+(defconstant pc-offset-in-register-context
+  #+linuxppc-target (ash #$PT_NIP target::word-shift)
+  #+(and darwinppc-target ppc32-target)
+  (+ (get-field-offset :darwin-mcontext32.ss)
+     (get-field-offset :darwin-ppc-thread-state32.srr0))
+  #+(and darwinppc-target ppc64-target)
+  (+ (get-field-offset :darwin-mcontext64.ss)
+     (get-field-offset :darwin-ppc-thread-state64.srr0)))
+
+;;; When a trap happens, we may have not yet created control
+;;; stack frames for the functions containing PC & LR.
+;;; If that is the case, we add fake-stack-frame's to *fake-stack-frames*
+;;; There are 4 cases:
+;;;
+;;; PC in FN
+;;;   Push 1 stack frame: PC/FN
+;;;   This might miss one recursive call, but it won't miss any variables
+;;; PC in NFN
+;;;   Push 2 stack frames:
+;;;   1) PC/NFN/VSP
+;;;   2) LR/FN/VSP
+;;;   This might think some of NFN's variables are part of FN's stack frame,
+;;;   but that's the best we can do.
+;;; LR in FN
+;;;   Push 1 stack frame: LR/FN
+;;; None of the above
+;;;   Push no new stack frames
+;;;
+;;; The backtrace support functions in "ccl:l1;l1-lisp-threads.lisp" know how
+;;; to find the fake stack frames and handle them as arguments.
+(defun funcall-with-xp-stack-frames (xp trap-function thunk)
+  (cond ((null trap-function)
+         ; Maybe inside a subprim from a lisp function
+         (let* ((fn (xp-gpr-lisp xp ppc::fn))
+                (lr (return-address-offset
+                     xp fn lr-offset-in-register-context)))
+           (if (fixnump lr)
+             (let* ((sp (xp-gpr-lisp xp ppc::sp))
+                    (vsp (xp-gpr-lisp xp ppc::vsp))
+                    (frame (%cons-fake-stack-frame sp sp fn lr vsp xp *fake-stack-frames*))
+                    (*fake-stack-frames* frame))
+               (declare (dynamic-extent frame))
+               (funcall thunk frame))
+             (funcall thunk (xp-gpr-lisp xp ppc::sp)))))
+        ((eq trap-function (xp-gpr-lisp xp ppc::fn))
+         (let* ((sp (xp-gpr-lisp xp ppc::sp))
+                (fn trap-function)
+                (lr (return-address-offset
+                     xp fn pc-offset-in-register-context))
+                (vsp (xp-gpr-lisp xp ppc::vsp))
+                (frame (%cons-fake-stack-frame sp sp fn lr vsp xp *fake-stack-frames*))
+                (*fake-stack-frames* frame))
+           (declare (dynamic-extent frame))
+           (funcall thunk frame)))
+        ((eq trap-function (xp-gpr-lisp xp ppc::nfn))
+         (let* ((sp (xp-gpr-lisp xp ppc::sp))
+                (fn (xp-gpr-lisp xp ppc::fn))
+                (lr (return-address-offset
+                     xp fn lr-offset-in-register-context))
+                (vsp (xp-gpr-lisp xp ppc::vsp))
+                (lr-frame (%cons-fake-stack-frame sp sp fn lr vsp xp))
+                (pc-fn trap-function)
+                (pc-lr (return-address-offset
+                        xp pc-fn pc-offset-in-register-context))
+                (pc-frame (%cons-fake-stack-frame sp lr-frame pc-fn pc-lr vsp xp *fake-stack-frames*))
+                (*fake-stack-frames* pc-frame))
+           (declare (dynamic-extent lr-frame pc-frame))
+           (funcall thunk pc-frame)))
+        (t (funcall thunk (xp-gpr-lisp xp ppc::sp)))))
+
+
+
+;;; Enter here from handle-trap in "lisp-exceptions.c".
+;;; xp is a pointer to an ExceptionInformationPowerPC record.
+;;; the-trap is the trap instruction that got us here.
+;;; fn-reg is either fn, nfn or 0. If it is fn or nfn, then
+;;; the trap occcurred in that register's code vector.
+;;; If it is 0, then the trap occurred somewhere else.
+;;; pc-index is either the index in fn-reg's code vector
+;;; or, if fn-reg is 0, the address of the PC at the trap instruction.
+;;; This code parallels the trap decoding code in
+;;; "lisp-exceptions.c" that runs if (symbol-value 'cmain)
+;;; is not a macptr.
+;;; Some of these could probably call %err-disp instead of error,
+;;; but I was too lazy to look them up.
+
+#+ppc32-target
+(defcallback xcmain (:without-interrupts t
+					:address xp 
+					:unsigned-fullword fn-reg 
+					:address pc-or-index 
+					:unsigned-fullword the-trap
+					:signed-fullword  arg-0
+					:signed-fullword arg-1)
+  ;; twgti nargs,0
+  ;; time for event polling.
+  ;; This used to happen a lot so we test for it first.
+  (let ((fn (unless (eql fn-reg 0) (xp-gpr-lisp xp fn-reg))))
+    (with-xp-stack-frames (xp fn frame-ptr)
+      (if (eql the-trap (ppc-lap-word (twgti nargs 0)))
+        (cmain)
+        (with-error-reentry-detection
+          (let ((pc-index (if (eql fn-reg 0) pc-or-index (%ptr-to-int pc-or-index)))
+                instr ra temp rs condition)
+            (cond
+              ((= the-trap #$SIGBUS)
+               (%error (make-condition 'invalid-memory-access
+                                       :address arg-0
+                                       :write-p (not (zerop arg-1)))
+                       ()
+                       frame-ptr))              
+             ;; tweqi RA nil-value - resolve-eep, or resolve-foreign-variable
+	      ((and (match-instr the-trap
+				 (ppc-instruction-mask  :opcode :to :d)
+				 (ppc-lap-word (tweqi ?? (target-nil-value))))
+		    (setq instr (scan-for-instr
+				 (ppc-instruction-mask :opcode :d)
+				 (ppc-lap-word (lwz ??
+						    (+ 4 ppc32::misc-data-offset)
+						    ??))
+                                               fn pc-index)))
+	       (let* ((eep-or-fv (xp-gpr-lisp xp (RA-field instr))))
+                 (etypecase eep-or-fv
+                   (external-entry-point
+                    (resolve-eep eep-or-fv)
+                    (setf (xp-gpr-lisp xp (RA-field the-trap))
+                          (eep.address eep-or-fv)))
+                   (foreign-variable
+                    (resolve-foreign-variable eep-or-fv)
+                    (setf (xp-gpr-lisp xp (RA-field the-trap))
+                          (fv.addr eep-or-fv))))))
+             ;; twnei RA,N; RA = nargs
+             ;; nargs check, no optional or rest involved
+	      ((match-instr the-trap
+                           (ppc-instruction-mask :opcode :to :ra)
+                           (ppc-lap-word (twnei nargs ??)))
+              (%error (if (< (xp-GPR-signed-long xp ppc::nargs) (D-field the-trap))
+                        'too-few-arguments
+                        'too-many-arguments )
+                      (list :nargs (ash (xp-GPR-signed-long xp ppc::nargs)
+					(- ppc32::fixnumshift))
+			    :fn  fn)
+                      frame-ptr))
+             
+             ;; twnei RA,N; RA != nargs, N = fulltag_node/immheader
+             ;; type check; look for "lbz rt-imm,-3(ra-node)"
+             ((and (or (match-instr the-trap
+                                    (ppc-instruction-mask :opcode :to :fulltag32)
+                                    (ppc-lap-word (twnei ?? ppc32::fulltag-nodeheader)))
+                       (match-instr the-trap
+                                    (ppc-instruction-mask :opcode :to :fulltag32)
+                                    (ppc-lap-word (twnei ?? ppc32::fulltag-immheader))))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :d)
+                                               (ppc-lap-word (lbz ?? ppc32::misc-subtag-offset ??))
+                                               fn pc-index))
+                   (lisp-reg-p (setq ra (RA-field instr))))
+              (let* ((typecode (D-field the-trap))
+                     (type-tag (logand typecode ppc32::fulltagmask))
+                     (type-name (svref (if (eql type-tag ppc32::fulltag-nodeheader)
+                                         *nodeheader-types*
+                                         *immheader-types*)
+                                       (ldb (byte (- ppc32::num-subtag-bits ppc32::ntagbits) ppc32::ntagbits) typecode))))
+                (%error (make-condition 'type-error
+                                        :format-control (%rsc-string $XWRONGTYPE)
+                                        :datum (xp-GPR-lisp xp ra)
+                                        :expected-type type-name)
+                        nil
+                        frame-ptr)))
+
+             ;; twnei RA,N; RA != nargs, N = subtag_character
+             ;; type check; look for "clrlwi rs-node,ra-imm,24" = "rlwinm rs,ra,0,24,31"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :d)
+                                (ppc-lap-word (twnei ?? ppc32::subtag-character)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :rb :mb :me)
+                                               (ppc-lap-word (rlwinm ?? ?? 0 24 31))
+                                               fn pc-index))
+                   (lisp-reg-p (setq rs (RS-field instr))))
+              (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type 'character)
+                        nil
+                        frame-ptr))
+
+             ;; twnei RA,N; RA != nargs, N != fulltag_node/immheader
+             ;; (since that case was handled above.)
+             ;; type check; look for "clrlwi rs-node,ra-imm,29/30" = "rlwinm rs,ra,0,29/30,31"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to) 
+                                (ppc-lap-word (twnei ?? ??)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :rb (:mb 28) :me)
+                                               (ppc-lap-word (rlwinm ?? ?? 0 28 31))                                               
+                                               fn pc-index))
+                   (or (eql (- 32 ppc32::ntagbits) (setq temp (ldb #.(ppc-instruction-field :mb) instr)))
+                       (eql (- 32 ppc32::nlisptagbits) temp))
+                   (lisp-reg-p (setq rs (RS-field instr))))
+              (let* ((tag (logand the-trap ppc32::tagmask))
+                     (type-name 
+                      (case tag
+                        (#.ppc32::tag-fixnum 'fixnum)
+                        (#.ppc32::tag-list (if (eql temp (- 32 ppc32::ntagbits)) 'cons 'list))
+                        (#.ppc32::tag-misc 'uvector)
+                        (#.ppc32::tag-imm 'immediate))))                                      
+                (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type type-name)
+                        nil
+                        frame-ptr)))
+             
+             ;; twlgti RA,N; RA = nargs (xy = 01)
+             ;; twllti RA,N; RA = nargs (xy = 10)
+             ;; nargs check, optional or rest involved
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode (:to #x1c) :ra)
+                                (ppc-lap-word (twi ?? ppc::nargs ??)))
+                   (or (eql #b01 (setq temp (ldb #.(ppc-instruction-field :to) the-trap)))
+	               (eql #b10 temp)))
+              (%error (if (eql temp #b10)
+                        'too-few-arguments
+                        'too-many-arguments)
+                      (list :nargs (ash (xp-GPR-signed-long xp ppc::nargs)
+					(- ppc32::fixnumshift))
+			    :fn  fn)
+                      frame-ptr))
+             
+             ;; tweqi RA,N; N = unbound
+             ;; symeval boundp check; look for "lwz RA,symbol.vcell(nodereg)"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :d)                                
+                                (ppc-lap-word (tweqi ?? ppc32::unbound-marker)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :d)
+                                               (ppc-lap-word (lwz ?? ppc32::symbol.vcell ??))                                               
+                                               fn pc-index))
+                   (lisp-reg-p (setq ra (RA-field instr))))
+              (setf (xp-GPR-lisp xp (RA-field the-trap))
+                    (%kernel-restart-internal $xvunbnd (list (xp-GPR-lisp xp ra)) frame-ptr)))
+	     ;; tweqi RA,N: n = (%slot-unbound-marker)
+	     ;; slot-unbound trap.  Look for preceding "lwzx RA,rx,ry".
+	     ;; rx = slots-vector, ry = scaled index in slots vector.
+	     ((and (match-instr the-trap
+				(ppc-instruction-mask :opcode :to :d)
+				(ppc-lap-word (tweqi ?? ppc32::slot-unbound-marker)))
+		   (setq instr (scan-for-instr (ppc-instruction-mask
+						:opcode :rt  :x-minor)
+					       (dpb
+						(RA-field the-trap)
+						(byte 5 21)
+						(ppc-lap-word
+						 (lwzx ?? ?? ??)))
+					       fn pc-index)))
+              (setq *error-reentry-count* 0)  ; succesfully reported error
+
+              ;; %SLOT-UNBOUND-TRAP will decode the arguments further,
+              ;; then call the generic function SLOT-UNBOUND.  That
+              ;; might return a value; if so, set the value of the
+              ;; register that caused the trap to that value.
+              (setf (xp-gpr-lisp xp (ra-field the-trap))
+                    (%slot-unbound-trap (xp-gpr-lisp xp (RA-field instr))
+                                        (ash (- (xp-gpr-signed-long xp (RB-field instr))
+                                                ppc32::misc-data-offset)
+                                             (- ppc32::word-shift))
+                                        frame-ptr)))
+             ;; twlge RA,RB
+             ;; vector bounds check; look for "lwz immreg, misc_header_offset(nodereg)"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :x-minor)                                
+                                (ppc-lap-word (twlge 0 0)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode #|:d|#)
+                                               (ppc-lap-word (lwz ?? ?? #|ppc32::misc-header-offset|# ??))
+                                               fn pc-index))
+                   (lisp-reg-p (setq ra (RA-field instr))))
+              (%error (%rsc-string $xarroob)
+                      (list (xp-GPR-lisp xp (RA-field the-trap))
+                            (xp-GPR-lisp xp ra))
+                      frame-ptr))
+             ;; twi 27 ra d - array header rank check
+	     ((and (match-instr the-trap
+				(ppc-instruction-mask :opcode :to)
+				(ppc-lap-word (twi 27 ?? ??)))
+		   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :d)
+                                               (ppc-lap-word (lwz ?? ppc32::arrayH.rank ??))
+                                               fn pc-index))
+		   (lisp-reg-p (setq ra (RA-field instr))))
+	      (%error (%rsc-string $xndims)
+		      (list (xp-gpr-lisp xp ra)
+			    (ash (ldb (byte 16 0) the-trap) (- ppc32::fixnumshift)))
+		      frame-ptr))
+	     ;; tw 27 ra rb - array flags check
+	     ((and (match-instr the-trap
+				(ppc-instruction-mask :opcode :to :x-minor)
+				(ppc-lap-word (tw 27 ?? ??)))
+		   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :d)
+                                               (ppc-lap-word (lwz ?? ppc32::arrayH.flags ??))
+                                               fn pc-index))
+		   (lisp-reg-p (setq ra (RA-field instr)))
+		   (let* ((expected (xp-gpr-lisp xp (RB-field the-trap)))
+			  (expected-subtype (ldb
+					     ppc32::arrayH.flags-cell-subtag-byte
+					     expected))
+			  (expect-simple (=
+					  (ldb ppc32::arrayH.flags-cell-bits-byte
+					       expected)
+					  (ash 1 $arh_simple_bit)))
+			  (type-name
+			   (case expected-subtype
+			     (#.ppc32::subtag-double-float-vector 'double-float))))
+
+		     (and type-name expect-simple
+			  (setq condition
+				(make-condition 'type-error
+						:datum (xp-gpr-lisp xp ra)
+						:expected-type
+						`(simple-array ,type-name))))))
+	      (%error condition nil frame-ptr))
+			       
+             ;; Unknown trap
+             (t (%error "Unknown trap: #x~x~%xp: ~s, fn: ~s, pc: #x~x"
+                        (list the-trap xp fn (ash pc-index ppc32::fixnumshift))
+                        frame-ptr)))))))))
+
+#+ppc64-target
+(defcallback xcmain (:without-interrupts t
+					:address xp 
+					:unsigned-fullword fn-reg 
+					:address pc-or-index 
+					:unsigned-fullword the-trap
+					:signed-doubleword  arg0
+					:signed-doubleword arg1)
+  ;; tdgti nargs,0
+  ;; time for event polling.
+  ;; This used to happen a lot so we test for it first.
+  (let ((fn (unless (eql fn-reg 0) (xp-gpr-lisp xp fn-reg))))
+    (with-xp-stack-frames (xp fn frame-ptr)
+      (if (eql the-trap (ppc-lap-word (tdgti nargs 0)))
+        (cmain)
+        (with-error-reentry-detection
+          (let ((pc-index (if (eql fn-reg 0) pc-or-index (%ptr-to-int pc-or-index)))
+                instr ra temp rs condition)
+            (cond
+              ;; tdeqi RA nil-value - resolve-eep, or resolve-foreign-variable
+	      ((and (match-instr the-trap
+				 (ppc-instruction-mask  :opcode :to :d)
+				 (ppc-lap-word (tdeqi ?? (target-nil-value))))
+		    (setq instr (scan-for-instr
+				 (ppc-instruction-mask :opcode :ds :ds-xo)
+				 (ppc-lap-word (ld ??
+						    (+ 8 ppc64::misc-data-offset)
+						    ??))
+                                               fn pc-index)))
+	       (let* ((eep-or-fv (xp-gpr-lisp xp (RA-field instr))))
+                 (etypecase eep-or-fv
+                   (external-entry-point
+                    (resolve-eep eep-or-fv)
+                    (setf (xp-gpr-lisp xp (RA-field the-trap))
+                          (eep.address eep-or-fv)))
+                   (foreign-variable
+                    (resolve-foreign-variable eep-or-fv)
+                    (setf (xp-gpr-lisp xp (RA-field the-trap))
+                          (fv.addr eep-or-fv))))))
+              ((= the-trap #$SIGBUS)
+               (%error (make-condition 'invalid-memory-access
+                                       :address arg0
+                                       :write-p (not (zerop arg1)))
+                       ()
+                       frame-ptr))
+              ;; tdnei RA,N; RA = nargs
+              ;; nargs check, no optional or rest involved
+	      ((match-instr the-trap
+                           (ppc-instruction-mask :opcode :to :ra)
+                           (ppc-lap-word (tdnei nargs ??)))
+              (%error (if (< (xp-GPR-signed-doubleword xp ppc::nargs) (D-field the-trap))
+                        'too-few-arguments
+                        'too-many-arguments )
+                      (list :nargs (ash (xp-GPR-signed-doubleword xp ppc::nargs)
+					(- ppc64::fixnumshift))
+			    :fn  fn)
+                      frame-ptr))
+             
+             ;; tdnei RA,N; RA != nargs, N = lowtag_node/immheader
+             ;; type check; look for "lbz rt-imm,-5(ra-node)"
+             ((and (or (match-instr the-trap
+                                    (ppc-instruction-mask :opcode :to :lowtag64)
+                                    (ppc-lap-word (tdnei ?? ppc64::lowtag-nodeheader)))
+                       (match-instr the-trap
+                                    (ppc-instruction-mask :opcode :rt :lowtag64)
+                                    (ppc-lap-word (tdnei ?? ppc64::lowtag-immheader))))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :d)
+                                               (ppc-lap-word (lbz ?? ppc64::misc-subtag-offset ??))
+                                               fn pc-index))
+                   (lisp-reg-p (setq ra (RA-field instr))))
+              (let* ((typecode (D-field the-trap))
+                     (type-tag (logand typecode ppc64::lowtagmask))
+                     (type-name (svref (if (eql type-tag ppc64::lowtag-nodeheader)
+                                         *nodeheader-types*
+                                         *immheader-types*)
+                                       (ash typecode (- ppc64::nlowtagbits)))))
+                (%error (make-condition 'type-error
+                                        :format-control (%rsc-string $XWRONGTYPE)
+                                        :datum (xp-GPR-lisp xp ra)
+                                        :expected-type type-name)
+                        nil
+                        frame-ptr)))
+             ;; tdnei RA,N; RA != nargs, N = subtag_character type
+             ;; check; look for "clrldi rs-node,ra-imm,56" = "rldicl
+             ;; rs,ra,0,55"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :rt :d)
+                                (ppc-lap-word (tdnei ?? ppc64::subtag-character)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :sh :mb6 :sh6)
+                                               (ppc-lap-word (rldicl ?? ?? 0 56))
+                                               fn pc-index))
+                   (lisp-reg-p (setq rs (RS-field instr))))
+              (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type 'character)
+                        nil
+                        frame-ptr))
+
+             ;; tdnei RA,N; RA != nargs, N = ppc64::tag-fixnum.  type
+             ;; check; look for "clrldi rs-node,ra-imm,61" = "rldicl
+             ;; rs,ra,61"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :rt)
+                                (ppc-lap-word (tdnei ?? ppc64::tag-fixnum)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :sh :mb6 :sh6)
+                                               (ppc-lap-word (rldicl ?? ?? 0 61))                                               
+                                               fn pc-index))
+
+                   (lisp-reg-p (setq rs (RS-field instr))))
+                (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type 'fixnum)
+                        nil
+                        frame-ptr))
+             ;; tdi 3,RA,ppc64::fulltag-cons; RA != nargs type check;
+             ;; look for "clrldi rs-node,ra-imm,60" = "rldicl
+             ;; rs,ra,60"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :d)
+                                (ppc-lap-word (tdi 3 ?? ppc64::fulltag-cons)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :sh :mb6 :sh6)
+                                               (ppc-lap-word (rldicl ?? ?? 0 60))                                               
+                                               fn pc-index))
+
+                   (lisp-reg-p (setq rs (RS-field instr))))
+                (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type 'list)
+                        nil
+                        frame-ptr))             
+             ;; tdnei RA,ppc64::fulltag-cons; RA != nargs type check;
+             ;; look for "clrldi rs-node,ra-imm,60" = "rldicl
+             ;; rs,ra,60"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :d)
+                                (ppc-lap-word (tdnei ?? ppc64::fulltag-cons)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :sh :mb6 :sh6)
+                                               (ppc-lap-word (rldicl ?? ?? 0 60))                                               
+                                               fn pc-index))
+
+                   (lisp-reg-p (setq rs (RS-field instr))))
+                (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type 'cons)
+                        nil
+                        frame-ptr))
+             ;; tdnei RA,ppc64::subtag-single-float; RA != nargs type check;
+             ;; look for "clrldi rs-node,ra-imm,60" = "rldicl
+             ;; rs,ra,60"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :d)
+                                (ppc-lap-word (tdnei ?? ppc64::subtag-single-float)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :sh :mb6 :sh6)
+                                               (ppc-lap-word (rldicl ?? ?? 0 60))                                               
+                                               fn pc-index))
+
+                   (lisp-reg-p (setq rs (RS-field instr))))
+                (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type 'short-float)
+                        nil
+                        frame-ptr))
+             ;; tdnei RA,ppc64::fulltag-misc; RA != nargs type check;
+             ;; look for "clrldi rs-node,ra-imm,60" = "rldicl
+             ;; rs,ra,60"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :d)
+                                (ppc-lap-word (tdnei ?? ppc64::fulltag-misc)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :sh :mb6 :sh6)
+                                               (ppc-lap-word (rldicl ?? ?? 0 60))                                               
+                                               fn pc-index))
+
+                   (lisp-reg-p (setq rs (RS-field instr))))
+                (%error (make-condition 'type-error
+                                        :datum (xp-GPR-lisp xp rs)
+                                        :expected-type 'uvector)
+                        nil
+                        frame-ptr))
+             ;; tdlgti RA,N; RA = nargs (xy = 01)
+             ;; tdllti RA,N; RA = nargs (xy = 10)
+             ;; nargs check, optional or rest involved
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode (:to #x1c) :ra)
+                                (ppc-lap-word (tdi ?? ppc::nargs ??)))
+                   (or (eql #b01 (setq temp (ldb #.(ppc-instruction-field :to) the-trap)))
+	               (eql #b10 temp)))
+              (%error (if (eql temp #b10)
+                        'too-few-arguments
+                        'too-many-arguments)
+                      (list :nargs (ash (xp-GPR-signed-doubleword xp ppc::nargs)
+					(- ppc64::fixnumshift))
+			    :fn  fn)
+                      frame-ptr))
+             
+             ;; tdeqi RA,N; N = unbound
+             ;; symeval boundp check; look for "ld RA,symbol.vcell(nodereg)"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :d) 
+                                (ppc-lap-word (tdeqi ?? ppc64::unbound-marker)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :ds :ds-xo)
+                                               (ppc-lap-word (ld ?? ppc64::symbol.vcell ??))                                               
+                                               fn pc-index))
+                   (lisp-reg-p (setq ra (RA-field instr))))
+              (setf (xp-GPR-lisp xp (RA-field the-trap))
+                    (%kernel-restart-internal $xvunbnd (list (xp-GPR-lisp xp ra)) frame-ptr)))
+	     ;; tdeqi RA,N: n = (%slot-unbound-marker)
+	     ;; slot-unbound trap.  Look for preceding "ldx RA,rx,ry".
+	     ;; rx = slots-vector, ry = scaled index in slots vector.
+	     ((and (match-instr the-trap
+				(ppc-instruction-mask :opcode :to :d)
+				(ppc-lap-word (tdeqi ?? ppc64::slot-unbound-marker)))
+		   (setq instr (scan-for-instr (ppc-instruction-mask
+						:opcode :rt  :x-minor)
+					       (dpb
+						(RA-field the-trap)
+						(byte 5 21)
+						(ppc-lap-word
+						 (ldx ?? ?? ??)))
+					       fn pc-index)))
+              (setq *error-reentry-count* 0)  ; succesfully reported error
+              ;; %SLOT-UNBOUND-TRAP will decode the arguments further,
+              ;; then call the generic function SLOT-UNBOUND.  That
+              ;; might return a value; if so, set the value of the
+              ;; register that caused the trap to that value.
+              (setf (xp-gpr-lisp xp (ra-field the-trap))
+                    (%slot-unbound-trap (xp-gpr-lisp xp (RA-field instr))
+                                        (ash (- (xp-gpr-signed-doubleword xp (RB-field instr))
+                                                ppc64::misc-data-offset)
+                                             (- ppc64::word-shift))
+                                        frame-ptr)))
+             ;; tdlge RA,RB
+             ;; vector bounds check; look for "ld immreg, misc_header_offset(nodereg)"
+             ((and (match-instr the-trap
+                                (ppc-instruction-mask :opcode :to :x-minor)
+                                (ppc-lap-word (tdlge ?? ??)))
+                   (setq instr (scan-for-instr (ppc-instruction-mask :opcode #|:d|# :ds-xo)
+                                               (ppc-lap-word (ld ?? ?? #|ppc32::misc-header-offset|# ??))
+                                               fn pc-index))
+                   (lisp-reg-p (setq ra (RA-field instr))))
+              (%error (%rsc-string $xarroob)
+                      (list (xp-GPR-lisp xp (RA-field the-trap))
+                            (xp-GPR-lisp xp ra))
+                      frame-ptr))
+             ;; tdi 27 ra d - array header rank check
+	     ((and (match-instr the-trap
+				(ppc-instruction-mask :opcode :to)
+				(ppc-lap-word (tdi 27 ?? ??)))
+		   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :ds :ds-xo)
+                                               (ppc-lap-word (ld ?? ppc64::arrayH.rank ??))
+                                               fn pc-index))
+		   (lisp-reg-p (setq ra (RA-field instr))))
+	      (%error (%rsc-string $xndims)
+		      (list (xp-gpr-lisp xp ra)
+			    (ash (ldb (byte 16 0) the-trap) (- ppc64::fixnumshift)))
+		      frame-ptr))
+	     ;; td 27 ra rb - array flags check
+	     ((and (match-instr the-trap
+				(ppc-instruction-mask :opcode :to :x-minor)
+				(ppc-lap-word (td 27 ?? ??)))
+		   (setq instr (scan-for-instr (ppc-instruction-mask :opcode :ds :ds-xo)
+                                               (ppc-lap-word (ld ?? ppc64::arrayH.flags ??))
+                                               fn pc-index))
+		   (lisp-reg-p (setq ra (RA-field instr)))
+		   (let* ((expected (xp-gpr-lisp xp (RB-field the-trap)))
+			  (expected-subtype (ldb
+					     ppc64::arrayH.flags-cell-subtag-byte
+					     expected))
+			  (expect-simple (=
+					  (ldb ppc64::arrayH.flags-cell-bits-byte
+					       expected)
+					  (ash 1 $arh_simple_bit)))
+			  (type-name
+			   (case expected-subtype
+			     (#.ppc64::subtag-double-float-vector 'double-float))))
+
+		     (and type-name expect-simple
+			  (setq condition
+				(make-condition 'type-error
+						:datum (xp-gpr-lisp xp ra)
+						:expected-type
+						`(simple-array ,type-name))))))
+	      (%error condition nil frame-ptr))
+			       
+             ;; Unknown trap
+             (t (%error "Unknown trap: #x~x~%xp: ~s, fn: ~s, pc: #x~x"
+                        (list the-trap xp fn (ash pc-index ppc64::fixnumshift))
+                        frame-ptr)))))))))
+
+
+
+
+
Index: /branches/new-random/level-1/runtime.lisp
===================================================================
--- /branches/new-random/level-1/runtime.lisp	(revision 13309)
+++ /branches/new-random/level-1/runtime.lisp	(revision 13309)
@@ -0,0 +1,159 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Load .pfsl files, create a "runtime" (compiler- & development-tools-less)
+;;; image.
+
+(in-package "CCL")
+
+(%fasload "./l1-pfsls/l1-cl-package.pfsl")
+(%fasload "./l1-pfsls/l1-utils.pfsl")
+(%fasload "./l1-pfsls/l1-init.pfsl")
+(%fasload "./l1-pfsls/l1-symhash.pfsl")
+(%fasload "./l1-pfsls/l1-numbers.pfsl")
+(%fasload "./l1-pfsls/l1-aprims.pfsl")
+(%fasload "./l1-pfsls/ppc-callback-support.pfsl")
+(%fasload "./l1-pfsls/l1-sort.pfsl")
+(%fasload "./l1-pfsls/l1-dcode.pfsl")
+(%fasload "./l1-pfsls/l1-clos.pfsl")
+(%fasload "./binppc/defstruct.pfsl")
+(%fasload "./l1-pfsls/l1-streams.pfsl")
+(%fasload "./l1-pfsls/linux-files.pfsl")
+(%fasload "./binppc/lists.pfsl")
+(%fasload "./binppc/sequences.pfsl")
+(%fasload "./binppc/chars.pfsl")
+(%fasload "./l1-pfsls/l1-files.pfsl")
+(provide "SEQUENCES")
+(provide "DEFSTRUCT")
+(provide "CHARS")
+(provide "LISTS")
+(%fasload "./l1-pfsls/ppc-stack-groups.pfsl")
+(%fasload "./l1-pfsls/l1-stack-groups.pfsl")
+(%fasload "./l1-pfsls/l1-processes.pfsl")
+(%fasload "./l1-pfsls/l1-io.pfsl")
+(%fasload "./l1-pfsls/l1-reader.pfsl")
+(%fasload "./l1-pfsls/l1-readloop.pfsl")
+(%fasload "./l1-pfsls/l1-readloop-lds.pfsl")
+(%fasload "./l1-pfsls/l1-error-system.pfsl")
+
+(%fasload "./l1-pfsls/l1-events.pfsl")
+(%fasload "./l1-pfsls/ppc-trap-support.pfsl")
+(%fasload "./l1-pfsls/l1-format.pfsl")
+(%fasload "./l1-pfsls/l1-sysio.pfsl")
+(%fasload "./l1-pfsls/l1-pathnames.pfsl")
+(%fasload "./l1-pfsls/version.pfsl")
+(%fasload "./l1-pfsls/l1-boot-lds.pfsl")
+
+(%fasload "./l1-pfsls/l1-boot-1.pfsl")
+(catch :toplevel
+    (%fasload "./l1-pfsls/l1-typesys.pfsl")
+    (%fasload "./l1-pfsls/sysutils.pfsl")
+    (%fasload "./l1-pfsls/l1-error-signal.pfsl")
+    (setq *LEVEL-1-LOADED* t))
+
+(def-ccl-pointers fd-streams ()
+  (let* ((in (make-fd-stream 0 :direction :input))
+         (out (make-fd-stream 1 :direction :output))
+         (error out))
+    (setq *terminal-io* (make-echoing-two-way-stream in out))
+    (setq *debug-io* (make-echoing-two-way-stream in error)
+          *query-io* *debug-io*)
+    (setq *standard-input* in
+          *standard-output* out
+          *error-output* error
+          *trace-output* error)))
+
+(catch :toplevel
+    (flet ((load-provide (module path)
+             (let* ((*package* *package*))
+               (%fasload path)
+               (provide module))))
+      (load-provide "SORT" "./binppc/sort.pfsl")
+      (load-provide "NUMBERS" "./binppc/numbers.pfsl")
+      (load-provide "HASH" "./binppc/hash.pfsl")
+;;;   (load-provide "DLL-NODE" "./binppc/dll-node.pfsl")
+;;;   (load-provide "PPC32-ARCH" "./binppc/ppc32-arch.pfsl")
+;;;   (load-provide "VREG" "./binppc/vreg.pfsl")
+;;;   (load-provide "PPC-ASM" "./binppc/ppc-asm.pfsl")
+;;;   (load-provide "VINSN" "./binppc/vinsn.pfsl")
+;;;   (load-provide "PPC-VINSNS" "./binppc/ppc-vinsns.pfsl")
+;;;   (load-provide "PPC-REG" "./binppc/ppc-reg.pfsl")
+;;;   (load-provide "SUBPRIMS" "./binppc/subprims.pfsl")
+;;;   (load-provide "PPC-LAP" "./binppc/ppc-lap.pfsl")
+;;;   (provide "PPC2")                  ; Lie, load the module manually
+;;;   (load-provide "NX" "./l1-pfsls/nx.pfsl")
+;;;   (%fasload "./binppc/ppc2.pfsl")
+      (load-provide "LEVEL-2" "./binppc/level-2.pfsl")
+;;;     (load-provide "SETF" "./binppc/setf.pfsl")
+      (load-provide "SETF-RUNTIME" "./binppc/setf-runtime.pfsl")
+      (load-provide "FORMAT" "./binppc/format.pfsl")
+      (load-provide "STREAMS" "./binppc/streams.pfsl")
+;;;   (load-provide "OPTIMIZERS" "./binppc/optimizers.pfsl")
+;;;   (load-provide "PPC-OPTIMIZERS" "./binppc/ppc-optimizers.pfsl")
+;;;   (load-provide "LISPEQU" "./library/lispequ.pfsl")          ; Shouldn't need this at load time ...
+;;;   (load-provide "DEFSTRUCT-MACROS" "./binppc/defstruct-macros.pfsl")        ;  ... but this file thinks it does.
+;;;   (load-provide "DEFSTRUCT-LDS" "./binppc/defstruct-lds.pfsl")
+;;;   (load-provide "NFCOMP" "./binppc/nfcomp.pfsl")
+;;;   (load-provide "BACKQUOTE" "./binppc/backquote.pfsl")
+      (load-provide "BACKTRACE-LDS" "./binppc/backtrace-lds.pfsl")
+      (load-provide "BACKTRACE" "./binppc/backtrace.pfsl")
+      (load-provide "READ" "./binppc/read.pfsl")
+      (load-provide "ARRAYS-FRY" "./binppc/arrays-fry.pfsl")
+;;;   (load-provide "APROPOS" "./binppc/apropos.pfsl")
+;;;   (load-provide "PPC-DISASSEMBLE" "./binppc/ppc-disassemble.pfsl")
+;;;   (load-provide "PPC-LAPMACROS" "./binppc/ppc-lapmacros.pfsl")
+;;;   (load-provide "MACTYPES" "./binppc/mactypes.pfsl")
+;;;   (load-provide "DEFRECORD" "./binppc/defrecord.pfsl")
+;;;   (load-provide "LINUX-RECORDS" "./library/linux-records.pfsl")
+      (load-provide "CASE-ERROR" "./binppc/case-error.pfsl")
+;;;   (load-provide "ENCAPSULATE" "./binppc/encapsulate.pfsl")
+      (load-provide "METHOD-COMBINATION" "./binppc/method-combination.pfsl")
+      (load-provide "MISC" "./binppc/misc.pfsl")
+      (load-provide "PPRINT" "./binppc/pprint.pfsl")
+      (load-provide "DUMPLISP" "./binppc/dumplisp.pfsl")
+      (load-provide "PATHNAMES" "./binppc/pathnames.pfsl")
+      (load-provide "TIME" "./binppc/time.pfsl")
+;;;   (load-provide "COMPILE-CCL" "./binppc/compile-ccl.pfsl")
+;;;   (load-provide "SOURCE-FILES" "./binppc/source-files.pfsl")
+      (load-provide "CCL-EXPORT-SYMS" "./binppc/ccl-export-syms.pfsl")
+      )
+    (setq *%fasload-verbose* nil)
+    )
+(catch :toplevel
+    (or (find-package "COMMON-LISP-USER")
+        (make-package "COMMON-LISP-USER" :use '("COMMON-LISP" "CCL") :NICKNAMES '("CL-USER")))
+)
+
+(defvar *LISTENER-PROCESS-STACKSEG-SIZE* (* 4 16384))
+
+(setf (interrupt-level) 0)
+
+(setq *warn-if-redefine* t)
+
+(setq *level-1-loaded* t)
+
+(set-periodic-task-interval 1)
+
+(do-all-symbols (s)
+  (setf (symbol-plist s) nil))
+
+(progn (%set-toplevel #'toplevel-loop) (save-application "RUNTIME"))
+
+
+
+
+
Index: /branches/new-random/level-1/sysutils.lisp
===================================================================
--- /branches/new-random/level-1/sysutils.lisp	(revision 13309)
+++ /branches/new-random/level-1/sysutils.lisp	(revision 13309)
@@ -0,0 +1,893 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;; sysutils.lisp - things which have outgrown l1-utils
+
+(in-package "CCL")
+
+(eval-when (:execute :compile-toplevel)
+  (require 'level-2)
+  (require 'optimizers)
+  (require 'backquote)
+  (require 'defstruct-macros)
+  )
+
+;;; things might be clearer if this stuff were in l1-typesys?
+;;; Translation from type keywords to specific predicates.
+(eval-when (:execute :compile-toplevel)
+
+(defconstant type-pred-pairs
+  '((array . arrayp)
+    (atom . atom)
+    (base-string . base-string-p)
+    (bignum . bignump)
+    (bit . bitp)
+    (bit-vector . bit-vector-p)
+    (character . characterp)
+    (compiled-function . compiled-function-p)
+    (complex . complexp)
+    (cons . consp)
+    (double-float . double-float-p)
+    (fixnum . fixnump) ;not cl
+    (float . floatp)
+    (function . functionp)
+    (hash-table . hash-table-p)
+    (integer . integerp)
+    (real . realp)
+    (keyword . keywordp)
+    (list . listp)
+    (long-float . double-float-p)
+    (nil . false)
+    (null . null)
+    (number . numberp)
+    (package . packagep)
+    (pathname . pathnamep)
+    (logical-pathname . logical-pathname-p)
+    (random-state . random-state-p)
+    (ratio . ratiop)
+    (rational . rationalp)
+    (readtable . readtablep)
+    (sequence . sequencep)
+    (short-float . short-float-p)
+    (signed-byte . integerp)
+    (simple-array . simple-array-p)
+    (simple-base-string . simple-base-string-p)
+    (simple-bit-vector . simple-bit-vector-p)
+    (simple-string . simple-string-p)
+    (simple-vector . simple-vector-p)
+    (single-float . short-float-p)
+    (stream . streamp)
+    (string . stringp)
+    (base-char . base-char-p)
+    (extended-char . extended-char-p)
+    (structure-object . structurep)
+    (symbol . symbolp)
+    (t . true)
+    (unsigned-byte . unsigned-byte-p)
+    (vector . vectorp)
+    ))
+
+(defmacro init-type-predicates ()
+  `(dolist (pair ',type-pred-pairs)
+     (setf (type-predicate (car pair)) (cdr pair))
+     (let ((ctype (info-type-builtin (car pair))))       
+       (if (typep ctype 'numeric-ctype)
+         (setf (numeric-ctype-predicate ctype) (cdr pair))))))
+
+)
+
+(init-type-predicates)
+
+(defun unsigned-byte-8-p (n)
+  (and (fixnump n)
+       (locally (declare (fixnum n))
+         (and 
+          (>= n 0)
+          (< n #x100)))))
+
+(defun signed-byte-8-p (n)
+  (and (fixnump n)
+       (locally (declare (fixnum n))
+         (and 
+          (>= n -128)
+          (<= n 127)))))
+
+(defun unsigned-byte-16-p (n)
+  (and (fixnump n)
+       (locally (declare (fixnum n))
+         (and 
+          (>= n 0)
+          (< n #x10000)))))
+
+(defun signed-byte-16-p (n)
+  (and (fixnump n)
+       (locally (declare (fixnum n))
+         (and 
+          (>= n -32768)
+          (<= n 32767)))))
+
+(defun unsigned-byte-32-p (n)
+  (and (integerp n)
+       (>= n 0)
+       (<= n #xffffffff)))
+
+(defun signed-byte-32-p (n)
+  (and (integerp n)
+       (>= n  -2147483648)
+       (<= n 2147483647)))
+
+(eval-when (:load-toplevel :execute)
+  (let ((more-pairs
+         '(((unsigned-byte 8) . unsigned-byte-8-p)
+           ((signed-byte 8) . signed-byte-8-p)
+           ((unsigned-byte 16) . unsigned-byte-16-p)
+           ((signed-byte 16) . signed-byte-16-p)
+           ((unsigned-byte 32) . unsigned-byte-32-p)
+           ((signed-byte 32) . signed-byte-32-p))))         
+    (dolist (pair more-pairs)
+      (let ((ctype (info-type-builtin (car pair))))       
+        (if (typep ctype 'numeric-ctype) (setf (numeric-ctype-predicate ctype) (cdr pair))))))
+  )
+
+
+(defun specifier-type-known (type)  
+  (let ((ctype (specifier-type type)))
+    (if (typep ctype 'unknown-ctype)
+      (error "Unknown type specifier ~s." type)
+      (if (and (typep ctype 'numeric-ctype) ; complexp??
+               (eq 'integer (numeric-ctype-class ctype))
+               (not (numeric-ctype-predicate ctype)))
+        (setf (numeric-ctype-predicate ctype)(make-numeric-ctype-predicate ctype))))
+    ctype))
+
+
+(defun find-builtin-cell (type  &optional (create t))
+  (let ((cell (gethash type %builtin-type-cells%)))
+    (or cell
+        (when create
+          (setf (gethash type %builtin-type-cells%)
+                (cons type (or (info-type-builtin type)(specifier-type-known type))))))))
+
+
+; for now only called for builtin types or car = unsigned-byte, signed-byte, mod or integer
+
+(defun builtin-typep (form cell)
+  (unless (listp cell)
+    (setq cell (require-type cell 'list)))
+  (locally (declare (type list cell))
+    (let ((ctype (cdr cell))
+          (name (car cell)))
+      (when (not ctype)
+        (setq ctype (or (info-type-builtin name)(specifier-type-known name)))
+        (when ctype (setf (gethash (car cell) %builtin-type-cells%) cell))
+        (rplacd cell ctype))
+      (if ctype 
+        (if (and (typep ctype 'numeric-ctype)
+                 (numeric-ctype-predicate ctype))
+          ; doing this inline is a winner - at least if true
+          (funcall (numeric-ctype-predicate ctype) form)
+          (%%typep form ctype))
+        (typep form name)))))
+
+#|
+(defvar %find-classes% (make-hash-table :test 'eq))
+
+(defun find-class-cell (name create?)
+  (let ((cell (gethash name %find-classes%)))
+    (or cell
+        (and create?
+             (setf (gethash name %find-classes%) (cons name nil))))))
+|#
+
+;(setq *type-system-initialized* t)
+
+
+;; Type-of, typep, and a bunch of other predicates.
+
+;;; Data type predicates.
+
+;;; things might be clearer if this stuff were in l1-typesys?
+;;; Translation from type keywords to specific predicates.
+
+
+
+
+;necessary since standard-char-p, by definition, errors if not passed a char.
+(setf (type-predicate 'standard-char)
+      #'(lambda (form) (and (characterp form) (standard-char-p form))))
+
+(defun type-of (form)
+  "Return the type of OBJECT."
+  (case form
+    ((t) 'boolean)
+    ((0 1) 'bit)
+    (t
+     (typecase form
+       (standard-char 'standard-char)
+       (keyword 'keyword)
+       ;; Partition integers so that the negative cases
+       ;; are SIGNED-BYTE and the positive are UNSIGNED-BYTE
+       (fixnum
+	(if (< (the fixnum form) 0)
+	  'fixnum
+	  '(integer 0 #.target::target-most-positive-fixnum)))
+       (bignum
+	(if (< form 0)
+	  'bignum
+	  '(integer  #.(1+ target::target-most-positive-fixnum))))
+       ((or array complex) (type-specifier (ctype-of form)))
+       (single-float 'single-float)
+       (double-float 'double-float)
+       (t
+	(if (eql (typecode form) target::subtag-istruct)
+	  (istruct-type-name form)
+	  (let* ((class (class-of form)))
+            (or (%class-proper-name class)
+                class))))))))
+
+;;; Create the list-style description of an array.
+
+;made more specific by fry. slisp used  (mod 2) , etc.
+;Oh.
+; As much fun as this has been, I think it'd be really neat if
+; it returned a type specifier.
+
+(defun describe-array (array)
+  (if (arrayp array)
+    (type-specifier
+     (specifier-type
+      `(,(if (simple-array-p array) 'simple-array 'array) 
+        ,(array-element-type array) 
+        ,(array-dimensions array))))
+    (report-bad-arg array 'array)))
+  
+
+;;;; TYPEP and auxiliary functions.
+
+
+
+(defun type-specifier-p (form &aux sym)
+  (cond ((symbolp form)
+         (or (type-predicate form)
+             (structure-class-p form)
+             (%deftype-expander form)
+             (find-class form nil)
+             ))
+        ((consp form)
+         (setq sym (%car form))
+         (or (type-specifier-p sym)
+             (memq sym '(member satisfies mod))
+             (and (memq sym '(and or not))
+                  (dolist (spec (%cdr form) t)
+                    (unless (type-specifier-p spec) (return nil))))))
+        (t (typep form 'class))))
+
+(defun built-in-type-p (type)
+  (if (symbolp type)
+    (or (type-predicate type)
+        (let ((class (find-class type nil)))
+          (and class (typep class 'built-in-class))))
+    (and (consp type)
+         (or (and (memq (%car type) '(and or not))
+                  (every #'built-in-type-p (%cdr type)))
+             (memq (%car type) '(array simple-array vector simple-vector
+                                 string simple-string bit-vector simple-bit-vector 
+                                 complex integer mod signed-byte unsigned-byte
+                                 rational float short-float single-float
+                                 double-float long-float real member))))))
+
+(defun typep (object type &optional env)
+  "Is OBJECT of type TYPE?"
+  (let* ((pred (if (symbolp type) (type-predicate type))))
+    (if pred
+      (funcall pred object)
+      (values (%typep object (if env (specifier-type type env) type))))))
+
+
+
+;;; This is like check-type, except it returns the value rather than setf'ing
+;;; anything, and so can be done entirely out-of-line.
+(defun require-type (arg type)
+  (multiple-value-bind (win sure)
+      (ctypep  arg (specifier-type type))
+    (if (or win (not sure))
+      arg
+      (%kernel-restart $xwrongtype arg type))))
+
+;;; Might want to use an inverted mapping instead of (satisfies ccl::obscurely-named)
+(defun %require-type (arg predsym)
+  (if (funcall predsym arg)
+    arg
+    (%kernel-restart $xwrongtype arg (type-for-predicate predsym))))
+
+(defun %require-type-builtin (arg type-cell)  
+  (if (builtin-typep arg type-cell)
+    arg
+    (%kernel-restart $xwrongtype arg (car type-cell))))
+
+
+
+;;; In lieu of an inverted mapping, at least try to find cases involving
+;;; builtin numeric types and predicates associated with them.
+(defun type-for-predicate (pred)
+  (or (block find
+        (maphash #'(lambda (type ctype) (when (and (typep ctype 'numeric-ctype)
+                                                   (eq (numeric-ctype-predicate ctype)
+                                                       pred))
+                                          (return-from find type)))
+                 *builtin-type-info*))
+      `(satisfies ,pred)))
+
+
+
+
+; Subtypep.
+
+(defun subtypep (type1 type2 &optional env)
+  "Return two values indicating the relationship between type1 and type2.
+  If values are T and T, type1 definitely is a subtype of type2.
+  If values are NIL and T, type1 definitely is not a subtype of type2.
+  If values are NIL and NIL, it couldn't be determined."
+  (csubtypep (specifier-type type1 env) (specifier-type type2 env)))
+
+(defun types-disjoint-p (type1 type2 &optional env)
+  ;; Return true if types are guaranteed to be disjoint, nil if not disjoint or unknown.
+  (let ((ctype1 (if (typep type1 'ctype) type1 (specifier-type type1 env)))
+	(ctype2 (if (typep type2 'ctype) type2 (specifier-type type2 env))))
+    (eq *empty-type* (type-intersection ctype1 ctype2))))
+
+
+
+(defun preload-all-functions ()
+  nil)
+
+
+ ; used by arglist
+(defun temp-cons (a b)
+  (cons a b))
+
+
+
+
+(defun copy-into-float (src dest)
+  (%copy-double-float src dest))
+
+(queue-fixup
+ (defun fmakunbound (name)
+   "Make NAME have no global function definition."
+   (let* ((fname (validate-function-name name)))
+     (remhash fname %structure-refs%)
+     (%unfhave fname))
+   name))
+
+(defun frozen-definition-p (name)
+  (if (symbolp name)
+    (%ilogbitp $sym_fbit_frozen (%symbol-bits name))))
+
+(defun redefine-kernel-function (name)
+  (when (and *warn-if-redefine-kernel*
+             (frozen-definition-p name)
+             (or (lfunp (fboundp name))
+                 (and (not (consp name)) (macro-function name)))
+             (or (and (consp name) (neq (car name) 'setf))
+                 (let ((pkg (symbol-package (if (consp name) (cadr name) name))))
+                   (or (eq *common-lisp-package* pkg) (eq *ccl-package* pkg)))))
+    (cerror "Replace the definition of ~S."
+            "The function ~S is predefined in Clozure CL." name)
+    (unless (consp name)
+      (proclaim-inline nil name))))
+
+(defun fset (name function)
+  (setq function (require-type function 'function))
+  (when (symbolp name)
+    (when (special-operator-p name)
+      (error "Can not redefine a special-form: ~S ." name))
+    (when (macro-function name)
+      (cerror "Redefine the macro ~S as a function"
+              "The macro ~S is being redefined as a function." name)))
+; This lets us redefine %FHAVE.  Big fun.
+  (let ((fhave #'%fhave))
+    (redefine-kernel-function name)
+    (fmakunbound name)
+    (funcall fhave name function)
+    function))
+
+(defsetf symbol-function fset)
+(defsetf fdefinition fset)
+
+(defun (setf macro-function) (macro-fun name &optional env)
+  (declare (ignore env))
+  (unless (typep macro-fun 'function)
+    (report-bad-arg macro-fun 'function))
+  (if (special-operator-p name)
+    (error "Can not redefine a special-form: ~S ." name))
+  (when (and (fboundp name) (not (macro-function name)))
+    (warn "The function ~S is being redefined as a macro." name))
+  (redefine-kernel-function name)
+  (fmakunbound name)
+  (%macro-have name macro-fun)
+  macro-fun)
+
+(defun set-macro-function (name def)
+  (setf (macro-function name) def))
+
+
+
+
+
+;;; Arrays and vectors, including make-array.
+
+
+
+
+
+
+
+(defun char (string index)
+  "Given a string and a non-negative integer index less than the length of
+  the string, returns the character object representing the character at
+  that position in the string."
+  (if (typep string 'simple-string)
+    (schar (the simple-string string) index)
+    (if (stringp string)
+      (multiple-value-bind (data offset) (array-data-and-offset string)
+        (schar (the simple-string data) (+ index offset)))
+      (report-bad-arg string 'string))))
+
+(defun set-char (string index new-el)
+  (if (typep string 'simple-string)
+    (setf (schar string index) new-el)
+    (if (stringp string)
+      (multiple-value-bind (data offset) (array-data-and-offset string)
+        (setf (schar (the simple-string data) (+ index offset)) new-el))
+      (report-bad-arg string 'string))))
+
+(defun equalp (x y)
+  "Just like EQUAL, but more liberal in several respects.
+  Numbers may be of different types, as long as the values are identical
+  after coercion.  Characters may differ in alphabetic case.  Vectors and
+  arrays must have identical dimensions and EQUALP elements, but may differ
+  in their type restriction.
+  If one of x or y is a pathname and one is a string with the name of the
+  pathname then this will return T."
+  (cond ((eql x y) t)
+        ((characterp x) (and (characterp y) (eq (char-upcase x) (char-upcase y))))
+        ((numberp x) (and (numberp y) (= x y)))
+        ((consp x)
+         (and (consp y)
+              (equalp (car x) (car y))
+              (equalp (cdr x) (cdr y))))        
+        ((pathnamep x) (equal x y))
+        ((vectorp x)
+         (and (vectorp y)
+              (let ((length (length x)))
+                (when (eq length (length y))
+                  (dotimes (i length t)
+                    (declare (fixnum i))
+                    (let ((x-el (aref x i))
+                          (y-el (aref y i)))
+                      (unless (or (eq x-el y-el) (equalp x-el y-el))
+                        (return nil))))))))
+        ((arrayp x)
+         (and (arrayp y)
+              (let ((rank (array-rank x)) x-el y-el)
+                (and (eq (array-rank y) rank)
+                     (if (%izerop rank) (equalp (aref x) (aref y))
+                         (and
+                          (dotimes (i rank t)
+                            (declare (fixnum i))
+                            (unless (eq (array-dimension x i)
+                                        (array-dimension y i))
+                              (return nil)))
+                          (multiple-value-bind (x0 i) (array-data-and-offset x)
+                            (multiple-value-bind (y0 j) (array-data-and-offset y)
+                              (dotimes (count (array-total-size x) t)
+                                (declare (fixnum count))
+                                (setq x-el (uvref x0 i) y-el (uvref y0 j))
+                                (unless (or (eq x-el y-el) (equalp x-el y-el))
+                                  (return nil))
+                                (setq i (%i+ i 1) j (%i+ j 1)))))))))))
+        ((and (structurep x) (structurep y))
+	 (let ((size (uvsize x)))
+	   (and (eq size (uvsize y))
+	        (dotimes (i size t)
+                  (declare (fixnum i))
+		  (unless (equalp (uvref x i) (uvref y i))
+                    (return nil))))))
+        ((and (hash-table-p x) (hash-table-p y))
+         (%hash-table-equalp x y))
+        (t nil)))
+
+
+; The compiler (or some transforms) might want to do something more interesting
+; with these, but they have to exist as functions anyhow.
+
+
+
+(defun complement (function)
+  "Return a new function that returns T whenever FUNCTION returns NIL and
+   NIL whenever FUNCTION returns non-NIL."
+  (let ((f (coerce-to-function function))) ; keep poor compiler from consing value cell
+  #'(lambda (&rest args)
+      (declare (dynamic-extent args)) ; not tail-recursive anyway
+      (not (apply f args)))))
+
+; Special variables are evil, but I can't think of a better way to do this.
+
+(defparameter *outstanding-deferred-warnings* nil)
+
+(defun call-with-compilation-unit (thunk &key override)
+  (let* ((*outstanding-deferred-warnings* (%defer-warnings override)))
+    (multiple-value-prog1 (funcall thunk)
+      (report-deferred-warnings))))
+
+(defun %defer-warnings (override &aux (parent *outstanding-deferred-warnings*))
+  (when parent
+    (ensure-merged-deferred-warnings parent))
+  (%istruct 'deferred-warnings
+            (unless override parent)
+            nil
+            (make-hash-table :test #'eq)
+            nil))
+
+(defun ensure-merged-deferred-warnings (parent &aux (last (deferred-warnings.last-file parent)))
+  (when last
+    (setf (deferred-warnings.last-file parent) nil)
+    (let* ((child (car last)) ;; last = (deferred-warnings . file)
+           (warnings (deferred-warnings.warnings child))
+           (defs (deferred-warnings.defs child))
+           (parent-defs (deferred-warnings.defs parent))
+           (parent-warnings (deferred-warnings.warnings parent)))
+      (maphash (lambda (key val) (setf (gethash key parent-defs) val)) defs)
+      (setf (deferred-warnings.warnings parent) (append warnings parent-warnings))))
+  parent)
+
+
+;; Should be a generic function but compiler-warning class not defined yet.
+(defun verify-deferred-warning (w)
+  (etypecase w
+    (undefined-type-reference (verify-deferred-type-warning w))
+    (undefined-function-reference (verify-deferred-function-warning w))
+    (undefined-keyword-reference (verify-deferred-keyword-warning w))
+    (compiler-warning nil)))
+
+(defun verify-deferred-type-warning (w)
+  (let* ((args (compiler-warning-args w))
+	 (typespec (car args))
+	 (defs (deferred-warnings.defs *outstanding-deferred-warnings*)))
+    (handler-bind ((parse-unknown-type
+		    (lambda (c)
+		      (let* ((type (parse-unknown-type-specifier c))
+			     (spec (if (consp type) (car type) type))
+			     (cell (and (symbolp spec) (gethash spec defs))))
+			(unless (and cell (def-info.deftype (cdr cell)))
+			  (when (and args (neq type typespec))
+			    (setf (car args) type))
+			  (return-from verify-deferred-type-warning w))
+			;; Else got defined.  TODO: Should check syntax, but don't have enuff info.
+			;; TODO: should note if got defined as a deftype (rather than class or struct) and
+			;; warn about forward reference, akin to the macro warning?  Might be missing out on
+			;; some intended optimizations.
+			)))
+		   (program-error ;; got defined, but turns out it's being used wrong
+		    (lambda (c)
+		      (let ((w2 (make-condition 'invalid-type-warning
+				  :function-name (compiler-warning-function-name w)
+				  :source-note (compiler-warning-source-note w)
+				  :warning-type :invalid-type
+				  :args (list typespec c))))
+			(return-from verify-deferred-type-warning w2)))))
+      (values-specifier-type typespec)
+      nil)))
+
+
+(defun deferred-function-def (name)
+  (let* ((defs (deferred-warnings.defs *outstanding-deferred-warnings*))
+	 (def (or (let ((cell (gethash name defs)))
+                    (and cell (def-info.function-p (cdr cell)) cell))
+		 (let* ((global (fboundp name)))
+		   (and (typep global 'function) global)))))
+    def))
+
+(defun check-deferred-call-args (w def wargs)
+  (destructuring-bind (arglist spread-p) wargs
+    (multiple-value-bind (deftype reason) (nx1-check-call-args def arglist spread-p)
+      (when (and (eq deftype :deferred-mismatch)
+                 (eq (car reason) :unknown-gf-keywords)
+                 (consp def)
+                 (not (logbitp $lfbits-gfn-bit (def-info.lfbits (cdr def)))))
+        ;; If didn't have a defgeneric, check against global defn
+        (let* ((global-def (fboundp (car def)))
+               (bad-keys (cadr reason)))
+          (when (typep global-def 'generic-function)
+            (setq bad-keys
+                  (multiple-value-bind (bits keyvect) (innermost-lfun-bits-keyvect global-def)
+                    (when (and bits
+                               (logbitp  $lfbits-keys-bit bits)
+                               (not (logbitp $lfbits-aok-bit bits)))
+                      (loop for key in bad-keys
+                        unless (or (find key keyvect)
+                                   (nx1-valid-gf-keyword-p global-def key))
+                        collect key)))))
+          (if bad-keys
+            (setq reason (list* :unknown-gf-keys bad-keys (cddr reason)))
+            (setq deftype nil))))
+      (when deftype
+        (when (eq deftype :deferred-mismatch)
+          (setq deftype (if (consp def) :environment-mismatch :global-mismatch)))
+        (make-condition
+         'invalid-arguments
+         :function-name (compiler-warning-function-name w)
+         :source-note (compiler-warning-source-note w)
+         :warning-type deftype
+         :args (list (car (compiler-warning-args w)) reason arglist spread-p))))))
+
+(defun verify-deferred-function-warning (w)
+  (let* ((args (compiler-warning-args w))
+	 (wfname (car args))
+	 (def (deferred-function-def wfname)))
+    (cond ((null def) w)
+	  ((or (typep def 'function)
+	       (and (consp def)
+		    (def-info.lfbits (cdr def))))
+	   ;; Check args in call to forward-referenced function.
+	   (when (cdr args)
+             (check-deferred-call-args w def (cdr args))))
+	  ((def-info.macro-p (cdr def))
+	   (let* ((w2 (make-condition
+		       'macro-used-before-definition
+		       :function-name (compiler-warning-function-name w)
+		       :source-note (compiler-warning-source-note w)
+		       :warning-type :macro-used-before-definition
+		       :args (list (car args)))))
+	     w2)))))
+
+(defun verify-deferred-keyword-warning (w)
+  (let* ((args (compiler-warning-args w))
+         (wfname (car args))
+         (def (deferred-function-def wfname)))
+    (when def
+      (check-deferred-call-args w def (cddr args)))))
+
+
+(defun report-deferred-warnings (&optional (file nil))
+  (let* ((current (ensure-merged-deferred-warnings *outstanding-deferred-warnings*))
+         (parent (deferred-warnings.parent current))
+         (warnings (deferred-warnings.warnings current))
+         (any nil)
+         (harsh nil))
+    (if parent
+      (progn
+        (setf (deferred-warnings.last-file parent) (cons current file))
+        (unless file ;; don't defer merge for non-file units.
+          (ensure-merged-deferred-warnings parent))
+        (setq parent t))
+      (let* ((file nil)
+             (init t))
+	(dolist (w warnings)
+	  (when (setq w (verify-deferred-warning w))
+	    (multiple-value-setq (harsh any file) (signal-compiler-warning w init file harsh any))
+	    (setq init nil)))))
+    (values any harsh parent)))
+
+(defun print-nested-name (name-list stream)
+  (if (null name-list)
+    (princ "a toplevel form" stream)
+    (progn
+      (if (car name-list)
+        (prin1 (%car name-list) stream)
+        (princ "an anonymous lambda form" stream))
+      (when (%cdr name-list)
+        (princ " inside " stream)
+        (print-nested-name (%cdr name-list) stream)))))
+
+(defparameter *suppress-compiler-warnings* nil)
+
+(defun signal-compiler-warning (w init-p last-w-file harsh-p any-p &optional eval-p)
+  (let ((muffled *suppress-compiler-warnings*)
+        (w-file (compiler-warning-file-name w))
+        (s *error-output*))
+    (unless muffled 
+      (restart-case (signal w)
+        (muffle-warning () (setq muffled t))))
+    (unless muffled
+      (setq any-p t)
+      (unless (typep w 'style-warning)
+        (unless (eq harsh-p :very)
+          (setq harsh-p t)
+          (when (and (typep w 'compiler-warning)
+                     (eq (compiler-warning-warning-type w) :program-error)
+                     (typep (car (compiler-warning-args w)) 'error))
+            (setq harsh-p :very))))
+      (when (or init-p (not (equalp w-file last-w-file)))
+        (format s "~&;~A warnings " (if (null eval-p) "Compiler" "Interpreter"))
+        (if w-file (format s "for ~S :" w-file) (princ ":" s)))
+      (let* ((indenting-stream (make-indenting-string-output-stream #\; 4)))
+        (format indenting-stream "~%~a" w)
+        (format s "~a" (get-output-stream-string indenting-stream))))
+    (values harsh-p any-p w-file)))
+
+;;;; Assorted mumble-P type predicates. 
+;;;; No functions have been in the kernel for the last year or so.
+;;;; (Just thought you'd like to know.)
+
+(defun sequencep (form)
+  "Not CL. SLISP Returns T if form is a sequence, NIL otherwise."
+   (or (listp form) (vectorp form)))
+
+;;; The following are not defined at user level, but are necessary for
+;;; internal use by TYPEP.
+
+(defun bitp (form)
+  "Not CL. SLISP"
+  (or (eq form 0) (eq form 1)))
+
+(defun unsigned-byte-p (form)
+  (and (integerp form) (not (< form 0))))
+
+;This is false for internal structures.
+;;; ---- look at defenv.structures, not defenv.structrefs
+
+(defun structure-class-p (form &optional env)
+  (and (symbolp form)
+       (let ((sd (or (and env
+                          (let ((defenv (definition-environment env)))
+                            (and defenv
+                                 (%cdr (assq form (defenv.structures defenv))))))
+                     (gethash form %defstructs%))))
+         (and sd
+              (null (sd-type sd))
+              sd))))
+
+
+
+
+
+(defun type-keyword-code (type-keyword &optional target)
+  (let* ((backend (if target (find-backend target) *target-backend*))
+         (alist (arch::target-uvector-subtags (backend-target-arch backend)))
+         (entry (assq type-keyword alist)))
+    (if entry
+      (let* ((code (cdr entry)))
+        (or code (error "Vector type ~s invalid," type-keyword)))
+      (error "Unknown type-keyword ~s. " type-keyword))))
+
+
+(defstruct id-map
+  (vector (make-array 1 :initial-element nil))
+  (free 0)
+  (lock (make-lock)))
+
+;;; Caller owns the lock on the id-map.
+(defun id-map-grow (id-map)
+  (without-interrupts
+   (let* ((old-vector (id-map-vector id-map))
+          (old-size (length old-vector))
+          (new-size (+ old-size old-size))
+          (new-vector (make-array new-size)))
+     (declare (fixnum old-size new-size))
+     (dotimes (i old-size)
+       (setf (svref new-vector i) (svref old-vector i)))
+     (let* ((limit (1- new-size)))
+       (declare (fixnum limit))
+       (do* ((i old-size (1+ i)))
+            ((= i limit) (setf (svref new-vector i) nil))
+         (declare (fixnum i))
+         (setf (svref new-vector i) (the fixnum (1+ i)))))
+     (setf (id-map-vector id-map) new-vector
+           (id-map-free id-map) old-size))))
+
+;;; Map an object to a small fixnum ID in id-map.
+;;; Object can't be NIL or a fixnum itself.
+(defun assign-id-map-id (id-map object)
+  (if (or (null object) (typep object 'fixnum))
+    (setq object (require-type object '(not (or null fixnum)))))
+  (with-lock-grabbed ((id-map-lock id-map))
+    (let* ((free (or (id-map-free id-map) (id-map-grow id-map)))
+           (vector (id-map-vector id-map))
+           (newfree (svref vector free)))
+      (setf (id-map-free id-map) newfree
+            (svref vector free) object)
+      free)))
+      
+;;; Referemce the object with id ID in ID-MAP.  Leave the object in
+;;; the map.
+(defun id-map-object (id-map id)
+  (let* ((object (with-lock-grabbed ((id-map-lock id-map))
+                   (svref (id-map-vector id-map) id))))
+    (if (or (null object) (typep object 'fixnum))
+      (error "invalid index ~d for ~s" id id-map)
+      object)))
+
+;;; Referemce the object with id ID in ID-MAP.  Remove the object from
+;;; the map.
+(defun id-map-free-object (id-map id)
+  (with-lock-grabbed ((id-map-lock id-map))
+    (let* ((vector (id-map-vector id-map))
+           (object (svref vector id)))
+      (if (or (null object) (typep object 'fixnum))
+        (error "invalid index ~d for ~s" id id-map))
+      (setf (svref vector id) (id-map-free id-map)
+            (id-map-free id-map) id)
+      object)))
+
+(defun id-map-modify-object (id-map id old-value new-value)
+  (with-lock-grabbed ((id-map-lock id-map))
+    (let* ((vector (id-map-vector id-map))
+           (object (svref vector id)))
+      (if (or (null object) (typep object 'fixnum))
+        (error "invalid index ~d for ~s" id id-map))
+      (if (eq object old-value)
+	(setf (svref vector id) new-value)))))
+
+
+    
+
+(setq *type-system-initialized* t)
+
+;;; Try to map from a CTYPE describing some array/stream
+;;; element-type to a target-specific typecode, catching
+;;; cases that CTYPE-SUBTYPE missed.
+
+(defun harder-ctype-subtype (ctype)
+  (cond ((csubtypep ctype (load-time-value (specifier-type 'bit)))
+         target::subtag-bit-vector)
+        ((csubtypep ctype (load-time-value (specifier-type '(unsigned-byte 8))))
+         target::subtag-u8-vector)
+        ((csubtypep ctype (load-time-value (specifier-type '(unsigned-byte 16))))
+         target::subtag-u16-vector)
+        ((csubtypep ctype (load-time-value (specifier-type '(unsigned-byte 32))))
+         target::subtag-u32-vector)
+        #+64-bit-target
+        ((csubtypep ctype (load-time-value (specifier-type '(unsigned-byte 64))))
+         target::subtag-u64-vector)
+        ((csubtypep ctype (load-time-value (specifier-type '(signed-byte 8))))
+         target::subtag-s8-vector)
+        ((csubtypep ctype (load-time-value (specifier-type '(signed-byte 16))))
+         target::subtag-s16-vector)
+        #+32-bit-target
+        ((csubtypep ctype (load-time-value (specifier-type `(integer ,target::target-most-negative-fixnum ,target::target-most-positive-fixnum))))
+         target::subtag-fixnum-vector)
+        ((csubtypep ctype (load-time-value (specifier-type '(signed-byte 32))))
+         target::subtag-s32-vector)
+        #+64-bit-target
+        ((csubtypep ctype (load-time-value (specifier-type `(integer ,target::target-most-negative-fixnum ,target::target-most-positive-fixnum))))
+         target::subtag-fixnum-vector)
+        #+64-bit-target
+        ((csubtypep ctype (load-time-value (specifier-type '(signed-byte 64))))
+         target::subtag-s64-vector)
+        (t target::subtag-simple-vector)))
+
+
+#+count-gf-calls
+(progn
+;;; Call-counting for generic functions.  We overload the
+;;; (previously unused
+(defmethod generic-function-call-count ((gf generic-function))
+  (gf.hash gf))
+
+
+(defun (setf generic-function-call-count) (count gf)
+  (setf (gf.hash gf) (require-type count 'fixnum)))
+
+(defun clear-all-generic-function-call-counts ()
+  (dolist (gf (population.data %all-gfs%))
+    (setf (gf.hash gf) 0)))
+);#+count-gf-calls
+
+
Index: /branches/new-random/level-1/version.lisp
===================================================================
--- /branches/new-random/level-1/version.lisp	(revision 13309)
+++ /branches/new-random/level-1/version.lisp	(revision 13309)
@@ -0,0 +1,41 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defparameter *openmcl-major-version* 1)
+(defparameter *openmcl-minor-version* 5)
+(defparameter *openmcl-revision* "dev")
+;;; May be set by xload-level-0
+(defvar *openmcl-svn-revision* nil)
+(defparameter *openmcl-dev-level* nil)
+
+(defparameter *openmcl-version* (format nil "~d.~d~@[-~a~]~@[-r~a~] ~@[+~s~] (~@[~A: ~]~~A)"
+					*openmcl-major-version*
+					*openmcl-minor-version*
+					(unless (null *openmcl-revision*)
+					  *openmcl-revision*)
+					(if (and (typep *openmcl-svn-revision* 'string)
+                                                 (> (length *openmcl-svn-revision*) 0))
+                                          *openmcl-svn-revision*)
+                                        *optional-features*
+                                        *openmcl-dev-level*))
+
+
+
+
+;;; end
Index: /branches/new-random/level-1/x86-callback-support.lisp
===================================================================
--- /branches/new-random/level-1/x86-callback-support.lisp	(revision 13309)
+++ /branches/new-random/level-1/x86-callback-support.lisp	(revision 13309)
@@ -0,0 +1,76 @@
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+
+#+x8664-target  
+(defun make-callback-trampoline (index &optional info)
+  (declare (ignore info))
+  (let* ((p (%allocate-callback-pointer 16))
+         (addr #.(subprim-name->offset '.SPcallback)))
+    (setf (%get-unsigned-byte p 0) #x41 ; movl $n,%r11d
+          (%get-unsigned-byte p 1) #xc7
+          (%get-unsigned-byte p 2) #xc3
+          (%get-unsigned-byte p 3) (ldb (byte 8 0) index)
+          (%get-unsigned-byte p 4) (ldb (byte 8 8) index)
+          (%get-unsigned-byte p 5) (ldb (byte 8 16) index)
+          (%get-unsigned-byte p 6) (ldb (byte 8 24) index)
+          (%get-unsigned-byte p 7) #xff  ; jmp *
+          (%get-unsigned-byte p 8) #x24
+          (%get-unsigned-byte p 9) #x25
+          (%get-unsigned-byte p 10) (ldb (byte 8 0) addr)
+          (%get-unsigned-byte p 11) (ldb (byte 8 8) addr)
+          (%get-unsigned-byte p 12) (ldb (byte 8 16) addr)
+          (%get-unsigned-byte p 13) (ldb (byte 8 24) addr))
+    p))
+          
+#+x8632-target          
+(defun make-callback-trampoline (index &optional info)
+  (let* ((p (%allocate-callback-pointer 12))
+         (addr #.(subprim-name->offset '.SPcallback)))
+    ;; If the optional info parameter is supplied, it will contain
+    ;; some stuff in bits 23 through 31.
+    ;;
+    ;; If bit 23 is set, that indicates that the caller will pass a
+    ;; "hidden" argument which is a pointer to appropriate storage for
+    ;; holding a returned structure.  .SPcallback will have to discard
+    ;; this extra argument upon return.
+    ;;
+    ;; The high 8 bits denote the number of words that .SPcallback
+    ;; will have to discard upon return (used for _stdcall on
+    ;; Windows).  Bit 23 won't be set in this case: we will have
+    ;; already added in the extra word to discard if that's necessary.
+    ;; 
+    ;; These bits are be packed into the value that .SPcallback
+    ;; receives in %eax.  Bits 0 through 22 are the callback index.
+    (if info
+      (setf (ldb (byte 23 0) info) index)
+      (setq info index))
+    (setf (%get-unsigned-byte p 0) #xb8 ; movl $n,%eax
+          (%get-unsigned-byte p 1) (ldb (byte 8 0) info)
+          (%get-unsigned-byte p 2) (ldb (byte 8 8) info)
+          (%get-unsigned-byte p 3) (ldb (byte 8 16) info)
+          (%get-unsigned-byte p 4) (ldb (byte 8 24) info)
+          (%get-unsigned-byte p 5) #xff  ; jmp *
+          (%get-unsigned-byte p 6) #x24
+          (%get-unsigned-byte p 7) #x25
+          (%get-unsigned-byte p 8) (ldb (byte 8 0) addr)
+          (%get-unsigned-byte p 9) (ldb (byte 8 8) addr)
+          (%get-unsigned-byte p 10) (ldb (byte 8 16) addr)
+          (%get-unsigned-byte p 11) (ldb (byte 8 24) addr))
+    p))
+  
Index: /branches/new-random/level-1/x86-error-signal.lisp
===================================================================
--- /branches/new-random/level-1/x86-error-signal.lisp	(revision 13309)
+++ /branches/new-random/level-1/x86-error-signal.lisp	(revision 13309)
@@ -0,0 +1,445 @@
+;;; x86-trap-support
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+#+x8664-target
+(defun xp-argument-count (xp)
+  (ldb (byte (- 16 x8664::fixnumshift) 0)
+                    (encoded-gpr-lisp xp x8664::nargs.q)))
+
+#+x8632-target
+(defun xp-argument-count (xp)
+  (encoded-gpr-lisp xp target::nargs))
+
+#+x8664-target
+(defun xp-argument-list (xp)
+  (let ((nargs (xp-argument-count xp))
+        (arg-x (encoded-gpr-lisp xp x8664::arg_x))
+        (arg-y (encoded-gpr-lisp xp x8664::arg_y))
+        (arg-z (encoded-gpr-lisp xp x8664::arg_z)))
+    (cond ((eql nargs 0) nil)
+          ((eql nargs 1) (list arg-z))
+          ((eql nargs 2) (list arg-y arg-z))
+          (t
+           (let ((args (list arg-x arg-y arg-z)))
+             (if (eql nargs 3)
+               args
+               (let ((sp (%inc-ptr (encoded-gpr-macptr xp x8664::rsp)
+                                   (+ x8664::node-size x8664::xcf.size))))
+                 (dotimes (i (- nargs 3))
+                   (push (%get-object sp (* i x8664::node-size)) args))
+                 args)))))))
+
+#+x8632-target
+(defun xp-argument-list (xp)
+  (let ((nargs (xp-argument-count xp))
+        (arg-y (encoded-gpr-lisp xp x8632::arg_y))
+        (arg-z (encoded-gpr-lisp xp x8632::arg_z)))
+    (cond ((eql nargs 0) nil)
+          ((eql nargs 1) (list arg-z))
+	  (t
+	   (let ((args (list arg-y arg-z)))
+	     (if (eql nargs 2)
+	       args
+	       (let ((sp (%inc-ptr (encoded-gpr-macptr xp x8632::ebp)
+				   (+ x8632::node-size x8632::xcf.size))))
+		 (dotimes (i (- nargs 2))
+		   (push (%get-object sp (* i x8632::node-size)) args))
+		 args)))))))
+
+;;; Making this be continuable is hard, because of the xcf on the
+;;; stack and the way that the kernel saves/restores rsp and rbp
+;;; before calling out.  If we get around those problems, then
+;;; we have to also deal with the fact that the return address
+;;; is on the stack.  Easiest to make the kernel deal with that,
+;;; and just set %fn to the function that returns the values
+;;; returned by the (newly defined) function and %arg_z to
+;;; that list of values.
+(defun handle-udf-call (xp frame-ptr)
+  (let* ((args (xp-argument-list xp))
+         (values (multiple-value-list
+                  (%kernel-restart-internal
+                   $xudfcall
+                   (list (maybe-setf-name (encoded-gpr-lisp xp target::fname)) args)
+                   frame-ptr)))
+         (f #'(lambda (values) (apply #'values values))))
+    (setf (encoded-gpr-lisp xp target::arg_z) values
+          (encoded-gpr-lisp xp target::fn) f)))
+
+#+x8664-target
+(defcallback %xerr-disp (:address xp :address xcf :int)
+  (with-error-reentry-detection
+      (let* ((frame-ptr (macptr->fixnum xcf))
+             (fn (%get-object xcf x8664::xcf.nominal-function))
+             (op0 (%get-xcf-byte xcf 0))
+             (op1 (%get-xcf-byte xcf 1))
+             (op2 (%get-xcf-byte xcf 2)))
+        (declare (type (unsigned-byte 8) op0 op1 op2))
+        (let* ((skip 2))
+          (if (and (= op0 #xcd)
+                   (>= op1 #x70))
+            (cond ((< op1 #x90)
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (setq *error-reentry-count* 0)
+                   (setf (encoded-gpr-lisp xp (ldb (byte 4 0) op1))
+                         (%slot-unbound-trap
+                          (encoded-gpr-lisp xp (ldb (byte 4 4) op2))
+                          (encoded-gpr-lisp xp (ldb (byte 4 0) op2))
+                          frame-ptr)))
+                  ((= op1 #x90)
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (setf (encoded-gpr-lisp xp (ldb (byte 4 4) op2))
+                         (%kernel-restart-internal $xvunbnd
+                                                   (list
+                                                    (encoded-gpr-lisp
+                                                     xp
+                                                     (ldb (byte 4 0) op2)))
+                                                   frame-ptr)))
+                  ((< op1 #xa0)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   ;; #x9x, x>0 - register X is a symbol.  It's unbound,
+                   ;; but we don't have enough info to offer USE-VALUE,
+                   ;; STORE-VALUE, or CONTINUE restarts.
+                   (%error (make-condition 'unbound-variable
+                                           :name
+                                           (encoded-gpr-lisp
+                                               xp
+                                               (ldb (byte 4 0) op1)))
+                           ()
+                           frame-ptr))
+                  ((< op1 #xb0)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%err-disp-internal $xfunbnd
+                                       (list (encoded-gpr-lisp
+                                              xp
+                                              (ldb (byte 4 0) op1)))
+                                       frame-ptr))
+                  ((< op1 #xc0)
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (%err-disp-internal 
+                    #.(car (rassoc 'type-error *kernel-simple-error-classes*))
+                    (list (encoded-gpr-lisp
+                           xp
+                           (ldb (byte 4 0) op1))
+                          (logandc2 op2 arch::error-type-error))
+                    frame-ptr))
+                  ((= op1 #xc0)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error 'too-few-arguments
+                           (list :nargs (xp-argument-count xp)
+                                 :fn fn)
+                           frame-ptr))
+                  ((= op1 #xc1)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error 'too-many-arguments
+                           (list :nargs (xp-argument-count xp)
+                                 :fn fn)
+                           frame-ptr))
+                  ((= op1 #xc2)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (let* ((flags (xp-flags-register xp))
+                          (nargs (xp-argument-count xp))
+                          (carry-bit (logbitp x86::x86-carry-flag-bit flags)))
+                     (if carry-bit
+                       (%error 'too-few-arguments
+                               (list :nargs nargs
+                                     :fn fn)
+                               frame-ptr)
+                       (%error 'too-many-arguments
+                               (list :nargs nargs
+                                     :fn fn)
+                               frame-ptr))))
+                  ((= op1 #xc3)         ;array rank
+                   (setq skip (%check-anchored-uuo xcf 3))                   
+                   (%err-disp-internal $XNDIMS
+                                       (list (encoded-gpr-lisp xp (ldb (byte 4 4) op2))
+                                             (encoded-gpr-lisp xp (ldb (byte 4 0) op2)))
+                                       frame-ptr))
+                  ((= op1 #xc6)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error (make-condition 'type-error
+                                           :datum (encoded-gpr-lisp xp x8664::temp0)
+                                           :expected-type '(or symbol function)
+                                           :format-control
+                                           "~S is not of type ~S, and can't be FUNCALLed or APPLYed")
+                           nil frame-ptr))
+                  ((= op1 #xc7)
+                   (handle-udf-call xp frame-ptr)
+                   (setq skip 0))
+                  ((or (= op1 #xc8) (= op1 #xcb))
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (%error (%rsc-string $xarroob)
+                           (list (encoded-gpr-lisp xp (ldb (byte 4 4) op2))
+                                 (encoded-gpr-lisp xp (ldb (byte 4 0) op2)))
+                           frame-ptr))
+                  ((= op1 #xc9)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%err-disp-internal $xnotfun
+                                       (list (encoded-gpr-lisp xp x8664::temp0))
+                                       frame-ptr))
+                  ;; #xca = uuo-error-debug-trap
+                  ((= op1 #xcc)
+                   ;; external entry point or foreign variable
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (let* ((eep-or-fv (encoded-gpr-lisp xp (ldb (byte 4 4) op2))))
+                     (etypecase eep-or-fv
+                       (external-entry-point
+                        (resolve-eep eep-or-fv)
+                        (setf (encoded-gpr-lisp xp (ldb (byte 4 0) op2))
+                              (eep.address eep-or-fv)))
+                       (foreign-variable
+                        (resolve-foreign-variable eep-or-fv)
+                        (setf (encoded-gpr-lisp xp (ldb (byte 4 0) op2))
+                              (fv.addr eep-or-fv))))))
+                  ((< op1 #xe0)
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (if (= op2 x8664::subtag-catch-frame)
+                     (%error (make-condition 'cant-throw-error
+                                             :tag (encoded-gpr-lisp
+                                                   xp
+                                                   (ldb (byte 4 0) op1)))
+                             nil frame-ptr)
+                     (let* ((typename
+                             (cond ((= op2 x8664::tag-fixnum) 'fixnum)
+                                   ((= op2 x8664::tag-single-float) 'single-float)
+                                   ((= op2 x8664::subtag-character) 'character)
+                                   ((= op2 x8664::fulltag-cons) 'cons)
+                                   ((= op2 x8664::tag-misc) 'uvector)
+                                   ((= op2 x8664::fulltag-symbol) 'symbol)
+                                   ((= op2 x8664::fulltag-function) 'function)
+                                   (t (let* ((class (logand op2 x8664::fulltagmask))
+                                             (high4 (ash op2 (- x8664::ntagbits))))
+                                        (cond ((= class x8664::fulltag-nodeheader-0)
+                                               (svref *nodeheader-0-types* high4))
+                                              ((= class x8664::fulltag-nodeheader-1)
+                                               (svref *nodeheader-1-types* high4))
+                                              ((= class x8664::fulltag-immheader-0)
+                                               (svref *immheader-0-types* high4))
+                                              ((= class x8664::fulltag-immheader-1)
+                                               (svref *immheader-1-types* high4))
+                                              ((= class x8664::fulltag-immheader-2)
+                                               (svref *immheader-2-types* high4))
+                                              (t (list 'bogus op2))))))))
+                       (%error (make-condition 'type-error
+                                               :datum (encoded-gpr-lisp
+                                                       xp
+                                                       (ldb (byte 4 0) op1))
+                                               :expected-type typename)
+                               nil
+                               frame-ptr))))
+                  ((< op1 #xf0)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error (make-condition 'type-error
+                                           :datum (encoded-gpr-lisp
+                                                   xp
+                                                   (ldb (byte 4 0) op1))
+                                           :expected-type 'list)
+                           nil
+                           frame-ptr))
+                  (t
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error (make-condition 'type-error
+                                           :datum (encoded-gpr-lisp
+                                                   xp
+                                                   (ldb (byte 4 0) op1))
+                                           :expected-type 'fixnum)
+                           nil
+                           frame-ptr)))
+            (%error "Unknown trap: #x~x~%xp=~s"
+                    (list (list op0 op1 op2) xp)
+                    frame-ptr))
+          skip))))
+
+;;; lots of duplicated code here
+#+x8632-target
+(defcallback %xerr-disp (:address xp :address xcf :int)
+  (with-error-reentry-detection
+      (let* ((frame-ptr (macptr->fixnum xcf))
+             (fn (%get-object xcf x8632::xcf.nominal-function))
+             (op0 (%get-xcf-byte xcf 0))
+             (op1 (%get-xcf-byte xcf 1))
+             (op2 (%get-xcf-byte xcf 2)))
+        (declare (type (unsigned-byte 8) op0 op1 op2))
+        (let* ((skip 2))
+          (if (and (= op0 #xcd)
+                   (>= op1 #x70))
+            (cond ((< op1 #x90)
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (setq *error-reentry-count* 0)
+                   (setf (encoded-gpr-lisp xp (ldb (byte 3 0) op1))
+                         (%slot-unbound-trap
+                          (encoded-gpr-lisp xp (ldb (byte 4 4) op2))
+                          (encoded-gpr-lisp xp (ldb (byte 4 0) op2))
+                          frame-ptr)))
+                  ((= op1 #x90)
+		   (setq skip (%check-anchored-uuo xcf 3))
+                   (setf (encoded-gpr-lisp
+                          xp
+                          (ldb (byte 3 0) op2))
+                         (%kernel-restart-internal $xvunbnd
+                                                   (list
+                                                    (encoded-gpr-lisp
+                                                     xp
+                                                     (ldb (byte 3 0) op2)))
+                                                   frame-ptr)))
+                  ((< op1 #xa0)
+		   (setq skip (%check-anchored-uuo xcf 2))
+                   ;; #x9x, x>- - register X is a symbol.  It's unbound,
+                   ;; but we don't have enough info to offer USE-VALUE,
+                   ;; STORE-VALUE, or CONTINUE restart
+                   (%error (make-condition 'unbound-variable
+                                           :name
+                                           (encoded-gpr-lisp
+                                               xp
+                                               (ldb (byte 3 0) op1)))
+                           ()
+                           frame-ptr))
+                  ((< op1 #xb0)
+		   (setq skip (%check-anchored-uuo xcf 2))
+                   (%err-disp-internal $xfunbnd
+                                       (list (encoded-gpr-lisp
+                                              xp
+                                              (ldb (byte 3 0) op1)))
+                                       frame-ptr))
+                  ((< op1 #xc0)
+		   (setq skip (%check-anchored-uuo xcf 3))
+                   (%err-disp-internal 
+                    #.(car (rassoc 'type-error *kernel-simple-error-classes*))
+                    (list (encoded-gpr-lisp
+                           xp
+                           (ldb (byte 3 0) op1))
+                          (logandc2 op2 arch::error-type-error))
+                    frame-ptr))
+                  ((= op1 #xc0)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error 'too-few-arguments
+                           (list :nargs (xp-argument-count xp)
+                                 :fn fn)
+                           frame-ptr))
+                  ((= op1 #xc1)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error 'too-many-arguments
+                           (list :nargs (xp-argument-count xp)
+                                 :fn fn)
+                           frame-ptr))
+                  ((= op1 #xc2)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (let* ((flags (xp-flags-register xp))
+                          (nargs (xp-argument-count xp))
+                          (carry-bit (logbitp x86::x86-carry-flag-bit flags)))
+                     (if carry-bit
+                       (%error 'too-few-arguments
+                               (list :nargs nargs
+                                     :fn fn)
+                               frame-ptr)
+                       (%error 'too-many-arguments
+                               (list :nargs nargs
+                                     :fn fn)
+                               frame-ptr))))
+                  ((= op1 #xc3)         ;array rank
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (%err-disp-internal $XNDIMS
+                                       (list (encoded-gpr-lisp xp (ldb (byte 4 4) op2))
+                                             (encoded-gpr-lisp xp (ldb (byte 4 0) op2)))
+                                       frame-ptr))
+                  ((= op1 #xc6)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error (make-condition 'type-error
+                                           :datum (encoded-gpr-lisp xp x8632::temp0)
+                                           :expected-type '(or symbol function)
+                                           :format-control
+                                           "~S is not of type ~S, and can't be FUNCALLed or APPLYed")
+                           nil frame-ptr))
+                  ((= op1 #xc7)
+                   (handle-udf-call xp frame-ptr)
+                   (setq skip 0))
+                  ((or (= op1 #xc8) (= op1 #xcb))
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (%error (%rsc-string $xarroob)
+                           (list (encoded-gpr-lisp xp (ldb (byte 4 4) op2))
+                                 (encoded-gpr-lisp xp (ldb (byte 4 0) op2)))
+                           frame-ptr))
+                  ((= op1 #xc9)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%err-disp-internal $xnotfun
+                                       (list (encoded-gpr-lisp xp x8632::temp0))
+                                       frame-ptr))
+                  ;; #xca = uuo-error-debug-trap
+                  ((= op1 #xcc)
+                   ;; external entry point or foreign variable
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (let* ((eep-or-fv (encoded-gpr-lisp xp (ldb (byte 4 4) op2))))
+                     (etypecase eep-or-fv
+                       (external-entry-point
+                        (resolve-eep eep-or-fv)
+                        (setf (encoded-gpr-lisp xp (ldb (byte 4 0) op2))
+                              (eep.address eep-or-fv)))
+                       (foreign-variable
+                        (resolve-foreign-variable eep-or-fv)
+                        (setf (encoded-gpr-lisp xp (ldb (byte 4 0) op2))
+                              (fv.addr eep-or-fv))))))
+                  ((< op1 #xe0)
+                   (setq skip (%check-anchored-uuo xcf 3))
+                   (if (= op2 x8632::subtag-catch-frame)
+                     (%error (make-condition 'cant-throw-error
+                                             :tag (encoded-gpr-lisp
+                                                   xp
+                                                   (ldb (byte 3 0) op1)))
+                             nil frame-ptr)
+                     (let* ((typename
+                             (cond ((= op2 x8632::tag-fixnum) 'fixnum)
+                                   ((= op2 x8632::subtag-character) 'character)
+                                   ((= op2 x8632::fulltag-cons) 'cons)
+                                   ((= op2 x8632::tag-misc) 'uvector)
+				   (t (let* ((class (logand op2 x8632::fulltagmask))
+                                             (high5 (ash op2 (- x8632::ntagbits))))
+                                        (cond ((= class x8632::fulltag-nodeheader)
+                                               (svref *nodeheader-types* high5))
+                                              ((= class x8632::fulltag-immheader)
+                                               (svref *immheader-types* high5))
+                                              (t (list 'bogus op2))))))))
+                       (%error (make-condition 'type-error
+                                               :datum (encoded-gpr-lisp
+                                                       xp
+                                                       (ldb (byte 3 0) op1))
+                                               :expected-type typename)
+                               nil
+                               frame-ptr))))
+                  ((< op1 #xf0)
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error (make-condition 'type-error
+                                           :datum (encoded-gpr-lisp
+                                                   xp
+                                                   (ldb (byte 3 0) op1))
+                                           :expected-type 'list)
+                           nil
+                           frame-ptr))
+                  (t
+                   (setq skip (%check-anchored-uuo xcf 2))
+                   (%error (make-condition 'type-error
+                                           :datum (encoded-gpr-lisp
+                                                   xp
+                                                   (ldb (byte 3 0) op1))
+                                           :expected-type 'fixnum)
+                           nil
+                           frame-ptr)))
+            (%error "Unknown trap: #x~x~%xp=~s"
+                    (list (list op0 op1 op2) xp)
+                    frame-ptr))
+          skip))))
+                 
Index: /branches/new-random/level-1/x86-threads-utils.lisp
===================================================================
--- /branches/new-random/level-1/x86-threads-utils.lisp	(revision 13309)
+++ /branches/new-random/level-1/x86-threads-utils.lisp	(revision 13309)
@@ -0,0 +1,208 @@
+;;; x86-trap-support
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+
+(defun %frame-backlink (p &optional context)
+  (declare (ignore context))
+  (cond ((fixnump p) (%%frame-backlink p))
+        (t (error "~s is not a valid stack frame" p))))
+
+(defun bottom-of-stack-p (p context)
+  (and (fixnump p)
+       (locally (declare (fixnum p))
+	 (let* ((tcr (if context (bt.tcr context) (%current-tcr)))
+                (vs-area (%fixnum-ref tcr target::tcr.vs-area)))
+	   (not (%ptr-in-area-p p vs-area))))))
+
+
+(defun lisp-frame-p (p context)
+  (declare (fixnum p))
+  (let ((next-frame (%frame-backlink p context)))
+    (declare (fixnum next-frame))
+    (if (bottom-of-stack-p next-frame context)
+        (values nil t)
+        (values t nil))))
+
+
+(defun catch-frame-sp (catch)
+  (uvref catch
+	 #+x8632-target x8632::catch-frame.ebp-cell
+	 #+x8664-target x8664::catch-frame.rbp-cell))
+
+;;; Sure would be nice to have &optional in defppclapfunction arglists
+;;; Sure would be nice not to do this at runtime.
+
+(let ((bits (lfun-bits #'(lambda (x &optional y) (declare (ignore x y))))))
+  (lfun-bits #'%fixnum-ref
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-ref)))))
+
+(let ((bits (lfun-bits #'(lambda (x &optional y) (declare (ignore x y))))))
+  (lfun-bits #'%fixnum-ref-natural
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-ref-natural)))))
+
+
+;;; Sure would be nice to have &optional in defppclapfunction arglists
+;;; Sure would be nice not to do this at runtime.
+
+(let ((bits (lfun-bits #'(lambda (x &optional y) (declare (ignore x y))))))
+  (lfun-bits #'%fixnum-ref
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-ref)))))
+
+(let ((bits (lfun-bits #'(lambda (x &optional y) (declare (ignore x y))))))
+  (lfun-bits #'%fixnum-ref-natural
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-ref-natural)))))
+
+(let ((bits (lfun-bits #'(lambda (x y &optional z) (declare (ignore x y z))))))
+  (lfun-bits #'%fixnum-set
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-set)))))
+
+(let ((bits (lfun-bits #'(lambda (x y &optional z) (declare (ignore x y z))))))
+  (lfun-bits #'%fixnum-set-natural
+             (dpb (ldb $lfbits-numreq bits)
+                  $lfbits-numreq
+                  (dpb (ldb $lfbits-numopt bits)
+                       $lfbits-numopt
+                       (lfun-bits #'%fixnum-set-natural)))))
+
+
+#+x8632-target
+(defun valid-subtag-p (subtag)
+  (declare (fixnum subtag))
+  (let* ((tagval (ldb (byte (- x8632::num-subtag-bits x8632::ntagbits) x8632::ntagbits) subtag)))
+    (declare (fixnum tagval))
+    (case (logand subtag x8632::fulltagmask)
+      (#. x8632::fulltag-immheader (not (eq (%svref *immheader-types* tagval) 'bogus)))
+      (#. x8632::fulltag-nodeheader (not (eq (%svref *nodeheader-types* tagval) 'bogus)))
+      (t nil))))
+
+#+x8664-target
+(defun valid-subtag-p (subtag)
+  (declare (fixnum subtag))
+  (let* ((tagval (logand x8664::fulltagmask subtag))
+         (high4 (ash subtag (- x8664::ntagbits))))
+    (declare (fixnum tagval high4))
+    (not (eq 'bogus
+             (case tagval
+               (#.x8664::fulltag-immheader-0
+                (%svref *immheader-0-types* high4))
+               (#.x8664::fulltag-immheader-1
+                (%svref *immheader-1-types* high4))
+               (#.x8664::fulltag-immheader-2
+                (%svref *immheader-2-types* high4))
+               (#.x8664::fulltag-nodeheader-0
+                (%svref *nodeheader-0-types* high4))
+               (#.x8664::fulltag-nodeheader-1
+                (%svref *nodeheader-1-types* high4))
+               (t 'bogus))))))
+
+#+x8632-target
+(defun valid-header-p (thing)
+  (let* ((fulltag (fulltag thing)))
+    (declare (fixnum fulltag))
+    (case fulltag
+      (#.x8632::fulltag-misc (valid-subtag-p (typecode thing)))
+      ((#.x8632::fulltag-immheader #.x8632::fulltag-nodeheader) nil)
+      (t t))))
+
+#+x8664-target
+(defun valid-header-p (thing)
+  (let* ((fulltag (fulltag thing)))
+    (declare (fixnum fulltag))
+    (case fulltag
+      ((#.x8664::fulltag-even-fixnum
+        #.x8664::fulltag-odd-fixnum
+        #.x8664::fulltag-imm-0
+        #.x8664::fulltag-imm-1)
+       t)
+      (#.x8664::fulltag-function
+       (= x8664::subtag-function (typecode (%function-to-function-vector thing))))
+      (#.x8664::fulltag-symbol
+       (= x8664::subtag-symbol (typecode (%symptr->symvector thing))))
+      (#.x8664::fulltag-misc
+       (valid-subtag-p (typecode thing)))
+      ((#.x8664::fulltag-tra-0
+        #.x8664::fulltag-tra-1)
+       (let* ((disp (%return-address-offset thing)))
+         (and disp
+              (let* ((f (%return-address-function thing)))
+                (and (typep f 'function) (valid-header-p f))))))
+      (#.x8664::fulltag-cons t)
+      (#.x8664::fulltag-nil (null thing))
+      (t nil))))
+             
+#+x8632-target
+(defun bogus-thing-p (x)
+  (when x
+    (or (not (valid-header-p x))
+        (let ((tag (lisptag x))
+	      (fulltag (fulltag x)))
+          (unless (or (eql tag x8632::tag-fixnum)
+                      (eql tag x8632::tag-imm)
+                      (in-any-consing-area-p x)
+		      (temporary-cons-p x)
+		      (and (or (typep x 'function)
+			       (typep x 'gvector))
+			   (on-any-tsp-stack x))
+		      (and (eql fulltag x8632::fulltag-tra)
+			   (%return-address-offset x))
+		      (and (typep x 'ivector)
+			   (on-any-csp-stack x))
+		      (%heap-ivector-p x))
+	    t)))))
+
+#+x8664-target
+(defun bogus-thing-p (x)
+  (when x
+    (or (not (valid-header-p x))
+        (let* ((tag (lisptag x)))
+          (unless (or (eql tag x8664::tag-fixnum)
+                      (eql tag x8664::tag-imm-0)
+                      (eql tag x8664::tag-imm-1)
+                      (in-any-consing-area-p x)
+                      (temporary-cons-p x)
+                      (and (or (typep x 'function)
+                               (typep x 'gvector))
+                           (on-any-tsp-stack x))
+                      (and (eql tag x8664::tag-tra)
+                           (eql 0 (%return-address-offset x)))
+                      (and (typep x 'ivector)
+                           (on-any-csp-stack x))
+                      (%heap-ivector-p x))
+            t)))))
+
Index: /branches/new-random/level-1/x86-trap-support.lisp
===================================================================
--- /branches/new-random/level-1/x86-trap-support.lisp	(revision 13309)
+++ /branches/new-random/level-1/x86-trap-support.lisp	(revision 13309)
@@ -0,0 +1,507 @@
+;;; x86-trap-support
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+;;; The order in which GPRs appear in an exception context generally
+;;; has nothing to do with how they're encoded in instructions/uuos,
+;;; and is OS-dependent.
+
+#+linuxx8664-target
+(progn
+  (defconstant gp-regs-offset (+ (get-field-offset :ucontext.uc_mcontext)
+                                 (get-field-offset :mcontext_t.gregs)))
+  (defmacro xp-gp-regs (xp) xp)
+  (defconstant flags-register-offset #$REG_EFL)
+  (defconstant rip-register-offset #$REG_RIP)
+  (defun xp-mxcsr (xp)
+    (pref xp :ucontext.uc_mcontext.fpregs.mxcsr))
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(13                                ;rax
+      14                                ;rcx
+      12                                ;rdx
+      11                                ;rbx
+      15                                ;rsp
+      10                                ;rbp
+      9                                 ;rsi
+      8                                 ;rdi
+      0                                 ;r8
+      1                                 ;r9
+      2                                 ;r10
+      3                                 ;r11
+      4                                 ;r12
+      5                                 ;r13
+      6                                 ;r14
+      7                                 ;r15
+      )))
+
+#+freebsdx8664-target
+(progn
+  (defconstant gp-regs-offset (get-field-offset :ucontext_t.uc_mcontext))
+  (defmacro xp-gp-regs (xp) xp)
+  (defconstant flags-register-offset 22)
+  (defconstant rip-register-offset 20)
+  (defun xp-mxcsr (xp)
+    (with-macptrs ((state (pref xp :__ucontext.uc_mcontext.mc_fpstate)))
+      (pref state :savefpu.sv_env.en_mxcsr)))
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(7					;rax
+      4					;rcx
+      3					;rdx
+      8					;rbx
+      23                                ;rsp
+      9					;rbp
+      2                                 ;rsi
+      1                                 ;rdi
+      5                                 ;r8
+      6                                 ;r9
+      10				;r10
+      11                                ;r11
+      12				;r12
+      13				;r13
+      14				;r14
+      15                                ;r15
+      )))
+
+#+darwinx8664-target
+;;; Apple has decided that compliance with some Unix standard or other
+;;; requires gratuitously renaming ucontext/mcontext structures and
+;;; their components.  Do you feel more compliant now ?
+(progn
+  (eval-when (:compile-toplevel :execute)
+    (def-foreign-type nil
+        (:struct :portable_mcontext64
+                 (:es :x86_exception_state64_t)
+                 (:ss :x86_thread_state64_t)
+                 (:fs :x86_float_state64_t)))
+    (def-foreign-type nil
+        (:struct :portable_uc_stack
+                 (:ss_sp (:* :void))
+                 (:ss_size (:unsigned 64))
+                 (:ss_flags  (:signed 32))))
+    (def-foreign-type nil
+        (:struct :portable_ucontext64
+                 (:onstack (:signed 32))
+                 (:sigmask (:unsigned 32))
+                 (:stack (:struct :portable_uc_stack))
+                 (:link :address)
+                 (:uc_mcsize (:unsigned 64))
+                 (:uc_mcontext64 (:* (:struct :portable_mcontext64))))))
+  (defun xp-mxcsr (xp)
+    (%get-unsigned-long
+     (pref (pref xp :portable_ucontext64.uc_mcontext64) :portable_mcontext64.fs) 32))
+  (defconstant gp-regs-offset 0)
+  (defmacro xp-gp-regs (xp)
+    `(pref (pref ,xp :portable_ucontext64.uc_mcontext64) :portable_mcontext64.ss))
+
+  (defconstant flags-register-offset 17)
+  (defconstant rip-register-offset 16)  
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(0					;rax
+      2					;rcx
+      3					;rdx
+      1					;rbx
+      7                                 ;rsp
+      6					;rbp
+      5                                 ;rsi
+      4                                 ;rdi
+      8                                 ;r8
+      9                                 ;r9
+      10				;r10
+      11                                ;r11
+      12				;r12
+      13				;r13
+      14				;r14
+      15                                ;r15
+      )))
+
+#+solarisx8664-target
+(progn
+  (defconstant gp-regs-offset (+ (get-field-offset :ucontext.uc_mcontext)
+                                 (get-field-offset :mcontext_t.gregs)))
+  (defmacro xp-gp-regs (xp) xp)
+  (defconstant flags-register-offset #$REG_RFL)
+  (defconstant rip-register-offset #$REG_RIP)
+  (defun xp-mxcsr (xp)
+    (pref xp :ucontext.uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr))
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(14                                ;rax
+      13                                ;rcx
+      12                                ;rdx
+      11                                ;rbx
+      20                                ;rsp
+      10                                ;rbp
+      9                                 ;rsi
+      8                                 ;rdi
+      7                                 ;r8
+      6                                 ;r9
+      5                                 ;r10
+      4                                 ;r11
+      3                                 ;r12
+      2                                 ;r13
+      1                                 ;r14
+      0                                 ;r15
+      )))
+
+#+win64-target
+(progn
+  (defconstant gp-regs-offset (get-field-offset #>CONTEXT.Rax))
+  (defmacro xp-gp-regs (xp) xp)
+  (defconstant rip-register-offset 16)
+  (defun xp-mxcsr (xp)
+    (pref xp #>CONTEXT.MxCsr))
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(0					;rax
+      1					;rcx
+      2					;rdx
+      3					;rbx
+      4                                 ;rsp
+      5					;rbp
+      6                                 ;rsi
+      7                                 ;rdi
+      8                                 ;r8
+      9                                 ;r9
+      10				;r10
+      11                                ;r11
+      12				;r12
+      13				;r13
+      14				;r14
+      15                                ;r15
+      )))
+
+#+darwinx8632-target
+(progn
+  (defconstant gp-regs-offset 0)
+  (defmacro xp-gp-regs (xp)
+    `(pref (pref ,xp :ucontext.uc_mcontext) :mcontext.ss))
+  (defun xp-mxcsr (xp)
+    (%get-unsigned-long (pref (pref xp :ucontext.uc_mcontext) :mcontext.fs) 32))
+  (defconstant flags-register-offset 9)
+  (defconstant eip-register-offset 10)
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(0					;eax
+      2					;ecx
+      3					;edx
+      1					;ebx
+      7					;esp
+      6					;ebp
+      5					;esi
+      4					;edi
+      )))
+
+#+linuxx8632-target
+(progn
+  (defconstant gp-regs-offset 0)
+  (defmacro xp-gp-regs (xp)
+    `(pref (pref ,xp :ucontext.uc_mcontext) :mcontext_t.gregs))
+  (defun xp-mxcsr (xp)
+    (pref (pref (pref xp :ucontext.uc_mcontext) :mcontext_t.fpregs)
+          :_fpstate.mxcsr))
+  (defconstant flags-register-offset #$REG_EFL)
+  (defconstant eip-register-offset #$REG_EIP)
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    (vector
+     #$REG_EAX                         ;eax
+      #$REG_ECX                         ;ecx
+      #$REG_EDX                         ;edx
+      #$REG_EBX                         ;ebx
+      #$REG_ESP                         ;esp
+      #$REG_EBP                         ;ebp
+      #$REG_ESI                         ;esi
+      #$REG_EDI                         ;edi
+      )))
+
+#+win32-target
+(progn
+  (defconstant gp-regs-offset 0)
+  (defmacro xp-gp-regs (xp)
+    `,xp)
+  (defun xp-mxcsr (xp)
+    (%get-unsigned-long (pref xp #>CONTEXT.ExtendedRegisters) 24))
+  (defconstant flags-register-offset 48)
+  (defconstant eip-register-offset 45)
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(
+     44                                ;eax
+     43                                ;ecx
+     42                                ;edx
+     41                                ;ebx
+     49                                ;esp
+     45                                ;ebp
+     40                                ;esi
+     39                                ;edi
+      )))
+
+#+solarisx8632-target
+(progn
+  (defconstant gp-regs-offset 0)
+  (defmacro xp-gp-regs (xp)
+    `(pref (pref ,xp :ucontext.uc_mcontext) :mcontext_t.gregs))
+  (defun xp-mxcsr (xp)
+    (pref xp :ucontext.uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr))
+  (defconstant flags-register-offset #$EFL)
+  (defconstant eip-register-offset #$EIP)
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    (vector
+     #$EAX
+     #$ECX
+     #$EDX
+     #$EBX
+     #$ESP
+     #$EBP
+     #$ESI
+     #$EDI)
+      ))
+
+#+freebsdx8632-target
+(progn
+  (defconstant gp-regs-offset 0)
+  (defmacro xp-gp-regs (xp)
+    `(pref ,xp :ucontext_t.uc_mcontext))
+  (defun xp-mxcsr (xp)
+    (pref (pref xp :ucontext_t.uc_mcontext.mc_fpstate) :savexmm.sv_env.en_mxcsr)
+)
+  (defconstant flags-register-offset 17)
+  (defconstant eip-register-offset 15)
+  (defparameter *encoded-gpr-to-indexed-gpr*
+    #(
+      12                                ;eax
+      11                                ;ecx
+      10                                ;edx
+      9                                 ;ebx
+      18                                ;esp
+      7                                 ;ebp
+      6                                 ;esi
+      5                                 ;edi
+      )
+      ))
+
+(defun indexed-gpr-lisp (xp igpr)
+  (%get-object (xp-gp-regs xp) (+ gp-regs-offset (ash igpr target::word-shift))))
+(defun (setf indexed-gpr-lisp) (new xp igpr)
+  (%set-object (xp-gp-regs xp) (+ gp-regs-offset (ash igpr target::word-shift)) new))
+(defun encoded-gpr-lisp (xp gpr)
+  (indexed-gpr-lisp xp (aref *encoded-gpr-to-indexed-gpr* gpr)))
+(defun (setf encoded-gpr-lisp) (new xp gpr)
+  (setf (indexed-gpr-lisp xp (aref *encoded-gpr-to-indexed-gpr* gpr)) new))
+(defun indexed-gpr-integer (xp igpr)
+  #+x8664-target
+  (%get-signed-long-long (xp-gp-regs xp) (+ gp-regs-offset (ash igpr x8664::word-shift)))
+  #+x8632-target
+  (%get-signed-long (xp-gp-regs xp) (+ gp-regs-offset (ash igpr x8632::word-shift))))
+(defun (setf indexed-gpr-integer) (new xp igpr)
+  (setf
+   #+x8664-target
+   (%get-signed-long-long (xp-gp-regs xp) (+ gp-regs-offset (ash igpr x8664::word-shift)))
+   #+x8632-target
+   (%get-signed-long (xp-gp-regs xp) (+ gp-regs-offset (ash igpr x8632::word-shift)))
+   new))
+(defun encoded-gpr-integer (xp gpr)
+  (indexed-gpr-integer xp (aref *encoded-gpr-to-indexed-gpr* gpr)))
+(defun (setf encoded-gpr-integer) (new xp gpr)
+  (setf (indexed-gpr-integer xp (aref *encoded-gpr-to-indexed-gpr* gpr)) new))
+(defun indexed-gpr-macptr (xp igpr)
+  (%get-ptr (xp-gp-regs xp) (+ gp-regs-offset (ash igpr target::word-shift))))
+(defun (setf indexed-gpr-macptr) (new xp igpr)
+  (setf (%get-ptr (xp-gp-regs xp) (+ gp-regs-offset (ash igpr target::word-shift))) new))
+(defun encoded-gpr-macptr (xp gpr)
+  (indexed-gpr-macptr xp (aref *encoded-gpr-to-indexed-gpr* gpr)))
+(defun (setf encoded-gpr-macptr) (new xp gpr)
+  (setf (indexed-gpr-macptr xp (aref *encoded-gpr-to-indexed-gpr* gpr)) new))
+(defun xp-flags-register (xp)
+  #+windows-target (pref xp #>CONTEXT.EFlags)
+  #-windows-target
+  (progn
+  #+x8664-target
+  (%get-signed-long-long (xp-gp-regs xp) (+ gp-regs-offset (ash flags-register-offset x8664::fixnumshift)))
+  #+x8632-target
+  (%get-signed-long (xp-gp-regs xp) (+ gp-regs-offset (ash flags-register-offset x8632::fixnumshift)))))
+  
+
+
+(defun %get-xcf-byte (xcf-ptr delta)
+  (let* ((containing-object (%get-object xcf-ptr target::xcf.containing-object))
+         (byte-offset (%get-object xcf-ptr target::xcf.relative-pc)))
+    (if containing-object
+      (locally (declare (optimize (speed 3) (safety 0))
+                        (type (simple-array (unsigned-byte 8) (*)) containing-object))
+        (aref containing-object (the fixnum (+ byte-offset delta))))
+      (%get-unsigned-byte (%int-to-ptr byte-offset) delta))))
+
+;;; If the byte following a uuo (which is "skip" bytes long, set
+;;; the xcf's relative PC to the value contained in the 32-bit
+;;; word preceding the current relative PC and return -1, else return skip.
+(defun %check-anchored-uuo (xcf skip)
+  (if (eql 0 (%get-xcf-byte xcf skip))
+    (let* ((new-rpc (+ #+x8664-target target::tag-function
+		       #+x8632-target target::fulltag-misc
+                       (logior (ash (%get-xcf-byte xcf -1) 24)
+                               (ash (%get-xcf-byte xcf -2) 16)
+                               (ash (%get-xcf-byte xcf -3) 8)
+                               (%get-xcf-byte xcf -4)))))
+      (%set-object xcf target::xcf.relative-pc new-rpc)
+      -1)
+    skip))
+                            
+                                  
+(defun decode-arithmetic-error (xp xcf)
+  (declare (ignore xp xcf))
+  (values 'unknown nil))
+
+(eval-when (:compile-toplevel :execute)
+  (progn
+    (defun conditional-os-constant (alternatives)
+      (dolist (c alternatives (error "None of the constants in ~s could be loaded" alternatives))
+        (if (load-os-constant c t)
+          (return (load-os-constant c)))))
+
+    (defconstant integer-divide-by-zero-code
+      (conditional-os-constant '(os::EXCEPTION_INT_DIVIDE_BY_ZERO os::FPE_INTDIV))
+)
+    (defconstant float-divide-by-zero-code
+      (conditional-os-constant '(os::EXCEPTION_FLT_DIVIDE_BY_ZERO os::FPE_FLTDIV)))
+    (defconstant float-overflow-code
+      (conditional-os-constant '(os::FPE_FLTOVF os::EXCEPTION_FLT_OVERFLOW)))
+    (defconstant float-underflow-code
+      (conditional-os-constant '(os::FPE_FLTUND os::EXCEPTION_FLT_UNDERFLOW)))
+    (defconstant float-inexact-code
+      (conditional-os-constant '(os::FPE_FLTRES os::EXCEPTION_FLT_INEXACT_RESULT)))))
+
+;;; UUOs are handled elsewhere.  This should handle all signals other than
+;;; those generated by UUOs (and the non-UUO cases of things like SIGSEGV.)
+;;; If the signal number is 0, other arguments (besides the exception context XP)
+;;; may not be meaningful.
+(defcallback xcmain (:address xp :address xcf :int signal :long code :long addr :long other :int)
+  (let* ((frame-ptr (macptr->fixnum xcf))
+	 (skip 0))
+    (cond ((zerop signal)               ;thread interrupt
+           (cmain))
+          ((< signal 0)
+           (%err-disp-internal code () frame-ptr))
+          ((= signal #$SIGFPE)
+           (setq code (logand #xffffffff code))
+           (multiple-value-bind (operation operands)
+               (decode-arithmetic-error xp xcf)
+             (let* ((condition-name
+                     (cond ((or (= code integer-divide-by-zero-code)
+                                (= code float-divide-by-zero-code))
+                            'division-by-zero)
+                           ((= code float-overflow-code)
+                            'floating-point-overflow)
+                           ((= code float-underflow-code)
+                            'floating-point-underflow)
+                           ((= code float-inexact-code)
+                            'floating-point-inexact)
+                           (t
+                            'floating-point-invalid-operation))))
+               (%error (make-condition condition-name
+                                       :operation operation
+                                       :operands operands
+                                       :status (xp-mxcsr xp))
+                       ()
+                       frame-ptr))))
+          ((= signal #$SIGSEGV)
+	   (cond
+	     ((or (= code 0) (= code 1))
+	      ;; Stack overflow.
+	      (let* ((on-tsp (= code 1)))
+		(unwind-protect
+		     (%error
+		      (make-condition
+		       'stack-overflow-condition 
+		       :format-control "Stack overflow on ~a stack."
+		       :format-arguments (list (if on-tsp "temp" "value")))
+		      nil frame-ptr)
+		  (ff-call (%kernel-import target::kernel-import-restore-soft-stack-limit)
+			   :unsigned-fullword code
+			   :void))))
+	     ((= code 2)
+	      ;; Write to a watched object.
+	      (let* ((offset other)
+		     ;; The kernel exception handler leaves the
+		     ;; watched object on the lisp stack under the
+		     ;; xcf.
+		     (object (%get-object xcf target::xcf.size)))
+		(multiple-value-bind (insn insn-length)
+		    (ignore-errors (x86-faulting-instruction xp))
+		  (restart-case (%error (make-condition
+					 'write-to-watched-object
+					 :offset offset
+					 :object object
+					 :instruction insn)
+					nil frame-ptr)
+		    #-windows-target
+		    (emulate ()
+		      :test (lambda (c)
+			      (declare (ignore c))
+			      (x86-can-emulate-instruction insn))
+		      :report
+		      "Emulate this instruction, leaving the object watched."
+		      (flet ((watchedp (object)
+			       (%map-areas #'(lambda (x)
+					       (when (eq object x)
+						 (return-from watchedp t)))
+					   area-watched)))
+			(let ((result nil))
+			  (with-other-threads-suspended
+			    (when (watchedp object)
+			      ;; We now trust that the object is in a
+			      ;; static gc area.
+			      (let* ((a (+ (%address-of object) offset))
+				     (ptr (%int-to-ptr
+					   (logandc2 a (1- *host-page-size*)))))
+				(#_mprotect ptr *host-page-size* #$PROT_WRITE)
+				(setq result (x86-emulate-instruction xp insn))
+				(#_mprotect ptr *host-page-size*
+					    (logior #$PROT_READ #$PROT_EXEC)))))
+			  (if result
+			    (setq skip insn-length)
+			    (error "could not emulate the instrution")))))
+		    (skip ()
+		      :test (lambda (c)
+			      (declare (ignore c))
+			      insn)
+		      :report "Skip over this write instruction."
+		      (setq skip insn-length))
+		    (unwatch ()
+		      :report "Unwatch the object and retry the write."
+		      (unwatch object))))))))
+          ((= signal #+win32-target 10 #-win32-target #$SIGBUS)
+           (if (= code -1)
+             (%error (make-condition 'invalid-memory-operation)
+                     ()
+                     frame-ptr)
+             (%error (make-condition 'invalid-memory-access
+                                     :address addr
+                                     :write-p (not (zerop code)))
+                     ()
+                     frame-ptr))))
+    skip))
+
+(defun x86-faulting-instruction (xp)
+  (let* ((code-bytes (make-array 15 :element-type '(unsigned-byte 8)))
+         (pc (indexed-gpr-macptr xp #+x8632-target eip-register-offset
+                                    #+x8664-target rip-register-offset)))
+    (dotimes (i (length code-bytes))
+      (setf (aref code-bytes i) (%get-unsigned-byte pc i)))
+    (let* ((ds (make-x86-disassembly-state
+                :mode-64 #+x8664-target t #+x8632-target nil
+                :code-vector code-bytes
+                :code-pointer 0))
+           (insn (x86-disassemble-instruction ds nil))
+           (len (- (x86-ds-code-pointer ds) (x86-ds-insn-start ds))))
+      (values insn len))))
Index: /branches/new-random/lib/.cvsignore
===================================================================
--- /branches/new-random/lib/.cvsignore	(revision 13309)
+++ /branches/new-random/lib/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/lib/apropos.lisp
===================================================================
--- /branches/new-random/lib/apropos.lisp	(revision 13309)
+++ /branches/new-random/lib/apropos.lisp	(revision 13309)
@@ -0,0 +1,248 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; Apropos.lisp
+
+(in-package "CCL")
+
+(eval-when (:execute :compile-toplevel)
+   (require :level-2)
+   )
+
+(defun apropos-list (string &optional package &aux list)
+  "Like APROPOS, except that it returns a list of the symbols found instead
+  of describing them."
+  (setq string (string-arg string))
+  (if package
+    (do-symbols (sym package)
+      (when (%apropos-substring-p string (symbol-name sym))
+        (push sym list)))
+    (do-all-symbols (sym)
+      (when (%apropos-substring-p string (symbol-name sym))
+        (push sym list))))
+  (let* ((last 0)                      ; not a symbol
+         (junk #'(lambda (item)
+                   (declare (debugging-function-name nil))
+                   (or (eq item last) (progn (setq last item) nil)))))
+    (declare (dynamic-extent junk))
+    (setq list (delete-if junk (sort list #'string-lessp))))
+  list)
+
+(defvar *apropos-indent-to-search-string* nil)
+(defun apropos-list-aux (theString package indent-to-search-string &aux theList)
+    (setq theString (string-arg theString))
+    (if package
+      (do-symbols (sym package)
+        (when (%apropos-substring-p theString (symbol-name sym))
+          (pushnew sym theList)))
+      (do-all-symbols (sym)
+        (when (%apropos-substring-p theString (symbol-name sym))
+          (pushnew sym theList))))
+    (let* ((last 0)                      ; not a symbol
+           (junk #'(lambda (item)
+                     (declare (debugging-function-name nil))
+                     (or (eq item last) (progn (setq last item) nil)))))
+      (declare (dynamic-extent junk))
+      (sort-symbol-list (delete-if junk theList) (if indent-to-search-string
+                                                   theString
+                                                   nil))))
+  
+(defun apropos-string-indented (symTuple indent)
+    (let ((pr-string     (prin1-to-string (aref symTuple 0)))
+          (displayOffset (aref symTuple 3)))
+      (format nil "~v@a~a"
+              indent
+              (subseq pr-string 0 displayOffset)
+              (subseq pr-string displayOffset))))
+  
+
+(defun apropos-aux (theString symtuple indent)
+  (declare (ignore theString))
+  (let ((sym (aref symtuple 0))
+        val)
+    (format t "~a" (apropos-string-indented symtuple indent))
+    (when (setq val (fboundp sym))
+      (cond ((functionp val)
+             (princ ", Def: ")
+             (prin1 (type-of val)))
+            ((setq val (macro-function sym))
+             (princ ", Def: MACRO ")
+             (prin1 (type-of val)))
+            (t (princ ", Special form"))))
+    (when (boundp sym)
+      (princ ",  Value: ")
+      (prin1 (symbol-value sym)))
+    (terpri)))
+
+  
+(defun apropos (theString &optional package)
+    (multiple-value-bind (symVector indent) (apropos-list-aux theString package *apropos-indent-to-search-string*)
+      (loop for symtuple across symVector
+        do (apropos-aux theString symtuple indent))
+      (values)))
+  
+#|
+(defun apropos (string &optional package)
+  "Briefly describe all symbols which contain the specified STRING.
+  If PACKAGE is supplied then only describe symbols present in
+  that package. If EXTERNAL-ONLY then only describe
+  external symbols in the specified package."
+  (setq string (string-arg string))
+  (if package
+    (do-symbols (sym package) (apropos-aux string sym))
+    (do-all-symbols (sym) (apropos-aux string sym)))
+  (values))
+
+(defun apropos-aux (string sym &aux val)
+  (when (%apropos-substring-p string (symbol-name sym))
+    (prin1 sym)
+    (when (setq val (fboundp sym))
+      (cond ((functionp val)
+             (princ ", Def: ")
+             (prin1 (type-of val)))
+            ((setq val (macro-function sym))
+             (princ ", Def: MACRO ")
+             (prin1 (type-of val)))
+            (t (princ ", Special form"))))
+    (when (boundp sym)
+       (princ ",  Value: ")
+       (prin1 (symbol-value sym)))
+    (terpri)))
+|#
+
+; (%apropos-substring-p a b)
+; Returns true iff a is a substring (case-sensitive) of b.
+; Internal subroutine of apropos, does no type-checking.  Assumes strings no
+; longer than 64K...
+
+
+
+
+(defun %apropos-substring-p (a b)
+  (let ((charA0 (%schar a 0))
+        (alen (length a))
+        (blen (length b)))
+    (declare (fixnum alen blen) (optimize (speed 3)(safety 0)))
+    (if (= alen 0)  ; "" is substring of every string
+        t
+        (if *apropos-case-sensitive-p*
+            (dotimes (i (the fixnum (%imin blen (%i+ 1 (%i- blen alen)))))
+              (declare (fixnum i))
+              (when (eq (%schar b i) chara0)
+                (when
+                    (do ((j 1 (1+ j)))
+                        ((>= j alen) t)
+                      (declare (fixnum j))
+                      (when (neq (%schar a j)(%schar b (%i+ j i)))
+                        (return nil)))
+                  (return  (%i- blen i alen)))))
+            (dotimes (i (the fixnum (%imin blen (%i+ 1 (%i- blen alen)))))
+              (declare (fixnum i))
+              (when (eq (char-upcase (%schar b i)) (char-upcase chara0))
+                (when
+                    (do ((j 1 (1+ j)))
+                        ((>= j alen) t)
+                      (declare (fixnum j))
+                      (unless (eq (char-upcase (%schar a j)) (char-upcase (%schar b (%i+ j i))))
+                        (return nil)))
+                  (return  (%i- blen i alen)))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; from Dave Yost
+(defun find-sym-alpha-part (sym)
+  (let* ((str (prin1-to-string sym))
+         (sortOffset (let ((sym-start (if (find #\: str)
+                                      (loop for ind from (1- (length str)) downto 0
+                                            when (eql #\: (char str ind))
+                                            return (1+ ind))
+                                      0)))
+                     (+ sym-start (find-alpha-char (subseq str sym-start))))))
+    (values str sortOffset sortOffset)))
+
+(defun find-str-in-sym (str sym)
+  (let* ((symStr (string-arg (prin1-to-string sym)))
+         (sortOffset (let ((sym-start (if (find #\: str)
+                                      (loop for ind from (1- (length str)) downto 0
+                                            when (eql #\: (char str ind))
+                                            return (1+ ind))
+                                      0)))
+                     (+ sym-start (find-alpha-char (subseq str sym-start)))))
+         (displayOffset (let ((sym-start (if (find #\: symStr)
+                                       (or (loop for ind from (1- (length symStr)) downto 0
+                                             when (eql #\| (schar symStr ind))
+                                             do (setf ind (loop for ind2 from (1- ind) downto 0
+                                                                when (eql #\| (schar symStr ind2))
+                                                                return ind2))
+                                             when (eql #\: (char symStr ind))
+                                             return (1+ ind))
+                                           0)
+                                       0)))
+                      (+ sym-start (search (string-upcase str) (string-upcase (subseq symStr sym-start)))))))
+    (values symStr sortOffset displayOffset)))
+
+(defun find-alpha-char (str)
+  "returns the character position of the first
+alphabetic character in str, or the length of str
+if it contains no alphabetic characters."
+  (setq str (string-arg str))
+  (dotimes (ind (length str)  ind)
+    (when (alpha-char-p (schar str ind))
+       (return ind))))
+
+(defun sort-symbol-list (theList search-string)
+  ;;; First precompute the stylized string form of the symbols as they will be compared
+  ;;; and calculate the maximum indent
+  (multiple-value-bind (tmpVector indentation)
+      (let (sortOffset
+            displayOffset
+            str)
+        (loop for x in thelist do
+              (multiple-value-setq (str sortOffset displayOffset)
+                (if search-string
+                  (find-str-in-sym search-string x)
+                  (find-sym-alpha-part           x)))
+                           
+                           
+              maximize displayOffset into indentation1
+              collect `#(,x ,(string-arg (subseq str sortOffset)) ,sortOffset ,displayOffset) into tmpList1
+              finally  (return (values `#(,@tmpList1) indentation1))))
+    (setq TMPVECTor (sort tmpVector #'(lambda (symPair1 symPair2)
+                                         (string-lessp (aref symPair1 1) (aref symPair2 1)))))
+    (values tmpVector ; each element is a vector of `#(,sym sortable-string-for-sym)
+            indentation)))
+
+
+#|
+(defun %apropos-substring-p (a b &aux (alen (length a))
+                                     (xlen (%i- (length b) alen)))
+  (if (%iminusp xlen) nil
+    (if (eq alen 0) alen
+      (let ((a0 (schar a 0)) (i 0) j)
+        (tagbody loop
+          (when (eq (schar b i) a0)
+            (setq j 1)
+            (tagbody subloop
+              (when (eq j alen) (return-from %apropos-substring-p i))
+              (when (eq (schar b (%i+ i j)) (schar a j))
+                 (setq j (%i+ j 1))
+                 (go subloop))))
+          (unless (eq i xlen)
+            (setq i (%i+ i 1))
+            (go loop)))
+        nil))))
+|#
Index: /branches/new-random/lib/arglist.lisp
===================================================================
--- /branches/new-random/lib/arglist.lisp	(revision 13309)
+++ /branches/new-random/lib/arglist.lisp	(revision 13309)
@@ -0,0 +1,286 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Record pseudo-arglist info for special operators.
+(record-arglist 'catch "tag &body body")
+(record-arglist 'progn "&BODY BODY")
+(record-arglist 'function "NAME-OR-LAMBDA-EXPRESSION")
+(record-arglist 'go "TAG")
+(record-arglist 'symbol-macrolet "(&REST BINDINGS) &BODY BODY")
+(record-arglist 'locally "DECLARATION* &BODY BODY")
+(record-arglist 'setq "[SYMBOL VALUE]*")
+(record-arglist 'tagbody "&REST TAGS-OR-FORMS")
+(record-arglist 'return-from "BLOCK VALUES")
+(record-arglist 'quote '(form))
+(record-arglist 'macrolet "(&REST BINDINGS) &BODY BODY")
+(record-arglist 'the '(type-specifier form))
+(record-arglist 'eval-when "(&REST SITUATIONS) &BODY BODY")
+(record-arglist 'let* "(&REST BINDINGS) &BODY BODY")
+(record-arglist 'let "(&REST BINDINGS) &BODY BODY")
+(record-arglist 'load-time-value '(form))
+(record-arglist 'throw '(tag value))
+(record-arglist 'unwind-protect "PROTECTED-FORM &BODY CLEANUP-FORMS")
+(record-arglist 'flet "(&REST BINDINGS) &BODY BODY")
+(record-arglist 'multiple-value-call '(function &rest values-producing-forms))
+(record-arglist 'block "NAME &BODY BODY")
+(record-arglist 'labels "(&REST BINDINGS) &BODY BODY")
+(record-arglist 'multiple-value-prog1 "VALUES-PRODUCING-FORM &BODY FORMS-FOR-EFFECT")
+(record-arglist 'if '(test true &optional false))
+(record-arglist 'progv "(&REST VARS) (&REST VALUES) &BODY BODY")
+(record-arglist 'nfunction '(function-name lambda-expression))
+
+
+; Returns two values: the arglist & it's functions binding.
+; If the second arg is NIL, there was no function binding.
+(defun arglist (sym &optional include-bindings)
+  (%arglist sym include-bindings))
+
+(defun arglist-string (sym &optional include-bindings)
+  (multiple-value-bind (res type)
+                       (%arglist-internal sym include-bindings)
+    (values
+     (if (stringp res)
+       res
+       (and res (princ-to-string res)))
+     type)))
+
+(defun set-arglist (sym arglist)
+  (let ((real-sym (arglist-sym-and-def sym)))
+    (when (or real-sym (null sym))
+      (if (eq arglist t)
+        (remhash real-sym %lambda-lists%)
+        (setf (gethash real-sym %lambda-lists%) arglist)))))
+
+(defsetf arglist set-arglist)
+
+; Same as ARGLIST, but has the option of using TEMP-CONS instead of CONS
+; to cons up the list.
+(defun %arglist (sym &optional include-bindings)
+  (multiple-value-bind (res type)
+                       (%arglist-internal
+                        sym include-bindings)
+    (when (stringp res)
+      (with-input-from-string (stream res)
+        (setq res nil)
+        (let ((eof (list nil))
+              val errorp)
+          (declare (dynamic-extent eof))
+          (loop
+            (multiple-value-setq (val errorp)
+              (ignore-errors (values (read stream nil eof))))
+            (when errorp
+              (push '&rest res)
+              (push ':unparseable res)
+              (return))
+            (when (eq val eof)
+              (return))
+            (push val res))
+          (setq res
+                (if (and (null (cdr res)) (listp (car res)))
+                  (car res)
+                  (nreverse res))))))
+    (values res type)))
+
+(defun %arglist-internal (sym include-bindings 
+                              &aux def type)
+  (multiple-value-setq (sym def) (arglist-sym-and-def sym))
+  (if (generic-function-p def)
+    (values (generic-function-lambda-list def) :declaration)
+    (let ((ll (gethash sym %lambda-lists% *eof-value*))
+        (macrop (and (symbolp sym) (eq (macro-function sym) def))))
+    (flet ((strip (f) (if (stringp f) f (strip-bindings f include-bindings))))
+      (declare (dynamic-extent #'strip))
+      (cond ((neq ll *eof-value*) (values (strip ll) :declaration))
+            ((consp def)
+             ;; Presumably (lambda (... arglist) ...)
+             (values (strip (cadr def)) :definition))
+            ((neq (setq ll (getf (%lfun-info def) 'arglist *eof-value*)) *eof-value*)
+             (values ll :definition))
+            ((and (not macrop) (setq ll (uncompile-function def)))
+             (values (strip (cadr ll)) (or type :definition)))
+            ((lfunp def)
+             (multiple-value-bind (arglist gotit) 
+                                  (unless macrop (arglist-from-map def))
+               (if gotit
+                 (values arglist :analysis)
+                 (cond  (macrop (values nil :unknown))
+                       (t (values (arglist-from-compiled-def def) :analysis))))))
+            (t (values nil nil)))))))
+
+            
+
+(defun strip-bindings (arglist include-bindings)
+  (if include-bindings
+    arglist
+    (let ((res nil))
+      (do ((args arglist (%cdr args)))
+          ((not (consp args)) (nreconc res args))
+        (let ((arg (car args)))
+          (cond ((atom arg)
+                 (push arg res))
+                ((atom (car arg))
+                 (push (car arg) res))
+                (t (push (caar arg) res))))))))
+
+(defun arglist-sym-and-def (sym &aux def)
+  (cond ((functionp sym)
+         (setq def sym
+               sym (function-name def))
+         (unless (and (symbolp sym) (eq def (fboundp sym)))
+           (setq sym nil)))
+        ((listp sym)
+         (if (eq (car sym) 'setf)
+           (setq sym (setf-function-name (cadr sym))
+                 def (find-unencapsulated-definition (fboundp sym)))
+           (setq sym nil def nil)))
+        ((standard-method-p sym)
+         (setq def (closure-function 
+                    (find-unencapsulated-definition (%method-function sym)))))
+        ((and (macro-function sym))
+         (setq def (macro-function sym)))
+        ((special-operator-p sym)
+         nil)
+        (t (setq def (find-unencapsulated-definition (fboundp sym)))))
+  (values sym (if (standard-generic-function-p def) def (closure-function def))))
+
+(defun arglist-from-map (lfun)
+  (multiple-value-bind (nreq nopt restp nkeys allow-other-keys
+                        optinit lexprp
+                        ncells nclosed)
+      (function-args lfun)
+    (declare (ignore optinit))
+    (if lexprp
+      (setq restp t))
+    (let ((map (car (function-symbol-map lfun))))
+      (if map
+        (let ((total (+ nreq nopt (if restp 1 0) (or nkeys 0)))
+              (idx (- (length map) nclosed))
+              (res nil))
+          (if (%izerop total)
+            (values nil t)
+            (progn
+              (dotimes (x nreq)
+                (declare (fixnum x))
+                (push (if (> idx 0) (elt map (decf idx)) (make-arg "ARG" x)) res))
+              (when (neq nopt 0)
+                (push '&optional res)
+                (dotimes (x (the fixnum nopt))
+                  (push (if (> idx 0) (elt map (decf idx)) (make-arg "OPT" x)) res)))
+
+              (when restp
+                (push (if lexprp '&lexpr '&rest) res)
+                (push (if (> idx 0) (elt map (decf idx)) 'the-rest) res))
+              (when nkeys
+                (push '&key res)
+                (let ((keyvect (lfun-keyvect lfun)))
+                  (dotimes (i (length keyvect))
+                    (push (elt keyvect i) res))))
+              (when allow-other-keys
+                (push '&allow-other-keys res))))
+          (values (nreverse res) t))
+        (values nil (zerop ncells))))))
+
+(defun arg-names-from-map (lfun pc)
+  (when lfun
+    (multiple-value-bind (nreq nopt restp nkeys allow-other-keys
+			       optinit lexprp
+			       ncells nclosed)
+	(function-args lfun)
+      (declare (ignore optinit ncells allow-other-keys))
+      (collect ((req)
+		(opt)
+		(keys))
+	(let* ((rest nil)
+	       (map (if (and pc (> pc target::arg-check-trap-pc-limit))
+			(car (function-symbol-map lfun)))))
+	  (if (and map pc)
+	      (let ((total (+ nreq nopt (if (or restp lexprp) 1 0) (or nkeys 0)))
+		    (idx (- (length map) nclosed)))
+		(unless (zerop total)
+		  (progn
+		    (dotimes (x (the fixnum nreq))
+		      (declare (fixnum x))
+		      (req (if (> idx 0) (elt map (decf idx)) (make-arg "ARG" x))))
+		    (when (neq nopt 0)
+		      (dotimes (x (the fixnum nopt))
+			(opt (if (> idx 0) (elt map (decf idx)) (make-arg "OPT" x)))))
+		    (when (or restp lexprp)
+		      (setq rest (if (> idx 0) (elt map (decf idx)) 'the-rest)))
+		    (when nkeys
+		      (dotimes (i (the fixnum nkeys))
+			(keys (if (> idx 0) (elt map (decf idx)) (make-arg "KEY" i)))))))))
+	  (values (or (not (null map))
+		      (and (eql 0 nreq) (eql 0 nopt) (not restp) (null nkeys)))
+		  (req) (opt) rest (keys)))))))
+              
+              
+
+
+(defvar *req-arg-names*
+  #(arg-0 arg-1 arg-2 arg-3 arg-4 arg-5 arg-6 arg-7 arg-8 arg-9))
+
+(defvar *opt-arg-names*
+  #(opt-0 opt-1 opt-2 opt-3 opt-4 opt-5 opt-6 opt-7 opt-8 opt-9))
+
+
+(defun make-arg (prefix count)
+  (cond ((and (string= prefix "ARG") (< count (length *req-arg-names*)))
+         (svref *req-arg-names* count))
+        ((and (string= prefix "OPT") (< count (length *opt-arg-names*)))
+         (svref *opt-arg-names* count))
+        (t (intern (format nil "~a-~d" prefix count) :CCL))))
+
+(defun arglist-from-compiled-def (lfun &aux (res nil) argnames)
+  (multiple-value-bind (nreq nopt restp nkeys allow-other-keys
+                             optinit lexprp
+                             ncells nclosed)
+      (function-args lfun)
+    (declare (ignore optinit ncells nclosed))
+    (flet ((push-various-args (prefix count)
+             (dotimes (i (the fixnum count))
+               (push (make-arg prefix i) res))))
+      (declare (dynamic-extent #'push-various-args))
+      ;; Treat &LEXPR like &REST.
+      (if lexprp (setq restp t lexprp nil))
+      (cond ((and (eq 0 (+ nreq nopt (or nkeys 0))) (not restp))
+             nil)
+            (t 
+             (if argnames
+               (setq res (reverse (butlast argnames (- (length argnames) nreq))))
+               (push-various-args "ARG" nreq))
+             (when (> nopt 0)
+               (push '&optional res)
+               (if argnames
+                 (setq res (append (reverse (subseq argnames nreq (+ nreq nopt))) res))
+                 (push-various-args "OPT" nopt)))
+             (when restp
+               (push '&rest res)
+               (if argnames
+                 (push (nth (+ nreq nopt) argnames) res)
+                 (push 'the-rest res)))
+             (when nkeys
+               (push '&key res)
+               (let ((keyvect (lfun-keyvect lfun)))
+                 (dotimes (i (length keyvect))
+                   (push (elt keyvect i) res))))
+             (when allow-other-keys
+               (push '&allow-other-keys res))
+             (nreverse res))))))
+
+; End of arglist.lisp
Index: /branches/new-random/lib/arrays-fry.lisp
===================================================================
--- /branches/new-random/lib/arrays-fry.lisp	(revision 13309)
+++ /branches/new-random/lib/arrays-fry.lisp	(revision 13309)
@@ -0,0 +1,465 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defun bit (bit-array &rest subscripts)
+  "Return the bit from the BIT-ARRAY at the specified SUBSCRIPTS."
+  (declare (dynamic-extent subscripts))
+  (unless (eq (array-element-type bit-array) 'bit)
+    (report-bad-arg bit-array '(array bit)))
+  (apply #'aref bit-array subscripts))
+
+(defun %bitset (bit-array &rest stuff)
+  (declare (dynamic-extent stuff))
+  (unless (eq (array-element-type bit-array) 'bit)
+    (report-bad-arg bit-array '(array bit)))
+  (apply #'aset bit-array stuff))
+
+(defun sbit (v &optional (sub0 nil sub0-p) &rest others)
+  "Return the bit from SIMPLE-BIT-ARRAY at the specified SUBSCRIPTS."
+  (declare (dynamic-extent others))
+  (if sub0-p
+    (if others
+      (apply #'bit v sub0 others)
+      ( sbit (require-type v 'simple-bit-vector) sub0))
+    (bit v)))
+
+(defun %sbitset (v sub0 &optional (newval nil newval-p) &rest newval-was-really-sub1)
+  (declare (dynamic-extent newval-was-really-sub1))
+  (if newval-p
+    (if newval-was-really-sub1
+      (apply #'%bitset v sub0 newval newval-was-really-sub1)
+      (progn
+        (unless (typep v 'simple-bit-vector)
+          (report-bad-arg v 'simple-bit-vector))
+        (uvset v sub0 newval)))
+    (%bitset v sub0)))
+
+(defun bit-and (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGAND on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+   (bit-boole boole-and bit-array1 bit-array2 result-bit-array))
+
+(defun bit-ior (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGIOR on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole  boole-ior bit-array1 bit-array2 result-bit-array))
+
+(defun bit-xor (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGXOR on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+   (bit-boole  boole-xor bit-array1 bit-array2 result-bit-array))
+
+(defun bit-eqv (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGEQV on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole boole-eqv bit-array1 bit-array2 result-bit-array))
+
+(defun bit-nand (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGNAND on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole boole-nand bit-array1 bit-array2 result-bit-array))
+
+(defun bit-nor (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGNOR on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole boole-nor bit-array1 bit-array2 result-bit-array))
+
+(defun bit-andc1 (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGANDC1 on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole boole-andc1 bit-array1 bit-array2 result-bit-array))
+
+(defun bit-andc2 (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGANDC2 on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole boole-andc2 bit-array1 bit-array2 result-bit-array))
+
+(defun bit-orc1 (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGORC1 on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole boole-orc1 bit-array1 bit-array2 result-bit-array))
+
+(defun bit-orc2 (bit-array1 bit-array2 &optional result-bit-array)
+  "Perform a bit-wise LOGORC2 on the elements of BIT-ARRAY-1 and BIT-ARRAY-2,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY-1 is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. All the arrays must have the same rank and dimensions."
+  (bit-boole boole-orc2 bit-array1 bit-array2 result-bit-array))
+
+(defun bit-not (bit-array &optional result-bit-array)
+  "Performs a bit-wise logical NOT on the elements of BIT-ARRAY,
+  putting the results in RESULT-BIT-ARRAY. If RESULT-BIT-ARRAY is T,
+  BIT-ARRAY is used. If RESULT-BIT-ARRAY is NIL or omitted, a new array is
+  created. Both arrays must have the same rank and dimensions."
+  (bit-boole boole-nor bit-array bit-array result-bit-array))
+
+(defun result-bit-array (bit-array-1 bit-array-2 result)
+  ; Check that the two bit-array args are bit-arrays with
+  ; compatible dimensions.  If "result" is specified as T,
+  ; return bit-array-1.  If result is unspecified, return
+  ; a new bit-array of the same dimensions as bit-array-2.
+  ; Otherwise, make sure that result is a bit-array of the
+  ; same dimensions as the other two arguments and return
+  ; it.
+  (let* ((typecode-1 (typecode bit-array-1))
+         (typecode-2 (typecode bit-array-2)))
+    (declare (fixnum typecode-1 typecode-2))
+    (flet ((bit-array-dimensions (bit-array typecode)
+             (declare (fixnum typecode))
+             (if (= typecode target::subtag-bit-vector)
+               (uvsize bit-array)
+               (let* ((array-p (= typecode target::subtag-arrayH))
+                      (vector-p (= typecode target::subtag-vectorH)))
+                 (if (and (or array-p vector-p) 
+                          (= (the fixnum (%array-header-subtype bit-array)) target::subtag-bit-vector))
+                   (if vector-p
+                     (array-dimension bit-array 0)
+                     (array-dimensions bit-array))
+                   (report-bad-arg bit-array '(array bit))))))
+           (check-matching-dimensions (a1 d1 a2 d2)
+             (unless (equal d1 d2)
+               (error "~s and ~s have different dimensions." a1 a2))
+             a2))
+      (let* ((dims-1 (bit-array-dimensions bit-array-1 typecode-1))
+             (dims-2 (bit-array-dimensions bit-array-2 typecode-2)))
+        (check-matching-dimensions bit-array-1 dims-1 bit-array-2 dims-2)
+        (if result
+          (if (eq result t)
+            bit-array-1
+            (check-matching-dimensions bit-array-2 dims-2 result (bit-array-dimensions result (typecode result))))
+          (make-array dims-2 :element-type 'bit :initial-element 0))))))
+
+
+
+
+  
+(defun bit-boole (opcode array1 array2 result-array)
+  (unless (eql opcode (logand 15 opcode))
+    (setq opcode (require-type opcode '(mod 16))))
+  (let* ((result (result-bit-array array1 array2 result-array)))
+    (if (and (typep array1 'simple-bit-vector)
+             (typep array2 'simple-bit-vector)
+             (typep result 'simple-bit-vector))
+      (%simple-bit-boole opcode array1 array2 result)
+      (multiple-value-bind (v1 i1) (array-data-and-offset array1)
+        (declare (simple-bit-vector v1) (fixnum i1))
+        (multiple-value-bind (v2 i2) (array-data-and-offset array2)
+          (declare (simple-bit-vector v2) (fixnum i2))
+          (multiple-value-bind (v3 i3) (array-data-and-offset result)
+            (declare (simple-bit-vector v3) (fixnum i3))
+            (let* ((e3 (+ i3 (the fixnum (array-total-size result)))))
+              (declare (fixnum e3))
+              (do* ( )
+                   ((= i3 e3) result)
+                (setf (sbit v3 i3) 
+                      (logand (boole opcode (sbit v1 i1) (sbit v2 i2)) 1))
+                (incf i1)
+                (incf i2)
+                (incf i3)))))))))
+
+
+          
+          
+
+
+
+
+; shrink-vector is called only in sequences-2. None of the calls depend on
+; the side affect of setting the passed-in symbol to the [possibly new]
+; returned vector
+; Since there hasn't been such a thing as sequences-2 in about 7 years,
+; this is especially puzzling.
+(eval-when (:compile-toplevel :execute :load-toplevel)
+  (defmacro shrink-vector (vector to-size)
+    `(setq ,vector (%shrink-vector ,vector ,to-size)))
+  )
+
+
+; new and faulty def
+(defun %shrink-vector (vector to-size)
+  (cond ((eq (length vector) to-size)
+         vector)
+        ((array-has-fill-pointer-p vector)
+         (setf (fill-pointer vector) to-size)
+         vector)
+        (t (subseq vector 0 to-size))))
+
+
+; this could be put into print-db as it was in ccl-pr-4.2
+; Or it (and print-db) could just be flushed ... tough one.
+(defun multi-dimension-array-to-list (array)
+  "Produces a nested list of the elements in array."
+  (mdal-aux array (array-dimensions array) nil 
+            (array-dimensions array)))
+
+(defun mdal-aux (array all-dimensions use-dimensions 
+                       remaining-dimensions)
+  (if (= (length all-dimensions) (length use-dimensions))
+    (apply 'aref array use-dimensions)
+    (do ((index 0 (1+ index))
+         (d-length (car remaining-dimensions))
+         (result nil))
+        ((= d-length index) result)
+      (setq result 
+            (append result (list (mdal-aux array all-dimensions
+                                           (append use-dimensions 
+                                                   (list index))
+                                           (cdr remaining-dimensions))))))))
+
+(defun adjust-array (array dims
+			   &key (element-type nil element-type-p)
+			   (initial-element nil initial-element-p)
+			   (initial-contents nil initial-contents-p)
+			   (fill-pointer nil fill-pointer-p)
+			   displaced-to
+			   displaced-index-offset
+			   &aux (subtype (array-element-subtype array)))
+  "Adjust ARRAY's dimensions to the given DIMENSIONS and stuff."
+  (when (and element-type-p
+             (neq (element-type-subtype element-type) subtype))
+    (error "~S is not of element type ~S" array element-type))
+  (when (integerp dims)(setq dims (list dims))) ; because %displace-array wants the list
+  (if (neq (list-length dims)(array-rank array))
+    (error "~S has wrong rank for adjusting to dimensions ~S" array dims))
+  (let ((size 1)
+        (explicitp nil))
+    (dolist (dim dims)
+      (when (< dim 0)(report-bad-arg dims '(integer 0 *)))
+      (setq size (* size dim)))
+    (when (and (neq fill-pointer t)
+               (array-has-fill-pointer-p array)
+               (< size (or fill-pointer (fill-pointer array))))
+      (error "Cannot adjust array ~S to size less than fill pointer ~S"
+             array (or fill-pointer (fill-pointer array))))
+    (when (and fill-pointer (not (array-has-fill-pointer-p array)))
+      (error "~S does not have a fill pointer" array))
+    (when (and displaced-index-offset (null displaced-to))
+      (error "Cannot specify ~S without ~S" :displaced-index-offset :displaced-to))
+    (when (and initial-element-p initial-contents-p)
+      (error "Cannot specify both ~S and ~S" :initial-element :initial-contents))
+    (cond 
+      ((not (adjustable-array-p array))
+       (let ((new-array (make-array-1  dims 
+                                       (array-element-type array) T
+                                       displaced-to
+                                       displaced-index-offset
+                                       nil
+                                       (or fill-pointer
+                                           (and (array-has-fill-pointer-p array)
+                                                (fill-pointer array)))
+                                       initial-element initial-element-p
+                                       initial-contents initial-contents-p
+                                       size)))
+                     
+	 (when (and (null initial-contents-p)
+		    (null displaced-to))
+	   (multiple-value-bind (array-data offs) (array-data-and-offset array)
+	     (let ((new-array-data (array-data-and-offset new-array))) 
+	       (cond ((null dims)
+		      (uvset new-array-data 0 (uvref array-data offs)))
+		     (T
+		      (init-array-data array-data offs (array-dimensions array) 
+				       new-array-data 0 dims))))))
+	 (setq array new-array)))
+      (T (cond 
+	   (displaced-to
+	    (if (and displaced-index-offset 
+		     (or (not (fixnump displaced-index-offset))
+			 (< displaced-index-offset 0)))
+	      (report-bad-arg displaced-index-offset '(integer 0 #.most-positive-fixnum)))
+	    (when (or initial-element-p initial-contents-p)
+	      (error "Cannot specify initial values for displaced arrays"))
+	    (unless (eq subtype (array-element-subtype displaced-to))
+	      (error "~S is not of element type ~S"
+		     displaced-to (array-element-type array)))
+	    (do* ((vec displaced-to (displaced-array-p vec)))
+		 ((null vec) ())
+	      (when (eq vec array)
+		(error "Array cannot be displaced to itself.")))
+	    (setq explicitp t))
+	   (T
+	    (setq displaced-to (%alloc-misc size subtype))
+	    (cond (initial-element-p
+		   (dotimes (i (the fixnum size)) (uvset displaced-to i initial-element)))
+		  (initial-contents-p
+		   (if (null dims) (uvset displaced-to 0 initial-contents)
+                     (init-uvector-contents displaced-to 0 dims initial-contents))))
+	    (cond ((null dims)
+		   (uvset displaced-to 0 (aref array)))
+		  ((not initial-contents-p)
+		   (multiple-value-bind (vec offs) (array-data-and-offset array)
+		     (init-array-data vec offs (array-dimensions array) displaced-to 0 dims))))))
+	 (%displace-array array dims size displaced-to (or displaced-index-offset 0) explicitp)))
+    (when fill-pointer-p
+      (cond
+        ((eq fill-pointer t)
+         (set-fill-pointer array size))
+        (fill-pointer
+         (set-fill-pointer array fill-pointer))))
+    array))
+
+(defun array-dims-sizes (dims)
+   (if (or (atom dims) (null (%cdr dims))) dims
+     (let ((ndims (array-dims-sizes (%cdr dims))))
+       (cons (* (%car dims) (%car ndims)) ndims))))
+
+(defun init-array-data (vec off dims nvec noff ndims)
+   (init-array-data-aux vec off dims (array-dims-sizes (cdr dims))
+                        nvec noff ndims (array-dims-sizes (cdr ndims))))
+
+(defun init-array-data-aux (vec off dims siz nvec noff ndims nsiz)
+   (when (null siz)
+      (return-from init-array-data-aux
+         (init-vector-data vec off (car dims) nvec noff (car ndims))))
+   (let ((count (pop dims))
+         (size (pop siz))
+         (ncount (pop ndims))
+         (nsize (pop nsiz)))
+     (dotimes (i (if (%i< count ncount) count ncount))
+        (declare (fixnum i))
+        (init-array-data-aux vec off dims siz nvec noff ndims nsiz)
+        (setq off (%i+ off size) noff (%i+ noff nsize)))))
+
+(defun init-vector-data (vec off len nvec noff nlen)
+  (dotimes (i (if (%i< len nlen) len nlen))
+     (declare (fixnum i))
+     (uvset nvec noff (uvref vec off))
+     (setq off (%i+ off 1) noff (%i+ noff 1))))
+
+;;; only caller is adjust-array
+
+(defun %displace-array (array dims size data offset explicitp)
+  (let* ((typecode (typecode array))
+         (array-p (eql typecode target::subtag-arrayH))
+         (vector-p (eql typecode target::subtag-vectorH)))
+    (unless (or array-p vector-p)
+      (error "Array ~S cannot be displaced" array))
+    (unless (fixnump offset) (report-bad-arg offset '(integer 0 #.most-positive-fixnum)))
+    (unless (adjustable-array-p data)
+      (multiple-value-bind (ndata noffset) (displaced-array-p data)
+        (if ndata (setq data ndata offset (%i+ offset noffset)))))
+    (unless (and (fixnump size) (%i<= (%i+ offset size) (array-total-size data)))
+      (error "Offset ~S + size ~S must be less than size of array displaced-to" offset size))
+    (let* ((flags (%svref array target::vectorH.flags-cell)))
+      (declare (fixnum flags))
+      (setf (%svref array target::vectorH.flags-cell)
+            (if (> (the fixnum (typecode data)) target::subtag-vectorH)
+              (bitclr $arh_disp_bit flags)
+              (bitset $arh_disp_bit flags)))
+      (setf (%svref array target::vectorH.flags-cell)
+            (if explicitp
+              (bitset $arh_exp_disp_bit flags)
+              (bitclr $arh_exp_disp_bit flags)))
+      (setf (%svref array target::arrayH.data-vector-cell) data)
+      (if array-p
+        (progn
+          (do ((i target::arrayH.dim0-cell (1+ i)))
+              ((null dims))
+            (declare (fixnum i))
+            (setf (%svref array i) (pop dims)))
+          (setf (%svref array target::arrayH.physsize-cell) size)
+          (setf (%svref array target::arrayH.displacement-cell) offset))
+        (progn
+          (if (or (not (logbitp $arh_fill_bit flags))
+                  (> (the fixnum (%svref array target::vectorH.logsize-cell)) size))
+            (setf (%svref array target::vectorH.logsize-cell) size))
+          (setf (%svref array target::vectorH.physsize-cell) size)
+          (setf (%svref array target::vectorH.displacement-cell) offset)))
+      array)))
+
+
+
+(defun array-row-major-index (array &lexpr subscripts)
+  (let ((rank  (array-rank array))
+        (nsubs (%lexpr-count subscripts))
+        (sum 0))
+    (declare (fixnum sum rank))
+    (unless (eql rank nsubs)
+      (%err-disp $xndims array nsubs))    
+      (if (eql 0 rank)
+        0
+        (do* ((i (1- rank) (1- i))
+              (dim (array-dimension array i) (array-dimension array i))
+              (last-size 1 size)
+              (size dim (* dim size)))
+             (nil)
+          (declare (fixnum i last-size size))
+          (let ((s (%lexpr-ref subscripts nsubs i)))
+            (unless (fixnump s)
+              (setq s (require-type s 'fixnum)))
+            (when (or (< s 0) (>= s dim))
+              (%err-disp $XARROOB (%apply-lexpr 'list subscripts) array))
+            (incf sum (the fixnum (* s last-size)))
+            (when (eql i 0) (return sum)))))))
+
+(defun array-in-bounds-p (array &lexpr subscripts)
+  "Return T if the SUBSCIPTS are in bounds for the ARRAY, NIL otherwise."
+  (let ((rank  (array-rank array))
+        (nsubs (%lexpr-count subscripts)))
+    (declare (fixnum nsubs rank))    
+    (if (not (eql nsubs rank))
+      (%err-disp $xndims array nsubs)
+      (if (eql 0 rank)
+        0
+        (do* ((i (1- rank) (1- i))
+              (dim (array-dimension array i) (array-dimension array i)))
+             (nil)
+          (declare (fixnum i dim))
+          (let ((s  (%lexpr-ref subscripts nsubs i)))
+	    (if (typep s 'fixnum)
+	      (locally (declare (fixnum s))
+		(if (or (< s 0)(>= s dim)) (return nil)))
+	      (if (typep s 'bignum)
+		(return nil)
+		(report-bad-arg s 'integer)))
+            (when (eql i 0) (return t))))))))
+
+(defun row-major-aref (array index)
+  "Return the element of array corressponding to the row-major index. This is
+   SETF'able."
+  (multiple-value-bind (displaced-to offset) (displaced-array-p array)
+    (aref (or displaced-to array) (+ index offset))))
+
+(defun row-major-aset (array index new)
+  (multiple-value-bind (displaced-to offset) (displaced-array-p array)
+    (setf (aref (or displaced-to array) (+ index offset)) new)))
+
+(defsetf row-major-aref row-major-aset)
+             
+
+
+; end
Index: /branches/new-random/lib/backquote.lisp
===================================================================
--- /branches/new-random/lib/backquote.lisp	(revision 13309)
+++ /branches/new-random/lib/backquote.lisp	(revision 13309)
@@ -0,0 +1,394 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+
+; Backquote.lisp
+
+(in-package "CCL")
+
+#+nil
+(progn
+;;; Common Lisp backquote implementation, written in Common Lisp.
+;;; Author: Guy L. Steele Jr.     Date: 27 December 1985
+;;; Texted under Symbolics Common Lisp and Lucid Common Lisp.
+;;; This software is in the public domain.
+
+;;; The following are unique tokens used during processing
+;;; They need not be symbols; they need not even be atoms.
+
+(defvar *comma* (make-symbol "`,"))
+(defvar *comma-atsign* (make-symbol "`,@"))
+(defvar *comma-dot* (make-symbol "`,."))
+(defvar *bq-list* (make-symbol "BQ-LIST"))
+(defvar *bq-append* (make-symbol "BQ-APPEND"))
+(defvar *bq-list** (make-symbol "BQ-LIST*"))
+(defvar *bq-nconc* (make-symbol "BQ-NCONC"))
+(defvar *bq-clobberable* (make-symbol "BQ-CLOBBERABLE"))
+(defvar *bq-quote* (make-symbol "BQ-QUOTE"))
+(defvar *bq-quote-nil* (list *bq-quote* nil))
+
+;;; Reader macro characters:
+;;;    `foo is read in as (BACKQUOTE foo)
+;;;    ,foo is read in as (#:COMMA foo)
+;;;    ,@foo is read in as (#:COMMA-ATSIGN foo)
+;;;    ,.foo is read in as (#:COMMA-DOT foo)
+;;; where #:COMMA is the value of the variable *COMMA* etc.
+
+;;; BACKQUOTE is an ordinary macro (not a read-macro) that
+;;; processes the expression foo, looking for occurrences of
+;;; #:COMMA, #:COMMA-ATSIGN, and #:COMMA-DOT.  It constructs code
+;;; in strict accordance with the rules on pages 349-350 of
+;;; of the first edition (pages 528-529 of this second edition).
+;;; It then optionally applies a code simplifier.
+
+(set-macro-character #\`
+                     #'(lambda (stream char)
+                         (declare (ignore char))
+                         (list 'backquote (read stream t nil t))))
+
+(set-macro-character #\,
+                     #'(lambda (stream char)
+                         (declare (ignore char))
+                         (case (peek-char nil stream t nil t)
+                           (#\@ (read-char stream t nil t)
+                            (list *comma-atsign* (read stream t nil t)))
+                           (#\. (read-char stream t nil t)
+                            (list *comma-dot* (read stream t nil t)))
+                           (otherwise (list *comma* (read stream t nil t))))))
+
+;;; if the value of *BQ-SIMPLIFY* is non-nil, then BACKQUOTE
+;;; processing applies the code simplifier.  If the value is NIL,
+;;; then the code resulting from BACKQUOTE is exactly that
+;;; specified by the official rules.
+
+(defvar *bq-simplify* t)
+
+(defmacro backquote (x)
+  (bq-completely-process x))
+
+;;; Backquote processing proceeds in three stages:
+;;;
+;;; (1) BQ-PROCESS applies the rules to remove occurrences of
+;;; #:COMMA, #:COMMA-ATSIGN, and #:COMMA-DOT corresponding to
+;;; this level of BACKQUOTE.  (It also causes embedded calls to
+;;; BACKQUOTE to be expanded so that nesting is properly handled.)
+;;; Code is produced that is expressed in terms of functions
+;;; #:BQ-LIST, #:BQ-APPEND, and #:BQ-CLOBBERABLE.  This is done
+;;; so that the simplifier will simplify only list construction
+;;; functions actually generated by backquote and will not involve
+;;; any user code in the simplification.   #:BQ-LIST means LIST,
+;;; #:BQ-APPEND means APPEND, and #:BQ-CLOBBERABLE means IDENTITY
+;;; but indicates places where ",." was used and where NCONC may
+;;; therefore be introduced by the simplifier for efficiency.
+;;;
+;;; (2) BQ-SIMPLIFY, if used, rewrites the code produced by
+;;; BQ-PROCESS to produce equivalent but faster code.  The
+;;; additional functions #:BQ-LIST* and #:BQ-NCONC may be
+;;; introduced into the code.
+;;;
+;;; (3) BQ-REMOVE-TOKENS goes through the code and replaces
+;;; #:BQ-LIST with LIST, #:BQ-APPEND with APPEND, and so on.
+;;; #:BQ-CLOBBERABLE is simply eliminated (a call to it being
+;;; replaced by its argument).  #:BQ-LIST* is replaced by either
+;;; LIST* or CONS (the latter is used in the two-argument case,
+;;; purely to make the resulting code a tad more readable).
+
+(defun bq-completely-process (x)
+  (let ((raw-result (bq-process x)))
+    (bq-remove-tokens (if *bq-simplify*
+                        (bq-simplify raw-result)
+                        raw-result))))
+
+; Portable code could just say (coerce list 'vector)
+(defun list-to-vector (list)
+  (unless (listp list)
+    (setq list (require-type list 'list)))
+  (%list-to-uvector nil list))
+
+(define-compiler-macro list-to-vector (&whole whole form)
+  (if (quoted-form-p form)
+    (list-to-vector (cadr form))
+    whole))
+
+(defun bq-process (x)
+  (cond ((atom x)
+         (if (simple-vector-p x)
+           (list 'list-to-vector (bq-process (coerce x 'list)))
+           (list *bq-quote* x)))
+        ((eq (car x) 'backquote)
+         (bq-process (bq-completely-process (cadr x))))
+        ((eq (car x) *comma*) (cadr x))
+        ((eq (car x) *comma-atsign*)
+         (error ",@~S after `" (cadr x)))
+        ((eq (car x) *comma-dot*)
+         (error ",.~S after `" (cadr x)))
+        (t (do ((p x (cdr p))
+                (q '() (cons (bracket (car p)) q)))
+               ((atom p)
+                (cons *bq-append*
+                      (nreconc q (list (list *bq-quote* p)))))
+             (when (eq (car p) *comma*)
+               (unless (null (cddr p)) (error "Malformed ,~S" p))
+               (return (cons *bq-append*
+                             (nreconc q (list (cadr p))))))
+             (when (eq (car p) *comma-atsign*)
+               (error "Dotted ,@~S" p))
+             (when (eq (car p) *comma-dot*)
+               (error "Dotted ,.~S" p))))))
+
+;;; This implements the bracket operator of the formal rules
+
+(defun bracket (x)
+  (cond ((atom x)
+         (list *bq-list* (bq-process x)))
+        ((eq (car x) *comma*)
+         (list *bq-list* (cadr x)))
+        ((eq (car x) *comma-atsign*)
+         (cadr x))
+        ((eq (car x) *comma-dot*)
+         (list *bq-clobberable* (cadr x)))
+        (t (list *bq-list* (bq-process x)))))
+
+;;; This auxiliary function is like MAPCAR but has two extra
+;;; purpoess: (1) it handles dotted lists; (2) it tries to make
+;;; the result share with the argument x as much as possible.
+
+(defun maptree (fn x)
+  (if (atom x)
+    (funcall fn x)
+    (let ((a (funcall fn (car x)))
+          (d (maptree fn (cdr x))))
+      (if (and (eql a (car x)) (eql d (cdr x)))
+        x
+        (cons a d)))))
+
+;;; This predicate is true of a form that when read looked
+;;; like ,@foo or ,.foo
+
+(defun bq-splicing-frob (x)
+  (and (consp x)
+       (or (eq (car x) *comma-atsign*)
+           (eq (car x) *comma-dot*))))
+
+;;; This predicate is true of a form that when read
+;;; looked like ,@foo or just plain ,foo.
+
+(defun bq-frob (x)
+  (and (consp x)
+       (or (eq (car x) *comma*)
+           (eq (car x) *comma-atsign*)
+           (eq (car x) *comma-dot*))))
+
+;;; The simplifier essentially looks for calls to #:BQ-APPEND and
+;;; tries to simplify them.  The arguments to #:BQ-APPEND are
+;;; processed from right to left, building up a replacement for.
+;;; At each step a number of special cases are handled that,
+;;; loosely speaking, look like this:
+;;;
+;;; (APPEND (LIST a b c) foo) => (LIST* a b c foo)
+;;;   provided a, b, c are not splicing frobs
+;;; (APPEND (LIST* a b c) foo) => (LIST* a b (APPEND c foo))
+;;;   provided a, b, c are not splicing frobs
+;;; (APPEND (QUOTE (x)) foo) => (LIST* (QUOTE x) foo)
+;;; (APPEND (CLOBBERABLE x) foo) => (NCONC x foo)
+
+(defun bq-simplify (x)
+  (if (atom x)
+    x
+    (let ((x (if (eq (car x) *bq-quote*)
+               x
+               (maptree #'bq-simplify x))))
+      (if (not (eq (car x) *bq-append*))
+        x
+        (bq-simplify-args x)))))
+
+(defun bq-simplify-args (x)
+  (do ((args (reverse (cdr x)) (cdr args))
+       (result
+        nil
+        (cond ((atom (car args))
+               (bq-attach-append *bq-append* (car args) result))
+              ((and (eq (caar args) *bq-list*)
+                    (notany #'bq-splicing-frob (cdar args)))
+               (bq-attach-conses (cdar args) result))
+              ((and (eq (caar args) *bq-list**)
+                    (notany #'bq-splicing-frob (cdar args)))
+               (bq-attach-conses
+                (reverse (cdr (reverse (cdar args))))
+                (bq-attach-append *bq-append*
+                                  (car (last (car args)))
+                                  result)))
+              ((and (eq (caar args) *bq-quote*)
+                    (consp (cadar args))
+                    (not (bq-frob (cadar args)))
+                    (null (cddar args)))
+               (bq-attach-conses (list (list *bq-quote*
+                                             (caadar args)))
+                                 result))
+              ((eq (caar args) *bq-clobberable*)
+               (bq-attach-append *bq-nconc* (cadar args) result))
+              (t (bq-attach-append *bq-append*
+                                   (car args)
+                                   result)))))
+      ((null args) result)))
+
+(defun null-or-quoted (x)
+  (or (null x) (and (consp x) (eq (car x) *bq-quote*))))
+
+;;; When BQ-ATTACH-APPEND is called, the OP should be #:BQ-APPEND
+;;; or #:BQ-NCONC.  This produces a form (op item result) but
+;;; some simplifications are done on the fly:
+;;;
+;;;  (op '(a b c) '(d e f g)) => '(a b c d e f g)
+;;;  (op item 'nil) => item, provided item is not a splicable frob
+;;;  (op item 'nil) => (op item), if item is a splicable frob
+;;;  (op item (op a b c)) => (op item a b c)
+
+(defun bq-attach-append (op item result)
+  (cond ((and (null-or-quoted item) (null-or-quoted result))
+         (list *bq-quote* (append (cadr item) (cadr result))))
+        ((or (null result) (equal result *bq-quote-nil*))
+         (if (bq-splicing-frob item) (list op item) item))
+        ((and (consp result) (eq (car result) op))
+         (list* (car result) item (cdr result)))
+        (t (list op item result))))
+
+;;; The effec tof BQ-ATTACH-CONSES is to produce a form as if by
+;;; `(LIST* ,@items ,result) but some simplifications are done
+;;; on the fly.
+;;;
+;;;  (LIST* 'a 'b 'c 'd) => '(a b c . d)
+;;;  (LIST* a b c 'nil) => (LIST a b c)
+;;;  (LIST* a b c (LIST* d e f g)) => (LIST* a b c d e f g)
+;;;  (LIST* a b c (LIST d e f g)) => (LIST a b c d e f g)
+
+(defun bq-attach-conses (items result)
+  (cond ((and (every #'null-or-quoted items)
+              (null-or-quoted result))
+         (list *bq-quote*
+               (append (mapcar #'cadr items) (cadr result))))
+        ((or (null result) (equal result *bq-quote-nil*))
+         (cons *bq-list* items))
+        ((and (consp result)
+              (or (eq (car result) *Bq-list*)
+                  (eq (car result) *bq-list**)))
+         (cons (car result) (append items (cdr result))))
+        (t (cons *bq-list** (append items (list result))))))
+
+;;; Removes funny toeksn and changes (#:BQ-LIST* a b) into
+;;; (CONS a b) instead of (LIST* a b), purely for readability.
+
+(defun bq-remove-tokens (x)
+  (cond ((eq x *bq-list*) 'list)
+        ((eq x *bq-append*) 'append)
+        ((eq x *bq-nconc*) 'nconc)
+        ((eq x *bq-list**) 'list*)
+        ((eq x *bq-quote*) 'quote)
+        ((atom x) x)
+        ((eq (car x) *bq-clobberable*)
+         (bq-remove-tokens (cadr x)))
+        ((and (eq (car x) *bq-list**)
+              (consp (cddr x))
+              (null (cdddr x)))
+         (cons 'cons (maptree #'bq-remove-tokens (cdr x))))
+        (t (maptree #'bq-remove-tokens x))))
+
+)
+
+#-nil
+(progn
+(declaim (special *|`,|* *|`,.|* *|`,@|*))
+
+;;;Backquote reads in as a call to the BACKQUOTE-EXPANDER macro.
+;;;This makes it a little obscure to look at raw, but makes it possible for
+;;;the pretty-printer to print things read in with backquote.
+
+(defvar *backquote-expand* t "If non-NIL, expand at read-time")
+
+(defmacro backquote-expander (*|`,|* *|`,.|* *|`,@|* form)
+   (declare (special *|`,|* *|`,.|* *|`,@|*))
+   (multiple-value-bind (form constantp) (backquote-aux form)
+     (backq-form form constantp)))
+
+(defun backquote-aux (form)
+  ;;Doesn't try to optimize multiple CONS's into LIST/LIST*'s, leaving it up
+  ;;to the compiler.  The code here is mainly concerned with folding
+  ;;constants, since the compiler is not allowed to do that in general.
+  (cond
+   ((simple-vector-p form)
+    (let ((elts ()) (i (length form)))
+      (until (%izerop i) (push (svref form (setq i (%i- i 1))) elts))
+      (multiple-value-bind (elts quotedp) (backquote-aux elts)
+        (if quotedp
+          (values (list-to-vector elts) t)
+          (list 'list-to-vector elts)))))
+   ((self-evaluating-p form) (values form t))
+   ((atom form) (values form t))
+   ((eq (%car form) 'backquote-expander) (backquote-aux (macroexpand-1 form)))
+   ((eq (%car form) *|`,|*) (%cdr form))
+   ((eq (%car form) *|`,@|*) (error "Misplaced ,@~S after backquote" (%cdr form)))
+   ((eq (%car form) *|`,.|*) (error "Misplaced ,.~S after backquote" (%cdr form)))
+   (t (let* ((car (%car form))
+             (splice (and (consp car) (if (eq (%car car) *|`,@|*) 'append
+                                        (if (eq (%car car) *|`,.|*) 'nconc)))))
+        (multiple-value-bind (cdr qd) (backquote-aux (%cdr form))
+          (if splice
+            (cond ((null (%cdr car)) (values cdr qd))
+                  ((null cdr) (values (%cdr car) (self-evaluating-p (%cdr car))))
+                  (t (list splice (%cdr car) (backq-form cdr qd))))
+            (multiple-value-bind (car qa) (backquote-aux car)
+              (cond ((and qa qd) (values (cons car cdr) t))
+                    ((null cdr) (list 'list car))
+                    (t (list 'list*     ; was CONS
+                             (backq-form car qa) (backq-form cdr qd)))))))))))
+
+(defun backq-form (form constantp)
+  (if (and constantp (not (self-evaluating-p form))) (list 'quote form) form))
+
+(defparameter *backquote-stack* ())
+
+(set-macro-character 
+ #\`
+ (nfunction 
+  |` reader|
+  (lambda (stream char &aux form)
+    (declare (ignore char))
+    (setq form
+          (let* ((|`,| (make-symbol "`,"))
+                 (|`,.| (make-symbol "`,."))
+                 (|`,@| (make-symbol "`,@")))
+            (list 'backquote-expander |`,| |`,.| |`,@|
+                  (let ((*backquote-stack* (list* |`,| |`,.| |`,@| *backquote-stack*)))
+                    (read stream t nil t)))))
+    (if *backquote-expand* (values (macroexpand-1 form)) form))))
+
+(set-macro-character 
+ #\, 
+ (nfunction
+  |, reader| 
+  (lambda (stream char &aux (stack *backquote-stack*))
+    (when (null stack)
+      (signal-reader-error stream "Comma not inside backquote"))
+    (let ((*backquote-stack* (cdddr stack)))
+      (setq char (tyi stream))
+      (cond ((eq char #\@)
+             (cons (%caddr stack) (read stream t nil t)))
+            ((eq char #\.)
+             (cons (%cadr stack) (read stream t nil t)))
+            (t
+             (untyi char stream)
+             (cons (%car stack) (read stream t nil t))))))))
+)
+
+(provide 'backquote)
Index: /branches/new-random/lib/backtrace-lds.lisp
===================================================================
--- /branches/new-random/lib/backtrace-lds.lisp	(revision 13309)
+++ /branches/new-random/lib/backtrace-lds.lisp	(revision 13309)
@@ -0,0 +1,141 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; backtrace-lds.lisp
+;;; low-level support for stack-backtrace dialog (Lisp Development System)
+
+(in-package "CCL")
+
+
+(defparameter *saved-register-count*
+  #+x8632-target 0
+  #+x8664-target 4
+  #+ppc-target 8)
+
+(defparameter *saved-register-names*
+  #+x8632-target nil
+  #+x8664-target #(save3 save2 save1 save0)
+  #+ppc-target #(save7 save6 save5 save4 save3 save2 save1 save0))
+
+(defun frame-function (frame context)
+  "Returns the function using the frame, and pc offset within the function, if known"
+  (declare (ignore context))
+  (cfp-lfun (require-type frame 'integer)))
+
+(defun frame-supplied-arguments (frame context &key (unknown-marker (%unbound-marker)))
+  "Return a list of supplied arguments to the call which opened this frame, as best we can reconstruct it"
+  (multiple-value-bind (lfun pc) (cfp-lfun frame)
+    (multiple-value-bind (args valid) (supplied-argument-list context frame lfun pc)
+      (if (not valid)
+        unknown-marker
+        (if (eq unknown-marker (%unbound-marker))
+          args
+          (substitute unknown-marker (%unbound-marker) args))))))
+
+(defun frame-named-variables (frame context &key (unknown-marker (%unbound-marker)))
+  "Returns an alist of (NAME . VALUE) of all named variables in this frame."
+  (multiple-value-bind (lfun pc) (cfp-lfun frame)
+    (multiple-value-bind (args locals) (arguments-and-locals context frame lfun pc unknown-marker)
+      (if (eq unknown-marker (%unbound-marker))
+        (append args locals)
+        (substitute unknown-marker (%unbound-marker) (append args locals))))))
+
+
+(defun frame-arguments-and-locals (frame context &key unknown-marker)
+  "Return two values, the arguments and the locals, known for this frame, as alists of (name . value)"
+  (multiple-value-bind (lfun pc) (cfp-lfun frame)
+    (arguments-and-locals context frame lfun pc unknown-marker)))
+
+;;; Returns three values: (ARG-VALUES TYPES NAMES), solely for the benefit
+;;; of the FRAME-ARGUMENTS function in SLIME's swank-openmcl.lisp.
+;;; ARG-VALUES is a list of the values of the args supplied to the function
+;;; TYPES is a list of (for bad historical reasons) strings .describing
+;;;   whether they're "required", "optional", etc.  SLIME only really
+;;;   cares about whether this is equal to "keyword" or not.
+;;; NAMES is a list of symbols which name the args.
+;; 7/13/2009: This is now deprecated.  Use frame-supplied-arguments.
+(defun frame-supplied-args (frame lfun pc child context)
+  (declare (ignore child))
+  (if (null pc)
+    (values nil nil nil)
+    (if (<= pc target::arg-check-trap-pc-limit)
+      (values (arg-check-call-arguments frame lfun) nil nil)
+      (multiple-value-bind (arglist valid) (arglist-from-map lfun)
+        (if (not valid)
+          (values nil nil nil)
+          (let* ((args (arguments-and-locals context frame lfun pc))
+                 (state :required))
+            (collect ((arg-values)
+                      (types)
+                      (names))
+              (dolist (arg arglist)
+                (if (or (member arg lambda-list-keywords)
+                        (eq arg '&lexpr))
+                  (setq state arg)
+                  (let* ((pair (pop args)))
+                    (case state
+                      (&lexpr
+                         (with-list-from-lexpr (rest (cdr pair))
+                           (dolist (r rest) (arg-values r) (names nil) (types nil)))
+                         (return))
+                      (&rest
+                         (dolist (r (cdr pair)) (arg-values r) (names nil) (types nil))
+                         (return))
+                      (&key
+                         (arg-values arg)
+                         (names nil)
+                         (types nil)))
+                    (let* ((value (cdr pair)))
+                      (if (eq value (%unbound-marker))
+                        (return))
+                      (names (car pair))
+                      (arg-values value)
+                      (types nil)))))
+              (values (arg-values) (types) (names)))))))))
+
+
+#|
+(setq *save-local-symbols* t)
+
+(defun test (flip flop &optional bar)
+  (let ((another-one t)
+        (bar 'quux))
+    (break)))
+
+(test '(a b c d) #\a)
+
+(defun closure-test (flim flam)
+  (labels ((inner (x)
+              (let ((ret (list x flam)))
+                (break))))
+    (inner flim)
+    (break)))
+
+(closure-test '(a b c) 'quux)
+
+(defun set-test (a b)
+  (break)
+  (+ a b))
+
+(set-test 1 'a)
+
+||#
+
+
+(provide 'backtrace-lds)
+
+; End of backtrace-lds.lisp
Index: /branches/new-random/lib/backtrace.lisp
===================================================================
--- /branches/new-random/lib/backtrace.lisp	(revision 13309)
+++ /branches/new-random/lib/backtrace.lisp	(revision 13309)
@@ -0,0 +1,702 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; backtrace.lisp
+;;; low-level support for stack-backtrace printing
+
+(in-package "CCL")
+
+#+ppc-target (require "PPC-BACKTRACE")
+#+x86-target (require "X86-BACKTRACE")
+
+
+(defparameter *backtrace-show-internal-frames* nil)
+(defparameter *backtrace-print-level* 2)
+(defparameter *backtrace-print-length* 5)
+
+(defparameter *backtrace-format* #+ccl-0711 :direct #-ccl-0711 :traditional
+  "If :TRADITIONAL, shows calls to non-toplevel functions using FUNCALL, and shows frame address values.
+   If :DIRECT, uses a more streamlined format.")
+
+(defun context-for-suspended-tcr (tcr)
+  (let ((frame-ptr (%tcr-frame-ptr tcr)))
+    (new-backtrace-info nil
+                        frame-ptr ;; youngest - not used
+                        frame-ptr ;; oldest - not used
+                        tcr
+                        nil       ;; condition - not used
+                        frame-ptr ;; current
+                        #+ppc-target *fake-stack-frames*
+                        #+x86-target frame-ptr
+                        (%fixnum-ref tcr target::tcr.db-link)
+                        0         ;; break level - not used
+                        )))
+  
+
+(defun backtrace-as-list (&key
+                          context
+                          process
+                          origin
+                          (count target::target-most-positive-fixnum)
+                          (start-frame-number 0)
+                          (print-level *backtrace-print-level*)
+                          (print-length *backtrace-print-length*)
+                          (show-internal-frames *backtrace-show-internal-frames*))
+  "Returns a list representing the backtrace.
+Each element in the list is a list that describes the call in one stack frame:
+   (function arg1 arg2 ...)
+The arguments are represented by strings, the function is a symbol or a function
+object."
+  (let* ((*backtrace-print-level* print-level)
+         (*backtrace-print-length* print-length)
+         (*backtrace-format* :list)
+         (result nil))
+    (map-call-frames (lambda (p context)
+                       (multiple-value-bind (lfun pc) (cfp-lfun p)
+                         (push (if lfun
+                                 (backtrace-call-arguments context p lfun pc)
+                                 "?????")
+                               result)))
+                     :context context
+                     :process process
+                     :origin origin
+                     :count count
+                     :start-frame-number start-frame-number
+                     :test (and (not show-internal-frames) 'function-frame-p))
+    (nreverse result)))
+
+(defun print-call-history (&key context
+                                process
+                                origin
+                                (detailed-p t)
+                                (count target::target-most-positive-fixnum)
+                                (start-frame-number 0)
+                                (stream *debug-io*)
+                                (print-level *backtrace-print-level*)
+                                (print-length *backtrace-print-length*)
+                                (show-internal-frames *backtrace-show-internal-frames*)
+                                (format *backtrace-format*))
+  (let ((*backtrace-print-level* print-level)
+        (*backtrace-print-length* print-length)
+        (*backtrace-format* format)
+        (*standard-output* stream)
+        (*print-circle* nil)
+        (frame-number (or start-frame-number 0)))
+    (map-call-frames (lambda (p context)
+                       (multiple-value-bind (lfun pc) (cfp-lfun p)
+                         (unless (and (typep detailed-p 'fixnum)
+                                      (not (= (the fixnum detailed-p) frame-number)))
+                           (%show-stack-frame-label frame-number p context lfun pc detailed-p)
+                           (when detailed-p
+                             (if (or (eq detailed-p :raw) (null lfun))
+                               (%show-stack-frame p context lfun pc)
+                               (%show-args-and-locals p context lfun pc)))
+                           (incf frame-number))))
+                     :context context
+                     :process process
+                     :origin origin
+                     :count count
+                     :start-frame-number start-frame-number
+                     :test (and (not show-internal-frames) 'function-frame-p))
+    (values)))
+
+(defun function-frame-p (p context)
+  (and (not (catch-csp-p p context)) (cfp-lfun p)))
+
+(defun map-call-frames (fn &key context
+                           process
+			   origin
+                           (count target::target-most-positive-fixnum)
+			   (start-frame-number 0)
+                           test)
+  (when (and context process (neq (bt.tcr context) (process-tcr process)))
+    (error "Context ~s doesn't correspond to the process ~s" context process))
+  (let ((tcr (cond (context (bt.tcr context))
+                   (process (process-tcr process))
+                   (t (%current-tcr))))
+        (*print-catch-errors* t)
+        (*signal-printing-errors* nil))
+    (if (eq tcr (%current-tcr))
+      (%map-call-frames-internal fn context (or origin (%get-frame-ptr)) count start-frame-number test)
+      (unwind-protect
+	   (progn
+	     (%suspend-tcr tcr)
+             (when (null context)
+               (setq context (context-for-suspended-tcr tcr)))
+             (%map-call-frames-internal fn context (or origin (bt.current context))  count start-frame-number test))
+	(%resume-tcr tcr))))
+  nil)
+
+; RAW case
+(defun %show-stack-frame (p context lfun pc)
+  (handler-case
+      (multiple-value-bind (count vsp parent-vsp) (count-values-in-frame p context)
+	(declare (fixnum count))
+	(dotimes (i count)
+	  (multiple-value-bind (var type name) 
+			       (nth-value-in-frame p i context lfun pc vsp parent-vsp)
+	    (format t "~&  ~D " i)
+	    (when name (format t "~s" name))
+	    (let* ((*print-length* *backtrace-print-length*)
+		   (*print-level* *backtrace-print-level*))
+	      (format t ": ~s" var))
+	    (when type (format t " (~S)" type)))))
+    (error () (format t "#<error printing frame>")))
+  (terpri)
+  (terpri))
+
+(defun %show-args-and-locals (p context lfun pc)
+  (handler-case
+      (let* ((unavailable (cons nil nil)))
+	(multiple-value-bind (args locals) (arguments-and-locals context p lfun pc unavailable)
+          (case *backtrace-format*
+            (:direct
+               (format t "~&     Arguments: ~:s" (arglist-from-map lfun)))
+            (t (format t "~&  ~s" (arglist-from-map lfun))))
+	  (let* ((*print-length* *backtrace-print-length*)
+		 (*print-level* *backtrace-print-level*))
+	    (flet ((show-pair (pair prefix)
+		     (destructuring-bind (name . val) pair
+		       (format t "~&~a~s: " prefix name)
+		       (if (eq val unavailable)
+			 (format t "#<Unavailable>")
+			 (format t "~s" val)))))
+              (case *backtrace-format*
+                (:direct
+                   (when args
+                     (dolist (arg args)
+                       (show-pair arg "       ")))
+                   (when locals
+                     ;; This shows all bindings (including specials), but help on debugger
+                     ;; commands refers to "locals", so say both words...
+                     (format t "~&     Local bindings:")
+                     (dolist (loc locals)
+                       (show-pair loc "       "))))
+                (t
+                   (dolist (arg args)
+                     (show-pair arg "   "))
+                   (terpri)
+                   (terpri)
+                   (dolist (loc locals)
+                     (show-pair loc "  "))))))))
+    (error () (format t "#<error printing args and locals>")))
+  (terpri)
+  (terpri))
+
+
+(defun backtrace-call-arguments (context cfp lfun pc)
+  (nconc (let* ((name (function-name lfun)))
+           (if (function-is-current-definition? lfun)
+             (list name)
+             (case *backtrace-format*
+               (:direct
+                  (list (format nil "~s" (or name lfun))))
+               (:list
+                  (list 'funcall (format nil "~s" (or name lfun))))
+               (t (list 'funcall `(function ,(concatenate 'string "#<" (%lfun-name-string lfun) ">")))))))
+         (backtrace-supplied-args context cfp lfun pc)))
+
+(defun backtrace-supplied-args (context frame lfun pc)
+  (multiple-value-bind (args valid) (supplied-argument-list context frame lfun pc)
+    (if (not valid)
+      '("???")    
+      (loop for arg in args
+            collect (if (eq arg (%unbound-marker))
+                      "?"
+                      (let* ((*print-length* *backtrace-print-length*)
+                             (*print-level* *backtrace-print-level*))
+                        (format nil "~s" arg)))))))
+
+;;; Return a list of "interesting" frame addresses in context, most
+;;; recent first.
+(defun %stack-frames-in-context (context &optional (include-internal *backtrace-show-internal-frames*))
+  (collect ((frames))
+    (do* ((p (bt.youngest context) (parent-frame p context))
+          (q (bt.oldest context)))
+         ((eql p q) (frames))
+      (when (or (not (catch-csp-p p context)) include-internal)
+        (when (or (cfp-lfun p) include-internal)
+          (frames p))))))
+
+(defun %map-call-frames-internal (fn context origin count skip-initial test)
+  (when (null skip-initial) (setq skip-initial 0))
+  (when (null count) (setq count target::target-most-positive-fixnum))
+  (unless (eq (last-frame-ptr context origin) (last-frame-ptr context))
+    (error "Origin ~s is not in the stack of ~s" origin context))
+  (let ((q (last-frame-ptr context))
+        (frame-number 0))
+    (do ((p origin (parent-frame p context)))
+        ((or (null p) (eq p q) (%stack< q p context) (<= count 0)) nil)
+      (when (or (null test) (funcall test p context))
+        (when (<= skip-initial frame-number)
+          (funcall fn p context)
+          (decf count))
+        (incf frame-number)))))
+
+(defun %show-stack-frame-label (frame-number p context lfun pc detailed-p)
+  (case *backtrace-format*
+    (:direct
+       (let ((call (backtrace-call-arguments context p lfun pc)))
+         (format t "~&~3D: ~a ~a~@d~:[~; [Exception]~]"
+                 frame-number
+                 (if lfun
+                   (if detailed-p (car call) call)
+                   "<non-function frame>")
+                 "at pc "
+                 pc
+                 (exception-frame-p p))))
+    (t (format t "~&~c(~x) : ~D ~a ~d"
+                      (if (exception-frame-p p)  #\* #\space)
+                      (index->address p) frame-number
+                      (if lfun (backtrace-call-arguments context p lfun pc))
+                      pc))))
+
+
+(defun %access-lisp-data (vstack-index)
+  (%fixnum-ref vstack-index))
+
+(defun %store-lisp-data (vstack-index value)
+  (setf (%fixnum-ref vstack-index) value))
+
+(defun closed-over-value (data)
+  (if (closed-over-value-p data)
+    (uvref data 0)
+    data))
+
+(defun set-closed-over-value (value-cell value)
+  (setf (uvref value-cell 0) value))
+
+
+
+;;; Act as if VSTACK-INDEX points at some lisp data & return that data.
+(defun access-lisp-data (vstack-index)
+  (closed-over-value (%access-lisp-data vstack-index)))
+
+(defun find-local-name (cellno lfun pc)
+  (let* ((n cellno))
+    (when lfun
+      (multiple-value-bind (mask where) (registers-used-by lfun pc)
+        (if (and where (< (1- where) n (+ where (logcount mask))))
+          (let ((j *saved-register-count*))
+            (decf n where)
+            (loop (loop (if (logbitp (decf j) mask) (return)))
+                  (if (< (decf n) 0) (return)))
+            (values (format nil "saved ~a" (aref *saved-register-names* j))
+                    nil))
+          (multiple-value-bind (nreq nopt restp nkeys junk optinitp junk ncells nclosed)
+                               (if lfun (function-args lfun))
+            (declare (ignore junk optinitp))
+            (if nkeys (setq nkeys (+ nkeys nkeys)))
+            (values
+             (if (and ncells (< n ncells))
+               (if (< n nclosed)
+                 :inherited
+                 (if (< (setq n (- n nclosed)) nreq)
+                   "required"
+                   (if (< (setq n (- n nreq)) nopt)
+                     "optional"
+                     (progn
+                       (setq n (- n nopt))
+                       (progn
+                         (if (and nkeys (< n nkeys))
+                           (if (not (logbitp 0 n)) ; a keyword
+                             "keyword"
+                             "key-supplied-p")
+                           (progn
+                             (if nkeys (setq n (- n nkeys)))
+                             (if (and restp (zerop n))
+                               "rest"
+                               "opt-supplied-p")))))))))
+             (match-local-name cellno (function-symbol-map lfun) pc))))))))
+
+(defun map-entry-value (context cfp lfun pc idx unavailable)
+  (declare (fixnum pc idx))
+  (let* ((info (function-symbol-map lfun)))
+    (if (null info)
+      unavailable
+      (let* ((addrs (cdr info))
+             (i (* 3 idx))
+             (addr (svref addrs i))
+             (startpc (svref addrs (the fixnum (+ i 1))))
+             (endpc (svref addrs (the fixnum (+ i 2)))))
+        (declare (fixnum i addr startpc endpc))
+        (if (or (< pc startpc)
+                (>= pc endpc))
+          unavailable
+          (let* ((value (if (= #o77 (ldb (byte 6 0) addr))
+                          (raw-frame-ref cfp context (ash addr (- (+ target::word-shift 6)))
+                                         unavailable)
+                          (find-register-argument-value context cfp addr unavailable))))
+            (if (typep value 'value-cell)
+              (uvref value 0)
+              value)))))))
+
+;;; Returns non-nil on success (not newval)
+(defun set-map-entry-value (context cfp lfun pc idx newval)
+  (declare (fixnum pc idx))
+  (let* ((unavailable (cons nil nil))
+         (value (map-entry-value context cfp lfun pc idx unavailable)))
+    (if (eq value unavailable)
+      nil
+      (if (typep value 'value-cell)
+        (progn (setf (uvref value 0) newval) t)
+
+        (let* ((addrs (cdr (function-symbol-map lfun)))
+               (addr (svref addrs (the fixnum (* 3 idx)))))
+          (declare (fixnum  addr))
+          (if (= #o77 (ldb (byte 6 0) addr))
+            (raw-frame-set cfp context (ash addr (- (+ target::word-shift 6))) newval)
+            (set-register-argument-value context cfp addr newval))
+          t)))))
+
+          
+(defun argument-value (context cfp lfun pc name &optional (quote t))
+  (declare (fixnum pc))
+  (let* ((info (function-symbol-map lfun))
+         (unavailable (%unbound-marker)))
+    (if (null info)
+      unavailable
+      (let* ((names (car info))
+             (addrs (cdr info)))
+        (do* ((nname (1- (length names)) (1- nname))
+              (naddr (- (length addrs) 3) (- naddr 3)))
+             ((or (< nname 0) (< naddr 0)) unavailable)
+          (declare (fixnum nname naddr))
+          (when (eq (svref names nname) name)
+            (let* ((value
+                    (let* ((addr (svref addrs naddr))
+                           (startpc (svref addrs (the fixnum (1+ naddr))))
+                           (endpc (svref addrs (the fixnum (+ naddr 2)))))
+                      (declare (fixnum addr startpc endpc))
+                      (if (or (< pc startpc)
+                              (>= pc endpc))
+                        unavailable
+                        (if (= #o77 (ldb (byte 6 0) addr))
+                          (raw-frame-ref cfp context (ash addr (- (+ target::word-shift 6)))
+                                         unavailable)
+                          (find-register-argument-value context cfp addr unavailable))))))
+              (if (typep value 'value-cell)
+                (setq value (uvref value 0)))
+              (if (or (not quote) (self-evaluating-p value))
+                (return value)
+                (return (list 'quote value))))))))))
+
+
+
+(defun raw-frame-ref (cfp context index bad)
+  (%raw-frame-ref cfp context index bad))
+
+(defun raw-frame-set (cfp context index new)
+  (%raw-frame-set cfp context index new))
+  
+(defun find-register-argument-value (context cfp regval bad)
+  (%find-register-argument-value context cfp regval bad))
+
+(defun set-register-argument-value (context cfp regval newval)
+  (%set-register-argument-value context cfp regval newval))
+
+    
+
+(defun dbg-form (frame-number)
+  (when *break-frame*
+    (let* ((cfp (nth-raw-frame frame-number *break-frame* nil)))
+      (if (and cfp (not (catch-csp-p cfp nil)))
+        (multiple-value-bind (function pc)
+            (cfp-lfun cfp)
+          (if (and function
+                   (function-is-current-definition? function))
+            (block %cfp-form
+              (collect ((form))
+                (multiple-value-bind (nreq nopt restp keys allow-other-keys
+                                           optinit lexprp ncells nclosed)
+                    (function-args function)
+                  (declare (ignore ncells))
+                  (unless (or lexprp restp (> 0 nclosed) (> 0 nopt) keys allow-other-keys
+                              optinit)
+                    (let* ((name (function-name function)))
+                      (multiple-value-bind (arglist win)
+                          (arglist-from-map function)
+                      (when (and win name (symbolp name))
+                        (form name)
+                        (dotimes (i nreq)
+                          (let* ((val (argument-value nil cfp function pc (pop arglist))))
+                            (if (closed-over-value-p val)
+                              (setq val (%svref val target::value-cell.value-cell)))
+                            (if (eq val (%unbound-marker))
+                              (return-from %cfp-form nil))
+                            (form val))))))))
+                (form)))))))))
+
+(defun function-args (lfun)
+  "Returns 9 values, as follows:
+     req = number of required arguments
+     opt = number of optional arguments
+     restp = t if rest arg
+     keys = number of keyword arguments or NIL if &key not mentioned
+     allow-other-keys = t if &allow-other-keys present
+     optinit = t if any optional arg has non-nil default value or supplied-p
+               variable
+     lexprp = t if function is a lexpr, in which case all other values are
+              undefined.
+     ncells = number of stack frame cells used by all arguments.
+     nclosed = number of inherited values (now counted distinctly from required)
+     All numeric values (but ncells) are mod 64."
+  (let* ((bits (lfun-bits lfun))
+         (req (ldb $lfbits-numreq bits))
+         (opt (ldb $lfbits-numopt bits))
+         (restp (logbitp $lfbits-rest-bit bits))
+         (keyvect (lfun-keyvect lfun))
+         (keys (and keyvect (length keyvect)))
+         (allow-other-keys (logbitp $lfbits-aok-bit bits))
+         (optinit (logbitp $lfbits-optinit-bit bits))
+         (lexprp (logbitp $lfbits-restv-bit bits))
+         (nclosed (ldb $lfbits-numinh bits)))
+    (values req opt restp keys allow-other-keys optinit lexprp
+            (unless (or lexprp)
+              (+ req opt (if restp 1 0) (if keys (+ keys keys) 0)
+                 (if optinit opt 0) nclosed))
+            nclosed)))
+
+;;; If we can tell reliably, return the function's minimum number of
+;;; non-inherited arguments, the maximum number of such arguments (or NIL),
+;;; and the actual number of such arguments.  We "can't tell" if either
+;;; of the arguments to this function are null, and we can't tell reliably
+;;; if any of the lfbits fields are full.
+(defun min-max-actual-args (fn nargs)
+  (let* ((lfbits (if (and fn nargs)
+		   (lfun-bits fn)
+		   -1))
+	 (raw-req (ldb $lfbits-numreq lfbits))
+	 (raw-opt (ldb $lfbits-numopt lfbits))
+	 (raw-inh (ldb $lfbits-numinh lfbits)))
+    (declare (fixnum raw-req raw-opt raw-inh))
+    (if (or (eql raw-req (1- (ash 1 (byte-size $lfbits-numreq))))
+	    (eql raw-opt (1- (ash 1 (byte-size $lfbits-numopt))))
+	    (eql raw-inh (1- (ash 1 (byte-size $lfbits-numinh)))))
+      (values nil nil nil)
+      (values raw-req
+	      (unless (or (lfun-keyvect fn)
+			  (logbitp $lfbits-rest-bit lfbits)
+			  (logbitp $lfbits-restv-bit lfbits))
+		(+ raw-req raw-opt))
+	      (- nargs raw-inh)))))
+
+
+
+(defun closed-over-value-p (value)
+  (eql target::subtag-value-cell (typecode value)))
+
+
+(defun variables-in-scope (lfun pc)
+  ;; Return a list of all symbol names "in scope" in the function lfun
+  ;; at relative program counter PC, using the function's symbol map.
+  ;; The list will be ordered so that least-recent bindings appear first.
+  ;; Return a list of the matching symbol map entries as a second value
+  (when pc
+    (locally (declare (fixnum pc))
+      (let* ((map (function-symbol-map lfun))
+             (names (car map))
+             (info (cdr map)))
+        (when map
+          (let* ((vars ())
+                 (indices ()))
+            (dotimes (i (length names) (values vars indices))
+              (let* ((start-pc (aref info (1+ (* 3 i))))
+                     (end-pc (aref info (+ 2 (* 3 i)))))
+                (declare (fixnum start-pc end-pc))
+                (when (and (>= pc start-pc)
+                           (< pc end-pc))
+                  (push i indices)
+                  (push (svref names i) vars))))))))))
+
+
+(defun arg-value (context cfp lfun pc unavailable name)
+  (multiple-value-bind (vars map-indices) (variables-in-scope lfun pc)
+    (multiple-value-bind (valid req opt rest keys)
+        (arg-names-from-map lfun pc)
+      (if valid
+        (let* ((nargs (+ (length req) (length opt) (if rest 1 0) (length keys)))
+               (pos (position name vars)))
+          (if (and pos (< pos nargs))
+            (map-entry-value context cfp lfun pc (nth pos map-indices) unavailable)
+            unavailable))
+        unavailable))))
+
+(defun local-value (context cfp lfun pc unavailable name)
+  (multiple-value-bind (vars map-indices) (variables-in-scope lfun pc)
+    (multiple-value-bind (valid req opt rest keys)
+        (arg-names-from-map lfun pc)
+      (if valid
+        (let* ((nargs (+ (length req) (length opt) (if rest 1 0) (length keys)))
+               (names (nthcdr nargs vars))
+               (indices (nthcdr nargs map-indices))
+               (pos (if (typep name 'unsigned-byte)
+                      name
+                      (position name names :from-end t))))
+          (if pos
+            (map-entry-value context cfp lfun pc (nth pos indices) unavailable)
+            unavailable))
+        unavailable))))
+
+(defun set-arg-value (context cfp lfun pc name new)
+  (multiple-value-bind (vars map-indices) (variables-in-scope lfun pc)
+    (multiple-value-bind (valid req opt rest keys)
+        (arg-names-from-map lfun pc)
+      (if valid
+        (let* ((nargs (+ (length req) (length opt) (if rest 1 0) (length keys)))
+               (pos (position name vars)))
+          (when (and pos (< pos nargs))
+            (set-map-entry-value context cfp lfun pc (nth pos map-indices) new)))))))
+
+(defun set-local-value (context cfp lfun pc name new)
+  (multiple-value-bind (vars map-indices) (variables-in-scope lfun pc)
+    (multiple-value-bind (valid req opt rest keys)
+        (arg-names-from-map lfun pc)
+      (if valid
+        (let* ((nargs (+ (length req) (length opt) (if rest 1 0) (length keys)))
+               (names (nthcdr nargs vars))
+               (indices (nthcdr nargs map-indices))
+               (pos (if (typep name 'unsigned-byte)
+                      name
+                      (position name names :from-end t))))
+          (if (and pos (< pos nargs))
+            (set-map-entry-value context cfp lfun pc (nth pos indices) new)))))))
+
+
+(defun arguments-and-locals (context cfp lfun pc &optional unavailable)
+  (multiple-value-bind (vars map-indices) (variables-in-scope lfun pc)
+    (collect ((args)
+              (inherited-indices)
+              (inherited-vars)
+              (locals))
+      (multiple-value-bind (valid req opt rest keys)
+          (arg-names-from-map lfun pc)
+        (when valid
+          (let* ((numinh (ldb $lfbits-numinh (lfun-bits lfun))))
+            (dotimes (i numinh)
+              (inherited-indices (pop map-indices))
+              (inherited-vars (pop vars))))
+          (let* ((nargs (+ (length req) (length opt) (if rest 1 0) (length keys)))
+                 (nlocals (- (length vars) nargs))
+                 (local-vars (append (nthcdr nargs vars) (inherited-vars)))
+                 (local-indices (append (nthcdr nargs map-indices) (inherited-indices)))
+                 (arg-vars (if (<= nlocals 0) vars (nbutlast vars nlocals)))
+                 (arg-indices (if (<= nlocals 0) map-indices (nbutlast map-indices nlocals))))
+            (flet ((get-arg-value (name)
+                     (let* ((pos (position name arg-vars :test #'eq)))
+                       (when pos
+                         (args (cons name (map-entry-value context cfp lfun pc (nth pos arg-indices) unavailable))))))
+                   (get-local-value (name)
+                     (when name
+                       (locals (cons name (map-entry-value context cfp lfun pc (pop local-indices) unavailable))))))
+              (dolist (name req)
+                (get-arg-value name))
+              (dolist (name opt)
+                (get-arg-value name))
+              (when rest
+                (get-arg-value rest))
+              (dolist (name keys)
+                (get-arg-value name))
+              (dolist (name local-vars)
+                (get-local-value name)))))
+           (values (args) (locals))))))
+
+;; Return list of supplied arguments, as best we can reconstruct it.
+(defun supplied-argument-list (context frame lfun pc)
+  (if (null pc)
+    (values nil nil)
+    (if (<= pc target::arg-check-trap-pc-limit)
+      (values (arg-check-call-arguments frame lfun) t)
+      (multiple-value-bind (params valid) (arglist-from-map lfun)
+        (if (not valid)
+          (values nil nil)
+          (let* ((args (arguments-and-locals context frame lfun pc)) ;overkill, but will do.
+                 (state :required)
+                 (result ()))
+            (dolist (param params)
+              (if (or (member param lambda-list-keywords) (eq param '&lexpr))
+                (setq state param)
+                (let* ((pair (pop args))
+                       (value (cdr pair)))
+                  (case state
+                    (&lexpr
+                     (with-list-from-lexpr (rest value)
+                       (dolist (r rest) (push r result)))
+                     (return))
+                    (&rest
+                     (dolist (r value) (push r result))
+                     (return))
+                    (&key (push param result)))
+                  (push value result))))
+            (values (nreverse result) t)))))))
+
+
+(defun safe-cell-value (val)
+  val)
+
+(defun closure-closed-over-values (closure)
+  (when (typep closure 'compiled-lexical-closure)
+    (let* ((inner (closure-function closure))
+           (nclosed (nth-value 8 (function-args inner)))
+           (names (car (function-symbol-map inner))))
+      (when nclosed
+        (collect ((cells))
+          (do* ((i (1- (length names)) (1- i))
+                (k 0 (1+ k))
+                (idx 2 (1+ idx)))
+               ((= k nclosed) (reverse (cells)))
+            (let* ((name (svref names i))
+                   (imm (nth-immediate closure idx)))
+              (cells (list name (if (closed-over-value-p imm)
+                                  (closed-over-value imm)
+                                  imm))))))))))
+
+      
+;;; Find the oldest binding frame that binds the same symbol as
+;;; FRAME in context.  If found, return the saved value of that
+;;; binding, else the value of the symbol in the context's thread.
+(defun oldest-binding-frame-value (context frame)
+  (let* ((oldest nil)
+         (binding-index (%fixnum-ref frame (ash 1 target::fixnum-shift))))
+    (do* ((db (db-link context) (%fixnum-ref db 0)))
+         ((eq frame db)
+          (if oldest
+            (%fixnum-ref oldest (ash 2 target::fixnum-shift))
+            (let* ((symbol (binding-index-symbol binding-index)))
+              (if context
+                (symbol-value-in-tcr symbol (bt.tcr context))
+                (%sym-value symbol)))))
+      (if (eq (%fixnum-ref db (ash 1 target::fixnum-shift)) binding-index)
+        (setq oldest db)))))
+
+(defun (setf oldest-binding-frame-value) (new context frame)
+  (let* ((oldest nil)
+         (binding-index (%fixnum-ref frame (ash 1 target::fixnum-shift))))
+    (do* ((db (db-link context) (%fixnum-ref db 0)))
+         ((eq frame db)
+          (if oldest
+            (setf (%fixnum-ref oldest (ash 2 target::fixnum-shift)) new)
+            (let* ((symbol (binding-index-symbol binding-index)))
+              (if context
+                (setf (symbol-value-in-tcr symbol (bt.tcr context)) new)
+                (%set-sym-value symbol new)))))
+      (if (eq (%fixnum-ref db (ash 1 target::fixnum-shift)) binding-index)
+        (setq oldest db)))))
+    
+
+
+;;; End of backtrace.lisp
Index: /branches/new-random/lib/case-error.lisp
===================================================================
--- /branches/new-random/lib/case-error.lisp	(revision 13309)
+++ /branches/new-random/lib/case-error.lisp	(revision 13309)
@@ -0,0 +1,70 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;I wanted a read that would not error even when given a #<
+; and also allow backspace and such.
+(defun read-line-no-error (&optional (stream *standard-output*) &aux result)
+  (ignore-errors
+     (setq result (read-from-string (read-line stream) nil))
+     (return-from read-line-no-error (values result t)))
+  (values nil nil))
+
+
+
+;;;; Assert & Check-Type
+
+;;; Assert-Value-Prompt  --  Internal
+;;;
+;;;    Prompt for a new value to set a place to.   We do a read-line,
+;;; and if there is anything there, we eval it and return the second
+;;; value true, otherwise it is false.
+;;;
+(defun assertion-value-prompt (place)
+  (let* ((nvals (length (nth-value 2 (get-setf-method-multiple-value place))))
+         (vals nil))
+    (dotimes (i nvals)
+      (if (eq nvals 1)
+        (format *query-io* "Value for ~S: " place)
+        (format *query-io* "Value ~D for ~S: " i place))
+      (let* ((line (read-line *query-io*))
+             (object  (read-from-string line nil *eof-value*)))
+        (if (eq object *eof-value*)
+            (return)
+            (push (eval object) vals))))
+    (values (nreverse vals) (not (null vals)))))
+
+(defun %assertion-failure (setf-places-p test-form string &rest condition-args)
+  (cerror 
+   (if setf-places-p 
+     "allow some places to be set and test the assertion again."
+     "test the assertion again.")
+   (cond
+    ((stringp string)
+     (make-condition 'simple-error
+                     :format-control string
+                     :format-arguments  condition-args))
+    ((null string)
+     (make-condition 'simple-error
+                     :format-control "Failed assertion: ~S"
+                     :format-arguments (list test-form)))
+    ((typep string 'condition)
+     (when  condition-args (error "No args ~S allowed with a condition ~S"  condition-args string))
+     string)
+    (t (apply #'make-condition string  condition-args)))))
+
Index: /branches/new-random/lib/ccl-export-syms.lisp
===================================================================
--- /branches/new-random/lib/ccl-export-syms.lisp	(revision 13309)
+++ /branches/new-random/lib/ccl-export-syms.lisp	(revision 13309)
@@ -0,0 +1,951 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (export				;remember "CCL" at end of list
+					;setq %ccl-package-export-syms
+   '(
+     local
+     set-local
+     @
+     *elements-per-buffer*
+     save-application
+     def-load-pointers
+     *save-exit-functions*
+     *restore-lisp-functions*
+     *lisp-cleanup-functions*
+     *lisp-startup-functions*
+     defloadvar
+     defstatic
+     *break-on-warnings*
+					; misc
+     record-source-file
+     get-source-files
+     edit-definition
+     edit-definition-p
+     *loading-file-source-file*
+     find-definition-sources
+     define-definition-type
+     definition-type
+     definition-type-name
+     *save-source-locations*
+     function-source-note
+     source-note
+     source-note-p
+     source-note-filename
+     source-note-start-pos
+     source-note-end-pos
+     source-note-text
+     ensure-source-note-text
+     *record-pc-mapping*
+     find-source-note-at-pc
+     caller-functions
+     *svn-program*
+     
+     show-documentation
+     %set-toplevel
+     toplevel-loop
+     toplevel-function
+     repl-function-name
+     toplevel
+     *listener-prompt-format*
+     cancel
+     catch-cancel
+     throw-cancel
+     *backtrace-on-break*
+     *show-restarts-on-break*
+     print-call-history
+     dbg-form
+     *backtrace-print-level*
+     *backtrace-print-length*
+     *backtrace-show-internal-frames*
+     *backtrace-format*
+     map-call-frames
+     frame-function
+     frame-supplied-arguments
+     frame-named-variables
+     apply-in-frame
+     *quit-on-eof*
+     *quit-interrupt-hook*
+     *break-hook*
+     *top-error-frame*
+     *select-interactive-process-hook*
+     interrupt-signal-condition
+     macroexpand-all
+     compiler-macroexpand
+     compiler-macroexpand-1
+     compile-user-function
+     uncompile-function
+     report-compiler-warning
+     compiler-warning
+     style-warning
+     compiler-warning-source-note
+     compiler-warning-function-name
+     *merge-compiler-warnings*
+     abort-break
+     *trace-print-level*
+     *trace-print-length*
+     *trace-bar-frequency*
+     trace-function
+     *ignore-extra-close-parenthesis*
+     advise
+     unadvise
+     advisedp
+     nfunction
+     function-name
+     setf-function-p
+     setf-function-spec-name
+     name-of
+
+     assq
+     bignump
+     bitp
+     constant-symbol-p
+     proclaimed-special-p
+     delq
+     fixnump
+     quit
+     include
+     memq
+     nremove
+					;put
+     ratiop
+     structure-typep
+     structurep
+     type-specifier-p
+     displaced-array-p
+     without-interrupts
+     with-interrupts-enabled
+     true
+     false
+     neq
+     whitespacep
+     *print-structure*
+     *print-simple-vector*
+     *print-simple-bit-vector*
+     *print-string-length*
+     *print-abbreviate-quote*
+     *signal-printing-errors*
+     unignore
+     *warn-if-redefine-kernel*
+     without-duplicate-definition-warnings
+     require-type
+     dovector
+     debugging-function-name
+     *make-package-use-defaults*
+     *autoload-lisp-package*
+     tyo
+     tyi
+     untyi
+     compiled-lexical-closure		; the type name
+     lsh
+
+     ;; Arguments, image name, etc.
+     *command-line-argument-list*
+     *unprocessed-command-line-arguments*
+     *heap-image-name*
+
+					; The MOP
+     accessor-method-slot-definition
+     add-dependent
+     add-direct-method
+     add-direct-subclass
+     add-method
+     class-default-initargs
+     class-direct-default-initargs
+     class-direct-slots
+     class-direct-subclasses
+     class-direct-superclasses
+     class-finalized-p
+     class-precedence-list
+     class-prototype
+     class-slots
+     compute-applicable-methods
+     compute-applicable-methods-using-classes
+     compute-class-precedence-list
+     compute-default-initargs
+     compute-discriminating-function
+     compute-effective-method
+     compute-effective-slot-definition
+     compute-slots
+     direct-slot-definition-class
+     effective-slot-definition-class
+     ensure-class
+     ensure-class-using-class
+     ensure-generic-function-using-class
+     eql-specializer
+     eql-specializer-object
+     extract-lambda-list
+     extract-specializer-names
+     finalize-inheritance
+     find-method-combination
+     funcallable-standard-instance-access
+     generic-function-argument-precedence-order
+     generic-function-declarations
+     generic-function-lambda-list
+     generic-function-method-class
+     generic-function-method-combination
+     generic-function-methods
+     generic-function-name
+     intern-eql-specializer
+     make-method-lambda
+     map-dependents
+     method-function
+     method-generic-function
+     method-lambda-list
+     method-name
+     method-specializers
+     method-qualifiers
+     slot-definition-documentation
+     slot-definition-allocation
+     slot-definition-initargs
+     slot-definition-initform
+     slot-definition-initfunction
+     slot-definition-name
+     slot-definition-type
+     slot-definition-readers
+     slot-definition-writers
+     slot-definition-location
+     reader-method-class
+     remove-dependent
+     remove-direct-method
+     remove-direct-subclass
+     remove-method
+     set-funcallable-instance-function
+     slot-boundp-using-class
+     slot-makunbound-using-class
+     slot-value-using-class
+     specializer-direct-generic-functions
+     specializer-direct-methods
+     standard-instance-access
+     update-dependent
+     validate-superclass
+     writer-method-class
+     
+     metaobject
+     long-method-combination
+     short-method-combination
+     standard-accessor-method
+     standard-reader-method
+     standard-writer-method
+     specializer
+
+     funcallable-standard-class
+     funcallable-standard-object
+     forward-referenced-class
+     standard-direct-slot-definition
+     standard-effective-slot-definition
+
+     standard-slot-definition
+     slot-definition
+     effective-slot-definition
+     direct-slot-definition
+     
+     clear-specializer-direct-methods-caches
+     *check-call-next-method-with-args*
+     clear-gf-cache
+     clear-all-gf-caches
+     clear-clos-caches
+
+     method-exists-p
+     method-specializers
+     class-own-wrapper
+     specializer-direct-methods
+     specializer-direct-generic-functions
+     copy-instance
+
+     override-one-method-one-arg-dcode
+     optimize-generic-function-dispatching
+
+     ;; Not MOP
+     string-studlify			;** DO NOT REMOVE, DO NOT DOCUMENT
+     nstring-studlify			;** DO NOT REMOVE, DO NOT DOCUMENT
+
+					; User Options
+     *compile-definitions*
+     *record-source-file*
+     *save-doc-strings*
+     *fasl-save-doc-strings* 
+     *warn-if-redefine*
+     *break-on-errors* 
+     *save-definitions*
+     *fasl-save-definitions* 
+     *save-local-symbols*
+     *fasl-save-local-symbols*
+     *save-arglist-info*
+     *always-eval-user-defvars*
+
+					;These 3 need to be set by the user in order for the correspondingly named
+					;functions to return something other than "unspecified".
+     *short-site-name*
+     *long-site-name*
+     machine-owner
+
+     init-list-default
+     fset
+
+					; Files.
+     mac-default-directory
+     current-directory
+     directory-pathname-p
+     full-pathname
+     temp-pathname
+     create-file
+     create-directory
+     file-create-date
+     set-file-write-date
+     set-file-create-date
+     copy-file
+     lock-file
+     unlock-file
+     file-locked-p
+     directoryp
+
+
+     *module-search-path*
+     *module-provider-functions*
+     *.lisp-pathname*
+     *.fasl-pathname*
+     *pathname-translations-pathname*
+     *default-external-format*
+     *default-line-termination*
+     pathname-encoding-name
+     with-filename-cstrs
+     get-foreign-namestring
+     native-translated-namestring
+     native-to-pathname
+     fasl-concatenate
+     event-ticks
+     set-event-ticks
+     event-dispatch
+     *ticks-per-second*
+
+     *application*
+     arglist
+     arglist-string
+     arglist-to-stream
+     function-args
+
+
+     get-string-from-user
+     with-terminal-input
+     *request-terminal-input-via-break*
+     add-auto-flush-stream
+     remove-auto-flush-stream
+     select-item-from-list
+
+
+					; Low-level
+     %stack-block
+     %vstack-block
+     %get-byte
+     %get-signed-byte
+     %get-unsigned-byte
+     %get-word
+     %get-signed-word
+     %get-unsigned-word
+     %get-long
+     %get-unsigned-long
+     %get-signed-long
+     %%get-signed-longlong
+     %%get-unsigned-longlong
+     %get-fixnum
+     %get-point
+     %get-ptr
+     %get-string
+     %get-cstring
+     %str-from-ptr
+     %get-double-float
+     %get-single-float
+     %inc-ptr
+     %incf-ptr
+     %setf-macptr
+     %null-ptr
+     %null-ptr-p
+     %ptr-eql
+     %ptr-to-int
+     %int-to-ptr
+     %word-to-int
+     %address-of
+     ensure-simple-string
+     %copy-float
+     with-macptrs
+     pointerp
+     macptrp
+     macptr
+     rlet
+     rletz
+     make-record
+     pref
+     rref
+     paref
+     with-cstrs
+     with-encoded-cstrs
+     with-string-vector
+     with-pointer-to-ivector
+     get-encoded-string
+     +null-ptr+
+     free
+     define-entry-point
+     define-callback
+     defcallback
+     ff-call
+     %ff-call
+     %reference-external-entry-point
+     foreign-symbol-entry
+     foreign-symbol-address
+     def-foreign-type
+
+     uvref
+     uvectorp
+     uvsize
+
+     ;;Streams (should be made more complete sometime)
+     input-stream
+     output-stream
+     stream-eofp
+
+     open-file-streams
+     note-open-file-stream
+     remove-open-file-stream
+     clear-open-file-streams
+     stream-line-length
+     string-output-stream
+     truncating-string-stream
+     make-truncating-string-stream
+     stream-rubout-handler
+
+
+					; Tools
+     gc
+     egc
+     egc-enabled-p
+     egc-active-p
+     configure-egc
+     egc-configuration
+     gccounts
+     gctime
+     lisp-heap-gc-threshold
+     use-lisp-heap-gc-threshold
+     set-lisp-heap-gc-threshold
+     gc-retain-pages
+     gc-retaining-pages
+     gc-verbose
+     gc-verbose-p
+     weak-gc-method
+     *trace-max-indent* 
+     *trace-level* 
+     static-cons
+     free-static-conses
+     reserved-static-conses
+
+     population
+     make-population
+     population-type
+     population-contents
+
+     hash-table-weak-p
+
+     compiler-let
+
+
+     COMPILER-POLICY
+     CURRENT-COMPILER-POLICY
+     CURRENT-FILE-COMPILER-POLICY
+     FIND-MACTYPE
+     NEW-COMPILER-POLICY
+     SET-CURRENT-COMPILER-POLICY
+     SET-CURRENT-FILE-COMPILER-POLICY
+     STANDARD-METHOD-COMBINATION
+     STREAM-DEVICE
+     STREAM-DIRECTION
+     *current-process*
+     PROCESS
+     all-processes
+     process-preset
+     process-reset
+     process-reset-and-enable
+     process-enable
+     process-abort
+     process-kill
+     process-interrupt
+     process-name
+     process-run-function
+     make-process
+     process-suspend-count
+     process-serial-number
+     process-initial-form
+     process-whostate
+     process-priority
+     process-total-run-time
+     process-creation-time
+     clear-process-run-time
+     process-resume
+     process-suspend
+     process-exhausted-p
+     let-globally
+     process-wait
+     process-wait-with-timeout
+     process-allow-schedule
+     process-kill-issued
+     process-termination-semaphore
+     process-allocation-quantum
+     default-allocation-quantum
+     current-process-allocation-quantum
+     join-process
+
+     *HOST-PAGE-SIZE*
+     
+     make-lock
+     lock-name
+     with-lock-grabbed
+     grab-lock
+     release-lock
+     try-lock
+     lock
+     read-write-lock
+     lock-not-owner
+
+     lock-acquisition-status
+     clear-lock-acquisition-status
+     lock-acquisition
+     make-lock-acquisition
+
+     semaphore-notification-status
+     clear-semaphore-notification-status
+     semaphore-notification
+     make-semaphore-notification
+     
+     make-read-write-lock
+     with-read-lock
+     with-write-lock
+     symbol-value-in-process
+
+     make-semaphore
+     wait-on-semaphore
+     timed-wait-on-semaphore
+     signal-semaphore
+     semaphore
+
+     process-input-wait
+     process-output-wait
+					; termination
+     terminate-when-unreachable
+     terminate
+     drain-termination-queue
+     cancel-terminate-when-unreachable
+     termination-function
+     *enable-automatic-termination*
+
+     get-fpu-mode
+     set-fpu-mode
+
+					; There's more. Like...
+
+     *listener-indent*
+     *error-print-circle*
+     *break-loop-when-uninterruptable*
+
+     application-error
+     application-name
+     application-init-file
+
+     cwd
+
+     ;; Old CLtL2 stuff:
+
+     *applyhook*
+     *evalhook*
+     applyhook
+     augment-environment
+     declaration-information
+     define-declaration
+     define-setf-method
+     evalhook
+     enclose
+     function-information
+     generic-flet
+     generic-labels
+     get-setf-method
+     get-setf-method-multiple-value
+     parse-macro
+     variable-information
+     with-added-methods
+
+     ;; Gray Streams
+     fundamental-stream
+     fundamental-input-stream
+     fundamental-output-stream
+     fundamental-character-stream
+     fundamental-character-input-stream
+     fundamental-character-output-stream
+     fundamental-binary-stream
+     fundamental-binary-input-stream
+     fundamental-binary-output-stream
+
+     stream-read-char
+     stream-unread-char
+     stream-read-char-no-hang
+     stream-peek-char
+     stream-listen
+     stream-read-line
+     stream-clear-input
+
+     stream-write-char
+     stream-line-column
+     stream-start-line-p
+     stream-write-string
+     stream-terpri
+     stream-fresh-line
+     stream-force-output
+     stream-clear-output
+     stream-advance-to-column
+
+     stream-read-byte
+     stream-write-byte
+
+     stream-read-ivector
+     stream-write-ivector
+
+     stream-read-list
+     stream-write-list
+     stream-read-vector
+     stream-write-vector
+
+     stream-input-timeout
+     stream-output-timeout
+     with-input-timeout
+     with-output-timeout
+     stream-deadline
+
+     input-timeout
+     output-timeout
+     communication-deadline-expired
+
+     make-heap-ivector
+     dispose-heap-ivector
+     ;;
+     external
+     external-call
+     open-shared-library
+     close-shared-library
+     shlib
+     external-entry-point
+     use-interface-dir
+     unuse-interface-dir
+     create-interfaces
+     ;;
+     run-program
+     external-process
+     signal-external-process
+     external-process-id
+     external-process-input-stream
+     external-process-output-stream
+     external-process-error-stream
+     external-process-status
+     ;;
+     *altivec-available*
+     altivec-available-p
+     *altivec-lapmacros-maintain-vrsave-p*
+     ;;
+     *alternate-line-terminator*
+     ;;
+     set-user-environment
+     set-development-environment
+     *resident-editor-hook*
+     cpu-count
+     *report-time-function*
+     ;;
+     compile-ccl
+     xcompile-ccl
+     xload-level-0
+     rebuild-ccl
+     update-ccl
+     test-ccl
+     defglobal
+
+     getenv
+     setenv
+
+     external-format
+     make-external-format
+     external-format-character-encoding
+     external-format-line-termination
+     character-encoding
+     define-character-encoding
+     describe-character-encoding
+     describe-character-encodings
+     get-character-encoding
+     lookup-character-encoding
+     string-size-in-octets
+     encode-string-to-octets
+     count-characters-in-octet-vector
+     decode-string-from-octets
+     *terminal-character-encoding-name*
+     *default-file-character-encoding*
+     *default-socket-character-encoding*
+     ;; Mapped files.
+     map-file-to-ivector
+     map-file-to-octet-vector
+     unmap-ivector
+     unmap-octet-vector
+     ;; Miscellany
+     heap-utilization
+     collect-heap-utilization
+
+     external-process-creation-failure
+
+     ) "CCL"
+   )
+  )
+
+;;; Define a package for MOP extensions.
+(defpackage "OPENMCL-MOP"
+  (:use)
+  (:import-from
+   "CCL"
+   "ACCESSOR-METHOD-SLOT-DEFINITION"
+   "ADD-DEPENDENT"
+   "ADD-DIRECT-METHOD"
+   "ADD-DIRECT-SUBCLASS"
+   "ADD-METHOD"
+   "CLASS-DEFAULT-INITARGS"
+   "CLASS-DIRECT-DEFAULT-INITARGS"
+   "CLASS-DIRECT-SLOTS"
+   "CLASS-DIRECT-SUBCLASSES"
+   "CLASS-DIRECT-SUPERCLASSES"
+   "CLASS-FINALIZED-P"
+   "CLASS-PRECEDENCE-LIST"
+   "CLASS-PROTOTYPE"
+   "CLASS-SLOTS"
+   "COMPUTE-APPLICABLE-METHODS"
+   "COMPUTE-APPLICABLE-METHODS-USING-CLASSES"
+   "COMPUTE-CLASS-PRECEDENCE-LIST"
+   "COMPUTE-DEFAULT-INITARGS"
+   "COMPUTE-DISCRIMINATING-FUNCTION"
+   "COMPUTE-EFFECTIVE-METHOD"
+   "COMPUTE-EFFECTIVE-SLOT-DEFINITION"
+   "COMPUTE-SLOTS"
+   "DIRECT-SLOT-DEFINITION-CLASS"
+   "EFFECTIVE-SLOT-DEFINITION-CLASS"
+   "ENSURE-CLASS"
+   "ENSURE-CLASS-USING-CLASS"
+   "ENSURE-GENERIC-FUNCTION-USING-CLASS"
+   "EQL-SPECIALIZER"
+   "EQL-SPECIALIZER-OBJECT"
+   "EXTRACT-LAMBDA-LIST"
+   "EXTRACT-SPECIALIZER-NAMES"
+   "FINALIZE-INHERITANCE"
+   "FIND-METHOD-COMBINATION"
+   "FUNCALLABLE-STANDARD-INSTANCE-ACCESS"
+   "GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER"
+   "GENERIC-FUNCTION-DECLARATIONS"
+   "GENERIC-FUNCTION-LAMBDA-LIST"
+   "GENERIC-FUNCTION-METHOD-CLASS"
+   "GENERIC-FUNCTION-METHOD-COMBINATION"
+   "GENERIC-FUNCTION-METHODS"
+   "GENERIC-FUNCTION-NAME"
+   "INTERN-EQL-SPECIALIZER"
+   "MAKE-METHOD-LAMBDA"
+   "MAP-DEPENDENTS"
+   "METHOD-FUNCTION"
+   "METHOD-GENERIC-FUNCTION"
+   "METHOD-LAMBDA-LIST"
+   "METHOD-NAME"
+   "METHOD-SPECIALIZERS"
+   "METHOD-QUALIFIERS"
+   "SLOT-DEFINITION-DOCUMENTATION"
+   "SLOT-DEFINITION-ALLOCATION"
+   "SLOT-DEFINITION-INITARGS"
+   "SLOT-DEFINITION-INITFORM"
+   "SLOT-DEFINITION-INITFUNCTION"
+   "SLOT-DEFINITION-NAME"
+   "SLOT-DEFINITION-TYPE"
+   "SLOT-DEFINITION-READERS"
+   "SLOT-DEFINITION-WRITERS"
+   "SLOT-DEFINITION-LOCATION"
+   "READER-METHOD-CLASS"
+   "REMOVE-DEPENDENT"
+   "REMOVE-DIRECT-METHOD"
+   "REMOVE-DIRECT-SUBCLASS"
+   "REMOVE-METHOD"
+   "SET-FUNCALLABLE-INSTANCE-FUNCTION"
+   "SLOT-BOUNDP-USING-CLASS"
+   "SLOT-MAKUNBOUND-USING-CLASS"
+   "SLOT-VALUE-USING-CLASS"
+   "SPECIALIZER-DIRECT-GENERIC-FUNCTIONS"
+   "SPECIALIZER-DIRECT-METHODS"
+   "STANDARD-DIRECT-SLOT-DEFINITION"
+   "STANDARD-EFFECTIVE-SLOT-DEFINITION"
+   "STANDARD-INSTANCE-ACCESS"
+   "UPDATE-DEPENDENT"
+   "VALIDATE-SUPERCLASS"
+   "WRITER-METHOD-CLASS"
+     
+   "METAOBJECT"
+   "LONG-METHOD-COMBINATION"
+   "SHORT-METHOD-COMBINATION"
+   "STANDARD-ACCESSOR-METHOD"
+   "STANDARD-READER-METHOD"
+   "STANDARD-WRITER-METHOD"
+   "SPECIALIZER"
+
+   "FUNCALLABLE-STANDARD-CLASS"
+   "FUNCALLABLE-STANDARD-OBJECT"
+   "FORWARD-REFERENCED-CLASS"
+
+   "CLEAR-SPECIALIZER-DIRECT-METHODS-CACHES"
+   "*CHECK-CALL-NEXT-METHOD-WITH-ARGS*"
+   "CLEAR-GF-CACHE"
+   "CLEAR-ALL-GF-CACHES"
+   "CLEAR-CLOS-CACHES"
+
+   "METHOD-EXISTS-P"
+   "METHOD-SPECIALIZERS"
+   "CLASS-OWN-WRAPPER"
+   "SPECIALIZER-DIRECT-METHODS"
+   "SPECIALIZER-DIRECT-GENERIC-FUNCTIONS"
+   "COPY-INSTANCE"
+   "STANDARD-SLOT-DEFINITION"
+   "SLOT-DEFINITION"
+   "EFFECTIVE-SLOT-DEFINITION"
+   "DIRECT-SLOT-DEFINITION"
+   )
+  (:export
+   "ACCESSOR-METHOD-SLOT-DEFINITION"
+   "ADD-DEPENDENT"
+   "ADD-DIRECT-METHOD"
+   "ADD-DIRECT-SUBCLASS"
+   "ADD-METHOD"
+   "CLASS-DEFAULT-INITARGS"
+   "CLASS-DIRECT-DEFAULT-INITARGS"
+   "CLASS-DIRECT-SLOTS"
+   "CLASS-DIRECT-SUBCLASSES"
+   "CLASS-DIRECT-SUPERCLASSES"
+   "CLASS-FINALIZED-P"
+   "CLASS-PRECEDENCE-LIST"
+   "CLASS-PROTOTYPE"
+   "CLASS-SLOTS"
+   "COMPUTE-APPLICABLE-METHODS"
+   "COMPUTE-APPLICABLE-METHODS-USING-CLASSES"
+   "COMPUTE-CLASS-PRECEDENCE-LIST"
+   "COMPUTE-DEFAULT-INITARGS"
+   "COMPUTE-DISCRIMINATING-FUNCTION"
+   "COMPUTE-EFFECTIVE-METHOD"
+   "COMPUTE-EFFECTIVE-SLOT-DEFINITION"
+   "COMPUTE-SLOTS"
+   "DIRECT-SLOT-DEFINITION-CLASS"
+   "EFFECTIVE-SLOT-DEFINITION-CLASS"
+   "ENSURE-CLASS"
+   "ENSURE-CLASS-USING-CLASS"
+   "ENSURE-GENERIC-FUNCTION-USING-CLASS"
+   "EQL-SPECIALIZER"
+   "EQL-SPECIALIZER-OBJECT"
+   "EXTRACT-LAMBDA-LIST"
+   "EXTRACT-SPECIALIZER-NAMES"
+   "FINALIZE-INHERITANCE"
+   "FIND-METHOD-COMBINATION"
+   "FUNCALLABLE-STANDARD-INSTANCE-ACCESS"
+   "GENERIC-FUNCTION-ARGUMENT-PRECEDENCE-ORDER"
+   "GENERIC-FUNCTION-DECLARATIONS"
+   "GENERIC-FUNCTION-LAMBDA-LIST"
+   "GENERIC-FUNCTION-METHOD-CLASS"
+   "GENERIC-FUNCTION-METHOD-COMBINATION"
+   "GENERIC-FUNCTION-METHODS"
+   "GENERIC-FUNCTION-NAME"
+   "INTERN-EQL-SPECIALIZER"
+   "MAKE-METHOD-LAMBDA"
+   "MAP-DEPENDENTS"
+   "METHOD-FUNCTION"
+   "METHOD-GENERIC-FUNCTION"
+   "METHOD-LAMBDA-LIST"
+   "METHOD-NAME"
+   "METHOD-SPECIALIZERS"
+   "METHOD-QUALIFIERS"
+   "SLOT-DEFINITION-DOCUMENTATION"
+   "SLOT-DEFINITION-ALLOCATION"
+   "SLOT-DEFINITION-INITARGS"
+   "SLOT-DEFINITION-INITFORM"
+   "SLOT-DEFINITION-INITFUNCTION"
+   "SLOT-DEFINITION-NAME"
+   "SLOT-DEFINITION-TYPE"
+   "SLOT-DEFINITION-READERS"
+   "SLOT-DEFINITION-WRITERS"
+   "SLOT-DEFINITION-LOCATION"
+   "READER-METHOD-CLASS"
+   "REMOVE-DEPENDENT"
+   "REMOVE-DIRECT-METHOD"
+   "REMOVE-DIRECT-SUBCLASS"
+   "REMOVE-METHOD"
+   "SET-FUNCALLABLE-INSTANCE-FUNCTION"
+   "SLOT-BOUNDP-USING-CLASS"
+   "SLOT-MAKUNBOUND-USING-CLASS"
+   "SLOT-VALUE-USING-CLASS"
+   "SPECIALIZER-DIRECT-GENERIC-FUNCTIONS"
+   "SPECIALIZER-DIRECT-METHODS"
+   "STANDARD-DIRECT-SLOT-DEFINITION"
+   "STANDARD-EFFECTIVE-SLOT-DEFINITION"
+   "STANDARD-INSTANCE-ACCESS"
+   "UPDATE-DEPENDENT"
+   "VALIDATE-SUPERCLASS"
+   "WRITER-METHOD-CLASS"
+     
+   "METAOBJECT"
+   "LONG-METHOD-COMBINATION"
+   "SHORT-METHOD-COMBINATION"
+   "STANDARD-ACCESSOR-METHOD"
+   "STANDARD-READER-METHOD"
+   "STANDARD-WRITER-METHOD"
+   "SPECIALIZER"
+
+   "FUNCALLABLE-STANDARD-CLASS"
+   "FORWARD-REFERENCED-CLASS"
+
+
+   "CLEAR-SPECIALIZER-DIRECT-METHODS-CACHES"
+   "*CHECK-CALL-NEXT-METHOD-WITH-ARGS*"
+   "CLEAR-GF-CACHE"
+   "CLEAR-ALL-GF-CACHES"
+   "CLEAR-CLOS-CACHES"
+
+   "METHOD-EXISTS-P"
+   "METHOD-SPECIALIZERS"
+   "CLASS-OWN-WRAPPER"
+   "SPECIALIZER-DIRECT-METHODS"
+   "SPECIALIZER-DIRECT-GENERIC-FUNCTIONS"
+   "COPY-INSTANCE"
+   "STANDARD-SLOT-DEFINITION"
+   "SLOT-DEFINITION"
+   "EFFECTIVE-SLOT-DEFINITION"
+   "DIRECT-SLOT-DEFINITION"
+   ))
+
+(unless (eq %lisp-system-fixups% T)
+  (while %lisp-system-fixups%
+    (let* ((fn.source (car %lisp-system-fixups%))
+           (*loading-toplevel-location* (and (source-note-p (cdr fn.source)) (cdr fn.source)))
+           (*loading-file-source-file* (source-note-filename (cdr fn.source)))
+           )
+      (funcall (car fn.source)))
+    (setq %lisp-system-fixups% (cdr %lisp-system-fixups%)))
+  (setq %lisp-system-fixups% T))
+
+
+
+
Index: /branches/new-random/lib/chars.lisp
===================================================================
--- /branches/new-random/lib/chars.lisp	(revision 13309)
+++ /branches/new-random/lib/chars.lisp	(revision 13309)
@@ -0,0 +1,748 @@
+; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+;; chars.lisp
+
+(in-package "CCL")
+
+(defun character-designator-p (thing)
+  (or (typep thing 'character)
+      (typep thing '(string 1))
+      (and (typep thing 'symbol) (typep (symbol-name thing) '(string 1)))))
+
+;;; If object is a character, it is returned.  If it is a string of
+;;; length 1, then the sole element of the string is returned.  If it
+;;; is a symbol whose pname is of length 1, then the sole element of
+;;; the pname is returned. Else error.
+
+(defun character (arg)
+  "Coerce OBJECT into a CHARACTER if possible. Legal inputs are 
+  characters, strings and symbols of length 1."
+  (if (typep arg 'character)
+    arg
+    (if (and (typep arg 'string)
+             (= (the fixnum (length arg)) 1))
+      (char arg 0)
+      (let* ((pname (if (typep arg 'symbol) (symbol-name arg))))
+        (if (and pname (= (the fixnum (length pname)) 1))
+          (char pname 0)
+          (report-bad-arg arg '(satisfies character-designator-p)))))))
+
+
+
+(defun digit-char (weight &optional radix)
+  "All arguments must be integers. Returns a character object that
+  represents a digit of the given weight in the specified radix. Returns
+  NIL if no such character exists."
+  (let* ((r (if radix (require-type radix 'integer) 10)))
+    (if (and (typep (require-type weight 'integer) 'fixnum)
+             (>= r 2)
+             (<= r 36)
+             (>= weight 0)
+             (< weight r))
+      (locally (declare (fixnum weight))
+        (if (< weight 10)
+          (code-char (the fixnum (+ weight (char-code #\0))))
+          (code-char (the fixnum (+ weight (- (char-code #\A) 10)))))))))
+
+
+(declaim (inline %control-char-p))
+
+(defun %control-char-p (char)
+  (let* ((code (char-code char)))
+    (declare (type (mod #x110000) code))
+    ;; If we believe that "most" characters will have relatively
+    ;; small codes, then doing a linear search on this short
+    ;; list is probably faster than binary search on a vector
+    ;; or other approaches.
+    (dolist (pair '((0 . #x1f)                          ;c0
+                    (#x7f . #x9f)                       ;#\rubout, c1
+                    (#x34f . #x34f)                     ;combining grapheme joiner.
+                    (#x200c . #x200f)
+                    (#x202a . #x202e)
+                    (#x2060 . #x2063)
+                    (#x206a . #x206f)
+                    #+darwin-target
+                    (#xf700 . #xf7ff)
+                    (#xfe00 . #xfe0f)
+                    (#xfeff . #xfeff)                   ;byte-order mark (0-width space).
+                    (#xfff0 . #xfffd)
+                    
+                    (#xe0000 . #xefffd)))
+      (let* ((low (car pair))
+             (high (cdr pair)))
+        (declare (type (mod #x110000) low high))
+        (if (> low code)
+          (return nil)
+          (if (<= code high)
+            (return t)))))))
+
+
+
+;;; Characters that aren't control/formatting characters are graphic.
+(defun graphic-char-p (c)
+  "The argument must be a character object. GRAPHIC-CHAR-P returns NIL if the
+  argument is a Unicode control character, otherwise returns T."
+  (not (%control-char-p c)))
+
+
+;True for ascii codes 10 and 32-126 inclusive.
+(defun standard-char-p (c)
+  "The argument must be a character object. STANDARD-CHAR-P returns T if the
+   argument is a standard character -- one of the 95 ASCII printing characters
+   or <return>."
+  (let* ((code (char-code c)))
+    (or (eq c #\newline)
+        (and 
+         (>= code (char-code #\space))
+         (< code (char-code #\rubout))))))
+
+
+
+
+
+
+
+(defun upper-case-p (c)
+  "The argument must be a character object; UPPER-CASE-P returns T if the
+   argument is an upper-case character, NIL otherwise."
+  (let* ((code (char-code c))
+         (to-lower *upper-to-lower*))
+    (declare (type (mod #x110000) code)
+             (type (simple-array (signed-byte 16) (*)) to-lower))
+    (and (< code (length to-lower))
+         (not (zerop (aref to-lower code))))))
+
+
+
+
+(defun both-case-p (c)
+  "The argument must be a character object. BOTH-CASE-P returns T if the
+  argument is an alphabetic character and if the character exists in
+  both upper and lower case. For ASCII, this is the same as ALPHA-CHAR-P."
+  (let* ((code (char-code c))
+         (to-upper *lower-to-upper*)
+         (to-lower *upper-to-lower*))
+    (declare (type (mod #x110000) code)
+             (type (simple-array (signed-byte 16) (*)) to-lower to-upper))
+    (or (and (< code (length to-upper))
+             (not (zerop (aref to-upper code))))
+        (and (< code (length to-lower))
+             (not (zerop (aref to-lower code)))))))
+  
+(defun alphanumericp (c)
+  "Given a character-object argument, ALPHANUMERICP returns T if the
+   argument is either numeric or alphabetic."
+  (let ((code (char-code c)))
+    (declare (type (mod #x110000) code))
+    (or
+     (and (>= code (char-code #\0))
+          (<= code (char-code #\9)))
+     (let* ((bits *alpha-char-bits*))
+       (declare (simple-bit-vector bits))
+       (and (< code (length bits))
+            (not (eql 0 (sbit bits code))))))))
+
+(defun char= (ch &rest others)
+  "Return T if all of the arguments are the same character."
+  (declare (dynamic-extent others))
+  (unless (typep ch 'character)
+    (setq ch (require-type ch 'character)))
+  (dolist (other others t)
+    (unless (eq other ch)
+      (unless (typep other 'character)
+        (setq other (require-type other 'character)))
+      (return))))
+
+(defun char/= (ch &rest others)
+  "Return T if no two of the arguments are the same character."
+  (declare (dynamic-extent others))
+  (unless (typep ch 'character)
+    (setq ch (require-type ch 'character)))
+  (do* ((rest others (cdr rest)))
+       ((null rest) t)
+    (let ((other (car rest)))
+      (if (eq other ch) (return))
+      (unless (typep other 'character)
+        (setq other (require-type other 'character)))
+      (dolist (o2 (cdr rest))
+        (if (eq o2 other)(return-from char/= nil))))))
+
+
+(defun char-equal (char &rest others)
+  "Return T if all of the arguments are the same character.
+  Font, bits, and case are ignored."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (dolist (c others t)
+      (when (not (eq c char))
+        (unless (eq (char-upcase char) (char-upcase c))
+          (return))))))
+
+;;; Compares each char against all following chars, not just next one. Tries
+;;; to be fast for one or two args.
+(defun char-not-equal (char &rest others)
+  "Return T if no two of the arguments are the same character.
+   Font, bits, and case are ignored."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3) (safety 0)))
+    (let* ((rest (cdr others)))
+      (cond 
+       (rest                   
+        (setq char (char-code (char-upcase char)))
+        (do ((list others (cdr list)))
+            ((null list))
+          (rplaca list (char-code (char-upcase (car list)))))
+        (while others
+          (when (memq char others)
+            (return-from char-not-equal nil))
+	  (setq char (car others)
+		others rest
+		rest (cdr others)))
+        t)
+       (others                     ;  2 args, no table
+        (not (eq (char-upcase char) (char-upcase (car others)))))
+       (t t)))))
+
+
+(defun char-lessp (char &rest others)
+  "Return T if the arguments are in strictly increasing alphabetic order.
+   Font, bits, and case are ignored."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ((code (char-code (char-upcase char))))
+      (dolist (c others t)
+        (unless (< code (setq code (char-code (char-upcase c))))
+          (return))))))
+
+(defun char-not-lessp (char &rest others)
+  "Return T if the arguments are in strictly non-increasing alphabetic order.
+   Font, bits, and case are ignored."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ((code (char-code (char-upcase char))))
+      (dolist (c others t)
+        (when (< code (setq code (char-code (char-upcase c))))
+          (return))))))
+
+(defun char-greaterp (char &rest others)
+  "Return T if the arguments are in strictly decreasing alphabetic order.
+   Font, bits, and case are ignored."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ((code (char-code (char-upcase char))))
+      (dolist (c others t)
+        (unless (> code (setq code (char-code (char-upcase c))))
+          (return))))))
+
+(defun char-not-greaterp (char &rest others)
+  "Return T if the arguments are in strictly non-decreasing alphabetic order.
+   Font, bits, and case are ignored."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ((code (char-code (char-upcase char))))
+      (dolist (c others t)
+        (when (> code (setq code (char-code (char-upcase c))))
+          (return))))))
+
+
+(defun char> (char &rest others)
+  "Return T if the arguments are in strictly decreasing alphabetic order."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ()      
+      (setq char (char-code char))
+      (dolist (c others t)
+        (let ((code (char-code c)))
+          (when (not (%i> char (setq char code)))
+            (return)))))))
+
+(defun char>= (char &rest others)
+  "Return T if the arguments are in strictly non-increasing alphabetic order."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ()      
+      (setq char (char-code char))
+      (dolist (c others t)
+        (let ((code (char-code c)))
+          (when (not (%i>= char (setq char code)))
+            (return)))))))
+
+
+(defun char< (char &rest others)
+  "Return T if the arguments are in strictly increasing alphabetic order."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ()      
+      (setq char (char-code char))
+      (dolist (c others t)
+        (let ((code (char-code c)))
+          (when (not (%i< char (setq char code)))
+            (return)))))))
+
+(defun char<= (char &rest others)
+  "Return T if the arguments are in strictly non-decreasing alphabetic order."
+  (declare (dynamic-extent others))
+  (locally (declare (optimize (speed 3)(safety 0)))
+    (let* ()      
+      (setq char (char-code char))
+      (dolist (c others t)
+        (let ((code (char-code c)))
+          (when (not (%i<= char (setq char code)))
+            (return)))))))
+
+; This is Common Lisp
+(defun char-int (c)
+  "Return the integer code of CHAR."
+  (char-code c))
+
+
+;If char has an entry in the *NAME-CHAR-ALIST*, return first such entry.
+;Otherwise, if char is a graphics character, return NIL
+;Otherwise, if char code is < 128, return "^C", otherwise "1nn"
+
+(defun char-name (c)
+  "Return the name (a STRING) for a CHARACTER object."
+  (let* ((code (char-code c)))
+    (declare (type (mod #x110000) code))
+    (or (gethash c *char->name*)
+        (cond ((< code #x7f)
+               (when (< code (char-code #\space))
+                 (let ((str (make-string 2 :element-type 'base-char)))
+                   (declare (simple-base-string str))
+                   (setf (schar str 0) #\^)
+                   (setf (schar str 1)(code-char (logxor code #x40)))
+                   str)))
+              ((and (< code #x100)(graphic-char-p c)) nil)
+              (t (format nil "U+~4,'0x" code))))))
+
+
+(defun string-downcase (string &key (start 0) end)
+  (setq string (copy-string-arg string))
+  (setq end (check-sequence-bounds string start end))
+  (%strdown string start end))
+
+
+(defun %strdown (string start end)
+  (declare (fixnum start end)
+           (optimize (speed 3) (safety 0)))
+  (unless (typep string 'simple-string)
+    (check-type string simple-string))
+  (do* ((i start (1+ i))
+        (to-lower *upper-to-lower*)
+        (n (length to-lower)))
+       ((>= i end) string)
+    (declare (fixnum i n) (type (simple-array (signed-byte 16) (*)) to-lower))
+    (let* ((ch (schar string i))
+           (code (char-code ch))
+           (delta (if (< code n) (aref to-lower code) 0)))
+      (declare (character ch)
+               (type (mod #x110000) code)
+               (type (signed-byte 16) delta))
+      (unless (zerop delta)
+        (setf (schar string i)
+              (code-char (the valid-char-code (+ code delta))))))))
+
+
+
+
+(defun copy-string-arg (string &aux (org 0) len)
+  (etypecase string
+    (string
+     (setq len (length string))
+     (multiple-value-setq (string org)(array-data-and-offset string)))
+    (symbol
+     (setq string (symbol-name string))
+     (setq len (length string)))
+    (character
+     (return-from copy-string-arg
+                    (make-string 1 :initial-element string ))))
+  (%substr string org (+ len org)))     
+
+(defun string-upcase (string &key (start 0) end)
+  (setq string (copy-string-arg string))
+  (setq end (check-sequence-bounds string start end))
+  (%strup string start end))
+
+(defun %strup (string start end)
+  (declare (fixnum start end)
+           (optimize (speed 3) (safety 0)))
+  (unless (typep string 'simple-string)
+    (check-type string simple-string))
+  (do* ((i start (1+ i))
+        (to-upper *lower-to-upper*)
+        (n (length to-upper)))
+       ((>= i end) string)
+    (declare (fixnum i n) (type (simple-array (signed-byte 16) (*)) to-upper))
+    (let* ((ch (schar string i))
+           (code (char-code ch))
+           (delta (if (< code n) (aref to-upper code) 0)))
+      (declare (character ch)
+               (type (mod #x110000) code)
+               (type (signed-byte 16) delta))
+      (unless (zerop delta)
+        (setf (schar string i) (code-char (the valid-char-code (+ code delta))))))))
+
+
+
+(defun string-capitalize (string &key (start 0) end)
+  (setq string (copy-string-arg string))
+  (setq end (check-sequence-bounds string start end))
+  (%strcap string start end))
+
+(defun %strcap (string start end)
+  (declare (fixnum start end))
+  (let ((state :up)
+        (i start))
+    (declare (fixnum i))
+    (while (< i end)
+      (let* ((c (%schar string i))
+             (alphap (alphanumericp c))) ; makes no sense
+        (if alphap
+          (progn
+            (setf (%schar string i)
+                  (case state
+                    (:up (char-upcase c))
+                    (t (char-downcase c))))
+            (setq state :down))
+          (setq state :up)))
+      (setq i (1+ i)))
+    string))
+
+
+
+
+(defun nstring-downcase (string &key (start 0) end)
+  (etypecase string
+    (string
+     (setq end (check-sequence-bounds string start end))
+     (if (typep string 'simple-string)
+       (%strdown string start end)
+       (multiple-value-bind (data offset) (array-data-and-offset string)
+         (%strdown data (+ start offset) (+ end offset))))
+     string)))
+
+(defun nstring-upcase (string &key (start 0) end)
+  (etypecase string
+    (string
+     (setq end (check-sequence-bounds string start end))
+     (if (typep string 'simple-string)
+       (%strup string start end)
+       (multiple-value-bind (data offset) (array-data-and-offset string)
+         (%strup data (+ start offset) (+ end offset))))
+     string)))
+
+
+(defun nstring-capitalize (string &key (start 0) end)
+  (etypecase string
+    (string
+     (setq end (check-sequence-bounds string start end))
+     (if (typep string 'simple-string)
+       (%strcap string start end)
+       (multiple-value-bind (data offset) (array-data-and-offset string)
+         (%strcap data (+ start offset) (+ end offset))))
+     string)))
+
+
+
+(defun nstring-studlify (string &key start end)
+  (declare (ignore start end))
+  string)
+
+  
+(defun string-compare (string1 start1 end1 string2 start2 end2)
+  (let ((istart1 (or start1 0)))
+    (if (and (typep string1 'simple-string)(null start1)(null end1))
+      (setq start1 0 end1 (length string1))
+      (multiple-value-setq (string1 start1 end1)(string-start-end string1 start1 end1)))
+    (if (and (typep string2 'simple-string)(null start2)(null end2))
+      (setq start2 0 end2 (length string2))
+      (multiple-value-setq (string2 start2 end2)(string-start-end string2 start2 end2)))
+    (setq istart1 (%i- start1 istart1))
+    (let* ((val t))
+      (declare (optimize (speed 3)(safety 0)))
+      (do* ((i start1 (%i+ 1 i))
+            (j start2 (%i+ 1 j)))
+           ()
+        (when (eq i end1)
+          (when (neq j end2)
+            (setq val -1))
+          (return))
+        (when (eq j end2)
+          (setq end1 i)
+          (setq val 1)
+          (return))
+        (let ((code1 (%scharcode string1 i))
+              (code2 (%scharcode string2 j)))
+          (declare (fixnum code1 code2))
+          (if (and (>= code1 (char-code #\a))
+                   (<= code1 (char-code #\z)))
+            (setq code1 (- code1 (- (char-code #\a) (char-code #\A)))))
+          (if (and (>= code2 (char-code #\a))
+                   (<= code2 (char-code #\z)))
+            (setq code2 (- code2 (- (char-code #\a) (char-code #\A)))))
+          (unless (= code1 code2)            
+            (setq val (if (%i< code1 code2) -1 1))
+            (setq end1 i)
+            (return))))
+      (values val (%i- end1 istart1)))))
+
+
+(defun string-greaterp (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically greater than
+  the second string, returns the longest common prefix (using char-equal)
+  of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-compare string1 start1 end1 string2 start2 end2)
+    (if (eq result 1) pos nil)))
+
+(defun string-not-greaterp (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically less than
+  or equal to the second string, returns the longest common prefix
+  (using char-equal) of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-compare string1 start1 end1 string2 start2 end2)
+    (if (eq result 1) nil pos)))
+
+(defun string-not-equal (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is not lexicographically equal
+  to the second string, returns the longest common prefix (using char-equal)
+  of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-compare string1 start1 end1 string2 start2 end2)
+    (if (eq result t) nil pos)))
+
+(defun string-not-lessp (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically greater
+  than or equal to the second string, returns the longest common prefix
+  (using char-equal) of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-compare string1 start1 end1 string2 start2 end2)
+    (if (eq result -1) nil pos)))
+
+(declaim (inline %string-start-end))
+(defun %string-start-end (string)
+  (etypecase string
+    (string (multiple-value-bind (data offset)
+                (array-data-and-offset string)
+              (declare (fixnum offset))
+              (values data offset (+ offset (length string)))))
+    (symbol (let* ((pname (symbol-name string)))
+              (values pname 0 (length pname))))
+    (character (let* ((data (make-string 1)))
+                 (setf (schar data 0) string)
+                 (values data 0 1)))))
+                       
+;;; This is generally a bit faster then the version that deals with
+;;; user-supplied bounds, both because the caller avoids passing
+;;; some extra arguments and because those bounds don't need to be
+;;; validated.
+(defun %fixed-string-equal (string1 string2)
+  (let* ((start1 0)
+         (end1 0)
+         (start2 0)
+         (end2 0))
+    (declare (fixnum start1 end1 start2 end2))
+    (if (typep string1 'simple-string)
+      (setq end1 (uvsize string1))
+      (multiple-value-setq (string1 start1 end1)
+        (%string-start-end string1)))
+    (if (typep string2 'simple-string)
+      (setq end2 (uvsize string2))
+      (multiple-value-setq (string2 start2 end2)
+        (%string-start-end string2)))
+    (locally
+        (declare (optimize (speed 3)(safety 0))
+                 (simple-string string1 string2))
+      (when (= (the fixnum (- end1 start1))
+               (the fixnum (- end2 start2)))
+        (do* ((i start1 (1+ i))
+              (j start2 (1+ j))
+              (map *lower-to-upper*))
+             ((= i end1) t)
+          (declare (fixnum i j))
+          (let ((code1 (%scharcode string1 i))
+                (code2 (%scharcode string2 j)))
+            (declare (type (mod #x110000) code1 code2))
+            (unless (= code1 code2)
+              (unless (= (the (mod #x110000) (%char-code-case-fold code1 map))
+                         (the (mod #x110000) (%char-code-case-fold code2 map)))
+                (return)))))))))
+
+;;; Some of the start1/end1/start2/end2 args may be bogus.
+(defun %bounded-string-equal (string1 string2 start1 end1 start2 end2)
+  (let* ((disp1 nil)
+         (len1 0)
+         (disp2 nil)
+         (len2 0))
+    (declare (fixnum len1 len2))
+    (if (typep string1 'simple-string)
+      (setq len1 (length (the simple-string string1)))
+      (etypecase string1
+        (string (setq len1 (length string1))
+                (multiple-value-setq (string1 disp1)
+                  (array-data-and-offset string1)))
+        (symbol (setq string1 (symbol-name string1)
+                      len1 (length (the simple-string string1))))
+        (character (setq string1 (make-string 1 :initial-element string1)
+                         len1 1))))
+    (if (typep string2 'simple-string)
+      (setq len2 (length (the simple-string string2)))
+      (etypecase string2
+        (string (setq len2 (length string2))
+                (multiple-value-setq (string2 disp2)
+                  (array-data-and-offset string2)))
+        (symbol (setq string2 (symbol-name string2)
+                      len1 (length (the simple-string string2))))
+        (character (setq string2 (make-string 1 :initial-element string2)
+                         len1 1))))
+    (flet ((bad-index (index vector) (error "Index ~s is invalid for ~s" index vector)))
+      (if (null start1)
+        (setq start1 0)
+        (when (or (not (typep start1 'fixnum))
+                  (< (the fixnum start1) 0))
+          (bad-index start1 string1)))
+      (if (null end1)
+        (setq end1 len1)
+        (when (or (not (typep end1 'fixnum))
+                  (< (the fixnum end1) 0)
+                  (> (the fixnum end1) len1))
+          (bad-index end1 string1)))
+      (locally (declare (fixnum start1 end1))
+        (if (> start1 end1)
+          (error ":start1 argument ~s exceeds :end1 argument ~s" start1 end1))
+        (when disp1
+          (locally (declare (fixnum disp1))
+            (incf start1 disp1)
+            (incf end1 disp1)))
+        (if (null start2)
+          (setq start2 0)
+          (when (or (not (typep start2 'fixnum))
+                    (< (the fixnum start2) 0))
+            (bad-index start2 string2)))
+        (if (null end2)
+          (setq end2 len2)
+          (when (or (not (typep end2 'fixnum))
+                    (< (the fixnum end2) 0)
+                    (> (the fixnum end2) len2))
+            (bad-index end2 string2)))
+        (locally (declare (fixnum start2 end2))
+          (if (> start2 end2)
+            (error ":start2 argument ~s exceeds :end2 argument ~s" start1 end1))
+          (when disp2
+            (locally (declare (fixnum disp2))
+              (incf start2 disp2)
+              (incf end2 disp2)))
+          (locally
+              (declare (optimize (speed 3)(safety 0))
+                       (simple-string string1 string2))
+            (when (= (the fixnum (- end1 start1))
+                     (the fixnum (- end2 start2)))
+              (do* ((i start1 (1+ i))
+                    (j start2 (1+ j))
+                    (map *lower-to-upper*))
+                   ((= i end1) t)
+                (declare (fixnum i j))
+                (let ((code1 (%scharcode string1 i))
+                      (code2 (%scharcode string2 j)))
+                  (declare (type (mod #x110000) code1 code2))
+                  (unless (= code1 code2)
+                    (unless (= (the (mod #x110000) (%char-code-case-fold code1 map))
+                               (the (mod #x110000) (%char-code-case-fold code2 map)))
+                      (return))))))))))))
+
+(defun string-equal (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings (string1 and string2), and optional integers start1,
+  start2, end1 and end2, compares characters in string1 to characters in
+  string2 (using char-equal)."
+  (if (or start1 end1 start2 end2)
+    (%bounded-string-equal string1 string2 start1 end1 start2 end2)
+    (%fixed-string-equal string1 string2)))
+
+
+
+(defun string-lessp (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically less than
+  the second string, returns the longest common prefix (using char-equal)
+  of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos)(string-compare string1 start1 end1 string2 start2 end2)
+    (if (eq result -1) pos nil)))
+
+;;; forget script-manager - just do codes
+(defun string-cmp (string1 start1 end1 string2 start2 end2)
+  (let ((istart1 (or start1 0)))
+    (if (and (typep string1 'simple-string)(null start1)(null end1))
+      (setq start1 0 end1 (length string1))
+      (multiple-value-setq (string1 start1 end1)(string-start-end string1 start1 end1)))
+    (if (and (typep string2 'simple-string)(null start2)(null end2))
+      (setq start2 0 end2 (length string2))
+      (multiple-value-setq (string2 start2 end2)(string-start-end string2 start2 end2)))
+    (setq istart1 (%i- start1 istart1))        
+    (let* ((val t))
+      (declare (optimize (speed 3)(safety 0)))
+      (do* ((i start1 (%i+ 1 i))
+            (j start2 (%i+ 1 j)))
+           ()
+        (when (eq i end1)
+          (when (neq j end2)(setq val -1))
+          (return))
+        (when (eq j end2)
+          (setq end1 i)
+          (setq val 1)(return))
+        (let ((code1 (%scharcode string1 i))
+              (code2 (%scharcode string2 j)))
+          (declare (fixnum code1 code2))
+          (unless (= code1 code2)            
+            (setq val (if (%i< code1 code2) -1 1))
+            (setq end1 i)
+            (return))))
+      (values val (%i- end1 istart1)))))
+
+(defun string> (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically greater than
+  the second string, returns the longest common prefix (using char=)
+  of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-cmp string1 start1 end1 string2 start2 end2)
+    (if (eq result 1) pos nil)))
+
+(defun string>= (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically greater
+  than or equal to the second string, returns the longest common prefix
+  (using char=) of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-cmp string1 start1 end1 string2 start2 end2)
+    (if (eq result -1) nil pos)))
+
+(defun string< (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically less than
+  the second string, returns the longest common prefix (using char=)
+  of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-cmp string1 start1 end1 string2 start2 end2)
+    (if (eq result -1) pos nil)))
+
+(defun string<= (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is lexicographically less than
+  or equal to the second string, returns the longest common prefix
+  (using char=) of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-cmp string1 start1 end1 string2 start2 end2)
+    (if (eq result 1) nil pos)))
+
+; this need not be so fancy?
+(defun string/= (string1 string2 &key start1 end1 start2 end2)
+  "Given two strings, if the first string is not lexicographically equal
+  to the second string, returns the longest common prefix (using char=)
+  of the two strings. Otherwise, returns ()."
+  (multiple-value-bind (result pos) (string-cmp string1 start1 end1 string2 start2 end2)
+    (if (eq result t) nil pos)))
+
+
+
+(provide 'chars)
Index: /branches/new-random/lib/compile-ccl.lisp
===================================================================
--- /branches/new-random/lib/compile-ccl.lisp	(revision 13309)
+++ /branches/new-random/lib/compile-ccl.lisp	(revision 13309)
@@ -0,0 +1,805 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(require 'systems)
+
+(defparameter *sysdef-modules*
+  '(systems compile-ccl))
+
+(defparameter *level-1-modules*
+  '(level-1
+    l1-cl-package
+    l1-boot-1 l1-boot-2 l1-boot-3
+    l1-utils l1-init l1-symhash l1-numbers l1-aprims 
+    l1-sort l1-dcode l1-clos-boot l1-clos
+    l1-unicode l1-streams l1-files l1-io 
+    l1-format l1-readloop l1-reader
+    l1-sysio l1-pathnames l1-events
+    l1-boot-lds  l1-readloop-lds 
+    l1-lisp-threads  l1-application l1-processes
+    l1-typesys sysutils l1-error-system
+    l1-error-signal version l1-callbacks
+    l1-sockets linux-files
+    ))
+
+(defparameter *compiler-modules*
+  '(nx optimizers dll-node arch vreg vinsn 
+    reg subprims  backend nx2))
+
+
+(defparameter *ppc-compiler-modules*
+  '(ppc32-arch
+    ppc64-arch
+    ppc-arch
+    ppcenv
+    ppc-asm
+    risc-lap
+    ppc-lap
+    ppc-backend
+))
+
+(defparameter *x86-compiler-modules*
+  '(x8632-arch
+    x8664-arch
+    x86-arch
+    x8632env
+    x8664env
+    x86-asm
+    x86-lap
+    x86-backend
+))
+
+(defparameter *ppc32-compiler-backend-modules*
+  '(ppc32-backend ppc32-vinsns))
+
+(defparameter *ppc64-compiler-backend-modules*
+  '(ppc64-backend ppc64-vinsns))
+
+
+(defparameter *ppc-compiler-backend-modules*
+  '(ppc2))
+
+
+(defparameter *x8632-compiler-backend-modules*
+  '(x8632-backend x8632-vinsns))
+
+(defparameter *x8664-compiler-backend-modules*
+  '(x8664-backend x8664-vinsns))
+
+(defparameter *x86-compiler-backend-modules*
+  '(x862))
+
+
+
+
+(defparameter *ppc-xload-modules* '(xppcfasload xfasload heap-image ))
+(defparameter *x8632-xload-modules* '(xx8632fasload xfasload heap-image ))
+(defparameter *x8664-xload-modules* '(xx8664fasload xfasload heap-image ))
+
+
+;;; Not too OS-specific.
+(defparameter *ppc-xdev-modules* '(ppc-lapmacros ))
+(defparameter *x86-xdev-modules* '(x86-lapmacros ))
+
+(defun target-xdev-modules (&optional (target
+				       (backend-target-arch-name
+					*host-backend*)))
+  (case target
+    ((:ppc32 :ppc64) *ppc-xdev-modules*)
+    ((:x8632 :x8664) *x86-xdev-modules*)))
+
+(defun target-xload-modules (&optional (target
+					(backend-target-arch-name *host-backend*)))
+  (case target
+    ((:ppc32 :ppc64) *ppc-xload-modules*)
+    (:x8632 *x8632-xload-modules*)
+    (:x8664 *x8664-xload-modules*)))
+
+
+
+
+
+
+(defparameter *env-modules*
+  '(hash backquote lispequ  level-2 macros
+    defstruct-macros lists chars setf setf-runtime
+    defstruct defstruct-lds 
+    foreign-types
+    db-io
+    nfcomp
+    ))
+
+(defun target-env-modules (&optional (target
+				      (backend-name *host-backend*)))
+  (append *env-modules*
+          (list
+           (ecase target
+             (:linuxppc32 'ffi-linuxppc32)
+             (:darwinppc32 'ffi-darwinppc32)
+             (:darwinppc64 'ffi-darwinppc64)
+             (:linuxppc64 'ffi-linuxppc64)
+	     (:darwinx8632 'ffi-darwinx8632)
+             (:linuxx8664 'ffi-linuxx8664)
+             (:darwinx8664 'ffi-darwinx8664)
+             (:freebsdx8664 'ffi-freebsdx8664)
+             (:solarisx8664 'ffi-solarisx8664)
+             (:win64 'ffi-win64)
+             (:linuxx8632 'ffi-linuxx8632)
+             (:win32 'ffi-win32)
+             (:solarisx8632 'ffi-solarisx8632)
+             (:freebsdx8632 'ffi-freebsdx8632)))))
+
+
+(defun target-compiler-modules (&optional (target
+					   (backend-target-arch-name
+					    *host-backend*)))
+  (case target
+    (:ppc32 (append *ppc-compiler-modules*
+                    *ppc32-compiler-backend-modules*
+                    *ppc-compiler-backend-modules*))
+    (:ppc64 (append *ppc-compiler-modules*
+                    *ppc64-compiler-backend-modules*
+                    *ppc-compiler-backend-modules*))
+    (:x8632 (append *x86-compiler-modules*
+                    *x8632-compiler-backend-modules*
+                    *x86-compiler-backend-modules*))
+    (:x8664 (append *x86-compiler-modules*
+                    *x8664-compiler-backend-modules*
+                    *x86-compiler-backend-modules*))))
+
+(defparameter *other-lib-modules*
+  '(streams pathnames backtrace
+    apropos
+    numbers 
+    dumplisp   source-files))
+
+(defun target-other-lib-modules (&optional (target
+					    (backend-target-arch-name
+					     *host-backend*)))
+  (append *other-lib-modules*
+	  (case target
+	    ((:ppc32 :ppc64) '(ppc-backtrace ppc-disassemble))
+            ((:x8632 :x8664) '(x86-backtrace x86-disassemble x86-watch)))))
+	  
+
+(defun target-lib-modules (&optional (backend-name
+                                      (backend-name *host-backend*)))
+  (let* ((backend (or (find-backend backend-name) *host-backend*))
+         (arch-name (backend-target-arch-name backend)))
+    (append (target-env-modules backend-name) (target-other-lib-modules arch-name))))
+
+
+(defparameter *code-modules*
+  '(encapsulate
+    read misc  arrays-fry
+    sequences sort 
+    method-combination
+    case-error pprint 
+    format time 
+;        eval step
+    backtrace-lds  ccl-export-syms prepare-mcl-environment))
+
+
+
+(defparameter *aux-modules*
+  '(number-macros number-case-macro
+    loop
+    runtime
+    mcl-compat
+    arglist
+    edit-callers
+    describe
+    cover
+    leaks
+    core-files
+    asdf
+    defsystem
+    jp-encode
+    ))
+
+
+
+
+
+
+
+(defun target-level-1-modules (&optional (target (backend-name *host-backend*)))
+  (append *level-1-modules*
+	  (case target
+	    ((:linuxppc32 :darwinppc32 :linuxppc64 :darwinppc64)
+	     '(ppc-error-signal ppc-trap-support
+	       ppc-threads-utils ppc-callback-support))
+            ((:linuxx8664 :freebsdx8664 :darwinx8664 :solarisx8664
+                          :darwinx8632 :win64  :linuxx8632 :win32 :solarisx8632
+                          :freebsdx8632)
+             '(x86-error-signal x86-trap-support
+               x86-threads-utils x86-callback-support)))))
+
+
+;;; Needed to cross-dump an image
+
+
+(unless (fboundp 'xload-level-0)
+  (%fhave 'xload-level-0
+          #'(lambda (&rest rest)
+	      (in-development-mode
+	       (require-modules (target-xload-modules)))
+              (apply 'xload-level-0 rest))))
+
+(defun find-module (module &optional (target (backend-name *host-backend*))  &aux data fasl sources)
+  (if (setq data (assoc module *ccl-system*))
+    (let* ((backend (or (find-backend target) *host-backend*)))
+      (setq fasl (cadr data) sources (caddr data))      
+      (setq fasl (merge-pathnames (backend-target-fasl-pathname
+				   backend) fasl))
+      (values fasl (if (listp sources) sources (list sources))))
+    (error "Module ~S not defined" module)))
+
+;compile if needed.
+(defun target-compile-modules (modules target force-compile)
+  (if (not (listp modules)) (setq modules (list modules)))
+  (in-development-mode
+   (dolist (module modules t)
+     (multiple-value-bind (fasl sources) (find-module module target)
+      (if (needs-compile-p fasl sources force-compile)
+        (progn
+          (require'nfcomp)
+          (compile-file (car sources)
+			:output-file fasl
+			:verbose t
+			:target target)))))))
+
+
+(defun needs-compile-p (fasl sources force-compile)
+  (if fasl
+    (if (eq force-compile t)
+      t
+      (if (not (probe-file fasl))
+        t
+        (let ((fasldate (file-write-date fasl)))
+          (if (if (integerp force-compile) (> force-compile fasldate))
+            t
+            (dolist (source sources nil)
+              (if (> (file-write-date source) fasldate)
+                (return t)))))))))
+
+
+
+;;;compile if needed, load if recompiled.
+
+(defun update-modules (modules &optional force-compile)
+  (if (not (listp modules)) (setq modules (list modules)))
+  (in-development-mode
+   (dolist (module modules t)
+     (multiple-value-bind (fasl sources) (find-module module)
+       (if (needs-compile-p fasl sources force-compile)
+	 (progn
+	   (require'nfcomp)
+	   (let* ((*warn-if-redefine* nil))
+	     (compile-file (car sources) :output-file fasl :verbose t :load t))
+	   (provide module)))))))
+
+(defun compile-modules (modules &optional force-compile)
+  (target-compile-modules modules (backend-name *host-backend*) force-compile)
+)
+
+(defun compile-ccl (&optional force-compile)
+  (with-compilation-unit ()
+    (update-modules *sysdef-modules* force-compile)
+    (update-modules 'nxenv force-compile)
+    (update-modules *compiler-modules* force-compile)
+    (update-modules (target-compiler-modules) force-compile)
+    (update-modules (target-xdev-modules) force-compile)
+    (update-modules (target-xload-modules)  force-compile)
+    (let* ((env-modules (target-env-modules))
+           (other-lib (target-other-lib-modules)))
+      (require-modules env-modules)
+      (update-modules env-modules force-compile)
+      (compile-modules (target-level-1-modules)  force-compile)
+      (update-modules other-lib force-compile)
+      (require-modules other-lib)
+      (require-update-modules *code-modules* force-compile))
+    (compile-modules *aux-modules* force-compile)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun require-env (&optional force-load)
+  (require-modules  (target-env-modules)
+                   force-load))
+
+(defun compile-level-1 (&optional force-compile)
+  (require-env)
+  (compile-modules (target-level-1-modules (backend-name *host-backend*))
+                   force-compile))
+
+
+
+
+
+(defun compile-lib (&optional force-compile)
+  (compile-modules (target-lib-modules)
+                   force-compile))
+
+(defun compile-code (&optional force-compile)
+  (compile-modules *code-modules* force-compile))
+
+
+;Compile but don't load
+
+(defun xcompile-ccl (&optional force)
+  (with-compilation-unit ()
+    (compile-modules *sysdef-modules* force)
+    (compile-modules 'nxenv force)
+    (compile-modules *compiler-modules* force)
+    (compile-modules (target-compiler-modules) force)
+    (compile-modules (target-xdev-modules) force)
+    (compile-modules (target-xload-modules)  force)
+    (compile-modules (target-env-modules) force)
+    (compile-modules (target-level-1-modules) force)
+    (compile-modules (target-other-lib-modules) force)
+    (compile-modules *code-modules* force)
+    (compile-modules *aux-modules* force)))
+
+(defun require-update-modules (modules &optional force-compile)
+  (if (not (listp modules)) (setq modules (list modules)))
+  (in-development-mode
+    (dolist (module modules)
+    (require-modules module)
+    (update-modules module force-compile))))
+
+
+(defun target-xcompile-ccl (target &optional force)
+  (require-update-modules *sysdef-modules* force) ;in the host
+  (let* ((backend (or (find-backend target) *target-backend*))
+	 (arch (backend-target-arch-name backend))
+	 (*defstruct-share-accessor-functions* nil))
+    (target-compile-modules 'nxenv target force)
+    (target-compile-modules *compiler-modules* target force)
+    (target-compile-modules (target-compiler-modules arch) target force)
+    (target-compile-modules (target-level-1-modules target) target force)
+    (target-compile-modules (target-lib-modules target) target force)
+    (target-compile-modules *sysdef-modules* target force)
+    (target-compile-modules *aux-modules* target force)
+    (target-compile-modules *code-modules* target force)
+    (target-compile-modules (target-xdev-modules arch) target force)))
+
+(defun cross-compile-ccl (target &optional force)
+  (with-cross-compilation-target (target)
+    (let* ((*target-backend* (find-backend target)))
+      (target-xcompile-ccl target force))))
+
+
+(defun require-module (module force-load)
+  (multiple-value-bind (fasl source) (find-module module)
+      (setq source (car source))
+      (if (if fasl (probe-file fasl))
+        (if force-load
+          (progn
+            (load fasl)
+            (provide module))
+          (require module fasl))
+        (if (probe-file source)
+          (progn
+            (if fasl (format t "~&Can't find ~S so requiring ~S instead"
+                             fasl source))
+            (if force-load
+              (progn
+                (load source)
+                (provide module))
+              (require module source)))
+          (error "Can't find ~S or ~S" fasl source)))))
+
+(defun require-modules (modules &optional force-load)
+  (if (not (listp modules)) (setq modules (list modules)))
+  (let ((*package* (find-package :ccl)))
+    (dolist (m modules t)
+      (require-module m force-load))))
+
+
+(defun target-xcompile-level-1 (target &optional force)
+  (target-compile-modules (target-level-1-modules target) target force))
+
+(defun standard-boot-image-name (&optional (target (backend-name *host-backend*)))
+  (ecase target
+    (:darwinppc32 "ppc-boot.image")
+    (:linuxppc32 "ppc-boot")
+    (:darwinppc64 "ppc-boot64.image")
+    (:linuxppc64 "ppc-boot64")
+    (:darwinx8632 "x86-boot32.image")
+    (:linuxx8664 "x86-boot64")
+    (:freebsdx8664 "fx86-boot64")
+    (:darwinx8664 "x86-boot64.image")
+    (:solarisx8664 "sx86-boot64")
+    (:win64 "wx86-boot64.image")
+    (:linuxx8632 "x86-boot32")
+    (:win32 "wx86-boot32.image")
+    (:solarisx8632 "sx86-boot32")
+    (:freebsdx8632 "fx86-boot32")))
+
+(defun standard-kernel-name (&optional (target (backend-name *host-backend*)))
+  (ecase target
+    (:darwinppc32 "dppccl")
+    (:linuxppc32 "ppccl")
+    (:darwinppc64 "dppccl64")
+    (:darwinx8632 "dx86cl")
+    (:linuxppc64 "ppccl64")
+    (:linuxx8664 "lx86cl64")
+    (:freebsdx8664 "fx86cl64")
+    (:darwinx8664 "dx86cl64")
+    (:solarisx8664 "sx86cl64")
+    (:win64 "wx86cl64.exe")
+    (:linuxx8632 "lx86cl")
+    (:win32 "wx86cl.exe")
+    (:solarisx8632 "sx86cl")
+    (:freebsdx8632 "fx86cl")))
+
+(defun standard-image-name (&optional (target (backend-name *host-backend*)))
+  (concatenate 'string (pathname-name (standard-kernel-name target)) ".image"))
+
+(defun kernel-build-directory (&optional (target (backend-name *host-backend*)))
+  (ecase target
+    (:darwinppc32 "darwinppc")
+    (:linuxppc32 "linuxppc")
+    (:darwinppc64 "darwinppc64")
+    (:linuxppc64 "linuxppc64")
+    (:darwinx8632 "darwinx8632")
+    (:linuxx8664 "linuxx8664")
+    (:freebsdx8664 "freebsdx8664")
+    (:darwinx8664 "darwinx8664")
+    (:solarisx8664 "solarisx64")
+    (:win64 "win64")
+    (:linuxx8632 "linuxx8632")
+    (:win32 "win32")
+    (:solarisx8632 "solarisx86")
+    (:freebsdx8632 "freebsdx8632")))
+
+;;; If we distribute (e.g.) 32- and 64-bit versions for the same
+;;; machine and OS in the same svn directory, return the name of the
+;;; peer backend, or NIL. For example., the peer of :linuxppc64 is
+;;; :linuxppc32.  Note that this may change over time.
+;;; Return NIL if the concept doesn't apply.
+(defun peer-platform (&optional (target (backend-name *host-backend*)))
+  (let* ((pairs '((:darwinppc32 . :darwinppc64)
+                  (:linuxppc32 . :linuxppc64)
+                  (:darwinx8632 . :darwinx8664)
+                  (:linuxx8632 . :linuxx8664)
+                  (:win32 . :win64)
+                  (:solarisx8632 . :solarisx8664)
+                  (:freebsdx8632 . :freebsdx8664))))
+    (or (cdr (assoc target pairs))
+        (car (rassoc target pairs)))))
+
+(defun make-program (&optional (target (backend-name *host-backend*)))
+  ;; The Solaris "make" program is too clever to understand -C, so
+  ;; use GNU make (installed as "gmake").
+  (case target
+    ((:solarisx8664 :solarisx8632) "gmake")
+    (t "make")))
+
+
+(defun describe-external-process-failure (proc reminder)
+  "If it appears that the external-process PROC failed in some way,
+try to return a string that describes that failure.  If it seems
+to have succeeded or if we can't tell why it failed, return NIL.
+This is mostly intended to describe process-creation/fork/exec failures,
+not runtime errors reported by a successfully created process."
+  (multiple-value-bind (status exit-code)
+      (external-process-status proc)
+    (let* ((procname (car (external-process-args proc)))
+           (string
+            (case status
+              (:error
+               (%strerror exit-code))
+              #-windows-target
+              (:exited
+               (when(= exit-code #$EX_OSERR)
+                 "generic OS error in fork/exec")))))
+      (when string
+        (format nil "Error executing ~a: ~a~&~a" procname string reminder)))))
+
+(defparameter *known-optional-features* '(:count-gf-calls :monitor-futex-wait :unique-dcode))
+(defvar *build-time-optional-features* nil)
+(defvar *ccl-save-source-locations* :no-text)
+
+(defun rebuild-ccl (&key update full clean kernel force (reload t) exit reload-arguments verbose optional-features (save-source-locations *ccl-save-source-locations*))
+  (let* ((*build-time-optional-features* (intersection *known-optional-features* optional-features))
+         (*features* (append *build-time-optional-features* *features*))
+	 (*save-source-locations* save-source-locations))
+    (when *build-time-optional-features*
+      (setq full t))
+    (when full
+      (setq clean t kernel t reload t))
+    (when update
+      (multiple-value-bind (changed conflicts new-binaries)
+	  (update-ccl :verbose (not (eq update :quiet)))
+	(declare (ignore changed conflicts))
+	(when new-binaries
+	  (format t "~&There are new bootstrapping binaries.  Please restart
+the lisp and run REBUILD-CCL again.")
+	  (return-from rebuild-ccl nil))))
+    (when (or clean force)
+      ;; for better bug reports...
+      (format t "~&Rebuilding ~a using ~a"
+              (lisp-implementation-type)
+              (lisp-implementation-version)))
+    (let* ((cd (current-directory)))
+      (unwind-protect
+           (progn
+             (setf (current-directory) "ccl:")
+             (when clean
+               (dolist (f (directory
+                           (merge-pathnames
+                            (make-pathname :name :wild
+                                           :type (pathname-type *.fasl-pathname*))
+                            "ccl:**;")))
+                 (delete-file f)))
+             (when kernel
+               (when (or clean force)
+                 ;; Do a "make -k clean".
+                 (run-program "make"
+                              (list "-k"
+                                    "-C"
+                                    (format nil "lisp-kernel/~a"
+                                            (kernel-build-directory))
+                                    "clean")))
+               (format t "~&;Building lisp-kernel ...")
+               (with-output-to-string (s)
+                 (let* ((proc (run-program (make-program)
+                                           (list "-k" "-C" 
+                                                 (format nil "lisp-kernel/~a"
+                                                         (kernel-build-directory))
+                                                 "-j"
+                                                            
+                                                 (format nil "~d" (1+ (cpu-count))))
+                                           :output s
+                                           :error :output)))
+                   (multiple-value-bind (status exit-code)
+                       (external-process-status proc)
+                     (if (and (eq :exited status) (zerop exit-code))
+                       (progn
+                         (format t "~&;Kernel built successfully.")
+                         (when verbose
+                           (format t "~&;kernel build output:~%~a"
+                                   (get-output-stream-string s)))
+                         (sleep 1))
+                       (error "Error(s) during kernel compilation.~%~a"
+                              (or
+                               (describe-external-process-failure
+                                proc
+                                "Developer tools may not be installed correctly.")
+                               (get-output-stream-string s))))))))
+             (compile-ccl (not (null force)))
+             (if force (xload-level-0 :force) (xload-level-0))
+             (when reload
+               (with-input-from-string (cmd (format nil
+                                              "(save-application ~s)"
+                                              (standard-image-name)))
+                 (with-output-to-string (output)
+                   (multiple-value-bind (status exit-code)
+                       (external-process-status
+                        (run-program
+                         (format nil "./~a" (standard-kernel-name))
+                         (list* "--image-name" (standard-boot-image-name)
+                                "--batch"
+                                reload-arguments)
+                         :input cmd
+                         :output output
+                         :error output))
+                     (if (and (eq status :exited)
+                              (eql exit-code 0))
+                       (progn
+                         (format t "~&;Wrote heap image: ~s"
+                                 (truename (format nil "ccl:~a"
+                                                   (standard-image-name))))
+                         (when verbose
+                           (format t "~&;Reload heap image output:~%~a"
+                                   (get-output-stream-string output))))
+                       (error "Errors (~s ~s) reloading boot image:~&~a"
+                              status exit-code
+                              (get-output-stream-string output)))))))
+             (when exit
+               (quit)))
+        (setf (current-directory) cd)))))
+                                                  
+               
+(defun create-interfaces (dirname &key target populate-arg)
+  (let* ((backend (if target (find-backend target) *target-backend*))
+         (*default-pathname-defaults* nil)
+         (ftd (backend-target-foreign-type-data backend))
+         (d (use-interface-dir dirname ftd))
+         (populate (merge-pathnames "C/populate.sh"
+                                    (merge-pathnames
+                                     (interface-dir-subdir d)
+                                     (ftd-interface-db-directory ftd))))
+         (cdir (make-pathname :directory (pathname-directory (translate-logical-pathname populate))))
+         (args (list "-c"
+                     (format nil "cd ~a && /bin/sh ~a ~@[~a~]"
+                             (native-translated-namestring cdir)
+                             (native-translated-namestring populate)
+                             populate-arg))))
+    (format t "~&;[Running interface translator via ~s to produce .ffi file(s) from headers]~&" populate)
+    (force-output t)
+    (multiple-value-bind (status exit-code)
+        (external-process-status
+         (run-program "/bin/sh" args :output t))
+      (if (and (eq status :exited)
+               (eql exit-code 0))
+        (let* ((f 'parse-standard-ffi-files))
+          (require "PARSE-FFI")
+          (format t "~%~%;[Parsing .ffi files; may create new .cdb files for ~s]" dirname)
+          (funcall f dirname target)
+          (format t "~%~%;[Parsing .ffi files again to resolve forward-referenced constants]")
+          (funcall f dirname target))))))
+
+(defun update-ccl (&key (verbose t))
+  (let* ((changed ())
+	 (new-binaries ())
+         (conflicts ()))
+    (with-output-to-string (out)
+      (with-preserved-working-directory ("ccl:")                     
+        (when verbose (format t "~&;Running 'svn update'."))
+        (multiple-value-bind (status exit-code)
+            (external-process-status
+             (run-program "svn" '("update" "--non-interactive") :output out :error t))
+          (when verbose (format t "~&;'svn update' complete."))
+          (if (not (and (eq status :exited)
+                        (eql exit-code 0)))
+            (error "Running \"svn update\" produced exit status ~s, code ~s." status exit-code)
+            (let* ((sout (get-output-stream-string out))
+                   (added ())
+                   (deleted ())
+                   (updated ())
+                   (merged ())
+                   (binaries (list (standard-kernel-name) (standard-image-name )))
+                   (peer (peer-platform)))
+              (when peer
+                (push (standard-kernel-name peer) binaries)
+                (push (standard-image-name peer) binaries))
+              (flet ((svn-revert (string)
+                       (multiple-value-bind (status exit-code)
+                           (external-process-status (run-program "svn" `("revert" ,string)))
+                         (when (and (eq status :exited) (eql exit-code 0))
+                           (setq conflicts (delete string conflicts :test #'string=))
+                           (push string updated)))))
+                (with-input-from-string (in sout)
+                  (do* ((line (read-line in nil nil) (read-line in nil nil)))
+                       ((null line))
+                    (when (and (> (length line) 2)
+                               (eql #\space (schar line 1)))
+                      (let* ((path (string-trim " " (subseq line 2))))
+                        (case (schar line 0)
+                          (#\A (push path added))
+                          (#\D (push path deleted))
+                          (#\U (push path updated))
+                          (#\G (push path merged))
+                          (#\C (push path conflicts)))))))
+                ;; If the kernel and/or image conflict, use "svn revert"
+                ;; to replace the working copies with the (just updated)
+                ;; repository versions.
+                (setq changed (if (or added deleted updated merged conflicts) t))
+                (dolist (f binaries)
+		  (cond ((member f conflicts :test #'string=)
+			 (svn-revert f)
+			 (setq new-binaries t))
+			((or (member f updated :test #'string=)
+			     (member f merged :test #'string=))
+			 (setq new-binaries t))))
+
+                ;; If there are any remaining conflicts, offer
+                ;; to revert them.
+                (when conflicts
+                  (with-preserved-working-directory ()
+                    (cerror "Discard local changes to these files (using 'svn revert')."
+                            "'svn update' was unable to merge local changes to the following file~p with the updated versions:~{~&~s~}" (length conflicts) conflicts)
+                    (dolist (c (copy-list conflicts))
+                      (svn-revert c))))
+                ;; Report other changes, if verbose.
+                (when (and verbose
+                           (or added deleted updated merged conflicts))
+                  (format t "~&;Changes from svn update:")
+                  (flet ((show-changes (herald files)
+                           (when files
+                             (format t "~&; ~a:~{~&;  ~a~}"
+                                     herald files))))
+                    (show-changes "Conflicting files" conflicts)
+                    (show-changes "New files/directories" added)
+                    (show-changes "Deleted files/directories" deleted)
+                    (show-changes "Updated files" updated)
+                    (show-changes "Files with local changes, successfully merged" merged)))))))))
+    (values changed conflicts new-binaries)))
+
+(defmacro with-preserved-working-directory ((&optional dir) &body body)
+  (let ((wd (gensym)))
+    `(let ((,wd (mac-default-directory)))
+       (unwind-protect
+	    (progn 
+	      ,@(when dir `((cwd ,dir)))
+	      ,@body)
+	 (cwd ,wd)))))
+
+(defun ensure-tests-loaded (&key force update ansi ccl)
+  (unless (and (find-package "REGRESSION-TEST") (not force))
+    (if (probe-file "ccl:tests;ansi-tests;")
+      (when update
+	(cwd "ccl:tests;")
+	(run-program "svn" '("update")))
+      (let* ((svn (probe-file "ccl:.svn;entries"))
+	     (repo (and svn (svn-repository)))
+	     (s (make-string-output-stream)))
+	(when repo
+	  (format t "~&Checking out test suite into ccl:tests;~%")
+	  (cwd "ccl:")
+	  (multiple-value-bind (status exit-code)
+	      (external-process-status
+	       (run-program "svn" (list "checkout" (format nil "~a/trunk/tests" repo) "tests")
+			    :output s
+			    :error s))
+	    (unless (and (eq status :exited)
+			 (eql exit-code 0))
+	      (error "Failed to check out test suite: ~%~a" (get-output-stream-string s)))))))
+    (cwd "ccl:tests;ansi-tests;")
+    (run-program "make" '("-k" "clean"))
+    (map nil 'delete-file (directory "*.*fsl"))
+    ;; Muffle the typecase "clause ignored" warnings, since there is really nothing we can do about
+    ;; it without making the test suite non-portable across platforms...
+    (handler-bind ((warning (lambda (c)
+			      (when (let ((w (or (and (typep c 'compiler-warning)
+                                                      (eq (compiler-warning-warning-type c) :program-error)
+                                                      (car (compiler-warning-args c)))
+                                                 c)))
+                                      (and (typep w 'simple-warning)
+                                           (or 
+                                            (string-equal
+                                             (simple-condition-format-control w)
+                                             "Clause ~S ignored in ~S form - shadowed by ~S .")
+                                            ;; Might as well ignore these as well, they're intentional.
+                                            (string-equal
+                                             (simple-condition-format-control w)
+                                             "Duplicate keyform ~s in ~s statement."))))
+				(muffle-warning c)))))
+      ;; This loads the infrastructure
+      (load "ccl:tests;ansi-tests;gclload1.lsp")
+      ;; This loads the actual tests
+      (let ((redef-var (find-symbol "*WARN-IF-REDEFINE-TEST*" :REGRESSION-TEST)))
+	(progv (list redef-var) (list (if force nil (symbol-value redef-var)))
+          (when ansi
+            (load "ccl:tests;ansi-tests;gclload2.lsp"))
+	  ;; And our own tests
+          (when ccl
+            (load "ccl:tests;ansi-tests;ccl.lsp")))))))
+
+(defun test-ccl (&key force (update t) verbose (catch-errors t) (ansi t) (ccl t)
+                      optimization-settings)
+  (with-preserved-working-directory ()
+    (let* ((*package* (find-package "CL-USER")))
+      (ensure-tests-loaded :force force :update update :ansi ansi :ccl ccl)
+      (cwd "ccl:tests;ansi-tests;")
+      (let ((do-tests (find-symbol "DO-TESTS" "REGRESSION-TEST"))
+            (failed (find-symbol "*FAILED-TESTS*" "REGRESSION-TEST"))
+            (*print-catch-errors* nil))
+        (prog1
+            (time (funcall do-tests :verbose verbose :compile t
+                           :catch-errors catch-errors
+                           :optimization-settings (or optimization-settings '((safety 2)))))
+          ;; Clean up a little
+          (map nil #'delete-file
+               (directory (merge-pathnames *.fasl-pathname* "ccl:tests;ansi-tests;temp*"))))
+        (symbol-value failed)))))
Index: /branches/new-random/lib/db-io.lisp
===================================================================
--- /branches/new-random/lib/db-io.lisp	(revision 13309)
+++ /branches/new-random/lib/db-io.lisp	(revision 13309)
@@ -0,0 +1,1898 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 2001 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; The "CDB" files used here are similar (but not identical) to those
+;;; used in the Unix CDB package <http://cr.yp.to/cdb.html>.  The primary
+;;; known & intentional differences are:
+;;;
+;;; a) key values, record positions, and other 32-bit metadata in the
+;;;    files are stored in native (vice little-endian) order.
+;;; b) hash values are always non-negative fixnums.
+;;;
+;;; I haven't thought of a compelling reason to attempt full compatibility.
+;;;
+;;; The basic idea is that the database files are created in a batch
+;;; process and are henceforth read-only (e.g., lookup is optimized by
+;;; making insertion & deletion impractical or impossible.)  That's
+;;; just about exactly what we want here.
+;;;
+;;; Those of you keeping score may notice that this is the third or forth
+;;; database format that Clozure CL has used for its interface database.
+;;; As always, this will hopefully be the last format change; the fact
+;;; that this code is self-contained (doesn't depend on any Unix database
+;;; library) should make it easier to port to other platforms.
+
+(in-package "CCL")
+
+(defparameter *interface-abi-version* 2)
+(defparameter *min-interface-abi-version* 1)
+
+(defconstant cdb-hash-mask (1- (ash 1 29)))
+
+(defun cdb-hash (buf len)
+  (declare (fixnum len))
+  (let* ((h 5381))
+    (declare (fixnum h))
+    (dotimes (i len (logand h cdb-hash-mask))
+      (setq h (+ h (the fixnum (logand cdb-hash-mask (ash h 5)))))
+      (setq h (logxor (the (unsigned-byte 8) (%get-unsigned-byte buf i)) h)))))
+
+(defconstant cdbm-hplist 1000)
+
+(defmacro hp-h (v n)
+  `(aref ,v (* ,n 2)))
+
+(defmacro hp-p (v n)
+  `(aref ,v (1+ (* ,n 2))))
+
+(defstruct cdbm-hplist
+  (hp (make-array (* 2 cdbm-hplist)
+		  :element-type '(unsigned-byte 32)
+		  :initial-element 0))
+  (next nil)
+  (num 0))
+
+
+
+
+
+#+openmcl
+(progn
+  ;;; Given a (possibly logical) PATHNAME, return a corresponding namestring
+  ;;; suitable for passing to an OS file-open call.
+  (defun cdb-native-namestring (pathname)
+    (native-translated-namestring pathname))
+  
+  ;;; Open the file specified by PATHNAME for output and return a
+  ;;; small integer "file id" (fid).
+  (defun fid-open-output (pathname)
+    (let ((dir (make-pathname :type nil :name nil :defaults pathname)))
+      (unless (probe-file dir)
+	(error "The directory ~S does not exist, cannot open/create ~S"
+	       dir pathname)))
+    (let* ((id (fd-open (cdb-native-namestring pathname)
+			(logior #$O_WRONLY #$O_CREAT #$O_TRUNC))))
+      (if (< id 0)
+	(%errno-disp id pathname)
+	id)))
+
+  ;;; Open the file specified by PATHNAME for input and return a
+  ;;; file id.
+  #-windows-target
+  (defun fid-open-input (pathname)
+    (let* ((id (fd-open (cdb-native-namestring pathname) #$O_RDONLY)))
+      (if (< id 0)
+	(%errno-disp id pathname)
+	id)))
+  ;; On Windows, open() can't open the same file twice, which breaks
+  ;; bootstrapping.  Use CreateFile instead, and tell it to share.
+  #+windows-target
+  (defun fid-open-input (pathname)
+    (with-filename-cstrs ((name (cdb-native-namestring pathname)))
+      (let* ((handle (#_CreateFileW
+				   name
+				   #$GENERIC_READ
+				   #$FILE_SHARE_READ
+				   (%null-ptr)
+				   #$OPEN_EXISTING
+				   #$FILE_ATTRIBUTE_NORMAL
+				   (%null-ptr))))
+	(if (eql handle *windows-invalid-handle*)
+	  (error "Error opening CDB database ~S" pathname)
+	  (%ptr-to-int handle)))))
+
+  ;;; Read N octets from FID into BUF.  Return #of octets read or error.
+  (defun fid-read (fid buf n)
+    (let* ((count (fd-read fid buf n)))
+      (if (< count 0)
+	(%errno-disp count "reading from file")
+	count)))
+
+  ;;; Write N octets to FID from BUF.  Return #of octets written or error.
+  (defun fid-write (fid buf n)
+    (let* ((count (fd-write fid buf n)))
+      (if (< count 0)
+	(%errno-disp count "writing to file")
+	count)))
+
+  ;;; Return the absolute (octet) position of FID.
+  (defun fid-pos (fid)
+    (fd-tell fid))
+
+  ;;; Return the current size of the file referenced by FID, in
+  ;;; octets.
+  (defun fid-size (fid)
+    (fd-size fid))
+  
+  ;;; Seek to specified position (relative to file start.)
+  (defun fid-seek (fid pos)
+    (fd-lseek fid pos #$SEEK_SET))
+
+  ;;; Guess what this does ?
+  (defun fid-close (fid)
+    (fd-close fid))
+
+  ;;; Allocate a block of size N bytes (via malloc, #_NewPtr, etc.)
+  (defun cdb-alloc (n)
+    (malloc n))
+
+  ;;; Free a block allocated by cdb-alloc.
+  (defun cdb-free (block)
+    (free block))
+  )
+
+;;; I suppose that if we wanted to store these things in little-endian
+;;; order this'd be the place to swap bytes ...
+(defun fid-write-u32 (fid val)
+  (%stack-block ((valptr 4))
+    (setf (%get-unsigned-long valptr) val)
+    (fid-write fid valptr 4)
+    val))
+
+(defun fid-read-u32 (fid)
+  (%stack-block ((valptr 4))
+    (fid-read fid valptr 4)
+    (%get-unsigned-long valptr)))
+
+
+
+;;; Write N elements of a vector of type (UNSIGNED-BYTE 32) to file-id
+;;; FID, starting at element START.  The vector should be a simple
+;;; (non-displaced) array.
+(defun fid-write-u32-vector (fid v n start)
+  (let* ((remaining-octets (* n 4))
+	 (start-octet (* start 4))
+	 (bufsize 2048))
+    (%stack-block ((buf bufsize))
+      (do* ()
+	   ((zerop remaining-octets))
+	(let* ((chunksize (min remaining-octets bufsize)))
+	  (%copy-ivector-to-ptr v start-octet buf 0 chunksize)
+	  (fid-write fid buf chunksize)
+	  (incf start-octet chunksize)
+	  (decf remaining-octets chunksize))))))
+
+(defstruct cdbx
+  fid					;a small integer denoting a file
+  pathname)				;that file's pathname
+
+;;; A CDBM is used to create a database.
+(defstruct (cdbm (:include cdbx))
+  (final (make-array (* 256 2)
+		     :element-type '(unsigned-byte 32)
+		     :initial-element 0))
+  (count (make-array 256 :element-type '(unsigned-byte 32) :initial-element 0))
+  (start (make-array 256 :element-type '(unsigned-byte 32) :initial-element 0))
+  (head nil)
+  (split nil)
+  (hash nil)
+  (numentries 0)
+  )
+
+(defun cdbm-open (pathname)
+  (let* ((fid (fid-open-output pathname))
+	 (cdbm (make-cdbm :fid fid :pathname pathname))
+	 (final (cdbm-final cdbm)))
+    ;;; Write the (empty) final table to the start of the file.  Twice.
+    (fid-write-u32-vector fid final (length final) 0)
+    (fid-write-u32-vector fid final (length final) 0)
+    cdbm))
+
+;;; Note a newly-added <key,value> pair's file position and hash code.
+(defun %cdbm-add-hash-pos (cdbm hash pos)
+  (let* ((head (cdbm-head cdbm)))
+    (when (or (null head)
+	      (>= (cdbm-hplist-num head) cdbm-hplist))
+      (setq head (make-cdbm-hplist))
+      (setf (cdbm-hplist-next head) (cdbm-head cdbm)
+	    (cdbm-head cdbm) head))
+    (let* ((num (cdbm-hplist-num head))
+	   (hp (cdbm-hplist-hp head)))
+      (setf (hp-h hp num) hash
+	    (hp-p hp num) pos))
+    (incf (cdbm-hplist-num head))
+    (incf (cdbm-numentries cdbm))))
+
+(defun cdbm-put (cdbm key data)
+  (let* ((fid (cdbm-fid cdbm))
+	 (pos (fid-pos fid))
+	 (keylen (pref key :cdb-datum.size))
+	 (keyptr (pref key :cdb-datum.data))
+	 (datalen (pref data :cdb-datum.size))
+	 (hash (cdb-hash keyptr keylen)))
+    (fid-write-u32 fid keylen)
+    (fid-write-u32 fid datalen)
+    (fid-write fid keyptr keylen)
+    (fid-write fid (pref data :cdb-datum.data) datalen)
+    (%cdbm-add-hash-pos cdbm hash pos)))
+
+(defun %cdbm-split (cdbm)
+  (let* ((count (cdbm-count cdbm))
+	 (start (cdbm-start cdbm))
+	 (numentries (cdbm-numentries cdbm)))
+    (dotimes (i 256) (setf (aref count i) 0))
+    (do* ((x (cdbm-head cdbm) (cdbm-hplist-next x)))
+	 ((null x))
+      (do* ((i (cdbm-hplist-num x))
+	    (hp (cdbm-hplist-hp x)))
+	   ((zerop i))
+	(decf i)
+	(incf (aref count (logand 255 (hp-h hp i))))))
+    (let* ((memsize 1))
+      (dotimes (i 256)
+	(let* ((u (* 2 (aref count i))))
+	  (if (> u memsize)
+	    (setq memsize u))))
+      (incf memsize numentries)
+      (let* ((split (make-array (the fixnum (* 2 memsize))
+				:element-type '(unsigned-byte 32))))
+	(setf (cdbm-split cdbm) split)
+	(setf (cdbm-hash cdbm)
+	      (make-array (- (* 2 memsize)
+			     (* 2 numentries))
+			  :element-type '(unsigned-byte 32)
+			  :displaced-to split
+			  :displaced-index-offset (* 2 numentries)))
+	(let* ((u 0))
+	  (dotimes (i 256)
+	    (incf u (aref count i))
+	    (setf (aref start i) u)))
+
+	(do* ((x (cdbm-head cdbm) (cdbm-hplist-next x)))
+	     ((null x))
+	  (do* ((i (cdbm-hplist-num x))
+		(hp (cdbm-hplist-hp x)))
+	       ((zerop i))
+	    (decf i)
+	    (let* ((idx (decf (aref start (logand 255 (hp-h hp i))))))
+	      (setf (hp-h split idx) (hp-h hp i)
+		    (hp-p split idx) (hp-p hp i)))))))))
+
+(defun %cdbm-throw (cdbm pos b)
+  (let* ((count (aref (cdbm-count cdbm) b))
+	 (len (* 2 count))
+	 (hash (cdbm-hash cdbm))
+	 (split (cdbm-split cdbm)))
+    (let* ((final (cdbm-final cdbm)))
+      (setf (aref final (* 2 b)) pos
+	    (aref final (1+ (* 2 b))) len))
+    (unless (zerop len)
+      (dotimes (j len)
+	(setf (hp-h hash j) 0
+	      (hp-p hash j) 0))
+      (let* ((hpi (aref (cdbm-start cdbm) b)))
+	(dotimes (j count)
+	  (let* ((where (mod (ash (hp-h split hpi) -8) len)))
+	    (do* ()
+		 ((zerop (hp-p hash where)))
+	      (incf where)
+	      (if (= where len)
+		(setq where 0)))
+	    (setf (hp-p hash where) (hp-p split hpi)
+		  (hp-h hash where) (hp-h split hpi)
+		  hpi (1+ hpi))))))
+    len))
+
+;;; Write data structures to the file, then close the file.
+(defun cdbm-close (cdbm)
+  (when (cdbm-fid cdbm)
+    (%cdbm-split cdbm)
+    (let* ((hash (cdbm-hash cdbm))
+	   (fid (cdbm-fid cdbm))
+	   (pos (fid-pos fid)))
+      (dotimes (i 256)
+	(let* ((len (%cdbm-throw cdbm pos i)))
+	  (dotimes (u len)
+	    (fid-write-u32 fid (hp-h hash u))
+	    (fid-write-u32 fid (hp-p hash u))
+	    (incf pos 8))))
+      (write-cdbm-trailer cdbm)
+      (fid-seek fid (* 256 2 4)) ; skip the empty "final" table, write the new one
+      (let* ((final (cdbm-final cdbm)))
+	(fid-write-u32-vector fid final (length final) 0))
+      (fid-close fid)
+      (setf (cdbm-fid cdbm) nil))))
+
+(defun write-cdbm-trailer (cdbm)
+  (let* ((string (format nil "~s ~s ~d " "OpenMCL Interface File" (backend-name *target-backend*) *interface-abi-version*)))
+    (%stack-block ((buf 512))
+      (%cstr-pointer string buf)
+      (fid-write (cdbm-fid cdbm) buf 512))))
+
+      
+;;; A CDB is used to access a database.
+(defstruct (cdb (:include cdbx))
+  (lock (make-lock)))
+
+      
+;;; Do the bytes on disk match KEY ?
+(defun %cdb-match (fid key keylen)
+  (%stack-block ((buf keylen))
+    (fid-read fid buf keylen)
+    (dotimes (i keylen t)
+      (unless (= (the fixnum (%get-unsigned-byte key i))
+		 (the fixnum (%get-unsigned-byte buf i)))
+	(return)))))
+
+;;; Seek to file position of data associated with key.  Return length
+;;; of data (or NIL if no matching key.)
+(defun %cdb-seek (fid key keylen)
+  (let* ((hash (cdb-hash key keylen)))
+    (fid-seek fid (+ (* 256 2 4) (* 8 (logand hash 255))))
+    (let* ((pos (fid-read-u32 fid))
+           (lenhash (fid-read-u32 fid)))
+      (unless (zerop lenhash)
+        (let* ((h2 (mod (ash hash -8) lenhash)))
+          (dotimes (i lenhash)
+            (fid-seek fid (+ pos (* 8 h2)))
+            (let* ((hashed-key (fid-read-u32 fid))
+                   (poskd (fid-read-u32 fid)))
+              (when (zerop poskd)
+                (return-from %cdb-seek nil))
+              (when (= hashed-key hash)
+                (fid-seek fid poskd)
+                (let* ((hashed-key-len (fid-read-u32 fid))
+                       (data-len (fid-read-u32 fid)))
+                  (when (= hashed-key-len keylen)
+                    (if (%cdb-match fid key keylen)
+                      (return-from %cdb-seek data-len)))))
+              (if (= (incf h2) lenhash)
+                (setq h2 0)))))))))
+
+;;; This should only be called with the cdb-lock of the containing cdb
+;;; held.
+(defun %cdb-get (fid key value)
+  (setf (pref value :cdb-datum.size) 0
+	(pref value :cdb-datum.data) (%null-ptr))
+  (when fid
+    (let* ((datalen (%cdb-seek fid
+                               (pref key :cdb-datum.data)
+                               (pref key :cdb-datum.size))))
+      (when datalen
+        (let* ((buf (cdb-alloc datalen)))
+          (fid-read fid buf datalen)
+          (setf (pref value :cdb-datum.size) datalen
+                (pref value :cdb-datum.data) buf)))
+      value)))
+
+(defun cdb-get (cdb key value)
+  (with-lock-grabbed ((cdb-lock cdb))
+    (%cdb-get (cdb-fid cdb) key value)))
+
+(defun cdb-subdirectory-path (&optional (ftd *target-ftd*))
+  (let* ((ftd-name (ftd-interface-db-directory ftd))
+	 (ftd-dir (pathname-directory ftd-name)))
+    (assert (equalp (pathname-host ftd-name) "ccl"))
+    (assert (eq (car ftd-dir) :absolute))
+    (cdr ftd-dir)))
+
+(defvar *interfaces-root* "ccl:")
+
+(defun open-interface-db-pathname (name d)
+  (let* ((db-path (make-pathname :host (pathname-host *interfaces-root*)
+				 :directory (append
+					     (or (pathname-directory *interfaces-root*)
+						 '(:absolute))
+					     (cdb-subdirectory-path *target-ftd*))))
+	 (path (merge-pathnames name
+				(merge-pathnames (interface-dir-subdir d) db-path))))
+    (cdb-open path)))
+
+(defun cdb-open (pathname)
+  (if (probe-file pathname)
+    (let* ((cdb (make-cdb :fid (fid-open-input (cdb-native-namestring pathname))
+                          :pathname (namestring pathname))))
+      (cdb-check-trailer cdb))
+    (progn
+      (if (probe-file (make-pathname :name nil :type nil :defaults pathname))
+        (warn "Interface file ~s does not exist." pathname)
+        (warn "Interface file ~s does not exist, and the containing directory does not exist.~%This may mean that that the \"ccl:\" logical-pathname host has not been properly initialized. " (translate-logical-pathname pathname)))
+      (make-cdb :fid nil :pathname (namestring pathname)))))
+
+(defun cdb-check-trailer (cdb)
+  (flet ((error-with-cdb (string &rest args)
+           (error "Error in interface file at ~s: ~a"
+                  (cdb-pathname cdb) (apply #'format nil string args))))
+    (let* ((fid (cdb-fid cdb)))
+      (fid-seek fid (- (fid-size fid) 512))
+      (%stack-block ((buf 512))
+        (fid-read fid buf 512)
+        (let* ((string (make-string 512)))
+          (dotimes (i 512)
+            (setf (%scharcode string i) (%get-unsigned-byte buf i)))
+          (with-input-from-string (s string)
+            (let* ((sig (ignore-errors (read s)))
+                   (target (ignore-errors (read s)))
+                   (version (ignore-errors (read s))))
+              (if (equal sig "OpenMCL Interface File")
+                (if (eq target (backend-name *target-backend*))
+                  (if (and version
+                           (>= version *min-interface-abi-version*)
+                           (<=  version *interface-abi-version*))
+                    cdb
+                    (error-with-cdb "Wrong interface ABI version. Expected ~d, got ~d" *interface-abi-version* version))
+                  cdb #+nil(error-with-cdb "Wrong target."))
+                (error-with-cdb "Missing interface file signature.  Obsolete version?")))))))))
+
+                  
+    
+(defun cdb-close (cdb)
+  (let* ((fid (cdb-fid cdb)))
+    (setf (cdb-fid cdb) nil)
+    (when fid
+      (fid-close fid))
+    t))
+
+(defmethod print-object ((cdb cdbx) stream)
+  (print-unreadable-object (cdb stream :type t :identity t)
+    (let* ((fid (cdb-fid cdb)))
+      (format stream "~s [~a]" (cdb-pathname cdb) (or fid "closed")))))
+
+
+(defun cdb-enumerate-keys (cdb &optional (predicate #'true))
+  "Returns a list of all keys (strings) in the open .cdb file CDB which
+satisfy the optional predicate PREDICATE."
+  (with-lock-grabbed ((cdb-lock cdb))
+    (let* ((keys ())
+           (fid (cdb-fid cdb)))
+      (dotimes (i 256 keys)
+        (fid-seek fid (+ (* 256 2 4) (* 8 i)))
+        (let* ((pos (fid-read-u32 fid))
+               (n (fid-read-u32 fid)))
+          (dotimes (j n)
+            (fid-seek fid (+ pos (* 8 j) 4))
+            (let* ((posk (fid-read-u32 fid)))
+              (unless (zerop posk)
+                (fid-seek fid posk)
+                (let* ((hashed-key-len (fid-read-u32 fid)))
+                  ;; Skip hashed data length
+                  (fid-read-u32 fid)
+                  (let* ((string (make-string hashed-key-len)))
+                    (%stack-block ((buf hashed-key-len))
+                      (fid-read fid buf hashed-key-len)
+                      (dotimes (k hashed-key-len)
+                        (setf (schar string k)
+                              (code-char (%get-unsigned-byte buf k)))))
+                    (when (funcall predicate string)
+                      (push (copy-seq string) keys))))))))))))
+                                        ;
+                  
+
+
+(defstruct ffi-type
+  (ordinal nil)
+  (defined nil)
+  (string)
+  (name)                                ; a keyword, uppercased or NIL
+)
+
+(defmethod print-object ((x ffi-type) out)
+  (print-unreadable-object (x out :type t :identity t)
+    (format out "~a" (ffi-type-string x))))
+
+(defvar *ffi-prefix* "")
+
+(defstruct (ffi-mem-block (:include ffi-type))
+  fields
+  (anon-global-id )
+  (alt-alignment-bits nil))
+
+(defstruct (ffi-union (:include ffi-mem-block)
+                      (:constructor
+                       make-ffi-union (&key
+                                       string name
+                                       &aux
+                                       (anon-global-id
+                                        (unless name
+                                          (concatenate 'string
+                                                       *ffi-prefix*
+                                                       "-" string)))))))
+
+
+(defstruct (ffi-transparent-union (:include ffi-mem-block)
+                                  (:constructor
+                                   make-ffi-transparent-union (&key
+                                                               string name
+                                                               &aux
+                                                               (anon-global-id
+                                                                (unless name
+                                                                  (concatenate 'string
+                                                                               *ffi-prefix*
+                                                                               "-" string)))))))
+(defstruct (ffi-struct (:include ffi-mem-block)
+                       (:constructor
+                       make-ffi-struct (&key
+                                       string name
+                                       &aux
+                                       (anon-global-id
+                                        (unless name
+                                          (concatenate 'string
+                                                       *ffi-prefix*
+                                                       "-" string)))))))
+
+(defstruct (ffi-typedef (:include ffi-type))
+  (type))
+
+(defstruct (ffi-objc-class (:include ffi-type))
+  super-foreign-name
+  protocol-names
+  own-ivars
+  )
+
+(defstruct (ffi-objc-method)
+  class-name
+  arglist
+  result-type
+  flags)
+
+(defstruct (ffi-objc-message (:include ffi-type))
+  methods)
+                            
+
+(defun ffi-struct-reference (s)
+  (or (ffi-struct-name s) (ffi-struct-anon-global-id s)))
+
+(defun ffi-union-reference (u)
+  (or (ffi-union-name u) (ffi-union-anon-global-id u)))
+
+(defun ffi-transparent-union-reference (u)
+  (or (ffi-transparent-union-name u) (ffi-transparent-union-anon-global-id u)))
+
+(defstruct (ffi-function (:include ffi-type))
+  arglist
+  return-value)
+    
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defconstant db-string-constant 0)
+(defconstant db-read-string-constant 1)
+(defconstant db-s32-constant 2)
+(defconstant db-u32-constant 3)
+(defconstant db-float-constant 4)
+(defconstant db-double-constant 5)
+(defconstant db-char-constant 6)
+(defconstant db-pointer-constant 7)
+)
+
+(defparameter *arg-spec-encoding*
+  '((#\Space . :void)
+    (#\a . :address)
+    (#\F . :signed-fullword)
+    (#\f . :unsigned-fullword)
+    (#\H . :signed-halfword)
+    (#\h . :unsigned-halfword)
+    (#\B . :signed-byte)
+    (#\b . :unsigned-byte)
+    (#\s . :single-float)
+    (#\d . :double-float)
+    (#\L . :signed-doubleword)
+    (#\l . :unsigned-doubleword)
+    (#\r . :record)))
+
+
+
+(defun decode-arguments (string)
+  (let* ((result nil))
+    (collect ((args))
+      (do* ((i 0 (1+ i)))
+           ((= i (length string)) (values (args) result))
+        (declare (fixnum i))
+        (let* ((ch (schar string i))
+               (val (if (or (eql ch #\r) (eql ch #\u) (eql ch #\t))
+                      (let* ((namelen (char-code (schar string (incf i))))
+                             (name (make-string namelen)))
+                        (dotimes (k namelen)
+                          (setf (schar name k)
+                                (schar string (incf i))))
+                        (setq name (escape-foreign-name name))
+                        (if (eql ch #\r)
+                          `(:struct ,name)
+                          (if (eql ch #\u)
+                            `(:union ,name)
+                            (if (eql ch #\U)
+                              `(:transparent-union ,name)
+                              name))))
+                      (cdr (assoc ch *arg-spec-encoding*)))))
+          (if result
+            (args val)
+            (setq result val)))))))
+
+
+;;; encoded external function looks like:
+;;; byte min-args
+;;; byte name-length
+;;; name-length bytes of name
+;;; result+arg specs
+
+(defun extract-db-function (datum)
+  (let* ((val nil)
+         (dsize (pref datum :cdb-datum.size)))
+    (with-macptrs ((dptr))
+      (%setf-macptr dptr (pref datum :cdb-datum.data))
+      (unless (%null-ptr-p dptr)
+	(let* ((min-args (%get-byte dptr))
+	       (name-len (%get-byte dptr 1))
+	       (external-name (%str-from-ptr (%inc-ptr dptr 2) name-len))
+	       (encoding-len (- dsize (+ 2 name-len)))
+	       (encoding (make-string encoding-len)))
+	  (declare (dynamic-extent encoding))
+          (%str-from-ptr (%inc-ptr dptr (+ 2 name-len)) encoding-len encoding)
+	  (cdb-free (pref datum :cdb-datum.data))
+	  (multiple-value-bind (args result)
+	      (decode-arguments encoding)
+	    (setq val (make-external-function-definition
+		       :entry-name external-name
+		       :arg-specs args
+		       :result-spec result
+		       :min-args min-args))))))
+    val))
+
+(defun db-lookup-function (cdb name)
+  (when cdb
+    (rletZ ((value :cdb-datum)
+            (key :cdb-datum))
+      (with-cstrs ((keyname (string name)))
+        (setf (pref key :cdb-datum.data) keyname
+              (pref key :cdb-datum.size) (length (string name))
+              (pref value :cdb-datum.data) (%null-ptr)
+              (pref value :cdb-datum.size) 0)
+        (cdb-get cdb key value)
+        (extract-db-function value)))))
+
+
+
+
+        
+(defun extract-db-constant-value (datum)
+  (let* ((val nil)
+         (dsize (pref datum :cdb-datum.size)))
+    (with-macptrs ((dptr))
+      (%setf-macptr dptr (pref datum :cdb-datum.data))
+      (unless (%null-ptr-p dptr)
+	(let* ((class (pref dptr :dbm-constant.class)))
+	  (setq val
+		(ecase class
+                  ((#.db-string-constant #.db-read-string-constant)
+                   (let* ((str (%str-from-ptr (%inc-ptr dptr 4) (- dsize 4))))
+                     (if (eql class db-read-string-constant)
+                       (read-from-string str)
+                       str)))
+                  (#.db-s32-constant (pref dptr :dbm-constant.value.s32))
+                  (#.db-u32-constant (pref dptr :dbm-constant.value.u32))
+                  (#.db-float-constant (pref dptr :dbm-constant.value.single-float))
+                  (#.db-double-constant (pref dptr :dbm-constant.value.double-float))
+                  (#.db-char-constant (code-char (pref dptr :dbm-constant.value.u32)))
+                  (#.db-pointer-constant
+                   (let* ((val (pref dptr :dbm-constant.value.u32)))
+                     #+64-bit-target
+                     (if (logbitp 31 val)
+                       (setq val (logior val (ash #xffffffff 32))))
+                     (%int-to-ptr val )))))
+	  (cdb-free (pref datum :cdb-datum.data)))))
+    val))
+
+
+
+(defun db-lookup-constant (cdb name)
+  (when cdb
+    (rletZ ((value :cdb-datum)
+            (key :cdb-datum))
+      (with-cstrs ((keyname (string name)))
+        (setf (pref key :cdb-datum.data) keyname
+              (pref key :cdb-datum.size) (length (string name))
+              (pref value :cdb-datum.data) (%null-ptr)
+              (pref value :cdb-datum.size) 0)
+        (cdb-get cdb key value)
+        (extract-db-constant-value value)))))
+    
+
+
+(defun db-define-string-constant (cdbm name val &optional (class db-string-constant))
+  (let* ((dsize (+ 4 (length val))))
+    (%stack-block ((valbuf dsize))
+      (dotimes (i (length val))
+        (setf (%get-unsigned-byte valbuf (the fixnum (+ 4 i)))
+              (%scharcode val i)))
+      (setf (%get-long valbuf) class)
+      (rletZ ((content :cdb-datum)
+	      (key :cdb-datum))
+        (setf (pref content :cdb-datum.size) dsize
+              (pref content :cdb-datum.data) valbuf)
+        (with-cstrs ((keyname (string name)))
+          (setf (pref key :cdb-datum.size) (length (string name))
+                (pref key :cdb-datum.data) keyname)
+	  (cdbm-put cdbm key content))))))
+      
+(defun db-define-constant (cdbm name val)
+  (typecase val
+    (string (db-define-string-constant cdbm name val))
+    ((or (unsigned-byte 32)
+         (signed-byte 32)
+         short-float
+         double-float
+         character
+         macptr)
+     (rletZ ((constant :dbm-constant)
+	     (content :cdb-datum)
+	     (key :cdb-datum))
+       (etypecase val
+         ((signed-byte 32)
+          (setf (pref constant :dbm-constant.value.s32) val)
+          (setf (pref constant :dbm-constant.class) db-s32-constant))
+         ((unsigned-byte 32)
+          (setf (pref constant :dbm-constant.value.u32) val)
+          (setf (pref constant :dbm-constant.class) db-u32-constant))
+         (short-float
+          (setf (pref constant :dbm-constant.value.single-float) val)
+          (setf (pref constant :dbm-constant.class) db-float-constant))
+         (double-float
+          (setf (pref constant :dbm-constant.value.double-float) val)
+          (setf (pref constant :dbm-constant.class) db-double-constant))
+         (character
+          (setf (pref constant :dbm-constant.value.u32) (char-code val))
+          (setf (pref constant :dbm-constant.class) db-char-constant))
+         (macptr
+          (setf (pref constant :dbm-constant.value.u32) (logand #xffffffff (%ptr-to-int val)))
+          (setf (pref constant :dbm-constant.class) db-pointer-constant))
+         )
+       (setf (pref content :cdb-datum.data) constant
+             (pref content :cdb-datum.size) (record-length :dbm-constant))
+       (with-cstrs ((keyname (string name)))
+         (setf (pref key :cdb-datum.data) keyname
+               (pref key :cdb-datum.size) (length (string name)))
+	 (cdbm-put cdbm key content))))
+    (t (db-define-string-constant cdbm name (format nil "~a" val) db-read-string-constant))))
+
+
+  
+
+(defmacro with-new-db-file ((var pathname) &body body)
+  (let* ((db (gensym)))
+    `(let* (,db)
+      (unwind-protect
+           (let* ((,var (setq ,db (cdbm-open ,pathname))))
+             ,@body)
+        (when ,db (cdbm-close ,db))))))
+
+
+
+(defun interface-db-pathname (name d &optional (ftd *target-ftd*))
+  (merge-pathnames name
+		   (merge-pathnames (interface-dir-subdir d)
+				    (ftd-interface-db-directory ftd))))
+
+(def-ccl-pointers reset-db-files ()
+  (do-interface-dirs (d)
+    (setf (interface-dir-constants-interface-db-file d) nil
+	  (interface-dir-functions-interface-db-file d) nil
+	  (interface-dir-records-interface-db-file d) nil
+	  (interface-dir-types-interface-db-file d) nil
+          (interface-dir-vars-interface-db-file d) nil
+          (interface-dir-objc-classes-interface-db-file d) nil
+          (interface-dir-objc-methods-interface-db-file d) nil)))
+
+(defun db-constants (dir)
+  (or (interface-dir-constants-interface-db-file dir)
+      (setf (interface-dir-constants-interface-db-file dir)
+	    (open-interface-db-pathname "constants.cdb" dir))))
+
+(defun db-objc-classes (dir)
+  (or (interface-dir-objc-classes-interface-db-file dir)
+      (setf (interface-dir-objc-classes-interface-db-file dir)
+            (open-interface-db-pathname "objc-classes.cdb" dir))))
+
+(defun db-objc-methods (dir)
+  (or (interface-dir-objc-methods-interface-db-file dir)
+      (setf (interface-dir-objc-methods-interface-db-file dir)
+            (open-interface-db-pathname "objc-methods.cdb" dir))))
+
+(defun db-vars (dir)
+  (or (interface-dir-vars-interface-db-file dir)
+      (setf (interface-dir-vars-interface-db-file dir)
+	    (open-interface-db-pathname "vars.cdb" dir))))
+
+(defun db-types (dir)
+  (or (interface-dir-types-interface-db-file dir)
+      (setf (interface-dir-types-interface-db-file dir)
+	    (open-interface-db-pathname "types.cdb" dir))))
+
+(defun db-records (dir)
+  (or (interface-dir-records-interface-db-file dir)
+      (setf (interface-dir-records-interface-db-file dir)
+	    (open-interface-db-pathname "records.cdb" dir))))
+
+(defun db-functions (dir)
+  (or (interface-dir-functions-interface-db-file dir)
+      (setf (interface-dir-functions-interface-db-file dir)
+	    (open-interface-db-pathname "functions.cdb" dir))))
+
+(defun load-os-constant (sym &optional query)
+  (let* ((val (do-interface-dirs (d)
+		    (let* ((v (db-lookup-constant (db-constants d) sym)))
+		      (when v (return v))))))
+    (if query
+      (not (null val))
+      (if val
+        (let* ((*record-source-file* nil))
+          (%defconstant sym val)
+          val)
+        (error "Constant not found: ~s" sym)))))
+
+(defun %load-var (name &optional query-only)
+  (let* ((ftd *target-ftd*)
+         (string (if (getf (ftd-attributes ftd)
+                           :prepend-underscores)
+                   (concatenate 'string "_" (string name))
+                   (string name)))
+         (fv (gethash string (fvs))))
+    (unless fv
+      (with-cstrs ((cstring string))
+        (let* ((type
+                (do-interface-dirs (d)
+                  (let* ((vars (db-vars d)))
+                    (when vars
+                      (rletZ ((value :cdb-datum)
+                              (key :cdb-datum))
+                        (setf (pref key :cdb-datum.data) cstring
+                              (pref key :cdb-datum.size) (length string)
+                              (pref value :cdb-datum.data) (%null-ptr)
+                              (pref value :cdb-datum.size) 0)
+                        (cdb-get vars key value)
+                        (let* ((vartype (extract-db-type value ftd)))
+                          (when vartype (return vartype)))))))))
+          (when type
+            (setq fv (%cons-foreign-variable string type))
+            (resolve-foreign-variable fv nil)
+            (setf (gethash string (fvs)) fv)))))
+    (if query-only
+      (not (null fv))
+      (or fv (error "Foreign variable ~s not found" string)))))
+
+
+(set-dispatch-macro-character 
+ #\# #\&
+ (qlfun |#&-reader| (stream char arg)
+   (declare (ignore char arg))
+   (let* ((package (find-package (ftd-interface-package-name *target-ftd*))))
+     (multiple-value-bind (sym query source)
+         (%read-symbol-preserving-case
+          stream
+          package)
+       (unless *read-suppress*
+         (let* ((fv (%load-var sym query)))
+           (values (if query
+                     fv
+                     (%foreign-access-form `(%reference-external-entry-point (load-time-value ,fv))
+                                           (fv.type fv)
+                                           0
+                                           nil))
+                   source)))))))
+
+
+              
+
+(defstruct objc-message-info
+  message-name
+  methods                               ; all methods
+  ambiguous-methods                     ; partitioned by signature
+  req-args
+  flags
+  protocol-methods
+  lisp-name
+  selector)
+
+
+
+   
+(defstruct objc-method-info
+  message-info
+  class-name
+  class-pointer                         ;canonical, in some sense
+  arglist
+  result-type
+  flags
+  signature
+  signature-info
+  )
+
+
+
+(defmethod print-object ((m objc-method-info) stream)
+  (print-unreadable-object (m stream :type t :identity t)
+    (format stream "~c[~a ~a]"
+            (if (getf (objc-method-info-flags m) :class)
+              #\+
+              #\-)
+            (let* ((name (objc-method-info-class-name m)))
+              (if (getf (objc-method-info-flags m) :protocol)
+                (format nil "<~a>" name)
+                name))
+            (objc-message-info-message-name
+                          (objc-method-info-message-info m)))))
+
+(defun extract-db-objc-message-info (datum message-name info &optional
+                                           (ftd *target-ftd*))
+  (with-macptrs ((buf))
+    (%setf-macptr buf (pref datum :cdb-datum.data))
+    (unless (%null-ptr-p buf)
+      (unless info
+        (setq info
+              (make-objc-message-info
+               :message-name (string message-name))))
+      (let* ((p 0)
+             (nmethods 0)
+             (nargs 0))
+        (multiple-value-setq (nmethods p) (%decode-uint buf p))
+        (multiple-value-setq (nargs p) (%decode-uint buf p))
+        (dotimes (i nmethods)
+          (let* ((flag-byte (prog1 (%get-unsigned-byte buf p)
+                              (incf p)))
+                 (is-class-method (logbitp 0 flag-byte))
+                 (is-protocol-method (logbitp 1 flag-byte))
+                 (class-name ())
+                 (result-type ())
+                 (arg-types ())
+                 (arg-type ()))
+            (multiple-value-setq (class-name p) (%decode-name buf p t))
+            (multiple-value-setq (result-type p) (%decode-type buf p ftd t))
+            (dotimes (i nargs)
+              (multiple-value-setq (arg-type p) (%decode-type buf p ftd t))
+              (push arg-type arg-types))
+            (unless (dolist (m (objc-message-info-methods info))
+                      (when (and (eq (getf (objc-method-info-flags m) :class)  is-class-method)
+                                 (string= (objc-method-info-class-name m)
+                                          class-name))
+                        (return t)))
+              (let* ((flags ()))
+                (if is-class-method
+                  (setf (getf flags :class) t))
+                (if is-protocol-method
+                  (setf (getf flags :protocol) t))
+                (push (make-objc-method-info
+                                     :message-info info
+                                     :class-name class-name
+                                     :arglist (nreverse arg-types)
+                                     :result-type result-type
+                                     :flags flags)
+                 (objc-message-info-methods info))))))
+        (cdb-free (pref datum :cdb-datum.data))))
+    info))
+
+(defun db-note-objc-method-info (cdb message-name message-info)
+  (when cdb
+    (rletZ ((value :cdb-datum)
+            (key :cdb-datum))
+      (with-cstrs ((keyname (string message-name)))
+        (setf (pref key :cdb-datum.data) keyname
+              (pref key :cdb-datum.size) (length (string message-name))
+              (pref value :cdb-datum.data) (%null-ptr)
+              (pref value :cdb-datum.size) 0)
+        (cdb-get cdb key value)
+        (extract-db-objc-message-info value message-name message-info)))))
+
+(defun lookup-objc-message-info (message-name &optional message-info)
+  (do-interface-dirs (d)
+    (setq message-info
+          (db-note-objc-method-info (db-objc-methods d) message-name message-info)))
+  message-info)
+
+(defun %find-objc-class-info (name)
+  (do-interface-dirs (d)
+    (let* ((info (db-lookup-objc-class (db-objc-classes d) name)))
+      (when info (return info)))))
+
+(defun load-external-function (sym query)
+  (let* ((def (or (do-interface-dirs (d)
+		    (let* ((f (db-lookup-function (db-functions d) sym)))
+		      (when f (return f))))
+                  (unless query
+                    (error "Foreign function not found: ~s" sym)))))
+    (if query
+      (not (null def))
+      (progn
+        (setf (gethash sym (ftd-external-function-definitions
+                            *target-ftd*)) def)
+        (setf (macro-function sym) #'%external-call-expander)
+        sym))))
+
+(defun %read-symbol-preserving-case (stream package)
+  (let* ((case (readtable-case *readtable*))
+         (query nil)
+	 (error nil)
+	 (sym nil)
+         (source nil))
+    (let* ((*package* package))
+      (unwind-protect
+	   (progn
+	     (setf (readtable-case *readtable*) :preserve)
+             (when (eq #\? (peek-char t stream nil nil))
+               (setq query t)
+               (read-char stream))
+	     (multiple-value-setq (sym source error)
+	       (handler-case (read-internal stream nil nil nil)
+		 (error (condition) (values nil nil condition)))))
+	(setf (readtable-case *readtable*) case)))
+    (when error
+      (error error))
+    (values sym query source)))
+
+(set-dispatch-macro-character 
+ #\# #\$
+ (qlfun |#$-reader| (stream char arg)
+        (declare (ignore char))
+        (let* ((package (find-package (ftd-interface-package-name *target-ftd*))))
+          (multiple-value-bind (sym query source)
+              (%read-symbol-preserving-case
+               stream
+               package)
+            (unless *read-suppress*
+              (etypecase sym
+                (symbol
+                 (let* ((const (load-os-constant sym t)))
+                   (if query
+                     (values const source)
+                     (progn
+                       (if const
+                         (progn
+                           (when (eq (symbol-package sym) package)
+                             (unless arg (setq arg 0))
+                             (ecase arg
+                               (0
+                                (unless (and (constant-symbol-p sym)
+                                             (not (eq (%sym-global-value sym)
+                                                      (%unbound-marker-8))))
+                                  (load-os-constant sym)))
+                               (1 (makunbound sym) (load-os-constant sym))))
+                           (values sym source))
+                         (let* ((fv (%load-var sym nil)))
+                           (values
+                            (%foreign-access-form `(%reference-external-entry-point (load-time-value ,fv))
+                                                  (fv.type fv)
+                                                  0
+                                                  nil)
+                            source)))))))
+                (string
+                 (let* ((val 0)
+                        (len (length sym)))
+                   (dotimes (i 4 (values val source))
+                     (let* ((ch (if (< i len) (char sym i) #\space)))
+                       (setq val (logior (ash val 8) (char-code ch)))))))))))))
+
+(set-dispatch-macro-character #\# #\_
+  (qlfun |#_-reader| (stream char arg)
+    (declare (ignore char))
+    (unless arg (setq arg 0))
+    (multiple-value-bind (sym query source)
+        (%read-symbol-preserving-case
+		 stream
+		 (find-package (ftd-interface-package-name *target-ftd*)))
+      (unless *read-suppress*
+        (unless (and sym (symbolp sym)) (report-bad-arg sym 'symbol))
+        (if query
+          (values (load-external-function sym t) source)
+          (let* ((def (if (eql arg 0)
+                        (gethash sym (ftd-external-function-definitions
+                                      *target-ftd*)))))
+            (values (if (and def (eq (macro-function sym) #'%external-call-expander))
+                      sym
+                      (load-external-function sym nil))
+                    source)))))))
+
+(set-dispatch-macro-character
+ #\# #\>
+ (qlfun |#>-reader| (stream char arg)
+    (declare (ignore char arg))
+    (if *read-suppress*
+      (progn
+        (%read-list-expression stream nil)
+        nil)
+      (let* ((readtable *readtable*)
+             (case (readtable-case readtable))
+             (string nil)
+             (error nil))
+        (unwind-protect
+             (progn
+               (setf (readtable-case readtable) :preserve)
+               (multiple-value-setq (string error)
+                 (handler-case (read-symbol-token stream)
+                   (error (condition) (values nil condition)))))
+          (setf (readtable-case *readtable*) case))
+        (when error
+          (error error))
+        (escape-foreign-name string)))))
+             
+
+
+
+(eval-when (:compile-toplevel :execute)
+  (defconstant encoded-type-void 0)
+  (defconstant encoded-type-signed-32 1)
+  (defconstant encoded-type-unsigned-32 2)
+  (defconstant encoded-type-signed-8 3)
+  (defconstant encoded-type-unsigned-8 4)
+  (defconstant encoded-type-signed-16 5)
+  (defconstant encoded-type-unsigned-16 6)
+  (defconstant encoded-type-signed-n 7) ;N
+  (defconstant encoded-type-unsigned-n 8) ;N
+  (defconstant encoded-type-single-float 9)
+  (defconstant encoded-type-double-float 10)
+  (defconstant encoded-type-pointer 11) ; <type>
+  (defconstant encoded-type-array 12) ; <size> <type>
+  (defconstant encoded-type-named-struct-ref 13); <tag>
+  (defconstant encoded-type-named-union-ref 14) ;<tag>
+  (defconstant encoded-type-named-type-ref 15) ; <name>
+  (defconstant encoded-type-anon-struct-ref 16) ; <tag>
+  (defconstant encoded-type-anon-union-ref 17) ; <tag>
+  (defconstant encoded-type-bitfield-marker 18) ; <nbits>
+  (defconstant encoded-type-named-transparent-union-ref 19) ; <name>
+  (defconstant encoded-type-anon-transparent-union-ref 20)  ;<tag>
+  )
+
+
+(defconstant encoded-type-type-byte (byte 5 0))
+(defconstant encoded-type-align-byte (byte 3 5)
+  "alignment in octets, if other than \"natural\" alignment,")
+
+;;; Constants & function names get saved verbatim.
+;;; Record, type, and field names get escaped.
+
+(defun encode-name (name &optional verbatim)
+  (if (null name)
+    (list 0)
+    (let* ((string
+	    (if (and (typep name 'keyword)
+		     (not verbatim))
+	      (unescape-foreign-name name)
+	      (string name)))
+           (length (length string)))
+      (cons length (map 'list #'char-code string)))))
+
+(defun encode-ffi-field (field)
+  (destructuring-bind (name type offset width) field
+  `(,@(encode-name name)
+    ,@(encode-ffi-type type)
+    ,@(encode-uint offset)
+    ,@(encode-uint width))))
+
+(defun encode-ffi-field-list (fields)
+  (let* ((len (length fields)))
+    (labels ((encode-fields (fields)
+               (if fields
+                 `(,@(encode-ffi-field (car fields)) ,@(encode-fields (cdr fields))))))
+      `(,@(encode-uint len) ,@(encode-fields fields)))))
+
+(defun encode-ffi-union (u)
+  (let* ((name (ffi-union-name u))
+	 (alt-align-in-bytes-mask (ash (or (ffi-union-alt-alignment-bits u)
+				      0)
+				  (- 5 3))))
+    (if name
+      `(,(logior encoded-type-named-union-ref alt-align-in-bytes-mask)
+        ,@(encode-name name)
+        ,@(encode-ffi-field-list (ffi-union-fields u)))
+      `(,(logior encoded-type-anon-union-ref alt-align-in-bytes-mask)
+        ,@(encode-ffi-field-list (ffi-union-fields u))))))
+
+(defun encode-ffi-transparent-union (u)
+  (let* ((name (ffi-transparent-union-name u))
+	 (alt-align-in-bytes-mask (ash (or (ffi-transparent-union-alt-alignment-bits u)
+                                           0)
+                                       (- 5 3))))
+    (if name
+      `(,(logior encoded-type-named-transparent-union-ref alt-align-in-bytes-mask)
+        ,@(encode-name name)
+        ,@(encode-ffi-field-list (ffi-union-fields u)))
+      `(,(logior encoded-type-anon-transparent-union-ref alt-align-in-bytes-mask)
+        ,@(encode-ffi-field-list (ffi-union-fields u))))))
+
+(defun encode-ffi-struct (s)
+  (let* ((name (ffi-struct-name s))
+	 (alt-align-in-bytes-mask (ash (or (ffi-struct-alt-alignment-bits s)
+					   0)
+				       (- 5 3))))
+    (if name
+      `(,(logior encoded-type-named-struct-ref alt-align-in-bytes-mask)
+        ,@(encode-name (ffi-struct-name s))
+        ,@(encode-ffi-field-list (ffi-struct-fields s)))
+      `(,(logior encoded-type-anon-struct-ref alt-align-in-bytes-mask)
+        ,@(encode-ffi-field-list (ffi-struct-fields s))))))
+
+(defun encode-ffi-objc-class (c)
+  (let* ((protocols (ffi-objc-class-protocol-names c)))
+    (labels ((encode-name-list (names)
+               (if names
+                 `(,@(encode-name (car names) t)
+                   ,@(encode-name-list (cdr names))))))
+      `(,@(encode-name (ffi-objc-class-string c))
+        ,@(encode-name (ffi-objc-class-super-foreign-name c))
+        ,@(encode-uint (length protocols))
+        ,@(encode-name-list protocols)
+        ,@(encode-ffi-field-list (ffi-objc-class-own-ivars c))))))
+
+
+(defstruct db-objc-class-info
+  class-name
+  superclass-name
+  protocols
+  ivars
+  instance-methods
+  class-methods
+  )
+
+(defun extract-db-objc-class (datum &optional (ftd *target-ftd*))
+  (let* ((val nil))
+    (with-macptrs ((buf))
+      (%setf-macptr buf (pref datum :cdb-datum.data))
+      (unless (%null-ptr-p buf)
+	(let* ((p 0)
+               (protocol-count 0)
+               (class-name ())
+               (superclass-name ())
+               (protocol-name ())
+               (ivars ()))
+          (collect ((protocols))
+            (multiple-value-setq (class-name p) (%decode-name buf p t))
+            (multiple-value-setq (superclass-name p) (%decode-name buf p t))
+            (multiple-value-setq (protocol-count p) (%decode-uint buf p))
+            (dotimes (i protocol-count)
+              (multiple-value-setq (protocol-name p) (%decode-name buf p t))
+              (protocols protocol-name))
+            (setq ivars (%decode-field-list buf p ftd))
+            (cdb-free (pref datum :cdb-datum.data))
+            (setq val (make-db-objc-class-info
+                       :class-name class-name
+                       :superclass-name superclass-name
+                       :ivars ivars
+                       :protocols (protocols)
+                     ))))))
+    val))
+
+(defun db-lookup-objc-class (cdb name)
+  (when cdb
+    (rletZ ((value :cdb-datum)
+            (key :cdb-datum))
+      (with-cstrs ((keyname (string name)))
+        (setf (pref key :cdb-datum.data) keyname
+              (pref key :cdb-datum.size) (length (string name))
+              (pref value :cdb-datum.data) (%null-ptr)
+              (pref value :cdb-datum.size) 0)
+        (cdb-get cdb key value)
+        (extract-db-objc-class value)))))
+
+(defun encode-u32 (val)
+  `(,(ldb (byte 8 24) val)
+    ,(ldb (byte 8 16) val)
+    ,(ldb (byte 8 8) val)
+    ,(ldb (byte 8 0) val)))
+
+(defun encode-uint (val)
+  (collect ((bytes))
+    (do* ((b (ldb (byte 7 0) val) (ldb (byte 7 0) val))
+          (done nil))
+         (done (bytes))
+      (when (zerop (setq val (ash val -7)))
+        (setq b (logior #x80 b) done t))
+      (bytes b))))
+
+    
+
+(defun encode-ffi-type (spec)
+  (case (car spec)
+    (:primitive
+     (let ((primtype (cadr spec)))
+       (if (atom primtype)
+         (case primtype
+           (:float `(,encoded-type-single-float))
+           (:double `(,encoded-type-double-float))
+           (:void `(,encoded-type-void))
+           (:signed `(,encoded-type-signed-32))
+           (:unsigned `(,encoded-type-unsigned-32))
+           ((:long-double :complex-int
+                        :complex-float :complex-double :complex-long-double)
+            (encode-ffi-type `(:struct ,primtype))))
+         (ecase (car primtype)
+           (* `(,encoded-type-pointer ,@(encode-ffi-type
+                                           (if (eq (cadr primtype) t)
+                                             `(:primitive :void)
+                                             (cadr primtype)))))
+           (:signed
+            (case (cadr primtype)
+              (32 `(,encoded-type-signed-32))
+              (16 `(,encoded-type-signed-16))
+              (8 `(,encoded-type-signed-8))
+              (t `(,encoded-type-signed-n ,(cadr primtype)))))
+           (:unsigned
+            (case (cadr primtype)
+              (32 `(,encoded-type-unsigned-32))
+              (16 `(,encoded-type-unsigned-16))
+              (8 `(,encoded-type-unsigned-8))
+              (t `(,encoded-type-unsigned-n ,(cadr primtype)))))))))
+     (:struct
+      (let* ((s (cadr spec))
+             (name (ffi-struct-name s))
+	     (alt-align-bytes-mask (ash (or (ffi-struct-alt-alignment-bits s)
+					    0)
+					(- 5 3))))
+      `(,(if name
+             (logior encoded-type-named-struct-ref alt-align-bytes-mask)
+             (logior encoded-type-anon-struct-ref alt-align-bytes-mask))
+        ,@(encode-name (ffi-struct-reference s)))))
+     (:union
+      (let* ((u (cadr spec))
+             (name (ffi-union-name u))
+	     (alt-align-bytes-mask (ash (or (ffi-union-alt-alignment-bits u)
+					    0)
+					(- 5 3)))	     )
+      `(,(if name
+             (logior encoded-type-named-union-ref alt-align-bytes-mask)
+             (logior encoded-type-anon-union-ref alt-align-bytes-mask))
+        ,@(encode-name (ffi-union-reference u)))))
+     (:transparent-union
+      (let* ((u (cadr spec))
+             (name (ffi-transparent-union-name u))
+	     (alt-align-bytes-mask (ash (or (ffi-union-alt-alignment-bits u)
+					    0)
+					(- 5 3)))	     )
+      `(,(if name
+             (logior encoded-type-named-transparent-union-ref alt-align-bytes-mask)
+             (logior encoded-type-anon-transparent-union-ref alt-align-bytes-mask))
+        ,@(encode-name (ffi-transparent-union-reference u)))))
+     (:typedef
+      `(,encoded-type-named-type-ref ,@(encode-name (ffi-typedef-name (cadr spec)))))
+     (:pointer
+      `(,encoded-type-pointer ,@(encode-ffi-type
+                                   (if (eq (cadr spec) t)
+                                     '(:primitive :void)
+                                     (cadr spec)))))
+     (:array
+      `(,encoded-type-array ,@(encode-uint (cadr spec)) ,@(encode-ffi-type (caddr spec))))
+     (t
+      (break "Type spec = ~s" spec))))
+
+(defun encode-ffi-arg-type (spec)
+  (case (car spec)
+    (:primitive
+     (let ((primtype (cadr spec)))
+       (if (atom primtype)
+         (case primtype
+           (:float `(#\s))
+           (:double `(#\d))
+           (:void `(#\Space))
+           (:signed `(#\F))
+           (:unsigned `(f))
+           ((:long-double :complex-int
+			  :complex-float :complex-double :complex-long-double)            
+            #|(encode-ffi-arg-type `(:struct ,primtype))|#
+            `(#\?)))
+         (ecase (car primtype)
+           (* `(#\a))
+           (:signed
+            (let* ((nbits (cadr primtype)))
+              (if (<= nbits 8)
+                '(#\B)
+                (if (<= nbits 16)
+                  '(#\H)
+                  (if (<= nbits 32)
+                    '(#\F)
+		    (if (<= nbits 64)
+		      `(#\L)
+		      '(#\?)))))))
+           (:unsigned
+            (let* ((nbits (cadr primtype)))
+              (if (<= nbits 8)
+                '(#\b)
+                (if (<= nbits 16)
+                  '(#\h)
+                  (if (<= nbits 32)
+                    '(#\f)
+		    (if (<= nbits 64)
+		      `(#\l)
+		      '(#\?)))))))))))
+    ((:struct :union :transparent-union)
+     `(,(ecase (car spec)
+          (:struct #\r)
+          (:union #\u)
+          (:transparent-union #\U))
+           ,@(encode-name (ffi-struct-reference (cadr spec)))))
+    (:typedef
+     `(#\t ,@(encode-name (ffi-typedef-name (cadr spec)))))
+    (:pointer
+      `(#\a))
+    (:array
+      `(#\?))))
+
+(defun encode-ffi-arg-list (args)
+  (if args
+    `(,@(encode-ffi-arg-type (car args)) ,@(encode-ffi-arg-list (cdr args)))))
+
+(defvar *prepend-underscores-to-ffi-function-names* nil)
+
+(defun encode-ffi-function (f)
+  (let* ((args (ffi-function-arglist f))
+	 (string (ffi-function-string f))
+	 (name (if *prepend-underscores-to-ffi-function-names*
+		 (concatenate 'string "_" string)
+		 string))
+         (min-args (length args))
+         (result (ffi-function-return-value f)))
+    `(,min-args
+      ,@(encode-name name t)		; verbatim
+      ,@(encode-ffi-arg-type result)
+      ,@(encode-ffi-arg-list args))))
+
+(defun encode-ffi-objc-method (m)
+  (let* ((flag-byte (logior (if (getf (ffi-objc-method-flags m) :class) 1 0)
+                            (if (getf (ffi-objc-method-flags m) :protocol) 2 0))))
+  `(,flag-byte
+    ,@(encode-name (ffi-objc-method-class-name m) t)
+    ,@(encode-ffi-type (ffi-objc-method-result-type m))
+    ,@(apply #'append (mapcar #'encode-ffi-type (ffi-objc-method-arglist m))))))
+
+(defun save-ffi-objc-message (cdbm message)
+  (let* ((methods (ffi-objc-message-methods message))
+         (nmethods (length methods))
+         (nargs (length (ffi-objc-method-arglist (car methods)))))
+    (labels ((encode-objc-method-list (ml)
+               (when ml
+                 `(,@(encode-ffi-objc-method (car ml))
+                   ,@(encode-objc-method-list (cdr ml))))))
+      (db-write-byte-list cdbm
+                          (ffi-objc-message-string message)
+                          `(,@(encode-uint nmethods)
+                            ,@(encode-uint nargs)
+                            ,@(encode-objc-method-list methods))
+                          t))))
+  
+    
+(defun save-byte-list (ptr l)
+  (do* ((l l (cdr l))
+        (i 0 (1+ i)))
+       ((null l))
+    (let* ((b (car l)))
+      (if (typep b 'character)
+        (setq b (char-code b)))
+      (setf (%get-unsigned-byte ptr i) b))))
+
+(defun db-write-byte-list (cdbm keyname bytes &optional verbatim)
+  (let* ((len (length bytes)))
+    (%stack-block ((p len))
+      (save-byte-list p bytes)
+      (rletZ ((contents :cdb-datum)
+	      (key :cdb-datum))
+        (let* ((foreign-name
+		(if verbatim
+		  keyname
+		  (unescape-foreign-name keyname))))
+	  (with-cstrs ((keystring foreign-name))
+	    (setf (pref contents :cdb-datum.data) p
+		  (pref contents :cdb-datum.size) len
+		  (pref key :cdb-datum.data) keystring
+		  (pref key :cdb-datum.size) (length foreign-name))
+	    (cdbm-put cdbm key contents)))))))
+
+(defun save-ffi-function (cdbm fun)
+  (let* ((encoding (encode-ffi-function fun)))
+    (db-write-byte-list cdbm
+			(ffi-function-string fun)
+			encoding
+			t)))
+
+(defun save-ffi-typedef (cdbm def)
+  (db-write-byte-list cdbm
+                       (ffi-typedef-string def)
+                       (encode-ffi-type (ffi-typedef-type def))
+		       t))
+
+(defun save-ffi-struct (cdbm s)
+  (db-write-byte-list cdbm (ffi-struct-reference s) (encode-ffi-struct s)))
+
+(defun save-ffi-union (cdbm u)
+  (db-write-byte-list cdbm (ffi-union-reference u) (encode-ffi-union u)))
+
+(defun save-ffi-transparent-union (cdbm u)
+  (db-write-byte-list cdbm (ffi-transparent-union-reference u) (encode-ffi-transparent-union u)))
+
+
+(defun db-define-var (cdbm name type)
+  (db-write-byte-list cdbm
+                      (if *prepend-underscores-to-ffi-function-names*
+                        (concatenate 'string "_" name)
+                        name)
+  (encode-ffi-type type) t))
+
+(defun save-ffi-objc-class (cdbm c)
+  (db-write-byte-list cdbm (ffi-objc-class-name c) (encode-ffi-objc-class c)))
+
+
+;;; An "uppercase-sequence" is a maximal substring of a string that
+;;; starts with an uppercase character and doesn't contain any
+;;; lowercase characters.
+(defun count-uppercase-sequences (string)
+  (let* ((state :lower)
+	 (nupper 0))
+    (declare (fixnum nupper))
+    (dotimes (i (length string) nupper)
+      (let* ((ch (char string i)))
+	(case state
+	  (:lower 
+	   (when (upper-case-p ch)
+	     (incf nupper)
+	     (setq state :upper)))
+	  (:upper
+	   (unless (upper-case-p ch)
+	     (setq state :lower))))))))
+
+(defun escape-foreign-name (in &optional
+			       (count (count-uppercase-sequences in)))
+  (intern
+   (if (zerop count)
+     (string-upcase in)
+     (let* ((len (length in))
+	    (j 0)
+	    (out (make-string (+ len (* 2 count))))
+	    (state :lower))
+       (flet ((outch (ch)
+		(setf (schar out j) ch)
+		(incf j)
+		ch))
+	 (dotimes (i len (progn (if (eq state :upper) (outch #\>)) out))
+	   (let* ((ch (char in i)))
+	     (cond ((and (upper-case-p ch) (eq state :lower))
+		    (outch #\<)
+		    (setq state :upper))
+		   ((and (not (upper-case-p ch)) (eq state :upper))
+		    (outch #\>)
+		    (setq state :lower)))
+	     (outch (char-upcase ch)))))))
+   *keyword-package*))
+
+(defun unescape-foreign-name (key)
+  (let* ((string (if (typep key 'symbol)
+                   (string-downcase key)
+                   (string key)))
+	 (nleftbrackets (count #\< string))
+         (nrightbrackets (count #\> string))
+         (nbrackets (+ nleftbrackets nrightbrackets)))
+    (declare (fixnum nleftbrackets nrightbrackets nbrackets))
+    (if (zerop nbrackets)
+      string
+      (if (/= nleftbrackets nrightbrackets)
+        (error "Mismatched brackets in ~s." key)
+        (let* ((len (length string))
+               (out (make-string (- len nbrackets)))
+               (j 0)
+               (state :lower))
+          (dotimes (i len out)
+            (let* ((ch (schar string i)))
+              (if (or (and (eq ch #\<)
+                           (eq state :upper))
+                      (and (eq ch #\>)
+                           (eq state :lower)))
+                (error "Mismatched brackets in ~s." key))
+              (case ch
+                (#\< (setq state :upper))
+                (#\> (setq state :lower))
+                (t (setf (schar out j) (if (eq state :upper)
+                                         (char-upcase ch)
+                                         (char-downcase ch))
+                         j (1+ j)))))))))))
+
+	
+	
+(defun %decode-name (buf p &optional verbatim)
+  (declare (type macptr buf) (fixnum p))
+  (let* ((n (%get-unsigned-byte buf p)))
+    (declare (fixnum n))
+    (if (zerop n)
+      (values nil (1+ p))
+      (let* ((pname (%str-from-ptr (%inc-ptr buf (1+ p)) n)))
+        (values (if verbatim pname (escape-foreign-name pname))
+                (+ p (1+ n)))))))
+
+(defun %decode-u32 (buf p)
+  (declare (fixnum p) (type macptr buf))
+  (values (dpb
+           (%get-unsigned-byte buf p)
+           (byte 8 24)
+           (dpb
+            (%get-unsigned-byte buf (+ p 1))
+            (byte 8 16)
+            (dpb
+             (%get-unsigned-byte buf (+ p 2))
+             (byte 8 8)
+             (%get-unsigned-byte buf (+ p 3)))))
+          (+ p 4)))
+
+(defun %decode-uint (buf p)
+  (do* ((val 0)
+        (p p (1+ p))
+        (shift 0 (+ shift 7))
+        (done nil))
+       (done (values val p))
+    (let* ((b (%get-unsigned-byte buf p)))
+      (setq done (logbitp 7 b) val (logior val (ash (logand b #x7f) shift))))))
+       
+  
+;; Should return a FOREIGN-TYPE structure (except if suppress-typedef-expansion is true, may
+;; return a symbol for encoded-type-named-type-ref)
+(defun %decode-type (buf p ftd &optional suppress-typedef-expansion)
+  (declare (type macptr buf) (fixnum p))
+  (let* ((q (1+ p)))
+    (ecase (ldb encoded-type-type-byte (%get-unsigned-byte buf p))
+      (#.encoded-type-void (values (parse-foreign-type :void) q))
+      (#.encoded-type-signed-32 (values (svref *signed-integer-types* 32) q))
+      (#.encoded-type-unsigned-32 (values (svref *unsigned-integer-types* 32) q))
+      (#.encoded-type-signed-8 (values (svref *signed-integer-types* 8) q))
+      (#.encoded-type-unsigned-8 (values (svref *unsigned-integer-types* 8) q))
+      (#.encoded-type-signed-16 (values (svref *signed-integer-types* 16) q))
+      (#.encoded-type-unsigned-16 (values (svref *unsigned-integer-types* 16) q))
+      (#.encoded-type-signed-n (values (let* ((bits (%get-unsigned-byte buf q)))
+                                         (if (<= bits 32)
+                                           (svref *signed-integer-types* bits)
+                                           (make-foreign-integer-type
+                                            :signed t
+                                            :bits bits)))
+                                         (1+ q)))
+      (#.encoded-type-unsigned-n (values (let* ((bits (%get-unsigned-byte buf q)))
+                                         (if (<= bits 32)
+                                           (svref *unsigned-integer-types* bits)
+                                           (make-foreign-integer-type
+                                            :signed nil
+                                            :bits bits)))
+                                           (1+ q)))
+      (#.encoded-type-single-float (values (parse-foreign-type :float) q))
+      (#.encoded-type-double-float (values (parse-foreign-type :double) q))
+      (#.encoded-type-pointer (multiple-value-bind (target qq)
+                                  (%decode-type buf q ftd suppress-typedef-expansion)
+                                (values (make-foreign-pointer-type
+                                         :to target
+                                         :bits (getf (ftd-attributes ftd)
+                                                     :bits-per-word)
+                                         )
+                                          qq)))
+      (#.encoded-type-array
+       (multiple-value-bind (size qq) (%decode-uint buf q)
+         (multiple-value-bind (target qqq) (%decode-type buf qq ftd)
+           (let* ((type-alignment (foreign-type-alignment target))
+                  (type-bits (foreign-type-bits target)))
+             (values (make-foreign-array-type
+                      :element-type target
+                      :dimensions (list size)
+                      :alignment type-alignment
+                      :bits (if type-bits
+                              (* (align-offset type-bits type-alignment) size)))
+                     qqq)))))
+      (#.encoded-type-named-type-ref
+       (multiple-value-bind (name qq) (%decode-name buf q)         
+         (values (if suppress-typedef-expansion
+                   name
+                   (%parse-foreign-type name))
+                 qq)))
+      (#.encoded-type-named-struct-ref
+       (multiple-value-bind (name qq) (%decode-name buf q)
+         (values (or (info-foreign-type-struct name)
+                     (setf (info-foreign-type-struct name)
+                           (make-foreign-record-type :kind :struct
+                                                     :name name)))
+                 qq)))
+      (#.encoded-type-named-union-ref
+       (multiple-value-bind (name qq) (%decode-name buf q)
+         (values (or (info-foreign-type-union name)
+                     (setf (info-foreign-type-union name)
+                           (make-foreign-record-type :kind :union
+                                                     :name name)))
+                 qq)))
+      (#.encoded-type-named-transparent-union-ref
+       (multiple-value-bind (name qq) (%decode-name buf q)
+         (let* ((already (info-foreign-type-union name)))
+           (when already
+             (setf (foreign-record-type-kind already) :transparent-union))
+           (values (or already
+                     (setf (info-foreign-type-union name)
+                           (make-foreign-record-type :kind :transparent-union
+                                                     :name name)))
+                 qq))))
+      ((#.encoded-type-anon-struct-ref
+        #.encoded-type-anon-union-ref
+        #.encoded-type-anon-transparent-union-ref)
+       (multiple-value-bind (tag qq) (%decode-name buf q t)
+         (values (load-record tag) qq))))))
+
+(defun extract-db-type (datum ftd)
+  (let* ((data (pref datum :cdb-datum.data)))
+    (unless (%null-ptr-p data)
+      (prog1
+	  (%decode-type data 0 ftd)
+	(cdb-free data)))))
+
+(defun %load-foreign-type (cdb name ftd)
+  (when cdb
+    (with-cstrs ((string (string name)))
+      (rletZ ((contents :cdb-datum)
+              (key :cdb-datum))
+        (setf (pref key :cdb-datum.size) (length (string name))
+            (pref key :cdb-datum.data) string
+            (pref contents :cdb-datum.data) (%null-ptr)
+            (pref contents :cdb-datum.size) 0)
+      (cdb-get cdb key contents)
+      (let* ((type (extract-db-type contents ftd)))
+	(if type
+	  (%def-foreign-type (escape-foreign-name name) type ftd)))))))
+
+(defun load-foreign-type (name &optional (ftd *target-ftd*))
+  (let* ((name (unescape-foreign-name name)))
+    (do-interface-dirs (d ftd)
+      (let* ((type (%load-foreign-type (db-types d) name ftd)))
+	(when type (return type))))))
+
+(defun %decode-field (buf p ftd)
+  (declare (type macptr buf) (fixnum p))
+  (multiple-value-bind (name p) (%decode-name buf p)
+    (multiple-value-bind (type p) (%decode-type buf p ftd)
+      (multiple-value-bind (offset p) (%decode-uint buf p)
+        (multiple-value-bind (width p) (%decode-uint buf p)
+          (values (make-foreign-record-field :type type
+                                             :name name
+                                             :bits width
+                                             :offset offset)
+                  p))))))
+
+(defun %decode-field-list (buf p ftd)
+  (declare (type macptr buf) (fixnum p))
+  (let* ((n nil)
+         (fields nil))
+    (multiple-value-setq (n p) (%decode-uint buf p))
+    (dotimes (i n (values (nreverse fields) p))
+      (multiple-value-bind (field q) (%decode-field buf p ftd)
+        (push field fields)
+        (setq p q)))))
+
+(defun %determine-record-attributes (rtype parsed-fields &optional alt-align)
+  (let* ((total-bits 0)
+         (overall-alignment 1)
+	 #+(and darwinppc-target ppc32-target)
+	 (first-field-p t)
+         (kind (foreign-record-type-kind rtype)))
+    (dolist (field parsed-fields)
+      (let* ((field-type (foreign-record-field-type field))
+             (bits (ensure-foreign-type-bits field-type))
+             (natural-alignment (foreign-type-alignment field-type))
+	     (alignment (if alt-align
+			  (min natural-alignment alt-align)
+			  #+(and darwinppc-target ppc32-target)
+			  (if first-field-p
+			    (progn
+			      (setq first-field-p nil)
+			      natural-alignment)
+			    (min 32 natural-alignment))
+			  #-(and darwinppc-target ppc32-target)
+			  natural-alignment)))
+        (unless bits
+          (error "Unknown size: ~S"
+                 (unparse-foreign-type field-type)))
+        (unless alignment
+          (error "Unknown alignment: ~S"
+                 (unparse-foreign-type field-type)))
+        (setq overall-alignment (max overall-alignment (if (= alignment 1) 32 alignment)))
+        (ecase kind
+          (:struct (let* ((imported-offset (foreign-record-field-offset field))
+                          (offset (or imported-offset (align-offset total-bits alignment))))
+                     (unless imported-offset
+                       (setf (foreign-record-field-offset field) offset))
+                     (setq total-bits (+ offset bits))))
+          ((:union :transparent-union) (setq total-bits (max total-bits bits))))))
+    (setf (foreign-record-type-fields rtype) parsed-fields
+          (foreign-record-type-alignment rtype) (or
+						 alt-align
+						 overall-alignment)
+          (foreign-record-type-bits rtype) (align-offset
+					    total-bits
+					    (or alt-align overall-alignment))
+	  (foreign-record-type-alt-align rtype) alt-align)
+    rtype))
+
+(defun %decode-record-type (buf p ftd already)
+  (declare (type macptr buf) (fixnum p))
+  (let* ((rbyte (%get-unsigned-byte buf p))
+	 (rcode (ldb encoded-type-type-byte rbyte))
+	 (ralign-in-bytes (ldb encoded-type-align-byte rbyte))
+	 (alt-align (unless (zerop ralign-in-bytes)
+		      (the fixnum (ash ralign-in-bytes 3)))))
+    (declare (fixnum rbyte rcode ralign-in-bytes))
+    (multiple-value-bind (name q)
+        (case rcode
+          ((#.encoded-type-anon-struct-ref
+            #.encoded-type-anon-union-ref
+            #.encoded-type-anon-transparent-union-ref)
+           (values nil (1+ p)))
+          (t
+           (%decode-name buf (1+ p))))
+      (%determine-record-attributes
+       (or already
+           (if name
+             (if (eql rcode encoded-type-named-struct-ref)
+               (or (info-foreign-type-struct name)
+                   (setf (info-foreign-type-struct name)
+                         (make-foreign-record-type :kind :struct :name name)))
+               (or (info-foreign-type-union name)
+                   (setf (info-foreign-type-union name)
+                         (make-foreign-record-type :kind
+                                                   (if (eql rcode encoded-type-named-union-ref)
+                                                     :union
+                                                     :transparent-union)
+                                                   :name name))))
+             (make-foreign-record-type
+              :kind (if (eql rcode encoded-type-anon-struct-ref)
+                      :struct
+                      (if (eql rcode encoded-type-anon-union-ref)
+                        :union
+                        :transparent-union))
+              :name name)))
+       (%decode-field-list buf q ftd)
+       alt-align))))
+
+(defun extract-db-record (datum ftd already)
+  (let* ((data (pref datum :cdb-datum.data)))
+    (unless (%null-ptr-p data)
+      (prog1
+	  (%decode-record-type data 0 ftd already)
+	(cdb-free data)))))
+
+
+(defun %load-foreign-record (cdb name ftd already)
+  (when cdb
+    (with-cstrs ((string (string name)))
+      (rlet ((contents :cdb-datum)
+             (key :cdb-datum))
+        (setf (pref key :cdb-datum.size) (length (string name))
+              (pref key :cdb-datum.data) string
+              (pref contents :cdb-datum.data) (%null-ptr)
+              (pref contents :cdb-datum.size) 0)
+        (cdb-get cdb key contents)
+        (extract-db-record contents ftd already)))))
+
+(defun load-record (name &optional (ftd *target-ftd*))
+  ;; Try to destructively modify any info we already have.  Use the
+  ;; "escaped" name (keyword) for the lookup here.
+  (let* ((already (or (info-foreign-type-struct name ftd)
+                      (info-foreign-type-union name ftd)))
+         (name (unescape-foreign-name name)))
+    (do-interface-dirs (d ftd)
+      (let* ((r (%load-foreign-record (db-records d) name ftd already)))
+	(when r (return r))))))
+
+
Index: /branches/new-random/lib/defstruct-lds.lisp
===================================================================
--- /branches/new-random/lib/defstruct-lds.lisp	(revision 13309)
+++ /branches/new-random/lib/defstruct-lds.lisp	(revision 13309)
@@ -0,0 +1,406 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; defstruct-lds.lisp
+
+(in-package "CCL")
+
+(eval-when (eval compile)
+  (require 'defstruct-macros)
+)
+
+
+
+
+(defun uvector-subtype-p (thing subtype-number)
+  (= (the fixnum (typecode thing)) subtype-number))
+
+(defun uvector (subtype &rest p)
+  (declare (dynamic-extent p))
+  (let ((n (length p)) (uv))
+    (setq uv  (%alloc-misc n subtype))
+    (dotimes (i (the fixnum n)) (declare (fixnum i)) (uvset uv i (pop p)))
+    uv))
+
+;(defmacro test (&rest args) `(macroexpand-1 (defstruct ,@args)))
+
+;--> To do: compiler transform for copier, possibly constructor.
+(defmacro defstruct (options &rest slots &environment env)
+  "DEFSTRUCT {Name | (Name Option*)} {Slot | (Slot [Default] {Key Value}*)}
+   Define the structure type Name. Instances are created by MAKE-<name>, 
+   which takes &KEY arguments allowing initial slot values to the specified.
+   A SETF'able function <name>-<slot> is defined for each slot to read and
+   write slot values. <name>-p is a type predicate.
+
+   Popular DEFSTRUCT options (see manual for others):
+
+   (:CONSTRUCTOR Name)
+   (:PREDICATE Name)
+       Specify the name for the constructor or predicate.
+
+   (:CONSTRUCTOR Name Lambda-List)
+       Specify the name and arguments for a BOA constructor
+       (which is more efficient when keyword syntax isn't necessary.)
+
+   (:INCLUDE Supertype Slot-Spec*)
+       Make this type a subtype of the structure type Supertype. The optional
+       Slot-Specs override inherited slot options.
+
+   Slot options:
+
+   :TYPE Type-Spec
+       Asserts that the value of this slot is always of the specified type.
+
+   :READ-ONLY {T | NIL}
+       If true, no setter function is defined for this slot."
+  ;There's too much state to keep around here to break it up into little
+  ;functions, so what the hell, let's do it all inline...
+  (prog (struct-name type conc-name constructor copier predicate include
+         print-function print-object  named initial-offset boa-constructors print-p
+         documentation (slot-list ()) (offset 0) superclasses sd
+         refnames)
+    ;Parse options
+    (if (atom options)
+      (setq struct-name options options ())
+      (setq struct-name (pop options)))
+    (unless (symbolp struct-name) (signal-program-error $XNotSym struct-name))
+    (let (name args constructor-p predicate-p)
+      (while options
+        (if (atom (car options))
+          (setq name (%car options) args ())
+          (setq name (%caar options) args (%cdar options)))
+        (case name
+          (:conc-name
+           (when conc-name (go dup-options))
+           (when (cdr args) (go bad-options))
+           (setq conc-name (or args (list nil))))
+          (:constructor
+           (when (cddr args) (go bad-options))
+           (cond ((cdr args) (push args boa-constructors))
+                 (t (when constructor (go dup-options))
+                    (unless (symbolp (%car args)) (go bad-options))
+                    (setq constructor-p t constructor args))))
+          (:copier
+           (when copier (go dup-options))
+           (when (or (cdr args) (not (symbolp (%car args)))) (go bad-options))
+           (setq copier args))
+          (:predicate
+           (when predicate (go dup-options))
+           (when (or (cdr args) (not (symbolp (%car args)))) (go bad-options))
+           (setq predicate-p t predicate args))
+          (:include
+           (when include (go dup-options))
+           (when (or (null args) (not (symbolp (car args)))) (go bad-options))
+           (setq include args))
+          ((:print-function :print-object)
+           (when print-function (go dup-options))
+           (when (or (cdr args)
+                     (not (or (symbolp (%car args))
+                              (and (consp (%car args)) (eq (%caar args) 'lambda)))))
+             (go bad-options))
+           (setq print-p t
+		 print-function (%car args)
+		 print-object (eq name :print-object)))
+          (:type
+           (when type (go dup-options))
+           (when (cdr args) (go bad-options))
+           (unless (eq (setq type (%car args)) 'list)
+             (when (eq type 'vector) (setq type '(vector t)))
+             (when (or (atom type) (neq (%car type) 'vector) (cdr (%cdr type)))
+               (go bad-options))))
+          (:named
+           (when args (go bad-options))
+           (setq named t))
+          (:initial-offset
+           (when initial-offset (go dup-options))
+           (when (or (cdr args) (not (fixnump (%car args))) (%i< (%car args) 0))
+             (go bad-options))
+           (setq initial-offset (%car args)))
+          (t (go bad-options)))
+        (setq options (%cdr options)))
+      ;Options parsed!  Do defaulting and some consistency checking.
+      (cond (type
+             (when (null (defstruct-reftype type)) ;e.g. (vector NIL)
+               (bad-named-arg :type type))
+             (when print-p
+               (error "Cannot specify ~S with ~S" :print-function :type))
+             (if (and named (consp type) (eq (car type) 'vector)
+                      (cadr type) (not (subtypep 'symbol (cadr type))))
+               (error "Cannot specify ~S with type: ~S" :named type))
+             )
+            ((built-in-type-p struct-name)
+             (error "Cannot redefine built-in type ~S" struct-name))
+            (initial-offset
+             (error "Cannot use ~S without ~S" :initial-offset :type))
+            (t (setq named t)))
+      (if (not named)
+        (when predicate-p
+          (unless (null (setq predicate (%car predicate)))
+            (error "Cannot specify :PREDICATE for an unnamed structure")))
+        (setq predicate (if (null predicate)
+                          (concat-pnames struct-name "-P")
+                          (%car predicate))))
+      (setq conc-name
+            (if (null conc-name) (%str-cat (symbol-name struct-name) "-")
+                (if (%car conc-name) (string (%car conc-name)))))
+      (unless (and boa-constructors (not constructor-p))
+        (setq constructor
+              (if (null constructor)
+                (concat-pnames "MAKE-" struct-name) (%car constructor))))
+      (setq copier
+            (if (null copier) (concat-pnames "COPY-" struct-name) (%car copier))))
+    ;Process included slots
+    (when include
+      (let* ((included-name (%car include))
+             (sub-sd (or (let* ((defenv (definition-environment env)))
+                          (when defenv (%cdr (assq included-name (defenv.structures defenv)))))
+                         (gethash included-name %defstructs%)))
+            (slots (%cdr include))
+            name args ssd)
+        (unless sub-sd (error "No such structure: ~S" (cons :include include)))
+        (unless (eq (defstruct-reftype type)
+                    (defstruct-reftype (sd-type sub-sd)))
+          (error "Incompatible structure type ~S for ~S"
+                 (sd-type sub-sd) (cons :include include)))
+        (dolist (ssd (sd-slots sub-sd)) (push
+					 (let* ((new-ssd (copy-ssd ssd)))
+					   (ssd-set-inherited new-ssd)
+					   new-ssd)
+					   slot-list))
+        (while slots
+          (if (atom (car slots))
+            (setq name (%car slots) args ())
+            (setq name (%caar slots) args (%cdar slots)))
+          (unless (symbolp name) (signal-program-error $XNotSym name))
+          (unless (setq ssd (named-ssd name slot-list))
+            (error "~S has no ~S slot, in ~S"
+                   (sd-name sub-sd) name (cons :include include)))
+          (ssd-set-initform ssd (pop args))
+          (while args
+            (when (atom (cdr args)) (signal-program-error "~S is not a proper list" (cdr args)))
+            (cond ((eq (%car args) :type) )
+                  ((eq (%car args) :read-only)
+                   (when (and (not (%cadr args)) (ssd-r/o ssd))
+                     (signal-program-error "Slot ~S in ~S must be read-only" name (sd-name sub-sd)))
+                   (when (%cadr args) (ssd-set-r/o ssd)))
+                  (t (signal-program-error "~S must be  (member :type :read-only)." (%car args))))
+            (setq args (%cddr args)))
+          (setq slots (%cdr slots)))
+        (setq offset (sd-size sub-sd))
+        (setq superclasses (sd-superclasses sub-sd))))
+    (push struct-name superclasses)
+    ;Now add own slots
+    (setq offset (%i+ offset (or initial-offset 0)))
+    (when (and named (or type (not include)))
+      (push (make-ssd 0 (if type `',struct-name `',superclasses) offset t) slot-list)
+      (setq named offset offset (%i+ offset 1)))
+    (when (stringp (%car slots))
+      (setq documentation (%car slots) slots (%cdr slots)))
+    (let (name args read-only initform slot-type)
+      (while slots
+         (if (atom (%car slots))
+           (setq name (%car slots) args ())
+           (setq name (%caar slots) args (%cdar slots)))
+         (unless (symbolp name) (go bad-slot))
+         (setq read-only nil initform (pop args) slot-type t)
+         (while args
+            (when (atom (cdr args)) (go bad-slot))
+            ;; To do: check for multiple/incompatible options.
+            (cond ((eq (%car args) :type)
+                   (setq slot-type (%cadr args)))
+                  ((eq (%car args) :read-only)
+                   (setq read-only (%cadr args)))
+                  (t (go bad-slot)))
+            (setq args (%cddr args)))
+         (specifier-type slot-type env) ;; Check for validity (signals program error)
+         (push (make-ssd name initform offset read-only slot-type) slot-list)
+         (setq slots (%cdr slots) offset (%i+ offset 1))))
+    (setq slot-list (nreverse slot-list))
+    (when (and (null type) include)
+      (ssd-set-initform (car slot-list) `',superclasses))
+    (progn ;when conc-name
+      (dolist (slot slot-list)
+        (unless (fixnump (ssd-name slot))
+          (push (if conc-name
+                  (concat-pnames conc-name (ssd-name slot))
+                  (ssd-name slot))
+                refnames)))
+      (setq refnames (nreverse refnames)))
+    (setq sd (vector type slot-list superclasses offset constructor () refnames))
+    (return
+     `(progn
+	,@(when (null (sd-type sd))
+		`((when (memq ',struct-name *nx-known-declarations*)
+		    (check-declaration-redefinition ',struct-name 'defstruct))))
+       (remove-structure-defs  ',struct-name) ; lose any previous defs
+        ,.(defstruct-slot-defs sd refnames env)
+        ,.(if constructor (list (defstruct-constructor sd constructor)))
+        ,.(defstruct-boa-constructors sd boa-constructors)
+        ,.(if copier (defstruct-copier sd copier env))
+        ,.(if predicate (defstruct-predicate sd named predicate env))
+        (eval-when (:compile-toplevel)
+          (define-compile-time-structure 
+            ',sd 
+            ',refnames 
+            ,(if (and predicate (null (sd-type sd))) `',predicate)
+            ,env))        
+        (%defstruct-do-load-time
+         ',sd
+         ,(if (and predicate (null (sd-type sd))) `',predicate)
+         ,.(if documentation (list documentation)))
+        ,.(%defstruct-compile sd refnames env)
+       ;; Wait until slot accessors are defined, to avoid
+       ;; undefined function warnings in the print function/method.
+       (%defstruct-set-print-function
+	',sd
+	,(if print-function
+	  (if (symbolp print-function)
+	    `',print-function
+	    `#',print-function)
+	  (unless print-p (if include 0)))
+	,print-object)
+        ',struct-name))
+
+    dup-options
+     (error "Duplicate ~S options not allowed" (%car options))
+    bad-options
+     (signal-program-error "Bad defstruct option ~S." (%car options))
+    bad-slot
+    (signal-program-error "Bad defstruct slot spec ~S." (%car slots))))
+
+(defun concat-pnames (name1 name2)
+  (intern (%str-cat (string name1) (string name2))))
+
+(defun wrap-with-type-check (value slot &aux (slot-type (ssd-type slot)))
+  (if (eq t slot-type)
+    value
+    `(require-type ,value ',slot-type)))
+
+(defun make-class-cells-list (class-names)
+  (if (and (consp class-names)
+           (eq (car class-names) 'quote)
+           (consp (cdr class-names))
+           (null (cddr class-names))
+           (listp (cadr class-names))
+           (every #'symbolp (cadr class-names)))
+    `',(mapcar (lambda (name) (find-class-cell name t)) (cadr class-names))
+    class-names))
+
+(defun defstruct-constructor (sd constructor &aux (offset 0)
+                                                  (args ())
+                                                  (values ())
+                                                  slot-offset
+                                                  name)
+  (dolist (slot (sd-slots sd))
+    (setq slot-offset (ssd-offset slot))
+    #-bccl (when (%i< slot-offset offset)
+             (error "slots out of order! ~S" (sd-slots sd)))
+    (while (%i< offset slot-offset)
+      (push nil values)
+      (setq offset (%i+ offset 1)))
+    (if (fixnump (setq name (ssd-name slot)))
+      (if (eql 0 name)
+        (push (make-class-cells-list (ssd-initform slot)) values) 
+        (push (wrap-with-type-check (ssd-initform slot) slot) values))
+      (let* ((temp (make-symbol (symbol-name name))))
+        (push (list (list (make-keyword name) temp) (ssd-initform slot)) args)
+        (push (wrap-with-type-check temp slot) values)))
+    (setq offset (%i+ offset 1)))
+  (setq values (nreverse values))
+  `(defun ,constructor (&key ,@(nreverse args))
+     ,(case (setq name (defstruct-reftype (sd-type sd)))
+          (#.$defstruct-nth `(list ,@values))
+          (#.target::subtag-simple-vector `(vector ,@values))
+          ((#.target::subtag-struct #.$defstruct-struct)
+           `(gvector :struct ,@values))
+          (t `(uvector ,name ,@values)))))
+
+(defun defstruct-boa-constructors (sd boas &aux (list ()))
+  (dolist (boa boas list)
+    (push (defstruct-boa-constructor sd boa) list)))
+
+(defun defstruct-boa-constructor (sd boa &aux (args ())
+                                     (used-slots ())
+                                     (values ())
+                                     (offset 0)
+                                     arg-kind slot slot-offset)
+  (unless (verify-lambda-list (cadr boa))
+    (error "Invalid lambda-list in ~S ." (cons :constructor boa)))
+  (dolist (arg (cadr boa))
+    (cond ((memq arg lambda-list-keywords)
+           (setq arg-kind arg))
+          ((setq slot (named-ssd arg (sd-slots sd)))
+           (when (or (eq arg-kind '&optional) (eq arg-kind '&key)
+                     ;; for &aux variables, init value is
+                     ;; implementation-defined, however it's not
+                     ;; supposed to signal a type error until slot is
+                     ;; assigned, so might as well just use the
+                     ;; initform.
+                     (eq arg-kind '&aux))
+             (setq arg (list arg (ssd-initform slot))))
+           (push slot used-slots))
+          ((and (consp arg) (setq slot (named-ssd (if (consp (%car arg)) (%cadar arg) (%car arg)) (sd-slots sd))))
+           (push slot used-slots))
+          (t nil))
+    (push arg args))
+  (dolist (slot (sd-slots sd))
+    (setq slot-offset (ssd-offset slot))
+    #-bccl (when (%i< slot-offset offset) (error "slots out of order! ~S" sd))
+    (while (%i< offset slot-offset)
+      (push nil values)
+      (setq offset (%i+ offset 1)))
+    (push (if (memq slot used-slots) (ssd-name slot)
+            (if (eql 0 (ssd-name slot))
+              (make-class-cells-list (ssd-initform slot))
+              (if (constantp (ssd-initform slot)) (ssd-initform slot)
+                (progn
+                  (unless (eq arg-kind '&aux)
+                    (push (setq arg-kind '&aux) args))
+                  (push (list (ssd-name slot) (ssd-initform slot)) args)
+                  (ssd-name slot)))))
+          values)
+    (setq offset (%i+ offset 1)))
+  (setq values (mapcar #'wrap-with-type-check (nreverse values) (sd-slots sd)))
+  `(defun ,(car boa) ,(nreverse args)
+    ,(case (setq slot (defstruct-reftype (sd-type sd)))
+           (#.$defstruct-nth `(list ,@values))
+           (#.target::subtag-simple-vector `(vector ,@values))
+           ((#.target::subtag-struct #.$defstruct-struct)
+            `(gvector :struct ,@values))
+           (t `(uvector ,slot ,@values)))))
+
+(defun defstruct-copier (sd copier env)
+  `((eval-when (:compile-toplevel)
+      (record-function-info ',copier ',*one-arg-defun-def-info* ,env))
+    (fset ',copier
+          ,(if (eq (sd-type sd) 'list) '#'copy-list '#'copy-uvector))
+    (record-source-file ',copier 'function)))
+
+(defun defstruct-predicate (sd named predicate env)
+  (declare (ignore env))
+  (let* ((arg (gensym))
+         (sd-name (sd-name sd))
+         (body
+          (case (sd-type sd)
+            ((nil) `(structure-typep ,arg ',(find-class-cell sd-name t)))
+            ((list) `(and (consp ,arg) (eq (nth ,named ,arg) ',sd-name)))
+            (t `(and (uvector-subtype-p ,arg ,(defstruct-reftype (sd-type sd)))
+               (< ,named (uvsize ,arg))
+               (eq (uvref ,arg ,named) ',sd-name))))))
+    `((defun ,predicate (,arg) ,body))))
+
+; End of defstruct-lds.lisp
Index: /branches/new-random/lib/defstruct-macros.lisp
===================================================================
--- /branches/new-random/lib/defstruct-macros.lisp	(revision 13309)
+++ /branches/new-random/lib/defstruct-macros.lisp	(revision 13309)
@@ -0,0 +1,110 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; This file is needed to compile DEFSTRUCT and anything accessing defstruct
+; data structures.
+
+(in-package "CCL")
+
+(eval-when (:execute :compile-toplevel)
+  (require "LISPEQU"))
+
+(defconstant $struct-r/o 24)             ; Read-only bit in refinfo fixnum
+(defconstant $struct-inherited 25)		; Struct slot is  inherited.
+
+
+(defconstant $defstruct-nth 0)   ; Anything that won't conflict with array types...
+(defconstant $defstruct-struct 8)
+(defconstant $defstruct-simple-vector 16)
+
+
+(defmacro ssd-name (ssd) `(car ,ssd))
+;(defmacro ssd-type (ssd) (declare (ignore ssd)) t)
+(defmacro ssd-initform (ssd) `(cadr ,ssd))
+;(defmacro ssd-refinfo (ssd) `(cddr ,ssd))
+
+(defmacro ssd-update-refinfo ((ssd refinfo-var) new-refinfo-form)
+  (check-type refinfo-var symbol)
+  (let ((refinfo-cons (gensym)))
+    `(let* ((,refinfo-cons (cdr ,ssd))
+            (,refinfo-var (cdr ,refinfo-cons)))
+       (when (consp ,refinfo-var)
+         (setq ,refinfo-cons ,refinfo-var)
+         (setq ,refinfo-var (%cdr ,refinfo-cons)))
+       (%rplacd ,refinfo-cons ,new-refinfo-form))))
+
+(defmacro refinfo-offset (refinfo) `(%ilogand2 #xFFFF ,refinfo))
+(defmacro refinfo-r/o (refinfo) `(%ilogbitp $struct-r/o ,refinfo))
+(defmacro refinfo-reftype (refinfo) `(%ilogand2 #xFF (%ilsr 16 ,refinfo)))
+
+(defmacro ssd-offset (ssd) `(refinfo-offset (ssd-refinfo ,ssd)))
+(defmacro ssd-r/o (ssd) `(refinfo-r/o (ssd-refinfo ,ssd)))
+(defmacro ssd-reftype (ssd) `(refinfo-reftype (ssd-refinfo ,ssd)))
+
+(defmacro ssd-set-initform (ssd value) `(rplaca (cdr ,ssd) ,value))
+
+#| these are fns now
+(defmacro ssd-set-reftype (ssd reftype)      ;-> ssd multiply evaluated
+  `(rplacd (cdr ,ssd) (%ilogior2 (%ilogand2 #x100FFFF (cdr (%cdr ,ssd)))
+                                 (%ilsl 16 ,reftype))))
+
+(defmacro ssd-set-r/o (ssd)                  ;-> ssd multiply evaluated
+  `(rplacd (cdr ,ssd) (%ilogior2 #x1000000 (cdr (%cdr ,ssd)))))
+
+(defmacro copy-ssd (ssd)                     ;-> ssd multiply evaluated
+  `(list* (car ,ssd) (car (%cdr ,ssd)) (%cddr ,ssd)))
+|#
+
+(defmacro named-ssd (name slot-list) `(assq ,name ,slot-list))
+
+(defmacro sd-name (sd) `(car (svref ,sd 2)))
+(defmacro sd-type (sd) `(svref ,sd 0))
+(defmacro sd-slots (sd) `(svref ,sd 1))
+(defmacro sd-superclasses (sd) `(svref ,sd 2))
+(defmacro sd-size (sd) `(svref ,sd 3))
+(defmacro sd-constructor (sd) `(svref ,sd 4))
+(defmacro sd-print-function (sd) `(svref ,sd 5))
+(defmacro sd-set-print-function (sd value) `(svset ,sd 5 ,value))
+(defmacro sd-refnames (sd) `(svref ,sd 6))
+
+(defmacro struct-name (struct) `(class-cell-name (car (uvref ,struct 0))))
+(defmacro struct-def (struct) `(gethash (struct-name ,struct) %defstructs%))
+
+;Can use this to let the printer print with print-function, reader read with
+;constructor and slot-names, inspector inspect with slot-names.
+;Everything else you have to arrange yourself.
+#+ignore
+(defmacro pretend-i-am-a-structure (name constructor print-function &rest slot-names)
+  (let ((slots slot-names) (offset 1) (supers (list name)))
+    (while slots
+      (%rplaca slots (make-ssd (%car slots) () offset t))
+      (ssd-set-reftype (%car slots) $v_struct)
+      (setq slots (%cdr slots) offset (1+ offset)))
+    (push (make-ssd 0 `',supers 0 t) slot-names)
+    (ssd-set-reftype (%car slot-names) $v_struct)
+    `(puthash ',name %defstructs%
+          '#(internal-structure  ;Make structure-class-p false.
+             ,slot-names
+             ,supers
+             ,offset
+             ,constructor
+             ,print-function
+             nil))))
+
+(provide 'defstruct-macros)
+
+; End of defstruct-macros.lisp
Index: /branches/new-random/lib/defstruct.lisp
===================================================================
--- /branches/new-random/lib/defstruct.lisp	(revision 13309)
+++ /branches/new-random/lib/defstruct.lisp	(revision 13309)
@@ -0,0 +1,305 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Defstruct.lisp
+
+(eval-when (eval compile)
+  (require 'defstruct-macros)
+
+)
+
+(defvar %structure-refs% (make-hash-table :test #'eq))
+(defvar %defstructs% (make-hash-table :test #'eq))
+
+(defun make-ssd (name initform offset r/o &optional (type t))
+  (let ((refinfo (%ilogior2 offset (if r/o #x1000000 0))))
+    (list* name initform
+           (if (eq type 't)
+             refinfo
+             (cons type refinfo)))))
+
+(declaim (inline type-and-refinfo-p))
+(defun type-and-refinfo-p (object)
+  (or (fixnump object) (consp object)))
+
+(defun ssd-set-reftype (ssd reftype)
+  (ssd-update-refinfo (ssd refinfo)
+                      (%ilogior2 (%ilogand2 #x300FFFF refinfo)
+                                 (%ilsl 16 reftype))))
+
+(defun ssd-set-r/o (ssd) 
+  (ssd-update-refinfo (ssd refinfo)
+                      (%ilogior2 #x1000000 refinfo)))
+
+(defun ssd-set-inherited (ssd)
+  (ssd-update-refinfo (ssd refinfo)
+		       (bitset $struct-inherited refinfo)))
+
+(defun copy-ssd (ssd)
+  (let* ((cdr (cdr ssd))
+         (cddr (cdr cdr)))
+    (list* (%car ssd) (%car cdr)
+           (if (consp cddr)
+             (list* (%car cddr) (%cdr cddr))
+             cddr))))
+
+(declaim (inline ssd-type-and-refinfo))
+(defun ssd-type-and-refinfo (ssd)
+  (cddr ssd))
+
+(defun ssd-type (ssd)
+  (let ((type-and-refinfo (ssd-type-and-refinfo ssd)))
+    (if (consp type-and-refinfo)
+      (%car type-and-refinfo)
+      't)))
+
+(defun ssd-refinfo (ssd)
+  (let ((type-and-refinfo (ssd-type-and-refinfo ssd)))
+    (if (consp type-and-refinfo) (%cdr type-and-refinfo) type-and-refinfo)))
+
+(defun %structure-class-of (thing)
+  (let* ((cell (car (uvref thing 0))))
+    (or (class-cell-class cell)
+        (setf (class-cell-class cell)
+              (find-class (class-cell-name cell))))))
+
+;These might want to compiler-transform into non-typechecking versions...
+(defun struct-ref (struct offset)
+  (if (structurep struct) (uvref struct offset)
+      (report-bad-arg struct 'structure-object)))
+
+(defun struct-set (struct offset value)
+  (if (structurep struct) (uvset struct offset value)
+      (report-bad-arg struct 'structure-object)))
+
+(defsetf struct-ref struct-set)
+
+
+; things for defstruct to do - at load time
+(defun %defstruct-do-load-time (sd predicate &optional doc &aux (name (sd-name sd)))
+  ;(declare (ignore refnames))
+  (when (null (sd-type sd))
+    (%define-structure-class sd))
+  (when (and doc *save-doc-strings*)
+    (set-documentation name 'type doc))  
+  (puthash name %defstructs% sd)
+  (record-source-file name 'structure)
+  (when (and predicate (null (sd-type sd)))
+    (puthash predicate %structure-refs% name))  
+  (when *fasload-print* (format t "~&~S~%" name))
+  name)
+
+(defun %defstruct-set-print-function (sd print-function print-object-p)
+  (sd-set-print-function sd (if print-object-p
+			      (list print-function)
+			      print-function)))
+
+
+(defun sd-refname-pos-in-included-struct (sd name)
+  (dolist (included-type (cdr (sd-superclasses sd)))
+    (let ((sub-sd (gethash included-type %defstructs%)))
+      (when sub-sd
+        (let ((refnames (sd-refnames sub-sd)))
+          (if refnames
+            (let ((pos (position name refnames :test 'eq)))
+              (and pos (1+ pos)))
+            (dolist (slot (sd-slots sub-sd))
+              (let ((ssd-name (ssd-name slot)))
+                (unless (fixnump ssd-name)
+                  (when (eq name ssd-name)
+                    (return-from sd-refname-pos-in-included-struct
+                      (ssd-offset slot))))))))))))
+
+;;; return stuff for defstruct to compile
+(defun %defstruct-compile (sd refnames env)
+  (let ((stuff))    
+    (dolist (slot (sd-slots sd))
+      (unless (fixnump (ssd-name slot))
+        (let* ((accessor (if refnames (pop refnames) (ssd-name slot)))
+               (pos (sd-refname-pos-in-included-struct sd accessor)))
+          (if pos
+            (let ((offset (ssd-offset slot)))
+              (unless (eql pos offset)
+                ; This should be a style-warning
+                (warn "Accessor ~s at different position than in included structure"
+                      accessor)))
+            (let ((fn (slot-accessor-fn slot accessor env)))
+              (push
+               `(progn
+                  ,.fn
+                  (puthash ',accessor %structure-refs% ',(ssd-type-and-refinfo slot))
+                  (record-source-file ',accessor 'structure-accessor))
+               stuff))))))
+    (nreverse stuff)))
+
+
+; no #. for cross compile
+(defvar *struct-ref-vector* 
+  (vector #'(lambda (x) (struct-ref x 0))
+          #'(lambda (x) (struct-ref x 1))
+          #'(lambda (x) (struct-ref x 2))
+          #'(lambda (x) (struct-ref x 3))
+          #'(lambda (x) (struct-ref x 4))
+          #'(lambda (x) (struct-ref x 5))
+          #'(lambda (x) (struct-ref x 6))
+          #'(lambda (x) (struct-ref x 7))
+          #'(lambda (x) (struct-ref x 8))
+          #'(lambda (x) (struct-ref x 9))))
+
+(defvar *svref-vector*
+  (vector #'(lambda (x) (svref x 0))
+          #'(lambda (x) (svref x 1))
+          #'(lambda (x) (svref x 2))
+          #'(lambda (x) (svref x 3))
+          #'(lambda (x) (svref x 4))
+          #'(lambda (x) (svref x 5))
+          #'(lambda (x) (svref x 6))
+          #'(lambda (x) (svref x 7))
+          #'(lambda (x) (svref x 8))
+          #'(lambda (x) (svref x 9))))
+
+
+;;; too bad there isnt a way to suppress generating these darn
+;;; functions when you dont want them.  Makes no sense to fetch
+;;; functions from a vector of 68K functions and send them over to
+;;; PPC.  So can use that space optimization iff host and target are
+;;; the same.
+
+
+(defparameter *defstruct-share-accessor-functions* t)   ;; TODO: isn't it time to get rid of this?
+
+(defun slot-accessor-fn (slot name env &aux (ref (ssd-reftype slot)) (offset (ssd-offset slot)))
+  (cond ((eq ref $defstruct-nth)
+         (if (and  (%i< offset 10) *defstruct-share-accessor-functions*)
+           `((eval-when (:compile-toplevel)
+               (record-function-info ',name ',*one-arg-defun-def-info* ,env))
+              (fset ',name
+                    ,(symbol-function
+                      (%svref '#(first second third fourth fifth
+                                 sixth seventh eighth ninth tenth) offset))))
+           `((defun ,name (x)  (nth ,offset x)))))
+        ((eq ref $defstruct-struct)
+         (if (and (%i< offset 10) *defstruct-share-accessor-functions*)
+           `((eval-when (:compile-toplevel)
+               (record-function-info ',name ',*one-arg-defun-def-info* ,env))                
+             (fset ',name , (%svref *struct-ref-vector* offset)))
+           `((defun ,name (x)  (struct-ref x ,offset)))))
+        ((or (eq ref target::subtag-simple-vector)
+             (eq ref $defstruct-simple-vector))
+         (if (and (%i< offset 10) *defstruct-share-accessor-functions*)
+           `((eval-when (:compile-toplevel)
+               (record-function-info ',name ',*one-arg-defun-def-info* ,env))
+             (fset ',name ,(%svref *svref-vector* offset)))
+           `((defun ,name (x)  (svref x ,offset)))))
+        (t `((defun ,name (x) (uvref x ,offset))))))
+
+(defun defstruct-reftype (type)
+  (cond ((null type) $defstruct-struct)
+        ((eq type 'list) $defstruct-nth)
+        (t (element-type-subtype (cadr type)))))
+
+(defun defstruct-slot-defs (sd refnames env)
+  (declare (ignore env))
+  (let ((ref (defstruct-reftype (sd-type sd))) name defs)
+    (dolist (slot (sd-slots sd))
+      (ssd-set-reftype slot ref)
+      (unless (fixnump (setq name (ssd-name slot))) ;Ignore fake 'name' slots
+        (when refnames (setq name (pop refnames)))
+        (unless (sd-refname-pos-in-included-struct sd name)
+          (push name defs))))
+    (setq defs (nreverse defs))
+    `((declaim (inline ,@defs)))))
+
+;;;Used by nx-transform, setf, and whatever...
+(defun defstruct-ref-transform (predicate-or-type-and-refinfo args &optional env)
+  (if (type-and-refinfo-p predicate-or-type-and-refinfo)
+    (multiple-value-bind (type refinfo)
+                         (if (consp predicate-or-type-and-refinfo)
+                           (values (%car predicate-or-type-and-refinfo)
+                                   (%cdr predicate-or-type-and-refinfo))
+                           (values 't predicate-or-type-and-refinfo))
+      (let* ((offset (refinfo-offset refinfo))
+             (ref (refinfo-reftype refinfo))
+             (accessor
+              (cond ((eq ref $defstruct-nth)
+                     `(nth ,offset ,@args))
+                    ((eq ref $defstruct-struct)
+                     `(struct-ref ,@args ,offset))
+                    ((eq ref target::subtag-simple-vector)
+                     `(svref ,@args ,offset))
+                    (ref
+                     `(aref (the (simple-array ,(element-subtype-type ref) (*))
+                                 ,@args) ,offset))
+                    (t `(uvref ,@args ,offset)))))
+        (if (eq type 't)
+          accessor
+          (if (specifier-type-if-known type env)
+            `(the ,type ,accessor)
+            (if (nx-declarations-typecheck env)
+              `(require-type ,accessor ',type)
+              ;; Otherwise just ignore the type, it's most likely a forward reference,
+              ;; and while it means we might be missing out on a possible optimization,
+              ;; most of the time it's not worth warning about.
+              accessor)))))
+    `(structure-typep ,@args ',predicate-or-type-and-refinfo)))
+
+;;; Should probably remove the constructor, copier, and predicate as
+;;; well. Can't remove the inline proclamations for the refnames,
+;;; as the user may have explicitly said this. Questionable - but surely
+;;; must delete the inline definitions.
+;;; Doesn't remove the copier because we don't know for sure what it's name is
+(defmethod change-class ((from structure-class)
+			 (to class)
+			  &rest initargs &key &allow-other-keys)
+  (declare (dynamic-extent initargs))
+  (let ((class-name (class-name from)))
+    (unless (eq from to)                  ; shouldn't be
+      (remove-structure-defs class-name)
+      (remhash class-name %defstructs%)))
+  (%change-class from to initargs))
+
+;;; if redefining a structure as another structure or redefining a
+;;; structure as a class
+(defun remove-structure-defs (class-name)
+  (let ((sd (gethash class-name %defstructs%)))
+    (when sd
+      (dolist (refname (sd-refnames sd))
+        (remhash refname %structure-refs%)
+        (let ((def (assq refname *nx-globally-inline*)))
+          (when def (set-function-info refname nil)))
+        (when (symbolp refname)(fmakunbound refname)))
+      (let ((print-fn (sd-print-function sd)))
+        (when (symbolp print-fn) (fmakunbound print-fn)))
+      (let ((constructor (sd-constructor sd)))
+        (when (symbolp constructor) (fmakunbound constructor)))
+      (let ((delete-match #'(lambda (pred struct-name)
+                              (when (eq struct-name class-name)
+                                (remhash pred %structure-refs%)
+                                (fmakunbound pred)))))
+        (declare (dynamic-extent delete-match))
+        ; get rid of the predicate
+        (maphash delete-match %structure-refs%)))))
+
+(defun copy-structure (source)
+  "Return a copy of STRUCTURE with the same (EQL) slot values."
+  (copy-uvector (require-type source 'structure-object)))
+
+(provide 'defstruct)
+
+; End of defstruct.lisp
Index: /branches/new-random/lib/describe.lisp
===================================================================
--- /branches/new-random/lib/describe.lisp	(revision 13309)
+++ /branches/new-random/lib/describe.lisp	(revision 13309)
@@ -0,0 +1,1955 @@
+;;; -*- Mode:Lisp; Package:INSPECTOR -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(defpackage "INSPECTOR"
+  (:use "CL" "CCL")
+  (:export "MAKE-INSPECTOR"
+           "COMPUTE-LINE-COUNT"
+           "LINE-N"
+           "INSPECTOR-OBJECT"
+           "INSPECTOR-LINE-COUNT"
+
+           "*INSPECTOR-DISASSEMBLY*"))
+
+
+
+(in-package "INSPECTOR")
+
+(defvar ccl::@)
+
+;;; The basic inspector object.
+;;; Note that this knows nothing about windows.
+;;; It merely knows how to number the constituent parts of an object,
+;;; How to access a constituent, and how to print a constituent to a stream.
+(defclass inspector ()
+  ((object :accessor inspector-object :initarg :object)
+   (line-count :accessor inspector-line-count :initarg :line-count :initform nil)
+   ;; so can refresh.
+   (initargs :reader inspector-initargs :initform nil)))
+
+(defmethod initialize-instance :before ((i inspector) &rest initargs)
+  (setf (slot-value i 'initargs) initargs))
+
+;;; The usual way to cons up an inspector
+(defmethod make-inspector (object)
+  (multiple-value-bind (class alias) (inspector-class object)
+    (make-instance class :object (or alias object))))
+
+(defmethod initialize-instance :after ((i inspector) &key update-line-count)
+  (when update-line-count
+    (update-line-count i)))
+
+(defmethod refresh-inspector ((i inspector))
+  (apply #'make-instance (class-of i) (slot-value i 'initargs)))
+
+;; New protocol, used by gui inspector instead of the line-n protocol, which isn't quite right.
+;; Perhaps tty inspector should use it as well.  Returns the line inspector rather than object,
+;; and returns the value string rather than having the caller print it.
+(defmethod inspector-line ((i inspector) index)
+  (let ((line-i (multiple-value-bind (value label type) (inspector::line-n i index)
+		  (and (not (eq (parse-type i type) :comment))
+		       (line-n-inspector i index value label type)))))
+    (multiple-value-bind (label-string value-string) (line-n-strings i index)
+      (values line-i label-string value-string))))
+
+;; for a comment value = nil, label = "the comment" type = :comment
+;;; => line-i = nil
+
+;;;;;;;
+;;;
+;;; The protocol for an inspector.
+;;; Change these to defgeneric's when it exists.
+;;;
+;;; Usually, you need to define methods only for
+;;; inspector-class, compute-line-count, line-n, and (setf line-n)
+
+;;; Return the type of inspector for an object
+(defmethod inspector-class (object)
+  (cond ((method-exists-p #'line-n object 0) 'usual-inspector)
+        ((and (uvectorp object)
+              (find-class 'uvector-inspector nil))
+         'uvector-inspector)
+        (t 'basic-inspector)))
+
+;;; Return three values: the value, label, and type of the nth line of the object
+;;; Valid types are:
+;;;  :NORMAL or NIL  - a normal constituent line: changeable
+;;;  :COLON          - a normal line with ": " between the label and the value
+;;;  :COMMENT        - a commentary line - Print only the label
+;;;  :STATIC         - a commentary line with an inspectable value: not changeable
+(defmethod line-n ((i inspector) n)
+  (declare (ignore n)))
+
+; set the value of line n of the object (the label is fixed)
+(defmethod (setf line-n) (value (i inspector) n)
+  (declare (ignore value n)))
+
+; Compute the number of lines in the object
+(defmethod compute-line-count ((i inspector))
+  0
+  )
+
+; Compute the number of lines in the object and set the line-count slot
+; If the length is greater than the limit, return (list limit)
+(defun update-line-count (inspector)
+  (setf (inspector-line-count inspector) (compute-line-count inspector)))
+
+; Print the nth line to a stream
+(defmethod prin1-line-n ((i inspector) stream n)
+  (multiple-value-call #'prin1-line i stream (line-n i n)))
+
+(defmethod prin1-line ((i inspector) stream value &optional label type function)
+  (unless function
+    (setq function (inspector-print-function i type)))
+  (funcall function i stream value label type))
+
+(defvar *collect-labels-if-list* t)
+
+(defmethod end-of-label ((stream string-output-stream))
+  (when (listp *collect-labels-if-list*)
+    (push (get-output-stream-string stream) *collect-labels-if-list*)))
+
+(defmethod line-n-strings ((i inspector) n)
+  (let* ((*collect-labels-if-list* ())
+	 (value-string (with-output-to-string (stream)
+			 (prin1-line-n i stream n)))
+	 (label-string (pop *collect-labels-if-list*))
+         (end (or (position-if-not #'whitespacep label-string :from-end t) -1)))
+    (assert (null *collect-labels-if-list*))
+    (unless (and (>= end 0) (eql (char label-string end) #\:)) (incf end))
+    (setq label-string (subseq label-string 0 end))
+    (values label-string value-string)))
+
+(defmethod inspector-print-function ((i inspector) type)
+  (declare (ignore type))
+  'prin1-normal-line)
+
+; Print a value to a stream.
+(defmethod prin1-normal-line ((i inspector) stream value &optional label type
+                              colon-p)
+  (let* ((type-sym (parse-type i type)))
+    (if (eq type-sym :colon) (setq colon-p t))
+    (when label
+      (prin1-label i stream value label type)
+      (if colon-p (princ ": " stream)))
+    (end-of-label stream)              ; used by cacheing code
+    (unless (eq type-sym :comment)
+      (prin1-value i stream value label type))))
+
+(defun prin1-colon-line (i stream value &optional label type)
+  (prin1-normal-line i stream value label type t))
+
+(defmethod prin1-label ((i inspector) stream value &optional label type)
+  (declare (ignore value type))
+  (if (stringp label)
+    (write-string label stream)
+    (princ label stream)))
+
+(defmethod prin1-value ((i inspector) stream value &optional label type)
+  (declare (ignore label type))
+  (prin1 value stream))
+
+;;; Call function on the inspector object and its value, label, & type, for
+;;; each line in the selected range (default to the whole thing).
+;;; This can avoid (e.g.) doing NTH for each element of a list.
+;;; This is the generic-function which the inspector-window uses to
+;;; display a screenful.
+(defmethod map-lines ((i inspector) function &optional 
+                      (start 0) 
+                      end)
+  (when (null (inspector-line-count i))
+    (update-line-count i))
+  (unless end
+    (setq end (inspector-line-count i)))
+  (when (and start end)
+    (let ((index start))
+      (dotimes (c (- end start))
+        (multiple-value-call function i index (inspector-line i index))
+        (incf index)))))
+
+;;;;;;;
+;;;
+;;; Dealing with unbound slots and bogus objects
+;;;
+(defclass unbound-marker () ())
+
+(defvar *unbound-marker* (make-instance 'unbound-marker))
+(defvar *slot-unbound-marker* (make-instance 'unbound-marker))
+
+(defmethod print-object ((x unbound-marker) stream)
+  (print-object (ccl::%unbound-marker) stream))
+
+(defclass bogus-object-wrapper ()
+  ((address :initarg :address)))
+
+(defmethod print-object ((x bogus-object-wrapper) stream)
+  (print-unreadable-object (x stream)
+    (format stream "BOGUS object @ #x~x" (slot-value x 'address))))
+
+(defvar *bogus-object-hash*
+  (make-hash-table :test 'eql :weak :value :size 0))
+
+(defun bogus-object-wrapper (x)
+  (let ((address (%address-of x)))
+    (or (gethash address *bogus-object-hash*)
+        (setf (gethash address *bogus-object-hash*)
+              (make-instance 'bogus-object-wrapper :address address)))))
+
+(defun eliminate-unbound (x)
+  (cond ((eq x (ccl::%unbound-marker))
+         *unbound-marker*)
+        ((eq x (ccl::%slot-unbound-marker))
+         *slot-unbound-marker*)
+        ((ccl::bogus-thing-p x)
+         (bogus-object-wrapper x))
+        (t x)))
+
+(defun restore-unbound (x)
+  (if (eq x *unbound-marker*)
+    (ccl::%unbound-marker)
+    (if (eq x *slot-unbound-marker*)
+      (ccl::%slot-unbound-marker)
+      x)))
+
+(defmethod line-n :around ((i inspector) n)
+  (declare (ignore n))
+  (let ((res (multiple-value-list (call-next-method))))
+    (declare (dynamic-extent res))
+    (apply #'values (eliminate-unbound (car res)) (cdr res))))
+
+(defmethod (setf line-n) :around (new-value (i inspector) n)
+  (call-next-method (restore-unbound new-value) i n))
+
+
+;;;;;;;
+;;;
+;;; describe-object
+;;; Eventually, this wants to reuse a global inspector rather than
+;;; consing one.
+(defparameter *describe-pretty* t)
+
+(defmacro with-errorfree-printing (&body body)
+  `(let ((*print-readably* nil)
+         (*signal-printing-errors* nil))
+     ,@body))
+
+(defun format-line-for-tty (stream label-string value-string)
+  (when (equal label-string "") (setq label-string nil))
+  (when (equal value-string "") (setq value-string nil))
+  (format stream "~@[~a~]~@[~a~]~@[~a~]"
+	  label-string
+	  (and label-string
+	       value-string 
+	       (not (eql #\space (char label-string (1- (length label-string)))))
+	       ": ")
+	  value-string))
+
+(defun describe (object &optional stream)
+  "Print a description of the object X."
+  (cond ((null stream) (setq stream *standard-output*))
+        ((eq stream t) (setq stream *terminal-io*)))
+  (setq stream (require-type stream 'stream))
+  (let* ((*print-circle* t)
+         (*print-length* 20))
+    (describe-object object stream)
+    (values)))
+
+(defmethod describe-object (object stream)
+  (let ((inspector (make-inspector object)))
+    (with-errorfree-printing
+        (let* ((*print-pretty* (or *print-pretty* *describe-pretty*))
+               (temp #'(lambda (i index child &optional label-string value-string)
+			 (declare (ignore i index child))
+			 (format-line-for-tty stream label-string value-string)
+			 (terpri stream))))
+          (declare (dynamic-extent temp))
+          (map-lines inspector temp))))
+  (values))
+
+;;; usual-inspector
+;;; Objects that know how to inspect themselves but don't need any
+;;; special info other than the object can be a usual-inspector.
+;;; This class exists mostly to save consing a class for every type
+;;; of object in the world.
+(defclass usual-inspector (inspector)
+  ())
+
+;;;;;;;
+;;
+;; formatting-inspector
+;; This one prints using a format string.
+;; Expects line-n to return (values value label type format-string)
+
+(defclass formatting-inspector (inspector) ())
+(defclass usual-formatting-inspector (usual-inspector formatting-inspector) ())
+
+(defmethod prin1-line ((i formatting-inspector) stream value
+                       &optional label type (format-string "~s"))
+  (funcall (if (listp format-string) #'apply #'funcall)
+           #'format-normal-line i stream value label type format-string))
+
+(defmethod format-normal-line ((i inspector) stream value &optional 
+                               label type (format-string "~s") colon-p)
+  (let* ((type-sym (parse-type i type)))
+    (if (eq type-sym :colon) (setq colon-p t))
+    (when label
+      (prin1-label i stream value label type)
+      (if colon-p (princ ": " stream)))
+    (end-of-label stream)              ; used by cacheing code
+    (unless (eq type-sym :comment)
+      (format stream format-string value))))
+
+;;;;;;;
+;;
+;; inspectors for CCL objects
+;;
+
+
+(defmethod parse-type ((i inspector) type &optional default1 default2)
+  (declare (ignore default1 default2))
+  (values (if (consp type) (car type) type)))
+
+;;; Used by the cache-entry-stream class to save the column where the label ends.
+(defmethod end-of-label (stream)
+  (declare (ignore stream)))
+
+
+
+;;;;;
+;;
+;; The default inspector class
+;; Used when we don't know what else to do
+;;
+
+(defclass basic-inspector (inspector) ())
+
+(defmethod compute-line-count ((i basic-inspector))
+  3)                                    ; type, class, value
+
+(defun line-n-out-of-range (i n)
+  (error "~s is not a valid index for line-n of ~s" n i))
+
+(defun setf-line-n-out-of-range (i n)
+  (error "~s is not a valid index for setf-line-n of ~s" n i))
+
+(defmethod line-n ((i basic-inspector) n)
+  (let ((object (inspector-object i)))
+    (case n
+      (0 (values object nil :static))
+      (1 (values (type-of object) "Type: " :static))
+      (2 (values (class-of object) "Class: " :static))
+      (t (line-n-out-of-range i n)))))
+
+;;;;;;;
+;;
+;; Automate the object being the first line
+;;
+(defclass object-first-mixin () ())
+(defclass object-first-inspector (object-first-mixin inspector) ())
+
+(defmethod compute-line-count :around ((i object-first-mixin))
+  (1+ (call-next-method)))
+
+(defmethod line-n :around ((i object-first-mixin) n)
+  (if (eql 0 n)
+    (values (inspector-object i) nil)
+    (call-next-method i (1- n))))
+
+(defmethod (setf line-n) :around (value (i object-first-mixin) n)
+  (if (eql n 0)
+    (replace-object i value)
+    (call-next-method value i (1- n))))
+
+(defun replace-object (inspector new-object)
+  (declare (ignore inspector))
+  (make-inspector new-object))
+
+
+; A mixin that displays the object, its type, and its class as the first three lines.
+(defclass basics-first-mixin () ())
+
+(defmethod compute-line-count :around ((i basics-first-mixin))
+  (+ 3 (call-next-method)))
+
+(defmethod line-n :around ((i basics-first-mixin) n)
+  (let ((object (inspector-object i)))
+    (case n
+      (0 (values object nil))
+      (1 (values (type-of object) "Type: " :static))
+      (2 (values (class-of object) "Class: " :static))
+      (t (call-next-method i (- n 3))))))
+
+(defmethod line-n-inspector :around ((i basics-first-mixin) n value label type)
+  (if (< n 3)
+    (make-inspector value)
+    (call-next-method i (- n 3) value label type)))
+
+(defmethod (setf line-n) :around (new-value (i basics-first-mixin) n)
+  (case n
+    (0 (replace-object i new-value))
+    ((1 2) (setf-line-n-out-of-range i n))
+    (t (call-next-method new-value i (- n 3)))))
+
+;;;;;;;
+;;
+(defclass usual-object-first-inspector (object-first-mixin usual-inspector)
+  ())
+(defclass usual-basics-first-inspector (basics-first-mixin usual-inspector)
+  ())
+
+(defvar *inspector*)
+
+(defmethod compute-line-count ((i usual-inspector))
+  (let ((*inspector* i))
+    (compute-line-count (inspector-object i))))
+
+(defmethod line-n ((i usual-inspector) n)
+  (let ((*inspector* i))
+    (line-n (inspector-object i) n)))
+
+(defmethod (setf line-n) (value (i usual-inspector) n)
+  (let ((*inspector* i))
+    (setf (line-n (inspector-object i) n) value)))
+
+(defmethod inspector-commands ((i usual-inspector))
+  (let ((*inspector* i))
+    (inspector-commands (inspector-object i))))
+
+(defmethod inspector-commands (random)
+  (declare (ignore random))
+  nil)
+
+;;;;;;;
+;;
+;; Bogus objects
+;;
+
+(defclass bogus-object-inspector (object-first-inspector)
+  ())
+
+(defmethod compute-line-count ((i bogus-object-inspector))
+  3)
+
+(defmethod line-n ((i bogus-object-inspector) n)
+  (values
+   nil
+   (case n
+     (0 "One cause of a bogus object is when a stack consed object is stored")
+     (1 "in a register and then control exits the dynamic-extent of the object.")
+     (2 "The compiler doesn't bother to clear the register since it won't be used again."))
+   '(:comment :plain :plain)))
+
+(defmethod inspector-class :around (object)
+  (if (ccl::bogus-thing-p object)
+    'bogus-object-inspector
+    (call-next-method)))
+
+;;;;;;;
+;;
+;; A general sequence inspector
+;;
+(defclass sequence-inspector (inspector)
+  ((print-function :initarg :print-function :initform #'prin1 :reader print-function)
+   (commands :initarg :commands :initform nil :accessor inspector-commands)
+   (line-n-inspector :initform nil :initarg :line-n-inspector
+                     :accessor line-n-inspector-function)
+   (replace-object-p :initform nil :initarg :replace-object-p
+                     :reader replace-object-p)
+   (resample-function :initform nil :initarg :resample-function
+                      :reader resample-function)
+   (line-n-function :initform nil :initarg :line-n-function
+                    :reader line-n-function)
+   (setf-line-n-p :initform t :initarg :setf-line-n-p
+                  :reader setf-line-n-p))
+  (:default-initargs :update-line-count t))
+
+
+
+(defmethod compute-line-count ((i sequence-inspector))
+  (let ((resample-function (resample-function i)))
+    (when resample-function
+      (setf (inspector-object i) (funcall resample-function i))))
+  (length (inspector-object i)))
+
+(defmethod line-n ((i sequence-inspector) n)
+  (let ((f (line-n-function i)))
+    (if f
+      (funcall f i n)
+      (values (elt (inspector-object i) n) nil (unless (setf-line-n-p i) :static)))))
+
+(defmethod (setf line-n) (new-value (i sequence-inspector) n)
+  (if (setf-line-n-p i)
+    (setf (elt (inspector-object i) n) new-value)
+    (setf-line-n-out-of-range i n)))
+
+(defmethod prin1-value ((inspector sequence-inspector) stream value
+                        &optional label type)
+  (declare (ignore label type))
+  (funcall (print-function inspector) value stream))
+
+(defmethod line-n-inspector ((i sequence-inspector) n value label type)
+  (let ((f (line-n-inspector-function i)))
+    (or (and f (funcall f i n value label type)) (call-next-method))))
+
+;;;;;;;
+;;
+;; standard-object
+;; This should be redone to use the exported class query functions
+;; (as soon as they exist)
+;;
+(defclass standard-object-inspector (object-first-inspector)
+  ())
+
+(defmethod inspector-class ((o standard-object))
+  'standard-object-inspector)
+
+(defmethod compute-line-count ((i standard-object-inspector))
+  (standard-object-compute-line-count i))
+
+(defun standard-object-compute-line-count (i)  
+  (let* ((object (ccl::maybe-update-obsolete-instance (inspector-object i)))
+         (class (class-of object))
+         (all-slots (ccl::class-slots class)))
+    (multiple-value-bind (instance-slots class-slots other-slots) (ccl::extract-instance-class-and-other-slotds all-slots)
+      (let* ((ninstance-slots (length instance-slots))
+             (nclass-slots (length class-slots))
+             (nother-slots (length other-slots)))
+        (+ 2                                ; class, wrapper
+           (if (eql 0 ninstance-slots)
+             0
+             (1+ ninstance-slots))
+           (if (eql 0 nclass-slots)
+             0
+             (1+ nclass-slots))
+           (if (eql 0 nother-slots)
+             0
+             (1+ nother-slots))
+           (if (eql 0 (+ nclass-slots ninstance-slots nother-slots))
+             1
+             0))))))
+
+(defun slot-value-or-unbound (instance slot-name)
+  (eliminate-unbound (ccl::slot-value-if-bound instance slot-name
+					       (ccl::%slot-unbound-marker))))
+
+(defparameter *standard-object-type* (list nil))
+(defparameter *standard-object-static-type*
+  (cons :static (cdr *standard-object-type*)))
+(defparameter *standard-object-comment-type* 
+  (list :comment))
+
+(defmethod line-n ((i standard-object-inspector) n)
+  (standard-object-line-n i n))
+
+(defmethod prin1-label ((i standard-object-inspector) stream value &optional label type)
+  (declare (ignore value type))
+  (if (symbolp label)
+    (prin1 label stream)
+    (call-next-method)))
+
+; Looks like
+; Class:
+; Wrapper:
+; [Instance slots:
+;  slots...]
+; [Class slots:
+;  slots...]
+; [Other slots:
+;  slots...]
+
+(defun standard-object-line-n (i n)
+  (let* ((instance (inspector-object i))
+         (class (class-of instance))
+         (all-slots (class-slots class))
+         (wrapper (or (ccl::standard-object-p instance)
+                      (if (typep instance 'ccl::funcallable-standard-object)
+                        (ccl::gf.instance.class-wrapper instance))))
+	 (instance-start 2))
+    (if (< n instance-start)
+      (if (eql n 0)
+	(values class "Class: " :normal)
+	(values wrapper "Wrapper: " :static))
+      (multiple-value-bind (instance-slotds class-slotds other-slotds)
+          (ccl::extract-instance-class-and-other-slotds all-slots)
+        (let* ((instance-count (length instance-slotds))
+               (shared-start (+ instance-start instance-count
+                                (if (eql 0 instance-count) 0 1))))
+          (if (< n shared-start)
+            (if (eql n instance-start)
+              (values nil "Instance slots" :comment)
+              (let ((slot-name (slot-definition-name
+                                (elt instance-slotds (- n instance-start 1)))))
+                (values (slot-value-or-unbound instance slot-name)
+                        slot-name
+                        :colon)))
+            (let* ((shared-count (length class-slotds))
+                   (shared-end (+ shared-start shared-count
+                                  (if (eql shared-count 0) 0 1))))
+              (if (< n shared-end)
+                (if (eql n shared-start)
+                  (values nil "Class slots" :comment)
+                  (let ((slot-name (slot-definition-name 
+                                    (elt class-slotds (- n shared-start 1)))))
+                    (values (slot-value-or-unbound instance slot-name)
+                            slot-name
+                            :colon)))
+                (let* ((other-start shared-end)
+                       (other-end (+ other-start (if other-slotds (1+ (length other-slotds)) 0))))
+                  (if (< n other-end)
+                    (if (eql n other-start)
+                      (values nil "Other slots" :comment)
+                      (let ((slot-name (slot-definition-name 
+                                        (elt other-slotds (- n other-start 1)))))
+                        (values (slot-value-or-unbound instance slot-name)
+                                slot-name
+                                :colon)))
+                    (if (and (eql 0 instance-count) (eql 0 shared-count) (null other-slotds) (eql n other-end))
+                      (values nil "No Slots" :comment)
+                      (line-n-out-of-range i n))))))))))))
+
+(defmethod (setf line-n) (value (i standard-object-inspector) n)
+  (standard-object-setf-line-n value i n))
+
+(defun standard-object-setf-line-n (value i n)
+  (let* ((instance (inspector-object i))
+         (class (class-of instance))
+         (instance-start 2))
+    (if (< n instance-start)
+      (cond
+       ((eql n 0) (change-class instance value)
+         (update-line-count i))
+        (t (setf-line-n-out-of-range i n)))
+      (let* ((slotds (ccl::extract-instance-effective-slotds class))
+             (instance-count (length slotds))
+             (shared-start (+ instance-start instance-count
+                              (if (eql 0 instance-count) 0 1))))
+        (if (< n shared-start)
+          (if (eql n instance-start)
+            (setf-line-n-out-of-range i n)
+            (let ((slot-name (slot-definition-name
+                              (elt slotds (- n instance-start 1)))))
+              (setf (slot-value instance slot-name) (restore-unbound value))))
+          (let* ((slotds (ccl::extract-class-effective-slotds class))
+                 (shared-count (length slotds))
+                 (shared-end (+ shared-start shared-count
+                                (if (eql shared-count 0) 0 1))))
+            (if (< n shared-end)
+              (if (eql n shared-start)
+                (setf-line-n-out-of-range i n)
+                (let ((slot-name (slot-definition-name 
+                                  (elt slotds (- n shared-start 1)))))
+                  (setf (slot-value instance slot-name)
+                        (restore-unbound value))))
+              (setf-line-n-out-of-range i n))))))))
+
+
+
+;;;;;;;;;;;  Inspector objects for common classes.
+
+(defparameter *plain-comment-type* '(:comment (:plain)))
+(defparameter *bold-comment-type* '(:comment (:bold)))
+
+(defun resample-it ()
+  )
+
+;;;;;;;
+;;
+;; Lists
+;;
+(defclass cons-inspector (basics-first-mixin inspector) ())
+
+(defclass list-inspector (basics-first-mixin inspector)
+  ((length :accessor list-inspector-length)
+   (dotted-p :accessor list-inspector-dotted-p)
+   (nthcdr :accessor list-inspector-nthcdr)
+   (n :accessor list-inspector-n)))
+
+(defmethod inspector-class ((o list))
+  (if (listp (cdr o))
+    'list-inspector
+    'cons-inspector))
+
+; Same as list-length-and-final-cdr, but computes the real length of the list
+(defun real-list-length (list)
+  (multiple-value-bind (len final-cdr max-circ-len)
+      (ccl::list-length-and-final-cdr list)
+    (if (null max-circ-len)
+      (values len final-cdr nil)
+      (let ((middle (nthcdr max-circ-len list))
+            (n 1))
+        (loop (when (eq list middle) (return))
+          (pop list)
+          (incf n))
+        (pop list)
+        (loop (when (eq list middle) (return))
+          (pop list)
+          (incf n))
+        (values nil nil n)))))        
+
+(defmethod compute-line-count ((i list-inspector))
+  (multiple-value-bind (len final-cdr circ-len) (real-list-length (inspector-object i))
+    (setf (list-inspector-dotted-p i) final-cdr)
+    (setf (list-inspector-nthcdr i) (inspector-object i))
+    (setf (list-inspector-n i) 0)
+    (+ 1                                ; regular, dotted, or circular
+       1                                ; length
+       (abs (setf (list-inspector-length i)
+                  (or len (- circ-len))))   ; the elements
+       (if final-cdr 2 0))))            ; the final-cdr and it's label
+
+(defmethod compute-line-count ((i cons-inspector))
+  2)                                    ; car & cdr
+
+(defmethod line-n ((i list-inspector) en &aux (n en))
+  (let* ((circ? (list-inspector-length i))
+         (length (abs circ?)))
+    (cond ((eql 0 n)
+           (values nil (cond ((list-inspector-dotted-p i) "Dotted List")
+                             ((< circ? 0) "Circular List")
+                             (t "Normal List"))
+                   *plain-comment-type*))
+          ((eql 0 (decf n)) (values length "Length: "))
+          ((>= (decf n) (setq length length))   ; end of dotted list
+           (let ((final-cdr (list-inspector-dotted-p i)))
+             (unless final-cdr (line-n-out-of-range i en))
+             (if (eql n length)
+               (values nil "Non-nil final cdr" *plain-comment-type*)
+               (values final-cdr (- length 0.5) :colon))))
+          (t (let* ((saved-n (list-inspector-n i))
+                    (nthcdr (if (>= n saved-n)
+                              (nthcdr (- n saved-n) (list-inspector-nthcdr i))
+                              (nthcdr n (inspector-object i)))))
+               (setf (list-inspector-nthcdr i) nthcdr
+                     (list-inspector-n i) n)
+               (values (car nthcdr) n :colon))))))
+
+(defmethod line-n ((i cons-inspector) n)
+  (let ((object (inspector-object i)))
+    (ecase n
+           (0 (values (car object) "Car: "))
+           (1 (values (cdr object) "Cdr: ")))))
+
+(defmethod (setf line-n) (value (i list-inspector) n)
+  (when (< n 2)
+    (setf-line-n-out-of-range i n))
+  (decf n 2)
+  (setf (elt (inspector-object i) n) value)
+  (resample-it))
+
+(defmethod (setf line-n) (value (i cons-inspector) n)
+  (let ((object (inspector-object i)))
+    (ecase n
+           (0 (setf (car object) value))
+           (1 (setf (cdr object) value))))
+  (resample-it))
+
+;;;;;;;
+;;
+;; General uvector's
+;;
+(defclass uvector-inspector (basics-first-mixin inspector)
+  ((name-list :initarg :name-list :initform nil :accessor name-list)))
+
+(defmethod uvector-name-list (object) 
+  (let* ((type (type-of object))
+         (names (cdr (assq type ccl::*def-accessor-types*)))
+         (names-size (length names))
+         res)
+    (when names
+      (dotimes (i (uvsize object))
+        (declare (fixnum i))
+        (let ((name (and (> names-size i) (aref names i))))
+          (if name
+            (push (if (listp name) (car name) name) res)
+            (if (and (eql i 0) (typep object 'ccl::internal-structure))
+              (push 'type res)
+              (push i res)))))
+      (nreverse res))))
+
+(defmethod compute-line-count ((i uvector-inspector))
+  (setf (name-list i) (uvector-name-list (inspector-object i)))
+  (uvsize (inspector-object i)))
+
+(defmethod line-n ((i uvector-inspector) n)
+  (values (uvref (inspector-object i) n)
+          (or (let ((name-list (name-list i))) (and name-list (nth n (name-list i))))
+              n)
+          :colon))
+
+(defmethod (setf line-n) (new-value (i uvector-inspector) n)
+  (setf (uvref (inspector-object i) n) new-value))
+
+(defmethod inspector-commands ((i uvector-inspector))
+  (let ((object (inspector-object i)))
+    (if (method-exists-p #'inspector-commands object)
+      (inspector-commands object))))
+
+;;;;;;;
+;;
+;; Vectors & Arrays
+;;
+(defmethod inspector-class ((v ccl::simple-1d-array))
+  'usual-basics-first-inspector)
+
+(defmethod compute-line-count ((v ccl::simple-1d-array))
+  (+ 1 (length v)))
+
+(defmethod line-n ((v ccl::simple-1d-array) n)
+  (cond ((eql 0 n) (values (length v) "Length" :static 'prin1-colon-line))
+        (t (decf n 1)
+           (values (aref v n) n :colon))))
+
+(defmethod (setf line-n) (value (v ccl::simple-1d-array) n)
+  (when (<= n 0)
+    (setf-line-n-out-of-range v n))
+  (decf n 1)
+  (prog1 (setf (aref v n) value)
+    (resample-it)))
+
+(defclass array-inspector (uvector-inspector) ())
+
+(defmethod inspector-class ((v array))
+  'array-inspector)
+
+(defmethod uvector-name-list ((a array))
+  (if (eql 1 (array-rank a))
+    (if (array-has-fill-pointer-p a)
+      '("Fill Pointer" "Physical size" "Data vector" "Displacement" "Flags")
+      '("Logical size" "Physical size" "Data vector" "Displacement" "Flags"))
+    `("Rank" "Physical size" "Data vector" "Displacement" "Flags" "Dim0" "Dim1" "Dim2" "Dim3")))
+
+(defmethod compute-line-count ((i array-inspector))
+  (let* ((a (inspector-object i))
+         (rank (array-rank a)))
+    (call-next-method)                  ; calculate name list
+    (+ (if (eql rank 1) (1+ (uvsize a))  7)
+       (apply #'* (array-dimensions a)))))
+
+(defmethod line-n ((i array-inspector) n)
+  (let* ((v (inspector-object i))
+         (rank (array-rank v))
+         (uvsize (if (eql rank 1)
+                   (+ (uvsize v) 1)
+                   7)))
+    (cond ((eql 0 n) (values (array-element-type v)
+                             (if (adjustable-array-p v)
+                               "Adjustable, Element type"
+                               "Element type")
+                             :static 'prin1-colon-line))
+          ((eql  5 n)
+           (values  (uvref v target::vectorH.flags-cell)
+                   "Flags: "
+                   :static
+                   #'(lambda (i s v l type)
+                       (format-normal-line i s v l type "#x~x"))))
+          ((and (eql  6 n) (not (eql rank 1)))
+           (values (array-dimensions v) "Dimensions: " :static))
+          ((< n uvsize) (call-next-method i (1- n)))
+          (t (let ((index (- n uvsize)))
+               (values (row-major-aref v index) (array-indices v index) :colon))))))
+
+(defmethod (setf line-n) (new-value (i array-inspector) n)
+  (let* ((v (inspector-object i))
+         (rank (array-rank v))
+         (uvsize (if (eql rank 1)
+                   (+ (uvsize v) 1)
+                   7)))
+    (prog1
+      (cond ((or (eql 0 n) (eql 1 n) (and (eql 4 n) (not (eql rank 1))))
+             (setf-line-n-out-of-range i n))
+            ((< n uvsize)
+             (if (eql 3 n)
+               (setq new-value (require-type new-value 'array))
+               (setq new-value (require-type new-value 'fixnum)))
+             (call-next-method new-value i (1- n)))
+          (t (let ((index (- n uvsize)))
+               (setf (row-major-aref v index) new-value))))
+      (resample-it))))
+
+(defun array-indices (a row-major-index)
+  (let ((rank (array-rank a)))
+    (if (eql 1 rank)
+      row-major-index
+      (let ((res nil)
+            dim
+            (dividend row-major-index)
+            remainder)
+        (loop
+          (when (zerop rank) (return res))
+          (setq dim (array-dimension a (decf rank)))
+          (multiple-value-setq (dividend remainder) (floor dividend dim))
+          (push remainder res))))))
+  
+(defmethod prin1-line ((i array-inspector) stream value &optional
+                       label type function)
+  (declare (ignore stream value type function))
+  (if (or (numberp label) (listp label))   ; First line or contents lines
+    (call-next-method)
+    (let ((*print-array* nil))
+      (call-next-method))))
+
+;;;;;;;
+;;
+;; Numbers
+;;
+(defmethod inspector-class ((num number)) 'usual-formatting-inspector)
+
+; floats
+(defmethod compute-line-count ((num float)) 5)
+
+(defmethod line-n ((num float) n)
+  (let ((type :static))
+    (ecase n
+      (0 (values num "Float:           " type))
+      (1 (values num "Scientific:      " type
+                 (if (< num 0) "~8,2e" "~7,2e")))
+      (2 (values (if (zerop num) "illegal" (log num 2))
+                     "Log base 2:      " type "~d"))
+      (3 (values (rationalize num)
+                     "Ratio equiv:     " type))
+      (4 (values (round num)
+                     "Nearest integer: " type)))))
+
+; complex numbers
+(defmethod compute-line-count ((num complex)) 3)
+
+(defmethod line-n ((num complex) n)
+  (let ((type :static))
+    (ecase n
+      (0 (values num            "Complex num:    " type))
+      (1 (values (realpart num) "Real part:      " type))
+      (2 (values (imagpart num) "Imaginary part: " type)))))
+
+; ratios
+(defmethod compute-line-count ((num ratio)) 6)
+
+(defmethod line-n ((num ratio) n)
+  (let ((type :static))
+    (ecase n
+      (0 (values num               "Ratio:           " type))
+      (1 (values (float num)       "Scientific:      " type 
+                 (if (< num 0) "~8,2e" "~7,2E")))
+      (2 (values (if (zerop num) "illegal" (log num 2))
+                                   "Log base 2:      " type "~d"))
+      (3 (values (round num)       "Nearest integer: " type))
+      (4 (values (numerator num)   "Numerator:       " type))
+      (5 (values (denominator num) "Denominator:     " type)))))
+
+; integers
+(defmethod compute-line-count ((num integer)) 
+  (let ((res 12))
+    (unless (< 0 num 4000) (decf res))   ; not a roman number
+    (unless (<= 0 num 255) (decf res))   ; not a character
+    res))
+
+(defmethod line-n ((num integer) n)
+  (if (and (>= n 7) (not (< 0 num 4000))) (incf n))   ; maybe skip roman.
+  (if (and (>= n 8) (not (<= 0 num 255))) (incf n))   ; maybe skip character.
+  (let* ((type :static)
+         (neg? (< num 0))
+         (norm (if neg? 
+                 (+ num (expt 2 (max 32 (* 4 (round (+ (integer-length num) 4) 4)))))
+                 num)))
+    (ecase n
+      (0  (values num
+                (if (fixnump num)
+                  "Fixnum:      "
+                  "Bignum:      ")
+                type "~s"))
+      (1  (let ((num (ignore-errors (float num))))
+            (values num "Scientific:  " type
+                    (cond ((null num) "FLOATING-POINT-OVERFLOW")
+                          ((< num 0) "~8,2e")
+                          (t "~7,2e")))))
+      (2  (values (if (zerop num) "illegal" (log num 2)) 
+                  "Log base 2:  " type "~d"))
+      (3  (values norm
+                  "Binary:      " type
+                  (if neg? "#b...~b" "#b~b")))
+      (4  (values norm
+                  "Octal:       " type
+                  (if neg? "#o...~o" "#o~o")))
+      (5  (values num
+                  "Decimal:     " type "~d."))
+      (6  (values norm
+                  "Hex:         " type
+                  (if neg? "#x...~x" "#x~x")))
+      (7  (values (format nil "~@r" num)
+                  "Roman:       " type "~a"))
+      (8  (values (code-char num)
+                  "Character:   " type "~s"))
+      (9 (values (ccl::ensure-simple-string (prin1-to-string num))
+                  "Abbreviated: "
+                  type #'format-abbreviated-string))
+      (10 (values (or (ignore-errors (universal-time-string num)) "#<error>")
+                  "As time:     " type "~a"))
+      (11 (if (< num 0)
+            (values most-negative-fixnum 'most-negative-fixnum type '("~d." t))
+            (values most-positive-fixnum 'most-positive-fixnum type '("~d." t)))))))
+
+(defun format-abbreviated-string (stream string)
+  (setq string (require-type string 'simple-string))
+  (let ((length (length string)))
+    (if (< length 7)
+      (princ string stream)
+      (format stream "~a <- ~s digits -> ~a"
+              (subseq string 0 3)
+              (- length 6)
+              (subseq string (- length 3) length)))))
+
+(defun universal-time-string (num)
+  (multiple-value-bind (second minute hour date month year day)
+                       (decode-universal-time num)
+    (with-output-to-string (s)
+      (format s "~d:~2,'0d:~2,'0d " hour minute second)
+      (princ (nth day '("Monday" "Tuesday" "Wednesday" "Thursday" "Friday"
+                        "Saturday" "Sunday"))
+             s)
+      (format s ", ~d " date)
+      (princ (nth month '("" "January" "February" "March" "April" "May" "June" "July"
+                          "August" "September" "October" "November" "December"))
+             s)
+      (format s ", ~d" year))))
+
+; Characters
+(defmethod compute-line-count ((ch character)) 2)
+
+(defmethod line-n ((ch character) n)
+  (let ((type :static))
+    (ecase n
+      (0 (values ch             "Character: " type))
+      (1 (values (char-code ch) "char-code: " type)))))
+
+;;;;;;;
+;;
+;; Symbols
+;;
+(defun symbol-has-bindings-p (sym)
+  (or (constantp sym) (proclaimed-special-p sym) (boundp sym)
+      (special-operator-p sym) (macro-function sym) (fboundp sym)
+      (type-specifier-p sym) (record-type-p sym nil)
+      (find-class sym nil)))
+
+(defmethod inspector-class ((sym symbol)) 'usual-basics-first-inspector)
+
+(defmethod compute-line-count ((sym symbol))
+  (+ (if (symbol-has-bindings-p sym) 1 0)
+     1                                  ; package
+     1                                  ; symbol-name
+     1                                  ; symbol-value
+     1                                  ; symbol-function
+     (if (fboundp sym) 1 0)             ; arglist
+     1                                  ; plist
+     (if (find-class sym nil) 1 0)      ; class
+     ))
+
+
+(defmethod normalize-line-number ((sym symbol) n)
+  (if (and (>= n 0) (not (symbol-has-bindings-p sym))) (incf n))
+  (if (and (>= n 5) (not (fboundp sym))) (incf n))
+  n)
+
+(defmethod line-n ((sym symbol) n)
+  (setq n (normalize-line-number sym n))
+  (let ((type :normal)
+        (comment '(:comment (:bold)))
+        (static :static))
+    (ecase n
+      (0 (values nil (symbol-type-line sym) comment))
+      (1 (let ((p (symbol-package sym)))
+           (if (null p)
+             (values nil "No home package." comment)
+             (multiple-value-bind (found kind) (find-symbol (symbol-name sym) p)
+               (values p 
+                       (if (or (null kind) (neq found sym))
+                         "NOT PRESENT in home package: "
+                         (format nil "~a in package: " kind))
+                       static)))))
+      (2 (values (symbol-name sym) "Print name: " static))
+      (3 (values (if (boundp sym) (symbol-value sym) *unbound-marker*)
+                 "Value: " type))
+      (4 (values (if (fboundp sym)
+                   (cond ((macro-function sym))
+                         ((special-operator-p sym) sym)
+                         (t (symbol-function sym)))
+                   *unbound-marker*)
+                 "Function: " type))
+      (5 (values (and (fboundp sym) (arglist sym))
+                 "Arglist: " static))
+      (6 (values (symbol-plist sym) "Plist: " type))
+      (7 (values (find-class sym) "Class: " static)))))
+
+(defmethod (setf line-n) (value (sym symbol) n)
+  (let (resample-p)
+    (setq n (normalize-line-number sym n))
+    (setq value (restore-unbound value))
+    (ecase n
+      ((0 1 2 5) (setf-line-n-out-of-range sym n))
+      (3 (setf resample-p (not (boundp sym))
+               (symbol-value sym) value))
+      (4 (setf resample-p (not (fboundp sym))
+               (symbol-function sym) value))
+      (6 (setf (symbol-plist sym) value)))
+    (when resample-p (resample-it))
+    value))
+
+(defun record-type-p (name &optional check-database)
+  (declare (ignore check-database))
+  (and (keywordp name)
+       (ignore-errors (ccl::%foreign-type-or-record name))))
+
+; Add arglist here.
+(defun symbol-type-line (sym)
+  (let ((types (list
+                (cond ((constantp sym)
+                       "Constant")
+                      ((proclaimed-special-p sym)
+                       "Special Variable")
+                      ((boundp sym)
+                       "Non-special Variable")
+                      (t nil))
+                (cond ((special-operator-p sym)
+                       "Special Operator")
+                      ((macro-function sym)
+                       "Macro")
+                      ((fboundp sym)
+                       "Function")
+                      (t nil))
+                (if (type-specifier-p sym) "Type Specifier")
+                (if (record-type-p sym nil) "Record Type")
+                (if (find-class sym nil) "Class Name")))
+        flag)
+    (with-output-to-string (s)
+      (dolist (type types)
+        (when type
+          (if flag (write-string ", " s))
+          (setq flag t)
+          (write-string type s))))))
+    
+
+(defmethod inspector-commands ((sym symbol))
+  (let ((res nil))
+    '(push (list "Documentation" #'(lambda () (show-documentation sym)))
+          res)
+    (let ((class (find-class sym nil)))
+      (if class
+        (push (list "Inspect Class" #'(lambda () (inspect class))) res)))
+    (if (boundp sym)
+      (push (list "MAKUNBOUND" #'(lambda () (when (y-or-n-p (format nil "~s?" `(makunbound ',sym)))
+                                              (makunbound sym) (resample-it))))
+            res))
+    (if (fboundp sym)
+      (push (list "FMAKUNBOUND" #'(lambda () (when (y-or-n-p (format nil "~s?" `(fmakunbound ',sym)))
+                                               (fmakunbound sym) (resample-it))))
+            res))
+    '(if (record-type-p sym)
+      (push (list "Inspect Record Type" #'(lambda () (inspect-record-type sym)))
+            res))
+    (nreverse res)))
+
+
+(defmethod line-n-inspector ((sym symbol) n value label type)
+  (declare (ignore label type))
+  (setq n (normalize-line-number sym n))
+  (if (eql n 6)
+    (make-instance 'plist-inspector :symbol sym :object value)
+    (call-next-method)))
+
+(defclass plist-inspector (inspector)
+  ((symbol :initarg :symbol :reader plist-symbol)))
+
+(defmethod inspector-window-title ((i plist-inspector))
+  (format nil "~a of ~s" 'plist (plist-symbol i)))
+
+(defmethod compute-line-count ((i plist-inspector))
+  (+ 3 (/ (length (inspector-object i)) 2)))
+
+(defmethod line-n ((i plist-inspector) n)
+  (let* ((plist (inspector-object i)))
+    (cond ((eql 0 n) (values plist "Plist: "))
+          ((eql 1 n) (values (plist-symbol i) "Symbol: " :static))
+          ((eql 2 n) (values nil nil :comment))
+          (t (let ((rest (nthcdr (* 2 (- n 3)) plist)))
+               (values (cadr rest) (car rest) :colon))))))
+
+(defmethod (setf line-n) (new-value (i plist-inspector) n)
+  (let* ((plist (inspector-object i)))
+    (if (eql n 0)
+      (replace-object i new-value)
+      (if (< n 3)
+        (setf-line-n-out-of-range i n)
+        (let ((rest (nthcdr (* 2 (- n 3)) plist)))
+          (setf (cadr rest) new-value)
+          (resample-it))))))
+
+(defparameter *inspector-disassembly* nil)
+
+;;;;;;;
+;;
+;; Functions
+;;
+(defclass function-inspector (inspector)
+  ((header-lines :initform nil :reader header-lines)
+   (disasm-p :accessor disasm-p :initform *inspector-disassembly*)
+   (disasm-info :accessor disasm-info)
+   (pc-width :accessor pc-width)
+   (pc :initarg :pc :initform nil :accessor pc)))
+
+(defmethod standard-header-count ((f function-inspector)) (length (header-lines f)))
+
+(defmethod header-count ((f function-inspector)) (standard-header-count f))
+
+(defclass closure-inspector (function-inspector)
+  ((n-closed :accessor closure-n-closed)))
+
+(defmethod inspector-class ((f function)) 'function-inspector)
+(defmethod inspector-class ((f compiled-lexical-closure)) 'closure-inspector)
+
+(defmethod compute-line-count :before ((f function-inspector))
+  (let* ((o (inspector-object f))
+         (doc (documentation o t))
+         (sn (ccl::function-source-note o))
+         (lines (nconc (list (list o ""))
+                       (list (list (function-name o) "Name" :colon))
+                       (list (multiple-value-bind (arglist type) (arglist o)
+                               (let ((label (if type
+                                              (format nil "Arglist (~(~a~))" type)
+                                              "Arglist unknown")))
+                                 (list arglist label (if type :colon '(:comment (:plain)))))))
+                       (when doc (list (list (substitute #\space #\newline doc) "Documentation" :colon)))
+                       (when sn (list (list sn "Source Location" :colon))))))
+    (setf (slot-value f 'header-lines) lines)))
+
+(defmethod compute-line-count ((f function-inspector))
+  (+ (header-count f) (compute-disassembly-lines f)))
+
+(defmethod line-n-strings ((f function-inspector) n)
+  (if (< (decf n (header-count f)) 0)
+    (call-next-method)
+    (disassembly-line-n-strings f n)))
+
+(defmethod line-n-inspector ((f function-inspector) n value label type)
+  (declare (ignore value label type))
+  (if (< (decf n (header-count f)) 0)
+    (call-next-method)
+    (disassembly-line-n-inspector f n)))
+
+(defmethod line-n ((f function-inspector) n)
+  (let* ((lines (header-lines f))
+         (nlines (length lines)))
+    (if (< n nlines)
+      (apply #'values (nth n lines))
+      (disassembly-line-n f (- n nlines)))))
+
+(defmethod compute-line-count :before ((f closure-inspector))
+  (let* ((o (inspector-object f))
+	 (nclosed (nth-value 8 (function-args (ccl::closure-function o)))))
+    (setf (closure-n-closed f) nclosed)))
+
+(defmethod header-count ((f closure-inspector))
+  (+ (standard-header-count f)
+     1                              ; the function we close over
+     1                              ; "Closed over values"
+     (closure-n-closed f)))
+
+(defmethod line-n ((f closure-inspector) n)
+  (let ((o (inspector-object f))
+        (nclosed (closure-n-closed f)))
+    (if (< (decf n (standard-header-count f)) 0)
+      (call-next-method)
+      (cond ((< (decf n) 0)
+             (values (ccl::closure-function o) "Inner lfun: " :static))
+            ((< (decf n) 0)
+             (values nclosed "Closed over values" :comment))
+            ((< n nclosed)
+             (let* ((value (ccl::nth-immediate o (1+ (- nclosed n))))
+                    (map (car (ccl::function-symbol-map (ccl::closure-function o))))
+                    (label (or (and map (svref map (+ n (- (length map) nclosed))))
+                               n))
+                    (cellp (ccl::closed-over-value-p value)))
+               (when cellp
+                 (setq value (ccl::closed-over-value value)
+                       label (format nil "(~a)" label)))
+               (values value label (if cellp :normal :static) #'prin1-colon-line)))
+            (t (disassembly-line-n f (- n nclosed)))))))
+
+(defmethod (setf line-n) (new-value (f function-inspector) n)
+  (let ((o (inspector-object f))
+        (standard-header-count (standard-header-count f)))
+    (if (< n standard-header-count)
+      (case n
+        (0 (replace-object f new-value))
+        (1 (ccl::lfun-name o new-value) (resample-it))
+        (t (setf-line-n-out-of-range f n)))
+      (set-disassembly-line-n f (- n standard-header-count) new-value)))
+  new-value)
+
+(defmethod (setf line-n) (new-value (f closure-inspector) en &aux (n en))
+  (let ((o (inspector-object f))
+        (nclosed (closure-n-closed f)))
+    (if (< (decf n (standard-header-count f)) 0)
+      (call-next-method)
+      (cond ((< (decf n 2) 0)          ; inner-lfun or "Closed over values"
+             (setf-line-n-out-of-range f en))
+            ((< n nclosed)       ; closed-over variable
+             (let* ((value (ccl::nth-immediate o (1+ (- nclosed n))))
+                    (cellp (ccl::closed-over-value-p value)))
+               (unless cellp (setf-line-n-out-of-range f en))
+               (ccl::set-closed-over-value value new-value)))
+            (t (set-disassembly-line-n f (- n nclosed) new-value))))))
+
+(defun compute-disassembly-lines (f &optional (function (inspector-object f)))
+  (if (and (functionp function) (disasm-p f))
+    (let* ((lines (ccl::disassemble-lines function)) ;; list of (object label instr)
+           (length (length lines))
+           (last-label (loop for n from (1- length) downto 0 as line = (aref lines n)
+                             thereis (and (consp line) (cadr line))))
+           (max-pc (if (consp last-label) (cadr last-label) last-label)))
+      (setf (pc-width f) (length (format nil "~d" max-pc)))
+      (setf (disasm-info f) lines)
+      (1+ length))
+    0))
+
+(defun disassembly-line-n (f n)
+  (if (< (decf n) 0)
+    (values nil "Disassembly:" :comment)
+    (let ((line (svref (disasm-info f) n)))
+      (if (consp line)
+        (destructuring-bind (object label instr) line
+          (values object (cons label instr) :static))
+        (values nil (cons nil line) :static)))))
+
+(defun disassembly-line-n-inspector (f n)
+  (unless (< (decf n) 0)
+    (let ((line (svref (disasm-info f) n)))
+      (and (consp line)
+	   (car line)
+	   (make-inspector (car line))))))
+
+(defun disassembly-line-n-strings (f n)
+  (if (< (decf n) 0)
+    (values "Disassembly:" nil)
+    (let ((line (svref (disasm-info f) n)))
+      (if (consp line)
+        (destructuring-bind (object label instr) line
+          (declare (ignore object))
+          (unless (stringp label)
+            (setq label (with-output-to-string (stream)
+                          (prin1-disassembly-label f stream label))))
+          (values label instr))
+        (values nil line)))))
+
+(defun set-disassembly-line-n (f n new-value &optional 
+                                 (function (inspector-object f)))
+  (declare (ignore new-value function))
+  (setf-line-n-out-of-range f n))
+
+(defmethod prin1-label ((f function-inspector) stream value &optional data type)
+  (declare (ignore value type))
+  (if (atom data)                      ; not a disassembly line
+    (call-next-method)
+    (prin1-disassembly-label f stream (car data))))
+
+(defun prin1-disassembly-label (f stream label)
+  (let* ((pc label)
+         (label-p (and (consp pc) (setq pc (cadr pc))))
+         (pc-mark (pc f))
+         (pc-width (pc-width f)))
+    (when pc
+      (write-char (if (eql pc pc-mark) #\* #\Space) stream)
+      (format stream "~@[L~d~]~vT~v<[~d]~> " label-p (+ pc-width 3) (+ pc-width 2) pc))))
+
+#+x86-target
+(defmethod prin1-value ((f function-inspector) stream value &optional data type)
+  (declare (ignore value type))
+  (if (atom data) ;; not a disassembly line
+    (call-next-method)
+    (princ (cdr data) stream)))
+
+
+#+ppc-target
+(defmethod prin1-value ((f function-inspector) stream value &optional label type)
+  (if (atom label)                      ; not a disassembly line
+    (unless (eq (if (consp type) (car type) type) :comment)
+      (call-next-method))
+    (let ((q (cdr label)))
+      (write-char #\( stream)
+      (loop (if (null q) (return))
+        (ccl::disasm-prin1 (pop q) stream)
+        (if q (write-char #\space stream)))
+      (write-char #\) stream)))
+  value)
+
+;; Generic-functions
+;; Display the list of methods on a line of its own to make getting at them faster
+;; (They're also inside the dispatch-table which is the first immediate in the disassembly).
+(defclass gf-inspector (function-inspector)
+  ((method-count :accessor method-count)))
+
+(defmethod inspector-class ((f standard-generic-function))
+  (if (functionp f) 
+    'gf-inspector
+    'standard-object-inspector))
+
+(defmethod compute-line-count :before ((f gf-inspector))
+  (let* ((gf (inspector-object f))
+         (count (length (generic-function-methods gf))))
+    (setf (method-count f) count)))
+
+(defmethod header-count ((f gf-inspector))
+  (+ (standard-header-count f) 1 (method-count f)))
+
+(defmethod line-n ((f gf-inspector) n)
+  (let* ((count (method-count f))
+	 (methods (generic-function-methods (inspector-object f))))
+    (cond ((< (decf n  (standard-header-count f)) 0)
+           (call-next-method))
+          ((< (decf n) 0)
+	   (values methods "Methods: " :comment))
+          ((< n count)
+	   (values (nth n methods) nil :static))
+          (t (disassembly-line-n f (- n count))))))
+
+(defmethod (setf line-n) (new-value (f gf-inspector) n)
+  (let* ((count (method-count f))
+         (en n))
+    (cond ((< (decf n (standard-header-count f)) 0)
+           (call-next-method))
+          ((< (decf n) count)
+           (setf-line-n-out-of-range f en))
+          (t (set-disassembly-line-n f (- n count) new-value)))))
+
+#|
+(defmethod inspector-commands ((f gf-inspector))
+  (let* ((function (inspector-object f))
+         (method (selected-object (inspector-view f))))
+    (if (typep method 'method)
+      (nconc
+       (call-next-method)
+       `(("Remove method"
+         ,#'(lambda ()
+              (remove-method function method)
+              (resample-it)))))
+      (call-next-method))))
+|#
+
+;;;;;;;
+;;
+;; Structures
+;;
+(defmethod inspector-class ((s structure-object))
+  'usual-basics-first-inspector)
+
+(defun structure-slots (s)
+  (let ((slots (ccl::sd-slots (ccl::struct-def s))))
+    (if (symbolp (caar slots))
+      slots
+      (cdr slots))))
+
+(defmethod compute-line-count ((s structure-object))
+  (length (structure-slots s)))
+
+(defmethod line-n ((s structure-object) n)
+  (let ((slot (nth n (structure-slots s))))
+    (if slot
+      (values (uvref s (ccl::ssd-offset slot)) (ccl::ssd-name slot) :colon)
+      (line-n-out-of-range s n))))
+
+(defmethod (setf line-n) (new-value (s structure-object) n)
+  (let ((slot (nth n (structure-slots s))))
+    (if slot
+      (setf (uvref s (ccl::ssd-offset slot)) new-value)
+      (setf-line-n-out-of-range s n))))
+
+
+(defclass basic-stream-inspector (uvector-inspector) ())
+
+(defmethod inspector-class ((bs ccl::basic-stream)) 'basic-stream-inspector)
+  
+;;;;;;;
+;;
+;; packages
+;;
+(defclass package-inspector (uvector-inspector) ())
+
+(defmethod inspector-class ((p package)) 'package-inspector)
+
+(defmethod compute-line-count ((i package-inspector))
+  (+ 2 (call-next-method)))
+
+(defmethod line-n ((i package-inspector) n)
+  (cond ((eql n 0) (values (ccl::%pkgtab-count (ccl::pkg.itab (inspector-object i)))
+                           "Internal Symbols: " :static))
+        ((eql n 1) (values (ccl::%pkgtab-count (ccl::pkg.etab (inspector-object i)))
+                           "External Symbols: " :static))
+        (t (call-next-method i (- n 2)))))
+
+(defmethod (setf line-n) (new-value (i package-inspector) n)
+  (if (< n 2)
+    (setf-line-n-out-of-range i n)
+    (call-next-method new-value i (- n 2))))
+
+(defmethod inspector-commands ((i package-inspector))
+  `(("Inspect all packages" ,#'(lambda () (inspect (list-all-packages))))
+    (,(format nil "(setq *package* '~a" (inspector-object i))
+     ,#'(lambda () (setq *package* (inspector-object i))))))
+
+;;;;;;;
+;;
+;; Records
+;;
+(defclass record-inspector (object-first-inspector)
+  ((record-type :accessor record-type)
+   (field-names :accessor field-names)
+   (unlock :initform nil :accessor unlock)))
+
+(defmethod inspector-class ((o macptr))
+  'record-inspector)
+
+
+;;; Still needs work.
+;;; Lots of work.
+(defclass thread-inspector (uvector-inspector) ())
+
+(defmethod inspector-class ((thread ccl::lisp-thread))
+  'thread-inspector)
+
+(defmethod compute-line-count :before ((i thread-inspector))
+)
+
+(defmethod line-n ((thread thread-inspector) n)
+  (declare (ignorable n))
+  (call-next-method)
+)
+
+#|
+(defmethod line-n-inspector ((i thread-inspector) n value label type)
+  (declare (ignore n type))
+  (or (and value
+           (macptrp value)
+           (not (%null-ptr-p value)))
+      (call-next-method)))
+|#
+
+
+(defmethod line-n-inspector (i n value label type)
+  (declare (ignore i n label type))
+  (make-inspector value))
+
+(defmethod line-n-inspector ((i usual-inspector) n value label type)
+  (let ((object (inspector-object i)))
+    (if (typep object 'usual-inspector)
+      (make-inspector value)
+      (line-n-inspector (inspector-object i) n value label type))))
+
+
+
+
+
+;;;;;;;
+;;
+;; an ERROR-FRAME stores the stack addresses that the backtrace window displays
+;;
+
+;; set to list of function you don't want to see
+;; Functions can be symbols, nil for kernel, or #'functions
+(defparameter *backtrace-internal-functions*  
+  (list :kernel))
+
+(defvar *backtrace-hide-internal-functions-p* t)
+
+(defclass error-frame ()
+  ((addresses :accessor addresses)
+   (restart-info :accessor restart-info)
+   (stack-start :initarg :stack-start  :reader stack-start)
+   (stack-end :initarg :stack-end :reader stack-end)
+   (tcr :initarg :tcr :initform (ccl::%current-tcr) :reader tcr)
+   (context :initarg :context :reader context)
+   (frame-count :accessor frame-count)
+   (ignored-functions :accessor ignored-functions
+                      :initform (and *backtrace-hide-internal-functions-p*
+                                     *backtrace-internal-functions*))
+   (break-condition :accessor break-condition
+                    :initarg :break-condition)
+   (unavailable-value-marker :initform (cons nil nil)
+                             :accessor unavailable-value-marker)))
+  
+
+
+(defmethod initialize-instance ((f error-frame) &key)
+  (call-next-method)
+  (initialize-addresses f))
+
+(defmethod initialize-addresses ((f error-frame))
+  (let* ((addresses (coerce (ccl::%stack-frames-in-context (context f)) 'vector)))
+      (setf (frame-count f) (length addresses)
+            (addresses f) addresses)))
+
+(defmethod compute-frame-info ((f error-frame) n)
+  (let* ((frame (svref (addresses f) n))
+         (context (context f))
+         (marker (unavailable-value-marker f)))
+    
+    (multiple-value-bind (lfun pc) (ccl::cfp-lfun frame)
+      (multiple-value-bind (args locals) (ccl::arguments-and-locals context frame lfun pc marker)
+        (list (ccl::arglist-from-map lfun) args locals)))))
+
+(defun print-error-frame-limits (f stream)
+  (format stream "#x~x - #x~x" (stack-start f) (stack-end f)))
+
+(defmethod print-object ((f error-frame) stream)
+  (print-unreadable-object (f stream :type 'frame-ptr)
+    (print-error-frame-limits f stream)))
+
+
+
+;;;;;;;
+;;
+;; The inspector for error-frame objects
+;;
+
+
+
+;;; The "vsp-range" and "tsp-range" slots have to do with
+;;; recognizing/validating stack-allocated objects
+(defclass stack-inspector (inspector)
+  ((vsp-range :accessor vsp-range :initarg :vsp-range)
+   (tsp-range :accessor tsp-range :initarg :tsp-range)
+   (csp-range :accessor csp-range :initarg :csp-range)))
+
+
+
+                           
+(defmethod initialize-instance ((i stack-inspector) &rest initargs &key context)
+  (declare (dynamic-extent initargs))
+  (let* ((start (ccl::child-frame (ccl::parent-frame (ccl::bt.youngest context) context) context))
+         (end (ccl::child-frame (ccl::parent-frame (ccl::bt.oldest context) context) context))
+         (tcr (ccl::bt.tcr context)))
+    (apply #'call-next-method
+           i
+           :object 
+           (make-instance 'error-frame
+             :stack-start start
+             :stack-end end
+             :tcr tcr
+             :context context
+             :break-condition (ccl::bt.break-condition context))
+           :tsp-range (make-tsp-stack-range tcr context)
+           :vsp-range (make-vsp-stack-range tcr context)
+           :csp-range (make-csp-stack-range tcr context)
+           initargs)))
+
+(defmethod print-object ((i stack-inspector) stream)
+  (print-unreadable-object (i stream :type 'stack-inspector)
+    (print-error-frame-limits (inspector-object i) stream)))
+
+(defmethod addresses ((f stack-inspector))
+  (addresses (inspector-object f)))
+
+(defmethod compute-line-count ((f stack-inspector))
+  (frame-count (inspector-object f)))
+
+(defmethod line-n ((f stack-inspector) n)
+  (let* ((frame (svref (addresses (inspector-object f)) n)))
+    (ccl::cfp-lfun frame)))
+
+
+
+ 
+
+
+;;; inspecting a single stack frame
+;;; The inspector-object is expected to be an error-frame
+(defclass stack-frame-inspector (inspector)
+  ((frame-number :initarg :frame-number :initform nil :reader frame-number)
+   (frame-info :initform nil :accessor frame-info)))
+
+
+(defmethod initialize-instance ((i stack-frame-inspector) &rest initargs &key
+                                object frame-number)
+  (declare (dynamic-extent initargs))
+  (setq object (require-type object 'error-frame))
+  (apply #'call-next-method i 
+         :object object
+         initargs)
+  (setf (frame-number i) frame-number))
+
+    
+
+(defmethod compute-line-count ((i stack-frame-inspector))
+  (let ((frame-number (frame-number i)))
+    (if (null frame-number)
+      0
+      (let* ((error-frame (inspector-object i))
+             (frame-info (or (frame-info i)
+                             (setf (frame-info i) (compute-frame-info error-frame frame-number)))))
+        (destructuring-bind (args locals) (cdr frame-info)
+          (+ 1 (length args) 1 (length locals)))))))
+
+(defmethod line-n ((i stack-frame-inspector) n)
+  (unless (< -1 n (inspector-line-count i))
+    (line-n-out-of-range i n))
+  (destructuring-bind (arglist args locals) (frame-info i)
+    (if (zerop n)
+      (values arglist nil :static)
+      (let* ((nargs (length args)))
+        (decf n)
+        (if (< n nargs)
+          (cons :arg (nth n args))
+          (progn
+            (decf n nargs)
+            (if (zerop n)
+              nil
+              (cons :local (nth (1- n) locals)))))))))
+
+(defmethod (setf line-n) (value (i stack-frame-inspector) n)
+  (declare (ignorable value n))
+  (error "not yet!"))
+
+        
+
+
+
+(defmethod prin1-value ((i stack-frame-inspector) stream value &optional label type)
+  (declare (ignore label type))
+  (when value
+    (if (or (atom value) (not (typep (car value) 'keyword)))
+      (prin1 value stream)
+      (progn
+        (if (eq (car value) :arg)
+          (format stream "   ")
+          (format stream "  "))
+        (when (cdr value)
+          (destructuring-bind (label . val) (cdr value)
+            (format stream "~a: " label)
+            (if (eq val *unbound-marker*)
+              (format stream "??")
+              (prin1 val stream))))))))
+
+(defmethod (setf frame-number) (frame-number (i stack-frame-inspector))
+  (let ((max (1- (frame-count (inspector-object i)))))
+    (unless (or (null frame-number)
+                (and (<= 0 frame-number max)))
+      (setq frame-number (require-type frame-number `(or null (integer 0 ,max))))))
+  (unless (eql frame-number (frame-number i))
+    (setf (slot-value i 'frame-number) frame-number)
+    (setf (inspector-line-count i) nil)
+    frame-number))
+
+
+;;; Each of these stack ranges defines the entire range of (control/value/temp)
+;;; addresses; they can be used to addresses of stack-allocated objects
+;;; for printing.
+(defun make-tsp-stack-range (tcr bt-info)
+  (list (cons (ccl::%catch-tsp (ccl::bt.top-catch bt-info))
+              (ccl::%fixnum-ref (ccl::%fixnum-ref tcr target::tcr.ts-area)
+                                target::area.high))))
+
+#+ppc-target
+(defun make-vsp-stack-range (tcr bt-info)
+  (list (cons (ccl::%fixnum-ref
+               (ccl::%svref (ccl::bt.top-catch bt-info) target::catch-frame.csp-cell)
+               target::lisp-frame.savevsp)
+              (ccl::%fixnum-ref (ccl::%fixnum-ref tcr target::tcr.vs-area)
+                                target::area.high))))
+#+x8632-target
+(defun make-vsp-stack-range (tcr bt-info)
+  (list (cons (ccl::%svref (ccl::bt.top-catch bt-info) target::catch-frame.esp-cell)
+              (ccl::%fixnum-ref (ccl::%fixnum-ref tcr target::tcr.vs-area)
+                                target::area.high))))
+
+#+x8664-target
+(defun make-vsp-stack-range (tcr bt-info)
+  (list (cons (ccl::%svref (ccl::bt.top-catch bt-info) target::catch-frame.rsp-cell)
+              (ccl::%fixnum-ref (ccl::%fixnum-ref tcr target::tcr.vs-area)
+                                target::area.high))))
+
+#+ppc-target
+(defun make-csp-stack-range (tcr bt-info)
+  (list (cons (ccl::%svref (ccl::bt.top-catch bt-info) target::catch-frame.csp-cell)
+              (ccl::%fixnum-ref (ccl::%fixnum-ref tcr target::tcr.cs-area)
+                                target::area.high))))
+
+#+x8632-target
+(defun make-csp-stack-range (tcr bt-info)
+  (list (cons (ccl::%svref (ccl::bt.top-catch bt-info) target::catch-frame.foreign-sp-cell)
+              (ccl::%fixnum-ref (ccl::%fixnum-ref tcr target::tcr.cs-area)
+                                target::area.high))))
+
+#+x8664-target
+(defun make-csp-stack-range (tcr bt-info)
+  (list (cons (ccl::%svref (ccl::bt.top-catch bt-info) target::catch-frame.foreign-sp-cell)
+              (ccl::%fixnum-ref (ccl::%fixnum-ref tcr target::tcr.cs-area)
+                                target::area.high))))
+
+
+;;; Inspector
+
+
+(defvar *inspector-ui* ())
+(defvar *previous-inspector-ui* nil)
+
+(defclass inspector-ui ()
+    ((inspector :initarg :inspector :accessor inspector-ui-inspector)
+     (level :initarg :level :accessor inspector-ui-level)))
+
+(defclass inspector-tty-ui (inspector-ui)
+    ((origin :initarg :origin :initform 0 :accessor inspector-tty-ui-origin)
+     (pagesize :initarg :pagesize :initform 20 :accessor
+	       inspector-tty-ui-pagesize)))
+
+(defmethod ui-initialize ((ui inspector-tty-ui)))
+
+(defmethod ui-present ((ui inspector-tty-ui))
+  (let* ((inspector (inspector-ui-inspector ui)))
+    (with-errorfree-printing
+	(let* ((stream *debug-io*)
+	       (origin (inspector-tty-ui-origin ui))
+	       (pagesize (inspector-tty-ui-pagesize ui))
+	       (page-end (+ origin pagesize))
+	       (n (compute-line-count inspector))
+	       (end (min page-end n))
+	       (tag -1)
+	       (*print-pretty* (or *print-pretty* *describe-pretty*))
+	       (*print-length* 5)
+	       (*print-level* 5)
+	       (func #'(lambda (i index child &optional label-string value-string)
+			 (declare (ignore i))
+			 (when child (incf tag))
+			 (unless (< index origin)
+			   (format stream "~@[[~d]~]~8t" (and child tag))
+			   (format-line-for-tty stream label-string value-string)
+			   (terpri stream)))))
+	  (declare (dynamic-extent func))
+	  (map-lines inspector func 0 end)))
+    (values)))
+
+(ccl::define-toplevel-command
+    :tty-inspect i (n)
+    "inspect <n>th item"
+    (inspector-ui-inspect-nth *inspector-ui* n))
+
+(ccl::define-toplevel-command
+    :tty-inspect pop ()
+    "exit current inspector level"
+    (invoke-restart 'exit-inspector))
+
+(ccl::define-toplevel-command
+    :tty-inspect q ()
+    "exit inspector"
+  (invoke-restart 'end-inspect))
+
+(ccl::define-toplevel-command
+    :tty-inspect show ()
+    "re-show currently inspected object (the value of CCL:@)"
+    (ui-present *inspector-ui*))
+
+(defmethod inspector-ui-next-page ((ui inspector-tty-ui))
+  (let* ((nlines (compute-line-count (inspector-ui-inspector ui)))
+	 (origin (inspector-tty-ui-origin ui))
+	 (page-size (inspector-tty-ui-pagesize ui))
+	 (new-origin (+ origin page-size)))
+    (if (< new-origin nlines)
+      (setf (inspector-tty-ui-origin ui) new-origin))
+    (ui-present ui)))
+    
+(ccl::define-toplevel-command
+    :tty-inspect next ()
+    "show next page of object data"
+    (inspector-ui-next-page *inspector-ui*))
+
+(defmethod inspector-ui-prev-page ((ui inspector-tty-ui))
+  (let* ((origin (inspector-tty-ui-origin ui))
+	 (page-size (inspector-tty-ui-pagesize ui))
+	 (new-origin (max 0 (- origin page-size))))
+    (setf (inspector-tty-ui-origin ui) new-origin)
+    (ui-present ui)))
+
+(ccl::define-toplevel-command
+    :tty-inspect prev ()
+    "show previous page of object data"
+    (inspector-ui-prev-page *inspector-ui*))
+
+(ccl::define-toplevel-command
+    :tty-inspect home ()
+    "show first page of object data"
+    (progn
+      (setf (inspector-tty-ui-origin *inspector-ui*) 0)
+      (ui-present *inspector-ui*)))
+
+(ccl::define-toplevel-command
+    :tty-inspect s (n v)
+    "set the <n>th line of object data to value <v>"
+    (let* ((ui *inspector-ui*))
+      (setf (line-n (inspector-ui-inspector ui) n) v)
+      (ui-present ui)))
+
+
+(defmethod ui-interact ((ui inspector-tty-ui))
+  (let* ((level (inspector-ui-level ui))
+         (ccl::*default-integer-command* `(:i 0 ,(1- (compute-line-count (inspector-ui-inspector ui))))))
+    (declare (special ccl::*default-integer-command*))
+    (restart-case
+        (ccl:with-terminal-input
+          (ccl::with-toplevel-commands :tty-inspect
+            (ccl::read-loop
+             :prompt-function #'(lambda (stream)
+                                  (if (eql level 0)
+                                    (format stream "~&Inspect> ")
+                                    (format stream "~&Inspect ~d> " level))))))
+      (exit-inspector ()
+        (if *previous-inspector-ui*
+          (ui-present *previous-inspector-ui*)
+          (terpri *debug-io*))))))
+
+(defmethod inspector-ui-inspect-nth ((ui inspector-tty-ui) n)
+  (let* ((inspector (inspector-ui-inspector ui))
+	 (new-inspector (block nil
+			  (let* ((tag -1)
+				 (func #'(lambda (i index child &rest strings)
+					   (declare (ignore i index strings))
+					   (when (and child (eql (incf tag) n)) (return child)))))
+			    (declare (dynamic-extent func))
+			    (map-lines inspector func))))
+	 (ccl::@ (inspector-object new-inspector)))
+    (inspector-ui-inspect
+     (make-instance 'inspector-tty-ui
+       :level (1+ (inspector-ui-level ui))
+       :inspector new-inspector))))
+
+(defparameter *default-inspector-ui-class-name* 'inspector-tty-ui)
+
+(defmethod inspector-ui-inspect ((ui inspector-ui))
+  (let* ((*previous-inspector-ui* *inspector-ui*)
+         (*inspector-ui* ui))
+    (ui-initialize ui)
+    (ui-present ui)
+    (ui-interact ui)
+    (values)))
+
+(defun tty-inspect (thing)
+  (inspector-ui-inspect (make-instance *default-inspector-ui-class-name*
+                                       :inspector (make-inspector thing)
+					 :level 0)))
+
+(defparameter *default-inspector-ui-creation-function* 'tty-inspect)
+       
+
+(defun inspect (thing)
+  (let* ((ccl::@ thing))
+    (restart-case (funcall *default-inspector-ui-creation-function* thing)
+      (end-inspect () thing))))
Index: /branches/new-random/lib/distrib-inits.lisp
===================================================================
--- /branches/new-random/lib/distrib-inits.lisp	(revision 13309)
+++ /branches/new-random/lib/distrib-inits.lisp	(revision 13309)
@@ -0,0 +1,29 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; distrib-inits.lisp
+
+; Things that are in the development environment that need to be
+; added to the distribution environment.
+
+; This needs to be compiled after everything is loaded.
+
+(in-package "CCL")
+
+; *def-accessor-types* is used by the inspector to name slots in uvectors
+(dolist (cell '#.*def-accessor-types*)
+  (add-accessor-types (list (car cell)) (cdr cell)))
Index: /branches/new-random/lib/dumplisp.lisp
===================================================================
--- /branches/new-random/lib/dumplisp.lisp	(revision 13309)
+++ /branches/new-random/lib/dumplisp.lisp	(revision 13309)
@@ -0,0 +1,329 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; Dumplisp.lisp
+
+(in-package "CCL")
+
+(defvar *save-exit-functions* nil 
+  "List of (0-arg)functions to call before saving memory image")
+
+(defvar *restore-lisp-functions* nil
+  "List of (0-arg)functions to call after restoring saved image")
+
+
+(declaim (special *lisp-system-pointer-functions*)) ; defined in l1-init.
+
+(defun kill-lisp-pointers ()
+  (setq * nil ** nil *** nil + nil ++ nil +++ nil - nil
+        / nil // nil /// nil
+         @ nil)
+  (clear-open-file-streams)
+  (setf (*%saved-method-var%*) nil)
+  (setq *%periodic-tasks%* nil)
+  (setq *event-dispatch-task* nil)
+  (setq *interactive-abort-process* nil)
+  )
+
+(defun clear-ioblock-streams ()
+  (%map-areas (lambda (o)
+                  (if (typep o 'basic-stream)
+                    (let ((s (basic-stream.state o)))
+                      (when (and (typep s 'ioblock)
+                                 (ioblock-device s)
+                                 (>= (ioblock-device s) 0))
+                        (setf (basic-stream.state o) nil)))
+                    ;; Have to be careful with use of TYPEP here (and
+                    ;; in the little bit of Lisp code that runs before
+                    ;; the image is saved.)  We may have just done
+                    ;; things to forget about (per-session) foreign
+                    ;; class addresses, and calling TYPEP on a pointer
+                    ;; to such a class might cause us to remember
+                    ;; those per-session addresses and confuse the
+                    ;; startup code.
+                    (if (and (eql (typecode o) target::subtag-instance)
+                             (typep o 'buffered-stream-mixin)
+                             (slot-boundp o 'ioblock))
+                      (let ((s (slot-value o 'ioblock)))
+                        (when (and (typep s 'ioblock)
+                                   (ioblock-device s)
+                                   (>= (ioblock-device s) 0))
+                          (setf (slot-value o 'ioblock) nil))))))))
+
+(defun save-application (filename
+                         &rest rest
+                         &key toplevel-function
+			 init-file
+                         error-handler application-class
+			 clear-clos-caches
+                         (purify t)
+                         impurify
+			 (mode #o644)
+			 prepend-kernel
+			 #+windows-target (application-type :console))
+  (declare (ignore toplevel-function error-handler application-class
+                   clear-clos-caches init-file impurify))
+  #+windows-target (check-type application-type (member :console :gui))
+  (unless (probe-file (make-pathname :defaults nil
+                                     :directory (pathname-directory (translate-logical-pathname filename))))
+    (error "Directory containing ~s does not exist." filename))
+  (let* ((kind (%unix-file-kind (native-translated-namestring filename))))
+    (when (and kind (not (eq kind :file )))
+      (error "~S is not a regular file." filename)))
+  (let* ((watched (watch)))
+    (when watched
+      (cerror "Un-watch them." "There are watched objects.")
+      (mapc #'unwatch watched)))
+  (let* ((ip *initial-process*)
+	 (cp *current-process*))
+    (when (process-verify-quit ip)
+      (let* ((fd (open-dumplisp-file filename
+                                     :mode mode
+                                     :prepend-kernel prepend-kernel
+                                     #+windows-target  #+windows-target 
+                                     :application-type application-type)))
+        (process-interrupt ip
+                           #'(lambda ()
+                               (process-exit-application
+                                *current-process*
+                                #'(lambda ()
+                                    (apply #'%save-application-internal
+                                           fd
+                                           :purify purify
+                                           rest))))))
+      (unless (eq cp ip)
+	(process-kill cp)))))
+
+(defun %save-application-internal (fd &key
+                                      toplevel-function ;???? 
+                                      error-handler ; meaningless unless application-class or *application* not lisp-development..
+                                      application-class
+                                      mode
+                                      (purify t)
+                                      (impurify nil)
+                                      (init-file nil init-file-p)
+                                      (clear-clos-caches t)
+                                      prepend-kernel
+                                      #+windows-target application-type)
+  (declare (ignore mode prepend-kernel #+windows-target application-type))
+  (when (and application-class (neq  (class-of *application*)
+                                     (if (symbolp application-class)
+                                       (find-class application-class)
+                                       application-class)))
+    (setq *application* (make-instance application-class)))
+  (if (not toplevel-function)
+    (setq toplevel-function 
+          #'(lambda ()
+              (toplevel-function *application*
+				 (if init-file-p
+				   init-file
+				   (application-init-file *application*)))))
+    (let* ((user-toplevel-function (coerce-to-function toplevel-function)))
+      (setq toplevel-function
+            (lambda ()
+              (process-run-function "toplevel" (lambda ()
+                                                 (funcall user-toplevel-function)
+                                                 (quit)))
+              (%set-toplevel #'housekeeping-loop)
+              (toplevel)))))
+  (when error-handler
+    (make-application-error-handler *application* error-handler))
+  
+  (if clear-clos-caches (clear-clos-caches))
+  (save-image #'(lambda () (%save-application fd
+                                              (logior (if impurify 2 0)
+                                                      (if purify 1 0))))
+              toplevel-function))
+
+(defun save-image (save-function toplevel-function)
+  (let ((toplevel #'(lambda () (#_exit -1))))
+      (%set-toplevel #'(lambda ()
+                         (setf (interrupt-level) -1)
+                         (%set-toplevel toplevel)       ; in case *save-exit-functions* error
+                         (dolist (f *save-exit-functions*)
+                           (funcall f))
+                         (kill-lisp-pointers)
+                         (clear-ioblock-streams)
+                         (with-deferred-gc
+                             (let* ((pop *termination-population*))
+                               (with-lock-grabbed (*termination-population-lock*)
+                                 (setf (population.data pop) nil
+                                       (population.termination-list pop) nil))))
+                         (%set-toplevel
+                          #'(lambda ()
+                              (%set-toplevel #'(lambda ()
+                                                 (setf (interrupt-level) 0)
+                                                 (funcall toplevel-function)))
+                              (restore-lisp-pointers)))   ; do startup stuff
+                         (funcall save-function)))
+      (toplevel)))
+
+;;; If file in-fd contains an embedded lisp image, return the file position
+;;; of the start of that image; otherwise, return the file's length.
+(defun skip-embedded-image (in-fd)
+  (let* ((len (fd-lseek in-fd 0 #$SEEK_END)))
+    (if (< len 0)
+      (%errno-disp len)
+      (%stack-block ((trailer 16))
+	(let* ((trailer-pos (fd-lseek in-fd -16 #$SEEK_CUR)))
+	  (if (< trailer-pos 0)
+	    len
+	    (if (not (= 16 (the fixnum (fd-read in-fd trailer 16))))
+	      len
+	      (if (not (dotimes (i 12 t)
+			 (unless (eql (char-code (schar "OpenMCLImage" i))
+				      (%get-unsigned-byte trailer i))
+			   (return nil))))
+		len
+		(let* ((header-pos (fd-lseek in-fd
+					     (%get-signed-long
+					      trailer
+					      12)
+					     #$SEEK_CUR)))
+		  (if (< header-pos 0)
+		    len
+		    header-pos))))))))))
+		  
+;;; Note that Windows executable files are in what they call "PE"
+;;; (= "Portable Executable") format, not to be confused with the "PEF"
+;;; (= "PowerPC Executable Format" or "Preferred Executable Format")
+;;; executable format that Apple used on Classic MacOS.
+(defun %prepend-file (out-fd in-fd len #+windows-target application-type)
+  (declare (fixnum out-fd in-fd len))
+  (fd-lseek in-fd 0 #$SEEK_SET)
+  (let* ((bufsize (ash 1 15))
+         #+windows-target (first-buf t))
+    (%stack-block ((buf bufsize))
+      (loop
+	  (when (zerop len) (return))
+	  (let* ((nread (fd-read in-fd buf (min len bufsize))))
+	    (declare (fixnum nread))
+	    (if (< nread 0)
+	      (%errno-disp nread))
+            #+windows-target
+            (when (shiftf first-buf nil)
+              (let* ((application-byte (ecase application-type
+                                         (:console #$IMAGE_SUBSYSTEM_WINDOWS_CUI)
+                                         (:gui #$IMAGE_SUBSYSTEM_WINDOWS_GUI)))
+                     (offset (%get-long buf (get-field-offset #>IMAGE_DOS_HEADER.e_lfanew))))
+                (assert (< offset bufsize) () "PE header not within first ~D bytes" bufsize)
+                (assert (= (%get-byte buf (+ offset 0)) (char-code #\P)) ()
+                        "File does not appear to be a PE file")
+                (assert (= (%get-byte buf (+ offset 1)) (char-code #\E)) ()
+                        "File does not appear to be a PE file")
+                (assert (= (%get-byte buf (+ offset 2)) 0) ()
+                        "File does not appear to be a PE file")
+                (assert (= (%get-byte buf (+ offset 3)) 0) ()
+                        "File does not appear to be a PE file")
+                ;; File is a PE file -- Windows subsystem byte goes at offset 68 in the
+                ;;  "optional header" which appears right after the standard header (20 bytes)
+                ;;  and the PE cookie (4 bytes)
+                (setf (%get-byte buf (+ offset 4 (record-length #>IMAGE_FILE_HEADER) (get-field-offset #>IMAGE_OPTIONAL_HEADER.Subsystem) )) application-byte)))
+            (let* ((nwritten (fd-write out-fd buf nread)))
+	      (declare (fixnum nwritten))
+	      (unless (= nwritten nread)
+		(error "I/O error writing to fd ~d" out-fd)))
+	    (decf len nread))))))
+
+
+
+(defun kernel-path ()
+  (let* ((p (%null-ptr)))
+    (declare (dynamic-extent p))
+    (%get-kernel-global-ptr 'kernel-path p)
+    (if (%null-ptr-p p)
+      (%realpath (car *command-line-argument-list*))
+      (let* ((string (%get-utf-8-cstring p)))
+        #+windows-target (nbackslash-to-forward-slash string)
+        #+darwin-target (precompose-simple-string string)
+        #-(or windows-target darwin-target) string))))
+
+
+(defun open-dumplisp-file (path &key (mode #o666) prepend-kernel
+                           #+windows-target application-type)
+  (let* ((prepend-path (if prepend-kernel
+                         (if (eq prepend-kernel t)
+                           (kernel-path)
+                           (native-translated-namestring
+                          (pathname prepend-kernel)))))
+         (prepend-fd (if prepend-path (fd-open prepend-path #$O_RDONLY)))
+	 (prepend-len (if prepend-kernel
+                        (if (and prepend-fd (>= prepend-fd 0))
+                          (skip-embedded-image prepend-fd)
+                          (signal-file-error prepend-fd prepend-path))))
+	 (filename (native-translated-namestring path)))
+    (when (probe-file filename)
+      (%delete-file filename))
+    (when prepend-fd
+      ;; Copy the execute mode bits from the prepended "kernel".
+      (let ((prepend-fd-mode (nth-value 1 (%fstat prepend-fd))))
+	(setq mode (logior (logand prepend-fd-mode #o111) mode))))
+    (let* ((image-fd (fd-open filename (logior #$O_WRONLY #$O_CREAT) mode)))
+      (unless (>= image-fd 0) (signal-file-error image-fd filename))
+      (when prepend-fd
+	(%prepend-file image-fd prepend-fd prepend-len #+windows-target application-type))
+      (fd-chmod image-fd mode)
+      image-fd)))
+
+
+(defun %save-application (fd &optional (flags 1))
+  (let* ((err (%%save-application flags fd)))
+    (unless (eql err 0)
+      (%err-disp err))))
+  
+
+(defun restore-lisp-pointers ()
+  (setq *interactive-streams-initialized* nil)
+  (setq *heap-ivectors* nil)
+  (setq *batch-flag* (not (eql (%get-kernel-global 'batch-flag) 0)))
+  (%revive-system-locks)
+  (refresh-external-entrypoints)
+  (restore-pascal-functions)
+  (initialize-interactive-streams)
+  (let ((system-ptr-fns (reverse *lisp-system-pointer-functions*))
+        (restore-lisp-fns *restore-lisp-functions*)
+        (user-pointer-fns *lisp-user-pointer-functions*)
+        (lisp-startup-fns *lisp-startup-functions*))
+    (unwind-protect
+      (with-simple-restart (abort "Abort (possibly crucial) startup functions.")
+        (let ((call-with-restart
+               #'(lambda (f)
+                   (with-simple-restart 
+                     (continue "Skip (possibly crucial) startup function ~s."
+                               (if (symbolp f) f (function-name f)))
+                     (funcall f)))))
+          (dolist (f system-ptr-fns) (funcall call-with-restart f))
+          (dolist (f restore-lisp-fns) (funcall call-with-restart f))
+          (dolist (f (reverse user-pointer-fns)) (funcall call-with-restart f))
+          (dolist (f (reverse lisp-startup-fns)) (funcall call-with-restart f))))
+      (setf (interrupt-level) 0)))
+  nil)
+
+
+(defun restore-pascal-functions ()
+  (reset-callback-storage)
+  (when (simple-vector-p %pascal-functions%)
+    (dotimes (i (length %pascal-functions%))
+      (let ((pfe (%svref %pascal-functions% i)))
+        (when (vectorp pfe)
+          (let* ((name (pfe.sym pfe))
+		 (descriptor (pfe.routine-descriptor pfe)))
+	    (%revive-macptr descriptor)
+	    (%setf-macptr descriptor (make-callback-trampoline i (pfe.proc-info pfe)))
+            (when name
+              (set name descriptor))))))))
+
Index: /branches/new-random/lib/edit-callers.lisp
===================================================================
--- /branches/new-random/lib/edit-callers.lisp	(revision 13309)
+++ /branches/new-random/lib/edit-callers.lisp	(revision 13309)
@@ -0,0 +1,243 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; edit-callers.lisp
+
+(in-package "CCL")
+
+(defun global-function-p (random &optional name)
+  (let* ((thing random)
+         (name (or name (ignore-errors (function-name thing)))))
+    (and name
+         (or (not (or (symbolp name) (setf-function-name-p name))) ; maybe its (setf baz)
+             (let ((fn  (fboundp name)))
+               (and fn
+                    (progn
+		; maybe this is enough for both cases?
+                      (or (eq thing fn)
+                          (and (symbolp name)(eq thing (macro-function name))))))))
+         name)))
+
+(defvar *function-parent-table* nil)
+(defvar *function-parent-pool* (%cons-pool))
+
+(defun copying-gc-p () ; if nz copying gc is on
+  nil)
+
+(defun lfun-closure-p (lfun)
+  (logbitp $lfbits-trampoline-bit (lfun-bits lfun)))
+
+; make a macro ?
+(defun puthash-parent (im fun)
+  (when (functionp im) ; was (or (functionp im)(eq imtype $sym.fapply))
+    (if (global-function-p fun)
+      (setf (gethash im *function-parent-table*) fun)
+      (let ((ht (gethash im *function-parent-table*)))
+        (if (not ht)
+          (setf (gethash im *function-parent-table*) fun)
+          (unless (eq ht fun)
+            (if (consp ht)
+              (when (not (memq fun ht))(nconc ht (list fun)))
+              (if (not (global-function-p ht))
+                (setf (gethash im *function-parent-table*) (list ht fun))))))))))       
+
+
+(defun callers (function &aux cfun callers gccount retry)
+  ;(declare (special cfun function callers))
+  (declare (optimize (speed 3)(safety 0)))
+
+  (let ((*function-parent-table* nil))
+    (if (setf-function-name-p function)
+      (let ((nm (cadr function)))
+        (setq function  (or (%setf-method nm)
+                            (and (symbolp nm)
+                                 (setq nm (setf-function-name nm))
+                                 (fboundp nm)
+                                 nm)
+                            function))))
+    (if (and (symbolp function) (fboundp function))
+      (setq cfun (symbol-function function)))
+    (when (copying-gc-p) (setq gccount (full-gccount)))
+    (flet ((do-it (fun)
+             (when (and gccount (neq gccount (full-gccount)))
+               (throw 'losing :lost))
+             (when (possible-caller-function-p fun)
+               (let* ((nm (ignore-errors (lfun-name fun)))
+                      (globalp (if nm (global-function-p fun nm))))
+                 (flet ((do-imm (im)
+                          (when (and (or (eq function im)
+                                         (and cfun (eq cfun im)))
+                                     (neq im nm))                             
+                            (push fun callers)) 
+                          (when (functionp im) ; was (or (functionp im)(eq imtype $sym.fapply))
+                            (if globalp
+                              (setf (gethash im *function-parent-table*) fun)
+                              (let ((ht (gethash im *function-parent-table*)))
+                                (if (not ht)
+                                  (setf (gethash im *function-parent-table*) fun)
+                                  (unless (eq ht fun)
+                                    (if (consp ht)
+                                      (when (not (memq fun ht))(nconc ht (list fun)))
+                                      (if (not (global-function-p ht))
+                                        (setf (gethash im *function-parent-table*) 
+                                              (list ht fun)))))))))))
+                   (declare (dynamic-extent #'do-imm))                                
+                   (%map-lfimms fun #'do-imm ))))))
+      (declare (dynamic-extent #'do-it))
+      (unwind-protect
+           (progn
+             (let* ((pool *function-parent-pool*)
+                    (tbl (pool.data pool)))
+               (setf (pool.data pool) nil
+                     *function-parent-table*
+                     (if tbl
+                       (clrhash tbl)
+                       (make-hash-table :size 700 :test 'eq :weak :value))))
+             (loop
+               (cond ((eq :lost (catch 'losing      
+                                  (%map-lfuns #'do-it)))
+                      (when retry (error "Callers is losing"))
+                      (setq callers nil)
+                      (setq retry t))
+                     (t (return))))
+             (delete-if #'(lambda (thing)
+                            (or (functionp thing)
+                                (and (typep thing 'method)
+                                     (let ((gf (fboundp (method-name thing))))
+                                       (not (and (typep gf 'standard-generic-function)
+                                                 (memq thing (%gf-methods gf))))))))
+                        (delete-duplicates (mapcar 'top-level-caller callers))))
+        (setf (pool.data *function-parent-pool*) *function-parent-table*
+              *function-parent-table* nil)))))
+
+
+(defun top-level-caller (function &optional the-list)
+  (or (global-function-p function)
+      (pascal-function-p function)
+      (let ((name (function-name function)))
+        (and name (function-encapsulated-p name) name))
+      (let ((caller function) next)
+        (loop
+          (setq next (gethash caller *function-parent-table*))
+          (if  next
+            (cond ((consp next)
+                   (when (null the-list)(push function the-list))
+                   (return
+                    (dolist (c next)
+                      (when (not (memq c the-list))
+                        (let ((res (top-level-caller c the-list)))
+                          (when (and res (not (functionp res)))
+                            (return res)))))))
+                  (t (let ((res (global-function-p next)))
+                       (when res (return res)))
+                     (when (null the-list)(push function the-list))
+                     (when (memq next the-list) (return))
+                     (push next the-list)
+                     (setq caller next)))
+            (return caller))))
+      function))
+
+(defun possible-caller-function-p (fun)
+  (let ((bits (lfun-bits fun)))
+    (declare (fixnum bits))
+    (not (or (and (logbitp $lfbits-cm-bit bits)
+                  (not (logbitp $lfbits-method-bit bits))) ; combined method
+             (and (logbitp $lfbits-trampoline-bit bits)
+                  (lfun-closure-p fun)
+                  (not (global-function-p fun))))))) ; closure (interp or compiled)
+
+  
+(defun caller-functions (function &aux cfun callers gccount retry)
+  "Returns a list of all functions (actual function objects, not names) that reference FUNCTION"
+  (declare (optimize (speed 3)(safety 0)(debug 0)))
+  (when (setf-function-name-p function)
+    (let ((nm (cadr function)))
+      (setq function  (or (%setf-method nm)
+                          (and (setq nm (setf-function-name nm))
+                               (fboundp nm)
+                               nm)
+                          function))))
+  (when (valid-function-name-p function)
+    (setq cfun (or (and (symbolp function) (macro-function function))
+                   (fboundp function))))
+  (when (copying-gc-p) (setq gccount (full-gccount)))
+  (flet ((do-it (fun)
+           (when (and gccount (neq gccount (full-gccount)))
+             (throw 'losing :lost))
+           (when (possible-caller-function-p fun)
+             (let* ((lfv (function-to-function-vector fun))
+                    (end (%i- (uvsize lfv) 1))
+                    (bits (%svref lfv end)))
+               ;; Don't count the function name slot as a reference.
+               (unless (logbitp $lfbits-noname-bit bits)
+                 (decf end))
+               ;; Don't count lfun-info  either
+               (when (logbitp $lfbits-info-bit bits)
+                 (decf end))
+               (loop for i from #+ppc-target 1 #+x86-target (%function-code-words fun) below end
+                     as im = (%svref lfv i)
+                     when (or (eq function im)
+                              (and cfun (eq cfun im)))
+                       do (return (pushnew (if (%method-function-p fun)
+                                             (%method-function-method fun)
+                                             fun)
+                                           callers)))))))
+    (declare (dynamic-extent #'do-it))
+    (loop while (eq :lost (catch 'losing      
+                            (%map-lfuns #'do-it)))
+          do (when retry (cerror "Try again" "Callers is losing"))
+          do (setq callers nil)
+          do (setq retry t))
+    callers))
+
+; in 3.x the function in pascal-functions calls the actual function
+(defun pascal-function-p (function)
+  (if (find function %pascal-functions%
+            :test #'eq
+            :key #'(lambda (elt)
+                     (if (consp elt)
+                       (let ((one (cdr elt)))
+                         (when (and (eq (function-name one)(function-name function))
+                                    (block blob
+                                      (%map-lfimms one #'(lambda (imm)
+                                                           (when (eq imm function)
+                                                             (return-from blob function))))))
+                           function))
+                       (if elt (aref elt 2)))))
+    (function-name function)))
+
+
+;;; Calls function f with args (imm) on each immediate in lfv.
+
+(defun %map-lfimms (function-object f)
+  (let* ((lfv (function-to-function-vector function-object))
+         (n (- (uvsize lfv) 2)))
+    (declare (fixnum n))
+    #+ppc-target
+    (dotimes (i n)
+      (funcall f (%svref lfv (%i+ 1 i))))
+    #+x86-target
+    (do* ((i (1- (the fixnum (%function-code-words function-object))) (1+ i)))
+         ((= i n))
+      (declare (fixnum i))
+      (funcall f (%svref lfv (%i+ 1 i))))
+    ))
+         
+    
+
+
+(provide :edit-callers)
Index: /branches/new-random/lib/encapsulate.lisp
===================================================================
--- /branches/new-random/lib/encapsulate.lisp	(revision 13309)
+++ /branches/new-random/lib/encapsulate.lisp	(revision 13309)
@@ -0,0 +1,891 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defvar *loading-removes-encapsulation* nil
+  "If true, loading a new method definition from a file will remove any tracing and advice on the method")
+
+(defvar *trace-pfun-list* nil)
+(defvar *trace-enable* t)
+(defvar *trace-level* 0)
+(defparameter *trace-max-indent* 40)
+(defvar *trace-print-level* nil)
+(defvar *trace-print-length* nil)
+;(defparameter *trace-define-if-undefined* nil)
+(defparameter *trace-bar-frequency* nil)
+(defvar *trace-hook* nil)
+(defvar *untrace-hook* nil)
+(defvar *trace-print-hook* nil)
+
+;;;
+;;;  We support encapsulating three types of objects, i.e. modifying their definition
+;;;  without changing their identity:
+;;;    1. symbol - via the symbol-function slot
+;;;    2. method - via the %method-function slot
+;;;    3. standard-generic-function - via the %gf-dcode slot
+;;;
+;;; Encapsulation is effected by creating a new compiled function and storing it in the
+;;; slot above. The new function references a gensym fbound to the original definition
+;;; (except in the case of a gf, the gensym is fbound to a copy of the gf which in
+;;; turn contains the original dcode, since we can't invoke the dcode directly).
+;;; In addition, an ENCAPSULATION struct describing the encapsulation is created and
+;;; stored in the *encapsulation-table* with the new compiled function as the key.
+;;;
+;;; 
+
+(defparameter *encapsulation-table*
+  (make-hash-table :test #'eq :rehash-size 2 :size 2 :weak t))
+
+(defstruct (encapsulation)
+  symbol         ; the uninterned name containing original def
+  type           ; trace or advise
+  spec           ; the original function spec
+  advice-name    ; optional
+  advice-when    ; :before, :after, :around 
+  owner          ; where encapsulation is installed (can change)
+)
+
+(defun encapsulation-old-def (cap)
+  (fboundp (encapsulation-symbol cap)))
+
+(defun setf-function-spec-name (spec)
+  (if (setf-function-name-p spec)
+    (let ((name (%setf-method (cadr spec))))
+      (if (non-nil-symbol-p name)  ; this can be an anonymous function
+        name
+        (setf-function-name (cadr spec))))
+    spec))
+
+(defun trace-tab (direction &aux (n (min *trace-level* *trace-max-indent*)))
+  (fresh-line *trace-output*)
+  (dotimes (i (1- n))
+    (declare (fixnum i))
+    (write-char (if (and *trace-bar-frequency* 
+                         (eq 0 (mod i *trace-bar-frequency*)))
+                  #\| #\Space) *trace-output*))
+  (if (eq direction :in)
+    (format *trace-output* "~d> " (1- *trace-level*))
+    (format *trace-output* "<~d " (1- *trace-level*))))
+
+(defun trace-before  (&rest args)
+  (declare (dynamic-extent args))
+  (trace-tab :in)
+  (let* ((*print-level* *trace-print-level*)
+         (*print-length* *trace-print-length*)
+         (*print-readably* nil))
+    (format *trace-output* "Calling ~S ~%" args)
+    (force-output *trace-output*)))
+
+(defun trace-after (sym &rest args &aux (n (length args)))
+  (declare (dynamic-extent args))
+  (let* ((*print-level* *trace-print-level*)
+         (*print-length* *trace-print-length*)
+         (*print-readably* nil))
+    (if (eq n 1)
+      (progn
+        (trace-tab :out)
+        (format *trace-output* "~S returned ~S~%" sym (%car args)))
+      (progn
+        (trace-tab :out)
+        (format *trace-output* "~S returned ~S values :" sym n)
+        (dolist (val args)
+          (trace-tab :out)
+          (format *trace-output* "     ~S" val))))
+    (force-output *trace-output*)))
+
+(defun forget-encapsulations (name)
+  (when (%traced-p name)
+    (format t "~%... Untracing ~a" name) 
+    (%untrace-1 name))
+  (when (%advised-p name)
+    (format t "~%... Unadvising ~a" name) 
+    (%unadvise-1 name))
+  nil)
+
+(defun function-encapsulated-p (fn-or-method)
+  (get-encapsulation fn-or-method))
+
+(defun %encap-fboundp (thing)
+  (etypecase thing
+    (symbol (fboundp thing))
+    (method (%method-function thing))))
+  
+(defun %encap-binding (thing)
+  (require-type (etypecase thing
+                  (symbol (fboundp thing))
+                  (method (%method-function thing)))
+                'function))
+
+(defun get-encapsulation (spec)
+  (let* ((key (typecase spec
+                (symbol (let* ((def (fboundp spec)))
+                          (if (generic-function-p def)
+                            (%gf-dcode def)
+                            def)))
+                (method (%method-function spec))
+                (standard-generic-function (%gf-dcode spec))
+                (function spec)))
+         (cap (gethash key *encapsulation-table*)))
+    #+gz (assert (or (null cap)
+                     (let ((fn (%encap-binding (encapsulation-owner cap))))
+                       (eq (if (standard-generic-function-p fn) (%gf-dcode fn) fn) key))))
+    cap))
+
+(defun set-encapsulation-owner (fn owner)
+  (let ((cap (get-encapsulation fn)))
+    (when cap
+      (setf (encapsulation-owner cap) owner))))
+
+(defun put-encapsulation (fn cap)
+  (let* ((owner (encapsulation-owner cap))
+         (old-def (%encap-binding owner))
+         (newsym (encapsulation-symbol cap)))
+    (setf (gethash fn *encapsulation-table*) cap)
+    (set-encapsulation-owner old-def newsym)
+    (etypecase owner
+      (symbol
+       (cond ((standard-generic-function-p old-def)
+              (%fhave newsym (%copy-function old-def))
+              (setf (%gf-dcode old-def) fn))
+             (t
+              (%fhave newsym old-def)
+              (%fhave owner fn))))
+      (method
+       (%fhave newsym old-def)
+       (setf (%method-function owner) fn)
+       (remove-obsoleted-combined-methods owner)))))
+
+(defun remove-encapsulation (cap)
+  (let* ((owner (encapsulation-owner cap))
+         (cur-def (%encap-fboundp owner))
+         (old-def (encapsulation-old-def cap)))
+    (typecase owner
+      (symbol
+       (cond ((or (null cur-def)
+                  (not (eq cap (get-encapsulation cur-def))))
+              ;; rebound behind our back, oh well.
+              nil)
+             ((standard-generic-function-p cur-def)
+              (remhash (%gf-dcode cur-def) *encapsulation-table*)
+              (set-encapsulation-owner old-def owner)
+              (setf (%gf-dcode cur-def) (%gf-dcode old-def)))
+             (t
+              (remhash cur-def *encapsulation-table*)
+              (set-encapsulation-owner old-def owner)
+              (%fhave owner old-def))))
+      (method
+       (remhash cur-def *encapsulation-table*)
+       (set-encapsulation-owner old-def owner)
+       (setf (%method-function owner) old-def)
+       (remove-obsoleted-combined-methods owner)))))
+
+
+(defun encapsulate (owner newdef type trace-spec newsym &optional advice-name advice-when)
+  (let ((cap (make-encapsulation
+	      :owner owner
+	      :symbol newsym
+	      :type type
+	      :spec trace-spec
+	      :advice-name advice-name
+	      :advice-when advice-when)))
+    (put-encapsulation newdef cap)
+    cap))
+
+(defun find-unencapsulated-definition (fn)
+  (when fn
+    (loop for cap = (get-encapsulation fn) while cap
+      do (setq fn (encapsulation-old-def cap)))
+    fn))
+
+(defun set-unencapsulated-definition (cap newdef)
+  (loop for owner = (encapsulation-symbol cap)
+    do (setq cap (get-encapsulation owner)) while cap
+    finally (%fhave owner newdef)))
+
+(defun %encapsulation-thing (spec &optional define-if-not (error-p t))
+  ;; Returns either an fboundp symbol or a method, or nil.
+  (typecase spec
+    (symbol
+     ;; weed out macros and special-forms
+     (if (or (null spec) (special-operator-p spec) (macro-function spec))
+       (if error-p
+         (error "Cannot trace or advise ~a~S"
+                (cond ((null spec) "")
+                      ((special-operator-p spec) "special operator ")
+                      (t "macro "))
+                spec)
+         nil)
+       (if (or (fboundp spec)
+               (and define-if-not
+                    (progn
+                      (warn "~S was undefined" spec)
+                      (%fhave spec (%function 'trace-null-def))
+                      t)))
+         spec
+         (if error-p
+           (error "~S is undefined." spec)
+           nil))))
+    (method spec)
+    (cons
+     (case (car spec)
+       (:method 
+        (let ((gf (cadr spec))
+              (qualifiers (butlast (cddr spec)))
+              (specializers (car (last (cddr spec))))
+              method)
+          (setq specializers (require-type specializers 'list))
+          (prog ()
+            AGN
+            (cond ((setq method
+                         (find-method-by-names gf qualifiers specializers))
+                   (return method))
+                  (define-if-not
+                    (when (define-undefined-method spec gf qualifiers specializers)
+                      (go AGN)))
+                  (t (if error-p
+                       (error "Method ~s qualifiers ~s specializers ~s not found."
+                              gf qualifiers specializers)
+                       (return nil)))))))
+       (setf
+        (let ((name-or-fn (setf-function-spec-name spec)))
+          (cond ((symbolp name-or-fn) (%encapsulation-thing name-or-fn))
+                ((functionp name-or-fn) ; it's anonymous - give it a name
+                 (let ((newname (gensym)))
+                   (%fhave newname name-or-fn)
+                   (store-setf-method (cadr spec) newname)
+                   newname)))))))
+    (t (if error-p
+         (error "Invalid trace spec ~s" spec)
+         nil))))
+
+(defun trace-null-def (&rest ignore)
+  (declare (ignore ignore)))
+
+(defun define-undefined-method (spec gf qualifiers specializers)
+  (let (vars def)    
+    (flet ((blob (e)
+                 (let ((v (gensym)))
+                   (push v vars)
+                   (list v e))))
+      (declare (dynamic-extent #'blob))
+      (setq def
+            (let ((lambda-list (mapcar #' blob specializers)))
+              (eval
+               `(defmethod ,gf ,@qualifiers (,@lambda-list &rest ignore)
+                  (declare (ignore ignore ,@vars))))))
+      (when def (warn "~S was undefined" spec))
+      def)))
+
+(defun traceable-symbol-p (sym)
+  (and sym
+       (not (special-operator-p sym))
+       (not (macro-function sym))
+       (fboundp sym)))
+
+(defun %trace-package (pkg &rest args)
+  (declare (dynamic-extent args))
+  (do-present-symbols (sym pkg)
+    ;; Don't auto-trace imported symbols, because too often these are imported
+    ;; system functions...
+    (when (eq (symbol-package sym) pkg)
+      (when (traceable-symbol-p sym)
+        (apply #'trace-function sym args))
+      (when (or (%setf-method sym)
+                ;; Not really right.  Should construct the name if doesn't exist.
+                ;; But that would create a lot of garbage for little gain...
+                (let ((name (existing-setf-function-name sym)))
+                  (traceable-symbol-p name)))
+        (apply #'trace-function `(setf ,sym) args)))))
+
+(defun trace-print-body (print-form)
+  (when print-form
+    (if (and (consp print-form) (eq (car print-form) 'values))
+      `((mapcar #'(lambda (name object)
+                    (trace-tab :in)
+                    (format *trace-output* "~s = ~s" name object))
+         ',(cdr print-form)
+         (list ,@(cdr print-form))))
+      `((let ((objects (multiple-value-list ,print-form))
+              (i -1))
+          (if (and objects (not (cdr objects)))
+            (progn
+              (trace-tab :in)
+              (format *trace-output* "~s = ~s" ',print-form (car objects)))
+            (dolist (object objects)
+              (trace-tab :in)
+              (format *trace-output* "~s [~d] = ~s" ',print-form (incf i) object))))))))
+
+(defun trace-backtrace-body (test-form)
+  (when test-form
+    `((let ((test ,test-form))
+        (when test
+          (multiple-value-bind (detailed-p count)
+              (cond ((memq test '(:detailed :verbose :full))
+                     (values t nil))
+                    ((integerp test)
+                     (values nil test))
+                    ((and (consp test)
+                          (keywordp (car test))
+                          (consp (cdr test))
+                          (null (cddr test)))
+                     (values (memq (car test) '(:detailed :verbose :full))
+                             (and (integerp (cadr test)) (cadr test))))
+                    (t (values nil nil)))
+            (let ((*debug-io* *trace-output*))
+              (print-call-history :detailed-p detailed-p
+                                  :count (or count most-positive-fixnum))
+              (terpri *trace-output*))))))))
+
+(defun trace-inside-frame-p (name)
+  (if (packagep name)
+    (map-call-frames #'(lambda (p)
+                         (let* ((fn (cfp-lfun p))
+                                (fname (and fn (function-name fn)))
+                                (sym (typecase fname
+                                       (method (method-name fname))
+                                       (cons (and (setf-function-name-p fname) (cadr fname)))
+                                       (symbol fname)
+                                       (t nil))))
+                           (when (and sym (eq (symbol-package sym) name))
+                             (return-from trace-inside-frame-p t)))))
+    (let ((fn (%encap-binding name)))
+      (when fn
+        (map-call-frames #'(lambda (p)
+                             (when (eq (cfp-lfun p) fn)
+                               (return-from trace-inside-frame-p t))))))))
+
+(defun trace-package-spec (spec)
+  (when (or (stringp spec)
+            (packagep spec)
+            (and (consp spec) (eq (car spec) :package)))
+    (let ((pkg (if (consp spec)
+                 (destructuring-bind (pkg) (cdr spec) pkg)
+                 spec)))
+      (pkg-arg pkg))))
+
+(defun trace-function (spec &rest args &key before after methods
+                            (if t) (before-if t) (after-if t)
+                            print print-before print-after
+                            eval eval-before eval-after
+                            break break-before break-after
+                            backtrace backtrace-before backtrace-after
+                            inside
+                            define-if-not
+                            ;; Some synonyms, just to be nice
+                            (condition t) (if-before t) (if-after t) (wherein nil))
+
+  (declare (dynamic-extent args))
+  (let ((pkg (trace-package-spec spec)))
+    (when pkg
+      (return-from trace-function (apply #'%trace-package pkg args))))
+
+  ;; A little bit of dwim, after all this _is_ an interactive tool...
+  (unless (eq condition t)
+    (setq if (if (eq if t) condition `(and ,if ,condition))))
+  (unless (eq if-before t)
+    (setq before-if (if (eq before-if t) if-before `(and ,before-if ,if-before))))
+  (unless (eq if-after t)
+    (setq after-if (if (eq after-if t) if-after `(and ,after-if ,if-after))))
+  (when (and inside (trace-spec-p inside))
+    (setq inside (list inside)))
+  (when wherein
+    (setq inside (append inside (if (trace-spec-p wherein) (list wherein) wherein))))
+  (case break
+    (:before (setq break-before (or break-before t) break nil))
+    (:after (setq break-after (or break-after t) break nil)))
+  (case backtrace
+    (:before (setq backtrace-before (or backtrace-before t) backtrace nil))
+    (:after (setq backtrace-after (or backtrace-after t) backtrace nil)))
+  (case before
+    (:break (setq before :print break-before t))
+    (:backtrace (setq before :print backtrace-before t)))
+  (case after
+    (:break (setq after :print break-after t))
+    (:backtrace (setq after :print backtrace-after t)))
+
+  (when break
+    (setq break-before (if break-before
+                         `(and ,break ,break-before)
+                         break))
+    (setq break-after (if break-after
+                        `(and ,break ,break-after)
+                        break)))
+  (unless backtrace-before
+    (setq backtrace-before backtrace))
+  (when (and (consp backtrace-before) (keywordp (car backtrace-before)))
+    (setq backtrace-before `',backtrace-before))
+  (when (and (consp backtrace-after) (keywordp (car backtrace-after)))
+    (setq backtrace-after `',backtrace-after))
+
+  (when (and (null before) (null after))
+    (setq before :print)
+    (setq after :print))
+  (when (and (null before) backtrace-before)
+    (setq before :print))
+
+  (case before
+    ((:print :default) (setq before #'trace-before)))
+  (case after
+    ((:print :default) (setq after #'trace-after)))
+
+  (when (or (non-nil-symbol-p before) (functionp before))
+    (setq before `',before))
+  (when (or (non-nil-symbol-p after) (functionp after))
+    (setq after `',after))
+
+  (when inside
+    (let ((tests (loop for spec in inside
+                       as name = (or (trace-package-spec spec)
+                                     (%encapsulation-thing spec nil nil)
+                                     (error "Cannot trace inside ~s" spec))
+                       collect `(trace-inside-frame-p ',name))))
+      (setq if `(and ,if (or ,@tests)))))
+
+  (setq eval-before `(,@(trace-print-body print-before)
+                      ,@(trace-print-body print)
+                      ,@(and eval-before `(,eval-before))
+                      ,@(and eval `(,eval))
+                      ,@(and before `((apply ,before ',spec args)))
+                      ,@(trace-backtrace-body backtrace-before)
+                      ,@(and break-before `((when ,break-before
+                                              (force-output *trace-output*)
+                                              (break "~s trace entry: ~s" ',spec args))))))
+  (setq eval-after `(,@(trace-backtrace-body backtrace-after)
+                     ,@(and after `((apply ,after ',spec vals)))
+                     ,@(and eval `(,eval))
+                     ,@(and eval-after `(,eval-after))
+                     ,@(trace-print-body print)
+                     ,@(trace-print-body print-after)
+                     ,@(and break-after `((when ,break-after
+                                            (force-output *trace-output*)
+                                            (break "~s trace exit: ~s" ',spec vals))))))
+
+  (prog1
+      (block %trace-block
+        ;;
+        ;; see if we're a callback
+        ;;
+        (when (and (typep spec 'symbol)
+                   (boundp spec)
+                   (macptrp (symbol-value spec)))
+          (let ((len (length %pascal-functions%))
+                (sym-name (symbol-name spec)))
+            (declare (fixnum len))
+            (dotimes (i len)
+              (let ((pfe (%svref %pascal-functions% i)))
+                (when (and (vectorp pfe)
+                           (string= sym-name (symbol-name (pfe.sym pfe))))
+                  (when backtrace
+                    (if (null before)
+                      (setq before :print)))
+                  (setf (pfe.trace-p pfe)
+                        `(,@(if before `((:before . ,before)))
+                          ,@(if after `((:after . ,after)))
+                          ,@(if backtrace `((:backtrace . ,backtrace)))))
+                  (push spec *trace-pfun-list*)))))
+          (return-from %trace-block))
+        ;;
+        ;; now look for traceable methods.
+        ;; It's possible, but not likely, that we will be both
+        ;; a callback and a function or method, if so we trace both.
+        ;; This isn't possible.
+        ;; If we're neither, signal an error.
+        ;;
+        (let* ((trace-thing (%encapsulation-thing spec define-if-not)) def)
+          (%untrace-1 trace-thing)
+          (setq def (%encap-binding trace-thing))
+          (when (and methods (typep def 'standard-generic-function))
+            (dolist (m (%gf-methods def))
+              (apply #'trace-function m args)))
+          #+old
+          (when step               ; just check if has interpreted def
+            (if (typep def 'standard-generic-function)
+              (let ((methods (%gf-methods def)))
+                ; should we complain if no methods? naah
+                (dolist (m methods) ; stick :step-gf in advice-when slot
+                  (%trace m :step t)
+                  (let ((e (function-encapsulation m)))
+                    (when e (setf (encapsulation-advice-when e) :step-gf))))
+                ; we choose to believe that before and after are intended for the gf
+                (if  (or before after)
+                  (setq step nil)                
+                  (return-from %trace-block)))
+              #|(uncompile-for-stepping trace-thing nil t)|#))
+          (let* ((newsym (gensym "TRACE"))
+                 (method-p (typep trace-thing 'method))
+                 (newdef (trace-global-def 
+                          spec newsym if before-if eval-before after-if eval-after method-p)))
+            (when method-p
+              (copy-method-function-bits def newdef))
+            (encapsulate trace-thing newdef 'trace spec newsym))))
+    (when *trace-hook*
+      (apply *trace-hook* spec args))))
+
+
+(defun %traced-p (thing)
+  (let ((cap (get-encapsulation thing)))
+    (and cap (eq (encapsulation-type cap) 'trace))))
+
+(defmacro untrace (&rest syms)
+  "Remove tracing from the specified functions. With no args, untrace all
+   functions."
+  (if syms
+    `(%untrace-0 ',syms)
+    `(%untrace-all)))
+
+(defun %untrace-0 (syms)
+  (let (val x)
+    (dolist (symbol syms)
+      (setq x (%untrace symbol))
+      (when x (push x val)))
+    val))
+
+(defun %untrace-all ()
+  (dolist (pfun *trace-pfun-list*)
+    (%untrace pfun)
+    (when *untrace-hook*
+      (funcall *untrace-hook* pfun)))
+  (loop for cap being the hash-value of *encapsulation-table*
+    when (eq (encapsulation-type cap) 'trace)
+    collect (let ((spec (encapsulation-spec cap)))
+              (remove-encapsulation cap)
+              (when *untrace-hook*
+                (funcall *untrace-hook* spec))
+              spec)))
+
+(defun %untrace (sym &aux val)
+  (when (and (consp sym)(consp (car sym)))
+    (setq sym (car sym)))
+  (cond
+   ((and (typep sym 'symbol)
+         (boundp sym)
+         (macptrp (symbol-value sym)))
+    (%untrace-pfun sym))
+   (t 
+    (let* ((trace-thing (%encapsulation-thing sym))
+           (def (%encap-binding trace-thing)))
+      (when (typep def 'standard-generic-function)
+        (let ((methods (%gf-methods def)))
+          (dolist (m methods)
+            (let ((cap (get-encapsulation m)))
+              (when (and cap (eq (encapsulation-advice-when cap) :step-gf))
+                (remove-encapsulation cap)
+                (push m val))))))
+      ; gf could have first been traced :step, and then just plain traced
+      ; maybe the latter trace should undo the stepping??
+      (let ((spec (%untrace-1 trace-thing)))
+        (when spec
+          (push spec val))))))
+  (when *untrace-hook*
+    (funcall *untrace-hook* sym))
+  (if (null (cdr val)) (car val) val))
+
+;; thing is a symbol or method - def is current definition
+;; we already know its traced
+(defun %untrace-1 (thing)
+  (let ((cap (get-encapsulation thing)))
+    (when (and cap (eq (encapsulation-type cap) 'trace))
+      (remove-encapsulation cap)
+      (encapsulation-spec cap))))
+
+(defun %untrace-pfun (sym)
+  (let ((len (length %pascal-functions%))
+        (sym-name (symbol-name sym)))
+    (declare (fixnum len))
+    (dotimes (i len)
+      (let ((pfe (%svref %pascal-functions% i)))
+        (when (and (vectorp pfe)
+                   (string= sym-name (symbol-name (pfe.sym pfe))))
+          (setf (pfe.trace-p pfe) nil
+                *trace-pfun-list* (remove sym *trace-pfun-list*))
+          (return-from %untrace-pfun sym))))
+    nil))
+
+
+
+(defmacro trace (&rest syms)
+  "TRACE {Option Global-Value}* { Name | (Name {Option Value}*) }*
+
+TRACE is a debugging tool that provides information when specified
+functions are called."
+  (if syms
+    (let ((options (loop while (keywordp (car syms))
+                     nconc (list (pop syms) (pop syms)))))
+      `(%trace-0 ',syms ',options))
+    `(%trace-list)))
+
+(defun trace-spec-p (arg)
+  (or (atom arg)
+      (memq (car arg) '(:method setf :package))))
+
+
+(defun %trace-0 (syms &optional global-options)
+  (dolist (spec syms)
+    (if (trace-spec-p spec)
+      (apply #'trace-function spec global-options)
+      (apply #'trace-function (append spec global-options)))))
+
+(defun %trace-list ()
+  (let (res)
+    (loop for x being the hash-value of *encapsulation-table*
+	 when (eq (encapsulation-type x) 'trace)
+	 do (push (encapsulation-spec x) res))
+    (dolist (x *trace-pfun-list*)
+      (push x res))
+    res))
+
+(defmacro with-traces (syms &body body)
+ `(unwind-protect
+       (progn
+         (let ((*trace-output* (make-broadcast-stream)))
+           ;; if you're tracing ccl internals you'll get trace output as it encapsulates the
+           ;; functions so hide all the trace output while eval'ing the trace form itself.
+           (trace ,@syms))
+         ,@body)
+    (untrace ,@syms)))
+
+;; this week def is the name of an uninterned gensym whose fn-cell is original def
+
+(defun trace-global-def (sym def if before-if eval-before after-if eval-after &optional method-p)
+  (let ((saved-method-var (gensym))
+        (enable (gensym))
+        do-it)
+    (setq do-it
+          (cond #+old (step
+                       (setq step-it            
+                             `(step-apply-simple ',def args))
+                       (if (eq step t)
+                         step-it
+                         `(if (apply ',step ',sym args) ; gaak
+                           ,step-it
+                           ,(if (and before method-p)
+                                `(apply-with-method-context ,saved-method-var (symbol-function ',def) args)
+                                `(apply ',def args)))))
+                (t (if (and eval-before method-p)
+                     `(apply-with-method-context ,saved-method-var (symbol-function ',def) args)
+                     `(apply ',def args)))))
+    (compile-named-function-warn
+     `(lambda (,@(and eval-before method-p `(&method ,saved-method-var))
+               &rest args) ; if methodp put &method on front of args - vs get-saved-method-var?
+       (declare (dynamic-extent args))
+       (declare (ftype function ,def))
+       (let ((*trace-level* (1+ *trace-level*))
+             (,enable ,if))
+         (declare (special *trace-enable* *trace-level*))
+         ,(when eval-before
+           `(when (and ,enable ,before-if *trace-enable*)
+             (when *trace-print-hook*
+               (funcall *trace-print-hook* ',sym t))
+             (let* ((*trace-enable* nil))
+               ,@eval-before)
+             (when *trace-print-hook*
+               (funcall *trace-print-hook* ',sym nil))))
+         ,(if eval-after
+           `(let ((vals (multiple-value-list ,do-it)))
+             (when (and ,enable ,after-if *trace-enable*)
+               (when *trace-print-hook* 
+                 (funcall *trace-print-hook* ',sym t))
+               (let* ((*trace-enable* nil))
+                 ,@eval-after)
+               (when *trace-print-hook* 
+                 (funcall *trace-print-hook* ',sym nil)))
+             (values-list vals))
+           do-it)))
+     `(traced ,sym)
+     :keep-symbols t)))
+
+; &method var tells compiler to bind var to contents of next-method-context
+(defun advise-global-def (def when stuff &optional method-p dynamic-extent-arglist)
+  (let* ((saved-method-var (gensym)))
+    `(lambda (,@(if (and method-p (neq when :after))
+                  `(&method ,saved-method-var))
+              &rest arglist)
+       ,@(and dynamic-extent-arglist '((declare (dynamic-extent arglist))))
+       (declare (ftype function ,def))
+       (let ()
+         ,(ecase
+            when
+            (:before
+             `(block nil
+                ,stuff                  
+                (return ,(if method-p
+                           `(apply-with-method-context ,saved-method-var (symbol-function ',def) arglist)
+                           `(apply ',def arglist)))))
+            (:after         
+             `(block nil
+                (let ((values (multiple-value-list (apply (function ,def) arglist))))
+                  ;(declare (dynamic-extent values))
+                  ,stuff
+                  (return (values-list values)))))
+            (:around
+             ;; stuff is e.g. (+ 5 (:do-it))
+             (if method-p 
+               `(macrolet ((:do-it ()
+                             `(apply-with-method-context ,',saved-method-var 
+                                                         (symbol-function ',',def)
+                                                         arglist)))
+                  (block nil
+                    (return  ,stuff)))
+               `(macrolet ((:do-it ()
+                             `(apply (function ,',def) arglist)))
+                  (block nil
+                    (return  ,stuff))))))))))
+
+
+(defun compile-named-function-warn (fn name &rest keys)
+  (declare (dynamic-extent keys))
+  (multiple-value-bind (result warnings) (apply #'compile-named-function fn :name name keys)
+    (when warnings 
+      (let ((first t))
+        (dolist (w warnings)
+          (signal-compiler-warning w first nil nil nil)
+          (setq first nil))))
+    result))
+
+       
+(defun %advised-p (thing)
+  (loop for nx = thing then (encapsulation-symbol cap)
+    as cap = (get-encapsulation nx) while cap
+    thereis (eq (encapsulation-type cap) 'advice)))
+
+(defun %advice-encapsulations (thing when advice-name)
+  (loop for nx = thing then (encapsulation-symbol cap)
+    as cap = (get-encapsulation nx) while cap
+    when (and (eq (encapsulation-type cap) 'advice)
+              (or (null when) (eq when (encapsulation-advice-when cap)))
+              (or (null advice-name) (equal advice-name (encapsulation-advice-name cap))))
+    collect cap))
+
+(defun advise-2 (newdef newsym method-p function-spec when advice-name define-if-not)      
+  (let* ((advise-thing (%encapsulation-thing function-spec define-if-not))
+         orig-sym)
+    (let ((capsules (%advice-encapsulations advise-thing when advice-name)))
+      (when capsules 
+        (unadvise-capsules capsules)))
+    (when (%traced-p advise-thing)
+      ; make traced call advised
+      (setq orig-sym
+            (encapsulation-symbol (get-encapsulation advise-thing))))
+    (lfun-name newdef `(advised ',function-spec))
+    (if method-p (copy-method-function-bits (%encap-binding advise-thing) newdef))
+    (encapsulate (or orig-sym advise-thing) newdef 'advice function-spec newsym advice-name when)
+    newdef))
+
+(defmacro advise (function form &key (when :before) name define-if-not dynamic-extent-arglist)
+  (let* ((newsym (gensym "ADVICE"))
+         ; WAS typep advise-thing 'method
+         (method-p (or (typep function 'method) ; can this happen?
+                       (and (consp function)(eq (car function) :method))))
+         (newdef (advise-global-def newsym when form method-p dynamic-extent-arglist)))
+      `(advise-2 ,newdef ',newsym ,method-p ',function ',when ',name
+                 ,define-if-not)))
+
+(defmacro advisedp (function-spec &key when name)
+  `(advisedp-1 ',function-spec ',when ',name))
+
+(defun encapsulation-advice-spec (cap)
+  (list (encapsulation-spec cap)
+        (encapsulation-advice-when cap)
+        (encapsulation-advice-name cap)))
+  
+(defun advisedp-1 (function-spec when name)
+  (cond ((eq t function-spec)
+         (loop for c being the hash-value of *encapsulation-table*
+           when (and (eq (encapsulation-type c) 'advice)
+                     (or (null when)(eq when (encapsulation-advice-when c)))
+                     (or (null name)(equal name (encapsulation-advice-name c))))
+           collect (encapsulation-advice-spec c)))
+        (t (let* ((advise-thing (%encapsulation-thing function-spec))
+                  (capsules (%advice-encapsulations advise-thing when name)))
+             (mapcar #'encapsulation-advice-spec capsules)))))
+
+(defun %unadvise-1 (function-spec &optional when advice-name ignore)
+  (declare (ignore ignore))
+  (let ((advise-thing (%encapsulation-thing function-spec)))
+    (let ((capsules (%advice-encapsulations advise-thing when advice-name)))
+      (when capsules (unadvise-capsules capsules)))))
+
+(defun unadvise-capsules (capsules)
+  (let (val)
+    (dolist (capsule capsules)
+        (push (encapsulation-advice-spec capsule) val)
+        (remove-encapsulation capsule))
+    val))
+
+(defmacro unadvise (function &key when name)
+  (cond ((neq function t)
+         `(%unadvise-1 ',function ',when ',name))
+        (t '(%unadvise-all))))
+
+(defun %unadvise-all ()
+  (loop for cap being the hash-value of *encapsulation-table*
+    when (eq (encapsulation-type cap) 'advice)
+    collect (progn
+              (remove-encapsulation cap)
+              (encapsulation-advice-spec cap))))
+
+;; Called from %defun. Return t if we defined it, nil otherwise
+(defun %defun-encapsulated-maybe (name newdef)
+  (assert (not (get-encapsulation newdef)))
+  (let ((old-def (fboundp name)) cap)
+    (when (and old-def (setq cap (get-encapsulation name)))
+      (cond ((or (and *loading-files* *loading-removes-encapsulation*)
+                 ;; redefining a gf as a fn.
+                 (typep old-def 'standard-generic-function))
+             (forget-encapsulations name)
+             nil)
+            (t (set-unencapsulated-definition cap newdef)
+               T)))))
+
+;; Called from clos when change dcode
+(defun %set-encapsulated-gf-dcode (gf new-dcode)
+  (loop with cap = (get-encapsulation gf)
+    for gf-copy = (encapsulation-old-def cap)
+    as cur-dcode = (%gf-dcode gf-copy)
+    do (setq cap (get-encapsulation cur-dcode))
+    ;; refresh all the gf copies, in case other info in gf changed
+    do (%copy-function gf gf-copy)
+    do (setf (%gf-dcode gf-copy) (if cap cur-dcode new-dcode))
+    while cap))
+
+;; Called from clos when oldmethod is being replaced by newmethod in a gf.
+(defun %move-method-encapsulations-maybe (oldmethod newmethod &aux cap)
+  (unless (eq oldmethod newmethod)
+    (cond ((and *loading-removes-encapsulation* *loading-files*)
+           (when (%traced-p oldmethod)
+             (warn "~%... Untracing ~s" (%untrace-1 oldmethod)))
+           (when (%advised-p oldmethod)
+             (format t "~%... Unadvising ~s" (%unadvise-1 oldmethod))))
+          (t (when (setq cap (get-encapsulation oldmethod))
+               (let* ((old-inner-def (find-unencapsulated-definition oldmethod))
+                      (newdef (%method-function newmethod))
+                      (olddef (%method-function oldmethod)))
+                 ;; make last encapsulation call new definition
+                 (set-unencapsulated-definition cap newdef)
+                 (setf (%method-function newmethod) olddef)
+                 (set-encapsulation-owner olddef newmethod)
+                 (setf (%method-function oldmethod) old-inner-def)
+                 (loop
+                   for def = olddef then (encapsulation-old-def cap)
+                   for cap = (get-encapsulation def) while cap
+                   do (copy-method-function-bits newdef def))))))))
+
+#|
+        Change History (most recent last):
+        2       12/29/94        akh     merge with d13
+|# ;(do not edit past this line!!)
Index: /branches/new-random/lib/ffi-darwinppc32.lisp
===================================================================
--- /branches/new-random/lib/ffi-darwinppc32.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-darwinppc32.lisp	(revision 13309)
@@ -0,0 +1,258 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; If a record type has a single scalar field, return the type
+;;; of that field.
+(defun darwin32::record-type-has-single-scalar-field (record-type)
+  (when (eq (foreign-record-type-kind record-type) :struct)
+    (require-foreign-type-bits record-type)
+    (let* ((fields (foreign-record-type-fields record-type)))
+      (when (null (cdr fields))
+        (let* ((f0 (car fields))
+               (type (foreign-record-field-type f0)))
+          (typecase type
+            ((or foreign-record-type foreign-array-type) nil)
+            (otherwise type)))))))
+
+;;; If type denotes a foreign record type, return T if it would
+;;; be "returned" by passing it as the first argument to the callee.
+;;; On DarwinPPC32, this is true of all record types except for
+;;; those for which RECORD-TYPE-HAS-SINGLE-SCALAR-FIELD returns
+;;; true.
+(defun darwin32::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+             (not (typep rtype 'unsigned-byte))
+             (not (member rtype *foreign-representation-type-keywords*
+                          :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+                    rtype
+                    (parse-foreign-type rtype))))
+      (and (typep ftype 'foreign-record-type)
+           (not (darwin32::record-type-has-single-scalar-field ftype))))))
+
+
+;;; Structures that contain a single scalar field are "returned"
+;;; as a value with that field's type.
+;;; Other structures are "returned" by passing a pointer to a structure
+;;; of the appropriate type as the first argument.
+;;; Structures that contain a single scalar field are passed by value
+;;; by passing the value of that field as a scalar.
+;;; Structures that contain more than one field are passed by value
+;;; as a sequence of N 32-bit words; %ff-call understands an unsigned
+;;; integer argument "type" specifier to denote this.
+
+(defun darwin32::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (let* ((result-type-spec (or (car (last args)) :void))
+         (enclosing-form nil))
+    (multiple-value-bind (result-type error)
+        (ignore-errors (parse-foreign-type result-type-spec))
+      (if error
+        (setq result-type-spec :void result-type *void-foreign-type*)
+        (setq args (butlast args)))
+      (collect ((argforms))
+        (when (eq (car args) :monitor-exception-ports)
+          (argforms (pop args)))
+        (when (typep result-type 'foreign-record-type)
+          (let* ((single-scalar (darwin32::record-type-has-single-scalar-field result-type))
+                 (result-form (pop args)))
+            (if single-scalar
+              (progn
+                (setq enclosing-form `(setf ,(%foreign-access-form result-form single-scalar 0 nil))
+                      result-type single-scalar
+                      result-type-spec (foreign-type-to-representation-type result-type)))
+                      
+              (progn
+                (argforms :address)
+                (argforms result-form)
+                (setq result-type *void-foreign-type*
+                      result-type-spec :void)))))
+        (unless (evenp (length args))
+          (error "~s should be an even-length list of alternating foreign types and values" args))
+        (do* ((args args (cddr args)))
+             ((null args))
+          (let* ((arg-type-spec (car args))
+                 (arg-value-form (cadr args)))
+            (if (or (member arg-type-spec *foreign-representation-type-keywords*
+                           :test #'eq)
+                    (typep arg-type-spec 'unsigned-byte))
+              (progn
+                (argforms arg-type-spec)
+                (argforms arg-value-form))
+              (let* ((ftype (parse-foreign-type arg-type-spec)))
+                (if (typep ftype 'foreign-record-type)
+                  (let* ((single-scalar (darwin32::record-type-has-single-scalar-field ftype)))
+                    (if single-scalar
+                      (progn
+                        (argforms (foreign-type-to-representation-type single-scalar))
+                        (argforms (%foreign-access-form arg-value-form single-scalar 0 nil)))
+                      (let* ((bits (ensure-foreign-type-bits ftype)))
+                        (argforms (ceiling bits 32))
+                        (argforms arg-value-form))))
+                  (progn
+                    (argforms (foreign-type-to-representation-type ftype))
+                    (argforms (funcall arg-coerce arg-type-spec arg-value-form))))))))
+        (argforms (foreign-type-to-representation-type result-type))
+        (let* ((call (funcall result-coerce result-type-spec `(,@callform ,@(argforms)))))
+          (if enclosing-form
+            `(,@enclosing-form ,call)
+            call))))))
+                  
+            
+            
+;;; Return 7 values:
+;;; A list of RLET bindings
+;;; A list of LET* bindings
+;;; A list of DYNAMIC-EXTENT declarations for the LET* bindings
+;;; A list of initializaton forms for (some) structure args
+;;; A FOREIGN-TYPE representing the "actual" return type.
+;;; A form which can be used to initialize FP-ARGS-PTR, relative
+;;;  to STACK-PTR.  (This is unused on linuxppc32.)
+;;; The byte offset of the foreign return address, relative to STACK-PTR
+
+(defun darwin32::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (collect ((lets)
+            (rlets)
+            (inits)
+            (dynamic-extent-names))
+    (let* ((rtype (parse-foreign-type result-spec))
+           (fp-regs-form nil))
+      (flet ((set-fp-regs-form ()
+               (unless fp-regs-form
+                 (setq fp-regs-form `(%get-ptr ,stack-ptr ,(- ppc32::c-frame.unused-1 ppc32::c-frame.param0))))))
+        (when (typep rtype 'foreign-record-type)
+          (if (darwin32::record-type-has-single-scalar-field rtype)
+            (rlets (list struct-result-name (foreign-record-type-name rtype)))
+            (setq argvars (cons struct-result-name argvars)
+                  argspecs (cons :address argspecs)
+                  rtype *void-foreign-type*)))
+        (when (typep rtype 'foreign-float-type)
+          (set-fp-regs-form))
+        (do* ((argvars argvars (cdr argvars))
+              (argspecs argspecs (cdr argspecs))
+              (fp-arg-num 0)
+              (offset 0 (+ offset delta))
+              (delta 4 4)
+              (bias 0 0)
+              (use-fp-args nil nil))
+             ((null argvars)
+              (values (rlets) (lets) (dynamic-extent-names) (inits) rtype fp-regs-form (- ppc32::c-frame.savelr ppc32::c-frame.param0)))
+          (flet ((next-scalar-arg (argtype)
+                   `(,(cond
+                       ((typep argtype 'foreign-single-float-type)
+                        (if (< (incf fp-arg-num) 14)
+                          (progn
+                            (setq use-fp-args t)
+                            '%get-single-float-from-double-ptr)
+                          (progn
+                            '%get-single-float)))
+                       ((typep argtype 'foreign-double-float-type)
+                        (setq delta 8)
+                        (if (< (incf fp-arg-num) 14)
+                          (setq use-fp-args t))
+                        '%get-double-float)
+                       ((and (typep argtype 'foreign-integer-type)
+                             (= (foreign-integer-type-bits argtype) 64)
+                             (foreign-integer-type-signed argtype))
+                        (setq delta 8)
+                        '%%get-signed-longlong)
+                       ((and (typep argtype 'foreign-integer-type)
+                             (= (foreign-integer-type-bits argtype) 64)
+                             (not (foreign-integer-type-signed argtype)))
+                        (setq delta 8)
+                        '%%get-unsigned-longlong)
+                       ((or (typep argtype 'foreign-pointer-type)
+                            (typep argtype 'foreign-array-type))
+                        '%get-ptr)
+                       (t
+                        (cond ((typep argtype 'foreign-integer-type)
+                               (let* ((bits (foreign-integer-type-bits argtype))
+                                      (signed (foreign-integer-type-signed argtype)))
+                                 (cond ((<= bits 8)
+                                        (setq bias 3)
+                                        (if signed
+                                          '%get-signed-byte
+                                          '%get-unsigned-byte))
+                                       ((<= bits 16)
+                                        (setq bias 2)
+                                        (if signed
+                                          '%get-signed-word 
+                                          '%get-unsigned-word))
+                                       ((<= bits 32)
+                                        (if signed
+                                          '%get-signed-long 
+                                          '%get-unsigned-long))
+                                       (t
+                                        (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                              (t
+                               (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                     ,(if use-fp-args fp-args-ptr stack-ptr)
+                     ,(if use-fp-args (* 8 (1- fp-arg-num))
+                          (+ offset bias)))))                   
+          (let* ((name (car argvars))
+                 (spec (car argspecs))
+                 (argtype (parse-foreign-type spec)))
+            (if (typep argtype 'foreign-record-type)
+              (let* ((type0 (darwin32::record-type-has-single-scalar-field argtype)))
+                (if type0
+                  (progn
+                    (when name (rlets (list name (foreign-record-type-name argtype))))
+                    (let* ((init `(setf ,(%foreign-access-form name type0 0 nil)
+                             ,(next-scalar-arg type0))))
+                      (when name (inits init))))
+                  (progn
+                    (setq delta (* (ceiling (foreign-record-type-bits argtype) 32) 4))
+                    (when name ; no side-efects hers     
+                    (lets (list name `(%inc-ptr ,stack-ptr ,offset)))))))
+              (let* ((pair (list name (next-scalar-arg argtype))))
+                (when name (lets pair))))
+            #+nil
+            (when (or (typep argtype 'foreign-pointer-type)
+                      (typep argtype 'foreign-array-type))
+              (dynamic-extent-names name))
+            (when use-fp-args (set-fp-regs-form)))))))))
+
+(defun darwin32::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (unless (eq return-type *void-foreign-type*)
+    ;; Coerce SINGLE-FLOAT result to DOUBLE-FLOAT
+    (when (typep return-type 'foreign-single-float-type)
+      (setq result `(float ,result 0.0d0)))    
+    (when (typep return-type 'foreign-record-type)
+      ;;; Would have been mapped to :VOID unless record-type contained
+      ;;; a single scalar field.
+      (let* ((field0 (car (foreign-record-type-fields return-type))))
+        (setq result (%foreign-access-form struct-return-arg
+                                           (foreign-record-field-type field0)
+                                           0
+                                           nil)
+              return-type (foreign-record-field-type field0))))
+    (let* ((return-type-keyword (foreign-type-to-representation-type return-type))
+           (result-ptr (case return-type-keyword
+                   ((:single-float :double-float)
+                    fp-args-ptr)
+                   (t stack-ptr))))
+      `(setf (,
+              (case return-type-keyword
+                                 (:address '%get-ptr)
+                                 (:signed-doubleword '%%get-signed-longlong)
+                                 (:unsigned-doubleword '%%get-unsigned-longlong)
+                                 ((:double-float :single-float)
+                                  '%get-double-float)
+                                 (:unsigned-fullword '%get-unsigned-long)
+                                 (t '%get-long )
+                                 ) ,result-ptr 0) ,result))))
+
Index: /branches/new-random/lib/ffi-darwinppc64.lisp
===================================================================
--- /branches/new-random/lib/ffi-darwinppc64.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-darwinppc64.lisp	(revision 13309)
@@ -0,0 +1,543 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; On DarwinPPC64:
+;;; Structures whose size is exactly 16 bytes are passed in 2 GPRs,
+;;; regardless of the types of their elements, when they are passed
+;;; by value.
+;;; Structures which contain unions are passed in N GPRs when passed
+;;; by value.
+;;; All other structures passed by value are passed by passing their
+;;; constituent elements as scalars.  (Sort of.)  GPR's are "consumed"
+;;; for and possibly/partly loaded with the contents of each 64-bit
+;;; word; FPRs (and vector registers) are consumed/loaded for each
+;;; field of the indicated type.
+;;; Structures whose size is exactly 16 bytes are returned in GPR3
+;;; and GPR4.
+;;; Structures which contain unions are "returned" by passing a pointer
+;;; to a structure instance in the first argument.
+;;; All other structures are returned by returning their constituent
+;;; elements as scalars.  (Note that - in some cases - we may need
+;;; to reserve space in the foreign stack frame to handle scalar
+;;; return values that don't fit in registers.  Need a way to tell
+;;; %ff-call about this, as well as runtime support.)
+
+
+(defun darwin64::record-type-contains-union (rtype)
+  ;;; RTYPE is a FOREIGN-RECORD-TYPE object.
+  ;;; If it, any of its fields, or any fields in an
+  ;;; embedded structure or array field is a union,
+  ;;; return true.
+  ;;; (If this function returns true, we can't
+  ;;; pass a structure of type RTYPE - or return one -
+  ;;; by passing or returning the values of all of
+  ;;; its fields, since some fields are aliased.
+  ;;; However, if the record's size is exactly 128
+  ;;; bits, we can pass/return  it in two GPRs.)
+  (ensure-foreign-type-bits rtype)
+  (or (eq (foreign-record-type-kind rtype) :union)
+      (dolist (f (foreign-record-type-fields rtype))
+        (let* ((fieldtype (foreign-record-field-type f)))
+          (if (and (typep fieldtype 'foreign-record-type)
+                   (darwin64::record-type-contains-union fieldtype))
+            (return t))
+          (if (typep fieldtype 'foreign-array-type)
+            (let* ((atype (foreign-array-type-element-type fieldtype)))
+              (if (and (typep atype 'foreign-record-type)
+                       (darwin64::record-type-contains-union atype))
+                (return t))))))))
+
+;;; On DarwinPPC64, we only have to pass a structure as a first
+;;; argument if the type contains a union
+(defun darwin64::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+             (not (typep rtype 'unsigned-byte))
+             (not (member rtype *foreign-representation-type-keywords*
+                          :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+                    rtype
+                    (parse-foreign-type rtype))))
+      (and (typep ftype 'foreign-record-type)
+           (not (= (ensure-foreign-type-bits ftype) 128))
+           (darwin64::record-type-contains-union ftype)))))
+
+
+
+
+
+;;; Generate code to set the fields in a structure R of record-type
+;;; RTYPE, based on the register values in REGBUF (8 64-bit GPRs,
+;;; followed by 13 64-bit GPRs.)
+;;; This also handles the 16-byte structure case.
+;;; (It doesn't yet handle embedded arrays or bitfields.)
+(defun darwin64::struct-from-regbuf-values (r rtype regbuf)
+  (let* ((bits (ccl::ensure-foreign-type-bits rtype)))
+    (collect ((forms))
+      (cond ((= bits 128)               ;(and (eql day 'tuesday) ...)
+             (forms `(setf (ccl::%get-signed-long ,r 0)
+                      (ccl::%get-signed-long ,regbuf 0)
+                      (ccl::%get-signed-long ,r 4)
+                      (ccl::%get-signed-long ,regbuf 4)
+                      (ccl::%get-signed-long ,r 8)
+                      (ccl::%get-signed-long ,regbuf 8)
+                      (ccl::%get-signed-long ,r 12)
+                      (ccl::%get-signed-long ,regbuf 12))))
+            ;;; One (slightly naive) way to do this is to just
+            ;;; copy GPRs into the structure until it's full,
+            ;;; then go back and overwrite float-typed fields
+            ;;; with FPRs.  That'd be very naive if all fields
+            ;;; were float-typed, slightly naive if some fields
+            ;;; were properly-aligned DOUBLE-FLOATs or if two
+            ;;; SINGLE-FLOATs were packed inro a 64-bit word,
+            ;;; and not that bad if a SINGLE-FLOAT shared a
+            ;;; 64-bit word with a non-FP field.
+            (t
+             (let* ((fpr-offset (* 8 8))
+                    (fields (foreign-record-type-fields rtype)))
+               (flet ((next-fpr-offset ()
+                        (prog1 fpr-offset
+                          (incf fpr-offset 8))))
+                 (unless (all-floats-in-field-list fields)
+                   (do* ((b 0 (+ b 32))
+                         (w 0 (+ w 4)))
+                        ((>= b bits))
+                     (declare (fixnum b w))
+                     (forms `(setf (%get-unsigned-long ,r ,w)
+                              (%get-unsigned-long ,regbuf ,w)))))
+                 (when (some-floats-in-field-list fields)
+                   (labels ((do-fp-fields (fields accessors)
+                              (dolist (field fields)
+                                (let* ((field-type (foreign-record-field-type field))
+                                       (field-accessor-list (append accessors (list (foreign-record-field-name field))))
+                                       (valform ()))
+                                  (etypecase field-type
+                                    (foreign-record-type
+                                     (do-fp-fields (foreign-record-type-fields field-type)
+                                       field-accessor-list))
+                                    (foreign-double-float-type
+                                     (setq valform
+                                           `(%get-double-float  ,regbuf ,(next-fpr-offset))))
+                                    (foreign-single-float-type
+                                     (setq valform
+                                           `(%get-single-float-from-double-ptr
+                                             ,regbuf ,(next-fpr-offset))))
+                                    (foreign-array-type
+                                     (error "Embedded array-type."))
+                                    )
+                                  (when valform
+                                    (forms `(setf ,(%foreign-access-form
+                                                    r
+                                                    rtype
+                                                    0
+                                                    field-accessor-list)
+                                             ,valform)))))))
+                     (do-fp-fields (foreign-record-type-fields rtype) nil )))))))
+      `(progn ,@(forms) nil))))
+
+;;; "Return" the structure R of foreign type RTYPE, by storing the
+;;; values of its fields in STACK-PTR and FP-ARG-PTR
+(defun darwin64::return-struct-to-registers (r rtype stack-ptr fp-args-ptr)
+  (let* ((bits (require-foreign-type-bits rtype)))
+    (collect ((forms))
+      (cond ((= bits 128)               ;(and (eql day 'tuesday) ...)
+             (forms `(setf (ccl::%get-unsigned-long ,stack-ptr 0)
+                      (ccl::%get-unsigned-long ,r 0)
+                      (ccl::%get-unsigned-long ,stack-ptr 4)
+                      (ccl::%get-unsigned-long ,r 4)
+                      (ccl::%get-unsigned-long ,stack-ptr 8)
+                      (ccl::%get-unsigned-long ,r 8)
+                      (ccl::%get-unsigned-long ,stack-ptr 12)
+                      (ccl::%get-unsigned-long ,r 12))))
+            (t
+             (let* ((fpr-offset 0)
+                    (fields (foreign-record-type-fields rtype)))
+               (unless (all-floats-in-field-list fields)
+                   (do* ((b 0 (+ b 32))
+                         (w 0 (+ w 4)))
+                        ((>= b bits))
+                     (declare (fixnum b w))
+                     (forms `(setf (%get-unsigned-long ,stack-ptr ,w)
+                              (%get-unsigned-long ,r ,w)))))
+               (when (some-floats-in-field-list fields)
+               (flet ((next-fpr-offset ()
+                        (prog1 fpr-offset
+                          (incf fpr-offset 8))))
+                 (labels ((do-fp-fields (fields accessors)
+                            (dolist (field fields)
+                              (let* ((field-type (foreign-record-field-type field))
+                                     (field-accessor-list (append accessors (list (foreign-record-field-name field))))
+                                     (valform ()))
+                                (etypecase field-type
+                                  (foreign-record-type
+                                   (do-fp-fields (foreign-record-type-fields field-type)
+                                     field-accessor-list))
+                                  (foreign-double-float-type
+                                   (setq valform
+                                         `(%get-double-float  ,fp-args-ptr ,(next-fpr-offset))))
+                                  (foreign-single-float-type
+                                   (setq valform
+                                         `(%get-double-float  ,fp-args-ptr ,(next-fpr-offset))))
+
+                                  (foreign-array-type
+                                   (error "Embedded array-type."))
+                                  )
+                                (when valform
+                                  (let* ((field-form (%foreign-access-form
+                                                      r
+                                                      rtype
+                                                      0
+                                                      field-accessor-list)))
+                                    (when (typep field-type 'foreign-single-float-type)
+                                      (setq field-form `(float ,field-form 0.0d0)))
+                                    (forms `(setf ,valform ,field-form))))))))
+                   (do-fp-fields fields nil )))))))
+      `(progn ,@(forms) nil))))
+
+;;; Return an ordered list of all scalar fields in the record type FTYPE.
+(defun darwin64::flatten-fields (ftype)
+  (if (darwin64::record-type-contains-union ftype)
+    (error "Can't flatten fields in ~s: contains union" ftype))
+  (collect ((fields))
+    (labels ((flatten (field-list bit-offset)
+               (dolist (field field-list)
+                 (let* ((field-type (foreign-record-field-type field))
+                        (next-offset (+ bit-offset (foreign-record-field-offset field))))
+                   (typecase field-type
+                     (foreign-record-type
+                      (flatten (foreign-record-type-fields field-type) next-offset))
+                     (foreign-array-type
+                      (let* ((element-type (foreign-array-type-element-type field-type))
+                             (nbits (foreign-type-bits element-type))
+                             (align (foreign-type-alignment  element-type))
+                             (dims (foreign-array-type-dimensions field-type))
+                             (n (or (and (null (cdr dims)) (car dims))
+                                    (error "Can't handle multidimensional foreign arrays")))
+                             (pos next-offset))
+                        (dotimes (i n)
+                          (fields (make-foreign-record-field :type element-type
+                                                             :bits nbits
+                                                             :offset pos))
+                          (setq pos (align-offset (+ pos nbits) align)))))
+                     (t
+                      (fields (make-foreign-record-field :type field-type
+                                                         :bits (foreign-record-field-bits field)
+                                                         :offset next-offset))))))))
+      (flatten (foreign-record-type-fields ftype) 0)
+      (fields))))
+
+               
+             
+
+(defun darwin64::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (let* ((result-type-spec (or (car (last args)) :void))
+         (regbuf nil)
+         (result-temp nil)
+         (result-form nil)
+         (struct-result-type nil)
+         (structure-arg-temp nil))
+    (multiple-value-bind (result-type error)
+        (ignore-errors (parse-foreign-type result-type-spec))
+      (if error
+        (setq result-type-spec :void result-type *void-foreign-type*)
+        (setq args (butlast args)))
+      (collect ((argforms))
+        (when (eq (car args) :monitor-exception-ports)
+          (argforms (pop args)))
+        (when (typep result-type 'foreign-record-type)
+          (setq result-form (pop args)
+                struct-result-type result-type
+                result-type *void-foreign-type*
+                result-type-spec :void)
+          (if (darwin64::record-type-returns-structure-as-first-arg struct-result-type)
+            (progn
+              (argforms :address)
+              (argforms result-form))
+            (progn
+              (setq regbuf (gensym)
+                    result-temp (gensym))
+              (argforms :registers)
+              (argforms regbuf))))
+        (let* ((valform nil))
+          (unless (evenp (length args))
+            (error "~s should be an even-length list of alternating foreign types and values" args))
+          (do* ((args args (cddr args)))
+               ((null args))
+            (let* ((arg-type-spec (car args))
+                   (arg-value-form (cadr args)))
+              (if (or (member arg-type-spec *foreign-representation-type-keywords*
+                              :test #'eq)
+                      (typep arg-type-spec 'unsigned-byte))
+                (progn
+                  (argforms arg-type-spec)
+                  (argforms arg-value-form))
+                (let* ((ftype (parse-foreign-type arg-type-spec))
+                       (bits (foreign-type-bits ftype)))
+                  (if (typep ftype 'foreign-record-type)
+                    (if (or (darwin64::record-type-contains-union ftype)
+                            (= bits 128))
+                      (progn
+                        (argforms (ceiling (foreign-record-type-bits ftype) 64))
+                        (argforms arg-value-form))
+                      (let* ((flattened-fields (darwin64::flatten-fields ftype)))
+
+                        (flet ((single-float-at-offset (offset)
+                                 (dolist (field flattened-fields)
+                                   (let* ((field-offset (foreign-record-field-offset field)))
+                                     (when (> field-offset offset)
+                                       (return nil))
+                                     (if (and (= field-offset offset)
+                                              (typep (foreign-record-field-type field)
+                                                     'foreign-single-float-type))
+                                       (return t)))))
+                               (double-float-at-offset (offset)
+                                 (dolist (field flattened-fields)
+                                   (let* ((field-offset (foreign-record-field-offset field)))
+                                     (when (> field-offset offset)
+                                       (return nil))
+                                     (if (and (= field-offset offset)
+                                              (typep (foreign-record-field-type field)
+                                                     'foreign-double-float-type))
+                                       (return t))))))
+                        (unless structure-arg-temp
+                          (setq structure-arg-temp (gensym)))
+                        (setq valform `(%setf-macptr ,structure-arg-temp ,arg-value-form))
+                        (do* ((bit-offset 0 (+ bit-offset 64))
+                              (byte-offset 0 (+ byte-offset 8)))
+                             ((>= bit-offset bits))
+                          (if (double-float-at-offset bit-offset)
+                            (progn
+                              (argforms :double-float)
+                              (argforms `(%get-double-float ,valform ,byte-offset)))
+                            (let* ((high-single (single-float-at-offset bit-offset))
+                                   (low-single (single-float-at-offset (+ bit-offset 32))))
+                              (if high-single
+                                (if low-single
+                                  (argforms :hybrid-float-float)
+                                  (argforms :hybrid-float-int))
+                                (if low-single
+                                  (argforms :hybrid-int-float)
+                                  (argforms :unsigned-doubleword)))
+                              (argforms `(%%get-unsigned-longlong ,valform ,byte-offset))))
+                          (setq valform structure-arg-temp)))))
+                    (progn
+                      (argforms (foreign-type-to-representation-type ftype))
+                      (argforms (funcall arg-coerce arg-type-spec arg-value-form))))))))
+          (argforms (foreign-type-to-representation-type result-type))
+          (let* ((call (funcall result-coerce result-type-spec `(,@callform ,@(argforms)))))
+            (when structure-arg-temp
+              (setq call `(let* ((,structure-arg-temp (%null-ptr)))
+                           (declare (dynamic-extent ,structure-arg-temp)
+                                    (type macptr ,structure-arg-temp))
+                           ,call)))
+            (if regbuf
+              `(let* ((,result-temp (%null-ptr)))
+                (declare (dynamic-extent ,result-temp)
+                         (type macptr ,result-temp))
+                (%setf-macptr ,result-temp ,result-form)
+                (%stack-block ((,regbuf (+ (* 8 8) (* 8 13))))
+                  ,call
+                  ,(darwin64::struct-from-regbuf-values result-temp struct-result-type regbuf)))
+              call)))))))
+            
+            
+;;; Return 7 values:
+;;; A list of RLET bindings
+;;; A list of LET* bindings
+;;; A list of DYNAMIC-EXTENT declarations for the LET* bindings
+;;; A list of initializaton forms for (some) structure args
+;;; A FOREIGN-TYPE representing the "actual" return type.
+;;; A form which can be used to initialize FP-ARGS-PTR, relative
+;;;  to STACK-PTR.  (This is unused on linuxppc32.)
+;;; The byte offset of the foreign return address, relative to STACK-PTR
+
+(defun darwin64::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (collect ((lets)
+            (rlets)
+            (inits)
+            (dynamic-extent-names))
+    (let* ((rtype (parse-foreign-type result-spec))
+           (fp-regs-form nil))
+      (flet ((set-fp-regs-form ()
+               (unless fp-regs-form
+                 (setq fp-regs-form `(%get-ptr ,stack-ptr ,(- ppc64::c-frame.unused-1 ppc64::c-frame.param0))))))
+        (when (typep rtype 'foreign-record-type)
+          (if (darwin64::record-type-contains-union rtype)
+            (setq argvars (cons struct-result-name argvars)
+                  argspecs (cons :address argspecs)
+                  rtype *void-foreign-type*)
+            (rlets (list struct-result-name (or (foreign-record-type-name rtype)
+                                                result-spec)))))
+        (when (typep rtype 'foreign-float-type)
+          (set-fp-regs-form))
+        (do* ((argvars argvars (cdr argvars))
+              (argspecs argspecs (cdr argspecs))
+              (fp-arg-num 0)
+              (offset 0)
+              (delta 0)
+              (bias 0)
+              (use-fp-args nil nil))
+             ((null argvars)
+              (values (rlets) (lets) (dynamic-extent-names) (inits) rtype fp-regs-form (- ppc64::c-frame.savelr ppc64::c-frame.param0)))
+          (flet ((next-scalar-arg (argtype)
+                   (setq delta 8 bias 0)
+                   (prog1
+                       `(,(cond
+                           ((typep argtype 'foreign-single-float-type)
+                            (if (< (incf fp-arg-num) 14)
+                              (progn
+                                (setq use-fp-args t)
+                                '%get-single-float-from-double-ptr)
+                              (progn
+                                '%get-single-float)))
+                           ((typep argtype 'foreign-double-float-type)
+                            (if (< (incf fp-arg-num) 14)
+                              (setq use-fp-args t))
+                            '%get-double-float)
+                           ((and (typep argtype 'foreign-integer-type)
+                                 (= (foreign-integer-type-bits argtype) 64)
+                                 (foreign-integer-type-signed argtype))
+                            (setq delta 8)
+                            '%%get-signed-longlong)
+                           ((and (typep argtype 'foreign-integer-type)
+                                 (= (foreign-integer-type-bits argtype) 64)
+                                 (not (foreign-integer-type-signed argtype)))
+                            (setq delta 8)
+                            '%%get-unsigned-longlong)
+                           ((or (typep argtype 'foreign-pointer-type)
+                                (typep argtype 'foreign-array-type))
+                            '%get-ptr)
+                           (t
+                            (cond ((typep argtype 'foreign-integer-type)
+                                   (let* ((bits (foreign-integer-type-bits argtype))
+                                          (signed (foreign-integer-type-signed argtype)))
+                                     (cond ((<= bits 8)
+                                            (setq bias 7)
+                                            (if signed
+                                              '%get-signed-byte '
+                                              '%get-unsigned-byte))
+                                           ((<= bits 16)
+                                            (setq bias 6)
+                                            (if signed
+                                              '%get-signed-word 
+                                              '%get-unsigned-word))
+                                           ((<= bits 32)
+                                            (setq bias 4)
+                                            (if signed
+                                              '%get-signed-long 
+                                              '%get-unsigned-long))
+                                           (t
+                                            (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                                  (t
+                                   (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                         ,(if use-fp-args fp-args-ptr stack-ptr)
+                         ,(if use-fp-args (* 8 (1- fp-arg-num))
+                              (+ offset bias)))
+                     (incf offset delta))))
+            (let* ((name (car argvars))
+                   (spec (car argspecs))
+                   (argtype (parse-foreign-type spec))
+                   (bits (foreign-type-bits argtype)))
+              (if (typep argtype 'foreign-record-type)
+                (if (or (darwin64::record-type-contains-union argtype)
+                        (= bits 128))
+                  (progn (setq delta (* (ceiling bits 64) 8))
+                         (when name (lets (list name `(%inc-ptr ,stack-ptr ,offset ))))
+                         (incf offset delta))
+
+                  (let* ((flattened-fields (darwin64::flatten-fields argtype)))
+                    (flet ((double-float-at-offset (offset)
+                             (dolist (field flattened-fields)
+                               (let* ((field-offset (foreign-record-field-offset field)))
+                                 (when (> field-offset offset) (return))
+                                 (if (and (= field-offset offset)
+                                          (typep (foreign-record-field-type field)
+                                                 'foreign-double-float-type))
+                                   (return t)))))
+                           (single-float-at-offset (offset)
+                             (dolist (field flattened-fields)
+                               (let* ((field-offset (foreign-record-field-offset field)))
+                                 (when (> field-offset offset) (return))
+                                 (if (and (= field-offset offset)
+                                          (typep (foreign-record-field-type field)
+                                                 'foreign-single-float-type))
+                                   (return t))))))
+                      (when name (rlets (list name (or (foreign-record-type-name argtype)
+                                            spec))))
+                      (do* ((bit-offset 0 (+ bit-offset 64))
+                            (byte-offset 0 (+ byte-offset 8)))
+                           ((>= bit-offset bits))
+                        (if (double-float-at-offset bit-offset)
+                          (let* ((init `(setf (%get-double-float ,name ,byte-offset)
+                                   ,(next-scalar-arg (parse-foreign-type :double-float)))))
+                            (when name
+                              (inits init)))
+                          (let* ((high-single (single-float-at-offset bit-offset))
+                                 (low-single (single-float-at-offset (+ bit-offset 32)))
+                                 (init `(setf (%%get-unsigned-longlong ,name ,byte-offset)
+                                     ,(next-scalar-arg (parse-foreign-type '(:unsigned 64))))))
+                            (when name (inits init))
+                            (when high-single
+                              (when (< (incf fp-arg-num) 14)
+                                (set-fp-regs-form)
+                                (when name
+                                  (inits `(setf (%get-single-float ,name ,byte-offset)
+                                         (%get-single-float-from-double-ptr
+                                          ,fp-args-ptr
+                                          ,(* 8 (1- fp-arg-num))))))))
+                            (when low-single
+                              (when (< (incf fp-arg-num) 14)
+                                (set-fp-regs-form)
+                                (when name
+                                  (inits `(setf (%get-single-float ,name ,(+ 4 byte-offset))
+                                         (%get-single-float-from-double-ptr
+                                          ,fp-args-ptr
+                                          ,(* 8 (1- fp-arg-num))))))))))))))
+                (let* ((form (next-scalar-arg argtype)))
+                  (when name 
+                    (lets (list name form)))))
+              #+nil
+              (when (or (typep argtype 'foreign-pointer-type)
+                        (typep argtype 'foreign-array-type))
+                (dynamic-extent-names name))
+              (when use-fp-args (set-fp-regs-form)))))))))
+
+(defun darwin64::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (unless (eq return-type *void-foreign-type*)
+    (when (typep return-type 'foreign-single-float-type)
+      (setq result `(float ,result 0.0d0)))    
+    (if (typep return-type 'foreign-record-type)
+      ;;; Would have been mapped to :VOID unless record-type contained
+      ;;; a single scalar field.
+      (darwin64::return-struct-to-registers struct-return-arg return-type stack-ptr fp-args-ptr)
+      (let* ((return-type-keyword (foreign-type-to-representation-type return-type))
+           (result-ptr (case return-type-keyword
+                   ((:single-float :double-float)
+                    fp-args-ptr)
+                   (t stack-ptr))))
+      `(setf (,
+              (case return-type-keyword
+                                 (:address '%get-ptr)
+                                 (:signed-doubleword '%%get-signed-longlong)
+                                 (:unsigned-doubleword '%%get-unsigned-longlong)
+                                 ((:double-float :single-float)
+                                  '%get-double-float)
+                                 (:unsigned-fullword '%get-unsigned-long)
+                                 (t '%%get-signed-longlong )
+                                 ) ,result-ptr 0) ,result)))))
+
+
Index: /branches/new-random/lib/ffi-darwinx8632.lisp
===================================================================
--- /branches/new-random/lib/ffi-darwinx8632.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-darwinx8632.lisp	(revision 13309)
@@ -0,0 +1,38 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Some small structures are returned in EAX and EDX.  Otherwise,
+;;; return values are placed at the address specified by the caller.
+(defun x86-darwin32::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+	     (not (typep rtype 'unsigned-byte))
+	     (not (member rtype *foreign-representation-type-keywords*
+			  :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+		    rtype
+		    (parse-foreign-type rtype)))
+	   (nbits (ensure-foreign-type-bits ftype)))
+      (not (member nbits '(8 16 32 64))))))
+
+;;; We don't support the __m64, __m128, __m128d, and __m128i types.
+(defun x86-darwin32::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8632::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+
+(defun x86-darwin32::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (x8632::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name))
+
+(defun x86-darwin32::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8632::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
Index: /branches/new-random/lib/ffi-darwinx8664.lisp
===================================================================
--- /branches/new-random/lib/ffi-darwinx8664.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-darwinx8664.lisp	(revision 13309)
@@ -0,0 +1,34 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; It looks like x86-64 Linux, FreeBSD, and Darwin all share the same
+;;; ABI.
+
+(defun x86-darwin64::record-type-returns-structure-as-first-arg (rtype)
+  (x8664::record-type-returns-structure-as-first-arg rtype))
+
+
+
+(defun x86-darwin64::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8664::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+
+(defun x86-darwin64::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name)
+  (x8664::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name))
+
+(defun x86-darwin64::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8664::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
Index: /branches/new-random/lib/ffi-freebsdx8632.lisp
===================================================================
--- /branches/new-random/lib/ffi-freebsdx8632.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-freebsdx8632.lisp	(revision 13309)
@@ -0,0 +1,38 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; On FreeBSD, the C compiler returns small structures in registers
+;;; (just like on Darwin, apparently).
+(defun x86-freebsd32::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+	     (not (typep rtype 'unsigned-byte))
+	     (not (member rtype *foreign-representation-type-keywords*
+			  :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+		    rtype
+		    (parse-foreign-type rtype)))
+	   (nbits (ensure-foreign-type-bits ftype)))
+      (not (member nbits '(8 16 32 64))))))
+
+(defun x86-freebsd32::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8632::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+
+(defun x86-freebsd32::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (x8632::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name))
+
+(defun x86-freebsd32::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8632::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
+
Index: /branches/new-random/lib/ffi-freebsdx8664.lisp
===================================================================
--- /branches/new-random/lib/ffi-freebsdx8664.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-freebsdx8664.lisp	(revision 13309)
@@ -0,0 +1,34 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; It looks like x86-64 Linux, FreeBSD, and Darwin all share the same
+;;; ABI.
+
+(defun x86-freebsd64::record-type-returns-structure-as-first-arg (rtype)
+  (x8664::record-type-returns-structure-as-first-arg rtype))
+
+
+
+(defun x86-freebsd64::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8664::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+
+(defun x86-freebsd64::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name)
+  (x8664::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name))
+
+(defun x86-freebsd64::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8664::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
Index: /branches/new-random/lib/ffi-linuxppc32.lisp
===================================================================
--- /branches/new-random/lib/ffi-linuxppc32.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-linuxppc32.lisp	(revision 13309)
@@ -0,0 +1,218 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; LinuxPPC32:
+;;; Structures are never actually passed by value; the caller
+;;; instead passes a pointer to the structure or a copy of it.
+;;; In the EABI (which Linux uses, as opposed to the SVR4 ABI)
+;;; structures are always "returned" by passing a pointer to
+;;; a caller-allocated structure in the first argument.
+(defun linux32::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+             (not (typep rtype 'unsigned-byte))
+             (not (member rtype *foreign-representation-type-keywords*
+                          :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+                    rtype
+                    (parse-foreign-type rtype))))
+      (typep ftype 'foreign-record-type))))
+
+
+(defun linux32::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (let* ((result-type-spec (or (car (last args)) :void))
+         (enclosing-form nil)
+         (result-form nil))
+    (multiple-value-bind (result-type error)
+        (ignore-errors (parse-foreign-type result-type-spec))
+      (if error
+        (setq result-type-spec :void result-type *void-foreign-type*)
+        (setq args (butlast args)))
+      (collect ((argforms))
+        (when (eq (car args) :monitor-exception-ports)
+          (argforms (pop args)))
+        (when (typep result-type 'foreign-record-type)
+          (setq result-form (pop args))
+          (if (linux32::record-type-returns-structure-as-first-arg result-type)
+            (progn
+              (setq result-type *void-foreign-type*
+                    result-type-spec :void)
+              (argforms :address)
+              (argforms result-form))
+            ;; This only happens in the SVR4 ABI.
+            (progn
+              (setq result-type (parse-foreign-type :unsigned-doubleword)
+                    result-type-spec :unsigned-doubleword
+                    enclosing-form `(setf (%%get-unsigned-longlong ,result-form 0))))))
+        (unless (evenp (length args))
+          (error "~s should be an even-length list of alternating foreign types and values" args))        
+        (do* ((args args (cddr args)))
+             ((null args))
+          (let* ((arg-type-spec (car args))
+                 (arg-value-form (cadr args)))
+            (if (or (member arg-type-spec *foreign-representation-type-keywords*
+                           :test #'eq)
+                    (typep arg-type-spec 'unsigned-byte))
+              (progn
+                (argforms arg-type-spec)
+                (argforms arg-value-form))
+              (let* ((ftype (parse-foreign-type arg-type-spec)))
+                (if (typep ftype 'foreign-record-type)
+                  (progn
+                    (argforms :address)
+                    (argforms arg-value-form))
+                  (progn
+                    (argforms (foreign-type-to-representation-type ftype))
+                    (argforms (funcall arg-coerce arg-type-spec arg-value-form))))))))
+        (argforms (foreign-type-to-representation-type result-type))
+        (let* ((call (funcall result-coerce result-type-spec `(,@callform ,@(argforms)))))
+          (if enclosing-form
+            `(,@enclosing-form ,call)
+            call))))))
+
+;;; Return 7 values:
+;;; A list of RLET bindings
+;;; A list of LET* bindings
+;;; A list of DYNAMIC-EXTENT declarations for the LET* bindings
+;;; A list of initializaton forms for (some) structure args
+;;; A FOREIGN-TYPE representing the "actual" return type.
+;;; A form which can be used to initialize FP-ARGS-PTR, relative
+;;;  to STACK-PTR.  (This is unused on linuxppc32.)
+;;; The byte offset of the foreign return address, relative to STACK-PTR
+(defun linux32::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (declare (ignore fp-args-ptr))
+  (collect ((lets)
+            (rlets)
+            (dynamic-extent-names))
+    (let* ((rtype (parse-foreign-type result-spec)))
+      (when (typep rtype 'foreign-record-type)
+        (let* ((bits (ensure-foreign-type-bits rtype)))
+          (if (<= bits 64)
+            (rlets (list struct-result-name (foreign-record-type-name rtype)))
+            (setq argvars (cons struct-result-name argvars)
+                  argspecs (cons :address argspecs)
+                  rtype *void-foreign-type*))))
+          (let* ((offset  96)
+                 (gpr 0)
+                 (fpr 32))
+            (do* ((argvars argvars (cdr argvars))
+                  (argspecs argspecs (cdr argspecs)))
+                 ((null argvars)
+                  (values (rlets) (lets) (dynamic-extent-names) nil rtype nil 0 #|wrong|#))
+              (let* ((name (car argvars))
+                     (spec (car argspecs))
+                     (nextgpr gpr)
+                     (nextfpr fpr)
+                     (nextoffset offset)
+                     (target gpr)
+                     (bias 0)
+                     (argtype (parse-foreign-type spec)))
+                (if (typep argtype 'foreign-record-type)
+                  (setq argtype (parse-foreign-type :address)))
+                (let* ((access-form
+                        `(,(cond
+                            ((typep argtype 'foreign-single-float-type)
+                             (incf nextfpr 8)
+                             (if (< fpr 96)
+                               (setq target fpr)
+                               (setq target (+ offset (logand offset 4))
+                                     nextoffset (+ target 8)))
+                             '%get-single-float-from-double-ptr)
+                            ((typep argtype 'foreign-double-float-type)
+                             (incf nextfpr 8)
+                             (if (< fpr 96)
+                               (setq target fpr)
+                               (setq target (+ offset (logand offset 4))
+                                     nextoffset (+ target 8)))
+                             '%get-double-float)
+                            ((and (typep argtype 'foreign-integer-type)
+                                  (= (foreign-integer-type-bits argtype) 64)
+                                  (foreign-integer-type-signed argtype))
+                             (if (< gpr 56)
+				     (setq target (+ gpr (logand gpr 4))
+					   nextgpr (+ 8 target))
+				     (setq target (+ offset (logand offset 4))
+					   nextoffset (+ 8 offset)))
+				   '%%get-signed-longlong)
+                            ((and (typep argtype 'foreign-integer-type)
+                                  (= (foreign-integer-type-bits argtype) 64)
+                                  (not (foreign-integer-type-signed argtype)))
+                             (if (< gpr 56)
+                               (setq target (+ gpr (logand gpr 4))
+                                     nextgpr (+ 8 target))
+                               (setq target (+ offset (logand offset 4))
+                                     nextoffset (+ 8 offset)))
+                             '%%get-unsigned-longlong)
+                            (t
+                             (incf nextgpr 4)
+                             (if (< gpr 64)
+                               (setq target gpr)
+                               (setq target offset nextoffset (+ offset 4)))
+                             (cond ((typep argtype 'foreign-pointer-type) '%get-ptr)
+                                   ((typep argtype 'foreign-integer-type)
+                                    (let* ((bits (foreign-integer-type-bits argtype))
+                                           (signed (foreign-integer-type-signed argtype)))
+                                      (cond ((<= bits 8)
+                                             (setq bias 3)
+                                             (if signed
+                                               '%get-signed-byte '
+                                               '%get-unsigned-byte))
+                                            ((<= bits 16)
+                                             (setq bias 2)
+                                             (if signed
+                                               '%get-signed-word 
+                                               '%get-unsigned-word))
+                                            ((<= bits 32)
+                                             (if signed
+                                               '%get-signed-long 
+                                               '%get-unsigned-long))
+                                            (t
+                                             (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                                   (t
+                                    (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                          ,stack-ptr
+                          ,(+ target bias))))
+                  (when name (lets (list name access-form)))
+                  #+nil
+                  (when (eq spec :address)
+                    (dynamic-extent-names name))
+                  (setq gpr nextgpr fpr nextfpr offset nextoffset))))))))
+
+(defun linux32::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (declare (ignore fp-args-ptr))
+  (unless (eq return-type *void-foreign-type*)
+    (when (typep return-type 'foreign-single-float-type)
+      (setq result `(float ,result 0.0d0)))    
+    (let* ((return-type-keyword
+            (if (typep return-type 'foreign-record-type)
+              (progn
+                (setq result `(%%get-unsigned-longlong ,struct-return-arg 0))
+                :unsigned-doubleword)
+              (foreign-type-to-representation-type return-type)))
+           (offset (case return-type-keyword
+                   ((:single-float :double-float)
+                    8)
+                   (t 0))))
+      `(setf (,
+              (case return-type-keyword
+                (:address '%get-ptr)
+                (:signed-doubleword '%%get-signed-longlong)
+                (:unsigned-doubleword '%%get-unsigned-longlong)
+                ((:double-float :single-float) '%get-double-float)
+                (t '%get-long)) ,stack-ptr ,offset) ,result))))
+      
+                 
Index: /branches/new-random/lib/ffi-linuxppc64.lisp
===================================================================
--- /branches/new-random/lib/ffi-linuxppc64.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-linuxppc64.lisp	(revision 13309)
@@ -0,0 +1,199 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; LinuxPPC64
+;;; Structures whose size is less than 64 bits are passed "right-justified"
+;;; in a GPR.
+;;; Larger structures passed by value are passed in GPRs as N doublewords.
+;;; If the structure would require > 64-bit alignment, this might result
+;;; in some GPRs/parameter area words being skipped.  (We don't handle this).
+;;; All structures - of any size - are returned by passing a pointer
+;;; in the first argument.
+
+(defun linux64::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+             (not (typep rtype 'unsigned-byte))
+             (not (member rtype *foreign-representation-type-keywords*
+                          :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+                    rtype
+                    (parse-foreign-type rtype))))
+      (typep ftype 'foreign-record-type))))
+
+(defun linux64::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (let* ((result-type-spec (or (car (last args)) :void)))
+    (multiple-value-bind (result-type error)
+        (ignore-errors (parse-foreign-type result-type-spec))
+      (if error
+        (setq result-type-spec :void result-type *void-foreign-type*)
+        (setq args (butlast args)))
+      (collect ((argforms))
+        (when (eq (car args) :monitor-exception-ports)
+          (argforms (pop args)))
+        (when (typep result-type 'foreign-record-type)
+          (setq result-type *void-foreign-type*
+                result-type-spec :void)
+          (argforms :address)
+          (argforms (pop args)))
+        (unless (evenp (length args))
+          (error "~s should be an even-length list of alternating foreign types and values" args))        
+        (do* ((args args (cddr args)))
+             ((null args))
+          (let* ((arg-type-spec (car args))
+                 (arg-value-form (cadr args)))
+            (if (or (member arg-type-spec *foreign-representation-type-keywords*
+                            :test #'eq)
+                    (typep arg-type-spec 'unsigned-byte))
+              (progn
+                (argforms arg-type-spec)
+                (argforms arg-value-form))
+              (let* ((ftype (parse-foreign-type arg-type-spec)))
+                (if (typep ftype 'foreign-record-type)
+                  (let* ((bits (ensure-foreign-type-bits ftype)))
+                    (if (< bits 64)
+                      (progn
+                        (argforms :unsigned-doubleword)
+                        (argforms `(ash (%%get-unsigned-longlong ,arg-value-form 0) ,(- bits 64))))
+                      (progn
+                        (argforms (ceiling bits 64))
+                        (argforms arg-value-form))))
+                  (progn
+                    (argforms (foreign-type-to-representation-type ftype))
+                    (argforms (funcall arg-coerce arg-type-spec arg-value-form))))))))
+        (argforms (foreign-type-to-representation-type result-type))
+        (funcall result-coerce result-type-spec `(,@callform ,@(argforms)))))))
+
+(defun linux64::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (collect ((lets)
+            (rlets)
+            (inits)
+            (dynamic-extent-names))
+    (let* ((rtype (parse-foreign-type result-spec))
+           (fp-regs-form nil))
+      (flet ((set-fp-regs-form ()
+               (unless fp-regs-form
+                 (setq fp-regs-form `(%get-ptr ,stack-ptr ,(- ppc64::c-frame.unused-1 ppc64::c-frame.param0))))))
+        (when (typep rtype 'foreign-record-type)
+          (setq argvars (cons struct-result-name argvars)
+                argspecs (cons :address argspecs)
+                rtype *void-foreign-type*))
+        (when (typep rtype 'foreign-float-type)
+          (set-fp-regs-form))
+        (do* ((argvars argvars (cdr argvars))
+              (argspecs argspecs (cdr argspecs))
+              (fp-arg-num 0)
+              (offset 0 (+ offset delta))
+              (delta 8 8)
+              (bias 0 0)
+              (use-fp-args nil nil))
+             ((null argvars)
+              (values (rlets) (lets) (dynamic-extent-names) (inits) rtype fp-regs-form (- ppc64::c-frame.savelr ppc64::c-frame.param0)))
+          (let* ((name (car argvars))
+                 (spec (car argspecs))
+                 (argtype (parse-foreign-type spec))
+                 (bits (ensure-foreign-type-bits argtype)))
+            (if (and (typep argtype 'foreign-record-type)
+                     (< bits 64))
+              (progn
+                (when name (rlets (list name (foreign-record-type-name argtype))))
+                (when name (inits `(setf (%%get-unsigned-longlong ,name 0)
+                                    (ash (%%get-unsigned-longlong ,stack-ptr ,offset)
+                                     ,(- 64 bits))))))
+              (let* ((access-form
+                      `(,(cond
+                          ((typep argtype 'foreign-single-float-type)
+                           (if (< (incf fp-arg-num) 14)
+                             (progn
+                               (setq use-fp-args t)
+                               '%get-single-float-from-double-ptr)
+                             (progn
+                               (setq bias 4)
+                               '%get-single-float)))
+                          ((typep argtype 'foreign-double-float-type)
+                           (if (< (incf fp-arg-num) 14)
+                             (setq use-fp-args t))
+                           '%get-double-float)
+                          ((and (typep argtype 'foreign-integer-type)
+                                (= (foreign-integer-type-bits argtype) 64)
+                                (foreign-integer-type-signed argtype))
+                           '%%get-signed-longlong)
+                          ((and (typep argtype 'foreign-integer-type)
+                                (= (foreign-integer-type-bits argtype) 64)
+                                (not (foreign-integer-type-signed argtype)))
+                           '%%get-unsigned-longlong)
+                          ((or (typep argtype 'foreign-pointer-type)
+                               (typep argtype 'foreign-array-type))
+                           '%get-ptr)
+                          ((typep argtype 'foreign-record-type)
+                           (setq delta (* (ceiling bits 64) 8))
+                           '%inc-ptr)
+                          (t
+                           (cond ((typep argtype 'foreign-integer-type)
+                                  (let* ((bits (foreign-integer-type-bits argtype))
+                                         (signed (foreign-integer-type-signed argtype)))
+                                    (cond ((<= bits 8)
+                                           (setq bias 7)
+                                           (if signed
+                                             '%get-signed-byte '
+                                             '%get-unsigned-byte))
+                                          ((<= bits 16)
+                                           (setq bias 6)
+                                           (if signed
+                                             '%get-signed-word 
+                                             '%get-unsigned-word))
+                                          ((<= bits 32)
+                                           (setq bias 4)
+                                           (if signed
+                                             '%get-signed-long 
+                                             '%get-unsigned-long))
+                                          (t
+                                           (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                                 (t
+                                  (error "Don't know how to access foreign argument of type ~s" (unparse-foreign-type argtype))))))
+                        ,(if use-fp-args fp-args-ptr stack-ptr)
+                        ,(if use-fp-args (* 8 (1- fp-arg-num))
+                             `(+ ,offset ,bias)))))
+                (when name (lets (list name access-form)))
+                #+nil
+                (when (eq spec :address)
+                  (dynamic-extent-names name))
+                (when use-fp-args (set-fp-regs-form))))))))))
+
+
+;;; All structures are "returned" via the implicit first argument; we'll have
+;;; already translated the return type to :void in that case.
+(defun linux64::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (declare (ignore struct-return-arg))
+  (unless (eq return-type *void-foreign-type*)
+    (when (typep return-type 'foreign-single-float-type)
+      (setq result `(float ,result 0.0d0)))    
+    (let* ((return-type-keyword (foreign-type-to-representation-type return-type))
+           (result-ptr (case return-type-keyword
+                   ((:single-float :double-float)
+                    fp-args-ptr)
+                   (t stack-ptr))))
+      `(setf (,
+              (case return-type-keyword
+                                 (:address '%get-ptr)
+                                 (:signed-doubleword '%%get-signed-longlong)
+                                 (:unsigned-doubleword '%%get-unsigned-longlong)
+                                 ((:double-float :single-float)
+                                  (setq stack-ptr `(%get-ptr ,stack-ptr ,(- ppc64::c-frame.unused-1 ppc64::c-frame.param0)))
+                                  '%get-double-float)
+                                 (t '%%get-signed-longlong )
+                                 ) ,result-ptr 0) ,result))))
Index: /branches/new-random/lib/ffi-linuxx8632.lisp
===================================================================
--- /branches/new-random/lib/ffi-linuxx8632.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-linuxx8632.lisp	(revision 13309)
@@ -0,0 +1,28 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defun x86-linux32::record-type-returns-structure-as-first-arg (rtype)
+  (x8632::record-type-returns-structure-as-first-arg rtype))
+
+(defun x86-linux32::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8632::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+
+(defun x86-linux32::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (x8632::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name))
+
+(defun x86-linux32::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8632::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
+
Index: /branches/new-random/lib/ffi-linuxx8664.lisp
===================================================================
--- /branches/new-random/lib/ffi-linuxx8664.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-linuxx8664.lisp	(revision 13309)
@@ -0,0 +1,36 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+;;; It looks like x86-64 Linux, FreeBSD, and Darwin all share the same
+;;; ABI.
+
+(defun x86-linux64::record-type-returns-structure-as-first-arg (rtype)
+  (x8664::record-type-returns-structure-as-first-arg rtype))
+
+
+
+(defun x86-linux64::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8664::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+                           
+
+(defun x86-linux64::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name)
+  (x8664::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name))
+
+(defun x86-linux64::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8664::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
Index: /branches/new-random/lib/ffi-solarisx8632.lisp
===================================================================
--- /branches/new-random/lib/ffi-solarisx8632.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-solarisx8632.lisp	(revision 13309)
@@ -0,0 +1,27 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defun x86-solaris32::record-type-returns-structure-as-first-arg (rtype)
+  (x8632::record-type-returns-structure-as-first-arg rtype))
+
+(defun x86-solaris32::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8632::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+
+(defun x86-solaris32::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (x8632::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name))
+
+(defun x86-solaris32::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8632::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
Index: /branches/new-random/lib/ffi-solarisx8664.lisp
===================================================================
--- /branches/new-random/lib/ffi-solarisx8664.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-solarisx8664.lisp	(revision 13309)
@@ -0,0 +1,36 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2008-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+;;; It looks like x86-64 Linux, FreeBSD, Darwin, and Solaris all share
+;;; the same ABI.
+
+(defun x86-solaris64::record-type-returns-structure-as-first-arg (rtype)
+  (x8664::record-type-returns-structure-as-first-arg rtype))
+
+
+
+(defun x86-solaris64::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8664::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+                           
+
+(defun x86-solaris64::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name)
+  (x8664::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-return-name))
+
+(defun x86-solaris64::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8664::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
Index: /branches/new-random/lib/ffi-win32.lisp
===================================================================
--- /branches/new-random/lib/ffi-win32.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-win32.lisp	(revision 13309)
@@ -0,0 +1,38 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Cygwin compiler returns small structures in registers
+;;; (just like on Darwin, apparently).
+(defun win32::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+	     (not (typep rtype 'unsigned-byte))
+	     (not (member rtype *foreign-representation-type-keywords*
+			  :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+		    rtype
+		    (parse-foreign-type rtype)))
+	   (nbits (ensure-foreign-type-bits ftype)))
+      (not (member nbits '(8 16 32 64))))))
+
+(defun win32::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (x8632::expand-ff-call callform args :arg-coerce arg-coerce :result-coerce result-coerce))
+
+(defun win32::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (x8632::generate-callback-bindings stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name))
+
+(defun win32::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (x8632::generate-callback-return-value stack-ptr fp-args-ptr result return-type struct-return-arg))
+
Index: /branches/new-random/lib/ffi-win64.lisp
===================================================================
--- /branches/new-random/lib/ffi-win64.lisp	(revision 13309)
+++ /branches/new-random/lib/ffi-win64.lisp	(revision 13309)
@@ -0,0 +1,183 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Win64:
+;;; Structures are never actually passed by value; the caller
+;;; instead passes a pointer to the structure or a copy of it.
+;;; 
+(defun win64::record-type-returns-structure-as-first-arg (rtype)
+  (when (and rtype
+             (not (typep rtype 'unsigned-byte))
+             (not (member rtype *foreign-representation-type-keywords*
+                          :test #'eq)))
+    (let* ((ftype (if (typep rtype 'foreign-type)
+                    rtype
+                    (parse-foreign-type rtype))))
+      (and (typep ftype 'foreign-record-type)
+           (> (ensure-foreign-type-bits ftype) 64)))))
+
+
+(defun win64::expand-ff-call (callform args &key (arg-coerce #'null-coerce-foreign-arg) (result-coerce #'null-coerce-foreign-result))
+  (let* ((result-type-spec (or (car (last args)) :void))
+         (enclosing-form nil)
+         (result-form nil))
+    (multiple-value-bind (result-type error)
+        (ignore-errors (parse-foreign-type result-type-spec))
+      (if error
+        (setq result-type-spec :void result-type *void-foreign-type*)
+        (setq args (butlast args)))
+      (collect ((argforms))
+        (when (eq (car args) :monitor-exception-ports)
+          (argforms (pop args)))
+        (when (typep result-type 'foreign-record-type)
+          (setq result-form (pop args))
+          (if (win64::record-type-returns-structure-as-first-arg result-type)
+            (progn
+              (setq result-type *void-foreign-type*
+                    result-type-spec :void)
+              (argforms :address)
+              (argforms result-form))
+            ;; This only happens in the SVR4 ABI.
+            (progn
+              (setq result-type (parse-foreign-type :unsigned-doubleword)
+                    result-type-spec :unsigned-doubleword
+                    enclosing-form `(setf (%%get-unsigned-longlong ,result-form 0))))))
+        (unless (evenp (length args))
+          (error "~s should be an even-length list of alternating foreign types and values" args))        
+        (do* ((args args (cddr args)))
+             ((null args))
+          (let* ((arg-type-spec (car args))
+                 (arg-value-form (cadr args)))
+            (if (or (member arg-type-spec *foreign-representation-type-keywords*
+                           :test #'eq)
+                    (typep arg-type-spec 'unsigned-byte))
+              (progn
+                (argforms arg-type-spec)
+                (argforms arg-value-form))
+              (let* ((ftype (parse-foreign-type arg-type-spec)))
+                (if (typep ftype 'foreign-record-type)
+                  (progn
+                    (argforms :address)
+                    (argforms arg-value-form))
+                  (progn
+                    (argforms (foreign-type-to-representation-type ftype))
+                    (argforms (funcall arg-coerce arg-type-spec arg-value-form))))))))
+        (argforms (foreign-type-to-representation-type result-type))
+        (let* ((call (funcall result-coerce result-type-spec `(,@callform ,@(argforms)))))
+          (if enclosing-form
+            `(,@enclosing-form ,call)
+            call))))))
+
+;;; Return 7 values:
+;;; A list of RLET bindings
+;;; A list of LET* bindings
+;;; A list of DYNAMIC-EXTENT declarations for the LET* bindings
+;;; A list of initializaton forms for (some) structure args
+;;; A FOREIGN-TYPE representing the "actual" return type.
+;;; A form which can be used to initialize FP-ARGS-PTR, relative
+;;;  to STACK-PTR.
+;;; The byte offset of the foreign return address, relative to STACK-PTR
+(defun win64::generate-callback-bindings (stack-ptr fp-args-ptr argvars argspecs result-spec struct-result-name)
+  (declare (ignore fp-args-ptr))
+  (collect ((lets)
+            (rlets)
+            (inits))
+    (let* ((rtype (parse-foreign-type result-spec)))
+      (when (typep rtype 'foreign-record-type)
+        (if (win64::record-type-returns-structure-as-first-arg rtype)
+          (setq argvars (cons struct-result-name argvars)
+                argspecs (cons :address argspecs)
+                rtype :address)
+          (rlets (list struct-result-name (foreign-record-type-name rtype)))))
+      (do* ((argvars argvars (cdr argvars))
+            (argspecs argspecs (cdr argspecs))
+            (arg-num 0)
+            (gpr-arg-offset -8)
+            (fpr-arg-offset -40)
+            (memory-arg-offset 48)
+            (fp nil nil))
+           ((null argvars)
+            (values (rlets) (lets) nil (inits) rtype nil 8))
+        (flet ((next-gpr ()
+                 (if (<= (incf arg-num) 4)
+                   (prog1
+                       gpr-arg-offset
+                     (decf gpr-arg-offset 8)
+                     (decf fpr-arg-offset 8))
+                   (prog1
+                       memory-arg-offset
+                     (incf memory-arg-offset 8))))
+               (next-fpr ()
+                 (if (<= (incf arg-num) 4)
+                   (prog1
+                       fpr-arg-offset
+                     (decf fpr-arg-offset 8)
+                     (decf gpr-arg-offset 8))
+                   (prog1
+                       memory-arg-offset
+                     (incf memory-arg-offset 8)))))
+          (let* ((name (car argvars))
+                 (spec (car argspecs))
+                 (argtype (parse-foreign-type spec)))
+            (if (typep argtype 'foreign-record-type)
+              (setq argtype :address))
+            (let* ((access-form
+                    `(,
+                          (ecase (foreign-type-to-representation-type argtype)
+                            (:single-float (setq fp t) '%get-single-float)
+                            (:double-float (setq fp t) '%get-double-float)
+                            (:signed-doubleword  '%%get-signed-longlong)
+                            (:signed-fullword '%get-signed-long)
+                            (:signed-halfword '%get-signed-word)
+                            (:signed-byte '%get-signed-byte)
+                            (:unsigned-doubleword '%%get-unsigned-longlong)
+                            (:unsigned-fullword '%get-unsigned-long)
+                            (:unsigned-halfword '%get-unsigned-word)
+                            (:unsigned-byte '%get-unsigned-byte)
+                            (:address
+                             #+nil
+                             (dynamic-extent-names name)
+                             '%get-ptr))
+                          ,stack-ptr
+                          ,(if fp (next-fpr) (next-gpr)))))
+              (when name (lets (list name access-form))))))))))
+
+(defun win64::generate-callback-return-value (stack-ptr fp-args-ptr result return-type struct-return-arg)
+  (declare (ignore fp-args-ptr))
+  (unless (eq return-type *void-foreign-type*)
+    (when (typep return-type 'foreign-single-float-type)
+      (setq result `(float ,result 0.0d0)))    
+    (let* ((return-type-keyword
+            (if (typep return-type 'foreign-record-type)
+              (progn
+                (setq result `(%%get-unsigned-longlong ,struct-return-arg 0))
+                :unsigned-doubleword)
+              (foreign-type-to-representation-type return-type)))
+           (offset (case return-type-keyword
+                   ((:single-float :double-float)
+                    -24)
+                   (t -8))))
+      `(setf (,
+              (case return-type-keyword
+                (:address '%get-ptr)
+                (:signed-doubleword '%%get-signed-longlong)
+                (:unsigned-doubleword '%%get-unsigned-longlong)
+                ((:double-float :single-float) '%get-double-float)
+                (t '%get-long)) ,stack-ptr ,offset) ,result))))
+      
+                 
Index: /branches/new-random/lib/foreign-types.lisp
===================================================================
--- /branches/new-random/lib/foreign-types.lisp	(revision 13309)
+++ /branches/new-random/lib/foreign-types.lisp	(revision 13309)
@@ -0,0 +1,1956 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; This is a slightly-watered-down version of CMUCL's ALIEN-TYPE system.
+
+(in-package "CCL")
+
+(defstruct (interface-dir
+	     (:include dll-node)
+	    )
+  (name)
+  (subdir)
+  (constants-interface-db-file)
+  (functions-interface-db-file)
+  (records-interface-db-file)
+  (types-interface-db-file)
+  (vars-interface-db-file)
+  (objc-classes-interface-db-file)
+  (objc-methods-interface-db-file))
+
+(defmethod print-object ((d interface-dir) stream)
+  (print-unreadable-object (d stream :type t :identity t)
+    (format stream "~s ~s"
+            (interface-dir-name d)
+            (interface-dir-subdir d))))
+
+;;; We can't reference foreign types early in the cold load,
+;;; but we want things like RLET to be able to set a pointer's
+;;; type based on the foreign-type's "ordinal".  We therefore
+;;; seem to have to arrange that certain types have fixed,
+;;; "canonical" ordinals.  I doubt if we need more than a handful
+;;; of these, but let's burn 100
+
+(defconstant max-canonical-foreign-type-ordinal 100)
+
+;;; Some foreign types are "common" (POSIXy things that're available
+;;; on most platforms; some are very platform-specific.  It's getting
+;;; to be a mess to keep those separate by reader conditionalization,
+;;; so use the first 50 ordinals for "common" foreign types and the
+;;; next 50 for platform-specific stuff.
+
+(defconstant max-common-foreign-type-ordinal 50)
+
+;;; This is intended to try to encapsulate foreign type stuff, to
+;;; ease cross-compilation (among other things.)
+
+(defstruct (foreign-type-data (:conc-name ftd-)
+			      (:constructor make-ftd))
+  (translators (make-hash-table :test #'eq))
+  (kind-info (make-hash-table :test #'eq))
+  (definitions (make-hash-table :test #'eq))
+  (struct-definitions (make-hash-table :test #'eq))
+  (union-definitions (make-hash-table :test #'eq))
+  ;; Do we even use this ?
+  (enum-definitions (make-hash-table :test #'eq))
+  (interface-db-directory ())
+  (interface-package-name ())
+  (external-function-definitions (make-hash-table :test #'eq))
+  (dirlist (make-dll-header))
+  (attributes ())
+  (ff-call-expand-function ())
+  (ff-call-struct-return-by-implicit-arg-function ())
+  (callback-bindings-function ())
+  (callback-return-value-function ())
+  (ordinal max-canonical-foreign-type-ordinal)
+  (ordinal-lock (make-lock))
+  (ordinal-types (make-hash-table :test #'eq :weak :value))
+  (pointer-types (make-hash-table :test #'eq))
+  (array-types (make-hash-table :test #'equal))
+  (platform-ordinal-types ()))
+
+
+
+
+(defvar *host-ftd* (make-ftd
+                    :interface-db-directory
+                    #.(ecase (backend-name *target-backend*)
+                        (:linuxppc32 "ccl:headers;")
+                        (:darwinppc32 "ccl:darwin-headers;")
+                        (:darwinppc64 "ccl:darwin-headers64;")
+                        (:linuxppc64 "ccl:headers64;")
+			(:darwinx8632 "ccl:darwin-x86-headers;")
+                        (:linuxx8664 "ccl:x86-headers64;")
+                        (:darwinx8664 "ccl:darwin-x86-headers64;")
+                        (:freebsdx8664 "ccl:freebsd-headers64;")
+                        (:solarisx8664 "ccl:solarisx64-headers;")
+                        (:win64 "ccl:win64-headers;")
+                        (:linuxx8632 "ccl:x86-headers;")
+                        (:win32 "ccl:win32-headers;")
+                        (:solarisx8632 "ccl:solarisx86-headers;")
+                        (:freebsdx8632 "ccl:freebsd-headers;"))
+                    :interface-package-name
+                    #.(ftd-interface-package-name *target-ftd*)
+                    :attributes
+                    '(:bits-per-word #+64-bit-target 64 #+32-bit-target 32
+                      #+win64-target :bits-per-long #+win64-target 32
+                      :signed-char #+darwinppc-target t #-darwinppc-target nil
+                      :struct-by-value #+darwinppc-target t #-darwinppc-target nil
+                      :struct-return-in-registers #+(or (and darwinppc-target 64-bit-target)) t #-(or (and darwinppc-target 64-bit-target)) nil
+                      :struct-return-explicit  #+(or (and darwinppc-target 64-bit-target)) t #-(or (and darwinppc-target 64-bit-target)) nil
+                      :struct-by-value-by-field  #+(or (and darwinppc-target 64-bit-target)) t #-(or (and darwinppc-target 64-bit-target)) nil
+                    
+                      :prepend-underscores #+darwinppc-target t #-darwinppc-target nil)
+                    :ff-call-expand-function
+                    'os::expand-ff-call
+                    :ff-call-struct-return-by-implicit-arg-function
+                    'os::record-type-returns-structure-as-first-arg
+                    :callback-bindings-function
+                    'os::generate-callback-bindings
+                    :callback-return-value-function
+                    'os::generate-callback-return-value
+                    :platform-ordinal-types
+                    (case (backend-name *target-backend*)
+                        (:win64 '((:struct :_stat64)))
+                        (:win32 '((:struct :__stat64)))
+                        (t
+                         (case (target-os-name *target-backend*)
+                           (:darwin '((:struct :host_basic_info)))
+                           (:solaris '((:struct :lifnum)
+                                       (:struct :lifconf)))
+                           (t ()))))))
+                    
+(defvar *target-ftd* *host-ftd*)
+(setf (backend-target-foreign-type-data *host-backend*)
+      *host-ftd*)
+
+(defun next-foreign-type-ordinal (&optional (ftd *target-ftd*))
+  (with-lock-grabbed ((ftd-ordinal-lock ftd))
+    (incf (ftd-ordinal ftd))))
+
+
+(defmacro do-interface-dirs ((dir &optional (ftd '*target-ftd*)) &body body)
+  `(do-dll-nodes  (,dir (ftd-dirlist ,ftd))
+    ,@body))
+
+(defun find-interface-dir (name &optional (ftd *target-ftd*))
+  (do-interface-dirs (d ftd)
+    (when (eq name (interface-dir-name d))
+      (return d))))
+
+(defun require-interface-dir (name &optional (ftd *target-ftd*))
+  (or (find-interface-dir name ftd)
+      (error "Interface directory ~s not found" name)))
+
+(defun ensure-interface-dir (name &optional (ftd *target-ftd*))
+  (or (find-interface-dir name ftd)
+      (let* ((d (make-interface-dir
+		 :name name
+		 :subdir (make-pathname
+			  :directory
+			  `(:relative ,(string-downcase name))))))
+	(append-dll-node d (ftd-dirlist ftd)))))
+
+(defun use-interface-dir (name &optional (ftd *target-ftd*))
+  "Tell Clozure CL to add the interface directory denoted by dir-id to the
+list of interface directories which it consults for foreign type and
+function information. Arrange that that directory is searched before any
+others.
+
+Note that use-interface-dir merely adds an entry to a search list. If the
+named directory doesn't exist in the file system or doesn't contain a set
+of database files, a runtime error may occur when Clozure CL tries to open some
+database file in that directory, and it will try to open such a database
+file whenever it needs to find any foreign type or function information.
+unuse-interface-dir may come in handy in that case."
+  (let* ((d (ensure-interface-dir name ftd)))
+    (move-dll-nodes d (ftd-dirlist ftd))
+    d))
+
+(defun unuse-interface-dir (name &optional (ftd *target-ftd*))
+  "Tell Clozure CL to remove the interface directory denoted by dir-id from
+the list of interface directories which are consulted for foreign type
+and function information. Returns T if the directory was on the search
+list, NIL otherwise."
+  (let* ((d (find-interface-dir name ftd)))
+    (when d
+      (remove-dll-node d)
+      t)))
+
+
+(use-interface-dir :libc)
+
+
+
+;;;; Utility functions.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun align-offset (offset alignment)
+    (let ((extra (rem offset alignment)))
+      (if (zerop extra) offset (+ offset (- alignment extra)))))
+
+  (defun guess-alignment (bits)
+    (cond ((null bits) nil)
+          ((> bits 32) 64)
+          ((> bits 16) 32)
+          ((> bits 8) 16)
+          ((= bits 8) 8)
+          (t 1)))
+
+  (defstruct foreign-type-class
+    (name nil #|:type symbol|#)
+    (include nil :type (or null foreign-type-class))
+    (unparse nil :type (or null function))
+    (type= nil :type (or null function))
+    (lisp-rep nil :type (or null function))
+    (foreign-rep nil :type (or null function))
+    (extract-gen nil :type (or null function))
+    (deposit-gen nil :type (or null function))
+    (naturalize-gen nil :type (or null function))
+    (deport-gen nil :type (or null function))
+    ;; Cast?
+    (arg-tn nil :type (or null function))
+    (result-tn nil :type (or null function))
+    (subtypep nil :type (or null function)))
+
+  (defvar *foreign-type-classes* (make-hash-table :test #'eq))
+
+  (defun info-foreign-type-translator (x &optional (ftd *target-ftd*))
+    (gethash (make-keyword x) (ftd-translators ftd)))
+  (defun (setf info-foreign-type-translator) (val x &optional (ftd *target-ftd*))
+    (setf (gethash (make-keyword x) (ftd-translators ftd)) val))
+
+  (defun note-foreign-type-ordinal (type ftd)
+    (let* ((ordinal (and type (foreign-type-ordinal type))))
+      (when (and ordinal (not (eql 0 ordinal)))
+        (with-lock-grabbed ((ftd-ordinal-lock ftd))
+          (setf (gethash ordinal (ftd-ordinal-types ftd)) type)))))
+  
+  (defun info-foreign-type-kind (x &optional (ftd *target-ftd*))
+    (if (info-foreign-type-translator x ftd)
+      :primitive
+      (or (gethash (make-keyword x) (ftd-kind-info ftd)) :unknown)))
+  (defun (setf info-foreign-type-kind) (val x &optional (ftd *target-ftd*))
+    (setf (gethash (make-keyword x) (ftd-kind-info ftd)) val))
+		   
+  (defun info-foreign-type-definition (x &optional (ftd *target-ftd*))
+    (gethash (make-keyword x) (ftd-definitions ftd)))
+  (defun (setf info-foreign-type-definition) (val x &optional (ftd *target-ftd*))
+    (note-foreign-type-ordinal val ftd)
+    (setf (gethash (make-keyword x) (ftd-definitions ftd)) val))
+  (defun clear-info-foreign-type-definition (x &optional (ftd *target-ftd*))
+    (remhash (make-keyword x) (ftd-definitions ftd)))
+
+  (defun info-foreign-type-struct (x &optional (ftd *target-ftd*))
+    (gethash (make-keyword x) (ftd-struct-definitions ftd)))
+  (defun (setf info-foreign-type-struct) (val x &optional (ftd *target-ftd*))
+    (let* ((name (make-keyword x)))
+      (when (gethash name (ftd-union-definitions ftd))
+        (cerror "Define ~s as a struct type"
+                "~s is already defined as a union type"
+                name)
+        (remhash name (ftd-union-definitions ftd)))
+      (note-foreign-type-ordinal val ftd)
+      (setf (gethash name (ftd-struct-definitions ftd)) val)))
+
+  (defun info-foreign-type-union (x &optional (ftd *target-ftd*))
+    (gethash (make-keyword x) (ftd-union-definitions ftd)))
+  (defun (setf info-foreign-type-union) (val x  &optional (ftd *target-ftd*))
+    (let* ((name (make-keyword x)))
+      (when (gethash name (ftd-struct-definitions ftd))
+        (cerror "Define ~s as a union type"
+                "~s is already defined as a struct type"
+                name)
+        (remhash name (ftd-struct-definitions ftd)))
+    (note-foreign-type-ordinal val ftd)
+    (setf (gethash name (ftd-union-definitions ftd)) val)))
+
+  (defun info-foreign-type-enum (x  &optional (ftd *target-ftd*))
+    (gethash (make-keyword x) (ftd-enum-definitions ftd)))
+  (defun (setf info-foreign-type-enum) (val x &optional (ftd *target-ftd*))
+    (note-foreign-type-ordinal val ftd)
+    (setf (gethash (make-keyword x) (ftd-enum-definitions ftd)) val))
+
+  (defun require-foreign-type-class (name)
+    (or (gethash name  *foreign-type-classes*)
+        (error "Unknown foreign type class ~s" name)))
+
+  (defun find-or-create-foreign-type-class (name include)
+    (let* ((old (gethash name *foreign-type-classes*))
+           (include-class (if include (require-foreign-type-class include))))
+      (if old
+        (setf (foreign-type-class-name old) include-class)
+        (setf (gethash name *foreign-type-classes*)
+              (make-foreign-type-class :name name :include include-class)))))
+
+
+  (defconstant method-slot-alist
+    '((:unparse . foreign-type-class-unparse)
+      (:type= . foreign-type-class-type=)
+      (:subtypep . foreign-type-class-subtypep)
+      (:lisp-rep . foreign-type-class-lisp-rep)
+      (:foreign-rep . foreign-type-class-foreign-rep)
+      (:extract-gen . foreign-type-class-extract-gen)
+      (:deposit-gen . foreign-type-class-deposit-gen)
+      (:naturalize-gen . foreign-type-class-naturalize-gen)
+      (:deport-gen . foreign-type-class-deport-gen)
+      ;; Cast?
+      (:arg-tn . foreign-type-class-arg-tn)
+      (:result-tn . foreign-type-class-result-tn)))
+
+  (defun method-slot (method)
+    (cdr (or (assoc method method-slot-alist)
+             (error "No method ~S" method))))
+  )
+
+(defmethod print-object ((f foreign-type-class) out)
+  (print-unreadable-object (f out :type t :identity t)
+    (prin1 (foreign-type-class-name f) out)))
+
+
+;;; We define a keyword "BOA" constructor so that we can reference the slots
+;;; names in init forms.
+;;;
+(defmacro def-foreign-type-class ((name &key include include-args) &rest slots)
+  (let ((defstruct-name
+	 (intern (concatenate 'string "FOREIGN-" (symbol-name name) "-TYPE"))))
+    (multiple-value-bind
+	(include include-defstruct overrides)
+	(etypecase include
+	  (null
+	   (values nil 'foreign-type nil))
+	  (symbol
+	   (values
+	    include
+	    (intern (concatenate 'string
+				 "FOREIGN-" (symbol-name include) "-TYPE"))
+	    nil))
+	  (list
+	   (values
+	    (car include)
+	    (intern (concatenate 'string
+				 "FOREIGN-" (symbol-name (car include)) "-TYPE"))
+	    (cdr include))))
+      `(progn
+	 (eval-when (:compile-toplevel :load-toplevel :execute)
+	   (find-or-create-foreign-type-class ',name ',(or include 'root)))
+	 (defstruct (,defstruct-name
+			(:include ,include-defstruct
+				  (class ',name)
+				  ,@overrides)
+			(:constructor
+			 ,(intern (concatenate 'string "MAKE-"
+					       (string defstruct-name)))
+			 (&key class bits alignment
+			       ,@(mapcar #'(lambda (x)
+					     (if (atom x) x (car x)))
+					 slots)
+			       ,@include-args)))
+	   ,@slots)))))
+
+(defmacro def-foreign-type-method ((class method) lambda-list &rest body)
+  (let ((defun-name (intern (concatenate 'string
+					 (symbol-name class)
+					 "-"
+					 (symbol-name method)
+					 "-METHOD"))))
+    `(progn
+       (defun ,defun-name ,lambda-list
+	 ,@body)
+       (setf (,(method-slot method) (require-foreign-type-class ',class))
+	     #',defun-name))))
+
+(defmacro invoke-foreign-type-method (method type &rest args)
+  (let ((slot (method-slot method)))
+    (once-only ((type type))
+      `(funcall (do ((class (require-foreign-type-class (foreign-type-class ,type))
+			    (foreign-type-class-include class)))
+		    ((null class)
+		     (error "Method ~S not defined for ~S"
+			    ',method (foreign-type-class ,type)))
+		  (let ((fn (,slot class)))
+		    (when fn
+		      (return fn))))
+		,type ,@args))))
+
+
+
+;;;; Foreign-type defstruct.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (find-or-create-foreign-type-class 'root nil))
+
+(defstruct (foreign-type
+	    (:constructor make-foreign-type (&key class bits alignment ordinal))
+	    (:print-object
+	     (lambda (s out)
+	       (print-unreadable-object (s out :type t :identity t)
+		 (prin1 (unparse-foreign-type s) out)))))
+  (class 'root :type symbol)
+  (bits nil :type (or null unsigned-byte))
+  (alignment (guess-alignment bits) :type (or null unsigned-byte))
+  (ordinal (next-foreign-type-ordinal)))
+
+
+
+(defmethod make-load-form ((s foreign-type) &optional env)
+  (if (eq s *void-foreign-type*)
+    '*void-foreign-type*
+    (make-load-form-saving-slots s :environment env)))
+
+
+
+
+
+;;;; Type parsing and unparsing.
+
+(defvar *auxiliary-type-definitions* nil)
+(defvar *new-auxiliary-types*)
+
+;;; WITH-AUXILIARY-FOREIGN-TYPES -- internal.
+;;;
+;;; Process stuff in a new scope.
+;;;
+(defmacro with-auxiliary-foreign-types (&body body)
+  `(let ((*auxiliary-type-definitions*
+	  (if (boundp '*new-auxiliary-types*)
+	      (append *new-auxiliary-types* *auxiliary-type-definitions*)
+	      *auxiliary-type-definitions*))
+	 (*new-auxiliary-types* nil))
+     ,@body))
+
+;;; PARSE-FOREIGN-TYPE -- public
+;;;
+(defun parse-foreign-type (type &optional (ftd *target-ftd*))
+  "Parse the list structure TYPE as a foreign type specifier and return
+   the resultant foreign-type structure."
+  (if (boundp '*new-auxiliary-types*)
+    (%parse-foreign-type type ftd)
+    (let ((*new-auxiliary-types* nil))
+      (%parse-foreign-type type ftd))))
+
+(defun %parse-foreign-type (type &optional (ftd *target-ftd*))
+  (if (consp type)
+    (let ((translator (info-foreign-type-translator (car type) ftd)))
+      (unless translator
+        (error "Unknown foreign type: ~S" type))
+      (funcall translator type nil))
+    (case (info-foreign-type-kind type)
+      (:primitive
+       (let ((translator (info-foreign-type-translator type ftd)))
+         (unless translator
+           (error "No translator for primitive foreign type ~S?" type))
+      (funcall translator (list type) nil)))
+      (:defined
+          (or (info-foreign-type-definition type ftd)
+              (error "Definition missing for foreign type ~S?" type)))
+      (:unknown
+       (let* ((loaded (load-foreign-type type ftd)))
+	 (if loaded
+	   (setq type loaded)))
+       (or (info-foreign-type-definition type ftd)
+           (error "Unknown foreign type: ~S" type))))))
+
+(defun auxiliary-foreign-type (kind name &optional (ftd *target-ftd*))
+  (declare (ignore ftd))
+  (flet ((aux-defn-matches (x)
+           (and (eq (first x) kind) (eq (second x) name))))
+    (let ((in-auxiliaries
+           (or (find-if #'aux-defn-matches *new-auxiliary-types*)
+               (find-if #'aux-defn-matches *auxiliary-type-definitions*))))
+      (if in-auxiliaries
+        (values (third in-auxiliaries) t)))))
+
+(defun %set-auxiliary-foreign-type (kind name defn &optional (ftd *target-ftd*))
+  (declare (ignore ftd))
+  (flet ((aux-defn-matches (x)
+	   (and (eq (first x) kind) (eq (second x) name))))
+    (when (find-if #'aux-defn-matches *new-auxiliary-types*)
+      (error "Attempt to multiple define ~A ~S." kind name))
+    (when (find-if #'aux-defn-matches *auxiliary-type-definitions*)
+      (error "Attempt to shadow definition of ~A ~S." kind name)))
+  (push (list kind name defn) *new-auxiliary-types*)
+  defn)
+
+(defsetf auxiliary-foreign-type %set-auxiliary-foreign-type)
+
+
+(defun ensure-foreign-type (x)
+  (if (typep x 'foreign-type)
+    x
+    (parse-foreign-type x)))
+
+;;; *record-type-already-unparsed* -- internal
+;;;
+;;; Holds the list of record types that have already been unparsed.  This is
+;;; used to keep from outputing the slots again if the same structure shows
+;;; up twice.
+;;; 
+(defvar *record-types-already-unparsed*)
+
+;;; UNPARSE-FOREIGN-TYPE -- public.
+;;; 
+(defun unparse-foreign-type (type)
+  "Convert the foreign-type structure TYPE back into a list specification of
+   the type."
+  (declare (type foreign-type type))
+  (let ((*record-types-already-unparsed* nil))
+    (%unparse-foreign-type type)))
+
+;;; %UNPARSE-FOREIGN-TYPE -- internal.
+;;;
+;;; Does all the work of UNPARSE-FOREIGN-TYPE.  It's seperate because we need
+;;; to recurse inside the binding of *record-types-already-unparsed*.
+;;; 
+(defun %unparse-foreign-type (type)
+  (invoke-foreign-type-method :unparse type))
+
+
+
+
+
+;;;; Foreign type defining stuff.
+
+(defmacro def-foreign-type-translator (name lambda-list &body body &environment env)
+  (expand-type-macro '%def-foreign-type-translator name lambda-list body env))
+
+
+(defun %def-foreign-type-translator (name translator docs)
+  (declare (ignore docs))
+  (setf (info-foreign-type-translator name) translator)
+  (clear-info-foreign-type-definition name)
+  #+nil
+  (setf (documentation name 'foreign-type) docs)
+  name)
+
+
+(defmacro def-foreign-type (name type)
+  "If name is non-NIL, define name to be an alias for the foreign type
+specified by foreign-type-spec. If foreign-type-spec is a named structure
+or union type, additionally defines that structure or union type.
+
+If name is NIL, foreign-type-spec must be a named foreign struct or union
+definition, in which case the foreign structure or union definition is put
+in effect.
+
+Note that there are two separate namespaces for foreign type names, one for
+the names of ordinary types and one for the names of structs and unions.
+Which one name refers to depends on foreign-type-spec in the obvious manner."
+  (with-auxiliary-foreign-types
+    (let ((foreign-type (parse-foreign-type type)))
+      `(eval-when (:compile-toplevel :load-toplevel :execute)
+	 ,@(when *new-auxiliary-types*
+	     `((%def-auxiliary-foreign-types ',*new-auxiliary-types*)))
+	 ,@(when name
+	     `((%def-foreign-type ',name ',foreign-type)))))))
+
+(defun %def-auxiliary-foreign-types (types)
+  (dolist (info types)
+    (destructuring-bind (kind name defn) info
+      (macrolet ((frob (accessor)
+		   `(let ((old (,accessor name)))
+		      (unless (or (null old) (foreign-type-= old defn))
+			(warn "Redefining ~A ~S to be:~%  ~S,~%was:~%  ~S"
+			      kind name defn old))
+		      (setf (,accessor name) defn))))
+	(ecase kind
+	  (:struct (frob info-foreign-type-struct))
+	  (:union (frob info-foreign-type-union))
+	  (:enum (frob info-foreign-type-enum)))))))
+
+(defun %def-foreign-type (name new &optional (ftd *target-ftd*))
+  (ecase (info-foreign-type-kind name ftd)
+    (:primitive
+     (error "~S is a built-in foreign type." name))
+    (:defined
+     (let ((old (info-foreign-type-definition name ftd)))
+       (unless (or (null old) (foreign-type-= new old))
+	 (warn "Redefining ~S to be:~%  ~S,~%was~%  ~S" name
+	       (unparse-foreign-type new) (unparse-foreign-type old)))))
+    (:unknown))
+  (setf (info-foreign-type-definition name ftd) new)
+  (setf (info-foreign-type-kind name ftd) :defined)
+  name)
+
+
+
+
+;;;; Interfaces to the different methods
+
+(defun foreign-type-= (type1 type2)
+  "Return T iff TYPE1 and TYPE2 describe equivalent foreign types."
+  (or (eq type1 type2)
+      (and (eq (foreign-type-class type1)
+	       (foreign-type-class type2))
+	   (invoke-foreign-type-method :type= type1 type2))))
+
+(defun foreign-subtype-p (type1 type2)
+  "Return T iff the foreign type TYPE1 is a subtype of TYPE2.  Currently, the
+   only supported subtype relationships are is that any pointer type is a
+   subtype of (* t), and any array type first dimension will match 
+   (array <eltype> nil ...).  Otherwise, the two types have to be
+   FOREIGN-TYPE-=."
+  (or (eq type1 type2)
+      (invoke-foreign-type-method :subtypep type1 type2)))
+
+(defun foreign-typep (object type)
+  "Return T iff OBJECT is a foreign of type TYPE."
+  (let ((lisp-rep-type (compute-lisp-rep-type type)))
+    (if lisp-rep-type
+	(typep object lisp-rep-type))))
+
+
+(defun compute-naturalize-lambda (type)
+  `(lambda (foreign ignore)
+     (declare (ignore ignore))
+     ,(invoke-foreign-type-method :naturalize-gen type 'foreign)))
+
+(defun compute-deport-lambda (type)
+  (declare (type foreign-type type))
+  (multiple-value-bind
+      (form value-type)
+      (invoke-foreign-type-method :deport-gen type 'value)
+    `(lambda (value ignore)
+       (declare (type ,(or value-type
+			   (compute-lisp-rep-type type)
+			   `(foreign ,type))
+		      value)
+		(ignore ignore))
+       ,form)))
+
+(defun compute-extract-lambda (type)
+  `(lambda (sap offset ignore)
+     (declare (type system-area-pointer sap)
+	      (type unsigned-byte offset)
+	      (ignore ignore))
+     (naturalize ,(invoke-foreign-type-method :extract-gen type 'sap 'offset)
+		 ',type)))
+
+(defun compute-deposit-lambda (type)
+  (declare (type foreign-type type))
+  `(lambda (sap offset ignore value)
+     (declare (type system-area-pointer sap)
+	      (type unsigned-byte offset)
+	      (ignore ignore))
+     (let ((value (deport value ',type)))
+       ,(invoke-foreign-type-method :deposit-gen type 'sap 'offset 'value)
+       ;; Note: the reason we don't just return the pre-deported value
+       ;; is because that would inhibit any (deport (naturalize ...))
+       ;; optimizations that might have otherwise happen.  Re-naturalizing
+       ;; the value might cause extra consing, but is flushable, so probably
+       ;; results in better code.
+       (naturalize value ',type))))
+
+(defun compute-lisp-rep-type (type)
+  (invoke-foreign-type-method :lisp-rep type))
+
+(defun compute-foreign-rep-type (type)
+  (invoke-foreign-type-method :foreign-rep type))
+
+
+
+
+
+
+;;;; Default methods.
+
+(defvar *void-foreign-type* (make-foreign-type :class 'root :bits 0 :alignment 0 :ordinal 0))
+
+(def-foreign-type-method (root :unparse) (type)
+  (if (eq type *void-foreign-type*)
+    :void
+    `(!!unknown-foreign-type!! ,(type-of type))))
+
+(def-foreign-type-method (root :type=) (type1 type2)
+  (declare (ignore type1 type2))
+  t)
+
+(def-foreign-type-method (root :subtypep) (type1 type2)
+  (foreign-type-= type1 type2))
+
+(def-foreign-type-method (root :lisp-rep) (type)
+  (declare (ignore type))
+  nil)
+
+(def-foreign-type-method (root :foreign-rep) (type)
+  (declare (ignore type))
+  '*)
+
+(def-foreign-type-method (root :naturalize-gen) (type foreign)
+  (declare (ignore foreign))
+  (error "Cannot represent ~S typed foreigns." type))
+
+(def-foreign-type-method (root :deport-gen) (type object)
+  (declare (ignore object))
+  (error "Cannot represent ~S typed foreigns." type))
+
+(def-foreign-type-method (root :extract-gen) (type sap offset)
+  (declare (ignore sap offset))
+  (error "Cannot represent ~S typed foreigns." type))
+
+(def-foreign-type-method (root :deposit-gen) (type sap offset value)
+  `(setf ,(invoke-foreign-type-method :extract-gen type sap offset) ,value))
+
+(def-foreign-type-method (root :arg-tn) (type state)
+  (declare (ignore state))
+  (error "Cannot pass foreigns of type ~S as arguments to call-out"
+	 (unparse-foreign-type type)))
+
+(def-foreign-type-method (root :result-tn) (type state)
+  (declare (ignore state))
+  (error "Cannot return foreigns of type ~S from call-out"
+	 (unparse-foreign-type type)))
+
+
+
+
+;;;; The INTEGER type.
+
+(def-foreign-type-class (integer)
+  (signed t :type (member t nil)))
+
+(defvar *unsigned-integer-types*
+  (let* ((a (make-array 65)))
+    (dotimes (i 65 a)
+      (setf (svref a i) (make-foreign-integer-type :signed nil
+						   :bits i
+						   :alignment
+						   (if (= 1 (logcount i))
+                                                     i
+                                                     1))))))
+
+(defvar *signed-integer-types*
+  (let* ((a (make-array 65)))
+    (dotimes (i 65 a)
+      (setf (svref a i) (make-foreign-integer-type :signed t
+						   :bits i
+						   :alignment
+                                                   (if (= 1 (logcount i))
+                                                     i
+                                                     1))))))
+         
+
+(defvar *bool-type* (make-foreign-integer-type :bits 8 :signed #+darwin-target t #-darwin-target nil))
+
+						  
+
+(def-foreign-type-method (integer :unparse) (type)
+  (if (eq type *bool-type*)
+    :<BOOL>
+    (let* ((bits (foreign-integer-type-bits type))
+           (signed (foreign-integer-type-signed type))
+           (alignment (foreign-integer-type-alignment type)))
+      (if (eql alignment 1)
+        (if (eql bits 1)
+          :bit
+          `(:bitfield ,bits))
+        (list (if signed :signed :unsigned) bits)))))
+  
+(def-foreign-type-method (integer :type=) (type1 type2)
+  (and (eq (foreign-integer-type-signed type1)
+	   (foreign-integer-type-signed type2))
+       (= (foreign-integer-type-bits type1)
+	  (foreign-integer-type-bits type2))))
+
+(def-foreign-type-method (integer :lisp-rep) (type)
+  (list (if (foreign-integer-type-signed type) 'signed-byte 'unsigned-byte)
+	(foreign-integer-type-bits type)))
+
+(def-foreign-type-method (integer :foreign-rep) (type)
+  (list (if (foreign-integer-type-signed type) 'signed-byte 'unsigned-byte)
+	(foreign-integer-type-bits type)))
+
+(def-foreign-type-method (integer :naturalize-gen) (type foreign)
+  (declare (ignore type))
+  foreign)
+
+(def-foreign-type-method (integer :deport-gen) (type value)
+  (declare (ignore type))
+  value)
+
+(def-foreign-type-method (integer :extract-gen) (type sap offset)
+  (declare (type foreign-integer-type type))
+  (let ((ref-form
+	 (if (foreign-integer-type-signed type)
+	  (case (foreign-integer-type-bits type)
+	    (8 `(%get-signed-byte ,sap (/ ,offset 8)))
+	    (16 `(%get-signed-word ,sap (/ ,offset 8)))
+	    (32 `(%get-signed-long ,sap (/ ,offset 8)))
+	    (64 `(%%get-signed-longlong ,sap (/ ,offset 8))))
+	  (case (foreign-integer-type-bits type)
+            (1 `(%get-bit ,sap ,offset))
+	    (8 `(%get-unsigned-byte ,sap (/ ,offset 8)))
+	    (16 `(%get-unsigned-word ,sap (/ ,offset 8)))
+	    (32 `(%get-unsigned-long ,sap (/ ,offset 8)))
+	    (64 `(%%get-unsigned-longlong ,sap (/ ,offset 8)))
+	    (t  `(%get-bitfield ,sap ,offset ,(foreign-integer-type-bits type)))))))
+    (or ref-form
+	(error "Cannot extract ~D bit integers."
+	       (foreign-integer-type-bits type)))))
+
+
+
+
+;;;; The BOOLEAN type.
+
+(def-foreign-type-class (boolean :include integer :include-args (signed)))
+
+
+
+(def-foreign-type-method (boolean :lisp-rep) (type)
+  (declare (ignore type))
+  `(member t nil))
+
+(def-foreign-type-method (boolean :naturalize-gen) (type foreign)
+  (declare (ignore type))
+  `(not (zerop ,foreign)))
+
+(def-foreign-type-method (boolean :deport-gen) (type value)
+  (declare (ignore type))
+  `(if ,value 1 0))
+
+
+(def-foreign-type-method (boolean :unparse) (type)
+  `(boolean ,(foreign-boolean-type-bits type)))
+
+
+
+;;;; the FLOAT types.
+
+(def-foreign-type-class (float)
+  (type () :type symbol))
+
+(def-foreign-type-method (float :unparse) (type)
+  (foreign-float-type-type type))
+
+(def-foreign-type-method (float :lisp-rep) (type)
+  (foreign-float-type-type type))
+
+(def-foreign-type-method (float :foreign-rep) (type)
+  (foreign-float-type-type type))
+
+(def-foreign-type-method (float :naturalize-gen) (type foreign)
+  (declare (ignore type))
+  foreign)
+
+(def-foreign-type-method (float :deport-gen) (type value)
+  (declare (ignore type))
+  value)
+
+
+(def-foreign-type-class (single-float :include (float (bits 32))
+				    :include-args (type)))
+
+
+(def-foreign-type-method (single-float :extract-gen) (type sap offset)
+  (declare (ignore type))
+  `(%get-single-float ,sap (/ ,offset 8)))
+
+
+(def-foreign-type-class (double-float :include (float (bits 64))
+				    :include-args (type)))
+
+
+(def-foreign-type-method (double-float :extract-gen) (type sap offset)
+  (declare (ignore type))
+  `(%get-double-float ,sap (/ ,offset 8)))
+
+
+
+
+;;;; The MACPTR type
+
+(def-foreign-type-class (macptr))
+
+
+(def-foreign-type-method (macptr :unparse) (type)
+  (declare (ignore type))
+  'macptr)
+
+(def-foreign-type-method (macptr :lisp-rep) (type)
+  (declare (ignore type))
+  'macptr)
+
+(def-foreign-type-method (macptr :foreign-rep) (type)
+  (declare (ignore type))
+  'macptr)
+
+(def-foreign-type-method (macptr :naturalize-gen) (type foreign)
+  (declare (ignore type))
+  foreign)
+
+(def-foreign-type-method (macptr :deport-gen) (type object)
+  (declare (ignore type))
+  object)
+
+(def-foreign-type-method (macptr :extract-gen) (type sap offset)
+  (declare (ignore type))
+  `(%get-ptr ,sap (/ ,offset 8)))
+
+
+
+;;;; the FOREIGN-VALUE type.
+
+(def-foreign-type-class (foreign-value :include macptr))
+
+(def-foreign-type-method (foreign-value :lisp-rep) (type)
+  (declare (ignore type))
+  nil)
+
+(def-foreign-type-method (foreign-value :naturalize-gen) (type foreign)
+  `(%macptr-foreign ,foreign ',type))
+
+(def-foreign-type-method (foreign-value :deport-gen) (type value)
+  (declare (ignore type))
+  `(foreign-macptr ,value))
+
+
+
+
+;;;; The POINTER type.
+
+(def-foreign-type-class (pointer :include (foreign-value))
+  (to *void-foreign-type* :type (or symbol foreign-type)))
+
+
+
+(def-foreign-type-method (pointer :unparse) (type)
+  (let ((to (foreign-pointer-type-to type)))
+    `(:* ,(if to
+	     (%unparse-foreign-type to)
+	     :void))))
+
+(def-foreign-type-method (pointer :type=) (type1 type2)
+  (let ((to1 (foreign-pointer-type-to type1))
+	(to2 (foreign-pointer-type-to type2)))
+    (if to1
+	(if to2
+	    (foreign-type-= to1 to2)
+	    nil)
+	(null to2))))
+
+(def-foreign-type-method (pointer :subtypep) (type1 type2)
+  (and (foreign-pointer-type-p type2)
+       (let ((to1 (foreign-pointer-type-to type1))
+	     (to2 (foreign-pointer-type-to type2)))
+	 (if to1
+	     (if to2
+		 (foreign-subtype-p to1 to2)
+		 t)
+	     (null to2)))))
+
+(def-foreign-type-method (pointer :deport-gen) (type value)
+  (values
+   `(etypecase ,value
+      (null
+       (%int-to-ptr 0))
+      (macptr
+       ,value)
+      ((foreign ,type)
+       (foreign-sap ,value)))
+   `(or null macptr (foreign ,type))))
+
+
+
+;;;; The MEM-BLOCK type.
+
+
+(def-foreign-type-class (mem-block :include foreign-value))
+
+(def-foreign-type-method (mem-block :extract-gen) (type sap offset)
+  (let* ((nbytes (%foreign-type-or-record-size type :bytes)))
+    `(%composite-pointer-ref ,nbytes ,sap (/ ,offset 8))))
+
+(def-foreign-type-method (mem-block :deposit-gen) (type sap offset value)
+  (let ((bits (foreign-mem-block-type-bits type)))
+    (unless bits
+      (error "Cannot deposit foreigns of type ~S (unknown size)." type))
+    `(%copy-macptr-to-macptr ,value 0 ,sap ,offset ',bits)))
+
+
+
+
+;;;; The ARRAY type.
+
+(def-foreign-type-class (array :include mem-block)
+  (element-type () :type foreign-type)
+  (dimensions () :type list))
+
+
+
+(def-foreign-type-method (array :unparse) (type)
+  `(array ,(%unparse-foreign-type (foreign-array-type-element-type type))
+	  ,@(foreign-array-type-dimensions type)))
+
+(def-foreign-type-method (array :type=) (type1 type2)
+  (and (equal (foreign-array-type-dimensions type1)
+	      (foreign-array-type-dimensions type2))
+       (foreign-type-= (foreign-array-type-element-type type1)
+                       (foreign-array-type-element-type type2))))
+
+(def-foreign-type-method (array :subtypep) (type1 type2)
+  (and (foreign-array-type-p type2)
+       (let ((dim1 (foreign-array-type-dimensions type1))
+	     (dim2 (foreign-array-type-dimensions type2)))
+	 (and (= (length dim1) (length dim2))
+	      (or (and dim2
+		       (null (car dim2))
+		       (equal (cdr dim1) (cdr dim2)))
+		  (equal dim1 dim2))
+	      (foreign-subtype-p (foreign-array-type-element-type type1)
+			       (foreign-array-type-element-type type2))))))
+
+
+
+;;;; The RECORD type.
+
+(defstruct (foreign-record-field
+	     (:print-object
+	      (lambda (field stream)
+		(print-unreadable-object (field stream :type t)
+		  (funcall (formatter "~S ~S~@[ ~D@~D~]")
+			   stream
+			   (foreign-record-field-type field)
+			   (foreign-record-field-name field)
+			   (foreign-record-field-bits field)
+                           (foreign-record-field-offset field))))))
+  (name () :type symbol)
+  (type () :type foreign-type)
+  (bits nil :type (or unsigned-byte null))
+  (offset 0 :type unsigned-byte))
+
+
+
+(defmethod make-load-form ((f foreign-record-field) &optional env)
+  (make-load-form-saving-slots f :environment env))
+
+(def-foreign-type-class (record :include mem-block)
+  (kind :struct :type (member :struct :union :transparent-union))
+  (name nil :type (or symbol null))
+  (fields nil :type list)
+  ;; For, e.g., records defined with #pragma options align=mac68k
+  ;; in effect.  When non-nil, this specifies the maximum alignment
+  ;; of record fields and the overall alignment of the record.
+  (alt-align nil :type (or unsigned-byte null)))
+
+(defmethod make-load-form ((r foreign-record-type) &optional environment)
+  (declare (ignore environment))
+  `(parse-foreign-type ',(unparse-foreign-type r)))
+
+
+(defun parse-foreign-record-type (kind name fields &optional (ftd *target-ftd*))
+  (let* ((result (if name
+                   (or
+                    (ecase kind
+                      (:struct (info-foreign-type-struct name ftd))
+                      ((:union :transparent-union) (info-foreign-type-union name ftd)))
+                    (case kind
+                      (:struct (setf (info-foreign-type-struct name ftd)
+                                     (make-foreign-record-type :name name :kind :struct)))
+                      ((:union :transparent-union)
+                       (setf (info-foreign-type-union name ftd)
+                                     (make-foreign-record-type :name name :kind kind)))))
+                   (make-foreign-record-type :kind kind))))
+    (when fields
+      (multiple-value-bind (parsed-fields alignment bits)
+          (parse-field-list fields kind (foreign-record-type-alt-align result))
+        (let* ((old-fields (foreign-record-type-fields result)))
+          (setf (foreign-record-type-fields result) parsed-fields
+                (foreign-record-type-alignment result) alignment
+                (foreign-record-type-bits result) bits)
+          (when old-fields
+            (unless (record-fields-match old-fields parsed-fields 5)
+              (warn "Redefining ~a ~s fields to be:~%~s~%were~%~s"
+                    kind name parsed-fields old-fields))))))
+    (if name
+      (unless (eq (auxiliary-foreign-type kind name) result)
+        (setf (auxiliary-foreign-type kind name) result)))
+    result))
+
+;;; PARSE-FOREIGN-RECORD-FIELDS -- internal
+;;;
+;;; Used by parse-foreign-type to parse the fields of struct and union
+;;; types.  RESULT holds the record type we are paring the fields of,
+;;; and FIELDS is the list of field specifications.
+;;;
+(defun parse-field-list (fields kind &optional alt-alignment)
+  (collect ((parsed-fields))
+    (let* ((total-bits 0)
+           (overall-alignment 1)
+           (first-field-p t)
+           (attributes (ftd-attributes *target-ftd*))
+           (poweropen-alignment (getf attributes :poweropen-alignment)))
+          
+      (dolist (field fields)
+        (destructuring-bind (var type &optional bits) field
+          (declare (ignore bits))
+          (let* ((field-type (parse-foreign-type type))
+                 (bits (ensure-foreign-type-bits field-type))
+                 (natural-alignment (foreign-type-alignment field-type))
+                 (alignment (if alt-alignment
+                              (min natural-alignment alt-alignment)
+                              (if poweropen-alignment
+                                (if first-field-p
+                                  (progn
+                                    (setq first-field-p nil)
+                                    natural-alignment)
+                                  (min 32 natural-alignment))
+                                natural-alignment)))
+                 (parsed-field
+                  (make-foreign-record-field :type field-type
+                                             :name var)))
+            (parsed-fields parsed-field)
+            (when (null bits)
+              (error "Unknown size: ~S"
+                     (unparse-foreign-type field-type)))
+            (when (null alignment)
+              (error "Unknown alignment: ~S"
+                     (unparse-foreign-type field-type)))
+            (setf overall-alignment (max overall-alignment (if (< alignment 8) 32 alignment)))
+            (ecase kind
+              (:struct
+               (let ((offset (align-offset total-bits alignment)))
+                 (setf (foreign-record-field-offset parsed-field) offset)
+                 (setf (foreign-record-field-bits parsed-field) bits)
+                 (setf total-bits (+ offset bits))))
+              ((:union :transparent-union)
+               (setf total-bits (max total-bits bits)))))))
+      (values (parsed-fields)
+              (or alt-alignment overall-alignment)
+              (align-offset total-bits (or alt-alignment overall-alignment))))))
+            
+
+
+(defun parse-foreign-record-fields (result fields)
+  (declare (type foreign-record-type result)
+	   (type list fields))
+  (multiple-value-bind (parsed-fields alignment bits)
+      (parse-field-list fields (foreign-record-type-kind result) (foreign-record-type-alt-align result))
+    (setf (foreign-record-type-fields result) parsed-fields
+          (foreign-record-type-alignment result) alignment
+          (foreign-record-type-bits result) bits)))
+
+
+(def-foreign-type-method (record :unparse) (type)
+  `(,(case (foreign-record-type-kind type)
+       (:struct :struct)
+       (:union :union)
+       (:transparent-union :transparent-union)
+       (t '???))
+    ,(foreign-record-type-name type)
+    ,@(unless (member type *record-types-already-unparsed* :test #'eq)
+	(push type *record-types-already-unparsed*)
+	(mapcar #'(lambda (field)
+		    `(,(foreign-record-field-name field)
+		      ,(%unparse-foreign-type (foreign-record-field-type field))
+		      ,@(if (foreign-record-field-bits field)
+			    (list (foreign-record-field-bits field)))))
+		(foreign-record-type-fields type)))))
+
+;;; Test the record fields. The depth is limiting in case of cyclic
+;;; pointers.
+(defun record-fields-match (fields1 fields2 depth)
+  (declare (type list fields1 fields2)
+	   (type (mod 64) depth))
+  (labels ((record-type-= (type1 type2 depth)
+	     (and (eq (foreign-record-type-name type1)
+		      (foreign-record-type-name type2))
+		  (eq (foreign-record-type-kind type1)
+		      (foreign-record-type-kind type2))
+		  (= (length (foreign-record-type-fields type1))
+		     (length (foreign-record-type-fields type2)))
+		  (record-fields-match (foreign-record-type-fields type1)
+				       (foreign-record-type-fields type2)
+				       (1+ depth))))
+	   (pointer-type-= (type1 type2 depth)
+	     (let ((to1 (foreign-pointer-type-to type1))
+		   (to2 (foreign-pointer-type-to type2)))
+	       (if to1
+		   (if to2
+		    (or (> depth 10)
+		       (type-= to1 to2 (1+ depth)))
+		       nil)
+		   (null to2))))
+	   (type-= (type1 type2 depth)
+	     (cond ((and (foreign-pointer-type-p type1)
+			 (foreign-pointer-type-p type2))
+		    (or (> depth 10)
+			(pointer-type-= type1 type2 depth)))
+		   ((and (foreign-record-type-p type1)
+			 (foreign-record-type-p type2))
+		    (record-type-= type1 type2 depth))
+		   (t
+		    (foreign-type-= type1 type2)))))
+    (do ((fields1-rem fields1 (rest fields1-rem))
+	 (fields2-rem fields2 (rest fields2-rem)))
+	((or (eq fields1-rem fields2-rem)
+	     (endp fields1-rem)
+             (endp fields2-rem))
+	 (eq fields1-rem fields2-rem))
+      (let ((field1 (first fields1-rem))
+	    (field2 (first fields2-rem)))
+	(declare (type foreign-record-field field1 field2))
+	(unless (and (eq (foreign-record-field-name field1)
+			 (foreign-record-field-name field2))
+		     (eql (foreign-record-field-bits field1)
+			  (foreign-record-field-bits field2))
+		     (eql (foreign-record-field-offset field1)
+			  (foreign-record-field-offset field2))
+		     (let ((field1 (foreign-record-field-type field1))
+			   (field2 (foreign-record-field-type field2)))
+		       (type-= field1 field2 (1+ depth))))
+	  (return nil))))))
+
+(def-foreign-type-method (record :type=) (type1 type2)
+  (and (eq (foreign-record-type-name type1)
+	   (foreign-record-type-name type2))
+       (eq (foreign-record-type-kind type1)
+	   (foreign-record-type-kind type2))
+       (= (length (foreign-record-type-fields type1))
+	  (length (foreign-record-type-fields type2)))
+       (record-fields-match (foreign-record-type-fields type1)
+			    (foreign-record-type-fields type2) 0)))
+
+
+
+;;;; The FUNCTION and VALUES types.
+
+(defvar *values-type-okay* nil)
+
+(def-foreign-type-class (function :include mem-block)
+  (result-type () :type foreign-type)
+  (arg-types () :type list)
+  (stub nil :type (or null function)))
+
+
+
+(def-foreign-type-method (function :unparse) (type)
+  `(function ,(%unparse-foreign-type (foreign-function-type-result-type type))
+	     ,@(mapcar #'%unparse-foreign-type
+		       (foreign-function-type-arg-types type))))
+
+(def-foreign-type-method (function :type=) (type1 type2)
+  (and (foreign-type-= (foreign-function-type-result-type type1)
+		     (foreign-function-type-result-type type2))
+       (= (length (foreign-function-type-arg-types type1))
+	  (length (foreign-function-type-arg-types type2)))
+       (every #'foreign-type-=
+	      (foreign-function-type-arg-types type1)
+	      (foreign-function-type-arg-types type2))))
+
+
+(def-foreign-type-class (values)
+  (values () :type list))
+
+
+
+(def-foreign-type-method (values :unparse) (type)
+  `(values ,@(mapcar #'%unparse-foreign-type
+		     (foreign-values-type-values type))))
+
+(def-foreign-type-method (values :type=) (type1 type2)
+  (and (= (length (foreign-values-type-values type1))
+	  (length (foreign-values-type-values type2)))
+       (every #'foreign-type-=
+	      (foreign-values-type-values type1)
+	      (foreign-values-type-values type2))))
+
+
+
+
+
+;;;; The FOREIGN-SIZE macro.
+
+(defmacro foreign-size (type &optional (units :bits))
+  "Return the size of the foreign type TYPE.  UNITS specifies the units to
+   use and can be either :BITS, :BYTES, or :WORDS."
+  (let* ((foreign-type (parse-foreign-type type))
+         (bits (ensure-foreign-type-bits foreign-type)))
+    (if bits
+      (values (ceiling bits
+                       (ecase units
+                         (:bits 1)
+                         (:bytes 8)
+                         (:words 32))))
+      (error "Unknown size for foreign type ~S."
+             (unparse-foreign-type foreign-type)))))
+
+(defun ensure-foreign-type-bits (type)
+  (or (foreign-type-bits type)
+      (and (typep type 'foreign-record-type)
+           (let* ((name (foreign-record-type-name type)))
+             (and name
+                  (load-record name)
+                  (foreign-type-bits type))))
+      (and (typep type 'foreign-array-type)
+	   (let* ((element-type (foreign-array-type-element-type type))
+		  (dims (foreign-array-type-dimensions type)))
+	     (if (and (ensure-foreign-type-bits element-type)
+		      (every #'integerp dims))
+	       (setf (foreign-array-type-alignment type)
+		     (foreign-type-alignment element-type)
+		     (foreign-array-type-bits type)
+		     (* (align-offset (foreign-type-bits element-type)
+				      (foreign-type-alignment element-type))
+			(reduce #'* dims))))))))
+
+(defun require-foreign-type-bits (type)
+  (or (ensure-foreign-type-bits type)
+      (error "Can't determine attributes of foreign type ~s" type)))
+
+(defun %find-foreign-record (name)
+  (or (info-foreign-type-struct name)
+      (info-foreign-type-union name)
+      (load-record name)))
+
+
+(defun %foreign-type-or-record (type)
+  (if (typep type 'foreign-type)
+    type
+    (if (consp type)
+      (parse-foreign-type type)
+      (or (%find-foreign-record type)
+	  (parse-foreign-type type)))))
+
+(defun %foreign-type-or-record-size (type &optional (units :bits))
+  (let* ((info (%foreign-type-or-record type))
+         (bits (ensure-foreign-type-bits info)))
+    (if bits
+      (values (ceiling bits
+                       (ecase units
+                         (:bits 1)
+                         (:bytes 8)
+                         (:words 32))))
+      (error "Unknown size for foreign type ~S."
+             (unparse-foreign-type info)))))
+
+(defun %find-foreign-record-type-field (type field-name)
+  (ensure-foreign-type-bits type)       ;load the record type if necessary.
+  (let* ((fields (foreign-record-type-fields type)))
+    (or (find field-name  fields :key #'foreign-record-field-name :test #'string-equal)
+                         (error "Record type ~a has no field named ~s.~&Valid field names are: ~&~a"
+                                (foreign-record-type-name type)
+                                field-name
+                                (mapcar #'foreign-record-field-name fields)))))
+
+(defun %foreign-access-form (base-form type bit-offset accessors)
+  (if (null accessors)
+    (invoke-foreign-type-method :extract-gen type base-form bit-offset)
+    (etypecase type
+      (foreign-record-type
+       (let* ((field (%find-foreign-record-type-field type (car accessors))))
+         (%foreign-access-form base-form
+                               (foreign-record-field-type field)
+                               (+ bit-offset (foreign-record-field-offset field))
+                               (cdr accessors))))
+      (foreign-pointer-type
+       (%foreign-access-form
+        (invoke-foreign-type-method :extract-gen type base-form bit-offset)
+        (foreign-pointer-type-to type)
+        0
+        accessors)))))
+
+(defun %foreign-array-access-form (base-form type index-form)
+  (etypecase type
+    ((or foreign-pointer-type foreign-array-type)
+     (let* ((to (foreign-pointer-type-to type))
+            (size (foreign-type-bits to))
+            (bit-offset `(the fixnum (* ,size (the fixnum ,index-form)))))
+       (invoke-foreign-type-method :extract-gen to base-form bit-offset)))))
+
+
+
+
+
+;;;; Naturalize, deport, extract-foreign-value, deposit-foreign-value
+
+(defun naturalize (foreign type)
+  (declare (type foreign-type type))
+  (funcall (coerce (compute-naturalize-lambda type) 'function)
+           foreign type))
+
+(defun deport (value type)
+  (declare (type foreign-type type))
+  (funcall (coerce (compute-deport-lambda type) 'function)
+           value type))
+
+(defun extract-foreign-value (sap offset type)
+  (declare (type macptr sap)
+           (type unsigned-byte offset)
+           (type foreign-type type))
+  (funcall (coerce (compute-extract-lambda type) 'function)
+           sap offset type))
+
+(defun deposit-foreign-value (sap offset type value)
+  (declare (type macptr sap)
+           (type unsigned-byte offset)
+           (type foreign-type type))
+  (funcall (coerce (compute-deposit-lambda type) 'function)
+           sap offset type value))
+
+
+
+(defmacro external (name)
+  "If there is already an EXTERNAL-ENTRY-POINT for the symbol named by name,
+find it and return it. If not, create one and return it.
+
+Try to resolve the entry point to a memory address, and identify the
+containing library.
+
+Be aware that under Darwin, external functions which are callable from C
+have underscores prepended to their names, as in '_fopen'."
+  `(load-eep ,name))
+
+(defmacro external-call (name &rest args)
+  "Call the foreign function at the address obtained by resolving the
+external-entry-point associated with name, passing the values of each arg
+as a foreign argument of type indicated by the corresponding
+arg-type-specifier. Returns the foreign function result (coerced to a
+Lisp object of type indicated by result-type-specifier), or NIL if
+result-type-specifer is :VOID or NIL"
+  `(ff-call (%reference-external-entry-point
+	     (load-time-value (external ,name))) ,@args))
+
+(defmacro ff-call (entry &rest args)
+  "Call the foreign function at address entrypoint passing the values of
+each arg as a foreign argument of type indicated by the corresponding
+arg-type-specifier. Returns the foreign function result (coerced to a
+Lisp object of type indicated by result-type-specifier), or NIL if
+result-type-specifer is :VOID or NIL"
+  (funcall (ftd-ff-call-expand-function *target-ftd*)
+           `(%ff-call ,entry) args))
+	
+	  
+
+(defmethod make-load-form ((eep external-entry-point) &optional env)
+  (declare (ignore env))
+  `(load-eep ,(eep.name eep)))
+
+
+(defmethod print-object ((eep external-entry-point) out)
+  (print-unreadable-object (eep out :type t :identity t)
+    (format out "~s" (eep.name eep))
+    (let* ((addr (eep.address eep))
+	   (container (eep.container eep)))
+      (if addr
+        #+ppc-target
+        (progn
+          #+32-bit-target
+          (format out " (#x~8,'0x) " (logand #xffffffff (ash addr 2)))
+          #+64-bit-target
+          (format out " (#x~16,'0x) " (if (typep addr 'integer)
+                                        (logand #xffffffffffffffff (ash addr 2))
+                                        (%ptr-to-int addr))))
+	#+x8632-target
+	(format out " (#x~8,'0x) " addr)
+        #+x8664-target
+        (format out " (#x~16,'0x) " addr)
+	(format out " {unresolved} "))
+      (when (and container (or (not (typep container 'macptr))
+				    (not (%null-ptr-p container))))
+	(format out "~a" (shlib.soname container))))))
+
+
+
+(defun %cons-foreign-variable (name type &optional container)
+  (%istruct 'foreign-variable nil name type container))
+
+(defmethod make-load-form ((fv foreign-variable) &optional env)
+  (declare (ignore env))
+  `(load-fv ,(fv.name fv) ',(fv.type fv)))
+
+(defmethod print-object ((fv foreign-variable) out)
+  (print-unreadable-object (fv out :type t :identity t)
+    (format out "~s" (fv.name fv))
+    (let* ((addr (fv.addr fv))
+	   (container (fv.container fv)))
+      (if addr
+        #+32-bit-target
+	(format out " (#x~8,'0x) " (logand #xffffffff (%ptr-to-int addr)))
+        #+64-bit-target
+        	(format out " (#x~16,'0x) " (logand #xfffffffffffffffff (%ptr-to-int addr)))
+	(format out " {unresolved} "))
+      (when (and container (or (not (typep container 'macptr))
+				    (not (%null-ptr-p container))))
+	(format out "~a" (shlib.soname container))))))
+
+
+(defmethod print-object ((s shlib) stream)
+  (print-unreadable-object (s stream :type t :identity t)
+    (format stream "~a" (or (shlib.soname s) (shlib.pathname s)))))
+
+#-(or darwin-target windows-target)
+(defun dlerror ()
+  (with-macptrs ((p))
+    (%setf-macptr p (#_dlerror))
+    (unless (%null-ptr-p p) (%get-cstring p))))
+
+(defstruct (external-function-definition (:conc-name "EFD-")
+                                         (:constructor
+                                          make-external-function-definition
+                                          (&key entry-name arg-specs
+                                                result-spec
+                                                (min-args (length arg-specs))))
+                                         )
+  (entry-name "" :type string)
+  (arg-specs () :type list)
+  (result-spec nil :type (or symbol list))
+  (min-args 0 :type fixnum))
+
+
+(defun %external-call-expander (whole env)
+  (declare (ignore env))
+  (destructuring-bind (name &rest args) whole
+    (collect ((call))
+      (let* ((info (or (gethash name (ftd-external-function-definitions
+                                      *target-ftd*))
+                       (error "Unknown external-function: ~s" name)))
+             (external-name (efd-entry-name info))
+             (arg-specs (efd-arg-specs info))
+             (result (efd-result-spec info))
+             (monitor (eq (car args) :monitor-exception-ports)))
+        (when monitor
+          (setq args (cdr args))
+          (call :monitor-exception-ports))
+        (let* ((rtype (parse-foreign-type result)))
+          (if (typep rtype 'foreign-record-type)
+            (call (pop args))))
+        (do* ((specs arg-specs (cdr specs))
+              (args args (cdr args)))
+             ((null specs)
+              (call result)
+              (if args
+                (error "Extra arguments in ~s"  whole)
+                `(external-call ,external-name ,@(call))))
+          (let* ((spec (car specs)))
+            (cond ((eq spec :void)
+                   ;; must be last arg-spec; remaining args should be
+                   ;; keyword/value pairs
+                   (unless (evenp (length args))
+                     (error "Remaining arguments should be keyword/value pairs: ~s"
+                            args))
+                   (do* ()
+                        ((null args))
+                     (call (pop args))
+                     (call (pop args))))
+                  (t
+                   (call spec)
+                   (if args
+                     (call (car args))
+                     (error "Missing arguments in ~s" whole))))))))))
+
+(defun translate-foreign-arg-type (foreign-type-spec)
+  (let* ((foreign-type (parse-foreign-type foreign-type-spec)))
+    (etypecase foreign-type
+      (foreign-pointer-type :address)
+      (foreign-integer-type
+       (let* ((bits (foreign-integer-type-bits foreign-type))
+              (signed (foreign-integer-type-signed foreign-type)))
+         (declare (fixnum bits))
+         (cond ((<= bits 8) (if signed :signed-byte :unsigned-byte))
+               ((<= bits 16) (if signed :signed-halfword :unsigned-halfword))
+               ((<= bits 32) (if signed :signed-fullword :unsigned-fullword))
+               ((<= bits 64) (if signed :signed-doubleword :unsigned-doubleword))
+               (t `(:record ,bits)))))
+      (foreign-float-type
+       (ecase (foreign-float-type-bits foreign-type)
+         (32 :single-float)
+         (64 :double-float)))
+      (foreign-record-type
+       `(:record ,(foreign-record-type-bits foreign-type))))))
+      
+
+(defmacro define-external-function (name (&rest arg-specs) result-spec
+					 &key (min-args (length arg-specs)))
+  (let* ((entry-name nil)
+         (package (find-package (ftd-interface-package-name *target-ftd*)))
+         (arg-keywords (mapcar #'translate-foreign-arg-type arg-specs))
+         (result-keyword (unless (and (symbolp result-spec)
+                                    (eq (make-keyword result-spec) :void))
+                               (translate-foreign-arg-type result-spec))))
+    (when (and (consp result-keyword) (eq (car result-keyword) :record))
+      (push :address arg-keywords)
+      (setq result-keyword nil))
+    (if (consp name)
+      (setq entry-name (cadr name) name (intern (unescape-foreign-name
+                                                 (car name))
+                                                package))
+      (progn
+        (setq entry-name (unescape-foreign-name name)
+              name (intern entry-name package))
+        (if (getf (ftd-attributes *target-ftd*)
+                  :prepend-underscore)
+          (setq entry-name (concatenate 'string "_" entry-name)))))
+    `(progn
+      (setf (gethash ',name (ftd-external-function-definitions *target-ftd*))
+       (make-external-function-definition
+	:entry-name ',entry-name
+	:arg-specs ',arg-keywords
+	:result-spec ',result-keyword
+	:min-args ,min-args))
+      (setf (macro-function ',name) #'%external-call-expander)
+      ',name)))
+
+
+#+darwinppc-target
+(defun open-dylib (name)
+  (with-cstrs ((name name))
+    (#_NSAddImage name (logior #$NSADDIMAGE_OPTION_RETURN_ON_ERROR 
+			       #$NSADDIMAGE_OPTION_WITH_SEARCHING))))
+
+(defparameter *foreign-representation-type-keywords*
+  `(:signed-doubleword :signed-fullword :signed-halfword :signed-byte
+    :unsigned-doubleword :unsigned-fullword :unsigned-halfword :unsigned-byte
+    :address
+    :single-float :double-float
+    :void))
+
+(defun null-coerce-foreign-arg (arg-type-keyword argform)
+  (declare (ignore arg-type-keyword))
+  argform)
+
+(defun null-coerce-foreign-result (result-type-keyword resultform)
+  (declare (ignore result-type-keyword))
+  resultform)
+
+(defun foreign-type-to-representation-type (f)
+  (if (or (member f *foreign-representation-type-keywords*)
+	  (typep f 'unsigned-byte))
+    f
+    (let* ((ftype (if (typep f 'foreign-type)
+                    f
+                    (parse-foreign-type f))))
+      (or
+       (and (eq (foreign-type-class ftype) 'root) :void)	 
+       (typecase ftype
+	 ((or foreign-pointer-type foreign-array-type) :address)
+	 (foreign-double-float-type :double-float)
+	 (foreign-single-float-type :single-float)
+	 (foreign-integer-type
+	  (let* ((signed (foreign-integer-type-signed ftype))
+		 (bits (foreign-integer-type-bits ftype)))
+	    (if signed
+	      (if (<= bits 8)
+		:signed-byte
+		(if (<= bits 16)
+		  :signed-halfword
+		  (if (<= bits 32)
+		    :signed-fullword
+		    (if (<= bits 64)
+		      :signed-doubleword))))
+	      (if (<= bits 8)
+		:unsigned-byte
+		(if (<= bits 16)
+		  :unsigned-halfword
+		  (if (<= bits 32)
+		    :unsigned-fullword
+		    (if (<= bits 64)
+		      :unsigned-doubleword)))))))
+	 (foreign-record-type
+          (if (getf (ftd-attributes *target-ftd*)
+                  :struct-by-value)
+            (let* ((bits (ensure-foreign-type-bits ftype)))
+              (ceiling bits (target-word-size-case
+                             (32 32)
+                             (64 64))))
+          :address)))
+       (error "can't determine representation keyword for ~s" f)))))
+
+(defun foreign-record-accessor-names (record-type &optional prefix)
+  (collect ((accessors))
+    (dolist (field (foreign-record-type-fields record-type) (accessors))
+      (let* ((field-name (append prefix (list (foreign-record-field-name field))))
+	     (field-type (foreign-record-field-type field)))
+	(if (typep field-type 'foreign-record-type)
+	  (dolist (s (foreign-record-accessor-names field-type field-name))
+	    (accessors s))
+	  (accessors field-name))))))
+
+;;; Are all (scalar) fields in the field-list FIELDS floats ?'
+(defun all-floats-in-field-list (fields)
+  (dolist (field fields t)
+    (let* ((field-type (foreign-record-field-type field)))
+      (cond ((typep field-type 'foreign-record-type)
+             (unless (all-floats-in-field-list (foreign-record-type-fields field-type))
+                                     (return nil)))
+            ((typep field-type 'foreign-array-type)
+             (unless (typep (foreign-array-type-element-type field-type) 'foreign-float-type)
+               (return nil)))
+            (t (unless (typep field-type 'foreign-float-type)
+                 (return nil)))))))
+
+;;; Are any (scalar) fields in the field-list FIELDS floats ?
+(defun some-floats-in-field-list (fields)
+  (dolist (field fields)
+    (let* ((field-type (foreign-record-field-type field)))
+      (cond ((typep field-type 'foreign-float-type)
+             (return t))
+            ((typep field-type 'foreign-record-type)
+             (if (some-floats-in-field-list (foreign-record-type-fields field-type))
+               (return t)))
+            ((typep field-type 'foreign-array-type)
+             (if (typep (foreign-array-type-element-type field-type)
+                        'foreign-float-type)
+               (return t)))))))
+
+;;; We don't use foreign type ordinals when cross-compiling,
+;;; so the read-time conditionalization is OK here.
+
+#-windows-target
+(defparameter *canonical-os-foreign-types*
+  '((:struct :timespec)
+    (:struct :stat)
+    (:struct :passwd)
+    #>Dl_info
+    (:array (:struct :pollfd) 1)) )
+
+#+windows-target
+(defparameter *canonical-os-foreign-types*
+  `(#>FILETIME
+    #>SYSTEM_INFO
+    #>HANDLE
+    #>PROCESS_INFORMATION
+    #>STARTUPINFO
+    (:array #>HANDLE 2)
+    #>DWORD
+    (:array #>wchar_t #.#$MAX_PATH)
+    #>fd_set
+    #>DWORD_PTR
+    #>SYSTEMTIME))
+    
+    
+(defun canonicalize-foreign-type-ordinals (ftd)
+  (let* ((canonical-ordinal 0))          ; used for :VOID
+    (flet ((canonicalize-foreign-type-ordinal (spec)
+             (let* ((new-ordinal (incf canonical-ordinal)))
+               (when spec
+                 (let* ((type (parse-foreign-type spec))
+                        (old-ordinal (foreign-type-ordinal type)))
+                   (unless (eql new-ordinal old-ordinal)
+                     (remhash old-ordinal (ftd-ordinal-types ftd))
+                     (setf (foreign-type-ordinal type) new-ordinal)
+                     (note-foreign-type-ordinal type ftd))))
+               new-ordinal)))
+      (canonicalize-foreign-type-ordinal :signed)
+      (canonicalize-foreign-type-ordinal :unsigned)
+      (canonicalize-foreign-type-ordinal #+64-bit-target :long #-64-bit-target nil)
+      (canonicalize-foreign-type-ordinal :address)
+      (canonicalize-foreign-type-ordinal '(:struct :sockaddr_in))
+      (canonicalize-foreign-type-ordinal '(:struct :sockaddr_un))
+      (canonicalize-foreign-type-ordinal '(:struct :linger))
+      (canonicalize-foreign-type-ordinal '(:struct :hostent))
+      (canonicalize-foreign-type-ordinal '(:array :unsigned-long 3))
+      (canonicalize-foreign-type-ordinal '(:* :char))
+      (canonicalize-foreign-type-ordinal '(:struct :in_addr))
+      (canonicalize-foreign-type-ordinal '(:struct :cdb-datum))
+      (canonicalize-foreign-type-ordinal '(:struct :dbm-constant))
+      (canonicalize-foreign-type-ordinal '(:* (:struct :hostent)))
+      (canonicalize-foreign-type-ordinal '(:array :int 2))
+      (canonicalize-foreign-type-ordinal '(:array (:struct :pollfd) 1))
+      (canonicalize-foreign-type-ordinal '(:struct :dirent))
+      (canonicalize-foreign-type-ordinal '(:struct :timeval))
+      (canonicalize-foreign-type-ordinal '(:struct :addrinfo))
+
+      (setq canonical-ordinal (1- max-common-foreign-type-ordinal))
+
+      (dolist (spec *canonical-os-foreign-types*)
+        (canonicalize-foreign-type-ordinal spec))
+      (dolist (spec (ftd-platform-ordinal-types ftd))
+        (canonicalize-foreign-type-ordinal spec)))))
+
+(defun install-standard-foreign-types (ftd)
+  (let* ((*target-ftd* ftd)
+         (natural-word-size (getf (ftd-attributes ftd) :bits-per-word))
+         (long-word-size (or (getf (ftd-attributes ftd) :bits-per-long)
+                             natural-word-size)))
+
+    (def-foreign-type-translator signed (&optional (bits 32))
+      (if (<= bits 64)
+        (svref *signed-integer-types* bits)
+        (make-foreign-integer-type :bits bits)))
+
+
+    (def-foreign-type-translator integer (&optional (bits 32))
+      (if (<= bits 64)
+        (svref *signed-integer-types* bits)
+        (make-foreign-integer-type :bits bits)))
+
+    (def-foreign-type-translator unsigned (&optional (bits 32))
+      (if (<= bits 64)
+        (svref *unsigned-integer-types* bits)
+        (make-foreign-integer-type :bits bits :signed nil)))
+
+    (def-foreign-type-translator bitfield (&optional (bits 1))
+      (make-foreign-integer-type :bits bits :signed nil :alignment 1))
+
+    (def-foreign-type-translator root ()
+      (make-foreign-type :class 'root :bits 0 :alignment 0))
+
+    (def-foreign-type-translator :<BOOL> () *bool-type*)
+
+    (def-foreign-type-translator single-float ()
+      (make-foreign-single-float-type :type 'single-float))
+
+    (def-foreign-type-translator double-float ()
+      (make-foreign-double-float-type :type 'double-float))
+
+    (def-foreign-type-translator macptr ()
+      (make-foreign-macptr-type :bits natural-word-size))
+
+    (def-foreign-type-translator values (&rest values)
+      (unless *values-type-okay*
+        (error "Cannot use values types here."))
+      (let ((*values-type-okay* nil))
+        (make-foreign-values-type
+         :values (mapcar #'parse-foreign-type values))))
+
+    (def-foreign-type-translator function (result-type &rest arg-types)
+      (make-foreign-function-type
+       :result-type (let ((*values-type-okay* t))
+                      (parse-foreign-type result-type))
+       :arg-types (mapcar #'parse-foreign-type arg-types)))
+
+    (def-foreign-type-translator struct (name &rest fields)
+      (parse-foreign-record-type :struct name fields))
+    
+    (def-foreign-type-translator union (name &rest fields)
+      (parse-foreign-record-type :union name fields))
+
+    (def-foreign-type-translator transparent-union (name &rest fields)
+      (parse-foreign-record-type :transparent-union name fields))
+
+    (def-foreign-type-translator array (ele-type &rest dims)
+      (when dims
+	;; cross-compiling kludge. replaces '(or index null)
+        (unless (typep (first dims) `(or
+				      ,(target-word-size-case
+					(32 '(integer 0 #.(expt 2 24)))
+					(64 '(integer 0 #.(expt 2 56))))
+				      null))
+          (error "First dimension is not a non-negative fixnum or NIL: ~S"
+                 (first dims)))
+        (let ((loser (find-if-not #'(lambda (x) (typep x 'index))
+                                  (rest dims))))
+          (when loser
+            (error "Dimension is not a non-negative fixnum: ~S" loser))))
+	
+      (let* ((type (parse-foreign-type ele-type))
+             (pair (cons type dims)))
+        (declare (dynamic-extent pair))
+        (ensure-foreign-type-bits type)
+        (or (gethash pair (ftd-array-types *target-ftd*))
+            (setf (gethash (cons type dims) (ftd-array-types *target-ftd*))
+                  
+                  (make-foreign-array-type
+                   :element-type type
+                   :dimensions dims
+                   :alignment (foreign-type-alignment type)
+                   :bits (if (and (ensure-foreign-type-bits type)
+                                  (every #'integerp dims))
+                           (* (align-offset (foreign-type-bits type)
+                                            (foreign-type-alignment type))
+                              (reduce #'* dims))))))))
+
+    (def-foreign-type-translator * (to)
+      (let* ((ftd *target-ftd*)
+             (to (if (eq to t) *void-foreign-type* (parse-foreign-type to ftd))))
+        (or (gethash to (ftd-pointer-types ftd))
+            (setf (gethash to (ftd-pointer-types *target-ftd*))
+                  (make-foreign-pointer-type
+                   :to to
+                   :bits natural-word-size)))))
+    
+    (def-foreign-type-translator boolean (&optional (bits 32))
+      (make-foreign-boolean-type :bits bits :signed nil))
+
+    (def-foreign-type signed-char (signed 8))
+    (def-foreign-type signed-byte (signed 8))
+    (def-foreign-type short (signed 16))
+    (def-foreign-type signed-halfword short)
+    (def-foreign-type int (signed 32))
+    (def-foreign-type signed-fullword int)
+    (def-foreign-type signed-short (signed 16))
+    (def-foreign-type signed-int (signed 32))
+    (def-foreign-type signed-doubleword (signed 64))
+    (def-foreign-type char #-darwin-target (unsigned 8)
+                      #+darwin-target (signed 8))
+    (def-foreign-type unsigned-char (unsigned 8))
+    (def-foreign-type unsigned-byte (unsigned 8))
+    (def-foreign-type unsigned-short (unsigned 16))
+    (def-foreign-type unsigned-halfword unsigned-short)
+    (def-foreign-type unsigned-int (unsigned 32))
+    (def-foreign-type unsigned-fullword unsigned-int)
+    (def-foreign-type unsigned-doubleword (unsigned 64))
+    (def-foreign-type bit (bitfield 1))
+
+    (def-foreign-type float single-float)
+    (def-foreign-type double double-float)
+
+    (%def-foreign-type :void *void-foreign-type*)
+    (def-foreign-type address (* :void))
+    (let* ((signed-long-type (parse-foreign-type
+                              `(:signed ,long-word-size)))
+           (unsigned-long-type (parse-foreign-type
+                                `(:unsigned ,long-word-size))))
+      (%def-foreign-type :long signed-long-type ftd)
+      (%def-foreign-type :signed-long signed-long-type ftd)
+      (%def-foreign-type :unsigned-long unsigned-long-type ftd))
+    ;;
+    ;; Defining the handful of foreign structures that are used
+    ;; to build Clozure CL here ensures that all backends see appropriate
+    ;; definitions of them.
+    ;;
+    ;; Don't use DEF-FOREIGN-TYPE here; this often runs too
+    ;; early in the cold load for that to work.
+    ;;
+    (parse-foreign-type
+     '(:struct :cdb-datum
+       (:data (* t))
+       (:size (:unsigned 32)))
+     ftd)
+    (parse-foreign-type
+     '(:struct :dbm-constant
+       (:class (:unsigned 32))
+       (:pad (:unsigned 32))
+       (:value
+        (:union nil
+         (:s32 (:signed 32))
+         (:u32 (:unsigned 32))
+         (:single-float :float)
+         (:double-float :double))))
+     ftd)
+    ;; This matches the xframe-list struct definition in
+    ;; "ccl:lisp-kernel;constants.h"
+    (parse-foreign-type
+     '(:struct :xframe-list
+       (:this (:* t #|(struct :ucontext)|#))
+       (:prev (:* (:struct  :xframe-list))))
+    ftd)
+  ))
+
+(defmethod make-load-form ((p macptr) &optional env)
+  (declare (ignore env))
+  (let* ((value (%ptr-to-int p)))
+    (unless (or (< value 65536)
+                (>= value (- (ash 1 target::nbits-in-word) 65536)))
+      (error "~&~s can't be referenced as a constant because its address contains more than 16 significant bits." p))
+    (if (zerop value)
+      '+null-ptr+
+      `(%int-to-ptr ,value))))
+
+
+
+
Index: /branches/new-random/lib/format.lisp
===================================================================
--- /branches/new-random/lib/format.lisp	(revision 13309)
+++ /branches/new-random/lib/format.lisp	(revision 13309)
@@ -0,0 +1,2627 @@
+;;; -*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Functions to implement FORMAT.
+;;;
+
+(in-package "CCL")
+
+;;; Special variables local to FORMAT
+;;; why do these have top-level bindings ????? - seems wrong or at least unnecessary
+
+(defvar *format-control-string* ""
+  "The current FORMAT control string")
+
+(defvar *format-index* 0
+  "The current index into *format-control-string*")
+
+(defvar *format-length* 0
+  "The length of the current FORMAT control string")
+
+(defvar *format-arguments* ()
+  "Arguments to the current call of FORMAT")
+
+(defvar *format-original-arguments* ()
+  "Saved arglist from top-level FORMAT call for ~* and ~@*")
+
+(defvar *format-arguments-variance* nil
+  "Non-NIL only during compile-time scanning of a format string, in which case it is the
+number of additional elements at the front of *format-arguments* that may be already used
+up at runtime.  I.e. the actual *format-arguments* may be anything between *format-arguments*
+and (nthcdr *format-arguments-variance* *format-arguments*)")
+
+(def-standard-initial-binding *format-stream-stack* nil "A stack of string streams for collecting FORMAT output")
+
+(defvar *format-pprint* nil
+  "Has a pprint format directive (~W ~I ~_ ~:T) or logical-block directive been seen?")
+
+(defvar *format-justification-semi* nil
+  "Has a ~<...~:;...~> been seen?")
+
+(defvar *format-colon-rest* nil
+  )
+
+;;; prevent circle checking rest args. Really EVIL when dynamic-extent
+(def-standard-initial-binding *format-top-level* nil)
+
+
+;;; ERRORS
+
+;;; Since errors may occur while an indirect control string is being
+;;; processed, i.e. by ~? or ~{~:}, some sort of backtrace is necessary
+;;; in order to indicate the location in the control string where the
+;;; error was detected.  To this end, errors detected by format are
+;;; signalled by throwing a list of the form ((control-string args))
+;;; to the tag FORMAT-ERROR.  This throw will be caught at each level
+;;; of indirection, and the list of error messages re-thrown with an
+;;; additional message indicating that indirection was present CONSed
+;;; onto it.  Ultimately, the last throw will be caught by the top level
+;;; FORMAT function, which will then signal an error to the Slisp error
+;;; system in such a way that all the errror messages will be displayed
+;;; in reverse order.
+
+(defun format-error (complaint &rest args)
+  (throw 'format-error
+         (list (list "~1{~:}~%~S~%~V@T^" complaint args
+                    *format-control-string* (1+ *format-index*)))))
+
+
+;;; MACROS
+
+;;; This macro establishes the correct environment for processing
+;;; an indirect control string.  CONTROL-STRING is the string to
+;;; process, and FORMS are the forms to do the processing.  They 
+;;; invariably will involve a call to SUB-FORMAT.  CONTROL-STRING
+;;; is guaranteed to be evaluated exactly once.
+(eval-when (compile eval #-bccl load)
+
+; does this need to exist?????
+#|| ; put it out of its misery
+(defmacro format-with-control-string (control-string &rest forms)
+  `(let ((string (if (simple-string-p ,control-string)
+                     ,control-string
+                     (coerce ,control-string 'simple-base-string))))
+        (declare (simple-string string))
+        (let ((error (catch 'format-error
+                            (let ((*format-control-string* string)
+                                  (*format-length* (length string))
+                                  (*format-index* 0))
+                                 ,@forms
+                                 nil))))
+          
+             (when error
+                   (throw 'format-error
+                          (cons (list "While processing indirect control string~%~S~%~V@T^"
+                                      *format-control-string*
+                                      (1+ *format-index*))
+                                error))))))
+||#
+(defmacro format-indirect-error (error)
+  `(throw 'format-error
+         (cons (list "While processing indirect control string~%~S~%~V@T^"
+                     *format-control-string*
+                     (1+ *format-index*))
+               ,error)))
+
+
+(defmacro get-a-format-string-stream ()
+  '(or (pop *format-stream-stack*) (make-string-output-stream :element-type 'base-char))) ; ??
+
+;;; This macro rebinds collects output to the standard output stream
+;;; in a string.  For efficiency, we avoid consing a new stream on
+;;; every call.  A stack of string streams is maintained in order to
+;;; guarantee re-entrancy.
+
+(defmacro with-format-string-output (stream-sym &rest forms)
+  `(let ((,stream-sym nil))
+     (unwind-protect
+       (progn
+         (setq ,stream-sym (get-a-format-string-stream))
+         ,@forms
+         (prog1
+           (get-output-stream-string ,stream-sym)
+           (push ,stream-sym *format-stream-stack*)))
+       (when ,stream-sym (file-position ,stream-sym 0)))))
+
+;;; This macro decomposes the argument list returned by PARSE-FORMAT-OPERATION.
+;;; PARMVAR is the list of parameters.  PARMDEFS is a list of lists of the form
+;;; (<var> <default>).  The FORMS are evaluated in an environment where each 
+;;; <var> is bound to either the value of the parameter supplied in the 
+;;; parameter list, or to its <default> value if the parameter was omitted or
+;;; explicitly defaulted.
+
+(defmacro with-format-parameters (parmvar parmdefs &body  body &environment env)
+  (do ((parmdefs parmdefs (cdr parmdefs))
+       (bindings () (cons `(,(caar parmdefs) (or (if ,parmvar (pop ,parmvar))
+                                                 ,(cadar parmdefs)))
+                          bindings)))
+      ((null parmdefs)
+       (multiple-value-bind (forms decls) (parse-body body env)
+         `(let ,(nreverse bindings)
+            ,@decls
+            (when ,parmvar
+              (format-error "Too many parameters"))
+            ,@forms)))))
+
+
+
+;;; Returns the index of the first occurrence of the specified character
+;;; between indices START (inclusive) and END (exclusive) in the control
+;;; string.
+
+
+(defmacro format-find-char (char start end)
+  `(%str-member  ,char *format-control-string*
+                   ,start ,end))
+
+
+) ;end of eval-when for macros
+
+;;; CONTROL STRING PARSING 
+
+;;; The current control string is kept in *format-control-string*. 
+;;; The variable *format-index* is the position of the last character
+;;; processed, indexing from zero.  The variable *format-length* is the
+;;; length of the control string, which is one greater than the maximum
+;;; value of *format-index*.  
+
+
+;;; Gets the next character from the current control string.  It is an
+;;; error if there is none.  Leave *format-index* pointing to the
+;;; character returned.
+
+(defun format-nextchar ()
+  (let ((index (%i+ 1 *format-index*)))    
+    (if (%i< (setq *format-index* index) *format-length*)
+      (schar *format-control-string* index)
+      (format-error "Syntax error"))))
+
+
+
+;;; Returns the current character, i.e. the one pointed to by *format-index*.
+
+(defmacro format-peek ()
+  `(schar *format-control-string* *format-index*))
+
+
+
+
+;;; Attempts to parse a parameter, starting at the current index.
+;;; Returns the value of the parameter, or NIL if none is found. 
+;;; On exit, *format-index* points to the first character which is
+;;; not a part of the recognized parameter.
+
+(defun format-get-parameter (ch)
+  (case ch
+    (#\# (format-nextchar)
+     (let ((n (or *format-arguments-variance* 0))
+           (len (length *format-arguments*)))
+       (declare (fixnum n len))
+       (if (eql n 0)
+         len
+         `(the (integer ,(- len n) ,len) (length *format-arguments*)))))
+    ((#\V #\v)
+     (prog1 (pop-format-arg) (format-nextchar)))
+    (#\' (prog1 (format-nextchar) (format-nextchar)))
+    (t (cond ((or (eq ch #\-) (eq ch #\+) (digit-char-p ch))
+              (let ((neg-parm (eq ch #\-)))
+                (unless (setq ch (digit-char-p ch))
+                  (unless (setq ch (digit-char-p (format-nextchar)))
+                    (format-error "Illegal parameter")))
+                (do ((number ch (+ ch (* number 10))))
+                    ((not (setq ch (digit-char-p (format-nextchar))))
+                     (if neg-parm (- number) number)))))
+             (t nil)))))
+
+(defun format-skip-parameter (ch) ; only caller is parse-format-operation
+  "Might someday want to add proper format error checking for negative 
+      parameters"
+  (let ()
+    (case ch
+      ((#\V #\v #\#)
+       (format-nextchar))
+      (#\' (format-nextchar) (format-nextchar))
+      (#\,)
+      (t (when (or (eq ch #\-) (eq ch #\+)) (format-nextchar))
+         (while (digit-char-p (format-nextchar)))))))
+
+(defun format-no-semi (char &optional colon atsign)
+  (when *format-justification-semi*
+    (format-error "~~~:[~;:~]~:[~;@~]~c illegal in this context" colon atsign char))
+  (setq *format-pprint* t))
+
+;;; Parses a format directive, including flags and parameters.  On entry,
+;;; *format-index* should point to the "~" preceding the command.  On
+;;; exit, *format-index* points to the command character itself.
+;;; Returns the list of parameters, the ":" flag, the "@" flag, and the
+;;; command character as multiple values.  Explicitly defaulted parameters
+;;; appear in the list of parameters as NIL.  Omitted parameters are simply 
+;;; not included in the list at all.
+
+(defun parse-format-operation (&optional get-params) ; only caller is format-find-command
+  (let ((ch (format-nextchar)) parms colon atsign)
+    (when (or (digit-char-p ch)
+              ;(%str-member ch ",#Vv'"))
+              (memq ch '(#\- #\, #\# #\V #\v #\')))      
+      (cond (get-params
+             (setq parms (list (format-get-parameter ch)))
+             (until (neq (setq ch (format-peek)) #\,)
+               (setq ch (format-nextchar))
+               (push (format-get-parameter ch) parms)))
+            (t (setq parms t)  ; tell caller there were some so we get correct error msgs
+               (format-skip-parameter ch)
+               (until (neq (setq ch (format-peek)) #\,)
+                 (setq ch (format-nextchar))
+                 (format-skip-parameter ch)))))
+    ; allow either order
+    (case ch
+      (#\: (setq colon t ch (format-nextchar))
+           (when (eq ch #\@)
+             (setq atsign t ch (format-nextchar))))
+      (#\@ (setq atsign t ch (format-nextchar))
+           (when (eq ch #\:)
+             (setq colon t ch (format-nextchar)))))
+    (values (if (consp parms) (nreverse parms) parms)
+            colon
+            atsign
+            ch)))
+
+
+;;; Starting at the current value of *format-index*, finds the first
+;;; occurrence of one of the specified directives. Embedded constructs,
+;;; i.e. those inside ~(~), ~[~], ~{~}, or ~<~>, are ignored.  And error is
+;;; signalled if no satisfactory command is found.  Otherwise, the
+;;; following are returned as multiple values:
+;;;
+;;;     The value of *format-index* at the start of the search
+;;;     The index of the "~" character preceding the command
+;;;     The parameter list of the command
+;;;     The ":" flag
+;;;     The "@" flag
+;;;     The command character
+;;;
+;;; Implementation note:  The present implementation is not particulary
+;;; careful with storage allocation.  It would be a good idea to have
+;;; a separate function for skipping embedded constructs which did not
+;;; bother to cons parameter lists and then throw them away. This issue has been addressed. (akh)
+;;;
+;;; We go to some trouble here to use POSITION for most of the searching.
+;;; God only knows why!!!!
+
+;; and interesting note - the only caller who wants parameters is format-get-segments for
+;; ~< .... ~n:; ...~>
+(defun format-find-command (command-list &optional get-params evil-commands)
+  (let* ((start *format-index*)
+         (length *format-length*)
+         tilde)
+    (loop
+      (setq tilde (format-find-char #\~ *format-index* length))
+      (if (not tilde) (format-error "Expecting one of ~S" command-list))
+      (setq *format-index* tilde)
+      (multiple-value-bind (parms colon atsign command)
+                           (parse-format-operation get-params)
+        (when (memq command command-list)
+          (return (values start tilde parms colon atsign command)))
+        (when (and evil-commands
+                   (or (memq command  '(#\w #\_ #\i #\W #\I))
+                       (and colon (memq command '(#\t #\T)))))
+          (format-error "Illegal in this context"))
+        (case command
+          (#\{ (format-nextchar) (format-find-command '(#\})))
+          (#\( (format-nextchar) (format-find-command '(#\))))
+          (#\[ (format-nextchar) (format-find-command '(#\])))
+          (#\< (format-nextchar) 
+               (multiple-value-bind (prev tilde parms colon atsign cmd)
+                   (format-find-command '(#\>))
+                 (declare (ignore prev tilde parms atsign cmd))
+                 (if (and evil-commands colon)
+                     (format-error "Logical-block directive not allowed inside justification directive"))))
+          ((#\} #\> #\) #\])
+           (format-error "No matching bracket")))))))
+
+(defun format-find-command-no-params (command-list &key (colon t) (atsign t))
+  (multiple-value-bind (prev tilde parms colon-flag atsign-flag command)
+                       (format-find-command command-list)
+    (with-format-parameters parms ()
+      (format-no-flags (and (not colon) colon-flag) (and (not atsign) atsign-flag)))
+    (values prev tilde command colon-flag atsign-flag)))
+
+;;; This is the FORMAT top-level function.
+
+(defun format (stream control-string &rest format-arguments)
+  (declare (dynamic-extent format-arguments))
+  (if (null stream)
+    (with-output-to-string (s)
+			   (apply #'format s control-string format-arguments))
+    (if (stringp stream)
+      (with-output-to-string (s stream)
+			     (apply #'format s control-string format-arguments))
+      (let ((*format-top-level* t))
+	(when (xp-structure-p stream)(setq stream (xp-stream-stream stream))) ; for xp tests only! They call format on a structure
+	(setq stream (if (eq stream t)
+		       *standard-output*
+		       (require-type stream 'stream)))     
+	(if (functionp control-string)
+	  (apply control-string stream format-arguments)
+	  (let* ((control-string (ensure-simple-string control-string))
+                 (*format-control-string* control-string)
+                 (*format-pprint* nil)
+                 (*format-justification-semi* nil))
+            (declare (type simple-string control-string))
+	    (cond
+	      ;; Try to avoid pprint overhead in this case.
+	      ((not (position #\~ control-string))
+	       (write-string control-string stream))
+	      ((and (or *print-pretty* *print-circle*)
+		    (not (typep stream 'xp-stream)))
+	       (maybe-initiate-xp-printing
+		#'(lambda (s o)
+		    (do-sub-format-1 s o))
+		stream format-arguments))
+	      (t 
+	       (let ((*format-original-arguments* format-arguments)
+		     (*format-arguments* format-arguments)
+		     (*format-colon-rest* 'error)) ; what should this be??
+		 (do-sub-format stream))))))
+	nil))))
+
+(defun format-to-string (string control-string &rest format-arguments)
+  (declare (dynamic-extent format-arguments))
+  (if string
+    (with-output-to-string (stream string)
+      (apply #'format stream control-string format-arguments))
+    (with-output-to-string (stream)
+      (apply #'format stream control-string format-arguments))))
+
+(defun do-sub-format (stream)
+  (let (errorp)
+    (setq errorp
+          (catch 'format-error
+            (catch 'format-escape 
+              (sub-format stream 0 (length *format-control-string*)))
+            nil))    
+    (when errorp
+      (error "~%~:{~@?~%~}" (nreverse errorp)))))
+
+
+
+;;; This function does the real work of format.  The segment of the control
+;;; string between indiced START (inclusive) and END (exclusive) is processed
+;;; as follows: Text not part of a directive is output without further
+;;; processing.  Directives are parsed along with their parameters and flags,
+;;; and the appropriate handlers invoked with the arguments COLON, ATSIGN, and
+;;; PARMS. 
+;;;
+
+;;; POP-FORMAT-ARG also defined in l1-format
+
+; in l1-format
+(def-standard-initial-binding *logical-block-xp* nil)
+
+(without-duplicate-definition-warnings
+ (defun pop-format-arg (&aux (args *format-arguments*) (xp *logical-block-xp*) (av *format-arguments-variance*))
+   (when (and (null args) (null xp))
+     (format-error "Missing argument"))
+   (when xp
+     (if (null av)
+       (when (pprint-pop-check+ args xp)    ; gets us level and length stuff in logical block
+         (throw 'logical-block nil))
+       ;; Could record that might exit here, but nobody cares.
+       #+no (note-format-scan-option *logical-block-options*)))
+   (if (or (null av) (eql av 0))
+     (progn
+       (setq *format-arguments* (cdr args))
+       (%car args))
+     (let ((types (loop for x in args as i from 0 below av
+                    collect (nx-form-type x))))
+       (when (eql av (length args))
+         (setq *format-arguments-variance* (1- av)))
+       (setq *format-arguments* (cdr args))
+       `(the (or ,@types) (car *format-arguments*))))))
+
+; SUB-FORMAT is now defined in L1-format.lisp
+; DEFFORMAT is also defined there.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; pretty-printing stuff
+;;; 
+
+(defformat #\W format-write (stream colon atsign)
+  (format-no-semi #\W)
+  (let ((arg (pop-format-arg)))
+    (cond (atsign
+       (let ((*print-level* nil)
+             (*print-length* nil))
+         (if colon
+           (let ((*print-pretty* t))
+             (write-1 arg stream))
+           (write-1 arg stream))))
+      (t (if colon
+           (let ((*print-pretty* t))
+             (write-1 arg stream))
+           (write-1 arg stream))))))
+
+(defformat #\I format-indent (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (declare (ignore atsign))
+  (format-no-semi #\I)
+  (with-format-parameters parms ((n 0))
+    (pprint-indent (if colon :current :block) n stream)))
+
+(defformat #\_ format-conditional-newline (stream colon atsign)
+  (format-no-semi #\_)
+  (let ((option
+         (cond (atsign
+                (cond (colon  :mandatory)
+                      (t :miser)))
+               (colon :fill)
+               (t :linear))))
+    (pprint-newline option stream)))
+
+;;; Tabulation  ~T 
+
+(defformat #\T format-tab (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (when colon
+    (format-no-semi #\T t))
+  (with-format-parameters parms ((colnum 1) (colinc 1))
+    (cond ((or (typep stream 'xp-stream) (xp-structure-p stream))
+           (let ((kind (if colon
+                           (if atsign :section-relative :section)
+                           (if atsign :line-relative :line))))
+             (cond ((xp-structure-p stream)
+                    (pprint-tab+ kind colnum colinc stream))
+                   ((typep stream 'xp-stream)
+                    (pprint-tab+ kind colnum colinc
+                                 (slot-value stream 'xp-structure))))))
+          ((not colon)
+           (pprint-tab-not-pretty stream colnum colinc atsign)))))
+
+(defun pprint-tab-not-pretty (stream colnum colinc &optional atsign)
+  (let* ((position (column stream))
+         (count (if atsign
+                  (if position
+                    (if (zerop colinc)
+                      colnum (+ colnum (mod (- (+ position colnum)) colinc)))
+                    colnum)
+                  (if position
+                    (if (<= colnum position)
+                      (if (zerop colinc)
+                        0 (- colinc (mod (- position colnum) colinc)))
+                      (- colnum position))
+                    2))))
+    (while (> count 0)
+      (write-string "                                                                                "
+                           stream :start 
+                           0 :end (min count 80))
+      (setq count (- count 80)))))
+
+
+;;; ~/ call function
+(defformat #\/ format-call-function (stream colon atsign &rest parms)
+  (let* ((string *format-control-string*)
+         (ipos (1+ *format-index*))
+         (epos (format-find-char #\/ ipos *format-length*)))    
+    ; the spec is DUMB here - it requires that : and :: be treated the same
+    (when (not epos) (format-error "Unmatched ~~/"))
+    (let ((cpos (format-find-char #\: ipos epos))
+          package)
+      (cond (cpos 
+             (setq package (or (find-package (string-upcase (%substr string ipos cpos)))
+                               (format-error "Unknown package")))
+             (when (eql #\: (schar string (%i+ 1 cpos)))
+               (setq cpos (%i+ cpos 1)))
+             (setq ipos (%i+ cpos 1)))
+            (t (setq package (find-package "CL-USER"))))
+      (let ((thing (intern (string-upcase (%substr string ipos epos)) package)))
+        (setq *format-index* epos) ; or 1+ epos?
+	(apply thing stream (pop-format-arg) colon atsign parms)))))
+
+;;; Conditional case conversion  ~( ... ~)
+
+#| coral's old version
+(defformat #\( format-capitalization (stream colon atsign)
+  (format-nextchar)
+  (multiple-value-bind (prev tilde) (format-find-command-no-params '(#\)))
+   (let* (finished
+          (string (with-format-string-output stream
+                    (setq finished (catch 'format-escape (sub-format stream prev tilde) t)))))
+     (write-string
+         (cond ((and atsign colon)
+                (nstring-upcase string))
+               (colon
+                (nstring-capitalize string))
+               (atsign
+                (let ((strlen (length string)))
+                     ;; Capitalize the first word only
+                     (nstring-downcase string)
+                     (do ((i 0 (1+ i)))
+                         ((or (<= strlen i) (alpha-char-p (char string i)))
+                          (setf (char string i) (char-upcase (char string i)))
+                          string))))
+               (t (nstring-downcase string)))
+         stream :start 
+         0 :end (length string))
+     (unless finished (throw 'format-escape nil)))))
+
+|#
+
+(defformat #\( format-capitalization (stream colon atsign)
+  (format-nextchar)
+  (multiple-value-bind (prev tilde) (format-find-command-no-params '(#\)))
+    (let (catchp)
+      (cond ((typep stream 'xp-stream)
+             (let ((xp (slot-value stream 'xp-structure)))
+               (push-char-mode xp (cond ((and colon atsign) :UP)
+				         (colon :CAP1)
+				         (atsign :CAP0)
+				         (T :DOWN)))
+               (setq catchp
+                     (catch 'format-escape
+                       (sub-format stream prev tilde)
+                       nil))
+	       (pop-char-mode xp)))
+            (t
+             (let* ((string (with-format-string-output stream                      
+                              (setq catchp (catch 'format-escape
+                                             (sub-format stream prev tilde)
+                                             nil)))))
+               (write-string
+                (cond ((and atsign colon)
+                       (nstring-upcase string))
+                      (colon
+                       (nstring-capitalize string))
+                      (atsign
+                       ;; Capitalize the first word only
+                       (nstring-downcase string)
+                       (dotimes (i (length string) string)
+                         (let ((ch (char string i)))
+                           (when (alpha-char-p ch)
+                             (setf (char string i) (char-upcase ch))
+                             (return string)))))
+                      (t (nstring-downcase string)))         
+                stream :start 
+                0 :end (length string)))))
+      (when catchp
+        (throw 'format-escape catchp))
+      )))
+
+;;; Up and Out (Escape)  ~^
+
+(defformat #\^ format-escape (stream colon atsign &optional p1 p2 p3)
+  (declare (ignore stream))
+  (when atsign
+    (format-error "FORMAT command ~~~:[~;:~]@^ is undefined" colon))
+  (when (cond (p3 (etypecase p2
+                    (real
+                     (<= p1 p2 p3))
+                    (character
+                     (char< p1 p2 p3))))
+              (p2 (equal p1 p2))
+              (p1 (eql p1 0))
+              (t (null (if colon *format-colon-rest* *format-arguments*))))
+    (throw 'format-escape (if colon 'format-colon-escape t))))
+
+;;; Conditional expression  ~[ ... ]
+
+
+;;; ~[  - Maybe these guys should deal with ~^ too - i.e. catch format-escape etc.
+;;; but I cant think of a case where just throwing to the { catcher fails
+
+(defun format-untagged-condition (stream)
+  (let ((test (pop-format-arg)))
+    (unless (integerp test)
+      (format-error "Argument to ~~[ must be integer - ~S" test))
+    (do ((count 0 (1+ count)))
+        ((= count test)
+         (multiple-value-bind (prev tilde cmd colon atsign)
+                              (format-find-command-no-params '(#\; #\]) :atsign nil)
+           (declare (ignore colon atsign))
+           (sub-format stream prev tilde)
+           (unless (eq cmd #\])
+             (format-find-command '(#\])))))
+      (multiple-value-bind (prev tilde cmd colon atsign)
+                           (format-find-command-no-params '(#\; #\]) :atsign nil)
+        (declare (ignore prev tilde atsign))
+        (when (eq cmd #\]) (return))
+        (format-nextchar)
+        (when colon
+          (multiple-value-bind (prev tilde cmd colon atsign)
+                               (format-find-command-no-params '(#\; #\]))
+            (declare (ignore colon atsign))
+            (sub-format stream prev tilde)
+            (unless (eq cmd #\])
+              (format-find-command-no-params '(#\]))))
+          (return))))))
+
+
+;;; ~@[
+
+(defun format-funny-condition (stream)
+  (multiple-value-bind (prev tilde) (format-find-command-no-params '(#\]))
+    (if *format-arguments*
+      (if (car *format-arguments*)
+        (sub-format stream prev tilde)
+        (pop *format-arguments*))
+      (format-error "Missing argument"))))
+
+
+;;; ~:[ 
+
+(defun format-boolean-condition (stream)
+  (multiple-value-bind (prev tilde command) (format-find-command-no-params '(#\; #\]))
+    (when (eq command #\])
+      (format-error "Two clauses separated by ~~; are required for ~~:["))
+    (format-nextchar)
+    (if (pop-format-arg)
+      (multiple-value-bind (prev tilde)
+          (format-find-command-no-params '(#\]) :colon nil :atsign nil)
+        (sub-format stream prev tilde))
+      (progn
+        (sub-format stream prev tilde)
+        (format-find-command-no-params '(#\]))))))
+
+
+(defformat #\[ format-condition (stream colon atsign &optional p)
+  (when p (push p *format-arguments*))
+  (format-nextchar)
+  (cond (colon
+         (when atsign
+           (format-error  "~~:@[ undefined"))
+         (format-boolean-condition stream))
+        (atsign
+         (format-funny-condition stream))
+        (t (format-untagged-condition stream))))
+
+
+;;; Iteration  ~{ ... ~}
+
+(defformat #\{ format-iteration (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (with-format-parameters parms ((max-iter -1))
+    (format-nextchar)
+    (multiple-value-bind (prev tilde end-cmd end-colon end-atsign)
+                         (format-find-command-no-params '(#\}) :atsign nil)
+      (declare (ignore end-cmd end-atsign))
+      (if (= prev tilde)
+        ;; Use an argument as the control string if ~{~} is empty
+        (let ((string (pop-format-arg)))
+          (cond ((stringp string)
+                 (when (not (simple-string-p string)) ; fix here too
+                   (setq string (coerce string 'simple-string))))
+                ((not (functionp string))
+                 (format-error "Control string is not a string or function")))          
+          (let ((error 
+                 (catch 'format-error
+                   (cond
+                    ((stringp string)
+                     (let* ((length (length (the simple-string string)))
+                            (*format-control-string* string)
+                            (*format-length* length)
+                            (*format-index* 0))
+                       (format-do-iteration stream 0 length
+                                            max-iter colon atsign end-colon)))
+                    (t ;(functionp string)
+                     (format-do-iteration stream string nil 
+                                          max-iter colon atsign end-colon)))
+                   nil)))
+            (when error (format-indirect-error error))))
+        (format-do-iteration stream prev tilde 
+                             max-iter colon atsign end-colon)))))
+
+
+;;; The two catch tags FORMAT-ESCAPE and FORMAT-COLON-ESCAPE are needed here
+;;; to correctly implement ~^ and ~:^.  The former aborts only the current
+;;; iteration, but the latter aborts the entire iteration process.
+;;; ~{ arg is a list  ~:{ arg is list of sublists, ~@{  arg is spread ~:@{ spread lists
+;;; We have nuked two catch tags. Instead throw two different values:
+;;; T if ~^ and 'format-colon-escape if ~:^
+
+(defun format-do-iteration (stream start end max-iter colon atsign at-least-once-p)
+  (flet ((do-iteration-1 (stream start end colon at-least-once-p)
+           (let (catchp)
+             (do* ((count 0 (1+ count)))
+                  ((or (= count max-iter)
+                       (and (null *format-arguments*)
+                            (if (= count 0) (not at-least-once-p) t))))
+               (setq catchp
+                     (catch 'format-escape
+                       (if colon
+                         (let* ((args (unless (and at-least-once-p (null *format-arguments*))
+                                        (pop-format-arg)))
+                                (*format-top-level* nil)
+                                (*format-colon-rest* *format-arguments*)
+                                (*format-arguments* args)
+                                (*format-original-arguments* args))
+                           (unless (listp *format-arguments*)
+                             (report-bad-arg *format-arguments* 'list))
+                           (if (functionp start)
+                             (apply start stream args)
+                             (sub-format stream start end)))
+                         (let ((*format-original-arguments* *format-arguments*))
+                           (if (functionp start)
+                             (setq *format-arguments* (apply start stream *format-arguments*))
+                             (sub-format stream start end))))
+                       nil))
+               (when (or (eq catchp 'format-colon-escape)
+                         (and catchp (null colon)))
+                 (return-from do-iteration-1  nil))))))
+      (if atsign
+        (do-iteration-1 stream start end colon at-least-once-p)        
+        ; no atsign - munch on first arg
+        (let* ((*format-arguments* (pop-format-arg))
+               (*format-top-level* nil)
+               (*format-original-arguments* *format-arguments*))
+          (unless (listp *format-arguments*)
+            (report-bad-arg *format-arguments* 'list))
+          (do-iteration-1 stream start end colon at-least-once-p)))))
+  
+
+;;; Justification  ~< ... ~>
+
+;;; Parses a list of clauses delimited by ~; and terminated by ~>.
+;;; Recursively invoke SUB-FORMAT to process them, and return a list
+;;; of the results, the length of this list, and the total number of
+;;; characters in the strings composing the list.
+
+
+(defun format-get-trailing-segments ()
+  (format-nextchar)
+  (multiple-value-bind (prev tilde parms colon atsign cmd)
+                       (format-find-command '(#\; #\>) nil T)
+    (with-format-parameters parms ()
+      (when colon
+        (format-error "~~:; allowed only after first segment in ~~<"))
+      (format-no-flags nil atsign))
+    (let ((str (catch 'format-escape
+                 (with-format-string-output stream
+                   (sub-format stream prev tilde)))))      
+      (if (stringp str)
+        (if (eq cmd #\;)
+          (multiple-value-bind
+            (segments numsegs numchars)
+            (format-get-trailing-segments)
+            (values (cons str segments)
+                    (1+ numsegs)
+                    (+ numchars
+                       (length str))))
+          (values (list str)
+                  1
+                  (length str)))
+        (progn
+          (unless (eq cmd #\>) (format-find-command '(#\>) nil T))
+          (values () 0 0))))))
+
+
+;;; Gets the first segment, which is treated specially.  Call 
+;;; FORMAT-GET-TRAILING-SEGMENTS to get the rest.
+
+(defun format-get-segments ()
+  (let (ignore)
+    (declare (ignore-if-unused ignore)) ; why??
+    (multiple-value-bind (prev tilde parms colon atsign cmd)
+                         (format-find-command '(#\; #\>) nil T) ; skipping
+      (when atsign
+        (format-error "Atsign flag not allowed"))
+      ;(setq *format-arguments* blech)
+      (let ((first-seg (catch 'format-escape
+                         (with-format-string-output stream
+                           (sub-format stream prev tilde)))))
+        (if (stringp first-seg)
+          (if (eq cmd #\;)
+            (progn
+              (when parms
+                (setq *format-index* tilde)
+                ; now get the parameters if any - do this way cause of the V thingies
+                ; maybe only necessary in the : case
+                (multiple-value-setq (ignore ignore parms)
+                                     (format-find-command '(#\; #\>) t T)))              
+              (multiple-value-bind
+                (segments numsegs numchars)
+                (format-get-trailing-segments)
+                (if colon
+                  (values first-seg parms segments numsegs numchars)
+                  (values nil nil (cons first-seg segments)
+                          (1+ numsegs)
+                          (+ (length first-seg) numchars)))))
+            (values nil nil (list first-seg) 1 (length first-seg)))
+          (progn
+            (unless (eq cmd #\>) (format-find-command '(#\>) nil T))
+            (values nil nil () 0 0)))))))
+
+
+#|
+;;; Given the total number of SPACES needed for padding, and the number
+;;; of padding segments needed (PADDINGS), returns a list of such segments.
+;;; We try to allocate the spaces equally to each segment.  When this is
+;;; not possible, we allocate the left-over spaces randomly, to improve the
+;;; appearance of many successive lines of justified text.
+;;; 
+;;; Query:  Is this right?  Perhaps consistency might be better for the kind
+;;; of applications ~<~> is used for.
+
+(defun make-pad-segs (spaces paddings)
+  (do* ((extra-space () (and (plusp extra-spaces)
+                             (< (random (float 1)) (/ segs extra-spaces))))
+        (result () (cons (if extra-space (1+ min-space) min-space) result))
+        (min-space (truncate spaces paddings))
+        (extra-spaces (- spaces (* paddings min-space))
+                      (if extra-space (1- extra-spaces) extra-spaces))
+        (segs paddings (1- segs)))
+       ((zerop segs) result)))
+|#
+(defun make-pad-segs (spaces segments)
+  (multiple-value-bind (min-space extra-spaces) (truncate spaces segments)
+    (declare (fixnum min-space extra-spaces))
+    (let* ((result (make-list segments :initial-element min-space))
+           (res result))
+      (setq min-space (1+ min-space))
+      (dotimes (i extra-spaces)
+        (rplaca res min-space)
+        (setq res (%cdr res)))
+      result)))
+
+;;; Determine the actual width to be used for a field requiring WIDTH
+;;; characters according to the following rule:  If WIDTH is less than or
+;;; equal to MINCOL, use WIDTH as the actual width.  Otherwise, round up 
+;;; to MINCOL + k * COLINC for the smallest possible positive integer k.
+
+(defun format-round-columns (width mincol colinc)
+  (if (< width mincol)
+    (+ width (* colinc (ceiling (- mincol width) colinc)))
+    width))
+
+(defun format-justification-round-columns (width mincol colinc)
+  (if (< width mincol)
+    mincol
+    (+ mincol (* colinc (ceiling (- width mincol) colinc)))))
+
+(defformat #\< format-justification (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (multiple-value-bind (start tilde ecmd ecolon eatsign)
+                       (format-find-command-no-params '(#\>)) ; bumps format-index
+    (declare (ignore tilde ecmd))
+    (cond
+     (ecolon
+      (format-logical-block stream colon atsign eatsign start *format-index* parms))
+     (t (setq *format-index* start)
+        (with-format-parameters parms ((mincol 0) (colinc 1) (minpad 0) (padchar #\space))
+          (unless (integerp mincol)
+            (format-error "Mincol must be an integer - ~S" mincol))
+          (unless (and (integerp colinc) (plusp colinc))
+            (format-error "Colinc must be a positive integer - ~S" colinc))
+          (unless (integerp minpad)
+            (format-error "Minpad must be an integer - ~S" minpad))
+          (unless (characterp padchar)
+            (if (typep padchar `(integer 0 #.char-code-limit))
+              (setq padchar (code-char padchar))
+              (format-error "Padchar must be a character or integer from 0 to ~a - ~S"
+                            char-code-limit padchar)))
+          (format-nextchar)
+          (multiple-value-bind (special-arg special-parms segments numsegs numchars)
+                               (format-get-segments)
+            (when (= numsegs 1) (setq minpad 0))
+            (when segments
+              (let* ((padsegs (+ (if (or colon (= numsegs 1)) 1 0)
+                                 (1- numsegs)
+                                 (if atsign 1 0)))
+                     (width (format-justification-round-columns (+ numchars (* minpad padsegs))
+                                                  mincol colinc))
+                     (spaces (if (and atsign (not colon) (= numsegs 1)) ;dirty but works
+                                 (list 0 (- width numchars))
+                                 (append (if (or colon (= numsegs 1)) () '(0))
+                                         (make-pad-segs (- width numchars) padsegs)
+                                         (if atsign () '(0))))))
+                (when special-arg
+                  (if *format-pprint*
+                      (format-error "Justification illegal in this context"))
+                  (setq *format-justification-semi* t)
+                  (with-format-parameters special-parms ((spare 0)
+                                                         (linel (stream-line-length stream)))
+                      
+                    (let ((pos (column stream)))
+                      (when (> (+ pos width spare) linel)
+                        (stream-write-entire-string stream special-arg)))))
+                (do ((segs segments (cdr segs))
+                     (spcs spaces (cdr spcs)))
+                    ((null segs) (dotimes (i (car spcs)) (write-char padchar stream)))
+                  (dotimes (i (car spcs)) (write-char padchar stream))
+                  (stream-write-entire-string stream (car segs)))))))))))
+
+
+(defun format-logical-block (stream colon atsign end-atsign start end &rest parms)
+  (declare (ignore parms))
+  (flet ((format-check-simple (str)
+           (when (and str (or (%str-member #\~ str) (%str-member #\newline str)))
+             (format-error "Suffix and prefix must be simple")))
+         (first-block-p (start)
+           (let* ((*format-index* 0))
+             (loop
+               (parse-format-operation)
+               (when (eq (format-peek) #\<)
+                 (cond ((eq *format-index* start)
+                        (return t))
+                       (t (return nil))))))))
+    (format-no-semi #\<)
+    (let ((format-string *format-control-string*)
+          (prefix (if colon "(" ""))
+          (suffix (if colon ")" ""))
+          body-string start1 tilde ignore colon1 atsign1 per-line-p)
+      (declare (ignore-if-unused ignore colon1))
+      (setq *format-index* start)
+      (multiple-value-setq (start1 tilde ignore colon1 atsign1)
+        (format-find-command  '(#\; #\>)))
+      (setq body-string (%substr format-string (1+ start) tilde))
+      (when (not (eql *format-index* end)) ; > 1 segment
+        (setq prefix body-string)
+        (if atsign1 (setq per-line-p t))
+        (multiple-value-setq (start1 tilde)
+          (format-find-command '(#\; #\>)))
+        (setq body-string (%substr format-string (1+ start1) tilde))
+        (when (neq *format-index* end)
+          (multiple-value-setq (start1 tilde)(format-find-command  '(#\; #\>)))
+          (setq suffix (%substr format-string (1+ start1) tilde))
+          (when (neq *format-index* end)
+            (format-error "Too many chunks"))))
+      (when end-atsign (setq body-string (format-fill-transform body-string)))
+      (format-check-simple prefix)
+      (format-check-simple suffix)
+      (let ((args (if (not atsign)
+                    ; This piece of garbage is needed to avoid double length counting from (formatter ...) things
+                    ; but also to allow (flet . t) not to barf.
+                    ; Was formerly simply  (if *format-arguments* (pop-format-arg))
+                    ; Actually wanna not count the arg iff the ~< is at the top level
+                    ; in a format string i.e. "is this the first ~< in THIS string?"                    
+                    (when *format-arguments*
+                      (if  (and (listp *format-arguments*)
+                                (first-block-p start))
+                        (pop *format-arguments*)  ; dont count
+                        (pop-format-arg))) ; unless not listp or not first
+                    (prog1 *format-arguments*
+                      (setq *format-arguments* nil))))
+            (*format-control-string* body-string)
+            (*format-top-level* (and atsign *format-top-level*)))
+        (let ((*logical-block-p* t)
+              (xp-struct (cond ((xp-structure-p stream) stream)
+                               ((typep stream 'xp-stream)
+                                (slot-value stream 'xp-structure)))))
+          ; lets avoid unnecessary closures
+          (cond (xp-struct (logical-block-sub xp-struct args  prefix suffix per-line-p atsign))
+                (t (maybe-initiate-xp-printing
+                    #'(lambda (s o)
+                        (logical-block-sub s o  prefix suffix per-line-p atsign))
+                    stream args))))))))
+
+
+    
+; flet?
+(defun logical-block-sub (stream args  prefix suffix per-line-p atsign)
+  ;(push (list args body-string) barf)
+  (let ((circle-chk (not (or *format-top-level* (and atsign (eq *current-length* -1)))))) ; i.e. ~<~@<
+    (let ((*current-level* (1+ *current-level*)) ; these are for pprint
+          (*current-length* -1))
+      (declare (special *current-level* *current-length*))
+      (unless (check-block-abbreviation stream args circle-chk) ;(neq args *format-original-arguments*)) ;??
+        (start-block stream prefix per-line-p suffix)
+        (let ((*logical-block-xp* stream)    ; for pop-format-arg
+              (my-stream (if (xp-structure-p stream) (get-xp-stream stream) stream)))
+          (catch 'logical-block
+            (do-sub-format-1 my-stream args)))
+        (end-block stream suffix)))))
+
+; bash in fill conditional newline after white space (except blanks after ~<newline>)
+; I think this is silly!
+(defun format-fill-transform (string)
+  (let ((pos 0)(end (length (the string string)))(result "") ch)
+    (while (%i< pos end)
+      (let ((wsp-pos (min (or (%str-member #\space string pos) end)
+                          (or (%str-member #\tab string pos) end)))
+            (yes nil))
+        (when (%i< wsp-pos end)
+          (when (not (and (%i> wsp-pos 1)
+                          (eq (schar string (%i- wsp-pos 1)) #\newline)
+                          (or (eq (setq ch (schar string (%i- wsp-pos 2))) #\~)
+                              (and (%i> wsp-pos 2)
+                                   (memq ch '(#\: #\@))
+                                   (eq (schar string (%i- wsp-pos 3)) #\~)))))
+            (setq yes t))
+          (loop 
+            (while (%i< wsp-pos end)
+              (setq ch (schar string wsp-pos))
+              (when (Not (%str-member ch wsp)) (return))
+              (setq wsp-pos (%i+ 1 wsp-pos)))
+            (return)))
+        (setq result (%str-cat result (%substr string pos  wsp-pos) (if yes "~:_" "")))
+      (setq pos wsp-pos)))
+    result))
+
+
+;;;;some functions needed for dealing with floats
+
+;;;; Floating Point printing
+;;;
+;;;  Written by Bill Maddox
+;;;
+;;;
+;;;
+;;; FLONUM-TO-STRING (and its subsidiary function FLOAT-STRING) does most of 
+;;; the work for all printing of floating point numbers in the printer and in
+;;; FORMAT.  It converts a floating point number to a string in a free or 
+;;; fixed format with no exponent.  The interpretation of the arguments is as 
+;;; follows:
+;;;
+;;;     X        - The floating point number to convert, which must not be
+;;;                negative.
+;;;     WIDTH    - The preferred field width, used to determine the number
+;;;                of fraction digits to produce if the FDIGITS parameter
+;;;                is unspecified or NIL.  If the non-fraction digits and the
+;;;                decimal point alone exceed this width, no fraction digits
+;;;                will be produced unless a non-NIL value of FDIGITS has been
+;;;                specified.  Field overflow is not considerd an error at this
+;;;                level.
+;;;     FDIGITS  - The number of fractional digits to produce. Insignificant
+;;;                trailing zeroes may be introduced as needed.  May be
+;;;                unspecified or NIL, in which case as many digits as possible
+;;;                are generated, subject to the constraint that there are no
+;;;                trailing zeroes.
+;;;     SCALE    - If this parameter is specified or non-NIL, then the number
+;;;                printed is (* x (expt 10 scale)).  This scaling is exact,
+;;;                and cannot lose precision.
+;;;     FMIN     - This parameter, if specified or non-NIL, is the minimum
+;;;                number of fraction digits which will be produced, regardless
+;;;                of the value of WIDTH or FDIGITS.  This feature is used by
+;;;                the ~E format directive to prevent complete loss of
+;;;                significance in the printed value due to a bogus choice of
+;;;                scale factor.
+;;;
+;;; Most of the optional arguments are for the benefit for FORMAT and are not
+;;; used by the printer.
+;;;
+;;; Returns:
+;;; (VALUES DIGIT-STRING DIGIT-LENGTH LEADING-POINT TRAILING-POINT DECPNT)
+;;; where the results have the following interpretation:
+;;;
+;;;     DIGIT-STRING    - The decimal representation of X, with decimal point.
+;;;     DIGIT-LENGTH    - The length of the string DIGIT-STRING.
+;;;     LEADING-POINT   - True if the first character of DIGIT-STRING is the
+;;;                       decimal point.
+;;;     TRAILING-POINT  - True if the last character of DIGIT-STRING is the
+;;;                       decimal point.
+;;;     POINT-POS       - The position of the digit preceding the decimal
+;;;                       point.  Zero indicates point before first digit.
+;;;     NZEROS          - number of zeros after point
+;;;
+;;; WARNING: For efficiency, there is a single string object *digit-string*
+;;; which is modified destructively and returned as the value of
+;;; FLONUM-TO-STRING.  Thus the returned value is not valid across multiple 
+;;; calls.
+;;;
+;;; NOTE:  FLONUM-TO-STRING goes to a lot of trouble to guarantee accuracy.
+;;; Specifically, the decimal number printed is the closest possible 
+;;; approximation to the true value of the binary number to be printed from 
+;;; among all decimal representations  with the same number of digits.  In
+;;; free-format output, i.e. with the number of digits unconstrained, it is 
+;;; guaranteed that all the information is preserved, so that a properly-
+;;; rounding reader can reconstruct the original binary number, bit-for-bit, 
+;;; from its printed decimal representation. Furthermore, only as many digits
+;;; as necessary to satisfy this condition will be printed.
+;;;
+;;;
+;;; FLOAT-STRING actually generates the digits for positive numbers.  The
+;;; algorithm is essentially that of algorithm Dragon4 in "How to Print 
+;;; Floating-Point Numbers Accurately" by Steele and White.  The current 
+;;; (draft) version of this paper may be found in [CMUC]<steele>tradix.press.
+;;; DO NOT EVEN THINK OF ATTEMPTING TO UNDERSTAND THIS CODE WITHOUT READING 
+;;; THE PAPER!
+
+
+
+
+(defun flonum-to-string (n &optional width fdigits scale)
+  (let ((*print-radix* nil))
+    (cond ((zerop n)(values "" 0 0))
+          ((and (not (or width fdigits scale))
+                (double-float-p n)
+                ; cheat for the only (?) number that fails to be aesthetically pleasing
+                (= n 1e23))
+           (values "1" 24 23))
+          (t (let ((string (make-array 12 :element-type 'base-char
+                                       :fill-pointer 0 :adjustable t)))
+               (multiple-value-bind (sig exp)(integer-decode-float n)
+                 (float-string string sig exp (integer-length sig) width fdigits scale)))))))
+
+;;; if width given and fdigits nil then if exponent is >= 0 returns at
+;;; most width-1 digits if exponent is < 0 returns (- width (- exp) 1)
+;;; digits if fdigits given width is ignored, returns fdigits after
+;;; (implied) point The Steele/White algorithm can produce a leading
+;;; zero for 1e23 which lies exactly between two double floats -
+;;; rounding picks the float whose rational is
+;;; 99999999999999991611392. This guy wants to print as
+;;; 9.999999999999999E+22. The untweaked algorithm generates a leading
+;;; zero in this case.  (actually wants to print as 1e23!)  If we
+;;; choose s such that r < s - m/2, and r = s/10 - m/2 (which it does
+;;; in this case) then r * 10 < s => first digit is zero and
+;;; (remainder (* r 10) s) is r * 10 = new-r, 10 * m = new-m new-r = s
+;;; - new-m/2 so high will be false and she won't round up we do r *
+;;; (expt 2 (- e (- scale))) and s * (expt 5 (- scale)) i.e. both less
+;;; by (expt 2 (- scale))
+
+(defun float-string (string f e p &optional width fdigits scale)
+  (macrolet ((nth-digit (n) `(%code-char (%i+ ,n (%char-code #\0)))))    
+    (let ((r f)(s 1)(m- 1)(m+ 1)(k 0) cutoff roundup (mm nil))
+      (when (= f (if (eql p 53) #.(ash 1 52) (ash 1 (1- p))))
+        (setq mm t))
+      (when (or (null scale)(zerop scale))
+        ; approximate k
+        (let ((fudge 0))
+          (setq fudge (truncate (*  (%i+ e p) .301)))
+          (when (neq fudge 0)
+            (setq k fudge)
+            (setq scale (- k)))))
+      (when (and scale (not (eql scale 0)))      
+        (if (minusp scale)
+          (setq s (* s (5-to-e  (- scale))))
+          (let ((scale-factor (5-to-e scale)))
+            (setq r (* r scale-factor))
+            (setq m+ scale-factor)
+            (when mm (setq m- scale-factor)))))
+      (let ((shift (- e (if scale (- scale) 0))))
+        (declare (fixnum shift))
+        ;(print (list e scale shift))
+        (cond ((> shift 0)
+               (setq r (ash f shift))
+               (setq m+ (ash m+ shift))
+               (when mm (setq m- (ash m- shift))))
+              ((< shift 0)
+               (setq s (ash s (- shift))))))
+      (when mm
+        (setq m+ (+ m+ m+))
+        (setq r (+ r r))
+        (setq s (+ s s)))    
+      (let ((ceil (ceiling s 10))(fudge 1))
+        (while (< r ceil)
+          (setq k (1- k))
+          (setq r (* r 10))
+          (setq fudge (* fudge 10)))
+        (when (> fudge 1)
+          (setq m+ (* m+ fudge))
+          (when mm (setq m- (* m- fudge)))))    
+      (let ((2r (+ r r)))
+        (loop
+          (let ((2rm+ (+ 2r m+)))          
+            (while
+              (if (not roundup)  ; guarantee no leading zero
+                (> 2rm+ (+ s s))
+                (>=  2rm+ (+ s s)))
+              (setq s (* s 10))
+              (setq k (1+ k))))
+          (when (not (or fdigits width))(return))
+          (cond 
+           (fdigits (setq cutoff (- fdigits)))
+           (width
+            (setq cutoff
+                  (if (< k 0) (- 1 width)(1+ (- k width))))
+            ;(if (and fmin (> cutoff (- fmin))) (setq cutoff (- fmin)))
+            ))
+          (let ((a (if cutoff (- cutoff k) 0))
+                (y s))
+            (DECLARE (FIXNUM A))
+            (if (>= a 0)
+              (when (> a 0)(setq y (* y (10-to-e a))))
+              (setq y (ceiling y (10-to-e (the fixnum (- a))))))
+            (when mm (setq m- (max y m-)))
+            (setq m+ (max y m+))
+            (when (= m+ y) (setq roundup t)))
+          (when (if (not roundup)   ; tweak as above
+                  (<= (+ 2r m+)(+ s s))
+                  (< (+ 2r m+)(+ s s)))
+            (return))))
+      (let* ((h k)
+             (half-m+ (* m+ 5))  ; 10 * m+/2
+             (half-m- (if mm (* m- 5)))
+             u high low 
+             )
+        ;(print (list r s m+ roundup))
+        (unless (and fdigits (>= (- k) fdigits))
+          (loop
+            (setq k (1- k))
+            (multiple-value-setq (u r) (truncate (* r 10) s))          
+            (setq low (< r (if mm half-m- half-m+)))
+            (setq high 
+                  (if (not roundup)
+                    (> r (- s half-m+))
+                    (>= r (- s half-m+))))                   
+            (if (or low high)
+              (return)
+              (progn
+                (vector-push-extend (nth-digit u) string)))
+            (when mm (setq half-m- (* half-m- 10) ))
+            (setq half-m+ (* half-m+ 10)))
+          ;(print (list r s  high low h k))
+          (vector-push-extend
+           (nth-digit (cond
+                       ((and low (not high)) u) 
+                       ((and high (not low))(+ u 1))
+                       
+                       (t ;(and high low)
+                        (if (<= (+ r r) s) u (1+ u)))))
+           string))
+        ; second value is exponent, third is exponent - # digits generated
+        (values string h k)))))
+
+
+(defparameter integer-powers-of-10 (make-array (+ 12 (floor 324 12))))
+
+; e better be positive
+(defun 10-to-e (e)
+  (declare (fixnum e)(optimize (speed 3)(safety 0)))
+  (if (> e 335)
+    (* (10-to-e 334) (10-to-e (%i- e 334)))
+    (if (< e 12)
+      (svref integer-powers-of-10 e)
+      (multiple-value-bind (q r) (truncate e 12)
+        (declare (fixnum q r))        
+        (if (eql r 0)
+          (svref integer-powers-of-10 (%i+ q 11))
+          (* (svref integer-powers-of-10 r)
+             (svref integer-powers-of-10 (%i+ q 11))))))))
+
+
+(let ((array integer-powers-of-10))
+  (dotimes (i 12)
+    (setf (svref array i)  (expt 10 i)))
+  (dotimes (i (floor 324 12))
+    (setf (svref array (+ i 12)) (expt 10 (* 12 (1+ i))))))
+#|
+(defun 10-to-e (e)
+  (ash (5-to-e e) e))
+|#
+      
+
+
+
+;;; Given a non-negative floating point number, SCALE-EXPONENT returns a
+;;; new floating point number Z in the range (0.1, 1.0] and and exponent
+;;; E such that Z * 10^E is (approximately) equal to the original number.
+;;; There may be some loss of precision due the floating point representation.
+;;; JUST do the EXPONENT since thats all we use
+
+
+(defconstant long-log10-of-2 0.30103d0)
+
+#| 
+(defun scale-exponent (x)
+  (if (floatp x )
+      (scale-expt-aux (abs x) 0.0d0 1.0d0 1.0d1 1.0d-1 long-log10-of-2)
+      (report-bad-arg x 'float)))
+
+#|this is the slisp code that was in the place of the error call above.
+  before floatp was put in place of shortfloatp.
+      ;(scale-expt-aux x (%sp-l-float 0) (%sp-l-float 1) %long-float-ten
+      ;                %long-float-one-tenth long-log10-of-2)))
+|#
+
+; this dies with floating point overflow (?) if fed least-positive-double-float
+
+(defun scale-expt-aux (x zero one ten one-tenth log10-of-2)
+  (let ((exponent (nth-value 1 (decode-float x))))
+    (if (= x zero)
+      (values zero 1)
+      (let* ((e (round (* exponent log10-of-2)))
+             (x (if (minusp e)		;For the end ranges.
+                  (* x ten (expt ten (- -1 e)))
+                  (/ x ten (expt ten (1- e))))))
+        (do ((d ten (* d ten))
+             (y x (/ x d))
+             (e e (1+ e)))
+            ((< y one)
+             (do ((m ten (* m ten))
+                  (z y (* z m))
+                  (e e (1- e)))
+                 ((>= z one-tenth) (values x e)))))))))
+|#
+
+(defun scale-exponent (n)
+  (let ((exp (nth-value 1 (decode-float n))))
+    (values (round (* exp long-log10-of-2)))))
+
+
+;;; Page  ~|
+
+(defformat #\| format-page (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (format-no-flags colon atsign)
+  (with-format-parameters parms ((repeat-count 1))
+    (declare (fixnum repeat-count))
+    (dotimes (i repeat-count) (write-char #\page stream))))
+
+
+(defun format-eat-whitespace ()
+  (do* ((i *format-index* (1+ i))
+        (s *format-control-string*)
+        (n *format-length*))
+       ((or (= i n)
+            (not (whitespacep (schar s i))))
+        (setq *format-index* (1- i)))))
+
+(defun format-newline (stream colon atsign parms)
+  (with-format-parameters parms ()
+    (cond (colon
+           (when atsign
+             (format-error "~:@<newline> is undefined")))
+          (atsign (terpri stream) (format-eat-whitespace))
+          (t (format-eat-whitespace)))))
+  
+(defformat  #\newline format-newline (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (format-newline stream colon atsign parms))
+
+(defformat #\return format-newline (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (format-newline stream colon atsign parms))
+
+;;; Indirection  ~?
+
+(defformat #\? format-indirection (stream colon atsign)
+  (format-no-flags colon nil)
+  (let ((string (pop-format-arg)))
+    (unless (or (stringp string)(functionp string))
+      (format-error "Indirected control string is not a string or function"))
+    (when (and (stringp string) (not (simple-string-p string)))
+      (setq string (coerce string 'simple-string)))
+    (catch 'format-escape
+      (let ((error 
+             (catch 'format-error
+               (cond 
+                ((stringp string)
+                 (let* ((length (length (the simple-string string)))
+                        (*format-control-string* string)
+                        (*format-length* length)
+                        (*format-index* 0))
+                    (if atsign
+                      (sub-format stream 0 length)
+                      (let ((args (pop-format-arg)))
+                        (let ((*format-top-level* nil)
+                              (*format-arguments* args)
+                              (*format-original-arguments* args))
+                          (sub-format stream 0 length))))))
+                (T ;(functionp string)
+                 (if (not atsign)
+                   (apply string stream (pop-format-arg))
+                   ; account for the args it eats
+                   (setq *format-arguments* (apply string stream *format-arguments*)))))
+               nil)))
+        (when error (format-indirect-error error))))))
+
+
+
+
+;;; Ascii  ~A
+
+(defformat #\A format-princ (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (let ((arg (pop-format-arg)))
+    (if (null parms)
+      (princ (or arg (if colon "()" nil)) stream)
+      (with-format-parameters parms ((mincol 0) (colinc 1) (minpad 0) (padchar #\space))
+        (format-write-field
+         stream
+         (if (or arg (not colon))
+           (princ-to-string arg)
+           "()")
+         mincol colinc minpad padchar atsign)))))
+
+
+
+;;; S-expression  ~S
+	    
+(defformat #\S format-prin1 (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (let ((arg (pop-format-arg)))
+    (if (null parms)
+      (if (or arg (not colon)) (prin1 arg stream) (princ "()" stream))
+      (with-format-parameters parms ((mincol 0) (colinc 1) (minpad 0) (padchar #\space))
+        (format-write-field
+         stream
+         (if (or arg (not colon))
+           (prin1-to-string arg)
+           "()")
+         mincol colinc minpad padchar atsign)))))
+
+
+
+;;; Character  ~C
+
+(defformat #\C format-print-character (stream colon atsign)
+  (let* ((char (character (pop-format-arg)))
+         (code (char-code char))
+         (name (char-name char)))
+    (cond ((and atsign (not colon))
+           (prin1 char stream))
+          (colon
+           (if (or (eql char #\space)
+                   (not (graphic-char-p char)))
+             (princ name stream)
+             (write-char char stream)))
+          ((not (or atsign colon))
+           (write-char char stream))
+          ((and (< code 32) atsign)
+	   (setq char (code-char (logxor code 64)))
+           (if (or colon (%str-member char "@CGHIJKLM[\\]^_"))
+               (princ name stream)
+               (progn
+                 (write-char #\^ stream)
+                 (write-char char stream)))
+           (princ " (" stream)
+           (princ "Control " stream)
+           (write-char char stream)
+           (write-char #\) stream))
+          (name (princ name stream))
+          (t (write-char char stream)))))
+
+
+;;; NUMERIC PRINTING
+
+
+
+;;; Output a string in a field at MINCOL wide, padding with PADCHAR.
+;;; Pads on the left if PADLEFT is true, else on the right.  If the
+;;; length of the string plus the minimum permissible padding, MINPAD,
+;;; is greater than MINCOL, the actual field size is rounded up to
+;;; MINCOL + k * COLINC for the smallest possible positive integer k.
+
+(defun format-write-field (stream string mincol colinc minpad padchar padleft)
+  (unless (or (null mincol)
+              (integerp mincol))
+    (format-error "Mincol must be an integer - ~S" mincol))
+  (unless (and (integerp colinc) (plusp colinc))
+    (format-error "Colinc must be a positive integer - ~S" colinc))
+  (unless (integerp minpad)
+    (format-error "Minpad must be an integer - ~S" minpad))
+  (unless (characterp padchar)
+    (if (typep padchar `(integer 0 #.char-code-limit))
+      (setq padchar (code-char padchar))
+      (format-error "Padchar must be a character or integer from 0 to ~a - ~S"
+                    char-code-limit padchar)))
+  (let* ((strlen (length (the string string)))
+         (strwid (+ strlen minpad))
+         (width (if mincol
+                  (format-round-columns strwid mincol colinc)
+                  strwid)))
+    (if padleft
+      (dotimes (i (the fixnum (- width strlen))) (write-char padchar stream)))
+    (write-string string stream :start  0 :end strlen)
+    (unless padleft
+      (dotimes (i (the fixnum (- width strlen))) (write-char padchar stream)))))
+
+
+;;; This functions does most of the work for the numeric printing
+;;; directives.  The parameters are interpreted as defined for ~D.
+
+(defun format-print-number (stream number radix print-commas-p print-sign-p parms)
+  (declare (dynamic-extent parms))
+  (declare (type t number) (type fixnum radix))
+  #+wrong
+  (when (> (length parms) 2) (setq print-commas-p t)) ; print commas if char or interval provided
+  (if (not (integerp number))
+      (let ((*print-base* radix)
+            (*print-escape* nil)
+            (*print-radix* nil))
+        (declare (special *print-base* *print-radix*))
+        (princ number stream))
+    (with-format-parameters parms
+          ((mincol 0) (padchar #\space) (commachar #\,) (commainterval 3))
+      ; look out for ",0D" - should be ",'0D"
+      (unless (characterp padchar)
+        (error "Use '~A instead of ~A for padchar in format directive" padchar padchar))
+       (setq print-sign-p 
+             (cond ((and print-sign-p (>= number 0)) #\+)
+                   ((< number 0) #\-)))
+       (setq number (abs number))
+       (block HAIRY
+         (block SIMPLE
+           (if (and (not print-commas-p) (eql 0 mincol))
+             (return-from SIMPLE))
+           (let ((lg 0)
+                 (commas 0))
+             (declare (type fixnum lg commas))
+             (do ((n (abs number) (floor n radix)))
+                 ((%i< n radix))
+               (declare (type integer n))
+               (setq lg (%i+ lg 1))) ; lg is 1- significant digits             
+             (setq commas (if print-commas-p
+                              (floor lg commainterval)
+                              0))
+             (when print-sign-p
+               (setq lg (1+ lg)))
+             (when (and (eq commas 0)
+                        (%i<= mincol lg))
+               (return-from SIMPLE))
+             ;; Cons-o-rama no more !
+             (let* ((s (make-string-output-stream)))
+               (when  (neq padchar #\space)
+                 (dotimes (i (- mincol (+ lg commas) 1))
+                   (write-char padchar s)))
+               (when print-sign-p (write-char print-sign-p s))
+               (%pr-integer  number radix s)                           
+               (dotimes (i (the fixnum commas)) (write-char commachar s))
+               (let ((text (get-output-stream-string s)))
+                 (declare (type string text))
+                 ;; -1234567,, => -1,234,567
+                 (when (%i> commas 0)
+                   (do* ((dest (%i- (length text) 1))
+                         (source (%i- dest commas)))
+                        ((= source dest))
+                     (declare (type fixnum dest source))
+                     (dotimes (i (the fixnum commainterval))
+                       (setf (char text dest) (char text source)
+                             dest (1- dest) 
+                             source (1- source)))
+                     (setf (char text dest) commachar
+                           dest (1- dest))))
+                 (format-write-field stream text mincol 1 0 padchar t)
+                 (return-from HAIRY)))))
+         ;; SIMPLE case         
+         (when print-sign-p (write-char print-sign-p stream))
+         (%pr-integer number radix stream))))
+  nil)
+
+;;; Print a cardinal number in English
+
+(eval-when (:compile-toplevel :execute)
+(defmacro cardinal-ones ()
+  "Table of cardinal ones-place digits in English"
+        '#(nil "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"))
+(defmacro cardinal-tens ()
+  "Table of cardinal tens-place digits in English"
+        '#(nil nil "twenty" "thirty" "forty"
+           "fifty" "sixty" "seventy" "eighty" "ninety"))
+(defmacro cardinal-teens ()
+        '#("ten" "eleven" "twelve" "thirteen" "fourteen"  ;;; RAD
+	   "fifteen" "sixteen" "seventeen" "eighteen" "nineteen"))
+)
+
+
+(defun format-print-small-cardinal (stream n)
+  (multiple-value-bind (hundreds rem) (truncate n 100)
+    (when (plusp hundreds)
+      (write-string (svref (cardinal-ones) hundreds) stream)
+      (write-string " hundred" stream)
+      (when (plusp rem) (write-char #\space stream)))    ; ; ; RAD
+    (when (plusp rem)
+      (multiple-value-bind (tens ones) (truncate rem 10)
+        (cond ((< 1 tens)
+               (write-string (svref (cardinal-tens) tens) stream)
+               (when (plusp ones)
+                 (write-char #\- stream)
+                 (write-string (svref (cardinal-ones) ones) stream)))
+              ((= tens 1)
+               (write-string (svref (cardinal-teens) ones) stream))
+              ((plusp ones)
+               (write-string (svref (cardinal-ones) ones) stream)))))))
+
+(eval-when (:compile-toplevel :execute)
+  (defmacro cardinal-periods ()
+    "Table of cardinal 'teens' digits in English"
+    '#("" " thousand" " million" " billion" " trillion" " quadrillion"
+       " quintillion" " sextillion" " septillion" " octillion" " nonillion" 
+       " decillion"))
+)
+
+
+(defun format-print-cardinal (stream n)
+  (cond ((minusp n)
+         (stream-write-entire-string stream "negative ")
+         (format-print-cardinal-aux stream (- n) 0 n))
+        ((zerop n)
+         (stream-write-entire-string stream "zero"))
+        (t (format-print-cardinal-aux stream n 0 n))))
+
+(defun format-print-cardinal-aux (stream n period err)
+  (multiple-value-bind (beyond here) (truncate n 1000)
+    (unless (<= period 10)
+      (format-error "Number too large to print in English: ~:D" err))
+    (unless (zerop beyond)
+      (format-print-cardinal-aux stream beyond (1+ period) err))
+    (unless (zerop here)
+      (unless (zerop beyond) (write-char #\space stream))
+      (format-print-small-cardinal stream here)
+      (stream-write-entire-string stream (svref (cardinal-periods) period)))))
+
+
+;;; Print an ordinal number in English
+
+
+(eval-when (:compile-toplevel :execute)
+(defmacro ordinal-ones ()
+  "Table of ordinal ones-place digits in English"
+  '#(nil "first" "second" "third" "fourth"
+         "fifth" "sixth" "seventh" "eighth" "ninth"))
+(defmacro ordinal-tens ()
+  "Table of ordinal tens-place digits in English"
+  '#(nil "tenth" "twentieth" "thirtieth" "fortieth"
+         "fiftieth" "sixtieth" "seventieth" "eightieth" "ninetieth"))
+)
+
+(defun format-print-ordinal (stream n)
+  (when (minusp n)
+    (stream-write-entire-string stream "negative "))
+  (let ((number (abs n)))
+    (multiple-value-bind (top bot) (truncate number 100)
+      (unless (zerop top) (format-print-cardinal stream (- number bot)))
+      (when (and (plusp top) (plusp bot)) (write-char #\space stream))
+      (multiple-value-bind (tens ones) (truncate bot 10)
+        (cond ((= bot 12) (stream-write-entire-string stream "twelfth"))
+              ((= tens 1)
+               (stream-write-entire-string stream (svref (cardinal-teens) ones));;;RAD
+               (stream-write-entire-string stream "th"))
+              ((and (zerop tens) (plusp ones))
+               (stream-write-entire-string stream (svref (ordinal-ones) ones)))
+              ((and (zerop ones)(plusp tens))
+               (stream-write-entire-string stream (svref (ordinal-tens) tens)))
+              ((plusp bot)
+               (stream-write-entire-string stream (svref (cardinal-tens) tens))
+               (write-char #\- stream)
+               (stream-write-entire-string stream (svref (ordinal-ones) ones)))
+              ((plusp number) (write-string "th" stream :start  0 :end 2))
+              (t (stream-write-entire-string stream "zeroth")))))))
+
+
+;;; Print Roman numerals
+
+(defun format-print-old-roman (stream n)
+  (unless (< 0 n 5000)
+          (format-error "Number out of range for old Roman numerals: ~:D" n))
+  (do ((char-list '(#\D #\C #\L #\X #\V #\I) (cdr char-list))
+       (val-list '(500 100 50 10 5 1) (cdr val-list))
+       (cur-char #\M (car char-list))
+       (cur-val 1000 (car val-list))
+       (start n (do ((i start (progn (write-char cur-char stream) (- i cur-val))))
+                    ((< i cur-val) i))))
+      ((zerop start))))
+
+
+(defun format-print-roman (stream n)
+  (unless (< 0 n 4000)
+          (format-error "Number out of range for Roman numerals: ~:D" n))
+  (do ((char-list '(#\D #\C #\L #\X #\V #\I) (cdr char-list))
+       (val-list '(500 100 50 10 5 1) (cdr val-list))
+       (sub-chars '(#\C #\X #\X #\I #\I) (cdr sub-chars))
+       (sub-val '(100 10 10 1 1 0) (cdr sub-val))
+       (cur-char #\M (car char-list))
+       (cur-val 1000 (car val-list))
+       (cur-sub-char #\C (car sub-chars))
+       (cur-sub-val 100 (car sub-val))
+       (start n (do ((i start (progn (write-char cur-char stream) (- i cur-val))))
+                    ((< i cur-val)
+                     (cond ((<= (- cur-val cur-sub-val) i)
+                            (write-char cur-sub-char stream)
+                            (write-char cur-char stream)
+                            (- i (- cur-val cur-sub-val)))
+                           (t i))))))
+      ((zerop start))))
+
+
+;;; Decimal  ~D
+
+(defformat #\D format-print-decimal (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (format-print-number stream (pop-format-arg) 10 colon atsign parms))
+
+
+;;; Binary  ~B
+
+(defformat #\B format-print-binary (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (format-print-number stream (pop-format-arg) 2 colon atsign parms))
+
+
+;;; Octal  ~O
+
+(defformat #\O format-print-octal (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (format-print-number stream (pop-format-arg) 8 colon atsign parms))
+
+
+;;; Hexadecimal  ~X
+
+(defformat #\X format-print-hexadecimal (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (format-print-number stream (pop-format-arg) 16 colon atsign parms))
+
+
+;;; Radix  ~R
+
+(defformat #\R format-print-radix (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (let ((number (pop-format-arg))
+        (parm (if parms (pop parms) nil)))
+    (if parm
+        (format-print-number stream number parm colon atsign parms)
+        (if atsign
+            (if colon
+                (format-print-old-roman stream number)
+                (format-print-roman stream number))
+            (if colon
+                (format-print-ordinal stream number)
+                (format-print-cardinal stream number))))))
+
+;;; FLOATING-POINT NUMBERS
+
+
+;;; Fixed-format floating point  ~F
+
+(defformat #\F format-fixed (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (when colon
+    (format-error "Colon flag not allowed"))
+  (with-format-parameters parms ((w nil) (d nil) (k nil) (ovf nil) (pad #\space))
+    ;;Note that the scale factor k defaults to nil.  This is interpreted as
+    ;;zero by flonum-to-string, but more efficiently.
+    (let ((number (pop-format-arg))(*print-escape* nil))
+      (if (floatp number)
+        (format-fixed-aux stream number w d k ovf pad atsign)
+        (if (rationalp number)
+          (format-fixed-aux stream (coerce number 'float) w d k ovf pad atsign)
+          (let ((*print-base* 10))
+            (format-write-field stream (princ-to-string number) w 1 0 #\space t)))))))
+
+; do something ad hoc if d > w - happens if (format nil "~15g" (- 2.3 .1))
+; called with w = 11 d = 16 - dont do it after all.
+
+(defun format-fixed-aux (stream number w d k ovf pad atsign)
+  (and w (<= w 0) (setq w nil))  ; if width is unreasonable, ignore it.
+  (if (not (or w d))  ; perhaps put this back when prin1 is better
+    (prin1 number stream)
+    (let ((spaceleft w)
+          (abs-number (abs number))
+          strlen zsuppress flonum-to-string-width)
+      (when (and w (or atsign (minusp number)))
+        (decf spaceleft))
+      (when (and d w (<= w (+ 1 d (if atsign 1 0))))
+        (setq zsuppress t))
+      (when (and d (minusp d))
+          (format-error "Illegal value for d"))
+      (setq flonum-to-string-width
+            (and w
+                 (if (and (< abs-number 1) (not zsuppress))
+                   (1- spaceleft)   ; room for leading 0
+                   spaceleft)))
+      (when (and w (not (plusp flonum-to-string-width)))
+        (if ovf 
+          (progn
+            (dotimes (i w) (write-char ovf stream))
+            (return-from format-fixed-aux))
+          (setq spaceleft nil w nil)))
+      (multiple-value-bind (str before-pt after-pt)
+                           (flonum-to-string abs-number
+                                             flonum-to-string-width
+                                             d k)
+        (setq strlen (length str))
+        (cond (w (decf spaceleft (+ (max before-pt 0) 1))
+                 (when (and (< before-pt 1) (not zsuppress))
+                   (decf spaceleft))
+                 (if d
+                   (decf spaceleft d)
+                   (setq d (max (min spaceleft (- after-pt))
+                                (if (> spaceleft 0) 1 0))
+                         spaceleft (- spaceleft d))))
+              ((null d) (setq d (max (- after-pt) 1))))
+        (cond ((and w (< spaceleft 0) ovf)
+               ;;field width overflow
+               (dotimes (i w) (declare (fixnum i)) (write-char ovf stream)))
+              (t (when w (dotimes (i spaceleft) (declare (fixnum i)) (write-char pad stream)))
+                 (if (minusp (float-sign number)) ; 5/25
+                   (write-char #\- stream)
+                   (if atsign (write-char #\+ stream)))
+                 (cond
+                  ((> before-pt 0)
+                   (cond ((> strlen before-pt)
+                          (write-string str stream :start  0 :end before-pt)
+                          (write-char #\. stream)
+                          (write-string str stream :start  before-pt :end strlen)
+                          (dotimes (i (- d (- strlen before-pt)))
+                            (write-char #\0 stream)))
+                         (t ; 0's after
+                          (stream-write-entire-string stream str)
+                          (dotimes (i (-  before-pt strlen))
+                            (write-char #\0 stream))
+                          (write-char #\. stream)
+                          (dotimes (i d)
+                            (write-char #\0 stream)))))
+                  (t (unless zsuppress (write-char #\0 stream))
+                     (write-char #\. stream)
+                     (dotimes (i (- before-pt))	 
+                       (write-char #\0 stream))
+                     (stream-write-entire-string stream str)
+                     (dotimes (i (+ d after-pt)) 
+                      (write-char #\0 stream))))))))))
+#|
+; (format t "~7,3,-2f" 8.88)
+; (format t "~10,5,2f" 8.88)
+; (format t "~10,5,-2f" 8.88)
+; (format t "~10,5,2f" 0.0)
+; (format t "~10,5,2f" 9.999999999)
+; (format t "~7,,,-2e" 8.88) s.b. .009e+3 ??
+; (format t "~10,,2f" 8.88)
+; (format t "~10,,-2f" 8.88)
+; (format t "~10,,2f" 0.0)
+; (format t "~10,,2f" 0.123454)
+; (format t "~10,,2f" 9.9999999)
+ (defun foo (x)
+    (format nil "~6,2f|~6,2,1,'*f|~6,2,,'?f|~6f|~,2f|~F"
+     x x x x x x))
+
+|#
+
+                  
+
+;;; Exponential-format floating point  ~E
+
+
+(defformat #\E format-exponential (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (when colon
+    (format-error "Colon flag not allowed"))
+  (with-format-parameters parms ((w nil) (d nil) (e nil) (k 1) (ovf nil) (pad #\space) (marker nil))
+    (let ((number (pop-format-arg)))
+      (if (floatp number)
+        (format-exp-aux stream number w d e k ovf pad marker atsign)
+        (if (rationalp number)
+          (format-exp-aux stream (coerce number 'float) w d e k ovf pad marker atsign)
+          (let ((*print-base* 10))
+            (format-write-field stream (princ-to-string number) w 1 0 #\space t)))))))
+#|
+(defun format-exponent-marker (number)
+  (if (typep number *read-default-float-format*)
+      #\E
+      (cond ((double-floatp) #\D)
+            ((short-floatp number) #\S)
+            ((single-floatp number) #\F)
+            ((long-floatp) #\L))))
+|#
+(eval-when (eval compile #-bccl load)
+  (defmacro format-exponent-marker (number)
+    `(float-exponent-char ,number))
+)
+
+;;;Here we prevent the scale factor from shifting all significance out of
+;;;a number to the right.  We allow insignificant zeroes to be shifted in
+;;;to the left right, athough it is an error to specify k and d such that this
+;;;occurs.  Perhaps we should detect both these condtions and flag them as
+;;;errors.  As for now, we let the user get away with it, and merely guarantee
+;;;that at least one significant digit will appear.
+;;; THE ABOVE COMMENT no longer applies
+
+(defun format-exp-aux (stream number w d e k ovf pad marker atsign &optional string exp)
+  (when (not k) (setq k 1))
+  (if (not (or w d e marker (neq k 1)))
+    (print-a-float number stream t)
+    (prog () 
+      (when d
+        (when (or (minusp d)
+                  (and (plusp k)(>= k (+ d 2)))
+                  (and (minusp k)(< k (- d))))
+          (format-error "incompatible values for k and d")))
+      (when (not exp) (setq exp (scale-exponent  number)))
+      AGAIN
+      (let* ((expt (- exp k))
+             (estr (let ((*print-base* 10))
+                     (princ-to-string (abs expt))))
+             (elen (max (length estr) (or e 0)))
+             (spaceleft (if w (- w 2 elen) nil))
+             (fwidth) scale)
+        (when (and w (or atsign (minusp (float-sign number)))) ; 5/25
+          (setq spaceleft (1- spaceleft)))
+        (if w
+          (progn 
+          (setq fwidth (if d 
+                         (if (> k 0)(+ d 2)(+ d k 1))
+                         (if (> k 0) spaceleft (+ spaceleft k))))
+          (when (minusp exp) ; i don't claim to understand this
+            (setq fwidth (- fwidth exp))
+            (when (< k 0) (setq fwidth (1- fwidth)))))          
+          (when (and d  (not (zerop number))) ; d and no w
+            (setq scale (- 2  k exp))))  ; 2 used to be 1  - 5/31
+        (when (or (and w e ovf (> elen e))(and w fwidth (not (plusp fwidth))))
+          ;;exponent overflow
+          (dotimes (i w) (declare (fixnum i)) (write-char ovf stream))
+          (if (plusp fwidth)
+            (return-from format-exp-aux nil)
+            (setq fwidth nil)))
+        (when (not string)
+          (multiple-value-bind (new-string before-pt) (flonum-to-string number fwidth 
+                                                                        (if (not fwidth) d)
+                                                                        (if (not fwidth) scale))
+            (setq string new-string)
+            (when scale (setq before-pt (- (+ 1 before-pt) k scale))) ; sign right?            
+            (when (neq exp before-pt)
+              ;(print (list 'agn exp before-pt))
+              ;(setq string new-string)
+              (setq exp before-pt)
+              (go again))))
+          (let ((strlen (length string)))
+            (when w
+              (if d 
+                (setq spaceleft (- spaceleft (+ d 2)))
+                (if (< k 1)
+                  (setq spaceleft (- spaceleft (+ 2 (- k)(max strlen 1))))
+                  (setq spaceleft (- spaceleft (+ 1 k (max 1 (- strlen k))))))))
+            (when (and w (< spaceleft 0))
+              (if (and ovf (or (plusp k)(< spaceleft -1)))            
+                (progn (dotimes (i w) (declare (fixnum i)) (write-char ovf stream))
+                       (return-from format-exp-aux nil))))
+            (when w
+              (dotimes (i  spaceleft)
+                (declare (fixnum i))
+                (write-char pad stream)))
+            (if (minusp (float-sign number)) ; 5/25
+              (write-char #\- stream)
+              (if atsign (write-char #\+ stream)))
+            (cond 
+             ((< k 1)
+              (when (not (minusp spaceleft))(write-char #\0 stream))
+              (write-char #\. stream)
+              (dotimes (i (- k))
+                (write-char #\0 stream))
+              (if (and (eq strlen 0)(not d))
+                (write-char #\0 stream)
+                (stream-write-entire-string stream string))
+              (if d
+                (dotimes (i (- (+ d k) strlen))
+                  (write-char #\0 stream))))
+             (t 
+              (write-string string stream :start 0 :end (min k strlen))
+              (dotimes (i (- k strlen))
+                (write-char #\0 stream))                    
+              (write-char #\. stream)
+              (when (> strlen k)
+                (write-string string stream :start k :end strlen))
+              (if (not d) 
+                (when (<= strlen k)(write-char #\0 stream))
+                (dotimes (i (1+ (- d k (max 0 (- strlen k)))))
+                  (write-char #\0 stream)))))
+            (write-char (if marker
+                          marker
+                          (format-exponent-marker number))
+                        stream)
+            (write-char (if (minusp expt) #\- #\+) stream)
+            (when e 
+              ;;zero-fill before exponent if necessary
+              (dotimes (i (- e (length estr)))
+                (declare (fixnum i))
+                (write-char #\0 stream)))
+            (stream-write-entire-string stream estr))))))
+#|
+; (format t "~7,3,,-2e" 8.88) s.b. .009e+3 
+; (format t "~10,5,,2e" 8.888888888) ; "88.8889E-1"
+; (format t "~10,5,,-2e" 8.88)   "0.00888E+3"
+; (format t "~10,5,,-2e" .00123445) ; "0.00123E+0"
+; (format t "~10,5,,-3e" .00123445) ; "0.00012E+1"
+; (format t "~10,,,-2e" .123445)
+; (format t "~10,5,,2e" .0012349999e-4)
+; (format t "~10,5,,2e" 9.9999999)
+; (format t "~10,5,,2e" 0.0)
+; (format t "~10,5,,0e" 40000000.0)
+; (format t "~10,5,,2e" 9.9999999)
+; (format t "~7,,,-2e" 8.88) s.b. .009e+3 ??
+; (format t "~10,,,2e" 8.888888)
+; (format t "~10,,,-2e" 8.88)
+; (format t "~10,,,-2e" 0.0)
+; (format t "~10,,,2e" 0.0) 
+; (format t "~10,,,2e" 9.9999999)
+; (format t "~10,,,2e" 9.9999999e100)
+; (format t "~10,5,3,2,'xe" 10e100)
+; (format t "~9,3,2,-2e" 1100.0)
+(defun foo (x)
+  (format nil
+          "~9,2,1,,'*e|~10,3,2,2,'?,,'$e|~9,3,2,-2,'%@e|~9,2e"
+          x x x x))
+|#
+
+
+;;; General Floating Point -  ~G
+
+(defformat #\G format-general-float (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (when colon
+    (format-error "Colon flag not allowed"))
+  (with-format-parameters parms ((w nil) (d nil) (e nil) (k nil) (ovf nil) (pad #\space) (marker nil))
+    (let ((number (pop-format-arg)))
+      ;;The Excelsior edition does not say what to do if
+      ;;the argument is not a float.  Here, we adopt the
+      ;;conventions used by ~F and ~E.
+      (if (floatp number)
+        (format-general-aux stream number w d e k ovf pad marker atsign)
+        (if (rationalp number)
+          (format-general-aux stream (coerce number 'float) w d e k ovf pad marker atsign)
+          (let ((*print-base* 10))
+            (format-write-field stream (princ-to-string number) w 1 0 #\space t)))))))
+
+#|
+; completely broken
+(defun foo (x)
+  (format nil
+          "~9,2,1,,'*g|~10,3,2,2,'?,,'$g|~9,3,2,-2,'%@g|~9,2g"
+          x x x x))
+|#
+
+
+(defun format-general-aux (stream number w d e k ovf pad marker atsign)
+  (multiple-value-bind (str n #|after-pt|#)(flonum-to-string number)
+    ;;Default d if omitted.  The procedure is taken directly
+    ;;from the definition given in the manual, and is not
+    ;;very efficient, since we generate the digits twice.
+    ;;Future maintainers are encouraged to improve on this.
+    (let* ((d2 (or d (max (length str) (min n 7))))
+           (ee (if e (+ e 2) 4))
+           (ww (if w (- w ee) nil))
+           (dd (- d2 n)))
+      (cond ((<= 0 dd d2)
+             ; this causes us to print 1.0 as 1. - seems weird
+             (format-fixed-aux stream number ww dd nil ovf pad atsign)
+             (dotimes (i ee) (declare (fixnum i)) (write-char #\space stream)))
+            (t (format-exp-aux stream number w d e (or k 1) ovf pad marker atsign nil n))))))
+
+
+;;; Dollars floating-point format  ~$
+
+(defformat #\$ format-dollars (stream colon atsign &rest parms)
+  (declare (dynamic-extent parms))
+  (with-format-parameters parms ((d 2) (n 1) (w 0) (pad #\space))
+    (let* ((number (float (pop-format-arg)))
+           (signstr (if (minusp (float-sign number)) "-" (if atsign "+" "")))
+           (spaceleft)
+           strlen)
+      (multiple-value-bind (str before-pt after-pt) (flonum-to-string number nil d)
+        (setq strlen (length str))
+        (setq spaceleft (- w (+ (length signstr) (max before-pt n) 1 d)))
+        (when colon (stream-write-entire-string stream signstr))
+        (dotimes (i spaceleft) (write-char pad stream))
+        (unless colon (stream-write-entire-string stream signstr))
+        (cond
+         ((> before-pt 0)
+          (cond ((> strlen before-pt)
+                 (dotimes (i (- n before-pt))
+                   (write-char #\0 stream))
+                 (write-string str stream :start 0 :end before-pt)
+                 (write-char #\. stream)
+                 (write-string str stream :start before-pt :end strlen)
+                 (dotimes (i (- d (- strlen before-pt)))
+                   (write-char #\0 stream)))
+                (t ; 0's after
+                 (stream-write-entire-string stream str)
+                 (dotimes (i (-  before-pt strlen))
+                   (write-char #\0 stream))
+                 (write-char #\. stream)
+                 (dotimes (i d)
+                   (write-char #\0 stream)))))
+         (t (dotimes (i n)
+              (write-char #\0 stream))
+            (write-char #\. stream)
+            (dotimes (i (- before-pt))
+              (write-char #\0 stream))
+            (stream-write-entire-string stream str)
+            (dotimes (i (+ d after-pt))
+              (write-char #\0 stream))))))))
+
+(defun y-or-n-p (&optional format-string &rest arguments &aux response)
+  "Y-OR-N-P prints the message, if any, and reads characters from
+   *QUERY-IO* until the user enters y or Y as an affirmative, or either
+   n or N as a negative answer. It asks again if you enter any other
+   characters."
+  (declare (dynamic-extent arguments))
+  (with-terminal-input
+      (clear-input *query-io*)
+      (loop
+        (when format-string
+          (fresh-line *query-io*)
+          (apply 'format *query-io* format-string arguments))
+        (princ " (y or n)  " *query-io*)
+	(setq response (read-char *query-io*))
+        ;; Consume input up to trailing newline
+        (when (peek-char #\NewLine *query-io* nil)
+          ;; And consume the #\newline
+          (read-char *query-io*))
+        (clear-input *query-io*)
+	(if (char-equal response #\y) (return t))
+	(if (char-equal response #\n) (return nil))
+	(format *query-io* "Please answer y or n."))))
+
+(defun yes-or-no-p (&optional format-string &rest arguments &aux response)
+  "YES-OR-NO-P is similar to Y-OR-N-P, except that it clears the
+   input buffer, beeps, and uses READ-LINE to get the strings
+   YES or NO."
+  (declare (dynamic-extent arguments))
+  (with-terminal-input
+      (loop
+        (when format-string
+          (fresh-line *query-io*)
+          (apply 'format *query-io* format-string arguments))
+        (princ " (yes or no)  " *query-io*)
+        (format *query-io* "~A" #\Bell)
+        (setq response (read-line *query-io*))
+        (clear-input *query-io*)
+	(when response
+	  (setq response (string-trim wsp response))
+	  (if (string-equal response "yes") (return t))
+	  (if (string-equal response "no") (return nil))
+          (format *query-io* "Please answer yes or no.")))))
+
+
+
+;; Compile-time format-scanning support.
+;;
+;; All this assumes it's called from the compiler, but it has to be kept in sync with code
+;; here more than with the code in the compiler, so keep it in here.
+
+(defun note-format-scan-option (cell)
+  (when cell
+    (if (null (cdr cell))
+      (setf (car cell) *format-arguments* (cdr cell) *format-arguments-variance*)
+      (let* ((new-args *format-arguments*)
+             (new-var *format-arguments-variance*)
+             (new-max (length new-args))
+             (old-args (car cell))
+             (old-var (cdr cell))
+             (old-max (length old-args))
+             (min (min (- new-max new-var) (- old-max old-var))))
+        (if (>= new-max old-max)
+          (setf (car cell) new-args (cdr cell) (- new-max min))
+          (setf (cdr cell) (- old-max min))))))
+  cell)
+
+(defmacro with-format-scan-options ((var) &body body)
+  (let ((cell (gensym)))
+    ;; CELL is used to record range of arg variations that should be deferred til the end
+    ;; of BODY because they represent possible non-local exits.
+    `(let* ((,cell (cons nil nil))
+            (,var ,cell))
+       (declare (dynamic-extent ,cell))
+       (prog1
+           (progn
+             ,@body)
+         (setq *format-arguments* (car ,cell)
+               *format-arguments-variance* (cdr ,cell))))))
+
+(defvar *format-escape-options* nil)
+
+(defun nx1-check-format-call (control-string format-arguments &optional (env *nx-lexical-environment*))
+  "Format-arguments are expressions that will evaluate to the actual arguments.
+  Pre-scan process the format string, nx1-whine if find errors"
+  (let* ((*nx-lexical-environment* env)
+         (*format-top-level* t)
+         (*logical-block-xp* nil)
+         (*format-pprint* nil)
+         (*format-justification-semi* nil))
+    (let ((error (catch 'format-error
+		   (format-scan control-string format-arguments 0)
+                   nil)))
+      (when error
+	(setf (cadar error) (concatenate 'string (cadar error) " in format string:"))
+	(nx1-whine :format-error (nreverse error))
+	t))))
+
+(defun format-scan (string args var)
+  (let ((*format-original-arguments* args)
+	(*format-arguments* args)
+	(*format-arguments-variance* var)
+	(*format-colon-rest* 'error)
+	(*format-control-string* (ensure-simple-string string)))
+    (with-format-scan-options (*format-escape-options*)
+      (catch 'format-escape
+	(sub-format-scan 0 (length *format-control-string*))
+	(note-format-scan-option *format-escape-options*)))
+    (when (> (length *format-arguments*) *format-arguments-variance*)
+      (format-error "Too many format arguments"))))
+
+(defun sub-format-scan (i end)
+  (let ((*format-index* i)
+        (*format-length* end)
+        (string *format-control-string*))
+    (loop while (setq *format-index* (position #\~ string :start *format-index* :end end)) do
+      (multiple-value-bind (params colon atsign char) (parse-format-operation t)
+	(setq char (char-upcase char))
+	(let ((code (%char-code char)))
+	  (unless (and (< -1 code (length *format-char-table*))
+		       (svref *format-char-table* code))
+	    (format-error "Unknown directive ~c" char)))
+        (format-scan-directive char colon atsign params)
+        (incf *format-index*)))))
+
+(defun nx-could-be-type (form type &optional transformed &aux (env *nx-lexical-environment*))
+  (unless transformed (setq form (nx-transform form env)))
+  (if (nx-form-constant-p form env)
+    (typep (nx-form-constant-value form env) type env)
+    (not (types-disjoint-p (nx-form-type form env) type env))))
+
+(defun format-require-type (form type &optional description)
+  (unless (nx-could-be-type form type)
+    (format-error "~a must be of type ~s" (or description form) type)))
+
+
+(defun format-scan-directive (char colon atsign parms)
+  (ecase char
+    ((#\% #\& #\~ #\|)
+     (with-format-parameters parms ((repeat-count 1))
+       (format-no-flags colon atsign)
+       (format-require-type repeat-count '(integer 0))))
+    ((#\newline #\return)
+     (with-format-parameters parms ()
+       (when (and atsign colon) (format-error "~:@<newline> is undefined"))
+       (unless colon
+	 (format-eat-whitespace))))
+    ((#\P)
+     (with-format-parameters parms ()
+       (when colon
+	 (loop with end = *format-arguments*
+	    for list on *format-original-arguments*
+	    when (eq (cdr list) end) return (setq *format-arguments* list)
+	    finally (if (> (or *format-arguments-variance* 0) 0)
+			(decf *format-arguments-variance*)
+			(format-error "No previous argument"))))
+       (pop-format-arg)))
+    ((#\A #\S)
+     (with-format-parameters parms ((mincol 0) (colinc 1) (minpad 0) (padchar #\space))
+       (format-require-type mincol 'integer "mincol (first parameter)")
+       (format-require-type colinc '(integer 1) "colinc (second parameter)")
+       (format-require-type minpad 'integer "minpad (third parameter)")
+       (format-require-type padchar '(or (integer 0 #.char-code-limit) character) "padchar (fourth parameter)"))
+     (pop-format-arg))
+    ((#\I)
+     (with-format-parameters parms ((n 0))
+       (format-no-flags nil atsign)
+       (format-no-semi char)
+       (format-require-type n 'real)))
+    ((#\_)
+     (with-format-parameters parms ()
+       (format-no-semi char)))
+    ((#\T)
+     (with-format-parameters parms ((colnum 1) (colinc 1))
+       (when colon
+	 (format-no-semi char t))
+       (format-require-type colnum 'integer "colnum (first parameter)")
+       (format-require-type colinc 'integer "colinc (second parameter)")))
+    ((#\W)
+     (with-format-parameters parms ()
+       (format-no-semi #\W))
+     (pop-format-arg))
+    ((#\C)
+     (with-format-parameters parms ())
+     (format-require-type (pop-format-arg) '(or character fixnum (string 1))))
+    ((#\D #\B #\O #\X #\R)
+     (when (eql char #\R)
+       (let ((radix (pop parms)))
+	 (when radix
+	   (format-require-type radix '(integer 2 36)))))
+     (with-format-parameters parms ((mincol 0) (padchar #\space) (commachar #\,) (commainterval 3))
+       (format-require-type mincol 'integer "mincol (first parameter)")
+       (format-require-type padchar 'character "padchar (second parameter)")
+       (format-require-type commachar 'character "comma char (third parameter)")
+       (format-require-type commainterval 'integer "comma interval (fourth parameter)"))
+     (pop-format-arg))
+    ((#\F)
+     (format-no-flags colon nil)
+     (with-format-parameters parms ((w nil) (d nil) (k nil) (ovf nil) (pad #\space))
+       (format-require-type w '(or null (integer 0)) "w (first parameter)")
+       (format-require-type d '(or null (integer 0)) "d (second parameter)")
+       (format-require-type k '(or null integer) "k (third parameter)")
+       (format-require-type ovf '(or null character) "overflowchar (fourth parameter)")
+       (format-require-type pad '(or null character) "padchar (fifth parameter)"))
+     (pop-format-arg))
+    ((#\E #\G)
+     (format-no-flags colon nil)
+     (with-format-parameters parms ((w nil) (d nil) (e nil) (k 1) (ovf nil) (pad #\space) (marker nil))
+       (format-require-type w '(or null (integer 0)) "w (first parameter)")
+       (format-require-type d '(or null (integer 0)) "d (second parameter)")
+       (format-require-type e '(or null (integer 0)) "e (third parameter)")
+       (format-require-type k '(or null integer) "k (fourth parameter)")
+       (format-require-type ovf '(or null character) "overflowchar (fifth parameter)")
+       (format-require-type pad '(or null character) "padchar (sixth parameter)")
+       (format-require-type marker '(or null character) "exponentchar (seventh parameter)"))
+     (pop-format-arg))
+    ((#\$)
+     (with-format-parameters parms ((d 2) (n 1) (w 0) (pad #\space))
+       (format-require-type d '(or null (integer 0)) "d (first parameter)")
+       (format-require-type n '(or null (integer 0)) "n (second parameter)")
+       (format-require-type w '(or null (integer 0)) "w (third parameter)")
+       (format-require-type pad '(or null character) "pad (fourth parameter)"))
+     (format-require-type (pop-format-arg) 'real))
+    ((#\*)
+     (with-format-parameters parms ((count nil))
+       (when count
+	 (format-require-type count 'integer "count parameter"))
+       (if (typep (setq count (nx-transform count)) '(or null integer))
+	 (format-scan-goto colon atsign count)
+	 ;; Else can't tell how much going back or forth, could be anywhere.
+	 (setq *format-arguments* *format-original-arguments*
+	       *format-arguments-variance* (length *format-arguments*)))))
+    ((#\?)
+     (with-format-parameters parms ()
+       (format-no-flags colon nil))
+     (let ((string (pop-format-arg)))
+       (format-require-type string '(or string function))
+       (if atsign
+	 (setq *format-arguments-variance* (length *format-arguments*))
+	 (let ((arg (pop-format-arg)))
+	   (format-require-type arg 'list)))))
+    ((#\/)
+     (let* ((string *format-control-string*)
+	    (ipos (1+ *format-index*))
+	    (epos (format-find-char #\/ ipos *format-length*)))
+       (when (not epos) (format-error "Unmatched ~~/"))
+       (let* ((cpos (format-find-char #\: ipos epos))
+	      (name (if cpos
+		      (prog1
+			  (string-upcase (%substr string ipos cpos))
+			(when (eql #\: (schar string (%i+ 1 cpos)))
+			  (setq cpos (%i+ cpos 1)))
+			(setq ipos (%i+ cpos 1)))
+		      "CL-USER"))
+	      (package (find-package name))
+	      (sym (and package (find-symbol (string-upcase (%substr string ipos epos)) package)))
+	      (arg (pop-format-arg)))
+	 (setq *format-index* epos) ; or 1+ epos?
+	 ;; TODO: should we complain if the symbol doesn't exit?  Perhaps it will be defined
+	 ;; later, and to detect that would need to intern it.  What if the package doesn't exist?
+	 ;; Would need to extend :undefined-function warnings to handle previously-undefined package.
+	 (when sym
+	   (when (nx1-check-typed-call sym (list* '*standard-output* arg colon atsign parms))
+	     ;; Whined, just get out now.
+	     (throw 'format-error nil))))))
+    ((#\[)
+     (when (and colon atsign) (format-error  "~~:@[ undefined"))
+     (format-nextchar)
+     (cond (colon
+	    (format-scan-boolean-condition parms))
+	   (atsign
+	    (format-scan-funny-condition parms))
+	   (t (format-scan-untagged-condition parms))))
+    ((#\()
+     (with-format-parameters parms ()
+       (format-nextchar)
+       (multiple-value-bind (prev tilde parms colon atsign) (format-find-command '(#\)))
+	 (with-format-parameters parms () (format-no-flags colon atsign))
+	 (sub-format-scan prev tilde))))
+    ((#\^)
+     (format-no-flags nil atsign)
+     (with-format-parameters parms ((p1 nil) (p2 nil) (p3 nil))
+       (let ((val (nx-transform (cond (p3
+				       (if (every (lambda (p) (nx-could-be-type p 'real)) parms)
+					 ;; If the params could also be chars, don't know enough to constant fold
+					 ;; anyway, so this test will do.
+					 `(< ,p1 ,p2 ,p3)
+					 (if (every (lambda (p) (nx-could-be-type p 'character)) parms)
+					   `(char< ,p1 ,p2 ,p3)
+					   ;; At least one can't be real, at least one can't be char.
+					   (format-error "Wrong type of parameters for three-way comparison"))))
+				      (p2 `(equal ,p1 ,p2))
+				      (p1 `(eq ,p1 0))
+				      (t (null (if colon *format-colon-rest* *format-arguments*)))))))
+	 (when val
+	   (note-format-scan-option *format-escape-options*)
+	   (unless (nx-could-be-type val 'null t)
+	     (throw 'format-escape t))))))
+    ((#\{)
+     (with-format-parameters parms ((max-iter -1))
+       (format-require-type max-iter 'integer "max-iter parameter")
+       (format-nextchar)
+       (multiple-value-bind (prev tilde end-parms end-colon end-atsign) (format-find-command '(#\}))
+	 (declare (ignore end-colon))
+	 (with-format-parameters end-parms () (format-no-flags nil end-atsign))
+	 (when (= prev tilde)
+	   ;; Use an argument as the control string if ~{~} is empty
+	   (let ((string (pop-format-arg)))
+	     (unless (nx-could-be-type string '(or string function))
+	       (format-error "Control string is not a string or function"))))
+	 ;; Could try to actually scan the iteration if string is a compile-time string,
+	 ;; by that seems unlikely.
+	 (if atsign
+	   (setq *format-arguments-variance* (length *format-arguments*))
+	   (format-require-type (pop-format-arg) 'list)))))
+    ((#\<)
+     (multiple-value-bind (start tilde eparms ecolon eatsign) (format-find-command '(#\>))
+       (declare (ignore tilde eparms eatsign))
+       (setq *format-index* start)
+       (if ecolon
+	 (format-logical-block-scan colon atsign parms)
+	 (format-justification-scan colon atsign parms))))
+    ))
+
+(defun format-justification-scan (colon atsign parms)
+  (declare (ignore colon atsign))
+  (with-format-parameters parms ((mincol 0) (colinc 1) (minpad 0) (padchar #\space))
+    (format-require-type mincol 'integer "mincol (first parameter)")
+    (format-require-type colinc '(integer 1) "colinc (second parameter)")
+    (format-require-type minpad 'integer "minpad (third parameter)")
+    (format-require-type padchar `(or character (integer 0 #.char-code-limit)) "padchar (fourth parameter)"))
+  (let ((first-parms nil) (first-colon nil) (count 0))
+    (with-format-scan-options (*format-escape-options*)
+      (loop
+	 (format-nextchar)
+	 (multiple-value-bind (prev tilde parms colon atsign cmd)
+	     (format-find-command '(#\; #\>) nil T)
+	   (if (and (eql count 0) (eql cmd #\;) colon)
+	     (progn
+	       (format-no-flags nil atsign)
+	       (setq first-colon t)
+	       (setq *format-index* tilde)
+	       (setq first-parms (nth-value 2 (format-find-command '(#\; #\>) t T))))
+	     (with-format-parameters parms ()
+	       (format-no-flags colon atsign)))
+	   (when (catch 'format-escape
+		   (sub-format-scan prev tilde)
+		   nil)
+	     (unless (eq cmd #\>) (format-find-command '(#\>) nil t))
+	     (return))
+	   (incf count)
+	   (when (eq cmd #\>)
+	     (return))))
+      (note-format-scan-option *format-escape-options*))
+    (when first-colon
+      (when *format-pprint*
+	(format-error "Justification illegal in this context"))
+      (setq *format-justification-semi* t)
+      (with-format-parameters first-parms ((spare 0) (linel 0))
+	(format-require-type spare 'integer "spare (first parameter)")
+	(format-require-type linel 'integer "line length (second parameter)")))))
+      
+
+
+(defun format-logical-block-scan (colon atsign params)
+  (declare (ignore colon))
+  (with-format-parameters params ()
+    (format-no-semi #\<))
+    ;; First section can be termined by ~@;
+  (let ((format-string *format-control-string*)
+	(prefix "")
+	(suffix "")
+	(body-string nil))
+    (multiple-value-bind (start1 tilde parms1 colon1 atsign1 cmd) (format-find-command  '(#\; #\>))
+      (setq body-string (%substr format-string (1+ start1) tilde))
+      (with-format-parameters parms1 ())
+      (when (eq cmd #\;)
+	(format-no-flags colon1 nil)
+	(setq prefix body-string)
+	(multiple-value-setq (start1 tilde parms1 colon1 atsign1 cmd) (format-find-command '(#\; #\>)))
+	(with-format-parameters parms1 ())
+	(setq body-string (%substr format-string (1+ start1) tilde))
+	(when (eq cmd #\;)
+	  (format-no-flags colon1 atsign1)
+	  (multiple-value-setq (start1 tilde parms1 colon1 atsign1 cmd) (format-find-command  '(#\; #\>)))
+	  (with-format-parameters parms1 ())
+	  (setq suffix (%substr format-string (1+ start1) tilde))
+	  (when (eq cmd #\;)
+	    (format-error "Too many sections")))))
+    (flet ((format-check-simple (str where)
+	     (when (and str (or (%str-member #\~ str) (%str-member #\newline str)))
+	       (format-error "~A must be simple" where))))
+      (format-check-simple prefix "Prefix")
+      (format-check-simple suffix "Suffix"))
+    (if atsign
+      (let ((*logical-block-p* t))
+	(format-scan body-string *format-arguments* *format-arguments-variance*)
+	(setq *format-arguments* nil *format-arguments-variance* 0))
+      ;; If no atsign, we just use up an arg.  Don't bother trying to scan it, unlikely to be a constant.
+      (when *format-arguments*
+	(pop-format-arg)))))
+
+
+(defun format-scan-untagged-condition (parms)
+  (with-format-parameters parms ((index nil))
+    (unless index (setq index (pop-format-arg)))
+    (format-require-type index 'integer)
+    (with-format-scan-options (cond-options)
+      (loop with default = nil do
+	   (multiple-value-bind (prev tilde parms colon atsign cmd)
+	       (format-find-command '(#\; #\]))
+	     (when (and default (eq cmd #\;))
+	       (format-error "~:; must be the last clause"))
+	     (with-format-parameters parms ()
+	       (format-no-flags (if (eq cmd #\]) colon) atsign)
+	       (when colon (setq default t)))
+	     (format-scan-optional-clause prev tilde cond-options)
+	     (when (eq cmd #\])
+	       (unless default 	  ;; Could just skip the whole thing
+		 (note-format-scan-option cond-options))
+	       (return))
+	     (format-nextchar))))))
+
+(defun format-scan-funny-condition (parms)
+  (with-format-parameters parms ())
+  (multiple-value-bind (prev tilde parms colon atsign) (format-find-command '(#\]))
+    (with-format-parameters parms ()
+      (format-no-flags colon atsign))
+    (when (null *format-arguments*) (pop-format-arg)) ;; invoke std error
+    (with-format-scan-options (cond-options)
+      (let ((arg (nx-transform (car *format-arguments*))))
+	(when (nx-could-be-type arg 'null t)
+	  (let ((*format-arguments* *format-arguments*)
+		(*format-arguments-variance* *format-arguments-variance*))
+	    (when (eql *format-arguments-variance* (length *format-arguments*))
+	      (decf *format-arguments-variance*))
+	    (pop *format-arguments*)
+	    (note-format-scan-option cond-options)))
+	(when arg
+	  (format-scan-optional-clause prev tilde cond-options))))))
+
+
+(defun format-scan-boolean-condition (parms)
+  (with-format-parameters parms ())
+  (multiple-value-bind (prev tilde parms colon atsign cmd) (format-find-command '(#\; #\]))
+    (when (eq cmd #\])
+      (format-error "Two clauses separated by ~~; are required for ~~:["))
+    (with-format-parameters parms () (format-no-flags colon atsign))
+    (format-nextchar)
+    (with-format-scan-options (cond-options)
+      (let ((arg (nx-transform (pop-format-arg))))
+	(when (nx-could-be-type arg 'null t)
+	  (format-scan-optional-clause prev tilde cond-options))
+	(multiple-value-bind (prev tilde parms colon atsign) (format-find-command '(#\]))
+	  (with-format-parameters parms () (format-no-flags colon atsign))
+	  (when arg
+	    (format-scan-optional-clause prev tilde cond-options)))))))
+
+
+(defun format-scan-optional-clause (start end cond-option)
+  (let ((*format-arguments* *format-arguments*)
+	(*format-arguments-variance* *format-arguments-variance*))
+    ;; Let the branch points collect in outer *format-escape-options*, but don't
+    ;; throw there because need to consider the other clauses.
+    (catch 'format-escape
+      (sub-format-scan start end)
+      (note-format-scan-option cond-option)
+      nil)))
+
+(defun format-scan-goto (colon atsign count)
+  (if atsign 
+    (let* ((orig *format-original-arguments*)
+           (orig-pos (- (length orig) (length *format-arguments*)))
+           (new-pos (or count 0)))
+      (format-no-flags colon nil)
+      ;; After backing up, we may not use up all the arguments we backed over,
+      ;; so even though real variance here is 0, increase variance so we don't
+      ;; complain.
+      (setq *format-arguments-variance* (max 0 (- orig-pos new-pos)))
+      (setq *format-arguments* (nthcdr-no-overflow new-pos orig)))
+    (progn
+      (when (null count)(setq count 1))
+      (when colon (setq count (- count)))
+      (cond ((> count 0)
+	     (when (> count (length *format-arguments*))
+	       (format-error "Target position for ~~* out of bounds"))
+	     (setq *format-arguments* (nthcdr count *format-arguments*))
+	     (when *format-arguments-variance*
+	       (setq *format-arguments-variance*
+		     (min *format-arguments-variance* (length *format-arguments*)))))
+	    ((< count 0)
+	     (let* ((orig *format-original-arguments*)
+		    (orig-pos (- (length orig) (length *format-arguments*)))
+		    (pos (+ orig-pos count))
+		    (max-pos (+ pos (or *format-arguments-variance* 0))))
+	       (when (< max-pos 0)
+		 (format-error "Target position for ~~* out of bounds"))
+	       ;; After backing up, we may not use up all the arguments we backed over.
+	       ;; Increase the variance allowed to cover those arguments, so we don't
+	       ;; complain about not using them.  E.g. (format t "~a ~a ~2:*~a" 1 2) should
+	       ;; be ok, (format t "~a ~a ~2:*" 1 2) should warn.
+	       (setq max-pos (1- (- max-pos count)))
+	       (if (< pos 0)
+		 (setq *format-arguments* orig
+		       *format-arguments-variance* max-pos)
+		 (setq *format-arguments* (nthcdr pos orig)
+		       *format-arguments-variance* (- max-pos pos)))))))))
Index: /branches/new-random/lib/hash.lisp
===================================================================
--- /branches/new-random/lib/hash.lisp	(revision 13309)
+++ /branches/new-random/lib/hash.lisp	(revision 13309)
@@ -0,0 +1,456 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;  This is just the stuff (make-load-form, print-object) that can't be fasloaded earlier.
+
+
+;;;;;;;;;;;;;
+;;
+;; hash.lisp
+;; New hash table implementation
+
+;;;;;;;;;;;;;
+;;
+;; Things I didn't do
+;;
+;; Save the 32-bit hash code along with the key so that growing the table can
+;; avoid calling the hashing function (at least until a GC happens during growing).
+;;
+;; Maybe use Knuth's better method for hashing:
+;; find two primes N-2, N.  N is the table size.
+;; First probe is at primary = (mod (funcall (nhash.keytransF h) key) N)
+;; Secondary probes are spaced by (mod (funcall (nhash.keytransF h) key) N-2)
+;; This does a bit better scrambling of the secondary probes, but costs another divide.
+;;
+;; Rethink how finalization is reported to the user.  Maybe have a finalization function which
+;; is called with the hash table and the deleted key & value.
+
+
+;;;;;;;;;;;;;
+;;
+;; Documentation
+;;
+;; MAKE-HASH-TABLE is extended to accept a :HASH-FUNCTION keyword arg which
+;; defaults for the 4 Common Lisp defined :TEST's.  Also, any fbound symbol can
+;; be used for the :TEST argument.  The HASH-FUNCTION is a function of one
+;; argument, the key, which returns one or two values:
+;;
+;; 1) HASH-CODE
+;; 2) ADDRESSP
+;;
+;; The HASH-CODE can be any object.  If it is a relocateable object (not a
+;; fixnum, short float, or immediate) then ADDRESSP will default to :KEY
+;; and it is an error if NIL is returned for ADDRESSP.
+;;
+;; If ADDRESSP is NIL, the hashing code assumes that no addresses were used
+;; in computing the HASH-CODE.  If ADDRESSP is :KEY (which is the default
+;; if the hash function returns only one value and it is relocateable) then
+;; the hashing code assumes that only the KEY's address was used to compute
+;; the HASH-CODE.  Otherwise, it is assumed that the address of a
+;; component of the key was used to compute the HASH-CODE.
+;;
+;;
+;;
+;; Some (proposed) functions for using in user hashing functions:
+;;
+;; (HASH-CODE object)
+;;
+;; returns two values:
+;;
+;; 1) HASH-CODE
+;; 2) ADDRESSP
+;;
+;; HASH-CODE is the object transformed into a fixnum by changing its tag
+;; bits to a fixnum's tag.  ADDRESSP is true if the object was
+;; relocateable. ;;
+;;
+;; (FIXNUM-ADD o1 o2)
+;; Combines two objects additively and returns a fixnum.
+;; If the two objects are fixnums, will be the same as (+ o1 o2) except
+;; that the result can not be a bignum.
+;;
+;; (FIXNUM-MULTIPLY o1 o2)
+;; Combines two objects multiplicatively and returns a fixnum.
+;;
+;; (FIXNUM-FLOOR dividend &optional divisor)
+;; Same as Common Lisp's FLOOR function, but converts the objects into
+;; fixnums before doing the divide and returns two fixnums: quotient &
+;; remainder.
+;;
+;;;;;;;;;;;;;
+;;
+;; Implementation details.
+;;
+;; Hash table vectors have a header that the garbage collector knows
+;; about followed by alternating keys and values.  Empty slots have a
+;; key of (%UNBOUND-MARKER), deleted slots are denoted by a key of
+;; (%SLOT-UNBOUND-MARKER), except in the case of "lock-free" hash
+;; tables, which see below.
+;;
+;; Four bits in the nhash.vector.flags fixnum interact with the garbage
+;; collector.  This description uses the symbols that represent bit numbers
+;; in a fixnum.  $nhash_xxx_bit has a corresponding $nhash_lap_xxx_bit which
+;; gives the byte offset of the bit for LAP code.  The two bytes in
+;; question are at offsets $nhash.vector-weak-byte and
+;; $nhash.vector-track-keys-byte offsets from the tagged vector.
+;; The raw 32 bits of the fixnum at nhash.vector.flags look like:
+;;
+;;     TKEC0000 00000000 WVFZ0000 00000000
+;;
+;;
+;; $nhash_track_keys_bit         "T" in the diagram above
+;;                               Sign bit of the longword at $nhash.vector.flags
+;;                               or the byte at $nhash.vector-track-keys-byte.
+;;                               If set, GC tracks relocation of keys in the
+;;                               vector.
+;; $nhash_key_moved_bit          "K" in the diagram above
+;;                               Set by GC to indicate that a key moved.
+;;                               If $nhash_track_keys_bit is clear, this bit is set to
+;;                               indicate that any GC will require a rehash.
+;;                               GC never clears this bit, but may set it if
+;;                               $nhash_track_keys_bit is set.
+;; $nhash_component_address_bit  "C" in the diagram above.
+;;                               Ignored by GC.  Set to indicate that the
+;;                               address of a component of a key was used. 
+;;                               Means that $nhash_track_keys_bit will
+;;                               never be set until all such keys are
+;;                               removed.
+;; $nhash_weak_bit               "W" in the diagram above
+;;                               Sign bit of the byte at $nhash.vector-weak-byte
+;;                               Set to indicate a weak hash table
+;; $nhash_weak_value_bit         "V" in the diagram above
+;;                               If clear, the table is weak on key
+;;                               If set, the table is weak on value
+;; $nhash_finalizeable_bit       "F" in the diagram above
+;;                               If set the table is finalizeable:
+;;                               If any key/value pairs are removed, they will be added to
+;;                               the nhash.vector.finalization-alist using cons cells
+;;                               from nhash.vector.free-alist
+;; $nhash_keys_frozen_bit       "Z" in diagram above.
+;;                               If set, GC will remove weak entries by setting the
+;;                               value to (%slot-unbound-marker), leaving key unchanged.
+
+(in-package "CCL")
+
+
+(eval-when (:compile-toplevel :execute)
+  (require "HASHENV" "ccl:xdump;hashenv"))
+
+(defvar *hash-table-class*
+  (progn
+;    #+sparc-target (dbg)
+    (find-class 'hash-table)))
+
+(setf (type-predicate 'hash-table) 'hash-table-p)
+
+
+(defmethod print-object ((table hash-table) stream)
+  (print-unreadable-object (table stream :type t :identity t)
+    (format stream "~S ~S size ~D/~D"
+            ':test (hash-table-test table)
+            (hash-table-count table)
+            (hash-table-size table))
+    (when (readonly-hash-table-p table)
+      (format stream " (Readonly)"))))
+
+
+#+vaporware
+;;; Of course, the lisp version of this would be too slow ...
+(defun hash-table-finalization-list (hash-table)
+  (unless (hash-table-p hash-table)
+    (report-bad-arg hash-table 'hash-table))
+  (let* ((vector (nhash.vector hash-table))
+         (flags (nhash.vector.flags vector)))
+    (declare (fixnum flags))
+    (if (logbitp $nhash_finalizeable_bit flags)
+      (nhash.vector.finalization-alist vector)
+      (error "~S is not a finalizeable hash table" hash-table))))
+
+#+vaporware
+(defun (setf hash-table-finalization-list) (value hash-table)
+  (unless (hash-table-p hash-table)
+    (report-bad-arg hash-table 'hash-table))
+  (let* ((vector (nhash.vector hash-table))
+         (flags (nhash.vector.flags vector)))
+    (declare (fixnum flags))
+    (if (logbitp $nhash_finalizeable_bit flags)
+      (setf (nhash.vector.finalization-alist vector) value)
+      (error "~S is not a finalizeable hash table" hash-table))))
+
+(defsetf gethash puthash)
+
+; Returns nil, :key or :value
+(defun hash-table-weak-p (hash)
+  (unless (hash-table-p hash)
+    (setq hash (require-type hash 'hash-table)))
+  (let* ((vector (nhash.vector hash))
+         (flags (nhash.vector.flags vector)))
+    (when (logbitp $nhash_weak_bit flags)
+      (if (logbitp $nhash_weak_value_bit flags)
+        :value
+        :key))))
+
+;;; It would be pretty complicated to offer a way of doing (SETF
+;;; HASH-TABLE-WEAK-P) after the hash-table's been created, and
+;;; it's not clear that that'd be incredibly useful.
+
+
+
+;;;;;;;;;;;;;
+;;
+;; Mapping functions
+;;
+
+
+
+(defun next-hash-table-iteration-1 (state)
+  (do* ((index (nhti.index state) (1+ index))
+        (keys (nhti.keys state))
+        (values (nhti.values state))
+        (nkeys (nhti.nkeys state)))
+       ((>= index nkeys)
+        (setf (nhti.index state) nkeys)
+        nil)
+    (declare (fixnum index nkeys)
+             (simple-vector keys))
+    (let* ((key (svref keys index))
+           (value (svref values index)))
+        (setf (nhti.index state) (1+ index))
+        (return (values t key value)))))
+
+
+
+(defun maphash (function hash-table)
+  "For each entry in HASH-TABLE, call the designated two-argument function
+   on the key and value of the entry. Return NIL."
+  (with-hash-table-iterator (m hash-table)
+    (loop
+      (multiple-value-bind (found key value) (m)
+        (unless found (return))
+        (funcall function key value)))))
+
+
+
+(defmethod make-load-form ((hash hash-table) &optional env)
+  (declare (ignore env))
+  (%normalize-hash-table-count hash)
+  (let ((keytransF (nhash.keytransF hash))
+        (compareF (nhash.compareF hash))
+        (vector (nhash.vector hash))
+        (private (if (nhash.owner hash) '*current-process*))
+        (lock-free-p (logtest $nhash.lock-free (the fixnum (nhash.lock hash)))))
+    (flet ((convert (f)
+             (if (or (fixnump f) (symbolp f))
+               `',f
+               `(symbol-function ',(function-name f)))))
+      (values
+       `(%cons-hash-table
+         nil nil nil ,(nhash.grow-threshold hash) ,(nhash.rehash-ratio hash) ,(nhash.rehash-size hash)
+        nil nil ,private ,lock-free-p)
+       `(%initialize-hash-table ,hash ,(convert keytransF) ,(convert compareF) ',vector)))))
+
+(defun needs-rehashing (hash)
+  (%set-needs-rehashing hash))
+
+(defun %initialize-hash-table (hash keytransF compareF vector)
+  (setf (nhash.keytransF hash) keytransF
+        (nhash.compareF hash) compareF)
+  (setf (nhash.find hash)
+        (case comparef
+          (0 #'eq-hash-find)
+          (-1 #'eql-hash-find)
+          (t #'general-hash-find))
+        (nhash.find-new hash)
+        (case comparef
+          (0 #'eq-hash-find-for-put)
+          (-1 #'eql-hash-find-for-put)
+          (t #'general-hash-find-for-put)))
+  (setf (nhash.vector hash) vector)
+  (%set-needs-rehashing hash))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Support for locking hash tables while fasdumping
+;;
+
+
+(defun fasl-lock-hash-table (hash-table)
+  (setq hash-table (require-type hash-table 'hash-table))
+  (without-interrupts
+   (let* ((lock (nhash.exclusion-lock hash-table)))
+     (if lock
+       (progn
+         (if (hash-lock-free-p hash-table)
+           ;; For lock-free hash tables, this only makes sure nobody is
+           ;; rehashing the table.  It doesn't necessarily stop readers
+           ;; or writers (unless they need to rehash).
+           (grab-lock lock)
+           (write-lock-rwlock lock))
+         (push hash-table *fcomp-locked-hash-tables*))
+       (unless (eq (nhash.owner hash-table) *current-process*)
+         (error "Current process doesn't own hash-table ~s" hash-table))))))
+
+(defun fasl-unlock-hash-tables ()
+  (dolist (h *fcomp-locked-hash-tables*)
+    (let* ((lock (nhash.exclusion-lock h)))
+      (if (hash-lock-free-p h)
+        (release-lock lock)
+        (unlock-rwlock lock)))))
+
+
+
+	      
+
+#+not-yet
+(progn
+;;;;;;;;;;;;;
+;;
+;; Replacement for population
+;;
+(def-accessors (weak-table) %svref
+  nil                                   ; 'weak-table
+  weak-table.vector                     ; a $v_nhash vector
+  weak-table.index                      ; index for next entry
+  weak-table.grow-threshold             ; number of entries left in vector
+  )
+
+(defun make-weak-table (&optional (size 20))
+  (%istruct 'weak-table
+            (%cons-nhash-vector
+             size (+ (ash 1 $nhash_weak_bit)))
+            0
+            size))
+
+(defun weak-table-p (weak-table)
+  (istruct-typep weak-table 'weak-table))
+
+(setf (type-predicate 'weak-table) 'weak-table-p)
+
+(defun weak-table-count (weak-table)
+  (setq weak-table (require-type weak-table 'weak-table))
+  (- (weak-table.index weak-table)
+     (nhash.vector.weak-deletions-count (weak-table.vector weak-table))))
+
+(defun weak-table-push (key weak-table &optional value)
+  (setq weak-table (require-type weak-table 'weak-table))
+  (let ((thresh (weak-table.grow-threshold weak-table))
+        (vector (weak-table.vector weak-table))
+        (index (weak-table.index weak-table)))
+    (declare (fixnum thresh index))
+    (if (> thresh 0)
+      (progn
+        (lap-inline (index)
+          (:variable vector key value)
+          (move.l (varg vector) atemp0)
+          (lea (atemp0 arg_z.l $nhash_data) atemp0)
+          (move.l (varg key) atemp0@+)
+          (move.l (varg value) @atemp0))
+        (setf (weak-table.index weak-table) (the fixnum (1+ index))
+              (weak-table.grow-threshold weak-table) (the fixnum (1- thresh)))
+        value)
+      (let ((deletions (nhash.vector.weak-deletions-count vector)))
+        (declare (fixnum deletions))
+        (if (> deletions 0)
+          ; GC deleted some entries, we can compact the table
+          (progn
+            (lap-inline (index)
+              (:variable vector)
+              (getint arg_z)            ; length
+              (move.l (varg vector) atemp0)
+              (lea (atemp0 $nhash_data) atemp0)
+              (move.l atemp0 atemp1)
+              (move.l ($ $undefined) da)
+              ; Find the first deleted entry
+              (dbfloop.l arg_z
+                (if# (ne (cmp.l @atemp0 da))
+                  (add.l ($ 1) arg_z)
+                  (bra @move))
+                (add.w ($ 8) atemp0))
+              ; copy the rest of the table up
+              @move
+              (dbfloop.l arg_z
+                (move.l atemp0@+ db)
+                (if# (eq (cmp.l db da))
+                  (add.w ($ 4) atemp0)
+                 else#
+                  (move.l db atemp1@+)
+                  (move.l atemp0@+ atemp1@+)))
+              ; Write over the newly emptied part of the table
+              (while# (ne (cmp.l atemp0 atemp1))
+                (move.l da @atemp1)
+                (add.l ($ 8) atemp1)))
+            (setf (nhash.vector.weak-deletions-count vector) 0
+                  (weak-table.index weak-table) (the fixnum (- index deletions))
+                  (weak-table.grow-threshold weak-table) (the fixnum (+ thresh deletions)))
+            (weak-table-push key weak-table value))
+          ; table is full.  Grow it by a factor of 1.5
+          (let* ((new-size (+ index (the fixnum (ash (the fixnum (1+ index)) -1))))
+                 (new-vector (%cons-nhash-vector new-size (ash 1 $nhash_weak_bit))))
+            (declare (fixnum new-size))
+            (lap-inline (index)
+              (:variable vector new-vector count)
+              (move.l (varg vector) atemp0)
+              (move.l (varg new-vector) atemp1)
+              (lea (atemp0 $nhash_data) atemp0)
+              (lea (atemp1 $nhash_data) atemp1)
+              (getint arg_z)            ; table length
+              (dbfloop.l arg_z
+                (move.l atemp0@+ atemp1@+)
+                (move.l atemp0@+ atemp1@+)))
+            (setf (weak-table.vector weak-table) new-vector
+                  (weak-table.grow-threshold weak-table) (the fixnum (- new-size index)))
+            ; It's possible that GC deleted some entries while consing the new vector
+            (setf (nhash.vector.weak-deletions-count new-vector)
+                  (nhash.vector.weak-deletions-count vector))
+            (weak-table-push key weak-table value)))))))
+
+; function gets two args: key & value
+(defun map-weak-table (function weak-table)
+  (setq weak-table (require-type weak-table 'weak-table))
+  (let* ((vector (weak-table.vector weak-table))
+         (index (weak-table.index weak-table))
+         (flags (nhash.vector.flags vector)))
+    (unwind-protect
+      (progn
+        (setf (nhash.vector.flags vector) 0)    ; disable deletion by GC
+        (lap-inline ()
+          (:variable function vector index)
+          (while# (gt (move.l (varg index) da))
+            (sub.l '1 da)
+            (move.l da (varg index))
+            (move.l (varg vector) atemp0)
+            (move.l (atemp0 da.l $nhash_data) arg_y)
+            (if# (ne (cmp.w ($ $undefined) arg_y))
+              (move.l (atemp0 da.l (+ $nhash_data 4)) arg_z)
+              (set_nargs 2)
+              (move.l (varg function) atemp0)
+              (jsr_subprim $sp-funcall))))
+        nil)
+      (setf (nhash.vector.flags vector) flags))))
+
+; function gets one arg, the key
+(defun map-weak-table-keys (function weak-table)
+  (flet ((f (key value)
+           (declare (ignore value))
+           (funcall function key)))
+    (declare (dynamic-extent #'f))
+    (map-weak-table #'f weak-table)))
+    
+) ; #+not-yet
+
+; end
Index: /branches/new-random/lib/late-clos.lisp
===================================================================
--- /branches/new-random/lib/late-clos.lisp	(revision 13309)
+++ /branches/new-random/lib/late-clos.lisp	(revision 13309)
@@ -0,0 +1,70 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Maybe compile specialized discriminating code (dcode) for generic
+;;; functions, if it seems likely that that might perform better than
+;;; the general generic-function-dispatch mechanism.
+
+
+;;; If the GF accepts a fixed number of arguments, return its
+;;; lambda list.
+(defun gf-fixed-arg-lambda-list (gf)
+  (let* ((lambda-list (generic-function-lambda-list gf)))
+    (dolist (arg lambda-list lambda-list)
+      (when (member arg lambda-list-keywords)
+        (return nil)))))
+
+(defun generate-conformance-test (arg-name specializer)
+  (cond ((typep specializer 'eql-specializer)
+         `(eql ,arg-name ',(eql-specializer-object specializer)))
+        ((eq specializer *t-class*))
+        ((typep specializer 'standard-class)
+         (let* ((wrapper (gensym)))
+           `(let* ((,wrapper (if (= (the fixnum (typecode ,arg-name))
+                                    target::subtag-instance)
+                               (instance.class-wrapper ,arg-name))))
+             (and ,wrapper
+              (memq ,specializer (or (%wrapper-cpl ,wrapper)
+                                                (%inited-class-cpl
+                                                 (%wrapper-class ,wrapper))))))))
+        (t `(typep ,arg-name ',(class-name specializer)))))
+
+(defun generate-conformance-clause (args method)
+  `((and ,@(mapcar #'generate-conformance-test args (method-specializers method)))
+     (funcall ,(method-function method) ,@args)))
+
+;;; Generate code to call the single fixed-arg primary method
+;;; defined on GF if all args are conformant, or to call
+;;; NO-APPLICABLE-METHOD otherwise.
+;;; Note that we can often do better than this for accessor
+;;; methods (especially reader methods) as a very late (delivery-time)
+;;; optimization.
+(defun dcode-for-fixed-arg-singleton-gf (gf)
+  (let* ((methods (generic-function-methods gf))
+         (method (car methods))
+         (args (gf-fixed-arg-lambda-list gf)))
+    (when (and method
+               args
+               (null (cdr methods))
+               (null (method-qualifiers method))
+               (dolist (spec (method-specializers method))
+                 (unless (eq spec *t-class*) (return t))))
+      (compile nil
+               `(lambda ,args
+                 (cond ,(generate-conformance-clause args method)
+                       (t (no-applicable-method ,gf ,@args))))))))
+
+(register-non-dt-dcode-function #'dcode-for-fixed-arg-singleton-gf)
Index: /branches/new-random/lib/level-2.lisp
===================================================================
--- /branches/new-random/lib/level-2.lisp	(revision 13309)
+++ /branches/new-random/lib/level-2.lisp	(revision 13309)
@@ -0,0 +1,483 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; Level-2.lisp
+
+(in-package "CCL")
+
+(eval-when (eval compile)
+  (require "LEVEL-2")
+  (require "BACKQUOTE")
+  (require "DEFSTRUCT-MACROS"))
+
+
+
+(eval-when (eval compile)
+  (require "LISPEQU"))
+
+
+
+
+
+
+
+
+; This incredibly essential thing is part of ANSI CL; put it in the
+; right package someday.
+; Like maybe when it says something about doc strings, or otherwise
+; becomes useful.
+
+(defun parse-macro (name arglist body &optional env)
+  (values (parse-macro-1 name arglist body env)))
+
+; Return a list containing a special declaration for SYM
+; if SYM is declared special in decls.
+; This is so we can be pedantic about binding &WHOLE/&ENVIRONMENT args
+; that have been scarfed out of a macro-like lambda list.
+; The returned value is supposed to be suitable for splicing ...
+(defun hoist-special-decls (sym decls)
+  (when sym
+    (dolist (decl decls)
+      (dolist (spec (cdr decl))
+        (when (eq (car spec) 'special)
+          (dolist (s (%cdr spec))
+            (when (eq s sym)
+              (return-from hoist-special-decls `((declare (special ,sym)))))))))))
+
+(defun parse-macro-1 (name arglist body &optional env)
+  (parse-macro-internal name arglist body env nil))
+
+(defun parse-macro-internal (name arglist body env default-initial-value)
+  (unless (verify-lambda-list arglist t t t)
+    (error "Invalid lambda list ~s" arglist))
+  (multiple-value-bind (lambda-list whole environment)
+      (normalize-lambda-list arglist t t)
+    (multiple-value-bind (body local-decs doc)
+        (parse-body body env t)
+      (let ((whole-var (gensym "WHOLE"))
+            (env-var (gensym "ENVIRONMENT")))
+        (multiple-value-bind (bindings binding-decls)
+            (%destructure-lambda-list lambda-list whole-var nil nil
+                                      :cdr-p t
+                                      :whole-p nil
+                                      :use-whole-var t
+                                      :default-initial-value default-initial-value)
+          (when environment
+            (setq bindings (nconc bindings (list `(,environment ,env-var)))))
+          (when whole
+            (setq bindings (nconc bindings (list `(,whole ,whole-var)))))
+          (values
+            `(lambda (,whole-var ,env-var)
+               (declare (ignorable ,whole-var ,env-var))
+               (block ,name
+                 (let* ,(nreverse bindings)
+                   ,@(when binding-decls `((declare ,@binding-decls)))
+                   ,@local-decs
+                   ,@body)))
+            doc))))))
+
+
+(defun %destructure-lambda-list (lambda-list wholeform  lets decls
+					     &key cdr-p (whole-p t) use-whole-var default-initial-value)
+  (unless (and (listp lambda-list)
+               (verify-lambda-list lambda-list t whole-p))
+    (signal-simple-program-error "Invalid lambda list: ~s" lambda-list))
+  (multiple-value-bind (normalized whole) (normalize-lambda-list
+					   lambda-list whole-p)
+    (let* ((argstate :required)
+	   (allow-other-keys nil)
+	   (rest-arg-name nil)
+	   (w (if use-whole-var wholeform (or whole (gensym "WHOLE"))))
+	   (argptr (gensym "ARGS"))
+	   (has-&key nil)
+	   (most-recent-binding nil)
+	   (keywords ())
+	   (first-keyword-init ())
+	   (restp nil))
+      (labels ((simple-var (var &optional (initform `,default-initial-value))
+		 (let* ((binding `(,var ,initform)))
+		   (unless (eq argstate :aux)
+		     (setq most-recent-binding binding))
+		   (push  binding lets)
+		   binding))
+	       (structured-var (context sub-lambda-list initform)
+		 (let* ((v (gensym (string context))))
+		   (simple-var v initform)
+		   (multiple-value-setq (lets decls)
+		     (%destructure-lambda-list
+		      sub-lambda-list
+		      v
+		      lets
+		      decls
+		      :default-initial-value default-initial-value
+))
+		   v)))
+	(unless use-whole-var
+	  (if (atom w)
+	    (simple-var w wholeform)
+	    (progn
+	      (setq w (structured-var "WHOLE" w (if cdr-p `(cdr ,wholeform) wholeform))
+		    cdr-p nil))))
+	(simple-var argptr `(make-destructure-state ,@(if cdr-p `((cdr ,w)) `(,w)) ,w ',lambda-list))
+	(setq most-recent-binding nil)
+	(push `(dynamic-extent ,argptr) decls)
+	(do* ((tail normalized (cdr tail)))
+	     ((null tail)
+	      (if has-&key
+		(let* ((key-check-form `(check-keywords
+					 ',(nreverse keywords)
+					 ,rest-arg-name ,allow-other-keys)))
+		  (if first-keyword-init
+		    (rplaca (cdr first-keyword-init)
+			    `(progn
+			      ,key-check-form
+			      ,(cadr first-keyword-init)))
+		    (let* ((check-var (gensym "CHECK")))
+		      (push `(ignorable ,check-var) decls)
+		      (simple-var check-var key-check-form))))
+		(unless restp
+		  (let* ((checkform `(%check-extra-arguments ,argptr))
+			 (b most-recent-binding)
+			 (b-init (cadr b)))
+		    (if b
+		      (rplaca (cdr b) `(prog1 ,b-init ,checkform))
+		      (let* ((junk (gensym "JUNK")))
+			(simple-var junk checkform)
+			(push `(ignorable ,junk) decls))))))
+	      (values lets decls))
+	  (let* ((var (car tail)))
+	    (cond ((or (eq var '&rest) (eq var '&body))
+		   (let* ((r (cadr tail))
+			  (init `(destructure-state.current ,argptr)))
+		     (if (listp r)
+		       (setq rest-arg-name
+			     (structured-var "REST" r init))
+		       (progn
+			 (setq rest-arg-name (gensym "REST"))
+			 (simple-var rest-arg-name init)
+			 (simple-var r rest-arg-name ))))
+		   (setq restp t)
+		   (setq tail (cdr tail)))
+		  ((eq var '&optional) (setq argstate :optional))
+		  ((eq var '&key)
+		   (setq argstate :key)
+		   (setq has-&key t)
+		   (unless restp
+		     (setq restp t
+			   rest-arg-name (gensym "KEYS"))
+		     (push `(ignorable ,rest-arg-name) decls)
+		     (simple-var rest-arg-name
+				 `(destructure-state.current ,argptr))))
+		  ((eq var '&allow-other-keys)
+		   (setq allow-other-keys t))
+		  ((eq var '&aux)
+		   (setq argstate :aux))
+		  ((listp var)
+		   (case argstate
+		     (:required
+		      (structured-var "REQ" var `(%pop-required-arg-ptr ,argptr)))
+		     (:optional
+		      (let* ((variable (car var))
+			     (initform (if (cdr var)
+					 (cadr var)
+					 `,default-initial-value))
+			     (spvar (if (cddr var)
+				      (caddr var)
+				      (gensym "OPT-SUPPLIED-P")))
+			     (varinit `(if ,spvar
+					(%default-optional-value ,argptr)
+					,initform)))
+			(simple-var spvar
+				    `(not (null (destructure-state.current ,argptr))))
+			(if (listp variable)
+			  (structured-var "OPT" variable varinit)
+			  (simple-var variable varinit))))
+		     (:key
+		      (let* ((explicit-key (consp (car var)))
+			     (variable (if explicit-key
+					 (cadar var)
+					 (car var)))
+			     (keyword (if explicit-key
+					(caar var)
+					(make-keyword variable)))
+			     (initform (if (cdr var)
+					 (cadr var)
+					 `,default-initial-value))
+			     (spvar (if (cddr var)
+				      (caddr var)
+				      (gensym "KEY-SUPPLIED-P"))))
+			(push keyword keywords)
+			(let* ((sp-init (simple-var spvar
+						    `(%keyword-present-p
+						      ,rest-arg-name
+						      ',keyword)))
+			       (var-init `(if ,spvar
+					   (getf ,rest-arg-name ',keyword)
+					   ,initform)))
+			  (unless first-keyword-init
+			    (setq first-keyword-init sp-init))
+			  (if (listp variable)
+			    (structured-var "KEY" variable var-init)
+			    (simple-var variable var-init)))))
+		     (:aux
+		      (simple-var (car var) (cadr var)))
+		     (t (error "NYI: ~s" argstate))))
+		  ((symbolp var)
+		   (case argstate
+		     (:required
+		      (simple-var var `(%pop-required-arg-ptr ,argptr)))
+		     (:optional
+		      (simple-var var `(%default-optional-value ,argptr
+					',default-initial-value)))
+		     (:key
+		      (let* ((keyword (make-keyword var)))
+			(push keyword keywords)
+			(let* ((init (simple-var
+				      var
+				      `(getf ,rest-arg-name
+					',keyword
+					,@(if default-initial-value
+                                             `(',default-initial-value))))))
+			  (unless first-keyword-init
+			    (setq first-keyword-init init)))))
+		     (:aux
+		      (simple-var var)))))))))))
+
+
+
+
+
+
+(defun apply-to-htab-syms (function pkg-vector)
+  (let* ((sym nil)
+         (foundp nil))
+    (dotimes (i (uvsize pkg-vector))
+      (declare (fixnum i))
+      (multiple-value-setq (sym foundp) (%htab-symbol pkg-vector i))
+      (when foundp (funcall function sym)))))
+
+(defun iterate-over-external-symbols (pkg-spec function)
+  (apply-to-htab-syms function (car (pkg.etab (pkg-arg (or pkg-spec *package*))))))
+
+(defun iterate-over-present-symbols (pkg-spec function)
+  (let ((pkg (pkg-arg (or pkg-spec *package*))))
+    (apply-to-htab-syms function (car (pkg.etab pkg)))
+    (apply-to-htab-syms function (car (pkg.itab pkg)))))
+
+(defun iterate-over-accessable-symbols (pkg-spec function)
+  (let* ((pkg (pkg-arg (or pkg-spec *package*)))
+         (used (pkg.used pkg))
+         (shadowed (pkg.shadowed pkg)))
+    (iterate-over-present-symbols pkg function)
+    (when used
+      (if shadowed
+        (flet ((ignore-shadowed-conflicts (var)
+                 (unless (%name-present-in-package-p (symbol-name var) pkg)
+                   (funcall function var))))
+          (declare (dynamic-extent #'ignore-shadowed-conflicts))
+          (dolist (u used) (iterate-over-external-symbols u #'ignore-shadowed-conflicts)))
+        (dolist (u used) (iterate-over-external-symbols u function))))))
+
+(defun iterate-over-all-symbols (function)
+  (dolist (pkg %all-packages%)
+    (iterate-over-present-symbols pkg function)))          
+
+
+
+;;;Eval definitions for things open-coded by the compiler.
+;;;Don't use DEFUN since it should be illegal to DEFUN compiler special forms...
+;;;Of course, these aren't special forms.
+(macrolet ((%eval-redef (name vars &rest body)
+             (when (null body) (setq body `((,name ,@vars))))
+             `(setf (symbol-function ',name)
+                    (qlfun ,name ,vars ,@body))))
+  (declare (optimize (speed 1) (safety 1)))
+  (%eval-redef %ilsl (n x))
+  (%eval-redef %ilsr (n x))
+  (%eval-redef neq (x y))
+  (%eval-redef not (x))
+  (%eval-redef null (x))
+  (%eval-redef rplaca (x y))
+  (%eval-redef rplacd (x y))
+  (%eval-redef set-car (x y))
+  (%eval-redef set-cdr (x y))
+  (%eval-redef int>0-p (x))
+  (%eval-redef %get-byte (ptr &optional (offset 0)) (%get-byte ptr offset))
+  (%eval-redef %get-word (ptr &optional (offset 0)) (%get-word ptr offset))
+  (%eval-redef %get-signed-byte (ptr &optional (offset 0)) (%get-signed-byte ptr offset))
+  (%eval-redef %get-signed-word (ptr &optional (offset 0)) (%get-signed-word ptr offset))
+  (%eval-redef %get-long (ptr &optional (offset 0)) (%get-long ptr offset))
+  (%eval-redef %get-fixnum (ptr &optional (offset 0)) (%get-fixnum ptr offset))
+  (%eval-redef %get-signed-long (ptr &optional (offset 0)) (%get-signed-long ptr offset))
+  (%eval-redef %get-unsigned-long (ptr &optional (offset 0)) (%get-unsigned-long ptr offset))
+  (%eval-redef %get-ptr (ptr &optional (offset 0)) (%get-ptr ptr offset))
+  (%eval-redef %get-full-long (ptr &optional (offset 0)) (%get-full-long ptr offset))
+  (%eval-redef %int-to-ptr (int))
+  (%eval-redef %ptr-to-int (ptr))
+  (%eval-redef %ptr-eql (ptr1 ptr2))
+  (%eval-redef %setf-macptr (ptr1 ptr2))
+  (%eval-redef %null-ptr-p (ptr))
+
+
+  (%eval-redef %iasr (x y))
+
+  
+  (%eval-redef %set-byte (p o &optional (new (prog1 o (setq o 0))))
+               (%set-byte p o new))
+  (%eval-redef %set-unsigned-byte (p o &optional (new (prog1 o (setq o 0))))
+               (%set-unsigned-byte p o new))
+  (%eval-redef %set-word (p o &optional (new (prog1 o (setq o 0))))
+               (%set-word p o new))
+  (%eval-redef %set-unsigned-word (p o &optional (new (prog1 o (setq o 0))))
+               (%set-unsigned-word p o new))
+  (%eval-redef %set-long (p o &optional (new (prog1 o (setq o 0))))
+               (%set-long p o new))
+  (%eval-redef %set-unsigned-long (p o &optional (new (prog1 o (setq o 0))))
+               (%set-unsigned-long p o new))
+  (%eval-redef %set-ptr (p o &optional (new (prog1 o (setq o 0))))
+               (%set-ptr p o new))
+
+  
+  (%eval-redef %word-to-int (word))
+  (%eval-redef %inc-ptr (ptr &optional (by 1)) (%inc-ptr ptr by))
+  
+  (%eval-redef char-code (x))
+  (%eval-redef code-char (x))
+  (%eval-redef 1- (n))
+  (%eval-redef 1+ (n))
+
+  (%eval-redef uvref (x y))
+  (%eval-redef uvset (x y z))
+  (%eval-redef uvsize (x))
+
+  (%eval-redef svref (x y))
+  (%eval-redef svset (x y z))
+  
+ 
+  
+  (%eval-redef car (x))
+  (%eval-redef cdr (x))
+  (%eval-redef cons (x y))
+  (%eval-redef endp (x))
+
+  (progn
+    (%eval-redef typecode (x))
+    (%eval-redef lisptag (x))
+    (%eval-redef fulltag (x))
+    (%eval-redef %unbound-marker ())
+    (%eval-redef %slot-unbound-marker ())
+    (%eval-redef %slot-ref (v i))
+    (%eval-redef %alloc-misc (count subtag &optional (initial nil initial-p))
+                 (if initial-p
+                   (%alloc-misc count subtag initial)
+                   (%alloc-misc count subtag)))
+    (%eval-redef %setf-double-float (x y))
+    (%eval-redef %lisp-word-ref (x y))
+    (%eval-redef %temp-cons (x y))
+    (%eval-redef require-fixnum (x))
+    (%eval-redef require-symbol (x))
+    (%eval-redef require-list (x))
+    (%eval-redef require-real (x))
+    (%eval-redef require-simple-string (x))
+    (%eval-redef require-simple-vector (x))
+    (%eval-redef require-character (x))
+    (%eval-redef require-number (x))
+    (%eval-redef require-integer (x))
+    (%eval-redef require-s8 (x))
+    (%eval-redef require-u8 (x))
+    (%eval-redef require-s16 (x))
+    (%eval-redef require-u16 (x))
+    (%eval-redef require-s32 (x))
+    (%eval-redef require-u32 (x))
+    (%eval-redef require-s64 (x))
+    (%eval-redef require-u64 (x))
+    (%eval-redef %reference-external-entry-point (x))
+    )
+  
+  (%eval-redef %get-bit (ptr offset))
+  (%eval-redef %set-bit (ptr offset val))
+  (%eval-redef %get-double-float (ptr &optional (offset 0))
+	       (%get-double-float ptr offset))
+  (%eval-redef %get-single-float (ptr &optional (offset 0))
+	       (%get-single-float ptr offset))
+  (%eval-redef %set-double-float (p o &optional (new (prog1 o (setq o 0))))
+	       (%set-double-float p o new))
+  (%eval-redef %set-single-float (p o &optional (new (prog1 o (setq o 0))))
+	       (%set-single-float p o new))
+  (%eval-redef assq (item list))
+)
+
+; In the spirit of eval-redef ...
+
+
+;; pointer hacking stuff 
+;
+;
+
+
+
+;;; I'd guess that the majority of bitfields in the world whose width is
+;;; greater than 1 have a width of two.  If that's true, this is probably
+;;; faster than trying to be more clever about it would be.
+(defun %get-bitfield (ptr start-bit width)
+  (declare (fixnum start-bit width))
+  (do* ((bit #+big-endian-target start-bit
+             #+little-endian-target (the fixnum (1- (the fixnum (+ start-bit width))))
+             #+big-endian-target (1+ bit)
+             #+little-endian-target (1- bit))
+	(i 0 (1+ i))
+	(val 0))
+       ((= i width) val)
+    (declare (fixnum val i bit))
+    (setq val (logior (ash val 1) (%get-bit ptr bit)))))
+
+(defun %set-bitfield (ptr start width val)
+  (declare (fixnum val start width))
+  (do* ((v val (ash v -1))
+	(bit #+big-endian-target (1- (+ start width))
+             #+little-endian-target start
+             #+big-endian-target (1- bit)
+             #+little-endian-target (1+ bit))
+	(i 0 (1+ i)))
+       ((= i width) val)
+    (declare (fixnum v bit i))
+    (setf (%get-bit ptr bit) (logand v 1))))
+
+; expands into compiler stuff
+
+(setf (symbol-function '%get-unsigned-byte) (symbol-function '%get-byte))
+(setf (symbol-function '%get-unsigned-word) (symbol-function '%get-word))
+(setf (symbol-function '%get-signed-long) (symbol-function '%get-long))
+
+(defun decompose-record-accessor (accessor &aux ret)
+  (do* ((str (symbol-name accessor) (%substr str (+ i 1) len))
+        (len (length str) (length str))
+        (i (%str-member #\. str) (%str-member #\. str))
+        (field (%substr str 0 (or i len)) (%substr str 0 (or i len))))
+       ((not i) (nreverse (cons (make-keyword field) ret)))
+    (push (make-keyword field) ret)))
+
+
+
+
+(provide 'level-2)
+
+	
+
+
+;; end of level-2.lisp
+
Index: /branches/new-random/lib/lists.lisp
===================================================================
--- /branches/new-random/lib/lists.lisp	(revision 13309)
+++ /branches/new-random/lib/lists.lisp	(revision 13309)
@@ -0,0 +1,898 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (eval compile)
+  (require 'backquote)
+  (require 'level-2))
+
+
+
+;;; These functions perform basic list operations:
+
+#|
+(defun caar (list) (car (car list)))
+(defun cadr (list) (car (cdr list)))
+(defun cdar (list) (cdr (car list)))
+(defun cddr (list) (cdr (cdr list)))
+
+(defun caaar (list) (car (caar list)))
+(defun caadr (list) (car (cadr list)))
+(defun cadar (list) (car (cdar list)))
+(defun caddr (list) (car (cddr list)))
+(defun cdaar (list) (cdr (caar list)))
+(defun cdadr (list) (cdr (cadr list)))
+(defun cddar (list) (cdr (cdar list)))
+(defun cdddr (list) (cdr (cddr list)))
+|#
+
+
+(defun caaaar (list)
+  "Return the car of the caaar of a list."
+  (car (caaar list)))
+
+(defun caaadr (list)
+  "Return the car of the caadr of a list."
+  (car (caadr list)))
+
+(defun caadar (list)
+  "Return the car of the cadar of a list."
+  (car (cadar list)))
+
+(defun caaddr (list)
+  "Return the car of the caddr of a list."
+  (car (caddr list)))
+
+(defun cadaar (list)
+  "Return the car of the cdaar of a list."
+  (car (cdaar list)))
+
+(defun cadadr (list)
+  "Return the car of the cdadr of a list."
+  (car (cdadr list)))
+
+(defun caddar (list)
+  "Return the car of the cddar of a list."
+  (car (cddar list)))
+
+(defun cdaaar (list)
+  "Return the cdr of the caaar of a list."
+  (cdr (caaar list)))
+
+(defun cdaadr (list)
+  "Return the cdr of the caadr of a list."
+  (cdr (caadr list)))
+
+(defun cdadar (list)
+  "Return the cdr of the cadar of a list."
+  (cdr (cadar list)))
+
+(defun cdaddr (list)
+  "Return the cdr of the caddr of a list."
+  (cdr (caddr list)))
+
+(defun cddaar (list)
+  "Return the cdr of the cdaar of a list."
+  (cdr (cdaar list)))
+
+(defun cddadr (list)
+  "Return the cdr of the cdadr of a list."
+  (cdr (cdadr list)))
+
+(defun cdddar (list)
+  "Return the cdr of the cddar of a list."
+  (cdr (cddar list)))
+
+(defun cddddr (list)
+  "Return the cdr of the cdddr of a list."
+  (cdr (cdddr list)))
+
+(defun tree-equal (x y &key (test (function eql)) test-not)
+  "Returns T if X and Y are isomorphic trees with identical leaves."
+  (if test-not
+      (tree-equal-test-not x y test-not)
+      (tree-equal-test x y test)))
+
+(defun tree-equal-test-not (x y test-not)
+  (cond ((and (atom x) (atom y))
+         (if (and (not x) (not y)) ;must special case end of both lists.
+           t
+           (if (not (funcall test-not x y)) t)))
+	((consp x)
+	 (and (consp y)
+	      (tree-equal-test-not (car x) (car y) test-not)
+	      (tree-equal-test-not (cdr x) (cdr y) test-not)))
+	(t ())))
+
+(defun tree-equal-test (x y test)
+  (if (atom x)
+    (if (atom y)
+      (if (funcall test x y) t))
+    (and (consp y)
+         (tree-equal-test (car x) (car y) test)
+         (tree-equal-test (cdr x) (cdr y) test))))
+
+(defun first (list)
+  "Return the 1st object in a list or NIL if the list is empty."
+  (car list))
+
+(defun second (list)
+  "Return the 2nd object in a list or NIL if there is no 2nd object."
+  (cadr list))
+
+(defun third (list)
+  "Return the 3rd object in a list or NIL if there is no 3rd object."
+  (caddr list))
+
+(defun fourth (list)
+  "Return the 4th object in a list or NIL if there is no 4th object."
+  (cadddr list))
+
+(defun fifth (list)
+  "Return the 5th object in a list or NIL if there is no 5th object."
+  (car (cddddr list)))
+
+(defun sixth (list)
+  "Return the 6th object in a list or NIL if there is no 6th object."
+  (cadr (cddddr list)))
+
+(defun seventh (list)
+  "Return the 7th object in a list or NIL if there is no 7th object."
+  (caddr (cddddr list)))
+
+(defun eighth (list)
+  "Return the 8th object in a list or NIL if there is no 8th object."
+  (cadddr (cddddr list)))
+
+(defun ninth (list)
+  "Return the 9th object in a list or NIL if there is no 9th object."
+  (car (cddddr (cddddr list))))
+
+(defun tenth (list)
+  "Return the 10th object in a list or NIL if there is no 10th object."
+  (cadr (cddddr (cddddr list))))
+
+(defun rest (list)
+  "Means the same as the cdr of a list."
+  (cdr list))
+;;; List* is done the same as list, except that the last cons is made a
+;;; dotted pair
+
+
+;;; List Copying Functions
+
+;;; The list is copied correctly even if the list is not terminated by ()
+;;; The new list is built by cdr'ing splice which is always at the tail
+;;; of the new list
+
+
+(defun copy-alist (alist)
+  "Return a new association list which is EQUAL to ALIST."
+  (unless (endp alist)
+    (let ((result
+           (cons (if (endp (car alist))
+                   (car alist)
+                   (cons (caar alist) (cdar alist)) )
+                 '() )))	      
+      (do ((x (cdr alist) (cdr x))
+           (splice result
+                   (cdr (rplacd splice
+                                (cons
+                                 (if (endp (car x)) 
+                                   (car x)
+                                   (cons (caar x) (cdar x)))
+                                 '() ))) ))
+          ((endp x) result)))))
+
+;;; More Commonly-used List Functions
+
+(defun revappend (x y)
+  "Return (append (reverse x) y)."
+  (dolist (a x y) (push a y)))
+
+
+
+
+(defun butlast (list &optional (n 1 n-p))
+  "Returns a new list the same as List without the N last elements."
+  (setq list (require-type list 'list))
+  (when (and n-p
+	     (if (typep n 'fixnum)
+	       (< (the fixnum n) 0)
+	       (not (typep n 'unsigned-byte))))
+    (report-bad-arg n 'unsigned-byte))
+  (let* ((length (alt-list-length list)))
+    (declare (fixnum length))		;guaranteed
+    (when (< n length)
+      (let* ((count (- length (the fixnum n)))
+	     (head (cons nil nil))
+	     (tail head))
+	(declare (fixnum count) (cons head tail) (dynamic-extent head))
+	;; Return a list of the first COUNT elements of list
+	(dotimes (i count (cdr head))
+	  (setq tail (cdr (rplacd tail (cons (pop list) nil)))))))))
+
+
+(defun nbutlast (list &optional (n 1 n-p))
+  "Modifies List to remove the last N elements."
+  (setq list (require-type list 'list))
+  (when (and n-p
+	     (if (typep n 'fixnum)
+	       (< (the fixnum n) 0)
+	       (not (typep n 'unsigned-byte))))
+    (report-bad-arg n 'unsigned-byte))
+  (let* ((length (alt-list-length list)))
+    (declare (fixnum length))		;guaranteed
+    (when (< n length)
+      (let* ((count (1- (the fixnum (- length (the fixnum n)))))
+	     (tail list))
+	(declare (fixnum count) (list tail))
+	(dotimes (i count (rplacd tail nil))
+	  (setq tail (cdr tail)))
+	list))))
+      
+
+(defun ldiff (list object)
+  "Return a new list, whose elements are those of LIST that appear before
+   OBJECT. If OBJECT is not a tail of LIST, a copy of LIST is returned.
+   LIST must be a proper list or a dotted list."
+  (do* ((list (require-type list 'list) (cdr list)) 
+        (result (cons nil nil))
+        (splice result))
+       ((atom list) 
+        (if (eql list object) 
+	  (cdr result) 
+	  (progn (rplacd splice list) (cdr result))))
+    (declare (dynamic-extent result)
+	     (cons splice result))
+    (if (eql list object) 
+      (return (cdr result)) 
+      (setq splice (cdr (rplacd splice (list (car list))))))))
+
+
+;;; Functions to alter list structure
+
+;;; The following are for use by SETF.
+
+(defun %setnth (n list newval)
+  "Sets the Nth element of List (zero based) to Newval."
+  (if (%i< n 0)
+      (error "~S is an illegal N for SETF of NTH." n)
+      (do ((count n (%i- count 1)))
+          ((%izerop count) (rplaca list newval) newval)
+        (if (endp (cdr list))
+            (error "~S is too large an index for SETF of NTH." n)
+            (setq list (cdr list))))))
+
+(defun test-not-error (test test-not)
+  (%err-disp $xkeyconflict :test test :test-not test-not))
+
+;;; Use this with the following keyword args:
+;;;  (&key (key #'identity) (test #'eql testp) (test-not nil notp))
+
+(eval-when (eval compile #-bccl load)
+ (defmacro with-set-keys (funcall)
+   `(cond (notp ,(append funcall '(:key key :test-not test-not)))
+          (t ,(append funcall '(:key key :test test)))))
+
+;;; Works with the above keylist.  We do three clauses so that if only test-not
+;;; is supplied, then we don't test eql.  In each case, the args should be 
+;;; multiply evaluable.
+
+(defmacro elements-match-p (elt1 elt2)
+  `(or (and testp
+	    (funcall test (funcall key ,elt1) (funcall key ,elt2)))
+       (and notp
+	    (not (funcall test-not (funcall key ,elt1) (funcall key ,elt2))))
+       (eql (funcall key ,elt1) (funcall key ,elt2))))
+
+
+
+)
+;;; Substitution of expressions
+
+;subst that doesn't call labels
+(defun subst (new old tree &key key
+		           (test #'eql testp) (test-not nil notp))
+  "Substitutes new for subtrees matching old."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (subst-aux new old tree key test test-not))
+
+(defun subst-aux (new old subtree key test test-not)
+  (flet ((satisfies-the-test (item elt)
+           (let* ((val (if key (funcall key elt) elt)))
+             (if test-not
+               (not (funcall test-not item val))
+               (funcall test item val)))))
+    (declare (inline satisfies-the-test))
+    (cond ((satisfies-the-test old subtree) new)
+          ((atom subtree) subtree)
+          (t (let ((car (subst-aux new old (car subtree)
+                                   key test test-not ))
+                   (cdr (subst-aux new old (cdr subtree)
+                                   key test test-not)))
+               (if (and (eq car (car subtree))
+                        (eq cdr (cdr subtree)))
+                 subtree
+                 (cons car cdr)))))))
+
+;;;subst-if without a call to labels
+;;; I've always wondered how those calls to a special operator
+;;; should best be avoided.  Clearly, the answer involves
+;;; lots of recursion.
+(defun subst-if (new test tree &key key)
+  "Substitutes new for subtrees for which test is true."
+  (unless key (setq key #'identity))
+  (cond ((funcall test (funcall key tree)) new)
+        ((atom tree) tree)
+        (t (let ((car (subst-if new test (car tree) :key key))
+                 (cdr (subst-if new test (cdr tree) :key key)))
+             (if (and (eq car (car tree))
+                      (eq cdr (cdr tree)))
+               tree
+               (cons car cdr))))))
+
+;subst-if-not without a call to labels
+(defun subst-if-not (new test tree &key key)
+  "Substitutes new for subtrees for which test is false."
+  (unless key (setq key #'identity))
+  (cond ((not (funcall test (funcall key tree))) new)
+        ((atom tree) tree)
+        (t (let ((car (subst-if-not new test (car tree) :key key))
+                 (cdr (subst-if-not new test (cdr tree) :key key)))
+             (if (and (eq car (car tree))
+                      (eq cdr (cdr tree)))
+               tree
+               (cons car cdr))))))
+
+(defun nsubst (new old tree &key key
+                   (test #'eql testp) (test-not nil notp))
+  "Substitute NEW for subtrees matching OLD."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (nsubst-aux new old tree (or key #'identity) test test-not))
+
+(defun nsubst-aux (new old subtree key test test-not)
+  (flet ((satisfies-the-test (item elt)
+           (let* ((val (if key (funcall key elt) elt)))
+             (if test-not
+               (not (funcall test-not item val))
+               (funcall test item val)))))
+    (declare (inline satisfies-the-test))
+    (cond ((satisfies-the-test old subtree) new)
+          ((atom subtree) subtree)
+          (t (do* ((last nil subtree)
+                   (subtree subtree (cdr subtree)))
+                  ((atom subtree)
+                   (if (satisfies-the-test old subtree)
+                     (set-cdr last new)))
+               (if (satisfies-the-test old subtree)
+                 (return (set-cdr last new))
+                 (set-car subtree 
+                          (nsubst-aux new old (car subtree)
+                                      key test test-not))))
+             subtree))))
+
+(defun nsubst-if (new test tree &key key)
+  "Substitute NEW for subtrees of TREE for which TEST is true."
+  (unless key (setq key #'identity))
+  (cond ((funcall test (funcall key tree)) new)
+        ((atom tree) tree)
+        (t (do* ((last nil tree)
+                 (tree tree (cdr tree)))
+                ((atom tree)
+                 (if (funcall test (funcall key tree))
+                   (set-cdr last new)))
+             (if (funcall test (funcall key tree))
+               (return (set-cdr last new))
+               (set-car tree 
+                        (nsubst-if new test (car tree) :key key))))
+           tree)))
+
+(defun nsubst-if-not (new test tree &key key)
+  "Substitute NEW for subtrees of TREE for which TEST is false."
+  (unless key (setq key #'identity))
+  (cond ((not (funcall test (funcall key tree))) new)
+        ((atom tree) tree)
+        (t (do* ((last nil tree)
+                 (tree tree (cdr tree)))
+                ((atom tree)
+                 (if (not (funcall test (funcall key tree)))
+                   (set-cdr last new)))
+             (if (not (funcall test (funcall key tree)))
+               (return (set-cdr (cdr last) new))
+               (set-car tree 
+                        (nsubst-if-not new test (car tree) :key key))))
+           tree)))
+
+(defun sublis (alist tree &key key
+                     (test #'eql testp) (test-not nil notp))
+  "Substitute from ALIST into TREE nondestructively."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (sublis-aux alist tree (or key #'identity) test test-not notp))
+
+(defun sublis-aux  (alist subtree key test test-not notp) 
+  (let ((assoc (if notp
+                 (assoc (funcall key subtree) alist :test-not test-not)
+                 (assoc (funcall key subtree) alist :test test))))
+    (cond (assoc (cdr assoc))
+          ((atom subtree) subtree)
+          (t (let ((car (sublis-aux alist (car subtree)
+                                    key test test-not notp))
+                   (cdr (sublis-aux alist (cdr subtree)
+                                    key test test-not notp)))
+               (if (and (eq car (car subtree))
+                        (eq cdr (cdr subtree)))
+                 subtree
+                 (cons car cdr)))))))
+
+(eval-when (compile eval)
+  (defmacro nsublis-macro ()
+    '(if notp
+       (assoc (funcall key subtree) alist :test-not test-not)
+       (assoc (funcall key subtree) alist :test test)))
+  )
+
+(defun nsublis (alist tree &key key
+                      (test #'eql testp) (test-not nil notp))
+  "Substitute from ALIST into TRUE destructively."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (nsublis-aux alist tree (or key #'identity) test test-not notp))
+
+(defun nsublis-aux (alist subtree key test test-not notp &optional temp)
+  (cond ((setq temp (nsublis-macro))
+         (cdr temp))
+        ((atom subtree) subtree)
+        (t (do*  ((last nil subtree)
+                  (subtree subtree (cdr subtree)))
+                 ((atom subtree)
+                  (if (setq temp (nsublis-macro))
+                    (set-cdr last (cdr temp))))
+             (if (setq temp (nsublis-macro))
+               (return (set-cdr last (cdr temp)))
+               (set-car subtree 
+                        (nsublis-aux alist (car subtree) key test
+                                     test-not notp temp))))
+           subtree)))
+
+;;; Functions for using lists as sets
+
+
+(defun member-if (test list &key key )
+  "Return tail of LIST beginning with first element satisfying TEST."
+  (unless key (setq key #'identity))
+  (do ((list list (Cdr list)))
+      ((endp list) nil)
+    (if (funcall test (funcall key (car list)))
+      (return list))))
+
+(defun member-if-not (test list &key key)
+  "Return tail of LIST beginning with first element not satisfying TEST."
+  (unless key (setq key #'identity))
+  (do ((list list (cdr list)))
+      ((endp list) ())
+    (if (not (funcall test (funcall key (car list))))
+      (return list))))
+
+(defun tailp (sublist list)                  ;Definition "B"
+  "Return true if OBJECT is the same as some tail of LIST, otherwise
+   returns false. LIST must be a proper list or a dotted list."
+  (do ((list list (%cdr list)))
+      ((atom list) (eql list sublist))
+    (if (eq sublist list)
+      (return t))))
+
+
+ 
+(defun union (list1 list2  &key
+                    key
+                    (test #'eql testp)
+                    (test-not nil notp))
+  "Returns the union of LIST1 and LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (let ((res list2))
+    (dolist (elt list1)
+      (if (not (with-set-keys (member (funcall key elt) list2)))
+        (push elt res)))
+    res))
+
+
+
+
+
+
+(eval-when (eval compile #-bccl load)
+;;; Destination and source are setf-able and many-evaluable.
+;;; Sets the source to the cdr, and "conses" the 1st elt of 
+;;; source to destination.
+(defmacro steve-splice (source destination)
+  `(let ((temp ,source))
+     (setf ,source (cdr ,source)
+           (cdr temp) ,destination
+           ,destination temp)))
+)
+
+(defun nunion (list1 list2 &key key
+                     (test #'eql testp) (test-not nil notp))
+  "Destructively return the union of LIST1 and LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (let ((res list2))
+    (do ()
+        ((endp list1))
+      (if (not (with-set-keys (member (funcall key (car list1)) list2)))
+        (steve-splice list1 res)
+        (setq list1 (cdr list1))))
+    res))
+
+
+
+
+(defun intersection (list1 list2  &key key
+                           (test #'eql testp) (test-not nil notp))
+  "Return the intersection of LIST1 and LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (let ((res nil))
+    (dolist (elt list1)
+      (if (with-set-keys (member (funcall key elt) list2))
+        (push elt res)))
+    res))
+
+(defun nintersection (list1 list2 &key key
+                            (test #'eql testp) (test-not nil notp))
+  "Destructively return the intersection of LIST1 and LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (let ((res nil))
+    (do () ((endp list1))
+      (if (with-set-keys (member (funcall key (car list1)) list2))
+        (steve-splice list1 res)
+        (setq list1 (Cdr list1))))
+    res))
+
+(defun set-difference (list1 list2 &key key
+                             (test #'eql testp) (test-not nil notp))
+  "Return the elements of LIST1 which are not in LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (let ((res nil))
+    (dolist (elt list1)
+      (if (not (with-set-keys (member (funcall key elt) list2)))
+        (push elt res)))
+    res))
+
+(defun nset-difference (list1 list2 &key key
+                              (test #'eql testp) (test-not nil notp))
+  "Destructively return the elements of LIST1 which are not in LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (let ((res nil))
+    (do () ((endp list1))
+      (if (not (with-set-keys (member (funcall key (car list1)) list2)))
+	  (steve-splice list1 res)
+          (setq list1 (cdr list1))))
+    res))
+
+#| spice version
+(defun set-exclusive-or (list1 list2 &key (key #'identity)
+                               (test #'eql testp) (test-not nil notp))
+  "Returns new list of elements appearing exactly  once in List1 and List2.
+  If an element appears > once in a list and does not appear at all in the
+  other list, that element will appear >1 in the output list."
+  (let ((result nil))
+    (dolist (elt list1)
+      (unless (with-set-keys (member (funcall key elt) list2))
+        (setq result (cons elt result))))
+    (dolist (elt list2)
+      (unless (with-set-keys (member (funcall key elt) list1))
+        (setq result (cons elt result))))
+    result))
+|#
+
+(defun set-exclusive-or (list1 list2 &key key
+                               (test #'eql testp) (test-not nil notp)
+                               &aux result elt1-compare elt2-compare)
+  "Return new list of elements appearing exactly once in LIST1 and LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (dolist (elt1 list1)
+    (setq elt1-compare (funcall key elt1))
+    (if (if notp
+           (dolist (elt2 list2 t)
+            (if (not (funcall test-not elt1-compare (funcall key elt2)))
+              (return nil)))
+          (dolist (elt2 list2 t)
+            (if (funcall test elt1-compare (funcall key elt2))
+              (return nil))))
+      (push elt1 result)))
+  (dolist (elt2 list2)
+    (setq elt2-compare (funcall key elt2))
+    (if (if notp
+          (dolist (elt1 list1 t)
+            (if (not (funcall test-not (funcall key elt1) elt2-compare))
+              (return nil)))
+          (dolist (elt1 list1 t)
+            (if (funcall test (funcall key elt1) elt2-compare)
+              (return nil))))
+      (push elt2 result)))
+  result)
+
+#| the description of the below SpiceLisp algorthm used for implementing
+ nset-exclusive-or sounds counter to CLtL. Furthermore, it fails 
+on the example (nset-exclusive-or (list 1 1) (list 1))
+  [returns (1) but should return NIL.] ... fry
+
+;;; The outer loop examines list1 while the inner loop examines list2. If an
+;;; element is found in list2 "equal" to the element in list1, both are
+;;; spliced out. When the end of list1 is reached, what is left of list2 is
+;;; tacked onto what is left of list1.  The splicing operation ensures that
+;;; the correct operation is performed depending on whether splice is at the
+;;; top of the list or not
+
+(defun nset-exclusive-or (list1 list2 &key (test #'eql) (test-not nil notp)
+                                (key #'identity))
+  "Return a list with elements which appear but once in List1 and List2."
+  (do ((x list1 (cdr x))
+       (splicex ()))
+      ((endp x)
+       (if (null splicex)
+         (setq list1 list2)
+         (rplacd splicex list2))
+       list1)
+    (do ((y list2 (cdr y))
+         (splicey ()))
+        ((endp y) (setq splicex x))
+      (cond ((if notp 
+               (not (funcall test-not (funcall key (car x))
+                             (funcall key (car y))))
+               (funcall test (funcall key (car x)) 
+                        (funcall key (car y))))
+             (if (null splicex)
+               (setq list1 (cdr x))
+               (rplacd splicex (cdr x)))
+             (if (null splicey) 
+               (setq list2 (cdr y))
+               (rplacd splicey (cdr y)))
+             (return ()))			; assume lists are really sets
+            (t (setq splicey y))))))
+|#
+
+(defun nset-exclusive-or (list1 list2 &key key
+                               (test #'eql testp) (test-not nil notp))
+  "Destructively return a list with elements which appear but once in LIST1
+   and LIST2."
+   (if (and testp notp)
+     (test-not-error test test-not))
+   (unless key (setq key #'identity))
+   (if notp
+     (set-exclusive-or list1 list2 :key key :test-not test-not)
+     (set-exclusive-or list1 list2 :key key :test test)
+     ))
+
+(defun subsetp (list1 list2 &key key
+                      (test #'eql testp) (test-not nil notp))
+  "Return T if every element in LIST1 is also in LIST2."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key (setq key #'identity))
+  (dolist (elt list1)
+    (unless (with-set-keys (member (funcall key elt) list2))
+      (return-from subsetp nil)))
+  T)
+
+
+;;; Functions that operate on association lists
+
+(defun acons (key datum a-list)
+  "Construct a new alist by adding the pair (KEY . DATUM) to ALIST."
+  (cons (cons key datum) a-list))
+
+(defun pairlis (keys data &optional (alist '()))
+  "Construct an association list from KEYS and DATA (adding to ALIST)."
+  (do ((x keys (cdr x))
+       (y data (cdr y)))
+      ((and (endp x) (endp y)) alist)
+    (if (or (endp x) (endp y)) 
+      (error "The lists of keys and data are of unequal length."))
+    (setq alist (acons (car x) (car y) alist))))
+
+(defun default-identity-key (key)
+  (and key (neq key 'identity) (neq key #'identity) (coerce-to-function key)))
+
+(defun assoc-if (predicate alist &key key)
+  "Return the first cons in ALIST whose CAR satisfies PREDICATE. If
+   KEY is supplied, apply it to the CAR of each cons before testing."
+  (setq key (default-identity-key key))
+  (dolist (pair alist)
+    (when (and pair
+               (funcall predicate 
+                        (if key (funcall key (car pair))
+                            (car pair))))
+      (return pair))))
+
+(defun assoc-if-not (predicate alist &key key)
+  "Return the first cons in ALIST whose CAR does not satisfy PREDICATE.
+  If KEY is supplied, apply it to the CAR of each cons before testing."
+  (setq key (default-identity-key key))
+  (dolist (pair alist)
+    (when (and pair
+               (not (funcall predicate 
+                        (if key (funcall key (car pair))
+                            (car pair)))))
+      (return pair))))
+
+(defun rassoc-if (predicate alist &key key)
+  "Return the first cons in ALIST whose CDR satisfies PREDICATE. If KEY
+  is supplied, apply it to the CDR of each cons before testing."
+  (setq key (default-identity-key key))
+  (dolist (pair alist)
+    (when (and pair
+               (funcall predicate 
+                        (if key (funcall key (cdr pair))
+                            (cdr pair))))
+      (return pair))))
+
+(defun rassoc-if-not (predicate alist &key key)
+  "Return the first cons in ALIST whose CDR does not satisfy PREDICATE.
+  If KEY is supplied, apply it to the CDR of each cons before testing."
+  (setq key (default-identity-key key))
+  (dolist (pair alist)
+    (when (and pair
+               (not (funcall predicate 
+                        (if key (funcall key (cdr pair))
+                            (cdr pair)))))
+      (return pair))))
+
+
+(defun map1 (function original-arglists accumulate take-car)
+ "This function is called by mapc, mapcar, mapcan, mapl, maplist, and mapcon.
+ It Maps function over the arglists in the appropriate way. It is done when any
+ of the arglists runs out.  Until then, it CDRs down the arglists calling the
+ function and accumulating results as desired."
+  (let* ((length (length original-arglists))
+         (arglists (make-list length))
+         (args (make-list length))
+         (ret-list (list nil))
+         (temp ret-list))
+    (declare (dynamic-extent arglists args ret-list))
+    (let ((argstail arglists))
+      (dolist (arg original-arglists)
+        (setf (car (the cons argstail)) arg)
+        (pop argstail)))
+    (do ((res nil)
+         (argstail args args))
+        ((memq nil arglists)
+         (if accumulate
+             (cdr ret-list)
+             (car original-arglists)))
+      (do ((l arglists (cdr l)))
+          ((not l))
+        (setf (car (the cons argstail)) (if take-car (car (car l)) (car l)))
+        (rplaca l (cdr (car l)))
+        (pop argstail))
+      (setq res (apply function args))
+      (case accumulate
+        (:nconc 
+         (setq temp (last (nconc temp res))))
+        (:list  (rplacd temp (list res))
+                (setq temp (cdr temp)))))))
+
+(defun mapc (function list &rest more-lists)
+  "Apply FUNCTION to successive elements of lists. Return the second argument."
+  (declare (dynamic-extent more-lists))
+  (let ((arglists (cons list more-lists)))
+    (declare (dynamic-extent arglists))
+    (values (map1 function arglists nil t))))
+
+(defun mapcar (function list &rest more-lists)
+  "Apply FUNCTION to successive elements of LIST. Return list of FUNCTION
+   return values."
+  (declare (dynamic-extent more-lists))
+  (let ((arglists (cons list more-lists)))
+    (declare (dynamic-extent arglists))
+    (values (map1 function arglists :list t))))
+
+(defun mapcan (function list &rest more-lists)
+  "Apply FUNCTION to successive elements of LIST. Return NCONC of FUNCTION
+   results."
+  (declare (dynamic-extent more-lists))
+  (let ((arglists (cons list more-lists)))
+    (declare (dynamic-extent arglists))
+    (values (map1 function arglists :nconc t))))
+
+(defun mapl (function list &rest more-lists)
+  "Apply FUNCTION to successive CDRs of list. Return NIL."
+  (declare (dynamic-extent more-lists))
+  (let ((arglists (cons list more-lists)))
+    (declare (dynamic-extent arglists))
+    (values (map1 function arglists nil nil))))
+
+(defun maplist (function list &rest more-lists)
+  "Apply FUNCTION to successive CDRs of list. Return list of results."
+  (declare (dynamic-extent more-lists))
+  (let ((arglists (cons list more-lists)))
+    (declare (dynamic-extent arglists))
+    (values (map1 function arglists :list nil))))
+
+(defun mapcon (function list &rest more-lists)
+  "Apply FUNCTION to successive CDRs of lists. Return NCONC of results."
+  (declare (dynamic-extent more-lists))
+  (let ((arglists (cons list more-lists)))
+    (declare (dynamic-extent arglists))
+    (values (map1 function arglists :nconc nil))))
+
+;;; Functions for compatibility sake:
+
+(defun delq (item a-list &optional (n 0 np))  
+  "Returns list with all (up to n) elements with all elements EQ to ITEM
+   deleted"
+   ;(%print "a-list = " a-list) 
+  (declare (type list a-list) (type integer n))
+  ;(%print "a-list = " a-list) 
+  (do ((x a-list (cdr x))
+       (splice '()))
+      ((or (endp x)
+           (and np (zerop n))) 
+       a-list)
+    ; (%print "a-list = " a-list)
+    (cond ((eq item (car x))
+           (setq n (- n 1))
+           (if (null splice) 
+             (setq a-list (cdr x))
+             (rplacd splice (cdr x))))
+          (T (setq splice x)))))	; move splice along to include element
+
+(defun list-length-and-final-cdr (list)
+  "First value reutrned is length of regular list.
+    [for (a b . c), returns 2]
+    [for circular lists, returns NIL]
+   Second value is the final cdr.
+    [ for (a b), returns NIL
+      for (a b . c), returns c
+      for circular lists, returns NIL]
+   Third value only returned if we have a circular list. It is
+   the MAX possible length of the list until the repeat."
+   (do* ((n 0 (+ n 2))
+         (fast list (cddr fast))
+         (slow list (cdr slow)))
+        ()
+     (declare (fixnum n))
+     (cond ((null fast)
+            (return (values n nil)))
+           ((not (consp fast))
+            (return (values n fast)))
+           ((null (cdr fast))
+            (return (values (1+ n) nil)))
+           ((and (eq fast slow) (> n 0)) ;circular list
+            (return (values nil nil n)))          
+           ((not (consp (cdr fast)))
+            (return (values (1+ n) (cdr fast)))))))
+
+(provide 'lists)
Index: /branches/new-random/lib/macros.lisp
===================================================================
--- /branches/new-random/lib/macros.lisp	(revision 13309)
+++ /branches/new-random/lib/macros.lisp	(revision 13309)
@@ -0,0 +1,3819 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Macros (and functions/constants used at macroexpand-time) ONLY.
+
+(in-package "CCL")
+
+(eval-when (eval compile)
+  (require "LEVEL-2")
+  (require "BACKQUOTE")
+  (require "DEFSTRUCT-MACROS"))
+
+;; Constants
+
+(defmacro defconstant (sym val &optional (doc () doc-p) &environment env)
+  "Define a global constant, saying that the value is constant and may be
+  compiled into code. If the variable already has a value, and this is not
+  EQL to the new value, the code is not portable (undefined behavior). The
+  third argument is an optional documentation string for the variable."
+  (setq sym (require-type sym 'symbol)
+        doc (if doc-p (require-type doc 'string)))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (define-compile-time-constant ',sym ',val ,env))
+     (eval-when (:load-toplevel :execute)
+       (%defconstant ',sym ,val ,@(if doc-p (list doc))))))
+
+;; Lists
+
+(defmacro %car (x)
+  `(car (the list ,x)))
+
+(defmacro set-%car (x y)
+  `(setf (car (the cons ,x)) ,y))
+
+(defmacro %cdr (x)
+  `(cdr (the list ,x)))
+
+(defmacro set-%cdr (x y)
+  `(setf (cdr (the cons ,x)) ,y))
+
+(defmacro %caar (x)
+ `(%car (%car ,x)))
+
+(defmacro %cadr (x)
+ `(%car (%cdr ,x)))
+
+(defmacro %cdar (x)
+ `(%cdr (%car ,x)))
+
+(defmacro %cddr (x)
+ `(%cdr (%cdr ,x)))
+
+(defmacro %caaar (x)
+ `(%car (%car (%car ,x))))
+
+(defmacro %caadr (x)
+ `(%car (%car (%cdr ,x))))
+
+(defmacro %cadar (x)
+ `(%car (%cdr (%car ,x))))
+
+(defmacro %caddr (x)
+ `(%car (%cdr (%cdr ,x))))
+
+(defmacro %cdaar (x)
+ `(%cdr (%car (%car ,x))))
+
+(defmacro %cdadr (x)
+ `(%cdr (%car (%cdr ,x))))
+
+(defmacro %cddar (x)
+ `(%cdr (%cdr (%car ,x))))
+
+(defmacro %cdddr (x)
+ `(%cdr (%cdr (%cdr ,x))))
+
+(defmacro %rplaca (x y)
+  `(rplaca (the cons ,x) ,y))
+
+(defmacro %rplacd (x y)
+  `(rplacd (the cons ,x) ,y))
+
+; These are open-coded by the compiler to isolate platform
+; dependencies.
+
+(defmacro %unbound-marker-8 ()
+  `(%unbound-marker))
+
+(defmacro %slot-missing-marker ()
+  `(%illegal-marker))
+
+
+
+
+(defmacro %null-ptr () '(%int-to-ptr 0))
+
+;;;Assorted useful macro definitions
+
+(defmacro def-accessors (ref &rest names)
+  (define-accessors ref names))
+
+(defmacro def-accessor-macros (ref &rest names)
+  (define-accessors ref names t))
+
+(defun define-accessors (ref names &optional no-constants
+                             &aux (arg (gensym)) (index 0) progn types)
+  (when (listp ref)
+    (setq types ref
+          ref (pop names)))
+  (dolist (name names)
+    (when name
+      (unless (listp name) (setq name (list name)))
+      (dolist (sym name)
+        (when sym
+          (push `(defmacro ,sym (,arg) (list ',ref ,arg ,index)) progn)
+          (unless no-constants
+	    (push `(defconstant ,sym ,index) progn)))))
+    (setq index (1+ index)))
+ `(progn
+    ,.(nreverse progn)
+    ,@(if types `((add-accessor-types ',types ',names)))
+    ,index))
+
+(defmacro specialv (var)
+  `(locally (declare (special ,var)) ,var))
+
+
+(defmacro prog1 (valform &rest otherforms)
+ (let ((val (gensym)))
+ `(let ((,val ,valform))
+   ,@otherforms
+   ,val)))
+
+(defmacro prog2 (first second &rest others)
+ `(progn ,first (prog1 ,second ,@others)))
+
+(defmacro prog (inits &body body &environment env)
+  (multiple-value-bind (forms decls) (parse-body body env nil)
+    `(block nil
+       (let ,inits
+         ,@decls
+         (tagbody ,@forms)))))
+
+(defmacro prog* (inits &body body &environment env)
+  (multiple-value-bind (forms decls) (parse-body body env nil)
+    `(block nil
+       (let* ,inits
+         ,@decls
+         (tagbody ,@forms)))))
+
+
+(defmacro %stack-block ((&rest specs) &body forms &aux vars lets)
+  (dolist (spec specs)
+    (destructuring-bind (var ptr &key clear) spec
+      (push var vars)
+      (push `(,var (%new-ptr ,ptr ,clear)) lets)))
+  `(let* ,(nreverse lets)
+     (declare (dynamic-extent ,@vars))
+     (declare (type macptr ,@vars))
+     (declare (unsettable ,@vars))
+     ,@forms))
+
+(defmacro %vstack-block (spec &body forms)
+  `(%stack-block (,spec) ,@forms))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defun extract-bound-decls-for-dolist-var (var decls env)
+  (if (null decls)
+    (values nil nil)
+      (collect ((var-decls)
+                (other-decls))
+        (dolist (declform decls
+                 (let* ((vdecls (var-decls))
+                        (others (other-decls)))
+                   (values (if vdecls `((declare ,@vdecls)))
+                           (if others `((declare ,@others))))))
+          ;; (assert (eq (car declform) 'declare))
+          (dolist (decl (cdr declform))
+            (if (atom decl)
+              (other-decls decl)
+              (let* ((spec (car decl)))
+                (if (specifier-type-if-known spec env)
+                  (setq spec 'type
+                        decl `(type ,@decl)))
+                (case spec
+                  (type
+                   (destructuring-bind (typespec &rest vars) (cdr decl)
+                     (cond ((member var vars :test #'eq)
+                            (setq vars (delete var vars))
+                            (var-decls `(type ,typespec ,var))
+                            (when vars
+                              (other-decls `(type ,typespec ,@vars))))
+                           (t (other-decls decl)))))
+                   ((special ingore ignorable ccl::ignore-if-unused)
+                    (let* ((vars (cdr decl)))
+                      (cond ((member var vars :test #'eq)
+                             (setq vars (delete var vars))
+                             (var-decls `(,spec ,var))
+                             (when vars
+                               (other-decls `(,spec ,@vars))))
+                            (t (other-decls decl)))))
+                   (t (other-decls decl))))))))))
+)
+
+
+
+(defmacro dolist ((varsym list &optional ret) &body body &environment env)
+  (if (not (symbolp varsym)) (signal-program-error $XNotSym varsym))
+    (multiple-value-bind (forms decls) (parse-body body env nil)
+      (multiple-value-bind (var-decls other-decls)
+          (extract-bound-decls-for-dolist-var varsym decls env)
+        (let* ((lstsym (gensym)))
+        `(do* ((,lstsym ,list (cdr (the list ,lstsym))))
+              ((null ,lstsym)
+               ,@(if ret `((let* ((,varsym ()))
+                             (declare (ignorable ,varsym))
+                             ,ret))))
+          ,@other-decls
+          (let* ((,varsym (car ,lstsym)))
+            ,@var-decls
+            (tagbody ,@forms)))))))
+
+(defmacro dovector ((varsym vector &optional ret) &body body &environment env)
+  (if (not (symbolp varsym))(signal-program-error $XNotSym varsym))
+  (let* ((toplab (gensym))
+         (tstlab (gensym))
+         (lengthsym (gensym))
+         (indexsym (gensym))
+         (vecsym (gensym)))
+    (multiple-value-bind (forms decls) (parse-body body env nil)
+     `(let* ((,vecsym ,vector)
+             (,lengthsym (length ,vecsym))
+             (,indexsym 0)
+             ,varsym)
+        ,@decls
+        ,@(let ((type (nx-form-type vector env)))
+            (unless (eq type t)
+              `((declare (type ,type ,vecsym)))))
+        (block nil
+          (tagbody
+            (go ,tstlab)
+            ,toplab
+            (setq ,varsym (locally (declare (optimize (speed 3) (safety 0)))
+                            (aref ,vecsym ,indexsym))
+                  ,indexsym (%i+ ,indexsym 1))
+            ,@forms
+            ,tstlab
+            (if (%i< ,indexsym ,lengthsym) (go ,toplab)))
+          ,@(if ret `((progn (setq ,varsym nil) ,ret))))))))
+
+(defmacro report-bad-arg (&rest args)
+  `(values (%badarg ,@args)))
+
+(defmacro %cons-restart (name action report interactive test)
+ `(%istruct 'restart ,name ,action ,report ,interactive ,test))
+
+(defmacro restart-bind (clauses &body body)
+  "Executes forms in a dynamic context where the given restart bindings are
+   in effect. Users probably want to use RESTART-CASE. When clauses contain
+   the same restart name, FIND-RESTART will find the first such clause."
+  (let* ((restarts (mapcar #'(lambda (clause) 
+                               (list (make-symbol (symbol-name (require-type (car clause) 'symbol)))
+                                     `(%cons-restart nil nil nil nil nil)))
+                           clauses))
+         (bindings (mapcar #'(lambda (clause name)
+                              `(make-restart ,(car name) ',(car clause)
+                                             ,@(cdr clause)))
+                           clauses restarts))
+        (cluster (gensym)))
+    `(let* (,@restarts)
+       (declare (dynamic-extent ,@(mapcar #'car restarts)))
+       (let* ((,cluster (list ,@bindings))
+              (%restarts% (cons ,cluster %restarts%)))
+         (declare (dynamic-extent ,cluster %restarts%))
+         (progn
+           ,@body)))))
+
+(defmacro handler-bind (clauses &body body)
+  "(HANDLER-BIND ( {(type handler)}* )  body)
+   Executes body in a dynamic context where the given handler bindings are
+   in effect. Each handler must take the condition being signalled as an
+   argument. The bindings are searched first to last in the event of a
+   signalled condition."
+  (let* ((fns)
+         (decls)         
+         (bindings (mapcan #'(lambda (clause)
+                               (destructuring-bind (condition handler) clause
+                                 (if (and (consp handler)(eq (car handler) 'function)
+                                          (consp (cadr handler))(eq (car (cadr handler)) 'lambda))
+                                   (let ((fn (gensym)))
+                                     (push `(,fn ,handler) fns)
+                                     (push `(declare (dynamic-extent ,fn)) decls)
+                                     `(',condition ,fn))
+                                   (list `',condition
+                                         `,handler))))
+                           clauses))
+        (cluster (gensym)))    
+    (if (null bindings)
+      `(progn ,@body)
+      `(let* (,@fns
+              (,cluster (list ,@bindings))
+              (%handlers% (cons ,cluster %handlers%)))
+         (declare (dynamic-extent ,cluster %handlers%))
+         ,@decls
+         ,@body))))
+
+(defmacro restart-case (&environment env form &rest clauses)
+  "(RESTART-CASE form
+   {(case-name arg-list {keyword value}* body)}*)
+   The form is evaluated in a dynamic context where the clauses have special
+   meanings as points to which control may be transferred (see INVOKE-RESTART).
+   When clauses contain the same case-name, FIND-RESTART will find the first
+   such clause. If Expression is a call to SIGNAL, ERROR, CERROR or WARN (or
+   macroexpands into such) then the signalled condition will be associated with
+   the new restarts."
+  (let ((cluster nil))
+    (when clauses (setq cluster (gensym) form (restart-case-form form env cluster)))
+    (flet ((restart-case-1 (name arglist &rest forms)
+             (let (interactive report test)
+               (loop
+                 (case (car forms)
+                   (:interactive (setq interactive (cadr forms)))
+                   (:report (setq report (cadr forms)))
+                   (:test (setq test (cadr forms)))
+                   (t (return nil)))
+                 (setq forms (cddr forms)))
+               (when (and report (not (stringp report)))
+                 (setq report `#',report))
+               (when interactive
+                 (setq interactive `#',interactive))
+               (when test
+                 (setq test `#',test))
+               (values (require-type name 'symbol) arglist report interactive test forms))))
+      (cond ((null clauses) form)
+            ((and (null (cdr clauses)) (null (cadr (car clauses))))
+             (let ((block (gensym)) 
+                   (restart-name (gensym)))
+               (multiple-value-bind (name arglist report interactive test body)
+                                    (apply #'restart-case-1 (car clauses))
+                 (declare (ignore arglist))
+                 `(block ,block
+                    (let* ((,restart-name (%cons-restart ',name () ,report ,interactive ,test))
+                           (,cluster (list ,restart-name)))
+                      (declare (dynamic-extent ,restart-name ,cluster))
+                      (catch ,cluster
+                        (let ((%restarts% (cons ,cluster %restarts%)))
+                          (declare (dynamic-extent %restarts%))
+                          (return-from ,block ,form))))
+                    ,@body))))
+            (t
+             (let ((block (gensym)) (val (gensym))
+                   (index -1) restarts restart-names restart-name cases)
+               (while clauses
+                 (setq index (1+ index))
+                 (multiple-value-bind (name arglist report interactive test body)
+                                      (apply #'restart-case-1 (pop clauses))
+                   (push (setq restart-name (make-symbol (symbol-name name))) restart-names)
+                   (push (list restart-name `(%cons-restart ',name ,index ,report ,interactive ,test))
+                         restarts)
+                   (when (null clauses) (setq index t))
+                   (push `(,index (apply #'(lambda ,arglist ,@body) ,val))
+                         cases)))
+               `(block ,block
+                  (let ((,val (let* (,@restarts
+                                     (,cluster (list ,@(reverse restart-names))))
+                                (declare (dynamic-extent ,@restart-names ,cluster))
+                                (catch ,cluster
+                                  (let ((%restarts% (cons ,cluster %restarts%)))
+                                    (declare (dynamic-extent %restarts%))
+                                    (return-from ,block ,form))))))
+                    (case (pop ,val)
+                      ,@(nreverse cases))))))))))
+
+
+; Anything this hairy should die a slow and painful death.
+; Unless, of course, I grossly misunderstand...
+(defun restart-case-form (form env clustername)
+  (let ((expansion (macroexpand form env))
+        (head nil))
+    (if (and (listp expansion)          ; already an ugly hack, made uglier by %error case ...
+             (memq (setq head (pop expansion)) '(signal error cerror warn %error)))
+      (let ((condform nil)
+            (signalform nil)
+            (cname (gensym)))
+        (case head
+          (cerror
+           (destructuring-bind 
+             (continue cond &rest args) expansion
+             (setq condform `(condition-arg ,cond (list ,@args) 'simple-error)
+                   signalform `(cerror ,continue ,cname))))
+          ((signal error warn)
+           (destructuring-bind
+             (cond &rest args) expansion
+             (setq condform `(condition-arg ,cond (list ,@args) ,(if (eq head 'warning)
+                                                                   ''simple-warning
+                                                                   (if (eq head 'error)
+                                                                     ''simple-error
+                                                                     ''simple-condition)))
+                   signalform `(,head ,cname))))
+          (t ;%error
+           (destructuring-bind (cond args fp) expansion
+             (setq condform `(condition-arg ,cond ,args 'simple-error)
+                   signalform `(%error ,cname nil ,fp)))))
+        `(let ((,cname ,condform))
+           (with-condition-restarts ,cname ,clustername
+             ,signalform)))
+      form)))
+      
+
+(defmacro handler-case (form &rest clauses)
+  "(HANDLER-CASE form
+   { (type ([var]) body) }* )
+   Execute FORM in a context with handlers established for the condition
+   types. A peculiar property allows type to be :NO-ERROR. If such a clause
+   occurs, and form returns normally, all its values are passed to this clause
+   as if by MULTIPLE-VALUE-CALL.  The :NO-ERROR clause accepts more than one
+   var specification."
+  (let* ((no-error-clause (assoc :no-error clauses)))
+    (if no-error-clause
+      (let* ((normal-return (gensym))
+             (error-return (gensym)))
+        `(block ,error-return
+          (multiple-value-call #'(lambda ,@(cdr no-error-clause))
+            (block ,normal-return
+              (return-from ,error-return
+                (handler-case (return-from ,normal-return ,form)
+                  ,@(remove no-error-clause clauses)))))))
+      (flet ((handler-case (type var &rest body)
+               (when (eq type :no-error)
+                 (signal-program-error "Duplicate :no-error clause. "))
+           (values type var body)))
+        (cond ((null clauses) form)
+          ((null (cdr clauses))
+           (let ((block   (gensym))
+                 (cluster (gensym)))
+             (multiple-value-bind (type var body)
+                                  (apply #'handler-case (car clauses))
+               (if var
+                 `(block ,block
+                    ((lambda ,var ,@body)
+                      (let* ((,cluster (list ',type)))
+                        (declare (dynamic-extent ,cluster))
+                        (catch ,cluster
+                          (let ((%handlers% (cons ,cluster %handlers%)))
+                            (declare (dynamic-extent %handlers%))
+                            (return-from ,block ,form))))))
+                 `(block ,block
+                    (let* ((,cluster (list ',type)))
+                      (declare (dynamic-extent ,cluster))
+                      (catch ,cluster
+                        (let ((%handlers% (cons ,cluster %handlers%)))
+                          (declare (dynamic-extent %handlers%))
+                          (return-from ,block ,form)))
+                      (locally ,@body)))))))
+          (t (let ((block (gensym)) (cluster (gensym)) (val (gensym))
+                   (index -1) handlers cases)
+               (while clauses
+                 (setq index (1+ index))
+                 (multiple-value-bind (type var body)
+                                      (apply #'handler-case (pop clauses))                   
+                   (push `',type handlers)
+                   (push index handlers)
+                   (when (null clauses) (setq index t))
+                   (push (if var
+                           `(,index ((lambda ,var ,@body) ,val))
+                           `(,index (locally ,@body))) cases)))
+               `(block ,block
+                  (let ((,val (let* ((,cluster (list ,@(nreverse handlers))))
+                                (declare (dynamic-extent ,cluster))
+                                (catch ,cluster
+                                  (let ((%handlers% (cons ,cluster %handlers%)))
+                                    (declare (dynamic-extent %handlers%))
+                                    (return-from ,block ,form))))))
+                    (case (pop ,val)
+                      ,@(nreverse cases)))))))))))
+
+(defmacro with-simple-restart ((restart-name format-string &rest format-args)
+                               &body body
+                               &aux (cluster (gensym)) (temp (make-symbol (symbol-name restart-name))))
+  "(WITH-SIMPLE-RESTART (restart-name format-string format-arguments)
+   body)
+   If restart-name is not invoked, then all values returned by forms are
+   returned. If control is transferred to this restart, it immediately
+   returns the values NIL and T."
+  (unless (and (stringp format-string)
+               (null format-args)
+               (not (%str-member #\~ (ensure-simple-string format-string))))
+    (let ((stream (gensym)))
+      (setq format-string `#'(lambda (,stream) (format ,stream ,format-string ,@format-args)))))
+  `(let* ((,temp (%cons-restart ',restart-name
+                                'simple-restart
+                                ,format-string
+                                nil
+                                nil))
+          (,cluster (list ,temp)))
+     (declare (dynamic-extent ,temp ,cluster))
+     (catch ,cluster
+       (let ((%restarts% (cons ,cluster %restarts%)))
+         (declare (dynamic-extent %restarts%))
+         ,@body))))
+
+;Like with-simple-restart but takes a pre-consed restart.  Not CL.
+(defmacro with-restart (restart &body body &aux (cluster (gensym)))
+  `(let* ((,cluster (list ,restart)))
+     (declare (dynamic-extent ,cluster))
+     (catch ,cluster
+       (let ((%restarts% (cons ,cluster %restarts%)))
+         (declare (dynamic-extent %restarts%))
+         ,@body))))
+
+(defmacro ignore-errors (&rest forms)
+  "Execute FORMS handling ERROR conditions, returning the result of the last
+  form, or (VALUES NIL the-ERROR-that-was-caught) if an ERROR was handled."
+  `(handler-case (progn ,@forms)
+     (error (condition) (values nil condition))))
+
+(defmacro def-kernel-restart (&environment env errno name arglist &body body)
+  (multiple-value-bind (body decls)
+                       (parse-body body env)
+    `(let* ((fn (nfunction ,name (lambda ,arglist ,@decls (block ,name ,@body))))
+            (pair (assq ,errno ccl::*kernel-restarts*)))
+       (if pair
+         (rplacd pair fn)
+         (push (cons ,errno fn) ccl::*kernel-restarts*))
+       fn)))
+
+
+;;; Setf.
+
+;  If you change anything here, be sure to make the corresponding change
+;  in get-setf-method.
+(defmacro setf (&rest args &environment env)
+  "Takes pairs of arguments like SETQ. The first is a place and the second
+  is the value that is supposed to go into that place. Returns the last
+  value. The place argument may be any of the access forms for which SETF
+  knows a corresponding setting form."
+  (let ((temp (length args))
+        (accessor nil))
+    (cond ((eq temp 2)
+           (let* ((form (car args)) 
+                  (value (cadr args)))
+             ;This must match get-setf-method .
+             (cond ((atom form)
+                    (progn
+                      (unless (symbolp form)(signal-program-error $XNotSym form))
+                      `(setq ,form ,value)))
+                   ((eq (car form) 'the)
+                    (unless (eql (length form) 3)
+                      (error "Bad THE place form in (SETF ~S ~S)" form value))
+                    (destructuring-bind (type place) (cdr form)
+                      `(setf ,place (the ,type ,value))))
+                   (t
+                    (multiple-value-bind (ftype local-p)
+                        (function-information (setq accessor (car form)) ENV)
+                      (if local-p
+                        (if (eq ftype :function)
+                                        ;Local function, so don't use global setf definitions.
+                          (default-setf form value env)
+                          `(setf ,(macroexpand-1 form env) ,value))
+                        (cond
+                          ((setq temp (%setf-method accessor))
+                           (if (symbolp temp)
+                             `(,temp ,@(cdar args) ,value)
+                             (multiple-value-bind (dummies vals storevars setter #|getter|#)
+                                 (funcall temp form env)
+                               (do* ((d dummies (cdr d))
+                                     (v vals (cdr v))
+                                     (let-list nil))
+                                    ((null d)
+                                     (setq let-list (nreverse let-list))
+                                     `(let* ,let-list
+                                       (declare (ignorable ,@dummies))
+                                       (multiple-value-bind ,storevars ,value
+                                         #|,getter|#
+                                         ,setter)))
+                                 (push (list (car d) (car v)) let-list)))))
+                          ((and (type-and-refinfo-p (setq temp (or (environment-structref-info accessor env)
+                                                                   (and #-bccl (boundp '%structure-refs%)
+                                                                        (gethash accessor %structure-refs%)))))
+                                (not (refinfo-r/o (if (consp temp) (%cdr temp) temp))))
+                           (if (consp temp)
+                             ;; strip off type, but add in a require-type
+                             (let ((type (%car temp)))
+                               `(the ,type (setf ,(defstruct-ref-transform (%cdr temp) (%cdar args) env)
+                                            (require-type ,value ',type))))
+                             `(setf ,(defstruct-ref-transform temp (%cdar args) env)
+                               ,value)))
+                          (t
+                           (multiple-value-bind (res win)
+                               (macroexpand-1 form env)
+                             (if win
+                               `(setf ,res ,value)
+                               (default-setf form value env)))))))))))
+          ((oddp temp)
+	   (signal-program-error "Odd number of args to SETF : ~s." args))
+          (t (do* ((a args (cddr a)) (l nil))
+                  ((null a) `(progn ,@(nreverse l)))
+               (push `(setf ,(car a) ,(cadr a)) l))))))
+
+
+(defun default-setf (setter value &optional env)
+  (let* ((reader (car setter))
+         (args (cdr setter))
+         (gensyms (mapcar #'(lambda (sym) (declare (ignore sym)) (gensym)) args))
+         types declares)
+    (flet ((form-type (form)
+             (nx-form-type form env)))
+      (declare (dynamic-extent #'form-type))
+      (setq types (mapcar #'form-type args)))
+    (dolist (sym gensyms)
+      (let ((sym-type (pop types)))
+        (unless (eq sym-type t)
+          (push `(type ,sym-type ,sym) declares))))
+    `(let ,(mapcar #'list gensyms args)
+       ,@(and declares (list `(declare ,@(nreverse declares))))
+       (funcall #'(setf ,reader) ,value ,@gensyms))))
+
+;; Establishing these setf-inverses is something that should
+;; happen at compile-time
+(defsetf elt set-elt)
+(defsetf car set-car)
+(defsetf %car set-%car)
+(defsetf first set-car)
+(defsetf cdr set-cdr)
+(defsetf %cdr set-%cdr)
+(defsetf rest set-cdr)
+(defsetf uvref uvset)
+(defsetf aref aset)
+(defsetf svref svset)
+(defsetf %svref %svset)
+(defsetf char set-char)
+(defsetf schar set-schar)
+(defsetf %scharcode %set-scharcode)
+(defsetf symbol-value set)
+(defsetf symbol-plist set-symbol-plist)
+(defsetf fill-pointer set-fill-pointer)
+
+; This sux; it calls the compiler twice (once to shove the macro in the
+; environment, once to dump it into the file.)
+(defmacro defmacro  (name arglist &body body &environment env)
+  (unless (symbolp name)(signal-program-error $XNotSym name))
+  (unless (listp arglist) (signal-program-error "~S is not a list." arglist))
+  (multiple-value-bind (lambda-form doc)
+                       (parse-macro-1 name arglist body env)
+    (let* ((normalized (normalize-lambda-list arglist t t))
+           (body-pos (position '&body normalized))
+           (argstring (let ((temp nil))
+                        (dolist (arg normalized)
+                          (if (eq arg '&aux)
+                            (return)
+                            (push arg temp)))
+                        (format nil "~:a" (nreverse temp)))))
+      (if (and body-pos (memq '&optional normalized)) (decf body-pos))
+      `(progn
+         (eval-when (:compile-toplevel)
+           (define-compile-time-macro ',name ',lambda-form ',env))
+         (eval-when (:load-toplevel :execute)
+           (%macro 
+            (nfunction ,name ,lambda-form)
+            '(,doc ,body-pos . ,argstring))
+           ',name)))))
+
+(defmacro define-symbol-macro (name expansion &environment env)
+  (unless (symbolp name)(signal-program-error $XNotSym name))
+  `(progn
+    (eval-when (:compile-toplevel)
+      (define-compile-time-symbol-macro ',name ',expansion ',env))
+    (eval-when (:load-toplevel :execute)
+      (%define-symbol-macro ',name ',expansion))))
+
+;; ---- allow inlining setf functions
+(defmacro defun (spec args &body body &environment env &aux global-name inline-spec)
+  "Define a function at top level."
+  (validate-function-name spec)
+  (setq args (require-type args 'list))
+  (setq body (require-type body 'list))
+  (multiple-value-bind (forms decls doc) (parse-body body env t)
+    (cond ((symbolp spec)
+           (setq global-name spec)
+           (setq inline-spec spec)
+           (setq body `(block ,spec ,@forms)))
+          ((setf-function-name-p spec)
+           (setq inline-spec spec)
+           (setq body `(block ,(cadr spec) ,@forms)))
+          (t (setq body `(progn ,@forms))))
+    (let* ((lambda-expression `(lambda ,args 
+                                ,@(if global-name
+                                    `((declare (global-function-name ,global-name))))
+                                ,@decls ,body))
+           (info (if (and inline-spec
+                          (or (null env)
+                              (definition-environment env t))
+                          (nx-declared-inline-p inline-spec env)
+                          (not (and (symbolp inline-spec)
+                                    (gethash inline-spec *NX1-ALPHATIZERS*))))
+                   (cons doc lambda-expression)
+                   doc)))
+      `(progn
+         (%defun (nfunction ,spec ,lambda-expression) ',info)
+         ',spec))))
+
+(defmacro %defvar-init (var initform doc)
+  `(unless (%defvar ',var ,doc)
+    (set ',var ,initform)))
+
+(defmacro defvar (&environment env var &optional (value () value-p) doc)
+  "Define a global variable at top level. Declare the variable
+  SPECIAL and, optionally, initialize it. If the variable already has a
+  value, the old value is not clobbered. The third argument is an optional
+  documentation string for the variable."
+  (if (and doc (not (stringp doc))) (report-bad-arg doc 'string))
+  (if (and (compile-file-environment-p env) (not *fasl-save-doc-strings*))
+    (setq doc nil))
+ `(progn
+    (eval-when (:compile-toplevel)
+      (note-variable-info ',var ,value-p ,env))
+    ,(if value-p
+       `(%defvar-init ,var ,value ,doc)
+       `(%defvar ',var))
+    ',var))
+         
+(defmacro def-standard-initial-binding (name &optional (form name) (doc nil doc-p) &environment env)
+  `(progn
+    (eval-when (:compile-toplevel)
+      (note-variable-info ',name t ,env))    
+    (define-standard-initial-binding ',name #'(lambda () ,form))
+    ,@(when doc-p
+           `((set-documentation ',name 'variable ,doc)))
+    ',name))
+
+(defmacro defparameter (&environment env var value &optional doc)
+  "Define a parameter that is not normally changed by the program,
+  but that may be changed without causing an error. Declare the
+  variable special and sets its value to VAL, overwriting any
+  previous value. The third argument is an optional documentation
+  string for the parameter."
+  (if (and doc (not (stringp doc))) (signal-program-error "~S is not a string." doc))
+  (if (and (compile-file-environment-p env) (not *fasl-save-doc-strings*))
+    (setq doc nil))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (note-variable-info ',var t ,env))
+     (%defparameter ',var ,value ,doc)))
+
+
+(defmacro defstatic (&environment env var value &optional doc)
+  "Syntax is like DEFPARAMETER.  Proclaims the symbol to be special,
+but also asserts that it will never be given a per-thread dynamic
+binding.  The value of the variable can be changed (via SETQ, etc.),
+but since all threads access the same static binding of the variable,
+such changes should be made with care."
+  (if (and doc (not (stringp doc))) (signal-program-error "~S is not a string." doc))
+  (if (and (compile-file-environment-p env) (not *fasl-save-doc-strings*))
+    (setq doc nil))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (note-variable-info ',var :global ,env))
+     (%defglobal ',var ,value ,doc)))
+
+(defmacro defstaticvar (&environment env var value &optional doc)
+  "Syntax is like DEFVAR.  Proclaims the symbol to be special,
+but also asserts that it will never be given a per-thread dynamic
+binding.  The value of the variable can be changed (via SETQ, etc.),
+but since all threads access the same static binding of the variable,
+such changes should be made with care.  Like DEFVAR, the initial value
+form is not evaluated if the variable is already BOUNDP."
+  (if (and doc (not (stringp doc))) (signal-program-error "~S is not a string." doc))
+  (if (and (compile-file-environment-p env) (not *fasl-save-doc-strings*))
+    (setq doc nil))
+  `(progn
+     (eval-when (:compile-toplevel)
+       (note-variable-info ',var :global ,env))
+      (%symbol-bits ',var (logior (ash 1 $sym_vbit_global) (the fixnum (%symbol-bits ',var))))
+     (%defvar-init ,var ,value ,doc)))
+
+
+(defmacro defglobal (&rest args)
+  "Synonym for DEFSTATIC."
+  `(defstatic ,@args))
+
+
+(defmacro defloadvar (var value &optional doc)
+  `(progn
+     (defstaticvar ,var ,nil ,@(if doc `(,doc)))
+     (def-ccl-pointers ,var ()
+       (setq ,var ,value))
+     ',var))
+
+
+
+
+(defmacro qlfun (name args &body body)
+  `(nfunction ,name (lambda ,args ,@body)))
+
+(defmacro lfun-bits-known-function (f)
+  (let* ((temp (gensym)))
+    `(let* ((,temp (function-to-function-vector ,f)))
+      (%svref ,temp (the fixnum (1- (the fixnum (uvsize ,temp))))))))
+
+(defmacro lfunloop (for var in function &body loop-body)
+  "Loop over immediates in function"
+  (assert (and (or (equal (symbol-name for) "FOR") (equal (symbol-name for) "AS"))
+               (equal (symbol-name in) "IN")))
+  (let ((fn (gensym))
+	(lfv (gensym))
+	(i (gensym)))
+    `(loop with ,fn = ,function
+           with ,lfv = (function-to-function-vector ,fn)
+           for ,i from #+ppc-target 1 #+x86-target (%function-code-words ,fn) below (%i- (uvsize  ,lfv) 1)
+           as ,var = (%svref ,lfv ,i)
+           ,@loop-body)))
+
+(defmacro cond (&rest args &aux clause)
+  (when args
+     (setq clause (car args))
+     (if (cdr clause)         
+         `(if ,(car clause) (progn ,@(cdr clause)) (cond ,@(cdr args)))
+       (if (cdr args) `(or ,(car clause) (cond ,@(cdr args)))
+                      `(values ,(car clause))))))
+
+(defmacro and (&rest args)
+  "And Form*
+AND evaluates each form in sequence, from left to right.  If any form
+returns NIL, AND returns NIL; otherwise, AND returns the values(s) returned
+by the last form.  If there are no forms, AND returns T."
+  (if (null args) t
+    (if (null (cdr args)) (car args)
+      `(if ,(car args) (and ,@(cdr args))))))
+
+(defmacro or (&rest args)
+  "Or Form*
+OR evaluates each Form, in sequence, from left to right.
+If any Form but the last returns a non-NIL value, OR returns that
+single value (without evaluating any subsequent Forms.)  If OR evaluates
+the last Form, it returns all values returned by that Form.  If there
+are no Forms, OR returns NIL."
+  (if args
+    (if (cdr args)
+      (do* ((temp (gensym))
+            (handle (list nil))
+            (forms `(let ((,temp ,(pop args)))
+                     (if ,temp ,temp ,@handle))))
+           ((null (cdr args))
+            (%rplaca handle (%car args))
+            forms)
+        (%rplaca handle `(if (setq ,temp ,(%car args)) 
+                          ,temp 
+                          ,@(setq handle (list nil))))
+        (setq args (%cdr args)))
+      (%car args))))
+
+(defmacro case (key &body forms)
+  "CASE Keyform {({(Key*) | Key} Form*)}*
+  Evaluates the Forms in the first clause with a Key EQL to the value of
+  Keyform. If a singleton key is T then the clause is a default clause."
+   (let ((key-var (gensym)))
+     `(let ((,key-var ,key))
+        (declare (ignorable ,key-var))
+        (cond ,@(case-aux forms key-var nil nil)))))
+
+(defmacro ccase (keyplace &body forms)
+  "CCASE Keyform {({(Key*) | Key} Form*)}*
+  Evaluates the Forms in the first clause with a Key EQL to the value of
+  Keyform. If none of the keys matches then a correctable error is
+  signalled."
+  (let* ((key-var (gensym))
+         (tag (gensym)))
+    `(prog (,key-var)
+       ,tag
+       (setq ,key-var ,keyplace)
+       (return (cond ,@(case-aux forms key-var tag keyplace))))))
+
+(defmacro ecase (key &body forms)
+  "ECASE Keyform {({(Key*) | Key} Form*)}*
+  Evaluates the Forms in the first clause with a Key EQL to the value of
+  Keyform. If none of the keys matches then an error is signalled."
+  (let* ((key-var (gensym)))
+    `(let ((,key-var ,key))
+       (declare (ignorable ,key-var))
+       (cond ,@(case-aux forms key-var 'ecase nil)))))
+       
+(defun case-aux (clauses key-var e-c-p placename &optional (used-keys (list (list '%case-core))))
+  (if clauses
+    (let* ((key-list (caar clauses))
+           (stype (if e-c-p (if (eq e-c-p 'ecase) e-c-p 'ccase) 'case))
+           (test (cond ((and (not e-c-p)
+                             (or (eq key-list 't)
+                                 (eq key-list 'otherwise)))
+                        t)
+                       (key-list
+                        (cons 'or
+                              (case-key-testers key-var used-keys key-list stype)))))
+           (consequent-list (or (%cdar clauses) '(nil))))
+      (if (eq test t)
+        (progn
+          (when (%cdr clauses) (warn "~s or ~s clause in the middle of a ~s statement.  Subsequent clauses ignored."
+                                     't 'otherwise 'case))
+          (cons (cons t consequent-list) nil))
+        (cons (cons test consequent-list)
+              (case-aux (%cdr clauses) key-var e-c-p placename used-keys))))
+    (when e-c-p
+      (setq used-keys `(member ,@(mapcar #'car (cdr used-keys))))
+      (if (eq e-c-p 'ecase)
+        `((t (values (%err-disp #.$XWRONGTYPE ,key-var ',used-keys))))
+        `((t (setf ,placename (ensure-value-of-type ,key-var ',used-keys ',placename))
+           (go ,e-c-p)))))))
+
+
+;;; We don't want to descend list structure more than once (like this has
+;;; been doing for the last 18 years or so.)
+(defun case-key-testers (symbol used-keys atom-or-list statement-type &optional recursive)
+  (if (or recursive (atom atom-or-list))
+    (progn
+      (if (assoc atom-or-list used-keys)
+        (warn "Duplicate keyform ~s in ~s statement." atom-or-list statement-type)
+        (setq used-keys (nconc used-keys (list (cons atom-or-list t)))))
+      `((,(if (typep atom-or-list '(and number (not fixnum)))
+              'eql
+              'eq)
+         ,symbol ',atom-or-list)))
+    (nconc (case-key-testers symbol used-keys (car atom-or-list) statement-type t)
+           (when (cdr atom-or-list)
+             (case-key-testers symbol used-keys (%cdr atom-or-list) statement-type nil)))))
+
+
+; generate the COND body of a {C,E}TYPECASE form
+(defun typecase-aux (key-var clauses &optional e-c-p keyform)
+  (let* ((construct (if e-c-p (if (eq e-c-p 'etypecase) e-c-p 'ctypecase) 'typecase))
+         (types ())
+         (body ())
+         otherwise-seen-p)
+    (flet ((bad-clause (c) 
+             (signal-program-error "Invalid clause ~S in ~S form." c construct)))
+      (dolist (clause clauses)
+        (if (atom clause)
+            (bad-clause clause))
+        (if otherwise-seen-p
+            (signal-program-error "OTHERWISE must be final clause in ~S form." construct))
+        (destructuring-bind (typespec &body consequents) clause
+          (when (eq construct 'typecase)
+            (if (eq typespec 'otherwise)
+                (progn (setq typespec t)
+                       (setq otherwise-seen-p t))))
+          (unless
+              (dolist (already types nil)
+                (when (subtypep typespec already)
+                  (warn "Clause ~S ignored in ~S form - shadowed by ~S ." clause construct (assq already clauses))
+                  (return t)))
+            (push typespec types)
+            (setq typespec `(typep ,key-var ',typespec))
+            (push `(,typespec nil ,@consequents) body))))
+      (when e-c-p
+        (setq types `(or ,@(nreverse types)))
+        (if (eq construct 'etypecase)
+            (push `(t (values (%err-disp #.$XWRONGTYPE ,key-var ',types))) body)
+            (push `(t (setf ,keyform (ensure-value-of-type  ,key-var ',types ',keyform))
+                      (go ,e-c-p)) body))))
+    `(cond ,@(nreverse body))))
+
+(defmacro typecase (keyform &body clauses)
+  "TYPECASE Keyform {(Type Form*)}*
+  Evaluates the Forms in the first clause for which TYPEP of Keyform and Type
+  is true."
+  (let ((key-var (gensym)))
+    `(let ((,key-var ,keyform))
+       (declare (ignorable ,key-var))
+       ,(typecase-aux key-var clauses))))
+
+(defmacro etypecase (keyform &body clauses)
+  "ETYPECASE Keyform {(Type Form*)}*
+  Evaluates the Forms in the first clause for which TYPEP of Keyform and Type
+  is true. If no form is satisfied then an error is signalled."
+  (let ((key-var (gensym)))
+    `(let ((,key-var ,keyform))
+       (declare (ignorable ,key-var))
+       ,(typecase-aux key-var clauses 'etypecase))))
+
+(defmacro ctypecase (keyplace &body clauses)
+  "CTYPECASE Key {(Type Form*)}*
+  Evaluates the Forms in the first clause for which TYPEP of Keyform and Type
+  is true. If no form is satisfied then a correctable error is signalled."
+  (let ((key-var (gensym))
+        (tag (gensym)))
+    `(prog (,key-var)
+       ,tag
+       (setq ,key-var ,keyplace)
+       (return ,(typecase-aux key-var clauses tag keyplace)))))
+
+(defmacro destructuring-bind (lambda-list expression &body body)
+  "Bind the variables in LAMBDA-LIST to the contents of ARG-LIST."
+  (multiple-value-bind (bindings decls)
+      (%destructure-lambda-list  lambda-list expression nil nil)
+    `(let* ,(nreverse bindings)
+      ,@(when decls `((declare ,@decls)))
+      ,@body)))
+
+(defmacro make-destructure-state (tail whole lambda)
+  `(%istruct 'destructure-state ,tail ,whole ,lambda))
+
+
+; This is supposedly ANSI CL.
+(defmacro lambda (&whole lambda-expression (&rest paramlist) &body body)
+  (declare (ignore paramlist body))
+  (unless (lambda-expression-p lambda-expression)
+    (warn "Invalid lambda expression: ~s" lambda-expression))
+  `(function ,lambda-expression))
+
+; This isn't
+(defmacro nlambda (name (&rest arglist) &body body)
+  `(nfunction ,name (lambda ,arglist ,@body)))
+
+(defmacro when (test &body body)
+  "If the first argument is true, the rest of the forms are
+  evaluated as a PROGN."
+ `(if ,test
+   (progn ,@body)))
+
+(defmacro unless (test &body body)
+  "If the first argument is not true, the rest of the forms are
+  evaluated as a PROGN."
+ `(if (not ,test)
+   (progn ,@body)))
+
+(defmacro return (&optional (form nil form-p))
+  `(return-from nil ,@(if form-p `(,form))))
+
+; since they use tagbody, while & until BOTH return NIL
+(defmacro while (test &body body)
+  (let ((testlab (gensym))
+        (toplab (gensym)))
+    `(tagbody
+       (go ,testlab)
+      ,toplab
+      (progn ,@body)
+      ,testlab
+      (when ,test (go ,toplab)))))
+
+(defmacro until (test &body body)
+  (let ((testlab (gensym))
+        (toplab (gensym)))
+    `(tagbody
+       (go ,testlab)
+      ,toplab
+      (progn ,@body)
+      ,testlab
+      (if (not ,test)
+        (go ,toplab)))))
+
+(defmacro psetq (&whole call &body pairs &environment env)
+  "PSETQ {var value}*
+   Set the variables to the values, like SETQ, except that assignments
+   happen in parallel, i.e. no assignments take place until all the
+   forms have been evaluated."
+  (when pairs
+   (if (evenp (length pairs))
+     (do* ((l pairs (%cddr l))
+           (sym (%car l) (%car l)))
+          ((null l) (%pset pairs))
+       (unless (symbolp sym) (report-bad-arg sym 'symbol))
+       (when (nth-value 1 (macroexpand-1 sym env))
+         (return `(psetf ,@pairs))))
+     (signal-program-error "Uneven number of args in the call ~S" call))))
+
+; generates body for psetq.
+; "pairs" is a proper list whose length is not odd.
+(defun %pset (pairs)
+ (when pairs
+   (let (vars vals gensyms let-list var val sets)
+      (loop
+        (setq var (pop pairs)
+              val (pop pairs))
+        (if (null pairs) (return))
+        (push var vars)
+        (push val vals)
+        (push (gensym) gensyms))
+      (dolist (g gensyms)
+        (push g sets)
+        (push (pop vars) sets)
+        (push (list g (pop vals)) let-list))
+      (push val sets)
+      (push var sets)
+      `(progn
+         (let ,let-list
+           (setq ,@sets))
+         nil))))
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defun do-loop (binder setter env var-init-steps end-test result body)
+  (let ((toptag (gensym))
+        (testtag (gensym)))
+    (multiple-value-bind (forms decls) (parse-body body env nil)
+      `(block nil
+         (,binder ,(do-let-vars var-init-steps)
+                  ,@decls
+                  (tagbody ; crocks-r-us.
+                    (go ,testtag)
+                    ,toptag
+                    (tagbody
+                      ,@forms)
+                    (,setter ,@(do-step-vars var-init-steps))
+                    ,testtag
+                    (unless ,end-test
+                      (go ,toptag)))
+                  ,@result)))))
+)
+
+(defmacro do (&environment env var-init-steps (&optional end-test &rest result) &body body)
+  "DO ({(Var [Init] [Step])}*) (Test Exit-Form*) Declaration* Form*
+  Iteration construct. Each Var is initialized in parallel to the value of the
+  specified Init form. On subsequent iterations, the Vars are assigned the
+  value of the Step form (if any) in parallel. The Test is evaluated before
+  each evaluation of the body Forms. When the Test is true, the Exit-Forms
+  are evaluated as a PROGN, with the result being the value of the DO. A block
+  named NIL is established around the entire expansion, allowing RETURN to be
+  used as an alternate exit mechanism."
+  (do-loop 'let 'psetq env var-init-steps end-test result body))
+
+(defmacro do* (&environment env var-init-steps (&optional end-test &rest result) &body body)
+  "DO* ({(Var [Init] [Step])}*) (Test Exit-Form*) Declaration* Form*
+  Iteration construct. Each Var is initialized sequentially (like LET*) to the
+  value of the specified Init form. On subsequent iterations, the Vars are
+  sequentially assigned the value of the Step form (if any). The Test is
+  evaluated before each evaluation of the body Forms. When the Test is true,
+  the Exit-Forms are evaluated as a PROGN, with the result being the value
+  of the DO. A block named NIL is established around the entire expansion,
+  allowing RETURN to be used as an laternate exit mechanism."
+  (do-loop 'let* 'setq env var-init-steps end-test result body))
+
+
+(defun do-let-vars (var-init-steps)
+  (if var-init-steps
+      (cons (list (do-let-vars-var (car var-init-steps))
+                  (do-let-vars-init (car var-init-steps)))
+             (do-let-vars (cdr var-init-steps)))))
+
+(defun do-let-vars-var (var-init-step)
+  (if (consp var-init-step)
+       (car var-init-step)
+       var-init-step))
+
+(defun do-let-vars-init (var-init-step)
+   (if (consp var-init-step)
+        (cadr var-init-step)
+        nil))
+
+(defun do-step-vars (var-init-steps)
+    (if var-init-steps
+        (if (do-step-vars-step? (car var-init-steps))
+             (append (list (do-let-vars-var (car var-init-steps))
+                           (do-step-vars-step (car var-init-steps)))
+                     (do-step-vars (cdr var-init-steps)))
+             (do-step-vars (cdr var-init-steps)))))
+
+(defun do-step-vars-step? (var-init-step)
+  (if (consp var-init-step)
+       (cddr var-init-step)))
+
+(defun do-step-vars-step (var-init-step)
+  (if (consp var-init-step)
+       (caddr var-init-step)))
+
+
+(defmacro dotimes ((i n &optional result) &body body &environment env)
+  (multiple-value-bind (forms decls)
+                       (parse-body body env)
+    (if (not (symbolp i))(signal-program-error $Xnotsym i))
+    (let* ((toptag (gensym))
+           (limit (gensym)))
+      `(block nil
+        (let ((,limit ,n) (,i 0))
+         ,@decls
+         (declare (unsettable ,i))
+           (if (int>0-p ,limit)
+             (tagbody
+               ,toptag
+               ,@forms
+               (locally
+                (declare (settable ,i))
+                (setq ,i (1+ ,i)))
+               (unless (eql ,i ,limit) (go ,toptag))))
+           ,result)))))
+  
+(defun do-syms-result (var resultform)
+  (unless (eq var resultform)
+    (if (and (consp resultform) (not (quoted-form-p resultform)))
+      `(progn (setq ,var nil) ,resultform)
+      resultform)))
+
+(defun expand-package-iteration-macro (iteration-function var pkg-spec resultform body env)
+  (multiple-value-bind (body decls) (parse-body body env nil)
+    (let* ((ftemp (gensym))
+           (vtemp (gensym))
+           (ptemp (gensym))
+           (result (do-syms-result var resultform)))
+      `(block nil
+        (let* ((,var nil)
+               (,ptemp ,pkg-spec))
+          ,@decls
+           (flet ((,ftemp (,vtemp) (declare (debugging-function-name nil)) (setq ,var ,vtemp) (tagbody ,@body)))
+             (declare (dynamic-extent #',ftemp))
+             (,iteration-function ,ptemp #',ftemp))
+           ,@(when result `(,result)))))))
+
+(defmacro do-symbols ((var &optional pkg result) &body body &environment env)
+  "DO-SYMBOLS (VAR [PACKAGE [RESULT-FORM]]) {DECLARATION}* {TAG | FORM}*
+   Executes the FORMs at least once for each symbol accessible in the given
+   PACKAGE with VAR bound to the current symbol."
+  (expand-package-iteration-macro 'iterate-over-accessable-symbols var pkg result body env))
+
+(defmacro do-present-symbols ((var &optional pkg result) &body body &environment env)
+  (expand-package-iteration-macro 'iterate-over-present-symbols var pkg result body env))
+
+(defmacro do-external-symbols ((var &optional pkg result) &body body &environment env)
+  "DO-EXTERNAL-SYMBOLS (VAR [PACKAGE [RESULT-FORM]]) {DECL}* {TAG | FORM}*
+   Executes the FORMs once for each external symbol in the given PACKAGE with
+   VAR bound to the current symbol."
+  (expand-package-iteration-macro 'iterate-over-external-symbols var pkg result body env))
+
+(defmacro do-all-symbols ((var &optional resultform)
+                          &body body &environment env)
+  "DO-ALL-SYMBOLS (VAR [RESULT-FORM]) {DECLARATION}* {TAG | FORM}*
+   Executes the FORMs once for each symbol in every package with VAR bound
+   to the current symbol."
+  (multiple-value-bind (body decls) (parse-body body env nil)
+    (let* ((ftemp (gensym))
+           (vtemp (gensym))
+           (result (do-syms-result var resultform)))
+      `(block nil
+        (let* ((,var nil))
+         ,@decls
+           (flet ((,ftemp (,vtemp) (declare (debugging-function-name nil)) (setq ,var ,vtemp) (tagbody ,@body)))
+             (declare (dynamic-extent #',ftemp))
+             (iterate-over-all-symbols #',ftemp))
+           ,@(when result `(,result)))))))
+
+(defmacro multiple-value-list (form)
+  `(multiple-value-call #'list ,form))
+
+
+
+
+(defmacro %i> (x y)
+  `(> (the fixnum ,x) (the fixnum ,y)))
+
+(defmacro %i< (x y)
+  `(< (the fixnum ,x) (the fixnum ,y)))
+
+(defmacro %i<= (x y)
+ `(not (%i> ,x ,y)))
+
+(defmacro %i>= (x y)
+ `(not (%i< ,x ,y)))
+
+(defmacro bitset (bit number)
+  `(logior (ash 1 ,bit) ,number))
+
+(defmacro bitclr (bit number)
+  `(logand (lognot (ash 1 ,bit)) ,number))
+
+(defmacro bitopf ((op bit place) &environment env)
+  (multiple-value-bind (vars vals stores store-form access-form)
+                       (get-setf-method place env)
+    (let* ((constant-bit-p (constantp bit))
+           (bitvar (if constant-bit-p bit (gensym))))
+      `(let ,(unless constant-bit-p `((,bitvar ,bit)))          ; compiler isn't smart enough
+         (let* ,(mapcar #'list `(,@vars ,@stores) `(,@vals (,op ,bitvar ,access-form)))
+           ,store-form)))))
+
+(defmacro bitsetf (bit place)
+  `(bitopf (bitset ,bit ,place)))
+
+(defmacro bitclrf (bit place)
+  `(bitopf (bitclr ,bit ,place)))
+
+(defmacro %svref (v i)
+  (let* ((vtemp (make-symbol "VECTOR"))
+           (itemp (make-symbol "INDEX")))
+      `(let* ((,vtemp ,v)
+              (,itemp ,i))
+         (locally (declare (optimize (speed 3) (safety 0)))
+           (svref ,vtemp ,itemp)))))
+
+(defmacro %svset (v i new)
+  (let* ((vtemp (make-symbol "VECTOR"))
+         (itemp (make-symbol "INDEX"))
+         (ntemp (make-symbol "NEW")))
+    `(let* ((,vtemp ,v)
+            (,itemp ,i)
+            (,ntemp ,new))
+      (locally (declare (optimize (speed 3) (safety 0)))
+        (setf (svref ,vtemp ,itemp) ,ntemp)))))
+
+
+(defmacro %schar (v i)
+  (let* ((vtemp (make-symbol "STRING"))
+         (itemp (make-symbol "INDEX")))
+    `(let* ((,vtemp ,v)
+            (,itemp ,i))
+       (locally (declare (optimize (speed 3) (safety 0)))
+         (schar ,vtemp ,itemp)))))
+
+(defmacro %set-schar (v i new)
+  (let* ((vtemp (make-symbol "STRING"))
+         (itemp (make-symbol "INDEX"))
+         (ntemp (make-symbol "NEW")))
+      `(let* ((,vtemp ,v)
+              (,itemp ,i)
+              (,ntemp ,new))
+         (locally (declare (optimize (speed 3) (safety 0)))
+           (setf (schar ,vtemp ,itemp) ,ntemp)))))
+
+
+
+(defmacro %char-code (c) `(char-code (the character ,c)))
+(defmacro %code-char (i) `(code-char (the (mod 256) ,i)))
+
+(defmacro %izerop (x) `(eq ,x 0))
+(defmacro %iminusp (x) `(< (the fixnum ,x) 0))
+(defmacro %i+ (&rest (&optional (n0 0) &rest others))
+  (if others
+    `(the fixnum (+ (the fixnum ,n0) (%i+ ,@others)))
+    `(the fixnum ,n0)))
+(defmacro %i- (x y &rest others) 
+  (if (not others)
+    `(the fixnum (- (the fixnum ,x) (the fixnum ,y)))
+    `(the fixnum (- (the fixnum ,x) (the fixnum (%i+ ,y ,@others))))))
+
+
+(defmacro %i* (x y) `(the fixnum (* (the fixnum ,x) (the fixnum ,y))))
+
+(defmacro %ilogbitp (b i)
+  (target-word-size-case
+   (32
+    `(logbitp (the (integer 0 29) ,b) (the fixnum ,i)))
+   (64
+    `(logbitp (the (integer 0 60) ,b) (the fixnum ,i)))))
+
+;;; Seq-Dispatch does an efficient type-dispatch on the given Sequence.
+
+(defmacro seq-dispatch (sequence list-form array-form)
+  `(if (sequence-type ,sequence)
+       ,list-form
+       ,array-form))
+
+
+(defsetf %get-byte %set-byte)
+(defsetf %get-unsigned-byte %set-unsigned-byte)
+(defsetf %get-signed-byte %set-byte)
+(defsetf %get-word %set-word)
+(defsetf %get-signed-word %set-word)
+(defsetf %get-unsigned-word %set-unsigned-word)
+(defsetf %get-long %set-long)
+(defsetf %get-signed-long %set-long)
+(defsetf %get-unsigned-long %set-unsigned-long)
+(defsetf %get-full-long %set-long)
+(defsetf %get-point %set-long)
+(defsetf %get-ptr %set-ptr)
+(defsetf %get-double-float %set-double-float)
+(defsetf %get-single-float %set-single-float)
+(defsetf %get-bit %set-bit)
+(defsetf %get-unsigned-long-long %set-unsigned-long-long)
+(defsetf %%get-unsigned-longlong %%set-unsigned-longlong)
+(defsetf %get-signed-long-long %set-signed-long-long)
+(defsetf %%get-signed-longlong %%set-signed-longlong)
+(defsetf %get-bitfield %set-bitfield)
+
+(defmacro %ilognot (int) `(%i- -1 ,int))
+
+(defmacro %ilogior2 (x y) 
+  `(logior (the fixnum ,x) (the fixnum ,y)))
+
+(defmacro %ilogior (body &rest args)
+   (while args
+     (setq body (list '%ilogior2 body (pop args))))
+   body)
+
+(defmacro %ilogand2 (x y)
+  `(logand (the fixnum ,x) (the fixnum ,y)))
+
+(defmacro %ilogand (body &body args)
+   (while args
+     (setq body (list '%ilogand2 body (pop args))))
+   body)
+
+(defmacro %ilogxor2 (x y)
+  `(logxor (the fixnum ,x) (the fixnum ,y)))
+
+(defmacro %ilogxor (body &body args)
+   (while args
+     (setq body (list '%ilogxor2 body (pop args))))
+   body)
+
+(defmacro with-macptrs (varlist &rest body &environment env)
+  (multiple-value-bind (body other-decls) (parse-body body env)
+    (collect ((temp-bindings)
+              (temp-decls)
+              (bindings)
+              (our-decls)
+              (inits))
+      (dolist (var varlist)
+        (let* ((temp (gensym)))
+          (temp-decls temp)
+        (if (consp var)
+          (progn
+            (our-decls (car var))
+            (temp-bindings `(,temp (%null-ptr)))
+            (bindings `(,(car var) ,temp))
+            (if (cdr var)
+              (inits `(%setf-macptr ,temp ,@(cdr var)))))
+          (progn
+            (our-decls var)
+            (temp-bindings  `(,temp  (%null-ptr)))
+            (bindings `(,var ,temp))))))
+  `(let* ,(temp-bindings)
+    (declare (dynamic-extent ,@(temp-decls)))
+    (declare (type macptr ,@(temp-decls)))
+    ,@(inits)
+    (let* ,(bindings)
+      (declare (type macptr ,@(our-decls)))
+      ,@other-decls
+      ,@body)))))
+
+
+(defmacro with-loading-file (filename &rest body)
+   `(let ((*loading-files* (cons ,filename (locally (declare (special *loading-files*))
+                                                    *loading-files*))))
+      (declare (special *loading-files*))
+      ,@body))
+
+(defmacro with-input-from-string ((var string &key index start end) &body forms &environment env)
+  "Create an input string stream, provide an opportunity to perform
+operations on the stream (returning zero or more values), and then close
+the string stream.
+
+STRING is evaluated first, and VAR is bound to a character input string
+stream that supplies characters from the subsequence of the resulting
+string bounded by start and end. BODY is executed as an implicit progn."
+  (multiple-value-bind (forms decls) (parse-body forms env nil)
+    `(let ((,var
+	    ,(cond ((null end)
+		    `(make-string-input-stream ,string ,(or start 0)))
+		   ((symbolp end)
+		    `(if ,end
+		      (make-string-input-stream ,string ,(or start 0) ,end)
+		      (make-string-input-stream ,string ,(or start 0))))
+		   (t
+		    `(make-string-input-stream ,string ,(or start 0) ,end)))))
+      ,@decls
+      (unwind-protect
+           (multiple-value-prog1
+               (progn ,@forms)
+             ,@(if index `((setf ,index (string-input-stream-index ,var)))))
+        (close ,var)))))
+
+(defmacro with-output-to-string ((var &optional string &key (element-type 'base-char element-type-p))
+                                 &body body 
+                                 &environment env)
+  "Create a character output stream, perform a series of operations that
+may send results to this stream, and then close the stream.  BODY is
+executed as an implicit progn with VAR bound to an output string stream.
+All output to that string stream is saved in a string."
+  (let ((string-var (gensym "string")))
+    (multiple-value-bind (forms decls) (parse-body body env nil)
+      `(let* ((,string-var ,string)
+              (,var (if ,string-var
+                      ,@(if element-type-p
+                            `((progn
+                                ,element-type
+                                (%make-string-output-stream ,string-var)))
+                            `((%make-string-output-stream ,string-var)))
+                      ,@(if element-type-p
+                            `((make-string-output-stream :element-type ,element-type))
+                            `((make-string-output-stream))))))
+         ,@decls
+         (unwind-protect
+              (progn
+                ,@forms
+                ,@(if string () `((get-output-stream-string ,var))))
+           (close ,var))))))
+
+(defmacro with-output-to-truncating-string-stream ((var len) &body body
+						   &environment env)
+  (multiple-value-bind (forms decls) (parse-body body env nil)
+    `(let* ((,var (make-truncating-string-stream ,len)))
+      ,@decls
+      (unwind-protect
+	   (progn
+	     ,@forms
+	     (values (get-output-stream-string ,var)
+		     (slot-value ,var 'truncated)))
+	(close ,var)))))
+
+(defmacro with-open-file ((var filename . args) &body body &aux (stream (gensym))(done (gensym)))
+  "Use open to create a file stream to file named by filename. Filename is
+the name of the file to be opened. Options are used as keyword arguments
+to open."
+  `(let (,stream ,done)
+     (unwind-protect
+       (multiple-value-prog1
+         (let ((,var (setq ,stream (open ,filename ,@args))))
+           ,@body)
+         (setq ,done t))
+       (when ,stream (close ,stream :abort (null ,done))))))
+
+(defmacro with-compilation-unit ((&key override) &body body)
+  "WITH-COMPILATION-UNIT ({Key Value}*) Form*
+  This form affects compilations that take place within its dynamic extent. It
+  is intended to be wrapped around the compilation of all files in the same
+  system. These keywords are defined:
+    :OVERRIDE Boolean-Form
+        One of the effects of this form is to delay undefined warnings
+        until the end of the form, instead of giving them at the end of each
+        compilation. If OVERRIDE is NIL (the default), then the outermost
+        WITH-COMPILATION-UNIT form grabs the undefined warnings. Specifying
+        OVERRIDE true causes that form to grab any enclosed warnings, even if
+        it is enclosed by another WITH-COMPILATION-UNIT."
+  `(flet ((with-compilation-unit-body ()
+            ,@body))
+     (declare (dynamic-extent #'with-compilation-unit-body))
+     (call-with-compilation-unit #'with-compilation-unit-body :override ,override)))
+
+; Yow! Another Done Fun.
+(defmacro with-standard-io-syntax (&body body &environment env)
+  "Bind the reader and printer control variables to values that enable READ
+   to reliably read the results of PRINT. These values are:
+       *PACKAGE*                        the COMMON-LISP-USER package
+       *PRINT-ARRAY*                    T
+       *PRINT-BASE*                     10
+       *PRINT-CASE*                     :UPCASE
+       *PRINT-CIRCLE*                   NIL
+       *PRINT-ESCAPE*                   T
+       *PRINT-GENSYM*                   T
+       *PRINT-LENGTH*                   NIL
+       *PRINT-LEVEL*                    NIL
+       *PRINT-LINES*                    NIL
+       *PRINT-MISER-WIDTH*              NIL
+       *PRINT-PRETTY*                   NIL
+       *PRINT-RADIX*                    NIL
+       *PRINT-READABLY*                 T
+       *PRINT-RIGHT-MARGIN*             NIL
+       *READ-BASE*                      10
+       *READ-DEFAULT-FLOAT-FORMAT*      SINGLE-FLOAT
+       *READ-EVAL*                      T
+       *READ-SUPPRESS*                  NIL
+       *READTABLE*                      the standard readtable"
+  (multiple-value-bind (decls body) (parse-body body env)
+    `(let ((*package* (pkg-arg "COMMON-LISP-USER"))
+           (*print-array* t)
+           (*print-base* 10.)
+           (*print-case* :upcase)
+           (*print-circle* nil)
+           (*print-escape* t)
+           (*print-gensym* t)
+           (*print-length* nil)
+           (*print-level* nil)
+           (*print-lines* nil) ; This doesn't exist as of 5/15/90 - does now
+           (*print-miser-width* nil)
+           (*print-pprint-dispatch* nil)
+           (*print-pretty* nil)
+           (*print-radix* nil)
+           (*print-readably* t)
+           (*print-right-margin* nil)
+           (*read-base* 10.)
+           (*read-default-float-format* 'single-float)
+           (*read-eval* t) ; Also MIA as of 5/15/90
+           (*read-suppress* nil)
+           (*readtable* %standard-readtable%)
+	   ; ccl extensions (see l1-io.lisp)
+	   (*print-abbreviate-quote* t)
+	   (*print-structure* t)
+	   (*print-simple-vector* nil)
+	   (*print-simple-bit-vector* nil)
+	   (*print-string-length* nil))
+       ,@decls
+       ,@body)))
+
+(defmacro with-self-bound-io-control-vars (&body body)
+  `(let (
+         (*print-array* *print-array*)
+         (*print-base* *print-base*)
+         (*print-case* *print-case*)
+         (*print-circle* *print-circle*)
+         (*print-escape* *print-escape*)
+         (*print-gensym* *print-gensym*)
+         (*print-length* *print-length*)
+         (*print-level* *print-level*)
+         (*print-lines* *print-lines*)
+         (*print-miser-width* *print-miser-width*)
+         (*print-pprint-dispatch* *print-pprint-dispatch*)
+         (*print-pretty* *print-pretty*)
+         (*print-radix* *print-radix*)
+         (*print-readably* *print-readably*)
+         (*print-right-margin* *print-right-margin*)
+         (*read-base* *read-base*)
+         (*read-default-float-format* *read-default-float-format*)
+         (*read-eval* *read-eval*)
+         (*read-suppress* *read-suppress*)
+         (*readtable* *readtable*))
+     ,@body))
+
+(defmacro print-unreadable-object (&environment env (object stream &key type identity) &body forms)
+  "Output OBJECT to STREAM with \"#<\" prefix, \">\" suffix, optionally
+  with object-type prefix and object-identity suffix, and executing the
+  code in BODY to provide possible further output."
+  (multiple-value-bind (body decls) (parse-body forms env)
+    (if body
+      (let ((thunk (gensym)))
+        `(let ((,thunk #'(lambda () ,@decls ,@body)))
+           (declare (dynamic-extent ,thunk))
+          (%print-unreadable-object ,object ,stream ,type ,identity ,thunk)))
+      `(%print-unreadable-object ,object ,stream ,type ,identity nil))))
+;; Pointers and Handles
+
+;;Add function to lisp system pointer functions, and run it if it's not already
+;; there.
+(defmacro def-ccl-pointers (name arglist &body body &aux (old (gensym)))
+  `(flet ((,name ,arglist ,@body))
+     (let ((,old (member ',name *lisp-system-pointer-functions* :key #'function-name)))
+       (if ,old
+         (rplaca ,old #',name)
+         (progn
+           (push #',name *lisp-system-pointer-functions*)
+           (,name))))))
+
+(defmacro def-load-pointers (name arglist &body body &aux (old (gensym)))
+  `(flet ((,name ,arglist ,@body))
+     (let ((,old (member ',name *lisp-user-pointer-functions* :key #'function-name)))
+       (if ,old
+         (rplaca ,old #',name)
+         (progn
+           (push #',name *lisp-user-pointer-functions*)
+           (,name))))))
+
+;Queue up some code to run after ccl all loaded up, or, if ccl is already
+;loaded up, just run it right now.
+(defmacro queue-fixup (&rest body &aux (fn (gensym)))
+  `(let ((,fn #'(lambda () ,@body)))
+     (if (eq %lisp-system-fixups% T)
+       (funcall ,fn)
+       (push (cons ,fn (or *loading-toplevel-location* *loading-file-source-file*)) %lisp-system-fixups%))))
+
+(defmacro %incf-ptr (p &optional (by 1))
+  (if (symbolp p)  ;once-only
+    `(%setf-macptr (the macptr ,p) (%inc-ptr ,p ,by))
+    (let ((var (gensym)))
+      `(let ((,var ,p)) (%setf-macptr (the macptr ,var) (%inc-ptr ,var ,by))))))
+
+(defmacro with-string-from-cstring ((s ptr) &body body)
+  (let* ((len (gensym))
+	 (p (gensym)))
+    `(let* ((,p ,ptr)
+	    (,len (%cstrlen ,p))
+	    (,s (make-string ,len)))
+      (declare (fixnum ,len))
+      (%copy-ptr-to-ivector ,p 0 ,s 0 ,len)
+      (locally
+	  ,@body))))
+
+
+(defmacro with-cstr ((sym str &optional start end) &rest body &environment env)
+  (multiple-value-bind (body decls) (parse-body body env nil)
+    (if (and (base-string-p str) (null start) (null end))
+      (let ((strlen (%i+ (length str) 1)))
+        `(%stack-block ((,sym ,strlen))
+           ,@decls
+           (%cstr-pointer ,str ,sym)
+           ,@body))
+      (let ((strname (gensym))
+            (start-name (gensym))
+            (end-name (gensym)))
+        `(let ((,strname ,str)
+               ,@(if (or start end)
+                   `((,start-name ,(or start 0))
+                     (,end-name ,(or end `(length ,strname))))))
+           (%vstack-block (,sym
+                           (the fixnum
+                             (1+
+                              (the fixnum
+                                ,(if (or start end)
+                                     `(byte-length
+                                       ,strname ,start-name ,end-name)
+                                     `(length ,strname))))))
+             ,@decls
+             ,(if (or start end)
+                `(%cstr-segment-pointer ,strname ,sym ,start-name ,end-name)
+                `(%cstr-pointer ,strname ,sym))
+             ,@body))))))
+
+(defmacro with-utf-8-cstr ((sym str) &body body)
+  (let* ((data (gensym))
+         (offset (gensym))
+         (string (gensym))
+         (len (gensym))
+         (noctets (gensym))
+         (end (gensym)))
+    `(let* ((,string ,str)
+            (,len (length ,string)))
+      (multiple-value-bind (,data ,offset) (array-data-and-offset ,string)
+        (let* ((,end (+ ,offset ,len))
+               (,noctets (utf-8-octets-in-string ,data ,offset ,end)))
+          (%stack-block ((,sym (1+ ,noctets)))
+            (utf-8-memory-encode ,data ,sym 0 ,offset ,end)
+            (setf (%get-unsigned-byte ,sym ,noctets) 0)
+            ,@body))))))
+
+
+
+(defmacro with-native-utf-16-cstr ((sym str) &body body)
+  (let* ((data (gensym))
+         (offset (gensym))
+         (string (gensym))
+         (len (gensym))
+         (noctets (gensym))
+         (end (gensym)))
+    `(let* ((,string ,str)
+            (,len (length ,string)))
+      (multiple-value-bind (,data ,offset) (array-data-and-offset ,string)
+        (let* ((,end (+ ,offset ,len))
+               (,noctets (utf-16-octets-in-string ,data ,offset ,end)))
+          (%stack-block ((,sym (1+ ,noctets)))
+            (native-utf-16-memory-encode ,data ,sym 0 ,offset ,end)
+            (setf (%get-unsigned-word ,sym ,noctets) 0)
+            ,@body))))))
+
+(defmacro with-pointers (speclist &body body)
+   (with-specs-aux 'with-pointer speclist body))
+
+
+
+(defmacro with-cstrs (speclist &body body)
+   (with-specs-aux 'with-cstr speclist body))
+
+(defmacro with-utf-8-cstrs (speclist &body body)
+   (with-specs-aux 'with-utf-8-cstr speclist body))
+
+(defmacro with-native-utf-16-cstrs (speclist &body body)
+  (with-specs-aux 'with-native-utf-16-cstr speclist body))
+
+(defmacro with-encoded-cstr ((encoding-name (sym string &optional start end))
+                             &rest body &environment env)
+  (let* ((encoding (gensym))
+         (str (gensym)))
+      (multiple-value-bind (body decls) (parse-body body env nil)
+        `(let* ((,str ,string)
+                (,encoding (get-character-encoding ,encoding-name)))
+          (%stack-block ((,sym (cstring-encoded-length-in-bytes ,encoding ,str ,start ,end) :clear t))
+            ,@decls
+            (encode-string-to-memory ,encoding ,sym 0 ,str ,start ,end)
+            ,@body)))))
+
+(defmacro with-encoded-cstrs (encoding-name bindings &body body)
+  (with-specs-aux 'with-encoded-cstr (mapcar #'(lambda (b)
+                                                 `(,encoding-name ,b))
+                                             bindings) body))
+
+(defmacro with-filename-cstrs (&rest rest)
+  (case (target-os-name)
+    (:darwin `(with-utf-8-cstrs ,@rest))
+    (:windows `(with-native-utf-16-cstrs ,@rest))
+    (t `(with-encoded-cstrs (pathname-encoding-name) ,@rest))))
+
+
+(defun with-specs-aux (name spec-list original-body)
+  (multiple-value-bind (body decls) (parse-body original-body nil)
+    (when decls (signal-program-error "declarations not allowed in ~s" original-body))
+    (setq body (cons 'progn body))
+    (dolist (spec (reverse spec-list))
+      (setq body (list name spec body)))
+    body))
+
+
+(defmacro type-predicate (type)
+  `(get-type-predicate ,type))
+
+(defsetf type-predicate set-type-predicate)
+
+(defun adjust-defmethod-lambda-list (ll)
+  ;; If the lambda list contains &key, ensure that it also contains
+  ;; &allow-other-keys
+  (if (or (not (memq '&key ll))
+          (memq '&allow-other-keys ll))
+    ll
+    (if (memq '&aux ll)
+      (let* ((ll (copy-list ll))
+             (aux (memq '&aux ll)))
+        (setf (car aux) '&allow-other-keys
+              (cdr aux) (cons '&aux (cdr aux)))
+        ll)
+      (append ll '(&allow-other-keys)))))
+
+(defmacro defmethod (name &rest args &environment env)
+  (multiple-value-bind (function-form specializers-form qualifiers lambda-list documentation specializers)
+      (parse-defmethod name args env)
+    `(progn
+       (eval-when (:compile-toplevel)
+         (record-function-info ',(maybe-setf-function-name name)
+                               ',(multiple-value-bind (bits keyvect) (encode-lambda-list lambda-list t)
+                                   (unless bits ;; verify failed
+                                     (signal-program-error "Invalid lambda list ~s"
+                                                           (find-if #'listp args)))
+                                   (%cons-def-info 'defmethod bits keyvect nil specializers qualifiers))
+                               ,env))
+       (compiler-let ((*nx-method-warning-name* '(,name ,@qualifiers ,specializers)))
+         (ensure-method ',name ,specializers-form
+                        :function ,function-form
+                        :qualifiers ',qualifiers
+                        :lambda-list ',lambda-list
+                        ,@(if documentation `(:documentation ,documentation)))))))
+
+
+(defun seperate-defmethod-decls (decls)
+  (let (outer inner)
+    (dolist (decl decls)
+      (if (neq (car decl) 'declare)
+        (push decl outer)
+        (let (outer-list inner-list)
+          (dolist (d (cdr decl))
+            (if (and (listp d) (eq (car d) 'dynamic-extent))
+              (let (in out)
+                (dolist (fspec (cdr d))
+                  (if (and (listp fspec)
+                           (eq (car fspec) 'function)
+                           (listp (cdr fspec))
+                           (null (cddr fspec))
+                           (memq (cadr fspec) '(call-next-method next-method-p)))
+                    (push fspec in)
+                    (push fspec out)))
+                (when out
+                  (push `(dynamic-extent ,@(nreverse out)) outer-list))
+                (when in
+                  (push `(dynamic-extent ,@(nreverse in)) inner-list)))
+              (push d outer-list)))
+          (when outer-list
+            (push `(declare ,@(nreverse outer-list)) outer))
+          (when inner-list
+            (push `(declare ,@(nreverse inner-list)) inner)))))
+    (values (nreverse outer) (nreverse inner))))
+		   
+
+(defvar *warn-about-unreferenced-required-args-in-methods* #+ccl-0711 nil #-ccl-0711 T)
+
+(defun parse-defmethod (name args env)
+  (validate-function-name name)
+  (let (qualifiers lambda-list parameters specializers specializers-form refs types temp)
+    (until (listp (car args))
+      (push (pop args) qualifiers))
+    (setq lambda-list (pop args))
+    (while (and lambda-list (not (memq (car lambda-list) lambda-list-keywords)))
+      (let ((p (pop lambda-list)))
+        (cond ((consp p)
+               (unless (and (consp (%cdr p)) (null (%cddr p)))
+                 (signal-program-error "Illegal arg ~S" p))
+               (push (%car p) parameters)
+               (push (%car p) refs)
+               (setq p (%cadr p))
+               (cond ((and (consp p) (eq (%car p) 'eql)
+                           (consp (%cdr p)) (null (%cddr p)))
+                      (push `(list 'eql ,(%cadr p)) specializers-form)
+                      (push p specializers))
+                     ((or (setq temp (non-nil-symbol-p p))
+                          (specializer-p p))
+                      (push `',p specializers-form)
+                      (push p specializers)
+                      (unless (or (eq p t) (not temp))
+                        ;Should be `(guaranteed-type ...).
+                        (push `(type ,p ,(%car parameters)) types)))
+                     (t (signal-program-error "Illegal arg ~S" p))))
+              (t
+               (push p parameters)
+               (unless *warn-about-unreferenced-required-args-in-methods*
+                 (push p refs))
+               (push t specializers-form)
+               (push t specializers)))))
+    (setq lambda-list (nreconc parameters lambda-list))
+    (multiple-value-bind (body decls doc) (parse-body args env t)
+      (multiple-value-bind (outer-decls inner-decls) 
+                           (seperate-defmethod-decls decls)
+        (let* ((methvar (make-symbol "NEXT-METHOD-CONTEXT"))
+               (cnm-args (gensym))
+               (lambda-form `(lambda ,(list* '&method methvar lambda-list)
+                               (declare ;,@types
+                                (ignorable ,@refs))
+                               ,@outer-decls
+                               (block ,(if (consp name) (cadr name) name)
+                                 (flet ((call-next-method (&rest ,cnm-args)
+                                          (declare (dynamic-extent ,cnm-args))
+                                          (if ,cnm-args
+                                            (apply #'%call-next-method-with-args ,methvar ,cnm-args)
+                                            (%call-next-method ,methvar)))
+                                        (next-method-p () (%next-method-p ,methvar)))
+                                   (declare (inline call-next-method next-method-p))
+                                   ,@inner-decls
+                                   ,@body)))))
+          (values
+           (if name `(nfunction ,name ,lambda-form) `(function ,lambda-form))
+           `(list ,@(nreverse specializers-form))
+           (nreverse qualifiers)
+	   lambda-list
+           doc
+           (nreverse specializers)))))))
+
+(defmacro anonymous-method (name &rest args &environment env)
+  (multiple-value-bind (function-form specializers-form qualifiers method-class documentation)
+                       (parse-defmethod name args env)
+    
+    `(%anonymous-method
+      ,function-form
+      ,specializers-form
+      ',qualifiers
+      ,@(if (or method-class documentation) `(',method-class))
+      ,@(if documentation `(,documentation)))))
+
+
+
+(defmacro defclass (class-name superclasses slots &rest class-options &environment env)
+  (flet ((duplicate-options (where) (signal-program-error "Duplicate options in ~S" where))
+         (illegal-option (option) (signal-program-error "Illegal option ~s" option))
+         (make-initfunction (form)
+           (cond ((or (eq form 't)
+                      (equal form ''t))
+                  '(function true))
+                 ((or (eq form 'nil)
+                      (equal form ''nil))
+                  '(function false))
+                 (t
+                  `(function (lambda () ,form))))))
+    (setq class-name (require-type class-name '(and symbol (not null))))
+    (setq superclasses (mapcar #'(lambda (s) (require-type s 'symbol)) superclasses))
+    (let* ((options-seen ())
+           (signatures ())
+           (slot-names ())
+           (slot-initargs ()))
+      (flet ((canonicalize-defclass-option (option)
+               (let* ((option-name (car option)))
+                 (if (member option-name options-seen :test #'eq)
+                   (duplicate-options class-options)
+                   (push option-name options-seen))
+                 (case option-name
+                   (:default-initargs
+                       (let ((canonical ())
+                             (initargs-seen ()))
+                         (let (key val (tail (cdr option)))
+                           (loop (when (null tail) (return nil))
+                              (setq key (pop tail)
+                                    val (pop tail))
+                              (when (memq key initargs-seen)
+                                (SIGNAL-PROGRAM-error "Duplicate initialization argument name ~S in :DEFAULT-INITARGS of DEFCLASS ~S" key class-name))
+                              (push key initargs-seen)
+                              (push ``(,',key ,',val  ,,(make-initfunction val)) canonical))
+                           `(':direct-default-initargs (list ,@(nreverse canonical))))))
+                   (:metaclass
+                    (unless (and (cadr option)
+                                 (typep (cadr option) 'symbol))
+                      (illegal-option option))
+                    `(:metaclass  ',(cadr option)))
+                   (:documentation
+                    `(:documentation ',(cadr option)))
+                   (t
+                     (list `',option-name `',(cdr option))))))
+             (canonicalize-slot-spec (slot)
+               (if (null slot) (signal-program-error "Illegal slot NIL"))
+               (if (not (listp slot)) (setq slot (list slot)))
+               (let* ((slot-name (require-type (car slot) 'symbol))
+		      (initargs nil)
+                      (other-options ())
+		      (initform nil)
+		      (initform-p nil)
+		      (initfunction nil)
+		      (type nil)
+		      (type-p nil)
+		      (allocation nil)
+		      (allocation-p nil)
+		      (documentation nil)
+		      (documentation-p nil)
+                      (readers nil)
+		      (writers nil)
+                      (reader-info (%cons-def-info 'defmethod (dpb 1 $lfbits-numreq 0) nil nil (list class-name)))
+                      (writer-info (%cons-def-info 'defmethod (dpb 2 $lfbits-numreq 0) nil nil (list t class-name))))
+                 (when (memq slot-name slot-names)
+                   (signal-program-error "Multiple slots named ~S in DEFCLASS ~S" slot-name class-name))
+                 (push slot-name slot-names)
+                 (do ((options (cdr slot) (cddr options))
+                      name)
+                     ((null options))
+                   (when (null (cdr options)) (signal-program-error "Illegal slot spec ~S" slot))
+                   (case (car options)
+                     (:reader
+                      (setq name (cadr options))
+                      (unless (memq name readers)
+                        (push (cons name reader-info) signatures)
+                        (push name readers)))
+                     (:writer                      
+                      (setq name (cadr options))
+                      (unless (member name writers :test 'equal)
+                        (push (cons name writer-info) signatures)
+                        (push name writers)))
+                     (:accessor
+                      (setq name (cadr options))
+                      (unless (memq name readers)
+                        (push (cons name reader-info) signatures)
+                        (push name readers))
+                      (let ((setf-name `(setf ,name)))
+                        (unless (member setf-name writers :test 'equal)
+                          (push (cons (setf-function-name name) writer-info) signatures)
+                          (push setf-name writers))))
+                     (:initarg
+                      (let* ((initarg (require-type (cadr options) 'symbol))
+                             (other (position initarg slot-initargs :test #'memq)))
+                        (when other
+                          (warn "Initarg ~s occurs in both ~s and ~s slots"
+                                initarg (nth (1+ other) slot-names) slot-name))
+                        (push initarg initargs)))
+                     (:type
+                      (if type-p
+			(duplicate-options slot)
+			(setq type-p t))
+                      (setq type (cadr options))
+                      ;; complain about illegal typespecs and continue
+                      (handler-case (specifier-type type env)
+                        (program-error ()
+                          (warn "Invalid type ~s in ~s slot definition ~s" type class-name slot))))
+                     (:initform
+                      (if initform-p
+			(duplicate-options slot)
+			(setq initform-p t))
+                      (let ((option (cadr options)))
+                        (setq initform `',option
+                              initfunction
+                              (if (constantp option)
+                                `(constantly ,option)
+                                `#'(lambda () ,option)))))
+                     (:allocation
+                      (if allocation-p
+			(duplicate-options slot)
+			(setq allocation-p t))
+                      (setq allocation (cadr options)))
+                     (:documentation
+                      (if documentation-p
+			(duplicate-options slot)
+			(setq documentation-p t))
+                      (setq documentation (cadr options)))
+                     (t
+                      (let* ((pair (or (assq (car options) other-options)
+                                       (car (push (list (car options)) other-options)))))
+                        (push (cadr options) (cdr pair))))))
+                 (push initargs slot-initargs)
+                 `(list :name ',slot-name
+		   ,@(when allocation `(:allocation ',allocation))
+		   ,@(when initform-p `(:initform ,initform
+					:initfunction ,initfunction))
+		   ,@(when initargs `(:initargs ',initargs))
+		   ,@(when readers `(:readers ',readers))
+		   ,@(when writers `(:writers ',writers))
+		   ,@(when type-p `(:type ',type))
+		   ,@(when documentation-p `(:documentation ,documentation))
+                   ,@(mapcan #'(lambda (opt)
+                                 `(',(car opt) ',(if (null (cddr opt))
+                                                     (cadr opt)
+                                                     (cdr opt)))) other-options)))))
+	(let* ((direct-superclasses superclasses)
+	       (direct-slot-specs (mapcar #'canonicalize-slot-spec slots))
+	       (other-options (apply #'append (mapcar #'canonicalize-defclass-option class-options )))
+	       (keyvect (class-keyvect class-name other-options)))
+	  (when (vectorp keyvect)
+	    (let ((illegal (loop for arg in other-options by #'cddr
+			      as key = (if (quoted-form-p arg) (%cadr arg) arg)
+			      unless (or (eq key :metaclass) (find key keyvect)) collect key)))
+	      (when illegal
+		(signal-program-error "Class option~p~{ ~s~} is not one of ~s"
+				      (length illegal) illegal keyvect))))
+	  `(progn
+	     (when (memq ',class-name *nx-known-declarations*)
+	       (check-declaration-redefinition ',class-name 'defclass))
+	    (eval-when (:compile-toplevel)
+	      (%compile-time-defclass ',class-name ,env)
+	      (progn
+		,@(mapcar #'(lambda (sig) `(record-function-info ',(car sig) ',(cdr sig) ,env))
+			  signatures)))
+	      (ensure-class-for-defclass ',class-name
+			    :direct-superclasses ',direct-superclasses
+			    :direct-slots ,`(list ,@direct-slot-specs)
+			    ,@other-options)))))))
+
+(defmacro define-method-combination (name &rest rest &environment env)
+  (setq name (require-type name 'symbol))
+  (cond ((or (null rest) (and (car rest) (symbolp (car rest))))
+         `(short-form-define-method-combination ',name ',rest))
+        ((listp (car rest))
+         (destructuring-bind (lambda-list method-group-specifiers . forms) rest
+           (long-form-define-method-combination 
+            name lambda-list method-group-specifiers forms env)))
+        (t (%badarg (car rest) '(or (and null symbol) list)))))
+
+(defmacro defgeneric (function-name lambda-list &rest options-and-methods &environment env)
+  (fboundp function-name)             ; type-check
+  (multiple-value-bind (method-combination generic-function-class options methods)
+      (parse-defgeneric function-name t lambda-list options-and-methods)
+    (let ((gf (gensym)))
+      `(progn
+         (eval-when (:compile-toplevel)
+           (record-function-info ',(maybe-setf-function-name function-name)
+                                 ',(multiple-value-bind (bits keyvect) (encode-lambda-list lambda-list t)
+                                     (%cons-def-info 'defgeneric bits keyvect))
+                                 ,env))
+         (let ((,gf (%defgeneric
+                     ',function-name ',lambda-list ',method-combination ',generic-function-class 
+                     ',(apply #'append options))))
+           (%set-defgeneric-methods ,gf ,@methods)
+           ,gf)))))
+
+
+
+(defun parse-defgeneric (function-name global-p lambda-list options-and-methods)
+  (check-generic-function-lambda-list lambda-list)
+  (let ((method-combination '(standard))
+        (generic-function-class 'standard-generic-function)
+        options declarations methods option-keywords method-class)
+    (flet ((bad-option (o)
+             (signal-program-error "Bad option: ~s to ~s." o 'defgeneric)))
+      (dolist (o options-and-methods)
+        (let ((keyword (car o))
+              (defmethod (if global-p 'defmethod 'anonymous-method)))
+          (if (eq keyword :method)
+	    (let ((defn `(,defmethod ,function-name ,@(%cdr o))))
+	      (note-source-transformation o defn)
+	      (push defn methods))
+            (cond ((and (not (eq keyword 'declare))
+			(memq keyword (prog1 option-keywords (push keyword option-keywords))))		   
+                   (signal-program-error "Duplicate option: ~s to ~s" keyword 'defgeneric))
+                  ((eq keyword :method-combination)
+                   (unless (symbolp (cadr o))
+                     (bad-option o))
+                   (setq method-combination (cdr o)))
+                  ((eq keyword :generic-function-class)
+                   (unless (and (cdr o) (symbolp (cadr o)) (null (%cddr o)))
+                     (bad-option o))
+                   (setq generic-function-class (%cadr o)))
+                  ((eq keyword 'declare)
+		   (push (cadr o) declarations))
+                  ((eq keyword :argument-precedence-order)
+                   (dolist (arg (cdr o))
+                     (unless (and (symbolp arg) (memq arg lambda-list))
+                       (bad-option o)))
+                   (push (list keyword (cdr o)) options))
+                  ((eq keyword :method-class)
+                   (push o options)
+                   (when (or (cddr o) (not (symbolp (setq method-class (%cadr o)))))
+                     (bad-option o)))
+                  ((eq keyword :documentation)
+                   (push o options)
+                   (when (or (cddr o) (not (stringp (%cadr o))))
+                     (bad-option o)))
+                  (t (bad-option o)))))))
+    (when method-class
+      (dolist (m methods)
+        (push `(:method-class ,method-class) (cddr m))))
+    (when declarations
+      (setq options `((:declarations ,declarations) ,@options)))
+    (values method-combination generic-function-class options methods)))
+
+                 
+(defmacro def-aux-init-functions (class &rest functions)
+  `(set-aux-init-functions ',class (list ,@functions)))
+
+
+
+
+
+
+;;; A powerful way of defining REPORT-CONDITION...
+;;; Do they really expect that each condition type has a unique method on PRINT-OBJECT
+;;; which tests *print-escape* ?  Scary if so ...
+
+(defmacro define-condition (name (&rest supers) (&rest slots) &body options)
+  "DEFINE-CONDITION Name (Parent-Type*) (Slot-Spec*) Option*
+   Define NAME as a condition type. This new type inherits slots and its
+   report function from the specified PARENT-TYPEs. A slot spec is a list of:
+     (slot-name :reader <rname> :initarg <iname> {Option Value}*
+
+   The DEFINE-CLASS slot options :ALLOCATION, :INITFORM, [slot] :DOCUMENTATION
+   and :TYPE and the overall options :DEFAULT-INITARGS and
+   [type] :DOCUMENTATION are also allowed.
+
+   The :REPORT option is peculiar to DEFINE-CONDITION. Its argument is either
+   a string or a two-argument lambda or function name. If a function, the
+   function is called with the condition and stream to report the condition.
+   If a string, the string is printed.
+
+   Condition types are classes, but (as allowed by ANSI and not as described in
+   CLtL2) are neither STANDARD-OBJECTs nor STRUCTURE-OBJECTs. WITH-SLOTS and
+   SLOT-VALUE may not be used on condition objects."
+  ; If we could tell what environment we're being expanded in, we'd
+  ; probably want to check to ensure that all supers name conditions
+  ; in that environment.
+  (let ((classopts nil)
+        (duplicate nil)
+        (docp nil)
+	(default-initargs-p nil)
+        (reporter nil))
+    (dolist (option options)
+      (unless (and (consp option)
+                   (consp (%cdr option)))
+        (signal-program-error "Invalid option ~s ." option))
+      (ecase (%car option)
+	(:default-initargs 
+	    (unless (plistp (cdr option)) 
+	      (signal-program-error "~S is not a plist." (%cdr option))) 
+	    (if default-initargs-p 
+	      (setq duplicate t) 
+	      (push (setq default-initargs-p option) classopts))) 
+        (:documentation 
+	 (unless (null (%cddr option)) 
+	   (signal-program-error "Invalid option ~s ." option)) 
+	 (if docp
+	   (setq duplicate t)
+           (push (setq docp option) classopts)))
+        (:report 
+	 (unless (null (%cddr option)) 
+	   (signal-program-error "Invalid option ~s ." option)) 
+         (if reporter
+           (setq duplicate t)
+           (progn
+             (if (or (lambda-expression-p (setq reporter (%cadr option)))
+                     (symbolp reporter))
+               (setq reporter `(function ,reporter))
+               (if (stringp reporter)
+                 (setq reporter `(function (lambda (c s) (declare (ignore c)) (write-string ,reporter s))))
+                 (signal-program-error "~a expression is not a string, symbol, or lambda expression ." (%car option))))
+             (setq reporter `((defmethod report-condition ((c ,name) s)
+                                (funcall ,reporter c s))))))))
+      (if duplicate (signal-program-error "Duplicate option ~s ." option)))
+    `(progn
+       (defclass ,name ,(or supers '(condition)) ,slots ,@classopts)
+       ,@reporter
+       ',name)))
+
+(defmacro with-condition-restarts (&environment env condition restarts &body body)
+  "Evaluates the BODY in a dynamic environment where the restarts in the list
+   RESTARTS-FORM are associated with the condition returned by CONDITION-FORM.
+   This allows FIND-RESTART, etc., to recognize restarts that are not related
+   to the error currently being debugged. See also RESTART-CASE."
+  (multiple-value-bind (body decls)
+                       (parse-body body env)
+    (let ((cond (gensym))
+          (r (gensym)))
+          `(let* ((*condition-restarts* *condition-restarts*))
+             ,@decls
+             (let ((,cond ,condition))
+               (dolist (,r ,restarts) (push (cons ,r ,cond) *condition-restarts*))
+               ,@body)))))
+  
+(defmacro setf-find-class (name arg1 &optional (arg2 () 2-p) (arg3 () 3-p))
+  (cond (3-p ;might want to pass env (arg2) to find-class someday?
+         `(set-find-class ,name (progn ,arg1 ,arg2 ,arg3)))
+        (2-p
+         `(set-find-class ,name (progn ,arg1 ,arg2)))
+        (t `(set-find-class ,name ,arg1))))
+
+(defsetf find-class setf-find-class)
+
+(defmacro restoring-interrupt-level (var &body body)
+  `(unwind-protect
+    (progn ,@body)
+    (restore-interrupt-level ,var)
+    (%interrupt-poll)))
+
+(defmacro without-interrupts (&body body)
+  "Evaluate its body in an environment in which process-interrupt
+requests are deferred."
+  `(let* ((*interrupt-level* -1))
+    ,@body))
+
+(defmacro with-interrupts-enabled (&body body)
+  "Evaluate its body in an environment in which process-interrupt
+has immediate effect."
+  `(let* ((*interrupt-level* 0))
+    ,@body))
+
+;;; undoes the effect of one enclosing without-interrupts during execution of body.
+(defmacro ignoring-without-interrupts (&body body)
+  `(let* ((*interrupt-level* 0))
+    ,@body))
+
+
+
+(defmacro error-ignoring-without-interrupts (format-string &rest format-args)
+  `(ignoring-without-interrupts
+    (error ,format-string ,@format-args)))
+
+
+;init-list-default: if there is no init pair for <keyword>,
+;    add a <keyword> <value> pair to init-list
+(defmacro init-list-default (the-init-list &rest args)
+  (let ((result)
+       (init-list-sym (gensym)))
+   (do ((args args (cddr args)))
+       ((not args))
+     (setq result 
+           (cons `(if (eq '%novalue (getf ,init-list-sym ,(car args) 
+                                          '%novalue))
+                    (setq ,init-list-sym (cons ,(car args) 
+                                               (cons ,(cadr args) 
+                                                     ,init-list-sym))))
+                 result)))                                                                                
+   `(let ((,init-list-sym ,the-init-list))
+      (progn ,@result)
+      ,init-list-sym)
+   ))
+
+; This can only be partially backward-compatible: even if only
+; the "name" arg is supplied, the old function would create the
+; package if it didn't exist.
+; Should see how well this works & maybe flush the whole idea.
+
+(defmacro in-package (name)
+  (let ((form nil))
+    (when (quoted-form-p name)
+      (warn "Unquoting argument ~S to ~S." name 'in-package )
+      (setq name (cadr name)))    
+    (setq form `(set-package ,(string name)))
+    `(eval-when (:execute :load-toplevel :compile-toplevel)
+      ,form)))
+
+(defmacro defpackage (name &rest options)
+  "Defines a new package called PACKAGE. Each of OPTIONS should be one of the 
+   following: 
+    (NICKNAMES {package-name}*)
+
+    (SIZE <integer>)
+    (SHADOW {symbol-name}*)
+    (SHADOWING-IMPORT-FROM <package-name> {symbol-name}*)
+    (USE {package-name}*)
+    (IMPORT-FROM <package-name> {symbol-name}*)
+    (INTERN {symbol-name}*)
+    (EXPORT {symbol-name}*)
+    (IMPLEMENT {package-name}*)
+    (LOCK boolean)
+    (DOCUMENTATION doc-string)
+   All options except SIZE, LOCK, and :DOCUMENTATION can be used multiple 
+   times."
+  (let* ((size nil)
+         (all-names-size 0)
+         (intern-export-size 0)
+         (shadow-etc-size 0)
+	 (documentation nil)
+         (all-names-hash (let ((all-options-alist nil))
+                           (dolist (option options)
+                             (let ((option-name (car option)))
+                               (when (memq option-name
+                                           '(:nicknames :shadow :shadowing-import-from
+                                             :use :import-from :intern :export))
+                                 (let ((option-size (length (cdr option)))
+                                       (cell (assq option-name all-options-alist)))
+                                   (declare (fixnum option-size))
+                                   (if cell
+                                     (incf (cdr cell) option-size)
+                                     (push (cons option-name option-size) all-options-alist))
+                                   (when (memq option-name '(:shadow :shadowing-import-from :import-from :intern))
+                                     (incf shadow-etc-size option-size))
+                                   (when (memq option-name '(:export :intern))
+                                     (incf intern-export-size option-size))))))
+                           (dolist (cell all-options-alist)
+                             (let ((option-size (cdr cell)))
+                               (when (> option-size all-names-size)
+                                 (setq all-names-size option-size))))
+                           (when (> all-names-size 0)
+                             (make-hash-table :test 'equal :size all-names-size))))
+         (intern-export-hash (when (> intern-export-size 0)
+                               (make-hash-table :test 'equal :size intern-export-size)))
+         (shadow-etc-hash (when (> shadow-etc-size 0)
+                            (make-hash-table :test 'equal :size shadow-etc-size)))
+         (external-size nil)
+         (nicknames nil)
+         (shadow nil)
+         (shadowing-import-from-specs nil)
+         (use :default)
+         (import-from-specs nil)
+         (intern nil)
+         (export nil))
+    (declare (fixnum all-names-size intern-export-size shadow-etc-size))
+    (labels ((string-or-name (s) (string s))
+             (duplicate-option (o)
+               (signal-program-error "Duplicate ~S option in ~S ." o options))
+             (duplicate-name (name option-name)
+               (signal-program-error "Name ~s, used in ~s option, is already used in a conflicting option ." name option-name))
+             (all-names (option-name tail already)
+               (when (eq already :default) (setq already nil))
+               (when all-names-hash
+                 (clrhash all-names-hash))
+               (dolist (name already)
+                 (setf (gethash (string-or-name name) all-names-hash) t))
+               (dolist (name tail already)
+                 (setq name (string-or-name name))
+                 (unless (gethash name all-names-hash)          ; Ok to repeat name in same option.
+                   (when (memq option-name '(:shadow :shadowing-import-from :import-from :intern))
+                     (if (gethash name shadow-etc-hash)
+                       (duplicate-name name option-name))
+                     (setf (gethash name shadow-etc-hash) t))
+                   (when (memq option-name '(:export :intern))
+                     (if (gethash name intern-export-hash)
+                       (duplicate-name name option-name))
+                     (setf (gethash name intern-export-hash) t))
+                   (setf (gethash name all-names-hash) t)
+                   (push name already)))))
+      (dolist (option options)
+        (let ((args (cdr option)))
+          (ecase (%car option)
+                 (:size 
+                  (if size 
+                    (duplicate-option :size) 
+                    (setq size (car args))))		 
+                 (:external-size 
+                  (if external-size 
+                    (duplicate-option :external-size) 
+                    (setq external-size (car args))))
+                 (:nicknames (setq nicknames (all-names nil args nicknames)))
+                 (:shadow (setq shadow (all-names :shadow args shadow)))
+                 (:shadowing-import-from
+                  (destructuring-bind (from &rest shadowing-imports) args
+                    (push (cons (string-or-name from)
+                                (all-names :shadowing-import-from shadowing-imports nil))
+                          shadowing-import-from-specs)))
+                 (:use (setq use (all-names nil args use)))
+                 (:import-from
+                  (destructuring-bind (from &rest imports) args
+                    (push (cons (string-or-name from)
+                                (all-names :import-from imports nil))
+                          import-from-specs)))
+                 (:intern (setq intern (all-names :intern args intern)))
+                 (:export (setq export (all-names :export args export)))
+		 (:documentation
+		  (if documentation
+		    (duplicate-option :documentation)
+		    (setq documentation (cadr option)))))))
+      `(eval-when (:execute :compile-toplevel :load-toplevel)
+         (%define-package ',(string-or-name name)
+	  ',size 
+	  ',external-size 
+	  ',nicknames
+	  ',shadow
+	  ',shadowing-import-from-specs
+	  ',use
+	  ',import-from-specs
+	  ',intern
+	  ',export
+	  ',documentation)))))
+
+
+
+(defmacro with-package-iterator ((mname package-list first-type &rest other-types)
+                                 &body body)
+  "Within the lexical scope of the body forms, MNAME is defined via macrolet
+   such that successive invocations of (MNAME) will return the symbols,
+   one by one, from the packages in PACKAGE-LIST. SYMBOL-TYPES may be
+   any of :INHERITED :EXTERNAL :INTERNAL."
+  (setq mname (require-type mname 'symbol))
+  (let ((state (make-symbol "WITH-PACKAGE-ITERATOR_STATE")))
+    (dolist (type (push first-type other-types))
+      (ecase type
+        ((:external :internal :inherited))))
+    `(let ((,state (%setup-pkg-iter-state ,package-list ',other-types)))
+       (macrolet ((,mname () `(%pkg-iter-next ,',state)))
+         ,@body))))
+
+; Does NOT evaluate the constructor, but DOES evaluate the destructor & initializer
+(defmacro defresource (name &key constructor destructor initializer)
+  `(defparameter ,name (make-resource #'(lambda () ,constructor)
+                                      ,@(when destructor
+                                          `(:destructor ,destructor))
+                                      ,@(when initializer
+                                          `(:initializer ,initializer)))))
+
+(defmacro using-resource ((var resource) &body body)
+  (let ((resource-var (gensym)))
+  `(let ((,resource-var ,resource)
+         ,var)
+     (unwind-protect
+       (progn
+         (setq ,var (allocate-resource ,resource-var))
+         ,@body)
+       (when ,var
+         (free-resource ,resource-var ,var))))))
+
+;;; Bind per-thread specials which help with lock accounting.
+(defmacro with-lock-context (&body body)
+  `(progn ,@body))
+
+(defmacro with-lock-grabbed ((lock &optional
+                                   (whostate "Lock"))
+                             &body body)
+  "Wait until a given lock can be obtained, then evaluate its body with
+the lock held."
+  (declare (ignore whostate))
+    (let* ((locked (gensym))
+           (l (gensym)))
+      `  (with-lock-context
+           (let ((,locked (make-lock-acquisition))
+             (,l ,lock))
+        (declare (dynamic-extent ,locked))
+        (unwind-protect
+             (progn
+               (%lock-recursive-lock-object ,l ,locked )
+               ,@body)
+          (when (lock-acquisition.status ,locked) (%unlock-recursive-lock-object ,l)))))))
+
+(defmacro with-lock-grabbed-maybe ((lock &optional
+					 (whostate "Lock"))
+				   &body body)
+  (declare (ignore whostate))
+  (let* ((l (gensym)))
+    `(with-lock-context
+      (let* ((,l ,lock))
+        (when (%try-recursive-lock-object ,l)
+          (unwind-protect
+               (progn ,@body)
+            (%unlock-recursive-lock-object ,l)))))))
+
+(defmacro with-standard-abort-handling (abort-message &body body)
+  (let ((stream (gensym)))
+    `(restart-case
+       (catch :abort
+         (catch-cancel
+           ,@body))
+       (abort () ,@(when abort-message
+                     `(:report (lambda (,stream)
+                                 (write-string ,abort-message ,stream)))))
+       (abort-break ()))))
+       
+
+
+
+(defmacro %lexpr-count (l)
+  `(%lisp-word-ref ,l 0))
+
+(defmacro %lexpr-ref (lexpr count i)
+  `(%lisp-word-ref ,lexpr (%i- ,count ,i)))
+
+;;; args will be list if old style clos
+(defmacro apply-with-method-context (magic function args)
+  (let ((m (gensym))
+        (f (gensym))
+        (as (gensym)))
+      `((lambda (,m ,f ,as)
+          (if (listp ,as)
+            (%apply-with-method-context ,m ,f ,as)
+            (%apply-lexpr-with-method-context ,m ,f ,as))) ,magic ,function ,args)))
+
+(defmacro defcallback (name arglist &body body &environment env)
+  "Proclaim name to be a special variable; sets its value to a MACPTR which,
+when called by foreign code, calls a lisp function which expects foreign
+arguments of the specified types and which returns a foreign value of the
+specified result type. Any argument variables which correspond to foreign
+arguments of type :ADDRESS are bound to stack-allocated MACPTRs.
+
+If name is already a callback function pointer, its value is not changed;
+instead, it's arranged that an updated version of the lisp callback function
+will be called. This feature allows for callback functions to be redefined
+incrementally, just like Lisp functions are.
+
+defcallback returns the callback pointer, e.g., the value of name."
+  (define-callback name arglist body env))
+
+(declare-arch-specific-macro %get-single-float-from-double-ptr)
+
+(declare-arch-specific-macro lfun-vector)
+(declare-arch-specific-macro lfun-vector-lfun)
+
+(declare-arch-specific-macro symptr->symvector)
+(declare-arch-specific-macro symvector->symptr)
+
+(declare-arch-specific-macro function-to-function-vector)
+(declare-arch-specific-macro function-vector-to-function)
+
+(declare-arch-specific-macro with-ffcall-results)
+
+(defvar *trace-print-functions* nil)
+(defun %trace-print-arg (stream arg val type)
+  (format stream " ")
+  (let ((fn (assoc type *trace-print-functions*)))
+    (if fn
+      (funcall (cdr fn) stream arg val)
+      (progn
+      (when arg
+        (format stream "~A = " arg))
+      (if (and type (not (eq type :void)))
+          (format stream "[:~A] ~A~%" type val)
+        (format stream ":VOID~%"))))))
+
+(defun def-trace-print-function (type fn)
+  (push (cons type fn) *trace-print-functions*))
+
+(defun define-callback (name args body env)
+  (let* ((stack-word (gensym))
+         (stack-ptr (gensym))
+         (fp-args-ptr (gensym))
+         (result-type-spec :void)
+         (args args)
+         (discard-stack-args nil)	;only meaningful on win32
+	 (discard-hidden-arg nil)	;only meaningful on x8632
+	 (info nil)
+         (woi nil)
+         (need-struct-arg)
+         (struct-return-arg-name)
+         (error-return nil))
+    (collect ((arg-names)
+              (arg-specs))
+      (let* ((spec (car (last args)))
+             (rtype (ignore-errors (parse-foreign-type spec))))
+        (setq need-struct-arg (typep rtype 'foreign-record-type))
+	(when need-struct-arg
+	  (setq discard-hidden-arg
+		(funcall (ftd-ff-call-struct-return-by-implicit-arg-function
+			  *target-ftd*) rtype)))
+        (if rtype
+          (setq result-type-spec spec args (butlast args))))
+      (loop
+        (when (null args) (return))
+        (if (eq (car args) :without-interrupts)
+          (setq woi (cadr args) args (cddr args))
+          (if (eq (car args) :discard-stack-args)
+            (setq discard-stack-args (eq (backend-target-os *target-backend*) :win32) args (cdr args))
+            (if (eq (car args) :error-return)
+              (setq error-return
+                    (cadr args)                  
+                    args (cddr args))
+              (if need-struct-arg
+                (setq struct-return-arg-name (pop args) need-struct-arg nil)
+                (progn
+                  (arg-specs (pop args))
+                  (arg-names (pop args))))))))
+      (multiple-value-bind (rlets lets dynamic-extent-names inits foreign-return-type fp-args-form error-return-offset num-arg-bytes)
+          (funcall (ftd-callback-bindings-function *target-ftd*)
+                   stack-ptr fp-args-ptr (arg-names) (arg-specs) result-type-spec struct-return-arg-name)
+	;; x8632 hair
+	(when discard-hidden-arg
+	  (if discard-stack-args
+	    ;; We already have to discard some number of args, so just
+	    ;; discard the extra hidden arg while we're at it.
+	    (incf num-arg-bytes 4)
+	    ;; Otherwise, indicate that we'll need to discard the
+	    ;; hidden arg.
+	    (setq info (ash 1 23))))
+	(when discard-stack-args
+	  (setq info 0)
+	  ;; put number of words to discard in high-order byte
+	  (setf (ldb (byte 8 24) info)
+		(ash num-arg-bytes (- target::word-shift))))
+        (multiple-value-bind (body decls doc) (parse-body body env t)
+          `(progn
+            (declaim (special ,name))
+            (define-callback-function
+                (nfunction ,name
+                 (lambda (,stack-word)
+                   (declare (ignorable ,stack-word))
+                   (block ,name
+                     (with-macptrs ((,stack-ptr))
+                       (%setf-macptr-to-object ,stack-ptr ,stack-word)
+                       (with-macptrs (,@(when fp-args-form
+                                              `((,fp-args-ptr ,fp-args-form))))
+                         ,(defcallback-body stack-ptr
+                                            fp-args-ptr
+                                            lets
+                                            rlets
+                                            inits
+                                            `(declare (dynamic-extent ,@dynamic-extent-names))
+                                            decls
+                                            body
+                                            foreign-return-type
+                                            struct-return-arg-name
+                                            error-return
+                                            error-return-offset
+                                            ))))))
+                ,doc
+              ,woi
+              ,info)))))))
+
+
+(defun defcallback-body (&rest args)
+  (declare (dynamic-extent args))
+  (destructuring-bind (stack-ptr fp-args-ptr lets rlets inits dynamic-extent-decls other-decls body return-type struct-return-arg error-return error-delta) args
+    (declare (ignorable dynamic-extent-decls))
+    (let* ((condition-name (if (atom error-return) 'error (car error-return)))
+           (error-return-function (if (atom error-return) error-return (cadr error-return)))
+           (result (if struct-return-arg (gensym)))
+           (body
+            `(rlet ,rlets
+              (let ,lets
+                ,dynamic-extent-decls
+                ,@other-decls
+                ,@inits
+                ,(if result
+                     `(let* ((,result ,@body))
+                       (declare (dynamic-extent ,result)
+                                (ignorable ,result))
+                       ,(funcall (ftd-callback-return-value-function *target-ftd*)
+                              stack-ptr
+                              fp-args-ptr
+                              result
+                              return-type
+                              struct-return-arg))
+                     (if (eq return-type *void-foreign-type*)
+                       `(progn ,@body)
+                       (funcall (ftd-callback-return-value-function *target-ftd*)
+                                stack-ptr
+                                fp-args-ptr
+                                `(progn ,@body)
+                                return-type
+                                struct-return-arg)))
+                nil))))
+      (if error-return
+        (let* ((cond (gensym))
+               (block (gensym))
+               (handler (gensym)))
+          `(block ,block
+            (let* ((,handler (lambda (,cond)
+                               (,error-return-function ,cond ,stack-ptr (%inc-ptr ,stack-ptr ,error-delta))
+                               (return-from ,block
+                                 nil))))
+              (declare (dynamic-extent ,handler))
+              (handler-bind ((,condition-name ,handler))
+                (values ,body)))))
+        body))))
+
+
+(defmacro define-toplevel-command (group-name name arglist &body body &environment env)
+  (let* ((key (make-keyword name)))
+    (multiple-value-bind (body decls doc) (parse-body body env)
+      `(%define-toplevel-command ',group-name ,key ',name 
+	(nfunction ,name (lambda ,arglist
+			   ,@decls
+			   (block ,name
+			     ,@body)))
+	,doc
+        ',(mapcar #'symbol-name arglist)))))
+
+(defmacro with-toplevel-commands (group-name &body body)
+  `(let* ((*active-toplevel-commands* *active-toplevel-commands*))
+    (progn
+      (%use-toplevel-commands ',group-name)
+      ,@body)))
+
+(defmacro assert (test-form &optional (places ()) string &rest args)
+  "ASSERT Test-Form [(Place*) [String Arg*]]
+  If the Test-Form is not true, then signal a correctable error.  If Places
+  are specified, then new values are prompted for when the error is proceeded.
+  String and Args are the format string and args to the error call."
+  (let* ((TOP (gensym))
+         (setf-places-p (not (null places))))
+    `(without-compiling-code-coverage
+      (tagbody
+       ,TOP
+       (unless ,test-form
+         (%assertion-failure ,setf-places-p ',test-form ,string ,@args)
+         ,@(if places
+             `((write-line "Type expressions to set places to, or nothing to leave them alone."
+                           *query-io*)
+               ,@(mapcar #'(lambda (place &aux (new-val (gensym))
+                                          (set-p (gensym)))
+                             `(multiple-value-bind
+                                (,new-val ,set-p)
+                                (assertion-value-prompt ',place)
+                                (when ,set-p (setf ,place (values-list ,new-val)))))
+                         places)))
+         (go ,TOP))))))
+
+
+(defmacro check-type (place typespec &optional string)
+  "CHECK-TYPE Place Typespec [String]
+  Signal a restartable error of type TYPE-ERROR if the value of PLACE is
+  not of the specified type. If an error is signalled and the restart is
+  used to return, this can only return if the STORE-VALUE restart is
+  invoked. In that case it will store into PLACE and start over."
+  (let* ((val (gensym)))
+    `(without-compiling-code-coverage
+      (do* ((,val ,place ,place))
+          ((typep ,val ',typespec))
+       (setf ,place (%check-type ,val ',typespec ',place ,string))))))
+
+
+
+
+(defmacro with-hash-table-iterator ((mname hash-table) &body body)
+  "WITH-HASH-TABLE-ITERATOR ((function hash-table) &body body)
+   provides a method of manually looping over the elements of a hash-table.
+   FUNCTION is bound to a generator-macro that, within the scope of the
+   invocation, returns one or three values. The first value tells whether
+   any objects remain in the hash table. When the first value is non-NIL,
+   the second and third values are the key and the value of the next object."
+  (let* ((hash (gensym))
+         (keys (gensym))
+         (values (gensym))
+         (count (gensym))
+         (state (gensym)))
+    `(let* ((,hash ,hash-table)
+            (,count (hash-table-count ,hash))
+            (,keys (make-array ,count))
+            (,values (make-array ,count))
+            (,state (vector ,hash 0 ,keys ,values (enumerate-hash-keys-and-values ,hash ,keys ,values))))
+      (declare (dynamic-extent ,keys ,state)
+               (fixnum ,count))
+      (macrolet ((,mname () `(next-hash-table-iteration-1 ,',state)))
+        ,@body))))
+
+
+(eval-when (compile load eval)
+(defmacro pprint-logical-block ((stream-symbol list
+				 &key (prefix "" prefixp)
+                                      (per-line-prefix "" per-line-prefix-p)
+				      (suffix "" suffixp))
+				&body body)
+  (cond ((eq stream-symbol nil) (setq stream-symbol '*standard-output*))
+	((eq stream-symbol T) (setq stream-symbol '*terminal-io*)))
+  (when (not (symbolp stream-symbol))
+    (warn "STREAM-SYMBOL arg ~S to PPRINT-LOGICAL-BLOCK is not a bindable symbol"
+	  stream-symbol)
+    (setq stream-symbol '*standard-output*))
+  (when (and prefixp per-line-prefix-p)
+    (warn "prefix ~S and per-line-prefix ~S cannot both be specified ~
+           in PPRINT-LOGICAL-BLOCK" prefix per-line-prefix)
+    (setq per-line-prefix nil))
+  `(let ((*logical-block-p* t))
+     (maybe-initiate-xp-printing
+      #'(lambda (,stream-symbol)
+          (let ((+l ,list)
+                (+p (or (and ,prefixp
+                             (require-type ,prefix 'string))
+                        (and ,per-line-prefix-p
+                             (require-type ,per-line-prefix 'string))))
+                (+s (require-type ,suffix 'string)))
+            (pprint-logical-block+
+                (,stream-symbol +l +p +s ,per-line-prefix-p T nil)
+              ,@ body nil)))
+      (decode-stream-arg ,stream-symbol))))
+
+
+;Assumes var and args must be variables.  Other arguments must be literals or variables.
+
+(defmacro pprint-logical-block+ ((var args prefix suffix per-line? circle-check? atsign?)
+				 &body body)
+  "Group some output into a logical block. STREAM-SYMBOL should be either a
+   stream, T (for *TERMINAL-IO*), or NIL (for *STANDARD-OUTPUT*). The printer
+   control variable *PRINT-LEVEL* is automatically handled."
+  (when (and circle-check? atsign?)
+    (setq circle-check? 'not-first-p))
+  `(let ((*current-level* (1+ *current-level*))
+	 (*current-length* -1)
+	 ;(*parents* *parents*)
+	 ,@(if (and circle-check? atsign?) `((not-first-p (plusp *current-length*)))))
+     (unless (check-block-abbreviation ,var ,args ,circle-check?)
+       (start-block ,var ,prefix ,per-line? ,suffix)
+       (when
+         (catch 'line-limit-abbreviation-exit
+           (block logical-block
+             (macrolet ((pprint-pop () `(pprint-pop+ ,',args ,',var))
+                        (pprint-exit-if-list-exhausted ()
+                          `(if (null ,',args) (return-from logical-block nil))))
+               ,@ body))
+           (end-block ,var ,suffix)
+           nil)
+         (end-block ,var ,suffix)
+         (throw 'line-limit-abbreviation-exit T)))))
+) ; eval-when
+
+(defmacro %old-class-local-shared-slotds (class &optional default)
+  (if default                           ; so setf works
+    `(%class-get ,class '%old-class-local-shared-slotds ,default)
+    `(%class-get ,class '%old-class-local-shared-slotds)))
+
+(defmacro with-slot-values (slot-entries instance-form &body body)
+; Simplified form of with-slots.  Expands into a let instead of a symbol-macrolet
+; Thus, you can access the slot values, but you can't setq them.
+  (let ((instance (gensym)) var slot-name bindings)
+    (dolist (slot-entry slot-entries)
+      (cond ((symbolp slot-entry)
+             (setq var slot-entry slot-name slot-entry))
+            ((and (listp slot-entry) (cdr slot-entry) (null (cddr slot-entry))
+                  (symbolp (car slot-entry)) (symbolp (cadr slot-entry)))
+             (setq var (car slot-entry) slot-name (cadr slot-entry)))
+            (t (signal-program-error "Malformed slot-entry: ~a to with-slot-values.~@
+                                      Should be a symbol or a list of two symbols."
+				     slot-entry)))
+      (push `(,var (slot-value ,instance ',slot-name)) bindings))
+    `(let ((,instance ,instance-form))
+       (let ,(nreverse bindings)
+         ,@body))))
+
+(defmacro with-slots (slot-entries instance-form &body body)
+  "Establish a lexical environment for referring to the slots in the
+instance named by the given slot-names as though they were variables.
+Within such a context the value of the slot can be specified by using
+its slot name, as if it were a lexically bound variable. Both setf and
+setq can be used to set the value of the slot."
+  (let ((instance (gensym)) var slot-name bindings)
+    (dolist (slot-entry slot-entries)
+      (cond ((symbolp slot-entry)
+             (setq var slot-entry slot-name slot-entry))
+            ((and (listp slot-entry) (cdr slot-entry) (null (cddr slot-entry))
+                  (symbolp (car slot-entry)) (symbolp (cadr slot-entry)))
+             (setq var (car slot-entry) slot-name (cadr slot-entry)))
+            (t (signal-program-error "Malformed slot-entry: ~a to with-slots.~@
+                                      Should be a symbol or a list of two symbols."
+				     slot-entry)))
+      (push `(,var (slot-value ,instance ',slot-name)) bindings))
+    `(let ((,instance ,instance-form))
+       ,@(if bindings 
+             (list `(declare (ignorable ,instance)))
+             (list `(declare (ignore ,instance))))
+       (symbol-macrolet ,(nreverse bindings)
+         ,@body))))
+
+(defmacro with-accessors (slot-entries instance-form &body body)
+  "Create a lexical environment in which the slots specified by slot-entry
+are lexically available through their accessors as if they were variables.
+The appropriate accessors are invoked to access the slots specified by
+slot-entry. Both setf and setq can be used to set the value of the slot."
+  (let ((instance (gensym)) var reader bindings)
+    (dolist (slot-entry slot-entries)
+      (cond ((and (listp slot-entry) (cdr slot-entry) (null (cddr slot-entry))
+                  (symbolp (car slot-entry)) (symbolp (cadr slot-entry)))
+             (setq var (car slot-entry) reader (cadr slot-entry)))
+            (t (signal-program-error "Malformed slot-entry: ~a to with-accessors.~@
+                                     Should be a list of two symbols."
+				     slot-entry)))
+      (push `(,var (,reader ,instance)) bindings))
+    `(let ((,instance ,instance-form))
+       ,@(if bindings 
+             (list `(declare (ignorable ,instance)))
+             (list `(declare (ignore ,instance))))
+       (symbol-macrolet ,(nreverse bindings)
+         ,@body))))
+
+; I wanted to call this ":method"
+(defmacro reference-method (gf &rest qualifiers-and-specializers)
+  (let ((qualifiers (butlast qualifiers-and-specializers))
+        (specializers (car (last qualifiers-and-specializers))))
+    (if (null specializers) (report-bad-arg qualifiers-and-specializers '(not null)))
+    `(find-method #',gf ',qualifiers (mapcar #'find-specializer ',specializers))))
+
+(defmacro time (form)
+  "Execute FORM and print timing information on *TRACE-OUTPUT*."
+  `(report-time ',form #'(lambda () (progn ,form))))
+
+(defmacro with-error-reentry-detection (&body body)
+  (let ((thunk (gensym)))
+    `(let ((,thunk #'(lambda () ,@body)))
+       (declare (dynamic-extent ,thunk))
+       (funcall-with-error-reentry-detection ,thunk))))
+
+(defmacro without-duplicate-definition-warnings (&body body)
+  `(compiler-let ((*compiler-warn-on-duplicate-definitions* nil))
+     ,@body))
+
+
+#+ppc-target
+(defmacro scan-for-instr (mask opcode fn pc-index &optional (tries *trap-lookup-tries*))
+  `(%scan-for-instr ,mask ,opcode ,fn ,pc-index ,tries))
+
+
+(declare-arch-specific-macro codevec-header-p)
+
+#+ppc-target
+(defmacro match-instr (instr mask bits-to-match)
+  `(eql (logand ,instr ,mask) ,bits-to-match))
+
+(defmacro with-xp-stack-frames ((xp trap-function &optional stack-frame) &body body)
+  (let ((thunk (gensym))
+        (sf (or stack-frame (gensym))))
+    `(let ((,thunk #'(lambda (&optional ,sf)
+                       ,@(unless stack-frame `((declare (ignore ,sf))))
+                       ,@body)))
+       (declare (dynamic-extent ,thunk))
+       (funcall-with-xp-stack-frames ,xp ,trap-function ,thunk))))
+
+(defmacro signal-eof-error (stream)
+  `(error 'end-of-file :stream ,stream))
+
+(defmacro check-eof (valform stream eof-error-p eof-value)
+  (let* ((val (gensym)))
+    `(let ((,val ,valform))
+      (if (eq ,val :eof)
+        (if ,eof-error-p
+          (signal-eof-error ,stream)
+          ,eof-value)
+        ,val))))
+
+(defmacro designated-input-stream (input-stream)
+  `(if ,input-stream
+    (if (eq t ,input-stream)
+      *terminal-io*
+      ,input-stream)
+    *standard-input*))
+
+(defmacro pref (pointer accessor)
+  "Reference an instance of a foreign type (or a component of a foreign
+type) accessible via ptr.
+
+Expand into code which references the indicated scalar type or component,
+or returns a pointer to a composite type."
+  (let* ((*target-ftd* (backend-target-foreign-type-data *target-backend*)))
+    (destructuring-bind (type-name &rest accessors) (decompose-record-accessor accessor)
+      (%foreign-access-form pointer (%foreign-type-or-record type-name) 0 accessors))))
+
+(defmacro paref (pointer type-name index)
+  (let* ((*target-ftd* (backend-target-foreign-type-data *target-backend*)))
+    (%foreign-array-access-form  pointer (%foreign-type-or-record type-name) index)))
+
+(defmacro rref (pointer accessor &key (storage :pointer storage-p))
+  (when storage-p
+    (warn "Use of :storage option ignored: ~a" storage))
+  `(pref ,pointer ,accessor))
+
+(defmacro rlet (spec &body body)
+  "Execute body in an environment in which each var is bound to a MACPTR
+encapsulating the address of a stack-allocated foreign memory block,
+allocated and initialized from typespec and initforms as per make-record.
+Return whatever value(s) body returns."
+  (let* ((*target-ftd* (backend-target-foreign-type-data *target-backend*)))
+    `(%stack-block ,(rlet-sizes spec)
+      ,@(rlet-inits spec)
+      ,@body)))
+
+(defmacro rletz (spec &body body)
+  "Execute body in an environment in which each var is bound to a MACPTR
+encapuslating the address of a stack-allocated foreign memory block,
+allocated and initialized from typespec and initforms as per make-record.
+Return whatever value(s) body returns.
+
+Unlike rlet, record fields that aren't explicitly initialized are set
+to binary 0."
+  (let* ((*target-ftd* (backend-target-foreign-type-data *target-backend*)))
+    `(%stack-block ,(rlet-sizes spec t)
+      ,@(rlet-inits spec)
+      ,@body)))
+
+(defun rlet-sizes (inits &optional clear-p &aux result)
+  (dolist (item inits (nreverse result))
+    (push `(,(car item)
+            ,(%foreign-type-or-record-size (cadr item) :bytes)
+            ,@(if clear-p '(:clear t)))
+          result)))
+
+(defun rlet-inits (inits &aux result)
+  (dolist (item inits result)
+    (let* ((name (car item))
+           (record-name (cadr item))
+           (inits (cddr item))
+           (ftype (%foreign-type-or-record record-name))
+           (ordinal (foreign-type-ordinal ftype))
+           (ordinal-form (if (< ordinal max-canonical-foreign-type-ordinal)
+                           ordinal
+                           `(foreign-type-ordinal (load-time-value (%foreign-type-or-record ',record-name))))))
+      (when (eq *host-backend* *target-backend*)
+        (setq result (nconc result `((%set-macptr-type ,name ,ordinal-form)))))
+      (if (typep ftype 'foreign-record-type)
+        (setq result
+              (nconc result (%foreign-record-field-forms name ftype record-name inits)))
+        (progn
+          (when inits
+            (if (and ftype (null (cdr inits)))
+              (setq result
+                    (nconc result
+                           `((setf ,(%foreign-access-form name ftype 0 nil)
+                              ,(car inits)))))
+              (signal-program-error "Unexpected or malformed initialization forms: ~s in field type: ~s"
+				    inits record-name))))))))
+
+(defun %foreign-record-field-forms (ptr record-type record-name inits)
+  (unless (evenp (length inits))
+    (signal-program-error "Unexpected or malformed initialization forms: ~s in field type: ~s"
+			  inits record-name))
+  (let* ((result ()))
+    (do* ()
+	 ((null inits)
+	  `((progn
+	      ;(%assert-macptr-ftype ,ptr ,record-type)
+	      ,@(nreverse result))))
+      (let* ((accessor (decompose-record-accessor (pop inits)))
+	     (valform (pop inits)))
+	(push `(setf ,(%foreign-access-form ptr record-type 0  accessor) ,valform)
+	      result)))))
+  
+(defmacro get-field-offset (accessor)
+  (destructuring-bind (type-name field-name) (decompose-record-accessor accessor)
+    (let* ((record-type (require-type (%foreign-type-or-record type-name) 'foreign-record-type))
+           (field (%find-foreign-record-type-field record-type field-name))
+           (bit-offset (foreign-record-field-offset field)))
+      `(values ,(floor bit-offset 8) ,(foreign-record-field-type field) ,bit-offset))))
+
+(defmacro record-length (recname)
+  (%foreign-type-or-record-size recname :bytes))
+
+(defun make-record-form (record-name allocator &rest initforms)
+  (let* ((ftype (%foreign-type-or-record record-name))
+         (ordinal (foreign-type-ordinal ftype))
+         (ordinal-form (if (< ordinal max-canonical-foreign-type-ordinal)
+                         ordinal
+                         `(foreign-type-ordinal (load-time-value (%foreign-type-or-record ',record-name)))))
+         (bits (ensure-foreign-type-bits ftype))
+	 (bytes (if bits
+		  (ceiling bits 8)
+		  (signal-program-error "Unknown size for foreign type ~S."
+					(unparse-foreign-type ftype))))
+	 (p (gensym))
+	 (memset (read-from-string "#_memset")))    
+    `(let* ((,p (,allocator ,bytes)))
+      ,@(when (eq *host-backend* *target-backend*)
+              `((%set-macptr-type ,p ,ordinal-form)))
+      (,memset ,p 0 ,bytes)
+      ,@(%foreign-record-field-forms p ftype record-name initforms)
+      ,p)))
+  
+(defmacro make-record (record-name &rest initforms)
+  "Expand into code which allocates and initalizes an instance of the type
+denoted by typespec, on the foreign heap. The record is allocated using the
+C function malloc, and the user of make-record must explicitly call the C
+function free to deallocate the record, when it is no longer needed."
+  (apply 'make-record-form record-name 'malloc initforms))
+
+(defmacro make-gcable-record (record-name &rest initforms)
+  "Like MAKE-RECORD, only advises the GC that the foreign memory can
+   be deallocated if the returned pointer becomes garbage."
+  (apply 'make-record-form record-name '%new-gcable-ptr initforms))
+
+(defmacro copy-record (type source dest)
+  (let* ((size (* (%foreign-type-or-record-size type :words) #+64-bit-target 1 #+32-bit-target 2))
+         (src (gensym "SRC"))
+         (dst (gensym "DST"))
+         (accessor #+64-bit-target '%get-unsigned-long #+32-bit-target '%get-unsigned-word)
+         (i (gensym "I"))
+         (j (gensym "J")))
+    `(with-macptrs ((,src ,source)
+                    (,dst ,dest))
+      (do* ((,i 0 (+ ,i #+64-bit-target 4 #+32-bit-target 2))
+            (,j 0 (+ ,j 1)))
+           ((= ,j ,size))
+        (declare (fixnum ,i))
+        (setf (,accessor ,dst ,i) (,accessor ,src ,i))))))
+
+(defmacro assert-pointer-type (pointer type)
+  "Assert that the pointer points to an instance of the specified foreign type.
+Return the pointer."
+  (let* ((ptr (gensym)))
+    `(let* ((,ptr ,pointer))
+      (%set-macptr-type ,ptr (foreign-type-ordinal (load-time-value (parse-foreign-type ',type))))
+      ,ptr)))
+
+    
+
+(defmacro with-terminal-input (&body body)
+  "Execute body in an environment with exclusive read access to the terminal."
+  (let* ((got-it (gensym)))
+    `(let* ((,got-it (%request-terminal-input)))
+      (unwind-protect
+	   (progn ,@body)
+	(%restore-terminal-input ,got-it)))))
+
+
+(defmacro with-process-whostate ((whostate) &body body)
+  `(let* ((*whostate* ,whostate))
+    ,@body))
+
+
+
+
+
+(defmacro with-read-lock ((lock) &body body)
+  "Wait until a given lock is available for read-only access, then evaluate
+its body with the lock held."
+  (let* ((p (gensym)))
+    `(with-lock-context
+      (let* ((,p ,lock))
+        (unwind-protect
+             (progn
+               (read-lock-rwlock ,p)
+               ,@body)
+          (unlock-rwlock ,p))))))
+
+
+(defmacro with-write-lock ((lock) &body body)
+  "Wait until the given lock is available for write access, then execute
+its body with the lock held."
+  (let* ((p (gensym)))
+    `(with-lock-context
+      (let* ((,p ,lock))
+      (unwind-protect
+           (progn
+             (write-lock-rwlock ,p)
+             ,@body)
+        (unlock-rwlock ,p))))))
+
+
+
+(defmacro without-gcing (&body body)
+  `(unwind-protect
+    (progn
+      (%lock-gc-lock)
+      ,@body)
+    (%unlock-gc-lock)))
+
+(defmacro with-deferred-gc (&body body)
+  "Execute BODY without responding to the signal used to suspend
+threads for GC.  BODY must be very careful not to do anything which
+could cause an exception (note that attempting to allocate lisp memory
+may cause an exception.)"
+  `(let* ((*interrupt-level* -2))
+    ,@body))
+
+(defmacro allowing-deferred-gc (&body body)
+  "Within the extent of a surrounding WITH-DEFERRED-GC, allow GC."
+  `(let* ((*interrupt-level* -1))
+    (%check-deferred-gc)
+    ,@body))
+
+(defmacro defer-gc ()
+  `(setq *interrupt-level* -2))
+
+
+(defmacro with-pointer-to-ivector ((ptr ivector) &body body)
+  "Executes BODY with PTR bound to a pointer to the first byte of data
+in IVECTOR.  The GC is disabled during execution of BODY; PTR has
+has dynamic-extent (and the address it references may become invalid
+after the BODY exits.)  IVECTOR should be a (SIMPLE-ARRAY (*)) whose
+element-type is numeric."
+  (let* ((v (gensym)))
+    `(let* ((,v ,ivector))
+       (unless (typep ,v 'ivector) (report-bad-arg ,v 'ivector))
+       (without-gcing
+         (with-macptrs ((,ptr))
+           (%vect-data-to-macptr ,v ,ptr)
+           ,@body)))))
+      
+
+
+(defmacro with-other-threads-suspended (&body body)
+  `(unwind-protect
+    (progn
+      (%suspend-other-threads)
+      ,@body)
+    (%resume-other-threads)))
+
+(defmacro with-package-read-lock ((p) &body body)
+  `(with-read-lock ((pkg.lock ,p)) ,@body))
+
+(defmacro with-package-write-lock ((p) &body body)
+  `(with-write-lock ((pkg.lock ,p)) ,@body))
+
+(defmacro with-package-lock ((p) &body body)
+  `(with-package-write-lock (,p) ,@body))
+
+;;; Lock %all-packages-lock%, for shared read access to %all-packages%
+
+(defmacro with-package-list-read-lock (&body body)
+  `(with-read-lock (%all-packages-lock%) ,@body))
+
+;;; Lock %all-packages-lock%, to allow modification to %all-packages%
+(defmacro with-package-list-write-lock (&body body)
+  `(with-write-lock (%all-packages-lock%) ,@body))
+
+(defmacro atomic-incf-decf (place delta &environment env)
+  (setq place (macroexpand place env))
+  (if (consp place)
+    (let* ((sym (car place))
+	   (struct-transform (or (environment-structref-info sym env)
+                                 (gethash sym %structure-refs%))))
+      (if struct-transform
+        (setq place (defstruct-ref-transform struct-transform (cdr place) env)
+              sym (car place)))
+      (ecase sym
+	(the `(the ,(cadr place) (atomic-incf-decf ,(caddr place) ,delta)))
+         ;; Needed so can handle %svref (which macroexpands into a LET*)
+         ((let let*) (multiple-value-bind (body decls) (parse-body (cddr place) env t)
+                       (unless (eql (length body) 1)
+                         (error "~S is not a valid atomic-incf/decf place" place))
+                       `(,sym ,(cadr place) ,@decls (atomic-incf-decf ,@body ,delta))))
+         ;; Ditto
+         (locally (multiple-value-bind (body decls) (parse-body (cdr place) env t)
+                    (unless (eql (length body) 1)
+                      (error "~S is not a valid atomic-incf/decf place" place))
+                    `(,sym ,@decls (atomic-incf-decf ,@body ,delta))))
+	(car `(%atomic-incf-car ,(cadr place) ,delta))
+	(cdr `(%atomic-incf-cdr ,(cadr place) ,delta))
+	(svref `(%atomic-incf-gvector ,@(cdr place) ,delta))))
+    (if (and (symbolp place) (eq :special (variable-information place env)))
+      (let* ((base (gensym))
+             (offset (gensym)))
+        `(multiple-value-bind (,base ,offset)
+          (%symbol-binding-address ',place)
+          (%atomic-incf-node ,delta ,base ,offset)))
+      (signal-program-error "~S is not a special variable"  place))))
+    
+(defmacro atomic-incf (place)
+  `(atomic-incf-decf ,place 1))
+
+(defmacro atomic-decf (place)
+  `(atomic-incf-decf ,place -1))
+
+; Some of these macros were stolen from CMUCL.  Sort of ...
+
+(defmacro iterate (name binds &body body)
+  "Iterate Name ({(Var Initial-Value)}*) Declaration* Form*
+  This is syntactic sugar for Labels.  It creates a local function Name with
+  the specified Vars as its arguments and the Declarations and Forms as its
+  body.  This function is then called with the Initial-Values, and the result
+  of the call is return from the macro."
+  (dolist (x binds)
+    (unless (and (listp x)
+                 (= (length x) 2))
+      (signal-program-error "Malformed iterate variable spec: ~S." x)))
+
+  `(labels ((,name ,(mapcar #'first binds) ,@body))
+     (,name ,@(mapcar #'second binds))))
+
+;;;; The Collect macro:
+
+;;; Collect-Normal-Expander  --  Internal
+;;;
+;;;    This function does the real work of macroexpansion for normal collection
+;;; macros.  N-Value is the name of the variable which holds the current
+;;; value.  Fun is the function which does collection.  Forms is the list of
+;;; forms whose values we are supposed to collect.
+;;;
+(eval-when (:compile-toplevel :load-toplevel :execute)
+
+
+(defun collect-normal-expander (n-value fun forms)
+  `(progn
+     ,@(mapcar #'(lambda (form) `(setq ,n-value (,fun ,form ,n-value))) forms)
+     ,n-value))
+
+
+)
+
+(defmacro once-only (specs &body body)
+  "Once-Only ({(Var Value-Expression)}*) Form*
+  Create a Let* which evaluates each Value-Expression, binding a temporary
+  variable to the result, and wrapping the Let* around the result of the
+  evaluation of Body.  Within the body, each Var is bound to the corresponding
+  temporary variable."
+  (iterate frob
+           ((specs specs)
+            (body body))
+    (if (null specs)
+      `(progn ,@body)
+      (let ((spec (first specs)))
+        (when (/= (length spec) 2)
+          (signal-program-error "Malformed ~s binding spec: ~S." 'once-only spec))
+        (let ((name (first spec))
+              (exp-temp (gensym)))
+          `(let ((,exp-temp ,(second spec))
+                 (,name (gensym)))
+             `(let ((,,name ,,exp-temp))
+                ,,(frob (rest specs) body))))))))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defun form-symbol (first &rest others)
+  (intern (apply #'concatenate 'simple-base-string (string first) (mapcar #'string others))))
+)
+
+
+;;; Collect-List-Expander  --  Internal
+;;;
+;;;    This function deals with the list collection case.  N-Tail is the pointer
+;;; to the current tail of the list, which is NIL if the list is empty.
+;;;
+(defun collect-list-expander (n-value n-tail forms)
+  (let ((n-res (gensym)))
+    `(progn
+       ,@(mapcar #'(lambda (form)
+                     `(let ((,n-res (cons ,form nil)))
+                        (cond (,n-tail
+                               (setf (cdr ,n-tail) ,n-res)
+                               (setq ,n-tail ,n-res))
+                              (t
+                               (setq ,n-tail ,n-res  ,n-value ,n-res)))))
+                 forms)
+       ,n-value)))
+
+;;;
+;;;    The ultimate collection macro...
+;;;
+
+(defmacro collect (collections &body body)
+  "Collect ({(Name [Initial-Value] [Function])}*) {Form}*
+  Collect some values somehow.  Each of the collections specifies a bunch of
+  things which collected during the evaluation of the body of the form.  The
+  name of the collection is used to define a local macro, a la MACROLET.
+  Within the body, this macro will evaluate each of its arguments and collect
+  the result, returning the current value after the collection is done.  The
+  body is evaluated as a PROGN; to get the final values when you are done, just
+  call the collection macro with no arguments.
+
+  Initial-Value is the value that the collection starts out with, which
+  defaults to NIL.  Function is the function which does the collection.  It is
+  a function which will accept two arguments: the value to be collected and the
+  current collection.  The result of the function is made the new value for the
+  collection.  As a totally magical special-case, the Function may be Collect,
+  which tells us to build a list in forward order; this is the default.  If an
+  Initial-Value is supplied for Collect, the stuff will be rplacd'd onto the
+  end.  Note that Function may be anything that can appear in the functional
+  position, including macros and lambdas."
+  
+  
+  (let ((macros ())
+        (binds ()))
+    (dolist (spec collections)
+      (unless (<= 1 (length spec) 3)
+        (signal-program-error "Malformed collection specifier: ~S." spec))
+      (let ((n-value (gensym))
+            (name (first spec))
+            (default (second spec))
+            (kind (or (third spec) 'collect)))
+        
+        (push `(,n-value ,default) binds)
+        (if (eq kind 'collect)
+          (let ((n-tail (gensym)))
+            (if default
+              (push `(,n-tail (last ,n-value)) binds)
+              (push n-tail binds))
+            (push `(,name (&rest args)
+                          (collect-list-expander ',n-value ',n-tail args))
+                  macros))
+          (push `(,name (&rest args)
+                        (collect-normal-expander ',n-value ',kind args))
+                macros))))
+    `(macrolet ,macros (let* ,(nreverse binds) (declare (ignorable ,@binds)) ,@body))))
+
+
+;;; DEFENUM -- Internal Interface.
+;;;
+(defmacro defenum ((&key (prefix "") (suffix "") (start 0) (step 1))
+                   &rest identifiers)
+  (let ((results nil)
+        (index 0)
+        (start (eval start))
+        (step (eval step)))
+    (dolist (id identifiers)
+      (multiple-value-bind
+        (root docs)
+        (if (consp id)
+          (values (car id) (cdr id))
+          (values id nil))
+        (push `(defconstant ,(intern (concatenate 'simple-base-string
+                                                  (string prefix)
+                                                  (string root)
+                                                  (string suffix)))
+                 ,(+ start (* step index))
+                 ,@docs)
+              results))
+      (incf index))
+    `(eval-when (:compile-toplevel :load-toplevel :execute)
+       ,@(nreverse results))))
+
+
+;;; This does something like special binding, but the "bindings" established
+;;; aren't thread-specific.
+
+(defmacro let-globally ((&rest vars) &body body &environment env)
+  (multiple-value-bind (body decls) (parse-body body env)
+    (let* ((initforms nil)
+           (psetform nil)
+           (specvars nil)
+           (restoreform nil))
+      (flet ((pair-name-value (p)
+               (if (atom p)
+                 (values (require-global-symbol p env) nil)
+                 (if (and (consp (%cdr p)) (null (%cddr p)))
+                   (values (require-global-symbol (%car p) env) (%cadr p))
+                   (signal-program-error "Invalid variable initialization form : ~s")))))
+        (declare (inline pair-name-value))
+        (dolist (v vars)
+          (let* ((oldval (gensym))
+                 (newval (gensym)))
+            (multiple-value-bind (var valueform) (pair-name-value v)
+              (push var specvars)
+              (push var restoreform)
+              (push oldval restoreform)
+              (push `(,oldval (uvref (symptr->symvector ',var) #.target::symbol.vcell-cell)) initforms)
+              (push `(,newval ,valueform) initforms)
+              (push var psetform)
+              (push newval psetform))))
+        `(let ,(nreverse initforms)
+           ,@decls
+           (locally (declare (special ,@(nreverse specvars)))
+             (unwind-protect
+               (progn (psetq ,@(nreverse psetform)) ,@body)
+               (psetq ,@(nreverse restoreform)))))))))
+;;; From CLX.
+
+;;; The good news is that this uses an interlocked load/store sequence
+;;; and is fairly efficient.
+;;; The bad news is that it only handles a few types of "place" forms.
+;;; The good news is that CLX only uses a few types of "place" forms.
+
+(defmacro conditional-store (place old-value new-value &environment env)
+  (setq place (macroexpand place env))
+  (if (atom place)
+    ;; CLX uses special variables' value cells as place forms.
+    (if (and (symbolp place)
+             (eq :special (ccl::variable-information place env)))
+      (let* ((base (gensym))
+             (offset (gensym)))
+        `(multiple-value-bind (,base ,offset)
+          (ccl::%symbol-binding-address ',place)
+          (ccl::%store-node-conditional ,offset ,base ,old-value ,new-value)))
+      (signal-program-error "~s is not a special variable ." place))
+    (let* ((sym (car place))
+           (struct-transform (or (ccl::environment-structref-info sym env)
+                                 (gethash sym ccl::%structure-refs%))))
+      (if struct-transform
+        (setq place (defstruct-ref-transform struct-transform (cdr place) env)
+              sym (car place)))
+      (if (member  sym '(svref ccl::%svref ccl::struct-ref))
+        (let* ((v (gensym)))
+          `(let* ((,v ,(cadr place)))
+            (ccl::store-gvector-conditional ,(caddr place)
+             ,v ,old-value ,new-value)))
+        (signal-program-error "Don't know how to do conditional store to ~s" place)))))
+
+(defmacro step (form)
+  "The form is evaluated with single stepping enabled. Function calls
+outside the lexical scope of the form can be stepped into only if the
+functions in question have been compiled with sufficient DEBUG policy
+to be at least partially steppable."
+  form)
+
+(defmacro target-arch-case (&rest clauses)
+  `(case (backend-target-arch-name *target-backend*)
+    ,@clauses))
+
+(defmacro target-os-case (&rest clauses)
+  `(ecase (backend-target-os *target-backend*)
+    ,@clauses))
+
+(defmacro target-word-size-case (&rest clauses)
+  `(ecase (arch::target-nbits-in-word (backend-target-arch *target-backend*))
+    ,@clauses))
+
+(defmacro %get-natural (&body body)
+  "A free copy of the next OpenMCL release to anyone who remembers Flakey Foont"
+  (target-word-size-case
+   (32 `(%get-unsigned-long ,@body))
+   (64 `(%%get-unsigned-longlong ,@body))))
+
+(defmacro %get-signed-natural (&body body)
+  "And that's my final offer."
+  (target-word-size-case
+   (32 `(%get-signed-long ,@body))
+   (64 `(%%get-signed-longlong ,@body))))
+
+(declare-arch-specific-macro %target-kernel-global)
+
+;;; This behaves like a function, but looks up the kernel global
+;;; at compile time if possible. Probably should be done as a function
+;;; and a compiler macro, but we can't define compiler macros yet,
+;;; and I don't want to add it to "ccl:compiler;optimizers.lisp"
+(declare-arch-specific-macro %get-kernel-global)
+
+(declare-arch-specific-macro %get-kernel-global-ptr)
+
+(declare-arch-specific-macro area-code)
+
+(declare-arch-specific-macro nth-immediate)
+
+(declare-arch-specific-macro set-nth-immediate)
+
+(defsetf nth-immediate set-nth-immediate)
+
+(defmacro do-consing-areas ((area) &body body)
+  (let ((code (gensym)))
+  `(do-gc-areas (,area)
+     (let ((,code (%fixnum-ref ,area  (area-code))))
+       (when (or (eql ,code area-readonly)
+		 (eql ,code area-watched)
+                 (eql ,code area-managed-static)
+                 (eql ,code area-static)
+                 (eql ,code area-dynamic))
+         ,@body)))))
+
+(declare-arch-specific-macro area-succ)
+
+
+(defmacro do-gc-areas ((area) &body body)
+  (let ((initial-area (gensym)))
+    `(let* ((,initial-area (%get-kernel-global 'all-areas))
+            (,area ,initial-area))
+       (declare (fixnum ,initial-area ,area))
+       (loop
+         (setq ,area (%fixnum-ref ,area (area-succ)))
+         (when (eql ,area ,initial-area)
+           (return))
+         ,@body))))
+
+(defmacro with-ioblock-input-lock-grabbed ((ioblock) &body body)
+  (let* ((i (gensym)))
+    `(let* ((,i ,ioblock))
+      (with-lock-grabbed ((ioblock-inbuf-lock ,i))
+        (cond ((ioblock-device ,i)
+               ,@body)
+              (t (stream-is-closed (ioblock-stream ,i))))))))
+
+(defmacro with-ioblock-output-lock-grabbed ((ioblock) &body body)
+  (let* ((i (gensym)))
+    `(let* ((,i ,ioblock))
+      (with-lock-grabbed ((ioblock-outbuf-lock ,i))
+        (cond ((ioblock-device ,i)
+               ,@body)
+              (t (stream-is-closed (ioblock-stream ,i))))))))
+  
+
+(defmacro with-stream-ioblock-input ((ioblock stream &key
+                                             speedy)
+                                  &body body)
+  `(let ((,ioblock (stream-ioblock ,stream t)))
+     ,@(when speedy `((declare (optimize (speed 3) (safety 0)))))
+     (with-ioblock-input-locked (,ioblock) ,@body)))
+
+(defmacro with-stream-ioblock-output ((ioblock stream &key
+                                             speedy)
+                                  &body body)
+  `(let ((,ioblock (stream-ioblock ,stream t)))
+     ,@(when speedy `((declare (optimize (speed 3) (safety 0)))))
+     (with-ioblock-output-locked (,ioblock) ,@body)))
+
+(defmacro with-stream-ioblock-output-maybe ((ioblock stream &key
+						     speedy)
+					    &body body)
+  `(let ((,ioblock (stream-ioblock ,stream t)))
+    ,@(when speedy `((declare (optimize (speed 3) (safety 0)))))
+    (with-ioblock-output-locked-maybe (,ioblock) ,@body)))
+
+(defmacro with-ioblock-input-locked ((ioblock) &body body)
+  (let* ((lock (gensym)))
+    `(let* ((,lock (locally (declare (optimize (speed 3) (safety 0)))
+                                  (ioblock-inbuf-lock ,ioblock))))
+      (if ,lock
+        (with-lock-grabbed (,lock)
+          (cond ((ioblock-device ,ioblock)
+                 ,@body)
+                (t (stream-is-closed (ioblock-stream ,ioblock)))))
+        (progn
+          (check-ioblock-owner ,ioblock)
+          ,@body)))))
+
+(defmacro with-ioblock-output-locked ((ioblock) &body body)
+  (let* ((lock (gensym)))
+    `(let* ((,lock (locally (declare (optimize (speed 3) (safety 0)))
+                                  (ioblock-outbuf-lock ,ioblock))))
+      (if ,lock
+        (with-lock-grabbed (,lock)
+          (cond ((ioblock-device ,ioblock)
+                 ,@body)
+                (t (stream-is-closed (ioblock-stream ,ioblock)))))
+        (progn
+          (check-ioblock-owner ,ioblock)
+          ,@body)))))
+
+
+
+(defmacro with-ioblock-output-locked-maybe ((ioblock) &body body)
+  (let* ((lock (gensym)))
+    `(let* ((,lock (locally (declare (optimize (speed 3) (safety 0)))
+                     (ioblock-outbuf-lock ,ioblock))))
+      (if ,lock
+        (with-lock-grabbed (,lock)
+          (cond ((ioblock-device ,ioblock)
+                 ,@body)
+                (t (stream-is-closed (ioblock-stream ,ioblock)))))
+        (progn
+          (check-ioblock-owner ,ioblock)
+          ,@body)))))
+
+;;; Use this when it's possible that the fd might be in
+;;; a non-blocking state.  Body must return a negative of
+;;; the os error number on failure.
+;;; The use of READ-FROM-STRING below is certainly ugly, but macros
+;;; that expand into reader-macros don't generally trigger the reader-macro's
+;;; side-effects.  (Besides, the reader-macro might return a different
+;;; value when the macro function is expanded than it did when the macro
+;;; function was defined; this can happen during cross-compilation.)
+(defmacro with-eagain (fd direction &body body)
+  (let* ((res (gensym))
+	 (eagain (symbol-value (read-from-string "#$EAGAIN"))))
+   `(loop
+      (let ((,res (progn ,@body)))
+	(if (eql ,res (- ,eagain))
+          (progn
+            (setq ,res
+                  (,(ecase direction
+                           (:input 'process-input-would-block)
+                           (:output 'process-output-would-block))
+                    ,fd))
+            (unless (eq ,res t) (return ,res)))
+	  (return ,res))))))
+
+(defmacro ignoring-eintr (&body body)
+  (let* ((res (gensym))
+         (eintr (symbol-value (read-from-string "#$EINTR"))))
+    `(loop
+       (let* ((,res (progn ,@body)))
+         (unless (eql ,res (- ,eintr))
+           (return ,res))))))
+
+(defmacro ff-call-ignoring-eintr (&body body)
+  (let* ((res (gensym))
+         (eintr (symbol-value (read-from-string "#$EINTR"))))
+    `(loop
+       (let* ((,res (progn ,@body)))
+         (declare (fixnum ,res))
+         (when (< ,res 0)
+           (setq ,res (%get-errno)))
+         (unless (eql ,res (- ,eintr))
+           (return ,res))))))
+
+(defmacro basic-stream-ioblock (s)
+  `(or (basic-stream.state ,s)
+    (stream-is-closed ,s)))
+
+(defsetf interrupt-level set-interrupt-level)
+
+(defmacro %swap-u16 (val)
+  (let* ((arg (gensym)))
+    `(let* ((,arg ,val))
+      (declare (type (unsigned-byte 16) ,arg))
+      (logand #xffff (the fixnum (logior (the fixnum (ash ,arg -8))
+                                         (the fixnum (ash ,arg 8))))))))
+
+(defmacro %swap-u32 (val)
+  (let* ((arg (gensym)))
+    `(let ((,arg ,val))
+      (declare (type (unsigned-byte 32) ,arg))
+      (the (unsigned-byte 32) (logior (the (unsigned-byte 32)
+                                        (ash (logand #xff ,arg) 24))
+                                      (the (unsigned-byte 24)
+                                        (logior
+                                         (the (unsigned-byte 24) (ash (logand #xff00 ,arg) 8))
+                                         (the (unsigned-byte 16)
+                                           (logior
+                                            (the (unsigned-byte 16) (ash (logand #xff0000 ,arg) -8))
+                                            (the (unsigned-byte 8) (ash ,arg -24)))))))))))
+    
+
+(defmacro multiple-value-bind (varlist values-form &body body &environment env)
+  (multiple-value-bind (body decls)
+                       (parse-body body env)
+    (let ((ignore (make-symbol "IGNORE")))
+      `(multiple-value-call #'(lambda (&optional ,@varlist &rest ,ignore)
+                                (declare (ignore ,ignore))
+                                ,@decls
+                                ,@body)
+                            ,values-form))))
+
+(defmacro multiple-value-setq (vars val)
+  (if vars
+    `(values (setf (values ,@(mapcar #'(lambda (s) (require-type s 'symbol)) vars))  ,val))
+    `(prog1 ,val)))
+
+(defmacro nth-value (n form)
+  "Evaluate FORM and return the Nth value (zero based). This involves no
+  consing when N is a trivial constant integer."
+  `(car (nthcdr ,n (multiple-value-list ,form))))
+
+
+
+(defmacro with-input-timeout (((stream-var &optional (stream-form stream-var)) timeout) &body body)
+  "Execute body with STREAM-VAR bound to STREAM-FORM and with that stream's
+stream-input-timeout set to TIMEOUT."
+  (let* ((old-input-timeout (gensym))
+         (stream (gensym)))
+    `(let* ((,stream ,stream-form)
+            (,stream-var ,stream)
+            (,old-input-timeout (stream-input-timeout ,stream)))
+      (unwind-protect
+           (progn
+             (setf (stream-input-timeout ,stream) ,timeout)
+             ,@body)
+        (setf (stream-input-timeout ,stream) ,old-input-timeout)))))
+
+(defmacro with-output-timeout (((stream-var &optional (stream-form stream-var)) timeout) &body body)
+  "Execute body with STREAM-VAR bound to STREAM-FORM and with that stream's
+stream-output-timeout set to TIMEOUT."
+  (let* ((old-output-timeout (gensym))
+         (stream (gensym)))
+    `(let* ((,stream ,stream-form)
+            (,stream-var ,stream)
+            (,old-output-timeout (stream-output-timeout ,stream)))
+      (unwind-protect
+           (progn
+             (setf (stream-output-timeout ,stream) ,timeout)
+             ,@body)
+        (setf (stream-output-timeout ,stream) ,old-output-timeout)))))
+
+;;; FORM returns a signed integer.  If it's non-negative, return that
+;;; value, otherwise, return the (negative) errnor value returned by
+;;; %GET-ERRNO
+(defmacro int-errno-call (form)
+  (let* ((value (gensym)))
+    `(let* ((,value ,form))
+      (if (< ,value 0)
+        (%get-errno)
+        ,value))))
+
+(defmacro int-errno-ffcall (entry &rest args)
+  `(int-errno-call (ff-call ,entry ,@args)))
Index: /branches/new-random/lib/mcl-compat.lisp
===================================================================
--- /branches/new-random/lib/mcl-compat.lisp	(revision 13309)
+++ /branches/new-random/lib/mcl-compat.lisp	(revision 13309)
@@ -0,0 +1,48 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; mcl-compat.lisp - (some) backwards-compatibility with traditional MCL
+;;;  (CLtL2/ANSI, etc.)
+
+;;;  Gratuitous name changes, for the most part:
+
+(deftype base-character () 'base-char)
+(deftype extended-character () 'extended-char)
+
+(defmacro define-setf-method (access-fn lambda-list &body body)
+  `(define-setf-expander ,access-fn ,lambda-list ,@body))
+
+(defun get-setf-method (form &optional environment)
+  (get-setf-expansion-aux form environment nil))
+
+(defun get-setf-method-multiple-value (form &optional environment)
+  "Like Get-Setf-Method, but may return multiple new-value variables."
+  (get-setf-expansion-aux form environment t))
+
+;;; Traditional MCL I/O primitives:
+
+(defun tyi (stream)
+  (let* ((ch (stream-read-char stream)))
+    (unless (eq ch :eof) ch)))
+
+(defun untyi (ch &optional stream)
+  (stream-unread-char (designated-input-stream stream) ch))
+
+(defun tyo (ch &optional stream)
+  (stream-write-char (real-print-stream stream) ch))
Index: /branches/new-random/lib/method-combination.lisp
===================================================================
--- /branches/new-random/lib/method-combination.lisp	(revision 13309)
+++ /branches/new-random/lib/method-combination.lisp	(revision 13309)
@@ -0,0 +1,784 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;;;;;;;;;;;;;;;
+;;
+;; define-method-combination.lisp
+;; Copyright 1990-1994, Apple Computer, Inc.
+;; Copyright 1995-1996 Digitool, Inc.
+
+;;
+
+;;;;;;;;;;;;;;;
+;
+; Change History
+;
+; 05/31/96 bill list method combination is not :identity-with-one-argument
+; ------------- MCL-PPC 3.9
+; 12/01/93 bill specifier-match-p uses EQUAL instead of EQ
+; ------------- 3.0d13
+; 04/30/93 bill no-applicable-primary-method -> make-no-applicable-method-function
+; ------------  2.0
+; 11/05/91 gb   experiment with INLINE.
+; 09/26/91 bill %badarg had the wrong number of args in with-call-method-context.
+;               Mix in Flavors Technology's optimization.
+; 07/21/91 gb   Use DYNAMIC-EXTENT vice DOWNWARD-FUNCTION.
+; 06/26/91 bill method-combination's direct-superclass is metaobject
+;-------------- 2.0b2
+; 02/13/91 bill New File.
+;------------ 2.0b1
+;
+
+; MOP functions pertaining to method-combination:
+;
+; COMPUTE-DISCRIMINATING-FUNCTION generic-function (not implemented)
+; COMPUTE-EFFECTIVE-METHOD generic-function method-combination methods
+; FIND-METHOD-COMBINATION generic-function method-combination-type method-combination-options
+; Readers for method-combination objects
+; METHOD-COMBINATION-NAME
+; METHOD-COMBINATION-OPTIONS
+; METHOD-COMBINATION-ORDER
+; METHOD-COMBINATION-OPERATOR
+; METHOD-COMBINATION-IDENTITY-WITH-ONE-ARGUMENT
+
+(in-package "CCL")
+
+(defclass method-combination (metaobject)
+  ((name :reader method-combination-name :initarg :name)
+   (options :reader method-combination-options :initarg :options :initform nil)))
+
+(defclass short-method-combination (method-combination) 
+  ((operator :reader method-combination-operator :initarg :operator :initform nil)
+   (identity-with-one-argument :reader method-combination-identity-with-one-argument
+                               :initarg :identity-with-one-argument
+                               :initform nil))
+  (:documentation "Generated by the simple form of define-method-combination"))
+
+(defclass long-method-combination (method-combination)
+  ((expander :reader method-combination-expander :initarg :expander
+             :documentation "The expander is called by compute-effective-method with args: gf mc options methods args")
+   )
+  (:documentation "Generated by the long form of define-method-combination"))
+
+(defmethod print-object ((object method-combination) stream)
+  (print-unreadable-object (object stream :type t)
+    (let* ((name (method-combination-name object))
+           (options (method-combination-options object)))
+      (declare (dynamic-extent options))
+      (prin1 name stream)
+      (dolist (option options)
+        (pp-space stream)
+        (prin1 option stream)))))
+
+; Hash a method-combination name to a method-combination-info vector
+(defvar *method-combination-info* (make-hash-table :test 'eq))
+
+(defmacro method-combination-info (method-combination-type)
+  `(gethash ,method-combination-type *method-combination-info*))
+
+;;; Need to special case (find-method-combination #'find-method-combination ...)
+(without-duplicate-definition-warnings ;; override version in l1-clos-boot.lisp
+ (defmethod find-method-combination ((generic-function standard-generic-function)
+                                     method-combination-type
+                                     method-combination-options)
+   (%find-method-combination
+    generic-function method-combination-type method-combination-options)))
+
+(defun %find-method-combination (gf type options)
+  (declare (ignore gf))
+  (if (eq type 'standard)
+    (progn
+      (unless (null options)
+        (error "STANDARD method-combination accepts no options."))
+      *standard-method-combination*)
+    (let ((mci (method-combination-info type)))
+      (unless mci
+        (error "~s is not a method-combination type" type))
+      (labels ((same-options-p (o1 o2)
+                 (cond ((null o1) (null o2))
+                       ((null o2) nil)
+                       ((or (atom o1) (atom o2)) nil)
+                       ((eq (car o1) (car o2)) 
+                        (same-options-p (cdr o1) (cdr o2)))
+                       (t nil))))
+        (dolist (mc (population-data (mci.instances mci)))
+          (when (same-options-p options (method-combination-options mc))
+            (return-from %find-method-combination mc))))
+      (let ((new-mc 
+             (case (mci.class mci)
+               (short-method-combination
+                (unless (or (null options)
+                            (and (listp options)
+                                 (null (cdr options))
+                                 (memq (car options)
+                                       '(:most-specific-first :most-specific-last))))
+                  (error "Illegal method-combination options: ~s" options))
+                (destructuring-bind (&key identity-with-one-argument
+                                          (operator type)
+                                          &allow-other-keys)
+                                    (mci.options mci)
+                  (make-instance 'short-method-combination
+                                 :name type
+                                 :identity-with-one-argument identity-with-one-argument
+                                 :operator operator
+                                 :options options)))
+               (long-method-combination
+                (make-instance 'long-method-combination
+                               :name type
+                               :options options
+                               :expander (mci.options mci)))
+               (t (error "Don't understand ~s method-combination" type)))))
+        (push new-mc (population-data (mci.instances mci)))
+        new-mc))))
+    
+; Push GF on the MCI.GFS population of its method-combination type.
+(defun register-gf-method-combination (gf &optional (mc (%gf-method-combination gf)))
+  (unless (eq mc *standard-method-combination*)
+    (let* ((name (method-combination-name mc))
+           (mci (or (method-combination-info name)
+                    (error "~s not a known method-combination type" name)))
+           (gfs (mci.gfs mci)))
+      (pushnew gf (population-data gfs)))
+    mc))
+
+(defun unregister-gf-method-combination (gf &optional (mc (%gf-method-combination gf)))
+  (unless (eq mc *standard-method-combination*)
+    (let* ((name (method-combination-name mc))
+           (mci (or (method-combination-info name)
+                    (error "~s not a known method-combination type" name)))
+           (gfs (mci.gfs mci)))
+      (setf (population-data gfs) (delq gf (population-data gfs))))
+    mc))
+
+
+;;; Need to special case (compute-effective-method #'compute-effective-method ...)
+(defmethod compute-effective-method ((generic-function standard-generic-function)
+                                     (method-combination standard-method-combination)
+                                     methods)
+  (%compute-standard-effective-method generic-function method-combination methods))
+
+(defun %compute-standard-effective-method (generic-function method-combination methods)
+  (declare (ignore method-combination))
+  (make-standard-combined-method methods nil generic-function t))
+
+(defvar *method-combination-evaluators* (make-hash-table :test 'eq))
+
+(defmacro get-method-combination-evaluator (key)
+  `(gethash ,key *method-combination-evaluators*))
+
+(defmacro define-method-combination-evaluator (name arglist &body body)
+  (setq name (require-type name 'symbol))
+  (unless (and arglist (listp arglist) (eq (length arglist) 2))
+    (error "A method-combination-evaluator must take two args."))
+  `(%define-method-combination-evaluator ',name #'(lambda ,arglist ,@body)))
+
+(defun %define-method-combination-evaluator (operator function)
+  (setq operator (require-type operator 'symbol))
+  (setq function (require-type function 'function))
+  (record-source-file operator 'method-combination-evaluator)
+  (setf (get-method-combination-evaluator operator) function)
+  (maphash #'(lambda (name mci)
+               (when (eq operator (or (and (eq (mci.class mci) 'short-method-combination) (getf (mci.options mci) :operator)) name)))
+                 (clear-method-combination-caches name mci))
+           *method-combination-info*)
+  function)
+
+(defmethod compute-effective-method ((generic-function standard-generic-function)
+                                     (method-combination short-method-combination)
+                                     methods)
+  (or (get-combined-method methods generic-function)
+      (put-combined-method
+       methods
+       (let* ((arounds nil)
+              (primaries nil)
+              (iwoa (method-combination-identity-with-one-argument method-combination))
+              (reverse-p (eq (car (method-combination-options method-combination))
+                             :most-specific-last))
+              (operator (method-combination-operator method-combination))
+              (name (method-combination-name method-combination))
+              qualifiers
+              q)
+         (dolist (m methods)
+           (setq qualifiers (method-qualifiers m))
+           (unless (and qualifiers (null (cdr qualifiers))
+                        (cond ((eq (setq q (car qualifiers)) name)
+                               (push m primaries))
+                              ((eq q :around)
+                               (push m arounds))
+                              (t nil)))
+             (%invalid-method-error m "invalid method qualifiers: ~s" qualifiers)))
+         (when (null primaries)
+           (return-from compute-effective-method
+             (make-no-applicable-method-function generic-function)))
+         (setq arounds (nreverse arounds))
+         (unless reverse-p (setq primaries (nreverse primaries)))
+         (or (optimized-short-effective-method generic-function operator iwoa arounds primaries)
+             (let ((code (if (and iwoa (null (cdr primaries)))
+                           `(call-method ,(car primaries) nil)
+                           `(,operator ,@(mapcar #'(lambda (m) `(call-method ,m nil)) primaries)))))
+               (make-effective-method
+                generic-function
+                (if arounds
+                  `(call-method ,(car arounds)
+                                (,@(cdr arounds) (make-method ,code)))
+                  code)))))
+       generic-function)))
+
+(defun optimized-short-effective-method (gf operator iwoa arounds primaries)
+  (let* ((functionp (functionp (fboundp operator)))
+         (evaluator (unless functionp (get-method-combination-evaluator operator))))
+    (when (or functionp evaluator)
+      (let ((code (if (and iwoa (null (cdr primaries)))
+                    (let ((method (car primaries)))
+                      (if (call-next-method-p method)
+                        #'(lambda (&rest args)
+                            (declare (dynamic-extent args))
+                            (%%call-method* method nil args))
+                        (method-function method)))
+                    (if functionp
+                      (let ((length (length primaries))
+                            (primaries primaries))
+                        #'(lambda (&rest args)
+                            (declare (dynamic-extent args))
+                            (let* ((results (make-list length))
+                                   (results-tail results))
+                              (declare (cons results-tail))
+                              (declare (dynamic-extent results))
+                              (dolist (method primaries)
+                                (setf (car results-tail)
+                                      (%%call-method* method nil args))
+                                (pop results-tail))
+                              (apply operator results))))
+                      (let ((primaries primaries))
+                        #'(lambda (&rest args)
+                            (declare (dynamic-extent args))
+                            (funcall evaluator primaries args)))))))
+        (if arounds
+          (let* ((code-method (make-instance 'standard-method
+                                             :function code
+                                             :generic-function gf
+                                             :name (function-name gf)))
+                 (first-around (car arounds))
+                 (rest-arounds (nconc (cdr arounds) (list code-method))))
+            #'(lambda (&rest args)
+                (declare (dynamic-extent args))
+                (%%call-method* first-around rest-arounds args)))
+          code)))))
+
+(defmethod compute-effective-method ((generic-function standard-generic-function)
+                                     (method-combination long-method-combination)
+                                     methods)
+  (or (get-combined-method methods generic-function)
+      (destructuring-bind ((args-var . gf-name) . expander) 
+                          (method-combination-expander method-combination)
+        (let* ((user-form (funcall expander
+                                   generic-function
+                                   methods
+                                   (method-combination-options method-combination)))
+               (effective-method
+                (if (functionp user-form)
+                  user-form 
+                  (make-effective-method generic-function user-form args-var gf-name))))
+          (put-combined-method methods effective-method generic-function)))))
+
+(defmacro with-call-method-context (args-var &body body)
+  (labels ((bad-call-method-method (method)
+             (error "~s is neither a method nor a ~s form." method 'make-method))
+           (call-method-aux (method next-methods args-var)
+             (unless (typep method 'standard-method)
+               (if (and (listp method) (eq (car method) 'make-method))
+                 (setq method (%make-method method))
+                 (bad-call-method-method method)))
+             (let ((real-next-methods nil))
+               (dolist (m next-methods)
+                 (cond ((typep m 'standard-method)
+                        (push m real-next-methods))
+                       ((and (listp m) (eq (car m) 'make-method))
+                        (push (%make-method m) real-next-methods))
+                       (t (bad-call-method-method m))))
+               `(%%call-method* ,method
+                                ',(nreverse real-next-methods)
+                                ,args-var))))
+    `(macrolet ((call-method (method &optional next-methods)
+                  (funcall ',#'call-method-aux method next-methods ',args-var)))
+       ,@body)))
+
+(defun %make-method (make-method-form &optional
+                                      args-var
+                                      generic-function
+                                      (method-class 'standard-method))
+  (setq args-var (require-type args-var 'symbol))
+  (unless (and (cdr make-method-form) (null (cddr make-method-form)))
+    (%method-combination-error "MAKE-METHOD requires exactly one argument."))
+  (let ((form (cadr make-method-form)))
+    (make-instance 
+     method-class
+     :generic-function generic-function
+     :name (and (functionp generic-function) (function-name generic-function))
+     :function (%make-function
+                nil
+                `(lambda (&rest ,(setq args-var (or args-var (make-symbol "ARGS"))))
+                   (declare (ignore-if-unused ,args-var)
+                            (dynamic-extent ,args-var))
+                   (with-call-method-context ,args-var
+                     ,form))
+                nil))))
+
+(defmethod call-next-method-p ((method standard-method))
+  (call-next-method-p (%method-function method)))
+
+(defmethod call-next-method-p ((function function))
+  (let (lfbits)
+    (and (logbitp $lfbits-method-bit
+                  (setq lfbits (lfun-bits function)))
+         (logbitp $lfbits-nextmeth-bit lfbits))))
+
+(defun make-effective-method (gf form  &optional (args-sym (make-symbol "ARGS")) (gf-name (make-symbol "GF")))
+  (setq args-sym (require-type args-sym 'symbol))
+  (let (m mf)
+    (if (and (listp form)
+             (eq (car form) 'call-method)
+             (listp (cdr form))
+             (typep (setq m (cadr form)) 'standard-method)
+             (listp (cddr form))
+             (null (cdddr form))
+             (not (call-next-method-p (setq mf (%method-function m)))))
+      mf
+      (%make-function
+       nil
+       `(lambda (&rest ,args-sym)
+         (declare (dynamic-extent ,args-sym))
+         (let* ((,gf-name ,gf))
+           (declare (ignorable ,gf-name))
+           (with-call-method-context ,args-sym
+             ,form)))
+       nil))))
+
+;;;;;;;
+;;
+;; Expansions of the DEFINE-METHOD-COMBINATION macro
+;;
+
+;;
+;; Short form
+;;
+(defun short-form-define-method-combination (name options)
+  (destructuring-bind (&key documentation identity-with-one-argument
+                            (operator name)) options
+    (setq name (require-type name 'symbol)
+          operator (require-type operator 'symbol)
+          documentation (unless (null documentation)
+                          (require-type documentation 'string)))
+    (let* ((mci (method-combination-info name))
+           (was-short? (and mci (eq (mci.class mci) 'short-method-combination))))
+      (when (and mci (not was-short?))
+        (check-long-to-short-method-combination name mci))
+      (if mci
+        (let ((old-options (mci.options mci)))
+          (setf (mci.class mci) 'short-method-combination
+                (mci.options mci) options)
+          (unless (and was-short?
+                       (destructuring-bind (&key ((:identity-with-one-argument id))
+                                                 ((:operator op) name)
+                                                 &allow-other-keys)
+                                           old-options
+                         (and (eq id identity-with-one-argument)
+                              (eq op operator))))
+            (update-redefined-short-method-combinations name mci)))
+        (setf (method-combination-info name)
+              (setq mci (%cons-mci 'short-method-combination options)))))
+    (set-documentation name 'method-combination documentation))
+  (record-source-file name 'method-combination)
+  name)
+
+(defun check-long-to-short-method-combination (name mci)
+  (dolist (gf (population-data (mci.gfs mci)))
+    (let ((options (method-combination-options (%gf-method-combination gf))))
+      (unless (or (null options)
+                  (and (listp options)
+                       (null (cdr options))
+                       (memq (car options) '(:most-specific-first :most-specific-last))))
+        (error "Redefining ~s method-combination disagrees with the~
+                method-combination arguments to ~s" name gf)))))
+
+(defun update-redefined-short-method-combinations (name mci)
+  (destructuring-bind (&key identity-with-one-argument (operator name)  documentation)
+                      (mci.options mci)
+    (declare (ignore documentation))
+    (dolist (mc (population-data (mci.instances mci)))
+      (when (typep mc 'long-method-combination)
+        (change-class mc 'short-method-combination))
+      (if (typep mc 'short-method-combination)
+         (setf (slot-value mc 'identity-with-one-argument) identity-with-one-argument
+               (slot-value mc 'operator) operator)
+         (error "Bad method-combination-type: ~s" mc))))
+  (clear-method-combination-caches name mci))
+
+(defun clear-method-combination-caches (name mci)
+  (dolist (gf (population-data (mci.gfs mci)))
+    (clear-gf-cache gf))
+  (when *effective-method-gfs*          ; startup glitch
+    (let ((temp #'(lambda (mc gf)
+                    (when (eq name (method-combination-name (%gf-method-combination gf)))
+                      (remhash mc *effective-method-gfs*)
+                      (remhash mc *combined-methods*)))))
+      (declare (dynamic-extent temp))
+      (maphash temp *effective-method-gfs*))))
+
+;;; Support el-bizarro arglist partitioning for the long form of
+;;; DEFINE-METHOD-COMBINATION.
+(defun nth-required-gf-arg (gf argvals i)
+  (declare (fixnum i))
+  (let* ((bits (lfun-bits gf))
+         (numreq (ldb $lfbits-numreq bits)))
+    (declare (fixnum bits numreq))
+    (if (< i numreq)
+      (nth i argvals))))
+
+(defun nth-opt-gf-arg-present-p (gf argvals i)
+  (declare (fixnum i))
+  (let* ((bits (lfun-bits gf))
+         (numreq (ldb $lfbits-numreq bits))
+         (numopt (ldb $lfbits-numopt bits)))
+    (declare (fixnum bits numreq numopt))
+    (and (< i numopt)
+         (< (the fixnum (+ i numreq)) (length argvals)))))
+
+;;; This assumes that we've checked for argument presence.
+(defun nth-opt-gf-arg (gf argvals i)
+  (declare (fixnum i))
+  (let* ((bits (lfun-bits gf))
+         (numreq (ldb $lfbits-numreq bits)))
+    (declare (fixnum bits numreq ))
+    (nth (the fixnum (+ i numreq)) argvals)))
+
+(defun gf-arguments-tail (gf argvals)
+  (let* ((bits (lfun-bits gf))
+         (numreq (ldb $lfbits-numreq bits))
+         (numopt (ldb $lfbits-numopt bits)))
+    (declare (fixnum bits numreq numopt))
+    (nthcdr (the fixnum (+ numreq numopt)) argvals)))
+
+(defun gf-key-present-p (gf argvals key)
+  (let* ((tail (gf-arguments-tail gf argvals))
+         (missing (cons nil nil)))
+    (declare (dynamic-extent missing))
+    (not (eq missing (getf tail key missing)))))
+
+;; Again, this should only be called if GF-KEY-PRESENT-P returns true.
+(defun gf-key-value (gf argvals key)
+  (let* ((tail (gf-arguments-tail gf argvals)))
+    (getf tail key)))  
+  
+
+(defun lfmc-bindings (gf-form args-form lambda-list)
+  (let* ((req-idx 0)
+         (opt-idx 0)
+         (state :required))
+    (collect ((names)
+              (vals))
+      (dolist (arg lambda-list)
+        (case arg
+          ((&whole &optional &rest &key &allow-other-keys &aux)
+           (setq state arg))
+          (t
+           (case state
+             (:required
+              (names arg)
+              (vals (list 'quote `(nth-required-gf-arg ,gf-form ,args-form ,req-idx)))
+              (incf req-idx))
+             (&whole
+              (names arg)
+              (vals `,args-form)
+              (setq state :required))
+             (&optional
+              (let* ((var arg)
+                     (val nil)
+                     (spvar nil))
+                (when (listp arg)
+                  (setq var (pop arg)
+                        val (pop arg)
+                        spvar (car arg)))
+                (names var)
+                (vals (list 'quote
+                            `(if (nth-opt-gf-arg-present-p ,gf-form ,args-form ,opt-idx)
+                              (nth-opt-gf-arg ,gf-form ,args-form ,opt-idx)
+                              ,val)))
+                (when spvar
+                  (names spvar)
+                  (vals (list 'quote 
+                         `(nth-opt-gf-arg-present-p ,gf-form ,args-form ,opt-idx))))
+                (incf opt-idx)))
+             (&rest
+              (names arg)
+              (vals (list 'quote
+                          `(gf-arguments-tail ,gf-form ,args-form))))
+             (&key
+              (let* ((var arg)
+                     (keyword nil)
+                     (val nil)
+                     (spvar nil))
+                (if (atom arg)
+                  (setq keyword (make-symbol (symbol-name arg)))
+                  (progn
+                    (setq var (car arg))
+                    (if (atom var)
+                      (setq keyword (make-symbol (symbol-name var)))
+                      (setq keyword (car var) var (cadr var)))
+                    (setq val (cadr arg) spvar (caddr arg))))
+                (names var)
+                (vals (list 'quote `(if (gf-key-present-p ,gf-form ,args-form ',keyword)
+                                     (gf-key-value ,gf-form ,args-form ',keyword)
+                                     ,val)))
+                (when spvar
+                  (names spvar)
+                  (vals (list 'quote `(gf-key-present-p ,gf-form ,args-form ',keyword))))))
+             (&allow-other-keys)
+             (&aux
+              (cond ((atom arg)
+                     (names arg)
+                     (vals nil))
+                    (t
+                     (names (car arg))
+                     (vals (list 'quote (cadr arg))))))))))
+      (values (names) (vals)))))
+;;
+;; Long form
+;;
+(defun long-form-define-method-combination (name lambda-list method-group-specifiers
+                                                 forms env)
+  (let (arguments args-specified? generic-fn-symbol gf-symbol-specified?)
+    (unless (verify-lambda-list lambda-list)
+      (error "~s is not a proper lambda-list" lambda-list))
+    (loop
+      (unless (and forms (consp (car forms))) (return))
+      (case (caar forms)
+        (:arguments
+         (when args-specified? (error ":ARGUMENTS specified twice"))
+         (setq arguments (cdr (pop forms))
+               args-specified? t)
+         (do ((args arguments (cdr args)))
+             ((null args))
+           (setf (car args) (require-type (car args) 'symbol))))
+        (:generic-function
+         (when gf-symbol-specified? (error ":GENERIC-FUNCTION specified twice"))
+         (setq generic-fn-symbol
+               (require-type (cadr (pop forms)) '(and symbol (not null)))
+               gf-symbol-specified? t))
+        (t (return))))
+    (multiple-value-bind (body decls doc) (parse-body forms env)
+      (unless generic-fn-symbol (setq generic-fn-symbol (make-symbol "GF")))
+      (multiple-value-bind (specs order-forms required-flags descriptions)
+                           (parse-method-group-specifiers method-group-specifiers)
+        (let* ((methods-sym (make-symbol "METHODS"))
+               (args-sym (make-symbol "ARGS"))
+               (options-sym (make-symbol "OPTIONS"))
+               (arg-vars ())
+               (arg-vals ())
+               (code `(lambda (,generic-fn-symbol ,methods-sym ,options-sym)
+                        ,@(unless gf-symbol-specified?
+                            `((declare (ignore-if-unused ,generic-fn-symbol))))
+                        (let* (,@(progn
+                                  (multiple-value-setq (arg-vars arg-vals)
+                                    (lfmc-bindings generic-fn-symbol
+                                                   args-sym
+                                                   arguments))
+                                  (mapcar #'list arg-vars arg-vals)))
+                          (declare (ignorable ,@arg-vars))
+                          ,@decls
+                          (destructuring-bind ,lambda-list ,options-sym
+                            (destructuring-bind
+                              ,(mapcar #'car method-group-specifiers)
+                              (seperate-method-groups
+                               ,methods-sym ',specs
+                               (list ,@order-forms)
+                               ',required-flags
+                               ',descriptions)
+                              ,@body))))))
+          `(%long-form-define-method-combination
+            ',name (cons (cons ',args-sym ',generic-fn-symbol) #',code) ',doc))))))
+
+(defun %long-form-define-method-combination (name args-var.expander documentation)
+  (setq name (require-type name 'symbol))
+  (let* ((mci (method-combination-info name)))
+    (if mci
+      (progn
+        (setf (mci.class mci) 'long-method-combination
+              (mci.options mci) args-var.expander)
+        (update-redefined-long-method-combinations name mci))
+      (setf (method-combination-info name)
+            (setq mci (%cons-mci 'long-method-combination args-var.expander)))))
+  (set-documentation name 'method-combination documentation)
+  (record-source-file name 'method-combination)
+  name)
+
+(defun update-redefined-long-method-combinations (name mci)
+  (let ((args-var.expander (mci.options mci)))
+    (dolist (mc (population-data (mci.instances mci)))
+      (when (typep mc 'short-method-combination)
+        (change-class mc 'long-method-combination))
+      (if (typep mc 'long-method-combination)
+        (setf (slot-value mc 'expander) args-var.expander)
+        (error "Bad method-combination-type: ~s" mc))))
+  (clear-method-combination-caches name mci))
+
+; Returns four values:
+; method-group specifiers with :order, :required, & :description parsed out
+; Values for the :order args
+; Values for the :required args
+; values for the :description args
+(defun parse-method-group-specifiers (mgs)
+  (let (specs orders requireds descriptions)
+    (dolist (mg mgs)
+      (push nil specs)
+      (push :most-specific-first orders)
+      (push nil requireds)
+      (push nil descriptions)
+      (push (pop mg) (car specs))       ; name
+      (loop
+        (when (null mg) (return))
+        (when (memq (car mg) '(:order :required :description))
+          (destructuring-bind (&key (order :most-specific-first) required description)
+                              mg
+            (setf (car orders) order)
+            (setf (car requireds) required)
+            (setf (car descriptions) description))
+          (return))
+        (push (pop mg) (car specs)))
+      (setf (car specs) (nreverse (car specs))))
+    (values (nreverse specs)
+            (nreverse orders)
+            (nreverse requireds)
+            (nreverse descriptions))))
+
+(defun seperate-method-groups (methods specs orders requireds descriptions)
+  (declare (ignore descriptions))
+  (let ((res (make-list (length specs))))
+    (dolist (m methods)
+      (let ((res-tail res))
+        (dolist (s specs (%invalid-method-error
+                          m "Does not match any of the method group specifiers"))
+          (when (specifier-match-p (method-qualifiers m) s)
+            (push m (car res-tail))
+            (return))
+          (pop res-tail))))
+    (do ((res-tail res (cdr res-tail))
+         (o-tail orders (cdr o-tail))
+         (r-tail requireds (cdr r-tail)))
+        ((null res-tail))
+      (case (car o-tail)
+        (:most-specific-last)
+        (:most-specific-first (setf (car res-tail) (nreverse (car res-tail))))
+        (t (error "~s is neither ~s nor ~s" (car o-tail) :most-specific-first :most-specific-last)))
+      (when (car r-tail)
+        (unless (car res-tail)
+          ; should use DESCRIPTIONS here
+          (error "A required method-group matched no method group specifiers"))))
+    res))
+
+(defun specifier-match-p (qualifiers spec)
+  (flet ((match (qs s)
+           (cond ((or (listp s) (eq s '*))
+                  (do ((qs-tail qs (cdr qs-tail))
+                       (s-tail s (cdr s-tail)))
+                      ((or (null qs-tail) (atom s-tail))
+                       (or (eq s-tail '*)
+                           (and (null qs-tail) (null s-tail))))
+                    (unless (or (eq (car s-tail) '*)
+                                (equal (car qs-tail) (car s-tail)))
+                      (return nil))))
+                 ((atom s) (funcall s qs))
+                 (t (error "Malformed method group specifier: ~s" spec)))))
+    (declare (inline match))
+    (dolist (s (cdr spec))
+      (when (match qualifiers s)
+        (return t)))))
+
+;;;;;;;
+;
+; The user visible error functions
+; We don't add any contextual information yet.
+; Maybe we never will.
+(setf (symbol-function 'method-combination-error) #'%method-combination-error)
+(setf (symbol-function 'invalid-method-error) #'%invalid-method-error)
+
+;;;;;;;
+;
+; The predefined method-combination types
+;
+(define-method-combination + :identity-with-one-argument t)
+(define-method-combination and :identity-with-one-argument t)
+(define-method-combination append :identity-with-one-argument t)
+(define-method-combination list :identity-with-one-argument nil)
+(define-method-combination max :identity-with-one-argument t)
+(define-method-combination min :identity-with-one-argument t)
+(define-method-combination nconc :identity-with-one-argument t)
+(define-method-combination or :identity-with-one-argument t)
+(define-method-combination progn :identity-with-one-argument t)
+
+; And evaluators for the non-functions
+(define-method-combination-evaluator and (methods args)
+  (when methods
+    (loop
+      (if (null (cdr methods))
+        (return (%%call-method* (car methods) nil args)))
+      (unless (%%call-method* (pop methods) nil args)
+        (return nil)))))
+
+(define-method-combination-evaluator or (methods args)
+  (when methods
+    (loop
+      (if (null (cdr methods))
+        (return (%%call-method* (car methods) nil args)))
+      (let ((res (%%call-method* (pop methods) nil args)))
+        (when res (return res))))))
+
+(define-method-combination-evaluator progn (methods args)
+  (when methods
+    (loop
+      (if (null (cdr methods))
+        (return (%%call-method* (car methods) nil args)))
+      (%%call-method* (pop methods) nil args))))
+
+#|
+
+;(define-method-combination and :identity-with-one-argument t)
+(defgeneric func (x) (:method-combination and))
+(defmethod func and ((x window)) (print 3))
+(defmethod func and ((x fred-window)) (print 2))
+(func (front-window))
+
+(define-method-combination example ()((methods positive-integer-qualifier-p))
+  `(progn ,@(mapcar #'(lambda (method)
+                        `(call-method ,method ()))
+                    (sort methods #'< :key #'(lambda (method)
+                                               (first (method-qualifiers method)))))))
+
+(defun positive-integer-qualifier-p (method-qualifiers)
+  (and (= (length method-qualifiers) 1)
+       (typep (first method-qualifiers)'(integer 0 *))))
+
+(defgeneric zork  (x)(:method-combination example))
+
+(defmethod zork 1 ((x window)) (print 1))
+(defmethod zork 2 ((x fred-window)) (print 2))
+(zork (front-window))
+
+
+|#
+
Index: /branches/new-random/lib/misc.lisp
===================================================================
--- /branches/new-random/lib/misc.lisp	(revision 13309)
+++ /branches/new-random/lib/misc.lisp	(revision 13309)
@@ -0,0 +1,1241 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (eval compile)
+  (require 'defstruct-macros))
+
+(defun short-site-name  ()
+  "Return a string with the abbreviated site name, or NIL if not known."
+  (or *short-site-name* "unspecified"))
+
+(defun long-site-name   ()
+  "Return a string with the long form of the site name, or NIL if not known."
+  (or *long-site-name* "unspecified"))
+
+(defun machine-instance ()
+  "Return a string giving the name of the local machine."
+  #-windows-target (%uname 1)
+  #+windows-target
+  (rlet ((nsize #>DWORD 0))
+    (if (eql 0 (#_GetComputerNameExW #$ComputerNameDnsFullyQualified
+                                     (%null-ptr)
+                                     nsize))
+      (%stack-block ((buf (* 2 (pref nsize #>DWORD))))
+        (#_GetComputerNameExW #$ComputerNameDnsFullyQualified
+                              buf
+                              nsize)
+        (%get-native-utf-16-cstring buf))
+      "localhost"))
+  )
+
+
+(defun machine-type ()
+  "Returns a string describing the type of the local machine."
+  #-windows-target (%uname 4)
+  #+windows-target
+  (rlet ((info #>SYSTEM_INFO))
+    (#_GetSystemInfo info)
+    (case (pref info #>SYSTEM_INFO.nil.nil.wProcessorArchitecture)
+      (#.#$PROCESSOR_ARCHITECTURE_AMD64 "x64")
+      (#.#$PROCESSOR_ARCHITECTURE_INTEL "x86")
+      (t "unknown")))
+  )
+
+
+
+(defloadvar *machine-version* nil)
+
+(defun machine-version ()
+  "Return a string describing the version of the computer hardware we
+are running on, or NIL if we can't find any useful information."
+  (or *machine-version*
+      (setq *machine-version*
+            #+darwin-target
+            (block darwin-machine-version
+              (%stack-block ((mib 8))
+                (setf (%get-long mib 0) #$CTL_HW
+                      (%get-long mib 4) #$HW_MODEL)
+                (%stack-block ((res 256)
+                               (reslen target::node-size))
+                  (setf (%get-byte res 0) 0
+                        (%get-natural reslen 0) 256)
+                  (if (zerop (#_sysctl mib 2 res reslen (%null-ptr) 0))
+                    (return-from darwin-machine-version (%get-cstring res))))))
+            #+linux-target
+            (with-open-file (f "/proc/cpuinfo" :if-does-not-exist nil)
+              (when f
+                (flet ((cpu-info-match (target line)
+                         (let* ((targetlen (length target))
+                                (linelen (length line)))
+                           (if (and (> linelen targetlen)
+                                    (string= target line
+                                             :end2 targetlen))
+                           (let* ((colonpos (position #\: line)))
+                             (when colonpos
+                               (string-trim " "
+                                            (subseq line (1+ colonpos)))))))))
+                  (do* ((line (read-line f nil nil)
+                              (read-line f nil nil))
+                        (target #+ppc-target "machine"
+                                #+x86-target "model name"))
+                       ((null line))
+                    (let* ((matched (cpu-info-match target line)))
+                      (when matched (return matched)))))))
+            #+freebsd-target
+            (%stack-block ((ret 512)
+                           (mib (* (record-length :uint))))
+              (setf (%get-unsigned-long mib 0)
+                    #$CTL_HW
+                    (%get-unsigned-long mib (record-length :uint))
+                    #$HW_MODEL)
+              (rlet ((oldsize :uint 512))
+                (if (eql 0 (#_sysctl mib 2 ret oldsize (%null-ptr) 0))
+                  (%get-cstring ret)
+                  1)))
+            #+solaris-target
+            (rlet ((info :processor_info_t))
+              (do* ((i 0 (1+ i)))
+                   ((and (= 0 (#_processor_info i info))
+                         (= (pref info :processor_info_t.pi_state)
+                            #$P_ONLINE))
+                    (%get-cstring (pref info :processor_info_t.pi_processor_type)))))
+            #+windows-target
+            (getenv "PROCESSOR_IDENTIFIER")
+            )))
+
+
+(defun software-type ()
+  "Return a string describing the supporting software."
+  #-windows-target (%uname 0)
+  #+windows-target "Microsoft Windows")
+
+
+(defun software-version ()
+  "Return a string describing version of the supporting software, or NIL
+   if not available."
+  #-windows-target (%uname 2)
+  #+windows-target
+  (rletZ ((info #>OSVERSIONINFOEX))
+    (setf (pref info #>OSVERSIONINFOEX.dwOSVersionInfoSize)
+          (record-length #>OSVERSIONINFOEX))
+    (#_GetVersionExA info)
+    (format nil "~d.~d Build ~d (~a)"
+            (pref info #>OSVERSIONINFOEX.dwMajorVersion)
+            (pref info #>OSVERSIONINFOEX.dwMinorVersion)
+            (pref info #>OSVERSIONINFOEX.dwBuildNumber)
+            (if (eql (pref info #>OSVERSIONINFOEX.wProductType)
+                     #$VER_NT_WORKSTATION)
+              "Workstation"
+              "Server")))
+  )
+
+
+
+
+
+
+
+;;; Yawn.
+
+
+
+(defmethod documentation (thing doc-id)
+  (%get-documentation thing doc-id))
+
+(defmethod (setf documentation) (new thing doc-id)
+  (%put-documentation thing doc-id new))
+
+
+(defmethod documentation ((symbol symbol) (doc-type (eql 'function)))
+  (let* ((def (fboundp symbol)))	; FBOUNDP returns info about definition
+    (when def
+      (%get-documentation def t))))
+
+(defmethod (setf documentation) ((new t)
+				 (symbol symbol)
+				 (doc-type (eql 'function)))
+  (let* ((def (fboundp symbol)))	; FBOUNDP returns info about definition
+    (when def
+      (%put-documentation def
+                          t
+                          new))
+    new))
+
+(defmethod documentation ((symbol symbol) (doc-type (eql 'setf)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t)
+				 (symbol symbol)
+				 (doc-type (eql 'setf)))
+  (call-next-method))
+
+
+(defmethod documentation ((symbol symbol) (doc-type (eql 'variable)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t)
+				 (symbol symbol)
+				 (doc-type (eql 'variable)))
+  (call-next-method))
+
+(defmethod documentation ((symbol symbol) (doc-type (eql 'compiler-macro)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t)
+				 (symbol symbol)
+				 (doc-type (eql 'compiler-macro)))
+  (call-next-method))
+
+(defmethod documentation ((symbol symbol) (doc-type (eql 'type)))
+  (let* ((class (find-class symbol nil)))
+    (if class
+      (documentation class doc-type)
+      (call-next-method))))
+
+(defmethod (setf documentation) (new (symbol symbol) (doc-type (eql 'type)))
+  (let* ((class (find-class symbol nil)))
+    (if class
+      (setf (documentation class doc-type) new)
+      (call-next-method))))
+
+(defmethod documentation ((symbol symbol) (doc-type (eql 'method-combination)))
+  (let* ((mci (method-combination-info symbol)))
+    (if mci
+      (documentation mci doc-type))))
+
+(defmethod (setf documentation) ((new t)
+				 (symbol symbol)
+				 (doc-type (eql 'method-combination)))
+  (let* ((mci (method-combination-info symbol)))
+    (if mci
+      (setf (documentation mci doc-type) new))))
+
+
+(defmethod documentation ((symbol symbol) (doc-type (eql 'structure)))
+  (let* ((class (find-class symbol nil)))
+    (if (typep class 'structure-class)
+      (documentation class 'type)
+      (call-next-method))))
+
+(defmethod (setf documentation) ((new t)
+				 (symbol symbol)
+				 (doc-type (eql 'structure)))
+  (let* ((class (find-class symbol nil)))
+    (if (typep class 'structure-class)
+      (setf (documentation class 'type) new)
+      (call-next-method))))
+
+(defmethod documentation ((p package) (doc-type (eql 't)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t) (p package) (doc-type (eql 't)))
+  (call-next-method))
+
+(defmethod documentation ((f function) (doc-type (eql 't)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t) (f function) (doc-type (eql 't)))
+  (call-next-method))
+
+(defmethod documentation ((f function) (doc-type (eql 'function)))
+  (documentation f t))
+
+(defmethod (setf documentation) ((new t)
+				 (f function)
+				 (doc-type (eql 'function)))
+  (setf (documentation f t) new))
+
+(defmethod documentation ((l cons) (doc-type (eql 'function)))
+  (let* ((name (setf-function-spec-name l)))
+    (if name
+      (documentation name doc-type)
+      (%get-documentation l doc-type))))
+
+(defmethod (setf documentation) ((new t) (l cons) (doc-type (eql 'function)))
+  (let* ((name  (setf-function-spec-name l)))
+    (if name
+      (setf (documentation name doc-type) new)
+      (%put-documentation l doc-type new))))
+
+
+(defmethod documentation ((l cons) (doc-type (eql 'compiler-macro)))
+  (let* ((name (setf-function-spec-name l)))
+    (if name
+      (documentation name doc-type)
+      (%get-documentation l doc-type))))
+
+(defmethod (setf documentation) ((new t) (l cons) (doc-type (eql 'compiler-macr0)))
+  (let* ((name (setf-function-spec-name l)))
+    (if name
+      (setf (documentation name doc-type) new)
+      (%put-documentation l doc-type new))))
+
+
+(defmethod documentation ((m method-combination)
+			  (doc-type (eql 'method-combination)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t)
+				 (m method-combination)
+				 (doc-type (eql 'method-combination)))
+  (call-next-method))
+
+(defmethod documentation ((m method-combination)
+			  (doc-type (eql t)))
+  (documentation m 'method-combination))
+
+(defmethod (setf documentation) ((new t)
+				 (m method-combination)
+				 (doc-type (eql t)))
+  (setf (documentation m 'method-combination) new))
+
+(defmethod documentation ((m standard-method)
+			  (doc-type (eql t)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t)
+				 (m standard-method)
+				 (doc-type (eql t)))
+  (call-next-method))
+
+(defmethod documentation ((c standard-class) (doc-type (eql 'type)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t)
+				 (c standard-class)
+				 (doc-type (eql 'type)))
+  (call-next-method))
+
+(defmethod documentation ((c standard-class) (doc-type (eql 't)))
+  (documentation c 'type))
+
+(defmethod (setf documentation) ((new t)
+				 (c standard-class)
+				 (doc-type (eql 't)))
+  (setf (documentation c 'type) new))
+
+(defmethod documentation ((c structure-class) (doc-type (eql 'type)))
+  (call-next-method))
+
+(defmethod (setf documentation) ((new t)
+				 (c structure-class)
+				 (doc-type (eql 'type)))
+  (call-next-method))
+
+(defmethod documentation ((c structure-class) (doc-type (eql 't)))
+  (documentation c 'type))
+
+(defmethod (setf documentation) ((new t)
+				 (c structure-class)
+				 (doc-type (eql 't)))
+  (setf (documentation c 'type) new))
+
+;;; This is now deprecated; things which call it should stop doing so.
+(defun set-documentation (symbol doc-type string)
+  (setf (documentation symbol doc-type) string))
+
+(defun set-function-info (symbol info)
+  (let* ((doc-string (if (consp info) (car info) info)))
+    (if (and *save-doc-strings* (stringp doc-string))
+      (set-documentation  symbol 'function doc-string)))
+  (let* ((cons (assq symbol *nx-globally-inline*))
+         (lambda-expression (if (consp info) (cdr info))))
+    (if (and (proclaimed-inline-p symbol)
+             (not (compiler-special-form-p symbol))
+             (lambda-expression-p lambda-expression)
+             (let* ((lambda-list (cadr lambda-expression)))
+               (and (not (memq '&lap lambda-list))
+                    (not (memq '&method lambda-list))
+                    (not (memq '&lexpr lambda-list)))))
+      (if cons 
+        (%rplacd cons lambda-expression)
+        (push (cons symbol lambda-expression) *nx-globally-inline*))
+      (if cons (setq *nx-globally-inline* (delete cons *nx-globally-inline*)))))
+  symbol)
+
+
+(setf (documentation 'if 'function)
+      "If Predicate Then [Else]
+  If Predicate evaluates to non-null, evaluate Then and returns its values,
+  otherwise evaluate Else and return its values. Else defaults to NIL.")
+
+(setf (documentation 'progn 'function)
+      "progn form*
+  Evaluates each FORM and returns the value(s) of the last FORM.")
+
+(defmethod documentation ((thing character-encoding) (doc-type (eql t)))
+  (character-encoding-documentation thing))
+
+(defmethod (setf documentation) (new (thing character-encoding) (doc-type (eql t)))
+  (check-type new (or null string))
+  (setf (character-encoding-documentation thing) new))
+
+(defmethod documentation ((thing symbol) (doc-type (eql 'character-encoding)))
+  (let* ((encoding (lookup-character-encoding (intern (string thing) :keyword))))
+    (when encoding
+      (documentation encoding t))))
+
+                                 
+
+
+#|
+(setf (documentation 'car 'variable) "Preferred brand of automobile")
+(documentation 'car 'variable)
+(setf (documentation 'foo 'structure) "the structure is grand.")
+(documentation 'foo 'structure)
+(setf (documentation 'foo 'variable) "the metasyntactic remarker")
+(documentation 'foo 'variable)
+(setf (documentation 'foo 'obscure) "no one really knows what it means")
+(documentation 'foo 'obscure)
+(setf (documentation 'foo 'structure) "the structure is solid")
+(documentation 'foo 'function)
+||#
+
+;;
+
+
+(defun %page-fault-info ()
+  #-(or darwin-target windows-target)
+  (rlet ((usage :rusage))
+    (%%rusage usage)
+    (values (pref usage :rusage.ru_minflt)
+            (pref usage :rusage.ru_majflt)
+            (pref usage :rusage.ru_nswap)))
+  #+darwin-target
+  (rlet ((count #>mach_msg_type_number_t #$TASK_EVENTS_INFO_COUNT)
+         (info #>task_events_info))
+    (#_task_info (#_mach_task_self) #$TASK_EVENTS_INFO info count)
+    (values (pref info #>task_events_info.cow_faults)
+            (pref info #>task_events_info.faults)
+            (pref info #>task_events_info.pageins)))
+  #+windows-target
+  ;; Um, don't know how to determine this, or anything like it.
+  (values 0 0 0))
+
+
+          
+(defparameter *report-time-function* nil
+  "If non-NULL, should be a function which accepts the following
+   keyword arguments:
+   :FORM              the form that was executed
+   :RESULTS           a list of all values returned by the execution of FORM
+   :ELAPSED-TIME      total elapsed (real) time, in internal-time-units-per-second
+   :USER-TIME         elapsed user time, in internal-time-units-per-second
+   :SYSTEM-TIME       elapsed system time, in internal-time-units-per-second
+   :GC-TIME           total real time spent in the GC, in internal-time-units-per-second
+   :BYTES-ALLOCATED   total bytes allocated
+   :MINOR-PAGE-FAULTS minor page faults
+   :MAJOR-PAGE-FAULTS major page faults
+   :SWAPS             swaps")
+
+
+(defun standard-report-time (&key form results elapsed-time user-time
+                                  system-time gc-time bytes-allocated
+                                  minor-page-faults major-page-faults
+                                  swaps)
+  (let* ((s *trace-output*)
+         (units
+          (ecase internal-time-units-per-second
+            (1000000 "microseconds")
+            (1000  "milliseconds")))
+         (width
+          (ecase internal-time-units-per-second
+            (1000000 6)
+            (1000  3)))
+         (cpu-count (cpu-count)))
+    (format s "~&~S took ~:D ~a (~,vF seconds) to run ~%~20twith ~D available CPU core~P."
+            form elapsed-time units width (/ elapsed-time internal-time-units-per-second) cpu-count cpu-count)
+    (format s "~&During that period, ~:D ~a (~,vF seconds) were spent in user mode" user-time units width (/ user-time internal-time-units-per-second))
+    (format s "~&                    ~:D ~a (~,vF seconds) were spent in system mode" system-time units width(/ system-time internal-time-units-per-second))
+    (unless (eql gc-time 0)
+      (format s
+              "~%~:D ~a (~,vF seconds) was spent in GC."
+              gc-time units width (/ gc-time internal-time-units-per-second)))
+    (unless (eql 0 bytes-allocated)
+      (format s "~% ~:D bytes of memory allocated." bytes-allocated))
+    (when (or (> minor-page-faults 0)
+              (> major-page-faults 0)
+              (> swaps 0))
+      (format s
+              "~% ~:D minor page faults, ~:D major page faults, ~:D swaps."
+              minor-page-faults major-page-faults swaps))
+    (format s "~&")
+    (values-list results)))
+
+(defun report-time (form thunk)
+  (flet ((integer-size-in-bytes (i)
+           (if (typep i 'fixnum)
+             0
+             (* (logand (+ 2 (uvsize i)) (lognot 1)) 4))))
+    (multiple-value-bind (user-start system-start)
+        (%internal-run-time)
+      (multiple-value-bind (minor-start major-start swaps-start)
+          (%page-fault-info)
+        (let* ((initial-real-time (get-internal-real-time))
+               (initial-gc-time (gctime))
+               (initial-consed (total-bytes-allocated))           
+               (initial-overhead (integer-size-in-bytes initial-consed)))
+          (let* ((results (multiple-value-list (funcall thunk))))
+            (declare (dynamic-extent results))
+            (multiple-value-bind (user-end system-end)
+                (%internal-run-time)
+              (multiple-value-bind (minor-end major-end swaps-end)
+                  (%page-fault-info)
+                (let* ((new-consed (total-bytes-allocated))		     
+                       (bytes-consed
+                        (- new-consed (+ initial-overhead initial-consed)))
+                       (elapsed-real-time
+                        (- (get-internal-real-time) initial-real-time))
+                       (elapsed-gc-time (- (gctime) initial-gc-time))
+                       (elapsed-user-time
+                        (- user-end user-start))
+                       (elapsed-system-time
+                        (- system-end system-start))
+                       (elapsed-minor (- minor-end minor-start))
+                       (elapsed-major (- major-end major-start))
+                       (elapsed-swaps (- swaps-end swaps-start)))
+                  (funcall (or *report-time-function*
+                               #'standard-report-time)
+                           :form form
+                           :results results
+                           :elapsed-time elapsed-real-time
+                           :user-time elapsed-user-time
+                           :system-time elapsed-system-time
+                           :gc-time elapsed-gc-time
+                           :bytes-allocated bytes-consed
+                           :minor-page-faults elapsed-minor
+                           :major-page-faults elapsed-major
+                           :swaps elapsed-swaps))))))))))
+
+
+
+
+;;; site names and machine-instance is in the init file.
+
+(defun add-feature (symbol)
+  "Not CL but should be."
+  (if (symbolp symbol)
+      (if (not (memq symbol *features*))
+          (setq *features* (cons symbol *features*)))))
+
+;;; (dotimes (i 5000) (declare (fixnum i)) (add-feature 'junk))
+
+
+
+
+;;; Misc string functions
+
+
+(defun string-left-trim (char-bag string &aux end)
+  "Given a set of characters (a list or string) and a string, returns
+  a copy of the string with the characters in the set removed from the
+  left end."
+  (setq string (string string))
+  (setq end (length string))
+  (do ((index 0 (%i+ index 1)))
+      ((or (eq index end) (not (find (aref string index) char-bag)))
+       (subseq string index end))))
+
+(defun string-right-trim (char-bag string &aux end)
+  "Given a set of characters (a list or string) and a string, returns
+  a copy of the string with the characters in the set removed from the
+  right end."
+  (setq string (string string))
+  (setq end (length string))
+  (do ((index (%i- end 1) (%i- index 1)))
+      ((or (%i< index 0) (not (find (aref string index) char-bag)))
+       (subseq string 0 (%i+ index 1)))))
+
+(defun string-trim (char-bag string &aux end)
+  "Given a set of characters (a list or string) and a string, returns a
+  copy of the string with the characters in the set removed from both
+  ends."
+  (setq string (string string))
+  (setq end (length string))
+  (let ((left-end) (right-end))
+     (do ((index 0 (%i+ index 1)))
+	 ((or (eq index end) (not (find (aref string index) char-bag)))
+	  (setq left-end index)))
+     (do ((index (%i- end 1) (%i- index 1)))
+	 ((or (%i< index left-end) (not (find (aref string index) char-bag)))
+	  (setq right-end index)))
+      (subseq string left-end (%i+ right-end 1))))
+
+
+
+(defun copy-symbol (symbol &optional (copy-props nil) &aux new-symbol def)
+  "Make and return a new uninterned symbol with the same print name
+  as SYMBOL. If COPY-PROPS is false, the new symbol is neither bound
+  nor fbound and has no properties, else it has a copy of SYMBOL's
+  function, value and property list."
+  (setq new-symbol (make-symbol (symbol-name symbol)))
+  (when copy-props
+      (when (boundp symbol)
+            (set new-symbol (symbol-value symbol)))
+      (when (setq def (fboundp symbol))
+            ;;;Shouldn't err out on macros/special forms.
+            (%fhave new-symbol def))
+      (set-symbol-plist new-symbol (copy-list (symbol-plist symbol))))
+  new-symbol)
+
+
+(defvar %gentemp-counter 0
+  "Counter for generating unique GENTEMP symbols.")
+
+(defun gentemp (&optional (prefix "T") (package *package*))
+  "Creates a new symbol interned in package PACKAGE with the given PREFIX."
+  (loop
+    (let* ((new-pname (%str-cat (ensure-simple-string prefix) 
+                                (%integer-to-string %gentemp-counter)))
+           (sym (find-symbol new-pname package)))
+      (if sym
+        (setq %gentemp-counter (%i+ %gentemp-counter 1))
+        (return (values (intern new-pname package))))))) ; 1 value.
+
+
+
+
+(defun add-gc-hook (hook-function &optional (which-hook :pre-gc))
+  (ecase which-hook
+    (:pre-gc
+     (pushnew hook-function *pre-gc-hook-list*)
+     (setq *pre-gc-hook* #'(lambda ()
+                             (dolist (hook *pre-gc-hook-list*)
+                               (funcall hook)))))
+    (:post-gc
+     (pushnew hook-function *post-gc-hook-list*)
+     (setq *post-gc-hook* #'(lambda ()
+                             (dolist (hook *post-gc-hook-list*)
+                               (funcall hook))))))
+  hook-function)
+
+(defun remove-gc-hook (hook-function &optional (which-hook :pre-gc))
+  (ecase which-hook
+    (:pre-gc
+     (unless (setq *pre-gc-hook-list* (delq hook-function *pre-gc-hook-list*))
+       (setq *pre-gc-hook* nil)))
+    (:post-gc
+     (unless (setq *post-gc-hook-list* (delq hook-function *post-gc-hook-list*))
+       (setq *post-gc-hook* nil)))))
+
+
+
+
+
+
+(defun find-method-by-names (name qualifiers specializers)
+  (let ((gf (fboundp name)))
+    (when gf
+      (if (not (standard-generic-function-p gf))
+        (error "~S is not a generic-function." gf)
+        (let ((methods (%gf-methods gf)))
+          (when methods
+            (let* ((spec-len (length (%method-specializers (car methods))))
+                   (new-specs (make-list spec-len :initial-element (find-class t))))
+              (declare (dynamic-extent new-specs))
+              (do ((specs specializers (cdr specs))
+                   (nspecs new-specs (cdr nspecs)))
+                  ((or (null specs) (null nspecs)))
+                (let ((s (car specs)))
+                  (rplaca nspecs (if (consp s) s (find-class s nil)))))
+              (find-method gf qualifiers new-specs nil))))))))
+
+
+
+
+(defun make-population (&key (type :list) initial-contents)
+  (let* ((ntype (ecase type
+                  (:list $population_weak-list)
+                  (:alist $population_weak-alist)))
+         (list (if (eq type :alist)
+                 (map 'list (lambda (c) (cons (car c) (%cdr c))) initial-contents)
+                 (if (listp initial-contents)
+                   (copy-list initial-contents)
+                   (coerce initial-contents 'list)))))
+    (%cons-population list ntype)))
+
+(defun population-type (population)
+  (let ((ntype (population.type (require-type population 'population))))
+    (cond ((eq ntype $population_weak-alist) :alist)
+          ((eq ntype $population_weak-list) :list)
+          (t nil))))
+
+(declaim (inline population-contents (setf population-contents)))
+
+(defun population-contents (population)
+  (population.data (require-type population 'population)))
+
+(defun (setf population-contents) (list population)
+  (setf (population.data (require-type population 'population)) (require-type list 'list)))
+
+
+
+
+(defun get-string-from-user (prompt)
+  (with-terminal-input
+      (format *query-io* "~&~a " prompt)
+    (force-output *query-io*)
+    (clear-input *query-io*)
+    (values (read-line *query-io*))))
+
+
+(defun select-item-from-list (list &key (window-title "Select one of the following")
+				   (table-print-function #'prin1)
+				   &allow-other-keys)
+  (block get-answer
+    (with-terminal-input
+      (format *query-io* "~a:~%" window-title)
+      (loop
+	 (catch :redisplay
+	   (do* ((l list (cdr l))
+		 (i 0 (1+ i))
+		 (item (car l) (car l)))
+		((null l))
+	     (declare (fixnum i))
+	     (format *query-io* "~&  ~d: " i)
+	     (funcall table-print-function item *query-io*))
+	   (loop
+	      (fresh-line *query-io*)
+	      (let* ((string (get-string-from-user "Selection [number,q,r,?]:"))
+		     (value (ignore-errors
+			      (let* ((*package* *keyword-package*))
+				(read-from-string string nil)))))
+		(cond ((eq value :q) (throw :cancel t))
+		      ((eq value :r) (throw :redisplay t))
+		      ((eq value :?) 
+		       (format *query-io* "~%Enter the number of the selection, ~%  r to redisplay, ~%  q to cancel or ~%  ? to show this message again."))
+		      ((and (typep value 'unsigned-byte)
+			    (< value (length list)))
+		       (return-from get-answer (list (nth value list))))))))))))
+
+(defvar *choose-file-dialog-hook* nil "for GUIs")
+
+;;; There should ideally be some way to override the UI (such as
+;;; it is ...) here.
+;;; More generally, this either
+;;;   a) shouldn't exist, or
+;;;   b) should do more sanity-checking
+(defun choose-file-dialog (&key file-types (prompt "File name:"))
+  (let* ((hook *choose-file-dialog-hook*))
+    (if hook
+      (funcall hook t prompt file-types)
+      (%choose-file-dialog t prompt file-types))))
+
+(defun choose-new-file-dialog (&key prompt)
+  (let* ((hook *choose-file-dialog-hook*))
+    (if hook
+      (funcall hook nil prompt nil)
+      (%choose-file-dialog nil prompt nil))))
+
+(defun %choose-file-dialog (must-exist prompt file-types)
+  (loop
+      (let* ((namestring (get-string-from-user prompt))
+	     (pathname (ignore-errors (pathname namestring)))
+	     (exists (and pathname (probe-file pathname))))
+	(when (and (if must-exist exists)
+		   (or (null file-types)
+		       (member (pathname-type pathname)
+			       file-types :test #'equal)))
+	  (return pathname))
+	(if (not exists)
+	  (format *query-io* "~&~s does not exist." namestring)
+	  (format *query-io* "~&Type of ~s is not one of ~{~a~}"
+		  namestring file-types)))))
+
+(defparameter *overwrite-dialog-hook* nil)
+(defun overwrite-dialog (filename prompt)
+  (if *overwrite-dialog-hook*
+    (funcall *overwrite-dialog-hook* filename prompt)
+    t))
+
+;;; Might want to have some other entry for, e.g., the inspector
+;;; and to let it get its hands on the list header returned by 
+;;; disassemble-ppc-function.  Maybe disassemble-ppc-function
+;;; should take care of "normalizing" the code-vector ?
+(defun disassemble (thing)
+  "Disassemble the compiled code associated with OBJECT, which can be a
+  function, a lambda expression, or a symbol with a function definition. If
+  it is not already compiled, the compiler is called to produce something to
+  disassemble."
+  (#+ppc-target ppc-xdisassemble
+   #+x86-target x86-xdisassemble
+   (require-type (function-for-disassembly thing) 'compiled-function)))
+
+(defun function-for-disassembly (thing)
+  (let* ((fun thing))
+    ;; CLHS says that DISASSEMBLE should signal a type error if its
+    ;; argument isn't a function designator.  Hard to imagine any
+    ;; code depending on that ...
+    ;;(when (typep fun 'standard-method) (setq fun (%method-function fun)))
+    (when (or (symbolp fun)
+              (and (consp fun) (neq (%car fun) 'lambda)))
+      (setq fun (fboundp thing))
+      (when (and (symbolp thing) (not (functionp fun)))
+        (setq fun (macro-function thing))))
+    (if (typep fun 'compiled-lexical-closure)
+        (setq fun (closure-function fun)))
+    (when (lambda-expression-p fun)
+      (setq fun (compile-named-function fun)))
+    fun))
+
+(%fhave 'df #'disassemble)
+
+(defun string-sans-most-whitespace (string &optional (max-length (length string)))
+  (with-output-to-string (sans-whitespace)
+    (loop
+      for count below max-length
+      for char across string
+      with just-saw-space = nil
+      if (member char '(#\Space #\Tab #\Newline #\Return #\Formfeed))
+        do (if just-saw-space
+               (decf count)
+               (write-char #\Space sans-whitespace))
+        and do (setf just-saw-space t)
+      else
+        do (setf just-saw-space nil)
+        and do (write-char char sans-whitespace))))
+
+
+(defparameter *svn-program* "svn")
+
+(defloadvar *use-cygwin-svn*
+    #+windows-target (not (null (getenv "CYGWIN")))
+    #-windows-target nil)
+
+(defun svn-info-component (component)
+  (let* ((component-length (length component)))
+    (let* ((s (make-string-output-stream)))
+      (multiple-value-bind (status exit-code)
+          (external-process-status
+           (run-program *svn-program*  (list "info" (native-translated-namestring "ccl:")) :output s :error :output))
+        (when (and (eq :exited status) (zerop exit-code))
+          (with-input-from-string (output (get-output-stream-string s))
+            (do* ((line (read-line output nil nil) (read-line output nil nil)))
+                 ((null line))
+              (when (and (>= (length line) component-length)
+                         (string= component line :end2 component-length))
+                (return-from svn-info-component
+                  (string-trim " " (subseq line component-length)))))))))
+    nil))
+
+(defun svn-url () (svn-info-component "URL:"))
+(defun svn-repository () (svn-info-component "Repository Root:"))
+
+;;; Try to say something about what tree (trunk, a branch, a release)
+;;; we were built from. If the URL (relative to the repository)
+;;; starts with "branches", return the second component of the
+;;; relative URL, otherwise return the first component.
+(defun svn-tree ()
+  (let* ((repo (svn-repository))
+         (url (svn-url)))
+    (or 
+     (if (and repo url)
+       (let* ((repo-len (length repo)))
+         (when (and (> (length url) repo-len)
+                    (string= repo url :end2 repo-len))
+           ;; Cheat: do pathname parsing here.
+           (let* ((path (pathname (ensure-directory-namestring (subseq url repo-len))))
+                  (dir (cdr (pathname-directory path))))
+             (when (string= "ccl" (car (last dir)))
+               (let* ((base (car dir)))
+                 (unless (or (string= base "release")
+                             (string= base "releases"))
+                   (if (string= base "branches")
+                     (cadr dir)
+                     (car dir))))))))))))
+
+
+(defun svnversion-program ()
+  (or (ignore-errors
+        (native-translated-namestring
+         (merge-pathnames "svnversion" *svn-program*)))
+      "svnversion"))
+        
+                      
+        
+                         
+(defun local-svn-revision ()
+  (let* ((s (make-string-output-stream))
+         (root (native-translated-namestring "ccl:")))
+    (when *use-cygwin-svn*
+      (setq root (cygpath root)))
+    (multiple-value-bind (status exit-code)
+        (external-process-status
+         (run-program (svnversion-program)  (list  (native-translated-namestring "ccl:") (or (svn-url) "")) :output s :error :output))
+      (when (and (eq :exited status) (zerop exit-code))
+        (with-input-from-string (output (get-output-stream-string s))
+          (let* ((line (read-line output nil nil)))
+            (when (and line (parse-integer line :junk-allowed t) )
+              (return-from local-svn-revision line))))))
+    nil))
+
+
+;;; Scan the heap, collecting infomation on the primitive object types
+;;; found.  Report that information.
+
+(defun heap-utilization (&key (stream *debug-io*)
+                              (gc-first t)
+                              (area nil)
+                              (unit nil)
+                              (sort :size)
+                              (classes nil)
+                              (start nil))
+  "Show statistic about types of objects in the heap.
+   If :GC-FIRST is true (the default), do a full gc before scanning the heap.
+   If :START is non-nil, it should be an object returned by GET-ALLOCATION-SENTINEL, only
+     objects at higher address are scanned (i.e. roughly, only objects allocated after it).
+   :SORT can be one of :COUNT, :LOGICAL-SIZE, or :PHYSICAL-SIZE to sort by count or size.
+   :UNIT can be one of :KB :MB or :GB to show sizes in units other than bytes.
+   :AREA can be used to restrict the walk to one area or a list of areas.  Some possible
+   values are :DYNAMIC, :STATIC, :MANAGED-STATIC, :READONLY.  By default, all areas
+   (including stacks) are examined.
+   If :CLASSES is true, classifies by class rather than just typecode"
+  (let ((data (collect-heap-utilization :gc-first gc-first :start start :area area :classes classes)))
+    (report-heap-utilization data :stream stream :unit unit :sort sort)))
+
+(defun collect-heap-utilization (&key (gc-first t) start area classes)
+  ;; returns list of (type-name count logical-sizes-total physical-sizes-total)
+  (when start
+    (unless (or (null area)
+                (eq (heap-area-code area) area-dynamic)
+                (and (consp area) (every (lambda (a) (eq (heap-area-code a) area-dynamic)) area)))
+      (error "~s ~s and ~s ~s are incompatible" :start start :area area))
+    (setq area area-dynamic))
+  (if classes
+    (collect-heap-utilization-by-class gc-first area start)
+    (collect-heap-utilization-by-typecode gc-first area start)))
+
+(defun collect-heap-utilization-by-typecode (gc-first area start)
+  (let* ((nconses 0)
+         (counts (make-array 257))
+         (sizes (make-array 257))
+         (physical-sizes (make-array 257))
+         (array-size-function (arch::target-array-data-size-function
+                               (backend-target-arch *host-backend*))))
+    (declare (type (simple-vector 257) counts sizes physical-sizes)
+             (fixnum nconses)
+             (dynamic-extent counts sizes physical-sizes))
+    (flet ((collect (thing)
+             (when (or (null start)
+                       (locally (declare (optimize (speed 3) (safety 0))) ;; lie
+                         (%i< start thing)))
+               (if (listp thing)
+                 (incf nconses)
+                 (let* ((typecode (typecode thing))
+                        (logsize (funcall array-size-function typecode (uvsize thing)))
+                        (physize (logandc2 (+ logsize
+                                              #+64-bit-target (+ 8 15)
+                                              #+32-bit-target (+ 4 7))
+                                           #+64-bit-target 15
+                                           #+32-bit-target 7)))
+                   (incf (aref counts typecode))
+                   (incf (aref sizes typecode) logsize)
+                   (incf (aref physical-sizes typecode) physize))))))
+      (declare (dynamic-extent #'collect))
+      (when gc-first (gc))
+      (%map-areas #'collect area))
+    (setf (aref counts 256) nconses)
+    (setf (aref sizes 256) (* nconses target::cons.size))
+    (setf (aref physical-sizes 256) (aref sizes 256))
+    (loop for i from 0 upto 256
+      when (plusp (aref counts i))
+      collect (list (if (eql i 256) 'cons (aref *heap-utilization-vector-type-names* i))
+                    (aref counts i)
+                    (aref sizes i)
+                    (aref physical-sizes i)))))
+
+(defun collect-heap-utilization-by-class (gc-first area start)
+  (let* ((nconses 0)
+         (max-classes (+ 100 (hash-table-count %find-classes%)))
+         (map (make-hash-table :shared nil
+                               :test 'eq
+                               :size max-classes))
+         (inst-counts (make-array max-classes :initial-element 0))
+         (slotv-counts (make-array max-classes :initial-element 0))
+         (inst-sizes (make-array max-classes :initial-element 0))
+         (slotv-sizes (make-array max-classes :initial-element 0))
+         (inst-psizes (make-array max-classes :initial-element 0))
+         (slotv-psizes (make-array max-classes :initial-element 0))
+         (overflow nil)
+         (array-size-function (arch::target-array-data-size-function
+                               (backend-target-arch *host-backend*))))
+    (declare (type simple-vector inst-counts slotv-counts inst-sizes slotv-sizes inst-psizes slotv-psizes))
+    (flet ((collect (thing)
+             (when (or (null start)
+                       (locally (declare (optimize (speed 3) (safety 0))) ;; lie
+                         (%i< start thing)))
+               (if (listp thing)
+                 (incf nconses)
+                 (unless (or (eq thing map)
+                             (eq thing (nhash.vector map))
+                             (eq thing inst-counts)
+                             (eq thing slotv-counts)
+                             (eq thing inst-sizes)
+                             (eq thing slotv-sizes)
+                             (eq thing inst-psizes)
+                             (eq thing slotv-psizes))
+                   (let* ((typecode (typecode thing))
+                          (logsize (funcall array-size-function typecode (uvsize thing)))
+                          (physize (logandc2 (+ logsize
+                                                #+64-bit-target (+ 8 15)
+                                                #+32-bit-target (+ 4 7))
+                                             #+64-bit-target 15
+                                             #+32-bit-target 7))
+                          (class (class-of (if (eql typecode target::subtag-slot-vector)
+                                             (uvref thing slot-vector.instance)
+                                             thing)))
+                          (index (or (gethash class map)
+                                     (let ((count (hash-table-count map)))
+                                       (if (eql count max-classes)
+                                         (setq overflow t count (1- max-classes))
+                                         (setf (gethash class map) count))))))
+                   
+                     (if (eql typecode target::subtag-slot-vector)
+                       (progn
+                         (incf (aref slotv-counts index))
+                         (incf (aref slotv-sizes index) logsize)
+                         (incf (aref slotv-psizes index) physize))
+                       (progn
+                         (incf (aref inst-counts index))
+                         (incf (aref inst-sizes index) logsize)
+                         (incf (aref inst-psizes index) physize)))))))))
+      (declare (dynamic-extent #'collect))
+      (when gc-first (gc))
+      (%map-areas #'collect area))
+    (let ((data ()))
+      (when (plusp nconses)
+        (push (list 'cons nconses (* nconses target::cons.size) (* nconses target::cons.size)) data))
+      (maphash (lambda (class index)
+                 (let* ((icount (aref inst-counts index))
+                        (scount (aref slotv-counts index))
+                        (name (if (and overflow (eql index (1- max-classes)))
+                                "All others"
+                                (or (%class-proper-name class) class))))
+                   (declare (fixnum icount) (fixnum scount))
+                   ;; When printing class names, the package matters.  report-heap-utilization
+                   ;; uses ~a, so print here.
+                   (when (plusp icount)
+                     (push (list (prin1-to-string name)
+                                 icount (aref inst-sizes index) (aref inst-psizes index)) data))
+                   (when (plusp scount)
+                     (push (list (format nil "(SLOT-VECTOR ~s)" name)
+                                 scount (aref slotv-sizes index) (aref slotv-psizes index)) data))))
+               map)
+      data)))
+
+(defvar *heap-utilization-vector-type-names*
+  (let* ((a (make-array 256)))
+    #+x8664-target
+    (dotimes (i 256)
+      (let* ((fulltag (logand i x8664::fulltagmask))
+             (names-vector
+              (cond ((= fulltag x8664::fulltag-nodeheader-0)
+                     *nodeheader-0-types*)
+                    ((= fulltag x8664::fulltag-nodeheader-1)
+                     *nodeheader-1-types*)
+                    ((= fulltag x8664::fulltag-immheader-0)
+                     *immheader-0-types*)
+                    ((= fulltag x8664::fulltag-immheader-1)
+                     *immheader-1-types*)
+                    ((= fulltag x8664::fulltag-immheader-2)
+                     *immheader-2-types*)))
+             (name (if names-vector
+                     (aref names-vector (ash i -4)))))
+        ;; Special-case a few things ...
+        (if (eq name 'symbol-vector)
+          (setq name 'symbol)
+          (if (eq name 'function-vector)
+            (setq name 'function)))
+        (setf (aref a i) name)))
+    #+ppc64-target
+    (dotimes (i 256)
+      (let* ((lowtag (logand i ppc64::lowtagmask)))
+        (setf (%svref a i)
+              (cond ((= lowtag ppc64::lowtag-immheader)
+                     (%svref *immheader-types* (ash i -2)))
+                    ((= lowtag ppc64::lowtag-nodeheader)
+                     (%svref *nodeheader-types* (ash i -2)))))))
+    #+(or ppc32-target x8632-target)
+    (dotimes (i 256)
+      (let* ((fulltag (logand i target::fulltagmask)))
+        (setf (%svref a i)
+              (cond ((= fulltag target::fulltag-immheader)
+                     (%svref *immheader-types* (ash i -3)))
+                    ((= fulltag target::fulltag-nodeheader)
+                     (%svref *nodeheader-types* (ash i -3)))))))
+    a))
+
+  
+(defun report-heap-utilization (data &key stream unit sort)
+  (let* ((div (ecase unit
+                ((nil) 1)
+                (:kb 1024.0d0)
+                (:mb (* 1024.0d0 1024.0d0))
+                (:gb (* 1024.0d0 1024.0d0 1024.0d0))))
+         (sort-key (ecase sort
+                     (:count #'cadr)
+                     (:logical-size #'caddr)
+                     ((:physical-size :size) #'cadddr)
+                     ((:name nil) nil)))
+         (total-count 0)
+         (total-lsize 0)
+         (total-psize 0)
+         (max-name 0))
+    (loop for (name count lsize psize) in data
+      do (incf total-count count)
+      do (incf total-lsize lsize)
+      do (incf total-psize psize)
+      do (setq max-name (max max-name
+                             (length (if (stringp name)
+                                       name
+                                       (if (symbolp name)
+                                         (symbol-name name)
+                                         (princ-to-string name)))))))
+    (setq data
+          (if sort-key
+            (sort data #'> :key sort-key)
+            (sort data #'string-lessp :key #'(lambda (name)
+                                               (if (stringp name)
+                                                 name
+                                                 (if (symbolp name)
+                                                   (symbol-name name)
+                                                   (princ-to-string name)))))))
+                                                    
+    (format stream "~&Object type~vtCount     Logical size   Physical size   % of Heap~%~vt ~a~vt ~2:*~a"
+            (+ max-name 7)
+            (+ max-name 15)
+            (ecase unit
+              ((nil) "  (in bytes)")
+              (:kb   "(in kilobytes)")
+              (:mb   "(in megabytes)")
+              (:gb   "(in gigabytes)"))
+            (+ max-name 31))
+    (loop for (type count logsize physsize) in data
+      do (if unit
+           (format stream "~&~a~vt~11d~16,2f~16,2f~11,2f%"
+                   type
+                   (1+ max-name)
+                   count
+                   (/ logsize div)
+                   (/ physsize div)
+                   (* 100.0 (/ physsize total-psize)))
+           (format stream "~&~a~vt~11d~16d~16d~11,2f%"
+                   type
+                   (1+ max-name)
+                   count
+                   logsize
+                   physsize
+                   (* 100.0 (/ physsize total-psize)))))
+    (if unit
+      (format stream "~&~a~vt~11d~16,2f~16,2f~11,2f%"
+              "Total"
+              (1+ max-name)
+              total-count
+              (/ total-lsize div)
+              (/ total-psize div)
+              100.0d0)
+      (format stream "~&~a~vt~11d~16d~16d~11,2f%"
+              "Total"
+              (1+ max-name)
+              total-count
+              total-lsize
+              total-psize
+              100.0d0)))
+  (values))
+
+
+
+(defun static-cons (car-value cdr-value)
+  "Allocates a cons cell that doesn't move on garbage collection,
+   and thus doesn't trigger re-hashing when used as a key in a hash
+   table.  Usage is equivalent to regular CONS."
+  (loop
+    (let ((cell (%atomic-pop-static-cons)))
+      (if cell
+        (progn
+          (setf (car cell) car-value)
+          (setf (cdr cell) cdr-value)
+          (return cell))
+        (progn
+          (%ensure-static-conses))))))
+
+(defun free-static-conses ()
+  (%get-kernel-global free-static-conses))
+
+(defun reserved-static-conses ()
+  (%fixnum-ref-natural (%get-kernel-global static-cons-area) target::area.ndnodes))
+	
+
+(defparameter *weak-gc-method-names*
+  '((:traditional . 0)
+    (:non-circular . 1)))
+
+
+(defun weak-gc-method ()
+  (or (car (rassoc (%get-kernel-global 'weak-gc-method)
+                   *weak-gc-method-names*))
+      :traditional))
+
+
+(defun (setf weak-gc-method) (name)
+  (setf (%get-kernel-global 'weak-gc-method)
+        (or (cdr (assoc name *weak-gc-method-names*))
+            0))
+  name)
+
+(defun %lock-whostate-string (string lock)
+  (with-standard-io-syntax
+      (format nil "~a for ~a ~@[~a ~]@ #x~x"
+              string
+              (%svref lock target::lock.kind-cell)
+              (lock-name lock)
+              (%ptr-to-int (%svref lock target::lock._value-cell)))))
+
+(defun all-watched-objects ()
+  (let (result)
+    (with-other-threads-suspended
+      (%map-areas #'(lambda (x) (push x result)) area-watched))
+    result))
+
+(defun primitive-watch (thing)
+  (require-type thing '(or cons (satisfies uvectorp)))
+  (%watch thing))
+
+(defun watch (&optional thing)
+  (cond ((null thing)
+	 (all-watched-objects))
+	((arrayp thing)
+	 (primitive-watch (array-data-and-offset thing)))
+	((hash-table-p thing)
+	 (primitive-watch (nhash.vector thing)))
+	((standard-instance-p thing)
+	 (primitive-watch (instance-slots thing)))
+	(t
+	 (primitive-watch thing))))
+
+(defun unwatch (thing)
+  (with-other-threads-suspended
+    (%map-areas #'(lambda (x)
+		    (when (eq x thing)
+		      (let ((new (if (uvectorp thing)
+				   (%alloc-misc (uvsize thing)
+						(typecode thing))
+				   (cons nil nil))))
+			(return-from unwatch (%unwatch thing new)))))
+                area-watched)))
Index: /branches/new-random/lib/nfcomp.lisp
===================================================================
--- /branches/new-random/lib/nfcomp.lisp	(revision 13309)
+++ /branches/new-random/lib/nfcomp.lisp	(revision 13309)
@@ -0,0 +1,2119 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;; :lib:nfcomp.lisp - New fasl compiler.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+   (require 'level-2))
+
+(require 'optimizers)
+(require 'hash)
+
+(eval-when (:compile-toplevel :execute)
+
+(require 'backquote)
+(require 'defstruct-macros)
+
+(defmacro short-fixnum-p (fixnum)
+  `(and (fixnump ,fixnum) (< (integer-length ,fixnum) 16)))
+
+(require "FASLENV" "ccl:xdump;faslenv")
+
+#+ppc32-target
+(require "PPC32-ARCH")
+#+ppc64-target
+(require "PPC64-ARCH")
+#+x8632-target
+(require "X8632-ARCH")
+#+x8664-target
+(require "X8664-ARCH")
+) ;eval-when (:compile-toplevel :execute)
+
+
+;File compiler options.  Not all of these need to be exported/documented, but
+;they should be in the product just in case we need them for patches....
+(defvar *fasl-save-local-symbols* t)
+(defvar *fasl-save-doc-strings*  t)
+(defvar *fasl-save-definitions* nil)
+
+(defvar *fasl-deferred-warnings* nil)
+(defvar *fasl-non-style-warnings-signalled-p* nil)
+(defvar *fasl-warnings-signalled-p* nil)
+
+(defvar *compile-verbose* nil ; Might wind up getting called *compile-FILE-verbose*
+  "The default for the :VERBOSE argument to COMPILE-FILE.")
+(defvar *compile-file-pathname* nil
+  "The defaulted pathname of the file currently being compiled, or NIL if not
+  compiling.") ; pathname of src arg to COMPILE-FILE
+(defvar *compile-file-truename* nil
+  "The TRUENAME of the file currently being compiled, or NIL if not
+  compiling.") ; truename ...
+(defvar *fasl-target* (backend-name *host-backend*))
+(defvar *fasl-backend* *host-backend*)
+(defvar *fasl-host-big-endian*
+  (arch::target-big-endian (backend-target-arch *host-backend*)))
+(defvar *fasl-target-big-endian* *fasl-host-big-endian*)
+(defvar *fcomp-external-format* :default)
+
+(defvar *fasl-break-on-program-errors* #+ccl-0711 nil #-ccl-0711 :defer
+  "Controls what happens when the compiler detects PROGRAM-ERROR's during file compilation.
+
+  If T, the compiler signals an error immediately when it detects the program-error.
+
+  If :DEFER, program errors are reported as compiler warnings, and in addition, an error
+    is signalled at the end of file compilation.  This allows all warnings for the file
+    to be reported, but prevents the creation of a fasl file.
+
+  If NIL, program errors are treated the same as any other error condition detected by
+   the compiler, i.e. they are reported as compiler warnings and do not cause any
+   error to be signalled at compile time.")
+  
+
+(defvar *compile-print* nil ; Might wind up getting called *compile-FILE-print*
+  "The default for the :PRINT argument to COMPILE-FILE.")
+
+;Note: errors need to rebind this to NIL if they do any reading without
+; unwinding the stack!
+(declaim (special *compiling-file*)) ; defined in l1-init.
+
+(defvar *fasl-source-file* nil "Name of file currently being read from.
+Will differ from *compiling-file* during an INCLUDE")
+
+(defparameter *fasl-package-qualified-symbols* '(*loading-file-source-file* set-package %define-package)
+  "These symbols are always fasdumped with full package qualification.")
+
+(defun setup-target-features (backend features)
+  (if (eq backend *host-backend*)
+    features
+    (let* ((new nil)
+	   (nope (backend-target-specific-features *host-backend*)))
+      (dolist (f features)
+	(unless (memq f nope) (pushnew f new)))
+      (dolist (f (backend-target-specific-features backend)
+	       (progn (pushnew :cross-compiling new) new))
+	(pushnew f new)))))
+
+(defun compile-file-pathname (pathname &rest ignore &key output-file &allow-other-keys)
+  "Return a pathname describing what file COMPILE-FILE would write to given
+   these arguments."
+  (declare (ignore ignore))
+  (setq pathname (merge-pathnames pathname))
+  (merge-pathnames (if output-file
+                     (merge-pathnames output-file *.fasl-pathname*)
+                     *.fasl-pathname*) 
+                   pathname))
+
+(defun compile-file (src &key output-file
+                         (verbose *compile-verbose*)
+                         (print *compile-print*)
+                         load
+                         features
+                         (target *fasl-target* target-p)
+                         (save-local-symbols *fasl-save-local-symbols*)
+                         (save-doc-strings *fasl-save-doc-strings*)
+                         (save-definitions *fasl-save-definitions*)
+                         (save-source-locations *save-source-locations*)
+                         (external-format :default)
+                         force
+                         ;; src may be a temp file with a section of the real source,
+                         ;; then this is the real source file name.
+                         compile-file-original-truename
+                         (compile-file-original-buffer-offset 0)
+                         (break-on-program-errors (if compile-file-original-truename
+                                                    t  ;; really SLIME being interactive...
+                                                    *fasl-break-on-program-errors*)))
+  "Compile SRC, producing a corresponding fasl file and returning its filename."
+  (let* ((backend *target-backend*))
+    (when (and target-p (not (setq backend (find-backend target))))
+      (warn "Unknown :TARGET : ~S.  Reverting to ~s ..." target *fasl-target*)
+      (setq target *fasl-target*  backend *target-backend*))
+    (multiple-value-bind (output-file truename warnings-p serious-p)
+        (loop
+          (restart-case
+              (return (%compile-file src output-file verbose print features
+                                     save-local-symbols save-doc-strings save-definitions
+                                     save-source-locations break-on-program-errors
+                                     force backend external-format
+                                     compile-file-original-truename compile-file-original-buffer-offset))
+            (retry-compile-file ()
+              :report (lambda (stream) (format stream "Retry compiling ~s" src))
+              nil)
+            (skip-compile-file ()
+              :report (lambda (stream)
+                        (if load
+                          (format stream "Skip compiling and loading ~s" src)
+                          (format stream "Skip compiling ~s" src)))
+              (return-from compile-file))))
+      (when load (load output-file :verbose (or verbose *load-verbose*)))
+      (values truename warnings-p serious-p))))
+
+
+(defvar *fasl-compile-time-env* nil)
+
+(defun %compile-file (src output-file verbose print features
+                          save-local-symbols save-doc-strings save-definitions
+                          save-source-locations break-on-program-errors
+                          force target-backend external-format
+                          compile-file-original-truename compile-file-original-buffer-offset)
+  (let* ((orig-src (merge-pathnames src))
+         (output-default-type (backend-target-fasl-pathname target-backend))
+         (*fasl-non-style-warnings-signalled-p* nil)
+         (*fasl-warnings-signalled-p* nil))
+    (setq src (fcomp-find-file orig-src))
+    (let* ((newtype (pathname-type src)))
+      (when (and newtype (not (pathname-type orig-src)))
+        (setq orig-src (merge-pathnames orig-src (make-pathname :type newtype :defaults nil)))))
+    (setq output-file (merge-pathnames
+		       (if output-file  ; full-pathname in case output-file is relative
+			 (full-pathname (merge-pathnames output-file output-default-type) :no-error nil) 
+			 output-default-type)
+		       orig-src))
+    ;; This should not be necessary, but it is.
+    (setq output-file (namestring output-file))
+    (when (physical-pathname-p orig-src) ; only back-translate to things likely to exist at load time
+      (setq orig-src (back-translate-pathname orig-src '("home" "ccl"))))
+    (when (and (not force)
+               (probe-file output-file)
+               (not (fasl-file-p output-file)))
+      (cerror "overwrite it anyway"
+              "Compile destination ~S is not a ~A file!"
+              output-file (pathname-type
+                           (backend-target-fasl-pathname
+                            *target-backend*))))
+    (let* ((*features* (append (if (listp features) features (list features)) (setup-target-features target-backend *features*)))
+           (*fasl-deferred-warnings* nil) ; !!! WITH-COMPILATION-UNIT ...
+           (*fasl-save-local-symbols* save-local-symbols)
+           (*save-source-locations* save-source-locations)
+           (*fasl-save-doc-strings* save-doc-strings)
+           (*fasl-save-definitions* save-definitions)
+           (*fasl-break-on-program-errors* break-on-program-errors)
+           (*fcomp-warnings-header* nil)
+           (*compile-file-pathname* orig-src)
+           (*compile-file-truename* (truename src))
+           (*package* *package*)
+           (*readtable* *readtable*)
+           (*compile-print* print)
+           (*compile-verbose* verbose)
+           (*fasl-target* (backend-name target-backend))
+           (*fasl-backend* target-backend)
+           (*fasl-target-big-endian* (arch::target-big-endian
+                                      (backend-target-arch target-backend)))
+           (*target-ftd* (backend-target-foreign-type-data target-backend))
+           (defenv (new-definition-environment))
+           (lexenv (new-lexical-environment defenv))
+           (*fasl-compile-time-env* (new-lexical-environment (new-definition-environment)))
+           (*fcomp-external-format* external-format)
+           (forms nil))
+      (let ((current *outstanding-deferred-warnings*) last)
+        (when (and current
+                   (setq last (deferred-warnings.last-file current))
+                   (equalp *compile-file-pathname* (cdr last)))
+          ;; Discard previous deferred warnings when recompiling exactly the same file again,
+          ;; since most likely this is due to an interactive "retry compilation" request and
+          ;; we want to avoid duplicate warnings.
+          (setf (deferred-warnings.last-file current) nil)))
+
+      (let* ((*outstanding-deferred-warnings* (%defer-warnings nil)))
+        (rplacd (defenv.type defenv) *outstanding-deferred-warnings*)
+        (setf (defenv.defined defenv) (deferred-warnings.defs *outstanding-deferred-warnings*))
+
+        (setq forms (fcomp-file src
+                                (or compile-file-original-truename (namestring orig-src))
+                                compile-file-original-buffer-offset
+                                lexenv))
+
+        (setf (deferred-warnings.warnings *outstanding-deferred-warnings*) 
+              (append *fasl-deferred-warnings* (deferred-warnings.warnings *outstanding-deferred-warnings*)))
+        (when *compile-verbose* (fresh-line))
+        (multiple-value-bind (any harsh) (report-deferred-warnings *compile-file-pathname*)
+          (setq *fasl-warnings-signalled-p* (or *fasl-warnings-signalled-p* any)
+                *fasl-non-style-warnings-signalled-p* (if (eq harsh :very) :very
+                                                        (or *fasl-non-style-warnings-signalled-p* harsh)))))
+      (when (and *fasl-break-on-program-errors* (eq *fasl-non-style-warnings-signalled-p* :very))
+        (cerror "create the output file despite the errors"
+                "Serious errors encountered during compilation of ~s"
+                src))
+      (fasl-scan-forms-and-dump-file forms output-file lexenv)
+      (values output-file
+              (truename (pathname output-file)) 
+              *fasl-warnings-signalled-p* 
+              (and *fasl-non-style-warnings-signalled-p* t)))))
+
+(defvar *fcomp-locked-hash-tables*)
+(defvar *fcomp-load-forms-environment* nil)
+
+; This is separated out so that dump-forms-to-file can use it
+(defun fasl-scan-forms-and-dump-file (forms output-file &optional env)
+  (let ((*fcomp-locked-hash-tables* nil)
+	(*fcomp-load-forms-environment* env))
+    (unwind-protect
+      (multiple-value-bind (hash gnames goffsets) (fasl-scan forms)
+        (fasl-dump-file gnames goffsets forms hash output-file))
+      (fasl-unlock-hash-tables))))
+
+#-bccl
+(defun nfcomp (src &optional dest &rest keys)
+  (when (keywordp dest) (setq keys (cons dest keys) dest nil))
+  (apply #'compile-file src :output-file dest keys))
+
+#-bccl
+(%fhave 'fcomp #'nfcomp)
+
+(defparameter *default-file-compilation-policy* (new-compiler-policy))
+
+(defun current-file-compiler-policy ()
+  *default-file-compilation-policy*)
+
+(defun set-current-file-compiler-policy (&optional new-policy)
+  (setq *default-file-compilation-policy* 
+        (if new-policy (require-type new-policy 'compiler-policy) (new-compiler-policy))))
+
+(defparameter *compile-time-evaluation-policy*
+  (new-compiler-policy :force-boundp-checks t))
+
+(defun %compile-time-eval (form env)
+  (declare (ignore env))
+  (let* ((*target-backend* *host-backend*)
+         (*loading-toplevel-location* (or (fcomp-source-note form)
+                                          *loading-toplevel-location*))
+         (lambda `(lambda () ,form)))
+    (fcomp-note-source-transformation form lambda)
+    ;; The HANDLER-BIND here is supposed to note WARNINGs that're
+    ;; signaled during (eval-when (:compile-toplevel) processing; this
+    ;; in turn is supposed to satisfy a pedantic interpretation of the
+    ;; spec's requirement that COMPILE-FILE's second and third return
+    ;; values reflect (all) conditions "detected by the compiler."
+    ;; (It's kind of sad that CL language design is influenced so
+    ;; strongly by the views of pedants these days.)
+    (handler-bind ((warning (lambda (c)
+                              (setq *fasl-warnings-signalled-p* t)
+                              (unless (typep c 'style-warning)
+                                (setq *fasl-non-style-warnings-signalled-p* t))
+                              (signal c))))
+      (funcall (compile-named-function
+                lambda
+                :source-notes *fcomp-source-note-map*
+                :env *fasl-compile-time-env*
+                :policy *compile-time-evaluation-policy*)))))
+
+
+;;; No methods by default, not even for structures.  This really sux.
+(defgeneric make-load-form (object &optional environment))
+
+;;; Well, no usable methods by default.  How this is better than
+;;; getting a NO-APPLICABLE-METHOD error frankly escapes me,
+(defun no-make-load-form-for (object)
+  (error "No ~S method is defined for ~s" 'make-load-form object))
+
+(defmethod make-load-form ((s standard-object) &optional environment)
+  (declare (ignore environment))
+  (no-make-load-form-for s))
+
+(defmethod make-load-form ((s structure-object) &optional environment)
+  (declare (ignore environment))
+  (no-make-load-form-for s))
+
+(defmethod make-load-form ((c condition) &optional environment)
+  (declare (ignore environment))
+  (no-make-load-form-for c))
+
+(defmethod make-load-form ((c class) &optional environment)
+  (let* ((name (class-name c))
+	 (found (if name (find-class name nil environment))))
+    (if (eq found c)
+      `(find-class ',name)
+      (error "Class ~s does not have a proper name." c))))
+
+
+;;;;          FCOMP-FILE - read & compile file
+;;;;          Produces a list of (opcode . args) to run on loading, intermixed
+;;;;          with read packages.
+
+(defparameter *fasl-eof-forms* nil)
+
+(defparameter cfasl-load-time-eval-sym (make-symbol "LOAD-TIME-EVAL"))
+(%macro-have cfasl-load-time-eval-sym
+    #'(lambda (call env) (declare (ignore env)) (list 'eval (list 'quote call))))
+;Make it a constant so compiler will barf if try to bind it, e.g. (LET #,foo ...)
+(define-constant cfasl-load-time-eval-sym cfasl-load-time-eval-sym)
+
+
+(defparameter *reading-for-cfasl* nil "Used by the reader for #,")
+
+
+
+(declaim (special *nx-compile-time-types*
+;The following are the global proclaimed values.  Since compile-file binds
+;them, this means you can't ever globally proclaim these things from within a
+;file compile (e.g. from within eval-when compile, or loading a file) - the
+;proclamations get lost when compile-file exits.  This is sort of intentional
+;(or at least the set of things which fall in this category as opposed to
+;having a separate compile-time variable is sort of intentional).
+                    *nx-proclaimed-inline*    ; inline and notinline
+                    *nx-proclaimed-ignore*    ; ignore and unignore
+                    *nx-known-declarations*   ; declaration
+                    *nx-speed*                ; optimize speed
+                    *nx-space*                ; optimize space
+                    *nx-safety*               ; optimize safety
+                    *nx-cspeed*))             ; optimize compiler-speed
+
+(defvar *fcomp-load-time*)
+(defvar *fcomp-inside-eval-always* nil)
+(defvar *fcomp-eval-always-functions* nil)   ; used by the LISP package
+(defvar *fcomp-output-list*)
+(defvar *fcomp-toplevel-forms*)
+(defvar *fcomp-source-note-map* nil)
+(defvar *fcomp-loading-toplevel-location*)
+(defvar *fcomp-warnings-header*)
+(defvar *fcomp-stream-position* nil)
+(defvar *fcomp-previous-position* nil)
+(defvar *fcomp-indentation*)
+(defvar *fcomp-print-handler-plist* nil)
+(defvar *fcomp-last-compile-print*
+  '(INCLUDE (NIL . T)
+    DEFSTRUCT ("Defstruct" . T) 
+    DEFCONSTANT "Defconstant" 
+    DEFSETF "Defsetf" 
+    DEFTYPE "Deftype" 
+    DEFCLASS "Defclass" 
+    DEFGENERIC "Defgeneric"
+    DEFMETHOD "Defmethod"
+    DEFMACRO "Defmacro" 
+    DEFPARAMETER "Defparameter" 
+    DEFVAR "Defvar" 
+    DEFUN ""))
+
+(setf (getf *fcomp-print-handler-plist* 'defun) ""
+      (getf *fcomp-print-handler-plist* 'defvar) "Defvar"
+      (getf *fcomp-print-handler-plist* 'defparameter) "Defparameter"
+      (getf *fcomp-print-handler-plist* 'defmacro) "Defmacro"
+      (getf *fcomp-print-handler-plist* 'defmethod) "Defmethod"  ; really want more than name (use the function option)
+      (getf *fcomp-print-handler-plist* 'defgeneric) "Defgeneric"
+      (getf *fcomp-print-handler-plist* 'defclass) "Defclass"
+      (getf *fcomp-print-handler-plist* 'deftype) "Deftype"
+      (getf *fcomp-print-handler-plist* 'defsetf) "Defsetf"
+      (getf *fcomp-print-handler-plist* 'defconstant) "Defconstant"
+      (getf *fcomp-print-handler-plist* 'defstruct) '("Defstruct" . t)
+      (getf *fcomp-print-handler-plist* 'include) '(nil . t))
+
+
+(defun fcomp-file (filename orig-file orig-offset env)  ; orig-file is back-translated
+  (let* ((*package* *package*)
+         (*compiling-file* filename)
+         (*nx-compile-time-types* *nx-compile-time-types*)
+         (*nx-proclaimed-inline* *nx-proclaimed-inline*)
+         (*nx-known-declarations* *nx-known-declarations*)
+         (*nx-proclaimed-ignore* *nx-proclaimed-ignore*)
+         (*nx-speed* *nx-speed*)
+         (*nx-space* *nx-space*)
+         (*nx-debug* *nx-debug*)
+         (*nx-safety* *nx-safety*)
+         (*nx-cspeed* *nx-cspeed*)
+         (*fcomp-load-time* t)
+         (*fcomp-output-list* nil)
+         (*fcomp-indentation* 0)
+         (*fcomp-last-compile-print* (cons nil (cons nil nil))))
+    (push (list $fasl-platform (backend-target-platform *fasl-backend*)) *fcomp-output-list*)
+    (fcomp-read-loop filename orig-file orig-offset env :not-compile-time)
+    (nreverse *fcomp-output-list*)))
+
+(defun fcomp-find-file (file &aux path)
+  (unless (or (setq path (probe-file file))
+              (setq path (probe-file (merge-pathnames file *.lisp-pathname*))))
+    (error 'file-error :pathname file :error-type "File ~S not found"))
+  (namestring path))
+
+;;; orig-file is back-translated when from fcomp-file
+;;; when from fcomp-include it's included filename merged with *compiling-file*
+;;; which is not back translated
+(defun fcomp-read-loop (filename orig-file orig-offset env processing-mode)
+  (when *compile-verbose*
+    (format t "~&;~A ~S..."
+            (if (eq filename *compiling-file*) "Compiling" " Including")
+            filename))
+  (with-open-file (stream filename
+                          :element-type 'base-char
+                          :external-format *fcomp-external-format*)
+    (let* ((old-file (and (neq filename *compiling-file*) *fasl-source-file*))
+           (*fasl-source-file* (or orig-file filename))
+           (*fcomp-toplevel-forms* nil)
+           (*fasl-eof-forms* nil)
+           (*loading-file-source-file* orig-file)
+           (*fcomp-source-note-map* (and (or *save-source-locations* *compile-code-coverage*)
+                                         (make-hash-table :test #'eq :shared nil)))
+           (*loading-toplevel-location* nil)
+           (*fcomp-loading-toplevel-location* nil)
+           (eofval (cons nil nil))
+           (read-package nil)
+           form)
+
+      (fcomp-output-form $fasl-src env *loading-file-source-file*)
+      (let* ((*fcomp-previous-position* nil))
+        (loop
+          (let* ((*fcomp-stream-position* (file-position stream))
+                 (*nx-warnings* nil)) ;; catch any warnings from :compile-toplevel forms
+            (when (and *fcomp-stream-position* orig-offset)
+              (incf *fcomp-stream-position* orig-offset))
+            (unless (eq read-package *package*)
+              (fcomp-compile-toplevel-forms env)
+              (setq read-package *package*))
+            (let ((*reading-for-cfasl*
+                   (and *fcomp-load-time* cfasl-load-time-eval-sym)))
+              (declare (special *reading-for-cfasl*))
+              (let ((pos (file-position stream)))
+                (handler-bind
+                    ((error #'(lambda (c) ; we should distinguish read errors from others?
+                                (format *error-output* "~&Read error between positions ~a and ~a in ~a." pos (file-position stream) filename)
+                                (signal c))))
+                  (multiple-value-setq (form *loading-toplevel-location*)
+                    (read-recording-source stream
+                                           :eofval eofval
+                                           :file-name *loading-file-source-file*
+                                           :start-offset orig-offset
+                                           :map *fcomp-source-note-map*
+                                           :save-source-text (neq *save-source-locations* :no-text))))))
+            (when (eq eofval form)
+	      (require-type *loading-toplevel-location* 'null)
+	      (return))
+            (fcomp-form form env processing-mode)
+            (fcomp-signal-or-defer-warnings *nx-warnings* env)
+            (setq *fcomp-previous-position* *fcomp-stream-position*))))
+      (when *compile-code-coverage*
+	(fcomp-compile-toplevel-forms env)
+        (let* ((fns (fcomp-code-covered-functions))
+	       (v (nreverse (coerce fns 'vector))))
+	  (map nil #'fcomp-digest-code-notes v)
+          (fcomp-random-toplevel-form `(register-code-covered-functions ',v) env)))
+      (while (setq form *fasl-eof-forms*)
+        (setq *fasl-eof-forms* nil)
+        (fcomp-form-list form env processing-mode))
+      (when old-file
+        (fcomp-output-form $fasl-src env (namestring *compile-file-pathname*)))
+      (fcomp-compile-toplevel-forms env))))
+
+(defun fcomp-code-covered-functions ()
+  (loop for op in *fcomp-output-list*
+        when (consp op)
+          nconc (if (eq (car op) $fasl-lfuncall)
+                  ;; Don't collect the toplevel lfun itself, it leads to spurious markings.
+                  ;; Instead, descend one level and collect any referenced fns.
+                  (destructuring-bind (fn) (cdr op)
+                    (lfunloop for imm in fn when (functionp imm) collect imm))
+                  (loop for arg in (cdr op) when (functionp arg) collect arg))))
+
+
+(defun fcomp-form (form env processing-mode
+                        &aux print-stuff 
+                        (load-time (and processing-mode (neq processing-mode :compile-time)))
+                        (compile-time-too (or (eq processing-mode :compile-time) 
+                                              (eq processing-mode :compile-time-too))))
+  (let* ((*fcomp-indentation* *fcomp-indentation*)
+         (*compile-print* *compile-print*))
+    (when *compile-print*
+      (cond ((and (consp form) (setq print-stuff (getf *fcomp-print-handler-plist* (car form))))
+             (rplaca (rplacd (cdr *fcomp-last-compile-print*) nil) nil)
+             (rplaca *fcomp-last-compile-print* nil)         
+             (let ((print-recurse nil))
+               (when (consp print-stuff)
+                 (setq print-recurse (cdr print-stuff) print-stuff (car print-stuff)))
+               (cond ((stringp print-stuff)
+                      (if (equal print-stuff "")
+                        (format t "~&~vT~S~%" *fcomp-indentation* (second form))
+                        (format t "~&~vT~S [~A]~%" *fcomp-indentation* (second form) print-stuff)))
+                     ((not (null print-stuff))
+                      (format t "~&~vT" *fcomp-indentation*)
+                      (funcall print-stuff form *standard-output*)
+                      (terpri *standard-output*)))
+               (if print-recurse
+                 (setq *fcomp-indentation* (+ *fcomp-indentation* 4))
+                 (setq *compile-print* nil))))
+            (t (unless (and (eq load-time (car *fcomp-last-compile-print*))
+                            (eq compile-time-too (cadr *fcomp-last-compile-print*))
+                            (eq *fcomp-indentation* (cddr *fcomp-last-compile-print*)))
+                 (rplaca *fcomp-last-compile-print* load-time)
+                 (rplaca (rplacd (cdr *fcomp-last-compile-print*) compile-time-too) *fcomp-indentation*)
+                 (format t "~&~vTToplevel Forms...~A~%"
+                         *fcomp-indentation*
+                         (if load-time
+                           (if compile-time-too
+                             "  (Compiletime, Loadtime)"
+                             "")
+                           (if compile-time-too
+                             "  (Compiletime)"
+                             "")))))))
+    (fcomp-form-1 form env processing-mode)))
+
+(defun fcomp-form-1 (form env processing-mode &aux sym body)
+  (if (consp form) (setq sym (%car form) body (%cdr form)))
+  (case sym
+    (progn (fcomp-form-list body env processing-mode))
+    (eval-when (fcomp-eval-when form env processing-mode))
+    (compiler-let (fcomp-compiler-let form env processing-mode))
+    (locally (fcomp-locally form env processing-mode))
+    (macrolet (fcomp-macrolet form env processing-mode))
+    (symbol-macrolet (fcomp-symbol-macrolet form env processing-mode))
+    ((%include include) (fcomp-include form env processing-mode))
+    (t
+     ;;Need to macroexpand to see if get more progn's/eval-when's and so should
+     ;;stay at toplevel.  But don't expand if either the evaluator or the
+     ;;compiler might not - better safe than sorry... 
+     ;; Good advice, but the hard part is knowing which is which.
+     (cond 
+       ((and (non-nil-symbol-p sym)
+             (macro-function sym env)
+             (not (compiler-macro-function sym env))
+             (not (eq sym '%defvar-init)) ;  a macro that we want to special-case
+             (multiple-value-bind (new win) (fcomp-macroexpand-1 form env)
+               (if win (setq form new))
+               win))
+        (fcomp-form form env processing-mode))
+       ((and (not *fcomp-inside-eval-always*)
+             (memq sym *fcomp-eval-always-functions*))
+        (let* ((*fcomp-inside-eval-always* t)
+               (new `(eval-when (:execute :compile-toplevel :load-toplevel) ,form)))
+          (fcomp-form-1 new env processing-mode)))
+       (t
+        (when (or (eq processing-mode :compile-time) (eq processing-mode :compile-time-too))
+          (%compile-time-eval form env))
+        (when (and processing-mode (neq processing-mode :compile-time))
+          (case sym
+            ((%defconstant) (fcomp-load-%defconstant form env))
+            ((%defparameter) (fcomp-load-%defparameter form env))
+            ((%defvar %defvar-init) (fcomp-load-defvar form env))
+            ((%defun) (fcomp-load-%defun form env))
+            ((set-package %define-package)
+             (fcomp-random-toplevel-form form env)
+             (fcomp-compile-toplevel-forms env))
+            ((%macro) (fcomp-load-%macro form env))
+            ;; ((%deftype) (fcomp-load-%deftype form))
+            ;; ((define-setf-method) (fcomp-load-define-setf-method form))
+            (t (fcomp-random-toplevel-form form env)))))))))
+
+(defun fcomp-form-list (forms env processing-mode)
+  (let* ((outer *loading-toplevel-location*))
+    (dolist (form forms)
+      (setq *loading-toplevel-location* (or (fcomp-source-note form) outer))
+      (fcomp-form form env processing-mode))
+    (setq *loading-toplevel-location* outer)))
+
+(defun fcomp-compiler-let (form env processing-mode &aux vars varinits (body (%cdr form)))
+  (fcomp-compile-toplevel-forms env)
+  (dolist (pair (car body))
+    (push (nx-pair-name pair) vars)
+    (push (%compile-time-eval (nx-pair-initform pair) env) varinits))
+  (progv (nreverse vars) (nreverse varinits)
+    (fcomp-form-list (cdr body) env processing-mode)
+    (fcomp-compile-toplevel-forms env)))
+
+(defun fcomp-locally (form env processing-mode &aux (body (%cdr form)))
+  (fcomp-compile-toplevel-forms env)
+  (multiple-value-bind (body decls) (parse-body body env)
+    (let* ((decl-specs (decl-specs-from-declarations decls))
+           (env (augment-environment env :declare decl-specs))
+           (*fasl-compile-time-env* (augment-environment *fasl-compile-time-env*
+                                                         :declare decl-specs)))
+      (fcomp-form-list body env processing-mode)
+      (fcomp-compile-toplevel-forms env))))
+
+(defun fcomp-macrolet (form env processing-mode &aux (body (%cdr form)))
+  (fcomp-compile-toplevel-forms env)
+  (flet ((augment-with-macros (e defs)
+           (augment-environment e
+                                :macro
+                                (mapcar #'(lambda (m)
+                                            (destructuring-bind (name arglist &body body) m
+                                              (list name (enclose (parse-macro name arglist body env)
+                                                                  e))))
+                                        defs))))
+           
+    (let* ((macros (car body))
+           (outer-env (augment-with-macros env macros)))
+      (multiple-value-bind (body decls) (parse-body (cdr body) outer-env)
+        (let* ((decl-specs (decl-specs-from-declarations decls))
+               (env (augment-environment 
+                     outer-env
+                     :declare decl-specs))
+               (*fasl-compile-time-env* (augment-environment
+                                         (augment-with-macros
+                                          *fasl-compile-time-env*
+                                          macros)
+                                         :declare decl-specs)))
+          (fcomp-form-list body env processing-mode)
+          (fcomp-compile-toplevel-forms env))))))
+
+(defun fcomp-symbol-macrolet (form env processing-mode &aux (body (%cdr form)))
+  (fcomp-compile-toplevel-forms env)
+  (let* ((defs (car body))
+         (outer-env (augment-environment env :symbol-macro defs)))
+    (multiple-value-bind (body decls) (parse-body (cdr body) env)
+      (let* ((decl-specs (decl-specs-from-declarations decls))
+             (env (augment-environment outer-env 
+                                       :declare decl-specs))
+             (*fasl-compile-time-env* (augment-environment *fasl-compile-time-env*
+                                                           :symbol-macro defs
+                                                           :declare decl-specs)))
+        (fcomp-form-list body env processing-mode)
+        (fcomp-compile-toplevel-forms env)))))
+
+(defun fcomp-eval-when (form env processing-mode &aux (body (%cdr form)) (eval-times (pop body)))
+  (let* ((compile-time-too  (eq processing-mode :compile-time-too))
+         (compile-time-only (eq processing-mode :compile-time))
+         (at-compile-time nil)
+         (at-load-time nil)
+         (at-eval-time nil))
+    (dolist (when eval-times)
+      (if (or (eq when 'compile) (eq when :compile-toplevel))
+        (setq at-compile-time t)
+        (if (or (eq when 'eval) (eq when :execute))
+          (setq at-eval-time t)
+          (if (or (eq when 'load) (eq when :load-toplevel))
+            (setq at-load-time t)
+            (warn "Unknown EVAL-WHEN time ~s in ~S while compiling ~S."
+                  when eval-times *fasl-source-file*)))))
+    (fcomp-compile-toplevel-forms env)        ; always flush the suckers
+    (cond (compile-time-only
+           (if at-eval-time (fcomp-form-list body env :compile-time)))
+          (at-load-time
+           (fcomp-form-list body env (if (or at-compile-time (and at-eval-time compile-time-too))
+                                       :compile-time-too
+                                       :not-compile-time)))
+          ((or at-compile-time (and at-eval-time compile-time-too))
+           (fcomp-form-list body env :compile-time))))
+  (fcomp-compile-toplevel-forms env))
+
+(defun fcomp-include (form env processing-mode &aux file)
+  (fcomp-compile-toplevel-forms env)
+  (verify-arg-count form 1 1)
+  (setq file (nx-transform (%cadr form) env))
+  (unless (constantp file) (report-bad-arg file '(or string pathname)))
+  (let ((actual (merge-pathnames (eval-constant file)
+                                 (directory-namestring *compiling-file*))))
+    (when *compile-print* (format t "~&~vTIncluding file ~A~%" *fcomp-indentation* actual))
+    (let ((*fcomp-indentation* (+ 4 *fcomp-indentation*))
+          (*package* *package*))
+      (fcomp-read-loop (fcomp-find-file actual) actual 0 env processing-mode)
+      (fcomp-output-form $fasl-src env *loading-file-source-file*))
+    (when *compile-print* (format t "~&~vTFinished included file ~A~%" *fcomp-indentation* actual))))
+
+(defun define-compile-time-constant (symbol initform env)
+  (note-variable-info symbol t env)
+  (let ((compile-time-defenv (definition-environment *fasl-compile-time-env*))
+        (definition-env (definition-environment env)))
+    (when (or compile-time-defenv definition-env)
+      (multiple-value-bind (value error) 
+                           (ignore-errors (values (%compile-time-eval initform env) nil))
+        (when error
+          (warn "Compile-time evaluation of DEFCONSTANT initial value form for ~S while ~
+                 compiling ~S signalled the error: ~&~A" symbol *fasl-source-file* error))
+        (let ((cell (cons symbol (if error (%unbound-marker-8) value))))
+          (when definition-env
+            (push cell (defenv.constants definition-env)))
+          (when compile-time-defenv
+            (push cell (defenv.constants compile-time-defenv))))))
+    symbol))
+
+(defun fcomp-load-%defconstant (form env)
+  (destructuring-bind (sym valform &optional doc) (cdr form)
+    (unless *fasl-save-doc-strings*
+      (setq doc nil))
+    (if (quoted-form-p sym)
+      (setq sym (%cadr sym)))
+    (if (and (typep sym 'symbol) (or (quoted-form-p valform) (self-evaluating-p valform)))
+      (fcomp-output-form $fasl-defconstant env sym (eval-constant valform) (eval-constant doc))
+      (fcomp-random-toplevel-form form env))))
+
+(defun fcomp-load-%defparameter (form env)
+  (destructuring-bind (sym valform &optional doc) (cdr form)
+    (unless *fasl-save-doc-strings*
+      (setq doc nil))
+    (if (quoted-form-p sym)
+      (setq sym (%cadr sym)))
+    (let* ((sym-p (typep sym 'symbol))
+           (fn (and sym-p (fcomp-function-arg valform env))))
+      (if (and sym-p (or fn (constantp valform)))
+        (fcomp-output-form $fasl-defparameter env sym (or fn (eval-constant valform)) (eval-constant doc))
+        (fcomp-random-toplevel-form form env)))))
+
+; Both the simple %DEFVAR and the initial-value case (%DEFVAR-INIT) come here.
+; Only try to dump this as a special fasl operator if the initform is missing
+;  or is "harmless" to evaluate whether needed or not (constant or function.)
+; Hairier initforms could be handled by another fasl operator that takes a thunk
+; and conditionally calls it.
+(defun fcomp-load-defvar (form env)
+  (destructuring-bind (sym &optional (valform nil val-p) doc) (cdr form)
+    (unless *fasl-save-doc-strings*
+      (setq doc nil))
+    (if (quoted-form-p sym)             ; %defvar quotes its arg, %defvar-init doesn't.
+      (setq sym (%cadr sym)))
+    (let* ((sym-p (typep sym 'symbol)))
+      (if (and sym-p (not val-p))
+        (fcomp-output-form $fasl-defvar env sym)
+        (let* ((fn (if sym-p (fcomp-function-arg valform env))))
+          (if (and sym-p (or fn (constantp valform)))
+            (fcomp-output-form $fasl-defvar-init env sym (or fn (eval-constant valform)) (eval-constant doc))
+            (fcomp-random-toplevel-form form env)))))))
+      
+(defun define-compile-time-macro (name lambda-expression env)
+  (let ((compile-time-defenv (definition-environment *fasl-compile-time-env*))
+        (definition-env (definition-environment env)))
+    (when (or definition-env compile-time-defenv)
+      (let ((cell (list* name 
+                         'macro 
+                         (compile-named-function lambda-expression :name name :env env))))
+        (when compile-time-defenv
+          (push cell (defenv.functions compile-time-defenv)))
+        (when definition-env
+          (push cell (defenv.functions definition-env))))
+      (record-function-info name (%cons-def-info 'defmacro) env))
+    name))
+
+(defun define-compile-time-symbol-macro (name expansion env)
+  (let ((compile-time-defenv (definition-environment *fasl-compile-time-env*))
+        (definition-env (definition-environment env)))
+    (let* ((info (variable-information name env)))
+      (when (or (eq info :special)
+                (eq info :constant))
+        (signal-program-error "Can't define ~s as a symbol-macro; already defined as a ~a." name (string-downcase info))))
+    (when (or definition-env compile-time-defenv)
+      (let ((cell (cons name expansion)))
+        (when compile-time-defenv
+          (push cell (defenv.symbol-macros compile-time-defenv)))
+        (when definition-env
+          (push cell (defenv.symbol-macros definition-env)))))
+    name))
+
+
+(defun fcomp-proclaim-type (type syms env)
+  (if (every #'symbolp syms)
+    (progn
+      (specifier-type-if-known type env :whine t)
+      (dolist (sym syms)
+        (push (cons sym type) *nx-compile-time-types*)))
+    (nx-bad-decls `(,type ,@syms))))
+
+(defun compile-time-proclamation (specs env &aux  sym (defenv (definition-environment env)))
+  (when defenv
+    (dolist (spec specs)
+      (setq sym (pop spec))
+      (case sym
+        (type
+         (fcomp-proclaim-type (car spec) (cdr spec) env))
+        (special
+         (if (every #'symbolp spec)
+           (dolist (sym spec)
+             (push (cons sym nil) (defenv.specials defenv)))
+           (nx-bad-decls `(,sym ,@spec))))
+        (notspecial
+         (if (every #'symbolp spec)
+           (let ((specials (defenv.specials defenv)))
+             (dolist (sym spec (setf (defenv.specials defenv) specials))
+               (let ((pair (assq sym specials)))
+                 (when pair (setq specials (nremove pair specials))))))
+           (nx-bad-decls `(,sym ,@spec))))
+        (optimize
+           (handler-case (%proclaim-optimize spec)
+             (program-error () (nx-bad-decls `(,sym ,@spec)))))
+        (inline
+         (if (every (lambda (v) (or (symbolp v) (setf-function-name-p v))) spec)
+           (dolist (sym spec)
+             (push (cons (maybe-setf-function-name sym) (cons 'inline 'inline)) (lexenv.fdecls defenv)))
+           (nx-bad-decls `(,sym ,@spec))))
+        (notinline
+         (if (every (lambda (v) (or (symbolp v) (setf-function-name-p v))) spec)
+           (dolist (sym spec)
+             (unless (compiler-special-form-p sym)
+               (push (cons (maybe-setf-function-name sym) (cons 'inline 'notinline)) (lexenv.fdecls defenv))))
+           (nx-bad-decls `(,sym ,@spec))))
+        (declaration
+         (if (every #'symbolp spec)
+           (dolist (sym spec)
+             (pushnew sym *nx-known-declarations*))
+           (nx-bad-decls `(,sym ,@spec))))
+        (ignore
+         (if (every #'symbolp spec)
+           (dolist (sym spec)
+             (push (cons sym t) *nx-proclaimed-ignore*))
+           (nx-bad-decls `(,sym ,@spec))))
+        (unignore
+         (if (every #'symbolp spec)
+           (dolist (sym spec)
+             (push (cons sym nil) *nx-proclaimed-ignore*))
+           (nx-bad-decls `(,sym ,@spec))))
+        (ftype 
+         (let ((ftype (car spec))
+               (fnames (cdr spec)))
+           (if (every (lambda (v) (or (symbolp v) (setf-function-name-p v))) fnames)
+             (when (specifier-type-if-known ftype env :whine t)
+               ;; ----- this part may be redundant, now that the lexenv.fdecls part is being done
+               (if (and (consp ftype)
+                        (consp fnames)
+                        (eq (%car ftype) 'function))
+                 (dolist (fname fnames)
+                   (note-function-info fname nil env)))
+               (dolist (fname fnames)
+                 (push (list* (maybe-setf-function-name fname) sym ftype) (lexenv.fdecls defenv))))
+             (nx-bad-decls `(ftype ,@spec)))))
+        (otherwise
+	 (unless (memq sym *nx-known-declarations*)
+	   ;; Any type name is now (ANSI CL) a valid declaration.
+	   (if (specifier-type-if-known sym env)
+	     (fcomp-proclaim-type sym spec env)
+	     (nx-bad-decls `(,sym ,@spec)))))))))
+
+(defun fcomp-load-%defun (form env)
+  (destructuring-bind (fn &optional doc) (cdr form)
+    (unless *fasl-save-doc-strings*
+      (if (consp doc)
+        (if (and (eq (car doc) 'quote) (consp (cadr doc)))
+          (setf (car (cadr doc)) nil))
+        (setq doc nil)))
+    (when (and (consp fn) (eq (%car fn) 'nfunction))
+      (note-function-info (cadr fn) (caddr fn) env))
+    (if (and (constantp doc)
+             (setq fn (fcomp-function-arg fn env)))
+      (progn
+        (setq doc (eval-constant doc))
+        (fcomp-output-form $fasl-defun env fn doc))
+      (fcomp-random-toplevel-form form env))))
+
+(defun fcomp-load-%macro (form env &aux fn doc)
+  (verify-arg-count form 1 2)
+  (if (and (constantp (setq doc (caddr form)))
+           (setq fn (fcomp-function-arg (cadr form) env)))
+    (progn
+      (setq doc (eval-constant doc))
+      (fcomp-output-form $fasl-macro env fn doc))
+    (fcomp-random-toplevel-form form env)))
+
+(defun define-compile-time-structure (sd refnames predicate env)
+  (let ((defenv (definition-environment env)))
+    (when defenv
+      (when (non-nil-symbolp (sd-name sd))
+	(note-type-info (sd-name sd) 'class env)
+        (push (make-instance 'compile-time-class :name (sd-name sd))
+              (defenv.classes defenv)))
+      (setf (defenv.structures defenv) (alist-adjoin (sd-name sd) sd (defenv.structures defenv)))
+      (let* ((structrefs (defenv.structrefs defenv)))
+        (when (and (null (sd-type sd))
+                   predicate)
+          (setq structrefs (alist-adjoin predicate (sd-name sd) structrefs)))
+        (dolist (slot (sd-slots sd))
+          (unless (fixnump (ssd-name slot))
+            (setq structrefs
+                (alist-adjoin (if refnames (pop refnames) (ssd-name slot))
+                              (ssd-type-and-refinfo slot)
+                              structrefs))))
+        (setf (defenv.structrefs defenv) structrefs)))))
+
+(defun fcomp-source-note (form &aux (notes *fcomp-source-note-map*))
+  (and notes (gethash form notes)))
+
+(defun fcomp-note-source-transformation (original new)
+  (let* ((*nx-source-note-map* *fcomp-source-note-map*))
+    (nx-note-source-transformation original new)))
+
+(defun fcomp-macroexpand-1 (form env)
+  (handler-bind ((warning (lambda (c)
+                            (nx1-whine :program-error c)
+                            (muffle-warning c)))
+                 (program-error (lambda (c)
+                                  (if *fasl-break-on-program-errors*
+                                    (cerror "continue compilation ignoring this form" c)
+                                    (progn
+                                      (when (typep c 'compile-time-program-error)
+                                        (setq c (make-condition 'simple-program-error
+                                                  :format-control (simple-condition-format-control c)
+                                                  :format-arguments (simple-condition-format-arguments c))))
+                                      (nx1-whine :program-error c)))
+                                  (return-from fcomp-macroexpand-1 (values nil t)))))
+    (let* ((*nx-source-note-map* *fcomp-source-note-map*))
+      (multiple-value-bind (new win)
+          (macroexpand-1 form env)
+        (when win
+          (nx-note-source-transformation form new))
+        (values new win)))))
+
+(defun fcomp-transform (form env)
+  (let* ((*nx-source-note-map* *fcomp-source-note-map*))
+    (nx-transform form env)))
+
+
+(defun fcomp-random-toplevel-form (form env)
+  (unless (constantp form)
+    (unless (or (atom form)
+                (compiler-special-form-p (%car form)))
+      ;;Pre-compile any lfun args.  This is an efficiency hack, since compiler
+      ;;reentering itself for inner lambdas tends to be more expensive than
+      ;;top-level compiles.
+      ;;This assumes the form has been macroexpanded, or at least none of the
+      ;;non-evaluated macro arguments could look like functions.
+      (let ((new-form (make-list (length form))))
+        (declare (dynamic-extent new-form))
+        (loop for arg in (%cdr form) for newptr on (%cdr new-form)
+              do (setf (%car newptr)
+                       (multiple-value-bind (new win) (fcomp-transform arg env)
+                         (let ((lfun (fcomp-function-arg new env)))
+                           (when lfun
+                             (setq new `',lfun win t)
+                             (fcomp-note-source-transformation arg new)))
+                         (if win new arg))))
+        (unless (every #'eq (%cdr form) (%cdr new-form))
+          (setf (%car new-form) (%car form))
+          (fcomp-note-source-transformation form (setq form (copy-list new-form))))))
+    ;; At some point we will dump the toplevel forms, make sure that when that happens,
+    ;;; the loading location for this form is stored in *fcomp-loading-toplevel-location*,
+    ;; because *loading-toplevel-location* will be long gone by then.
+    (fcomp-ensure-source env)
+    (push form *fcomp-toplevel-forms*)))
+
+(defun fcomp-function-arg (expr env)
+  (when (consp expr)
+    (multiple-value-bind (lambda-expr name win)
+        (cond ((and (eq (%car expr) 'nfunction)
+                    (lambda-expression-p (cadr (%cdr expr))))
+               (values (%caddr expr) (%cadr expr) t))
+              ((and (eq (%car expr) 'function)
+                    (lambda-expression-p (car (%cdr expr))))
+               (values (%cadr expr) nil t)))
+      (when win
+        (fcomp-named-function lambda-expr name env
+                              (or (fcomp-source-note expr)
+                                  (fcomp-source-note lambda-expr)
+                                  *loading-toplevel-location*))))))
+
+(defun fcomp-compile-toplevel-forms (env)
+  (when *fcomp-toplevel-forms*
+    (let* ((forms (nreverse *fcomp-toplevel-forms*))
+           (*fcomp-stream-position* *fcomp-previous-position*)
+	   (*loading-toplevel-location* *fcomp-loading-toplevel-location*)
+           (lambda (if T ;; (null (cdr forms))
+                     `(lambda () ,@forms)
+                     `(lambda ()
+                        (macrolet ((load-time-value (value)
+                                     (declare (ignore value))
+                                     (compiler-function-overflow)))
+                          ,@forms)))))
+      (setq *fcomp-toplevel-forms* nil)
+      ;(format t "~& Random toplevel form: ~s" lambda)
+      (handler-case (fcomp-output-form
+                     $fasl-lfuncall
+                     env
+                     (fcomp-named-function lambda nil env *loading-toplevel-location*))
+        (compiler-function-overflow ()
+          (if (null (cdr forms))
+            (error "Form ~s cannot be compiled - size exceeds compiler limitation"
+                   (%car forms))
+            ; else compile each half :
+            (progn
+              (dotimes (i (floor (length forms) 2))
+                (declare (fixnum i))
+                (push (pop forms) *fcomp-toplevel-forms*))
+              (fcomp-compile-toplevel-forms env)
+              (setq *fcomp-toplevel-forms* (nreverse forms))
+              (fcomp-compile-toplevel-forms env))))))))
+
+(defun fcomp-ensure-source (env)
+  ;; if source location saving is off, both values are NIL, so this will do nothing,
+  ;; don't need to check explicitly.
+  (unless (eq *fcomp-loading-toplevel-location* *loading-toplevel-location*)
+    (setq *fcomp-loading-toplevel-location* *loading-toplevel-location*)
+    (fcomp-output-form $fasl-toplevel-location env *loading-toplevel-location*)))
+
+(defun fcomp-output-form (opcode env &rest args)
+  (fcomp-ensure-source env)
+  (when *fcomp-toplevel-forms* (fcomp-compile-toplevel-forms env))
+  (push (cons opcode args) *fcomp-output-list*))
+
+
+;;; Compile a lambda expression for the sole purpose of putting it in a fasl
+;;; file.  The result will not be funcalled.  This really shouldn't bother
+;;; making an lfun, but it's simpler this way...
+(defun fcomp-named-function (def name env &optional source-note)
+  (let* ((env (new-lexical-environment env))
+         (*nx-break-on-program-errors* (not (memq *fasl-break-on-program-errors* '(nil :defer)))))
+    (multiple-value-bind (lfun warnings)
+        (compile-named-function def
+                                :name name
+                                :env env
+                                :function-note source-note
+                                :keep-lambda *fasl-save-definitions*
+                                :keep-symbols *fasl-save-local-symbols*
+                                :policy *default-file-compilation-policy*
+                                :source-notes *fcomp-source-note-map*
+                                :load-time-eval-token cfasl-load-time-eval-sym
+                                :target *fasl-target*)
+      (fcomp-signal-or-defer-warnings warnings env)
+      lfun)))
+
+
+;; Convert parent-notes to immediate indices.  The reason this is necessary is to avoid hitting
+;; the fasdumper's 64K limit on multiply-referenced objects.  This removes the reference
+;; from parent slots, making notes less likely to be multiply-referenced.
+(defun fcomp-digest-code-notes (lfun &optional refs)
+  (unless (memq lfun refs)
+    (let* ((lfv (function-to-function-vector lfun))
+	   (start #+ppc-target 0 #+x86-target (%function-code-words lfun))
+	   (refs (cons lfun refs)))
+      (declare (dynamic-extent refs))
+      (loop for i from start below (uvsize lfv) as imm = (uvref lfv i)
+	    do (typecase imm
+		 (code-note
+		  (let* ((parent (code-note-parent-note imm))
+			 (pos (when (code-note-p parent)
+				(loop for j from start below i
+				      do (when (eq parent (uvref lfv j)) (return j))))))
+		    (when pos
+		      (setf (code-note-parent-note imm) pos))))
+		 (function
+		  (fcomp-digest-code-notes imm refs)))))))
+
+; For now, defer only UNDEFINED-REFERENCEs, signal all others via WARN.
+; Well, maybe not WARN, exactly.
+(defun fcomp-signal-or-defer-warnings (warnings env)
+  (let ((init (null *fcomp-warnings-header*))
+        (some *fasl-warnings-signalled-p*)
+        (harsh *fasl-non-style-warnings-signalled-p*))
+    (dolist (w warnings)
+      (unless (compiler-warning-source-note w)
+        (setf (compiler-warning-source-note w)
+              (make-source-note :source nil
+                                :filename *fasl-source-file*
+                                :start-pos *fcomp-stream-position*
+                                :end-pos *fcomp-stream-position*)))
+      (if (and (typep w 'undefined-reference) 
+               (eq w (setq w (macro-too-late-p w env))))
+        (push w *fasl-deferred-warnings*)
+        (progn
+          (multiple-value-setq (harsh some *fcomp-warnings-header*)
+                               (signal-compiler-warning w init *fcomp-warnings-header* harsh some))
+          (setq init nil))))
+    (setq *fasl-warnings-signalled-p* some
+          *fasl-non-style-warnings-signalled-p* harsh)))
+
+; If W is an UNDEFINED-FUNCTION-REFERENCE which refers to a macro (either at compile-time in ENV
+; or globally), cons up a MACRO-USED-BEFORE-DEFINITION warning and return it; else return W.
+
+(defun macro-too-late-p (w env)
+  (let* ((args (compiler-warning-args w))
+         (name (car args)))
+    (if (typep w 'undefined-function-reference)
+      (if (or (macro-function name)
+	      (let* ((defenv (definition-environment env))
+		     (info (if defenv (assq name (defenv.functions defenv)))))
+		(and (consp (cdr info))
+		     (eq 'macro (cadr info)))))
+	  (make-instance 'macro-used-before-definition
+	    :source-note (compiler-warning-source-note w)
+	    :function-name (compiler-warning-function-name w)
+	    :warning-type ':macro-used-before-definition
+	    :args args)
+	  w)
+      w)))
+
+
+              
+;;;;          fasl-scan - dumping reference counting
+;;;;
+;;;;
+;These should be constants, but it's too much trouble when need to change 'em.
+(defparameter FASL-FILE-ID #xFF00)  ;Overall file format, shouldn't change much
+(defparameter FASL-VERSION #xFF5e)  ;Fasl block format. ($fasl-vers)
+
+(defvar *fasdump-hash*)
+(defvar *fasdump-read-package*)
+(defvar *fasdump-global-offsets*)
+(defvar *make-load-form-hash*)
+
+;;;Return a hash table containing subexp's which are referenced more than once.
+(defun fasl-scan (forms)
+  (let* ((*fasdump-hash* (make-hash-table :size (length forms)          ; Crude estimate
+                                          :rehash-threshold 0.9
+                                          :test 'eq
+					  :shared nil))
+         (*make-load-form-hash* (make-hash-table :test 'eq :shared nil))
+         (*fasdump-read-package* nil)
+         (*fasdump-global-offsets* nil)
+         (gsymbols nil))
+    (dolist (op forms)
+      (if (packagep op) ; old magic treatment of *package*
+        (setq *fasdump-read-package* op)
+        (dolist (arg (cdr op)) (fasl-scan-form arg))))
+
+    #-bccl (when (eq *compile-verbose* :debug)
+             (format t "~&~S forms, ~S entries -> "
+                     (length forms)
+                     (hash-table-count *fasdump-hash*)))
+    (maphash #'(lambda (key val)
+                 (when (%izerop val) (remhash key *fasdump-hash*)))
+             *fasdump-hash*)
+    #-bccl (when (eq *compile-verbose* :debug)
+             (format t "~S." (hash-table-count *fasdump-hash*)))
+    (values *fasdump-hash*
+            gsymbols
+            *fasdump-global-offsets*)))
+
+;;; During scanning, *fasdump-hash* values are one of the following:
+;;;  nil - form hasn't been referenced yet.
+;;;   0 - form has been referenced exactly once
+;;;   T - form has been referenced more than once
+;;;  (load-form scanning-p referenced-p initform)
+;;;     form should be replaced by load-form
+;;;     scanning-p is true while we're scanning load-form
+;;;     referenced-p is nil if unreferenced,
+;;;                     T if referenced but not dumped yet,
+;;;                     0 if dumped already (fasl-dump-form uses this)
+;;;     initform is a compiled version of the user's initform
+(defun fasl-scan-form (form)
+  (when form
+    (let ((info (gethash form *fasdump-hash*)))
+      (cond ((null info)
+             (fasl-scan-dispatch form))
+            ((eql info 0)
+             (puthash form *fasdump-hash* t))
+            ((listp info)               ; a make-load-form form
+             (when (cadr info)
+               (error "Circularity in ~S for ~S" 'make-load-form form))
+             (let ((referenced-cell (cddr info)))
+               (setf (car referenced-cell) t)   ; referenced-p
+               (setf (gethash (car info) *fasdump-hash*) t)))))))
+
+
+
+
+(defun fasl-scan-dispatch (exp)
+  (when exp
+    (let ((type-code (typecode exp)))
+      (declare (fixnum type-code))
+      (case type-code
+        (#.target::tag-fixnum
+         (fasl-scan-fixnum exp))
+        (#.target::fulltag-cons (fasl-scan-list exp))
+        #+ppc32-target
+        (#.ppc32::tag-imm)
+        #+ppc64-target
+        ((#.ppc64::fulltag-imm-0
+          #.ppc64::fulltag-imm-1
+          #.ppc64::fulltag-imm-2
+          #.ppc64::fulltag-imm-3))
+	#+x8632-target
+	(#.x8632::tag-imm)
+        #+x8664-target
+        ((#.x8664::fulltag-imm-0
+          #.x8664::fulltag-imm-1))
+        (t
+         (if
+           #+ppc32-target
+           (= (the fixnum (logand type-code ppc32::full-tag-mask)) ppc32::fulltag-immheader)
+           #+ppc64-target
+           (= (the fixnum (logand type-code ppc64::lowtagmask)) ppc64::lowtag-immheader)
+	   #+x8632-target
+	   (= (the fixnum (logand type-code x8632::fulltagmask)) x8632::fulltag-immheader)
+           #+x8664-target
+           (and (= (the fixnum (lisptag exp)) x8664::tag-misc)
+                (logbitp (the (unsigned-byte 16) (logand type-code x8664::fulltagmask))
+                         (logior (ash 1 x8664::fulltag-immheader-0)
+                                 (ash 1 x8664::fulltag-immheader-1)
+                                 (ash 1 x8664::fulltag-immheader-2))))
+           (case type-code
+             (#.target::subtag-dead-macptr (fasl-unknown exp))
+             (#.target::subtag-macptr
+              ;; Treat untyped pointers to the high/low 64K of the address
+              ;; space as constants.  Refuse to dump other pointers.
+              (unless (and (zerop (%macptr-type exp))
+                           (<= (%macptr-domain exp) 1))
+                (error "Can't dump typed pointer ~s" exp))
+              (let* ((addr (%ptr-to-int exp)))
+                (unless (or (< addr #x10000)
+                            (>= addr (- (ash 1 target::nbits-in-word)
+                                        #x10000)))
+                  (error "Can't dump pointer ~s : address is not in the low or high 64K of the address space." exp))))
+             (t (fasl-scan-ref exp)))
+           (case type-code
+             ((#.target::subtag-pool #.target::subtag-weak #.target::subtag-lock) (fasl-unknown exp))
+             (#+ppc-target #.target::subtag-symbol
+              #+x8632-target #.target::subtag-symbol
+              #+x8664-target #.target::tag-symbol (fasl-scan-symbol exp))
+             ((#.target::subtag-instance #.target::subtag-struct)
+              (fasl-scan-user-form exp))
+             (#.target::subtag-package (fasl-scan-ref exp))
+             (#.target::subtag-istruct
+              (if (memq (istruct-type-name exp) *istruct-make-load-form-types*)
+                (progn
+                  (if (hash-table-p exp)
+                    (fasl-lock-hash-table exp))
+                  (fasl-scan-user-form exp))
+                (fasl-scan-gvector exp)))
+	     #+x8632-target
+	     (#.target::subtag-function (fasl-scan-clfun exp))
+             #+x8664-target
+             (#.target::tag-function (fasl-scan-clfun exp))
+             (t (fasl-scan-gvector exp)))))))))
+              
+
+(defun fasl-scan-ref (form)
+  (puthash form *fasdump-hash* 0))
+
+(defun fasl-scan-fixnum (fixnum)
+  (unless (short-fixnum-p fixnum) (fasl-scan-ref fixnum)))
+
+(defparameter *istruct-make-load-form-types*
+  '(lexical-environment shared-library-descriptor shared-library-entry-point
+    external-entry-point foreign-variable
+    ctype unknown-ctype class-ctype foreign-ctype union-ctype member-ctype 
+    array-ctype numeric-ctype hairy-ctype named-ctype constant-ctype args-ctype
+    hash-table package-ref type-cell class-cell slot-id))
+
+
+
+
+(defun fasl-scan-gvector (vec)
+  (fasl-scan-ref vec)
+  (dotimes (i (uvsize vec)) 
+    (declare (fixnum i))
+    (fasl-scan-form (%svref vec i))))
+
+#+x86-target
+(defun fasl-scan-clfun (f)
+  (let* ((fv (function-to-function-vector f))
+         (size (uvsize fv))
+         (ncode-words (%function-code-words f)))
+    (fasl-scan-ref f)
+    (do* ((k ncode-words (1+ k)))
+         ((= k size))
+      (fasl-scan-form (uvref fv k)))))
+
+(defun funcall-lfun-p (form)
+  (and (listp form)
+       (eq (%car form) 'funcall)
+       (listp (%cdr form))
+       (or (functionp (%cadr form))
+           (eql (typecode (%cadr form)) target::subtag-xfunction))
+       (null (%cddr form))))
+
+;;; We currently represent istruct-cells as conses.  That's not
+;;; incredibly efficient (among other things, we have to do this
+;;; check when scanning/dumping any list), but it's probably not
+;;; worth burning a tag on them.  There are currently about 50
+;;; entries on the *istruct-cells* list.
+(defun istruct-cell-p (x)
+  (and (consp x)
+       (typep (%car x) 'symbol)
+       (atom (%cdr x))
+       (not (null (memq x *istruct-cells*)))))
+
+(defun fasl-scan-list (list)
+  (cond ((eq (%car list) cfasl-load-time-eval-sym)
+         (let ((form (car (%cdr list))))
+           (fasl-scan-form (if (funcall-lfun-p form)
+                             (%cadr form)
+                             form))))
+        ((istruct-cell-p list)
+         (fasl-scan-form (%car list)))
+        (t (when list
+             (fasl-scan-ref list)
+             (fasl-scan-form (%car list))
+             (fasl-scan-form (%cdr list))))))
+
+(defun fasl-scan-user-form (form)
+  (when (or (source-note-p form)
+            (code-note-p form))
+    (return-from fasl-scan-user-form (fasl-scan-gvector form)))
+  (multiple-value-bind (load-form init-form) (make-load-form form *fcomp-load-forms-environment*)
+    (labels ((simple-load-form (form)
+               (or (atom form)
+                   (let ((function (car form)))
+                     (or (eq function 'quote)
+                         (and (symbolp function)
+                              ;; using fboundp instead of symbol-function
+                              ;; see comments in symbol-function
+                              (or (functionp (fboundp function))
+                                  (eq function 'progn))
+                              ;; (every #'simple-load-form (cdr form))
+                              (dolist (arg (cdr form) t)
+                                (unless (simple-load-form arg)
+                                  (return nil))))))))
+             (load-time-eval-form (load-form form type)
+               (cond ((quoted-form-p load-form)
+                      (%cadr load-form))
+                     ((self-evaluating-p load-form)
+                      load-form)
+                     ((simple-load-form load-form)
+                      `(,cfasl-load-time-eval-sym ,load-form))
+                     (t (multiple-value-bind (lfun warnings)
+                                             (or
+                                              (gethash load-form *make-load-form-hash*)
+                                              (fcomp-named-function `(lambda () ,load-form) nil nil))
+                          (when warnings
+                            (cerror "Ignore the warnings"
+                                    "Compiling the ~s ~a form for~%~s~%produced warnings."
+                                    'make-load-form type form))
+                          (setf (gethash load-form *make-load-form-hash*) lfun)
+                          `(,cfasl-load-time-eval-sym (funcall ,lfun)))))))
+      (declare (dynamic-extent #'simple-load-form #'load-time-eval-form))
+      (let* ((compiled-initform
+              (and init-form (load-time-eval-form init-form form "initialization")))
+             (info (list (load-time-eval-form load-form form "creation")
+                         T              ; scanning-p
+                         nil            ; referenced-p
+                         compiled-initform  ;initform-info
+                         )))
+        (puthash form *fasdump-hash* info)
+        (fasl-scan-form (%car info))
+        (setf (cadr info) nil)        ; no longer scanning load-form
+        (when init-form
+          (fasl-scan-form compiled-initform))))))
+
+(defun fasl-scan-symbol (form)
+  (fasl-scan-ref form)
+  (fasl-scan-form (symbol-package form)))
+  
+
+
+;;;;          Pass 3 - dumping
+;;;;
+;;;;
+(defvar *fasdump-epush*)
+(defvar *fasdump-stream*)
+(defvar *fasdump-eref*)
+
+(defun fasl-dump-file (gnames goffsets forms hash filename)
+  (let ((opened? nil)
+        (finished? nil))
+    (unwind-protect
+      (with-open-file (*fasdump-stream* filename :direction :output
+                                        :element-type '(unsigned-byte 8)
+                                        :if-exists :supersede
+                                        :if-does-not-exist :create)
+        (setq opened? t)
+        (fasl-set-filepos 0)
+        (fasl-out-word 0)             ;Will become the ID word
+        (fasl-out-word 1)             ;One block in the file
+        (fasl-out-long 12)            ;Block starts at file pos 12
+        (fasl-out-long 0)             ;Length will go here
+        (fasl-dump-block gnames goffsets forms hash)  ;Write the block
+        (let ((pos (fasl-filepos)))
+          (fasl-set-filepos 8)        ;Back to length longword
+          (fasl-out-long (- pos 12))) ;Write length
+        (fasl-set-filepos 0)          ;Seem to have won, make us legal
+        (fasl-out-word FASL-FILE-ID)
+        (setq finished? t)
+        filename)
+      (when (and opened? (not finished?))
+        (delete-file filename)))))
+
+(defun fasl-dump-block (gnames goffsets forms hash)
+  (let ((etab-size (hash-table-count hash)))
+    (when (> etab-size 65535)
+      (error "Too many multiply-referenced objects in fasl file.~%Limit is ~d. Were ~d." 65535 etab-size))
+    (fasl-out-word FASL-VERSION)          ; Word 0
+    (fasl-out-long  0)
+    (fasl-out-byte $fasl-vetab-alloc)
+    (fasl-out-count etab-size)
+    (fasl-dump gnames goffsets forms hash)
+    (fasl-out-byte $fasl-end)))
+
+(defun fasl-dump (gnames goffsets forms hash)
+  (let* ((*fasdump-hash* hash)
+         (*fasdump-read-package* nil)
+         (*fasdump-epush* nil)
+         (*fasdump-eref* -1)
+         (*fasdump-global-offsets* goffsets))
+    (when gnames
+      (fasl-out-byte $fasl-globals)
+      (fasl-dump-form gnames))
+    (dolist (op forms)
+      (if (packagep op)
+        (setq *fasdump-read-package* op)
+        (progn
+          (fasl-out-byte (car op))
+          (dolist (arg (cdr op)) (fasl-dump-form arg)))))))
+
+;;;During dumping, *fasdump-hash* values are one of the following:
+;;;   nil - form has no load form, is referenced at most once.
+;;;   fixnum - form has already been dumped, fixnum is the etab index.
+;;;   T - form hasn't been dumped yet, is referenced more than once.
+;;;  (load-form . nil) - form should be replaced by load-form.
+(defun fasl-dump-form (form)
+  (let ((info (gethash form *fasdump-hash*)))
+    (cond ((fixnump info)
+           (fasl-out-byte $fasl-veref)
+           (fasl-out-count info))
+          ((consp info)
+           (fasl-dump-user-form form info))
+          (t
+           (setq *fasdump-epush* info)
+           (fasl-dump-dispatch form)))))
+
+(defun fasl-dump-user-form (form info)
+  (let* ((load-form (car info))
+         (referenced-p (caddr info))
+         (initform (cadddr info)))
+    (when referenced-p
+      (unless (gethash load-form *fasdump-hash*)
+        (error "~s was not in ~s.  This shouldn't happen." 'load-form '*fasdump-hash*)))
+    (when initform
+      (fasl-out-byte $fasl-prog1))      ; ignore the initform
+    (fasl-dump-form load-form)
+    (when referenced-p
+      (setf (gethash form *fasdump-hash*) (gethash load-form *fasdump-hash*)))
+    (when initform
+      (fasl-dump-form initform))))
+
+(defun fasl-out-opcode (opcode form)
+  (if *fasdump-epush*
+    (progn
+      (setq *fasdump-epush* nil)
+      (fasl-out-byte (fasl-epush-op opcode))
+      (fasl-dump-epush form))
+    (fasl-out-byte opcode)))
+
+(defun fasl-dump-epush (form)
+  #-bccl (when (fixnump (gethash form *fasdump-hash*))
+           (error "Bug! Duplicate epush for ~S" form))
+  (puthash form *fasdump-hash* (setq *fasdump-eref* (1+ *fasdump-eref*))))
+
+
+(defun fasl-dump-dispatch (exp)
+  (etypecase exp
+    ((signed-byte 16) (fasl-dump-s16 exp))
+    ((signed-byte 32) (fasl-dump-s32 exp))
+    ((signed-byte 64) (fasl-dump-s64 exp))
+    (bignum (fasl-dump-32-bit-ivector exp $fasl-bignum32))
+    (character (fasl-dump-char exp))
+    (list (fasl-dump-list exp))
+    (immediate (fasl-dump-t_imm exp))
+    (double-float (fasl-dump-dfloat exp))
+    (single-float (fasl-dump-sfloat exp))
+    (simple-string
+     (let* ((nextra (utf-8-extra-bytes exp)))
+       (cond ((= 0 nextra)
+              (fasl-out-opcode $fasl-nvstr exp)
+              (fasl-out-nvstring exp))
+             (t (fasl-out-opcode $fasl-vstr exp)
+                (fasl-out-vstring exp nextra)))))
+    (simple-bit-vector (fasl-dump-bit-vector exp))
+    ((simple-array (unsigned-byte 8) (*))
+     (fasl-dump-8-bit-ivector exp $fasl-u8-vector))
+    ((simple-array (signed-byte 8) (*))
+     (fasl-dump-8-bit-ivector exp $fasl-s8-vector))
+    ((simple-array (unsigned-byte 16) (*))
+     (fasl-dump-16-bit-ivector exp $fasl-u16-vector))
+    ((simple-array (signed-byte 16) (*))
+     (fasl-dump-16-bit-ivector exp $fasl-s16-vector))
+    ((simple-array (unsigned-byte 32) (*))
+     (fasl-dump-32-bit-ivector exp $fasl-u32-vector))
+    ((simple-array (signed-byte 32) (*))
+     (fasl-dump-32-bit-ivector exp $fasl-s32-vector))
+    ((simple-array single-float (*))
+     (fasl-dump-32-bit-ivector exp $fasl-single-float-vector))
+    ((simple-array double-float (*))
+     (fasl-dump-double-float-vector exp))
+    (symbol (fasl-dump-symbol exp))
+    (package (fasl-dump-package exp))
+    (function (fasl-dump-function exp))
+    (xfunction (fasl-dump-function exp))
+    (code-vector (fasl-dump-codevector exp))
+    (xcode-vector (fasl-dump-codevector exp))
+    (simple-vector (fasl-dump-gvector exp $fasl-t-vector))
+    (ratio (fasl-dump-ratio exp))
+    (complex (fasl-dump-complex exp))
+    #+(and 64-bit-target (not cross-compiling))
+    ((simple-array (unsigned-byte 64) (*))
+     (fasl-dump-64-bit-ivector exp $fasl-u64-vector))
+    #+(and 64-bit-target (not cross-compiling))
+    ((simple-array (signed-byte 64) (*))
+     (fasl-dump-64-bit-ivector exp $fasl-s64-vector))
+    (ivector
+     (unless (eq (backend-target-arch-name *target-backend*)
+                 (backend-target-arch-name *host-backend*))
+       (error "can't cross-compile constant reference to ~s" exp))
+     (let* ((typecode (typecode exp))
+            (n (uvsize exp))
+            (nb (subtag-bytes typecode n)))
+       (declare (fixnum n nb typecode))
+       (fasl-out-opcode $fasl-vivec exp)
+       (fasl-out-byte typecode)
+       (fasl-out-count n)
+       (fasl-out-ivect exp 0 nb)))
+    (vector (fasl-dump-gvector exp $fasl-vector-header))
+    (array (fasl-dump-gvector exp $fasl-array-header))
+
+    (gvector
+     (if (= (typecode exp) target::subtag-istruct)
+       (fasl-dump-gvector exp $fasl-istruct)
+       (progn
+         (unless (eq (backend-target-arch-name *target-backend*)
+                     (backend-target-arch-name *host-backend*))
+           (error "can't cross-compile constant reference to ~s" exp))
+         (let* ((typecode (typecode exp))
+                (n (uvsize exp)))
+           (declare (fixnum n typecode))
+           (fasl-out-opcode $fasl-vgvec exp)
+           (fasl-out-byte typecode)
+           (fasl-out-count n)
+           (dotimes (i n)
+             (fasl-dump-form (%svref exp i)))))))))
+
+(defun fasl-dump-gvector (v op)
+  (let* ((n (uvsize v)))
+    (fasl-out-opcode op v)
+    (fasl-out-count n)
+    (dotimes (i n)
+      (fasl-dump-form (%svref v i)))))
+
+(defun fasl-dump-ratio (v)
+  (fasl-out-opcode $fasl-ratio v)
+  (fasl-dump-form (%svref v target::ratio.numer-cell))
+  (fasl-dump-form (%svref v target::ratio.denom-cell)))
+
+(defun fasl-dump-complex (v)
+  (fasl-out-opcode $fasl-complex v)
+  (fasl-dump-form (%svref v target::complex.realpart-cell))
+  (fasl-dump-form (%svref v target::complex.imagpart-cell)))
+
+(defun fasl-dump-bit-vector (v)
+  (let* ((n (uvsize v)))
+    (fasl-out-opcode $fasl-bit-vector v)
+    (fasl-out-count n)
+    (if (eq *fasl-host-big-endian* *fasl-target-big-endian*)
+      (let* ((nb (ash (+ n 7) -3)))
+        (fasl-out-ivect v 0 nb))
+      (compiler-bug "need to byte-swap ~a" v))))
+
+(defun fasl-dump-8-bit-ivector (v op)
+  (let* ((n (uvsize v)))
+    (fasl-out-opcode op v)
+    (fasl-out-count n)
+    (let* ((nb n))
+      (fasl-out-ivect v 0 nb))))
+
+(defun fasl-dump-16-bit-ivector (v op)
+  (let* ((n (uvsize v)))
+    (fasl-out-opcode op v)
+    (fasl-out-count n)
+    (if (eq *fasl-host-big-endian* *fasl-target-big-endian*)
+      (let* ((nb (ash n 1)))
+        (fasl-out-ivect v 0 nb))
+      (dotimes (i n)
+        (let* ((k (uvref v i)))
+          (fasl-out-byte (ldb (byte 8 0) k))
+          (fasl-out-byte (ldb (byte 8 8) k)))))))
+
+(defun fasl-dump-32-bit-ivector (v op)
+  (let* ((n (uvsize v)))
+    (fasl-out-opcode op v)
+    (fasl-out-count n)
+    (if (eq *fasl-host-big-endian* *fasl-target-big-endian*)
+      (let* ((nb (ash n 2)))
+        (fasl-out-ivect v 0 nb))
+      (dotimes (i n)
+        (let* ((k (uvref v i)))
+          (fasl-out-byte (ldb (byte 8 0) k))
+          (fasl-out-byte (ldb (byte 8 8) k))
+          (fasl-out-byte (ldb (byte 8 16) k))
+          (fasl-out-byte (ldb (byte 8 24) k)))))))
+
+
+(defun fasl-dump-64-bit-ivector (v op)
+  (let* ((n (uvsize v)))
+    (fasl-out-opcode op v)
+    (fasl-out-count n)
+    (if (eq *fasl-host-big-endian* *fasl-target-big-endian*)
+      (let* ((nb (ash n 3)))
+        (fasl-out-ivect v 0 nb))
+      (compiler-bug "need to byte-swap ~a" v))))
+
+(defun fasl-dump-double-float-vector (v)
+  (let* ((n (uvsize v)))
+    (fasl-out-opcode $fasl-double-float-vector v)
+    (fasl-out-count n)
+    (if (eq *fasl-host-big-endian* *fasl-target-big-endian*)
+      (let* ((nb (ash n 3)))
+        (fasl-out-ivect v (- target::misc-dfloat-offset
+                             target::misc-data-offset) nb))
+      (compiler-bug "need to byte-swap ~a" v))))
+
+;;; This is used to dump functions and "xfunctions".
+;;; If we're cross-compiling, we shouldn't reference any
+;;; (host) functions as constants; try to detect that
+;;; case.
+#-x86-target
+(defun fasl-dump-function (f)
+  (if (and (not (eq *fasl-backend* *host-backend*))
+           (typep f 'function))
+    (compiler-bug "Dumping a native function constant ~s during cross-compilation." f))
+  (if (and (= (typecode f) target::subtag-xfunction)
+           (= (typecode (uvref f 0)) target::subtag-u8-vector))
+    (fasl-xdump-clfun f)
+    (let* ((n (uvsize f)))
+      (fasl-out-opcode $fasl-function f)
+      (fasl-out-count n)
+      (dotimes (i n)
+        (fasl-dump-form (%svref f i))))))
+
+#+x86-target
+(defun fasl-dump-function (f)
+  (if (and (not (eq *fasl-backend* *host-backend*))
+           (typep f 'function))
+    (compiler-bug "Dumping a native function constant ~s during cross-compilation." f))
+  (if (and (= (typecode f) target::subtag-xfunction)
+           (= (typecode (uvref f 0)) target::subtag-u8-vector))
+    (fasl-xdump-clfun f)
+    (let* ((code-size (%function-code-words f))
+           (function-vector (function-to-function-vector f))
+           (function-size (uvsize function-vector)))
+      (fasl-out-opcode $fasl-clfun f)
+      (fasl-out-count function-size)
+      (fasl-out-count code-size)
+      (fasl-out-ivect function-vector 0 (ash code-size target::word-shift))
+      (do* ((k code-size (1+ k)))
+           ((= k function-size))
+        (declare (fixnum k))
+        (fasl-dump-form (uvref function-vector k))))))
+        
+
+  
+
+;;; Write a "concatenated function".
+(defun fasl-xdump-clfun (f)
+  (target-arch-case
+   (:x8632
+    (let* ((code (uvref f 0))
+	   (function-size (ash (uvsize code) -2))
+	   (imm-words (dpb (uvref code 1) (byte 8 8) (uvref code 0)))
+	   (imm-bytes (ash imm-words 2))
+	   (other-words (- function-size imm-words)))
+      (assert (= other-words (1- (uvsize f))))
+      (fasl-out-opcode $fasl-clfun f)
+      (fasl-out-count function-size)
+      (fasl-out-count imm-words)
+      (fasl-out-ivect code 0 imm-bytes)
+      (do ((i 1 (1+ i))
+	   (n (uvsize f)))
+	  ((= i n))
+	(declare (fixnum i n))
+	(fasl-dump-form (%svref f i)))))
+   (:x8664
+    (let* ((code (uvref f 0))
+	   (code-size (dpb (uvref code 3)
+			   (byte 8 24)
+			   (dpb (uvref code 2)
+				(byte 8 16)
+				(dpb (uvref code 1)
+				     (byte 8 8)
+				     (uvref code 0)))))
+	   (function-size (ash (uvsize code) -3)))
+      (assert (= (- function-size code-size) (1- (uvsize f))))
+      (fasl-out-opcode $fasl-clfun f)
+      (fasl-out-count function-size)
+      (fasl-out-count code-size)
+      (fasl-out-ivect code 0 (ash code-size 3))
+      (do* ((i 1 (1+ i))
+	    (n (uvsize f)))
+	   ((= i n))
+	(declare (fixnum i n))
+	(fasl-dump-form (%svref f i)))))))
+
+(defun fasl-dump-codevector (c)
+  (if (and (not (eq *fasl-backend* *host-backend*))
+           (typep c 'code-vector))
+    (compiler-bug "Dumping a native code-vector constant ~s during cross-compilation." c))
+  (let* ((n (uvsize c)))
+    (fasl-out-opcode $fasl-code-vector c)
+    (fasl-out-count n)
+    (fasl-out-ivect c)))
+
+(defun fasl-dump-t_imm (imm)
+  (fasl-out-opcode $fasl-timm imm)
+  (fasl-out-long (%address-of imm)))
+
+(defun fasl-dump-char (char)     ; << maybe not
+  (let ((code (%char-code char)))
+    (fasl-out-opcode $fasl-char char)
+    (fasl-out-count code)))
+
+;;; Always write big-endian.
+(defun fasl-dump-s16 (s16)
+  (fasl-out-opcode $fasl-word-fixnum s16)
+  (fasl-out-word s16))
+
+;;; Always write big-endian
+(defun fasl-dump-s32 (s32)
+  (fasl-out-opcode $fasl-s32 s32)
+  (fasl-out-word (ldb (byte 16 16) s32))
+  (fasl-out-word (ldb (byte 16 0) s32)))
+
+;;; Always write big-endian
+(defun fasl-dump-s64 (s64)
+  (fasl-out-opcode $fasl-s64 s64)
+  (fasl-out-word (ldb (byte 16 48) s64))
+  (fasl-out-word (ldb (byte 16 32) s64))
+  (fasl-out-word (ldb (byte 16 16) s64))
+  (fasl-out-word (ldb (byte 16 0) s64)))
+
+
+
+(defun fasl-dump-dfloat (float)
+  (fasl-out-opcode $fasl-dfloat float)
+  (multiple-value-bind (high low) (double-float-bits float)
+    (fasl-out-long high)
+    (fasl-out-long low)))
+
+(defun fasl-dump-sfloat (float)
+  (fasl-out-opcode $fasl-sfloat float)
+  (fasl-out-long (single-float-bits float)))
+
+
+(defun fasl-dump-package (pkg)
+  (let* ((name (package-name pkg))
+         (nextra (utf-8-extra-bytes name)))
+    (cond ((eql nextra 0)
+           (fasl-out-opcode $fasl-nvpkg pkg)
+           (fasl-out-nvstring name))
+          (t
+           (fasl-out-opcode $fasl-vpkg pkg)
+           (fasl-out-vstring name nextra)))))
+
+
+
+(defun fasl-dump-list (list)
+  (cond ((null list) (fasl-out-opcode $fasl-nil list))
+        ((eq (%car list) cfasl-load-time-eval-sym)
+         (let* ((form (car (%cdr list)))
+                (opcode $fasl-eval))
+           (when (funcall-lfun-p form)
+             (setq opcode $fasl-lfuncall
+                   form (%cadr form)))
+           (if *fasdump-epush*
+             (progn
+               (fasl-out-byte (fasl-epush-op opcode))
+               (fasl-dump-form form)
+               (fasl-dump-epush list))
+             (progn
+               (fasl-out-byte opcode)
+               (fasl-dump-form form)))))
+        ((istruct-cell-p list)
+         (fasl-out-opcode $fasl-istruct-cell (car list))
+         (fasl-dump-symbol (car list)))
+        (t (fasl-dump-cons list))))
+
+(defun fasl-dump-cons (cons &aux (end cons) (cdr-len 0))
+  (declare (fixnum cdr-len))
+  (while (and (consp (setq end (%cdr end)))
+              (null (gethash end *fasdump-hash*)))
+    (incf cdr-len))
+  (if (eql 0 cdr-len)
+    (fasl-out-opcode $fasl-cons cons)
+    (progn
+      (fasl-out-opcode (if end $fasl-vlist* $fasl-vlist) cons)
+      (fasl-out-count cdr-len)))
+  (dotimes (i (the fixnum (1+ cdr-len)))
+    (fasl-dump-form (%car cons))
+    (setq cons (%cdr cons)))
+  (when (or (eql 0 cdr-len) end)      ;cons or list*
+    (fasl-dump-form end)))
+
+
+
+(defun fasl-dump-symbol (sym)
+  (let* ((pkg (symbol-package sym))
+         (name (symbol-name sym))
+         (nextra (utf-8-extra-bytes name))
+         (ascii (eql nextra 0))
+         (idx (let* ((i (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.binding-index-cell)))
+                (declare (fixnum i))
+                (unless (zerop i) i))))
+    (cond ((null pkg) 
+           (progn 
+             (fasl-out-opcode (if idx
+                                (if ascii $fasl-nvmksym-special $fasl-vmksym-special)
+                                (if ascii $fasl-nvmksym $fasl-vmksym))
+                              sym)
+             (if ascii
+               (fasl-out-nvstring name)
+               (fasl-out-vstring name nextra))))
+          (*fasdump-epush*
+           (progn
+             (fasl-out-byte (fasl-epush-op (if idx
+                                             (if ascii $fasl-nvpkg-intern-special $fasl-vpkg-intern-special)
+                                             (if ascii $fasl-nvpkg-intern $fasl-vpkg-intern))))
+             (fasl-dump-form pkg)
+             (fasl-dump-epush sym)
+             (if ascii
+               (fasl-out-nvstring name)
+               (fasl-out-vstring name nextra))))
+          (t
+           (progn
+             (fasl-out-byte (if idx
+                              (if ascii $fasl-nvpkg-intern-special $fasl-vpkg-intern-special)
+                              (if ascii $fasl-nvpkg-intern-special $fasl-vpkg-intern)))
+             (fasl-dump-form pkg)
+             (if ascii
+               (fasl-out-nvstring name)
+               (fasl-out-vstring name nextra)))))))
+
+
+(defun fasl-unknown (exp)
+  (error "Can't dump ~S - unknown type" exp))
+
+(defun fasl-out-simple-string (str start end)
+  (declare (simple-string str) (fixnum start end))
+  (do* ((k start (1+ k)))
+       ((= k end))
+    (declare (fixnum k))
+    (fasl-out-byte (char-code (schar str k)))))
+
+(defun fasl-out-nvstring (str)
+  (fasl-out-count (length str))
+  (fasl-out-simple-string str 0 (length str)))
+
+(defun utf-8-extra-bytes (string)
+  (declare (simple-string string))
+  (let* ((extra 0))
+    (declare (fixnum extra))
+    (dotimes (i (length string) extra)
+      (let* ((code (%scharcode string i)))
+        (declare ((mod #x110000) code))
+        (cond ((>= code #x10000) (incf extra 3))
+              ((>= code #x800) (incf extra 2))
+              ((>= code #x80) (incf extra 1)))))))
+
+(defun fasl-out-vstring (str nextra)
+  (declare (fixnum nextra))
+  (let* ((len (length str)))
+    (declare (fixnum len))
+    (fasl-out-count len)
+    (fasl-out-count nextra)
+    (dotimes (i len)
+      (let* ((code (%scharcode str i)))
+        (declare ((mod #x110000) code))
+        (cond ((< code #x80) (fasl-out-byte code))
+              ((< code #x800)
+               (let* ((y (ldb (byte 5 6) code))
+                      (z (ldb (byte 6 0) code)))
+                 (declare (fixnum y z))
+                 (fasl-out-byte (logior #xc0 y))
+                 (fasl-out-byte (logior #x80 z))))
+              ((< code #x10000)
+               (let* ((x (ldb (byte 4 12) code))
+                      (y (ldb (byte 6 6) code))
+                      (z (ldb (byte 6 0) code)))
+                 (declare (fixnum x y z))
+                 (fasl-out-byte (logior #xe0 x))
+                 (fasl-out-byte (logior #x80 y))
+                 (fasl-out-byte (logior #x80 z))))
+              (t
+                (let* ((w (ldb (byte 3 18) code))
+                       (x (ldb (byte 6 12) code))
+                       (y (ldb (byte 6 6) code))
+                       (z (ldb (byte 6 0) code)))
+                  (declare (fixnum w x y z))
+                  (fasl-out-byte (logior #xf0 w))
+                  (fasl-out-byte (logior #x80 x))
+                  (fasl-out-byte (logior #x80 y))
+                  (fasl-out-byte (logior #x80 z)))))))))
+
+
+(defun fasl-out-ivect (iv &optional 
+                          (start 0) 
+                          (nb 
+			   (subtag-bytes (typecode iv) (uvsize iv))))
+  (stream-write-ivector *fasdump-stream* iv start nb))
+
+
+(defun fasl-out-long (long)
+  (fasl-out-word (ash long -16))
+  (fasl-out-word (logand long #xFFFF)))
+
+(defun fasl-out-word (word)
+  (fasl-out-byte (ash word -8))
+  (fasl-out-byte word))
+
+(defun fasl-out-byte (byte)
+  (write-byte (%ilogand2 byte #xFF) *fasdump-stream*))
+
+;;; Write an unsigned integer in 7-bit chunks.
+(defun fasl-out-count (val)
+  (do* ((b (ldb (byte 7 0) val) (ldb (byte 7 0) val))
+        (done nil))
+       (done)
+    (when (zerop (setq val (ash val -7)))
+      (setq b (logior #x80 b) done t))
+    (fasl-out-byte b)))
+
+(defun fasl-filepos ()
+  (file-position *fasdump-stream*))
+
+(defun fasl-set-filepos (pos)
+  (file-position *fasdump-stream* pos)
+  #-bccl (unless (eq (file-position *fasdump-stream*) pos)
+           (error "Unable to set file position to ~S" pos)))
+
+;;; Concatenate fasl files.
+
+;;; Format of a fasl file as expected by the fasloader.
+;;;
+;;; #xFF00         2 bytes - File version
+;;; Block Count    2 bytes - Number of blocks in the file
+;;; addr[0]        4 bytes - address of 0th block
+;;; length[0]      4 bytes - length of 0th block
+;;; addr[1]        4 bytes - address of 1st block
+;;; length[1]      4 bytes - length of 1st block
+;;; ...
+;;; addr[n-1]      4 bytes
+;;; length[n-1]    4 bytes
+;;; length[0] + length[1] + ... + length [n-1] bytes of data
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; (fasl-concatenate out-file fasl-files &key :if-exists)
+;;
+;; out-file     name of file in which to store the concatenation
+;; fasl-files   list of names of fasl files to concatenate
+;; if-exists    as for OPEN, defaults to :error
+;;
+;; function result: pathname to the output file.
+;; It works to use the output of one invocation of fasl-concatenate
+;; as an input of another invocation.
+;;
+(defun fasl-concatenate (out-file fasl-files &key (if-exists :error))
+  (%fasl-concatenate out-file fasl-files if-exists (pathname-type *.fasl-pathname*)))
+
+(defun %fasl-concatenate (out-file fasl-files if-exists file-ext)
+  (let ((count 0)
+        (created? nil)
+        (finished? nil)
+	(ext-pathname (make-pathname :type file-ext)))
+    (declare (fixnum count))
+    (flet ((fasl-read-halfword (f)
+	     (dpb (read-byte f) (byte 8 8) (read-byte f)))
+	   (fasl-write-halfword (h f)
+	     (write-byte (ldb (byte 8 8) h) f)
+	     (write-byte (ldb (byte 8 0) h) f)
+	     h))
+      (flet ((fasl-read-fullword (f)
+	       (dpb (fasl-read-halfword f) (byte 16 16) (fasl-read-halfword f)))
+	     (fasl-write-fullword (w f)
+	       (fasl-write-halfword (ldb (byte 16 16) w) f)
+	       (fasl-write-halfword (ldb (byte 16 0) w) f)
+	       w))
+	(dolist (file fasl-files)
+	  (setq file (merge-pathnames file ext-pathname))
+	  (unless (equal (pathname-type file) file-ext)
+	    (error "Not a ~A file: ~s" file-ext file))
+	  (with-open-file (instream file :element-type '(unsigned-byte 8))
+	    (unless (eql fasl-file-id (fasl-read-halfword instream))
+	      (error "Bad ~A file ID in ~s" file-ext file))
+	    (incf count (fasl-read-halfword instream))))
+	(unwind-protect
+	     (with-open-file (outstream
+			      (setq out-file (merge-pathnames out-file ext-pathname))
+			      :element-type '(unsigned-byte 8)
+			      :direction :output
+			      :if-does-not-exist :create
+			      :if-exists if-exists)
+	       (setq created? t)
+	       (let ((addr-address 4)
+		     (data-address (+ 4 (* count 8))))
+		 (fasl-write-halfword 0 outstream) ;  will be $fasl-id
+		 (fasl-write-halfword count outstream)
+		 (dotimes (i (* 2 count))
+		   (fasl-write-fullword 0 outstream)) ; for addresses/lengths
+		 (dolist (file fasl-files)
+		   (with-open-file (instream (merge-pathnames file ext-pathname)
+					     :element-type '(unsigned-byte 8))
+		     (fasl-read-halfword instream) ; skip ID
+		     (let* ((fasl-count (fasl-read-halfword instream))
+			    (addrs (make-array fasl-count))
+			    (sizes (make-array fasl-count))
+			    addr0)
+		       (declare (fixnum fasl-count)
+				(dynamic-extent addrs sizes))
+		       (dotimes (i fasl-count)
+			 (setf (svref addrs i) (fasl-read-fullword instream)
+			       (svref sizes i) (fasl-read-fullword instream)))
+		       (setq addr0 (svref addrs 0))
+		       (file-position outstream addr-address)
+		       (dotimes (i fasl-count)
+			 (fasl-write-fullword
+			  (+ data-address (- (svref addrs i) addr0))
+			  outstream)
+			 (fasl-write-fullword (svref sizes i) outstream)
+			 (incf addr-address 8))
+		       (file-position outstream data-address)
+		       (dotimes (i fasl-count)
+			 (file-position instream (svref addrs i))
+			 (let ((fasl-length (svref sizes i)))
+			   (dotimes (j fasl-length)
+			     (write-byte (read-byte instream) outstream))
+			   (incf data-address fasl-length))))))
+		 (stream-length outstream data-address)
+		 (file-position outstream 0)
+		 (fasl-write-halfword fasl-file-id outstream)
+		 (setq finished? t)))
+	  (when (and created? (not finished?))
+	    (delete-file out-file))))
+      out-file)))
+
+;;; Cross-compilation environment stuff.  Some of this involves
+;;; setting up the TARGET and OS packages.
+(defun ensure-package-nickname (name package)
+  (let* ((old (find-package name)))
+    (unless (eq old package)
+      (rename-package old (package-name old) (delete name (package-nicknames old) :test #'string=))
+      (rename-package package (package-name package) (cons name (package-nicknames package)))
+      old)))
+
+(defmacro with-cross-compilation-package ((name target) &body body)
+  (let* ((old-package (gensym))
+         (name-var (gensym))
+         (target-var (gensym)))
+    `(let* ((,name-var ,name)
+            (,target-var ,target)
+            (,old-package (ensure-package-nickname ,name-var ,target-var)))
+      (unwind-protect
+           (progn ,@body)
+        (when ,old-package (ensure-package-nickname ,name-var
+                                                          ,old-package))))))
+
+(defun %with-cross-compilation-target (target thunk)
+  (let* ((backend (find-backend target)))
+    (if (null backend)
+      (error "No known compilation target named ~s." target)
+      (let* ((arch (backend-target-arch backend))
+             (arch-package-name (arch::target-package-name arch))
+             (ftd (backend-target-foreign-type-data backend))
+             (ftd-package-name (ftd-interface-package-name ftd)))
+        (or (find-package arch-package-name)
+            (make-package arch-package-name))
+        (or (find-package ftd-package-name)
+            (make-package ftd-package-name :use "COMMON-LISP"))
+        (with-cross-compilation-package ("OS" ftd-package-name)
+          (with-cross-compilation-package ("TARGET" arch-package-name)
+            (let* ((*target-ftd* ftd))
+               (funcall thunk))))))))
+
+(defmacro with-cross-compilation-target ((target) &body body)
+  `(%with-cross-compilation-target ,target #'(lambda () ,@body)))
+             
+
+  
+
+(provide 'nfcomp)
+
Index: /branches/new-random/lib/number-case-macro.lisp
===================================================================
--- /branches/new-random/lib/number-case-macro.lisp	(revision 13309)
+++ /branches/new-random/lib/number-case-macro.lisp	(revision 13309)
@@ -0,0 +1,109 @@
+;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;;;;;;;;
+;; support fns and vars for number-case
+
+(defun type-name-to-code (name)
+  (funcall (arch::target-numeric-type-name-to-typecode-function
+            (backend-target-arch *target-backend*))
+           name))
+
+(defvar nd-onions `((integer fixnum bignum) (rational fixnum bignum ratio)
+                    (float double-float short-float)
+                    (real fixnum bignum ratio double-float short-float)
+                    (number fixnum bignum ratio double-float short-float complex)))
+
+(defun nd-diff (x y) ; things in x that are not in y
+  (let ((res))
+    (dolist (e x)
+      (when (not (memq e y))(push e res)))
+    res))
+
+(defun nd-type-compose (selectors)
+  ;; this could do better but probably not worth the trouble - only
+  ;; for require-type error
+  (or (dolist (union nd-onions)
+        (if (when (eq (length selectors)(length (cdr union)))
+              (dolist (e selectors t)(if (not (memq e (cdr union)))(return))))
+          (return (car union))))
+      (cons 'or selectors)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Simpler number dispatch. Syntax is just like case.
+;;
+;; (number-case x                 =>         (case (typecode x)
+;;     (fixnum (print 4))		        (target::tag-fixnum (print 4)) ; actually tag value
+;;     ((bignum ratio)(print 5)))		((target::tag-bignum target::tag-ratio)(print 5))
+;;	                      			(t (require-type x 'rational)))) 
+;;						  
+
+(defmacro number-case (var &rest cases)
+  (let ((selectors-so-far)
+        (t-case nil)
+        (tag (gensym))
+        (block (gensym)))
+    (flet ((maybe-compound (selector)
+             (let ((compound (cdr (assq selector nd-onions))))
+               (when compound
+                 (setq compound (nd-diff compound selectors-so-far))
+                 (when (not compound)(error "Unreachable case ~s" selector))
+                 (setq selectors-so-far
+                       (append compound selectors-so-far))
+                 compound))))
+      (declare (dynamic-extent #'maybe-compound))
+      `(block ,block
+         (tagbody 
+           ,tag
+           (return-from ,block              
+             (case (typecode ,var)
+               ,@(mapcar 
+                  #'(lambda (case)
+                      (let ((selector (car case)))
+                        (if (atom selector)
+                          (cond ((eq selector t)(setq t-case t))
+                                ((memq selector selectors-so-far)(error "Unreachable case ~s" selector))
+                                ((let ((compound (maybe-compound selector)))
+                                   (when compound
+                                     (setq selector compound))))
+                                (t (push selector selectors-so-far)))
+                          (progn
+                            (setq selector
+                                  (mapcan #'(lambda (item)
+                                              (cond ((memq item selectors-so-far))
+                                                    ((let ((compound (maybe-compound item)))
+                                                       (when compound
+                                                         (setq item compound))))
+                                                    (t (push item selectors-so-far)))
+                                              (if (listp item) item (list item)))
+                                          selector))))
+                        (setq selector (if (listp selector)
+                                         (mapcar #'type-name-to-code selector)
+                                         (if (eq selector t) t
+                                             (type-name-to-code selector))))
+                        `(,selector ,@(cdr case))))
+                  cases)
+               ,@(if (not t-case)
+                   `((t (setq ,var (%kernel-restart $xwrongtype ,var ',(nd-type-compose selectors-so-far)))
+                        (go ,tag)))))))))))
+
+(provide "NUMBER-CASE-MACRO")
Index: /branches/new-random/lib/number-macros.lisp
===================================================================
--- /branches/new-random/lib/number-macros.lisp	(revision 13309)
+++ /branches/new-random/lib/number-macros.lisp	(revision 13309)
@@ -0,0 +1,141 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "LISPEQU")
+  )
+
+(declare-arch-specific-macro %make-sfloat)
+
+(declare-arch-specific-macro %make-dfloat)
+
+(defmacro require-null-or-double-float-sym (sym)
+  (setq sym (require-type sym 'symbol))
+  `(when (and ,sym (not (double-float-p ,sym)))
+     (setq ,sym (require-type ,sym 'double-float))))
+
+
+(declare-arch-specific-macro %numerator)
+
+(declare-arch-specific-macro %denominator)
+
+(declare-arch-specific-macro %realpart)
+
+(declare-arch-specific-macro %imagpart)
+
+
+(defmacro with-stack-double-floats (specs &body body)
+  (collect ((binds)
+            (inits)
+            (names))
+    (dolist (spec specs)
+      (let ((name (first spec)))
+        (binds `(,name (%make-dfloat)))
+        (names name)
+        (let ((init (second spec)))
+          (when init
+            (inits `(%double-float ,init ,name))))))
+    `(let* ,(binds)
+      (declare (dynamic-extent ,@(names))
+               (double-float ,@(names)))
+      ,@(inits)
+      ,@body)))
+
+
+
+
+
+
+ ;;; WITH-BIGNUM-BUFFERS  --  Internal.
+  ;;;
+  ;;; Could do freelisting someday. NAH
+  ;;;
+(defmacro with-bignum-buffers (specs &body body)  ; <<
+  "WITH-BIGNUM-BUFFERS ({(var size [init])}*) Form*"
+  (collect ((binds)
+	    (inits)
+	    (names))
+    (dolist (spec specs)
+      (let ((name (first spec))
+            (size (second spec)))
+        (binds `(,name (allocate-typed-vector :bignum ,size)))
+        (names name)          
+        (let ((init (third spec)))
+          (when init
+            (inits `(bignum-replace ,name ,init))))))
+    `(let* ,(binds)
+       (declare (dynamic-extent ,@(names)))
+       ,@(inits)
+       ,@body)))
+
+;;; call fn on possibly stack allocated negative of a and/or b
+;;; args better be vars - we dont bother with once-only
+(defmacro with-negated-bignum-buffers (a b fn)
+  `(let* ((len-a (%bignum-length ,a))
+          (len-b (%bignum-length ,b))
+          (a-plusp (bignum-plusp ,a))
+          (b-plusp (bignum-plusp ,b)))
+     (declare (type bignum-index len-a len-b))
+     (if (and a-plusp b-plusp)
+       (,fn ,a ,b )
+       (if (not a-plusp)
+         (with-bignum-buffers ((a1 (1+ len-a)))
+           (negate-bignum ,a nil a1)
+           (if b-plusp
+             (,fn a1 ,b)
+             (with-bignum-buffers ((b1 (1+ len-b)))
+               (negate-bignum ,b nil b1)
+               (,fn a1 b1))))
+         (with-bignum-buffers ((b1 (1+ len-b)))
+           (negate-bignum ,b nil b1)
+           (,fn ,a b1))))))
+
+(defmacro with-one-negated-bignum-buffer (a fn)
+  `(if (bignum-plusp ,a)
+    (,fn ,a)
+    (with-bignum-buffers ((a1 (1+ (%bignum-length ,a))))
+      (negate-bignum ,a nil a1)
+      (,fn a1))))
+
+
+(defmacro fixnum-to-bignum-set (big fix)
+  `(%fixnum-to-bignum-set ,big ,fix))
+
+(defmacro with-small-bignum-buffers (specs &body body)
+  (collect ((binds)
+	    (inits)
+	    (names))
+    (dolist (spec specs)
+      (let ((name (first spec)))
+	(binds `(,name (allocate-typed-vector :bignum
+                        ,(target-word-size-case (32 1)
+                                                (64 2)))))
+                        
+	(names name)
+	(let ((init (second spec)))
+	  (when init
+	    (inits `(fixnum-to-bignum-set ,name ,init))))))
+    `(let* ,(binds)
+      (declare (dynamic-extent ,@(names)))
+      ,@(inits)
+      ,@body)))
+
+(provide "NUMBER-MACROS")
+
+;;; end of number-macros.lisp
Index: /branches/new-random/lib/numbers.lisp
===================================================================
--- /branches/new-random/lib/numbers.lisp	(revision 13309)
+++ /branches/new-random/lib/numbers.lisp	(revision 13309)
@@ -0,0 +1,814 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; Lib;numbers.lisp - Lisp arithmetic code.
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+ (require :number-macros)
+ (require :number-case-macro)
+ #+(and cross-compiling 64-bit-target)
+ (declaim (ftype function %single-float-atanh %single-float-acosh
+                 %single-float-asinh %single-float-tanh
+                 %single-float-cosh %single-float-sinh)))
+
+
+
+(defconstant double-float-positive-infinity
+  #.(let* ((division-by-zero (get-fpu-mode  :division-by-zero)))
+      (declare (notinline /))
+      (unwind-protect
+           (progn
+             (ccl:set-fpu-mode :division-by-zero nil)
+             (/ 0d0))
+	(ccl:set-fpu-mode :division-by-zero division-by-zero))))
+
+(defconstant double-float-negative-infinity
+  #.(let* ((division-by-zero (get-fpu-mode  :division-by-zero)))
+      (declare (notinline /))
+      (unwind-protect
+           (progn
+             (ccl:set-fpu-mode :division-by-zero nil)
+             (/ -0d0))
+	(ccl:set-fpu-mode :division-by-zero division-by-zero))))
+
+(defconstant double-float-nan
+  #.(let ((invalid (get-fpu-mode :invalid)))
+      (unwind-protect
+	   (progn
+	     (set-fpu-mode :invalid nil)
+	     (+ double-float-positive-infinity double-float-negative-infinity))
+	(set-fpu-mode :invalid invalid))))
+
+(defun parse-float (str len off)  
+  ; we cant assume this really is a float but dont call with eg s1 or e1
+  (let ((integer 0)(expt 0)(sign 0)(done 0)(digits 0) point-pos type) 
+    (setq integer
+          (do ((n off (1+ n))
+               (first t nil)
+               (maxn  (+ off len)))
+              ((>= n maxn) integer)
+            (declare (fixnum n maxn))
+            (let ((c (%schar str n)))
+              (cond ((eq c #\.)
+                     (setq point-pos digits))
+                    ((and first (eq c #\+)))
+                    ((and first (eq c #\-))
+                     (setq sign -1))
+                    ((memq c '(#\s #\f #\S #\F))
+                     (setq type 'short-float)
+                     (return integer))
+                    ((memq c '(#\d #\l  #\D  #\L))
+                     (setq type 'double-float)
+                     (return integer))
+                    ((memq c '(#\e #\E))
+                     (return integer))
+                    ((setq c (digit-char-p c))
+                     (setq digits (1+ digits))
+                     (setq integer (+ c (* 10 integer))))                  
+                    (t (return-from parse-float nil)))
+              (setq done (1+ done)))))
+    (when point-pos
+      (setq expt  (%i- point-pos digits)))
+    (when (null type)
+      (setq type *read-default-float-format*))
+    (when (> len done)
+      (let ((eexp nil) (inf nil) (nan nil) (esign 1) c (xsign-n -1))
+        (do ((n (%i+ off done 1) (1+ n))
+             (first t nil))
+            ((>= n (+ off len)))
+          (declare (fixnum n))
+          (setq c (%schar str n))
+          (cond ((and first (or (eq c #\+)(eq c #\-)))
+                 (when (eq c #\-)(setq esign -1))
+		 (setq xsign-n (1+ n)))
+		((and (= n xsign-n)
+		      (or (eq c #\+)(eq c #\-)))
+                 (if (eq c #\-)
+		     (setq nan t)
+		     (setq inf t)))
+                ((setq c (digit-char-p c))
+                 (setq eexp (+ c (* (or eexp 0) 10))))
+                (t (return-from parse-float nil))))
+        (when (not eexp)(return-from parse-float nil))
+        (cond 
+	 (inf 
+	  (return-from parse-float
+	    (coerce (if (minusp sign)
+			double-float-negative-infinity
+			double-float-positive-infinity)
+		    type)))
+	 (nan 
+	  (return-from parse-float
+	    (coerce double-float-nan type)))
+	 (expt (setq expt (%i+ expt (* esign eexp))))
+	 (t (return-from parse-float nil)))))
+    (fide sign integer expt (subtypep type 'short-float))))
+
+
+;; an interesting test case: 1.448997445238699
+;; The correct result is 6525704354437805 x 2^-52
+;; Incorrect is          6525704354437806 x 2^-52
+;; (from Will Clinger, "How to Read Floating Point Numbers Accurately",
+;;  ACM SIGPLAN'90 Conference on Programming Language Design and Implementation")
+;; Doug Curries numbers 214748.3646, 1073741823/5000
+
+
+;; Sane read losers
+;; 15871904747836473438871.0e-8
+;; 3123927307537977993905.0-13
+;; 17209940865514936528.0e-6
+;; "13.60447536e132" => adds some gratuitous drech
+;; "94824331561426550.889e182"
+;; "1166694.64175277e-150" => 1.1666946417527701E-144
+;; "3109973217844.55680988601e-173"
+;; "817332.e-184" => 8.173320000000001E-179
+;; "2695.13e-180" => 2.6951300000000002E-177
+;; "89.85345789e-183" => 8.985345789000001E-182
+;; "0864813880.29e140" => 8.648138802899999E+148
+;; "5221.e-193" => 5.2209999999999995E-190
+;; "7.15628e-175" => 7.156280000000001E-175
+
+(defparameter float-powers-of-5  nil)
+(defparameter integer-powers-of-5 nil)
+
+(defun 5-to-e (e)
+  (declare (fixnum e)(optimize (speed 3)(safety 0)))
+  (if (> e 335)
+    (* (5-to-e 335)(5-to-e (- e 335))) ; for the dude who types 200 digits and e-500
+    (if (< e 12)
+      (svref integer-powers-of-5 e)
+      (multiple-value-bind (q r) (truncate e 12) ; was floor
+        (declare (fixnum q r))        
+        (if (eql r 0)
+          (svref integer-powers-of-5 (%i+ q 11))
+          (* (svref integer-powers-of-5 r)
+             (svref integer-powers-of-5 (%i+ q 11))))))))
+
+(defun float-5-to-e (e)
+  (if (> e 22)  ; shouldnt happen
+    (expt 5.0d0 e)
+    (svref float-powers-of-5 e)))
+
+(defparameter a-short-float nil)
+
+(eval-when (:compile-toplevel :execute)
+  ; number of bits for mantissa before rounding
+  (defconstant *short-float-extended-precision* 28)
+  (defconstant *double-float-extended-precision* 60)
+  ; number of mantissa bits including hidden bit
+  (defconstant *double-float-precision* (1+ IEEE-double-float-mantissa-width))
+  (defconstant *short-float-precision* (1+ IEEE-single-float-mantissa-width))
+  (defconstant *double-float-bias* IEEE-double-float-bias)
+  (defconstant *double-float-max-exponent* (1+ IEEE-double-float-normal-exponent-max))
+  (defconstant *double-float-max-exact-power-of-5* 23)
+  ;(defconstant *short-float-max-exact-integer-length* 24)
+  (defconstant *double-float-max-exact-integer-length* 53)
+)
+
+
+
+
+(eval-when (:compile-toplevel :execute)
+  (defconstant *short-float-max-exact-power-of-5* 10)
+  (defconstant *short-float-bias* IEEE-single-float-bias)
+  (defconstant *short-float-max-exact-integer-length* 24)
+  (defconstant *short-float-max-exponent* (1+ IEEE-single-float-normal-exponent-max))
+)
+
+  
+;; this stuff  could be in a shared file
+
+(defun fide #|float-integer-with-decimal-exponent|# (sign integer power-of-10 &optional short)
+  ;; take care of the zero case
+  (when (zerop integer)
+    (return-from fide ;float-integer-with-decimal-exponent
+       (if short
+         (if (minusp sign) -0.0s0 0.0s0)
+         (if (minusp sign) -0.0d0 0.0d0))))
+  (let ((abs-power (abs power-of-10))
+        (integer-length (integer-length integer)))
+    ;; this doesn't work for the above example, so arithmetic must be done wrong
+    ;; This does work if set FPCR precision to double
+    ;; now see if the conversion can be done simply:
+    ;; if both the integer and the power of 10 can be floated exactly, then
+    ;; correct rounding can be done by the multiply or divide
+    (when (or;short
+           (and (<= integer-length  
+                    ;; was (if short 17 53) why 17? see above
+                    (if short *short-float-max-exact-integer-length* *double-float-max-exact-integer-length*)) 
+                ;; (integer-length (expt 5 23)) => 54
+                ;; was (if short 5 23)
+                (< abs-power  (if short 
+                                *short-float-max-exact-power-of-5*
+                                *double-float-max-exact-power-of-5*)))) ; we mean < 23 not <=
+      ;; if you care about consing, this could be done in assembly language or whatever,
+      ;; since all integers fit in 53 bits
+      (return-from fide ;float-integer-with-decimal-exponent
+        (let* ((signed-integer (prog1 (if (minusp sign) (- integer) integer)))
+               (float (float signed-integer (if short 0.0s0 0.0d0)))
+               (10-to-power (scale-float (float-5-to-e abs-power) abs-power)))
+          ;; coerce to short-float does not whine about undeflow, but does re overflow
+          (when short (setq 10-to-power (coerce 10-to-power 'short-float)))
+          (if (zerop abs-power)
+            float
+            (if (minusp power-of-10)
+              (/ float  10-to-power)
+              (* float  10-to-power))))))
+    (try-harder sign integer power-of-10 short)))
+
+
+(defun try-harder (sign integer power-of-10 short)
+  (flet ((ovf (&optional under)
+           (if under
+             (if (get-fpu-mode :underflow)
+               (error 'floating-point-underflow
+                      :operation 'scale
+                      :operands (list sign integer power-of-10)))
+             (if (get-fpu-mode :overflow)
+               (error 'floating-point-overflow
+                      :operation 'scale
+                      :operands (list sign integer power-of-10))))
+           (return-from try-harder
+             (if under
+               (if short
+                 (if (minusp sign) -0.0s0 0.0s0)                 
+                 (if (minusp sign) 0.0d0 0.0d0))
+               (if short
+                 (if (minusp sign) most-negative-short-float most-positive-short-float)              
+                 (if (minusp sign) most-negative-double-float most-positive-double-float))))))
+  (let* ((integer-length (integer-length integer)) new-int power-of-2)
+    (if (minusp power-of-10)
+      (progn 
+        ;; avoid creating enormous integers with 5-to-e only to error later
+        (when (< power-of-10 -335)
+          (let ((poo (+ (round integer-length 3.2) power-of-10)))
+            ;; overestimate digits in integer
+            (when (< poo -335) (ovf t))
+            ;; this case occurs if 600+ digits 
+            (when (> poo 335) (ovf))))
+        (let* ((divisor (5-to-e (- power-of-10)))
+               ;; make sure we will have enough bits in the quotient
+               ;; (and a couple extra for rounding)
+               (shift-factor (+ (- (integer-length divisor) integer-length)
+                                (if short *short-float-extended-precision* *double-float-extended-precision*)))
+               (scaled-integer integer))
+          (if (plusp shift-factor)
+            (setq scaled-integer (ash integer shift-factor))
+            (setq divisor (ash divisor (- shift-factor))))
+          (multiple-value-bind (quotient remainder)(floor scaled-integer divisor)
+            (unless (zerop remainder) ; whats this - tells us there's junk below
+              (setq quotient (logior quotient 1)))
+            (setq new-int quotient)
+            (setq power-of-2  (- power-of-10 shift-factor)))))
+      (progn
+        (when (> power-of-10 335)(ovf))
+        (setq new-int (* integer (5-to-e power-of-10)))
+        (setq power-of-2 power-of-10)))
+    (float-and-scale-and-round sign new-int power-of-2 short))))
+
+
+(defun float-and-scale-and-round (sign integer power-of-2 short &optional result)
+  (let* ((length (integer-length integer))
+         (lowbits 0)
+         (prec (if short *short-float-precision* *double-float-precision*))
+         (ep (if short *short-float-extended-precision* *double-float-extended-precision*)))
+    (when (<= length prec)
+      ;; float can be done exactly, so do it the easy way
+      (return-from float-and-scale-and-round
+        (scale-float (float (if (minusp sign) (- integer) integer) (if short a-short-float))
+                     power-of-2)))    
+    (let* ((exponent (+ length power-of-2))
+           (biased-exponent (+ exponent (if short *short-float-bias* *double-float-bias*)))
+           (sticky-residue nil))
+      (cond
+       ((<= biased-exponent 0)
+        ;; denormalize the number
+        (setf sticky-residue (not (zerop (ldb integer (byte (- 1 biased-exponent) 0)))))
+        (setf integer (ash integer (- biased-exponent 1)))
+        (setf biased-exponent 0)))
+      (let ((lowest (min ep length)))
+        (when (and (> length ep)(not (zerop (ldb (byte (- length ep) 0) integer))))
+          (setq integer (logior integer (ash 1 (- length ep)))))
+        ; somewhere between 1 and (- ep prec) bits
+        (setq lowbits (ash (ldb (byte (- lowest prec) (- length lowest)) integer) (- ep lowest))))
+      (let* ((significand (ldb (byte (1- prec) (- length prec)) integer)))
+        (when (and (not (zerop (ldb (byte 1 (- length (1+ prec))) integer)))   ; round bit
+                   (or sticky-residue (oddp significand)
+                       (not (zerop (ldb (byte (- ep prec 1) 0) lowbits)))))
+          ;; round up
+          (setf significand (ldb (byte (1- prec) 0) (+ significand 1)))
+          (when (zerop significand)
+            (incf biased-exponent)))
+        (cond ((and (zerop biased-exponent)
+                    (zerop significand)
+                    (get-fpu-mode :underflow))
+               (error 'floating-point-underflow
+                      :operation 'scale
+                      :operands (list sign integer power-of-2)))
+              ((>= biased-exponent (if short *short-float-max-exponent* *double-float-max-exponent*))
+               (cond 
+                     (t
+                      (if (get-fpu-mode :overflow)
+                        (error 'floating-point-overflow
+                               :operation 'scale
+                               :operands (list sign integer power-of-2)))
+                      (setf significand 0)                      
+                      (setq biased-exponent (if short *short-float-max-exponent* *double-float-max-exponent*))))))
+        (values
+         (if short 
+           (make-short-float-from-fixnums (ldb (byte 23 0) significand)
+                                          biased-exponent
+                                          sign #-64-bit-target result)
+           (make-float-from-fixnums (ldb (byte 24 28) significand)
+                                    (ldb (byte 28 0) significand)
+                                    biased-exponent
+                                    sign result))
+         lowbits)))))
+
+
+
+
+(defparameter a-short-float 1.0s0)
+
+#+32-bit-target
+(defmethod print-object ((rs random-state) stream)
+  (format stream "#.(~S ~S ~S)"         ;>> #.GAG!!!
+          'ccl::initialize-random-state
+          (random.seed-1 rs)
+          (random.seed-2 rs)))
+
+#+64-bit-target
+(defmethod print-object ((rs random-state) stream)
+  (let* ((s1 (random.seed-1 rs)))
+    (format stream "#.(~S ~S ~S)"       ;>> #.GAG!!!
+            'ccl::initialize-random-state
+            (ldb (byte 16 16) s1)
+            (ldb (byte 16 0) s1))))
+
+
+
+(defun float-radix (float)
+  "Return (as an integer) the radix b of its floating-point argument."
+  (require-type float 'float)
+  2)
+
+(defun float-digits (float)
+  (if (typep (require-type float 'float) 'short-float)
+    IEEE-single-float-digits
+    IEEE-double-float-digits))
+
+(defun number-arg (arg)
+  (if (numberp arg) arg (%badarg arg 'number)))
+
+
+
+
+
+;==> Needs a transform...
+(defun logandc2 (integer1 integer2)
+  "Bitwise AND INTEGER1 with (LOGNOT INTEGER2)."
+  (logandc1 integer2 integer1))
+
+(defun logorc2 (integer1 integer2)
+  "Bitwise OR INTEGER1 with (LOGNOT INTEGER2)."
+  (logorc1 integer2 integer1))
+
+
+
+; Figure that the common (2-arg) case is caught by a compiler transform anyway.
+(defun gcd (&lexpr numbers)
+  "Return the greatest common divisor of the arguments, which must be
+  integers. Gcd with no arguments is defined to be 0."
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))   
+    (if (zerop count)
+      0
+      (let* ((n0 (%lexpr-ref numbers count 0)))
+        (if (= count 1)
+          (%integer-abs n0)
+          (do* ((i 1 (1+ i)))
+               ((= i count) n0)
+            (declare (fixnum i))
+            (setq n0 (gcd-2 n0 (%lexpr-ref numbers count i)))))))))
+
+(defun lcm-2 (n0 n1)
+  (or (typep n0 'integer) (report-bad-arg n0 'integer))
+  (or (typep n1 'integer) (report-bad-arg n1 'integer))
+  (locally (declare (integer n0 n1))
+    (if (zerop n0)
+      0
+      (if (zerop n1)
+	0
+	(let* ((small (if (< n0 n1) n0 n1))
+	       (large (if (eq small n0) n1 n0)))
+	  (values (truncate (abs (* n0 n1)) (gcd large small))))))))
+
+(defun lcm (&lexpr numbers)
+  "Return the least common multiple of one or more integers. LCM of no
+  arguments is defined to be 1."
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))    
+    (if (zerop count)
+      1
+      (let* ((n0 (%lexpr-ref numbers count 0)))
+        (if (= count 1)
+          (%integer-abs n0)
+	  (if (= count 2)
+	    (lcm-2 n0 (%lexpr-ref numbers count 1))
+	    (do* ((i 1 (1+ i)))
+		 ((= i count) n0)
+	      (declare (fixnum i))
+	      (setq n0 (lcm-2 n0 (%lexpr-ref numbers count i))))))))))
+
+
+#|
+(defun rationalize (x)
+  (etypecase x
+    (rational x)
+    (real
+     (cond ((minusp x) (- (rationalize (- x))))
+	   ((zerop x) 0)
+	   (t
+	    (let ((eps (etypecase x
+			 (single-float single-float-epsilon)
+			 (double-float double-float-epsilon)))
+		  (y ())
+		  (a ()))
+	      (do ((xx x (setq y (/ (float 1.0 x) (- xx (float a x)))))
+		   (num (setq a (truncate x))
+			(+ (* (setq a (truncate y)) num) onum))
+		   (den 1 (+ (* a den) oden))
+		   (onum 1 num)
+		   (oden 0 den))
+		  ((and (not (zerop den))
+			(not (> (abs (/ (- x (/ (float num x)
+						(float den x)))
+					x))
+				eps)))
+		   (integer-/-integer num den)))))))))
+|#
+
+(defun rationalize (number)
+  "Converts any REAL to a RATIONAL.  Floats are converted to a simple rational
+  representation exploiting the assumption that floats are only accurate to
+  their precision.  RATIONALIZE (and also RATIONAL) preserve the invariant:
+      (= x (float (rationalize x) x))"
+  (if (floatp number)
+    (labels ((simpler-rational (less-predicate lonum loden hinum hiden
+                                               &aux (trunc (if (eql less-predicate #'<=)
+                                                             #'ceiling
+                                                             #'(lambda (n d) (1+ (floor n d)))))
+                                               (term (funcall trunc lonum loden)))
+               ;(pprint (list lonum loden hinum hiden))
+               (if (funcall less-predicate (* term hiden) hinum)
+                 (values term 1)
+                 (multiple-value-bind 
+                   (num den)
+                   (simpler-rational less-predicate hiden (- hinum (* (1- term) hiden))
+                                     loden (- lonum (* (1- term) loden)))
+                   (values (+ den (* (1- term) num)) num)))))                           
+      (multiple-value-bind (fraction exponent sign) (integer-decode-float number)
+        ;; the first 2 tests may be unnecessary - I think the check
+        ;; for denormalized is compensating for a bug in 3.0 re
+        ;; floating a rational (in order to pass tests in
+        ;; ppc-test-arith).
+        (if (or (and (typep number 'double-float)  ; is it denormalized
+                     (eq exponent #.(nth-value 1 (integer-decode-float least-positive-double-float)))) ; aka -1074))
+                (eq exponent #.(nth-value 1 (integer-decode-float least-positive-short-float))) ; aka -149))
+                (zerop (logand fraction (1- fraction)))) ; or a power of two
+          (rational number)
+          (if (minusp exponent)
+	    ;;less than 1
+            (let ((num (ash fraction 2))
+	          (den (ash 1 (- 2 exponent))))
+	      (multiple-value-bind 
+                (n d)
+                (simpler-rational (if (evenp fraction) #'<= #'<)
+                                  (- num 2) ;(if (zerop (logand fraction (1- fraction))) 1 2))
+                                  den  (+ num 2) den)
+	        (when (minusp sign)
+	          (setq n (- n)))
+	        (/ n d)))
+            ;;greater than 1
+            (ash (if (minusp number) (- fraction) fraction) exponent)))))
+    (rational number)))
+#|
+(defun testrat (&optional (n 1000))
+  (dotimes (i n)
+    (let* (( numerator (random (ash 1 63)))
+          (denominator (random (ash 1 63)))
+          (sign  (if (zerop (random 2)) 1 -1))
+          (trial (float (/ (* sign numerator) denominator)))
+          (rat (rationalize trial)))
+      (when (not (= (float rat) trial))
+        (error "Rationalize failed. Input ~s Rational ~s Float ~s" trial rat (float rat))))))
+
+; smallest fails in 3.0 - powers of 2 - works here but we cheat a bit
+(defun testrat2 ()
+  (let ((f least-positive-double-float))
+    (dotimes (i 100)
+      (when (not (= (float (rationalize f)) f))
+        (cerror "a" "rat failed ~s ~s" f i))
+      (setq f (* f 2)))))
+
+; fails a lot in 3.0 - not powers of 2 - works here
+(defun testrat3 ()
+  (let ((f least-positive-double-float))
+    (dotimes (i 1000)
+      (let ((f2 (* (+ i i 1) f)))
+        (when (not (= (float (rationalize f2)) f2))
+          (cerror "a" "rat failed ~s ~s" f2 i)))))
+  (let ((f least-negative-double-float))
+    (dotimes (i 1000)
+      (let ((f2 (* (+ i i 1) f)))
+        (when (not (= (float (rationalize f2)) f2))
+          (cerror "a" "rat failed ~s ~s" f2 i))))))
+
+(defun testrat31 ()
+  (let ((f least-positive-short-float))
+    (dotimes (i 1000)
+      (let ((f2 (* (+ i i 1) f)))
+        (when (not (= (float (rationalize f2)) f2))
+          (cerror "a" "rat failed ~s ~s" f2 i)))))
+  (let ((f least-negative-short-float))
+    (dotimes (i 1000)
+      (let ((f2 (* (+ i i 1) f)))
+        (when (not (= (float (rationalize f2)) f2))
+          (cerror "a" "rat failed ~s ~s" f2 i))))))
+
+; works in 3.0 - and here
+(defun testrat4 ()
+  (let ((f least-positive-normalized-double-float))
+    (dotimes (i 1000)
+      (let ((f2 (* (+ i i 1) f)))
+        (when (not (= (float (rationalize f2)) f2))
+          (cerror "a" "rat failed ~s ~s" f2 i)))))
+  (let ((f least-negative-normalized-double-float))
+    (dotimes (i 100)
+      (let ((f2 (* (+ i i 1) f)))
+        (when (not (= (float (rationalize f2)) f2))
+          (cerror "a" "rat failed ~s ~s" f2 i))))))
+        
+    
+|#
+
+#| now in l1-numbers.lisp
+(defun logeqv (&lexpr numbers)
+  (let* ((count (%lexpr-count numbers)))
+    (declare (fixnum count))
+    (if (zerop count)
+      -1
+      (let* ((n0 (%lisp-word-ref numbers count)))
+        (if (= count 1)
+          (require-type n0 'integer)
+          (do* ((i 1 (1+ i)))
+               ((= i count) n0)
+            (declare (fixnum i))
+            (declare (optimize (speed 3) (safety 0)))
+            (setq n0 (logeqv-2 (%lexpr-ref numbers count i) n0))))))))
+|#
+
+
+(defparameter *boole-ops* 
+  (vector
+   #'(lambda (i1 i2) (declare (ignore i1 i2)) 0)
+   #'(lambda (i1 i2) (declare (ignore i1 i2)) -1)
+   #'(lambda (i1 i2) (declare (ignore i2)) i1)
+   #'(lambda (i1 i2) (declare (ignore i1)) i2)
+   #'(lambda (i1 i2) (declare (ignore i2)) (lognot i1))
+   #'(lambda (i1 i2) (declare (ignore i1)) (lognot i2))
+   #'(lambda (i1 i2) (logand i1 i2))
+   #'(lambda (i1 i2) (logior i1 i2))
+   #'(lambda (i1 i2) (logxor i1 i2))
+   #'(lambda (i1 i2) (logeqv i1 i2))
+   #'(lambda (i1 i2) (lognand i1 i2))
+   #'(lambda (i1 i2) (lognor i1 i2))
+   #'(lambda (i1 i2) (logandc1 i1 i2))
+   #'(lambda (i1 i2) (logandc2 i1 i2))
+   #'(lambda (i1 i2) (logorc1 i1 i2))
+   #'(lambda (i1 i2) (logorc2 i1 i2))))
+ 
+
+
+;===> Change these constants to match maclisp!!
+(defun boole (op integer1 integer2)
+  "Bit-wise boolean function on two integers. Function chosen by OP:
+        0       BOOLE-CLR
+        1       BOOLE-SET
+        2       BOOLE-1
+        3       BOOLE-2
+        4       BOOLE-C1
+        5       BOOLE-C2
+        6       BOOLE-AND
+        7       BOOLE-IOR
+        8       BOOLE-XOR
+        9       BOOLE-EQV
+        10      BOOLE-NAND
+        11      BOOLE-NOR
+        12      BOOLE-ANDC1
+        13      BOOLE-ANDC2
+        14      BOOLE-ORC1
+        15      BOOLE-ORC2"
+  (unless (and (typep op 'fixnum)
+               (locally (declare (fixnum op))
+                 (and (>= op 0)
+                      (<= op 15))))
+    (report-bad-arg op '(integer 0 15)))
+  (funcall (%svref *boole-ops* op)
+	   (require-type integer1 'integer)
+	   (require-type integer2 'integer)))
+
+
+(defun %integer-power (b e)
+  (declare (type unsigned-byte e))
+  (if (zerop e)
+    (+ 1 (* b 0))
+    (if (eql b 2)
+      (ash 1 e)
+      (do* ((next (ash e -1) (ash e -1))
+            (oddexp (oddp e) (oddp e))
+            (total (if oddexp b 1) (if oddexp (* b total) total)))
+           ((zerop next) total)
+        (declare (type unsigned-byte next))
+        (setq b (* b b) e next)))))
+
+(defun signum (x)
+  "If NUMBER is zero, return NUMBER, else return (/ NUMBER (ABS NUMBER))."
+  (cond ((complexp x) (if (zerop x) x (/ x (abs x))))
+        ((rationalp x) (if (plusp x) 1 (if (zerop x) 0 -1)))
+        ((zerop x) (float 0.0 x))
+        (t (float-sign x))))
+
+
+
+; Thanks to d34676@tansei.cc.u-tokyo.ac.jp (Akira KURIHARA)
+(defun isqrt (n &aux n-len-quarter n-half n-half-isqrt
+                init-value iterated-value)
+  "Return the root of the nearest integer less than n which is a perfect
+   square.  Argument n must be a non-negative integer"
+  (cond
+   ((eql n 0) 0)
+   ; this fails sometimes - do we care? 70851992595801818865024053174 or #x80000000
+   ; maybe we do - its used by dotimes
+   ;((not (int>0-p n)) (report-bad-arg n '(integer 0))) ;'unsigned-byte)) ; Huh?
+   ((or (not (integerp n))(minusp n))(report-bad-arg n '(integer 0)))
+   ((> n 24)		; theoretically (> n 7) ,i.e., n-len-quarter > 0
+    (setq n-len-quarter (ash (integer-length n) -2))
+    (setq n-half (ash n (- (ash n-len-quarter 1))))
+    (setq n-half-isqrt (isqrt n-half))
+    (setq init-value (ash (1+ n-half-isqrt) n-len-quarter))
+    (loop
+      (setq iterated-value (ash (+ init-value (floor n init-value)) -1))
+      (if (not (< iterated-value init-value))
+        (return init-value)
+        (setq init-value iterated-value))))
+   ((> n 15) 4)
+   ((> n  8) 3)
+   ((> n  3) 2)
+   (t 1)))
+
+
+(defun sinh (x)
+  "Return the hyperbolic sine of NUMBER."
+  (if (complexp x) 
+    (/ (- (exp x) (exp (- x))) 2)
+    (if (typep x 'double-float)
+      (%double-float-sinh! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+	(%single-float-sinh! sx (%make-sfloat)))
+      #+64-bit-target
+        (%single-float-sinh (%short-float x)))))
+
+
+(defun cosh (x)
+  "Return the hyperbolic cosine of NUMBER."
+  (if (complexp x) 
+    (/ (+ (exp x) (exp (- x))) 2)
+    (if (typep x 'double-float)
+      (%double-float-cosh! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+	(%single-float-cosh! sx (%make-sfloat)))
+      #+64-bit-target
+      (%single-float-cosh (%short-float x)))))
+
+(defun tanh (x)
+  "Return the hyperbolic tangent of NUMBER."
+  (if (complexp x) 
+    (/ (sinh x) (cosh x))
+    (if (typep x 'double-float)
+      (%double-float-tanh! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+	(%single-float-tanh! sx (%make-sfloat)))
+      #+64-bit-target
+      (%single-float-tanh (%short-float x)))))
+
+(defun asinh (x)
+  "Return the hyperbolic arc sine of NUMBER."
+  (if (complexp x) 
+    (log (+ x (sqrt (+ 1 (* x x)))))
+    (if (typep x 'double-float)
+      (%double-float-asinh! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+	(%single-float-asinh! sx (%make-sfloat)))
+      #+64-bit-target
+      (%single-float-asinh (%short-float x)))))
+
+(defun acosh (x)
+  "Return the hyperbolic arc cosine of NUMBER."
+  (if (and (realp x) (<= 1.0 x))
+    (if (typep x 'double-float)
+      (%double-float-acosh! x (%make-dfloat))
+      #+32-bit-target
+      (target::with-stack-short-floats ((sx x))
+	(%single-float-acosh! sx (%make-sfloat)))
+      #+64-bit-target
+      (%single-float-acosh (%short-float x)))
+    (* 2 (log (+ (sqrt (/ (1+ x) 2)) (sqrt (/ (1- x) 2)))))))
+
+(defun atanh (x)
+  "Return the hyperbolic arc tangent of NUMBER."
+  (if (and (realp x) (<= -1.0 (setq x (float x)) 1.0))
+    (if (typep x 'double-float)
+      (%double-float-atanh! x (%make-dfloat))
+      #+32-bit-target
+      (%single-float-atanh! x (%make-sfloat))
+      #+64-bit-target
+      (%single-float-atanh x))
+    (/ (log (/ (+ 1 x) (- 1 x))) 2)))
+
+
+(defun ffloor (number &optional divisor)
+  "Same as FLOOR, but returns first value as a float."
+  (multiple-value-bind (q r) (floor number divisor)
+    (values (float q (if (floatp r) r 0.0)) r)))
+
+(defun fceiling (number &optional divisor)
+  "Same as CEILING, but returns first value as a float."
+  (multiple-value-bind (q r) (ceiling number divisor)
+    (values (float q (if (floatp r) r 0.0)) r)))
+
+(defun ftruncate (number &optional divisor)
+  "Same as TRUNCATE, but returns first value as a float."
+  (multiple-value-bind (q r) (truncate number divisor)
+    (values (float q (if (floatp r) r 0.0)) r)))
+
+(defun fround (number &optional divisor)
+  "Same as ROUND, but returns first value as a float."
+  (multiple-value-bind (q r) (round number divisor)
+    (values (float q (if (floatp r) r 0.0)) r)))
+
+(defun rational (number)
+  "RATIONAL produces a rational number for any real numeric argument. This is
+  more efficient than RATIONALIZE, but it assumes that floating-point is
+  completely accurate, giving a result that isn't as pretty."
+  (if (floatp number)
+    (multiple-value-bind (s e sign)
+        (number-case number
+          (short-float
+           (integer-decode-short-float number))
+          (double-float
+           (integer-decode-double-float number)))
+      (if (eq sign -1) (setq s (- s)))
+      (if (%iminusp e)
+        (/ s (ash 1 (%i- 0 e)))
+        (ash s e)))
+    (if (rationalp number)
+      number
+      (report-bad-arg number 'real))))
+
+; make power tables for floating point reader
+(progn
+  (setq float-powers-of-5 (make-array 23))
+  (let ((array float-powers-of-5))
+    (dotimes (i 23)
+      (setf (svref array i)  (float (expt 5 i) 0.0d0))))
+  (setq integer-powers-of-5 (make-array (+ 12 (floor 324 12))))
+  (let ((array integer-powers-of-5))
+    (dotimes (i 12)
+      (setf (svref array i)  (expt 5 i)))
+    (dotimes (i (floor 324 12))
+      (setf (svref array (+ i 12)) (expt 5 (* 12 (1+ i)))))))
+
+
+(provide 'numbers)
+
Index: /branches/new-random/lib/pathnames.lisp
===================================================================
--- /branches/new-random/lib/pathnames.lisp	(revision 13309)
+++ /branches/new-random/lib/pathnames.lisp	(revision 13309)
@@ -0,0 +1,525 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Portions copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;pathnames.lisp Pathnames for Coral Common LISP
+(in-package "CCL")
+
+(eval-when (eval compile)
+  (require 'level-2)
+  (require 'backquote)
+)
+;(defconstant $accessDenied -5000) ; put this with other errnos
+(defconstant $afpAccessDenied -5000) ; which name to use?
+
+
+
+;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+;ANSI CL logical pathnames
+
+
+(defvar *pathname-translations-pathname*
+  (make-pathname :host "ccl" :type "pathname-translations"))
+
+(defun load-logical-pathname-translations (host)
+  ;(setq host (verify-logical-host-name host))
+  (when (not (%str-assoc host %logical-host-translations%))
+    (setf (logical-pathname-translations host)
+          (with-open-file (file (merge-pathnames (make-pathname :name host :defaults nil)
+                                                 *pathname-translations-pathname*)
+                                :element-type 'base-char)
+            (read file)))
+    T))
+
+(defun back-translate-pathname (path &optional hosts)
+  (let ((newpath (back-translate-pathname-1 path hosts)))
+    (cond ((equalp path newpath)
+	   ;; (fcomp-standard-source path)
+	   (namestring (pathname path)))
+          (t newpath))))
+
+
+(defun back-translate-pathname-1 (path &optional hosts)
+  (dolist (host %logical-host-translations%)
+    (when (or (null hosts) (member (car host) hosts :test 'string-equal))
+      (dolist (trans (cdr host))
+        (when (pathname-match-p path (cadr trans))
+          (let* (newpath)          
+            (setq newpath (translate-pathname path (cadr trans) (car trans) :reversible t))
+            (return-from back-translate-pathname-1 
+              (if  (equalp path newpath) path (back-translate-pathname-1 newpath hosts))))))))
+  path)
+
+
+
+; must be after back-translate-pathname
+(defun physical-pathname-p (path)
+  (let* ((path (pathname path))
+         (dir (pathname-directory path)))
+    (and dir
+         (or (not (logical-pathname-p path))
+             (not (null (memq (pathname-host path) '(nil :unspecific))))))))
+
+
+
+;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+;File or directory Manipulations
+
+(defun unix-rename (old-name new-name)
+  (with-cstrs ((old old-name)
+               (new new-name))
+    #+windows-target
+    (#__unlink new)
+    (let* ((res (#_rename old new)))
+      (declare (fixnum res))
+      (if (zerop res)
+        (values t nil)
+        (values nil (%get-errno))))))
+
+(defun rename-file (file new-name &key (if-exists :error))
+  "Rename FILE to have the specified NEW-NAME. If FILE is a stream open to a
+  file, then the associated file is renamed."
+  (let* ((original (truename file))
+	 (original-namestring (native-translated-namestring original))
+	 (new-name (merge-pathnames new-name original))
+	 (new-namestring (native-translated-namestring new-name)))
+    (unless new-namestring
+      (error "~S can't be created." new-name))
+    (unless (and (probe-file new-name)
+		 (not (if-exists if-exists new-name)))
+      (multiple-value-bind (res error)
+	                   (unix-rename original-namestring
+					new-namestring)
+	(unless res
+	  (error "Failed to rename ~A to ~A: ~A"
+		 original new-name error))
+	(when (streamp file)
+	  (setf (stream-filename file)
+		(namestring (native-to-pathname new-namestring))))
+	(values new-name original (truename new-name))))))
+
+(defun copy-file (source-path dest-path &key (if-exists :error) (if-does-not-exist :create)
+			      (preserve-attributes nil))
+  (let* ((original (truename source-path))
+	 (new-name (merge-pathnames dest-path original))
+         (buffer (make-array 4096 :element-type '(unsigned-byte 8))))
+    (with-open-file (in original :direction :input
+                        :element-type '(unsigned-byte 8))
+      (with-open-file (out new-name :direction :output
+                           :if-exists if-exists
+                           :if-does-not-exist if-does-not-exist
+                           :element-type '(unsigned-byte 8))
+        (loop
+          as n = (stream-read-vector in buffer 0 4096) until (eql n 0)
+          do (stream-write-vector out buffer 0 n))))
+    (when preserve-attributes
+      (copy-file-attributes original new-name))
+    (values new-name original (truename new-name))))
+
+(defun recursive-copy-directory (source-path dest-path &key test (if-exists :error))
+  ;; TODO: Support :if-exists :supersede to blow away any files not in source dir
+  (assert (directoryp source-path)(source-path)
+          "source-path is not a directory in RECURSIVE-COPY-DIRECTORY")
+  (setq if-exists (require-type if-exists '(member :overwrite :error)))
+  (setq dest-path (ensure-directory-pathname dest-path))
+  (when (eq if-exists :error)
+    (when (probe-file dest-path)
+      (if-exists if-exists dest-path))
+    ;; Skip the probe-file in recursive calls, we already know it's ok.
+    (setq if-exists :overwrite))
+  (let* ((source-dir (ensure-directory-pathname source-path))
+         (pattern (make-pathname :name :wild :type :wild :defaults source-dir))
+         (source-files (directory pattern :test test :directories t :files t)))
+    (ensure-directories-exist dest-path)
+    (dolist (f source-files)
+      (when (or (null test) (funcall test f))
+        (if (directory-pathname-p f)
+            (let ((dest-file (make-pathname :name (first (last (pathname-directory f)))
+                                            :defaults dest-path)))
+              (recursive-copy-directory f dest-file :test test :if-exists if-exists))
+            (let* ((dest-file (make-pathname :name (pathname-name f)
+                                             :type (pathname-type f)
+                                             :defaults dest-path)))
+              (copy-file f dest-file :if-exists :supersede :preserve-attributes t)))))))
+
+;;; use with caution!
+;;; blows away a directory and all its contents
+(defun recursive-delete-directory (path &key (if-does-not-exist :error))
+  (setq path (ensure-directory-pathname path))
+  (setq if-does-not-exist (require-type if-does-not-exist '(member :error nil)))
+  (when (eq if-does-not-exist :error)
+    (unless (probe-file path)
+      (if-does-not-exist if-does-not-exist path)))
+  (when (probe-file path)
+      (if (directoryp path)
+	  ;; it's a directory: blow it away
+	  (let* ((pattern (make-pathname :name :wild :type :wild :defaults path))
+		 (files (directory pattern :directories nil :files t))
+		 (subdirs (directory pattern :directories t :files nil))
+		 (target-pathname (native-translated-namestring path)))
+	    (dolist (f files)
+	      (delete-file f))
+	    (dolist (d subdirs)
+	      (recursive-delete-directory d :if-does-not-exist if-does-not-exist))
+	    (%rmdir target-pathname))
+	  ;; it's not a directory: for safety's sake, signal an error
+	  (error "Pathname '~A' is not a directory" path))))
+
+;;; It's not clear that we can support anything stronger than
+;;; "advisory" ("you pretend the file's locked & I will too") file
+;;; locking under Darwin.
+
+
+
+
+(defun create-directory (path &key (mode #o777))
+  (let* ((pathname (translate-logical-pathname (merge-pathnames path)))
+	 (created-p nil)
+	 (parent-dirs (let* ((pd (pathname-directory pathname)))
+			(if (eq (car pd) :relative)
+			  (pathname-directory (merge-pathnames
+					       pathname
+					       (mac-default-directory)))
+			  pd)))
+	 (nparents (length parent-dirs)))
+    (when (wild-pathname-p pathname)
+      (error 'file-error :error-type "Inappropriate use of wild pathname ~s"
+	     :pathname pathname))
+    (do* ((i 1 (1+ i)))
+	 ((> i nparents) (values pathname created-p))
+      (declare (fixnum i))
+      (let* ((parent (make-pathname
+		      :name :unspecific
+		      :type :unspecific
+		      :host (pathname-host pathname)
+		      :device (pathname-device pathname)
+		      :directory (subseq parent-dirs 0 i)))
+	     (parent-name (native-translated-namestring parent))
+	     (parent-kind (%unix-file-kind parent-name)))
+
+	(if parent-kind
+	  (unless (eq parent-kind :directory)
+	    (error 'simple-file-error
+		   :error-type "Can't create directory ~s, since file ~a exists and is not a directory"
+		   :pathname pathname
+		   :format-arguments (list parent-name)))
+	  (let* ((result (%mkdir parent-name mode)))
+	    (declare (fixnum result))
+	    (if (< result 0)
+	      (signal-file-error result parent-name)
+	      (setq created-p t))))))))
+
+
+(defun ensure-directories-exist (pathspec &key verbose (mode #o777))
+  "Test whether the directories containing the specified file
+  actually exist, and attempt to create them if they do not.
+  The MODE argument is an extension to control the Unix permission
+  bits.  Portable programs should avoid using the :MODE keyword
+  argument."
+  (let ((pathname (let ((pathspec (translate-logical-pathname (merge-pathnames pathspec))))
+		    (make-directory-pathname :device (pathname-device pathspec)
+					     :directory (pathname-directory pathspec))))
+	(created-p nil))
+    (when (wild-pathname-p pathname)
+      (error 'file-error
+	     :error-type "Inappropriate use of wild pathname ~s"
+	     :pathname pathname))
+    (let ((dir (pathname-directory pathname)))
+      (if (eq (car dir) :relative)
+	(setq dir (pathname-directory (merge-pathnames
+				       pathname
+				       (mac-default-directory)))))
+      (loop for i from 1 upto (length dir)
+	    do (let ((newpath (make-pathname
+			       :name :unspecific
+			       :type :unspecific
+			       :host (pathname-host pathname)
+			       :device (pathname-device pathname)
+			       :directory (subseq dir 0 i))))
+		 (unless (probe-file newpath)
+		   (let ((namestring (native-translated-namestring newpath)))
+		     (when verbose
+		       (format *standard-output* "~&Creating directory: ~A~%"
+			       namestring))
+		     (%mkdir namestring mode)
+		     (unless (probe-file newpath)
+		       (error 'file-error
+			      :pathname namestring
+			      :error-type "Can't create directory ~S."))
+		     (setf created-p t)))))
+      (values pathspec created-p))))
+
+(defun dirpath-to-filepath (path)
+  (setq path (translate-logical-pathname (merge-pathnames path)))
+  (let* ((dir (pathname-directory path))
+         (super (butlast dir))
+         (name (car (last dir))))
+    (when (eq name :up)
+      (setq dir (remove-up (copy-list dir)))
+      (setq super (butlast dir))
+      (setq name (car (last dir))))
+    (when (null super)
+      (signal-file-error $xnocreate path))
+    (setq path (make-pathname :directory super :name name :defaults nil))))
+
+(defun filepath-to-dirpath (path)
+  (let* ((dir (pathname-directory path))
+         (rest (file-namestring path)))
+    (make-pathname :directory (append dir (list rest)) :defaults nil)))
+  
+
+
+;Takes a pathname, returns the truename of the directory if the pathname
+;names a directory, NIL if it names an ordinary file, error otherwise.
+;E.g. (directoryp "ccl;:foo:baz") might return #P"hd:mumble:foo:baz:" if baz
+;is a dir. - should we doc this - its exported?
+(defun directoryp (path)
+  (let* ((native (native-translated-namestring path))
+	 (realpath (%realpath native)))
+    (if realpath (eq (%unix-file-kind realpath) :directory))))
+	 
+
+;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+;Wildcards
+
+
+
+ 
+;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+;Directory Traversing
+
+(defun %path-cat (device dir subdir)
+  (if device
+      (%str-cat device ":" dir subdir)
+    (%str-cat dir subdir)))
+
+(defmacro with-open-dir ((dirent device dir) &body body)
+  `(let ((,dirent (%open-dir (native-translated-namestring (make-pathname :device ,device :directory ,dir :defaults nil)))))
+     (when ,dirent
+       (unwind-protect
+	   (progn ,@body)
+	 (close-dir ,dirent)))))
+
+(defun directory (path &key (directories nil) ;; include subdirectories
+                            (files t)         ;; include files
+			    (all t)           ;; include Unix dot files (other than dot and dot dot)
+			    (directory-pathnames t) ;; return directories as directory-pathname-p's.
+                            (include-emacs-lockfiles nil) ;; inculde .#foo
+			    test              ;; Only return pathnames matching test
+			    (follow-links t)) ;; return truename's of matching files.
+  "Return a list of PATHNAMEs, each the TRUENAME of a file that matched the
+   given pathname. Note that the interaction between this ANSI-specified
+   TRUENAMEing and the semantics of the Unix filesystem (symbolic links..)
+   means this function can sometimes return files which don't have the same
+   directory as PATHNAME."
+  (let* ((keys (list :directories directories ;list defaulted key values
+		     :files files
+		     :all all
+		     :directory-pathnames directory-pathnames
+		     :test test
+                     :include-emacs-lockfiles include-emacs-lockfiles
+		     :follow-links follow-links))
+	 (path (full-pathname (merge-pathnames path) :no-error nil))
+	 (dir (directory-namestring path)))
+    (declare (dynamic-extent keys))
+    (if (null (pathname-directory path))
+      (setq dir (directory-namestring (setq path
+					    (merge-pathnames path
+							     (mac-default-directory))))))
+    (assert (eq (car (pathname-directory path)) :absolute) ()
+	    "full-pathname returned relative path ~s??" path)
+    ;; return sorted in alphabetical order, target-Xload-level-0 depends
+    ;; on this.
+    (nreverse
+     (delete-duplicates (%directory "/" dir path '(:absolute) keys) :test #'equal))))
+
+(defun %directory (dir rest path so-far keys)
+  (multiple-value-bind (sub-dir wild rest) (%split-dir rest)
+    (%some-specific dir sub-dir wild rest path so-far keys)))
+
+(defun %some-specific (dir sub-dir wild rest path so-far keys)
+  (let* ((start 1)
+	 (end (length sub-dir))
+	 (full-dir (if (eq start end) dir (%str-cat dir (%substr sub-dir start end)))))
+    (while (neq start end)
+      (let ((pos (position #\/ sub-dir :start start :end end)))
+	(push (%path-std-quotes (%substr sub-dir start pos) nil "/:;*") so-far)
+	(setq start (%i+ 1 pos))))
+    (cond ((null wild)
+	   (%files-in-directory full-dir path so-far keys))
+	  ((string= wild "**")
+	   (%all-directories full-dir rest path so-far keys))
+	  (t (%one-wild full-dir wild rest path so-far keys)))))
+
+; for a * or *x*y
+(defun %one-wild (dir wild rest path so-far keys)
+  (let ((result ())
+	(device (pathname-device path))
+	(all (getf keys :all))
+	name)
+    (with-open-dir (dirent device dir)
+      (while (setq name (%read-dir dirent))
+	(when (and (or all (neq (%schar name 0) #\.))
+		   (not (string= name "."))
+		   (not (string= name ".."))
+		   (%path-pstr*= wild name)
+		   (eq (%unix-file-kind (%path-cat device dir name) t) :directory))
+	  (let ((subdir (%path-cat nil dir name))
+                (so-far (cons (%path-std-quotes name nil "/;:*") so-far)))
+	    (declare (dynamic-extent so-far))
+	    (setq result
+		  (nconc (%directory (%str-cat subdir "/") rest path so-far keys) result))))))
+    result))
+
+(defun %files-in-directory (dir path so-far keys)
+  (let ((device (pathname-device path))
+        (name (pathname-name path))
+        (type (pathname-type path))
+	(directories (getf keys :directories))
+	(files (getf keys :files))
+	(directory-pathnames (getf keys :directory-pathnames))
+	(test (getf keys :test))
+	(follow-links (getf keys :follow-links))
+	(all (getf keys :all))
+        (include-emacs-lockfiles (getf keys :include-emacs-lockfiles))
+        (result ())
+        sub dir-list ans)
+    (if (not (or name type))
+      (let (full-path)
+	(when (and directories
+		   (eq (%unix-file-kind (namestring (setq full-path (%cons-pathname (reverse so-far) nil nil nil device)))
+					t)
+		       :directory))
+	  (setq ans (if directory-pathnames full-path
+		      (%cons-pathname (reverse (cdr so-far)) (car so-far) nil nil device)))
+	  (when (and ans (or (null test) (funcall test ans)))
+	    (setq result (list ans)))))
+      (with-open-dir (dirent (pathname-device path) dir)
+	(while (setq sub (%read-dir dirent))
+	  (when (and (or all (neq (%schar sub 0) #\.))
+                     (or include-emacs-lockfiles
+                         (< (length sub) 2)
+                         (not (string= sub ".#" :end1 2)))
+		     (not (string= sub "."))
+		     (not (string= sub ".."))
+		     (%file*= name type sub))
+	    (setq ans
+		  (if (eq (%unix-file-kind (%path-cat device dir sub) t) :directory)
+		    (when directories
+		      (let* ((std-sub (%path-std-quotes sub nil "/;:*")))
+			(if directory-pathnames
+			  (%cons-pathname (reverse (cons std-sub so-far)) nil nil nil device)
+			  (%cons-pathname (or dir-list (setq dir-list (reverse so-far))) std-sub nil nil device))))
+		    (when files
+		      (multiple-value-bind (name type) (%std-name-and-type sub)
+			(%cons-pathname (or dir-list (setq dir-list (reverse so-far))) name type nil device)))))
+	    (when (and ans (or (null test) (funcall test ans)))
+	      (push (if follow-links (or (probe-file ans) ans) ans) result))))))
+    result))
+
+(defun %all-directories (dir rest path so-far keys)
+  (let ((do-files nil)
+        (do-dirs nil)
+        (result nil)
+        (device (pathname-device path))
+        (name (pathname-name path))
+        (type (pathname-type path))
+	(all (getf keys :all))
+	(test (getf keys :test))
+	(directory-pathnames (getf keys :directory-pathnames))
+	(follow-links (getf keys :follow-links))
+	sub dir-list ans)
+    ;; First process the case that the ** stands for 0 components
+    (multiple-value-bind (next-dir next-wild next-rest) (%split-dir rest)
+      (while (and next-wild ; Check for **/**/ which is the same as **/
+		  (string= next-dir "/")
+		  (string= next-wild "**"))
+        (setq rest next-rest)
+        (multiple-value-setq (next-dir next-wild next-rest) (%split-dir rest)))
+      (cond ((not (string= next-dir "/"))
+	     (setq result
+		   (%some-specific dir next-dir next-wild next-rest path so-far keys)))
+	    (next-wild
+	     (setq result
+		   (%one-wild dir next-wild next-rest path so-far keys)))
+	    ((or name type)
+	     (when (getf keys :files) (setq do-files t))
+	     (when (getf keys :directories) (setq do-dirs t)))
+	    (t (when (getf keys :directories)
+		 (setq sub (if directory-pathnames
+			     (%cons-pathname (setq dir-list (reverse so-far)) nil nil nil device)
+			     (%cons-pathname (reverse (cdr so-far)) (car so-far) nil nil device)))
+		 (when (or (null test) (funcall test sub))
+		   (setq result (list (if follow-links (truename sub) sub))))))))
+    ; now descend doing %all-dirs on dirs and collecting files & dirs if do-x is t
+    (with-open-dir (dirent device dir)
+      (while (setq sub (%read-dir dirent))
+	(when (and (or all (neq (%schar sub 0) #\.))
+		   (not (string= sub "."))
+		   (not (string= sub "..")))
+	  (if (eq (%unix-file-kind (%path-cat device dir sub) t) :directory)
+	    (let* ((subfile (%path-cat nil dir sub))
+		   (std-sub (%path-std-quotes sub nil "/;:*"))
+		   (so-far (cons std-sub so-far))
+		   (subdir (%str-cat subfile "/")))
+	      (declare (dynamic-extent so-far))
+	      (when (and do-dirs (%file*= name type sub))
+		(setq ans (if directory-pathnames
+			    (%cons-pathname (reverse so-far) nil nil nil device)
+			    (%cons-pathname (or dir-list (setq dir-list (reverse (cdr so-far))))
+					    std-sub nil nil device)))
+		(when (or (null test) (funcall test ans))
+		  (push (if follow-links (truename ans) ans) result)))
+	      (setq result (nconc (%all-directories subdir rest path so-far keys) result)))
+	    (when (and do-files (%file*= name type sub))
+	      (multiple-value-bind (name type) (%std-name-and-type sub)
+		(setq ans (%cons-pathname (or dir-list (setq dir-list (reverse so-far))) name type nil device))
+		(when (or (null test) (funcall test ans))
+		  (push (if follow-links (truename ans) ans) result))))))))
+    result))
+
+(defun %split-dir (dir &aux pos)                 ; dir ends in a "/".
+  ;"/foo/bar/../x*y/baz/../z*t/"  ->  "/foo/bar/../" "x*y" "/baz/../z*t/"
+  (if (null (setq pos (%path-mem "*" dir)))
+    (values dir nil nil)
+    (let (epos (len (length dir)))
+      (setq pos (if (setq pos (%path-mem-last "/" dir 0 pos)) (%i+ pos 1) 0)
+            epos (%path-mem "/" dir pos len))
+      (when (%path-mem-last-quoted "/" dir 0 pos)
+	(signal-file-error $xbadfilenamechar dir #\/))
+      (values (unless (%izerop pos) (namestring-unquote (%substr dir 0 pos)))
+              (%substr dir pos epos)
+              (%substr dir epos len)))))
+
+(defun %path-pstr*= (pattern pstr &optional (p-start 0))
+  (assert (eq p-start 0))
+  (%path-str*= pstr pattern))
+
+(defun %file*= (name-pat type-pat pstr)
+  (if (eq name-pat :wild) (setq name-pat "*"))
+  (if (eq type-pat :wild) (setq type-pat "*"))
+  (when (and (null name-pat) (null type-pat))
+    (return-from %file*= T))
+  (let* ((end (length pstr))
+	 (pos (position #\. pstr :from-end t))
+	 (type (and pos (%substr pstr (%i+ pos 1) end)))
+	 (name (unless (eq (or pos end) 0) (if pos (%substr pstr 0 pos) pstr))))
+    (and (cond ((or (eq name-pat :unspecific) (null name-pat)) (null name))
+	       (t (%path-pstr*= name-pat (or name ""))))
+	 (cond ((or (null type-pat) (eq type-pat :unspecific)) (null type))
+	       (t (%path-pstr*= type-pat (or type "")))))))
+
+(provide "PATHNAMES")
Index: /branches/new-random/lib/ppc-backtrace.lisp
===================================================================
--- /branches/new-random/lib/ppc-backtrace.lisp	(revision 13309)
+++ /branches/new-random/lib/ppc-backtrace.lisp	(revision 13309)
@@ -0,0 +1,883 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+(def-accessors (fake-stack-frame) %svref
+  nil                           ; 'fake-stack-frame
+  %fake-stack-frame.sp          ; fixnum. The stack pointer where this frame "should" be
+  %fake-stack-frame.next-sp     ; Either sp or another fake-stack-frame
+  %fake-stack-frame.fn          ; The current function
+  %fake-stack-frame.lr          ; fixnum offset from fn (nil if fn is not functionp)
+  %fake-stack-frame.vsp         ; The value stack pointer
+  %fake-stack-frame.xp          ; Exception frame.
+  %fake-stack-frame.link        ; next in *fake-stack-frames* list
+  )
+
+;;; Linked list of fake stack frames.
+;;; %frame-backlink looks here
+(def-standard-initial-binding *fake-stack-frames* nil)
+  
+
+(defun fake-stack-frame-p (x)
+  (istruct-typep x 'fake-stack-frame))
+
+(defun cfp-lfun (p)
+  (if (fake-stack-frame-p p)
+    (let* ((fn (%fake-stack-frame.fn p))
+           (lr (%fake-stack-frame.lr p)))
+      (if (and (typep fn 'function)
+               (typep lr 'fixnum))
+        (values fn lr)
+        (values nil nil)))
+    (%cfp-lfun p)))
+
+
+(defun %stack< (index1 index2 &optional context)
+  (cond ((fake-stack-frame-p index1)
+         (let ((sp1 (%fake-stack-frame.sp index1)))
+           (declare (fixnum sp1))
+           (if (fake-stack-frame-p index2)
+             (or (%stack< sp1 (%fake-stack-frame.sp index2) context)
+                 (eq index2 (%fake-stack-frame.next-sp index1)))
+             (%stack< sp1 (%i+ index2 1) context))))
+        ((fake-stack-frame-p index2)
+         (%stack< index1 (%fake-stack-frame.sp index2) context))
+        (t (let* ((tcr (if context (bt.tcr context) (%current-tcr)))
+                  (cs-area (%fixnum-ref tcr target::tcr.cs-area)))
+             (and (%ptr-in-area-p index1 cs-area)
+                  (%ptr-in-area-p index2 cs-area)
+                  (< (the fixnum index1) (the fixnum index2)))))))
+
+;;; Returns two values:
+;;;  [nil, nil] if it can be reliably determined that function uses no registers at PC
+;;;  [mask, savevsp]  if it can be reliably determined that the registers specified by "mask"
+;;;      were saved at "savevsp" in the function's stack frame
+;;;  [mask, nil] if registers in "mask" MAY have been saved, but we don't know how to restore them
+;;;      (perhaps because the "at-pc" argument wasn't specified.
+
+
+;;; If the last instruction in a code vector is an
+;;; LWZ instruction (of the form "(LWZ rx s16 ry)"),
+;;; then 
+;;;   this function uses registers RX-R31.  Note that this leaves
+;;;    us 2 extra bits, since we're only encoding 3 bits worth of
+;;;    register info.
+;;;   RX is saved nearest the top of the vstack
+;;;   s16 is the offset from the saved-vsp to the address at which
+;;;    RX was saved; this is a negative value whose low two bits
+;;;    are ignored
+;;;   (logior (ash (logand s16 3) 5) rY) is the pc at which
+;;;   the registers were saved (a fullword code-vector index).
+;;; This scheme lets us encode any "simple" register usage, where
+;;; the registers were saved once, saved somewhere within the first 
+;;; 128 instructions in the code vector, and nothing interesting (to
+;;; backtrace) happens after the registers have been restored.
+;;; If the compiler ever gets cleverer about this, we'll have to use
+;;; some other scheme (perhaps a STW instruction, preceded by branches).
+;;;
+;;; Note that the "last instruction" really means "last instruction
+;;; before any traceback table"; we should be able to truncate the code
+;;; vector (probably by copying it) to strip off the traceback table
+;;; without losing this information.
+;;; Note also that the disassembler would probably ordinarily want to
+;;; hide this last instruction ...
+;;;   
+
+#+ppc32-target
+(defun registers-used-by (lfun &optional at-pc)
+  (let* ((regs-used nil)
+         (where-saved nil))
+    (multiple-value-bind (op-high op-low) (%code-vector-last-instruction (uvref lfun 0))
+      (declare (fixnum op-high op-low))
+      (if (eql (ldb (byte 6 (- 26 16)) op-high) 32)       ; LWZ
+        (let* ((nregs (- 32 (ldb (byte 5 (- 21 16)) op-high)))
+               (pc (dpb (ldb (byte 2 0) op-low) (byte 2 5) (ldb (byte 5 (- 16 16)) op-high)))
+               (offset (%word-to-int (logand op-low (lognot 3)))))
+          (declare (fixnum nregs pc offset))
+          (setq regs-used (1- (ash 1 nregs)))
+          (if at-pc
+            (if (>= at-pc pc)
+              (setq where-saved (- (ash (- offset) -2) nregs))
+              (setq regs-used nil))))))
+    (values (and regs-used (bit-reverse-8 regs-used)) where-saved)))
+
+#+ppc64-target
+(defun registers-used-by (lfun &optional at-pc)
+  (let* ((regs-used nil)
+         (where-saved nil)
+         (instr (%code-vector-last-instruction (uvref lfun 0))))
+      (if (eql (ldb (byte 6 26) instr) 32)       ; LWZ
+        (let* ((nregs (- 32 (ldb (byte 5 21) instr)))
+               (pc (dpb (ldb (byte 2 0) instr) (byte 2 5) (ldb (byte 5 16) instr)))
+               (offset (%word-to-int (logand instr (lognot 7)))))
+          (declare (fixnum nregs pc offset))
+          (setq regs-used (1- (ash 1 nregs)))
+          (if at-pc
+            (if (>= at-pc pc)
+              (setq where-saved (- (ash (- offset) -3) nregs))
+              (setq regs-used nil)))))        
+      (values (and regs-used (bit-reverse-8 regs-used)) where-saved)))    
+  
+
+(defparameter *bit-reverse-8-table*
+  #.(let ((table (make-array 256 :element-type '(unsigned-byte 8))))
+      (dotimes (i 256)
+        (let ((j 0)
+              (out-mask (ash 1 7)))
+          (declare (fixnum j out-mask))
+          (dotimes (bit 8)
+            (when (logbitp bit i)
+              (setq j (logior j out-mask)))
+            (setq out-mask (ash out-mask -1)))
+          (setf (aref table i) j)))
+      table))
+
+(defun bit-reverse-8 (x)
+  (aref *bit-reverse-8-table* x))
+
+(defun %frame-savefn (p)
+  (if (fake-stack-frame-p p)
+    (%fake-stack-frame.fn p)
+    (%%frame-savefn p)))
+
+(defun %frame-savevsp (p)
+  (if (fake-stack-frame-p p)
+    (%fake-stack-frame.vsp p)
+    (%%frame-savevsp p)))
+
+(defun frame-vsp (frame)
+  (%frame-savevsp frame))
+
+;;; Return two values: the vsp of p and the vsp of p's "parent" frame.
+;;; The "parent" frame vsp might actually be the end of p's segment,
+;;; if the real "parent" frame vsp is in another segment.
+(defun vsp-limits (p context)
+  (let* ((vsp (%frame-savevsp p))
+         parent)
+    (when (eql vsp 0)
+      ; This frame is where the code continues after an unwind-protect cleanup form
+      (setq vsp (%frame-savevsp (child-frame p context))))
+    (flet ((grand-parent (frame)
+             (let ((parent (parent-frame frame context)))
+               (when (and parent (eq parent (%frame-backlink frame context)))
+                 (let ((grand-parent (parent-frame parent context)))
+                   (when (and grand-parent (eq grand-parent (%frame-backlink parent context)))
+                     grand-parent))))))
+      (declare (dynamic-extent #'grand-parent))
+      (let* ((frame p)
+             grand-parent)
+        (loop
+          (setq grand-parent (grand-parent frame))
+          (when (or (null grand-parent) (not (eql 0 (%frame-savevsp grand-parent))))
+            (return))
+          (setq frame grand-parent))
+        (setq parent (parent-frame frame context)))
+      (let* ((parent-vsp (if parent (%frame-savevsp parent) vsp))
+             (tcr (if context (bt.tcr context) (%current-tcr)))
+             (vsp-area (%fixnum-ref tcr target::tcr.vs-area)))
+        (if (eql 0 parent-vsp)
+          (values vsp vsp)              ; p is the kernel frame pushed by an unwind-protect cleanup form
+          (progn
+            (unless vsp-area
+              (error "~s is not a stack frame pointer for context ~s" p tcr))
+            (unless (%ptr-in-area-p parent-vsp vsp-area)
+              (setq parent-vsp (%fixnum-ref vsp-area target::area.high)))
+            (values vsp parent-vsp)))))))
+
+
+(defun catch-csp-p (p context)
+  (let ((catch (if context
+                 (bt.top-catch context)
+                 (%catch-top (%current-tcr)))))
+    (loop
+      (when (null catch) (return nil))
+      (let ((sp (catch-frame-sp catch)))
+        (when (eql sp p)
+          (return t)))
+      (setq catch (next-catch catch)))))
+
+(defun last-catch-since (sp context)
+  (let* ((tcr (if context (bt.tcr context) (%current-tcr)))
+         (catch (%catch-top tcr))
+         (last-catch nil))
+    (loop
+      (unless catch (return last-catch))
+      (let ((csp (uvref catch target::catch-frame.csp-cell)))
+        (when (%stack< sp csp context) (return last-catch))
+        (setq last-catch catch
+              catch (next-catch catch))))))
+
+(defun register-number->saved-register-index (regno)
+  (- regno ppc::save7))
+
+(defun %find-register-argument-value (context cfp regval bad)
+  (let* ((last-catch (last-catch-since cfp context))
+         (index (register-number->saved-register-index regval)))
+    (do* ((frame cfp
+                 (child-frame frame context))
+          (first t))
+         ((null frame))
+      (if (fake-stack-frame-p frame)
+        (return-from %find-register-argument-value
+          (xp-gpr-lisp (%fake-stack-frame.xp frame) regval))
+        (if first
+          (setq first nil)
+          (multiple-value-bind (lfun pc)
+              (cfp-lfun frame)
+            (when lfun
+              (multiple-value-bind (mask where)
+                  (registers-used-by lfun pc)
+                (when (if mask (logbitp index mask))
+                  (incf where (logcount (logandc2 mask (1- (ash 1 (1+ index))))))
+                  (return-from
+                   %find-register-argument-value
+                    (raw-frame-ref frame context where bad)))))))))
+    (get-register-value nil last-catch index)))
+
+(defun %set-register-argument-value (context cfp regval new)
+  (let* ((last-catch (last-catch-since cfp context))
+         (index (register-number->saved-register-index regval)))
+    (do* ((frame cfp
+                 (child-frame frame context))
+          (first t))
+         ((null frame))
+      (if (fake-stack-frame-p frame)
+        (return-from %set-register-argument-value
+          (setf (xp-gpr-lisp (%fake-stack-frame.xp frame) regval) new))
+        (if first
+          (setq first nil)
+          (multiple-value-bind (lfun pc)
+              (cfp-lfun frame)
+            (when lfun
+              (multiple-value-bind (mask where)
+                  (registers-used-by lfun pc)
+                (when (if mask (logbitp index mask))
+                  (incf where (logcount (logandc2 mask (1- (ash 1 (1+ index))))))
+                  (return-from
+                   %set-register-argument-value
+                    (raw-frame-set frame context where new)))))))))
+    (set-register-value new nil last-catch index)))
+
+(defun %raw-frame-ref (cfp context idx bad)
+  (declare (fixnum idx))
+  (multiple-value-bind (frame base)
+      (vsp-limits cfp context)
+    (let* ((raw-size (- base frame)))
+      (declare (fixnum frame base raw-size))
+      (if (and (>= idx 0)
+               (< idx raw-size))
+        (let* ((addr (- (the fixnum (1- base))
+                        idx)))
+          (multiple-value-bind (db-count first-db last-db)
+              (count-db-links-in-frame frame base context)
+            (let* ((is-db-link
+                    (unless (zerop db-count)
+                      (do* ((last last-db (previous-db-link last first-db)))
+                           ((null last))
+                        (when (= addr last)
+                          (return t))))))
+              (if is-db-link
+                (oldest-binding-frame-value context addr)
+                (%fixnum-ref addr)))))
+        bad))))
+
+(defun %raw-frame-set (cfp context idx new)
+  (declare (fixnum idx))
+  (multiple-value-bind (frame base)
+      (vsp-limits cfp context)
+    (let* ((raw-size (- base frame)))
+      (declare (fixnum frame base raw-size))
+      (if (and (>= idx 0)
+               (< idx raw-size))
+        (let* ((addr (- (the fixnum (1- base))
+                        idx)))
+          (multiple-value-bind (db-count first-db last-db)
+              (count-db-links-in-frame frame base context)
+            (let* ((is-db-link
+                    (unless (zerop db-count)
+                      (do* ((last last-db (previous-db-link last first-db)))
+                           ((null last))
+                        (when (= addr last)
+                          (return t))))))
+              (if is-db-link
+                (setf (oldest-binding-frame-value context addr) new)
+                (setf (%fixnum-ref addr) new))))
+          t)))))
+
+;;; Used for printing only.
+(defun index->address (p)
+  (when (fake-stack-frame-p p)
+    (setq p (%fake-stack-frame.sp p)))
+  (ldb (byte #+32-bit-target 32 #+64-bit-target 64 0)  (ash p target::fixnumshift)))
+
+
+(defun match-local-name (cellno info pc)
+  (when info
+    (let* ((syms (%car info))
+           (ptrs (%cdr info)))
+      (dotimes (i (length syms))
+        (let ((j (%i+ i (%i+ i i ))))
+          (and (eq (uvref ptrs j) (%ilogior (%ilsl (+ 6 target::word-shift) cellno) #o77))
+               (%i>= pc (uvref ptrs (%i+ j 1)))
+               (%i< pc (uvref ptrs (%i+ j 2)))
+               (return (aref syms i))))))))
+
+(defun get-register-value (address last-catch index)
+  (if address
+    (%fixnum-ref address)
+    (uvref last-catch (+ index target::catch-frame.save-save7-cell))))
+
+;;; Inverse of get-register-value
+
+(defun set-register-value (value address last-catch index)
+  (if address
+    (%fixnum-set address value)
+    (setf (uvref last-catch (+ index target::catch-frame.save-save7-cell))
+          value)))
+
+;;; I'm skeptical about a lot of this stuff on the PPC, but if anything it's
+;;; pretty PPC-specific
+
+;;; Act as if VSTACK-INDEX points somewhere where DATA could go & put it there.
+(defun set-lisp-data (vstack-index data)
+  (let* ((old (%access-lisp-data vstack-index)))
+    (if (closed-over-value-p old)
+      (set-closed-over-value old data)
+      (%store-lisp-data vstack-index data))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;extensions to let user access and modify values
+
+
+
+
+
+;;; nth-frame-info, set-nth-frame-info, & frame-lfun are in "inspector;new-backtrace"
+
+
+
+
+
+
+(defparameter *saved-register-count+1*
+  (1+ *saved-register-count*))
+
+
+
+(defparameter *saved-register-numbers*
+  #+x8664-target #(wrong)
+  #+ppc-target #(31 30 29 28 27 26 25 24))
+
+;;; Don't do unbound checks in compiled code
+(declaim (type t *saved-register-count* *saved-register-count+1*
+               *saved-register-names* *saved-register-numbers*))
+
+(defmacro %cons-saved-register-vector ()
+  `(make-array (the fixnum *saved-register-count+1*) :initial-element nil))
+
+(defun copy-srv (from-srv &optional to-srv)
+  (if to-srv
+    (if (eq from-srv to-srv)
+      to-srv
+      (dotimes (i (uvsize from-srv) to-srv)
+        (setf (uvref to-srv i) (uvref from-srv i))))
+    (copy-uvector from-srv)))
+
+(defmacro srv.unresolved (saved-register-vector)
+  `(svref ,saved-register-vector 0))
+
+(defmacro srv.register-n (saved-register-vector n)
+  `(svref ,saved-register-vector (1+ ,n)))
+
+;;; This isn't quite right - has to look at all functions on stack,
+;;; not just those that saved VSPs.
+
+
+(defun frame-restartable-p (target &optional context)
+  (multiple-value-bind (frame last-catch srv) (last-catch-since-saved-vars target context)
+    (when frame
+      (loop
+        (when (null frame)
+          (return-from frame-restartable-p nil))
+        (when (eq frame target) (return))
+        (multiple-value-setq (frame last-catch srv)
+          (ccl::parent-frame-saved-vars context frame last-catch srv srv)))
+      (when (and srv (eql 0 (srv.unresolved srv)))
+        (setf (srv.unresolved srv) last-catch)
+        srv))))
+
+
+;;; get the saved register addresses for this frame
+;;; still need to worry about this unresolved business
+;;; could share some code with parent-frame-saved-vars
+(defun my-saved-vars (frame &optional (srv-out (%cons-saved-register-vector)))
+  (let ((unresolved 0))
+    (multiple-value-bind (lfun pc) (cfp-lfun frame)
+        (if lfun
+          (multiple-value-bind (mask where) (registers-used-by lfun pc)
+            (when mask
+              (if (not where) 
+                (setq unresolved (%ilogior unresolved mask))
+                (let ((vsp (- (frame-vsp frame) where (1- (logcount mask))))
+                      (j *saved-register-count*))
+                  (declare (fixnum j))
+                  (dotimes (i j)
+                    (declare (fixnum i))
+                    (when (%ilogbitp (decf j) mask)
+                      (setf (srv.register-n srv-out i) vsp
+                            vsp (1+ vsp)
+                            unresolved (%ilogand unresolved (%ilognot (%ilsl j 1))))))))))
+          (setq unresolved (1- (ash 1 *saved-register-count*)))))
+    (setf (srv.unresolved srv-out) unresolved)
+    srv-out))
+
+(defun parent-frame-saved-vars 
+       (context frame last-catch srv &optional (srv-out (%cons-saved-register-vector)))
+  (copy-srv srv srv-out)
+  (let* ((parent (and frame (parent-frame frame context)))
+         (grand-parent (and parent (parent-frame parent context))))
+    (when grand-parent
+      (loop (let ((next-catch (and last-catch (next-catch last-catch))))
+              ;(declare (ignore next-catch))
+              (if (and next-catch (%stack< (catch-frame-sp next-catch) grand-parent context))
+                (progn
+                  (setf last-catch next-catch
+                        (srv.unresolved srv-out) 0)
+                  (dotimes (i *saved-register-count*)
+                    (setf (srv.register-n srv i) nil)))
+                (return))))
+      (lookup-registers parent context grand-parent srv-out)
+      (values parent last-catch srv-out))))
+
+(defun lookup-registers (parent context grand-parent srv-out)
+  (unless (or (eql (frame-vsp grand-parent) 0)
+              (let ((gg-parent (parent-frame grand-parent context)))
+                (eql (frame-vsp gg-parent) 0)))
+    (multiple-value-bind (lfun pc) (cfp-lfun parent)
+      (when lfun
+        (multiple-value-bind (mask where) (registers-used-by lfun pc)
+          (when mask
+            (locally (declare (fixnum mask))
+              (if (not where) 
+                (setf (srv.unresolved srv-out) (%ilogior (srv.unresolved srv-out) mask))
+                (let* ((grand-parent-vsp (frame-vsp grand-parent)))
+
+                  (let ((vsp (- grand-parent-vsp where 1))
+                        (j *saved-register-count*))
+                    (declare (fixnum j))
+                    (dotimes (i j)
+                      (declare (fixnum i))
+                      (when (%ilogbitp (decf j) mask)
+                        (setf (srv.register-n srv-out i) vsp
+                              vsp (1- vsp)
+                              (srv.unresolved srv-out)
+                              (%ilogand (srv.unresolved srv-out) (%ilognot (%ilsl j 1))))))))))))))))
+
+;;; initialization for looping on parent-frame-saved-vars
+(defun last-catch-since-saved-vars (frame context)
+  (let* ((parent (parent-frame frame context))
+         (last-catch (and parent (last-catch-since parent context))))
+    (when last-catch
+      (let ((frame (catch-frame-sp last-catch))
+            (srv (%cons-saved-register-vector)))
+        (setf (srv.unresolved srv) 0)
+        (let* ((parent (parent-frame frame context))
+               (child (and parent (child-frame parent context))))
+          (when child
+            (lookup-registers child context parent srv))
+          (values child last-catch srv))))))
+
+;;; Returns 2 values:
+;;; mask srv
+;;; The mask says which registers are used at PC in LFUN.  srv is a
+;;; saved-register-vector whose register contents are the register
+;;; values registers whose bits are not set in MASK or set in
+;;; UNRESOLVED will be returned as NIL.
+
+(defun saved-register-values 
+       (lfun pc child last-catch srv &optional (srv-out (%cons-saved-register-vector)))
+  (declare (ignore child))
+  (cond ((null srv-out) (setq srv-out (copy-uvector srv)))
+        ((eq srv-out srv))
+        (t (dotimes (i (the fixnum (uvsize srv)))
+             (setf (uvref srv-out i) (uvref srv i)))))
+  (let ((mask (or (registers-used-by lfun pc) 0))
+        (unresolved (srv.unresolved srv))
+        (j *saved-register-count*))
+    (declare (fixnum j))
+    (dotimes (i j)
+      (declare (fixnum i))
+      (setf (srv.register-n srv-out i)
+            (and (%ilogbitp (setq j (%i- j 1)) mask)
+                 (not (%ilogbitp j unresolved))
+                 (safe-cell-value (get-register-value (srv.register-n srv i) last-catch j)))))
+    (setf (srv.unresolved srv-out) mask)
+    (values mask srv-out)))
+
+; Set the nth saved register to value.
+(defun set-saved-register (value n lfun pc child last-catch srv)
+  (declare (ignore lfun pc child) (dynamic-extent))
+  (let ((j (- target::node-size n))
+        (unresolved (srv.unresolved srv))
+        (addr (srv.register-n srv n)))
+    (when (logbitp j unresolved)
+      (error "Can't set register ~S to ~S" n value))
+    (set-register-value value addr last-catch j))
+  value)
+
+
+
+
+
+(defun return-from-nth-frame (n &rest values)
+  (apply-in-nth-frame n #'values values))
+
+(defun apply-in-nth-frame (n fn arglist)
+  (let* ((bt-info (car *backtrace-contexts*)))
+    (and bt-info
+         (let* ((frame (nth-frame nil (bt.youngest bt-info) n bt-info)))
+           (and frame (apply-in-frame frame fn arglist)))))
+  (format t "Can't return to frame ~d ." n))
+
+;;; This method is shadowed by one for the backtrace window.
+(defmethod nth-frame (w target n context)
+  (declare (ignore w))
+  (and target (dotimes (i n target)
+                (declare (fixnum i))
+                (unless (setq target (parent-frame target context)) (return nil)))))
+
+; If this returns at all, it's because the frame wasn't restartable.
+(defun apply-in-frame (frame fn arglist &optional context)
+  (let* ((srv (frame-restartable-p frame context))
+         (target-sp (and srv (srv.unresolved srv))))
+    (if target-sp
+      (apply-in-frame-internal context frame fn arglist srv))))
+
+(defun apply-in-frame-internal (context frame fn arglist srv)
+  (let* ((tcr (if context (bt.tcr context) (%current-tcr))))
+    (if (eq tcr (%current-tcr))
+      (%apply-in-frame frame fn arglist srv)
+      (let ((process (tcr->process tcr)))
+        (if process
+          (process-interrupt
+           process
+           #'%apply-in-frame
+           frame fn arglist srv)
+          (error "Can't find active process for ~s" tcr))))))
+
+
+(defun return-from-frame (frame &rest values)
+  (apply-in-frame frame #'values values nil))
+
+
+;;; (srv.unresolved srv) is the last catch frame, left there by
+;;; frame-restartable-p The registers in srv are locations of
+;;; variables saved between frame and that catch frame.
+(defun %apply-in-frame (frame fn arglist srv)
+  (declare (fixnum frame))
+  (let* ((catch (srv.unresolved srv))
+         (tsp-count 0)
+         (tcr (%current-tcr))
+         (parent (parent-frame frame tcr))
+         (vsp (frame-vsp parent))
+         (catch-top (%catch-top tcr))
+         (db-link (%svref catch target::catch-frame.db-link-cell))
+         (catch-count 0))
+    (declare (fixnum parent vsp db-link catch-count))
+    ;; Figure out how many catch frames to throw through
+    (loop
+      (unless catch-top
+        (error "Didn't find catch frame"))
+      (incf catch-count)
+      (when (eq catch-top catch)
+        (return))
+      (setq catch-top (next-catch catch-top)))
+    ;; Figure out where the db-link should be
+    (loop
+      (when (or (eql db-link 0) (>= db-link vsp))
+        (return))
+      (setq db-link (%fixnum-ref db-link)))
+    ;; Figure out how many TSP frames to pop after throwing.
+    (let ((sp (catch-frame-sp catch)))
+      (loop
+        (multiple-value-bind (f pc) (cfp-lfun sp)
+          (when f (incf tsp-count (active-tsp-count f pc))))
+        (setq sp (parent-frame sp tcr))
+        (when (eql sp parent) (return))
+        (unless sp (error "Didn't find frame: ~s" frame))))
+    #+debug
+    (cerror "Continue" "(apply-in-frame ~s ~s ~s ~s ~s ~s ~s)"
+            catch-count srv tsp-count db-link parent fn arglist)
+    (%%apply-in-frame catch-count srv tsp-count db-link parent fn arglist)))
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Code to determine how many tsp frames to pop.
+;;; This is done by parsing the code.
+;;; active-tsp-count is the entry point below.
+;;;
+
+(defstruct (branch-tree (:print-function print-branch-tree))
+  first-instruction
+  last-instruction
+  branch-target     ; a branch-tree or nil
+  fall-through)     ; a branch-tree or nil
+
+(defun print-branch-tree (tree stream print-level)
+  (declare (ignore print-level))
+  (print-unreadable-object (tree stream :type t :identity t)
+    (format stream "~s-~s"
+            (branch-tree-first-pc tree)
+            (branch-tree-last-pc tree))))
+
+(defun branch-tree-first-pc (branch-tree)
+  (let ((first (branch-tree-first-instruction branch-tree)))
+    (and first (instruction-element-address first))))
+
+(defun branch-tree-last-pc (branch-tree)
+  (let ((last (branch-tree-last-instruction branch-tree)))
+    (if last
+      (instruction-element-address last)
+      (branch-tree-first-pc branch-tree))))
+
+(defun branch-tree-contains-pc-p (branch-tree pc)
+  (<= (branch-tree-first-pc branch-tree)
+      pc
+      (branch-tree-last-pc branch-tree)))
+
+(defvar *branch-tree-hash*
+  (make-hash-table :test 'eq :weak :value))
+
+(defun get-branch-tree (function)
+  (or (gethash function *branch-tree-hash*)
+      (let* ((dll (function-to-dll-header function))
+             (tree (dll-to-branch-tree dll)))
+        (setf (gethash function *branch-tree-hash*) tree))))         
+
+; Return the number of TSP frames that will be active after throwing out
+; of all the active catch frames in function at pc.
+; PC is a byte address, a multiple of 4.
+(defun active-tsp-count (function pc)
+  (setq function
+        (require-type
+         (if (symbolp function)
+           (symbol-function function)
+           function)
+         'compiled-function))
+  (let* ((tree (get-branch-tree function))
+         (visited nil))
+    (labels ((find-pc (branch path)
+               (unless (memq branch visited)
+                 (push branch path)
+                 (if (branch-tree-contains-pc-p branch pc)
+                   path
+                   (let ((target (branch-tree-branch-target branch))
+                         (fall-through (branch-tree-fall-through branch)))
+                     (push branch visited)
+                     (if fall-through
+                       (or (and target (find-pc target path))
+                           (find-pc fall-through path))
+                       (and target (find-pc target path))))))))
+      (let* ((path (nreverse (find-pc tree nil)))
+             (last-tree (car (last path)))
+             (catch-count 0)
+             (tsp-count 0))
+        (unless path
+          (error "Can't find path to pc: ~s in ~s" pc function))
+        (dolist (tree path)
+          (let ((next (branch-tree-first-instruction tree))
+                (last (branch-tree-last-instruction tree)))
+            (loop
+              (when (and (eq tree last-tree)
+                         (eql pc (instruction-element-address next)))
+                ; If the instruction before the current one is an ff-call,
+                ; then callback pushed a TSP frame.
+                #| ; Not any more
+                (when (ff-call-instruction-p (dll-node-pred next))
+                  (incf tsp-count))
+                |#
+                (return))
+              (multiple-value-bind (type target fall-through count) (categorize-instruction next)
+                (declare (ignore target fall-through))
+                (case type
+                  (:tsp-push
+                   (when (eql catch-count 0)
+                     (incf tsp-count count)))
+                  (:tsp-pop
+                   (when (eql catch-count 0)
+                     (decf tsp-count count)))
+                  ((:catch :unwind-protect)
+                   (incf catch-count))
+                  (:throw
+                   (decf catch-count count))))
+              (when (eq next last)
+                (return))
+              (setq next (dll-node-succ next)))))
+        tsp-count))))
+        
+
+(defun dll-to-branch-tree (dll)
+  (let* ((hash (make-hash-table :test 'eql))    ; start-pc -> branch-tree
+         (res (collect-branch-tree (dll-header-first dll) dll hash))
+         (did-something nil))
+    (loop
+      (setq did-something nil)
+      (let ((mapper #'(lambda (key value)
+                        (declare (ignore key))
+                        (flet ((maybe-collect (pc)
+                                 (when (integerp pc)
+                                   (let ((target-tree (gethash pc hash)))
+                                     (if target-tree
+                                       target-tree
+                                       (progn
+                                         (collect-branch-tree (dll-pc->instr dll pc) dll hash)
+                                         (setq did-something t)
+                                         nil))))))
+                          (declare (dynamic-extent #'maybe-collect))
+                          (let ((target-tree (maybe-collect (branch-tree-branch-target value))))
+                            (when target-tree (setf (branch-tree-branch-target value) target-tree)))
+                          (let ((target-tree (maybe-collect (branch-tree-fall-through value))))
+                            (when target-tree (setf (branch-tree-fall-through value) target-tree)))))))
+        (declare (dynamic-extent mapper))
+        (maphash mapper hash))
+      (unless did-something (return)))
+    ; To be totally correct, we should fix up the trees containing
+    ; the BLR instruction for unwind-protect cleanups, but none
+    ; of the users of this code yet care that it appears that the code
+    ; stops there.
+    res))
+
+(defun collect-branch-tree (instr dll hash)
+  (unless (eq instr dll)
+    (let ((tree (make-branch-tree :first-instruction instr))
+          (pred nil)
+          (next instr))
+      (setf (gethash (instruction-element-address instr) hash)
+            tree)
+      (loop
+        (when (eq next dll)
+          (setf (branch-tree-last-instruction tree) pred)
+          (return))
+        (multiple-value-bind (type target fall-through) (categorize-instruction next)
+          (case type
+            (:label
+             (when pred
+               (setf (branch-tree-last-instruction tree) pred
+                     (branch-tree-fall-through tree) (instruction-element-address next))
+               (return)))
+            ((:branch :catch :unwind-protect)
+             (setf (branch-tree-last-instruction tree) next
+                   (branch-tree-branch-target tree) target
+                   (branch-tree-fall-through tree) fall-through)
+             (return))))
+        (setq pred next
+              next (dll-node-succ next)))
+      tree)))
+
+;;; Returns 4 values:
+;;; 1) type: one of :regular, :label, :branch, :catch, :unwind-protect, :throw, :tsp-push, :tsp-pop
+;;; 2) branch target (or catch or unwind-protect cleanup)
+;;; 3) branch-fallthrough (or catch or unwind-protect body)
+;;; 4) Count for throw, tsp-push, tsp-pop
+(defun categorize-instruction (instr)
+  (etypecase instr
+    (lap-label :label)
+    (lap-instruction
+     (let* ((opcode (lap-instruction-opcode instr))
+            (opcode-p (typep opcode 'opcode))
+            (name (if opcode-p (opcode-name opcode) opcode))
+            (pc (lap-instruction-address instr))
+            (operands (lap-instruction-parsed-operands instr)))
+       (cond ((equalp name "bla")
+              (let ((subprim (car operands)))
+                (case subprim
+                  (.SPmkunwind
+                   (values :unwind-protect (+ pc 4) (+ pc 8)))
+                  ((.SPmkcatch1v .SPmkcatchmv)
+                   (values :catch (+ pc 4) (+ pc 8)))
+                  (.SPthrow
+                   (values :branch nil nil))
+                  ((.SPnthrowvalues .SPnthrow1value)
+                   (let* ((prev-instr (require-type (lap-instruction-pred instr)
+                                                    'lap-instruction))
+                          (prev-name (opcode-name (lap-instruction-opcode prev-instr)))
+                          (prev-operands (lap-instruction-parsed-operands prev-instr)))
+                     ; Maybe we should recognize the other possible outputs of ppc2-lwi, but I
+                     ; can't imagine we'll ever see them
+                     (unless (and (equalp prev-name "li")
+                                  (equalp (car prev-operands) "imm0"))
+                       (error "Can't determine throw count for ~s" instr))
+                     (values :throw nil (+ pc 4) (ash (cadr prev-operands) (- target::fixnum-shift)))))
+                  ((.SPprogvsave
+                    .SPstack-rest-arg .SPreq-stack-rest-arg .SPstack-cons-rest-arg
+                    .SPmakestackblock .SPmakestackblock0 .SPmakestacklist .SPstkgvector
+                    .SPstkconslist .SPstkconslist-star
+                    .SPmkstackv .SPstack-misc-alloc .SPstack-misc-alloc-init
+                    .SPstkvcell0 .SPstkvcellvsp
+                    .SPsave-values)
+                   (values :tsp-push nil nil 1))
+                  (.SPrecover-values
+                   (values :tsp-pop nil nil 1))
+                  (t :regular))))
+             ((or (equalp name "lwz") (equalp name "addi"))
+              (if (equalp (car operands) "tsp")
+                (values :tsp-pop nil nil 1)
+                :regular))
+             ((equalp name "stwu")
+              (if (equalp (car operands) "tsp")
+                (values :tsp-push nil nil 1)
+                :regular))
+             ((member name '("ba" "blr" "bctr") :test 'equalp)
+              (values :branch nil nil))
+             ; It would probably be faster to determine the branch address by adding the PC and the offset.
+             ((equalp name "b")
+              (values :branch (branch-label-address instr (car (last operands))) nil))
+             ((and opcode-p (eql (opcode-majorop opcode) 16))
+              (values :branch (branch-label-address instr (car (last operands))) (+ pc 4)))
+             (t :regular))))))
+
+(defun branch-label-address (instr label-name &aux (next instr))
+  (loop
+    (setq next (dll-node-succ next))
+    (when (eq next instr)
+      (error "Couldn't find label ~s" label-name))
+    (when (and (typep next 'lap-label)
+               (eq (lap-label-name next) label-name))
+      (return (instruction-element-address next)))))
+
+(defun dll-pc->instr (dll pc)
+  (let ((next (dll-node-succ dll)))
+    (loop
+      (when (eq next dll)
+        (error "Couldn't find pc: ~s in ~s" pc dll))
+      (when (eql (instruction-element-address next) pc)
+        (return next))
+      (setq next (dll-node-succ next)))))
+
+(defun exception-frame-p (frame)
+  (fake-stack-frame-p frame))
+
+(defun arg-check-call-arguments (frame function)
+  (declare (ignore function))
+  (xp-argument-list (%fake-stack-frame.xp frame)))
Index: /branches/new-random/lib/ppc-init-ccl.lisp
===================================================================
--- /branches/new-random/lib/ppc-init-ccl.lisp	(revision 13309)
+++ /branches/new-random/lib/ppc-init-ccl.lisp	(revision 13309)
@@ -0,0 +1,64 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+a;;;   Opensourced MCL is distributed in the hope that it will be useful,
+;;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;   Lesser General Public License for more details.
+;;;
+;;;   You should have received a copy of the GNU Lesser General Public
+;;;   License along with this library; if not, write to the Free Software
+;;;   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;(setq *save-local-symbols* t)
+
+#+ppc-target
+(progn
+(breaker)
+(format t "~&Initializing Macintosh Common Lisp ...")
+(setq *load-verbose* t)
+(setq *warn-if-redefine* nil)
+(setq *.fasl-pathname* (pathname ".pfsl")) ; leave it?
+(setq *.pfsl-pathname* (pathname ".pfsl"))
+(setq *fasl-target* :ppc)
+(setq *save-exit-functions* nil)
+
+(require 'compile-ccl)
+(ppc-load-ccl)
+
+(setq *warn-if-redefine* t)
+(setq *load-verbose* nil)
+(format t "~&Macintosh Common Lisp Loaded")
+
+(defun save-mcl-libraries (&optional (suffix ""))
+  (save-library (concatenate 'string "ccl:ccl;pmcl-compiler" suffix)
+                "pmcl-compiler" *nx-start* *nx-end*)
+  ; More here ?
+  ; Pick up the leftovers ...
+  (save-library (concatenate 'string "ccl:ccl;pmcl-library" suffix)
+                "pmcl-library" nil nil))
+
+(defun save-it (&optional (suffix ""))
+  (save-mcl-libraries (and suffix (concatenate 'string "-" suffix)))
+  (let ((prefix "ccl:ccl;PPCCL"))
+    (save-application (if suffix
+                        (concatenate 'string prefix " " suffix)
+                        prefix))))
+
+;(save-application "ccl;CCL")
+)
+; End of init-ccl.lisp
Index: /branches/new-random/lib/ppcenv.lisp
===================================================================
--- /branches/new-random/lib/ppcenv.lisp	(revision 13309)
+++ /branches/new-random/lib/ppcenv.lisp	(revision 13309)
@@ -0,0 +1,93 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defconstant $numppcsaveregs 8)
+(defconstant $numppcargregs 3)
+
+
+(defconstant ppc-nonvolatile-registers-mask
+  (logior (ash 1 ppc::save0)
+          (ash 1 ppc::save1)
+          (ash 1 ppc::save2)
+          (ash 1 ppc::save3)
+          (ash 1 ppc::save4)
+          (ash 1 ppc::save5)
+          (ash 1 ppc::save6)
+          (ash 1 ppc::save7)))
+
+(defconstant ppc-arg-registers-mask
+  (logior (ash 1 ppc::arg_z)
+          (ash 1 ppc::arg_y)
+          (ash 1 ppc::arg_x)))
+
+(defconstant ppc-temp-registers-mask
+  (logior (ash 1 ppc::temp0)
+          (ash 1 ppc::temp1)
+          (ash 1 ppc::temp2)
+          (ash 1 ppc::temp3)))
+
+
+(defconstant ppc-tagged-registers-mask
+  (logior ppc-temp-registers-mask
+          ppc-arg-registers-mask
+          ppc-nonvolatile-registers-mask))
+
+
+
+(defconstant ppc-temp-node-regs 
+  (make-mask ppc::temp0
+             ppc::temp1
+             ppc::temp2
+             ppc::temp3
+             ppc::arg_x
+             ppc::arg_y
+             ppc::arg_z))
+
+(defconstant ppc-nonvolatile-node-regs
+  (make-mask ppc::save0
+             ppc::save1
+             ppc::save2
+             ppc::save3
+             ppc::save4
+             ppc::save5
+             ppc::save6
+             ppc::save7))
+
+
+(defconstant ppc-node-regs (logior ppc-temp-node-regs ppc-nonvolatile-node-regs))
+
+(defconstant ppc-imm-regs (make-mask
+                            ppc::imm0
+                            ppc::imm1
+                            ppc::imm2
+                            ppc::imm3
+                            ppc::imm4
+                            ppc::imm5))
+
+(defconstant ppc-temp-fp-regs (1- (ash 1 ppc::fp14)))
+                               
+(defconstant ppc-cr-fields
+  (make-mask 0 (ash 4 -2) (ash 8 -2) (ash 12 -2) (ash 16 -2) (ash 20 -2) (ash 24 -2) (ash 28 -2)))
+
+
+
+(defconstant $undo-ppc-c-frame 16)
+
+
+(ccl::provide "PPCENV")
Index: /branches/new-random/lib/pprint.lisp
===================================================================
--- /branches/new-random/lib/pprint.lisp	(revision 13309)
+++ /branches/new-random/lib/pprint.lisp	(revision 13309)
@@ -0,0 +1,2035 @@
+;-*-syntax:COMMON-LISP;Package:"CCL"-*-
+
+;;	Change History (most recent first):
+;;  2 4/8/97   akh  pretty-loop dont loop
+;;  3 12/13/95 Alice Hartley no call compiler at load time
+;;  3 3/2/95   akh  will promote strings to fat strings if needed
+;;  (do not edit before this line!!)
+
+
+;------------------------------------------------------------------------
+
+;Copyright 1989,1990 by the Massachusetts Institute of Technology, Cambridge, 
+;Massachusetts.
+
+;Permission to use, copy, modify, and distribute this software and its
+;documentation for any purpose and without fee is hereby granted,
+;provided that this copyright and permission notice appear in all
+;copies and supporting documentation, and that the name of M.I.T. not
+;be used in advertising or publicity pertaining to distribution of the
+;software without specific, written prior permission. M.I.T. makes no
+;representations about the suitability of this software for any
+;purpose.  It is provided "as is" without express or implied warranty.
+
+;    M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+;    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+;    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+;    ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+;    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+;    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+;    SOFTWARE.
+
+;------------------------------------------------------------------------
+
+;This file "XP.LISP" implements an efficient pretty printer for Common
+;Lisp.  The functions in this file are documented fully in MIT/AIM-1102a, July
+;1989.  This report can be obtained by sending $3.25 to
+
+;              Publications
+;	       MIT AI Laboratory
+;	       545 Tech. Sq.
+;	       Cambridge MA 02139
+
+;This file attempts to be as compatible with pure Common Lisp as possible.
+;It has been tested on the following Common Lisps to date (7/31/89).
+;  Symbolics CL version 7 (does not work in version 6),
+;  LUCID CL version 3.0.2 on a sun.
+;  Allegro CL version 1.2.1 on a Macintosh.
+;  CMU CL.
+
+;The companion file "XPTEST.LISP" contains a set of 600+ tests.  You should
+;run these tests after the first time you compile this file on a new system.
+
+;The companion file "XPDOC.TXT" contains brief documentation
+; 04/05/97 akh  pretty-loop fix for *print-level* exceeded
+; 10/26/95 slh   %gvector -> %istruct
+; 08/26/93 bill  indentation
+; -------- 3.0d12
+; 06/26/93 alice stream-fresh-line (xp-stream) was producing premature newlines
+; 05/24/93 alice *free-xps* and *free-circularity-hash-tables* are global
+; 03/04/93 alice set *error-print-circle* to T
+; 02/23/93 alice get-printer - look in others table before def.., with.. hack
+; 02/15/93 alice don't unwind-protect in pprint-logical-block+
+; 12/21/92 alice lets not print loop as #'
+; 06/23/92 alice change set-pprint-dispatch+ and priority-> so '(0) is less than 0
+;--------------- 2.0
+; 02/22/92 (alice from "post 2.0f2c5:pprint-defmethod-patch") fix DEFMETHOD-LIKE.
+; -------- 2.0f2c5
+; 01/29/92 gb    pretty-structure calls structure-print-function.
+; -------- 2.0f2
+; 10/11/91 alice dont print generic-function as #'
+; 10/09/91 alice write+ don't deal with structures and arrays - prior fix was brain dead
+;    p.s. technically we shouldn't special case strings, fixnums and symbols either
+; 10/03/91 alice write+ - if print-object method for structure use it.
+; 09/25/91 alice fix circularity-process so we can rebind *print-circle* in mid stream 
+; 09/25/91 alice pretty-structure - no dangling space if no slots
+; 09/24/91 alice fix pretty-structure bogus keyword printing
+; 09/11/91 alice keep first pass output until first circularity in case no circularities
+; 09/09/91 alice fix print circle in case circularity detected after first line (geez)
+; 		dont die if *print-pprint-dispatch* is nil
+;--------------- 2.0b3
+; 08/21/91 gb xp-stream-stream
+; 07/21/91 gb def-accessors vice defstruct.
+; 07/09/91 alice allow write+ to tail call 
+; 07/01/91 bind level and length as (f *print-readably*)
+; 07/01/91 generic-function & reinstate some MLY hacks for "def.." "with-.." etc.
+; 06/24/91 added pretty-structure
+; 05/22/91 Modified for MCL 2.0b
+;;;;;;;;;;;;;;
+;;; lisp: => cl:
+;;; string-char => character (or base-character?)
+;;; #-ccl-2 compiled format and format and much else
+;;;  put the xp-stream in the xp-structure
+;;; write-char => write-char+ in pretty-loop
+;;; nuke *last-abbreviated-printing*
+;;; Teach it about fred-special-indent-alist
+;;; in fred-alist 2 means defun-like, 0 is progn-like
+;;;   3 is defsetf-print , 1 is block-like
+;;; Put circularity table & number in the structure? - didn't do it
+;;; Nuke the xp package
+;;; Added progn-print
+;;; MAYBELAB take xp-stream or xp-structure
+;;; Gave up on #+/#-ccl-2
+;;; Could save a few hundred bytes by (funcall (formatter ...)) to (format ... )) - maybe not
+;;; The dispatch table could use some compacting: done!
+;;;  an entry contains test: 0 - must be some predicate if not of the other form
+;;;			fn: ok
+;;;                     full-spec: '((0)(cons (member defvar)))
+;;; Nuke *print-shared* and *parents*
+;;; This version has a new special *xp-current-object* but doesnt gratuitously cons.
+;;; Fixed circle doing it twice when it needn't (what does this break?)
+;;; member => memq
+;;; Apply optimizations as Mly did in prior conversion, i.e. liberal doses
+;;; of %i+, (declare (fixnum ...)), dont fetch a stucture field 15 times
+;;; when once will suffice, no char=, fewer position & find
+;;; Now about same speed as old one. (actually 10% slower) & it conses less
+;;; In pprint-dispatch just store the function if (cons (member blah)) & (0) or 0.
+;;; nuke some entries in pprint-dispatch where same info is in fred-special-indent-alist
+;;; Size is down from 23K larger to 18K larger.
+;;; maybe-print-fast iff readtable-case is :upcase
+;;; add defmethod-like for guess what
+;;;  nuke *abbreviation-happened*
+
+
+
+(in-package "CCL")
+
+(defvar *ipd* nil ;see initialization at end of file.
+  "initial print dispatch table.")
+
+(eval-when (:compile-toplevel :execute)
+  (declaim (inline xp-structure-p)))
+
+(defun xp-structure-p (x)
+  (istruct-typep x 'xp-structure))
+
+
+(defun entry-p (x)
+  (istruct-typep x 'entry))
+
+  
+
+;default (bad) definitions for the non-portable functions
+
+(eval-when (:execute :load-toplevel :compile-toplevel)
+(defun structure-type-p (x) (structurep x))
+(defun output-width     (&optional (s *standard-output*))
+  (when (streamp s)(line-length s)))
+(defun output-position  (&optional (s *standard-output*))
+  (when (streamp s)(column s)))
+)
+
+(defvar *logical-block-p* nil
+  "True if currently inside a logical block.")
+
+(defvar *locating-circularities* nil
+  "Integer if making a first pass over things to identify circularities.
+   Integer used as counter for #n= syntax.")
+
+(def-standard-initial-binding *free-circularity-hash-tables* nil)
+
+(defun get-circularity-hash-table ()
+  (let ((table (pop *free-circularity-hash-tables*)))
+    (if table table (make-hash-table :test 'eq))))
+
+;If you call this, then the table gets efficiently recycled.
+(defun free-circularity-hash-table (table)
+  (clrhash table)
+  (pushnew table *free-circularity-hash-tables*))
+
+
+
+;                       ---- DISPATCHING ----
+
+(cl:defstruct (pprint-dispatch-table (:conc-name nil) (:copier nil))
+  (conses-with-cars (make-hash-table :test #'eq) :type hash-table)
+  (structures (make-hash-table :test #'eq) :type (or null hash-table))
+  (others nil :type list))
+
+;The list and the hash-tables contain entries of the
+;following form.  When stored in the hash tables, the test entry is 
+;the number of entries in the OTHERS list that have a higher priority.
+
+(defun make-entry (&key test fn full-spec)
+  (%istruct 'entry test fn full-spec))
+
+(defun copy-pprint-dispatch (&optional (table *print-pprint-dispatch*))
+  (let* ((table (if (null table)
+                    *IPD*
+                    (require-type table '(or nil pprint-dispatch-table))))
+         (new-conses-with-cars
+           (make-hash-table :test #'eq
+	     :size (max (hash-table-count (conses-with-cars table)) 32)))
+	 (new-structures NIL))
+    (maphash #'(lambda (key value)
+		 (setf (gethash key new-conses-with-cars)
+                       (if (istruct-typep value 'entry)(copy-uvector value) value)))
+	     (conses-with-cars table))
+    (make-pprint-dispatch-table
+      :conses-with-cars new-conses-with-cars
+      :structures new-structures
+      :others (copy-list (others table)))))
+
+
+(defun set-pprint-dispatch (type-specifier function
+			    &optional (priority 0) (table *print-pprint-dispatch*))
+  (when (or (not (numberp priority)) (complexp priority))
+    (error "invalid PRIORITY argument ~A to SET-PPRINT-DISPATCH" priority))
+  (set-pprint-dispatch+ type-specifier function priority table))
+
+(defun set-pprint-dispatch+ (type-specifier function priority table)
+  (let* ((category (specifier-category type-specifier))
+	 (pred
+	   (if (not (eq category 'other)) nil
+	       (let ((pred (specifier-fn type-specifier)))
+		 (if (symbolp pred)
+                  (symbol-function pred)
+                  ; checking for (lambda (x) (foo x)) => #'foo 
+		  (if (and (consp (caddr pred))
+			   (symbolp (caaddr pred)) 
+			   (equal (cdaddr pred) '(x)))
+                    (symbol-function (caaddr pred))
+                    ; calling the compiler at load time is an indictable offense
+                    (compile nil pred))))))
+	 (entry (if function (make-entry :test pred
+					 :fn function
+					 :full-spec (list priority type-specifier)))))
+    (case category
+      (cons-with-car
+       (let ((key (cadadr type-specifier)) ;(cons (member FOO))
+             (cons-tbl (conses-with-cars table)))
+	(cond ((null function) (remhash key cons-tbl))
+	      (T (let ((num 
+		       (count-if #'(lambda (e)
+				     (priority-> e priority))
+				 (others table))))
+                   (cond ((and (or ;(eq priority 0)
+                                   (and (consp priority)(eq (%car priority) 0)))
+                               (eq num 0))
+                          (setq entry function))
+                         (t (setf (entry-test entry) num)))
+		   (setf (gethash key cons-tbl) entry))))))
+      (T ;other
+	 (let ((old (car (member type-specifier (others table) :test #'equal
+				 :key #'(lambda (e) (cadr (entry-full-spec e)))))))
+	   (when old
+	     (setf (others table) (delete old (others table)))
+	     (adjust-counts table (car (entry-full-spec old)) -1)))
+	 (when entry
+	   (let ((others (cons nil (others table))))
+	      (do ((l others (cdr l)))
+		  ((null (cdr l)) (rplacd l (list entry)))
+		(when (priority-> priority (car (entry-full-spec (cadr l))))
+		  (rplacd l (cons entry (cdr l)))
+		  (return nil)))
+	      (setf (others table) (cdr others)))
+	   (adjust-counts table priority 1)))))
+  nil)
+
+(defun priority-> (entry-x entry-y)
+  (flet ((foo (e)
+              (cond ((istruct-typep e 'entry)(car (entry-full-spec e)))
+                    ((or (numberp e)(consp  e)) e)
+                    (t '(0)))))
+    (let ((x (foo entry-x))
+          (y (foo entry-y)))      
+      (if (consp x)
+        (if (consp y) (> (car x) (car y)) nil)
+        (if (consp y) T (> x y))))))
+
+
+
+(defun adjust-counts (table priority delta)
+  (maphash #'(lambda (key value)
+	       (when (priority-> priority value)
+                 (when (not (istruct-typep value 'entry))
+                   (setf (gethash key (conses-with-cars table))
+                         (setq value (make-entry :fn value :test 0 :full-spec '(0)))))
+                 (incf (entry-test value) delta)))
+	   (conses-with-cars table)))
+
+(defun pprint-dispatch (object &optional (table *print-pprint-dispatch*))
+  (flet ((non-pretty-print (s object)
+           (write-not-pretty s object
+                             (if (get-*print-frob* '*print-level*)
+                               (- *print-level* *current-level*))
+                             nil nil)))
+    (when (null table) (setq table *IPD*))  
+    (let ((fn (get-printer object table)))
+      (values (or fn #'non-pretty-print) (not (null fn))))))
+
+(defun get-printer (object table)
+  (when (null table)(setq table *IPD*))
+  (let* (entry)
+    (cond ((consp object)
+           (setq entry (gethash (%car object) (conses-with-cars table)))
+           (when (not entry)
+             (setq entry (find object (others table) :test #'fits))
+             (if entry
+               (setq entry (entry-fn entry)))))
+          (nil (setq entry (gethash (type-of object) (structures table)))))
+    (if (not entry)
+      (setq entry (find object (others table) :test #'fits))
+      (if (istruct-typep entry 'entry)
+        (let ((test (entry-test entry)))
+          (when (numberp test)
+            (do ((i test (1- i))
+                 (l (others table) (cdr l)))
+                ((zerop i))
+              (when (fits object (car l)) (setq entry (car l)) (return nil)))))))    
+    (when entry 
+      (if (istruct-typep entry 'entry)(entry-fn entry) entry))))
+
+(defun fits (obj entry) 
+  (funcall (entry-test entry) obj))
+
+(defun specifier-category (spec)
+  (cond ((and (consp spec)
+	      (eq (car spec) 'cons)
+	      (consp (cdr spec))
+	      (null (cddr spec))
+	      (consp (cadr spec))
+	      (eq (caadr spec) 'member)
+	      (consp (cdadr spec))
+	      (null (cddadr spec)))
+	 'cons-with-car)
+	(T 'other)))
+
+
+; lets make fewer things fns that compile at load time, esp anything
+; we do - really none should
+(defun specifier-fn (spec) 
+  (if (and (consp spec)(eq (car spec) 'satisfies)(symbolp (cadr spec)))
+    (cadr spec)
+    (if (and (symbolp spec)(type-predicate spec))  ; ccl specific
+      (type-predicate spec)
+      `(lambda (x) ,(convert-body spec)))))
+
+(defun convert-body (spec)
+  (cond ((atom spec) `(typep x ',spec))
+	((member (car spec) '(and or not))
+	 (cons (car spec) (mapcar #'convert-body (cdr spec))))
+	((eq (car spec) 'member)
+	 `(member x ',(copy-list (cdr spec))))
+	((eq (car spec) 'cons)
+	 `(and (consp x)
+	       ,@(if (cdr spec) `((let ((x (car x)))
+				    ,(convert-body (cadr spec)))))
+	       ,@(if (cddr spec) `((let ((x (cdr x)))
+				     ,(convert-body (caddr spec)))))))
+	((eq (car spec) 'satisfies)
+	 `(funcall (function ,(cadr spec)) x))
+	(T `(typep x ',spec))))
+
+
+;               ---- XP STRUCTURES, AND THE INTERNAL ALGORITHM ----
+
+(eval-when (:execute :compile-toplevel) ;not used at run time.
+  (defvar block-stack-entry-size 1)
+  (defvar prefix-stack-entry-size 5)
+  (defvar queue-entry-size 7)
+  (defvar buffer-entry-size 1)
+  (defvar prefix-entry-size 1)
+  (defvar suffix-entry-size 1))
+
+(eval-when (:execute :load-toplevel :compile-toplevel) ;used at run time
+  (defvar block-stack-min-size #.(* 35. block-stack-entry-size))
+  (defvar prefix-stack-min-size #.(* 30. prefix-stack-entry-size))
+  (defvar queue-min-size #.(* 75. queue-entry-size))
+  (defvar buffer-min-size 256.)
+  (defvar prefix-min-size 256.)
+  (defvar suffix-min-size 256.)) 
+
+(progn
+  (setf (symbol-function 'xp-stream-stream) #'(lambda (s) (xp-stream s)))
+
+  (defmethod streamp ((x xp-structure)) t)
+  (defmethod streamp ((x xp-stream)) t)
+
+  (defmethod output-stream-p ((x xp-structure)) t)
+  (defmethod output-stream-p ((x xp-stream)) t)
+  
+  (defun make-xp-structure ()
+    (%istruct
+     'xp-structure
+     nil                                ; xp-base-stream
+     nil                                ; xp-linel
+     nil                                ; xp-line-limit
+     nil                                ; xp-line-no
+     nil                                ; xp-char-mode
+     nil                                ; xp-char-mode-counter
+     nil                                ; xp-depth-in-blocks
+     (make-array #.block-stack-min-size) ; xp-block-stack
+     nil                                ; xp-block-stack-ptr
+     (make-array #.buffer-min-size :element-type 'base-char)
+                                        ; use make-string and let it default?
+                                        ; xp-buffer
+     nil                                ; xp-charpos
+     nil                                ; xp-buffer-ptr
+     nil                                ; xp-buffer-offset
+     (make-array #.queue-min-size)      ; xp-queue
+     0                                  ; xp-qleft
+     0                                  ; xp-qright
+     (make-array #.buffer-min-size :element-type 'base-char)
+                                        ; xp-prefix
+     (make-array #.prefix-stack-min-size) ; xp-prefix-stack
+     nil                                ; xp-prefix-stack-ptr
+     (make-array #.buffer-min-size :element-type 'base-char)
+                                        ; xp-suffix
+     nil                                ; xp-stream
+     nil                                ; xp-string-stream
+     ))                            ; XP-STRUCTURE is a built-in class.
+
+  (defmethod write-internal-1 ((xp-struc xp-structure) object level list-kludge)
+    (write-internal-1 (xp-stream xp-struc) object level list-kludge))
+
+
+
+  (defun get-xp-stream (pp)
+    (xp-stream pp))
+  )
+
+
+ 
+(eval-when (:compile-toplevel :execute)
+(defmacro LP<-BP (xp &optional (ptr nil))
+  (if (null ptr) (setq ptr `(xp-buffer-ptr ,xp)))
+  `(the fixnum (%i+ ,ptr (xp-charpos ,xp))))
+(defmacro TP<-BP (xp)
+  `(the fixnum (%i+ (xp-buffer-ptr ,xp) (xp-buffer-offset ,xp))))
+(defmacro BP<-LP (xp ptr)
+  `(the fixnum (%i- ,ptr (xp-charpos ,xp))))
+(defmacro BP<-TP (xp ptr)
+  `(the fixnum (%i- ,ptr (xp-buffer-offset ,xp))))
+;This does not tell you the line position you were at when the TP
+;was set, unless there have been no newlines or indentation output 
+;between ptr and the current output point.
+(defmacro LP<-TP (xp ptr)
+  `(LP<-BP ,xp (BP<-TP ,xp ,ptr)))
+
+;We don't use adjustable vectors or any of that, because we seldom have
+;to actually extend and non-adjustable vectors are a lot faster in
+;many Common Lisps.
+
+(defmacro xp-check-size (FORM ptr min-size entry-size
+                           &optional (type '(simple-array * (*))))
+  `(let ((.old. ,form)
+         (.ptr. ,ptr))
+     (declare (type ,type .old.) (type fixnum .ptr.))
+     (if (and (ccl::%i> .ptr. ,(- min-size entry-size)) ;seldom haxpens
+              (ccl::%i> .ptr. (- (length (the ,type .old.)) ,entry-size)))
+         (let ((.new. ,(let ((l `(ccl::%i+ .ptr. ,(if (= entry-size 1)
+                                                    50
+                                                    (* 10 entry-size)))))
+                         `(make-array ,l :element-type (array-element-type .old.)))))
+           ;;>>
+           (replace .new. .old.)
+           (setf ,form .new.))
+         .old.)))
+
+(defmacro section-start (xp) `(svref (xp-block-stack ,xp) (xp-block-stack-ptr ,xp)))
+) ; eval-when
+
+;		---- CCL specific METHODS --------
+(progn
+(defmethod stream-write-char ((stream xp-stream) char)
+  (write-char+ char (slot-value stream 'xp-structure))
+  char)
+
+(defmethod stream-write-char ((stream xp-structure) char)
+  (write-char+ char stream)
+  char)
+
+(defmethod stream-write-string ((stream xp-stream) string &optional (start 0) end)
+  (setq end (check-sequence-bounds string start end))
+  (write-string+ string (slot-value stream 'xp-structure) start end)
+  string)
+
+(defmethod stream-write-string ((stream xp-structure) string &optional (start 0) end)
+  (setq end (check-sequence-bounds string start end))
+  (write-string+ string stream start end)
+  string)
+
+; If we really don't care about the value returned then just
+; plain (pprint-newline+ :fresh xp) is fine.
+(defmethod stream-fresh-line ((stream xp-stream))
+  (let ((xp (slot-value stream 'xp-structure)))
+    (attempt-to-output xp nil nil)  ; was (attempt-to-output xp T T)
+    (prog1 (not (zerop (LP<-BP xp)))      
+      (pprint-newline+ :fresh xp))))
+
+
+(defmethod stream-finish-output ((stream xp-stream))
+  (attempt-to-output (slot-value stream 'xp-structure) t t))
+
+(defmethod stream-force-output ((stream xp-stream))
+  (attempt-to-output (slot-value stream 'xp-structure) t t)
+  nil)
+
+(defmethod stream-clear-output ((stream xp-stream))
+  (let ((*locating-circularities* 1)) ;hack to prevent visible output
+    (attempt-to-output (slot-value stream 'xp-structure) T T))
+  nil)
+
+(defmethod stream-line-column ((stream xp-stream))
+  (LP<-BP (slot-value stream 'xp-structure)))
+
+(defmethod stream-line-length ((stream xp-stream))
+  (xp-linel (slot-value stream 'xp-structure)))
+
+)
+
+
+(defun push-block-stack (xp)
+  (let ((ptr (%i+ (xp-block-stack-ptr xp) #.block-stack-entry-size)))
+    (setf (xp-block-stack-ptr xp) ptr)
+    (xp-check-size (xp-block-stack xp) ptr
+                   #.block-stack-min-size #.block-stack-entry-size)))
+
+(eval-when (:compile-toplevel :execute)
+(defmacro prefix-ptr (xp)
+  `(svref (xp-prefix-stack ,xp) (xp-prefix-stack-ptr ,xp)))
+(defmacro suffix-ptr (xp)
+  `(svref (xp-prefix-stack ,xp) (%i+ (xp-prefix-stack-ptr ,xp) 1)))
+(defmacro non-blank-prefix-ptr (xp)
+  `(svref (xp-prefix-stack ,xp) (%i+ (xp-prefix-stack-ptr ,xp) 2)))
+(defmacro initial-prefix-ptr (xp)
+  `(svref (xp-prefix-stack ,xp) (%i+ (xp-prefix-stack-ptr ,xp) 3)))
+(defmacro section-start-line (xp)
+  `(svref (xp-prefix-stack ,xp) (%i+ (xp-prefix-stack-ptr ,xp) 4)))
+
+(defmacro stk-prefix-ptr (stk ptr)
+  `(svref ,stk ,ptr))
+(defmacro stk-suffix-ptr (stk ptr)
+  `(svref ,stk (%i+ ,ptr 1)))
+(defmacro stk-non-blank-prefix-ptr (stk ptr)
+  `(svref ,stk (%i+ ,ptr 2)))
+) ; EVAL-when
+
+
+
+; saves 100 bytes and a microsecond or 2
+(defun push-prefix-stack (xp)
+  (let ((old-prefix 0)
+        (old-suffix 0) 
+        (old-non-blank 0)
+        (stack (xp-prefix-stack xp))
+        (ptr (xp-prefix-stack-ptr xp)))
+    (declare (fixnum ptr))
+    (when (>= ptr 0)
+      (setq old-prefix (stk-prefix-ptr stack ptr)
+	    old-suffix (stk-suffix-ptr stack ptr)
+	    old-non-blank (stk-non-blank-prefix-ptr stack ptr)))
+    (setq ptr (%i+ ptr #.prefix-stack-entry-size))
+    (setf (xp-prefix-stack-ptr xp) ptr)
+    (setq stack
+          (xp-check-size (xp-prefix-stack xp) ptr
+                   #.prefix-stack-min-size #.prefix-stack-entry-size))
+    (setf (stk-prefix-ptr stack ptr) old-prefix)
+    (setf (stk-suffix-ptr stack ptr) old-suffix)
+    (setf (stk-non-blank-prefix-ptr stack ptr) old-non-blank)))
+
+
+
+(eval-when (:compile-toplevel :execute)
+(defmacro Qtype   (xp index) `(svref (xp-queue ,xp) ,index))
+(defmacro Qkind   (xp index) `(svref (xp-queue ,xp) (1+ ,index)))
+(defmacro Qpos    (xp index) `(svref (xp-queue ,xp) (+ ,index 2)))
+(defmacro Qdepth  (xp index) `(svref (xp-queue ,xp) (+ ,index 3)))
+(defmacro Qend    (xp index) `(svref (xp-queue ,xp) (+ ,index 4)))
+(defmacro Qoffset (xp index) `(svref (xp-queue ,xp) (+ ,index 5)))
+(defmacro Qarg    (xp index) `(svref (xp-queue ,xp) (+ ,index 6)))
+(defmacro xpq-type (queue index)
+  `(svref ,queue ,index))
+(defmacro xpq-kind (queue index)
+  `(svref ,queue (ccl::%i+ ,index 1)))
+(defmacro xpq-pos (queue index)
+  `(svref ,queue (ccl::%i+ ,index 2)))
+(defmacro xpq-depth (queue index)
+  `(svref ,queue (ccl::%i+ ,index 3)))
+(defmacro xpq-end (queue index)
+  `(svref ,queue (ccl::%i+ ,index 4)))
+(defmacro xpq-offset (queue index)
+  `(svref ,queue (ccl::%i+ ,index 5)))
+(defmacro xpq-arg (queue index)
+  `(svref ,queue (ccl::%i+ ,index 6)))
+) ; eval-when
+
+;we shift the queue over rather than using a circular queue because
+;that works out to be a lot faster in practice.  Note, short printout
+;does not ever cause a shift, and even in long printout, the queue is
+;shifted left for free every time it happens to empty out.
+
+(defun enqueue (xp type kind &optional arg)  
+  (let ((queue (xp-queue xp))
+        (qright (ccl::%i+ (xp-qright xp) #.queue-entry-size))
+        (qleft (xp-qleft xp)))
+    (declare (type fixnum qright qleft) (type simple-vector queue))
+    (when (ccl::%i> qright #.(- queue-min-size queue-entry-size))
+      ;;>> generic
+      (replace queue queue :start2 qleft :end2 qright)
+      (setf (xp-qleft xp) 0
+            qright (ccl::%i- qright qleft)))
+    (setq queue (xp-check-size (xp-queue  xp) qright
+                               #.queue-min-size #.queue-entry-size))
+    (setf (xp-qright xp) qright
+          (xpq-type queue qright) type
+          (xpq-kind queue qright) kind
+          (xpq-pos queue qright) (TP<-BP xp)
+          (xpq-depth queue qright) (xp-depth-in-blocks xp)
+          (xpq-end queue qright) nil
+          (xpq-offset queue qright) nil
+          (xpq-arg queue qright) arg)))
+
+(defmacro Qnext (index) `(%i+ ,index #.queue-entry-size))
+
+
+
+;This maintains a list of XP structures.  We save them
+;so that we don't have to create new ones all of the time.
+;We have separate objects so that many can be in use at once.
+
+;(Note should really be doing some locking here, but CL does not have the
+;primitives for it.  There is a tiny probability here that two different
+;processes could end up trying to use the same xp-stream)
+
+(def-standard-initial-binding *free-xps* nil) ;free list of XP stream objects
+
+(defun get-pretty-print-stream (stream)
+  (let ((xp (without-interrupts (pop *free-xps*))))
+    (when (not xp)(setq xp (make-xp-structure)))
+    (initialize-xp xp stream)
+    (let ((the-xp-stream (make-instance  'xp-stream)))
+      (setf (slot-value the-xp-stream 'xp-structure) xp)
+      (setf (xp-stream xp) the-xp-stream) ; lets be circular
+      the-xp-stream)))
+
+;If you call this, the xp-stream gets efficiently recycled.
+
+(defun free-pretty-print-stream (xp)
+  (setf (xp-base-stream xp) nil)
+  (pushnew xp *free-xps*))
+
+;This is called to initialize things when you start pretty printing.
+
+(defun initialize-xp (xp stream)
+  (setf (xp-base-stream xp) stream)
+  (setf (xp-linel xp) (max 0 (cond (*print-right-margin*)
+				           ((output-width stream))
+				           (T *default-right-margin*))))
+  (setf (xp-line-limit xp) *print-lines*)
+  (setf (xp-line-no xp) 1)
+  (setf (xp-char-mode xp) nil)
+  (setf (xp-char-mode-counter xp) 0)
+  (setf (xp-depth-in-blocks xp) 0)
+  (setf (xp-block-stack-ptr xp) 0)
+  (setf (xp-charpos xp) (cond ((output-position stream)) (T 0)))
+  (setf (section-start xp) 0)
+  (setf (xp-buffer-ptr xp) 0)
+  (setf (xp-buffer-offset xp) (xp-charpos xp))
+  (setf (xp-qleft xp) 0)
+  (setf (xp-qright xp) #.(- queue-entry-size))
+  (setf (xp-prefix-stack-ptr xp) #.(- prefix-stack-entry-size))
+  (let ((s (xp-string-stream xp)))
+    (when s (stream-position s 0)))
+  xp)
+
+
+;The char-mode stuff is a bit tricky.
+;one can be in one of the following modes:
+;NIL no changes to characters output.
+;:UP CHAR-UPCASE used.
+;:DOWN CHAR-DOWNCASE used.
+;:CAP0 capitalize next alphanumeric letter then switch to :DOWN.
+;:CAP1 capitalize next alphanumeric letter then switch to :CAPW
+;:CAPW downcase letters.  When a word break letter found, switch to :CAP1.
+;It is possible for ~(~) to be nested in a format string, but note that
+;each mode specifies what should happen to every letter.  Therefore, inner
+;nested modes never have any effect.  You can just ignore them.
+
+(defun push-char-mode (xp new-mode)
+  (if (zerop (xp-char-mode-counter xp))
+      (setf (xp-char-mode xp) new-mode))
+  (incf (xp-char-mode-counter xp)))
+
+(defun pop-char-mode (xp)
+  (decf (xp-char-mode-counter xp))
+  (if (zerop (xp-char-mode-counter xp))
+      (setf (xp-char-mode xp) nil)))
+
+;Assumes is only called when char-mode is non-nil
+(defun handle-char-mode (xp char)
+  (case (xp-char-mode xp)
+    (:CAP0 (cond ((not (alphanumericp char)) char)
+		 (T (setf (xp-char-mode xp) :DOWN) (char-upcase char))))
+    (:CAP1 (cond ((not (alphanumericp char)) char)
+		 (T (setf (xp-char-mode xp) :CAPW) (char-upcase char))))
+    (:CAPW (cond ((alphanumericp char) (char-downcase char))
+		 (T (setf (xp-char-mode xp) :CAP1) char)))
+    (:UP (char-upcase char))
+    (T (char-downcase char)))) ;:DOWN
+
+;All characters output are passed through the handler above.  However, it must
+;be noted that on-each-line prefixes are only processed in the context of the
+;first place they appear.  They stay the same later no matter what.  Also
+;non-literal newlines do not count as word breaks.
+
+
+;This handles the basic outputting of characters.  note + suffix means that
+;the stream is known to be an XP stream, all inputs are mandatory, and no
+;error checking has to be done.  Suffix ++ additionally means that the
+;output is guaranteed not to contain a newline char.
+
+(defun write-char+ (char xp)
+  (if (eql char #\newline) (pprint-newline+ :unconditional xp)
+      (write-char++ char xp)))
+
+(defun write-string+ (string xp start end)
+  (let ((sub-end nil) next-newline)
+    (loop (setq next-newline
+		(if (typep string 'simple-string)
+                  (%str-member #\newline string start end)
+                  (position #\newline string :start start :end end :test #'eq )))
+	  (setq sub-end (if next-newline next-newline end))
+	  (write-string++ string xp start sub-end)
+	  (when (null next-newline) (return nil))
+	  (pprint-newline+ :unconditional xp)
+	  (setq start (%i+ 1 sub-end)))))
+
+
+
+
+;note this checks (> BUFFER-PTR LINEL) instead of (> (LP<-BP) LINEL)
+;this is important so that when things are longer than a line they
+;end up getting printed in chunks of size LINEL.
+
+(defun write-char++ (char xp)
+  (when (> (xp-buffer-ptr xp) (xp-linel xp))
+    (force-some-output xp))
+  (let ((new-buffer-end (%i+ 1 (xp-buffer-ptr xp))))
+    (xp-check-size (xp-buffer xp) new-buffer-end #.buffer-min-size #.buffer-entry-size)
+    (if (xp-char-mode xp) (setq char (handle-char-mode xp char)))
+    (setf (schar (xp-buffer xp) (xp-buffer-ptr xp)) char)    
+    (setf (xp-buffer-ptr xp) new-buffer-end)))
+
+
+(defun force-some-output (xp)
+  (attempt-to-output xp nil nil)
+  (when (> (xp-buffer-ptr xp) (xp-linel xp)) ;only if printing off end of line
+    (attempt-to-output xp T T)))
+
+(defun write-string++ (string xp start end)
+  (when (> (xp-buffer-ptr xp) (xp-linel xp))
+    (force-some-output xp))
+  (write-string+++ string xp start end))
+
+;never forces output; therefore safe to call from within output-line.
+
+(defun write-string+++ (string xp start end)
+  (declare (fixnum start end))
+  (let ((new-buffer-end (%i+ (xp-buffer-ptr xp) (- end start))))
+    (xp-check-size (xp-buffer xp) new-buffer-end #.buffer-min-size #.buffer-entry-size)
+    (do ((buffer (xp-buffer xp))
+	 (i (xp-buffer-ptr xp) (1+ i))
+	 (j start (1+ j)))
+	((= j end))
+      (declare (fixnum i j))
+      (let ((char (char string j)))
+	(if (xp-char-mode xp) (setq char (handle-char-mode xp char)))      
+	(setf (schar buffer i) char)))
+    (setf (xp-buffer-ptr xp) new-buffer-end)))
+
+(defun pprint-tab+ (kind colnum colinc xp)
+  (let ((indented? nil) (relative? nil))
+    (declare (fixnum colnum colinc))
+    (case kind
+      (:section (setq indented? T))
+      (:line-relative (setq relative? T))
+      (:section-relative (setq indented? T relative? T)))
+    (when (or (not indented?)
+              (and *print-pretty* *logical-block-p*))
+      (let* ((current
+              (if (not indented?) (LP<-BP xp)
+                  (%i- (TP<-BP xp) (section-start xp))))
+             (new
+              (if (zerop colinc)
+                  (if relative? (+ current colnum) (max colnum current))
+                  (cond (relative?
+                         (* colinc (floor (+ current colnum colinc -1) colinc)))
+                        ((> colnum current) colnum)
+                        (T (+ colnum
+                              (* colinc
+                                 (floor (+ current (- colnum) colinc) colinc)))))))
+             (length (- new current)))
+        (declare (fixnum current new length))
+        (when (plusp length)
+          (if (xp-char-mode xp) (handle-char-mode xp #\space))
+          (let ((end (%i+ (xp-buffer-ptr xp) length)))
+            (xp-check-size (xp-buffer xp) end #.buffer-min-size #.buffer-entry-size)
+            (fill (xp-buffer xp) #\space :start (xp-buffer-ptr xp) :end end)
+            (setf (xp-buffer-ptr xp) end)))))))
+
+;note following is smallest number >= x that is a multiple of colinc
+;  (* colinc (floor (+ x (1- colinc)) colinc))
+
+
+(defun pprint-newline+ (kind xp)
+  (enqueue xp :newline kind)
+  (let ((queue (xp-queue xp))
+        (qright (xp-qright xp)))
+    (declare (fixnum qright))
+    (do ((ptr (xp-qleft xp) (Qnext ptr))) ;find sections we are ending
+        ((not (< ptr qright)))            ;all but last
+      (declare (fixnum ptr))
+      (when (and (null (xpq-end queue ptr))
+                 (not (%i> (xp-depth-in-blocks xp) (xpq-depth queue ptr)))
+                 (memq (xpq-type queue ptr) '(:newline :start-block)))
+        (setf (xpq-end queue ptr) (- qright ptr))))
+    (setf (section-start xp) (TP<-BP xp))
+    (when (and (memq kind '(:fresh :unconditional)) (xp-char-mode xp))
+      (handle-char-mode xp #\newline))
+    (when (memq kind '(:fresh :unconditional :mandatory))
+      (attempt-to-output xp T nil))))
+
+(defun start-block (xp prefix-string on-each-line? suffix-string)
+  (macrolet ((push-block-stack (xp)
+               `(let ((ptr (%i+ (xp-block-stack-ptr ,xp) #.block-stack-entry-size)))
+                  (setf (xp-block-stack-ptr ,xp) ptr)
+                  (xp-check-size (xp-block-stack ,xp) ptr
+                                 #.block-stack-min-size #.block-stack-entry-size))))
+    (let ((length (if prefix-string (length (the string prefix-string)) 0)))        
+      (declare (fixnum length))
+      (when prefix-string (write-string++ prefix-string xp 0 length))    
+      (if (and (xp-char-mode xp) on-each-line?)
+        (let ((ptr (xp-buffer-ptr xp)))
+          (declare (fixnum ptr))
+          (setq prefix-string
+	        (%substr (xp-buffer xp) (- ptr length) ptr))))
+      (push-block-stack xp)
+      (enqueue xp :start-block nil
+	       (if on-each-line? (cons suffix-string prefix-string) suffix-string))
+      (setf (xp-depth-in-blocks xp)(%i+ 1 (xp-depth-in-blocks xp)))      ;must be after enqueue
+      (setf (section-start xp) (TP<-BP xp)))))
+
+(defun end-block (xp suffix)
+  (macrolet ((pop-block-stack (xp)
+               `(decf (the fixnum (xp-block-stack-ptr ,xp)) #.block-stack-entry-size)))
+    ;(unless (eq *abbreviation-happened* '*print-lines*)
+      (when suffix (write-string+ suffix xp 0 (length suffix)))
+      (decf (xp-depth-in-blocks xp))
+      (enqueue xp :end-block nil suffix)
+      (let ((queue (xp-queue xp))
+            (qright (xp-qright xp)))
+        (declare (fixnum qright))
+        (do ((ptr (xp-qleft xp) (Qnext ptr))) ;looking for start of block we are ending
+	    ((not (< ptr qright)))    ;all but last
+          (declare (fixnum ptr))
+          (when (and (= (the fixnum (xp-depth-in-blocks xp)) (the fixnum (xpq-depth queue ptr)))
+		     (eq (xpq-type queue ptr) :start-block)
+		     (null (xpq-offset queue ptr)))
+	    (setf (xpq-offset queue ptr) (- qright ptr))
+	    (return nil)))	;can only be 1
+        (pop-block-stack xp)))) ;)
+
+(defun pprint-indent+ (kind n xp)
+  (when (and *print-pretty* *logical-block-p*)
+    (enqueue xp :ind kind n)))
+
+
+; The next function scans the queue looking for things it can do.
+;it keeps outputting things until the queue is empty, or it finds
+;a place where it cannot make a decision yet.
+
+(eval-when (:compile-toplevel :execute)
+(defmacro maybe-too-large (xp Qentry queue linel)
+  `(let ((.limit. ,linel)
+         (.qend. (xpq-end ,queue ,qentry)))
+     (declare (fixnum .limit.))
+     (when (eql (xp-line-limit ,xp) (xp-line-no ,xp)) ;prevents suffix overflow
+       (decf .limit. 2) ;3 for " .." minus 1 for space (heuristic)
+       (when (not (minusp (xp-prefix-stack-ptr ,xp)))
+	 (decf .limit. (suffix-ptr ,xp))))
+     (cond (.qend.
+	    (%i> (LP<-TP ,xp (xpq-pos ,queue (%i+ ,Qentry .qend.))) .limit.))
+	   ((or force-newlines? (%i> (LP<-BP ,xp) .limit.)) T)
+	   (T (return nil)))))	;wait until later to decide.
+
+(defmacro misering? (xp left)
+  `(<= ,left
+       (the fixnum (initial-prefix-ptr ,xp))))
+) ; eval-when
+
+;If flush-out? is T and force-newlines? is NIL then the buffer,
+;prefix-stack, and queue will be in an inconsistent state after the call.
+;You better not call it this way except as the last act of outputting.
+
+
+(defun attempt-to-output (xp force-newlines? flush-out?)
+  (macrolet ((pop-prefix-stack (xp)             
+             `(decf (the fixnum (xp-prefix-stack-ptr ,xp))
+                #.prefix-stack-entry-size)))
+  (let* ((width  *print-miser-width*)
+         (linel (xp-linel xp))
+         (left  (if width (- linel width) most-positive-fixnum)))
+    (declare (fixnum linel left))
+  (do ((qleft (xp-qleft xp))
+       (queue (xp-queue xp)(xp-queue xp)))
+      ((%i> qleft (xp-qright xp))
+	  (setf (xp-qleft xp) 0)
+	  (setf (xp-qright xp) #.(- queue-entry-size))) ;saves shifting
+    ; initial-prefix-ptr cant be referenced initially - prefix-stack-ptr is negative
+    (case (xpq-type queue qleft)
+      (:ind
+       (unless (misering? xp left)
+	 (set-indentation-prefix xp
+	   (case (xpq-kind queue qleft)
+	     (:block (%i+ (initial-prefix-ptr xp) (xpq-arg queue qleft)))
+	     (T ; :current
+	       (%i+ (LP<-TP xp (xpq-pos queue qleft))
+		  (xpq-arg queue qleft)))))) )
+      (:start-block
+       (cond ((maybe-too-large xp qleft queue linel)
+	      (push-prefix-stack xp)
+	      (setf (initial-prefix-ptr xp) (prefix-ptr xp))
+	      (set-indentation-prefix xp (LP<-TP xp (xpq-pos queue qleft)))
+	      (let ((arg (xpq-arg queue qleft)))
+		(when (consp arg) (set-prefix xp (cdr arg)))
+		(setf (initial-prefix-ptr xp) (prefix-ptr xp))
+		(cond ((not (listp arg)) (set-suffix xp arg))
+		      ((car arg) (set-suffix xp (car arg)))))
+	      (setf (section-start-line xp) (xp-line-no xp)))
+	     (T (setq qleft (%i+ qleft (xpq-offset queue qleft))))) )
+      (:end-block (pop-prefix-stack xp))
+      (T ; :newline
+       (when (case (xpq-kind queue qleft)
+	       (:fresh (not (%izerop (LP<-BP xp))))
+	       (:miser (misering? xp left))
+	       (:fill (or (misering? xp left)
+			  (%i> (xp-line-no xp) (section-start-line xp))
+			  (maybe-too-large xp qleft queue linel)))
+	       (T T)) ;(:linear :unconditional :mandatory) 
+	 (output-line xp qleft)
+	 (setup-for-next-line xp qleft))))
+    (setf (xp-qleft xp) (setq qleft (qnext qleft))))
+  (when flush-out? (flush xp)))))
+
+
+
+(defun flush (xp)
+  (let ((ostream (xp-out-stream xp)))
+    (when ostream      
+      (write-string (xp-buffer xp) ostream :start 0 :end (xp-buffer-ptr xp)))
+    (incf (xp-buffer-offset xp) (xp-buffer-ptr xp))
+    (incf (xp-charpos xp) (xp-buffer-ptr xp))
+    (setf (xp-buffer-ptr xp) 0)))
+
+
+(defun xp-out-stream (xp)
+  (let ((lc *locating-circularities*))
+    (cond 
+     ((null lc)
+      (xp-base-stream xp))
+     ((= lc 0)
+      (if  (null (xp-string-stream xp))
+        (setf (xp-string-stream xp) (make-string-output-stream))
+        (xp-string-stream xp))))))
+  
+
+;This prints out a line of stuff.
+
+(defun output-line (xp Qentry)
+  (flet ((find-not-char-reverse (buffer out-point)
+	   (declare (type simple-base-string buffer) (type fixnum out-point))
+	   (do ((i (%i- out-point 1) (%i- i 1)))
+	       ((%i< i 0) nil)
+	     (when (or (neq (schar buffer i) #\Space)
+		       ;; Don't match possibly-quoted space ("possibly" because the #\\ itself might be 
+		       ;; quoted; don't bother checking for that, no big harm leaving the space even if
+		       ;; not totally necessary).
+		       (and (%i< 0 i) (eq (schar buffer (%i- i 1)) #\\)))
+	       (return i)))))
+    (let* ((queue (xp-queue xp))
+           (out-point (BP<-TP xp (xpq-pos queue Qentry)))
+	   (last-non-blank (find-not-char-reverse (xp-buffer xp) out-point))
+	   (end (cond ((memq (xpq-kind queue Qentry) '(:fresh :unconditional)) out-point)
+		      (last-non-blank (%i+ 1 last-non-blank))
+		      (T 0)))
+	   (line-limit-exit (and (xp-line-limit xp) (not (%i> (xp-line-limit xp) (xp-line-no xp))))))
+      (when line-limit-exit
+        (setf (xp-buffer-ptr xp) end)          ;truncate pending output.
+        (write-string+++ " .." xp 0 3)
+        (reverse-string-in-place (xp-suffix xp) 0 (suffix-ptr xp))
+        (write-string+++ (xp-suffix xp) xp 0 (suffix-ptr xp))
+        (setf (xp-qleft xp) (qnext (xp-qright xp)))
+        ;(setq *abbreviation-happened* '*print-lines*)
+        (throw 'line-limit-abbreviation-exit T))
+      (setf (xp-line-no xp)(%i+ 1 (xp-line-no xp)))
+      (let ((bstream (xp-out-stream xp)))
+        (when bstream
+          (write-string (xp-buffer xp) bstream :start 0 :end end)
+          (stream-write-char bstream #\newline))))))
+
+(defun setup-for-next-line (xp Qentry)
+  (let* ((queue (xp-queue xp))
+         (out-point (BP<-TP xp (xpq-pos queue Qentry)))
+	 (prefix-end
+          (cond ((memq (xpq-kind queue Qentry) '(:unconditional :fresh))
+                 (non-blank-prefix-ptr xp))
+                (T (prefix-ptr xp))))
+	 (change (- prefix-end out-point)))
+    (declare (fixnum out-point prefix-end change))
+    (setf (xp-charpos xp) 0)
+    (when (plusp change)                  ;almost never happens
+      (xp-check-size (xp-buffer xp) (%i+ (xp-buffer-ptr xp) change)
+                     #.buffer-min-size #.buffer-entry-size))
+    (let ((buffer (xp-buffer xp)))
+      (replace buffer buffer :start1 prefix-end
+	       :start2 out-point :end2 (xp-buffer-ptr xp))
+      (replace buffer (xp-prefix xp) :end2 prefix-end)
+      (setf (xp-buffer-ptr xp) (%i+ (xp-buffer-ptr xp) change))
+      (setf (xp-buffer-offset xp) (%i- (xp-buffer-offset xp) change))
+      (when (not (memq (xpq-kind queue Qentry) '(:unconditional :fresh)))
+        (setf (section-start-line xp) (xp-line-no xp))))))
+
+(defun set-indentation-prefix (xp new-position)
+  (let ((new-ind (max (non-blank-prefix-ptr xp) new-position)))
+    (declare (fixnum new-ind))
+    (setf (prefix-ptr xp) (initial-prefix-ptr xp))
+    (xp-check-size (xp-prefix xp) new-ind #.prefix-min-size #.prefix-entry-size)
+    (when (%i> new-ind (prefix-ptr xp))
+      (fill (xp-prefix xp) #\space :start (prefix-ptr xp) :end new-ind))
+    (setf (prefix-ptr xp) new-ind)))
+
+(defun set-prefix (xp prefix-string)
+  (declare (string prefix-string))
+  (replace (xp-prefix xp) prefix-string
+	   :start1 (%i- (prefix-ptr xp) (length prefix-string)))
+  (setf (non-blank-prefix-ptr xp) (prefix-ptr xp)))
+
+(defun set-suffix (xp suffix-string)
+  (declare (string suffix-string))
+  (let* ((end (length suffix-string))
+	 (new-end (%i+ (suffix-ptr xp) end)))
+    (declare (fixnum end new-end))
+    (xp-check-size (xp-suffix xp) new-end #.suffix-min-size #.suffix-entry-size)
+    (do ((i (1- new-end) (1- i)) (j 0 (1+ j))) ((= j end))
+      (declare (fixnum i j))
+      (setf (char (xp-suffix xp) i) (char suffix-string j)))
+    (setf (suffix-ptr xp) new-end)))
+
+(defun reverse-string-in-place (string start end)
+  (declare (fixnum start end))
+  (do ((i start (1+ i)) (j (1- end) (1- j))) ((not (< i j)) string)
+    (declare (fixnum i j))
+    (let ((c (schar string i)))
+      (setf (schar string i) (schar string j))
+      (setf (schar string j) c))))
+
+
+;		   ---- BASIC INTERFACE FUNCTIONS ----
+
+;The internal functions in this file, and the (formatter "...") expansions
+;use the '+' forms of these functions directly (which is faster) because,
+;they do not need error checking of fancy stream coercion.  The '++' forms
+;additionally assume the thing being output does not contain a newline.
+
+(defun maybe-initiate-xp-printing (fn stream &rest args)
+  (if (xp-structure-p stream) (apply fn stream args)
+    (if (typep stream 'xp-stream)
+      (apply fn (slot-value stream 'xp-structure) args)
+      (let ((*locating-circularities* (if *print-circle* 0 nil))
+            (*circularity-hash-table*
+             (if *print-circle* (get-circularity-hash-table) nil)))
+        (prog1 (xp-print fn (decode-stream-arg stream) args)
+          (if *circularity-hash-table*
+            (free-circularity-hash-table *circularity-hash-table*)))))))
+
+(defun xp-print (fn stream args)
+  (flet ((do-it (fn stream args)
+           (prog1 (do-xp-printing fn stream args)
+             (when *locating-circularities*
+               (setq *locating-circularities* nil)
+               (do-xp-printing fn stream args)))))
+    (cond (*print-readably*
+           (let* ((*print-level* nil)
+                  (*print-length* nil)
+                  (*print-lines* nil)
+                  (*print-escape* t)
+                  (*print-gensym* t)
+                  (*print-array* nil))
+             (do-it fn stream args)))
+          (t (do-it fn stream args)))))
+
+
+(defun decode-stream-arg (stream)
+  (cond ((eq stream T) *terminal-io*)
+	((null stream) *standard-output*)
+	(T stream)))
+
+(defun do-xp-printing (fn stream args)
+  (let ((xp (slot-value (get-pretty-print-stream stream) 'xp-structure))
+	(*current-level* 0)
+        (*xp-current-object* nil)
+	(result nil))
+    (declare (special *foo-string*))
+    (catch 'line-limit-abbreviation-exit
+      (start-block xp nil nil nil)
+      (setq result (apply fn xp args))
+      (end-block xp nil))
+    (when (and *locating-circularities*
+	       (zerop *locating-circularities*)	;No circularities.
+               ;(= (xp-line-no xp) 1)	     	;Didn't suppress line.
+	       ;(zerop (xp-buffer-offset xp))
+               )	;Didn't suppress partial line.
+      (setq *locating-circularities* nil)
+      (let ((s (xp-string-stream xp)))
+        (when s
+          (stream-write-entire-string (xp-base-stream xp)
+                                      (get-output-stream-string s)))))
+    (when (catch 'line-limit-abbreviation-exit
+	    (attempt-to-output xp nil T)
+            nil)
+      (attempt-to-output xp T T))
+    (free-pretty-print-stream xp)
+    result))
+
+
+
+(defun write+ (object xp &optional interior-cdr circle)
+  (let ((pretty *print-pretty*)) ;((*parents* *parents*))
+    (when (or circle
+              (not (and *circularity-hash-table*
+		        (eq (setq circle (circularity-process xp object interior-cdr)) :subsequent))))
+      (when *circularity-hash-table*
+        (setq *xp-current-object* object))	
+      (let ((printer (if pretty (get-printer object *print-pprint-dispatch*) nil))
+	    #|type|#)
+	(cond (printer
+	       (funcall printer xp object))
+	      ((and pretty (maybe-print-fast xp object)))
+              (t (write-not-pretty xp object
+                                   (if *print-level*
+                                     (- *print-level* *current-level*)
+                                     most-positive-fixnum)
+                                   interior-cdr circle)))))))
+
+;It is vital that this function be called EXACTLY once for each occurrence of 
+;  each thing in something being printed.
+;Returns nil if printing should just continue on.
+;  Either it is not a duplicate, or we are in the first pass and do not know.
+;returns :FIRST if object is first occurrence of a DUPLICATE.
+;  (This can only be returned on a second pass.)
+;  After an initial code (printed by this routine on the second pass)
+;  printing should continue on for the object.
+;returns :SUBSEQUENT if second or later occurrence.
+;  Printing is all taken care of by this routine.
+
+;Note many (maybe most) lisp implementations have characters and small numbers
+;represented in a single word so that the are always eq when they are equal and the
+;reader takes care of properly sharing them (just as it does with symbols).
+;Therefore, we do not want circularity processing applied to them.  However,
+;some kinds of numbers (e.g., bignums) undoubtedly are complex structures that
+;the reader does not share.  However, they cannot have circular pointers in them
+;and it is therefore probably a waste to do circularity checking on them.  In
+;any case, it is not clear that it easy to tell exactly what kinds of numbers a
+;given implementation of CL is going to have the reader automatically share.
+
+; if not pretty print a space before dot
+
+(defun circularity-process (xp object interior-cdr? &aux (not-pretty (not *print-pretty*)))
+  (unless (or (numberp object)
+	      (characterp object)
+	      (and (symbolp object)	;Reader takes care of sharing.
+		   (or (null *print-gensym*) (symbol-package object))))
+    (let ((id (gethash object *circularity-hash-table*)))
+      (if (and *locating-circularities* *print-circle*) ; << was *locating-circularities*
+        (progn ;(push (list object id info-p) barf)
+          (cond ((null id)	;never seen before
+                 ;(when *parents* (push object *parents*))
+                 (setf (gethash object *circularity-hash-table*) 0)
+                 nil)
+                ((zerop id) ;possible second occurrence
+                 (setf (gethash object *circularity-hash-table*)
+                       (incf *locating-circularities*))
+                 :subsequent)
+                (T :subsequent)));third or later occurrence
+        (progn ;(push (list object id info-p interior-cdr?) barf2)          
+          (cond 
+           ((or (null id)	;never seen before (note ~@* etc. conses)
+                (zerop id));no duplicates
+            nil)
+           (t (when interior-cdr?
+                (write-string++ (if not-pretty " . #" ". #")
+                                            xp 0
+                                            (if not-pretty 4 3)))
+              (cond ((plusp id)
+                     (cond (interior-cdr?
+                            (decf *current-level*))
+                           (T (write-char++ #\# xp)))
+                     (print-fixnum xp id)
+                     (write-char++ #\= xp)
+                     (setf (gethash object *circularity-hash-table*) (- id))
+                     :first)
+                    (T (when (not interior-cdr?) (write-char++ #\# xp))
+                       (print-fixnum xp (- id))
+                       (write-char++ #\# xp)
+                       :subsequent)))))))))
+
+
+;This prints a few very common, simple atoms very fast.
+;Pragmatically, this turns out to be an enormous savings over going to the
+;standard printer all the time.  There would be diminishing returns from making
+;this work with more things, but might be worth it.
+; does this really win?
+
+(defun maybe-print-fast (xp object)
+  (cond ((stringp object)
+	 (cond ((null *print-escape*) (write-string+ object xp 0 (length object)) T)
+	       ((every #'(lambda (c) (not (or (eq c #\") (eq c #\\))))
+		       object)
+		(write-char++ #\" xp)
+		(write-string+ object xp 0 (length object))
+		(write-char++ #\" xp) T)))
+	((typep object 'fixnum)
+	 (when (and (null *print-radix*) (= *print-base* 10.))
+	   (when (minusp object)
+	     (write-char++ #\- xp)
+	     (setq object (- object)))
+	   (print-fixnum xp object) T))
+	((symbolp object)
+         (if (> *print-base* 10) ; may need to escape potential numbers
+           (write-a-symbol object (xp-stream xp))
+           (let ((s (symbol-name object))
+                 (p (symbol-package object))
+                 (is-key (keywordp object))
+                 (mode (case *print-case*
+                         (:downcase :down)
+                         (:capitalize :cap1)
+                         (T nil)))) ; note no-escapes-needed requires all caps
+             (declare (string s))
+             (cond ((and (or is-key (eq p *package*)
+                             (and  ;*package* ;can be NIL on symbolics
+                              (multiple-value-bind (symbol type) (find-symbol s)
+                                (and type (eq object symbol)))))
+                         (eq (readtable-case *readtable*) :upcase)
+                         (neq *print-case* :studly)
+                         (no-escapes-needed s))
+                    (when (and is-key *print-escape*)
+                      (write-char++ #\: xp))
+                    (if mode (push-char-mode xp mode))
+                    (write-string++ s xp 0 (length s))
+                    (if mode (pop-char-mode xp)) T)))))))
+         
+(defun print-fixnum (xp fixnum)
+  (multiple-value-bind (digits d)
+      (truncate fixnum 10)
+    (unless (zerop digits)
+      (print-fixnum xp digits))
+    (write-char++ (code-char (+ #.(char-code #\0) d)) xp)))
+
+;just wants to succeed fast in a lot of common cases.
+;assumes no funny readtable junk for the characters shown.
+
+(defun no-escapes-needed (s)
+  (declare (string s))
+  (let ((n (length s)))
+    (declare (fixnum n))
+    (and (not (zerop n))
+	 (let ((c (schar s 0)))
+	   (or (and (alpha-char-p c) (upper-case-p c)) (%str-member c "*<>")))
+	 (do ((i 1 (1+ i))) ((= i n) T)
+           (declare (fixnum i))
+	   (let ((c (schar s i)))
+	     (if (not (or (digit-char-p c)
+                          (and (alpha-char-p c) (upper-case-p c))
+			  (%str-member c "*+<>-")))
+		 (return nil)))))))
+
+
+
+(without-duplicate-definition-warnings  ;; override l1-io version.
+ (defun pprint (object &optional (stream *standard-output*))
+   "Prettily output OBJECT preceded by a newline."
+   (setq stream (decode-stream-arg stream))
+   (terpri stream)
+   (let ((*print-escape* T) (*print-pretty* T))
+     (write-1 object stream))
+   (values)))
+
+
+
+;Any format string that is converted to a function is always printed
+;via an XP stream (See formatter).
+
+(defvar *format-string-cache* nil)
+
+(defun process-format-string (string-or-fn force-fn?)
+  (declare (ignore force-fn?))
+  string-or-fn)
+
+
+
+;Each of these causes the stream to be pessimistic and insert
+;newlines wherever it might have to, when forcing the partial output
+;out.  This is so that things will be in a consistent state if
+;output continues to the stream later.
+
+(defmethod stream-force-output ((xp xp-structure))
+  (attempt-to-output xp t t))
+
+(defmethod stream-finish-output ((xp xp-structure))
+  (attempt-to-output xp t t))
+
+
+
+;           ---- FUNCTIONAL INTERFACE TO DYNAMIC FORMATTING ----
+
+;The internal functions in this file, and the (formatter "...") expansions
+;use the '+' forms of these functions directly (which is faster) because,
+;they do not need error checking or fancy stream coercion.  The '++' forms
+;additionally assume the thing being output does not contain a newline.
+
+
+
+(defun pprint-newline (kind &optional (stream *standard-output*))
+    "Output a conditional newline to STREAM (which defaults to
+   *STANDARD-OUTPUT*) if it is a pretty-printing stream, and do
+   nothing if not. KIND can be one of:
+     :LINEAR - A line break is inserted if and only if the immediatly
+        containing section cannot be printed on one line.
+     :MISER - Same as LINEAR, but only if ``miser-style'' is in effect.
+        (See *PRINT-MISER-WIDTH*.)
+     :FILL - A line break is inserted if and only if either:
+       (a) the following section cannot be printed on the end of the
+           current line,
+       (b) the preceding section was not printed on a single line, or
+       (c) the immediately containing section cannot be printed on one
+           line and miser-style is in effect.
+     :MANDATORY - A line break is always inserted.
+   When a line break is inserted by any type of conditional newline, any
+   blanks that immediately precede the conditional newline are ommitted
+   from the output and indentation is introduced at the beginning of the
+   next line. (See PPRINT-INDENT.)"
+    (when (not (memq kind '(:linear :miser :fill :mandatory)))
+      (signal-type-error kind '(member :linear :miser :fill :mandatory) 
+                         "Invalid KIND argument ~A to PPRINT-NEWLINE"))
+    (when (and *print-pretty* *logical-block-p*)    
+      (setq stream (decode-stream-arg stream))
+      (cond ((xp-structure-p stream)
+             (pprint-newline+ kind stream))
+            ((typep stream 'xp-stream)
+             (pprint-newline+ kind (slot-value stream 'xp-structure)))
+            (t (pp-newline stream kind))))
+    nil)
+
+(defun pprint-indent (relative-to n &optional (stream *standard-output*))
+  "Specify the indentation to use in the current logical block if STREAM
+   (which defaults to *STANDARD-OUTPUT*) is it is a pretty-printing stream
+   and do nothing if not. (See PPRINT-LOGICAL-BLOCK.)  N is the indentation
+   to use (in ems, the width of an ``m'') and RELATIVE-TO can be either:
+     :BLOCK - Indent relative to the column the current logical block
+        started on.
+     :CURRENT - Indent relative to the current column.
+   The new indentation value does not take effect until the following line
+   break."
+  (setq stream (decode-stream-arg stream))
+  (when (not (memq relative-to '(:block :current)))
+    (error "Invalid KIND argument ~A to PPRINT-INDENT" relative-to))
+  (cond ((xp-structure-p stream)
+         (pprint-indent+ relative-to (truncate n) stream))
+        ((typep stream 'xp-stream)
+         (pprint-indent+ relative-to (truncate n) (slot-value stream 'xp-structure)))
+        (t nil)) ; ???(break)))
+  nil)
+
+(defun pprint-tab (kind colnum colinc &optional (stream *standard-output*))
+  "If STREAM (which defaults to *STANDARD-OUTPUT*) is a pretty-printing
+   stream, perform tabbing based on KIND, otherwise do nothing. KIND can
+   be one of:
+     :LINE - Tab to column COLNUM. If already past COLNUM tab to the next
+       multiple of COLINC.
+     :SECTION - Same as :LINE, but count from the start of the current
+       section, not the start of the line.
+     :LINE-RELATIVE - Output COLNUM spaces, then tab to the next multiple of
+       COLINC.
+     :SECTION-RELATIVE - Same as :LINE-RELATIVE, but count from the start
+       of the current section, not the start of the line."
+  (setq stream (decode-stream-arg stream))
+  (when (not (memq kind '(:line :section :line-relative :section-relative)))
+    (error "Invalid KIND argument ~A to PPRINT-TAB" kind))
+
+  (when (and *print-pretty* *logical-block-p*)
+    (cond ((xp-structure-p stream)
+           (pprint-tab+ kind colnum colinc stream))
+          ((typep stream 'xp-stream)
+           (pprint-tab+ kind colnum colinc (slot-value stream 'xp-structure)))))
+  nil)
+
+
+;                        ---- COMPILED FORMAT ----
+
+;Note that compiled format strings always print through xp streams even if
+;they don't have any xp directives in them.  As a result, the compiled code
+;can depend on the fact that the stream being operated on is an xp
+;stream not an ordinary one.
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+; called by formatter frobs
+(defun do-sub-format-0 (s control-string args)
+    (setq s (if (xp-structure-p s)(xp-stream s)
+              (if (output-stream-p s)
+                s
+                (require-type s '(satisfies output-stream-p)))))
+                
+    (let ((*format-control-string* control-string)
+          (*format-top-level* t))      
+      (cond ((and (or *print-pretty* *print-circle*)
+                  (not (typep s 'xp-stream)))
+             (maybe-initiate-xp-printing
+              #'do-sub-format-1 s args))
+            (t (do-sub-format-1 s args)))))
+
+; called from above, format, and logical-block-sub
+(defun do-sub-format-1 (stream args)
+  (let ((*format-original-arguments* args)
+        (*format-arguments* args)
+        (*format-colon-rest* 'error))
+    (declare (special *format-colon-rest*))
+    (if (xp-structure-p stream)(setq stream (xp-stream stream)))
+    (do-sub-format stream)
+    ; copylist cause args is dynamic extent in format & formatter
+    ; n.b. when printing lisp code its nearly always nil
+    (setq args *format-arguments*)
+    (if (and (consp args) *format-top-level*)(copy-list args) args)))
+
+(defmacro formatter (control-string) ; maybe-initiate-xp-printing?
+  (setq control-string (require-type control-string 'string))
+  `(function 
+    (lambda (s &rest args)
+      ; IFFY because things can end up in the same place on the stack
+      ; appearing EQ giving bogus circularity detection
+      ; But now we have fixed things so we don't circle check rest args (ha!)
+      (do-sub-format-0 s ,control-string args))))
+
+(defmacro pprint-pop+ (args xp)
+  `(if (pprint-pop-check+ ,args ,xp)
+       (return-from logical-block nil)
+       (pop ,args)))
+
+(defun pprint-pop-check+ (args xp)
+  (let ((current-length *current-length*))
+    (declare (fixnum current-length))
+    (setq current-length (setq *current-length* (1+ *current-length*)))
+    (cond ((not (listp args))  ;must be first so supersedes length abbrev
+	   (write-string++ ". " xp 0 2)
+	   (write+ args xp)
+	   T)
+	  ((and *print-length* ;must supersede circle check
+	        (not (< current-length *print-length*)))
+	   (write-string++ "..." xp 0 3)
+	   ;(setq *abbreviation-happened* T)
+	   T)
+	  ((and *circularity-hash-table* (not *format-top-level*)
+                (not (zerop current-length)))
+           (let ((circle (circularity-process xp args T)))
+	     (case circle
+	       (:first ;; note must inhibit rechecking of circularity for args.
+                (write+ args xp T circle)
+                T)
+	       (:subsequent T)
+	       (T nil)))))))
+
+(defun check-block-abbreviation (xp args circle-check?)
+  (cond ((not (listp args)) (write+ args xp) T)
+	((and *print-level* (> *current-level* *print-level*))
+	 (write-char++ #\# XP) 
+         ;(setq *abbreviation-happened* T)
+         T)
+	((and *circularity-hash-table* circle-check? (neq args *xp-current-object*)
+	      (eq (circularity-process xp args nil) :subsequent))
+         T)
+	(T nil)))
+
+
+)
+
+
+
+;                ---- PRETTY PRINTING FORMATS ----
+
+(defun pretty-array (xp array)
+  (when (typep xp 'xp-stream)(setq xp (slot-value xp 'xp-structure)))
+  (cond ((vectorp array) (pretty-vector xp array))
+	((zerop (array-rank array))
+	 (write-string++ "#0A" xp 0 3)
+	 (write+ (aref array) xp))
+	(T (pretty-non-vector xp array))))
+
+(defun pretty-vector (xp v)
+  (pprint-logical-block (xp nil :prefix "#(" :suffix ")")
+    (let ((end (length v)) (i 0))
+      (declare (fixnum end i))
+      (when (plusp end)
+	(loop (pprint-pop)   ;HUH
+	      (write+ (aref v i) xp)
+	      (if (= (incf i) end) (return nil))
+	      (write-char++ #\space xp)
+	      (pprint-newline+ :fill xp))))))
+
+(defun pretty-non-vector (xp array)
+  (let* ((bottom (1- (array-rank array)))
+	 (indices (make-list (1+ bottom) :initial-element 0))
+	 (dims (array-dimensions array)))
+    (funcall (formatter "#~DA") xp (1+ bottom))
+    (labels ((pretty-slice (slice)
+	       (pprint-logical-block (xp nil :prefix "(" :suffix ")")
+		 (let ((end (nth slice dims))
+		       (spot (nthcdr slice indices))
+		       (i 0))
+		   (when (plusp end)
+		     (loop (pprint-pop)
+			   (setf (car spot) i)
+			   (if (= slice bottom)
+			       (write+ (apply #'aref array indices) xp)
+			       (pretty-slice (1+ slice)))
+			   (if (= (incf i) end) (return nil))
+			   (write-char++ #\space xp)
+			   (pprint-newline+ (if (= slice bottom) :fill :linear) xp)))))))
+      (pretty-slice 0))))
+
+(defun pretty-structure (xp struc &aux (class (struct-def struc)) (slots (sd-slots class)))
+  (when (typep xp 'xp-stream)(setq xp (slot-value xp 'xp-structure)))
+  (let* ((class (ccl::struct-def struc)) ;;guaranteed non-NIL if this function is called
+         (pf (structure-print-function class)))
+    (cond 
+     (pf
+      (if (consp pf)
+        (funcall (car pf) struc (xp-stream xp))
+	(funcall pf struc (xp-stream xp) *current-level*)))
+     (t 
+      (pprint-logical-block (xp nil :prefix "#S(" :suffix ")")
+        (pprint-pop)
+        (write+ (sd-name class) xp)
+        (start-block xp (if (cdr slots) " " "") nil "")
+        (when slots
+          (let ((pcase *print-case*))
+            (loop 
+              (let* ((slot (pop slots))(name (ssd-name slot)))
+                (cond
+                 ((symbolp name)
+                  (pprint-pop)
+                  (write-char++ #\: xp)
+                  (write-pname (symbol-name name) pcase xp)
+                  (write-char++ #\space xp)
+                  (pprint-pop)
+                  (write+ (uvref struc (ssd-offset slot)) xp)              
+                  (when (null slots)(return nil))
+                  (write-char++ #\space xp)
+                  (pprint-newline+ :fill xp))
+                 ((null slots)(return nil)))))))
+        (end-block xp ""))))))
+
+
+
+
+;Must use pprint-logical-block (no +) in the following three, because they are
+;exported functions.
+
+(defun pprint-linear (s list &optional (colon? T) atsign?)
+  "Output LIST to STREAM putting :LINEAR conditional newlines between each
+   element. If COLON? is NIL (defaults to T), then no parens are printed
+   around the output. ATSIGN? is ignored (but allowed so that PPRINT-LINEAR
+   can be used with the ~/.../ format directive."
+  (declare (ignore atsign?))
+  (pprint-logical-block (s list :prefix (if colon? "(" "")
+			        :suffix (if colon? ")" ""))
+    (pprint-exit-if-list-exhausted)
+    (loop (write+ (pprint-pop) s)
+	  (pprint-exit-if-list-exhausted)
+	  (write-char++ #\space s)
+	  (pprint-newline+ :linear s))))
+
+(defun pprint-fill (s list &optional (colon? T) atsign?)
+  "Output LIST to STREAM putting :FILL conditional newlines between each
+   element. If COLON? is NIL (defaults to T), then no parens are printed
+   around the output. ATSIGN? is ignored (but allowed so that PPRINT-FILL
+   can be used with the ~/.../ format directive."
+  (declare (ignore atsign?))
+  (pprint-logical-block (s list :prefix (if colon? "(" "")
+			        :suffix (if colon? ")" ""))
+    (pprint-exit-if-list-exhausted)
+    (loop (write+ (pprint-pop) s)
+	  (pprint-exit-if-list-exhausted)
+	  (write-char++ #\space s)
+	  (pprint-newline+ :fill s))))
+
+(defun pprint-tabular (s list &optional (colon? T) atsign? (tabsize nil))
+  "Output LIST to STREAM tabbing to the next column that is an even multiple
+   of TABSIZE (which defaults to 16) between each element. :FILL style
+   conditional newlines are also output between each element. If COLON? is
+   NIL (defaults to T), then no parens are printed around the output.
+   ATSIGN? is ignored (but allowed so that PPRINT-TABULAR can be used with
+   the ~/.../ format directive."
+  (declare (ignore atsign?))
+  (when (null tabsize) (setq tabsize 16))
+  (pprint-logical-block (s list :prefix (if colon? "(" "")
+			        :suffix (if colon? ")" ""))    
+    (pprint-exit-if-list-exhausted)
+    (loop (write+ (pprint-pop) s)
+	  (pprint-exit-if-list-exhausted)
+	  (write-char++ #\space s)
+	  (pprint-tab+ :section-relative 0 tabsize s)
+	  (pprint-newline+ :fill s))))
+
+; perhaps should use alternate-fn-call instead
+(defun fn-call (xp list)
+  (funcall (formatter "~:<~W~^ ~:I~@_~@{~W~^ ~_~}~:>") xp list))
+
+;Although idiosyncratic, I have found this very useful to avoid large
+;indentations when printing out code.
+
+(defun alternative-fn-call (xp list)
+  (if (> (length (symbol-name (car list))) 12)
+      (funcall (formatter "~:<~1I~@{~W~^ ~_~}~:>") xp list)
+      (funcall (formatter "~:<~W~^ ~:I~@_~@{~W~^ ~_~}~:>") xp list)))
+
+
+(defun bind-list (xp list &rest args)
+  (declare (ignore args))
+  (if (do ((i 50 (1- i))
+	   (ls list (cdr ls))) ((null ls) t)
+	(when (or (not (consp ls)) (not (symbolp (car ls))) (minusp i))
+	  (return nil)))
+      (pprint-fill xp list)
+      (funcall (formatter "~:<~@{~:/pprint-fill/~^ ~_~}~:>") xp list)))
+
+(defun block-like (xp list &rest args)
+    (declare (ignore args))
+  (funcall (formatter "~:<~1I~^~W~^ ~@_~W~^~@{ ~_~W~^~}~:>") xp list))
+
+(defun defun-like (xp list &rest args)
+    (declare (ignore args))
+  (funcall (formatter "~:<~1I~W~^ ~@_~W~^ ~@_~:/pprint-fill/~^~@{ ~_~W~^~}~:>")
+	    xp list))
+
+(defun print-fancy-fn-call (xp list template)
+  (let ((i 0) (in-first-section T))
+    (declare (fixnum i))
+    (pprint-logical-block+ (xp list "(" ")" nil T nil)
+      (write+ (pprint-pop) xp)
+      (pprint-indent+ :current 1 xp)
+      (loop
+	(pprint-exit-if-list-exhausted)
+	(write-char++ #\space xp)
+	(when (eq i (car template))
+	  (pprint-indent+ :block (cadr template) xp)
+	  (setq template (cddr template))
+	  (setq in-first-section nil))
+	(pprint-newline (cond ((and (zerop i) in-first-section) :miser)
+			      (in-first-section :fill)
+			      (T :linear))
+			xp)
+	(write+ (pprint-pop) xp)
+	(incf i)))))
+
+(defun defmethod-like (xp list &rest args)
+  (declare (ignore args))
+  (cond ((and (consp (cdr list))(consp (cddr list))(listp (caddr list)))
+         (defun-like xp list))
+        (t (defsetf-print xp list))))
+
+
+(defun maybelab (xp item &rest args)
+    (declare (ignore args) (special need-newline indentation))
+  (when (typep xp 'xp-stream)(setq xp (slot-value xp 'xp-structure)))
+  (when need-newline (pprint-newline+ :mandatory xp))
+  (cond ((and item (symbolp item))
+	 (write+ item xp)
+	 (setq need-newline nil))
+	(T (pprint-tab+ :section indentation 0 xp)
+	   (write+ item xp)
+	   (setq need-newline T))))
+
+(defun function-call-p (x)
+  (and (consp x) (symbolp (car x)) (fboundp (car x))))
+
+
+
+
+;THE FOLLOWING STUFF SETS UP THE DEFAULT *PRINT-PPRINT-DISPATCH*
+ 
+;This is an attempt to specify a correct format for every form in the CL book
+;that does not just get printed out like an ordinary function call 
+;(i.e., most special forms and many macros).  This of course does not 
+;cover anything new you define.
+
+(defun let-print (xp obj)
+  (funcall (formatter "~:<~1I~W~^ ~@_~/ccl::bind-list/~^~@{ ~_~W~^~}~:>") xp obj))
+
+(defun cond-print (xp obj)
+  (funcall (formatter "~:<~W~^ ~:I~@_~@{~:/pprint-linear/~^ ~_~}~:>") xp obj))
+
+(defun dmm-print (xp list)
+  (print-fancy-fn-call xp list '(3 1)))
+
+(defun defsetf-print (xp list)
+  (print-fancy-fn-call xp list '(3 1)))
+
+(defun do-print (xp obj)
+  (funcall 
+ (formatter "~:<~W~^ ~:I~@_~/ccl::bind-list/~^ ~_~:/pprint-linear/ ~1I~^~@{ ~_~W~^~}~:>")
+           xp obj))
+
+
+(defun flet-print (xp obj)
+  (funcall (formatter "~:<~1I~W~^ ~@_~:<~@{~/ccl::block-like/~^ ~_~}~:>~^~@{ ~_~W~^~}~:>")
+	   xp obj))
+
+(defun function-print (xp list)
+  (if (and *print-abbreviate-quote* (consp (cdr list)) (null (cddr list)))
+      (format (xp-stream xp) "#'~W" (cadr list))
+      (fn-call xp list)))
+
+(defun mvb-print (xp list)
+  (print-fancy-fn-call xp list '(1 3 2 1)))
+
+(defun prog-print (xp list)
+  (let ((need-newline T) (indentation (1+ (length (symbol-name (car list)))))) ; less?
+    (declare (special need-newline indentation))
+    (funcall (formatter "~:<~W~^ ~:/pprint-fill/~^ ~@{~/ccl::maybelab/~^ ~}~:>")
+	     xp list)))
+
+
+(defun progn-print (xp list)
+  (funcall (formatter "~:<~1I~@{~W~^ ~_~}~:>") xp list))
+
+(defun setq-print (xp obj)
+  (funcall (formatter "~:<~W~^ ~:I~@_~@{~W~^ ~:_~W~^ ~_~}~:>") xp obj))
+
+(defun quote-print (xp list)
+  (if (and (consp (cdr list)) (null (cddr list)))
+      (format (xp-stream xp) "'~W" (cadr list))
+      (pprint-fill xp list)))
+
+(defun tagbody-print (xp list)
+  (let ((need-newline (and (consp (cdr list))
+			   (symbolp (cadr list)) (cadr list)))
+	(indentation (1+ (length (symbol-name (car list))))))
+    (declare (special need-newline indentation))
+    (funcall (formatter "~:<~W~^ ~@{~/ccl::maybelab/~^ ~}~:>") xp list)))
+
+(defun up-print (xp list)
+  (print-fancy-fn-call xp list '(0 3 1 1)))
+
+
+;here is some simple stuff for printing LOOP
+
+;The challange here is that we have to effectively parse the clauses of the
+;loop in order to know how to print things.  Also you want to do this in a 
+;purely incremental way so that all of the abbreviation things work, and
+;you wont blow up on circular lists or the like.  (More aesthic output could
+;be produced by really parsing the clauses into nested lists before printing them.)
+
+;The following program assumes the following simplified grammar of the loop
+;clauses that explains how to print them.  Note that it does not bare much
+;resemblence to the right parsing grammar, however, it produces half decent
+;output.  The way to make the output better is to make the grammar more
+;detailed.  
+;
+;loop == (LOOP {clause}*)      ;one clause on each line.
+;clause == block | linear | cond | finally
+;block == block-head {expr}*   ;as many exprs as possible on each line.
+;linear == linear-head {expr}* ;one expr on each line.
+;finally == FINALLY [DO | DOING | RETURN] {expr}* ;one expr on each line.
+;cond == cond-head [expr]
+;          clause
+;	   {AND clause}*       ;one AND on each line.
+;        [ELSE
+;          clause
+;	   {AND clause}*]      ;one AND on each line.
+;        [END]
+;block-head == FOR | AS | WITH | AND
+;              | REPEAT | NAMED | WHILE | UNTIL | ALWAYS | NEVER | THEREIS | RETURN
+;              | COLLECT | COLLECTING | APPEND | APPENDING | NCONC | NCONCING | COUNT
+;              | COUNTING | SUM | SUMMING | MAXIMIZE | MAXIMIZING | MINIMIZE | MINIMIZING 
+;linear-head == DO | DOING | INITIALLY
+;var-head == FOR | AS | WITH
+;cond-head == IF | WHEN | UNLESS
+;expr == <anything that is not a head symbol>
+
+;Note all the string comparisons below are required to support some
+;existing implementations of LOOP.
+(defun token-type (token &aux string)
+  (cond ((not (symbolp token)) :expr)
+	((string= (setq string (string token)) "FINALLY") :finally)
+	((member string '("IF" "WHEN" "UNLESS") :test #'string=) :cond-head)
+	((member string '("DO" "DOING" "INITIALLY") :test #'string=) :linear-head)
+	((member string '("FOR" "AS" "WITH" "AND" "END" "ELSE"
+			  "REPEAT" "NAMED" "WHILE" "UNTIL" "ALWAYS" "NEVER"
+			  "THEREIS" "RETURN" "COLLECT" "COLLECTING" "APPEND"
+			  "APPENDING" "NCONC" "NCONCING" "COUNT" "COUNTING"
+			  "SUM" "SUMMING" "MAXIMIZE" "MAXIMIZING"
+			  "MINIMIZE" "MINIMIZING")
+		 :test #'string=)
+	 :block-head)
+	(T :expr)))
+
+
+; maybe put in a separate file (replace write-char by write-char+)
+(defun pretty-loop (xp loop)
+  (if (not (and (consp (cdr loop)) (symbolp (cadr loop)))) ; old-style loop
+      (tagbody-print xp loop)
+      (pprint-logical-block (xp loop :prefix "(" :suffix ")")
+	(let (token type)
+	  (labels ((next-token ()
+		     (pprint-exit-if-list-exhausted)
+		     (setq token (pprint-pop))
+		     (setq type (token-type token)))
+		   (print-clause (xp)
+		     (case type
+		       (:linear-head (print-exprs xp nil :mandatory))
+		       (:cond-head (print-cond xp))
+		       (:finally (print-exprs xp T :mandatory))
+		       (otherwise (print-exprs xp nil :fill))))
+		   (print-exprs (xp skip-first-non-expr newline-type)
+		     (pprint-logical-block (xp nil)
+		       (write+ token xp)
+		       (next-token)
+		       (when (and skip-first-non-expr (not (eq type :expr)))
+			 (write-char+ #\space xp)
+			 (write+ token xp)
+			 (next-token))
+		       (when (eq type :expr)
+			 (write-char+ #\space xp)
+			 (pprint-indent :current 0 xp)
+			 (loop (write+ token xp)
+			       (next-token)
+			       (when (not (eq type :expr)) (return nil))
+			       (write-char+ #\space xp)
+			       (pprint-newline newline-type xp)))))
+		   (print-cond (xp)
+		     (pprint-logical-block (xp nil)
+		       (write+ token xp)
+		       (next-token)
+		       (when (eq type :expr)
+			 (write-char+ #\space xp)
+			 (write+ token xp)
+			 (next-token))
+		       (write-char+ #\space xp)
+		       (pprint-indent :block 2 xp)
+		       (pprint-newline :linear xp)
+		       (print-clause xp)
+		       (print-and-list xp)
+		       (when (string= (string token) "ELSE")
+			 (print-else-or-end xp)
+			 (write-char+ #\space xp)
+			 (pprint-newline :linear xp)
+			 (print-clause xp)
+			 (print-and-list xp))
+		       (when (string= (string token) "END")
+			 (print-else-or-end xp))))
+		   (print-and-list (xp)
+		     (loop (when (not (string= (string token) "AND")) (return nil))
+			   (write-char+ #\space xp)
+			   (pprint-newline :mandatory xp)
+			   (write+ token xp)
+			   (next-token)
+			   (write-char+ #\space xp)
+			   (print-clause xp)))
+		   (print-else-or-end (xp)
+		     (write-char+ #\space xp)
+		     (pprint-indent :block 0 xp)
+		     (pprint-newline :linear xp)
+		     (write+ token xp)
+		     (next-token)
+		     (pprint-indent :block 2 xp)))
+	    (pprint-exit-if-list-exhausted)
+	    (write+ (pprint-pop) xp)
+	    (next-token)
+	    (write-char+ #\space xp)
+	    (pprint-indent :current 0 xp)
+	    (loop (print-clause xp)
+		  (write-char+ #\space xp)
+		  (pprint-newline :linear xp)
+                  ; without this we can loop forever
+                  (if (and *print-level*
+			   (>= *current-level* *print-level*))
+		    (return))))))))
+
+
+;Backquote is a big problem we MUST do all this reconsing of structure in
+;order to get a list that will trigger the right formatting functions to
+;operate on it.  On the other side of the coin, we must use a non-list structure 
+;for the little backquote printing markers to ensure that they will always
+;print out the way we want no matter what the code printers say.
+;  Note that since it is sometimes possible to write the same
+;backquote form in several ways, this might not necessarily print out a
+;form in exactly the way you wrote it.  For example '`(a .,b) and '`(a ,@b)
+;both print out as `'(a .,b), because the backquote reader produces the
+;same code in both cases.
+
+
+
+(setq *IPD* (make-pprint-dispatch-table))
+
+(set-pprint-dispatch+ '(satisfies function-call-p) #'alternative-fn-call '(-5) *IPD*)
+(set-pprint-dispatch+ 'cons #'pprint-fill '(-10) *IPD*)
+
+(set-pprint-dispatch+ '(cons (member defstruct)) #'block-like '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member block)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member case)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member catch)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member ccase)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member compiler-let)) #'let-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member cond)) #'cond-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member ctypecase)) #'block-like '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member defclass)) #'defun-like '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member ctypecase)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member defconstant)) #'defun-like '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member define-setf-expander)) #'defun-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member defmacro)) #'defun-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member define-modify-macro)) #'dmm-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member defparameter)) #'defun-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member defsetf)) #'defsetf-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member define-setf-expander)) #'defun-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member cl:defstruct)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member deftype)) #'defun-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member defun)) #'defun-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member defmethod)) #'defmethod-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member defvar)) #'defun-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member do)) #'do-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member do*)) #'do-print '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member do-all-symbols)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member do-external-symbols)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member do-symbols)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member dolist)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member dotimes)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member ecase)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member etypecase)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member eval-when)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member flet)) #'flet-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member function)) #'function-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member generic-function)) #'fn-call '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member labels)) #'flet-print '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member lambda)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member let)) #'let-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member let*)) #'let-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member locally)) #'block-like '(0) *IPD*)
+
+(set-pprint-dispatch+ '(cons (member loop)) #'pretty-loop '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member macrolet)) #'flet-print '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member multiple-value-bind)) #'mvb-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member multiple-value-setq)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member prog)) #'prog-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member prog*)) #'prog-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member progv)) #'defun-like '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member psetf)) #'setq-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member psetq)) #'setq-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member quote)) #'quote-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member return-from)) #'block-like '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member setf)) #'setq-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member setq)) #'setq-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member tagbody)) #'tagbody-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member throw)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member typecase)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member unless)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member unwind-protect)) #'up-print '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member when)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member with-input-from-string)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member with-open-file)) #'block-like '(0) *IPD*)
+(set-pprint-dispatch+ '(cons (member with-open-stream)) #'block-like '(0) *IPD*) 
+(set-pprint-dispatch+ '(cons (member with-output-to-string)) #'block-like '(0) *IPD*) 
+
+
+
+;so only happens first time is loaded. - why doesn't this work right?
+; cause we have *print-pprin... bound to NIL
+(when  t ;(eq *print-pprint-dispatch* T)
+  (setq *print-pprint-dispatch* (copy-pprint-dispatch nil)))
+
+(setq *error-print-circle* t)  ; now we can circle-print
+
+; 82 bytes shorter but uglier
+(defun write-not-pretty (stream object level list-kludge circle)
+  (declare (type fixnum level) (type (or null fixnum) list-kludge))
+  (when (xp-structure-p stream)(setq stream (xp-stream stream)))  
+  (cond ((eq circle :subsequent)
+         (if  list-kludge (stream-write-char stream #\)))
+         (return-from write-not-pretty nil))
+        ((not list-kludge))
+        ((null object)(return-from write-not-pretty nil))
+        ((not (consp object))
+         (stream-write-entire-string stream " . "))
+        ((eq circle :first)
+         (stream-write-char stream #\()        
+         (write-a-frob object stream level list-kludge)
+         (stream-write-char stream #\))
+         (return-from write-not-pretty nil))                     
+        (t (stream-write-char stream #\space)))
+  (write-a-frob object stream level list-kludge))
+
+(eval-when (:load-toplevel :execute) 
+  (setq *error-print-circle* t))
+
+;changes since last documentation.
+;~/fn/ only refers to global function values, not lexical.
+
+;------------------------------------------------------------------------
+
+;Copyright 1989,1990 by the Massachusetts Institute of Technology, Cambridge, 
+;Massachusetts.
+
+;Permission to use, copy, modify, and distribute this software and its
+;documentation for any purpose and without fee is hereby granted,
+;provided that this copyright and permission notice appear in all
+;copies and supporting documentation, and that the name of M.I.T. not
+;be used in advertising or publicity pertaining to distribution of the
+;software without specific, written prior permission. M.I.T. makes no
+;representations about the suitability of this software for any
+;purpose.  It is provided "as is" without express or implied warranty.
+
+;    M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+;    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+;    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+;    ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+;    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+;    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+;    SOFTWARE.
+
+;------------------------------------------------------------------------
+
+#|
+	Change History (most recent last):
+	2	12/29/94	akh	merge with d13
+|# ;(do not edit past this line!!)
Index: /branches/new-random/lib/prepare-mcl-environment.lisp
===================================================================
--- /branches/new-random/lib/prepare-mcl-environment.lisp	(revision 13309)
+++ /branches/new-random/lib/prepare-mcl-environment.lisp	(revision 13309)
@@ -0,0 +1,91 @@
+;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; prepare-mcl-environment.lisp
+;; Load this into a PPCCL to make it into an MCL-PPC for shipping
+;; Sort of.
+
+(in-package "CCL")
+
+(defun %reset-outermost-binding (symbol value)
+  (let* ((symvector (symptr->symvector symbol))
+         (idx (%svref symvector target::symbol.binding-index-cell))
+         (marker (%no-thread-local-binding-marker)))
+    (if (> idx 0)
+      (do-db-links (db var)
+        (when (eq var idx)
+          (let* ((oldval (%fixnum-ref db (* 2 target::node-size))))
+            (unless (eq oldval marker)
+              (setf (%fixnum-ref db (* 2 target::node-size)) value))))))
+    (setf (uvref symvector target::symbol.vcell-cell) value)))
+
+(defun freeze-current-definitions ()
+  ;; Set the frozen bits so that redefine-kernel-function
+  ;; will error if a builtin function is redefined.
+  (do-all-symbols (s)
+    (when (fboundp s)
+      (%symbol-bits s (bitset $sym_fbit_frozen (%symbol-bits s)))))
+  ;; Force an error if a kernel method is redefined.
+  (make-all-methods-kernel))
+
+(defun thaw-current-definitions ()
+  ;; Clear the frozen bits on all fboundp symbols
+  (do-all-symbols (s)
+    (when (fboundp s)
+      (%symbol-bits s (bitclr $sym_fbit_frozen (%symbol-bits s)))))
+  ;; Allow redefinition of kernel methods.
+  (make-all-methods-non-kernel))
+
+(defun set-user-environment (&optional (freeze-definitions nil))
+  "Arrange that the outermost special bindings of *PACKAGE* and
+*WARN-IF-REDEFINE-KERNEL* restore values of the CL-USER package and T
+respectively, and set *CCL-SAVE-SOURCE-LOCATIONS* to :NO-TEXT.
+If the optional argument is true, marks all globally defined
+functions and methods as being predefined (this is a fairly
+expensive operation.)"
+  (when freeze-definitions
+    (freeze-current-definitions))
+  ;; enable redefine-kernel-function's error checking
+  (%reset-outermost-binding '*warn-if-redefine-kernel* t)
+  ;; Set the top-level *package* to the CL-USER package
+  (%reset-outermost-binding '*package* (find-package "CL-USER"))
+  (setq *ccl-save-source-locations* :NO-TEXT))
+
+(defun set-development-environment (&optional (thaw-definitions nil))
+  "Arrange that the outermost special bindings of *PACKAGE* and
+*WARN-IF-REDEFINE-KERNEL* restore values of the CCL package and NIL
+respectively, and set *ccl-save-source-locations* to T. If the
+optional argument is true, mark all globally defined functions and
+methods as being not predefined (this is a fairly expensive operation.)"
+  (when thaw-definitions
+    (thaw-current-definitions))
+  ;; enable redefine-kernel-function's error checking
+  (%reset-outermost-binding '*warn-if-redefine-kernel* nil)
+  ;; Set the top-level *package* to the CCL package
+  (%reset-outermost-binding '*package* (find-package "CCL"))
+  (setq *ccl-save-source-locations* T))
+  
+
+
+(defmacro in-development-mode (&body body)
+  `(let* ((*package* (find-package "CCL"))
+	  (*warn-if-redefine-kernel* nil))
+    ,@body))
+
+
+
+
Index: /branches/new-random/lib/print-db.lisp
===================================================================
--- /branches/new-random/lib/print-db.lisp	(revision 13309)
+++ /branches/new-random/lib/print-db.lisp	(revision 13309)
@@ -0,0 +1,39 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defmacro print-db (&rest forms &aux)
+  `(multiple-value-prog1
+     (progn ,@(print-db-aux forms))
+     (terpri *trace-output*)))
+
+(defun print-db-aux (forms)
+   (when forms
+     (cond ((stringp (car forms))
+            `((print ',(car forms) *trace-output*)
+              ,@(print-db-aux (cdr forms))))
+           ((null (cdr forms))
+            `((print ',(car forms) *trace-output*)
+              (let ((values (multiple-value-list ,(car forms))))
+                (prin1 (car values) *trace-output*)
+                (apply #'values values))))
+           (t `((print ',(car forms) *trace-output*)
+                (prin1 ,(car forms) *trace-output*)
+                ,@(print-db-aux (cdr forms)))))))
+
+
Index: /branches/new-random/lib/read.lisp
===================================================================
--- /branches/new-random/lib/read.lisp	(revision 13309)
+++ /branches/new-random/lib/read.lisp	(revision 13309)
@@ -0,0 +1,250 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+                         
+(define-condition simple-reader-error (reader-error simple-error) ()
+  (:report (lambda (c output-stream)
+             (format output-stream "Reader error ~a:~%~?"
+                     (stream-error-context c)
+                     (simple-condition-format-control c)
+                     (simple-condition-format-arguments c)))))
+
+(defun signal-reader-error (input-stream format-string &rest format-args)
+  (error 'simple-reader-error :stream input-stream
+         :format-control format-string :format-arguments format-args))
+
+#| ; Can't see any reason to leave this in
+(defun read-file-to-list (file &aux result)
+   ;(print-db (setq file (prepend-default-dir file)))   
+   (with-open-file (stream file :direction :input)
+       (setq result (read-file-to-list-aux stream)))
+   result)
+
+(defun read-file-to-list-aux (stream)
+   (if (eofp stream)
+        nil
+       (let ((form (read stream nil *eof-value* nil)))
+            ;(%print "just read " form)
+           (if (eq form *eof-value*)
+                nil
+               (cons form (read-file-to-list-aux stream))))))
+|#
+
+(set-dispatch-macro-character #\# #\*
+ (qlfun |#*-reader| (input-stream sub-char int 
+   &aux list list-length array array-length last-bit)
+  (declare (ignore sub-char))
+  (do* ((char (read-char input-stream nil nil t)
+              (read-char input-stream nil nil t))
+        (attr (%character-attribute char (rdtab.ttab *readtable*))
+              (%character-attribute char (rdtab.ttab *readtable*))))
+       ((or (null char)
+            (= $cht_tmac attr)
+            (= $cht_wsp attr))
+        (if char (unread-char char input-stream)))
+    (let ((number (- (char-code char) 48)))
+      (if (or (<= 0 number 1) *read-suppress*)
+          (setq list (cons number list))
+          (signal-reader-error input-stream "reader macro #* got illegal character ~S" char))))
+  (setq last-bit (car list))
+  (setq list (nreverse list))
+  (setq list-length (list-length list))
+  (if (not (integerp int))
+      (setq int list-length))
+  (cond (*read-suppress* nil)
+        ((and (= 0 list-length) (> int 0))
+         (signal-reader-error input-stream "reader macro #~S* needs something" int))
+        ((> list-length int)
+         (signal-reader-error input-stream "reader macro #~S* can't fit ~S" int list))
+        (t (setq array-length (if int int list-length))
+           (setq array (make-array array-length :element-type 'bit))
+           (do ((i 0 (1+ i))
+                (bit-list list (cdr bit-list)))
+               ((>= i array-length))
+             (aset array i (if bit-list
+                               (car bit-list)
+                               last-bit)))
+           array))))
+
+(set-dispatch-macro-character #\# #\A
+ (qlfun |#A-reader| (stream ignore dimensions)
+   (declare (ignore ignore))
+   (cond (*read-suppress*
+          (read stream () () t)
+          nil)
+         ((not dimensions)
+          (signal-reader-error stream "reader macro #A used without a rank integer"))
+         ((eql dimensions 0) ;0 dimensional array
+          (make-array nil :initial-contents (read-internal stream t nil t)))
+         ((and (integerp dimensions) (> dimensions 0)) 
+          (let ((init-list (read-internal stream t nil t)))
+            (cond ((not (typep init-list 'sequence))
+                   (signal-reader-error stream "The form following a #~SA reader macro should have been a sequence, but it was: ~S" dimensions init-list))
+                  ((= (length init-list) 0)
+                   (make-array (make-list dimensions :initial-element 0)))
+                  ((= dimensions 1)
+                   (make-array (length init-list) :initial-contents init-list))
+                  ((vectorp init-list)
+                   (let ((dlist (make-list dimensions)))
+                     (do ((dl dlist (cdr dl))
+                          (il init-list (svref il 0)))
+                         ((null dl))
+                       (if (vectorp il)
+                           (rplaca dl (length il))
+                           (signal-reader-error stream "Initial contents for #A is inconsistent with dimensions: #~SA~S" dimensions init-list)))
+                     (make-array dlist :initial-contents init-list)))
+                  ((listp init-list)
+                   (let ((dlist (make-list dimensions)))
+                     (do ((dl dlist (cdr dl))
+                          (il init-list (car il)))
+                         ((null dl))
+                       (if (listp il)
+                           (rplaca dl (list-length il))
+                           (signal-reader-error stream "Initial contents for #A is inconsistent with dimensions: #~SA~S" dimensions init-list)))
+                     (make-array dlist :initial-contents init-list)))
+                  (t
+                   (signal-reader-error stream "#~SA~S invalid." dimensions init-list)))))
+         (t (signal-reader-error stream "Dimensions argument to #A not a non-negative integer: ~S" dimensions)))))
+
+(set-dispatch-macro-character #\# #\S
+  (qlfun |#S-reader| (input-stream sub-char int &aux list sd)
+     (declare (ignore sub-char int))
+     (setq list (read-internal input-stream t nil t))
+     (unless *read-suppress*
+       (unless (and (consp list)
+                    (symbolp (%car list))
+                    (setq sd (gethash (%car list) %defstructs%))
+		    (setq sd (sd-constructor sd)))
+         (error "Can't initialize structure from ~S." list))
+       (let ((args ()) (plist (cdr list)))
+         (unless (plistp plist) (report-bad-arg plist '(satisfies plistp)))
+         (while plist
+           (push (make-keyword (pop plist)) args)
+           (push (pop plist) args))
+         (apply sd (nreverse args))))))
+
+;;;from slisp reader2.lisp, and apparently not touched in 20 years.
+(defun parse-integer (string &key (start 0) end
+                      (radix 10) junk-allowed)
+  "Examine the substring of string delimited by start and end
+  (default to the beginning and end of the string)  It skips over
+  whitespace characters and then tries to parse an integer. The
+  radix parameter must be between 2 and 36."
+  (flet ((parse-integer-not-integer-string (s)
+	   (error 'parse-integer-not-integer-string :string s)))
+    (declare (inline parse-integer-not-integer-string))
+    (unless (typep string 'string)
+      (setq string (require-type string 'string)))
+    (setq end (check-sequence-bounds string start end))
+    (setq radix (%validate-radix radix))
+    (let ((index (do ((i start (1+ i)))
+		     ((= i end)
+		      (if junk-allowed
+                        (return-from parse-integer (values nil end))
+                        (parse-integer-not-integer-string string)))
+                   (unless (whitespacep (char string i)) (return i))))
+        (minusp nil)
+        (found-digit nil)
+        (result 0))
+       (let ((char (char string index)))
+            (cond ((char= char #\-)
+                   (setq minusp t)
+                   (setq index (1+ index)))
+                  ((char= char #\+)
+                    (setq index (1+ index))
+                   )))
+       (loop
+        (when (= index end) (return nil))
+        (let* ((char (char string index))
+               (weight (digit-char-p char radix)))
+              (cond (weight
+                     (setq result (+ weight (* result radix))
+                                  found-digit t))
+                    (junk-allowed (return nil))
+                    ((whitespacep char)
+                     (until (eq (setq index (1+ index)) end)
+                       (unless (whitespacep (char string index))
+                         (parse-integer-not-integer-string string)))
+                     (return nil))
+                    (t
+                     (parse-integer-not-integer-string string))))
+         (setq index (1+ index)))
+       (values
+        (if found-digit
+            (if minusp (- result) result)
+            (if junk-allowed
+                nil
+                (parse-integer-not-integer-string string)))
+        index))))
+
+
+(set-dispatch-macro-character #\# #\#
+  #'(lambda (stream char arg)
+      (declare (ignore stream))
+      (if *read-suppress* 
+        nil
+        (if arg
+          (let ((pair (assoc arg %read-objects%))) ;Not assq, could be bignum!
+            (if pair
+              (cdr pair)
+              (%err-disp $xnordlbl arg)))
+          (%err-disp $xrdndarg char)))))
+
+(set-dispatch-macro-character 
+ #\# 
+ #\=
+ #'(lambda (stream char arg &aux lab form)
+     (cond (*read-suppress* (values))
+           ((null arg) (%err-disp $xrdndarg char))
+           ((assoc arg %read-objects%)    ;Not assq, could be bignum!
+            (%err-disp $xduprdlbl arg))
+           (t (setq lab (cons arg nil))
+              (push (%rplacd lab lab) %read-objects%)
+              (setq form (read stream t nil t))
+              (when (eq form lab)   ;#n= #n#.  No can do.
+                (%err-disp $xnordlbl (%car lab)))
+              (%rplacd lab form)
+              (let ((scanned nil))
+                  (labels ((circle-subst (tree)
+                             (if (memq tree %read-objects%)
+                               (progn
+                                 (unless (memq tree scanned)
+                                   (setq scanned (%temp-cons tree scanned))
+                                   (circle-subst (cdr tree)))
+                                 (cdr tree))
+                               (let ((gvectorp (and (gvectorp tree)  (not (or (symbolp tree) (functionp tree))))))
+                                 (unless (or (and (atom tree) (not gvectorp)) (memq tree scanned))
+                                   (setq scanned (%temp-cons tree scanned))
+                                   (if gvectorp
+                                     (let* ((subtype  (typecode tree)))
+                                       (dotimes (i (uvsize tree))
+                                         (declare (fixnum i))
+                                         (unless (and (eql i 0) (eql subtype target::subtag-instance))
+                                           (setf (uvref tree i) (circle-subst (uvref tree i))))))
+                                     (locally 
+                                      (declare (type cons tree))
+                                      (rplaca tree (circle-subst (car tree)))
+                                      (rplacd tree (circle-subst (cdr tree))))))
+                                 tree))))
+                    (declare (dynamic-extent #'circle-subst))
+                    (circle-subst form)))))))
+
+
+
Index: /branches/new-random/lib/sequences.lisp
===================================================================
--- /branches/new-random/lib/sequences.lisp	(revision 13309)
+++ /branches/new-random/lib/sequences.lisp	(revision 13309)
@@ -0,0 +1,2154 @@
+;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;
+;; utility functions
+;;
+;;  these probably want to be in-line
+
+(defun make-sequence-like (sequence length)
+  (seq-dispatch 
+   sequence
+   (make-list length)
+   (make-array length :element-type (array-element-type sequence))))
+
+(defun adjust-test-args (item test test-not)
+  ;; after running this "test" is the real test, a null test means "eq"
+  ;; and "test-not" is used as a flag
+  (when test-not
+    (if test 
+      (error "Both ~s and ~s keywords supplied" :test :test-not)
+      (setq test test-not)))
+  (if test
+    (if (or (eq test #'eq)
+            (eq test 'eq)
+            (and (or (eq test #'equal) (eq test 'equal))
+                 (or (fixnump item) (symbolp item))))
+      (setq test nil)
+      (if (eq test #'funcall)
+        (setq test 'funcall)))
+    (if (or (macptrp item) (and (not (fixnump item)) (numberp item)))
+      (setq test #'eql)))
+  (values test test-not))
+
+(defun adjust-key (key)
+  (and (neq key 'identity) 
+       (neq key #'identity)
+       key))
+
+(defun matchp2 (item elt test test-not key)
+  (if key
+    (setq elt (funcall key elt)))
+  (let ((res (if test
+               (if (eq test 'funcall)
+                 (funcall item elt)
+                 (funcall test item elt))
+               (eq item elt))))
+    (if test-not
+      (not res)
+      res)))
+
+;;; CTYPE is a recognizable subtype of VECTOR, which means that it's either
+;;; a) an ARRAY-CTYPE
+;;; b) a UNION-CTYPE whose leaves are ARRAY-CTYPE
+;;; c) the NIL type, which is trivially a subtype of VECTOR but isn't really
+;;;    worth considering here
+;;; d) a MEMBER-CTYPE whose members are all vectors and which therefore have
+;;;    corresponding ARRAY-CTYPEs.
+;;; Try to find the interesection of all ARRAY-CTYPEs referenced in CTYPE and
+;;;  return it.
+;;; Note that this intersection may be the null type.
+(defun simplify-vector-ctype (ctype)
+  (typecase ctype
+    (array-ctype
+     (make-array-ctype :complexp nil
+                       :element-type (array-ctype-element-type ctype)
+                       :specialized-element-type (array-ctype-specialized-element-type ctype)
+                       :dimensions '(*)))
+                                      
+    (named-ctype ctype)
+    (member-ctype
+     (apply #'type-intersection (mapcar #'(lambda (x)
+                                            (simplify-vector-ctype
+                                             (ctype-of x)))
+                                        (member-ctype-members ctype))))
+    (union-ctype
+     (apply #'type-intersection (mapcar #'simplify-vector-ctype (union-ctype-types ctype))))))
+    
+(defun make-sequence (type length &key (initial-element nil initial-element-p))
+  "Return a sequence of the given TYPE and LENGTH, with elements initialized
+  to INITIAL-ELEMENT."
+  (setq length (require-type length 'fixnum))
+  (let* ((ctype (specifier-type type)))
+    (declare (fixnum length))
+    (if (< length 0) (report-bad-arg length '(and fixnum unsigned-byte)))
+    (let ((tlength (array-ctype-length ctype)))
+      (if (and tlength (neq tlength length))
+        (error 'invalid-subtype-error
+               :datum type
+               :expected-type `(vector ,(type-specifier (array-ctype-element-type ctype)) ,length))))
+    (cond 
+          ((csubtypep ctype (specifier-type 'base-string))
+           (if initial-element-p
+             (make-string length 
+                          :element-type 'base-char
+                          :initial-element initial-element)
+             (make-string length
+                          :element-type 'base-char)))
+          ((csubtypep ctype (specifier-type 'vector))
+           (let* ((atype (simplify-vector-ctype ctype)))
+             (unless (typep atype 'array-ctype)
+               (error "Can't determine vector element-type of ~s" (type-specifier ctype)))
+             (let* ((element-type (type-specifier (array-ctype-element-type atype))))
+               (if (eq element-type '*) (setq element-type t))
+               (if initial-element-p
+                 (make-array (the fixnum length)
+                             :element-type element-type
+                             :initial-element initial-element)
+                 (make-array (the fixnum length)
+                             :element-type element-type)))))
+          ((csubtypep ctype (specifier-type 'null))
+           (unless (zerop length)
+             (error 'invalid-subtype-error :datum type :expected-type 'cons)))
+          ((csubtypep ctype (specifier-type 'cons))
+           (if (zerop length)
+             (error 'invalid-subtype-error :datum type :expected-type 'null)
+             (make-list length :initial-element initial-element)))
+          ((csubtypep ctype (specifier-type 'list))
+           (make-list length :initial-element initial-element))
+          (t (error 'invalid-subtype-error :datum  type
+                    :expected-type 'sequence)))))
+
+
+
+;;; Subseq:
+
+;;; SRC is a (SIMPLE-ARRAY * (*)), TYPECODE is its ... typecode,
+;;; START and END are fixnums and sanity-checked.
+(defun simple-1d-array-subseq (src typecode start end)
+  (declare (fixnum start end typecode))
+  (let* ((n (- end start))
+	 (dest (%alloc-misc n typecode)))
+    (declare (fixnum n))
+    (if (= typecode target::subtag-simple-vector)
+      (%copy-gvector-to-gvector src start dest 0 n)
+      (ecase typecode
+	((#.target::subtag-s8-vector
+	  #.target::subtag-u8-vector)
+	 (%copy-ivector-to-ivector src start dest 0 n))
+	((#.target::subtag-s16-vector
+	  #.target::subtag-u16-vector)
+	 (%copy-ivector-to-ivector src
+				   (the fixnum (+ start start))
+				   dest
+				   0
+				   (the fixnum (+ n n))))
+	((#.target::subtag-s32-vector
+	  #.target::subtag-u32-vector
+	  #.target::subtag-single-float-vector
+          #+32-bit-target #.target::subtag-fixnum-vector
+          #.target::subtag-simple-base-string)
+	 (%copy-ivector-to-ivector src
+				   (the fixnum (ash start 2))
+				   dest
+				   0
+				   (the fixnum (ash n 2))))
+	;; DOUBLE-FLOAT vectors have extra alignment padding on ppc32/x8632.
+	#+(or ppc32-target x8632-target)
+	(#.target::subtag-double-float-vector
+	 (%copy-ivector-to-ivector src
+				   (the fixnum (+ (the fixnum (ash start 3))
+						  (- target::misc-dfloat-offset
+						     target::misc-data-offset)))
+				   dest
+				   (- target::misc-dfloat-offset
+						     target::misc-data-offset)
+				   (the fixnum (ash n 3))))
+	#+64-bit-target
+	((#.target::subtag-double-float-vector
+	  #.target::subtag-s64-vector
+	  #.target::subtag-u64-vector
+          #.target::subtag-fixnum-vector)
+	 (%copy-ivector-to-ivector src
+				   (the fixnum (ash start 3))
+				   dest
+				   0
+				   (the fixnum (ash n 3))))
+	(#.target::subtag-bit-vector
+	 ;; We can probably do a byte at a time if (not (logtest start 7))
+	 (if (not (logtest start 7))
+	   (%copy-ivector-to-ivector src
+				     (the fixnum (ash (the fixnum (+ start 7))
+						      -3))
+				     dest
+				     0
+				     (the fixnum (ash (the fixnum (+ n 7))
+						      -3)))
+	   ;; Harder to optimize this case.
+	   (locally  (declare (simple-bit-vector src dest)
+			      (optimize (speed 3) (safety 0)))
+	     (do* ((i start (1+ i))
+		   (j 0 (1+ j)))
+		  ((= i end) dest)
+	       (declare (fixnum i j))
+	       (setf (sbit dest j) (sbit src i))))))))))
+
+
+(defun nthcdr-error (index list &aux (copy list))
+ "If index > length, error"
+ (dotimes (i index copy)
+   (declare (fixnum i))
+   (if copy
+     (setq copy (cdr copy))
+     (%err-disp $XACCESSNTH index list))))
+
+; slisp didn't error if end > length, or if start > end.
+(defun list-subseq* (sequence start end)
+  (declare (fixnum start end))
+  (if (= start end)
+    nil
+    (let* ((groveled (nthcdr-error start sequence))
+           (result (list (car groveled))))
+      (when groveled
+        (do ((list (cdr groveled) (cdr list))
+             (splice result (cdr (rplacd splice (list (car list)))))
+             (index (1+ start) (1+ index)))
+             ((= index end) result)
+          (declare (fixnum index))
+           ())))))
+
+; This ensures that start & end will be non-negative FIXNUMS ...
+; This implies that the address space is < 2^31 bytes, i.e., no list
+; can have a length > most-positive fixnum.  Let them report it as a
+; bug ...
+
+(defun subseq (sequence start &optional end)
+  "Return a copy of a subsequence of SEQUENCE starting with element number
+   START and continuing to the end of SEQUENCE or the optional END."
+  (setq end (check-sequence-bounds sequence start end))
+  (locally 
+      (declare (fixnum start end))
+      (seq-dispatch 
+       sequence
+       (list-subseq* sequence start end)
+       (let* ((typecode (typecode sequence)))
+	 (declare (fixnum typecode))
+	 (when (= typecode target::subtag-vectorH)
+	   (multiple-value-bind (data offset)
+	       (array-data-and-offset sequence)
+	     (declare (fixnum offset))
+	     (incf start offset)
+	     (incf end offset)
+	     (setq sequence data typecode (typecode data))))
+	 (simple-1d-array-subseq sequence typecode start end)))))
+	 
+
+;;; Copy-seq:
+
+(defun copy-seq (sequence)
+  "Return a copy of SEQUENCE which is EQUAL to SEQUENCE but not EQ."
+  (seq-dispatch 
+   sequence
+   (copy-list sequence)
+   (let* ((length (length sequence))
+          (subtype (element-type-subtype (array-element-type sequence)))
+          (result  (%alloc-misc length subtype))
+          )
+     (multiple-value-bind (src offset) (array-data-and-offset sequence)
+       (declare (fixnum offset))                          
+       (dotimes (i length result)
+         (declare (fixnum i))
+         (setf (uvref result i) (uvref src offset))
+         (incf offset))))))
+
+
+
+;;; Fill:
+
+(defun fill (sequence item &key (start 0) end)
+  "Replace the specified elements of SEQUENCE with ITEM.
+   !$ could be sped up by calling iv-fill, sv-fill to avoid aref overhead."
+  (setq end (check-sequence-bounds sequence start end))
+  (seq-dispatch 
+   sequence
+   (do* ((current (nthcdr start sequence) (cdr (the list current)))
+         (index start (1+ index)))
+        ((or (atom current) (= index end)) sequence)
+     (rplaca (the cons current) item))
+   (if (and (typep sequence 'ivector)
+            (eql start 0)
+            (eql end (uvsize sequence)))
+     (%init-misc item sequence)
+     (do ((index start (1+ index)))
+         ((= index end) sequence)
+       (aset sequence index item)))))
+
+;;; Replace:
+
+(defun replace (target-sequence source-sequence &key
+                                ((:start1 target-start) 0)
+                                ((:end1 target-end))
+                                ((:start2 source-start) 0)
+                                ((:end2 source-end)))
+  "The target sequence is destructively modified by copying successive
+   elements into it from the source sequence."
+  (setq target-end (check-sequence-bounds target-sequence target-start
+                                          target-end))
+  (setq source-end (check-sequence-bounds source-sequence source-start
+                                          source-end))
+  (locally (declare (fixnum target-start target-end source-start source-end))
+    (seq-dispatch 
+     target-sequence
+     (seq-dispatch 
+      source-sequence
+      (if (and (eq target-sequence source-sequence) 
+               (> target-start source-start))
+        (let ((new-elts (subseq source-sequence source-start
+                                (+ source-start
+                                   (min (- target-end target-start)
+                                        (- source-end source-start))))))
+          (do ((n new-elts (cdr n))
+               (o (nthcdr target-start target-sequence) (cdr o)))
+              ((null n) target-sequence)
+            (rplaca o (car n))))
+        (do ((target-index target-start (1+ target-index))
+             (source-index source-start (1+ source-index))
+             (target-sequence-ref (nthcdr target-start target-sequence)
+                                  (cdr target-sequence-ref))
+             (source-sequence-ref (nthcdr source-start source-sequence)
+                                  (cdr source-sequence-ref)))
+            ((or (= target-index target-end) (= source-index source-end)
+                 (null target-sequence-ref) (null source-sequence-ref))
+             target-sequence)
+          (declare (fixnum target-index source-index))
+          (rplaca target-sequence-ref (car source-sequence-ref))))
+      (do ((target-index target-start (1+ target-index))
+           (source-index source-start (1+ source-index))
+           (target-sequence-ref (nthcdr target-start target-sequence)
+                                (cdr target-sequence-ref)))
+          ((or (= target-index target-end) (= source-index source-end)
+               (null target-sequence-ref))
+           target-sequence)
+        (declare (fixnum target-index source-index))
+        (rplaca target-sequence-ref (aref source-sequence source-index))))
+     (seq-dispatch 
+      source-sequence
+      (do ((target-index target-start (1+ target-index))
+           (source-index source-start (1+ source-index))
+           (source-sequence (nthcdr source-start source-sequence)
+                            (cdr source-sequence)))
+          ((or (= target-index target-end) (= source-index source-end)
+               (null source-sequence))
+           target-sequence)
+        (declare (fixnum target-index source-index))
+        (aset target-sequence target-index (car source-sequence)))
+      ;; If we are copying around in the same vector, be careful not
+      ;; to copy the same elements over repeatedly.  We do this by
+      ;; copying backwards.
+      (if (and (eq target-sequence source-sequence) 
+               (> target-start source-start))
+        (let ((nelts (min (- target-end target-start) 
+                          (- source-end source-start))))
+          (do ((target-index (+ target-start nelts -1) (1- target-index))
+               (source-index (+ source-start nelts -1) (1- source-index)))
+              ((= target-index (1- target-start)) target-sequence)
+            (aset target-sequence target-index
+                  (aref source-sequence source-index))))
+        (do ((target-index target-start (1+ target-index))
+             (source-index source-start (1+ source-index)))
+            ((or (= target-index target-end) (= source-index source-end))
+             target-sequence)
+          (declare (fixnum target-index source-index))
+          (aset target-sequence target-index
+                (aref source-sequence source-index))))))))
+
+;;; Concatenate:
+
+
+(defun concatenate (output-type-spec &rest sequences)
+  "Return a new sequence of all the argument sequences concatenated together
+  which shares no structure with the original argument sequences of the
+  specified OUTPUT-TYPE-SPEC."
+  (declare (dynamic-extent sequences))
+  (if (memq output-type-spec '(string simple-string))
+    (setq output-type-spec 'base-string)
+    (unless (memq output-type-spec '(string simple-string base-string list vector
+                                     simple-base-string
+                                     bit-vector simple-bit-vector))
+      (setq output-type-spec (type-expand output-type-spec))))
+  (case (if (atom output-type-spec) output-type-spec (car output-type-spec))
+    (list (apply #'concat-to-list* sequences))
+    ((simple-vector simple-string simple-base-string base-string vector string array
+                    bit-vector simple-bit-vector)
+     (apply #'concat-to-simple* output-type-spec sequences))
+    (t
+     (if (subtypep output-type-spec 'vector)
+       (apply #'concat-to-simple* output-type-spec sequences)
+       (if (subtypep output-type-spec 'list)
+         (apply #'concat-to-list* sequences)
+         (error "~S: invalid output type specification." output-type-spec))))))
+
+;;; Internal Frobs:
+
+(defun concat-to-list* (&rest sequences)
+  (declare (dynamic-extent sequences))
+  (let* ((result (list nil))
+         (splice result))
+    (dolist (sequence sequences (%cdr result))
+      (seq-dispatch
+       sequence
+       (dolist (item sequence)
+         (setq splice (%cdr (%rplacd splice (list item)))))
+       (dotimes (i (length sequence))
+         (setq splice (%cdr (%rplacd splice (list (aref sequence i))))))))))
+             
+
+(defun concat-to-simple* (output-type-spec &rest arg-sequences)
+  (declare (dynamic-extent arg-sequences))
+  (do ((seqs arg-sequences (cdr seqs))
+        (total-length 0)
+        ;(lengths ())
+        )
+      ((null seqs)
+       (do ((sequences arg-sequences (cdr sequences))
+            ;(lengths lengths (cdr lengths))
+            (index 0)
+            (result (make-sequence output-type-spec total-length)))
+           ((= index total-length) result)
+         (let ((sequence (car sequences)))
+           (seq-dispatch
+            sequence
+            (do ((sequence sequence (cdr sequence)))
+                ((atom sequence))
+              (aset result index (car sequence))
+              (setq index (1+ index)))
+            (let ((len (length sequence)))
+              (do ((jndex 0 (1+ jndex)))
+                  ((= jndex len))
+                (aset result index (aref sequence jndex))
+                (setq index (1+ index))))))))
+     (let ((length (length (car seqs))))
+       ;(setq lengths (nconc lengths (list length))) ; if itsa list, we dont care about its length, if itsan array, length twice is cheap
+       (setq total-length (+ total-length length)))))
+
+(defun concat-to-string (&rest sequences)
+  (declare (dynamic-extent sequences))
+  (let* ((size 0))
+    (declare (fixnum size))
+    (dolist (seq sequences)
+      (setq size (+ size (the fixnum (length seq)))))
+    (let* ((result (make-string size))
+           (out 0))
+      (declare (simple-string result) (fixnum out))
+      (dolist (seq sequences result)
+        (etypecase seq
+          (simple-string
+           (let* ((n (length seq)))
+             (declare (fixnum n))
+             (%copy-ivector-to-ivector seq
+                                       0
+                                       result
+                                       (the fixnum (ash out 2))
+                                       (the fixnum (ash n 2)))
+             (incf out n)))
+          (string
+           (let* ((n (length seq)))
+             (declare (fixnum n))
+             (multiple-value-bind (data offset) (array-data-and-offset seq)
+               (declare (fixnum offset))
+               (%copy-ivector-to-ivector data
+                                         (the fixnum (ash offset 2))
+                                         result
+                                         (the fixnum (ash out 2))
+                                         (the fixnum (ash n 2)))
+               (incf out n))))
+          (vector
+           (dotimes (i (length seq))
+             (setf (schar result out) (aref seq i))
+             (incf out)))
+          (list
+           (dolist (elt seq)
+             (setf (schar result out) elt))))))))
+
+;This one doesn't choke on circular lists, doesn't cons as much, and is
+;about 1/8K smaller to boot.
+(defun map (type function sequence &rest more-sequences)
+  (declare (dynamic-extent more-sequences))
+  (let* ((sequences (cons sequence more-sequences))
+         (arglist (make-list (length sequences)))
+         (index 0)
+         args seq p (ans ()))
+    (declare (dynamic-extent sequences arglist))
+    (unless (or (null type)
+                (eq type 'list)
+                (memq (if (consp type) (%car type) type)
+                      '(simple-vector simple-string vector string array
+                        simple-array bit-vector simple-bit-vector))
+                (subtypep type 'sequence))
+      (report-bad-arg type 'sequence))
+    (loop
+      (setq p sequences args arglist)
+      (while p
+        (cond ((null (setq seq (%car p))) (return))
+              ((consp seq)
+               (%rplaca p (%cdr seq))
+               (%rplaca args (%car seq)))
+              ((eq index (length seq)) (return))
+              (t (%rplaca args (elt seq index))))
+        (setq args (%cdr args) p (%cdr p)))
+      (setq p (apply function arglist))
+      (if type (push p ans))
+      (setq index (%i+ index 1)))
+    (when type
+      (setq ans (nreverse ans))
+      (if (eq type 'list) ans (coerce ans type)))))
+
+;;;;;;;;;;;;;;;;;
+;;
+;; some, every, notevery, notany
+;;
+;; these all call SOME-XX-MULTI or SOME-XX-ONE
+;; SOME-XX-MULTI should probably be coded in lap
+;;
+;; these should be transformed at compile time
+;;
+;; we may want to consider open-coding when
+;; the predicate is a lambda
+;; 
+
+(eval-when (:execute :compile-toplevel)
+  (defmacro negating-quantifier-p (quantifier-constant)
+    `(%i> ,quantifier-constant $notany))
+  )
+
+; Vector is guaranteed to be simple; new-size is guaranteed <= (length vector).
+; Return vector with its size adjusted and extra doublewords zeroed out.
+; Should only be called on freshly consed vectors...
+
+    
+    
+(defun some (predicate one-seq &rest sequences)
+  "Apply PREDICATE to the 0-indexed elements of the sequences, then 
+   possibly to those with index 1, and so on. Return the first 
+   non-NIL value encountered, or NIL if the end of any sequence is reached."
+  (declare (dynamic-extent sequences))
+  (if sequences
+      (some-xx-multi $some nil predicate one-seq sequences)
+      (some-xx-one $some nil predicate one-seq)))
+
+(defun notany (predicate one-seq &rest sequences)
+  "Apply PREDICATE to the 0-indexed elements of the sequences, then 
+   possibly to those with index 1, and so on. Return NIL as soon
+   as any invocation of PREDICATE returns a non-NIL value, or T if the end
+   of any sequence is reached."
+  (declare (dynamic-extent sequences))
+  (if sequences
+      (some-xx-multi $notany t predicate one-seq sequences)
+      (some-xx-one $notany t predicate one-seq)))
+
+(defun every (predicate one-seq &rest sequences)
+  "Apply PREDICATE to the 0-indexed elements of the sequences, then
+   possibly to those with index 1, and so on. Return NIL as soon
+   as any invocation of PREDICATE returns NIL, or T if every invocation
+   is non-NIL."
+  (declare (dynamic-extent sequences))
+  (if sequences
+      (some-xx-multi $every t predicate one-seq sequences)
+      (some-xx-one $every t predicate one-seq)))
+
+(defun notevery (predicate one-seq &rest sequences)
+  "Apply PREDICATE to 0-indexed elements of the sequences, then
+   possibly to those with index 1, and so on. Return T as soon
+   as any invocation of PREDICATE returns NIL, or NIL if every invocation
+   is non-NIL."
+  (declare (dynamic-extent sequences))
+  (if sequences
+      (some-xx-multi $notevery nil predicate one-seq sequences)
+      (some-xx-one $notevery nil predicate one-seq)))
+
+(defun some-xx-multi (caller at-end predicate first-seq sequences)
+  (let* ((sequences (cons first-seq sequences))
+         (min-vector-length target::target-most-positive-fixnum)
+         (arg-slice (make-list (list-length sequences)))
+         (cur-slice arg-slice)
+         (not-result (negating-quantifier-p caller))
+         result)
+  (declare (fixnum min-vector-length)
+           (list sequences arg-slice cur-slice)
+           (dynamic-extent sequences arg-slice))
+  (dolist (seq sequences)
+    (seq-dispatch seq
+                  nil
+                  (setq min-vector-length (min min-vector-length
+                                               (length seq)))))
+  (dotimes (index min-vector-length)
+    (dolist (one-seq sequences)
+      (%rplaca cur-slice
+               (if (vectorp one-seq)
+                   (aref one-seq index)
+                   (if one-seq
+                       (progn
+                         (%rplaca (memq one-seq sequences) (cdr one-seq))
+                         (%car one-seq))
+                       (return-from some-xx-multi at-end))))
+      (setq cur-slice (%cdr cur-slice)))
+    (setq result (apply predicate arg-slice)
+          cur-slice arg-slice)
+    (if not-result
+        (when (not result)
+          (return-from some-xx-multi
+                       (if (eq caller $every) nil t)))
+        (when result
+          (return-from some-xx-multi
+                       (if (eq caller $some) result nil)))))
+  at-end))
+
+
+(defun some-xx-one (caller at-end predicate seq
+                           &aux (not-result (negating-quantifier-p caller))
+                           result)
+  (if (vectorp seq)
+      (if (simple-vector-p seq)
+        (locally (declare (type simple-vector seq))
+          (dovector (element seq)
+            (setq result (funcall predicate element))
+            (if not-result
+              (when (not result)
+                (return-from some-xx-one
+                  (if (eq caller $every) nil t)))
+              (when result
+                (return-from some-xx-one
+                  (if (eq caller $some ) result nil))))))
+        (dovector (element seq)
+          (setq result (funcall predicate element))
+          (if not-result
+            (when (not result)
+              (return-from some-xx-one
+                (if (eq caller $every) nil t)))
+            (when result
+              (return-from some-xx-one
+                (if (eq caller $some ) result nil))))))
+      (dolist (element seq)
+        (setq result (funcall predicate element))
+        (if not-result
+            (when (not result)
+              (return-from some-xx-one
+                           (if (eq caller $every) nil t)))
+            (when result
+              (return-from some-xx-one
+                           (if (eq caller $some ) result nil))))))
+      at-end)
+
+;;; simple positional versions of find, position
+
+(defun find-positional-test-key (item sequence test key)
+  (if sequence
+    (seq-dispatch
+     sequence
+     (let ((cons (member item sequence :test test :key key)))
+       (and cons (%car cons)))
+     (let ((pos (vector-position-1 item sequence nil test nil 0 nil key)))
+       (and pos (aref sequence pos))))))
+
+(defun find-positional-test-not-key (item sequence test-not key)
+  (if sequence
+    (seq-dispatch
+     sequence
+     (let ((cons (member item sequence :test-not test-not :key key)))
+       (and cons (%car cons)))
+     (let ((pos (vector-position-1 item sequence nil nil test-not 0 nil key)))
+       (and pos (aref sequence pos))))))
+
+(defun position-positional-test-key (item sequence test key)
+  (if sequence
+    (seq-dispatch
+     sequence
+     (progn
+       (setq key (adjust-key key))
+       (setq test
+             (adjust-test-args item test nil))
+       (if (or test key)
+         (list-position/find-complex nil item sequence 0 nil test nil key)
+         (list-position/find-simple nil item sequence 0 nil)))
+     (vector-position-1 item sequence nil test nil 0 nil key))))
+
+(defun position-positional-test-not-key (item sequence test-not key)
+  (if sequence
+    (seq-dispatch
+     sequence
+     (progn
+       (setq key (adjust-key key))
+       (multiple-value-bind (test test-not)
+                            (adjust-test-args item nil test-not)
+         (list-position/find-complex nil item sequence 0 nil test test-not key)))
+     (vector-position-1 item sequence nil nil test-not 0 nil key))))
+
+
+;;; Reduce:
+
+(eval-when (:execute :compile-toplevel)
+  
+  (defmacro list-reduce (function sequence start end initial-value ivp key)
+    (let ((what `(if ,key (funcall ,key (car sequence)) (car sequence))))
+      `(let ((sequence (nthcdr ,start ,sequence)))
+         (do ((count (if ,ivp ,start (1+ ,start)) (1+ count))
+              (sequence (if ,ivp sequence (cdr sequence))
+                        (cdr sequence))
+              (value (if ,ivp ,initial-value ,what)
+                     (funcall ,function value ,what)))
+             ((= count ,end) value)))))
+  
+  (defmacro list-reduce-from-end (function sequence start end 
+                                           initial-value ivp key)
+    (let ((what `(if ,key (funcall ,key (car sequence)) (car sequence))))
+      `(let ((sequence (nthcdr (- (length ,sequence) ,end) (reverse ,sequence))))
+         (do ((count (if ,ivp ,start (1+ ,start)) (1+ count))
+              (sequence (if ,ivp sequence (cdr sequence))
+                        (cdr sequence))
+              (value (if ,ivp ,initial-value ,what)
+                     (funcall ,function ,what value)))
+             ((= count ,end) value)))))
+  
+  ) ;; end eval-when
+
+(defun reduce (function sequence &key from-end (start 0)
+                        end (initial-value nil ivp) key)
+  "The specified Sequence is ``reduced'' using the given Function.
+  See manual for details."
+  (unless end (setq end (length sequence)))
+  (if (= end start)
+    (if ivp initial-value (funcall function))
+    (seq-dispatch
+     sequence
+     (if from-end
+       (list-reduce-from-end  function sequence start end initial-value ivp key)
+       (list-reduce function sequence start end initial-value ivp key))
+     (let* ((disp (if from-end -1 1))
+            (index (if from-end (1- end) start))
+            (terminus (if from-end (1- start) end))
+            (value (if ivp initial-value
+                       (let ((elt (aref sequence index)))
+                         (setq index (+ index disp))
+                         (if key (funcall key elt) elt))))
+            (element nil))
+       (do* ()
+            ((= index terminus) value)
+         (setq element (aref sequence index)
+               index (+ index disp)
+               element (if key (funcall key element) element)
+               value (funcall function (if from-end element value) (if from-end value element))))))))
+
+(defun map-into (result-sequence function &rest sequences)
+  (declare (dynamic-extent sequences))
+  (let* ((nargs (list-length sequences))
+         (temp (make-list (length sequences)))
+         (maxcnt (seq-dispatch result-sequence (length result-sequence) (array-total-size result-sequence)))
+         (rseq result-sequence))
+    (declare (fixnum nargs maxcnt))
+    (declare (dynamic-extent temp))
+    ; this declaration is maybe bogus
+    (dolist (seq sequences)
+      (let ((len (length seq)))
+        (declare (fixnum len))
+        (if (< len maxcnt)(setq maxcnt len))))
+    (dotimes (cnt maxcnt)
+      (let ((args temp)(seqs sequences))
+        (dotimes (i nargs)
+          (let ((seq (%car seqs)))
+            (cond ((listp seq)
+                   (%rplaca seqs (%cdr seq))
+                   (%rplaca args (%car seq)))
+                  (t (%rplaca args (aref seq cnt)))))
+          (setq args (%cdr args))
+          (setq seqs (%cdr seqs))))
+      (let ((res (apply function temp)))
+        (cond ((consp rseq)
+               (%rplaca rseq res)
+               (setq rseq (%cdr rseq)))
+              (t (setf (aref result-sequence cnt) res)))))
+    (when (and (not (listp result-sequence))
+               (array-has-fill-pointer-p result-sequence))
+      (setf (fill-pointer result-sequence) maxcnt))
+    result-sequence))
+          
+    
+;;; Coerce:
+
+#|
+; don't know if this is always right
+; It's almost never right: the "type-spec" could be something
+; defined with DEFTYPE, whose last element (if it has one) has
+; nothing to do with the "length" of the specified type.
+(defun specifier-length (type-spec)
+  (if (consp type-spec)
+    (let ((len? (car (last type-spec))))
+      (if (fixnump len?) len?))))
+|#
+
+
+(defun array-ctype-length (ctype)
+  (if (typep ctype 'array-ctype)
+    (let* ((dims (array-ctype-dimensions ctype)))
+      (if (listp dims)
+        (if (null (cdr dims))
+          (let* ((dim0 (car dims)))
+            (unless (eq dim0 '*) dim0)))))))
+
+
+
+
+; from optimizer - just return object if type is OK
+
+
+;If you change this, remember to change the transform.
+(defun coerce (object output-type-spec)
+  "Coerce the Object to an object of type Output-Type-Spec."
+  (let* ((type (specifier-type output-type-spec)))
+    (if (%typep object type)
+      object
+      (cond
+        ((csubtypep type (specifier-type 'character))
+         (character object))
+        ((eq output-type-spec 'standard-char)
+         (let ((char (character object)))
+           (unless (standard-char-p char) (%err-disp $xcoerce object 'standard-char))
+           char))
+        ((eq output-type-spec 'compiled-function)
+         (coerce-to-compiled-function object))
+        ((csubtypep type (specifier-type 'function))
+         (coerce-to-function-1 object))
+        ((csubtypep type (specifier-type 'cons))
+         (if object
+           (coerce-to-list object)
+           (report-bad-arg object 'cons)))
+        ((csubtypep type (specifier-type 'list))
+         (coerce-to-list object))
+        ((csubtypep type (specifier-type 'string))
+         (let ((length (array-ctype-length type)))
+           (if (and length (neq length (length object)))
+             (report-bad-arg (make-string length) `(string ,(length object)))))
+         (coerce-to-uarray object #.(type-keyword-code :simple-string)
+                           t))
+        ((csubtypep type (specifier-type 'vector))
+         (let ((length (array-ctype-length type)))
+           (if (and length (neq length (length object)))
+             (error 'invalid-subtype-error
+                    :datum output-type-spec
+                    :expected-type `(vector * ,(length object)))))
+         (let* ((atype (simplify-vector-ctype type)))
+           (unless (typep atype 'array-ctype)
+             (error "Can't determine vector type of ~s" output-type-spec))
+           (let* ((element-type (type-specifier (array-ctype-element-type atype))))
+             (let ((length (array-ctype-length atype)))
+               (if (and length (neq length (length object)))
+                 (report-bad-arg (make-array length :element-type element-type)
+                                 `(vector ,element-type ,(length object))))
+               (coerce-to-uarray object (element-type-subtype element-type) t)))))
+        ((csubtypep type (specifier-type 'array))
+         (let* ((dims (array-ctype-dimensions type)))
+           (when (consp dims)
+             (when (not (null (cdr dims)))(error "~s is not a sequence type." output-type-spec))))
+         (let ((length (array-ctype-length type)))
+           (if (and length (neq length (length object)))
+             (error "Length of ~s is not ~s." object length)))
+         (coerce-to-uarray object (element-type-subtype (type-specifier 
+                                                         (array-ctype-element-type type))) t))
+        ((numberp object)
+         (let ((res
+                (cond
+                  ((csubtypep type (specifier-type 'double-float))
+                   (float object 1.0d0))
+                  ((csubtypep type (specifier-type 'float))
+                   (float object 1.0s0))                		
+                  ((csubtypep type (specifier-type 'complex))
+                   (coerce-to-complex object  output-type-spec)))))
+           (unless res                  ;(and res (%typep res type))
+             (error "~S can't be coerced to type ~S." object output-type-spec))
+           res))
+        (t (error "~S can't be coerced to type ~S." object output-type-spec))))))
+
+(defun %coerce-to-string (seq)
+   (let* ((len (length seq))
+          (string (make-string len)))
+     (declare (fixnum len) (simple-base-string string))
+     (if (typep seq 'list)
+       (do* ((l seq (cdr l))
+             (i 0 (1+ i)))
+            ((null l) string)
+         (declare (list l) ; we know that it's a proper list because LENGTH won
+                  (fixnum i))
+         (setf (schar string i) (car l)))
+       (dotimes (i len string)
+         (setf (schar string i) (aref seq i))))))
+
+(defun %coerce-to-vector (seq subtype)
+   (let* ((len (length seq))
+          (vector (%alloc-misc len subtype)))
+     (declare (fixnum len) (type (simple-array * (*)) vector))
+     (if (typep seq 'list)
+       (do* ((l seq (cdr l))
+             (i 0 (1+ i)))
+            ((null l) vector)
+         (declare (list l) ; we know that it's a proper list because LENGTH won
+                  (fixnum i))
+         (setf (uvref vector i) (car l)))
+       (dotimes (i len vector)
+         (setf (uvref vector i) (aref seq i))))))
+
+(defun %coerce-to-list (seq)
+  (if (typep seq 'list)
+    seq
+    (collect ((result))
+      (dotimes (i (length seq) (result))
+        (result (aref seq i))))))
+
+
+
+
+(defun coerce-to-complex (object  output-type-spec)
+  (if (consp output-type-spec)
+      (let ((type2 (cadr output-type-spec)))     
+        (if (complexp object)
+	    (complex (coerce (realpart object) type2)(coerce (imagpart object) type2))
+	    (complex (coerce object type2) 0)))
+      (complex object)))
+        
+
+(defun coerce-to-function-1 (thing)
+  (if (functionp thing)
+    thing
+    (if (symbolp thing)
+      (%function thing)
+      (if (lambda-expression-p thing)
+        (%make-function nil thing nil)
+        (%err-disp $xcoerce thing 'function)))))
+
+;;; Internal Frobs:
+;(coerce object '<array-type>)
+(defun coerce-to-uarray (object subtype simple-p)
+  (if (typep object 'array)
+    (if (and (or (not simple-p) (typep object 'simple-array))
+             (or (null subtype) (eq (array-element-subtype object) subtype)))
+      object
+      ;Make an array of the same shape as object but different subtype..
+      (%copy-array subtype object))
+    (if (typep object 'list)
+      (%list-to-uvector subtype object)
+      (%err-disp $xcoerce object 'array))))
+
+;(coerce object 'list)
+(defun coerce-to-list (object)
+  (seq-dispatch 
+   object
+   object
+   (let* ((n (length object)))
+     (declare (fixnum n))
+     (multiple-value-bind (data offset) (array-data-and-offset object)
+       (let* ((head (cons nil nil))
+              (tail head))
+         (declare (dynamic-extent head)
+                  (cons head tail))
+         (do* ((i 0 (1+ i))
+               (j offset (1+ j)))
+              ((= i n) (cdr head))
+           (declare (fixnum i j))
+           (setq tail (cdr (rplacd tail (cons (uvref data j) nil))))))))))
+ 
+
+(defun %copy-array (new-subtype array)
+  ;To be rewritten once make-array disentangled (so have a subtype-based entry
+  ;point)
+  (make-array (if (eql 1 (array-rank array))
+                (length array)
+                (array-dimensions array))
+              :element-type (element-subtype-type new-subtype)
+              :initial-contents array ;***** WRONG *****
+              ))
+
+(defun check-count (c)
+  (if c
+    (min (max (require-type c 'integer) 0) target::target-most-positive-fixnum)
+    target::target-most-positive-fixnum))
+
+;;; Delete:
+
+(defun list-delete-1 (item list from-end test test-not start end count key 
+                           &aux (temp list)  revp)
+  (unless end (setq end target::target-most-positive-fixnum))
+  (when (and from-end count)
+    (let ((len (length temp)))
+      (if (not (%i< start len))
+        (return-from list-delete-1 temp))
+      (setq temp (nreverse temp) revp t)
+      (psetq end (%i- len start)
+             start (%i- len (%imin len end)))))
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not)
+                       (adjust-test-args item test test-not))
+  (setq temp
+        (if (or test key test-not)
+          (list-delete-moderately-complex item temp start end count test test-not key)
+          (list-delete-very-simple item temp start end count)))
+   (if revp
+    (nreverse temp)
+    temp))
+
+
+(defun list-delete-very-simple (item list start end count)
+  (unless start (setq start 0))
+  (unless end (setq end target::target-most-positive-fixnum))
+  (setq count (check-count count))
+  (do* ((handle (cons nil list))
+        (splice handle)
+        (numdeleted 0)
+        (i 0 (1+ i)))
+       ((or (eq i end) (null (%cdr splice)) (eq numdeleted count))
+        (%cdr handle))
+    (declare (fixnum i start end count numdeleted)  ; declare-type-free !!
+             (dynamic-extent handle) 
+             (list splice handle))
+    (if (and (%i>= i start) (eq item (car (%cdr splice))))
+      (progn
+        (%rplacd splice (%cddr splice))
+        (setq numdeleted (%i+ numdeleted 1)))
+      (setq splice (%cdr splice)))))
+
+(defun list-delete-moderately-complex (item list start end count test test-not key)
+  (unless start (setq start 0))
+  (unless end (setq end target::target-most-positive-fixnum))
+  (setq count (check-count count))
+  (do* ((handle (cons nil list))
+        (splice handle)
+        (numdeleted 0)
+        (i 0 (1+ i)))
+       ((or (= i end) (null (cdr splice)) (= numdeleted count))
+        (cdr handle))
+    (declare (fixnum i start end count numdeleted)
+             (dynamic-extent handle)
+             (list splice))
+    (if (and (>= i start) (matchp2 item (cadr splice) test test-not key))
+      (progn
+        (rplacd splice (cddr splice))
+        (setq numdeleted (1+ numdeleted)))
+      (setq splice (cdr splice)))))
+
+(defun list-delete (item list &key from-end test test-not (start 0)
+                         end count key 
+                         &aux (temp list)  revp)
+  (unless end (setq end target::target-most-positive-fixnum))
+  (when (and from-end count)
+    (let ((len (length temp)))
+      (if (not (%i< start len))
+        (return-from list-delete temp))
+      (setq temp (nreverse temp) revp t)
+      (psetq end (%i- len start)
+             start (%i- len (%imin len end)))))
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not)
+                       (adjust-test-args item test test-not))
+  (setq temp
+        (if (or test key test-not)
+          (list-delete-moderately-complex item temp start end count test test-not key)
+          (list-delete-very-simple item temp start end count)))
+   (if revp
+    (nreverse temp)
+    temp))
+
+; The vector will be freshly consed & nothing is displaced to it,
+; so it's legit to destructively truncate it.
+; Likewise, it's ok to access its components with UVREF.
+
+(defun simple-vector-delete (item vector test test-not key start end inc count
+                                  &aux (length (length vector)) 
+                                  subtype pos fill)
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not) (adjust-test-args item test test-not))
+  (setq end (check-sequence-bounds vector start end))
+  (setq fill start)
+  (if (%i< inc 0) (psetq start (%i- end 1) end (%i- start 1)))
+  (let* ((bv (make-array (the fixnum (length vector)) :element-type 'bit :Initial-element 0))
+         offset)    
+    (declare (dynamic-extent bv)
+             (type (simple-array bit (*)) bv))
+    (multiple-value-setq (vector offset)(array-data-and-offset vector))
+    (setq subtype (typecode vector))
+    (setq pos start)
+    (loop
+      (when (or (eq count 0) (eq pos end))
+        (unless (eq pos end)
+          (incf fill (abs (- pos end))))
+        (return))
+      (if (matchp2 item (uvref  vector (%i+ pos offset))
+                   test test-not key)
+        (progn (setf (aref bv pos) 1)
+               (setq count (%i- count 1)))
+        (setq fill (%i+ fill 1)))
+      (setq pos (%i+ pos inc)))
+    (when (%i< inc 0)
+      (psetq start (%i+ end 1) end (%i+ start 1)))
+    (let* ((tail (- length end))
+           (size (+ fill tail))
+           (new-vect (%alloc-misc size subtype))
+           (fill-end fill))
+      (declare (fixnum tail size))
+      (when (neq 0 start)
+        (dotimes (i start)
+          (setf (uvref new-vect i) (uvref  vector (%i+ offset i)))
+          ))
+      (setq fill start)
+      (setq pos start)
+      (loop
+        (if (eq fill fill-end) (return))
+        (if (neq 1 (aref bv pos))
+          (progn
+            (setf (uvref new-vect fill) (uvref vector (%i+ offset pos)))
+            (setq fill (%i+ fill 1))))
+        (setq pos (%i+ pos 1)))
+      (setq pos end)
+      (loop
+        (when (eq fill size) (return))
+          (setf (uvref  new-vect fill) (uvref  vector (%i+ offset pos)))
+          (setq fill (%i+ fill 1)
+                pos (%i+ pos 1)))
+      new-vect)))
+
+
+; When a vector has a fill pointer & it can be "destructively modified" by adjusting
+; that fill pointer.
+(defun vector-delete (item vector test test-not key start end inc count
+                           &aux (length (length vector)) pos fill val)
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not) (adjust-test-args item test test-not))
+  (setq end (check-sequence-bounds vector start end))
+  (if (%i< inc 0) (psetq start (%i- end 1) end (%i- start 1)))
+  (setq fill (setq pos start))
+  (loop
+    (if (or (eq count 0) (eq pos end)) (return))
+    (if (matchp2 item (setq val (aref vector pos)) test test-not key)
+      (setq count (%i- count 1))
+      (progn
+        (if (neq fill pos) (setf (aref vector fill) val))
+        (setq fill (%i+ fill inc))))
+    (setq pos (%i+ pos inc)))
+  (if (%i> fill pos) (psetq fill (%i+ pos 1) pos (%i+ fill 1)))
+  (loop
+    (if (eq pos length) (return))
+    (setf (aref vector fill) (aref vector pos))
+    (setq fill (%i+ fill 1) pos (%i+ pos 1)))
+  (when (eq t (array-element-type vector))
+    (let ((old-fill (fill-pointer vector))
+          (i fill))
+      (declare (fixnum i old-fill))
+      (loop
+        (when (>= i old-fill) (return))
+        (setf (aref vector i) nil)
+        (incf i))))
+  (setf (fill-pointer vector) fill)
+  vector)
+
+(defun delete (item sequence &key from-end test test-not (start 0)
+                    end count key)
+  "Return a sequence formed by destructively removing the specified ITEM from
+  the given SEQUENCE."
+  (setq count (check-count count))
+  (if sequence
+    (seq-dispatch
+     sequence
+     (list-delete-1 item 
+                  sequence 
+                  from-end
+                  test 
+                  test-not
+                  start 
+                  end 
+                  count
+                  key)
+     (if (array-has-fill-pointer-p sequence)
+       (vector-delete item sequence test test-not key start end (if from-end -1 1) count)
+       (simple-vector-delete item
+                            sequence
+                             test test-not key start end (if from-end -1 1) count)))))
+
+(defun delete-if (test sequence &key from-end (start 0)                       
+                       end count key)
+  "Return a sequence formed by destructively removing the elements satisfying
+  the specified PREDICATE from the given SEQUENCE."
+  (delete test sequence
+          :test #'funcall
+          :from-end from-end 
+          :start start 
+          :end end 
+          :count count 
+          :key key))
+
+(defun delete-if-not (test sequence &key from-end (start 0) end count key)
+  "Return a sequence formed by destructively removing the elements not
+  satisfying the specified PREDICATE from the given SEQUENCE."
+  (delete test sequence 
+          :test-not #'funcall 
+          :from-end from-end 
+          :start start 
+          :end end 
+          :count count 
+          :key key))
+
+
+
+;;; Remove:
+
+
+
+(defun remove (item sequence &key from-end test test-not (start 0)
+                    end count key)
+  "Return a copy of SEQUENCE with elements satisfying the test (default is
+   EQL) with ITEM removed."
+  (setq count (check-count count))
+  (seq-dispatch
+   sequence
+   (list-delete-1 item 
+                (copy-list sequence)
+                from-end
+                test 
+                test-not
+                start 
+                end 
+                count
+                key)
+   (simple-vector-delete item
+                         sequence
+                         test
+                         test-not
+                         key
+                         start
+                         end
+                         (if from-end -1 1)
+                         count)))
+
+
+
+
+(defun remove-if (test sequence &key from-end (start 0)
+                         end count key)
+  "Return a copy of sequence with elements such that predicate(element)
+   is non-null removed"
+  (setq count (check-count count))
+  (remove test sequence
+          :test #'funcall
+          :from-end from-end
+          :start start
+          :end end
+          :count count
+          :key key))
+
+(defun remove-if-not (test sequence &key from-end (start 0)
+                         end count key)
+  "Return a copy of sequence with elements such that predicate(element)
+   is null removed"
+  (setq count (check-count count))
+  (remove test sequence
+          :test-not #'funcall
+          :from-end from-end
+          :start start
+          :end end
+          :count count
+          :key key))
+
+;;; Remove-Duplicates:
+
+;;; Remove duplicates from a list. If from-end, remove the later duplicates,
+;;; not the earlier ones. Thus if we check from-end we don't copy an item
+;;; if we look into the already copied structure (from after :start) and see
+;;; the item. If we check from beginning we check into the rest of the 
+;;; original list up to the :end marker (this we have to do by running a
+;;; do loop down the list that far and using our test.
+; test-not is typically NIL, but member doesn't like getting passed NIL
+; for its test-not fn, so I special cased the call to member. --- cfry
+
+(defun remove-duplicates (sequence &key (test #'eql) test-not (start 0) 
+      from-end end key)
+  "The elements of SEQUENCE are compared pairwise, and if any two match,
+   the one occurring earlier is discarded, unless FROM-END is true, in
+   which case the one later in the sequence is discarded. The resulting
+   sequence is returned.
+
+   The :TEST-NOT argument is deprecated."
+  (setq end (check-sequence-bounds sequence start end))
+  (delete-duplicates (copy-seq sequence) :from-end from-end :test test
+                     :test-not test-not :start start :end end :key key))
+
+;;; Delete-Duplicates:
+
+(defparameter *delete-duplicates-hash-threshold*  200)
+
+(defun list-delete-duplicates* (list test test-not key from-end start end)
+  ;;(%print "test:" test "test-not:" test-not "key:" key)
+  (let* ((len (- end start))
+	 (handle (cons nil list))
+	 (previous (nthcdr start handle)))
+    (declare (dynamic-extent handle))
+    (if (and (> len *delete-duplicates-hash-threshold*)
+	     (or (eq test 'eq) (eq test 'eql) (eq test 'equal) (eq test 'equalp)
+		 (eq test #'eq) (eq test #'eql) (eq test #'equal) (eq test #'equalp)))
+      (let ((hash (make-hash-table :size len :test test :shared nil)))
+        (loop for i from start below end as obj in (cdr previous)
+          do (incf (gethash (funcall key obj) hash 0)))
+        (loop for i from start below end while (cdr previous)
+          do (let* ((current (cdr previous))
+                    (obj (car current))
+                    (obj-key (funcall key obj)))
+               (if (if from-end
+                     ;; Keep first ref
+                     (prog1 (gethash obj-key hash) (setf (gethash obj-key hash) nil))
+                     ;; Keep last ref
+                     (eql (decf (gethash obj-key hash)) 0))
+                 (setq previous current)
+                 (rplacd previous (cdr current))))))
+      (do ((current (cdr previous) (cdr current))
+           (index start (1+ index)))
+          ((or (= index end) (null current)))
+        ;;(%print "outer loop top current:" current "previous:" previous)
+        (if (do ((x (if from-end 
+                      (nthcdr (1+ start) handle)
+                      (cdr current))
+                    (cdr x))
+                 (i (1+ index) (1+ i)))
+                ((or (null x) 
+                     (and (not from-end) (= i end)) 
+                     (eq x current)) 
+                 nil)
+              ;;(%print "inner loop top x:" x "i:" i)
+              (if (list-delete-duplicates*-aux current x test test-not key)
+                (return t)))
+          (rplacd previous (cdr current))
+          (setq previous (cdr previous)))))
+    (cdr handle)))
+
+(defun list-delete-duplicates*-aux (current x test test-not key)
+  (if test-not
+    (not (funcall test-not 
+                  (funcall key (car current))
+                  (funcall key (car x))))
+    (funcall test 
+             (funcall key (car current)) 
+             (funcall key (car x)))))
+
+
+(defun vector-delete-duplicates* (vector test test-not key from-end start end 
+					 &optional (length (length vector)))
+  (declare (vector vector))
+  (let* ((len (- end start))
+	 (index start)
+	 (jndex start))
+    (if (and (not test-not)
+	     (> len *delete-duplicates-hash-threshold*)
+	     (or (eq test 'eq) (eq test 'eql) (eq test 'equal) (eq test 'equalp)
+		 (eq test #'eq) (eq test #'eql) (eq test #'equal) (eq test #'equalp)))
+	(let ((hash (make-hash-table :size len :test test :shared nil)))
+	  (loop for i from start below end as obj = (aref vector i)
+	     do (incf (gethash (funcall key obj) hash 0)))
+	  (loop while (< index end) as obj = (aref vector index) as obj-key = (funcall key obj)
+	     do (incf index)
+	     do (when (if from-end
+			  (prog1 (gethash obj-key hash) (setf (gethash obj-key hash) nil))
+			  (eql (decf (gethash obj-key hash)) 0))
+		  (aset vector jndex obj)
+		  (incf jndex))))
+	(loop while (< index end) as obj = (aref vector index)
+	   do (incf index)
+	   do (unless (position (funcall key obj) vector :key key
+				:start (if from-end start index) :test test
+				:end (if from-end jndex end) :test-not test-not)
+		(aset vector jndex obj)
+		(incf jndex))))
+    (do ((index index (1+ index))	; copy the rest of the vector
+	 (jndex jndex (1+ jndex)))
+	((= index length)
+	 (setq vector (shrink-vector vector jndex)))
+      (aset vector jndex (aref vector index)))))
+
+
+(defun delete-duplicates (sequence &key (test #'eql) test-not (start 0) from-end end key)
+  "The elements of SEQUENCE are examined, and if any two match, one is
+   discarded.  The resulting sequence, which may be formed by destroying the
+   given sequence, is returned.
+   Sequences of type STR have a NEW str returned."
+  (setq end (check-sequence-bounds sequence start end))
+  (unless key (setq key #'identity))
+  (seq-dispatch sequence
+    (if sequence
+      (list-delete-duplicates* sequence test test-not key from-end start end))
+    (vector-delete-duplicates* sequence test test-not key from-end start end)))
+
+(defun list-substitute* (pred new list start end count key 
+                              test test-not old)
+  ;(print-db pred new list start end count key test test-not old)
+  (let* ((result (list nil))
+         elt
+         (splice result)
+         (list list))           ; Get a local list for a stepper.
+    (do ((index 0 (1+ index)))
+        ((= index start))
+      (setq splice (cdr (rplacd splice (list (car list)))))
+      (setq list (cdr list)))
+    (do ((index start (1+ index)))
+        ((or (and end (= index end)) (null list) (= count 0)))
+      (setq elt (car list))
+      (setq splice
+            (cdr (rplacd splice
+                         (list
+                          (cond ((case pred
+                                   (normal
+                                    (if test-not
+                                      (not (funcall test-not  old
+                                                    ;fry mod to slisp, which had arg order of OLD and ELT reversed.
+                                                    (funcall key elt)))
+                                      (funcall test old
+                                               (funcall key elt))))
+                                   (if (funcall test (funcall key elt)))
+                                   (if-not (not (funcall test 
+                                                         (funcall key elt)))))
+                                 (setq count (1- count))
+                                 new)
+                                (t elt))))))
+      (setq list (cdr list)))
+    (do ()
+        ((null list))
+      (setq splice (cdr (rplacd splice (list (car list)))))
+      (setq list (cdr list)))
+    (cdr result)))
+
+;;; Replace old with new in sequence moving from left to right by incrementer
+;;; on each pass through the loop. Called by all three substitute functions.
+(defun vector-substitute* (pred new sequence incrementer left right length
+                                start end count key test test-not old)
+  (let ((result (make-sequence-like sequence length))
+        (index left))
+    (do ()
+        ((= index start))
+      (aset result index (aref sequence index))
+      (setq index (+ index incrementer)))
+    (do ((elt))
+        ((or (= index end) (= count 0)))
+      (setq elt (aref sequence index))
+      (aset result index 
+            (cond ((case pred
+                     (normal
+                      (if test-not
+                        (not (funcall test-not old (funcall key elt))) ;cfry mod
+                        (funcall test old (funcall key elt)))) ;cfry mod
+                     (if (funcall test (funcall key elt)))
+                     (if-not (not (funcall test (funcall key elt)))))
+                   (setq count (1- count))
+                   new)
+                  (t elt)))
+      (setq index (+ index incrementer)))
+    (do ()
+        ((= index right))
+      (aset result index (aref sequence index))
+      (setq index (+ index incrementer)))
+    result))
+
+;;; Substitute:
+
+(defun substitute (new old sequence &key from-end (test #'eql) test-not
+                       (start 0) count
+                       end (key #'identity))
+  "Return a sequence of the same kind as SEQUENCE with the same elements,
+  except that all elements equal to OLD are replaced with NEW. See manual
+  for details."
+  (setq count (check-count count))
+  (let ((length (length sequence))        )
+    (setq end (check-sequence-bounds sequence start end))
+    (seq-dispatch 
+     sequence
+     (if from-end
+       (nreverse (list-substitute* 'normal new (reverse sequence) (- length end)
+                                   (- length start) count key test test-not old))
+       (list-substitute* 'normal new sequence start end count key test test-not
+                         old))
+     (if from-end
+       (vector-substitute* 'normal new sequence -1 (1- length) -1 length 
+                           (1- end) (1- start) count key test test-not old)
+       (vector-substitute* 'normal new sequence 1 0 length length
+                           start end count key test test-not old)))))
+
+
+(defun substitute-if (new test sequence &key from-end (start 0)
+                          (end (length sequence))
+                          count (key #'identity))
+  "Return a sequence of the same kind as SEQUENCE with the same elements
+  except that all elements satisfying the PRED are replaced with NEW. See
+  manual for details."
+  (substitute new test sequence
+              :from-end from-end
+              :test #'funcall
+              :start start
+              :end end
+              :from-end from-end
+              :count count
+              :key key))
+
+(defun substitute-if-not (new test sequence &key from-end (start 0)
+                              (end (length sequence))
+                              count (key #'identity))
+  "Return a sequence of the same kind as SEQUENCE with the same elements
+  except that all elements not satisfying the PRED are replaced with NEW.
+  See manual for details."
+  (substitute new test sequence
+              :from-end from-end
+              :test-not #'funcall
+              :start start
+              :end end
+              :from-end from-end
+              :count count
+              :key key))
+
+;;; NSubstitute:
+
+(defun nsubstitute (new old sequence &key from-end (test #'eql) test-not 
+                        end 
+                        (count target::target-most-positive-fixnum) (key #'identity) (start 0))
+  "Return a sequence of the same kind as SEQUENCE with the same elements
+  except that all elements equal to OLD are replaced with NEW. The SEQUENCE
+  may be destructively modified. See manual for details."
+  (setq count (check-count count))
+  (let ((incrementer 1)
+	(length (length sequence)))
+    (setq end (check-sequence-bounds sequence start end))
+    (seq-dispatch
+     sequence
+      (if from-end
+        (nreverse (nlist-substitute*
+                   new old (nreverse (the list sequence))
+                   test test-not 
+                   (- length end) 
+                   (- length start)
+                   count key))
+        (nlist-substitute* new old sequence
+                           test test-not start end count key))
+      (progn 
+        (if from-end
+          (psetq start (1- end)
+                 end (1- start)
+                 incrementer -1))
+        (nvector-substitute* new old sequence incrementer
+                             test test-not start end count key)))))
+
+(defun nlist-substitute* (new old sequence test test-not start end count key)
+  (do ((list (nthcdr start sequence) (cdr list))
+       (index start (1+ index)))
+      ((or (and end (= index end)) (null list) (= count 0)) sequence)
+    (when (if test-not
+            (not (funcall test-not  old (funcall key (car list)))) ;cfry mod
+            (funcall test  old (funcall key (car list)))) ;cfry mod
+      (rplaca list new)
+      (setq count (1- count)))))
+
+(defun nvector-substitute* (new old sequence incrementer
+                                test test-not start end count key)
+  (do ((index start (+ index incrementer)))
+      ((or (= index end) (= count 0)) sequence)
+    (when (if test-not
+            (not (funcall test-not  old (funcall key (aref sequence index))))
+            ;above cfry mod. both order of argss to test-not and paren error
+            ; between the funcall key and the funcall test-not
+            (funcall test old (funcall key (aref sequence index)))) ;cfry mod
+      (aset sequence index new)
+      (setq count (1- count)))))
+
+;;; NSubstitute-If:
+
+(defun nsubstitute-if (new test sequence &key from-end (start 0)
+                           end  
+                           (count target::target-most-positive-fixnum) (key #'identity))
+  "Return a sequence of the same kind as SEQUENCE with the same elements
+   except that all elements satisfying the PRED are replaced with NEW. 
+   SEQUENCE may be destructively modified. See manual for details."
+  (nsubstitute new test sequence
+               :from-end from-end
+               :test #'funcall
+               :start start
+               :end end
+               :count count
+               :key key))
+
+
+;;; NSubstitute-If-Not:
+
+(defun nsubstitute-if-not (new test sequence &key from-end (start 0)
+                               end (count target::target-most-positive-fixnum) (key #'identity))
+  "Return a sequence of the same kind as SEQUENCE with the same elements
+   except that all elements not satisfying the TEST are replaced with NEW.
+   SEQUENCE may be destructively modified. See manual for details."
+  (nsubstitute new test sequence
+                 :from-end from-end
+                 :test-not #'funcall
+                 :start start
+                 :end end
+                 :count count
+                 :key key))
+
+
+;;; Position:
+
+(defun list-position/find-1 (eltp item list from-end test test-not start end key &aux hard)
+  ;;if eltp is true, return element, otherwise return position
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not)
+                       (adjust-test-args item test test-not))
+  (setq end (check-sequence-bounds list start end)
+        hard (or test key test-not))
+  (if from-end
+    (if hard
+      (list-position/find-from-end-complex eltp item list start end test test-not key)
+      (list-position/find-from-end-simple eltp item list start end))
+    (if hard
+      (list-position/find-complex eltp item list start end test test-not key)
+      (list-position/find-simple eltp item list start end))))
+
+(defun position (item sequence &key from-end test test-not (start 0) end key)
+  (if sequence
+    (seq-dispatch 
+     sequence
+     (list-position/find-1 nil item sequence from-end test test-not start end key)
+     (vector-position-1 item sequence from-end test test-not start end key))))
+
+;Is it really necessary for these internal functions to take keyword args?
+(defun list-position/find (eltp item list &key from-end test test-not (start 0) end key &aux hard)
+  ;;if eltp is true, return element, otherwise return position
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not)
+                       (adjust-test-args item test test-not))
+  (setq end (check-sequence-bounds list start end)
+        hard (or test key test-not))
+  (if from-end
+    (if hard
+      (list-position/find-from-end-complex eltp item list start end test test-not key)
+      (list-position/find-from-end-simple eltp item list start end))
+    (if hard
+      (list-position/find-complex eltp item list start end test test-not key)
+      (list-position/find-simple eltp item list start end))))
+
+;;; make these things positional
+
+
+
+;;; add a simple-vector case
+
+(defun vector-position-1 (item vector from-end test test-not start end key
+                        &aux (inc (if from-end -1 1)) pos)
+  (setq end (check-sequence-bounds vector start end))
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not) (adjust-test-args item test test-not))
+  (if from-end (psetq start (%i- end 1) end (%i- start 1)))
+  (setq pos start)
+  (if (simple-vector-p vector)
+    (locally (declare (type simple-vector vector)
+                      (optimize (speed 3) (safety 0)))
+      (loop
+        (if (eq pos end) (return))
+        (if (matchp2 item (aref vector pos) test test-not key) (return pos))
+        (setq pos (%i+ pos inc))))
+    (loop
+      (if (eq pos end) (return))
+      (if (matchp2 item (aref vector pos) test test-not key) (return pos))
+      (setq pos (%i+ pos inc)))))
+
+(defun list-position/find-simple (eltp item list start end &aux (pos 0))
+  (loop
+    (if (or (eq pos start) (null list))
+      (return)
+      (setq list (cdr list) pos (%i+ pos 1))))
+  (loop
+    (if (and list (neq end pos))
+      (if (eq item (car list))
+        (return (if eltp item pos))
+        (setq list (%cdr list) pos (%i+ pos 1)))
+      (return))))
+
+(defun list-position/find-complex (eltp item list start end test test-not key &aux (pos 0))
+  (loop
+    (if (or (eq pos start) (null list))
+      (return)
+      (setq list (cdr list) pos (%i+ pos 1))))
+  (loop
+    (if (and list (neq end pos))
+      (progn
+        (if (matchp2 item (car list) test test-not key)
+          (return (if eltp (%car list) pos))
+          (setq list (%cdr list) pos (%i+ pos 1))))
+      (return))))
+
+(defun list-position/find-from-end-simple (eltp item list start end &aux (pos 0) ret)
+  (loop
+    (if (or (eq pos start) (null list))
+      (return)
+      (setq list (cdr list) pos (%i+ pos 1))))
+  (loop
+    (if (and list (neq end pos))
+      (progn
+        (if (eq item (car list)) (setq ret pos))
+        (setq list (%cdr list) pos (%i+ pos 1)))
+      (return (if eltp (if ret item) ret)))))
+
+(defun list-position/find-from-end-complex (eltp item list start end test test-not key 
+                                            &aux (pos 0) ret val)
+  (loop
+    (if (or (eq pos start) (null list))
+      (return)
+      (setq list (cdr list) pos (%i+ pos 1))))
+  (loop
+    (if (and list (neq end pos))
+      (progn
+        (if (matchp2 item (setq val (car list)) test test-not key)
+          (setq ret (if eltp val pos)))
+        (setq list (%cdr list) pos (%i+ pos 1)))
+      (return ret))))
+
+(defun vector-position (item vector &key from-end test test-not (start 0) end key
+                        &aux (inc (if from-end -1 1)) pos)
+  (setq end (check-sequence-bounds vector start end))
+  (setq key (adjust-key key))
+  (multiple-value-setq (test test-not) (adjust-test-args item test test-not))
+  (if from-end (psetq start (%i- end 1) end (%i- start 1)))
+  (setq pos start)
+  (loop
+    (if (eq pos end) (return))
+    (if (matchp2 item (aref vector pos) test test-not key) (return pos))
+    (setq pos (%i+ pos inc))))
+
+;;; Position-if:
+
+(defun position-if (test sequence &key from-end (start 0) end key)
+  (position test sequence
+            :test #'funcall
+            :from-end from-end
+            :start start
+            :end end
+            :key key))
+
+
+;;; Position-if-not:
+
+(defun position-if-not (test sequence &key from-end (start 0) end key)
+  (position test sequence
+            :test-not #'funcall
+            :from-end from-end
+            :start start
+            :end end
+            :key key))
+
+;;; Count:
+
+(defun vector-count-from-start (test item sequence start end key)
+  (declare (fixnum start end))
+  (do* ((index start (1+ index))
+        (count 0))
+       ((= index end) count)
+    (declare (fixnum index count))
+    (when (funcall test item  (funcall key (aref sequence index)))
+      (incf count))))
+
+(defun vector-count-from-end (test item sequence start end key)
+  (declare (fixnum start end))
+  (do* ((index (1- end) (1- index))
+        (count 0)
+        (limit (1- start)))
+       ((= index limit) count)
+    (declare (fixnum index count limit))
+    (when (funcall test item (funcall key (aref sequence index)))
+      (incf count))))
+
+(defun vector-count-not-p-from-start (test-not item sequence start end key)
+  (declare (fixnum start end))
+  (do* ((index start (1+ index))
+        (count 0))
+       ((= index end) count)
+    (declare (fixnum index count))
+    (unless (funcall test-not item (funcall key (aref sequence index)))
+      (incf count))))
+
+(defun vector-count-not-p-from-end (test-not item sequence start end key)
+  (declare (fixnum start end))
+  (do* ((index (1- end) (1- index))
+        (count 0)
+        (limit (1- start)))
+       ((= index limit) count)
+    (declare (fixnum index count limit))
+    (unless (funcall test-not item (funcall key (aref sequence index)))
+      (incf count))))
+
+(defun list-count-from-start (test item sequence start end key)
+  (declare (fixnum start end) (list sequence))
+  (do* ((seq (nthcdr start sequence) (cdr seq))
+        (element (car seq) (car seq))
+        (index start (1+ index))
+        (count 0))
+       ((or (= index end) (null seq)) count)
+    (declare (fixnum index count) (list seq))
+    (when (funcall test item (funcall key element))
+      (incf count))))
+
+(defun list-count-from-end (test item sequence start end key)
+  (declare (fixnum start end))
+  (let* ((len (length sequence)))
+    (declare (fixnum len))
+    (list-count-from-start test item (reverse sequence) (- len end) (- len start) key)))
+
+(defun list-count-not-p-from-start (test-not item sequence start end key)
+  (declare (fixnum start end) (list sequence))
+  (do* ((seq (nthcdr start sequence) (cdr seq))
+        (element (car seq) (car seq))
+        (index start (1+ index))
+        (count 0))
+       ((or (= index end) (null seq)) count)
+    (declare (fixnum index count) (list seq))
+    (unless (funcall test-not item  (funcall key element))
+      (incf count))))
+
+(defun list-count-not-p-from-end (test-not item sequence start end key)
+  (declare (fixnum start end))
+  (let* ((len (length sequence)))
+    (declare (fixnum len))
+    (list-count-not-p-from-start test-not item (reverse sequence) (- len end) (- len start) key)))
+
+(defun count (item sequence &key from-end (test #'eql testp)
+                   (test-not nil notp) (start 0) end key)
+  "Return the number of elements in SEQUENCE satisfying a test with ITEM,
+   which defaults to EQL."
+  (if (and testp notp)
+    (test-not-error test test-not))
+  (unless key
+    (setq key #'identity))
+  (setq end (check-sequence-bounds sequence start end))
+  (if sequence
+    (seq-dispatch
+     sequence
+     (if notp
+       (if from-end
+         (list-count-not-p-from-end test-not item  sequence start end key)
+         (list-count-not-p-from-start test-not item sequence start end key))
+       (if from-end
+         (list-count-from-end test item sequence start end key)
+         (list-count-from-start test item sequence start end key)))
+     (if notp
+       (if from-end
+         (vector-count-not-p-from-end test-not item sequence start end key)
+         (vector-count-not-p-from-start test-not item sequence start end key))
+       (if from-end
+         (vector-count-from-end test item sequence start end key)
+         (vector-count-from-start test item sequence start end key))))
+    0))
+
+
+;;; Count-if:
+
+(defun count-if (test sequence &key from-end (start 0) end key)
+  "Return the number of elements in SEQUENCE satisfying PRED(el)."
+  (count test sequence
+         :test #'funcall
+         :from-end from-end
+         :start start
+         :end end
+         :key key))
+
+;;; Count-if-not:
+
+(defun count-if-not (test sequence &key from-end (start 0) end key)
+  "Return the number of elements in SEQUENCE not satisfying TEST(el)."
+  (count test sequence
+         :test-not #'funcall
+         :from-end from-end
+         :start start
+         :end end
+         :key key))
+
+
+;;; Find:
+
+(defun find (item sequence &key from-end test test-not (start 0) end key &aux temp)
+  (if sequence
+    (seq-dispatch
+     sequence
+     (list-position/find-1 t item sequence from-end test test-not start end key)
+     (if (setq temp (vector-position-1 item sequence from-end test test-not start end key))
+       (aref sequence temp)))))
+
+(defun find-if (test sequence &key from-end (start 0) end key)
+  (find test sequence
+        :test #'funcall
+        :from-end from-end
+        :start start
+        :end end
+        :key key))
+
+(defun find-if-not (test sequence &key from-end (start 0) end key)
+  (find test sequence
+        :test-not #'funcall
+        :from-end from-end
+        :start start
+        :end end
+        :key key))
+
+
+;;; Mismatch:
+
+(defun mismatch (seq1 seq2 &key (from-end nil)
+                                  (test #'eql)
+                                  (test-not nil)
+                                  (key #'identity)
+                                  (start1 0)
+                                  (start2 0)
+                                  (end1 nil)
+                                  (end2 nil)
+                             &aux (length1 (length seq1))
+                                  (length2 (length seq2))
+                                  (vectorp1 (vectorp seq1))
+                                  (vectorp2 (vectorp seq2)))
+  "The specified subsequences of SEQUENCE1 and SEQUENCE2 are compared
+   element-wise. If they are of equal length and match in every element, the
+   result is NIL. Otherwise, the result is a non-negative integer, the index
+   within SEQUENCE1 of the leftmost position at which they fail to match; or,
+   if one is shorter than and a matching prefix of the other, the index within
+   SEQUENCE1 beyond the last position tested is returned. If a non-NIL
+   :FROM-END argument is given, then one plus the index of the rightmost
+   position in which the sequences differ is returned."
+  ;seq type-checking is done by length
+  ;start/end type-cheking is done by <= (below)
+  ;test/key type-checking is done by funcall
+  ;no check for both test and test-not
+  (or end1 (setq end1 length1))
+  (or end2 (setq end2 length2))
+  (unless (and (<= start1 end1 length1)
+               (<= start2 end2 length2))
+    (error "Sequence arg out of range"))
+  (unless vectorp1
+    (setq seq1 (nthcdr start1 seq1))
+    (if from-end
+      (do* ((s1 ())
+            (i start1 (1+ i)))
+           ((= i end1) (setq seq1 s1))
+        (push (pop seq1) s1))))
+  (unless vectorp2
+    (setq seq2 (nthcdr start2 seq2))
+    (if from-end
+      (do* ((s2 ())
+            (i start2 (1+ i)))
+           ((= i end2) (setq seq2 s2))
+        (push (pop seq2) s2))))
+  (when test-not (setq test test-not))
+  (if from-end
+      ;from-end
+      (let* ((count1 end1)
+             (count2 end2)
+             (elt1)
+             (elt2))
+        (loop
+          (if (or (eq count1 start1)
+                  (eq count2 start2))
+              (return-from mismatch
+                           (if (and (eq count1 start1)
+                                    (eq count2 start2))
+                               nil
+                               count1)))
+          
+          (setq count1 (%i- count1 1)
+                count2 (%i- count2 1))
+
+          (setq elt1 (funcall key (if vectorp1
+                                      (aref seq1 count1)
+                                      (prog1
+                                        (%car seq1)
+                                        (setq seq1 (%cdr seq1)))))
+                elt2 (funcall key (if vectorp2
+                                      (aref seq2 count2)
+                                      (prog1
+                                        (%car seq2)
+                                        (setq seq2 (%cdr seq2))))))
+
+          (when (if test-not
+                    (funcall test elt1 elt2)
+                    (not (funcall test elt1 elt2)))
+            (return-from mismatch (%i+ count1 1)))))
+      ;from-start
+      (let* ((count1 start1)
+             (count2 start2)
+             (elt1)
+             (elt2))
+        (loop
+          (if (or (eq count1 end1)
+                  (eq count2 end2))
+              (return-from mismatch
+                           (if (and (eq count1 end1)
+                                    (eq count2 end2))
+                               nil
+                               count1)))
+          (setq elt1 (funcall key (if vectorp1
+                                      (aref seq1 count1)
+                                      (prog1
+                                        (%car seq1)
+                                        (setq seq1 (%cdr seq1)))))
+                elt2 (funcall key (if vectorp2
+                                      (aref seq2 count2)
+                                      (prog1
+                                        (%car seq2)
+                                        (setq seq2 (%cdr seq2))))))
+          
+          (when (if test-not
+                    (funcall test elt1 elt2)
+                    (not (funcall test elt1 elt2)))
+            (return-from mismatch count1)) 
+          (setq count1 (%i+ count1 1)
+                count2 (%i+ count2 1))
+          
+          ))))
+
+
+;;; Search comparison functions:
+
+(eval-when (:execute :compile-toplevel)
+  
+  ;;; Compare two elements
+  
+  (defmacro xcompare-elements (elt1 elt2)
+    `(if (not key)
+       (if test-not
+         (not (funcall test-not ,elt1 ,elt2))
+         (funcall test ,elt1 ,elt2))
+       (let* ((e1 (funcall key ,elt1))
+              (e2 (funcall key ,elt2)))
+         (if test-not
+           (not (funcall test-not  e1 e2))
+           (funcall test e1 e2)))))  
+  
+  (defmacro vector-vector-search (sub main)
+    `(let ((first-elt (aref ,sub start1))
+           (last-one nil))
+       (do* ((index2 start2 (1+ index2))
+             (terminus (%i- end2 (%i- end1 start1))))
+            ((> index2 terminus))
+         (declare (fixnum index2 terminus))
+         (if (xcompare-elements first-elt (aref ,main index2))
+           (if (do* ((subi1 (1+ start1)(1+ subi1))
+                     (subi2 (1+ index2) (1+ subi2)))
+                    ((eq subi1 end1) t)
+                 (declare (fixnum subi1 subi2))
+                 (if (not (xcompare-elements (aref ,sub subi1) (aref ,main subi2)))
+                   (return nil)))
+             (if from-end
+               (setq last-one index2)
+               (return-from search index2)))))
+       last-one))
+
+  (defmacro list-list-search (sub main)
+    `(let* ((sub-sub (nthcdr start1 ,sub))
+            (first-elt (%car sub-sub))
+            (last-one nil))
+       (do* ((index2 start2 (1+ index2))
+             (sub-main (nthcdr start2 ,main) (%cdr sub-main))
+             (terminus (%i- end2 (%i- end1 start1))))
+            ((> index2 terminus))
+         (declare (fixnum index2 terminus))
+         (if (xcompare-elements first-elt (car sub-main))
+           (if (do* ((ss (%cdr sub-sub) (%cdr ss))
+		     (pos (1+ start1) (1+ pos))
+                     (sm (%cdr sub-main) (cdr sm)))
+                    ((or (null ss) (= pos end1))  t)
+		 (declare (fixnum pos))
+                 (if (not (xcompare-elements (%car ss) (%car sm)))
+                     (return nil)))
+              (if from-end
+               (setq last-one index2)
+               (return-from search index2)))))
+       last-one))
+  
+  (defmacro list-vector-search (sub main)
+    `(let* ((sub-sub (nthcdr start1 ,sub))
+              (first-elt (%car sub-sub))
+              (last-one nil))
+         (do* ((index2 start2 (1+ index2))
+               (terminus (%i- end2 (%i- end1 start1))))
+              ((> index2 terminus))
+           (declare (fixnum index2 terminus))
+           (if (xcompare-elements first-elt (aref ,main index2))
+             (if (do* ((ss (%cdr sub-sub) (%cdr ss))
+		       (pos (1+ start1) (1+ pos))
+                       (subi2 (1+ index2) (1+ subi2)))
+                      ((or (null ss) (= pos end1))  t)
+                   (declare (fixnum subi2 pos))
+                   (if (not (xcompare-elements (%car ss) (aref ,main subi2)))
+                     (return nil)))
+               (if from-end
+                 (setq last-one index2)
+                 (return-from search index2)))))
+         last-one))
+
+  (defmacro vector-list-search (sub main)
+    `(let ((first-elt (aref ,sub start1))
+           (last-one nil))
+       (do* ((index2 start2 (1+ index2))
+             (sub-main (nthcdr start2 ,main) (%cdr sub-main))
+             (terminus (%i- end2 (%i- end1 start1))))
+            ((> index2 terminus))
+         (declare (fixnum index2 terminus))
+         (if (xcompare-elements first-elt (car sub-main))
+           (if (do* ((subi1 (1+ start1)(1+ subi1))
+                     (sm (%cdr sub-main) (cdr sm)))
+                    ((eq subi1 end1) t)
+                 (declare (fixnum subi1))
+                 (if (not (xcompare-elements (aref ,sub subi1) (car sm)))
+                   (return nil)))
+             (if from-end
+               (setq last-one index2)
+               (return-from search index2)))))
+       last-one))
+                 
+    
+  )
+
+
+
+(defun search (sequence1 sequence2 &key from-end (test #'eql) test-not 
+                          (start1 0) end1 (start2 0) end2 (key #'identity))
+  (setq end1 (check-sequence-bounds sequence1 start1 end1))
+  (setq end2 (check-sequence-bounds sequence2 start2 end2))
+  (setq key (adjust-key key))
+  (locally (declare (fixnum start1 end1 start2 end2))
+    (if (eq 0 (%i- end1 start1))(if from-end end2 start2)
+    (seq-dispatch sequence1
+                  (seq-dispatch sequence2
+                                (list-list-search sequence1 sequence2)
+                                (list-vector-search sequence1 sequence2))
+                  (seq-dispatch sequence2
+                                (vector-list-search sequence1 sequence2)
+                                (vector-vector-search sequence1 sequence2))))))
+
+(defun make-string (size &key (initial-element () initial-element-p) (element-type 'character element-type-p))
+  "Given a character count and an optional fill character, makes and returns
+   a new string COUNT long filled with the fill character."
+  (declare (optimize (speed 1) (safety 1)))
+  (when (and initial-element-p (not (typep initial-element 'character)))
+    (report-bad-arg initial-element 'character))
+  (when (and element-type-p
+             (not (or (member element-type '(character base-char standard-char))
+                      (subtypep element-type 'character))))
+    (error ":element-type ~S is not a subtype of CHARACTER" element-type))
+  (if initial-element-p
+      (make-string size :element-type 'base-char :initial-element initial-element)
+      (make-string size :element-type 'base-char)))
Index: /branches/new-random/lib/setf-runtime.lisp
===================================================================
--- /branches/new-random/lib/setf-runtime.lisp	(revision 13309)
+++ /branches/new-random/lib/setf-runtime.lisp	(revision 13309)
@@ -0,0 +1,134 @@
+; -*- Mode: Lisp; Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;
+; setf-runtime.lisp - runtime support for setf expressions
+
+(in-package "CCL")
+
+(defun set-cadr (list new-value)
+  (set-car (cdr list) new-value))
+
+(defun set-cdar (list new-value)
+  (set-cdr (car list) new-value))
+
+(defun set-caar (list new-value)
+  (set-car (car list) new-value))
+
+(defun set-cddr (list new-value)
+  (set-cdr (cdr list) new-value))
+
+(defun %set-nthcdr (index list new-value)
+  "If INDEX is 0, just return NEW-VALUE."
+  (if (not (zerop index))
+    (rplacd (nthcdr (1- index) list)
+            new-value))
+  new-value)
+
+(defun set-fifth (list new-value)
+  (set-car (cddddr list) new-value))
+
+(defun set-sixth (list new-value)
+  (set-car (cdr (cddddr list)) new-value))
+
+(defun set-seventh (list new-value)
+  (set-car (cddr (cddddr list)) new-value))
+
+(defun set-eighth (list new-value)
+  (set-car (cdddr (cddddr list)) new-value))
+
+(defun set-ninth (list new-value)
+  (set-car (cddddr (cddddr list)) new-value))
+
+(defun set-tenth (list new-value)
+  (set-car (cdr (cddddr (cddddr list))) new-value))
+
+(defun set-caaar (list new-value)
+  (set-car (caar list) new-value))
+
+(defun set-caadr (list new-value)
+  (set-car (cadr list) new-value))
+
+(defun set-cadar (list new-value)
+  (set-car (cdar list) new-value))
+
+(defun set-caddr (list new-value)
+  (set-car (cddr list) new-value))
+
+(defun set-cdaar (list new-value)
+  (set-cdr (caar list) new-value))
+
+(defun set-cdadr (list new-value)
+  (set-cdr (cadr list) new-value))
+
+(defun set-cddar (list new-value)
+  (set-cdr (cdar list) new-value))
+
+(defun set-cdddr (list new-value)
+  (set-cdr (cddr list) new-value))
+
+(defun set-caaaar (list new-value)
+  (set-car (caaar list) new-value))
+
+(defun set-caaadr (list new-value)
+  (set-car (caadr list) new-value))
+
+(defun set-caadar (list new-value)
+  (set-car (cadar list) new-value))
+
+(defun set-caaddr (list new-value)
+  (set-car (caddr list) new-value))
+
+(defun set-cadaar (list new-value)
+  (set-car (cdaar list) new-value))
+
+(defun set-cadadr (list new-value)
+  (set-car (cdadr list) new-value))
+
+(defun set-caddar (list new-value)
+  (set-car (cddar list) new-value))
+
+(defun set-cadddr (list new-value)
+  (set-car (cdddr list) new-value))
+
+(defun set-cdaaar (list new-value)
+  (set-cdr (caaar list) new-value))
+
+(defun set-cdaadr (list new-value)
+  (set-cdr (caadr list) new-value))
+
+(defun set-cdadar (list new-value)
+  (set-cdr (cadar list) new-value))
+
+(defun set-cdaddr (list new-value)
+  (set-cdr (caddr list) new-value))
+
+(defun set-cddaar (list new-value)
+  (set-cdr (cdaar list) new-value))
+
+(defun set-cddadr (list new-value)
+  (set-cdr (cdadr list) new-value))
+
+(defun set-cdddar (list new-value)
+  (set-cdr (cddar list) new-value))
+
+(defun set-cddddr (list new-value)
+  (set-cdr (cdddr list) new-value))
+
+
+
+; End of setf-runtime.lisp
Index: /branches/new-random/lib/setf.lisp
===================================================================
--- /branches/new-random/lib/setf.lisp	(revision 13309)
+++ /branches/new-random/lib/setf.lisp	(revision 13309)
@@ -0,0 +1,908 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;Bootstrapping.
+(defvar %setf-methods% (let ((a (make-hash-table :test #'eq)))
+                         (do-all-symbols (s)
+                           (let ((f (get s 'bootstrapping-setf-method)))
+                             (when f
+                               (setf (gethash s a) f)
+                               (remprop s 'bootstrapping-setf-method))))
+                         a))
+(defun %setf-method (name)
+  (gethash name %setf-methods%))
+
+(defun store-setf-method (name fn &optional doc)
+  (puthash name %setf-methods% fn)
+  (let ((type-and-refinfo (and #-bccl (boundp '%structure-refs%)
+                               (gethash name %structure-refs%))))
+    (typecase type-and-refinfo
+      (fixnum
+       (puthash name %structure-refs% (%ilogior2 (%ilsl $struct-r/o 1)
+                                                 type-and-refinfo)))
+      (cons
+       (setf (%cdr type-and-refinfo) (%ilogior2 (%ilsl $struct-r/o 1)
+                                                (%cdr type-and-refinfo))))
+      (otherwise nil)))
+  (set-documentation name 'setf doc) ;clears it if doc = nil.
+  name)
+
+
+;;; Note: The expansions for SETF and friends create needless LET-bindings of 
+;;; argument values when using get-setf-method.
+;;; That's why SETF no longer uses get-setf-method.  If you change anything
+;;; here, be sure to make the corresponding change in SETF.
+
+(defun get-setf-expansion (form &optional env)
+  "Return five values needed by the SETF machinery: a list of temporary
+   variables, a list of values with which to fill them, a list of temporaries
+   for the new values, the setting function, and the accessing function."
+  ;This isn't actually used by setf, but it has to be compatible.
+  (get-setf-expansion-aux form env t))
+
+(defun get-setf-expansion-aux (form environment multiple-store-vars-p)
+  (let* ((temp nil) 
+         (accessor nil))
+    (if (atom form)
+      (progn
+        (unless (symbolp form) (signal-program-error $XNotSym form))
+        (multiple-value-bind (symbol-macro-expansion expanded)
+            (macroexpand-1 form environment)
+          (if expanded
+            (get-setf-expansion-aux symbol-macro-expansion environment
+                                    multiple-store-vars-p)
+            (let ((new-var (gensym)))
+              (values nil nil (list new-var) `(setq ,form ,new-var) form)))))
+      (multiple-value-bind (ftype local-p)
+                           (function-information (setq accessor (car form)) environment)
+        (if local-p
+          (if (eq ftype :function)
+            ;Local function or macro, so don't use global setf definitions.
+            (default-setf-method form)
+            (get-setf-expansion-aux (macroexpand-1 form environment) environment multiple-store-vars-p))
+          (cond
+           ((setq temp (gethash accessor %setf-methods%))
+            (if (symbolp temp)
+              (let ((new-var (gensym))
+                    (args nil)
+                    (vars nil)
+                    (vals nil))
+                (dolist (x (cdr form))
+                  ;; Rebinding defeats optimizations, so avoid it if can.
+                  (if (constantp x environment)
+                    (push x args)
+                    (let ((var (gensym)))
+                      (push var vars)
+                      (push var args)
+                      (push x vals))))
+                (setq args (nreverse args))
+                (values (nreverse vars) 
+                        (nreverse vals) 
+                        (list new-var)
+                        `(,temp ,@args ,new-var)
+                        `(,accessor ,@args)))
+              (multiple-value-bind (temps values storevars storeform accessform)
+                                   (funcall temp form environment)
+                (when (and (not multiple-store-vars-p) (not (= (length storevars) 1)))
+                  (signal-program-error "Multiple store variables not expected in setf expansion of ~S" form))
+                (values temps values storevars storeform accessform))))
+           ((and (type-and-refinfo-p (setq temp (or (environment-structref-info accessor environment)
+                                                    (and #-bccl (boundp '%structure-refs%)
+                                                         (gethash accessor %structure-refs%)))))
+                 (not (refinfo-r/o (if (consp temp) (%cdr temp) temp))))
+            (if (consp temp)
+              (let ((type (%car temp)))
+                (multiple-value-bind
+                  (temps values storevars storeform accessform)
+                  (get-setf-method (defstruct-ref-transform (%cdr temp) (%cdr form) environment) environment)
+                  (values temps values storevars
+                          (let ((storevar (first storevars)))
+                            `(the ,type
+                                  (let ((,storevar (require-type ,storevar ',type)))
+                                    ,storeform)))
+                          `(the ,type ,accessform))))
+              (get-setf-method (defstruct-ref-transform temp (%cdr form) environment) environment)))
+	   (t
+	    (multiple-value-bind (res win)
+				 (macroexpand-1 form environment)
+	      (if win
+                (get-setf-expansion-aux res environment multiple-store-vars-p)
+                (default-setf-method form))))))))))
+
+(defun default-setf-method (form)
+  (let ((new-value (gensym))
+        (temp-vars ())
+        (temp-args ())
+        (temp-vals ()))
+    (dolist (val (cdr form))
+      (if (fixnump val)
+        (push val temp-args)
+        (let ((var (gensym)))
+          (push var temp-vars)
+          (push val temp-vals)
+          (push var temp-args))))
+    (setq temp-vars (nreverse temp-vars)
+          temp-args (nreverse temp-args)
+          temp-vals (nreverse temp-vals))
+    (values temp-vars
+	    temp-vals
+	    (list new-value)
+	    `(funcall #'(setf ,(car form)) ,new-value ,@temp-args)
+	    `(,(car form) ,@temp-args))))
+
+;;; The inverse for a generalized-variable reference function is stored in
+;;; one of two ways:
+;;;
+;;; A SETF-INVERSE property corresponds to the short form of DEFSETF.  It is
+;;; the name of a function takes the same args as the reference form, plus a
+;;; new-value arg at the end.
+;;;
+;;; A SETF-METHOD-EXPANDER property is created by the long form of DEFSETF or
+;;; by DEFINE-SETF-METHOD.  It is a function that is called on the reference
+;;; form and that produces five values: a list of temporary variables, a list
+;;; of value forms, a list of the single store-value form, a storing function,
+;;; and an accessing function.
+
+(eval-when (eval compile)
+  (require 'defstruct-macros))
+  
+(defmacro set-get (symbol indicator value &optional (value1 () default-p))
+  (if default-p
+    `(put ,symbol ,indicator (progn ,value ,value1))
+    `(put ,symbol ,indicator ,value)))
+
+; (defsetf get set-get)
+(store-setf-method 'get 'SET-GET)
+
+; does this wrap a named block around the body yet ?
+(defmacro define-setf-expander (access-fn lambda-list &body body)
+  "Syntax like DEFMACRO, but creates a setf expander function. The body
+  of the definition must be a form that returns five appropriate values."
+  (unless (symbolp access-fn)
+    (signal-program-error $xnotsym access-fn))
+  (multiple-value-bind (lambda-form doc)
+                       (parse-macro-1 access-fn lambda-list body)
+    `(eval-when (load compile eval)
+       (record-source-file ',access-fn 'setf-expander)
+       (store-setf-method ',access-fn
+                          (nfunction ,access-fn ,lambda-form)
+                          ,@(when doc (list doc))))))
+
+(defun rename-lambda-vars (lambda-list)
+  (let* ((vars nil)
+         (temps nil)
+         (new-lambda nil)
+         (state nil))
+    (flet ((temp-symbol (s) (make-symbol (symbol-name s))))
+      (declare (inline temp-symbol))
+      (dolist (item lambda-list)
+        (if (memq item lambda-list-keywords)
+          (setq state item item (list 'quote item))
+          (if (atom item)
+            (progn
+              (push item vars))
+            (locally (declare (type cons item))
+              (when (consp (cddr item))
+                (push (caddr item) vars))
+              (if (and (eq state '&key) (consp (car item)))
+                (progn
+                  (push (cadar item) vars)
+                  (setq item `(list (list ,(list 'quote (caar item)) ,(cadar item)) ,@(cdr item))))
+                (progn 
+                  (push (car item) vars)
+                  (setq item `(list ,(car item) ,@(cdr item))))))))
+        (push item new-lambda))
+      (setq temps (mapcar #'temp-symbol vars))
+      (values `(list ,@(nreverse new-lambda)) (nreverse temps) (nreverse vars)))))
+
+(defmacro defsetf (access-fn &rest rest &environment env)
+  "Associates a SETF update function or macro with the specified access
+  function or macro. The format is complex. See the manual for details."
+  (unless (symbolp access-fn) (signal-program-error $xnotsym access-fn))
+  (if (non-nil-symbol-p (%car rest))
+    `(eval-when (:compile-toplevel :load-toplevel :execute)
+       (store-setf-method
+        ',access-fn
+        ',(%car rest)
+        ,@(%cdr rest)))
+    (destructuring-bind (lambda-list (store-var &rest mv-store-vars) &body body)
+        rest
+      (unless (verify-lambda-list lambda-list)
+        (signal-program-error $XBadLambdaList lambda-list))
+      (let* ((store-vars (cons store-var mv-store-vars)))
+        (multiple-value-bind (lambda-list lambda-temps lambda-vars)
+                             (rename-lambda-vars lambda-list)
+          (multiple-value-bind (body decls doc)
+                               (parse-body body env t)
+            (setq body `((block ,access-fn ,@body)))
+            (let* ((args (gensym))
+                   (dummies (gensym))
+                   (newval-vars (gensym))
+                   (new-access-form (gensym))
+                   (access-form (gensym))
+                   (environment (gensym)))
+              `(eval-when (:compile-toplevel :load-toplevel :execute)
+                 (record-source-file ',access-fn 'setf-expander)
+                 (store-setf-method 
+                  ',access-fn
+                  #'(lambda (,access-form ,environment)
+                      (declare (ignore ,environment))
+                      (do* ((,args (cdr ,access-form) (cdr ,args))
+                            (,dummies nil (cons (gensym) ,dummies))
+                            (,newval-vars (mapcar #'(lambda (v) (declare (ignore v)) (gensym)) ',store-vars))
+                            (,new-access-form nil))
+                           ((atom ,args)
+                            (setq ,new-access-form 
+                                  (cons (car ,access-form) ,dummies))
+                            (destructuring-bind ,(append lambda-vars store-vars )
+                                                `,(append ',lambda-temps ,newval-vars)
+                              ,@decls
+                              (values
+                               ,dummies
+                               (cdr ,access-form)
+                               ,newval-vars
+                               `((lambda ,,lambda-list ,,@body)
+                                 ,@,dummies)
+                               ,new-access-form))))))
+                 ,@(if doc (list doc))
+                 ',access-fn))))))))
+  
+(defmacro define-modify-macro (name lambda-list function &optional doc-string)
+  "Creates a new read-modify-write macro like PUSH or INCF."
+  (let ((other-args nil)
+        (rest-arg nil)
+        (env (gensym))
+        (reference (gensym)))
+    
+    ;; Parse out the variable names and rest arg from the lambda list.
+    (do ((ll lambda-list (cdr ll))
+         (arg nil))
+        ((null ll))
+      (setq arg (car ll))
+      (cond ((eq arg '&optional))
+            ((eq arg '&rest)
+             (if (symbolp (cadr ll))
+               (setq rest-arg (cadr ll))
+               (error "Non-symbol &rest arg in definition of ~S." name))
+             (if (null (cddr ll))
+               (return nil)
+               (error "Illegal stuff after &rest arg in Define-Modify-Macro.")))
+            ((memq arg '(&key &allow-other-keys &aux))
+             (error "~S not allowed in Define-Modify-Macro lambda list." arg))
+            ((symbolp arg)
+             (push arg other-args))
+            ((and (listp arg) (symbolp (car arg)))
+             (push (car arg) other-args))
+            (t (error "Illegal stuff in lambda list of Define-Modify-Macro."))))
+    (setq other-args (nreverse other-args))
+      `(defmacro ,name (,reference ,@lambda-list &environment ,env)
+         ,doc-string
+         (multiple-value-bind (dummies vals newval setter getter)
+                                (get-setf-method ,reference ,env)
+             (do ((d dummies (cdr d))
+                  (v vals (cdr v))
+                  (let-list nil (cons (list (car d) (car v)) let-list)))
+                 ((null d)
+                  (push 
+                   (list (car newval)
+                         ,(if rest-arg
+                            `(list* ',function getter ,@other-args ,rest-arg)
+                            `(list ',function getter ,@other-args)))
+                   let-list)
+                  `(let* ,(nreverse let-list)
+                     ,setter)))))))
+
+(defmacro incf (place &optional (delta 1) &environment env)
+  "The first argument is some location holding a number.  This number is
+incremented by the second argument, DELTA, which defaults to 1."
+  (if (and (symbolp (setq place (%symbol-macroexpand place env)))
+           (or (constantp delta)
+               (and (symbolp delta)
+                    (not (nth-value 1 (%symbol-macroexpand delta env))))))
+    `(setq ,place (+ ,place ,delta))
+    (multiple-value-bind (dummies vals newval setter getter)
+        (get-setf-method place env)
+      (let ((d (gensym))
+            ;; Doesn't propagate inferred types, but better than nothing.
+            (d-type (cond ((constantp delta) (type-of delta))
+                          ((and (consp delta) (eq (car delta) 'the)) (cadr delta))
+                          (t t)))
+            (v-type (if (and (consp place) (eq (car place) 'the)) (cadr place) t)))
+        `(let* (,@(mapcar #'list dummies vals)
+                (,d ,delta)
+                (,(car newval) (+ ,getter ,d)))
+           (declare (type ,d-type ,d) (type ,v-type ,(car newval)))
+           ,setter)))))
+
+(defmacro decf (place &optional (delta 1) &environment env)
+  "The first argument is some location holding a number.  This number is
+decremented by the second argument, DELTA, which defaults to 1."
+  (if (and (symbolp (setq place (%symbol-macroexpand place env)))
+           (or (constantp delta)
+               (and (symbolp delta)
+                    (not (nth-value 1 (%symbol-macroexpand delta env))))))
+    `(setq ,place (- ,place ,delta))
+    (multiple-value-bind (dummies vals newval setter getter)
+        (get-setf-method place env)
+      (let* ((d (gensym))
+             ;; Doesn't propagate inferred types, but better than nothing.
+             (d-type (cond ((constantp delta) (type-of delta))
+                           ((and (consp delta) (eq (car delta) 'the)) (cadr delta))
+                           (t t)))
+             (v-type (if (and (consp place) (eq (car place) 'the)) (cadr place) t)))
+        `(let* (,@(mapcar #'list dummies vals)
+                (,d ,delta)
+                (,(car newval) (- ,getter ,d)))
+           (declare (type ,d-type ,d) (type ,v-type ,(car newval)))
+           ,setter)))))
+  
+(defmacro psetf (&whole call &rest pairs &environment env)  ;same structure as psetq
+  "This is to SETF as PSETQ is to SETQ. Args are alternating place
+  expressions and values to go into those places. All of the subforms and
+  values are determined, left to right, and only then are the locations
+  updated. Returns NIL."
+  (when pairs
+    (if (evenp (length pairs))
+      (let* ((places nil)
+             (values nil)
+             (tempsets nil)
+             (the-progn (list 'progn))
+             (place nil)
+             (body the-progn)
+             (valform nil))
+        (loop
+          (setq place (pop pairs) valform (pop pairs))
+          (if (null pairs) (return))
+          (push place places)
+          (push valform values)
+          (multiple-value-bind (temps vals newvals setter getter)
+                               (get-setf-method-multiple-value place env)
+            (push (list temps vals newvals setter getter) tempsets)))
+        (dolist (temp tempsets)
+          (destructuring-bind (temps vals newvals setter getter) temp
+            (declare (ignore getter))
+            (setq body
+                  `(let
+                     ,(let* ((let-list nil))
+                        (dolist (x temps (nreverse let-list))
+                          (push (list x (pop vals)) let-list)))
+                     (multiple-value-bind ,newvals ,(pop values)
+                       ,body)))
+            (push setter (cdr the-progn))))
+        (push `(setf ,place ,valform) (cdr the-progn))
+        `(progn ,body nil))
+      (error "Odd number of args in the call ~S" call))))
+
+;;Simple Setf specializations
+
+
+
+(defsetf cadr set-cadr)
+(defsetf second set-cadr)
+
+
+(defsetf cdar set-cdar)
+
+(defsetf caar set-caar)
+
+(defsetf cddr set-cddr)
+
+(defsetf elt set-elt)
+(defsetf aref aset)
+(defsetf svref svset)
+(defsetf char set-char)
+(defsetf bit %bitset)
+
+(defsetf schar set-schar)
+(defsetf sbit %sbitset)
+(defsetf symbol-value set)
+(defsetf %schar %set-schar)
+
+
+(defsetf symbol-plist set-symbol-plist)
+(defsetf nth %setnth)
+
+(defsetf nthcdr %set-nthcdr)
+
+(defsetf fill-pointer set-fill-pointer)
+
+
+(defsetf subseq (sequence start &optional (end nil)) (new-seq)
+  `(progn (replace ,sequence ,new-seq :start1 ,start :end1 ,end)
+	  ,new-seq))
+
+
+
+(defsetf third set-caddr)
+(defsetf fourth set-cadddr)
+(defsetf fifth set-fifth)
+(defsetf sixth set-sixth)
+(defsetf seventh set-seventh)
+(defsetf eighth set-eighth)
+(defsetf ninth set-ninth)
+(defsetf tenth set-tenth)
+
+
+(defsetf caaar set-caaar)
+(defsetf caadr set-caadr)
+(defsetf cadar set-cadar)
+(defsetf caddr set-caddr)
+(defsetf cdaar set-cdaar)
+(defsetf cdadr set-cdadr)
+(defsetf cddar set-cddar)
+(defsetf cdddr set-cdddr)
+
+
+
+
+(defsetf caaaar set-caaaar)
+(defsetf caaadr set-caaadr)
+(defsetf caadar set-caadar)
+(defsetf caaddr set-caaddr)
+(defsetf cadaar set-cadaar)
+(defsetf cadadr set-cadadr)
+(defsetf caddar set-caddar)
+(defsetf cadddr set-cadddr)
+
+
+(defsetf cdaaar set-cdaaar)
+(defsetf cdaadr set-cdaadr)
+(defsetf cdadar set-cdadar)
+(defsetf cdaddr set-cdaddr)
+(defsetf cddaar set-cddaar)
+(defsetf cddadr set-cddadr)
+(defsetf cdddar set-cdddar)
+(defsetf cddddr set-cddddr)
+
+(defsetf %fixnum-ref %fixnum-set)
+
+(define-setf-method the (typespec expr &environment env)
+  (multiple-value-bind (dummies vals newval setter getter)
+                       (get-setf-method expr env)
+    (let ((store-var (gensym)))
+      (values
+       dummies
+       vals
+       (list store-var)
+       `(let ((,(car newval) ,store-var))
+                         ,setter)
+       `(the ,typespec ,getter)))))
+
+   
+(define-setf-method apply (function &rest args &environment env)
+  (if (and (listp function)
+	   (= (list-length function) 2)
+	   (eq (first function) 'function)
+	   (symbolp (second function)))
+      (setq function (second function))
+      (error
+       "Setf of Apply is only defined for function args of form #'symbol."))
+  (multiple-value-bind (dummies vals newval setter getter)
+		       (get-setf-expansion (cons function args) env)
+    ;; Make sure the place is one that we can handle.
+    ;;Mainly to insure against cases of ldb and mask-field and such creeping in.
+    (let* ((last-arg (car (last args)))
+           (last-val (car (last vals)))
+           (last-dummy (car (last dummies)))
+           (last-getter (car (last getter)))
+           (last2-setter (car (last setter 2)))
+           (last-setter (car (last setter))))
+      (cond ((and (or (and (eq last-arg last-val)
+                           (eq last-getter last-dummy))
+                      (eq last-arg last-getter))
+                  newval
+                  (null (cdr newval))
+                  (eq last-setter (car newval))
+                  (or (and (eq last-arg last-val)
+                           (eq last2-setter last-dummy))
+                      (eq last-arg last2-setter)))
+             ;; (setf (foo ... argn) bar) -> (set-foo ... argn bar)
+             (values dummies vals newval
+                     `(apply+ (function ,(car setter)) ,@(cdr setter))
+                     `(apply (function ,(car getter)) ,@(cdr getter))))
+            ((and (or (and (eq last-arg last-val)
+                           (eq last-getter last-dummy))
+                      (eq last-arg last-getter))
+                  newval
+                  (null (cdr newval))
+                  (eq (car setter) 'funcall)
+                  (eq (third setter) (car newval))
+                  (or (and (eq last-arg last-val)
+                           (eq last-setter last-dummy))
+                      (eq last-arg last-setter)))
+             ;; (setf (foo ... argn) bar) -> (funcall #'(setf foo) bar ... argn)  [with bindings for evaluation order]
+             (values dummies vals newval
+                     `(apply ,@(cdr setter))
+                     `(apply (function ,(car getter)) ,@(cdr getter))))
+            (t (error "Apply of ~S is not understood as a location for Setf."
+                      function))))))
+
+;;These are the supporting functions for the am-style hard-cases of setf.
+(defun assoc-2-lists (list1 list2)
+  "Not CL. Returns an assoc-like list with members taken by associating corresponding
+   elements of each list. uses list instead of cons.
+   Will stop when first list runs out."
+  (do* ((lst1 list1 (cdr lst1))
+        (lst2 list2 (cdr lst2))
+        (result nil))
+       ((null lst1) result)
+       (setq result (cons (list (car lst1)
+                                (car lst2))
+                          result))))
+
+(defun make-gsym-list (size)
+  "Not CL. Returns a list with size members, each being a different gensym"
+  (let ((temp nil))
+        (dotimes (arg size temp)
+          (declare (fixnum arg))
+          (setq temp (cons (gensym) temp)))))
+;;;;;;;
+
+(define-setf-method getf (plist prop &optional (default () default-p)
+                                     &aux (prop-p (not (quoted-form-p prop)))
+                                     &environment env)
+ (multiple-value-bind (vars vals stores store-form access-form)
+                      (get-setf-method plist env)
+   (when default-p (setq default (list default)))
+   (let ((prop-var (if prop-p (gensym) prop))
+         (store-var (gensym))
+         (default-var (if default-p (list (gensym)))))
+     (values
+      `(,@vars ,.(if prop-p (list prop-var)) ,@default-var)
+      `(,@vals ,.(if prop-p (list prop)) ,@default)
+      (list store-var)
+      `(let* ((,(car stores) (setprop ,access-form ,prop-var ,store-var)))
+         ,store-form
+         ,store-var)
+      `(getf ,access-form ,prop-var ,@default-var)))))
+
+(define-setf-method getf-test (plist prop test &optional (default () default-p)
+                                       &aux (prop-p (not (quoted-form-p prop)))
+                                       &environment env)
+ (multiple-value-bind (vars vals stores store-form access-form)
+                      (get-setf-method plist env)
+   (when default-p (setq default (list default)))
+   (let ((prop-var (if prop-p (gensym) prop))
+         (test-var (gensym))
+         (store-var (gensym))
+         (default-var (if default-p (list (gensym)))))
+     (values
+      `(,@vars ,.(if prop-p (list prop-var)) ,test-var ,@default-var)
+      `(,@vals ,.(if prop-p (list prop)) ,test ,@default)
+      (list store-var)
+      `(let* ((,(car stores) (setprop-test ,access-form ,prop-var ,test-var ,store-var)))
+         ,store-form
+         ,store-var)
+      `(getf-test ,access-form ,prop-var ,test-var ,@default-var)))))
+
+(define-setf-method ldb (bytespec place &environment env)
+  "The first argument is a byte specifier. The second is any place form
+  acceptable to SETF. Replace the specified byte of the number in this
+  place with bits from the low-order end of the new value."
+  (multiple-value-bind (dummies vals newval setter getter)
+		       (get-setf-method place env)
+    (let ((btemp (gensym))
+	  (gnuval (gensym)))
+      (values (cons btemp dummies)
+	      (cons bytespec vals)
+	      (list gnuval)
+	      `(let ((,(car newval) (dpb ,gnuval ,btemp ,getter)))
+		 ,setter
+		 ,gnuval)
+	      `(ldb ,btemp ,getter)))))
+
+
+(define-setf-method mask-field (bytespec place &environment env)
+  "The first argument is a byte specifier. The second is any place form
+  acceptable to SETF. Replaces the specified byte of the number in this place
+  with bits from the corresponding position in the new value."
+  (multiple-value-bind (dummies vals newval setter getter)
+		       (get-setf-method place env)
+    (let ((btemp (gensym))
+	  (gnuval (gensym)))
+      (values (cons btemp dummies)
+	      (cons bytespec vals)
+	      (list gnuval)
+	      `(let ((,(car newval) (deposit-field ,gnuval ,btemp ,getter)))
+		 ,setter
+		 ,gnuval)
+	      `(mask-field ,btemp ,getter)))))
+
+(defmacro shiftf (arg1 arg2 &rest places-&-nuval &environment env)
+  "One or more SETF-style place expressions, followed by a single
+   value expression. Evaluates all of the expressions in turn, then
+   assigns the value of each expression to the place on its left,
+   returning the value of the leftmost."
+  (setq places-&-nuval (list* arg1 arg2 places-&-nuval))
+  (let* ((nuval (car (last places-&-nuval)))
+         (places (cdr (reverse places-&-nuval)))  ; not nreverse, since &rest arg shares structure with &whole.
+         (setters (list 'progn))
+         (last-getter nuval)
+         last-let-list
+         let-list
+         (body setters))
+    (dolist (place places)
+      (multiple-value-bind (vars values storevars setter getter)
+                           (get-setf-method-multiple-value place env)
+        (dolist (v vars)
+          (push (list v (pop values)) let-list))
+        (push setter (cdr setters))
+        (setq body
+              (if last-let-list
+                `(let* ,(nreverse last-let-list)
+                   (multiple-value-bind ,storevars ,last-getter
+                     ,body))
+                `(multiple-value-bind ,storevars ,last-getter
+                   ,body))
+              last-let-list let-list
+              let-list nil
+              last-getter getter)))
+    (if last-let-list
+      `(let* ,(nreverse last-let-list)
+         (multiple-value-prog1 ,last-getter
+           ,body))
+      `(multiple-value-prog1 ,last-getter
+         ,body))))
+
+;(shiftf (car x)(cadr x) 3)
+
+#|
+(defmacro rotatef (&rest args &environment env)
+  (let* ((setf-result nil)
+         (let-result nil)
+         (last-store nil)
+         (fixpair nil))
+    (dolist (arg args)
+      (multiple-value-bind (vars vals storevars setter getter) 
+                           (get-setf-method arg env)
+        (dolist (var vars)
+          (push (list var (pop vals)) let-result))
+        (push (list last-store getter) let-result)
+        (unless fixpair (setq fixpair (car let-result)))
+        (push setter setf-result)
+        (setq last-store (car storevars))))
+    (rplaca fixpair last-store)
+    `(let* ,(nreverse let-result) ,@(nreverse setf-result) nil)))
+
+
+;(rotatef (blob x)(blob y))
+(defun blob (x) (values (car x)(cadr x)))
+(define-setf-method blob (x)
+    (let ((v1 (gensym))(v2 (gensym))(v3 (gensym)))
+    (values
+     (list v1)
+     (list x)
+     (list v2 v3)      
+     `(progn (setf (car ,v1) ,v2)
+             (setf (cadr ,v1) ,v3))     
+     `(values (car ,v1)(cadr ,v1)))))
+|#
+
+(defmacro rotatef (&rest args &environment env)
+  "Takes any number of SETF-style place expressions. Evaluates all of the
+   expressions in turn, then assigns to each place the value of the form to
+   its right. The rightmost form gets the value of the leftmost.
+   Returns NIL."
+  (when args
+    (let* ((places (reverse args))  ; not nreverse, since &rest arg shares structure with &whole.
+           (final-place (pop places))
+           (setters (list 'progn nil))
+           last-let-list
+           let-list
+           (body setters))
+      (multiple-value-bind (final-vars final-values final-storevars
+                                       final-setter last-getter)
+                           (get-setf-method-multiple-value final-place env)
+        (dolist (v final-vars)
+          (push (list v (pop final-values)) last-let-list))
+        (push final-setter (cdr setters))
+        (dolist (place places)
+          (multiple-value-bind (vars values storevars setter getter)
+                               (get-setf-method-multiple-value place env)
+            (dolist (v vars)
+              (push (list v (pop values)) let-list))
+            (push setter (cdr setters))
+            (setq body
+                  (if last-let-list
+                    `(let* ,(nreverse last-let-list)
+                       (multiple-value-bind ,storevars ,last-getter
+                         ,body))
+                    `(multiple-value-bind ,storevars ,last-getter
+                       ,body))
+                  last-let-list let-list
+                  let-list nil
+                  last-getter getter)))
+        (if last-let-list
+          `(let* ,(nreverse last-let-list)
+             (multiple-value-bind ,final-storevars ,last-getter
+               ,body))
+          `(multiple-value-bind ,final-storevars ,last-getter
+             ,body))))))
+
+
+
+(defmacro push (value place &environment env)
+  "Takes an object and a location holding a list. Conses the object onto
+  the list, returning the modified list. OBJ is evaluated before PLACE."
+  (if (not (consp place))
+    `(setq ,place (cons ,value ,place))
+    (multiple-value-bind (dummies vals store-var setter getter)
+                         (get-setf-method place env)
+      (let ((valvar (gensym)))
+        `(let* ((,valvar ,value)
+                ,@(mapcar #'list dummies vals)
+                (,(car store-var) (cons ,valvar ,getter)))
+           ,@dummies
+           ,(car store-var)
+           ,setter)))))
+
+(defmacro pushnew (value place &rest keys &environment env)
+  "Takes an object and a location holding a list. If the object is
+  already in the list, does nothing; otherwise, conses the object onto
+  the list. Returns the modified list. If there is a :TEST keyword, this
+  is used for the comparison."
+  (if (not (consp place))
+    `(setq ,place (adjoin ,value ,place ,@keys))
+    (let ((valvar (gensym)))
+      (multiple-value-bind (dummies vals store-var setter getter)
+                           (get-setf-method place env)
+        `(let* ((,valvar ,value)
+                ,@(mapcar #'list dummies vals)
+                (,(car store-var) (adjoin ,valvar ,getter ,@keys)))
+           ,@dummies
+           ,(car store-var)
+           ,setter)))))
+
+(defmacro pop (place &environment env &aux win)
+  "The argument is a location holding a list. Pops one item off the front
+  of the list and returns it."
+  (while (atom place)
+    (multiple-value-setq (place win) (macroexpand-1 place env))
+    (unless win
+      (return-from pop
+        `(prog1 (car ,place) (setq ,place (cdr (the list ,place)))))))
+  (let ((value (gensym)))
+    (multiple-value-bind (dummies vals store-var setter getter)
+                         (get-setf-method place env)
+      `(let* (,@(mapcar #'list dummies vals)
+              (,value ,getter)
+              (,(car store-var) (cdr ,value)))
+         ,@dummies
+         ,(car store-var)
+         (prog1
+           (%car ,value)
+           ,setter)))))
+
+(defmacro %pop (symbol)
+  `(prog1 (%car ,symbol) (setq ,symbol (%cdr ,symbol))))
+
+#|
+(defmacro push (item place)
+  (if (not (consp place))
+    `(setq ,place (cons ,item ,place))
+    (let* ((arg-num (1- (length place)))
+           (place-args (make-gsym-list arg-num)))
+      `(let ,(cons (list 'nu-item item)
+                   (reverse (assoc-2-lists place-args (cdr place))))
+         (setf (,(car place) ,@place-args)
+               (cons nu-item (,(car place) ,@place-args)))))))
+
+(defmacro pushnew (item place &rest key-args)
+  (let ((item-gsym (gensym)))
+    (if (not (consp place))
+      `(let ((,item-gsym ,item))
+         (setq ,place (adjoin ,item-gsym ,place ,@key-args)))
+      (let* ((arg-num (1- (length place)))
+             (place-args (make-gsym-list arg-num)))
+        `(let ,(cons (list item-gsym item)
+                     (reverse (assoc-2-lists place-args (cdr place))))
+           (setf (,(car place) ,@place-args)
+                 (adjoin ,item-gsym (,(car place) ,@place-args)
+                         ,@key-args)))))))
+(defmacro pop (place)
+  (if (not (consp place))               ;  screw: symbol macros.
+    `(prog1 (car ,place) (setq ,place (%cdr ,place)))
+    (let* ((arg-num (1- (length place)))
+           (place-args (make-gsym-list arg-num)))
+      `(let ,(reverse (assoc-2-lists place-args (cdr place)))
+         (prog1 (car (,(car place) ,@place-args))
+           (setf (,(car place) ,@place-args)
+                 (cdr (,(car place) ,@place-args))))))))
+|#
+
+(defmacro remf (place indicator &environment env)
+  "Place may be any place expression acceptable to SETF, and is expected
+  to hold a property list or (). This list is destructively altered to
+  remove the property specified by the indicator. Returns T if such a
+  property was present, NIL if not."
+  (multiple-value-bind (dummies vals newval setter getter)
+                       (get-setf-method place env)
+    (do* ((d dummies (cdr d))
+          (v vals (cdr v))
+          (let-list nil)
+          (ind-temp (gensym))
+          (local1 (gensym))
+          (local2 (gensym)))
+         ((null d)
+          (push (list ind-temp indicator) let-list)
+          (push (list (car newval) getter) let-list)
+          `(let* ,(nreverse let-list)
+             (do ((,local1 ,(car newval) (cddr ,local1))
+                  (,local2 nil ,local1))
+                 ((atom ,local1) nil)
+               (cond ((atom (cdr ,local1))
+                      (error "Odd-length property list in REMF."))
+                     ((eq (car ,local1) ,ind-temp)
+                      (cond (,local2
+                             (rplacd (cdr ,local2) (cddr ,local1))
+                             (return t))
+                            (t (setq ,(car newval) (cddr ,(car newval)))
+                               ,setter
+                               (return t))))))))
+      (push (list (car d) (car v)) let-list))))
+
+(defmacro remf-test (place indicator test &environment env)
+  "Place may be any place expression acceptable to SETF, and is expected
+  to hold a property list or ().  This list is destructively altered to
+  remove the property specified by the indicator.  Returns T if such a
+  property was present, NIL if not."
+  (multiple-value-bind (dummies vals newval setter getter)
+                       (get-setf-method place env)
+    (do* ((d dummies (cdr d))
+          (v vals (cdr v))
+          (let-list nil)
+          (ind-temp (gensym))
+          (test-temp (gensym))
+          (local1 (gensym))
+          (local2 (gensym)))
+         ((null d)
+          (push (list (car newval) getter) let-list)
+          (push (list ind-temp indicator) let-list)
+          (push (list test-temp test) let-list)
+          `(let* ,(nreverse let-list)
+             (do ((,local1 ,(car newval) (cddr ,local1))
+                  (,local2 nil ,local1))
+                 ((atom ,local1) nil)
+               (cond ((atom (cdr ,local1))
+                      (error "Odd-length property list in REMF."))
+                     ((funcall ,test-temp (car ,local1) ,ind-temp)
+                      (cond (,local2
+                             (rplacd (cdr ,local2) (cddr ,local1))
+                             (return t))
+                            (t (setq ,(car newval) (cddr ,(car newval)))
+                               ,setter
+                               (return t))))))))
+      (push (list (car d) (car v)) let-list))))
+
+(define-setf-expander values (&rest places &environment env) 
+  (let* ((setters ())
+	 (getters ())
+	 (all-dummies ()) 
+	 (all-vals ()) 
+	 (newvals ())) 
+    (dolist (place places) 
+      (multiple-value-bind (dummies vals newval setter getter) 
+	  (get-setf-expansion place env) 
+	(setf all-dummies (append all-dummies dummies (cdr newval))) 
+	(setf all-vals (append all-vals vals (mapcar (constantly nil) (cdr newval)))) 
+	(setf newvals (append newvals (list (car newval)))) 
+	(push setter setters)
+	(push getter getters))) 
+      (values all-dummies all-vals newvals 
+              `(values ,@(nreverse setters)) `(values ,@(nreverse getters)))))
Index: /branches/new-random/lib/sort.lisp
===================================================================
--- /branches/new-random/lib/sort.lisp	(revision 13309)
+++ /branches/new-random/lib/sort.lisp	(revision 13309)
@@ -0,0 +1,505 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Sort
+
+;;; sorts a sequence destructively using a predicate which must be a
+;;;  of two arguments which returns non-() only if the first argument is
+;;;  strictly less than the second.  The keyfun (if present) must be a
+;;;  function of one argument.  The predicate is applied to keyfun of the
+;;;  sequence elements, or directly to the elements if the keyfun is not
+;;;  given.
+
+;;; Sort dispatches to type specific sorting routines.
+
+(in-package "CCL")
+
+(defun sort (sequence predicate &key key)
+  "Returns SEQUENCE, which has been modified to be in order.
+   If sequence is a displaced array, sorts just that portion of the
+   data-array which is part of SEQUENCE."
+  (if (< (length sequence) 2)
+    sequence
+    (if (listp sequence)
+      (sort-list sequence predicate key)
+      (quick-sort-vector sequence predicate key))))
+
+(defun stable-sort (sequence predicate &key key)
+  "Returns SEQUENCE, which has been modified to be in order.
+   If sequence is a displaced array, sorts just that portion of the
+   data-array which is part of SEQUENCE."
+  (if (< (length sequence) 2)
+    sequence
+    (if (listp sequence)
+      (sort-list sequence predicate key)
+      (merge-sort-vector sequence predicate key))))
+
+
+;;; Vector sorting.
+;;; The quick-sort is a little slower than the merge-sort, but it doesn't cons.
+;;; The merge-sort is stable.
+;;; Note that there are three version of each:
+;;;   AREF for non-simple (eventually) vectors.
+;;;   %SVREF with a key.
+;;;   %SVREF without a key.
+;;; Other than that, the three versions are duplicates.
+(defun merge-sort-vector (vector pred key)
+  (canonicalize-pred-and-key)
+  (let* ((end (length vector)))
+    (when (> end 1)
+      (multiple-value-bind (real-vector start) 
+                           (array-data-and-offset vector)
+        (incf end start)
+        (unless (fixnump end)
+          (error "Sorry, can't sort vectors larger than ~d." most-positive-fixnum))
+        (let* ((temp-array (make-array (the fixnum end))))
+          (declare (dynamic-extent temp-array))
+          (if (simple-vector-p real-vector)
+            (if key
+              (%merge-sort-simple-vector
+               real-vector start end pred key temp-array nil)
+              (%merge-sort-simple-vector-no-key
+               real-vector start end pred temp-array nil))
+            (%merge-sort-vector real-vector start end pred key temp-array nil))))))
+  vector)
+
+(defun quick-sort-vector (vector pred key)
+  (canonicalize-pred-and-key)
+  (let ((end (length vector)))
+    (when (> end 1)
+      (multiple-value-bind (real-vector start) 
+                           (array-data-and-offset vector)
+        (incf end (%i- start 1))
+; No vector should have a length that's not  a fixnum.
+        '(unless (fixnump end)
+          (error "Sorry, can't sort vectors larger than ~d." most-positive-fixnum))
+        (if (simple-vector-p real-vector)
+          (if key
+            (%quick-sort-simple-vector real-vector start end pred key)
+            (%quick-sort-simple-vector-no-key real-vector start end pred))
+          (%quick-sort-vector
+           real-vector start end pred (or key #'identity))))))
+  vector)
+
+;;; merge-sort internals
+
+(defun %merge-sort-vector (vector start end pred key
+                                  temp-vec res-temp?)
+  ;; If somebody wanted to do it, half of these arefs can be %svrefs,
+  ;; but you'd need two loops in the merge code
+  ;; (temp-vec is simple if res-temp? is false).
+  ;; But who sorts non-svref'able vectors anyway?
+  (let* ((mid (%ilsr 1 (%i+ start end))))
+    (if (%i<= (%i- mid 1) start)
+      (unless res-temp?
+        (setf (aref temp-vec start) (aref vector start)))
+      (%merge-sort-vector
+       vector start mid pred key temp-vec (not res-temp?)))
+    (if (%i>= (%i+ mid 1) end)
+      (unless res-temp?
+        (setf (aref temp-vec mid) (aref vector mid)))
+      (%merge-sort-vector 
+       vector mid end pred key temp-vec (not res-temp?)))
+    
+    (unless res-temp?
+      (psetq vector temp-vec temp-vec vector))
+    
+    (%merge-vectors vector start mid vector mid end temp-vec start pred key)))
+    
+(defun %merge-sort-simple-vector (vector start end pred key
+                                         temp-vec res-temp?)
+  (let* ((mid (%ilsr 1 (%i+ start end))))
+    (if (%i<= (%i- mid 1) start)
+      (unless res-temp?
+        (setf (%svref temp-vec start) (%svref vector start)))
+      (%merge-sort-simple-vector
+       vector start mid pred key temp-vec (not res-temp?)))
+    (if (%i>= (%i+ mid 1) end)
+      (unless res-temp?
+        (setf (%svref temp-vec mid) (%svref vector mid)))
+      (%merge-sort-simple-vector 
+       vector mid end pred key temp-vec (not res-temp?)))
+    
+    (unless res-temp?
+      (psetq vector temp-vec temp-vec vector))
+    
+    (%merge-simple-vectors
+     vector start mid vector mid end temp-vec start pred key)))
+
+(defun %merge-sort-simple-vector-no-key (vector start end pred
+                                                temp-vec res-temp?)
+  (let* ((mid (%ilsr 1 (%i+ start end))))
+    (if (%i<= (%i- mid 1) start)
+      (unless res-temp?
+        (setf (%svref temp-vec start) (%svref vector start)))
+      (%merge-sort-simple-vector-no-key
+       vector start mid pred temp-vec (not res-temp?)))
+    (if (%i>= (%i+ mid 1) end)
+      (unless res-temp?
+        (setf (%svref temp-vec mid) (%svref vector mid)))
+      (%merge-sort-simple-vector-no-key
+       vector mid end pred temp-vec (not res-temp?)))
+    
+    (unless res-temp?
+      (psetq vector temp-vec temp-vec vector))
+    
+    (%merge-simple-vectors-no-key
+     vector start mid vector mid end temp-vec start pred)))
+
+(defun %merge-vectors (a1 start1 end1 a2 start2 end2
+                          out start-out pred key)
+  (let* ((i1 start1)
+         (i2 start2)
+         (i-out start-out)
+         v1 v2 k1 k2)
+    (cond ((eq start1 end1)
+           (when (eq start2 end2)
+             (return-from %merge-vectors out))
+           (setq i1 start2
+                 end1 end2
+                 a1 a2
+                 v1 (aref a1 i1)))
+          ((eq start2 end2)
+           (setq i1 start1
+                 v1 (aref a1 i1)))
+          (t
+           (setq v1 (aref a1 i1)
+                 v2 (aref a2 i2)
+                 k1 (if key (funcall key v1) v1)
+                 k2 (if key (funcall key v2) v2))
+           (loop (if (funcall pred k2 k1)
+                   (progn (setf (aref out i-out) v2
+                                i-out (%i+ i-out 1)
+                                i2 (%i+ i2 1))
+                          (when (eq i2 end2)
+                            (return))
+                          (setq v2 (aref a2 i2)
+                                k2 (if key (funcall key v2) v2)))
+                   (progn (setf (aref out i-out) v1
+                                i-out (%i+ i-out 1)
+                                i1 (%i+ i1 1))
+                          (when (eq i1 end1)
+                            (setq a1 a2 i1 i2 end1 end2 v1 v2)
+                            (return))
+                          (setq v1 (aref a1 i1)
+                                k1 (if key (funcall key v1) v1)))))))
+    (loop
+      (setf (aref out i-out) v1
+            i1 (%i+ i1 1))
+      (if (eq i1 end1) 
+        (return out))
+      (setq v1 (aref a1 i1)
+            i-out (%i+ i-out 1)))))
+
+(defun %merge-simple-vectors (a1 start1 end1 a2 start2 end2
+                                 out start-out pred key)
+  (let* ((i1 start1)
+         (i2 start2)
+         (i-out start-out)
+         v1 v2 k1 k2)
+    (cond ((eq start1 end1)
+           (when (eq start2 end2)
+             (return-from %merge-simple-vectors out))
+           (setq i1 start2
+                 end1 end2
+                 a1 a2
+                 v1 (%svref a1 i1)))
+          ((eq start2 end2)
+           (setq i1 start1
+                 v1 (%svref a1 i1)))
+          (t
+           (setq v1 (%svref a1 i1)
+                 v2 (%svref a2 i2)
+                 k1 (if key (funcall key v1) v1)
+                 k2 (if key (funcall key v2) v2))
+           (loop (if (funcall pred k2 k1)
+                   (progn (setf (%svref out i-out) v2
+                                i-out (%i+ i-out 1)
+                                i2 (%i+ i2 1))
+                          (when (eq i2 end2)
+                            (return))
+                          (setq v2 (%svref a2 i2)
+                                k2 (funcall key v2)))
+                   (progn (setf (%svref out i-out) v1
+                                i-out (%i+ i-out 1)
+                                i1 (%i+ i1 1))
+                          (when (eq i1 end1)
+                            (setq a1 a2 i1 i2 end1 end2 v1 v2)
+                            (return))
+                          (setq v1 (%svref a1 i1)
+                                k1 (funcall key v1)))))))
+    (loop
+      (setf (%svref out i-out) v1
+            i1 (%i+ i1 1))
+      (if (eq i1 end1) 
+        (return out))
+      (setq v1 (%svref a1 i1)
+            i-out (%i+ i-out 1)))))
+
+(defun %merge-simple-vectors-no-key (a1 start1 end1 a2 start2 end2
+                                        out start-out pred)
+  (let* ((i1 start1)
+         (i2 start2)
+         (i-out start-out)
+         v1 v2)
+    (cond ((eq start1 end1)
+           (when (eq start2 end2)
+             (return-from %merge-simple-vectors-no-key out))
+           (setq i1 start2
+                 end1 end2
+                 a1 a2
+                 v1 (%svref a1 i1)))
+          ((eq start2 end2)
+           (setq i1 start1
+                 v1 (%svref a1 i1)))
+          (t
+           (setq v1 (%svref a1 i1)
+                 v2 (%svref a2 i2))
+           (loop (if (funcall pred v2 v1)
+                   (progn (setf (%svref out i-out) v2
+                                i-out (%i+ i-out 1)
+                                i2 (%i+ i2 1))
+                          (when (eq i2 end2)
+                            (return))
+                          (setq v2 (%svref a2 i2)))
+                   (progn (setf (%svref out i-out) v1
+                                i-out (%i+ i-out 1)
+                                i1 (%i+ i1 1))
+                          (when (eq i1 end1)
+                            (setq a1 a2 i1 i2 end1 end2 v1 v2)
+                            (return))
+                          (setq v1 (%svref a1 i1)))))))
+    (loop
+      (setf (%svref out i-out) v1
+            i1 (%i+ i1 1))
+      (if (eq i1 end1) 
+        (return out))
+      (setq v1 (%svref a1 i1)
+            i-out (%i+ i-out 1)))))
+
+
+;;; Quick sort internals
+(defun %quick-sort-vector (vector start end pred key)
+  (declare (optimize (speed 3) (safety 0)))
+  (declare (fixnum start end))
+  (if (< start end)
+    (let* ((p (the fixnum (+ start (the fixnum (ash (the fixnum (- end start)) -1)))))
+           (Ai (aref vector p))
+           (x (funcall key Ai))
+           (pivot Ai)
+           (i start)
+           (j (the fixnum (1+ end)))
+           Aj)
+      (declare (fixnum p i j))
+      (setf (aref vector p) (aref vector start)
+            (aref vector start) Ai)
+      (block partition
+        (loop
+          (loop (unless (> (decf j) i) (return-from partition))
+                (unless (funcall pred
+                                 x
+                                 (funcall key (setq Aj (aref vector j))))
+                  (return)))
+          (loop (unless (< (incf i) j) (return-from partition))
+                (unless (funcall pred
+                                 (funcall key (setq Ai (aref vector i)))
+                                 x)
+                  (return)))
+          (setf (aref vector i) Aj
+                (aref vector j) Ai)))
+      (setf (aref vector start) (aref vector j)
+            (aref vector j) pivot)
+      ; This compare is important.  It limits stack depth to log(end-start)
+      (if (< (the fixnum (- j start)) (the fixnum (- end j)))
+        (progn
+          (%quick-sort-vector vector start (the fixnum (1- j)) pred key)
+          (%quick-sort-vector vector (the fixnum (1+ j)) end pred key))
+        (progn
+          (%quick-sort-vector vector (the fixnum (1+ j)) end pred key)
+          (%quick-sort-vector vector start (the fixnum (1- j)) pred key))))
+    vector))
+
+(defun %quick-sort-simple-vector (vector start end pred key)
+  (declare (optimize (speed 3) (safety 0)))
+  (declare (type simple-vector vector)
+           (fixnum start end))
+  (if (< start end)
+    (let* ((p (the fixnum (+ start (the fixnum (ash (the fixnum (- end start)) -1)))))
+           (Ai (svref vector p))
+           (pivot Ai)
+           (x (funcall key Ai))
+           (i start)
+           (j (the fixnum (1+ end)))
+           Aj)
+      (declare (fixnum p i j))
+      (setf (svref vector p) (svref vector start)
+            (svref vector start) Ai)
+      (block partition
+        (loop
+          (loop (unless (> (decf j) i) (return-from partition))
+                (unless (funcall pred
+                                 x
+                                 (funcall key (setq Aj (svref vector j))))
+                  (return)))
+          (loop (unless (< (incf i) j) (return-from partition))
+                (unless (funcall pred
+                                 (funcall key (setq Ai (svref vector i)))
+                                 x)
+                  (return)))
+          (setf (aref vector i) Aj
+                (aref vector j) Ai)))
+      (setf (svref vector start) (svref vector j)
+            (svref vector j) pivot)
+      (if (< (the fixnum (- j start)) (the fixnum (- end j)))
+        (progn
+          (%quick-sort-simple-vector vector start (the fixnum (1- j)) pred key)
+          (%quick-sort-simple-vector vector (the fixnum (1+ j)) end pred key))
+        (progn
+          (%quick-sort-simple-vector vector (the fixnum (1+ j)) end pred key)
+          (%quick-sort-simple-vector vector start (the fixnum (1- j)) pred key))))
+    vector))
+
+(defun %quick-sort-simple-vector-no-key (vector start end pred)
+  (declare (optimize (speed 3) (safety 0)))
+  (declare (type simple-vector vector)
+           (fixnum start end))
+  (if (< start end)
+    (let* ((p (the fixnum (+ start (the fixnum (ash (the fixnum (- end start)) -1)))))
+           (x (svref vector p))
+           (i start)
+           (j (the fixnum (1+ end)))
+           Ai Aj)
+      (declare (fixnum p i j))
+      (setf (svref vector p) (svref vector start)
+            (svref vector start) x)
+      (block partition
+        (loop
+          (loop (unless (> (decf j) i) (return-from partition))
+                (unless (funcall pred
+                                 x
+                                 (setq Aj (svref vector j)))
+                  (return)))
+          (loop (unless (< (incf i) j) (return-from partition))
+                (unless (funcall pred
+                                 (setq Ai (svref vector i))
+                                 x)
+                  (return)))
+          (setf (aref vector i) Aj
+                (aref vector j) Ai)))
+      (setf (svref vector start) (svref vector j)
+            (svref vector j) x)
+      (if (< (the fixnum (- j start)) (the fixnum (- end j)))
+        (progn
+          (%quick-sort-simple-vector-no-key vector start (the fixnum (1- j)) pred)
+          (%quick-sort-simple-vector-no-key vector (the fixnum (1+ j)) end pred))
+        (progn
+          (%quick-sort-simple-vector-no-key vector (the fixnum (1+ j)) end pred)
+          (%quick-sort-simple-vector-no-key vector start (the fixnum (1- j)) pred))))
+    vector))
+
+
+
+;; This conses like crazy if you merge lists into vectors or vice-versa, but
+;; I don't want to write 6 more merging routines.  Fry's coerce's
+;; will have to stand for now.
+;; Only difficulty here is parsing the result-type for vectors.
+(defun merge (result-type sequence1 sequence2 predicate &key key)
+  "Merge the sequences SEQUENCE1 and SEQUENCE2 destructively into a
+   sequence of type RESULT-TYPE using PREDICATE to order the elements.
+   If result-type specifies an array, the returned array will not be
+   a complex array. Usually, result-type is either LIST, ARRAY or STRING."
+  (let* ((result-len (+ (length sequence1) (length sequence2)))
+         (result-ctype (specifier-type result-type)))
+    (cond ((csubtypep result-ctype (specifier-type 'null))
+           (unless (zerop result-len)
+             (error 'invalid-subtype-error :datum result-type
+                    :expected-type 'cons)))
+          ((csubtypep result-ctype (specifier-type 'list))
+           (canonicalize-pred-and-key predicate key)
+           (values                      ; For the terminally pedantic.
+            (merge-lists* (if (listp sequence1)
+                            sequence1
+                            (coerce sequence1 'list))
+                          (if (listp sequence2)
+                            sequence2
+                            (coerce sequence2 'list))
+                          predicate key)))
+          ((csubtypep result-ctype (specifier-type 'vector))
+           (merge-vectors (if (listp sequence1)
+                            (coerce sequence1 'vector)
+                            sequence1)
+                          (if (listp sequence2)
+                            (coerce sequence2 'vector)
+                            sequence2)
+                          predicate key
+                          result-type))
+          (t (error 'invalid-subtype-error
+                    :datum result-type
+                    :expected-type 'sequence)))))
+
+(defun merge-vectors (vector-1 vector-2 pred key 
+                               &optional (result-type 'vector))
+  "Internal function.  Use MERGE instead."
+  (canonicalize-pred-and-key)
+  (let* ((length-1 (length vector-1))
+         (length-2 (length vector-2))
+         (result-length (+ length-1 length-2))
+         (result (make-merge-vectors-result
+                  result-type result-length vector-1 vector-2))
+         real-vector-1 start-1 real-vector-2 start-2)
+    (multiple-value-setq (real-vector-1 start-1)
+                         (array-data-and-offset vector-1))
+    (multiple-value-setq (real-vector-2 start-2)
+                         (array-data-and-offset vector-2))
+    (incf length-1 start-1)
+    (incf length-2 start-2)
+    (if (and (simple-vector-p real-vector-1) (simple-vector-p real-vector-2)
+             (simple-vector-p result))
+      (if key
+        (%merge-simple-vectors real-vector-1 start-1 length-1
+                               real-vector-2 start-2 length-2
+                               result 0 pred key)
+        (%merge-simple-vectors-no-key real-vector-1 start-1 length-1
+                                      real-vector-2 start-2 length-2
+                                      result 0 pred))
+      (%merge-vectors real-vector-1 start-1 length-1
+                      real-vector-2 start-2 length-2
+                      result 0 pred key))))
+
+;; OK, here goes the type parsing...
+(defun make-merge-vectors-result (result-type result-length vector-1 vector-2)
+  (let* ((ctype (specifier-type result-type)))
+    (let* ((size (array-ctype-length ctype))
+           (elt-type (array-or-union-ctype-element-type ctype)))
+      (if (eq elt-type '*)
+        (let ((et1 (array-element-type vector-1))
+              (et2 (array-element-type vector-2)))
+          (setq elt-type (if (eq et1 et2) et1 `(or ,et1 ,et2)))))
+      (if (and size (not (eq size result-length)))
+        (error 'invalid-subtype-error
+               :datum result-type
+               :expected-type `(vector ,elt-type ,result-length))
+        (make-array (the fixnum (or size result-length))
+                    :element-type elt-type)))))
+        
+
+;; Gee, that wasn't so bad after all.
+;; Well, when you're building on the shoulders of giants,
+;; your little effort can seem great.
+
+
+;; "If I haven't seen as far as others, it's because giants were standing on my shoulders."
Index: /branches/new-random/lib/source-files.lisp
===================================================================
--- /branches/new-random/lib/source-files.lisp	(revision 13309)
+++ /branches/new-random/lib/source-files.lisp	(revision 13309)
@@ -0,0 +1,770 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;; If we're reloading this file, don't want to be calling functions from here with
+;; only some of them redefined.  So revert to the bootstrapping version until the end.
+(fset 'record-source-file #'level-1-record-source-file)
+
+(defvar *source-files-lock* (make-lock "Source Files Lock"))
+
+(defvar *unique-setf-names* (make-hash-table :test #'eq))
+
+(defun canonical-maybe-setf-name (name)
+  (if (setf-function-name-p name)
+    (let ((tem (%setf-method (%cadr name))))
+      (if (non-nil-symbol-p tem) ;; e.g. (setf car) => set-car
+        tem
+        (or (gethash (%cadr name) *unique-setf-names*)
+            (setf (gethash (%cadr name) *unique-setf-names*) (list 'setf (%cadr name))))))
+    name))
+
+(defgeneric name-of (thing)
+  (:method ((thing t)) thing)
+  (:method ((thing method-function)) (name-of (%method-function-method thing)))
+  (:method ((thing function)) (name-of (function-name thing)))
+  (:method ((thing method)) `(:method ,(method-name thing) ,@(method-qualifiers thing) ,(method-specializers thing)))
+  (:method ((thing class)) (class-name thing))
+  (:method ((thing method-combination)) (method-combination-name thing))
+  (:method ((thing package)) (package-name thing))
+  (:method ((thing eql-specializer)) `(eql ,(eql-specializer-object thing))))
+
+;; This used to be weak, but the keys are symbols-with-definitions, so why bother.
+;; Set a high rehash threshold because space matters more than speed here.
+;; Do not use lock-free hash tables, because they optimize reads at the expense of
+;; writes/rehashes.  Writes/rehashes affect file-compilation speed, which matters.
+(defvar %source-files% (make-hash-table :test #'eq
+                                        :size 14000
+                                        :rehash-size 1.8 ;; compensate for high threshold
+                                        :rehash-threshold .95
+                                        :lock-free nil))
+
+
+
+(defvar *direct-methods-only* t
+  "If true, method name source location lookup will find direct methods only.  If false,
+   include all applicable methods")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Definition types
+;;
+;; Definition types are uniquely identified by a symbol, but are implemented as
+;; classes so they can inherit/customize behavior.  They have no instances other
+;; than the class prototype, which is used to invoke methods.
+;;
+
+(defgeneric definition-type-name (def-type)
+  (:documentation "The preferred user-visible name of the def-type.  Used for
+error messages etc.  The default method returns the name specified in
+define-definition-type."))
+
+(defclass definition-type ()
+  ((name :allocation :class :reader definition-type-name :initform t))
+  (:documentation "Superclass of all definition types"))
+
+(defgeneric definition-base-name (def-type def)
+  ;; Note that a def can have multiple base names, but each one needs a different def-type
+  (:documentation "Return the name that, when the user asks for all definitions of that
+name, this def should be included.  Typically this is a symbol.  It's used as a key in
+an EQ hash table, so must return EQ values for equivalent definitions.
+The default method returns the rightmost atom in name")
+  (:method ((dt definition-type) name)
+    (while (consp name)
+      (let ((x (last name)))
+        (setq name (or (cdr x) (car x)))))
+    name))
+
+(defgeneric definition-same-p (def-type def1 def2)
+  (:documentation "Returns true if the two definitions are equivalent, i.e. one should
+replace the other.  The default method calls EQUAL.")
+  (:method ((dt definition-type) name1 name2)
+    (equal name1 name2)))
+
+(defgeneric definition-bound-p (def-type def)
+  (:documentation "Returns true if def is currently defined.  Used to decide whether to issue
+redefinition warnings.  The default method returns T.")
+  (:method ((dt definition-type) name)
+    (declare (ignore name))
+    t))
+
+;;;;;;;;;;
+
+(defvar *definition-types* ()
+  "alist of all known definition type names and their class prototypes")
+
+(defmethod print-object ((dt definition-type) stream)
+  (if *print-escape*
+    (let ((definedp (class-name (class-of dt))))
+      (print-unreadable-object (dt stream :type definedp :identity t)
+        (unless definedp
+          (format stream "#:~s " 'definition-type)) ;; subtly indicate it's a subclass...
+        (format stream "~s" (definition-type-name dt))))
+    (format stream "~s" (definition-type-name dt))))
+
+(defmethod name-of ((thing definition-type))
+  (definition-type-name thing))
+
+(defmacro define-definition-type (name supers &rest options)
+  "Defines a class named name-DEFINITION-TYPE and registers it as the class of
+definition type NAME"
+  (loop with known-keys = '( ;; Backward compatibility
+                            #+ccl-0711 :default-name-function)
+        for (key . nil) in options
+        unless (memq key known-keys)
+          do (signal-program-error "Unknown option ~s" key))
+  (let ((class-name (intern (%str-cat (symbol-name name) "-DEFINITION-TYPE"))))
+    `(progn
+       (defclass ,class-name ,(or supers '(definition-type))
+         ((name :allocation :class :initform ',name)))
+       (record-source-file ',name 'definition-type)
+       (register-definition-type (find-class ',class-name) '(,name)))))
+
+(defun register-definition-type (class names)
+  (let ((instance (class-prototype class)))
+    (with-lock-grabbed (*source-files-lock*)
+      ;; If had a previous definition, the defclass will signal any duplicate
+      ;; definition warnings, so here just silently replace previous one.
+      (without-interrupts
+        (setq *definition-types*
+              (remove instance *definition-types* :key #'cdr)))
+      (loop for name in names
+            unless (without-interrupts
+                     (unless (assq name *definition-types*)
+                       (push (cons name instance) *definition-types*)))
+              do (error "There is already a different definition type ~s named ~s"
+                        (cdr (assq name *definition-types*))
+                        name)))
+    ;; Return instance for use in make-load-form
+    instance))
+
+(defun auto-create-definition-type (name)
+  ;; Use an anonymous class, so this means can't write methods on it.
+  ;; If you want to write methods on it, use define-definition-type first.
+  (let* ((super (find-class 'definition-type))
+         (new-class (make-instance (class-of super)
+                      :direct-superclasses (list super)
+                      :direct-slots `((:name name
+                                       :allocation :class
+                                       :initform ',name
+                                       :initfunction ,(constantly name))))))
+    (register-definition-type new-class (list name))
+    (class-prototype new-class)))
+
+(defmethod definition-type-instance ((dt definition-type) &key (if-does-not-exist :error))
+  (if (rassoc dt *definition-types* :test #'eq)
+    dt
+    (ecase if-does-not-exist
+      ((nil) nil)
+      ((:error) (error "~s is not a known definition-type" dt)))))
+
+(defmethod definition-type-instance ((name symbol) &key (if-does-not-exist :error))
+  (or (cdr (assq name *definition-types*))
+      (ecase if-does-not-exist
+        ((nil) nil)
+        ((:error) (error "~s is not a known definition-type" name))
+        ((:create) (auto-create-definition-type name)))))
+
+(defmethod definition-type-instance ((class class) &key (if-does-not-exist :error))
+  (definition-type-instance (class-prototype class) :if-does-not-exist if-does-not-exist))
+
+(defmethod make-load-form ((dt definition-type) &optional env)
+  (declare (ignore env))
+  (let ((names (loop for (name . instance) in *definition-types*
+                     when (eq dt instance) collect name)))
+    `(register-definition-type ',(class-of dt) ',names)))
+
+
+(register-definition-type (find-class 'definition-type) '(t))
+
+(defparameter *t-definition-type* (definition-type-instance 't))
+
+(define-definition-type function ())
+
+(defparameter *function-definition-type* (definition-type-instance 'function))
+
+(defmethod definition-base-name ((dt function-definition-type) name)
+  (while (and (consp name) (not (setf-function-name-p name)))
+    (let ((x (last name)))
+      (or (setq name (cdr x))
+          ;; Try to detect the (:internal .... <hairy-method-name>) case
+          (when (and (setq name (car x))
+                     ;;check for plausible method name
+                     (setq x (method-def-parameters name))
+                     (neq x 'setf)
+                     (not (keywordp x)))
+            (setq name x)))))
+  (canonical-maybe-setf-name name))
+
+(defmethod definition-bound-p ((dt function-definition-type) name)
+  (and (or (symbolp name) (setf-function-name-p name))
+       (or (fboundp name)
+           ;; treat long-form setf expanders like macros.
+           (and (consp name) (functionp (%setf-method (cadr name)))))))
+
+(define-definition-type macro (function-definition-type))
+
+(define-definition-type compiler-macro (macro-definition-type))
+
+(define-definition-type symbol-macro (macro-definition-type))
+
+(define-definition-type setf-expander (macro-definition-type))
+
+(define-definition-type generic-function (function-definition-type))
+
+(define-definition-type method ())
+
+(defparameter *method-definition-type* (definition-type-instance 'method))
+
+(defmethod definition-base-name ((dt method-definition-type) (name cons))
+  (if (setf-function-name-p name)
+    (canonical-maybe-setf-name name)
+    (definition-base-name *function-definition-type* (car name))))
+
+;; defmethod passes the actual method into record-source-file
+(defmethod definition-base-name ((dt method-definition-type) (method method))
+  (definition-base-name dt (method-name method)))
+
+(defmethod definition-base-name ((dt method-definition-type) (fn method-function))
+  (definition-base-name dt (function-name fn)))
+
+(defmethod definition-same-p ((dt method-definition-type) m1 m2)
+  (multiple-value-bind (n1 q1 s1) (method-def-parameters m1)
+    (multiple-value-bind (n2 q2 s2) (method-def-parameters m2)
+      (and (definition-same-p *function-definition-type* n1 n2)
+           (equal q1 q2)
+           (eql (length s1) (length s2))
+           (every #'(lambda (s1 s2)
+                      (or (equal s1 s2)
+                          (progn
+                            (when (symbolp s2) (rotatef s1 s2))
+                            (and (symbolp s1)
+                                 (classp s2)
+                                 (or (eq (find-class s1 nil) s2)
+                                     (eq s1 (class-name s2)))))))
+                  s1 s2)))))
+
+(defmethod definition-bound-p ((dt method-definition-type) meth &aux fn)
+  (when (setq fn (method-def-parameters meth))
+    (loop for m in (and (setq fn (fboundp fn))
+                        (typep fn 'generic-function)
+                        (generic-function-methods fn))
+          thereis (definition-same-p dt meth m))))
+
+(define-definition-type reader-method (method-definition-type))
+
+(define-definition-type writer-method (method-definition-type))
+
+(define-definition-type callback (function-definition-type))
+
+(define-definition-type structure-accessor (function-definition-type))
+
+(define-definition-type type ())
+
+(define-definition-type class ())
+
+(defmethod definition-bound-p ((dt class-definition-type) name)
+  (and (non-nil-symbol-p name) (find-class name nil)))
+
+(define-definition-type condition (class-definition-type))
+
+(define-definition-type structure ())
+
+(define-definition-type definition-type ())
+
+(defmethod definition-bound-p ((dt definition-type-definition-type) name)
+  (definition-type-instance name :if-does-not-exist nil))
+
+(define-definition-type method-combination ())
+
+(define-definition-type variable ())
+
+(defmethod definition-bound-p ((dt variable-definition-type) name)
+  (and (non-nil-symbol-p name) (boundp name)))
+
+(define-definition-type constant (variable-definition-type))
+
+(define-definition-type package ())
+
+(defmethod definition-base-name ((dt package-definition-type) name)
+  (if (or (stringp name) (non-nil-symbol-p name))
+    (intern (string name) :keyword)
+    name))
+
+(defmethod definition-bound-p ((dt package-definition-type) name)
+  (and (or (stringp name) (symbolp name))
+       (find-package (string name))))
+
+(defmethod definition-same-p ((dt package-definition-type) d1 d2)
+  (and (or (stringp d1) (symbolp d1))
+       (or (stringp d2) (symbolp d2))
+       (equal (string d1) (string d2))))
+
+
+;;;;;;;;;;;
+
+(declaim (inline default-definition-type))
+
+(defun default-definition-type (name)
+  (if (typep name 'method)
+    *method-definition-type*
+    *function-definition-type*))
+
+;; remember & reuse last few (TYPE . file) entries
+(let ((cache (make-list 10 :initial-element nil)))
+  (defun type-file-cons (type files)
+    (loop for prev = nil then p for p = cache then (cdr p)
+          do (when (or (and (eq type (caar p)) (equal files (cdar p)))
+                       (and (null (cdr p))
+                            (setf (car p) (cons type files))))
+               (when prev ;; move to front unless already there
+                 (setf (cdr prev) (cdr p))
+                 (setf (cdr p) cache)
+                 (setq cache p))
+               (return (car p))))))
+
+(defun %source-file-entries (key)
+  (let ((data (gethash key %source-files%)))
+    (if (and (listp data)
+             (listp (%cdr data)))
+      data
+      (list data))))
+
+(defun %set-source-file-entries (key list &aux data)
+  (setf (gethash key %source-files%)
+        (if (and list
+                 (null (cdr list))
+                 ;; One element, but make sure can recognize it.
+                 (not (and (listp (%car list))
+                           (listp (%cdar data)))))
+          (car list)
+          list)))
+
+(defun make-def-source-entry (key type name files)
+  (setq files (if (or (%cdr files) (listp (%car files))) files (%car files)))
+  (cond ((eq type (default-definition-type name))
+         (if (and (eq name key) (atom files))
+           files
+           (cons name files)))
+        ((eq name key)
+         (type-file-cons type files))
+        (t
+         (cons (cons type name) files))))
+
+(defun decode-def-source-entry (key entry)
+  (if (atom entry)
+    (and entry (values (default-definition-type key) key (list entry)))
+    (let* ((file-or-files (%cdr entry))
+           (files (if (consp file-or-files) file-or-files (list file-or-files))))
+      (cond ((typep (%car entry) 'definition-type)
+             (values (%car entry) key files))
+            ((and (consp (%car entry)) (typep (%caar entry) 'definition-type))
+             (values (%caar entry) (%cdar entry) files))
+            (t
+             (values (default-definition-type (%car entry)) (%car entry) files))))))
+
+(defun def-source-entry.name (key entry)
+  (assert (not (null entry)))
+  (cond ((atom entry) key)
+        ((typep (%car entry) 'definition-type) key)
+        ((and (consp (%car entry)) (typep (%caar entry) 'definition-type))
+         (%cdar entry))
+        (t
+         (%car entry))))
+
+(defun def-source-entry.type (key entry)
+  (cond ((atom entry) (default-definition-type key))
+        ((typep (%car entry) 'definition-type) (%car entry))
+        ((and (consp (%car entry)) (typep (%caar entry) 'definition-type))
+         (%caar entry))
+        (t
+         (default-definition-type (%car entry)))))
+
+(defun def-source-entry.sources (key entry)
+  (declare (ignore key))
+  (cond ((consp entry)
+         (if (consp (%cdr entry)) (%cdr entry) (list (%cdr entry))))
+        (entry (list entry))
+        (t nil)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; 
+
+
+;; Some objects (specifically functions) have source location information associated with the
+;; object itself, in addition to any source locations associated with its definition.  This
+;; allows us to find source for, e.g., anonymous functions.
+(defgeneric get-object-sources (thing)
+  ;; returns a list of entries ((a-type . a-name) source . previous-sources)
+  (:method ((thing t)) nil)
+  (:method ((fn function))
+    (let ((source (function-source-note fn)))
+      (when source
+        (list (list* (cons *function-definition-type* (or (name-of fn) fn)) source nil)))))
+  (:method ((fn method-function))
+    (let ((source (function-source-note fn)))
+      (when source
+        (list (list* (cons *method-definition-type* (%method-function-method fn)) source nil)))))
+  (:method ((m method))
+    (get-object-sources (method-function m))))
+
+(defun find-definition-sources (name &optional (type t))
+  "Returns a list of entries ((a-type . a-name) source . previous-sources), where
+a-type is a subtype of TYPE, and a-name is either NAME or it's a special case of
+NAME (e.g. if NAME is the name of generic function, a-name could be a method of NAME).
+
+If NAME is not a cons or symbol, it's assumed to be an object (e.g. class or
+function) whose source location we try to heuristically locate, usually by looking up
+the sources of its name.
+
+If NAME is a method name and *DIRECT-METHODS-ONLY* is false, will also locate all
+applicable methods.
+
+The returned list is guaranteed freshly consed (ie suitable for nconc'ing)."
+
+  (let* ((dt-class (class-of (definition-type-instance type)))
+         (matches (get-object-sources name)))
+    (if matches
+      (setq matches (delete-if-not (lambda (info) (typep (caar info) dt-class)) matches))
+      ;; No intrinsic source info for the thing itself, look it up by name.
+      (let (seen-dts implicit-type implicit-dt-class implicit-name)
+        (typecase name
+          (method
+             (setq implicit-type 'method implicit-name name))
+          (method-function
+             (setq implicit-type 'method implicit-name (%method-function-method name)))
+          (function
+             (setq implicit-type 'function implicit-name (name-of name)))
+          (method-combination
+             (setq implicit-type 'method-combination implicit-name (name-of name)))
+          (package
+             (setq implicit-type 'package implicit-name (name-of name)))
+          (class
+             (setq implicit-type 'class implicit-name (name-of name)))
+          (t
+           (locally
+               (declare (ftype function xref-entry-p xref-entry-full-name xref-entry-type))
+             (if (and (find-class 'xref-entry nil)
+                      (xref-entry-p name))
+               (setq implicit-type (xref-entry-type name) implicit-name (xref-entry-full-name name))
+               (setq implicit-type t implicit-name name)))))
+        (setq implicit-dt-class (class-of (definition-type-instance implicit-type)))
+        (with-lock-grabbed (*source-files-lock*)
+          (loop for (nil . dt) in *definition-types*
+                when (and (typep dt dt-class) (typep dt implicit-dt-class) (not (memq dt seen-dts)))
+                  do (let* ((key (definition-base-name dt implicit-name))
+                            (all (%source-file-entries key)))
+                       (push dt seen-dts)
+                       (loop for entry in all
+                             when (and (eq dt (def-source-entry.type key entry))
+                                       (or (eq implicit-name key) ;; e.g. all methods on a gf
+                                           (definition-same-p dt implicit-name (def-source-entry.name key entry))))
+                               do (multiple-value-bind (type name files)
+                                      (decode-def-source-entry key entry)
+                                    (push (cons (cons type name) files) matches))))))))
+
+    ;; include indirect applicable methods.  Who uses this case?
+    (when (and (eq type 'method)
+               (not (typep name 'method))
+               (not *direct-methods-only*))
+      (multiple-value-bind (sym qualifiers specializers) (method-def-parameters name)
+        (when sym
+          (loop for m in (find-applicable-methods sym specializers qualifiers)
+                unless (definition-same-p *method-definition-type* m name)
+                  do (setq matches (nconc (find-definition-sources m 'method) matches))))))
+    matches))
+
+;;; backward compatibility
+
+;;; modified version of %method-applicable-p - args are class names
+;;; not instances
+(defun %my-method-applicable-p (method args cpls)
+  (do* ((specs (%method-specializers method) (%cdr specs))
+        (args args (%cdr args))
+        (cpls cpls (%cdr cpls)))
+      ((null args) t)
+    (let ((spec (%car specs))
+          (arg (%car args)))
+      (if (typep spec 'eql-specializer)
+        (if (consp arg)
+          (unless (eql (cadr arg) (eql-specializer-object spec))
+            (return nil))
+          (if (typep (eql-specializer-object spec) arg)
+            ;(unless (eq arg *null-class*) (return :undecidable))
+            t  ;; include if it's at all possible it might be applicable.
+            (return nil)))
+        (unless (memq spec (%car cpls))
+          (return nil))))))
+
+;;; modified version of %compute-applicable-methods*
+;;; omit errors and args are class names not instances
+;;; returns a new list.
+(defun find-applicable-methods (name args qualifiers)
+  (let ((gf (fboundp name)))
+    (when (and gf (typep gf 'standard-generic-function))
+      (let* ((methods (or (%gf-methods gf)
+                          (return-from find-applicable-methods nil)))
+             (arg-count (length (%method-specializers (car methods))))
+             (args-length (length args))
+             (bits (inner-lfun-bits gf))
+             res)
+        (unless (or (logbitp $lfbits-rest-bit bits)
+                    (logbitp $lfbits-restv-bit bits)
+                    (logbitp $lfbits-keys-bit bits)
+                    (<= args-length 
+                        (+ (ldb $lfbits-numreq bits) (ldb $lfbits-numopt bits))))
+                                        ;(error "Too many args for ~s" gf)
+          (return-from find-applicable-methods))
+        (when (< arg-count args-length)
+          (setq args (subseq args 0 (setq args-length arg-count))))
+        (setq args (mapcar (lambda (arg)
+                             (typecase arg
+                               (eql-specializer `(eql ,(eql-specializer-object arg)))
+                               (class arg)
+                               (symbol (or (find-class (or arg t) nil)
+                                           ;;(error "Invalid class name ~s" arg)
+                                           (return-from find-applicable-methods)))
+                               (t
+                                  (unless (and (consp arg) (eql (car arg) 'eql) (null (cddr arg)))
+                                    ;;(error "Invalid specializer ~s" arg)
+                                    (return-from find-applicable-methods))
+                                  arg)))
+                           args))
+        (let ((cpls (make-list args-length)))
+          (declare (dynamic-extent cpls))
+          (do ((args-tail args (cdr args-tail))
+               (cpls-tail cpls (cdr cpls-tail)))
+              ((null cpls-tail))
+            (declare (type list args-tail cpls-tail))
+            (let ((arg (car args-tail)))
+              (setf (car cpls-tail)
+                    (%class-precedence-list (if (consp arg)
+                                              (class-of (cadr arg))
+                                              arg)))))
+          (dolist (m methods)
+            (when (%my-method-applicable-p m args cpls)
+              (push m res)))
+          (let ((methods (sort-methods res cpls (%gf-precedence-list gf))))
+            (when (eq (generic-function-method-combination gf)
+                      *standard-method-combination*)
+                                        ; around* (befores) (afters) primaries*
+              (setq methods (compute-method-list methods))
+              (when methods
+                (setq methods
+                      (if (not (consp methods))
+                        (list methods)
+                        (let ((afters (cadr (member-if #'listp methods))))
+                          (when afters (nremove afters methods))
+                          (nconc
+                           (mapcan #'(lambda (x)(if (listp x) x (cons x nil)))
+                                   methods)
+                           afters))))))
+            (if (and qualifiers (neq qualifiers t))
+              (delete-if #'(lambda (m)(not (equal qualifiers (%method-qualifiers m))))
+                         methods)
+              methods)))))))
+
+;;; Do this just in case record source file doesn't remember the right
+;;; definition
+(defun methods-match-p (x y)  
+  (or (eq x y)
+      (and (typep x 'method)
+           (typep y 'method)
+           (equal (method-name x)
+                  (method-name y))
+           (equal (method-specializers x)
+                  (method-specializers y))
+           (equal (method-qualifiers x)
+                  (method-qualifiers y)))))
+
+(defun edit-definition-p (name &optional (type t)) ;exported
+  (let ((specs (get-source-files-with-types name type)))
+    (when (and (null specs)
+               (symbolp name))
+      (let* ((str (symbol-name name))
+             (len (length str)))
+        (when (and (> len 0) (memq (char str (1- len)) '(#\. #\, #\:)))
+          (let ((newsym (find-symbol (%substr str 0 (1- len)) (symbol-package name))))
+            (when newsym
+              (setq specs (get-source-files-with-types newsym type)))))))
+    specs))
+
+(defun get-source-files-with-types (name &optional (type t))
+  (let ((list (find-definition-sources name type)))
+    ;; Convert to old format, (type-or-name . file)
+    (loop for ((dt . full-name) . sources) in list
+          as spec = (if (eq full-name name) (definition-type-name dt) full-name)
+          nconc (mapcan (lambda (s)
+                          (when s (list (cons spec (source-note-filename s)))))
+                        sources))))
+
+
+;; For ilisp.
+(defun %source-files (name)
+  (let ((type-list ())
+        (meth-list ()))
+    (loop for ((dt . full-name) . sources) in (find-definition-sources name t)
+          as files = (mapcan #'(lambda (s)
+                                 (and s (setq s (source-note-filename s)) (list s)))
+                             sources)
+          when files
+            do (if (typep dt 'method-definition-type)
+                 (dolist (file files)
+                   (push (cons full-name file) meth-list))
+                 (push (cons (definition-type-name dt) files) type-list)))
+    (when meth-list
+      (push (cons 'method meth-list) type-list))
+    type-list))
+
+;; For CVS slime as of 11/15/2008.
+(defun get-source-files-with-types&classes (sym &optional (type t) classes qualifiers the-method)
+  (let* ((name (or the-method
+                   (and (or (eq type 'method) classes qualifiers)
+                        `(sym ,@qualifiers ,classes))
+                   sym)))
+    (get-source-files-with-types name type)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; record-source-file
+
+;; Returns nil if not a method/method name
+(defun method-def-parameters (m)
+  (when (typep m 'method-function)
+    (setq m (%method-function-method m)))
+  (if (typep m 'method)
+    (values (method-name m)
+            (method-qualifiers m)
+            (method-specializers m))
+    (let (name quals specs data last)
+      (when (consp m)
+        (when (eq (car m) :method) (setq m (cdr m)))
+        ;; (name spec1 .. specn) or (name qual1 .. qualn (spec1 ... specn))
+        (setq data (cdr m) last (last data))
+        (when (null (cdr last))
+          (setq last (car last))
+          (if (and (listp last) (neq (car last) 'eql))
+            (setq quals (butlast data) specs last)
+            (setq specs data))
+          (setq name (car m))
+          (when (and (or (non-nil-symbol-p name) (setf-function-name-p name))
+                     (every #'(lambda (q) (not (listp q))) quals)
+                     (every #'(lambda (s)
+                                (or (non-nil-symbol-p s)
+                                    (classp s)
+                                    (and (consp s)
+                                         (consp (cdr s))
+                                        (null (cddr s))
+                                         (eq (car s) 'eql))))
+                            specs))
+            (values name quals specs)))))))
+
+(defmethod record-definition-source ((dt definition-type) name source)
+  (let* ((key (definition-base-name dt name))
+         (all (%source-file-entries key))
+         (e-loc nil)
+         (e-files nil))
+    (loop for ptr on all as entry = (car ptr)
+          do (when (and (eq dt (def-source-entry.type key entry))
+                        (definition-same-p dt name (def-source-entry.name key entry)))
+               (setq e-files (def-source-entry.sources key entry))
+               (let ((old (flet ((same-file (x y)
+                                   (setq x (source-note-filename x))
+                                   (setq y (source-note-filename y))
+                                   (or (equal x y)
+                                       (and x
+                                            y
+                                            (or (stringp x) (pathnamep x))
+                                            (or (stringp y) (pathnamep y))
+                                            (equal
+                                             (or (probe-file x) (full-pathname x))
+                                             (or (probe-file y) (full-pathname y)))))))
+                            (member source e-files :test #'same-file))))
+                 (when (and old (neq source (car e-files))) ;; move to front
+                   (setq e-files (cons source (remove (car old) e-files :test #'eq)))))
+               (return (setq e-loc ptr))))
+    (unless (and e-files (eq source (car e-files)))
+      ;; Never previously defined in this file
+      (when (and (car e-files)            ; don't warn if last defined interactively
+                 *warn-if-redefine*
+                 (definition-bound-p dt name))
+        (warn "~A ~S previously defined in: ~A is now being redefined in: ~A~%"
+              (definition-type-name dt)
+              name
+              (source-note-filename (car e-files))
+              (or (source-note-filename source) "{No file}")))
+      (setq e-files (cons source e-files)))
+    (let ((entry (make-def-source-entry key dt name e-files)))
+      (if e-loc
+        (setf (car e-loc) entry)
+        (push entry all))
+      (%set-source-file-entries key all))
+    name))
+
+(defmethod record-definition-source ((dt method-definition-type) (m method) source)
+  ;; In cases of non-toplevel method definitions, as in the expansion of defgeneric,
+  ;; the method function note has more specific info than *loading-toplevel-location*.
+  (call-next-method dt m (or (function-source-note (method-function m)) source)))
+
+;;; avoid hanging onto beezillions of pathnames
+(defparameter *last-back-translated-name* (cons nil nil))
+
+;; Define the real record-source-file, which will be the last defn handled by the
+;; bootstrapping record-source-file, so convert all queued up data right afterwards.
+(progn
+
+(defun record-source-file (name def-type &optional (source (or *loading-toplevel-location*
+                                                               *loading-file-source-file*)))
+  (when (and source *record-source-file*)
+    (with-lock-grabbed (*source-files-lock*)
+      (let ((file-name (source-note-filename source)))
+        (when file-name
+          (unless (equalp file-name (car *last-back-translated-name*))
+            (setf (car *last-back-translated-name*) file-name)
+            (setf (cdr *last-back-translated-name*)
+                  (if (physical-pathname-p file-name)
+                    (namestring (back-translate-pathname file-name))
+                    file-name)))
+          (setq file-name (cdr *last-back-translated-name*))
+          (if (source-note-p source)
+            (setf (source-note-filename source) file-name)
+            (setq source file-name))))
+      (when (eq def-type 't) (report-bad-arg def-type '(not (eql t))))
+      (record-definition-source (definition-type-instance def-type
+                                    :if-does-not-exist :create)
+                                name
+                                source))))
+
+;; Collect level-0 source file info
+(do-all-symbols (s)
+  (let ((f (get s 'bootstrapping-source-files)))
+    (when f
+      (if (consp f)
+        (destructuring-bind ((type . source)) f
+          (when source (record-source-file s type source)))
+        (record-source-file s 'function f))
+      (remprop s 'bootstrapping-source-files))))
+
+;; Collect level-1 source file info
+(when (consp *record-source-file*)
+  (let ((list (nreverse (shiftf *record-source-file* t))))
+    (while list
+      (apply #'record-source-file (pop list)))))
+)
Index: /branches/new-random/lib/streams.lisp
===================================================================
--- /branches/new-random/lib/streams.lisp	(revision 13309)
+++ /branches/new-random/lib/streams.lisp	(revision 13309)
@@ -0,0 +1,192 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; streams.lisp
+;;;General io-functions
+
+(in-package "CCL")
+
+(eval-when (:execute :compile-toplevel)
+  (require :level-2)
+  (require :streams)
+  (require :backquote)
+
+  )
+
+
+
+
+
+
+(defun read-line (&optional input-stream (eof-error-p t) eof-value recursive-p)
+  
+  (declare (ignore recursive-p)
+           (optimize (speed 3)))
+  (let* ((input-stream (designated-input-stream input-stream)))
+    (multiple-value-bind (string eof)
+        (if (typep input-stream 'basic-stream)
+          (let* ((ioblock (basic-stream-ioblock input-stream)))
+            (with-ioblock-input-locked (ioblock)
+               (funcall (ioblock-read-line-function ioblock) ioblock)))
+          (stream-read-line input-stream))
+      (if eof
+	(if (= (length string) 0)
+	  (if eof-error-p
+	    (signal-eof-error input-stream)
+	    (values eof-value t))
+	  (values string t))
+	(values string nil)))))
+
+(eval-when (:compile-toplevel)
+  (declaim (inline read-char-internal)))
+
+(defun read-char-internal (input-stream eof-error-p eof-value)
+  (declare (optimize (speed 3) (space 0)))
+  (check-eof
+   (if (or (typep input-stream 'basic-stream)
+           (typep (setq input-stream (designated-input-stream input-stream))
+                  'basic-stream))
+     (let* ((ioblock (basic-stream-ioblock input-stream)))
+       (funcall (ioblock-read-char-function ioblock) ioblock))
+     (stream-read-char input-stream))
+   input-stream eof-error-p eof-value))
+
+(defun read-char (&optional input-stream (eof-error-p t) eof-value recursive-p)
+  (declare (ignore recursive-p))
+  (read-char-internal input-stream eof-error-p eof-value))
+
+(defun unread-char (char &optional input-stream)
+  (let* ((input-stream (designated-input-stream input-stream)))
+    (if (typep input-stream 'basic-stream)
+      (let* ((ioblock (basic-stream-ioblock input-stream)))
+        (funcall (ioblock-unread-char-function ioblock) ioblock char))
+      (stream-unread-char input-stream char))
+    nil))
+
+(defun peek-char (&optional peek-type input-stream
+                            (eof-error-p t) eof-value recursive-p)
+  (declare (ignore recursive-p))
+  (let* ((input-stream (designated-input-stream input-stream)))
+    (cond ((null peek-type)
+           (check-eof (stream-peek-char input-stream) input-stream eof-error-p eof-value))
+          (t
+           (do* ((value (stream-peek-char input-stream) (stream-peek-char input-stream)))
+                ((eq value :eof)
+                 (return (check-eof value input-stream eof-error-p eof-value)))
+             (if (eq peek-type t)
+               (unless (whitespacep value)
+                 (return value))
+               (if (characterp peek-type)
+                 (if (eql peek-type value)
+                   (return value))
+                 (report-bad-arg peek-type '(or character (member nil t)))))
+             (stream-read-char input-stream))))))
+
+(defun read-char-no-hang (&optional input-stream (eof-error-p t) eof-value recursive-p)
+  (declare (ignore recursive-p))
+  (setq input-stream (designated-input-stream input-stream))
+  (check-eof (stream-read-char-no-hang input-stream) input-stream eof-error-p eof-value))
+
+(defun read-byte (stream &optional (eof-error-p t) eof-value)
+  (declare (optimize (speed 3) (space 0)))
+  (if (typep stream 'basic-stream)
+    (let* ((ioblock (basic-stream-ioblock stream)))
+      (check-eof (funcall (ioblock-read-byte-function ioblock) ioblock)
+                 stream
+                 eof-error-p
+                 eof-value))
+    (check-eof
+     (stream-read-byte stream)
+     stream
+     eof-error-p
+     eof-value)))
+
+;;;;;;;;;;;; OUTPUT STREAMS
+
+(defun clear-output (&optional stream)
+  (let* ((stream (real-print-stream stream)))
+    (stream-clear-output stream)
+    nil))
+
+(defun finish-output (&optional stream)
+  (let* ((stream (real-print-stream stream)))
+    (stream-finish-output stream)
+    nil))
+
+
+
+(defun line-length (stream)
+  (declare (ignore stream))
+  80)
+
+(defun write-byte (byte stream)
+  (declare (optimize (speed 3) (space 0)))
+  "Write one byte, BYTE, to STREAM."
+  (if (typep stream 'basic-stream)
+    (let* ((ioblock (basic-stream-ioblock stream)))
+      (funcall (ioblock-write-byte-function ioblock) ioblock byte))
+    (stream-write-byte stream byte))
+  byte)
+
+
+;;;General stream functions
+
+
+
+(defmacro with-open-stream ((var stream) &body body &aux (svar (gensym)))
+  "Perform a series of operations on stream, return a value, and then
+close the stream.  VAR is bound to the value of STREAM, and then BODY is
+executed as an implicit progn. STREAM is automatically closed on exit
+from with-open-stream, no matter whether the exit is normal or abnormal.
+The stream has dynamic extent; its extent ends when the form is exited."
+  `(let (,svar)
+     (unwind-protect
+       (let ((,var (setq ,svar ,stream)))
+         ,@body)
+       (when ,svar (close ,svar)))))
+
+
+
+
+;;
+
+;;; from i/o chapter of steele
+;;; Ever notice that -much- of this code is from the i/o chapter
+;;; of steele ?  Strange but true ...
+
+(defun read-from-string (string &optional (eof-error-p t) eof-value
+                                &key (start 0) end preserve-whitespace
+                                &aux idx)
+  "The characters of string are successively given to the lisp reader
+   and the lisp object built by the reader is returned. Macro chars
+   will take effect."
+  (values
+   (with-input-from-string (stream string :index idx :start start :end end)
+     (if preserve-whitespace
+       (read-preserving-whitespace stream eof-error-p eof-value)
+       (read stream eof-error-p eof-value)))
+   idx))
+
+
+;;;File Stuff here
+
+(defun dribble (&optional filename)
+  "With a file name as an argument, dribble opens the file and sends a
+     record of further I/O to that file. Without an argument, it closes
+     the dribble file, and quits logging."
+  (process-dribble *current-process* filename))
+
Index: /branches/new-random/lib/systems.lisp
===================================================================
--- /branches/new-random/lib/systems.lisp	(revision 13309)
+++ /branches/new-random/lib/systems.lisp	(revision 13309)
@@ -0,0 +1,216 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; module-name       binary                    (source . files-depends-on)
+;;; -----------       ------                    ---------------------------
+(defparameter *ccl-system*
+  '(
+    (level-1          "ccl:ccl;level-1"          ("ccl:l1;level-1.lisp"))
+    (runtime          "ccl:ccl;runtime"          ("ccl:l1;runtime.lisp"))
+    (level-1-test     "ccl:level-1-test"         ("ccl:l1;level-1-test.lisp"))
+    (l1-cl-package    "ccl:l1f;l1-cl-package"    ("ccl:l1;l1-cl-package.lisp"))
+    (l1-utils         "ccl:l1f;l1-utils"         ("ccl:l1;l1-utils.lisp"))
+    (l1-numbers       "ccl:l1f;l1-numbers"       ("ccl:l1;l1-numbers.lisp"))
+    (l1-init          "ccl:l1f;l1-init"          ("ccl:l1;l1-init.lisp"))
+    (version          "ccl:l1f;version"          ("ccl:l1;version.lisp"))
+    (l1-boot-1        "ccl:l1f;l1-boot-1"        ("ccl:l1;l1-boot-1.lisp"))
+    (l1-boot-2        "ccl:l1f;l1-boot-2"        ("ccl:l1;l1-boot-2.lisp"))
+    (l1-boot-3        "ccl:l1f;l1-boot-3"        ("ccl:l1;l1-boot-3.lisp"))
+    (l1-boot-lds      "ccl:l1f;l1-boot-lds"      ("ccl:l1;l1-boot-lds.lisp"))
+    (l1-files         "ccl:l1f;l1-files"         ("ccl:l1;l1-files.lisp"))
+    (l1-sort          "ccl:l1f;l1-sort"          ("ccl:l1;l1-sort.lisp"))
+    (l1-dcode         "ccl:l1f;l1-dcode"         ("ccl:l1;l1-dcode.lisp"))
+    (l1-clos-boot     "ccl:l1f;l1-clos-boot"    ("ccl:l1;l1-clos-boot.lisp"))
+    (l1-clos          "ccl:l1f;l1-clos"          ("ccl:l1;l1-clos.lisp"))
+    (l1-io            "ccl:l1f;l1-io"            ("ccl:l1;l1-io.lisp"))
+    (l1-unicode       "ccl:l1f;l1-unicode"       ("ccl:l1;l1-unicode.lisp"))
+    
+    (l1-streams       "ccl:l1f;l1-streams"       ("ccl:l1;l1-streams.lisp"))
+    (l1-events        "ccl:l1f;l1-events"        ("ccl:l1;l1-events.lisp"))
+    (ppc-trap-support "ccl:l1f;ppc-trap-support" ("ccl:l1;ppc-trap-support.lisp"))
+    (x86-trap-support "ccl:l1f;x86-trap-support" ("ccl:l1;x86-trap-support.lisp"))
+
+    (l1-format        "ccl:l1f;l1-format"        ("ccl:l1;l1-format.lisp"))
+    (l1-readloop      "ccl:l1f;l1-readloop"      ("ccl:l1;l1-readloop.lisp"))
+    (l1-readloop-lds  "ccl:l1f;l1-readloop-lds"  ("ccl:l1;l1-readloop-lds.lisp"))
+    (l1-reader        "ccl:l1f;l1-reader"        ("ccl:l1;l1-reader.lisp"))
+    (l1-error-system  "ccl:l1f;l1-error-system"  ("ccl:l1;l1-error-system.lisp"))
+    (ppc-error-signal "ccl:l1f;ppc-error-signal" ("ccl:l1;ppc-error-signal.lisp"))
+    (x86-error-signal "ccl:l1f;x86-error-signal" ("ccl:l1;x86-error-signal.lisp"))    
+    (l1-error-signal  "ccl:l1f;l1-error-signal"  ("ccl:l1;l1-error-signal.lisp"))
+    (l1-aprims        "ccl:l1f;l1-aprims"        ("ccl:l1;l1-aprims.lisp"))
+    (l1-callbacks     "ccl:l1f;l1-callbacks"    ("ccl:l1;l1-callbacks.lisp"))
+    (ppc-callback-support "ccl:l1f;ppc-callback-support" ("ccl:l1;ppc-callback-support.lisp"))
+    (x86-callback-support "ccl:l1f;x86-callback-support" ("ccl:l1;x86-callback-support.lisp"))    
+    (l1-sysio         "ccl:l1f;l1-sysio"         ("ccl:l1;l1-sysio.lisp"))
+    (l1-symhash       "ccl:l1f;l1-symhash"       ("ccl:l1;l1-symhash.lisp"))
+    (l1-pathnames     "ccl:l1f;l1-pathnames"     ("ccl:l1;l1-pathnames.lisp"))
+    (l1-lisp-threads  "ccl:l1f;l1-lisp-threads"  ("ccl:l1;l1-lisp-threads.lisp"))
+    (l1-sockets       "ccl:l1f;l1-sockets"       ("ccl:l1;l1-sockets.lisp"))
+    (ppc-threads-utils "ccl:l1f;ppc-threads-utils" ("ccl:l1;ppc-threads-utils.lisp"))
+    (x86-threads-utils "ccl:l1f;x86-threads-utils" ("ccl:l1;x86-threads-utils.lisp"))
+    (l1-application   "ccl:l1f;l1-application"   ("ccl:l1;l1-application.lisp"))
+    (l1-processes     "ccl:l1f;l1-processes"     ("ccl:l1;l1-processes.lisp"))
+
+    (l1-typesys       "ccl:l1f;l1-typesys"       ("ccl:l1;l1-typesys.lisp"))
+    (sysutils         "ccl:l1f;sysutils"         ("ccl:l1;sysutils.lisp"))
+    (nx               "ccl:l1f;nx"               ("ccl:compiler;nx.lisp"
+                                                  "ccl:compiler;nx0.lisp"
+                                                  "ccl:compiler;lambda-list.lisp"
+                                                  "ccl:compiler;nx-basic.lisp"
+                                                  "ccl:compiler;nx1.lisp"))
+    (nxenv            "ccl:bin;nxenv"            ("ccl:compiler;nxenv.lisp"))
+    (nx2              "ccl:bin;nx2"              ("ccl:compiler;nx2.lisp"))
+    (nx-base-app      "ccl:l1f;nx-base-app"      ("ccl:compiler;nx-base-app.lisp"
+                                                  "ccl:compiler;lambda-list.lisp"))
+    (dll-node         "ccl:bin;dll-node"         ("ccl:compiler;dll-node.lisp"))
+    (ppc32-arch       "ccl:bin;ppc32-arch"       ("ccl:compiler;PPC;PPC32;ppc32-arch.lisp"))
+    (ppc-arch         "ccl:bin;ppc-arch"         ("ccl:compiler;PPC;ppc-arch.lisp"))
+    (x86-arch         "ccl:bin;x86-arch"         ("ccl:compiler;X86;x86-arch.lisp"))
+    (ppc64-arch       "ccl:bin;ppc64-arch"       ("ccl:compiler;PPC;PPC64;ppc64-arch.lisp"))
+    (x8632-arch       "ccl:bin;x8632-arch"       ("ccl:compiler;X86;X8632;x8632-arch.lisp"))
+    (x8664-arch       "ccl:bin;x8664-arch"       ("ccl:compiler;X86;X8664;x8664-arch.lisp"))
+    (arch             "ccl:bin;arch"             ("ccl:compiler;arch.lisp"))
+    (ppcenv           "ccl:bin;ppcenv"           ("ccl:lib;ppcenv.lisp"))
+    (x8664env         "ccl:bin;x8664env"         ("ccl:lib;x8664env.lisp"))
+    (x8632env         "ccl:bin;x8632env"         ("ccl:lib;x8632env.lisp"))
+    (vreg             "ccl:bin;vreg"             ("ccl:compiler;vreg.lisp"))
+    (ppc-asm          "ccl:bin;ppc-asm"          ("ccl:compiler;PPC;ppc-asm.lisp"))
+    (x86-asm          "ccl:bin;x86-asm"          ("ccl:compiler;X86;x86-asm.lisp"))
+    (vinsn            "ccl:bin;vinsn"            ("ccl:compiler;vinsn.lisp"))
+    (ppc32-vinsns     "ccl:bin;ppc32-vinsns"     ("ccl:compiler;PPC;PPC32;ppc32-vinsns.lisp"))
+    (ppc64-vinsns     "ccl:bin;ppc64-vinsns"     ("ccl:compiler;PPC;PPC64;ppc64-vinsns.lisp"))
+    (x8632-vinsns     "ccl:bin;x8632-vinsns"     ("ccl:compiler;X86;X8632;x8632-vinsns.lisp"))
+    (x8664-vinsns     "ccl:bin;x8664-vinsns"     ("ccl:compiler;X86;X8664;x8664-vinsns.lisp"))
+    (reg              "ccl:bin;reg"              ("ccl:compiler;reg.lisp"))
+    (subprims         "ccl:bin;subprims"         ("ccl:compiler;subprims.lisp"))
+    (risc-lap         "ccl:bin;risc-lap"         ("ccl:compiler;risc-lap.lisp"))
+    (ppc-lap          "ccl:bin;ppc-lap"          ("ccl:compiler;PPC;ppc-lap.lisp"))
+    (x86-lap          "ccl:bin;x86-lap"          ("ccl:compiler;X86;x86-lap.lisp"))
+    (backend          "ccl:bin;backend"          ("ccl:compiler;backend.lisp"))
+    (ppc32-backend    "ccl:bin;ppc32-backend"    ("ccl:compiler;PPC;PPC32;ppc32-backend.lisp"))			   
+    (ppc64-backend    "ccl:bin;ppc64-backend"    ("ccl:compiler;PPC;PPC64;ppc64-backend.lisp"))
+    (ppc-backend      "ccl:bin;ppc-backend"      ("ccl:compiler;PPC;ppc-backend.lisp"))
+    (x8632-backend    "ccl:bin;x8632-backend"    ("ccl:compiler;X86;X8632;x8632-backend.lisp"))
+    (x8664-backend    "ccl:bin;x8664-backend"    ("ccl:compiler;X86;X8664;x8664-backend.lisp"))
+    (x86-backend      "ccl:bin;x86-backend"      ("ccl:compiler;X86;x86-backend.lisp"))
+    (ppc2             "ccl:bin;ppc2"             ("ccl:compiler;PPC;ppc2.lisp"))
+    (x862             "ccl:bin;x862"             ("ccl:compiler;X86;x862.lisp"))
+
+    (ppc-lapmacros    "ccl:bin;ppc-lapmacros"    ("ccl:compiler;PPC;ppc-lapmacros.lisp"))
+    (x86-lapmacros    "ccl:bin;x86-lapmacros"    ("ccl:compiler;X86;x86-lapmacros.lisp"))
+    (ppc-disassemble  "ccl:bin;ppc-disassemble"  ("ccl:compiler;PPC;ppc-disassemble.lisp"))
+    (x86-disassemble  "ccl:bin;x86-disassemble"  ("ccl:compiler;X86;x86-disassemble.lisp"))
+    (xfasload         "ccl:xdump;xfasload"       ("ccl:xdump;xfasload.lisp"))
+    (xppcfasload      "ccl:xdump;xppcfasload"    ("ccl:xdump;xppcfasload.lisp"))
+    (xx8632fasload    "ccl:xdump;xx8632-fasload"  ("ccl:xdump;xx8632-fasload.lisp"))
+    (xx8664fasload    "ccl:xdump;xx8664-fasload"  ("ccl:xdump;xx8664-fasload.lisp"))
+    (heap-image       "ccl:xdump;heap-image"     ("ccl:xdump;heap-image.lisp"))
+    (xsym             "ccl:xdump;xsym"           ("ccl:xdump;xsym.lisp"))
+    (number-macros "ccl:bin;number-macros"    ("ccl:lib;number-macros.lisp"))
+    (number-case-macro  "ccl:bin;number-case-macro" ("ccl:lib;number-case-macro.lisp"))
+    (optimizers       "ccl:bin;optimizers"       ("ccl:compiler;optimizers.lisp")) 
+    (backquote        "ccl:bin;backquote"        ("ccl:lib;backquote.lisp"))
+    (lispequ          "ccl:library;lispequ"      ("ccl:library;lispequ.lisp"))
+    (sysequ           "ccl:bin;sysequ"           ("ccl:lib;sysequ.lisp"))
+    (toolequ          "ccl:bin;toolequ"          ("ccl:lib;toolequ.lisp"))
+    (level-2          "ccl:bin;level-2"          ("ccl:lib;level-2.lisp"))
+    (macros           "ccl:bin;macros"           ("ccl:lib;macros.lisp"))
+    (defstruct-macros "ccl:bin;defstruct-macros" ("ccl:lib;defstruct-macros.lisp"))
+    (foreign-types    "ccl:bin;foreign-types"    ("ccl:lib;foreign-types.lisp"))
+    (ffi-linuxppc32   "ccl:bin;ffi-linuxppc32"   ("ccl:lib;ffi-linuxppc32.lisp"))
+    (ffi-darwinppc32  "ccl:bin;ffi-darwinppc32"  ("ccl:lib;ffi-darwinppc32.lisp"))
+    (ffi-darwinppc64  "ccl:bin;ffi-darwinppc64"  ("ccl:lib;ffi-darwinppc64.lisp"))
+    (ffi-linuxppc64   "ccl:bin;ffi-linuxppc64"   ("ccl:lib;ffi-linuxppc64.lisp"))
+    (ffi-darwinx8632  "ccl:bin;ffi-darwinx8632"  ("ccl:lib;ffi-darwinx8632.lisp"))
+    (ffi-linuxx8664   "ccl:bin;ffi-linuxx8664"   ("ccl:lib;ffi-linuxx8664.lisp"))
+    (ffi-darwinx8664  "ccl:bin;ffi-darwinx8664"  ("ccl:lib;ffi-darwinx8664.lisp"))
+    (ffi-freebsdx8664 "ccl:bin;ffi-freebsdx8664" ("ccl:lib;ffi-freebsdx8664.lisp"))
+    (ffi-solarisx8664 "ccl:bin;ffi-solarisx8664" ("ccl:lib;ffi-solarisx8664.lisp"))
+    (ffi-win64 "ccl:bin;ffi-win64" ("ccl:lib;ffi-win64.lisp"))
+    (ffi-linuxx8632  "ccl:bin;ffi-linuxx8632" ("ccl:lib;ffi-linuxx8632.lisp"))
+    (ffi-win32 "ccl:bin;ffi-win32" ("ccl:lib;ffi-win32.lisp"))
+    (ffi-solarisx8632 "ccl:bin;ffi-solarisx8632" ("ccl:lib;ffi-solarisx8632.lisp"))
+    (ffi-freebsdx8632 "ccl:bin;ffi-freebsdx8632" ("ccl:lib;ffi-freebsdx8632.lisp"))
+    
+    (db-io            "ccl:bin;db-io"            ("ccl:lib;db-io.lisp"))
+    (hash             "ccl:bin;hash"             ("ccl:lib;hash.lisp"))
+    (nfcomp           "ccl:bin;nfcomp"           ("ccl:lib;nfcomp.lisp"))
+    (lists            "ccl:bin;lists"            ("ccl:lib;lists.lisp"))
+    (chars            "ccl:bin;chars"            ("ccl:lib;chars.lisp"))
+    (streams          "ccl:bin;streams"          ("ccl:lib;streams.lisp"))
+    (pathnames        "ccl:bin;pathnames"        ("ccl:lib;pathnames.lisp"))
+    (describe         "ccl:bin;describe"         ("ccl:lib;describe.lisp")) 
+    (mcl-compat       "ccl:bin;mcl-compat"       ("ccl:lib;mcl-compat.lisp"))
+    (backtrace        "ccl:bin;backtrace"        ("ccl:lib;backtrace.lisp"))
+    (ppc-backtrace    "ccl:bin;ppc-backtrace"    ("ccl:lib;ppc-backtrace.lisp"))
+    (x86-backtrace    "ccl:bin;x86-backtrace"    ("ccl:lib;x86-backtrace.lisp"))
+    (x86-watch        "ccl:bin;x86-watch"        ("ccl:lib;x86-watch.lisp"))
+    (backtrace-lds    "ccl:bin;backtrace-lds"    ("ccl:lib;backtrace-lds.lisp"))
+    (apropos          "ccl:bin;apropos"          ("ccl:lib;apropos.lisp"))
+    (numbers          "ccl:bin;numbers"          ("ccl:lib;numbers.lisp"))
+    (dumplisp         "ccl:bin;dumplisp"         ("ccl:lib;dumplisp.lisp"))
+    (defstruct        "ccl:bin;defstruct"        ("ccl:lib;defstruct.lisp"
+                                                  "ccl:lib;defstruct-macros.lisp"))
+    (defstruct-lds    "ccl:bin;defstruct-lds"    ("ccl:lib;defstruct-lds.lisp"
+                                                  "ccl:lib;defstruct-macros.lisp"))
+    (method-combination
+     "ccl:bin;method-combination"
+     ("ccl:lib;method-combination.lisp"))
+    (encapsulate      "ccl:bin;encapsulate"      ("ccl:lib;encapsulate.lisp"))
+    (read             "ccl:bin;read"           ("ccl:lib;read.lisp"))
+    (misc             "ccl:bin;misc"           ("ccl:lib;misc.lisp"))
+    (arrays-fry       "ccl:bin;arrays-fry"     ("ccl:lib;arrays-fry.lisp"))
+    (sequences        "ccl:bin;sequences"      ("ccl:lib;sequences.lisp"))
+    (sort             "ccl:bin;sort"           ("ccl:lib;sort.lisp"))
+    (setf             "ccl:bin;setf"           ("ccl:lib;setf.lisp"))
+    (setf-runtime     "ccl:bin;setf-runtime"   ("ccl:lib;setf-runtime.lisp"))
+    (format           "ccl:bin;format"         ("ccl:lib;format.lisp"))
+    (case-error       "ccl:bin;case-error"     ("ccl:lib;case-error.lisp"))
+    (pprint           "ccl:bin;pprint"         ("ccl:lib;pprint.lisp"))
+    (time             "ccl:bin;time"           ("ccl:lib;time.lisp"))
+    (print-db         "ccl:bin;print-db"       ("ccl:lib;print-db.lisp"))
+; (eval             "ccl:bin;eval"           ("ccl:lib;eval.lisp"))
+
+    (arglist          "ccl:bin;arglist"          ("ccl:lib;arglist.lisp"))
+
+    (edit-callers	   "ccl:bin;edit-callers"   ("ccl:lib;edit-callers.lisp"))
+    ;; (hash-cons        "ccl:library;hash-cons"    ("ccl:library;hash-cons.lisp"))
+    ;; (step             "ccl:bin;step"           ("ccl:lib;step.lisp"))
+    (ccl-export-syms  "ccl:bin;ccl-export-syms"  ("ccl:lib;ccl-export-syms.lisp"))
+    (systems          "ccl:bin;systems"        ("ccl:lib;systems.lisp"))
+    (compile-ccl      "ccl:bin;compile-ccl"    ("ccl:lib;compile-ccl.lisp"))
+    (ppc-init-ccl     "ccl:bin;ppc-init-ccl"   ("ccl:lib;ppc-init-ccl.lisp"))
+    (distrib-inits    "ccl:bin;distrib-inits"  ("ccl:lib;distrib-inits.lisp"))
+    (lisp-package     "ccl:library;lisp-package" ("ccl:library;lisp-package.lisp"))
+    ;; need to add swapping, xdump to CCL's *module-search-path*
+    (xdump            "ccl:xdump;xdump"          ("ccl:xdump;xdump.lisp"))
+    (fasload          "ccl:xdump;fasload"        ("ccl:xdump;fasload.lisp"))
+    (loop             "ccl:library;loop"         ("ccl:library;loop.lisp"))
+    (linux-files      "ccl:l1f;linux-files"      ("ccl:level-1;linux-files.lisp"))
+    (source-files     "ccl:bin;source-files"     ("ccl:lib;source-files.lisp"))
+    (cover            "ccl:bin;cover"            ("ccl:library;cover.lisp"))
+    (leaks            "ccl:bin;leaks"            ("ccl:library;leaks.lisp"))
+    (core-files       "ccl:bin;core-files"       ("ccl:library;core-files.lisp"))
+ 
+    (prepare-mcl-environment "ccl:bin;prepare-mcl-environment" ("ccl:lib;prepare-mcl-environment.lisp"))
+    (defsystem        "ccl:tools;defsystem"      ("ccl:tools;defsystem.lisp"))
+    (asdf             "ccl:tools;asdf"	    ("ccl:tools;asdf.lisp"))
+    (jp-encode        "ccl:bin;jp-encode"        ("ccl:library;jp-encode.lisp"))))
+
Index: /branches/new-random/lib/time.lisp
===================================================================
--- /branches/new-random/lib/time.lisp	(revision 13309)
+++ /branches/new-random/lib/time.lisp	(revision 13309)
@@ -0,0 +1,265 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (defconstant seconds-in-week (* 60 60 24 7))
+  (defconstant weeks-offset 2145)
+  (defconstant seconds-offset 432000)
+  (defconstant minutes-per-day (* 24 60))
+  (defconstant quarter-days-per-year (1+ (* 365 4)))
+  (defconstant quarter-days-per-century 146097)
+  (defconstant november-17-1858 678882)
+  (defconstant weekday-november-17-1858 2)
+)
+
+(defun gctime ()
+  (let* ((timeval-size (record-length :timeval)))
+    (%stack-block ((copy (* timeval-size 5)))
+      (#_memmove copy *total-gc-microseconds* (* timeval-size 5))
+      (macrolet ((funk (arg)
+                   (ecase internal-time-units-per-second 
+                    (1000000 `(timeval->microseconds ,arg))
+                    (1000 `(timeval->milliseconds ,arg)))))
+        (values
+         (funk copy)
+         (funk (%incf-ptr copy timeval-size))
+         (funk (%incf-ptr copy timeval-size))
+         (funk (%incf-ptr copy timeval-size))
+         (funk (%incf-ptr copy timeval-size)))))))
+
+
+
+
+;;; This should stop using #_localtime_r: not all times can be represented
+;;; as a signed natural offset from the start of Unix time.
+;;; For now, if the time won't fit in a :time_t, use an arbitrary time
+;;; value to get the time zone and assume that DST was -not- in effect.
+#-windows-target
+(defun get-timezone (time)
+  (let* ((toobig (not (typep time '(signed-byte
+                                    #+32-bit-target 32
+                                    #+64-bit-target 64)))))
+    (when toobig
+      (setq time 0))
+    (rlet ((when :time_t)
+           (tm :tm))
+      (setf (pref when :time_t) time)
+      (with-macptrs ((ltm (#_localtime_r when tm)))
+        (if (%null-ptr-p ltm)
+          (values 0 nil)
+          (progn
+            (values (floor #-solaris-target (pref tm :tm.tm_gmtoff)
+                           #+solaris-target #&altzone
+                           -60)
+                    (unless toobig (not (zerop (pref tm :tm.tm_isdst)))))))))))
+
+#+windows-target
+(defun get-timezone (time)
+  (declare (ignore time))
+  (rlet ((tzinfo #>TIME_ZONE_INFORMATION))
+    (let* ((id (#_GetTimeZoneInformation tzinfo))
+           (minutes-west (pref tzinfo #>TIME_ZONE_INFORMATION.Bias))
+           (is-dst (= id #$TIME_ZONE_ID_DAYLIGHT)))
+      (values (floor (+ minutes-west
+                        (if is-dst
+                          (pref tzinfo #>TIME_ZONE_INFORMATION.DaylightBias)
+                          0)))
+              is-dst))))
+
+
+
+(defun decode-universal-time (universal-time &optional time-zone)
+  "Converts a universal-time to decoded time format returning the following
+   nine values: second, minute, hour, date, month, year, day of week (0 =
+   Monday), T (daylight savings time) or NIL (standard time), and timezone.
+   Completely ignores daylight-savings-time when time-zone is supplied."
+  (multiple-value-bind (weeks secs)
+		       (truncate (+ universal-time seconds-offset)
+				 seconds-in-week)
+    (let* ((weeks (+ weeks weeks-offset))
+	   (second NIL)
+	   (minute NIL)
+	   (hour NIL)
+	   (date NIL)
+	   (month NIL)
+	   (year NIL)
+	   (day NIL)
+	   (daylight NIL)
+	   (timezone (if (null time-zone)
+			 (multiple-value-bind
+			     (minwest dst)
+			     (get-timezone (- universal-time
+					      unix-to-universal-time))
+			   (setf daylight dst)
+			   minwest)
+			 (* time-zone 60))))
+      (declare (fixnum timezone))
+      (multiple-value-bind (t1 seconds) (truncate secs 60)
+	(setq second seconds)
+	(setq t1 (- t1 timezone))
+	(let* ((tday (if (< t1 0)
+			 (1- (truncate (1+ t1) minutes-per-day))
+			 (truncate t1 minutes-per-day))))
+	  (multiple-value-setq (hour minute)
+	    (truncate (- t1 (* tday minutes-per-day)) 60))
+	  (let* ((t2 (1- (* (+ (* weeks 7) tday november-17-1858) 4)))
+		 (tcent (truncate t2 quarter-days-per-century)))
+	    (setq t2 (mod t2 quarter-days-per-century))
+	    (setq t2 (+ (- t2 (mod t2 4)) 3))
+	    (setq year (+ (* tcent 100) (truncate t2 quarter-days-per-year)))
+	    (let ((days-since-mar0 (1+ (truncate (mod t2 quarter-days-per-year)
+						 4))))
+	      (setq day (mod (+ tday weekday-november-17-1858) 7))
+	      (let ((t3 (+ (* days-since-mar0 5) 456)))
+		(cond ((>= t3 1989)
+		       (setq t3 (- t3 1836))
+		       (setq year (1+ year))))
+		(multiple-value-setq (month t3) (truncate t3 153))
+		(setq date (1+ (truncate t3 5))))))))
+      (values second minute hour date month year day
+	      daylight
+	      (if daylight
+		  (1+ (/ timezone 60))
+		  (/ timezone 60))))))
+
+(defun get-decoded-time ()
+  "Return nine values specifying the current time as follows:
+   second, minute, hour, date, month, year, day of week (0 = Monday), T
+   (daylight savings times) or NIL (standard time), and timezone."
+  (decode-universal-time (get-universal-time)))
+
+(defun current-year ()
+  (nth-value 5 (get-decoded-time)))
+
+(defun leap-years-before (year)
+  (let ((years (- year 1901)))
+    (+ (- (truncate years 4)
+	  (truncate years 100))
+       (truncate (+ years 300) 400))))
+
+(defvar *days-before-month*
+  (let* ((results (list nil)))
+    (let ((sum 0))
+      (dolist (days-per-month '(31 28 31 30 31 30 31 31 30 31 30 31))
+	(push sum results)
+	(incf sum days-per-month)))
+    (coerce (nreverse results) 'vector)))
+
+(defun encode-universal-time (second minute hour date month year
+				     &optional time-zone)
+  "The time values specified in decoded format are converted to
+   universal time, which is returned."
+  (declare (type (mod 60) second)
+	   (type (mod 60) minute)
+	   (type (mod 24) hour)
+	   (type (integer 1 31) date)
+	   (type (integer 1 12) month)
+	   (type unsigned-byte year)
+	   (type (or null rational) time-zone))
+  (when (< year 100)
+    (let* ((this (current-year))
+           (past (- this 50))
+           (future (+ this 49))
+           (maybe-past (+ (- past (mod past 100)) year))
+           (maybe-future (+ (- future (mod future 100)) year)))
+      (if (>= maybe-past past)
+        (setq year maybe-past)
+        (setq year maybe-future))))
+           
+  (let* ((days (+ (1- date)
+		  (aref *days-before-month* month)
+		  (if (> month 2)
+		    (leap-years-before (1+ year))
+		    (leap-years-before year))
+		  (* (- year 1900) 365)))
+	 (hours (+ hour (* days 24))))
+    (if time-zone
+      (+ second (* (+ minute (* (+ hours time-zone) 60)) 60))
+      (let* ((minwest-guess
+	      (get-timezone (- (* hours 60 60)
+			       unix-to-universal-time)))
+	     (guess (+ minute (* hours 60) minwest-guess))
+	     (minwest
+	      (get-timezone (- (* guess 60)
+			       unix-to-universal-time))))
+	(+ second (* (+ guess (- minwest minwest-guess)) 60))))))
+
+
+#+windows-target
+(defun %windows-sleep (millis)
+  (do* ((start (floor (get-internal-real-time)
+                      (floor internal-time-units-per-second 1000))
+               (floor (get-internal-real-time)
+                      (floor internal-time-units-per-second 1000)))
+        (millis millis (- stop start))
+        (stop (+ start millis)))
+       ((or (<= millis 0)
+            (not (eql (#_SleepEx millis #$true) #$WAIT_IO_COMPLETION))))))
+
+(defun sleep (seconds)
+  "This function causes execution to be suspended for N seconds. N may
+  be any non-negative, non-complex number."
+  (when (minusp seconds) (report-bad-arg seconds '(real 0 *)))
+  #-windows-target
+  (multiple-value-bind (secs nanos)
+      (nanoseconds seconds)
+    (%nanosleep secs nanos))
+  #+windows-target
+  (%windows-sleep (round (* seconds 1000))))
+
+
+(defun %internal-run-time ()
+  ;; Returns user and system times in internal-time-units as multiple values.
+  #-windows-target
+  (rlet ((usage :rusage))
+    (%%rusage usage)
+    (let* ((user-seconds (pref usage :rusage.ru_utime.tv_sec))
+           (system-seconds (pref usage :rusage.ru_stime.tv_sec))
+           (user-micros (pref usage :rusage.ru_utime.tv_usec))
+           (system-micros (pref usage :rusage.ru_stime.tv_usec)))
+      (values (+ (* user-seconds internal-time-units-per-second)
+                 (round user-micros (floor 1000000 internal-time-units-per-second)))
+              (+ (* system-seconds internal-time-units-per-second)
+                 (round system-micros (floor 1000000 internal-time-units-per-second))))))
+  #+windows-target
+  (rlet ((start #>FILETIME)
+         (end #>FILETIME)
+         (kernel #>FILETIME)
+         (user #>FILETIME))
+    (#_GetProcessTimes (#_GetCurrentProcess) start end kernel user)
+    (let* ((user-100ns (dpb (pref user #>FILETIME.dwHighDateTime)
+                            (byte 32 32)
+                            (pref user #>FILETIME.dwLowDateTime)))
+           (kernel-100ns (dpb (pref kernel #>FILETIME.dwHighDateTime)
+                            (byte 32 32)
+                            (pref kernel #>FILETIME.dwLowDateTime)))
+           (convert (floor 10000000 internal-time-units-per-second)))
+      (values (floor user-100ns convert) (floor kernel-100ns convert)))))
+
+(defun get-internal-run-time ()
+  "Return the run time in the internal time format. (See
+  INTERNAL-TIME-UNITS-PER-SECOND.) This is useful for finding CPU usage."
+  (multiple-value-bind (user sys) (%internal-run-time)
+    (+ user sys)))
+
+
+
+
+
+      
Index: /branches/new-random/lib/x86-backtrace.lisp
===================================================================
--- /branches/new-random/lib/x86-backtrace.lisp	(revision 13309)
+++ /branches/new-random/lib/x86-backtrace.lisp	(revision 13309)
@@ -0,0 +1,460 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+
+;;; Returns two values:
+;;;  [nil, nil] if it can be reliably determined that function uses no registers at PC
+;;;  [mask, saved-location]  if it can be reliably determined that the registers specified by "mask"
+;;;      were saved at "saved-location" in the function's stack frame
+;;;  [mask, nil] if registers in "mask" MAY have been saved, but we don't know how to restore them
+;;;      (perhaps because the "at-pc" argument wasn't specified.
+
+
+(defun registers-used-by (function &optional at-pc)
+  (multiple-value-bind (mask stack-location rpc)
+      (%function-register-usage function)
+    (if (or (null mask)
+            (and at-pc rpc (<= at-pc rpc)))
+      (values nil nil)
+      (values (canonicalize-register-mask mask) (if (and at-pc rpc) stack-location)))))
+
+(defun canonicalize-register-mask (mask)
+  (dpb (ldb (byte 2 14) mask) (byte 2 2) (ldb (byte 2 11) mask)))
+
+(defun xcf-p (p)
+  (eql 0 (%fixnum-ref p target::lisp-frame.return-address)))
+
+(defun %current-xcf ()
+  (do* ((q (%get-frame-ptr) (%%frame-backlink q)))
+       ((zerop q))
+    (declare (fixnum q))
+    (when (xcf-p q) (return q))))
+
+;;; Try to determine the program counter value, relative to an xcf's nominal function.
+(defun pc-from-xcf (xcf)
+  (let* ((nominal-function (%fixnum-ref xcf target::xcf.nominal-function))
+         (containing-object (%fixnum-ref xcf target::xcf.containing-object)))
+    (when (typep nominal-function 'function)
+      (if (eq containing-object (function-to-function-vector nominal-function))
+        (- (%fixnum-ref xcf target::xcf.relative-pc)
+	   #+x8632-target x8632::fulltag-misc
+	   #+x8664-target x8664::tag-function)
+        (let* ((tra (%fixnum-ref xcf target::xcf.ra0)))
+          (if (and #+x8664-target (= (lisptag tra) x8664::tag-tra)
+		   #+x8632-target (= (fulltag tra) x8632::fulltag-tra)
+                   (eq nominal-function (%return-address-function tra)))
+            (%return-address-offset tra)))))))
+            
+(defun cfp-lfun (p)
+  (if (xcf-p p)
+    (values
+     (%fixnum-ref p target::xcf.nominal-function)
+     (pc-from-xcf p))
+    (%cfp-lfun p)))
+
+;;; On PPC, some frames on the control stack are associated with catch
+;;; frames rather than with function calls.  The whole concept doesn't
+;;; really apply here (e.g., nothing we encounter while walking frame
+;;; pointer links belongs to a catch frame.)
+(defun catch-csp-p (p context)
+  (declare (ignore p context)))
+
+(defun %raw-frame-ref (frame context idx bad)
+  (declare (fixnum frame idx))
+  (let* ((base (parent-frame frame context))
+         (raw-size (- base frame)))
+    (declare (fixnum base raw-size))
+    (if (and (>= idx 0)
+             (< idx raw-size))
+      (let* ((addr (- (the fixnum (1- base))
+                      idx)))
+        (multiple-value-bind (db-count first-db last-db)
+            (count-db-links-in-frame frame base context)
+          (let* ((is-db-link
+                  (unless (zerop db-count)
+                    (do* ((last last-db (previous-db-link last first-db)))
+                         ((null last))
+                      (when (= addr last)
+                        (return t))))))
+            (if is-db-link
+              (oldest-binding-frame-value context addr)
+              (%fixnum-ref addr)))))
+      bad)))
+
+(defun %raw-frame-set (frame context idx new)
+  (declare (fixnum frame idx))
+  (let* ((base (parent-frame frame context))
+         (raw-size (- base frame)))
+    (declare (fixnum base raw-size))
+    (if (and (>= idx 0)
+             (< idx raw-size))
+      (let* ((addr (- (the fixnum (1- base))
+                      idx)))
+        (multiple-value-bind (db-count first-db last-db)
+            (count-db-links-in-frame frame base context)
+          (let* ((is-db-link
+                  (unless (zerop db-count)
+                    (do* ((last last-db (previous-db-link last first-db)))
+                         ((null last))
+                      (when (= addr last)
+                        (return t))))))
+            (if is-db-link
+              (setf (oldest-binding-frame-value context addr) new)
+              (setf (%fixnum-ref addr) new))))))))
+
+(defun %stack< (index1 index2 &optional context)
+  (let* ((tcr (if context (bt.tcr context) (%current-tcr)))
+         (vs-area (%fixnum-ref tcr target::tcr.vs-area)))
+    (and (%ptr-in-area-p index1 vs-area)
+         (%ptr-in-area-p index2 vs-area)
+         (< (the fixnum index1) (the fixnum index2)))))
+
+
+
+
+(defun register-number->saved-register-index (regnum)
+  (ecase regnum
+    (#.x8664::save3 0)
+    (#.x8664::save2 1)
+    (#.x8664::save1 2)
+    (#.x8664::save0 3)))
+
+
+(defun get-register-value (address last-catch index)
+  (if address
+    (%fixnum-ref address)
+    (uvref last-catch (+ index 
+			 #+x8632-target
+			 x8632::catch-frame.db-link-cell
+			 #+x8664-target
+			 x8664::catch-frame.save-save3-cell))))
+
+;;; Inverse of get-register-value
+
+(defun set-register-value (value address last-catch index)
+  (if address
+    (%fixnum-set address value)
+    (setf (uvref last-catch (+ index
+			       #+x8632-target
+			       x8632::catch-frame.db-link-cell
+			       #+x8664-target
+			       x8664::catch-frame.save-save3-cell))
+          value)))
+
+(defun %find-register-argument-value (context cfp regval bad)
+  (let* ((last-catch (last-catch-since cfp context))
+         (index (register-number->saved-register-index regval)))
+    (do* ((frame cfp (child-frame frame context))
+          (first t))
+         ((null frame))
+      (if (xcf-p frame)
+        (with-macptrs (xp)
+          (%setf-macptr-to-object xp (%fixnum-ref frame x8664::xcf.xp))
+          (return-from %find-register-argument-value
+            (encoded-gpr-lisp xp regval)))
+        (progn
+          (unless first
+            (multiple-value-bind (lfun pc)
+                (cfp-lfun frame)
+              (when lfun
+                (multiple-value-bind (mask where)
+                    (registers-used-by lfun pc)
+                  (when (if mask (logbitp index mask))
+                    (return-from %find-register-argument-value
+                      (if where
+                        (let ((offset (logcount (logandc2 mask (1- (ash 1 (1+ index)))))))
+                          (raw-frame-ref frame context (+ where offset) bad))
+                        bad)))))))
+          (setq first nil))))
+    (get-register-value nil last-catch index)))
+
+(defun %set-register-argument-value (context cfp regval new)
+  (let* ((last-catch (last-catch-since cfp context))
+         (index (register-number->saved-register-index regval)))
+    (do* ((frame cfp (child-frame frame context))
+          (first t))
+         ((null frame))
+      (if (xcf-p frame)
+        (with-macptrs (xp)
+          (%setf-macptr-to-object xp (%fixnum-ref frame x8664::xcf.xp))
+          (return-from %set-register-argument-value
+            (setf (encoded-gpr-lisp xp regval) new)))
+        (progn
+          (unless first
+            (multiple-value-bind (lfun pc)
+                (cfp-lfun frame)
+              (when lfun
+                (multiple-value-bind (mask where)
+                    (registers-used-by lfun pc)
+                  (when (if mask (logbitp index mask))
+                    (incf where (logcount (logandc2 mask (1- (ash 1 (1+ index))))))
+
+                    (return-from %set-register-argument-value
+                      (raw-frame-set frame context where new)))))))
+          (setq first nil))))
+    (set-register-value new nil last-catch index)))
+
+;;; Used for printing only.
+(defun index->address (p)
+  (ldb (byte #+32-bit-target 32 #+64-bit-target 64 0)  (ash p target::fixnumshift)))
+
+(defun exception-frame-p (x)
+  (and x (xcf-p x)))
+
+;;; Function has failed a number-of-arguments check; return a list
+;;; of the actual arguments.
+;;; On x86-64, the kernel has finished the frame and pushed everything
+;;; for us, so all that we need to do is to hide any inherited arguments.
+(defun arg-check-call-arguments (fp function)
+  (when (xcf-p fp)
+    (with-macptrs (xp)
+      (%setf-macptr-to-object xp (%fixnum-ref fp target::xcf.xp))
+      (let* ((numinh (ldb $lfbits-numinh (lfun-bits function)))
+             (nargs (- (xp-argument-count xp) numinh))
+             (p (- (%fixnum-ref fp target::xcf.backptr)
+                   (* target::node-size numinh))))
+        (declare (fixnum numinh nargs p))
+        (collect ((args))
+          (dotimes (i nargs (args))
+            (args (%fixnum-ref p (- target::node-size)))
+            (decf p)))))))
+
+(defun vsp-limits (frame context)
+  (let* ((parent (parent-frame frame context)))
+    (if (xcf-p frame)
+      (values (+ frame (ash target::xcf.size (- target::word-shift)))
+              parent)
+      (let* ((tra (%fixnum-ref frame target::lisp-frame.return-address)))
+        (values (+ frame 2 (if (eq tra (%get-kernel-global ret1valaddr)) 1 0))
+                parent)))))
+
+(defun last-catch-since (fp context)
+  (let* ((tcr (if context (bt.tcr context) (%current-tcr)))
+         (catch (%catch-top tcr))
+         (last-catch nil))
+    (loop
+      (unless catch (return last-catch))
+      (let ((catch-fp (uvref catch
+			     #+x8632-target
+			     x8632::catch-frame.ebp-cell
+			     #+x8664-target
+			     x8664::catch-frame.rbp-cell)))
+        (when (%stack< fp catch-fp context) (return last-catch))
+        (setq last-catch catch
+              catch (next-catch catch))))))
+
+(defun last-xcf-since (target-fp start-fp context)
+  (do* ((last-xcf nil)
+        (fp start-fp (parent-frame fp context)))
+       ((or (eql fp target-fp)
+            (null fp)
+            (%stack< target-fp fp)) last-xcf)
+    (if (xcf-p fp) (setq last-xcf fp))))
+
+(defun match-local-name (cellno info pc)
+  (when info
+    (let* ((syms (%car info))
+           (ptrs (%cdr info)))
+      (dotimes (i (length syms))
+        (let ((j (%i+ i (%i+ i i ))))
+          (and (eq (uvref ptrs j) (%ilogior (%ilsl (+ 6 target::word-shift) cellno) #o77))
+               (%i>= pc (uvref ptrs (%i+ j 1)))
+               (%i< pc (uvref ptrs (%i+ j 2)))
+               (return (aref syms i))))))))
+
+(defun apply-in-frame (frame function arglist &optional context)
+  (setq function (coerce-to-function function))
+  (let* ((parent (parent-frame frame context)))
+    (when parent
+      (if (xcf-p parent)
+        (error "Can't unwind to exception frame ~s" frame)
+        (setq frame parent))
+      (if (or (null context)
+              (eq (bt.tcr context) (%current-tcr)))
+        (%apply-in-frame frame function arglist)
+        (let* ((process (tcr->process (bt.tcr context))))
+          (if process
+            (process-interrupt process #'%apply-in-frame frame function arglist)
+            (error "Can't find process for backtrace context ~s" context)))))))
+
+(defun return-from-frame (frame &rest values)
+  (apply-in-frame frame #'values values nil))
+    
+
+(defun last-tsp-before (target)
+  (declare (fixnum target))
+  (do* ((tsp (%fixnum-ref (%current-tcr) target::tcr.save-tsp)
+             (%fixnum-ref tsp target::tsp-frame.backptr)))
+       ((zerop tsp) nil)
+    (declare (fixnum tsp))
+    (when (> (the fixnum (%fixnum-ref tsp #+x8632-target x8632::tsp-frame.ebp
+				          #+x8664-target x8664::tsp-frame.rbp))
+             target)
+      (return tsp))))
+
+    
+
+
+;;; We can't determine this reliably (yet).
+(defun last-foreign-sp-before (target)
+  (declare (fixnum target))
+  (do* ((cfp (%fixnum-ref (%current-tcr) target::tcr.foreign-sp)
+             (%fixnum-ref cfp target::csp-frame.backptr)))
+       ((zerop cfp))
+    (declare (fixnum cfp))
+    (let* ((rbp (%fixnum-ref cfp #+x8632-target x8632::csp-frame.ebp
+			         #+x8664-target x8664::csp-frame.rbp)))
+      (declare (fixnum rbp))
+      (if (> rbp target)
+        (return cfp)
+        (if (zerop rbp)
+          (return nil))))))
+
+
+(defun %tsp-frame-containing-progv-binding (db)
+  (declare (fixnum db))
+  (do* ((tsp (%fixnum-ref (%current-tcr) target::tcr.save-tsp) next)
+        (next (%fixnum-ref tsp target::tsp-frame.backptr)
+              (%fixnum-ref tsp target::tsp-frame.backptr)))
+       ()
+    (declare (fixnum tsp next))
+    (let* ((rbp (%fixnum-ref tsp #+x8632-target x8632::tsp-frame.ebp
+			         #+x8664-target x8664::tsp-frame.rbp)))
+      (declare (fixnum rbp))
+      (if (zerop rbp)
+        (return (values nil nil))
+        (if (and (> db tsp)
+                 (< db next))
+          (return (values tsp rbp)))))))
+
+        
+
+
+
+
+(defun last-binding-before (frame)
+  (declare (fixnum frame))
+  (do* ((db (%current-db-link) (%fixnum-ref db 0))
+        (tcr (%current-tcr))
+        (vs-area (%fixnum-ref tcr target::tcr.vs-area))
+        (vs-low (%fixnum-ref vs-area target::area.low))
+        (vs-high (%fixnum-ref vs-area target::area.high)))
+       ((eql db 0) nil)
+    (declare (fixnum db vs-low vs-high))
+    (if (and (> db vs-low)
+             (< db vs-high))
+      (if (> db frame)
+        (return db))
+      ;; db link points elsewhere; PROGV uses the temp stack
+      ;; to store an indefinite number of bindings.
+      (multiple-value-bind (tsp rbp)
+          (%tsp-frame-containing-progv-binding db)
+        (if tsp
+          (if (> rbp frame)
+            (return db)
+            ;; If the tsp frame is too young, we can skip
+            ;; all of the bindings it contains.  The tsp
+            ;; frame contains two words of overhead, followed
+            ;; by a count of binding records in the frame,
+            ;; followed by the youngest of "count" binding
+            ;; records (which happens to be the value of
+            ;; "db".)  Skip "count" binding records.
+            (dotimes (i (the fixnum (%fixnum-ref tsp target::dnode-size)))
+              (setq db (%fixnum-ref db 0))))
+          ;; If the binding record wasn't on the temp stack and wasn't
+          ;; on the value stack, that probably means that things are
+          ;; seriously screwed up.  This error will be almost
+          ;; meaningless to the user.
+          (error "binding record (#x~16,'0x/#x~16,'0x) not on temp or value stack" (index->address db) db))))))
+          
+
+
+(defun find-x8664-saved-nvrs (frame start-fp context)
+  (let* ((locations (make-array 16 :initial-element nil))
+         (need (logior (ash 1 x8664::save0)
+                       (ash 1 x8664::save1)
+                       (ash 1 x8664::save2)
+                       (ash 1 x8664::save3))))
+    (declare (fixnum need)
+             (dynamic-extent locations))
+    (do* ((parent frame child)
+          (child (child-frame parent context) (child-frame child context)))
+         ((or (= need 0) (eq child start-fp))
+          (values (%svref locations x8664::save0)
+                  (%svref locations x8664::save1)
+                  (%svref locations x8664::save2)
+                  (%svref locations x8664::save3)))
+      (multiple-value-bind (lfun pc) (cfp-lfun child)
+        (when (and lfun pc)
+          (multiple-value-bind (used where) (registers-used-by lfun pc)
+            (when (and used where (logtest used need))
+              (locally (declare (fixnum used))
+                (do* ((i x8664::save3 (1+ i)))
+                     ((or (= i 16) (= used 0)))
+                  (declare (type (mod 16) i))
+                  (when (logbitp i used)
+                    (when (logbitp i need)
+                      (setq need (logandc2 need (ash 1 i)))
+                      (setf (%svref locations i)
+                            (- (the fixnum (1- parent))
+                               (+ where (logcount (logandc2 used (1+ (ash 1 (1+ i)))))))))
+                    (setq used (logandc2 used (ash 1 i)))))))))))))
+                                         
+              
+         
+(defun %apply-in-frame (frame function arglist)
+  (target-arch-case
+   (:x8632 (error "%apply-in-frame doesn't work for x8632 yet"))
+   (:x8664
+    (let* ((target-catch (last-catch-since frame nil))
+	   (start-fp (if target-catch
+		       (uvref target-catch x8664::catch-frame.rbp-cell)
+		       (%get-frame-ptr)))
+	   (target-xcf (last-xcf-since frame start-fp nil))
+	   (target-db-link (last-binding-before frame))
+	   (target-tsp (last-tsp-before frame))
+	   (target-foreign-sp (last-foreign-sp-before frame)))
+      (multiple-value-bind (save0-loc save1-loc save2-loc save3-loc)
+	  (find-x8664-saved-nvrs frame start-fp nil)
+	(let* ((thunk (%clone-x86-function #'%%apply-in-frame-proto
+					   frame
+					   target-catch
+					   target-db-link
+					   target-xcf
+					   target-tsp
+					   target-foreign-sp
+					   (if save0-loc
+					     (- save0-loc frame)
+					     0)
+					   (if save1-loc
+					     (- save1-loc frame)
+					     0)
+					   (if save2-loc
+					     (- save2-loc frame)
+					     0)
+					   (if save3-loc
+					     (- save3-loc frame)
+					     0)
+					   (coerce-to-function function)
+					   arglist
+					   0)))
+	  (funcall thunk)))))))
+
+            
+    
Index: /branches/new-random/lib/x86-watch.lisp
===================================================================
--- /branches/new-random/lib/x86-watch.lisp	(revision 13309)
+++ /branches/new-random/lib/x86-watch.lisp	(revision 13309)
@@ -0,0 +1,87 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; Return the effective address of a memory operand by using the
+;;; register state in xp, or NIL if we can't figure it out.
+;;; Needs to run inside a without-gcing form.
+(defun x86-memory-operand-ea (xp op)
+  (let* ((seg (x86::x86-memory-operand-seg op))
+	 (disp (x86::x86-memory-operand-disp op))
+	 (base (x86::x86-memory-operand-base op))
+	 (index (x86::x86-memory-operand-index op))
+	 (scale (x86::x86-memory-operand-scale op)))
+    (cond
+      ((and base index (not seg))
+       (let* ((base-re (x86::x86-register-operand-entry base))
+	      (index-re (x86::x86-register-operand-entry index))
+	      (base-num (x86::reg-entry-reg-num base-re))
+	      (index-num (x86::reg-entry-reg-num index-re))
+	      (base-val nil)
+	      (index-val nil))
+	 (when (logtest (x86::reg-entry-reg-flags base-re) x86::+regrex+)
+	   (incf base-num 8))
+	 (setq base-val (encoded-gpr-integer xp base-num))
+	 (when (logtest (x86::reg-entry-reg-flags index-re) x86::+regrex+)
+	   (incf index-num 8))
+	 (setq index-val (encoded-gpr-integer xp index-num))
+	 (when scale
+	   (setq index-val (ash index-val scale)))
+	 (+ (or disp 0) base-val index-val))))))
+
+;;; Try to emulate the disassembled instruction using the
+;;; register state in xp.  Return NIL if we couldn't do it.
+;;; This will run with other threads suspended.
+(defun x86-emulate-instruction (xp instruction)
+  (let* ((mnemonic (x86-di-mnemonic instruction))
+	 (op0 (x86-di-op0 instruction))
+	 (op1 (x86-di-op1 instruction))
+	 (op2 (x86-di-op2 instruction)))
+    (when (and op0 op1 (not op2)
+	       (typep op0 'x86::x86-register-operand)
+	       (typep op1 'x86::x86-memory-operand))
+      (without-gcing
+	(let* ((src-re (x86::x86-register-operand-entry op0))
+	       (src-num (x86::reg-entry-reg-num src-re))
+	       (src-val nil)
+	       (ea (x86-memory-operand-ea xp op1)))
+	  (when (logtest (x86::reg-entry-reg-flags src-re) x86::+regrex+)
+	    (incf src-num 8))
+	  (setq src-val (encoded-gpr-integer xp src-num))
+	  (when ea
+	    (with-macptrs ((p (%int-to-ptr ea)))
+	      (cond
+		((string= mnemonic "movb")
+		 (setf (%get-signed-byte p) (ldb (byte 8 0) src-val)))
+		((string= mnemonic "movw")
+		 (setf (%get-signed-word p) (ldb (byte 16 0) src-val)))
+		((string= mnemonic "movl")
+		 (setf (%get-signed-long p) (ldb (byte 32 0) src-val)))
+		((string= mnemonic "movq")
+		 (setf (%%get-signed-longlong p 0) (ldb (byte 64 0) src-val)))))))))))
+
+(defun x86-can-emulate-instruction (instruction)
+  (let* ((mnemonic (x86-di-mnemonic instruction))
+	 (op0 (x86-di-op0 instruction))
+	 (op1 (x86-di-op1 instruction))
+	 (op2 (x86-di-op2 instruction)))
+    (when (and op0 op1 (not op2)
+	       (typep op0 'x86::x86-register-operand)
+	       (typep op1 'x86::x86-memory-operand)
+	       (member mnemonic '("movb" "movw" "movl" "movq") :test 'string=))
+      (let* ((seg (x86::x86-memory-operand-seg op1))
+	     (base (x86::x86-memory-operand-base op1))
+	     (index (x86::x86-memory-operand-index op1)))
+	(and base index (not seg))))))
Index: /branches/new-random/lib/x8632env.lisp
===================================================================
--- /branches/new-random/lib/x8632env.lisp	(revision 13309)
+++ /branches/new-random/lib/x8632env.lisp	(revision 13309)
@@ -0,0 +1,71 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defconstant $numx8632saveregs 0)
+(defconstant $numx8632argregs 2)
+
+
+(defconstant x8632-nonvolatile-registers-mask 0)
+
+(defconstant x8632-arg-registers-mask
+  (logior (ash 1 x8632::arg_z)
+          (ash 1 x8632::arg_y)))
+  
+(defconstant x8632-temp-registers-mask
+  (logior (ash 1 x8632::temp0)
+	  (ash 1 x8632::temp1)))
+  
+(defconstant x8632-tagged-registers-mask
+  (logior x8632-temp-registers-mask
+          x8632-arg-registers-mask
+          x8632-nonvolatile-registers-mask))
+
+
+
+(defconstant x8632-temp-node-regs 
+  (make-mask x8632::temp0
+	     x8632::temp1
+             x8632::arg_y
+             x8632::arg_z))
+
+(defconstant x8632-nonvolatile-node-regs 0)
+
+(defconstant x8632-node-regs (logior x8632-temp-node-regs x8632-nonvolatile-node-regs))
+
+(defconstant x8632-imm-regs (make-mask
+                             x8632::imm0))
+
+;;; Fine if we assume SSE support;  not so hot when using x87
+(defconstant x8632-temp-fp-regs (make-mask x8632::fp0
+                                           x8632::fp1
+                                           x8632::fp2
+                                           x8632::fp3
+                                           x8632::fp4
+                                           x8632::fp5
+                                           x8632::fp6
+                                           x8632::fp7))
+                               
+
+
+(defconstant x8632-cr-fields (make-mask 0))
+
+;;; hmm.
+(defconstant $undo-x86-c-frame 16)
+
+
+(ccl::provide "X8632ENV")
Index: /branches/new-random/lib/x8664env.lisp
===================================================================
--- /branches/new-random/lib/x8664env.lisp	(revision 13309)
+++ /branches/new-random/lib/x8664env.lisp	(revision 13309)
@@ -0,0 +1,84 @@
+; -*- Mode:Lisp; Package:CCL; -*-
+;;;
+;;;   Copyright (C) 2005-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defconstant $numx8664saveregs 4)
+(defconstant $numx8664argregs 3)
+
+
+(defconstant x8664-nonvolatile-registers-mask
+  (logior (ash 1 x8664::save0)
+          (ash 1 x8664::save1)
+          (ash 1 x8664::save2)
+          (ash 1 x8664::save3)))
+
+(defconstant x8664-arg-registers-mask
+  (logior (ash 1 x8664::arg_z)
+          (ash 1 x8664::arg_y)
+          (ash 1 x8664::arg_x)))
+
+(defconstant x8664-temp-registers-mask
+  (logior (ash 1 x8664::temp0)
+          (ash 1 x8664::temp1)
+          (ash 1 x8664::temp2)))
+
+
+(defconstant x8664-tagged-registers-mask
+  (logior x8664-temp-registers-mask
+          x8664-arg-registers-mask
+          x8664-nonvolatile-registers-mask))
+
+
+(defconstant x8664-temp-node-regs 
+  (make-mask x8664::temp0
+             x8664::temp1
+             x8664::temp2
+             x8664::arg_x
+             x8664::arg_y
+             x8664::arg_z))
+
+(defconstant x8664-nonvolatile-node-regs
+  (make-mask x8664::save0
+             x8664::save1
+             x8664::save2
+             x8664::save3))
+
+
+(defconstant x8664-node-regs (logior x8664-temp-node-regs x8664-nonvolatile-node-regs))
+
+(defconstant x8664-imm-regs (make-mask
+                             x8664::imm0
+                             x8664::imm1
+                             x8664::imm2))
+
+(defconstant x8664-temp-fp-regs (make-mask x8664::fp0
+                                           x8664::fp1
+                                           x8664::fp2
+                                           x8664::fp3
+                                           x8664::fp4
+                                           x8664::fp5
+                                           x8664::fp6
+                                           x8664::fp7))
+                               
+
+
+(defconstant x8664-cr-fields (make-mask 0))
+
+(defconstant $undo-x86-c-frame 16)
+
+
+(ccl::provide "X8664ENV")
Index: /branches/new-random/lib/xref.lisp
===================================================================
--- /branches/new-random/lib/xref.lisp	(revision 13309)
+++ /branches/new-random/lib/xref.lisp	(revision 13309)
@@ -0,0 +1,659 @@
+;;; -*- Mode: Lisp; Package: CCL; indent-tabs-mode: nil -*-
+;;;
+;;;   Copyright (C) 2003 Oliver Markovic <entrox@entrox.org>
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (export '(*RECORD-XREF-INFO*
+            *LOAD-XREF-INFO*
+            XREF-ENTRY
+            XREF-ENTRY-NAME
+            XREF-ENTRY-TYPE
+            XREF-ENTRY-FULL-NAME
+            XREF-ENTRY-METHOD-QUALIFIERS
+            XREF-ENTRY-METHOD-SPECIALIZERS
+            XREF-ENTRY-P
+            XREF-ENTRY-EQUAL
+            DISCARD-ALL-XREF-INFO
+            GET-RELATION
+            MACROS-CALLED-BY
+            START-XREF
+            STOP-XREF
+            WHO-BINDS
+            WHO-CALLS
+            WHO-DIRECTLY-CALLS
+            WHO-INDIRECTLY-CALLS
+            WHO-REFERENCES
+            WHO-SETS
+            WHO-USES
+            WITH-XREF
+            XREF-DESCRIBE)))
+
+(defpackage "CROSS-REFERENCE"
+  (:use "CL")
+  (:nicknames "XREF")
+  (:import-from "CCL"
+                "*RECORD-XREF-INFO*"
+                "*LOAD-XREF-INFO*"
+                "XREF-ENTRY"
+                "XREF-ENTRY-NAME"
+                "XREF-ENTRY-TYPE"
+                "XREF-ENTRY-FULL-NAME"
+                "XREF-ENTRY-METHOD-QUALIFIERS"
+                "XREF-ENTRY-METHOD-SPECIALIZERS"
+                "XREF-ENTRY-P"
+                "XREF-ENTRY-EQUAL"
+                "DISCARD-ALL-XREF-INFO"
+                "GET-RELATION"
+                "MACROS-CALLED-BY"
+                "START-XREF"
+                "STOP-XREF"
+                "WHO-BINDS"
+                "WHO-CALLS"
+                "WHO-DIRECTLY-CALLS"
+                "WHO-INDIRECTLY-CALLS"
+                "WHO-REFERENCES"
+                "WHO-SETS"
+                "WHO-USES"
+                "WITH-XREF"
+                "XREF-DESCRIBE")
+  (:export "*RECORD-XREF-INFO*"
+           "*LOAD-XREF-INFO*"
+           "XREF-ENTRY"
+           "XREF-ENTRY-NAME"
+           "XREF-ENTRY-TYPE"
+           "XREF-ENTRY-FULL-NAME"
+           "XREF-ENTRY-METHOD-QUALIFIERS"
+           "XREF-ENTRY-METHOD-SPECIALIZERS"
+           "XREF-ENTRY-P"
+           "XREF-ENTRY-EQUAL"
+           "DISCARD-ALL-XREF-INFO"
+           "GET-RELATION"
+           "MACROS-CALLED-BY"
+           "START-XREF"
+           "STOP-XREF"
+           "WHO-BINDS"
+           "WHO-CALLS"
+           "WHO-DIRECTLY-CALLS"
+           "WHO-INDIRECTLY-CALLS"
+           "WHO-REFERENCES"
+           "WHO-SETS"
+           "WHO-USES"
+           "WITH-XREF"
+           "XREF-DESCRIBE"))
+
+
+;; *RECORD-XREF-INFO* -- external
+;;
+;; Cross-referencing information will only be recorded if this flag
+;; is set. It is usually set/unset by START-XREF/STOP-XREF
+(defvar *record-xref-info* nil
+  "Flag indicating wether cross-referencing information should be recorded.")
+
+;; *LOAD-XREF-INFO* -- external
+;;
+;; FIXME: We don't save any information yet...
+(defvar *load-xref-info* nil
+  "Flag indicating wether cross-referencing information should be loaded
+from FASLs.")
+
+
+
+;; START-XREF -- external
+;;
+(defun start-xref ()
+  "Start recording cross-referencing information while compiling."
+  (setf *record-xref-info* t)
+  (setf *load-xref-info* t)
+  t)
+
+;; STOP-XREF -- external
+;;
+(defun stop-xref ()
+  "Stop recording cross-referencing information while compiling."
+  (setf *record-xref-info* nil)
+  (setf *load-xref-info* nil)
+  nil)
+
+;; WITH-XREF -- external
+;;
+(defmacro with-xref (&body body)
+  "Execute BODY with cross-referencing turned on."
+  (let ((return-value (gensym "RETURN-VALUE")))
+    `(let ((*record-xref-info* t)
+           (*load-xref-info* t)
+           (,return-value nil))
+       (setf ,return-value (progn ,@body))
+       ,return-value)))
+
+
+;; XREF-ENTRY -- external
+;;
+(defstruct (xref-entry
+            (:constructor %make-xref-entry)
+            (:print-function %print-xref-entry))
+  name
+  type
+  (method-qualifiers nil)
+  (method-specializers nil))
+
+;; %PRINT-XREF-ENTRY -- internal
+;;
+(defun %print-xref-entry (struct stream d)
+  (declare (ignore d))
+  (if *print-readably*
+      (format stream "#S(xref::xref-entry :name '~A :type '~A :method-qualifiers ~A :method-specializers ~A)"
+              (xref-entry-name struct)
+              (xref-entry-type struct)
+              (xref-entry-method-qualifiers struct)
+              (xref-entry-method-specializers struct))
+    (print-unreadable-object (struct stream :type t)
+      (format stream "~A ~A~@[ ~A~]~@[ ~A~]"
+              (xref-entry-name struct)
+              (xref-entry-type struct)
+              (xref-entry-method-qualifiers struct)
+              (xref-entry-method-specializers struct)))))
+
+;; MAKE-XREF-ENTRY -- internal
+;;
+;; Takes a simple input form and makes a XREF-ENTRY from it. The input is
+;; assumed to be a function, macro or variable when a simple symbol is passed,
+;; or a method when it is a cons. Since this needs to also handle the ouput
+;; from CCL::CALLERS, there is additional hackery trying to do the right thing.
+(defun make-xref-entry (input relation)
+  (etypecase input
+    (symbol
+     (let ((type (ecase relation
+                   ((:direct-calls :indirect-calls) 'function)
+                   ((:binds :sets :references) 'variable)
+                   ((:macro-calls) 'macro))))
+       (%make-xref-entry :name input :type type)))
+    (method
+     (let ((name (method-name input))
+           (qualifiers (method-qualifiers input))
+           (specializers (canonicalize-specializers (method-specializers input))))
+       (%make-xref-entry :name name :type 'method
+                         :method-qualifiers (unless (eql qualifiers t) qualifiers)
+                         :method-specializers specializers)))
+    (cons
+     (case (car input)
+       ((ppc-lap-macro compiler-macro-function)
+        (%make-xref-entry :name (cadr input) :type (car input)))
+       ((:internal)
+        (make-xref-entry (car (last input)) relation))
+       (t
+        (multiple-value-bind (type name specializers qualifiers)
+            (parse-definition-spec input)
+          (%make-xref-entry :name name :type type
+                            :method-qualifiers (unless (eql qualifiers t) qualifiers)
+                            :method-specializers specializers)))))))
+
+(defun parse-definition-spec (form)
+  (let ((type t)
+        name classes qualifiers)
+    (cond
+     ((consp form)
+      (cond ((eq (car form) 'setf)
+             (setq name form))
+            (t
+             (when (eq (car form) :method) (pop form))
+             (setq name (car form))
+             (let* ((last (car (last (cdr form)))))
+                 (cond ((and (listp last)(or (null last)(neq (car last) 'eql)))
+                        (setq classes last)
+                        (setq qualifiers (butlast (cdr form))))
+                       (t (setq classes (cdr form)))))                   
+               (cond ((null qualifiers)
+                      (setq qualifiers t))
+                     ((equal qualifiers '(:primary))
+                      (setq qualifiers nil))))))
+     (t (setq name form)))
+    (when (setf-function-name-p name)
+      (setq name (canonical-maybe-setf-name name)))
+    (when (not (or (symbolp name)
+                   (setf-function-name-p name)))
+      (return-from parse-definition-spec))
+    (when (consp qualifiers)
+      (mapc #'(lambda (q)
+                (when (listp q)
+                  (return-from parse-definition-spec)))
+          qualifiers))
+    (when classes
+      (mapc #'(lambda (c)
+                (when (not (and c (or (symbolp c)(and (consp c)(eq (car c) 'eql)))))
+                  (return-from parse-definition-spec)))
+            classes))            
+    (when (or (consp classes)(consp qualifiers))(setq type 'method))
+    (values type name classes qualifiers)))
+
+;; XREF-ENTRY-EQUAL -- external
+;;
+;; Simply compares all slots.
+(defun xref-entry-equal (entry1 entry2)
+  (and (eql (xref-entry-name entry1) (xref-entry-name entry2))
+       (eql (xref-entry-type entry1) (xref-entry-type entry2))
+       (equal (xref-entry-method-qualifiers entry1)
+              (xref-entry-method-qualifiers entry2))
+       (equal (xref-entry-method-specializers entry1)
+              (xref-entry-method-specializers entry2))))
+
+;; XREF-ENTRY-FULL-NAME -- external
+;;
+(defun xref-entry-full-name (entry)
+  (if (eql (xref-entry-type entry) 'method)
+    `(:method ,(xref-entry-name entry)
+              ,@(xref-entry-method-qualifiers entry)
+              ,(xref-entry-method-specializers entry))
+    (xref-entry-name entry)))
+
+
+;; %DB-KEY-FROM-XREF-ENTRY -- internal
+;;
+;; This is mostly the inverse to MAKE-XREF-ENTRY, since it takes an entry
+;; and returns either a symbol (for functions, macros and variables) or a
+;; list in the form (METHOD-NAME QUALIFIERS (SPECIALIZERS)) for a method.
+;; These are used as keys in the database hash-tables.
+(defun %db-key-from-xref-entry (entry)
+  (if (eql (xref-entry-type entry) 'method)
+      `(,(xref-entry-name entry)
+        ,@(xref-entry-method-qualifiers entry)
+        ,(xref-entry-method-specializers entry))
+    (xref-entry-name entry)))
+
+;; %SOURCE-FILE-FOR-XREF-ENTRY -- internal
+;;
+(defun %source-file-for-xref-entry (entry)
+  (multiple-value-bind (files name type specializers qualifiers)
+      (edit-definition-p (%db-key-from-xref-entry entry)
+                         (if (eql (xref-entry-type entry) 'macro)
+                             'function
+                           (xref-entry-type entry)))
+    (declare (ignore name type specializers qualifiers))
+    (let ((filename (if (consp files) (cdar files) files)))
+      (when filename
+        (truename filename)))))
+
+
+;; MAKE-XREF-DATABASE -- internal
+;;
+;; This returns a fresh cross-referencing "database". It's a simple association
+;; list with two hash-tables per entry. The CAR hash holds the direct entries
+;; e.g. KEY calls/references/etc VALUE, while the CDR holds inverse hash (KEY
+;; is called/referenced/etc by VALUE.
+(defun make-xref-database ()
+  (list :binds (cons (make-hash-table :test #'equal)
+                     (make-hash-table :test #'equal))
+        :references (cons (make-hash-table :test #'equal)
+                          (make-hash-table :test #'equal))
+        :sets (cons (make-hash-table :test #'equal)
+                    (make-hash-table :test #'equal))
+        :direct-calls (cons (make-hash-table :test #'equal)
+                            (make-hash-table :test #'equal))
+        :indirect-calls (cons (make-hash-table :test #'equal)
+                              (make-hash-table :test #'equal))
+        :macro-calls (cons (make-hash-table :test #'equal)
+                           (make-hash-table :test #'equal))))
+
+;; *XREF-DATABASE* -- internal
+;;
+;; The one and only cross-referencing database.
+(defvar *xref-database* (make-xref-database))
+
+
+;; %XREF-TABLE -- internal
+;;
+;; Returns the appropriate table for a given relation.
+(defun %xref-table (relation inversep)
+  (if inversep
+      (cdr (getf *xref-database* relation))
+    (car (getf *xref-database* relation))))
+
+
+;; DISCARD-ALL-XREF-INFO -- external
+;;
+(defun discard-all-xref-info ()
+  "Clear the cross-referencing database."
+  (setf *xref-database* (make-xref-database))
+  t)
+
+
+;; %ADD-XREF-ENTRY -- internal
+;;
+;; The compiler adds cross-referencing information by calling this
+;; (see NX-RECORD-XREF-INFO).
+(defun %add-xref-entry (relation name1 name2)
+  (when (and *record-xref-info* relation name1 name2)
+    (pushnew (make-xref-entry name2 relation)
+             (gethash name1 (%xref-table relation nil))
+             :test #'xref-entry-equal)
+    (pushnew (make-xref-entry name1 relation)
+             (gethash name2 (%xref-table relation t))
+             :test #'xref-entry-equal)
+    t))
+
+
+
+
+;; %DISCARD-XREF-INFO-FOR-FUNCTION -- internal
+;;
+;; This rather expensive operation removes all traces of a given function
+;; from the cross-referencing database. It needs to be called whenever a
+;; function gets redefined, so we don't pick up stale xref entries.
+(defun %discard-xref-info-for-function (func)
+  ;; need to go through every possible relation
+  (dolist (relation '(:direct-calls :indirect-calls :macro-calls
+                      :binds :references :sets))
+    ;; get a list of the places to which the func points to...
+    (dolist (entry (gethash func (%xref-table relation nil)))
+      (let ((key (%db-key-from-xref-entry entry)))
+        ;; ... and remove it from there
+        (setf (gethash key (%xref-table relation t))
+              (delete func (gethash key (%xref-table relation t))))))
+    ;; the non-inverse case is easy
+    (remhash func (%xref-table relation nil))))
+
+
+;; GET-RELATION -- external
+;;
+;; FIXME: Implement filtering by files.
+;;        And what the heck should errorp do?
+(defun get-relation (relation name1 name2 &key in-files in-functions exhaustive errorp)
+  "Returns a list of matches for RELATION between NAME1 and NAME2. Results can
+be filtered by passing a list of files in IN-FILES or functions in IN-FUNCTIONS.
+If EXHAUSTIVE is true, it will also look for callers for which no xref information
+is present by looping through all defined functions in memory."
+  (when (and (eql name1 :wild) (eql name2 :wild))
+    (error "Only one wildcard allowed in a cross-reference query"))
+  (ecase relation
+    ((:binds :references :sets :direct-calls :indirect-calls :macro-calls)
+     (let ((lookup-table (%xref-table relation nil))
+           (inverse-lookup-table (%xref-table relation t)))
+       (let ((matches (if (eql name1 :wild)
+                          (%do-wild-xref-lookup name2 inverse-lookup-table
+                                                in-files in-functions)
+                        (if (eql name2 :wild)
+                            (%do-wild-xref-lookup name1 lookup-table
+                                                  in-files in-functions)
+                          (%do-simple-xref-lookup name1 name2 lookup-table
+                                                  in-files in-functions)))))
+         ;; search all lfuns if exhaustive is t
+         (when (and exhaustive (eql name1 :wild) (or (eql relation :direct-calls)
+                                                     (eql relation :indirect-calls)))
+           (dolist (caller (callers name2))
+             (pushnew (make-xref-entry caller relation)
+                      matches
+                      :test #'xref-entry-equal)))
+         matches)))
+    (:calls
+     (let ((direct-calls (get-relation :direct-calls name1 name2
+                                       :in-files in-files :in-functions in-functions
+                                       :exhaustive exhaustive :errorp errorp))
+           (indirect-calls (get-relation :indirect-calls name1 name2
+                                         :in-files in-files :in-functions in-functions
+                                         :exhaustive exhaustive :errorp errorp))
+           (macro-calls (get-relation :macro-calls name1 name2
+                                      :in-files in-files :in-functions in-functions
+                                      :exhaustive exhaustive :errorp errorp)))
+       (if (or (eql name1 :wild) (eql name2 :wild))
+           ;; need to weed out possible duplicates here
+           (let ((matches nil))
+             (dolist (c direct-calls) (pushnew c matches))
+             (dolist (c indirect-calls) (pushnew c matches))
+             (dolist (c macro-calls) (pushnew c matches))
+             matches)
+         (when (or direct-calls indirect-calls macro-calls)
+           name2))))
+    (:uses
+     (let ((binds (get-relation :binds name1 name2 :in-files in-files
+                                :in-functions in-functions :errorp errorp
+                                :exhaustive exhaustive))
+           (references (get-relation :binds name1 name2 :in-files in-files
+                                     :in-functions in-functions :errorp errorp
+                                     :exhaustive exhaustive))
+           (sets (get-relation :sets name1 name2 :in-files in-files
+                               :in-functions in-functions :errorp errorp
+                               :exhaustive exhaustive)))
+       (if (or (eql name1 :wild) (eql name2 :wild))
+           (concatenate 'list binds references sets)
+         (when (or binds references sets)
+           name2))))))
+
+;; %DO-WILD-XREF-LOOKUP -- internal
+;;
+;; Does a wild lookup into the xref database and returns a list of matches.
+;;
+;; FIXME: implement filtering by files
+(defun %do-wild-xref-lookup (name table in-files in-functions)
+  (declare (ignore in-files))
+  (multiple-value-bind (value foundp) (gethash name table)
+    (declare (ignore foundp))
+    (if in-functions
+        (remove-if (lambda (x) (not (find x in-functions))) value)
+      value)))
+
+;; %DO-SIMPLE-XREF-LOOKUP -- internal
+;;
+;; Does a simple lookup into the xref database and returns NAME2 if a relation
+;; between NAME1 and NAME2 exists.
+;;
+;; FIXME: implement filtering by files
+(defun %do-simple-xref-lookup (name1 name2 table in-files in-functions)
+  (declare (ignore in-files))
+  (when (some (lambda (x)
+                (when in-functions
+                  (find x in-functions))
+                (eql x name2))
+              (gethash name1 table))
+    name2))
+
+
+(defun %print-xref-entries (entries stream verbose)
+  (dolist (entry entries)
+    (if (eql (xref-entry-type entry) 'method)
+        ;; print qualifiers and specializers if it's a method
+        (format stream "~5,5T~A ~@[~A ~]~A~%"
+                (xref-entry-name entry)
+                (xref-entry-method-qualifiers entry)
+                (xref-entry-method-specializers entry))
+      (format stream "~5,5T~A~%" (xref-entry-name entry)))
+    ;; print extra information when verbose
+    (when verbose
+      (format stream "~5,5T  Type: ~A~%" (xref-entry-type entry))
+      (let ((file (%source-file-for-xref-entry entry)))
+        (format stream "~5,5T  File: ~A~%~%" (if file file "not recorded"))))))
+
+
+;; WHO-DIRECTLY-CALLS -- external
+;;
+(defun who-directly-calls (name &key inverse in-files in-functions verbose
+                                (stream *standard-output*))
+  "Prints information about direct callers of NAME. If INVERSE is true,
+it will print direct callees of NAME instead."
+  (let ((callers/callees (if inverse
+                             (get-relation :direct-calls name :wild 
+                                           :in-files in-files
+                                           :in-functions in-functions)
+                           (get-relation :direct-calls :wild name
+                                         :in-files in-files
+                                         :in-functions in-functions
+                                         :exhaustive t))))
+    (format stream "~%~T")
+    (if callers/callees
+        (progn
+          (format stream "~A ~:[is directly called by~;directly calls~]:~%"
+                  name inverse)
+          (%print-xref-entries callers/callees stream verbose))
+      (format stream "No direct ~:[callers~;callees~] of ~A were found in the database~%"
+              inverse name)))
+  (values))
+
+;; WHO-INDIRECTLY-CALLS -- external
+;;
+;; FIXME: Implement this (we can't currently detect indirect calls).
+(defun who-indirectly-calls (name &key inverse in-files in-functions verbose
+                                  (stream *standard-output*))
+  "Prints information about indirect callers of NAME. If INVERSE is true,
+it will print indirect callees of NAME instead."
+  (let ((callers/callees (if inverse
+                             (get-relation :indirect-calls name :wild 
+                                           :in-files in-files
+                                           :in-functions in-functions)
+                           (get-relation :indirect-calls :wild name
+                                         :in-files in-files
+                                         :in-functions in-functions))))
+    (format stream "~%~T")
+    (if callers/callees
+        (progn
+          (format stream "~A ~:[is indirectly called by~;indirectly calls~]:~%"
+                  name inverse)
+          (%print-xref-entries callers/callees stream verbose))
+      (format stream "No indirect ~:[callers~;callees~] of ~A were found in the database~%"
+              inverse name)))
+  (values))
+
+;; MACROS-CALLED-BY -- external
+;;
+(defun macros-called-by (name &key inverse in-files in-functions verbose
+                              (stream *standard-output*))
+  "Prints information about macros which get called by NAME. If INVERSE is true,
+it will list all functions which macroexpand NAME instead."
+    (let ((callers/callees (if (not inverse)
+                             (get-relation :macro-calls name :wild 
+                                           :in-files in-files
+                                           :in-functions in-functions)
+                           (get-relation :macro-calls :wild name
+                                         :in-files in-files
+                                         :in-functions in-functions))))
+    (format stream "~%~T")
+    (if callers/callees
+        (progn
+          (format stream "~A ~:[is macro called by~;macro calls~]:~%"
+                name (not inverse))
+          (%print-xref-entries callers/callees stream verbose))
+      (format stream "No macro ~:[callers~;callees~] of ~A were found in the database~%"
+              (not inverse) name)))
+    (values))
+
+;; WHO-CALLS -- external
+;;
+(defun who-calls (name &key inverse in-files in-functions verbose
+                       (stream *standard-output*))
+  "Shorthand for WHO-DIRECTLY-CALLS, WHO-INDIRECTLY-CALLS and
+MACROS-CALLED-BY."
+  (who-directly-calls name :inverse inverse :stream stream :verbose verbose
+                           :in-files in-files :in-functions in-functions)
+  (who-indirectly-calls name :inverse inverse :stream stream :verbose verbose
+                             :in-files in-files :in-functions in-functions)
+  (macros-called-by name :inverse (not inverse) :stream stream :verbose verbose
+                         :in-files in-files :in-functions in-functions)
+  (values))
+
+
+;; WHO-BINDS -- external
+;;
+(defun who-binds (name &key inverse in-files in-functions verbose
+                       (stream *standard-output*))
+  "Prints a list of functions which bind NAME. If INVERSE is true, it will
+print a list of variables bound by NAME instead."
+  (let ((bindings (if inverse
+                      (get-relation :binds name :wild :in-files in-files
+                                    :in-functions in-functions)
+                    (get-relation :binds :wild name :in-files in-files
+                                  :in-functions in-functions))))
+    (format stream "~%~T")
+    (if bindings
+        (progn
+          (format stream "~A ~:[is bound by~;binds~]:" name inverse)
+          (%print-xref-entries bindings stream verbose))
+      (format stream "No ~:[bindings of~;symbols bound by~] ~A were found in the database~%"
+              inverse name)))
+  (values))
+
+;; WHO-REFERENCES -- external
+;;
+(defun who-references (name &key inverse in-files in-functions verbose
+                            (stream *standard-output*))
+  "Prints a list of functions which reference NAME. If INVERSE is true, it will
+print a list of variables referenced by NAME instead."
+  (let ((references (if inverse
+                        (get-relation :references name :wild :in-files in-files
+                                      :in-functions in-functions)
+                      (get-relation :references :wild name :in-files in-files
+                                    :in-functions in-functions))))
+    (format stream "~%~T")
+    (if references
+        (progn
+          (format stream "~A ~:[is referenced by~;references~]:~%" name inverse)
+          (%print-xref-entries references stream verbose))
+      (format stream "No ~:[references to~;symbols referenced by~] ~A were found in the database~%"
+              inverse name)))
+  (values))
+
+;; WHO-SETS -- external
+;;
+(defun who-sets (name &key inverse in-files in-functions verbose
+                      (stream *standard-output*))
+    "Prints a list of functions which set NAME. If INVERSE is true, it will
+print a list of variables set by NAME instead."
+  (let ((sets (if inverse
+                  (get-relation :sets name :wild :in-files in-files
+                                :in-functions in-functions)
+                (get-relation :sets :wild name :in-files in-files
+                              :in-functions in-functions))))
+    (format stream "~%~T")
+    (if sets
+        (progn
+          (format stream "~A ~:[is set by~;sets~]:~%" name inverse)
+          (%print-xref-entries sets stream verbose))
+      (format stream "No ~:[settings of~;symbols set by~] ~A were found in the database~%"
+              inverse name)))
+  (values))
+
+;; WHO-USES -- external
+;;
+(defun who-uses (name &key inverse in-files in-functions verbose
+                      (stream *standard-output*))
+  "Shorthand for WHO-BINDS, WHO-REFERENCES and WHO-SETS."
+  (who-binds name :inverse inverse :stream stream :verbose verbose
+                  :in-files in-files :in-functions in-functions)
+
+  (who-references name :inverse inverse :stream stream :verbose verbose
+                       :in-files in-files :in-functions in-functions)
+
+  (who-sets name :inverse inverse :stream stream :verbose verbose
+                 :in-files in-files :in-functions in-functions)
+  (values))
+
+
+;; XREF-DESCRIBE -- external
+;;
+(defun xref-describe (name &key verbose)
+  "Prints relevant cross-referencing information about NAME."
+  (if (fboundp name)
+      (progn
+        (who-calls name :stream *terminal-io* :verbose verbose)
+        (who-calls name :inverse t :stream *terminal-io* :verbose verbose)
+        (who-uses name :inverse t :stream *terminal-io* :verbose verbose))
+      (who-uses name :stream *terminal-io* :verbose verbose))
+  (values))
+
+
+;;; Hook into the Clozure CL compiler frontend, by pointing a couple
+;;; of its variables at our functions.
+(setq ccl::*nx-discard-xref-info-hook* #'%discard-xref-info-for-function)
+(setq ccl::*nx-add-xref-entry-hook* #'%add-xref-entry)
+
+(provide :xref)
Index: /branches/new-random/library/.cvsignore
===================================================================
--- /branches/new-random/library/.cvsignore	(revision 13309)
+++ /branches/new-random/library/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*fsl
+*~.*
Index: /branches/new-random/library/chud-metering.lisp
===================================================================
--- /branches/new-random/library/chud-metering.lisp	(revision 13309)
+++ /branches/new-random/library/chud-metering.lisp	(revision 13309)
@@ -0,0 +1,306 @@
+;;;-*-Mode: LISP; Package: (CHUD (:USE CL CCL)) -*-
+;;;
+;;;   Copyright (C) 2005,2008,2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Some of this is based on work done by Dan Knapp and Hamilton Link
+;;; (and possibly others.)
+
+;;; CHUD 4.4.3-5 claims to offer 64-bit support; however, the library
+;;; which provides the API to control CHUD metering functions still
+;;; seems to be 32-bit only.  Conditionalization for x86-64 and
+;;; for 64-bit targets is (so far) just an exercise.
+
+(defpackage "CHUD"
+  (:use "CL" "CCL")
+  (:export "METER" "*SHARK-CONFIG-FILE*"))
+  
+(in-package "CHUD")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (progn
+    #-darwin-target
+    (error "This code is Darwin/MacOSX-specific.")))
+
+
+(defparameter *shark-session-path* nil)
+
+(defloadvar *written-spatch-file* nil)
+
+(defparameter *shark-session-native-namestring* nil)
+
+(defparameter *shark-config-file* nil "Full pathname of .cfg file to use for profiling, or NIL.")
+
+(defun finder-open-file (namestring)
+  "Open the file named by NAMESTRING, as if it was double-clicked on
+in the finder"
+  (run-program "/usr/bin/open" (list namestring) :output nil))
+
+(defun ensure-shark-session-path ()
+  (unless *shark-session-path*
+    (multiple-value-bind (second minute hour date month year)
+	(decode-universal-time (get-universal-time))
+      (let* ((subdir (format nil "profiling-session-~A-~d_~d-~d-~d_~d.~d.~d"
+			     (pathname-name
+			      (car
+			       ccl::*command-line-argument-list*))
+			     (ccl::getpid)
+			     month
+			     date
+			     year
+			     hour
+			     minute
+			     second))
+	     (dir (make-pathname :directory (append (pathname-directory (user-homedir-pathname)) (list subdir)) :defaults nil))
+	     (native-name (ccl::native-untranslated-namestring dir)))
+	(ensure-directories-exist dir)
+	(setenv "SHARK_SEARCH_PATH_PATCH_FILES" native-name)
+	(setq *shark-session-native-namestring*
+	      native-name
+	      *shark-session-path* dir))))
+  *shark-session-path*)
+
+
+  
+
+(defloadvar *shark-process* nil)
+(defloadvar *sampling* nil)
+
+(defvar *debug-shark-process-output* nil)
+
+
+(defun safe-shark-function-name (function)
+  (let* ((name (format nil "~s" function)))
+    (subseq (nsubstitute #\0 #\# (nsubstitute #\. #\Space name)) 1)))
+
+(defun print-shark-spatch-record (fn &optional (stream t))
+  (let* ((code-vector #+ppc-target (uvref fn 0) #-ppc-target fn)
+         (startaddr (+ (ccl::%address-of code-vector)
+                       #+x8664-target 0
+                       #+ppc32-target target::misc-data-offset
+		       #-ppc32-target 0))
+         (endaddr (+ startaddr
+                     #+x8664-target
+                     (1+ (ash (1- (ccl::%function-code-words fn)
+                                  ) target::word-shift))
+                     #+ppc-target
+                     (* 4 (- (uvsize code-vector)
+				       #+ppc64-target 2
+				       #-ppc64-target 1)))))
+    ;; i hope all lisp sym characters are allowed... we'll see
+    (format stream "{~%~@
+                        ~a~@
+                        ~@?~@
+                        ~@?~@
+                        }~%"
+            (safe-shark-function-name fn)
+            #+32-bit-target "0x~8,'0x" #+64-bit-target "0x~16,'0x"
+            startaddr
+            #+32-bit-target "0x~8,'0x" #+64-bit-target "0x~16,'0x"
+            endaddr)))
+
+#+x8664-target
+(ccl::defx86lapfunction dynamic-dnode ((x arg_z))
+  (movq (% x) (% imm0))
+  (ref-global x86::heap-start arg_y)
+  (subq (% arg_y) (% imm0))
+  (shrq ($ x8664::dnode-shift) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+#+x8632-target
+(ccl::defx8632lapfunction dynamic-dnode ((x arg_z))
+  (movl (% x) (% imm0))
+  (ref-global x86::heap-start arg_y)
+  (subl (% arg_y) (% imm0))
+  (shrl ($ x8632::dnode-shift) (% imm0))
+  (box-fixnum imm0 arg_z)
+  (single-value-return))
+
+#+x8664-target
+(defun identify-functions-with-pure-code ()
+  (ccl::freeze)
+  (ccl::collect ((functions))
+    (block walk
+      (let* ((frozen-dnodes (ccl::frozen-space-dnodes)))
+        (ccl::%map-areas (lambda (o)
+                           (when (>= (dynamic-dnode o) frozen-dnodes)
+                             (return-from walk nil))
+                           (when (typep o 'ccl::function-vector)
+                             (functions (ccl::function-vector-to-function o))))
+                         ccl::area-dynamic
+                         )))
+    (functions)))
+
+#+x8632-target
+(defun identify-functions-with-pure-code ()
+  (ccl::freeze)
+  (ccl::collect ((functions))
+    (block walk
+      (let* ((frozen-dnodes (ccl::frozen-space-dnodes)))
+        (ccl::%map-areas (lambda (o)
+                           (when (>= (dynamic-dnode o) frozen-dnodes)
+                             (return-from walk nil))
+                           (when (typep o 'function)
+                             (functions o)))
+                         ccl::area-dynamic
+                         )))
+    (functions)))
+
+#+ppc-target
+(defun identify-functions-with-pure-code ()
+  (ccl::purify)
+  (multiple-value-bind (pure-low pure-high)
+                                 
+      (ccl::do-gc-areas (a)
+        (when (eql(ccl::%fixnum-ref a target::area.code)
+                  ccl::area-readonly)
+          (return
+            (values (ash (ccl::%fixnum-ref a target::area.low) target::fixnumshift)
+                    (ash (ccl::%fixnum-ref a target::area.active) target::fixnumshift)))))
+    (let* ((hash (make-hash-table :test #'eq)))
+      (ccl::%map-lfuns #'(lambda (f)
+                           (let* ((code-vector  (ccl:uvref f 0))
+                                  (startaddr (+ (ccl::%address-of code-vector)
+                                                target::misc-data-offset)))
+                             (when (and (>= startaddr pure-low)
+                                        (< startaddr pure-high))
+                               (push f (gethash code-vector hash))))))
+      (let* ((n 0))
+        (declare (fixnum n))
+        (maphash #'(lambda (k v)
+                     (declare (ignore k))
+                     (if (null (cdr v))
+                       (incf n)))
+                 hash)
+        (let* ((functions ()))
+          (maphash #'(lambda (k v)
+                       (declare (ignore k))
+                       (when (null (cdr v))
+                         (push (car v) functions)))
+                   hash)
+          (sort functions
+                #'(lambda (x y)
+                    (< (ccl::%address-of (uvref x 0) )
+                       (ccl::%address-of  (uvref y 0))))))))))
+        
+                           
+
+
+(defun generate-shark-spatch-file ()
+  (let* ((functions (identify-functions-with-pure-code)))
+    (with-open-file (f (make-pathname
+                        :host nil
+                        :directory (pathname-directory
+                                    (ensure-shark-session-path))
+                        :name (format nil "~a_~D"
+                                      (pathname-name
+                                       (car
+                                        ccl::*command-line-argument-list*))
+                                      (ccl::getpid))
+                        :type "spatch")
+                       :direction :output
+                       :if-exists :supersede)
+      (format f "!SHARK_SPATCH_BEGIN~%")
+      (dolist (fun functions)
+        (print-shark-spatch-record fun f))
+      (format f "!SHARK_SPATCH_END~%"))))
+
+(defun terminate-shark-process ()
+  (when *shark-process*
+    (signal-external-process *shark-process* #$SIGUSR2))
+  (setq *shark-process* nil
+	*sampling* nil))
+
+(defun toggle-sampling ()
+  (if *shark-process*
+    (progn
+      (signal-external-process *shark-process* #$SIGUSR1)
+      (setq *sampling* (not *sampling*)))
+    (warn "No active shark procsss")))
+
+(defun enable-sampling ()
+  (unless *sampling* (toggle-sampling)))
+
+(defun disable-sampling ()
+  (when *sampling* (toggle-sampling)))
+
+(defun ensure-shark-process (reset hook)
+  (when (or (null *shark-process*) reset)
+    (terminate-shark-process)
+    (when (or reset (not *written-spatch-file*))
+      (generate-shark-spatch-file))
+    (let* ((args (list "-b" "-1" "-a" (format nil "~d" (ccl::getpid))
+			     "-d" *shark-session-native-namestring*)))
+      (when *shark-config-file*
+	(push (ccl::native-untranslated-namestring *shark-config-file*)
+	      args)
+	(push "-m" args))
+      (setq *shark-process*
+	    (run-program "/usr/bin/shark"
+			 args
+			 :output :stream
+			 :status-hook hook
+			 :wait nil))
+      (let* ((output (external-process-output-stream *shark-process*)))
+	(do* ((line (read-line output nil nil) (read-line output nil nil)))
+	     ((null line))
+	  (when *debug-shark-process-output*
+	    (format t "~&~a" line))
+	  (when (search "ready." line :key #'char-downcase)
+            (sleep 1)
+	    (return)))))))
+
+(defun display-shark-session-file (line)
+  (let* ((last-quote (position #\' line :from-end t))
+	 (first-quote (and last-quote (position #\' line :end (1- last-quote) :from-end t)))
+	 (path (and first-quote  (subseq line (1+ first-quote) last-quote))))
+    (when path (finder-open-file path))))
+    
+(defun scan-shark-process-output (p)
+  (with-interrupts-enabled 
+      (let* ((out (ccl::external-process-output p)))
+	(do* ((line (read-line out nil nil) (read-line out nil nil)))
+	     ((null line))
+	  (when *debug-shark-process-output*
+	    (format t "~&~a" line))
+	  (when (search "Created session file:" line)
+	    (display-shark-session-file line)
+	    (return))))))
+
+
+
+(defmacro meter (form &key reset debug-output)
+  (let* ((hook (gensym))
+	 (block (gensym))
+	 (process (gensym)))
+    `(block ,block
+      (flet ((,hook (p)
+	       (when (or (eq (external-process-status p) :exited)
+			 (eq (external-process-status p) :signaled))
+		 (setq *shark-process* nil
+		       *sampling* nil))))
+	(let* ((*debug-shark-process-output* ,debug-output))
+	  (ensure-shark-process ,reset #',hook)
+	  (unwind-protect
+	       (progn
+		 (enable-sampling)
+		 ,form)
+	    (disable-sampling)
+	    (let* ((,process *shark-process*))
+	      (when ,process
+		(scan-shark-process-output ,process)))))))))
+
+;;; Try to clean up after ourselves when the lisp quits.
+(pushnew 'terminate-shark-process ccl::*save-exit-functions*)
Index: /branches/new-random/library/chud-metering.txt
===================================================================
--- /branches/new-random/library/chud-metering.txt	(revision 13309)
+++ /branches/new-random/library/chud-metering.txt	(revision 13309)
@@ -0,0 +1,157 @@
+Using Apple's CHUD metering tools from CCL
+==========================================
+
+Prerequisites
+-------------
+
+Apple's CHUD metering tools are available (as of this writing) from:
+
+<ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/>. 
+
+The CHUD tools are also generally bundled with Apple's XCode tools.
+CHUD 4.5.0 (which seems to be bundled with XCode 3.0) seems to work
+well with this interface; later versions may have problems.
+Versions of CHUD as old as 4.1.1 may work with 32-bit PPC versions
+of CCL; later versions (not sure exactly -what- versions) added
+x86, ppc64, and x86-64 support.
+
+One way to tell whether any version of the CHUD tools is installed
+is to try to invoke the "shark" command-line program (/usr/bin/shark)
+from the shell:
+
+shell> shark --help
+
+and verifying that that prints a usage summary.
+
+CHUD consists of several components, including command-line programs,
+GUI applications, kernel extensions, and "frameworks" (collections of
+libraries, headers, and other resources which applications can use to
+access functionality provided by the other components.)  Past versions
+of CCL/OpenMCL have used the CHUD framework libraries to control the
+CHUD profiler.  Even though the rest of CHUD is currently 64-bit aware,
+the frameworks are unfortunately still only available as 32-bit libraries,
+so the traditional way of controlling the profiling facility from OpenMCL
+has only worked from DarwinPPC32 versions.
+
+Two of the CHUD component programs are of particular interest:
+
+1) The "Shark" application (often installed in
+"/Developer/Applications/Performance Tools/Shark.app"), which provides
+a graphical user interface for exploring and analyzing profiling results
+and provides tools for creating "sampling configurations" (see below),
+among other things.
+
+2) the "shark" program ("/usr/bin/shark"), which can be used to control
+the CHUD profiling facility and to collect sampling data, which can then
+be displayed and analyzed in Shark.app.
+
+The fact that these two (substantially different) programs have names that
+differ only in alphabetic case may be confusing.  The discussion below
+tries to consistently distinguish between "the shark program" and "the
+Shark application".
+
+Usage synopsis
+--------------
+
+? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
+FACT
+? (require "CHUD-METERING")
+"CHUD-METERING"
+("CHUD-METERING")
+? (chud:meter (null (fact 10000)))
+NIL	      ; since that large number is not NULL
+
+and, a few seconds after the result is returned, a file whose
+name is of the form "session_nnn.mshark" will open in Shark.app.
+
+The fist time that CHUD:METER is used in a lisp session, it'll do a
+few things to prepare subsequent profiling sessions.  Those things
+include:
+
+1) creating a directory to store files that are related to using
+the CHUD tools in this lisp session.  This directory is created in
+the user's home directory and has a name of the form:
+
+profiling-session-<lisp-kernel>-<pid>_<mm>-<dd>-<yyyy>_<h>.<m>.<s>
+
+where <pid> is the lisp's process id, <lisp-kernel> is the name of
+the lisp kernel (of all things ...), and the other values provide
+a timestamp.
+
+2) does whatever needs to be done to ensure that currently-defined
+lisp functions don't move around as the result of GC activity, then
+writes a text file describing the names and addresses of those functions
+to the profiling-session directory created above.  (The naming conventions
+for and format of that file are described in
+
+<http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42>
+
+3) run the shark program ("/usr/bin/shark") and wait until it's ready to
+receive signals that control its operation.
+
+This startup activity typically takes a few seconds; after it's been
+completed, subsequent use of CHUD:METER doesn't involve that overhead.
+(See the discussion of :RESET below.)
+
+After any startup activity is complete, CHUD:METER arranges to send
+a "start profiling" signal to the running shark program, executes
+the form, sends a "stop profiling" signal to the shark program, and
+reads its diagnostic output, looking for the name of the ".mshark"
+file it produces.  If it's able to find this filename, it arranges
+for "Shark.app" to open it
+
+Profiling "configurations".
+--------------------------
+
+By default, a shark profiling session will:
+a) use "time based" sampling, to periodically interrupt the lisp
+   process and note the value of the program counter and at least
+   a few levels of call history.
+b) do this sampling once every millisecond
+c) run for up to 30 seconds, unless told to stop earlier.
+
+This is known as "the default configuration"; it's possible to use
+items on the "Config" menu in the Shark application to create alternate
+configurations which provide different kinds of profiling parameters
+and to save these configurations in files for subsequent reuse.
+(The set of things that CHUD knows how to monitor is large and interesting.)
+
+You use alternate profiling configurations (created and "exported" via
+Shark.app) with CHUD:METER, but the interface is a little awkward.
+
+Reference
+---------
+
+CHUD:*SHARK-CONFIG-FILE*   [Variable]
+
+When non-null, this should be the pathname of an alternate profiling
+configuration file created by the "Config Editor" in Shark.app.
+
+(CHUD:METER form &key (reset nil) (debug-output nil))  [Macro]
+
+Executes FORM (an arbitrary lisp form) and returns whatever result(s)
+it returns, with CHUD profiling enabled during the form's execution.
+Tries to determine the name of the session file (*.mshark) to which
+the shark program wrote profiling data and opens this file in the
+Shark application.
+
+Arguments:
+
+debug-output   - when non-nil, causes output generated by the shark program to
+                 be echoed to *TERMINAL-IO*.  For debugging.
+reset          - when non-nil, terminates any running instance of the
+                 shark program created by previous invocations of CHUD:METER
+                 in this lisp session, generates a new .spatch file 
+                 (describing the names and addresses of lisp functions),
+                 and starts a new instance of the shark program; if
+                 CHUD:*SHARK-CONFIG-FILE* is non-NIL when this new instance
+                 is started, that instance is told to use the specified
+                 config file for profiling (in lieu of the default profiling
+                 configuration.)
+
+Acknowledgments
+---------------
+
+Both Dan Knapp and Hamilton Link have posted similar CHUD interfaces
+to openmcl-devel in the past; Hamilton's also reported bugs in the
+spatch mechanism to CHUD developers (and gotten those bugs fixed.)
Index: /branches/new-random/library/core-files.lisp
===================================================================
--- /branches/new-random/library/core-files.lisp	(revision 13309)
+++ /branches/new-random/library/core-files.lisp	(revision 13309)
@@ -0,0 +1,1159 @@
+;;;
+;;;   Copyright (C) 2009, Clozure Associates and contributors
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; Functions to examine core files.
+
+(in-package :ccl)
+
+#+:linuxx8664-target
+(progn
+
+(export '(open-core close-core
+          core-heap-utilization map-core-areas map-core-pointers
+          core-q core-l core-w core-b
+          core-consp core-symbolp core-functionp core-listp core-nullp core-uvector-p
+          core-uvtype core-uvtypep core-uvref core-uvsize
+          core-car core-cdr core-object-type core-istruct-type
+          copy-from-core core-list
+          core-keyword-package core-find-package core-find-symbol
+          core-package-names core-package-name
+          core-map-symbols
+          core-symbol-name core-symbol-value core-symbol-package
+          core-gethash core-hash-table-count
+          core-lfun-name core-lfun-bits
+          core-find-class
+          core-instance-class
+          core-instance-p
+          core-instance-class-name
+          core-string-equal
+          core-all-processes core-process-name
+          core-find-process-for-id
+          core-print
+          core-print-call-history
+          ))
+
+(eval-when (:compile-toplevel :execute)
+  (require "HASHENV" "ccl:xdump;hashenv"))
+
+;; The intended way to use these facilities is to open up a particular core file once,
+;; and then repeatedly call functions to examine it.  So for convenience, we keep the
+;; core file in a global var, rather than making all user functions take an extra arg.
+;; There is nothing intrinsic that would prevent having multiple core files open at once.
+
+(defvar *current-core* nil)
+
+
+(defstruct core-info
+  pathname
+  sections
+  ;; uses either stream or ivector, determined at runtime
+  stream
+  mapped-ivector
+  raw-ivector
+  ;; caches
+  symbol-ptrs
+  classes-hash-table-ptr
+  lfun-names-table-ptr
+  process-class
+  )
+
+(defmethod print-object :around ((core core-info) (stream t))
+  (let ((*print-array* nil))
+    (call-next-method)))
+
+(declaim (type (or null core-info) *current-core*)
+         (ftype (function () core-info) current-core)
+         (inline current-core))
+
+(defun current-core ()
+  (or *current-core* (require-type *current-core* 'core-info)))
+
+(defun close-core ()
+  (let ((core *current-core*))
+    (setq *current-core* nil)
+    (when core
+      (when (core-info-stream core)
+        (close (core-info-stream core)))
+      (when (core-info-mapped-ivector core)
+        (unmap-ivector (core-info-mapped-ivector core)))
+      t)))
+
+;; TODO: after load sections, check if highest heap address is a fixnum, and
+;; arrange to use fixnum-only versions of the reading functions.
+(defun open-core (pathname &key (method :mmap))
+  (when *current-core*
+    (close-core))
+  (let* ((sections (readelf-sections pathname))
+         (core (make-core-info :pathname pathname :sections sections)))
+    (ecase method
+      (:mmap   (let ((mapped-vector (map-file-to-ivector pathname '(unsigned-byte 8))))
+                 (multiple-value-bind (vector offset) (array-data-and-offset mapped-vector)
+                   (loop for data across sections do (incf (cdr data) offset))
+                   (setf (core-info-mapped-ivector core) mapped-vector)
+                   (setf (core-info-raw-ivector core) vector))))
+      (:stream (setf (core-info-stream core)
+                     (open pathname :element-type '(unsigned-byte 8)))))
+    (setq *current-core* core))
+  pathname)
+
+;; Kinda stupid to call external program for this...
+(defun readelf-sections (pathname)
+  (flet ((split (line start end)
+           (loop while (setq start (position-if-not #'whitespacep line :start start :end end))
+                 as match = (cdr (assq (char line start) '((#\[ . #\]) (#\( . #\)) (#\< . #\>))))
+                 as next = (if match
+                             (1+ (or (position match line :start (1+ start) :end end)
+                                     (error "Unmatched ~c at position ~s" (char line start) start)))
+                             (or (position-if #'whitespacep line :start start :end end) end))
+                 collect (subseq line start next)
+                 do (setq start next))))
+    (let* ((file (native-translated-namestring pathname))
+           (string (with-output-to-string (output)
+                     (ccl:run-program "readelf" `("--sections" ,file) :output output)))
+           (sections (loop
+                       for start = (1+ (position #\newline string
+                                                 :start (1+ (position #\newline string
+                                                                      :start (position #\[ string)))))
+                         then next
+                       for next = (1+ (position #\newline string
+                                                :start (1+ (position #\newline string :start start))))
+                       while (eql #\space (aref string next))
+                       nconc
+                       (destructuring-bind (number name type address filepos size &optional ent-size flags link info align)
+                           (split string start next)
+                         (assert (and (eql (char number 0) #\[) (eql (char number (1- (length number))) #\])))
+                         (setq number (read-from-string number :start 1 :end (1- (length number))))
+                         (when (eql number 0)
+                           (shiftf align info link flags ent-size size filepos address type name ""))
+                         (setq address (parse-integer address :radix 16))
+                         (setq filepos  (parse-integer filepos :radix 16))
+                         (setq size (parse-integer size :radix 16))
+                         (setq ent-size (parse-integer ent-size :radix 16))
+                         (unless (eql size 0)
+                           (assert (and (equal link "0") (equal info "0") (equal align "1")))
+                           (list (list address filepos size))))))
+           (sections (cons (list most-positive-fixnum 0 0) sections));; hack for loop below
+           (sections (sort sections #'< :key #'car));; sort by address
+           (sections (loop
+                       with cur-address = -1
+                       with cur-filepos = -1
+                       with cur-end = cur-address
+                       for (address filepos size) in sections
+                       unless (or (= (+ cur-filepos (- address cur-address)) filepos)
+                                  (= cur-address cur-end))
+                         collect (cons cur-address cur-filepos)
+                       do (if (= (+ cur-filepos (- address cur-address)) filepos)
+                            (setq cur-end (max (+ address size) cur-end))
+                            (progn
+                              (assert (<= cur-end address));; no overlap.
+                              (setq cur-address address cur-filepos filepos cur-end (+ address size)))))))
+      (coerce sections 'vector))))
+
+(declaim (inline core-ivector-readb core-ivector-readw core-ivector-readl core-ivector-readq
+                 core-stream-readb core-stream-readw core-stream-readl core-stream-readq))
+(declaim (ftype (function (t t) (unsigned-byte 8)) core-ivector-readb core-stream-readb)
+         (ftype (function (t t) (unsigned-byte 16)) core-ivector-readw core-stream-readw)
+         (ftype (function (t t) (unsigned-byte 32)) core-ivector-readl core-stream-readl)
+         (ftype (function (t t) (unsigned-byte 64)) core-ivector-readq core-stream-readq)
+         (ftype (function (integer) fixnum) core-offset-for-address))
+
+(defun core-offset-for-address (address)
+  ;; sections are sorted, so could do binary search if this became a bottleneck.
+  ;; (there are around 50 sections)
+  (or (loop for prev = nil then sect as sect across (core-info-sections (current-core))
+            do (when (< address (car sect))
+                 (return (and prev (+ (cdr prev) (- address (car prev)))))))
+      (error "Unknown core address x~x" address)))
+
+(defun core-stream-readb (s offset)
+  (declare (type basic-input-stream s) (optimize (speed 3) (safety 0)))
+  (when offset (stream-position s offset))
+  (read-byte s))
+
+(defun core-stream-readw (s offset)
+  (declare (type basic-input-stream s) (optimize (speed 3) (safety 0)))
+  (when offset (stream-position s offset))
+  (%i+ (core-stream-readb s nil) (ash (core-stream-readb s nil) 8)))
+
+(defun core-stream-readl (s offset)
+  (declare (type basic-input-stream s) (optimize (speed 3) (safety 0)))
+  (when offset (stream-position s offset))
+  (%i+ (core-stream-readw s nil) (ash (core-stream-readw s nil) 16)))
+
+(defun core-stream-readq (s offset)
+  (declare (type basic-input-stream s) (optimize (speed 3) (safety 0)))
+  (when offset (stream-position s offset))
+  (+ (core-stream-readl s nil) (ash (core-stream-readl s nil) 32)))
+
+(defun core-ivector-readb (vec offset)
+  (declare (type (simple-array (unsigned-byte 8) (*)) vec) (fixnum offset)
+           (optimize (speed 3) (safety 0)))
+  (aref vec offset))
+
+(defun core-ivector-readw (vec offset)
+  (declare (optimize (speed 3) (safety 0)))
+  (%i+ (core-ivector-readb vec offset) (ash (core-ivector-readb vec (%i+ offset 1)) 8)))
+
+(defun core-ivector-readl (vec offset)
+  (declare (optimize (speed 3) (safety 0)))
+  (%i+ (core-ivector-readw vec offset) (ash (core-ivector-readw vec (%i+ offset 2)) 16)))
+
+(defun core-ivector-readq (vec offset)
+  (declare (optimize (speed 3) (safety 0)))
+  (+ (core-ivector-readl vec offset) (ash (core-ivector-readl vec (%i+ offset 4)) 32)))
+
+
+(defun core-q (address &optional (offset 0))
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((core (current-core))
+         (ivector (core-info-raw-ivector core)))
+    (declare (type core-info core))
+    (if ivector
+      (core-ivector-readq ivector (core-offset-for-address (+ address offset)))
+      (core-stream-readq (core-info-stream core) (core-offset-for-address (+ address offset))))))
+
+(defun core-l (address &optional (offset 0))
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((core (current-core))
+         (ivector (core-info-raw-ivector core)))
+    (declare (type core-info core))
+    (if ivector
+      (core-ivector-readl ivector (core-offset-for-address (+ address offset)))
+      (core-stream-readl (core-info-stream core) (core-offset-for-address (+ address offset))))))
+
+(defun core-w (address &optional (offset 0))
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((core (current-core))
+         (ivector (core-info-raw-ivector core)))
+    (declare (type core-info core))
+    (if ivector
+      (core-ivector-readw ivector (core-offset-for-address (+ address offset)))
+      (core-stream-readw (core-info-stream core) (core-offset-for-address (+ address offset))))))
+
+(defun core-b (address &optional (offset 0))
+  (declare (optimize (speed 3) (safety 0)))
+  (let* ((core (current-core))
+         (ivector (core-info-raw-ivector core)))
+    (declare (type core-info core))
+    (if ivector
+      (core-ivector-readb ivector (core-offset-for-address (+ address offset)))
+      (core-stream-readb (core-info-stream core) (core-offset-for-address (+ address offset))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; general utilities
+
+;; NIL is constant, assume is same in core as here.
+(defun kernel-global-address (global)
+  (check-type global symbol)
+  (+ (target-nil-value) (target::%kernel-global global)))
+
+(defun nil-relative-symbol-address (sym)
+  (+ (target-nil-value)
+     #x20  ;;; dunno why
+     (* (or (position sym x86::*x86-nil-relative-symbols* :test #'eq)
+            (error "Not a nil-relative symbol ~s" sym))
+        target::symbol.size)
+     (- target::fulltag-symbol target::fulltag-nil)))
+
+(defun core-area-name (code)
+  (or (heap-area-name code)
+      (and (integerp code)
+           (not (logtest code (1- (ash 1 target::fixnum-shift))))
+           (heap-area-name (ash code (- target::fixnum-shift))))))
+
+(defx86lapfunction %%raw-obj ((address arg_z))
+  (unbox-fixnum address arg_z)
+  (single-value-return))
+
+(declaim (inline uvheader-p uvheader-typecode uvheader-size))
+
+(defun uvheader-p (header)
+  (let ((tag (logand header target::fulltagmask)))
+    (declare (fixnum tag))
+    (and (<= target::fulltag-nodeheader-0 tag)
+         (<= tag target::fulltag-immheader-2)
+         (neq tag target::fulltag-odd-fixnum))))
+
+(defun uvheader-typecode (header)
+  (the fixnum (logand #xFF header)))
+
+(defun uvheader-size (header)
+  (ash header (- target::num-subtag-bits)))
+
+(defun uvheader-byte-size (header)
+  (x8664::x8664-misc-byte-count (uvheader-typecode header) (uvheader-size header)))
+
+(defun uvheader-type (header)
+  (let* ((typecode (uvheader-typecode header))
+         (low4 (logand typecode target::fulltagmask))
+         (high4 (ash typecode (- target::ntagbits))))
+    (declare (type (unsigned-byte 8) typecode)
+             (type (unsigned-byte 4) low4 high4))
+    (cond ((eql low4 x8664::fulltag-immheader-0)
+           (%svref *immheader-0-types* high4))
+          ((eql low4 x8664::fulltag-immheader-1)
+           (%svref *immheader-1-types* high4))
+          ((eql low4 x8664::fulltag-immheader-2)
+           (%svref *immheader-2-types* high4))
+          ((eql low4 x8664::fulltag-nodeheader-0)
+           (%svref *nodeheader-0-types* high4))
+          ((eql low4 x8664::fulltag-nodeheader-1)
+           (%svref *nodeheader-1-types* high4))
+          (t 'bogus))))
+
+(defun uvheader-type-typecode (symbol &aux pos)
+  (unless (eq symbol 'bogus)
+    (cond ((setq pos (position symbol *immheader-0-types*))
+           (logior (ash pos target::ntagbits) target::fulltag-immheader-0))
+          ((setq pos (position symbol *immheader-1-types*))
+           (logior (ash pos target::ntagbits) target::fulltag-immheader-1))
+          ((setq pos (position symbol *immheader-2-types*))
+           (logior (ash pos target::ntagbits) target::fulltag-immheader-2))
+          ((setq pos (position symbol *nodeheader-0-types*))
+           (logior (ash pos target::ntagbits) target::fulltag-nodeheader-0))
+          ((setq pos (position symbol *nodeheader-1-types*))
+           (logior (ash pos target::ntagbits) target::fulltag-nodeheader-1)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;  Core heap
+
+(defun map-core-areas (function &key area)
+  (setq area (cond ((or (eq area t) (eq area nil)) nil)
+                   ((consp area) (mapcar #'heap-area-code area))
+                   (t (list (heap-area-code area)))))
+  (loop for area-ptr = (core-q (core-q (kernel-global-address 'all-areas)) target::area.succ)
+          then (core-q area-ptr target::area.succ)
+        as code = (ash (core-q area-ptr target::area.code) (- target::fixnum-shift))
+        until (= code area-void)
+        do (when (and (<= area-readonly code)
+                      (<= code area-dynamic)
+                      (or (null area) (member code area))
+                      (< (core-q area-ptr target::area.low) (core-q area-ptr target::area.active)))
+             #+debug
+             (format t "~& AREA at x~x, type = ~a low = x~x active = x~x (size = x~x out of x~x)"
+                     area-ptr (core-area-name code)
+                     (core-q area-ptr target::area.low)
+                     (core-q area-ptr target::area.active)
+                     (- (core-q area-ptr target::area.active) (core-q area-ptr target::area.low))
+                     (- (core-q area-ptr target::area.high) (core-q area-ptr target::area.low)))
+             (map-core-area area-ptr function))))
+
+(defun map-core-area (area-ptr fun)
+  (let* ((ptr (core-q area-ptr target::area.low))
+         (end (core-q area-ptr target::area.active)))
+    (loop
+      (when (>= ptr end) (return))
+      (let ((header (core-q ptr)))
+        (cond ((uvheader-p header)
+               (let ((subtag (uvheader-typecode header)))
+                 (funcall fun
+                          (+ ptr (cond ((eq subtag target::subtag-symbol) target::fulltag-symbol)
+                                       ((eq subtag target::subtag-function) target::fulltag-function)
+                                       (t target::fulltag-misc)))))
+               (let* ((bytes (uvheader-byte-size header))
+                      (total (logandc2 (%i+ bytes (+ target::node-size (1- target::dnode-size)))
+                                       (1- target::dnode-size))))
+                 (declare (fixnum bytes total))
+                 (incf ptr total)))
+              (t
+               (funcall fun (+ ptr target::fulltag-cons))
+               (incf ptr target::cons.size)))))))
+
+
+(declaim (inline core-consp core-symbolp core-functionp core-listp core-nullp))
+
+(defun core-consp (ptr)
+  (eq (logand ptr target::fulltagmask) target::fulltag-cons))
+
+(defun core-symbolp (ptr)
+  (eq (logand ptr target::fulltagmask) target::fulltag-symbol))
+
+(defun core-functionp (ptr)
+  (eq (logand ptr target::fulltagmask) target::fulltag-function))
+
+(defun core-listp (ptr)
+  (eq (logand ptr target::tagmask) target::tag-list))
+
+(defun core-nullp (obj)
+  (eq (logand obj target::fulltagmask) target::fulltag-nil))
+
+;; uvector utilities
+(declaim (inline core-uvector-p core-uvheader core-uvtypecode core-uvtype))
+
+(defun core-uvector-p (ptr)
+  (%i>= (logand ptr target::fulltagmask) target::fulltag-misc))
+
+(defun core-uvheader (vec-ptr)
+  (core-q (logandc2 vec-ptr target::fulltagmask)))
+
+(defun core-uvtypecode (vec-ptr)
+  (uvheader-typecode (core-uvheader vec-ptr)))
+
+(defun core-uvtype (vec-ptr)
+  (uvheader-type (core-uvheader vec-ptr)))
+
+(defmacro core-uvtypep (vec-ptr type &aux temp)
+  (when (keywordp type)
+    (setq type (type-keyword-code type)))
+  (when (and (or (symbolp (setq temp type))
+                 (and (quoted-form-p type)
+                      (symbolp (setq temp (cadr type)))))
+             (setq temp (find-symbol (symbol-name temp) :ccl))
+             (setq temp (uvheader-type-typecode temp)))
+    (setq type temp))
+  (when (constant-symbol-p type)
+    (setq temp (symbol-value type))
+    (when (<= 0 temp #xFF) (setq type temp)))
+  `(let ((vec-ptr ,vec-ptr))
+     (and (core-uvector-p vec-ptr)
+          (eq (core-uvtypecode vec-ptr) ,type))))
+
+(defun core-uvref (vec-ptr index)
+  (let* ((header (core-uvheader vec-ptr))
+         (addr (+ (logandc2 vec-ptr target::fulltagmask) target::node-size))
+         (typecode (uvheader-typecode header))
+         (tag (logand typecode target::fulltagmask))
+         (len (uvheader-size header)))
+    (assert (< -1 index len))
+    (cond ((or (eql tag target::fulltag-nodeheader-0)
+               (eql tag target::fulltag-nodeheader-1))
+           (core-q addr (ash index target::word-shift)))
+          ((eql tag target::ivector-class-64-bit)
+           (cond ((eq typecode target::subtag-double-float-vector)
+                  (error "~s not implemented yet" 'target::subtag-double-float-vector))
+                 (t
+                  (core-q addr (ash index target::word-shift)))))
+          ((eq tag target::ivector-class-32-bit)
+           (cond ((eq typecode target::subtag-simple-base-string)
+                  (code-char (core-l addr (ash index 2))))
+                 ((eq typecode target::subtag-single-float-vector)
+                  (error "~s not implemented yet" 'target::subtag-single-float-vector))
+                 (t (core-l addr (ash index 2)))))
+          ((eq typecode target::subtag-bit-vector)
+           (let ((byte (core-b addr (ash (+ index 7) -3))))
+             (error "not implemented, for ~b" byte)))
+          ((>= typecode target::min-8-bit-ivector-subtag)
+           (core-b addr index))
+          (t (core-w addr (ash index 1))))))
+
+(defun core-uvsize (vec-ptr)
+  (uvheader-size (core-uvheader vec-ptr)))
+
+(defun core-car (obj)
+  (assert (core-listp obj))
+  (core-q obj target::cons.car))
+
+(defun core-cdr (obj)
+  (assert (core-listp obj))
+  (core-q obj target::cons.cdr))
+
+(defun core-object-type (obj)
+  (let ((fulltag (logand obj target::fulltagmask)))
+    (cond ((eq fulltag target::fulltag-cons) 'cons)
+          ((eq fulltag target::fulltag-nil) 'null)
+          ((eq (logand fulltag target::tagmask) target::tag-fixnum) 'fixnum)
+          ((and (or (eq fulltag target::fulltag-imm-0)
+                    (eq fulltag target::fulltag-imm-1))
+                (fixnump obj))
+           ;; Assumes we're running on same architecture as core file.
+           (type-of (%%raw-obj obj)))
+          ((eq (logand fulltag target::tagmask) target::tag-tra) 'tagged-return-address)
+          ((eq fulltag target::fulltag-misc) (core-uvtype obj))
+          ((eq fulltag target::fulltag-symbol) 'symbol)
+          ;; TODO: Could get hairier based on lfun-bits, but usually don't care.
+          ((eq fulltag target::fulltag-function) 'function)
+          (t (cerror "treat as ~*~s" "Invalid object tag at #x~x" obj 'bogus)
+           'bogus))))
+
+(defun core-istruct-type (obj)
+  (and (core-uvtypep obj :istruct)
+       (core-car (core-uvref obj 0))))
+       
+
+(defun core-object-type-and-size (obj)
+  (let ((fulltag (logand obj target::fulltagmask)))
+    (if (eq fulltag target::fulltag-cons)
+      (values 'cons target::dnode-size target::dnode-size)
+      (if (%i<= target::fulltag-misc fulltag)
+        (let* ((header (core-uvheader obj))
+               (logsize (uvheader-byte-size header))
+               ;; total including header and alignment.
+               (total (logandc2 (+ logsize target::node-size (1- target::dnode-size))
+                                (1- target::dnode-size))))
+          (values (uvheader-type header) logsize total))))))
+
+(defun core-heap-utilization (&key area unit sort)
+  (let* ((hash (make-hash-table :shared nil))
+         (total-physsize 0)
+         (div (ecase unit
+                ((nil) 1)
+                (:kb 1024.0d0)
+                (:mb (* 1024.0d0 1024.0d0))
+                (:gb (* 1024.0d0 1024.0d0 1024.0d0))))
+         (sort-key (ecase sort
+                     (:count #'cadr)
+                     (:logical-size #'caddr)
+                     ((:physical-size nil) #'cdddr)))
+         (all nil))
+    (map-core-areas (lambda (obj)
+                      (multiple-value-bind (type logsize physsize) (core-object-type-and-size obj)
+                        (let ((a (or (gethash type hash)
+                                     (setf (gethash type hash) (list* 0 0 0)))))
+                          (incf (car a))
+                          (incf (cadr a) logsize)
+                          (incf (cddr a) physsize))))
+                    :area area)
+    (maphash (lambda (type data)
+               (incf total-physsize (cddr data))
+               (push (cons type data) all))
+             hash)
+    (setq all (sort all #'> :key sort-key))
+    (format t "~&Object type~42tCount    Logical size   Physical size   % of Heap~%~50t~a~66t~:*~a"
+            (ecase unit
+              ((nil) " (in bytes)")
+              (:kb   "(in kilobytes)")
+              (:mb   "(in megabytes)")
+              (:gb   "(in gigabytes)")))
+    (loop for (type count logsize . physsize) in all
+          do (if unit
+               (format t "~&~a~36t~11d~16,2f~16,2f~11,2f%"
+                       type
+                       count
+                       (/ logsize div)
+                       (/ physsize div)
+                       (* 100.0 (/ physsize total-physsize)))
+               (format t "~&~a~36t~11d~16d~16d~11,2f%"
+                       type
+                       count
+                       logsize
+                       physsize
+                       (* 100.0 (/ physsize total-physsize)))))
+    (if unit
+      (format t "~&Total~63t~16,2f" (/ total-physsize div))
+      (format t "~&Total~63t~16d" total-physsize)))
+  (values))
+
+
+(defstruct unresolved-address address)
+
+(defmethod print-object ((obj unresolved-address) stream)
+  (let* ((address (unresolved-address-address obj)))
+    (format stream "#<Core ~S~@[[~d]~] #x~x >" 
+            (core-object-type address)
+            (and (core-uvector-p address) (core-uvsize address))
+            address)))
+
+(defun copy-from-core (obj &key (depth 1))
+  (check-type depth (integer 0))
+  (when (unresolved-address-p obj)
+    (setq obj (unresolved-address-address obj)))
+  (let ((fulltag (logand obj target::fulltagmask)))
+    (cond ((eq fulltag target::fulltag-nil) nil)
+          ((eq (logand fulltag target::tagmask) target::tag-fixnum)
+           (ash obj (- target::fixnum-shift)))
+          ((and (fixnump obj)
+                (or (eq fulltag target::fulltag-imm-0)
+                    (eq fulltag target::fulltag-imm-1)))
+           (%%raw-obj obj))
+          ((< (decf depth) 0)
+           (make-unresolved-address :address obj))
+          ((%i<= target::fulltag-misc fulltag)
+           (or (and (core-uvtypep obj :package)
+                    (find-package (core-package-name obj)))
+               (let ((v (%copy-uvector-from-core obj depth)))
+                 (when (and (symbolp v) (<= depth 1))
+                   ;; Need to fix up the package slot else it's not useful
+                   (let ((pp (%svref (symptr->symvector v) target::symbol.package-predicate-cell)))
+                     (when (unresolved-address-p pp)
+                       (setq pp (copy-from-core pp :depth 1)))
+                     (when (and (consp pp) (unresolved-address-p (car pp)))
+                       (let ((pkg (unresolved-address-address (car pp))))
+                         (when (and (core-uvtypep pkg :package)
+                                    (setq pkg (find-package (core-package-name pkg))))
+                           (setf (car pp) pkg))))
+                     (setf (%svref (symptr->symvector v) target::symbol.package-predicate-cell) pp))
+                   ;; ditto for pname
+                   (let ((pp (%svref (symptr->symvector v) target::symbol.pname-cell)))
+                     (when (unresolved-address-p pp)
+                       (setf (%svref (symptr->symvector v) target::symbol.pname-cell)
+                             (copy-from-core pp :depth 1)))))
+                 v)))
+          ((eq fulltag target::fulltag-cons)
+           (cons (copy-from-core (core-car obj) :depth depth)
+                 (copy-from-core (core-cdr obj) :depth depth)))
+          (t (make-unresolved-address :address obj)))))
+
+(defun %copy-uvector-from-core (vec-ptr depth)
+  (let* ((header (core-uvheader vec-ptr))
+         (addr (+ (logandc2 vec-ptr target::fulltagmask) target::node-size))
+         (typecode (uvheader-typecode header))
+         (tag (logand typecode target::fulltagmask))
+         (len (uvheader-size header))
+         (vec (%alloc-misc len typecode)))
+    (cond ((or (eq tag target::fulltag-nodeheader-0)
+               (eq tag target::fulltag-nodeheader-1))
+           (when (eql typecode target::subtag-function)
+             ;; Don't bother copying the code for now
+             (let ((skip (core-l addr)))
+               (assert (<= 0 skip len))
+               (incf addr (ash skip target::word-shift))
+               (decf len skip)))
+           (dotimes (i len)
+             (setf (%svref vec i)
+                   (copy-from-core (core-q addr (ash i target::word-shift)) :depth depth)))
+           (let ((ptrtag (logand vec-ptr target::fulltagmask)))
+             (cond ((eql ptrtag target::fulltag-symbol)
+                    (%symvector->symptr vec))
+                   ((eql ptrtag target::fulltag-function)
+                    (%function-vector-to-function vec))
+                   (t vec))))
+          ((eq tag target::ivector-class-64-bit)
+           (cond ((eq typecode target::subtag-double-float-vector)
+                  (warn "~s not implemented yet" 'target::subtag-double-float-vector)
+                  (make-unresolved-address :address vec-ptr))
+                 (t
+                  (dotimes (i len vec)
+                    (setf (uvref vec i) (core-q addr (ash i target::word-shift)))))))
+          ((eq tag target::ivector-class-32-bit)
+           (cond ((eq typecode target::subtag-simple-base-string)
+                  (dotimes (i len vec)
+                    (setf (uvref vec i) (code-char (core-l addr (ash i 2))))))
+                 ((eq typecode target::subtag-single-float-vector)
+                  (warn "~s not implemented yet" 'target::subtag-single-float-vector)
+                  (make-unresolved-address :address vec-ptr))
+                 (t
+                  (dotimes (i len vec)
+                    (setf (uvref vec i) (core-l addr (ash i 2)))))))
+          ((eq typecode target::subtag-bit-vector)
+           (warn "bit vector not implemented yet")
+           (make-unresolved-address :address vec-ptr))
+          ((>= typecode target::min-8-bit-ivector-subtag)
+           (dotimes (i len vec)
+             (setf (uvref vec i) (core-b addr i))))
+          (t
+           (dotimes (i len vec)
+             (setf (uvref vec i) (core-w addr (ash i 1))))))))
+
+(defun map-core-pointers (fn &key area)
+  (map-core-areas (lambda (obj)
+                    (cond ((core-consp obj)
+                           (funcall fn (core-car obj) obj 0)
+                           (funcall fn (core-cdr obj) obj 1))
+                          (t
+                           (let* ((header (core-uvheader obj))
+                                  (subtag (logand header target::fulltagmask)))
+                             (when (or (eq subtag target::fulltag-nodeheader-0)
+                                       (eq subtag target::fulltag-nodeheader-1))
+                               (let* ((typecode (uvheader-typecode header))
+                                      (len (uvheader-size header))
+                                      (addr (+ (logandc2 obj target::fulltagmask) target::node-size)))
+                                 (when (eql typecode target::subtag-function)
+                                   (let ((skip (core-l addr)))
+                                     (assert (<= 0 skip len))
+                                     (incf addr (ash skip target::word-shift))
+                                     (decf len skip)))
+                                 (dotimes (i len)
+                                   (funcall fn (core-q addr (ash i target::word-shift)) obj i))))))))
+                  :area area))
+
+(defun core-find-tra-function (tra)
+  (assert (eq (logand tra target::tagmask) target::tag-tra))
+  (map-core-areas (lambda (obj)
+                    (when (core-uvtypep obj :function)
+                      (let* ((addr (+ (logandc2 obj target::fulltagmask) target::node-size))
+                             (skip  (core-l addr))
+                             (offset (- tra addr)))
+                        (when (<= 0 offset (ash skip target::word-shift))
+                          (return-from core-find-tra-function (values obj (+ offset (- target::node-size
+                                                                                       (logand obj target::fulltagmask)))))))))))
+
+(defun core-instance-class (obj)
+  (when (core-uvtypep obj :slot-vector)
+    (setq obj (core-uvref obj slot-vector.instance)))
+  (assert (core-uvtypep obj :instance))
+  (core-uvref (core-uvref obj instance.class-wrapper) %wrapper-class))
+
+(defun core-instance-p (obj class)
+  (and (core-uvtypep obj :instance)
+       (labels ((matchp (iclass)
+                  (or (eql iclass class)
+                      (loop for supers = (core-uvref (core-uvref iclass instance.slots) %class.local-supers)
+                              then (core-cdr supers)
+                            while (core-consp supers)
+                            thereis (matchp (core-car supers))))))
+         (matchp (core-instance-class obj)))))
+
+
+(defun core-instance-class-name (obj)
+  (let* ((class (core-instance-class obj))
+         (class-slots (core-uvref class instance.slots))
+         (name (core-uvref class-slots %class.name)))
+    (core-symbol-name name)))
+
+(defun core-symptr (obj)
+  (if (core-nullp obj)
+    (nil-relative-symbol-address 'nil)
+    (when (core-uvtypep obj :symbol)
+      (let ((tag (logand obj target::fulltagmask)))
+        (unless (eq tag target::fulltag-symbol)
+          (incf obj (%i- target::fulltag-symbol tag))))
+      obj)))
+    
+(defun core-symbol-name (obj)
+  (when (setq obj (core-symptr obj))
+    (copy-from-core (core-q obj target::symbol.pname) :depth 1)))
+
+(defun core-symbol-value (obj)
+  (when (setq obj (core-symptr obj))
+    (core-q obj target::symbol.vcell)))
+
+(defun core-symbol-package (obj)
+  (when (setq obj (core-symptr obj))
+    (let ((cell (core-q obj target::symbol.package-predicate)))
+      (if (core-consp cell)
+        (core-car cell)
+        cell))))
+
+(defun core-all-packages-ptr ()
+  (core-symbol-value (nil-relative-symbol-address '%all-packages%)))
+
+(defun core-keyword-package ()
+  (core-symbol-value (nil-relative-symbol-address '*keyword-package*)))
+
+(defun core-symbol-pointers ()
+  (or (core-info-symbol-ptrs (current-core))
+      (let ((vector (make-array 1000 :adjustable t :fill-pointer 0))
+            (keys (core-keyword-package)))
+        (map-core-areas (lambda (obj)
+                          (when (core-symbolp obj)
+                            (unless (eq (core-symbol-package obj) keys)
+                              (vector-push-extend obj vector)))))
+        (setf (core-info-symbol-ptrs (current-core)) vector))))
+
+(defun core-map-symbols (fun)
+  (loop for sym-ptr across (core-symbol-pointers) do (funcall fun sym-ptr)))
+
+
+(defun core-string-equal (ptr string &aux (len (length string)))
+  (assert (core-uvtypep ptr :simple-string))
+  (when (eq (core-uvsize ptr) len)
+    (loop for i from 0 below len
+          always (eql (core-uvref ptr i) (aref string i)))))
+
+(defun core-find-package (name &key error)
+  (setq name (string name))
+  (or (loop for list-ptr = (core-all-packages-ptr) then (core-cdr list-ptr)
+            while (core-consp list-ptr)
+            as pkg-ptr = (core-car list-ptr)
+            when (loop for names-ptr = (core-uvref pkg-ptr pkg.names) then (core-cdr names-ptr)
+                       while (core-consp names-ptr)
+                       as name-ptr = (core-car names-ptr)
+                       thereis (core-string-equal name-ptr name))
+              do (return pkg-ptr))
+      (and error (error "No package named ~s" name))))
+
+(defun core-package-names (pkg-ptr)
+  (assert (core-uvtypep pkg-ptr :package))
+  (copy-from-core (core-uvref pkg-ptr pkg.names) :depth 2))
+
+(defun core-package-name (pkg-ptr)
+  (assert (core-uvtypep pkg-ptr :package))  
+  (copy-from-core (core-car (core-uvref pkg-ptr pkg.names)) :depth 1))
+
+(defun core-find-symbol (name &optional (package (symbol-package name)))
+  ;; Unlike the real cl:find-symbol, this doesn't look for inherited symbols,
+  ;; you have to get the package right.
+  (let* ((symbol-name (string name))
+         (name-len (length symbol-name))
+         (pkg-ptr (if (integerp package)
+                    package
+                    (core-find-package (if (packagep package)
+                                         (package-name package)
+                                         (string package))
+                                       :error t))))
+    (assert (core-uvtypep pkg-ptr :package))
+    (multiple-value-bind (primary secondary) (hash-pname symbol-name name-len)
+      (flet ((findsym (htab-ptr)
+               (let* ((vec-ptr (core-car htab-ptr))
+                      (vlen (core-uvsize vec-ptr)))
+                 (loop for idx = (fast-mod primary vlen) then (+ i secondary)
+                       for i = idx then (if (>= idx vlen) (- idx vlen) idx)
+                       as sym = (core-uvref vec-ptr i)
+                       until (eql sym 0)
+                       do (when (and (core-symbolp sym)
+                                     (core-string-equal (core-q sym target::symbol.pname) symbol-name))
+                            (return (if (eq sym (nil-relative-symbol-address 'nil))
+                                      (target-nil-value)
+                                      sym)))))))
+        (or (findsym (core-uvref pkg-ptr pkg.itab))
+            (findsym (core-uvref pkg-ptr pkg.etab)))))))
+
+(defun core-gethash (key-ptr hash-ptr)
+  (when (core-uvtypep hash-ptr :istruct)
+    (setq hash-ptr (core-uvref hash-ptr nhash.vector)))
+  (assert (core-uvtypep hash-ptr :hash-vector))
+  (loop for i from $nhash.vector_overhead below (core-uvsize hash-ptr) by 2
+        do (when (eq (core-uvref hash-ptr i) key-ptr)
+             (return (core-uvref hash-ptr (1+ i))))))
+
+(defun core-hash-table-count (hash-ptr)
+  (when (core-uvtypep hash-ptr :istruct)
+    (setq hash-ptr (core-uvref hash-ptr nhash.vector)))
+  (assert (core-uvtypep hash-ptr :hash-vector))
+  (loop with rehashing = (%fixnum-address-of (%slot-unbound-marker))
+        with free = (%fixnum-address-of (%unbound-marker))
+        for i from $nhash.vector_overhead below (core-uvsize hash-ptr) by 2
+        count (let ((value (core-uvref hash-ptr (1+ i))))
+                (when (eq value rehashing)
+                  (error "This table is being rehashed"))
+                (neq value free))))
+
+(defun core-classes-hash-table-ptr ()
+  (or (core-info-classes-hash-table-ptr (current-core))
+      (setf (core-info-classes-hash-table-ptr (current-core))
+            (core-symbol-value (core-find-symbol '%find-classes%)))))
+
+(defun core-find-class (name)
+  (let* ((name-ptr (etypecase name
+                     (integer 
+                        (assert (core-symbolp name))
+                        name)
+                     (symbol (core-find-symbol name))))
+         (hash-ptr (core-classes-hash-table-ptr))
+         (cell (core-gethash name-ptr hash-ptr))
+         (class (and cell (core-uvref cell class-cell-class))))
+    (and class (core-uvtypep class :instance) class)))
+
+(defun core-lfun-names-table-ptr ()
+  (or (core-info-lfun-names-table-ptr (current-core))
+      (setf (core-info-lfun-names-table-ptr (current-core))
+            (core-symbol-value (core-find-symbol '*lfun-names*)))))
+
+(defun core-closure-function (fun)
+  (while (and (core-functionp fun)
+              (logbitp $lfbits-trampoline-bit (core-lfun-bits fun)))
+    (let* ((addr (+ (logandc2 fun target::fulltagmask) target::node-size)))
+      (setq fun (core-q addr (ash (core-l addr) target::word-shift)))
+      (when (core-uvtypep fun :simple-vector)
+        (setq fun (core-uvref fun 0)))
+      #+gz (assert (core-functionp fun))))
+  fun)
+
+    
+(defun core-lfun-name (fn)
+  (assert (core-functionp fn))
+  (flet ((lfun-name (fn)
+           (or (core-gethash fn (core-lfun-names-table-ptr))
+               (let* ((lfbits (core-lfun-bits fn))
+                      (name (if (and (logbitp $lfbits-gfn-bit lfbits)
+                                     (not (logbitp $lfbits-method-bit lfbits)))
+                                (core-uvref (core-uvref fn gf.slots) sgf.name)
+                                (unless (logbitp $lfbits-noname-bit lfbits)
+                                  (core-uvref fn (- (core-uvsize fn) 2))))))
+                 (and name
+                      (not (eql name (%fixnum-address-of (%slot-unbound-marker))))
+                      (not (core-nullp name))
+                      name)))))
+    (or (lfun-name fn)
+        (let ((inner-fn (core-closure-function fn)))
+          (and (core-functionp inner-fn)
+               (not (eql inner-fn fn))
+               (lfun-name inner-fn))))))
+
+(defun core-list (ptr)
+  (let ((cars (loop while (core-consp ptr)
+                    collect (core-car ptr)
+                    do (setq ptr (core-cdr ptr)))))
+    (if (core-nullp ptr)
+      cars
+      (nconc cars ptr))))
+
+(defun core-all-processes ()
+  (let* ((sym (core-find-symbol 'all-processes))
+         (closure (core-uvref sym target::symbol.fcell-cell))
+         (imm-start (core-l (logandc2 closure target::fulltagmask) target::node-size))
+         (imm-end (core-uvsize closure))
+         (vcell (loop for idx from (1+ imm-start) below imm-end as imm = (core-uvref closure idx)
+                      when (core-uvtypep imm :value-cell) return imm))
+         (val (core-uvref vcell target::value-cell.value-cell))
+         (processes (core-list val)))
+    processes))
+
+(defun core-process-name (proc)
+  (assert (core-uvtypep proc :instance))
+  (let ((slots (core-uvref proc ccl::instance.slots)))
+    (copy-from-core (core-uvref slots 1) :depth 1)))
+
+(defun core-process-tcr (proc)
+  (assert (core-uvtypep proc :instance))
+  (let* ((slots (core-uvref proc ccl::instance.slots))
+         (thread (core-uvref slots 2)))
+    (core-uvref thread ccl::lisp-thread.tcr)))
+
+(defun core-find-process-for-id (lwp)
+  (loop for proc in (core-all-processes)
+        when (eql lwp (core-q (core-process-tcr proc) target::tcr.native-thread-id))
+          return proc))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun core-process-class ()
+  (or (core-info-process-class (current-core))
+      (setf (core-info-process-class (current-core))
+            (core-find-class 'process))))
+
+(defun core-print (obj &optional (stream t) depth)
+  ;; TODO: could dispatch on core-object-type...
+  (cond ((core-nullp obj) (format stream "NIL"))
+        ((core-symbolp obj)
+         (core-print-symbol obj stream))
+        ((core-uvtypep obj :function)
+         (core-print-function obj stream))
+        ((core-instance-p obj (core-process-class))
+         (core-print-process obj stream))
+        ((and depth (< (decf depth) 0))
+         (format stream "x~x" obj))
+        ((core-consp obj)
+         (loop for sep = "(" then " "
+               for i from 0 below (or *print-length* 100)
+               while (core-consp obj)
+               do (format stream sep)
+               do (core-print (core-car obj) stream depth)
+               do (setq obj (core-cdr obj)))
+         (unless (core-nullp obj)
+           (format stream " . ")
+           (core-print obj stream depth))
+         (format stream ")"))
+        (t (format stream "#<core ~s x~x>"
+                   (core-object-type obj) obj))))
+
+(defun core-print-symbol (sym stream)
+  (let ((package (core-symbol-package sym)))
+    (cond ((core-nullp package)
+           (format stream "#:"))
+          ((eq package (core-keyword-package))
+           (format stream ":"))
+          (t (let ((pkgname (core-package-name package)))
+               (unless (string-equal pkgname "COMMON-LISP")
+                 (format stream "~a::" pkgname)))))
+    (format stream "~a" (core-symbol-name sym))))
+
+(defun core-lfun-bits (fun)
+  (ash (core-uvref fun (1- (core-uvsize fun))) (- target::fixnum-shift)))
+
+(defun core-print-function (fun stream)
+  (let* ((lfbits (core-lfun-bits fun))
+         (name (core-lfun-name fun)))
+    (format stream "#<")
+    (cond ((or (null name) (core-nullp name))
+           (format stream "Anonymous function"))
+          ((logbitp $lfbits-method-bit lfbits)
+           (assert (core-uvtypep name :instance))
+           (let* ((slot-vector (core-uvref name instance.slots))
+                  (method-qualifiers (core-uvref slot-vector %method.qualifiers))
+                  (method-specializers (core-uvref slot-vector %method.specializers))
+                  (method-name (core-uvref slot-vector %method.name)))
+             (format stream "Method-Function ")
+             (core-print method-name stream)
+             (format stream " ")
+             (unless (core-nullp method-qualifiers)
+               (if (core-nullp (core-cdr method-qualifiers))
+                 (core-print (core-car method-qualifiers) stream)
+                 (core-print method-qualifiers stream))
+               (format stream " "))
+             ;; print specializer list but print names instead of classes.
+             (loop for sep = "(" then " "
+                   while (core-consp method-specializers)
+                   do (format stream sep)
+                   do (let ((spec (core-car method-specializers)))
+                        (if (core-uvtypep spec :instance)
+                          (core-print (core-uvref (core-uvref spec instance.slots) %class.name) stream)
+                          (core-print spec stream)))
+                   do (setq method-specializers (core-cdr method-specializers)))
+             (unless (core-nullp method-specializers)
+               (format stream " . ")
+               (core-print method-specializers stream))
+             (format stream ")")))
+          (t
+           (if (logbitp $lfbits-gfn-bit lfbits)
+               (format stream "Generic Function ")
+               (format stream "Function "))
+           (core-print name stream)))
+    (format stream " x~x>" fun)))
+
+(defun core-print-process (proc stream)
+  (format stream "#<~a ~s LWP(~d) #x~x>"
+          (core-instance-class-name proc)
+          (core-process-name proc)
+          (core-q (core-process-tcr proc) target::tcr.native-thread-id)
+          proc))
+
+(defun dwim-core-frame-pointer (tcr &optional end)
+  (let* ((ret1valn (core-q (kernel-global-address 'ret1valaddr)))
+         (lexprs (list (core-q (kernel-global-address 'lexpr-return))
+                       (core-q (kernel-global-address 'lexpr-return1v))))
+         (stack-area (core-q tcr target::tcr.vs-area))
+         (fp (core-q stack-area target::area.high))
+         (low (core-q stack-area target::area.low)))
+    (flet ((validp (pp)
+             (let ((tra (core-q pp target::lisp-frame.return-address)))
+               (when (eql tra ret1valn)
+                 (setq tra (core-q pp target::lisp-frame.xtra)))
+               (or (eql (logand tra target::tagmask) target::tag-tra)
+                   (eql tra 0)
+                   (member tra lexprs)))))
+      (decf fp (* 2 target::node-size))
+      (when (and end (<= low end fp))
+        (setq low (- end 8)))
+      (loop while
+            (loop for pp downfrom (- fp target::node-size) above low by target::node-size
+                  do (when (eql (core-q pp target::lisp-frame.backptr) fp)
+                       (when (validp pp)
+                         (return (setq fp pp))))))
+      fp)))
+
+(defun core-stack-frame-values (tcr fp)
+  (let* ((bottom (core-q fp target::lisp-frame.backptr))
+         (top (if (eql 0 (core-q fp target::lisp-frame.return-address))
+                (+ fp target::xcf.size)
+                (+ fp (if (eql (core-q fp target::lisp-frame.return-address)
+                               (core-q (kernel-global-address 'ret1valaddr)))
+                        target::lisp-frame.size
+                        target::lisp-frame.xtra))))
+         (db-link (loop as db = (core-q tcr target::tcr.db-link) then (core-q db)
+                        until (or (eql db 0) (>= db bottom))
+                        when (<= top db) return db)))
+    (loop for vsp from top below bottom by target::node-size
+          when (eql vsp db-link)
+            ;; The db-link will be followed by var and val, which we'll just collect normally
+            do (setq db-link (core-q db-link) vsp (+ vsp target::node-size))
+            and collect `(:db-link ,db-link)
+          collect (core-q vsp))))
+
+(defun core-print-call-history (process &key (stream t) origin detailed-p)
+  (flet ((fp-backlink (fp vs-end)
+           (let ((backlink (core-q fp target::lisp-frame.backptr)))
+             (when (or (eql backlink 0)
+                       (<= vs-end backlink)
+                       (<= vs-end (core-q backlink target::lisp-frame.backptr)))
+               (setq backlink vs-end))
+             (assert (< fp backlink))
+             backlink))
+         (fp-tra (fp)
+           (let ((tra (core-q fp target::lisp-frame.return-address)))
+             (if (eql tra (core-q (kernel-global-address 'ret1valaddr)))
+               (core-q fp target::lisp-frame.xtra)
+               tra)))
+         (recover-fn (pc)
+           (when (and (eql (logand pc target::tagmask) target::tag-tra)
+                      (eql (core-w pc) target::recover-fn-from-rip-word0)
+                      (eql (core-b pc 2) target::recover-fn-from-rip-byte2))
+             (+ pc target::recover-fn-from-rip-length
+                (- (core-l pc target::recover-fn-from-rip-disp-offset)
+                   #x100000000)))))
+    (format stream "~&")
+    (core-print process stream)
+    (let* ((tcr (core-process-tcr process))
+           (vs-area (core-q tcr target::tcr.vs-area))
+           (vs-end (core-q vs-area target::area.high))
+           (valence (core-q tcr target::tcr.valence))
+           (fp (or origin
+                   ;; TODO: find the registers in the core file!
+                   (case valence
+                     ;; TCR_STATE_LISP
+                     (0 (let ((xp (core-q tcr target::tcr.suspend-context)))
+                          (format stream "~&")
+                          (if (eql xp 0)
+                            (format stream "Unknown lisp context, guessing frame pointer:")
+                            (core-print (core-q xp (* 10 target::node-size)) stream)) ;; r13 = fn
+                          (if (eql xp 0)
+                            (dwim-core-frame-pointer tcr)
+                            ;; uc_mcontext.gregs[rbp]
+                            (core-q xp (* 15 target::node-size)))))
+                     ;; TCR_STATE_FOREIGN
+                     (1 (format stream "~&In foreign code")
+                        ;; the save-rbp seems to include some non-lisp frames sometimes,
+                        ;; shave them down.
+                        #+no (core-q tcr target::tcr.save-rbp)
+                        (dwim-core-frame-pointer tcr (core-q tcr target::tcr.save-rbp)))
+                     ;; TCR_STATE_EXCEPTION_WAIT
+                     (2 (let ((xp (core-q tcr target::tcr.pending-exception-context)))
+                          ;; regs start at index 5, in this order:
+                          ;; arg_x temp1 ra0 save3 save2 fn save1 save0 arg_y arg_z
+                          ;; rbp temp0 imm1 imm0 nargs rsp rip
+                          (format stream " exception-wait")
+                          (if (zerop xp)
+                            (format stream "~&context unknown")
+                            (let* ((fn (core-q xp (* 10 target::node-size)))
+                                   (sp (core-q xp (* 20 target::node-size)))
+                                   (ra (core-q sp)))
+                              (if (and (core-functionp fn)
+                                       (and (<= fn ra)
+                                            (< ra (+ fn (* (core-uvsize fn) target::node-size)))))
+                                (progn
+                                  (format stream "~&")
+                                  (core-print fn stream)
+                                  (format stream " + ~d" (- ra fn)))
+                                (progn
+                                  (format stream "~&top of stack = x~x, r13 = " ra)
+                                  (core-print fn stream)))))
+                          (unless (zerop xp)
+                            (core-q xp (* 15 target::node-size))))))
+                   (error "Cannot find frame pointer"))))
+      (unless (<= (core-q vs-area target::area.low) fp vs-end)
+        (error "frame pointer x~x is not in stack area" fp))
+      (loop while (< fp vs-end) for pc = (fp-tra fp) for fun = (recover-fn pc)
+            do (format stream "~&fp: x~x  pc: x~x : " fp pc)
+            do (cond (fun
+                      (core-print fun stream)
+                      (format stream " + ~d " (- pc fun)))
+                     ((eql pc 0) ;; exception frame
+                      (let* ((nominal-function (core-q fp target::xcf.nominal-function))
+                             (obj (core-q fp target::xcf.containing-object)))
+                        (when (core-functionp nominal-function)
+                          (format stream "exception ")
+                          (core-print nominal-function stream)
+                          (format stream " + ~d"
+                                  (if (eq (- obj target::fulltag-misc)
+                                          (- nominal-function target::fulltag-function))
+                                    (- (core-q fp target::xcf.relative-pc) target::tag-function)
+                                    (let ((pc (core-q fp target::xcf.ra0)))
+                                      (when (eql nominal-function (recover-fn pc))
+                                        (- pc nominal-function))))))))
+                     ((eql pc (core-q (kernel-global-address 'lexpr-return)))
+                      (format stream "lexpr return"))
+                     ((eql pc (core-q (kernel-global-address 'lexpr-return1v)))
+                      (format stream "lexpr1v return"))
+                     (t
+                      (if (eql (logand pc target::tagmask) target::tag-tra)
+                        (format stream " # couldn't recover function")
+                        (unless (core-nullp pc)
+                          (format stream "bad frame!")))
+                      ;; can't trust backlink
+                      (return)))
+               ;; TODO: print stack addressses
+            do (when detailed-p
+                 (loop for val in (core-stack-frame-values tcr fp)
+                       do (format stream "~&     ")
+                       do (if (integerp val)
+                            (handler-case (core-print val stream)
+                              (error () (format stream "#<Error printing value @x~x>" val)))
+                            (format stream "~a x~x" (car val) (cadr val)))))
+            do (setq fp (fp-backlink fp vs-end))))))
+
+
+)                             ; :x8664-target
Index: /branches/new-random/library/cover.lisp
===================================================================
--- /branches/new-random/library/cover.lisp	(revision 13309)
+++ /branches/new-random/library/cover.lisp	(revision 13309)
@@ -0,0 +1,856 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2008-2009 Clozure Associates
+;;;   This file is part of Clozure CL.
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Code coverage reporting facility, originally inspired by SBCL's sb-cover API.
+
+(in-package :ccl)
+
+(export '(*compile-code-coverage*
+          report-coverage
+          reset-coverage
+          clear-coverage
+          save-coverage-in-file
+          restore-coverage-from-file
+
+          save-coverage
+          restore-coverage
+          combine-coverage
+          read-coverage-from-file
+          write-coverage-to-file
+
+          coverage-statistics
+          coverage-source-file
+          coverage-expressions-total
+          coverage-expressions-entered
+          coverage-expressions-covered
+          coverage-unreached-branches
+          coverage-code-forms-total
+          coverage-code-forms-covered
+          coverage-functions-total
+          coverage-functions-fully-covered
+          coverage-functions-partly-covered
+          coverage-functions-not-entered
+
+          without-compiling-code-coverage))
+
+(defconstant $not-executed-style 2)
+(defconstant $totally-covered-style 5)
+(defconstant $partially-covered-style 6)
+
+(defparameter *file-coverage* ())
+(defparameter *coverage-subnotes* (make-hash-table :test #'eq))
+(defparameter *emitted-code-notes* (make-hash-table :test #'eq))
+(defparameter *entry-code-notes* (make-hash-table :test #'eq))
+
+
+(defstruct (coverage-state (:conc-name "%COVERAGE-STATE-"))
+  alist)
+
+;; Wrapper in case we ever want to do dwim on raw alists
+(defun coverage-state-alist (coverage)
+  (etypecase coverage
+    (coverage-state (%coverage-state-alist coverage))))
+
+
+(defun file-coverage-file (entry)
+  (car entry))
+
+(defun file-coverage-functions (entry)
+  (cadr entry))
+
+(defun file-coverage-toplevel-functions (entry)
+  (cddr entry))
+
+(defun coverage-subnotes (note) ;; reversed parent chain
+  (gethash note *coverage-subnotes*))
+
+(defun emitted-code-note-p (note)
+  (gethash note *emitted-code-notes*))
+
+(defun entry-code-note-p (note)
+  (gethash note *entry-code-notes*))
+
+(defun map-function-coverage (lfun fn &optional refs)
+  (let ((refs (cons lfun refs)))
+    (declare (dynamic-extent refs))
+    (lfunloop for imm in lfun
+	      when (code-note-p imm)
+	      do (funcall fn imm)
+	      when (and (functionp imm)
+			(not (memq imm refs)))
+	      do (map-function-coverage imm fn refs))))
+
+(defun get-function-coverage (fn refs)
+  (let ((entry (function-entry-code-note fn))
+	(refs (cons fn refs)))
+    (declare (dynamic-extent refs))
+    (when entry
+      (assert (eq fn (gethash entry *entry-code-notes* fn)))
+      (setf (gethash entry *entry-code-notes*) fn))
+    (nconc
+     (and entry (list fn))
+     (lfunloop for imm in fn
+       when (code-note-p imm)
+       do (setf (gethash imm *emitted-code-notes*) t)
+       when (and (functionp imm)
+                 (not (memq imm refs)))
+       nconc (get-function-coverage imm refs)))))
+
+(defun get-coverage ()
+  (setq *file-coverage* nil)
+  (clrhash *coverage-subnotes*)
+  (clrhash *emitted-code-notes*)
+  (clrhash *entry-code-notes*)
+  (loop for data in *code-covered-functions*
+	when (consp data)
+	do (destructuring-bind (file . toplevel-functions) data
+	     (push (list* file
+			  ;; Duplicates are possible if you have multiple instances of
+			  ;; (load-time-value (foo)) where (foo) returns an lfun.
+			  ;; CL-PPCRE does that.
+			  (delete-duplicates
+			   (loop for fn across toplevel-functions
+				nconc (get-function-coverage fn nil)))
+			  toplevel-functions)
+		   *file-coverage*)))
+  ;; Now get subnotes, including un-emitted ones.
+  (loop for note being the hash-key of *emitted-code-notes*
+        do (loop for n = note then parent as parent = (code-note-parent-note n)
+                 while parent
+                 do (pushnew n (gethash parent *coverage-subnotes*))
+                 until (emitted-code-note-p parent))))
+
+#+debug
+(defun show-notes (note)
+  (when (functionp note)
+    (setq note (function-entry-code-note note)))
+  (labels ((show (note indent label)
+	     (dotimes (i indent) (write-char #\space))
+	     (format t "~a ~a" label note)
+	     (unless (emitted-code-note-p note)
+	       (format t " [Not Emitted]"))
+	     (when (entry-code-note-p note)
+	       (format t " (Entry to ~s)" (entry-code-note-p note)))
+	     (format t "~%")
+	     (when (code-note-p note)
+	       (loop with subindent = (+ indent 3)
+		     for sub in (coverage-subnotes note) as i upfrom 1
+		     do (show sub subindent (format nil "~a~d." label i))))))
+    (show note 0 "")))
+
+(defun assoc-by-filename (path alist)
+  (let* ((true-path (probe-file path)))
+    (find-if #'(lambda (data)
+                 (or (equalp (car data) path)
+                     (and true-path (equalp (probe-file (car data)) true-path))))
+             alist)))
+
+(defun covered-functions-for-file (path)
+  (cdr (assoc-by-filename path *code-covered-functions*)))
+
+(defun clear-coverage ()
+  "Clear all files from the coverage database. The files will be re-entered
+into the database when the FASL files (produced by compiling with
+CCL:*COMPILE-CODE-COVERAGE* set to true) are loaded again into the
+image."
+  (setq *code-covered-functions* nil))
+
+(defun reset-function-coverage (lfun)
+  (map-function-coverage lfun #'(lambda (note)
+                                  (setf (code-note-code-coverage note) nil))))
+
+(defun reset-coverage ()
+  "Reset all coverage data back to the `Not executed` state."
+  (loop for data in *code-covered-functions*
+        do (typecase data
+             (cons ;; (source-file . functions)
+		(loop for fn across (cdr data)
+		      do (reset-function-coverage fn)))
+             (function (reset-function-coverage data)))))
+
+;; Name used for consistency checking across file save/restore
+(defun function-covered-name (fn)
+  (let ((name (function-name fn)))
+    (and (symbolp name)
+         (symbol-package name)
+         name)))
+  
+
+(defun coverage-mismatch (why &rest args)
+  ;; Throw to somebody who knows what file we're working on.
+  (throw 'coverage-mismatch (cons why args)))
+
+(defmacro with-coverage-mismatch-catch ((saved-file) &body body)
+  `(let ((file ,saved-file)
+         (err (catch 'coverage-mismatch ,@body nil)))
+     (when err
+       (error "Mismatched coverage data for ~s, ~?" file (car err) (cdr err)))))
+
+
+;; (name . #(i1 i2 ...)) where in is either an index or (index . subfncoverage).
+(defun save-function-coverage (fn &optional (refs ()))
+  (let ((refs (cons fn refs)))
+    (declare (dynamic-extent refs))
+    (cons (function-covered-name fn)
+          (lfunloop for imm in fn as i upfrom 0
+                    when (and (code-note-p imm)
+                              (code-note-code-coverage imm))
+                    collect i into list
+                    when (and (functionp imm) (not (memq imm refs)))
+                    collect (cons i (save-function-coverage imm refs)) into list
+                    finally (return (and list (coerce list 'vector)))))))
+
+(defun copy-function-coverage (fn-data)
+  (cons (car fn-data)
+        (and (cdr fn-data)
+             (map 'vector #'(lambda (imm-data)
+                              (if (consp imm-data)
+                                (cons (car imm-data)
+                                      (copy-function-coverage (cdr imm-data)))
+                                imm-data))
+                  (cdr fn-data)))))
+
+(defun restore-function-coverage (fn saved-fn-data &optional (refs ()))
+  (let* ((refs (cons fn refs))
+         (saved-name (car saved-fn-data))
+         (saved-imms (cdr saved-fn-data))
+         (nimms (length saved-imms))
+         (n 0))
+    (declare (dynamic-extent refs))
+    (unless (equalp saved-name (function-covered-name fn))
+      (coverage-mismatch "had function ~s now have ~s" saved-name fn))
+    (lfunloop for imm in fn as i upfrom 0
+              when (code-note-p imm)
+              do (let* ((next (and (< n nimms) (aref saved-imms n))))
+                   (when (if (consp next) (<= (car next) i) (and next (< next i)))
+                     (coverage-mismatch "in ~s" fn))
+                   (when (setf (code-note-code-coverage imm)
+                               (and (eql next i) 'restored))
+                     (incf n)))
+              when (and (functionp imm) (not (memq imm refs)))
+              do (let* ((next (and (< n nimms) (aref saved-imms n))))
+                   (unless (and (consp next) (eql (car next) i))
+                     (coverage-mismatch "in ~s" fn))
+                   (restore-function-coverage imm (cdr next) refs)
+                   (incf n)))))
+
+
+(defun add-function-coverage (fn-data new-fn-data)
+  (let* ((fn-name (car fn-data))
+         (imms (cdr fn-data))
+         (new-fn-name (car new-fn-data))
+         (new-imms (cdr new-fn-data)))
+    (flet ((kar (x) (if (consp x) (%car x) x)))
+      (declare (inline kar))
+      (unless (equalp fn-name new-fn-name)
+        (coverage-mismatch "function ~s vs. ~s" fn-name new-fn-name))
+      (when new-imms
+        (loop for new across new-imms
+              as old = (find (kar new) imms :key #'kar)
+              if (and (null old) (fixnump new))
+                collect new into extras
+              else do (unless (eql old new)
+                        (if (and (consp new) (consp old))
+                          (add-function-coverage (cdr old) (cdr new))
+                          (coverage-mismatch "in function ~s" fn-name)))
+              finally (when extras
+                        (setf (cdr fn-data)
+                              (sort (concatenate 'vector imms extras) #'< :key #'kar))))))
+    fn-data))
+
+
+(defun save-coverage ()
+  "Returns a snapshot of the current coverage state"
+  (make-coverage-state
+   :alist (loop for data in *code-covered-functions*
+                when (consp data)
+                  collect (cons (car data)
+                                (map 'vector #'save-function-coverage (cdr data))))))
+
+(defun combine-coverage (coverage-states)
+  (let ((result nil))
+    (map nil
+         (lambda (coverage-state)
+           (loop for (saved-file . saved-fns) in (coverage-state-alist coverage-state)
+                 for result-fns = (cdr (assoc-by-filename saved-file result))
+                 do (with-coverage-mismatch-catch (saved-file)
+                      (cond ((null result-fns)
+                             (push (cons saved-file
+                                         (map 'vector #'copy-function-coverage saved-fns))
+                                   result))
+                            ((not (eql (length result-fns) (length saved-fns)))
+                             (coverage-mismatch "different function counts"))
+                            (t 
+                             (loop for result-fn across result-fns
+                                   for saved-fn across saved-fns
+                                   do (add-function-coverage result-fn saved-fn)))))))
+         coverage-states)
+    (make-coverage-state :alist (nreverse result))))
+
+
+(defun restore-coverage (coverage-state)
+  "Restore the code coverage data back to an earlier state produced by SAVE-COVERAGE."
+  (loop for (saved-file . saved-fns) in (coverage-state-alist coverage-state)
+        for fns = (covered-functions-for-file saved-file)
+        do (with-coverage-mismatch-catch (saved-file)
+             (cond ((null fns)
+                    (warn "Couldn't restore saved coverage for ~s, no matching file present"
+                          saved-file))
+                   ((not (eql (length fns) (length saved-fns)))
+                    (coverage-mismatch "had ~s functions, now have ~s"
+                                       (length saved-fns) (length fns)))
+                   (t 
+                    (map nil #'restore-function-coverage fns saved-fns))))))
+
+(defvar *loading-coverage*)
+
+(defun write-coverage-to-file (coverage pathname)
+  "Write the coverage state COVERAGE in the file designated by PATHNAME"
+  (with-open-file (stream pathname
+                          :direction :output
+                          :if-exists :supersede
+                          :if-does-not-exist :create)
+    (with-standard-io-syntax
+      (let ((*package* (pkg-arg "CCL")))
+        (format stream "(in-package :ccl)~%~s~%"
+                `(setq *loading-coverage* ',(coverage-state-alist coverage)))))
+    (values)))
+  
+(defun read-coverage-from-file (pathname)
+  " Return the coverage state saved in the file.  Doesn't affect the current coverage state."
+  (let ((*package* (pkg-arg "CCL"))
+        (*loading-coverage* :none))
+    (load pathname)
+    (when (eq *loading-coverage* :none)
+      (error "~s doesn't seem to be a saved coverage file" pathname))
+    (make-coverage-state :alist *loading-coverage*)))
+
+(defun save-coverage-in-file (pathname)
+  "Save the current coverage state in the file designed by PATHNAME"
+  (write-coverage-to-file (save-coverage) pathname))
+
+(defun restore-coverage-from-file (pathname)
+  "Set the current coverage state from the file designed by PATHNAME"
+  (restore-coverage (read-coverage-from-file pathname)))
+
+(defun common-coverage-directory ()
+  (let* ((host :unknown)
+	 (rev-dir ()))
+    (loop for data in *code-covered-functions*
+       when (consp data)
+       do (let ((file (probe-file (car data))))
+	    (when file
+	      (cond ((eq host :unknown)
+		     (setq host (pathname-host file)
+			   rev-dir (reverse (pathname-directory file))))
+		    ((not (equalp host (pathname-host file)))
+		     (return-from common-coverage-directory nil))
+		    (t
+		     (let* ((path (pathname-directory file))
+			    (dir-len (length rev-dir))
+			    (len (length path)))
+		       (if (< len dir-len)
+			 (setq rev-dir (nthcdr (- dir-len len) rev-dir))
+			 (setq path (subseq path 0 dir-len)))
+		       (loop for pp on (reverse path) until (equalp pp rev-dir)
+			  do (pop rev-dir))))))))
+    (unless (eq host :unknown)
+      (make-pathname :host host :directory (reverse rev-dir)))))
+
+
+(defstruct (coverage-statistics (:conc-name "COVERAGE-"))
+  source-file
+  expressions-total
+  expressions-entered
+  expressions-covered
+  unreached-branches
+  code-forms-total
+  code-forms-covered
+  functions-total
+  functions-fully-covered
+  functions-partly-covered
+  functions-not-entered)
+
+(defun coverage-statistics ()
+  (let* ((*file-coverage* nil)
+	 (*coverage-subnotes* (make-hash-table :test #'eq :shared nil))
+	 (*emitted-code-notes* (make-hash-table :test #'eq :shared nil))
+	 (*entry-code-notes* (make-hash-table :test #'eq :shared nil)))
+    (get-coverage)
+    (loop for coverage in *file-coverage*
+          as stats = (make-coverage-statistics :source-file (file-coverage-file coverage))
+          do (map nil (lambda (fn)
+                        (let ((note (function-entry-code-note fn)))
+                          (when note (precompute-note-coverage note))))
+                  (file-coverage-toplevel-functions coverage))
+          do (destructuring-bind (total entered %entered covered %covered)
+                 (count-covered-sexps coverage)
+               (declare (ignore %entered %covered))
+               (setf (coverage-expressions-total stats) total)
+               (setf (coverage-expressions-entered stats) entered)
+               (setf (coverage-expressions-covered stats) covered))
+          do (let ((count (count-unreached-branches coverage)))
+               (setf (coverage-unreached-branches stats) count))
+          do (destructuring-bind (total covered %covered) (count-covered-aexps coverage)
+               (declare (ignore %covered))
+               (setf (coverage-code-forms-total stats) total)
+               (setf (coverage-code-forms-covered stats) covered))
+          do (destructuring-bind (total fully %fully partly %partly never %never)
+                 (count-covered-entry-notes coverage)
+               (declare (ignore %fully %partly %never))
+               (setf (coverage-functions-total stats) total)
+               (setf (coverage-functions-fully-covered stats) fully)
+               (setf (coverage-functions-partly-covered stats) partly)
+               (setf (coverage-functions-not-entered stats) never))
+          collect stats)))
+
+
+(defun report-coverage (output-file &key (external-format :default) (statistics t) (html t))
+  "If :HTML is non-nil, generate an HTML report, consisting of an index file in OUTPUT-FILE
+and, in the same directory, one html file for each instrumented source file that has been
+loaded in the current session.
+The external format of the source files can be specified with the EXTERNAL-FORMAT parameter.
+If :STATISTICS is non-nil, a CSV file is generated with a table.  If
+:STATISTICS is a filename, that file is used, else 'statistics.csv' is
+written to the output directory.
+"
+  (let* ((paths)
+         (directory (make-pathname :name nil :type nil :defaults output-file))
+         (coverage-dir (common-coverage-directory))
+	 (*file-coverage* nil)
+	 (*coverage-subnotes* (make-hash-table :test #'eq :shared nil))
+	 (*emitted-code-notes* (make-hash-table :test #'eq :shared nil))
+	 (*entry-code-notes* (make-hash-table :test #'eq :shared nil))
+         (index-file (and html (merge-pathnames output-file "index.html")))
+         (stats-file (and statistics (merge-pathnames (if (or (stringp statistics)
+                                                              (pathnamep statistics))
+                                                        (merge-pathnames statistics "statistics.csv")
+                                                        "statistics.csv")
+                                                      output-file))))
+    (get-coverage)
+    (ensure-directories-exist directory)
+    (loop for coverage in *file-coverage*
+      as file = (or (probe-file (file-coverage-file coverage))
+		    (progn (warn "Cannot find ~s, won't report coverage" (file-coverage-file coverage))
+			   nil))
+      do (when file
+           (let* ((src-name (enough-namestring file coverage-dir))
+                  (html-name (substitute
+                              #\_ #\: (substitute
+                                       #\_ #\. (substitute
+                                                #\_ #\/ (namestring-unquote src-name))))))
+             (when html
+               (with-open-file (stream (make-pathname :name html-name :type "html" :defaults directory)
+                                       :direction :output
+                                       :if-exists :supersede
+                                       :if-does-not-exist :create)
+                 (report-file-coverage index-file coverage stream external-format)))
+             (push (list* src-name html-name coverage) paths))))
+    (when (null paths)
+      (error "No code coverage data available"))
+    (setq paths (sort paths #'(lambda (path1 path2)
+                                (let* ((f1 (car path1))
+                                       (f2 (car path2)))
+                                  (or (string< (directory-namestring f1)
+                                               (directory-namestring f2))
+                                      (and (equal (pathname-directory f1)
+                                                  (pathname-directory f2))
+                                           (string< (file-namestring f1)
+                                                    (file-namestring f2))))))))
+    (if html
+      (with-open-file (html-stream index-file
+                                   :direction :output
+                                   :if-exists :supersede
+                                   :if-does-not-exist :create)
+        (if stats-file
+          (with-open-file (stats-stream stats-file
+                                        :direction :output
+                                        :if-exists :supersede
+                                        :if-does-not-exist :create)
+            (report-coverage-to-streams paths html-stream stats-stream))
+          (report-coverage-to-streams paths html-stream nil)))
+      (if stats-file
+        (with-open-file (stats-stream stats-file
+                                      :direction :output
+                                      :if-exists :supersede
+                                      :if-does-not-exist :create)
+          (report-coverage-to-streams paths nil stats-stream))
+        (error "One of :HTML or :STATISTICS must be non-nil")))
+    (values index-file stats-file)))
+
+(defun report-coverage-to-streams (paths html-stream stats-stream)
+  (when html-stream (write-coverage-styles html-stream))
+  (unless paths
+    (warn "No coverage data found for any file, producing an empty report. Maybe you forgot to (SETQ CCL::*COMPILE-CODE-COVERAGE* T) before compiling?")
+    (when html-stream (format html-stream "<h3>No code coverage data found.</h3>~%"))
+    (when stats-stream (format stats-stream "No code coverage data found.~%"))
+    (return-from report-coverage-to-streams))
+  (when html-stream (format html-stream "<table class='summary'>"))
+  (coverage-stats-head html-stream stats-stream)
+  (loop for prev = nil then src-name
+	for (src-name report-name . coverage) in paths
+	for even = nil then (not even)
+	do (when (or (null prev)
+		     (not (equal (pathname-directory (pathname src-name))
+				 (pathname-directory (pathname prev)))))
+	     (let ((dir (namestring (make-pathname :name nil :type nil :defaults src-name))))
+	       (when html-stream (format html-stream "<tr class='subheading'><td colspan='17'>~A</td></tr>~%" dir))
+	       (when stats-stream (format stats-stream "~a~%" dir))))
+	do (coverage-stats-data html-stream stats-stream coverage even report-name src-name))
+  (when html-stream (format html-stream "</table>")))
+
+(defun precompute-note-coverage (note &optional refs)
+  (when note
+    (let ((subnotes (coverage-subnotes note))
+	  (refs (cons note refs)))
+      (declare (dynamic-extent refs))
+      (loop for sub in subnotes
+	    when (member sub refs)
+	    do (break "Circularity!!")
+	    unless (member sub refs)
+	    do (precompute-note-coverage sub refs))
+      (when (and (or (not (emitted-code-note-p note))
+		     (code-note-code-coverage note))
+		 (loop for sub in subnotes
+		       always (or (eq 'full (code-note-code-coverage sub))
+				  (entry-code-note-p sub))))
+	(setf (code-note-code-coverage note) 'full)))))
+
+
+(defun fill-with-text-style (coverage location-note styles)
+  (let ((style (case coverage
+		 ((full) $totally-covered-style)
+		 ((nil) $not-executed-style)
+		 (t $partially-covered-style))))
+    (fill styles style
+	  :start (source-note-start-pos location-note)
+	  :end (source-note-end-pos location-note))))
+
+(defun update-text-styles (note styles)
+  (let ((source (code-note-source-note note)))
+    (when source
+      (fill-with-text-style (code-note-code-coverage note) source styles))
+    (unless (and (emitted-code-note-p note)
+                 (memq (code-note-code-coverage note) '(nil full))
+                 ;; If not a source note, descend in case have some subnotes
+                 ;; that can be shown
+                 source)
+      (loop for sub in (coverage-subnotes note)
+            unless (entry-code-note-p sub)
+            do (update-text-styles sub styles)))))
+
+(defun entry-note-unambiguous-source (entry-note)
+  ;; Return the nearest containing source note provided it can be done unambiguously.
+  (loop for n = entry-note then parent until (code-note-source-note n)
+	as parent = (code-note-parent-note n)
+	do (unless (and parent
+			(labels ((no-other-entry-subnotes (n refs)
+				   (let ((subs (coverage-subnotes n))
+					 (refs (cons n refs)))
+				     (declare (dynamic-extent refs))
+				     (loop for sub in subs
+					   always (or (memq sub refs)
+						      (eq sub entry-note)
+						      (and (not (entry-code-note-p sub))
+							   (no-other-entry-subnotes sub refs)))))))
+			  (no-other-entry-subnotes parent ())))
+	     (return nil))
+	finally (return (code-note-source-note n))))
+
+(defun colorize-source-note (note styles)
+  ;; Change coverage flag to 'full if all subforms are covered.
+  (precompute-note-coverage note)
+  ;; Now actually change text styles, from outside in.
+  ;; But first, a special kludge:
+  ;; In cases like (setq foo (function (lambda (x) x))), we can colorize "(setq foo (function "
+  ;; based on whether the setq got executed, and "(lambda (x) x)" on whether the inner
+  ;; function got executed.  However, suppose have a macro "(setq-fun foo (x) x)" that
+  ;; expanded into the above, there isn't a clear way to show the distinction between
+  ;; just referencing the inner fn and executing it.  In practice, the colorization
+  ;; based on the inner function is more interesting -- consider for example DEFUN,
+  ;; nobody cares whether the defun form itself got executed.
+  ;; So when showing the colorization of an inner function, we usurp the whole nearest source
+  ;; form, provided it can be done unambiguously.
+  (let ((n (entry-note-unambiguous-source note)))
+    (when n
+      (fill-with-text-style (code-note-code-coverage note) n styles)))
+  (update-text-styles note styles))
+
+(defun function-source-form-note (fn)
+  ;; Find the outermost source form containing the fn.
+  (loop with sn = nil
+        for n = (function-entry-code-note fn) then (code-note-parent-note n)
+	do (when (null n) (return nil))
+	do (when (setq sn (code-note-source-note n))
+	     (loop for s = (source-note-source sn) while (source-note-p s)
+		   do (setq sn s))
+	     (return sn))))
+
+  
+(defun colorize-function (fn styles &optional refs)
+  (let* ((note (function-entry-code-note fn))
+	 (source (function-source-form-note fn))
+	 (refs (cons fn refs)))
+    (declare (dynamic-extent refs))
+    ;; Colorize the body of the function
+    (when note
+      (colorize-source-note note styles))
+    ;; And now any subfunction references
+    (lfunloop for imm in fn
+	      when (and (functionp imm)
+			(not (memq imm refs))
+			;; Make sure this fn is in the source we're currently looking at.
+			;; It might not be, if it is referenced via (load-time-value (foo))
+			;; where (foo) returns an lfun from some different source entirely.
+			;; CL-PPCRE does that.
+			(or (null source)
+			    (eq source (function-source-form-note imm))
+			    #+debug (progn
+				      (warn "Ignoring ref to ~s from ~s" imm fn)
+				      nil)))
+	      do (colorize-function imm styles refs))))
+
+(defun report-file-coverage (index-file coverage html-stream external-format)
+  "Print a code coverage report of FILE into the stream HTML-STREAM."
+  (format html-stream "<html><head>")
+  (write-coverage-styles html-stream)
+  (format html-stream "</head><body>")
+  (let* ((source (with-open-file (s (file-coverage-file coverage) :external-format external-format)
+                   (let ((string (make-string (file-length s))))
+                     (read-sequence string s)
+                     string)))
+         (styles (make-array (length source)
+                             :initial-element 0
+                             :element-type '(unsigned-byte 2))))
+    (map nil #'(lambda (fn) (colorize-function fn styles)) (file-coverage-toplevel-functions coverage))
+    (print-file-coverage-report index-file html-stream coverage styles source)
+    (format html-stream "</body></html>")))
+
+(defun print-file-coverage-report (index-file html-stream coverage styles source)
+  (let ((*print-case* :downcase))
+    (format html-stream "<h3><a href=~s>Coverage report</a>: ~a <br />~%</h3>~%"
+            (native-translated-namestring (make-pathname :name (pathname-name index-file)
+							 :type (pathname-type index-file)))
+            (file-coverage-file coverage))
+    (format html-stream "<table class='summary'>")
+    (coverage-stats-head html-stream nil)
+    (coverage-stats-data html-stream nil coverage)
+    (format html-stream "</table>")
+
+    (format html-stream "<div class='key'><b>Key</b><br />~%")
+    (format html-stream "<div class='state-~a'>Fully covered - every single instruction executed</div>" $totally-covered-style)
+    (format html-stream "<div class='state-~a'>Partly covered - entered but some subforms not executed</div>" $partially-covered-style)
+    (format html-stream "<div class='state-~a'>Never entered - not a single instruction executed</div>" $not-executed-style)
+    (format html-stream "<p></p><div><code>~%")
+
+    (flet ((line (line)
+             (unless (eql line 0)
+               (format html-stream "</span>"))
+             (incf line)
+             (format html-stream "</code></div></nobr>~%<nobr><div class='source'><div class='line-number'><code>~A</code></div><code>&#160;" line)
+             line))
+      (loop with line = (line 0) with col = 0
+        for last-style = nil then style
+        for char across source
+        for style across styles
+        do (unless (eq style last-style)
+             (when last-style
+               (format html-stream "</span>"))
+             (format html-stream "<span class='state-~a'>" style))
+        do (case char
+             ((#\Newline)
+              (setq style nil)
+              (setq col 0)
+              (setq line (line line)))
+             ((#\Space)
+              (incf col)
+              (write-string "&#160;" html-stream))
+             ((#\Tab)
+              (dotimes (i (- 8 (mod col 8)))
+                (incf col)
+                (write-string "&#160;" html-stream)))
+             (t
+              (incf col)
+              (if (alphanumericp char)
+                (write-char char html-stream)
+                (format html-stream "&#~D;" (char-code char))))))
+      (format html-stream "</code></div>"))))
+
+
+(defun coverage-stats-head (html-stream stats-stream)
+  (when html-stream
+    (format html-stream "<tr class='head-row'><td></td>")
+    (format html-stream "<td class='main-head' colspan='5'>Expressions</td>")
+    (format html-stream "<td class='main-head' colspan='1'>Branches</td>")
+    (format html-stream "<td class='main-head' colspan='3'>Code Forms</td>")
+    (format html-stream "<td class='main-head' colspan='7'>Functions</td></tr>")
+    (format html-stream "<tr class='head-row'>~{<td width='60px'>~A</td>~}</tr>"
+            '("Source file"
+              ;; Expressions
+              "Total" "Entered" "% entered" "Fully covered" "% fully covered"
+              ;; Branches
+              "total unreached"
+              ;; Code forms
+              "Total" "Covered" "% covered"
+              ;; Functions
+              "Total" "Fully covered" "% fully covered" "Partly covered" "% partly covered" "Not entered" "% not entered")))
+  (when stats-stream
+    (format stats-stream "~{~a~^,~}"
+	    `("Source file"
+              "Expressions Total" "Expressions Entered" "% Expressions Entered"
+              "Unreached Branches"
+              "Code Forms Total" "Code Forms Covered" "% Code Forms Covered"
+              "Functions Total" "Functions Fully Covered" "% Functions Fully Covered"
+	      "Functions Partly Covered" "% Functions Partly Covered"
+	      "Functions Not Entered" "% Functions Not Entered"))))
+
+(defun coverage-stats-data (html-stream stats-stream coverage &optional evenp report-name src-name)
+  (when html-stream
+    (format html-stream "<tr class='~:[odd~;even~]'>" evenp)
+    (if report-name
+      (format html-stream "<td class='text-cell'><a href='~a.html'>~a</a></td>" report-name src-name)
+      (format html-stream "<td class='text-cell'>~a</td>" (file-coverage-file coverage))))
+  (when stats-stream
+    (format stats-stream "~a," (file-coverage-file coverage)))
+
+  (let ((exp-counts (count-covered-sexps coverage)))
+    (when html-stream
+      (format html-stream "~{<td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~5,1f%~]</td><td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~5,1f%~]</td>~}" exp-counts))
+    (when stats-stream
+      (format stats-stream "~{~:[~;~:*~a~],~:[~;~:*~a~],~:[~;~:*~5,1f%~],~:[~;~:*~a~],~:[~;~:*~5,1f%~],~}" exp-counts)))
+
+  (let ((count (count-unreached-branches coverage)))
+    (when html-stream
+      (format html-stream "<td>~:[-~;~:*~a~]</td>" count))
+    (when stats-stream
+      (format stats-stream "~:[~;~:*~a~]," count)))
+
+  (let ((exp-counts (count-covered-aexps coverage)))
+    (when html-stream
+      (format html-stream "~{<td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~5,1f%~]</td>~}" exp-counts))
+    (when stats-stream
+      (format stats-stream "~{~:[~;~:*~a~],~:[~;~:*~a~],~:[~;~:*~5,1f%~],~}" exp-counts)))
+
+  (destructuring-bind (total . counts) (count-covered-entry-notes coverage)
+    (when html-stream
+      (format html-stream "<td>~:[-~;~:*~a~]</td>~{<td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~5,1f%~]</td>~}</tr>" total counts))
+    (when stats-stream
+      (format stats-stream "~:[~;~:*~a~],~{~:[~;~:*~a~],~:[-~;~:*~5,1f%~]~^,~}~%" total counts))))
+
+(defun map-coverage-entry-notes (coverage fn)
+  (map nil #'(lambda (function)
+                 (let ((note (function-entry-code-note function)))
+                   (when (and note
+			      ;; Ignore toplevel functions created by the compiler.
+			      (or (code-note-source-note note)
+				  (code-note-parent-note note)))
+                     (funcall fn note))))
+       (file-coverage-functions coverage)))
+
+
+(defun count-covered-entry-notes (coverage)
+  (let ((fully 0) (partly 0) (never 0) (total 0))
+    (map-coverage-entry-notes
+     coverage
+     #'(lambda (note)
+         (incf total)
+         (case (code-note-code-coverage note)
+           ((full) (incf fully))
+           ((nil) (incf never))
+           (t (incf partly)))))
+    (if (> total 0)
+	(list total
+	      fully (* 100.0 (/ fully total))
+	      partly (* 100.0 (/ partly total))
+	      never (* 100.0 (/ never total)))
+	'(0 0 -- 0 -- 0 --))))
+
+(defun count-covered-aexps (coverage)
+  (let ((covered 0) (total 0))
+    (map-coverage-entry-notes
+     coverage
+     (lambda (note)
+       (labels ((rec (note)
+		  (when (emitted-code-note-p note)
+		    (incf total)
+		    (when (code-note-code-coverage note)
+		      (incf covered)))
+                  (loop for sub in (coverage-subnotes note)
+                        unless (entry-code-note-p sub) do (rec sub))))
+         (rec note))))
+    (list total covered (if (> total 0) (* 100.0d0 (/ covered total)) '--))))
+
+(defun count-covered-sexps (coverage)
+  ;; Count the number of source expressions that have been entered (regardless
+  ;; of whether or not they are completely covered).
+  (let ((entered 0) (covered 0) (total 0))
+    (map-coverage-entry-notes
+     coverage
+     (lambda (note)
+       (labels ((rec (note)
+                  (when (code-note-source-note note)
+                    #+debug (format t "~&~s" note)
+                    (incf total)
+                    (when (code-note-code-coverage note)
+                      (incf entered)
+                      (when (eq (code-note-code-coverage note) 'full)
+                        (incf covered))))
+                  (loop for sub in (coverage-subnotes note)
+                        unless (entry-code-note-p sub) do (rec sub))))
+         (rec note))))
+    (list total
+          entered (if (> total 0) (* 100.0d0 (/ entered total)) '--)
+          covered (if (> total 0) (* 100.0d0 (/ covered total)) '--))))
+
+(defun count-unreached-branches (coverage)
+  ;; Count the number of maximal unentered forms
+  (let ((count 0))
+    (map-coverage-entry-notes
+     coverage
+     (lambda (note)
+       (labels ((rec (note parent)
+                  (case (code-note-code-coverage note)
+                    ((full) nil)
+                    ((nil) (when parent (incf count)))
+                    (t (loop for sub in (coverage-subnotes note)
+                             unless (entry-code-note-p sub) do (rec sub note))))))
+         (rec note nil))))
+    count))
+
+(defun write-coverage-styles (html-stream)
+  (format html-stream "<style type='text/css'>
+*.state-~a { background-color: #ffaaaa }
+*.state-~a { background-color: #aaffaa }
+*.state-~a { background-color: #44dd44 }
+div.key { margin: 20px; width: 88ex }
+div.source { width: 98ex; background-color: #eeeeee; padding-left: 5px;
+             /* border-style: solid none none none; border-width: 1px;
+             border-color: #dddddd */ }
+
+*.line-number { color: #666666; float: left; width: 6ex; text-align: right; margin-right: 1ex; }
+
+table.summary tr.head-row { background-color: #aaaaff }
+table.summary tr td.text-cell { text-align: left }
+table.summary tr td.main-head { text-align: center }
+table.summary tr td { text-align: right }
+table.summary tr.even { background-color: #eeeeff }
+table.summary tr.subheading { background-color: #aaaaff}
+table.summary tr.subheading td { text-align: left; font-weight: bold; padding-left: 5ex; }
+</style>"
+          $not-executed-style
+          $partially-covered-style
+          $totally-covered-style
+          ))
Index: /branches/new-random/library/darwinppc-syscalls.lisp
===================================================================
--- /branches/new-random/library/darwinppc-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/darwinppc-syscalls.lisp	(revision 13309)
@@ -0,0 +1,298 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL"))
+
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::exit 1 (:int) :void )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fork 2 () :void)
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::read 3 (:unsigned-fullword :address :unsigned-long)
+		:signed-long )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::write 4 (:unsigned-fullword :address :unsigned-long)
+		:signed-long )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::open 5 (:address :unsigned-fullword :unsigned-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::close 6 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::wait4 7 (:unsigned-fullword :address :signed-fullword :address) :unsigned-fullword )
+				; 8 is old creat 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::link 9 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::unlink 10 (:address) :signed-fullword )
+				; 11 is obsolete execv 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::chdir 12 (:address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fchdir 13 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mknod 14  (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::chmod 15 (:address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lchown 16 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getpid 20 () :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setuid 23 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getuid 24 () :unsigned-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::geteuid 25 () :unsigned-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::recvmsg 27 (:unsigned-fullword :address :unsigned-fullword):signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sendmsg 28 (:unsigned-fullword :address :unsigned-fullword):signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::recvfrom 29 (:unsigned-fullword :address :unsigned-long :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::accept 30 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getpeername 31 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getsockname 32 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::kill 37 (:signed-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sync 36 () :unsigned-fullword )
+				; 38 is old stat 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getppid 39 ()  :unsigned-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::dup 41 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::pipe 42 () :signed-doubleword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getgid 47 ()  :unsigned-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ioctl 54 (:unsigned-fullword :signed-fullword :address) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::dup2 90 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fcntl 92 (:unsigned-fullword :signed-fullword :signed-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::select 93 (:unsigned-fullword :address :address
+                                                  :address :address)
+                :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fsync 95 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::socket 97 (:unsigned-fullword :unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::connect 98 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::bind 104 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setsockopt 105 (:unsigned-fullword :signed-fullword :signed-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::listen 106 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::gettimeofday 116 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getrusage 117 (:signed-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getsockopt 118 (:unsigned-fullword :signed-fullword :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fchmod 124 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::rename 128 (:address :address) :signed-fullword)
+				; 129 is old truncate 
+				; 130 is old ftruncate 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sendto 133 (:unsigned-fullword :address :unsigned-fullword :unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shutdown 134 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::socketpair 135 (:unsigned-fullword :unsigned-fullword :unsigned-fullword :address) :signed-fullword )
+
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mkdir 136 (:address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::rmdir 137 (:address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mount 167 (:address :address :unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setgid 181 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::stat 188 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fstat 189 (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lstat 190 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lseek 199 (:unsigned-fullword :signed-doubleword :unsigned-fullword) :signed-doubleword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::truncate 200 (:address :unsigned-doubleword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ftruncate 201 (:unsigned-fullword :unsigned-doubleword) :signed-fullword )
+
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::poll 230 ((:* (:struct :pollfd)) :int :int) :int)
+
+#+notdefinedyet
+(progn
+				; 17 is obsolete sbreak 
+				; 18 is old getfsstat 
+				; 19 is old lseek 
+				; 21 is obsolete mount 
+				; 22 is obsolete umount 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ptrace 26 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::access 33 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::chflags 34 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fchflags 35 () )
+				; 40 is old lstat 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getegid 43 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::profil 44 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ktrace 45 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sigaction 46 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sigprocmask 48 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getlogin 49 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setlogin 50 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::acct 51 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sigpending 52 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sigaltstack 53 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::reboot 55 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::revoke 56 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::symlink 57 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::readlink 58 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::execve 59 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::umask 60 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::chroot 61 () )
+				; 62 is old fstat 
+				; 63 is unused 
+				; 64 is old getpagesize 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::msync 65 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::vfork 66 () )
+				; 67 is obsolete vread 
+				; 68 is obsolete vwrite 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sbrk 69 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sstk 70 () )
+				; 71 is old mmap 
+				; 72 is obsolete vadvise 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::munmap 73 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mprotect 74 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::madvise 75 () )
+				; 76 is obsolete vhangup 
+				; 77 is obsolete vlimit 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mincore 78 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getgroups 79 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setgroups 80 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getpgrp 81 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setpgid 82 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setitimer 83 () )
+				; 84 is old wait 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::swapon 85 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getitimer 86 () )
+				; 87 is old gethostname 
+				; 88 is old sethostname 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getdtablesize 89 () )
+
+
+				; 94 is obsolete setdopt 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setpriority 96 () )
+				; 99 is old accept 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getpriority 100 () )
+				; 101 is old send 
+				; 102 is old recv 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sigreturn 103 () )
+				; 107 is obsolete vtimes 
+				; 108 is old sigvec 
+				; 109 is old sigblock 
+				; 110 is old sigsetmask 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sigsuspend 111 () )
+				; 112 is old sigstack 
+				; 113 is old recvmsg 
+				; 114 is old sendmsg 
+				; 115 is obsolete vtrace 
+				; 119 is obsolete resuba 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::readv 120 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::writev 121 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::settimeofday 122 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fchown 123 () )
+				; 125 is old recvfrom 
+				; 126 is old setreuid 
+				; 127 is old setregid 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::flock 131 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mkfifo 132 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::utimes 138 () )
+				; 139 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::adjtime 140 () )
+				; 141 is old getpeername 
+				; 142 is old gethostid 
+				; 143 is old sethostid 
+				; 144 is old getrlimit 
+				; 145 is old setrlimit 
+				; 146 is old killpg 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setsid 147 () )
+				; 148 is obsolete setquota 
+				; 149 is obsolete quota 
+				; 150 is old getsockname 
+				; 151 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setprivexec 152 () )
+				; 153 is reserved 
+				; 154 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::nfssvc 155 () )
+				; 156 is old getdirentries 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::statfs 157 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fstatfs 158 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::unmount 159 () )
+				; 160 is obsolete async_daemon 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getfh 161 () )
+				; 162 is old getdomainname 
+				; 163 is old setdomainname 
+				; 164 is obsolete pcfs_mount 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::quotactl 165 () )
+				; 166 is obsolete exportfs	
+
+				; 168 is obsolete ustat 
+				; 169 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::table 170 () )
+				; 171 is old wait_3 
+				; 172 is obsolete rpause 
+				; 173 is unused 
+				; 174 is obsolete getdents 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::gc_control 175 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::add_profil 176 () )
+				; 177 is unused 
+				; 178 is unused 
+				; 179 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::kdebug_trace 180        () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setegid 182 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::seteuid 183 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lfs_bmapv 184 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lfs_markv 185 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lfs_segclean 186 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lfs_segwait 187 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::pathconf 191 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fpathconf 192 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getrlimit 194 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setrlimit 195 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getdirentries 196 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mmap 197 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::__syscall 198 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::__sysctl 202 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mlock 203 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::munlock 204 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::undelete 205 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ATsocket 206 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ATgetmsg 207 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ATputmsg 208 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ATPsndreq 209 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ATPsndrsp 210 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ATPgetreq 211 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::ATPgetrsp 212 () )
+				; 213-215 are reserved for AppleTalk 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mkcomplex 216  () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::statv 217		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::lstatv 218 			 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::fstatv 219 			 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getattrlist 220 		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::setattrlist 221		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::getdirentriesattr 222 	 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::exchangedata 223 				 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::checkuseraccess 224  () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::searchfs 225 () )
+
+       				; 226 - 230 are reserved for HFS expansion 
+       				; 231 - 249 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::minherit 250 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::semsys 251 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::msgsys 252 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shmsys 253 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::semctl 254 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::semget 255 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::semop 256 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::semconfig 257 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::msgctl 258 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::msgget 259 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::msgsnd 260 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::msgrcv 261 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shmat 262 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shmctl 263 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shmdt 264 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shmget 265 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shm_open 266 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::shm_unlink 267 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_open 268 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_close 269 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_unlink 270 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_wait 271 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_trywait 272 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_post 273 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_getvalue 274 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_init 275 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::sem_destroy 276 () )
+       				; 277 - 295 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::load_shared_file 296 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::reset_shared_file 297 () )
+       				; 298 - 323 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::mlockall 324 () )
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::munlockall 325 () )
+				; 326 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-ppc) syscalls::issetugid 327 () )
+)
Index: /branches/new-random/library/darwinx8632-syscalls.lisp
===================================================================
--- /branches/new-random/library/darwinx8632-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/darwinx8632-syscalls.lisp	(revision 13309)
@@ -0,0 +1,296 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL"))
+
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::exit 1 (:int) :void )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fork 2 () :void)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::read 3 (:unsigned-fullword :address :unsigned-long)
+		:signed-long )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::write 4 (:unsigned-fullword :address :unsigned-long)
+		:signed-long )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::open 5 (:address :unsigned-fullword :unsigned-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::close 6 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::wait4 7 (:unsigned-fullword :address :signed-fullword :address) :unsigned-fullword )
+				; 8 is old creat 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::link 9 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::unlink 10 (:address) :signed-fullword )
+				; 11 is obsolete execv 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::chdir 12 (:address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fchdir 13 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mknod 14  (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::chmod 15 (:address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lchown 16 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getpid 20 () :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setuid 23 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getuid 24 () :unsigned-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::geteuid 25 () :unsigned-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::recvmsg 27 (:unsigned-fullword :address :unsigned-fullword):signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sendmsg 28 (:unsigned-fullword :address :unsigned-fullword):signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::recvfrom 29 (:unsigned-fullword :address :unsigned-long :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::accept 30 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getpeername 31 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getsockname 32 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::kill 37 (:signed-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sync 36 () :unsigned-fullword )
+				; 38 is old stat 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getppid 39 ()  :unsigned-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::dup 41 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::pipe 42 () :signed-doubleword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getgid 47 ()  :unsigned-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ioctl 54 (:unsigned-fullword :signed-fullword :address) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::dup2 90 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fcntl 92 (:unsigned-fullword :signed-fullword :signed-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::select 93 (:unsigned-fullword :address :address
+                                                  :address :address)
+                :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fsync 95 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::socket 97 (:unsigned-fullword :unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::connect 98 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::bind 104 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setsockopt 105 (:unsigned-fullword :signed-fullword :signed-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::listen 106 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::gettimeofday 116 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getrusage 117 (:signed-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getsockopt 118 (:unsigned-fullword :signed-fullword :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fchmod 124 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::rename 128 (:address :address) :signed-fullword)
+				; 129 is old truncate 
+				; 130 is old ftruncate 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sendto 133 (:unsigned-fullword :address :unsigned-fullword :unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shutdown 134 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::socketpair 135 (:unsigned-fullword :unsigned-fullword :unsigned-fullword :address) :signed-fullword )
+
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mkdir 136 (:address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::rmdir 137 (:address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mount 167 (:address :address :unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setgid 181 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::stat 188 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fstat 189 (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lstat 190 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lseek 199 (:unsigned-fullword :signed-doubleword :unsigned-fullword) :signed-doubleword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::truncate 200 (:address :unsigned-doubleword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ftruncate 201 (:unsigned-fullword :unsigned-doubleword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::poll 230 ((:* (:struct :pollfd)) :int :int) :int)
+
+#+notdefinedyet
+(progn
+				; 17 is obsolete sbreak 
+				; 18 is old getfsstat 
+				; 19 is old lseek 
+				; 21 is obsolete mount 
+				; 22 is obsolete umount 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ptrace 26 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::access 33 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::chflags 34 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fchflags 35 () )
+				; 40 is old lstat 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getegid 43 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::profil 44 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ktrace 45 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sigaction 46 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sigprocmask 48 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getlogin 49 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setlogin 50 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::acct 51 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sigpending 52 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sigaltstack 53 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::reboot 55 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::revoke 56 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::symlink 57 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::readlink 58 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::execve 59 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::umask 60 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::chroot 61 () )
+				; 62 is old fstat 
+				; 63 is unused 
+				; 64 is old getpagesize 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::msync 65 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::vfork 66 () )
+				; 67 is obsolete vread 
+				; 68 is obsolete vwrite 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sbrk 69 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sstk 70 () )
+				; 71 is old mmap 
+				; 72 is obsolete vadvise 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::munmap 73 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mprotect 74 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::madvise 75 () )
+				; 76 is obsolete vhangup 
+				; 77 is obsolete vlimit 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mincore 78 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getgroups 79 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setgroups 80 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getpgrp 81 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setpgid 82 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setitimer 83 () )
+				; 84 is old wait 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::swapon 85 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getitimer 86 () )
+				; 87 is old gethostname 
+				; 88 is old sethostname 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getdtablesize 89 () )
+
+
+				; 94 is obsolete setdopt 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setpriority 96 () )
+				; 99 is old accept 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getpriority 100 () )
+				; 101 is old send 
+				; 102 is old recv 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sigreturn 103 () )
+				; 107 is obsolete vtimes 
+				; 108 is old sigvec 
+				; 109 is old sigblock 
+				; 110 is old sigsetmask 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sigsuspend 111 () )
+				; 112 is old sigstack 
+				; 113 is old recvmsg 
+				; 114 is old sendmsg 
+				; 115 is obsolete vtrace 
+				; 119 is obsolete resuba 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::readv 120 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::writev 121 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::settimeofday 122 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fchown 123 () )
+				; 125 is old recvfrom 
+				; 126 is old setreuid 
+				; 127 is old setregid 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::flock 131 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mkfifo 132 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::utimes 138 () )
+				; 139 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::adjtime 140 () )
+				; 141 is old getpeername 
+				; 142 is old gethostid 
+				; 143 is old sethostid 
+				; 144 is old getrlimit 
+				; 145 is old setrlimit 
+				; 146 is old killpg 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setsid 147 () )
+				; 148 is obsolete setquota 
+				; 149 is obsolete quota 
+				; 150 is old getsockname 
+				; 151 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setprivexec 152 () )
+				; 153 is reserved 
+				; 154 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::nfssvc 155 () )
+				; 156 is old getdirentries 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::statfs 157 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fstatfs 158 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::unmount 159 () )
+				; 160 is obsolete async_daemon 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getfh 161 () )
+				; 162 is old getdomainname 
+				; 163 is old setdomainname 
+				; 164 is obsolete pcfs_mount 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::quotactl 165 () )
+				; 166 is obsolete exportfs	
+
+				; 168 is obsolete ustat 
+				; 169 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::table 170 () )
+				; 171 is old wait_3 
+				; 172 is obsolete rpause 
+				; 173 is unused 
+				; 174 is obsolete getdents 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::gc_control 175 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::add_profil 176 () )
+				; 177 is unused 
+				; 178 is unused 
+				; 179 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::kdebug_trace 180        () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setegid 182 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::seteuid 183 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lfs_bmapv 184 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lfs_markv 185 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lfs_segclean 186 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lfs_segwait 187 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::pathconf 191 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fpathconf 192 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getrlimit 194 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setrlimit 195 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getdirentries 196 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mmap 197 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::__syscall 198 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::__sysctl 202 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mlock 203 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::munlock 204 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::undelete 205 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ATsocket 206 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ATgetmsg 207 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ATputmsg 208 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ATPsndreq 209 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ATPsndrsp 210 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ATPgetreq 211 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::ATPgetrsp 212 () )
+				; 213-215 are reserved for AppleTalk 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mkcomplex 216  () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::statv 217		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::lstatv 218 			 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::fstatv 219 			 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getattrlist 220 		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::setattrlist 221		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::getdirentriesattr 222 	 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::exchangedata 223 				 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::checkuseraccess 224  () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::searchfs 225 () )
+
+       				; 226 - 230 are reserved for HFS expansion 
+       				; 231 - 249 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::minherit 250 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::semsys 251 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::msgsys 252 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shmsys 253 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::semctl 254 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::semget 255 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::semop 256 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::semconfig 257 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::msgctl 258 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::msgget 259 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::msgsnd 260 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::msgrcv 261 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shmat 262 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shmctl 263 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shmdt 264 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shmget 265 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shm_open 266 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::shm_unlink 267 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_open 268 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_close 269 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_unlink 270 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_wait 271 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_trywait 272 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_post 273 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_getvalue 274 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_init 275 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::sem_destroy 276 () )
+       				; 277 - 295 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::load_shared_file 296 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::reset_shared_file 297 () )
+       				; 298 - 323 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::mlockall 324 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::munlockall 325 () )
+				; 326 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-32) syscalls::issetugid 327 () )
+)
+
+
Index: /branches/new-random/library/darwinx8664-syscalls.lisp
===================================================================
--- /branches/new-random/library/darwinx8664-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/darwinx8664-syscalls.lisp	(revision 13309)
@@ -0,0 +1,297 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL")
+  (defconstant darwinx8664-unix-syscall-mask #x2000000))
+
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::exit  (logior darwinx8664-unix-syscall-mask 1) (:int) :void )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fork  (logior darwinx8664-unix-syscall-mask 2) () :void)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::read  (logior darwinx8664-unix-syscall-mask 3) (:unsigned-fullword :address :unsigned-long)
+		:signed-long )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::write  (logior darwinx8664-unix-syscall-mask 4) (:unsigned-fullword :address :unsigned-long)
+		:signed-long )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::open  (logior darwinx8664-unix-syscall-mask 5) (:address :unsigned-fullword :unsigned-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::close  (logior darwinx8664-unix-syscall-mask 6) (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::wait4  (logior darwinx8664-unix-syscall-mask 7) (:unsigned-fullword :address :signed-fullword :address) :unsigned-fullword )
+				; 8 is old creat 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::link  (logior darwinx8664-unix-syscall-mask 9) (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::unlink  (logior darwinx8664-unix-syscall-mask 10) (:address) :signed-fullword )
+				; 11 is obsolete execv 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::chdir  (logior darwinx8664-unix-syscall-mask 12) (:address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fchdir  (logior darwinx8664-unix-syscall-mask 13) (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mknod  (logior darwinx8664-unix-syscall-mask 14)  (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::chmod  (logior darwinx8664-unix-syscall-mask 15) (:address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lchown  (logior darwinx8664-unix-syscall-mask 16) (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getpid  (logior darwinx8664-unix-syscall-mask 20) () :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setuid  (logior darwinx8664-unix-syscall-mask 23) (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getuid  (logior darwinx8664-unix-syscall-mask 24) () :unsigned-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::geteuid  (logior darwinx8664-unix-syscall-mask 25) () :unsigned-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::recvmsg  (logior darwinx8664-unix-syscall-mask 27) (:unsigned-fullword :address :unsigned-fullword):signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sendmsg  (logior darwinx8664-unix-syscall-mask 28) (:unsigned-fullword :address :unsigned-fullword):signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::recvfrom  (logior darwinx8664-unix-syscall-mask 29) (:unsigned-fullword :address :unsigned-long :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::accept  (logior darwinx8664-unix-syscall-mask 30) (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getpeername  (logior darwinx8664-unix-syscall-mask 31) (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getsockname  (logior darwinx8664-unix-syscall-mask 32) (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::kill  (logior darwinx8664-unix-syscall-mask 37) (:signed-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sync  (logior darwinx8664-unix-syscall-mask 36) () :unsigned-fullword )
+				; 38 is old stat 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getppid  (logior darwinx8664-unix-syscall-mask 39) ()  :unsigned-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::dup  (logior darwinx8664-unix-syscall-mask 41) (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::pipe  (logior darwinx8664-unix-syscall-mask 42) () :signed-doubleword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getgid  (logior darwinx8664-unix-syscall-mask 47) ()  :unsigned-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ioctl  (logior darwinx8664-unix-syscall-mask 54) (:unsigned-fullword :signed-fullword :address) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::dup2  (logior darwinx8664-unix-syscall-mask 90) (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fcntl  (logior darwinx8664-unix-syscall-mask 92) (:unsigned-fullword :signed-fullword :signed-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::select  (logior darwinx8664-unix-syscall-mask 93) (:unsigned-fullword :address :address
+                                                  :address :address)
+                :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fsync  (logior darwinx8664-unix-syscall-mask 95) (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::socket  (logior darwinx8664-unix-syscall-mask 97) (:unsigned-fullword :unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::connect  (logior darwinx8664-unix-syscall-mask 98) (:unsigned-fullword :address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::bind  (logior darwinx8664-unix-syscall-mask 104) (:unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setsockopt  (logior darwinx8664-unix-syscall-mask 105) (:unsigned-fullword :signed-fullword :signed-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::listen  (logior darwinx8664-unix-syscall-mask 106) (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::gettimeofday  (logior darwinx8664-unix-syscall-mask 116) (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getrusage  (logior darwinx8664-unix-syscall-mask 117) (:signed-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getsockopt  (logior darwinx8664-unix-syscall-mask 118) (:unsigned-fullword :signed-fullword :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fchmod  (logior darwinx8664-unix-syscall-mask 124) (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::rename  (logior darwinx8664-unix-syscall-mask 128) (:address :address) :signed-fullword)
+				; 129 is old truncate 
+				; 130 is old ftruncate 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sendto  (logior darwinx8664-unix-syscall-mask 133) (:unsigned-fullword :address :unsigned-fullword :unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shutdown  (logior darwinx8664-unix-syscall-mask 134) (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::socketpair  (logior darwinx8664-unix-syscall-mask 135) (:unsigned-fullword :unsigned-fullword :unsigned-fullword :address) :signed-fullword )
+
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mkdir  (logior darwinx8664-unix-syscall-mask 136) (:address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::rmdir  (logior darwinx8664-unix-syscall-mask 137) (:address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mount  (logior darwinx8664-unix-syscall-mask 167) (:address :address :unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setgid  (logior darwinx8664-unix-syscall-mask 181) (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::stat  (logior darwinx8664-unix-syscall-mask 188) (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fstat  (logior darwinx8664-unix-syscall-mask 189) (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lstat  (logior darwinx8664-unix-syscall-mask 190) (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lseek  (logior darwinx8664-unix-syscall-mask 199) (:unsigned-fullword :signed-doubleword :unsigned-fullword) :signed-doubleword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::truncate  (logior darwinx8664-unix-syscall-mask 200) (:address :unsigned-doubleword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ftruncate  (logior darwinx8664-unix-syscall-mask 201) (:unsigned-fullword :unsigned-doubleword) :signed-fullword )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::poll (logior darwinx8664-unix-syscall-mask 230) ((:* (:struct :pollfd)) :int :int) :int)
+#+notdefinedyet
+(progn
+				; 17 is obsolete sbreak 
+				; 18 is old getfsstat 
+				; 19 is old lseek 
+				; 21 is obsolete mount 
+				; 22 is obsolete umount 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ptrace  (logior darwinx8664-unix-syscall-mask 26) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::access  (logior darwinx8664-unix-syscall-mask 33) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::chflags  (logior darwinx8664-unix-syscall-mask 34) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fchflags  (logior darwinx8664-unix-syscall-mask 35) () )
+				; 40 is old lstat 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getegid  (logior darwinx8664-unix-syscall-mask 43) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::profil  (logior darwinx8664-unix-syscall-mask 44) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ktrace  (logior darwinx8664-unix-syscall-mask 45) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sigaction  (logior darwinx8664-unix-syscall-mask 46) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sigprocmask  (logior darwinx8664-unix-syscall-mask 48) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getlogin  (logior darwinx8664-unix-syscall-mask 49) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setlogin  (logior darwinx8664-unix-syscall-mask 50) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::acct  (logior darwinx8664-unix-syscall-mask 51) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sigpending  (logior darwinx8664-unix-syscall-mask 52) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sigaltstack  (logior darwinx8664-unix-syscall-mask 53) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::reboot  (logior darwinx8664-unix-syscall-mask 55) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::revoke  (logior darwinx8664-unix-syscall-mask 56) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::symlink  (logior darwinx8664-unix-syscall-mask 57) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::readlink  (logior darwinx8664-unix-syscall-mask 58) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::execve  (logior darwinx8664-unix-syscall-mask 59) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::umask  (logior darwinx8664-unix-syscall-mask 60) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::chroot  (logior darwinx8664-unix-syscall-mask 61) () )
+				; 62 is old fstat 
+				; 63 is unused 
+				; 64 is old getpagesize 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::msync  (logior darwinx8664-unix-syscall-mask 65) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::vfork  (logior darwinx8664-unix-syscall-mask 66) () )
+				; 67 is obsolete vread 
+				; 68 is obsolete vwrite 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sbrk  (logior darwinx8664-unix-syscall-mask 69) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sstk  (logior darwinx8664-unix-syscall-mask 70) () )
+				; 71 is old mmap 
+				; 72 is obsolete vadvise 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::munmap  (logior darwinx8664-unix-syscall-mask 73) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mprotect  (logior darwinx8664-unix-syscall-mask 74) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::madvise  (logior darwinx8664-unix-syscall-mask 75) () )
+				; 76 is obsolete vhangup 
+				; 77 is obsolete vlimit 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mincore  (logior darwinx8664-unix-syscall-mask 78) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getgroups  (logior darwinx8664-unix-syscall-mask 79) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setgroups  (logior darwinx8664-unix-syscall-mask 80) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getpgrp  (logior darwinx8664-unix-syscall-mask 81) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setpgid  (logior darwinx8664-unix-syscall-mask 82) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setitimer  (logior darwinx8664-unix-syscall-mask 83) () )
+				; 84 is old wait 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::swapon  (logior darwinx8664-unix-syscall-mask 85) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getitimer  (logior darwinx8664-unix-syscall-mask 86) () )
+				; 87 is old gethostname 
+				; 88 is old sethostname 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getdtablesize  (logior darwinx8664-unix-syscall-mask 89) () )
+
+
+				; 94 is obsolete setdopt 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setpriority  (logior darwinx8664-unix-syscall-mask 96) () )
+				; 99 is old accept 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getpriority  (logior darwinx8664-unix-syscall-mask 100) () )
+				; 101 is old send 
+				; 102 is old recv 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sigreturn  (logior darwinx8664-unix-syscall-mask 103) () )
+				; 107 is obsolete vtimes 
+				; 108 is old sigvec 
+				; 109 is old sigblock 
+				; 110 is old sigsetmask 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sigsuspend  (logior darwinx8664-unix-syscall-mask 111) () )
+				; 112 is old sigstack 
+				; 113 is old recvmsg 
+				; 114 is old sendmsg 
+				; 115 is obsolete vtrace 
+				; 119 is obsolete resuba 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::readv  (logior darwinx8664-unix-syscall-mask 120) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::writev  (logior darwinx8664-unix-syscall-mask 121) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::settimeofday  (logior darwinx8664-unix-syscall-mask 122) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fchown  (logior darwinx8664-unix-syscall-mask 123) () )
+				; 125 is old recvfrom 
+				; 126 is old setreuid 
+				; 127 is old setregid 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::flock  (logior darwinx8664-unix-syscall-mask 131) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mkfifo  (logior darwinx8664-unix-syscall-mask 132) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::utimes  (logior darwinx8664-unix-syscall-mask 138) () )
+				; 139 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::adjtime  (logior darwinx8664-unix-syscall-mask 140) () )
+				; 141 is old getpeername 
+				; 142 is old gethostid 
+				; 143 is old sethostid 
+				; 144 is old getrlimit 
+				; 145 is old setrlimit 
+				; 146 is old killpg 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setsid  (logior darwinx8664-unix-syscall-mask 147) () )
+				; 148 is obsolete setquota 
+				; 149 is obsolete quota 
+				; 150 is old getsockname 
+				; 151 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setprivexec  (logior darwinx8664-unix-syscall-mask 152) () )
+				; 153 is reserved 
+				; 154 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::nfssvc  (logior darwinx8664-unix-syscall-mask 155) () )
+				; 156 is old getdirentries 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::statfs  (logior darwinx8664-unix-syscall-mask 157) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fstatfs  (logior darwinx8664-unix-syscall-mask 158) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::unmount  (logior darwinx8664-unix-syscall-mask 159) () )
+				; 160 is obsolete async_daemon 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getfh  (logior darwinx8664-unix-syscall-mask 161) () )
+				; 162 is old getdomainname 
+				; 163 is old setdomainname 
+				; 164 is obsolete pcfs_mount 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::quotactl  (logior darwinx8664-unix-syscall-mask 165) () )
+				; 166 is obsolete exportfs	
+
+				; 168 is obsolete ustat 
+				; 169 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::table  (logior darwinx8664-unix-syscall-mask 170) () )
+				; 171 is old wait_3 
+				; 172 is obsolete rpause 
+				; 173 is unused 
+				; 174 is obsolete getdents 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::gc_control  (logior darwinx8664-unix-syscall-mask 175) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::add_profil  (logior darwinx8664-unix-syscall-mask 176) () )
+				; 177 is unused 
+				; 178 is unused 
+				; 179 is unused 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::kdebug_trace  (logior darwinx8664-unix-syscall-mask 180)        () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setegid  (logior darwinx8664-unix-syscall-mask 182) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::seteuid  (logior darwinx8664-unix-syscall-mask 183) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lfs_bmapv  (logior darwinx8664-unix-syscall-mask 184) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lfs_markv  (logior darwinx8664-unix-syscall-mask 185) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lfs_segclean  (logior darwinx8664-unix-syscall-mask 186) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lfs_segwait  (logior darwinx8664-unix-syscall-mask 187) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::pathconf  (logior darwinx8664-unix-syscall-mask 191) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fpathconf  (logior darwinx8664-unix-syscall-mask 192) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getrlimit  (logior darwinx8664-unix-syscall-mask 194) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setrlimit  (logior darwinx8664-unix-syscall-mask 195) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getdirentries  (logior darwinx8664-unix-syscall-mask 196) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mmap  (logior darwinx8664-unix-syscall-mask 197) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::__syscall  (logior darwinx8664-unix-syscall-mask 198) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::__sysctl  (logior darwinx8664-unix-syscall-mask 202) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mlock  (logior darwinx8664-unix-syscall-mask 203) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::munlock  (logior darwinx8664-unix-syscall-mask 204) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::undelete  (logior darwinx8664-unix-syscall-mask 205) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ATsocket  (logior darwinx8664-unix-syscall-mask 206) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ATgetmsg  (logior darwinx8664-unix-syscall-mask 207) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ATputmsg  (logior darwinx8664-unix-syscall-mask 208) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ATPsndreq  (logior darwinx8664-unix-syscall-mask 209) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ATPsndrsp  (logior darwinx8664-unix-syscall-mask 210) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ATPgetreq  (logior darwinx8664-unix-syscall-mask 211) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::ATPgetrsp  (logior darwinx8664-unix-syscall-mask 212) () )
+				; 213-215 are reserved for AppleTalk 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mkcomplex  (logior darwinx8664-unix-syscall-mask 216)  () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::statv  (logior darwinx8664-unix-syscall-mask 217)		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::lstatv  (logior darwinx8664-unix-syscall-mask 218) 			 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::fstatv  (logior darwinx8664-unix-syscall-mask 219) 			 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getattrlist  (logior darwinx8664-unix-syscall-mask 220) 		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::setattrlist  (logior darwinx8664-unix-syscall-mask 221)		 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::getdirentriesattr  (logior darwinx8664-unix-syscall-mask 222) 	 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::exchangedata  (logior darwinx8664-unix-syscall-mask 223) 				 () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::checkuseraccess  (logior darwinx8664-unix-syscall-mask 224)  () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::searchfs  (logior darwinx8664-unix-syscall-mask 225) () )
+
+       				; 226 - 230 are reserved for HFS expansion 
+       				; 231 - 249 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::minherit  (logior darwinx8664-unix-syscall-mask 250) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::semsys  (logior darwinx8664-unix-syscall-mask 251) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::msgsys  (logior darwinx8664-unix-syscall-mask 252) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shmsys  (logior darwinx8664-unix-syscall-mask 253) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::semctl  (logior darwinx8664-unix-syscall-mask 254) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::semget  (logior darwinx8664-unix-syscall-mask 255) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::semop  (logior darwinx8664-unix-syscall-mask 256) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::semconfig  (logior darwinx8664-unix-syscall-mask 257) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::msgctl  (logior darwinx8664-unix-syscall-mask 258) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::msgget  (logior darwinx8664-unix-syscall-mask 259) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::msgsnd  (logior darwinx8664-unix-syscall-mask 260) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::msgrcv  (logior darwinx8664-unix-syscall-mask 261) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shmat  (logior darwinx8664-unix-syscall-mask 262) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shmctl  (logior darwinx8664-unix-syscall-mask 263) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shmdt  (logior darwinx8664-unix-syscall-mask 264) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shmget  (logior darwinx8664-unix-syscall-mask 265) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shm_open  (logior darwinx8664-unix-syscall-mask 266) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::shm_unlink  (logior darwinx8664-unix-syscall-mask 267) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_open  (logior darwinx8664-unix-syscall-mask 268) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_close  (logior darwinx8664-unix-syscall-mask 269) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_unlink  (logior darwinx8664-unix-syscall-mask 270) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_wait  (logior darwinx8664-unix-syscall-mask 271) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_trywait  (logior darwinx8664-unix-syscall-mask 272) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_post  (logior darwinx8664-unix-syscall-mask 273) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_getvalue  (logior darwinx8664-unix-syscall-mask 274) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_init  (logior darwinx8664-unix-syscall-mask 275) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::sem_destroy  (logior darwinx8664-unix-syscall-mask 276) () )
+       				; 277 - 295 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::load_shared_file  (logior darwinx8664-unix-syscall-mask 296) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::reset_shared_file  (logior darwinx8664-unix-syscall-mask 297) () )
+       				; 298 - 323 are reserved  
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::mlockall  (logior darwinx8664-unix-syscall-mask 324) () )
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::munlockall  (logior darwinx8664-unix-syscall-mask 325) () )
+				; 326 is reserved 
+(define-syscall (logior platform-os-darwin platform-cpu-x86 platform-word-size-64) syscalls::issetugid  (logior darwinx8664-unix-syscall-mask 327) () )
+)
Index: /branches/new-random/library/elf.lisp
===================================================================
--- /branches/new-random/library/elf.lisp	(revision 13309)
+++ /branches/new-random/library/elf.lisp	(revision 13309)
@@ -0,0 +1,408 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (use-interface-dir :elf))
+
+
+(defloadvar *readonly-area*
+    (do-consing-areas (a)
+      (when (eql (%fixnum-ref a target::area.code)
+                 ccl::area-readonly)
+        (return a))))
+
+;;; String tables: used both for symbol names and for section names.
+(defstruct elf-string-table
+  (hash (make-hash-table :test #'equal))
+  (string (make-array 100 :element-type '(unsigned-byte 8) :fill-pointer 1 :adjustable t)))
+
+;;; Collect info about Elf symbols.
+(defstruct elf-symbol-table
+  (strings (make-elf-string-table))
+  data                                  ; foreign pointer
+  nsyms
+  )
+
+;;; Wrapper around libelf's "elf" pointer
+(defstruct elf-object
+  libelf-pointer
+  fd
+  pathname
+  )
+
+
+;;; Is libelf thread-safe ?  Who knows, there's no
+;;; documentation ...
+(defun libelf-error-string (&optional (errnum -1))
+  (let* ((p (#_elf_errmsg errnum)))
+    (if (%null-ptr-p p)
+      (format nil "ELF error ~d" errnum)
+      (%get-cstring p))))
+
+(defloadvar *checked-libelf-version* nil)
+
+(defun check-libelf-version ()
+  (or *checked-libelf-version*
+      (progn
+        (open-shared-library "libelf.so")
+        (let* ((version (#_elf_version #$EV_CURRENT)))
+          (if (eql #$EV_NONE version)
+            (error "ELF library initialization failed: ~a" (libelf-error-string)))
+          (setq *checked-libelf-version* version)))))
+
+
+;;; Prepate to create an ELF object file at PATHNAME, overwriting
+;;; whatever might have been there.
+(defun create-elf-object (pathname)
+  (let* ((namestring (native-translated-namestring pathname))
+         (fd (ccl::fd-open namestring
+                           (logior #$O_RDWR #$O_CREAT #$O_TRUNC)
+                           #o755)))
+    (if (< fd 0)
+      (signal-file-error fd pathname)
+      (progn
+        (check-libelf-version)
+        (let* ((ptr (#_elf_begin fd #$ELF_C_WRITE +null-ptr+)))
+          (if (%null-ptr-p ptr)
+            (error "Can't initialize libelf object for ~s: ~a"
+                   pathname (libelf-error-string))
+            (make-elf-object :libelf-pointer (assert-pointer-type ptr :<E>lf)
+                             :fd fd
+                             :pathname pathname)))))))
+
+(defun elf-end (object)
+  (#_elf_end (elf-object-libelf-pointer object))
+  (setf (elf-object-libelf-pointer object) nil
+        (elf-object-fd object) nil))
+
+(defun new-elf-file-header (object format type machine)
+  (let* ((ehdr (#+64-bit-target #_elf64_newehdr #+32-bit-target #_elf32_newehdr (elf-object-libelf-pointer object))))
+    (if (%null-ptr-p ehdr)
+      (error "Can't create ELF file header for ~s: ~a"
+             (elf-object-pathname object)
+             (libelf-error-string))
+      (progn
+        (setf (paref (pref ehdr
+                           #+64-bit-target :<E>lf64_<E>hdr.e_ident
+                           #+32-bit-target :<E>lf32_<E>hdr.e_ident) (:* :unsigned-char) #$EI_DATA) format
+              (pref ehdr
+                    #+64-bit-target :<E>lf64_<E>hdr.e_machine
+                    #+32-bit-target :<E>lf32_<E>hdr.e_machine) machine
+              (pref ehdr
+                    #+64-bit-target :<E>lf64_<E>hdr.e_type
+                    #+32-bit-target :<E>lf32_<E>hdr.e_type) type
+              (pref ehdr
+                    #+64-bit-target :<E>lf64_<E>hdr.e_version
+                    #+32-bit-target :<E>lf32_<E>hdr.e_version) *checked-libelf-version*)
+        (assert-pointer-type ehdr
+                             #+64-bit-target :<E>lf64_<E>hdr
+                             #+32-bit-target :<E>lf32_<E>hdr)))))
+
+(defun new-elf-program-header (object &optional (count 1))
+  (let* ((phdr (#+64-bit-target #_elf64_newphdr #+32-bit-target #_elf32_newphdr (elf-object-libelf-pointer object) count)))
+    (if (%null-ptr-p phdr)
+      (error "Can't create ELF program header for ~s: ~a"
+             (elf-object-pathname object)
+             (libelf-error-string))
+      (assert-pointer-type phdr
+                           #+64-bit-target :<E>lf64_<P>hdr
+                           #+32-bit-target :<E>lf32_<P>hdr))))
+
+(defun new-elf-section (object)
+  (let* ((scn (#_elf_newscn (elf-object-libelf-pointer object))))
+    (if (%null-ptr-p scn)
+      (error "Can' create ELF section for ~s: ~a"
+             (elf-object-pathname object)
+             (libelf-error-string))
+      (assert-pointer-type scn :<E>lf_<S>cn))))
+
+(defun elf-section-header-for-section (object section)
+  (let* ((shdr (#+64-bit-target #_elf64_getshdr #+32-bit-target #_elf32_getshdr  section)))
+    (if (%null-ptr-p shdr)
+      (error "Can' obtain ELF section header for ~s: ~a"
+             (elf-object-pathname object)
+             (libelf-error-string))
+      (assert-pointer-type shdr
+                           #+64-bit-target :<E>lf64_<S>hdr
+                           #+32-bit-target :<E>lf32_<S>hdr))))
+
+(defun elf-data-pointer-for-section (object section)
+  (let* ((data (#_elf_newdata section)))
+    (if (%null-ptr-p data)
+      (error "Can' obtain ELF data pointer for ~s: ~a"
+             (elf-object-pathname object)
+             (libelf-error-string))
+      (assert-pointer-type data :<E>lf_<D>ata))))
+                   
+
+(defun elf-register-string (string table)
+  (let* ((hash (elf-string-table-hash table))
+         (s (elf-string-table-string table)))
+    (when (gethash string hash)
+      (format t "~& duplicate: ~s" string))
+    (or (gethash string hash)
+        (setf (gethash string hash)
+              (let* ((n (length s)))
+                (dotimes (i (length string) (progn (vector-push-extend 0 s) n))
+                  (let* ((code (char-code (char string i))))
+                    (declare (type (mod #x110000) code))
+                    (if (> code 255)
+                      (vector-push-extend (char-code #\sub) s)
+                      (vector-push-extend code s)))))))))
+
+
+(defun elf-lisp-function-name (f)
+  (let* ((name (format nil "~s" f)))
+    (subseq (nsubstitute #\0 #\# (nsubstitute #\. #\Space name)) 1)))
+
+
+
+(defun collect-elf-static-functions ()
+  (collect ((functions))
+    (purify)
+    (block walk
+      (%map-areas (lambda (o)
+                    (when (typep o
+                                 #+x8664-target 'function-vector
+                                 #-x8664-target 'function)
+                      (functions (function-vector-to-function o))))
+                  ccl::area-readonly
+                  ccl::area-readonly
+                  ))
+    (functions)))
+
+(defun register-elf-functions (section-number)
+  (let* ((functions (collect-elf-static-functions))
+         (n (length functions))
+         (data (#_calloc (1+ n) (record-length #+64-bit-target :<E>lf64_<S>ym
+                                               #+32-bit-target :<E>lf32_<S>ym)))
+         (string-table (make-elf-string-table)))
+    (declare (fixnum n))
+    (do* ((i 0 (1+ i))
+          (p (%inc-ptr data
+                       (record-length #+64-bit-target :<E>lf64_<S>ym
+                                      #+32-bit-target :<E>lf32_<S>ym))
+             (progn (%incf-ptr p
+                               (record-length #+64-bit-target :<E>lf64_<S>ym
+                                              #+32-bit-target :<E>lf32_<S>ym))
+                    p))
+          (f (pop functions) (pop functions)))
+         ((= i n)
+          (make-elf-symbol-table :strings string-table :data data :nsyms n))
+      (declare (fixnum n))
+      (setf (pref p
+                  #+64-bit-target :<E>lf64_<S>ym.st_name
+                  #+32-bit-target :<E>lf32_<S>ym.st_name)
+            (elf-register-string (elf-lisp-function-name f) string-table)
+            (pref p
+                  #+64-bit-target :<E>lf64_<S>ym.st_info
+                  #+32-bit-target :<E>lf32_<S>ym.st_info)
+            (logior (ash #$STB_GLOBAL 4) #$STT_FUNC)
+            (pref p
+                  #+64-bit-target :<E>lf64_<S>ym.st_shndx
+                  #+32-bit-target :<E>lf32_<S>ym.st_shndx) section-number
+            (pref p
+                  #+64-bit-target :<E>lf64_<S>ym.st_value
+                  #+32-bit-target :<E>lf32_<S>ym.st_value) (%address-of f)
+            (pref p
+                  #+64-bit-target :<E>lf64_<S>ym.st_size
+                  #+32-bit-target :<E>lf32_<S>ym.st_size) (1+ (ash (1- (%function-code-words f)) target::word-shift))))))
+
+(defun elf-section-index (section)
+  (#_elf_ndxscn section))
+
+(defun elf-set-shstrab-section (object scn)
+  #+freebsd-target
+  (#_elf_setshstrndx (elf-object-libelf-pointer object) (elf-section-index scn))
+  #-freebsd-target
+  (declare (ignore object scn)))
+
+
+(defun elf-init-section-data-from-string-table (object section string-table)
+  (let* ((strings-data (elf-data-pointer-for-section object section))
+         (s (elf-string-table-string string-table))
+         (bytes (array-data-and-offset s))
+         (n (length s))
+         (buf (#_malloc n)))
+    (%copy-ivector-to-ptr bytes 0 buf 0 n)
+    (setf (pref strings-data :<E>lf_<D>ata.d_align) 1
+          (pref strings-data :<E>lf_<D>ata.d_off) 0
+          (pref strings-data :<E>lf_<D>ata.d_type) #$ELF_T_BYTE
+          (pref strings-data :<E>lf_<D>ata.d_version) #$EV_CURRENT
+          (pref strings-data :<E>lf_<D>ata.d_size) n
+          (pref strings-data :<E>lf_<D>ata.d_buf) buf)
+    n))
+
+(defun elf-init-symbol-section-from-symbol-table (object section symbols)
+  (let* ((symbols-data (elf-data-pointer-for-section object section))
+         (buf (elf-symbol-table-data symbols))
+         (nsyms (elf-symbol-table-nsyms symbols) )
+         (n (* (1+ nsyms) (record-length #+64-bit-target :<E>lf64_<S>ym
+                                         #+32-bit-target :<E>lf32_<S>ym))))
+    (setf (pref symbols-data :<E>lf_<D>ata.d_align) 8
+          (pref symbols-data :<E>lf_<D>ata.d_off) 0
+          (pref symbols-data :<E>lf_<D>ata.d_type) #$ELF_T_SYM
+          (pref symbols-data :<E>lf_<D>ata.d_version) #$EV_CURRENT
+          (pref symbols-data :<E>lf_<D>ata.d_size) n
+          (pref symbols-data :<E>lf_<D>ata.d_buf) buf)
+    nsyms))
+
+(defun elf-make-empty-data-for-section (object section &optional (size 0))
+  (let* ((data (elf-data-pointer-for-section object section))
+         (buf +null-ptr+))
+    (setf (pref data :<E>lf_<D>ata.d_align) 0
+          (pref data :<E>lf_<D>ata.d_off) 0
+          (pref data :<E>lf_<D>ata.d_type) #$ELF_T_BYTE
+          (pref data :<E>lf_<D>ata.d_version) #$EV_CURRENT
+          (pref data :<E>lf_<D>ata.d_size) size
+          (pref data :<E>lf_<D>ata.d_buf) buf)
+    0))
+  
+
+(defun elf-flag-phdr (object cmd flags)
+  (#_elf_flagphdr (elf-object-libelf-pointer object) cmd flags))
+
+(defun elf-update (object cmd)
+  (let* ((size (#_elf_update (elf-object-libelf-pointer object) cmd)))
+    (if (< size 0)
+      (error "elf_update failed for for ~s: ~a"
+             (elf-object-pathname object)
+             (libelf-error-string))
+      size)))
+
+(defun fixup-lisp-section-offset (fd eof sectnum)
+  (fd-lseek fd 0 #$SEEK_SET)
+  (rlet ((fhdr #+64-bit-target :<E>lf64_<E>hdr
+               #+32-bit-target :<E>lf32_<E>hdr)
+         (shdr #+64-bit-target :<E>lf64_<S>hdr
+               #+32-bit-target :<E>lf32_<S>hdr))
+    (fd-read fd fhdr (record-length #+64-bit-target :<E>lf64_<E>hdr
+                                    #+32-bit-target :<E>lf32_<E>hdr))
+    (let* ((pos (+ (pref fhdr #+64-bit-target :<E>lf64_<E>hdr.e_shoff
+                         #+32-bit-target :<E>lf32_<E>hdr.e_shoff)
+                   (* sectnum (pref fhdr #+64-bit-target :<E>lf64_<E>hdr.e_shentsize
+                                    #+32-bit-target :<E>lf32_<E>hdr.e_shentsize)))))
+      (fd-lseek fd pos #$SEEK_SET)
+      (fd-read fd shdr (record-length #+64-bit-target :<E>lf64_<S>hdr
+                                      #+32-bit-target :<E>lf32_<S>hdr))
+      ;; On 64-bit platforms, the section data precedes the image
+      ;; header; on 32-bit platforms, the image header and image
+      ;; section table precede the image data for the first (static)
+      ;; section.  With alignment, the header/section headers are
+      ;; one 4K page, and the static section size is 8K ...
+      (setf (pref shdr #+64-bit-target :<E>lf64_<S>hdr.sh_offset
+                  #+32-bit-target :<E>lf32_<S>hdr.sh_offset)
+            (+ #+32-bit-target #x1000 #+64-bit-target 0  #x2000 (logandc2 (+ eof 4095) 4095))) 
+      (setf (pref shdr #+64-bit-target :<E>lf64_<S>hdr.sh_type
+                  #+32-bit-target :<E>lf32_<S>hdr.sh_type)
+            #$SHT_PROGBITS)
+      (fd-lseek fd pos #$SEEK_SET)
+      (fd-write fd shdr (record-length #+64-bit-target :<E>lf64_<S>hdr
+                                       #+32-bit-target :<E>lf32_<S>hdr))
+      t)))
+  
+(defun write-elf-symbols-to-file (pathname)
+  (let* ((object (create-elf-object pathname))
+         (file-header (new-elf-file-header object
+                                           #+little-endian-target #$ELFDATA2LSB
+                                           #+big-endian-target #$ELFDATA2MSB
+                                           #$ET_DYN
+                                           #+x8664-target #$EM_X86_64
+                                           #+x8632-target #$EM_386
+                                           #+ppc32-target #$EM_PPC
+                                           #+ppc64-target #$EM_PPC64
+                                           ))
+         (program-header (new-elf-program-header object))
+         (lisp-section (new-elf-section object))
+         (symbols-section (new-elf-section object))
+         (strings-section (new-elf-section object))
+         (shstrtab-section (new-elf-section object))
+         (section-names (make-elf-string-table))
+         (lisp-section-index (elf-section-index lisp-section))
+         (symbols (register-elf-functions lisp-section-index))
+         (lisp-section-header (elf-section-header-for-section object lisp-section))
+         (symbols-section-header (elf-section-header-for-section object symbols-section))
+         (strings-section-header (elf-section-header-for-section object strings-section))
+         (shstrtab-section-header (elf-section-header-for-section object shstrtab-section)))
+    
+    (setf (pref file-header #+64-bit-target :<E>lf64_<E>hdr.e_shstrndx
+                #+32-bit-target :<E>lf32_<E>hdr.e_shstrndx) (elf-section-index shstrtab-section))
+    (setf (pref lisp-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_name
+                #+32-bit-target :<E>lf32_<S>hdr.sh_name) (elf-register-string ".lisp" section-names)
+          (pref lisp-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_type
+                #+32-bit-target :<E>lf32_<S>hdr.sh_type) #$SHT_NOBITS
+          (pref lisp-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_flags
+                #+32-bit-target :<E>lf32_<S>hdr.sh_flags) (logior #$SHF_WRITE #$SHF_ALLOC #$SHF_EXECINSTR)
+          (pref lisp-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_addr
+                #+32-bit-target :<E>lf32_<S>hdr.sh_addr) (ash (%fixnum-ref *readonly-area* target::area.low) target::fixnumshift)
+          (pref lisp-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_size
+                #+32-bit-target :<E>lf32_<S>hdr.sh_size) (ash (- (%fixnum-ref *readonly-area* target::area.active) (%fixnum-ref *readonly-area* target::area.low) )target::fixnumshift)
+          (pref lisp-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_offset
+                #+32-bit-target :<E>lf32_<S>hdr.sh_offset) 0
+          (pref lisp-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_addralign
+                #+32-bit-target :<E>lf32_<S>hdr.sh_addralign) 1)
+    (setf (pref symbols-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_name
+                #+32-bit-target :<E>lf32_<S>hdr.sh_name) (elf-register-string ".symtab" section-names)
+          (pref symbols-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_type
+                #+32-bit-target :<E>lf32_<S>hdr.sh_type) #$SHT_SYMTAB
+          (pref symbols-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_entsize
+                #+32-bit-target :<E>lf32_<S>hdr.sh_entsize) (record-length #+64-bit-target :<E>lf64_<S>ym
+                                                                           #+32-bit-target :<E>lf32_<S>ym)
+          (pref symbols-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_link
+                #+32-bit-target :<E>lf32_<S>hdr.sh_link) (elf-section-index strings-section))
+    (setf (pref strings-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_name
+                #+32-bit-target :<E>lf32_<S>hdr.sh_name) (elf-register-string ".strtab" section-names)
+          (pref strings-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_type
+                #+32-bit-target :<E>lf32_<S>hdr.sh_type) #$SHT_STRTAB
+          (pref strings-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_flags
+                #+32-bit-target :<E>lf32_<S>hdr.sh_flags) (logior #$SHF_STRINGS #$SHF_ALLOC))
+    (setf (pref shstrtab-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_name
+                #+32-bit-target :<E>lf32_<S>hdr.sh_name) (elf-register-string ".shstrtab" section-names)
+          (pref shstrtab-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_type
+                #+32-bit-target :<E>lf32_<S>hdr.sh_type) #$SHT_STRTAB
+          (pref shstrtab-section-header #+64-bit-target :<E>lf64_<S>hdr.sh_flags
+                #+32-bit-target :<E>lf32_<S>hdr.sh_flags) (logior #$SHF_STRINGS #$SHF_ALLOC))
+    (elf-make-empty-data-for-section object lisp-section (ash (- (%fixnum-ref *readonly-area* target::area.active) (%fixnum-ref *readonly-area* target::area.low) )target::fixnumshift))
+    (elf-init-section-data-from-string-table object strings-section (elf-symbol-table-strings symbols))
+    (elf-init-section-data-from-string-table object shstrtab-section section-names)
+    (elf-init-symbol-section-from-symbol-table object symbols-section symbols)
+    ;; Prepare in-memory data structures.
+    (elf-update object #$ELF_C_NULL)
+    ;; Fix up the program header.
+    (setf (pref program-header
+                #+64-bit-target :<E>lf64_<P>hdr.p_type
+                #+32-bit-target :<E>lf32_<P>hdr.p_type) #$PT_PHDR
+          (pref program-header #+64-bit-target :<E>lf64_<P>hdr.p_offset
+                #+32-bit-target :<E>lf32_<P>hdr.p_offset)
+          (pref file-header
+                #+64-bit-target :<E>lf64_<E>hdr.e_phoff
+                #+32-bit-target :<E>lf32_<E>hdr.e_phoff)
+          (pref program-header
+                #+64-bit-target :<E>lf64_<P>hdr.p_filesz
+                #+32-bit-target :<E>lf32_<P>hdr.p_filesz)
+          (#+64-bit-target #_elf64_fsize #+32-bit-target #_elf32_fsize #$ELF_T_PHDR 1 #$EV_CURRENT))
+    ;; Mark the program header as being dirty.
+    (elf-flag-phdr object #$ELF_C_SET #$ELF_F_DIRTY)
+    (let* ((eof (elf-update object #$ELF_C_WRITE))
+           (fd (elf-object-fd object)))
+      (elf-end object)
+      (fixup-lisp-section-offset fd eof lisp-section-index)
+      (fd-close fd))
+    pathname))
+
+      
+    
+    
Index: /branches/new-random/library/jp-encode.lisp
===================================================================
--- /branches/new-random/library/jp-encode.lisp	(revision 13309)
+++ /branches/new-random/library/jp-encode.lisp	(revision 13309)
@@ -0,0 +1,17945 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;;; helper functions
+(defvar *eucjp-to-ucs-hash* (make-hash-table))
+(defvar *ucs-to-eucjp-hash* (make-hash-table))
+(defvar *cp932-to-ucs-hash* (make-hash-table))
+(defvar *ucs-to-cp932-hash* (make-hash-table))
+
+(let* ((cp932-only '((#xFC4B #x9ED1)
+                     (#xFC4A #x9E19)
+                     (#xFC49 #xFA2D)
+                     (#xFC48 #x9D6B)
+                     (#xFC47 #x9D70)
+                     (#xFC46 #x9C00)
+                     (#xFC45 #x9BBB)
+                     (#xFC44 #x9BB1)
+                     (#xFC43 #x9B8F)
+                     (#xFC42 #x9B72)
+                     (#xFC41 #x9B75)
+                     (#xFC40 #x9ADC)
+                     (#xFBFC #x9AD9)
+                     (#xFBFB #x9A4E)
+                     (#xFBFA #x999E)
+                     (#xFBF9 #xFA2C)
+                     (#xFBF8 #x9927)
+                     (#xFBF7 #xFA2B)
+                     (#xFBF6 #xFA2A)
+                     (#xFBF5 #x9865)
+                     (#xFBF4 #x9857)
+                     (#xFBF3 #x9755)
+                     (#xFBF2 #x9751)
+                     (#xFBF1 #x974F)
+                     (#xFBF0 #x974D)
+                     (#xFBEF #x9743)
+                     (#xFBEE #x973B)
+                     (#xFBED #x9733)
+                     (#xFBEC #x96AF)
+                     (#xFBEB #x969D)
+                     (#xFBEA #xFA29)
+                     (#xFBE9 #xF9DC)
+                     (#xFBE8 #x9592)
+                     (#xFBE7 #x9448)
+                     (#xFBE6 #x9445)
+                     (#xFBE5 #x9431)
+                     (#xFBE4 #x93F8)
+                     (#xFBE3 #x93DE)
+                     (#xFBE2 #x93C6)
+                     (#xFBE1 #x93A4)
+                     (#xFBE0 #x9357)
+                     (#xFBDF #x9370)
+                     (#xFBDE #x9302)
+                     (#xFBDD #x931D)
+                     (#xFBDC #x92FF)
+                     (#xFBDB #x931E)
+                     (#xFBDA #xFA28)
+                     (#xFBD9 #x92FB)
+                     (#xFBD8 #x9321)
+                     (#xFBD7 #x9325)
+                     (#xFBD6 #x92D3)
+                     (#xFBD5 #x92E0)
+                     (#xFBD4 #x92D5)
+                     (#xFBD3 #xFA27)
+                     (#xFBD2 #x92D0)
+                     (#xFBD1 #x92D9)
+                     (#xFBD0 #x92D7)
+                     (#xFBCF #x92E7)
+                     (#xFBCE #x9278)
+                     (#xFBCD #x9277)
+                     (#xFBCC #x92A7)
+                     (#xFBCB #x9267)
+                     (#xFBCA #x9239)
+                     (#xFBC9 #x9251)
+                     (#xFBC8 #x9259)
+                     (#xFBC7 #x924E)
+                     (#xFBC6 #x923C)
+                     (#xFBC5 #x9240)
+                     (#xFBC4 #x923A)
+                     (#xFBC3 #x920A)
+                     (#xFBC2 #x9210)
+                     (#xFBC1 #x9206)
+                     (#xFBC0 #x91E5)
+                     (#xFBBF #x91E4)
+                     (#xFBBE #x91EE)
+                     (#xFBBD #x91ED)
+                     (#xFBBC #x91DE)
+                     (#xFBBB #x91D7)
+                     (#xFBBA #x91DA)
+                     (#xFBB9 #x9127)
+                     (#xFBB8 #x9115)
+                     (#xFBB7 #xFA26)
+                     (#xFBB6 #x90DE)
+                     (#xFBB5 #x9067)
+                     (#xFBB4 #xFA25)
+                     (#xFBB3 #xFA24)
+                     (#xFBB2 #x8ECF)
+                     (#xFBB1 #xFA23)
+                     (#xFBB0 #x8D76)
+                     (#xFBAF #x8D12)
+                     (#xFBAE #x8CF4)
+                     (#xFBAD #x8CF0)
+                     (#xFBAC #x8B7F)
+                     (#xFBAB #x8B53)
+                     (#xFBAA #x8AF6)
+                     (#xFBA9 #xFA22)
+                     (#xFBA8 #x8ADF)
+                     (#xFBA7 #x8ABE)
+                     (#xFBA6 #x8AA7)
+                     (#xFBA5 #x8A79)
+                     (#xFBA4 #x8A37)
+                     (#xFBA3 #x8A12)
+                     (#xFBA2 #x88F5)
+                     (#xFBA1 #x8807)
+                     (#xFBA0 #xFA21)
+                     (#xFB9F #xFA20)
+                     (#xFB9E #x85B0)
+                     (#xFB9D #xFA1F)
+                     (#xFB9C #x856B)
+                     (#xFB9B #x8559)
+                     (#xFB9A #x8553)
+                     (#xFB99 #x84B4)
+                     (#xFB98 #x8448)
+                     (#xFB97 #x83F6)
+                     (#xFB96 #x83C7)
+                     (#xFB95 #x837F)
+                     (#xFB94 #x8362)
+                     (#xFB93 #x8301)
+                     (#xFB92 #xFA1E)
+                     (#xFB91 #x7FA1)
+                     (#xFB90 #x7F47)
+                     (#xFB8F #x7E52)
+                     (#xFB8E #x7DD6)
+                     (#xFB8D #x7DA0)
+                     (#xFB8C #x7DB7)
+                     (#xFB8B #x7D5C)
+                     (#xFB8A #x7D48)
+                     (#xFB89 #xFA1D)
+                     (#xFB88 #x7B9E)
+                     (#xFB87 #x7AEB)
+                     (#xFB86 #xFA1C)
+                     (#xFB85 #x7AE7)
+                     (#xFB84 #x7AD1)
+                     (#xFB83 #x799B)
+                     (#xFB82 #xFA1B)
+                     (#xFB81 #x7994)
+                     (#xFB80 #xFA1A)
+                     (#xFB7E #xFA19)
+                     (#xFB7D #xFA18)
+                     (#xFB7C #x7930)
+                     (#xFB7B #x787A)
+                     (#xFB7A #x7864)
+                     (#xFB79 #x784E)
+                     (#xFB78 #x7821)
+                     (#xFB77 #x52AF)
+                     (#xFB76 #x7746)
+                     (#xFB75 #xFA17)
+                     (#xFB74 #x76A6)
+                     (#xFB73 #x769B)
+                     (#xFB72 #x769E)
+                     (#xFB71 #x769C)
+                     (#xFB70 #x7682)
+                     (#xFB6F #x756F)
+                     (#xFB6E #x7501)
+                     (#xFB6D #x749F)
+                     (#xFB6C #x7489)
+                     (#xFB6B #x7462)
+                     (#xFB6A #x742E)
+                     (#xFB69 #x7429)
+                     (#xFB68 #x742A)
+                     (#xFB67 #x7426)
+                     (#xFB66 #x73F5)
+                     (#xFB65 #x7407)
+                     (#xFB64 #x73D2)
+                     (#xFB63 #x73E3)
+                     (#xFB62 #x73D6)
+                     (#xFB61 #x73C9)
+                     (#xFB60 #x73BD)
+                     (#xFB5F #x7377)
+                     (#xFB5E #xFA16)
+                     (#xFB5D #x7324)
+                     (#xFB5C #x72BE)
+                     (#xFB5B #x72B1)
+                     (#xFB5A #x71FE)
+                     (#xFB59 #x71C1)
+                     (#xFB58 #xFA15)
+                     (#xFB57 #x7147)
+                     (#xFB56 #x7146)
+                     (#xFB55 #x715C)
+                     (#xFB54 #x7104)
+                     (#xFB53 #x710F)
+                     (#xFB52 #x70AB)
+                     (#xFB51 #x7085)
+                     (#xFB50 #x7028)
+                     (#xFB4F #x7007)
+                     (#xFB4E #x7005)
+                     (#xFB4D #x6FF5)
+                     (#xFB4C #x6FB5)
+                     (#xFB4B #x6F88)
+                     (#xFB4A #x6EBF)
+                     (#xFB49 #x6E3C)
+                     (#xFB48 #x6E27)
+                     (#xFB47 #x6E5C)
+                     (#xFB46 #x6E39)
+                     (#xFB45 #x6DFC)
+                     (#xFB44 #x6DF2)
+                     (#xFB43 #x6DF8)
+                     (#xFB42 #x6DCF)
+                     (#xFB41 #x6DAC)
+                     (#xFB40 #x6D96)
+                     (#xFAFC #x6D6F)
+                     (#xFAFB #x6D87)
+                     (#xFAFA #x6D04)
+                     (#xFAF9 #x6CDA)
+                     (#xFAF8 #x6C6F)
+                     (#xFAF7 #x6C86)
+                     (#xFAF6 #x6C5C)
+                     (#xFAF5 #x6C3F)
+                     (#xFAF4 #x6BD6)
+                     (#xFAF3 #x6AE4)
+                     (#xFAF2 #x6AE2)
+                     (#xFAF1 #x6A7E)
+                     (#xFAF0 #x6A73)
+                     (#xFAEF #x6A46)
+                     (#xFAEE #x6A6B)
+                     (#xFAED #x6A30)
+                     (#xFAEC #x69E2)
+                     (#xFAEB #x6998)
+                     (#xFAEA #xFA14)
+                     (#xFAE9 #x6968)
+                     (#xFAE8 #xFA13)
+                     (#xFAE7 #x68CF)
+                     (#xFAE6 #x6844)
+                     (#xFAE5 #x6801)
+                     (#xFAE4 #x67C0)
+                     (#xFAE3 #x6852)
+                     (#xFAE2 #x67BB)
+                     (#xFAE1 #x6766)
+                     (#xFAE0 #xF929)
+                     (#xFADF #x670E)
+                     (#xFADE #x66FA)
+                     (#xFADD #x66BF)
+                     (#xFADC #x66B2)
+                     (#xFADB #x66A0)
+                     (#xFADA #x6699)
+                     (#xFAD9 #x6673)
+                     (#xFAD8 #xFA12)
+                     (#xFAD7 #x6659)
+                     (#xFAD6 #x6657)
+                     (#xFAD5 #x6665)
+                     (#xFAD4 #x6624)
+                     (#xFAD3 #x661E)
+                     (#xFAD2 #x662E)
+                     (#xFAD1 #x6609)
+                     (#xFAD0 #x663B)
+                     (#xFACF #x6615)
+                     (#xFACE #x6600)
+                     (#xFACD #x654E)
+                     (#xFACC #x64CE)
+                     (#xFACB #x649D)
+                     (#xFACA #x6460)
+                     (#xFAC9 #x63F5)
+                     (#xFAC8 #x62A6)
+                     (#xFAC7 #x6213)
+                     (#xFAC6 #x6198)
+                     (#xFAC5 #x6130)
+                     (#xFAC4 #x6137)
+                     (#xFAC3 #x6111)
+                     (#xFAC2 #x60F2)
+                     (#xFAC1 #x6120)
+                     (#xFAC0 #x60D5)
+                     (#xFABF #x60DE)
+                     (#xFABE #x608A)
+                     (#xFABD #x6085)
+                     (#xFABC #x605D)
+                     (#xFABB #x5FDE)
+                     (#xFABA #x5FB7)
+                     (#xFAB9 #x5F67)
+                     (#xFAB8 #x5F34)
+                     (#xFAB7 #x5F21)
+                     (#xFAB6 #x5DD0)
+                     (#xFAB5 #x5DB9)
+                     (#xFAB4 #x5DB8)
+                     (#xFAB3 #x5D6D)
+                     (#xFAB2 #x5D42)
+                     (#xFAB1 #xFA11)
+                     (#xFAB0 #x5D53)
+                     (#xFAAF #x5D27)
+                     (#xFAAE #x5CF5)
+                     (#xFAAD #x5CBA)
+                     (#xFAAC #x5CA6)
+                     (#xFAAB #x5C1E)
+                     (#xFAAA #x5BEC)
+                     (#xFAA9 #x5BD8)
+                     (#xFAA8 #x752F)
+                     (#xFAA7 #x5BC0)
+                     (#xFAA6 #x5B56)
+                     (#xFAA5 #x59BA)
+                     (#xFAA4 #x59A4)
+                     (#xFAA3 #x5963)
+                     (#xFAA2 #x595D)
+                     (#xFAA1 #x595B)
+                     (#xFAA0 #x5953)
+                     (#xFA9F #x590B)
+                     (#xFA9E #x58B2)
+                     (#xFA9D #x589E)
+                     (#xFA9C #xFA10)
+                     (#xFA9B #xFA0F)
+                     (#xFA9A #x57C7)
+                     (#xFA99 #x57C8)
+                     (#xFA98 #x57AC)
+                     (#xFA97 #x5765)
+                     (#xFA96 #x5759)
+                     (#xFA95 #x5586)
+                     (#xFA94 #x54FF)
+                     (#xFA93 #x54A9)
+                     (#xFA92 #x548A)
+                     (#xFA91 #x549C)
+                     (#xFA90 #xFA0E)
+                     (#xFA8F #x53DD)
+                     (#xFA8E #x53B2)
+                     (#xFA8D #x5393)
+                     (#xFA8C #x5372)
+                     (#xFA8B #x5324)
+                     (#xFA8A #x5307)
+                     (#xFA89 #x5300)
+                     (#xFA88 #x52DB)
+                     (#xFA87 #x52C0)
+                     (#xFA86 #x52A6)
+                     (#xFA85 #x529C)
+                     (#xFA84 #x5215)
+                     (#xFA83 #x51EC)
+                     (#xFA82 #x51BE)
+                     (#xFA81 #x519D)
+                     (#xFA80 #x5164)
+                     (#xFA7E #x514A)
+                     (#xFA7D #x50D8)
+                     (#xFA7C #x50F4)
+                     (#xFA7B #x5094)
+                     (#xFA7A #x5042)
+                     (#xFA79 #x5070)
+                     (#xFA78 #x5046)
+                     (#xFA77 #x501E)
+                     (#xFA76 #x4FFF)
+                     (#xFA75 #x5022)
+                     (#xFA74 #x5040)
+                     (#xFA73 #x4FCD)
+                     (#xFA72 #x4F94)
+                     (#xFA71 #x4F9A)
+                     (#xFA70 #x4F8A)
+                     (#xFA6F #x4F92)
+                     (#xFA6E #x4F56)
+                     (#xFA6D #x4F39)
+                     (#xFA6C #x4F03)
+                     (#xFA6B #x4F00)
+                     (#xFA6A #x4EFC)
+                     (#xFA69 #x4EE1)
+                     (#xFA68 #x4E28)
+                     (#xFA67 #x5F45)
+                     (#xFA66 #x66FB)
+                     (#xFA65 #x92F9)
+                     (#xFA64 #x68C8)
+                     (#xFA63 #x6631)
+                     (#xFA62 #x70BB)
+                     (#xFA61 #x4FC9)
+                     (#xFA60 #x84DC)
+                     (#xFA5F #x9288)
+                     (#xFA5E #x9348)
+                     (#xFA5D #x891C)
+                     (#xFA5C #x7E8A)
+                     (#xFA5B #x2235)
+                     (#xFA5A #x2121)
+                     (#xFA59 #x2116)
+                     (#xFA58 #x3231)
+                     (#xFA57 #xFF02)
+                     (#xFA56 #xFF07)
+                     (#xFA55 #xFFE4)
+                     (#xFA54 #xFFE2)
+                     (#xFA53 #x2169)
+                     (#xFA52 #x2168)
+                     (#xFA51 #x2167)
+                     (#xFA50 #x2166)
+                     (#xFA4F #x2165)
+                     (#xFA4E #x2164)
+                     (#xFA4D #x2163)
+                     (#xFA4C #x2162)
+                     (#xFA4B #x2161)
+                     (#xFA4A #x2160)
+                     (#xFA49 #x2179)
+                     (#xFA48 #x2178)
+                     (#xFA47 #x2177)
+                     (#xFA46 #x2176)
+                     (#xFA45 #x2175)
+                     (#xFA44 #x2174)
+                     (#xFA43 #x2173)
+                     (#xFA42 #x2172)
+                     (#xFA41 #x2171)
+                     (#xFA40 #x2170)
+                     (#xF9FC #xE757)
+                     (#xF9FB #xE756)
+                     (#xF9FA #xE755)
+                     (#xF9F9 #xE754)
+                     (#xF9F8 #xE753)
+                     (#xF9F7 #xE752)
+                     (#xF9F6 #xE751)
+                     (#xF9F5 #xE750)
+                     (#xF9F4 #xE74F)
+                     (#xF9F3 #xE74E)
+                     (#xF9F2 #xE74D)
+                     (#xF9F1 #xE74C)
+                     (#xF9F0 #xE74B)
+                     (#xF9EF #xE74A)
+                     (#xF9EE #xE749)
+                     (#xF9ED #xE748)
+                     (#xF9EC #xE747)
+                     (#xF9EB #xE746)
+                     (#xF9EA #xE745)
+                     (#xF9E9 #xE744)
+                     (#xF9E8 #xE743)
+                     (#xF9E7 #xE742)
+                     (#xF9E6 #xE741)
+                     (#xF9E5 #xE740)
+                     (#xF9E4 #xE73F)
+                     (#xF9E3 #xE73E)
+                     (#xF9E2 #xE73D)
+                     (#xF9E1 #xE73C)
+                     (#xF9E0 #xE73B)
+                     (#xF9DF #xE73A)
+                     (#xF9DE #xE739)
+                     (#xF9DD #xE738)
+                     (#xF9DC #xE737)
+                     (#xF9DB #xE736)
+                     (#xF9DA #xE735)
+                     (#xF9D9 #xE734)
+                     (#xF9D8 #xE733)
+                     (#xF9D7 #xE732)
+                     (#xF9D6 #xE731)
+                     (#xF9D5 #xE730)
+                     (#xF9D4 #xE72F)
+                     (#xF9D3 #xE72E)
+                     (#xF9D2 #xE72D)
+                     (#xF9D1 #xE72C)
+                     (#xF9D0 #xE72B)
+                     (#xF9CF #xE72A)
+                     (#xF9CE #xE729)
+                     (#xF9CD #xE728)
+                     (#xF9CC #xE727)
+                     (#xF9CB #xE726)
+                     (#xF9CA #xE725)
+                     (#xF9C9 #xE724)
+                     (#xF9C8 #xE723)
+                     (#xF9C7 #xE722)
+                     (#xF9C6 #xE721)
+                     (#xF9C5 #xE720)
+                     (#xF9C4 #xE71F)
+                     (#xF9C3 #xE71E)
+                     (#xF9C2 #xE71D)
+                     (#xF9C1 #xE71C)
+                     (#xF9C0 #xE71B)
+                     (#xF9BF #xE71A)
+                     (#xF9BE #xE719)
+                     (#xF9BD #xE718)
+                     (#xF9BC #xE717)
+                     (#xF9BB #xE716)
+                     (#xF9BA #xE715)
+                     (#xF9B9 #xE714)
+                     (#xF9B8 #xE713)
+                     (#xF9B7 #xE712)
+                     (#xF9B6 #xE711)
+                     (#xF9B5 #xE710)
+                     (#xF9B4 #xE70F)
+                     (#xF9B3 #xE70E)
+                     (#xF9B2 #xE70D)
+                     (#xF9B1 #xE70C)
+                     (#xF9B0 #xE70B)
+                     (#xF9AF #xE70A)
+                     (#xF9AE #xE709)
+                     (#xF9AD #xE708)
+                     (#xF9AC #xE707)
+                     (#xF9AB #xE706)
+                     (#xF9AA #xE705)
+                     (#xF9A9 #xE704)
+                     (#xF9A8 #xE703)
+                     (#xF9A7 #xE702)
+                     (#xF9A6 #xE701)
+                     (#xF9A5 #xE700)
+                     (#xF9A4 #xE6FF)
+                     (#xF9A3 #xE6FE)
+                     (#xF9A2 #xE6FD)
+                     (#xF9A1 #xE6FC)
+                     (#xF9A0 #xE6FB)
+                     (#xF99F #xE6FA)
+                     (#xF99E #xE6F9)
+                     (#xF99D #xE6F8)
+                     (#xF99C #xE6F7)
+                     (#xF99B #xE6F6)
+                     (#xF99A #xE6F5)
+                     (#xF999 #xE6F4)
+                     (#xF998 #xE6F3)
+                     (#xF997 #xE6F2)
+                     (#xF996 #xE6F1)
+                     (#xF995 #xE6F0)
+                     (#xF994 #xE6EF)
+                     (#xF993 #xE6EE)
+                     (#xF992 #xE6ED)
+                     (#xF991 #xE6EC)
+                     (#xF990 #xE6EB)
+                     (#xF98F #xE6EA)
+                     (#xF98E #xE6E9)
+                     (#xF98D #xE6E8)
+                     (#xF98C #xE6E7)
+                     (#xF98B #xE6E6)
+                     (#xF98A #xE6E5)
+                     (#xF989 #xE6E4)
+                     (#xF988 #xE6E3)
+                     (#xF987 #xE6E2)
+                     (#xF986 #xE6E1)
+                     (#xF985 #xE6E0)
+                     (#xF984 #xE6DF)
+                     (#xF983 #xE6DE)
+                     (#xF982 #xE6DD)
+                     (#xF981 #xE6DC)
+                     (#xF980 #xE6DB)
+                     (#xF97E #xE6DA)
+                     (#xF97D #xE6D9)
+                     (#xF97C #xE6D8)
+                     (#xF97B #xE6D7)
+                     (#xF97A #xE6D6)
+                     (#xF979 #xE6D5)
+                     (#xF978 #xE6D4)
+                     (#xF977 #xE6D3)
+                     (#xF976 #xE6D2)
+                     (#xF975 #xE6D1)
+                     (#xF974 #xE6D0)
+                     (#xF973 #xE6CF)
+                     (#xF972 #xE6CE)
+                     (#xF971 #xE6CD)
+                     (#xF970 #xE6CC)
+                     (#xF96F #xE6CB)
+                     (#xF96E #xE6CA)
+                     (#xF96D #xE6C9)
+                     (#xF96C #xE6C8)
+                     (#xF96B #xE6C7)
+                     (#xF96A #xE6C6)
+                     (#xF969 #xE6C5)
+                     (#xF968 #xE6C4)
+                     (#xF967 #xE6C3)
+                     (#xF966 #xE6C2)
+                     (#xF965 #xE6C1)
+                     (#xF964 #xE6C0)
+                     (#xF963 #xE6BF)
+                     (#xF962 #xE6BE)
+                     (#xF961 #xE6BD)
+                     (#xF960 #xE6BC)
+                     (#xF95F #xE6BB)
+                     (#xF95E #xE6BA)
+                     (#xF95D #xE6B9)
+                     (#xF95C #xE6B8)
+                     (#xF95B #xE6B7)
+                     (#xF95A #xE6B6)
+                     (#xF959 #xE6B5)
+                     (#xF958 #xE6B4)
+                     (#xF957 #xE6B3)
+                     (#xF956 #xE6B2)
+                     (#xF955 #xE6B1)
+                     (#xF954 #xE6B0)
+                     (#xF953 #xE6AF)
+                     (#xF952 #xE6AE)
+                     (#xF951 #xE6AD)
+                     (#xF950 #xE6AC)
+                     (#xF94F #xE6AB)
+                     (#xF94E #xE6AA)
+                     (#xF94D #xE6A9)
+                     (#xF94C #xE6A8)
+                     (#xF94B #xE6A7)
+                     (#xF94A #xE6A6)
+                     (#xF949 #xE6A5)
+                     (#xF948 #xE6A4)
+                     (#xF947 #xE6A3)
+                     (#xF946 #xE6A2)
+                     (#xF945 #xE6A1)
+                     (#xF944 #xE6A0)
+                     (#xF943 #xE69F)
+                     (#xF942 #xE69E)
+                     (#xF941 #xE69D)
+                     (#xF940 #xE69C)
+                     (#xF8FC #xE69B)
+                     (#xF8FB #xE69A)
+                     (#xF8FA #xE699)
+                     (#xF8F9 #xE698)
+                     (#xF8F8 #xE697)
+                     (#xF8F7 #xE696)
+                     (#xF8F6 #xE695)
+                     (#xF8F5 #xE694)
+                     (#xF8F4 #xE693)
+                     (#xF8F3 #xE692)
+                     (#xF8F2 #xE691)
+                     (#xF8F1 #xE690)
+                     (#xF8F0 #xE68F)
+                     (#xF8EF #xE68E)
+                     (#xF8EE #xE68D)
+                     (#xF8ED #xE68C)
+                     (#xF8EC #xE68B)
+                     (#xF8EB #xE68A)
+                     (#xF8EA #xE689)
+                     (#xF8E9 #xE688)
+                     (#xF8E8 #xE687)
+                     (#xF8E7 #xE686)
+                     (#xF8E6 #xE685)
+                     (#xF8E5 #xE684)
+                     (#xF8E4 #xE683)
+                     (#xF8E3 #xE682)
+                     (#xF8E2 #xE681)
+                     (#xF8E1 #xE680)
+                     (#xF8E0 #xE67F)
+                     (#xF8DF #xE67E)
+                     (#xF8DE #xE67D)
+                     (#xF8DD #xE67C)
+                     (#xF8DC #xE67B)
+                     (#xF8DB #xE67A)
+                     (#xF8DA #xE679)
+                     (#xF8D9 #xE678)
+                     (#xF8D8 #xE677)
+                     (#xF8D7 #xE676)
+                     (#xF8D6 #xE675)
+                     (#xF8D5 #xE674)
+                     (#xF8D4 #xE673)
+                     (#xF8D3 #xE672)
+                     (#xF8D2 #xE671)
+                     (#xF8D1 #xE670)
+                     (#xF8D0 #xE66F)
+                     (#xF8CF #xE66E)
+                     (#xF8CE #xE66D)
+                     (#xF8CD #xE66C)
+                     (#xF8CC #xE66B)
+                     (#xF8CB #xE66A)
+                     (#xF8CA #xE669)
+                     (#xF8C9 #xE668)
+                     (#xF8C8 #xE667)
+                     (#xF8C7 #xE666)
+                     (#xF8C6 #xE665)
+                     (#xF8C5 #xE664)
+                     (#xF8C4 #xE663)
+                     (#xF8C3 #xE662)
+                     (#xF8C2 #xE661)
+                     (#xF8C1 #xE660)
+                     (#xF8C0 #xE65F)
+                     (#xF8BF #xE65E)
+                     (#xF8BE #xE65D)
+                     (#xF8BD #xE65C)
+                     (#xF8BC #xE65B)
+                     (#xF8BB #xE65A)
+                     (#xF8BA #xE659)
+                     (#xF8B9 #xE658)
+                     (#xF8B8 #xE657)
+                     (#xF8B7 #xE656)
+                     (#xF8B6 #xE655)
+                     (#xF8B5 #xE654)
+                     (#xF8B4 #xE653)
+                     (#xF8B3 #xE652)
+                     (#xF8B2 #xE651)
+                     (#xF8B1 #xE650)
+                     (#xF8B0 #xE64F)
+                     (#xF8AF #xE64E)
+                     (#xF8AE #xE64D)
+                     (#xF8AD #xE64C)
+                     (#xF8AC #xE64B)
+                     (#xF8AB #xE64A)
+                     (#xF8AA #xE649)
+                     (#xF8A9 #xE648)
+                     (#xF8A8 #xE647)
+                     (#xF8A7 #xE646)
+                     (#xF8A6 #xE645)
+                     (#xF8A5 #xE644)
+                     (#xF8A4 #xE643)
+                     (#xF8A3 #xE642)
+                     (#xF8A2 #xE641)
+                     (#xF8A1 #xE640)
+                     (#xF8A0 #xE63F)
+                     (#xF89F #xE63E)
+                     (#xF89E #xE63D)
+                     (#xF89D #xE63C)
+                     (#xF89C #xE63B)
+                     (#xF89B #xE63A)
+                     (#xF89A #xE639)
+                     (#xF899 #xE638)
+                     (#xF898 #xE637)
+                     (#xF897 #xE636)
+                     (#xF896 #xE635)
+                     (#xF895 #xE634)
+                     (#xF894 #xE633)
+                     (#xF893 #xE632)
+                     (#xF892 #xE631)
+                     (#xF891 #xE630)
+                     (#xF890 #xE62F)
+                     (#xF88F #xE62E)
+                     (#xF88E #xE62D)
+                     (#xF88D #xE62C)
+                     (#xF88C #xE62B)
+                     (#xF88B #xE62A)
+                     (#xF88A #xE629)
+                     (#xF889 #xE628)
+                     (#xF888 #xE627)
+                     (#xF887 #xE626)
+                     (#xF886 #xE625)
+                     (#xF885 #xE624)
+                     (#xF884 #xE623)
+                     (#xF883 #xE622)
+                     (#xF882 #xE621)
+                     (#xF881 #xE620)
+                     (#xF880 #xE61F)
+                     (#xF87E #xE61E)
+                     (#xF87D #xE61D)
+                     (#xF87C #xE61C)
+                     (#xF87B #xE61B)
+                     (#xF87A #xE61A)
+                     (#xF879 #xE619)
+                     (#xF878 #xE618)
+                     (#xF877 #xE617)
+                     (#xF876 #xE616)
+                     (#xF875 #xE615)
+                     (#xF874 #xE614)
+                     (#xF873 #xE613)
+                     (#xF872 #xE612)
+                     (#xF871 #xE611)
+                     (#xF870 #xE610)
+                     (#xF86F #xE60F)
+                     (#xF86E #xE60E)
+                     (#xF86D #xE60D)
+                     (#xF86C #xE60C)
+                     (#xF86B #xE60B)
+                     (#xF86A #xE60A)
+                     (#xF869 #xE609)
+                     (#xF868 #xE608)
+                     (#xF867 #xE607)
+                     (#xF866 #xE606)
+                     (#xF865 #xE605)
+                     (#xF864 #xE604)
+                     (#xF863 #xE603)
+                     (#xF862 #xE602)
+                     (#xF861 #xE601)
+                     (#xF860 #xE600)
+                     (#xF85F #xE5FF)
+                     (#xF85E #xE5FE)
+                     (#xF85D #xE5FD)
+                     (#xF85C #xE5FC)
+                     (#xF85B #xE5FB)
+                     (#xF85A #xE5FA)
+                     (#xF859 #xE5F9)
+                     (#xF858 #xE5F8)
+                     (#xF857 #xE5F7)
+                     (#xF856 #xE5F6)
+                     (#xF855 #xE5F5)
+                     (#xF854 #xE5F4)
+                     (#xF853 #xE5F3)
+                     (#xF852 #xE5F2)
+                     (#xF851 #xE5F1)
+                     (#xF850 #xE5F0)
+                     (#xF84F #xE5EF)
+                     (#xF84E #xE5EE)
+                     (#xF84D #xE5ED)
+                     (#xF84C #xE5EC)
+                     (#xF84B #xE5EB)
+                     (#xF84A #xE5EA)
+                     (#xF849 #xE5E9)
+                     (#xF848 #xE5E8)
+                     (#xF847 #xE5E7)
+                     (#xF846 #xE5E6)
+                     (#xF845 #xE5E5)
+                     (#xF844 #xE5E4)
+                     (#xF843 #xE5E3)
+                     (#xF842 #xE5E2)
+                     (#xF841 #xE5E1)
+                     (#xF840 #xE5E0)
+                     (#xF7FC #xE5DF)
+                     (#xF7FB #xE5DE)
+                     (#xF7FA #xE5DD)
+                     (#xF7F9 #xE5DC)
+                     (#xF7F8 #xE5DB)
+                     (#xF7F7 #xE5DA)
+                     (#xF7F6 #xE5D9)
+                     (#xF7F5 #xE5D8)
+                     (#xF7F4 #xE5D7)
+                     (#xF7F3 #xE5D6)
+                     (#xF7F2 #xE5D5)
+                     (#xF7F1 #xE5D4)
+                     (#xF7F0 #xE5D3)
+                     (#xF7EF #xE5D2)
+                     (#xF7EE #xE5D1)
+                     (#xF7ED #xE5D0)
+                     (#xF7EC #xE5CF)
+                     (#xF7EB #xE5CE)
+                     (#xF7EA #xE5CD)
+                     (#xF7E9 #xE5CC)
+                     (#xF7E8 #xE5CB)
+                     (#xF7E7 #xE5CA)
+                     (#xF7E6 #xE5C9)
+                     (#xF7E5 #xE5C8)
+                     (#xF7E4 #xE5C7)
+                     (#xF7E3 #xE5C6)
+                     (#xF7E2 #xE5C5)
+                     (#xF7E1 #xE5C4)
+                     (#xF7E0 #xE5C3)
+                     (#xF7DF #xE5C2)
+                     (#xF7DE #xE5C1)
+                     (#xF7DD #xE5C0)
+                     (#xF7DC #xE5BF)
+                     (#xF7DB #xE5BE)
+                     (#xF7DA #xE5BD)
+                     (#xF7D9 #xE5BC)
+                     (#xF7D8 #xE5BB)
+                     (#xF7D7 #xE5BA)
+                     (#xF7D6 #xE5B9)
+                     (#xF7D5 #xE5B8)
+                     (#xF7D4 #xE5B7)
+                     (#xF7D3 #xE5B6)
+                     (#xF7D2 #xE5B5)
+                     (#xF7D1 #xE5B4)
+                     (#xF7D0 #xE5B3)
+                     (#xF7CF #xE5B2)
+                     (#xF7CE #xE5B1)
+                     (#xF7CD #xE5B0)
+                     (#xF7CC #xE5AF)
+                     (#xF7CB #xE5AE)
+                     (#xF7CA #xE5AD)
+                     (#xF7C9 #xE5AC)
+                     (#xF7C8 #xE5AB)
+                     (#xF7C7 #xE5AA)
+                     (#xF7C6 #xE5A9)
+                     (#xF7C5 #xE5A8)
+                     (#xF7C4 #xE5A7)
+                     (#xF7C3 #xE5A6)
+                     (#xF7C2 #xE5A5)
+                     (#xF7C1 #xE5A4)
+                     (#xF7C0 #xE5A3)
+                     (#xF7BF #xE5A2)
+                     (#xF7BE #xE5A1)
+                     (#xF7BD #xE5A0)
+                     (#xF7BC #xE59F)
+                     (#xF7BB #xE59E)
+                     (#xF7BA #xE59D)
+                     (#xF7B9 #xE59C)
+                     (#xF7B8 #xE59B)
+                     (#xF7B7 #xE59A)
+                     (#xF7B6 #xE599)
+                     (#xF7B5 #xE598)
+                     (#xF7B4 #xE597)
+                     (#xF7B3 #xE596)
+                     (#xF7B2 #xE595)
+                     (#xF7B1 #xE594)
+                     (#xF7B0 #xE593)
+                     (#xF7AF #xE592)
+                     (#xF7AE #xE591)
+                     (#xF7AD #xE590)
+                     (#xF7AC #xE58F)
+                     (#xF7AB #xE58E)
+                     (#xF7AA #xE58D)
+                     (#xF7A9 #xE58C)
+                     (#xF7A8 #xE58B)
+                     (#xF7A7 #xE58A)
+                     (#xF7A6 #xE589)
+                     (#xF7A5 #xE588)
+                     (#xF7A4 #xE587)
+                     (#xF7A3 #xE586)
+                     (#xF7A2 #xE585)
+                     (#xF7A1 #xE584)
+                     (#xF7A0 #xE583)
+                     (#xF79F #xE582)
+                     (#xF79E #xE581)
+                     (#xF79D #xE580)
+                     (#xF79C #xE57F)
+                     (#xF79B #xE57E)
+                     (#xF79A #xE57D)
+                     (#xF799 #xE57C)
+                     (#xF798 #xE57B)
+                     (#xF797 #xE57A)
+                     (#xF796 #xE579)
+                     (#xF795 #xE578)
+                     (#xF794 #xE577)
+                     (#xF793 #xE576)
+                     (#xF792 #xE575)
+                     (#xF791 #xE574)
+                     (#xF790 #xE573)
+                     (#xF78F #xE572)
+                     (#xF78E #xE571)
+                     (#xF78D #xE570)
+                     (#xF78C #xE56F)
+                     (#xF78B #xE56E)
+                     (#xF78A #xE56D)
+                     (#xF789 #xE56C)
+                     (#xF788 #xE56B)
+                     (#xF787 #xE56A)
+                     (#xF786 #xE569)
+                     (#xF785 #xE568)
+                     (#xF784 #xE567)
+                     (#xF783 #xE566)
+                     (#xF782 #xE565)
+                     (#xF781 #xE564)
+                     (#xF780 #xE563)
+                     (#xF77E #xE562)
+                     (#xF77D #xE561)
+                     (#xF77C #xE560)
+                     (#xF77B #xE55F)
+                     (#xF77A #xE55E)
+                     (#xF779 #xE55D)
+                     (#xF778 #xE55C)
+                     (#xF777 #xE55B)
+                     (#xF776 #xE55A)
+                     (#xF775 #xE559)
+                     (#xF774 #xE558)
+                     (#xF773 #xE557)
+                     (#xF772 #xE556)
+                     (#xF771 #xE555)
+                     (#xF770 #xE554)
+                     (#xF76F #xE553)
+                     (#xF76E #xE552)
+                     (#xF76D #xE551)
+                     (#xF76C #xE550)
+                     (#xF76B #xE54F)
+                     (#xF76A #xE54E)
+                     (#xF769 #xE54D)
+                     (#xF768 #xE54C)
+                     (#xF767 #xE54B)
+                     (#xF766 #xE54A)
+                     (#xF765 #xE549)
+                     (#xF764 #xE548)
+                     (#xF763 #xE547)
+                     (#xF762 #xE546)
+                     (#xF761 #xE545)
+                     (#xF760 #xE544)
+                     (#xF75F #xE543)
+                     (#xF75E #xE542)
+                     (#xF75D #xE541)
+                     (#xF75C #xE540)
+                     (#xF75B #xE53F)
+                     (#xF75A #xE53E)
+                     (#xF759 #xE53D)
+                     (#xF758 #xE53C)
+                     (#xF757 #xE53B)
+                     (#xF756 #xE53A)
+                     (#xF755 #xE539)
+                     (#xF754 #xE538)
+                     (#xF753 #xE537)
+                     (#xF752 #xE536)
+                     (#xF751 #xE535)
+                     (#xF750 #xE534)
+                     (#xF74F #xE533)
+                     (#xF74E #xE532)
+                     (#xF74D #xE531)
+                     (#xF74C #xE530)
+                     (#xF74B #xE52F)
+                     (#xF74A #xE52E)
+                     (#xF749 #xE52D)
+                     (#xF748 #xE52C)
+                     (#xF747 #xE52B)
+                     (#xF746 #xE52A)
+                     (#xF745 #xE529)
+                     (#xF744 #xE528)
+                     (#xF743 #xE527)
+                     (#xF742 #xE526)
+                     (#xF741 #xE525)
+                     (#xF740 #xE524)
+                     (#xF6FC #xE523)
+                     (#xF6FB #xE522)
+                     (#xF6FA #xE521)
+                     (#xF6F9 #xE520)
+                     (#xF6F8 #xE51F)
+                     (#xF6F7 #xE51E)
+                     (#xF6F6 #xE51D)
+                     (#xF6F5 #xE51C)
+                     (#xF6F4 #xE51B)
+                     (#xF6F3 #xE51A)
+                     (#xF6F2 #xE519)
+                     (#xF6F1 #xE518)
+                     (#xF6F0 #xE517)
+                     (#xF6EF #xE516)
+                     (#xF6EE #xE515)
+                     (#xF6ED #xE514)
+                     (#xF6EC #xE513)
+                     (#xF6EB #xE512)
+                     (#xF6EA #xE511)
+                     (#xF6E9 #xE510)
+                     (#xF6E8 #xE50F)
+                     (#xF6E7 #xE50E)
+                     (#xF6E6 #xE50D)
+                     (#xF6E5 #xE50C)
+                     (#xF6E4 #xE50B)
+                     (#xF6E3 #xE50A)
+                     (#xF6E2 #xE509)
+                     (#xF6E1 #xE508)
+                     (#xF6E0 #xE507)
+                     (#xF6DF #xE506)
+                     (#xF6DE #xE505)
+                     (#xF6DD #xE504)
+                     (#xF6DC #xE503)
+                     (#xF6DB #xE502)
+                     (#xF6DA #xE501)
+                     (#xF6D9 #xE500)
+                     (#xF6D8 #xE4FF)
+                     (#xF6D7 #xE4FE)
+                     (#xF6D6 #xE4FD)
+                     (#xF6D5 #xE4FC)
+                     (#xF6D4 #xE4FB)
+                     (#xF6D3 #xE4FA)
+                     (#xF6D2 #xE4F9)
+                     (#xF6D1 #xE4F8)
+                     (#xF6D0 #xE4F7)
+                     (#xF6CF #xE4F6)
+                     (#xF6CE #xE4F5)
+                     (#xF6CD #xE4F4)
+                     (#xF6CC #xE4F3)
+                     (#xF6CB #xE4F2)
+                     (#xF6CA #xE4F1)
+                     (#xF6C9 #xE4F0)
+                     (#xF6C8 #xE4EF)
+                     (#xF6C7 #xE4EE)
+                     (#xF6C6 #xE4ED)
+                     (#xF6C5 #xE4EC)
+                     (#xF6C4 #xE4EB)
+                     (#xF6C3 #xE4EA)
+                     (#xF6C2 #xE4E9)
+                     (#xF6C1 #xE4E8)
+                     (#xF6C0 #xE4E7)
+                     (#xF6BF #xE4E6)
+                     (#xF6BE #xE4E5)
+                     (#xF6BD #xE4E4)
+                     (#xF6BC #xE4E3)
+                     (#xF6BB #xE4E2)
+                     (#xF6BA #xE4E1)
+                     (#xF6B9 #xE4E0)
+                     (#xF6B8 #xE4DF)
+                     (#xF6B7 #xE4DE)
+                     (#xF6B6 #xE4DD)
+                     (#xF6B5 #xE4DC)
+                     (#xF6B4 #xE4DB)
+                     (#xF6B3 #xE4DA)
+                     (#xF6B2 #xE4D9)
+                     (#xF6B1 #xE4D8)
+                     (#xF6B0 #xE4D7)
+                     (#xF6AF #xE4D6)
+                     (#xF6AE #xE4D5)
+                     (#xF6AD #xE4D4)
+                     (#xF6AC #xE4D3)
+                     (#xF6AB #xE4D2)
+                     (#xF6AA #xE4D1)
+                     (#xF6A9 #xE4D0)
+                     (#xF6A8 #xE4CF)
+                     (#xF6A7 #xE4CE)
+                     (#xF6A6 #xE4CD)
+                     (#xF6A5 #xE4CC)
+                     (#xF6A4 #xE4CB)
+                     (#xF6A3 #xE4CA)
+                     (#xF6A2 #xE4C9)
+                     (#xF6A1 #xE4C8)
+                     (#xF6A0 #xE4C7)
+                     (#xF69F #xE4C6)
+                     (#xF69E #xE4C5)
+                     (#xF69D #xE4C4)
+                     (#xF69C #xE4C3)
+                     (#xF69B #xE4C2)
+                     (#xF69A #xE4C1)
+                     (#xF699 #xE4C0)
+                     (#xF698 #xE4BF)
+                     (#xF697 #xE4BE)
+                     (#xF696 #xE4BD)
+                     (#xF695 #xE4BC)
+                     (#xF694 #xE4BB)
+                     (#xF693 #xE4BA)
+                     (#xF692 #xE4B9)
+                     (#xF691 #xE4B8)
+                     (#xF690 #xE4B7)
+                     (#xF68F #xE4B6)
+                     (#xF68E #xE4B5)
+                     (#xF68D #xE4B4)
+                     (#xF68C #xE4B3)
+                     (#xF68B #xE4B2)
+                     (#xF68A #xE4B1)
+                     (#xF689 #xE4B0)
+                     (#xF688 #xE4AF)
+                     (#xF687 #xE4AE)
+                     (#xF686 #xE4AD)
+                     (#xF685 #xE4AC)
+                     (#xF684 #xE4AB)
+                     (#xF683 #xE4AA)
+                     (#xF682 #xE4A9)
+                     (#xF681 #xE4A8)
+                     (#xF680 #xE4A7)
+                     (#xF67E #xE4A6)
+                     (#xF67D #xE4A5)
+                     (#xF67C #xE4A4)
+                     (#xF67B #xE4A3)
+                     (#xF67A #xE4A2)
+                     (#xF679 #xE4A1)
+                     (#xF678 #xE4A0)
+                     (#xF677 #xE49F)
+                     (#xF676 #xE49E)
+                     (#xF675 #xE49D)
+                     (#xF674 #xE49C)
+                     (#xF673 #xE49B)
+                     (#xF672 #xE49A)
+                     (#xF671 #xE499)
+                     (#xF670 #xE498)
+                     (#xF66F #xE497)
+                     (#xF66E #xE496)
+                     (#xF66D #xE495)
+                     (#xF66C #xE494)
+                     (#xF66B #xE493)
+                     (#xF66A #xE492)
+                     (#xF669 #xE491)
+                     (#xF668 #xE490)
+                     (#xF667 #xE48F)
+                     (#xF666 #xE48E)
+                     (#xF665 #xE48D)
+                     (#xF664 #xE48C)
+                     (#xF663 #xE48B)
+                     (#xF662 #xE48A)
+                     (#xF661 #xE489)
+                     (#xF660 #xE488)
+                     (#xF65F #xE487)
+                     (#xF65E #xE486)
+                     (#xF65D #xE485)
+                     (#xF65C #xE484)
+                     (#xF65B #xE483)
+                     (#xF65A #xE482)
+                     (#xF659 #xE481)
+                     (#xF658 #xE480)
+                     (#xF657 #xE47F)
+                     (#xF656 #xE47E)
+                     (#xF655 #xE47D)
+                     (#xF654 #xE47C)
+                     (#xF653 #xE47B)
+                     (#xF652 #xE47A)
+                     (#xF651 #xE479)
+                     (#xF650 #xE478)
+                     (#xF64F #xE477)
+                     (#xF64E #xE476)
+                     (#xF64D #xE475)
+                     (#xF64C #xE474)
+                     (#xF64B #xE473)
+                     (#xF64A #xE472)
+                     (#xF649 #xE471)
+                     (#xF648 #xE470)
+                     (#xF647 #xE46F)
+                     (#xF646 #xE46E)
+                     (#xF645 #xE46D)
+                     (#xF644 #xE46C)
+                     (#xF643 #xE46B)
+                     (#xF642 #xE46A)
+                     (#xF641 #xE469)
+                     (#xF640 #xE468)
+                     (#xF5FC #xE467)
+                     (#xF5FB #xE466)
+                     (#xF5FA #xE465)
+                     (#xF5F9 #xE464)
+                     (#xF5F8 #xE463)
+                     (#xF5F7 #xE462)
+                     (#xF5F6 #xE461)
+                     (#xF5F5 #xE460)
+                     (#xF5F4 #xE45F)
+                     (#xF5F3 #xE45E)
+                     (#xF5F2 #xE45D)
+                     (#xF5F1 #xE45C)
+                     (#xF5F0 #xE45B)
+                     (#xF5EF #xE45A)
+                     (#xF5EE #xE459)
+                     (#xF5ED #xE458)
+                     (#xF5EC #xE457)
+                     (#xF5EB #xE456)
+                     (#xF5EA #xE455)
+                     (#xF5E9 #xE454)
+                     (#xF5E8 #xE453)
+                     (#xF5E7 #xE452)
+                     (#xF5E6 #xE451)
+                     (#xF5E5 #xE450)
+                     (#xF5E4 #xE44F)
+                     (#xF5E3 #xE44E)
+                     (#xF5E2 #xE44D)
+                     (#xF5E1 #xE44C)
+                     (#xF5E0 #xE44B)
+                     (#xF5DF #xE44A)
+                     (#xF5DE #xE449)
+                     (#xF5DD #xE448)
+                     (#xF5DC #xE447)
+                     (#xF5DB #xE446)
+                     (#xF5DA #xE445)
+                     (#xF5D9 #xE444)
+                     (#xF5D8 #xE443)
+                     (#xF5D7 #xE442)
+                     (#xF5D6 #xE441)
+                     (#xF5D5 #xE440)
+                     (#xF5D4 #xE43F)
+                     (#xF5D3 #xE43E)
+                     (#xF5D2 #xE43D)
+                     (#xF5D1 #xE43C)
+                     (#xF5D0 #xE43B)
+                     (#xF5CF #xE43A)
+                     (#xF5CE #xE439)
+                     (#xF5CD #xE438)
+                     (#xF5CC #xE437)
+                     (#xF5CB #xE436)
+                     (#xF5CA #xE435)
+                     (#xF5C9 #xE434)
+                     (#xF5C8 #xE433)
+                     (#xF5C7 #xE432)
+                     (#xF5C6 #xE431)
+                     (#xF5C5 #xE430)
+                     (#xF5C4 #xE42F)
+                     (#xF5C3 #xE42E)
+                     (#xF5C2 #xE42D)
+                     (#xF5C1 #xE42C)
+                     (#xF5C0 #xE42B)
+                     (#xF5BF #xE42A)
+                     (#xF5BE #xE429)
+                     (#xF5BD #xE428)
+                     (#xF5BC #xE427)
+                     (#xF5BB #xE426)
+                     (#xF5BA #xE425)
+                     (#xF5B9 #xE424)
+                     (#xF5B8 #xE423)
+                     (#xF5B7 #xE422)
+                     (#xF5B6 #xE421)
+                     (#xF5B5 #xE420)
+                     (#xF5B4 #xE41F)
+                     (#xF5B3 #xE41E)
+                     (#xF5B2 #xE41D)
+                     (#xF5B1 #xE41C)
+                     (#xF5B0 #xE41B)
+                     (#xF5AF #xE41A)
+                     (#xF5AE #xE419)
+                     (#xF5AD #xE418)
+                     (#xF5AC #xE417)
+                     (#xF5AB #xE416)
+                     (#xF5AA #xE415)
+                     (#xF5A9 #xE414)
+                     (#xF5A8 #xE413)
+                     (#xF5A7 #xE412)
+                     (#xF5A6 #xE411)
+                     (#xF5A5 #xE410)
+                     (#xF5A4 #xE40F)
+                     (#xF5A3 #xE40E)
+                     (#xF5A2 #xE40D)
+                     (#xF5A1 #xE40C)
+                     (#xF5A0 #xE40B)
+                     (#xF59F #xE40A)
+                     (#xF59E #xE409)
+                     (#xF59D #xE408)
+                     (#xF59C #xE407)
+                     (#xF59B #xE406)
+                     (#xF59A #xE405)
+                     (#xF599 #xE404)
+                     (#xF598 #xE403)
+                     (#xF597 #xE402)
+                     (#xF596 #xE401)
+                     (#xF595 #xE400)
+                     (#xF594 #xE3FF)
+                     (#xF593 #xE3FE)
+                     (#xF592 #xE3FD)
+                     (#xF591 #xE3FC)
+                     (#xF590 #xE3FB)
+                     (#xF58F #xE3FA)
+                     (#xF58E #xE3F9)
+                     (#xF58D #xE3F8)
+                     (#xF58C #xE3F7)
+                     (#xF58B #xE3F6)
+                     (#xF58A #xE3F5)
+                     (#xF589 #xE3F4)
+                     (#xF588 #xE3F3)
+                     (#xF587 #xE3F2)
+                     (#xF586 #xE3F1)
+                     (#xF585 #xE3F0)
+                     (#xF584 #xE3EF)
+                     (#xF583 #xE3EE)
+                     (#xF582 #xE3ED)
+                     (#xF581 #xE3EC)
+                     (#xF580 #xE3EB)
+                     (#xF57E #xE3EA)
+                     (#xF57D #xE3E9)
+                     (#xF57C #xE3E8)
+                     (#xF57B #xE3E7)
+                     (#xF57A #xE3E6)
+                     (#xF579 #xE3E5)
+                     (#xF578 #xE3E4)
+                     (#xF577 #xE3E3)
+                     (#xF576 #xE3E2)
+                     (#xF575 #xE3E1)
+                     (#xF574 #xE3E0)
+                     (#xF573 #xE3DF)
+                     (#xF572 #xE3DE)
+                     (#xF571 #xE3DD)
+                     (#xF570 #xE3DC)
+                     (#xF56F #xE3DB)
+                     (#xF56E #xE3DA)
+                     (#xF56D #xE3D9)
+                     (#xF56C #xE3D8)
+                     (#xF56B #xE3D7)
+                     (#xF56A #xE3D6)
+                     (#xF569 #xE3D5)
+                     (#xF568 #xE3D4)
+                     (#xF567 #xE3D3)
+                     (#xF566 #xE3D2)
+                     (#xF565 #xE3D1)
+                     (#xF564 #xE3D0)
+                     (#xF563 #xE3CF)
+                     (#xF562 #xE3CE)
+                     (#xF561 #xE3CD)
+                     (#xF560 #xE3CC)
+                     (#xF55F #xE3CB)
+                     (#xF55E #xE3CA)
+                     (#xF55D #xE3C9)
+                     (#xF55C #xE3C8)
+                     (#xF55B #xE3C7)
+                     (#xF55A #xE3C6)
+                     (#xF559 #xE3C5)
+                     (#xF558 #xE3C4)
+                     (#xF557 #xE3C3)
+                     (#xF556 #xE3C2)
+                     (#xF555 #xE3C1)
+                     (#xF554 #xE3C0)
+                     (#xF553 #xE3BF)
+                     (#xF552 #xE3BE)
+                     (#xF551 #xE3BD)
+                     (#xF550 #xE3BC)
+                     (#xF54F #xE3BB)
+                     (#xF54E #xE3BA)
+                     (#xF54D #xE3B9)
+                     (#xF54C #xE3B8)
+                     (#xF54B #xE3B7)
+                     (#xF54A #xE3B6)
+                     (#xF549 #xE3B5)
+                     (#xF548 #xE3B4)
+                     (#xF547 #xE3B3)
+                     (#xF546 #xE3B2)
+                     (#xF545 #xE3B1)
+                     (#xF544 #xE3B0)
+                     (#xF543 #xE3AF)
+                     (#xF542 #xE3AE)
+                     (#xF541 #xE3AD)
+                     (#xF540 #xE3AC)
+                     (#xF4FC #xE3AB)
+                     (#xF4FB #xE3AA)
+                     (#xF4FA #xE3A9)
+                     (#xF4F9 #xE3A8)
+                     (#xF4F8 #xE3A7)
+                     (#xF4F7 #xE3A6)
+                     (#xF4F6 #xE3A5)
+                     (#xF4F5 #xE3A4)
+                     (#xF4F4 #xE3A3)
+                     (#xF4F3 #xE3A2)
+                     (#xF4F2 #xE3A1)
+                     (#xF4F1 #xE3A0)
+                     (#xF4F0 #xE39F)
+                     (#xF4EF #xE39E)
+                     (#xF4EE #xE39D)
+                     (#xF4ED #xE39C)
+                     (#xF4EC #xE39B)
+                     (#xF4EB #xE39A)
+                     (#xF4EA #xE399)
+                     (#xF4E9 #xE398)
+                     (#xF4E8 #xE397)
+                     (#xF4E7 #xE396)
+                     (#xF4E6 #xE395)
+                     (#xF4E5 #xE394)
+                     (#xF4E4 #xE393)
+                     (#xF4E3 #xE392)
+                     (#xF4E2 #xE391)
+                     (#xF4E1 #xE390)
+                     (#xF4E0 #xE38F)
+                     (#xF4DF #xE38E)
+                     (#xF4DE #xE38D)
+                     (#xF4DD #xE38C)
+                     (#xF4DC #xE38B)
+                     (#xF4DB #xE38A)
+                     (#xF4DA #xE389)
+                     (#xF4D9 #xE388)
+                     (#xF4D8 #xE387)
+                     (#xF4D7 #xE386)
+                     (#xF4D6 #xE385)
+                     (#xF4D5 #xE384)
+                     (#xF4D4 #xE383)
+                     (#xF4D3 #xE382)
+                     (#xF4D2 #xE381)
+                     (#xF4D1 #xE380)
+                     (#xF4D0 #xE37F)
+                     (#xF4CF #xE37E)
+                     (#xF4CE #xE37D)
+                     (#xF4CD #xE37C)
+                     (#xF4CC #xE37B)
+                     (#xF4CB #xE37A)
+                     (#xF4CA #xE379)
+                     (#xF4C9 #xE378)
+                     (#xF4C8 #xE377)
+                     (#xF4C7 #xE376)
+                     (#xF4C6 #xE375)
+                     (#xF4C5 #xE374)
+                     (#xF4C4 #xE373)
+                     (#xF4C3 #xE372)
+                     (#xF4C2 #xE371)
+                     (#xF4C1 #xE370)
+                     (#xF4C0 #xE36F)
+                     (#xF4BF #xE36E)
+                     (#xF4BE #xE36D)
+                     (#xF4BD #xE36C)
+                     (#xF4BC #xE36B)
+                     (#xF4BB #xE36A)
+                     (#xF4BA #xE369)
+                     (#xF4B9 #xE368)
+                     (#xF4B8 #xE367)
+                     (#xF4B7 #xE366)
+                     (#xF4B6 #xE365)
+                     (#xF4B5 #xE364)
+                     (#xF4B4 #xE363)
+                     (#xF4B3 #xE362)
+                     (#xF4B2 #xE361)
+                     (#xF4B1 #xE360)
+                     (#xF4B0 #xE35F)
+                     (#xF4AF #xE35E)
+                     (#xF4AE #xE35D)
+                     (#xF4AD #xE35C)
+                     (#xF4AC #xE35B)
+                     (#xF4AB #xE35A)
+                     (#xF4AA #xE359)
+                     (#xF4A9 #xE358)
+                     (#xF4A8 #xE357)
+                     (#xF4A7 #xE356)
+                     (#xF4A6 #xE355)
+                     (#xF4A5 #xE354)
+                     (#xF4A4 #xE353)
+                     (#xF4A3 #xE352)
+                     (#xF4A2 #xE351)
+                     (#xF4A1 #xE350)
+                     (#xF4A0 #xE34F)
+                     (#xF49F #xE34E)
+                     (#xF49E #xE34D)
+                     (#xF49D #xE34C)
+                     (#xF49C #xE34B)
+                     (#xF49B #xE34A)
+                     (#xF49A #xE349)
+                     (#xF499 #xE348)
+                     (#xF498 #xE347)
+                     (#xF497 #xE346)
+                     (#xF496 #xE345)
+                     (#xF495 #xE344)
+                     (#xF494 #xE343)
+                     (#xF493 #xE342)
+                     (#xF492 #xE341)
+                     (#xF491 #xE340)
+                     (#xF490 #xE33F)
+                     (#xF48F #xE33E)
+                     (#xF48E #xE33D)
+                     (#xF48D #xE33C)
+                     (#xF48C #xE33B)
+                     (#xF48B #xE33A)
+                     (#xF48A #xE339)
+                     (#xF489 #xE338)
+                     (#xF488 #xE337)
+                     (#xF487 #xE336)
+                     (#xF486 #xE335)
+                     (#xF485 #xE334)
+                     (#xF484 #xE333)
+                     (#xF483 #xE332)
+                     (#xF482 #xE331)
+                     (#xF481 #xE330)
+                     (#xF480 #xE32F)
+                     (#xF47E #xE32E)
+                     (#xF47D #xE32D)
+                     (#xF47C #xE32C)
+                     (#xF47B #xE32B)
+                     (#xF47A #xE32A)
+                     (#xF479 #xE329)
+                     (#xF478 #xE328)
+                     (#xF477 #xE327)
+                     (#xF476 #xE326)
+                     (#xF475 #xE325)
+                     (#xF474 #xE324)
+                     (#xF473 #xE323)
+                     (#xF472 #xE322)
+                     (#xF471 #xE321)
+                     (#xF470 #xE320)
+                     (#xF46F #xE31F)
+                     (#xF46E #xE31E)
+                     (#xF46D #xE31D)
+                     (#xF46C #xE31C)
+                     (#xF46B #xE31B)
+                     (#xF46A #xE31A)
+                     (#xF469 #xE319)
+                     (#xF468 #xE318)
+                     (#xF467 #xE317)
+                     (#xF466 #xE316)
+                     (#xF465 #xE315)
+                     (#xF464 #xE314)
+                     (#xF463 #xE313)
+                     (#xF462 #xE312)
+                     (#xF461 #xE311)
+                     (#xF460 #xE310)
+                     (#xF45F #xE30F)
+                     (#xF45E #xE30E)
+                     (#xF45D #xE30D)
+                     (#xF45C #xE30C)
+                     (#xF45B #xE30B)
+                     (#xF45A #xE30A)
+                     (#xF459 #xE309)
+                     (#xF458 #xE308)
+                     (#xF457 #xE307)
+                     (#xF456 #xE306)
+                     (#xF455 #xE305)
+                     (#xF454 #xE304)
+                     (#xF453 #xE303)
+                     (#xF452 #xE302)
+                     (#xF451 #xE301)
+                     (#xF450 #xE300)
+                     (#xF44F #xE2FF)
+                     (#xF44E #xE2FE)
+                     (#xF44D #xE2FD)
+                     (#xF44C #xE2FC)
+                     (#xF44B #xE2FB)
+                     (#xF44A #xE2FA)
+                     (#xF449 #xE2F9)
+                     (#xF448 #xE2F8)
+                     (#xF447 #xE2F7)
+                     (#xF446 #xE2F6)
+                     (#xF445 #xE2F5)
+                     (#xF444 #xE2F4)
+                     (#xF443 #xE2F3)
+                     (#xF442 #xE2F2)
+                     (#xF441 #xE2F1)
+                     (#xF440 #xE2F0)
+                     (#xF3FC #xE2EF)
+                     (#xF3FB #xE2EE)
+                     (#xF3FA #xE2ED)
+                     (#xF3F9 #xE2EC)
+                     (#xF3F8 #xE2EB)
+                     (#xF3F7 #xE2EA)
+                     (#xF3F6 #xE2E9)
+                     (#xF3F5 #xE2E8)
+                     (#xF3F4 #xE2E7)
+                     (#xF3F3 #xE2E6)
+                     (#xF3F2 #xE2E5)
+                     (#xF3F1 #xE2E4)
+                     (#xF3F0 #xE2E3)
+                     (#xF3EF #xE2E2)
+                     (#xF3EE #xE2E1)
+                     (#xF3ED #xE2E0)
+                     (#xF3EC #xE2DF)
+                     (#xF3EB #xE2DE)
+                     (#xF3EA #xE2DD)
+                     (#xF3E9 #xE2DC)
+                     (#xF3E8 #xE2DB)
+                     (#xF3E7 #xE2DA)
+                     (#xF3E6 #xE2D9)
+                     (#xF3E5 #xE2D8)
+                     (#xF3E4 #xE2D7)
+                     (#xF3E3 #xE2D6)
+                     (#xF3E2 #xE2D5)
+                     (#xF3E1 #xE2D4)
+                     (#xF3E0 #xE2D3)
+                     (#xF3DF #xE2D2)
+                     (#xF3DE #xE2D1)
+                     (#xF3DD #xE2D0)
+                     (#xF3DC #xE2CF)
+                     (#xF3DB #xE2CE)
+                     (#xF3DA #xE2CD)
+                     (#xF3D9 #xE2CC)
+                     (#xF3D8 #xE2CB)
+                     (#xF3D7 #xE2CA)
+                     (#xF3D6 #xE2C9)
+                     (#xF3D5 #xE2C8)
+                     (#xF3D4 #xE2C7)
+                     (#xF3D3 #xE2C6)
+                     (#xF3D2 #xE2C5)
+                     (#xF3D1 #xE2C4)
+                     (#xF3D0 #xE2C3)
+                     (#xF3CF #xE2C2)
+                     (#xF3CE #xE2C1)
+                     (#xF3CD #xE2C0)
+                     (#xF3CC #xE2BF)
+                     (#xF3CB #xE2BE)
+                     (#xF3CA #xE2BD)
+                     (#xF3C9 #xE2BC)
+                     (#xF3C8 #xE2BB)
+                     (#xF3C7 #xE2BA)
+                     (#xF3C6 #xE2B9)
+                     (#xF3C5 #xE2B8)
+                     (#xF3C4 #xE2B7)
+                     (#xF3C3 #xE2B6)
+                     (#xF3C2 #xE2B5)
+                     (#xF3C1 #xE2B4)
+                     (#xF3C0 #xE2B3)
+                     (#xF3BF #xE2B2)
+                     (#xF3BE #xE2B1)
+                     (#xF3BD #xE2B0)
+                     (#xF3BC #xE2AF)
+                     (#xF3BB #xE2AE)
+                     (#xF3BA #xE2AD)
+                     (#xF3B9 #xE2AC)
+                     (#xF3B8 #xE2AB)
+                     (#xF3B7 #xE2AA)
+                     (#xF3B6 #xE2A9)
+                     (#xF3B5 #xE2A8)
+                     (#xF3B4 #xE2A7)
+                     (#xF3B3 #xE2A6)
+                     (#xF3B2 #xE2A5)
+                     (#xF3B1 #xE2A4)
+                     (#xF3B0 #xE2A3)
+                     (#xF3AF #xE2A2)
+                     (#xF3AE #xE2A1)
+                     (#xF3AD #xE2A0)
+                     (#xF3AC #xE29F)
+                     (#xF3AB #xE29E)
+                     (#xF3AA #xE29D)
+                     (#xF3A9 #xE29C)
+                     (#xF3A8 #xE29B)
+                     (#xF3A7 #xE29A)
+                     (#xF3A6 #xE299)
+                     (#xF3A5 #xE298)
+                     (#xF3A4 #xE297)
+                     (#xF3A3 #xE296)
+                     (#xF3A2 #xE295)
+                     (#xF3A1 #xE294)
+                     (#xF3A0 #xE293)
+                     (#xF39F #xE292)
+                     (#xF39E #xE291)
+                     (#xF39D #xE290)
+                     (#xF39C #xE28F)
+                     (#xF39B #xE28E)
+                     (#xF39A #xE28D)
+                     (#xF399 #xE28C)
+                     (#xF398 #xE28B)
+                     (#xF397 #xE28A)
+                     (#xF396 #xE289)
+                     (#xF395 #xE288)
+                     (#xF394 #xE287)
+                     (#xF393 #xE286)
+                     (#xF392 #xE285)
+                     (#xF391 #xE284)
+                     (#xF390 #xE283)
+                     (#xF38F #xE282)
+                     (#xF38E #xE281)
+                     (#xF38D #xE280)
+                     (#xF38C #xE27F)
+                     (#xF38B #xE27E)
+                     (#xF38A #xE27D)
+                     (#xF389 #xE27C)
+                     (#xF388 #xE27B)
+                     (#xF387 #xE27A)
+                     (#xF386 #xE279)
+                     (#xF385 #xE278)
+                     (#xF384 #xE277)
+                     (#xF383 #xE276)
+                     (#xF382 #xE275)
+                     (#xF381 #xE274)
+                     (#xF380 #xE273)
+                     (#xF37E #xE272)
+                     (#xF37D #xE271)
+                     (#xF37C #xE270)
+                     (#xF37B #xE26F)
+                     (#xF37A #xE26E)
+                     (#xF379 #xE26D)
+                     (#xF378 #xE26C)
+                     (#xF377 #xE26B)
+                     (#xF376 #xE26A)
+                     (#xF375 #xE269)
+                     (#xF374 #xE268)
+                     (#xF373 #xE267)
+                     (#xF372 #xE266)
+                     (#xF371 #xE265)
+                     (#xF370 #xE264)
+                     (#xF36F #xE263)
+                     (#xF36E #xE262)
+                     (#xF36D #xE261)
+                     (#xF36C #xE260)
+                     (#xF36B #xE25F)
+                     (#xF36A #xE25E)
+                     (#xF369 #xE25D)
+                     (#xF368 #xE25C)
+                     (#xF367 #xE25B)
+                     (#xF366 #xE25A)
+                     (#xF365 #xE259)
+                     (#xF364 #xE258)
+                     (#xF363 #xE257)
+                     (#xF362 #xE256)
+                     (#xF361 #xE255)
+                     (#xF360 #xE254)
+                     (#xF35F #xE253)
+                     (#xF35E #xE252)
+                     (#xF35D #xE251)
+                     (#xF35C #xE250)
+                     (#xF35B #xE24F)
+                     (#xF35A #xE24E)
+                     (#xF359 #xE24D)
+                     (#xF358 #xE24C)
+                     (#xF357 #xE24B)
+                     (#xF356 #xE24A)
+                     (#xF355 #xE249)
+                     (#xF354 #xE248)
+                     (#xF353 #xE247)
+                     (#xF352 #xE246)
+                     (#xF351 #xE245)
+                     (#xF350 #xE244)
+                     (#xF34F #xE243)
+                     (#xF34E #xE242)
+                     (#xF34D #xE241)
+                     (#xF34C #xE240)
+                     (#xF34B #xE23F)
+                     (#xF34A #xE23E)
+                     (#xF349 #xE23D)
+                     (#xF348 #xE23C)
+                     (#xF347 #xE23B)
+                     (#xF346 #xE23A)
+                     (#xF345 #xE239)
+                     (#xF344 #xE238)
+                     (#xF343 #xE237)
+                     (#xF342 #xE236)
+                     (#xF341 #xE235)
+                     (#xF340 #xE234)
+                     (#xF2FC #xE233)
+                     (#xF2FB #xE232)
+                     (#xF2FA #xE231)
+                     (#xF2F9 #xE230)
+                     (#xF2F8 #xE22F)
+                     (#xF2F7 #xE22E)
+                     (#xF2F6 #xE22D)
+                     (#xF2F5 #xE22C)
+                     (#xF2F4 #xE22B)
+                     (#xF2F3 #xE22A)
+                     (#xF2F2 #xE229)
+                     (#xF2F1 #xE228)
+                     (#xF2F0 #xE227)
+                     (#xF2EF #xE226)
+                     (#xF2EE #xE225)
+                     (#xF2ED #xE224)
+                     (#xF2EC #xE223)
+                     (#xF2EB #xE222)
+                     (#xF2EA #xE221)
+                     (#xF2E9 #xE220)
+                     (#xF2E8 #xE21F)
+                     (#xF2E7 #xE21E)
+                     (#xF2E6 #xE21D)
+                     (#xF2E5 #xE21C)
+                     (#xF2E4 #xE21B)
+                     (#xF2E3 #xE21A)
+                     (#xF2E2 #xE219)
+                     (#xF2E1 #xE218)
+                     (#xF2E0 #xE217)
+                     (#xF2DF #xE216)
+                     (#xF2DE #xE215)
+                     (#xF2DD #xE214)
+                     (#xF2DC #xE213)
+                     (#xF2DB #xE212)
+                     (#xF2DA #xE211)
+                     (#xF2D9 #xE210)
+                     (#xF2D8 #xE20F)
+                     (#xF2D7 #xE20E)
+                     (#xF2D6 #xE20D)
+                     (#xF2D5 #xE20C)
+                     (#xF2D4 #xE20B)
+                     (#xF2D3 #xE20A)
+                     (#xF2D2 #xE209)
+                     (#xF2D1 #xE208)
+                     (#xF2D0 #xE207)
+                     (#xF2CF #xE206)
+                     (#xF2CE #xE205)
+                     (#xF2CD #xE204)
+                     (#xF2CC #xE203)
+                     (#xF2CB #xE202)
+                     (#xF2CA #xE201)
+                     (#xF2C9 #xE200)
+                     (#xF2C8 #xE1FF)
+                     (#xF2C7 #xE1FE)
+                     (#xF2C6 #xE1FD)
+                     (#xF2C5 #xE1FC)
+                     (#xF2C4 #xE1FB)
+                     (#xF2C3 #xE1FA)
+                     (#xF2C2 #xE1F9)
+                     (#xF2C1 #xE1F8)
+                     (#xF2C0 #xE1F7)
+                     (#xF2BF #xE1F6)
+                     (#xF2BE #xE1F5)
+                     (#xF2BD #xE1F4)
+                     (#xF2BC #xE1F3)
+                     (#xF2BB #xE1F2)
+                     (#xF2BA #xE1F1)
+                     (#xF2B9 #xE1F0)
+                     (#xF2B8 #xE1EF)
+                     (#xF2B7 #xE1EE)
+                     (#xF2B6 #xE1ED)
+                     (#xF2B5 #xE1EC)
+                     (#xF2B4 #xE1EB)
+                     (#xF2B3 #xE1EA)
+                     (#xF2B2 #xE1E9)
+                     (#xF2B1 #xE1E8)
+                     (#xF2B0 #xE1E7)
+                     (#xF2AF #xE1E6)
+                     (#xF2AE #xE1E5)
+                     (#xF2AD #xE1E4)
+                     (#xF2AC #xE1E3)
+                     (#xF2AB #xE1E2)
+                     (#xF2AA #xE1E1)
+                     (#xF2A9 #xE1E0)
+                     (#xF2A8 #xE1DF)
+                     (#xF2A7 #xE1DE)
+                     (#xF2A6 #xE1DD)
+                     (#xF2A5 #xE1DC)
+                     (#xF2A4 #xE1DB)
+                     (#xF2A3 #xE1DA)
+                     (#xF2A2 #xE1D9)
+                     (#xF2A1 #xE1D8)
+                     (#xF2A0 #xE1D7)
+                     (#xF29F #xE1D6)
+                     (#xF29E #xE1D5)
+                     (#xF29D #xE1D4)
+                     (#xF29C #xE1D3)
+                     (#xF29B #xE1D2)
+                     (#xF29A #xE1D1)
+                     (#xF299 #xE1D0)
+                     (#xF298 #xE1CF)
+                     (#xF297 #xE1CE)
+                     (#xF296 #xE1CD)
+                     (#xF295 #xE1CC)
+                     (#xF294 #xE1CB)
+                     (#xF293 #xE1CA)
+                     (#xF292 #xE1C9)
+                     (#xF291 #xE1C8)
+                     (#xF290 #xE1C7)
+                     (#xF28F #xE1C6)
+                     (#xF28E #xE1C5)
+                     (#xF28D #xE1C4)
+                     (#xF28C #xE1C3)
+                     (#xF28B #xE1C2)
+                     (#xF28A #xE1C1)
+                     (#xF289 #xE1C0)
+                     (#xF288 #xE1BF)
+                     (#xF287 #xE1BE)
+                     (#xF286 #xE1BD)
+                     (#xF285 #xE1BC)
+                     (#xF284 #xE1BB)
+                     (#xF283 #xE1BA)
+                     (#xF282 #xE1B9)
+                     (#xF281 #xE1B8)
+                     (#xF280 #xE1B7)
+                     (#xF27E #xE1B6)
+                     (#xF27D #xE1B5)
+                     (#xF27C #xE1B4)
+                     (#xF27B #xE1B3)
+                     (#xF27A #xE1B2)
+                     (#xF279 #xE1B1)
+                     (#xF278 #xE1B0)
+                     (#xF277 #xE1AF)
+                     (#xF276 #xE1AE)
+                     (#xF275 #xE1AD)
+                     (#xF274 #xE1AC)
+                     (#xF273 #xE1AB)
+                     (#xF272 #xE1AA)
+                     (#xF271 #xE1A9)
+                     (#xF270 #xE1A8)
+                     (#xF26F #xE1A7)
+                     (#xF26E #xE1A6)
+                     (#xF26D #xE1A5)
+                     (#xF26C #xE1A4)
+                     (#xF26B #xE1A3)
+                     (#xF26A #xE1A2)
+                     (#xF269 #xE1A1)
+                     (#xF268 #xE1A0)
+                     (#xF267 #xE19F)
+                     (#xF266 #xE19E)
+                     (#xF265 #xE19D)
+                     (#xF264 #xE19C)
+                     (#xF263 #xE19B)
+                     (#xF262 #xE19A)
+                     (#xF261 #xE199)
+                     (#xF260 #xE198)
+                     (#xF25F #xE197)
+                     (#xF25E #xE196)
+                     (#xF25D #xE195)
+                     (#xF25C #xE194)
+                     (#xF25B #xE193)
+                     (#xF25A #xE192)
+                     (#xF259 #xE191)
+                     (#xF258 #xE190)
+                     (#xF257 #xE18F)
+                     (#xF256 #xE18E)
+                     (#xF255 #xE18D)
+                     (#xF254 #xE18C)
+                     (#xF253 #xE18B)
+                     (#xF252 #xE18A)
+                     (#xF251 #xE189)
+                     (#xF250 #xE188)
+                     (#xF24F #xE187)
+                     (#xF24E #xE186)
+                     (#xF24D #xE185)
+                     (#xF24C #xE184)
+                     (#xF24B #xE183)
+                     (#xF24A #xE182)
+                     (#xF249 #xE181)
+                     (#xF248 #xE180)
+                     (#xF247 #xE17F)
+                     (#xF246 #xE17E)
+                     (#xF245 #xE17D)
+                     (#xF244 #xE17C)
+                     (#xF243 #xE17B)
+                     (#xF242 #xE17A)
+                     (#xF241 #xE179)
+                     (#xF240 #xE178)
+                     (#xF1FC #xE177)
+                     (#xF1FB #xE176)
+                     (#xF1FA #xE175)
+                     (#xF1F9 #xE174)
+                     (#xF1F8 #xE173)
+                     (#xF1F7 #xE172)
+                     (#xF1F6 #xE171)
+                     (#xF1F5 #xE170)
+                     (#xF1F4 #xE16F)
+                     (#xF1F3 #xE16E)
+                     (#xF1F2 #xE16D)
+                     (#xF1F1 #xE16C)
+                     (#xF1F0 #xE16B)
+                     (#xF1EF #xE16A)
+                     (#xF1EE #xE169)
+                     (#xF1ED #xE168)
+                     (#xF1EC #xE167)
+                     (#xF1EB #xE166)
+                     (#xF1EA #xE165)
+                     (#xF1E9 #xE164)
+                     (#xF1E8 #xE163)
+                     (#xF1E7 #xE162)
+                     (#xF1E6 #xE161)
+                     (#xF1E5 #xE160)
+                     (#xF1E4 #xE15F)
+                     (#xF1E3 #xE15E)
+                     (#xF1E2 #xE15D)
+                     (#xF1E1 #xE15C)
+                     (#xF1E0 #xE15B)
+                     (#xF1DF #xE15A)
+                     (#xF1DE #xE159)
+                     (#xF1DD #xE158)
+                     (#xF1DC #xE157)
+                     (#xF1DB #xE156)
+                     (#xF1DA #xE155)
+                     (#xF1D9 #xE154)
+                     (#xF1D8 #xE153)
+                     (#xF1D7 #xE152)
+                     (#xF1D6 #xE151)
+                     (#xF1D5 #xE150)
+                     (#xF1D4 #xE14F)
+                     (#xF1D3 #xE14E)
+                     (#xF1D2 #xE14D)
+                     (#xF1D1 #xE14C)
+                     (#xF1D0 #xE14B)
+                     (#xF1CF #xE14A)
+                     (#xF1CE #xE149)
+                     (#xF1CD #xE148)
+                     (#xF1CC #xE147)
+                     (#xF1CB #xE146)
+                     (#xF1CA #xE145)
+                     (#xF1C9 #xE144)
+                     (#xF1C8 #xE143)
+                     (#xF1C7 #xE142)
+                     (#xF1C6 #xE141)
+                     (#xF1C5 #xE140)
+                     (#xF1C4 #xE13F)
+                     (#xF1C3 #xE13E)
+                     (#xF1C2 #xE13D)
+                     (#xF1C1 #xE13C)
+                     (#xF1C0 #xE13B)
+                     (#xF1BF #xE13A)
+                     (#xF1BE #xE139)
+                     (#xF1BD #xE138)
+                     (#xF1BC #xE137)
+                     (#xF1BB #xE136)
+                     (#xF1BA #xE135)
+                     (#xF1B9 #xE134)
+                     (#xF1B8 #xE133)
+                     (#xF1B7 #xE132)
+                     (#xF1B6 #xE131)
+                     (#xF1B5 #xE130)
+                     (#xF1B4 #xE12F)
+                     (#xF1B3 #xE12E)
+                     (#xF1B2 #xE12D)
+                     (#xF1B1 #xE12C)
+                     (#xF1B0 #xE12B)
+                     (#xF1AF #xE12A)
+                     (#xF1AE #xE129)
+                     (#xF1AD #xE128)
+                     (#xF1AC #xE127)
+                     (#xF1AB #xE126)
+                     (#xF1AA #xE125)
+                     (#xF1A9 #xE124)
+                     (#xF1A8 #xE123)
+                     (#xF1A7 #xE122)
+                     (#xF1A6 #xE121)
+                     (#xF1A5 #xE120)
+                     (#xF1A4 #xE11F)
+                     (#xF1A3 #xE11E)
+                     (#xF1A2 #xE11D)
+                     (#xF1A1 #xE11C)
+                     (#xF1A0 #xE11B)
+                     (#xF19F #xE11A)
+                     (#xF19E #xE119)
+                     (#xF19D #xE118)
+                     (#xF19C #xE117)
+                     (#xF19B #xE116)
+                     (#xF19A #xE115)
+                     (#xF199 #xE114)
+                     (#xF198 #xE113)
+                     (#xF197 #xE112)
+                     (#xF196 #xE111)
+                     (#xF195 #xE110)
+                     (#xF194 #xE10F)
+                     (#xF193 #xE10E)
+                     (#xF192 #xE10D)
+                     (#xF191 #xE10C)
+                     (#xF190 #xE10B)
+                     (#xF18F #xE10A)
+                     (#xF18E #xE109)
+                     (#xF18D #xE108)
+                     (#xF18C #xE107)
+                     (#xF18B #xE106)
+                     (#xF18A #xE105)
+                     (#xF189 #xE104)
+                     (#xF188 #xE103)
+                     (#xF187 #xE102)
+                     (#xF186 #xE101)
+                     (#xF185 #xE100)
+                     (#xF184 #xE0FF)
+                     (#xF183 #xE0FE)
+                     (#xF182 #xE0FD)
+                     (#xF181 #xE0FC)
+                     (#xF180 #xE0FB)
+                     (#xF17E #xE0FA)
+                     (#xF17D #xE0F9)
+                     (#xF17C #xE0F8)
+                     (#xF17B #xE0F7)
+                     (#xF17A #xE0F6)
+                     (#xF179 #xE0F5)
+                     (#xF178 #xE0F4)
+                     (#xF177 #xE0F3)
+                     (#xF176 #xE0F2)
+                     (#xF175 #xE0F1)
+                     (#xF174 #xE0F0)
+                     (#xF173 #xE0EF)
+                     (#xF172 #xE0EE)
+                     (#xF171 #xE0ED)
+                     (#xF170 #xE0EC)
+                     (#xF16F #xE0EB)
+                     (#xF16E #xE0EA)
+                     (#xF16D #xE0E9)
+                     (#xF16C #xE0E8)
+                     (#xF16B #xE0E7)
+                     (#xF16A #xE0E6)
+                     (#xF169 #xE0E5)
+                     (#xF168 #xE0E4)
+                     (#xF167 #xE0E3)
+                     (#xF166 #xE0E2)
+                     (#xF165 #xE0E1)
+                     (#xF164 #xE0E0)
+                     (#xF163 #xE0DF)
+                     (#xF162 #xE0DE)
+                     (#xF161 #xE0DD)
+                     (#xF160 #xE0DC)
+                     (#xF15F #xE0DB)
+                     (#xF15E #xE0DA)
+                     (#xF15D #xE0D9)
+                     (#xF15C #xE0D8)
+                     (#xF15B #xE0D7)
+                     (#xF15A #xE0D6)
+                     (#xF159 #xE0D5)
+                     (#xF158 #xE0D4)
+                     (#xF157 #xE0D3)
+                     (#xF156 #xE0D2)
+                     (#xF155 #xE0D1)
+                     (#xF154 #xE0D0)
+                     (#xF153 #xE0CF)
+                     (#xF152 #xE0CE)
+                     (#xF151 #xE0CD)
+                     (#xF150 #xE0CC)
+                     (#xF14F #xE0CB)
+                     (#xF14E #xE0CA)
+                     (#xF14D #xE0C9)
+                     (#xF14C #xE0C8)
+                     (#xF14B #xE0C7)
+                     (#xF14A #xE0C6)
+                     (#xF149 #xE0C5)
+                     (#xF148 #xE0C4)
+                     (#xF147 #xE0C3)
+                     (#xF146 #xE0C2)
+                     (#xF145 #xE0C1)
+                     (#xF144 #xE0C0)
+                     (#xF143 #xE0BF)
+                     (#xF142 #xE0BE)
+                     (#xF141 #xE0BD)
+                     (#xF140 #xE0BC)
+                     (#xF0FC #xE0BB)
+                     (#xF0FB #xE0BA)
+                     (#xF0FA #xE0B9)
+                     (#xF0F9 #xE0B8)
+                     (#xF0F8 #xE0B7)
+                     (#xF0F7 #xE0B6)
+                     (#xF0F6 #xE0B5)
+                     (#xF0F5 #xE0B4)
+                     (#xF0F4 #xE0B3)
+                     (#xF0F3 #xE0B2)
+                     (#xF0F2 #xE0B1)
+                     (#xF0F1 #xE0B0)
+                     (#xF0F0 #xE0AF)
+                     (#xF0EF #xE0AE)
+                     (#xF0EE #xE0AD)
+                     (#xF0ED #xE0AC)
+                     (#xF0EC #xE0AB)
+                     (#xF0EB #xE0AA)
+                     (#xF0EA #xE0A9)
+                     (#xF0E9 #xE0A8)
+                     (#xF0E8 #xE0A7)
+                     (#xF0E7 #xE0A6)
+                     (#xF0E6 #xE0A5)
+                     (#xF0E5 #xE0A4)
+                     (#xF0E4 #xE0A3)
+                     (#xF0E3 #xE0A2)
+                     (#xF0E2 #xE0A1)
+                     (#xF0E1 #xE0A0)
+                     (#xF0E0 #xE09F)
+                     (#xF0DF #xE09E)
+                     (#xF0DE #xE09D)
+                     (#xF0DD #xE09C)
+                     (#xF0DC #xE09B)
+                     (#xF0DB #xE09A)
+                     (#xF0DA #xE099)
+                     (#xF0D9 #xE098)
+                     (#xF0D8 #xE097)
+                     (#xF0D7 #xE096)
+                     (#xF0D6 #xE095)
+                     (#xF0D5 #xE094)
+                     (#xF0D4 #xE093)
+                     (#xF0D3 #xE092)
+                     (#xF0D2 #xE091)
+                     (#xF0D1 #xE090)
+                     (#xF0D0 #xE08F)
+                     (#xF0CF #xE08E)
+                     (#xF0CE #xE08D)
+                     (#xF0CD #xE08C)
+                     (#xF0CC #xE08B)
+                     (#xF0CB #xE08A)
+                     (#xF0CA #xE089)
+                     (#xF0C9 #xE088)
+                     (#xF0C8 #xE087)
+                     (#xF0C7 #xE086)
+                     (#xF0C6 #xE085)
+                     (#xF0C5 #xE084)
+                     (#xF0C4 #xE083)
+                     (#xF0C3 #xE082)
+                     (#xF0C2 #xE081)
+                     (#xF0C1 #xE080)
+                     (#xF0C0 #xE07F)
+                     (#xF0BF #xE07E)
+                     (#xF0BE #xE07D)
+                     (#xF0BD #xE07C)
+                     (#xF0BC #xE07B)
+                     (#xF0BB #xE07A)
+                     (#xF0BA #xE079)
+                     (#xF0B9 #xE078)
+                     (#xF0B8 #xE077)
+                     (#xF0B7 #xE076)
+                     (#xF0B6 #xE075)
+                     (#xF0B5 #xE074)
+                     (#xF0B4 #xE073)
+                     (#xF0B3 #xE072)
+                     (#xF0B2 #xE071)
+                     (#xF0B1 #xE070)
+                     (#xF0B0 #xE06F)
+                     (#xF0AF #xE06E)
+                     (#xF0AE #xE06D)
+                     (#xF0AD #xE06C)
+                     (#xF0AC #xE06B)
+                     (#xF0AB #xE06A)
+                     (#xF0AA #xE069)
+                     (#xF0A9 #xE068)
+                     (#xF0A8 #xE067)
+                     (#xF0A7 #xE066)
+                     (#xF0A6 #xE065)
+                     (#xF0A5 #xE064)
+                     (#xF0A4 #xE063)
+                     (#xF0A3 #xE062)
+                     (#xF0A2 #xE061)
+                     (#xF0A1 #xE060)
+                     (#xF0A0 #xE05F)
+                     (#xF09F #xE05E)
+                     (#xF09E #xE05D)
+                     (#xF09D #xE05C)
+                     (#xF09C #xE05B)
+                     (#xF09B #xE05A)
+                     (#xF09A #xE059)
+                     (#xF099 #xE058)
+                     (#xF098 #xE057)
+                     (#xF097 #xE056)
+                     (#xF096 #xE055)
+                     (#xF095 #xE054)
+                     (#xF094 #xE053)
+                     (#xF093 #xE052)
+                     (#xF092 #xE051)
+                     (#xF091 #xE050)
+                     (#xF090 #xE04F)
+                     (#xF08F #xE04E)
+                     (#xF08E #xE04D)
+                     (#xF08D #xE04C)
+                     (#xF08C #xE04B)
+                     (#xF08B #xE04A)
+                     (#xF08A #xE049)
+                     (#xF089 #xE048)
+                     (#xF088 #xE047)
+                     (#xF087 #xE046)
+                     (#xF086 #xE045)
+                     (#xF085 #xE044)
+                     (#xF084 #xE043)
+                     (#xF083 #xE042)
+                     (#xF082 #xE041)
+                     (#xF081 #xE040)
+                     (#xF080 #xE03F)
+                     (#xF07E #xE03E)
+                     (#xF07D #xE03D)
+                     (#xF07C #xE03C)
+                     (#xF07B #xE03B)
+                     (#xF07A #xE03A)
+                     (#xF079 #xE039)
+                     (#xF078 #xE038)
+                     (#xF077 #xE037)
+                     (#xF076 #xE036)
+                     (#xF075 #xE035)
+                     (#xF074 #xE034)
+                     (#xF073 #xE033)
+                     (#xF072 #xE032)
+                     (#xF071 #xE031)
+                     (#xF070 #xE030)
+                     (#xF06F #xE02F)
+                     (#xF06E #xE02E)
+                     (#xF06D #xE02D)
+                     (#xF06C #xE02C)
+                     (#xF06B #xE02B)
+                     (#xF06A #xE02A)
+                     (#xF069 #xE029)
+                     (#xF068 #xE028)
+                     (#xF067 #xE027)
+                     (#xF066 #xE026)
+                     (#xF065 #xE025)
+                     (#xF064 #xE024)
+                     (#xF063 #xE023)
+                     (#xF062 #xE022)
+                     (#xF061 #xE021)
+                     (#xF060 #xE020)
+                     (#xF05F #xE01F)
+                     (#xF05E #xE01E)
+                     (#xF05D #xE01D)
+                     (#xF05C #xE01C)
+                     (#xF05B #xE01B)
+                     (#xF05A #xE01A)
+                     (#xF059 #xE019)
+                     (#xF058 #xE018)
+                     (#xF057 #xE017)
+                     (#xF056 #xE016)
+                     (#xF055 #xE015)
+                     (#xF054 #xE014)
+                     (#xF053 #xE013)
+                     (#xF052 #xE012)
+                     (#xF051 #xE011)
+                     (#xF050 #xE010)
+                     (#xF04F #xE00F)
+                     (#xF04E #xE00E)
+                     (#xF04D #xE00D)
+                     (#xF04C #xE00C)
+                     (#xF04B #xE00B)
+                     (#xF04A #xE00A)
+                     (#xF049 #xE009)
+                     (#xF048 #xE008)
+                     (#xF047 #xE007)
+                     (#xF046 #xE006)
+                     (#xF045 #xE005)
+                     (#xF044 #xE004)
+                     (#xF043 #xE003)
+                     (#xF042 #xE002)
+                     (#xF041 #xE001)
+                     (#xF040 #xE000)
+                     (#xEEFC #xFF02)
+                     (#xEEFB #xFF07)
+                     (#xEEFA #xFFE4)
+                     (#xEEF9 #xFFE2)
+                     (#xEEF8 #x2179)
+                     (#xEEF7 #x2178)
+                     (#xEEF6 #x2177)
+                     (#xEEF5 #x2176)
+                     (#xEEF4 #x2175)
+                     (#xEEF3 #x2174)
+                     (#xEEF2 #x2173)
+                     (#xEEF1 #x2172)
+                     (#xEEF0 #x2171)
+                     (#xEEEF #x2170)
+                     (#xEEEC #x9ED1)
+                     (#xEEEB #x9E19)
+                     (#xEEEA #xFA2D)
+                     (#xEEE9 #x9D6B)
+                     (#xEEE8 #x9D70)
+                     (#xEEE7 #x9C00)
+                     (#xEEE6 #x9BBB)
+                     (#xEEE5 #x9BB1)
+                     (#xEEE4 #x9B8F)
+                     (#xEEE3 #x9B72)
+                     (#xEEE2 #x9B75)
+                     (#xEEE1 #x9ADC)
+                     (#xEEE0 #x9AD9)
+                     (#xEEDF #x9A4E)
+                     (#xEEDE #x999E)
+                     (#xEEDD #xFA2C)
+                     (#xEEDC #x9927)
+                     (#xEEDB #xFA2B)
+                     (#xEEDA #xFA2A)
+                     (#xEED9 #x9865)
+                     (#xEED8 #x9857)
+                     (#xEED7 #x9755)
+                     (#xEED6 #x9751)
+                     (#xEED5 #x974F)
+                     (#xEED4 #x974D)
+                     (#xEED3 #x9743)
+                     (#xEED2 #x973B)
+                     (#xEED1 #x9733)
+                     (#xEED0 #x96AF)
+                     (#xEECF #x969D)
+                     (#xEECE #xFA29)
+                     (#xEECD #xF9DC)
+                     (#xEECC #x9592)
+                     (#xEECB #x9448)
+                     (#xEECA #x9445)
+                     (#xEEC9 #x9431)
+                     (#xEEC8 #x93F8)
+                     (#xEEC7 #x93DE)
+                     (#xEEC6 #x93C6)
+                     (#xEEC5 #x93A4)
+                     (#xEEC4 #x9357)
+                     (#xEEC3 #x9370)
+                     (#xEEC2 #x9302)
+                     (#xEEC1 #x931D)
+                     (#xEEC0 #x92FF)
+                     (#xEEBF #x931E)
+                     (#xEEBE #xFA28)
+                     (#xEEBD #x92FB)
+                     (#xEEBC #x9321)
+                     (#xEEBB #x9325)
+                     (#xEEBA #x92D3)
+                     (#xEEB9 #x92E0)
+                     (#xEEB8 #x92D5)
+                     (#xEEB7 #xFA27)
+                     (#xEEB6 #x92D0)
+                     (#xEEB5 #x92D9)
+                     (#xEEB4 #x92D7)
+                     (#xEEB3 #x92E7)
+                     (#xEEB2 #x9278)
+                     (#xEEB1 #x9277)
+                     (#xEEB0 #x92A7)
+                     (#xEEAF #x9267)
+                     (#xEEAE #x9239)
+                     (#xEEAD #x9251)
+                     (#xEEAC #x9259)
+                     (#xEEAB #x924E)
+                     (#xEEAA #x923C)
+                     (#xEEA9 #x9240)
+                     (#xEEA8 #x923A)
+                     (#xEEA7 #x920A)
+                     (#xEEA6 #x9210)
+                     (#xEEA5 #x9206)
+                     (#xEEA4 #x91E5)
+                     (#xEEA3 #x91E4)
+                     (#xEEA2 #x91EE)
+                     (#xEEA1 #x91ED)
+                     (#xEEA0 #x91DE)
+                     (#xEE9F #x91D7)
+                     (#xEE9E #x91DA)
+                     (#xEE9D #x9127)
+                     (#xEE9C #x9115)
+                     (#xEE9B #xFA26)
+                     (#xEE9A #x90DE)
+                     (#xEE99 #x9067)
+                     (#xEE98 #xFA25)
+                     (#xEE97 #xFA24)
+                     (#xEE96 #x8ECF)
+                     (#xEE95 #xFA23)
+                     (#xEE94 #x8D76)
+                     (#xEE93 #x8D12)
+                     (#xEE92 #x8CF4)
+                     (#xEE91 #x8CF0)
+                     (#xEE90 #x8B7F)
+                     (#xEE8F #x8B53)
+                     (#xEE8E #x8AF6)
+                     (#xEE8D #xFA22)
+                     (#xEE8C #x8ADF)
+                     (#xEE8B #x8ABE)
+                     (#xEE8A #x8AA7)
+                     (#xEE89 #x8A79)
+                     (#xEE88 #x8A37)
+                     (#xEE87 #x8A12)
+                     (#xEE86 #x88F5)
+                     (#xEE85 #x8807)
+                     (#xEE84 #xFA21)
+                     (#xEE83 #xFA20)
+                     (#xEE82 #x85B0)
+                     (#xEE81 #xFA1F)
+                     (#xEE80 #x856B)
+                     (#xEE7E #x8559)
+                     (#xEE7D #x8553)
+                     (#xEE7C #x84B4)
+                     (#xEE7B #x8448)
+                     (#xEE7A #x83F6)
+                     (#xEE79 #x83C7)
+                     (#xEE78 #x837F)
+                     (#xEE77 #x8362)
+                     (#xEE76 #x8301)
+                     (#xEE75 #xFA1E)
+                     (#xEE74 #x7FA1)
+                     (#xEE73 #x7F47)
+                     (#xEE72 #x7E52)
+                     (#xEE71 #x7DD6)
+                     (#xEE70 #x7DA0)
+                     (#xEE6F #x7DB7)
+                     (#xEE6E #x7D5C)
+                     (#xEE6D #x7D48)
+                     (#xEE6C #xFA1D)
+                     (#xEE6B #x7B9E)
+                     (#xEE6A #x7AEB)
+                     (#xEE69 #xFA1C)
+                     (#xEE68 #x7AE7)
+                     (#xEE67 #x7AD1)
+                     (#xEE66 #x799B)
+                     (#xEE65 #xFA1B)
+                     (#xEE64 #x7994)
+                     (#xEE63 #xFA1A)
+                     (#xEE62 #xFA19)
+                     (#xEE61 #xFA18)
+                     (#xEE60 #x7930)
+                     (#xEE5F #x787A)
+                     (#xEE5E #x7864)
+                     (#xEE5D #x784E)
+                     (#xEE5C #x7821)
+                     (#xEE5B #x52AF)
+                     (#xEE5A #x7746)
+                     (#xEE59 #xFA17)
+                     (#xEE58 #x76A6)
+                     (#xEE57 #x769B)
+                     (#xEE56 #x769E)
+                     (#xEE55 #x769C)
+                     (#xEE54 #x7682)
+                     (#xEE53 #x756F)
+                     (#xEE52 #x7501)
+                     (#xEE51 #x749F)
+                     (#xEE50 #x7489)
+                     (#xEE4F #x7462)
+                     (#xEE4E #x742E)
+                     (#xEE4D #x7429)
+                     (#xEE4C #x742A)
+                     (#xEE4B #x7426)
+                     (#xEE4A #x73F5)
+                     (#xEE49 #x7407)
+                     (#xEE48 #x73D2)
+                     (#xEE47 #x73E3)
+                     (#xEE46 #x73D6)
+                     (#xEE45 #x73C9)
+                     (#xEE44 #x73BD)
+                     (#xEE43 #x7377)
+                     (#xEE42 #xFA16)
+                     (#xEE41 #x7324)
+                     (#xEE40 #x72BE)
+                     (#xEDFC #x72B1)
+                     (#xEDFB #x71FE)
+                     (#xEDFA #x71C1)
+                     (#xEDF9 #xFA15)
+                     (#xEDF8 #x7147)
+                     (#xEDF7 #x7146)
+                     (#xEDF6 #x715C)
+                     (#xEDF5 #x7104)
+                     (#xEDF4 #x710F)
+                     (#xEDF3 #x70AB)
+                     (#xEDF2 #x7085)
+                     (#xEDF1 #x7028)
+                     (#xEDF0 #x7007)
+                     (#xEDEF #x7005)
+                     (#xEDEE #x6FF5)
+                     (#xEDED #x6FB5)
+                     (#xEDEC #x6F88)
+                     (#xEDEB #x6EBF)
+                     (#xEDEA #x6E3C)
+                     (#xEDE9 #x6E27)
+                     (#xEDE8 #x6E5C)
+                     (#xEDE7 #x6E39)
+                     (#xEDE6 #x6DFC)
+                     (#xEDE5 #x6DF2)
+                     (#xEDE4 #x6DF8)
+                     (#xEDE3 #x6DCF)
+                     (#xEDE2 #x6DAC)
+                     (#xEDE1 #x6D96)
+                     (#xEDE0 #x6D6F)
+                     (#xEDDF #x6D87)
+                     (#xEDDE #x6D04)
+                     (#xEDDD #x6CDA)
+                     (#xEDDC #x6C6F)
+                     (#xEDDB #x6C86)
+                     (#xEDDA #x6C5C)
+                     (#xEDD9 #x6C3F)
+                     (#xEDD8 #x6BD6)
+                     (#xEDD7 #x6AE4)
+                     (#xEDD6 #x6AE2)
+                     (#xEDD5 #x6A7E)
+                     (#xEDD4 #x6A73)
+                     (#xEDD3 #x6A46)
+                     (#xEDD2 #x6A6B)
+                     (#xEDD1 #x6A30)
+                     (#xEDD0 #x69E2)
+                     (#xEDCF #x6998)
+                     (#xEDCE #xFA14)
+                     (#xEDCD #x6968)
+                     (#xEDCC #xFA13)
+                     (#xEDCB #x68CF)
+                     (#xEDCA #x6844)
+                     (#xEDC9 #x6801)
+                     (#xEDC8 #x67C0)
+                     (#xEDC7 #x6852)
+                     (#xEDC6 #x67BB)
+                     (#xEDC5 #x6766)
+                     (#xEDC4 #xF929)
+                     (#xEDC3 #x670E)
+                     (#xEDC2 #x66FA)
+                     (#xEDC1 #x66BF)
+                     (#xEDC0 #x66B2)
+                     (#xEDBF #x66A0)
+                     (#xEDBE #x6699)
+                     (#xEDBD #x6673)
+                     (#xEDBC #xFA12)
+                     (#xEDBB #x6659)
+                     (#xEDBA #x6657)
+                     (#xEDB9 #x6665)
+                     (#xEDB8 #x6624)
+                     (#xEDB7 #x661E)
+                     (#xEDB6 #x662E)
+                     (#xEDB5 #x6609)
+                     (#xEDB4 #x663B)
+                     (#xEDB3 #x6615)
+                     (#xEDB2 #x6600)
+                     (#xEDB1 #x654E)
+                     (#xEDB0 #x64CE)
+                     (#xEDAF #x649D)
+                     (#xEDAE #x6460)
+                     (#xEDAD #x63F5)
+                     (#xEDAC #x62A6)
+                     (#xEDAB #x6213)
+                     (#xEDAA #x6198)
+                     (#xEDA9 #x6130)
+                     (#xEDA8 #x6137)
+                     (#xEDA7 #x6111)
+                     (#xEDA6 #x60F2)
+                     (#xEDA5 #x6120)
+                     (#xEDA4 #x60D5)
+                     (#xEDA3 #x60DE)
+                     (#xEDA2 #x608A)
+                     (#xEDA1 #x6085)
+                     (#xEDA0 #x605D)
+                     (#xED9F #x5FDE)
+                     (#xED9E #x5FB7)
+                     (#xED9D #x5F67)
+                     (#xED9C #x5F34)
+                     (#xED9B #x5F21)
+                     (#xED9A #x5DD0)
+                     (#xED99 #x5DB9)
+                     (#xED98 #x5DB8)
+                     (#xED97 #x5D6D)
+                     (#xED96 #x5D42)
+                     (#xED95 #xFA11)
+                     (#xED94 #x5D53)
+                     (#xED93 #x5D27)
+                     (#xED92 #x5CF5)
+                     (#xED91 #x5CBA)
+                     (#xED90 #x5CA6)
+                     (#xED8F #x5C1E)
+                     (#xED8E #x5BEC)
+                     (#xED8D #x5BD8)
+                     (#xED8C #x752F)
+                     (#xED8B #x5BC0)
+                     (#xED8A #x5B56)
+                     (#xED89 #x59BA)
+                     (#xED88 #x59A4)
+                     (#xED87 #x5963)
+                     (#xED86 #x595D)
+                     (#xED85 #x595B)
+                     (#xED84 #x5953)
+                     (#xED83 #x590B)
+                     (#xED82 #x58B2)
+                     (#xED81 #x589E)
+                     (#xED80 #xFA10)
+                     (#xED7E #xFA0F)
+                     (#xED7D #x57C7)
+                     (#xED7C #x57C8)
+                     (#xED7B #x57AC)
+                     (#xED7A #x5765)
+                     (#xED79 #x5759)
+                     (#xED78 #x5586)
+                     (#xED77 #x54FF)
+                     (#xED76 #x54A9)
+                     (#xED75 #x548A)
+                     (#xED74 #x549C)
+                     (#xED73 #xFA0E)
+                     (#xED72 #x53DD)
+                     (#xED71 #x53B2)
+                     (#xED70 #x5393)
+                     (#xED6F #x5372)
+                     (#xED6E #x5324)
+                     (#xED6D #x5307)
+                     (#xED6C #x5300)
+                     (#xED6B #x52DB)
+                     (#xED6A #x52C0)
+                     (#xED69 #x52A6)
+                     (#xED68 #x529C)
+                     (#xED67 #x5215)
+                     (#xED66 #x51EC)
+                     (#xED65 #x51BE)
+                     (#xED64 #x519D)
+                     (#xED63 #x5164)
+                     (#xED62 #x514A)
+                     (#xED61 #x50D8)
+                     (#xED60 #x50F4)
+                     (#xED5F #x5094)
+                     (#xED5E #x5042)
+                     (#xED5D #x5070)
+                     (#xED5C #x5046)
+                     (#xED5B #x501E)
+                     (#xED5A #x4FFF)
+                     (#xED59 #x5022)
+                     (#xED58 #x5040)
+                     (#xED57 #x4FCD)
+                     (#xED56 #x4F94)
+                     (#xED55 #x4F9A)
+                     (#xED54 #x4F8A)
+                     (#xED53 #x4F92)
+                     (#xED52 #x4F56)
+                     (#xED51 #x4F39)
+                     (#xED50 #x4F03)
+                     (#xED4F #x4F00)
+                     (#xED4E #x4EFC)
+                     (#xED4D #x4EE1)
+                     (#xED4C #x4E28)
+                     (#xED4B #x5F45)
+                     (#xED4A #x66FB)
+                     (#xED49 #x92F9)
+                     (#xED48 #x68C8)
+                     (#xED47 #x6631)
+                     (#xED46 #x70BB)
+                     (#xED45 #x4FC9)
+                     (#xED44 #x84DC)
+                     (#xED43 #x9288)
+                     (#xED42 #x9348)
+                     (#xED41 #x891C)
+                     (#xED40 #x7E8A)
+                     (#xEA9E #x9FA0)
+                     (#xEA40 #x9D5D)
+                     (#xE99E #x9AF7)
+                     (#xE940 #x9871)
+                     (#xE89E #x965E)
+                     (#xE840 #x9319)
+                     (#xE79E #x8FF8)
+                     (#xE740 #x8E47)
+                     (#xE69E #x8B6B)
+                     (#xE640 #x8966)
+                     (#xE59E #x8759)
+                     (#xE540 #x8541)
+                     (#xE49E #x82D9)
+                     (#xE440 #x968B)
+                     (#xE39E #x7F3A)
+                     (#xE340 #x7D02)
+                     (#xE29E #x7B50)
+                     (#xE240 #x78E7)
+                     (#xE19E #x7670)
+                     (#xE140 #x74E0)
+                     (#xE09E #x71FC)
+                     (#xE040 #x6F3E)
+                     (#x9F9E #x6CBE)
+                     (#x9F40 #x6A97)
+                     (#x9E9E #x68CD)
+                     (#x9E40 #x66C4)
+                     (#x9D9E #x64BC)
+                     (#x9D40 #x621E)
+                     (#x9C9E #x609A)
+                     (#x9C40 #x5ED6)
+                     (#x9B9E #x5C53)
+                     (#x9B40 #x5978)
+                     (#x9A9E #x5709)
+                     (#x9A40 #x54AB)
+                     (#x999E #x8FA8)
+                     (#x9940 #x50C9)
+                     (#x9840 #x84EE)
+                     (#x979E #x7483)
+                     (#x9740 #x8AED)
+                     (#x969E #x6E80)
+                     (#x9640 #x6CD5)
+                     (#x959E #x670D)
+                     (#x9540 #x9F3B)
+                     (#x949E #x9EA6)
+                     (#x9440 #x5982)
+                     (#x939E #x5230)
+                     (#x9340 #x90B8)
+                     (#x929E #x5BF5)
+                     (#x9240 #x53E9)
+                     (#x919E #x618E)
+                     (#x9140 #x7E4A)
+                     (#x909E #x88FE)
+                     (#x9040 #x62ED)
+                     (#x8F9E #x511F)
+                     (#x8F40 #x5B97)
+                     (#x8E9E #x6642)
+                     (#x8E40 #x5BDF)
+                     (#x8D9E #x8FBC)
+                     (#x8D40 #x540E)
+                     (#x8C9E #x6372)
+                     (#x8C40 #x6398)
+                     (#x8B9E #x4EAC)
+                     (#x8B40 #x6A5F)
+                     (#x8A9E #x8431)
+                     (#x8A40 #x9B41)
+                     (#x899E #x5FDC)
+                     (#x8940 #x9662)
+                     (#x879C #x222A)
+                     (#x879B #x2229)
+                     (#x879A #x2235)
+                     (#x8799 #x22BF)
+                     (#x8798 #x221F)
+                     (#x8797 #x2220)
+                     (#x8796 #x22A5)
+                     (#x8795 #x221A)
+                     (#x8794 #x2211)
+                     (#x8793 #x222E)
+                     (#x8792 #x222B)
+                     (#x8791 #x2261)
+                     (#x8790 #x2252)
+                     (#x878F #x337C)
+                     (#x878E #x337D)
+                     (#x878D #x337E)
+                     (#x878C #x3239)
+                     (#x878B #x3232)
+                     (#x878A #x3231)
+                     (#x8789 #x32A8)
+                     (#x8788 #x32A7)
+                     (#x8787 #x32A6)
+                     (#x8786 #x32A5)
+                     (#x8785 #x32A4)
+                     (#x8784 #x2121)
+                     (#x8783 #x33CD)
+                     (#x8782 #x2116)
+                     (#x8781 #x301F)
+                     (#x8780 #x301D)
+                     (#x877E #x337B)
+                     (#x8775 #x33A1)
+                     (#x8774 #x33C4)
+                     (#x8773 #x338F)
+                     (#x8772 #x338E)
+                     (#x8771 #x339E)
+                     (#x8770 #x339D)
+                     (#x876F #x339C)
+                     (#x876E #x333B)
+                     (#x876D #x334A)
+                     (#x876C #x332B)
+                     (#x876B #x3323)
+                     (#x876A #x3326)
+                     (#x8769 #x330D)
+                     (#x8768 #x3357)
+                     (#x8767 #x3351)
+                     (#x8766 #x3336)
+                     (#x8765 #x3303)
+                     (#x8764 #x3327)
+                     (#x8763 #x3318)
+                     (#x8762 #x334D)
+                     (#x8761 #x3322)
+                     (#x8760 #x3314)
+                     (#x875F #x3349)
+                     (#x875D #x2169)
+                     (#x875C #x2168)
+                     (#x875B #x2167)
+                     (#x875A #x2166)
+                     (#x8759 #x2165)
+                     (#x8758 #x2164)
+                     (#x8757 #x2163)
+                     (#x8756 #x2162)
+                     (#x8755 #x2161)
+                     (#x8754 #x2160)
+                     (#x8753 #x2473)
+                     (#x8752 #x2472)
+                     (#x8751 #x2471)
+                     (#x8750 #x2470)
+                     (#x874F #x246F)
+                     (#x874E #x246E)
+                     (#x874D #x246D)
+                     (#x874C #x246C)
+                     (#x874B #x246B)
+                     (#x874A #x246A)
+                     (#x8749 #x2469)
+                     (#x8748 #x2468)
+                     (#x8747 #x2467)
+                     (#x8746 #x2466)
+                     (#x8745 #x2465)
+                     (#x8744 #x2464)
+                     (#x8743 #x2463)
+                     (#x8742 #x2462)
+                     (#x8741 #x2461)
+                     (#x8740 #x2460)
+                     (#x8440 #x410)
+                     (#x8340 #x30A1)
+                     (#x819E #x25C7)
+                     (#x8140 #x3000)
+                     ))
+       (eucjp-only '((#xFEFE #xE3AB)
+                     (#xFEFD #xE3AA)
+                     (#xFEFC #xE3A9)
+                     (#xFEFB #xE3A8)
+                     (#xFEFA #xE3A7)
+                     (#xFEF9 #xE3A6)
+                     (#xFEF8 #xE3A5)
+                     (#xFEF7 #xE3A4)
+                     (#xFEF6 #xE3A3)
+                     (#xFEF5 #xE3A2)
+                     (#xFEF4 #xE3A1)
+                     (#xFEF3 #xE3A0)
+                     (#xFEF2 #xE39F)
+                     (#xFEF1 #xE39E)
+                     (#xFEF0 #xE39D)
+                     (#xFEEF #xE39C)
+                     (#xFEEE #xE39B)
+                     (#xFEED #xE39A)
+                     (#xFEEC #xE399)
+                     (#xFEEB #xE398)
+                     (#xFEEA #xE397)
+                     (#xFEE9 #xE396)
+                     (#xFEE8 #xE395)
+                     (#xFEE7 #xE394)
+                     (#xFEE6 #xE393)
+                     (#xFEE5 #xE392)
+                     (#xFEE4 #xE391)
+                     (#xFEE3 #xE390)
+                     (#xFEE2 #xE38F)
+                     (#xFEE1 #xE38E)
+                     (#xFEE0 #xE38D)
+                     (#xFEDF #xE38C)
+                     (#xFEDE #xE38B)
+                     (#xFEDD #xE38A)
+                     (#xFEDC #xE389)
+                     (#xFEDB #xE388)
+                     (#xFEDA #xE387)
+                     (#xFED9 #xE386)
+                     (#xFED8 #xE385)
+                     (#xFED7 #xE384)
+                     (#xFED6 #xE383)
+                     (#xFED5 #xE382)
+                     (#xFED4 #xE381)
+                     (#xFED3 #xE380)
+                     (#xFED2 #xE37F)
+                     (#xFED1 #xE37E)
+                     (#xFED0 #xE37D)
+                     (#xFECF #xE37C)
+                     (#xFECE #xE37B)
+                     (#xFECD #xE37A)
+                     (#xFECC #xE379)
+                     (#xFECB #xE378)
+                     (#xFECA #xE377)
+                     (#xFEC9 #xE376)
+                     (#xFEC8 #xE375)
+                     (#xFEC7 #xE374)
+                     (#xFEC6 #xE373)
+                     (#xFEC5 #xE372)
+                     (#xFEC4 #xE371)
+                     (#xFEC3 #xE370)
+                     (#xFEC2 #xE36F)
+                     (#xFEC1 #xE36E)
+                     (#xFEC0 #xE36D)
+                     (#xFEBF #xE36C)
+                     (#xFEBE #xE36B)
+                     (#xFEBD #xE36A)
+                     (#xFEBC #xE369)
+                     (#xFEBB #xE368)
+                     (#xFEBA #xE367)
+                     (#xFEB9 #xE366)
+                     (#xFEB8 #xE365)
+                     (#xFEB7 #xE364)
+                     (#xFEB6 #xE363)
+                     (#xFEB5 #xE362)
+                     (#xFEB4 #xE361)
+                     (#xFEB3 #xE360)
+                     (#xFEB2 #xE35F)
+                     (#xFEB1 #xE35E)
+                     (#xFEB0 #xE35D)
+                     (#xFEAF #xE35C)
+                     (#xFEAE #xE35B)
+                     (#xFEAD #xE35A)
+                     (#xFEAC #xE359)
+                     (#xFEAB #xE358)
+                     (#xFEAA #xE357)
+                     (#xFEA9 #xE356)
+                     (#xFEA8 #xE355)
+                     (#xFEA7 #xE354)
+                     (#xFEA6 #xE353)
+                     (#xFEA5 #xE352)
+                     (#xFEA4 #xE351)
+                     (#xFEA3 #xE350)
+                     (#xFEA2 #xE34F)
+                     (#xFEA1 #xE34E)
+                     (#xFDFE #xE34D)
+                     (#xFDFD #xE34C)
+                     (#xFDFC #xE34B)
+                     (#xFDFB #xE34A)
+                     (#xFDFA #xE349)
+                     (#xFDF9 #xE348)
+                     (#xFDF8 #xE347)
+                     (#xFDF7 #xE346)
+                     (#xFDF6 #xE345)
+                     (#xFDF5 #xE344)
+                     (#xFDF4 #xE343)
+                     (#xFDF3 #xE342)
+                     (#xFDF2 #xE341)
+                     (#xFDF1 #xE340)
+                     (#xFDF0 #xE33F)
+                     (#xFDEF #xE33E)
+                     (#xFDEE #xE33D)
+                     (#xFDED #xE33C)
+                     (#xFDEC #xE33B)
+                     (#xFDEB #xE33A)
+                     (#xFDEA #xE339)
+                     (#xFDE9 #xE338)
+                     (#xFDE8 #xE337)
+                     (#xFDE7 #xE336)
+                     (#xFDE6 #xE335)
+                     (#xFDE5 #xE334)
+                     (#xFDE4 #xE333)
+                     (#xFDE3 #xE332)
+                     (#xFDE2 #xE331)
+                     (#xFDE1 #xE330)
+                     (#xFDE0 #xE32F)
+                     (#xFDDF #xE32E)
+                     (#xFDDE #xE32D)
+                     (#xFDDD #xE32C)
+                     (#xFDDC #xE32B)
+                     (#xFDDB #xE32A)
+                     (#xFDDA #xE329)
+                     (#xFDD9 #xE328)
+                     (#xFDD8 #xE327)
+                     (#xFDD7 #xE326)
+                     (#xFDD6 #xE325)
+                     (#xFDD5 #xE324)
+                     (#xFDD4 #xE323)
+                     (#xFDD3 #xE322)
+                     (#xFDD2 #xE321)
+                     (#xFDD1 #xE320)
+                     (#xFDD0 #xE31F)
+                     (#xFDCF #xE31E)
+                     (#xFDCE #xE31D)
+                     (#xFDCD #xE31C)
+                     (#xFDCC #xE31B)
+                     (#xFDCB #xE31A)
+                     (#xFDCA #xE319)
+                     (#xFDC9 #xE318)
+                     (#xFDC8 #xE317)
+                     (#xFDC7 #xE316)
+                     (#xFDC6 #xE315)
+                     (#xFDC5 #xE314)
+                     (#xFDC4 #xE313)
+                     (#xFDC3 #xE312)
+                     (#xFDC2 #xE311)
+                     (#xFDC1 #xE310)
+                     (#xFDC0 #xE30F)
+                     (#xFDBF #xE30E)
+                     (#xFDBE #xE30D)
+                     (#xFDBD #xE30C)
+                     (#xFDBC #xE30B)
+                     (#xFDBB #xE30A)
+                     (#xFDBA #xE309)
+                     (#xFDB9 #xE308)
+                     (#xFDB8 #xE307)
+                     (#xFDB7 #xE306)
+                     (#xFDB6 #xE305)
+                     (#xFDB5 #xE304)
+                     (#xFDB4 #xE303)
+                     (#xFDB3 #xE302)
+                     (#xFDB2 #xE301)
+                     (#xFDB1 #xE300)
+                     (#xFDB0 #xE2FF)
+                     (#xFDAF #xE2FE)
+                     (#xFDAE #xE2FD)
+                     (#xFDAD #xE2FC)
+                     (#xFDAC #xE2FB)
+                     (#xFDAB #xE2FA)
+                     (#xFDAA #xE2F9)
+                     (#xFDA9 #xE2F8)
+                     (#xFDA8 #xE2F7)
+                     (#xFDA7 #xE2F6)
+                     (#xFDA6 #xE2F5)
+                     (#xFDA5 #xE2F4)
+                     (#xFDA4 #xE2F3)
+                     (#xFDA3 #xE2F2)
+                     (#xFDA2 #xE2F1)
+                     (#xFDA1 #xE2F0)
+                     (#xFCFE #xE2EF)
+                     (#xFCFD #xE2EE)
+                     (#xFCFC #xE2ED)
+                     (#xFCFB #xE2EC)
+                     (#xFCFA #xE2EB)
+                     (#xFCF9 #xE2EA)
+                     (#xFCF8 #xE2E9)
+                     (#xFCF7 #xE2E8)
+                     (#xFCF6 #xE2E7)
+                     (#xFCF5 #xE2E6)
+                     (#xFCF4 #xE2E5)
+                     (#xFCF3 #xE2E4)
+                     (#xFCF2 #xE2E3)
+                     (#xFCF1 #xE2E2)
+                     (#xFCF0 #xE2E1)
+                     (#xFCEF #xE2E0)
+                     (#xFCEE #xE2DF)
+                     (#xFCED #xE2DE)
+                     (#xFCEC #xE2DD)
+                     (#xFCEB #xE2DC)
+                     (#xFCEA #xE2DB)
+                     (#xFCE9 #xE2DA)
+                     (#xFCE8 #xE2D9)
+                     (#xFCE7 #xE2D8)
+                     (#xFCE6 #xE2D7)
+                     (#xFCE5 #xE2D6)
+                     (#xFCE4 #xE2D5)
+                     (#xFCE3 #xE2D4)
+                     (#xFCE2 #xE2D3)
+                     (#xFCE1 #xE2D2)
+                     (#xFCE0 #xE2D1)
+                     (#xFCDF #xE2D0)
+                     (#xFCDE #xE2CF)
+                     (#xFCDD #xE2CE)
+                     (#xFCDC #xE2CD)
+                     (#xFCDB #xE2CC)
+                     (#xFCDA #xE2CB)
+                     (#xFCD9 #xE2CA)
+                     (#xFCD8 #xE2C9)
+                     (#xFCD7 #xE2C8)
+                     (#xFCD6 #xE2C7)
+                     (#xFCD5 #xE2C6)
+                     (#xFCD4 #xE2C5)
+                     (#xFCD3 #xE2C4)
+                     (#xFCD2 #xE2C3)
+                     (#xFCD1 #xE2C2)
+                     (#xFCD0 #xE2C1)
+                     (#xFCCF #xE2C0)
+                     (#xFCCE #xE2BF)
+                     (#xFCCD #xE2BE)
+                     (#xFCCC #xE2BD)
+                     (#xFCCB #xE2BC)
+                     (#xFCCA #xE2BB)
+                     (#xFCC9 #xE2BA)
+                     (#xFCC8 #xE2B9)
+                     (#xFCC7 #xE2B8)
+                     (#xFCC6 #xE2B7)
+                     (#xFCC5 #xE2B6)
+                     (#xFCC4 #xE2B5)
+                     (#xFCC3 #xE2B4)
+                     (#xFCC2 #xE2B3)
+                     (#xFCC1 #xE2B2)
+                     (#xFCC0 #xE2B1)
+                     (#xFCBF #xE2B0)
+                     (#xFCBE #xE2AF)
+                     (#xFCBD #xE2AE)
+                     (#xFCBC #xE2AD)
+                     (#xFCBB #xE2AC)
+                     (#xFCBA #xE2AB)
+                     (#xFCB9 #xE2AA)
+                     (#xFCB8 #xE2A9)
+                     (#xFCB7 #xE2A8)
+                     (#xFCB6 #xE2A7)
+                     (#xFCB5 #xE2A6)
+                     (#xFCB4 #xE2A5)
+                     (#xFCB3 #xE2A4)
+                     (#xFCB2 #xE2A3)
+                     (#xFCB1 #xE2A2)
+                     (#xFCB0 #xE2A1)
+                     (#xFCAF #xE2A0)
+                     (#xFCAE #xE29F)
+                     (#xFCAD #xE29E)
+                     (#xFCAC #xE29D)
+                     (#xFCAB #xE29C)
+                     (#xFCAA #xE29B)
+                     (#xFCA9 #xE29A)
+                     (#xFCA8 #xE299)
+                     (#xFCA7 #xE298)
+                     (#xFCA6 #xE297)
+                     (#xFCA5 #xE296)
+                     (#xFCA4 #xE295)
+                     (#xFCA3 #xE294)
+                     (#xFCA2 #xE293)
+                     (#xFCA1 #xE292)
+                     (#xFBFE #xE291)
+                     (#xFBFD #xE290)
+                     (#xFBFC #xE28F)
+                     (#xFBFB #xE28E)
+                     (#xFBFA #xE28D)
+                     (#xFBF9 #xE28C)
+                     (#xFBF8 #xE28B)
+                     (#xFBF7 #xE28A)
+                     (#xFBF6 #xE289)
+                     (#xFBF5 #xE288)
+                     (#xFBF4 #xE287)
+                     (#xFBF3 #xE286)
+                     (#xFBF2 #xE285)
+                     (#xFBF1 #xE284)
+                     (#xFBF0 #xE283)
+                     (#xFBEF #xE282)
+                     (#xFBEE #xE281)
+                     (#xFBED #xE280)
+                     (#xFBEC #xE27F)
+                     (#xFBEB #xE27E)
+                     (#xFBEA #xE27D)
+                     (#xFBE9 #xE27C)
+                     (#xFBE8 #xE27B)
+                     (#xFBE7 #xE27A)
+                     (#xFBE6 #xE279)
+                     (#xFBE5 #xE278)
+                     (#xFBE4 #xE277)
+                     (#xFBE3 #xE276)
+                     (#xFBE2 #xE275)
+                     (#xFBE1 #xE274)
+                     (#xFBE0 #xE273)
+                     (#xFBDF #xE272)
+                     (#xFBDE #xE271)
+                     (#xFBDD #xE270)
+                     (#xFBDC #xE26F)
+                     (#xFBDB #xE26E)
+                     (#xFBDA #xE26D)
+                     (#xFBD9 #xE26C)
+                     (#xFBD8 #xE26B)
+                     (#xFBD7 #xE26A)
+                     (#xFBD6 #xE269)
+                     (#xFBD5 #xE268)
+                     (#xFBD4 #xE267)
+                     (#xFBD3 #xE266)
+                     (#xFBD2 #xE265)
+                     (#xFBD1 #xE264)
+                     (#xFBD0 #xE263)
+                     (#xFBCF #xE262)
+                     (#xFBCE #xE261)
+                     (#xFBCD #xE260)
+                     (#xFBCC #xE25F)
+                     (#xFBCB #xE25E)
+                     (#xFBCA #xE25D)
+                     (#xFBC9 #xE25C)
+                     (#xFBC8 #xE25B)
+                     (#xFBC7 #xE25A)
+                     (#xFBC6 #xE259)
+                     (#xFBC5 #xE258)
+                     (#xFBC4 #xE257)
+                     (#xFBC3 #xE256)
+                     (#xFBC2 #xE255)
+                     (#xFBC1 #xE254)
+                     (#xFBC0 #xE253)
+                     (#xFBBF #xE252)
+                     (#xFBBE #xE251)
+                     (#xFBBD #xE250)
+                     (#xFBBC #xE24F)
+                     (#xFBBB #xE24E)
+                     (#xFBBA #xE24D)
+                     (#xFBB9 #xE24C)
+                     (#xFBB8 #xE24B)
+                     (#xFBB7 #xE24A)
+                     (#xFBB6 #xE249)
+                     (#xFBB5 #xE248)
+                     (#xFBB4 #xE247)
+                     (#xFBB3 #xE246)
+                     (#xFBB2 #xE245)
+                     (#xFBB1 #xE244)
+                     (#xFBB0 #xE243)
+                     (#xFBAF #xE242)
+                     (#xFBAE #xE241)
+                     (#xFBAD #xE240)
+                     (#xFBAC #xE23F)
+                     (#xFBAB #xE23E)
+                     (#xFBAA #xE23D)
+                     (#xFBA9 #xE23C)
+                     (#xFBA8 #xE23B)
+                     (#xFBA7 #xE23A)
+                     (#xFBA6 #xE239)
+                     (#xFBA5 #xE238)
+                     (#xFBA4 #xE237)
+                     (#xFBA3 #xE236)
+                     (#xFBA2 #xE235)
+                     (#xFBA1 #xE234)
+                     (#xFAFE #xE233)
+                     (#xFAFD #xE232)
+                     (#xFAFC #xE231)
+                     (#xFAFB #xE230)
+                     (#xFAFA #xE22F)
+                     (#xFAF9 #xE22E)
+                     (#xFAF8 #xE22D)
+                     (#xFAF7 #xE22C)
+                     (#xFAF6 #xE22B)
+                     (#xFAF5 #xE22A)
+                     (#xFAF4 #xE229)
+                     (#xFAF3 #xE228)
+                     (#xFAF2 #xE227)
+                     (#xFAF1 #xE226)
+                     (#xFAF0 #xE225)
+                     (#xFAEF #xE224)
+                     (#xFAEE #xE223)
+                     (#xFAED #xE222)
+                     (#xFAEC #xE221)
+                     (#xFAEB #xE220)
+                     (#xFAEA #xE21F)
+                     (#xFAE9 #xE21E)
+                     (#xFAE8 #xE21D)
+                     (#xFAE7 #xE21C)
+                     (#xFAE6 #xE21B)
+                     (#xFAE5 #xE21A)
+                     (#xFAE4 #xE219)
+                     (#xFAE3 #xE218)
+                     (#xFAE2 #xE217)
+                     (#xFAE1 #xE216)
+                     (#xFAE0 #xE215)
+                     (#xFADF #xE214)
+                     (#xFADE #xE213)
+                     (#xFADD #xE212)
+                     (#xFADC #xE211)
+                     (#xFADB #xE210)
+                     (#xFADA #xE20F)
+                     (#xFAD9 #xE20E)
+                     (#xFAD8 #xE20D)
+                     (#xFAD7 #xE20C)
+                     (#xFAD6 #xE20B)
+                     (#xFAD5 #xE20A)
+                     (#xFAD4 #xE209)
+                     (#xFAD3 #xE208)
+                     (#xFAD2 #xE207)
+                     (#xFAD1 #xE206)
+                     (#xFAD0 #xE205)
+                     (#xFACF #xE204)
+                     (#xFACE #xE203)
+                     (#xFACD #xE202)
+                     (#xFACC #xE201)
+                     (#xFACB #xE200)
+                     (#xFACA #xE1FF)
+                     (#xFAC9 #xE1FE)
+                     (#xFAC8 #xE1FD)
+                     (#xFAC7 #xE1FC)
+                     (#xFAC6 #xE1FB)
+                     (#xFAC5 #xE1FA)
+                     (#xFAC4 #xE1F9)
+                     (#xFAC3 #xE1F8)
+                     (#xFAC2 #xE1F7)
+                     (#xFAC1 #xE1F6)
+                     (#xFAC0 #xE1F5)
+                     (#xFABF #xE1F4)
+                     (#xFABE #xE1F3)
+                     (#xFABD #xE1F2)
+                     (#xFABC #xE1F1)
+                     (#xFABB #xE1F0)
+                     (#xFABA #xE1EF)
+                     (#xFAB9 #xE1EE)
+                     (#xFAB8 #xE1ED)
+                     (#xFAB7 #xE1EC)
+                     (#xFAB6 #xE1EB)
+                     (#xFAB5 #xE1EA)
+                     (#xFAB4 #xE1E9)
+                     (#xFAB3 #xE1E8)
+                     (#xFAB2 #xE1E7)
+                     (#xFAB1 #xE1E6)
+                     (#xFAB0 #xE1E5)
+                     (#xFAAF #xE1E4)
+                     (#xFAAE #xE1E3)
+                     (#xFAAD #xE1E2)
+                     (#xFAAC #xE1E1)
+                     (#xFAAB #xE1E0)
+                     (#xFAAA #xE1DF)
+                     (#xFAA9 #xE1DE)
+                     (#xFAA8 #xE1DD)
+                     (#xFAA7 #xE1DC)
+                     (#xFAA6 #xE1DB)
+                     (#xFAA5 #xE1DA)
+                     (#xFAA4 #xE1D9)
+                     (#xFAA3 #xE1D8)
+                     (#xFAA2 #xE1D7)
+                     (#xFAA1 #xE1D6)
+                     (#xF9FE #xE1D5)
+                     (#xF9FD #xE1D4)
+                     (#xF9FC #xE1D3)
+                     (#xF9FB #xE1D2)
+                     (#xF9FA #xE1D1)
+                     (#xF9F9 #xE1D0)
+                     (#xF9F8 #xE1CF)
+                     (#xF9F7 #xE1CE)
+                     (#xF9F6 #xE1CD)
+                     (#xF9F5 #xE1CC)
+                     (#xF9F4 #xE1CB)
+                     (#xF9F3 #xE1CA)
+                     (#xF9F2 #xE1C9)
+                     (#xF9F1 #xE1C8)
+                     (#xF9F0 #xE1C7)
+                     (#xF9EF #xE1C6)
+                     (#xF9EE #xE1C5)
+                     (#xF9ED #xE1C4)
+                     (#xF9EC #xE1C3)
+                     (#xF9EB #xE1C2)
+                     (#xF9EA #xE1C1)
+                     (#xF9E9 #xE1C0)
+                     (#xF9E8 #xE1BF)
+                     (#xF9E7 #xE1BE)
+                     (#xF9E6 #xE1BD)
+                     (#xF9E5 #xE1BC)
+                     (#xF9E4 #xE1BB)
+                     (#xF9E3 #xE1BA)
+                     (#xF9E2 #xE1B9)
+                     (#xF9E1 #xE1B8)
+                     (#xF9E0 #xE1B7)
+                     (#xF9DF #xE1B6)
+                     (#xF9DE #xE1B5)
+                     (#xF9DD #xE1B4)
+                     (#xF9DC #xE1B3)
+                     (#xF9DB #xE1B2)
+                     (#xF9DA #xE1B1)
+                     (#xF9D9 #xE1B0)
+                     (#xF9D8 #xE1AF)
+                     (#xF9D7 #xE1AE)
+                     (#xF9D6 #xE1AD)
+                     (#xF9D5 #xE1AC)
+                     (#xF9D4 #xE1AB)
+                     (#xF9D3 #xE1AA)
+                     (#xF9D2 #xE1A9)
+                     (#xF9D1 #xE1A8)
+                     (#xF9D0 #xE1A7)
+                     (#xF9CF #xE1A6)
+                     (#xF9CE #xE1A5)
+                     (#xF9CD #xE1A4)
+                     (#xF9CC #xE1A3)
+                     (#xF9CB #xE1A2)
+                     (#xF9CA #xE1A1)
+                     (#xF9C9 #xE1A0)
+                     (#xF9C8 #xE19F)
+                     (#xF9C7 #xE19E)
+                     (#xF9C6 #xE19D)
+                     (#xF9C5 #xE19C)
+                     (#xF9C4 #xE19B)
+                     (#xF9C3 #xE19A)
+                     (#xF9C2 #xE199)
+                     (#xF9C1 #xE198)
+                     (#xF9C0 #xE197)
+                     (#xF9BF #xE196)
+                     (#xF9BE #xE195)
+                     (#xF9BD #xE194)
+                     (#xF9BC #xE193)
+                     (#xF9BB #xE192)
+                     (#xF9BA #xE191)
+                     (#xF9B9 #xE190)
+                     (#xF9B8 #xE18F)
+                     (#xF9B7 #xE18E)
+                     (#xF9B6 #xE18D)
+                     (#xF9B5 #xE18C)
+                     (#xF9B4 #xE18B)
+                     (#xF9B3 #xE18A)
+                     (#xF9B2 #xE189)
+                     (#xF9B1 #xE188)
+                     (#xF9B0 #xE187)
+                     (#xF9AF #xE186)
+                     (#xF9AE #xE185)
+                     (#xF9AD #xE184)
+                     (#xF9AC #xE183)
+                     (#xF9AB #xE182)
+                     (#xF9AA #xE181)
+                     (#xF9A9 #xE180)
+                     (#xF9A8 #xE17F)
+                     (#xF9A7 #xE17E)
+                     (#xF9A6 #xE17D)
+                     (#xF9A5 #xE17C)
+                     (#xF9A4 #xE17B)
+                     (#xF9A3 #xE17A)
+                     (#xF9A2 #xE179)
+                     (#xF9A1 #xE178)
+                     (#xF8FE #xE177)
+                     (#xF8FD #xE176)
+                     (#xF8FC #xE175)
+                     (#xF8FB #xE174)
+                     (#xF8FA #xE173)
+                     (#xF8F9 #xE172)
+                     (#xF8F8 #xE171)
+                     (#xF8F7 #xE170)
+                     (#xF8F6 #xE16F)
+                     (#xF8F5 #xE16E)
+                     (#xF8F4 #xE16D)
+                     (#xF8F3 #xE16C)
+                     (#xF8F2 #xE16B)
+                     (#xF8F1 #xE16A)
+                     (#xF8F0 #xE169)
+                     (#xF8EF #xE168)
+                     (#xF8EE #xE167)
+                     (#xF8ED #xE166)
+                     (#xF8EC #xE165)
+                     (#xF8EB #xE164)
+                     (#xF8EA #xE163)
+                     (#xF8E9 #xE162)
+                     (#xF8E8 #xE161)
+                     (#xF8E7 #xE160)
+                     (#xF8E6 #xE15F)
+                     (#xF8E5 #xE15E)
+                     (#xF8E4 #xE15D)
+                     (#xF8E3 #xE15C)
+                     (#xF8E2 #xE15B)
+                     (#xF8E1 #xE15A)
+                     (#xF8E0 #xE159)
+                     (#xF8DF #xE158)
+                     (#xF8DE #xE157)
+                     (#xF8DD #xE156)
+                     (#xF8DC #xE155)
+                     (#xF8DB #xE154)
+                     (#xF8DA #xE153)
+                     (#xF8D9 #xE152)
+                     (#xF8D8 #xE151)
+                     (#xF8D7 #xE150)
+                     (#xF8D6 #xE14F)
+                     (#xF8D5 #xE14E)
+                     (#xF8D4 #xE14D)
+                     (#xF8D3 #xE14C)
+                     (#xF8D2 #xE14B)
+                     (#xF8D1 #xE14A)
+                     (#xF8D0 #xE149)
+                     (#xF8CF #xE148)
+                     (#xF8CE #xE147)
+                     (#xF8CD #xE146)
+                     (#xF8CC #xE145)
+                     (#xF8CB #xE144)
+                     (#xF8CA #xE143)
+                     (#xF8C9 #xE142)
+                     (#xF8C8 #xE141)
+                     (#xF8C7 #xE140)
+                     (#xF8C6 #xE13F)
+                     (#xF8C5 #xE13E)
+                     (#xF8C4 #xE13D)
+                     (#xF8C3 #xE13C)
+                     (#xF8C2 #xE13B)
+                     (#xF8C1 #xE13A)
+                     (#xF8C0 #xE139)
+                     (#xF8BF #xE138)
+                     (#xF8BE #xE137)
+                     (#xF8BD #xE136)
+                     (#xF8BC #xE135)
+                     (#xF8BB #xE134)
+                     (#xF8BA #xE133)
+                     (#xF8B9 #xE132)
+                     (#xF8B8 #xE131)
+                     (#xF8B7 #xE130)
+                     (#xF8B6 #xE12F)
+                     (#xF8B5 #xE12E)
+                     (#xF8B4 #xE12D)
+                     (#xF8B3 #xE12C)
+                     (#xF8B2 #xE12B)
+                     (#xF8B1 #xE12A)
+                     (#xF8B0 #xE129)
+                     (#xF8AF #xE128)
+                     (#xF8AE #xE127)
+                     (#xF8AD #xE126)
+                     (#xF8AC #xE125)
+                     (#xF8AB #xE124)
+                     (#xF8AA #xE123)
+                     (#xF8A9 #xE122)
+                     (#xF8A8 #xE121)
+                     (#xF8A7 #xE120)
+                     (#xF8A6 #xE11F)
+                     (#xF8A5 #xE11E)
+                     (#xF8A4 #xE11D)
+                     (#xF8A3 #xE11C)
+                     (#xF8A2 #xE11B)
+                     (#xF8A1 #xE11A)
+                     (#xF7FE #xE119)
+                     (#xF7FD #xE118)
+                     (#xF7FC #xE117)
+                     (#xF7FB #xE116)
+                     (#xF7FA #xE115)
+                     (#xF7F9 #xE114)
+                     (#xF7F8 #xE113)
+                     (#xF7F7 #xE112)
+                     (#xF7F6 #xE111)
+                     (#xF7F5 #xE110)
+                     (#xF7F4 #xE10F)
+                     (#xF7F3 #xE10E)
+                     (#xF7F2 #xE10D)
+                     (#xF7F1 #xE10C)
+                     (#xF7F0 #xE10B)
+                     (#xF7EF #xE10A)
+                     (#xF7EE #xE109)
+                     (#xF7ED #xE108)
+                     (#xF7EC #xE107)
+                     (#xF7EB #xE106)
+                     (#xF7EA #xE105)
+                     (#xF7E9 #xE104)
+                     (#xF7E8 #xE103)
+                     (#xF7E7 #xE102)
+                     (#xF7E6 #xE101)
+                     (#xF7E5 #xE100)
+                     (#xF7E4 #xE0FF)
+                     (#xF7E3 #xE0FE)
+                     (#xF7E2 #xE0FD)
+                     (#xF7E1 #xE0FC)
+                     (#xF7E0 #xE0FB)
+                     (#xF7DF #xE0FA)
+                     (#xF7DE #xE0F9)
+                     (#xF7DD #xE0F8)
+                     (#xF7DC #xE0F7)
+                     (#xF7DB #xE0F6)
+                     (#xF7DA #xE0F5)
+                     (#xF7D9 #xE0F4)
+                     (#xF7D8 #xE0F3)
+                     (#xF7D7 #xE0F2)
+                     (#xF7D6 #xE0F1)
+                     (#xF7D5 #xE0F0)
+                     (#xF7D4 #xE0EF)
+                     (#xF7D3 #xE0EE)
+                     (#xF7D2 #xE0ED)
+                     (#xF7D1 #xE0EC)
+                     (#xF7D0 #xE0EB)
+                     (#xF7CF #xE0EA)
+                     (#xF7CE #xE0E9)
+                     (#xF7CD #xE0E8)
+                     (#xF7CC #xE0E7)
+                     (#xF7CB #xE0E6)
+                     (#xF7CA #xE0E5)
+                     (#xF7C9 #xE0E4)
+                     (#xF7C8 #xE0E3)
+                     (#xF7C7 #xE0E2)
+                     (#xF7C6 #xE0E1)
+                     (#xF7C5 #xE0E0)
+                     (#xF7C4 #xE0DF)
+                     (#xF7C3 #xE0DE)
+                     (#xF7C2 #xE0DD)
+                     (#xF7C1 #xE0DC)
+                     (#xF7C0 #xE0DB)
+                     (#xF7BF #xE0DA)
+                     (#xF7BE #xE0D9)
+                     (#xF7BD #xE0D8)
+                     (#xF7BC #xE0D7)
+                     (#xF7BB #xE0D6)
+                     (#xF7BA #xE0D5)
+                     (#xF7B9 #xE0D4)
+                     (#xF7B8 #xE0D3)
+                     (#xF7B7 #xE0D2)
+                     (#xF7B6 #xE0D1)
+                     (#xF7B5 #xE0D0)
+                     (#xF7B4 #xE0CF)
+                     (#xF7B3 #xE0CE)
+                     (#xF7B2 #xE0CD)
+                     (#xF7B1 #xE0CC)
+                     (#xF7B0 #xE0CB)
+                     (#xF7AF #xE0CA)
+                     (#xF7AE #xE0C9)
+                     (#xF7AD #xE0C8)
+                     (#xF7AC #xE0C7)
+                     (#xF7AB #xE0C6)
+                     (#xF7AA #xE0C5)
+                     (#xF7A9 #xE0C4)
+                     (#xF7A8 #xE0C3)
+                     (#xF7A7 #xE0C2)
+                     (#xF7A6 #xE0C1)
+                     (#xF7A5 #xE0C0)
+                     (#xF7A4 #xE0BF)
+                     (#xF7A3 #xE0BE)
+                     (#xF7A2 #xE0BD)
+                     (#xF7A1 #xE0BC)
+                     (#xF6FE #xE0BB)
+                     (#xF6FD #xE0BA)
+                     (#xF6FC #xE0B9)
+                     (#xF6FB #xE0B8)
+                     (#xF6FA #xE0B7)
+                     (#xF6F9 #xE0B6)
+                     (#xF6F8 #xE0B5)
+                     (#xF6F7 #xE0B4)
+                     (#xF6F6 #xE0B3)
+                     (#xF6F5 #xE0B2)
+                     (#xF6F4 #xE0B1)
+                     (#xF6F3 #xE0B0)
+                     (#xF6F2 #xE0AF)
+                     (#xF6F1 #xE0AE)
+                     (#xF6F0 #xE0AD)
+                     (#xF6EF #xE0AC)
+                     (#xF6EE #xE0AB)
+                     (#xF6ED #xE0AA)
+                     (#xF6EC #xE0A9)
+                     (#xF6EB #xE0A8)
+                     (#xF6EA #xE0A7)
+                     (#xF6E9 #xE0A6)
+                     (#xF6E8 #xE0A5)
+                     (#xF6E7 #xE0A4)
+                     (#xF6E6 #xE0A3)
+                     (#xF6E5 #xE0A2)
+                     (#xF6E4 #xE0A1)
+                     (#xF6E3 #xE0A0)
+                     (#xF6E2 #xE09F)
+                     (#xF6E1 #xE09E)
+                     (#xF6E0 #xE09D)
+                     (#xF6DF #xE09C)
+                     (#xF6DE #xE09B)
+                     (#xF6DD #xE09A)
+                     (#xF6DC #xE099)
+                     (#xF6DB #xE098)
+                     (#xF6DA #xE097)
+                     (#xF6D9 #xE096)
+                     (#xF6D8 #xE095)
+                     (#xF6D7 #xE094)
+                     (#xF6D6 #xE093)
+                     (#xF6D5 #xE092)
+                     (#xF6D4 #xE091)
+                     (#xF6D3 #xE090)
+                     (#xF6D2 #xE08F)
+                     (#xF6D1 #xE08E)
+                     (#xF6D0 #xE08D)
+                     (#xF6CF #xE08C)
+                     (#xF6CE #xE08B)
+                     (#xF6CD #xE08A)
+                     (#xF6CC #xE089)
+                     (#xF6CB #xE088)
+                     (#xF6CA #xE087)
+                     (#xF6C9 #xE086)
+                     (#xF6C8 #xE085)
+                     (#xF6C7 #xE084)
+                     (#xF6C6 #xE083)
+                     (#xF6C5 #xE082)
+                     (#xF6C4 #xE081)
+                     (#xF6C3 #xE080)
+                     (#xF6C2 #xE07F)
+                     (#xF6C1 #xE07E)
+                     (#xF6C0 #xE07D)
+                     (#xF6BF #xE07C)
+                     (#xF6BE #xE07B)
+                     (#xF6BD #xE07A)
+                     (#xF6BC #xE079)
+                     (#xF6BB #xE078)
+                     (#xF6BA #xE077)
+                     (#xF6B9 #xE076)
+                     (#xF6B8 #xE075)
+                     (#xF6B7 #xE074)
+                     (#xF6B6 #xE073)
+                     (#xF6B5 #xE072)
+                     (#xF6B4 #xE071)
+                     (#xF6B3 #xE070)
+                     (#xF6B2 #xE06F)
+                     (#xF6B1 #xE06E)
+                     (#xF6B0 #xE06D)
+                     (#xF6AF #xE06C)
+                     (#xF6AE #xE06B)
+                     (#xF6AD #xE06A)
+                     (#xF6AC #xE069)
+                     (#xF6AB #xE068)
+                     (#xF6AA #xE067)
+                     (#xF6A9 #xE066)
+                     (#xF6A8 #xE065)
+                     (#xF6A7 #xE064)
+                     (#xF6A6 #xE063)
+                     (#xF6A5 #xE062)
+                     (#xF6A4 #xE061)
+                     (#xF6A3 #xE060)
+                     (#xF6A2 #xE05F)
+                     (#xF6A1 #xE05E)
+                     (#xF5FE #xE05D)
+                     (#xF5FD #xE05C)
+                     (#xF5FC #xE05B)
+                     (#xF5FB #xE05A)
+                     (#xF5FA #xE059)
+                     (#xF5F9 #xE058)
+                     (#xF5F8 #xE057)
+                     (#xF5F7 #xE056)
+                     (#xF5F6 #xE055)
+                     (#xF5F5 #xE054)
+                     (#xF5F4 #xE053)
+                     (#xF5F3 #xE052)
+                     (#xF5F2 #xE051)
+                     (#xF5F1 #xE050)
+                     (#xF5F0 #xE04F)
+                     (#xF5EF #xE04E)
+                     (#xF5EE #xE04D)
+                     (#xF5ED #xE04C)
+                     (#xF5EC #xE04B)
+                     (#xF5EB #xE04A)
+                     (#xF5EA #xE049)
+                     (#xF5E9 #xE048)
+                     (#xF5E8 #xE047)
+                     (#xF5E7 #xE046)
+                     (#xF5E6 #xE045)
+                     (#xF5E5 #xE044)
+                     (#xF5E4 #xE043)
+                     (#xF5E3 #xE042)
+                     (#xF5E2 #xE041)
+                     (#xF5E1 #xE040)
+                     (#xF5E0 #xE03F)
+                     (#xF5DF #xE03E)
+                     (#xF5DE #xE03D)
+                     (#xF5DD #xE03C)
+                     (#xF5DC #xE03B)
+                     (#xF5DB #xE03A)
+                     (#xF5DA #xE039)
+                     (#xF5D9 #xE038)
+                     (#xF5D8 #xE037)
+                     (#xF5D7 #xE036)
+                     (#xF5D6 #xE035)
+                     (#xF5D5 #xE034)
+                     (#xF5D4 #xE033)
+                     (#xF5D3 #xE032)
+                     (#xF5D2 #xE031)
+                     (#xF5D1 #xE030)
+                     (#xF5D0 #xE02F)
+                     (#xF5CF #xE02E)
+                     (#xF5CE #xE02D)
+                     (#xF5CD #xE02C)
+                     (#xF5CC #xE02B)
+                     (#xF5CB #xE02A)
+                     (#xF5CA #xE029)
+                     (#xF5C9 #xE028)
+                     (#xF5C8 #xE027)
+                     (#xF5C7 #xE026)
+                     (#xF5C6 #xE025)
+                     (#xF5C5 #xE024)
+                     (#xF5C4 #xE023)
+                     (#xF5C3 #xE022)
+                     (#xF5C2 #xE021)
+                     (#xF5C1 #xE020)
+                     (#xF5C0 #xE01F)
+                     (#xF5BF #xE01E)
+                     (#xF5BE #xE01D)
+                     (#xF5BD #xE01C)
+                     (#xF5BC #xE01B)
+                     (#xF5BB #xE01A)
+                     (#xF5BA #xE019)
+                     (#xF5B9 #xE018)
+                     (#xF5B8 #xE017)
+                     (#xF5B7 #xE016)
+                     (#xF5B6 #xE015)
+                     (#xF5B5 #xE014)
+                     (#xF5B4 #xE013)
+                     (#xF5B3 #xE012)
+                     (#xF5B2 #xE011)
+                     (#xF5B1 #xE010)
+                     (#xF5B0 #xE00F)
+                     (#xF5AF #xE00E)
+                     (#xF5AE #xE00D)
+                     (#xF5AD #xE00C)
+                     (#xF5AC #xE00B)
+                     (#xF5AB #xE00A)
+                     (#xF5AA #xE009)
+                     (#xF5A9 #xE008)
+                     (#xF5A8 #xE007)
+                     (#xF5A7 #xE006)
+                     (#xF5A6 #xE005)
+                     (#xF5A5 #xE004)
+                     (#xF5A4 #xE003)
+                     (#xF5A3 #xE002)
+                     (#xF5A2 #xE001)
+                     (#xF5A1 #xE000)
+                     ))
+       (eucjp '((#x8FA2AF #x2D8)
+                (#x8FA2B0 #x2C7)
+                (#x8FA2B1 #xB8)
+                (#x8FA2B2 #x2D9)
+                (#x8FA2B3 #x2DD)
+                (#x8FA2B4 #xAF)
+                (#x8FA2B5 #x2DB)
+                (#x8FA2B6 #x2DA)
+                (#x8FA2B7 #xFF5E)
+                (#x8FA2B8 #x384)
+                (#x8FA2B9 #x385)
+                (#x8FA2C2 #xA1)
+                (#x8FA2C3 #xA6)
+                (#x8FA2C4 #xBF)
+                (#x8FA2EB #xBA)
+                (#x8FA2EC #xAA)
+                (#x8FA2ED #xA9)
+                (#x8FA2EE #xAE)
+                (#x8FA2EF #x2122)
+                (#x8FA2F0 #xA4)
+                (#x8FA2F1 #x2116)
+                (#x8FA6E1 #x386)
+                (#x8FA6E2 #x388)
+                (#x8FA6E3 #x389)
+                (#x8FA6E4 #x38A)
+                (#x8FA6E5 #x3AA)
+                (#x8FA6E7 #x38C)
+                (#x8FA6E9 #x38E)
+                (#x8FA6EA #x3AB)
+                (#x8FA6EC #x38F)
+                (#x8FA6F1 #x3AC)
+                (#x8FA6F2 #x3AD)
+                (#x8FA6F3 #x3AE)
+                (#x8FA6F4 #x3AF)
+                (#x8FA6F5 #x3CA)
+                (#x8FA6F6 #x390)
+                (#x8FA6F7 #x3CC)
+                (#x8FA6F8 #x3C2)
+                (#x8FA6F9 #x3CD)
+                (#x8FA6FA #x3CB)
+                (#x8FA6FB #x3B0)
+                (#x8FA6FC #x3CE)
+                (#x8FA7C2 #x402)
+                (#x8FA7C3 #x403)
+                (#x8FA7C4 #x404)
+                (#x8FA7C5 #x405)
+                (#x8FA7C6 #x406)
+                (#x8FA7C7 #x407)
+                (#x8FA7C8 #x408)
+                (#x8FA7C9 #x409)
+                (#x8FA7CA #x40A)
+                (#x8FA7CB #x40B)
+                (#x8FA7CC #x40C)
+                (#x8FA7CD #x40E)
+                (#x8FA7CE #x40F)
+                (#x8FA7F2 #x452)
+                (#x8FA7F3 #x453)
+                (#x8FA7F4 #x454)
+                (#x8FA7F5 #x455)
+                (#x8FA7F6 #x456)
+                (#x8FA7F7 #x457)
+                (#x8FA7F8 #x458)
+                (#x8FA7F9 #x459)
+                (#x8FA7FA #x45A)
+                (#x8FA7FB #x45B)
+                (#x8FA7FC #x45C)
+                (#x8FA7FD #x45E)
+                (#x8FA7FE #x45F)
+                (#x8FA9A1 #xC6)
+                (#x8FA9A2 #x110)
+                (#x8FA9A4 #x126)
+                (#x8FA9A6 #x132)
+                (#x8FA9A8 #x141)
+                (#x8FA9A9 #x13F)
+                (#x8FA9AB #x14A)
+                (#x8FA9AC #xD8)
+                (#x8FA9AD #x152)
+                (#x8FA9AF #x166)
+                (#x8FA9B0 #xDE)
+                (#x8FA9C1 #xE6)
+                (#x8FA9C2 #x111)
+                (#x8FA9C3 #xF0)
+                (#x8FA9C4 #x127)
+                (#x8FA9C5 #x131)
+                (#x8FA9C6 #x133)
+                (#x8FA9C7 #x138)
+                (#x8FA9C8 #x142)
+                (#x8FA9C9 #x140)
+                (#x8FA9CA #x149)
+                (#x8FA9CB #x14B)
+                (#x8FA9CC #xF8)
+                (#x8FA9CD #x153)
+                (#x8FA9CE #xDF)
+                (#x8FA9CF #x167)
+                (#x8FA9D0 #xFE)
+                (#x8FAAA1 #xC1)
+                (#x8FAAA2 #xC0)
+                (#x8FAAA3 #xC4)
+                (#x8FAAA4 #xC2)
+                (#x8FAAA5 #x102)
+                (#x8FAAA6 #x1CD)
+                (#x8FAAA7 #x100)
+                (#x8FAAA8 #x104)
+                (#x8FAAA9 #xC5)
+                (#x8FAAAA #xC3)
+                (#x8FAAAB #x106)
+                (#x8FAAAC #x108)
+                (#x8FAAAD #x10C)
+                (#x8FAAAE #xC7)
+                (#x8FAAAF #x10A)
+                (#x8FAAB0 #x10E)
+                (#x8FAAB1 #xC9)
+                (#x8FAAB2 #xC8)
+                (#x8FAAB3 #xCB)
+                (#x8FAAB4 #xCA)
+                (#x8FAAB5 #x11A)
+                (#x8FAAB6 #x116)
+                (#x8FAAB7 #x112)
+                (#x8FAAB8 #x118)
+                (#x8FAABA #x11C)
+                (#x8FAABB #x11E)
+                (#x8FAABC #x122)
+                (#x8FAABD #x120)
+                (#x8FAABE #x124)
+                (#x8FAABF #xCD)
+                (#x8FAAC0 #xCC)
+                (#x8FAAC1 #xCF)
+                (#x8FAAC2 #xCE)
+                (#x8FAAC3 #x1CF)
+                (#x8FAAC4 #x130)
+                (#x8FAAC5 #x12A)
+                (#x8FAAC6 #x12E)
+                (#x8FAAC7 #x128)
+                (#x8FAAC8 #x134)
+                (#x8FAAC9 #x136)
+                (#x8FAACA #x139)
+                (#x8FAACB #x13D)
+                (#x8FAACC #x13B)
+                (#x8FAACD #x143)
+                (#x8FAACE #x147)
+                (#x8FAACF #x145)
+                (#x8FAAD0 #xD1)
+                (#x8FAAD1 #xD3)
+                (#x8FAAD2 #xD2)
+                (#x8FAAD3 #xD6)
+                (#x8FAAD4 #xD4)
+                (#x8FAAD5 #x1D1)
+                (#x8FAAD6 #x150)
+                (#x8FAAD7 #x14C)
+                (#x8FAAD8 #xD5)
+                (#x8FAAD9 #x154)
+                (#x8FAADA #x158)
+                (#x8FAADB #x156)
+                (#x8FAADC #x15A)
+                (#x8FAADD #x15C)
+                (#x8FAADE #x160)
+                (#x8FAADF #x15E)
+                (#x8FAAE0 #x164)
+                (#x8FAAE1 #x162)
+                (#x8FAAE2 #xDA)
+                (#x8FAAE3 #xD9)
+                (#x8FAAE4 #xDC)
+                (#x8FAAE5 #xDB)
+                (#x8FAAE6 #x16C)
+                (#x8FAAE7 #x1D3)
+                (#x8FAAE8 #x170)
+                (#x8FAAE9 #x16A)
+                (#x8FAAEA #x172)
+                (#x8FAAEB #x16E)
+                (#x8FAAEC #x168)
+                (#x8FAAED #x1D7)
+                (#x8FAAEE #x1DB)
+                (#x8FAAEF #x1D9)
+                (#x8FAAF0 #x1D5)
+                (#x8FAAF1 #x174)
+                (#x8FAAF2 #xDD)
+                (#x8FAAF3 #x178)
+                (#x8FAAF4 #x176)
+                (#x8FAAF5 #x179)
+                (#x8FAAF6 #x17D)
+                (#x8FAAF7 #x17B)
+                (#x8FABA1 #xE1)
+                (#x8FABA2 #xE0)
+                (#x8FABA3 #xE4)
+                (#x8FABA4 #xE2)
+                (#x8FABA5 #x103)
+                (#x8FABA6 #x1CE)
+                (#x8FABA7 #x101)
+                (#x8FABA8 #x105)
+                (#x8FABA9 #xE5)
+                (#x8FABAA #xE3)
+                (#x8FABAB #x107)
+                (#x8FABAC #x109)
+                (#x8FABAD #x10D)
+                (#x8FABAE #xE7)
+                (#x8FABAF #x10B)
+                (#x8FABB0 #x10F)
+                (#x8FABB1 #xE9)
+                (#x8FABB2 #xE8)
+                (#x8FABB3 #xEB)
+                (#x8FABB4 #xEA)
+                (#x8FABB5 #x11B)
+                (#x8FABB6 #x117)
+                (#x8FABB7 #x113)
+                (#x8FABB8 #x119)
+                (#x8FABB9 #x1F5)
+                (#x8FABBA #x11D)
+                (#x8FABBB #x11F)
+                (#x8FABBD #x121)
+                (#x8FABBE #x125)
+                (#x8FABBF #xED)
+                (#x8FABC0 #xEC)
+                (#x8FABC1 #xEF)
+                (#x8FABC2 #xEE)
+                (#x8FABC3 #x1D0)
+                (#x8FABC5 #x12B)
+                (#x8FABC6 #x12F)
+                (#x8FABC7 #x129)
+                (#x8FABC8 #x135)
+                (#x8FABC9 #x137)
+                (#x8FABCA #x13A)
+                (#x8FABCB #x13E)
+                (#x8FABCC #x13C)
+                (#x8FABCD #x144)
+                (#x8FABCE #x148)
+                (#x8FABCF #x146)
+                (#x8FABD0 #xF1)
+                (#x8FABD1 #xF3)
+                (#x8FABD2 #xF2)
+                (#x8FABD3 #xF6)
+                (#x8FABD4 #xF4)
+                (#x8FABD5 #x1D2)
+                (#x8FABD6 #x151)
+                (#x8FABD7 #x14D)
+                (#x8FABD8 #xF5)
+                (#x8FABD9 #x155)
+                (#x8FABDA #x159)
+                (#x8FABDB #x157)
+                (#x8FABDC #x15B)
+                (#x8FABDD #x15D)
+                (#x8FABDE #x161)
+                (#x8FABDF #x15F)
+                (#x8FABE0 #x165)
+                (#x8FABE1 #x163)
+                (#x8FABE2 #xFA)
+                (#x8FABE3 #xF9)
+                (#x8FABE4 #xFC)
+                (#x8FABE5 #xFB)
+                (#x8FABE6 #x16D)
+                (#x8FABE7 #x1D4)
+                (#x8FABE8 #x171)
+                (#x8FABE9 #x16B)
+                (#x8FABEA #x173)
+                (#x8FABEB #x16F)
+                (#x8FABEC #x169)
+                (#x8FABED #x1D8)
+                (#x8FABEE #x1DC)
+                (#x8FABEF #x1DA)
+                (#x8FABF0 #x1D6)
+                (#x8FABF1 #x175)
+                (#x8FABF2 #xFD)
+                (#x8FABF3 #xFF)
+                (#x8FABF4 #x177)
+                (#x8FABF5 #x17A)
+                (#x8FABF6 #x17E)
+                (#x8FABF7 #x17C)
+                (#x8FB0A1 #x4E02)
+                (#x8FB0A2 #x4E04)
+                (#x8FB0A3 #x4E05)
+                (#x8FB0A4 #x4E0C)
+                (#x8FB0A5 #x4E12)
+                (#x8FB0A6 #x4E1F)
+                (#x8FB0A7 #x4E23)
+                (#x8FB0A8 #x4E24)
+                (#x8FB0A9 #x4E28)
+                (#x8FB0AA #x4E2B)
+                (#x8FB0AB #x4E2E)
+                (#x8FB0AC #x4E2F)
+                (#x8FB0AD #x4E30)
+                (#x8FB0AE #x4E35)
+                (#x8FB0AF #x4E40)
+                (#x8FB0B0 #x4E41)
+                (#x8FB0B1 #x4E44)
+                (#x8FB0B2 #x4E47)
+                (#x8FB0B3 #x4E51)
+                (#x8FB0B4 #x4E5A)
+                (#x8FB0B5 #x4E5C)
+                (#x8FB0B6 #x4E63)
+                (#x8FB0B7 #x4E68)
+                (#x8FB0B8 #x4E69)
+                (#x8FB0B9 #x4E74)
+                (#x8FB0BA #x4E75)
+                (#x8FB0BB #x4E79)
+                (#x8FB0BC #x4E7F)
+                (#x8FB0BD #x4E8D)
+                (#x8FB0BE #x4E96)
+                (#x8FB0BF #x4E97)
+                (#x8FB0C0 #x4E9D)
+                (#x8FB0C1 #x4EAF)
+                (#x8FB0C2 #x4EB9)
+                (#x8FB0C3 #x4EC3)
+                (#x8FB0C4 #x4ED0)
+                (#x8FB0C5 #x4EDA)
+                (#x8FB0C6 #x4EDB)
+                (#x8FB0C7 #x4EE0)
+                (#x8FB0C8 #x4EE1)
+                (#x8FB0C9 #x4EE2)
+                (#x8FB0CA #x4EE8)
+                (#x8FB0CB #x4EEF)
+                (#x8FB0CC #x4EF1)
+                (#x8FB0CD #x4EF3)
+                (#x8FB0CE #x4EF5)
+                (#x8FB0CF #x4EFD)
+                (#x8FB0D0 #x4EFE)
+                (#x8FB0D1 #x4EFF)
+                (#x8FB0D2 #x4F00)
+                (#x8FB0D3 #x4F02)
+                (#x8FB0D4 #x4F03)
+                (#x8FB0D5 #x4F08)
+                (#x8FB0D6 #x4F0B)
+                (#x8FB0D7 #x4F0C)
+                (#x8FB0D8 #x4F12)
+                (#x8FB0D9 #x4F15)
+                (#x8FB0DA #x4F16)
+                (#x8FB0DB #x4F17)
+                (#x8FB0DC #x4F19)
+                (#x8FB0DD #x4F2E)
+                (#x8FB0DE #x4F31)
+                (#x8FB0DF #x4F60)
+                (#x8FB0E0 #x4F33)
+                (#x8FB0E1 #x4F35)
+                (#x8FB0E2 #x4F37)
+                (#x8FB0E3 #x4F39)
+                (#x8FB0E4 #x4F3B)
+                (#x8FB0E5 #x4F3E)
+                (#x8FB0E6 #x4F40)
+                (#x8FB0E7 #x4F42)
+                (#x8FB0E8 #x4F48)
+                (#x8FB0E9 #x4F49)
+                (#x8FB0EA #x4F4B)
+                (#x8FB0EB #x4F4C)
+                (#x8FB0EC #x4F52)
+                (#x8FB0ED #x4F54)
+                (#x8FB0EE #x4F56)
+                (#x8FB0EF #x4F58)
+                (#x8FB0F0 #x4F5F)
+                (#x8FB0F1 #x4F63)
+                (#x8FB0F2 #x4F6A)
+                (#x8FB0F3 #x4F6C)
+                (#x8FB0F4 #x4F6E)
+                (#x8FB0F5 #x4F71)
+                (#x8FB0F6 #x4F77)
+                (#x8FB0F7 #x4F78)
+                (#x8FB0F8 #x4F79)
+                (#x8FB0F9 #x4F7A)
+                (#x8FB0FA #x4F7D)
+                (#x8FB0FB #x4F7E)
+                (#x8FB0FC #x4F81)
+                (#x8FB0FD #x4F82)
+                (#x8FB0FE #x4F84)
+                (#x8FB1A1 #x4F85)
+                (#x8FB1A2 #x4F89)
+                (#x8FB1A3 #x4F8A)
+                (#x8FB1A4 #x4F8C)
+                (#x8FB1A5 #x4F8E)
+                (#x8FB1A6 #x4F90)
+                (#x8FB1A7 #x4F92)
+                (#x8FB1A8 #x4F93)
+                (#x8FB1A9 #x4F94)
+                (#x8FB1AA #x4F97)
+                (#x8FB1AB #x4F99)
+                (#x8FB1AC #x4F9A)
+                (#x8FB1AD #x4F9E)
+                (#x8FB1AE #x4F9F)
+                (#x8FB1AF #x4FB2)
+                (#x8FB1B0 #x4FB7)
+                (#x8FB1B1 #x4FB9)
+                (#x8FB1B2 #x4FBB)
+                (#x8FB1B3 #x4FBC)
+                (#x8FB1B4 #x4FBD)
+                (#x8FB1B5 #x4FBE)
+                (#x8FB1B6 #x4FC0)
+                (#x8FB1B7 #x4FC1)
+                (#x8FB1B8 #x4FC5)
+                (#x8FB1B9 #x4FC6)
+                (#x8FB1BA #x4FC8)
+                (#x8FB1BB #x4FC9)
+                (#x8FB1BC #x4FCB)
+                (#x8FB1BD #x4FCC)
+                (#x8FB1BE #x4FCD)
+                (#x8FB1BF #x4FCF)
+                (#x8FB1C0 #x4FD2)
+                (#x8FB1C1 #x4FDC)
+                (#x8FB1C2 #x4FE0)
+                (#x8FB1C3 #x4FE2)
+                (#x8FB1C4 #x4FF0)
+                (#x8FB1C5 #x4FF2)
+                (#x8FB1C6 #x4FFC)
+                (#x8FB1C7 #x4FFD)
+                (#x8FB1C8 #x4FFF)
+                (#x8FB1C9 #x5000)
+                (#x8FB1CA #x5001)
+                (#x8FB1CB #x5004)
+                (#x8FB1CC #x5007)
+                (#x8FB1CD #x500A)
+                (#x8FB1CE #x500C)
+                (#x8FB1CF #x500E)
+                (#x8FB1D0 #x5010)
+                (#x8FB1D1 #x5013)
+                (#x8FB1D2 #x5017)
+                (#x8FB1D3 #x5018)
+                (#x8FB1D4 #x501B)
+                (#x8FB1D5 #x501C)
+                (#x8FB1D6 #x501D)
+                (#x8FB1D7 #x501E)
+                (#x8FB1D8 #x5022)
+                (#x8FB1D9 #x5027)
+                (#x8FB1DA #x502E)
+                (#x8FB1DB #x5030)
+                (#x8FB1DC #x5032)
+                (#x8FB1DD #x5033)
+                (#x8FB1DE #x5035)
+                (#x8FB1DF #x5040)
+                (#x8FB1E0 #x5041)
+                (#x8FB1E1 #x5042)
+                (#x8FB1E2 #x5045)
+                (#x8FB1E3 #x5046)
+                (#x8FB1E4 #x504A)
+                (#x8FB1E5 #x504C)
+                (#x8FB1E6 #x504E)
+                (#x8FB1E7 #x5051)
+                (#x8FB1E8 #x5052)
+                (#x8FB1E9 #x5053)
+                (#x8FB1EA #x5057)
+                (#x8FB1EB #x5059)
+                (#x8FB1EC #x505F)
+                (#x8FB1ED #x5060)
+                (#x8FB1EE #x5062)
+                (#x8FB1EF #x5063)
+                (#x8FB1F0 #x5066)
+                (#x8FB1F1 #x5067)
+                (#x8FB1F2 #x506A)
+                (#x8FB1F3 #x506D)
+                (#x8FB1F4 #x5070)
+                (#x8FB1F5 #x5071)
+                (#x8FB1F6 #x503B)
+                (#x8FB1F7 #x5081)
+                (#x8FB1F8 #x5083)
+                (#x8FB1F9 #x5084)
+                (#x8FB1FA #x5086)
+                (#x8FB1FB #x508A)
+                (#x8FB1FC #x508E)
+                (#x8FB1FD #x508F)
+                (#x8FB1FE #x5090)
+                (#x8FB2A1 #x5092)
+                (#x8FB2A2 #x5093)
+                (#x8FB2A3 #x5094)
+                (#x8FB2A4 #x5096)
+                (#x8FB2A5 #x509B)
+                (#x8FB2A6 #x509C)
+                (#x8FB2A7 #x509E)
+                (#x8FB2A8 #x509F)
+                (#x8FB2A9 #x50A0)
+                (#x8FB2AA #x50A1)
+                (#x8FB2AB #x50A2)
+                (#x8FB2AC #x50AA)
+                (#x8FB2AD #x50AF)
+                (#x8FB2AE #x50B0)
+                (#x8FB2AF #x50B9)
+                (#x8FB2B0 #x50BA)
+                (#x8FB2B1 #x50BD)
+                (#x8FB2B2 #x50C0)
+                (#x8FB2B3 #x50C3)
+                (#x8FB2B4 #x50C4)
+                (#x8FB2B5 #x50C7)
+                (#x8FB2B6 #x50CC)
+                (#x8FB2B7 #x50CE)
+                (#x8FB2B8 #x50D0)
+                (#x8FB2B9 #x50D3)
+                (#x8FB2BA #x50D4)
+                (#x8FB2BB #x50D8)
+                (#x8FB2BC #x50DC)
+                (#x8FB2BD #x50DD)
+                (#x8FB2BE #x50DF)
+                (#x8FB2BF #x50E2)
+                (#x8FB2C0 #x50E4)
+                (#x8FB2C1 #x50E6)
+                (#x8FB2C2 #x50E8)
+                (#x8FB2C3 #x50E9)
+                (#x8FB2C4 #x50EF)
+                (#x8FB2C5 #x50F1)
+                (#x8FB2C6 #x50F6)
+                (#x8FB2C7 #x50FA)
+                (#x8FB2C8 #x50FE)
+                (#x8FB2C9 #x5103)
+                (#x8FB2CA #x5106)
+                (#x8FB2CB #x5107)
+                (#x8FB2CC #x5108)
+                (#x8FB2CD #x510B)
+                (#x8FB2CE #x510C)
+                (#x8FB2CF #x510D)
+                (#x8FB2D0 #x510E)
+                (#x8FB2D1 #x50F2)
+                (#x8FB2D2 #x5110)
+                (#x8FB2D3 #x5117)
+                (#x8FB2D4 #x5119)
+                (#x8FB2D5 #x511B)
+                (#x8FB2D6 #x511C)
+                (#x8FB2D7 #x511D)
+                (#x8FB2D8 #x511E)
+                (#x8FB2D9 #x5123)
+                (#x8FB2DA #x5127)
+                (#x8FB2DB #x5128)
+                (#x8FB2DC #x512C)
+                (#x8FB2DD #x512D)
+                (#x8FB2DE #x512F)
+                (#x8FB2DF #x5131)
+                (#x8FB2E0 #x5133)
+                (#x8FB2E1 #x5134)
+                (#x8FB2E2 #x5135)
+                (#x8FB2E3 #x5138)
+                (#x8FB2E4 #x5139)
+                (#x8FB2E5 #x5142)
+                (#x8FB2E6 #x514A)
+                (#x8FB2E7 #x514F)
+                (#x8FB2E8 #x5153)
+                (#x8FB2E9 #x5155)
+                (#x8FB2EA #x5157)
+                (#x8FB2EB #x5158)
+                (#x8FB2EC #x515F)
+                (#x8FB2ED #x5164)
+                (#x8FB2EE #x5166)
+                (#x8FB2EF #x517E)
+                (#x8FB2F0 #x5183)
+                (#x8FB2F1 #x5184)
+                (#x8FB2F2 #x518B)
+                (#x8FB2F3 #x518E)
+                (#x8FB2F4 #x5198)
+                (#x8FB2F5 #x519D)
+                (#x8FB2F6 #x51A1)
+                (#x8FB2F7 #x51A3)
+                (#x8FB2F8 #x51AD)
+                (#x8FB2F9 #x51B8)
+                (#x8FB2FA #x51BA)
+                (#x8FB2FB #x51BC)
+                (#x8FB2FC #x51BE)
+                (#x8FB2FD #x51BF)
+                (#x8FB2FE #x51C2)
+                (#x8FB3A1 #x51C8)
+                (#x8FB3A2 #x51CF)
+                (#x8FB3A3 #x51D1)
+                (#x8FB3A4 #x51D2)
+                (#x8FB3A5 #x51D3)
+                (#x8FB3A6 #x51D5)
+                (#x8FB3A7 #x51D8)
+                (#x8FB3A8 #x51DE)
+                (#x8FB3A9 #x51E2)
+                (#x8FB3AA #x51E5)
+                (#x8FB3AB #x51EE)
+                (#x8FB3AC #x51F2)
+                (#x8FB3AD #x51F3)
+                (#x8FB3AE #x51F4)
+                (#x8FB3AF #x51F7)
+                (#x8FB3B0 #x5201)
+                (#x8FB3B1 #x5202)
+                (#x8FB3B2 #x5205)
+                (#x8FB3B3 #x5212)
+                (#x8FB3B4 #x5213)
+                (#x8FB3B5 #x5215)
+                (#x8FB3B6 #x5216)
+                (#x8FB3B7 #x5218)
+                (#x8FB3B8 #x5222)
+                (#x8FB3B9 #x5228)
+                (#x8FB3BA #x5231)
+                (#x8FB3BB #x5232)
+                (#x8FB3BC #x5235)
+                (#x8FB3BD #x523C)
+                (#x8FB3BE #x5245)
+                (#x8FB3BF #x5249)
+                (#x8FB3C0 #x5255)
+                (#x8FB3C1 #x5257)
+                (#x8FB3C2 #x5258)
+                (#x8FB3C3 #x525A)
+                (#x8FB3C4 #x525C)
+                (#x8FB3C5 #x525F)
+                (#x8FB3C6 #x5260)
+                (#x8FB3C7 #x5261)
+                (#x8FB3C8 #x5266)
+                (#x8FB3C9 #x526E)
+                (#x8FB3CA #x5277)
+                (#x8FB3CB #x5278)
+                (#x8FB3CC #x5279)
+                (#x8FB3CD #x5280)
+                (#x8FB3CE #x5282)
+                (#x8FB3CF #x5285)
+                (#x8FB3D0 #x528A)
+                (#x8FB3D1 #x528C)
+                (#x8FB3D2 #x5293)
+                (#x8FB3D3 #x5295)
+                (#x8FB3D4 #x5296)
+                (#x8FB3D5 #x5297)
+                (#x8FB3D6 #x5298)
+                (#x8FB3D7 #x529A)
+                (#x8FB3D8 #x529C)
+                (#x8FB3D9 #x52A4)
+                (#x8FB3DA #x52A5)
+                (#x8FB3DB #x52A6)
+                (#x8FB3DC #x52A7)
+                (#x8FB3DD #x52AF)
+                (#x8FB3DE #x52B0)
+                (#x8FB3DF #x52B6)
+                (#x8FB3E0 #x52B7)
+                (#x8FB3E1 #x52B8)
+                (#x8FB3E2 #x52BA)
+                (#x8FB3E3 #x52BB)
+                (#x8FB3E4 #x52BD)
+                (#x8FB3E5 #x52C0)
+                (#x8FB3E6 #x52C4)
+                (#x8FB3E7 #x52C6)
+                (#x8FB3E8 #x52C8)
+                (#x8FB3E9 #x52CC)
+                (#x8FB3EA #x52CF)
+                (#x8FB3EB #x52D1)
+                (#x8FB3EC #x52D4)
+                (#x8FB3ED #x52D6)
+                (#x8FB3EE #x52DB)
+                (#x8FB3EF #x52DC)
+                (#x8FB3F0 #x52E1)
+                (#x8FB3F1 #x52E5)
+                (#x8FB3F2 #x52E8)
+                (#x8FB3F3 #x52E9)
+                (#x8FB3F4 #x52EA)
+                (#x8FB3F5 #x52EC)
+                (#x8FB3F6 #x52F0)
+                (#x8FB3F7 #x52F1)
+                (#x8FB3F8 #x52F4)
+                (#x8FB3F9 #x52F6)
+                (#x8FB3FA #x52F7)
+                (#x8FB3FB #x5300)
+                (#x8FB3FC #x5303)
+                (#x8FB3FD #x530A)
+                (#x8FB3FE #x530B)
+                (#x8FB4A1 #x530C)
+                (#x8FB4A2 #x5311)
+                (#x8FB4A3 #x5313)
+                (#x8FB4A4 #x5318)
+                (#x8FB4A5 #x531B)
+                (#x8FB4A6 #x531C)
+                (#x8FB4A7 #x531E)
+                (#x8FB4A8 #x531F)
+                (#x8FB4A9 #x5325)
+                (#x8FB4AA #x5327)
+                (#x8FB4AB #x5328)
+                (#x8FB4AC #x5329)
+                (#x8FB4AD #x532B)
+                (#x8FB4AE #x532C)
+                (#x8FB4AF #x532D)
+                (#x8FB4B0 #x5330)
+                (#x8FB4B1 #x5332)
+                (#x8FB4B2 #x5335)
+                (#x8FB4B3 #x533C)
+                (#x8FB4B4 #x533D)
+                (#x8FB4B5 #x533E)
+                (#x8FB4B6 #x5342)
+                (#x8FB4B7 #x534C)
+                (#x8FB4B8 #x534B)
+                (#x8FB4B9 #x5359)
+                (#x8FB4BA #x535B)
+                (#x8FB4BB #x5361)
+                (#x8FB4BC #x5363)
+                (#x8FB4BD #x5365)
+                (#x8FB4BE #x536C)
+                (#x8FB4BF #x536D)
+                (#x8FB4C0 #x5372)
+                (#x8FB4C1 #x5379)
+                (#x8FB4C2 #x537E)
+                (#x8FB4C3 #x5383)
+                (#x8FB4C4 #x5387)
+                (#x8FB4C5 #x5388)
+                (#x8FB4C6 #x538E)
+                (#x8FB4C7 #x5393)
+                (#x8FB4C8 #x5394)
+                (#x8FB4C9 #x5399)
+                (#x8FB4CA #x539D)
+                (#x8FB4CB #x53A1)
+                (#x8FB4CC #x53A4)
+                (#x8FB4CD #x53AA)
+                (#x8FB4CE #x53AB)
+                (#x8FB4CF #x53AF)
+                (#x8FB4D0 #x53B2)
+                (#x8FB4D1 #x53B4)
+                (#x8FB4D2 #x53B5)
+                (#x8FB4D3 #x53B7)
+                (#x8FB4D4 #x53B8)
+                (#x8FB4D5 #x53BA)
+                (#x8FB4D6 #x53BD)
+                (#x8FB4D7 #x53C0)
+                (#x8FB4D8 #x53C5)
+                (#x8FB4D9 #x53CF)
+                (#x8FB4DA #x53D2)
+                (#x8FB4DB #x53D3)
+                (#x8FB4DC #x53D5)
+                (#x8FB4DD #x53DA)
+                (#x8FB4DE #x53DD)
+                (#x8FB4DF #x53DE)
+                (#x8FB4E0 #x53E0)
+                (#x8FB4E1 #x53E6)
+                (#x8FB4E2 #x53E7)
+                (#x8FB4E3 #x53F5)
+                (#x8FB4E4 #x5402)
+                (#x8FB4E5 #x5413)
+                (#x8FB4E6 #x541A)
+                (#x8FB4E7 #x5421)
+                (#x8FB4E8 #x5427)
+                (#x8FB4E9 #x5428)
+                (#x8FB4EA #x542A)
+                (#x8FB4EB #x542F)
+                (#x8FB4EC #x5431)
+                (#x8FB4ED #x5434)
+                (#x8FB4EE #x5435)
+                (#x8FB4EF #x5443)
+                (#x8FB4F0 #x5444)
+                (#x8FB4F1 #x5447)
+                (#x8FB4F2 #x544D)
+                (#x8FB4F3 #x544F)
+                (#x8FB4F4 #x545E)
+                (#x8FB4F5 #x5462)
+                (#x8FB4F6 #x5464)
+                (#x8FB4F7 #x5466)
+                (#x8FB4F8 #x5467)
+                (#x8FB4F9 #x5469)
+                (#x8FB4FA #x546B)
+                (#x8FB4FB #x546D)
+                (#x8FB4FC #x546E)
+                (#x8FB4FD #x5474)
+                (#x8FB4FE #x547F)
+                (#x8FB5A1 #x5481)
+                (#x8FB5A2 #x5483)
+                (#x8FB5A3 #x5485)
+                (#x8FB5A4 #x5488)
+                (#x8FB5A5 #x5489)
+                (#x8FB5A6 #x548D)
+                (#x8FB5A7 #x5491)
+                (#x8FB5A8 #x5495)
+                (#x8FB5A9 #x5496)
+                (#x8FB5AA #x549C)
+                (#x8FB5AB #x549F)
+                (#x8FB5AC #x54A1)
+                (#x8FB5AD #x54A6)
+                (#x8FB5AE #x54A7)
+                (#x8FB5AF #x54A9)
+                (#x8FB5B0 #x54AA)
+                (#x8FB5B1 #x54AD)
+                (#x8FB5B2 #x54AE)
+                (#x8FB5B3 #x54B1)
+                (#x8FB5B4 #x54B7)
+                (#x8FB5B5 #x54B9)
+                (#x8FB5B6 #x54BA)
+                (#x8FB5B7 #x54BB)
+                (#x8FB5B8 #x54BF)
+                (#x8FB5B9 #x54C6)
+                (#x8FB5BA #x54CA)
+                (#x8FB5BB #x54CD)
+                (#x8FB5BC #x54CE)
+                (#x8FB5BD #x54E0)
+                (#x8FB5BE #x54EA)
+                (#x8FB5BF #x54EC)
+                (#x8FB5C0 #x54EF)
+                (#x8FB5C1 #x54F6)
+                (#x8FB5C2 #x54FC)
+                (#x8FB5C3 #x54FE)
+                (#x8FB5C4 #x54FF)
+                (#x8FB5C5 #x5500)
+                (#x8FB5C6 #x5501)
+                (#x8FB5C7 #x5505)
+                (#x8FB5C8 #x5508)
+                (#x8FB5C9 #x5509)
+                (#x8FB5CA #x550C)
+                (#x8FB5CB #x550D)
+                (#x8FB5CC #x550E)
+                (#x8FB5CD #x5515)
+                (#x8FB5CE #x552A)
+                (#x8FB5CF #x552B)
+                (#x8FB5D0 #x5532)
+                (#x8FB5D1 #x5535)
+                (#x8FB5D2 #x5536)
+                (#x8FB5D3 #x553B)
+                (#x8FB5D4 #x553C)
+                (#x8FB5D5 #x553D)
+                (#x8FB5D6 #x5541)
+                (#x8FB5D7 #x5547)
+                (#x8FB5D8 #x5549)
+                (#x8FB5D9 #x554A)
+                (#x8FB5DA #x554D)
+                (#x8FB5DB #x5550)
+                (#x8FB5DC #x5551)
+                (#x8FB5DD #x5558)
+                (#x8FB5DE #x555A)
+                (#x8FB5DF #x555B)
+                (#x8FB5E0 #x555E)
+                (#x8FB5E1 #x5560)
+                (#x8FB5E2 #x5561)
+                (#x8FB5E3 #x5564)
+                (#x8FB5E4 #x5566)
+                (#x8FB5E5 #x557F)
+                (#x8FB5E6 #x5581)
+                (#x8FB5E7 #x5582)
+                (#x8FB5E8 #x5586)
+                (#x8FB5E9 #x5588)
+                (#x8FB5EA #x558E)
+                (#x8FB5EB #x558F)
+                (#x8FB5EC #x5591)
+                (#x8FB5ED #x5592)
+                (#x8FB5EE #x5593)
+                (#x8FB5EF #x5594)
+                (#x8FB5F0 #x5597)
+                (#x8FB5F1 #x55A3)
+                (#x8FB5F2 #x55A4)
+                (#x8FB5F3 #x55AD)
+                (#x8FB5F4 #x55B2)
+                (#x8FB5F5 #x55BF)
+                (#x8FB5F6 #x55C1)
+                (#x8FB5F7 #x55C3)
+                (#x8FB5F8 #x55C6)
+                (#x8FB5F9 #x55C9)
+                (#x8FB5FA #x55CB)
+                (#x8FB5FB #x55CC)
+                (#x8FB5FC #x55CE)
+                (#x8FB5FD #x55D1)
+                (#x8FB5FE #x55D2)
+                (#x8FB6A1 #x55D3)
+                (#x8FB6A2 #x55D7)
+                (#x8FB6A3 #x55D8)
+                (#x8FB6A4 #x55DB)
+                (#x8FB6A5 #x55DE)
+                (#x8FB6A6 #x55E2)
+                (#x8FB6A7 #x55E9)
+                (#x8FB6A8 #x55F6)
+                (#x8FB6A9 #x55FF)
+                (#x8FB6AA #x5605)
+                (#x8FB6AB #x5608)
+                (#x8FB6AC #x560A)
+                (#x8FB6AD #x560D)
+                (#x8FB6AE #x560E)
+                (#x8FB6AF #x560F)
+                (#x8FB6B0 #x5610)
+                (#x8FB6B1 #x5611)
+                (#x8FB6B2 #x5612)
+                (#x8FB6B3 #x5619)
+                (#x8FB6B4 #x562C)
+                (#x8FB6B5 #x5630)
+                (#x8FB6B6 #x5633)
+                (#x8FB6B7 #x5635)
+                (#x8FB6B8 #x5637)
+                (#x8FB6B9 #x5639)
+                (#x8FB6BA #x563B)
+                (#x8FB6BB #x563C)
+                (#x8FB6BC #x563D)
+                (#x8FB6BD #x563F)
+                (#x8FB6BE #x5640)
+                (#x8FB6BF #x5641)
+                (#x8FB6C0 #x5643)
+                (#x8FB6C1 #x5644)
+                (#x8FB6C2 #x5646)
+                (#x8FB6C3 #x5649)
+                (#x8FB6C4 #x564B)
+                (#x8FB6C5 #x564D)
+                (#x8FB6C6 #x564F)
+                (#x8FB6C7 #x5654)
+                (#x8FB6C8 #x565E)
+                (#x8FB6C9 #x5660)
+                (#x8FB6CA #x5661)
+                (#x8FB6CB #x5662)
+                (#x8FB6CC #x5663)
+                (#x8FB6CD #x5666)
+                (#x8FB6CE #x5669)
+                (#x8FB6CF #x566D)
+                (#x8FB6D0 #x566F)
+                (#x8FB6D1 #x5671)
+                (#x8FB6D2 #x5672)
+                (#x8FB6D3 #x5675)
+                (#x8FB6D4 #x5684)
+                (#x8FB6D5 #x5685)
+                (#x8FB6D6 #x5688)
+                (#x8FB6D7 #x568B)
+                (#x8FB6D8 #x568C)
+                (#x8FB6D9 #x5695)
+                (#x8FB6DA #x5699)
+                (#x8FB6DB #x569A)
+                (#x8FB6DC #x569D)
+                (#x8FB6DD #x569E)
+                (#x8FB6DE #x569F)
+                (#x8FB6DF #x56A6)
+                (#x8FB6E0 #x56A7)
+                (#x8FB6E1 #x56A8)
+                (#x8FB6E2 #x56A9)
+                (#x8FB6E3 #x56AB)
+                (#x8FB6E4 #x56AC)
+                (#x8FB6E5 #x56AD)
+                (#x8FB6E6 #x56B1)
+                (#x8FB6E7 #x56B3)
+                (#x8FB6E8 #x56B7)
+                (#x8FB6E9 #x56BE)
+                (#x8FB6EA #x56C5)
+                (#x8FB6EB #x56C9)
+                (#x8FB6EC #x56CA)
+                (#x8FB6ED #x56CB)
+                (#x8FB6EE #x56CF)
+                (#x8FB6EF #x56D0)
+                (#x8FB6F0 #x56CC)
+                (#x8FB6F1 #x56CD)
+                (#x8FB6F2 #x56D9)
+                (#x8FB6F3 #x56DC)
+                (#x8FB6F4 #x56DD)
+                (#x8FB6F5 #x56DF)
+                (#x8FB6F6 #x56E1)
+                (#x8FB6F7 #x56E4)
+                (#x8FB6F8 #x56E5)
+                (#x8FB6F9 #x56E6)
+                (#x8FB6FA #x56E7)
+                (#x8FB6FB #x56E8)
+                (#x8FB6FC #x56F1)
+                (#x8FB6FD #x56EB)
+                (#x8FB6FE #x56ED)
+                (#x8FB7A1 #x56F6)
+                (#x8FB7A2 #x56F7)
+                (#x8FB7A3 #x5701)
+                (#x8FB7A4 #x5702)
+                (#x8FB7A5 #x5707)
+                (#x8FB7A6 #x570A)
+                (#x8FB7A7 #x570C)
+                (#x8FB7A8 #x5711)
+                (#x8FB7A9 #x5715)
+                (#x8FB7AA #x571A)
+                (#x8FB7AB #x571B)
+                (#x8FB7AC #x571D)
+                (#x8FB7AD #x5720)
+                (#x8FB7AE #x5722)
+                (#x8FB7AF #x5723)
+                (#x8FB7B0 #x5724)
+                (#x8FB7B1 #x5725)
+                (#x8FB7B2 #x5729)
+                (#x8FB7B3 #x572A)
+                (#x8FB7B4 #x572C)
+                (#x8FB7B5 #x572E)
+                (#x8FB7B6 #x572F)
+                (#x8FB7B7 #x5733)
+                (#x8FB7B8 #x5734)
+                (#x8FB7B9 #x573D)
+                (#x8FB7BA #x573E)
+                (#x8FB7BB #x573F)
+                (#x8FB7BC #x5745)
+                (#x8FB7BD #x5746)
+                (#x8FB7BE #x574C)
+                (#x8FB7BF #x574D)
+                (#x8FB7C0 #x5752)
+                (#x8FB7C1 #x5762)
+                (#x8FB7C2 #x5765)
+                (#x8FB7C3 #x5767)
+                (#x8FB7C4 #x5768)
+                (#x8FB7C5 #x576B)
+                (#x8FB7C6 #x576D)
+                (#x8FB7C7 #x576E)
+                (#x8FB7C8 #x576F)
+                (#x8FB7C9 #x5770)
+                (#x8FB7CA #x5771)
+                (#x8FB7CB #x5773)
+                (#x8FB7CC #x5774)
+                (#x8FB7CD #x5775)
+                (#x8FB7CE #x5777)
+                (#x8FB7CF #x5779)
+                (#x8FB7D0 #x577A)
+                (#x8FB7D1 #x577B)
+                (#x8FB7D2 #x577C)
+                (#x8FB7D3 #x577E)
+                (#x8FB7D4 #x5781)
+                (#x8FB7D5 #x5783)
+                (#x8FB7D6 #x578C)
+                (#x8FB7D7 #x5794)
+                (#x8FB7D8 #x5797)
+                (#x8FB7D9 #x5799)
+                (#x8FB7DA #x579A)
+                (#x8FB7DB #x579C)
+                (#x8FB7DC #x579D)
+                (#x8FB7DD #x579E)
+                (#x8FB7DE #x579F)
+                (#x8FB7DF #x57A1)
+                (#x8FB7E0 #x5795)
+                (#x8FB7E1 #x57A7)
+                (#x8FB7E2 #x57A8)
+                (#x8FB7E3 #x57A9)
+                (#x8FB7E4 #x57AC)
+                (#x8FB7E5 #x57B8)
+                (#x8FB7E6 #x57BD)
+                (#x8FB7E7 #x57C7)
+                (#x8FB7E8 #x57C8)
+                (#x8FB7E9 #x57CC)
+                (#x8FB7EA #x57CF)
+                (#x8FB7EB #x57D5)
+                (#x8FB7EC #x57DD)
+                (#x8FB7ED #x57DE)
+                (#x8FB7EE #x57E4)
+                (#x8FB7EF #x57E6)
+                (#x8FB7F0 #x57E7)
+                (#x8FB7F1 #x57E9)
+                (#x8FB7F2 #x57ED)
+                (#x8FB7F3 #x57F0)
+                (#x8FB7F4 #x57F5)
+                (#x8FB7F5 #x57F6)
+                (#x8FB7F6 #x57F8)
+                (#x8FB7F7 #x57FD)
+                (#x8FB7F8 #x57FE)
+                (#x8FB7F9 #x57FF)
+                (#x8FB7FA #x5803)
+                (#x8FB7FB #x5804)
+                (#x8FB7FC #x5808)
+                (#x8FB7FD #x5809)
+                (#x8FB7FE #x57E1)
+                (#x8FB8A1 #x580C)
+                (#x8FB8A2 #x580D)
+                (#x8FB8A3 #x581B)
+                (#x8FB8A4 #x581E)
+                (#x8FB8A5 #x581F)
+                (#x8FB8A6 #x5820)
+                (#x8FB8A7 #x5826)
+                (#x8FB8A8 #x5827)
+                (#x8FB8A9 #x582D)
+                (#x8FB8AA #x5832)
+                (#x8FB8AB #x5839)
+                (#x8FB8AC #x583F)
+                (#x8FB8AD #x5849)
+                (#x8FB8AE #x584C)
+                (#x8FB8AF #x584D)
+                (#x8FB8B0 #x584F)
+                (#x8FB8B1 #x5850)
+                (#x8FB8B2 #x5855)
+                (#x8FB8B3 #x585F)
+                (#x8FB8B4 #x5861)
+                (#x8FB8B5 #x5864)
+                (#x8FB8B6 #x5867)
+                (#x8FB8B7 #x5868)
+                (#x8FB8B8 #x5878)
+                (#x8FB8B9 #x587C)
+                (#x8FB8BA #x587F)
+                (#x8FB8BB #x5880)
+                (#x8FB8BC #x5881)
+                (#x8FB8BD #x5887)
+                (#x8FB8BE #x5888)
+                (#x8FB8BF #x5889)
+                (#x8FB8C0 #x588A)
+                (#x8FB8C1 #x588C)
+                (#x8FB8C2 #x588D)
+                (#x8FB8C3 #x588F)
+                (#x8FB8C4 #x5890)
+                (#x8FB8C5 #x5894)
+                (#x8FB8C6 #x5896)
+                (#x8FB8C7 #x589D)
+                (#x8FB8C8 #x58A0)
+                (#x8FB8C9 #x58A1)
+                (#x8FB8CA #x58A2)
+                (#x8FB8CB #x58A6)
+                (#x8FB8CC #x58A9)
+                (#x8FB8CD #x58B1)
+                (#x8FB8CE #x58B2)
+                (#x8FB8CF #x58C4)
+                (#x8FB8D0 #x58BC)
+                (#x8FB8D1 #x58C2)
+                (#x8FB8D2 #x58C8)
+                (#x8FB8D3 #x58CD)
+                (#x8FB8D4 #x58CE)
+                (#x8FB8D5 #x58D0)
+                (#x8FB8D6 #x58D2)
+                (#x8FB8D7 #x58D4)
+                (#x8FB8D8 #x58D6)
+                (#x8FB8D9 #x58DA)
+                (#x8FB8DA #x58DD)
+                (#x8FB8DB #x58E1)
+                (#x8FB8DC #x58E2)
+                (#x8FB8DD #x58E9)
+                (#x8FB8DE #x58F3)
+                (#x8FB8DF #x5905)
+                (#x8FB8E0 #x5906)
+                (#x8FB8E1 #x590B)
+                (#x8FB8E2 #x590C)
+                (#x8FB8E3 #x5912)
+                (#x8FB8E4 #x5913)
+                (#x8FB8E5 #x5914)
+                (#x8FB8E6 #x8641)
+                (#x8FB8E7 #x591D)
+                (#x8FB8E8 #x5921)
+                (#x8FB8E9 #x5923)
+                (#x8FB8EA #x5924)
+                (#x8FB8EB #x5928)
+                (#x8FB8EC #x592F)
+                (#x8FB8ED #x5930)
+                (#x8FB8EE #x5933)
+                (#x8FB8EF #x5935)
+                (#x8FB8F0 #x5936)
+                (#x8FB8F1 #x593F)
+                (#x8FB8F2 #x5943)
+                (#x8FB8F3 #x5946)
+                (#x8FB8F4 #x5952)
+                (#x8FB8F5 #x5953)
+                (#x8FB8F6 #x5959)
+                (#x8FB8F7 #x595B)
+                (#x8FB8F8 #x595D)
+                (#x8FB8F9 #x595E)
+                (#x8FB8FA #x595F)
+                (#x8FB8FB #x5961)
+                (#x8FB8FC #x5963)
+                (#x8FB8FD #x596B)
+                (#x8FB8FE #x596D)
+                (#x8FB9A1 #x596F)
+                (#x8FB9A2 #x5972)
+                (#x8FB9A3 #x5975)
+                (#x8FB9A4 #x5976)
+                (#x8FB9A5 #x5979)
+                (#x8FB9A6 #x597B)
+                (#x8FB9A7 #x597C)
+                (#x8FB9A8 #x598B)
+                (#x8FB9A9 #x598C)
+                (#x8FB9AA #x598E)
+                (#x8FB9AB #x5992)
+                (#x8FB9AC #x5995)
+                (#x8FB9AD #x5997)
+                (#x8FB9AE #x599F)
+                (#x8FB9AF #x59A4)
+                (#x8FB9B0 #x59A7)
+                (#x8FB9B1 #x59AD)
+                (#x8FB9B2 #x59AE)
+                (#x8FB9B3 #x59AF)
+                (#x8FB9B4 #x59B0)
+                (#x8FB9B5 #x59B3)
+                (#x8FB9B6 #x59B7)
+                (#x8FB9B7 #x59BA)
+                (#x8FB9B8 #x59BC)
+                (#x8FB9B9 #x59C1)
+                (#x8FB9BA #x59C3)
+                (#x8FB9BB #x59C4)
+                (#x8FB9BC #x59C8)
+                (#x8FB9BD #x59CA)
+                (#x8FB9BE #x59CD)
+                (#x8FB9BF #x59D2)
+                (#x8FB9C0 #x59DD)
+                (#x8FB9C1 #x59DE)
+                (#x8FB9C2 #x59DF)
+                (#x8FB9C3 #x59E3)
+                (#x8FB9C4 #x59E4)
+                (#x8FB9C5 #x59E7)
+                (#x8FB9C6 #x59EE)
+                (#x8FB9C7 #x59EF)
+                (#x8FB9C8 #x59F1)
+                (#x8FB9C9 #x59F2)
+                (#x8FB9CA #x59F4)
+                (#x8FB9CB #x59F7)
+                (#x8FB9CC #x5A00)
+                (#x8FB9CD #x5A04)
+                (#x8FB9CE #x5A0C)
+                (#x8FB9CF #x5A0D)
+                (#x8FB9D0 #x5A0E)
+                (#x8FB9D1 #x5A12)
+                (#x8FB9D2 #x5A13)
+                (#x8FB9D3 #x5A1E)
+                (#x8FB9D4 #x5A23)
+                (#x8FB9D5 #x5A24)
+                (#x8FB9D6 #x5A27)
+                (#x8FB9D7 #x5A28)
+                (#x8FB9D8 #x5A2A)
+                (#x8FB9D9 #x5A2D)
+                (#x8FB9DA #x5A30)
+                (#x8FB9DB #x5A44)
+                (#x8FB9DC #x5A45)
+                (#x8FB9DD #x5A47)
+                (#x8FB9DE #x5A48)
+                (#x8FB9DF #x5A4C)
+                (#x8FB9E0 #x5A50)
+                (#x8FB9E1 #x5A55)
+                (#x8FB9E2 #x5A5E)
+                (#x8FB9E3 #x5A63)
+                (#x8FB9E4 #x5A65)
+                (#x8FB9E5 #x5A67)
+                (#x8FB9E6 #x5A6D)
+                (#x8FB9E7 #x5A77)
+                (#x8FB9E8 #x5A7A)
+                (#x8FB9E9 #x5A7B)
+                (#x8FB9EA #x5A7E)
+                (#x8FB9EB #x5A8B)
+                (#x8FB9EC #x5A90)
+                (#x8FB9ED #x5A93)
+                (#x8FB9EE #x5A96)
+                (#x8FB9EF #x5A99)
+                (#x8FB9F0 #x5A9C)
+                (#x8FB9F1 #x5A9E)
+                (#x8FB9F2 #x5A9F)
+                (#x8FB9F3 #x5AA0)
+                (#x8FB9F4 #x5AA2)
+                (#x8FB9F5 #x5AA7)
+                (#x8FB9F6 #x5AAC)
+                (#x8FB9F7 #x5AB1)
+                (#x8FB9F8 #x5AB2)
+                (#x8FB9F9 #x5AB3)
+                (#x8FB9FA #x5AB5)
+                (#x8FB9FB #x5AB8)
+                (#x8FB9FC #x5ABA)
+                (#x8FB9FD #x5ABB)
+                (#x8FB9FE #x5ABF)
+                (#x8FBAA1 #x5AC4)
+                (#x8FBAA2 #x5AC6)
+                (#x8FBAA3 #x5AC8)
+                (#x8FBAA4 #x5ACF)
+                (#x8FBAA5 #x5ADA)
+                (#x8FBAA6 #x5ADC)
+                (#x8FBAA7 #x5AE0)
+                (#x8FBAA8 #x5AE5)
+                (#x8FBAA9 #x5AEA)
+                (#x8FBAAA #x5AEE)
+                (#x8FBAAB #x5AF5)
+                (#x8FBAAC #x5AF6)
+                (#x8FBAAD #x5AFD)
+                (#x8FBAAE #x5B00)
+                (#x8FBAAF #x5B01)
+                (#x8FBAB0 #x5B08)
+                (#x8FBAB1 #x5B17)
+                (#x8FBAB2 #x5B34)
+                (#x8FBAB3 #x5B19)
+                (#x8FBAB4 #x5B1B)
+                (#x8FBAB5 #x5B1D)
+                (#x8FBAB6 #x5B21)
+                (#x8FBAB7 #x5B25)
+                (#x8FBAB8 #x5B2D)
+                (#x8FBAB9 #x5B38)
+                (#x8FBABA #x5B41)
+                (#x8FBABB #x5B4B)
+                (#x8FBABC #x5B4C)
+                (#x8FBABD #x5B52)
+                (#x8FBABE #x5B56)
+                (#x8FBABF #x5B5E)
+                (#x8FBAC0 #x5B68)
+                (#x8FBAC1 #x5B6E)
+                (#x8FBAC2 #x5B6F)
+                (#x8FBAC3 #x5B7C)
+                (#x8FBAC4 #x5B7D)
+                (#x8FBAC5 #x5B7E)
+                (#x8FBAC6 #x5B7F)
+                (#x8FBAC7 #x5B81)
+                (#x8FBAC8 #x5B84)
+                (#x8FBAC9 #x5B86)
+                (#x8FBACA #x5B8A)
+                (#x8FBACB #x5B8E)
+                (#x8FBACC #x5B90)
+                (#x8FBACD #x5B91)
+                (#x8FBACE #x5B93)
+                (#x8FBACF #x5B94)
+                (#x8FBAD0 #x5B96)
+                (#x8FBAD1 #x5BA8)
+                (#x8FBAD2 #x5BA9)
+                (#x8FBAD3 #x5BAC)
+                (#x8FBAD4 #x5BAD)
+                (#x8FBAD5 #x5BAF)
+                (#x8FBAD6 #x5BB1)
+                (#x8FBAD7 #x5BB2)
+                (#x8FBAD8 #x5BB7)
+                (#x8FBAD9 #x5BBA)
+                (#x8FBADA #x5BBC)
+                (#x8FBADB #x5BC0)
+                (#x8FBADC #x5BC1)
+                (#x8FBADD #x5BCD)
+                (#x8FBADE #x5BCF)
+                (#x8FBADF #x5BD6)
+                (#x8FBAE0 #x5BD7)
+                (#x8FBAE1 #x5BD8)
+                (#x8FBAE2 #x5BD9)
+                (#x8FBAE3 #x5BDA)
+                (#x8FBAE4 #x5BE0)
+                (#x8FBAE5 #x5BEF)
+                (#x8FBAE6 #x5BF1)
+                (#x8FBAE7 #x5BF4)
+                (#x8FBAE8 #x5BFD)
+                (#x8FBAE9 #x5C0C)
+                (#x8FBAEA #x5C17)
+                (#x8FBAEB #x5C1E)
+                (#x8FBAEC #x5C1F)
+                (#x8FBAED #x5C23)
+                (#x8FBAEE #x5C26)
+                (#x8FBAEF #x5C29)
+                (#x8FBAF0 #x5C2B)
+                (#x8FBAF1 #x5C2C)
+                (#x8FBAF2 #x5C2E)
+                (#x8FBAF3 #x5C30)
+                (#x8FBAF4 #x5C32)
+                (#x8FBAF5 #x5C35)
+                (#x8FBAF6 #x5C36)
+                (#x8FBAF7 #x5C59)
+                (#x8FBAF8 #x5C5A)
+                (#x8FBAF9 #x5C5C)
+                (#x8FBAFA #x5C62)
+                (#x8FBAFB #x5C63)
+                (#x8FBAFC #x5C67)
+                (#x8FBAFD #x5C68)
+                (#x8FBAFE #x5C69)
+                (#x8FBBA1 #x5C6D)
+                (#x8FBBA2 #x5C70)
+                (#x8FBBA3 #x5C74)
+                (#x8FBBA4 #x5C75)
+                (#x8FBBA5 #x5C7A)
+                (#x8FBBA6 #x5C7B)
+                (#x8FBBA7 #x5C7C)
+                (#x8FBBA8 #x5C7D)
+                (#x8FBBA9 #x5C87)
+                (#x8FBBAA #x5C88)
+                (#x8FBBAB #x5C8A)
+                (#x8FBBAC #x5C8F)
+                (#x8FBBAD #x5C92)
+                (#x8FBBAE #x5C9D)
+                (#x8FBBAF #x5C9F)
+                (#x8FBBB0 #x5CA0)
+                (#x8FBBB1 #x5CA2)
+                (#x8FBBB2 #x5CA3)
+                (#x8FBBB3 #x5CA6)
+                (#x8FBBB4 #x5CAA)
+                (#x8FBBB5 #x5CB2)
+                (#x8FBBB6 #x5CB4)
+                (#x8FBBB7 #x5CB5)
+                (#x8FBBB8 #x5CBA)
+                (#x8FBBB9 #x5CC9)
+                (#x8FBBBA #x5CCB)
+                (#x8FBBBB #x5CD2)
+                (#x8FBBBC #x5CDD)
+                (#x8FBBBD #x5CD7)
+                (#x8FBBBE #x5CEE)
+                (#x8FBBBF #x5CF1)
+                (#x8FBBC0 #x5CF2)
+                (#x8FBBC1 #x5CF4)
+                (#x8FBBC2 #x5D01)
+                (#x8FBBC3 #x5D06)
+                (#x8FBBC4 #x5D0D)
+                (#x8FBBC5 #x5D12)
+                (#x8FBBC6 #x5D2B)
+                (#x8FBBC7 #x5D23)
+                (#x8FBBC8 #x5D24)
+                (#x8FBBC9 #x5D26)
+                (#x8FBBCA #x5D27)
+                (#x8FBBCB #x5D31)
+                (#x8FBBCC #x5D34)
+                (#x8FBBCD #x5D39)
+                (#x8FBBCE #x5D3D)
+                (#x8FBBCF #x5D3F)
+                (#x8FBBD0 #x5D42)
+                (#x8FBBD1 #x5D43)
+                (#x8FBBD2 #x5D46)
+                (#x8FBBD3 #x5D48)
+                (#x8FBBD4 #x5D55)
+                (#x8FBBD5 #x5D51)
+                (#x8FBBD6 #x5D59)
+                (#x8FBBD7 #x5D4A)
+                (#x8FBBD8 #x5D5F)
+                (#x8FBBD9 #x5D60)
+                (#x8FBBDA #x5D61)
+                (#x8FBBDB #x5D62)
+                (#x8FBBDC #x5D64)
+                (#x8FBBDD #x5D6A)
+                (#x8FBBDE #x5D6D)
+                (#x8FBBDF #x5D70)
+                (#x8FBBE0 #x5D79)
+                (#x8FBBE1 #x5D7A)
+                (#x8FBBE2 #x5D7E)
+                (#x8FBBE3 #x5D7F)
+                (#x8FBBE4 #x5D81)
+                (#x8FBBE5 #x5D83)
+                (#x8FBBE6 #x5D88)
+                (#x8FBBE7 #x5D8A)
+                (#x8FBBE8 #x5D92)
+                (#x8FBBE9 #x5D93)
+                (#x8FBBEA #x5D94)
+                (#x8FBBEB #x5D95)
+                (#x8FBBEC #x5D99)
+                (#x8FBBED #x5D9B)
+                (#x8FBBEE #x5D9F)
+                (#x8FBBEF #x5DA0)
+                (#x8FBBF0 #x5DA7)
+                (#x8FBBF1 #x5DAB)
+                (#x8FBBF2 #x5DB0)
+                (#x8FBBF3 #x5DB4)
+                (#x8FBBF4 #x5DB8)
+                (#x8FBBF5 #x5DB9)
+                (#x8FBBF6 #x5DC3)
+                (#x8FBBF7 #x5DC7)
+                (#x8FBBF8 #x5DCB)
+                (#x8FBBF9 #x5DD0)
+                (#x8FBBFA #x5DCE)
+                (#x8FBBFB #x5DD8)
+                (#x8FBBFC #x5DD9)
+                (#x8FBBFD #x5DE0)
+                (#x8FBBFE #x5DE4)
+                (#x8FBCA1 #x5DE9)
+                (#x8FBCA2 #x5DF8)
+                (#x8FBCA3 #x5DF9)
+                (#x8FBCA4 #x5E00)
+                (#x8FBCA5 #x5E07)
+                (#x8FBCA6 #x5E0D)
+                (#x8FBCA7 #x5E12)
+                (#x8FBCA8 #x5E14)
+                (#x8FBCA9 #x5E15)
+                (#x8FBCAA #x5E18)
+                (#x8FBCAB #x5E1F)
+                (#x8FBCAC #x5E20)
+                (#x8FBCAD #x5E2E)
+                (#x8FBCAE #x5E28)
+                (#x8FBCAF #x5E32)
+                (#x8FBCB0 #x5E35)
+                (#x8FBCB1 #x5E3E)
+                (#x8FBCB2 #x5E4B)
+                (#x8FBCB3 #x5E50)
+                (#x8FBCB4 #x5E49)
+                (#x8FBCB5 #x5E51)
+                (#x8FBCB6 #x5E56)
+                (#x8FBCB7 #x5E58)
+                (#x8FBCB8 #x5E5B)
+                (#x8FBCB9 #x5E5C)
+                (#x8FBCBA #x5E5E)
+                (#x8FBCBB #x5E68)
+                (#x8FBCBC #x5E6A)
+                (#x8FBCBD #x5E6B)
+                (#x8FBCBE #x5E6C)
+                (#x8FBCBF #x5E6D)
+                (#x8FBCC0 #x5E6E)
+                (#x8FBCC1 #x5E70)
+                (#x8FBCC2 #x5E80)
+                (#x8FBCC3 #x5E8B)
+                (#x8FBCC4 #x5E8E)
+                (#x8FBCC5 #x5EA2)
+                (#x8FBCC6 #x5EA4)
+                (#x8FBCC7 #x5EA5)
+                (#x8FBCC8 #x5EA8)
+                (#x8FBCC9 #x5EAA)
+                (#x8FBCCA #x5EAC)
+                (#x8FBCCB #x5EB1)
+                (#x8FBCCC #x5EB3)
+                (#x8FBCCD #x5EBD)
+                (#x8FBCCE #x5EBE)
+                (#x8FBCCF #x5EBF)
+                (#x8FBCD0 #x5EC6)
+                (#x8FBCD1 #x5ECC)
+                (#x8FBCD2 #x5ECB)
+                (#x8FBCD3 #x5ECE)
+                (#x8FBCD4 #x5ED1)
+                (#x8FBCD5 #x5ED2)
+                (#x8FBCD6 #x5ED4)
+                (#x8FBCD7 #x5ED5)
+                (#x8FBCD8 #x5EDC)
+                (#x8FBCD9 #x5EDE)
+                (#x8FBCDA #x5EE5)
+                (#x8FBCDB #x5EEB)
+                (#x8FBCDC #x5F02)
+                (#x8FBCDD #x5F06)
+                (#x8FBCDE #x5F07)
+                (#x8FBCDF #x5F08)
+                (#x8FBCE0 #x5F0E)
+                (#x8FBCE1 #x5F19)
+                (#x8FBCE2 #x5F1C)
+                (#x8FBCE3 #x5F1D)
+                (#x8FBCE4 #x5F21)
+                (#x8FBCE5 #x5F22)
+                (#x8FBCE6 #x5F23)
+                (#x8FBCE7 #x5F24)
+                (#x8FBCE8 #x5F28)
+                (#x8FBCE9 #x5F2B)
+                (#x8FBCEA #x5F2C)
+                (#x8FBCEB #x5F2E)
+                (#x8FBCEC #x5F30)
+                (#x8FBCED #x5F34)
+                (#x8FBCEE #x5F36)
+                (#x8FBCEF #x5F3B)
+                (#x8FBCF0 #x5F3D)
+                (#x8FBCF1 #x5F3F)
+                (#x8FBCF2 #x5F40)
+                (#x8FBCF3 #x5F44)
+                (#x8FBCF4 #x5F45)
+                (#x8FBCF5 #x5F47)
+                (#x8FBCF6 #x5F4D)
+                (#x8FBCF7 #x5F50)
+                (#x8FBCF8 #x5F54)
+                (#x8FBCF9 #x5F58)
+                (#x8FBCFA #x5F5B)
+                (#x8FBCFB #x5F60)
+                (#x8FBCFC #x5F63)
+                (#x8FBCFD #x5F64)
+                (#x8FBCFE #x5F67)
+                (#x8FBDA1 #x5F6F)
+                (#x8FBDA2 #x5F72)
+                (#x8FBDA3 #x5F74)
+                (#x8FBDA4 #x5F75)
+                (#x8FBDA5 #x5F78)
+                (#x8FBDA6 #x5F7A)
+                (#x8FBDA7 #x5F7D)
+                (#x8FBDA8 #x5F7E)
+                (#x8FBDA9 #x5F89)
+                (#x8FBDAA #x5F8D)
+                (#x8FBDAB #x5F8F)
+                (#x8FBDAC #x5F96)
+                (#x8FBDAD #x5F9C)
+                (#x8FBDAE #x5F9D)
+                (#x8FBDAF #x5FA2)
+                (#x8FBDB0 #x5FA7)
+                (#x8FBDB1 #x5FAB)
+                (#x8FBDB2 #x5FA4)
+                (#x8FBDB3 #x5FAC)
+                (#x8FBDB4 #x5FAF)
+                (#x8FBDB5 #x5FB0)
+                (#x8FBDB6 #x5FB1)
+                (#x8FBDB7 #x5FB8)
+                (#x8FBDB8 #x5FC4)
+                (#x8FBDB9 #x5FC7)
+                (#x8FBDBA #x5FC8)
+                (#x8FBDBB #x5FC9)
+                (#x8FBDBC #x5FCB)
+                (#x8FBDBD #x5FD0)
+                (#x8FBDBE #x5FD1)
+                (#x8FBDBF #x5FD2)
+                (#x8FBDC0 #x5FD3)
+                (#x8FBDC1 #x5FD4)
+                (#x8FBDC2 #x5FDE)
+                (#x8FBDC3 #x5FE1)
+                (#x8FBDC4 #x5FE2)
+                (#x8FBDC5 #x5FE8)
+                (#x8FBDC6 #x5FE9)
+                (#x8FBDC7 #x5FEA)
+                (#x8FBDC8 #x5FEC)
+                (#x8FBDC9 #x5FED)
+                (#x8FBDCA #x5FEE)
+                (#x8FBDCB #x5FEF)
+                (#x8FBDCC #x5FF2)
+                (#x8FBDCD #x5FF3)
+                (#x8FBDCE #x5FF6)
+                (#x8FBDCF #x5FFA)
+                (#x8FBDD0 #x5FFC)
+                (#x8FBDD1 #x6007)
+                (#x8FBDD2 #x600A)
+                (#x8FBDD3 #x600D)
+                (#x8FBDD4 #x6013)
+                (#x8FBDD5 #x6014)
+                (#x8FBDD6 #x6017)
+                (#x8FBDD7 #x6018)
+                (#x8FBDD8 #x601A)
+                (#x8FBDD9 #x601F)
+                (#x8FBDDA #x6024)
+                (#x8FBDDB #x602D)
+                (#x8FBDDC #x6033)
+                (#x8FBDDD #x6035)
+                (#x8FBDDE #x6040)
+                (#x8FBDDF #x6047)
+                (#x8FBDE0 #x6048)
+                (#x8FBDE1 #x6049)
+                (#x8FBDE2 #x604C)
+                (#x8FBDE3 #x6051)
+                (#x8FBDE4 #x6054)
+                (#x8FBDE5 #x6056)
+                (#x8FBDE6 #x6057)
+                (#x8FBDE7 #x605D)
+                (#x8FBDE8 #x6061)
+                (#x8FBDE9 #x6067)
+                (#x8FBDEA #x6071)
+                (#x8FBDEB #x607E)
+                (#x8FBDEC #x607F)
+                (#x8FBDED #x6082)
+                (#x8FBDEE #x6086)
+                (#x8FBDEF #x6088)
+                (#x8FBDF0 #x608A)
+                (#x8FBDF1 #x608E)
+                (#x8FBDF2 #x6091)
+                (#x8FBDF3 #x6093)
+                (#x8FBDF4 #x6095)
+                (#x8FBDF5 #x6098)
+                (#x8FBDF6 #x609D)
+                (#x8FBDF7 #x609E)
+                (#x8FBDF8 #x60A2)
+                (#x8FBDF9 #x60A4)
+                (#x8FBDFA #x60A5)
+                (#x8FBDFB #x60A8)
+                (#x8FBDFC #x60B0)
+                (#x8FBDFD #x60B1)
+                (#x8FBDFE #x60B7)
+                (#x8FBEA1 #x60BB)
+                (#x8FBEA2 #x60BE)
+                (#x8FBEA3 #x60C2)
+                (#x8FBEA4 #x60C4)
+                (#x8FBEA5 #x60C8)
+                (#x8FBEA6 #x60C9)
+                (#x8FBEA7 #x60CA)
+                (#x8FBEA8 #x60CB)
+                (#x8FBEA9 #x60CE)
+                (#x8FBEAA #x60CF)
+                (#x8FBEAB #x60D4)
+                (#x8FBEAC #x60D5)
+                (#x8FBEAD #x60D9)
+                (#x8FBEAE #x60DB)
+                (#x8FBEAF #x60DD)
+                (#x8FBEB0 #x60DE)
+                (#x8FBEB1 #x60E2)
+                (#x8FBEB2 #x60E5)
+                (#x8FBEB3 #x60F2)
+                (#x8FBEB4 #x60F5)
+                (#x8FBEB5 #x60F8)
+                (#x8FBEB6 #x60FC)
+                (#x8FBEB7 #x60FD)
+                (#x8FBEB8 #x6102)
+                (#x8FBEB9 #x6107)
+                (#x8FBEBA #x610A)
+                (#x8FBEBB #x610C)
+                (#x8FBEBC #x6110)
+                (#x8FBEBD #x6111)
+                (#x8FBEBE #x6112)
+                (#x8FBEBF #x6113)
+                (#x8FBEC0 #x6114)
+                (#x8FBEC1 #x6116)
+                (#x8FBEC2 #x6117)
+                (#x8FBEC3 #x6119)
+                (#x8FBEC4 #x611C)
+                (#x8FBEC5 #x611E)
+                (#x8FBEC6 #x6122)
+                (#x8FBEC7 #x612A)
+                (#x8FBEC8 #x612B)
+                (#x8FBEC9 #x6130)
+                (#x8FBECA #x6131)
+                (#x8FBECB #x6135)
+                (#x8FBECC #x6136)
+                (#x8FBECD #x6137)
+                (#x8FBECE #x6139)
+                (#x8FBECF #x6141)
+                (#x8FBED0 #x6145)
+                (#x8FBED1 #x6146)
+                (#x8FBED2 #x6149)
+                (#x8FBED3 #x615E)
+                (#x8FBED4 #x6160)
+                (#x8FBED5 #x616C)
+                (#x8FBED6 #x6172)
+                (#x8FBED7 #x6178)
+                (#x8FBED8 #x617B)
+                (#x8FBED9 #x617C)
+                (#x8FBEDA #x617F)
+                (#x8FBEDB #x6180)
+                (#x8FBEDC #x6181)
+                (#x8FBEDD #x6183)
+                (#x8FBEDE #x6184)
+                (#x8FBEDF #x618B)
+                (#x8FBEE0 #x618D)
+                (#x8FBEE1 #x6192)
+                (#x8FBEE2 #x6193)
+                (#x8FBEE3 #x6197)
+                (#x8FBEE4 #x6198)
+                (#x8FBEE5 #x619C)
+                (#x8FBEE6 #x619D)
+                (#x8FBEE7 #x619F)
+                (#x8FBEE8 #x61A0)
+                (#x8FBEE9 #x61A5)
+                (#x8FBEEA #x61A8)
+                (#x8FBEEB #x61AA)
+                (#x8FBEEC #x61AD)
+                (#x8FBEED #x61B8)
+                (#x8FBEEE #x61B9)
+                (#x8FBEEF #x61BC)
+                (#x8FBEF0 #x61C0)
+                (#x8FBEF1 #x61C1)
+                (#x8FBEF2 #x61C2)
+                (#x8FBEF3 #x61CE)
+                (#x8FBEF4 #x61CF)
+                (#x8FBEF5 #x61D5)
+                (#x8FBEF6 #x61DC)
+                (#x8FBEF7 #x61DD)
+                (#x8FBEF8 #x61DE)
+                (#x8FBEF9 #x61DF)
+                (#x8FBEFA #x61E1)
+                (#x8FBEFB #x61E2)
+                (#x8FBEFC #x61E7)
+                (#x8FBEFD #x61E9)
+                (#x8FBEFE #x61E5)
+                (#x8FBFA1 #x61EC)
+                (#x8FBFA2 #x61ED)
+                (#x8FBFA3 #x61EF)
+                (#x8FBFA4 #x6201)
+                (#x8FBFA5 #x6203)
+                (#x8FBFA6 #x6204)
+                (#x8FBFA7 #x6207)
+                (#x8FBFA8 #x6213)
+                (#x8FBFA9 #x6215)
+                (#x8FBFAA #x621C)
+                (#x8FBFAB #x6220)
+                (#x8FBFAC #x6222)
+                (#x8FBFAD #x6223)
+                (#x8FBFAE #x6227)
+                (#x8FBFAF #x6229)
+                (#x8FBFB0 #x622B)
+                (#x8FBFB1 #x6239)
+                (#x8FBFB2 #x623D)
+                (#x8FBFB3 #x6242)
+                (#x8FBFB4 #x6243)
+                (#x8FBFB5 #x6244)
+                (#x8FBFB6 #x6246)
+                (#x8FBFB7 #x624C)
+                (#x8FBFB8 #x6250)
+                (#x8FBFB9 #x6251)
+                (#x8FBFBA #x6252)
+                (#x8FBFBB #x6254)
+                (#x8FBFBC #x6256)
+                (#x8FBFBD #x625A)
+                (#x8FBFBE #x625C)
+                (#x8FBFBF #x6264)
+                (#x8FBFC0 #x626D)
+                (#x8FBFC1 #x626F)
+                (#x8FBFC2 #x6273)
+                (#x8FBFC3 #x627A)
+                (#x8FBFC4 #x627D)
+                (#x8FBFC5 #x628D)
+                (#x8FBFC6 #x628E)
+                (#x8FBFC7 #x628F)
+                (#x8FBFC8 #x6290)
+                (#x8FBFC9 #x62A6)
+                (#x8FBFCA #x62A8)
+                (#x8FBFCB #x62B3)
+                (#x8FBFCC #x62B6)
+                (#x8FBFCD #x62B7)
+                (#x8FBFCE #x62BA)
+                (#x8FBFCF #x62BE)
+                (#x8FBFD0 #x62BF)
+                (#x8FBFD1 #x62C4)
+                (#x8FBFD2 #x62CE)
+                (#x8FBFD3 #x62D5)
+                (#x8FBFD4 #x62D6)
+                (#x8FBFD5 #x62DA)
+                (#x8FBFD6 #x62EA)
+                (#x8FBFD7 #x62F2)
+                (#x8FBFD8 #x62F4)
+                (#x8FBFD9 #x62FC)
+                (#x8FBFDA #x62FD)
+                (#x8FBFDB #x6303)
+                (#x8FBFDC #x6304)
+                (#x8FBFDD #x630A)
+                (#x8FBFDE #x630B)
+                (#x8FBFDF #x630D)
+                (#x8FBFE0 #x6310)
+                (#x8FBFE1 #x6313)
+                (#x8FBFE2 #x6316)
+                (#x8FBFE3 #x6318)
+                (#x8FBFE4 #x6329)
+                (#x8FBFE5 #x632A)
+                (#x8FBFE6 #x632D)
+                (#x8FBFE7 #x6335)
+                (#x8FBFE8 #x6336)
+                (#x8FBFE9 #x6339)
+                (#x8FBFEA #x633C)
+                (#x8FBFEB #x6341)
+                (#x8FBFEC #x6342)
+                (#x8FBFED #x6343)
+                (#x8FBFEE #x6344)
+                (#x8FBFEF #x6346)
+                (#x8FBFF0 #x634A)
+                (#x8FBFF1 #x634B)
+                (#x8FBFF2 #x634E)
+                (#x8FBFF3 #x6352)
+                (#x8FBFF4 #x6353)
+                (#x8FBFF5 #x6354)
+                (#x8FBFF6 #x6358)
+                (#x8FBFF7 #x635B)
+                (#x8FBFF8 #x6365)
+                (#x8FBFF9 #x6366)
+                (#x8FBFFA #x636C)
+                (#x8FBFFB #x636D)
+                (#x8FBFFC #x6371)
+                (#x8FBFFD #x6374)
+                (#x8FBFFE #x6375)
+                (#x8FC0A1 #x6378)
+                (#x8FC0A2 #x637C)
+                (#x8FC0A3 #x637D)
+                (#x8FC0A4 #x637F)
+                (#x8FC0A5 #x6382)
+                (#x8FC0A6 #x6384)
+                (#x8FC0A7 #x6387)
+                (#x8FC0A8 #x638A)
+                (#x8FC0A9 #x6390)
+                (#x8FC0AA #x6394)
+                (#x8FC0AB #x6395)
+                (#x8FC0AC #x6399)
+                (#x8FC0AD #x639A)
+                (#x8FC0AE #x639E)
+                (#x8FC0AF #x63A4)
+                (#x8FC0B0 #x63A6)
+                (#x8FC0B1 #x63AD)
+                (#x8FC0B2 #x63AE)
+                (#x8FC0B3 #x63AF)
+                (#x8FC0B4 #x63BD)
+                (#x8FC0B5 #x63C1)
+                (#x8FC0B6 #x63C5)
+                (#x8FC0B7 #x63C8)
+                (#x8FC0B8 #x63CE)
+                (#x8FC0B9 #x63D1)
+                (#x8FC0BA #x63D3)
+                (#x8FC0BB #x63D4)
+                (#x8FC0BC #x63D5)
+                (#x8FC0BD #x63DC)
+                (#x8FC0BE #x63E0)
+                (#x8FC0BF #x63E5)
+                (#x8FC0C0 #x63EA)
+                (#x8FC0C1 #x63EC)
+                (#x8FC0C2 #x63F2)
+                (#x8FC0C3 #x63F3)
+                (#x8FC0C4 #x63F5)
+                (#x8FC0C5 #x63F8)
+                (#x8FC0C6 #x63F9)
+                (#x8FC0C7 #x6409)
+                (#x8FC0C8 #x640A)
+                (#x8FC0C9 #x6410)
+                (#x8FC0CA #x6412)
+                (#x8FC0CB #x6414)
+                (#x8FC0CC #x6418)
+                (#x8FC0CD #x641E)
+                (#x8FC0CE #x6420)
+                (#x8FC0CF #x6422)
+                (#x8FC0D0 #x6424)
+                (#x8FC0D1 #x6425)
+                (#x8FC0D2 #x6429)
+                (#x8FC0D3 #x642A)
+                (#x8FC0D4 #x642F)
+                (#x8FC0D5 #x6430)
+                (#x8FC0D6 #x6435)
+                (#x8FC0D7 #x643D)
+                (#x8FC0D8 #x643F)
+                (#x8FC0D9 #x644B)
+                (#x8FC0DA #x644F)
+                (#x8FC0DB #x6451)
+                (#x8FC0DC #x6452)
+                (#x8FC0DD #x6453)
+                (#x8FC0DE #x6454)
+                (#x8FC0DF #x645A)
+                (#x8FC0E0 #x645B)
+                (#x8FC0E1 #x645C)
+                (#x8FC0E2 #x645D)
+                (#x8FC0E3 #x645F)
+                (#x8FC0E4 #x6460)
+                (#x8FC0E5 #x6461)
+                (#x8FC0E6 #x6463)
+                (#x8FC0E7 #x646D)
+                (#x8FC0E8 #x6473)
+                (#x8FC0E9 #x6474)
+                (#x8FC0EA #x647B)
+                (#x8FC0EB #x647D)
+                (#x8FC0EC #x6485)
+                (#x8FC0ED #x6487)
+                (#x8FC0EE #x648F)
+                (#x8FC0EF #x6490)
+                (#x8FC0F0 #x6491)
+                (#x8FC0F1 #x6498)
+                (#x8FC0F2 #x6499)
+                (#x8FC0F3 #x649B)
+                (#x8FC0F4 #x649D)
+                (#x8FC0F5 #x649F)
+                (#x8FC0F6 #x64A1)
+                (#x8FC0F7 #x64A3)
+                (#x8FC0F8 #x64A6)
+                (#x8FC0F9 #x64A8)
+                (#x8FC0FA #x64AC)
+                (#x8FC0FB #x64B3)
+                (#x8FC0FC #x64BD)
+                (#x8FC0FD #x64BE)
+                (#x8FC0FE #x64BF)
+                (#x8FC1A1 #x64C4)
+                (#x8FC1A2 #x64C9)
+                (#x8FC1A3 #x64CA)
+                (#x8FC1A4 #x64CB)
+                (#x8FC1A5 #x64CC)
+                (#x8FC1A6 #x64CE)
+                (#x8FC1A7 #x64D0)
+                (#x8FC1A8 #x64D1)
+                (#x8FC1A9 #x64D5)
+                (#x8FC1AA #x64D7)
+                (#x8FC1AB #x64E4)
+                (#x8FC1AC #x64E5)
+                (#x8FC1AD #x64E9)
+                (#x8FC1AE #x64EA)
+                (#x8FC1AF #x64ED)
+                (#x8FC1B0 #x64F0)
+                (#x8FC1B1 #x64F5)
+                (#x8FC1B2 #x64F7)
+                (#x8FC1B3 #x64FB)
+                (#x8FC1B4 #x64FF)
+                (#x8FC1B5 #x6501)
+                (#x8FC1B6 #x6504)
+                (#x8FC1B7 #x6508)
+                (#x8FC1B8 #x6509)
+                (#x8FC1B9 #x650A)
+                (#x8FC1BA #x650F)
+                (#x8FC1BB #x6513)
+                (#x8FC1BC #x6514)
+                (#x8FC1BD #x6516)
+                (#x8FC1BE #x6519)
+                (#x8FC1BF #x651B)
+                (#x8FC1C0 #x651E)
+                (#x8FC1C1 #x651F)
+                (#x8FC1C2 #x6522)
+                (#x8FC1C3 #x6526)
+                (#x8FC1C4 #x6529)
+                (#x8FC1C5 #x652E)
+                (#x8FC1C6 #x6531)
+                (#x8FC1C7 #x653A)
+                (#x8FC1C8 #x653C)
+                (#x8FC1C9 #x653D)
+                (#x8FC1CA #x6543)
+                (#x8FC1CB #x6547)
+                (#x8FC1CC #x6549)
+                (#x8FC1CD #x6550)
+                (#x8FC1CE #x6552)
+                (#x8FC1CF #x6554)
+                (#x8FC1D0 #x655F)
+                (#x8FC1D1 #x6560)
+                (#x8FC1D2 #x6567)
+                (#x8FC1D3 #x656B)
+                (#x8FC1D4 #x657A)
+                (#x8FC1D5 #x657D)
+                (#x8FC1D6 #x6581)
+                (#x8FC1D7 #x6585)
+                (#x8FC1D8 #x658A)
+                (#x8FC1D9 #x6592)
+                (#x8FC1DA #x6595)
+                (#x8FC1DB #x6598)
+                (#x8FC1DC #x659D)
+                (#x8FC1DD #x65A0)
+                (#x8FC1DE #x65A3)
+                (#x8FC1DF #x65A6)
+                (#x8FC1E0 #x65AE)
+                (#x8FC1E1 #x65B2)
+                (#x8FC1E2 #x65B3)
+                (#x8FC1E3 #x65B4)
+                (#x8FC1E4 #x65BF)
+                (#x8FC1E5 #x65C2)
+                (#x8FC1E6 #x65C8)
+                (#x8FC1E7 #x65C9)
+                (#x8FC1E8 #x65CE)
+                (#x8FC1E9 #x65D0)
+                (#x8FC1EA #x65D4)
+                (#x8FC1EB #x65D6)
+                (#x8FC1EC #x65D8)
+                (#x8FC1ED #x65DF)
+                (#x8FC1EE #x65F0)
+                (#x8FC1EF #x65F2)
+                (#x8FC1F0 #x65F4)
+                (#x8FC1F1 #x65F5)
+                (#x8FC1F2 #x65F9)
+                (#x8FC1F3 #x65FE)
+                (#x8FC1F4 #x65FF)
+                (#x8FC1F5 #x6600)
+                (#x8FC1F6 #x6604)
+                (#x8FC1F7 #x6608)
+                (#x8FC1F8 #x6609)
+                (#x8FC1F9 #x660D)
+                (#x8FC1FA #x6611)
+                (#x8FC1FB #x6612)
+                (#x8FC1FC #x6615)
+                (#x8FC1FD #x6616)
+                (#x8FC1FE #x661D)
+                (#x8FC2A1 #x661E)
+                (#x8FC2A2 #x6621)
+                (#x8FC2A3 #x6622)
+                (#x8FC2A4 #x6623)
+                (#x8FC2A5 #x6624)
+                (#x8FC2A6 #x6626)
+                (#x8FC2A7 #x6629)
+                (#x8FC2A8 #x662A)
+                (#x8FC2A9 #x662B)
+                (#x8FC2AA #x662C)
+                (#x8FC2AB #x662E)
+                (#x8FC2AC #x6630)
+                (#x8FC2AD #x6631)
+                (#x8FC2AE #x6633)
+                (#x8FC2AF #x6639)
+                (#x8FC2B0 #x6637)
+                (#x8FC2B1 #x6640)
+                (#x8FC2B2 #x6645)
+                (#x8FC2B3 #x6646)
+                (#x8FC2B4 #x664A)
+                (#x8FC2B5 #x664C)
+                (#x8FC2B6 #x6651)
+                (#x8FC2B7 #x664E)
+                (#x8FC2B8 #x6657)
+                (#x8FC2B9 #x6658)
+                (#x8FC2BA #x6659)
+                (#x8FC2BB #x665B)
+                (#x8FC2BC #x665C)
+                (#x8FC2BD #x6660)
+                (#x8FC2BE #x6661)
+                (#x8FC2BF #x66FB)
+                (#x8FC2C0 #x666A)
+                (#x8FC2C1 #x666B)
+                (#x8FC2C2 #x666C)
+                (#x8FC2C3 #x667E)
+                (#x8FC2C4 #x6673)
+                (#x8FC2C5 #x6675)
+                (#x8FC2C6 #x667F)
+                (#x8FC2C7 #x6677)
+                (#x8FC2C8 #x6678)
+                (#x8FC2C9 #x6679)
+                (#x8FC2CA #x667B)
+                (#x8FC2CB #x6680)
+                (#x8FC2CC #x667C)
+                (#x8FC2CD #x668B)
+                (#x8FC2CE #x668C)
+                (#x8FC2CF #x668D)
+                (#x8FC2D0 #x6690)
+                (#x8FC2D1 #x6692)
+                (#x8FC2D2 #x6699)
+                (#x8FC2D3 #x669A)
+                (#x8FC2D4 #x669B)
+                (#x8FC2D5 #x669C)
+                (#x8FC2D6 #x669F)
+                (#x8FC2D7 #x66A0)
+                (#x8FC2D8 #x66A4)
+                (#x8FC2D9 #x66AD)
+                (#x8FC2DA #x66B1)
+                (#x8FC2DB #x66B2)
+                (#x8FC2DC #x66B5)
+                (#x8FC2DD #x66BB)
+                (#x8FC2DE #x66BF)
+                (#x8FC2DF #x66C0)
+                (#x8FC2E0 #x66C2)
+                (#x8FC2E1 #x66C3)
+                (#x8FC2E2 #x66C8)
+                (#x8FC2E3 #x66CC)
+                (#x8FC2E4 #x66CE)
+                (#x8FC2E5 #x66CF)
+                (#x8FC2E6 #x66D4)
+                (#x8FC2E7 #x66DB)
+                (#x8FC2E8 #x66DF)
+                (#x8FC2E9 #x66E8)
+                (#x8FC2EA #x66EB)
+                (#x8FC2EB #x66EC)
+                (#x8FC2EC #x66EE)
+                (#x8FC2ED #x66FA)
+                (#x8FC2EE #x6705)
+                (#x8FC2EF #x6707)
+                (#x8FC2F0 #x670E)
+                (#x8FC2F1 #x6713)
+                (#x8FC2F2 #x6719)
+                (#x8FC2F3 #x671C)
+                (#x8FC2F4 #x6720)
+                (#x8FC2F5 #x6722)
+                (#x8FC2F6 #x6733)
+                (#x8FC2F7 #x673E)
+                (#x8FC2F8 #x6745)
+                (#x8FC2F9 #x6747)
+                (#x8FC2FA #x6748)
+                (#x8FC2FB #x674C)
+                (#x8FC2FC #x6754)
+                (#x8FC2FD #x6755)
+                (#x8FC2FE #x675D)
+                (#x8FC3A1 #x6766)
+                (#x8FC3A2 #x676C)
+                (#x8FC3A3 #x676E)
+                (#x8FC3A4 #x6774)
+                (#x8FC3A5 #x6776)
+                (#x8FC3A6 #x677B)
+                (#x8FC3A7 #x6781)
+                (#x8FC3A8 #x6784)
+                (#x8FC3A9 #x678E)
+                (#x8FC3AA #x678F)
+                (#x8FC3AB #x6791)
+                (#x8FC3AC #x6793)
+                (#x8FC3AD #x6796)
+                (#x8FC3AE #x6798)
+                (#x8FC3AF #x6799)
+                (#x8FC3B0 #x679B)
+                (#x8FC3B1 #x67B0)
+                (#x8FC3B2 #x67B1)
+                (#x8FC3B3 #x67B2)
+                (#x8FC3B4 #x67B5)
+                (#x8FC3B5 #x67BB)
+                (#x8FC3B6 #x67BC)
+                (#x8FC3B7 #x67BD)
+                (#x8FC3B8 #x67F9)
+                (#x8FC3B9 #x67C0)
+                (#x8FC3BA #x67C2)
+                (#x8FC3BB #x67C3)
+                (#x8FC3BC #x67C5)
+                (#x8FC3BD #x67C8)
+                (#x8FC3BE #x67C9)
+                (#x8FC3BF #x67D2)
+                (#x8FC3C0 #x67D7)
+                (#x8FC3C1 #x67D9)
+                (#x8FC3C2 #x67DC)
+                (#x8FC3C3 #x67E1)
+                (#x8FC3C4 #x67E6)
+                (#x8FC3C5 #x67F0)
+                (#x8FC3C6 #x67F2)
+                (#x8FC3C7 #x67F6)
+                (#x8FC3C8 #x67F7)
+                (#x8FC3C9 #x6852)
+                (#x8FC3CA #x6814)
+                (#x8FC3CB #x6819)
+                (#x8FC3CC #x681D)
+                (#x8FC3CD #x681F)
+                (#x8FC3CE #x6828)
+                (#x8FC3CF #x6827)
+                (#x8FC3D0 #x682C)
+                (#x8FC3D1 #x682D)
+                (#x8FC3D2 #x682F)
+                (#x8FC3D3 #x6830)
+                (#x8FC3D4 #x6831)
+                (#x8FC3D5 #x6833)
+                (#x8FC3D6 #x683B)
+                (#x8FC3D7 #x683F)
+                (#x8FC3D8 #x6844)
+                (#x8FC3D9 #x6845)
+                (#x8FC3DA #x684A)
+                (#x8FC3DB #x684C)
+                (#x8FC3DC #x6855)
+                (#x8FC3DD #x6857)
+                (#x8FC3DE #x6858)
+                (#x8FC3DF #x685B)
+                (#x8FC3E0 #x686B)
+                (#x8FC3E1 #x686E)
+                (#x8FC3E2 #x686F)
+                (#x8FC3E3 #x6870)
+                (#x8FC3E4 #x6871)
+                (#x8FC3E5 #x6872)
+                (#x8FC3E6 #x6875)
+                (#x8FC3E7 #x6879)
+                (#x8FC3E8 #x687A)
+                (#x8FC3E9 #x687B)
+                (#x8FC3EA #x687C)
+                (#x8FC3EB #x6882)
+                (#x8FC3EC #x6884)
+                (#x8FC3ED #x6886)
+                (#x8FC3EE #x6888)
+                (#x8FC3EF #x6896)
+                (#x8FC3F0 #x6898)
+                (#x8FC3F1 #x689A)
+                (#x8FC3F2 #x689C)
+                (#x8FC3F3 #x68A1)
+                (#x8FC3F4 #x68A3)
+                (#x8FC3F5 #x68A5)
+                (#x8FC3F6 #x68A9)
+                (#x8FC3F7 #x68AA)
+                (#x8FC3F8 #x68AE)
+                (#x8FC3F9 #x68B2)
+                (#x8FC3FA #x68BB)
+                (#x8FC3FB #x68C5)
+                (#x8FC3FC #x68C8)
+                (#x8FC3FD #x68CC)
+                (#x8FC3FE #x68CF)
+                (#x8FC4A1 #x68D0)
+                (#x8FC4A2 #x68D1)
+                (#x8FC4A3 #x68D3)
+                (#x8FC4A4 #x68D6)
+                (#x8FC4A5 #x68D9)
+                (#x8FC4A6 #x68DC)
+                (#x8FC4A7 #x68DD)
+                (#x8FC4A8 #x68E5)
+                (#x8FC4A9 #x68E8)
+                (#x8FC4AA #x68EA)
+                (#x8FC4AB #x68EB)
+                (#x8FC4AC #x68EC)
+                (#x8FC4AD #x68ED)
+                (#x8FC4AE #x68F0)
+                (#x8FC4AF #x68F1)
+                (#x8FC4B0 #x68F5)
+                (#x8FC4B1 #x68F6)
+                (#x8FC4B2 #x68FB)
+                (#x8FC4B3 #x68FC)
+                (#x8FC4B4 #x68FD)
+                (#x8FC4B5 #x6906)
+                (#x8FC4B6 #x6909)
+                (#x8FC4B7 #x690A)
+                (#x8FC4B8 #x6910)
+                (#x8FC4B9 #x6911)
+                (#x8FC4BA #x6913)
+                (#x8FC4BB #x6916)
+                (#x8FC4BC #x6917)
+                (#x8FC4BD #x6931)
+                (#x8FC4BE #x6933)
+                (#x8FC4BF #x6935)
+                (#x8FC4C0 #x6938)
+                (#x8FC4C1 #x693B)
+                (#x8FC4C2 #x6942)
+                (#x8FC4C3 #x6945)
+                (#x8FC4C4 #x6949)
+                (#x8FC4C5 #x694E)
+                (#x8FC4C6 #x6957)
+                (#x8FC4C7 #x695B)
+                (#x8FC4C8 #x6963)
+                (#x8FC4C9 #x6964)
+                (#x8FC4CA #x6965)
+                (#x8FC4CB #x6966)
+                (#x8FC4CC #x6968)
+                (#x8FC4CD #x6969)
+                (#x8FC4CE #x696C)
+                (#x8FC4CF #x6970)
+                (#x8FC4D0 #x6971)
+                (#x8FC4D1 #x6972)
+                (#x8FC4D2 #x697A)
+                (#x8FC4D3 #x697B)
+                (#x8FC4D4 #x697F)
+                (#x8FC4D5 #x6980)
+                (#x8FC4D6 #x698D)
+                (#x8FC4D7 #x6992)
+                (#x8FC4D8 #x6996)
+                (#x8FC4D9 #x6998)
+                (#x8FC4DA #x69A1)
+                (#x8FC4DB #x69A5)
+                (#x8FC4DC #x69A6)
+                (#x8FC4DD #x69A8)
+                (#x8FC4DE #x69AB)
+                (#x8FC4DF #x69AD)
+                (#x8FC4E0 #x69AF)
+                (#x8FC4E1 #x69B7)
+                (#x8FC4E2 #x69B8)
+                (#x8FC4E3 #x69BA)
+                (#x8FC4E4 #x69BC)
+                (#x8FC4E5 #x69C5)
+                (#x8FC4E6 #x69C8)
+                (#x8FC4E7 #x69D1)
+                (#x8FC4E8 #x69D6)
+                (#x8FC4E9 #x69D7)
+                (#x8FC4EA #x69E2)
+                (#x8FC4EB #x69E5)
+                (#x8FC4EC #x69EE)
+                (#x8FC4ED #x69EF)
+                (#x8FC4EE #x69F1)
+                (#x8FC4EF #x69F3)
+                (#x8FC4F0 #x69F5)
+                (#x8FC4F1 #x69FE)
+                (#x8FC4F2 #x6A00)
+                (#x8FC4F3 #x6A01)
+                (#x8FC4F4 #x6A03)
+                (#x8FC4F5 #x6A0F)
+                (#x8FC4F6 #x6A11)
+                (#x8FC4F7 #x6A15)
+                (#x8FC4F8 #x6A1A)
+                (#x8FC4F9 #x6A1D)
+                (#x8FC4FA #x6A20)
+                (#x8FC4FB #x6A24)
+                (#x8FC4FC #x6A28)
+                (#x8FC4FD #x6A30)
+                (#x8FC4FE #x6A32)
+                (#x8FC5A1 #x6A34)
+                (#x8FC5A2 #x6A37)
+                (#x8FC5A3 #x6A3B)
+                (#x8FC5A4 #x6A3E)
+                (#x8FC5A5 #x6A3F)
+                (#x8FC5A6 #x6A45)
+                (#x8FC5A7 #x6A46)
+                (#x8FC5A8 #x6A49)
+                (#x8FC5A9 #x6A4A)
+                (#x8FC5AA #x6A4E)
+                (#x8FC5AB #x6A50)
+                (#x8FC5AC #x6A51)
+                (#x8FC5AD #x6A52)
+                (#x8FC5AE #x6A55)
+                (#x8FC5AF #x6A56)
+                (#x8FC5B0 #x6A5B)
+                (#x8FC5B1 #x6A64)
+                (#x8FC5B2 #x6A67)
+                (#x8FC5B3 #x6A6A)
+                (#x8FC5B4 #x6A71)
+                (#x8FC5B5 #x6A73)
+                (#x8FC5B6 #x6A7E)
+                (#x8FC5B7 #x6A81)
+                (#x8FC5B8 #x6A83)
+                (#x8FC5B9 #x6A86)
+                (#x8FC5BA #x6A87)
+                (#x8FC5BB #x6A89)
+                (#x8FC5BC #x6A8B)
+                (#x8FC5BD #x6A91)
+                (#x8FC5BE #x6A9B)
+                (#x8FC5BF #x6A9D)
+                (#x8FC5C0 #x6A9E)
+                (#x8FC5C1 #x6A9F)
+                (#x8FC5C2 #x6AA5)
+                (#x8FC5C3 #x6AAB)
+                (#x8FC5C4 #x6AAF)
+                (#x8FC5C5 #x6AB0)
+                (#x8FC5C6 #x6AB1)
+                (#x8FC5C7 #x6AB4)
+                (#x8FC5C8 #x6ABD)
+                (#x8FC5C9 #x6ABE)
+                (#x8FC5CA #x6ABF)
+                (#x8FC5CB #x6AC6)
+                (#x8FC5CC #x6AC9)
+                (#x8FC5CD #x6AC8)
+                (#x8FC5CE #x6ACC)
+                (#x8FC5CF #x6AD0)
+                (#x8FC5D0 #x6AD4)
+                (#x8FC5D1 #x6AD5)
+                (#x8FC5D2 #x6AD6)
+                (#x8FC5D3 #x6ADC)
+                (#x8FC5D4 #x6ADD)
+                (#x8FC5D5 #x6AE4)
+                (#x8FC5D6 #x6AE7)
+                (#x8FC5D7 #x6AEC)
+                (#x8FC5D8 #x6AF0)
+                (#x8FC5D9 #x6AF1)
+                (#x8FC5DA #x6AF2)
+                (#x8FC5DB #x6AFC)
+                (#x8FC5DC #x6AFD)
+                (#x8FC5DD #x6B02)
+                (#x8FC5DE #x6B03)
+                (#x8FC5DF #x6B06)
+                (#x8FC5E0 #x6B07)
+                (#x8FC5E1 #x6B09)
+                (#x8FC5E2 #x6B0F)
+                (#x8FC5E3 #x6B10)
+                (#x8FC5E4 #x6B11)
+                (#x8FC5E5 #x6B17)
+                (#x8FC5E6 #x6B1B)
+                (#x8FC5E7 #x6B1E)
+                (#x8FC5E8 #x6B24)
+                (#x8FC5E9 #x6B28)
+                (#x8FC5EA #x6B2B)
+                (#x8FC5EB #x6B2C)
+                (#x8FC5EC #x6B2F)
+                (#x8FC5ED #x6B35)
+                (#x8FC5EE #x6B36)
+                (#x8FC5EF #x6B3B)
+                (#x8FC5F0 #x6B3F)
+                (#x8FC5F1 #x6B46)
+                (#x8FC5F2 #x6B4A)
+                (#x8FC5F3 #x6B4D)
+                (#x8FC5F4 #x6B52)
+                (#x8FC5F5 #x6B56)
+                (#x8FC5F6 #x6B58)
+                (#x8FC5F7 #x6B5D)
+                (#x8FC5F8 #x6B60)
+                (#x8FC5F9 #x6B67)
+                (#x8FC5FA #x6B6B)
+                (#x8FC5FB #x6B6E)
+                (#x8FC5FC #x6B70)
+                (#x8FC5FD #x6B75)
+                (#x8FC5FE #x6B7D)
+                (#x8FC6A1 #x6B7E)
+                (#x8FC6A2 #x6B82)
+                (#x8FC6A3 #x6B85)
+                (#x8FC6A4 #x6B97)
+                (#x8FC6A5 #x6B9B)
+                (#x8FC6A6 #x6B9F)
+                (#x8FC6A7 #x6BA0)
+                (#x8FC6A8 #x6BA2)
+                (#x8FC6A9 #x6BA3)
+                (#x8FC6AA #x6BA8)
+                (#x8FC6AB #x6BA9)
+                (#x8FC6AC #x6BAC)
+                (#x8FC6AD #x6BAD)
+                (#x8FC6AE #x6BAE)
+                (#x8FC6AF #x6BB0)
+                (#x8FC6B0 #x6BB8)
+                (#x8FC6B1 #x6BB9)
+                (#x8FC6B2 #x6BBD)
+                (#x8FC6B3 #x6BBE)
+                (#x8FC6B4 #x6BC3)
+                (#x8FC6B5 #x6BC4)
+                (#x8FC6B6 #x6BC9)
+                (#x8FC6B7 #x6BCC)
+                (#x8FC6B8 #x6BD6)
+                (#x8FC6B9 #x6BDA)
+                (#x8FC6BA #x6BE1)
+                (#x8FC6BB #x6BE3)
+                (#x8FC6BC #x6BE6)
+                (#x8FC6BD #x6BE7)
+                (#x8FC6BE #x6BEE)
+                (#x8FC6BF #x6BF1)
+                (#x8FC6C0 #x6BF7)
+                (#x8FC6C1 #x6BF9)
+                (#x8FC6C2 #x6BFF)
+                (#x8FC6C3 #x6C02)
+                (#x8FC6C4 #x6C04)
+                (#x8FC6C5 #x6C05)
+                (#x8FC6C6 #x6C09)
+                (#x8FC6C7 #x6C0D)
+                (#x8FC6C8 #x6C0E)
+                (#x8FC6C9 #x6C10)
+                (#x8FC6CA #x6C12)
+                (#x8FC6CB #x6C19)
+                (#x8FC6CC #x6C1F)
+                (#x8FC6CD #x6C26)
+                (#x8FC6CE #x6C27)
+                (#x8FC6CF #x6C28)
+                (#x8FC6D0 #x6C2C)
+                (#x8FC6D1 #x6C2E)
+                (#x8FC6D2 #x6C33)
+                (#x8FC6D3 #x6C35)
+                (#x8FC6D4 #x6C36)
+                (#x8FC6D5 #x6C3A)
+                (#x8FC6D6 #x6C3B)
+                (#x8FC6D7 #x6C3F)
+                (#x8FC6D8 #x6C4A)
+                (#x8FC6D9 #x6C4B)
+                (#x8FC6DA #x6C4D)
+                (#x8FC6DB #x6C4F)
+                (#x8FC6DC #x6C52)
+                (#x8FC6DD #x6C54)
+                (#x8FC6DE #x6C59)
+                (#x8FC6DF #x6C5B)
+                (#x8FC6E0 #x6C5C)
+                (#x8FC6E1 #x6C6B)
+                (#x8FC6E2 #x6C6D)
+                (#x8FC6E3 #x6C6F)
+                (#x8FC6E4 #x6C74)
+                (#x8FC6E5 #x6C76)
+                (#x8FC6E6 #x6C78)
+                (#x8FC6E7 #x6C79)
+                (#x8FC6E8 #x6C7B)
+                (#x8FC6E9 #x6C85)
+                (#x8FC6EA #x6C86)
+                (#x8FC6EB #x6C87)
+                (#x8FC6EC #x6C89)
+                (#x8FC6ED #x6C94)
+                (#x8FC6EE #x6C95)
+                (#x8FC6EF #x6C97)
+                (#x8FC6F0 #x6C98)
+                (#x8FC6F1 #x6C9C)
+                (#x8FC6F2 #x6C9F)
+                (#x8FC6F3 #x6CB0)
+                (#x8FC6F4 #x6CB2)
+                (#x8FC6F5 #x6CB4)
+                (#x8FC6F6 #x6CC2)
+                (#x8FC6F7 #x6CC6)
+                (#x8FC6F8 #x6CCD)
+                (#x8FC6F9 #x6CCF)
+                (#x8FC6FA #x6CD0)
+                (#x8FC6FB #x6CD1)
+                (#x8FC6FC #x6CD2)
+                (#x8FC6FD #x6CD4)
+                (#x8FC6FE #x6CD6)
+                (#x8FC7A1 #x6CDA)
+                (#x8FC7A2 #x6CDC)
+                (#x8FC7A3 #x6CE0)
+                (#x8FC7A4 #x6CE7)
+                (#x8FC7A5 #x6CE9)
+                (#x8FC7A6 #x6CEB)
+                (#x8FC7A7 #x6CEC)
+                (#x8FC7A8 #x6CEE)
+                (#x8FC7A9 #x6CF2)
+                (#x8FC7AA #x6CF4)
+                (#x8FC7AB #x6D04)
+                (#x8FC7AC #x6D07)
+                (#x8FC7AD #x6D0A)
+                (#x8FC7AE #x6D0E)
+                (#x8FC7AF #x6D0F)
+                (#x8FC7B0 #x6D11)
+                (#x8FC7B1 #x6D13)
+                (#x8FC7B2 #x6D1A)
+                (#x8FC7B3 #x6D26)
+                (#x8FC7B4 #x6D27)
+                (#x8FC7B5 #x6D28)
+                (#x8FC7B6 #x6C67)
+                (#x8FC7B7 #x6D2E)
+                (#x8FC7B8 #x6D2F)
+                (#x8FC7B9 #x6D31)
+                (#x8FC7BA #x6D39)
+                (#x8FC7BB #x6D3C)
+                (#x8FC7BC #x6D3F)
+                (#x8FC7BD #x6D57)
+                (#x8FC7BE #x6D5E)
+                (#x8FC7BF #x6D5F)
+                (#x8FC7C0 #x6D61)
+                (#x8FC7C1 #x6D65)
+                (#x8FC7C2 #x6D67)
+                (#x8FC7C3 #x6D6F)
+                (#x8FC7C4 #x6D70)
+                (#x8FC7C5 #x6D7C)
+                (#x8FC7C6 #x6D82)
+                (#x8FC7C7 #x6D87)
+                (#x8FC7C8 #x6D91)
+                (#x8FC7C9 #x6D92)
+                (#x8FC7CA #x6D94)
+                (#x8FC7CB #x6D96)
+                (#x8FC7CC #x6D97)
+                (#x8FC7CD #x6D98)
+                (#x8FC7CE #x6DAA)
+                (#x8FC7CF #x6DAC)
+                (#x8FC7D0 #x6DB4)
+                (#x8FC7D1 #x6DB7)
+                (#x8FC7D2 #x6DB9)
+                (#x8FC7D3 #x6DBD)
+                (#x8FC7D4 #x6DBF)
+                (#x8FC7D5 #x6DC4)
+                (#x8FC7D6 #x6DC8)
+                (#x8FC7D7 #x6DCA)
+                (#x8FC7D8 #x6DCE)
+                (#x8FC7D9 #x6DCF)
+                (#x8FC7DA #x6DD6)
+                (#x8FC7DB #x6DDB)
+                (#x8FC7DC #x6DDD)
+                (#x8FC7DD #x6DDF)
+                (#x8FC7DE #x6DE0)
+                (#x8FC7DF #x6DE2)
+                (#x8FC7E0 #x6DE5)
+                (#x8FC7E1 #x6DE9)
+                (#x8FC7E2 #x6DEF)
+                (#x8FC7E3 #x6DF0)
+                (#x8FC7E4 #x6DF4)
+                (#x8FC7E5 #x6DF6)
+                (#x8FC7E6 #x6DFC)
+                (#x8FC7E7 #x6E00)
+                (#x8FC7E8 #x6E04)
+                (#x8FC7E9 #x6E1E)
+                (#x8FC7EA #x6E22)
+                (#x8FC7EB #x6E27)
+                (#x8FC7EC #x6E32)
+                (#x8FC7ED #x6E36)
+                (#x8FC7EE #x6E39)
+                (#x8FC7EF #x6E3B)
+                (#x8FC7F0 #x6E3C)
+                (#x8FC7F1 #x6E44)
+                (#x8FC7F2 #x6E45)
+                (#x8FC7F3 #x6E48)
+                (#x8FC7F4 #x6E49)
+                (#x8FC7F5 #x6E4B)
+                (#x8FC7F6 #x6E4F)
+                (#x8FC7F7 #x6E51)
+                (#x8FC7F8 #x6E52)
+                (#x8FC7F9 #x6E53)
+                (#x8FC7FA #x6E54)
+                (#x8FC7FB #x6E57)
+                (#x8FC7FC #x6E5C)
+                (#x8FC7FD #x6E5D)
+                (#x8FC7FE #x6E5E)
+                (#x8FC8A1 #x6E62)
+                (#x8FC8A2 #x6E63)
+                (#x8FC8A3 #x6E68)
+                (#x8FC8A4 #x6E73)
+                (#x8FC8A5 #x6E7B)
+                (#x8FC8A6 #x6E7D)
+                (#x8FC8A7 #x6E8D)
+                (#x8FC8A8 #x6E93)
+                (#x8FC8A9 #x6E99)
+                (#x8FC8AA #x6EA0)
+                (#x8FC8AB #x6EA7)
+                (#x8FC8AC #x6EAD)
+                (#x8FC8AD #x6EAE)
+                (#x8FC8AE #x6EB1)
+                (#x8FC8AF #x6EB3)
+                (#x8FC8B0 #x6EBB)
+                (#x8FC8B1 #x6EBF)
+                (#x8FC8B2 #x6EC0)
+                (#x8FC8B3 #x6EC1)
+                (#x8FC8B4 #x6EC3)
+                (#x8FC8B5 #x6EC7)
+                (#x8FC8B6 #x6EC8)
+                (#x8FC8B7 #x6ECA)
+                (#x8FC8B8 #x6ECD)
+                (#x8FC8B9 #x6ECE)
+                (#x8FC8BA #x6ECF)
+                (#x8FC8BB #x6EEB)
+                (#x8FC8BC #x6EED)
+                (#x8FC8BD #x6EEE)
+                (#x8FC8BE #x6EF9)
+                (#x8FC8BF #x6EFB)
+                (#x8FC8C0 #x6EFD)
+                (#x8FC8C1 #x6F04)
+                (#x8FC8C2 #x6F08)
+                (#x8FC8C3 #x6F0A)
+                (#x8FC8C4 #x6F0C)
+                (#x8FC8C5 #x6F0D)
+                (#x8FC8C6 #x6F16)
+                (#x8FC8C7 #x6F18)
+                (#x8FC8C8 #x6F1A)
+                (#x8FC8C9 #x6F1B)
+                (#x8FC8CA #x6F26)
+                (#x8FC8CB #x6F29)
+                (#x8FC8CC #x6F2A)
+                (#x8FC8CD #x6F2F)
+                (#x8FC8CE #x6F30)
+                (#x8FC8CF #x6F33)
+                (#x8FC8D0 #x6F36)
+                (#x8FC8D1 #x6F3B)
+                (#x8FC8D2 #x6F3C)
+                (#x8FC8D3 #x6F2D)
+                (#x8FC8D4 #x6F4F)
+                (#x8FC8D5 #x6F51)
+                (#x8FC8D6 #x6F52)
+                (#x8FC8D7 #x6F53)
+                (#x8FC8D8 #x6F57)
+                (#x8FC8D9 #x6F59)
+                (#x8FC8DA #x6F5A)
+                (#x8FC8DB #x6F5D)
+                (#x8FC8DC #x6F5E)
+                (#x8FC8DD #x6F61)
+                (#x8FC8DE #x6F62)
+                (#x8FC8DF #x6F68)
+                (#x8FC8E0 #x6F6C)
+                (#x8FC8E1 #x6F7D)
+                (#x8FC8E2 #x6F7E)
+                (#x8FC8E3 #x6F83)
+                (#x8FC8E4 #x6F87)
+                (#x8FC8E5 #x6F88)
+                (#x8FC8E6 #x6F8B)
+                (#x8FC8E7 #x6F8C)
+                (#x8FC8E8 #x6F8D)
+                (#x8FC8E9 #x6F90)
+                (#x8FC8EA #x6F92)
+                (#x8FC8EB #x6F93)
+                (#x8FC8EC #x6F94)
+                (#x8FC8ED #x6F96)
+                (#x8FC8EE #x6F9A)
+                (#x8FC8EF #x6F9F)
+                (#x8FC8F0 #x6FA0)
+                (#x8FC8F1 #x6FA5)
+                (#x8FC8F2 #x6FA6)
+                (#x8FC8F3 #x6FA7)
+                (#x8FC8F4 #x6FA8)
+                (#x8FC8F5 #x6FAE)
+                (#x8FC8F6 #x6FAF)
+                (#x8FC8F7 #x6FB0)
+                (#x8FC8F8 #x6FB5)
+                (#x8FC8F9 #x6FB6)
+                (#x8FC8FA #x6FBC)
+                (#x8FC8FB #x6FC5)
+                (#x8FC8FC #x6FC7)
+                (#x8FC8FD #x6FC8)
+                (#x8FC8FE #x6FCA)
+                (#x8FC9A1 #x6FDA)
+                (#x8FC9A2 #x6FDE)
+                (#x8FC9A3 #x6FE8)
+                (#x8FC9A4 #x6FE9)
+                (#x8FC9A5 #x6FF0)
+                (#x8FC9A6 #x6FF5)
+                (#x8FC9A7 #x6FF9)
+                (#x8FC9A8 #x6FFC)
+                (#x8FC9A9 #x6FFD)
+                (#x8FC9AA #x7000)
+                (#x8FC9AB #x7005)
+                (#x8FC9AC #x7006)
+                (#x8FC9AD #x7007)
+                (#x8FC9AE #x700D)
+                (#x8FC9AF #x7017)
+                (#x8FC9B0 #x7020)
+                (#x8FC9B1 #x7023)
+                (#x8FC9B2 #x702F)
+                (#x8FC9B3 #x7034)
+                (#x8FC9B4 #x7037)
+                (#x8FC9B5 #x7039)
+                (#x8FC9B6 #x703C)
+                (#x8FC9B7 #x7043)
+                (#x8FC9B8 #x7044)
+                (#x8FC9B9 #x7048)
+                (#x8FC9BA #x7049)
+                (#x8FC9BB #x704A)
+                (#x8FC9BC #x704B)
+                (#x8FC9BD #x7054)
+                (#x8FC9BE #x7055)
+                (#x8FC9BF #x705D)
+                (#x8FC9C0 #x705E)
+                (#x8FC9C1 #x704E)
+                (#x8FC9C2 #x7064)
+                (#x8FC9C3 #x7065)
+                (#x8FC9C4 #x706C)
+                (#x8FC9C5 #x706E)
+                (#x8FC9C6 #x7075)
+                (#x8FC9C7 #x7076)
+                (#x8FC9C8 #x707E)
+                (#x8FC9C9 #x7081)
+                (#x8FC9CA #x7085)
+                (#x8FC9CB #x7086)
+                (#x8FC9CC #x7094)
+                (#x8FC9CD #x7095)
+                (#x8FC9CE #x7096)
+                (#x8FC9CF #x7097)
+                (#x8FC9D0 #x7098)
+                (#x8FC9D1 #x709B)
+                (#x8FC9D2 #x70A4)
+                (#x8FC9D3 #x70AB)
+                (#x8FC9D4 #x70B0)
+                (#x8FC9D5 #x70B1)
+                (#x8FC9D6 #x70B4)
+                (#x8FC9D7 #x70B7)
+                (#x8FC9D8 #x70CA)
+                (#x8FC9D9 #x70D1)
+                (#x8FC9DA #x70D3)
+                (#x8FC9DB #x70D4)
+                (#x8FC9DC #x70D5)
+                (#x8FC9DD #x70D6)
+                (#x8FC9DE #x70D8)
+                (#x8FC9DF #x70DC)
+                (#x8FC9E0 #x70E4)
+                (#x8FC9E1 #x70FA)
+                (#x8FC9E2 #x7103)
+                (#x8FC9E3 #x7104)
+                (#x8FC9E4 #x7105)
+                (#x8FC9E5 #x7106)
+                (#x8FC9E6 #x7107)
+                (#x8FC9E7 #x710B)
+                (#x8FC9E8 #x710C)
+                (#x8FC9E9 #x710F)
+                (#x8FC9EA #x711E)
+                (#x8FC9EB #x7120)
+                (#x8FC9EC #x712B)
+                (#x8FC9ED #x712D)
+                (#x8FC9EE #x712F)
+                (#x8FC9EF #x7130)
+                (#x8FC9F0 #x7131)
+                (#x8FC9F1 #x7138)
+                (#x8FC9F2 #x7141)
+                (#x8FC9F3 #x7145)
+                (#x8FC9F4 #x7146)
+                (#x8FC9F5 #x7147)
+                (#x8FC9F6 #x714A)
+                (#x8FC9F7 #x714B)
+                (#x8FC9F8 #x7150)
+                (#x8FC9F9 #x7152)
+                (#x8FC9FA #x7157)
+                (#x8FC9FB #x715A)
+                (#x8FC9FC #x715C)
+                (#x8FC9FD #x715E)
+                (#x8FC9FE #x7160)
+                (#x8FCAA1 #x7168)
+                (#x8FCAA2 #x7179)
+                (#x8FCAA3 #x7180)
+                (#x8FCAA4 #x7185)
+                (#x8FCAA5 #x7187)
+                (#x8FCAA6 #x718C)
+                (#x8FCAA7 #x7192)
+                (#x8FCAA8 #x719A)
+                (#x8FCAA9 #x719B)
+                (#x8FCAAA #x71A0)
+                (#x8FCAAB #x71A2)
+                (#x8FCAAC #x71AF)
+                (#x8FCAAD #x71B0)
+                (#x8FCAAE #x71B2)
+                (#x8FCAAF #x71B3)
+                (#x8FCAB0 #x71BA)
+                (#x8FCAB1 #x71BF)
+                (#x8FCAB2 #x71C0)
+                (#x8FCAB3 #x71C1)
+                (#x8FCAB4 #x71C4)
+                (#x8FCAB5 #x71CB)
+                (#x8FCAB6 #x71CC)
+                (#x8FCAB7 #x71D3)
+                (#x8FCAB8 #x71D6)
+                (#x8FCAB9 #x71D9)
+                (#x8FCABA #x71DA)
+                (#x8FCABB #x71DC)
+                (#x8FCABC #x71F8)
+                (#x8FCABD #x71FE)
+                (#x8FCABE #x7200)
+                (#x8FCABF #x7207)
+                (#x8FCAC0 #x7208)
+                (#x8FCAC1 #x7209)
+                (#x8FCAC2 #x7213)
+                (#x8FCAC3 #x7217)
+                (#x8FCAC4 #x721A)
+                (#x8FCAC5 #x721D)
+                (#x8FCAC6 #x721F)
+                (#x8FCAC7 #x7224)
+                (#x8FCAC8 #x722B)
+                (#x8FCAC9 #x722F)
+                (#x8FCACA #x7234)
+                (#x8FCACB #x7238)
+                (#x8FCACC #x7239)
+                (#x8FCACD #x7241)
+                (#x8FCACE #x7242)
+                (#x8FCACF #x7243)
+                (#x8FCAD0 #x7245)
+                (#x8FCAD1 #x724E)
+                (#x8FCAD2 #x724F)
+                (#x8FCAD3 #x7250)
+                (#x8FCAD4 #x7253)
+                (#x8FCAD5 #x7255)
+                (#x8FCAD6 #x7256)
+                (#x8FCAD7 #x725A)
+                (#x8FCAD8 #x725C)
+                (#x8FCAD9 #x725E)
+                (#x8FCADA #x7260)
+                (#x8FCADB #x7263)
+                (#x8FCADC #x7268)
+                (#x8FCADD #x726B)
+                (#x8FCADE #x726E)
+                (#x8FCADF #x726F)
+                (#x8FCAE0 #x7271)
+                (#x8FCAE1 #x7277)
+                (#x8FCAE2 #x7278)
+                (#x8FCAE3 #x727B)
+                (#x8FCAE4 #x727C)
+                (#x8FCAE5 #x727F)
+                (#x8FCAE6 #x7284)
+                (#x8FCAE7 #x7289)
+                (#x8FCAE8 #x728D)
+                (#x8FCAE9 #x728E)
+                (#x8FCAEA #x7293)
+                (#x8FCAEB #x729B)
+                (#x8FCAEC #x72A8)
+                (#x8FCAED #x72AD)
+                (#x8FCAEE #x72AE)
+                (#x8FCAEF #x72B1)
+                (#x8FCAF0 #x72B4)
+                (#x8FCAF1 #x72BE)
+                (#x8FCAF2 #x72C1)
+                (#x8FCAF3 #x72C7)
+                (#x8FCAF4 #x72C9)
+                (#x8FCAF5 #x72CC)
+                (#x8FCAF6 #x72D5)
+                (#x8FCAF7 #x72D6)
+                (#x8FCAF8 #x72D8)
+                (#x8FCAF9 #x72DF)
+                (#x8FCAFA #x72E5)
+                (#x8FCAFB #x72F3)
+                (#x8FCAFC #x72F4)
+                (#x8FCAFD #x72FA)
+                (#x8FCAFE #x72FB)
+                (#x8FCBA1 #x72FE)
+                (#x8FCBA2 #x7302)
+                (#x8FCBA3 #x7304)
+                (#x8FCBA4 #x7305)
+                (#x8FCBA5 #x7307)
+                (#x8FCBA6 #x730B)
+                (#x8FCBA7 #x730D)
+                (#x8FCBA8 #x7312)
+                (#x8FCBA9 #x7313)
+                (#x8FCBAA #x7318)
+                (#x8FCBAB #x7319)
+                (#x8FCBAC #x731E)
+                (#x8FCBAD #x7322)
+                (#x8FCBAE #x7324)
+                (#x8FCBAF #x7327)
+                (#x8FCBB0 #x7328)
+                (#x8FCBB1 #x732C)
+                (#x8FCBB2 #x7331)
+                (#x8FCBB3 #x7332)
+                (#x8FCBB4 #x7335)
+                (#x8FCBB5 #x733A)
+                (#x8FCBB6 #x733B)
+                (#x8FCBB7 #x733D)
+                (#x8FCBB8 #x7343)
+                (#x8FCBB9 #x734D)
+                (#x8FCBBA #x7350)
+                (#x8FCBBB #x7352)
+                (#x8FCBBC #x7356)
+                (#x8FCBBD #x7358)
+                (#x8FCBBE #x735D)
+                (#x8FCBBF #x735E)
+                (#x8FCBC0 #x735F)
+                (#x8FCBC1 #x7360)
+                (#x8FCBC2 #x7366)
+                (#x8FCBC3 #x7367)
+                (#x8FCBC4 #x7369)
+                (#x8FCBC5 #x736B)
+                (#x8FCBC6 #x736C)
+                (#x8FCBC7 #x736E)
+                (#x8FCBC8 #x736F)
+                (#x8FCBC9 #x7371)
+                (#x8FCBCA #x7377)
+                (#x8FCBCB #x7379)
+                (#x8FCBCC #x737C)
+                (#x8FCBCD #x7380)
+                (#x8FCBCE #x7381)
+                (#x8FCBCF #x7383)
+                (#x8FCBD0 #x7385)
+                (#x8FCBD1 #x7386)
+                (#x8FCBD2 #x738E)
+                (#x8FCBD3 #x7390)
+                (#x8FCBD4 #x7393)
+                (#x8FCBD5 #x7395)
+                (#x8FCBD6 #x7397)
+                (#x8FCBD7 #x7398)
+                (#x8FCBD8 #x739C)
+                (#x8FCBD9 #x739E)
+                (#x8FCBDA #x739F)
+                (#x8FCBDB #x73A0)
+                (#x8FCBDC #x73A2)
+                (#x8FCBDD #x73A5)
+                (#x8FCBDE #x73A6)
+                (#x8FCBDF #x73AA)
+                (#x8FCBE0 #x73AB)
+                (#x8FCBE1 #x73AD)
+                (#x8FCBE2 #x73B5)
+                (#x8FCBE3 #x73B7)
+                (#x8FCBE4 #x73B9)
+                (#x8FCBE5 #x73BC)
+                (#x8FCBE6 #x73BD)
+                (#x8FCBE7 #x73BF)
+                (#x8FCBE8 #x73C5)
+                (#x8FCBE9 #x73C6)
+                (#x8FCBEA #x73C9)
+                (#x8FCBEB #x73CB)
+                (#x8FCBEC #x73CC)
+                (#x8FCBED #x73CF)
+                (#x8FCBEE #x73D2)
+                (#x8FCBEF #x73D3)
+                (#x8FCBF0 #x73D6)
+                (#x8FCBF1 #x73D9)
+                (#x8FCBF2 #x73DD)
+                (#x8FCBF3 #x73E1)
+                (#x8FCBF4 #x73E3)
+                (#x8FCBF5 #x73E6)
+                (#x8FCBF6 #x73E7)
+                (#x8FCBF7 #x73E9)
+                (#x8FCBF8 #x73F4)
+                (#x8FCBF9 #x73F5)
+                (#x8FCBFA #x73F7)
+                (#x8FCBFB #x73F9)
+                (#x8FCBFC #x73FA)
+                (#x8FCBFD #x73FB)
+                (#x8FCBFE #x73FD)
+                (#x8FCCA1 #x73FF)
+                (#x8FCCA2 #x7400)
+                (#x8FCCA3 #x7401)
+                (#x8FCCA4 #x7404)
+                (#x8FCCA5 #x7407)
+                (#x8FCCA6 #x740A)
+                (#x8FCCA7 #x7411)
+                (#x8FCCA8 #x741A)
+                (#x8FCCA9 #x741B)
+                (#x8FCCAA #x7424)
+                (#x8FCCAB #x7426)
+                (#x8FCCAC #x7428)
+                (#x8FCCAD #x7429)
+                (#x8FCCAE #x742A)
+                (#x8FCCAF #x742B)
+                (#x8FCCB0 #x742C)
+                (#x8FCCB1 #x742D)
+                (#x8FCCB2 #x742E)
+                (#x8FCCB3 #x742F)
+                (#x8FCCB4 #x7430)
+                (#x8FCCB5 #x7431)
+                (#x8FCCB6 #x7439)
+                (#x8FCCB7 #x7440)
+                (#x8FCCB8 #x7443)
+                (#x8FCCB9 #x7444)
+                (#x8FCCBA #x7446)
+                (#x8FCCBB #x7447)
+                (#x8FCCBC #x744B)
+                (#x8FCCBD #x744D)
+                (#x8FCCBE #x7451)
+                (#x8FCCBF #x7452)
+                (#x8FCCC0 #x7457)
+                (#x8FCCC1 #x745D)
+                (#x8FCCC2 #x7462)
+                (#x8FCCC3 #x7466)
+                (#x8FCCC4 #x7467)
+                (#x8FCCC5 #x7468)
+                (#x8FCCC6 #x746B)
+                (#x8FCCC7 #x746D)
+                (#x8FCCC8 #x746E)
+                (#x8FCCC9 #x7471)
+                (#x8FCCCA #x7472)
+                (#x8FCCCB #x7480)
+                (#x8FCCCC #x7481)
+                (#x8FCCCD #x7485)
+                (#x8FCCCE #x7486)
+                (#x8FCCCF #x7487)
+                (#x8FCCD0 #x7489)
+                (#x8FCCD1 #x748F)
+                (#x8FCCD2 #x7490)
+                (#x8FCCD3 #x7491)
+                (#x8FCCD4 #x7492)
+                (#x8FCCD5 #x7498)
+                (#x8FCCD6 #x7499)
+                (#x8FCCD7 #x749A)
+                (#x8FCCD8 #x749C)
+                (#x8FCCD9 #x749F)
+                (#x8FCCDA #x74A0)
+                (#x8FCCDB #x74A1)
+                (#x8FCCDC #x74A3)
+                (#x8FCCDD #x74A6)
+                (#x8FCCDE #x74A8)
+                (#x8FCCDF #x74A9)
+                (#x8FCCE0 #x74AA)
+                (#x8FCCE1 #x74AB)
+                (#x8FCCE2 #x74AE)
+                (#x8FCCE3 #x74AF)
+                (#x8FCCE4 #x74B1)
+                (#x8FCCE5 #x74B2)
+                (#x8FCCE6 #x74B5)
+                (#x8FCCE7 #x74B9)
+                (#x8FCCE8 #x74BB)
+                (#x8FCCE9 #x74BF)
+                (#x8FCCEA #x74C8)
+                (#x8FCCEB #x74C9)
+                (#x8FCCEC #x74CC)
+                (#x8FCCED #x74D0)
+                (#x8FCCEE #x74D3)
+                (#x8FCCEF #x74D8)
+                (#x8FCCF0 #x74DA)
+                (#x8FCCF1 #x74DB)
+                (#x8FCCF2 #x74DE)
+                (#x8FCCF3 #x74DF)
+                (#x8FCCF4 #x74E4)
+                (#x8FCCF5 #x74E8)
+                (#x8FCCF6 #x74EA)
+                (#x8FCCF7 #x74EB)
+                (#x8FCCF8 #x74EF)
+                (#x8FCCF9 #x74F4)
+                (#x8FCCFA #x74FA)
+                (#x8FCCFB #x74FB)
+                (#x8FCCFC #x74FC)
+                (#x8FCCFD #x74FF)
+                (#x8FCCFE #x7506)
+                (#x8FCDA1 #x7512)
+                (#x8FCDA2 #x7516)
+                (#x8FCDA3 #x7517)
+                (#x8FCDA4 #x7520)
+                (#x8FCDA5 #x7521)
+                (#x8FCDA6 #x7524)
+                (#x8FCDA7 #x7527)
+                (#x8FCDA8 #x7529)
+                (#x8FCDA9 #x752A)
+                (#x8FCDAA #x752F)
+                (#x8FCDAB #x7536)
+                (#x8FCDAC #x7539)
+                (#x8FCDAD #x753D)
+                (#x8FCDAE #x753E)
+                (#x8FCDAF #x753F)
+                (#x8FCDB0 #x7540)
+                (#x8FCDB1 #x7543)
+                (#x8FCDB2 #x7547)
+                (#x8FCDB3 #x7548)
+                (#x8FCDB4 #x754E)
+                (#x8FCDB5 #x7550)
+                (#x8FCDB6 #x7552)
+                (#x8FCDB7 #x7557)
+                (#x8FCDB8 #x755E)
+                (#x8FCDB9 #x755F)
+                (#x8FCDBA #x7561)
+                (#x8FCDBB #x756F)
+                (#x8FCDBC #x7571)
+                (#x8FCDBD #x7579)
+                (#x8FCDBE #x757A)
+                (#x8FCDBF #x757B)
+                (#x8FCDC0 #x757C)
+                (#x8FCDC1 #x757D)
+                (#x8FCDC2 #x757E)
+                (#x8FCDC3 #x7581)
+                (#x8FCDC4 #x7585)
+                (#x8FCDC5 #x7590)
+                (#x8FCDC6 #x7592)
+                (#x8FCDC7 #x7593)
+                (#x8FCDC8 #x7595)
+                (#x8FCDC9 #x7599)
+                (#x8FCDCA #x759C)
+                (#x8FCDCB #x75A2)
+                (#x8FCDCC #x75A4)
+                (#x8FCDCD #x75B4)
+                (#x8FCDCE #x75BA)
+                (#x8FCDCF #x75BF)
+                (#x8FCDD0 #x75C0)
+                (#x8FCDD1 #x75C1)
+                (#x8FCDD2 #x75C4)
+                (#x8FCDD3 #x75C6)
+                (#x8FCDD4 #x75CC)
+                (#x8FCDD5 #x75CE)
+                (#x8FCDD6 #x75CF)
+                (#x8FCDD7 #x75D7)
+                (#x8FCDD8 #x75DC)
+                (#x8FCDD9 #x75DF)
+                (#x8FCDDA #x75E0)
+                (#x8FCDDB #x75E1)
+                (#x8FCDDC #x75E4)
+                (#x8FCDDD #x75E7)
+                (#x8FCDDE #x75EC)
+                (#x8FCDDF #x75EE)
+                (#x8FCDE0 #x75EF)
+                (#x8FCDE1 #x75F1)
+                (#x8FCDE2 #x75F9)
+                (#x8FCDE3 #x7600)
+                (#x8FCDE4 #x7602)
+                (#x8FCDE5 #x7603)
+                (#x8FCDE6 #x7604)
+                (#x8FCDE7 #x7607)
+                (#x8FCDE8 #x7608)
+                (#x8FCDE9 #x760A)
+                (#x8FCDEA #x760C)
+                (#x8FCDEB #x760F)
+                (#x8FCDEC #x7612)
+                (#x8FCDED #x7613)
+                (#x8FCDEE #x7615)
+                (#x8FCDEF #x7616)
+                (#x8FCDF0 #x7619)
+                (#x8FCDF1 #x761B)
+                (#x8FCDF2 #x761C)
+                (#x8FCDF3 #x761D)
+                (#x8FCDF4 #x761E)
+                (#x8FCDF5 #x7623)
+                (#x8FCDF6 #x7625)
+                (#x8FCDF7 #x7626)
+                (#x8FCDF8 #x7629)
+                (#x8FCDF9 #x762D)
+                (#x8FCDFA #x7632)
+                (#x8FCDFB #x7633)
+                (#x8FCDFC #x7635)
+                (#x8FCDFD #x7638)
+                (#x8FCDFE #x7639)
+                (#x8FCEA1 #x763A)
+                (#x8FCEA2 #x763C)
+                (#x8FCEA3 #x764A)
+                (#x8FCEA4 #x7640)
+                (#x8FCEA5 #x7641)
+                (#x8FCEA6 #x7643)
+                (#x8FCEA7 #x7644)
+                (#x8FCEA8 #x7645)
+                (#x8FCEA9 #x7649)
+                (#x8FCEAA #x764B)
+                (#x8FCEAB #x7655)
+                (#x8FCEAC #x7659)
+                (#x8FCEAD #x765F)
+                (#x8FCEAE #x7664)
+                (#x8FCEAF #x7665)
+                (#x8FCEB0 #x766D)
+                (#x8FCEB1 #x766E)
+                (#x8FCEB2 #x766F)
+                (#x8FCEB3 #x7671)
+                (#x8FCEB4 #x7674)
+                (#x8FCEB5 #x7681)
+                (#x8FCEB6 #x7685)
+                (#x8FCEB7 #x768C)
+                (#x8FCEB8 #x768D)
+                (#x8FCEB9 #x7695)
+                (#x8FCEBA #x769B)
+                (#x8FCEBB #x769C)
+                (#x8FCEBC #x769D)
+                (#x8FCEBD #x769F)
+                (#x8FCEBE #x76A0)
+                (#x8FCEBF #x76A2)
+                (#x8FCEC0 #x76A3)
+                (#x8FCEC1 #x76A4)
+                (#x8FCEC2 #x76A5)
+                (#x8FCEC3 #x76A6)
+                (#x8FCEC4 #x76A7)
+                (#x8FCEC5 #x76A8)
+                (#x8FCEC6 #x76AA)
+                (#x8FCEC7 #x76AD)
+                (#x8FCEC8 #x76BD)
+                (#x8FCEC9 #x76C1)
+                (#x8FCECA #x76C5)
+                (#x8FCECB #x76C9)
+                (#x8FCECC #x76CB)
+                (#x8FCECD #x76CC)
+                (#x8FCECE #x76CE)
+                (#x8FCECF #x76D4)
+                (#x8FCED0 #x76D9)
+                (#x8FCED1 #x76E0)
+                (#x8FCED2 #x76E6)
+                (#x8FCED3 #x76E8)
+                (#x8FCED4 #x76EC)
+                (#x8FCED5 #x76F0)
+                (#x8FCED6 #x76F1)
+                (#x8FCED7 #x76F6)
+                (#x8FCED8 #x76F9)
+                (#x8FCED9 #x76FC)
+                (#x8FCEDA #x7700)
+                (#x8FCEDB #x7706)
+                (#x8FCEDC #x770A)
+                (#x8FCEDD #x770E)
+                (#x8FCEDE #x7712)
+                (#x8FCEDF #x7714)
+                (#x8FCEE0 #x7715)
+                (#x8FCEE1 #x7717)
+                (#x8FCEE2 #x7719)
+                (#x8FCEE3 #x771A)
+                (#x8FCEE4 #x771C)
+                (#x8FCEE5 #x7722)
+                (#x8FCEE6 #x7728)
+                (#x8FCEE7 #x772D)
+                (#x8FCEE8 #x772E)
+                (#x8FCEE9 #x772F)
+                (#x8FCEEA #x7734)
+                (#x8FCEEB #x7735)
+                (#x8FCEEC #x7736)
+                (#x8FCEED #x7739)
+                (#x8FCEEE #x773D)
+                (#x8FCEEF #x773E)
+                (#x8FCEF0 #x7742)
+                (#x8FCEF1 #x7745)
+                (#x8FCEF2 #x7746)
+                (#x8FCEF3 #x774A)
+                (#x8FCEF4 #x774D)
+                (#x8FCEF5 #x774E)
+                (#x8FCEF6 #x774F)
+                (#x8FCEF7 #x7752)
+                (#x8FCEF8 #x7756)
+                (#x8FCEF9 #x7757)
+                (#x8FCEFA #x775C)
+                (#x8FCEFB #x775E)
+                (#x8FCEFC #x775F)
+                (#x8FCEFD #x7760)
+                (#x8FCEFE #x7762)
+                (#x8FCFA1 #x7764)
+                (#x8FCFA2 #x7767)
+                (#x8FCFA3 #x776A)
+                (#x8FCFA4 #x776C)
+                (#x8FCFA5 #x7770)
+                (#x8FCFA6 #x7772)
+                (#x8FCFA7 #x7773)
+                (#x8FCFA8 #x7774)
+                (#x8FCFA9 #x777A)
+                (#x8FCFAA #x777D)
+                (#x8FCFAB #x7780)
+                (#x8FCFAC #x7784)
+                (#x8FCFAD #x778C)
+                (#x8FCFAE #x778D)
+                (#x8FCFAF #x7794)
+                (#x8FCFB0 #x7795)
+                (#x8FCFB1 #x7796)
+                (#x8FCFB2 #x779A)
+                (#x8FCFB3 #x779F)
+                (#x8FCFB4 #x77A2)
+                (#x8FCFB5 #x77A7)
+                (#x8FCFB6 #x77AA)
+                (#x8FCFB7 #x77AE)
+                (#x8FCFB8 #x77AF)
+                (#x8FCFB9 #x77B1)
+                (#x8FCFBA #x77B5)
+                (#x8FCFBB #x77BE)
+                (#x8FCFBC #x77C3)
+                (#x8FCFBD #x77C9)
+                (#x8FCFBE #x77D1)
+                (#x8FCFBF #x77D2)
+                (#x8FCFC0 #x77D5)
+                (#x8FCFC1 #x77D9)
+                (#x8FCFC2 #x77DE)
+                (#x8FCFC3 #x77DF)
+                (#x8FCFC4 #x77E0)
+                (#x8FCFC5 #x77E4)
+                (#x8FCFC6 #x77E6)
+                (#x8FCFC7 #x77EA)
+                (#x8FCFC8 #x77EC)
+                (#x8FCFC9 #x77F0)
+                (#x8FCFCA #x77F1)
+                (#x8FCFCB #x77F4)
+                (#x8FCFCC #x77F8)
+                (#x8FCFCD #x77FB)
+                (#x8FCFCE #x7805)
+                (#x8FCFCF #x7806)
+                (#x8FCFD0 #x7809)
+                (#x8FCFD1 #x780D)
+                (#x8FCFD2 #x780E)
+                (#x8FCFD3 #x7811)
+                (#x8FCFD4 #x781D)
+                (#x8FCFD5 #x7821)
+                (#x8FCFD6 #x7822)
+                (#x8FCFD7 #x7823)
+                (#x8FCFD8 #x782D)
+                (#x8FCFD9 #x782E)
+                (#x8FCFDA #x7830)
+                (#x8FCFDB #x7835)
+                (#x8FCFDC #x7837)
+                (#x8FCFDD #x7843)
+                (#x8FCFDE #x7844)
+                (#x8FCFDF #x7847)
+                (#x8FCFE0 #x7848)
+                (#x8FCFE1 #x784C)
+                (#x8FCFE2 #x784E)
+                (#x8FCFE3 #x7852)
+                (#x8FCFE4 #x785C)
+                (#x8FCFE5 #x785E)
+                (#x8FCFE6 #x7860)
+                (#x8FCFE7 #x7861)
+                (#x8FCFE8 #x7863)
+                (#x8FCFE9 #x7864)
+                (#x8FCFEA #x7868)
+                (#x8FCFEB #x786A)
+                (#x8FCFEC #x786E)
+                (#x8FCFED #x787A)
+                (#x8FCFEE #x787E)
+                (#x8FCFEF #x788A)
+                (#x8FCFF0 #x788F)
+                (#x8FCFF1 #x7894)
+                (#x8FCFF2 #x7898)
+                (#x8FCFF3 #x78A1)
+                (#x8FCFF4 #x789D)
+                (#x8FCFF5 #x789E)
+                (#x8FCFF6 #x789F)
+                (#x8FCFF7 #x78A4)
+                (#x8FCFF8 #x78A8)
+                (#x8FCFF9 #x78AC)
+                (#x8FCFFA #x78AD)
+                (#x8FCFFB #x78B0)
+                (#x8FCFFC #x78B1)
+                (#x8FCFFD #x78B2)
+                (#x8FCFFE #x78B3)
+                (#x8FD0A1 #x78BB)
+                (#x8FD0A2 #x78BD)
+                (#x8FD0A3 #x78BF)
+                (#x8FD0A4 #x78C7)
+                (#x8FD0A5 #x78C8)
+                (#x8FD0A6 #x78C9)
+                (#x8FD0A7 #x78CC)
+                (#x8FD0A8 #x78CE)
+                (#x8FD0A9 #x78D2)
+                (#x8FD0AA #x78D3)
+                (#x8FD0AB #x78D5)
+                (#x8FD0AC #x78D6)
+                (#x8FD0AD #x78E4)
+                (#x8FD0AE #x78DB)
+                (#x8FD0AF #x78DF)
+                (#x8FD0B0 #x78E0)
+                (#x8FD0B1 #x78E1)
+                (#x8FD0B2 #x78E6)
+                (#x8FD0B3 #x78EA)
+                (#x8FD0B4 #x78F2)
+                (#x8FD0B5 #x78F3)
+                (#x8FD0B6 #x7900)
+                (#x8FD0B7 #x78F6)
+                (#x8FD0B8 #x78F7)
+                (#x8FD0B9 #x78FA)
+                (#x8FD0BA #x78FB)
+                (#x8FD0BB #x78FF)
+                (#x8FD0BC #x7906)
+                (#x8FD0BD #x790C)
+                (#x8FD0BE #x7910)
+                (#x8FD0BF #x791A)
+                (#x8FD0C0 #x791C)
+                (#x8FD0C1 #x791E)
+                (#x8FD0C2 #x791F)
+                (#x8FD0C3 #x7920)
+                (#x8FD0C4 #x7925)
+                (#x8FD0C5 #x7927)
+                (#x8FD0C6 #x7929)
+                (#x8FD0C7 #x792D)
+                (#x8FD0C8 #x7931)
+                (#x8FD0C9 #x7934)
+                (#x8FD0CA #x7935)
+                (#x8FD0CB #x793B)
+                (#x8FD0CC #x793D)
+                (#x8FD0CD #x793F)
+                (#x8FD0CE #x7944)
+                (#x8FD0CF #x7945)
+                (#x8FD0D0 #x7946)
+                (#x8FD0D1 #x794A)
+                (#x8FD0D2 #x794B)
+                (#x8FD0D3 #x794F)
+                (#x8FD0D4 #x7951)
+                (#x8FD0D5 #x7954)
+                (#x8FD0D6 #x7958)
+                (#x8FD0D7 #x795B)
+                (#x8FD0D8 #x795C)
+                (#x8FD0D9 #x7967)
+                (#x8FD0DA #x7969)
+                (#x8FD0DB #x796B)
+                (#x8FD0DC #x7972)
+                (#x8FD0DD #x7979)
+                (#x8FD0DE #x797B)
+                (#x8FD0DF #x797C)
+                (#x8FD0E0 #x797E)
+                (#x8FD0E1 #x798B)
+                (#x8FD0E2 #x798C)
+                (#x8FD0E3 #x7991)
+                (#x8FD0E4 #x7993)
+                (#x8FD0E5 #x7994)
+                (#x8FD0E6 #x7995)
+                (#x8FD0E7 #x7996)
+                (#x8FD0E8 #x7998)
+                (#x8FD0E9 #x799B)
+                (#x8FD0EA #x799C)
+                (#x8FD0EB #x79A1)
+                (#x8FD0EC #x79A8)
+                (#x8FD0ED #x79A9)
+                (#x8FD0EE #x79AB)
+                (#x8FD0EF #x79AF)
+                (#x8FD0F0 #x79B1)
+                (#x8FD0F1 #x79B4)
+                (#x8FD0F2 #x79B8)
+                (#x8FD0F3 #x79BB)
+                (#x8FD0F4 #x79C2)
+                (#x8FD0F5 #x79C4)
+                (#x8FD0F6 #x79C7)
+                (#x8FD0F7 #x79C8)
+                (#x8FD0F8 #x79CA)
+                (#x8FD0F9 #x79CF)
+                (#x8FD0FA #x79D4)
+                (#x8FD0FB #x79D6)
+                (#x8FD0FC #x79DA)
+                (#x8FD0FD #x79DD)
+                (#x8FD0FE #x79DE)
+                (#x8FD1A1 #x79E0)
+                (#x8FD1A2 #x79E2)
+                (#x8FD1A3 #x79E5)
+                (#x8FD1A4 #x79EA)
+                (#x8FD1A5 #x79EB)
+                (#x8FD1A6 #x79ED)
+                (#x8FD1A7 #x79F1)
+                (#x8FD1A8 #x79F8)
+                (#x8FD1A9 #x79FC)
+                (#x8FD1AA #x7A02)
+                (#x8FD1AB #x7A03)
+                (#x8FD1AC #x7A07)
+                (#x8FD1AD #x7A09)
+                (#x8FD1AE #x7A0A)
+                (#x8FD1AF #x7A0C)
+                (#x8FD1B0 #x7A11)
+                (#x8FD1B1 #x7A15)
+                (#x8FD1B2 #x7A1B)
+                (#x8FD1B3 #x7A1E)
+                (#x8FD1B4 #x7A21)
+                (#x8FD1B5 #x7A27)
+                (#x8FD1B6 #x7A2B)
+                (#x8FD1B7 #x7A2D)
+                (#x8FD1B8 #x7A2F)
+                (#x8FD1B9 #x7A30)
+                (#x8FD1BA #x7A34)
+                (#x8FD1BB #x7A35)
+                (#x8FD1BC #x7A38)
+                (#x8FD1BD #x7A39)
+                (#x8FD1BE #x7A3A)
+                (#x8FD1BF #x7A44)
+                (#x8FD1C0 #x7A45)
+                (#x8FD1C1 #x7A47)
+                (#x8FD1C2 #x7A48)
+                (#x8FD1C3 #x7A4C)
+                (#x8FD1C4 #x7A55)
+                (#x8FD1C5 #x7A56)
+                (#x8FD1C6 #x7A59)
+                (#x8FD1C7 #x7A5C)
+                (#x8FD1C8 #x7A5D)
+                (#x8FD1C9 #x7A5F)
+                (#x8FD1CA #x7A60)
+                (#x8FD1CB #x7A65)
+                (#x8FD1CC #x7A67)
+                (#x8FD1CD #x7A6A)
+                (#x8FD1CE #x7A6D)
+                (#x8FD1CF #x7A75)
+                (#x8FD1D0 #x7A78)
+                (#x8FD1D1 #x7A7E)
+                (#x8FD1D2 #x7A80)
+                (#x8FD1D3 #x7A82)
+                (#x8FD1D4 #x7A85)
+                (#x8FD1D5 #x7A86)
+                (#x8FD1D6 #x7A8A)
+                (#x8FD1D7 #x7A8B)
+                (#x8FD1D8 #x7A90)
+                (#x8FD1D9 #x7A91)
+                (#x8FD1DA #x7A94)
+                (#x8FD1DB #x7A9E)
+                (#x8FD1DC #x7AA0)
+                (#x8FD1DD #x7AA3)
+                (#x8FD1DE #x7AAC)
+                (#x8FD1DF #x7AB3)
+                (#x8FD1E0 #x7AB5)
+                (#x8FD1E1 #x7AB9)
+                (#x8FD1E2 #x7ABB)
+                (#x8FD1E3 #x7ABC)
+                (#x8FD1E4 #x7AC6)
+                (#x8FD1E5 #x7AC9)
+                (#x8FD1E6 #x7ACC)
+                (#x8FD1E7 #x7ACE)
+                (#x8FD1E8 #x7AD1)
+                (#x8FD1E9 #x7ADB)
+                (#x8FD1EA #x7AE8)
+                (#x8FD1EB #x7AE9)
+                (#x8FD1EC #x7AEB)
+                (#x8FD1ED #x7AEC)
+                (#x8FD1EE #x7AF1)
+                (#x8FD1EF #x7AF4)
+                (#x8FD1F0 #x7AFB)
+                (#x8FD1F1 #x7AFD)
+                (#x8FD1F2 #x7AFE)
+                (#x8FD1F3 #x7B07)
+                (#x8FD1F4 #x7B14)
+                (#x8FD1F5 #x7B1F)
+                (#x8FD1F6 #x7B23)
+                (#x8FD1F7 #x7B27)
+                (#x8FD1F8 #x7B29)
+                (#x8FD1F9 #x7B2A)
+                (#x8FD1FA #x7B2B)
+                (#x8FD1FB #x7B2D)
+                (#x8FD1FC #x7B2E)
+                (#x8FD1FD #x7B2F)
+                (#x8FD1FE #x7B30)
+                (#x8FD2A1 #x7B31)
+                (#x8FD2A2 #x7B34)
+                (#x8FD2A3 #x7B3D)
+                (#x8FD2A4 #x7B3F)
+                (#x8FD2A5 #x7B40)
+                (#x8FD2A6 #x7B41)
+                (#x8FD2A7 #x7B47)
+                (#x8FD2A8 #x7B4E)
+                (#x8FD2A9 #x7B55)
+                (#x8FD2AA #x7B60)
+                (#x8FD2AB #x7B64)
+                (#x8FD2AC #x7B66)
+                (#x8FD2AD #x7B69)
+                (#x8FD2AE #x7B6A)
+                (#x8FD2AF #x7B6D)
+                (#x8FD2B0 #x7B6F)
+                (#x8FD2B1 #x7B72)
+                (#x8FD2B2 #x7B73)
+                (#x8FD2B3 #x7B77)
+                (#x8FD2B4 #x7B84)
+                (#x8FD2B5 #x7B89)
+                (#x8FD2B6 #x7B8E)
+                (#x8FD2B7 #x7B90)
+                (#x8FD2B8 #x7B91)
+                (#x8FD2B9 #x7B96)
+                (#x8FD2BA #x7B9B)
+                (#x8FD2BB #x7B9E)
+                (#x8FD2BC #x7BA0)
+                (#x8FD2BD #x7BA5)
+                (#x8FD2BE #x7BAC)
+                (#x8FD2BF #x7BAF)
+                (#x8FD2C0 #x7BB0)
+                (#x8FD2C1 #x7BB2)
+                (#x8FD2C2 #x7BB5)
+                (#x8FD2C3 #x7BB6)
+                (#x8FD2C4 #x7BBA)
+                (#x8FD2C5 #x7BBB)
+                (#x8FD2C6 #x7BBC)
+                (#x8FD2C7 #x7BBD)
+                (#x8FD2C8 #x7BC2)
+                (#x8FD2C9 #x7BC5)
+                (#x8FD2CA #x7BC8)
+                (#x8FD2CB #x7BCA)
+                (#x8FD2CC #x7BD4)
+                (#x8FD2CD #x7BD6)
+                (#x8FD2CE #x7BD7)
+                (#x8FD2CF #x7BD9)
+                (#x8FD2D0 #x7BDA)
+                (#x8FD2D1 #x7BDB)
+                (#x8FD2D2 #x7BE8)
+                (#x8FD2D3 #x7BEA)
+                (#x8FD2D4 #x7BF2)
+                (#x8FD2D5 #x7BF4)
+                (#x8FD2D6 #x7BF5)
+                (#x8FD2D7 #x7BF8)
+                (#x8FD2D8 #x7BF9)
+                (#x8FD2D9 #x7BFA)
+                (#x8FD2DA #x7BFC)
+                (#x8FD2DB #x7BFE)
+                (#x8FD2DC #x7C01)
+                (#x8FD2DD #x7C02)
+                (#x8FD2DE #x7C03)
+                (#x8FD2DF #x7C04)
+                (#x8FD2E0 #x7C06)
+                (#x8FD2E1 #x7C09)
+                (#x8FD2E2 #x7C0B)
+                (#x8FD2E3 #x7C0C)
+                (#x8FD2E4 #x7C0E)
+                (#x8FD2E5 #x7C0F)
+                (#x8FD2E6 #x7C19)
+                (#x8FD2E7 #x7C1B)
+                (#x8FD2E8 #x7C20)
+                (#x8FD2E9 #x7C25)
+                (#x8FD2EA #x7C26)
+                (#x8FD2EB #x7C28)
+                (#x8FD2EC #x7C2C)
+                (#x8FD2ED #x7C31)
+                (#x8FD2EE #x7C33)
+                (#x8FD2EF #x7C34)
+                (#x8FD2F0 #x7C36)
+                (#x8FD2F1 #x7C39)
+                (#x8FD2F2 #x7C3A)
+                (#x8FD2F3 #x7C46)
+                (#x8FD2F4 #x7C4A)
+                (#x8FD2F5 #x7C55)
+                (#x8FD2F6 #x7C51)
+                (#x8FD2F7 #x7C52)
+                (#x8FD2F8 #x7C53)
+                (#x8FD2F9 #x7C59)
+                (#x8FD2FA #x7C5A)
+                (#x8FD2FB #x7C5B)
+                (#x8FD2FC #x7C5C)
+                (#x8FD2FD #x7C5D)
+                (#x8FD2FE #x7C5E)
+                (#x8FD3A1 #x7C61)
+                (#x8FD3A2 #x7C63)
+                (#x8FD3A3 #x7C67)
+                (#x8FD3A4 #x7C69)
+                (#x8FD3A5 #x7C6D)
+                (#x8FD3A6 #x7C6E)
+                (#x8FD3A7 #x7C70)
+                (#x8FD3A8 #x7C72)
+                (#x8FD3A9 #x7C79)
+                (#x8FD3AA #x7C7C)
+                (#x8FD3AB #x7C7D)
+                (#x8FD3AC #x7C86)
+                (#x8FD3AD #x7C87)
+                (#x8FD3AE #x7C8F)
+                (#x8FD3AF #x7C94)
+                (#x8FD3B0 #x7C9E)
+                (#x8FD3B1 #x7CA0)
+                (#x8FD3B2 #x7CA6)
+                (#x8FD3B3 #x7CB0)
+                (#x8FD3B4 #x7CB6)
+                (#x8FD3B5 #x7CB7)
+                (#x8FD3B6 #x7CBA)
+                (#x8FD3B7 #x7CBB)
+                (#x8FD3B8 #x7CBC)
+                (#x8FD3B9 #x7CBF)
+                (#x8FD3BA #x7CC4)
+                (#x8FD3BB #x7CC7)
+                (#x8FD3BC #x7CC8)
+                (#x8FD3BD #x7CC9)
+                (#x8FD3BE #x7CCD)
+                (#x8FD3BF #x7CCF)
+                (#x8FD3C0 #x7CD3)
+                (#x8FD3C1 #x7CD4)
+                (#x8FD3C2 #x7CD5)
+                (#x8FD3C3 #x7CD7)
+                (#x8FD3C4 #x7CD9)
+                (#x8FD3C5 #x7CDA)
+                (#x8FD3C6 #x7CDD)
+                (#x8FD3C7 #x7CE6)
+                (#x8FD3C8 #x7CE9)
+                (#x8FD3C9 #x7CEB)
+                (#x8FD3CA #x7CF5)
+                (#x8FD3CB #x7D03)
+                (#x8FD3CC #x7D07)
+                (#x8FD3CD #x7D08)
+                (#x8FD3CE #x7D09)
+                (#x8FD3CF #x7D0F)
+                (#x8FD3D0 #x7D11)
+                (#x8FD3D1 #x7D12)
+                (#x8FD3D2 #x7D13)
+                (#x8FD3D3 #x7D16)
+                (#x8FD3D4 #x7D1D)
+                (#x8FD3D5 #x7D1E)
+                (#x8FD3D6 #x7D23)
+                (#x8FD3D7 #x7D26)
+                (#x8FD3D8 #x7D2A)
+                (#x8FD3D9 #x7D2D)
+                (#x8FD3DA #x7D31)
+                (#x8FD3DB #x7D3C)
+                (#x8FD3DC #x7D3D)
+                (#x8FD3DD #x7D3E)
+                (#x8FD3DE #x7D40)
+                (#x8FD3DF #x7D41)
+                (#x8FD3E0 #x7D47)
+                (#x8FD3E1 #x7D48)
+                (#x8FD3E2 #x7D4D)
+                (#x8FD3E3 #x7D51)
+                (#x8FD3E4 #x7D53)
+                (#x8FD3E5 #x7D57)
+                (#x8FD3E6 #x7D59)
+                (#x8FD3E7 #x7D5A)
+                (#x8FD3E8 #x7D5C)
+                (#x8FD3E9 #x7D5D)
+                (#x8FD3EA #x7D65)
+                (#x8FD3EB #x7D67)
+                (#x8FD3EC #x7D6A)
+                (#x8FD3ED #x7D70)
+                (#x8FD3EE #x7D78)
+                (#x8FD3EF #x7D7A)
+                (#x8FD3F0 #x7D7B)
+                (#x8FD3F1 #x7D7F)
+                (#x8FD3F2 #x7D81)
+                (#x8FD3F3 #x7D82)
+                (#x8FD3F4 #x7D83)
+                (#x8FD3F5 #x7D85)
+                (#x8FD3F6 #x7D86)
+                (#x8FD3F7 #x7D88)
+                (#x8FD3F8 #x7D8B)
+                (#x8FD3F9 #x7D8C)
+                (#x8FD3FA #x7D8D)
+                (#x8FD3FB #x7D91)
+                (#x8FD3FC #x7D96)
+                (#x8FD3FD #x7D97)
+                (#x8FD3FE #x7D9D)
+                (#x8FD4A1 #x7D9E)
+                (#x8FD4A2 #x7DA6)
+                (#x8FD4A3 #x7DA7)
+                (#x8FD4A4 #x7DAA)
+                (#x8FD4A5 #x7DB3)
+                (#x8FD4A6 #x7DB6)
+                (#x8FD4A7 #x7DB7)
+                (#x8FD4A8 #x7DB9)
+                (#x8FD4A9 #x7DC2)
+                (#x8FD4AA #x7DC3)
+                (#x8FD4AB #x7DC4)
+                (#x8FD4AC #x7DC5)
+                (#x8FD4AD #x7DC6)
+                (#x8FD4AE #x7DCC)
+                (#x8FD4AF #x7DCD)
+                (#x8FD4B0 #x7DCE)
+                (#x8FD4B1 #x7DD7)
+                (#x8FD4B2 #x7DD9)
+                (#x8FD4B3 #x7E00)
+                (#x8FD4B4 #x7DE2)
+                (#x8FD4B5 #x7DE5)
+                (#x8FD4B6 #x7DE6)
+                (#x8FD4B7 #x7DEA)
+                (#x8FD4B8 #x7DEB)
+                (#x8FD4B9 #x7DED)
+                (#x8FD4BA #x7DF1)
+                (#x8FD4BB #x7DF5)
+                (#x8FD4BC #x7DF6)
+                (#x8FD4BD #x7DF9)
+                (#x8FD4BE #x7DFA)
+                (#x8FD4BF #x7E08)
+                (#x8FD4C0 #x7E10)
+                (#x8FD4C1 #x7E11)
+                (#x8FD4C2 #x7E15)
+                (#x8FD4C3 #x7E17)
+                (#x8FD4C4 #x7E1C)
+                (#x8FD4C5 #x7E1D)
+                (#x8FD4C6 #x7E20)
+                (#x8FD4C7 #x7E27)
+                (#x8FD4C8 #x7E28)
+                (#x8FD4C9 #x7E2C)
+                (#x8FD4CA #x7E2D)
+                (#x8FD4CB #x7E2F)
+                (#x8FD4CC #x7E33)
+                (#x8FD4CD #x7E36)
+                (#x8FD4CE #x7E3F)
+                (#x8FD4CF #x7E44)
+                (#x8FD4D0 #x7E45)
+                (#x8FD4D1 #x7E47)
+                (#x8FD4D2 #x7E4E)
+                (#x8FD4D3 #x7E50)
+                (#x8FD4D4 #x7E52)
+                (#x8FD4D5 #x7E58)
+                (#x8FD4D6 #x7E5F)
+                (#x8FD4D7 #x7E61)
+                (#x8FD4D8 #x7E62)
+                (#x8FD4D9 #x7E65)
+                (#x8FD4DA #x7E6B)
+                (#x8FD4DB #x7E6E)
+                (#x8FD4DC #x7E6F)
+                (#x8FD4DD #x7E73)
+                (#x8FD4DE #x7E78)
+                (#x8FD4DF #x7E7E)
+                (#x8FD4E0 #x7E81)
+                (#x8FD4E1 #x7E86)
+                (#x8FD4E2 #x7E87)
+                (#x8FD4E3 #x7E8A)
+                (#x8FD4E4 #x7E8D)
+                (#x8FD4E5 #x7E91)
+                (#x8FD4E6 #x7E95)
+                (#x8FD4E7 #x7E98)
+                (#x8FD4E8 #x7E9A)
+                (#x8FD4E9 #x7E9D)
+                (#x8FD4EA #x7E9E)
+                (#x8FD4EB #x7F3C)
+                (#x8FD4EC #x7F3B)
+                (#x8FD4ED #x7F3D)
+                (#x8FD4EE #x7F3E)
+                (#x8FD4EF #x7F3F)
+                (#x8FD4F0 #x7F43)
+                (#x8FD4F1 #x7F44)
+                (#x8FD4F2 #x7F47)
+                (#x8FD4F3 #x7F4F)
+                (#x8FD4F4 #x7F52)
+                (#x8FD4F5 #x7F53)
+                (#x8FD4F6 #x7F5B)
+                (#x8FD4F7 #x7F5C)
+                (#x8FD4F8 #x7F5D)
+                (#x8FD4F9 #x7F61)
+                (#x8FD4FA #x7F63)
+                (#x8FD4FB #x7F64)
+                (#x8FD4FC #x7F65)
+                (#x8FD4FD #x7F66)
+                (#x8FD4FE #x7F6D)
+                (#x8FD5A1 #x7F71)
+                (#x8FD5A2 #x7F7D)
+                (#x8FD5A3 #x7F7E)
+                (#x8FD5A4 #x7F7F)
+                (#x8FD5A5 #x7F80)
+                (#x8FD5A6 #x7F8B)
+                (#x8FD5A7 #x7F8D)
+                (#x8FD5A8 #x7F8F)
+                (#x8FD5A9 #x7F90)
+                (#x8FD5AA #x7F91)
+                (#x8FD5AB #x7F96)
+                (#x8FD5AC #x7F97)
+                (#x8FD5AD #x7F9C)
+                (#x8FD5AE #x7FA1)
+                (#x8FD5AF #x7FA2)
+                (#x8FD5B0 #x7FA6)
+                (#x8FD5B1 #x7FAA)
+                (#x8FD5B2 #x7FAD)
+                (#x8FD5B3 #x7FB4)
+                (#x8FD5B4 #x7FBC)
+                (#x8FD5B5 #x7FBF)
+                (#x8FD5B6 #x7FC0)
+                (#x8FD5B7 #x7FC3)
+                (#x8FD5B8 #x7FC8)
+                (#x8FD5B9 #x7FCE)
+                (#x8FD5BA #x7FCF)
+                (#x8FD5BB #x7FDB)
+                (#x8FD5BC #x7FDF)
+                (#x8FD5BD #x7FE3)
+                (#x8FD5BE #x7FE5)
+                (#x8FD5BF #x7FE8)
+                (#x8FD5C0 #x7FEC)
+                (#x8FD5C1 #x7FEE)
+                (#x8FD5C2 #x7FEF)
+                (#x8FD5C3 #x7FF2)
+                (#x8FD5C4 #x7FFA)
+                (#x8FD5C5 #x7FFD)
+                (#x8FD5C6 #x7FFE)
+                (#x8FD5C7 #x7FFF)
+                (#x8FD5C8 #x8007)
+                (#x8FD5C9 #x8008)
+                (#x8FD5CA #x800A)
+                (#x8FD5CB #x800D)
+                (#x8FD5CC #x800E)
+                (#x8FD5CD #x800F)
+                (#x8FD5CE #x8011)
+                (#x8FD5CF #x8013)
+                (#x8FD5D0 #x8014)
+                (#x8FD5D1 #x8016)
+                (#x8FD5D2 #x801D)
+                (#x8FD5D3 #x801E)
+                (#x8FD5D4 #x801F)
+                (#x8FD5D5 #x8020)
+                (#x8FD5D6 #x8024)
+                (#x8FD5D7 #x8026)
+                (#x8FD5D8 #x802C)
+                (#x8FD5D9 #x802E)
+                (#x8FD5DA #x8030)
+                (#x8FD5DB #x8034)
+                (#x8FD5DC #x8035)
+                (#x8FD5DD #x8037)
+                (#x8FD5DE #x8039)
+                (#x8FD5DF #x803A)
+                (#x8FD5E0 #x803C)
+                (#x8FD5E1 #x803E)
+                (#x8FD5E2 #x8040)
+                (#x8FD5E3 #x8044)
+                (#x8FD5E4 #x8060)
+                (#x8FD5E5 #x8064)
+                (#x8FD5E6 #x8066)
+                (#x8FD5E7 #x806D)
+                (#x8FD5E8 #x8071)
+                (#x8FD5E9 #x8075)
+                (#x8FD5EA #x8081)
+                (#x8FD5EB #x8088)
+                (#x8FD5EC #x808E)
+                (#x8FD5ED #x809C)
+                (#x8FD5EE #x809E)
+                (#x8FD5EF #x80A6)
+                (#x8FD5F0 #x80A7)
+                (#x8FD5F1 #x80AB)
+                (#x8FD5F2 #x80B8)
+                (#x8FD5F3 #x80B9)
+                (#x8FD5F4 #x80C8)
+                (#x8FD5F5 #x80CD)
+                (#x8FD5F6 #x80CF)
+                (#x8FD5F7 #x80D2)
+                (#x8FD5F8 #x80D4)
+                (#x8FD5F9 #x80D5)
+                (#x8FD5FA #x80D7)
+                (#x8FD5FB #x80D8)
+                (#x8FD5FC #x80E0)
+                (#x8FD5FD #x80ED)
+                (#x8FD5FE #x80EE)
+                (#x8FD6A1 #x80F0)
+                (#x8FD6A2 #x80F2)
+                (#x8FD6A3 #x80F3)
+                (#x8FD6A4 #x80F6)
+                (#x8FD6A5 #x80F9)
+                (#x8FD6A6 #x80FA)
+                (#x8FD6A7 #x80FE)
+                (#x8FD6A8 #x8103)
+                (#x8FD6A9 #x810B)
+                (#x8FD6AA #x8116)
+                (#x8FD6AB #x8117)
+                (#x8FD6AC #x8118)
+                (#x8FD6AD #x811C)
+                (#x8FD6AE #x811E)
+                (#x8FD6AF #x8120)
+                (#x8FD6B0 #x8124)
+                (#x8FD6B1 #x8127)
+                (#x8FD6B2 #x812C)
+                (#x8FD6B3 #x8130)
+                (#x8FD6B4 #x8135)
+                (#x8FD6B5 #x813A)
+                (#x8FD6B6 #x813C)
+                (#x8FD6B7 #x8145)
+                (#x8FD6B8 #x8147)
+                (#x8FD6B9 #x814A)
+                (#x8FD6BA #x814C)
+                (#x8FD6BB #x8152)
+                (#x8FD6BC #x8157)
+                (#x8FD6BD #x8160)
+                (#x8FD6BE #x8161)
+                (#x8FD6BF #x8167)
+                (#x8FD6C0 #x8168)
+                (#x8FD6C1 #x8169)
+                (#x8FD6C2 #x816D)
+                (#x8FD6C3 #x816F)
+                (#x8FD6C4 #x8177)
+                (#x8FD6C5 #x8181)
+                (#x8FD6C6 #x8190)
+                (#x8FD6C7 #x8184)
+                (#x8FD6C8 #x8185)
+                (#x8FD6C9 #x8186)
+                (#x8FD6CA #x818B)
+                (#x8FD6CB #x818E)
+                (#x8FD6CC #x8196)
+                (#x8FD6CD #x8198)
+                (#x8FD6CE #x819B)
+                (#x8FD6CF #x819E)
+                (#x8FD6D0 #x81A2)
+                (#x8FD6D1 #x81AE)
+                (#x8FD6D2 #x81B2)
+                (#x8FD6D3 #x81B4)
+                (#x8FD6D4 #x81BB)
+                (#x8FD6D5 #x81CB)
+                (#x8FD6D6 #x81C3)
+                (#x8FD6D7 #x81C5)
+                (#x8FD6D8 #x81CA)
+                (#x8FD6D9 #x81CE)
+                (#x8FD6DA #x81CF)
+                (#x8FD6DB #x81D5)
+                (#x8FD6DC #x81D7)
+                (#x8FD6DD #x81DB)
+                (#x8FD6DE #x81DD)
+                (#x8FD6DF #x81DE)
+                (#x8FD6E0 #x81E1)
+                (#x8FD6E1 #x81E4)
+                (#x8FD6E2 #x81EB)
+                (#x8FD6E3 #x81EC)
+                (#x8FD6E4 #x81F0)
+                (#x8FD6E5 #x81F1)
+                (#x8FD6E6 #x81F2)
+                (#x8FD6E7 #x81F5)
+                (#x8FD6E8 #x81F6)
+                (#x8FD6E9 #x81F8)
+                (#x8FD6EA #x81F9)
+                (#x8FD6EB #x81FD)
+                (#x8FD6EC #x81FF)
+                (#x8FD6ED #x8200)
+                (#x8FD6EE #x8203)
+                (#x8FD6EF #x820F)
+                (#x8FD6F0 #x8213)
+                (#x8FD6F1 #x8214)
+                (#x8FD6F2 #x8219)
+                (#x8FD6F3 #x821A)
+                (#x8FD6F4 #x821D)
+                (#x8FD6F5 #x8221)
+                (#x8FD6F6 #x8222)
+                (#x8FD6F7 #x8228)
+                (#x8FD6F8 #x8232)
+                (#x8FD6F9 #x8234)
+                (#x8FD6FA #x823A)
+                (#x8FD6FB #x8243)
+                (#x8FD6FC #x8244)
+                (#x8FD6FD #x8245)
+                (#x8FD6FE #x8246)
+                (#x8FD7A1 #x824B)
+                (#x8FD7A2 #x824E)
+                (#x8FD7A3 #x824F)
+                (#x8FD7A4 #x8251)
+                (#x8FD7A5 #x8256)
+                (#x8FD7A6 #x825C)
+                (#x8FD7A7 #x8260)
+                (#x8FD7A8 #x8263)
+                (#x8FD7A9 #x8267)
+                (#x8FD7AA #x826D)
+                (#x8FD7AB #x8274)
+                (#x8FD7AC #x827B)
+                (#x8FD7AD #x827D)
+                (#x8FD7AE #x827F)
+                (#x8FD7AF #x8280)
+                (#x8FD7B0 #x8281)
+                (#x8FD7B1 #x8283)
+                (#x8FD7B2 #x8284)
+                (#x8FD7B3 #x8287)
+                (#x8FD7B4 #x8289)
+                (#x8FD7B5 #x828A)
+                (#x8FD7B6 #x828E)
+                (#x8FD7B7 #x8291)
+                (#x8FD7B8 #x8294)
+                (#x8FD7B9 #x8296)
+                (#x8FD7BA #x8298)
+                (#x8FD7BB #x829A)
+                (#x8FD7BC #x829B)
+                (#x8FD7BD #x82A0)
+                (#x8FD7BE #x82A1)
+                (#x8FD7BF #x82A3)
+                (#x8FD7C0 #x82A4)
+                (#x8FD7C1 #x82A7)
+                (#x8FD7C2 #x82A8)
+                (#x8FD7C3 #x82A9)
+                (#x8FD7C4 #x82AA)
+                (#x8FD7C5 #x82AE)
+                (#x8FD7C6 #x82B0)
+                (#x8FD7C7 #x82B2)
+                (#x8FD7C8 #x82B4)
+                (#x8FD7C9 #x82B7)
+                (#x8FD7CA #x82BA)
+                (#x8FD7CB #x82BC)
+                (#x8FD7CC #x82BE)
+                (#x8FD7CD #x82BF)
+                (#x8FD7CE #x82C6)
+                (#x8FD7CF #x82D0)
+                (#x8FD7D0 #x82D5)
+                (#x8FD7D1 #x82DA)
+                (#x8FD7D2 #x82E0)
+                (#x8FD7D3 #x82E2)
+                (#x8FD7D4 #x82E4)
+                (#x8FD7D5 #x82E8)
+                (#x8FD7D6 #x82EA)
+                (#x8FD7D7 #x82ED)
+                (#x8FD7D8 #x82EF)
+                (#x8FD7D9 #x82F6)
+                (#x8FD7DA #x82F7)
+                (#x8FD7DB #x82FD)
+                (#x8FD7DC #x82FE)
+                (#x8FD7DD #x8300)
+                (#x8FD7DE #x8301)
+                (#x8FD7DF #x8307)
+                (#x8FD7E0 #x8308)
+                (#x8FD7E1 #x830A)
+                (#x8FD7E2 #x830B)
+                (#x8FD7E3 #x8354)
+                (#x8FD7E4 #x831B)
+                (#x8FD7E5 #x831D)
+                (#x8FD7E6 #x831E)
+                (#x8FD7E7 #x831F)
+                (#x8FD7E8 #x8321)
+                (#x8FD7E9 #x8322)
+                (#x8FD7EA #x832C)
+                (#x8FD7EB #x832D)
+                (#x8FD7EC #x832E)
+                (#x8FD7ED #x8330)
+                (#x8FD7EE #x8333)
+                (#x8FD7EF #x8337)
+                (#x8FD7F0 #x833A)
+                (#x8FD7F1 #x833C)
+                (#x8FD7F2 #x833D)
+                (#x8FD7F3 #x8342)
+                (#x8FD7F4 #x8343)
+                (#x8FD7F5 #x8344)
+                (#x8FD7F6 #x8347)
+                (#x8FD7F7 #x834D)
+                (#x8FD7F8 #x834E)
+                (#x8FD7F9 #x8351)
+                (#x8FD7FA #x8355)
+                (#x8FD7FB #x8356)
+                (#x8FD7FC #x8357)
+                (#x8FD7FD #x8370)
+                (#x8FD7FE #x8378)
+                (#x8FD8A1 #x837D)
+                (#x8FD8A2 #x837F)
+                (#x8FD8A3 #x8380)
+                (#x8FD8A4 #x8382)
+                (#x8FD8A5 #x8384)
+                (#x8FD8A6 #x8386)
+                (#x8FD8A7 #x838D)
+                (#x8FD8A8 #x8392)
+                (#x8FD8A9 #x8394)
+                (#x8FD8AA #x8395)
+                (#x8FD8AB #x8398)
+                (#x8FD8AC #x8399)
+                (#x8FD8AD #x839B)
+                (#x8FD8AE #x839C)
+                (#x8FD8AF #x839D)
+                (#x8FD8B0 #x83A6)
+                (#x8FD8B1 #x83A7)
+                (#x8FD8B2 #x83A9)
+                (#x8FD8B3 #x83AC)
+                (#x8FD8B4 #x83BE)
+                (#x8FD8B5 #x83BF)
+                (#x8FD8B6 #x83C0)
+                (#x8FD8B7 #x83C7)
+                (#x8FD8B8 #x83C9)
+                (#x8FD8B9 #x83CF)
+                (#x8FD8BA #x83D0)
+                (#x8FD8BB #x83D1)
+                (#x8FD8BC #x83D4)
+                (#x8FD8BD #x83DD)
+                (#x8FD8BE #x8353)
+                (#x8FD8BF #x83E8)
+                (#x8FD8C0 #x83EA)
+                (#x8FD8C1 #x83F6)
+                (#x8FD8C2 #x83F8)
+                (#x8FD8C3 #x83F9)
+                (#x8FD8C4 #x83FC)
+                (#x8FD8C5 #x8401)
+                (#x8FD8C6 #x8406)
+                (#x8FD8C7 #x840A)
+                (#x8FD8C8 #x840F)
+                (#x8FD8C9 #x8411)
+                (#x8FD8CA #x8415)
+                (#x8FD8CB #x8419)
+                (#x8FD8CC #x83AD)
+                (#x8FD8CD #x842F)
+                (#x8FD8CE #x8439)
+                (#x8FD8CF #x8445)
+                (#x8FD8D0 #x8447)
+                (#x8FD8D1 #x8448)
+                (#x8FD8D2 #x844A)
+                (#x8FD8D3 #x844D)
+                (#x8FD8D4 #x844F)
+                (#x8FD8D5 #x8451)
+                (#x8FD8D6 #x8452)
+                (#x8FD8D7 #x8456)
+                (#x8FD8D8 #x8458)
+                (#x8FD8D9 #x8459)
+                (#x8FD8DA #x845A)
+                (#x8FD8DB #x845C)
+                (#x8FD8DC #x8460)
+                (#x8FD8DD #x8464)
+                (#x8FD8DE #x8465)
+                (#x8FD8DF #x8467)
+                (#x8FD8E0 #x846A)
+                (#x8FD8E1 #x8470)
+                (#x8FD8E2 #x8473)
+                (#x8FD8E3 #x8474)
+                (#x8FD8E4 #x8476)
+                (#x8FD8E5 #x8478)
+                (#x8FD8E6 #x847C)
+                (#x8FD8E7 #x847D)
+                (#x8FD8E8 #x8481)
+                (#x8FD8E9 #x8485)
+                (#x8FD8EA #x8492)
+                (#x8FD8EB #x8493)
+                (#x8FD8EC #x8495)
+                (#x8FD8ED #x849E)
+                (#x8FD8EE #x84A6)
+                (#x8FD8EF #x84A8)
+                (#x8FD8F0 #x84A9)
+                (#x8FD8F1 #x84AA)
+                (#x8FD8F2 #x84AF)
+                (#x8FD8F3 #x84B1)
+                (#x8FD8F4 #x84B4)
+                (#x8FD8F5 #x84BA)
+                (#x8FD8F6 #x84BD)
+                (#x8FD8F7 #x84BE)
+                (#x8FD8F8 #x84C0)
+                (#x8FD8F9 #x84C2)
+                (#x8FD8FA #x84C7)
+                (#x8FD8FB #x84C8)
+                (#x8FD8FC #x84CC)
+                (#x8FD8FD #x84CF)
+                (#x8FD8FE #x84D3)
+                (#x8FD9A1 #x84DC)
+                (#x8FD9A2 #x84E7)
+                (#x8FD9A3 #x84EA)
+                (#x8FD9A4 #x84EF)
+                (#x8FD9A5 #x84F0)
+                (#x8FD9A6 #x84F1)
+                (#x8FD9A7 #x84F2)
+                (#x8FD9A8 #x84F7)
+                (#x8FD9A9 #x8532)
+                (#x8FD9AA #x84FA)
+                (#x8FD9AB #x84FB)
+                (#x8FD9AC #x84FD)
+                (#x8FD9AD #x8502)
+                (#x8FD9AE #x8503)
+                (#x8FD9AF #x8507)
+                (#x8FD9B0 #x850C)
+                (#x8FD9B1 #x850E)
+                (#x8FD9B2 #x8510)
+                (#x8FD9B3 #x851C)
+                (#x8FD9B4 #x851E)
+                (#x8FD9B5 #x8522)
+                (#x8FD9B6 #x8523)
+                (#x8FD9B7 #x8524)
+                (#x8FD9B8 #x8525)
+                (#x8FD9B9 #x8527)
+                (#x8FD9BA #x852A)
+                (#x8FD9BB #x852B)
+                (#x8FD9BC #x852F)
+                (#x8FD9BD #x8533)
+                (#x8FD9BE #x8534)
+                (#x8FD9BF #x8536)
+                (#x8FD9C0 #x853F)
+                (#x8FD9C1 #x8546)
+                (#x8FD9C2 #x854F)
+                (#x8FD9C3 #x8550)
+                (#x8FD9C4 #x8551)
+                (#x8FD9C5 #x8552)
+                (#x8FD9C6 #x8553)
+                (#x8FD9C7 #x8556)
+                (#x8FD9C8 #x8559)
+                (#x8FD9C9 #x855C)
+                (#x8FD9CA #x855D)
+                (#x8FD9CB #x855E)
+                (#x8FD9CC #x855F)
+                (#x8FD9CD #x8560)
+                (#x8FD9CE #x8561)
+                (#x8FD9CF #x8562)
+                (#x8FD9D0 #x8564)
+                (#x8FD9D1 #x856B)
+                (#x8FD9D2 #x856F)
+                (#x8FD9D3 #x8579)
+                (#x8FD9D4 #x857A)
+                (#x8FD9D5 #x857B)
+                (#x8FD9D6 #x857D)
+                (#x8FD9D7 #x857F)
+                (#x8FD9D8 #x8581)
+                (#x8FD9D9 #x8585)
+                (#x8FD9DA #x8586)
+                (#x8FD9DB #x8589)
+                (#x8FD9DC #x858B)
+                (#x8FD9DD #x858C)
+                (#x8FD9DE #x858F)
+                (#x8FD9DF #x8593)
+                (#x8FD9E0 #x8598)
+                (#x8FD9E1 #x859D)
+                (#x8FD9E2 #x859F)
+                (#x8FD9E3 #x85A0)
+                (#x8FD9E4 #x85A2)
+                (#x8FD9E5 #x85A5)
+                (#x8FD9E6 #x85A7)
+                (#x8FD9E7 #x85B4)
+                (#x8FD9E8 #x85B6)
+                (#x8FD9E9 #x85B7)
+                (#x8FD9EA #x85B8)
+                (#x8FD9EB #x85BC)
+                (#x8FD9EC #x85BD)
+                (#x8FD9ED #x85BE)
+                (#x8FD9EE #x85BF)
+                (#x8FD9EF #x85C2)
+                (#x8FD9F0 #x85C7)
+                (#x8FD9F1 #x85CA)
+                (#x8FD9F2 #x85CB)
+                (#x8FD9F3 #x85CE)
+                (#x8FD9F4 #x85AD)
+                (#x8FD9F5 #x85D8)
+                (#x8FD9F6 #x85DA)
+                (#x8FD9F7 #x85DF)
+                (#x8FD9F8 #x85E0)
+                (#x8FD9F9 #x85E6)
+                (#x8FD9FA #x85E8)
+                (#x8FD9FB #x85ED)
+                (#x8FD9FC #x85F3)
+                (#x8FD9FD #x85F6)
+                (#x8FD9FE #x85FC)
+                (#x8FDAA1 #x85FF)
+                (#x8FDAA2 #x8600)
+                (#x8FDAA3 #x8604)
+                (#x8FDAA4 #x8605)
+                (#x8FDAA5 #x860D)
+                (#x8FDAA6 #x860E)
+                (#x8FDAA7 #x8610)
+                (#x8FDAA8 #x8611)
+                (#x8FDAA9 #x8612)
+                (#x8FDAAA #x8618)
+                (#x8FDAAB #x8619)
+                (#x8FDAAC #x861B)
+                (#x8FDAAD #x861E)
+                (#x8FDAAE #x8621)
+                (#x8FDAAF #x8627)
+                (#x8FDAB0 #x8629)
+                (#x8FDAB1 #x8636)
+                (#x8FDAB2 #x8638)
+                (#x8FDAB3 #x863A)
+                (#x8FDAB4 #x863C)
+                (#x8FDAB5 #x863D)
+                (#x8FDAB6 #x8640)
+                (#x8FDAB7 #x8642)
+                (#x8FDAB8 #x8646)
+                (#x8FDAB9 #x8652)
+                (#x8FDABA #x8653)
+                (#x8FDABB #x8656)
+                (#x8FDABC #x8657)
+                (#x8FDABD #x8658)
+                (#x8FDABE #x8659)
+                (#x8FDABF #x865D)
+                (#x8FDAC0 #x8660)
+                (#x8FDAC1 #x8661)
+                (#x8FDAC2 #x8662)
+                (#x8FDAC3 #x8663)
+                (#x8FDAC4 #x8664)
+                (#x8FDAC5 #x8669)
+                (#x8FDAC6 #x866C)
+                (#x8FDAC7 #x866F)
+                (#x8FDAC8 #x8675)
+                (#x8FDAC9 #x8676)
+                (#x8FDACA #x8677)
+                (#x8FDACB #x867A)
+                (#x8FDACC #x868D)
+                (#x8FDACD #x8691)
+                (#x8FDACE #x8696)
+                (#x8FDACF #x8698)
+                (#x8FDAD0 #x869A)
+                (#x8FDAD1 #x869C)
+                (#x8FDAD2 #x86A1)
+                (#x8FDAD3 #x86A6)
+                (#x8FDAD4 #x86A7)
+                (#x8FDAD5 #x86A8)
+                (#x8FDAD6 #x86AD)
+                (#x8FDAD7 #x86B1)
+                (#x8FDAD8 #x86B3)
+                (#x8FDAD9 #x86B4)
+                (#x8FDADA #x86B5)
+                (#x8FDADB #x86B7)
+                (#x8FDADC #x86B8)
+                (#x8FDADD #x86B9)
+                (#x8FDADE #x86BF)
+                (#x8FDADF #x86C0)
+                (#x8FDAE0 #x86C1)
+                (#x8FDAE1 #x86C3)
+                (#x8FDAE2 #x86C5)
+                (#x8FDAE3 #x86D1)
+                (#x8FDAE4 #x86D2)
+                (#x8FDAE5 #x86D5)
+                (#x8FDAE6 #x86D7)
+                (#x8FDAE7 #x86DA)
+                (#x8FDAE8 #x86DC)
+                (#x8FDAE9 #x86E0)
+                (#x8FDAEA #x86E3)
+                (#x8FDAEB #x86E5)
+                (#x8FDAEC #x86E7)
+                (#x8FDAED #x8688)
+                (#x8FDAEE #x86FA)
+                (#x8FDAEF #x86FC)
+                (#x8FDAF0 #x86FD)
+                (#x8FDAF1 #x8704)
+                (#x8FDAF2 #x8705)
+                (#x8FDAF3 #x8707)
+                (#x8FDAF4 #x870B)
+                (#x8FDAF5 #x870E)
+                (#x8FDAF6 #x870F)
+                (#x8FDAF7 #x8710)
+                (#x8FDAF8 #x8713)
+                (#x8FDAF9 #x8714)
+                (#x8FDAFA #x8719)
+                (#x8FDAFB #x871E)
+                (#x8FDAFC #x871F)
+                (#x8FDAFD #x8721)
+                (#x8FDAFE #x8723)
+                (#x8FDBA1 #x8728)
+                (#x8FDBA2 #x872E)
+                (#x8FDBA3 #x872F)
+                (#x8FDBA4 #x8731)
+                (#x8FDBA5 #x8732)
+                (#x8FDBA6 #x8739)
+                (#x8FDBA7 #x873A)
+                (#x8FDBA8 #x873C)
+                (#x8FDBA9 #x873D)
+                (#x8FDBAA #x873E)
+                (#x8FDBAB #x8740)
+                (#x8FDBAC #x8743)
+                (#x8FDBAD #x8745)
+                (#x8FDBAE #x874D)
+                (#x8FDBAF #x8758)
+                (#x8FDBB0 #x875D)
+                (#x8FDBB1 #x8761)
+                (#x8FDBB2 #x8764)
+                (#x8FDBB3 #x8765)
+                (#x8FDBB4 #x876F)
+                (#x8FDBB5 #x8771)
+                (#x8FDBB6 #x8772)
+                (#x8FDBB7 #x877B)
+                (#x8FDBB8 #x8783)
+                (#x8FDBB9 #x8784)
+                (#x8FDBBA #x8785)
+                (#x8FDBBB #x8786)
+                (#x8FDBBC #x8787)
+                (#x8FDBBD #x8788)
+                (#x8FDBBE #x8789)
+                (#x8FDBBF #x878B)
+                (#x8FDBC0 #x878C)
+                (#x8FDBC1 #x8790)
+                (#x8FDBC2 #x8793)
+                (#x8FDBC3 #x8795)
+                (#x8FDBC4 #x8797)
+                (#x8FDBC5 #x8798)
+                (#x8FDBC6 #x8799)
+                (#x8FDBC7 #x879E)
+                (#x8FDBC8 #x87A0)
+                (#x8FDBC9 #x87A3)
+                (#x8FDBCA #x87A7)
+                (#x8FDBCB #x87AC)
+                (#x8FDBCC #x87AD)
+                (#x8FDBCD #x87AE)
+                (#x8FDBCE #x87B1)
+                (#x8FDBCF #x87B5)
+                (#x8FDBD0 #x87BE)
+                (#x8FDBD1 #x87BF)
+                (#x8FDBD2 #x87C1)
+                (#x8FDBD3 #x87C8)
+                (#x8FDBD4 #x87C9)
+                (#x8FDBD5 #x87CA)
+                (#x8FDBD6 #x87CE)
+                (#x8FDBD7 #x87D5)
+                (#x8FDBD8 #x87D6)
+                (#x8FDBD9 #x87D9)
+                (#x8FDBDA #x87DA)
+                (#x8FDBDB #x87DC)
+                (#x8FDBDC #x87DF)
+                (#x8FDBDD #x87E2)
+                (#x8FDBDE #x87E3)
+                (#x8FDBDF #x87E4)
+                (#x8FDBE0 #x87EA)
+                (#x8FDBE1 #x87EB)
+                (#x8FDBE2 #x87ED)
+                (#x8FDBE3 #x87F1)
+                (#x8FDBE4 #x87F3)
+                (#x8FDBE5 #x87F8)
+                (#x8FDBE6 #x87FA)
+                (#x8FDBE7 #x87FF)
+                (#x8FDBE8 #x8801)
+                (#x8FDBE9 #x8803)
+                (#x8FDBEA #x8806)
+                (#x8FDBEB #x8809)
+                (#x8FDBEC #x880A)
+                (#x8FDBED #x880B)
+                (#x8FDBEE #x8810)
+                (#x8FDBEF #x8819)
+                (#x8FDBF0 #x8812)
+                (#x8FDBF1 #x8813)
+                (#x8FDBF2 #x8814)
+                (#x8FDBF3 #x8818)
+                (#x8FDBF4 #x881A)
+                (#x8FDBF5 #x881B)
+                (#x8FDBF6 #x881C)
+                (#x8FDBF7 #x881E)
+                (#x8FDBF8 #x881F)
+                (#x8FDBF9 #x8828)
+                (#x8FDBFA #x882D)
+                (#x8FDBFB #x882E)
+                (#x8FDBFC #x8830)
+                (#x8FDBFD #x8832)
+                (#x8FDBFE #x8835)
+                (#x8FDCA1 #x883A)
+                (#x8FDCA2 #x883C)
+                (#x8FDCA3 #x8841)
+                (#x8FDCA4 #x8843)
+                (#x8FDCA5 #x8845)
+                (#x8FDCA6 #x8848)
+                (#x8FDCA7 #x8849)
+                (#x8FDCA8 #x884A)
+                (#x8FDCA9 #x884B)
+                (#x8FDCAA #x884E)
+                (#x8FDCAB #x8851)
+                (#x8FDCAC #x8855)
+                (#x8FDCAD #x8856)
+                (#x8FDCAE #x8858)
+                (#x8FDCAF #x885A)
+                (#x8FDCB0 #x885C)
+                (#x8FDCB1 #x885F)
+                (#x8FDCB2 #x8860)
+                (#x8FDCB3 #x8864)
+                (#x8FDCB4 #x8869)
+                (#x8FDCB5 #x8871)
+                (#x8FDCB6 #x8879)
+                (#x8FDCB7 #x887B)
+                (#x8FDCB8 #x8880)
+                (#x8FDCB9 #x8898)
+                (#x8FDCBA #x889A)
+                (#x8FDCBB #x889B)
+                (#x8FDCBC #x889C)
+                (#x8FDCBD #x889F)
+                (#x8FDCBE #x88A0)
+                (#x8FDCBF #x88A8)
+                (#x8FDCC0 #x88AA)
+                (#x8FDCC1 #x88BA)
+                (#x8FDCC2 #x88BD)
+                (#x8FDCC3 #x88BE)
+                (#x8FDCC4 #x88C0)
+                (#x8FDCC5 #x88CA)
+                (#x8FDCC6 #x88CB)
+                (#x8FDCC7 #x88CC)
+                (#x8FDCC8 #x88CD)
+                (#x8FDCC9 #x88CE)
+                (#x8FDCCA #x88D1)
+                (#x8FDCCB #x88D2)
+                (#x8FDCCC #x88D3)
+                (#x8FDCCD #x88DB)
+                (#x8FDCCE #x88DE)
+                (#x8FDCCF #x88E7)
+                (#x8FDCD0 #x88EF)
+                (#x8FDCD1 #x88F0)
+                (#x8FDCD2 #x88F1)
+                (#x8FDCD3 #x88F5)
+                (#x8FDCD4 #x88F7)
+                (#x8FDCD5 #x8901)
+                (#x8FDCD6 #x8906)
+                (#x8FDCD7 #x890D)
+                (#x8FDCD8 #x890E)
+                (#x8FDCD9 #x890F)
+                (#x8FDCDA #x8915)
+                (#x8FDCDB #x8916)
+                (#x8FDCDC #x8918)
+                (#x8FDCDD #x8919)
+                (#x8FDCDE #x891A)
+                (#x8FDCDF #x891C)
+                (#x8FDCE0 #x8920)
+                (#x8FDCE1 #x8926)
+                (#x8FDCE2 #x8927)
+                (#x8FDCE3 #x8928)
+                (#x8FDCE4 #x8930)
+                (#x8FDCE5 #x8931)
+                (#x8FDCE6 #x8932)
+                (#x8FDCE7 #x8935)
+                (#x8FDCE8 #x8939)
+                (#x8FDCE9 #x893A)
+                (#x8FDCEA #x893E)
+                (#x8FDCEB #x8940)
+                (#x8FDCEC #x8942)
+                (#x8FDCED #x8945)
+                (#x8FDCEE #x8946)
+                (#x8FDCEF #x8949)
+                (#x8FDCF0 #x894F)
+                (#x8FDCF1 #x8952)
+                (#x8FDCF2 #x8957)
+                (#x8FDCF3 #x895A)
+                (#x8FDCF4 #x895B)
+                (#x8FDCF5 #x895C)
+                (#x8FDCF6 #x8961)
+                (#x8FDCF7 #x8962)
+                (#x8FDCF8 #x8963)
+                (#x8FDCF9 #x896B)
+                (#x8FDCFA #x896E)
+                (#x8FDCFB #x8970)
+                (#x8FDCFC #x8973)
+                (#x8FDCFD #x8975)
+                (#x8FDCFE #x897A)
+                (#x8FDDA1 #x897B)
+                (#x8FDDA2 #x897C)
+                (#x8FDDA3 #x897D)
+                (#x8FDDA4 #x8989)
+                (#x8FDDA5 #x898D)
+                (#x8FDDA6 #x8990)
+                (#x8FDDA7 #x8994)
+                (#x8FDDA8 #x8995)
+                (#x8FDDA9 #x899B)
+                (#x8FDDAA #x899C)
+                (#x8FDDAB #x899F)
+                (#x8FDDAC #x89A0)
+                (#x8FDDAD #x89A5)
+                (#x8FDDAE #x89B0)
+                (#x8FDDAF #x89B4)
+                (#x8FDDB0 #x89B5)
+                (#x8FDDB1 #x89B6)
+                (#x8FDDB2 #x89B7)
+                (#x8FDDB3 #x89BC)
+                (#x8FDDB4 #x89D4)
+                (#x8FDDB5 #x89D5)
+                (#x8FDDB6 #x89D6)
+                (#x8FDDB7 #x89D7)
+                (#x8FDDB8 #x89D8)
+                (#x8FDDB9 #x89E5)
+                (#x8FDDBA #x89E9)
+                (#x8FDDBB #x89EB)
+                (#x8FDDBC #x89ED)
+                (#x8FDDBD #x89F1)
+                (#x8FDDBE #x89F3)
+                (#x8FDDBF #x89F6)
+                (#x8FDDC0 #x89F9)
+                (#x8FDDC1 #x89FD)
+                (#x8FDDC2 #x89FF)
+                (#x8FDDC3 #x8A04)
+                (#x8FDDC4 #x8A05)
+                (#x8FDDC5 #x8A07)
+                (#x8FDDC6 #x8A0F)
+                (#x8FDDC7 #x8A11)
+                (#x8FDDC8 #x8A12)
+                (#x8FDDC9 #x8A14)
+                (#x8FDDCA #x8A15)
+                (#x8FDDCB #x8A1E)
+                (#x8FDDCC #x8A20)
+                (#x8FDDCD #x8A22)
+                (#x8FDDCE #x8A24)
+                (#x8FDDCF #x8A26)
+                (#x8FDDD0 #x8A2B)
+                (#x8FDDD1 #x8A2C)
+                (#x8FDDD2 #x8A2F)
+                (#x8FDDD3 #x8A35)
+                (#x8FDDD4 #x8A37)
+                (#x8FDDD5 #x8A3D)
+                (#x8FDDD6 #x8A3E)
+                (#x8FDDD7 #x8A40)
+                (#x8FDDD8 #x8A43)
+                (#x8FDDD9 #x8A45)
+                (#x8FDDDA #x8A47)
+                (#x8FDDDB #x8A49)
+                (#x8FDDDC #x8A4D)
+                (#x8FDDDD #x8A4E)
+                (#x8FDDDE #x8A53)
+                (#x8FDDDF #x8A56)
+                (#x8FDDE0 #x8A57)
+                (#x8FDDE1 #x8A58)
+                (#x8FDDE2 #x8A5C)
+                (#x8FDDE3 #x8A5D)
+                (#x8FDDE4 #x8A61)
+                (#x8FDDE5 #x8A65)
+                (#x8FDDE6 #x8A67)
+                (#x8FDDE7 #x8A75)
+                (#x8FDDE8 #x8A76)
+                (#x8FDDE9 #x8A77)
+                (#x8FDDEA #x8A79)
+                (#x8FDDEB #x8A7A)
+                (#x8FDDEC #x8A7B)
+                (#x8FDDED #x8A7E)
+                (#x8FDDEE #x8A7F)
+                (#x8FDDEF #x8A80)
+                (#x8FDDF0 #x8A83)
+                (#x8FDDF1 #x8A86)
+                (#x8FDDF2 #x8A8B)
+                (#x8FDDF3 #x8A8F)
+                (#x8FDDF4 #x8A90)
+                (#x8FDDF5 #x8A92)
+                (#x8FDDF6 #x8A96)
+                (#x8FDDF7 #x8A97)
+                (#x8FDDF8 #x8A99)
+                (#x8FDDF9 #x8A9F)
+                (#x8FDDFA #x8AA7)
+                (#x8FDDFB #x8AA9)
+                (#x8FDDFC #x8AAE)
+                (#x8FDDFD #x8AAF)
+                (#x8FDDFE #x8AB3)
+                (#x8FDEA1 #x8AB6)
+                (#x8FDEA2 #x8AB7)
+                (#x8FDEA3 #x8ABB)
+                (#x8FDEA4 #x8ABE)
+                (#x8FDEA5 #x8AC3)
+                (#x8FDEA6 #x8AC6)
+                (#x8FDEA7 #x8AC8)
+                (#x8FDEA8 #x8AC9)
+                (#x8FDEA9 #x8ACA)
+                (#x8FDEAA #x8AD1)
+                (#x8FDEAB #x8AD3)
+                (#x8FDEAC #x8AD4)
+                (#x8FDEAD #x8AD5)
+                (#x8FDEAE #x8AD7)
+                (#x8FDEAF #x8ADD)
+                (#x8FDEB0 #x8ADF)
+                (#x8FDEB1 #x8AEC)
+                (#x8FDEB2 #x8AF0)
+                (#x8FDEB3 #x8AF4)
+                (#x8FDEB4 #x8AF5)
+                (#x8FDEB5 #x8AF6)
+                (#x8FDEB6 #x8AFC)
+                (#x8FDEB7 #x8AFF)
+                (#x8FDEB8 #x8B05)
+                (#x8FDEB9 #x8B06)
+                (#x8FDEBA #x8B0B)
+                (#x8FDEBB #x8B11)
+                (#x8FDEBC #x8B1C)
+                (#x8FDEBD #x8B1E)
+                (#x8FDEBE #x8B1F)
+                (#x8FDEBF #x8B0A)
+                (#x8FDEC0 #x8B2D)
+                (#x8FDEC1 #x8B30)
+                (#x8FDEC2 #x8B37)
+                (#x8FDEC3 #x8B3C)
+                (#x8FDEC4 #x8B42)
+                (#x8FDEC5 #x8B43)
+                (#x8FDEC6 #x8B44)
+                (#x8FDEC7 #x8B45)
+                (#x8FDEC8 #x8B46)
+                (#x8FDEC9 #x8B48)
+                (#x8FDECA #x8B52)
+                (#x8FDECB #x8B53)
+                (#x8FDECC #x8B54)
+                (#x8FDECD #x8B59)
+                (#x8FDECE #x8B4D)
+                (#x8FDECF #x8B5E)
+                (#x8FDED0 #x8B63)
+                (#x8FDED1 #x8B6D)
+                (#x8FDED2 #x8B76)
+                (#x8FDED3 #x8B78)
+                (#x8FDED4 #x8B79)
+                (#x8FDED5 #x8B7C)
+                (#x8FDED6 #x8B7E)
+                (#x8FDED7 #x8B81)
+                (#x8FDED8 #x8B84)
+                (#x8FDED9 #x8B85)
+                (#x8FDEDA #x8B8B)
+                (#x8FDEDB #x8B8D)
+                (#x8FDEDC #x8B8F)
+                (#x8FDEDD #x8B94)
+                (#x8FDEDE #x8B95)
+                (#x8FDEDF #x8B9C)
+                (#x8FDEE0 #x8B9E)
+                (#x8FDEE1 #x8B9F)
+                (#x8FDEE2 #x8C38)
+                (#x8FDEE3 #x8C39)
+                (#x8FDEE4 #x8C3D)
+                (#x8FDEE5 #x8C3E)
+                (#x8FDEE6 #x8C45)
+                (#x8FDEE7 #x8C47)
+                (#x8FDEE8 #x8C49)
+                (#x8FDEE9 #x8C4B)
+                (#x8FDEEA #x8C4F)
+                (#x8FDEEB #x8C51)
+                (#x8FDEEC #x8C53)
+                (#x8FDEED #x8C54)
+                (#x8FDEEE #x8C57)
+                (#x8FDEEF #x8C58)
+                (#x8FDEF0 #x8C5B)
+                (#x8FDEF1 #x8C5D)
+                (#x8FDEF2 #x8C59)
+                (#x8FDEF3 #x8C63)
+                (#x8FDEF4 #x8C64)
+                (#x8FDEF5 #x8C66)
+                (#x8FDEF6 #x8C68)
+                (#x8FDEF7 #x8C69)
+                (#x8FDEF8 #x8C6D)
+                (#x8FDEF9 #x8C73)
+                (#x8FDEFA #x8C75)
+                (#x8FDEFB #x8C76)
+                (#x8FDEFC #x8C7B)
+                (#x8FDEFD #x8C7E)
+                (#x8FDEFE #x8C86)
+                (#x8FDFA1 #x8C87)
+                (#x8FDFA2 #x8C8B)
+                (#x8FDFA3 #x8C90)
+                (#x8FDFA4 #x8C92)
+                (#x8FDFA5 #x8C93)
+                (#x8FDFA6 #x8C99)
+                (#x8FDFA7 #x8C9B)
+                (#x8FDFA8 #x8C9C)
+                (#x8FDFA9 #x8CA4)
+                (#x8FDFAA #x8CB9)
+                (#x8FDFAB #x8CBA)
+                (#x8FDFAC #x8CC5)
+                (#x8FDFAD #x8CC6)
+                (#x8FDFAE #x8CC9)
+                (#x8FDFAF #x8CCB)
+                (#x8FDFB0 #x8CCF)
+                (#x8FDFB1 #x8CD6)
+                (#x8FDFB2 #x8CD5)
+                (#x8FDFB3 #x8CD9)
+                (#x8FDFB4 #x8CDD)
+                (#x8FDFB5 #x8CE1)
+                (#x8FDFB6 #x8CE8)
+                (#x8FDFB7 #x8CEC)
+                (#x8FDFB8 #x8CEF)
+                (#x8FDFB9 #x8CF0)
+                (#x8FDFBA #x8CF2)
+                (#x8FDFBB #x8CF5)
+                (#x8FDFBC #x8CF7)
+                (#x8FDFBD #x8CF8)
+                (#x8FDFBE #x8CFE)
+                (#x8FDFBF #x8CFF)
+                (#x8FDFC0 #x8D01)
+                (#x8FDFC1 #x8D03)
+                (#x8FDFC2 #x8D09)
+                (#x8FDFC3 #x8D12)
+                (#x8FDFC4 #x8D17)
+                (#x8FDFC5 #x8D1B)
+                (#x8FDFC6 #x8D65)
+                (#x8FDFC7 #x8D69)
+                (#x8FDFC8 #x8D6C)
+                (#x8FDFC9 #x8D6E)
+                (#x8FDFCA #x8D7F)
+                (#x8FDFCB #x8D82)
+                (#x8FDFCC #x8D84)
+                (#x8FDFCD #x8D88)
+                (#x8FDFCE #x8D8D)
+                (#x8FDFCF #x8D90)
+                (#x8FDFD0 #x8D91)
+                (#x8FDFD1 #x8D95)
+                (#x8FDFD2 #x8D9E)
+                (#x8FDFD3 #x8D9F)
+                (#x8FDFD4 #x8DA0)
+                (#x8FDFD5 #x8DA6)
+                (#x8FDFD6 #x8DAB)
+                (#x8FDFD7 #x8DAC)
+                (#x8FDFD8 #x8DAF)
+                (#x8FDFD9 #x8DB2)
+                (#x8FDFDA #x8DB5)
+                (#x8FDFDB #x8DB7)
+                (#x8FDFDC #x8DB9)
+                (#x8FDFDD #x8DBB)
+                (#x8FDFDE #x8DC0)
+                (#x8FDFDF #x8DC5)
+                (#x8FDFE0 #x8DC6)
+                (#x8FDFE1 #x8DC7)
+                (#x8FDFE2 #x8DC8)
+                (#x8FDFE3 #x8DCA)
+                (#x8FDFE4 #x8DCE)
+                (#x8FDFE5 #x8DD1)
+                (#x8FDFE6 #x8DD4)
+                (#x8FDFE7 #x8DD5)
+                (#x8FDFE8 #x8DD7)
+                (#x8FDFE9 #x8DD9)
+                (#x8FDFEA #x8DE4)
+                (#x8FDFEB #x8DE5)
+                (#x8FDFEC #x8DE7)
+                (#x8FDFED #x8DEC)
+                (#x8FDFEE #x8DF0)
+                (#x8FDFEF #x8DBC)
+                (#x8FDFF0 #x8DF1)
+                (#x8FDFF1 #x8DF2)
+                (#x8FDFF2 #x8DF4)
+                (#x8FDFF3 #x8DFD)
+                (#x8FDFF4 #x8E01)
+                (#x8FDFF5 #x8E04)
+                (#x8FDFF6 #x8E05)
+                (#x8FDFF7 #x8E06)
+                (#x8FDFF8 #x8E0B)
+                (#x8FDFF9 #x8E11)
+                (#x8FDFFA #x8E14)
+                (#x8FDFFB #x8E16)
+                (#x8FDFFC #x8E20)
+                (#x8FDFFD #x8E21)
+                (#x8FDFFE #x8E22)
+                (#x8FE0A1 #x8E23)
+                (#x8FE0A2 #x8E26)
+                (#x8FE0A3 #x8E27)
+                (#x8FE0A4 #x8E31)
+                (#x8FE0A5 #x8E33)
+                (#x8FE0A6 #x8E36)
+                (#x8FE0A7 #x8E37)
+                (#x8FE0A8 #x8E38)
+                (#x8FE0A9 #x8E39)
+                (#x8FE0AA #x8E3D)
+                (#x8FE0AB #x8E40)
+                (#x8FE0AC #x8E41)
+                (#x8FE0AD #x8E4B)
+                (#x8FE0AE #x8E4D)
+                (#x8FE0AF #x8E4E)
+                (#x8FE0B0 #x8E4F)
+                (#x8FE0B1 #x8E54)
+                (#x8FE0B2 #x8E5B)
+                (#x8FE0B3 #x8E5C)
+                (#x8FE0B4 #x8E5D)
+                (#x8FE0B5 #x8E5E)
+                (#x8FE0B6 #x8E61)
+                (#x8FE0B7 #x8E62)
+                (#x8FE0B8 #x8E69)
+                (#x8FE0B9 #x8E6C)
+                (#x8FE0BA #x8E6D)
+                (#x8FE0BB #x8E6F)
+                (#x8FE0BC #x8E70)
+                (#x8FE0BD #x8E71)
+                (#x8FE0BE #x8E79)
+                (#x8FE0BF #x8E7A)
+                (#x8FE0C0 #x8E7B)
+                (#x8FE0C1 #x8E82)
+                (#x8FE0C2 #x8E83)
+                (#x8FE0C3 #x8E89)
+                (#x8FE0C4 #x8E90)
+                (#x8FE0C5 #x8E92)
+                (#x8FE0C6 #x8E95)
+                (#x8FE0C7 #x8E9A)
+                (#x8FE0C8 #x8E9B)
+                (#x8FE0C9 #x8E9D)
+                (#x8FE0CA #x8E9E)
+                (#x8FE0CB #x8EA2)
+                (#x8FE0CC #x8EA7)
+                (#x8FE0CD #x8EA9)
+                (#x8FE0CE #x8EAD)
+                (#x8FE0CF #x8EAE)
+                (#x8FE0D0 #x8EB3)
+                (#x8FE0D1 #x8EB5)
+                (#x8FE0D2 #x8EBA)
+                (#x8FE0D3 #x8EBB)
+                (#x8FE0D4 #x8EC0)
+                (#x8FE0D5 #x8EC1)
+                (#x8FE0D6 #x8EC3)
+                (#x8FE0D7 #x8EC4)
+                (#x8FE0D8 #x8EC7)
+                (#x8FE0D9 #x8ECF)
+                (#x8FE0DA #x8ED1)
+                (#x8FE0DB #x8ED4)
+                (#x8FE0DC #x8EDC)
+                (#x8FE0DD #x8EE8)
+                (#x8FE0DE #x8EEE)
+                (#x8FE0DF #x8EF0)
+                (#x8FE0E0 #x8EF1)
+                (#x8FE0E1 #x8EF7)
+                (#x8FE0E2 #x8EF9)
+                (#x8FE0E3 #x8EFA)
+                (#x8FE0E4 #x8EED)
+                (#x8FE0E5 #x8F00)
+                (#x8FE0E6 #x8F02)
+                (#x8FE0E7 #x8F07)
+                (#x8FE0E8 #x8F08)
+                (#x8FE0E9 #x8F0F)
+                (#x8FE0EA #x8F10)
+                (#x8FE0EB #x8F16)
+                (#x8FE0EC #x8F17)
+                (#x8FE0ED #x8F18)
+                (#x8FE0EE #x8F1E)
+                (#x8FE0EF #x8F20)
+                (#x8FE0F0 #x8F21)
+                (#x8FE0F1 #x8F23)
+                (#x8FE0F2 #x8F25)
+                (#x8FE0F3 #x8F27)
+                (#x8FE0F4 #x8F28)
+                (#x8FE0F5 #x8F2C)
+                (#x8FE0F6 #x8F2D)
+                (#x8FE0F7 #x8F2E)
+                (#x8FE0F8 #x8F34)
+                (#x8FE0F9 #x8F35)
+                (#x8FE0FA #x8F36)
+                (#x8FE0FB #x8F37)
+                (#x8FE0FC #x8F3A)
+                (#x8FE0FD #x8F40)
+                (#x8FE0FE #x8F41)
+                (#x8FE1A1 #x8F43)
+                (#x8FE1A2 #x8F47)
+                (#x8FE1A3 #x8F4F)
+                (#x8FE1A4 #x8F51)
+                (#x8FE1A5 #x8F52)
+                (#x8FE1A6 #x8F53)
+                (#x8FE1A7 #x8F54)
+                (#x8FE1A8 #x8F55)
+                (#x8FE1A9 #x8F58)
+                (#x8FE1AA #x8F5D)
+                (#x8FE1AB #x8F5E)
+                (#x8FE1AC #x8F65)
+                (#x8FE1AD #x8F9D)
+                (#x8FE1AE #x8FA0)
+                (#x8FE1AF #x8FA1)
+                (#x8FE1B0 #x8FA4)
+                (#x8FE1B1 #x8FA5)
+                (#x8FE1B2 #x8FA6)
+                (#x8FE1B3 #x8FB5)
+                (#x8FE1B4 #x8FB6)
+                (#x8FE1B5 #x8FB8)
+                (#x8FE1B6 #x8FBE)
+                (#x8FE1B7 #x8FC0)
+                (#x8FE1B8 #x8FC1)
+                (#x8FE1B9 #x8FC6)
+                (#x8FE1BA #x8FCA)
+                (#x8FE1BB #x8FCB)
+                (#x8FE1BC #x8FCD)
+                (#x8FE1BD #x8FD0)
+                (#x8FE1BE #x8FD2)
+                (#x8FE1BF #x8FD3)
+                (#x8FE1C0 #x8FD5)
+                (#x8FE1C1 #x8FE0)
+                (#x8FE1C2 #x8FE3)
+                (#x8FE1C3 #x8FE4)
+                (#x8FE1C4 #x8FE8)
+                (#x8FE1C5 #x8FEE)
+                (#x8FE1C6 #x8FF1)
+                (#x8FE1C7 #x8FF5)
+                (#x8FE1C8 #x8FF6)
+                (#x8FE1C9 #x8FFB)
+                (#x8FE1CA #x8FFE)
+                (#x8FE1CB #x9002)
+                (#x8FE1CC #x9004)
+                (#x8FE1CD #x9008)
+                (#x8FE1CE #x900C)
+                (#x8FE1CF #x9018)
+                (#x8FE1D0 #x901B)
+                (#x8FE1D1 #x9028)
+                (#x8FE1D2 #x9029)
+                (#x8FE1D3 #x902F)
+                (#x8FE1D4 #x902A)
+                (#x8FE1D5 #x902C)
+                (#x8FE1D6 #x902D)
+                (#x8FE1D7 #x9033)
+                (#x8FE1D8 #x9034)
+                (#x8FE1D9 #x9037)
+                (#x8FE1DA #x903F)
+                (#x8FE1DB #x9043)
+                (#x8FE1DC #x9044)
+                (#x8FE1DD #x904C)
+                (#x8FE1DE #x905B)
+                (#x8FE1DF #x905D)
+                (#x8FE1E0 #x9062)
+                (#x8FE1E1 #x9066)
+                (#x8FE1E2 #x9067)
+                (#x8FE1E3 #x906C)
+                (#x8FE1E4 #x9070)
+                (#x8FE1E5 #x9074)
+                (#x8FE1E6 #x9079)
+                (#x8FE1E7 #x9085)
+                (#x8FE1E8 #x9088)
+                (#x8FE1E9 #x908B)
+                (#x8FE1EA #x908C)
+                (#x8FE1EB #x908E)
+                (#x8FE1EC #x9090)
+                (#x8FE1ED #x9095)
+                (#x8FE1EE #x9097)
+                (#x8FE1EF #x9098)
+                (#x8FE1F0 #x9099)
+                (#x8FE1F1 #x909B)
+                (#x8FE1F2 #x90A0)
+                (#x8FE1F3 #x90A1)
+                (#x8FE1F4 #x90A2)
+                (#x8FE1F5 #x90A5)
+                (#x8FE1F6 #x90B0)
+                (#x8FE1F7 #x90B2)
+                (#x8FE1F8 #x90B3)
+                (#x8FE1F9 #x90B4)
+                (#x8FE1FA #x90B6)
+                (#x8FE1FB #x90BD)
+                (#x8FE1FC #x90CC)
+                (#x8FE1FD #x90BE)
+                (#x8FE1FE #x90C3)
+                (#x8FE2A1 #x90C4)
+                (#x8FE2A2 #x90C5)
+                (#x8FE2A3 #x90C7)
+                (#x8FE2A4 #x90C8)
+                (#x8FE2A5 #x90D5)
+                (#x8FE2A6 #x90D7)
+                (#x8FE2A7 #x90D8)
+                (#x8FE2A8 #x90D9)
+                (#x8FE2A9 #x90DC)
+                (#x8FE2AA #x90DD)
+                (#x8FE2AB #x90DF)
+                (#x8FE2AC #x90E5)
+                (#x8FE2AD #x90D2)
+                (#x8FE2AE #x90F6)
+                (#x8FE2AF #x90EB)
+                (#x8FE2B0 #x90EF)
+                (#x8FE2B1 #x90F0)
+                (#x8FE2B2 #x90F4)
+                (#x8FE2B3 #x90FE)
+                (#x8FE2B4 #x90FF)
+                (#x8FE2B5 #x9100)
+                (#x8FE2B6 #x9104)
+                (#x8FE2B7 #x9105)
+                (#x8FE2B8 #x9106)
+                (#x8FE2B9 #x9108)
+                (#x8FE2BA #x910D)
+                (#x8FE2BB #x9110)
+                (#x8FE2BC #x9114)
+                (#x8FE2BD #x9116)
+                (#x8FE2BE #x9117)
+                (#x8FE2BF #x9118)
+                (#x8FE2C0 #x911A)
+                (#x8FE2C1 #x911C)
+                (#x8FE2C2 #x911E)
+                (#x8FE2C3 #x9120)
+                (#x8FE2C4 #x9125)
+                (#x8FE2C5 #x9122)
+                (#x8FE2C6 #x9123)
+                (#x8FE2C7 #x9127)
+                (#x8FE2C8 #x9129)
+                (#x8FE2C9 #x912E)
+                (#x8FE2CA #x912F)
+                (#x8FE2CB #x9131)
+                (#x8FE2CC #x9134)
+                (#x8FE2CD #x9136)
+                (#x8FE2CE #x9137)
+                (#x8FE2CF #x9139)
+                (#x8FE2D0 #x913A)
+                (#x8FE2D1 #x913C)
+                (#x8FE2D2 #x913D)
+                (#x8FE2D3 #x9143)
+                (#x8FE2D4 #x9147)
+                (#x8FE2D5 #x9148)
+                (#x8FE2D6 #x914F)
+                (#x8FE2D7 #x9153)
+                (#x8FE2D8 #x9157)
+                (#x8FE2D9 #x9159)
+                (#x8FE2DA #x915A)
+                (#x8FE2DB #x915B)
+                (#x8FE2DC #x9161)
+                (#x8FE2DD #x9164)
+                (#x8FE2DE #x9167)
+                (#x8FE2DF #x916D)
+                (#x8FE2E0 #x9174)
+                (#x8FE2E1 #x9179)
+                (#x8FE2E2 #x917A)
+                (#x8FE2E3 #x917B)
+                (#x8FE2E4 #x9181)
+                (#x8FE2E5 #x9183)
+                (#x8FE2E6 #x9185)
+                (#x8FE2E7 #x9186)
+                (#x8FE2E8 #x918A)
+                (#x8FE2E9 #x918E)
+                (#x8FE2EA #x9191)
+                (#x8FE2EB #x9193)
+                (#x8FE2EC #x9194)
+                (#x8FE2ED #x9195)
+                (#x8FE2EE #x9198)
+                (#x8FE2EF #x919E)
+                (#x8FE2F0 #x91A1)
+                (#x8FE2F1 #x91A6)
+                (#x8FE2F2 #x91A8)
+                (#x8FE2F3 #x91AC)
+                (#x8FE2F4 #x91AD)
+                (#x8FE2F5 #x91AE)
+                (#x8FE2F6 #x91B0)
+                (#x8FE2F7 #x91B1)
+                (#x8FE2F8 #x91B2)
+                (#x8FE2F9 #x91B3)
+                (#x8FE2FA #x91B6)
+                (#x8FE2FB #x91BB)
+                (#x8FE2FC #x91BC)
+                (#x8FE2FD #x91BD)
+                (#x8FE2FE #x91BF)
+                (#x8FE3A1 #x91C2)
+                (#x8FE3A2 #x91C3)
+                (#x8FE3A3 #x91C5)
+                (#x8FE3A4 #x91D3)
+                (#x8FE3A5 #x91D4)
+                (#x8FE3A6 #x91D7)
+                (#x8FE3A7 #x91D9)
+                (#x8FE3A8 #x91DA)
+                (#x8FE3A9 #x91DE)
+                (#x8FE3AA #x91E4)
+                (#x8FE3AB #x91E5)
+                (#x8FE3AC #x91E9)
+                (#x8FE3AD #x91EA)
+                (#x8FE3AE #x91EC)
+                (#x8FE3AF #x91ED)
+                (#x8FE3B0 #x91EE)
+                (#x8FE3B1 #x91EF)
+                (#x8FE3B2 #x91F0)
+                (#x8FE3B3 #x91F1)
+                (#x8FE3B4 #x91F7)
+                (#x8FE3B5 #x91F9)
+                (#x8FE3B6 #x91FB)
+                (#x8FE3B7 #x91FD)
+                (#x8FE3B8 #x9200)
+                (#x8FE3B9 #x9201)
+                (#x8FE3BA #x9204)
+                (#x8FE3BB #x9205)
+                (#x8FE3BC #x9206)
+                (#x8FE3BD #x9207)
+                (#x8FE3BE #x9209)
+                (#x8FE3BF #x920A)
+                (#x8FE3C0 #x920C)
+                (#x8FE3C1 #x9210)
+                (#x8FE3C2 #x9212)
+                (#x8FE3C3 #x9213)
+                (#x8FE3C4 #x9216)
+                (#x8FE3C5 #x9218)
+                (#x8FE3C6 #x921C)
+                (#x8FE3C7 #x921D)
+                (#x8FE3C8 #x9223)
+                (#x8FE3C9 #x9224)
+                (#x8FE3CA #x9225)
+                (#x8FE3CB #x9226)
+                (#x8FE3CC #x9228)
+                (#x8FE3CD #x922E)
+                (#x8FE3CE #x922F)
+                (#x8FE3CF #x9230)
+                (#x8FE3D0 #x9233)
+                (#x8FE3D1 #x9235)
+                (#x8FE3D2 #x9236)
+                (#x8FE3D3 #x9238)
+                (#x8FE3D4 #x9239)
+                (#x8FE3D5 #x923A)
+                (#x8FE3D6 #x923C)
+                (#x8FE3D7 #x923E)
+                (#x8FE3D8 #x9240)
+                (#x8FE3D9 #x9242)
+                (#x8FE3DA #x9243)
+                (#x8FE3DB #x9246)
+                (#x8FE3DC #x9247)
+                (#x8FE3DD #x924A)
+                (#x8FE3DE #x924D)
+                (#x8FE3DF #x924E)
+                (#x8FE3E0 #x924F)
+                (#x8FE3E1 #x9251)
+                (#x8FE3E2 #x9258)
+                (#x8FE3E3 #x9259)
+                (#x8FE3E4 #x925C)
+                (#x8FE3E5 #x925D)
+                (#x8FE3E6 #x9260)
+                (#x8FE3E7 #x9261)
+                (#x8FE3E8 #x9265)
+                (#x8FE3E9 #x9267)
+                (#x8FE3EA #x9268)
+                (#x8FE3EB #x9269)
+                (#x8FE3EC #x926E)
+                (#x8FE3ED #x926F)
+                (#x8FE3EE #x9270)
+                (#x8FE3EF #x9275)
+                (#x8FE3F0 #x9276)
+                (#x8FE3F1 #x9277)
+                (#x8FE3F2 #x9278)
+                (#x8FE3F3 #x9279)
+                (#x8FE3F4 #x927B)
+                (#x8FE3F5 #x927C)
+                (#x8FE3F6 #x927D)
+                (#x8FE3F7 #x927F)
+                (#x8FE3F8 #x9288)
+                (#x8FE3F9 #x9289)
+                (#x8FE3FA #x928A)
+                (#x8FE3FB #x928D)
+                (#x8FE3FC #x928E)
+                (#x8FE3FD #x9292)
+                (#x8FE3FE #x9297)
+                (#x8FE4A1 #x9299)
+                (#x8FE4A2 #x929F)
+                (#x8FE4A3 #x92A0)
+                (#x8FE4A4 #x92A4)
+                (#x8FE4A5 #x92A5)
+                (#x8FE4A6 #x92A7)
+                (#x8FE4A7 #x92A8)
+                (#x8FE4A8 #x92AB)
+                (#x8FE4A9 #x92AF)
+                (#x8FE4AA #x92B2)
+                (#x8FE4AB #x92B6)
+                (#x8FE4AC #x92B8)
+                (#x8FE4AD #x92BA)
+                (#x8FE4AE #x92BB)
+                (#x8FE4AF #x92BC)
+                (#x8FE4B0 #x92BD)
+                (#x8FE4B1 #x92BF)
+                (#x8FE4B2 #x92C0)
+                (#x8FE4B3 #x92C1)
+                (#x8FE4B4 #x92C2)
+                (#x8FE4B5 #x92C3)
+                (#x8FE4B6 #x92C5)
+                (#x8FE4B7 #x92C6)
+                (#x8FE4B8 #x92C7)
+                (#x8FE4B9 #x92C8)
+                (#x8FE4BA #x92CB)
+                (#x8FE4BB #x92CC)
+                (#x8FE4BC #x92CD)
+                (#x8FE4BD #x92CE)
+                (#x8FE4BE #x92D0)
+                (#x8FE4BF #x92D3)
+                (#x8FE4C0 #x92D5)
+                (#x8FE4C1 #x92D7)
+                (#x8FE4C2 #x92D8)
+                (#x8FE4C3 #x92D9)
+                (#x8FE4C4 #x92DC)
+                (#x8FE4C5 #x92DD)
+                (#x8FE4C6 #x92DF)
+                (#x8FE4C7 #x92E0)
+                (#x8FE4C8 #x92E1)
+                (#x8FE4C9 #x92E3)
+                (#x8FE4CA #x92E5)
+                (#x8FE4CB #x92E7)
+                (#x8FE4CC #x92E8)
+                (#x8FE4CD #x92EC)
+                (#x8FE4CE #x92EE)
+                (#x8FE4CF #x92F0)
+                (#x8FE4D0 #x92F9)
+                (#x8FE4D1 #x92FB)
+                (#x8FE4D2 #x92FF)
+                (#x8FE4D3 #x9300)
+                (#x8FE4D4 #x9302)
+                (#x8FE4D5 #x9308)
+                (#x8FE4D6 #x930D)
+                (#x8FE4D7 #x9311)
+                (#x8FE4D8 #x9314)
+                (#x8FE4D9 #x9315)
+                (#x8FE4DA #x931C)
+                (#x8FE4DB #x931D)
+                (#x8FE4DC #x931E)
+                (#x8FE4DD #x931F)
+                (#x8FE4DE #x9321)
+                (#x8FE4DF #x9324)
+                (#x8FE4E0 #x9325)
+                (#x8FE4E1 #x9327)
+                (#x8FE4E2 #x9329)
+                (#x8FE4E3 #x932A)
+                (#x8FE4E4 #x9333)
+                (#x8FE4E5 #x9334)
+                (#x8FE4E6 #x9336)
+                (#x8FE4E7 #x9337)
+                (#x8FE4E8 #x9347)
+                (#x8FE4E9 #x9348)
+                (#x8FE4EA #x9349)
+                (#x8FE4EB #x9350)
+                (#x8FE4EC #x9351)
+                (#x8FE4ED #x9352)
+                (#x8FE4EE #x9355)
+                (#x8FE4EF #x9357)
+                (#x8FE4F0 #x9358)
+                (#x8FE4F1 #x935A)
+                (#x8FE4F2 #x935E)
+                (#x8FE4F3 #x9364)
+                (#x8FE4F4 #x9365)
+                (#x8FE4F5 #x9367)
+                (#x8FE4F6 #x9369)
+                (#x8FE4F7 #x936A)
+                (#x8FE4F8 #x936D)
+                (#x8FE4F9 #x936F)
+                (#x8FE4FA #x9370)
+                (#x8FE4FB #x9371)
+                (#x8FE4FC #x9373)
+                (#x8FE4FD #x9374)
+                (#x8FE4FE #x9376)
+                (#x8FE5A1 #x937A)
+                (#x8FE5A2 #x937D)
+                (#x8FE5A3 #x937F)
+                (#x8FE5A4 #x9380)
+                (#x8FE5A5 #x9381)
+                (#x8FE5A6 #x9382)
+                (#x8FE5A7 #x9388)
+                (#x8FE5A8 #x938A)
+                (#x8FE5A9 #x938B)
+                (#x8FE5AA #x938D)
+                (#x8FE5AB #x938F)
+                (#x8FE5AC #x9392)
+                (#x8FE5AD #x9395)
+                (#x8FE5AE #x9398)
+                (#x8FE5AF #x939B)
+                (#x8FE5B0 #x939E)
+                (#x8FE5B1 #x93A1)
+                (#x8FE5B2 #x93A3)
+                (#x8FE5B3 #x93A4)
+                (#x8FE5B4 #x93A6)
+                (#x8FE5B5 #x93A8)
+                (#x8FE5B6 #x93AB)
+                (#x8FE5B7 #x93B4)
+                (#x8FE5B8 #x93B5)
+                (#x8FE5B9 #x93B6)
+                (#x8FE5BA #x93BA)
+                (#x8FE5BB #x93A9)
+                (#x8FE5BC #x93C1)
+                (#x8FE5BD #x93C4)
+                (#x8FE5BE #x93C5)
+                (#x8FE5BF #x93C6)
+                (#x8FE5C0 #x93C7)
+                (#x8FE5C1 #x93C9)
+                (#x8FE5C2 #x93CA)
+                (#x8FE5C3 #x93CB)
+                (#x8FE5C4 #x93CC)
+                (#x8FE5C5 #x93CD)
+                (#x8FE5C6 #x93D3)
+                (#x8FE5C7 #x93D9)
+                (#x8FE5C8 #x93DC)
+                (#x8FE5C9 #x93DE)
+                (#x8FE5CA #x93DF)
+                (#x8FE5CB #x93E2)
+                (#x8FE5CC #x93E6)
+                (#x8FE5CD #x93E7)
+                (#x8FE5CE #x93F9)
+                (#x8FE5CF #x93F7)
+                (#x8FE5D0 #x93F8)
+                (#x8FE5D1 #x93FA)
+                (#x8FE5D2 #x93FB)
+                (#x8FE5D3 #x93FD)
+                (#x8FE5D4 #x9401)
+                (#x8FE5D5 #x9402)
+                (#x8FE5D6 #x9404)
+                (#x8FE5D7 #x9408)
+                (#x8FE5D8 #x9409)
+                (#x8FE5D9 #x940D)
+                (#x8FE5DA #x940E)
+                (#x8FE5DB #x940F)
+                (#x8FE5DC #x9415)
+                (#x8FE5DD #x9416)
+                (#x8FE5DE #x9417)
+                (#x8FE5DF #x941F)
+                (#x8FE5E0 #x942E)
+                (#x8FE5E1 #x942F)
+                (#x8FE5E2 #x9431)
+                (#x8FE5E3 #x9432)
+                (#x8FE5E4 #x9433)
+                (#x8FE5E5 #x9434)
+                (#x8FE5E6 #x943B)
+                (#x8FE5E7 #x943F)
+                (#x8FE5E8 #x943D)
+                (#x8FE5E9 #x9443)
+                (#x8FE5EA #x9445)
+                (#x8FE5EB #x9448)
+                (#x8FE5EC #x944A)
+                (#x8FE5ED #x944C)
+                (#x8FE5EE #x9455)
+                (#x8FE5EF #x9459)
+                (#x8FE5F0 #x945C)
+                (#x8FE5F1 #x945F)
+                (#x8FE5F2 #x9461)
+                (#x8FE5F3 #x9463)
+                (#x8FE5F4 #x9468)
+                (#x8FE5F5 #x946B)
+                (#x8FE5F6 #x946D)
+                (#x8FE5F7 #x946E)
+                (#x8FE5F8 #x946F)
+                (#x8FE5F9 #x9471)
+                (#x8FE5FA #x9472)
+                (#x8FE5FB #x9484)
+                (#x8FE5FC #x9483)
+                (#x8FE5FD #x9578)
+                (#x8FE5FE #x9579)
+                (#x8FE6A1 #x957E)
+                (#x8FE6A2 #x9584)
+                (#x8FE6A3 #x9588)
+                (#x8FE6A4 #x958C)
+                (#x8FE6A5 #x958D)
+                (#x8FE6A6 #x958E)
+                (#x8FE6A7 #x959D)
+                (#x8FE6A8 #x959E)
+                (#x8FE6A9 #x959F)
+                (#x8FE6AA #x95A1)
+                (#x8FE6AB #x95A6)
+                (#x8FE6AC #x95A9)
+                (#x8FE6AD #x95AB)
+                (#x8FE6AE #x95AC)
+                (#x8FE6AF #x95B4)
+                (#x8FE6B0 #x95B6)
+                (#x8FE6B1 #x95BA)
+                (#x8FE6B2 #x95BD)
+                (#x8FE6B3 #x95BF)
+                (#x8FE6B4 #x95C6)
+                (#x8FE6B5 #x95C8)
+                (#x8FE6B6 #x95C9)
+                (#x8FE6B7 #x95CB)
+                (#x8FE6B8 #x95D0)
+                (#x8FE6B9 #x95D1)
+                (#x8FE6BA #x95D2)
+                (#x8FE6BB #x95D3)
+                (#x8FE6BC #x95D9)
+                (#x8FE6BD #x95DA)
+                (#x8FE6BE #x95DD)
+                (#x8FE6BF #x95DE)
+                (#x8FE6C0 #x95DF)
+                (#x8FE6C1 #x95E0)
+                (#x8FE6C2 #x95E4)
+                (#x8FE6C3 #x95E6)
+                (#x8FE6C4 #x961D)
+                (#x8FE6C5 #x961E)
+                (#x8FE6C6 #x9622)
+                (#x8FE6C7 #x9624)
+                (#x8FE6C8 #x9625)
+                (#x8FE6C9 #x9626)
+                (#x8FE6CA #x962C)
+                (#x8FE6CB #x9631)
+                (#x8FE6CC #x9633)
+                (#x8FE6CD #x9637)
+                (#x8FE6CE #x9638)
+                (#x8FE6CF #x9639)
+                (#x8FE6D0 #x963A)
+                (#x8FE6D1 #x963C)
+                (#x8FE6D2 #x963D)
+                (#x8FE6D3 #x9641)
+                (#x8FE6D4 #x9652)
+                (#x8FE6D5 #x9654)
+                (#x8FE6D6 #x9656)
+                (#x8FE6D7 #x9657)
+                (#x8FE6D8 #x9658)
+                (#x8FE6D9 #x9661)
+                (#x8FE6DA #x966E)
+                (#x8FE6DB #x9674)
+                (#x8FE6DC #x967B)
+                (#x8FE6DD #x967C)
+                (#x8FE6DE #x967E)
+                (#x8FE6DF #x967F)
+                (#x8FE6E0 #x9681)
+                (#x8FE6E1 #x9682)
+                (#x8FE6E2 #x9683)
+                (#x8FE6E3 #x9684)
+                (#x8FE6E4 #x9689)
+                (#x8FE6E5 #x9691)
+                (#x8FE6E6 #x9696)
+                (#x8FE6E7 #x969A)
+                (#x8FE6E8 #x969D)
+                (#x8FE6E9 #x969F)
+                (#x8FE6EA #x96A4)
+                (#x8FE6EB #x96A5)
+                (#x8FE6EC #x96A6)
+                (#x8FE6ED #x96A9)
+                (#x8FE6EE #x96AE)
+                (#x8FE6EF #x96AF)
+                (#x8FE6F0 #x96B3)
+                (#x8FE6F1 #x96BA)
+                (#x8FE6F2 #x96CA)
+                (#x8FE6F3 #x96D2)
+                (#x8FE6F4 #x5DB2)
+                (#x8FE6F5 #x96D8)
+                (#x8FE6F6 #x96DA)
+                (#x8FE6F7 #x96DD)
+                (#x8FE6F8 #x96DE)
+                (#x8FE6F9 #x96DF)
+                (#x8FE6FA #x96E9)
+                (#x8FE6FB #x96EF)
+                (#x8FE6FC #x96F1)
+                (#x8FE6FD #x96FA)
+                (#x8FE6FE #x9702)
+                (#x8FE7A1 #x9703)
+                (#x8FE7A2 #x9705)
+                (#x8FE7A3 #x9709)
+                (#x8FE7A4 #x971A)
+                (#x8FE7A5 #x971B)
+                (#x8FE7A6 #x971D)
+                (#x8FE7A7 #x9721)
+                (#x8FE7A8 #x9722)
+                (#x8FE7A9 #x9723)
+                (#x8FE7AA #x9728)
+                (#x8FE7AB #x9731)
+                (#x8FE7AC #x9733)
+                (#x8FE7AD #x9741)
+                (#x8FE7AE #x9743)
+                (#x8FE7AF #x974A)
+                (#x8FE7B0 #x974E)
+                (#x8FE7B1 #x974F)
+                (#x8FE7B2 #x9755)
+                (#x8FE7B3 #x9757)
+                (#x8FE7B4 #x9758)
+                (#x8FE7B5 #x975A)
+                (#x8FE7B6 #x975B)
+                (#x8FE7B7 #x9763)
+                (#x8FE7B8 #x9767)
+                (#x8FE7B9 #x976A)
+                (#x8FE7BA #x976E)
+                (#x8FE7BB #x9773)
+                (#x8FE7BC #x9776)
+                (#x8FE7BD #x9777)
+                (#x8FE7BE #x9778)
+                (#x8FE7BF #x977B)
+                (#x8FE7C0 #x977D)
+                (#x8FE7C1 #x977F)
+                (#x8FE7C2 #x9780)
+                (#x8FE7C3 #x9789)
+                (#x8FE7C4 #x9795)
+                (#x8FE7C5 #x9796)
+                (#x8FE7C6 #x9797)
+                (#x8FE7C7 #x9799)
+                (#x8FE7C8 #x979A)
+                (#x8FE7C9 #x979E)
+                (#x8FE7CA #x979F)
+                (#x8FE7CB #x97A2)
+                (#x8FE7CC #x97AC)
+                (#x8FE7CD #x97AE)
+                (#x8FE7CE #x97B1)
+                (#x8FE7CF #x97B2)
+                (#x8FE7D0 #x97B5)
+                (#x8FE7D1 #x97B6)
+                (#x8FE7D2 #x97B8)
+                (#x8FE7D3 #x97B9)
+                (#x8FE7D4 #x97BA)
+                (#x8FE7D5 #x97BC)
+                (#x8FE7D6 #x97BE)
+                (#x8FE7D7 #x97BF)
+                (#x8FE7D8 #x97C1)
+                (#x8FE7D9 #x97C4)
+                (#x8FE7DA #x97C5)
+                (#x8FE7DB #x97C7)
+                (#x8FE7DC #x97C9)
+                (#x8FE7DD #x97CA)
+                (#x8FE7DE #x97CC)
+                (#x8FE7DF #x97CD)
+                (#x8FE7E0 #x97CE)
+                (#x8FE7E1 #x97D0)
+                (#x8FE7E2 #x97D1)
+                (#x8FE7E3 #x97D4)
+                (#x8FE7E4 #x97D7)
+                (#x8FE7E5 #x97D8)
+                (#x8FE7E6 #x97D9)
+                (#x8FE7E7 #x97DD)
+                (#x8FE7E8 #x97DE)
+                (#x8FE7E9 #x97E0)
+                (#x8FE7EA #x97DB)
+                (#x8FE7EB #x97E1)
+                (#x8FE7EC #x97E4)
+                (#x8FE7ED #x97EF)
+                (#x8FE7EE #x97F1)
+                (#x8FE7EF #x97F4)
+                (#x8FE7F0 #x97F7)
+                (#x8FE7F1 #x97F8)
+                (#x8FE7F2 #x97FA)
+                (#x8FE7F3 #x9807)
+                (#x8FE7F4 #x980A)
+                (#x8FE7F5 #x9819)
+                (#x8FE7F6 #x980D)
+                (#x8FE7F7 #x980E)
+                (#x8FE7F8 #x9814)
+                (#x8FE7F9 #x9816)
+                (#x8FE7FA #x981C)
+                (#x8FE7FB #x981E)
+                (#x8FE7FC #x9820)
+                (#x8FE7FD #x9823)
+                (#x8FE7FE #x9826)
+                (#x8FE8A1 #x982B)
+                (#x8FE8A2 #x982E)
+                (#x8FE8A3 #x982F)
+                (#x8FE8A4 #x9830)
+                (#x8FE8A5 #x9832)
+                (#x8FE8A6 #x9833)
+                (#x8FE8A7 #x9835)
+                (#x8FE8A8 #x9825)
+                (#x8FE8A9 #x983E)
+                (#x8FE8AA #x9844)
+                (#x8FE8AB #x9847)
+                (#x8FE8AC #x984A)
+                (#x8FE8AD #x9851)
+                (#x8FE8AE #x9852)
+                (#x8FE8AF #x9853)
+                (#x8FE8B0 #x9856)
+                (#x8FE8B1 #x9857)
+                (#x8FE8B2 #x9859)
+                (#x8FE8B3 #x985A)
+                (#x8FE8B4 #x9862)
+                (#x8FE8B5 #x9863)
+                (#x8FE8B6 #x9865)
+                (#x8FE8B7 #x9866)
+                (#x8FE8B8 #x986A)
+                (#x8FE8B9 #x986C)
+                (#x8FE8BA #x98AB)
+                (#x8FE8BB #x98AD)
+                (#x8FE8BC #x98AE)
+                (#x8FE8BD #x98B0)
+                (#x8FE8BE #x98B4)
+                (#x8FE8BF #x98B7)
+                (#x8FE8C0 #x98B8)
+                (#x8FE8C1 #x98BA)
+                (#x8FE8C2 #x98BB)
+                (#x8FE8C3 #x98BF)
+                (#x8FE8C4 #x98C2)
+                (#x8FE8C5 #x98C5)
+                (#x8FE8C6 #x98C8)
+                (#x8FE8C7 #x98CC)
+                (#x8FE8C8 #x98E1)
+                (#x8FE8C9 #x98E3)
+                (#x8FE8CA #x98E5)
+                (#x8FE8CB #x98E6)
+                (#x8FE8CC #x98E7)
+                (#x8FE8CD #x98EA)
+                (#x8FE8CE #x98F3)
+                (#x8FE8CF #x98F6)
+                (#x8FE8D0 #x9902)
+                (#x8FE8D1 #x9907)
+                (#x8FE8D2 #x9908)
+                (#x8FE8D3 #x9911)
+                (#x8FE8D4 #x9915)
+                (#x8FE8D5 #x9916)
+                (#x8FE8D6 #x9917)
+                (#x8FE8D7 #x991A)
+                (#x8FE8D8 #x991B)
+                (#x8FE8D9 #x991C)
+                (#x8FE8DA #x991F)
+                (#x8FE8DB #x9922)
+                (#x8FE8DC #x9926)
+                (#x8FE8DD #x9927)
+                (#x8FE8DE #x992B)
+                (#x8FE8DF #x9931)
+                (#x8FE8E0 #x9932)
+                (#x8FE8E1 #x9933)
+                (#x8FE8E2 #x9934)
+                (#x8FE8E3 #x9935)
+                (#x8FE8E4 #x9939)
+                (#x8FE8E5 #x993A)
+                (#x8FE8E6 #x993B)
+                (#x8FE8E7 #x993C)
+                (#x8FE8E8 #x9940)
+                (#x8FE8E9 #x9941)
+                (#x8FE8EA #x9946)
+                (#x8FE8EB #x9947)
+                (#x8FE8EC #x9948)
+                (#x8FE8ED #x994D)
+                (#x8FE8EE #x994E)
+                (#x8FE8EF #x9954)
+                (#x8FE8F0 #x9958)
+                (#x8FE8F1 #x9959)
+                (#x8FE8F2 #x995B)
+                (#x8FE8F3 #x995C)
+                (#x8FE8F4 #x995E)
+                (#x8FE8F5 #x995F)
+                (#x8FE8F6 #x9960)
+                (#x8FE8F7 #x999B)
+                (#x8FE8F8 #x999D)
+                (#x8FE8F9 #x999F)
+                (#x8FE8FA #x99A6)
+                (#x8FE8FB #x99B0)
+                (#x8FE8FC #x99B1)
+                (#x8FE8FD #x99B2)
+                (#x8FE8FE #x99B5)
+                (#x8FE9A1 #x99B9)
+                (#x8FE9A2 #x99BA)
+                (#x8FE9A3 #x99BD)
+                (#x8FE9A4 #x99BF)
+                (#x8FE9A5 #x99C3)
+                (#x8FE9A6 #x99C9)
+                (#x8FE9A7 #x99D3)
+                (#x8FE9A8 #x99D4)
+                (#x8FE9A9 #x99D9)
+                (#x8FE9AA #x99DA)
+                (#x8FE9AB #x99DC)
+                (#x8FE9AC #x99DE)
+                (#x8FE9AD #x99E7)
+                (#x8FE9AE #x99EA)
+                (#x8FE9AF #x99EB)
+                (#x8FE9B0 #x99EC)
+                (#x8FE9B1 #x99F0)
+                (#x8FE9B2 #x99F4)
+                (#x8FE9B3 #x99F5)
+                (#x8FE9B4 #x99F9)
+                (#x8FE9B5 #x99FD)
+                (#x8FE9B6 #x99FE)
+                (#x8FE9B7 #x9A02)
+                (#x8FE9B8 #x9A03)
+                (#x8FE9B9 #x9A04)
+                (#x8FE9BA #x9A0B)
+                (#x8FE9BB #x9A0C)
+                (#x8FE9BC #x9A10)
+                (#x8FE9BD #x9A11)
+                (#x8FE9BE #x9A16)
+                (#x8FE9BF #x9A1E)
+                (#x8FE9C0 #x9A20)
+                (#x8FE9C1 #x9A22)
+                (#x8FE9C2 #x9A23)
+                (#x8FE9C3 #x9A24)
+                (#x8FE9C4 #x9A27)
+                (#x8FE9C5 #x9A2D)
+                (#x8FE9C6 #x9A2E)
+                (#x8FE9C7 #x9A33)
+                (#x8FE9C8 #x9A35)
+                (#x8FE9C9 #x9A36)
+                (#x8FE9CA #x9A38)
+                (#x8FE9CB #x9A47)
+                (#x8FE9CC #x9A41)
+                (#x8FE9CD #x9A44)
+                (#x8FE9CE #x9A4A)
+                (#x8FE9CF #x9A4B)
+                (#x8FE9D0 #x9A4C)
+                (#x8FE9D1 #x9A4E)
+                (#x8FE9D2 #x9A51)
+                (#x8FE9D3 #x9A54)
+                (#x8FE9D4 #x9A56)
+                (#x8FE9D5 #x9A5D)
+                (#x8FE9D6 #x9AAA)
+                (#x8FE9D7 #x9AAC)
+                (#x8FE9D8 #x9AAE)
+                (#x8FE9D9 #x9AAF)
+                (#x8FE9DA #x9AB2)
+                (#x8FE9DB #x9AB4)
+                (#x8FE9DC #x9AB5)
+                (#x8FE9DD #x9AB6)
+                (#x8FE9DE #x9AB9)
+                (#x8FE9DF #x9ABB)
+                (#x8FE9E0 #x9ABE)
+                (#x8FE9E1 #x9ABF)
+                (#x8FE9E2 #x9AC1)
+                (#x8FE9E3 #x9AC3)
+                (#x8FE9E4 #x9AC6)
+                (#x8FE9E5 #x9AC8)
+                (#x8FE9E6 #x9ACE)
+                (#x8FE9E7 #x9AD0)
+                (#x8FE9E8 #x9AD2)
+                (#x8FE9E9 #x9AD5)
+                (#x8FE9EA #x9AD6)
+                (#x8FE9EB #x9AD7)
+                (#x8FE9EC #x9ADB)
+                (#x8FE9ED #x9ADC)
+                (#x8FE9EE #x9AE0)
+                (#x8FE9EF #x9AE4)
+                (#x8FE9F0 #x9AE5)
+                (#x8FE9F1 #x9AE7)
+                (#x8FE9F2 #x9AE9)
+                (#x8FE9F3 #x9AEC)
+                (#x8FE9F4 #x9AF2)
+                (#x8FE9F5 #x9AF3)
+                (#x8FE9F6 #x9AF5)
+                (#x8FE9F7 #x9AF9)
+                (#x8FE9F8 #x9AFA)
+                (#x8FE9F9 #x9AFD)
+                (#x8FE9FA #x9AFF)
+                (#x8FE9FB #x9B00)
+                (#x8FE9FC #x9B01)
+                (#x8FE9FD #x9B02)
+                (#x8FE9FE #x9B03)
+                (#x8FEAA1 #x9B04)
+                (#x8FEAA2 #x9B05)
+                (#x8FEAA3 #x9B08)
+                (#x8FEAA4 #x9B09)
+                (#x8FEAA5 #x9B0B)
+                (#x8FEAA6 #x9B0C)
+                (#x8FEAA7 #x9B0D)
+                (#x8FEAA8 #x9B0E)
+                (#x8FEAA9 #x9B10)
+                (#x8FEAAA #x9B12)
+                (#x8FEAAB #x9B16)
+                (#x8FEAAC #x9B19)
+                (#x8FEAAD #x9B1B)
+                (#x8FEAAE #x9B1C)
+                (#x8FEAAF #x9B20)
+                (#x8FEAB0 #x9B26)
+                (#x8FEAB1 #x9B2B)
+                (#x8FEAB2 #x9B2D)
+                (#x8FEAB3 #x9B33)
+                (#x8FEAB4 #x9B34)
+                (#x8FEAB5 #x9B35)
+                (#x8FEAB6 #x9B37)
+                (#x8FEAB7 #x9B39)
+                (#x8FEAB8 #x9B3A)
+                (#x8FEAB9 #x9B3D)
+                (#x8FEABA #x9B48)
+                (#x8FEABB #x9B4B)
+                (#x8FEABC #x9B4C)
+                (#x8FEABD #x9B55)
+                (#x8FEABE #x9B56)
+                (#x8FEABF #x9B57)
+                (#x8FEAC0 #x9B5B)
+                (#x8FEAC1 #x9B5E)
+                (#x8FEAC2 #x9B61)
+                (#x8FEAC3 #x9B63)
+                (#x8FEAC4 #x9B65)
+                (#x8FEAC5 #x9B66)
+                (#x8FEAC6 #x9B68)
+                (#x8FEAC7 #x9B6A)
+                (#x8FEAC8 #x9B6B)
+                (#x8FEAC9 #x9B6C)
+                (#x8FEACA #x9B6D)
+                (#x8FEACB #x9B6E)
+                (#x8FEACC #x9B73)
+                (#x8FEACD #x9B75)
+                (#x8FEACE #x9B77)
+                (#x8FEACF #x9B78)
+                (#x8FEAD0 #x9B79)
+                (#x8FEAD1 #x9B7F)
+                (#x8FEAD2 #x9B80)
+                (#x8FEAD3 #x9B84)
+                (#x8FEAD4 #x9B85)
+                (#x8FEAD5 #x9B86)
+                (#x8FEAD6 #x9B87)
+                (#x8FEAD7 #x9B89)
+                (#x8FEAD8 #x9B8A)
+                (#x8FEAD9 #x9B8B)
+                (#x8FEADA #x9B8D)
+                (#x8FEADB #x9B8F)
+                (#x8FEADC #x9B90)
+                (#x8FEADD #x9B94)
+                (#x8FEADE #x9B9A)
+                (#x8FEADF #x9B9D)
+                (#x8FEAE0 #x9B9E)
+                (#x8FEAE1 #x9BA6)
+                (#x8FEAE2 #x9BA7)
+                (#x8FEAE3 #x9BA9)
+                (#x8FEAE4 #x9BAC)
+                (#x8FEAE5 #x9BB0)
+                (#x8FEAE6 #x9BB1)
+                (#x8FEAE7 #x9BB2)
+                (#x8FEAE8 #x9BB7)
+                (#x8FEAE9 #x9BB8)
+                (#x8FEAEA #x9BBB)
+                (#x8FEAEB #x9BBC)
+                (#x8FEAEC #x9BBE)
+                (#x8FEAED #x9BBF)
+                (#x8FEAEE #x9BC1)
+                (#x8FEAEF #x9BC7)
+                (#x8FEAF0 #x9BC8)
+                (#x8FEAF1 #x9BCE)
+                (#x8FEAF2 #x9BD0)
+                (#x8FEAF3 #x9BD7)
+                (#x8FEAF4 #x9BD8)
+                (#x8FEAF5 #x9BDD)
+                (#x8FEAF6 #x9BDF)
+                (#x8FEAF7 #x9BE5)
+                (#x8FEAF8 #x9BE7)
+                (#x8FEAF9 #x9BEA)
+                (#x8FEAFA #x9BEB)
+                (#x8FEAFB #x9BEF)
+                (#x8FEAFC #x9BF3)
+                (#x8FEAFD #x9BF7)
+                (#x8FEAFE #x9BF8)
+                (#x8FEBA1 #x9BF9)
+                (#x8FEBA2 #x9BFA)
+                (#x8FEBA3 #x9BFD)
+                (#x8FEBA4 #x9BFF)
+                (#x8FEBA5 #x9C00)
+                (#x8FEBA6 #x9C02)
+                (#x8FEBA7 #x9C0B)
+                (#x8FEBA8 #x9C0F)
+                (#x8FEBA9 #x9C11)
+                (#x8FEBAA #x9C16)
+                (#x8FEBAB #x9C18)
+                (#x8FEBAC #x9C19)
+                (#x8FEBAD #x9C1A)
+                (#x8FEBAE #x9C1C)
+                (#x8FEBAF #x9C1E)
+                (#x8FEBB0 #x9C22)
+                (#x8FEBB1 #x9C23)
+                (#x8FEBB2 #x9C26)
+                (#x8FEBB3 #x9C27)
+                (#x8FEBB4 #x9C28)
+                (#x8FEBB5 #x9C29)
+                (#x8FEBB6 #x9C2A)
+                (#x8FEBB7 #x9C31)
+                (#x8FEBB8 #x9C35)
+                (#x8FEBB9 #x9C36)
+                (#x8FEBBA #x9C37)
+                (#x8FEBBB #x9C3D)
+                (#x8FEBBC #x9C41)
+                (#x8FEBBD #x9C43)
+                (#x8FEBBE #x9C44)
+                (#x8FEBBF #x9C45)
+                (#x8FEBC0 #x9C49)
+                (#x8FEBC1 #x9C4A)
+                (#x8FEBC2 #x9C4E)
+                (#x8FEBC3 #x9C4F)
+                (#x8FEBC4 #x9C50)
+                (#x8FEBC5 #x9C53)
+                (#x8FEBC6 #x9C54)
+                (#x8FEBC7 #x9C56)
+                (#x8FEBC8 #x9C58)
+                (#x8FEBC9 #x9C5B)
+                (#x8FEBCA #x9C5D)
+                (#x8FEBCB #x9C5E)
+                (#x8FEBCC #x9C5F)
+                (#x8FEBCD #x9C63)
+                (#x8FEBCE #x9C69)
+                (#x8FEBCF #x9C6A)
+                (#x8FEBD0 #x9C5C)
+                (#x8FEBD1 #x9C6B)
+                (#x8FEBD2 #x9C68)
+                (#x8FEBD3 #x9C6E)
+                (#x8FEBD4 #x9C70)
+                (#x8FEBD5 #x9C72)
+                (#x8FEBD6 #x9C75)
+                (#x8FEBD7 #x9C77)
+                (#x8FEBD8 #x9C7B)
+                (#x8FEBD9 #x9CE6)
+                (#x8FEBDA #x9CF2)
+                (#x8FEBDB #x9CF7)
+                (#x8FEBDC #x9CF9)
+                (#x8FEBDD #x9D0B)
+                (#x8FEBDE #x9D02)
+                (#x8FEBDF #x9D11)
+                (#x8FEBE0 #x9D17)
+                (#x8FEBE1 #x9D18)
+                (#x8FEBE2 #x9D1C)
+                (#x8FEBE3 #x9D1D)
+                (#x8FEBE4 #x9D1E)
+                (#x8FEBE5 #x9D2F)
+                (#x8FEBE6 #x9D30)
+                (#x8FEBE7 #x9D32)
+                (#x8FEBE8 #x9D33)
+                (#x8FEBE9 #x9D34)
+                (#x8FEBEA #x9D3A)
+                (#x8FEBEB #x9D3C)
+                (#x8FEBEC #x9D45)
+                (#x8FEBED #x9D3D)
+                (#x8FEBEE #x9D42)
+                (#x8FEBEF #x9D43)
+                (#x8FEBF0 #x9D47)
+                (#x8FEBF1 #x9D4A)
+                (#x8FEBF2 #x9D53)
+                (#x8FEBF3 #x9D54)
+                (#x8FEBF4 #x9D5F)
+                (#x8FEBF5 #x9D63)
+                (#x8FEBF6 #x9D62)
+                (#x8FEBF7 #x9D65)
+                (#x8FEBF8 #x9D69)
+                (#x8FEBF9 #x9D6A)
+                (#x8FEBFA #x9D6B)
+                (#x8FEBFB #x9D70)
+                (#x8FEBFC #x9D76)
+                (#x8FEBFD #x9D77)
+                (#x8FEBFE #x9D7B)
+                (#x8FECA1 #x9D7C)
+                (#x8FECA2 #x9D7E)
+                (#x8FECA3 #x9D83)
+                (#x8FECA4 #x9D84)
+                (#x8FECA5 #x9D86)
+                (#x8FECA6 #x9D8A)
+                (#x8FECA7 #x9D8D)
+                (#x8FECA8 #x9D8E)
+                (#x8FECA9 #x9D92)
+                (#x8FECAA #x9D93)
+                (#x8FECAB #x9D95)
+                (#x8FECAC #x9D96)
+                (#x8FECAD #x9D97)
+                (#x8FECAE #x9D98)
+                (#x8FECAF #x9DA1)
+                (#x8FECB0 #x9DAA)
+                (#x8FECB1 #x9DAC)
+                (#x8FECB2 #x9DAE)
+                (#x8FECB3 #x9DB1)
+                (#x8FECB4 #x9DB5)
+                (#x8FECB5 #x9DB9)
+                (#x8FECB6 #x9DBC)
+                (#x8FECB7 #x9DBF)
+                (#x8FECB8 #x9DC3)
+                (#x8FECB9 #x9DC7)
+                (#x8FECBA #x9DC9)
+                (#x8FECBB #x9DCA)
+                (#x8FECBC #x9DD4)
+                (#x8FECBD #x9DD5)
+                (#x8FECBE #x9DD6)
+                (#x8FECBF #x9DD7)
+                (#x8FECC0 #x9DDA)
+                (#x8FECC1 #x9DDE)
+                (#x8FECC2 #x9DDF)
+                (#x8FECC3 #x9DE0)
+                (#x8FECC4 #x9DE5)
+                (#x8FECC5 #x9DE7)
+                (#x8FECC6 #x9DE9)
+                (#x8FECC7 #x9DEB)
+                (#x8FECC8 #x9DEE)
+                (#x8FECC9 #x9DF0)
+                (#x8FECCA #x9DF3)
+                (#x8FECCB #x9DF4)
+                (#x8FECCC #x9DFE)
+                (#x8FECCD #x9E0A)
+                (#x8FECCE #x9E02)
+                (#x8FECCF #x9E07)
+                (#x8FECD0 #x9E0E)
+                (#x8FECD1 #x9E10)
+                (#x8FECD2 #x9E11)
+                (#x8FECD3 #x9E12)
+                (#x8FECD4 #x9E15)
+                (#x8FECD5 #x9E16)
+                (#x8FECD6 #x9E19)
+                (#x8FECD7 #x9E1C)
+                (#x8FECD8 #x9E1D)
+                (#x8FECD9 #x9E7A)
+                (#x8FECDA #x9E7B)
+                (#x8FECDB #x9E7C)
+                (#x8FECDC #x9E80)
+                (#x8FECDD #x9E82)
+                (#x8FECDE #x9E83)
+                (#x8FECDF #x9E84)
+                (#x8FECE0 #x9E85)
+                (#x8FECE1 #x9E87)
+                (#x8FECE2 #x9E8E)
+                (#x8FECE3 #x9E8F)
+                (#x8FECE4 #x9E96)
+                (#x8FECE5 #x9E98)
+                (#x8FECE6 #x9E9B)
+                (#x8FECE7 #x9E9E)
+                (#x8FECE8 #x9EA4)
+                (#x8FECE9 #x9EA8)
+                (#x8FECEA #x9EAC)
+                (#x8FECEB #x9EAE)
+                (#x8FECEC #x9EAF)
+                (#x8FECED #x9EB0)
+                (#x8FECEE #x9EB3)
+                (#x8FECEF #x9EB4)
+                (#x8FECF0 #x9EB5)
+                (#x8FECF1 #x9EC6)
+                (#x8FECF2 #x9EC8)
+                (#x8FECF3 #x9ECB)
+                (#x8FECF4 #x9ED5)
+                (#x8FECF5 #x9EDF)
+                (#x8FECF6 #x9EE4)
+                (#x8FECF7 #x9EE7)
+                (#x8FECF8 #x9EEC)
+                (#x8FECF9 #x9EED)
+                (#x8FECFA #x9EEE)
+                (#x8FECFB #x9EF0)
+                (#x8FECFC #x9EF1)
+                (#x8FECFD #x9EF2)
+                (#x8FECFE #x9EF5)
+                (#x8FEDA1 #x9EF8)
+                (#x8FEDA2 #x9EFF)
+                (#x8FEDA3 #x9F02)
+                (#x8FEDA4 #x9F03)
+                (#x8FEDA5 #x9F09)
+                (#x8FEDA6 #x9F0F)
+                (#x8FEDA7 #x9F10)
+                (#x8FEDA8 #x9F11)
+                (#x8FEDA9 #x9F12)
+                (#x8FEDAA #x9F14)
+                (#x8FEDAB #x9F16)
+                (#x8FEDAC #x9F17)
+                (#x8FEDAD #x9F19)
+                (#x8FEDAE #x9F1A)
+                (#x8FEDAF #x9F1B)
+                (#x8FEDB0 #x9F1F)
+                (#x8FEDB1 #x9F22)
+                (#x8FEDB2 #x9F26)
+                (#x8FEDB3 #x9F2A)
+                (#x8FEDB4 #x9F2B)
+                (#x8FEDB5 #x9F2F)
+                (#x8FEDB6 #x9F31)
+                (#x8FEDB7 #x9F32)
+                (#x8FEDB8 #x9F34)
+                (#x8FEDB9 #x9F37)
+                (#x8FEDBA #x9F39)
+                (#x8FEDBB #x9F3A)
+                (#x8FEDBC #x9F3C)
+                (#x8FEDBD #x9F3D)
+                (#x8FEDBE #x9F3F)
+                (#x8FEDBF #x9F41)
+                (#x8FEDC0 #x9F43)
+                (#x8FEDC1 #x9F44)
+                (#x8FEDC2 #x9F45)
+                (#x8FEDC3 #x9F46)
+                (#x8FEDC4 #x9F47)
+                (#x8FEDC5 #x9F53)
+                (#x8FEDC6 #x9F55)
+                (#x8FEDC7 #x9F56)
+                (#x8FEDC8 #x9F57)
+                (#x8FEDC9 #x9F58)
+                (#x8FEDCA #x9F5A)
+                (#x8FEDCB #x9F5D)
+                (#x8FEDCC #x9F5E)
+                (#x8FEDCD #x9F68)
+                (#x8FEDCE #x9F69)
+                (#x8FEDCF #x9F6D)
+                (#x8FEDD0 #x9F6E)
+                (#x8FEDD1 #x9F6F)
+                (#x8FEDD2 #x9F70)
+                (#x8FEDD3 #x9F71)
+                (#x8FEDD4 #x9F73)
+                (#x8FEDD5 #x9F75)
+                (#x8FEDD6 #x9F7A)
+                (#x8FEDD7 #x9F7D)
+                (#x8FEDD8 #x9F8F)
+                (#x8FEDD9 #x9F90)
+                (#x8FEDDA #x9F91)
+                (#x8FEDDB #x9F92)
+                (#x8FEDDC #x9F94)
+                (#x8FEDDD #x9F96)
+                (#x8FEDDE #x9F97)
+                (#x8FEDDF #x9F9E)
+                (#x8FEDE0 #x9FA1)
+                (#x8FEDE1 #x9FA2)
+                (#x8FEDE2 #x9FA3)
+                (#x8FEDE3 #x9FA5)
+                (#x8FF5A1 #xE3AC)
+                (#x8FF5A2 #xE3AD)
+                (#x8FF5A3 #xE3AE)
+                (#x8FF5A4 #xE3AF)
+                (#x8FF5A5 #xE3B0)
+                (#x8FF5A6 #xE3B1)
+                (#x8FF5A7 #xE3B2)
+                (#x8FF5A8 #xE3B3)
+                (#x8FF5A9 #xE3B4)
+                (#x8FF5AA #xE3B5)
+                (#x8FF5AB #xE3B6)
+                (#x8FF5AC #xE3B7)
+                (#x8FF5AD #xE3B8)
+                (#x8FF5AE #xE3B9)
+                (#x8FF5AF #xE3BA)
+                (#x8FF5B0 #xE3BB)
+                (#x8FF5B1 #xE3BC)
+                (#x8FF5B2 #xE3BD)
+                (#x8FF5B3 #xE3BE)
+                (#x8FF5B4 #xE3BF)
+                (#x8FF5B5 #xE3C0)
+                (#x8FF5B6 #xE3C1)
+                (#x8FF5B7 #xE3C2)
+                (#x8FF5B8 #xE3C3)
+                (#x8FF5B9 #xE3C4)
+                (#x8FF5BA #xE3C5)
+                (#x8FF5BB #xE3C6)
+                (#x8FF5BC #xE3C7)
+                (#x8FF5BD #xE3C8)
+                (#x8FF5BE #xE3C9)
+                (#x8FF5BF #xE3CA)
+                (#x8FF5C0 #xE3CB)
+                (#x8FF5C1 #xE3CC)
+                (#x8FF5C2 #xE3CD)
+                (#x8FF5C3 #xE3CE)
+                (#x8FF5C4 #xE3CF)
+                (#x8FF5C5 #xE3D0)
+                (#x8FF5C6 #xE3D1)
+                (#x8FF5C7 #xE3D2)
+                (#x8FF5C8 #xE3D3)
+                (#x8FF5C9 #xE3D4)
+                (#x8FF5CA #xE3D5)
+                (#x8FF5CB #xE3D6)
+                (#x8FF5CC #xE3D7)
+                (#x8FF5CD #xE3D8)
+                (#x8FF5CE #xE3D9)
+                (#x8FF5CF #xE3DA)
+                (#x8FF5D0 #xE3DB)
+                (#x8FF5D1 #xE3DC)
+                (#x8FF5D2 #xE3DD)
+                (#x8FF5D3 #xE3DE)
+                (#x8FF5D4 #xE3DF)
+                (#x8FF5D5 #xE3E0)
+                (#x8FF5D6 #xE3E1)
+                (#x8FF5D7 #xE3E2)
+                (#x8FF5D8 #xE3E3)
+                (#x8FF5D9 #xE3E4)
+                (#x8FF5DA #xE3E5)
+                (#x8FF5DB #xE3E6)
+                (#x8FF5DC #xE3E7)
+                (#x8FF5DD #xE3E8)
+                (#x8FF5DE #xE3E9)
+                (#x8FF5DF #xE3EA)
+                (#x8FF5E0 #xE3EB)
+                (#x8FF5E1 #xE3EC)
+                (#x8FF5E2 #xE3ED)
+                (#x8FF5E3 #xE3EE)
+                (#x8FF5E4 #xE3EF)
+                (#x8FF5E5 #xE3F0)
+                (#x8FF5E6 #xE3F1)
+                (#x8FF5E7 #xE3F2)
+                (#x8FF5E8 #xE3F3)
+                (#x8FF5E9 #xE3F4)
+                (#x8FF5EA #xE3F5)
+                (#x8FF5EB #xE3F6)
+                (#x8FF5EC #xE3F7)
+                (#x8FF5ED #xE3F8)
+                (#x8FF5EE #xE3F9)
+                (#x8FF5EF #xE3FA)
+                (#x8FF5F0 #xE3FB)
+                (#x8FF5F1 #xE3FC)
+                (#x8FF5F2 #xE3FD)
+                (#x8FF5F3 #xE3FE)
+                (#x8FF5F4 #xE3FF)
+                (#x8FF5F5 #xE400)
+                (#x8FF5F6 #xE401)
+                (#x8FF5F7 #xE402)
+                (#x8FF5F8 #xE403)
+                (#x8FF5F9 #xE404)
+                (#x8FF5FA #xE405)
+                (#x8FF5FB #xE406)
+                (#x8FF5FC #xE407)
+                (#x8FF5FD #xE408)
+                (#x8FF5FE #xE409)
+                (#x8FF6A1 #xE40A)
+                (#x8FF6A2 #xE40B)
+                (#x8FF6A3 #xE40C)
+                (#x8FF6A4 #xE40D)
+                (#x8FF6A5 #xE40E)
+                (#x8FF6A6 #xE40F)
+                (#x8FF6A7 #xE410)
+                (#x8FF6A8 #xE411)
+                (#x8FF6A9 #xE412)
+                (#x8FF6AA #xE413)
+                (#x8FF6AB #xE414)
+                (#x8FF6AC #xE415)
+                (#x8FF6AD #xE416)
+                (#x8FF6AE #xE417)
+                (#x8FF6AF #xE418)
+                (#x8FF6B0 #xE419)
+                (#x8FF6B1 #xE41A)
+                (#x8FF6B2 #xE41B)
+                (#x8FF6B3 #xE41C)
+                (#x8FF6B4 #xE41D)
+                (#x8FF6B5 #xE41E)
+                (#x8FF6B6 #xE41F)
+                (#x8FF6B7 #xE420)
+                (#x8FF6B8 #xE421)
+                (#x8FF6B9 #xE422)
+                (#x8FF6BA #xE423)
+                (#x8FF6BB #xE424)
+                (#x8FF6BC #xE425)
+                (#x8FF6BD #xE426)
+                (#x8FF6BE #xE427)
+                (#x8FF6BF #xE428)
+                (#x8FF6C0 #xE429)
+                (#x8FF6C1 #xE42A)
+                (#x8FF6C2 #xE42B)
+                (#x8FF6C3 #xE42C)
+                (#x8FF6C4 #xE42D)
+                (#x8FF6C5 #xE42E)
+                (#x8FF6C6 #xE42F)
+                (#x8FF6C7 #xE430)
+                (#x8FF6C8 #xE431)
+                (#x8FF6C9 #xE432)
+                (#x8FF6CA #xE433)
+                (#x8FF6CB #xE434)
+                (#x8FF6CC #xE435)
+                (#x8FF6CD #xE436)
+                (#x8FF6CE #xE437)
+                (#x8FF6CF #xE438)
+                (#x8FF6D0 #xE439)
+                (#x8FF6D1 #xE43A)
+                (#x8FF6D2 #xE43B)
+                (#x8FF6D3 #xE43C)
+                (#x8FF6D4 #xE43D)
+                (#x8FF6D5 #xE43E)
+                (#x8FF6D6 #xE43F)
+                (#x8FF6D7 #xE440)
+                (#x8FF6D8 #xE441)
+                (#x8FF6D9 #xE442)
+                (#x8FF6DA #xE443)
+                (#x8FF6DB #xE444)
+                (#x8FF6DC #xE445)
+                (#x8FF6DD #xE446)
+                (#x8FF6DE #xE447)
+                (#x8FF6DF #xE448)
+                (#x8FF6E0 #xE449)
+                (#x8FF6E1 #xE44A)
+                (#x8FF6E2 #xE44B)
+                (#x8FF6E3 #xE44C)
+                (#x8FF6E4 #xE44D)
+                (#x8FF6E5 #xE44E)
+                (#x8FF6E6 #xE44F)
+                (#x8FF6E7 #xE450)
+                (#x8FF6E8 #xE451)
+                (#x8FF6E9 #xE452)
+                (#x8FF6EA #xE453)
+                (#x8FF6EB #xE454)
+                (#x8FF6EC #xE455)
+                (#x8FF6ED #xE456)
+                (#x8FF6EE #xE457)
+                (#x8FF6EF #xE458)
+                (#x8FF6F0 #xE459)
+                (#x8FF6F1 #xE45A)
+                (#x8FF6F2 #xE45B)
+                (#x8FF6F3 #xE45C)
+                (#x8FF6F4 #xE45D)
+                (#x8FF6F5 #xE45E)
+                (#x8FF6F6 #xE45F)
+                (#x8FF6F7 #xE460)
+                (#x8FF6F8 #xE461)
+                (#x8FF6F9 #xE462)
+                (#x8FF6FA #xE463)
+                (#x8FF6FB #xE464)
+                (#x8FF6FC #xE465)
+                (#x8FF6FD #xE466)
+                (#x8FF6FE #xE467)
+                (#x8FF7A1 #xE468)
+                (#x8FF7A2 #xE469)
+                (#x8FF7A3 #xE46A)
+                (#x8FF7A4 #xE46B)
+                (#x8FF7A5 #xE46C)
+                (#x8FF7A6 #xE46D)
+                (#x8FF7A7 #xE46E)
+                (#x8FF7A8 #xE46F)
+                (#x8FF7A9 #xE470)
+                (#x8FF7AA #xE471)
+                (#x8FF7AB #xE472)
+                (#x8FF7AC #xE473)
+                (#x8FF7AD #xE474)
+                (#x8FF7AE #xE475)
+                (#x8FF7AF #xE476)
+                (#x8FF7B0 #xE477)
+                (#x8FF7B1 #xE478)
+                (#x8FF7B2 #xE479)
+                (#x8FF7B3 #xE47A)
+                (#x8FF7B4 #xE47B)
+                (#x8FF7B5 #xE47C)
+                (#x8FF7B6 #xE47D)
+                (#x8FF7B7 #xE47E)
+                (#x8FF7B8 #xE47F)
+                (#x8FF7B9 #xE480)
+                (#x8FF7BA #xE481)
+                (#x8FF7BB #xE482)
+                (#x8FF7BC #xE483)
+                (#x8FF7BD #xE484)
+                (#x8FF7BE #xE485)
+                (#x8FF7BF #xE486)
+                (#x8FF7C0 #xE487)
+                (#x8FF7C1 #xE488)
+                (#x8FF7C2 #xE489)
+                (#x8FF7C3 #xE48A)
+                (#x8FF7C4 #xE48B)
+                (#x8FF7C5 #xE48C)
+                (#x8FF7C6 #xE48D)
+                (#x8FF7C7 #xE48E)
+                (#x8FF7C8 #xE48F)
+                (#x8FF7C9 #xE490)
+                (#x8FF7CA #xE491)
+                (#x8FF7CB #xE492)
+                (#x8FF7CC #xE493)
+                (#x8FF7CD #xE494)
+                (#x8FF7CE #xE495)
+                (#x8FF7CF #xE496)
+                (#x8FF7D0 #xE497)
+                (#x8FF7D1 #xE498)
+                (#x8FF7D2 #xE499)
+                (#x8FF7D3 #xE49A)
+                (#x8FF7D4 #xE49B)
+                (#x8FF7D5 #xE49C)
+                (#x8FF7D6 #xE49D)
+                (#x8FF7D7 #xE49E)
+                (#x8FF7D8 #xE49F)
+                (#x8FF7D9 #xE4A0)
+                (#x8FF7DA #xE4A1)
+                (#x8FF7DB #xE4A2)
+                (#x8FF7DC #xE4A3)
+                (#x8FF7DD #xE4A4)
+                (#x8FF7DE #xE4A5)
+                (#x8FF7DF #xE4A6)
+                (#x8FF7E0 #xE4A7)
+                (#x8FF7E1 #xE4A8)
+                (#x8FF7E2 #xE4A9)
+                (#x8FF7E3 #xE4AA)
+                (#x8FF7E4 #xE4AB)
+                (#x8FF7E5 #xE4AC)
+                (#x8FF7E6 #xE4AD)
+                (#x8FF7E7 #xE4AE)
+                (#x8FF7E8 #xE4AF)
+                (#x8FF7E9 #xE4B0)
+                (#x8FF7EA #xE4B1)
+                (#x8FF7EB #xE4B2)
+                (#x8FF7EC #xE4B3)
+                (#x8FF7ED #xE4B4)
+                (#x8FF7EE #xE4B5)
+                (#x8FF7EF #xE4B6)
+                (#x8FF7F0 #xE4B7)
+                (#x8FF7F1 #xE4B8)
+                (#x8FF7F2 #xE4B9)
+                (#x8FF7F3 #xE4BA)
+                (#x8FF7F4 #xE4BB)
+                (#x8FF7F5 #xE4BC)
+                (#x8FF7F6 #xE4BD)
+                (#x8FF7F7 #xE4BE)
+                (#x8FF7F8 #xE4BF)
+                (#x8FF7F9 #xE4C0)
+                (#x8FF7FA #xE4C1)
+                (#x8FF7FB #xE4C2)
+                (#x8FF7FC #xE4C3)
+                (#x8FF7FD #xE4C4)
+                (#x8FF7FE #xE4C5)
+                (#x8FF8A1 #xE4C6)
+                (#x8FF8A2 #xE4C7)
+                (#x8FF8A3 #xE4C8)
+                (#x8FF8A4 #xE4C9)
+                (#x8FF8A5 #xE4CA)
+                (#x8FF8A6 #xE4CB)
+                (#x8FF8A7 #xE4CC)
+                (#x8FF8A8 #xE4CD)
+                (#x8FF8A9 #xE4CE)
+                (#x8FF8AA #xE4CF)
+                (#x8FF8AB #xE4D0)
+                (#x8FF8AC #xE4D1)
+                (#x8FF8AD #xE4D2)
+                (#x8FF8AE #xE4D3)
+                (#x8FF8AF #xE4D4)
+                (#x8FF8B0 #xE4D5)
+                (#x8FF8B1 #xE4D6)
+                (#x8FF8B2 #xE4D7)
+                (#x8FF8B3 #xE4D8)
+                (#x8FF8B4 #xE4D9)
+                (#x8FF8B5 #xE4DA)
+                (#x8FF8B6 #xE4DB)
+                (#x8FF8B7 #xE4DC)
+                (#x8FF8B8 #xE4DD)
+                (#x8FF8B9 #xE4DE)
+                (#x8FF8BA #xE4DF)
+                (#x8FF8BB #xE4E0)
+                (#x8FF8BC #xE4E1)
+                (#x8FF8BD #xE4E2)
+                (#x8FF8BE #xE4E3)
+                (#x8FF8BF #xE4E4)
+                (#x8FF8C0 #xE4E5)
+                (#x8FF8C1 #xE4E6)
+                (#x8FF8C2 #xE4E7)
+                (#x8FF8C3 #xE4E8)
+                (#x8FF8C4 #xE4E9)
+                (#x8FF8C5 #xE4EA)
+                (#x8FF8C6 #xE4EB)
+                (#x8FF8C7 #xE4EC)
+                (#x8FF8C8 #xE4ED)
+                (#x8FF8C9 #xE4EE)
+                (#x8FF8CA #xE4EF)
+                (#x8FF8CB #xE4F0)
+                (#x8FF8CC #xE4F1)
+                (#x8FF8CD #xE4F2)
+                (#x8FF8CE #xE4F3)
+                (#x8FF8CF #xE4F4)
+                (#x8FF8D0 #xE4F5)
+                (#x8FF8D1 #xE4F6)
+                (#x8FF8D2 #xE4F7)
+                (#x8FF8D3 #xE4F8)
+                (#x8FF8D4 #xE4F9)
+                (#x8FF8D5 #xE4FA)
+                (#x8FF8D6 #xE4FB)
+                (#x8FF8D7 #xE4FC)
+                (#x8FF8D8 #xE4FD)
+                (#x8FF8D9 #xE4FE)
+                (#x8FF8DA #xE4FF)
+                (#x8FF8DB #xE500)
+                (#x8FF8DC #xE501)
+                (#x8FF8DD #xE502)
+                (#x8FF8DE #xE503)
+                (#x8FF8DF #xE504)
+                (#x8FF8E0 #xE505)
+                (#x8FF8E1 #xE506)
+                (#x8FF8E2 #xE507)
+                (#x8FF8E3 #xE508)
+                (#x8FF8E4 #xE509)
+                (#x8FF8E5 #xE50A)
+                (#x8FF8E6 #xE50B)
+                (#x8FF8E7 #xE50C)
+                (#x8FF8E8 #xE50D)
+                (#x8FF8E9 #xE50E)
+                (#x8FF8EA #xE50F)
+                (#x8FF8EB #xE510)
+                (#x8FF8EC #xE511)
+                (#x8FF8ED #xE512)
+                (#x8FF8EE #xE513)
+                (#x8FF8EF #xE514)
+                (#x8FF8F0 #xE515)
+                (#x8FF8F1 #xE516)
+                (#x8FF8F2 #xE517)
+                (#x8FF8F3 #xE518)
+                (#x8FF8F4 #xE519)
+                (#x8FF8F5 #xE51A)
+                (#x8FF8F6 #xE51B)
+                (#x8FF8F7 #xE51C)
+                (#x8FF8F8 #xE51D)
+                (#x8FF8F9 #xE51E)
+                (#x8FF8FA #xE51F)
+                (#x8FF8FB #xE520)
+                (#x8FF8FC #xE521)
+                (#x8FF8FD #xE522)
+                (#x8FF8FE #xE523)
+                (#x8FF9A1 #xE524)
+                (#x8FF9A2 #xE525)
+                (#x8FF9A3 #xE526)
+                (#x8FF9A4 #xE527)
+                (#x8FF9A5 #xE528)
+                (#x8FF9A6 #xE529)
+                (#x8FF9A7 #xE52A)
+                (#x8FF9A8 #xE52B)
+                (#x8FF9A9 #xE52C)
+                (#x8FF9AA #xE52D)
+                (#x8FF9AB #xE52E)
+                (#x8FF9AC #xE52F)
+                (#x8FF9AD #xE530)
+                (#x8FF9AE #xE531)
+                (#x8FF9AF #xE532)
+                (#x8FF9B0 #xE533)
+                (#x8FF9B1 #xE534)
+                (#x8FF9B2 #xE535)
+                (#x8FF9B3 #xE536)
+                (#x8FF9B4 #xE537)
+                (#x8FF9B5 #xE538)
+                (#x8FF9B6 #xE539)
+                (#x8FF9B7 #xE53A)
+                (#x8FF9B8 #xE53B)
+                (#x8FF9B9 #xE53C)
+                (#x8FF9BA #xE53D)
+                (#x8FF9BB #xE53E)
+                (#x8FF9BC #xE53F)
+                (#x8FF9BD #xE540)
+                (#x8FF9BE #xE541)
+                (#x8FF9BF #xE542)
+                (#x8FF9C0 #xE543)
+                (#x8FF9C1 #xE544)
+                (#x8FF9C2 #xE545)
+                (#x8FF9C3 #xE546)
+                (#x8FF9C4 #xE547)
+                (#x8FF9C5 #xE548)
+                (#x8FF9C6 #xE549)
+                (#x8FF9C7 #xE54A)
+                (#x8FF9C8 #xE54B)
+                (#x8FF9C9 #xE54C)
+                (#x8FF9CA #xE54D)
+                (#x8FF9CB #xE54E)
+                (#x8FF9CC #xE54F)
+                (#x8FF9CD #xE550)
+                (#x8FF9CE #xE551)
+                (#x8FF9CF #xE552)
+                (#x8FF9D0 #xE553)
+                (#x8FF9D1 #xE554)
+                (#x8FF9D2 #xE555)
+                (#x8FF9D3 #xE556)
+                (#x8FF9D4 #xE557)
+                (#x8FF9D5 #xE558)
+                (#x8FF9D6 #xE559)
+                (#x8FF9D7 #xE55A)
+                (#x8FF9D8 #xE55B)
+                (#x8FF9D9 #xE55C)
+                (#x8FF9DA #xE55D)
+                (#x8FF9DB #xE55E)
+                (#x8FF9DC #xE55F)
+                (#x8FF9DD #xE560)
+                (#x8FF9DE #xE561)
+                (#x8FF9DF #xE562)
+                (#x8FF9E0 #xE563)
+                (#x8FF9E1 #xE564)
+                (#x8FF9E2 #xE565)
+                (#x8FF9E3 #xE566)
+                (#x8FF9E4 #xE567)
+                (#x8FF9E5 #xE568)
+                (#x8FF9E6 #xE569)
+                (#x8FF9E7 #xE56A)
+                (#x8FF9E8 #xE56B)
+                (#x8FF9E9 #xE56C)
+                (#x8FF9EA #xE56D)
+                (#x8FF9EB #xE56E)
+                (#x8FF9EC #xE56F)
+                (#x8FF9ED #xE570)
+                (#x8FF9EE #xE571)
+                (#x8FF9EF #xE572)
+                (#x8FF9F0 #xE573)
+                (#x8FF9F1 #xE574)
+                (#x8FF9F2 #xE575)
+                (#x8FF9F3 #xE576)
+                (#x8FF9F4 #xE577)
+                (#x8FF9F5 #xE578)
+                (#x8FF9F6 #xE579)
+                (#x8FF9F7 #xE57A)
+                (#x8FF9F8 #xE57B)
+                (#x8FF9F9 #xE57C)
+                (#x8FF9FA #xE57D)
+                (#x8FF9FB #xE57E)
+                (#x8FF9FC #xE57F)
+                (#x8FF9FD #xE580)
+                (#x8FF9FE #xE581)
+                (#x8FFAA1 #xE582)
+                (#x8FFAA2 #xE583)
+                (#x8FFAA3 #xE584)
+                (#x8FFAA4 #xE585)
+                (#x8FFAA5 #xE586)
+                (#x8FFAA6 #xE587)
+                (#x8FFAA7 #xE588)
+                (#x8FFAA8 #xE589)
+                (#x8FFAA9 #xE58A)
+                (#x8FFAAA #xE58B)
+                (#x8FFAAB #xE58C)
+                (#x8FFAAC #xE58D)
+                (#x8FFAAD #xE58E)
+                (#x8FFAAE #xE58F)
+                (#x8FFAAF #xE590)
+                (#x8FFAB0 #xE591)
+                (#x8FFAB1 #xE592)
+                (#x8FFAB2 #xE593)
+                (#x8FFAB3 #xE594)
+                (#x8FFAB4 #xE595)
+                (#x8FFAB5 #xE596)
+                (#x8FFAB6 #xE597)
+                (#x8FFAB7 #xE598)
+                (#x8FFAB8 #xE599)
+                (#x8FFAB9 #xE59A)
+                (#x8FFABA #xE59B)
+                (#x8FFABB #xE59C)
+                (#x8FFABC #xE59D)
+                (#x8FFABD #xE59E)
+                (#x8FFABE #xE59F)
+                (#x8FFABF #xE5A0)
+                (#x8FFAC0 #xE5A1)
+                (#x8FFAC1 #xE5A2)
+                (#x8FFAC2 #xE5A3)
+                (#x8FFAC3 #xE5A4)
+                (#x8FFAC4 #xE5A5)
+                (#x8FFAC5 #xE5A6)
+                (#x8FFAC6 #xE5A7)
+                (#x8FFAC7 #xE5A8)
+                (#x8FFAC8 #xE5A9)
+                (#x8FFAC9 #xE5AA)
+                (#x8FFACA #xE5AB)
+                (#x8FFACB #xE5AC)
+                (#x8FFACC #xE5AD)
+                (#x8FFACD #xE5AE)
+                (#x8FFACE #xE5AF)
+                (#x8FFACF #xE5B0)
+                (#x8FFAD0 #xE5B1)
+                (#x8FFAD1 #xE5B2)
+                (#x8FFAD2 #xE5B3)
+                (#x8FFAD3 #xE5B4)
+                (#x8FFAD4 #xE5B5)
+                (#x8FFAD5 #xE5B6)
+                (#x8FFAD6 #xE5B7)
+                (#x8FFAD7 #xE5B8)
+                (#x8FFAD8 #xE5B9)
+                (#x8FFAD9 #xE5BA)
+                (#x8FFADA #xE5BB)
+                (#x8FFADB #xE5BC)
+                (#x8FFADC #xE5BD)
+                (#x8FFADD #xE5BE)
+                (#x8FFADE #xE5BF)
+                (#x8FFADF #xE5C0)
+                (#x8FFAE0 #xE5C1)
+                (#x8FFAE1 #xE5C2)
+                (#x8FFAE2 #xE5C3)
+                (#x8FFAE3 #xE5C4)
+                (#x8FFAE4 #xE5C5)
+                (#x8FFAE5 #xE5C6)
+                (#x8FFAE6 #xE5C7)
+                (#x8FFAE7 #xE5C8)
+                (#x8FFAE8 #xE5C9)
+                (#x8FFAE9 #xE5CA)
+                (#x8FFAEA #xE5CB)
+                (#x8FFAEB #xE5CC)
+                (#x8FFAEC #xE5CD)
+                (#x8FFAED #xE5CE)
+                (#x8FFAEE #xE5CF)
+                (#x8FFAEF #xE5D0)
+                (#x8FFAF0 #xE5D1)
+                (#x8FFAF1 #xE5D2)
+                (#x8FFAF2 #xE5D3)
+                (#x8FFAF3 #xE5D4)
+                (#x8FFAF4 #xE5D5)
+                (#x8FFAF5 #xE5D6)
+                (#x8FFAF6 #xE5D7)
+                (#x8FFAF7 #xE5D8)
+                (#x8FFAF8 #xE5D9)
+                (#x8FFAF9 #xE5DA)
+                (#x8FFAFA #xE5DB)
+                (#x8FFAFB #xE5DC)
+                (#x8FFAFC #xE5DD)
+                (#x8FFAFD #xE5DE)
+                (#x8FFAFE #xE5DF)
+                (#x8FFBA1 #xE5E0)
+                (#x8FFBA2 #xE5E1)
+                (#x8FFBA3 #xE5E2)
+                (#x8FFBA4 #xE5E3)
+                (#x8FFBA5 #xE5E4)
+                (#x8FFBA6 #xE5E5)
+                (#x8FFBA7 #xE5E6)
+                (#x8FFBA8 #xE5E7)
+                (#x8FFBA9 #xE5E8)
+                (#x8FFBAA #xE5E9)
+                (#x8FFBAB #xE5EA)
+                (#x8FFBAC #xE5EB)
+                (#x8FFBAD #xE5EC)
+                (#x8FFBAE #xE5ED)
+                (#x8FFBAF #xE5EE)
+                (#x8FFBB0 #xE5EF)
+                (#x8FFBB1 #xE5F0)
+                (#x8FFBB2 #xE5F1)
+                (#x8FFBB3 #xE5F2)
+                (#x8FFBB4 #xE5F3)
+                (#x8FFBB5 #xE5F4)
+                (#x8FFBB6 #xE5F5)
+                (#x8FFBB7 #xE5F6)
+                (#x8FFBB8 #xE5F7)
+                (#x8FFBB9 #xE5F8)
+                (#x8FFBBA #xE5F9)
+                (#x8FFBBB #xE5FA)
+                (#x8FFBBC #xE5FB)
+                (#x8FFBBD #xE5FC)
+                (#x8FFBBE #xE5FD)
+                (#x8FFBBF #xE5FE)
+                (#x8FFBC0 #xE5FF)
+                (#x8FFBC1 #xE600)
+                (#x8FFBC2 #xE601)
+                (#x8FFBC3 #xE602)
+                (#x8FFBC4 #xE603)
+                (#x8FFBC5 #xE604)
+                (#x8FFBC6 #xE605)
+                (#x8FFBC7 #xE606)
+                (#x8FFBC8 #xE607)
+                (#x8FFBC9 #xE608)
+                (#x8FFBCA #xE609)
+                (#x8FFBCB #xE60A)
+                (#x8FFBCC #xE60B)
+                (#x8FFBCD #xE60C)
+                (#x8FFBCE #xE60D)
+                (#x8FFBCF #xE60E)
+                (#x8FFBD0 #xE60F)
+                (#x8FFBD1 #xE610)
+                (#x8FFBD2 #xE611)
+                (#x8FFBD3 #xE612)
+                (#x8FFBD4 #xE613)
+                (#x8FFBD5 #xE614)
+                (#x8FFBD6 #xE615)
+                (#x8FFBD7 #xE616)
+                (#x8FFBD8 #xE617)
+                (#x8FFBD9 #xE618)
+                (#x8FFBDA #xE619)
+                (#x8FFBDB #xE61A)
+                (#x8FFBDC #xE61B)
+                (#x8FFBDD #xE61C)
+                (#x8FFBDE #xE61D)
+                (#x8FFBDF #xE61E)
+                (#x8FFBE0 #xE61F)
+                (#x8FFBE1 #xE620)
+                (#x8FFBE2 #xE621)
+                (#x8FFBE3 #xE622)
+                (#x8FFBE4 #xE623)
+                (#x8FFBE5 #xE624)
+                (#x8FFBE6 #xE625)
+                (#x8FFBE7 #xE626)
+                (#x8FFBE8 #xE627)
+                (#x8FFBE9 #xE628)
+                (#x8FFBEA #xE629)
+                (#x8FFBEB #xE62A)
+                (#x8FFBEC #xE62B)
+                (#x8FFBED #xE62C)
+                (#x8FFBEE #xE62D)
+                (#x8FFBEF #xE62E)
+                (#x8FFBF0 #xE62F)
+                (#x8FFBF1 #xE630)
+                (#x8FFBF2 #xE631)
+                (#x8FFBF3 #xE632)
+                (#x8FFBF4 #xE633)
+                (#x8FFBF5 #xE634)
+                (#x8FFBF6 #xE635)
+                (#x8FFBF7 #xE636)
+                (#x8FFBF8 #xE637)
+                (#x8FFBF9 #xE638)
+                (#x8FFBFA #xE639)
+                (#x8FFBFB #xE63A)
+                (#x8FFBFC #xE63B)
+                (#x8FFBFD #xE63C)
+                (#x8FFBFE #xE63D)
+                (#x8FFCA1 #xE63E)
+                (#x8FFCA2 #xE63F)
+                (#x8FFCA3 #xE640)
+                (#x8FFCA4 #xE641)
+                (#x8FFCA5 #xE642)
+                (#x8FFCA6 #xE643)
+                (#x8FFCA7 #xE644)
+                (#x8FFCA8 #xE645)
+                (#x8FFCA9 #xE646)
+                (#x8FFCAA #xE647)
+                (#x8FFCAB #xE648)
+                (#x8FFCAC #xE649)
+                (#x8FFCAD #xE64A)
+                (#x8FFCAE #xE64B)
+                (#x8FFCAF #xE64C)
+                (#x8FFCB0 #xE64D)
+                (#x8FFCB1 #xE64E)
+                (#x8FFCB2 #xE64F)
+                (#x8FFCB3 #xE650)
+                (#x8FFCB4 #xE651)
+                (#x8FFCB5 #xE652)
+                (#x8FFCB6 #xE653)
+                (#x8FFCB7 #xE654)
+                (#x8FFCB8 #xE655)
+                (#x8FFCB9 #xE656)
+                (#x8FFCBA #xE657)
+                (#x8FFCBB #xE658)
+                (#x8FFCBC #xE659)
+                (#x8FFCBD #xE65A)
+                (#x8FFCBE #xE65B)
+                (#x8FFCBF #xE65C)
+                (#x8FFCC0 #xE65D)
+                (#x8FFCC1 #xE65E)
+                (#x8FFCC2 #xE65F)
+                (#x8FFCC3 #xE660)
+                (#x8FFCC4 #xE661)
+                (#x8FFCC5 #xE662)
+                (#x8FFCC6 #xE663)
+                (#x8FFCC7 #xE664)
+                (#x8FFCC8 #xE665)
+                (#x8FFCC9 #xE666)
+                (#x8FFCCA #xE667)
+                (#x8FFCCB #xE668)
+                (#x8FFCCC #xE669)
+                (#x8FFCCD #xE66A)
+                (#x8FFCCE #xE66B)
+                (#x8FFCCF #xE66C)
+                (#x8FFCD0 #xE66D)
+                (#x8FFCD1 #xE66E)
+                (#x8FFCD2 #xE66F)
+                (#x8FFCD3 #xE670)
+                (#x8FFCD4 #xE671)
+                (#x8FFCD5 #xE672)
+                (#x8FFCD6 #xE673)
+                (#x8FFCD7 #xE674)
+                (#x8FFCD8 #xE675)
+                (#x8FFCD9 #xE676)
+                (#x8FFCDA #xE677)
+                (#x8FFCDB #xE678)
+                (#x8FFCDC #xE679)
+                (#x8FFCDD #xE67A)
+                (#x8FFCDE #xE67B)
+                (#x8FFCDF #xE67C)
+                (#x8FFCE0 #xE67D)
+                (#x8FFCE1 #xE67E)
+                (#x8FFCE2 #xE67F)
+                (#x8FFCE3 #xE680)
+                (#x8FFCE4 #xE681)
+                (#x8FFCE5 #xE682)
+                (#x8FFCE6 #xE683)
+                (#x8FFCE7 #xE684)
+                (#x8FFCE8 #xE685)
+                (#x8FFCE9 #xE686)
+                (#x8FFCEA #xE687)
+                (#x8FFCEB #xE688)
+                (#x8FFCEC #xE689)
+                (#x8FFCED #xE68A)
+                (#x8FFCEE #xE68B)
+                (#x8FFCEF #xE68C)
+                (#x8FFCF0 #xE68D)
+                (#x8FFCF1 #xE68E)
+                (#x8FFCF2 #xE68F)
+                (#x8FFCF3 #xE690)
+                (#x8FFCF4 #xE691)
+                (#x8FFCF5 #xE692)
+                (#x8FFCF6 #xE693)
+                (#x8FFCF7 #xE694)
+                (#x8FFCF8 #xE695)
+                (#x8FFCF9 #xE696)
+                (#x8FFCFA #xE697)
+                (#x8FFCFB #xE698)
+                (#x8FFCFC #xE699)
+                (#x8FFCFD #xE69A)
+                (#x8FFCFE #xE69B)
+                (#x8FFDA1 #xE69C)
+                (#x8FFDA2 #xE69D)
+                (#x8FFDA3 #xE69E)
+                (#x8FFDA4 #xE69F)
+                (#x8FFDA5 #xE6A0)
+                (#x8FFDA6 #xE6A1)
+                (#x8FFDA7 #xE6A2)
+                (#x8FFDA8 #xE6A3)
+                (#x8FFDA9 #xE6A4)
+                (#x8FFDAA #xE6A5)
+                (#x8FFDAB #xE6A6)
+                (#x8FFDAC #xE6A7)
+                (#x8FFDAD #xE6A8)
+                (#x8FFDAE #xE6A9)
+                (#x8FFDAF #xE6AA)
+                (#x8FFDB0 #xE6AB)
+                (#x8FFDB1 #xE6AC)
+                (#x8FFDB2 #xE6AD)
+                (#x8FFDB3 #xE6AE)
+                (#x8FFDB4 #xE6AF)
+                (#x8FFDB5 #xE6B0)
+                (#x8FFDB6 #xE6B1)
+                (#x8FFDB7 #xE6B2)
+                (#x8FFDB8 #xE6B3)
+                (#x8FFDB9 #xE6B4)
+                (#x8FFDBA #xE6B5)
+                (#x8FFDBB #xE6B6)
+                (#x8FFDBC #xE6B7)
+                (#x8FFDBD #xE6B8)
+                (#x8FFDBE #xE6B9)
+                (#x8FFDBF #xE6BA)
+                (#x8FFDC0 #xE6BB)
+                (#x8FFDC1 #xE6BC)
+                (#x8FFDC2 #xE6BD)
+                (#x8FFDC3 #xE6BE)
+                (#x8FFDC4 #xE6BF)
+                (#x8FFDC5 #xE6C0)
+                (#x8FFDC6 #xE6C1)
+                (#x8FFDC7 #xE6C2)
+                (#x8FFDC8 #xE6C3)
+                (#x8FFDC9 #xE6C4)
+                (#x8FFDCA #xE6C5)
+                (#x8FFDCB #xE6C6)
+                (#x8FFDCC #xE6C7)
+                (#x8FFDCD #xE6C8)
+                (#x8FFDCE #xE6C9)
+                (#x8FFDCF #xE6CA)
+                (#x8FFDD0 #xE6CB)
+                (#x8FFDD1 #xE6CC)
+                (#x8FFDD2 #xE6CD)
+                (#x8FFDD3 #xE6CE)
+                (#x8FFDD4 #xE6CF)
+                (#x8FFDD5 #xE6D0)
+                (#x8FFDD6 #xE6D1)
+                (#x8FFDD7 #xE6D2)
+                (#x8FFDD8 #xE6D3)
+                (#x8FFDD9 #xE6D4)
+                (#x8FFDDA #xE6D5)
+                (#x8FFDDB #xE6D6)
+                (#x8FFDDC #xE6D7)
+                (#x8FFDDD #xE6D8)
+                (#x8FFDDE #xE6D9)
+                (#x8FFDDF #xE6DA)
+                (#x8FFDE0 #xE6DB)
+                (#x8FFDE1 #xE6DC)
+                (#x8FFDE2 #xE6DD)
+                (#x8FFDE3 #xE6DE)
+                (#x8FFDE4 #xE6DF)
+                (#x8FFDE5 #xE6E0)
+                (#x8FFDE6 #xE6E1)
+                (#x8FFDE7 #xE6E2)
+                (#x8FFDE8 #xE6E3)
+                (#x8FFDE9 #xE6E4)
+                (#x8FFDEA #xE6E5)
+                (#x8FFDEB #xE6E6)
+                (#x8FFDEC #xE6E7)
+                (#x8FFDED #xE6E8)
+                (#x8FFDEE #xE6E9)
+                (#x8FFDEF #xE6EA)
+                (#x8FFDF0 #xE6EB)
+                (#x8FFDF1 #xE6EC)
+                (#x8FFDF2 #xE6ED)
+                (#x8FFDF3 #xE6EE)
+                (#x8FFDF4 #xE6EF)
+                (#x8FFDF5 #xE6F0)
+                (#x8FFDF6 #xE6F1)
+                (#x8FFDF7 #xE6F2)
+                (#x8FFDF8 #xE6F3)
+                (#x8FFDF9 #xE6F4)
+                (#x8FFDFA #xE6F5)
+                (#x8FFDFB #xE6F6)
+                (#x8FFDFC #xE6F7)
+                (#x8FFDFD #xE6F8)
+                (#x8FFDFE #xE6F9)
+                (#x8FFEA1 #xE6FA)
+                (#x8FFEA2 #xE6FB)
+                (#x8FFEA3 #xE6FC)
+                (#x8FFEA4 #xE6FD)
+                (#x8FFEA5 #xE6FE)
+                (#x8FFEA6 #xE6FF)
+                (#x8FFEA7 #xE700)
+                (#x8FFEA8 #xE701)
+                (#x8FFEA9 #xE702)
+                (#x8FFEAA #xE703)
+                (#x8FFEAB #xE704)
+                (#x8FFEAC #xE705)
+                (#x8FFEAD #xE706)
+                (#x8FFEAE #xE707)
+                (#x8FFEAF #xE708)
+                (#x8FFEB0 #xE709)
+                (#x8FFEB1 #xE70A)
+                (#x8FFEB2 #xE70B)
+                (#x8FFEB3 #xE70C)
+                (#x8FFEB4 #xE70D)
+                (#x8FFEB5 #xE70E)
+                (#x8FFEB6 #xE70F)
+                (#x8FFEB7 #xE710)
+                (#x8FFEB8 #xE711)
+                (#x8FFEB9 #xE712)
+                (#x8FFEBA #xE713)
+                (#x8FFEBB #xE714)
+                (#x8FFEBC #xE715)
+                (#x8FFEBD #xE716)
+                (#x8FFEBE #xE717)
+                (#x8FFEBF #xE718)
+                (#x8FFEC0 #xE719)
+                (#x8FFEC1 #xE71A)
+                (#x8FFEC2 #xE71B)
+                (#x8FFEC3 #xE71C)
+                (#x8FFEC4 #xE71D)
+                (#x8FFEC5 #xE71E)
+                (#x8FFEC6 #xE71F)
+                (#x8FFEC7 #xE720)
+                (#x8FFEC8 #xE721)
+                (#x8FFEC9 #xE722)
+                (#x8FFECA #xE723)
+                (#x8FFECB #xE724)
+                (#x8FFECC #xE725)
+                (#x8FFECD #xE726)
+                (#x8FFECE #xE727)
+                (#x8FFECF #xE728)
+                (#x8FFED0 #xE729)
+                (#x8FFED1 #xE72A)
+                (#x8FFED2 #xE72B)
+                (#x8FFED3 #xE72C)
+                (#x8FFED4 #xE72D)
+                (#x8FFED5 #xE72E)
+                (#x8FFED6 #xE72F)
+                (#x8FFED7 #xE730)
+                (#x8FFED8 #xE731)
+                (#x8FFED9 #xE732)
+                (#x8FFEDA #xE733)
+                (#x8FFEDB #xE734)
+                (#x8FFEDC #xE735)
+                (#x8FFEDD #xE736)
+                (#x8FFEDE #xE737)
+                (#x8FFEDF #xE738)
+                (#x8FFEE0 #xE739)
+                (#x8FFEE1 #xE73A)
+                (#x8FFEE2 #xE73B)
+                (#x8FFEE3 #xE73C)
+                (#x8FFEE4 #xE73D)
+                (#x8FFEE5 #xE73E)
+                (#x8FFEE6 #xE73F)
+                (#x8FFEE7 #xE740)
+                (#x8FFEE8 #xE741)
+                (#x8FFEE9 #xE742)
+                (#x8FFEEA #xE743)
+                (#x8FFEEB #xE744)
+                (#x8FFEEC #xE745)
+                (#x8FFEED #xE746)
+                (#x8FFEEE #xE747)
+                (#x8FFEEF #xE748)
+                (#x8FFEF0 #xE749)
+                (#x8FFEF1 #xE74A)
+                (#x8FFEF2 #xE74B)
+                (#x8FFEF3 #xE74C)
+                (#x8FFEF4 #xE74D)
+                (#x8FFEF5 #xE74E)
+                (#x8FFEF6 #xE74F)
+                (#x8FFEF7 #xE750)
+                (#x8FFEF8 #xE751)
+                (#x8FFEF9 #xE752)
+                (#x8FFEFA #xE753)
+                (#x8FFEFB #xE754)
+                (#x8FFEFC #xE755)
+                (#x8FFEFD #xE756)
+                (#x8FFEFE #xE757)
+                (#xA1A1 #x3000)
+                (#xA1A2 #x3001)
+                (#xA1A3 #x3002)
+                (#xA1A4 #xFF0C)
+                (#xA1A5 #xFF0E)
+                (#xA1A6 #x30FB)
+                (#xA1A7 #xFF1A)
+                (#xA1A8 #xFF1B)
+                (#xA1A9 #xFF1F)
+                (#xA1AA #xFF01)
+                (#xA1AB #x309B)
+                (#xA1AC #x309C)
+                (#xA1AD #xB4)
+                (#xA1AE #xFF40)
+                (#xA1AF #xA8)
+                (#xA1B0 #xFF3E)
+                (#xA1B1 #xFFE3)
+                (#xA1B2 #xFF3F)
+                (#xA1B3 #x30FD)
+                (#xA1B4 #x30FE)
+                (#xA1B5 #x309D)
+                (#xA1B6 #x309E)
+                (#xA1B7 #x3003)
+                (#xA1B8 #x4EDD)
+                (#xA1B9 #x3005)
+                (#xA1BA #x3006)
+                (#xA1BB #x3007)
+                (#xA1BC #x30FC)
+                (#xA1BD #x2015)
+                (#xA1BE #x2010)
+                (#xA1BF #xFF0F)
+                (#xA1C0 #xFF3C)
+                (#xA1C1 #x301C)
+                (#xA1C2 #x2016)
+                (#xA1C3 #xFF5C)
+                (#xA1C4 #x2026)
+                (#xA1C5 #x2025)
+                (#xA1C6 #x2018)
+                (#xA1C7 #x2019)
+                (#xA1C8 #x201C)
+                (#xA1C9 #x201D)
+                (#xA1CA #xFF08)
+                (#xA1CB #xFF09)
+                (#xA1CC #x3014)
+                (#xA1CD #x3015)
+                (#xA1CE #xFF3B)
+                (#xA1CF #xFF3D)
+                (#xA1D0 #xFF5B)
+                (#xA1D1 #xFF5D)
+                (#xA1D2 #x3008)
+                (#xA1D3 #x3009)
+                (#xA1D4 #x300A)
+                (#xA1D5 #x300B)
+                (#xA1D6 #x300C)
+                (#xA1D7 #x300D)
+                (#xA1D8 #x300E)
+                (#xA1D9 #x300F)
+                (#xA1DA #x3010)
+                (#xA1DB #x3011)
+                (#xA1DC #xFF0B)
+                (#xA1DD #x2212)
+                (#xA1DE #xB1)
+                (#xA1DF #xD7)
+                (#xA1E0 #xF7)
+                (#xA1E1 #xFF1D)
+                (#xA1E2 #x2260)
+                (#xA1E3 #xFF1C)
+                (#xA1E4 #xFF1E)
+                (#xA1E5 #x2266)
+                (#xA1E6 #x2267)
+                (#xA1E7 #x221E)
+                (#xA1E8 #x2234)
+                (#xA1E9 #x2642)
+                (#xA1EA #x2640)
+                (#xA1EB #xB0)
+                (#xA1EC #x2032)
+                (#xA1ED #x2033)
+                (#xA1EE #x2103)
+                (#xA1EF #xFFE5)
+                (#xA1F0 #xFF04)
+                (#xA1F1 #xA2)
+                (#xA1F2 #xA3)
+                (#xA1F3 #xFF05)
+                (#xA1F4 #xFF03)
+                (#xA1F5 #xFF06)
+                (#xA1F6 #xFF0A)
+                (#xA1F7 #xFF20)
+                (#xA1F8 #xA7)
+                (#xA1F9 #x2606)
+                (#xA1FA #x2605)
+                (#xA1FB #x25CB)
+                (#xA1FC #x25CF)
+                (#xA1FD #x25CE)
+                (#xA1FE #x25C7)
+                (#xA2A1 #x25C6)
+                (#xA2A2 #x25A1)
+                (#xA2A3 #x25A0)
+                (#xA2A4 #x25B3)
+                (#xA2A5 #x25B2)
+                (#xA2A6 #x25BD)
+                (#xA2A7 #x25BC)
+                (#xA2A8 #x203B)
+                (#xA2A9 #x3012)
+                (#xA2AA #x2192)
+                (#xA2AB #x2190)
+                (#xA2AC #x2191)
+                (#xA2AD #x2193)
+                (#xA2AE #x3013)
+                (#xA2BA #x2208)
+                (#xA2BB #x220B)
+                (#xA2BC #x2286)
+                (#xA2BD #x2287)
+                (#xA2BE #x2282)
+                (#xA2BF #x2283)
+                (#xA2C0 #x222A)
+                (#xA2C1 #x2229)
+                (#xA2CA #x2227)
+                (#xA2CB #x2228)
+                (#xA2CC #xAC)
+                (#xA2CD #x21D2)
+                (#xA2CE #x21D4)
+                (#xA2CF #x2200)
+                (#xA2D0 #x2203)
+                (#xA2DC #x2220)
+                (#xA2DD #x22A5)
+                (#xA2DE #x2312)
+                (#xA2DF #x2202)
+                (#xA2E0 #x2207)
+                (#xA2E1 #x2261)
+                (#xA2E2 #x2252)
+                (#xA2E3 #x226A)
+                (#xA2E4 #x226B)
+                (#xA2E5 #x221A)
+                (#xA2E6 #x223D)
+                (#xA2E7 #x221D)
+                (#xA2E8 #x2235)
+                (#xA2E9 #x222B)
+                (#xA2EA #x222C)
+                (#xA2F2 #x212B)
+                (#xA2F3 #x2030)
+                (#xA2F4 #x266F)
+                (#xA2F5 #x266D)
+                (#xA2F6 #x266A)
+                (#xA2F7 #x2020)
+                (#xA2F8 #x2021)
+                (#xA2F9 #xB6)
+                (#xA2FE #x25EF)
+                (#xA3B0 #xFF10)
+                (#xA3B1 #xFF11)
+                (#xA3B2 #xFF12)
+                (#xA3B3 #xFF13)
+                (#xA3B4 #xFF14)
+                (#xA3B5 #xFF15)
+                (#xA3B6 #xFF16)
+                (#xA3B7 #xFF17)
+                (#xA3B8 #xFF18)
+                (#xA3B9 #xFF19)
+                (#xA3C1 #xFF21)
+                (#xA3C2 #xFF22)
+                (#xA3C3 #xFF23)
+                (#xA3C4 #xFF24)
+                (#xA3C5 #xFF25)
+                (#xA3C6 #xFF26)
+                (#xA3C7 #xFF27)
+                (#xA3C8 #xFF28)
+                (#xA3C9 #xFF29)
+                (#xA3CA #xFF2A)
+                (#xA3CB #xFF2B)
+                (#xA3CC #xFF2C)
+                (#xA3CD #xFF2D)
+                (#xA3CE #xFF2E)
+                (#xA3CF #xFF2F)
+                (#xA3D0 #xFF30)
+                (#xA3D1 #xFF31)
+                (#xA3D2 #xFF32)
+                (#xA3D3 #xFF33)
+                (#xA3D4 #xFF34)
+                (#xA3D5 #xFF35)
+                (#xA3D6 #xFF36)
+                (#xA3D7 #xFF37)
+                (#xA3D8 #xFF38)
+                (#xA3D9 #xFF39)
+                (#xA3DA #xFF3A)
+                (#xA3E1 #xFF41)
+                (#xA3E2 #xFF42)
+                (#xA3E3 #xFF43)
+                (#xA3E4 #xFF44)
+                (#xA3E5 #xFF45)
+                (#xA3E6 #xFF46)
+                (#xA3E7 #xFF47)
+                (#xA3E8 #xFF48)
+                (#xA3E9 #xFF49)
+                (#xA3EA #xFF4A)
+                (#xA3EB #xFF4B)
+                (#xA3EC #xFF4C)
+                (#xA3ED #xFF4D)
+                (#xA3EE #xFF4E)
+                (#xA3EF #xFF4F)
+                (#xA3F0 #xFF50)
+                (#xA3F1 #xFF51)
+                (#xA3F2 #xFF52)
+                (#xA3F3 #xFF53)
+                (#xA3F4 #xFF54)
+                (#xA3F5 #xFF55)
+                (#xA3F6 #xFF56)
+                (#xA3F7 #xFF57)
+                (#xA3F8 #xFF58)
+                (#xA3F9 #xFF59)
+                (#xA3FA #xFF5A)
+                (#xA4A1 #x3041)
+                (#xA4A2 #x3042)
+                (#xA4A3 #x3043)
+                (#xA4A4 #x3044)
+                (#xA4A5 #x3045)
+                (#xA4A6 #x3046)
+                (#xA4A7 #x3047)
+                (#xA4A8 #x3048)
+                (#xA4A9 #x3049)
+                (#xA4AA #x304A)
+                (#xA4AB #x304B)
+                (#xA4AC #x304C)
+                (#xA4AD #x304D)
+                (#xA4AE #x304E)
+                (#xA4AF #x304F)
+                (#xA4B0 #x3050)
+                (#xA4B1 #x3051)
+                (#xA4B2 #x3052)
+                (#xA4B3 #x3053)
+                (#xA4B4 #x3054)
+                (#xA4B5 #x3055)
+                (#xA4B6 #x3056)
+                (#xA4B7 #x3057)
+                (#xA4B8 #x3058)
+                (#xA4B9 #x3059)
+                (#xA4BA #x305A)
+                (#xA4BB #x305B)
+                (#xA4BC #x305C)
+                (#xA4BD #x305D)
+                (#xA4BE #x305E)
+                (#xA4BF #x305F)
+                (#xA4C0 #x3060)
+                (#xA4C1 #x3061)
+                (#xA4C2 #x3062)
+                (#xA4C3 #x3063)
+                (#xA4C4 #x3064)
+                (#xA4C5 #x3065)
+                (#xA4C6 #x3066)
+                (#xA4C7 #x3067)
+                (#xA4C8 #x3068)
+                (#xA4C9 #x3069)
+                (#xA4CA #x306A)
+                (#xA4CB #x306B)
+                (#xA4CC #x306C)
+                (#xA4CD #x306D)
+                (#xA4CE #x306E)
+                (#xA4CF #x306F)
+                (#xA4D0 #x3070)
+                (#xA4D1 #x3071)
+                (#xA4D2 #x3072)
+                (#xA4D3 #x3073)
+                (#xA4D4 #x3074)
+                (#xA4D5 #x3075)
+                (#xA4D6 #x3076)
+                (#xA4D7 #x3077)
+                (#xA4D8 #x3078)
+                (#xA4D9 #x3079)
+                (#xA4DA #x307A)
+                (#xA4DB #x307B)
+                (#xA4DC #x307C)
+                (#xA4DD #x307D)
+                (#xA4DE #x307E)
+                (#xA4DF #x307F)
+                (#xA4E0 #x3080)
+                (#xA4E1 #x3081)
+                (#xA4E2 #x3082)
+                (#xA4E3 #x3083)
+                (#xA4E4 #x3084)
+                (#xA4E5 #x3085)
+                (#xA4E6 #x3086)
+                (#xA4E7 #x3087)
+                (#xA4E8 #x3088)
+                (#xA4E9 #x3089)
+                (#xA4EA #x308A)
+                (#xA4EB #x308B)
+                (#xA4EC #x308C)
+                (#xA4ED #x308D)
+                (#xA4EE #x308E)
+                (#xA4EF #x308F)
+                (#xA4F0 #x3090)
+                (#xA4F1 #x3091)
+                (#xA4F2 #x3092)
+                (#xA4F3 #x3093)
+                (#xA5A1 #x30A1)
+                (#xA5A2 #x30A2)
+                (#xA5A3 #x30A3)
+                (#xA5A4 #x30A4)
+                (#xA5A5 #x30A5)
+                (#xA5A6 #x30A6)
+                (#xA5A7 #x30A7)
+                (#xA5A8 #x30A8)
+                (#xA5A9 #x30A9)
+                (#xA5AA #x30AA)
+                (#xA5AB #x30AB)
+                (#xA5AC #x30AC)
+                (#xA5AD #x30AD)
+                (#xA5AE #x30AE)
+                (#xA5AF #x30AF)
+                (#xA5B0 #x30B0)
+                (#xA5B1 #x30B1)
+                (#xA5B2 #x30B2)
+                (#xA5B3 #x30B3)
+                (#xA5B4 #x30B4)
+                (#xA5B5 #x30B5)
+                (#xA5B6 #x30B6)
+                (#xA5B7 #x30B7)
+                (#xA5B8 #x30B8)
+                (#xA5B9 #x30B9)
+                (#xA5BA #x30BA)
+                (#xA5BB #x30BB)
+                (#xA5BC #x30BC)
+                (#xA5BD #x30BD)
+                (#xA5BE #x30BE)
+                (#xA5BF #x30BF)
+                (#xA5C0 #x30C0)
+                (#xA5C1 #x30C1)
+                (#xA5C2 #x30C2)
+                (#xA5C3 #x30C3)
+                (#xA5C4 #x30C4)
+                (#xA5C5 #x30C5)
+                (#xA5C6 #x30C6)
+                (#xA5C7 #x30C7)
+                (#xA5C8 #x30C8)
+                (#xA5C9 #x30C9)
+                (#xA5CA #x30CA)
+                (#xA5CB #x30CB)
+                (#xA5CC #x30CC)
+                (#xA5CD #x30CD)
+                (#xA5CE #x30CE)
+                (#xA5CF #x30CF)
+                (#xA5D0 #x30D0)
+                (#xA5D1 #x30D1)
+                (#xA5D2 #x30D2)
+                (#xA5D3 #x30D3)
+                (#xA5D4 #x30D4)
+                (#xA5D5 #x30D5)
+                (#xA5D6 #x30D6)
+                (#xA5D7 #x30D7)
+                (#xA5D8 #x30D8)
+                (#xA5D9 #x30D9)
+                (#xA5DA #x30DA)
+                (#xA5DB #x30DB)
+                (#xA5DC #x30DC)
+                (#xA5DD #x30DD)
+                (#xA5DE #x30DE)
+                (#xA5DF #x30DF)
+                (#xA5E0 #x30E0)
+                (#xA5E1 #x30E1)
+                (#xA5E2 #x30E2)
+                (#xA5E3 #x30E3)
+                (#xA5E4 #x30E4)
+                (#xA5E5 #x30E5)
+                (#xA5E6 #x30E6)
+                (#xA5E7 #x30E7)
+                (#xA5E8 #x30E8)
+                (#xA5E9 #x30E9)
+                (#xA5EA #x30EA)
+                (#xA5EB #x30EB)
+                (#xA5EC #x30EC)
+                (#xA5ED #x30ED)
+                (#xA5EE #x30EE)
+                (#xA5EF #x30EF)
+                (#xA5F0 #x30F0)
+                (#xA5F1 #x30F1)
+                (#xA5F2 #x30F2)
+                (#xA5F3 #x30F3)
+                (#xA5F4 #x30F4)
+                (#xA5F5 #x30F5)
+                (#xA5F6 #x30F6)
+                (#xA6A1 #x391)
+                (#xA6A2 #x392)
+                (#xA6A3 #x393)
+                (#xA6A4 #x394)
+                (#xA6A5 #x395)
+                (#xA6A6 #x396)
+                (#xA6A7 #x397)
+                (#xA6A8 #x398)
+                (#xA6A9 #x399)
+                (#xA6AA #x39A)
+                (#xA6AB #x39B)
+                (#xA6AC #x39C)
+                (#xA6AD #x39D)
+                (#xA6AE #x39E)
+                (#xA6AF #x39F)
+                (#xA6B0 #x3A0)
+                (#xA6B1 #x3A1)
+                (#xA6B2 #x3A3)
+                (#xA6B3 #x3A4)
+                (#xA6B4 #x3A5)
+                (#xA6B5 #x3A6)
+                (#xA6B6 #x3A7)
+                (#xA6B7 #x3A8)
+                (#xA6B8 #x3A9)
+                (#xA6C1 #x3B1)
+                (#xA6C2 #x3B2)
+                (#xA6C3 #x3B3)
+                (#xA6C4 #x3B4)
+                (#xA6C5 #x3B5)
+                (#xA6C6 #x3B6)
+                (#xA6C7 #x3B7)
+                (#xA6C8 #x3B8)
+                (#xA6C9 #x3B9)
+                (#xA6CA #x3BA)
+                (#xA6CB #x3BB)
+                (#xA6CC #x3BC)
+                (#xA6CD #x3BD)
+                (#xA6CE #x3BE)
+                (#xA6CF #x3BF)
+                (#xA6D0 #x3C0)
+                (#xA6D1 #x3C1)
+                (#xA6D2 #x3C3)
+                (#xA6D3 #x3C4)
+                (#xA6D4 #x3C5)
+                (#xA6D5 #x3C6)
+                (#xA6D6 #x3C7)
+                (#xA6D7 #x3C8)
+                (#xA6D8 #x3C9)
+                (#xA7A1 #x410)
+                (#xA7A2 #x411)
+                (#xA7A3 #x412)
+                (#xA7A4 #x413)
+                (#xA7A5 #x414)
+                (#xA7A6 #x415)
+                (#xA7A7 #x401)
+                (#xA7A8 #x416)
+                (#xA7A9 #x417)
+                (#xA7AA #x418)
+                (#xA7AB #x419)
+                (#xA7AC #x41A)
+                (#xA7AD #x41B)
+                (#xA7AE #x41C)
+                (#xA7AF #x41D)
+                (#xA7B0 #x41E)
+                (#xA7B1 #x41F)
+                (#xA7B2 #x420)
+                (#xA7B3 #x421)
+                (#xA7B4 #x422)
+                (#xA7B5 #x423)
+                (#xA7B6 #x424)
+                (#xA7B7 #x425)
+                (#xA7B8 #x426)
+                (#xA7B9 #x427)
+                (#xA7BA #x428)
+                (#xA7BB #x429)
+                (#xA7BC #x42A)
+                (#xA7BD #x42B)
+                (#xA7BE #x42C)
+                (#xA7BF #x42D)
+                (#xA7C0 #x42E)
+                (#xA7C1 #x42F)
+                (#xA7D1 #x430)
+                (#xA7D2 #x431)
+                (#xA7D3 #x432)
+                (#xA7D4 #x433)
+                (#xA7D5 #x434)
+                (#xA7D6 #x435)
+                (#xA7D7 #x451)
+                (#xA7D8 #x436)
+                (#xA7D9 #x437)
+                (#xA7DA #x438)
+                (#xA7DB #x439)
+                (#xA7DC #x43A)
+                (#xA7DD #x43B)
+                (#xA7DE #x43C)
+                (#xA7DF #x43D)
+                (#xA7E0 #x43E)
+                (#xA7E1 #x43F)
+                (#xA7E2 #x440)
+                (#xA7E3 #x441)
+                (#xA7E4 #x442)
+                (#xA7E5 #x443)
+                (#xA7E6 #x444)
+                (#xA7E7 #x445)
+                (#xA7E8 #x446)
+                (#xA7E9 #x447)
+                (#xA7EA #x448)
+                (#xA7EB #x449)
+                (#xA7EC #x44A)
+                (#xA7ED #x44B)
+                (#xA7EE #x44C)
+                (#xA7EF #x44D)
+                (#xA7F0 #x44E)
+                (#xA7F1 #x44F)
+                (#xA8A1 #x2500)
+                (#xA8A2 #x2502)
+                (#xA8A3 #x250C)
+                (#xA8A4 #x2510)
+                (#xA8A5 #x2518)
+                (#xA8A6 #x2514)
+                (#xA8A7 #x251C)
+                (#xA8A8 #x252C)
+                (#xA8A9 #x2524)
+                (#xA8AA #x2534)
+                (#xA8AB #x253C)
+                (#xA8AC #x2501)
+                (#xA8AD #x2503)
+                (#xA8AE #x250F)
+                (#xA8AF #x2513)
+                (#xA8B0 #x251B)
+                (#xA8B1 #x2517)
+                (#xA8B2 #x2523)
+                (#xA8B3 #x2533)
+                (#xA8B4 #x252B)
+                (#xA8B5 #x253B)
+                (#xA8B6 #x254B)
+                (#xA8B7 #x2520)
+                (#xA8B8 #x252F)
+                (#xA8B9 #x2528)
+                (#xA8BA #x2537)
+                (#xA8BB #x253F)
+                (#xA8BC #x251D)
+                (#xA8BD #x2530)
+                (#xA8BE #x2525)
+                (#xA8BF #x2538)
+                (#xA8C0 #x2542)
+                (#xB0A1 #x4E9C)
+                (#xB0A2 #x5516)
+                (#xB0A3 #x5A03)
+                (#xB0A4 #x963F)
+                (#xB0A5 #x54C0)
+                (#xB0A6 #x611B)
+                (#xB0A7 #x6328)
+                (#xB0A8 #x59F6)
+                (#xB0A9 #x9022)
+                (#xB0AA #x8475)
+                (#xB0AB #x831C)
+                (#xB0AC #x7A50)
+                (#xB0AD #x60AA)
+                (#xB0AE #x63E1)
+                (#xB0AF #x6E25)
+                (#xB0B0 #x65ED)
+                (#xB0B1 #x8466)
+                (#xB0B2 #x82A6)
+                (#xB0B3 #x9BF5)
+                (#xB0B4 #x6893)
+                (#xB0B5 #x5727)
+                (#xB0B6 #x65A1)
+                (#xB0B7 #x6271)
+                (#xB0B8 #x5B9B)
+                (#xB0B9 #x59D0)
+                (#xB0BA #x867B)
+                (#xB0BB #x98F4)
+                (#xB0BC #x7D62)
+                (#xB0BD #x7DBE)
+                (#xB0BE #x9B8E)
+                (#xB0BF #x6216)
+                (#xB0C0 #x7C9F)
+                (#xB0C1 #x88B7)
+                (#xB0C2 #x5B89)
+                (#xB0C3 #x5EB5)
+                (#xB0C4 #x6309)
+                (#xB0C5 #x6697)
+                (#xB0C6 #x6848)
+                (#xB0C7 #x95C7)
+                (#xB0C8 #x978D)
+                (#xB0C9 #x674F)
+                (#xB0CA #x4EE5)
+                (#xB0CB #x4F0A)
+                (#xB0CC #x4F4D)
+                (#xB0CD #x4F9D)
+                (#xB0CE #x5049)
+                (#xB0CF #x56F2)
+                (#xB0D0 #x5937)
+                (#xB0D1 #x59D4)
+                (#xB0D2 #x5A01)
+                (#xB0D3 #x5C09)
+                (#xB0D4 #x60DF)
+                (#xB0D5 #x610F)
+                (#xB0D6 #x6170)
+                (#xB0D7 #x6613)
+                (#xB0D8 #x6905)
+                (#xB0D9 #x70BA)
+                (#xB0DA #x754F)
+                (#xB0DB #x7570)
+                (#xB0DC #x79FB)
+                (#xB0DD #x7DAD)
+                (#xB0DE #x7DEF)
+                (#xB0DF #x80C3)
+                (#xB0E0 #x840E)
+                (#xB0E1 #x8863)
+                (#xB0E2 #x8B02)
+                (#xB0E3 #x9055)
+                (#xB0E4 #x907A)
+                (#xB0E5 #x533B)
+                (#xB0E6 #x4E95)
+                (#xB0E7 #x4EA5)
+                (#xB0E8 #x57DF)
+                (#xB0E9 #x80B2)
+                (#xB0EA #x90C1)
+                (#xB0EB #x78EF)
+                (#xB0EC #x4E00)
+                (#xB0ED #x58F1)
+                (#xB0EE #x6EA2)
+                (#xB0EF #x9038)
+                (#xB0F0 #x7A32)
+                (#xB0F1 #x8328)
+                (#xB0F2 #x828B)
+                (#xB0F3 #x9C2F)
+                (#xB0F4 #x5141)
+                (#xB0F5 #x5370)
+                (#xB0F6 #x54BD)
+                (#xB0F7 #x54E1)
+                (#xB0F8 #x56E0)
+                (#xB0F9 #x59FB)
+                (#xB0FA #x5F15)
+                (#xB0FB #x98F2)
+                (#xB0FC #x6DEB)
+                (#xB0FD #x80E4)
+                (#xB0FE #x852D)
+                (#xB1A1 #x9662)
+                (#xB1A2 #x9670)
+                (#xB1A3 #x96A0)
+                (#xB1A4 #x97FB)
+                (#xB1A5 #x540B)
+                (#xB1A6 #x53F3)
+                (#xB1A7 #x5B87)
+                (#xB1A8 #x70CF)
+                (#xB1A9 #x7FBD)
+                (#xB1AA #x8FC2)
+                (#xB1AB #x96E8)
+                (#xB1AC #x536F)
+                (#xB1AD #x9D5C)
+                (#xB1AE #x7ABA)
+                (#xB1AF #x4E11)
+                (#xB1B0 #x7893)
+                (#xB1B1 #x81FC)
+                (#xB1B2 #x6E26)
+                (#xB1B3 #x5618)
+                (#xB1B4 #x5504)
+                (#xB1B5 #x6B1D)
+                (#xB1B6 #x851A)
+                (#xB1B7 #x9C3B)
+                (#xB1B8 #x59E5)
+                (#xB1B9 #x53A9)
+                (#xB1BA #x6D66)
+                (#xB1BB #x74DC)
+                (#xB1BC #x958F)
+                (#xB1BD #x5642)
+                (#xB1BE #x4E91)
+                (#xB1BF #x904B)
+                (#xB1C0 #x96F2)
+                (#xB1C1 #x834F)
+                (#xB1C2 #x990C)
+                (#xB1C3 #x53E1)
+                (#xB1C4 #x55B6)
+                (#xB1C5 #x5B30)
+                (#xB1C6 #x5F71)
+                (#xB1C7 #x6620)
+                (#xB1C8 #x66F3)
+                (#xB1C9 #x6804)
+                (#xB1CA #x6C38)
+                (#xB1CB #x6CF3)
+                (#xB1CC #x6D29)
+                (#xB1CD #x745B)
+                (#xB1CE #x76C8)
+                (#xB1CF #x7A4E)
+                (#xB1D0 #x9834)
+                (#xB1D1 #x82F1)
+                (#xB1D2 #x885B)
+                (#xB1D3 #x8A60)
+                (#xB1D4 #x92ED)
+                (#xB1D5 #x6DB2)
+                (#xB1D6 #x75AB)
+                (#xB1D7 #x76CA)
+                (#xB1D8 #x99C5)
+                (#xB1D9 #x60A6)
+                (#xB1DA #x8B01)
+                (#xB1DB #x8D8A)
+                (#xB1DC #x95B2)
+                (#xB1DD #x698E)
+                (#xB1DE #x53AD)
+                (#xB1DF #x5186)
+                (#xB1E0 #x5712)
+                (#xB1E1 #x5830)
+                (#xB1E2 #x5944)
+                (#xB1E3 #x5BB4)
+                (#xB1E4 #x5EF6)
+                (#xB1E5 #x6028)
+                (#xB1E6 #x63A9)
+                (#xB1E7 #x63F4)
+                (#xB1E8 #x6CBF)
+                (#xB1E9 #x6F14)
+                (#xB1EA #x708E)
+                (#xB1EB #x7114)
+                (#xB1EC #x7159)
+                (#xB1ED #x71D5)
+                (#xB1EE #x733F)
+                (#xB1EF #x7E01)
+                (#xB1F0 #x8276)
+                (#xB1F1 #x82D1)
+                (#xB1F2 #x8597)
+                (#xB1F3 #x9060)
+                (#xB1F4 #x925B)
+                (#xB1F5 #x9D1B)
+                (#xB1F6 #x5869)
+                (#xB1F7 #x65BC)
+                (#xB1F8 #x6C5A)
+                (#xB1F9 #x7525)
+                (#xB1FA #x51F9)
+                (#xB1FB #x592E)
+                (#xB1FC #x5965)
+                (#xB1FD #x5F80)
+                (#xB1FE #x5FDC)
+                (#xB2A1 #x62BC)
+                (#xB2A2 #x65FA)
+                (#xB2A3 #x6A2A)
+                (#xB2A4 #x6B27)
+                (#xB2A5 #x6BB4)
+                (#xB2A6 #x738B)
+                (#xB2A7 #x7FC1)
+                (#xB2A8 #x8956)
+                (#xB2A9 #x9D2C)
+                (#xB2AA #x9D0E)
+                (#xB2AB #x9EC4)
+                (#xB2AC #x5CA1)
+                (#xB2AD #x6C96)
+                (#xB2AE #x837B)
+                (#xB2AF #x5104)
+                (#xB2B0 #x5C4B)
+                (#xB2B1 #x61B6)
+                (#xB2B2 #x81C6)
+                (#xB2B3 #x6876)
+                (#xB2B4 #x7261)
+                (#xB2B5 #x4E59)
+                (#xB2B6 #x4FFA)
+                (#xB2B7 #x5378)
+                (#xB2B8 #x6069)
+                (#xB2B9 #x6E29)
+                (#xB2BA #x7A4F)
+                (#xB2BB #x97F3)
+                (#xB2BC #x4E0B)
+                (#xB2BD #x5316)
+                (#xB2BE #x4EEE)
+                (#xB2BF #x4F55)
+                (#xB2C0 #x4F3D)
+                (#xB2C1 #x4FA1)
+                (#xB2C2 #x4F73)
+                (#xB2C3 #x52A0)
+                (#xB2C4 #x53EF)
+                (#xB2C5 #x5609)
+                (#xB2C6 #x590F)
+                (#xB2C7 #x5AC1)
+                (#xB2C8 #x5BB6)
+                (#xB2C9 #x5BE1)
+                (#xB2CA #x79D1)
+                (#xB2CB #x6687)
+                (#xB2CC #x679C)
+                (#xB2CD #x67B6)
+                (#xB2CE #x6B4C)
+                (#xB2CF #x6CB3)
+                (#xB2D0 #x706B)
+                (#xB2D1 #x73C2)
+                (#xB2D2 #x798D)
+                (#xB2D3 #x79BE)
+                (#xB2D4 #x7A3C)
+                (#xB2D5 #x7B87)
+                (#xB2D6 #x82B1)
+                (#xB2D7 #x82DB)
+                (#xB2D8 #x8304)
+                (#xB2D9 #x8377)
+                (#xB2DA #x83EF)
+                (#xB2DB #x83D3)
+                (#xB2DC #x8766)
+                (#xB2DD #x8AB2)
+                (#xB2DE #x5629)
+                (#xB2DF #x8CA8)
+                (#xB2E0 #x8FE6)
+                (#xB2E1 #x904E)
+                (#xB2E2 #x971E)
+                (#xB2E3 #x868A)
+                (#xB2E4 #x4FC4)
+                (#xB2E5 #x5CE8)
+                (#xB2E6 #x6211)
+                (#xB2E7 #x7259)
+                (#xB2E8 #x753B)
+                (#xB2E9 #x81E5)
+                (#xB2EA #x82BD)
+                (#xB2EB #x86FE)
+                (#xB2EC #x8CC0)
+                (#xB2ED #x96C5)
+                (#xB2EE #x9913)
+                (#xB2EF #x99D5)
+                (#xB2F0 #x4ECB)
+                (#xB2F1 #x4F1A)
+                (#xB2F2 #x89E3)
+                (#xB2F3 #x56DE)
+                (#xB2F4 #x584A)
+                (#xB2F5 #x58CA)
+                (#xB2F6 #x5EFB)
+                (#xB2F7 #x5FEB)
+                (#xB2F8 #x602A)
+                (#xB2F9 #x6094)
+                (#xB2FA #x6062)
+                (#xB2FB #x61D0)
+                (#xB2FC #x6212)
+                (#xB2FD #x62D0)
+                (#xB2FE #x6539)
+                (#xB3A1 #x9B41)
+                (#xB3A2 #x6666)
+                (#xB3A3 #x68B0)
+                (#xB3A4 #x6D77)
+                (#xB3A5 #x7070)
+                (#xB3A6 #x754C)
+                (#xB3A7 #x7686)
+                (#xB3A8 #x7D75)
+                (#xB3A9 #x82A5)
+                (#xB3AA #x87F9)
+                (#xB3AB #x958B)
+                (#xB3AC #x968E)
+                (#xB3AD #x8C9D)
+                (#xB3AE #x51F1)
+                (#xB3AF #x52BE)
+                (#xB3B0 #x5916)
+                (#xB3B1 #x54B3)
+                (#xB3B2 #x5BB3)
+                (#xB3B3 #x5D16)
+                (#xB3B4 #x6168)
+                (#xB3B5 #x6982)
+                (#xB3B6 #x6DAF)
+                (#xB3B7 #x788D)
+                (#xB3B8 #x84CB)
+                (#xB3B9 #x8857)
+                (#xB3BA #x8A72)
+                (#xB3BB #x93A7)
+                (#xB3BC #x9AB8)
+                (#xB3BD #x6D6C)
+                (#xB3BE #x99A8)
+                (#xB3BF #x86D9)
+                (#xB3C0 #x57A3)
+                (#xB3C1 #x67FF)
+                (#xB3C2 #x86CE)
+                (#xB3C3 #x920E)
+                (#xB3C4 #x5283)
+                (#xB3C5 #x5687)
+                (#xB3C6 #x5404)
+                (#xB3C7 #x5ED3)
+                (#xB3C8 #x62E1)
+                (#xB3C9 #x64B9)
+                (#xB3CA #x683C)
+                (#xB3CB #x6838)
+                (#xB3CC #x6BBB)
+                (#xB3CD #x7372)
+                (#xB3CE #x78BA)
+                (#xB3CF #x7A6B)
+                (#xB3D0 #x899A)
+                (#xB3D1 #x89D2)
+                (#xB3D2 #x8D6B)
+                (#xB3D3 #x8F03)
+                (#xB3D4 #x90ED)
+                (#xB3D5 #x95A3)
+                (#xB3D6 #x9694)
+                (#xB3D7 #x9769)
+                (#xB3D8 #x5B66)
+                (#xB3D9 #x5CB3)
+                (#xB3DA #x697D)
+                (#xB3DB #x984D)
+                (#xB3DC #x984E)
+                (#xB3DD #x639B)
+                (#xB3DE #x7B20)
+                (#xB3DF #x6A2B)
+                (#xB3E0 #x6A7F)
+                (#xB3E1 #x68B6)
+                (#xB3E2 #x9C0D)
+                (#xB3E3 #x6F5F)
+                (#xB3E4 #x5272)
+                (#xB3E5 #x559D)
+                (#xB3E6 #x6070)
+                (#xB3E7 #x62EC)
+                (#xB3E8 #x6D3B)
+                (#xB3E9 #x6E07)
+                (#xB3EA #x6ED1)
+                (#xB3EB #x845B)
+                (#xB3EC #x8910)
+                (#xB3ED #x8F44)
+                (#xB3EE #x4E14)
+                (#xB3EF #x9C39)
+                (#xB3F0 #x53F6)
+                (#xB3F1 #x691B)
+                (#xB3F2 #x6A3A)
+                (#xB3F3 #x9784)
+                (#xB3F4 #x682A)
+                (#xB3F5 #x515C)
+                (#xB3F6 #x7AC3)
+                (#xB3F7 #x84B2)
+                (#xB3F8 #x91DC)
+                (#xB3F9 #x938C)
+                (#xB3FA #x565B)
+                (#xB3FB #x9D28)
+                (#xB3FC #x6822)
+                (#xB3FD #x8305)
+                (#xB3FE #x8431)
+                (#xB4A1 #x7CA5)
+                (#xB4A2 #x5208)
+                (#xB4A3 #x82C5)
+                (#xB4A4 #x74E6)
+                (#xB4A5 #x4E7E)
+                (#xB4A6 #x4F83)
+                (#xB4A7 #x51A0)
+                (#xB4A8 #x5BD2)
+                (#xB4A9 #x520A)
+                (#xB4AA #x52D8)
+                (#xB4AB #x52E7)
+                (#xB4AC #x5DFB)
+                (#xB4AD #x559A)
+                (#xB4AE #x582A)
+                (#xB4AF #x59E6)
+                (#xB4B0 #x5B8C)
+                (#xB4B1 #x5B98)
+                (#xB4B2 #x5BDB)
+                (#xB4B3 #x5E72)
+                (#xB4B4 #x5E79)
+                (#xB4B5 #x60A3)
+                (#xB4B6 #x611F)
+                (#xB4B7 #x6163)
+                (#xB4B8 #x61BE)
+                (#xB4B9 #x63DB)
+                (#xB4BA #x6562)
+                (#xB4BB #x67D1)
+                (#xB4BC #x6853)
+                (#xB4BD #x68FA)
+                (#xB4BE #x6B3E)
+                (#xB4BF #x6B53)
+                (#xB4C0 #x6C57)
+                (#xB4C1 #x6F22)
+                (#xB4C2 #x6F97)
+                (#xB4C3 #x6F45)
+                (#xB4C4 #x74B0)
+                (#xB4C5 #x7518)
+                (#xB4C6 #x76E3)
+                (#xB4C7 #x770B)
+                (#xB4C8 #x7AFF)
+                (#xB4C9 #x7BA1)
+                (#xB4CA #x7C21)
+                (#xB4CB #x7DE9)
+                (#xB4CC #x7F36)
+                (#xB4CD #x7FF0)
+                (#xB4CE #x809D)
+                (#xB4CF #x8266)
+                (#xB4D0 #x839E)
+                (#xB4D1 #x89B3)
+                (#xB4D2 #x8ACC)
+                (#xB4D3 #x8CAB)
+                (#xB4D4 #x9084)
+                (#xB4D5 #x9451)
+                (#xB4D6 #x9593)
+                (#xB4D7 #x9591)
+                (#xB4D8 #x95A2)
+                (#xB4D9 #x9665)
+                (#xB4DA #x97D3)
+                (#xB4DB #x9928)
+                (#xB4DC #x8218)
+                (#xB4DD #x4E38)
+                (#xB4DE #x542B)
+                (#xB4DF #x5CB8)
+                (#xB4E0 #x5DCC)
+                (#xB4E1 #x73A9)
+                (#xB4E2 #x764C)
+                (#xB4E3 #x773C)
+                (#xB4E4 #x5CA9)
+                (#xB4E5 #x7FEB)
+                (#xB4E6 #x8D0B)
+                (#xB4E7 #x96C1)
+                (#xB4E8 #x9811)
+                (#xB4E9 #x9854)
+                (#xB4EA #x9858)
+                (#xB4EB #x4F01)
+                (#xB4EC #x4F0E)
+                (#xB4ED #x5371)
+                (#xB4EE #x559C)
+                (#xB4EF #x5668)
+                (#xB4F0 #x57FA)
+                (#xB4F1 #x5947)
+                (#xB4F2 #x5B09)
+                (#xB4F3 #x5BC4)
+                (#xB4F4 #x5C90)
+                (#xB4F5 #x5E0C)
+                (#xB4F6 #x5E7E)
+                (#xB4F7 #x5FCC)
+                (#xB4F8 #x63EE)
+                (#xB4F9 #x673A)
+                (#xB4FA #x65D7)
+                (#xB4FB #x65E2)
+                (#xB4FC #x671F)
+                (#xB4FD #x68CB)
+                (#xB4FE #x68C4)
+                (#xB5A1 #x6A5F)
+                (#xB5A2 #x5E30)
+                (#xB5A3 #x6BC5)
+                (#xB5A4 #x6C17)
+                (#xB5A5 #x6C7D)
+                (#xB5A6 #x757F)
+                (#xB5A7 #x7948)
+                (#xB5A8 #x5B63)
+                (#xB5A9 #x7A00)
+                (#xB5AA #x7D00)
+                (#xB5AB #x5FBD)
+                (#xB5AC #x898F)
+                (#xB5AD #x8A18)
+                (#xB5AE #x8CB4)
+                (#xB5AF #x8D77)
+                (#xB5B0 #x8ECC)
+                (#xB5B1 #x8F1D)
+                (#xB5B2 #x98E2)
+                (#xB5B3 #x9A0E)
+                (#xB5B4 #x9B3C)
+                (#xB5B5 #x4E80)
+                (#xB5B6 #x507D)
+                (#xB5B7 #x5100)
+                (#xB5B8 #x5993)
+                (#xB5B9 #x5B9C)
+                (#xB5BA #x622F)
+                (#xB5BB #x6280)
+                (#xB5BC #x64EC)
+                (#xB5BD #x6B3A)
+                (#xB5BE #x72A0)
+                (#xB5BF #x7591)
+                (#xB5C0 #x7947)
+                (#xB5C1 #x7FA9)
+                (#xB5C2 #x87FB)
+                (#xB5C3 #x8ABC)
+                (#xB5C4 #x8B70)
+                (#xB5C5 #x63AC)
+                (#xB5C6 #x83CA)
+                (#xB5C7 #x97A0)
+                (#xB5C8 #x5409)
+                (#xB5C9 #x5403)
+                (#xB5CA #x55AB)
+                (#xB5CB #x6854)
+                (#xB5CC #x6A58)
+                (#xB5CD #x8A70)
+                (#xB5CE #x7827)
+                (#xB5CF #x6775)
+                (#xB5D0 #x9ECD)
+                (#xB5D1 #x5374)
+                (#xB5D2 #x5BA2)
+                (#xB5D3 #x811A)
+                (#xB5D4 #x8650)
+                (#xB5D5 #x9006)
+                (#xB5D6 #x4E18)
+                (#xB5D7 #x4E45)
+                (#xB5D8 #x4EC7)
+                (#xB5D9 #x4F11)
+                (#xB5DA #x53CA)
+                (#xB5DB #x5438)
+                (#xB5DC #x5BAE)
+                (#xB5DD #x5F13)
+                (#xB5DE #x6025)
+                (#xB5DF #x6551)
+                (#xB5E0 #x673D)
+                (#xB5E1 #x6C42)
+                (#xB5E2 #x6C72)
+                (#xB5E3 #x6CE3)
+                (#xB5E4 #x7078)
+                (#xB5E5 #x7403)
+                (#xB5E6 #x7A76)
+                (#xB5E7 #x7AAE)
+                (#xB5E8 #x7B08)
+                (#xB5E9 #x7D1A)
+                (#xB5EA #x7CFE)
+                (#xB5EB #x7D66)
+                (#xB5EC #x65E7)
+                (#xB5ED #x725B)
+                (#xB5EE #x53BB)
+                (#xB5EF #x5C45)
+                (#xB5F0 #x5DE8)
+                (#xB5F1 #x62D2)
+                (#xB5F2 #x62E0)
+                (#xB5F3 #x6319)
+                (#xB5F4 #x6E20)
+                (#xB5F5 #x865A)
+                (#xB5F6 #x8A31)
+                (#xB5F7 #x8DDD)
+                (#xB5F8 #x92F8)
+                (#xB5F9 #x6F01)
+                (#xB5FA #x79A6)
+                (#xB5FB #x9B5A)
+                (#xB5FC #x4EA8)
+                (#xB5FD #x4EAB)
+                (#xB5FE #x4EAC)
+                (#xB6A1 #x4F9B)
+                (#xB6A2 #x4FA0)
+                (#xB6A3 #x50D1)
+                (#xB6A4 #x5147)
+                (#xB6A5 #x7AF6)
+                (#xB6A6 #x5171)
+                (#xB6A7 #x51F6)
+                (#xB6A8 #x5354)
+                (#xB6A9 #x5321)
+                (#xB6AA #x537F)
+                (#xB6AB #x53EB)
+                (#xB6AC #x55AC)
+                (#xB6AD #x5883)
+                (#xB6AE #x5CE1)
+                (#xB6AF #x5F37)
+                (#xB6B0 #x5F4A)
+                (#xB6B1 #x602F)
+                (#xB6B2 #x6050)
+                (#xB6B3 #x606D)
+                (#xB6B4 #x631F)
+                (#xB6B5 #x6559)
+                (#xB6B6 #x6A4B)
+                (#xB6B7 #x6CC1)
+                (#xB6B8 #x72C2)
+                (#xB6B9 #x72ED)
+                (#xB6BA #x77EF)
+                (#xB6BB #x80F8)
+                (#xB6BC #x8105)
+                (#xB6BD #x8208)
+                (#xB6BE #x854E)
+                (#xB6BF #x90F7)
+                (#xB6C0 #x93E1)
+                (#xB6C1 #x97FF)
+                (#xB6C2 #x9957)
+                (#xB6C3 #x9A5A)
+                (#xB6C4 #x4EF0)
+                (#xB6C5 #x51DD)
+                (#xB6C6 #x5C2D)
+                (#xB6C7 #x6681)
+                (#xB6C8 #x696D)
+                (#xB6C9 #x5C40)
+                (#xB6CA #x66F2)
+                (#xB6CB #x6975)
+                (#xB6CC #x7389)
+                (#xB6CD #x6850)
+                (#xB6CE #x7C81)
+                (#xB6CF #x50C5)
+                (#xB6D0 #x52E4)
+                (#xB6D1 #x5747)
+                (#xB6D2 #x5DFE)
+                (#xB6D3 #x9326)
+                (#xB6D4 #x65A4)
+                (#xB6D5 #x6B23)
+                (#xB6D6 #x6B3D)
+                (#xB6D7 #x7434)
+                (#xB6D8 #x7981)
+                (#xB6D9 #x79BD)
+                (#xB6DA #x7B4B)
+                (#xB6DB #x7DCA)
+                (#xB6DC #x82B9)
+                (#xB6DD #x83CC)
+                (#xB6DE #x887F)
+                (#xB6DF #x895F)
+                (#xB6E0 #x8B39)
+                (#xB6E1 #x8FD1)
+                (#xB6E2 #x91D1)
+                (#xB6E3 #x541F)
+                (#xB6E4 #x9280)
+                (#xB6E5 #x4E5D)
+                (#xB6E6 #x5036)
+                (#xB6E7 #x53E5)
+                (#xB6E8 #x533A)
+                (#xB6E9 #x72D7)
+                (#xB6EA #x7396)
+                (#xB6EB #x77E9)
+                (#xB6EC #x82E6)
+                (#xB6ED #x8EAF)
+                (#xB6EE #x99C6)
+                (#xB6EF #x99C8)
+                (#xB6F0 #x99D2)
+                (#xB6F1 #x5177)
+                (#xB6F2 #x611A)
+                (#xB6F3 #x865E)
+                (#xB6F4 #x55B0)
+                (#xB6F5 #x7A7A)
+                (#xB6F6 #x5076)
+                (#xB6F7 #x5BD3)
+                (#xB6F8 #x9047)
+                (#xB6F9 #x9685)
+                (#xB6FA #x4E32)
+                (#xB6FB #x6ADB)
+                (#xB6FC #x91E7)
+                (#xB6FD #x5C51)
+                (#xB6FE #x5C48)
+                (#xB7A1 #x6398)
+                (#xB7A2 #x7A9F)
+                (#xB7A3 #x6C93)
+                (#xB7A4 #x9774)
+                (#xB7A5 #x8F61)
+                (#xB7A6 #x7AAA)
+                (#xB7A7 #x718A)
+                (#xB7A8 #x9688)
+                (#xB7A9 #x7C82)
+                (#xB7AA #x6817)
+                (#xB7AB #x7E70)
+                (#xB7AC #x6851)
+                (#xB7AD #x936C)
+                (#xB7AE #x52F2)
+                (#xB7AF #x541B)
+                (#xB7B0 #x85AB)
+                (#xB7B1 #x8A13)
+                (#xB7B2 #x7FA4)
+                (#xB7B3 #x8ECD)
+                (#xB7B4 #x90E1)
+                (#xB7B5 #x5366)
+                (#xB7B6 #x8888)
+                (#xB7B7 #x7941)
+                (#xB7B8 #x4FC2)
+                (#xB7B9 #x50BE)
+                (#xB7BA #x5211)
+                (#xB7BB #x5144)
+                (#xB7BC #x5553)
+                (#xB7BD #x572D)
+                (#xB7BE #x73EA)
+                (#xB7BF #x578B)
+                (#xB7C0 #x5951)
+                (#xB7C1 #x5F62)
+                (#xB7C2 #x5F84)
+                (#xB7C3 #x6075)
+                (#xB7C4 #x6176)
+                (#xB7C5 #x6167)
+                (#xB7C6 #x61A9)
+                (#xB7C7 #x63B2)
+                (#xB7C8 #x643A)
+                (#xB7C9 #x656C)
+                (#xB7CA #x666F)
+                (#xB7CB #x6842)
+                (#xB7CC #x6E13)
+                (#xB7CD #x7566)
+                (#xB7CE #x7A3D)
+                (#xB7CF #x7CFB)
+                (#xB7D0 #x7D4C)
+                (#xB7D1 #x7D99)
+                (#xB7D2 #x7E4B)
+                (#xB7D3 #x7F6B)
+                (#xB7D4 #x830E)
+                (#xB7D5 #x834A)
+                (#xB7D6 #x86CD)
+                (#xB7D7 #x8A08)
+                (#xB7D8 #x8A63)
+                (#xB7D9 #x8B66)
+                (#xB7DA #x8EFD)
+                (#xB7DB #x981A)
+                (#xB7DC #x9D8F)
+                (#xB7DD #x82B8)
+                (#xB7DE #x8FCE)
+                (#xB7DF #x9BE8)
+                (#xB7E0 #x5287)
+                (#xB7E1 #x621F)
+                (#xB7E2 #x6483)
+                (#xB7E3 #x6FC0)
+                (#xB7E4 #x9699)
+                (#xB7E5 #x6841)
+                (#xB7E6 #x5091)
+                (#xB7E7 #x6B20)
+                (#xB7E8 #x6C7A)
+                (#xB7E9 #x6F54)
+                (#xB7EA #x7A74)
+                (#xB7EB #x7D50)
+                (#xB7EC #x8840)
+                (#xB7ED #x8A23)
+                (#xB7EE #x6708)
+                (#xB7EF #x4EF6)
+                (#xB7F0 #x5039)
+                (#xB7F1 #x5026)
+                (#xB7F2 #x5065)
+                (#xB7F3 #x517C)
+                (#xB7F4 #x5238)
+                (#xB7F5 #x5263)
+                (#xB7F6 #x55A7)
+                (#xB7F7 #x570F)
+                (#xB7F8 #x5805)
+                (#xB7F9 #x5ACC)
+                (#xB7FA #x5EFA)
+                (#xB7FB #x61B2)
+                (#xB7FC #x61F8)
+                (#xB7FD #x62F3)
+                (#xB7FE #x6372)
+                (#xB8A1 #x691C)
+                (#xB8A2 #x6A29)
+                (#xB8A3 #x727D)
+                (#xB8A4 #x72AC)
+                (#xB8A5 #x732E)
+                (#xB8A6 #x7814)
+                (#xB8A7 #x786F)
+                (#xB8A8 #x7D79)
+                (#xB8A9 #x770C)
+                (#xB8AA #x80A9)
+                (#xB8AB #x898B)
+                (#xB8AC #x8B19)
+                (#xB8AD #x8CE2)
+                (#xB8AE #x8ED2)
+                (#xB8AF #x9063)
+                (#xB8B0 #x9375)
+                (#xB8B1 #x967A)
+                (#xB8B2 #x9855)
+                (#xB8B3 #x9A13)
+                (#xB8B4 #x9E78)
+                (#xB8B5 #x5143)
+                (#xB8B6 #x539F)
+                (#xB8B7 #x53B3)
+                (#xB8B8 #x5E7B)
+                (#xB8B9 #x5F26)
+                (#xB8BA #x6E1B)
+                (#xB8BB #x6E90)
+                (#xB8BC #x7384)
+                (#xB8BD #x73FE)
+                (#xB8BE #x7D43)
+                (#xB8BF #x8237)
+                (#xB8C0 #x8A00)
+                (#xB8C1 #x8AFA)
+                (#xB8C2 #x9650)
+                (#xB8C3 #x4E4E)
+                (#xB8C4 #x500B)
+                (#xB8C5 #x53E4)
+                (#xB8C6 #x547C)
+                (#xB8C7 #x56FA)
+                (#xB8C8 #x59D1)
+                (#xB8C9 #x5B64)
+                (#xB8CA #x5DF1)
+                (#xB8CB #x5EAB)
+                (#xB8CC #x5F27)
+                (#xB8CD #x6238)
+                (#xB8CE #x6545)
+                (#xB8CF #x67AF)
+                (#xB8D0 #x6E56)
+                (#xB8D1 #x72D0)
+                (#xB8D2 #x7CCA)
+                (#xB8D3 #x88B4)
+                (#xB8D4 #x80A1)
+                (#xB8D5 #x80E1)
+                (#xB8D6 #x83F0)
+                (#xB8D7 #x864E)
+                (#xB8D8 #x8A87)
+                (#xB8D9 #x8DE8)
+                (#xB8DA #x9237)
+                (#xB8DB #x96C7)
+                (#xB8DC #x9867)
+                (#xB8DD #x9F13)
+                (#xB8DE #x4E94)
+                (#xB8DF #x4E92)
+                (#xB8E0 #x4F0D)
+                (#xB8E1 #x5348)
+                (#xB8E2 #x5449)
+                (#xB8E3 #x543E)
+                (#xB8E4 #x5A2F)
+                (#xB8E5 #x5F8C)
+                (#xB8E6 #x5FA1)
+                (#xB8E7 #x609F)
+                (#xB8E8 #x68A7)
+                (#xB8E9 #x6A8E)
+                (#xB8EA #x745A)
+                (#xB8EB #x7881)
+                (#xB8EC #x8A9E)
+                (#xB8ED #x8AA4)
+                (#xB8EE #x8B77)
+                (#xB8EF #x9190)
+                (#xB8F0 #x4E5E)
+                (#xB8F1 #x9BC9)
+                (#xB8F2 #x4EA4)
+                (#xB8F3 #x4F7C)
+                (#xB8F4 #x4FAF)
+                (#xB8F5 #x5019)
+                (#xB8F6 #x5016)
+                (#xB8F7 #x5149)
+                (#xB8F8 #x516C)
+                (#xB8F9 #x529F)
+                (#xB8FA #x52B9)
+                (#xB8FB #x52FE)
+                (#xB8FC #x539A)
+                (#xB8FD #x53E3)
+                (#xB8FE #x5411)
+                (#xB9A1 #x540E)
+                (#xB9A2 #x5589)
+                (#xB9A3 #x5751)
+                (#xB9A4 #x57A2)
+                (#xB9A5 #x597D)
+                (#xB9A6 #x5B54)
+                (#xB9A7 #x5B5D)
+                (#xB9A8 #x5B8F)
+                (#xB9A9 #x5DE5)
+                (#xB9AA #x5DE7)
+                (#xB9AB #x5DF7)
+                (#xB9AC #x5E78)
+                (#xB9AD #x5E83)
+                (#xB9AE #x5E9A)
+                (#xB9AF #x5EB7)
+                (#xB9B0 #x5F18)
+                (#xB9B1 #x6052)
+                (#xB9B2 #x614C)
+                (#xB9B3 #x6297)
+                (#xB9B4 #x62D8)
+                (#xB9B5 #x63A7)
+                (#xB9B6 #x653B)
+                (#xB9B7 #x6602)
+                (#xB9B8 #x6643)
+                (#xB9B9 #x66F4)
+                (#xB9BA #x676D)
+                (#xB9BB #x6821)
+                (#xB9BC #x6897)
+                (#xB9BD #x69CB)
+                (#xB9BE #x6C5F)
+                (#xB9BF #x6D2A)
+                (#xB9C0 #x6D69)
+                (#xB9C1 #x6E2F)
+                (#xB9C2 #x6E9D)
+                (#xB9C3 #x7532)
+                (#xB9C4 #x7687)
+                (#xB9C5 #x786C)
+                (#xB9C6 #x7A3F)
+                (#xB9C7 #x7CE0)
+                (#xB9C8 #x7D05)
+                (#xB9C9 #x7D18)
+                (#xB9CA #x7D5E)
+                (#xB9CB #x7DB1)
+                (#xB9CC #x8015)
+                (#xB9CD #x8003)
+                (#xB9CE #x80AF)
+                (#xB9CF #x80B1)
+                (#xB9D0 #x8154)
+                (#xB9D1 #x818F)
+                (#xB9D2 #x822A)
+                (#xB9D3 #x8352)
+                (#xB9D4 #x884C)
+                (#xB9D5 #x8861)
+                (#xB9D6 #x8B1B)
+                (#xB9D7 #x8CA2)
+                (#xB9D8 #x8CFC)
+                (#xB9D9 #x90CA)
+                (#xB9DA #x9175)
+                (#xB9DB #x9271)
+                (#xB9DC #x783F)
+                (#xB9DD #x92FC)
+                (#xB9DE #x95A4)
+                (#xB9DF #x964D)
+                (#xB9E0 #x9805)
+                (#xB9E1 #x9999)
+                (#xB9E2 #x9AD8)
+                (#xB9E3 #x9D3B)
+                (#xB9E4 #x525B)
+                (#xB9E5 #x52AB)
+                (#xB9E6 #x53F7)
+                (#xB9E7 #x5408)
+                (#xB9E8 #x58D5)
+                (#xB9E9 #x62F7)
+                (#xB9EA #x6FE0)
+                (#xB9EB #x8C6A)
+                (#xB9EC #x8F5F)
+                (#xB9ED #x9EB9)
+                (#xB9EE #x514B)
+                (#xB9EF #x523B)
+                (#xB9F0 #x544A)
+                (#xB9F1 #x56FD)
+                (#xB9F2 #x7A40)
+                (#xB9F3 #x9177)
+                (#xB9F4 #x9D60)
+                (#xB9F5 #x9ED2)
+                (#xB9F6 #x7344)
+                (#xB9F7 #x6F09)
+                (#xB9F8 #x8170)
+                (#xB9F9 #x7511)
+                (#xB9FA #x5FFD)
+                (#xB9FB #x60DA)
+                (#xB9FC #x9AA8)
+                (#xB9FD #x72DB)
+                (#xB9FE #x8FBC)
+                (#xBAA1 #x6B64)
+                (#xBAA2 #x9803)
+                (#xBAA3 #x4ECA)
+                (#xBAA4 #x56F0)
+                (#xBAA5 #x5764)
+                (#xBAA6 #x58BE)
+                (#xBAA7 #x5A5A)
+                (#xBAA8 #x6068)
+                (#xBAA9 #x61C7)
+                (#xBAAA #x660F)
+                (#xBAAB #x6606)
+                (#xBAAC #x6839)
+                (#xBAAD #x68B1)
+                (#xBAAE #x6DF7)
+                (#xBAAF #x75D5)
+                (#xBAB0 #x7D3A)
+                (#xBAB1 #x826E)
+                (#xBAB2 #x9B42)
+                (#xBAB3 #x4E9B)
+                (#xBAB4 #x4F50)
+                (#xBAB5 #x53C9)
+                (#xBAB6 #x5506)
+                (#xBAB7 #x5D6F)
+                (#xBAB8 #x5DE6)
+                (#xBAB9 #x5DEE)
+                (#xBABA #x67FB)
+                (#xBABB #x6C99)
+                (#xBABC #x7473)
+                (#xBABD #x7802)
+                (#xBABE #x8A50)
+                (#xBABF #x9396)
+                (#xBAC0 #x88DF)
+                (#xBAC1 #x5750)
+                (#xBAC2 #x5EA7)
+                (#xBAC3 #x632B)
+                (#xBAC4 #x50B5)
+                (#xBAC5 #x50AC)
+                (#xBAC6 #x518D)
+                (#xBAC7 #x6700)
+                (#xBAC8 #x54C9)
+                (#xBAC9 #x585E)
+                (#xBACA #x59BB)
+                (#xBACB #x5BB0)
+                (#xBACC #x5F69)
+                (#xBACD #x624D)
+                (#xBACE #x63A1)
+                (#xBACF #x683D)
+                (#xBAD0 #x6B73)
+                (#xBAD1 #x6E08)
+                (#xBAD2 #x707D)
+                (#xBAD3 #x91C7)
+                (#xBAD4 #x7280)
+                (#xBAD5 #x7815)
+                (#xBAD6 #x7826)
+                (#xBAD7 #x796D)
+                (#xBAD8 #x658E)
+                (#xBAD9 #x7D30)
+                (#xBADA #x83DC)
+                (#xBADB #x88C1)
+                (#xBADC #x8F09)
+                (#xBADD #x969B)
+                (#xBADE #x5264)
+                (#xBADF #x5728)
+                (#xBAE0 #x6750)
+                (#xBAE1 #x7F6A)
+                (#xBAE2 #x8CA1)
+                (#xBAE3 #x51B4)
+                (#xBAE4 #x5742)
+                (#xBAE5 #x962A)
+                (#xBAE6 #x583A)
+                (#xBAE7 #x698A)
+                (#xBAE8 #x80B4)
+                (#xBAE9 #x54B2)
+                (#xBAEA #x5D0E)
+                (#xBAEB #x57FC)
+                (#xBAEC #x7895)
+                (#xBAED #x9DFA)
+                (#xBAEE #x4F5C)
+                (#xBAEF #x524A)
+                (#xBAF0 #x548B)
+                (#xBAF1 #x643E)
+                (#xBAF2 #x6628)
+                (#xBAF3 #x6714)
+                (#xBAF4 #x67F5)
+                (#xBAF5 #x7A84)
+                (#xBAF6 #x7B56)
+                (#xBAF7 #x7D22)
+                (#xBAF8 #x932F)
+                (#xBAF9 #x685C)
+                (#xBAFA #x9BAD)
+                (#xBAFB #x7B39)
+                (#xBAFC #x5319)
+                (#xBAFD #x518A)
+                (#xBAFE #x5237)
+                (#xBBA1 #x5BDF)
+                (#xBBA2 #x62F6)
+                (#xBBA3 #x64AE)
+                (#xBBA4 #x64E6)
+                (#xBBA5 #x672D)
+                (#xBBA6 #x6BBA)
+                (#xBBA7 #x85A9)
+                (#xBBA8 #x96D1)
+                (#xBBA9 #x7690)
+                (#xBBAA #x9BD6)
+                (#xBBAB #x634C)
+                (#xBBAC #x9306)
+                (#xBBAD #x9BAB)
+                (#xBBAE #x76BF)
+                (#xBBAF #x6652)
+                (#xBBB0 #x4E09)
+                (#xBBB1 #x5098)
+                (#xBBB2 #x53C2)
+                (#xBBB3 #x5C71)
+                (#xBBB4 #x60E8)
+                (#xBBB5 #x6492)
+                (#xBBB6 #x6563)
+                (#xBBB7 #x685F)
+                (#xBBB8 #x71E6)
+                (#xBBB9 #x73CA)
+                (#xBBBA #x7523)
+                (#xBBBB #x7B97)
+                (#xBBBC #x7E82)
+                (#xBBBD #x8695)
+                (#xBBBE #x8B83)
+                (#xBBBF #x8CDB)
+                (#xBBC0 #x9178)
+                (#xBBC1 #x9910)
+                (#xBBC2 #x65AC)
+                (#xBBC3 #x66AB)
+                (#xBBC4 #x6B8B)
+                (#xBBC5 #x4ED5)
+                (#xBBC6 #x4ED4)
+                (#xBBC7 #x4F3A)
+                (#xBBC8 #x4F7F)
+                (#xBBC9 #x523A)
+                (#xBBCA #x53F8)
+                (#xBBCB #x53F2)
+                (#xBBCC #x55E3)
+                (#xBBCD #x56DB)
+                (#xBBCE #x58EB)
+                (#xBBCF #x59CB)
+                (#xBBD0 #x59C9)
+                (#xBBD1 #x59FF)
+                (#xBBD2 #x5B50)
+                (#xBBD3 #x5C4D)
+                (#xBBD4 #x5E02)
+                (#xBBD5 #x5E2B)
+                (#xBBD6 #x5FD7)
+                (#xBBD7 #x601D)
+                (#xBBD8 #x6307)
+                (#xBBD9 #x652F)
+                (#xBBDA #x5B5C)
+                (#xBBDB #x65AF)
+                (#xBBDC #x65BD)
+                (#xBBDD #x65E8)
+                (#xBBDE #x679D)
+                (#xBBDF #x6B62)
+                (#xBBE0 #x6B7B)
+                (#xBBE1 #x6C0F)
+                (#xBBE2 #x7345)
+                (#xBBE3 #x7949)
+                (#xBBE4 #x79C1)
+                (#xBBE5 #x7CF8)
+                (#xBBE6 #x7D19)
+                (#xBBE7 #x7D2B)
+                (#xBBE8 #x80A2)
+                (#xBBE9 #x8102)
+                (#xBBEA #x81F3)
+                (#xBBEB #x8996)
+                (#xBBEC #x8A5E)
+                (#xBBED #x8A69)
+                (#xBBEE #x8A66)
+                (#xBBEF #x8A8C)
+                (#xBBF0 #x8AEE)
+                (#xBBF1 #x8CC7)
+                (#xBBF2 #x8CDC)
+                (#xBBF3 #x96CC)
+                (#xBBF4 #x98FC)
+                (#xBBF5 #x6B6F)
+                (#xBBF6 #x4E8B)
+                (#xBBF7 #x4F3C)
+                (#xBBF8 #x4F8D)
+                (#xBBF9 #x5150)
+                (#xBBFA #x5B57)
+                (#xBBFB #x5BFA)
+                (#xBBFC #x6148)
+                (#xBBFD #x6301)
+                (#xBBFE #x6642)
+                (#xBCA1 #x6B21)
+                (#xBCA2 #x6ECB)
+                (#xBCA3 #x6CBB)
+                (#xBCA4 #x723E)
+                (#xBCA5 #x74BD)
+                (#xBCA6 #x75D4)
+                (#xBCA7 #x78C1)
+                (#xBCA8 #x793A)
+                (#xBCA9 #x800C)
+                (#xBCAA #x8033)
+                (#xBCAB #x81EA)
+                (#xBCAC #x8494)
+                (#xBCAD #x8F9E)
+                (#xBCAE #x6C50)
+                (#xBCAF #x9E7F)
+                (#xBCB0 #x5F0F)
+                (#xBCB1 #x8B58)
+                (#xBCB2 #x9D2B)
+                (#xBCB3 #x7AFA)
+                (#xBCB4 #x8EF8)
+                (#xBCB5 #x5B8D)
+                (#xBCB6 #x96EB)
+                (#xBCB7 #x4E03)
+                (#xBCB8 #x53F1)
+                (#xBCB9 #x57F7)
+                (#xBCBA #x5931)
+                (#xBCBB #x5AC9)
+                (#xBCBC #x5BA4)
+                (#xBCBD #x6089)
+                (#xBCBE #x6E7F)
+                (#xBCBF #x6F06)
+                (#xBCC0 #x75BE)
+                (#xBCC1 #x8CEA)
+                (#xBCC2 #x5B9F)
+                (#xBCC3 #x8500)
+                (#xBCC4 #x7BE0)
+                (#xBCC5 #x5072)
+                (#xBCC6 #x67F4)
+                (#xBCC7 #x829D)
+                (#xBCC8 #x5C61)
+                (#xBCC9 #x854A)
+                (#xBCCA #x7E1E)
+                (#xBCCB #x820E)
+                (#xBCCC #x5199)
+                (#xBCCD #x5C04)
+                (#xBCCE #x6368)
+                (#xBCCF #x8D66)
+                (#xBCD0 #x659C)
+                (#xBCD1 #x716E)
+                (#xBCD2 #x793E)
+                (#xBCD3 #x7D17)
+                (#xBCD4 #x8005)
+                (#xBCD5 #x8B1D)
+                (#xBCD6 #x8ECA)
+                (#xBCD7 #x906E)
+                (#xBCD8 #x86C7)
+                (#xBCD9 #x90AA)
+                (#xBCDA #x501F)
+                (#xBCDB #x52FA)
+                (#xBCDC #x5C3A)
+                (#xBCDD #x6753)
+                (#xBCDE #x707C)
+                (#xBCDF #x7235)
+                (#xBCE0 #x914C)
+                (#xBCE1 #x91C8)
+                (#xBCE2 #x932B)
+                (#xBCE3 #x82E5)
+                (#xBCE4 #x5BC2)
+                (#xBCE5 #x5F31)
+                (#xBCE6 #x60F9)
+                (#xBCE7 #x4E3B)
+                (#xBCE8 #x53D6)
+                (#xBCE9 #x5B88)
+                (#xBCEA #x624B)
+                (#xBCEB #x6731)
+                (#xBCEC #x6B8A)
+                (#xBCED #x72E9)
+                (#xBCEE #x73E0)
+                (#xBCEF #x7A2E)
+                (#xBCF0 #x816B)
+                (#xBCF1 #x8DA3)
+                (#xBCF2 #x9152)
+                (#xBCF3 #x9996)
+                (#xBCF4 #x5112)
+                (#xBCF5 #x53D7)
+                (#xBCF6 #x546A)
+                (#xBCF7 #x5BFF)
+                (#xBCF8 #x6388)
+                (#xBCF9 #x6A39)
+                (#xBCFA #x7DAC)
+                (#xBCFB #x9700)
+                (#xBCFC #x56DA)
+                (#xBCFD #x53CE)
+                (#xBCFE #x5468)
+                (#xBDA1 #x5B97)
+                (#xBDA2 #x5C31)
+                (#xBDA3 #x5DDE)
+                (#xBDA4 #x4FEE)
+                (#xBDA5 #x6101)
+                (#xBDA6 #x62FE)
+                (#xBDA7 #x6D32)
+                (#xBDA8 #x79C0)
+                (#xBDA9 #x79CB)
+                (#xBDAA #x7D42)
+                (#xBDAB #x7E4D)
+                (#xBDAC #x7FD2)
+                (#xBDAD #x81ED)
+                (#xBDAE #x821F)
+                (#xBDAF #x8490)
+                (#xBDB0 #x8846)
+                (#xBDB1 #x8972)
+                (#xBDB2 #x8B90)
+                (#xBDB3 #x8E74)
+                (#xBDB4 #x8F2F)
+                (#xBDB5 #x9031)
+                (#xBDB6 #x914B)
+                (#xBDB7 #x916C)
+                (#xBDB8 #x96C6)
+                (#xBDB9 #x919C)
+                (#xBDBA #x4EC0)
+                (#xBDBB #x4F4F)
+                (#xBDBC #x5145)
+                (#xBDBD #x5341)
+                (#xBDBE #x5F93)
+                (#xBDBF #x620E)
+                (#xBDC0 #x67D4)
+                (#xBDC1 #x6C41)
+                (#xBDC2 #x6E0B)
+                (#xBDC3 #x7363)
+                (#xBDC4 #x7E26)
+                (#xBDC5 #x91CD)
+                (#xBDC6 #x9283)
+                (#xBDC7 #x53D4)
+                (#xBDC8 #x5919)
+                (#xBDC9 #x5BBF)
+                (#xBDCA #x6DD1)
+                (#xBDCB #x795D)
+                (#xBDCC #x7E2E)
+                (#xBDCD #x7C9B)
+                (#xBDCE #x587E)
+                (#xBDCF #x719F)
+                (#xBDD0 #x51FA)
+                (#xBDD1 #x8853)
+                (#xBDD2 #x8FF0)
+                (#xBDD3 #x4FCA)
+                (#xBDD4 #x5CFB)
+                (#xBDD5 #x6625)
+                (#xBDD6 #x77AC)
+                (#xBDD7 #x7AE3)
+                (#xBDD8 #x821C)
+                (#xBDD9 #x99FF)
+                (#xBDDA #x51C6)
+                (#xBDDB #x5FAA)
+                (#xBDDC #x65EC)
+                (#xBDDD #x696F)
+                (#xBDDE #x6B89)
+                (#xBDDF #x6DF3)
+                (#xBDE0 #x6E96)
+                (#xBDE1 #x6F64)
+                (#xBDE2 #x76FE)
+                (#xBDE3 #x7D14)
+                (#xBDE4 #x5DE1)
+                (#xBDE5 #x9075)
+                (#xBDE6 #x9187)
+                (#xBDE7 #x9806)
+                (#xBDE8 #x51E6)
+                (#xBDE9 #x521D)
+                (#xBDEA #x6240)
+                (#xBDEB #x6691)
+                (#xBDEC #x66D9)
+                (#xBDED #x6E1A)
+                (#xBDEE #x5EB6)
+                (#xBDEF #x7DD2)
+                (#xBDF0 #x7F72)
+                (#xBDF1 #x66F8)
+                (#xBDF2 #x85AF)
+                (#xBDF3 #x85F7)
+                (#xBDF4 #x8AF8)
+                (#xBDF5 #x52A9)
+                (#xBDF6 #x53D9)
+                (#xBDF7 #x5973)
+                (#xBDF8 #x5E8F)
+                (#xBDF9 #x5F90)
+                (#xBDFA #x6055)
+                (#xBDFB #x92E4)
+                (#xBDFC #x9664)
+                (#xBDFD #x50B7)
+                (#xBDFE #x511F)
+                (#xBEA1 #x52DD)
+                (#xBEA2 #x5320)
+                (#xBEA3 #x5347)
+                (#xBEA4 #x53EC)
+                (#xBEA5 #x54E8)
+                (#xBEA6 #x5546)
+                (#xBEA7 #x5531)
+                (#xBEA8 #x5617)
+                (#xBEA9 #x5968)
+                (#xBEAA #x59BE)
+                (#xBEAB #x5A3C)
+                (#xBEAC #x5BB5)
+                (#xBEAD #x5C06)
+                (#xBEAE #x5C0F)
+                (#xBEAF #x5C11)
+                (#xBEB0 #x5C1A)
+                (#xBEB1 #x5E84)
+                (#xBEB2 #x5E8A)
+                (#xBEB3 #x5EE0)
+                (#xBEB4 #x5F70)
+                (#xBEB5 #x627F)
+                (#xBEB6 #x6284)
+                (#xBEB7 #x62DB)
+                (#xBEB8 #x638C)
+                (#xBEB9 #x6377)
+                (#xBEBA #x6607)
+                (#xBEBB #x660C)
+                (#xBEBC #x662D)
+                (#xBEBD #x6676)
+                (#xBEBE #x677E)
+                (#xBEBF #x68A2)
+                (#xBEC0 #x6A1F)
+                (#xBEC1 #x6A35)
+                (#xBEC2 #x6CBC)
+                (#xBEC3 #x6D88)
+                (#xBEC4 #x6E09)
+                (#xBEC5 #x6E58)
+                (#xBEC6 #x713C)
+                (#xBEC7 #x7126)
+                (#xBEC8 #x7167)
+                (#xBEC9 #x75C7)
+                (#xBECA #x7701)
+                (#xBECB #x785D)
+                (#xBECC #x7901)
+                (#xBECD #x7965)
+                (#xBECE #x79F0)
+                (#xBECF #x7AE0)
+                (#xBED0 #x7B11)
+                (#xBED1 #x7CA7)
+                (#xBED2 #x7D39)
+                (#xBED3 #x8096)
+                (#xBED4 #x83D6)
+                (#xBED5 #x848B)
+                (#xBED6 #x8549)
+                (#xBED7 #x885D)
+                (#xBED8 #x88F3)
+                (#xBED9 #x8A1F)
+                (#xBEDA #x8A3C)
+                (#xBEDB #x8A54)
+                (#xBEDC #x8A73)
+                (#xBEDD #x8C61)
+                (#xBEDE #x8CDE)
+                (#xBEDF #x91A4)
+                (#xBEE0 #x9266)
+                (#xBEE1 #x937E)
+                (#xBEE2 #x9418)
+                (#xBEE3 #x969C)
+                (#xBEE4 #x9798)
+                (#xBEE5 #x4E0A)
+                (#xBEE6 #x4E08)
+                (#xBEE7 #x4E1E)
+                (#xBEE8 #x4E57)
+                (#xBEE9 #x5197)
+                (#xBEEA #x5270)
+                (#xBEEB #x57CE)
+                (#xBEEC #x5834)
+                (#xBEED #x58CC)
+                (#xBEEE #x5B22)
+                (#xBEEF #x5E38)
+                (#xBEF0 #x60C5)
+                (#xBEF1 #x64FE)
+                (#xBEF2 #x6761)
+                (#xBEF3 #x6756)
+                (#xBEF4 #x6D44)
+                (#xBEF5 #x72B6)
+                (#xBEF6 #x7573)
+                (#xBEF7 #x7A63)
+                (#xBEF8 #x84B8)
+                (#xBEF9 #x8B72)
+                (#xBEFA #x91B8)
+                (#xBEFB #x9320)
+                (#xBEFC #x5631)
+                (#xBEFD #x57F4)
+                (#xBEFE #x98FE)
+                (#xBFA1 #x62ED)
+                (#xBFA2 #x690D)
+                (#xBFA3 #x6B96)
+                (#xBFA4 #x71ED)
+                (#xBFA5 #x7E54)
+                (#xBFA6 #x8077)
+                (#xBFA7 #x8272)
+                (#xBFA8 #x89E6)
+                (#xBFA9 #x98DF)
+                (#xBFAA #x8755)
+                (#xBFAB #x8FB1)
+                (#xBFAC #x5C3B)
+                (#xBFAD #x4F38)
+                (#xBFAE #x4FE1)
+                (#xBFAF #x4FB5)
+                (#xBFB0 #x5507)
+                (#xBFB1 #x5A20)
+                (#xBFB2 #x5BDD)
+                (#xBFB3 #x5BE9)
+                (#xBFB4 #x5FC3)
+                (#xBFB5 #x614E)
+                (#xBFB6 #x632F)
+                (#xBFB7 #x65B0)
+                (#xBFB8 #x664B)
+                (#xBFB9 #x68EE)
+                (#xBFBA #x699B)
+                (#xBFBB #x6D78)
+                (#xBFBC #x6DF1)
+                (#xBFBD #x7533)
+                (#xBFBE #x75B9)
+                (#xBFBF #x771F)
+                (#xBFC0 #x795E)
+                (#xBFC1 #x79E6)
+                (#xBFC2 #x7D33)
+                (#xBFC3 #x81E3)
+                (#xBFC4 #x82AF)
+                (#xBFC5 #x85AA)
+                (#xBFC6 #x89AA)
+                (#xBFC7 #x8A3A)
+                (#xBFC8 #x8EAB)
+                (#xBFC9 #x8F9B)
+                (#xBFCA #x9032)
+                (#xBFCB #x91DD)
+                (#xBFCC #x9707)
+                (#xBFCD #x4EBA)
+                (#xBFCE #x4EC1)
+                (#xBFCF #x5203)
+                (#xBFD0 #x5875)
+                (#xBFD1 #x58EC)
+                (#xBFD2 #x5C0B)
+                (#xBFD3 #x751A)
+                (#xBFD4 #x5C3D)
+                (#xBFD5 #x814E)
+                (#xBFD6 #x8A0A)
+                (#xBFD7 #x8FC5)
+                (#xBFD8 #x9663)
+                (#xBFD9 #x976D)
+                (#xBFDA #x7B25)
+                (#xBFDB #x8ACF)
+                (#xBFDC #x9808)
+                (#xBFDD #x9162)
+                (#xBFDE #x56F3)
+                (#xBFDF #x53A8)
+                (#xBFE0 #x9017)
+                (#xBFE1 #x5439)
+                (#xBFE2 #x5782)
+                (#xBFE3 #x5E25)
+                (#xBFE4 #x63A8)
+                (#xBFE5 #x6C34)
+                (#xBFE6 #x708A)
+                (#xBFE7 #x7761)
+                (#xBFE8 #x7C8B)
+                (#xBFE9 #x7FE0)
+                (#xBFEA #x8870)
+                (#xBFEB #x9042)
+                (#xBFEC #x9154)
+                (#xBFED #x9310)
+                (#xBFEE #x9318)
+                (#xBFEF #x968F)
+                (#xBFF0 #x745E)
+                (#xBFF1 #x9AC4)
+                (#xBFF2 #x5D07)
+                (#xBFF3 #x5D69)
+                (#xBFF4 #x6570)
+                (#xBFF5 #x67A2)
+                (#xBFF6 #x8DA8)
+                (#xBFF7 #x96DB)
+                (#xBFF8 #x636E)
+                (#xBFF9 #x6749)
+                (#xBFFA #x6919)
+                (#xBFFB #x83C5)
+                (#xBFFC #x9817)
+                (#xBFFD #x96C0)
+                (#xBFFE #x88FE)
+                (#xC0A1 #x6F84)
+                (#xC0A2 #x647A)
+                (#xC0A3 #x5BF8)
+                (#xC0A4 #x4E16)
+                (#xC0A5 #x702C)
+                (#xC0A6 #x755D)
+                (#xC0A7 #x662F)
+                (#xC0A8 #x51C4)
+                (#xC0A9 #x5236)
+                (#xC0AA #x52E2)
+                (#xC0AB #x59D3)
+                (#xC0AC #x5F81)
+                (#xC0AD #x6027)
+                (#xC0AE #x6210)
+                (#xC0AF #x653F)
+                (#xC0B0 #x6574)
+                (#xC0B1 #x661F)
+                (#xC0B2 #x6674)
+                (#xC0B3 #x68F2)
+                (#xC0B4 #x6816)
+                (#xC0B5 #x6B63)
+                (#xC0B6 #x6E05)
+                (#xC0B7 #x7272)
+                (#xC0B8 #x751F)
+                (#xC0B9 #x76DB)
+                (#xC0BA #x7CBE)
+                (#xC0BB #x8056)
+                (#xC0BC #x58F0)
+                (#xC0BD #x88FD)
+                (#xC0BE #x897F)
+                (#xC0BF #x8AA0)
+                (#xC0C0 #x8A93)
+                (#xC0C1 #x8ACB)
+                (#xC0C2 #x901D)
+                (#xC0C3 #x9192)
+                (#xC0C4 #x9752)
+                (#xC0C5 #x9759)
+                (#xC0C6 #x6589)
+                (#xC0C7 #x7A0E)
+                (#xC0C8 #x8106)
+                (#xC0C9 #x96BB)
+                (#xC0CA #x5E2D)
+                (#xC0CB #x60DC)
+                (#xC0CC #x621A)
+                (#xC0CD #x65A5)
+                (#xC0CE #x6614)
+                (#xC0CF #x6790)
+                (#xC0D0 #x77F3)
+                (#xC0D1 #x7A4D)
+                (#xC0D2 #x7C4D)
+                (#xC0D3 #x7E3E)
+                (#xC0D4 #x810A)
+                (#xC0D5 #x8CAC)
+                (#xC0D6 #x8D64)
+                (#xC0D7 #x8DE1)
+                (#xC0D8 #x8E5F)
+                (#xC0D9 #x78A9)
+                (#xC0DA #x5207)
+                (#xC0DB #x62D9)
+                (#xC0DC #x63A5)
+                (#xC0DD #x6442)
+                (#xC0DE #x6298)
+                (#xC0DF #x8A2D)
+                (#xC0E0 #x7A83)
+                (#xC0E1 #x7BC0)
+                (#xC0E2 #x8AAC)
+                (#xC0E3 #x96EA)
+                (#xC0E4 #x7D76)
+                (#xC0E5 #x820C)
+                (#xC0E6 #x8749)
+                (#xC0E7 #x4ED9)
+                (#xC0E8 #x5148)
+                (#xC0E9 #x5343)
+                (#xC0EA #x5360)
+                (#xC0EB #x5BA3)
+                (#xC0EC #x5C02)
+                (#xC0ED #x5C16)
+                (#xC0EE #x5DDD)
+                (#xC0EF #x6226)
+                (#xC0F0 #x6247)
+                (#xC0F1 #x64B0)
+                (#xC0F2 #x6813)
+                (#xC0F3 #x6834)
+                (#xC0F4 #x6CC9)
+                (#xC0F5 #x6D45)
+                (#xC0F6 #x6D17)
+                (#xC0F7 #x67D3)
+                (#xC0F8 #x6F5C)
+                (#xC0F9 #x714E)
+                (#xC0FA #x717D)
+                (#xC0FB #x65CB)
+                (#xC0FC #x7A7F)
+                (#xC0FD #x7BAD)
+                (#xC0FE #x7DDA)
+                (#xC1A1 #x7E4A)
+                (#xC1A2 #x7FA8)
+                (#xC1A3 #x817A)
+                (#xC1A4 #x821B)
+                (#xC1A5 #x8239)
+                (#xC1A6 #x85A6)
+                (#xC1A7 #x8A6E)
+                (#xC1A8 #x8CCE)
+                (#xC1A9 #x8DF5)
+                (#xC1AA #x9078)
+                (#xC1AB #x9077)
+                (#xC1AC #x92AD)
+                (#xC1AD #x9291)
+                (#xC1AE #x9583)
+                (#xC1AF #x9BAE)
+                (#xC1B0 #x524D)
+                (#xC1B1 #x5584)
+                (#xC1B2 #x6F38)
+                (#xC1B3 #x7136)
+                (#xC1B4 #x5168)
+                (#xC1B5 #x7985)
+                (#xC1B6 #x7E55)
+                (#xC1B7 #x81B3)
+                (#xC1B8 #x7CCE)
+                (#xC1B9 #x564C)
+                (#xC1BA #x5851)
+                (#xC1BB #x5CA8)
+                (#xC1BC #x63AA)
+                (#xC1BD #x66FE)
+                (#xC1BE #x66FD)
+                (#xC1BF #x695A)
+                (#xC1C0 #x72D9)
+                (#xC1C1 #x758F)
+                (#xC1C2 #x758E)
+                (#xC1C3 #x790E)
+                (#xC1C4 #x7956)
+                (#xC1C5 #x79DF)
+                (#xC1C6 #x7C97)
+                (#xC1C7 #x7D20)
+                (#xC1C8 #x7D44)
+                (#xC1C9 #x8607)
+                (#xC1CA #x8A34)
+                (#xC1CB #x963B)
+                (#xC1CC #x9061)
+                (#xC1CD #x9F20)
+                (#xC1CE #x50E7)
+                (#xC1CF #x5275)
+                (#xC1D0 #x53CC)
+                (#xC1D1 #x53E2)
+                (#xC1D2 #x5009)
+                (#xC1D3 #x55AA)
+                (#xC1D4 #x58EE)
+                (#xC1D5 #x594F)
+                (#xC1D6 #x723D)
+                (#xC1D7 #x5B8B)
+                (#xC1D8 #x5C64)
+                (#xC1D9 #x531D)
+                (#xC1DA #x60E3)
+                (#xC1DB #x60F3)
+                (#xC1DC #x635C)
+                (#xC1DD #x6383)
+                (#xC1DE #x633F)
+                (#xC1DF #x63BB)
+                (#xC1E0 #x64CD)
+                (#xC1E1 #x65E9)
+                (#xC1E2 #x66F9)
+                (#xC1E3 #x5DE3)
+                (#xC1E4 #x69CD)
+                (#xC1E5 #x69FD)
+                (#xC1E6 #x6F15)
+                (#xC1E7 #x71E5)
+                (#xC1E8 #x4E89)
+                (#xC1E9 #x75E9)
+                (#xC1EA #x76F8)
+                (#xC1EB #x7A93)
+                (#xC1EC #x7CDF)
+                (#xC1ED #x7DCF)
+                (#xC1EE #x7D9C)
+                (#xC1EF #x8061)
+                (#xC1F0 #x8349)
+                (#xC1F1 #x8358)
+                (#xC1F2 #x846C)
+                (#xC1F3 #x84BC)
+                (#xC1F4 #x85FB)
+                (#xC1F5 #x88C5)
+                (#xC1F6 #x8D70)
+                (#xC1F7 #x9001)
+                (#xC1F8 #x906D)
+                (#xC1F9 #x9397)
+                (#xC1FA #x971C)
+                (#xC1FB #x9A12)
+                (#xC1FC #x50CF)
+                (#xC1FD #x5897)
+                (#xC1FE #x618E)
+                (#xC2A1 #x81D3)
+                (#xC2A2 #x8535)
+                (#xC2A3 #x8D08)
+                (#xC2A4 #x9020)
+                (#xC2A5 #x4FC3)
+                (#xC2A6 #x5074)
+                (#xC2A7 #x5247)
+                (#xC2A8 #x5373)
+                (#xC2A9 #x606F)
+                (#xC2AA #x6349)
+                (#xC2AB #x675F)
+                (#xC2AC #x6E2C)
+                (#xC2AD #x8DB3)
+                (#xC2AE #x901F)
+                (#xC2AF #x4FD7)
+                (#xC2B0 #x5C5E)
+                (#xC2B1 #x8CCA)
+                (#xC2B2 #x65CF)
+                (#xC2B3 #x7D9A)
+                (#xC2B4 #x5352)
+                (#xC2B5 #x8896)
+                (#xC2B6 #x5176)
+                (#xC2B7 #x63C3)
+                (#xC2B8 #x5B58)
+                (#xC2B9 #x5B6B)
+                (#xC2BA #x5C0A)
+                (#xC2BB #x640D)
+                (#xC2BC #x6751)
+                (#xC2BD #x905C)
+                (#xC2BE #x4ED6)
+                (#xC2BF #x591A)
+                (#xC2C0 #x592A)
+                (#xC2C1 #x6C70)
+                (#xC2C2 #x8A51)
+                (#xC2C3 #x553E)
+                (#xC2C4 #x5815)
+                (#xC2C5 #x59A5)
+                (#xC2C6 #x60F0)
+                (#xC2C7 #x6253)
+                (#xC2C8 #x67C1)
+                (#xC2C9 #x8235)
+                (#xC2CA #x6955)
+                (#xC2CB #x9640)
+                (#xC2CC #x99C4)
+                (#xC2CD #x9A28)
+                (#xC2CE #x4F53)
+                (#xC2CF #x5806)
+                (#xC2D0 #x5BFE)
+                (#xC2D1 #x8010)
+                (#xC2D2 #x5CB1)
+                (#xC2D3 #x5E2F)
+                (#xC2D4 #x5F85)
+                (#xC2D5 #x6020)
+                (#xC2D6 #x614B)
+                (#xC2D7 #x6234)
+                (#xC2D8 #x66FF)
+                (#xC2D9 #x6CF0)
+                (#xC2DA #x6EDE)
+                (#xC2DB #x80CE)
+                (#xC2DC #x817F)
+                (#xC2DD #x82D4)
+                (#xC2DE #x888B)
+                (#xC2DF #x8CB8)
+                (#xC2E0 #x9000)
+                (#xC2E1 #x902E)
+                (#xC2E2 #x968A)
+                (#xC2E3 #x9EDB)
+                (#xC2E4 #x9BDB)
+                (#xC2E5 #x4EE3)
+                (#xC2E6 #x53F0)
+                (#xC2E7 #x5927)
+                (#xC2E8 #x7B2C)
+                (#xC2E9 #x918D)
+                (#xC2EA #x984C)
+                (#xC2EB #x9DF9)
+                (#xC2EC #x6EDD)
+                (#xC2ED #x7027)
+                (#xC2EE #x5353)
+                (#xC2EF #x5544)
+                (#xC2F0 #x5B85)
+                (#xC2F1 #x6258)
+                (#xC2F2 #x629E)
+                (#xC2F3 #x62D3)
+                (#xC2F4 #x6CA2)
+                (#xC2F5 #x6FEF)
+                (#xC2F6 #x7422)
+                (#xC2F7 #x8A17)
+                (#xC2F8 #x9438)
+                (#xC2F9 #x6FC1)
+                (#xC2FA #x8AFE)
+                (#xC2FB #x8338)
+                (#xC2FC #x51E7)
+                (#xC2FD #x86F8)
+                (#xC2FE #x53EA)
+                (#xC3A1 #x53E9)
+                (#xC3A2 #x4F46)
+                (#xC3A3 #x9054)
+                (#xC3A4 #x8FB0)
+                (#xC3A5 #x596A)
+                (#xC3A6 #x8131)
+                (#xC3A7 #x5DFD)
+                (#xC3A8 #x7AEA)
+                (#xC3A9 #x8FBF)
+                (#xC3AA #x68DA)
+                (#xC3AB #x8C37)
+                (#xC3AC #x72F8)
+                (#xC3AD #x9C48)
+                (#xC3AE #x6A3D)
+                (#xC3AF #x8AB0)
+                (#xC3B0 #x4E39)
+                (#xC3B1 #x5358)
+                (#xC3B2 #x5606)
+                (#xC3B3 #x5766)
+                (#xC3B4 #x62C5)
+                (#xC3B5 #x63A2)
+                (#xC3B6 #x65E6)
+                (#xC3B7 #x6B4E)
+                (#xC3B8 #x6DE1)
+                (#xC3B9 #x6E5B)
+                (#xC3BA #x70AD)
+                (#xC3BB #x77ED)
+                (#xC3BC #x7AEF)
+                (#xC3BD #x7BAA)
+                (#xC3BE #x7DBB)
+                (#xC3BF #x803D)
+                (#xC3C0 #x80C6)
+                (#xC3C1 #x86CB)
+                (#xC3C2 #x8A95)
+                (#xC3C3 #x935B)
+                (#xC3C4 #x56E3)
+                (#xC3C5 #x58C7)
+                (#xC3C6 #x5F3E)
+                (#xC3C7 #x65AD)
+                (#xC3C8 #x6696)
+                (#xC3C9 #x6A80)
+                (#xC3CA #x6BB5)
+                (#xC3CB #x7537)
+                (#xC3CC #x8AC7)
+                (#xC3CD #x5024)
+                (#xC3CE #x77E5)
+                (#xC3CF #x5730)
+                (#xC3D0 #x5F1B)
+                (#xC3D1 #x6065)
+                (#xC3D2 #x667A)
+                (#xC3D3 #x6C60)
+                (#xC3D4 #x75F4)
+                (#xC3D5 #x7A1A)
+                (#xC3D6 #x7F6E)
+                (#xC3D7 #x81F4)
+                (#xC3D8 #x8718)
+                (#xC3D9 #x9045)
+                (#xC3DA #x99B3)
+                (#xC3DB #x7BC9)
+                (#xC3DC #x755C)
+                (#xC3DD #x7AF9)
+                (#xC3DE #x7B51)
+                (#xC3DF #x84C4)
+                (#xC3E0 #x9010)
+                (#xC3E1 #x79E9)
+                (#xC3E2 #x7A92)
+                (#xC3E3 #x8336)
+                (#xC3E4 #x5AE1)
+                (#xC3E5 #x7740)
+                (#xC3E6 #x4E2D)
+                (#xC3E7 #x4EF2)
+                (#xC3E8 #x5B99)
+                (#xC3E9 #x5FE0)
+                (#xC3EA #x62BD)
+                (#xC3EB #x663C)
+                (#xC3EC #x67F1)
+                (#xC3ED #x6CE8)
+                (#xC3EE #x866B)
+                (#xC3EF #x8877)
+                (#xC3F0 #x8A3B)
+                (#xC3F1 #x914E)
+                (#xC3F2 #x92F3)
+                (#xC3F3 #x99D0)
+                (#xC3F4 #x6A17)
+                (#xC3F5 #x7026)
+                (#xC3F6 #x732A)
+                (#xC3F7 #x82E7)
+                (#xC3F8 #x8457)
+                (#xC3F9 #x8CAF)
+                (#xC3FA #x4E01)
+                (#xC3FB #x5146)
+                (#xC3FC #x51CB)
+                (#xC3FD #x558B)
+                (#xC3FE #x5BF5)
+                (#xC4A1 #x5E16)
+                (#xC4A2 #x5E33)
+                (#xC4A3 #x5E81)
+                (#xC4A4 #x5F14)
+                (#xC4A5 #x5F35)
+                (#xC4A6 #x5F6B)
+                (#xC4A7 #x5FB4)
+                (#xC4A8 #x61F2)
+                (#xC4A9 #x6311)
+                (#xC4AA #x66A2)
+                (#xC4AB #x671D)
+                (#xC4AC #x6F6E)
+                (#xC4AD #x7252)
+                (#xC4AE #x753A)
+                (#xC4AF #x773A)
+                (#xC4B0 #x8074)
+                (#xC4B1 #x8139)
+                (#xC4B2 #x8178)
+                (#xC4B3 #x8776)
+                (#xC4B4 #x8ABF)
+                (#xC4B5 #x8ADC)
+                (#xC4B6 #x8D85)
+                (#xC4B7 #x8DF3)
+                (#xC4B8 #x929A)
+                (#xC4B9 #x9577)
+                (#xC4BA #x9802)
+                (#xC4BB #x9CE5)
+                (#xC4BC #x52C5)
+                (#xC4BD #x6357)
+                (#xC4BE #x76F4)
+                (#xC4BF #x6715)
+                (#xC4C0 #x6C88)
+                (#xC4C1 #x73CD)
+                (#xC4C2 #x8CC3)
+                (#xC4C3 #x93AE)
+                (#xC4C4 #x9673)
+                (#xC4C5 #x6D25)
+                (#xC4C6 #x589C)
+                (#xC4C7 #x690E)
+                (#xC4C8 #x69CC)
+                (#xC4C9 #x8FFD)
+                (#xC4CA #x939A)
+                (#xC4CB #x75DB)
+                (#xC4CC #x901A)
+                (#xC4CD #x585A)
+                (#xC4CE #x6802)
+                (#xC4CF #x63B4)
+                (#xC4D0 #x69FB)
+                (#xC4D1 #x4F43)
+                (#xC4D2 #x6F2C)
+                (#xC4D3 #x67D8)
+                (#xC4D4 #x8FBB)
+                (#xC4D5 #x8526)
+                (#xC4D6 #x7DB4)
+                (#xC4D7 #x9354)
+                (#xC4D8 #x693F)
+                (#xC4D9 #x6F70)
+                (#xC4DA #x576A)
+                (#xC4DB #x58F7)
+                (#xC4DC #x5B2C)
+                (#xC4DD #x7D2C)
+                (#xC4DE #x722A)
+                (#xC4DF #x540A)
+                (#xC4E0 #x91E3)
+                (#xC4E1 #x9DB4)
+                (#xC4E2 #x4EAD)
+                (#xC4E3 #x4F4E)
+                (#xC4E4 #x505C)
+                (#xC4E5 #x5075)
+                (#xC4E6 #x5243)
+                (#xC4E7 #x8C9E)
+                (#xC4E8 #x5448)
+                (#xC4E9 #x5824)
+                (#xC4EA #x5B9A)
+                (#xC4EB #x5E1D)
+                (#xC4EC #x5E95)
+                (#xC4ED #x5EAD)
+                (#xC4EE #x5EF7)
+                (#xC4EF #x5F1F)
+                (#xC4F0 #x608C)
+                (#xC4F1 #x62B5)
+                (#xC4F2 #x633A)
+                (#xC4F3 #x63D0)
+                (#xC4F4 #x68AF)
+                (#xC4F5 #x6C40)
+                (#xC4F6 #x7887)
+                (#xC4F7 #x798E)
+                (#xC4F8 #x7A0B)
+                (#xC4F9 #x7DE0)
+                (#xC4FA #x8247)
+                (#xC4FB #x8A02)
+                (#xC4FC #x8AE6)
+                (#xC4FD #x8E44)
+                (#xC4FE #x9013)
+                (#xC5A1 #x90B8)
+                (#xC5A2 #x912D)
+                (#xC5A3 #x91D8)
+                (#xC5A4 #x9F0E)
+                (#xC5A5 #x6CE5)
+                (#xC5A6 #x6458)
+                (#xC5A7 #x64E2)
+                (#xC5A8 #x6575)
+                (#xC5A9 #x6EF4)
+                (#xC5AA #x7684)
+                (#xC5AB #x7B1B)
+                (#xC5AC #x9069)
+                (#xC5AD #x93D1)
+                (#xC5AE #x6EBA)
+                (#xC5AF #x54F2)
+                (#xC5B0 #x5FB9)
+                (#xC5B1 #x64A4)
+                (#xC5B2 #x8F4D)
+                (#xC5B3 #x8FED)
+                (#xC5B4 #x9244)
+                (#xC5B5 #x5178)
+                (#xC5B6 #x586B)
+                (#xC5B7 #x5929)
+                (#xC5B8 #x5C55)
+                (#xC5B9 #x5E97)
+                (#xC5BA #x6DFB)
+                (#xC5BB #x7E8F)
+                (#xC5BC #x751C)
+                (#xC5BD #x8CBC)
+                (#xC5BE #x8EE2)
+                (#xC5BF #x985B)
+                (#xC5C0 #x70B9)
+                (#xC5C1 #x4F1D)
+                (#xC5C2 #x6BBF)
+                (#xC5C3 #x6FB1)
+                (#xC5C4 #x7530)
+                (#xC5C5 #x96FB)
+                (#xC5C6 #x514E)
+                (#xC5C7 #x5410)
+                (#xC5C8 #x5835)
+                (#xC5C9 #x5857)
+                (#xC5CA #x59AC)
+                (#xC5CB #x5C60)
+                (#xC5CC #x5F92)
+                (#xC5CD #x6597)
+                (#xC5CE #x675C)
+                (#xC5CF #x6E21)
+                (#xC5D0 #x767B)
+                (#xC5D1 #x83DF)
+                (#xC5D2 #x8CED)
+                (#xC5D3 #x9014)
+                (#xC5D4 #x90FD)
+                (#xC5D5 #x934D)
+                (#xC5D6 #x7825)
+                (#xC5D7 #x783A)
+                (#xC5D8 #x52AA)
+                (#xC5D9 #x5EA6)
+                (#xC5DA #x571F)
+                (#xC5DB #x5974)
+                (#xC5DC #x6012)
+                (#xC5DD #x5012)
+                (#xC5DE #x515A)
+                (#xC5DF #x51AC)
+                (#xC5E0 #x51CD)
+                (#xC5E1 #x5200)
+                (#xC5E2 #x5510)
+                (#xC5E3 #x5854)
+                (#xC5E4 #x5858)
+                (#xC5E5 #x5957)
+                (#xC5E6 #x5B95)
+                (#xC5E7 #x5CF6)
+                (#xC5E8 #x5D8B)
+                (#xC5E9 #x60BC)
+                (#xC5EA #x6295)
+                (#xC5EB #x642D)
+                (#xC5EC #x6771)
+                (#xC5ED #x6843)
+                (#xC5EE #x68BC)
+                (#xC5EF #x68DF)
+                (#xC5F0 #x76D7)
+                (#xC5F1 #x6DD8)
+                (#xC5F2 #x6E6F)
+                (#xC5F3 #x6D9B)
+                (#xC5F4 #x706F)
+                (#xC5F5 #x71C8)
+                (#xC5F6 #x5F53)
+                (#xC5F7 #x75D8)
+                (#xC5F8 #x7977)
+                (#xC5F9 #x7B49)
+                (#xC5FA #x7B54)
+                (#xC5FB #x7B52)
+                (#xC5FC #x7CD6)
+                (#xC5FD #x7D71)
+                (#xC5FE #x5230)
+                (#xC6A1 #x8463)
+                (#xC6A2 #x8569)
+                (#xC6A3 #x85E4)
+                (#xC6A4 #x8A0E)
+                (#xC6A5 #x8B04)
+                (#xC6A6 #x8C46)
+                (#xC6A7 #x8E0F)
+                (#xC6A8 #x9003)
+                (#xC6A9 #x900F)
+                (#xC6AA #x9419)
+                (#xC6AB #x9676)
+                (#xC6AC #x982D)
+                (#xC6AD #x9A30)
+                (#xC6AE #x95D8)
+                (#xC6AF #x50CD)
+                (#xC6B0 #x52D5)
+                (#xC6B1 #x540C)
+                (#xC6B2 #x5802)
+                (#xC6B3 #x5C0E)
+                (#xC6B4 #x61A7)
+                (#xC6B5 #x649E)
+                (#xC6B6 #x6D1E)
+                (#xC6B7 #x77B3)
+                (#xC6B8 #x7AE5)
+                (#xC6B9 #x80F4)
+                (#xC6BA #x8404)
+                (#xC6BB #x9053)
+                (#xC6BC #x9285)
+                (#xC6BD #x5CE0)
+                (#xC6BE #x9D07)
+                (#xC6BF #x533F)
+                (#xC6C0 #x5F97)
+                (#xC6C1 #x5FB3)
+                (#xC6C2 #x6D9C)
+                (#xC6C3 #x7279)
+                (#xC6C4 #x7763)
+                (#xC6C5 #x79BF)
+                (#xC6C6 #x7BE4)
+                (#xC6C7 #x6BD2)
+                (#xC6C8 #x72EC)
+                (#xC6C9 #x8AAD)
+                (#xC6CA #x6803)
+                (#xC6CB #x6A61)
+                (#xC6CC #x51F8)
+                (#xC6CD #x7A81)
+                (#xC6CE #x6934)
+                (#xC6CF #x5C4A)
+                (#xC6D0 #x9CF6)
+                (#xC6D1 #x82EB)
+                (#xC6D2 #x5BC5)
+                (#xC6D3 #x9149)
+                (#xC6D4 #x701E)
+                (#xC6D5 #x5678)
+                (#xC6D6 #x5C6F)
+                (#xC6D7 #x60C7)
+                (#xC6D8 #x6566)
+                (#xC6D9 #x6C8C)
+                (#xC6DA #x8C5A)
+                (#xC6DB #x9041)
+                (#xC6DC #x9813)
+                (#xC6DD #x5451)
+                (#xC6DE #x66C7)
+                (#xC6DF #x920D)
+                (#xC6E0 #x5948)
+                (#xC6E1 #x90A3)
+                (#xC6E2 #x5185)
+                (#xC6E3 #x4E4D)
+                (#xC6E4 #x51EA)
+                (#xC6E5 #x8599)
+                (#xC6E6 #x8B0E)
+                (#xC6E7 #x7058)
+                (#xC6E8 #x637A)
+                (#xC6E9 #x934B)
+                (#xC6EA #x6962)
+                (#xC6EB #x99B4)
+                (#xC6EC #x7E04)
+                (#xC6ED #x7577)
+                (#xC6EE #x5357)
+                (#xC6EF #x6960)
+                (#xC6F0 #x8EDF)
+                (#xC6F1 #x96E3)
+                (#xC6F2 #x6C5D)
+                (#xC6F3 #x4E8C)
+                (#xC6F4 #x5C3C)
+                (#xC6F5 #x5F10)
+                (#xC6F6 #x8FE9)
+                (#xC6F7 #x5302)
+                (#xC6F8 #x8CD1)
+                (#xC6F9 #x8089)
+                (#xC6FA #x8679)
+                (#xC6FB #x5EFF)
+                (#xC6FC #x65E5)
+                (#xC6FD #x4E73)
+                (#xC6FE #x5165)
+                (#xC7A1 #x5982)
+                (#xC7A2 #x5C3F)
+                (#xC7A3 #x97EE)
+                (#xC7A4 #x4EFB)
+                (#xC7A5 #x598A)
+                (#xC7A6 #x5FCD)
+                (#xC7A7 #x8A8D)
+                (#xC7A8 #x6FE1)
+                (#xC7A9 #x79B0)
+                (#xC7AA #x7962)
+                (#xC7AB #x5BE7)
+                (#xC7AC #x8471)
+                (#xC7AD #x732B)
+                (#xC7AE #x71B1)
+                (#xC7AF #x5E74)
+                (#xC7B0 #x5FF5)
+                (#xC7B1 #x637B)
+                (#xC7B2 #x649A)
+                (#xC7B3 #x71C3)
+                (#xC7B4 #x7C98)
+                (#xC7B5 #x4E43)
+                (#xC7B6 #x5EFC)
+                (#xC7B7 #x4E4B)
+                (#xC7B8 #x57DC)
+                (#xC7B9 #x56A2)
+                (#xC7BA #x60A9)
+                (#xC7BB #x6FC3)
+                (#xC7BC #x7D0D)
+                (#xC7BD #x80FD)
+                (#xC7BE #x8133)
+                (#xC7BF #x81BF)
+                (#xC7C0 #x8FB2)
+                (#xC7C1 #x8997)
+                (#xC7C2 #x86A4)
+                (#xC7C3 #x5DF4)
+                (#xC7C4 #x628A)
+                (#xC7C5 #x64AD)
+                (#xC7C6 #x8987)
+                (#xC7C7 #x6777)
+                (#xC7C8 #x6CE2)
+                (#xC7C9 #x6D3E)
+                (#xC7CA #x7436)
+                (#xC7CB #x7834)
+                (#xC7CC #x5A46)
+                (#xC7CD #x7F75)
+                (#xC7CE #x82AD)
+                (#xC7CF #x99AC)
+                (#xC7D0 #x4FF3)
+                (#xC7D1 #x5EC3)
+                (#xC7D2 #x62DD)
+                (#xC7D3 #x6392)
+                (#xC7D4 #x6557)
+                (#xC7D5 #x676F)
+                (#xC7D6 #x76C3)
+                (#xC7D7 #x724C)
+                (#xC7D8 #x80CC)
+                (#xC7D9 #x80BA)
+                (#xC7DA #x8F29)
+                (#xC7DB #x914D)
+                (#xC7DC #x500D)
+                (#xC7DD #x57F9)
+                (#xC7DE #x5A92)
+                (#xC7DF #x6885)
+                (#xC7E0 #x6973)
+                (#xC7E1 #x7164)
+                (#xC7E2 #x72FD)
+                (#xC7E3 #x8CB7)
+                (#xC7E4 #x58F2)
+                (#xC7E5 #x8CE0)
+                (#xC7E6 #x966A)
+                (#xC7E7 #x9019)
+                (#xC7E8 #x877F)
+                (#xC7E9 #x79E4)
+                (#xC7EA #x77E7)
+                (#xC7EB #x8429)
+                (#xC7EC #x4F2F)
+                (#xC7ED #x5265)
+                (#xC7EE #x535A)
+                (#xC7EF #x62CD)
+                (#xC7F0 #x67CF)
+                (#xC7F1 #x6CCA)
+                (#xC7F2 #x767D)
+                (#xC7F3 #x7B94)
+                (#xC7F4 #x7C95)
+                (#xC7F5 #x8236)
+                (#xC7F6 #x8584)
+                (#xC7F7 #x8FEB)
+                (#xC7F8 #x66DD)
+                (#xC7F9 #x6F20)
+                (#xC7FA #x7206)
+                (#xC7FB #x7E1B)
+                (#xC7FC #x83AB)
+                (#xC7FD #x99C1)
+                (#xC7FE #x9EA6)
+                (#xC8A1 #x51FD)
+                (#xC8A2 #x7BB1)
+                (#xC8A3 #x7872)
+                (#xC8A4 #x7BB8)
+                (#xC8A5 #x8087)
+                (#xC8A6 #x7B48)
+                (#xC8A7 #x6AE8)
+                (#xC8A8 #x5E61)
+                (#xC8A9 #x808C)
+                (#xC8AA #x7551)
+                (#xC8AB #x7560)
+                (#xC8AC #x516B)
+                (#xC8AD #x9262)
+                (#xC8AE #x6E8C)
+                (#xC8AF #x767A)
+                (#xC8B0 #x9197)
+                (#xC8B1 #x9AEA)
+                (#xC8B2 #x4F10)
+                (#xC8B3 #x7F70)
+                (#xC8B4 #x629C)
+                (#xC8B5 #x7B4F)
+                (#xC8B6 #x95A5)
+                (#xC8B7 #x9CE9)
+                (#xC8B8 #x567A)
+                (#xC8B9 #x5859)
+                (#xC8BA #x86E4)
+                (#xC8BB #x96BC)
+                (#xC8BC #x4F34)
+                (#xC8BD #x5224)
+                (#xC8BE #x534A)
+                (#xC8BF #x53CD)
+                (#xC8C0 #x53DB)
+                (#xC8C1 #x5E06)
+                (#xC8C2 #x642C)
+                (#xC8C3 #x6591)
+                (#xC8C4 #x677F)
+                (#xC8C5 #x6C3E)
+                (#xC8C6 #x6C4E)
+                (#xC8C7 #x7248)
+                (#xC8C8 #x72AF)
+                (#xC8C9 #x73ED)
+                (#xC8CA #x7554)
+                (#xC8CB #x7E41)
+                (#xC8CC #x822C)
+                (#xC8CD #x85E9)
+                (#xC8CE #x8CA9)
+                (#xC8CF #x7BC4)
+                (#xC8D0 #x91C6)
+                (#xC8D1 #x7169)
+                (#xC8D2 #x9812)
+                (#xC8D3 #x98EF)
+                (#xC8D4 #x633D)
+                (#xC8D5 #x6669)
+                (#xC8D6 #x756A)
+                (#xC8D7 #x76E4)
+                (#xC8D8 #x78D0)
+                (#xC8D9 #x8543)
+                (#xC8DA #x86EE)
+                (#xC8DB #x532A)
+                (#xC8DC #x5351)
+                (#xC8DD #x5426)
+                (#xC8DE #x5983)
+                (#xC8DF #x5E87)
+                (#xC8E0 #x5F7C)
+                (#xC8E1 #x60B2)
+                (#xC8E2 #x6249)
+                (#xC8E3 #x6279)
+                (#xC8E4 #x62AB)
+                (#xC8E5 #x6590)
+                (#xC8E6 #x6BD4)
+                (#xC8E7 #x6CCC)
+                (#xC8E8 #x75B2)
+                (#xC8E9 #x76AE)
+                (#xC8EA #x7891)
+                (#xC8EB #x79D8)
+                (#xC8EC #x7DCB)
+                (#xC8ED #x7F77)
+                (#xC8EE #x80A5)
+                (#xC8EF #x88AB)
+                (#xC8F0 #x8AB9)
+                (#xC8F1 #x8CBB)
+                (#xC8F2 #x907F)
+                (#xC8F3 #x975E)
+                (#xC8F4 #x98DB)
+                (#xC8F5 #x6A0B)
+                (#xC8F6 #x7C38)
+                (#xC8F7 #x5099)
+                (#xC8F8 #x5C3E)
+                (#xC8F9 #x5FAE)
+                (#xC8FA #x6787)
+                (#xC8FB #x6BD8)
+                (#xC8FC #x7435)
+                (#xC8FD #x7709)
+                (#xC8FE #x7F8E)
+                (#xC9A1 #x9F3B)
+                (#xC9A2 #x67CA)
+                (#xC9A3 #x7A17)
+                (#xC9A4 #x5339)
+                (#xC9A5 #x758B)
+                (#xC9A6 #x9AED)
+                (#xC9A7 #x5F66)
+                (#xC9A8 #x819D)
+                (#xC9A9 #x83F1)
+                (#xC9AA #x8098)
+                (#xC9AB #x5F3C)
+                (#xC9AC #x5FC5)
+                (#xC9AD #x7562)
+                (#xC9AE #x7B46)
+                (#xC9AF #x903C)
+                (#xC9B0 #x6867)
+                (#xC9B1 #x59EB)
+                (#xC9B2 #x5A9B)
+                (#xC9B3 #x7D10)
+                (#xC9B4 #x767E)
+                (#xC9B5 #x8B2C)
+                (#xC9B6 #x4FF5)
+                (#xC9B7 #x5F6A)
+                (#xC9B8 #x6A19)
+                (#xC9B9 #x6C37)
+                (#xC9BA #x6F02)
+                (#xC9BB #x74E2)
+                (#xC9BC #x7968)
+                (#xC9BD #x8868)
+                (#xC9BE #x8A55)
+                (#xC9BF #x8C79)
+                (#xC9C0 #x5EDF)
+                (#xC9C1 #x63CF)
+                (#xC9C2 #x75C5)
+                (#xC9C3 #x79D2)
+                (#xC9C4 #x82D7)
+                (#xC9C5 #x9328)
+                (#xC9C6 #x92F2)
+                (#xC9C7 #x849C)
+                (#xC9C8 #x86ED)
+                (#xC9C9 #x9C2D)
+                (#xC9CA #x54C1)
+                (#xC9CB #x5F6C)
+                (#xC9CC #x658C)
+                (#xC9CD #x6D5C)
+                (#xC9CE #x7015)
+                (#xC9CF #x8CA7)
+                (#xC9D0 #x8CD3)
+                (#xC9D1 #x983B)
+                (#xC9D2 #x654F)
+                (#xC9D3 #x74F6)
+                (#xC9D4 #x4E0D)
+                (#xC9D5 #x4ED8)
+                (#xC9D6 #x57E0)
+                (#xC9D7 #x592B)
+                (#xC9D8 #x5A66)
+                (#xC9D9 #x5BCC)
+                (#xC9DA #x51A8)
+                (#xC9DB #x5E03)
+                (#xC9DC #x5E9C)
+                (#xC9DD #x6016)
+                (#xC9DE #x6276)
+                (#xC9DF #x6577)
+                (#xC9E0 #x65A7)
+                (#xC9E1 #x666E)
+                (#xC9E2 #x6D6E)
+                (#xC9E3 #x7236)
+                (#xC9E4 #x7B26)
+                (#xC9E5 #x8150)
+                (#xC9E6 #x819A)
+                (#xC9E7 #x8299)
+                (#xC9E8 #x8B5C)
+                (#xC9E9 #x8CA0)
+                (#xC9EA #x8CE6)
+                (#xC9EB #x8D74)
+                (#xC9EC #x961C)
+                (#xC9ED #x9644)
+                (#xC9EE #x4FAE)
+                (#xC9EF #x64AB)
+                (#xC9F0 #x6B66)
+                (#xC9F1 #x821E)
+                (#xC9F2 #x8461)
+                (#xC9F3 #x856A)
+                (#xC9F4 #x90E8)
+                (#xC9F5 #x5C01)
+                (#xC9F6 #x6953)
+                (#xC9F7 #x98A8)
+                (#xC9F8 #x847A)
+                (#xC9F9 #x8557)
+                (#xC9FA #x4F0F)
+                (#xC9FB #x526F)
+                (#xC9FC #x5FA9)
+                (#xC9FD #x5E45)
+                (#xC9FE #x670D)
+                (#xCAA1 #x798F)
+                (#xCAA2 #x8179)
+                (#xCAA3 #x8907)
+                (#xCAA4 #x8986)
+                (#xCAA5 #x6DF5)
+                (#xCAA6 #x5F17)
+                (#xCAA7 #x6255)
+                (#xCAA8 #x6CB8)
+                (#xCAA9 #x4ECF)
+                (#xCAAA #x7269)
+                (#xCAAB #x9B92)
+                (#xCAAC #x5206)
+                (#xCAAD #x543B)
+                (#xCAAE #x5674)
+                (#xCAAF #x58B3)
+                (#xCAB0 #x61A4)
+                (#xCAB1 #x626E)
+                (#xCAB2 #x711A)
+                (#xCAB3 #x596E)
+                (#xCAB4 #x7C89)
+                (#xCAB5 #x7CDE)
+                (#xCAB6 #x7D1B)
+                (#xCAB7 #x96F0)
+                (#xCAB8 #x6587)
+                (#xCAB9 #x805E)
+                (#xCABA #x4E19)
+                (#xCABB #x4F75)
+                (#xCABC #x5175)
+                (#xCABD #x5840)
+                (#xCABE #x5E63)
+                (#xCABF #x5E73)
+                (#xCAC0 #x5F0A)
+                (#xCAC1 #x67C4)
+                (#xCAC2 #x4E26)
+                (#xCAC3 #x853D)
+                (#xCAC4 #x9589)
+                (#xCAC5 #x965B)
+                (#xCAC6 #x7C73)
+                (#xCAC7 #x9801)
+                (#xCAC8 #x50FB)
+                (#xCAC9 #x58C1)
+                (#xCACA #x7656)
+                (#xCACB #x78A7)
+                (#xCACC #x5225)
+                (#xCACD #x77A5)
+                (#xCACE #x8511)
+                (#xCACF #x7B86)
+                (#xCAD0 #x504F)
+                (#xCAD1 #x5909)
+                (#xCAD2 #x7247)
+                (#xCAD3 #x7BC7)
+                (#xCAD4 #x7DE8)
+                (#xCAD5 #x8FBA)
+                (#xCAD6 #x8FD4)
+                (#xCAD7 #x904D)
+                (#xCAD8 #x4FBF)
+                (#xCAD9 #x52C9)
+                (#xCADA #x5A29)
+                (#xCADB #x5F01)
+                (#xCADC #x97AD)
+                (#xCADD #x4FDD)
+                (#xCADE #x8217)
+                (#xCADF #x92EA)
+                (#xCAE0 #x5703)
+                (#xCAE1 #x6355)
+                (#xCAE2 #x6B69)
+                (#xCAE3 #x752B)
+                (#xCAE4 #x88DC)
+                (#xCAE5 #x8F14)
+                (#xCAE6 #x7A42)
+                (#xCAE7 #x52DF)
+                (#xCAE8 #x5893)
+                (#xCAE9 #x6155)
+                (#xCAEA #x620A)
+                (#xCAEB #x66AE)
+                (#xCAEC #x6BCD)
+                (#xCAED #x7C3F)
+                (#xCAEE #x83E9)
+                (#xCAEF #x5023)
+                (#xCAF0 #x4FF8)
+                (#xCAF1 #x5305)
+                (#xCAF2 #x5446)
+                (#xCAF3 #x5831)
+                (#xCAF4 #x5949)
+                (#xCAF5 #x5B9D)
+                (#xCAF6 #x5CF0)
+                (#xCAF7 #x5CEF)
+                (#xCAF8 #x5D29)
+                (#xCAF9 #x5E96)
+                (#xCAFA #x62B1)
+                (#xCAFB #x6367)
+                (#xCAFC #x653E)
+                (#xCAFD #x65B9)
+                (#xCAFE #x670B)
+                (#xCBA1 #x6CD5)
+                (#xCBA2 #x6CE1)
+                (#xCBA3 #x70F9)
+                (#xCBA4 #x7832)
+                (#xCBA5 #x7E2B)
+                (#xCBA6 #x80DE)
+                (#xCBA7 #x82B3)
+                (#xCBA8 #x840C)
+                (#xCBA9 #x84EC)
+                (#xCBAA #x8702)
+                (#xCBAB #x8912)
+                (#xCBAC #x8A2A)
+                (#xCBAD #x8C4A)
+                (#xCBAE #x90A6)
+                (#xCBAF #x92D2)
+                (#xCBB0 #x98FD)
+                (#xCBB1 #x9CF3)
+                (#xCBB2 #x9D6C)
+                (#xCBB3 #x4E4F)
+                (#xCBB4 #x4EA1)
+                (#xCBB5 #x508D)
+                (#xCBB6 #x5256)
+                (#xCBB7 #x574A)
+                (#xCBB8 #x59A8)
+                (#xCBB9 #x5E3D)
+                (#xCBBA #x5FD8)
+                (#xCBBB #x5FD9)
+                (#xCBBC #x623F)
+                (#xCBBD #x66B4)
+                (#xCBBE #x671B)
+                (#xCBBF #x67D0)
+                (#xCBC0 #x68D2)
+                (#xCBC1 #x5192)
+                (#xCBC2 #x7D21)
+                (#xCBC3 #x80AA)
+                (#xCBC4 #x81A8)
+                (#xCBC5 #x8B00)
+                (#xCBC6 #x8C8C)
+                (#xCBC7 #x8CBF)
+                (#xCBC8 #x927E)
+                (#xCBC9 #x9632)
+                (#xCBCA #x5420)
+                (#xCBCB #x982C)
+                (#xCBCC #x5317)
+                (#xCBCD #x50D5)
+                (#xCBCE #x535C)
+                (#xCBCF #x58A8)
+                (#xCBD0 #x64B2)
+                (#xCBD1 #x6734)
+                (#xCBD2 #x7267)
+                (#xCBD3 #x7766)
+                (#xCBD4 #x7A46)
+                (#xCBD5 #x91E6)
+                (#xCBD6 #x52C3)
+                (#xCBD7 #x6CA1)
+                (#xCBD8 #x6B86)
+                (#xCBD9 #x5800)
+                (#xCBDA #x5E4C)
+                (#xCBDB #x5954)
+                (#xCBDC #x672C)
+                (#xCBDD #x7FFB)
+                (#xCBDE #x51E1)
+                (#xCBDF #x76C6)
+                (#xCBE0 #x6469)
+                (#xCBE1 #x78E8)
+                (#xCBE2 #x9B54)
+                (#xCBE3 #x9EBB)
+                (#xCBE4 #x57CB)
+                (#xCBE5 #x59B9)
+                (#xCBE6 #x6627)
+                (#xCBE7 #x679A)
+                (#xCBE8 #x6BCE)
+                (#xCBE9 #x54E9)
+                (#xCBEA #x69D9)
+                (#xCBEB #x5E55)
+                (#xCBEC #x819C)
+                (#xCBED #x6795)
+                (#xCBEE #x9BAA)
+                (#xCBEF #x67FE)
+                (#xCBF0 #x9C52)
+                (#xCBF1 #x685D)
+                (#xCBF2 #x4EA6)
+                (#xCBF3 #x4FE3)
+                (#xCBF4 #x53C8)
+                (#xCBF5 #x62B9)
+                (#xCBF6 #x672B)
+                (#xCBF7 #x6CAB)
+                (#xCBF8 #x8FC4)
+                (#xCBF9 #x4FAD)
+                (#xCBFA #x7E6D)
+                (#xCBFB #x9EBF)
+                (#xCBFC #x4E07)
+                (#xCBFD #x6162)
+                (#xCBFE #x6E80)
+                (#xCCA1 #x6F2B)
+                (#xCCA2 #x8513)
+                (#xCCA3 #x5473)
+                (#xCCA4 #x672A)
+                (#xCCA5 #x9B45)
+                (#xCCA6 #x5DF3)
+                (#xCCA7 #x7B95)
+                (#xCCA8 #x5CAC)
+                (#xCCA9 #x5BC6)
+                (#xCCAA #x871C)
+                (#xCCAB #x6E4A)
+                (#xCCAC #x84D1)
+                (#xCCAD #x7A14)
+                (#xCCAE #x8108)
+                (#xCCAF #x5999)
+                (#xCCB0 #x7C8D)
+                (#xCCB1 #x6C11)
+                (#xCCB2 #x7720)
+                (#xCCB3 #x52D9)
+                (#xCCB4 #x5922)
+                (#xCCB5 #x7121)
+                (#xCCB6 #x725F)
+                (#xCCB7 #x77DB)
+                (#xCCB8 #x9727)
+                (#xCCB9 #x9D61)
+                (#xCCBA #x690B)
+                (#xCCBB #x5A7F)
+                (#xCCBC #x5A18)
+                (#xCCBD #x51A5)
+                (#xCCBE #x540D)
+                (#xCCBF #x547D)
+                (#xCCC0 #x660E)
+                (#xCCC1 #x76DF)
+                (#xCCC2 #x8FF7)
+                (#xCCC3 #x9298)
+                (#xCCC4 #x9CF4)
+                (#xCCC5 #x59EA)
+                (#xCCC6 #x725D)
+                (#xCCC7 #x6EC5)
+                (#xCCC8 #x514D)
+                (#xCCC9 #x68C9)
+                (#xCCCA #x7DBF)
+                (#xCCCB #x7DEC)
+                (#xCCCC #x9762)
+                (#xCCCD #x9EBA)
+                (#xCCCE #x6478)
+                (#xCCCF #x6A21)
+                (#xCCD0 #x8302)
+                (#xCCD1 #x5984)
+                (#xCCD2 #x5B5F)
+                (#xCCD3 #x6BDB)
+                (#xCCD4 #x731B)
+                (#xCCD5 #x76F2)
+                (#xCCD6 #x7DB2)
+                (#xCCD7 #x8017)
+                (#xCCD8 #x8499)
+                (#xCCD9 #x5132)
+                (#xCCDA #x6728)
+                (#xCCDB #x9ED9)
+                (#xCCDC #x76EE)
+                (#xCCDD #x6762)
+                (#xCCDE #x52FF)
+                (#xCCDF #x9905)
+                (#xCCE0 #x5C24)
+                (#xCCE1 #x623B)
+                (#xCCE2 #x7C7E)
+                (#xCCE3 #x8CB0)
+                (#xCCE4 #x554F)
+                (#xCCE5 #x60B6)
+                (#xCCE6 #x7D0B)
+                (#xCCE7 #x9580)
+                (#xCCE8 #x5301)
+                (#xCCE9 #x4E5F)
+                (#xCCEA #x51B6)
+                (#xCCEB #x591C)
+                (#xCCEC #x723A)
+                (#xCCED #x8036)
+                (#xCCEE #x91CE)
+                (#xCCEF #x5F25)
+                (#xCCF0 #x77E2)
+                (#xCCF1 #x5384)
+                (#xCCF2 #x5F79)
+                (#xCCF3 #x7D04)
+                (#xCCF4 #x85AC)
+                (#xCCF5 #x8A33)
+                (#xCCF6 #x8E8D)
+                (#xCCF7 #x9756)
+                (#xCCF8 #x67F3)
+                (#xCCF9 #x85AE)
+                (#xCCFA #x9453)
+                (#xCCFB #x6109)
+                (#xCCFC #x6108)
+                (#xCCFD #x6CB9)
+                (#xCCFE #x7652)
+                (#xCDA1 #x8AED)
+                (#xCDA2 #x8F38)
+                (#xCDA3 #x552F)
+                (#xCDA4 #x4F51)
+                (#xCDA5 #x512A)
+                (#xCDA6 #x52C7)
+                (#xCDA7 #x53CB)
+                (#xCDA8 #x5BA5)
+                (#xCDA9 #x5E7D)
+                (#xCDAA #x60A0)
+                (#xCDAB #x6182)
+                (#xCDAC #x63D6)
+                (#xCDAD #x6709)
+                (#xCDAE #x67DA)
+                (#xCDAF #x6E67)
+                (#xCDB0 #x6D8C)
+                (#xCDB1 #x7336)
+                (#xCDB2 #x7337)
+                (#xCDB3 #x7531)
+                (#xCDB4 #x7950)
+                (#xCDB5 #x88D5)
+                (#xCDB6 #x8A98)
+                (#xCDB7 #x904A)
+                (#xCDB8 #x9091)
+                (#xCDB9 #x90F5)
+                (#xCDBA #x96C4)
+                (#xCDBB #x878D)
+                (#xCDBC #x5915)
+                (#xCDBD #x4E88)
+                (#xCDBE #x4F59)
+                (#xCDBF #x4E0E)
+                (#xCDC0 #x8A89)
+                (#xCDC1 #x8F3F)
+                (#xCDC2 #x9810)
+                (#xCDC3 #x50AD)
+                (#xCDC4 #x5E7C)
+                (#xCDC5 #x5996)
+                (#xCDC6 #x5BB9)
+                (#xCDC7 #x5EB8)
+                (#xCDC8 #x63DA)
+                (#xCDC9 #x63FA)
+                (#xCDCA #x64C1)
+                (#xCDCB #x66DC)
+                (#xCDCC #x694A)
+                (#xCDCD #x69D8)
+                (#xCDCE #x6D0B)
+                (#xCDCF #x6EB6)
+                (#xCDD0 #x7194)
+                (#xCDD1 #x7528)
+                (#xCDD2 #x7AAF)
+                (#xCDD3 #x7F8A)
+                (#xCDD4 #x8000)
+                (#xCDD5 #x8449)
+                (#xCDD6 #x84C9)
+                (#xCDD7 #x8981)
+                (#xCDD8 #x8B21)
+                (#xCDD9 #x8E0A)
+                (#xCDDA #x9065)
+                (#xCDDB #x967D)
+                (#xCDDC #x990A)
+                (#xCDDD #x617E)
+                (#xCDDE #x6291)
+                (#xCDDF #x6B32)
+                (#xCDE0 #x6C83)
+                (#xCDE1 #x6D74)
+                (#xCDE2 #x7FCC)
+                (#xCDE3 #x7FFC)
+                (#xCDE4 #x6DC0)
+                (#xCDE5 #x7F85)
+                (#xCDE6 #x87BA)
+                (#xCDE7 #x88F8)
+                (#xCDE8 #x6765)
+                (#xCDE9 #x83B1)
+                (#xCDEA #x983C)
+                (#xCDEB #x96F7)
+                (#xCDEC #x6D1B)
+                (#xCDED #x7D61)
+                (#xCDEE #x843D)
+                (#xCDEF #x916A)
+                (#xCDF0 #x4E71)
+                (#xCDF1 #x5375)
+                (#xCDF2 #x5D50)
+                (#xCDF3 #x6B04)
+                (#xCDF4 #x6FEB)
+                (#xCDF5 #x85CD)
+                (#xCDF6 #x862D)
+                (#xCDF7 #x89A7)
+                (#xCDF8 #x5229)
+                (#xCDF9 #x540F)
+                (#xCDFA #x5C65)
+                (#xCDFB #x674E)
+                (#xCDFC #x68A8)
+                (#xCDFD #x7406)
+                (#xCDFE #x7483)
+                (#xCEA1 #x75E2)
+                (#xCEA2 #x88CF)
+                (#xCEA3 #x88E1)
+                (#xCEA4 #x91CC)
+                (#xCEA5 #x96E2)
+                (#xCEA6 #x9678)
+                (#xCEA7 #x5F8B)
+                (#xCEA8 #x7387)
+                (#xCEA9 #x7ACB)
+                (#xCEAA #x844E)
+                (#xCEAB #x63A0)
+                (#xCEAC #x7565)
+                (#xCEAD #x5289)
+                (#xCEAE #x6D41)
+                (#xCEAF #x6E9C)
+                (#xCEB0 #x7409)
+                (#xCEB1 #x7559)
+                (#xCEB2 #x786B)
+                (#xCEB3 #x7C92)
+                (#xCEB4 #x9686)
+                (#xCEB5 #x7ADC)
+                (#xCEB6 #x9F8D)
+                (#xCEB7 #x4FB6)
+                (#xCEB8 #x616E)
+                (#xCEB9 #x65C5)
+                (#xCEBA #x865C)
+                (#xCEBB #x4E86)
+                (#xCEBC #x4EAE)
+                (#xCEBD #x50DA)
+                (#xCEBE #x4E21)
+                (#xCEBF #x51CC)
+                (#xCEC0 #x5BEE)
+                (#xCEC1 #x6599)
+                (#xCEC2 #x6881)
+                (#xCEC3 #x6DBC)
+                (#xCEC4 #x731F)
+                (#xCEC5 #x7642)
+                (#xCEC6 #x77AD)
+                (#xCEC7 #x7A1C)
+                (#xCEC8 #x7CE7)
+                (#xCEC9 #x826F)
+                (#xCECA #x8AD2)
+                (#xCECB #x907C)
+                (#xCECC #x91CF)
+                (#xCECD #x9675)
+                (#xCECE #x9818)
+                (#xCECF #x529B)
+                (#xCED0 #x7DD1)
+                (#xCED1 #x502B)
+                (#xCED2 #x5398)
+                (#xCED3 #x6797)
+                (#xCED4 #x6DCB)
+                (#xCED5 #x71D0)
+                (#xCED6 #x7433)
+                (#xCED7 #x81E8)
+                (#xCED8 #x8F2A)
+                (#xCED9 #x96A3)
+                (#xCEDA #x9C57)
+                (#xCEDB #x9E9F)
+                (#xCEDC #x7460)
+                (#xCEDD #x5841)
+                (#xCEDE #x6D99)
+                (#xCEDF #x7D2F)
+                (#xCEE0 #x985E)
+                (#xCEE1 #x4EE4)
+                (#xCEE2 #x4F36)
+                (#xCEE3 #x4F8B)
+                (#xCEE4 #x51B7)
+                (#xCEE5 #x52B1)
+                (#xCEE6 #x5DBA)
+                (#xCEE7 #x601C)
+                (#xCEE8 #x73B2)
+                (#xCEE9 #x793C)
+                (#xCEEA #x82D3)
+                (#xCEEB #x9234)
+                (#xCEEC #x96B7)
+                (#xCEED #x96F6)
+                (#xCEEE #x970A)
+                (#xCEEF #x9E97)
+                (#xCEF0 #x9F62)
+                (#xCEF1 #x66A6)
+                (#xCEF2 #x6B74)
+                (#xCEF3 #x5217)
+                (#xCEF4 #x52A3)
+                (#xCEF5 #x70C8)
+                (#xCEF6 #x88C2)
+                (#xCEF7 #x5EC9)
+                (#xCEF8 #x604B)
+                (#xCEF9 #x6190)
+                (#xCEFA #x6F23)
+                (#xCEFB #x7149)
+                (#xCEFC #x7C3E)
+                (#xCEFD #x7DF4)
+                (#xCEFE #x806F)
+                (#xCFA1 #x84EE)
+                (#xCFA2 #x9023)
+                (#xCFA3 #x932C)
+                (#xCFA4 #x5442)
+                (#xCFA5 #x9B6F)
+                (#xCFA6 #x6AD3)
+                (#xCFA7 #x7089)
+                (#xCFA8 #x8CC2)
+                (#xCFA9 #x8DEF)
+                (#xCFAA #x9732)
+                (#xCFAB #x52B4)
+                (#xCFAC #x5A41)
+                (#xCFAD #x5ECA)
+                (#xCFAE #x5F04)
+                (#xCFAF #x6717)
+                (#xCFB0 #x697C)
+                (#xCFB1 #x6994)
+                (#xCFB2 #x6D6A)
+                (#xCFB3 #x6F0F)
+                (#xCFB4 #x7262)
+                (#xCFB5 #x72FC)
+                (#xCFB6 #x7BED)
+                (#xCFB7 #x8001)
+                (#xCFB8 #x807E)
+                (#xCFB9 #x874B)
+                (#xCFBA #x90CE)
+                (#xCFBB #x516D)
+                (#xCFBC #x9E93)
+                (#xCFBD #x7984)
+                (#xCFBE #x808B)
+                (#xCFBF #x9332)
+                (#xCFC0 #x8AD6)
+                (#xCFC1 #x502D)
+                (#xCFC2 #x548C)
+                (#xCFC3 #x8A71)
+                (#xCFC4 #x6B6A)
+                (#xCFC5 #x8CC4)
+                (#xCFC6 #x8107)
+                (#xCFC7 #x60D1)
+                (#xCFC8 #x67A0)
+                (#xCFC9 #x9DF2)
+                (#xCFCA #x4E99)
+                (#xCFCB #x4E98)
+                (#xCFCC #x9C10)
+                (#xCFCD #x8A6B)
+                (#xCFCE #x85C1)
+                (#xCFCF #x8568)
+                (#xCFD0 #x6900)
+                (#xCFD1 #x6E7E)
+                (#xCFD2 #x7897)
+                (#xCFD3 #x8155)
+                (#xD0A1 #x5F0C)
+                (#xD0A2 #x4E10)
+                (#xD0A3 #x4E15)
+                (#xD0A4 #x4E2A)
+                (#xD0A5 #x4E31)
+                (#xD0A6 #x4E36)
+                (#xD0A7 #x4E3C)
+                (#xD0A8 #x4E3F)
+                (#xD0A9 #x4E42)
+                (#xD0AA #x4E56)
+                (#xD0AB #x4E58)
+                (#xD0AC #x4E82)
+                (#xD0AD #x4E85)
+                (#xD0AE #x8C6B)
+                (#xD0AF #x4E8A)
+                (#xD0B0 #x8212)
+                (#xD0B1 #x5F0D)
+                (#xD0B2 #x4E8E)
+                (#xD0B3 #x4E9E)
+                (#xD0B4 #x4E9F)
+                (#xD0B5 #x4EA0)
+                (#xD0B6 #x4EA2)
+                (#xD0B7 #x4EB0)
+                (#xD0B8 #x4EB3)
+                (#xD0B9 #x4EB6)
+                (#xD0BA #x4ECE)
+                (#xD0BB #x4ECD)
+                (#xD0BC #x4EC4)
+                (#xD0BD #x4EC6)
+                (#xD0BE #x4EC2)
+                (#xD0BF #x4ED7)
+                (#xD0C0 #x4EDE)
+                (#xD0C1 #x4EED)
+                (#xD0C2 #x4EDF)
+                (#xD0C3 #x4EF7)
+                (#xD0C4 #x4F09)
+                (#xD0C5 #x4F5A)
+                (#xD0C6 #x4F30)
+                (#xD0C7 #x4F5B)
+                (#xD0C8 #x4F5D)
+                (#xD0C9 #x4F57)
+                (#xD0CA #x4F47)
+                (#xD0CB #x4F76)
+                (#xD0CC #x4F88)
+                (#xD0CD #x4F8F)
+                (#xD0CE #x4F98)
+                (#xD0CF #x4F7B)
+                (#xD0D0 #x4F69)
+                (#xD0D1 #x4F70)
+                (#xD0D2 #x4F91)
+                (#xD0D3 #x4F6F)
+                (#xD0D4 #x4F86)
+                (#xD0D5 #x4F96)
+                (#xD0D6 #x5118)
+                (#xD0D7 #x4FD4)
+                (#xD0D8 #x4FDF)
+                (#xD0D9 #x4FCE)
+                (#xD0DA #x4FD8)
+                (#xD0DB #x4FDB)
+                (#xD0DC #x4FD1)
+                (#xD0DD #x4FDA)
+                (#xD0DE #x4FD0)
+                (#xD0DF #x4FE4)
+                (#xD0E0 #x4FE5)
+                (#xD0E1 #x501A)
+                (#xD0E2 #x5028)
+                (#xD0E3 #x5014)
+                (#xD0E4 #x502A)
+                (#xD0E5 #x5025)
+                (#xD0E6 #x5005)
+                (#xD0E7 #x4F1C)
+                (#xD0E8 #x4FF6)
+                (#xD0E9 #x5021)
+                (#xD0EA #x5029)
+                (#xD0EB #x502C)
+                (#xD0EC #x4FFE)
+                (#xD0ED #x4FEF)
+                (#xD0EE #x5011)
+                (#xD0EF #x5006)
+                (#xD0F0 #x5043)
+                (#xD0F1 #x5047)
+                (#xD0F2 #x6703)
+                (#xD0F3 #x5055)
+                (#xD0F4 #x5050)
+                (#xD0F5 #x5048)
+                (#xD0F6 #x505A)
+                (#xD0F7 #x5056)
+                (#xD0F8 #x506C)
+                (#xD0F9 #x5078)
+                (#xD0FA #x5080)
+                (#xD0FB #x509A)
+                (#xD0FC #x5085)
+                (#xD0FD #x50B4)
+                (#xD0FE #x50B2)
+                (#xD1A1 #x50C9)
+                (#xD1A2 #x50CA)
+                (#xD1A3 #x50B3)
+                (#xD1A4 #x50C2)
+                (#xD1A5 #x50D6)
+                (#xD1A6 #x50DE)
+                (#xD1A7 #x50E5)
+                (#xD1A8 #x50ED)
+                (#xD1A9 #x50E3)
+                (#xD1AA #x50EE)
+                (#xD1AB #x50F9)
+                (#xD1AC #x50F5)
+                (#xD1AD #x5109)
+                (#xD1AE #x5101)
+                (#xD1AF #x5102)
+                (#xD1B0 #x5116)
+                (#xD1B1 #x5115)
+                (#xD1B2 #x5114)
+                (#xD1B3 #x511A)
+                (#xD1B4 #x5121)
+                (#xD1B5 #x513A)
+                (#xD1B6 #x5137)
+                (#xD1B7 #x513C)
+                (#xD1B8 #x513B)
+                (#xD1B9 #x513F)
+                (#xD1BA #x5140)
+                (#xD1BB #x5152)
+                (#xD1BC #x514C)
+                (#xD1BD #x5154)
+                (#xD1BE #x5162)
+                (#xD1BF #x7AF8)
+                (#xD1C0 #x5169)
+                (#xD1C1 #x516A)
+                (#xD1C2 #x516E)
+                (#xD1C3 #x5180)
+                (#xD1C4 #x5182)
+                (#xD1C5 #x56D8)
+                (#xD1C6 #x518C)
+                (#xD1C7 #x5189)
+                (#xD1C8 #x518F)
+                (#xD1C9 #x5191)
+                (#xD1CA #x5193)
+                (#xD1CB #x5195)
+                (#xD1CC #x5196)
+                (#xD1CD #x51A4)
+                (#xD1CE #x51A6)
+                (#xD1CF #x51A2)
+                (#xD1D0 #x51A9)
+                (#xD1D1 #x51AA)
+                (#xD1D2 #x51AB)
+                (#xD1D3 #x51B3)
+                (#xD1D4 #x51B1)
+                (#xD1D5 #x51B2)
+                (#xD1D6 #x51B0)
+                (#xD1D7 #x51B5)
+                (#xD1D8 #x51BD)
+                (#xD1D9 #x51C5)
+                (#xD1DA #x51C9)
+                (#xD1DB #x51DB)
+                (#xD1DC #x51E0)
+                (#xD1DD #x8655)
+                (#xD1DE #x51E9)
+                (#xD1DF #x51ED)
+                (#xD1E0 #x51F0)
+                (#xD1E1 #x51F5)
+                (#xD1E2 #x51FE)
+                (#xD1E3 #x5204)
+                (#xD1E4 #x520B)
+                (#xD1E5 #x5214)
+                (#xD1E6 #x520E)
+                (#xD1E7 #x5227)
+                (#xD1E8 #x522A)
+                (#xD1E9 #x522E)
+                (#xD1EA #x5233)
+                (#xD1EB #x5239)
+                (#xD1EC #x524F)
+                (#xD1ED #x5244)
+                (#xD1EE #x524B)
+                (#xD1EF #x524C)
+                (#xD1F0 #x525E)
+                (#xD1F1 #x5254)
+                (#xD1F2 #x526A)
+                (#xD1F3 #x5274)
+                (#xD1F4 #x5269)
+                (#xD1F5 #x5273)
+                (#xD1F6 #x527F)
+                (#xD1F7 #x527D)
+                (#xD1F8 #x528D)
+                (#xD1F9 #x5294)
+                (#xD1FA #x5292)
+                (#xD1FB #x5271)
+                (#xD1FC #x5288)
+                (#xD1FD #x5291)
+                (#xD1FE #x8FA8)
+                (#xD2A1 #x8FA7)
+                (#xD2A2 #x52AC)
+                (#xD2A3 #x52AD)
+                (#xD2A4 #x52BC)
+                (#xD2A5 #x52B5)
+                (#xD2A6 #x52C1)
+                (#xD2A7 #x52CD)
+                (#xD2A8 #x52D7)
+                (#xD2A9 #x52DE)
+                (#xD2AA #x52E3)
+                (#xD2AB #x52E6)
+                (#xD2AC #x98ED)
+                (#xD2AD #x52E0)
+                (#xD2AE #x52F3)
+                (#xD2AF #x52F5)
+                (#xD2B0 #x52F8)
+                (#xD2B1 #x52F9)
+                (#xD2B2 #x5306)
+                (#xD2B3 #x5308)
+                (#xD2B4 #x7538)
+                (#xD2B5 #x530D)
+                (#xD2B6 #x5310)
+                (#xD2B7 #x530F)
+                (#xD2B8 #x5315)
+                (#xD2B9 #x531A)
+                (#xD2BA #x5323)
+                (#xD2BB #x532F)
+                (#xD2BC #x5331)
+                (#xD2BD #x5333)
+                (#xD2BE #x5338)
+                (#xD2BF #x5340)
+                (#xD2C0 #x5346)
+                (#xD2C1 #x5345)
+                (#xD2C2 #x4E17)
+                (#xD2C3 #x5349)
+                (#xD2C4 #x534D)
+                (#xD2C5 #x51D6)
+                (#xD2C6 #x535E)
+                (#xD2C7 #x5369)
+                (#xD2C8 #x536E)
+                (#xD2C9 #x5918)
+                (#xD2CA #x537B)
+                (#xD2CB #x5377)
+                (#xD2CC #x5382)
+                (#xD2CD #x5396)
+                (#xD2CE #x53A0)
+                (#xD2CF #x53A6)
+                (#xD2D0 #x53A5)
+                (#xD2D1 #x53AE)
+                (#xD2D2 #x53B0)
+                (#xD2D3 #x53B6)
+                (#xD2D4 #x53C3)
+                (#xD2D5 #x7C12)
+                (#xD2D6 #x96D9)
+                (#xD2D7 #x53DF)
+                (#xD2D8 #x66FC)
+                (#xD2D9 #x71EE)
+                (#xD2DA #x53EE)
+                (#xD2DB #x53E8)
+                (#xD2DC #x53ED)
+                (#xD2DD #x53FA)
+                (#xD2DE #x5401)
+                (#xD2DF #x543D)
+                (#xD2E0 #x5440)
+                (#xD2E1 #x542C)
+                (#xD2E2 #x542D)
+                (#xD2E3 #x543C)
+                (#xD2E4 #x542E)
+                (#xD2E5 #x5436)
+                (#xD2E6 #x5429)
+                (#xD2E7 #x541D)
+                (#xD2E8 #x544E)
+                (#xD2E9 #x548F)
+                (#xD2EA #x5475)
+                (#xD2EB #x548E)
+                (#xD2EC #x545F)
+                (#xD2ED #x5471)
+                (#xD2EE #x5477)
+                (#xD2EF #x5470)
+                (#xD2F0 #x5492)
+                (#xD2F1 #x547B)
+                (#xD2F2 #x5480)
+                (#xD2F3 #x5476)
+                (#xD2F4 #x5484)
+                (#xD2F5 #x5490)
+                (#xD2F6 #x5486)
+                (#xD2F7 #x54C7)
+                (#xD2F8 #x54A2)
+                (#xD2F9 #x54B8)
+                (#xD2FA #x54A5)
+                (#xD2FB #x54AC)
+                (#xD2FC #x54C4)
+                (#xD2FD #x54C8)
+                (#xD2FE #x54A8)
+                (#xD3A1 #x54AB)
+                (#xD3A2 #x54C2)
+                (#xD3A3 #x54A4)
+                (#xD3A4 #x54BE)
+                (#xD3A5 #x54BC)
+                (#xD3A6 #x54D8)
+                (#xD3A7 #x54E5)
+                (#xD3A8 #x54E6)
+                (#xD3A9 #x550F)
+                (#xD3AA #x5514)
+                (#xD3AB #x54FD)
+                (#xD3AC #x54EE)
+                (#xD3AD #x54ED)
+                (#xD3AE #x54FA)
+                (#xD3AF #x54E2)
+                (#xD3B0 #x5539)
+                (#xD3B1 #x5540)
+                (#xD3B2 #x5563)
+                (#xD3B3 #x554C)
+                (#xD3B4 #x552E)
+                (#xD3B5 #x555C)
+                (#xD3B6 #x5545)
+                (#xD3B7 #x5556)
+                (#xD3B8 #x5557)
+                (#xD3B9 #x5538)
+                (#xD3BA #x5533)
+                (#xD3BB #x555D)
+                (#xD3BC #x5599)
+                (#xD3BD #x5580)
+                (#xD3BE #x54AF)
+                (#xD3BF #x558A)
+                (#xD3C0 #x559F)
+                (#xD3C1 #x557B)
+                (#xD3C2 #x557E)
+                (#xD3C3 #x5598)
+                (#xD3C4 #x559E)
+                (#xD3C5 #x55AE)
+                (#xD3C6 #x557C)
+                (#xD3C7 #x5583)
+                (#xD3C8 #x55A9)
+                (#xD3C9 #x5587)
+                (#xD3CA #x55A8)
+                (#xD3CB #x55DA)
+                (#xD3CC #x55C5)
+                (#xD3CD #x55DF)
+                (#xD3CE #x55C4)
+                (#xD3CF #x55DC)
+                (#xD3D0 #x55E4)
+                (#xD3D1 #x55D4)
+                (#xD3D2 #x5614)
+                (#xD3D3 #x55F7)
+                (#xD3D4 #x5616)
+                (#xD3D5 #x55FE)
+                (#xD3D6 #x55FD)
+                (#xD3D7 #x561B)
+                (#xD3D8 #x55F9)
+                (#xD3D9 #x564E)
+                (#xD3DA #x5650)
+                (#xD3DB #x71DF)
+                (#xD3DC #x5634)
+                (#xD3DD #x5636)
+                (#xD3DE #x5632)
+                (#xD3DF #x5638)
+                (#xD3E0 #x566B)
+                (#xD3E1 #x5664)
+                (#xD3E2 #x562F)
+                (#xD3E3 #x566C)
+                (#xD3E4 #x566A)
+                (#xD3E5 #x5686)
+                (#xD3E6 #x5680)
+                (#xD3E7 #x568A)
+                (#xD3E8 #x56A0)
+                (#xD3E9 #x5694)
+                (#xD3EA #x568F)
+                (#xD3EB #x56A5)
+                (#xD3EC #x56AE)
+                (#xD3ED #x56B6)
+                (#xD3EE #x56B4)
+                (#xD3EF #x56C2)
+                (#xD3F0 #x56BC)
+                (#xD3F1 #x56C1)
+                (#xD3F2 #x56C3)
+                (#xD3F3 #x56C0)
+                (#xD3F4 #x56C8)
+                (#xD3F5 #x56CE)
+                (#xD3F6 #x56D1)
+                (#xD3F7 #x56D3)
+                (#xD3F8 #x56D7)
+                (#xD3F9 #x56EE)
+                (#xD3FA #x56F9)
+                (#xD3FB #x5700)
+                (#xD3FC #x56FF)
+                (#xD3FD #x5704)
+                (#xD3FE #x5709)
+                (#xD4A1 #x5708)
+                (#xD4A2 #x570B)
+                (#xD4A3 #x570D)
+                (#xD4A4 #x5713)
+                (#xD4A5 #x5718)
+                (#xD4A6 #x5716)
+                (#xD4A7 #x55C7)
+                (#xD4A8 #x571C)
+                (#xD4A9 #x5726)
+                (#xD4AA #x5737)
+                (#xD4AB #x5738)
+                (#xD4AC #x574E)
+                (#xD4AD #x573B)
+                (#xD4AE #x5740)
+                (#xD4AF #x574F)
+                (#xD4B0 #x5769)
+                (#xD4B1 #x57C0)
+                (#xD4B2 #x5788)
+                (#xD4B3 #x5761)
+                (#xD4B4 #x577F)
+                (#xD4B5 #x5789)
+                (#xD4B6 #x5793)
+                (#xD4B7 #x57A0)
+                (#xD4B8 #x57B3)
+                (#xD4B9 #x57A4)
+                (#xD4BA #x57AA)
+                (#xD4BB #x57B0)
+                (#xD4BC #x57C3)
+                (#xD4BD #x57C6)
+                (#xD4BE #x57D4)
+                (#xD4BF #x57D2)
+                (#xD4C0 #x57D3)
+                (#xD4C1 #x580A)
+                (#xD4C2 #x57D6)
+                (#xD4C3 #x57E3)
+                (#xD4C4 #x580B)
+                (#xD4C5 #x5819)
+                (#xD4C6 #x581D)
+                (#xD4C7 #x5872)
+                (#xD4C8 #x5821)
+                (#xD4C9 #x5862)
+                (#xD4CA #x584B)
+                (#xD4CB #x5870)
+                (#xD4CC #x6BC0)
+                (#xD4CD #x5852)
+                (#xD4CE #x583D)
+                (#xD4CF #x5879)
+                (#xD4D0 #x5885)
+                (#xD4D1 #x58B9)
+                (#xD4D2 #x589F)
+                (#xD4D3 #x58AB)
+                (#xD4D4 #x58BA)
+                (#xD4D5 #x58DE)
+                (#xD4D6 #x58BB)
+                (#xD4D7 #x58B8)
+                (#xD4D8 #x58AE)
+                (#xD4D9 #x58C5)
+                (#xD4DA #x58D3)
+                (#xD4DB #x58D1)
+                (#xD4DC #x58D7)
+                (#xD4DD #x58D9)
+                (#xD4DE #x58D8)
+                (#xD4DF #x58E5)
+                (#xD4E0 #x58DC)
+                (#xD4E1 #x58E4)
+                (#xD4E2 #x58DF)
+                (#xD4E3 #x58EF)
+                (#xD4E4 #x58FA)
+                (#xD4E5 #x58F9)
+                (#xD4E6 #x58FB)
+                (#xD4E7 #x58FC)
+                (#xD4E8 #x58FD)
+                (#xD4E9 #x5902)
+                (#xD4EA #x590A)
+                (#xD4EB #x5910)
+                (#xD4EC #x591B)
+                (#xD4ED #x68A6)
+                (#xD4EE #x5925)
+                (#xD4EF #x592C)
+                (#xD4F0 #x592D)
+                (#xD4F1 #x5932)
+                (#xD4F2 #x5938)
+                (#xD4F3 #x593E)
+                (#xD4F4 #x7AD2)
+                (#xD4F5 #x5955)
+                (#xD4F6 #x5950)
+                (#xD4F7 #x594E)
+                (#xD4F8 #x595A)
+                (#xD4F9 #x5958)
+                (#xD4FA #x5962)
+                (#xD4FB #x5960)
+                (#xD4FC #x5967)
+                (#xD4FD #x596C)
+                (#xD4FE #x5969)
+                (#xD5A1 #x5978)
+                (#xD5A2 #x5981)
+                (#xD5A3 #x599D)
+                (#xD5A4 #x4F5E)
+                (#xD5A5 #x4FAB)
+                (#xD5A6 #x59A3)
+                (#xD5A7 #x59B2)
+                (#xD5A8 #x59C6)
+                (#xD5A9 #x59E8)
+                (#xD5AA #x59DC)
+                (#xD5AB #x598D)
+                (#xD5AC #x59D9)
+                (#xD5AD #x59DA)
+                (#xD5AE #x5A25)
+                (#xD5AF #x5A1F)
+                (#xD5B0 #x5A11)
+                (#xD5B1 #x5A1C)
+                (#xD5B2 #x5A09)
+                (#xD5B3 #x5A1A)
+                (#xD5B4 #x5A40)
+                (#xD5B5 #x5A6C)
+                (#xD5B6 #x5A49)
+                (#xD5B7 #x5A35)
+                (#xD5B8 #x5A36)
+                (#xD5B9 #x5A62)
+                (#xD5BA #x5A6A)
+                (#xD5BB #x5A9A)
+                (#xD5BC #x5ABC)
+                (#xD5BD #x5ABE)
+                (#xD5BE #x5ACB)
+                (#xD5BF #x5AC2)
+                (#xD5C0 #x5ABD)
+                (#xD5C1 #x5AE3)
+                (#xD5C2 #x5AD7)
+                (#xD5C3 #x5AE6)
+                (#xD5C4 #x5AE9)
+                (#xD5C5 #x5AD6)
+                (#xD5C6 #x5AFA)
+                (#xD5C7 #x5AFB)
+                (#xD5C8 #x5B0C)
+                (#xD5C9 #x5B0B)
+                (#xD5CA #x5B16)
+                (#xD5CB #x5B32)
+                (#xD5CC #x5AD0)
+                (#xD5CD #x5B2A)
+                (#xD5CE #x5B36)
+                (#xD5CF #x5B3E)
+                (#xD5D0 #x5B43)
+                (#xD5D1 #x5B45)
+                (#xD5D2 #x5B40)
+                (#xD5D3 #x5B51)
+                (#xD5D4 #x5B55)
+                (#xD5D5 #x5B5A)
+                (#xD5D6 #x5B5B)
+                (#xD5D7 #x5B65)
+                (#xD5D8 #x5B69)
+                (#xD5D9 #x5B70)
+                (#xD5DA #x5B73)
+                (#xD5DB #x5B75)
+                (#xD5DC #x5B78)
+                (#xD5DD #x6588)
+                (#xD5DE #x5B7A)
+                (#xD5DF #x5B80)
+                (#xD5E0 #x5B83)
+                (#xD5E1 #x5BA6)
+                (#xD5E2 #x5BB8)
+                (#xD5E3 #x5BC3)
+                (#xD5E4 #x5BC7)
+                (#xD5E5 #x5BC9)
+                (#xD5E6 #x5BD4)
+                (#xD5E7 #x5BD0)
+                (#xD5E8 #x5BE4)
+                (#xD5E9 #x5BE6)
+                (#xD5EA #x5BE2)
+                (#xD5EB #x5BDE)
+                (#xD5EC #x5BE5)
+                (#xD5ED #x5BEB)
+                (#xD5EE #x5BF0)
+                (#xD5EF #x5BF6)
+                (#xD5F0 #x5BF3)
+                (#xD5F1 #x5C05)
+                (#xD5F2 #x5C07)
+                (#xD5F3 #x5C08)
+                (#xD5F4 #x5C0D)
+                (#xD5F5 #x5C13)
+                (#xD5F6 #x5C20)
+                (#xD5F7 #x5C22)
+                (#xD5F8 #x5C28)
+                (#xD5F9 #x5C38)
+                (#xD5FA #x5C39)
+                (#xD5FB #x5C41)
+                (#xD5FC #x5C46)
+                (#xD5FD #x5C4E)
+                (#xD5FE #x5C53)
+                (#xD6A1 #x5C50)
+                (#xD6A2 #x5C4F)
+                (#xD6A3 #x5B71)
+                (#xD6A4 #x5C6C)
+                (#xD6A5 #x5C6E)
+                (#xD6A6 #x4E62)
+                (#xD6A7 #x5C76)
+                (#xD6A8 #x5C79)
+                (#xD6A9 #x5C8C)
+                (#xD6AA #x5C91)
+                (#xD6AB #x5C94)
+                (#xD6AC #x599B)
+                (#xD6AD #x5CAB)
+                (#xD6AE #x5CBB)
+                (#xD6AF #x5CB6)
+                (#xD6B0 #x5CBC)
+                (#xD6B1 #x5CB7)
+                (#xD6B2 #x5CC5)
+                (#xD6B3 #x5CBE)
+                (#xD6B4 #x5CC7)
+                (#xD6B5 #x5CD9)
+                (#xD6B6 #x5CE9)
+                (#xD6B7 #x5CFD)
+                (#xD6B8 #x5CFA)
+                (#xD6B9 #x5CED)
+                (#xD6BA #x5D8C)
+                (#xD6BB #x5CEA)
+                (#xD6BC #x5D0B)
+                (#xD6BD #x5D15)
+                (#xD6BE #x5D17)
+                (#xD6BF #x5D5C)
+                (#xD6C0 #x5D1F)
+                (#xD6C1 #x5D1B)
+                (#xD6C2 #x5D11)
+                (#xD6C3 #x5D14)
+                (#xD6C4 #x5D22)
+                (#xD6C5 #x5D1A)
+                (#xD6C6 #x5D19)
+                (#xD6C7 #x5D18)
+                (#xD6C8 #x5D4C)
+                (#xD6C9 #x5D52)
+                (#xD6CA #x5D4E)
+                (#xD6CB #x5D4B)
+                (#xD6CC #x5D6C)
+                (#xD6CD #x5D73)
+                (#xD6CE #x5D76)
+                (#xD6CF #x5D87)
+                (#xD6D0 #x5D84)
+                (#xD6D1 #x5D82)
+                (#xD6D2 #x5DA2)
+                (#xD6D3 #x5D9D)
+                (#xD6D4 #x5DAC)
+                (#xD6D5 #x5DAE)
+                (#xD6D6 #x5DBD)
+                (#xD6D7 #x5D90)
+                (#xD6D8 #x5DB7)
+                (#xD6D9 #x5DBC)
+                (#xD6DA #x5DC9)
+                (#xD6DB #x5DCD)
+                (#xD6DC #x5DD3)
+                (#xD6DD #x5DD2)
+                (#xD6DE #x5DD6)
+                (#xD6DF #x5DDB)
+                (#xD6E0 #x5DEB)
+                (#xD6E1 #x5DF2)
+                (#xD6E2 #x5DF5)
+                (#xD6E3 #x5E0B)
+                (#xD6E4 #x5E1A)
+                (#xD6E5 #x5E19)
+                (#xD6E6 #x5E11)
+                (#xD6E7 #x5E1B)
+                (#xD6E8 #x5E36)
+                (#xD6E9 #x5E37)
+                (#xD6EA #x5E44)
+                (#xD6EB #x5E43)
+                (#xD6EC #x5E40)
+                (#xD6ED #x5E4E)
+                (#xD6EE #x5E57)
+                (#xD6EF #x5E54)
+                (#xD6F0 #x5E5F)
+                (#xD6F1 #x5E62)
+                (#xD6F2 #x5E64)
+                (#xD6F3 #x5E47)
+                (#xD6F4 #x5E75)
+                (#xD6F5 #x5E76)
+                (#xD6F6 #x5E7A)
+                (#xD6F7 #x9EBC)
+                (#xD6F8 #x5E7F)
+                (#xD6F9 #x5EA0)
+                (#xD6FA #x5EC1)
+                (#xD6FB #x5EC2)
+                (#xD6FC #x5EC8)
+                (#xD6FD #x5ED0)
+                (#xD6FE #x5ECF)
+                (#xD7A1 #x5ED6)
+                (#xD7A2 #x5EE3)
+                (#xD7A3 #x5EDD)
+                (#xD7A4 #x5EDA)
+                (#xD7A5 #x5EDB)
+                (#xD7A6 #x5EE2)
+                (#xD7A7 #x5EE1)
+                (#xD7A8 #x5EE8)
+                (#xD7A9 #x5EE9)
+                (#xD7AA #x5EEC)
+                (#xD7AB #x5EF1)
+                (#xD7AC #x5EF3)
+                (#xD7AD #x5EF0)
+                (#xD7AE #x5EF4)
+                (#xD7AF #x5EF8)
+                (#xD7B0 #x5EFE)
+                (#xD7B1 #x5F03)
+                (#xD7B2 #x5F09)
+                (#xD7B3 #x5F5D)
+                (#xD7B4 #x5F5C)
+                (#xD7B5 #x5F0B)
+                (#xD7B6 #x5F11)
+                (#xD7B7 #x5F16)
+                (#xD7B8 #x5F29)
+                (#xD7B9 #x5F2D)
+                (#xD7BA #x5F38)
+                (#xD7BB #x5F41)
+                (#xD7BC #x5F48)
+                (#xD7BD #x5F4C)
+                (#xD7BE #x5F4E)
+                (#xD7BF #x5F2F)
+                (#xD7C0 #x5F51)
+                (#xD7C1 #x5F56)
+                (#xD7C2 #x5F57)
+                (#xD7C3 #x5F59)
+                (#xD7C4 #x5F61)
+                (#xD7C5 #x5F6D)
+                (#xD7C6 #x5F73)
+                (#xD7C7 #x5F77)
+                (#xD7C8 #x5F83)
+                (#xD7C9 #x5F82)
+                (#xD7CA #x5F7F)
+                (#xD7CB #x5F8A)
+                (#xD7CC #x5F88)
+                (#xD7CD #x5F91)
+                (#xD7CE #x5F87)
+                (#xD7CF #x5F9E)
+                (#xD7D0 #x5F99)
+                (#xD7D1 #x5F98)
+                (#xD7D2 #x5FA0)
+                (#xD7D3 #x5FA8)
+                (#xD7D4 #x5FAD)
+                (#xD7D5 #x5FBC)
+                (#xD7D6 #x5FD6)
+                (#xD7D7 #x5FFB)
+                (#xD7D8 #x5FE4)
+                (#xD7D9 #x5FF8)
+                (#xD7DA #x5FF1)
+                (#xD7DB #x5FDD)
+                (#xD7DC #x60B3)
+                (#xD7DD #x5FFF)
+                (#xD7DE #x6021)
+                (#xD7DF #x6060)
+                (#xD7E0 #x6019)
+                (#xD7E1 #x6010)
+                (#xD7E2 #x6029)
+                (#xD7E3 #x600E)
+                (#xD7E4 #x6031)
+                (#xD7E5 #x601B)
+                (#xD7E6 #x6015)
+                (#xD7E7 #x602B)
+                (#xD7E8 #x6026)
+                (#xD7E9 #x600F)
+                (#xD7EA #x603A)
+                (#xD7EB #x605A)
+                (#xD7EC #x6041)
+                (#xD7ED #x606A)
+                (#xD7EE #x6077)
+                (#xD7EF #x605F)
+                (#xD7F0 #x604A)
+                (#xD7F1 #x6046)
+                (#xD7F2 #x604D)
+                (#xD7F3 #x6063)
+                (#xD7F4 #x6043)
+                (#xD7F5 #x6064)
+                (#xD7F6 #x6042)
+                (#xD7F7 #x606C)
+                (#xD7F8 #x606B)
+                (#xD7F9 #x6059)
+                (#xD7FA #x6081)
+                (#xD7FB #x608D)
+                (#xD7FC #x60E7)
+                (#xD7FD #x6083)
+                (#xD7FE #x609A)
+                (#xD8A1 #x6084)
+                (#xD8A2 #x609B)
+                (#xD8A3 #x6096)
+                (#xD8A4 #x6097)
+                (#xD8A5 #x6092)
+                (#xD8A6 #x60A7)
+                (#xD8A7 #x608B)
+                (#xD8A8 #x60E1)
+                (#xD8A9 #x60B8)
+                (#xD8AA #x60E0)
+                (#xD8AB #x60D3)
+                (#xD8AC #x60B4)
+                (#xD8AD #x5FF0)
+                (#xD8AE #x60BD)
+                (#xD8AF #x60C6)
+                (#xD8B0 #x60B5)
+                (#xD8B1 #x60D8)
+                (#xD8B2 #x614D)
+                (#xD8B3 #x6115)
+                (#xD8B4 #x6106)
+                (#xD8B5 #x60F6)
+                (#xD8B6 #x60F7)
+                (#xD8B7 #x6100)
+                (#xD8B8 #x60F4)
+                (#xD8B9 #x60FA)
+                (#xD8BA #x6103)
+                (#xD8BB #x6121)
+                (#xD8BC #x60FB)
+                (#xD8BD #x60F1)
+                (#xD8BE #x610D)
+                (#xD8BF #x610E)
+                (#xD8C0 #x6147)
+                (#xD8C1 #x613E)
+                (#xD8C2 #x6128)
+                (#xD8C3 #x6127)
+                (#xD8C4 #x614A)
+                (#xD8C5 #x613F)
+                (#xD8C6 #x613C)
+                (#xD8C7 #x612C)
+                (#xD8C8 #x6134)
+                (#xD8C9 #x613D)
+                (#xD8CA #x6142)
+                (#xD8CB #x6144)
+                (#xD8CC #x6173)
+                (#xD8CD #x6177)
+                (#xD8CE #x6158)
+                (#xD8CF #x6159)
+                (#xD8D0 #x615A)
+                (#xD8D1 #x616B)
+                (#xD8D2 #x6174)
+                (#xD8D3 #x616F)
+                (#xD8D4 #x6165)
+                (#xD8D5 #x6171)
+                (#xD8D6 #x615F)
+                (#xD8D7 #x615D)
+                (#xD8D8 #x6153)
+                (#xD8D9 #x6175)
+                (#xD8DA #x6199)
+                (#xD8DB #x6196)
+                (#xD8DC #x6187)
+                (#xD8DD #x61AC)
+                (#xD8DE #x6194)
+                (#xD8DF #x619A)
+                (#xD8E0 #x618A)
+                (#xD8E1 #x6191)
+                (#xD8E2 #x61AB)
+                (#xD8E3 #x61AE)
+                (#xD8E4 #x61CC)
+                (#xD8E5 #x61CA)
+                (#xD8E6 #x61C9)
+                (#xD8E7 #x61F7)
+                (#xD8E8 #x61C8)
+                (#xD8E9 #x61C3)
+                (#xD8EA #x61C6)
+                (#xD8EB #x61BA)
+                (#xD8EC #x61CB)
+                (#xD8ED #x7F79)
+                (#xD8EE #x61CD)
+                (#xD8EF #x61E6)
+                (#xD8F0 #x61E3)
+                (#xD8F1 #x61F6)
+                (#xD8F2 #x61FA)
+                (#xD8F3 #x61F4)
+                (#xD8F4 #x61FF)
+                (#xD8F5 #x61FD)
+                (#xD8F6 #x61FC)
+                (#xD8F7 #x61FE)
+                (#xD8F8 #x6200)
+                (#xD8F9 #x6208)
+                (#xD8FA #x6209)
+                (#xD8FB #x620D)
+                (#xD8FC #x620C)
+                (#xD8FD #x6214)
+                (#xD8FE #x621B)
+                (#xD9A1 #x621E)
+                (#xD9A2 #x6221)
+                (#xD9A3 #x622A)
+                (#xD9A4 #x622E)
+                (#xD9A5 #x6230)
+                (#xD9A6 #x6232)
+                (#xD9A7 #x6233)
+                (#xD9A8 #x6241)
+                (#xD9A9 #x624E)
+                (#xD9AA #x625E)
+                (#xD9AB #x6263)
+                (#xD9AC #x625B)
+                (#xD9AD #x6260)
+                (#xD9AE #x6268)
+                (#xD9AF #x627C)
+                (#xD9B0 #x6282)
+                (#xD9B1 #x6289)
+                (#xD9B2 #x627E)
+                (#xD9B3 #x6292)
+                (#xD9B4 #x6293)
+                (#xD9B5 #x6296)
+                (#xD9B6 #x62D4)
+                (#xD9B7 #x6283)
+                (#xD9B8 #x6294)
+                (#xD9B9 #x62D7)
+                (#xD9BA #x62D1)
+                (#xD9BB #x62BB)
+                (#xD9BC #x62CF)
+                (#xD9BD #x62FF)
+                (#xD9BE #x62C6)
+                (#xD9BF #x64D4)
+                (#xD9C0 #x62C8)
+                (#xD9C1 #x62DC)
+                (#xD9C2 #x62CC)
+                (#xD9C3 #x62CA)
+                (#xD9C4 #x62C2)
+                (#xD9C5 #x62C7)
+                (#xD9C6 #x629B)
+                (#xD9C7 #x62C9)
+                (#xD9C8 #x630C)
+                (#xD9C9 #x62EE)
+                (#xD9CA #x62F1)
+                (#xD9CB #x6327)
+                (#xD9CC #x6302)
+                (#xD9CD #x6308)
+                (#xD9CE #x62EF)
+                (#xD9CF #x62F5)
+                (#xD9D0 #x6350)
+                (#xD9D1 #x633E)
+                (#xD9D2 #x634D)
+                (#xD9D3 #x641C)
+                (#xD9D4 #x634F)
+                (#xD9D5 #x6396)
+                (#xD9D6 #x638E)
+                (#xD9D7 #x6380)
+                (#xD9D8 #x63AB)
+                (#xD9D9 #x6376)
+                (#xD9DA #x63A3)
+                (#xD9DB #x638F)
+                (#xD9DC #x6389)
+                (#xD9DD #x639F)
+                (#xD9DE #x63B5)
+                (#xD9DF #x636B)
+                (#xD9E0 #x6369)
+                (#xD9E1 #x63BE)
+                (#xD9E2 #x63E9)
+                (#xD9E3 #x63C0)
+                (#xD9E4 #x63C6)
+                (#xD9E5 #x63E3)
+                (#xD9E6 #x63C9)
+                (#xD9E7 #x63D2)
+                (#xD9E8 #x63F6)
+                (#xD9E9 #x63C4)
+                (#xD9EA #x6416)
+                (#xD9EB #x6434)
+                (#xD9EC #x6406)
+                (#xD9ED #x6413)
+                (#xD9EE #x6426)
+                (#xD9EF #x6436)
+                (#xD9F0 #x651D)
+                (#xD9F1 #x6417)
+                (#xD9F2 #x6428)
+                (#xD9F3 #x640F)
+                (#xD9F4 #x6467)
+                (#xD9F5 #x646F)
+                (#xD9F6 #x6476)
+                (#xD9F7 #x644E)
+                (#xD9F8 #x652A)
+                (#xD9F9 #x6495)
+                (#xD9FA #x6493)
+                (#xD9FB #x64A5)
+                (#xD9FC #x64A9)
+                (#xD9FD #x6488)
+                (#xD9FE #x64BC)
+                (#xDAA1 #x64DA)
+                (#xDAA2 #x64D2)
+                (#xDAA3 #x64C5)
+                (#xDAA4 #x64C7)
+                (#xDAA5 #x64BB)
+                (#xDAA6 #x64D8)
+                (#xDAA7 #x64C2)
+                (#xDAA8 #x64F1)
+                (#xDAA9 #x64E7)
+                (#xDAAA #x8209)
+                (#xDAAB #x64E0)
+                (#xDAAC #x64E1)
+                (#xDAAD #x62AC)
+                (#xDAAE #x64E3)
+                (#xDAAF #x64EF)
+                (#xDAB0 #x652C)
+                (#xDAB1 #x64F6)
+                (#xDAB2 #x64F4)
+                (#xDAB3 #x64F2)
+                (#xDAB4 #x64FA)
+                (#xDAB5 #x6500)
+                (#xDAB6 #x64FD)
+                (#xDAB7 #x6518)
+                (#xDAB8 #x651C)
+                (#xDAB9 #x6505)
+                (#xDABA #x6524)
+                (#xDABB #x6523)
+                (#xDABC #x652B)
+                (#xDABD #x6534)
+                (#xDABE #x6535)
+                (#xDABF #x6537)
+                (#xDAC0 #x6536)
+                (#xDAC1 #x6538)
+                (#xDAC2 #x754B)
+                (#xDAC3 #x6548)
+                (#xDAC4 #x6556)
+                (#xDAC5 #x6555)
+                (#xDAC6 #x654D)
+                (#xDAC7 #x6558)
+                (#xDAC8 #x655E)
+                (#xDAC9 #x655D)
+                (#xDACA #x6572)
+                (#xDACB #x6578)
+                (#xDACC #x6582)
+                (#xDACD #x6583)
+                (#xDACE #x8B8A)
+                (#xDACF #x659B)
+                (#xDAD0 #x659F)
+                (#xDAD1 #x65AB)
+                (#xDAD2 #x65B7)
+                (#xDAD3 #x65C3)
+                (#xDAD4 #x65C6)
+                (#xDAD5 #x65C1)
+                (#xDAD6 #x65C4)
+                (#xDAD7 #x65CC)
+                (#xDAD8 #x65D2)
+                (#xDAD9 #x65DB)
+                (#xDADA #x65D9)
+                (#xDADB #x65E0)
+                (#xDADC #x65E1)
+                (#xDADD #x65F1)
+                (#xDADE #x6772)
+                (#xDADF #x660A)
+                (#xDAE0 #x6603)
+                (#xDAE1 #x65FB)
+                (#xDAE2 #x6773)
+                (#xDAE3 #x6635)
+                (#xDAE4 #x6636)
+                (#xDAE5 #x6634)
+                (#xDAE6 #x661C)
+                (#xDAE7 #x664F)
+                (#xDAE8 #x6644)
+                (#xDAE9 #x6649)
+                (#xDAEA #x6641)
+                (#xDAEB #x665E)
+                (#xDAEC #x665D)
+                (#xDAED #x6664)
+                (#xDAEE #x6667)
+                (#xDAEF #x6668)
+                (#xDAF0 #x665F)
+                (#xDAF1 #x6662)
+                (#xDAF2 #x6670)
+                (#xDAF3 #x6683)
+                (#xDAF4 #x6688)
+                (#xDAF5 #x668E)
+                (#xDAF6 #x6689)
+                (#xDAF7 #x6684)
+                (#xDAF8 #x6698)
+                (#xDAF9 #x669D)
+                (#xDAFA #x66C1)
+                (#xDAFB #x66B9)
+                (#xDAFC #x66C9)
+                (#xDAFD #x66BE)
+                (#xDAFE #x66BC)
+                (#xDBA1 #x66C4)
+                (#xDBA2 #x66B8)
+                (#xDBA3 #x66D6)
+                (#xDBA4 #x66DA)
+                (#xDBA5 #x66E0)
+                (#xDBA6 #x663F)
+                (#xDBA7 #x66E6)
+                (#xDBA8 #x66E9)
+                (#xDBA9 #x66F0)
+                (#xDBAA #x66F5)
+                (#xDBAB #x66F7)
+                (#xDBAC #x670F)
+                (#xDBAD #x6716)
+                (#xDBAE #x671E)
+                (#xDBAF #x6726)
+                (#xDBB0 #x6727)
+                (#xDBB1 #x9738)
+                (#xDBB2 #x672E)
+                (#xDBB3 #x673F)
+                (#xDBB4 #x6736)
+                (#xDBB5 #x6741)
+                (#xDBB6 #x6738)
+                (#xDBB7 #x6737)
+                (#xDBB8 #x6746)
+                (#xDBB9 #x675E)
+                (#xDBBA #x6760)
+                (#xDBBB #x6759)
+                (#xDBBC #x6763)
+                (#xDBBD #x6764)
+                (#xDBBE #x6789)
+                (#xDBBF #x6770)
+                (#xDBC0 #x67A9)
+                (#xDBC1 #x677C)
+                (#xDBC2 #x676A)
+                (#xDBC3 #x678C)
+                (#xDBC4 #x678B)
+                (#xDBC5 #x67A6)
+                (#xDBC6 #x67A1)
+                (#xDBC7 #x6785)
+                (#xDBC8 #x67B7)
+                (#xDBC9 #x67EF)
+                (#xDBCA #x67B4)
+                (#xDBCB #x67EC)
+                (#xDBCC #x67B3)
+                (#xDBCD #x67E9)
+                (#xDBCE #x67B8)
+                (#xDBCF #x67E4)
+                (#xDBD0 #x67DE)
+                (#xDBD1 #x67DD)
+                (#xDBD2 #x67E2)
+                (#xDBD3 #x67EE)
+                (#xDBD4 #x67B9)
+                (#xDBD5 #x67CE)
+                (#xDBD6 #x67C6)
+                (#xDBD7 #x67E7)
+                (#xDBD8 #x6A9C)
+                (#xDBD9 #x681E)
+                (#xDBDA #x6846)
+                (#xDBDB #x6829)
+                (#xDBDC #x6840)
+                (#xDBDD #x684D)
+                (#xDBDE #x6832)
+                (#xDBDF #x684E)
+                (#xDBE0 #x68B3)
+                (#xDBE1 #x682B)
+                (#xDBE2 #x6859)
+                (#xDBE3 #x6863)
+                (#xDBE4 #x6877)
+                (#xDBE5 #x687F)
+                (#xDBE6 #x689F)
+                (#xDBE7 #x688F)
+                (#xDBE8 #x68AD)
+                (#xDBE9 #x6894)
+                (#xDBEA #x689D)
+                (#xDBEB #x689B)
+                (#xDBEC #x6883)
+                (#xDBED #x6AAE)
+                (#xDBEE #x68B9)
+                (#xDBEF #x6874)
+                (#xDBF0 #x68B5)
+                (#xDBF1 #x68A0)
+                (#xDBF2 #x68BA)
+                (#xDBF3 #x690F)
+                (#xDBF4 #x688D)
+                (#xDBF5 #x687E)
+                (#xDBF6 #x6901)
+                (#xDBF7 #x68CA)
+                (#xDBF8 #x6908)
+                (#xDBF9 #x68D8)
+                (#xDBFA #x6922)
+                (#xDBFB #x6926)
+                (#xDBFC #x68E1)
+                (#xDBFD #x690C)
+                (#xDBFE #x68CD)
+                (#xDCA1 #x68D4)
+                (#xDCA2 #x68E7)
+                (#xDCA3 #x68D5)
+                (#xDCA4 #x6936)
+                (#xDCA5 #x6912)
+                (#xDCA6 #x6904)
+                (#xDCA7 #x68D7)
+                (#xDCA8 #x68E3)
+                (#xDCA9 #x6925)
+                (#xDCAA #x68F9)
+                (#xDCAB #x68E0)
+                (#xDCAC #x68EF)
+                (#xDCAD #x6928)
+                (#xDCAE #x692A)
+                (#xDCAF #x691A)
+                (#xDCB0 #x6923)
+                (#xDCB1 #x6921)
+                (#xDCB2 #x68C6)
+                (#xDCB3 #x6979)
+                (#xDCB4 #x6977)
+                (#xDCB5 #x695C)
+                (#xDCB6 #x6978)
+                (#xDCB7 #x696B)
+                (#xDCB8 #x6954)
+                (#xDCB9 #x697E)
+                (#xDCBA #x696E)
+                (#xDCBB #x6939)
+                (#xDCBC #x6974)
+                (#xDCBD #x693D)
+                (#xDCBE #x6959)
+                (#xDCBF #x6930)
+                (#xDCC0 #x6961)
+                (#xDCC1 #x695E)
+                (#xDCC2 #x695D)
+                (#xDCC3 #x6981)
+                (#xDCC4 #x696A)
+                (#xDCC5 #x69B2)
+                (#xDCC6 #x69AE)
+                (#xDCC7 #x69D0)
+                (#xDCC8 #x69BF)
+                (#xDCC9 #x69C1)
+                (#xDCCA #x69D3)
+                (#xDCCB #x69BE)
+                (#xDCCC #x69CE)
+                (#xDCCD #x5BE8)
+                (#xDCCE #x69CA)
+                (#xDCCF #x69DD)
+                (#xDCD0 #x69BB)
+                (#xDCD1 #x69C3)
+                (#xDCD2 #x69A7)
+                (#xDCD3 #x6A2E)
+                (#xDCD4 #x6991)
+                (#xDCD5 #x69A0)
+                (#xDCD6 #x699C)
+                (#xDCD7 #x6995)
+                (#xDCD8 #x69B4)
+                (#xDCD9 #x69DE)
+                (#xDCDA #x69E8)
+                (#xDCDB #x6A02)
+                (#xDCDC #x6A1B)
+                (#xDCDD #x69FF)
+                (#xDCDE #x6B0A)
+                (#xDCDF #x69F9)
+                (#xDCE0 #x69F2)
+                (#xDCE1 #x69E7)
+                (#xDCE2 #x6A05)
+                (#xDCE3 #x69B1)
+                (#xDCE4 #x6A1E)
+                (#xDCE5 #x69ED)
+                (#xDCE6 #x6A14)
+                (#xDCE7 #x69EB)
+                (#xDCE8 #x6A0A)
+                (#xDCE9 #x6A12)
+                (#xDCEA #x6AC1)
+                (#xDCEB #x6A23)
+                (#xDCEC #x6A13)
+                (#xDCED #x6A44)
+                (#xDCEE #x6A0C)
+                (#xDCEF #x6A72)
+                (#xDCF0 #x6A36)
+                (#xDCF1 #x6A78)
+                (#xDCF2 #x6A47)
+                (#xDCF3 #x6A62)
+                (#xDCF4 #x6A59)
+                (#xDCF5 #x6A66)
+                (#xDCF6 #x6A48)
+                (#xDCF7 #x6A38)
+                (#xDCF8 #x6A22)
+                (#xDCF9 #x6A90)
+                (#xDCFA #x6A8D)
+                (#xDCFB #x6AA0)
+                (#xDCFC #x6A84)
+                (#xDCFD #x6AA2)
+                (#xDCFE #x6AA3)
+                (#xDDA1 #x6A97)
+                (#xDDA2 #x8617)
+                (#xDDA3 #x6ABB)
+                (#xDDA4 #x6AC3)
+                (#xDDA5 #x6AC2)
+                (#xDDA6 #x6AB8)
+                (#xDDA7 #x6AB3)
+                (#xDDA8 #x6AAC)
+                (#xDDA9 #x6ADE)
+                (#xDDAA #x6AD1)
+                (#xDDAB #x6ADF)
+                (#xDDAC #x6AAA)
+                (#xDDAD #x6ADA)
+                (#xDDAE #x6AEA)
+                (#xDDAF #x6AFB)
+                (#xDDB0 #x6B05)
+                (#xDDB1 #x8616)
+                (#xDDB2 #x6AFA)
+                (#xDDB3 #x6B12)
+                (#xDDB4 #x6B16)
+                (#xDDB5 #x9B31)
+                (#xDDB6 #x6B1F)
+                (#xDDB7 #x6B38)
+                (#xDDB8 #x6B37)
+                (#xDDB9 #x76DC)
+                (#xDDBA #x6B39)
+                (#xDDBB #x98EE)
+                (#xDDBC #x6B47)
+                (#xDDBD #x6B43)
+                (#xDDBE #x6B49)
+                (#xDDBF #x6B50)
+                (#xDDC0 #x6B59)
+                (#xDDC1 #x6B54)
+                (#xDDC2 #x6B5B)
+                (#xDDC3 #x6B5F)
+                (#xDDC4 #x6B61)
+                (#xDDC5 #x6B78)
+                (#xDDC6 #x6B79)
+                (#xDDC7 #x6B7F)
+                (#xDDC8 #x6B80)
+                (#xDDC9 #x6B84)
+                (#xDDCA #x6B83)
+                (#xDDCB #x6B8D)
+                (#xDDCC #x6B98)
+                (#xDDCD #x6B95)
+                (#xDDCE #x6B9E)
+                (#xDDCF #x6BA4)
+                (#xDDD0 #x6BAA)
+                (#xDDD1 #x6BAB)
+                (#xDDD2 #x6BAF)
+                (#xDDD3 #x6BB2)
+                (#xDDD4 #x6BB1)
+                (#xDDD5 #x6BB3)
+                (#xDDD6 #x6BB7)
+                (#xDDD7 #x6BBC)
+                (#xDDD8 #x6BC6)
+                (#xDDD9 #x6BCB)
+                (#xDDDA #x6BD3)
+                (#xDDDB #x6BDF)
+                (#xDDDC #x6BEC)
+                (#xDDDD #x6BEB)
+                (#xDDDE #x6BF3)
+                (#xDDDF #x6BEF)
+                (#xDDE0 #x9EBE)
+                (#xDDE1 #x6C08)
+                (#xDDE2 #x6C13)
+                (#xDDE3 #x6C14)
+                (#xDDE4 #x6C1B)
+                (#xDDE5 #x6C24)
+                (#xDDE6 #x6C23)
+                (#xDDE7 #x6C5E)
+                (#xDDE8 #x6C55)
+                (#xDDE9 #x6C62)
+                (#xDDEA #x6C6A)
+                (#xDDEB #x6C82)
+                (#xDDEC #x6C8D)
+                (#xDDED #x6C9A)
+                (#xDDEE #x6C81)
+                (#xDDEF #x6C9B)
+                (#xDDF0 #x6C7E)
+                (#xDDF1 #x6C68)
+                (#xDDF2 #x6C73)
+                (#xDDF3 #x6C92)
+                (#xDDF4 #x6C90)
+                (#xDDF5 #x6CC4)
+                (#xDDF6 #x6CF1)
+                (#xDDF7 #x6CD3)
+                (#xDDF8 #x6CBD)
+                (#xDDF9 #x6CD7)
+                (#xDDFA #x6CC5)
+                (#xDDFB #x6CDD)
+                (#xDDFC #x6CAE)
+                (#xDDFD #x6CB1)
+                (#xDDFE #x6CBE)
+                (#xDEA1 #x6CBA)
+                (#xDEA2 #x6CDB)
+                (#xDEA3 #x6CEF)
+                (#xDEA4 #x6CD9)
+                (#xDEA5 #x6CEA)
+                (#xDEA6 #x6D1F)
+                (#xDEA7 #x884D)
+                (#xDEA8 #x6D36)
+                (#xDEA9 #x6D2B)
+                (#xDEAA #x6D3D)
+                (#xDEAB #x6D38)
+                (#xDEAC #x6D19)
+                (#xDEAD #x6D35)
+                (#xDEAE #x6D33)
+                (#xDEAF #x6D12)
+                (#xDEB0 #x6D0C)
+                (#xDEB1 #x6D63)
+                (#xDEB2 #x6D93)
+                (#xDEB3 #x6D64)
+                (#xDEB4 #x6D5A)
+                (#xDEB5 #x6D79)
+                (#xDEB6 #x6D59)
+                (#xDEB7 #x6D8E)
+                (#xDEB8 #x6D95)
+                (#xDEB9 #x6FE4)
+                (#xDEBA #x6D85)
+                (#xDEBB #x6DF9)
+                (#xDEBC #x6E15)
+                (#xDEBD #x6E0A)
+                (#xDEBE #x6DB5)
+                (#xDEBF #x6DC7)
+                (#xDEC0 #x6DE6)
+                (#xDEC1 #x6DB8)
+                (#xDEC2 #x6DC6)
+                (#xDEC3 #x6DEC)
+                (#xDEC4 #x6DDE)
+                (#xDEC5 #x6DCC)
+                (#xDEC6 #x6DE8)
+                (#xDEC7 #x6DD2)
+                (#xDEC8 #x6DC5)
+                (#xDEC9 #x6DFA)
+                (#xDECA #x6DD9)
+                (#xDECB #x6DE4)
+                (#xDECC #x6DD5)
+                (#xDECD #x6DEA)
+                (#xDECE #x6DEE)
+                (#xDECF #x6E2D)
+                (#xDED0 #x6E6E)
+                (#xDED1 #x6E2E)
+                (#xDED2 #x6E19)
+                (#xDED3 #x6E72)
+                (#xDED4 #x6E5F)
+                (#xDED5 #x6E3E)
+                (#xDED6 #x6E23)
+                (#xDED7 #x6E6B)
+                (#xDED8 #x6E2B)
+                (#xDED9 #x6E76)
+                (#xDEDA #x6E4D)
+                (#xDEDB #x6E1F)
+                (#xDEDC #x6E43)
+                (#xDEDD #x6E3A)
+                (#xDEDE #x6E4E)
+                (#xDEDF #x6E24)
+                (#xDEE0 #x6EFF)
+                (#xDEE1 #x6E1D)
+                (#xDEE2 #x6E38)
+                (#xDEE3 #x6E82)
+                (#xDEE4 #x6EAA)
+                (#xDEE5 #x6E98)
+                (#xDEE6 #x6EC9)
+                (#xDEE7 #x6EB7)
+                (#xDEE8 #x6ED3)
+                (#xDEE9 #x6EBD)
+                (#xDEEA #x6EAF)
+                (#xDEEB #x6EC4)
+                (#xDEEC #x6EB2)
+                (#xDEED #x6ED4)
+                (#xDEEE #x6ED5)
+                (#xDEEF #x6E8F)
+                (#xDEF0 #x6EA5)
+                (#xDEF1 #x6EC2)
+                (#xDEF2 #x6E9F)
+                (#xDEF3 #x6F41)
+                (#xDEF4 #x6F11)
+                (#xDEF5 #x704C)
+                (#xDEF6 #x6EEC)
+                (#xDEF7 #x6EF8)
+                (#xDEF8 #x6EFE)
+                (#xDEF9 #x6F3F)
+                (#xDEFA #x6EF2)
+                (#xDEFB #x6F31)
+                (#xDEFC #x6EEF)
+                (#xDEFD #x6F32)
+                (#xDEFE #x6ECC)
+                (#xDFA1 #x6F3E)
+                (#xDFA2 #x6F13)
+                (#xDFA3 #x6EF7)
+                (#xDFA4 #x6F86)
+                (#xDFA5 #x6F7A)
+                (#xDFA6 #x6F78)
+                (#xDFA7 #x6F81)
+                (#xDFA8 #x6F80)
+                (#xDFA9 #x6F6F)
+                (#xDFAA #x6F5B)
+                (#xDFAB #x6FF3)
+                (#xDFAC #x6F6D)
+                (#xDFAD #x6F82)
+                (#xDFAE #x6F7C)
+                (#xDFAF #x6F58)
+                (#xDFB0 #x6F8E)
+                (#xDFB1 #x6F91)
+                (#xDFB2 #x6FC2)
+                (#xDFB3 #x6F66)
+                (#xDFB4 #x6FB3)
+                (#xDFB5 #x6FA3)
+                (#xDFB6 #x6FA1)
+                (#xDFB7 #x6FA4)
+                (#xDFB8 #x6FB9)
+                (#xDFB9 #x6FC6)
+                (#xDFBA #x6FAA)
+                (#xDFBB #x6FDF)
+                (#xDFBC #x6FD5)
+                (#xDFBD #x6FEC)
+                (#xDFBE #x6FD4)
+                (#xDFBF #x6FD8)
+                (#xDFC0 #x6FF1)
+                (#xDFC1 #x6FEE)
+                (#xDFC2 #x6FDB)
+                (#xDFC3 #x7009)
+                (#xDFC4 #x700B)
+                (#xDFC5 #x6FFA)
+                (#xDFC6 #x7011)
+                (#xDFC7 #x7001)
+                (#xDFC8 #x700F)
+                (#xDFC9 #x6FFE)
+                (#xDFCA #x701B)
+                (#xDFCB #x701A)
+                (#xDFCC #x6F74)
+                (#xDFCD #x701D)
+                (#xDFCE #x7018)
+                (#xDFCF #x701F)
+                (#xDFD0 #x7030)
+                (#xDFD1 #x703E)
+                (#xDFD2 #x7032)
+                (#xDFD3 #x7051)
+                (#xDFD4 #x7063)
+                (#xDFD5 #x7099)
+                (#xDFD6 #x7092)
+                (#xDFD7 #x70AF)
+                (#xDFD8 #x70F1)
+                (#xDFD9 #x70AC)
+                (#xDFDA #x70B8)
+                (#xDFDB #x70B3)
+                (#xDFDC #x70AE)
+                (#xDFDD #x70DF)
+                (#xDFDE #x70CB)
+                (#xDFDF #x70DD)
+                (#xDFE0 #x70D9)
+                (#xDFE1 #x7109)
+                (#xDFE2 #x70FD)
+                (#xDFE3 #x711C)
+                (#xDFE4 #x7119)
+                (#xDFE5 #x7165)
+                (#xDFE6 #x7155)
+                (#xDFE7 #x7188)
+                (#xDFE8 #x7166)
+                (#xDFE9 #x7162)
+                (#xDFEA #x714C)
+                (#xDFEB #x7156)
+                (#xDFEC #x716C)
+                (#xDFED #x718F)
+                (#xDFEE #x71FB)
+                (#xDFEF #x7184)
+                (#xDFF0 #x7195)
+                (#xDFF1 #x71A8)
+                (#xDFF2 #x71AC)
+                (#xDFF3 #x71D7)
+                (#xDFF4 #x71B9)
+                (#xDFF5 #x71BE)
+                (#xDFF6 #x71D2)
+                (#xDFF7 #x71C9)
+                (#xDFF8 #x71D4)
+                (#xDFF9 #x71CE)
+                (#xDFFA #x71E0)
+                (#xDFFB #x71EC)
+                (#xDFFC #x71E7)
+                (#xDFFD #x71F5)
+                (#xDFFE #x71FC)
+                (#xE0A1 #x71F9)
+                (#xE0A2 #x71FF)
+                (#xE0A3 #x720D)
+                (#xE0A4 #x7210)
+                (#xE0A5 #x721B)
+                (#xE0A6 #x7228)
+                (#xE0A7 #x722D)
+                (#xE0A8 #x722C)
+                (#xE0A9 #x7230)
+                (#xE0AA #x7232)
+                (#xE0AB #x723B)
+                (#xE0AC #x723C)
+                (#xE0AD #x723F)
+                (#xE0AE #x7240)
+                (#xE0AF #x7246)
+                (#xE0B0 #x724B)
+                (#xE0B1 #x7258)
+                (#xE0B2 #x7274)
+                (#xE0B3 #x727E)
+                (#xE0B4 #x7282)
+                (#xE0B5 #x7281)
+                (#xE0B6 #x7287)
+                (#xE0B7 #x7292)
+                (#xE0B8 #x7296)
+                (#xE0B9 #x72A2)
+                (#xE0BA #x72A7)
+                (#xE0BB #x72B9)
+                (#xE0BC #x72B2)
+                (#xE0BD #x72C3)
+                (#xE0BE #x72C6)
+                (#xE0BF #x72C4)
+                (#xE0C0 #x72CE)
+                (#xE0C1 #x72D2)
+                (#xE0C2 #x72E2)
+                (#xE0C3 #x72E0)
+                (#xE0C4 #x72E1)
+                (#xE0C5 #x72F9)
+                (#xE0C6 #x72F7)
+                (#xE0C7 #x500F)
+                (#xE0C8 #x7317)
+                (#xE0C9 #x730A)
+                (#xE0CA #x731C)
+                (#xE0CB #x7316)
+                (#xE0CC #x731D)
+                (#xE0CD #x7334)
+                (#xE0CE #x732F)
+                (#xE0CF #x7329)
+                (#xE0D0 #x7325)
+                (#xE0D1 #x733E)
+                (#xE0D2 #x734E)
+                (#xE0D3 #x734F)
+                (#xE0D4 #x9ED8)
+                (#xE0D5 #x7357)
+                (#xE0D6 #x736A)
+                (#xE0D7 #x7368)
+                (#xE0D8 #x7370)
+                (#xE0D9 #x7378)
+                (#xE0DA #x7375)
+                (#xE0DB #x737B)
+                (#xE0DC #x737A)
+                (#xE0DD #x73C8)
+                (#xE0DE #x73B3)
+                (#xE0DF #x73CE)
+                (#xE0E0 #x73BB)
+                (#xE0E1 #x73C0)
+                (#xE0E2 #x73E5)
+                (#xE0E3 #x73EE)
+                (#xE0E4 #x73DE)
+                (#xE0E5 #x74A2)
+                (#xE0E6 #x7405)
+                (#xE0E7 #x746F)
+                (#xE0E8 #x7425)
+                (#xE0E9 #x73F8)
+                (#xE0EA #x7432)
+                (#xE0EB #x743A)
+                (#xE0EC #x7455)
+                (#xE0ED #x743F)
+                (#xE0EE #x745F)
+                (#xE0EF #x7459)
+                (#xE0F0 #x7441)
+                (#xE0F1 #x745C)
+                (#xE0F2 #x7469)
+                (#xE0F3 #x7470)
+                (#xE0F4 #x7463)
+                (#xE0F5 #x746A)
+                (#xE0F6 #x7476)
+                (#xE0F7 #x747E)
+                (#xE0F8 #x748B)
+                (#xE0F9 #x749E)
+                (#xE0FA #x74A7)
+                (#xE0FB #x74CA)
+                (#xE0FC #x74CF)
+                (#xE0FD #x74D4)
+                (#xE0FE #x73F1)
+                (#xE1A1 #x74E0)
+                (#xE1A2 #x74E3)
+                (#xE1A3 #x74E7)
+                (#xE1A4 #x74E9)
+                (#xE1A5 #x74EE)
+                (#xE1A6 #x74F2)
+                (#xE1A7 #x74F0)
+                (#xE1A8 #x74F1)
+                (#xE1A9 #x74F8)
+                (#xE1AA #x74F7)
+                (#xE1AB #x7504)
+                (#xE1AC #x7503)
+                (#xE1AD #x7505)
+                (#xE1AE #x750C)
+                (#xE1AF #x750E)
+                (#xE1B0 #x750D)
+                (#xE1B1 #x7515)
+                (#xE1B2 #x7513)
+                (#xE1B3 #x751E)
+                (#xE1B4 #x7526)
+                (#xE1B5 #x752C)
+                (#xE1B6 #x753C)
+                (#xE1B7 #x7544)
+                (#xE1B8 #x754D)
+                (#xE1B9 #x754A)
+                (#xE1BA #x7549)
+                (#xE1BB #x755B)
+                (#xE1BC #x7546)
+                (#xE1BD #x755A)
+                (#xE1BE #x7569)
+                (#xE1BF #x7564)
+                (#xE1C0 #x7567)
+                (#xE1C1 #x756B)
+                (#xE1C2 #x756D)
+                (#xE1C3 #x7578)
+                (#xE1C4 #x7576)
+                (#xE1C5 #x7586)
+                (#xE1C6 #x7587)
+                (#xE1C7 #x7574)
+                (#xE1C8 #x758A)
+                (#xE1C9 #x7589)
+                (#xE1CA #x7582)
+                (#xE1CB #x7594)
+                (#xE1CC #x759A)
+                (#xE1CD #x759D)
+                (#xE1CE #x75A5)
+                (#xE1CF #x75A3)
+                (#xE1D0 #x75C2)
+                (#xE1D1 #x75B3)
+                (#xE1D2 #x75C3)
+                (#xE1D3 #x75B5)
+                (#xE1D4 #x75BD)
+                (#xE1D5 #x75B8)
+                (#xE1D6 #x75BC)
+                (#xE1D7 #x75B1)
+                (#xE1D8 #x75CD)
+                (#xE1D9 #x75CA)
+                (#xE1DA #x75D2)
+                (#xE1DB #x75D9)
+                (#xE1DC #x75E3)
+                (#xE1DD #x75DE)
+                (#xE1DE #x75FE)
+                (#xE1DF #x75FF)
+                (#xE1E0 #x75FC)
+                (#xE1E1 #x7601)
+                (#xE1E2 #x75F0)
+                (#xE1E3 #x75FA)
+                (#xE1E4 #x75F2)
+                (#xE1E5 #x75F3)
+                (#xE1E6 #x760B)
+                (#xE1E7 #x760D)
+                (#xE1E8 #x7609)
+                (#xE1E9 #x761F)
+                (#xE1EA #x7627)
+                (#xE1EB #x7620)
+                (#xE1EC #x7621)
+                (#xE1ED #x7622)
+                (#xE1EE #x7624)
+                (#xE1EF #x7634)
+                (#xE1F0 #x7630)
+                (#xE1F1 #x763B)
+                (#xE1F2 #x7647)
+                (#xE1F3 #x7648)
+                (#xE1F4 #x7646)
+                (#xE1F5 #x765C)
+                (#xE1F6 #x7658)
+                (#xE1F7 #x7661)
+                (#xE1F8 #x7662)
+                (#xE1F9 #x7668)
+                (#xE1FA #x7669)
+                (#xE1FB #x766A)
+                (#xE1FC #x7667)
+                (#xE1FD #x766C)
+                (#xE1FE #x7670)
+                (#xE2A1 #x7672)
+                (#xE2A2 #x7676)
+                (#xE2A3 #x7678)
+                (#xE2A4 #x767C)
+                (#xE2A5 #x7680)
+                (#xE2A6 #x7683)
+                (#xE2A7 #x7688)
+                (#xE2A8 #x768B)
+                (#xE2A9 #x768E)
+                (#xE2AA #x7696)
+                (#xE2AB #x7693)
+                (#xE2AC #x7699)
+                (#xE2AD #x769A)
+                (#xE2AE #x76B0)
+                (#xE2AF #x76B4)
+                (#xE2B0 #x76B8)
+                (#xE2B1 #x76B9)
+                (#xE2B2 #x76BA)
+                (#xE2B3 #x76C2)
+                (#xE2B4 #x76CD)
+                (#xE2B5 #x76D6)
+                (#xE2B6 #x76D2)
+                (#xE2B7 #x76DE)
+                (#xE2B8 #x76E1)
+                (#xE2B9 #x76E5)
+                (#xE2BA #x76E7)
+                (#xE2BB #x76EA)
+                (#xE2BC #x862F)
+                (#xE2BD #x76FB)
+                (#xE2BE #x7708)
+                (#xE2BF #x7707)
+                (#xE2C0 #x7704)
+                (#xE2C1 #x7729)
+                (#xE2C2 #x7724)
+                (#xE2C3 #x771E)
+                (#xE2C4 #x7725)
+                (#xE2C5 #x7726)
+                (#xE2C6 #x771B)
+                (#xE2C7 #x7737)
+                (#xE2C8 #x7738)
+                (#xE2C9 #x7747)
+                (#xE2CA #x775A)
+                (#xE2CB #x7768)
+                (#xE2CC #x776B)
+                (#xE2CD #x775B)
+                (#xE2CE #x7765)
+                (#xE2CF #x777F)
+                (#xE2D0 #x777E)
+                (#xE2D1 #x7779)
+                (#xE2D2 #x778E)
+                (#xE2D3 #x778B)
+                (#xE2D4 #x7791)
+                (#xE2D5 #x77A0)
+                (#xE2D6 #x779E)
+                (#xE2D7 #x77B0)
+                (#xE2D8 #x77B6)
+                (#xE2D9 #x77B9)
+                (#xE2DA #x77BF)
+                (#xE2DB #x77BC)
+                (#xE2DC #x77BD)
+                (#xE2DD #x77BB)
+                (#xE2DE #x77C7)
+                (#xE2DF #x77CD)
+                (#xE2E0 #x77D7)
+                (#xE2E1 #x77DA)
+                (#xE2E2 #x77DC)
+                (#xE2E3 #x77E3)
+                (#xE2E4 #x77EE)
+                (#xE2E5 #x77FC)
+                (#xE2E6 #x780C)
+                (#xE2E7 #x7812)
+                (#xE2E8 #x7926)
+                (#xE2E9 #x7820)
+                (#xE2EA #x792A)
+                (#xE2EB #x7845)
+                (#xE2EC #x788E)
+                (#xE2ED #x7874)
+                (#xE2EE #x7886)
+                (#xE2EF #x787C)
+                (#xE2F0 #x789A)
+                (#xE2F1 #x788C)
+                (#xE2F2 #x78A3)
+                (#xE2F3 #x78B5)
+                (#xE2F4 #x78AA)
+                (#xE2F5 #x78AF)
+                (#xE2F6 #x78D1)
+                (#xE2F7 #x78C6)
+                (#xE2F8 #x78CB)
+                (#xE2F9 #x78D4)
+                (#xE2FA #x78BE)
+                (#xE2FB #x78BC)
+                (#xE2FC #x78C5)
+                (#xE2FD #x78CA)
+                (#xE2FE #x78EC)
+                (#xE3A1 #x78E7)
+                (#xE3A2 #x78DA)
+                (#xE3A3 #x78FD)
+                (#xE3A4 #x78F4)
+                (#xE3A5 #x7907)
+                (#xE3A6 #x7912)
+                (#xE3A7 #x7911)
+                (#xE3A8 #x7919)
+                (#xE3A9 #x792C)
+                (#xE3AA #x792B)
+                (#xE3AB #x7940)
+                (#xE3AC #x7960)
+                (#xE3AD #x7957)
+                (#xE3AE #x795F)
+                (#xE3AF #x795A)
+                (#xE3B0 #x7955)
+                (#xE3B1 #x7953)
+                (#xE3B2 #x797A)
+                (#xE3B3 #x797F)
+                (#xE3B4 #x798A)
+                (#xE3B5 #x799D)
+                (#xE3B6 #x79A7)
+                (#xE3B7 #x9F4B)
+                (#xE3B8 #x79AA)
+                (#xE3B9 #x79AE)
+                (#xE3BA #x79B3)
+                (#xE3BB #x79B9)
+                (#xE3BC #x79BA)
+                (#xE3BD #x79C9)
+                (#xE3BE #x79D5)
+                (#xE3BF #x79E7)
+                (#xE3C0 #x79EC)
+                (#xE3C1 #x79E1)
+                (#xE3C2 #x79E3)
+                (#xE3C3 #x7A08)
+                (#xE3C4 #x7A0D)
+                (#xE3C5 #x7A18)
+                (#xE3C6 #x7A19)
+                (#xE3C7 #x7A20)
+                (#xE3C8 #x7A1F)
+                (#xE3C9 #x7980)
+                (#xE3CA #x7A31)
+                (#xE3CB #x7A3B)
+                (#xE3CC #x7A3E)
+                (#xE3CD #x7A37)
+                (#xE3CE #x7A43)
+                (#xE3CF #x7A57)
+                (#xE3D0 #x7A49)
+                (#xE3D1 #x7A61)
+                (#xE3D2 #x7A62)
+                (#xE3D3 #x7A69)
+                (#xE3D4 #x9F9D)
+                (#xE3D5 #x7A70)
+                (#xE3D6 #x7A79)
+                (#xE3D7 #x7A7D)
+                (#xE3D8 #x7A88)
+                (#xE3D9 #x7A97)
+                (#xE3DA #x7A95)
+                (#xE3DB #x7A98)
+                (#xE3DC #x7A96)
+                (#xE3DD #x7AA9)
+                (#xE3DE #x7AC8)
+                (#xE3DF #x7AB0)
+                (#xE3E0 #x7AB6)
+                (#xE3E1 #x7AC5)
+                (#xE3E2 #x7AC4)
+                (#xE3E3 #x7ABF)
+                (#xE3E4 #x9083)
+                (#xE3E5 #x7AC7)
+                (#xE3E6 #x7ACA)
+                (#xE3E7 #x7ACD)
+                (#xE3E8 #x7ACF)
+                (#xE3E9 #x7AD5)
+                (#xE3EA #x7AD3)
+                (#xE3EB #x7AD9)
+                (#xE3EC #x7ADA)
+                (#xE3ED #x7ADD)
+                (#xE3EE #x7AE1)
+                (#xE3EF #x7AE2)
+                (#xE3F0 #x7AE6)
+                (#xE3F1 #x7AED)
+                (#xE3F2 #x7AF0)
+                (#xE3F3 #x7B02)
+                (#xE3F4 #x7B0F)
+                (#xE3F5 #x7B0A)
+                (#xE3F6 #x7B06)
+                (#xE3F7 #x7B33)
+                (#xE3F8 #x7B18)
+                (#xE3F9 #x7B19)
+                (#xE3FA #x7B1E)
+                (#xE3FB #x7B35)
+                (#xE3FC #x7B28)
+                (#xE3FD #x7B36)
+                (#xE3FE #x7B50)
+                (#xE4A1 #x7B7A)
+                (#xE4A2 #x7B04)
+                (#xE4A3 #x7B4D)
+                (#xE4A4 #x7B0B)
+                (#xE4A5 #x7B4C)
+                (#xE4A6 #x7B45)
+                (#xE4A7 #x7B75)
+                (#xE4A8 #x7B65)
+                (#xE4A9 #x7B74)
+                (#xE4AA #x7B67)
+                (#xE4AB #x7B70)
+                (#xE4AC #x7B71)
+                (#xE4AD #x7B6C)
+                (#xE4AE #x7B6E)
+                (#xE4AF #x7B9D)
+                (#xE4B0 #x7B98)
+                (#xE4B1 #x7B9F)
+                (#xE4B2 #x7B8D)
+                (#xE4B3 #x7B9C)
+                (#xE4B4 #x7B9A)
+                (#xE4B5 #x7B8B)
+                (#xE4B6 #x7B92)
+                (#xE4B7 #x7B8F)
+                (#xE4B8 #x7B5D)
+                (#xE4B9 #x7B99)
+                (#xE4BA #x7BCB)
+                (#xE4BB #x7BC1)
+                (#xE4BC #x7BCC)
+                (#xE4BD #x7BCF)
+                (#xE4BE #x7BB4)
+                (#xE4BF #x7BC6)
+                (#xE4C0 #x7BDD)
+                (#xE4C1 #x7BE9)
+                (#xE4C2 #x7C11)
+                (#xE4C3 #x7C14)
+                (#xE4C4 #x7BE6)
+                (#xE4C5 #x7BE5)
+                (#xE4C6 #x7C60)
+                (#xE4C7 #x7C00)
+                (#xE4C8 #x7C07)
+                (#xE4C9 #x7C13)
+                (#xE4CA #x7BF3)
+                (#xE4CB #x7BF7)
+                (#xE4CC #x7C17)
+                (#xE4CD #x7C0D)
+                (#xE4CE #x7BF6)
+                (#xE4CF #x7C23)
+                (#xE4D0 #x7C27)
+                (#xE4D1 #x7C2A)
+                (#xE4D2 #x7C1F)
+                (#xE4D3 #x7C37)
+                (#xE4D4 #x7C2B)
+                (#xE4D5 #x7C3D)
+                (#xE4D6 #x7C4C)
+                (#xE4D7 #x7C43)
+                (#xE4D8 #x7C54)
+                (#xE4D9 #x7C4F)
+                (#xE4DA #x7C40)
+                (#xE4DB #x7C50)
+                (#xE4DC #x7C58)
+                (#xE4DD #x7C5F)
+                (#xE4DE #x7C64)
+                (#xE4DF #x7C56)
+                (#xE4E0 #x7C65)
+                (#xE4E1 #x7C6C)
+                (#xE4E2 #x7C75)
+                (#xE4E3 #x7C83)
+                (#xE4E4 #x7C90)
+                (#xE4E5 #x7CA4)
+                (#xE4E6 #x7CAD)
+                (#xE4E7 #x7CA2)
+                (#xE4E8 #x7CAB)
+                (#xE4E9 #x7CA1)
+                (#xE4EA #x7CA8)
+                (#xE4EB #x7CB3)
+                (#xE4EC #x7CB2)
+                (#xE4ED #x7CB1)
+                (#xE4EE #x7CAE)
+                (#xE4EF #x7CB9)
+                (#xE4F0 #x7CBD)
+                (#xE4F1 #x7CC0)
+                (#xE4F2 #x7CC5)
+                (#xE4F3 #x7CC2)
+                (#xE4F4 #x7CD8)
+                (#xE4F5 #x7CD2)
+                (#xE4F6 #x7CDC)
+                (#xE4F7 #x7CE2)
+                (#xE4F8 #x9B3B)
+                (#xE4F9 #x7CEF)
+                (#xE4FA #x7CF2)
+                (#xE4FB #x7CF4)
+                (#xE4FC #x7CF6)
+                (#xE4FD #x7CFA)
+                (#xE4FE #x7D06)
+                (#xE5A1 #x7D02)
+                (#xE5A2 #x7D1C)
+                (#xE5A3 #x7D15)
+                (#xE5A4 #x7D0A)
+                (#xE5A5 #x7D45)
+                (#xE5A6 #x7D4B)
+                (#xE5A7 #x7D2E)
+                (#xE5A8 #x7D32)
+                (#xE5A9 #x7D3F)
+                (#xE5AA #x7D35)
+                (#xE5AB #x7D46)
+                (#xE5AC #x7D73)
+                (#xE5AD #x7D56)
+                (#xE5AE #x7D4E)
+                (#xE5AF #x7D72)
+                (#xE5B0 #x7D68)
+                (#xE5B1 #x7D6E)
+                (#xE5B2 #x7D4F)
+                (#xE5B3 #x7D63)
+                (#xE5B4 #x7D93)
+                (#xE5B5 #x7D89)
+                (#xE5B6 #x7D5B)
+                (#xE5B7 #x7D8F)
+                (#xE5B8 #x7D7D)
+                (#xE5B9 #x7D9B)
+                (#xE5BA #x7DBA)
+                (#xE5BB #x7DAE)
+                (#xE5BC #x7DA3)
+                (#xE5BD #x7DB5)
+                (#xE5BE #x7DC7)
+                (#xE5BF #x7DBD)
+                (#xE5C0 #x7DAB)
+                (#xE5C1 #x7E3D)
+                (#xE5C2 #x7DA2)
+                (#xE5C3 #x7DAF)
+                (#xE5C4 #x7DDC)
+                (#xE5C5 #x7DB8)
+                (#xE5C6 #x7D9F)
+                (#xE5C7 #x7DB0)
+                (#xE5C8 #x7DD8)
+                (#xE5C9 #x7DDD)
+                (#xE5CA #x7DE4)
+                (#xE5CB #x7DDE)
+                (#xE5CC #x7DFB)
+                (#xE5CD #x7DF2)
+                (#xE5CE #x7DE1)
+                (#xE5CF #x7E05)
+                (#xE5D0 #x7E0A)
+                (#xE5D1 #x7E23)
+                (#xE5D2 #x7E21)
+                (#xE5D3 #x7E12)
+                (#xE5D4 #x7E31)
+                (#xE5D5 #x7E1F)
+                (#xE5D6 #x7E09)
+                (#xE5D7 #x7E0B)
+                (#xE5D8 #x7E22)
+                (#xE5D9 #x7E46)
+                (#xE5DA #x7E66)
+                (#xE5DB #x7E3B)
+                (#xE5DC #x7E35)
+                (#xE5DD #x7E39)
+                (#xE5DE #x7E43)
+                (#xE5DF #x7E37)
+                (#xE5E0 #x7E32)
+                (#xE5E1 #x7E3A)
+                (#xE5E2 #x7E67)
+                (#xE5E3 #x7E5D)
+                (#xE5E4 #x7E56)
+                (#xE5E5 #x7E5E)
+                (#xE5E6 #x7E59)
+                (#xE5E7 #x7E5A)
+                (#xE5E8 #x7E79)
+                (#xE5E9 #x7E6A)
+                (#xE5EA #x7E69)
+                (#xE5EB #x7E7C)
+                (#xE5EC #x7E7B)
+                (#xE5ED #x7E83)
+                (#xE5EE #x7DD5)
+                (#xE5EF #x7E7D)
+                (#xE5F0 #x8FAE)
+                (#xE5F1 #x7E7F)
+                (#xE5F2 #x7E88)
+                (#xE5F3 #x7E89)
+                (#xE5F4 #x7E8C)
+                (#xE5F5 #x7E92)
+                (#xE5F6 #x7E90)
+                (#xE5F7 #x7E93)
+                (#xE5F8 #x7E94)
+                (#xE5F9 #x7E96)
+                (#xE5FA #x7E8E)
+                (#xE5FB #x7E9B)
+                (#xE5FC #x7E9C)
+                (#xE5FD #x7F38)
+                (#xE5FE #x7F3A)
+                (#xE6A1 #x7F45)
+                (#xE6A2 #x7F4C)
+                (#xE6A3 #x7F4D)
+                (#xE6A4 #x7F4E)
+                (#xE6A5 #x7F50)
+                (#xE6A6 #x7F51)
+                (#xE6A7 #x7F55)
+                (#xE6A8 #x7F54)
+                (#xE6A9 #x7F58)
+                (#xE6AA #x7F5F)
+                (#xE6AB #x7F60)
+                (#xE6AC #x7F68)
+                (#xE6AD #x7F69)
+                (#xE6AE #x7F67)
+                (#xE6AF #x7F78)
+                (#xE6B0 #x7F82)
+                (#xE6B1 #x7F86)
+                (#xE6B2 #x7F83)
+                (#xE6B3 #x7F88)
+                (#xE6B4 #x7F87)
+                (#xE6B5 #x7F8C)
+                (#xE6B6 #x7F94)
+                (#xE6B7 #x7F9E)
+                (#xE6B8 #x7F9D)
+                (#xE6B9 #x7F9A)
+                (#xE6BA #x7FA3)
+                (#xE6BB #x7FAF)
+                (#xE6BC #x7FB2)
+                (#xE6BD #x7FB9)
+                (#xE6BE #x7FAE)
+                (#xE6BF #x7FB6)
+                (#xE6C0 #x7FB8)
+                (#xE6C1 #x8B71)
+                (#xE6C2 #x7FC5)
+                (#xE6C3 #x7FC6)
+                (#xE6C4 #x7FCA)
+                (#xE6C5 #x7FD5)
+                (#xE6C6 #x7FD4)
+                (#xE6C7 #x7FE1)
+                (#xE6C8 #x7FE6)
+                (#xE6C9 #x7FE9)
+                (#xE6CA #x7FF3)
+                (#xE6CB #x7FF9)
+                (#xE6CC #x98DC)
+                (#xE6CD #x8006)
+                (#xE6CE #x8004)
+                (#xE6CF #x800B)
+                (#xE6D0 #x8012)
+                (#xE6D1 #x8018)
+                (#xE6D2 #x8019)
+                (#xE6D3 #x801C)
+                (#xE6D4 #x8021)
+                (#xE6D5 #x8028)
+                (#xE6D6 #x803F)
+                (#xE6D7 #x803B)
+                (#xE6D8 #x804A)
+                (#xE6D9 #x8046)
+                (#xE6DA #x8052)
+                (#xE6DB #x8058)
+                (#xE6DC #x805A)
+                (#xE6DD #x805F)
+                (#xE6DE #x8062)
+                (#xE6DF #x8068)
+                (#xE6E0 #x8073)
+                (#xE6E1 #x8072)
+                (#xE6E2 #x8070)
+                (#xE6E3 #x8076)
+                (#xE6E4 #x8079)
+                (#xE6E5 #x807D)
+                (#xE6E6 #x807F)
+                (#xE6E7 #x8084)
+                (#xE6E8 #x8086)
+                (#xE6E9 #x8085)
+                (#xE6EA #x809B)
+                (#xE6EB #x8093)
+                (#xE6EC #x809A)
+                (#xE6ED #x80AD)
+                (#xE6EE #x5190)
+                (#xE6EF #x80AC)
+                (#xE6F0 #x80DB)
+                (#xE6F1 #x80E5)
+                (#xE6F2 #x80D9)
+                (#xE6F3 #x80DD)
+                (#xE6F4 #x80C4)
+                (#xE6F5 #x80DA)
+                (#xE6F6 #x80D6)
+                (#xE6F7 #x8109)
+                (#xE6F8 #x80EF)
+                (#xE6F9 #x80F1)
+                (#xE6FA #x811B)
+                (#xE6FB #x8129)
+                (#xE6FC #x8123)
+                (#xE6FD #x812F)
+                (#xE6FE #x814B)
+                (#xE7A1 #x968B)
+                (#xE7A2 #x8146)
+                (#xE7A3 #x813E)
+                (#xE7A4 #x8153)
+                (#xE7A5 #x8151)
+                (#xE7A6 #x80FC)
+                (#xE7A7 #x8171)
+                (#xE7A8 #x816E)
+                (#xE7A9 #x8165)
+                (#xE7AA #x8166)
+                (#xE7AB #x8174)
+                (#xE7AC #x8183)
+                (#xE7AD #x8188)
+                (#xE7AE #x818A)
+                (#xE7AF #x8180)
+                (#xE7B0 #x8182)
+                (#xE7B1 #x81A0)
+                (#xE7B2 #x8195)
+                (#xE7B3 #x81A4)
+                (#xE7B4 #x81A3)
+                (#xE7B5 #x815F)
+                (#xE7B6 #x8193)
+                (#xE7B7 #x81A9)
+                (#xE7B8 #x81B0)
+                (#xE7B9 #x81B5)
+                (#xE7BA #x81BE)
+                (#xE7BB #x81B8)
+                (#xE7BC #x81BD)
+                (#xE7BD #x81C0)
+                (#xE7BE #x81C2)
+                (#xE7BF #x81BA)
+                (#xE7C0 #x81C9)
+                (#xE7C1 #x81CD)
+                (#xE7C2 #x81D1)
+                (#xE7C3 #x81D9)
+                (#xE7C4 #x81D8)
+                (#xE7C5 #x81C8)
+                (#xE7C6 #x81DA)
+                (#xE7C7 #x81DF)
+                (#xE7C8 #x81E0)
+                (#xE7C9 #x81E7)
+                (#xE7CA #x81FA)
+                (#xE7CB #x81FB)
+                (#xE7CC #x81FE)
+                (#xE7CD #x8201)
+                (#xE7CE #x8202)
+                (#xE7CF #x8205)
+                (#xE7D0 #x8207)
+                (#xE7D1 #x820A)
+                (#xE7D2 #x820D)
+                (#xE7D3 #x8210)
+                (#xE7D4 #x8216)
+                (#xE7D5 #x8229)
+                (#xE7D6 #x822B)
+                (#xE7D7 #x8238)
+                (#xE7D8 #x8233)
+                (#xE7D9 #x8240)
+                (#xE7DA #x8259)
+                (#xE7DB #x8258)
+                (#xE7DC #x825D)
+                (#xE7DD #x825A)
+                (#xE7DE #x825F)
+                (#xE7DF #x8264)
+                (#xE7E0 #x8262)
+                (#xE7E1 #x8268)
+                (#xE7E2 #x826A)
+                (#xE7E3 #x826B)
+                (#xE7E4 #x822E)
+                (#xE7E5 #x8271)
+                (#xE7E6 #x8277)
+                (#xE7E7 #x8278)
+                (#xE7E8 #x827E)
+                (#xE7E9 #x828D)
+                (#xE7EA #x8292)
+                (#xE7EB #x82AB)
+                (#xE7EC #x829F)
+                (#xE7ED #x82BB)
+                (#xE7EE #x82AC)
+                (#xE7EF #x82E1)
+                (#xE7F0 #x82E3)
+                (#xE7F1 #x82DF)
+                (#xE7F2 #x82D2)
+                (#xE7F3 #x82F4)
+                (#xE7F4 #x82F3)
+                (#xE7F5 #x82FA)
+                (#xE7F6 #x8393)
+                (#xE7F7 #x8303)
+                (#xE7F8 #x82FB)
+                (#xE7F9 #x82F9)
+                (#xE7FA #x82DE)
+                (#xE7FB #x8306)
+                (#xE7FC #x82DC)
+                (#xE7FD #x8309)
+                (#xE7FE #x82D9)
+                (#xE8A1 #x8335)
+                (#xE8A2 #x8334)
+                (#xE8A3 #x8316)
+                (#xE8A4 #x8332)
+                (#xE8A5 #x8331)
+                (#xE8A6 #x8340)
+                (#xE8A7 #x8339)
+                (#xE8A8 #x8350)
+                (#xE8A9 #x8345)
+                (#xE8AA #x832F)
+                (#xE8AB #x832B)
+                (#xE8AC #x8317)
+                (#xE8AD #x8318)
+                (#xE8AE #x8385)
+                (#xE8AF #x839A)
+                (#xE8B0 #x83AA)
+                (#xE8B1 #x839F)
+                (#xE8B2 #x83A2)
+                (#xE8B3 #x8396)
+                (#xE8B4 #x8323)
+                (#xE8B5 #x838E)
+                (#xE8B6 #x8387)
+                (#xE8B7 #x838A)
+                (#xE8B8 #x837C)
+                (#xE8B9 #x83B5)
+                (#xE8BA #x8373)
+                (#xE8BB #x8375)
+                (#xE8BC #x83A0)
+                (#xE8BD #x8389)
+                (#xE8BE #x83A8)
+                (#xE8BF #x83F4)
+                (#xE8C0 #x8413)
+                (#xE8C1 #x83EB)
+                (#xE8C2 #x83CE)
+                (#xE8C3 #x83FD)
+                (#xE8C4 #x8403)
+                (#xE8C5 #x83D8)
+                (#xE8C6 #x840B)
+                (#xE8C7 #x83C1)
+                (#xE8C8 #x83F7)
+                (#xE8C9 #x8407)
+                (#xE8CA #x83E0)
+                (#xE8CB #x83F2)
+                (#xE8CC #x840D)
+                (#xE8CD #x8422)
+                (#xE8CE #x8420)
+                (#xE8CF #x83BD)
+                (#xE8D0 #x8438)
+                (#xE8D1 #x8506)
+                (#xE8D2 #x83FB)
+                (#xE8D3 #x846D)
+                (#xE8D4 #x842A)
+                (#xE8D5 #x843C)
+                (#xE8D6 #x855A)
+                (#xE8D7 #x8484)
+                (#xE8D8 #x8477)
+                (#xE8D9 #x846B)
+                (#xE8DA #x84AD)
+                (#xE8DB #x846E)
+                (#xE8DC #x8482)
+                (#xE8DD #x8469)
+                (#xE8DE #x8446)
+                (#xE8DF #x842C)
+                (#xE8E0 #x846F)
+                (#xE8E1 #x8479)
+                (#xE8E2 #x8435)
+                (#xE8E3 #x84CA)
+                (#xE8E4 #x8462)
+                (#xE8E5 #x84B9)
+                (#xE8E6 #x84BF)
+                (#xE8E7 #x849F)
+                (#xE8E8 #x84D9)
+                (#xE8E9 #x84CD)
+                (#xE8EA #x84BB)
+                (#xE8EB #x84DA)
+                (#xE8EC #x84D0)
+                (#xE8ED #x84C1)
+                (#xE8EE #x84C6)
+                (#xE8EF #x84D6)
+                (#xE8F0 #x84A1)
+                (#xE8F1 #x8521)
+                (#xE8F2 #x84FF)
+                (#xE8F3 #x84F4)
+                (#xE8F4 #x8517)
+                (#xE8F5 #x8518)
+                (#xE8F6 #x852C)
+                (#xE8F7 #x851F)
+                (#xE8F8 #x8515)
+                (#xE8F9 #x8514)
+                (#xE8FA #x84FC)
+                (#xE8FB #x8540)
+                (#xE8FC #x8563)
+                (#xE8FD #x8558)
+                (#xE8FE #x8548)
+                (#xE9A1 #x8541)
+                (#xE9A2 #x8602)
+                (#xE9A3 #x854B)
+                (#xE9A4 #x8555)
+                (#xE9A5 #x8580)
+                (#xE9A6 #x85A4)
+                (#xE9A7 #x8588)
+                (#xE9A8 #x8591)
+                (#xE9A9 #x858A)
+                (#xE9AA #x85A8)
+                (#xE9AB #x856D)
+                (#xE9AC #x8594)
+                (#xE9AD #x859B)
+                (#xE9AE #x85EA)
+                (#xE9AF #x8587)
+                (#xE9B0 #x859C)
+                (#xE9B1 #x8577)
+                (#xE9B2 #x857E)
+                (#xE9B3 #x8590)
+                (#xE9B4 #x85C9)
+                (#xE9B5 #x85BA)
+                (#xE9B6 #x85CF)
+                (#xE9B7 #x85B9)
+                (#xE9B8 #x85D0)
+                (#xE9B9 #x85D5)
+                (#xE9BA #x85DD)
+                (#xE9BB #x85E5)
+                (#xE9BC #x85DC)
+                (#xE9BD #x85F9)
+                (#xE9BE #x860A)
+                (#xE9BF #x8613)
+                (#xE9C0 #x860B)
+                (#xE9C1 #x85FE)
+                (#xE9C2 #x85FA)
+                (#xE9C3 #x8606)
+                (#xE9C4 #x8622)
+                (#xE9C5 #x861A)
+                (#xE9C6 #x8630)
+                (#xE9C7 #x863F)
+                (#xE9C8 #x864D)
+                (#xE9C9 #x4E55)
+                (#xE9CA #x8654)
+                (#xE9CB #x865F)
+                (#xE9CC #x8667)
+                (#xE9CD #x8671)
+                (#xE9CE #x8693)
+                (#xE9CF #x86A3)
+                (#xE9D0 #x86A9)
+                (#xE9D1 #x86AA)
+                (#xE9D2 #x868B)
+                (#xE9D3 #x868C)
+                (#xE9D4 #x86B6)
+                (#xE9D5 #x86AF)
+                (#xE9D6 #x86C4)
+                (#xE9D7 #x86C6)
+                (#xE9D8 #x86B0)
+                (#xE9D9 #x86C9)
+                (#xE9DA #x8823)
+                (#xE9DB #x86AB)
+                (#xE9DC #x86D4)
+                (#xE9DD #x86DE)
+                (#xE9DE #x86E9)
+                (#xE9DF #x86EC)
+                (#xE9E0 #x86DF)
+                (#xE9E1 #x86DB)
+                (#xE9E2 #x86EF)
+                (#xE9E3 #x8712)
+                (#xE9E4 #x8706)
+                (#xE9E5 #x8708)
+                (#xE9E6 #x8700)
+                (#xE9E7 #x8703)
+                (#xE9E8 #x86FB)
+                (#xE9E9 #x8711)
+                (#xE9EA #x8709)
+                (#xE9EB #x870D)
+                (#xE9EC #x86F9)
+                (#xE9ED #x870A)
+                (#xE9EE #x8734)
+                (#xE9EF #x873F)
+                (#xE9F0 #x8737)
+                (#xE9F1 #x873B)
+                (#xE9F2 #x8725)
+                (#xE9F3 #x8729)
+                (#xE9F4 #x871A)
+                (#xE9F5 #x8760)
+                (#xE9F6 #x875F)
+                (#xE9F7 #x8778)
+                (#xE9F8 #x874C)
+                (#xE9F9 #x874E)
+                (#xE9FA #x8774)
+                (#xE9FB #x8757)
+                (#xE9FC #x8768)
+                (#xE9FD #x876E)
+                (#xE9FE #x8759)
+                (#xEAA1 #x8753)
+                (#xEAA2 #x8763)
+                (#xEAA3 #x876A)
+                (#xEAA4 #x8805)
+                (#xEAA5 #x87A2)
+                (#xEAA6 #x879F)
+                (#xEAA7 #x8782)
+                (#xEAA8 #x87AF)
+                (#xEAA9 #x87CB)
+                (#xEAAA #x87BD)
+                (#xEAAB #x87C0)
+                (#xEAAC #x87D0)
+                (#xEAAD #x96D6)
+                (#xEAAE #x87AB)
+                (#xEAAF #x87C4)
+                (#xEAB0 #x87B3)
+                (#xEAB1 #x87C7)
+                (#xEAB2 #x87C6)
+                (#xEAB3 #x87BB)
+                (#xEAB4 #x87EF)
+                (#xEAB5 #x87F2)
+                (#xEAB6 #x87E0)
+                (#xEAB7 #x880F)
+                (#xEAB8 #x880D)
+                (#xEAB9 #x87FE)
+                (#xEABA #x87F6)
+                (#xEABB #x87F7)
+                (#xEABC #x880E)
+                (#xEABD #x87D2)
+                (#xEABE #x8811)
+                (#xEABF #x8816)
+                (#xEAC0 #x8815)
+                (#xEAC1 #x8822)
+                (#xEAC2 #x8821)
+                (#xEAC3 #x8831)
+                (#xEAC4 #x8836)
+                (#xEAC5 #x8839)
+                (#xEAC6 #x8827)
+                (#xEAC7 #x883B)
+                (#xEAC8 #x8844)
+                (#xEAC9 #x8842)
+                (#xEACA #x8852)
+                (#xEACB #x8859)
+                (#xEACC #x885E)
+                (#xEACD #x8862)
+                (#xEACE #x886B)
+                (#xEACF #x8881)
+                (#xEAD0 #x887E)
+                (#xEAD1 #x889E)
+                (#xEAD2 #x8875)
+                (#xEAD3 #x887D)
+                (#xEAD4 #x88B5)
+                (#xEAD5 #x8872)
+                (#xEAD6 #x8882)
+                (#xEAD7 #x8897)
+                (#xEAD8 #x8892)
+                (#xEAD9 #x88AE)
+                (#xEADA #x8899)
+                (#xEADB #x88A2)
+                (#xEADC #x888D)
+                (#xEADD #x88A4)
+                (#xEADE #x88B0)
+                (#xEADF #x88BF)
+                (#xEAE0 #x88B1)
+                (#xEAE1 #x88C3)
+                (#xEAE2 #x88C4)
+                (#xEAE3 #x88D4)
+                (#xEAE4 #x88D8)
+                (#xEAE5 #x88D9)
+                (#xEAE6 #x88DD)
+                (#xEAE7 #x88F9)
+                (#xEAE8 #x8902)
+                (#xEAE9 #x88FC)
+                (#xEAEA #x88F4)
+                (#xEAEB #x88E8)
+                (#xEAEC #x88F2)
+                (#xEAED #x8904)
+                (#xEAEE #x890C)
+                (#xEAEF #x890A)
+                (#xEAF0 #x8913)
+                (#xEAF1 #x8943)
+                (#xEAF2 #x891E)
+                (#xEAF3 #x8925)
+                (#xEAF4 #x892A)
+                (#xEAF5 #x892B)
+                (#xEAF6 #x8941)
+                (#xEAF7 #x8944)
+                (#xEAF8 #x893B)
+                (#xEAF9 #x8936)
+                (#xEAFA #x8938)
+                (#xEAFB #x894C)
+                (#xEAFC #x891D)
+                (#xEAFD #x8960)
+                (#xEAFE #x895E)
+                (#xEBA1 #x8966)
+                (#xEBA2 #x8964)
+                (#xEBA3 #x896D)
+                (#xEBA4 #x896A)
+                (#xEBA5 #x896F)
+                (#xEBA6 #x8974)
+                (#xEBA7 #x8977)
+                (#xEBA8 #x897E)
+                (#xEBA9 #x8983)
+                (#xEBAA #x8988)
+                (#xEBAB #x898A)
+                (#xEBAC #x8993)
+                (#xEBAD #x8998)
+                (#xEBAE #x89A1)
+                (#xEBAF #x89A9)
+                (#xEBB0 #x89A6)
+                (#xEBB1 #x89AC)
+                (#xEBB2 #x89AF)
+                (#xEBB3 #x89B2)
+                (#xEBB4 #x89BA)
+                (#xEBB5 #x89BD)
+                (#xEBB6 #x89BF)
+                (#xEBB7 #x89C0)
+                (#xEBB8 #x89DA)
+                (#xEBB9 #x89DC)
+                (#xEBBA #x89DD)
+                (#xEBBB #x89E7)
+                (#xEBBC #x89F4)
+                (#xEBBD #x89F8)
+                (#xEBBE #x8A03)
+                (#xEBBF #x8A16)
+                (#xEBC0 #x8A10)
+                (#xEBC1 #x8A0C)
+                (#xEBC2 #x8A1B)
+                (#xEBC3 #x8A1D)
+                (#xEBC4 #x8A25)
+                (#xEBC5 #x8A36)
+                (#xEBC6 #x8A41)
+                (#xEBC7 #x8A5B)
+                (#xEBC8 #x8A52)
+                (#xEBC9 #x8A46)
+                (#xEBCA #x8A48)
+                (#xEBCB #x8A7C)
+                (#xEBCC #x8A6D)
+                (#xEBCD #x8A6C)
+                (#xEBCE #x8A62)
+                (#xEBCF #x8A85)
+                (#xEBD0 #x8A82)
+                (#xEBD1 #x8A84)
+                (#xEBD2 #x8AA8)
+                (#xEBD3 #x8AA1)
+                (#xEBD4 #x8A91)
+                (#xEBD5 #x8AA5)
+                (#xEBD6 #x8AA6)
+                (#xEBD7 #x8A9A)
+                (#xEBD8 #x8AA3)
+                (#xEBD9 #x8AC4)
+                (#xEBDA #x8ACD)
+                (#xEBDB #x8AC2)
+                (#xEBDC #x8ADA)
+                (#xEBDD #x8AEB)
+                (#xEBDE #x8AF3)
+                (#xEBDF #x8AE7)
+                (#xEBE0 #x8AE4)
+                (#xEBE1 #x8AF1)
+                (#xEBE2 #x8B14)
+                (#xEBE3 #x8AE0)
+                (#xEBE4 #x8AE2)
+                (#xEBE5 #x8AF7)
+                (#xEBE6 #x8ADE)
+                (#xEBE7 #x8ADB)
+                (#xEBE8 #x8B0C)
+                (#xEBE9 #x8B07)
+                (#xEBEA #x8B1A)
+                (#xEBEB #x8AE1)
+                (#xEBEC #x8B16)
+                (#xEBED #x8B10)
+                (#xEBEE #x8B17)
+                (#xEBEF #x8B20)
+                (#xEBF0 #x8B33)
+                (#xEBF1 #x97AB)
+                (#xEBF2 #x8B26)
+                (#xEBF3 #x8B2B)
+                (#xEBF4 #x8B3E)
+                (#xEBF5 #x8B28)
+                (#xEBF6 #x8B41)
+                (#xEBF7 #x8B4C)
+                (#xEBF8 #x8B4F)
+                (#xEBF9 #x8B4E)
+                (#xEBFA #x8B49)
+                (#xEBFB #x8B56)
+                (#xEBFC #x8B5B)
+                (#xEBFD #x8B5A)
+                (#xEBFE #x8B6B)
+                (#xECA1 #x8B5F)
+                (#xECA2 #x8B6C)
+                (#xECA3 #x8B6F)
+                (#xECA4 #x8B74)
+                (#xECA5 #x8B7D)
+                (#xECA6 #x8B80)
+                (#xECA7 #x8B8C)
+                (#xECA8 #x8B8E)
+                (#xECA9 #x8B92)
+                (#xECAA #x8B93)
+                (#xECAB #x8B96)
+                (#xECAC #x8B99)
+                (#xECAD #x8B9A)
+                (#xECAE #x8C3A)
+                (#xECAF #x8C41)
+                (#xECB0 #x8C3F)
+                (#xECB1 #x8C48)
+                (#xECB2 #x8C4C)
+                (#xECB3 #x8C4E)
+                (#xECB4 #x8C50)
+                (#xECB5 #x8C55)
+                (#xECB6 #x8C62)
+                (#xECB7 #x8C6C)
+                (#xECB8 #x8C78)
+                (#xECB9 #x8C7A)
+                (#xECBA #x8C82)
+                (#xECBB #x8C89)
+                (#xECBC #x8C85)
+                (#xECBD #x8C8A)
+                (#xECBE #x8C8D)
+                (#xECBF #x8C8E)
+                (#xECC0 #x8C94)
+                (#xECC1 #x8C7C)
+                (#xECC2 #x8C98)
+                (#xECC3 #x621D)
+                (#xECC4 #x8CAD)
+                (#xECC5 #x8CAA)
+                (#xECC6 #x8CBD)
+                (#xECC7 #x8CB2)
+                (#xECC8 #x8CB3)
+                (#xECC9 #x8CAE)
+                (#xECCA #x8CB6)
+                (#xECCB #x8CC8)
+                (#xECCC #x8CC1)
+                (#xECCD #x8CE4)
+                (#xECCE #x8CE3)
+                (#xECCF #x8CDA)
+                (#xECD0 #x8CFD)
+                (#xECD1 #x8CFA)
+                (#xECD2 #x8CFB)
+                (#xECD3 #x8D04)
+                (#xECD4 #x8D05)
+                (#xECD5 #x8D0A)
+                (#xECD6 #x8D07)
+                (#xECD7 #x8D0F)
+                (#xECD8 #x8D0D)
+                (#xECD9 #x8D10)
+                (#xECDA #x9F4E)
+                (#xECDB #x8D13)
+                (#xECDC #x8CCD)
+                (#xECDD #x8D14)
+                (#xECDE #x8D16)
+                (#xECDF #x8D67)
+                (#xECE0 #x8D6D)
+                (#xECE1 #x8D71)
+                (#xECE2 #x8D73)
+                (#xECE3 #x8D81)
+                (#xECE4 #x8D99)
+                (#xECE5 #x8DC2)
+                (#xECE6 #x8DBE)
+                (#xECE7 #x8DBA)
+                (#xECE8 #x8DCF)
+                (#xECE9 #x8DDA)
+                (#xECEA #x8DD6)
+                (#xECEB #x8DCC)
+                (#xECEC #x8DDB)
+                (#xECED #x8DCB)
+                (#xECEE #x8DEA)
+                (#xECEF #x8DEB)
+                (#xECF0 #x8DDF)
+                (#xECF1 #x8DE3)
+                (#xECF2 #x8DFC)
+                (#xECF3 #x8E08)
+                (#xECF4 #x8E09)
+                (#xECF5 #x8DFF)
+                (#xECF6 #x8E1D)
+                (#xECF7 #x8E1E)
+                (#xECF8 #x8E10)
+                (#xECF9 #x8E1F)
+                (#xECFA #x8E42)
+                (#xECFB #x8E35)
+                (#xECFC #x8E30)
+                (#xECFD #x8E34)
+                (#xECFE #x8E4A)
+                (#xEDA1 #x8E47)
+                (#xEDA2 #x8E49)
+                (#xEDA3 #x8E4C)
+                (#xEDA4 #x8E50)
+                (#xEDA5 #x8E48)
+                (#xEDA6 #x8E59)
+                (#xEDA7 #x8E64)
+                (#xEDA8 #x8E60)
+                (#xEDA9 #x8E2A)
+                (#xEDAA #x8E63)
+                (#xEDAB #x8E55)
+                (#xEDAC #x8E76)
+                (#xEDAD #x8E72)
+                (#xEDAE #x8E7C)
+                (#xEDAF #x8E81)
+                (#xEDB0 #x8E87)
+                (#xEDB1 #x8E85)
+                (#xEDB2 #x8E84)
+                (#xEDB3 #x8E8B)
+                (#xEDB4 #x8E8A)
+                (#xEDB5 #x8E93)
+                (#xEDB6 #x8E91)
+                (#xEDB7 #x8E94)
+                (#xEDB8 #x8E99)
+                (#xEDB9 #x8EAA)
+                (#xEDBA #x8EA1)
+                (#xEDBB #x8EAC)
+                (#xEDBC #x8EB0)
+                (#xEDBD #x8EC6)
+                (#xEDBE #x8EB1)
+                (#xEDBF #x8EBE)
+                (#xEDC0 #x8EC5)
+                (#xEDC1 #x8EC8)
+                (#xEDC2 #x8ECB)
+                (#xEDC3 #x8EDB)
+                (#xEDC4 #x8EE3)
+                (#xEDC5 #x8EFC)
+                (#xEDC6 #x8EFB)
+                (#xEDC7 #x8EEB)
+                (#xEDC8 #x8EFE)
+                (#xEDC9 #x8F0A)
+                (#xEDCA #x8F05)
+                (#xEDCB #x8F15)
+                (#xEDCC #x8F12)
+                (#xEDCD #x8F19)
+                (#xEDCE #x8F13)
+                (#xEDCF #x8F1C)
+                (#xEDD0 #x8F1F)
+                (#xEDD1 #x8F1B)
+                (#xEDD2 #x8F0C)
+                (#xEDD3 #x8F26)
+                (#xEDD4 #x8F33)
+                (#xEDD5 #x8F3B)
+                (#xEDD6 #x8F39)
+                (#xEDD7 #x8F45)
+                (#xEDD8 #x8F42)
+                (#xEDD9 #x8F3E)
+                (#xEDDA #x8F4C)
+                (#xEDDB #x8F49)
+                (#xEDDC #x8F46)
+                (#xEDDD #x8F4E)
+                (#xEDDE #x8F57)
+                (#xEDDF #x8F5C)
+                (#xEDE0 #x8F62)
+                (#xEDE1 #x8F63)
+                (#xEDE2 #x8F64)
+                (#xEDE3 #x8F9C)
+                (#xEDE4 #x8F9F)
+                (#xEDE5 #x8FA3)
+                (#xEDE6 #x8FAD)
+                (#xEDE7 #x8FAF)
+                (#xEDE8 #x8FB7)
+                (#xEDE9 #x8FDA)
+                (#xEDEA #x8FE5)
+                (#xEDEB #x8FE2)
+                (#xEDEC #x8FEA)
+                (#xEDED #x8FEF)
+                (#xEDEE #x9087)
+                (#xEDEF #x8FF4)
+                (#xEDF0 #x9005)
+                (#xEDF1 #x8FF9)
+                (#xEDF2 #x8FFA)
+                (#xEDF3 #x9011)
+                (#xEDF4 #x9015)
+                (#xEDF5 #x9021)
+                (#xEDF6 #x900D)
+                (#xEDF7 #x901E)
+                (#xEDF8 #x9016)
+                (#xEDF9 #x900B)
+                (#xEDFA #x9027)
+                (#xEDFB #x9036)
+                (#xEDFC #x9035)
+                (#xEDFD #x9039)
+                (#xEDFE #x8FF8)
+                (#xEEA1 #x904F)
+                (#xEEA2 #x9050)
+                (#xEEA3 #x9051)
+                (#xEEA4 #x9052)
+                (#xEEA5 #x900E)
+                (#xEEA6 #x9049)
+                (#xEEA7 #x903E)
+                (#xEEA8 #x9056)
+                (#xEEA9 #x9058)
+                (#xEEAA #x905E)
+                (#xEEAB #x9068)
+                (#xEEAC #x906F)
+                (#xEEAD #x9076)
+                (#xEEAE #x96A8)
+                (#xEEAF #x9072)
+                (#xEEB0 #x9082)
+                (#xEEB1 #x907D)
+                (#xEEB2 #x9081)
+                (#xEEB3 #x9080)
+                (#xEEB4 #x908A)
+                (#xEEB5 #x9089)
+                (#xEEB6 #x908F)
+                (#xEEB7 #x90A8)
+                (#xEEB8 #x90AF)
+                (#xEEB9 #x90B1)
+                (#xEEBA #x90B5)
+                (#xEEBB #x90E2)
+                (#xEEBC #x90E4)
+                (#xEEBD #x6248)
+                (#xEEBE #x90DB)
+                (#xEEBF #x9102)
+                (#xEEC0 #x9112)
+                (#xEEC1 #x9119)
+                (#xEEC2 #x9132)
+                (#xEEC3 #x9130)
+                (#xEEC4 #x914A)
+                (#xEEC5 #x9156)
+                (#xEEC6 #x9158)
+                (#xEEC7 #x9163)
+                (#xEEC8 #x9165)
+                (#xEEC9 #x9169)
+                (#xEECA #x9173)
+                (#xEECB #x9172)
+                (#xEECC #x918B)
+                (#xEECD #x9189)
+                (#xEECE #x9182)
+                (#xEECF #x91A2)
+                (#xEED0 #x91AB)
+                (#xEED1 #x91AF)
+                (#xEED2 #x91AA)
+                (#xEED3 #x91B5)
+                (#xEED4 #x91B4)
+                (#xEED5 #x91BA)
+                (#xEED6 #x91C0)
+                (#xEED7 #x91C1)
+                (#xEED8 #x91C9)
+                (#xEED9 #x91CB)
+                (#xEEDA #x91D0)
+                (#xEEDB #x91D6)
+                (#xEEDC #x91DF)
+                (#xEEDD #x91E1)
+                (#xEEDE #x91DB)
+                (#xEEDF #x91FC)
+                (#xEEE0 #x91F5)
+                (#xEEE1 #x91F6)
+                (#xEEE2 #x921E)
+                (#xEEE3 #x91FF)
+                (#xEEE4 #x9214)
+                (#xEEE5 #x922C)
+                (#xEEE6 #x9215)
+                (#xEEE7 #x9211)
+                (#xEEE8 #x925E)
+                (#xEEE9 #x9257)
+                (#xEEEA #x9245)
+                (#xEEEB #x9249)
+                (#xEEEC #x9264)
+                (#xEEED #x9248)
+                (#xEEEE #x9295)
+                (#xEEEF #x923F)
+                (#xEEF0 #x924B)
+                (#xEEF1 #x9250)
+                (#xEEF2 #x929C)
+                (#xEEF3 #x9296)
+                (#xEEF4 #x9293)
+                (#xEEF5 #x929B)
+                (#xEEF6 #x925A)
+                (#xEEF7 #x92CF)
+                (#xEEF8 #x92B9)
+                (#xEEF9 #x92B7)
+                (#xEEFA #x92E9)
+                (#xEEFB #x930F)
+                (#xEEFC #x92FA)
+                (#xEEFD #x9344)
+                (#xEEFE #x932E)
+                (#xEFA1 #x9319)
+                (#xEFA2 #x9322)
+                (#xEFA3 #x931A)
+                (#xEFA4 #x9323)
+                (#xEFA5 #x933A)
+                (#xEFA6 #x9335)
+                (#xEFA7 #x933B)
+                (#xEFA8 #x935C)
+                (#xEFA9 #x9360)
+                (#xEFAA #x937C)
+                (#xEFAB #x936E)
+                (#xEFAC #x9356)
+                (#xEFAD #x93B0)
+                (#xEFAE #x93AC)
+                (#xEFAF #x93AD)
+                (#xEFB0 #x9394)
+                (#xEFB1 #x93B9)
+                (#xEFB2 #x93D6)
+                (#xEFB3 #x93D7)
+                (#xEFB4 #x93E8)
+                (#xEFB5 #x93E5)
+                (#xEFB6 #x93D8)
+                (#xEFB7 #x93C3)
+                (#xEFB8 #x93DD)
+                (#xEFB9 #x93D0)
+                (#xEFBA #x93C8)
+                (#xEFBB #x93E4)
+                (#xEFBC #x941A)
+                (#xEFBD #x9414)
+                (#xEFBE #x9413)
+                (#xEFBF #x9403)
+                (#xEFC0 #x9407)
+                (#xEFC1 #x9410)
+                (#xEFC2 #x9436)
+                (#xEFC3 #x942B)
+                (#xEFC4 #x9435)
+                (#xEFC5 #x9421)
+                (#xEFC6 #x943A)
+                (#xEFC7 #x9441)
+                (#xEFC8 #x9452)
+                (#xEFC9 #x9444)
+                (#xEFCA #x945B)
+                (#xEFCB #x9460)
+                (#xEFCC #x9462)
+                (#xEFCD #x945E)
+                (#xEFCE #x946A)
+                (#xEFCF #x9229)
+                (#xEFD0 #x9470)
+                (#xEFD1 #x9475)
+                (#xEFD2 #x9477)
+                (#xEFD3 #x947D)
+                (#xEFD4 #x945A)
+                (#xEFD5 #x947C)
+                (#xEFD6 #x947E)
+                (#xEFD7 #x9481)
+                (#xEFD8 #x947F)
+                (#xEFD9 #x9582)
+                (#xEFDA #x9587)
+                (#xEFDB #x958A)
+                (#xEFDC #x9594)
+                (#xEFDD #x9596)
+                (#xEFDE #x9598)
+                (#xEFDF #x9599)
+                (#xEFE0 #x95A0)
+                (#xEFE1 #x95A8)
+                (#xEFE2 #x95A7)
+                (#xEFE3 #x95AD)
+                (#xEFE4 #x95BC)
+                (#xEFE5 #x95BB)
+                (#xEFE6 #x95B9)
+                (#xEFE7 #x95BE)
+                (#xEFE8 #x95CA)
+                (#xEFE9 #x6FF6)
+                (#xEFEA #x95C3)
+                (#xEFEB #x95CD)
+                (#xEFEC #x95CC)
+                (#xEFED #x95D5)
+                (#xEFEE #x95D4)
+                (#xEFEF #x95D6)
+                (#xEFF0 #x95DC)
+                (#xEFF1 #x95E1)
+                (#xEFF2 #x95E5)
+                (#xEFF3 #x95E2)
+                (#xEFF4 #x9621)
+                (#xEFF5 #x9628)
+                (#xEFF6 #x962E)
+                (#xEFF7 #x962F)
+                (#xEFF8 #x9642)
+                (#xEFF9 #x964C)
+                (#xEFFA #x964F)
+                (#xEFFB #x964B)
+                (#xEFFC #x9677)
+                (#xEFFD #x965C)
+                (#xEFFE #x965E)
+                (#xF0A1 #x965D)
+                (#xF0A2 #x965F)
+                (#xF0A3 #x9666)
+                (#xF0A4 #x9672)
+                (#xF0A5 #x966C)
+                (#xF0A6 #x968D)
+                (#xF0A7 #x9698)
+                (#xF0A8 #x9695)
+                (#xF0A9 #x9697)
+                (#xF0AA #x96AA)
+                (#xF0AB #x96A7)
+                (#xF0AC #x96B1)
+                (#xF0AD #x96B2)
+                (#xF0AE #x96B0)
+                (#xF0AF #x96B4)
+                (#xF0B0 #x96B6)
+                (#xF0B1 #x96B8)
+                (#xF0B2 #x96B9)
+                (#xF0B3 #x96CE)
+                (#xF0B4 #x96CB)
+                (#xF0B5 #x96C9)
+                (#xF0B6 #x96CD)
+                (#xF0B7 #x894D)
+                (#xF0B8 #x96DC)
+                (#xF0B9 #x970D)
+                (#xF0BA #x96D5)
+                (#xF0BB #x96F9)
+                (#xF0BC #x9704)
+                (#xF0BD #x9706)
+                (#xF0BE #x9708)
+                (#xF0BF #x9713)
+                (#xF0C0 #x970E)
+                (#xF0C1 #x9711)
+                (#xF0C2 #x970F)
+                (#xF0C3 #x9716)
+                (#xF0C4 #x9719)
+                (#xF0C5 #x9724)
+                (#xF0C6 #x972A)
+                (#xF0C7 #x9730)
+                (#xF0C8 #x9739)
+                (#xF0C9 #x973D)
+                (#xF0CA #x973E)
+                (#xF0CB #x9744)
+                (#xF0CC #x9746)
+                (#xF0CD #x9748)
+                (#xF0CE #x9742)
+                (#xF0CF #x9749)
+                (#xF0D0 #x975C)
+                (#xF0D1 #x9760)
+                (#xF0D2 #x9764)
+                (#xF0D3 #x9766)
+                (#xF0D4 #x9768)
+                (#xF0D5 #x52D2)
+                (#xF0D6 #x976B)
+                (#xF0D7 #x9771)
+                (#xF0D8 #x9779)
+                (#xF0D9 #x9785)
+                (#xF0DA #x977C)
+                (#xF0DB #x9781)
+                (#xF0DC #x977A)
+                (#xF0DD #x9786)
+                (#xF0DE #x978B)
+                (#xF0DF #x978F)
+                (#xF0E0 #x9790)
+                (#xF0E1 #x979C)
+                (#xF0E2 #x97A8)
+                (#xF0E3 #x97A6)
+                (#xF0E4 #x97A3)
+                (#xF0E5 #x97B3)
+                (#xF0E6 #x97B4)
+                (#xF0E7 #x97C3)
+                (#xF0E8 #x97C6)
+                (#xF0E9 #x97C8)
+                (#xF0EA #x97CB)
+                (#xF0EB #x97DC)
+                (#xF0EC #x97ED)
+                (#xF0ED #x9F4F)
+                (#xF0EE #x97F2)
+                (#xF0EF #x7ADF)
+                (#xF0F0 #x97F6)
+                (#xF0F1 #x97F5)
+                (#xF0F2 #x980F)
+                (#xF0F3 #x980C)
+                (#xF0F4 #x9838)
+                (#xF0F5 #x9824)
+                (#xF0F6 #x9821)
+                (#xF0F7 #x9837)
+                (#xF0F8 #x983D)
+                (#xF0F9 #x9846)
+                (#xF0FA #x984F)
+                (#xF0FB #x984B)
+                (#xF0FC #x986B)
+                (#xF0FD #x986F)
+                (#xF0FE #x9870)
+                (#xF1A1 #x9871)
+                (#xF1A2 #x9874)
+                (#xF1A3 #x9873)
+                (#xF1A4 #x98AA)
+                (#xF1A5 #x98AF)
+                (#xF1A6 #x98B1)
+                (#xF1A7 #x98B6)
+                (#xF1A8 #x98C4)
+                (#xF1A9 #x98C3)
+                (#xF1AA #x98C6)
+                (#xF1AB #x98E9)
+                (#xF1AC #x98EB)
+                (#xF1AD #x9903)
+                (#xF1AE #x9909)
+                (#xF1AF #x9912)
+                (#xF1B0 #x9914)
+                (#xF1B1 #x9918)
+                (#xF1B2 #x9921)
+                (#xF1B3 #x991D)
+                (#xF1B4 #x991E)
+                (#xF1B5 #x9924)
+                (#xF1B6 #x9920)
+                (#xF1B7 #x992C)
+                (#xF1B8 #x992E)
+                (#xF1B9 #x993D)
+                (#xF1BA #x993E)
+                (#xF1BB #x9942)
+                (#xF1BC #x9949)
+                (#xF1BD #x9945)
+                (#xF1BE #x9950)
+                (#xF1BF #x994B)
+                (#xF1C0 #x9951)
+                (#xF1C1 #x9952)
+                (#xF1C2 #x994C)
+                (#xF1C3 #x9955)
+                (#xF1C4 #x9997)
+                (#xF1C5 #x9998)
+                (#xF1C6 #x99A5)
+                (#xF1C7 #x99AD)
+                (#xF1C8 #x99AE)
+                (#xF1C9 #x99BC)
+                (#xF1CA #x99DF)
+                (#xF1CB #x99DB)
+                (#xF1CC #x99DD)
+                (#xF1CD #x99D8)
+                (#xF1CE #x99D1)
+                (#xF1CF #x99ED)
+                (#xF1D0 #x99EE)
+                (#xF1D1 #x99F1)
+                (#xF1D2 #x99F2)
+                (#xF1D3 #x99FB)
+                (#xF1D4 #x99F8)
+                (#xF1D5 #x9A01)
+                (#xF1D6 #x9A0F)
+                (#xF1D7 #x9A05)
+                (#xF1D8 #x99E2)
+                (#xF1D9 #x9A19)
+                (#xF1DA #x9A2B)
+                (#xF1DB #x9A37)
+                (#xF1DC #x9A45)
+                (#xF1DD #x9A42)
+                (#xF1DE #x9A40)
+                (#xF1DF #x9A43)
+                (#xF1E0 #x9A3E)
+                (#xF1E1 #x9A55)
+                (#xF1E2 #x9A4D)
+                (#xF1E3 #x9A5B)
+                (#xF1E4 #x9A57)
+                (#xF1E5 #x9A5F)
+                (#xF1E6 #x9A62)
+                (#xF1E7 #x9A65)
+                (#xF1E8 #x9A64)
+                (#xF1E9 #x9A69)
+                (#xF1EA #x9A6B)
+                (#xF1EB #x9A6A)
+                (#xF1EC #x9AAD)
+                (#xF1ED #x9AB0)
+                (#xF1EE #x9ABC)
+                (#xF1EF #x9AC0)
+                (#xF1F0 #x9ACF)
+                (#xF1F1 #x9AD1)
+                (#xF1F2 #x9AD3)
+                (#xF1F3 #x9AD4)
+                (#xF1F4 #x9ADE)
+                (#xF1F5 #x9ADF)
+                (#xF1F6 #x9AE2)
+                (#xF1F7 #x9AE3)
+                (#xF1F8 #x9AE6)
+                (#xF1F9 #x9AEF)
+                (#xF1FA #x9AEB)
+                (#xF1FB #x9AEE)
+                (#xF1FC #x9AF4)
+                (#xF1FD #x9AF1)
+                (#xF1FE #x9AF7)
+                (#xF2A1 #x9AFB)
+                (#xF2A2 #x9B06)
+                (#xF2A3 #x9B18)
+                (#xF2A4 #x9B1A)
+                (#xF2A5 #x9B1F)
+                (#xF2A6 #x9B22)
+                (#xF2A7 #x9B23)
+                (#xF2A8 #x9B25)
+                (#xF2A9 #x9B27)
+                (#xF2AA #x9B28)
+                (#xF2AB #x9B29)
+                (#xF2AC #x9B2A)
+                (#xF2AD #x9B2E)
+                (#xF2AE #x9B2F)
+                (#xF2AF #x9B32)
+                (#xF2B0 #x9B44)
+                (#xF2B1 #x9B43)
+                (#xF2B2 #x9B4F)
+                (#xF2B3 #x9B4D)
+                (#xF2B4 #x9B4E)
+                (#xF2B5 #x9B51)
+                (#xF2B6 #x9B58)
+                (#xF2B7 #x9B74)
+                (#xF2B8 #x9B93)
+                (#xF2B9 #x9B83)
+                (#xF2BA #x9B91)
+                (#xF2BB #x9B96)
+                (#xF2BC #x9B97)
+                (#xF2BD #x9B9F)
+                (#xF2BE #x9BA0)
+                (#xF2BF #x9BA8)
+                (#xF2C0 #x9BB4)
+                (#xF2C1 #x9BC0)
+                (#xF2C2 #x9BCA)
+                (#xF2C3 #x9BB9)
+                (#xF2C4 #x9BC6)
+                (#xF2C5 #x9BCF)
+                (#xF2C6 #x9BD1)
+                (#xF2C7 #x9BD2)
+                (#xF2C8 #x9BE3)
+                (#xF2C9 #x9BE2)
+                (#xF2CA #x9BE4)
+                (#xF2CB #x9BD4)
+                (#xF2CC #x9BE1)
+                (#xF2CD #x9C3A)
+                (#xF2CE #x9BF2)
+                (#xF2CF #x9BF1)
+                (#xF2D0 #x9BF0)
+                (#xF2D1 #x9C15)
+                (#xF2D2 #x9C14)
+                (#xF2D3 #x9C09)
+                (#xF2D4 #x9C13)
+                (#xF2D5 #x9C0C)
+                (#xF2D6 #x9C06)
+                (#xF2D7 #x9C08)
+                (#xF2D8 #x9C12)
+                (#xF2D9 #x9C0A)
+                (#xF2DA #x9C04)
+                (#xF2DB #x9C2E)
+                (#xF2DC #x9C1B)
+                (#xF2DD #x9C25)
+                (#xF2DE #x9C24)
+                (#xF2DF #x9C21)
+                (#xF2E0 #x9C30)
+                (#xF2E1 #x9C47)
+                (#xF2E2 #x9C32)
+                (#xF2E3 #x9C46)
+                (#xF2E4 #x9C3E)
+                (#xF2E5 #x9C5A)
+                (#xF2E6 #x9C60)
+                (#xF2E7 #x9C67)
+                (#xF2E8 #x9C76)
+                (#xF2E9 #x9C78)
+                (#xF2EA #x9CE7)
+                (#xF2EB #x9CEC)
+                (#xF2EC #x9CF0)
+                (#xF2ED #x9D09)
+                (#xF2EE #x9D08)
+                (#xF2EF #x9CEB)
+                (#xF2F0 #x9D03)
+                (#xF2F1 #x9D06)
+                (#xF2F2 #x9D2A)
+                (#xF2F3 #x9D26)
+                (#xF2F4 #x9DAF)
+                (#xF2F5 #x9D23)
+                (#xF2F6 #x9D1F)
+                (#xF2F7 #x9D44)
+                (#xF2F8 #x9D15)
+                (#xF2F9 #x9D12)
+                (#xF2FA #x9D41)
+                (#xF2FB #x9D3F)
+                (#xF2FC #x9D3E)
+                (#xF2FD #x9D46)
+                (#xF2FE #x9D48)
+                (#xF3A1 #x9D5D)
+                (#xF3A2 #x9D5E)
+                (#xF3A3 #x9D64)
+                (#xF3A4 #x9D51)
+                (#xF3A5 #x9D50)
+                (#xF3A6 #x9D59)
+                (#xF3A7 #x9D72)
+                (#xF3A8 #x9D89)
+                (#xF3A9 #x9D87)
+                (#xF3AA #x9DAB)
+                (#xF3AB #x9D6F)
+                (#xF3AC #x9D7A)
+                (#xF3AD #x9D9A)
+                (#xF3AE #x9DA4)
+                (#xF3AF #x9DA9)
+                (#xF3B0 #x9DB2)
+                (#xF3B1 #x9DC4)
+                (#xF3B2 #x9DC1)
+                (#xF3B3 #x9DBB)
+                (#xF3B4 #x9DB8)
+                (#xF3B5 #x9DBA)
+                (#xF3B6 #x9DC6)
+                (#xF3B7 #x9DCF)
+                (#xF3B8 #x9DC2)
+                (#xF3B9 #x9DD9)
+                (#xF3BA #x9DD3)
+                (#xF3BB #x9DF8)
+                (#xF3BC #x9DE6)
+                (#xF3BD #x9DED)
+                (#xF3BE #x9DEF)
+                (#xF3BF #x9DFD)
+                (#xF3C0 #x9E1A)
+                (#xF3C1 #x9E1B)
+                (#xF3C2 #x9E1E)
+                (#xF3C3 #x9E75)
+                (#xF3C4 #x9E79)
+                (#xF3C5 #x9E7D)
+                (#xF3C6 #x9E81)
+                (#xF3C7 #x9E88)
+                (#xF3C8 #x9E8B)
+                (#xF3C9 #x9E8C)
+                (#xF3CA #x9E92)
+                (#xF3CB #x9E95)
+                (#xF3CC #x9E91)
+                (#xF3CD #x9E9D)
+                (#xF3CE #x9EA5)
+                (#xF3CF #x9EA9)
+                (#xF3D0 #x9EB8)
+                (#xF3D1 #x9EAA)
+                (#xF3D2 #x9EAD)
+                (#xF3D3 #x9761)
+                (#xF3D4 #x9ECC)
+                (#xF3D5 #x9ECE)
+                (#xF3D6 #x9ECF)
+                (#xF3D7 #x9ED0)
+                (#xF3D8 #x9ED4)
+                (#xF3D9 #x9EDC)
+                (#xF3DA #x9EDE)
+                (#xF3DB #x9EDD)
+                (#xF3DC #x9EE0)
+                (#xF3DD #x9EE5)
+                (#xF3DE #x9EE8)
+                (#xF3DF #x9EEF)
+                (#xF3E0 #x9EF4)
+                (#xF3E1 #x9EF6)
+                (#xF3E2 #x9EF7)
+                (#xF3E3 #x9EF9)
+                (#xF3E4 #x9EFB)
+                (#xF3E5 #x9EFC)
+                (#xF3E6 #x9EFD)
+                (#xF3E7 #x9F07)
+                (#xF3E8 #x9F08)
+                (#xF3E9 #x76B7)
+                (#xF3EA #x9F15)
+                (#xF3EB #x9F21)
+                (#xF3EC #x9F2C)
+                (#xF3ED #x9F3E)
+                (#xF3EE #x9F4A)
+                (#xF3EF #x9F52)
+                (#xF3F0 #x9F54)
+                (#xF3F1 #x9F63)
+                (#xF3F2 #x9F5F)
+                (#xF3F3 #x9F60)
+                (#xF3F4 #x9F61)
+                (#xF3F5 #x9F66)
+                (#xF3F6 #x9F67)
+                (#xF3F7 #x9F6C)
+                (#xF3F8 #x9F6A)
+                (#xF3F9 #x9F77)
+                (#xF3FA #x9F72)
+                (#xF3FB #x9F76)
+                (#xF3FC #x9F95)
+                (#xF3FD #x9F9C)
+                (#xF3FE #x9FA0)
+                (#xF4A1 #x582F)
+                (#xF4A2 #x69C7)
+                (#xF4A3 #x9059)
+                (#xF4A4 #x7464)
+                (#xF4A5 #x51DC)
+                (#xF4A6 #x7199)
+                )))
+        
+  (dolist (i `((,cp932-only
+                ,*cp932-to-ucs-hash*
+                ,*ucs-to-cp932-hash*)
+               (,eucjp-only
+                ,*eucjp-to-ucs-hash*
+                ,*ucs-to-eucjp-hash*)
+               (,eucjp
+                ,*eucjp-to-ucs-hash*
+                ,*ucs-to-eucjp-hash*)))
+    (dolist (j (first i))
+      (setf (gethash (car j) (second i)) (cadr j))
+      (setf (gethash (cadr j) (third i)) (car j))))
+
+  (flet ((euc-cp932 (x)
+           (let ((high (ash x -16))
+                 (mid (logand (ash x -8) 255))
+                 (low (logand x 255)))
+             (cond ((not (zerop high))
+                    nil)
+                   ((= mid #x8e)
+                    (logand x 255))
+                   ((zerop mid)
+                    x)
+                   ((decf mid #xa1)
+                    (decf low #x80)
+                    (incf low (if (zerop (logand mid 1)) #x1f #x7e))
+                    (incf low (if (<= #x7f low #x9d) 1 0))
+                    (setq mid (ash mid -1))
+                    (incf mid (if (<= mid #x1e) #x81 #xc1))
+                    (+ (ash mid 8) low))))))
+    (dolist (i eucjp)
+      (let ((cp932 (euc-cp932 (first i))))
+        (setf (gethash cp932 *cp932-to-ucs-hash*) (second i))
+        (setf (gethash (second i) *ucs-to-cp932-hash*) cp932))))
+
+;; ascii
+  (loop for i from #x00 to #x7f
+        do
+        (setf (gethash i *cp932-to-ucs-hash*) i)
+        (setf (gethash i *eucjp-to-ucs-hash*) i)
+        (setf (gethash i *ucs-to-eucjp-hash*) i)
+        (setf (gethash i *ucs-to-cp932-hash*) i))
+
+;; half-width katakana
+  (loop for i from #xa1 to #xdf
+        do
+        (setf (gethash i *cp932-to-ucs-hash*) (+ #xff61 #x-a1 i))
+        (setf (gethash (+ #xff61 #x-a1 i) *ucs-to-cp932-hash*) i)
+        (setf (gethash (+ #x8e00 i) *eucjp-to-ucs-hash*) (+ #xff61 #x-a1 i))
+        (setf (gethash (+ #xff61 #x-a1 i) *ucs-to-eucjp-hash*) (+ #x8e00 i))))
+
+(defun eucjp-to-ucs (code)
+  (values (gethash code *eucjp-to-ucs-hash*)))
+
+(defun ucs-to-eucjp (code)
+  (values (gethash code *ucs-to-eucjp-hash*)))
+
+(defun cp932-to-ucs (code)
+  (values (gethash code *cp932-to-ucs-hash*)))
+
+(defun ucs-to-cp932 (code)
+  (values (gethash code *ucs-to-cp932-hash*)))
+
+
+(defmacro define-jp-encoding (name docstring aliases max-units-per-char
+                              from-ucs
+                              to-ucs
+                              length-by-code
+                              length-by-1st-unit)
+  `(define-character-encoding ,name
+       ,docstring
+     :aliases ,aliases
+     :native-endianness nil
+     :max-units-per-char ,max-units-per-char
+     :stream-encode-function
+     (lambda (char write-function stream)
+       (let ((code (,from-ucs (char-code char))))
+         (cond ((null code)
+                (funcall write-function stream #.(char-code #\?))
+                1)
+               ((< code #x100)
+                (funcall write-function stream code)
+                1)
+               ((< code #x10000)
+                (funcall write-function stream (logand #xff (ash code -8)))
+                (funcall write-function stream (logand code #xff))
+                2)
+               (t
+                (funcall write-function stream (logand #xff (ash code -16)))
+                (funcall write-function stream (logand #xff (ash code -8)))
+                (funcall write-function stream (logand code #xff))
+                3))))
+     :stream-decode-function
+     (lambda (1st-unit next-unit-function stream)
+       (declare (type (unsigned-byte 8) 1st-unit))
+       (let ((code
+              (case ,length-by-1st-unit
+                (3 (let ((2nd-unit (funcall next-unit-function stream)))
+                     (if (eq 2nd-unit :eof)
+                         :eof
+                         (let ((3rd-unit (funcall next-unit-function stream)))
+                           (if (eq 3rd-unit :eof)
+                               :eof
+                               (logior #x8f0000
+                                       (ash 2nd-unit 8)
+                                       3rd-unit))))))
+                (2 (let ((2nd-unit (funcall next-unit-function stream)))
+                     (if (eq 2nd-unit :eof)
+                         :eof
+                         (logior (ash 1st-unit 8)
+                                 2nd-unit))))
+                (1 1st-unit))))
+         (if (eq code :eof)
+             :eof
+             (let ((ucs (,to-ucs code)))
+               (if ucs
+                   (code-char ucs)
+                   #\?)))))
+     :vector-encode-function
+     (lambda (string vector idx start end)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+                (fixnum idx))
+       (do* ((i start (1+ i)))
+            ((>= i end) idx)
+         (let* ((char (schar string i))
+                (code (,from-ucs (char-code char))))
+           (cond ((null code)
+                  (setf (aref vector idx) #.(char-code #\?))
+                  (incf idx))
+                 ((< code #x100)
+                  (setf (aref vector idx) code)
+                  (incf idx))
+                 ((< code #x10000)
+                  (setf (aref vector idx) (logand #xff (ash code -8)))
+                  (setf (aref vector (the fixnum (1+ idx))) (logand code #xff))
+                  (incf idx 2))
+                 (t
+                  (setf (aref vector idx) (logand #xff (ash code -16)))
+                  (setf (aref vector (the fixnum (1+ idx)))
+                        (logand #xff (ash code -8)))
+                  (setf (aref vector (the fixnum (+ idx 2))) (logand code #xff))
+                  (incf idx 3))))))
+     :vector-decode-function
+     (lambda (vector idx noctets string)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector)
+                (type index idx))
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx (1+ index)))
+            ((= index end) index)
+         (let* ((1st-unit (aref vector index)))
+           (declare (type (unsigned-byte 8) 1st-unit))
+           (let* ((code (,to-ucs
+                         (case ,length-by-1st-unit
+                           (3 (logior
+                               #x8f0000
+                               (ash (aref vector (incf index)) 8)
+                               (aref vector (incf index))))
+                           (2 (logior
+                               (ash 1st-unit 8)
+                               (aref vector (incf index))))
+                           (1 1st-unit))))
+                  (char (and code (code-char code))))
+             (setf (schar string i) (or char #\?))))))
+     :memory-encode-function
+     (lambda (string pointer idx start end)
+       (declare (fixnum idx))
+       (do* ((i start (1+ i)))
+            ((>= i end) idx)
+         (let* ((code (,from-ucs (char-code (schar string i)))))
+           (cond ((null code)
+                  (setf (%get-unsigned-byte pointer idx) #.(char-code #\?))
+                  (incf idx))
+                 ((< code #x100)
+                  (setf (%get-unsigned-byte pointer idx) code)
+                  (incf idx))
+                 ((< code #x10000)
+                  (setf (%get-unsigned-byte pointer idx)
+                        (logand #xff (ash code -8)))
+                  (setf (%get-unsigned-byte pointer (the fixnum (1+ idx)))
+                        (logand code #xff))
+                  (incf idx 2))
+                 (t
+                  (setf (%get-unsigned-byte pointer idx)
+                        (logand #xff (ash code -16)))
+                  (setf (%get-unsigned-byte pointer (the fixnum (1+ idx)))
+                        (logand #xff (ash code -8)))
+                  (setf (%get-unsigned-byte pointer (the fixnum (+ 2 idx)))
+                        (logand code #xff))
+                  (incf idx 3))))))
+     :memory-decode-function
+     (lambda (pointer noctets idx string)
+       (declare (fixnum noctets idx))
+       (do* ((i 0 (1+ i))
+             (end (+ idx noctets))
+             (index idx (1+ index)))
+            ((>= index end) (if (= index end) index 0))
+         (let* ((1st-unit (%get-unsigned-byte pointer index)))
+           (declare (type (unsigned-byte 8) 1st-unit))
+           (let* ((code
+                   (,to-ucs
+                    (case ,length-by-1st-unit
+                      (3 (logior
+                          #x8f0000
+                          (ash (%get-unsigned-byte
+                                pointer (incf index)) 8)
+                          (%get-unsigned-byte pointer (incf index))))
+                      (2 (logior
+                          (ash 1st-unit 8)
+                          (%get-unsigned-byte pointer (incf index))))
+                      (1 1st-unit))))
+                  (char (if code (code-char code) #\?)))
+             (setf (schar string i) char)))))
+     :octets-in-string-function
+     (lambda (string start end)
+       (if (>= end start)
+           (do* ((noctets 0)
+                 (i start (1+ i)))
+                ((= i end) noctets)
+             (declare (fixnum noctets))
+             (let* ((code (,from-ucs (char-code (schar string i)))))
+               (if code
+                   (incf noctets ,length-by-code)
+                   (incf noctets))))
+           0))
+     :length-of-vector-encoding-function
+     (lambda (vector start end)
+       (declare (type (simple-array (unsigned-byte 8) (*)) vector))
+       (do* ((i start)
+             (nchars 0))
+            ((>= i end)
+             (values nchars i))
+         (declare (fixnum i))
+         (let* ((1st-unit (aref vector i))
+                (nexti (+ i ,length-by-1st-unit)))
+           (declare (type (unsigned-byte 8) 1st-unit))
+           (if (> nexti end)
+               (return (values nchars i))
+               (setq nchars (1+ nchars) i nexti)))))
+     :length-of-memory-encoding-function
+     (lambda (pointer noctets start)
+       (do* ((i start)
+             (end (+ start noctets))
+             (nchars 0 (1+ nchars)))
+            ((= i end) (values nchars (- i start)))
+         (let* ((1st-unit (%get-unsigned-byte pointer i))
+                (nexti (+ i ,length-by-1st-unit)))
+           (declare (type (unsigned-byte 8) 1st-unit))
+           (if (> nexti end)
+               (return (values nchars (- i start)))
+               (setq i nexti)))))
+     :decode-literal-code-unit-limit #x80
+     :encode-literal-char-code-limit #x80
+     :character-size-in-octets-function
+     (lambda (c)
+       (let ((code (,from-ucs (char-code c))))
+         (if code
+             ,length-by-code
+             1)))))
+
+
+(define-jp-encoding :euc-jp
+    "An 8-bit, variable-length character encoding in which
+character code points in the range #x00-#x7f can be encoded in a
+single octet; characters with larger code values can be encoded
+in 2 to 3 bytes."
+  '(:eucjp)
+  3
+  ucs-to-eucjp
+  eucjp-to-ucs
+  (cond ((< code #x100) 1)
+        ((< code #x10000) 2)
+        (t 3))
+  (cond ((= 1st-unit #x8f)
+         3)
+        ((or (= 1st-unit #x8e)
+             (< #xa0 1st-unit #xff))
+         2)
+        (t 1)))
+
+(define-jp-encoding :windows-31j
+    "An 8-bit, variable-length character encoding in which
+character code points in the range #x00-#x7f can be encoded in a
+single octet; characters with larger code values can be encoded
+in 2 bytes."
+  '(:cp932 :csWindows31J)
+  2
+  ucs-to-cp932
+  cp932-to-ucs
+  (cond ((< code #x100) 1)
+        (t 2))
+  (cond ((or (<= #x81 1st-unit #x9f)
+             (<= #xe0 1st-unit #xfc))
+         2)
+        (t 1)))
Index: /branches/new-random/library/leaks.lisp
===================================================================
--- /branches/new-random/library/leaks.lisp	(revision 13309)
+++ /branches/new-random/library/leaks.lisp	(revision 13309)
@@ -0,0 +1,365 @@
+;;;-*-Mode: LISP; Package: ccl -*-
+;;;
+;;;   Copyright (C) 2008-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; leaks.lisp
+; A few functions to help in finding memory leaks
+
+(in-package :ccl)
+
+;; Returns all objects that satisfy predicate of one of the types in
+;; ccl::*heap-utilization-vector-type-names*
+;; Note that these can contain stack-consed objects that are dead.
+;; Use pointer-in-some-dynamic-area-p to be sure to follow only real objects
+;; (ccl::heap-utilization) prints a useful list of object counts and sizes
+;; per type.
+(defun all-objects-of-type (type &optional predicate)
+  (let ((typecode (position type ccl::*heap-utilization-vector-type-names*))
+        (res nil))
+    (when typecode
+      (flet ((mapper (thing)
+               (when (and (eq typecode (ccl::typecode thing))
+                          (or (null predicate) (funcall predicate thing)))
+                 (push thing res))))
+        (declare (dynamic-extent #'mapper))
+        (ccl::%map-areas #'mapper))
+      res)))
+
+;; Counts objects that satisfy predicate of one of the types in
+;; ccl::*heap-utilization-vector-type-names*
+(defun count-objects-of-type (type &optional predicate)
+  (let ((typecode (position type ccl::*heap-utilization-vector-type-names*))
+        (res 0))
+    (when typecode
+      (flet ((mapper (thing)
+               (when (and (eq typecode (ccl::typecode thing))
+                          (or (null predicate) (funcall predicate thing)))
+                 (incf res))))
+        (declare (dynamic-extent #'mapper))
+        (ccl::%map-areas #'mapper))
+      res)))
+
+(defun count-conses ()
+  (let ((res 0))
+    (flet ((mapper (thing)
+             (when (consp thing) (incf res))))
+      (declare (dynamic-extent #'mapper))
+      (ccl::%map-areas #'mapper))
+    res))
+
+;; Like set-difference, but uses a hash table to go faster.
+(defun fast-set-difference (list1 list2 &optional (test #'eq))
+  (let ((hash (make-hash-table :test test))
+        (res nil))
+    (dolist (e1 list1) (setf (gethash e1 hash) t))
+    (dolist (e2 list2) (remhash e2 hash))
+    (maphash (lambda (k v)
+               (declare (ignore v))
+               (push k res))
+             hash)
+    res))
+
+;; Returns all references to object.
+;; Note that these can contain stack-consed objects that are dead.
+;; Use pointer-in-some-dynamic-area-p to be sure to follow only real objects
+(defun find-references (object)
+  (let ((res nil))
+    (ccl::%map-areas
+     (lambda (thing)
+       (cond ((and (not (eq thing object))
+                   (ccl::uvectorp thing)
+                   (not (ccl::ivectorp thing)))
+              (dotimes (i (ccl::uvsize thing))
+                (when (eq object (ccl::uvref thing i))
+                  (push thing res)
+                  (return))))
+             ((consp thing)
+              (when(or (eq object (car thing))
+                       (eq object (cdr thing)))
+                (push thing res))))))
+    res))
+
+;; Return true if P is heap-consed
+(defun pointer-in-some-dynamic-area-p (p)
+ (block found
+   (ccl::do-consing-areas (a)
+     (when (eql (%fixnum-ref a target::area.code) ccl::area-dynamic)
+       (when (ccl::%ptr-in-area-p p a)
+         (return-from found t))))))
+
+;; Find all transitive referencers to object-or-list. If as-object is
+;; true, just start with object-or-list. If as-object is false, then if
+;; object-or-list is a list, start with its elements, and ignore its
+;; cons cells.
+;; Returns a hash table with the references as keys.
+(defun transitive-referencers (object-or-list &optional as-object)
+  (let ((found (make-hash-table :test 'eq)))
+    (cond ((or (atom object-or-list) as-object)
+           (setf (gethash object-or-list found) t))
+          (t (loop for cons on object-or-list
+                   do
+                (setf (gethash cons found) t
+                      (gethash (car cons) found) t))))
+    (ccl:gc)
+    (format t "Searching") (finish-output)
+    (loop
+      (let ((added-one nil))
+        (format t " ~d" (hash-table-count found)) (finish-output)
+        (ccl::%map-areas
+         (lambda (thing)
+           (unless (or (not (pointer-in-some-dynamic-area-p thing))
+                       (gethash thing found))
+             (cond ((and (not (eq thing (ccl::nhash.vector found)))
+                         (ccl::uvectorp thing)
+                         (not (ccl::ivectorp thing))
+                         (not (packagep thing)))
+                    (dotimes (i (ccl::uvsize thing))
+                      (let ((object (ccl::uvref thing i)))
+                        (when (gethash object found)
+                          (setf (gethash thing found) t
+                                added-one t)
+                          (return)))))
+                   ((and (consp thing)
+                         (pointer-in-some-dynamic-area-p (car thing))
+                         (pointer-in-some-dynamic-area-p (cdr thing)))
+                    (when (or (gethash (car thing) found)
+                              (gethash (cdr thing) found))
+                      (setf (gethash thing found) t)))))))
+        (unless added-one
+          (return))))
+    (format t " done.~%") (finish-output)
+    ;; Eliminate any cons that is referenced by another cons.
+    ;; Also eliminate or replace objects that nobody will want to see.
+    (let ((cons-refs (make-hash-table :test 'eq))
+          (additions nil))
+      (loop for cons being the hash-keys of found
+            when (consp cons)
+              do
+           (when (consp (car cons))
+             (setf (gethash (car cons) cons-refs) t))
+           (when (consp (cdr cons))
+             (setf (gethash (cdr cons) cons-refs) t)))
+      (loop for key being the hash-keys of found
+            when (or (and (consp key) (gethash key cons-refs))
+                     (and (consp key) (eq (car key) 'ccl::%function-source-note))
+                     (typep key 'ccl::hash-table-vector)
+                     (when (and key
+				(typep key
+				  #+x8664-target 'ccl::symbol-vector
+				  #-x8664-target 'symbol
+				  ))
+                       (push (ccl::symvector->symptr key) additions)
+                       t)
+                     (when (typep key
+				  #+x8664-target 'ccl::function-vector
+				  #-x8664-target 'function
+				  )
+                       (push (ccl::function-vector-to-function key) additions)
+                       t))
+              do
+              (remhash key found))
+      (dolist (addition additions)
+        (setf (gethash addition found) t))
+      (remhash object-or-list found)
+      (unless (or (atom object-or-list) as-object)
+        (loop for cons on object-or-list
+             do
+             (remhash cons found)
+             (remhash (car cons) found)))
+      found)))
+
+;; One convenient way to print the hash table returned by transitive-referencers
+(defun print-referencers (hash &key
+                          predicate
+                          (pause-period 20)
+                          (print-circle t)
+                          (print-length 20)
+                          (print-level 5))
+  (let ((cnt 0)
+        (*print-circle* print-circle)
+        (*print-length* print-length)
+        (*print-level* print-level))
+    (maphash (lambda (key value)
+               (declare (ignore value))
+               (when (or (null predicate) (funcall predicate key))
+                 (format t "~s~%" key)
+                 (when (> (incf cnt) pause-period)
+                   (format t "Continue (Y/N)? ")
+                   (unless (equalp (read-line) "Y")
+                     (return-from print-referencers))
+                   (setq cnt 0))))
+             hash)))
+
+;; Returns all the obsolete CLOS instances, those whose class has been
+;; changed since they were created. Each will be updated as soon as
+;; method dispatch is done on it."
+(defun obsolete-instances (list)
+  (let ((res nil))
+    (dolist (i list)
+      (when (eq 0 (ccl::%wrapper-hash-index (ccl::instance-class-wrapper i)))
+        (push i res)))
+    res))
+
+;; Linux-only malloc leak finding
+#+linux-target
+(progn
+
+;; (ccl::start-mtrace LOGFILE)
+;; Do some work.
+;; (ccl::stop-mtrace)
+;; (ccl::parse-mtrace-log LOGFILE)
+(defun start-mtrace (log-file)
+  (touch log-file)
+  (setf log-file (probe-file log-file))
+  (setenv "MALLOC_TRACE" (namestring log-file))
+  (gc)
+  (#_mtrace))
+
+(defun stop-mtrace ()
+  (gc)
+  (#_muntrace))
+
+(defun parse-mtrace-log (log-file)
+  (with-open-file (s log-file)
+    (let ((hash (make-hash-table :test 'equal))
+          (free-list '())
+          (eof (list :eof)))
+      (loop for line = (read-line s nil eof)
+            until (eq line eof)
+            when (and (> (length line) 2)
+                      (equal "@ " (subseq line 0 2)))
+              do
+           (setf line (subseq line 2))
+           (let ((plus-pos (or (search " + " line) (search " > " line)))
+                 (minus-pos (or (search " - " line) (search " < " line))))
+             (cond (plus-pos
+                    (let* ((where (subseq line 0 plus-pos))
+                           (addr-and-size (subseq line (+ plus-pos 3)))
+                           (space-pos (position #\space addr-and-size))
+                           (addr (subseq addr-and-size 0 space-pos))
+                           (size (subseq addr-and-size (1+ space-pos))))
+                      (setf (gethash addr hash) (list where size))))
+                   (minus-pos
+                    (let* ((where (subseq line 0 minus-pos))
+                           (addr (subseq line (+ minus-pos 3)))
+                           (found (nth-value 1 (gethash addr hash))))
+                      (if found
+                        (remhash addr hash)
+                        (push (list where addr) free-list)))))))
+      (let ((res nil))
+        (maphash (lambda (key value)
+                   (push (append value (list key)) res))
+                 hash)
+        (values res free-list)))))
+
+(defun pretty-print-mtrace-summary (file)
+  (let* ((malloc-sum 0))
+    (multiple-value-bind (mallocs frees) (parse-mtrace-log file)
+      (dolist (i mallocs)
+        (incf malloc-sum (parse-integer (second i) :radix 16 :start 2))
+        (format t "~&~A" i))
+      (format t "~&Freed but not malloced:~%~{~A~%~}" frees)
+      (format t "~&total-malloc-not-freed: ~A ~A free not malloc: ~A"
+              (/ malloc-sum 1024.0)
+              (length mallocs)
+              (length frees)))))
+
+;; Return the total number of bytes allocated by malloc()
+(defun mallinfo ()
+  (ccl:rlet ((mallinfo :mallinfo))
+    (#_mallinfo mallinfo)
+    (ccl::rref mallinfo :mallinfo.uordblks)))
+
+#||
+http://www.gnu.org/s/libc/manual/html_node/Statistics-of-Malloc.html
+
+int arena
+    This is the total size of memory allocated with sbrk by malloc, in bytes.
+int ordblks
+    This is the number of chunks not in use. (The memory allocator internally gets chunks of memory from the operating system, and then carves them up to satisfy individual malloc requests; see Efficiency and Malloc.)
+int smblks
+    This field is unused.
+int hblks
+    This is the total number of chunks allocated with mmap.
+int hblkhd
+    This is the total size of memory allocated with mmap, in bytes.
+int usmblks
+    This field is unused.
+int fsmblks
+    This field is unused.
+int uordblks
+    This is the total size of memory occupied by chunks handed out by malloc.
+int fordblks
+    This is the total size of memory occupied by free (not in use) chunks.
+int keepcost
+    This is the size of the top-most releasable chunk that normally borders the end of the heap (i.e., the high end of the virtual address space's data segment).
+||#    
+
+(defun show-malloc-info ()
+  (rlet ((info :mallinfo))
+    (#_mallinfo info)                   ;struct return invisible arg.
+    (let* ((arena (pref info :mallinfo.arena))
+           (ordblks (pref info :mallinfo.ordblks))
+           (hblks (pref info :mallinfo.hblks))
+           (hblkhd (pref info :mallinfo.hblkhd))
+           (uordblks (pref info :mallinfo.uordblks))
+           (fordblks (pref info :mallinfo.fordblks))
+           (keepcost (pref info :mallinfo.keepcost)))
+      (format t "~& arena size: ~d/#x~x" arena arena)
+      (format t "~& number of unused chunks = ~d" ordblks)
+      (format t "~& number of mmap'ed chunks = ~d" hblks)
+      (format t "~& total size of mmap'ed chunks = ~d/#x~x" hblkhd hblkhd)
+      (format t "~& total size of malloc'ed chunks = ~d/#x~x" uordblks uordblks)
+      (format t "~& total size of free chunks = ~d/#x~x" fordblks fordblks)
+      (format t "~& size of releaseable chunk = ~d/#x~x" keepcost keepcost))))
+
+)  ;; end of linux-only code
+
+(defun get-allocation-sentinel (&key (gc-first t))
+  ;; Return the object with the highest address that can be guaranteed to be at a lower
+  ;; address than any newer objects.
+  ;; If gc-first is true, can also conversely guarantee that all older objects are at a
+  ;; lower address than the sentinel.  If gc-first is false, than there may be some
+  ;; already-allocated objects at higher addresses, though no more than the size of the
+  ;; youngest generation (and usually even less than that). Second value returned is the
+  ;; size of the active region above the sentinel.
+  (with-other-threads-suspended
+    (when gc-first (gc)) ;; get rid of thread allocation chunks.  Wish could just egc...
+    ;; This mustn't cons.
+    (let* ((first-area (%normalize-areas)) ;; youngest generation
+           (min-base (loop with current = (%current-tcr)
+                           for tcr = (%fixnum-ref current target::tcr.next)
+                             then (%fixnum-ref tcr target::tcr.next)
+                           as base fixnum = (%fixnum-ref tcr target::tcr.save-allocbase)
+                           when (> base 0)
+                             minimize base
+                           until (eql tcr current)))
+           (active (%fixnum-ref first-area  target::area.active))
+           (limit (if (eql min-base 0) active min-base))
+           (last-obj nil))
+      ;; Normally will find it in the youngest generation, but loop in case limit = area.low.
+      (block walk
+        (flet ((skip (obj)
+                 (declare (optimize (speed 3) (safety 0))) ;; lie
+                 (unless (%i< obj limit)
+                   (return-from walk))
+                 (setq last-obj obj)))
+          (declare (dynamic-extent #'skip))
+          (loop for area = first-area then (%fixnum-ref area target::area.succ)
+                until (neq (%fixnum-ref area target::area.code) area-dynamic)
+                when (< (%fixnum-ref area target::area.low) (%fixnum-ref area target::area.active))
+                  do (walk-static-area area #'skip))))
+      (values last-obj (%i- active limit)))))
+
Index: /branches/new-random/library/lisp-package.lisp
===================================================================
--- /branches/new-random/library/lisp-package.lisp	(revision 13309)
+++ /branches/new-random/library/lisp-package.lisp	(revision 13309)
@@ -0,0 +1,1650 @@
+;;;-*-Mode: LISP; Package: ccl -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+; lisp-package.lisp
+; Define a lisp package that attempts to behave like CLTL-1.
+
+(in-package "CCL")
+
+(defpackage "LISP"
+  (:use )
+  (:import-from "COMMON-LISP"
+                "&ALLOW-OTHER-KEYS"
+                "&AUX"
+                "&BODY"
+                "&ENVIRONMENT"
+                "&KEY"
+                "&OPTIONAL"
+                "&REST"
+                "&WHOLE"
+                "*"
+                "**"
+                "***"
+                "*DEBUG-IO*"
+                "*DEFAULT-PATHNAME-DEFAULTS*"
+                "*ERROR-OUTPUT*"
+                "*FEATURES*"
+                "*LOAD-VERBOSE*"
+                "*MACROEXPAND-HOOK*"
+                "*PACKAGE*"
+                "*PRINT-ARRAY*"
+                "*PRINT-BASE*"
+                "*PRINT-CASE*"
+                "*PRINT-CIRCLE*"
+                "*PRINT-ESCAPE*"
+                "*PRINT-GENSYM*"
+                "*PRINT-LENGTH*"
+                "*PRINT-LEVEL*"
+                "*PRINT-PRETTY*"
+                "*PRINT-RADIX*"
+                "*QUERY-IO*"
+                "*RANDOM-STATE*"
+                "*READ-BASE*"
+                "*READ-DEFAULT-FLOAT-FORMAT*"
+                "*READ-SUPPRESS*"
+                "*READTABLE*"
+                "*STANDARD-INPUT*"
+                "*STANDARD-OUTPUT*"
+                "*TERMINAL-IO*"
+                "*TRACE-OUTPUT*"
+                "+"
+                "++"
+                "+++"
+                "-"
+                "/"
+                "//"
+                "///"
+                "/="
+                "1+"
+                "1-"
+                "<"
+                "<="
+                "="
+                ">"
+                ">="
+                "ABS"
+                "ACONS"
+                "ACOS"
+                "ACOSH"
+                "ADJOIN"
+                "ADJUST-ARRAY"
+                "ADJUSTABLE-ARRAY-P"
+                "ALPHA-CHAR-P"
+                "ALPHANUMERICP"
+                "AND"
+                "APPEND"
+                "APPLY"
+                "APROPOS"
+                "APROPOS-LIST"
+                "AREF"
+                "ARRAY"
+                "ARRAY-DIMENSION"
+                "ARRAY-DIMENSION-LIMIT"
+                "ARRAY-DIMENSIONS"
+                "ARRAY-ELEMENT-TYPE"
+                "ARRAY-HAS-FILL-POINTER-P"
+                "ARRAY-IN-BOUNDS-P"
+                "ARRAY-RANK"
+                "ARRAY-RANK-LIMIT"
+                "ARRAY-ROW-MAJOR-INDEX"
+                "ARRAY-TOTAL-SIZE"
+                "ARRAY-TOTAL-SIZE-LIMIT"
+                "ARRAYP"
+                "ASH"
+                "ASIN"
+                "ASINH"
+                "ASSERT"
+                "ASSOC"
+                "ASSOC-IF"
+                "ASSOC-IF-NOT"
+                "ATAN"
+                "ATANH"
+                "ATOM"
+                "BIGNUM"
+                "BIT"
+                "BIT-AND"
+                "BIT-ANDC1"
+                "BIT-ANDC2"
+                "BIT-EQV"
+                "BIT-IOR"
+                "BIT-NAND"
+                "BIT-NOR"
+                "BIT-NOT"
+                "BIT-ORC1"
+                "BIT-ORC2"
+                "BIT-VECTOR"
+                "BIT-VECTOR-P"
+                "BIT-XOR"
+                "BLOCK"
+                "BOOLE"
+                "BOOLE-1"
+                "BOOLE-2"
+                "BOOLE-AND"
+                "BOOLE-ANDC1"
+                "BOOLE-ANDC2"
+                "BOOLE-C1"
+                "BOOLE-C2"
+                "BOOLE-CLR"
+                "BOOLE-EQV"
+                "BOOLE-IOR"
+                "BOOLE-NAND"
+                "BOOLE-NOR"
+                "BOOLE-ORC1"
+                "BOOLE-ORC2"
+                "BOOLE-SET"
+                "BOOLE-XOR"
+                "BOTH-CASE-P"
+                "BOUNDP"
+                "BREAK"
+                "BUTLAST"
+                "BYTE"
+                "BYTE-POSITION"
+                "BYTE-SIZE"
+                "CAAAAR"
+                "CAAADR"
+                "CAAAR"
+                "CAADAR"
+                "CAADDR"
+                "CAADR"
+                "CAAR"
+                "CADAAR"
+                "CADADR"
+                "CADAR"
+                "CADDAR"
+                "CADDDR"
+                "CADDR"
+                "CADR"
+                "CALL-ARGUMENTS-LIMIT"
+                "CAR"
+                "CASE"
+                "CATCH"
+                "CCASE"
+                "CDAAAR"
+                "CDAADR"
+                "CDAAR"
+                "CDADAR"
+                "CDADDR"
+                "CDADR"
+                "CDAR"
+                "CDDAAR"
+                "CDDADR"
+                "CDDAR"
+                "CDDDAR"
+                "CDDDDR"
+                "CDDDR"
+                "CDDR"
+                "CDR"
+                "CEILING"
+                "CERROR"
+                "CHAR"
+                "CHAR-CODE"
+                "CHAR-CODE-LIMIT"
+                "CHAR-DOWNCASE"
+                "CHAR-EQUAL"
+;                "CHAR-FONT"
+                "CHAR-GREATERP"
+                "CHAR-INT"
+                "CHAR-LESSP"
+                "CHAR-NAME"
+                "CHAR-NOT-EQUAL"
+                "CHAR-NOT-GREATERP"
+                "CHAR-NOT-LESSP"
+                "CHAR-UPCASE"
+                "CHAR/="
+                "CHAR<"
+                "CHAR<="
+                "CHAR="
+                "CHAR>"
+                "CHAR>="
+                "CHARACTER"
+                "CHARACTERP"
+                "CHECK-TYPE"
+                "CIS"
+                "CLEAR-INPUT"
+                "CLEAR-OUTPUT"
+                "CLOSE"
+                "CLRHASH"
+                "CODE-CHAR"
+                "COERCE"
+                "COMPILATION-SPEED"
+                "COMPILE"
+                "COMPILE-FILE"
+                "COMPILED-FUNCTION"
+                "COMPILED-FUNCTION-P"
+                "COMPLEX"
+                "COMPLEXP"
+                "CONCATENATE"
+                "COND"
+                "CONJUGATE"
+                "CONS"
+                "CONSP"
+                "CONSTANTP"
+                "COPY-ALIST"
+                "COPY-LIST"
+                "COPY-READTABLE"
+                "COPY-SEQ"
+                "COPY-SYMBOL"
+                "COPY-TREE"
+                "COS"
+                "COSH"
+                "COUNT"
+                "COUNT-IF"
+                "COUNT-IF-NOT"
+                "CTYPECASE"
+                "DECF"
+                "DECLARATION"
+                "DECLARE"
+                "DECODE-FLOAT"
+                "DECODE-UNIVERSAL-TIME"
+                "DEFCONSTANT"
+                "DEFINE-MODIFY-MACRO"
+                "DEFMACRO"
+                "DEFPARAMETER"
+                "DEFSETF"
+                "DEFSTRUCT"
+                "DEFTYPE"
+                "DEFUN"
+                "DEFVAR"
+                "DELETE"
+                "DELETE-DUPLICATES"
+                "DELETE-FILE"
+                "DELETE-IF"
+                "DELETE-IF-NOT"
+                "DENOMINATOR"
+                "DEPOSIT-FIELD"
+                "DESCRIBE"
+                "DIGIT-CHAR-P"
+                "DIRECTORY"
+                "DIRECTORY-NAMESTRING"
+                "DISASSEMBLE"
+                "DO"
+                "DO*"
+                "DO-ALL-SYMBOLS"
+                "DO-EXTERNAL-SYMBOLS"
+                "DO-SYMBOLS"
+                "DOCUMENTATION"
+                "DOLIST"
+                "DOTIMES"
+                "DOUBLE-FLOAT"
+                "DOUBLE-FLOAT-EPSILON"
+                "DOUBLE-FLOAT-NEGATIVE-EPSILON"
+                "DPB"
+                "DRIBBLE"
+                "ECASE"
+                "ED"
+                "EIGHTH"
+                "ELT"
+                "ENCODE-UNIVERSAL-TIME"
+                "ENDP"
+                "ENOUGH-NAMESTRING"
+                "EQ"
+                "EQL"
+                "EQUAL"
+                "EQUALP"
+                "ERROR"
+                "ETYPECASE"
+                "EVAL"
+                "EVAL-WHEN"
+                "EVENP"
+                "EVERY"
+                "EXP"
+                "EXPT"
+                "FBOUNDP"
+                "FCEILING"
+                "FFLOOR"
+                "FIFTH"
+                "FILE-AUTHOR"
+                "FILE-LENGTH"
+                "FILE-NAMESTRING"
+                "FILE-POSITION"
+                "FILE-WRITE-DATE"
+                "FILL"
+                "FILL-POINTER"
+                "FIND"
+                "FIND-ALL-SYMBOLS"
+                "FIND-IF"
+                "FIND-IF-NOT"
+                "FIND-PACKAGE"
+                "FIND-SYMBOL"
+                "FINISH-OUTPUT"
+                "FIRST"
+                "FIXNUM"
+                "FLET"
+                "FLOAT"
+                "FLOAT-DIGITS"
+                "FLOAT-PRECISION"
+                "FLOAT-RADIX"
+                "FLOAT-SIGN"
+                "FLOATP"
+                "FLOOR"
+                "FMAKUNBOUND"
+                "FORCE-OUTPUT"
+                "FORMAT"
+                "FOURTH"
+                "FRESH-LINE"
+                "FROUND"
+                "FTRUNCATE"
+                "FTYPE"
+                "FUNCALL"
+                "FUNCTION"
+                "GCD"
+                "GENSYM"
+                "GENTEMP"
+                "GET"
+                "GET-DECODED-TIME"
+                "GET-DISPATCH-MACRO-CHARACTER"
+                "GET-INTERNAL-REAL-TIME"
+                "GET-INTERNAL-RUN-TIME"
+                "GET-MACRO-CHARACTER"
+                "GET-OUTPUT-STREAM-STRING"
+                "GET-PROPERTIES"
+                "GET-UNIVERSAL-TIME"
+                "GETF"
+                "GETHASH"
+                "GO"
+                "GRAPHIC-CHAR-P"
+                "HASH-TABLE"
+                "HASH-TABLE-COUNT"
+                "HASH-TABLE-P"
+                "HOST-NAMESTRING"
+                "IDENTITY"
+                "IF"
+                "IGNORE"
+                "IMAGPART"
+                "INCF"
+                "INLINE"
+                "INPUT-STREAM-P"
+                "INSPECT"
+                "INTEGER"
+                "INTEGER-DECODE-FLOAT"
+                "INTEGER-LENGTH"
+                "INTEGERP"
+                "INTERN"
+                "INTERNAL-TIME-UNITS-PER-SECOND"
+                "INTERSECTION"
+                "ISQRT"
+                "KEYWORD"
+                "KEYWORDP"
+                "LABELS"
+                "LAMBDA"
+                "LAMBDA-LIST-KEYWORDS"
+                "LAMBDA-PARAMETERS-LIMIT"
+                "LAST"
+                "LCM"
+                "LDB"
+                "LDB-TEST"
+                "LDIFF"
+                "LEAST-NEGATIVE-DOUBLE-FLOAT"
+                "LEAST-NEGATIVE-LONG-FLOAT"
+                "LEAST-NEGATIVE-SHORT-FLOAT"
+                "LEAST-NEGATIVE-SINGLE-FLOAT"
+                "LEAST-POSITIVE-DOUBLE-FLOAT"
+                "LEAST-POSITIVE-LONG-FLOAT"
+                "LEAST-POSITIVE-SHORT-FLOAT"
+                "LEAST-POSITIVE-SINGLE-FLOAT"
+                "LENGTH"
+                "LET"
+                "LET*"
+                "LISP-IMPLEMENTATION-TYPE"
+                "LISP-IMPLEMENTATION-VERSION"
+                "LIST"
+                "LIST*"
+                "LIST-ALL-PACKAGES"
+                "LIST-LENGTH"
+                "LISTEN"
+                "LISTP"
+                "LOAD"
+                "LOCALLY"
+                "LOG"
+                "LOGAND"
+                "LOGANDC1"
+                "LOGANDC2"
+                "LOGBITP"
+                "LOGCOUNT"
+                "LOGEQV"
+                "LOGIOR"
+                "LOGNAND"
+                "LOGNOR"
+                "LOGNOT"
+                "LOGORC1"
+                "LOGORC2"
+                "LOGTEST"
+                "LOGXOR"
+                "LONG-FLOAT"
+                "LONG-FLOAT-EPSILON"
+                "LONG-FLOAT-NEGATIVE-EPSILON"
+                "LONG-SITE-NAME"
+                "LOOP"
+                "LOWER-CASE-P"
+                "MACHINE-INSTANCE"
+                "MACHINE-TYPE"
+                "MACHINE-VERSION"
+                "MACRO-FUNCTION"
+                "MACROEXPAND"
+                "MACROEXPAND-1"
+                "MACROLET"
+                "MAKE-ARRAY"
+                "MAKE-BROADCAST-STREAM"
+                "MAKE-CONCATENATED-STREAM"
+                "MAKE-DISPATCH-MACRO-CHARACTER"
+                "MAKE-ECHO-STREAM"
+                "MAKE-HASH-TABLE"
+                "MAKE-LIST"
+                "MAKE-PATHNAME"
+                "MAKE-RANDOM-STATE"
+                "MAKE-SEQUENCE"
+                "MAKE-STRING"
+                "MAKE-STRING-INPUT-STREAM"
+                "MAKE-STRING-OUTPUT-STREAM"
+                "MAKE-SYMBOL"
+                "MAKE-SYNONYM-STREAM"
+                "MAKE-TWO-WAY-STREAM"
+                "MAKUNBOUND"
+                "MAP"
+                "MAPC"
+                "MAPCAN"
+                "MAPCAR"
+                "MAPCON"
+                "MAPHASH"
+                "MAPL"
+                "MAPLIST"
+                "MASK-FIELD"
+                "MAX"
+                "MEMBER"
+                "MEMBER-IF"
+                "MEMBER-IF-NOT"
+                "MERGE"
+                "MERGE-PATHNAMES"
+                "MIN"
+                "MINUSP"
+                "MISMATCH"
+                "MOD"
+                "MOST-NEGATIVE-DOUBLE-FLOAT"
+                "MOST-NEGATIVE-FIXNUM"
+                "MOST-NEGATIVE-LONG-FLOAT"
+                "MOST-NEGATIVE-SHORT-FLOAT"
+                "MOST-NEGATIVE-SINGLE-FLOAT"
+                "MOST-POSITIVE-DOUBLE-FLOAT"
+                "MOST-POSITIVE-FIXNUM"
+                "MOST-POSITIVE-LONG-FLOAT"
+                "MOST-POSITIVE-SHORT-FLOAT"
+                "MOST-POSITIVE-SINGLE-FLOAT"
+                "MULTIPLE-VALUE-BIND"
+                "MULTIPLE-VALUE-CALL"
+                "MULTIPLE-VALUE-LIST"
+                "MULTIPLE-VALUE-PROG1"
+                "MULTIPLE-VALUE-SETQ"
+                "MULTIPLE-VALUES-LIMIT"
+                "NAME-CHAR"
+                "NAMESTRING"
+                "NBUTLAST"
+                "NCONC"
+                "NIL"
+                "NINTERSECTION"
+                "NINTH"
+                "NOT"
+                "NOTANY"
+                "NOTEVERY"
+                "NOTINLINE"
+                "NRECONC"
+                "NREVERSE"
+                "NSET-DIFFERENCE"
+                "NSET-EXCLUSIVE-OR"
+                "NSTRING-CAPITALIZE"
+                "NSTRING-DOWNCASE"
+                "NSTRING-UPCASE"
+                "NSUBLIS"
+                "NSUBST"
+                "NSUBST-IF"
+                "NSUBST-IF-NOT"
+                "NSUBSTITUTE"
+                "NSUBSTITUTE-IF"
+                "NSUBSTITUTE-IF-NOT"
+                "NTH"
+                "NTHCDR"
+                "NULL"
+                "NUMBER"
+                "NUMBERP"
+                "NUMERATOR"
+                "NUNION"
+                "ODDP"
+                "OPEN"
+                "OPTIMIZE"
+                "OR"
+                "OTHERWISE"
+                "OUTPUT-STREAM-P"
+                "PACKAGE"
+                "PACKAGE-NAME"
+                "PACKAGE-NICKNAMES"
+                "PACKAGE-SHADOWING-SYMBOLS"
+                "PACKAGE-USE-LIST"
+                "PACKAGE-USED-BY-LIST"
+                "PACKAGEP"
+                "PAIRLIS"
+                "PARSE-INTEGER"
+                "PARSE-NAMESTRING"
+                "PATHNAME"
+                "PATHNAME-DEVICE"
+                "PATHNAME-DIRECTORY"
+                "PATHNAME-HOST"
+                "PATHNAME-NAME"
+                "PATHNAME-TYPE"
+                "PATHNAME-VERSION"
+                "PATHNAMEP"
+                "PEEK-CHAR"
+                "PHASE"
+                "PI"
+                "PLUSP"
+                "POP"
+                "POSITION"
+                "POSITION-IF"
+                "POSITION-IF-NOT"
+                "PPRINT"
+                "PRIN1"
+                "PRIN1-TO-STRING"
+                "PRINC"
+                "PRINC-TO-STRING"
+                "PRINT"
+                "PROBE-FILE"
+                "PROCLAIM"
+                "PROG"
+                "PROG*"
+                "PROG1"
+                "PROG2"
+                "PROGN"
+                "PROGV"
+                "PSETF"
+                "PSETQ"
+                "PUSH"
+                "PUSHNEW"
+                "QUOTE"
+                "RANDOM"
+                "RANDOM-STATE"
+                "RANDOM-STATE-P"
+                "RASSOC"
+                "RASSOC-IF"
+                "RASSOC-IF-NOT"
+                "RATIO"
+                "RATIONAL"
+                "RATIONALIZE"
+                "RATIONALP"
+                "READ"
+                "READ-BYTE"
+                "READ-CHAR"
+                "READ-CHAR-NO-HANG"
+                "READ-DELIMITED-LIST"
+                "READ-FROM-STRING"
+                "READ-LINE"
+                "READ-PRESERVING-WHITESPACE"
+                "READTABLE"
+                "READTABLEP"
+                "REALPART"
+                "REDUCE"
+                "REM"
+                "REMF"
+                "REMHASH"
+                "REMOVE"
+                "REMOVE-DUPLICATES"
+                "REMOVE-IF"
+                "REMOVE-IF-NOT"
+                "REMPROP"
+                "RENAME-FILE"
+                "RENAME-PACKAGE"
+                "REPLACE"
+                "REST"
+                "RETURN"
+                "RETURN-FROM"
+                "REVAPPEND"
+                "REVERSE"
+                "ROOM"
+                "ROTATEF"
+                "ROUND"
+                "RPLACA"
+                "RPLACD"
+                "SAFETY"
+                "SATISFIES"
+                "SBIT"
+                "SCALE-FLOAT"
+                "SCHAR"
+                "SEARCH"
+                "SECOND"
+                "SEQUENCE"
+                "SET"
+;                "SET-CHAR-BIT"
+                "SET-DIFFERENCE"
+                "SET-DISPATCH-MACRO-CHARACTER"
+                "SET-EXCLUSIVE-OR"
+                "SET-MACRO-CHARACTER"
+                "SET-SYNTAX-FROM-CHAR"
+                "SETF"
+                "SETQ"
+                "SEVENTH"
+                "SHIFTF"
+                "SHORT-FLOAT"
+                "SHORT-FLOAT-EPSILON"
+                "SHORT-FLOAT-NEGATIVE-EPSILON"
+                "SHORT-SITE-NAME"
+                "SIGNED-BYTE"
+                "SIGNUM"
+                "SIMPLE-ARRAY"
+                "SIMPLE-BIT-VECTOR"
+                "SIMPLE-BIT-VECTOR-P"
+                "SIMPLE-STRING"
+                "SIMPLE-STRING-P"
+                "SIMPLE-VECTOR"
+                "SIMPLE-VECTOR-P"
+                "SIN"
+                "SINGLE-FLOAT"
+                "SINGLE-FLOAT-EPSILON"
+                "SINGLE-FLOAT-NEGATIVE-EPSILON"
+                "SINH"
+                "SIXTH"
+                "SLEEP"
+                "SOFTWARE-TYPE"
+                "SOFTWARE-VERSION"
+                "SOME"
+                "SORT"
+                "SPACE"
+                "SPECIAL"
+                "SPEED"
+                "SQRT"
+                "STABLE-SORT"
+                "STANDARD-CHAR"
+                "STANDARD-CHAR-P"
+                "STEP"
+                "STREAM"
+                "STREAM-ELEMENT-TYPE"
+                "STREAMP"
+                "STRING"
+                "STRING-CAPITALIZE"
+;                "STRING-CHAR"
+;                "STRING-CHAR-P"
+                "STRING-DOWNCASE"
+                "STRING-EQUAL"
+                "STRING-GREATERP"
+                "STRING-LEFT-TRIM"
+                "STRING-LESSP"
+                "STRING-NOT-EQUAL"
+                "STRING-NOT-GREATERP"
+                "STRING-NOT-LESSP"
+                "STRING-RIGHT-TRIM"
+                "STRING-TRIM"
+                "STRING-UPCASE"
+                "STRING/="
+                "STRING<"
+                "STRING<="
+                "STRING="
+                "STRING>"
+                "STRING>="
+                "STRINGP"
+                "STRUCTURE"
+                "SUBLIS"
+                "SUBSEQ"
+                "SUBSETP"
+                "SUBST"
+                "SUBST-IF"
+                "SUBST-IF-NOT"
+                "SUBSTITUTE"
+                "SUBSTITUTE-IF"
+                "SUBSTITUTE-IF-NOT"
+                "SUBTYPEP"
+                "SVREF"
+                "SXHASH"
+                "SYMBOL"
+                "SYMBOL-FUNCTION"
+                "SYMBOL-NAME"
+                "SYMBOL-PACKAGE"
+                "SYMBOL-PLIST"
+                "SYMBOL-VALUE"
+                "SYMBOLP"
+                "T"
+                "TAGBODY"
+                "TAILP"
+                "TAN"
+                "TANH"
+                "TENTH"
+                "TERPRI"
+                "THE"
+                "THIRD"
+                "THROW"
+                "TIME"
+                "TRACE"
+                "TREE-EQUAL"
+                "TRUENAME"
+                "TRUNCATE"
+                "TYPE"
+                "TYPE-OF"
+                "TYPECASE"
+                "TYPEP"
+                "UNINTERN"
+                "UNION"
+                "UNLESS"
+                "UNREAD-CHAR"
+                "UNSIGNED-BYTE"
+                "UNTRACE"
+                "UNWIND-PROTECT"
+                "UPPER-CASE-P"
+                "USER-HOMEDIR-PATHNAME"
+                "VALUES"
+                "VALUES-LIST"
+                "VARIABLE"
+                "VECTOR"
+                "VECTOR-POP"
+                "VECTOR-PUSH"
+                "VECTOR-PUSH-EXTEND"
+                "VECTORP"
+                "WARN"
+                "WHEN"
+                "WITH-INPUT-FROM-STRING"
+                "WITH-OPEN-FILE"
+                "WITH-OPEN-STREAM"
+                "WITH-OUTPUT-TO-STRING"
+                "WRITE"
+                "WRITE-BYTE"
+                "WRITE-CHAR"
+                "WRITE-LINE"
+                "WRITE-STRING"
+                "WRITE-TO-STRING"
+                "Y-OR-N-P"
+                "YES-OR-NO-P"
+                "ZEROP"
+		"*MODULES*"
+		"PROVIDE"
+		"REQUIRE")
+  (:import-from "CCL"
+                "*BREAK-ON-WARNINGS*"
+                "COMPILER-LET"
+		"*APPLYHOOK*"
+		"*EVALHOOK*"
+		"APPLYHOOK"
+		"EVALHOOK"
+		"SPECIAL-FORM-P"
+		"GET-SETF-METHOD"
+		"GET-SETF-METHOD-MULTIPLE-VALUE"
+		"DEFINE-SETF-METHOD"
+)
+  (:shadow "IN-PACKAGE"
+           "FUNCTIONP"
+           "MAKE-PACKAGE"
+           "SHADOW"
+           "SHADOWING-IMPORT"
+           "EXPORT"
+           "UNEXPORT"
+           "USE-PACKAGE"
+           "UNUSE-PACKAGE"
+           "IMPORT")
+  (:export
+   "&ALLOW-OTHER-KEYS"
+   "&AUX"
+   "&BODY"
+   "&ENVIRONMENT"
+   "&KEY"
+   "&OPTIONAL"
+   "&REST"
+   "&WHOLE"
+   "*"
+   "**"
+   "***"
+   "*APPLYHOOK*"
+   "*BREAK-ON-WARNINGS*"
+   "*DEBUG-IO*"
+   "*DEFAULT-PATHNAME-DEFAULTS*"
+   "*ERROR-OUTPUT*"
+   "*EVALHOOK*"
+   "*FEATURES*"
+   "*LOAD-VERBOSE*"
+   "*MODULES*"
+   "*MACROEXPAND-HOOK*"
+   "*PACKAGE*"
+   "*PRINT-ARRAY*"
+   "*PRINT-BASE*"
+   "*PRINT-CASE*"
+   "*PRINT-CIRCLE*"
+   "*PRINT-ESCAPE*"
+   "*PRINT-GENSYM*"
+   "*PRINT-LENGTH*"
+   "*PRINT-LEVEL*"
+   "*PRINT-PRETTY*"
+   "*PRINT-RADIX*"
+   "*QUERY-IO*"
+   "*RANDOM-STATE*"
+   "*READ-BASE*"
+   "*READ-DEFAULT-FLOAT-FORMAT*"
+   "*READ-SUPPRESS*"
+   "*READTABLE*"
+   "*STANDARD-INPUT*"
+   "*STANDARD-OUTPUT*"
+   "*TERMINAL-IO*"
+   "*TRACE-OUTPUT*"
+   "+"
+   "++"
+   "+++"
+   "-"
+   "/"
+   "//"
+   "///"
+   "/="
+   "1+"
+   "1-"
+   "<"
+   "<="
+   "="
+   ">"
+   ">="
+   "ABS"
+   "ACONS"
+   "ACOS"
+   "ACOSH"
+   "ADJOIN"
+   "ADJUST-ARRAY"
+   "ADJUSTABLE-ARRAY-P"
+   "ALPHA-CHAR-P"
+   "ALPHANUMERICP"
+   "AND"
+   "APPEND"
+   "APPLY"
+   "APPLYHOOK"
+   "APROPOS"
+   "APROPOS-LIST"
+   "AREF"
+   "ARRAY"
+   "ARRAY-DIMENSION"
+   "ARRAY-DIMENSION-LIMIT"
+   "ARRAY-DIMENSIONS"
+   "ARRAY-ELEMENT-TYPE"
+   "ARRAY-HAS-FILL-POINTER-P"
+   "ARRAY-IN-BOUNDS-P"
+   "ARRAY-RANK"
+   "ARRAY-RANK-LIMIT"
+   "ARRAY-ROW-MAJOR-INDEX"
+   "ARRAY-TOTAL-SIZE"
+   "ARRAY-TOTAL-SIZE-LIMIT"
+   "ARRAYP"
+   "ASH"
+   "ASIN"
+   "ASINH"
+   "ASSERT"
+   "ASSOC"
+   "ASSOC-IF"
+   "ASSOC-IF-NOT"
+   "ATAN"
+   "ATANH"
+   "ATOM"
+   "BIGNUM"
+   "BIT"
+   "BIT-AND"
+   "BIT-ANDC1"
+   "BIT-ANDC2"
+   "BIT-EQV"
+   "BIT-IOR"
+   "BIT-NAND"
+   "BIT-NOR"
+   "BIT-NOT"
+   "BIT-ORC1"
+   "BIT-ORC2"
+   "BIT-VECTOR"
+   "BIT-VECTOR-P"
+   "BIT-XOR"
+   "BLOCK"
+   "BOOLE"
+   "BOOLE-1"
+   "BOOLE-2"
+   "BOOLE-AND"
+   "BOOLE-ANDC1"
+   "BOOLE-ANDC2"
+   "BOOLE-C1"
+   "BOOLE-C2"
+   "BOOLE-CLR"
+   "BOOLE-EQV"
+   "BOOLE-IOR"
+   "BOOLE-NAND"
+   "BOOLE-NOR"
+   "BOOLE-ORC1"
+   "BOOLE-ORC2"
+   "BOOLE-SET"
+   "BOOLE-XOR"
+   "BOTH-CASE-P"
+   "BOUNDP"
+   "BREAK"
+   "BUTLAST"
+   "BYTE"
+   "BYTE-POSITION"
+   "BYTE-SIZE"
+   "CAAAAR"
+   "CAAADR"
+   "CAAAR"
+   "CAADAR"
+   "CAADDR"
+   "CAADR"
+   "CAAR"
+   "CADAAR"
+   "CADADR"
+   "CADAR"
+   "CADDAR"
+   "CADDDR"
+   "CADDR"
+   "CADR"
+   "CALL-ARGUMENTS-LIMIT"
+   "CAR"
+   "CASE"
+   "CATCH"
+   "CCASE"
+   "CDAAAR"
+   "CDAADR"
+   "CDAAR"
+   "CDADAR"
+   "CDADDR"
+   "CDADR"
+   "CDAR"
+   "CDDAAR"
+   "CDDADR"
+   "CDDAR"
+   "CDDDAR"
+   "CDDDDR"
+   "CDDDR"
+   "CDDR"
+   "CDR"
+   "CEILING"
+   "CERROR"
+   "CHAR"
+   "CHAR-BIT"
+   "CHAR-BITS"
+   "CHAR-BITS-LIMIT"
+   "CHAR-CODE"
+   "CHAR-CODE-LIMIT"
+   "CHAR-CONTROL-BIT"
+   "CHAR-DOWNCASE"
+   "CHAR-EQUAL"
+   "CHAR-FONT"
+   "CHAR-FONT-LIMIT"
+   "CHAR-GREATERP"
+   "CHAR-HYPER-BIT"
+   "CHAR-INT"
+   "CHAR-LESSP"
+   "CHAR-META-BIT"
+   "CHAR-NAME"
+   "CHAR-NOT-EQUAL"
+   "CHAR-NOT-GREATERP"
+   "CHAR-NOT-LESSP"
+   "CHAR-SUPER-BIT"
+   "CHAR-UPCASE"
+   "CHAR/="
+   "CHAR<"
+   "CHAR<="
+   "CHAR="
+   "CHAR>"
+   "CHAR>="
+   "CHARACTER"
+   "CHARACTERP"
+   "CHECK-TYPE"
+   "CIS"
+   "CLEAR-INPUT"
+   "CLEAR-OUTPUT"
+   "CLOSE"
+   "CLRHASH"
+   "CODE-CHAR"
+   "COERCE"
+   "COMMON"
+   "COMMONP"
+   "COMPILATION-SPEED"
+   "COMPILE"
+   "COMPILE-FILE"
+   "COMPILED-FUNCTION"
+   "COMPILED-FUNCTION-P"
+   "COMPILER-LET"
+   "COMPLEX"
+   "COMPLEXP"
+   "CONCATENATE"
+   "COND"
+   "CONJUGATE"
+   "CONS"
+   "CONSP"
+   "CONSTANTP"
+   "COPY-ALIST"
+   "COPY-LIST"
+   "COPY-READTABLE"
+   "COPY-SEQ"
+   "COPY-SYMBOL"
+   "COPY-TREE"
+   "COS"
+   "COSH"
+   "COUNT"
+   "COUNT-IF"
+   "COUNT-IF-NOT"
+   "CTYPECASE"
+   "DECF"
+   "DECLARATION"
+   "DECLARE"
+   "DECODE-FLOAT"
+   "DECODE-UNIVERSAL-TIME"
+   "DEFCONSTANT"
+   "DEFINE-MODIFY-MACRO"
+   "DEFINE-SETF-METHOD"
+   "DEFMACRO"
+   "DEFPARAMETER"
+   "DEFSETF"
+   "DEFSTRUCT"
+   "DEFTYPE"
+   "DEFUN"
+   "DEFVAR"
+   "DELETE"
+   "DELETE-DUPLICATES"
+   "DELETE-FILE"
+   "DELETE-IF"
+   "DELETE-IF-NOT"
+   "DENOMINATOR"
+   "DEPOSIT-FIELD"
+   "DESCRIBE"
+   "DIGIT-CHAR"
+   "DIGIT-CHAR-P"
+   "DIRECTORY"
+   "DIRECTORY-NAMESTRING"
+   "DISASSEMBLE"
+   "DO"
+   "DO*"
+   "DO-ALL-SYMBOLS"
+   "DO-EXTERNAL-SYMBOLS"
+   "DO-SYMBOLS"
+   "DOCUMENTATION"
+   "DOLIST"
+   "DOTIMES"
+   "DOUBLE-FLOAT"
+   "DOUBLE-FLOAT-EPSILON"
+   "DOUBLE-FLOAT-NEGATIVE-EPSILON"
+   "DPB"
+   "DRIBBLE"
+   "ECASE"
+   "ED"
+   "EIGHTH"
+   "ELT"
+   "ENCODE-UNIVERSAL-TIME"
+   "ENDP"
+   "ENOUGH-NAMESTRING"
+   "EQ"
+   "EQL"
+   "EQUAL"
+   "EQUALP"
+   "ERROR"
+   "ETYPECASE"
+   "EVAL"
+   "EVAL-WHEN"
+   "EVALHOOK"
+   "EVENP"
+   "EVERY"
+   "EXP"
+   "EXPORT"
+   "EXPT"
+   "FBOUNDP"
+   "FCEILING"
+   "FFLOOR"
+   "FIFTH"
+   "FILE-AUTHOR"
+   "FILE-LENGTH"
+   "FILE-NAMESTRING"
+   "FILE-POSITION"
+   "FILE-WRITE-DATE"
+   "FILL"
+   "FILL-POINTER"
+   "FIND"
+   "FIND-ALL-SYMBOLS"
+   "FIND-IF"
+   "FIND-IF-NOT"
+   "FIND-PACKAGE"
+   "FIND-SYMBOL"
+   "FINISH-OUTPUT"
+   "FIRST"
+   "FIXNUM"
+   "FLET"
+   "FLOAT"
+   "FLOAT-DIGITS"
+   "FLOAT-PRECISION"
+   "FLOAT-RADIX"
+   "FLOAT-SIGN"
+   "FLOATP"
+   "FLOOR"
+   "FMAKUNBOUND"
+   "FORCE-OUTPUT"
+   "FORMAT"
+   "FOURTH"
+   "FRESH-LINE"
+   "FROUND"
+   "FTRUNCATE"
+   "FTYPE"
+   "FUNCALL"
+   "FUNCTION"
+   "FUNCTIONP"
+   "GCD"
+   "GENSYM"
+   "GENTEMP"
+   "GET"
+   "GET-DECODED-TIME"
+   "GET-DISPATCH-MACRO-CHARACTER"
+   "GET-INTERNAL-REAL-TIME"
+   "GET-INTERNAL-RUN-TIME"
+   "GET-MACRO-CHARACTER"
+   "GET-OUTPUT-STREAM-STRING"
+   "GET-PROPERTIES"
+   "GET-SETF-METHOD"
+   "GET-SETF-METHOD-MULTIPLE-VALUE"
+   "GET-UNIVERSAL-TIME"
+   "GETF"
+   "GETHASH"
+   "GO"
+   "GRAPHIC-CHAR-P"
+   "HASH-TABLE"
+   "HASH-TABLE-COUNT"
+   "HASH-TABLE-P"
+   "HOST-NAMESTRING"
+   "IDENTITY"
+   "IF"
+   "IGNORE"
+   "IMAGPART"
+   "IMPORT"
+   "IN-PACKAGE"
+   "INCF"
+   "INLINE"
+   "INPUT-STREAM-P"
+   "INSPECT"
+   "INT-CHAR"
+   "INTEGER"
+   "INTEGER-DECODE-FLOAT"
+   "INTEGER-LENGTH"
+   "INTEGERP"
+   "INTERN"
+   "INTERNAL-TIME-UNITS-PER-SECOND"
+   "INTERSECTION"
+   "ISQRT"
+   "KEYWORD"
+   "KEYWORDP"
+   "LABELS"
+   "LAMBDA"
+   "LAMBDA-LIST-KEYWORDS"
+   "LAMBDA-PARAMETERS-LIMIT"
+   "LAST"
+   "LCM"
+   "LDB"
+   "LDB-TEST"
+   "LDIFF"
+   "LEAST-NEGATIVE-DOUBLE-FLOAT"
+   "LEAST-NEGATIVE-LONG-FLOAT"
+   "LEAST-NEGATIVE-SHORT-FLOAT"
+   "LEAST-NEGATIVE-SINGLE-FLOAT"
+   "LEAST-POSITIVE-DOUBLE-FLOAT"
+   "LEAST-POSITIVE-LONG-FLOAT"
+   "LEAST-POSITIVE-SHORT-FLOAT"
+   "LEAST-POSITIVE-SINGLE-FLOAT"
+   "LENGTH"
+   "LET"
+   "LET*"
+   "LISP-IMPLEMENTATION-TYPE"
+   "LISP-IMPLEMENTATION-VERSION"
+   "LIST"
+   "LIST*"
+   "LIST-ALL-PACKAGES"
+   "LIST-LENGTH"
+   "LISTEN"
+   "LISTP"
+   "LOAD"
+   "LOCALLY"
+   "LOG"
+   "LOGAND"
+   "LOGANDC1"
+   "LOGANDC2"
+   "LOGBITP"
+   "LOGCOUNT"
+   "LOGEQV"
+   "LOGIOR"
+   "LOGNAND"
+   "LOGNOR"
+   "LOGNOT"
+   "LOGORC1"
+   "LOGORC2"
+   "LOGTEST"
+   "LOGXOR"
+   "LONG-FLOAT"
+   "LONG-FLOAT-EPSILON"
+   "LONG-FLOAT-NEGATIVE-EPSILON"
+   "LONG-SITE-NAME"
+   "LOOP"
+   "LOWER-CASE-P"
+   "MACHINE-INSTANCE"
+   "MACHINE-TYPE"
+   "MACHINE-VERSION"
+   "MACRO-FUNCTION"
+   "MACROEXPAND"
+   "MACROEXPAND-1"
+   "MACROLET"
+   "MAKE-ARRAY"
+   "MAKE-BROADCAST-STREAM"
+   "MAKE-CHAR"
+   "MAKE-CONCATENATED-STREAM"
+   "MAKE-DISPATCH-MACRO-CHARACTER"
+   "MAKE-ECHO-STREAM"
+   "MAKE-HASH-TABLE"
+   "MAKE-LIST"
+   "MAKE-PACKAGE"
+   "MAKE-PATHNAME"
+   "MAKE-RANDOM-STATE"
+   "MAKE-SEQUENCE"
+   "MAKE-STRING"
+   "MAKE-STRING-INPUT-STREAM"
+   "MAKE-STRING-OUTPUT-STREAM"
+   "MAKE-SYMBOL"
+   "MAKE-SYNONYM-STREAM"
+   "MAKE-TWO-WAY-STREAM"
+   "MAKUNBOUND"
+   "MAP"
+   "MAPC"
+   "MAPCAN"
+   "MAPCAR"
+   "MAPCON"
+   "MAPHASH"
+   "MAPL"
+   "MAPLIST"
+   "MASK-FIELD"
+   "MAX"
+   "MEMBER"
+   "MEMBER-IF"
+   "MEMBER-IF-NOT"
+   "MERGE"
+   "MERGE-PATHNAMES"
+   "MIN"
+   "MINUSP"
+   "MISMATCH"
+   "MOD"
+   "MOST-NEGATIVE-DOUBLE-FLOAT"
+   "MOST-NEGATIVE-FIXNUM"
+   "MOST-NEGATIVE-LONG-FLOAT"
+   "MOST-NEGATIVE-SHORT-FLOAT"
+   "MOST-NEGATIVE-SINGLE-FLOAT"
+   "MOST-POSITIVE-DOUBLE-FLOAT"
+   "MOST-POSITIVE-FIXNUM"
+   "MOST-POSITIVE-LONG-FLOAT"
+   "MOST-POSITIVE-SHORT-FLOAT"
+   "MOST-POSITIVE-SINGLE-FLOAT"
+   "MULTIPLE-VALUE-BIND"
+   "MULTIPLE-VALUE-CALL"
+   "MULTIPLE-VALUE-LIST"
+   "MULTIPLE-VALUE-PROG1"
+   "MULTIPLE-VALUE-SETQ"
+   "MULTIPLE-VALUES-LIMIT"
+   "NAME-CHAR"
+   "NAMESTRING"
+   "NBUTLAST"
+   "NCONC"
+   "NIL"
+   "NINTERSECTION"
+   "NINTH"
+   "NOT"
+   "NOTANY"
+   "NOTEVERY"
+   "NOTINLINE"
+   "NRECONC"
+   "NREVERSE"
+   "NSET-DIFFERENCE"
+   "NSET-EXCLUSIVE-OR"
+   "NSTRING-CAPITALIZE"
+   "NSTRING-DOWNCASE"
+   "NSTRING-UPCASE"
+   "NSUBLIS"
+   "NSUBST"
+   "NSUBST-IF"
+   "NSUBST-IF-NOT"
+   "NSUBSTITUTE"
+   "NSUBSTITUTE-IF"
+   "NSUBSTITUTE-IF-NOT"
+   "NTH"
+   "NTHCDR"
+   "NULL"
+   "NUMBER"
+   "NUMBERP"
+   "NUMERATOR"
+   "NUNION"
+   "ODDP"
+   "OPEN"
+   "OPTIMIZE"
+   "OR"
+   "OTHERWISE"
+   "OUTPUT-STREAM-P"
+   "PACKAGE"
+   "PACKAGE-NAME"
+   "PACKAGE-NICKNAMES"
+   "PACKAGE-SHADOWING-SYMBOLS"
+   "PACKAGE-USE-LIST"
+   "PACKAGE-USED-BY-LIST"
+   "PACKAGEP"
+   "PAIRLIS"
+   "PARSE-INTEGER"
+   "PARSE-NAMESTRING"
+   "PATHNAME"
+   "PATHNAME-DEVICE"
+   "PATHNAME-DIRECTORY"
+   "PATHNAME-HOST"
+   "PATHNAME-NAME"
+   "PATHNAME-TYPE"
+   "PATHNAME-VERSION"
+   "PATHNAMEP"
+   "PEEK-CHAR"
+   "PHASE"
+   "PI"
+   "PLUSP"
+   "POP"
+   "POSITION"
+   "POSITION-IF"
+   "POSITION-IF-NOT"
+   "PPRINT"
+   "PRIN1"
+   "PRIN1-TO-STRING"
+   "PRINC"
+   "PRINC-TO-STRING"
+   "PRINT"
+   "PROBE-FILE"
+   "PROCLAIM"
+   "PROG"
+   "PROG*"
+   "PROG1"
+   "PROG2"
+   "PROGN"
+   "PROGV"
+   "PROVIDE"
+   "PSETF"
+   "PSETQ"
+   "PUSH"
+   "PUSHNEW"
+   "QUOTE"
+   "RANDOM"
+   "RANDOM-STATE"
+   "RANDOM-STATE-P"
+   "RASSOC"
+   "RASSOC-IF"
+   "RASSOC-IF-NOT"
+   "RATIO"
+   "RATIONAL"
+   "RATIONALIZE"
+   "RATIONALP"
+   "READ"
+   "READ-BYTE"
+   "READ-CHAR"
+   "READ-CHAR-NO-HANG"
+   "READ-DELIMITED-LIST"
+   "READ-FROM-STRING"
+   "READ-LINE"
+   "READ-PRESERVING-WHITESPACE"
+   "READTABLE"
+   "READTABLEP"
+   "REALPART"
+   "REDUCE"
+   "REM"
+   "REMF"
+   "REMHASH"
+   "REMOVE"
+   "REMOVE-DUPLICATES"
+   "REMOVE-IF"
+   "REMOVE-IF-NOT"
+   "REMPROP"
+   "RENAME-FILE"
+   "RENAME-PACKAGE"
+   "REPLACE"
+   "REQUIRE"
+   "REST"
+   "RETURN"
+   "RETURN-FROM"
+   "REVAPPEND"
+   "REVERSE"
+   "ROOM"
+   "ROTATEF"
+   "ROUND"
+   "RPLACA"
+   "RPLACD"
+   "SAFETY"
+   "SATISFIES"
+   "SBIT"
+   "SCALE-FLOAT"
+   "SCHAR"
+   "SEARCH"
+   "SECOND"
+   "SEQUENCE"
+   "SET"
+   "SET-CHAR-BIT"
+   "SET-DIFFERENCE"
+   "SET-DISPATCH-MACRO-CHARACTER"
+   "SET-EXCLUSIVE-OR"
+   "SET-MACRO-CHARACTER"
+   "SET-SYNTAX-FROM-CHAR"
+   "SETF"
+   "SETQ"
+   "SEVENTH"
+   "SHADOW"
+   "SHADOWING-IMPORT"
+   "SHIFTF"
+   "SHORT-FLOAT"
+   "SHORT-FLOAT-EPSILON"
+   "SHORT-FLOAT-NEGATIVE-EPSILON"
+   "SHORT-SITE-NAME"
+   "SIGNED-BYTE"
+   "SIGNUM"
+   "SIMPLE-ARRAY"
+   "SIMPLE-BIT-VECTOR"
+   "SIMPLE-BIT-VECTOR-P"
+   "SIMPLE-STRING"
+   "SIMPLE-STRING-P"
+   "SIMPLE-VECTOR"
+   "SIMPLE-VECTOR-P"
+   "SIN"
+   "SINGLE-FLOAT"
+   "SINGLE-FLOAT-EPSILON"
+   "SINGLE-FLOAT-NEGATIVE-EPSILON"
+   "SINH"
+   "SIXTH"
+   "SLEEP"
+   "SOFTWARE-TYPE"
+   "SOFTWARE-VERSION"
+   "SOME"
+   "SORT"
+   "SPACE"
+   "SPECIAL"
+   "SPEED"
+   "SQRT"
+   "STABLE-SORT"
+   "STANDARD-CHAR"
+   "STANDARD-CHAR-P"
+   "STEP"
+   "STREAM"
+   "STREAM-ELEMENT-TYPE"
+   "STREAMP"
+   "STRING"
+   "STRING-CAPITALIZE"
+   "STRING-CHAR"
+   "STRING-CHAR-P"
+   "STRING-DOWNCASE"
+   "STRING-EQUAL"
+   "STRING-GREATERP"
+   "STRING-LEFT-TRIM"
+   "STRING-LESSP"
+   "STRING-NOT-EQUAL"
+   "STRING-NOT-GREATERP"
+   "STRING-NOT-LESSP"
+   "STRING-RIGHT-TRIM"
+   "STRING-TRIM"
+   "STRING-UPCASE"
+   "STRING/="
+   "STRING<"
+   "STRING<="
+   "STRING="
+   "STRING>"
+   "STRING>="
+   "STRINGP"
+   "STRUCTURE"
+   "SUBLIS"
+   "SUBSEQ"
+   "SUBSETP"
+   "SUBST"
+   "SUBST-IF"
+   "SUBST-IF-NOT"
+   "SUBSTITUTE"
+   "SUBSTITUTE-IF"
+   "SUBSTITUTE-IF-NOT"
+   "SUBTYPEP"
+   "SVREF"
+   "SXHASH"
+   "SYMBOL"
+   "SYMBOL-FUNCTION"
+   "SYMBOL-NAME"
+   "SYMBOL-PACKAGE"
+   "SYMBOL-PLIST"
+   "SYMBOL-VALUE"
+   "SYMBOLP"
+   "T"
+   "TAGBODY"
+   "TAILP"
+   "TAN"
+   "TANH"
+   "TENTH"
+   "TERPRI"
+   "THE"
+   "THIRD"
+   "THROW"
+   "TIME"
+   "TRACE"
+   "TREE-EQUAL"
+   "TRUENAME"
+   "TRUNCATE"
+   "TYPE"
+   "TYPE-OF"
+   "TYPECASE"
+   "TYPEP"
+   "UNEXPORT"
+   "UNINTERN"
+   "UNION"
+   "UNLESS"
+   "UNREAD-CHAR"
+   "UNSIGNED-BYTE"
+   "UNTRACE"
+   "UNUSE-PACKAGE"
+   "UNWIND-PROTECT"
+   "UPPER-CASE-P"
+   "USE-PACKAGE"
+   "USER-HOMEDIR-PATHNAME"
+   "VALUES"
+   "VALUES-LIST"
+   "VARIABLE"
+   "VECTOR"
+   "VECTOR-POP"
+   "VECTOR-PUSH"
+   "VECTOR-PUSH-EXTEND"
+   "VECTORP"
+   "WARN"
+   "WHEN"
+   "WITH-INPUT-FROM-STRING"
+   "WITH-OPEN-FILE"
+   "WITH-OPEN-STREAM"
+   "WITH-OUTPUT-TO-STRING"
+   "WRITE"
+   "WRITE-BYTE"
+   "WRITE-CHAR"
+   "WRITE-LINE"
+   "WRITE-STRING"
+   "WRITE-TO-STRING"
+   "Y-OR-N-P"
+   "YES-OR-NO-P"
+   "ZEROP"
+   ))
+
+(%resize-package (find-package "LISP"))
+
+(defpackage "USER"
+  (:use "LISP" "CCL"))  
+
+(defconstant lisp:char-control-bit 0)
+(defconstant lisp:char-meta-bit 0)
+(defconstant lisp:char-super-bit 0)
+(defconstant lisp:char-hyper-bit 0)
+(defconstant lisp:char-bits-limit 1)
+(defconstant lisp:char-font-limit 1)
+
+(defun lisp:int-char (i)
+  (cl:code-char i))
+
+(defun lisp:char-bits (c)
+  (require-type c 'character)
+  0)
+
+(defun lisp:char-font (c)
+  (require-type c 'character)
+  0)
+
+(defun lisp:digit-char (weight &optional (radix 10) font)
+  (when (and font (not (eql font 0)))
+    (error "Non-zero ~S (~S) not supported" 'font font))
+  (cl:digit-char weight radix))
+
+; 'It is an error to give char-bit the name of a bit not supported by the
+;   implementation'
+(defun lisp:char-bit (char name)
+  (declare (ignore char))
+  (error "Unsupported character bit name ~S." name))
+
+(defun lisp:set-char-bit (char name newvalue)
+  (declare (ignore char newvalue))
+  (error "Unsupported character bit name ~S." name))
+
+(defun lisp:make-char (char &optional bits font)
+  (flet ((non-supported (argname argval)
+           (if (and argval (not (eql argval 0)))
+             (error "Non-zero ~S argument (~S) not supported." argname argval))))
+    (non-supported 'bits bits)
+    (non-supported 'font font)
+    (require-type char 'character)))
+
+; A tragic waste of precious silicon.
+(define-setf-method char-bit (place bit-name &environment env)
+  (multiple-value-bind (dummies vals newval setter getter)
+		       (get-setf-method place env)
+    (let ((btemp (gensym))
+	  (gnuval (gensym)))
+      (values `(,@dummies ,btemp)
+	      `(,@vals ,bit-name)
+	      (list gnuval)
+	      `(let ((,(car newval)
+		      (set-char-bit ,getter ,btemp ,gnuval)))
+		 ,setter
+		 ,gnuval)
+	      `(char-bit ,getter ,btemp)))))
+
+(defun lisp:in-package (package-name &rest rest &key
+                                     nicknames use internal-size external-size)
+  (declare (ignore nicknames use internal-size external-size))
+  (declare (dynamic-extent rest))
+  (apply 'old-in-package package-name rest))
+
+(defun lisp:functionp (x)
+  (or (symbolp x)
+      (and (consp x) (eq (ccl::%car x) 'lambda))
+      (cl:functionp x)))
+
+(setf (cl:find-class 'lisp:string-char) (cl:find-class 'cl:base-char)
+      (symbol-function 'lisp:string-char-p) #'cl:characterp)
+
+(dolist (sym '(lisp:make-package lisp:in-package lisp:shadow lisp:shadowing-import
+               lisp:export lisp:unexport lisp:use-package lisp:unuse-package
+               lisp:import))
+  (unless (eq sym 'lisp:in-package)
+    (setf (symbol-function sym)
+          (symbol-function (find-symbol (symbol-name sym) "COMMON-LISP"))))
+  (pushnew sym *fcomp-eval-always-functions*))
+
+(provide :lisp-package)
Index: /branches/new-random/library/lispequ.lisp
===================================================================
--- /branches/new-random/library/lispequ.lisp	(revision 13309)
+++ /branches/new-random/library/lispequ.lisp	(revision 13309)
@@ -0,0 +1,1607 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;; LispEqu.lisp
+
+(in-package "CCL")
+
+(defconstant $flags_Normal 0)
+(defconstant $flags_DisposeRecursiveLock 1)
+(defconstant $flags_DisposPtr 2)
+(defconstant $flags_DisposeRwlock 3)
+(defconstant $flags_DisposeSemaphore 4)
+
+(defconstant $system-lock-type-recursive 0)
+(defconstant $system-lock-type-rwlock 1)
+
+;;; this stuff is really ppc specific at the moment
+(defconstant $population_weak-list 0)
+(defconstant $population_weak-alist 1)
+(defconstant $population_termination-bit 16)
+
+;;; type of 0 is a weak-list
+;;; Note that this evals its args in the wrong order.
+(defmacro %cons-population (data &optional (type 0) (termination? nil))
+  (if termination?
+    `(gvector :population 0 (logior (ash 1 $population_termination-bit) ,type) ,data nil)
+    `(gvector :population 0 ,type ,data)))
+
+(defmacro %cons-terminatable-alist (&optional data)
+  `(%cons-population ,data $population_weak-alist t))
+
+;;; The GC assumes that this structure is laid out exactly as below.
+;;; It also assumes that if the $population_termination-bit is set in the
+;;; population.type slot, the vector is of length 4, otherwise 3.
+(def-accessors (population) %svref
+  population.gclink
+  population.type
+  population.data
+  population.termination-list)
+
+(def-accessors () uvref
+  nil
+  nil
+  population-data                      ; type-checked
+  population-termination-list)
+
+(defmacro %cons-pool (&optional data)
+  `(gvector :pool ,data))
+
+(def-accessors (pool) %svref
+  pool.data)
+
+(def-accessors (resource) %svref
+  nil                                   ; 'resource
+  resource.constructor
+  resource.destructor
+  resource.initializer
+  resource.pool
+  resource.lock)
+
+(defmacro gvector (type-keyword &rest initial-values)
+  `(%gvector ,(type-keyword-code type-keyword) ,@initial-values))
+
+
+(defmacro allocate-typed-vector (type-keyword elements &optional (init nil init-p))
+  `(%alloc-misc ,elements ,(type-keyword-code type-keyword)
+    ,@(if init-p `(,init))))
+    
+
+(def-accessors (semaphore) %svref
+  nil					;'semaphore
+  semaphore.value)
+
+
+(defmacro %istruct (istruct-name &rest initial-values)
+  `(gvector :ISTRUCT (register-istruct-cell ,istruct-name) ,@initial-values))
+
+
+(defmacro %cons-resource (constructor &optional destructor initializer)
+  `(%istruct 'resource ,constructor ,destructor ,initializer (%cons-pool) (make-lock)))
+
+
+
+;;; Symbol [f,v]bits.
+
+(defconstant $sym_bit_bound 0)		;Proclaimed bound.
+(defconstant $sym_bit_const 1)
+(defconstant $sym_bit_global 2)         ;Should never be lambda-bound.
+(defconstant $sym_bit_special 4)
+(defconstant $sym_vbit_typeppred 5)
+(defconstant $sym_bit_indirect 6)
+(defconstant $sym_bit_defunct 7)
+
+(defconstant $sym_vbit_bound $sym_bit_bound)
+(defconstant $sym_vbit_const $sym_bit_const)
+(defconstant $sym_vbit_global $sym_bit_global)
+(defconstant $sym_vbit_special $sym_bit_special)
+(defconstant $sym_vbit_indirect $sym_bit_indirect)
+(defconstant $sym_vbit_defunct $sym_bit_defunct)
+
+(defconstant $sym_fbit_frozen (+ 8 $sym_bit_bound))
+(defconstant $sym_fbit_special (+ 8 $sym_bit_special))
+(defconstant $sym_fbit_indirect (+ 8 $sym_bit_indirect))
+(defconstant $sym_fbit_defunct (+ 8 $sym_bit_defunct))
+
+(defconstant $sym_fbit_constant_fold (+ 8 $sym_bit_const))
+(defconstant $sym_fbit_fold_subforms (+ 8 $sym_bit_global))
+
+(def-accessors () %svref
+  nil					;'destructure-state
+  destructure-state.current
+  destructure-state.whole
+  destructure-state.lambda
+  )
+
+;Lfun bits.
+;Assumed to be a fixnum, so if you ever assign a bit number > 28,
+;change lfun-bits and its callers.
+(defconstant $lfbits-nonnullenv-bit 0)
+(defconstant $lfbits-keys-bit 1)
+(defconstant $lfbits-numopt (byte 5 2))
+(defconstant $lfbits-restv-bit 7)
+(defconstant $lfbits-numreq (byte 6 8))
+(defconstant $lfbits-optinit-bit 14)
+(defconstant $lfbits-rest-bit 15)
+(defconstant $lfbits-aok-bit 16)
+(defconstant $lfbits-numinh (byte 6 17))
+(defconstant $lfbits-info-bit 23)
+(defconstant $lfbits-trampoline-bit 24)
+(defconstant $lfbits-code-coverage-bit 25)
+(defconstant $lfbits-cm-bit 26)         ; combined-method
+(defconstant $lfbits-nextmeth-bit 26)   ; or call-next-method with method-bit
+(defconstant $lfbits-gfn-bit 27)        ; generic-function
+(defconstant $lfbits-nextmeth-with-args-bit 27)   ; or call-next-method-with-args with method-bit
+(defconstant $lfbits-method-bit 28)     ; method function
+(defconstant $lfbits-noname-bit 29)
+
+
+(defconstant $lfbits-args-mask
+  (%ilogior (dpb -1 $lfbits-numreq 0)
+            (dpb -1 $lfbits-numopt 0)
+            (%ilsl $lfbits-rest-bit 1)
+            (%ilsl $lfbits-keys-bit 1)
+            (%ilsl $lfbits-aok-bit 1)))
+
+;Bits in $arh_bits.
+(defconstant $arh_adjp_bit 7)		;adjustable-p
+(defconstant $arh_fill_bit 6)		;fill-pointer-p
+(defconstant $arh_disp_bit 5)		;displaced to another array header -p
+(defconstant $arh_simple_bit 4)		;not adjustable, no fill-pointer and
+					; not user-visibly displaced -p
+(defconstant $arh_exp_disp_bit 3)	;explicitly-displaced -p
+
+(def-accessors (lexical-environment) %svref
+  ()					; 'lexical-environment
+  lexenv.parent-env
+  lexenv.functions
+  lexenv.variables
+  lexenv.fdecls				; function-binding decls, e.g., [NOT]INLINE, FTYPE
+  lexenv.vdecls				; variable-binding decls, e.g., SPECIAL, TYPE
+  lexenv.mdecls				; misc decls, e.g., OPTIMIZE
+  lexenv.lambda				; unique id (e.g., afunc) of containing lambda expression.
+  )
+
+(def-accessors (definition-environment) %svref
+  ()					; 'definition-environment
+  defenv.type				; must be LIST, match lexenv.parent-env
+  defenv.functions			; compile-time macros, same structure as lexenv.functions
+  defenv.constants			; definition-time constants, shadows lexenv.variables
+  defenv.fdecls				; shadows lexenv.fdecls
+  defenv.vdecls				; shadows lexenv.vdecls
+  defenv.mdecls				; shadows lexenv.mdecls
+;;; extended info
+  defenv.types				; compile-time deftype info, shadows lexenv.function
+  defenv.defined			; functions defined in compilation unit.
+  defenv.specials
+  defenv.classes                        ; classed defined in compilation unit
+  defenv.structrefs                     ; compile-time DEFSTRUCT accessor info
+  defenv.structures                     ; compile-time DEFSTRUCT info
+  defenv.symbol-macros			; compile-time SYMBOL-MACROS.
+)
+
+(def-accessors (var) %svref
+  nil                                   ; 'var
+  var-name                              ; symbol
+  (var-bits var-parent)                 ; fixnum or ptr to parent
+  (var-ea  var-expansion)               ; p2 address (or symbol-macro expansion)
+  var-ref-forms                         ; in intermediate-code
+  var-inittype
+  var-binding-info
+  var-refs
+  var-nvr
+  var-declared-type
+)
+
+(def-accessors (package) %svref
+  pkg.itab
+  pkg.etab
+  pkg.used
+  pkg.used-by
+  pkg.names
+  pkg.shadowed
+  pkg.lock
+  pkg.intern-hook
+  )
+
+(defmacro package-deleted-marker ()
+  `(%unbound-marker))
+
+
+
+
+(defmacro %cons-fake-stack-frame (&optional sp next-sp fn lr vsp xp link)
+  `(%istruct 'fake-stack-frame ,sp ,next-sp ,fn ,lr ,vsp ,xp ,link))
+
+(def-accessors () svref
+  bt.dialog
+  bt.youngest
+  bt.oldest
+  bt.tcr
+  bt.restarts
+  bt.top-catch
+  bt.break-condition
+  bt.current
+  bt.fake-frames
+  bt.db-link
+  bt.break-level)
+
+(defconstant bt.sg bt.tcr)
+(setf (macro-function 'bt.sg) (macro-function 'bt.tcr))
+
+
+(def-accessors (lock) %svref
+  lock.value
+  lock.name)
+
+
+
+
+
+
+  
+;contents of pkg.itab/pkg.etab.
+(defmacro pkgtab-table (htab) `(car (the list ,htab)))
+#|
+(defmacro pkgtab-hcount (htab) `(car (the list (cdr (the list ,htab)))))                                            (mkint acc)))
+(defmacro pkgtab-hlimit (htab) `(cdr (the list (cdr (the list ,htab)))))
+|#
+
+
+
+(def-accessors (pathname) %svref
+  ()                                    ; 'pathname
+  %pathname-directory
+  %pathname-name
+  %pathname-type
+  %physical-pathname-version
+  %physical-pathname-device)
+
+(def-accessors (logical-pathname) %svref
+  ()                                    ; 'logical-pathname
+  nil                                   ; %pathname-directory
+  nil                                   ; %pathname-name
+  nil                                   ; %pathname-type  
+  %logical-pathname-host
+  %logical-pathname-version)
+
+(defmacro %cons-pathname (directory name type &optional version device)
+  `(%istruct 'pathname ,directory ,name ,type ,version ,device))
+
+(defmacro %cons-logical-pathname (directory name type host version)
+  `(%istruct 'logical-pathname ,directory ,name ,type ,host ,version))
+
+(def-accessors (restart) %svref
+  ()                                    ; 'restart
+  %restart-name
+  %restart-action
+  %restart-report
+  %restart-interactive
+  %restart-test)
+
+;;; %cons-restart now in level-2.lisp
+
+
+(def-accessors %svref
+  nil                                   ; 'periodic-task
+  ptask.state
+  ptask.name
+  ptask.function
+)
+
+;;;;;; CMU type system.
+
+
+
+(def-accessors (type-class) %svref
+  nil                                   ; 'type-class
+  type-class-name                       ; name
+
+  ;; Dyadic type methods.  If the classes of the two types are EQ, then we call
+  ;; the SIMPLE-xxx method.  If the classes are not EQ, and either type's class
+  ;; has a COMPLEX-xxx method, then we call it.
+  ;;
+  ;; Although it is undefined which method will get precedence when both types
+  ;; have a complex method, the complex method can assume that the second arg
+  ;; always is in its class, and the first always is not.  The arguments to
+  ;; commutative operations will be swapped if the first argument has a complex
+  ;; method.
+  ;;
+  ;; Since SUBTYPEP is not commutative, we have two complex methods.  the ARG1
+  ;; method is only called when the first argument is in its class, and the
+  ;; ARG2 method is only called when called when the second type is.  If either
+  ;; is specified, both must be.
+  type-class-simple-subtypep
+  type-class-complex-subtypep-arg1
+  type-class-complex-subtypep-arg2
+  ;;
+  ;; SIMPLE-UNION combines two types of the same class into a single type of
+  ;; that class.  If the result is a two-type union, then return NIL.
+  ;; VANILLA-UNION returns whichever argument is a supertype of the other, or
+  ;; NIL.
+  type-class-simple-union
+  type-class-complex-union
+  ;; The default intersection methods assume that if one type is a subtype of
+  ;; the other, then that type is the intersection.
+  type-class-simple-intersection
+  type-class-complex-intersection
+  ;;
+  type-class-simple-=
+  type-class-complex-=
+  type-class-unparse
+) 
+
+;; This istruct (and its subtypes) are used to define types.
+(def-accessors (ctype) %svref
+  nil                                   ; 'ctype or a subtype
+  ctype-class-info                       ; a type-class
+  ;; True if this type has a fixed number of members, and as such could
+  ;; possibly be completely specified in a MEMBER type.  This is used by the
+  ;; MEMBER type methods.
+  ctype-enumerable
+)
+
+;; args-ctype is a subtype of ctype
+(def-accessors (args-ctype) %svref
+  nil                                   ; 'args-ctype
+  nil                                   ; ctype-class-info              
+  nil                                   ; ctype-enumerable
+  ;; Lists of the type for each required and optional argument.
+  args-ctype-required
+  args-ctype-optional
+  ;;
+  ;; The type for the rest arg.  NIL if there is no rest arg.
+  args-ctype-rest
+  ;; True if keyword arguments are specified.
+  args-ctype-keyp
+  ;; List of key-info structures describing the keyword arguments.
+  args-ctype-keywords
+  ;; True if other keywords are allowed.
+  args-ctype-allowp
+)
+
+(def-accessors (key-info) %svref
+  nil                                   ; 'key-info
+  key-info-name                         ; Name of &key arg
+  key-info-type                         ; type (ctype) of this &key arg
+)
+
+;;; VALUES-ctype is a subtype of ARGS-ctype.
+(def-accessors (values-ctype) %svref
+  nil                                   ; 'values-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;; Lists of the type for each required and optional argument.
+  values-ctype-required
+  values-ctype-optional
+  ;;
+  ;; The type for the rest arg.  NIL if there is no rest arg.
+  values-ctype-rest
+  ;; True if keyword arguments are specified.
+  values-ctype-keyp
+  ;; List of key-info structures describing the keyword arguments.
+  values-ctype-keywords
+  ;; True if other keywords are allowed.
+  values-ctype-allowp
+)
+
+;;; FUNCTION-ctype is a subtype of ARGS-ctype.
+(def-accessors (args-ctype) %svref
+  nil                                   ; 'function-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  function-ctype-required               ; args-ctype-required
+  function-ctype-optional               ; args-ctype-optional
+  function-ctype-rest                   ; args-ctype-rest
+  function-ctype-keyp                   ; args-ctype-keyp
+  function-ctype-keywords               ; args-ctype-keywords
+  function-ctype-allowp                 ; args-ctype-allowp
+;; True if the arguments are unrestrictive, i.e. *.
+  function-ctype-wild-args
+  ;;
+  ;; Type describing the return values.  This is a values type
+  ;; when multiple values were specified for the return.
+  function-ctype-returns
+)
+
+;;; The CONSTANT-ctype structure represents a use of the CONSTANT-ARGUMENT "type
+;;; specifier", which is only meaningful in function argument type specifiers
+;;; used within the compiler.
+;;;
+
+
+(def-accessors (constant-ctype) %svref
+  nil                                   ; 'constant-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;; The type which the argument must be a constant instance of for this type
+  ;; specifier to win.
+  constant-ctype-type
+)
+
+;;; The NAMED-ctype is used to represent *, T and NIL.  These types must be
+;;; super or sub types of all types, not just classes and * & NIL aren't
+;;; classes anyway, so it wouldn't make much sense to make them built-in
+;;; classes.
+;;;
+
+(def-accessors (named-ctype) %svref
+  nil                                   ; 'named-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  named-ctype-name
+)
+
+;;; The Hairy-ctype represents anything too wierd to be described
+;;; reasonably or to be useful, such as SATISFIES.  We just remember
+;;; the original type spec.
+;;;
+
+(def-accessors (hairy-ctype) %svref
+  nil                                   ; 'hairy-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;; The type which the argument must be a constant instance of for this type
+  ;; specifier to win.
+  hairy-ctype-specifier
+)
+
+;;; An UNKNOWN-ctype is a type not known to the type system (not yet defined).
+;;; We make this distinction since we don't want to complain about types that
+;;; are hairy but defined.
+;;;
+
+;;; This means that UNKNOWN-ctype is a HAIRY-ctype.
+(def-accessors (unknown-ctype) %svref
+  nil                                   ; 'unknown-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  unknown-ctype-specifier
+)
+
+;;; CONS-ctype is a subclass of CTYPE
+(def-accessors (cons-ctype) %svref
+  nil                                   ; 'cons-ctype
+  nil                                   ; ctype-class-info
+  nil                                   ; ctype-enumerable
+  cons-ctype-car-ctype                  ; ctype of the car
+  cons-ctype-cdr-ctype                  ; ctype of the cdr
+  )
+
+;;; NUMERIC-ctype is a subclass of CTYPE
+(def-accessors (numeric-ctype) %svref
+  nil                                   ; numeric-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;;
+  ;; The kind of numeric type we have.  NIL if not specified (just NUMBER or
+  ;; COMPLEX).
+  numeric-ctype-class
+  ;; Format for a float type.  NIL if not specified or not a float.  Formats
+  ;; which don't exist in a given implementation don't appear here.
+  numeric-ctype-format
+  ;; Is this a complex numeric type?  Null if unknown (only in NUMBER.)
+  numeric-ctype-complexp
+  ;; The upper and lower bounds on the value.  If null, there is no bound.  If
+  ;; a list of a number, the bound is exclusive.  Integer types never have
+  ;; exclusive bounds.
+  numeric-ctype-low
+  numeric-ctype-high
+  numeric-ctype-predicate
+)
+
+;;; ARRAY-ctype is a subclass of CTYPE.
+(def-accessors (array-ctype) %svref
+  nil                                   ; 'array-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;;
+  ;; The dimensions of the array.  * if unspecified.  If a dimension is
+  ;; unspecified, it is *.
+  array-ctype-dimensions
+  ;;
+  ;; Is this not a simple array type?
+  array-ctype-complexp
+  ;;
+  ;; The element type as originally specified.
+  array-ctype-element-type
+  ;;
+  ;; The element type as it is specialized in this implementation.
+  array-ctype-specialized-element-type
+  ;; The typecode of the specialize element type, or NIL.
+  array-ctype-typecode
+)
+
+;;; MEMBER-ctype is a direct subclass of CTYPE.
+(def-accessors (member-ctype) %svref
+  nil                                   ; 'member-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;;
+  ;; The things in the set, with no duplications.
+  member-ctype-members
+)
+
+;;; UNION-ctype is a direct subclass of CTYPE.
+(def-accessors (union-ctype) %svref
+  nil                                   ; 'union-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;;
+  ;; The types in the union.
+  union-ctype-types
+)
+
+;;; INTERSECTION-ctype is a direct subclass of CTYPE.
+(def-accessors (intersection-ctype) %svref
+  nil                                   ; 'intersection-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;;
+  ;; The types in the intersection
+  intersection-ctype-types
+)
+
+(def-accessors (negation-ctype) %svref
+  nil                                   ; 'negation-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  ;; The type of what we're not:
+  negation-ctype-type
+  )
+  
+
+
+
+;;; It'd be nice to integrate "foreign" types into the type system
+(def-accessors (foreign-ctype) %svref
+  nil                                   ; 'foreign-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  foreign-ctype-foreign-type
+)
+  
+;;; Most "real" CLOS objects have one of these in their %class.ctype slot
+
+(def-accessors (class-ctype) %svref
+  nil                                   ; 'class-ctype
+  nil                                   ; ctype-class-info           
+  nil                                   ; ctype-enumerable
+  class-ctype-class                     ; backptr to class.
+  class-ctype-translation               ; ctype for some built-in-classes.
+)
+
+
+
+;;;;;;;
+;;
+;; state for with-package-iterator
+;;
+(def-accessors %svref
+  pkg-iter-step.pkg                     ; package
+  pkg-iter-step.type                    ; keyword
+  pkg-iter-step.table
+  pkg-iter-step.shadowed
+  pkg-iter-step.vector
+  pkg-iter-step.index)
+
+(def-accessors %svref
+  pkg-iter.step                         ; current step
+  pkg-iter.remaining-steps              ; steps to be processed
+)
+
+;;;;;;;;;;;;;
+
+;;; Bits in *gc-event-status-bits*
+(defconstant $gc-retain-pages-bit 0)
+(defconstant $gc-integrity-check-bit 2)
+(defconstant $gc-allow-stack-overflows-bit 5)
+(defconstant $egc-verbose-bit 3)
+(defconstant $gc-verbose-bit 4)
+(defconstant $gc-postgc-pending-bit 26)
+
+
+
+;;; Values for the flags arg to %install-periodic-task
+(defconstant $ptask_draw-flag 1)       ; set for tasks that do drawing
+(defconstant $ptask_event-dispatch-flag 2)      ; set for tasks that do event processing
+
+
+
+
+
+(defconstant struct.type 0)
+(defconstant istruct.type 0)
+
+(def-accessors (readtable) %svref
+  ()                                        ; 'readtable
+  rdtab.ttab                                ; type table
+  rdtab.alist                               ; macro-char alist
+  rdtab.case)				    ; gratuitous braindeath
+
+;character types in readtables
+(defconstant $cht_ill 0)                ;Illegal char
+(defconstant $cht_wsp 1)                ;Whitespace
+(defconstant $cht_sesc 4)               ;Single escape (\)
+(defconstant $cht_mesc 5)               ;Multiple escape (|)
+(defconstant $cht_cnst 6)               ;Atom constituent
+(defconstant $cht_tmac 8)               ;Terminating macro
+(defconstant $cht_ntmac 9)              ;Non-terminating macro
+
+(defconstant $cht_macbit 3)             ;This bit on in CHT_TMAC and CHT_NTMAC
+
+;;; quantifiers
+
+(defconstant $some 0)
+(defconstant $notany 1)
+(defconstant $every 2)
+(defconstant $notevery 3)
+
+;;; Error string constants.  As accurate as constants.i ...
+
+(defconstant $XVUNBND 1)
+;(defconstant $XNOCDR 2)
+(defconstant $xbadvec 6)
+(defconstant $XTMINPS 3)
+(defconstant $XNEINPS 4)
+(defconstant $XWRNGINP 5)
+(defconstant $err-bad-input 5)
+(defconstant $XFUNBND 6)
+;;(defconstant $err-fundefined 6)
+;;(defconstant $XNOCAR 7)
+(defconstant $xsetbadvec 7)
+(defconstant $xcoerce 8)
+(defconstant $xnofinfunction 9)
+(defconstant $xnomem 10)
+(defconstant $xnotranslation 12)
+(defconstant $XNOTFUN 13)
+(defconstant $XNOTsymlam 14)
+(defconstant $Xdeclpos 15)
+(defconstant $Xsetconstant 16)
+(defconstant $Xoddsetq 17)
+(defconstant $Xbadsetq 18)
+(defconstant $Xnotsym 19)
+(defconstant $Xisconstant 20)
+(defconstant $Xbadinit 21)
+(defconstant $Xsmacspec 22)
+(defconstant $X2manyargs 23)
+(defconstant $XNolexvar 24)
+(defconstant $XNolexfunc 25)
+(defconstant $XNolextag 26)
+(defconstant $XNolexblock 27)
+(defconstant $XNotag 28)
+(defconstant $Xduplicatetag 29)
+(defconstant $XNoblock 30)
+(defconstant $XBadLambdaList 31)
+(defconstant $XBadLambda 32)
+(defconstant $XNOCTAG 33)
+(defconstant $XOBJBadType 34)
+(defconstant $XFuncLexMacro 35)
+(defconstant $xumrpr 41)
+(defconstant $xnotsamevol 42)
+(defconstant $xbadfilenamechar 43)
+(defconstant $xillwild 44)
+(defconstant $xnotfaslortext 45)
+(defconstant $xrenamedir 46)
+(defconstant $xdirnotfile 47)
+(defconstant $xnocopydir 48)
+(defconstant $XBADTOK 49)
+(defconstant $err-long-pstr 49)
+(defconstant $xnocreate 50)
+(defconstant $XFLOVFL 64)
+(defconstant $XDIVZRO 66)
+(defconstant $XFLDZRO 66)
+(defconstant $XSTKOVER 75)
+(defconstant $XMEMFULL 76)
+(defconstant $xarrlimit 77)
+(defconstant $err-printer 94)
+(defconstant $err-printer-load 95)
+(defconstant $err-printer-params 96)
+(defconstant $err-printer-start 97)
+(defconstant $XFLEXC 98)
+(defconstant $xfileof 111)
+(defconstant $XARROOB 112)
+(defconstant $err-arroob 112)
+(defconstant $xunread 113)
+(defconstant $xbadmac 114)
+(defconstant $XCONST 115)
+(defconstant $xillchr 116)
+(defconstant $xbadsym 117)
+(defconstant $xdoterr 118)
+(defconstant $xbadrdx 119)
+(defconstant $XNOSPREAD 120)
+(defconstant $XFASLVERS 121)
+(defconstant $XNOTFASL 122)
+(defconstant $xudfcall 123)
+
+(defconstant $xusecX 127)
+(defconstant $ximprtcx 128)
+(defconstant $xbadnum 129)	 ;Bad arg to #b/#o/#x/#r... 
+(defconstant $XNOPKG 130)
+(defconstant $xnoesym 131)
+(defconstant $XBADFASL 132)
+(defconstant $ximprtc 133)
+(defconstant $xunintc 134)
+(defconstant $XSYMACC 135)
+(defconstant $XEXPRTC 136)
+(defconstant $xusec 137)
+(defconstant $xduppkg 138)
+(defconstant $xrmactx 139)
+(defconstant $xnordisp 140)
+(defconstant $xrdnoarg 141)
+(defconstant $xrdndarg 142)
+(defconstant $xmacrdx 143)
+(defconstant $xduprdlbl 144)
+(defconstant $xnordlbl 145)
+(defconstant $xrdfont 146)
+(defconstant $xrdname 147)
+(defconstant $XNDIMS 148)
+(defconstant $err-disp-size 149)
+(defconstant $XNARGS 150)
+(defconstant $xdifdim 151)
+(defconstant $xkeyconflict 152)
+(defconstant $XBADKEYS 153)
+(defconstant $xtoofew 154)
+(defconstant $xtoomany 155)
+(defconstant $XWRONGTYPE 157)
+(defconstant $XBADSTRUCT 158)
+(defconstant $XSTRUCTBOUNDS 159)
+(defconstant $XCALLNOTLAMBDA 160)
+(defconstant $XTEMPFLT 161)
+(defconstant $xrdfeature 163)
+(defconstant $err-no-file 164)
+(defconstant $err-bad-named-arg 165)
+(defconstant $err-bad-named-arg-2 166)
+(defconstant $XCALLTOOMANY 167)
+(defconstant $XCALLTOOFEW 168)
+(defconstant $XCALLNOMATCH 169)
+(defconstant $XIMPROPERLIST 170)
+(defconstant $XNOFILLPTR 171)
+(defconstant $XMALADJUST 172)
+(defconstant $XACCESSNTH 173)
+(defconstant $XNOTELT 174)
+(defconstant $XSGEXHAUSTED 175)
+(defconstant $XSGNARGS 176)
+(defconstant $XTOOMANYVALUES 177)
+(defconstant $XFOREIGNEXCEPTION 200)
+
+(defconstant $cons-area.gspace-start 0)
+(defconstant $cons-area.gspace-end 4)
+(defconstant $cons-area.ispace-start 8)
+(defconstant $cons-area.ispace-end 12)
+(defconstant $cons-area.pgc-count 16)
+(defconstant $cons-area.pgc-time 20)
+(defconstant $cons-area.total 24)
+
+
+;; Values returned by %number-check.
+
+(defconstant $Num1Dfloat 0)
+(defconstant $Num1Int 2)
+(defconstant $Num1Sfloat 4)
+(defconstant $Num1Ratio 6)
+(defconstant $Num1CR 8)
+(defconstant $Num1CF 10)
+(defconstant $Num1CS 12)
+
+(defconstant %numeric-type-names-alist% 
+  `((double-float . ,$Num1Dfloat)
+    (integer . ,$Num1Int)
+    (short-float . ,$Num1Sfloat)
+    (ratio . ,$Num1Ratio)
+    ((complex rational) . ,$Num1CR)
+    ((complex double-float) . ,$Num1CF)
+    ((complex short-float) . ,$Num1CS)))
+  
+(defmacro numeric-dispatch (numform &body cases)
+  (flet ((numtype (name)
+           (if (memq name '(t otherwise))
+             name
+             (dolist (pair %numeric-type-names-alist% (error "Unknown numeric type name ~s" name))
+               (when (subtypep name (car pair)) (return (cdr pair)))))))
+    (flet ((numify (case)
+             (destructuring-bind (types &body body) case
+               (if (atom types)
+                 `(,(numtype types) ,@body)
+                 `(,(mapcar #'numtype types) ,@body)))))
+      `(case (%number-check ,numform)
+         ,@(mapcar #'numify cases)))))
+
+(def-accessors (random-state) %svref
+  ()
+  random.seed-1
+  random.seed-2)
+
+;;; IEEE-floating-point constants.
+
+(defconstant IEEE-single-float-bias 126)
+(defconstant IEEE-single-float-exponent-offset 23)
+(defconstant IEEE-single-float-exponent-width 8)
+(defconstant IEEE-single-float-mantissa-offset 0)
+(defconstant IEEE-single-float-mantissa-width 23)
+(defconstant IEEE-single-float-hidden-bit 23)
+(defconstant IEEE-single-float-signalling-NAN-bit 22)
+(defconstant IEEE-single-float-normal-exponent-min 1)
+(defconstant IEEE-single-float-normal-exponent-max 254)
+(defconstant IEEE-single-float-digits (1+ IEEE-single-float-mantissa-width))
+
+;;; Double-floats are IEEE DOUBLE-FLOATs in both MCL implementations.
+
+(defconstant IEEE-double-float-bias 1022)
+(defconstant IEEE-double-float-exponent-offset 52)
+(defconstant IEEE-double-float-exponent-width 11)
+(defconstant IEEE-double-float-mantissa-offset 0)
+(defconstant IEEE-double-float-mantissa-width 52)
+(defconstant IEEE-double-float-hidden-bit 52)
+(defconstant IEEE-double-float-signalling-NAN-bit 51)
+(defconstant IEEE-double-float-normal-exponent-min 1)
+(defconstant IEEE-double-float-normal-exponent-max 2046)
+(defconstant IEEE-double-float-digits (1+ IEEE-double-float-mantissa-width))
+
+
+
+
+(def-accessors (ptaskstate) %svref
+  nil                                   ;ptaskstate
+  ptaskstate.nexttick
+  ptaskstate.interval
+  ptaskstate.privatedata
+  ptaskstate.flags)
+
+
+
+
+ 
+
+
+;;;;;; clos instance and class layout.
+
+;;; All standard-instances (classes, instances other than funcallable
+;;; instances) consist of a vector of slot values and a pointer to the
+;;; class wrapper.
+(def-accessors (instance) %svref
+  instance.hash				; a fixnum for EQ-based hashing
+  instance.class-wrapper
+  instance.slots			; a slot-vector
+)
+;;; Doing this via %SLOT-REF traps if the slot is unbound
+(defmacro standard-instance-instance-location-access (instance location)
+  `(%slot-ref (instance-slots ,instance) ,location))
+
+;;; Get the "raw" contents of the slot, even if it's %SLOT-UNBOUND-MARKER.
+(defmacro %standard-instance-instance-location-access (instance location)
+  `(%svref (instance-slots ,instance) ,location))
+
+(defmacro set-standard-instance-instance-location-access (instance location new)
+  `(setf (%svref (instance-slots ,instance) ,location) ,new))
+
+(defsetf standard-instance-instance-location-access
+    set-standard-instance-instance-location-access)
+
+(defmacro standard-generic-function-instance-location-access (sgf location)
+  `(%slot-ref (gf.slots ,sgf) ,location))
+
+(defmacro %standard-generic-function-instance-location-access (sgf location)
+  `(%svref (gf.slots ,sgf) ,location))
+
+(defmacro set-standard-generic-function-instance-location-access (sgf location new)
+  `(setf (%svref (gf.slots ,sgf) ,location) ,new))
+
+(defsetf standard-generic-function-instance-location-access
+    set-standard-generic-function-instance-location-access)
+
+;;; Slot vectors contain the instance they "belong" to (or NIL) in
+;;; their 0th element, and the instance's slots in elements 1 .. n.
+
+(def-accessors (slot-vector) %svref
+  slot-vector.instance
+  )
+
+(def-accessors (class-wrapper) %svref
+  nil                                   ; 'class-wrapper
+  %wrapper-hash-index                   ; for generic-function dispatch tables
+  %wrapper-class                        ; the class itself
+  %wrapper-instance-slots               ; vector of instance slot names
+  %wrapper-class-slots                  ; alist of (name . value-cell) pairs
+  %wrapper-slot-id->slotd               ; map slot-id to slotd, or NIL
+  %wrapper-slot-id-map                  ; (vector (mod nslots) next-slot-id-index)
+  %wrapper-slot-definition-table        ; vector of nil || slot-definitions
+  %wrapper-slot-id-value                ; "fast" SLOT-VALUE function
+  %wrapper-set-slot-id-value            ; "fast" (SETF SLOT-VALUE) function
+  %wrapper-cpl                          ; cached cpl of %wrapper-class or NIL
+  %wrapper-class-ordinal                ; cached copy of class-ordinal
+  %wrapper-cpl-bits                     ; bitvector representation of cpl
+)
+
+;; Use the wrapper-class-slots for info on obsolete & forwarded instances
+;; Note: none of this xx-forwarding-xx or xx-forwarded-xx is valid unless
+;; (%wrapper-instance-slots ...) is 0.
+(defmacro %wrapper-forwarding-info (instance)
+  `(%wrapper-class-slots ,instance))
+
+(defmacro %forwarding-instance-slots (info)
+  `(%car ,info))
+(defmacro %forwarding-class-slots (info)
+  `(%cdr ,info))
+
+
+(defmacro %wrapper-forwarded-instance-slots (instance)
+  `(%forwarding-instance-slots (%wrapper-forwarding-info ,instance)))
+(defmacro %wrapper-forwarded-class-slots (instance)
+  `(%forwarding-class-slots (%wrapper-forwarding-info ,instance)))
+
+
+(defmacro %cons-forwarding-info (instance-slots class-slots)
+  `(cons ,instance-slots ,class-slots))
+
+
+(defmacro %cons-wrapper (class &optional 
+                               (hash-index '(new-class-wrapper-hash-index)))
+  (let* ((c (gensym)))
+  `(let* ((,c ,class))
+    (%istruct 'class-wrapper ,hash-index ,c nil nil #'slot-id-lookup-no-slots nil nil #'%slot-id-ref-missing #'%slot-id-set-missing nil (%class-ordinal ,c t) nil))))
+
+
+(defmacro %instance-class (instance)
+  `(%wrapper-class (instance.class-wrapper ,instance)))
+
+(def-accessors standard-instance-instance-location-access ;A specializer
+    nil					; backptr
+  specializer.direct-methods
+)
+
+(def-accessors (class) standard-instance-instance-location-access ;Slots of any class
+  nil                                   ; backptr
+  %class.direct-methods			; aka specializer.direct-methods
+  %class.prototype			; prototype instance
+  %class.name
+  %class.cpl                            ; class-precedence-list
+  %class.own-wrapper                    ; own wrapper (or nil)
+  %class.local-supers                   ; class-direct-superclasses
+  %class.subclasses                     ; class-direct-subclasses
+  %class.dependents			; arbitrary dependents
+  %class.ctype
+  %class.direct-slots                   ; local slots
+  %class.slots                          ; all slots
+  %class.info                           ; cons of kernel-p, proper-name
+  %class.local-default-initargs         ; local default initargs alist
+  %class.default-initargs               ; all default initargs if initialized.
+)
+
+
+(def-accessors () standard-instance-instance-location-access ; any standard class
+  nil                                   ; slot-vector backptr
+  nil                                   ; usual class stuff: direct-methods,
+  nil					;   prototype,
+  nil					;   name,
+  nil					;   cpl,
+  nil					;   own-wrapper,
+  nil					;   local-supers,
+  nil					;   subclasses,
+  nil					;   dependents,
+  nil					;   ctype.
+  nil                                   ; local slots
+  nil                                   ; all slots
+  nil                                ; true if a non-redefinable class
+  nil                                   ; local default initargs alist
+  nil                           ; all default initargs if initialized.
+  %class.alist                          ; other stuff about the class.
+  %class.make-instance-initargs         ; (vector of) valid initargs to make-instance
+  %class.reinit-initargs                ; valid initargs to reinitialize-instance
+  %class.redefined-initargs             ; valid initargs to update-instance-for-redefined-class
+  %class.changed-initargs               ; valid initargs to update-instance-for-changed-class
+  )
+
+
+
+
+
+(defmacro %instance-vector (wrapper &rest slots)
+  (let ((instance (gensym))
+	(slots-vector (gensym)))
+    `(let* ((,instance (gvector :instance 0 ,wrapper nil))
+	    (,slots-vector (gvector :slot-vector ,instance ,@slots)))
+       (setf (instance.slots ,instance) ,slots-vector
+	     (instance.hash ,instance) (strip-tag-to-fixnum ,instance))
+       ,instance)))
+ 
+
+
+
+(defmacro %cons-built-in-class (name)
+  `(%instance-vector  *built-in-class-wrapper*
+    nil                                 ;direct-methods
+    nil                                 ;prototype
+    ,name                               ;name
+    nil                                 ;precedence-list
+    nil                                 ;own-wrapper
+    nil                                 ;direct-superclasses
+    nil                                 ;direct-subclasses
+    nil                                 ;dependents
+    nil                                 ;class-ctype
+    nil                                 ;direct-slots
+    nil                                 ;slots
+    (cons nil nil)                      ;info
+    nil                                 ;direct-default-initargs
+    nil                                 ;default-initargs
+    ))
+
+(defmacro %cons-standard-class (name &optional
+                                     (metaclass-wrapper '*standard-class-wrapper*))
+  `(%instance-vector  ,metaclass-wrapper
+    nil                                 ;direct-methods
+    nil                                 ;prototype
+    ,name                               ;name
+    nil                                 ;precedence-list
+    nil                                 ;own-wrapper
+    nil                                 ;direct-superclasses
+    nil                                 ;direct-subclasses
+    nil                                 ;dependents
+    nil                                 ;class-ctype
+    nil                                 ;direct-slots
+    nil                                 ;slots
+    (cons nil nil)                      ;info
+    nil                                 ;direct-default-initargs
+    nil                                 ;default-initargs
+    nil                                 ;alist
+    nil                                 ;make-instance-initargs
+    nil                                 ;reinit-initargs
+    nil                                 ;redefined-initargs
+    nil                                 ;changed-initargs
+    )
+)
+
+
+
+(defconstant max-class-ordinal (ash 1 20))
+
+
+(def-accessors () standard-instance-instance-location-access
+  nil					; backptr
+  standard-slot-definition.name
+  standard-slot-definition.type
+  standard-slot-definition.initfunction
+  standard-slot-definition.initform
+  standard-slot-definition.initargs
+  standard-slot-definition.allocation
+  standard-slot-definition.documentation
+  standard-slot-definition.class
+  )
+
+(def-accessors () standard-instance-instance-location-access
+  nil
+  standard-effective-slot-definition.name
+  standard-effective-slot-definition.type
+  standard-effective-slot-definition.initfunction
+  standard-effective-slot-definition.initform
+  standard-effective-slot-definition.initargs
+  standard-effective-slot-definition.allocation
+  standard-effective-slot-definition.documentation
+  standard-effective-slot-definition.class
+  standard-effective-slot-definition.location
+  standard-effective-slot-definition.slot-id
+  standard-effective-slot-definition.type-predicate
+  )
+
+
+(def-accessors () standard-instance-instance-location-access
+  nil
+  standard-direct-slot-definition.name
+  standard-direct-slot-definition.type
+  standard-direct-slot-definition.initfunction
+  standard-direct-slot-definition.initform
+  standard-direct-slot-definition.initargs
+  standard-direct-slot-definition.allocation
+  standard-direct-slot-definition.documentation
+  standard-direct-slot-definition.class
+  standard-direct-slot-definition.readers
+  standard-direct-slot-definition.writers  
+  )
+
+;; Methods
+(defmacro %cons-method (name qualifiers specializers function &optional 
+                             (class '*standard-method-class*))
+  `(%instance-vector 
+    (%class.own-wrapper ,class)
+    ,qualifiers
+    ,specializers
+    ,function
+    nil
+    ,name))
+
+
+(def-accessors standard-instance-instance-location-access ; method
+  nil                                   ; backptr
+  %method.qualifiers
+  %method.specializers
+  %method.function
+  %method.gf
+  %method.name
+  %method.lambda-list)
+
+;;; Painful, but seems to be necessary.
+(def-accessors standard-instance-instance-location-access ; standard-accessor-method
+  nil                                   ; backptr
+  nil					;%method.qualifiers
+  nil					;%method.specializers
+  nil					;%method.function
+  nil					;%method.gf
+  nil					;%method.name
+  nil					;%method.lambda-list
+  %accessor-method.slot-definition)
+
+
+
+
+
+;; Generic Function Dispatch tables.
+;; These accessors are at the beginning of the table.
+;; rest of the table is alternating wrappers & combined-methods.
+
+(def-accessors %svref
+    %gf-dispatch-table-methods		; List of methods
+    %gf-dispatch-table-precedence-list	; List of argument numbers in precedence order
+    %gf-dispatch-table-keyvect          ; keyword vector, set by E-G-F.
+    %gf-dispatch-table-argnum		; argument number
+    %gf-dispatch-table-gf		; back pointer to gf - NEW
+    %gf-dispatch-table-mask		; mask for rest of table
+    %gf-dispatch-table-first-data)	; offset to first data.  Must follow mask.
+  
+(defmacro %gf-dispatch-table-size (dt)
+  `(%i- (uvsize ,dt) ,(+ 2 %gf-dispatch-table-first-data)))
+
+(defmacro %gf-dispatch-table-ref (table index)
+  `(%svref ,table (%i+ ,index %gf-dispatch-table-first-data)))
+
+(defmacro %cons-gf-dispatch-table (size)
+  `(make-array (%i+ ,size ,(%i+ 2 %gf-dispatch-table-first-data))
+               :initial-element nil))
+
+
+;;; method-combination info
+(def-accessors svref
+  mci.class                             ; short-method-combination or long-method-combination
+  mci.options                           ; short-form-options or long-form function
+  mci.instances                         ; a population of instances
+  mci.gfs                               ; a population of generic-functions
+  )
+
+(defmacro %cons-mci (&optional class options)
+  `(vector ,class ,options (%cons-population nil) (%cons-population nil)))
+
+;;; slot accessor info for primary classes
+(def-accessors %svref
+  %slot-accessor-info.class
+  (%slot-accessor-info.accessor %slot-accessor-info.slot-name)
+  %slot-accessor-info.offset
+  )
+
+(defmacro %cons-slot-accessor-info (class accessor-or-slot-name &optional offset)
+  `(vector ,class ,accessor-or-slot-name ,offset))
+
+(def-accessors (combined-method) nth-immediate
+  combined-method.code-vector		; trampoline code vector
+  combined-method.thing			; arbitrary arg to dcode
+  combined-method.dcode			; discriminator function
+  combined-method.gf			; gf
+  combined-method.bits			; lfun-bits
+  )
+;;; The structure of a generic-function object (funcallable instance).
+(def-accessors (generic-function) nth-immediate
+  gf.code-vector			; trampoline code-vector
+  gf.instance.class-wrapper		; instance class-wrapper
+  gf.slots				; slots vector
+  gf.dispatch-table			; effective-method cache
+  gf.dcode				; discriminating code
+  gf.hash				; hashing identity
+  gf.bits				;
+  )
+
+;;; The slots of STANDARD-GENERIC-FUNCTION.
+(def-accessors (standard-generic-function) standard-generic-function-instance-location-access
+  nil					; backptr
+  sgf.name				; generic-function-name
+  sgf.method-combination		; generic-function-method-combination
+  sgf.method-class			; generic-function-method-class
+  sgf.methods				; generic-function-methods
+  sgf.decls				; generic-function-declarations
+  sgf.%lambda-list                      ; explicit lambda-list
+  sgf.dependents			; dependents for MAP-DEPENDENTS et al.
+  )
+
+(def-accessors (slot-id) %svref
+  nil                                   ;'slot-id
+  slot-id.name                          ; slot name (symbol)
+  slot-id.index                         ; index (integer)
+  )
+
+(def-accessors (foreign-object-domain) %svref
+  nil					; foreign-object-domain
+  foreign-object-domain-index		; 1..n
+  foreign-object-domain-name		;
+  foreign-object-domain-recognize	; function: is object one of ours ?
+  foreign-object-domain-class-of	; function: returns class of object
+  foreign-object-domain-classp		; function: true if object is a class
+  foreign-object-domain-instance-class-wrapper ; function: returns wrapper of object's class
+  foreign-object-domain-class-own-wrapper ; function: returns class own wrapper if class
+  foreign-object-domain-slots-vector	; returns slots vector of object or nil
+  foreign-object-domain-class-ordinal   ; returns class ordinal if class
+  foreign-object-domain-set-class-ordinal  ; sets class ordinal if class
+  )
+
+;;; Hash table accessors.
+(def-accessors (hash-table) %svref
+    nil                                 ; 'HASH-TABLE
+    nhash.keytransF                     ; transform key into (values primary addressp)
+    nhash.compareF                      ; comparison function: 0 -> eq, -1 ->eql, else function
+    nhash.rehash-bits                   ; bitset (array (unsigned-byte 32)) for rehash
+    nhash.vector                        ; N <key,value> pairs; n relatively prime to & larger than all secondary keys
+    nhash.lock                          ; flag: non-zero if lock-free
+    nhash.owner                         ; tcr of "owning" thread, else NIL.
+    nhash.grow-threshold                ; Max # entries before grow
+    nhash.rehash-ratio                  ; inverted rehash-threshold
+    nhash.rehash-size			; rehash-size from user
+    nhash.puthash-count                 ; number of times table has been rehashed or grown
+    nhash.exclusion-lock                ; read-write lock for access
+    nhash.find                          ; function: find vector-index
+    nhash.find-new                      ; function: find vector-index on put
+    nhash.read-only                     ; boolean: true when read-only
+    )
+
+(def-accessors (lock-acquisition) %svref
+  nil                                   ; 'lock-acquisition
+  lock-acquisition.status
+  )
+
+(defmacro make-lock-acquisition ()
+  `(%istruct 'lock-acquisition nil))
+
+(def-accessors (semaphore-notification) %svref
+  nil                                   ; 'semaphore-notification
+  semaphore-notification.status
+  )
+
+(defmacro make-semaphore-notification ()
+  `(%istruct 'semaphore-notification nil))
+
+;;; Why were these ever in architecture-dependent packages ?
+(defenum (:prefix "AREA-")
+  void                                  ; list header
+  cstack                                ; a control stack
+  vstack                                ; a value stack
+  tstack                                ; (dynamic-extent) temp stack
+  readonly                              ; readonly section
+  watched				; static area containing a single object
+  static-cons                           ; static cons cells
+  managed-static                        ; growable static area
+  static                                ; static data in application
+  dynamic                               ; dynmaic (heap) data in application
+)
+
+;;; areas are sorted such that (in the "succ" direction) codes are >=.
+;;; If you think that you're looking for a stack (instead of a heap), look
+;;; in the "pred" direction from the all-areas header.
+(defconstant max-stack-area-code area-tstack)
+(defconstant min-heap-area-code area-readonly)
+
+
+;;; Lisp threads, which barely need to exist and aren't worth burning
+;;; a separate tag on ...
+(def-accessors (lisp-thread) %svref
+  nil                                   ;'lisp-thread
+  lisp-thread.tcr
+  lisp-thread.name
+  lisp-thread.cs-size
+  lisp-thread.vs-size
+  lisp-thread.ts-size
+  lisp-thread.initial-function.args
+  lisp-thread.interrupt-functions
+  lisp-thread.interrupt-lock
+  lisp-thread.startup-function
+  lisp-thread.state
+  lisp-thread.state-change-lock
+  )
+
+;;; "basic" (e.g., builtin, non-extensible) streams.
+(def-accessors (basic-stream) %svref
+  basic-stream.wrapper                  ; a class wrapper object
+  basic-stream.flags                    ; fixnum; bits.
+  basic-stream.state                    ; typically an ioblock
+  basic-stream.info                     ; a plist for less-often-used things.
+)
+
+(def-accessors (basic-file-stream) %svref
+  basic-file-stream.class               ; a class object
+  basic-file-stream.flags               ; fixnum; bits.
+  basic-file-stream.state               ; typically an ioblock
+  basic-file-stream.info                ; a plist for less-often-used things.
+  basic-file-stream.filename
+  basic-file-stream.actual-filename
+  basic-file-stream.external-format
+  )
+
+;;; Bits in basic-stream.flags
+(defenum (:prefix "BASIC-STREAM-FLAG.")
+  open-input
+  open-output
+  open-character
+  open-binary
+  file-stream)
+
+
+(def-accessors (class-cell) %svref
+  nil                                   ; 'class-cell
+  class-cell-name
+  class-cell-class
+  class-cell-instantiate
+  class-cell-extra                      ; wrapper in some cases
+  )
+
+(defmacro make-class-cell (name) `(%istruct 'class-cell ,name nil '%make-instance nil))
+
+;;; Map between TYPE-SPECIFIERS and CTYPEs
+(def-accessors (type-cell) %svref
+  nil
+  type-cell-type-specifier
+  type-cell-ctype)
+
+(defmacro make-type-cell (specifier) `(%istruct 'type-cell ,specifier nil))
+
+;;; Map between package names and packages, sometimes.
+(def-accessors (package-ref) %svref
+  nil
+  package-ref.name                      ; a string
+  package-ref.pkg                       ; a package or NIL
+  )
+
+(defmacro make-package-ref (name) `(%istruct 'package-ref (string ,name) nil))
+
+
+(def-accessor-macros %svref
+  nil                                 ; 'external-entry-point
+  eep.address
+  eep.name
+  eep.container)
+
+(defmacro %cons-external-entry-point (name &optional container)
+  `(%istruct 'external-entry-point nil ,name ,container))
+
+(def-accessor-macros %svref
+    nil                                 ;'foreign-variable
+  fv.addr                               ; a MACPTR, or nil
+  fv.name                               ; a string
+  fv.type                               ; a foreign type
+  fv.container                          ; containing library
+  )
+
+
+(def-accessor-macros %svref
+    nil					;'shlib
+  shlib.soname
+  shlib.pathname
+  shlib.handle                          ; if explicitly opened
+  shlib.map
+  shlib.base
+  shlib.opencount)
+
+(defmacro %cons-shlib (soname pathname map base)
+  `(%istruct 'shlib ,soname ,pathname nil ,map ,base 0))
+
+(def-accessors uvref ; %svref
+    ()                                  ;'entry
+  entry-test                          ;predicate function or count of higher priority others.
+  entry-fn                            ;pprint function
+  entry-full-spec                     ;list of priority and type specifier
+  )
+
+;;; MacOS toolbox routines were once written mostly in Pascal, so some
+;;; code still refers to callbacks from foreign code as "pascal-callable
+;;; functions".
+
+; %Pascal-Functions% Entry
+(def-accessor-macros %svref
+  pfe.routine-descriptor
+  pfe.proc-info
+  pfe.lisp-function
+  pfe.sym
+  pfe.without-interrupts
+  pfe.trace-p)
+
+(defmacro %cons-pfe (routine-descriptor proc-info lisp-function sym without-interrupts)
+  `(vector ,routine-descriptor ,proc-info ,lisp-function ,sym ,without-interrupts nil))
+
+
+(def-accessors %svref
+    ()                                  ; 'xp-structure
+  xp-base-stream ;;The stream io eventually goes to.
+  xp-linel ;;The line length to use for formatting.
+  xp-line-limit ;;If non-NIL the max number of lines to print.
+  xp-line-no ;;number of next line to be printed.
+  xp-char-mode ;;NIL :UP :DOWN :CAP0 :CAP1 :CAPW
+  xp-char-mode-counter                  ;depth of nesting of ~(...~)
+  xp-depth-in-blocks ;;Number of logical blocks at QRIGHT that 
+  ;;are started but not ended.              
+  xp-block-stack 
+  xp-block-stack-ptr
+  ;;This stack is pushed and popped in accordance with the way blocks are 
+  ;;nested at the moment they are entered into the queue.  It contains the 
+  ;;following block specific value.
+  ;;SECTION-START total position where the section (see AIM-1102)
+  ;;that is rightmost in the queue started.
+  xp-buffer
+  xp-charpos
+  xp-buffer-ptr 
+  xp-buffer-offset
+  ;;This is a vector of characters (eg a string) that builds up the
+  ;;line images that will be printed out.  BUFFER-PTR is the
+  ;;buffer position where the next character should be inserted in
+  ;;the string.  CHARPOS is the output character position of the
+  ;;first character in the buffer (non-zero only if a partial line
+  ;;has been output).  BUFFER-OFFSET is used in computing total lengths.
+  ;;It is changed to reflect all shifting and insertion of prefixes so that
+  ;;total length computes things as they would be if they were 
+  ;;all on one line.  Positions are kept three different ways
+  ;; Buffer position (eg BUFFER-PTR)
+  ;; Line position (eg (+ BUFFER-PTR CHARPOS)).  Indentations are stored in this form.
+  ;; Total position if all on one line (eg (+ BUFFER-PTR BUFFER-OFFSET))
+  ;;  Positions are stored in this form.
+  xp-queue
+  xp-qleft
+  xp-qright
+  ;;This holds a queue of action descriptors.  QLEFT and QRIGHT
+  ;;point to the next entry to dequeue and the last entry enqueued
+  ;;respectively.  The queue is empty when
+  ;;(> QLEFT QRIGHT).  The queue entries have several parts:
+  ;;QTYPE one of :NEWLINE/:IND/:START-BLOCK/:END-BLOCK
+  ;;QKIND :LINEAR/:MISER/:FILL/:MANDATORY or :UNCONDITIONAL/:FRESH
+  ;; or :BLOCK/:CURRENT
+  ;;QPOS total position corresponding to this entry
+  ;;QDEPTH depth in blocks of this entry.
+  ;;QEND offset to entry marking end of section this entry starts. (NIL until known.)
+  ;; Only :start-block and non-literal :newline entries can start sections.
+  ;;QOFFSET offset to :END-BLOCK for :START-BLOCK (NIL until known).
+  ;;QARG for :IND indentation delta
+  ;;     for :START-BLOCK suffix in the block if any.
+  ;;                      or if per-line-prefix then cons of suffix and
+  ;;                      per-line-prefix.
+  ;;     for :END-BLOCK suffix for the block if any.
+  xp-prefix
+  ;;this stores the prefix that should be used at the start of the line
+  xp-prefix-stack
+  xp-prefix-stack-ptr
+  ;;This stack is pushed and popped in accordance with the way blocks 
+  ;;are nested at the moment things are taken off the queue and printed.
+  ;;It contains the following block specific values.
+  ;;PREFIX-PTR current length of PREFIX.
+  ;;SUFFIX-PTR current length of pending suffix
+  ;;NON-BLANK-PREFIX-PTR current length of non-blank prefix.
+  ;;INITIAL-PREFIX-PTR prefix-ptr at the start of this block.
+  ;;SECTION-START-LINE line-no value at last non-literal break at this level.
+  xp-suffix
+  ;;this stores the suffixes that have to be printed to close of the current
+  ;;open blocks.  For convenient in popping, the whole suffix
+  ;;is stored in reverse order.
+  xp-stream  ;;; the xp-stream containing this structure
+  xp-string-stream ;; string-stream for output until first circularity (in case none)
+  )
+
+(def-accessors (afunc) %svref
+  ()                                    ; 'afunc
+  afunc-acode
+  afunc-parent
+  afunc-vars
+  afunc-inherited-vars
+  afunc-blocks
+  afunc-tags
+  afunc-inner-functions
+  afunc-name
+  afunc-bits
+  afunc-lfun
+  afunc-environment
+  afunc-lambdaform
+  afunc-argsword
+  afunc-ref-form
+  afunc-warnings
+  afunc-fn-refcount
+  afunc-fn-downward-refcount
+  afunc-all-vars
+  afunc-callers
+  afunc-vcells
+  afunc-fcells
+  afunc-fwd-refs
+  afunc-lfun-info
+  afunc-linkmap)
+
+(defmacro %make-afunc ()
+  `(%istruct 'afunc
+    nil                                 ;afunc-acode
+    nil                                 ;afunc-parent
+    nil                                 ;afunc-vars
+    nil                                 ;afunc-inherited-vars
+    nil                                 ;afunc-blocks
+    nil                                 ;afunc-tags
+    nil                                 ;afunc-inner-functions
+    nil                                 ;afunc-name
+    nil                                 ;afunc-bits
+    nil                                 ;afunc-lfun
+    nil                                 ;afunc-environment
+    nil                                 ;afunc-lambdaform
+    nil                                 ;afunc-argsword
+    nil                                 ;afunc-ref-form
+    nil                                 ;afunc-warnings
+    nil                                 ;afunc-fn-refcount
+    nil                                 ;afunc-fn-downward-refcount
+    nil                                 ;afunc-all-vars
+    nil                                 ;afunc-callers
+    nil                                 ;afunc-vcells
+    nil                                 ;afunc-fcells
+    nil                                 ;afunc-fwd-refs
+    nil                                 ;afunc-lfun-info
+    nil                                 ;afunc-linkmap
+    ))
+
+
+(def-accessors (compiler-policy) uvref
+  nil                                   ; 'compiler-policy
+  policy.allow-tail-recursion-elimination
+  policy.inhibit-register-allocation
+  policy.trust-declarations
+  policy.open-code-inline
+  policy.inhibit-safety-checking
+  policy.declarations-typecheck
+  policy.inline-self-calls
+  policy.allow-transforms
+  policy.force-boundp-checks
+  policy.allow-constant-substitution
+  policy.misc)
+
+
+(def-accessors (deferred-warnings) %svref
+  nil
+  deferred-warnings.parent
+  deferred-warnings.warnings
+  deferred-warnings.defs
+  deferred-warnings.last-file
+)
+
+;;; loader framework istruct
+(def-accessors (faslapi) %svref
+  ()
+  ;; these represent all users of faslstate.iobuffer, .bufcount, and
+  ;; .faslfd -- I think these are all the important file- and
+  ;; buffer-IO-specific slots in faslstate; encapsulating these allows
+  ;; sophisticated users to load fasl data from nonstandard sources
+  ;; without too much trouble
+  faslapi.fasl-open
+  faslapi.fasl-close
+  faslapi.fasl-init-buffer
+  faslapi.fasl-set-file-pos
+  faslapi.fasl-get-file-pos
+  faslapi.fasl-read-buffer
+  faslapi.fasl-read-byte
+  faslapi.fasl-read-n-bytes)
+
+
+(defmacro istruct-cell-name (cell)
+  `(car ,cell))
+
+(defmacro istruct-cell-info (cell)
+  `(cdr ,cell))
+
+(provide "LISPEQU")
+
+;;; End of lispequ.lisp
Index: /branches/new-random/library/loop.lisp
===================================================================
--- /branches/new-random/library/loop.lisp	(revision 13309)
+++ /branches/new-random/library/loop.lisp	(revision 13309)
@@ -0,0 +1,2129 @@
+;;;   -*- Mode: LISP; Syntax: Common-lisp; Package: (ANSI-LOOP "COMMON-LISP"); Base: 10; Lowercase:T -*-
+;;;>
+;;;> Portions of LOOP are Copyright (c) 1986 by the Massachusetts Institute of Technology.
+;;;> All Rights Reserved.
+;;;> 
+;;;> Permission to use, copy, modify and distribute this software and its
+;;;> documentation for any purpose and without fee is hereby granted,
+;;;> provided that the M.I.T. copyright notice appear in all copies and that
+;;;> both that copyright notice and this permission notice appear in
+;;;> supporting documentation.  The names "M.I.T." and "Massachusetts
+;;;> Institute of Technology" may not be used in advertising or publicity
+;;;> pertaining to distribution of the software without specific, written
+;;;> prior permission.  Notice must be given in supporting documentation that
+;;;> copying distribution is by permission of M.I.T.  M.I.T. makes no
+;;;> representations about the suitability of this software for any purpose.
+;;;> It is provided "as is" without express or implied warranty.
+;;;> 
+;;;>      Massachusetts Institute of Technology
+;;;>      77 Massachusetts Avenue
+;;;>      Cambridge, Massachusetts  02139
+;;;>      United States of America
+;;;>      +1-617-253-1000
+;;;>
+;;;> Portions of LOOP are Copyright (c) 1989, 1990, 1991, 1992 by Symbolics, Inc.
+;;;> All Rights Reserved.
+;;;> 
+;;;> Permission to use, copy, modify and distribute this software and its
+;;;> documentation for any purpose and without fee is hereby granted,
+;;;> provided that the Symbolics copyright notice appear in all copies and
+;;;> that both that copyright notice and this permission notice appear in
+;;;> supporting documentation.  The name "Symbolics" may not be used in
+;;;> advertising or publicity pertaining to distribution of the software
+;;;> without specific, written prior permission.  Notice must be given in
+;;;> supporting documentation that copying distribution is by permission of
+;;;> Symbolics.  Symbolics makes no representations about the suitability of
+;;;> this software for any purpose.  It is provided "as is" without express
+;;;> or implied warranty.
+;;;> 
+;;;> Symbolics, CLOE Runtime, and Minima are trademarks, and CLOE, Genera,
+;;;> and Zetalisp are registered trademarks of Symbolics, Inc.
+;;;>
+;;;>      Symbolics, Inc.
+;;;>      8 New England Executive Park, East
+;;;>      Burlington, Massachusetts  01803
+;;;>      United States of America
+;;;>      +1-617-221-1000
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Modification History
+;;;
+;;; 07/28/92 bill loop-bind-block now does destructuring correctly.
+;;; 07/07/92 bill Prevent one more warning in loop-hash-table-iteration-path
+;;; 04/23/92 bill loop-do-finally now supports "finally return expr"
+;;;               and "finally [do | doing] {expr}*" instead of just
+;;;               "finally {expr}*".
+;;; 03/23/92 gb   Use IGNORABLE declarations when (if (multiple-value-setq (...) ...) ...)
+;;;               involved.
+;;; ------------- 2.0
+;;; 03/12/92 bill gb's patches to prevent compiler warnings
+;;;               for hash-values, hash-types, and symbols
+
+;;;; LOOP Iteration Macro
+
+(defpackage ANSI-LOOP (:use "COMMON-LISP"))
+
+(in-package :ansi-loop)
+
+;;; Technology.
+;;;
+;;; The LOOP iteration macro is one of a number of pieces of code
+;;; originally developed at MIT for which free distribution has been
+;;; permitted, as long as the code is not sold for profit, and as long
+;;; as notification of MIT's interest in the code is preserved.
+;;;
+;;; This version of LOOP, which is almost entirely rewritten both as
+;;; clean-up and to conform with the ANSI Lisp LOOP standard, started
+;;; life as MIT LOOP version 829 (which was a part of NIL, possibly
+;;; never released).
+;;;
+;;; A "light revision" was performed by me (Glenn Burke) while at
+;;; Palladian Software in April 1986, to make the code run in Common
+;;; Lisp.  This revision was informally distributed to a number of
+;;; people, and was sort of the "MIT" version of LOOP for running in
+;;; Common Lisp.
+;;;
+;;; A later more drastic revision was performed at Palladian perhaps a
+;;; year later.  This version was more thoroughly Common Lisp in style,
+;;; with a few miscellaneous internal improvements and extensions.  I
+;;; have lost track of this source, apparently never having moved it to
+;;; the MIT distribution point.  I do not remember if it was ever
+;;; distributed.
+;;;
+;;; This revision for the ANSI standard is based on the code of my April
+;;; 1986 version, with almost everything redesigned and/or rewritten.
+
+
+
+;;; The design of this LOOP is intended to permit, using mostly the same
+;;; kernel of code, up to three different "loop" macros:
+;;; 
+;;; (1) The unextended, unextensible ANSI standard LOOP;
+;;;
+;;; (2) A clean "superset" extension of the ANSI LOOP which provides
+;;; functionality similar to that of the old LOOP, but "in the style of"
+;;; the ANSI LOOP.  For instance, user-definable iteration paths, with a
+;;; somewhat cleaned-up interface.
+;;;
+;;; (3) Extensions provided in another file which can make this LOOP
+;;; kernel behave largely compatibly with the Genera-vintage LOOP macro,
+;;; with only a small addition of code (instead of two whole, separate,
+;;; LOOP macros).
+;;;
+;;; Each of the above three LOOP variations can coexist in the same LISP
+;;; environment.
+;;; 
+
+
+
+;;;; Miscellaneous Environment Things
+
+;;; The uses of this macro are retained in the CL version of loop, in
+;;; case they are needed in a particular implementation.  Originally
+;;; dating from the use of the Zetalisp COPYLIST* function, this is used
+;;; in situations where, were cdr-coding in use, having cdr-NIL at the
+;;; end of the list might be suboptimal because the end of the list will
+;;; probably be RPLACDed and so cdr-normal should be used instead.
+(defmacro loop-copylist* (l)
+  `(copy-list ,l))
+
+(defvar *loop-gentemp*
+	nil)
+
+(defun loop-gentemp (&optional (pref 'loopvar-))
+  (if *loop-gentemp*
+      (gentemp (string pref))
+      (gensym (string pref))))
+
+(defvar *loop-real-data-type* 'real)
+
+(defun loop-optimization-quantities (env)
+  ;;@@@@ The ANSI conditionalization here is for those lisps that implement
+  ;; DECLARATION-INFORMATION (from cleanup SYNTACTIC-ENVIRONMENT-ACCESS).
+  ;; It is really commentary on how this code could be written.  I don't
+  ;; actually expect there to be an ANSI #+-conditional -- it should be
+  ;; replaced with the appropriate conditional name for your
+  ;; implementation/dialect.
+  ;; Uhh, DECLARATION-INFORMATION isn't ANSI-CL anymore
+  (let ((stuff (ccl:declaration-information 'optimize env)))
+    (values (or (cadr (assoc 'speed stuff)) 1)
+            (or (cadr (assoc 'space stuff)) 1)
+            (or (cadr (assoc 'safety stuff)) 1)
+            (or (cadr (assoc 'compilation-speed stuff)) 1)
+            (or (cadr (assoc 'debug stuff)) 1))))
+
+
+;;;@@@@ The following form takes a list of variables and a form which presumably
+;;; references those variables, and wraps it somehow so that the compiler does not
+;;; consider those variables have been referenced.  The intent of this is that
+;;; iteration variables can be flagged as unused by the compiler, e.g. I in
+;;; (loop for i from 1 to 10 do (print t)), since we will tell it when a usage
+;;; of it is "invisible" or "not to be considered".
+;;;We implicitly assume that a setq does not count as a reference.  That is, the
+;;; kind of form generated for the above loop construct to step I, simplified, is
+;;; `(SETQ I ,(HIDE-VARIABLE-REFERENCES '(I) '(1+ I))).
+(defun hide-variable-references (variable-list form)
+  (declare (ignore variable-list))
+  form)
+
+;;;@@@@ The following function takes a flag, a variable, and a form which presumably
+;;; references that variable, and wraps it somehow so that the compiler does not
+;;; consider that variable to have been referenced.  The intent of this is that
+;;; iteration variables can be flagged as unused by the compiler, e.g. I in
+;;; (loop for i from 1 to 10 do (print t)), since we will tell it when a usage
+;;; of it is "invisible" or "not to be considered".
+;;;We implicitly assume that a setq does not count as a reference.  That is, the
+;;; kind of form generated for the above loop construct to step I, simplified, is
+;;; `(SETQ I ,(HIDE-VARIABLE-REFERENCES T 'I '(1+ I))).
+;;;Certain cases require that the "invisibility" of the reference be conditional upon
+;;; something.  This occurs in cases of "named" variables (the USING clause).  For instance,
+;;; we want IDX in (LOOP FOR E BEING THE VECTOR-ELEMENTS OF V USING (INDEX IDX) ...)
+;;; to be "invisible" when it is stepped, so that the user gets informed if IDX is
+;;; not referenced.  However, if no USING clause is present, we definitely do not
+;;; want to be informed that some random gensym is not used.
+;;;It is easier for the caller to do this conditionally by passing a flag (which
+;;; happens to be the second value of NAMED-VARIABLE, q.v.) to this function than
+;;; for all callers to contain the conditional invisibility construction.
+(defun hide-variable-reference (really-hide variable form)
+  (declare (ignore really-hide variable))
+  form)
+
+
+
+;;;; List Collection Macrology
+
+
+(defmacro with-loop-list-collection-head ((head-var tail-var &optional user-head-var)
+					  &body body)
+  (let ((l (and user-head-var (list (list user-head-var nil)))))
+    `(let* ((,head-var (list nil)) (,tail-var ,head-var) ,@l)
+       ,@body)))
+
+
+(defmacro loop-collect-rplacd (&environment env
+			       (head-var tail-var &optional user-head-var) form)
+  (setq form (macroexpand form env))
+  (flet ((cdr-wrap (form n)
+	   (declare (fixnum n))
+	   (do () ((<= n 4) (setq form `(,(case n
+					    (1 'cdr)
+					    (2 'cddr)
+					    (3 'cdddr)
+					    (4 'cddddr))
+					 ,form)))
+	     (setq form `(cddddr ,form) n (- n 4)))))
+    (let ((tail-form form) (ncdrs nil))
+      ;;Determine if the form being constructed is a list of known length.
+      (when (consp form)
+	(cond ((eq (car form) 'list)
+	       (setq ncdrs (1- (length (cdr form))))
+	       ;;@@@@ Because the last element is going to be RPLACDed,
+	       ;; we don't want the cdr-coded implementations to use
+	       ;; cdr-nil at the end (which would just force copying
+	       ;; the whole list again).
+	       )
+	      ((member (car form) '(list* cons))
+	       (when (and (cddr form) (member (car (last form)) '(nil 'nil)))
+		 (setq ncdrs (- (length (cdr form)) 2))))))
+      (let ((answer
+	      (cond ((null ncdrs)
+		     `(when (setf (cdr ,tail-var) ,tail-form)
+			(setq ,tail-var (last (cdr ,tail-var)))))
+		    ((< ncdrs 0) (return-from loop-collect-rplacd nil))
+		    ((= ncdrs 0)
+		     ;;@@@@ Here we have a choice of two idioms:
+		     ;; (rplacd tail (setq tail tail-form))
+		     ;; (setq tail (setf (cdr tail) tail-form)).
+		     ;;Genera and most others I have seen do better with the former.
+		     `(rplacd ,tail-var (setq ,tail-var ,tail-form)))
+		    (t `(setq ,tail-var ,(cdr-wrap `(setf (cdr ,tail-var) ,tail-form)
+						   ncdrs))))))
+	;;If not using locatives or something similar to update the user's
+	;; head variable, we've got to set it...  It's harmless to repeatedly set it
+	;; unconditionally, and probably faster than checking.
+	(when user-head-var
+          (setq answer `(progn ,answer (setq ,user-head-var (cdr ,head-var)))))
+	answer))))
+
+
+(defmacro loop-collect-answer (head-var &optional user-head-var)
+  (or user-head-var
+      (progn
+	;;If we use locatives to get tail-updating to update the head var,
+	;; then the head var itself contains the answer.  Otherwise we
+	;; have to cdr it.
+        `(cdr ,head-var))))
+
+
+
+;;;; Maximization Technology
+
+
+#|
+The basic idea of all this minimax randomness here is that we have to
+have constructed all uses of maximize and minimize to a particular
+"destination" before we can decide how to code them.  The goal is to not
+have to have any kinds of flags, by knowing both that (1) the type is
+something which we can provide an initial minimum or maximum value for
+and (2) know that a MAXIMIZE and MINIMIZE are not being combined.
+
+SO, we have a datastructure which we annotate with all sorts of things,
+incrementally updating it as we generate loop body code, and then use
+a wrapper and internal macros to do the coding when the loop has been
+constructed.
+|#
+
+
+(defstruct (loop-minimax
+	     (:constructor make-loop-minimax-internal)
+	     (:copier nil)
+	     (:predicate nil))
+  answer-variable
+  type
+  temp-variable
+  flag-variable
+  operations
+  infinity-data)
+
+
+(defvar *loop-minimax-type-infinities-alist*
+  '((fixnum   		most-positive-fixnum		most-negative-fixnum))
+  )
+
+
+(defun make-loop-minimax (answer-variable type)
+  (let ((infinity-data (cdr (assoc type *loop-minimax-type-infinities-alist* :test #'subtypep))))
+    (make-loop-minimax-internal
+      :answer-variable answer-variable
+      :type type
+      :temp-variable (loop-gentemp 'loop-maxmin-temp-)
+      :flag-variable (and (not infinity-data) (loop-gentemp 'loop-maxmin-flag-))
+      :operations nil
+      :infinity-data infinity-data)))
+
+
+(defun loop-note-minimax-operation (operation minimax)
+  (pushnew (the symbol operation) (loop-minimax-operations minimax))
+  (when (and (cdr (loop-minimax-operations minimax))
+	     (not (loop-minimax-flag-variable minimax)))
+    (setf (loop-minimax-flag-variable minimax) (loop-gentemp 'loop-maxmin-flag-)))
+  operation)
+
+
+(defmacro with-minimax-value (lm &body body)
+  (let ((init (loop-typed-init (loop-minimax-type lm)))
+	(which (car (loop-minimax-operations lm)))
+	(infinity-data (loop-minimax-infinity-data lm))
+	(answer-var (loop-minimax-answer-variable lm))
+	(temp-var (loop-minimax-temp-variable lm))
+	(flag-var (loop-minimax-flag-variable lm))
+	(type (loop-minimax-type lm)))
+    (if flag-var
+	`(let ((,answer-var ,init) (,temp-var ,init) (,flag-var nil))
+	   (declare (type ,type ,answer-var ,temp-var))
+	   ,@body)
+	`(let ((,answer-var ,(if (eq which 'min) (first infinity-data) (second infinity-data)))
+	       (,temp-var ,init))
+	   (declare (type ,type ,answer-var ,temp-var))
+	   ,@body))))
+
+
+(defmacro loop-accumulate-minimax-value (lm operation form)
+  (let* ((answer-var (loop-minimax-answer-variable lm))
+	 (temp-var (loop-minimax-temp-variable lm))
+	 (flag-var (loop-minimax-flag-variable lm))
+	 (test
+	   (hide-variable-reference
+	     t (loop-minimax-answer-variable lm)
+	     `(,(ecase operation
+		  (min '<)
+		  (max '>))
+	       ,temp-var ,answer-var))))
+    `(progn
+       (setq ,temp-var ,form)
+       (when ,(if flag-var `(or (not ,flag-var) ,test) test)
+	 (setq ,@(and flag-var `(,flag-var t))
+	       ,answer-var ,temp-var)))))
+
+
+
+
+;;;; Loop Keyword Tables
+
+
+#|
+LOOP keyword tables are hash tables string keys and a test of EQUAL.
+
+The actual descriptive/dispatch structure used by LOOP is called a "loop
+universe" contains a few tables and parameterizations.  The basic idea is
+that we can provide a non-extensible ANSI-compatible loop environment,
+an extensible ANSI-superset loop environment, and (for such environments
+as CLOE) one which is "sufficiently close" to the old Genera-vintage
+LOOP for use by old user programs without requiring all of the old LOOP
+code to be loaded.
+|#
+
+
+;;;; Token Hackery
+
+
+;;;Compare two "tokens".  The first is the frob out of *LOOP-SOURCE-CODE*,
+;;; the second a symbol to check against.
+(defun loop-tequal (x1 x2)
+  (and (symbolp x1) (string= x1 x2)))
+
+
+(defun loop-tassoc (kwd alist)
+  (and (symbolp kwd) (assoc kwd alist :test #'string=)))
+
+
+(defun loop-tmember (kwd list)
+  (and (symbolp kwd) (member kwd list :test #'string=)))
+
+
+(defun loop-lookup-keyword (loop-token table)
+  (and (symbolp loop-token)
+       (values (gethash (symbol-name loop-token) table))))
+
+
+(defmacro loop-store-table-data (symbol table datum)
+  `(setf (gethash (symbol-name ,symbol) ,table) ,datum))
+
+
+(defstruct (loop-universe
+	     (:print-function print-loop-universe)
+	     (:copier nil)
+	     (:predicate nil))
+  keywords					;hash table, value = (fn-name . extra-data).
+  iteration-keywords				;hash table, value = (fn-name . extra-data).
+  for-keywords					;hash table, value = (fn-name . extra-data).
+  path-keywords					;hash table, value = (fn-name . extra-data).
+  type-symbols					;hash table of type SYMBOLS, test EQ, value = CL type specifier.
+  type-keywords					;hash table of type STRINGS, test EQUAL, value = CL type spec.
+  ansi						;NIL, T, or :EXTENDED.
+  implicit-for-required				;see loop-hack-iteration
+  )
+
+
+(defun print-loop-universe (u stream level)
+  (declare (ignore level))
+  (let ((str (case (loop-universe-ansi u)
+	       ((nil) "Non-ANSI")
+	       ((t) "ANSI")
+	       (:extended "Extended-ANSI")
+	       (t (loop-universe-ansi u)))))
+    (print-unreadable-object (u stream :type t :identity t)
+      (princ str stream))))
+
+
+;;;This is the "current" loop context in use when we are expanding a
+;;;loop.  It gets bound on each invocation of LOOP.
+(defvar *loop-universe*)
+
+
+(defun make-standard-loop-universe (&key keywords for-keywords iteration-keywords path-keywords
+				    type-keywords type-symbols ansi)
+  (check-type ansi (member nil t :extended))
+  (flet ((maketable (entries)
+	   (let* ((size (length entries))
+		  (ht (make-hash-table :size (if (< size 10) 10 size) :test #'equal)))
+	     (dolist (x entries) (setf (gethash (symbol-name (car x)) ht) (cadr x)))
+	     ht)))
+    (make-loop-universe
+      :keywords (maketable keywords)
+      :for-keywords (maketable for-keywords)
+      :iteration-keywords (maketable iteration-keywords)
+      :path-keywords (maketable path-keywords)
+      :ansi ansi
+      :implicit-for-required (not (null ansi))
+      :type-keywords (maketable type-keywords)
+      :type-symbols (let* ((size (length type-symbols))
+			   (ht (make-hash-table :size (if (< size 10) 10 size) :test #'eq)))
+		      (dolist (x type-symbols)
+			(if (atom x) (setf (gethash x ht) x) (setf (gethash (car x) ht) (cadr x))))
+		      ht)))) 
+
+
+
+;;;; Setq Hackery
+
+
+(defvar *loop-destructuring-hooks*
+	nil
+  "If not NIL, this must be a list of two things:
+a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring.")
+
+
+(defun loop-make-psetq (frobs)
+  (and frobs
+       (loop-make-desetq
+	 (list (car frobs)
+	       (if (null (cddr frobs)) (cadr frobs)
+		   `(prog1 ,(cadr frobs)
+			   ,(loop-make-psetq (cddr frobs))))))))
+
+
+(defun loop-make-desetq (var-val-pairs)
+  (if (null var-val-pairs)
+      nil
+      (cons (if *loop-destructuring-hooks*
+		(cadr *loop-destructuring-hooks*)
+		'loop-really-desetq)
+	    var-val-pairs)))
+
+
+(defvar *loop-desetq-temporary*
+	(make-symbol "LOOP-DESETQ-TEMP"))
+
+
+(defmacro loop-really-desetq (&environment env &rest var-val-pairs)
+  (labels ((find-non-null (var)
+	     ;; see if there's any non-null thing here
+	     ;; recurse if the list element is itself a list
+	     (do ((tail var)) ((not (consp tail)) tail)
+	       (when (find-non-null (pop tail)) (return t))))
+	   (loop-desetq-internal (var val &optional temp)
+	     ;; returns a list of actions to be performed
+	     (typecase var
+	       (null
+		 (when (consp val)
+		   ;; don't lose possible side-effects
+		   (if (eq (car val) 'prog1)
+		       ;; these can come from psetq or desetq below.
+		       ;; throw away the value, keep the side-effects.
+		       ;;Special case is for handling an expanded POP.
+		       (mapcan #'(lambda (x)
+				   (and (consp x)
+					(or (not (eq (car x) 'car))
+					    (not (symbolp (cadr x)))
+					    (not (symbolp (setq x (macroexpand x env)))))
+					(cons x nil)))
+			       (cdr val))
+		       `(,val))))
+	       (cons
+		 (let* ((car (car var))
+			(cdr (cdr var))
+			(car-non-null (find-non-null car))
+			(cdr-non-null (find-non-null cdr)))
+		   (when (or car-non-null cdr-non-null)
+		     (if cdr-non-null
+			 (let* ((temp-p temp)
+				(temp (or temp *loop-desetq-temporary*))
+				(body  `(,@(loop-desetq-internal car `(car ,temp))
+                                           (setq ,temp (cdr ,temp))
+                                           ,@(loop-desetq-internal cdr temp temp))))
+			   (if temp-p
+			       `(,@(unless (eq temp val)
+				     `((setq ,temp ,val)))
+				 ,@body)
+			       `((let ((,temp ,val))
+				   ,@body))))
+			 ;; no cdring to do
+			 (loop-desetq-internal car `(car ,val) temp)))))
+	       (otherwise
+		 (unless (eq var val)
+		   `((setq ,var ,val)))))))
+    (do ((actions))
+	((null var-val-pairs)
+	 (if (null (cdr actions)) (car actions) `(progn ,@(nreverse actions))))
+      (setq actions (revappend
+		      (loop-desetq-internal (pop var-val-pairs) (pop var-val-pairs))
+		      actions)))))
+
+
+
+;;;; LOOP-local variables
+
+;;;This is the "current" pointer into the LOOP source code.
+(defvar *loop-source-code*)
+
+
+;;;This is the pointer to the original, for things like NAMED that
+;;;insist on being in a particular position
+(defvar *loop-original-source-code*)
+
+
+;;;This is *loop-source-code* as of the "last" clause.  It is used
+;;;primarily for generating error messages (see loop-error, loop-warn).
+(defvar *loop-source-context*)
+
+
+;;;List of names for the LOOP, supplied by the NAMED clause.
+(defvar *loop-names*)
+
+;;;The macroexpansion environment given to the macro.
+(defvar *loop-macro-environment*)
+
+;;;This holds variable names specified with the USING clause.
+;;; See LOOP-NAMED-VARIABLE.
+(defvar *loop-named-variables*)
+
+;;; LETlist-like list being accumulated for one group of parallel bindings.
+(defvar *loop-variables*)
+
+;;;List of declarations being accumulated in parallel with
+;;;*loop-variables*.
+(defvar *loop-declarations*)
+
+;;;Used by LOOP for destructuring binding, if it is doing that itself.
+;;; See loop-make-variable.
+(defvar *loop-desetq-crocks*)
+
+;;; List of wrapping forms, innermost first, which go immediately inside
+;;; the current set of parallel bindings being accumulated in
+;;; *loop-variables*.  The wrappers are appended onto a body.  E.g.,
+;;; this list could conceivably has as its value ((with-open-file (g0001
+;;; g0002 ...))), with g0002 being one of the bindings in
+;;; *loop-variables* (this is why the wrappers go inside of the variable
+;;; bindings).
+(defvar *loop-wrappers*)
+
+;;;This accumulates lists of previous values of *loop-variables* and the
+;;;other lists  above, for each new nesting of bindings.  See
+;;;loop-bind-block.
+(defvar *loop-bind-stack*)
+
+;;;This is a LOOP-global variable for the (obsolete) NODECLARE clause
+;;;which inhibits  LOOP from actually outputting a type declaration for
+;;;an iteration (or any) variable.
+(defvar *loop-nodeclare*)
+
+;;;This is simply a list of LOOP iteration variables, used for checking
+;;;for duplications.
+(defvar *loop-iteration-variables*)
+
+
+;;;List of prologue forms of the loop, accumulated in reverse order.
+(defvar *loop-prologue*)
+
+(defvar *loop-before-loop*)
+(defvar *loop-body*)
+(defvar *loop-after-body*)
+
+;;;This is T if we have emitted any body code, so that iteration driving
+;;;clauses can be disallowed.   This is not strictly the same as
+;;;checking *loop-body*, because we permit some clauses  such as RETURN
+;;;to not be considered "real" body (so as to permit the user to "code"
+;;;an  abnormal return value "in loop").
+(defvar *loop-emitted-body*)
+
+
+;;;List of epilogue forms (supplied by FINALLY generally), accumulated
+;;; in reverse order.
+(defvar *loop-epilogue*)
+
+;;;List of epilogue forms which are supplied after the above "user"
+;;;epilogue.  "normal" termination return values are provide by putting
+;;;the return form in here.  Normally this is done using
+;;;loop-emit-final-value, q.v.
+(defvar *loop-after-epilogue*)
+
+;;;The "culprit" responsible for supplying a final value from the loop.
+;;;This  is so loop-emit-final-value can moan about multiple return
+;;;values being supplied.
+(defvar *loop-final-value-culprit*)
+
+;;;If not NIL, we are in some branch of a conditional.  Some clauses may
+;;;be disallowed.
+(defvar *loop-inside-conditional*)
+
+;;;If not NIL, this is a temporary bound around the loop for holding the
+;;;temporary  value for "it" in things like "when (f) collect it".  It
+;;;may be used as a supertemporary by some other things.
+(defvar *loop-when-it-variable*)
+
+;;;Sometimes we decide we need to fold together parts of the loop, but
+;;;some part of the generated iteration  code is different for the first
+;;;and remaining iterations.  This variable will be the temporary which 
+;;;is the flag used in the loop to tell whether we are in the first or
+;;;remaining iterations.
+(defvar *loop-never-stepped-variable*)
+
+;;;List of all the value-accumulation descriptor structures in the loop.
+;;; See loop-get-collection-info.
+(defvar *loop-collection-cruft*)		; for multiple COLLECTs (etc)
+
+
+
+;;;; Code Analysis Stuff
+
+
+(defun loop-constant-fold-if-possible (form &optional expected-type)
+  (let ((new-form form) (constantp nil) (constant-value nil))
+    (when (setq constantp (constantp new-form))
+      (setq constant-value (eval new-form)))
+    (when (and constantp expected-type)
+      (unless (typep constant-value expected-type)
+	(loop-warn "The form ~S evaluated to ~S, which was not of the anticipated type ~S."
+          form constant-value expected-type)
+	(setq constantp nil constant-value nil)))
+    (values new-form constantp constant-value)))
+
+
+(defun loop-constantp (form)
+  (constantp form))
+
+
+
+;;;; LOOP Iteration Optimization
+
+(defvar *loop-duplicate-code*
+	nil)
+
+
+(defvar *loop-iteration-flag-variable*
+	(make-symbol "LOOP-NOT-FIRST-TIME"))
+
+
+(defun loop-code-duplication-threshold (env)
+  (multiple-value-bind (speed space) (loop-optimization-quantities env)
+    (+ 40 (* (- speed space) 10))))
+
+
+(defmacro loop-body (&environment env
+		     prologue
+		     before-loop
+		     main-body
+		     after-loop
+		     epilogue
+		     &aux rbefore rafter flagvar)
+  (unless (= (length before-loop) (length after-loop))
+    (loop-error "LOOP-BODY called with non-synched before- and after-loop lists."))
+  ;;All our work is done from these copies, working backwards from the end:
+  (setq rbefore (reverse before-loop) rafter (reverse after-loop))
+  (labels ((psimp (l)
+	     (let ((ans nil))
+	       (dolist (x l)
+		 (when x
+		   (push x ans)
+		   (when (and (consp x) (member (car x) '(go return return-from)))
+		     (return nil))))
+	       (nreverse ans)))
+	   (pify (l) (if (null (cdr l)) (car l) `(progn ,@l)))
+	   (makebody ()
+	     (let ((form `(tagbody
+			    ,@(psimp (append prologue (nreverse rbefore)))
+			 next-loop
+			    ,@(psimp (append main-body (nreconc rafter `((go next-loop)))))
+			 end-loop
+			    ,@(psimp epilogue))))
+	       (if flagvar `(let ((,flagvar nil)) ,form) form))))
+    (when (or *loop-duplicate-code* (not rbefore))
+      (return-from loop-body (makebody)))
+    ;; This outer loop iterates once for each not-first-time flag test generated
+    ;; plus once more for the forms that don't need a flag test
+    (do ((threshold (loop-code-duplication-threshold env))) (nil)
+      (declare (fixnum threshold))
+      ;; Go backwards from the ends of before-loop and after-loop merging all the equivalent
+      ;; forms into the body.
+      (do () ((or (null rbefore) (not (equal (car rbefore) (car rafter)))))
+	(push (pop rbefore) main-body)
+	(pop rafter))
+      (unless rbefore (return (makebody)))
+      ;; The first forms in rbefore & rafter (which are the chronologically
+      ;; last forms in the list) differ, therefore they cannot be moved
+      ;; into the main body.  If everything that chronologically precedes
+      ;; them either differs or is equal but is okay to duplicate, we can
+      ;; just put all of rbefore in the prologue and all of rafter after
+      ;; the body.  Otherwise, there is something that is not okay to
+      ;; duplicate, so it and everything chronologically after it in
+      ;; rbefore and rafter must go into the body, with a flag test to
+      ;; distinguish the first time around the loop from later times.
+      ;; What chronologically precedes the non-duplicatable form will
+      ;; be handled the next time around the outer loop.
+      (do ((bb rbefore (cdr bb)) (aa rafter (cdr aa)) (lastdiff nil) (count 0) (inc nil))
+	  ((null bb) (return-from loop-body (makebody)))	;Did it.
+	(cond ((not (equal (car bb) (car aa))) (setq lastdiff bb count 0))
+	      ((or (not (setq inc (estimate-code-size (car bb) env)))
+		   (> (incf count inc) threshold))
+	       ;; Ok, we have found a non-duplicatable piece of code.  Everything
+	       ;; chronologically after it must be in the central body.
+	       ;; Everything chronologically at and after lastdiff goes into the
+	       ;; central body under a flag test.
+	       (let ((then nil) (else nil))
+		 (do () (nil)
+		   (push (pop rbefore) else)
+		   (push (pop rafter) then)
+		   (when (eq rbefore (cdr lastdiff)) (return)))
+		 (unless flagvar
+		   (push `(setq ,(setq flagvar *loop-iteration-flag-variable*) t) else))
+		 (push `(if ,flagvar ,(pify (psimp then)) ,(pify (psimp else)))
+		       main-body))
+	       ;; Everything chronologically before lastdiff until the non-duplicatable form (car bb) 
+	       ;; is the same in rbefore and rafter so just copy it into the body
+	       (do () (nil)
+		 (pop rafter)
+		 (push (pop rbefore) main-body)
+		 (when (eq rbefore (cdr bb)) (return)))
+	       (return)))))))
+
+
+
+
+(defun duplicatable-code-p (expr env)
+  (if (null expr) 0
+      (let ((ans (estimate-code-size expr env)))
+	(declare (fixnum ans))
+	;;@@@@ Use (DECLARATION-INFORMATION 'OPTIMIZE ENV) here to get an alist of
+	;; optimize quantities back to help quantify how much code we are willing to
+	;; duplicate.
+	ans)))
+
+
+(defvar *special-code-sizes*
+	'((return 0) (progn 0)
+	  (null 1) (not 1) (eq 1) (car 1) (cdr 1)
+	  (when 1) (unless 1) (if 1)
+	  (caar 2) (cadr 2) (cdar 2) (cddr 2)
+	  (caaar 3) (caadr 3) (cadar 3) (caddr 3) (cdaar 3) (cdadr 3) (cddar 3) (cdddr 3)
+	  (caaaar 4) (caaadr 4) (caadar 4) (caaddr 4)
+	  (cadaar 4) (cadadr 4) (caddar 4) (cadddr 4)
+	  (cdaaar 4) (cdaadr 4) (cdadar 4) (cdaddr 4)
+	  (cddaar 4) (cddadr 4) (cdddar 4) (cddddr 4)))
+
+
+(defvar *estimate-code-size-punt*
+	'(block
+	   do do* dolist
+	   flet
+	   labels lambda let let* locally
+	   macrolet multiple-value-bind
+	   prog prog*
+	   symbol-macrolet
+	   tagbody
+	   unwind-protect
+	   with-open-file))
+
+
+(defun destructuring-size (x)
+  (do ((x x (cdr x)) (n 0 (+ (destructuring-size (car x)) n)))
+      ((atom x) (+ n (if (null x) 0 1)))))
+
+
+(defun estimate-code-size (x env)
+  (catch 'estimate-code-size
+    (estimate-code-size-1 x env)))
+
+
+(defun estimate-code-size-1 (x env)
+  (flet ((list-size (l)
+	   (let ((n 0))
+	     (declare (fixnum n))
+	     (dolist (x l n) (incf n (estimate-code-size-1 x env))))))
+    ;;@@@@ ???? (declare (function list-size (list) fixnum))
+    (cond ((constantp x) 1)
+	  ((symbolp x) (multiple-value-bind (new-form expanded-p) (macroexpand-1 x env)
+			 (if expanded-p (estimate-code-size-1 new-form env) 1)))
+	  ((atom x) 1)				;??? self-evaluating???
+	  ((symbolp (car x))
+	   (let ((fn (car x)) (tem nil) (n 0))
+	     (declare (symbol fn) (fixnum n))
+	     (macrolet ((f (overhead &optional (args nil args-p))
+			  `(the fixnum (+ (the fixnum ,overhead)
+					  (the fixnum (list-size ,(if args-p args '(cdr x))))))))
+	       (cond ((setq tem (get fn 'estimate-code-size))
+		      (typecase tem
+			(fixnum (f tem))
+			(t (funcall tem x env))))
+		     ((setq tem (assoc fn *special-code-sizes*)) (f (second tem)))
+                     ((eq fn 'cond)
+		      (dolist (clause (cdr x) n) (incf n (list-size clause)) (incf n)))
+		     ((eq fn 'desetq)
+		      (do ((l (cdr x) (cdr l))) ((null l) n)
+			(setq n (+ n (destructuring-size (car l)) (estimate-code-size-1 (cadr l) env)))))
+		     ((member fn '(setq psetq))
+		      (do ((l (cdr x) (cdr l))) ((null l) n)
+			(setq n (+ n (estimate-code-size-1 (cadr l) env) 1))))
+		     ((eq fn 'go) 1)
+		     ((eq fn 'function)
+		      ;;This skirts the issue of implementationally-defined lambda macros
+		      ;; by recognizing CL function names and nothing else.
+		      (if (or (symbolp (cadr x))
+                              (ccl::setf-function-name-p  (cadr x)))
+			  1
+			  (throw 'duplicatable-code-p nil)))
+		     ((eq fn 'multiple-value-setq) (f (length (second x)) (cddr x)))
+		     ((eq fn 'return-from) (1+ (estimate-code-size-1 (third x) env)))
+		     ((or (special-operator-p fn) (member fn *estimate-code-size-punt*))
+		      (throw 'estimate-code-size nil))
+		     (t (multiple-value-bind (new-form expanded-p) (macroexpand-1 x env)
+			  (if expanded-p
+			      (estimate-code-size-1 new-form env)
+			      (f 3))))))))
+	  (t (throw 'estimate-code-size nil)))))
+
+
+
+;;;; Loop Errors
+
+
+(defun loop-context ()
+  (do ((l *loop-source-context* (cdr l)) (new nil (cons (car l) new)))
+      ((eq l (cdr *loop-source-code*)) (nreverse new))))
+
+
+(defun loop-error (format-string &rest format-args)
+  (ccl::signal-program-error "~?~%Current LOOP context:~{ ~S~}."
+                             format-string format-args (loop-context)))
+
+
+(defun loop-warn (format-string &rest format-args)
+  (warn "~?~%Current LOOP context:~{ ~S~}." format-string format-args (loop-context)))
+
+(pushnew '(loop-error . 0) ccl::*format-arg-functions* :test #'equal)
+(pushnew '(loop-warn . 0) ccl::*format-arg-functions* :test #'equal)
+
+
+(defun loop-check-data-type (specified-type required-type
+			     &optional (default-type required-type))
+  (if (null specified-type)
+      default-type
+      (multiple-value-bind (a b) (subtypep specified-type required-type)
+	(cond ((not b)
+	       (loop-warn "LOOP couldn't verify that ~S is a subtype of the required type ~S."
+			  specified-type required-type))
+	      ((not a)
+	       (loop-error "Specified data type ~S is not a subtype of ~S."
+			   specified-type required-type)))
+	specified-type)))
+
+
+
+;;;INTERFACE: Traditional, ANSI, Lucid.
+(defmacro loop-finish ()
+  "Cause the iteration to terminate \"normally\", the same as implicit
+termination by an iteration driving clause, or by use of WHILE or
+UNTIL -- the epilogue code (if any) will be run, and any implicitly
+collected result will be returned as the value of the LOOP."
+  '(go end-loop))
+
+
+
+
+(defun subst-gensyms-for-nil (tree)
+  (declare (special *ignores*))
+  (cond
+    ((null tree) (car (push (loop-gentemp) *ignores*)))
+    ((atom tree) tree)
+    (t (cons (subst-gensyms-for-nil (car tree))
+	     (subst-gensyms-for-nil (cdr tree))))))
+ 
+(defun loop-build-destructuring-bindings (crocks forms)
+  (if crocks
+      (let ((*ignores* ()))
+	(declare (special *ignores*))
+	`((destructuring-bind ,(subst-gensyms-for-nil (car crocks))
+	      ,(cadr crocks)
+	    (declare (ignore ,@*ignores*))
+	    ,@(loop-build-destructuring-bindings (cddr crocks) forms))))
+      forms))
+
+(defun loop-translate (*loop-source-code* *loop-macro-environment* *loop-universe*)
+  (let ((*loop-original-source-code* *loop-source-code*)
+	(*loop-source-context* nil)
+	(*loop-iteration-variables* nil)
+	(*loop-variables* nil)
+	(*loop-nodeclare* nil)
+	(*loop-named-variables* nil)
+	(*loop-declarations* nil)
+	(*loop-desetq-crocks* nil)
+	(*loop-bind-stack* nil)
+	(*loop-prologue* nil)
+	(*loop-wrappers* nil)
+	(*loop-before-loop* nil)
+	(*loop-body* nil)
+	(*loop-emitted-body* nil)
+	(*loop-after-body* nil)
+	(*loop-epilogue* nil)
+	(*loop-after-epilogue* nil)
+	(*loop-final-value-culprit* nil)
+	(*loop-inside-conditional* nil)
+	(*loop-when-it-variable* nil)
+	(*loop-never-stepped-variable* nil)
+	(*loop-names* nil)
+	(*loop-collection-cruft* nil))
+    (loop-iteration-driver)
+    (loop-bind-block)
+    (let ((answer `(loop-body
+		     ,(nreverse *loop-prologue*)
+		     ,(nreverse *loop-before-loop*)
+		     ,(nreverse *loop-body*)
+		     ,(nreverse *loop-after-body*)
+		     ,(nreconc *loop-epilogue* (nreverse *loop-after-epilogue*)))))
+      (dolist (entry *loop-bind-stack*)
+	(let ((vars (first entry))
+	      (dcls (second entry))
+	      (crocks (third entry))
+	      (wrappers (fourth entry)))
+	  (dolist (w wrappers)
+	    (setq answer (append w (list answer))))
+	  (when (or vars dcls crocks)
+	    (let ((forms (list answer)))
+	      ;;(when crocks (push crocks forms))
+	      (when dcls (push `(declare ,@dcls) forms))
+	      (setq answer `(,(cond ((not vars) 'locally)
+				    (*loop-destructuring-hooks* (first *loop-destructuring-hooks*))
+				    (t 'let))
+			     ,vars
+			     ,@(loop-build-destructuring-bindings crocks forms)))))))
+      (if *loop-names*
+	  (do () ((null (car *loop-names*)) answer)
+	    (setq answer `(block ,(pop *loop-names*) ,answer)))
+	  `(block nil ,answer)))))
+
+
+(defun loop-iteration-driver ()
+  (do () ((null *loop-source-code*))
+    (let ((keyword (car *loop-source-code*)) (tem nil))
+      (cond ((not (symbolp keyword))
+	     (loop-error "~S found where LOOP keyword expected." keyword))
+	    (t (setq *loop-source-context* *loop-source-code*)
+	       (loop-pop-source)
+	       (cond ((setq tem (loop-lookup-keyword keyword (loop-universe-keywords *loop-universe*)))
+		      ;;It's a "miscellaneous" toplevel LOOP keyword (do, collect, named, etc.)
+		      (apply (symbol-function (first tem)) (rest tem)))
+		     ((setq tem (loop-lookup-keyword keyword (loop-universe-iteration-keywords *loop-universe*)))
+		      (loop-hack-iteration tem))
+		     ((loop-tmember keyword '(and else))
+		      ;; Alternative is to ignore it, ie let it go around to the next keyword...
+		      (loop-error "Secondary clause misplaced at top level in LOOP macro: ~S ~S ~S ..."
+				  keyword (car *loop-source-code*) (cadr *loop-source-code*)))
+		     (t (loop-error "~S is an unknown keyword in LOOP macro." keyword))))))))
+
+
+
+
+(defun loop-pop-source ()
+  (if *loop-source-code*
+      (pop *loop-source-code*)
+      (loop-error "LOOP source code ran out when another token was expected.")))
+
+
+(defun loop-get-compound-form ()
+  (let ((form (loop-get-form)))
+    (unless (consp form)
+      (loop-error "Compound form expected, but found ~A." form))
+    form))
+
+(defun loop-get-progn ()
+  (do ((forms (list (loop-get-compound-form))
+              (cons (loop-get-compound-form) forms))
+       (nextform (car *loop-source-code*)
+                 (car *loop-source-code*)))
+      ((atom nextform)
+       (if (null (cdr forms)) (car forms) (cons 'progn (nreverse forms))))))
+
+
+(defun loop-get-form ()
+  (if *loop-source-code*
+      (loop-pop-source)
+      (loop-error "LOOP code ran out where a form was expected.")))
+
+
+(defun loop-construct-return (form)
+  `(return-from ,(car *loop-names*) ,form))
+
+
+(defun loop-pseudo-body (form)
+  (cond ((or *loop-emitted-body* *loop-inside-conditional*) (push form *loop-body*))
+	(t (push form *loop-before-loop*) (push form *loop-after-body*))))
+
+(defun loop-emit-body (form)
+  (setq *loop-emitted-body* t)
+  (loop-pseudo-body form))
+
+(defun loop-emit-final-value (&optional (form nil form-supplied-p))
+  (when form-supplied-p
+    (push (loop-construct-return form) *loop-after-epilogue*))
+  (when *loop-final-value-culprit*
+    (loop-warn "LOOP clause is providing a value for the iteration,~@
+	        however one was already established by a ~S clause."
+	       *loop-final-value-culprit*))
+  (setq *loop-final-value-culprit* (car *loop-source-context*)))
+
+
+(defun loop-disallow-conditional (&optional kwd)
+  (when *loop-inside-conditional*
+    (loop-error "~:[This LOOP~;The LOOP ~:*~S~] clause is not permitted inside a conditional." kwd)))
+
+(defun loop-disallow-anonymous-collectors ()
+  (when (find-if-not 'loop-collector-name *loop-collection-cruft*)
+    (loop-error "This LOOP clause is not permitted with anonymous collectors.")))
+
+(defun loop-disallow-aggregate-booleans ()
+  (when (loop-tmember *loop-final-value-culprit* '(always never thereis))
+    (loop-error "This anonymous collection LOOP clause is not permitted with aggregate booleans.")))
+
+
+
+
+;;;; Loop Types
+
+
+(defun loop-typed-init (data-type)
+  (when data-type
+    (let ((val (if (subtypep data-type 'number)
+                 (if (or (subtypep data-type 'float) (subtypep data-type '(complex float)))
+                   (coerce 0 data-type)
+                   0)
+                 (if (subtypep data-type 'character)
+                   #\Null
+                   nil))))
+      (and val (typep val data-type) val))))
+
+
+(defun loop-optional-type (&optional variable)
+  ;;No variable specified implies that no destructuring is permissible.
+  (and *loop-source-code*			;Don't get confused by NILs...
+       (let ((z (car *loop-source-code*)))
+	 (cond ((loop-tequal z 'of-type)
+		;;This is the syntactically unambigous form in that the form of the
+		;; type specifier does not matter.  Also, it is assumed that the
+		;; type specifier is unambiguously, and without need of translation,
+		;; a common lisp type specifier or pattern (matching the variable) thereof.
+		(loop-pop-source)
+		(loop-pop-source))
+		      
+	       ((symbolp z)
+		;;This is the (sort of) "old" syntax, even though we didn't used to support all of
+		;; these type symbols.
+		(let ((type-spec (or (gethash z (loop-universe-type-symbols *loop-universe*))
+				     (gethash (symbol-name z) (loop-universe-type-keywords *loop-universe*)))))
+		  (when type-spec
+		    (loop-pop-source)
+		    type-spec)))
+	       (t 
+		;;This is our sort-of old syntax.  But this is only valid for when we are destructuring,
+		;; so we will be compulsive (should we really be?) and require that we in fact be
+		;; doing variable destructuring here.  We must translate the old keyword pattern typespec
+		;; into a fully-specified pattern of real type specifiers here.
+		(if (consp variable)
+		    (unless (consp z)
+		     (loop-error
+			"~S found where a LOOP keyword, LOOP type keyword, or LOOP type pattern expected."
+			z))
+		    (loop-error "~S found where a LOOP keyword or LOOP type keyword expected." z))
+		(loop-pop-source)
+		(labels ((translate (k v)
+			   (cond ((null k) nil)
+				 ((atom k)
+				  (replicate
+				    (or (gethash k (loop-universe-type-symbols *loop-universe*))
+					(gethash (symbol-name k) (loop-universe-type-keywords *loop-universe*))
+					(loop-error
+					  "Destructuring type pattern ~S contains unrecognized type keyword ~S."
+					  z k))
+				    v))
+				 ((atom v)
+				  (loop-error
+				    "Destructuring type pattern ~S doesn't match variable pattern ~S."
+				    z variable))
+				 (t (cons (translate (car k) (car v)) (translate (cdr k) (cdr v))))))
+			 (replicate (typ v)
+			   (if (atom v) typ (cons (replicate typ (car v)) (replicate typ (cdr v))))))
+		  (translate z variable)))))))
+
+
+
+
+;;;; Loop Variables
+
+
+(defun loop-bind-block ()
+  (when (or *loop-variables* *loop-declarations* *loop-wrappers*)
+    (push (list (nreverse *loop-variables*) *loop-declarations* *loop-desetq-crocks* *loop-wrappers*)
+	  *loop-bind-stack*)
+    (setq *loop-variables* nil
+	  *loop-declarations* nil
+	  *loop-desetq-crocks* nil
+	  *loop-wrappers* nil)))
+
+(defun loop-variable-p (name)
+  (do ((entry *loop-bind-stack* (cdr entry))) (nil)
+    (cond ((null entry)
+	   (return nil))
+	  ((assoc name (caar entry) :test #'eq)
+	   (return t)))))
+
+(defun loop-make-variable (name initialization dtype &optional iteration-variable-p)
+  (cond ((null name)
+	 (cond ((not (null initialization))
+		(push (list (setq name (loop-gentemp 'loop-ignore-))
+			    initialization)
+		      *loop-variables*)
+		(push `(ignore ,name) *loop-declarations*))))
+	((atom name)
+	 (cond (iteration-variable-p
+		(if (member name *loop-iteration-variables*)
+		    (loop-error "Duplicated LOOP iteration variable ~S." name)
+		    (push name *loop-iteration-variables*)))
+	       ((assoc name *loop-variables*)
+		(loop-error "Duplicated variable ~S in LOOP parallel binding." name)))
+	 (unless (symbolp name)
+	   (loop-error "Bad variable ~S somewhere in LOOP." name))
+         (unless initialization (setq initialization (loop-typed-init dtype)))
+         (when (and dtype
+                    (null initialization)
+                    (not (typep nil dtype)))
+           (if (eq dtype 'complex)
+             (setq initialization 0 dtype 'number)
+             (when iteration-variable-p
+               (setq dtype `(or null ,dtype)))))
+	 (loop-declare-variable name dtype)
+	 ;; We use ASSOC on this list to check for duplications (above),
+	 ;; so don't optimize out this list:
+	 (push (list name initialization) *loop-variables*))
+	(initialization
+	 (cond (*loop-destructuring-hooks*
+		(loop-declare-variable name dtype)
+		(push (list name initialization) *loop-variables*))
+	       (t (let ((newvar (loop-gentemp 'loop-destructure-)))
+		    (loop-declare-variable name dtype)
+		    (push (list newvar initialization) *loop-variables*)
+		    ;; *LOOP-DESETQ-CROCKS* gathered in reverse order.
+		    (setq *loop-desetq-crocks*
+		      (list* name newvar *loop-desetq-crocks*))))))
+	(t (let ((tcar nil) (tcdr nil))
+	     (if (atom dtype) (setq tcar (setq tcdr dtype))
+		 (setq tcar (car dtype) tcdr (cdr dtype)))
+	     (loop-make-variable (car name) nil tcar iteration-variable-p)
+	     (loop-make-variable (cdr name) nil tcdr iteration-variable-p))))
+  name)
+
+
+(defun loop-make-iteration-variable (name initialization dtype)
+  (loop-make-variable name initialization dtype t))
+
+
+(defun loop-declare-variable (name dtype)
+  (cond ((or (null name) (null dtype) (eq dtype t)) nil)
+	((symbolp name)
+	 (unless (or (eq dtype t) (member (the symbol name) *loop-nodeclare*))
+	   (push `(type ,dtype ,name) *loop-declarations*)))
+	((consp name)
+	 (cond ((consp dtype)
+		(loop-declare-variable (car name) (car dtype))
+		(loop-declare-variable (cdr name) (cdr dtype)))
+	       (t (loop-declare-variable (car name) dtype)
+		  (loop-declare-variable (cdr name) dtype))))
+	(t (loop-error "Invalid LOOP variable passed in: ~S." name))))
+
+
+(defun loop-maybe-bind-form (form data-type)
+  (if (loop-constantp form)
+      form
+      (loop-make-variable (loop-gentemp 'loop-bind-) form data-type)))
+
+
+
+
+(defun loop-do-if (for negatep)
+  (let ((form (loop-get-form))
+	(*loop-inside-conditional* t)
+	(it-p nil)
+	(first-clause-p t))
+    (flet ((get-clause (for)
+	     (do ((body nil)) (nil)
+	       (let ((key (car *loop-source-code*)) (*loop-body* nil) data)
+		 (cond ((not (symbolp key))
+			(loop-error
+			  "~S found where keyword expected getting LOOP clause after ~S."
+			  key for))
+		       (t (setq *loop-source-context* *loop-source-code*)
+			  (loop-pop-source)
+			  (when (and (loop-tequal (car *loop-source-code*) 'it)
+				     first-clause-p)
+			    (setq *loop-source-code*
+				  (cons (or it-p (setq it-p (loop-when-it-variable)))
+					(cdr *loop-source-code*))))
+			  (cond ((or (not (setq data (loop-lookup-keyword
+						       key (loop-universe-keywords *loop-universe*))))
+				     (progn (apply (symbol-function (car data)) (cdr data))
+					    (null *loop-body*)))
+				 (loop-error
+				   "~S does not introduce a LOOP clause that can follow ~S."
+				   key for))
+				(t (setq body (nreconc *loop-body* body)))))))
+	       (setq first-clause-p nil)
+	       (if (loop-tequal (car *loop-source-code*) :and)
+		   (loop-pop-source)
+		   (return (if (cdr body) `(progn ,@(nreverse body)) (car body)))))))
+      (let ((then (get-clause for))
+	    (else (when (loop-tequal (car *loop-source-code*) :else)
+		    (loop-pop-source)
+		    (list (get-clause :else)))))
+	(when (loop-tequal (car *loop-source-code*) :end)
+	  (loop-pop-source))
+	(when it-p (setq form `(setq ,it-p ,form)))
+	(loop-pseudo-body
+	  `(if ,(if negatep `(not ,form) form)
+	       ,then
+	       ,@else))))))
+
+
+(defun loop-do-initially ()
+  (loop-disallow-conditional :initially)
+  (push (loop-get-progn) *loop-prologue*))
+
+(defun loop-do-finally ()
+  (loop-disallow-conditional :finally)
+  (push (loop-get-progn) *loop-epilogue*))
+
+(defun loop-do-do ()
+  (loop-emit-body (loop-get-progn)))
+
+(defun loop-do-named ()
+  (let ((name (loop-pop-source)))
+    (unless (symbolp name)
+      (loop-error "~S is an invalid name for your LOOP." name))
+    (when (or *loop-before-loop* *loop-body* *loop-after-epilogue* *loop-inside-conditional*)
+      (loop-error "The NAMED ~S clause occurs too late." name))
+    (when *loop-names*
+      (loop-error "You may only use one NAMED clause in your loop: NAMED ~S ... NAMED ~S."
+		  (car *loop-names*) name))
+    (setq *loop-names* (list name nil))))
+
+(defun loop-do-return ()
+  (loop-emit-body (loop-construct-return (loop-get-form))))
+
+
+
+;;;; Value Accumulation: List
+
+
+(defstruct (loop-collector
+	     (:copier nil)
+	     (:predicate nil))
+  name
+  class
+  (history nil)
+  (tempvars nil)
+  dtype
+  (data nil))						;collector-specific data
+
+
+(defun loop-get-collection-info (collector class default-type)
+  (let ((form (loop-get-form))
+	(dtype (and (not (loop-universe-ansi *loop-universe*)) (loop-optional-type)))
+	(name (when (loop-tequal (car *loop-source-code*) 'into)
+		(loop-pop-source)
+		(loop-pop-source))))
+    (when (not (symbolp name))
+      (loop-error "Value accumulation recipient name, ~S, is not a symbol." name))
+    (unless name
+      (loop-disallow-aggregate-booleans))
+    (unless dtype
+      (setq dtype (or (loop-optional-type) default-type)))
+    (let ((cruft (find (the symbol name) *loop-collection-cruft*
+		       :key #'loop-collector-name)))
+      (cond ((not cruft)
+	     (when (and name (loop-variable-p name))
+	       (loop-error "Variable ~S cannot be used in INTO clause" name))
+	     (push (setq cruft (make-loop-collector
+				 :name name :class class
+				 :history (list collector) :dtype dtype))
+		   *loop-collection-cruft*))
+	    (t (unless (eq (loop-collector-class cruft) class)
+		 (loop-error
+		   "Incompatible kinds of LOOP value accumulation specified for collecting~@
+		    ~:[as the value of the LOOP~;~:*INTO ~S~]: ~S and ~S."
+		   name (car (loop-collector-history cruft)) collector))
+	       (unless (equal dtype (loop-collector-dtype cruft))
+		 (loop-warn
+		   "Unequal datatypes specified in different LOOP value accumulations~@
+		   into ~S: ~S and ~S."
+		   name dtype (loop-collector-dtype cruft))
+		 (when (eq (loop-collector-dtype cruft) t)
+		   (setf (loop-collector-dtype cruft) dtype)))
+	       (push collector (loop-collector-history cruft))))
+      (values cruft form))))
+
+
+(defun loop-list-collection (specifically)	;NCONC, LIST, or APPEND
+  (multiple-value-bind (lc form) (loop-get-collection-info specifically 'list 'list)
+    (let ((tempvars (loop-collector-tempvars lc)))
+      (unless tempvars
+	(setf (loop-collector-tempvars lc)
+	      (setq tempvars (list* (loop-gentemp 'loop-list-head-)
+				    (loop-gentemp 'loop-list-tail-)
+				    (and (loop-collector-name lc)
+					 (list (loop-collector-name lc))))))
+	(push `(with-loop-list-collection-head ,tempvars) *loop-wrappers*)
+	(unless (loop-collector-name lc)
+	  (loop-emit-final-value `(loop-collect-answer ,(car tempvars) ,@(cddr tempvars)))))
+      (ecase specifically
+	(list (setq form `(list ,form)))
+	(nconc nil)
+	(append (unless (and (consp form) (eq (car form) 'list))
+		  (setq form `(loop-copylist* ,form)))))
+      (loop-emit-body `(loop-collect-rplacd ,tempvars ,form)))))
+
+
+
+;;;; Value Accumulation: max, min, sum, count.
+
+
+
+(defun loop-sum-collection (specifically required-type default-type)	;SUM, COUNT
+  (multiple-value-bind (lc form)
+      (loop-get-collection-info specifically 'sum default-type)
+    (loop-check-data-type (loop-collector-dtype lc) required-type)
+    (let ((tempvars (loop-collector-tempvars lc)))
+      (unless tempvars
+	(setf (loop-collector-tempvars lc)
+	      (setq tempvars (list (loop-make-variable
+				     (or (loop-collector-name lc)
+					 (loop-gentemp 'loop-sum-))
+				     nil (loop-collector-dtype lc)))))
+	(unless (loop-collector-name lc)
+	  (loop-emit-final-value (car (loop-collector-tempvars lc)))))
+      (loop-emit-body
+	(if (eq specifically 'count)
+	    `(when ,form
+	       (setq ,(car tempvars)
+		     ,(hide-variable-reference t (car tempvars) `(1+ ,(car tempvars)))))
+	    `(setq ,(car tempvars)
+		   (+ ,(hide-variable-reference t (car tempvars) (car tempvars))
+		      ,form)))))))
+
+
+
+(defun loop-maxmin-collection (specifically)
+  (multiple-value-bind (lc form)
+      (loop-get-collection-info specifically 'maxmin *loop-real-data-type*)
+    (loop-check-data-type (loop-collector-dtype lc) *loop-real-data-type*)
+    (let ((data (loop-collector-data lc)))
+      (unless data
+	(setf (loop-collector-data lc)
+	      (setq data (make-loop-minimax
+			   (or (loop-collector-name lc) (loop-gentemp 'loop-maxmin-))
+			   (loop-collector-dtype lc))))
+	(unless (loop-collector-name lc)
+	  (loop-emit-final-value (loop-minimax-answer-variable data))))
+      (loop-note-minimax-operation specifically data)
+      (push `(with-minimax-value ,data) *loop-wrappers*)
+      (loop-emit-body `(loop-accumulate-minimax-value ,data ,specifically ,form))
+      )))
+
+
+
+;;;; Value Accumulation:  Aggregate Booleans
+
+;;;ALWAYS and NEVER.
+;;; Under ANSI these are not permitted to appear under conditionalization.
+(defun loop-do-always (restrictive negate)
+  (let ((form (loop-get-form)))
+    (when restrictive (loop-disallow-conditional))
+    (loop-disallow-anonymous-collectors)
+    (loop-emit-body `(,(if negate 'when 'unless) ,form
+		      ,(loop-construct-return nil)))
+    (loop-emit-final-value t)))
+
+
+
+;;;THERIS.
+;;; Under ANSI this is not permitted to appear under conditionalization.
+(defun loop-do-thereis (restrictive)
+  (when restrictive (loop-disallow-conditional))
+  (loop-disallow-anonymous-collectors)
+  (loop-emit-final-value)
+  (loop-emit-body `(when (setq ,(loop-when-it-variable) ,(loop-get-form))
+		     ,(loop-construct-return *loop-when-it-variable*))))
+
+
+
+(defun loop-do-while (negate kwd &aux (form (loop-get-form)))
+  (loop-disallow-conditional kwd)
+  (loop-pseudo-body `(,(if negate 'when 'unless) ,form (go end-loop))))
+
+
+(defun loop-do-with ()
+  (loop-disallow-conditional :with)
+  (do ((var) (val) (dtype)) (nil)
+    (setq var (loop-pop-source)
+	  dtype (loop-optional-type var)
+	  val (cond ((loop-tequal (car *loop-source-code*) :=)
+		     (loop-pop-source)
+		     (loop-get-form))
+		    (t nil)))
+    (when (and var (loop-variable-p var))
+      (loop-error "Variable ~S has already been used" var))
+    (loop-make-variable var val dtype)
+    (if (loop-tequal (car *loop-source-code*) :and)
+	(loop-pop-source)
+	(return (loop-bind-block)))))
+
+
+
+;;;; The iteration driver
+
+(defun loop-hack-iteration (entry)
+  (flet ((make-endtest (list-of-forms)
+	   (cond ((null list-of-forms) nil)
+		 ((member t list-of-forms) '(go end-loop))
+		 (t `(when ,(if (null (cdr (setq list-of-forms (nreverse list-of-forms))))
+				(car list-of-forms)
+				(cons 'or list-of-forms))
+		       (go end-loop))))))
+    (do ((pre-step-tests nil)
+	 (steps nil)
+	 (post-step-tests nil)
+	 (pseudo-steps nil)
+	 (pre-loop-pre-step-tests nil)
+	 (pre-loop-steps nil)
+	 (pre-loop-post-step-tests nil)
+	 (pre-loop-pseudo-steps nil)
+	 (tem) (data))
+	(nil)
+      ;; Note we collect endtests in reverse order, but steps in correct
+      ;; order.  MAKE-ENDTEST does the nreverse for us.
+      (setq tem (setq data (apply (symbol-function (first entry)) (rest entry))))
+      (and (car tem) (push (car tem) pre-step-tests))
+      (setq steps (nconc steps (loop-copylist* (car (setq tem (cdr tem))))))
+      (and (car (setq tem (cdr tem))) (push (car tem) post-step-tests))
+      (setq pseudo-steps (nconc pseudo-steps (loop-copylist* (car (setq tem (cdr tem))))))
+      (setq tem (cdr tem))
+      (when *loop-emitted-body*
+	(loop-error "Iteration in LOOP follows body code."))
+      (unless tem (setq tem data))
+      (when (car tem) (push (car tem) pre-loop-pre-step-tests))
+      (setq pre-loop-steps (nconc pre-loop-steps (loop-copylist* (car (setq tem (cdr tem))))))
+      (when (car (setq tem (cdr tem))) (push (car tem) pre-loop-post-step-tests))
+      (setq pre-loop-pseudo-steps (nconc pre-loop-pseudo-steps (loop-copylist* (cadr tem))))
+      (unless (loop-tequal (car *loop-source-code*) :and)
+	(setq *loop-before-loop* (list* (loop-make-desetq pre-loop-pseudo-steps)
+					(make-endtest pre-loop-post-step-tests)
+					(loop-make-psetq pre-loop-steps)
+					(make-endtest pre-loop-pre-step-tests)
+					*loop-before-loop*)
+	      *loop-after-body* (list* (loop-make-desetq pseudo-steps)
+				       (make-endtest post-step-tests)
+				       (loop-make-psetq steps)
+				       (make-endtest pre-step-tests)
+				       *loop-after-body*))
+	(loop-bind-block)
+	(return nil))
+      (loop-pop-source)				; flush the "AND"
+      (when (and (not (loop-universe-implicit-for-required *loop-universe*))
+		 (setq tem (loop-lookup-keyword
+			     (car *loop-source-code*)
+			     (loop-universe-iteration-keywords *loop-universe*))))
+	;;Latest ANSI clarification is that the FOR/AS after the AND must NOT be supplied.
+	(loop-pop-source)
+	(setq entry tem)))))
+
+
+
+;;;; Main Iteration Drivers
+
+
+;FOR variable keyword ..args..
+(defun loop-do-for ()
+  (let* ((var (loop-pop-source))
+	 (data-type (loop-optional-type var))
+	 (keyword (loop-pop-source))
+	 (first-arg nil)
+	 (tem nil))
+    (setq first-arg (loop-get-form))
+    (unless (and (symbolp keyword)
+		 (setq tem (loop-lookup-keyword
+			     keyword
+			     (loop-universe-for-keywords *loop-universe*))))
+      (loop-error "~S is an unknown keyword in FOR or AS clause in LOOP." keyword))
+    (apply (car tem) var first-arg data-type (cdr tem))))
+
+(defun loop-do-repeat ()
+  (loop-disallow-conditional :repeat)
+  (let ((form (loop-get-form))
+	(type 'real))
+    (let ((var (loop-make-variable (loop-gentemp) form type)))
+      (push `(when (minusp (decf ,var)) (go end-loop)) *loop-before-loop*)
+      (push `(when (minusp (decf ,var)) (go end-loop)) *loop-after-body*)
+      ;; FIXME: What should
+      ;;   (loop count t into a
+      ;;         repeat 3
+      ;;         count t into b
+      ;;         finally (return (list a b)))
+      ;; return: (3 3) or (4 3)? PUSHes above are for the former
+      ;; variant, L-P-B below for the latter.
+      )))
+
+(defun loop-when-it-variable ()
+  (or *loop-when-it-variable*
+      (setq *loop-when-it-variable*
+	    (loop-make-variable (loop-gentemp 'loop-it-) nil nil))))
+
+
+
+;;;; Various FOR/AS Subdispatches
+
+
+;;;ANSI "FOR x = y [THEN z]" is sort of like the old Genera one when the THEN
+;;; is omitted (other than being more stringent in its placement), and like
+;;; the old "FOR x FIRST y THEN z" when the THEN is present.  I.e., the first
+;;; initialization occurs in the loop body (first-step), not in the variable binding
+;;; phase.
+(defun loop-ansi-for-equals (var val data-type)
+  (loop-make-iteration-variable var nil data-type)
+  (cond ((loop-tequal (car *loop-source-code*) :then)
+	 ;;Then we are the same as "FOR x FIRST y THEN z".
+	 (loop-pop-source)
+	 `(() (,var ,(loop-get-form)) () ()
+	   () (,var ,val) () ()))
+	(t ;;We are the same as "FOR x = y".
+	 `(() (,var ,val) () ()))))
+
+
+(defun loop-for-across (var val data-type)
+  (loop-make-iteration-variable var nil data-type)
+  (let ((vector-var (loop-gentemp 'loop-across-vector-))
+	(index-var (loop-gentemp 'loop-across-index-)))
+    (multiple-value-bind (vector-form constantp vector-value)
+	(loop-constant-fold-if-possible val 'vector)
+      (loop-make-variable
+	vector-var vector-form
+	(if (and (consp vector-form) (eq (car vector-form) 'the))
+	    (cadr vector-form)
+	    'vector))
+      (loop-make-variable index-var 0 'fixnum)
+      (let* ((length 0)
+	     (length-form (cond ((not constantp)
+				 (let ((v (loop-gentemp 'loop-across-limit-)))
+				   (push `(setq ,v (length ,vector-var)) *loop-prologue*)
+				   (loop-make-variable v 0 'fixnum)))
+				(t (setq length (length vector-value)))))
+	     (first-test `(>= ,index-var ,length-form))
+	     (other-test first-test)
+	     (step `(,var (aref ,vector-var ,index-var)))
+	     (pstep `(,index-var (1+ ,index-var))))
+	(declare (fixnum length))
+	(when constantp
+	  (setq first-test (= length 0))
+	  (when (<= length 1)
+	    (setq other-test t)))
+	`(,other-test ,step () ,pstep
+	  ,@(and (not (eq first-test other-test)) `(,first-test ,step () ,pstep)))))))
+
+
+
+
+;;;; List Iteration
+
+
+(defun loop-list-step (listvar)
+  ;;We are not equipped to analyze whether 'FOO is the same as #'FOO here in any
+  ;; sensible fashion, so let's give an obnoxious warning whenever 'FOO is used
+  ;; as the stepping function.
+  ;;While a Discerning Compiler may deal intelligently with (funcall 'foo ...), not
+  ;; recognizing FOO may defeat some LOOP optimizations.
+  (let ((stepper (cond ((loop-tequal (car *loop-source-code*) :by)
+			(loop-pop-source)
+			(loop-get-form))
+		       (t '(function cdr)))))
+    (cond ((and (consp stepper) (eq (car stepper) 'quote))
+	   (loop-warn "Use of QUOTE around stepping function in LOOP will be left verbatim.")
+	   (values `(funcall ,stepper ,listvar) nil))
+	  ((and (consp stepper) (eq (car stepper) 'function))
+	   (values (list (cadr stepper) listvar) (cadr stepper)))
+	  (t (values `(funcall ,(loop-make-variable (loop-gentemp 'loop-fn-) stepper 'function)
+			       ,listvar)
+		     nil)))))
+
+
+(defun loop-for-on (var val data-type)
+  (multiple-value-bind (list constantp list-value) (loop-constant-fold-if-possible val)
+    (let ((listvar var))
+      (cond ((and var (symbolp var)) (loop-make-iteration-variable var list data-type))
+	    (t (loop-make-variable (setq listvar (loop-gentemp)) list nil)
+	       (loop-make-iteration-variable var nil data-type)))
+      (multiple-value-bind (list-step step-function) (loop-list-step `(the cons ,listvar))
+	(declare (ignore step-function))
+	;;@@@@ The CLOE problem above has to do with bug in macroexpansion of multiple-value-bind.
+	(let* ((first-endtest
+		(hide-variable-reference
+		 (eq var listvar)
+		 listvar
+		 ;; the following should use `atom' instead of `endp', per
+		 ;; [bug2428]
+		 `(atom ,listvar)))
+	       (other-endtest first-endtest))
+	  (when (and constantp (listp list-value))
+	    (setq first-endtest (null list-value)))
+	  (cond ((eq var listvar)
+		 ;;Contour of the loop is different because we use the user's variable...
+		 `(() (,listvar ,(hide-variable-reference t listvar list-step)) ,other-endtest
+		   () () () ,first-endtest ()))
+		(t (let ((step `(,var (the cons ,listvar))) (pseudo `(,listvar ,list-step)))
+		     `(,other-endtest ,step () ,pseudo
+		       ,@(and (not (eq first-endtest other-endtest))
+			      `(,first-endtest ,step () ,pseudo)))))))))))
+
+
+(defun loop-for-in (var val data-type)
+  (multiple-value-bind (list constantp list-value) (loop-constant-fold-if-possible val)
+    (let ((listvar (loop-gentemp 'loop-list-)))
+      (loop-make-iteration-variable var nil data-type)
+      (loop-make-variable listvar list 'list)
+      (multiple-value-bind (list-step step-function) (loop-list-step listvar)
+        (declare (ignore step-function))
+	(let* ((first-endtest `(endp ,listvar))
+	       (other-endtest first-endtest)
+	       (step `(,var (car ,listvar)))
+	       (pseudo-step `(,listvar ,list-step)))
+	  (when (and constantp (listp list-value))
+	    (setq first-endtest (null list-value)))
+	  `(,other-endtest ,step () ,pseudo-step
+	    ,@(and (not (eq first-endtest other-endtest))
+		   `(,first-endtest ,step () ,pseudo-step))))))))
+
+
+
+;;;; Iteration Paths
+
+
+(defstruct (loop-path
+	     (:copier nil)
+	     (:predicate nil))
+  names
+  preposition-groups
+  inclusive-permitted
+  function
+  user-data)
+
+
+(defun add-loop-path (names function universe &key preposition-groups inclusive-permitted user-data)
+  (unless (listp names) (setq names (list names)))
+  ;; Can't do this due to CLOS bootstrapping problems.
+  (check-type universe loop-universe)
+  (let ((ht (loop-universe-path-keywords universe))
+	(lp (make-loop-path
+	      :names (mapcar #'symbol-name names)
+	      :function function
+	      :user-data user-data
+	      :preposition-groups (mapcar #'(lambda (x) (if (listp x) x (list x))) preposition-groups)
+	      :inclusive-permitted inclusive-permitted)))
+    (dolist (name names) (setf (gethash (symbol-name name) ht) lp))
+    lp))
+
+
+
+;;; Note:  path functions are allowed to use loop-make-variable, hack
+;;; the prologue, etc.
+(defun loop-for-being (var val data-type)
+  ;; FOR var BEING each/the pathname prep-phrases using-stuff...
+  ;; each/the = EACH or THE.  Not clear if it is optional, so I guess we'll warn.
+  (let ((path nil)
+	(data nil)
+	(inclusive nil)
+	(stuff nil)
+	(initial-prepositions nil))
+    (cond ((loop-tmember val '(:each :the)) (setq path (loop-pop-source)))
+	  ((loop-tequal (car *loop-source-code*) :and)
+	   (loop-pop-source)
+	   (setq inclusive t)
+	   (unless (loop-tmember (car *loop-source-code*) '(:its :each :his :her))
+	     (loop-error "~S found where ITS or EACH expected in LOOP iteration path syntax."
+			 (car *loop-source-code*)))
+	   (loop-pop-source)
+	   (setq path (loop-pop-source))
+	   (setq initial-prepositions `((:in ,val))))
+	  (t (loop-error "Unrecognizable LOOP iteration path syntax.  Missing EACH or THE?")))
+    (cond ((not (symbolp path))
+	   (loop-error "~S found where a LOOP iteration path name was expected." path))
+	  ((not (setq data (loop-lookup-keyword path (loop-universe-path-keywords *loop-universe*))))
+	   (loop-error "~S is not the name of a LOOP iteration path." path))
+	  ((and inclusive (not (loop-path-inclusive-permitted data)))
+	   (loop-error "\"Inclusive\" iteration is not possible with the ~S LOOP iteration path." path)))
+    (let ((fun (loop-path-function data))
+	  (preps (nconc initial-prepositions
+			(loop-collect-prepositional-phrases (loop-path-preposition-groups data) t)))
+	  (user-data (loop-path-user-data data)))
+      (when (symbolp fun) (setq fun (symbol-function fun)))
+      (setq stuff (if inclusive
+		      (apply fun var data-type preps :inclusive t user-data)
+		      (apply fun var data-type preps user-data))))
+    (when *loop-named-variables*
+      (loop-error "Unused USING variables: ~S." *loop-named-variables*))
+    ;; STUFF is now (bindings prologue-forms . stuff-to-pass-back).  Protect the system from the user
+    ;; and the user from himself.
+    (unless (member (length stuff) '(6 10))
+      (loop-error "Value passed back by LOOP iteration path function for path ~S has invalid length."
+		  path))
+    (do ((l (car stuff) (cdr l)) (x)) ((null l))
+      (if (atom (setq x (car l)))
+	  (loop-make-iteration-variable x nil nil)
+	  (loop-make-iteration-variable (car x) (cadr x) (caddr x))))
+    (setq *loop-prologue* (nconc (reverse (cadr stuff)) *loop-prologue*))
+    (cddr stuff)))
+
+
+
+
+;;;INTERFACE:  Lucid, exported.
+;;; i.e., this is part of our extended ansi-loop interface.
+(defun named-variable (name)
+  (let ((tem (loop-tassoc name *loop-named-variables*)))
+    (declare (list tem))
+    (cond ((null tem) (values (loop-gentemp) nil))
+	  (t (setq *loop-named-variables* (delete tem *loop-named-variables*))
+	     (values (cdr tem) t)))))
+
+
+(defun loop-collect-prepositional-phrases (preposition-groups &optional USING-allowed initial-phrases)
+  (flet ((in-group-p (x group) (car (loop-tmember x group))))
+    (do ((token nil)
+	 (prepositional-phrases initial-phrases)
+	 (this-group nil nil)
+	 (this-prep nil nil)
+	 (disallowed-prepositions
+	   (mapcan #'(lambda (x)
+		       (loop-copylist*
+			 (find (car x) preposition-groups :test #'in-group-p)))
+		   initial-phrases))
+	 (used-prepositions (mapcar #'car initial-phrases)))
+	((null *loop-source-code*) (nreverse prepositional-phrases))
+      (declare (symbol this-prep))
+      (setq token (car *loop-source-code*))
+      (dolist (group preposition-groups)
+	(when (setq this-prep (in-group-p token group))
+	  (return (setq this-group group))))
+      (cond (this-group
+	     (when (member this-prep disallowed-prepositions)
+	       (loop-error
+		 (if (member this-prep used-prepositions)
+		     "A ~S prepositional phrase occurs multiply for some LOOP clause."
+		     "Preposition ~S used when some other preposition has subsumed it.")
+		 token))
+	     (setq used-prepositions (if (listp this-group)
+					 (append this-group used-prepositions)
+					 (cons this-group used-prepositions)))
+	     (loop-pop-source)
+	     (push (list this-prep (loop-get-form)) prepositional-phrases))
+	    ((and USING-allowed (loop-tequal token 'using))
+	     (loop-pop-source)
+	     (do ((z (loop-pop-source) (loop-pop-source)) (tem)) (nil)
+	       (when (cadr z)
+		 (if (setq tem (loop-tassoc (car z) *loop-named-variables*))
+		     (loop-error
+		       "The variable substitution for ~S occurs twice in a USING phrase,~@
+		        with ~S and ~S."
+		       (car z) (cadr z) (cadr tem))
+		     (push (cons (car z) (cadr z)) *loop-named-variables*)))
+	       (when (or (null *loop-source-code*) (symbolp (car *loop-source-code*)))
+		 (return nil))))
+	    (t (return (nreverse prepositional-phrases)))))))
+
+
+
+;;;; Master Sequencer Function
+
+
+(defun loop-sequencer (indexv indexv-type indexv-user-specified-p
+			  variable variable-type
+			  sequence-variable sequence-type
+			  step-hack default-top
+			  prep-phrases)
+   (let ((endform nil)				;Form (constant or variable) with limit value.
+	 (sequencep nil)			;T if sequence arg has been provided.
+	 (testfn nil)				;endtest function
+	 (test nil)				;endtest form.
+	 (stepby (1+ (or (loop-typed-init indexv-type) 0)))	;Our increment.
+	 (stepby-constantp t)
+	 (step nil)				;step form.
+	 (dir nil)				;Direction of stepping: NIL, :UP, :DOWN.
+	 (inclusive-iteration nil)		;T if include last index.
+	 (start-given nil)			;T when prep phrase has specified start
+	 (start-value nil)
+	 (start-constantp nil)
+	 (limit-given nil)			;T when prep phrase has specified end
+	 (limit-constantp nil)
+	 (limit-value nil)
+	 )
+     (when variable (loop-make-iteration-variable variable nil variable-type))
+     (do ((l prep-phrases (cdr l)) (prep) (form) (odir)) ((null l))
+       (setq prep (caar l) form (cadar l))
+       (case prep
+	 ((:of :in)
+	  (setq sequencep t)
+	  (loop-make-variable sequence-variable form sequence-type))
+	 ((:from :downfrom :upfrom)
+	  (setq start-given t)
+	  (cond ((eq prep :downfrom) (setq dir ':down))
+		((eq prep :upfrom) (setq dir ':up)))
+	  (multiple-value-setq (form start-constantp start-value)
+	    (loop-constant-fold-if-possible form indexv-type))
+	  (setq indexv (loop-make-iteration-variable indexv form indexv-type)))
+	 ((:upto :to :downto :above :below)
+	  (cond ((loop-tequal prep :upto) (setq inclusive-iteration (setq dir ':up)))
+		((loop-tequal prep :to) (setq inclusive-iteration t))
+		((loop-tequal prep :downto) (setq inclusive-iteration (setq dir ':down)))
+		((loop-tequal prep :above) (setq dir ':down))
+		((loop-tequal prep :below) (setq dir ':up)))
+	  (setq limit-given t)
+	  (multiple-value-setq (form limit-constantp limit-value)
+	    (loop-constant-fold-if-possible form indexv-type))
+	  (setq endform (if limit-constantp
+			    `',limit-value
+			    (loop-make-variable
+			      (loop-gentemp 'loop-limit-) form indexv-type))))
+	 (:by
+	   (multiple-value-setq (form stepby-constantp stepby)
+	     (loop-constant-fold-if-possible form indexv-type))
+	   (unless stepby-constantp
+	     (loop-make-variable (setq stepby (loop-gentemp 'loop-step-by-)) form indexv-type)))
+	 (t (loop-error
+	      "~S invalid preposition in sequencing or sequence path.~@
+	       Invalid prepositions specified in iteration path descriptor or something?"
+	      prep)))
+       (when (and odir dir (not (eq dir odir)))
+	 (loop-error "Conflicting stepping directions in LOOP sequencing path"))
+       (setq odir dir))
+     (when (and sequence-variable (not sequencep))
+       (loop-error "Missing OF or IN phrase in sequence path"))
+     ;; Now fill in the defaults.
+     (unless start-given
+       (loop-make-iteration-variable
+	 indexv
+	 (setq start-constantp t start-value (or (loop-typed-init indexv-type) 0))
+	 indexv-type))
+     (cond ((member dir '(nil :up))
+	    (when (or limit-given default-top)
+	      (unless limit-given
+		(loop-make-variable (setq endform (loop-gentemp 'loop-seq-limit-))
+				    nil indexv-type)
+		(push `(setq ,endform ,default-top) *loop-prologue*))
+	      (setq testfn (if inclusive-iteration '> '>=)))
+	    (setq step (if (eql stepby 1) `(1+ ,indexv) `(+ ,indexv ,stepby))))
+	   (t (unless start-given
+		(unless default-top
+		  (loop-error "Don't know where to start stepping."))
+		(push `(setq ,indexv (1- ,default-top)) *loop-prologue*))
+	      (when (and default-top (not endform))
+		(setq endform (loop-typed-init indexv-type) inclusive-iteration t))
+	      (when endform (setq testfn (if inclusive-iteration  '< '<=)))
+	      (setq step (if (eql stepby 1) `(1- ,indexv) `(- ,indexv ,stepby)))))
+     (when testfn (setq test (hide-variable-reference t indexv `(,testfn ,indexv ,endform))))
+     (when step-hack
+       (setq step-hack `(,variable ,(hide-variable-reference indexv-user-specified-p indexv step-hack))))
+     (let ((first-test test) (remaining-tests test))
+       (when (and stepby-constantp start-constantp limit-constantp)
+	 (when (setq first-test (funcall (symbol-function testfn) start-value limit-value))
+	   (setq remaining-tests t)))
+       `(() (,indexv ,(hide-variable-reference t indexv step)) ,remaining-tests ,step-hack
+	 () () ,first-test ,step-hack))))
+
+
+
+;;;; Interfaces to the Master Sequencer
+
+
+
+(defun loop-for-arithmetic (var val data-type kwd)
+  (loop-sequencer
+    var (loop-check-data-type data-type 'number) t
+    nil nil nil nil nil nil
+    (loop-collect-prepositional-phrases
+      '((:from :upfrom :downfrom) (:to :upto :downto :above :below) (:by))
+      nil (list (list kwd val)))))
+
+
+(defun loop-sequence-elements-path (variable data-type prep-phrases
+				    &key fetch-function size-function sequence-type element-type)
+  (multiple-value-bind (indexv indexv-user-specified-p) (named-variable 'index)
+    (let ((sequencev (named-variable 'sequence)))
+      (list* nil nil				; dummy bindings and prologue
+	     (loop-sequencer
+	       indexv 'fixnum indexv-user-specified-p
+	       variable (or data-type element-type)
+	       sequencev sequence-type
+	       `(,fetch-function ,sequencev ,indexv) `(,size-function ,sequencev)
+	       prep-phrases)))))
+
+
+
+;;;; Builtin LOOP Iteration Paths
+
+
+#||
+(loop for v being the hash-values of ht do (print v))
+(loop for k being the hash-keys of ht do (print k))
+(loop for v being the hash-values of ht using (hash-key k) do (print (list k v)))
+(loop for k being the hash-keys of ht using (hash-value v) do (print (list k v)))
+||#
+
+(defun loop-hash-table-iteration-path (variable data-type prep-phrases &key which)
+  (check-type which (member hash-key hash-value))
+  (cond ((or (cdr prep-phrases) (not (member (caar prep-phrases) '(:in :of))))
+	 (loop-error "Too many prepositions!"))
+	((null prep-phrases) (loop-error "Missing OF or IN in iteration path." )))
+  (let ((ht-var (loop-gentemp 'loop-hashtab-))
+	(next-fn (loop-gentemp 'loop-hashtab-next-))
+	(dummy-predicate-var nil)
+	(post-steps nil))
+    (multiple-value-bind (other-var other-p)
+	(named-variable (if (eq which 'hash-key) 'hash-value 'hash-key))
+      ;;@@@@ named-variable returns a second value of T if the name was actually
+      ;; specified, so clever code can throw away the gensym'ed up variable if
+      ;; it isn't really needed.
+      (unless other-p (push `(ignorable ,other-var) *loop-declarations*))
+      ;;The following is for those implementations in which we cannot put dummy NILs
+      ;; into multiple-value-setq variable lists.
+      (setq other-p t
+            dummy-predicate-var (loop-when-it-variable))
+      (setq variable (or variable (loop-gentemp 'ignore-)))
+      (let ((key-var nil)
+	    (val-var nil)
+	    (bindings `((,variable nil ,data-type)
+			(,ht-var ,(cadar prep-phrases))
+			,@(and other-p other-var `((,other-var nil))))))
+	(if (eq which 'hash-key)
+	    (setq key-var variable val-var (and other-p other-var))
+	    (setq key-var (and other-p other-var) val-var variable))
+	(push `(with-hash-table-iterator (,next-fn ,ht-var)) *loop-wrappers*)
+	(when (or (consp key-var) data-type)
+	  (setq post-steps `(,key-var ,(setq key-var (loop-gentemp 'loop-hash-key-temp-))
+			     ,@post-steps))
+	  (push `(,key-var nil) bindings))
+	(when (or (consp val-var) data-type)
+	  (setq post-steps `(,val-var ,(setq val-var (loop-gentemp 'loop-hash-val-temp-))
+			     ,@post-steps))
+	  (push `(,val-var nil) bindings))
+        (push `(ignorable ,dummy-predicate-var) *loop-declarations*)
+	`(,bindings				;bindings
+	  ()					;prologue
+	  ()					;pre-test
+	  ()					;parallel steps
+	  (not (multiple-value-setq (,dummy-predicate-var ,key-var ,val-var) (,next-fn)))	;post-test
+	  ,post-steps)))))
+
+
+(defun loop-package-symbols-iteration-path (variable data-type prep-phrases &key symbol-types)
+  (cond ((and prep-phrases (cdr prep-phrases))
+	 (loop-error "Too many prepositions!"))
+	((and prep-phrases (not (member (caar prep-phrases) '(:in :of))))
+	 (loop-error "Unknown preposition ~S" (caar prep-phrases))))
+  (unless (symbolp variable)
+    (loop-error "Destructuring is not valid for package symbol iteration."))
+  (let ((pkg-var (loop-gentemp 'loop-pkgsym-))
+	(next-fn (loop-gentemp 'loop-pkgsym-next-))
+	(variable (or variable (loop-gentemp 'ignore-)))
+	(pkg (or (cadar prep-phrases) '*package*)))
+    (push `(with-package-iterator (,next-fn ,pkg-var ,@symbol-types)) *loop-wrappers*)
+    (push `(ignorable ,(loop-when-it-variable)) *loop-declarations*)
+    
+    `(((,variable nil ,data-type) (,pkg-var ,pkg))
+      ()
+      ()
+      ()
+      (not (multiple-value-setq (,(progn
+				    ;;@@@@ If an implementation can get away without actually
+				    ;; using a variable here, so much the better.
+                                    (loop-when-it-variable))
+				 ,variable)
+	     (,next-fn)))
+      ())))
+
+
+;;;; ANSI Loop
+
+(defun make-ansi-loop-universe (extended-p)
+  (let ((w (make-standard-loop-universe
+	     :keywords `((named (loop-do-named))
+			 (initially (loop-do-initially))
+			 (finally (loop-do-finally))
+			 (do (loop-do-do))
+			 (doing (loop-do-do))
+			 (return (loop-do-return))
+			 (collect (loop-list-collection list))
+			 (collecting (loop-list-collection list))
+			 (append (loop-list-collection append))
+			 (appending (loop-list-collection append))
+			 (nconc (loop-list-collection nconc))
+			 (nconcing (loop-list-collection nconc))
+			 (count (loop-sum-collection count ,*loop-real-data-type* fixnum))
+			 (counting (loop-sum-collection count ,*loop-real-data-type* fixnum))
+			 (sum (loop-sum-collection sum number number))
+			 (summing (loop-sum-collection sum number number))
+			 (maximize (loop-maxmin-collection max))
+			 (minimize (loop-maxmin-collection min))
+			 (maximizing (loop-maxmin-collection max))
+			 (minimizing (loop-maxmin-collection min))
+			 (always (loop-do-always t nil))	; Normal, do always
+			 (never (loop-do-always t t))	; Negate the test on always.
+			 (thereis (loop-do-thereis t))
+			 (while (loop-do-while nil :while))	; Normal, do while
+			 (until (loop-do-while t :until))	; Negate the test on while
+			 (when (loop-do-if when nil))	; Normal, do when
+			 (if (loop-do-if if nil))	; synonymous
+			 (unless (loop-do-if unless t))	; Negate the test on when
+			 (with (loop-do-with))
+			 (repeat (loop-do-repeat)))
+	     :for-keywords '((= (loop-ansi-for-equals))
+			     (across (loop-for-across))
+			     (in (loop-for-in))
+			     (on (loop-for-on))
+			     (from (loop-for-arithmetic :from))
+			     (downfrom (loop-for-arithmetic :downfrom))
+			     (upfrom (loop-for-arithmetic :upfrom))
+			     (below (loop-for-arithmetic :below))
+			     (above (loop-for-arithmetic :above))
+			     (by (loop-for-arithmetic :by))
+			     (to (loop-for-arithmetic :to))
+			     (upto (loop-for-arithmetic :upto))
+                             (downto (loop-for-arithmetic :downto))
+			     (being (loop-for-being)))
+	     :iteration-keywords '((for (loop-do-for))
+				   (as (loop-do-for)))
+	     :type-symbols '(array atom bignum bit bit-vector character compiled-function
+				   complex cons double-float fixnum float
+				   function hash-table integer keyword list long-float
+				   nil null number package pathname random-state
+				   ratio rational readtable sequence short-float
+				   simple-array simple-bit-vector simple-string
+				   simple-vector single-float standard-char
+				   stream string base-char
+				   symbol t vector)
+	     :type-keywords nil
+	     :ansi (if extended-p :extended t))))
+    (add-loop-path '(hash-key hash-keys) 'loop-hash-table-iteration-path w
+		   :preposition-groups '((:of :in))
+		   :inclusive-permitted nil
+		   :user-data '(:which hash-key))
+    (add-loop-path '(hash-value hash-values) 'loop-hash-table-iteration-path w
+		   :preposition-groups '((:of :in))
+		   :inclusive-permitted nil
+		   :user-data '(:which hash-value))
+    (add-loop-path '(symbol symbols) 'loop-package-symbols-iteration-path w
+		   :preposition-groups '((:of :in))
+		   :inclusive-permitted nil
+		   :user-data '(:symbol-types (:internal :external :inherited)))
+    (add-loop-path '(external-symbol external-symbols) 'loop-package-symbols-iteration-path w
+		   :preposition-groups '((:of :in))
+		   :inclusive-permitted nil
+		   :user-data '(:symbol-types (:external)))
+    (add-loop-path '(present-symbol present-symbols) 'loop-package-symbols-iteration-path w
+		   :preposition-groups '((:of :in))
+		   :inclusive-permitted nil
+		   :user-data '(:symbol-types (:internal :external)))
+    w))
+
+
+(defparameter *loop-ansi-universe*
+	      (make-ansi-loop-universe nil))
+
+
+(defun loop-standard-expansion (keywords-and-forms environment universe)
+  (if (and keywords-and-forms (symbolp (car keywords-and-forms)))
+      (loop-translate keywords-and-forms environment universe)
+      (let ((tag (gensym)))
+	`(block nil (tagbody ,tag (progn ,@keywords-and-forms) (go ,tag))))))
+
+
+(fmakunbound 'loop)                     ; Avoid redefinition warning
+
+;;;INTERFACE: ANSI
+(defmacro loop (&environment env &rest keywords-and-forms)
+  (loop-standard-expansion keywords-and-forms env *loop-ansi-universe*))
+
+(cl:provide "LOOP")
Index: /branches/new-random/library/mac-file-io.lisp
===================================================================
--- /branches/new-random/library/mac-file-io.lisp	(revision 13309)
+++ /branches/new-random/library/mac-file-io.lisp	(revision 13309)
@@ -0,0 +1,161 @@
+;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Opensourced MCL.
+;;;
+;;;   Opensourced MCL is free software; you can redistribute it and/or
+;;;   modify it under the terms of the GNU Lesser General Public
+;;;   License as published by the Free Software Foundation; either
+;;;   version 2.1 of the License, or (at your option) any later version.
+;;;
+;;;   Opensourced MCL is distributed in the hope that it will be useful,
+;;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;   Lesser General Public License for more details.
+;;;
+;;;   You should have received a copy of the GNU Lesser General Public
+;;;   License along with this library; if not, write to the Free Software
+;;;   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+;;;
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; mac-file-io.lisp
+;;
+
+;; This file implements something similar to the high-level file I/O
+;; primitives in Inside Macintosh.
+;; It does NOT support asynchronous I/O (and neither does the Macintosh, really).
+
+;; Routines that take an errorp parameter will signal an error if
+;; the parameter is unspecified or true, otherwise, if there is an
+;; error they return two values: NIL & the error number.
+;; If there is no error, routines return one or more values the
+;; first of which is non-NIL.
+
+;;;;;;;;;;;;;
+;;
+;; Modification History
+;;
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require 'sysequ))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (export '(with-FSOpen-file FSOpen FSClose FSRead FSWrite setFPos getFPos getEOF)))
+
+(defmacro with-FSOpen-file ((pb filename &optional read-write-p (vrefnum 0))
+                            &body body)
+  `(let ((,pb (FSOpen ,filename ,read-write-p ,vrefnum)))
+     (unwind-protect
+       (progn ,@body)
+       (FSClose ,pb))))
+
+(defmacro with-FSOpen-file-noerr ((pb filename &optional read-write-p (vrefnum 0))
+                                  &body body)
+  `(let ((,pb (ignore-errors
+               (FSOpen ,filename ,read-write-p ,vrefnum))))
+     (when ,pb
+       (unwind-protect
+         (progn ,@body)
+         (FSClose ,pb)))))
+
+; Returns a paramBlock for doing furthur I/O with the file
+(defun FSOpen (filename &optional read-write-p (vrefnum 0) (errorp t)
+                        (resolve-aliases-p t))
+  (when resolve-aliases-p (setq filename (truename filename)))
+  (let ((paramBlock (make-record :hparamblockrec))
+        ok)
+    (unwind-protect
+      (with-pstrs ((pname (mac-namestring filename)))
+        (setf (pref paramblock :hparamblockrec.ioNameptr) pname
+              (pref paramblock :hparamblockrec.ioVrefnum) vrefnum
+              (pref paramblock :hparamblockrec.ioVersNum) 0
+              (pref paramblock :hparamblockrec.ioPermssn) (if read-write-p #$fsRdWrPerm #$fsRdPerm)
+              (pref paramblock :hparamblockrec.ioMisc) (%null-ptr))
+        (#_PBOpenSync paramBlock)
+        (let ((res (pref paramBlock :hparamblockrec.ioResult)))
+          (if (eql #$NoErr res)
+            (progn
+              (setf (pref paramblock :hparamblockrec.ioPosOffSet) 0
+                    (pref paramblock :hparamblockrec.ioPosMode) #$fsAtMark)
+              (setq ok t)
+              paramBlock)
+            (maybe-file-error errorp res filename))))
+      (unless ok
+        (#_DisposePtr paramBlock)))))
+
+(defun FSClose (paramBlock &optional (errorp t))
+  (#_PBCloseSync paramBlock)
+  (let ((errnum (pref paramBlock :hparamblockrec.ioResult)))
+    (#_DisposePtr paramBlock)
+    (or (eql errnum #$noErr)
+        (maybe-file-error errorp errnum))))
+
+; Returns two values: the number of bytes actually read, and the
+; location of the file mark.
+(defun fsRead (paramBlock count buffer &optional (offset 0) (errorp t))
+  (setf (pref paramBlock :hparamblockrec.ioBuffer) (%inc-ptr buffer offset)
+        (pref paramBlock :hparamblockrec.ioReqCount) count)
+  (#_PBReadSync paramBlock)
+  (setf (pref paramBlock :hparamblockrec.ioPosMode) #$fsAtMark)
+  (let ((errnum (pref paramBlock :hparamblockrec.ioResult)))
+    (if (or (eql #$noErr errnum) (eql #$eofErr errnum))
+      (values (pref paramBlock :hparamblockrec.ioActCount)
+              (pref paramBlock :hparamblockrec.ioPosOffset))
+      (maybe-file-error errorp errnum))))
+
+; Returns two values: the number of bytes actually written, and the
+; location of the file mark.
+(defun fsWrite (paramBlock count buffer &optional (offset 0) (errorp t))
+  (setf (pref paramBlock :hparamblockrec.ioBuffer) (%inc-ptr buffer offset)
+        (pref paramBlock :hparamblockrec.ioReqCount) count)
+  (#_PBWriteSync paramBlock)
+  (setf (pref paramBlock :hparamblockrec.ioPosMode) #$fsAtMark)
+  (let ((errnum (pref paramBlock :hparamblockrec.ioResult)))
+    (if (or (eql #$noErr errnum) (eql #$eofErr errnum))
+      (values (pref paramBlock :hparamblockrec.ioActCount)
+              (pref paramBlock :hparamblockrec.ioPosOffset))
+      (maybe-file-error errorp errnum))))
+
+(defun setFPos (paramBlock pos)
+  (setf (pref paramBlock :hparamblockrec.ioPosOffset) pos
+        (pref paramblock :hparamblockrec.ioPosMode) #$fsFromStart)
+  pos)
+
+(defun getFPos (paramBlock)
+  (pref paramBlock :hparamblockrec.ioPosOffset))
+
+(defun getEOF (paramBlock &optional (errorp t))
+  (let* ((errnum (#_PBGetEOFSync paramBlock)))
+    (if (eql #$noErr errnum)
+      (%ptr-to-int (pref paramblock :hparamblockrec.ioMisc))
+      (maybe-file-error errorp errnum))))
+
+(defun GetVInfo (&key (volName "") (vRefNum 0))
+  (let* ((vol-pathname (truename (make-pathname :type nil :name nil :defaults volName)))
+         (directory    (pathname-directory vol-pathname)))
+    (assert (and directory (eq :absolute (car directory))))
+    (rlet ((paramBlock :hparamblockrec))
+      (with-returned-pstrs ((pname (cadr directory)))
+        (setf (pref paramblock :hparamblockrec.ioCompletion) (%null-ptr)
+              (pref paramblock :hparamblockrec.ioNamePtr)    pname
+              (pref paramblock :hparamblockrec.ioVRefNum)    vRefNum
+              (pref paramblock :hparamblockrec.ioVolIndex)   0)
+        (values (#_PBHGetVInfoSync paramBlock)
+                (* (%get-unsigned-long paramblock $ioVAlBlkSiz)         ; see IM:Files 2-46
+                   (pref paramblock :hparamblockrec.ioVFrBlk))
+                (pref paramblock :hparamblockrec.ioVRefNum)
+                (%get-string (pref paramblock :hparamblockrec.ioNamePtr)))))))
+
+(defun maybe-file-error (errorp errnum &optional filename)
+  (if errorp
+    (%err-disp errnum filename)
+    (values nil errnum)))
+
+(provide :mac-file-io)
+
+; End of mac-file-io.lisp
Index: /branches/new-random/library/mach-o-symbols.lisp
===================================================================
--- /branches/new-random/library/mach-o-symbols.lisp	(revision 13309)
+++ /branches/new-random/library/mach-o-symbols.lisp	(revision 13309)
@@ -0,0 +1,216 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+;;; String tables: used both for symbol names and for section names.
+(defstruct mach-o-string-table
+  (hash (make-hash-table :test #'equal))
+  (string (make-array 100 :element-type '(unsigned-byte 8) :fill-pointer 1 :adjustable t)))
+
+;;; Collect info about Mach-O symbols.
+(defstruct mach-o-symbol-table
+  (strings (make-mach-o-string-table))
+  data                                  ; foreign pointer
+  nsyms
+  )
+
+(defun mach-o-lisp-function-name (f)
+  (let* ((name (format nil "~s" f)))
+    (subseq (nsubstitute #\0 #\# (nsubstitute #\. #\Space name)) 1)))
+
+(defun mach-o-register-string (string table)
+  (let* ((hash (mach-o-string-table-hash table))
+         (s (mach-o-string-table-string table)))
+    (when (gethash string hash)
+      (format t "~& duplicate: ~s" string))
+    (or (gethash string hash)
+        (setf (gethash string hash)
+              (let* ((n (length s)))
+                (dotimes (i (length string) (progn (vector-push-extend 0 s) n))
+                  (let* ((code (char-code (char string i))))
+                    (declare (type (mod #x110000 code)))
+                    (if (> code 255)
+                      (vector-push-extend (char-code #\sub) s)
+                      (vector-push-extend code s)))))))))
+
+(defun readonly-area-bounds ()
+  (ccl::do-gc-areas (a)
+    (when (eql (ccl::%fixnum-ref a target::area.code)
+	       ccl::area-readonly)
+      (return
+	(values (ash (ccl::%fixnum-ref a target::area.low) target::fixnumshift)
+		(ash (ccl::%fixnum-ref a target::area.active) target::fixnumshift))))))
+
+#+ppc-target
+(defun collect-mach-o-static-functions ()
+  (purify)
+  (multiple-value-bind (readonly-low readonly-high)
+      (readonly-area-bounds)
+    (let* ((hash (make-hash-table :test #'eq)))
+      (ccl::%map-lfuns #'(lambda (f)
+			   (let* ((code-vector (ccl:uvref f 0))
+				  (startaddr (+ (ccl::%address-of code-vector)
+						target::misc-data-offset)))
+			     (when (and (>= startaddr readonly-low)
+					(< startaddr readonly-high))
+			       (push f (gethash code-vector hash))))))
+      (collect ((functions))
+	(maphash #'(lambda (k v)
+		     (declare (ignore k))
+		     (if (null (cdr v))
+		       (functions (car v))))
+		 hash)
+        (values (sort (functions)
+		      #'(lambda (x y)
+			  (< (ccl::%address-of  (uvref x 0))
+			     (ccl::%address-of  (uvref y 0)))))
+		readonly-low
+		(- readonly-high readonly-low))))))
+
+(defun register-mach-o-functions (functions section-number)
+  (let* ((n (length functions))
+	 (nlist-len #+64-bit-target (record-length :nlist_64)
+		    #+32-bit-target (record-length :nlist))
+	 (data (#_calloc n nlist-len))
+	 (string-table (make-mach-o-string-table)))
+    (declare (fixnum n))
+    (do* ((i 0 (1+ i))
+	  (p (%inc-ptr data 0) (progn (%incf-ptr p nlist-len) p))
+	  (f (pop functions) (pop functions)))
+	 ((= i n)
+	  (make-mach-o-symbol-table :strings string-table :data data :nsyms n))
+      (declare (fixnum i))
+      (let* ((namidx (mach-o-register-string (mach-o-lisp-function-name f) string-table))
+	     (value (%address-of #+ppc-target (uvref f 0) #-ppc-target g))
+	     (type #$N_SECT))
+      #+32-bit-target
+      (setf (pref p :nlist.n_un.n_strx) namidx
+	    (pref p :nlist.n_value) value
+	    (pref p :nlist.n_type) type
+	    (pref p :nlist.n_other) section-number)
+      #+64-bit-target
+      (setf (pref p :nlist_64.n_un.n_strx) namidx
+	    (pref p :nlist_64.n_value) value
+	    (pref p :nlist_64.n_type) type
+	    (pref p :nlist_64.n_sect) section-number)))))
+
+(defun write-mach-o-symbol-info (fd symtab)
+  (let* ((symoff *host-page-size*)
+	 (nsyms (mach-o-symbol-table-nsyms symtab))
+	 (symsize (* nsyms (record-length #+64-bit-target :nlist_64
+						   #+32-bit-target :nlist)))
+	 (stroff (+ symoff symsize))
+	 (string (mach-o-string-table-string (mach-o-symbol-table-strings symtab)))
+	 (strsize (length string))
+	 (bytes (array-data-and-offset string))
+	 (strbuf (#_malloc strsize)))
+    (%copy-ivector-to-ptr bytes 0 strbuf 0 strsize)
+    (fd-lseek fd symoff #$SEEK_SET)
+    (fd-write fd (mach-o-symbol-table-data symtab) symsize)
+    (fd-write fd strbuf strsize)
+    (values symoff nsyms stroff strsize)))
+
+(defun write-mach-o-load-commands (fd pos)
+  (multiple-value-bind (functions start length)
+      (collect-mach-o-static-functions)
+    (let* ((symbols (register-mach-o-functions functions 1)))
+      (multiple-value-bind (symoff nsyms stroff strsize)
+	  (write-mach-o-symbol-info fd symbols)
+	(rlet ((symtab :symtab_command
+		 :cmd #$LC_SYMTAB
+		 :cmdsize (record-length :symtab_command)
+		 :symoff symoff
+		 :nsyms nsyms
+		 :stroff stroff
+		 :strsize strsize))
+	  (let* ((segsize (record-length #+64-bit-target :segment_command_64
+					 #+32-bit-target :segment_command))
+		 (sectsize (record-length #+64-bit-target :section_64
+					 #+32-bit-target :section))
+		 (totalsize (+ segsize sectsize)))
+	    (%stack-block ((segment totalsize :clear t))
+	      (let* ((section (%inc-ptr segment segsize)))
+		#+64-bit-target
+		(progn
+		  (setf (pref segment :segment_command_64.cmd) #$LC_SEGMENT_64
+			(pref segment :segment_command_64.cmdsize) totalsize)
+		  (%cstr-pointer #$SEG_DATA
+				 (pref segment :segment_command_64.segname)
+				 nil)
+		  (setf (pref segment :segment_command_64.vmaddr) start
+			(pref segment :segment_command_64.vmsize) length
+			(pref segment :segment_command_64.fileoff) 0
+			(pref segment :segment_command_64.filesize) 0
+			(pref segment :segment_command_64.maxprot) 0
+			(pref segment :segment_command_64.initprot) 0
+			(pref segment :segment_command_64.nsects) 1)
+		  (%cstr-pointer "__lisp" (pref section :section_64.sectname) nil)
+		  (%cstr-pointer #$SEG_DATA (pref section :section_64.segname) nil)
+		  (setf (pref section :section_64.addr) start
+			(pref section :section_64.size) length
+			(pref section :section_64.align) 12))
+		#+32-bit-target
+		(progn
+		  (setf (pref segment :segment_command.cmd) #$LC_SEGMENT
+			(pref segment :segment_command.cmdsize) totalsize)
+		  (%cstr-pointer #$SEG_DATA
+				 (pref segment :segment_command.segname)
+				 nil)
+		  (setf (pref segment :segment_command.vmaddr) start
+			(pref segment :segment_command.vmsize) length
+			(pref segment :segment_command.fileoff) 0
+			(pref segment :segment_command.filesize) 0
+			(pref segment :segment_command.maxprot) 0
+			(pref segment :segment_command.initprot) 0
+			(pref segment :segment_command.nsects) 1)
+		  (%cstr-pointer "__lisp" (pref section :section.sectname) nil)
+		  (%cstr-pointer #$SEG_DATA (pref section :section.segname) nil)
+		  (setf (pref section :section.addr) start
+			(pref section :section.size) length
+			(pref section :section.align) 12))
+		(fd-lseek fd pos #$SEEK_SET)
+		(fd-write fd segment totalsize)
+		(fd-write fd symtab (record-length :symtab_command))
+		(values 2
+			(+ totalsize (record-length :symtab_command)))))))))))
+
+    
+(defun write-mach-header (fd)
+  (let* ((n (record-length #+64-bit-target :mach_header_64
+			   #+32-bit-target :mach_header)))
+    (multiple-value-bind (ncmds cmd-size)
+	(write-mach-o-load-commands fd n)
+      (rlet ((header #+64-bit-target :mach_header_64 #+32-bit-target :mach_header
+		     :magic #+64-bit-target #$#$MH_MAGIC_64 #+32-bit-target #$MH_MAGIC
+		     :cputype (logior #+64-bit-target #$CPU_ARCH_ABI64
+				      #+32-bit-target 0
+				      #+ppc-target #$CPU_TYPE_POWERPC
+				      #+x86-target #$CPU_TYPE_X86)
+		     :cpusubtype #+x86-target #$CPU_SUBTYPE_X86_ALL #+ppc-target #$CPU_SUBTYPE_POWERPC_ALL
+		     :filetype #$MH_BUNDLE
+		     :ncmds ncmds
+		     :sizeofcmds cmd-size
+		     :flags (logior #$MH_NOUNDEFS)))
+	(fd-lseek fd 0 #$SEEK_SET)
+	(let* ((res (fd-write fd header n)))
+	  (unless (eql res n)
+	    (%errno-disp res)))
+	(fd-close fd)))))
+	   
+
+    
+		 
+  
+		  
Index: /branches/new-random/library/mach-o.lisp
===================================================================
--- /branches/new-random/library/mach-o.lisp	(revision 13309)
+++ /branches/new-random/library/mach-o.lisp	(revision 13309)
@@ -0,0 +1,133 @@
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(defstruct mach-o-file
+  header
+  load-commands
+  segments
+  symbols
+  strings)
+
+(defmethod print-object ((m mach-o-file) stream)
+  (print-unreadable-object (m stream :type t :identity t)))
+
+
+(defstruct mach-o-string-table
+  (hash (make-hash-table :test #'equal))
+  (string (make-array 100 :element-type '(unsigned-byte 8) :fill-pointer 1 :adjustable t)))
+
+(defstruct mach-o-symbol
+  string-index
+  type
+  sect
+  desc
+  value)
+
+(defun init-mach-o-string-table (fd symtab-command)
+  (fd-lseek fd (pref symtab-command #>symtab_command.stroff) #$SEEK_SET)
+  (let* ((strsize (pref symtab-command #>symtab_command.strsize))
+         (nbytes (+ strsize strsize))
+         (bytes (make-array nbytes :element-type '(unsigned-byte 8)))
+         (out 0))
+    (declare (fixnum nbytes strsize out))
+    (%stack-block ((buf 32768))
+      (do* ((n strsize))
+           ((= n 0))
+        (let* ((bufsize (fd-read fd buf (min n 32768))))
+          (%copy-ptr-to-ivector buf 0 bytes out bufsize)
+          (incf out bufsize)
+          (decf n bufsize))))
+    (make-mach-o-string-table
+     :string (make-array nbytes
+                         :element-type '(unsigned-byte 8)
+                         :displaced-to bytes
+                         :fill-pointer strsize
+                         :adjustable t))))
+
+(defun init-mach-o-symbols64 (fd symtab-command)
+  (fd-lseek fd (pref symtab-command #>symtab_command.symoff) #$SEEK_SET)
+  (rlet ((nlist #>nlist_64))
+    (let* ((nsyms (pref symtab-command #>symtab_command.nsyms))
+           (nentries (* nsyms 2))
+           (vec (make-array nentries)))
+      (declare (fixnum nsyms nentries))
+      (flet ((read-nlist ()
+               (fd-read fd nlist (record-length #>nlist_64))
+               (make-mach-o-symbol :string-index (pref nlist #>nlist_64.n_un.n_strx)
+                                   :type (pref nlist #>nlist_64.n_type)
+                                   :sect (pref nlist #>nlist_64.n_sect)
+                                   :desc (pref nlist #>nlist_64.n_desc)
+                                   :value (pref nlist #>nlist_64.n_value))))
+        (dotimes (i nsyms (make-array nentries
+                                      :displaced-to vec
+                                      :fill-pointer nsyms
+                                      :adjustable t))
+          (setf (svref vec i) (read-nlist)))))))
+    
+
+(defun read-header-and-load-commands64 (fd)
+  (fd-lseek fd 0 #$SEEK_SET)
+  (let* ((mh (make-record :mach_header_64))
+         (mach-o (make-mach-o-file :header mh)))
+    (when (= (fd-read fd mh (record-length :mach_header_64))
+             (record-length :mach_header_64))
+      (collect ((commands))
+        (flet ((read-command ()
+                 (rlet ((cmd :load_command))
+                   (fd-read fd cmd (record-length :load_command))
+                   (let* ((n (pref cmd :load_command.cmdsize))
+                          (p (#_malloc n))
+                          (q (%inc-ptr p (record-length :load_command))))
+                     (#_memcpy p cmd (record-length :load_command))
+                     (fd-read fd q (- n (record-length :load_command)))
+                     (let* ((lcmd (pref cmd :load_command.cmd))
+                            (ftype 
+                             (cond ((= lcmd #$LC_SEGMENT_64)
+                                    (load-record #>segment_command_64))
+                                   ((= lcmd #$LC_SYMTAB)
+                                    (load-record #>symtab_command))
+                                   ((= lcmd #$LC_DYSYMTAB)
+                                    (load-record #>dysymtab_command))
+                                   ((= lcmd #$LC_LOAD_DYLINKER)
+                                    (load-record #>dylinker_command))
+                                   ((= lcmd #$LC_UUID)
+                                    (load-record #>uuid_command))
+                                   ((= lcmd #$LC_LOAD_DYLIB)
+                                    (load-record #>dylib_command))
+                                   ((= lcmd #$LC_UNIXTHREAD)
+                                    (load-record #>thread_command)))))
+
+                       (if ftype
+                         (%set-macptr-type p (foreign-record-type-ordinal ftype))
+                         (format t "~&~x" lcmd)))
+                     p))))
+          (dotimes (i (pref mh :mach_header_64.ncmds))
+            (commands (read-command)))
+          (setf (mach-o-file-load-commands mach-o) (commands))
+          (dolist (cmd (mach-o-file-load-commands mach-o))
+            (when (= #$LC_SYMTAB (pref cmd #>load_command.cmd))
+              (setf (mach-o-file-strings mach-o)
+                    (init-mach-o-string-table fd cmd)
+                    (mach-o-file-symbols mach-o)
+                    (init-mach-o-symbols64 fd cmd))))
+          mach-o)))))
+
+(defun mach-o-string-index (mo string)
+  (let* ((bytes (make-array (the fixnum (+ (length string) 2)) :element-type '(unsigned-byte 8))))
+    (declare (dynamic-extent bytes))
+    (dotimes (i (length string))
+      (setf (aref bytes (1+ i)) (char-code (char string i))))
+    (let* ((pos (search bytes (mach-o-string-table-string (mach-o-file-strings mo)))))
+      (when pos (1+ pos)))))
+              
Index: /branches/new-random/library/macptr-termination.lisp
===================================================================
--- /branches/new-random/library/macptr-termination.lisp	(revision 13309)
+++ /branches/new-random/library/macptr-termination.lisp	(revision 13309)
@@ -0,0 +1,480 @@
+; -*- Mode: Lisp; Package: CCL; -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; macptr-termination.lisp
+;;;
+;;; Allows you to associate a termination function with a macptr.
+;;; The termination function will be called with the macptr as
+;;; its single arg when the macptr is no longer accessible in the
+;;; mac heap (i.e. when the garbage collector decides that its
+;;; storage can be recycled).
+;;;
+;;; This file is provided primarily for backward compatibility.
+;;; You can use terminate-when-unreachable for new code.
+
+;; Modification History
+;;
+;; 11/26/96 bill Remove cons-terminable-macptr from the PPC version of the code.
+;;               It referenced undefined $macptr-size and it was not used.
+;; ------------- 4.0
+;; 09/12/96 bill *slave-macptrs-table* is for non-terminable slaves.
+;;               *terminable-slaves-table* is for terminable slaves.
+;;               *terminable-slaves-table* is not weak, *slave-macptrs-table* still is.
+;;               *terminable-slaves-table* is an EQL hash table which maps a copy of the
+;;               slave to the master.
+;;               When a slave is terminated, its entry is explicitly removed from *terminable-slaves-table*.
+;;               This means that a master will be removed on the next GC after all of
+;;               its slaves are terminated. Not optimal, but it guarantees that all the slaves are
+;;               disposed before the master.
+;; 08/23/96 bill A *save-exit-function* to clear-terminable-macptrs
+;; 08/21/96 bill add the SK8 register-slave-macptr & teminable-macptr-p functions
+;;               and the :deactivate-only keyword to deactivate-macptr
+;; ------------- 4.0b1
+;; 02/28/96 bill Make it work in PPC MCL
+;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Documentation
+;;;
+
+#|
+
+SET-POST-EGC-HOOK-ENABLED-P value
+  This package works by setting MCL's undocumented ccl::*post-gc-hook*.
+The hook is normally called only after a full GC. If you want it to
+be called after each ephemeral GC as well, call this with a true value.
+
+POST-EGC-HOOK-ENABLED-P
+  Returns true if the post gc hook will be called after EGC as well as
+after full GC.¬
+
+ADD-PRE-GC-HOOK hook
+DELETE-PRE-GC-HOOK hook
+ADD-POST-GC-HOOK hook
+DELETE-POST-GC-HOOK hook
+  MCL's ccl::*pre-gc-hook* and ccl::*post-gc-hook* can each contain
+either a function or NIL. These four functions extend that functionality
+by maintaining a list of functions for each of the two hooks. Hooks are
+compared with EQ, so it is best to pass a symbol that has a global
+definition (see the last form in this file).
+
+MAKE-TERMINABLE-MACPTR macptr termination-function &key master
+  Creates and returns a terminable macptr. It will point at the same Mac
+Heap address as the macptr arg. When the return value becomes scavengeable
+(e.g. no longer accessible in the Lisp heap), will call the
+termination-function with a single arg, the returned macptr. If the
+termination-function's return value is non-NIL, will free the macptr.
+Otherwise, will assume that you decided not to terminate it, and will
+call the termination-function again the next time the GC runs and
+it is scavengeable.  If master is supplied, then
+initialize the new terminable macptr as a slave to the given master.
+All slave terminable macptrs are terminated before their master is terminated.
+Raise an error if macptr is not a macptr or the supplied master
+is not a terminable macptr.
+
+REGISTER-SLAVE-MACPTR slave-macptr master-macptr
+  Registers a macptr as the slave of a terminable macptr.
+A master terminable macptr is not terminated until all of its slaves
+have been GC'ed (and terminated if appropriate).
+Raise an error if master-macptr is not a terminable macptr.
+
+TERMINABLE-MACPTR-P thing
+returns t if thing is an active terminable or gcable macptr;
+otherwise returns  nil.
+
+DEACTIVATE-MACPTR macptr &key deactivate-only
+  If macptr has an associated termination action,
+cancel that action. If deactivate-only is nil, call the
+termination action before canceling it, and change
+the macptr to a dead macptr.  Raise an error if macptr
+is not a macptr.  Return nil if not a terminable macptr
+or if deactivate-only is nil and disposal function returns
+nil;  otherwise return true.
+
+|#
+
+(in-package "CCL")
+
+(provide "MACPTR-TERMINATION")
+
+(export '(set-post-egc-hook-enabled-p post-egc-hook-enabled-p
+          add-pre-gc-hook delete-pre-gc-hook add-post-gc-hook delete-post-gc-hook
+          make-terminable-macptr register-slave-macptr terminable-macptr-p deactivate-macptr))
+
+; Map slave-macptr to master-macptr
+; This holds on to the master until the slave is GC'd
+(defvar *slave-macptrs-table*
+  (make-hash-table :test 'eq :weak :key))
+
+; Map a copy of a terminable slave to its master
+; This holds on to the master until the slave is terminated
+(defvar *terminable-slaves-table*
+  (make-hash-table :test 'eql))
+
+(defun register-slave-macptr (slave-macptr master-macptr)
+  (unless (terminable-macptr-p master-macptr)
+    (error "~s is not a terminable macptr" master-macptr))
+  (unless (macptrp slave-macptr)
+    (setq slave-macptr (require-type slave-macptr 'macptr)))
+  (if (terminable-macptr-p slave-macptr)
+    (setf (gethash (%inc-ptr slave-macptr 0) *terminable-slaves-table*) master-macptr)
+    (setf (gethash slave-macptr *slave-macptrs-table*) master-macptr)))
+
+(defun dispose-gcable-macptr (macptr)
+  (let ((flags (macptr-flags macptr)))
+    ; we set to $flags_normal before calling the dispose function.
+    ; (client code can and does depend on this).
+    ; hence, if it aborts a memory leak results.
+    ; if we were to wait until after the user function returns
+    ; to put in the $flags_normal, then it will get called again
+    ; and might try to free something twice: crash!
+    (setf (macptr.flags macptr) #.$flags_normal)
+    (case flags
+      (#.$flags_normal nil)
+      (#.$flags_DisposHandle (#_DisposeHandle macptr) t)
+      (#.$flags_DisposPtr    (#_DisposePtr    macptr) t)
+      (#.$flags_DisposWindow (#_DisposeWindow macptr) t)
+      (#.$flags_DisposGWorld (#_DisposeGWorld macptr) t)
+      (otherwise (error "Macptr has bogus flags")))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; The PPC version uses the new general termination support
+;;;
+
+#+ppc-target
+(progn
+
+(eval-when (:compile-toplevel :execute)
+  (require "LISPEQU"))
+
+(defvar *macptr-termination-population*
+  (%cons-terminatable-alist))
+
+(defun make-terminable-macptr (macptr termination-function &key master)
+  (let* ((p (%inc-ptr macptr 0))
+         (cell (list (cons p termination-function)))
+         (population *macptr-termination-population*))
+    (without-interrupts
+     (setf (cdr cell) (population-data population)
+           (population-data population) cell))
+    (when master
+      (register-slave-macptr p master))
+    p))
+
+(defun terminable-macptr-p (thing)
+  (or (not (eql $flags_normal (macptr-flags thing)))
+      (member thing (population-data *macptr-termination-population*)
+              :key 'car)))
+
+(defun deactivate-macptr (macptr &key (deactivate-only t))
+  (unless (macptrp macptr)
+    (setq macptr (require-type macptr 'macptr)))
+  (let ((termination-function nil)
+        (population *macptr-termination-population*))
+    (flet ((test (macptr cell) (and (eq macptr (car cell)) (setq termination-function (cdr cell)))))
+      (declare (dynamic-extent #'test))
+      (without-interrupts
+       (setf (population-data population)
+             (delete macptr (population-data population)
+                     :test #'test
+                     :count 1))))
+    (when termination-function
+      (remhash macptr *terminable-slaves-table*))
+    (if deactivate-only
+      termination-function
+      (prog1
+        (if termination-function
+          (funcall termination-function macptr)
+          (progn
+            (dispose-gcable-macptr macptr)
+            (remhash macptr *slave-macptrs-table*)))
+        (macptr->dead-macptr macptr)))))
+
+; The post GC hook
+(defun terminate-macptrs ()
+  (let ((population *macptr-termination-population*)
+        list cell)
+    (loop
+      (without-interrupts
+       (setq list (population-termination-list population))
+       (unless list (return))
+       (setf cell (car list)
+             (population-termination-list population) (cdr list)
+             (cdr list) nil))
+      (let ((macptr (car cell)))
+        (if (funcall (cdr cell) macptr)
+          (remhash macptr *terminable-slaves-table*)
+          (without-interrupts
+           (setf (cdr list) (population-data population)
+                 (population-data population) list)))))))
+
+(defun macptr->dead-macptr (macptr)
+  (if (macptrp macptr)
+    (%macptr->dead-macptr macptr)
+    (macptr->dead-macptr (require-type macptr 'macptr))))
+
+
+
+; Call this before save-application.
+; It makes no sense to keep terminable macptrs around after that.
+; They'll be dead-macptr's then causing lots of grief.
+(defun clear-terminable-macptrs ()
+  (let ((population *macptr-termination-population*))
+    (setf (population-data population) nil
+          (population-termination-list population) nil)
+    (clrhash *slave-macptrs-table*)))
+
+)  ; end of #+ppc-target progn
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; The 68K version needs to work harder.
+;;; It also requires a kernel patch.
+;;; It won't work in a vanilla MCL 3.0 (or 2.0).
+;;;
+
+#-ppc-target
+(progn
+
+(eval-when (:compile-toplevel :execute)
+  (require "LAPMACROS")
+
+  (defconstant $flags_terminable 5)
+  (defconstant $flags_terminate_when_ready 6)
+  
+  (defconstant $gc-finalize-macptrs-bit (- 26 $fixnumshift))
+  (defconstant $gc-post-egc-hook-p (- 25 $fixnumshift))
+  
+  (def-accessors () %svref
+    nil                                   ; macptr.ptr
+    nil                                   ; macptr.flags
+    macptr.link
+    macptr.id
+    macptr-size)
+  
+  ; This is not exported from the kernel. In future MCL versions, it
+  ; will be and this definition will not be necessary.
+  ; This value came from the lisp-8.map file for the new kernel
+  (defconstant $gcable_ptrs (- #xD84 #x1000))
+  )
+
+(defun gcable-ptrs-head ()
+  (lap-inline ()
+    (move.l (a5 $gcable_ptrs) acc)))
+
+(defun (setf macptr-flags) (value p)
+  (setq p (require-type p 'macptr))
+  (setq value (require-type value 'fixnum))
+  (lap-inline (value p)
+    (move.l arg_z atemp0)
+    (getint arg_y)
+    (move.l arg_y (atemp0 $macptr.flags)))
+  value)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; cons-terminable-macptr & map-over-terminated-macptrs
+;;; are the low-level interface to this package.
+;;;
+
+; Create a terminable macptr from another macptr
+(defun cons-terminable-macptr (macptr &optional (id 0))
+  (setq macptr (require-type macptr 'macptr))
+  (setq id (require-type id 'fixnum))
+  (let ((p (make-uvector macptr-size $v_macptr :initial-element 0)))
+    (%setf-macptr p macptr)
+    (setf (macptr-flags p) $flags_terminable
+          (macptr.id p) id)
+    (lap-inline (p)
+      (move.l arg_z atemp0)
+      (move.l (a5 $gcable_ptrs) (svref atemp0 macptr.link))
+      (move.l atemp0 (a5 $gcable_ptrs)))
+    p))
+
+; Calls function with each terminated macptr.
+; If function returns NIL, will not reap the macptr;
+; it will reappear in the list of terminated macptrs after the next GC
+; (assuming FUNCTION didn't store it somewhere).
+(defun map-over-terminated-macptrs (function)
+  (declare (fixnum *gc-event-status-bits*))
+  (when (logbitp $gc-finalize-macptrs-bit *gc-event-status-bits*)
+    (let ((done? nil))
+      (unwind-protect
+        (let ((p (gcable-ptrs-head)))
+          (setq *gc-event-status-bits*
+                (the fixnum 
+                     (bitclr $gc-finalize-macptrs-bit *gc-event-status-bits*)))
+          (loop
+            (when (eql 0 p)
+              (return))
+            (when (eql $flags_terminate_when_ready (macptr-flags p))
+              ; We set to $flags_normal BEFORE calling the user function.
+              ; Hence, if it aborts a memory leak results.
+              ; If we were to wait until after the user function returns
+              ; to put in the $flags_normal, then it will get called again
+              ; and might try to free something twice: CRASH!
+              (setf (macptr-flags p) $flags_normal)
+              (unless (funcall function p)
+                (setf (macptr-flags p) $flags_terminable)))
+            (setq p (macptr.link p)))
+          (setq done? t))
+        (unless done?
+          (setq *gc-event-status-bits*
+                (the fixnum
+                     (bitset $gc-finalize-macptrs-bit *gc-event-status-bits*))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; make-terminable-macptr is the user entry point.
+;;;
+
+; This table cannot be weak on key since hash tables are reaped before gcable-macptrs.
+(defvar *termination-functions-table* (make-hash-table :test 'eql))
+
+(defvar *terminable-macptr-max-id* most-negative-fixnum)
+(defvar *free-terminable-macptr-ids* nil)
+
+(defun make-terminable-macptr (macptr termination-function &key master)
+  (let* ((id (or (pop *free-terminable-macptr-ids*)
+                 (incf *terminable-macptr-max-id*)))
+         (p (cons-terminable-macptr macptr id)))
+    (setf (gethash id *termination-functions-table*) termination-function
+          (gethash nil *termination-functions-table*) nil)       ; clear cache
+    (when master
+      (register-slave-macptr p master))
+    p))
+
+(defun terminable-macptr-p (thing)
+  (not (eql $flags_normal (macptr-flags thing))))
+
+(defun terminate-macptrs ()
+  (map-over-terminated-macptrs
+   #'(lambda (p)
+       (let* ((id (macptr.id p))
+              (termination-function (gethash id *termination-functions-table*)))
+         (if termination-function
+           (when (funcall termination-function p)
+             (remhash id *termination-functions-table*)
+             (remhash p *terminable-slaves-table*)
+             (push id *free-terminable-macptr-ids*)
+             t)
+           (progn
+             (cerror "Continue." "Can't find ~s in ~s"
+                     p '*termination-functions-table*)
+             t))))))
+
+(defun deactivate-macptr (macptr &key (deactivate-only t))
+  (setq macptr (require-type macptr 'macptr))
+  (let ((flags (macptr-flags macptr))
+        (termination-function nil))
+    (unless (eql $flags_normal flags)
+      (when (or (eql flags $flags_terminable)
+                (eql flags $flags_terminate_when_ready))
+        (setf (macptr-flags macptr) $flags_normal)
+        (let ((id (macptr.id macptr)))
+          (setq termination-function
+                (if deactivate-only
+                  t
+                  (gethash id *termination-functions-table*)))
+          (remhash id *termination-functions-table*)
+          (push id *free-terminable-macptr-ids*)
+          (remhash macptr *terminable-slaves-table*)))
+      (if deactivate-only
+        termination-function
+        (prog1
+          (if termination-function
+            (funcall termination-function macptr)
+            (progn
+              (dispose-gcable-macptr macptr)
+              (remhash macptr *slave-macptrs-table*)))
+          (macptr->dead-macptr macptr))))))
+
+#+ccl-3
+(defun macptr->dead-macptr (macptrObject)
+  (require-type macptrObject 'macptr)
+  (lap-inline ()
+    (:variable macptrobject)
+    (move.l (varg macptrObject) atemp0)
+    (set_vsubtype ($ $v_badptr) atemp0 da))
+  macptrObject)
+  
+#-ccl-3
+(defun macptr->dead-macptr (macptrObject)
+  (require-type macptrObject 'macptr)
+  (lap
+    (move.l (varg macptrObject) atemp0)
+    (move.b ($ $v_badptr) (atemp0 $v_subtype)))
+  macptrObject)
+
+; Call this before save-application.
+; It makes no sense to keep terminable macptrs around after that.
+; They'll be dead-macptr's then causing lots of grief.
+(defun clear-terminable-macptrs ()
+  (clrhash *termination-functions-table*)
+  (clrhash *slave-macptrs-table*))
+
+)  ; End of #-ppc-target progn
+
+(pushnew 'clear-terminable-macptrs *save-exit-functions*)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Backward compatibility for the gc-hook maintenance functions.
+;;;
+
+(defun add-pre-gc-hook (hook)
+  (add-gc-hook hook :pre-gc))
+
+(defun delete-pre-gc-hook (hook)
+  (remove-gc-hook hook :pre-gc))
+
+(defun add-post-gc-hook (hook)
+  (add-gc-hook hook :post-gc))
+
+(defun delete-post-gc-hook (hook)
+  (remove-gc-hook hook :post-gc))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Enabling the ccl::*post-gc-hook* after EGC
+;;;
+
+#|  ; These are built in now
+
+(defun post-egc-hook-enabled-p ()
+  (declare (fixnum *gc-event-status-bits*))
+  (logbitp $gc-post-egc-hook-p *gc-event-status-bits*))
+
+(defun set-post-egc-hook-enabled-p (value)
+  (declare (fixnum *gc-event-status-bits*))
+  (setq *gc-event-status-bits* 
+        (if (setq value (not (null value)))
+          (the fixnum (bitset $gc-post-egc-hook-p *gc-event-status-bits*))
+          (the fixnum (bitclr $gc-post-egc-hook-p *gc-event-status-bits*))))
+  value)
+
+|#
+  
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Install the hook
+;;;
+
+(add-post-gc-hook 'terminate-macptrs)
Index: /branches/new-random/library/openmcl-gtk-support.lisp
===================================================================
--- /branches/new-random/library/openmcl-gtk-support.lisp	(revision 13309)
+++ /branches/new-random/library/openmcl-gtk-support.lisp	(revision 13309)
@@ -0,0 +1,73 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Opensourced MCL is free software; you can redistribute it and/or
+;;;   modify it under the terms of the GNU Lesser General Public
+;;;   License as published by the Free Software Foundation; either
+;;;   version 2.1 of the License, or (at your option) any later version.
+;;;
+;;;   Opensourced MCL is distributed in the hope that it will be useful,
+;;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;;;   Lesser General Public License for more details.
+;;;
+;;;   You should have received a copy of the GNU Lesser General Public
+;;;   License along with this library; if not, write to the Free Software
+;;;   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (use-interface-dir :GTK2))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (open-shared-library "libgnomeui-2.so"))
+
+
+;;; All arguments (including the first, required one) should
+;;; be strings.  This is supposed to be called from a C main
+;;; function; it picks off gtk+-specific arguments from the
+;;; caller's argv and deletes them from that C string vector.
+;;; I don't know how to suppress any messages that this call
+;;; might generate.
+(defun gtk-init (arg &rest args)
+  (declare (dynamic-extent args))
+  (push arg args)
+  (with-string-vector (argv args)
+    (rlet ((argvp (* t))
+           (argcp :signed))
+     (setf (%get-ptr argvp) argv
+           (%get-long argcp) (length args))
+       (#_gtk_init argcp argvp))))
+
+;;; Run this every 10 ticks.  (There seem to be about 100 ticks
+;;; per second.)
+#-openmcl-native-threads
+(def-load-pointers gtk-task ()
+  (%install-periodic-task 'gtk-task
+			  #'(lambda ()
+			      (do* ()
+				   ((eql (#_gtk_events_pending) 0))
+                              (#_gtk_main_iteration)))
+                        10))
+
+;;; Ensure that GTK's initialized whenever this file's loaded
+;;; and whenever a saved image starts up.  (If an application
+;;; needs to defer GTK initialization, *GTK-AUTO-INITIALIZE*
+;;; can be set to nil to suppress this behavior.)
+
+;;; Used in error reporting and to provide default window titles
+(defvar *gtk-init-application-name* "Clozure CL")
+
+(defvar *gtk-init-arguments* ())
+(defvar *gtk-auto-initialize* t)
+
+(def-load-pointers initialize-gtk ()
+  (when *gtk-auto-initialize*
+    (apply #'gtk-init *gtk-init-application-name* *gtk-init-arguments*)))
+
Index: /branches/new-random/library/oprofile.txt
===================================================================
--- /branches/new-random/library/oprofile.txt	(revision 13309)
+++ /branches/new-random/library/oprofile.txt	(revision 13309)
@@ -0,0 +1,155 @@
+Using the Linux oprofile system-level profiler with CCL
+=======================================================
+
+'oprofile' (<http://oprofile.sourceforge.net>) is a system-level profiler
+that's available for most modern Linux distributions.
+
+Use of oprofile and its companion programs isn't really documented here;
+what -is- described is a way of generating symbolic information that
+enables profiling summaries generated by the 'opreport' program to
+identify lisp functions meaningfully.
+
+
+Generating a lisp image for use with oprofile
+---------------------------------------------
+
+Modern Linux uses the 'ELF" (Executable and Linking Format) object
+file format; the oprofile tools can associate symbolic names with
+addresses in a memory-mapped file if that file appears to be an
+ELF object file and if it contains ELF symbol information that
+describes those memory regiions.  So, the general idea is to make
+a lisp heap image that looks enough like an ELF shared library
+to fool the oprofile tools (we don't actually load heap images
+via ELF dynamic linking technology, but we can make it look like
+we did.)
+
+Prerequisites
+-------------
+
+1) oprofile itself, which is almost certainly available via your
+distributions's package management system if not already preinstalled.
+2) 'libelf', which provides utilities for reading and writing ELF
+files (and is likewise likely preinstalled or readily installable.)
+
+Generating ELF symbols for lisp functions.
+-----------------------------------------
+In order to create a lisp heap image which can be used for oprofile-
+based profiling, we need to:
+
+1) load any code that we want to profile
+2) generate a file that contains ELF symbol information describing
+the names and addresses of all lisp functions.
+
+This step involves doing (from within CCL)
+
+? (require "ELF")
+"ELF"
+("ELF")
+
+? (ccl::write-elf-symbols-to-file "home:elf-symbols")
+
+The argument to CCL::WRITE-ELF-SYMBOLS-TO-FILE can be any writable
+pathname.  The function will do whatever's necessary to nail lisp
+functions down in memory (so that they aren't moved by GC), then
+write an ELF object file to the indicated pathname.  This typically
+takes a few seconds.
+
+3) Generating a lisp heap image in which the ELF symbols generated
+in the previous step are prepended.
+
+The function CCL:SAVE-APPLICATION provides a :PREPEND-KERNEL argument,
+which is ordinarily used to save a standalone application in which
+the kernel and heap image occupy a single file.  :PREPEND-KERNEL
+doesn't really care what it's prepending to the image, and we can
+just as easily ask it to prepend the ELF symbol file generated in
+the previous step.
+
+? (save-application "somewhere/image-for-profiling" :prepend-kernel
+"home:elf-symbols")
+
+If you then run
+
+shell> ccl64 somewhare/image-for-profiling
+
+any lisp code sampled by oprofile in that image will be identified
+"symbolically" by opreport.
+
+Example
+-------
+;;; Define some lisp functions that we want to profile and save
+;;; a profiling-enabled image.  In this case, we just want to 
+;;; define the FACTORIAL funcion, to keep things simple.
+? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n)))))
+FACT
+? (require "ELF")
+"ELF"
+("ELF")
+? (ccl::write-elf-symbols-to-file "home:elf-symbols")
+"home:elf-symbols"
+? (save-application "home:profiled-ccl" :prepend-kernel "home:elf-symbols")
+
+;;; Setup oprofile with (mostly) default arguments.  This example was
+;;; run on a Fedora 8 system where an uncompressed 'vmlinux' kernel
+;;; image isn't readily available.
+
+;;; Note that use of 'opcontrol' generally requires root access, e.g.,
+;;; 'sudo' or equivalent:
+
+[~] gb@rinpoche> sudo opcontrol --no-vmlinux --setup
+
+;;; Start the profiler
+
+[~] gb@rinpoche> sudo opcontrol --start
+Using 2.6+ OProfile kernel interface.
+Using log file /var/lib/oprofile/samples/oprofiled.log
+Daemon started.
+Profiler running.
+
+;;; Start CCL with the "profiled-ccl" image created above.
+;;; Invoke "(FACT 10000)"
+
+[~] gb@rinpoche> ccl64 profiled-ccl 
+Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk  (LinuxX8664)!
+? (null (fact 10000))
+NIL
+? (quit)
+
+;;; We could stop the profiler (opcontrol --stop) here; instead,
+;;; we simply flush profiling data to disk, where 'opreport' can
+;;; find it.
+
+[~] gb@rinpoche> sudo opcontrol --dump
+
+;;; Ask opreport to show us where we were spending time in the
+;;; 'profiled-ccl' image.
+
+[~] gb@rinpoche> opreport -l profiled-ccl | head
+CPU: Core 2, speed 1596 MHz (estimated)
+Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
+samples  %        symbol name
+6417     65.2466  <Compiled-function.(:INTERNAL.MULTIPLY-UNSIGNED-BIGNUM-AND-1-DIGIT-FIXNUM.MULTIPLY-BIGNUM-AND-FIXNUM).(Non-Global)..0x30004002453F>
+3211     32.6487  <Compiled-function.%MULTIPLY-AND-ADD4.0x300040000AAF>
+17        0.1729  <Compiled-function.%%ONE-ARG-DCODE.0x3000401740AF>
+11        0.1118  <Compiled-function.%UNLOCK-RECURSIVE-LOCK-OBJECT.0x30004007F7DF>
+10        0.1017  <Compiled-function.AUTO-FLUSH-INTERACTIVE-STREAMS.0x3000404ED6AF>
+7         0.0712  <Compiled-function.%NANOSLEEP.0x30004040385F>
+7         0.0712  <Compiled-function.%ZERO-TRAILING-SIGN-DIGITS.0x300040030F3F>
+
+I think that we can conclude that (FACT 10000) mostly involves multiplying
+bignums by small fixnums.
+
+Issues
+------
+CCL::WRITE-ELF-SYMBOLS-TO-FILE currently only works on x86-64; it certainly
+-could- be made to work on ppc32/ppc64 as well.
+
+So far, no one has been able to make oprofile/opreport options that're
+supposed to generate call-stack info generate meaningful call-stack info.
+
+As of a few months ago, there was an attempt to provide symbol info
+for oprofile/opreport "on the fly", e.g., for use in JIT compilation
+or other incremental compilations scenarios.  That's obviously more nearly
+The Right Thing, but it might be awhile before that experimental code
+makes it into widespread use.
+
+
Index: /branches/new-random/library/parse-ffi.lisp
===================================================================
--- /branches/new-random/library/parse-ffi.lisp	(revision 13309)
+++ /branches/new-random/library/parse-ffi.lisp	(revision 13309)
@@ -0,0 +1,1485 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(defvar *parse-ffi-target-ftd* *target-ftd*)
+(defvar *ffi-lisp-readtable* (copy-readtable nil))
+(defvar *ffi-ordinal* -1)
+(defpackage "C" (:use))
+(defvar *lparen-symbol* (intern "(" (find-package "C")))
+(defvar *rparen-symbol* (intern ")" (find-package "C")))
+(defvar *leftbracket-symbol* (intern "[" (find-package "C")))
+(defvar *rightbracket-symbol* (intern "]" (find-package "C")))
+(defvar *sharp-symbol* (intern "#" (find-package "C")))
+(defvar *sharp-sharp-symbol* (intern "##" (find-package "C")))
+(defvar *comma-symbol* (intern "," (find-package "C")))
+
+
+(defstruct (ffi-macro (:include ffi-type))
+  args
+  expansion
+  disposition
+  tokens
+  expression )
+
+(defstruct (ffi-enum (:include ffi-type)))
+
+(defvar *ffi-typedefs*)
+(defvar *ffi-global-typedefs* nil)
+(defvar *ffi-unions*)
+(defvar *ffi-global-unions* nil)
+(defvar *ffi-transparent-unions* nil)
+(defvar *ffi-global-transparent-unions* nil)
+(defvar *ffi-structs*)
+(defvar *ffi-global-structs* nil)
+(defvar *ffi-functions*)
+(defvar *ffi-global-functions* nil)
+(defvar *ffi-global-constants* nil)
+(defvar *ffi-global-vars* nil)
+(defvar *ffi-objc-classes* nil)
+(defvar *ffi-global-objc-classes* nil)
+(defvar *ffi-global-objc-messages* nil)
+;;; Some things are just too hard to parse, but are important.
+;;; Override those things with simpler versions.
+(defvar *ffi-macro-overrides*
+  '((:macro ("{override}" 0) "_IOC_TYPECHECK ( t )" "sizeof(t)")))
+
+(defvar *ffi-void-reference* '(:primitive :void))
+
+
+
+(defun find-or-create-ffi-struct (string)
+  (or (gethash string *ffi-structs*)
+      (setf (gethash string *ffi-structs*)
+            (make-ffi-struct :string string
+                             :name (unless (digit-char-p (schar string 0))
+                                     (escape-foreign-name string))))))
+
+(defun find-or-create-ffi-union (string)
+  (or (gethash string *ffi-unions*)
+      (setf (gethash string *ffi-unions*)
+            (make-ffi-union :string string
+                            :name (unless (digit-char-p (schar string 0))
+                                    (escape-foreign-name string))))))
+
+(defun find-or-create-ffi-transparent-union (string)
+  (or (gethash string *ffi-transparent-unions*)
+      (setf (gethash string *ffi-transparent-unions*)
+            (make-ffi-transparent-union :string string
+                                        :name (unless (digit-char-p (schar string 0))
+                                                (escape-foreign-name string))))))
+
+(defun find-or-create-ffi-objc-class (string)
+  (or (gethash string *ffi-objc-classes*)
+      (setf (gethash string *ffi-objc-classes*)
+            (make-ffi-objc-class :string string
+                                 :name (escape-foreign-name string)))))
+
+(defun find-or-create-ffi-objc-message (string)
+  (or (gethash string *ffi-global-objc-messages*)
+      (setf (gethash string *ffi-global-objc-messages*)
+            (make-ffi-objc-message :string string))))
+
+(defun find-or-create-ffi-typedef (string)
+  (or (gethash string *ffi-typedefs*)
+      (setf (gethash string *ffi-typedefs*)
+            (make-ffi-typedef :string string
+                              :name (escape-foreign-name string)))))
+
+(defun eval-complex-c-expression (string constant-alist)
+  (declare (ignore string constant-alist)))
+
+(defun eval-c-float-string (string)
+  (setq string (nstring-upcase string))
+  ;; Make the c float string (which may contain trailing garbage)
+  ;; look enough like a lisp float string that READ-FROM-STRING will
+  ;; work.
+  ;; There can be some trailing garbage on the string, or it might
+  ;; end in a decimal point.
+  ;; The trailing garbage might be a size specifier : #\L or #\F,
+  ;; to denote a LONG-DOUBLE or a (single) FLOAT.
+  ;; MCL can't deal with LONG-DOUBLEs, and will assume that an
+  ;; unqualified float constant is a SINGLE-FLOAT (or whatever
+  ;; *READ-DEFAULT-FLOAT-FORMAT* says.  We may have to add or
+  ;; change an exponent marker.
+  (let* ((lastpos (1- (length string)))
+         (lastchar (schar string lastpos))
+         (size :double))
+    (case lastchar
+      (#\L (setq size :long-double) (setf (schar string lastpos) #\Space))
+      (#\F (setq size :single) (setf (schar string lastpos) #\Space))
+      (#\. (setq string (concatenate 'string string "0"))))
+    (unless (eq size :long-double)
+      (let* ((epos (position #\E string))
+             (dpos (position #\D string)))
+        (if (eq size :double)
+          (if epos
+            (setf (schar string epos) #\d)
+            (setq string (concatenate 'string string "d0")))
+          (if dpos
+            (setf (schar string dpos) #\e))))
+      (values (ignore-errors (let* ((*readtable* *ffi-lisp-readtable*))
+                               (read-from-string string)))))))
+
+(defun read-c-number (stream char)
+  (loop collect char into chars
+        with class = :integer
+        with hex = nil
+        with octal = (eql char #\0)
+        do (setq char (read-char stream nil nil))
+        while (or (find char "0123456789abcdefABCDEFxulXUL.")
+                  (and (find char "+-")
+                       (char-equal (car (last chars)) #\e)))   ;signed exponent
+        do (cond ((char-equal char #\x) 
+                  (setq hex t octal nil))
+                 ((and (not hex) (or (char-equal char #\.) (char-equal char #\e)))
+                  (setq class :float)))
+        finally
+        (when char (unread-char char stream))
+        (setq chars (coerce chars 'string))
+        (if (eq class :integer)
+          (return
+            (values
+             (ignore-errors
+               (parse-integer chars
+                              :start (if hex 2 0)
+                              :radix (if hex 16 (if octal 8 10))
+                              :junk-allowed t))))
+          (return (eval-c-float-string chars)))))
+
+(defun eval-c-number (string char)
+  (loop collect char into chars
+        with class = :integer
+        with hex = nil
+        with octal = (eql char #\0)
+        with len = (length string)
+        with i = 0
+        do (setq char (if (< (incf i) len) (schar string i)))
+        while (or (find char "0123456789abcdefABCDEFxulXUL.")
+                  (and (find char "+-")
+                       (char-equal (car (last chars)) #\e)))   ;signed exponent
+        do (cond ((char-equal char #\x) 
+                  (setq hex t octal nil))
+                 ((and (not hex) (or (char-equal char #\.) (char-equal char #\e)))
+                  (setq class :float)))
+        finally
+          (setq chars (coerce chars 'string))
+          (if (eq class :integer)
+            (return
+              (values
+               (ignore-errors
+                 (parse-integer chars
+                                :start (if hex 2 0)
+                                :radix (if hex 16 (if octal 8 10))
+                                :junk-allowed t))))
+            (return (eval-c-float-string chars)))))
+
+;;; For our purposes (evaluating constant expressions in C macros),
+;;; we don't have to get this exactly right (since the result is
+;;; only going to be used in a size-of or cast operation.)
+;;; All pointer types would therefore look identical.
+
+(defvar *the-ffi-pointer-type* (parse-foreign-type '(* t)))
+
+;;; If we don't get this right the first time, we never will;
+;;; if there's nothing better, just return the void type.
+
+(defvar *the-ffi-void-type* (parse-foreign-type :void))
+
+(defun parse-c-ffi-type (spec)
+  (flet ((parse-it-or-lose (spec)
+           (or (ignore-errors (parse-foreign-type spec))
+               *the-ffi-void-type*))
+         (make-type-name (name)
+	   (escape-foreign-name (string name))))
+    (cond ((eq (car (last spec)) 'c::*) *the-ffi-pointer-type*)
+          ((member (car spec) '(c::|struct| c::|union|))
+           (parse-it-or-lose (mapcar #'make-type-name spec)))
+          ((null (cdr spec))
+           (parse-it-or-lose (make-type-name (car spec))))
+          (t
+           ;;; A qualified primitive type
+           (let* ((primitive (parse-it-or-lose (make-type-name (car (last spec))))))
+             (if (eq primitive *the-ffi-void-type*)
+               primitive
+               (let* ((long 0)
+                      (explicitly-signed nil))
+                 (declare (fixnum long))
+                 (if
+                   (dolist (token (butlast spec) t)
+                     (case token
+                       (c::|unsigned| (setq explicitly-signed :unsigned))
+                       (c::|signed| (setq explicitly-signed :signed))
+                       (c::|long| (incf long))
+                       (c::|short| (decf long))
+                       (t (return nil))))
+                   (cond ((typep primitive 'foreign-integer-type)
+                          (let* ((prim-bits (foreign-type-bits primitive))
+                                 (prim-signed (foreign-integer-type-signed primitive)))
+                            (if (> long 1)
+                              (make-foreign-integer-type :bits 64
+                                                         :signed (or (not explicitly-signed)
+                                                                     (eq explicitly-signed :signed)))
+                              (if (< long 0)
+                                (make-foreign-integer-type :bits 16
+                                                           :signed (or (not explicitly-signed)
+                                                                       (eq explicitly-signed :signed)))
+                                (if (= long 1)
+                                  (make-foreign-integer-type :bits 32
+                                                             :signed (or (not explicitly-signed)
+                                                                         (eq explicitly-signed :signed)))
+                                  (make-foreign-integer-type :bits prim-bits
+                                                             :signed
+                                                             (case explicitly-signed
+                                                               (:signed t)
+                                                               (:unsigned nil)
+                                                               (t prim-signed))))))))
+                         ((and (= long 1)
+                               (typep primitive 'foreign-double-float-type))
+                          (parse-it-or-lose :long-double))
+                         (t *the-ffi-void-type*))
+                   *the-ffi-void-type*))))))))
+                                                               
+(defun eval-parsed-c-expression (expression constant-alist)
+  (if (atom expression)
+    (if (identifierp expression)
+      (find-constant expression constant-alist)
+      (if (typep expression 'character)
+        (char-code expression)
+        expression))
+    (let* ((operator (car expression))
+           (operands (cdr expression))
+           (noperands (length operands)))
+      (case operator
+        (c::resolve-type (let* ((foreign-type  (ignore-errors (parse-c-ffi-type (car operands)))))
+                           (when foreign-type
+                             (setf (cdr expression) nil
+                                   (car expression) foreign-type)
+                             )))
+        (c::curly-bracketed-list ())
+        (t
+         (if (typep operator 'foreign-type)
+           operator
+         (when (do* ((tail (cdr expression) (cdr tail)))
+                    ((null tail) t)
+                 (let* ((expr (car tail))
+                        (value (eval-parsed-c-expression expr constant-alist)))
+                   (unless value (return))
+                   (unless (eq expr value)
+                     (rplaca tail value))))
+           (case noperands
+             (1
+              (let* ((operand (cadr expression)))
+                (case operator
+                  (c::! (if (zerop operand) 1 0))
+                  (c::- (- operand))
+		  (c::+ operand)
+                  (c::~ (lognot operand))
+                  (c::size-of
+                   (let* ((bits (ignore-errors (ensure-foreign-type-bits operand))))
+                     (when bits
+                       (ash (+ bits 7) -3))))
+                  (t
+                   ;(break "~s" expression)
+		   nil))))
+             (2
+              (let* ((a (car operands))
+                     (b (cadr operands)))
+                (case operator
+                  (c::<< (ash a b))
+                  (c::>> (ash a (- b)))
+                  (c::* (* a b))
+                  (c::/ (if (zerop b) 0 (values (floor a b)))) ; or maybe TRUNCATE ?
+                  (c::+ (+ a b))
+                  (c::- (- a b))
+                  (c::\| (logior a b))
+                  (c::\& (logand a b))
+                  (c::cast (if (foreign-typep (setq b (eval-parsed-c-expression b constant-alist)) a)
+                             b
+                             (if (and (typep a 'foreign-integer-type)
+                                      (not (foreign-integer-type-signed a))
+                                      (typep b 'integer)
+                                      (not (> (integer-length b)
+                                              (foreign-integer-type-bits a))))
+                               (logand b (1- (ash 1 (foreign-integer-type-bits a))))
+                               (if (and (typep a 'foreign-pointer-type)
+                                        (typep b 'integer)
+                                        (<= (integer-length b) 16))
+                                 (progn                                   
+                                   (%int-to-ptr (logand b #xffffffff)))))))
+                               
+                                           
+                  (t 
+		   ;(break "binary op = ~s ~s ~s" operator a b)
+		   nil))))
+             (t
+              ;(break "expression = ~s" expression)
+	      nil)))))))))
+
+(defun eval-c-expression (macro constant-alist macro-table)
+  (let* ((string (ffi-macro-expansion macro))
+         (len (length string)))
+    (if (= len 0)
+      1
+      (progn
+        (unless (ffi-macro-tokens macro)
+          (let* ((transitive (gethash (ffi-macro-expansion macro) macro-table)))
+            (if transitive
+              (setf (ffi-macro-tokens macro) transitive
+                    (gethash (ffi-macro-name macro) macro-table) transitive)
+              (multiple-value-bind (tokens error) (ignore-errors (string-to-tokens string))
+                (if error
+                  (setf (ffi-macro-disposition macro) :bad-tokenize)
+                  (setf (ffi-macro-tokens macro) tokens))))))
+        (unless (ffi-macro-expression macro)
+          (let* ((tokens (ffi-macro-tokens macro)))
+            (when tokens
+              (multiple-value-bind (expression error)
+                  (ignore-errors (parse-c-expression tokens
+                                                     :constants constant-alist
+                                                     :expand-macros macro-table ))
+                (if (or error (null expression))
+                  (progn
+                    ;(format t "~& parse failed: ~s ~s" (ffi-macro-name macro)  string)
+                    ;(format t "~&  tokens = ~s, error = ~a" tokens error)
+                    (setf (ffi-macro-disposition macro) :bad-parse))
+                  (setf (ffi-macro-expression macro) expression))))))
+        (let* ((expression (ffi-macro-expression macro)))
+          (when expression (values (eval-parsed-c-expression expression constant-alist) t)))))))
+
+;;; Repeatedly iterate over the macros until nothing new's defined.
+(defun process-defined-macros (ffi-macros constant-alist parameterized-macros)
+  (let* ((new-def ()))
+    (loop
+        (setq new-def nil)
+        (dolist (macro ffi-macros)
+          (unless (ffi-macro-disposition macro)
+            (let* ((expansion (ffi-macro-expansion macro))
+                   (name (ffi-macro-name macro))
+                   (value nil))
+              (if (string= name expansion)
+                (setf (ffi-macro-disposition macro) t)
+                (when (setq value (eval-c-expression macro constant-alist parameterized-macros))
+                  (push (cons name value) constant-alist)
+                  (setf (ffi-macro-disposition macro) t)
+                  (setq new-def t))))))
+        (unless new-def
+          (return (values (reverse constant-alist) nil))))))
+
+(defun reference-ffi-type (spec)
+  (case (car spec)
+    (:typedef (list :typedef (find-or-create-ffi-typedef (cadr spec))))
+    (:struct-ref (list :struct (find-or-create-ffi-struct (cadr spec))))
+    (:union-ref (list :union (find-or-create-ffi-union (cadr spec))))
+    (:transparent-union-ref
+     (list :transparent-union (find-or-create-ffi-transparent-union (cadr spec))))
+    (:enum-ref `(:primitive :signed))
+    (:function `(:primitive (* t)))
+    (:pointer (list :pointer (reference-ffi-type (cadr spec))))
+    (:array (list :array (cadr spec) (reference-ffi-type (caddr spec))))
+    (:void *ffi-void-reference*)
+    (t
+     (list :primitive
+           (ecase (car spec)
+	     (:char (if (getf (ftd-attributes *parse-ffi-target-ftd*)
+                              :signed-char)
+		      '(:signed 8)
+		      '(:unsigned 8)))
+             (:signed-char  '(:signed 8))
+             (:unsigned-char '(:unsigned 8))
+             (:short '(:signed 16))
+             (:unsigned-short '(:unsigned 16))
+             ((:vec128 :unsigned-long-long-long) '(:unsigned 128))
+             (:signed-long-long-long '(:signed 128))
+             (:int '(:signed 32))
+             (:long (ecase (or
+                            (getf
+                             (ftd-attributes *parse-ffi-target-ftd*)
+                             :bits-per-long)
+                            (getf
+                             (ftd-attributes *parse-ffi-target-ftd*)
+                             :bits-per-word))
+                      (32 '(:signed 32))
+                      (64 '(:signed 64))))
+             (:unsigned  '(:unsigned 32))
+             (:unsigned-long (ecase (or
+                                     (getf
+                                      (ftd-attributes *parse-ffi-target-ftd*)
+                                      :bits-per-long)
+                                     (getf
+                                      (ftd-attributes *parse-ffi-target-ftd*)
+                                      :bits-per-word))
+                               (32 '(:unsigned 32))
+                               (64 '(:unsigned 64))))
+             (:long-long '(:signed 64))
+             ((:vec64 :unsigned-long-long) '(:unsigned 64))
+             (:float :float)
+             (:double :double)
+             (:long-double :long-float)
+             (:complex-int :complex-int)
+             (:complex-float :complex-float)
+             (:complex-double :complex-double)
+             (:complex-long-double :complex-long-float)
+             (:long-long-long :long-long-long)
+             #|(:void :void)|#)))))
+             
+             
+(defun process-ffi-fieldlist (fields)
+  (let* ((parsed-fields ()))
+    (dolist (field fields (nreverse parsed-fields))
+      (let* ((field-name (escape-foreign-name (car field)))
+             (field-descr (cadr field)))
+        (destructuring-bind (field-type offset width)
+            (cdr field-descr)
+          (push (cons field-name
+                      (ecase (car field-descr)
+                        (:field `(,(reference-ffi-type field-type) ,(ash offset 3) ,(ash width 3)))
+                        (:bitfield `((:primitive (:unsigned ,width)) ,offset ,width))))
+                parsed-fields))))))
+
+(defun process-ffi-union (form)
+  (destructuring-bind (source-info string fields &optional alignform)
+      (cdr form)
+    (declare (ignore source-info))
+    (let* ((union (find-or-create-ffi-union string)))
+      (setf (ffi-union-ordinal union) (incf *ffi-ordinal*))
+      (when alignform
+	(setf (ffi-union-alt-alignment-bits union) (cadr alignform)))
+      (unless (ffi-union-fields union)
+	(setf (ffi-union-fields union)
+	      (process-ffi-fieldlist fields)))
+      union)))
+
+(defun process-ffi-transparent-union (form)
+  (destructuring-bind (source-info string fields &optional alignform)
+      (cdr form)
+    (declare (ignore source-info))
+    (let* ((union (find-or-create-ffi-transparent-union string)))
+      (setf (ffi-transparent-union-ordinal union) (incf *ffi-ordinal*))
+      (when alignform
+	(setf (ffi-transparent-union-alt-alignment-bits union) (cadr alignform)))
+      (unless (ffi-transparent-union-fields union)
+	(setf (ffi-transparent-union-fields union)
+	      (process-ffi-fieldlist fields)))
+      union)))
+
+(defun process-ffi-struct (form)
+  (destructuring-bind (source-info string fields &optional alignform)
+      (cdr form)
+    (declare (ignore source-info))
+    (let* ((struct (find-or-create-ffi-struct string)))
+      (setf (ffi-struct-ordinal struct) (incf *ffi-ordinal*))
+      (when alignform
+	(setf (ffi-struct-alt-alignment-bits struct) (cadr alignform)))
+      (unless (ffi-struct-fields struct)
+	(setf (ffi-struct-fields struct)
+	      (process-ffi-fieldlist fields)))
+      struct)))
+
+(defun process-ffi-objc-class (form)
+  (destructuring-bind (source-info class-name superclass-form protocols ivars) (cdr form)
+    (declare (ignore source-info))
+    (let* ((class (find-or-create-ffi-objc-class class-name)))
+      (setf (ffi-objc-class-ordinal class) (incf *ffi-ordinal*))
+      (unless (ffi-objc-class-super-foreign-name class)
+        (let* ((super-name (car superclass-form)))
+          (unless (eq super-name :void)
+            (setf (ffi-objc-class-super-foreign-name class)
+                  super-name))))
+      (unless (ffi-objc-class-protocol-names class)
+        (setf (ffi-objc-class-protocol-names class) protocols))
+      (unless (ffi-objc-class-own-ivars class)
+        (setf (ffi-objc-class-own-ivars class)
+              (process-ffi-fieldlist ivars)))
+      class)))
+
+(defun process-ffi-objc-method (form)
+  (destructuring-bind (method-type source-info class-name category-name message-name arglist result-type) form
+    (declare (ignore source-info category-name))
+    (let* ((flags ()))
+      (if (or (eq method-type :objc-class-method)
+              (eq method-type :objc-protocol-class-method))
+        (setf (getf flags :class) t))
+      (if (or (eq method-type :objc-protocol-class-method)
+              (eq method-type :objc-protocol-instance-method))
+        (setf (getf flags :protocol) t))
+      (let* ((message (find-or-create-ffi-objc-message message-name))
+             (class-method-p (getf flags :class))
+             (method
+              (make-ffi-objc-method :class-name class-name
+                                    :arglist (mapcar #'reference-ffi-type
+                                                     arglist)
+                                    :result-type (reference-ffi-type
+                                                  result-type)
+                                    :flags flags)))
+        (unless (dolist (m (ffi-objc-message-methods message))
+                  (when (and (equal (ffi-objc-method-class-name m)
+                                    class-name)
+                             (eq (getf (ffi-objc-method-flags m) :class)
+                                 class-method-p))
+                    (return t)))
+          (push method (ffi-objc-message-methods message)))))))
+      
+(defun process-ffi-typedef (form)
+  (let* ((string (caddr form))
+         (def (find-or-create-ffi-typedef string)))
+    (setf (ffi-typedef-ordinal def) (incf *ffi-ordinal*))
+    (unless (ffi-typedef-type def)
+      (setf (ffi-typedef-type def) (reference-ffi-type (cadddr form))))
+    def))
+
+
+(defun process-ffi-function (form)
+  (let* ((name (caddr form))
+         (ftype (cadddr form)))
+    (make-ffi-function :string name
+                       :arglist (mapcar #'reference-ffi-type (cadr ftype))
+                       :return-value (reference-ffi-type (caddr ftype)))))
+
+(defun process-ffi-macro (form)
+  (let* ((name-form (caddr form))
+         (expansion (cadddr form))
+         (name name-form)
+         (args nil)
+         (space-pos (position #\space name-form)))
+    (when space-pos
+      (setq name (subseq name-form 0 space-pos))
+      (let* ((open-pos (position #\( name-form))
+             (close-pos (position #\) name-form)))
+        (when (and open-pos close-pos (> close-pos open-pos))
+          (let* ((arg-string (subseq name-form open-pos close-pos))
+                 (arg-tokens (ignore-errors (string-to-tokens arg-string)))
+                 (arg-names (let* ((l ()))
+                              (dolist (arg-token arg-tokens (nreverse l))
+                                (unless (or (eq arg-token 'c::|,|)
+                                            (eq arg-token *lparen-symbol*))
+                                  (push arg-token l)))))
+                 (body-tokens (ignore-errors (string-to-tokens expansion))))
+            (when (and arg-names body-tokens)
+              (setq args (list arg-names body-tokens)
+                    expansion name))))))
+    (make-ffi-macro :name name :args args :expansion expansion)))
+
+(defun process-ffi-enum (form)
+  (declare (ignore form)))
+
+(defun process-ffi-var (form)
+  (let* ((name (caddr form))
+         (type (cadddr form)))
+    (cons name (reference-ffi-type type))))
+
+(defun process-ffi-enum-ident (form)
+  (cons (caddr form) (cadddr form)))
+
+(defun ensure-referenced-type-defined (spec)
+  (declare (ignorable spec))
+  (when nil
+  (ecase (car spec)
+    (:primitive)
+    (:typedef (define-typedef-from-ffi-info (cadr spec)))
+    (:struct (ensure-struct-defined (cadr spec)))
+    (:union (ensure-union-defined (cadr spec)))
+    (:transparent-union (ensure-transparent-union-defined (cadr spec)))
+    (:pointer (ensure-referenced-type-defined (cadr spec)))
+    (:array (ensure-referenced-type-defined (caddr spec)))
+    (:function (dolist (arg (ffi-function-arglist (cadr spec)))
+                 (ensure-referenced-type-defined arg))
+               (ensure-referenced-type-defined (ffi-function-return-value (cadr spec))))
+    )))
+
+  
+(defun ensure-fields-defined (fields)
+  (dolist (f fields)
+    (let* ((ftype (cadr f)))
+      (ensure-referenced-type-defined ftype))))
+
+(defun record-global-objc-class (c)
+  (when *ffi-global-objc-classes*
+    (setf (gethash (ffi-objc-class-string c) *ffi-global-objc-classes*) c)))
+
+(defun define-objc-class-from-ffi-info (c)
+  (unless (ffi-objc-class-defined c)
+    (setf (ffi-objc-class-defined c) t)
+    (record-global-objc-class c)
+    (ensure-fields-defined (ffi-objc-class-own-ivars c))))
+
+(defun record-global-union (u)
+  (when (and *ffi-global-unions* (ffi-union-fields u))
+    (setf (gethash (ffi-union-reference u) *ffi-global-unions*) u)))
+
+(defun record-global-transparent-union (u)
+  (when (and *ffi-global-transparent-unions* (ffi-transparent-union-fields u))
+    (setf (gethash (ffi-transparent-union-reference u) *ffi-global-transparent-unions*) u)))
+
+(defun define-union-from-ffi-info (u)
+  (unless (ffi-union-defined u)
+    (setf (ffi-union-defined u) t)
+    (record-global-union u)
+    (when (ffi-union-name u)
+      (let* ((fields (ffi-union-fields u)))
+        (ensure-fields-defined fields)))))
+
+(defun define-transparent-union-from-ffi-info (u)
+  (unless (ffi-transparent-union-defined u)
+    (setf (ffi-transparent-union-defined u) t)
+    (record-global-transparent-union u)
+    (when (ffi-transparent-union-name u)
+      (let* ((fields (ffi-transparent-union-fields u)))
+        (ensure-fields-defined fields)))))
+
+(defun ensure-union-defined (u)
+  (let* ((name (ffi-union-name u)))
+    (if name
+      (define-union-from-ffi-info u)
+      (ensure-fields-defined (ffi-union-fields u)))))
+
+(defun ensure-transparent-union-defined (u)
+  (let* ((name (ffi-transparent-union-name u)))
+    (if name
+      (define-transparent-union-from-ffi-info u)
+      (ensure-fields-defined (ffi-transparent-union-fields u)))))
+
+(defun record-global-struct (s)
+  (when (and *ffi-global-structs* (ffi-struct-fields s))
+    (setf (gethash (ffi-struct-reference s) *ffi-global-structs*) s)))
+
+(defun define-struct-from-ffi-info (s)
+  (unless (ffi-struct-defined s)
+    (setf (ffi-struct-defined s) t)
+    (record-global-struct s)
+    (when (typep (ffi-struct-name s) 'keyword)
+      (let* ((fields (ffi-struct-fields s)))
+        (ensure-fields-defined fields)))))
+
+(defun ensure-struct-defined (s)
+  (let* ((name (ffi-struct-name s)))
+    (if (typep name 'keyword)
+      (define-struct-from-ffi-info s)
+      (ensure-fields-defined (ffi-struct-fields s)))))
+
+(defun record-global-typedef (def)
+  (when *ffi-global-typedefs*
+    (setf (gethash (ffi-typedef-string def) *ffi-global-typedefs*) def)))
+  
+(defun define-typedef-from-ffi-info (def)
+  (unless (ffi-typedef-defined def)
+    (setf (ffi-typedef-defined def) t)
+    (record-global-typedef def)
+    (let* ((target (ffi-typedef-type def)))
+      (unless (and (consp target)
+		   (member (car target) '(:struct :union :transparent-union :primitive)))
+	(ensure-referenced-type-defined target)))))
+
+(defun record-global-constant (name val)
+  (when *ffi-global-constants*
+    (setf (gethash name *ffi-global-constants*) val)))
+      
+(defun emit-ffi-constant (name val)
+  (record-global-constant name val))
+
+(defun record-global-var (name type)
+  (when *ffi-global-vars*
+    (setf (gethash name *ffi-global-vars*) type)))
+
+(defun emit-ffi-var (name type)
+  (record-global-var name type))
+
+
+(defun ffi-record-type-p (typeref)
+  (case (car typeref)
+    ((:struct :union :transparent-union) t)
+    (:typedef (ffi-record-type-p (ffi-typedef-type (cadr typeref))))
+    (t nil)))
+
+(defun record-global-function (ffi-function)
+  (when *ffi-global-functions*
+    (setf (gethash (ffi-function-string ffi-function) *ffi-global-functions*)
+	  ffi-function)))
+
+(defun emit-function-decl (ffi-function)
+  (let* ((args (ffi-function-arglist ffi-function))
+         (retval (ffi-function-return-value ffi-function)))
+    (if (eq (car (last args)) *ffi-void-reference*)
+      (setq args (butlast args)))
+    (dolist (arg args) (ensure-referenced-type-defined arg))
+    (ensure-referenced-type-defined retval)
+    (record-global-function ffi-function)))
+
+
+(defun read-ffi-toplevel-form (stream eof-value)
+  (loop
+    (let* ((ch (peek-char  nil stream nil eof-value)))
+      (cond ((eq ch eof-value) (return eof-value))
+            ((eql ch #\() (return (read stream nil eof-value)))
+            (t (read-line stream))))))
+
+(defun parse-ffi (inpath)
+  (let* ((*ffi-typedefs* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-unions* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-transparent-unions* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-structs* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-objc-classes* (make-hash-table :test 'string= :hash-function 'sxhash)) 
+         (argument-macros (make-hash-table :test 'equal)))
+    (let* ((defined-types ())
+           (defined-constants ())
+           (defined-macros ())
+           (defined-functions ())
+           (defined-vars ()))
+      (with-open-file (in inpath)
+        (let* ((*ffi-ordinal* -1))
+          (let* ((*package* (find-package "KEYWORD")))
+            (do* ((form (read-ffi-toplevel-form in :eof)
+                        (read-ffi-toplevel-form in :eof)))
+                 ((eq form :eof))
+              (case (car form)
+                (:struct (push (process-ffi-struct form) defined-types))
+                (:objc-class (push (process-ffi-objc-class form) defined-types))
+                ((:objc-class-method
+                  :objc-instance-method
+                  :objc-protocol-class-method
+                  :objc-protocol-instance-method
+                  )
+                 (process-ffi-objc-method form))
+                (:function (push (process-ffi-function form) defined-functions))
+                (:macro (let* ((m (process-ffi-macro form))
+                               (args (ffi-macro-args m)))
+                          (if args
+                            (setf (gethash (string (ffi-macro-name m)) argument-macros) args)
+                            (push m defined-macros))))
+                (:type (push (process-ffi-typedef form) defined-types))
+                (:var (push (process-ffi-var form) defined-vars))
+                (:enum-ident (push (process-ffi-enum-ident form) defined-constants))
+                (:enum (process-ffi-enum form))
+                (:union (push (process-ffi-union form) defined-types))
+                (:transparent-union (push (process-ffi-transparent-union form) defined-types)))))
+          (dolist (override *ffi-macro-overrides*)
+            (let* ((m (process-ffi-macro override))
+                   (args (ffi-macro-args m)))
+              (if args
+                (setf (gethash (string (ffi-macro-name m)) argument-macros) args)
+                (push m defined-macros))))
+          (multiple-value-bind (new-constants new-macros)
+              (process-defined-macros defined-macros (reverse defined-constants) argument-macros)
+	    ;; If we're really lucky, we might be able to turn some C macros
+	    ;; into lisp macros.  We can probably turn some C macros into
+	    ;; lisp constants.
+            (declare (ignore new-macros))
+            (dolist (x (reverse new-constants))
+              (emit-ffi-constant (car x) (cdr x)))
+            (dolist (x defined-vars)
+              (emit-ffi-var (car x) (cdr x)))
+            (dolist (x (sort defined-types #'< :key #'ffi-type-ordinal))
+              (typecase x
+                (ffi-struct (define-struct-from-ffi-info x))
+                (ffi-union (define-union-from-ffi-info x))
+                (ffi-transparent-union (define-transparent-union-from-ffi-info x))
+                (ffi-typedef (define-typedef-from-ffi-info x))
+                (ffi-objc-class (define-objc-class-from-ffi-info x))))
+            (dolist (f defined-functions) (emit-function-decl f))))))))
+
+(defun parse-standard-ffi-files (dirname &optional target)
+  (let* ((backend (if target (find-backend target) *target-backend*))
+         (ftd (backend-target-foreign-type-data backend))
+         (*parse-ffi-target-ftd* ftd)
+         (*target-ftd* ftd)
+         (*target-backend* backend)
+	 (d (use-interface-dir dirname ftd))
+	 (interface-dir (merge-pathnames
+			 (interface-dir-subdir d)
+			 (ftd-interface-db-directory ftd)))
+	 (*prepend-underscores-to-ffi-function-names*
+          (getf (ftd-attributes ftd) :prepend-underscores))
+	 (*ffi-global-typedefs* (make-hash-table :test 'string= :hash-function 'sxhash))
+	 (*ffi-global-unions* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-global-transparent-unions* (make-hash-table :test 'string= :hash-function 'sxhash))
+	 (*ffi-global-structs* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-global-objc-classes* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-global-objc-messages* (make-hash-table :test 'string= :hash-function 'sxhash)) 
+	 (*ffi-global-functions* (make-hash-table :test 'string= :hash-function 'sxhash))
+	 (*ffi-global-constants* (make-hash-table :test 'string= :hash-function 'sxhash))
+         (*ffi-global-vars* (make-hash-table :test 'string= :hash-function 'sxhash)))
+         
+    (dolist (f (directory (merge-pathnames ";C;**;*.ffi"
+					   interface-dir)))
+      (format t "~&~s ..." f)
+      (parse-ffi f )
+      (format t "~&"))
+    (with-new-db-file (constants-cdbm (merge-pathnames
+                                       "new-constants.cdb"
+                                       interface-dir))
+      (maphash #'(lambda (name def)
+                   (db-define-constant constants-cdbm name def))
+	       *ffi-global-constants*))
+    (with-new-db-file (types-cdbm (merge-pathnames
+				       "new-types.cdb"
+				       interface-dir))
+      (maphash #'(lambda (name def)
+		   (declare (ignore name))
+		   (save-ffi-typedef types-cdbm def))
+	       *ffi-global-typedefs*))
+    (with-new-db-file (records-cdbm (merge-pathnames
+                                     "new-records.cdb"
+                                     interface-dir))
+      (maphash #'(lambda (name def)
+		   (declare (ignore name))
+                   (save-ffi-union records-cdbm def))
+	       *ffi-global-unions*)
+      (maphash #'(lambda (name def)
+                   (declare (ignore name))
+                   (save-ffi-transparent-union records-cdbm def))
+               *ffi-global-transparent-unions*)
+                         
+      (maphash #'(lambda (name def)
+		   (declare (ignore name))
+		   (save-ffi-struct records-cdbm def))
+	       *ffi-global-structs*))
+    (with-new-db-file (function-cdbm (merge-pathnames
+					   "new-functions.cdb"
+					   interface-dir))
+      (maphash #'(lambda (name def)
+		   (declare (ignore name))
+		   (save-ffi-function function-cdbm def))
+	       *ffi-global-functions*))
+    (with-new-db-file (class-cdbm (merge-pathnames
+                                   "new-objc-classes.cdb"
+                                   interface-dir))
+      (maphash #'(lambda (name def)
+                   (declare (ignore name))
+                   (save-ffi-objc-class class-cdbm def))
+               *ffi-global-objc-classes*))
+    (with-new-db-file (vars-cdbm (merge-pathnames
+                             "new-vars.cdb"
+                             interface-dir))
+      (maphash #'(lambda (name type)
+                   (db-define-var vars-cdbm name type))
+               *ffi-global-vars*))
+    (with-new-db-file (methods-cdbm  (merge-pathnames
+                                      "new-objc-methods.cdb"
+                                      interface-dir))
+      (maphash #'(lambda (name message)
+                   (declare (ignore name))
+                   (save-ffi-objc-message methods-cdbm message))
+               *ffi-global-objc-messages*))
+    (install-new-db-files ftd d)))
+
+(defvar *c-readtable* (copy-readtable nil))
+(setf (readtable-case *c-readtable*) :preserve)
+
+
+;;; Each element of operators can be a symbol or a list of a symbol, a
+;;; function, and args All the symbols must start with the character
+;;; for which this is the macro-character fcn The entries must be in
+;;; the right order, e.g. dictionary order, so any two symbols with a
+;;; common prefix are adjacent in the list.  Furthermore each symbol
+;;; in the list must be preceded by every non-empty leading substring
+;;; of that symbol, since we only have one character of look-ahead in
+;;; the stream.
+(defun operator-macro (operators)
+  ;; The tree is an alist keyed by character (with a nil key at the end for the default)
+  ;; The cdr of each entry is either a symbol to produce, another decision tree,
+  ;; or a list of a function to call and additional arguments for the function
+  (let ((decision-tree (make-decision-tree operators)))
+    (labels ((read-c-operator (stream char)
+               (declare (ignore char))
+               (loop with decision-tree = decision-tree
+                     as char = (read-char stream nil nil)   ; eof => nil which works too
+                     as elem = (assoc char decision-tree)
+                     do (unless elem
+                          (unread-char char stream)
+                          (setq elem (assoc nil decision-tree)))
+                        (setq elem (cdr elem))
+                        (cond ((symbolp elem) 
+                               (return elem))
+                              ((symbolp (car elem)) 
+                               (return (apply (car elem) stream (cdr elem))))
+                              (t (setq decision-tree elem)))))
+             (read-c-singleton-operator (stream char)
+               (declare (ignore stream char))
+               (first operators))
+             (read-c-macro-character (stream char)
+               (declare (ignore char))
+               (apply (car decision-tree) stream (cdr decision-tree))))
+      (cond ((symbolp decision-tree) #'read-c-singleton-operator)
+            ((consp (car decision-tree)) #'read-c-operator)
+            (t #'read-c-macro-character)))))
+
+(defun make-decision-tree (operators)
+  (labels ((recurse (operators chars-so-far) ;returns new operators and decision tree element
+             (let ((next-char (aref (key (first operators))
+                                    (length chars-so-far)))
+                   (alist nil))
+               (setq chars-so-far (append chars-so-far (list next-char)))
+               (loop while operators
+                 as key = (key (first operators))
+                 while (every #'char= key chars-so-far)
+                 do (if (= (length key) (length chars-so-far))
+                      (push (cons nil (val (pop operators))) alist)
+                      (multiple-value-bind (remaining-operators elem)
+                          (recurse operators chars-so-far)
+                        (push elem alist)
+                        (setq operators remaining-operators))))
+               (values operators 
+                       (cons next-char (if (cdr alist) alist (cdar alist))))))
+           (key (operator)
+             (string (if (atom operator) operator (car operator))))
+           (val (operator)
+             (if (atom operator) operator (cdr operator))))
+    (multiple-value-bind (left-over elem) (recurse operators nil)
+      (when left-over
+        (error "Malformed operators list ~S:~S" (ldiff operators left-over) left-over))
+      (cdr elem))))
+
+;;; Doesn't support the L prefix for wide characters.  What a complete kludge!
+(defun c-read-string (stream single-quote)
+  (loop with delimiter = (if single-quote #\' #\")
+        as char = (read-char stream nil nil)
+        do (cond ((null char)
+                  (c-parse-error stream "Unmatched ~A" delimiter))
+                 ((char= char delimiter)
+
+                  (return (if single-quote
+                              (char-code (car chars))
+                              (coerce chars 'string))))
+                 ((char= char #\\)
+                  (setq char (read-char stream nil nil))
+                  (unless char (c-parse-error stream "EOF after backslash in string"))
+                  (let ((tem (assoc char '((#\n . #\newline)
+                                           (#\t . #\tab)
+                                           (#\v . #\^K)
+                                           (#\b . #\backspace)
+                                           (#\r . #\return)
+                                           (#\f . #\page)
+                                           (#\a . #\bell)
+                                           (#\\ . #\\)
+                                           (#\? . #\?)
+                                           (#\' . #\')
+                                           (#\" . #\")))))
+                    (cond (tem (setq char (cdr tem)))
+                          ((char<= #\0 char #\7)
+                           (setq char (loop while (char<= #\0 char #\7) for count from 1
+                                            with sum = 0
+                                            do (setq sum (+ (* sum 8) (digit-char-p char)))
+                                               (setq char (read-char stream nil nil))
+                                            until (= count 3)
+                                            finally 
+                                              (unread-char char stream)
+                                              (return (code-char sum)))))
+                          ((char= char #\x)
+                           (setq char (loop with sum = 0
+                                            as char = (read-char stream)
+                                            while (or (char<= #\0 char #\9)
+                                                      (char<= #\A char #\F)
+                                                      (char<= #\a char #\f))
+                                            do (setq sum (+ (* sum 16) (digit-char-p char 16)))
+                                            finally 
+                                              (unread-char char stream)
+                                              (return (code-char sum)))))))))
+        collect char into chars))
+
+(dolist (char '(#\_))
+  (set-syntax-from-char char #\A *c-readtable*))
+
+(dolist (op '( (c::! c::!=)
+               ((\" c-read-string nil))
+               (|#| |##|)            ; # and ## are pre-processor operators
+               (c::% c::%=)
+               (c::& c::&= c::&&)
+               ((\' c-read-string t))
+               (c::\()
+               (c::\))
+               (c::* c::*=)
+               (c::+ c::+= c::++)
+               (c::- c::-= c::-- c::->)
+               (c::\,)
+               (c::|.| c::|.*| c::|..| c::|...|)                 ; .01 will fail to parse as 0.01
+               (c::/ c::/= (// c-read-line-comment) (/* c-read-block-comment))
+               (c::\: c::\:\:)
+               (c::\;)
+               (c::< c::<= c::<< c::<<=)
+               (c::= c::==)
+               (c::> c::>= c::>> c::>>=)
+               (c::?)
+               (c::[)
+               (c::\\)
+               (c::])
+               (c::^ c::^=)
+               (c::{)
+               (c::\| c::\|= c::\|\|)
+               (c::})
+               (c::~)
+               ;; C++ doesn't define any meaning for these, treat them as operators
+               (c::\$)
+               (c::\@)
+               (c::\`)
+               ))
+  (set-macro-character (char (string (if (atom (car op)) (car op) (caar op))) 0)
+                       (operator-macro op)
+                       nil              ;token-terminating
+                       *c-readtable*))
+
+(dolist (char '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
+  (set-macro-character char 'read-c-number t *c-readtable*))
+
+
+(defvar *backslash-symbol* 'c::|\\|)
+
+(defvar *pending-tokens* ())
+
+(defun unread-token (token)
+  (push token *pending-tokens*)
+  token)
+
+(defun next-token (stream)
+  (if *pending-tokens*
+    (pop *pending-tokens*)
+    (do* ((tok (read-preserving-whitespace stream nil :eof)
+                       (read-preserving-whitespace stream nil :eof)))
+                 ((or (not (eq tok *backslash-symbol*))
+                      (not (eq (peek-char nil stream nil nil) #\Newline)))
+                  tok)     
+	     ;; Consume the #\newline that followed #\\.  Yecch.
+	     (read-char stream nil nil))))
+              
+(defun string-to-tokens (string)
+  (with-input-from-string (stream string)
+    (let* ((*package* (find-package "C"))
+           (*readtable* *c-readtable*)
+           (tokens ()))
+      (loop
+          (let* ((token (next-token stream)))
+            (when (eq token :eof)
+              (return (nreverse tokens)))
+            (push token tokens))))))
+
+
+(defun identifierp (token)
+  (and (symbolp token)
+       (let ((char (char (symbol-name token) 0)))
+	 (or (alpha-char-p char) (char= char #\_)))))
+
+
+(defun evaluate-type-name (x)
+  (let* ((name (car x)))
+    (if (and (atom name) nil (null (cdr x)))
+      name)))
+      
+
+(defun find-constant (x constants)
+  (when (symbolp x)
+    (cdr (assoc (string x) constants :test #'string=))))
+
+(defun find-user-or-primitive-type (x)
+  x
+  nil)
+
+(defun macro-definition (id table)
+  (gethash (string id) table))
+
+(defun expand-c-macro (name parameters arguments body stream macros-not-to-expand macro-table)
+  (let ((expansion nil))
+    (unless (= (length arguments) (length parameters))
+      (c-parse-error stream "Expected ~D argument~:P to macro ~A but got ~D argument~:P."
+			 (length parameters) name (length arguments)))
+    (loop while body
+      as token = (pop body)
+      as next = (first body)
+      as argno = (position token parameters) do
+      (cond ((and argno (eq next *sharp-sharp-symbol*)) ; parameter ## token/parameter
+	     (pop body)
+	     (setq next (pop body))
+	     (let ((next-argno (position next parameters)))
+	       (push (intern (concatenate 'string (c-stringize-token-list (nth argno arguments))
+					  (if next-argno
+					    (c-stringize-token-list (nth next-argno arguments))
+					    (c-stringize-token next))))
+		     expansion)))
+	    (argno			; normal parameter substitution
+	     (setq expansion (nreconc (expand-c-macros-in-token-list (nth argno arguments)
+                                                                     stream macros-not-to-expand
+                                                                     macro-table)
+				      expansion)))
+	    ((and (eq token *sharp-sharp-symbol*) ; token ## parameter
+		  (setq argno (position next parameters)))
+	     (pop body)
+	     (push (intern (concatenate 'string (c-stringize-token (pop expansion))
+					(c-stringize-token-list (nth argno arguments))))
+		   expansion))
+	    ((and (eq token *sharp-symbol*)	; # parameter
+		  (setq argno (position next parameters)))
+	     (pop body)
+	     (push (c-stringize-token-list (nth argno arguments)) expansion))
+	    (t (push token expansion))))
+    (expand-c-macros-in-token-list (nreverse expansion) stream
+                                   (adjoin name macros-not-to-expand)
+                                   macro-table)))
+
+(defun expand-c-macros-in-token-list (tokens stream macros-not-to-expand macro-table)
+  (loop
+      while tokens
+    as token = (pop tokens)
+    as macro = (and (symbolp token)
+                    (not (member token macros-not-to-expand))
+                    (macro-definition token macro-table))
+    if macro
+    nconc (if (eq (first macro) :none) 
+            (expand-c-macros-in-token-list (second macro) stream 
+                                           (adjoin token macros-not-to-expand) macro-table)
+            (expand-c-macro token (first macro)
+                            (let ((open (pop tokens)))
+                              (unless (eq open *lparen-symbol*)
+                                (c-parse-error
+                                 stream
+                                 "~A where open parenthesis expected after macro name ~A"
+                                 open token))
+                              (loop with done = nil
+                                    collect
+                                    (loop as token = (if tokens (pop tokens)
+                                                       (c-parse-error stream
+                                                                      "Unexpected impossible EOF"))
+                                          with level = 0
+                                          do (cond ((eq token *lparen-symbol*) (incf level))
+                                                   ((eq token *rparen-symbol*)
+                                                    (if (plusp level) (decf level) (setq done t))))
+                                                  until (or done (and (zerop level)
+                                                                      (eq token *comma-symbol*)))
+                                                  collect token)
+                                    until done))
+                            (second macro) stream macros-not-to-expand macro-table))
+    else collect token))
+
+(defun parse-c-expression (token-list &key  constants additional-constants 
+                                          expand-macros)
+  (labels ((next ()
+             (unless token-list
+               (fail "Unterminated expression or unbalanced parentheses"))
+             (pop token-list))
+           (peek ()
+             (car token-list))
+           (unread (token)
+             (push token token-list))
+           (collect-parenthesized ()
+             (loop with level = 0
+                   as token = (next)
+                   until (and (eq token *rparen-symbol*) (= level 0))
+                   collect token
+                   do (case token
+                        (#.*lparen-symbol* (incf level))
+                        (#.*rparen-symbol* (decf level)))))
+           (fail (format-string &rest format-arguments)
+             (apply #'c-parse-error nil format-string format-arguments))
+           (parse-expression ()
+             (parse-assignment))
+           (parse-assignment ()
+             (let ((left (parse-conditional)))
+               (if (eq (peek) 'c::|=|)
+                 (let ((right (progn (next) (parse-assignment))))
+                   (list 'setf left right))
+                 left)))
+           (parse-conditional ()
+             (let ((left (parse-logical-or)))
+               (if (eq (peek) 'c::|?|)
+                 (let ((then (progn (next) (parse-expression)))
+                       (else (if (eq (peek) 'c::|:|)
+                               (progn (next) (parse-conditional))
+                               (fail "~A where : was expected" (peek)))))
+                   (list 'if left then else))
+                 left)))
+           (parse-logical-or ()
+             (let ((left (parse-logical-and)))
+               (loop while (eq (peek) 'c::|\|\||)
+                     do (setq left (list (next) left (parse-logical-and))))
+               left))
+           (parse-logical-and ()
+             (let ((left (parse-bitwise-ior)))
+               (loop while (eq (peek) 'c::|&&|)
+                     do (setq left (list (next) left (parse-bitwise-ior))))
+               left))
+           (parse-bitwise-ior ()
+             (let ((left (parse-bitwise-xor)))
+               (loop while (eq (peek) 'c::|\||)
+                     do (setq left (list (next) left (parse-bitwise-xor))))
+               left))
+           (parse-bitwise-xor ()
+             (let ((left (parse-bitwise-and)))
+               (loop while (eq (peek) 'c::|\^|)
+                     do (setq left (list (next) left (parse-bitwise-and))))
+               left))
+           (parse-bitwise-and ()
+             (let ((left (parse-equality)))
+               (loop while (eq (peek) 'c::|&|)
+                     do (setq left (list (next) left (parse-equality))))
+               left))
+           (parse-equality ()
+             (let ((left (parse-relational)))
+               (loop while (member (peek) '(c::|==| c::|!=|))
+                     do (setq left (list (next) left (parse-relational))))
+               left))
+           (parse-relational ()
+             (let ((left (parse-shift)))
+               (loop while (member (peek) '(c::|<| c::|>| c::|<=| c::|>=|))
+                     do (setq left (list (next) left (parse-shift))))
+               left))
+           (parse-shift ()
+             (let ((left (parse-additive)))
+               (loop while (member (peek) '(c::|<<| c::|>>|))
+                     do (setq left (list (next) left (parse-additive))))
+               left))
+           (parse-additive ()
+             (let ((left (parse-multiplicative)))
+               (loop while (member (peek) '(c::|+| c::|-|))
+                     do (setq left (list (next) left (parse-multiplicative))))
+               left))
+           (parse-multiplicative ()
+             (let ((left (parse-pointer-to-member)))
+               (loop while (member (peek) '(c::|*| c::|/| c::|%|))
+                     do (setq left (list (next) left (parse-pointer-to-member))))
+               left))
+           (parse-pointer-to-member ()
+             (let ((left (parse-unary)))
+               (loop while (member (peek) '(c::|.*| c::|->*|))
+                     do (setq left (list (next) left (parse-unary))))
+               left))
+           (parse-unary ()              ; subsumes parse-cast, thus accepting some invalid programs
+             (let ((token (next)))      ; --- doesn't support new and delete yet
+               (cond ((member token '(c::|+| c::|-| c::|!| c::|~| c::|++| c::|--|))
+                      ;;--- doesn't yet have special support for calling destructors...
+                      (list token (parse-unary)))
+                     ((eq token 'c::|*|)
+                      (list 'c::indirect (parse-unary)))
+                     ((eq token 'c::|&|)
+                      (list 'c::address-of (parse-unary)))
+                     ((eq token 'c::|sizeof|)
+                      (unless (eq (peek) *lparen-symbol*)          ; Require open paren, maybe it's really optional
+                        (fail "~A where ( was expected after sizeof" (peek)))
+                      (next)            ; Swallow open parenthesis
+                      `(c::size-of (c::resolve-type ,(loop as token = (next)
+                                                           until (eq token *rparen-symbol*)
+                                                           collect token))))
+                     (t (parse-postfix token)))))
+           (parse-postfix (token)
+             (loop with left = (parse-primary token)
+                   as right =  (peek) do
+                   (setq left
+                         (cond ((eq right *leftbracket-symbol*)
+                                (next)          ; swallow [
+                                (let ((subscript (parse-expression))
+                                      (delimiter (next)))
+                                  (unless (eq delimiter *rightbracket-symbol*)
+                                  (fail "~A where ] expected after subscript" delimiter))
+                                  `(c::aref ,left ,subscript)))
+                               ((eq right *lparen-symbol*)
+                                (next)          ; swallow open parenthesis
+                                (let ((macro (and expand-macros
+                                                  (identifierp left)
+                                                  (macro-definition left expand-macros))))
+                                  (cond ((and macro (not (eq (first macro) ':none)))
+                                         ;; Function-like macro - constant-like was alraedy handled
+                                         (let ((more-tokens 
+                                                (expand-c-macro left (first macro)
+                                                                (collect-macro-arguments)
+                                                                (second macro) nil '()
+                                                                expand-macros)))
+                                           (setq token-list (append more-tokens token-list))
+                                           (parse-expression)))
+                                        ((valid-type-name? (list left))
+                                         ;; This is an explicit type conversion
+                                         `(c::cast ,(evaluate-type-name (list left))
+                                           ,@(parse-argument-list)))
+                                        (t nil #|`(c::call ,left ,@(parse-argument-list))|#))))
+                               ((memq right '(c::|.| c::|->|))
+                                (next)          ; swallow operator
+                                `(,right ,left ,(parse-primary (next))))  ; parse-name, really
+                               ((eq right 'c::|++|)
+                                (next)          ; swallow operator
+                                `(c::postfix++ ,left))
+                               ((eq right 'c::|--|)
+                                (next)          ; swallow operator
+                                `(c::postfix-- ,left))
+                               (t (return left))))))
+           (parse-primary (token)
+               (cond ((identifierp token)
+                        ;; nonqualified name
+                        (let ((value (find-constant token constants)))
+                          (cond (value 
+                                 (setq value (list value) token-list `(,@value #.*rparen-symbol* ,@token-list))
+                                 (parse-parenthesized))
+                                ((setq value (assoc token additional-constants))
+                                 (cdr value))
+                                ((and expand-macros
+                                      (setq value (macro-definition-of-token token))
+                                      (eq (first value) ':none))
+                                 (setq token-list (append (expand-c-macros-in-token-list 
+                                                           (second value) nil (list token) expand-macros)
+                                                          token-list ))
+                                 (parse-primary (next)))
+                                (t token))))
+                     ((eq token *lparen-symbol*)
+                      (let* ((save-token-list token-list)
+                            (type-name (collect-parenthesized))
+                            (type (valid-type-name? type-name)))
+                        (cond (type
+                               ;; This is a cast
+                               ;; Doing cast here is easier but accepts some invalid programs
+                               (progn
+                                 `(c::cast (,type) ,(parse-unary))))
+                              (t
+                               ;; These are ordinary grouping parentheses
+                               (setq token-list save-token-list)
+                               (parse-parenthesized)))))
+                     ((eq token 'c::|{|)
+                      (cons 'c::curly-bracketed-list
+                            (loop as token = (next)
+                                  until (eq token 'c::|}|)
+                                  do (unread token)
+                                  collect (parse-expression)
+                                  do (let ((delimiter (peek)))
+                                       (case delimiter
+                                         (c::|,| (next))
+                                         (c::|}| )
+                                         (otherwise 
+                                          (fail "~A where , or } was expected" delimiter)))))))
+                     ((numberp token) token)
+                     ((stringp token) token)
+                     ((eq token 'c::|::|)
+                      (fail "Unary :: is not supported yet"))
+                     (t (fail "~A is unrecognized syntax in an expression" token))))
+           (parse-parenthesized ()
+             (prog1 (parse-expression)
+               (let ((close (next)))
+                 (unless (eq close *rparen-symbol*)
+                   (fail "~A where ) was expected" close)))))
+           (parse-argument-list ()
+             (if (eq (peek) *rparen-symbol*)
+               (progn (next) '())
+               (loop as arg = (parse-expression)
+                     as delimiter = (next)
+                     collect arg
+                     do (unless (or (eq delimiter 'c::|,|) (eq delimiter *rparen-symbol*))
+                          (fail "~A where , or ) expected in function arguments"
+                                delimiter))
+                     while (eq delimiter 'c::|,|))))
+           (collect-macro-arguments ()
+             (loop with done = nil with first = t
+                   collect (loop as token = (next) with level = 0
+                                 do (cond ((eq token *lparen-symbol*) (incf level))
+                                          ((eq token *rparen-symbol*) 
+                                           (when first   ; () has to be treated as a special case
+                                             (return-from collect-macro-arguments '()))
+                                           (if (plusp level) (decf level) (setq done t))))
+                                    (setq first nil)
+                                 until (or done (and (zerop level) (eq token 'c::|,|)))
+                                 collect token)
+                   until done))
+           
+           ;;--- The following type-name routines don't support the full C++ syntax
+           ;;--- Maybe we will add ::, arrays, functions, and God knows what later
+           (valid-type-name? (token-list &optional tailp)
+             (let* ((type (ignore-errors (parse-c-ffi-type token-list))))
+               tailp
+               (return-from valid-type-name?
+                 (if (and type (not (eq type *the-ffi-void-type*)))
+                   type)))
+                                              
+             ;; At least one type-specifier followed by an optional abstract-declarator
+             ;; For now the type-specifier cannot contain :: and the only
+             ;; abstract-declarators we accept are stars (not functions, arrays)
+             (cond ((null token-list) tailp)
+                   ((member (car token-list) '(c::|long| c::|short| c::|signed| c::|unsigned|))
+                    (valid-type-name? (cdr token-list) t))
+                   ((and (identifierp (car token-list))
+                         (find-user-or-primitive-type (car token-list)))
+                    (valid-type-name? (cdr token-list) t))
+                   ;((eq (car token-list) '|::|) (valid-type-name? (cdr token-list)))
+                   ((and tailp (eq (car token-list) 'c::|*|))
+                    (valid-type-name? (cdr token-list) t))
+                   (t nil))))
+    (prog1 (parse-expression)
+      (when token-list
+        (fail "~{~A ~} left over after expression" token-list)))))
+
+(defun c-parse-error (stream format &rest args)
+  (declare (ignore stream))
+  (apply #'error format args))
+
+(pushnew '(c-parse-error . 1) ccl::*format-arg-functions* :test #'equal)
+
+(defun macro-definition-of-token (x)
+  (declare (ignore x)))
+
+(defun c-stringize-token-list (tokens)
+  (apply #'concatenate 'string (mapcar #'c-stringize-token tokens)))
+
+(defun c-stringize-token (token)
+  (etypecase token
+    (symbol (string token))
+    (string token)
+    (number (princ-to-string token))))
+
+(defun install-new-db-files (ftd d)
+  (let* ((dir (merge-pathnames (interface-dir-subdir d)
+			       (ftd-interface-db-directory ftd))))
+    (flet ((rename-and-reopen (was-open path newpath)
+	     (let* ((path (merge-pathnames path dir))
+		    (newpath (merge-pathnames newpath dir)))
+	       (when was-open
+		 (cdb-close was-open))
+	       (when (probe-file path)
+		 (rename-file path
+			      (concatenate 'string (namestring (truename path)) "-BAK")
+			      :if-exists :supersede))
+	       (rename-file newpath path)
+	       (when was-open
+		 (cdb-open path)))))
+      (without-interrupts
+       (setf (interface-dir-constants-interface-db-file d)
+	     (rename-and-reopen
+	      (interface-dir-constants-interface-db-file d)
+	      "constants.cdb"
+	      "new-constants.cdb"))
+       (setf (interface-dir-functions-interface-db-file d)
+	     (rename-and-reopen
+	      (interface-dir-functions-interface-db-file d)
+	      "functions.cdb"
+	      "new-functions.cdb"))
+       (setf (interface-dir-records-interface-db-file d)
+	     (rename-and-reopen
+	      (interface-dir-records-interface-db-file d)
+	      "records.cdb"
+	      "new-records.cdb"))
+       (setf (interface-dir-types-interface-db-file d)
+	     (rename-and-reopen
+	      (interface-dir-types-interface-db-file d)
+	      "types.cdb"
+	      "new-types.cdb"))
+       (setf (interface-dir-vars-interface-db-file d)
+	     (rename-and-reopen
+	      (interface-dir-vars-interface-db-file d)
+	      "vars.cdb"
+	      "new-vars.cdb"))
+       (setf (interface-dir-objc-classes-interface-db-file d)
+	     (rename-and-reopen
+	      (interface-dir-objc-classes-interface-db-file d)
+	      "objc-classes.cdb"
+	      "new-objc-classes.cdb"))
+       (setf (interface-dir-objc-methods-interface-db-file d)
+	     (rename-and-reopen
+	      (interface-dir-objc-methods-interface-db-file d)
+	      "objc-methods.cdb"
+	      "new-objc-methods.cdb")))))
+  t)
+
+
Index: /branches/new-random/library/pascal-strings.lisp
===================================================================
--- /branches/new-random/library/pascal-strings.lisp	(revision 13309)
+++ /branches/new-random/library/pascal-strings.lisp	(revision 13309)
@@ -0,0 +1,107 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2003-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+;;; Utilities for dealing with Pascal strings
+;;;
+;;; In 68K Mac Pascal, strings were represented by a pointer to a
+;;; "length byte", which indicated the number of data bytes immediately
+;;; following.
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  ;; What else should be exported ?  What else should be added
+  ;; to this file ?
+  (export '(with-pstrs with-returned-pstrs %get-string)))
+
+(defun %pstr-pointer (string pointer)
+  (multiple-value-bind (s o n) (dereference-base-string string)
+    (declare (fixnum o n))
+    (%copy-ivector-to-ptr s o pointer 1 n)
+    (setf (%get-byte pointer 0) n))
+  nil)
+
+(defun %pstr-segment-pointer (string pointer start end)
+  (declare (fixnum start end))
+  (let* ((n (- end start)))
+    (multiple-value-bind (s o) (dereference-base-string string)
+      (declare (fixnum o))
+      (%copy-ivector-to-ptr s (the fixnum (+ o start)) pointer 1 n)
+    (setf (%get-byte pointer 0) n)
+    nil)))
+
+(defun %get-string (pointer)
+  (let* ((len (%get-unsigned-byte pointer)))
+    (%copy-ptr-to-ivector
+     pointer
+     1
+     (make-string len :element-type 'base-char)
+     0
+     len)))
+
+(defun (setf %get-string) (lisp-string pointer)
+  (let* ((len (length lisp-string)))
+    (multiple-value-bind (string offset)
+        (dereference-base-string lisp-string)
+      (setf (%get-unsigned-byte pointer) len)
+      (%copy-ivector-to-ptr string offset pointer 1 len))
+    lisp-string))
+
+(defmacro with-pstr ((sym str &optional start end) &rest body &environment env)
+  (multiple-value-bind (body decls) (parse-body body env nil)
+    (if (and (base-string-p str) (null start) (null end))
+      (let ((strlen (%i+ (length str) 1)))
+        `(%stack-block ((,sym ,strlen))
+           ,@decls
+           (%pstr-pointer ,str ,sym)
+           ,@body))
+      (let ((strname (gensym))
+            (start-name (gensym))
+            (end-name (gensym)))
+        `(let ((,strname ,str)
+               ,@(if (or start end)
+                   `((,start-name ,(or start 0))
+                     (,end-name ,(or end `(length ,strname))))))
+           (%vstack-block (,sym
+                           (the fixnum
+                             (1+
+                              (the fixnum
+                                ,(if (or start end)
+                                     `(byte-length
+                                       ,strname ,start-name ,end-name)
+                                     `(length ,strname))))))
+             ,@decls
+             ,(if (or start end)
+                `(%pstr-segment-pointer ,strname ,sym ,start-name ,end-name)
+                `(%pstr-pointer ,strname ,sym))
+             ,@body))))))
+
+
+(defmacro with-returned-pstr ((sym str &optional start end) &body body)
+   `(%stack-block ((,sym 256))
+      ,(if (or start end)
+         `(%pstr-segment-pointer ,str ,sym ,start ,end)
+         `(%pstr-pointer ,str ,sym))
+      ,@body))
+
+(defmacro with-pstrs (speclist &body body)
+   (with-specs-aux 'with-pstr speclist body))
+
+(defmacro with-returned-pstrs (speclist &body body)
+   (with-specs-aux 'with-returned-pstr speclist body))
+
+
Index: /branches/new-random/library/ppc-linux-syscalls.lisp
===================================================================
--- /branches/new-random/library/ppc-linux-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/ppc-linux-syscalls.lisp	(revision 13309)
@@ -0,0 +1,234 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL"))
+
+
+
+
+
+
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::exit 1 (:signed-fullword) :void)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fork 2 () :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::read 3 (:unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::write 4 (:unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::open 5 (:address :unsigned-fullword :unsigned-fullword) :signed-fullword :min-args 2)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::close 6 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::waitpid 7 (:unsigned-fullword :address :signed-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::creat 8 (:address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::link 9 (:address :address) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::unlink 10 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::execve 11 (:address :address :address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::chdir 12 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::time 13 (:address) :unsigned-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mknod 14 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::chmod 15 (:address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::lchown 16 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+;(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::oldstat 18 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::lseek 19 (:unsigned-fullword :signed-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getpid 20 () :unsigned-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mount 21 (:address
+				 :address
+				 :address
+				 :unsigned-fullword
+				 :address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::umount 22 (:address) :signed-fullword )
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setuid 23 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getuid 24 () :unsigned-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::stime 25 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::ptrace 26 (:unsigned-fullword
+				  :unsigned-fullword
+				  :address
+				  :address)
+		:signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::alarm 27 (:unsigned-fullword) :unsigned-fullword )
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::pause 29 () :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::utime 30 (:address :address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::access 33 (:address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::nice 34 (:signed-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sync 36 () :unsigned-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::kill 37 (:signed-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rename 38 (:address :address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mkdir 39 (:address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rmdir 40 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::dup 41 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::pipe 42 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::times 43 (:address) :unsigned-fullword )
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::brk 45 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setgid 46 (:unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getgid 47 () :unsigned-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::signal 48 (:unsigned-fullword :address) :address )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::geteuid 49 () :unsigned-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getegid 50 () :unsigned-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::acct 51 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::umount2 52 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::ioctl 54 (:unsigned-fullword :signed-fullword :address) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fcntl 55 (:unsigned-fullword :signed-fullword :signed-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setpgid 57 (:signed-fullword :signed-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::umask 60 (:unsigned-fullword) :unsigned-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::chroot 61 (:address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::ustat 62 (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::dup2 63 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getppid 64 () :unsigned-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getpgrp 65 () :unsigned-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setsid 66 () :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sigaction 67 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getrusage 77 (:signed-fullword :address) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::gettimeofday 78 (:address :address) :void)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::ftruncate 93 (:unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fchmod 94 (:unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::socketcall 102 (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::stat 106 (:address :address) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::lstat 107 (:address :address) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fstat 108 (:unsigned-fullword :address) :signed-fullword )
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fsync 118 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::uname 122  (:address) :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fchdir 133 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::_llseek 140 (:unsigned-fullword :unsigned-fullword :unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-cpu-ppc platform-os-linux) 	syscalls::select 142 (:unsigned-fullword :address :address
+                                                  :address :address)
+                :signed-fullword)
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getcwd 182 (:address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::poll 167 ((:* (:struct :pollfd)) :int :int) :int)
+
+#+notdefinedyet
+(progn
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sgetmask 68 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::ssetmask 69 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setreuid 70 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setregid 71 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sigsuspend 72 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sigpending 73 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sethostname 74 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setrlimit 75 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getrlimit 76 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::settimeofday 79 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getgroups 80 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setgroups 81 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::symlink 83 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::oldlstat 84 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::readlink 85 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::uselib 86 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::swapon 87 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::reboot 88 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::readdir 89 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mmap 90 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::munmap 91 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::truncate 92 () )
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fchown 95 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getpriority 96 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setpriority 97 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::statfs 99 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fstatfs 100 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::ioperm 101 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::syslog 103 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setitimer 104 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getitimer 105 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::olduname 109 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::iopl 110 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::vhangup 111 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::idle 112 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::vm86 113 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::wait4 114 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::swapoff 115 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sysinfo 116 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::ipc 117 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sigreturn 119 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::clone 120 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setdomainname 121 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::modify_ldt 123 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::adjtimex 124 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mprotect 125 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sigprocmask 126 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::create_module	127 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::init_module	128 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::delete_module	129 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::get_kernel_syms	130 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::quotactl 131 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getpgid 132 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::bdflush 134 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sysfs 135 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::personality 136 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setfsuid 138 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setfsgid 139 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getdents 141 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::_newselect 142 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::flock 143 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::msync 144 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::readv 145 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::writev 146 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getsid 147 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::fdatasync 148 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::_sysctl 149 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mlock 150 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::munlock 151 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mlockall 152 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::munlockall 153 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_setparam 154 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_getparam 155 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_setscheduler 156 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_getscheduler 157 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_yield 158 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_get_priority_max 159 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_get_priority_min 160 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sched_rr_get_interval 161 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::nanosleep 162 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::mremap 163 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setresuid 164 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getresuid 165 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::query_module	166 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::poll 167 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::nfsservctl 168 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::setresgid 169 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getresgid 170 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::prctl 171 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rt_sigreturn 172 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rt_sigaction 173 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rt_sigprocmask 174 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rt_sigpending 175 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rt_sigtimedwait 176 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rt_sigqueueinfo 177 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::rt_sigsuspend 178 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::pread 179 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::pwrite 180 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::chown 181 (:address) )
+
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::capget 183 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::capset 184 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sigaltstack 185 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::sendfile 186 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::getpmsg 187	 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::putpmsg 188	 () )
+(define-syscall (logior platform-cpu-ppc platform-os-linux)  syscalls::vfork 189 () )
+
+)
Index: /branches/new-random/library/pty.lisp
===================================================================
--- /branches/new-random/library/pty.lisp	(revision 13309)
+++ /branches/new-random/library/pty.lisp	(revision 13309)
@@ -0,0 +1,143 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2002-2009 Clozure Associates.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; (very) preliminary support for dealing with TTYs (and PTYs).
+
+(in-package "CCL")
+
+;;; Open a (connected) pair of pty file descriptors, such that anything
+;;; written to one can be read from the other.
+#+linuxppc-target
+(eval-when (:load-toplevel :execute)
+  (open-shared-library "libutil.so"))
+
+(defun open-pty-pair ()
+  (rlet ((alphap :unsigned 0)
+	 (betap :unsigned 0))
+    (let* ((status (#_openpty alphap betap (%null-ptr) (%null-ptr) (%null-ptr))))
+      (if (eql status 0)
+	(values (pref alphap :unsigned) (pref betap :unsigned))
+	(%errno-disp (%get-errno))))))
+
+
+(defun %get-tty-attributes (tty-fd &optional control-chars)
+  (if (and control-chars
+	   (not (and (typep control-chars 'simple-string)
+		     (= (length control-chars) #$NCCS))))
+    (report-bad-arg control-chars '(or null (simple-string #.#$NCCS))))
+  (rlet ((attr :termios))
+    (let* ((result (#_tcgetattr tty-fd attr)))
+      (if (< result 0)
+	(values nil nil nil nil nil nil nil)
+	(progn
+	  (if control-chars
+            (%str-from-ptr (pref attr :termios.c_cc) #$NCCS control-chars))
+	  (values
+	   (pref attr :termios.c_iflag)
+	   (pref attr :termios.c_oflag)
+	   (pref attr :termios.c_cflag)
+	   (pref attr :termios.c_lflag)
+	   #+darwin-target 0
+	   #-darwin-target
+	   (pref attr :termios.c_line)
+	   control-chars
+	   (pref attr :termios.c_ispeed)
+	   (pref attr :termios.c_ospeed)))))))
+
+(defun %set-tty-attributes (tty &key
+				input-modes
+				output-modes
+				control-modes
+				local-modes
+				control-chars
+				input-speed
+				output-speed)
+  (if (and control-chars
+	   (not (and (typep control-chars 'simple-string)
+		     (= (length control-chars) #$NCCS))))
+    (report-bad-arg control-chars '(or null (simple-string #.#$NCCS))))
+  (rlet ((attr :termios))
+	(let* ((get-ok (#_tcgetattr tty attr))
+	       (write-back nil))
+	  (when (eql 0 get-ok)
+	    (when input-modes
+	      (setf (pref attr :termios.c_iflag) input-modes)
+	      (setq write-back t))
+	    (when output-modes
+	      (setf (pref attr :termios.c_oflag) output-modes)
+	      (setq write-back t))
+	    (when control-modes
+	      (setf (pref attr :termios.c_cflag) control-modes)
+	      (setq write-back t))
+	    (when local-modes
+	      (setf (pref attr :termios.c_lflag) local-modes)
+	      (setq write-back t))
+	    (when control-chars
+              (%cstr-pointer control-chars (pref attr :termios.c_cc) nil)
+	      (setq write-back t))
+	    (when input-speed
+	      (setf (pref attr :termios.c_ispeed) input-speed)
+	      (setq write-back t))
+	    (when output-speed
+	      (setf (pref attr :termios.c_ospeed) output-speed)
+	      (setq write-back t))
+	    (and write-back
+		 (eql 0 (#_tcsetattr tty #$TCSAFLUSH attr)))))))
+
+(defun enable-tty-input-modes (tty mask)
+  (let* ((old (nth-value 0 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :input-modes (logior old mask)))))
+
+(defun disable-tty-input-modes (tty mask)
+  (let* ((old (nth-value 0 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :input-modes (logand old (lognot mask))))))
+
+(defun enable-tty-output-modes (tty mask)
+  (let* ((old (nth-value 1 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :output-modes (logior old mask)))))
+
+(defun disable-tty-output-modes (tty mask)
+  (let* ((old (nth-value 1 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :output-modes (logand old (lognot mask))))))
+
+(defun enable-tty-control-modes (tty mask)
+  (let* ((old (nth-value 2 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :control-modes (logior old mask)))))
+
+(defun disable-tty-control-modes (tty mask)
+  (let* ((old (nth-value 2 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :control-modes (logand old (lognot mask))))))
+
+(defun enable-tty-local-modes (tty mask)
+  (let* ((old (nth-value 3 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :local-modes (logior old mask)))))
+
+(defun disable-tty-local-modes (tty mask)
+  (let* ((old (nth-value 3 (%get-tty-attributes tty))))
+    (when old
+      (%set-tty-attributes tty :local-modes (logand old (lognot mask))))))
+
+(defun set-tty-raw (tty)
+  (rlet ((attr :termios))
+    (#_cfmakeraw attr)
+    (eql 0 (#_tcsetattr tty #$TCSAFLUSH attr))))
Index: /branches/new-random/library/sequence-utils.lisp
===================================================================
--- /branches/new-random/library/sequence-utils.lisp	(revision 13309)
+++ /branches/new-random/library/sequence-utils.lisp	(revision 13309)
@@ -0,0 +1,92 @@
+;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: cl-user -*-
+;;;; ***********************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          sequence-utils.lisp
+;;;; Version:       0.2
+;;;; Project:       utilities
+;;;; Purpose:       utilities for working with sequences
+;;;;
+;;;; ***********************************************************************
+
+(in-package "CCL")
+
+;;; -----------------------------------------------------------------
+;;; splitting sequences
+;;; -----------------------------------------------------------------
+
+;;; Split a sequence SEQ at each point where TEST is true 
+;;; DIR should be one of :BEFORE, :AFTER or :ELIDE
+
+(defun split-if (test seq &optional (dir :before))
+  (remove-if
+   #'(lambda (x) (equal x (subseq seq 0 0)))
+   (loop for start fixnum = 0 
+         then (if (eq dir :before) stop (the fixnum (1+ (the fixnum stop))))
+         while (< start (length seq))
+         for stop = (position-if 
+                     test seq 
+                     :start (if (eq dir :elide) start (the fixnum (1+ start))))
+         collect (subseq 
+                  seq start 
+                  (if (and stop (eq dir :after)) 
+                    (the fixnum (1+ (the fixnum stop))) 
+                    stop))
+         while stop)))
+  
+(defun split-if-char (char seq &optional dir)
+  (split-if #'(lambda (ch) (eq ch char)) seq dir))
+
+(defmethod split-lines ((text string))
+  (delete-if (lambda (x) (string= x ""))
+             (mapcar (lambda (s)
+                       (string-trim '(#\return #\newline) s))
+                     (split-if (lambda (c) (member c '(#\return #\newline) :test #'char=))
+                               text))))
+
+;;; -----------------------------------------------------------------
+;;; matching subsequences
+;;; -----------------------------------------------------------------
+
+(defun match-subsequence (subseq seq &key (test #'eql) (start 0))
+  (let ((max-index (1- (length seq))))
+    (block matching
+      ;; search for mismatches
+      (dotimes (i (length subseq))
+        (let ((pos (+ start i)))
+          (when (or (> pos max-index)
+                    (not (funcall test (elt seq pos)
+                                  (elt subseq i))))
+            (return-from matching nil))))
+      ;; no mismatches found; return true
+      (return-from matching t))))
+
+(defun %find-matching-subsequence-backward (subseq seq &key (test #'eql) (start 0) end)
+  (let ((end (or end (length seq)))
+        (pos end)
+        (min-index (or start 0)))
+    (block finding
+      (dotimes (i (- (length seq) start))
+        (setf pos (- end i))
+        (if (<= pos min-index)
+            (return-from finding nil)
+            (when (match-subsequence subseq seq :test test :start pos)
+              (return-from finding pos))))
+      nil)))
+
+(defun %find-matching-subsequence-forward (subseq seq &key (test #'eql) (start 0) end)
+  (let ((pos start)
+        (max-index (or end (length seq))))
+    (block finding
+      (dotimes (i (- (length seq) start))
+        (setf pos (+ start i))
+        (if (>= pos max-index)
+            (return-from finding nil)
+            (when (match-subsequence subseq seq :test test :start pos)
+              (return-from finding pos))))
+      nil)))
+
+(defun find-matching-subsequence (subseq seq &key (test #'eql) (start 0) end from-end)
+  (if from-end
+      (%find-matching-subsequence-backward subseq seq :test test :start start :end end)
+      (%find-matching-subsequence-forward subseq seq :test test :start start :end end)))
Index: /branches/new-random/library/sharp-comma.lisp
===================================================================
--- /branches/new-random/library/sharp-comma.lisp	(revision 13309)
+++ /branches/new-random/library/sharp-comma.lisp	(revision 13309)
@@ -0,0 +1,32 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+;;; #, was removed from CL in 1998 or so, but there may be some legacy
+;;; code that still uses it.
+
+(set-dispatch-macro-character
+ #\#
+ #\,
+ #'(lambda (stream subchar numarg)
+     (let* ((sharp-comma-token *reading-for-cfasl*))
+       (if (or *read-suppress* (not *compiling-file*) (not sharp-comma-token))
+         (read-eval stream subchar numarg)
+         (progn
+           (require-no-numarg subchar numarg)
+           (list sharp-comma-token (read stream t nil t)))))))
Index: /branches/new-random/library/splay-tree.lisp
===================================================================
--- /branches/new-random/library/splay-tree.lisp	(revision 13309)
+++ /branches/new-random/library/splay-tree.lisp	(revision 13309)
@@ -0,0 +1,208 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2003-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+
+;;; A (partial) implementation of SPLAY-TREEs, which are binary trees
+;;; that reorganize themselves so that the most recently accessed keys
+;;; cluster near the tree's root.
+
+(defstruct (tree-node
+             (:constructor make-tree-node (key value)))
+  key
+  value
+  left                                  ; the child < this key, or NIL
+  right                                 ; the child > this key, or NIL
+  parent                                ; we're the root if NIL.   
+  )
+
+(defmethod print-object ((node tree-node) stream)
+  (print-unreadable-object (node stream :type t :identity t)
+    (let* ((*print-circle* t))
+      (format stream "~s -> ~s" (tree-node-key node) (tree-node-value node)))))
+
+
+(defun tree-node-is-leaf (n)
+  (and (null (tree-node-left n))
+       (null (tree-node-right n))))
+
+(defun tree-node-is-root (n)
+  (null (tree-node-parent n)))
+
+;;; Is node the left child of its parent ?
+(defun tree-node-is-left (n)
+  (let* ((parent (tree-node-parent n)))
+    (and parent (eq n (tree-node-left parent)))))
+
+(defun tree-node-is-right (n)
+  (let* ((parent (tree-node-parent n)))
+    (and parent (eq n (tree-node-right parent)))))
+
+(defun tree-node-set-right (node newright)
+  (when (setf (tree-node-right node) newright)
+    (setf (tree-node-parent newright) node)))
+
+(defun tree-node-set-left (node newleft)
+  (when (setf (tree-node-left node) newleft)
+    (setf (tree-node-parent newleft) node)))             
+
+(defun tree-node-replace-child (node old new)
+  (if (eq old (tree-node-left node))
+    (tree-node-set-left node new)
+    (tree-node-set-right node new)))
+
+(defstruct (splay-tree (:constructor %make-splay-tree))
+  (root nil #|:type (or null splay-tree-node)|#)
+  equal                                 ; true if x = y
+  less                                  ; true if x < y
+  (count 0)
+  )
+
+(defmethod print-object ((tree splay-tree) stream)
+  (print-unreadable-object (tree stream :type t :identity t)
+    (format stream "count = ~d, root = ~s"
+	    (splay-tree-count tree)
+	    (splay-tree-root tree))))
+	    
+
+
+;;; Returns tree-node or NIL
+(defun binary-tree-get (tree key)
+  (do* ((equal (splay-tree-equal tree))
+        (less (splay-tree-less tree))
+        (node (splay-tree-root tree)))
+       ((null node))
+    (let* ((node-key (tree-node-key node)))
+      (if (funcall equal key node-key)
+        (return node)
+        (if (funcall less key node-key)
+          (setq node (tree-node-left node))
+          (setq node (tree-node-right node)))))))
+
+;;; No node with matching key exists in the tree
+(defun binary-tree-insert (tree node)
+  (let* ((root (splay-tree-root tree)))
+    (if (null root)
+      (setf (splay-tree-root tree) node)
+      (do* ((less (splay-tree-less tree))
+            (key (tree-node-key node))
+            (current root)
+            (parent nil))
+           ((null current)
+            (if (funcall less key (tree-node-key parent))
+              (tree-node-set-left parent node)
+              (tree-node-set-right parent node)))
+        (setq parent current)
+        (if (funcall less key (tree-node-key current))
+          (setq current (tree-node-left current))
+          (setq current (tree-node-right current))))))
+  (incf (splay-tree-count tree)))
+    
+            
+;;; Replace the node's parent with the node itself, updating the
+;;; affected children so that the binary tree remains properly
+;;; ordered.
+(defun binary-tree-rotate (tree node)
+  (when (and node (not (tree-node-is-root node)))
+    (let* ((parent (tree-node-parent node))
+           (grandparent (if parent (tree-node-parent parent)))
+           (was-left (tree-node-is-left node)))
+      (if grandparent
+        (tree-node-replace-child grandparent parent node)
+        (setf (splay-tree-root tree) node
+              (tree-node-parent node) nil))
+      (if was-left
+        (progn
+          (tree-node-set-left parent (tree-node-right node))
+          (tree-node-set-right node parent))
+        (progn
+          (tree-node-set-right parent (tree-node-left node))
+          (tree-node-set-left node parent))))))
+
+;;; Keep rotating the node (and maybe its parent) until the node's the
+;;; root of tree.
+(defun splay-tree-splay (tree node)
+  (when node
+    (do* ()
+         ((tree-node-is-root node))
+      (let* ((parent (tree-node-parent node))
+             (grandparent (tree-node-parent parent)))
+        (cond ((null grandparent)
+               (binary-tree-rotate tree node)) ; node is now root
+              ((eq (tree-node-is-left node)
+                   (tree-node-is-left parent))
+               (binary-tree-rotate tree parent)
+               (binary-tree-rotate tree node))
+              (t
+               (binary-tree-rotate tree node)
+               (binary-tree-rotate tree node)))))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; The more-or-less public API follows.
+;;;
+;;; I suppose that we should support DELETE as well, and perhaps
+;;; UPDATE (find the node and modify its key in place.)  For now,
+;;; SPLAY-TREE-PUT assumes that no node with a matching key exists.
+;;; Access to the tree has to be serialized by the caller.
+
+(defun splay-tree-get (tree key &optional default)
+  (let* ((node (binary-tree-get tree key)))
+    (if node
+      (progn
+        (splay-tree-splay tree node)
+        (tree-node-value node))
+      default)))
+
+(defun splay-tree-put (tree key value)
+  (let* ((node (make-tree-node key value)))
+    (binary-tree-insert tree node)
+    (splay-tree-splay tree node)
+    value))
+
+;;; Note that the tree wants two comparison functions.  This may
+;;; increase the chance that builtin CL functions can be used; a tree
+;;; whose keys are real numbers could use #'= and #'<, for instance.
+;;; Using two comparison functions is (at best) only slightly better
+;;; than insisting that a single comparison function return (values
+;;; equal less), or (member -1 0 1), or some other convention.
+
+(defun make-splay-tree (equal less)
+  (check-type equal function)
+  (check-type less function)
+  (%make-splay-tree :equal equal :less less))
+
+;;; Do an inorder traversal of the splay tree, applying function F
+;;; to the value of each node.
+
+(defun map-splay-tree (tree f)
+  (labels ((map-tree-node (node)
+	     (when node
+	       (map-tree-node (tree-node-left node))
+	       (funcall f (tree-node-value node))
+	       (map-tree-node (tree-node-right node)))))
+    (map-tree-node (splay-tree-root tree))))
+
+(defun map-splay-tree-keys-and-values (tree f)
+  (labels ((map-tree-node (node)
+	     (when node
+	       (map-tree-node (tree-node-left node))
+	       (funcall f (tree-node-key node) (tree-node-value node))
+	       (map-tree-node (tree-node-right node)))))
+    (map-tree-node (splay-tree-root tree)))) 
Index: /branches/new-random/library/syscall.lisp
===================================================================
--- /branches/new-random/library/syscall.lisp	(revision 13309)
+++ /branches/new-random/library/syscall.lisp	(revision 13309)
@@ -0,0 +1,68 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; "Generic" syscall sypport.
+
+(in-package "CCL")
+
+(defpackage "SYSCALLS" (:use))
+
+(defstruct syscall
+  (idx 0 :type fixnum)
+  (arg-specs () :type list)
+  (result-spec nil :type symbol)
+  (min-args 0 :type fixnum))
+
+(defvar *os-syscall-definitions* ())
+
+(defun platform-syscall-definitions (platform-os)
+  (or (getf *os-syscall-definitions* platform-os)
+      (setf (getf *os-syscall-definitions* platform-os)
+            (make-hash-table :test 'eq))))
+
+(defun backend-syscall-definitions (backend)
+  (platform-syscall-definitions (backend-platform-syscall-mask backend)))
+
+
+
+(defmacro define-syscall (platform name idx (&rest arg-specs) result-spec
+			       &key (min-args (length arg-specs)))
+  `(progn
+    (setf (gethash ',name (platform-syscall-definitions ,platform))
+     (make-syscall :idx ,idx
+      :arg-specs ',arg-specs
+      :result-spec ',result-spec
+      :min-args ,min-args))
+    ',name))
+
+(defmacro syscall (name &rest args)
+  (let* ((info (or (gethash name (backend-syscall-definitions *target-backend*))
+		   (error "Unknown system call: ~s" name)))
+	 (idx (syscall-idx info))
+	 (arg-specs (syscall-arg-specs info))
+	 (n-argspecs (length arg-specs))
+	 (n-args (length args))
+	 (min-args (syscall-min-args info))
+	 (result (syscall-result-spec info)))
+    (unless (and (>= n-args min-args) (<= n-args n-argspecs))
+      (error "wrong number of args in ~s" args))
+    (do* ((call ())
+	  (specs arg-specs (cdr specs))
+	  (args args (cdr args)))
+	 ((null args)
+	  `(%syscall ,idx ,@(nreverse (cons result call))))
+      (push (car specs) call)
+      (push (car args) call))))
Index: /branches/new-random/library/x86-win64-syscalls.lisp
===================================================================
--- /branches/new-random/library/x86-win64-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/x86-win64-syscalls.lisp	(revision 13309)
@@ -0,0 +1,281 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2008-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL"))
+
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::open 0 (:address :unsigned-fullword :unsigned-fullword) :signed-fullword :min-args 2)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::close 1 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::read 2 (:unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::write 3 (:unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fchmod 4 (:unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::lseek 5 (:unsigned-fullword :signed-doubleword :unsigned-fullword) :signed-doubleword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::stat 6 (:address :address) :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fstat 7 (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::ftruncate 8 (:unsigned-fullword :unsigned-doubleword)
+		:signed-fullword)
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::opendir 9 (:address) :address)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::readdir 10 (:address) :address)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::closedir 11 (:address)
+		:signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::pipe 12 (:address) :signed-fullword )
+
+#+notdefinedyet
+(progn
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::lstat 190 (:address :address) :signed-fullword)
+
+
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::exit 1 (:signed-fullword) :void)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fork 2 () :signed-fullword)
+
+
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::creat 85 (:address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::link 9 (:address :address) :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::unlink 10 (:address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::execve 59 (:address :address :address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::chdir 12 (:address) :signed-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::time 201 (:address) :unsigned-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mknod 14 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::chmod 15 (:address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::lchown 254 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getpid 20 () :unsigned-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mount 21 (:address :address :address :unsigned-fullword :address) :signed-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::umount2 166 (:address) :signed-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setuid 23 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getuid 24 () :unsigned-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::ptrace 26 (:unsigned-fullword
+				  :unsigned-fullword
+				  :address
+				  :address)
+		:signed-fullword)
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::alarm 37 (:unsigned-fullword) :unsigned-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::pause 34 () :signed-fullword)
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::utime 132 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::access 33 (:address :unsigned-fullword) :signed-fullword)
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sync 36 () :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::kill 37 (:signed-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rename 128 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mkdir 136 (:address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rmdir 17 (:address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::dup 41 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::times 100 (:address) :unsigned-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::brk 12 (:address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setgid 181 (:unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getgid 47 () :unsigned-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::geteuid 25 () :unsigned-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getegid 43 () :unsigned-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::acct 51 (:address) :signed-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::ioctl 54 (:unsigned-fullword :signed-fullword :address) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fcntl 92 (:unsigned-fullword :signed-fullword :signed-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setpgid 82 (:signed-fullword :signed-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::umask 60 (:unsigned-fullword) :unsigned-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::chroot 61 (:address) :signed-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::ustat 136 (:unsigned-fullword :address) :signed-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::dup2 90 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getppid 39 () :unsigned-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getpgrp 81 () :unsigned-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setsid 147 () :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sigaction 416 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getrusage 117 (:signed-fullword :address) :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::gettimeofday 116 (:address :address) :void)
+
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fchmod 124 (:unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::socket 97 (:signed-fullword :signed-fullword :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::connect 98 (:signed-fullword :address :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::accept 30 (:signed-fullword :address :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sendto 133 (:unsigned-fullword :address :unsigned-fullword :unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64) syscalls::recvfrom 29 (:unsigned-fullword :address :unsigned-long :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64) syscalls::sendmsg 28 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64) syscalls::recvmsg 27 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall  (logior platform-os-windows platform-cpu-x86 platform-word-size-64) syscalls::shutdown 134 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::bind 104 (:signed-fullword :address :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::listen 106 (:signed-fullword  :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getpeername 31 (:signed-fullword :address :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getsockname 32 (:signed-fullword :address :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::socketpair 135 (:signed-fullword :signed-fullword :signed-fullword  :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64) syscalls::setsockopt 105 (:unsigned-fullword :signed-fullword :signed-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64) syscalls::getsockopt 118 (:unsigned-fullword :signed-fullword :unsigned-fullword :address :address) :signed-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fsync 95 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::uname 164  (:address) :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fchdir 13 (:unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64) 	syscalls::select 93 (:unsigned-fullword :address :address
+                                                  :address :address)
+                :signed-fullword)
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getcwd 326 (:address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64) syscalls::poll 209 ((:* (:struct :pollfd)) :int :int) :int)
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sgetmask 68 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::ssetmask 69 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setreuid 70 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setregid 71 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sigsuspend 72 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sigpending 73 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sethostname 74 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setrlimit 75 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getrlimit 76 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::settimeofday 79 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getgroups 80 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setgroups 81 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::symlink 83 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::oldlstat 84 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::readlink 58 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::uselib 86 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::swapon 87 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::reboot 88 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::readdir 89 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::truncate 92 () )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fchown 95 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getpriority 96 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setpriority 97 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::statfs 99 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fstatfs 100 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::ioperm 101 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::syslog 103 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setitimer 38 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getitimer 36 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::olduname 109 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::iopl 110 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::vhangup 111 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::idle 112 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::vm86 113 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::wait4 7 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::swapoff 115 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sysinfo 116 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::ipc 117 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sigreturn 119 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::clone 120 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setdomainname 121 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::modify_ldt 123 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::adjtimex 124 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mprotect 10 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sigprocmask 126 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::create_module	127 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::init_module	128 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::delete_module	129 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::get_kernel_syms	130 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::quotactl 131 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getpgid 132 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::bdflush 134 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sysfs 135 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::personality 136 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setfsuid 138 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setfsgid 139 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getdents 141 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::_newselect 142 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::flock 143 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::msync 26 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::readv 19 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::writev 20 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getsid 147 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::fdatasync 148 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::_sysctl 149 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mlock 150 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::munlock 151 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mlockall 152 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::munlockall 153 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_setparam 154 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_getparam 155 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_setscheduler 156 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_getscheduler 157 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_yield 24 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_get_priority_max 159 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_get_priority_min 160 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sched_rr_get_interval 161 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::nanosleep 35 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mremap 25 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setresuid 164 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getresuid 165 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::query_module	166 () )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::nfsservctl 168 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::setresgid 169 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getresgid 170 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::prctl 171 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigreturn 15 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigaction 13 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigprocmask 14 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigpending 175 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigtimedwait 176 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigqueueinfo 177 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigsuspend 178 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::pread 17 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::pwrite 18 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::chown 181 (:address) )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::capget 183 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::capset 184 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sigaltstack 185 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::sendfile 40 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::getpmsg 187	 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::putpmsg 188	 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::vfork 189 () )
+
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::mmap 9 () )
+(define-syscall (logior platform-os-windows platform-cpu-x86 platform-word-size-64)  syscalls::munmap 73 () )
+
+)
Index: /branches/new-random/library/x8664-freebsd-syscalls.lisp
===================================================================
--- /branches/new-random/library/x8664-freebsd-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/x8664-freebsd-syscalls.lisp	(revision 13309)
@@ -0,0 +1,272 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2006-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL"))
+
+
+
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::read 3 (:unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::write 4 (:unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::open 5 (:address :unsigned-fullword :unsigned-fullword) :signed-fullword :min-args 2)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::close 6 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::stat 188 (:address :address) :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fstat 189 (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::lstat 190 (:address :address) :signed-fullword)
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::lseek 199 (:unsigned-fullword  :unsigned-doubleword :signed-doubleword :unsigned-fullword) :signed-doubleword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::exit 1 (:signed-fullword) :void)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fork 2 () :signed-fullword)
+
+
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::creat 85 (:address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::link 9 (:address :address) :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::unlink 10 (:address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::execve 59 (:address :address :address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::chdir 12 (:address) :signed-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::time 201 (:address) :unsigned-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mknod 14 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::chmod 15 (:address :unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::lchown 254 (:address :unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getpid 20 () :unsigned-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mount 21 (:address :address :address :unsigned-fullword :address) :signed-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::umount2 166 (:address) :signed-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setuid 23 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getuid 24 () :unsigned-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::ptrace 26 (:unsigned-fullword
+				  :unsigned-fullword
+				  :address
+				  :address)
+		:signed-fullword)
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::alarm 37 (:unsigned-fullword) :unsigned-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::pause 34 () :signed-fullword)
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::utime 132 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::access 33 (:address :unsigned-fullword) :signed-fullword)
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sync 36 () :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::kill 37 (:signed-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rename 128 (:address :address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mkdir 136 (:address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rmdir 137 (:address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::dup 41 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::pipe 42 (:address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::times 100 (:address) :unsigned-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::brk 12 (:address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setgid 181 (:unsigned-fullword) :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getgid 47 () :unsigned-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::geteuid 25 () :unsigned-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getegid 43 () :unsigned-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::acct 51 (:address) :signed-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::ioctl 54 (:unsigned-fullword :signed-fullword :address) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fcntl 92 (:unsigned-fullword :signed-fullword :signed-fullword) :signed-fullword :min-args 2 )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setpgid 82 (:signed-fullword :signed-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::umask 60 (:unsigned-fullword) :unsigned-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::chroot 61 (:address) :signed-fullword )
+
+#+notyet
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::ustat 136 (:unsigned-fullword :address) :signed-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::dup2 90 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getppid 39 () :unsigned-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getpgrp 81 () :unsigned-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setsid 147 () :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sigaction 416 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getrusage 117 (:signed-fullword :address) :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::gettimeofday 116 (:address :address) :void)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::ftruncate 201 (:unsigned-fullword :unsigned-fullword)
+		:signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fchmod 91 (:unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fchmod 124 (:unsigned-fullword :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::socket 97 (:signed-fullword :signed-fullword :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::connect 98 (:signed-fullword :address :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::accept 30 (:signed-fullword :address :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sendto 133 (:unsigned-fullword :address :unsigned-fullword :unsigned-fullword :address :unsigned-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) syscalls::recvfrom 29 (:unsigned-fullword :address :unsigned-long :unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) syscalls::sendmsg 28 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) syscalls::recvmsg 27 (:unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall  (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) syscalls::shutdown 134 (:unsigned-fullword :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::bind 104 (:signed-fullword :address :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::listen 106 (:signed-fullword  :signed-fullword)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getpeername 31 (:signed-fullword :address :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getsockname 32 (:signed-fullword :address :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::socketpair 135 (:signed-fullword :signed-fullword :signed-fullword  :address)
+		:signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) syscalls::setsockopt 105 (:unsigned-fullword :signed-fullword :signed-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) syscalls::getsockopt 118 (:unsigned-fullword :signed-fullword :unsigned-fullword :address :address) :signed-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fsync 95 (:unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::uname 164  (:address) :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fchdir 13 (:unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) 	syscalls::select 93 (:unsigned-fullword :address :address
+                                                  :address :address)
+                :signed-fullword)
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getcwd 326 (:address :unsigned-fullword) :signed-fullword )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64) syscalls::poll 209 ((:* (:struct :pollfd)) :int :int) :int)
+
+#+notdefinedyet
+(progn
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sgetmask 68 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::ssetmask 69 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setreuid 70 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setregid 71 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sigsuspend 72 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sigpending 73 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sethostname 74 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setrlimit 75 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getrlimit 76 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::settimeofday 79 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getgroups 80 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setgroups 81 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::symlink 83 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::oldlstat 84 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::readlink 58 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::uselib 86 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::swapon 87 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::reboot 88 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::readdir 89 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::truncate 92 () )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fchown 95 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getpriority 96 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setpriority 97 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::statfs 99 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fstatfs 100 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::ioperm 101 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::syslog 103 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setitimer 38 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getitimer 36 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::olduname 109 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::iopl 110 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::vhangup 111 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::idle 112 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::vm86 113 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::wait4 7 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::swapoff 115 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sysinfo 116 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::ipc 117 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sigreturn 119 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::clone 120 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setdomainname 121 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::modify_ldt 123 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::adjtimex 124 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mprotect 10 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sigprocmask 126 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::create_module	127 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::init_module	128 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::delete_module	129 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::get_kernel_syms	130 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::quotactl 131 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getpgid 132 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::bdflush 134 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sysfs 135 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::personality 136 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setfsuid 138 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setfsgid 139 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getdents 141 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::_newselect 142 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::flock 143 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::msync 26 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::readv 19 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::writev 20 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getsid 147 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::fdatasync 148 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::_sysctl 149 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mlock 150 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::munlock 151 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mlockall 152 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::munlockall 153 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_setparam 154 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_getparam 155 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_setscheduler 156 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_getscheduler 157 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_yield 24 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_get_priority_max 159 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_get_priority_min 160 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sched_rr_get_interval 161 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::nanosleep 35 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mremap 25 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setresuid 164 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getresuid 165 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::query_module	166 () )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::nfsservctl 168 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::setresgid 169 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getresgid 170 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::prctl 171 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigreturn 15 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigaction 13 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigprocmask 14 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigpending 175 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigtimedwait 176 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigqueueinfo 177 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigsuspend 178 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::pread 17 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::pwrite 18 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::chown 181 (:address) )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::capget 183 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::capset 184 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sigaltstack 185 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::sendfile 40 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::getpmsg 187	 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::putpmsg 188	 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::vfork 189 () )
+
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::mmap 9 () )
+(define-syscall (logior platform-os-freebsd platform-cpu-x86 platform-word-size-64)  syscalls::munmap 73 () )
+
+)
Index: /branches/new-random/library/x8664-linux-syscalls.lisp
===================================================================
--- /branches/new-random/library/x8664-linux-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/x8664-linux-syscalls.lisp	(revision 13309)
@@ -0,0 +1,261 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL"))
+
+
+
+
+
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::read 0 (:int :address :size_t)
+		:ssize_t)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::write 1 (:int :address :size_t)
+		:ssize_t)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::open 2 (:address :int :mode_t) :int :min-args 2)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::close 3 (:int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::stat 4 (:address :address) :signed-fullword)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fstat 5 (:unsigned-fullword :address) :signed-fullword )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::lstat 6 (:address :address) :signed-fullword)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64) syscalls::poll 7 ((:* (:struct :pollfd)) :int :int) :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::lseek 8 (:int :off_t :int) :off_t )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::exit 60 (:int) :void)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fork 57 () :pid_t)
+
+
+
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::creat 85 (:address :mode_t) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::link 86 (:address :address) :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::unlink 87 (:address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::execve 59 (:address :address :address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::chdir 80 (:address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::time 201 (:address) :time_t )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mknod 133 (:address :mode_t :dev_t)
+		:int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::chmod 90 (:address :mode_t) :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::lchown 94 (:address :uid_t :gid_t)
+		:int)
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getpid 39 () :pid_t)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mount 165 (:address
+				 :address
+				 :address
+				 :unsigned-long
+				 :address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::umount2 166 (:address :int) :int )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setuid 105 (:uid_t) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getuid 102 () :uid_t )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::ptrace 101 (:unsigned-fullword
+				  :pid_t
+				  :address
+				  :address)
+		:long)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::alarm 37 (:unsigned) :unsigned )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::pause 34 () :unt)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::utime 132 (:address :address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::access 21 (:address :int) :int)
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sync 162 () :void )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::kill 62 (:pid_t :int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rename 82 (:address :address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mkdir 83 (:address :mode_t) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rmdir 84 (:address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::dup 32 (:int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::pipe 22 (:address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::times 100 (:address) :clock_t )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::brk 12 (:address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setgid 106 (:gid_t) :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getgid 104 () :gid_t )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::geteuid 107 () :uid_t )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getegid 108 () :gid_t)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::acct 163 (:address) :INT )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::ioctl 16 (:int :int :address) :int :min-args 2 )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fcntl 72 (:int :int :long) :int :min-args 2 )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setpgid 109 (:pid_t :gid_t) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::umask 95 (:mode_t) :mode_t )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::chroot 161 (:address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::ustat 136 (:dev_t :address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::dup2 33 (:int :int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getppid 110 () :pid_t)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getpgrp 111 () :gid_t)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setsid 112 () :pid_t)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt-sigaction 13 (:unsigned-fullword :address :address) :signed-fullword )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getrusage 98 (:int :address) :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::gettimeofday 96 (:address :address) :void)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::ftruncate 77 (:int :off_t)
+		:int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fchmod 91 (:int :mode_t)
+		:int )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::socket 41 (:int :int :int)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::connect 42 (:int :address :socklen_t)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::accept 43 (:int :address :address)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sendto 44 (:int :address :size_t :int :address :socklen_t) :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64) syscalls::recvfrom 45 (:int :address :size_t :int :address :address) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64) syscalls::sendmsg 46 (:int :address :int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64) syscalls::recvmsg 47 (:int :address :int) :int )
+(define-syscall  (logior platform-os-linux platform-cpu-x86 platform-word-size-64) syscalls::shutdown 48 (:int :int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::bind 49 (:int :address :socklen_t)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::listen 50 (:int  :int)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getsockname 51 (:int :address :address)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getpeername 52 (:int :address :address)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::socketpair 53 (:int :int :int  :address)
+		:int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64) syscalls::setsockopt 54 (:int :int :int :address :socklen_t) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64) syscalls::getsockopt 55 (:int :int :int :address :address) :int )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fsync 118 (:int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::uname 63  (:address) :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fchdir 133 (:int) :int )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::_llseek 140 (:unsigned-fullword :unsigned-fullword :unsigned-fullword :address :unsigned-fullword) :signed-fullword )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64) 	syscalls::select 23 (:int :address :address
+                                                  :address :address)
+                :int)
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getcwd 79 (:address :unsigned-long) :long )
+
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::futex 202 (:address :int :int :address :address :int) :int )
+
+#+notdefinedyet
+(progn
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sgetmask 68 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::ssetmask 69 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setreuid 70 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setregid 71 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sigsuspend 72 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sigpending 73 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sethostname 74 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setrlimit 75 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getrlimit 76 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::settimeofday 79 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getgroups 80 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setgroups 81 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::symlink 83 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::oldlstat 84 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::readlink 85 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::uselib 86 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::swapon 87 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::reboot 88 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::readdir 89 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::truncate 92 () )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fchown 95 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getpriority 96 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setpriority 97 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::statfs 99 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fstatfs 100 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::ioperm 101 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::syslog 103 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setitimer 38 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getitimer 36 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::olduname 109 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::iopl 110 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::vhangup 111 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::idle 112 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::vm86 113 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::wait4 114 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::swapoff 115 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sysinfo 116 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::ipc 117 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sigreturn 119 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::clone 120 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setdomainname 121 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::modify_ldt 123 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::adjtimex 124 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mprotect 10 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sigprocmask 126 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::create_module	127 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::init_module	128 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::delete_module	129 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::get_kernel_syms	130 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::quotactl 131 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getpgid 132 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::bdflush 134 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sysfs 135 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::personality 136 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setfsuid 138 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setfsgid 139 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getdents 141 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::_newselect 142 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::flock 143 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::msync 26 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::readv 19 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::writev 20 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getsid 147 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::fdatasync 148 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::_sysctl 149 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mlock 150 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::munlock 151 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mlockall 152 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::munlockall 153 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_setparam 154 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_getparam 155 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_setscheduler 156 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_getscheduler 157 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_yield 24 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_get_priority_max 159 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_get_priority_min 160 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sched_rr_get_interval 161 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::nanosleep 35 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mremap 25 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setresuid 164 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getresuid 165 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::query_module	166 () )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::nfsservctl 168 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::setresgid 169 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getresgid 170 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::prctl 171 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigreturn 15 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigaction 13 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigprocmask 14 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigpending 175 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigtimedwait 176 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigqueueinfo 177 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::rt_sigsuspend 178 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::pread 17 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::pwrite 18 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::chown 181 (:address) )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::capget 183 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::capset 184 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sigaltstack 185 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::sendfile 40 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::getpmsg 187	 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::putpmsg 188	 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::vfork 189 () )
+
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::mmap 9 () )
+(define-syscall (logior platform-os-linux platform-cpu-x86 platform-word-size-64)  syscalls::munmap 11 () )
+
+)
Index: /branches/new-random/library/x8664-solaris-syscalls.lisp
===================================================================
--- /branches/new-random/library/x8664-solaris-syscalls.lisp	(revision 13309)
+++ /branches/new-random/library/x8664-solaris-syscalls.lisp	(revision 13309)
@@ -0,0 +1,493 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2008-2009 Clozure Associates and contributors
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "SYSCALL"))
+
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::syscall 0 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::exit 1 (:int) :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::forkall 2 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::read 3 (:int :address :size_t) :ssize_t)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::write 4 (:int :address :size_t) :ssize_t)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::open 5 (:address :int :mode_t) :int :min-args 2)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::close 6 (:int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::wait 7 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::creat 8 (:address :mode_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::link 9 (:address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::unlink 10 (:address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::exec 11 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::chdir 12 (:address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::time 13 (:address) :time_t)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::mknod 14 (:address :mode_t :dev_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::chmod 15 (:address :mode_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::chown 16 (:address :uid_t :gid_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::brk 17 (:address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::stat 18 (:address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lseek 19 (:int :off_t :int) :off_t)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getpid 20 () :pid_t)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::mount 21 (:address :address :int :address :address :int :adress :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::umount 22 (:address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setuid 23 (:uid_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getuid 24 () :uid_t)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::stime 25 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pcsample 26 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::alarm 27 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fstat 28 (:int :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pause 29 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::utime 30 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::stty 31 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::gtty 32 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::access 33 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::nice 34 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::statfs 35 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sync 36 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::kill 37 (:pid_t :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fstatfs 38 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pgrpsys 39 () :void)
+ #||
+ * subcodes:
+ * getpgrp()  :: syscall(39,0)
+ * setpgrp()  :: syscall(39,1)
+ * getsid(pid)  :: syscall(39,2,pid)
+ * setsid()  :: syscall(39,3)
+ * getpgid(pid)  :: syscall(39,4,pid)
+ * setpgid(pid,pgid) :: syscall(39,5,pid,pgid)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::uucopystr 40 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::dup 41 (:int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pipe 42 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::times 43 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::profil 44 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::plock 45 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setgid 46 (:gid_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getgid 47 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::signal 48 () :void)
+ #||
+ * subcodes:
+ * signal(sig, f) :: signal(sig, f)  ((sig&SIGNO_MASK) == sig)
+ * sigset(sig, f) :: signal(sig|SIGDEFER, f)
+ * sighold(sig)  :: signal(sig|SIGHOLD)
+ * sigrelse(sig) :: signal(sig|SIGRELSE)
+ * sigignore(sig) :: signal(sig|SIGIGNORE)
+ * sigpause(sig) :: signal(sig|SIGPAUSE)
+ * see <sys/signal.h>
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::msgsys 49 () :void)
+ #||
+ * subcodes:
+ * msgget(...) :: msgsys(0, ...)
+ * msgctl(...) :: msgsys(1, ...)
+ * msgrcv(...) :: msgsys(2, ...)
+ * msgsnd(...) :: msgsys(3, ...)
+ * msgids(...) :: msgsys(4, ...)
+ * msgsnap(...) :: msgsys(5, ...)
+ * see <sys/msg.h>
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sysi86 50 () :void)
+ #||
+ * subcodes:
+ * sysi86(code, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::acct 51 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::shmsys 52 () :void)
+ #||
+ * subcodes:
+ * shmat (...) :: shmsys(0, ...)
+ * shmctl(...) :: shmsys(1, ...)
+ * shmdt (...) :: shmsys(2, ...)
+ * shmget(...) :: shmsys(3, ...)
+ * shmids(...) :: shmsys(4, ...)
+ * see <sys/shm.h>
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::semsys 53 () :void)
+ #||
+ * subcodes:
+ * semctl(...) :: semsys(0, ...)
+ * semget(...) :: semsys(1, ...)
+ * semop (...) :: semsys(2, ...)
+ * semids(...) :: semsys(3, ...)
+ * semtimedop(...) :: semsys(4, ...)
+ * see <sys/sem.h>
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::ioctl 54 (:int :int :address) :int :min-args 2)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::uadmin 55 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::utssys 57 () :void)
+ #||
+ * subcodes (third argument):
+ * uname(obuf) (obsolete)  :: syscall(57, obuf, ign, 0)
+ *   subcode 1 unused
+ * ustat(dev, obuf)  :: syscall(57, obuf, dev, 2)
+ * fusers(path, flags, obuf) :: syscall(57, path, flags, 3, obuf)
+ * see <sys/utssys.h>
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fdsync 58 (:int :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::execve 59 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::umask 60 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::chroot 61 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fcntl 62 (:int :int :address) :int :min-args 2)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::ulimit 63 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::reserved_64 64 #|| 64 reserved ||# () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::reserved_65 65 #|| 65 reserved ||# () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::reserved_66 66 #|| 66 reserved ||# () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::reserved_67 67 #|| 67 reserved ||# () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::reserved_68 68 #|| 68 reserved ||# () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::reserved_69 69 #|| 69 reserved ||# () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::tasksys 70 () :void)
+ #||
+ * subcodes:
+ * settaskid(...) :: tasksys(0, ...)
+ * gettaskid(...) :: tasksys(1, ...)
+ * getprojid(...) :: tasksys(2, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::acctctl 71 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::exacctsys 72 () :void)
+ #||
+ * subcodes:
+ * getacct(...) :: exacct(0, ...)
+ * putacct(...) :: exacct(1, ...)
+ * wracct(...) :: exacct(2, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getpagesizes 73 () :void)
+ #||
+ * subcodes:
+ * getpagesizes2(...) :: getpagesizes(0, ...)
+ * getpagesizes(...) :: getpagesizes(1, ...) legacy
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::rctlsys 74 () :void)
+ #||
+ * subcodes:
+ * getrctl(...) :: rctlsys(0, ...)
+ * setrctl(...) :: rctlsys(1, ...)
+ * rctllist(...) :: rctlsys(2, ...)
+ * rctlctl(...) :: rctlsys(3, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sidsys 75 () :void)
+ #||
+ * subcodes:
+ * allocids(...) :: sidsys(0, ...)
+ * idmap_reg(...) :: sidsys(1, ...)
+ * idmap_unreg(...) :: sidsys(2, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fsat 76 () :void)
+ #||
+ * subcodes:
+ * openat(...) :: fsat(0, ...)
+ * openat64(...) :: fsat(1, ...)
+ * fstatat64(...) :: fsat(2, ...)
+ * fstatat(...) :: fsat(3, ...)
+ * renameat(...) :: fsat(4, ...)
+ * fchownat(...) :: fsat(5, ...)
+ * unlinkat(...) :: fsat(6, ...)
+ * futimesat(...) :: fsat(7, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_park 77 () :void)
+ #||
+ * subcodes:
+ * _lwp_park(timespec_t *, lwpid_t) :: syslwp_park(0, ...)
+ * _lwp_unpark(lwpid_t, int) :: syslwp_park(1, ...)
+ * _lwp_unpark_all(lwpid_t *, int) :: syslwp_park(2, ...)
+ * _lwp_unpark_cancel(lwpid_t *, int) :: syslwp_park(3, ...)
+ * _lwp_set_park(lwpid_t *, int)  :: syslwp_park(4, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sendfilev 78 () :void)
+ #||
+ * subcodes :
+ * sendfilev()  :: sendfilev(0, ...)
+ * sendfilev64() :: sendfilev(1, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::rmdir 79 (:address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::mkdir 80 (:address :mode_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getdents 81 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::privsys 82 () :void)
+ #||
+ * subcodes:
+ * setppriv(...) :: privsys(0, ...)
+ * getppriv(...) :: privsys(1, ...)
+ * getimplinfo(...) :: privsys(2, ...)
+ * setpflags(...)  :: privsys(3, ...)
+ * getpflags(...)  :: privsys(4, ...)
+ * issetugid(); :: privsys(5)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::ucredsys 83 () :void)
+ #||
+ * subcodes:
+ * ucred_get(...) :: ucredsys(0, ...)
+ * getpeerucred(...) :: ucredsys(1, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sysfs 84 () :void)
+ #||
+ * subcodes:
+ * sysfs(code, ...)
+ * see <sys/fstyp.h>
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getmsg 85 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::putmsg 86 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::poll 87 (:address :nfds_t :int) :int)
+
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lstat 88 (:address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::symlink 89 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::readlink 90 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setgroups 91 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getgroups 92 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fchmod 93 (:int :mode_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fchown 94 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigprocmask 95 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigsuspend 96 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigaltstack 97 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigaction 98 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigpending 99 () :void)
+ #||
+ * subcodes:
+ *  subcode 0 unused
+ * sigpending(...) :: syscall(99, 1, ...)
+ * sigfillset(...) :: syscall(99, 2, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::context 100 () :void)
+ #||
+ * subcodes:
+ * getcontext(...) :: syscall(100, 0, ...)
+ * setcontext(...) :: syscall(100, 1, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::evsys 101 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::evtrapret 102 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::statvfs 103 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fstatvfs 104 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getloadavg 105 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::nfssys 106 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::waitid 107 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigsendsys 108 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::hrtsys 109 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigresend 111 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::priocntlsys 112 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pathconf 113 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::mincore 114 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::mmap 115 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::mprotect 116 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::munmap 117 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fpathconf 118 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::vfork 119 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fchdir 120 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::readv 121 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::writev 122 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::xstat 123 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lxstat 124 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fxstat 125 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::xmknod 126 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setrlimit 128 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getrlimit 129 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lchown 130 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::memcntl 131 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getpmsg 132 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::putpmsg 133 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::rename 134 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::uname 135 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setegid 136 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sysconfig 137 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::adjtime 138 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::systeminfo 139 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sharefs 140 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::seteuid 141 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::forksys 142 () :void)
+ #||
+ * subcodes:
+ * forkx(flags)  :: forksys(0, flags)
+ * forkallx(flags) :: forksys(1, flags)
+ * vforkx(flags)  :: forksys(2, flags)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fork1 143 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigtimedwait 144 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_info 145 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::yield 146 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_sema_wait 147 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_sema_post 148 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_sema_trywait 149 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_detach 150 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::corectl 151 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::modctl 152 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fchroot 153 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::utimes 154 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::vhangup 155 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::gettimeofday 156 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getitimer 157 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setitimer 158 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_create 159 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_exit 160 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_suspend 161 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_continue 162 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_kill 163 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_self 164 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_sigmask 165 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_private 166 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_wait 167 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_mutex_wakeup 168 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_mutex_lock 169 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_cond_wait 170 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_cond_signal 171 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_cond_broadcast 172 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pread 173 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pwrite 174 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::llseek 175 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::inst_sync 176 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::brand 177 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::kaio 178 () :void)
+ #||
+ * subcodes:
+ * aioread(...) :: kaio(AIOREAD, ...)
+ * aiowrite(...) :: kaio(AIOWRITE, ...)
+ * aiowait(...) :: kaio(AIOWAIT, ...)
+ * aiocancel(...) :: kaio(AIOCANCEL, ...)
+ * aionotify() :: kaio(AIONOTIFY)
+ * aioinit() :: kaio(AIOINIT)
+ * aiostart() :: kaio(AIOSTART)
+ * see <sys/aio.h>
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::cpc  179 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lgrpsys 180 () :void)
+ #||
+ * subcodes:
+ * meminfo(...) :: meminfosys(MIsyscalls::MEMINFO, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::rusagesys 181 (:int :int :address) :int)
+ #||
+ * subcodes:
+ * getrusage(...) :: rusagesys(RUSAGEsyscalls::GETRUSAGE, ...)
+ * getvmusage(...)  :: rusagesys(RUSAGEsyscalls::GETVMUSAGE, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::port 182 () :void)
+ #||
+ * subcodes:
+ * port_create(...) :: portfs(PORT_CREATE, ...)
+ * port_associate(...) :: portfs(PORT_ASSOCIATE, ...)
+ * port_dissociate(...) :: portfs(PORT_DISSOCIATE, ...)
+ * port_send(...) :: portfs(PORT_SEND, ...)
+ * port_sendn(...) :: portfs(PORT_SENDN, ...)
+ * port_get(...) :: portfs(PORT_GET, ...)
+ * port_getn(...) :: portfs(PORT_GETN, ...)
+ * port_alert(...) :: portfs(PORT_ALERT, ...)
+ * port_dispatch(...) :: portfs(PORT_DISPATCH, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pollsys 183 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::labelsys 184 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::acl  185 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::auditsys 186 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::processor_bind 187 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::processor_info 188 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::p_online 189 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sigqueue 190 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::clock_gettime 191 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::clock_settime 192 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::clock_getres 193 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::timer_create 194 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::timer_delete 195 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::timer_settime 196 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::timer_gettime 197 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::timer_getoverrun 198 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::nanosleep 199 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::facl 200 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::door 201 () :void)
+ #||
+ * Door Subcodes:
+ * 0 door_create
+ * 1 door_revoke
+ * 2 door_info
+ * 3 door_call
+ * 4 door_return
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setreuid 202 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setregid 203 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::install_utrap 204 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::signotify 205 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::schedctl 206 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pset 207 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sparc_utrap_install 208 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::resolvepath 209 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_mutex_timedlock 210 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_sema_timedwait 211 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_rwlock_sys 212 () :void)
+ #||
+ * subcodes:
+ * lwp_rwlock_rdlock(...)  :: syscall(212, 0, ...)
+ * lwp_rwlock_wrlock(...)  :: syscall(212, 1, ...)
+ * lwp_rwlock_tryrdlock(...) :: syscall(212, 2, ...)
+ * lwp_rwlock_trywrlock(...) :: syscall(212, 3, ...)
+ * lwp_rwlock_unlock(...)  :: syscall(212, 4, ...)
+ ||#
+#|| system calls for large file ( > 2 gigabyte) support ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getdents64 213 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::mmap64 214 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::stat64 215 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lstat64 216 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fstat64 217 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::statvfs64 218 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::fstatvfs64 219 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setrlimit64 220 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getrlimit64 221 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pread64 222 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::pwrite64 223 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::creat64 224 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::open64 225 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::rpcsys 226 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::zone 227 () :void)
+ #||
+ * subcodes:
+ * zone_create(...) :: zone(ZONE_CREATE, ...)
+ * zone_destroy(...) :: zone(ZONE_DESTROY, ...)
+ * zone_getattr(...) :: zone(ZONE_GETATTR, ...)
+ * zone_enter(...) :: zone(ZONE_ENTER, ...)
+ * zone_list(...) :: zone(ZONE_LIST, ...)
+ * zone_shutdown(...) :: zone(ZONE_SHUTDOWN, ...)
+ * zone_lookup(...) :: zone(ZONE_LOOKUP, ...)
+ * zone_boot(...) :: zone(ZONE_BOOT, ...)
+ * zone_version(...) :: zone(ZONE_VERSION, ...)
+ * zone_setattr(...) :: zone(ZONE_SETATTR, ...)
+ * zone_add_datalink(...) :: zone(ZONE_ADD_DATALINK, ...)
+ * zone_remove_datalink(...) :: zone(ZONE_DEL_DATALINK, ...)
+ * zone_check_datalink(...) :: zone(ZONE_CHECK_DATALINK, ...)
+ * zone_list_datalink(...) :: zone(ZONE_LIST_DATALINK, ...)
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::autofssys 228 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getcwd 229 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::so_socket 230 (:int :int :int :address :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::so_socketpair 231 (:address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::bind 232 (:int :address :socklen_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::listen 233 (:int :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::accept 234 (:int :address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::connect 235 (:int :address :socklen_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::shutdown 236 (:int :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::recv 237 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::recvfrom 238 (:int :address :size_t :int :address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::recvmsg 239 (:int :address :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::send 240 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sendmsg 241 (:int :address :int) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sendto 242 (:int :address :size_t :int :address :socklen_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getpeername 243 (:int :address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getsockname 244 (:int :address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::getsockopt 245 (:int :int :int :address :address) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::setsockopt 246 (:int :int :int :address :socklen_t) :int)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::sockconfig 247 () :void)
+ #||
+ * NTP codes
+ ||#
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::ntp_gettime 248 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::ntp_adjtime 249 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_mutex_unlock 250 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_mutex_trylock 251 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::lwp_mutex_register 252 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::cladm 253 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::uucopy 254 () :void)
+(define-syscall (logior platform-os-solaris platform-cpu-x86 platform-word-size-64) syscalls::umount2 255 () :void)
Index: /branches/new-random/lisp-kernel/.cvsignore
===================================================================
--- /branches/new-random/lisp-kernel/.cvsignore	(revision 13309)
+++ /branches/new-random/lisp-kernel/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/lisp-kernel/Threads.h
===================================================================
--- /branches/new-random/lisp-kernel/Threads.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/Threads.h	(revision 13309)
@@ -0,0 +1,275 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include <stdlib.h>
+#ifndef WINDOWS
+#include <unistd.h>
+#include <sys/mman.h>
+#endif
+#undef __argv
+#include <stdio.h>
+#ifndef WINDOWS
+#include <pthread.h>
+#endif
+#ifdef WINDOWS
+#include <process.h>
+#endif
+#include <errno.h>
+#include <limits.h>
+
+#ifdef SOLARIS
+#include <sys/syscall.h>
+#include <sys/lwp.h>
+#endif
+
+#ifdef LINUX
+#include <sys/syscall.h>
+#endif
+
+#undef USE_MACH_SEMAPHORES
+#define USE_POSIX_SEMAPHORES
+#undef USE_WINDOWS_SEMAPHORES
+
+#ifdef DARWIN
+#define USE_MACH_SEMAPHORES 1
+#undef  USE_POSIX_SEMAPHORES
+#endif
+#ifdef WINDOWS
+#define USE_WINDOWS_SEMAPHORES 1
+#undef USE_POSIX_SEMAPHORES
+#ifdef WIN_32
+struct timespec {
+  int tv_sec;
+  int tv_nsec;
+};
+#endif
+#endif
+
+#ifdef USE_POSIX_SEMAPHORES
+#include <semaphore.h>
+#endif
+
+
+#ifdef USE_MACH_SEMAPHORES
+/* We have to use Mach semaphores, even if we're otherwise 
+   using POSIX signals, etc. */
+#include <mach/task.h>
+#include <mach/semaphore.h>
+#endif
+
+#include <limits.h>
+
+#ifdef FREEBSD
+#include <pthread_np.h>
+#endif
+
+#ifndef WINDOWS
+#include <sched.h>
+#endif
+
+#include "lisp.h"
+#include "lisp_globals.h"
+#include "gc.h"
+
+#ifdef USE_FUTEX
+#ifndef FUTEX_WAIT
+#define FUTEX_WAIT (0)
+#endif
+#ifndef FUTEX_WAKE
+#define FUTEX_WAKE (1)
+#endif
+#include <sys/syscall.h>
+#endif
+
+#ifndef WINDOWS
+#include <syslog.h>
+#endif
+
+Boolean extern threads_initialized;
+Boolean extern log_tcr_info;
+
+#define LOCK_SPINLOCK(x,tcr) get_spin_lock(&(x),tcr)
+#define RELEASE_SPINLOCK(x) (x)=0
+
+#define TCR_TO_TSD(tcr) ((void *)((natural)(tcr)+TCR_BIAS))
+#define TCR_FROM_TSD(tsd) ((TCR *)((natural)(tsd)-TCR_BIAS))
+
+#ifdef USE_WINDOWS_SEMAPHORES
+
+typedef void * SEMAPHORE;
+#define SEM_WAIT(s) WaitForSingleObject(s,INFINITE)
+#define SEM_RAISE(s) ReleaseSemaphore(s, 1L, NULL)
+#define SEM_BROADCAST(s, count) do {while(count) {SEM_RAISE(s);(count)--;}}while(0)
+#define SEM_TIMEDWAIT(s,t) WaitOnSingleObject(s,t)
+
+#endif
+#ifdef USE_POSIX_SEMAPHORES
+typedef sem_t * SEMAPHORE;
+#define SEM_WAIT(s) sem_wait((SEMAPHORE)s)
+#define SEM_RAISE(s) sem_post((SEMAPHORE)s)
+#define SEM_BROADCAST(s, count) do {while(count) {SEM_RAISE(s);(count)--;}}while(0)
+#define SEM_TIMEDWAIT(s,t) sem_timedwait((SEMAPHORE)s,(struct timespec *)t)
+#endif
+
+#ifdef USE_MACH_SEMAPHORES
+typedef semaphore_t SEMAPHORE;
+#define SEM_WAIT(s) semaphore_wait((SEMAPHORE)(natural)s)
+#define SEM_RAISE(s) semaphore_signal((SEMAPHORE)(natural)s)
+#define SEM_BROADCAST(s,count)semaphore_signal_all((SEMAPHORE)(natural)s)
+#define SEM_TIMEDWAIT(s,t) semaphore_timedwait((SEMAPHORE)(natural)s,t)
+#endif
+
+void sem_wait_forever(SEMAPHORE s);
+
+#ifdef USE_POSIX_SEMAPHORES
+#define SEM_WAIT_FOREVER(s) sem_wait_forever((SEMAPHORE)s)
+#endif
+
+#ifdef USE_MACH_SEMAPHORES
+#define SEM_WAIT_FOREVER(s) sem_wait_forever((SEMAPHORE)(natural)s)
+#endif
+
+#ifdef USE_WINDOWS_SEMAPHORES
+#define SEM_WAIT_FOREVER(s) sem_wait_forever((SEMAPHORE)s)
+#endif
+
+typedef struct
+{
+  signed_natural avail;
+  TCR* owner;
+  signed_natural  count;
+  void* signal;
+  signed_natural waiting;
+  void *malloced_ptr;
+  signed_natural spinlock;
+} _recursive_lock, *RECURSIVE_LOCK;
+
+
+int lock_recursive_lock(RECURSIVE_LOCK, TCR *);
+int unlock_recursive_lock(RECURSIVE_LOCK, TCR *);
+RECURSIVE_LOCK new_recursive_lock(void);
+void destroy_recursive_lock(RECURSIVE_LOCK);
+int recursive_lock_trylock(RECURSIVE_LOCK, TCR *, int *);
+
+#define LOCK(m, t) lock_recursive_lock((RECURSIVE_LOCK)ptr_from_lispobj(m), (TCR *)t)
+#define UNLOCK(m, t) unlock_recursive_lock((RECURSIVE_LOCK)ptr_from_lispobj(m), (TCR *)t)
+
+/* Hmm.  This doesn't look like the MacOS Thread Manager ... */
+LispObj current_thread_osid(void);
+void *current_native_thread_id(void);
+void *new_semaphore(int);
+void destroy_semaphore(void**);
+void tsd_set(LispObj, void *);
+void *tsd_get(LispObj);
+TCR *new_tcr(natural, natural);
+TCR *initial_thread_tcr;
+
+#define DEFAULT_THREAD_STACK_SIZE ((size_t) -1)
+#define MINIMAL_THREAD_STACK_SIZE ((size_t) 0)
+
+
+LispObj create_system_thread(size_t stack_size, 
+			     void* stackaddr,
+#ifdef WINDOWS
+                             unsigned CALLBACK (*start_routine)(void *)
+#else
+			     void* (*start_routine)(void *)
+#endif
+                             ,
+			     void* param);
+
+TCR *get_tcr(Boolean);
+TCR *get_interrupt_tcr(Boolean);
+Boolean suspend_tcr(TCR *);
+Boolean resume_tcr(TCR *);
+
+typedef struct
+{
+  signed_natural spin; /* need spin lock to change fields */
+  signed_natural state; /* 0 = free, positive if writer, negative if readers; */
+  natural blocked_writers;
+  natural blocked_readers;
+  TCR  *writer;
+#ifdef USE_FUTEX
+  natural reader_signal;
+  natural writer_signal;
+#else
+  void * reader_signal;
+  void * writer_signal;
+#endif
+  void *malloced_ptr;
+} rwlock;
+
+
+rwlock * rwlock_new(void);
+void rwlock_destroy(rwlock *);
+int rwlock_rlock(rwlock *, TCR *, struct timespec *);
+int rwlock_wlock(rwlock *, TCR *, struct timespec *);
+int rwlock_try_wlock(rwlock *, TCR *);
+int rwlock_try_rlock(rwlock *, TCR *);
+int rwlock_unlock(rwlock *, TCR *);
+
+
+natural 
+atomic_and(natural*, natural);
+
+natural 
+atomic_ior(natural*, natural);
+
+#define SET_TCR_FLAG(t,bit) atomic_ior(&(t->flags),(1L<<bit))
+#define CLR_TCR_FLAG(t,bit) atomic_and(&(t->flags),~(1L<<bit))
+
+
+#if defined(SIGRTMIN) && !defined(SOLARIS)
+#define SIG_SUSPEND_THREAD (SIGRTMIN+6)
+#else
+#define SIG_SUSPEND_THREAD SIGUSR2
+#endif
+
+
+#ifdef DARWIN
+#define SIG_KILL_THREAD SIGEMT
+#endif
+
+#if defined(LINUX) && defined(SIGRTMIN)
+#define SIG_KILL_THREAD (SIGRTMIN+7)
+#endif
+
+#ifdef SOLARIS
+#define SIG_KILL_THREAD SIGRTMIN
+#endif
+
+#ifdef FREEBSD
+#define SIG_KILL_THREAD (SIGTHR+5)
+#endif
+
+
+extern int thread_suspend_signal, thread_kill_signal;
+
+void *
+allocate_stack(natural);
+
+void
+suspend_resume_handler(int, siginfo_t *, ExceptionInformation *);
+
+/* Maybe later
+Boolean
+rwlock_try_rlock(rwlock *);
+
+Boolean
+rwlock_try_wlock(rwlock *);
+*/
Index: /branches/new-random/lisp-kernel/area.h
===================================================================
--- /branches/new-random/lisp-kernel/area.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/area.h	(revision 13309)
@@ -0,0 +1,219 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __AREA_H__
+#define __AREA_H__ 1
+
+
+#include "bits.h"
+#include "memprotect.h"
+
+
+
+typedef enum {
+  AREA_VOID = 0,		/* Not really an area at all */
+  AREA_CSTACK = 1<<fixnumshift, /* A control stack */
+  AREA_VSTACK = 2<<fixnumshift, /* A value stack.  The GC sees it as being doubleword-aligned */
+  AREA_TSTACK = 3<<fixnumshift, /* A temp stack.  It -is- doubleword-aligned */
+  AREA_READONLY = 4<<fixnumshift, /* A (cfm) read-only section. */
+  AREA_WATCHED = 5<<fixnumshift, /* A static area containing a single object. */
+  AREA_STATIC_CONS = 6<<fixnumshift, /* static, conses only */
+  AREA_MANAGED_STATIC = 7<<fixnumshift, /* A resizable static area */
+  AREA_STATIC = 8<<fixnumshift, /* A  static section: contains
+                                 roots, but not GCed */
+  AREA_DYNAMIC = 9<<fixnumshift /* A heap. Only one such area is "the heap."*/
+} area_code;
+
+typedef struct area {
+  struct area* pred;            /* linked list predecessor */
+  struct area* succ;            /* linked list successor */
+  char* low;                    /* arithmetic lower limit on addresses
+                                   (inclusive) */
+  char* high;                   /* arithmetic upper limit on addresses
+                                   (exclusive) */
+  char* active;                 /* low bound (stack) or high bound
+                                   (heap) */
+  char* softlimit;		/* only makes sense for dynamic heaps
+                                   & stacks */
+  char* hardlimit;		/* only makes sense for dynamic heaps
+                                   & stacks */
+  natural code;
+  natural*  markbits;           /* markbits for active area */
+  natural ndnodes;		/* "active" size of dynamic area or
+                                   stack */
+  struct area* older;		/* if ephemeral, the next older ephemeral area
+				 or the dynamic area */
+  struct area* younger;         /* if ephemeral, the next "younger"
+                                  ephemeral area if there is one.  If
+                                  dynamic, the oldest ephemeral
+                                  area. */
+  char*  h;			/* The pointer allocated to contain
+				 this area, or NULL if the operating
+				 system allocated it for us. */
+  protected_area* softprot;     /* "soft" protected_area */
+  protected_area* hardprot;     /* "hard" protected_area */
+  TCR * owner;                  /* TCR that the area belongs to, if a stack */
+  natural*  refbits;            /* intergenerational references.  May
+                                               or may not be the same
+                                               as markbits */
+  natural threshold;            /* egc threshold (boxed "fullword
+                                   count") or 0 */
+  LispObj gccount;              /* boxed generation GC count. */
+  natural static_dnodes;        /* for hash consing, maybe other things. */
+  natural *static_used;         /* bitvector */
+} area;
+
+
+/*
+  Areas are kept in a doubly-linked list.
+  The list header is just a distinguished element of
+  that list; by convention, the "active" dynamic
+  area is described by that header's successor, and areas
+  that may have entries in their "markbits" vector (heaps)
+  precede (in the area_list->succ sense) those  that don't (stacks).
+  The list header's "area" pointer is an "AREA_VOID" area; the header
+  (once allocated during kernel initialization) never
+  moves or changes.  Lisp code can get its hands on
+  the list header via a nilreg global, and carefully,
+  atomically, traverse it to do ROOM, etc.
+*/
+
+
+area *new_area(BytePtr, BytePtr, area_code);
+void add_area(area *, TCR *);
+void add_area_holding_area_lock(area *);
+void condemn_area(area *, TCR *);
+void condemn_area_holding_area_lock(area *);
+area *area_containing(BytePtr);
+area *stack_area_containing(BytePtr);
+area *heap_area_containing(BytePtr);
+void tenure_to_area(area *);
+void untenure_from_area(area *);
+
+/* serialize add_area/remove_area, and also the tcr queue */
+void *tcr_area_lock;
+
+#define reserved_area ((area *)(all_areas))
+#define active_dynamic_area ((area *)(reserved_area->succ))
+
+typedef struct area_list {
+  area *the_area;
+  struct area_list *next;
+} area_list;
+
+/* The useable size of a tsp or vsp stack segment.
+  */
+/* #define STACK_SEGMENT_SIZE (64<<10) */
+#define MIN_CSTACK_SIZE (1<<17)
+#define CSTACK_HARDPROT (100<<10)
+#define CSTACK_SOFTPROT (100<<10)
+#define MIN_VSTACK_SIZE (1<<16)
+#define VSTACK_HARDPROT (1<<12)
+#define VSTACK_SOFTPROT (1<<16)
+#define MIN_TSTACK_SIZE (1<<18)
+#define TSTACK_HARDPROT 0
+#define TSTACK_SOFTPROT (1<<16)
+#ifdef PPC
+#define CS_OVERFLOW_FORCE_LIMIT ((natural)(-(sizeof(lisp_frame))))
+#endif
+
+#ifdef X86
+#define CS_OVERFLOW_FORCE_LIMIT ((natural)(-16))
+#endif
+
+
+#ifdef PPC
+#ifdef LINUX
+#ifdef PPC64
+#define IMAGE_BASE_ADDRESS 0x50000000000L
+#else
+#define IMAGE_BASE_ADDRESS 0x31000000
+#endif
+#endif
+#ifdef DARWIN
+#ifdef PPC64
+#define IMAGE_BASE_ADDRESS 0x300000000000L
+#else
+#define IMAGE_BASE_ADDRESS 0x04000000
+#endif
+#endif
+#endif
+
+#ifdef X86
+#ifdef LINUX
+#ifdef X8664
+#define IMAGE_BASE_ADDRESS 0x300000000000L
+#else
+#define IMAGE_BASE_ADDRESS 0x10000000
+#endif
+#endif
+#ifdef FREEBSD
+#ifdef X8664
+#define IMAGE_BASE_ADDRESS 0x300000000000L /* 0x100000000L */
+#else
+#define IMAGE_BASE_ADDRESS 0x30000000
+#endif
+#endif
+#ifdef SOLARIS
+#ifdef X8664
+#define IMAGE_BASE_ADDRESS 0x300000000000L
+#else
+#define IMAGE_BASE_ADDRESS 0x10000000
+#endif
+#endif
+#ifdef DARWIN
+#ifdef X8664
+#define IMAGE_BASE_ADDRESS 0x300000000000L
+#else
+#define IMAGE_BASE_ADDRESS 0x04000000
+#endif
+#endif
+#endif
+#ifdef WINDOWS
+#ifdef X8664
+#define IMAGE_BASE_ADDRESS 0x100000000LL
+#else
+#define IMAGE_BASE_ADDRESS 0x04000000
+#endif
+#endif
+
+#if (WORD_SIZE==64)
+#define PURESPACE_RESERVE 0x2000000000LL /* 128 GB */
+#define PURESPACE_SIZE (1LL<<30LL)
+#else
+#define PURESPACE_RESERVE (128<<20) /* MB */
+#define PURESPACE_SIZE (64<<20)
+#endif
+
+#define STATIC_RESERVE heap_segment_size
+
+#ifndef X86
+#define STATIC_BASE_ADDRESS (0x00002000+(LOWMEM_BIAS))
+#else
+#define STATIC_BASE_ADDRESS (0x00012000+(LOWMEM_BIAS))
+#endif
+
+#define SPJUMP_TARGET_ADDRESS (STATIC_BASE_ADDRESS+0x3000)
+
+extern LispObj image_base;
+extern BytePtr pure_space_start, pure_space_active, pure_space_limit;
+extern BytePtr static_space_start, static_space_active, static_space_limit;
+extern area *find_readonly_area(void);
+extern BytePtr low_relocatable_address, high_relocatable_address,
+  low_markable_address, high_markable_address;
+
+#endif /* __AREA_H__ */
Index: /branches/new-random/lisp-kernel/bits.c
===================================================================
--- /branches/new-random/lisp-kernel/bits.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/bits.c	(revision 13309)
@@ -0,0 +1,70 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+
+#include "lisp.h"
+#include "bits.h"
+#include "lisp-exceptions.h"
+
+
+/* This should be a lot faster than calling set_bit N times */
+
+void
+set_n_bits(bitvector bits, natural first, natural n)
+{
+  if (n) {
+    natural
+      lastbit = (first+n)-1,
+      leftbit = first & bitmap_shift_count_mask,
+      leftmask = ALL_ONES >> leftbit,
+      rightmask = ALL_ONES << ((nbits_in_word-1) - (lastbit & bitmap_shift_count_mask)),
+      *wstart = ((natural *) bits) + (first>>bitmap_shift),
+      *wend = ((natural *) bits) + (lastbit>>bitmap_shift);
+
+    if (wstart == wend) {
+      *wstart |= (leftmask & rightmask);
+    } else {
+      *wstart++ |= leftmask;
+      n -= (nbits_in_word - leftbit);
+      
+      while (n >= nbits_in_word) {
+        *wstart++ = ALL_ONES;
+        n-= nbits_in_word;
+      }
+      
+      if (n) {
+        *wstart |= rightmask;
+      }
+    }
+  }
+}
+
+/* Note that this zeros longwords */
+void
+zero_bits(bitvector bits, natural nbits)
+{
+  memset(bits, 0, ((sizeof(natural)*(((nbits+(nbits_in_word-1)))>>bitmap_shift))));
+}
+
+void
+ior_bits(bitvector dest, bitvector src, natural nbits)
+{
+  while (nbits > 0) {
+    *dest++ |= *src++;
+    nbits -= nbits_in_word;
+  }
+}
Index: /branches/new-random/lisp-kernel/bits.h
===================================================================
--- /branches/new-random/lisp-kernel/bits.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/bits.h	(revision 13309)
@@ -0,0 +1,183 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+
+
+#ifndef __bits_h__
+#define __bits_h__ 1
+
+#include <string.h>
+
+typedef natural *bitvector;
+
+#if WORD_SIZE == 64
+#define bitmap_shift 6
+#define BIT0_MASK 0x8000000000000000ULL
+#define ALL_ONES  0xffffffffffffffffULL
+#define NATURAL1 1ULL
+#else
+#define bitmap_shift 5
+#define BIT0_MASK 0x80000000U 
+#define ALL_ONES  0xFFFFFFFFU
+#define NATURAL1 1U
+#endif
+
+#define bitmap_shift_count_mask ((1<<bitmap_shift)-1)
+
+static inline int
+set_bit(bitvector bits,natural bitnum)  __attribute__((always_inline));
+
+static inline int
+set_bit(bitvector bits,natural bitnum)
+{
+  natural
+    windex = bitnum>>bitmap_shift, 
+    old = bits[windex],
+    new = old | (BIT0_MASK >> (bitnum & bitmap_shift_count_mask));
+  if (new == old) {
+    return 1;			/* Was set */
+  } else {
+    bits[windex] = new;
+    return 0;			/* Was clear */
+  }
+}
+
+static inline int 
+atomic_set_bit(bitvector bits ,natural bitnum)
+{
+  extern natural atomic_ior(bitvector, natural);
+  natural
+    windex = bitnum>>bitmap_shift,
+    mask = (BIT0_MASK >> (bitnum & bitmap_shift_count_mask));
+
+  return atomic_ior(bits + windex, mask);
+}
+
+void set_n_bits(bitvector,natural,natural);
+
+static inline int
+clr_bit(bitvector bits, natural bitnum)
+{
+  unsigned 
+    windex = bitnum>>bitmap_shift, 
+    old = bits[windex],
+    new = old & ~(BIT0_MASK >> (bitnum & bitmap_shift_count_mask));
+  if (new == old) {
+    return 0;	/* Was clear */
+  } else {
+    bits[windex] = new;
+    return 1;	/* Was set */
+  }
+}
+
+
+static inline unsigned
+ref_bit(bitvector bits,natural bitnum) __attribute__((always_inline));
+
+static inline unsigned
+ref_bit(bitvector bits,natural bitnum)
+{
+  return ((bits[bitnum>>bitmap_shift] & (BIT0_MASK >> (bitnum & bitmap_shift_count_mask))) != 0);
+}
+
+void zero_bits(bitvector, natural);
+void ior_bits(bitvector,bitvector,natural);
+
+#define bits_word_index(bitnum) (((natural)(bitnum)) >> bitmap_shift)
+#define bits_bit_index(bitnum) (((natural)(bitnum)) & bitmap_shift_count_mask)
+#define bits_word_ptr(bits,bitnum) \
+  ((natural*) (((natural*) bits) + ((natural) (bits_word_index(bitnum)))))
+#define bits_word_mask(bitnum) ((BIT0_MASK) >> bits_bit_index(bitnum))
+#define bits_indexed_word(bitv,indexw) ((((natural*)(bitv))[indexw]))
+#define bits_word(bitv,bitnum) bits_indexed_word(bits,bits_word_index(bitnum))
+
+/* Evaluates some arguments twice */
+
+#define set_bits_vars(BITVvar,BITNUMvar,BITPvar,BITWvar,MASKvar) \
+{ BITPvar = bits_word_ptr(BITVvar,BITNUMvar); BITWvar = *BITPvar; MASKvar = bits_word_mask(BITNUMvar); }
+
+#define set_bitidx_vars(BITVvar,BITNUMvar,BITPvar,BITWvar,BITIDXvar) \
+{ BITPvar = bits_word_ptr(BITVvar,BITNUMvar); BITIDXvar = bits_bit_index(BITNUMvar); \
+    BITWvar = (*BITPvar << BITIDXvar) >> BITIDXvar; }
+
+#ifdef __GNUC__
+static __inline__ natural
+current_stack_pointer(void) __attribute__((always_inline));
+
+static __inline__ natural
+current_stack_pointer(void)
+{
+#ifdef PPC
+  register natural _sp __asm__("r1");
+#endif
+#ifdef X8664
+  register natural _sp __asm__("%rsp");
+#endif
+#ifdef X8632
+  register natural _sp __asm__("%esp");
+#endif
+  return _sp;
+}
+#else
+natural
+current_stack_pointer(void);
+#endif
+
+#ifdef __GNUC__
+static __inline__ unsigned
+count_leading_zeros(natural w) __attribute__((always_inline));
+
+
+/* Beware: on some platforms, __builtin_clz[ll](0) returns an undefined
+   result */
+
+static __inline__ unsigned
+count_leading_zeros(natural w)
+{
+#if __GNUC__ >= 4
+#if WORD_SIZE == 64
+  return __builtin_clzll(w);  
+#else
+  return __builtin_clz(w);  
+#endif
+#else /* __GNUC__ < 4 */
+  natural lz;
+#ifdef PPC
+#ifdef PPC64
+  __asm__ __volatile__("cntlzd %0,%1" : "=r" (lz) : "r" (w));
+#else
+  __asm__ __volatile__("cntlzw %0,%1" : "=r" (lz) : "r" (w));
+#endif
+#endif /* PPC */
+#ifdef X86
+#ifdef X8664
+  __asm__ __volatile__("bsr %1,%0" : "=r" (lz) : "r" (w));
+  __asm__ __volatile__("xor $63,%0" : "=r" (lz));
+#else
+  __asm__ __volatile__("bsr %1,%0" : "=r" (lz) : "r" (w));
+  __asm__ __volatile__("xor $31,%0" : "=r" (lz));
+#endif 
+#endif
+  return lz;
+#endif
+}
+#else /* not __GNUC__ */
+unsigned
+count_leading_zeros(natural);
+#endif
+                                        
+#endif /* __bits_h__ */
Index: /branches/new-random/lisp-kernel/darwinppc/.cvsignore
===================================================================
--- /branches/new-random/lisp-kernel/darwinppc/.cvsignore	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinppc/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/lisp-kernel/darwinppc/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/darwinppc/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinppc/.gdbinit	(revision 13309)
@@ -0,0 +1,39 @@
+define pl
+call print_lisp_object($arg0)
+end
+
+define arg_x
+pl $r21
+end
+
+define arg_y
+pl $r22
+end
+
+define arg_z
+pl $r23
+end
+
+define lw
+pl $r16
+end
+
+define fname
+pl $r17
+end
+
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIGUSR1 pass nostop noprint
+handle SIGUSR2 pass nostop noprint
+handle SIGEMT pass nostop noprint
+# Work around apparent Apple GDB bug
+handle SIGTTIN nopass nostop noprint
Index: /branches/new-random/lisp-kernel/darwinppc/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/darwinppc/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinppc/Makefile	(revision 13309)
@@ -0,0 +1,125 @@
+#
+#   Copyright (C) 1994-2001 Digitool, Inc
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+# For versions of GCC prior to 3.3, the option "-traditional-cpp" meant
+# "don't use precompiled headers", which was good advice since they didn't
+# work too well.  Beginning with GCC 3.3, the "-traditional-cpp" means 
+# "use a broken preprocessor", which is (in a sense) the opposite of what
+# it used to mean.
+
+# Try to determine the version of GCC in use.  Invoke gcc with the
+# -v flag, and look for a line containing the phrase "specs from" in
+# the output.  Use sed to extract the full pathname of ths specs file
+# printed in that line, then strip off the trailing "/specs".
+gccdir = $(shell $(CC) -v 2>&1 | grep "specs from" | sed -e 's/.*from //' -e 's|/specs||')
+# $(gccdir) is set to the directory containing the specs file, without the
+# trailing slash.  The make intrinsic 'notdir' will strip a leading directory
+# prefix from that pathname, leaving us with a string that should match
+# the gcc version number
+ifneq ($(gccdir),)
+gccversion:=$(notdir $(gccdir))
+oldgcc:=$(shell expr $(gccversion) "<" "3.3")
+pregcc4:=$(shell expr $(gccversion) "<" "4.0")
+ifeq ($(oldgcc),1)
+BROKEN_PREPROCESSOR_WORKAROUND = -traditional-cpp
+endif
+endif
+
+MDYNAMIC_NO_PIC = $(shell ($(CC) --help -v 2>&1 | grep -q -e "-mdynamic-no-pic") && /bin/echo "-mdynamic-no-pic")
+
+OPENMCL_MAJOR_VERSION=0
+OPENMCL_MINOR_VERSION=14
+
+VPATH = ..
+RM = /bin/rm
+LD = ld
+LDFLAGS = -arch ppc -dynamic  -o $@ -e start -pagezero_size 0x1000 -seg1addr 0x00001000 -sectalign __TEXT __text 0x1000 
+AS = as
+M4 = gm4
+M4FLAGS = -DDARWIN -DPPC
+ASFLAGS = -arch ppc -force_cpusubtype_ALL
+CDEFINES = -DDARWIN -DPPC  $(BROKEN_PREPROCESSOR_WORKAROUND) #-DDEBUG -DGC_INTEGRITY_CHECKING
+CDEBUG = -g
+COPT = -O2
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS) $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c -arch ppc $< $(CDEFINES) $(CDEBUG) $(COPT) -Wno-deprecated-declarations -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk  $(MDYNAMIC_NO_PIC) -o $@
+
+SPOBJ = ppc-spjump.o ppc-spentry.o  ppc-subprims.o 
+ASMOBJ = ppc-asmutils.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o ppc-gc.o bits.o  ppc-exceptions.o \
+	thread_manager.o lisp-debug.o image.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o plbt.o ppc_print.o
+KERNELOBJ= imports.o $(COBJ) ppc-asmutils.o 
+
+SPINC =	lisp.s m4macros.m4 ppc-constants.s ppc-macros.s errors.s ppc-uuo.s ppc-constants32.s
+
+CHEADERS = area.h bits.h ppc-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h lisptypes.h ppc-constants32.h ppc-exceptions.h
+
+# Subprims linked into the kernel ?
+# Yes:
+
+KSPOBJ= $(SPOBJ)
+all:	../../dppccl
+
+
+# No:
+
+# KSPOBJ=
+
+OSEARLYLIBS = -lcrt1.o
+OSLATELIBS = -lSystem
+
+# gcc 4.0 and later want to use -lSystemStubs for many of the
+# runtime support functions that were in -lgcc in previous
+# versions.  'pregcc4' may have been set above.
+ifeq ($(pregcc4),1)
+OSMIDDLELIBS = -lgcc
+else
+OSMIDDLELIBS = -lSystemStubs
+endif
+
+OSLIBS = $(OSEARLYLIBS) $(OSMIDDLELIBS) $(OSLATELIBS)
+
+../../dppccl:	 $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ)
+	$(LD)  $(LDFLAGS) $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ)   $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+
+thread_manager.o: thread_manager.c 
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../dppccl 
+
+# Some earlier versions of this Makefile built "subprims_r.o".  
+# (That file is now defunct.)
+clean:	cclean
+	$(RM) -f $(SPOBJ) $(KSPOBJ) subprims_r.o
+
+strip:	../../dppccl
+	strip -s retain ../../dppccl
Index: /branches/new-random/lisp-kernel/darwinppc/retain
===================================================================
--- /branches/new-random/lisp-kernel/darwinppc/retain	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinppc/retain	(revision 13309)
@@ -0,0 +1,3 @@
+#symbols that must be retained in a lisp kernel image
+# % strip -s <this file> dppccl
+_catch_exception_raise
Index: /branches/new-random/lisp-kernel/darwinppc64/.cvsignore
===================================================================
--- /branches/new-random/lisp-kernel/darwinppc64/.cvsignore	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinppc64/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/lisp-kernel/darwinppc64/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/darwinppc64/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinppc64/Makefile	(revision 13309)
@@ -0,0 +1,129 @@
+#
+#   Copyright (C) 2005 Clozure Associates and contributors.
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+# For versions of GCC prior to 3.3, the option "-traditional-cpp" meant
+# "don't use precompiled headers", which was good advice since they didn't
+# work too well.  Beginning with GCC 3.3, the "-traditional-cpp" means 
+# "use a broken preprocessor", which is (in a sense) the opposite of what
+# it used to mean.
+
+# Try to determine the version of GCC in use.  Invoke gcc with the
+# -v flag, and look for a line containing the phrase "specs from" in
+# the output.  Use sed to extract the full pathname of ths specs file
+# printed in that line, then strip off the trailing "/specs".
+gccdir = $(shell $(CC) -v 2>&1 | grep "specs from" | sed -e 's/.*from //' -e 's|/specs||')
+# $(gccdir) is set to the directory containing the specs file, without the
+# trailing slash.  The make intrinsic 'notdir' will strip a leading directory
+# prefix from that pathname, leaving us with a string that should match
+# the gcc version number
+#gccversion:=$(notdir $(gccdir))
+#oldgcc:=$(shell expr $(gccversion) "<" "3.3")
+#ifeq ($(oldgcc),1)
+#BROKEN_PREPROCESSOR_WORKAROUND = -traditional-cpp
+#endif
+
+MDYNAMIC_NO_PIC = $(shell ($(CC) --help -v 2>&1 | grep -q -e "-mdynamic-no-pic") && /bin/echo "-mdynamic-no-pic")
+
+OPENMCL_MAJOR_VERSION=0
+OPENMCL_MINOR_VERSION=14
+
+VPATH = ..
+RM = /bin/rm
+LD = ld64
+
+### The -pagezero_size/-seg1addr args are an attempt to work around a
+### bug (#4057702) in ld64.
+
+### The -seg1addr and -pagezero_size arguments below are nonsense;
+### early versions of ld64 were/are broken.
+LDFLAGS = -macosx_version_min 10.4 -M -arch ppc64 -dynamic  -o $@ -e start -pagezero_size 0x1000 -seg1addr 0x1000 -sectalign __TEXT __text 0x1000
+AS = as
+M4 = gm4
+M4FLAGS = -DDARWIN -DPPC -DPPC64
+ASFLAGS = -arch ppc64
+CDEFINES = -DDARWIN -DPPC -DPPC64 $(BROKEN_PREPROCESSOR_WORKAROUND)
+CDEBUG = -g
+COPT = -O2
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS) $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< -arch ppc64 -m64 $(CDEFINES) $(CDEBUG) $(COPT) $(MDYNAMIC_NO_PIC) -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o $@
+
+SPOBJ = ppc-spjump.o ppc-spentry.o ppc-subprims.o 
+ASMOBJ = ppc-asmutils.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o ppc-gc.o bits.o  ppc-exceptions.o \
+	thread_manager.o lisp-debug.o image.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o plbt.o ppc_print.o
+KERNELOBJ= imports.o $(COBJ) ppc-asmutils.o 
+
+SPINC =	lisp.s m4macros.m4 ppc-constants.s ppc-macros.s errors.s ppc-uuo.s \
+	ppc-constants64.s
+
+CHEADERS = area.h bits.h ppc-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h lisptypes.h ppc-constants64.h ppc-exceptions.h
+
+# Subprims linked into the kernel ?
+# Yes:
+
+KSPOBJ= $(SPOBJ)
+all:	../../dppccl64
+
+
+# No:
+
+# KSPOBJ=
+
+OSEARLYLIBS = -lcrt1.o
+OSLATELIBS = -lSystem -lmx
+
+# If the linker can find an absolute path to -lSystemStubs, use
+# -lSystemStubs; otherwise, just use libgcc.a
+SYSTEMSTUBSPATH = $(shell $(CC) --print-file-name=libSystemStubs.a)
+SYSTEMSTUBSABSOLUTE = $(shell expr $(SYSTEMSTUBSPATH) : "^/*")
+ifeq ($(SYSTEMSTUBSABSOLUTE),1)
+OSMIDDLELIBS = -lSystemStubs
+else
+OSMIDDLELIBS = -lgcc
+endif
+
+OSLIBS = $(OSEARLYLIBS) $(OSMIDDLELIBS) $(OSLATELIBS)
+
+../../dppccl64:	 $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile
+	$(LD)  $(LDFLAGS) $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ)   $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+thread_manager.o: thread_manager.c 
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../dppccl64 
+
+# Some earlier versions of this Makefile built "subprims_r.o".  
+# (That file is now defunct.)
+clean:	cclean
+	$(RM) -f $(SPOBJ) $(KSPOBJ) subprims_r.o
+
+strip:	../../dppccl64
+	strip -s retain ../../dppccl64
Index: /branches/new-random/lisp-kernel/darwinx8632/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/darwinx8632/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinx8632/.gdbinit	(revision 13309)
@@ -0,0 +1,48 @@
+define pl
+  call print_lisp_object($arg0)
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x3001
+   set $car = *((LispObj *)($l+3))
+   set $l =  *((LispObj *)($l-1))
+   pl $car
+  end
+end
+
+
+define fn
+  pl $edi
+end
+
+define arg_y
+ pl $esi
+end
+
+define arg_z
+ pl $ebx
+end
+
+define offset
+ p (int)$pc-$edi
+end
+
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIGUSR1 pass nostop noprint
+handle SIGUSR2 pass nostop noprint
+handle SIGEMT pass nostop noprint
+# Work around apparent Apple GDB bug
+handle SIGTTIN nopass nostop noprint
+# Work around Leopard bug du jour
+handle SIGSYS pass nostop noprint
+
Index: /branches/new-random/lisp-kernel/darwinx8632/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/darwinx8632/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinx8632/Makefile	(revision 13309)
@@ -0,0 +1,102 @@
+#
+#   Copyright (C) 2005 Clozure Associates and contributors.
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+MDYNAMIC_NO_PIC = $(shell ($(CC) --help -v 2>&1 | grep -q -e "-mdynamic-no-pic") && /bin/echo "-mdynamic-no-pic")
+
+VPATH = ..
+RM = /bin/rm
+LD = ld
+LDFLAGS =  -macosx_version_min 10.4 -arch i386 -dynamic  -o $@ -e start -pagezero_size 0x11000 -seg1addr 0x00011000 -sectalign __TEXT __text 0x1000 
+AS = as
+M4 = gm4
+M4FLAGS = -DDARWIN -DX86 -DX8632
+ASFLAGS = -arch i386 -g
+CDEFINES = -DDARWIN -DX86 -DX8632 #-DGC_INTEGRITY_CHECKING -DFORCE_DWS_MARK -DDISABLE_EGC -DDEBUG_MACH_EXCEPTIONS
+CDEBUG = -g
+COPT = -O2
+CC=gcc-4.0
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS) $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c -arch i386 $< $(CDEFINES) $(CDEBUG) $(COPT) $(MDYNAMIC_NO_PIC) -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o $@
+
+SPOBJ = x86-spjump32.o x86-spentry32.o x86-subprims32.o
+ASMOBJ = x86-asmutils32.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o bits.o  \
+	thread_manager.o lisp-debug.o image.o memory.o x86-gc.o \
+	x86-exceptions.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o x86_print.o xlbt.o
+KERNELOBJ= imports.o $(COBJ) x86-asmutils32.o 
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s x86-constants32.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h lisptypes.h x86-constants32.h x86-exceptions.h
+
+# Subprims linked into the kernel ?
+# Yes:
+
+KSPOBJ= $(SPOBJ)
+all:	../../dx86cl
+
+
+# No:
+
+# KSPOBJ=
+
+OSEARLYLIBS = -lcrt1.o
+OSLATELIBS = -lSystem
+
+# is this needed?
+#OSMIDDLELIBS = -lSystemStubs
+
+OSLIBS = $(OSEARLYLIBS) $(OSMIDDLELIBS) $(OSLATELIBS)
+
+../../dx86cl:	 tiger-sdk-check $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile
+	$(LD)  $(LDFLAGS) $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ)   $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+
+thread_manager.o: thread_manager.c 
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../dx86cl 
+
+# Some earlier versions of this Makefile built "subprims_r.o".  
+# (That file is now defunct.)
+clean:	cclean
+	$(RM) -f $(SPOBJ) $(KSPOBJ) subprims_r.o
+
+# retain file not here at the moment
+strip:	../../dx86cl
+	strip -s retain ../../dx86cl
+
+.PHONY: tiger-sdk-check
+tiger-sdk-check:
+	@test -d /Developer/SDKs/MacOSX10.4u.sdk || \
+		 (echo "*** Install Xcode 10.4 support"; exit 1)
+
+
Index: /branches/new-random/lisp-kernel/darwinx8664/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/darwinx8664/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinx8664/.gdbinit	(revision 13309)
@@ -0,0 +1,78 @@
+define x86_lisp_string
+x/s $arg0-5
+end
+
+define x86pname
+set $temp=*((long *)((long)($arg0-6)))
+x86_lisp_string $temp
+end
+
+define gtra
+br *$r10
+cont
+end
+
+
+define pname
+ x86pname $arg0
+end
+
+define pl
+ call print_lisp_object($arg0)
+end
+
+define lw
+ pl $r13
+end
+
+define clobber_breakpoint
+  set *(short *)($pc-2)=0x9090
+end
+
+define arg_z
+ pl $rsi
+end
+
+define arg_y
+ pl $rdi
+end
+
+define arg_x
+ pl $r8
+end
+
+define bx
+ pl $rbx
+end
+
+
+define lbt
+ call plbt_sp($rbp)
+end
+
+define ada
+ p/x *(all_areas->succ)
+end
+
+define lregs
+ call debug_lisp_registers($arg0,0,0)
+end
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIGUSR1 pass nostop noprint
+handle SIGUSR2 pass nostop noprint
+handle SIGEMT pass nostop noprint
+# Work around apparent Apple GDB bug
+handle SIGTTIN nopass nostop noprint
+# Work around Leopard bug du jour
+handle SIGSYS pass nostop noprint
+handle SIGQUIT pass nostop noprint
+
Index: /branches/new-random/lisp-kernel/darwinx8664/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/darwinx8664/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/darwinx8664/Makefile	(revision 13309)
@@ -0,0 +1,122 @@
+#
+#   Copyright (C) 2005 Clozure Associates and contributors.
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+
+
+MDYNAMIC_NO_PIC = $(shell ($(CC) --help -v 2>&1 | grep -q -e "-mdynamic-no-pic") && /bin/echo "-mdynamic-no-pic")
+
+
+VPATH = ..
+RM = /bin/rm
+LD = ld
+CC=gcc-4.0
+
+### Current ld64 bugs include the claim that 0x1000 isn't a power of 2.
+### Gosh.  I always thought that it was.  Go know, right ?
+LDFLAGS = -macosx_version_min 10.4 -arch x86_64 -dynamic  -o $@ -e start -pagezero_size 0x11000 -seg1addr 0x00011000
+
+
+AS = as
+M4 = gm4
+###
+### DARWIN_GS_HACK enables some awful, dangerous, and slow workarounds
+### for the fact that early versions of x86-64 Darwin don't provide
+### working mechanisms for threads to address thread-local-data
+### relative to a spare segment register.  We instead use the
+### undocumented mechanism which the pthreads library uses to
+### keep pthread data in %gs, and switch %gs between pthread data
+### when running foreign code and lisp tcr data when running lisp
+### code.  Hopefully, we won't have to do this for very long.
+###
+### (Things like i386_set_ldt() are defined, but not implemented
+### correctly on the libc side and not implemented at all on the
+### Mach kernel side.)
+###
+### Apple never
+M4FLAGS = -DDARWIN -DX86 -DX8664 -DTCR_IN_GPR
+ASFLAGS = -arch x86_64 -g
+CDEFINES = -DDARWIN -DX86 -DX8664 -DTCR_IN_GPR
+CDEBUG = -g
+COPT = -O2
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS) $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< -arch x86_64 -m64 $(CDEFINES) $(CDEBUG) $(COPT) $(MDYNAMIC_NO_PIC) -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o $@
+
+SPOBJ = x86-spjump64.o x86-spentry64.o x86-subprims64.o 
+ASMOBJ = x86-asmutils64.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o x86-gc.o bits.o  x86-exceptions.o \
+	thread_manager.o lisp-debug.o image.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= imports.o $(COBJ) x86-asmutils64.o 
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants64.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h lisptypes.h x86-constants64.h x86-exceptions.h
+
+# Subprims linked into the kernel ?
+# Yes:
+
+KSPOBJ= $(SPOBJ)
+all:	../../dx86cl64
+
+
+# No:
+
+# KSPOBJ=
+
+OSEARLYLIBS = -lcrt1.o
+OSLATELIBS = -lSystem
+
+OSMIDDLELIBS = 
+
+
+OSLIBS = $(OSEARLYLIBS) $(OSMIDDLELIBS) $(OSLATELIBS)
+
+../../dx86cl64:	 tiger-sdk-check $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile
+	$(LD) $(LDFLAGS) $(KSPOBJ) $(KERNELOBJ)  $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+thread_manager.o: thread_manager.c 
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../dx86cl64 
+
+# Some earlier versions of this Makefile built "subprims_r.o".  
+# (That file is now defunct.)
+clean:	cclean
+	$(RM) -f $(SPOBJ) $(KSPOBJ) subprims_r.o
+
+strip:	../../dx86cl64
+	strip -s retain ../../dx86cl64
+
+.PHONY: tiger-sdk-check
+tiger-sdk-check:
+	@test -d /Developer/SDKs/MacOSX10.4u.sdk || \
+		(echo "*** Install Xcode 10.4 support"; exit 1)
+
Index: /branches/new-random/lisp-kernel/errors.s
===================================================================
--- /branches/new-random/lisp-kernel/errors.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/errors.s	(revision 13309)
@@ -0,0 +1,236 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL. */
+ 
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence. */
+ 
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+ 
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+
+	
+
+error_reg_errnum = 0		/* "real" (typically negative) error number is in RB */
+error_udf = 1
+error_udf_call = 2
+error_throw_tag_missing = 3
+error_alloc_failed = 4
+error_stack_overflow = 5
+error_excised_function_call = 6
+error_too_many_values = 7
+error_propagate_suspend = 10
+error_interrupt = 11
+error_suspend = 12
+error_suspend_all = 13
+error_resume = 14
+error_resume_all = 15					
+error_cant_call = 17
+        
+error_type_error = 128
+
+define([__type_error_counter__],128)
+define([def_type_error],[
+error_object_not_$1 = __type_error_counter__
+        define([__type_error_counter__],eval(__type_error_counter__+1))])
+
+	def_type_error(array)
+	def_type_error(bignum)
+	def_type_error(fixnum)
+	def_type_error(character)
+	def_type_error(integer)
+	def_type_error(list)
+	def_type_error(number)
+	def_type_error(sequence)
+	def_type_error(simple_string)
+	def_type_error(simple_vector)
+	def_type_error(string)
+	def_type_error(symbol)
+	def_type_error(macptr)
+	def_type_error(real)
+	def_type_error(cons)
+	def_type_error(unsigned_byte)
+	def_type_error(radix)
+	def_type_error(float)
+	def_type_error(rational)
+	def_type_error(ratio)
+	def_type_error(short_float)
+	def_type_error(double_float)
+	def_type_error(complex)
+	def_type_error(vector)
+	def_type_error(simple_base_string)
+	def_type_error(function)
+	def_type_error(unsigned_byte_16)
+	def_type_error(unsigned_byte_8)
+	def_type_error(unsigned_byte_32)
+	def_type_error(signed_byte_32)
+	def_type_error(signed_byte_16)
+	def_type_error(signed_byte_8)	
+	def_type_error(base_character)
+	def_type_error(bit)
+	def_type_error(unsigned_byte_24)
+	def_type_error(u64)
+	def_type_error(s64)
+        def_type_error(unsigned_byte_56)
+        def_type_error(simple_array_double_float_2d)
+        def_type_error(simple_array_single_float_2d)
+        def_type_error(mod_char_code_limit)
+        def_type_error(array_2d)
+        def_type_error(array_3d)
+        def_type_error(array_t)
+        def_type_error(array_bit)
+        def_type_error(array_s8)
+        def_type_error(array_u8)
+        def_type_error(array_s16)
+        def_type_error(array_u16)
+        def_type_error(array_s32)
+        def_type_error(array_u32)
+        def_type_error(array_s64)
+        def_type_error(array_u64)
+        def_type_error(array_fixnum)
+        def_type_error(array_single_float)
+        def_type_error(array_double_float)
+        def_type_error(array_char)
+        def_type_error(array_t_2d)
+        def_type_error(array_bit_2d)
+        def_type_error(array_s8_2d)
+        def_type_error(array_u8_2d)
+        def_type_error(array_s16_2d)
+        def_type_error(array_u16_2d)
+        def_type_error(array_s32_2d)
+        def_type_error(array_u32_2d)
+        def_type_error(array_s64_2d)
+        def_type_error(array_u64_2d)
+        def_type_error(array_fixnum_2d)
+        def_type_error(array_single_float_2d)
+        def_type_error(array_double_float_2d)
+        def_type_error(array_char_2d)
+        def_type_error(simple_array_t_2d)
+        def_type_error(simple_array_bit_2d)
+        def_type_error(simple_array_s8_2d)
+        def_type_error(simple_array_u8_2d)
+        def_type_error(simple_array_s16_2d)
+        def_type_error(simple_array_u16_2d)
+        def_type_error(simple_array_s32_2d)
+        def_type_error(simple_array_u32_2d)
+        def_type_error(simple_array_s64_2d)
+        def_type_error(simple_array_u64_2d)
+        def_type_error(simple_array_fixnum_2d)
+        def_type_error(simple_array_char_2d)
+        def_type_error(array_t_3d)
+        def_type_error(array_bit_3d)
+        def_type_error(array_s8_3d)
+        def_type_error(array_u8_3d)
+        def_type_error(array_s16_3d)
+        def_type_error(array_u16_3d)
+        def_type_error(array_s32_3d)
+        def_type_error(array_u32_3d)
+        def_type_error(array_s64_3d)
+        def_type_error(array_u64_3d)
+        def_type_error(array_fixnum_3d)
+        def_type_error(array_single_float_3d)
+        def_type_error(array_double_float_3d)
+        def_type_error(array_char_3d)
+        def_type_error(simple_array_t_3d)
+        def_type_error(simple_array_bit_3d)
+        def_type_error(simple_array_s8_3d)
+        def_type_error(simple_array_u8_3d)
+        def_type_error(simple_array_s16_3d)
+        def_type_error(simple_array_u16_3d)
+        def_type_error(simple_array_s32_3d)
+        def_type_error(simple_array_u32_3d)
+        def_type_error(simple_array_s64_3d)
+        def_type_error(simple_array_u64_3d)
+        def_type_error(simple_array_fixnum_3d)
+        def_type_error(simple_array_single_float_3d)
+        def_type_error(simple_array_double_float_3d)
+        def_type_error(simple_array_char_3d)
+        def_type_error(vector_t)
+        def_type_error(bit_vector)
+        def_type_error(vector_s8)
+        def_type_error(vector_u8)
+        def_type_error(vector_s16)
+        def_type_error(vector_u16)
+        def_type_error(vector_s32)
+        def_type_error(vector_u32)
+        def_type_error(vector_s64)
+        def_type_error(vector_u64)
+        def_type_error(vector_fixnum)
+        def_type_error(vector_single_float)
+        def_type_error(vector_double_float)
+        
+        
+	
+/* These are the "old" error constants that %ERR-DISP understands */
+
+define([deferr],[
+$1 = $2<<fixnumshift])
+
+
+	deferr(XVUNBND,1)
+	deferr(XBADVEC,2)
+	deferr(XTMINPS,3)
+	deferr(XNEINPS,4)
+	deferr(XWRNGINP,5)
+	deferr(XFUNBND,6)
+	deferr(XSETBADVEC,7)
+	deferr(XCOERCE,8)
+	deferr(XWRONGSYS,9)
+	deferr(XNOMEM,10)
+	deferr(XOPENIMAGE,11)
+	deferr(XNOTFUN,13)
+	deferr(XNOCTAG,33)
+	deferr(XNOFPU,36)
+	deferr(XBADTOK,49)
+	deferr(XFLOVFL,64)
+	deferr(XDIVZRO,66)
+	deferr(XFLDZRO,66)
+	deferr(XMEMFULL,76)
+	deferr(XARRLIMIT,77)
+	deferr(XSTKOVER,75)
+	deferr(XFLEXC,98)
+	deferr(XMFULL,-41)
+
+	deferr(XARROOB,112)
+	deferr(XCONST,115)
+	deferr(XNOSPREAD,120)
+	deferr(XFASLVERS,121)
+	deferr(XNOTFASL,122)
+	deferr(XUDFCALL,123)
+	deferr(XWRONGIMAGE,124)
+
+	deferr(XNOPKG,130)
+	deferr(XBADFASL,132)
+	deferr(XSYMACC,135)
+	deferr(XEXPRTC,136)
+	deferr(XNDIMS,148)
+	deferr(XNARGS,150)
+	deferr(XBADKEYS,153)
+	deferr(XWRONGTYPE,157)
+	deferr(XBADSTRUCT,158)
+	deferr(XSTRUCTBOUNDS,159)
+	deferr(XCALLNOTLAMBDA,160)
+	deferr(XTEMPFLT,161)
+	deferr(XCALLTOOMANY,167)
+	deferr(XCALLTOOFEW,168)
+	deferr(XCALLNOMATCH,169)
+	deferr(XIMPROPERLIST,170)
+	deferr(XNOFILLPTR,171)
+	deferr(XMALADJUST,172)
+	deferr(XACCESSNTH,173)
+	deferr(XNOTELT,174)
+	deferr(XSGEXHAUSTED,175)
+	deferr(XSGNARGS,176)
+	deferr(XTOOMANYVALUES,177)
+        deferr(XSYMNOBIND,178)
+	deferr(XFOREIGNEXCEPTION,200)
+
+error_FPU_exception_double = 1024
+error_FPU_exception_short = 1025
+error_memory_full = 2048
Index: /branches/new-random/lisp-kernel/freebsdx8632/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/freebsdx8632/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/freebsdx8632/.gdbinit	(revision 13309)
@@ -0,0 +1,43 @@
+define pl
+  call print_lisp_object($arg0)
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x3001
+   set $car = *((LispObj *)($l+3))
+   set $l =  *((LispObj *)($l-1))
+   pl $car
+  end
+end
+
+
+define fn
+  pl $edi
+end
+
+define arg_y
+ pl $esi
+end
+
+define arg_z
+ pl $ebx
+end
+
+define offset
+ p (int)$pc-$edi
+end
+
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIGEMT pass nostop noprint
+handle SIGUSR1 pass nostop noprint
+handle SIGUSR2 pass nostop noprint
Index: /branches/new-random/lisp-kernel/freebsdx8632/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/freebsdx8632/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/freebsdx8632/Makefile	(revision 13309)
@@ -0,0 +1,81 @@
+#
+#   Copyright (C) 2005-2006 Clozure Associates
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ..
+RM = /bin/rm
+AS = as
+M4 = m4
+ASFLAGS = --32
+M4FLAGS = -DFREEBSD -DX86 -DX8632 -DHAVE_TLS
+CDEFINES = -DFREEBSD -D_REENTRANT -DX86 -DX8632 -D_GNU_SOURCE -DHAVE_TLS
+CDEBUG = -g
+COPT = -O2
+
+
+
+
+SPOBJ = pad.o x86-spjump32.o x86-spentry32.o x86-subprims32.o
+ASMOBJ = x86-asmutils32.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o  x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils32.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants32.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants32.h x86-exceptions.h
+
+.if $(MACHINE) == "amd64"
+CROSS = -B/usr/lib32
+.endif
+
+KSPOBJ = $(SPOBJ)
+all:	../../fx86cl
+
+
+OSLIBS = -lm -lthr $(CROSS)
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) -m32 -o $@
+
+LINKSCRIPTFILE = # 
+LINKSCRIPT =  # -T $(LINKSCRIPTFILE)
+
+../../fx86cl:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(LINKSCRIPTFILE)
+	$(CC) -m32 $(CDEBUG)  -Wl,--export-dynamic  $(LINKSCRIPT)  -o $@  $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../fx86cl
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../fx86cl
+	strip -g ../../fx86cl
Index: /branches/new-random/lisp-kernel/freebsdx8632/fpu.h
===================================================================
--- /branches/new-random/lisp-kernel/freebsdx8632/fpu.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/freebsdx8632/fpu.h	(revision 13309)
@@ -0,0 +1,70 @@
+/* These definitions are taken from the file /usr/include/machine/npx.h,
+   which isn't distributed with amd64 versions of FreeBSD */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	from: @(#)npx.h	5.3 (Berkeley) 1/18/91
+ * $FreeBSD: src/sys/i386/include/npx.h,v 1.29.2.1 2006/07/01 00:57:55 davidxu Exp $
+ */
+
+struct  ccl_envxmm {
+	u_int16_t	en_cw;		/* control word (16bits) */
+	u_int16_t	en_sw;		/* status word (16bits) */
+	u_int16_t	en_tw;		/* tag word (16bits) */
+	u_int16_t	en_opcode;	/* opcode last executed (11 bits ) */
+	u_int32_t	en_fip;		/* floating point instruction pointer */
+	u_int16_t	en_fcs;		/* floating code segment selector */
+	u_int16_t	en_pad0;	/* padding */
+	u_int32_t	en_foo;		/* floating operand offset */
+	u_int16_t	en_fos;		/* floating operand segment selector */
+	u_int16_t	en_pad1;	/* padding */
+	u_int32_t	en_mxcsr;	/* SSE sontorol/status register */
+	u_int32_t	en_mxcsr_mask;	/* valid bits in mxcsr */
+};
+
+struct  ccl_xmmacc {
+	u_char	xmm_bytes[16];
+};
+
+struct ccl_fpacc87 {
+	u_char	fp_bytes[10];
+};
+
+struct  ccl_savexmm {
+	struct	ccl_envxmm	sv_env;
+	struct {
+		struct ccl_fpacc87	fp_acc;
+		u_char		fp_pad[6];      /* padding */
+	} sv_fp[8];
+	struct ccl_xmmacc	sv_xmm[8];
+	u_char sv_pad[224];
+} __aligned(16);
Index: /branches/new-random/lisp-kernel/freebsdx8664/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/freebsdx8664/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/freebsdx8664/.gdbinit	(revision 13309)
@@ -0,0 +1,75 @@
+define x86_lisp_string
+x/s $arg0-5
+end
+
+define x86pname
+set $temp=*((long *)((long)($arg0-6)))
+x86_lisp_string $temp
+end
+
+
+define pname
+ x86pname $arg0
+end
+
+define l
+ call print_lisp_object($arg0)
+end
+
+define lw
+ l $r13
+end
+
+define clobber_breakpoint
+  set *(short *)($pc-2)=0x9090
+end
+
+define arg_z
+ l $rsi
+end
+
+define arg_y
+ l $rdi
+end
+
+define arg_x
+ l $r8
+end
+
+define bx
+ l $rbx
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x200b
+   set $car = *((LispObj *)($l+5))
+   set $l =  *((LispObj *)($l-3))
+   l $car
+  end
+end
+
+define lbt
+ call plbt_sp($rbp)
+end
+
+define ada
+ p/x *(all_areas->succ)
+end
+
+define lregs
+ call debug_lisp_registers($arg0,0,0)
+end
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIGEMT pass nostop noprint
+handle SIGUSR1 pass nostop noprint
+handle SIGUSR2 pass nostop noprint
Index: /branches/new-random/lisp-kernel/freebsdx8664/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/freebsdx8664/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/freebsdx8664/Makefile	(revision 13309)
@@ -0,0 +1,78 @@
+#
+#   Copyright (C) 2005-2006 Clozure Associates
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ..
+RM = /bin/rm
+AS = as
+M4 = m4
+ASFLAGS = --64
+M4FLAGS = -DFREEBSD -DX86 -DX8664 -DHAVE_TLS
+CDEFINES = -DFREEBSD -D_REENTRANT -DX86 -DX8664 -D_GNU_SOURCE -DHAVE_TLS
+CDEBUG = -g
+COPT = #-O2
+
+
+
+
+SPOBJ = pad.o x86-spjump64.o x86-spentry64.o x86-subprims64.o
+ASMOBJ = x86-asmutils64.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o  x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils64.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants64.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants64.h x86-exceptions.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	../../fx86cl64
+
+
+OSLIBS = -lm -lthr
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) -m64 -o $@
+
+LINKSCRIPTFILE = # ./elf_x86_64.x
+LINKSCRIPT =  # -T $(LINKSCRIPTFILE)
+
+../../fx86cl64:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(LINKSCRIPTFILE)
+	$(CC) -m64 $(CDEBUG)  -Wl,--export-dynamic  $(LINKSCRIPT)  -o $@  $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../fx86cl64
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../fx86cl64
+	strip -g ../../fx86cl64
Index: /branches/new-random/lisp-kernel/gc-common.c
===================================================================
--- /branches/new-random/lisp-kernel/gc-common.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/gc-common.c	(revision 13309)
@@ -0,0 +1,1556 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp_globals.h"
+#include "bits.h"
+#include "gc.h"
+#include "area.h"
+#include "Threads.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef WINDOWS
+#include <sys/time.h>
+#endif
+
+#ifndef timeradd
+# define timeradd(a, b, result)						      \
+  do {									      \
+    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;			      \
+    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec;			      \
+    if ((result)->tv_usec >= 1000000)					      \
+      {									      \
+	++(result)->tv_sec;						      \
+	(result)->tv_usec -= 1000000;					      \
+      }									      \
+  } while (0)
+#endif
+#ifndef timersub
+# define timersub(a, b, result)						      \
+  do {									      \
+    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;			      \
+    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;			      \
+    if ((result)->tv_usec < 0) {					      \
+      --(result)->tv_sec;						      \
+      (result)->tv_usec += 1000000;					      \
+    }									      \
+  } while (0)
+#endif
+
+void
+comma_output_decimal(char *buf, int len, natural n) 
+{
+  int nout = 0;
+
+  buf[--len] = 0;
+  do {
+    buf[--len] = n%10+'0';
+    n = n/10;
+    if (n == 0) {
+      while (len) {
+        buf[--len] = ' ';
+      }
+      return;
+    }
+    if (len == 0) return;
+    nout ++;
+    if (nout == 3) {
+      buf[--len] = ',';
+      nout = 0;
+    }
+  } while (len >= 0);
+}
+
+
+natural
+static_dnodes_for_area(area *a)
+{
+  if (a->low == tenured_area->low) {
+    return tenured_area->static_dnodes;
+  }
+  return 0;
+}
+
+Boolean GCDebug = false, GCverbose = false;
+bitvector GCmarkbits = NULL, GCdynamic_markbits = NULL;
+LispObj GCarealow = 0, GCareadynamiclow = 0;
+natural GCndnodes_in_area = 0, GCndynamic_dnodes_in_area = 0;
+LispObj GCweakvll = (LispObj)NULL;
+LispObj GCdwsweakvll = (LispObj)NULL;
+LispObj GCephemeral_low = 0;
+natural GCn_ephemeral_dnodes = 0;
+natural GCstack_limit = 0;
+
+
+void
+reapweakv(LispObj weakv)
+{
+  /*
+    element 2 of the weak vector should be tagged as a cons: if it
+    isn't, just mark it as a root.  if it is, cdr through it until a
+    "marked" cons is encountered.  If the car of any unmarked cons is
+    marked, mark the cons which contains it; otherwise, splice the
+    cons out of the list.  N.B. : elements 0 and 1 are already marked
+    (or are immediate, etc.)
+  */
+  LispObj *prev = ((LispObj *) ptr_from_lispobj(untag(weakv))+(1+2)), cell = *prev;
+  LispObj termination_list = lisp_nil;
+  natural weak_type = (natural) deref(weakv,2);
+  Boolean alistp = ((weak_type & population_type_mask) == population_weak_alist),
+    terminatablep = ((weak_type >> population_termination_bit) != 0);
+  Boolean done = false;
+  cons *rawcons;
+  natural dnode, car_dnode;
+  bitvector markbits = GCmarkbits;
+
+  if (terminatablep) {
+    termination_list = deref(weakv,1+3);
+  }
+
+  if (fulltag_of(cell) != fulltag_cons) {
+    mark_root(cell);
+  } else if (alistp) {
+    /* weak alist */
+    while (! done) {
+      dnode = gc_area_dnode(cell);
+      if ((dnode >= GCndnodes_in_area) ||
+          (ref_bit(markbits, dnode))) {
+        done = true;
+      } else {
+        /* Cons cell is unmarked. */
+        LispObj alist_cell, thecar;
+        unsigned cell_tag;
+
+        rawcons = (cons *) ptr_from_lispobj(untag(cell));
+        alist_cell = rawcons->car;
+        cell_tag = fulltag_of(alist_cell);
+
+        if ((cell_tag == fulltag_cons) &&
+            ((car_dnode = gc_area_dnode(alist_cell)) < GCndnodes_in_area) &&
+            (! ref_bit(markbits, car_dnode)) &&
+            (is_node_fulltag(fulltag_of(thecar = car(alist_cell)))) &&
+            ((car_dnode = gc_area_dnode(thecar)) < GCndnodes_in_area) &&
+            (! ref_bit(markbits, car_dnode))) {
+          *prev = rawcons->cdr;
+          if (terminatablep) {
+            rawcons->cdr = termination_list;
+            termination_list = cell;
+          }
+        } else {
+          set_bit(markbits, dnode);
+          prev = (LispObj *)(&(rawcons->cdr));
+          mark_root(alist_cell);
+        }
+        cell = *prev;
+      }
+    }
+  } else {
+    /* weak list */
+    while (! done) {
+      dnode = gc_area_dnode(cell);
+      if ((dnode >= GCndnodes_in_area) ||
+          (ref_bit(markbits, dnode))) {
+        done = true;
+      } else {
+        /* Cons cell is unmarked. */
+        LispObj thecar;
+        unsigned cartag;
+
+        rawcons = (cons *) ptr_from_lispobj(untag(cell));
+        thecar = rawcons->car;
+        cartag = fulltag_of(thecar);
+
+        if (is_node_fulltag(cartag) &&
+            ((car_dnode = gc_area_dnode(thecar)) < GCndnodes_in_area) &&
+            (! ref_bit(markbits, car_dnode))) {
+          *prev = rawcons->cdr;
+          if (terminatablep) {
+            rawcons->cdr = termination_list;
+            termination_list = cell;
+          }
+        } else {
+          set_bit(markbits, dnode);
+          prev = (LispObj *)(&(rawcons->cdr));
+        }
+        cell = *prev;
+      }
+    }
+  }
+
+  if (terminatablep) {
+    deref(weakv,1+3) = termination_list;
+    if (termination_list != lisp_nil) {
+      deref(weakv,1) = GCweakvll;
+      GCweakvll = weakv;
+    }
+  }
+}
+
+/* 
+  Screw: doesn't deal with finalization.
+  */
+
+void
+reaphashv(LispObj hashv)
+{
+  hash_table_vector_header
+    *hashp = (hash_table_vector_header *) ptr_from_lispobj(untag(hashv));
+  natural
+    dnode,
+    npairs = (header_element_count(hashp->header) - 
+              (hash_table_vector_header_count -1)) >> 1;
+  LispObj *pairp = (LispObj*) (hashp+1), weakelement;
+  Boolean 
+    weak_on_value = ((hashp->flags & nhash_weak_value_mask) != 0);
+  Boolean
+    keys_frozen = ((hashp->flags & nhash_keys_frozen_mask) != 0);
+  bitvector markbits = GCmarkbits;
+  int tag;
+
+  while (npairs--) {
+    if (weak_on_value) {
+      weakelement = pairp[1];
+    } else {
+      weakelement = pairp[0];
+    }
+    tag = fulltag_of(weakelement);
+    if (is_node_fulltag(tag)) {
+      dnode = gc_area_dnode(weakelement);
+      if ((dnode < GCndnodes_in_area) && 
+          ! ref_bit(markbits, dnode)) {
+        pairp[0] = slot_unbound;
+        if (keys_frozen) {
+          if (pairp[1] != slot_unbound) {
+            pairp[1] = unbound;
+          }
+        }
+        else {
+          pairp[1] = lisp_nil;
+        }
+        hashp->weak_deletions_count += (1<<fixnumshift);
+      }
+    }
+    pairp += 2;
+  }
+}
+
+void
+traditional_dws_mark_htabv(LispObj htabv)
+{
+  /* Do nothing, just add htabv to GCweakvll */
+  LispObj *base = (LispObj *) ptr_from_lispobj(untag(htabv));
+  
+  deref(base,1) = GCweakvll;
+  GCweakvll = htabv;
+}
+
+void
+ncircle_dws_mark_htabv(LispObj htabv)
+{
+  /* Do nothing, just add htabv to GCdwsweakvll */
+  LispObj *base = (LispObj *) ptr_from_lispobj(untag(htabv));
+  
+  deref(base,1) = GCdwsweakvll;
+  GCdwsweakvll = htabv;
+}
+
+void
+traditional_mark_weak_htabv(LispObj htabv)
+{
+  int i, skip = hash_table_vector_header_count;;
+
+  for (i = 2; i <= skip; i++) {
+    rmark(deref(htabv,i));
+  }
+
+  deref(htabv,1) = GCweakvll;
+  GCweakvll = htabv;
+}
+
+void
+ncircle_mark_weak_htabv(LispObj htabv)
+{
+  int i, skip = hash_table_vector_header_count;
+  hash_table_vector_header *hashp = (hash_table_vector_header *)(untag(htabv));
+  natural
+    npairs = (header_element_count(hashp->header) - 
+              (hash_table_vector_header_count - 1)) >> 1;
+  LispObj *pairp = (LispObj*) (hashp+1);
+  Boolean 
+    weak_on_value = ((hashp->flags & nhash_weak_value_mask) != 0);
+
+
+  for (i = 2; i <= skip; i++) {
+    rmark(deref(htabv,i));
+  }
+  
+  if (!weak_on_value) {
+    pairp++;
+  }
+  /* unconditionally mark the non-weak element of each pair */
+  while (npairs--) {
+    rmark(*pairp);
+    pairp += 2;
+  }
+
+  deref(htabv,1) = GCweakvll;
+  GCweakvll = htabv;
+}
+
+
+Boolean
+mark_weak_hash_vector(hash_table_vector_header *hashp, natural elements)
+{
+  natural flags = hashp->flags, key_dnode, val_dnode;
+  Boolean 
+    marked_new = false, 
+    key_marked,
+    val_marked,
+    weak_value = ((flags & nhash_weak_value_mask) != 0);
+  int 
+    skip = hash_table_vector_header_count-1,
+    key_tag,
+    val_tag,
+    i;
+  LispObj 
+    *pairp = (LispObj*) (hashp+1),
+    key,
+    val;
+
+  /* Mark everything in the header */
+  
+  for (i = 2; i<= skip; i++) {
+    mark_root(deref(ptr_to_lispobj(hashp),i));
+  }
+
+  elements -= skip;
+
+  for (i = 0; i<elements; i+=2, pairp+=2) {
+    key = pairp[0];
+    val = pairp[1];
+    key_marked = val_marked = true;
+    key_tag = fulltag_of(key);
+    val_tag = fulltag_of(val);
+    if (is_node_fulltag(key_tag)) {
+      key_dnode = gc_area_dnode(key);
+      if ((key_dnode < GCndnodes_in_area) &&
+          ! ref_bit(GCmarkbits,key_dnode)) {
+        key_marked = false;
+      }
+    }
+    if (is_node_fulltag(val_tag)) {
+      val_dnode = gc_area_dnode(val);
+      if ((val_dnode < GCndnodes_in_area) &&
+          ! ref_bit(GCmarkbits,val_dnode)) {
+        val_marked = false;
+      }
+    }
+
+    if (weak_value) {
+      if (val_marked & !key_marked) {
+        mark_root(key);
+        marked_new = true;
+      }
+    } else {
+      if (key_marked & !val_marked) {
+        mark_root(val);
+        marked_new = true;
+      }
+    }
+  }
+  return marked_new;
+}
+
+
+Boolean
+mark_weak_alist(LispObj weak_alist, int weak_type)
+{
+  natural
+    elements = header_element_count(header_of(weak_alist)),
+    dnode;
+  int pair_tag;
+  Boolean marked_new = false;
+  LispObj alist, pair, key, value;
+  bitvector markbits = GCmarkbits;
+
+  if (weak_type >> population_termination_bit) {
+    elements -= 1;
+  }
+  for(alist = deref(weak_alist, elements);
+      (fulltag_of(alist) == fulltag_cons) &&
+      ((dnode = gc_area_dnode(alist)) < GCndnodes_in_area) &&
+      (! ref_bit(markbits,dnode));
+      alist = cdr(alist)) {
+    pair = car(alist);
+    pair_tag = fulltag_of(pair);
+    if ((is_node_fulltag(pair_tag)) &&
+        ((dnode = gc_area_dnode(pair_tag)) < GCndnodes_in_area) &&
+        (! ref_bit(markbits,dnode))) {
+      if (pair_tag == fulltag_cons) {
+        key = car(pair);
+        if ((! is_node_fulltag(fulltag_of(key))) ||
+            ((dnode = gc_area_dnode(key)) >= GCndnodes_in_area) ||
+            ref_bit(markbits,dnode)) {
+          /* key is marked, mark value if necessary */
+          value = cdr(pair);
+          if (is_node_fulltag(fulltag_of(value)) &&
+              ((dnode = gc_area_dnode(value)) < GCndnodes_in_area) &&
+              (! ref_bit(markbits,dnode))) {
+            mark_root(value);
+            marked_new = true;
+          }
+        }
+      } else {
+          mark_root(pair);
+          marked_new = true;
+      }
+    }
+  }
+  return marked_new;
+}
+  
+void
+traditional_markhtabvs()
+{
+  LispObj this, header, pending;
+  int subtag;
+  hash_table_vector_header *hashp;
+  Boolean marked_new;
+
+  do {
+    pending = (LispObj) NULL;
+    marked_new = false;
+    
+    while (GCweakvll) {
+      this = GCweakvll;
+      GCweakvll = deref(this,1);
+      
+      header = header_of(this);
+      subtag = header_subtag(header);
+      
+      if (subtag == subtag_weak) {
+        natural weak_type = deref(this,2);
+        deref(this,1) = pending;
+        pending = this;
+        if ((weak_type & population_type_mask) == population_weak_alist) {
+          if (mark_weak_alist(this, weak_type)) {
+            marked_new = true;
+          }
+        }
+      } else if (subtag == subtag_hash_vector) {
+        natural elements = header_element_count(header);
+
+        hashp = (hash_table_vector_header *) ptr_from_lispobj(untag(this));
+        if (hashp->flags & nhash_weak_mask) {
+          deref(this,1) = pending;
+          pending = this;
+          if (mark_weak_hash_vector(hashp, elements)) {
+            marked_new = true;
+          }
+        } 
+      } else {
+        Bug(NULL, "Strange object on weak vector linked list: 0x~08x\n", this);
+      }
+    }
+
+    if (marked_new) {
+      GCweakvll = pending;
+    }
+  } while (marked_new);
+
+  /* Now, everything's marked that's going to be,  and "pending" is a list
+     of populations and weak hash tables.  CDR down that list and free
+     anything that isn't marked.
+     */
+
+  while (pending) {
+    this = pending;
+    pending = deref(this,1);
+    deref(this,1) = (LispObj)NULL;
+
+    subtag = header_subtag(header_of(this));
+    if (subtag == subtag_weak) {
+      reapweakv(this);
+    } else {
+      reaphashv(this);
+    }
+  }
+
+  /* Finally, mark the termination lists in all terminatable weak vectors
+     They are now linked together on GCweakvll.
+     This is where to store  lisp_global(TERMINATION_LIST) if we decide to do that,
+     but it will force terminatable popualations to hold on to each other
+     (set TERMINATION_LIST before clearing GCweakvll, and don't clear deref(this,1)).
+     */
+  pending = GCweakvll;
+  GCweakvll = (LispObj)NULL;
+  while (pending) {
+    this = pending;
+    pending = deref(this,1);
+    deref(this,1) = (LispObj)NULL;
+    mark_root(deref(this,1+3));
+  }
+}
+
+void
+ncircle_markhtabvs()
+{
+  LispObj this, header, pending = 0;
+  int subtag;
+  Boolean marked_new;
+
+  /* First, process any weak hash tables that may have
+     been encountered by the link-inverting marker; we
+     should have more stack space now. */
+
+  while (GCdwsweakvll) {
+    this = GCdwsweakvll;
+    GCdwsweakvll = deref(this,1);
+    ncircle_mark_weak_htabv(this);
+  }
+
+  while (GCweakvll) {
+    this = GCweakvll;
+    GCweakvll = deref(this,1);
+      
+    header = header_of(this);
+    subtag = header_subtag(header);
+      
+    if (subtag == subtag_weak) {
+      natural weak_type = deref(this,2);
+      deref(this,1) = pending;
+      pending = this;
+      if ((weak_type & population_type_mask) == population_weak_alist) {
+        if (mark_weak_alist(this, weak_type)) {
+          marked_new = true;
+          }
+      }
+    } else if (subtag == subtag_hash_vector) {
+      reaphashv(this);
+    }
+  }
+
+  /* Now, everything's marked that's going to be,  and "pending" is a list
+     of populations.  CDR down that list and free
+     anything that isn't marked.
+     */
+
+  while (pending) {
+    this = pending;
+    pending = deref(this,1);
+    deref(this,1) = (LispObj)NULL;
+
+    subtag = header_subtag(header_of(this));
+    if (subtag == subtag_weak) {
+      reapweakv(this);
+    } else {
+      Bug(NULL, "Bad object on pending list: %s\n", this);
+    }
+  }
+
+  /* Finally, mark the termination lists in all terminatable weak vectors
+     They are now linked together on GCweakvll.
+     This is where to store  lisp_global(TERMINATION_LIST) if we decide to do that,
+     but it will force terminatable popualations to hold on to each other
+     (set TERMINATION_LIST before clearing GCweakvll, and don't clear deref(this,1)).
+     */
+  pending = GCweakvll;
+  GCweakvll = (LispObj)NULL;
+  while (pending) {
+    this = pending;
+    pending = deref(this,1);
+    deref(this,1) = (LispObj)NULL;
+    mark_root(deref(this,1+3));
+  }
+}
+
+void
+mark_tcr_tlb(TCR *tcr)
+{
+  natural n = tcr->tlb_limit;
+  LispObj 
+    *start = tcr->tlb_pointer,
+    *end = (LispObj *) ((BytePtr)start+n),
+    node;
+
+  while (start < end) {
+    node = *start;
+    if (node != no_thread_local_binding_marker) {
+      mark_root(node);
+    }
+    start++;
+  }
+}
+
+/*
+  Mark things that're only reachable through some (suspended) TCR.
+  (This basically means the tcr's gc_context and the exception
+  frames on its xframe_list.)
+*/
+
+void
+mark_tcr_xframes(TCR *tcr)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+
+  xp = tcr->gc_context;
+  if (xp) {
+#ifndef X8632
+    mark_xp(xp);
+#else
+    mark_xp(xp, tcr->node_regs_mask);
+#endif
+  }
+#ifdef X8632
+  mark_root(tcr->save0);
+  mark_root(tcr->save1);
+  mark_root(tcr->save2);
+  mark_root(tcr->save3);
+  mark_root(tcr->next_method_context);
+#endif
+  
+  for (xframes = (xframe_list *) tcr->xframe; 
+       xframes; 
+       xframes = xframes->prev) {
+#ifndef X8632
+      mark_xp(xframes->curr);
+#else
+      mark_xp(xframes->curr, xframes->node_regs_mask);
+#endif
+  }
+}
+      
+
+void *postGCptrs = NULL;
+struct xmacptr *user_postGC_macptrs = NULL;
+
+
+void
+postGCfree(void *p)
+{
+  *(void **)p = postGCptrs;
+  postGCptrs = p;
+}
+
+void
+postGCfreexmacptr(struct xmacptr *p)
+{
+  p->class = (LispObj) user_postGC_macptrs;
+  user_postGC_macptrs = p;
+}
+
+
+xmacptr_dispose_fn xmacptr_dispose_functions[xmacptr_flag_user_last-xmacptr_flag_user_first];
+
+
+
+void
+freeGCptrs()
+{
+  void *p, *next, *addr;
+  struct xmacptr *x, *xnext;
+  int i, flags;
+  xmacptr_dispose_fn dfn;
+
+  for (p = postGCptrs; p; p = next) {
+    next = *((void **)p);
+    free(p);
+  }
+  postGCptrs = NULL;
+  
+  for (x = user_postGC_macptrs; x; x = xnext) {
+    xnext = (xmacptr *) (x->class);;
+    flags = x->flags - xmacptr_flag_user_first;
+    dfn = xmacptr_dispose_functions[flags];
+    addr = (void *) x->address;
+    x->address = 0;
+    x->flags = 0;
+    x->link = 0;
+    x->class = 0;
+    if (dfn && addr) {
+      dfn(addr);
+    }
+  }
+
+  user_postGC_macptrs = NULL;
+}
+
+int
+register_xmacptr_dispose_function(void *dfn)
+{
+  int i, k;
+  
+  for( i = 0, k = xmacptr_flag_user_first; k < xmacptr_flag_user_last; i++, k++) {
+    if (xmacptr_dispose_functions[i]==NULL) {
+      xmacptr_dispose_functions[i] = dfn;
+      return k;
+    }
+    if (xmacptr_dispose_functions[i] == dfn) {
+      return k;
+    }
+  }
+  return 0;
+}
+
+void
+reap_gcable_ptrs()
+{
+  LispObj *prev = &(lisp_global(GCABLE_POINTERS)), next, ptr;
+  xmacptr_flag flag;
+  natural dnode;
+  xmacptr *x;
+
+  while((next = *prev) != (LispObj)NULL) {
+    dnode = gc_area_dnode(next);
+    x = (xmacptr *) ptr_from_lispobj(untag(next));
+
+    if ((dnode >= GCndnodes_in_area) ||
+        (ref_bit(GCmarkbits,dnode))) {
+      prev = &(x->link);
+    } else {
+      *prev = x->link;
+      flag = (xmacptr_flag)(x->flags);
+      ptr = x->address;
+
+      if (ptr) {
+        switch (flag) {
+        case xmacptr_flag_recursive_lock:
+	  destroy_recursive_lock((RECURSIVE_LOCK)ptr_from_lispobj(ptr));
+          break;
+
+        case xmacptr_flag_ptr:
+	  postGCfree((void *)ptr_from_lispobj(ptr));
+          break;
+
+        case xmacptr_flag_rwlock:
+          rwlock_destroy((rwlock *)ptr_from_lispobj(ptr));
+          break;
+
+        case xmacptr_flag_semaphore:
+	  destroy_semaphore((void**)&(x->address));
+          break;
+
+        default:
+          if ((flag >= xmacptr_flag_user_first) &&
+              (flag < xmacptr_flag_user_last)) {
+            set_n_bits(GCmarkbits,dnode,3);
+            postGCfreexmacptr(x);
+            break;
+          }
+          /* (warn "unknown xmacptr_flag: ~s" flag) */
+          /* Unknowd, and perhaps unknowdable. */
+          /* Fall in: */
+        case xmacptr_flag_none:
+          break;
+        }
+      }
+    }
+  }
+}
+
+
+
+#if  WORD_SIZE == 64
+unsigned short *_one_bits = NULL;
+
+unsigned short
+logcount16(unsigned short n)
+{
+  unsigned short c=0;
+  
+  while(n) {
+    n = n & (n-1);
+    c++;
+  }
+  return c;
+}
+
+void
+gc_init()
+{
+  int i;
+  
+  _one_bits = malloc(sizeof(unsigned short) * (1<<16));
+
+  for (i = 0; i < (1<<16); i++) {
+    _one_bits[i] = dnode_size*logcount16(i);
+  }
+}
+
+
+#else
+const unsigned char _one_bits[256] = {
+    0*8,1*8,1*8,2*8,1*8,2*8,2*8,3*8,1*8,2*8,2*8,3*8,2*8,3*8,3*8,4*8,
+    1*8,2*8,2*8,3*8,2*8,3*8,3*8,4*8,2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,
+    1*8,2*8,2*8,3*8,2*8,3*8,3*8,4*8,2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,
+    2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,
+    1*8,2*8,2*8,3*8,2*8,3*8,3*8,4*8,2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,
+    2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,
+    2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,
+    3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,4*8,5*8,5*8,6*8,5*8,6*8,6*8,7*8,
+    1*8,2*8,2*8,3*8,2*8,3*8,3*8,4*8,2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,
+    2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,
+    2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,
+    3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,4*8,5*8,5*8,6*8,5*8,6*8,6*8,7*8,
+    2*8,3*8,3*8,4*8,3*8,4*8,4*8,5*8,3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,
+    3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,4*8,5*8,5*8,6*8,5*8,6*8,6*8,7*8,
+    3*8,4*8,4*8,5*8,4*8,5*8,5*8,6*8,4*8,5*8,5*8,6*8,5*8,6*8,6*8,7*8,
+    4*8,5*8,5*8,6*8,5*8,6*8,6*8,7*8,5*8,6*8,6*8,7*8,6*8,7*8,7*8,8*8
+};
+
+
+void
+gc_init()
+{
+}
+
+#endif
+
+
+weak_mark_fun dws_mark_weak_htabv = traditional_dws_mark_htabv;
+weak_mark_fun mark_weak_htabv = traditional_mark_weak_htabv;
+weak_process_fun markhtabvs = traditional_markhtabvs;
+
+void
+install_weak_mark_functions(natural set) {
+  switch(set) {
+  case 0:
+  default:
+    dws_mark_weak_htabv = traditional_dws_mark_htabv;
+    mark_weak_htabv = traditional_mark_weak_htabv;
+    markhtabvs = traditional_markhtabvs;
+    break;
+  case 1:
+    dws_mark_weak_htabv = ncircle_dws_mark_htabv;
+    mark_weak_htabv = ncircle_mark_weak_htabv;
+    markhtabvs = ncircle_markhtabvs;
+    break;
+  }
+}
+
+LispObj
+node_forwarding_address(LispObj node)
+{
+  int tag_n;
+  natural dnode = gc_dynamic_area_dnode(node);
+
+  if ((dnode >= GCndynamic_dnodes_in_area) ||
+      (node < GCfirstunmarked)) {
+    return node;
+  }
+
+  tag_n = fulltag_of(node);
+  if (!is_node_fulltag(tag_n)) {
+    return node;
+  }
+
+  return dnode_forwarding_address(dnode, tag_n);
+}
+
+Boolean
+update_noderef(LispObj *noderef)
+{
+  LispObj
+    node = *noderef,
+    new = node_forwarding_address(node);
+
+  if (new != node) {
+    *noderef = new;
+    return true;
+  }
+  return false;
+}
+
+void
+update_locref(LispObj *locref)
+{
+  LispObj
+    obj = *locref,
+    new = locative_forwarding_address(obj);
+
+  if (new != obj) {
+    *locref = new;
+  }
+}
+
+void
+forward_gcable_ptrs()
+{
+  LispObj *prev = &(lisp_global(GCABLE_POINTERS)), next, new;
+  struct xmacptr **xprev, *xnext, *xnew;
+
+  while ((next = *prev) != (LispObj)NULL) {
+    new = node_forwarding_address(next);
+    if (new != next) {
+      *prev = new;
+    }
+    prev = &(((xmacptr *)ptr_from_lispobj(untag(next)))->link);
+  }
+  xprev = &user_postGC_macptrs;
+  while (xnext = *xprev) {
+    xnew = (struct xmacptr *)locative_forwarding_address((LispObj)xnext);
+    if (xnew != xnext) {
+      *xprev = xnew;
+    }
+    xprev = (struct xmacptr **)(&(xnext->class));
+  }
+}
+
+void
+forward_memoized_area(area *a, natural num_memo_dnodes)
+{
+  bitvector refbits = a->refbits;
+  LispObj *p = (LispObj *) a->low, x1, x2, new;
+  natural bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0, hash_dnode_limit = 0;
+  int tag_x1;
+  hash_table_vector_header *hashp = NULL;
+  Boolean header_p;
+
+  if (num_memo_dnodes) {
+    if (GCDebug) {
+      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
+    }
+
+    /* This is pretty straightforward, but we have to note
+       when we move a key in a hash table vector that wants
+       us to tell it about that. */
+
+    set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
+    while (memo_dnode < num_memo_dnodes) {
+      if (bits == 0) {
+        int remain = nbits_in_word - bitidx;
+        memo_dnode += remain;
+        p += (remain+remain);
+        bits = *++bitsp;
+        bitidx = 0;
+      } else {
+        nextbit = count_leading_zeros(bits);
+        if ((diff = (nextbit - bitidx)) != 0) {
+          memo_dnode += diff;
+          bitidx = nextbit;
+          p += (diff+diff);
+        }
+        x1 = p[0];
+        x2 = p[1];
+        tag_x1 = fulltag_of(x1);
+        bits &= ~(BIT0_MASK >> bitidx);
+        header_p = (nodeheader_tag_p(tag_x1));
+
+        if (header_p &&
+            (header_subtag(x1) == subtag_hash_vector)) {
+          hashp = (hash_table_vector_header *) p;
+          if (hashp->flags & nhash_track_keys_mask) {
+            hash_dnode_limit = memo_dnode + ((header_element_count(x1)+2)>>1);
+          } else {
+            hashp = NULL;
+          }
+        }
+
+
+        if (! header_p) {
+          new = node_forwarding_address(x1);
+          if (new != x1) {
+            *p = new;
+          }
+        }
+        p++;
+
+        new = node_forwarding_address(x2);
+        if (new != x2) {
+          *p = new;
+          if (memo_dnode < hash_dnode_limit) {
+            /* If this code is reached, 'hashp' is non-NULL and pointing
+               at the header of a hash_table_vector, and 'memo_dnode' identifies
+               a pair of words inside the hash_table_vector.  It may be
+               hard for program analysis tools to recognize that, but I
+               believe that warnings about 'hashp' being NULL here can
+               be safely ignored. */
+            hashp->flags |= nhash_key_moved_mask;
+            hash_dnode_limit = 0;
+            hashp = NULL;
+          }
+        }
+        p++;
+        memo_dnode++;
+        bitidx++;
+
+      }
+    }
+  }
+}
+
+void
+forward_tcr_tlb(TCR *tcr)
+{
+  natural n = tcr->tlb_limit;
+  LispObj 
+    *start = tcr->tlb_pointer, 
+    *end = (LispObj *) ((BytePtr)start+n),
+    node;
+
+  while (start < end) {
+    node = *start;
+    if (node != no_thread_local_binding_marker) {
+      update_noderef(start);
+    }
+    start++;
+  }
+}
+
+void
+reclaim_static_dnodes()
+{
+  natural nstatic = tenured_area->static_dnodes, 
+    i, 
+    bits, 
+    bitnum,
+    nfree = 0,
+    nstatic_conses = area_dnode(static_cons_area->high, static_cons_area->low);
+  cons *c = (cons *)tenured_area->low, *d;
+  bitvector bitsp = GCmarkbits;
+  LispObj head = lisp_global(STATIC_CONSES);
+
+  for (i = 0; i < nstatic; i+= nbits_in_word, c+= nbits_in_word) {
+    bits = *bitsp++;
+    if (bits != ALL_ONES) {
+      for (bitnum = 0; bitnum < nbits_in_word; bitnum++) {
+        if (! (bits & (BIT0_MASK>>bitnum))) {
+          d = c + bitnum;
+          d->car = 0;
+          if (i < nstatic_conses) {                
+            d->cdr = head;
+            head = ((LispObj)d)+fulltag_cons;
+            nfree++;
+          } else {
+            d->cdr = 0;
+          }
+        }
+      }
+    }
+  }
+  lisp_global(STATIC_CONSES) = head;
+  lisp_global(FREE_STATIC_CONSES)+=(nfree<<fixnumshift);
+}
+
+Boolean
+youngest_non_null_area_p (area *a)
+{
+  if (a->active == a->high) {
+    return false;
+  } else {
+    for (a = a->younger; a; a = a->younger) {
+      if (a->active != a->high) {
+        return false;
+      }
+    }
+  };
+  return true;
+}
+
+Boolean just_purified_p = false;
+
+/*
+  All thread's stack areas have been "normalized", as
+  has the dynamic heap.  (The "active" pointer in these areas
+  matches the stack pointer/freeptr value at the time that
+  the exception occurred.)
+*/
+
+#define get_time(when) gettimeofday(&when, NULL)
+
+
+
+#ifdef FORCE_DWS_MARK
+#warning recursive marker disabled for testing; remember to re-enable it
+#endif
+
+
+Boolean
+mark_static_ref(LispObj n, BytePtr dynamic_start, natural ndynamic_dnodes)
+{
+  int tag_n = fulltag_of(n);
+  natural dyn_dnode;
+
+  if (nodeheader_tag_p(tag_n)) {
+    return (header_subtag(n) == subtag_hash_vector);
+  }
+ 
+  if (is_node_fulltag (tag_n)) {
+    dyn_dnode = area_dnode(n, dynamic_start);
+    if (dyn_dnode < ndynamic_dnodes) {
+      mark_root(n);             /* May or may not mark it */
+      return true;              /* but return true 'cause it's a dynamic node */
+    }
+  }
+  return false;                 /* Not a heap pointer or not dynamic */
+}
+
+void
+mark_managed_static_refs(area *a, BytePtr low_dynamic_address, natural ndynamic_dnodes)
+{
+  bitvector refbits = a->refbits;
+  LispObj *p = (LispObj *) a->low, x1, x2;
+  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0,
+    num_memo_dnodes = a->ndnodes;
+  Boolean keep_x1, keep_x2;
+
+  if (num_memo_dnodes) {
+    if (GCDebug) {
+      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
+    }
+
+ 
+    set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
+    inbits = outbits = bits;
+    while (memo_dnode < num_memo_dnodes) {
+      if (bits == 0) {
+        int remain = nbits_in_word - bitidx;
+        memo_dnode += remain;
+        p += (remain+remain);
+        if (outbits != inbits) {
+          *bitsp = outbits;
+        }
+        bits = *++bitsp;
+        inbits = outbits = bits;
+        bitidx = 0;
+      } else {
+        nextbit = count_leading_zeros(bits);
+        if ((diff = (nextbit - bitidx)) != 0) {
+          memo_dnode += diff;
+          bitidx = nextbit;
+          p += (diff+diff);
+        }
+        x1 = *p++;
+        x2 = *p++;
+        bits &= ~(BIT0_MASK >> bitidx);
+        keep_x1 = mark_static_ref(x1, low_dynamic_address, ndynamic_dnodes);
+        keep_x2 = mark_static_ref(x2, low_dynamic_address, ndynamic_dnodes);
+        if ((keep_x1 == false) && 
+            (keep_x2 == false)) {
+          outbits &= ~(BIT0_MASK >> bitidx);
+        }
+        memo_dnode++;
+        bitidx++;
+      }
+    }
+    if (GCDebug) {
+      p = (LispObj *) a->low;
+      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
+    }
+  }
+}
+
+void 
+gc(TCR *tcr, signed_natural param)
+{
+  struct timeval start, stop;
+  area *a = active_dynamic_area, *to = NULL, *from = NULL, *note = NULL;
+  unsigned timeidx = 1;
+  paging_info paging_info_start;
+  LispObj
+    pkg = 0,
+    itabvec = 0;
+  BytePtr oldfree = a->active;
+  TCR *other_tcr;
+  natural static_dnodes;
+
+  install_weak_mark_functions(lisp_global(WEAK_GC_METHOD) >> fixnumshift);
+  
+#ifndef FORCE_DWS_MARK
+  if ((natural) (tcr->cs_limit) == CS_OVERFLOW_FORCE_LIMIT) {
+    GCstack_limit = CS_OVERFLOW_FORCE_LIMIT;
+  } else {
+    GCstack_limit = (natural)(tcr->cs_limit)+(natural)page_size;
+  }
+#else
+  GCstack_limit = CS_OVERFLOW_FORCE_LIMIT;
+#endif
+
+  GCephemeral_low = lisp_global(OLDEST_EPHEMERAL);
+  if (GCephemeral_low) {
+    GCn_ephemeral_dnodes=area_dnode(oldfree, GCephemeral_low);
+  } else {
+    GCn_ephemeral_dnodes = 0;
+  }
+  
+  if (GCn_ephemeral_dnodes) {
+    GCverbose = ((nrs_GC_EVENT_STATUS_BITS.vcell & egc_verbose_bit) != 0);
+  } else {
+    GCverbose = ((nrs_GC_EVENT_STATUS_BITS.vcell & gc_verbose_bit) != 0);
+  }
+
+  if (GCephemeral_low) {
+    if ((oldfree-g1_area->low) < g1_area->threshold) {
+      to = g1_area;
+      note = a;
+      timeidx = 4;
+    } else if ((oldfree-g2_area->low) < g2_area->threshold) {
+      to = g2_area;
+      from = g1_area;
+      note = g1_area;
+      timeidx = 3;
+    } else {
+      to = tenured_area;
+      from = g2_area;
+      note = g2_area;
+      timeidx = 2;
+    } 
+  } else {
+    note = tenured_area;
+  }
+
+  if (GCverbose) {
+    char buf[16];
+
+    sample_paging_info(&paging_info_start);
+    comma_output_decimal(buf,16,area_dnode(oldfree,a->low) << dnode_shift);
+    if (GCephemeral_low) {
+      fprintf(dbgout,
+              "\n\n;;; Starting Ephemeral GC of generation %d",
+              (from == g2_area) ? 2 : (from == g1_area) ? 1 : 0); 
+    } else {
+      fprintf(dbgout,"\n\n;;; Starting full GC");
+    }
+    fprintf(dbgout, ", %s bytes allocated.\n", buf);
+  }
+
+  get_time(start);
+
+  /* The link-inverting marker might need to write to watched areas */
+  unprotect_watched_areas();
+
+  lisp_global(IN_GC) = (1<<fixnumshift);
+
+  if (just_purified_p) {
+    just_purified_p = false;
+    GCDebug = false;
+  } else {
+    GCDebug = ((nrs_GC_EVENT_STATUS_BITS.vcell & gc_integrity_check_bit) != 0);
+    if (GCDebug) {
+      check_all_areas(tcr);
+    }
+  }
+
+  if (from) {
+    untenure_from_area(from);
+  }
+  static_dnodes = static_dnodes_for_area(a);
+  GCmarkbits = a->markbits;
+  GCarealow = ptr_to_lispobj(a->low);
+  GCareadynamiclow = GCarealow+(static_dnodes << dnode_shift);
+  GCndnodes_in_area = gc_area_dnode(oldfree);
+
+  if (GCndnodes_in_area) {
+    GCndynamic_dnodes_in_area = GCndnodes_in_area-static_dnodes;
+    GCdynamic_markbits = 
+      GCmarkbits + ((GCndnodes_in_area-GCndynamic_dnodes_in_area)>>bitmap_shift);
+
+    zero_bits(GCmarkbits, GCndnodes_in_area);
+    GCweakvll = (LispObj)NULL;
+
+    if (GCn_ephemeral_dnodes == 0) {
+      /* For GCTWA, mark the internal package hash table vector of
+       *PACKAGE*, but don't mark its contents. */
+      {
+        LispObj
+          itab;
+        natural
+          dnode, ndnodes;
+      
+        pkg = nrs_PACKAGE.vcell;
+        if ((fulltag_of(pkg) == fulltag_misc) &&
+            (header_subtag(header_of(pkg)) == subtag_package)) {
+          itab = ((package *)ptr_from_lispobj(untag(pkg)))->itab;
+          itabvec = car(itab);
+          dnode = gc_area_dnode(itabvec);
+          if (dnode < GCndnodes_in_area) {
+            ndnodes = (header_element_count(header_of(itabvec))+1) >> 1;
+            set_n_bits(GCmarkbits, dnode, ndnodes);
+          }
+        }
+      }
+    }
+
+    mark_root(lisp_global(STATIC_CONSES));
+
+    {
+      area *next_area;
+      area_code code;
+
+      /* Could make a jump table instead of the typecase */
+
+      for (next_area = a->succ; (code = next_area->code) != AREA_VOID; next_area = next_area->succ) {
+        switch (code) {
+        case AREA_TSTACK:
+          mark_tstack_area(next_area);
+          break;
+
+        case AREA_VSTACK:
+          mark_vstack_area(next_area);
+          break;
+          
+        case AREA_CSTACK:
+          mark_cstack_area(next_area);
+          break;
+
+        case AREA_STATIC:
+	case AREA_WATCHED:
+        case AREA_DYNAMIC:                  /* some heap that isn't "the" heap */
+          /* In both of these cases, we -could- use the area's "markbits"
+             bitvector as a reference map.  It's safe (but slower) to
+             ignore that map and process the entire area.
+          */
+          if (next_area->younger == NULL) {
+            mark_simple_area_range((LispObj *) next_area->low, (LispObj *) next_area->active);
+          }
+          break;
+
+        default:
+          break;
+        }
+      }
+    }
+  
+    if (lisp_global(OLDEST_EPHEMERAL)) {
+      mark_memoized_area(tenured_area, area_dnode(a->low,tenured_area->low));
+    }
+
+    mark_managed_static_refs(managed_static_area,low_markable_address,area_dnode(a->active,low_markable_address));
+    
+    other_tcr = tcr;
+    do {
+      mark_tcr_xframes(other_tcr);
+      mark_tcr_tlb(other_tcr);
+      other_tcr = other_tcr->next;
+    } while (other_tcr != tcr);
+
+
+
+
+    /* Go back through *package*'s internal symbols, marking
+       any that aren't worthless.
+    */
+    
+    if (itabvec) {
+      natural
+        i,
+        n = header_element_count(header_of(itabvec));
+      LispObj
+        sym,
+        *raw = 1+((LispObj *)ptr_from_lispobj(untag(itabvec)));
+
+      for (i = 0; i < n; i++) {
+        sym = *raw++;
+        if (is_symbol_fulltag(sym)) {
+          lispsymbol *rawsym = (lispsymbol *)ptr_from_lispobj(untag(sym));
+          natural dnode = gc_area_dnode(sym);
+          
+          if ((dnode < GCndnodes_in_area) &&
+              (!ref_bit(GCmarkbits,dnode))) {
+            /* Symbol is in GC area, not marked.
+               Mark it if fboundp, boundp, or if
+               it has a plist or another home package.
+            */
+            
+            if (FBOUNDP(rawsym) ||
+                BOUNDP(rawsym) ||
+                (rawsym->flags != 0) || /* SPECIAL, etc. */
+                (rawsym->plist != lisp_nil) ||
+                ((rawsym->package_predicate != pkg) &&
+                 (rawsym->package_predicate != lisp_nil))) {
+              mark_root(sym);
+            }
+          }
+        }
+      }
+    }
+
+    (void)markhtabvs();
+
+    if (itabvec) {
+      natural
+        i,
+        n = header_element_count(header_of(itabvec));
+      LispObj
+        sym,
+        *raw = 1+((LispObj *)ptr_from_lispobj(untag(itabvec)));
+
+      for (i = 0; i < n; i++, raw++) {
+        sym = *raw;
+        if (is_symbol_fulltag(sym)) {
+          natural dnode = gc_area_dnode(sym);
+
+          if ((dnode < GCndnodes_in_area) &&
+              (!ref_bit(GCmarkbits,dnode))) {
+            *raw = unbound_marker;
+          }
+        }
+      }
+    }
+  
+    reap_gcable_ptrs();
+
+    GCrelocptr = global_reloctab;
+    GCfirstunmarked = calculate_relocation();
+
+    if (!GCephemeral_low) {
+      reclaim_static_dnodes();
+    }
+
+    forward_range((LispObj *) ptr_from_lispobj(GCarealow), (LispObj *) ptr_from_lispobj(GCfirstunmarked));
+
+    other_tcr = tcr;
+    do {
+      forward_tcr_xframes(other_tcr);
+      forward_tcr_tlb(other_tcr);
+      other_tcr = other_tcr->next;
+    } while (other_tcr != tcr);
+
+  
+    forward_gcable_ptrs();
+
+
+
+    {
+      area *next_area;
+      area_code code;
+
+      /* Could make a jump table instead of the typecase */
+
+      for (next_area = a->succ; (code = next_area->code) != AREA_VOID; next_area = next_area->succ) {
+        switch (code) {
+        case AREA_TSTACK:
+          forward_tstack_area(next_area);
+          break;
+
+        case AREA_VSTACK:
+          forward_vstack_area(next_area);
+          break;
+
+        case AREA_CSTACK:
+          forward_cstack_area(next_area);
+          break;
+
+        case AREA_STATIC:
+	case AREA_WATCHED:
+        case AREA_DYNAMIC:                  /* some heap that isn't "the" heap */
+          if (next_area->younger == NULL) {
+            forward_range((LispObj *) next_area->low, (LispObj *) next_area->active);
+          }
+          break;
+
+        default:
+          break;
+        }
+      }
+    }
+
+    if (GCephemeral_low) {
+      forward_memoized_area(tenured_area, area_dnode(a->low, tenured_area->low));
+    }
+  
+    forward_memoized_area(managed_static_area,area_dnode(managed_static_area->active,managed_static_area->low));
+    a->active = (BytePtr) ptr_from_lispobj(compact_dynamic_heap());
+    if (to) {
+      tenure_to_area(to);
+    }
+
+    zero_memory_range(a->active, oldfree);
+
+    resize_dynamic_heap(a->active,
+                        (GCephemeral_low == 0) ? lisp_heap_gc_threshold : 0);
+
+    /*
+      If the EGC is enabled: If there's no room for the youngest
+      generation, untenure everything.  If this was a full GC and
+      there's now room for the youngest generation, tenure everything.
+    */
+    if (a->older != NULL) {
+      natural nfree = (a->high - a->active);
+
+
+      if (nfree < a->threshold) {
+        untenure_from_area(tenured_area);
+      } else {
+        if (GCephemeral_low == 0) {
+          tenure_to_area(tenured_area);
+        }
+      }
+    }
+  }
+  lisp_global(GC_NUM) += (1<<fixnumshift);
+  if (note) {
+    note->gccount += (1<<fixnumshift);
+  }
+
+  if (GCDebug) {
+    check_all_areas(tcr);
+  }
+
+  
+  lisp_global(IN_GC) = 0;
+  
+  protect_watched_areas();
+
+  nrs_GC_EVENT_STATUS_BITS.vcell |= gc_postgc_pending;
+  get_time(stop);
+
+  {
+    lispsymbol * total_gc_microseconds = (lispsymbol *) &(nrs_TOTAL_GC_MICROSECONDS);
+    lispsymbol * total_bytes_freed = (lispsymbol *) &(nrs_TOTAL_BYTES_FREED);
+    LispObj val;
+    struct timeval *timeinfo, elapsed = {0, 0};
+
+    val = total_gc_microseconds->vcell;
+    if ((fulltag_of(val) == fulltag_misc) &&
+        (header_subtag(header_of(val)) == subtag_macptr)) {
+      timersub(&stop, &start, &elapsed);
+      timeinfo = (struct timeval *) ptr_from_lispobj(((macptr *) ptr_from_lispobj(untag(val)))->address);
+      timeradd(timeinfo,  &elapsed, timeinfo);
+      timeradd(timeinfo+timeidx,  &elapsed, timeinfo+timeidx);
+    }
+
+    val = total_bytes_freed->vcell;
+    if ((fulltag_of(val) == fulltag_misc) &&
+        (header_subtag(header_of(val)) == subtag_macptr)) {
+      long long justfreed = oldfree - a->active;
+      *( (long long *) ptr_from_lispobj(((macptr *) ptr_from_lispobj(untag(val)))->address)) += justfreed;
+      if (GCverbose) {
+        char buf[16];
+        paging_info paging_info_stop;
+
+        sample_paging_info(&paging_info_stop);
+        if (justfreed <= heap_segment_size) {
+          justfreed = 0;
+        }
+        comma_output_decimal(buf,16,justfreed);
+        if (note == tenured_area) {
+          fprintf(dbgout,";;; Finished full GC. %s bytes freed in %d.%06d s\n\n", buf, elapsed.tv_sec, elapsed.tv_usec);
+        } else {
+          fprintf(dbgout,";;; Finished EGC of generation %d. %s bytes freed in %d.%06d s\n\n", 
+                  (from == g2_area) ? 2 : (from == g1_area) ? 1 : 0,
+                  buf, 
+                  elapsed.tv_sec, elapsed.tv_usec);
+        }
+        report_paging_info_delta(dbgout, &paging_info_start, &paging_info_stop);
+      }
+    }
+  }
+}
Index: /branches/new-random/lisp-kernel/gc.h
===================================================================
--- /branches/new-random/lisp-kernel/gc.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/gc.h	(revision 13309)
@@ -0,0 +1,246 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __GC_H__
+#define __GC_H__ 1
+
+#include "lisp.h"
+#include "bits.h"
+#include "lisp-exceptions.h"
+#include "memprotect.h"
+
+
+
+#ifdef PPC
+#define is_node_fulltag(f)  ((1<<(f))&((1<<fulltag_cons)|(1<<fulltag_misc)))
+#ifdef PPC64
+#define PPC64_CODE_VECTOR_PREFIX (('C'<< 24) | ('O' << 16) | ('D' << 8) | 'E')
+#else
+/*
+  A code-vector's header can't look like a valid instruction or UUO:
+  the low 8 bits must be subtag_code_vector, and the top 6 bits
+  must be 0.  That means that the maximum length of a code vector
+  is 18 bits worth of elements (~1MB.)
+*/
+
+#define code_header_mask ((0x3f<<26) | subtag_code_vector)
+#endif
+#endif
+
+#ifdef X86
+#ifdef X8664
+#define is_node_fulltag(f)  ((1<<(f))&((1<<fulltag_cons)    | \
+				       (1<<fulltag_tra_0)   | \
+				       (1<<fulltag_tra_1)   | \
+				       (1<<fulltag_misc)    | \
+				       (1<<fulltag_symbol)  | \
+				       (1<<fulltag_function)))
+#else
+#define is_node_fulltag(f)  ((1<<(f))&((1<<fulltag_cons) | \
+				       (1<<fulltag_misc) | \
+				       (1<<fulltag_tra)))
+#endif
+#endif
+
+
+extern void zero_memory_range(BytePtr,BytePtr);
+extern LispObj GCarealow, GCareadynamiclow;
+extern natural GCndnodes_in_area, GCndynamic_dnodes_in_area;
+extern bitvector GCmarkbits, GCdynamic_markbits;
+LispObj *global_reloctab, *GCrelocptr;
+LispObj GCfirstunmarked;
+
+extern natural lisp_heap_gc_threshold;
+void mark_root(LispObj);
+void mark_pc_root(LispObj);
+void mark_locative_root(LispObj);
+void rmark(LispObj);
+void postGCfree(void *);
+LispObj *skip_over_ivector(LispObj, LispObj);
+void mark_simple_area_range(LispObj *,LispObj *);
+LispObj calculate_relocation();
+LispObj locative_forwarding_address(LispObj);
+LispObj node_forwarding_address(LispObj);
+void forward_range(LispObj *, LispObj *);
+void note_memoized_references(ExceptionInformation *,LogicalAddress, LogicalAddress, BytePtr *, BytePtr *);
+void gc(TCR *, signed_natural);
+int change_hons_area_size(TCR *, signed_natural);
+void delete_protected_area(protected_area_ptr);
+Boolean egc_control(Boolean, BytePtr);
+Boolean free_segments_zero_filled_by_OS;
+
+/* an type representing 1/4 of a natural word */
+#if WORD_SIZE == 64
+typedef unsigned short qnode;
+#else
+typedef unsigned char qnode;
+#endif
+
+
+#ifdef fulltag_symbol
+#define is_symbol_fulltag(x) (fulltag_of(x) == fulltag_symbol)
+#else
+#define is_symbol_fulltag(x) (fulltag_of(x) == fulltag_misc)
+#endif
+
+#define area_dnode(w,low) ((natural)(((ptr_to_lispobj(w)) - ptr_to_lispobj(low))>>dnode_shift))
+#define gc_area_dnode(w)  area_dnode(w,GCarealow)
+#define gc_dynamic_area_dnode(w) area_dnode(w,GCareadynamiclow)
+
+#if defined(PPC64) || defined(X8632)
+#define forward_marker subtag_forward_marker
+#else
+#define forward_marker fulltag_nil
+#endif
+
+#ifdef PPC64
+#define VOID_ALLOCPTR ((LispObj)(0x8000000000000000-dnode_size))
+#else
+#define VOID_ALLOCPTR ((LispObj)(-dnode_size))
+#endif
+
+#ifdef DARWIN
+#include <mach/task_info.h>
+typedef struct task_events_info paging_info;
+#else
+#ifndef WINDOWS
+#include <sys/resource.h>
+typedef struct rusage paging_info;
+#else
+typedef natural paging_info;
+#endif
+#endif
+
+#undef __argv
+#include <stdio.h>
+
+void sample_paging_info(paging_info *);
+void report_paging_info_delta(FILE*, paging_info *, paging_info *);
+
+
+#define GC_TRAP_FUNCTION_IMMEDIATE_GC (-1)
+#define GC_TRAP_FUNCTION_GC 0
+#define GC_TRAP_FUNCTION_PURIFY 1
+#define GC_TRAP_FUNCTION_IMPURIFY 2
+#define GC_TRAP_FUNCTION_FLASH_FREEZE 4
+#define GC_TRAP_FUNCTION_SAVE_APPLICATION 8
+
+#define GC_TRAP_FUNCTION_GET_LISP_HEAP_THRESHOLD 16
+#define GC_TRAP_FUNCTION_SET_LISP_HEAP_THRESHOLD 17
+#define GC_TRAP_FUNCTION_USE_LISP_HEAP_THRESHOLD 18
+#define GC_TRAP_FUNCTION_ENSURE_STATIC_CONSES 19
+#define GC_TRAP_FUNCTION_EGC_CONTROL 32
+#define GC_TRAP_FUNCTION_CONFIGURE_EGC 64
+#define GC_TRAP_FUNCTION_FREEZE 129
+#define GC_TRAP_FUNCTION_THAW 130
+
+Boolean GCDebug, GCverbose, just_purified_p;
+bitvector GCmarkbits, GCdynamic_markbits;
+LispObj GCarealow, GCareadynamiclow;
+natural GCndnodes_in_area, GCndynamic_dnodes_in_area;
+LispObj GCweakvll,GCdwsweakvll;
+LispObj GCephemeral_low;
+natural GCn_ephemeral_dnodes;
+natural GCstack_limit;
+
+#if WORD_SIZE == 64
+unsigned short *_one_bits;
+#else
+const unsigned char _one_bits[256];
+#endif
+
+#define one_bits(x) _one_bits[x]
+
+natural static_dnodes_for_area(area *a);
+void reapweakv(LispObj weakv);
+void reaphashv(LispObj hashv);
+Boolean mark_weak_hash_vector(hash_table_vector_header *hashp, natural elements);
+Boolean mark_weak_alist(LispObj weak_alist, int weak_type);
+void mark_tcr_tlb(TCR *);
+void mark_tcr_xframes(TCR *);
+void freeGCptrs(void);
+void reap_gcable_ptrs(void);
+unsigned short logcount16(unsigned short);
+void gc_init(void);
+LispObj node_forwarding_address(LispObj);
+Boolean update_noderef(LispObj *);
+void update_locref(LispObj *);
+void forward_gcable_ptrs(void);
+void forward_memoized_area(area *, natural);
+void forward_tcr_tlb(TCR *);
+void reclaim_static_dnodes(void);
+Boolean youngest_non_null_area_p(area *);
+void gc(TCR *, signed_natural);
+
+/* backend-interface */
+
+typedef void (*weak_mark_fun) (LispObj);
+weak_mark_fun mark_weak_htabv, dws_mark_weak_htabv;
+
+typedef void (*weak_process_fun)(void);
+
+weak_process_fun markhtabvs;
+
+
+#define hash_table_vector_header_count (sizeof(hash_table_vector_header)/sizeof(LispObj))
+
+void mark_root(LispObj);
+void rmark(LispObj);
+#ifdef X8632
+void mark_xp(ExceptionInformation *, natural);
+#else
+void mark_xp(ExceptionInformation *);
+#endif
+LispObj dnode_forwarding_address(natural, int);
+LispObj locative_forwarding_address(LispObj);
+void check_refmap_consistency(LispObj *, LispObj *, bitvector);
+void check_all_areas(TCR *);
+void mark_tstack_area(area *);
+void mark_vstack_area(area *);
+void mark_cstack_area(area *);
+void mark_simple_area_range(LispObj *, LispObj *);
+void mark_memoized_area(area *, natural);
+LispObj calculate_relocation(void);
+void forward_range(LispObj *, LispObj *);
+void forward_tstack_area(area *);
+void forward_vstack_area(area *);
+void forward_cstack_area(area *);
+LispObj compact_dynamic_heap(void);
+signed_natural purify(TCR *, signed_natural);
+signed_natural impurify(TCR *, signed_natural);
+signed_natural gc_like_from_xp(ExceptionInformation *, signed_natural(*fun)(TCR *, signed_natural), signed_natural);
+
+
+typedef enum {
+  xmacptr_flag_none = 0,        /* Maybe already disposed by Lisp */
+  xmacptr_flag_recursive_lock,  /* recursive-lock */
+  xmacptr_flag_ptr,             /* malloc/free */
+  xmacptr_flag_rwlock,          /* read/write lock */
+  xmacptr_flag_semaphore,        /* semaphore */
+  xmacptr_flag_user_first = 8,  /* first user-defined dispose fn */
+  xmacptr_flag_user_last = 16   /* exclusive upper bound */
+} xmacptr_flag;
+
+
+typedef void (*xmacptr_dispose_fn)(void *);
+
+extern xmacptr_dispose_fn xmacptr_dispose_functions[];
+
+extern bitvector global_mark_ref_bits, dynamic_mark_ref_bits, relocatable_mark_ref_bits;
+
+
+#endif                          /* __GC_H__ */
Index: /branches/new-random/lisp-kernel/image.c
===================================================================
--- /branches/new-random/lisp-kernel/image.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/image.c	(revision 13309)
@@ -0,0 +1,619 @@
+/*
+   Copyright (C) 2002-2009 Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp_globals.h"
+#include "area.h"
+#include "image.h"
+#include "gc.h"
+#include <errno.h>
+#include <unistd.h>
+#ifndef WINDOWS
+#include <sys/mman.h>
+#endif
+#include <stdio.h>
+#include <limits.h>
+
+
+
+#if defined(PPC64) || defined(X8632)
+#define RELOCATABLE_FULLTAG_MASK \
+  ((1<<fulltag_cons)|(1<<fulltag_misc))
+#else
+#ifdef X8664
+#define RELOCATABLE_FULLTAG_MASK \
+  ((1<<fulltag_cons)|(1<<fulltag_misc)|(1<<fulltag_symbol)|(1<<fulltag_function))
+#else
+#define RELOCATABLE_FULLTAG_MASK \
+  ((1<<fulltag_cons)|(1<<fulltag_nil)|(1<<fulltag_misc))
+#endif
+#endif
+
+void
+relocate_area_contents(area *a, LispObj bias)
+{
+  LispObj 
+    *start = (LispObj *)(a->low), 
+    *end = (LispObj *)(a->active),
+    low = (LispObj)image_base - bias,
+    high = ptr_to_lispobj(active_dynamic_area->active) - bias,
+    w0;
+  int fulltag;
+
+  while (start < end) {
+    w0 = *start;
+    fulltag = fulltag_of(w0);
+    if (immheader_tag_p(fulltag)) {
+      start = (LispObj *)skip_over_ivector((natural)start, w0);
+    } else {
+#ifdef X86
+      if (header_subtag(w0) == subtag_function) {
+#ifdef X8664
+        int skip = ((int) start[1])+1;
+#else
+        extern void update_self_references(LispObj *);
+        extern natural imm_word_count(LispObj);
+
+        natural skip = (natural)imm_word_count(((LispObj)start)+fulltag_misc)+1;
+        update_self_references(start);
+#endif
+     
+        start += skip;
+        if (((LispObj) start) & node_size) {
+          --start;
+        }
+        w0 = *start;
+        fulltag = fulltag_of(w0);
+      }
+#endif
+
+      if ((w0 >= low) && (w0 < high) &&
+	  ((1<<fulltag) & RELOCATABLE_FULLTAG_MASK)) {
+	*start = (w0+bias);
+      }
+      w0 = *++start;
+      fulltag = fulltag_of(w0);
+      if ((w0 >= low) && (w0 < high) &&
+	  ((1<<fulltag) & RELOCATABLE_FULLTAG_MASK)) {
+	*start = (w0+bias);
+      }
+      ++start;
+    }
+  }
+  if (start > end) {
+    Bug(NULL, "Overran area bounds in relocate_area_contents");
+  }
+}
+      
+
+
+
+off_t
+seek_to_next_page(int fd)
+{
+  off_t pos = LSEEK(fd, 0, SEEK_CUR);
+  pos = align_to_power_of_2(pos, log2_page_size);
+  return LSEEK(fd, pos, SEEK_SET);
+}
+  
+/*
+  fd is positioned to EOF; header has been allocated by caller.
+  If we find a trailer (and that leads us to the header), read
+  the header & return true else return false.
+*/
+Boolean
+find_openmcl_image_file_header(int fd, openmcl_image_file_header *header)
+{
+  openmcl_image_file_trailer trailer;
+  int disp;
+  off_t pos;
+  unsigned version, flags;
+
+  pos = LSEEK(fd, 0, SEEK_END);
+  if (pos < 0) {
+    return false;
+  }
+  pos -= sizeof(trailer);
+
+  if (LSEEK(fd, pos, SEEK_SET) < 0) {
+    return false;
+  }
+  if (read(fd, &trailer, sizeof(trailer)) != sizeof(trailer)) {
+    return false;
+  }
+  if ((trailer.sig0 != IMAGE_SIG0) ||
+      (trailer.sig1 != IMAGE_SIG1) ||
+      (trailer.sig2 != IMAGE_SIG2)) {
+    return false;
+  }
+  disp = trailer.delta;
+  
+  if (disp >= 0) {
+    return false;
+  }
+  if (LSEEK(fd, disp, SEEK_CUR) < 0) {
+    return false;
+  }
+  if (read(fd, header, sizeof(openmcl_image_file_header)) !=
+      sizeof(openmcl_image_file_header)) {
+    return false;
+  }
+  if ((header->sig0 != IMAGE_SIG0) ||
+      (header->sig1 != IMAGE_SIG1) ||
+      (header->sig2 != IMAGE_SIG2) ||
+      (header->sig3 != IMAGE_SIG3)) {
+    return false;
+  }
+  version = (header->abi_version) & 0xffff;
+  if (version < ABI_VERSION_MIN) {
+    fprintf(dbgout, "Heap image is too old for this kernel.\n");
+    return false;
+  }
+  if (version > ABI_VERSION_MAX) {
+    fprintf(dbgout, "Heap image is too new for this kernel.\n");
+    return false;
+  }
+  flags = header->flags;
+  if (flags != PLATFORM) {
+    fprintf(dbgout, "Heap image was saved for another platform.\n");
+    return false;
+  }
+  return true;
+}
+
+void
+load_image_section(int fd, openmcl_image_section_header *sect)
+{
+  extern area* allocate_dynamic_area(unsigned);
+  off_t
+    pos = seek_to_next_page(fd), advance;
+  natural
+    mem_size = sect->memory_size;
+  void *addr;
+  area *a;
+
+  advance = mem_size;
+  switch(sect->code) {
+  case AREA_READONLY:
+    if (!MapFile(pure_space_active,
+		 pos,
+		 align_to_power_of_2(mem_size,log2_page_size),
+		 MEMPROTECT_RX,
+		 fd)) {
+      return;
+    }
+    a = new_area(pure_space_active, pure_space_limit, AREA_READONLY);
+    pure_space_active += mem_size;
+    a->active = pure_space_active;
+    sect->area = a;      
+    break;
+
+  case AREA_STATIC:
+    if (!MapFile(static_space_active,
+		 pos,
+		 align_to_power_of_2(mem_size,log2_page_size),
+		 MEMPROTECT_RWX,
+		 fd)) {
+      return;
+    }
+    a = new_area(static_space_active, static_space_limit, AREA_STATIC);
+    static_space_active += mem_size;
+    a->active = static_space_active;
+    sect->area = a;
+    break;
+
+  case AREA_DYNAMIC:
+    a = allocate_dynamic_area(mem_size);
+    if (!MapFile(a->low,
+		 pos,
+		 align_to_power_of_2(mem_size,log2_page_size),
+		 MEMPROTECT_RWX,
+		 fd)) {
+      return;
+    }
+
+    a->static_dnodes = sect->static_dnodes;
+    sect->area = a;
+    break;
+
+  case AREA_MANAGED_STATIC:
+    a = new_area(pure_space_limit, pure_space_limit+align_to_power_of_2(mem_size,log2_page_size), AREA_MANAGED_STATIC);
+    a->active = a->low+mem_size;
+    if (mem_size) {
+      natural
+        refbits_size = align_to_power_of_2((((mem_size>>dnode_shift)+7)>>3),
+                                           log2_page_size);
+      if (!MapFile(a->low,
+                   pos,
+                   align_to_power_of_2(mem_size,log2_page_size),
+                   MEMPROTECT_RWX,
+                   fd)) {
+        return;
+      }
+      /* Need to save/restore persistent refbits. */
+      if (!MapFile(global_mark_ref_bits,
+                   align_to_power_of_2(pos+mem_size,log2_page_size),
+                   refbits_size,
+                   MEMPROTECT_RW,
+                   fd)) {
+        return;
+      }
+      advance += refbits_size;
+    }
+    sect->area = a;
+    a->ndnodes = area_dnode(a->active, a->low);
+    managed_static_area = a;
+    lisp_global(REF_BASE) = (LispObj) a->low;
+    break;
+
+    /* In many respects, the static_cons_area is part of the dynamic
+       area; it's physically adjacent to it (immediately precedes the
+       dynamic area in memory) and its contents are subject to full
+       GC (but not compaction.)  It's maintained as a seperate section
+       in the image file, at least for now. */
+
+
+  case AREA_STATIC_CONS:
+    addr = (void *) lisp_global(HEAP_START);
+    a = new_area(addr-align_to_power_of_2(mem_size,log2_page_size), addr, AREA_STATIC_CONS);
+    if (mem_size) {      
+      if (!MapFile(a->low,
+                   pos,
+                   align_to_power_of_2(mem_size,log2_page_size),
+                   MEMPROTECT_RWX,
+                   fd)) {
+        return;
+      }
+    }
+    a->ndnodes = area_dnode(a->active, a->low);
+    sect->area = a;
+    static_cons_area = a;
+    break;
+
+  default:
+    return;
+    
+  }
+  LSEEK(fd, pos+advance, SEEK_SET);
+}
+
+LispObj
+load_openmcl_image(int fd, openmcl_image_file_header *h)
+{
+  LispObj image_nil = 0;
+  area *a;
+  if (find_openmcl_image_file_header(fd, h)) {
+    int i, nsections = h->nsections;
+    openmcl_image_section_header sections[nsections], *sect=sections;
+    LispObj bias = image_base - ACTUAL_IMAGE_BASE(h);
+#if (WORD_SIZE== 64)
+    signed_natural section_data_delta = 
+      ((signed_natural)(h->section_data_offset_high) << 32L) | h->section_data_offset_low;
+#endif
+
+    if (read (fd, sections, nsections*sizeof(openmcl_image_section_header)) !=
+	nsections * sizeof(openmcl_image_section_header)) {
+      return 0;
+    }
+#if WORD_SIZE == 64
+    LSEEK(fd, section_data_delta, SEEK_CUR);
+#endif
+    for (i = 0; i < nsections; i++, sect++) {
+      load_image_section(fd, sect);
+      a = sect->area;
+      if (a == NULL) {
+	return 0;
+      }
+    }
+
+    for (i = 0, sect = sections; i < nsections; i++, sect++) {
+      a = sect->area;
+      switch(sect->code) {
+      case AREA_STATIC:
+	nilreg_area = a;
+#ifdef PPC
+#ifdef PPC64
+        image_nil = ptr_to_lispobj(a->low + (1024*4) + sizeof(lispsymbol) + fulltag_misc);
+#else
+	image_nil = (LispObj)(a->low + 8 + 8 + (1024*4) + fulltag_nil);
+#endif
+#endif
+#ifdef X86
+#ifdef X8664
+	image_nil = (LispObj)(a->low) + (1024*4) + fulltag_nil;
+#else
+	image_nil = (LispObj)(a->low) + (1024*4) + fulltag_cons;
+#endif
+#endif
+	set_nil(image_nil);
+	if (bias) {
+	  relocate_area_contents(a, bias);
+	}
+	make_dynamic_heap_executable(a->low, a->active);
+        add_area_holding_area_lock(a);
+        break;
+        
+      case AREA_READONLY:
+        if (bias && 
+            (managed_static_area->active != managed_static_area->low)) {
+          UnProtectMemory(a->low, a->active-a->low);
+          relocate_area_contents(a, bias);
+          ProtectMemory(a->low, a->active-a->low);
+        }
+        readonly_area = a;
+	add_area_holding_area_lock(a);
+	break;
+      }
+    }
+    for (i = 0, sect = sections; i < nsections; i++, sect++) {
+      a = sect->area;
+      switch(sect->code) {
+      case AREA_MANAGED_STATIC:
+        if (bias) {
+          relocate_area_contents(a, bias);
+        }
+        add_area_holding_area_lock(a);
+        break;
+      case AREA_STATIC_CONS:
+        break;
+      case AREA_DYNAMIC:
+        lower_heap_start(static_cons_area->low,a);
+        if (bias) {
+          relocate_area_contents(a, bias);
+        }
+	resize_dynamic_heap(a->active, lisp_heap_gc_threshold);
+	xMakeDataExecutable(a->low, a->active - a->low);
+	break;
+      }
+    }
+  }
+  return image_nil;
+}
+ 
+void
+prepare_to_write_dynamic_space()
+{
+  area *a = active_dynamic_area;
+  LispObj 
+    *start = (LispObj *)(a->low),
+    *end = (LispObj *) (a->active),
+    x1;
+  int tag, subtag, element_count;
+
+  while (start < end) {
+    x1 = *start;
+    tag = fulltag_of(x1);
+    if (immheader_tag_p(tag)) {
+      subtag = header_subtag(x1);
+      if (subtag == subtag_macptr) {
+        if ((start[1] >= (natural)0x10000) && (start[1] < (natural)-0x10000)) {
+          /* Leave small pointers alone */
+          *start = make_header(subtag_dead_macptr,header_element_count(x1));
+        }
+      }
+      start = (LispObj *)skip_over_ivector((natural)start, x1);
+    } else if (nodeheader_tag_p(tag)) {
+      element_count = header_element_count(x1) | 1;
+      start += (element_count+1);
+    } else {
+      start += 2;
+    }
+  }
+}
+
+  
+
+int
+write_file_and_section_headers(int fd, 
+                               openmcl_image_file_header *file_header,
+                               openmcl_image_section_header* section_headers,
+                               int nsections,
+                               off_t *header_pos)
+{
+  *header_pos = seek_to_next_page(fd);
+
+  if (LSEEK (fd, *header_pos, SEEK_SET) < 0) {
+    return errno;
+  }
+  if (write(fd, file_header, sizeof(*file_header)) != sizeof(*file_header)) {
+    return errno;
+  }
+  if (write(fd, section_headers, sizeof(section_headers[0])*nsections)
+      != (sizeof(section_headers[0])*nsections)) {
+    return errno;
+  }
+  return 0;
+}
+  
+natural
+writebuf(int fd, char *bytes, natural n)
+{
+  natural remain = n, this_size;
+  signed_natural result;
+
+  while (remain) {
+    this_size = remain;
+    if (this_size > INT_MAX) {
+      this_size = INT_MAX;
+    }
+    result = write(fd, bytes, this_size);
+    if (result < 0) {
+      return errno;
+    }
+    bytes += result;
+
+    remain -= result;
+  }
+  return 0;
+}
+
+OSErr
+save_application(unsigned fd, Boolean egc_was_enabled)
+{
+  openmcl_image_file_header fh;
+  openmcl_image_section_header sections[NUM_IMAGE_SECTIONS];
+  openmcl_image_file_trailer trailer;
+  area *areas[NUM_IMAGE_SECTIONS], *a;
+  int i, err;
+  off_t header_pos, eof_pos;
+#if WORD_SIZE == 64
+  off_t image_data_pos;
+  signed_natural section_data_delta;
+#endif
+
+  /*
+    Coerce macptrs to dead_macptrs.
+  */
+  
+  prepare_to_write_dynamic_space(active_dynamic_area);
+
+  /* 
+     If we ever support continuing after saving an image,
+     undo this .. */
+
+  if (static_cons_area->high > static_cons_area->low) {
+    active_dynamic_area->low = static_cons_area->high;
+    tenured_area->static_dnodes -= area_dnode(static_cons_area->high, static_cons_area->low);
+  }
+
+  areas[0] = nilreg_area; 
+  areas[1] = readonly_area;
+  areas[2] = active_dynamic_area;
+  areas[3] = managed_static_area;
+  areas[4] = static_cons_area;
+  for (i = 0; i < NUM_IMAGE_SECTIONS; i++) {
+    a = areas[i];
+    sections[i].code = a->code;
+    sections[i].area = NULL;
+    sections[i].memory_size  = a->active - a->low;
+    if (a == active_dynamic_area) {
+      sections[i].static_dnodes = tenured_area->static_dnodes;
+    } else {
+      sections[i].static_dnodes = 0;
+    }
+  }
+  fh.sig0 = IMAGE_SIG0;
+  fh.sig1 = IMAGE_SIG1;
+  fh.sig2 = IMAGE_SIG2;
+  fh.sig3 = IMAGE_SIG3;
+  fh.timestamp = time(NULL);
+  CANONICAL_IMAGE_BASE(&fh) = IMAGE_BASE_ADDRESS;
+  ACTUAL_IMAGE_BASE(&fh) = image_base;
+  fh.nsections = NUM_IMAGE_SECTIONS;
+  fh.abi_version=ABI_VERSION_CURRENT;
+#if WORD_SIZE == 64
+  fh.section_data_offset_high = 0;
+  fh.section_data_offset_low = 0;
+#else
+  fh.pad0[0] = fh.pad0[1] = 0;
+  fh.pad1[0] = fh.pad1[1] = fh.pad1[2] = fh.pad1[3] = 0;
+#endif
+  fh.flags = PLATFORM;
+
+#if WORD_SIZE == 64
+  image_data_pos = seek_to_next_page(fd);
+#else
+  err = write_file_and_section_headers(fd, &fh, sections, NUM_IMAGE_SECTIONS, &header_pos);
+  if (err) {
+    return err;
+  }
+#endif
+
+
+  {
+    area *g0_area = g1_area->younger;
+
+    /* Save GC config */
+    lisp_global(LISP_HEAP_THRESHOLD) = lisp_heap_gc_threshold;
+    lisp_global(G0_THRESHOLD) = g0_area->threshold;
+    lisp_global(G1_THRESHOLD) = g1_area->threshold;
+    lisp_global(G2_THRESHOLD) = g2_area->threshold;
+    lisp_global(EGC_ENABLED) = (LispObj)egc_was_enabled;
+  }
+  /*
+    lisp_global(GC_NUM) and lisp_global(FWDNUM) are persistent,
+    as is DELETED_STATIC_PAIRS.
+    Nothing else is even meaningful at this point.
+  */
+  for (i = MIN_KERNEL_GLOBAL; i < 0; i++) {
+    switch (i) {
+    case FREE_STATIC_CONSES:
+    case FWDNUM:
+    case GC_NUM:
+    case STATIC_CONSES:
+    case WEAK_GC_METHOD:
+    case LISP_HEAP_THRESHOLD:
+    case EGC_ENABLED:
+    case G0_THRESHOLD:
+    case G1_THRESHOLD:
+    case G2_THRESHOLD:
+      break;
+    default:
+      lisp_global(i) = 0;
+    }
+  }
+
+  for (i = 0; i < NUM_IMAGE_SECTIONS; i++) {
+    natural n;
+    a = areas[i];
+    seek_to_next_page(fd);
+    n = sections[i].memory_size;
+    if (writebuf(fd, a->low, n)) {
+	return errno;
+    }
+    if (n &&  ((sections[i].code) == AREA_MANAGED_STATIC)) {
+      natural ndnodes = area_dnode(a->active, a->low);
+      natural nrefbytes = align_to_power_of_2((ndnodes+7)>>3,log2_page_size);
+
+      seek_to_next_page(fd);
+      if (writebuf(fd,(char*)a->refbits,nrefbytes)) {
+        return errno;
+      }
+    }
+  }
+
+#if WORD_SIZE == 64
+  seek_to_next_page(fd);
+  section_data_delta = -((LSEEK(fd,0,SEEK_CUR)+sizeof(fh)+sizeof(sections)) -
+                         image_data_pos);
+  fh.section_data_offset_high = (int)(section_data_delta>>32L);
+  fh.section_data_offset_low = (unsigned)section_data_delta;
+  err =  write_file_and_section_headers(fd, &fh, sections, NUM_IMAGE_SECTIONS, &header_pos);
+  if (err) {
+    return err;
+  }  
+#endif
+
+  trailer.sig0 = IMAGE_SIG0;
+  trailer.sig1 = IMAGE_SIG1;
+  trailer.sig2 = IMAGE_SIG2;
+  eof_pos = LSEEK(fd, 0, SEEK_CUR) + sizeof(trailer);
+  trailer.delta = (int) (header_pos-eof_pos);
+  if (write(fd, &trailer, sizeof(trailer)) == sizeof(trailer)) {
+#ifndef WINDOWS
+    fsync(fd);
+#endif
+    close(fd);
+    return 0;
+  } 
+  i = errno;
+  close(fd);
+  return i;
+}
+      
+
+
+
Index: /branches/new-random/lisp-kernel/image.h
===================================================================
--- /branches/new-random/lisp-kernel/image.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/image.h	(revision 13309)
@@ -0,0 +1,96 @@
+/*
+   Copyright (C) 2002-2009 Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+
+#define IMAGE_SIG0 (('O'<<24) | ('p'<<16) | ('e'<<8) | 'n')
+#define IMAGE_SIG1 (('M'<<24) | ('C'<<16) | ('L'<<8) | 'I')
+#define IMAGE_SIG2 (('m'<<24) | ('a'<<16) | ('g'<<8) | 'e')
+#define IMAGE_SIG3 (('F'<<24) | ('i'<<16) | ('l'<<8) | 'e')
+
+/* 
+   An image file contains a header (which describes the type, size,
+   and nominal memory address of one or more sections) and data for
+   each section; each section's data is page-aligned within the image
+   file, so its disk address is implicit.  The header must reside
+   entirely within a page; the first section's data starts on the page
+   after the image header, and subsequent sections start on the pages
+   after the page which contains the last byte of their predecessor's
+   data.
+
+   The image header's position relative to the start of the file is
+   arbitrary.  The image header's position relative to the end of the
+   file is indicated by the last word in the file (which is preceded
+   by the first three signature words above.)  The last word contains
+   the distance from the end-of-file to the start of the header.
+
+   As long as these alignment constraints are met, the image file can
+   have arbitrary data (or executable programs, or shell scripts)
+   prepended to it.  This is supposed to simplify distribution.
+*/
+
+typedef struct {
+  natural code;
+  area *area;
+  natural memory_size;
+  natural static_dnodes;
+} openmcl_image_section_header;
+
+typedef struct {
+  unsigned sig0, sig1, sig2, sig3;
+  unsigned timestamp;
+  unsigned canonical_image_base_32; /* IMAGE_BASE_ADDRESS */
+  unsigned actual_image_base_32;	/* Hopefully the same */
+  unsigned nsections;
+  unsigned abi_version;
+#if WORD_SIZE == 64
+  int section_data_offset_high; /* signed offset from end of
+                                         section headers to first
+                                         section's data.  May be zero. */
+  unsigned section_data_offset_low;
+  unsigned flags; 
+  natural canonical_image_base_64;
+  natural actual_image_base_64;
+#else 
+  unsigned pad0[2]; 
+  unsigned flags;
+  unsigned pad1[4];
+#endif
+} openmcl_image_file_header;
+
+#if WORD_SIZE == 64
+#define ACTUAL_IMAGE_BASE(header) ((header)->actual_image_base_64)
+#define CANONICAL_IMAGE_BASE(header) ((header)->canonical_image_base_64)
+#else
+#define ACTUAL_IMAGE_BASE(header) ((header)->actual_image_base_32)
+#define CANONICAL_IMAGE_BASE(header) ((header)->canonical_image_base_32)
+#endif
+
+typedef struct {
+  unsigned sig0, sig1, sig2;
+  int delta;
+} openmcl_image_file_trailer;
+
+LispObj
+load_openmcl_image(int, openmcl_image_file_header*);
+
+
+
+
+#define ABI_VERSION_MIN 1036
+#define ABI_VERSION_CURRENT 1036
+#define ABI_VERSION_MAX 1036
+
+#define NUM_IMAGE_SECTIONS 5    /* used to be 3 */
Index: /branches/new-random/lisp-kernel/imports.s
===================================================================
--- /branches/new-random/lisp-kernel/imports.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/imports.s	(revision 13309)
@@ -0,0 +1,120 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL. */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence. */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+	include(m4macros.m4)
+define([PTR],[
+        __ifdef([PPC64])
+        .quad $1
+        __else
+	 __ifdef([X8664])
+	 .quad $1
+	 __else
+	  .long $1
+	 __endif
+        __endif
+])
+	_beginfile
+
+        	
+	.globl C(import_ptrs_base)
+define([defimport],[
+	.globl C($1)
+        PTR(C($1))
+                
+# __line__
+])
+	.data
+import_ptrs_start:
+
+	defimport(fd_setsize_bytes)
+	defimport(do_fd_set)
+	defimport(do_fd_clr)
+	defimport(do_fd_is_set)
+	defimport(do_fd_zero)
+	defimport(xMakeDataExecutable)
+	defimport(xGetSharedLibrary)
+	defimport(xFindSymbol)
+	defimport(allocate)
+	defimport(deallocate)
+	defimport(jvm_init)
+	defimport(tcr_frame_ptr)
+	defimport(register_xmacptr_dispose_function)
+	defimport(open_debug_output)
+	defimport(get_r_debug)
+	defimport(restore_soft_stack_limit)
+	defimport(lisp_egc_control)
+	defimport(lisp_bug)
+	defimport(xNewThread)
+	defimport(cooperative_thread_startup)
+	defimport(xDisposeThread)
+	defimport(xThreadCurrentStackSpace)
+	defimport(usage_exit)
+	defimport(save_fp_context)
+	defimport(restore_fp_context)
+	defimport(put_vector_registers)
+	defimport(get_vector_registers)
+        defimport(new_semaphore)
+	defimport(wait_on_semaphore)
+	defimport(signal_semaphore)
+        defimport(destroy_semaphore)
+        defimport(new_recursive_lock)
+        defimport(lock_recursive_lock)
+        defimport(unlock_recursive_lock)
+        defimport(destroy_recursive_lock)
+        defimport(lisp_suspend_other_threads)
+        defimport(lisp_resume_other_threads)
+        defimport(lisp_suspend_tcr)
+        defimport(lisp_resume_tcr)
+        defimport(rwlock_new)
+        defimport(rwlock_destroy)
+        defimport(rwlock_rlock)
+        defimport(rwlock_wlock)
+        defimport(rwlock_unlock)
+        defimport(recursive_lock_trylock)
+	defimport(foreign_name_and_offset)
+        defimport(lisp_read)
+        defimport(lisp_write)
+        defimport(lisp_open)
+        defimport(lisp_fchmod)
+        defimport(lisp_lseek)
+        defimport(lisp_close)
+        defimport(lisp_ftruncate)
+        defimport(lisp_stat)
+        defimport(lisp_fstat)
+        defimport(lisp_futex)
+        defimport(lisp_opendir)
+        defimport(lisp_readdir)
+        defimport(lisp_closedir)
+        defimport(lisp_pipe)
+        defimport(lisp_gettimeofday)
+        defimport(lisp_sigexit)
+   
+        .globl C(import_ptrs_base)
+C(import_ptrs_base):
+	PTR(import_ptrs_start)
+
+	__ifdef([PPC])
+        __ifdef([LINUX])
+        __ifndef([PPC64])
+        .globl __trampoline_setup
+	.long  __trampoline_setup
+        __endif
+        __endif
+	__endif
+
+
+
+
+	_endfile
Index: /branches/new-random/lisp-kernel/kernel-globals.h
===================================================================
--- /branches/new-random/lisp-kernel/kernel-globals.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/kernel-globals.h	(revision 13309)
@@ -0,0 +1,33 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __kernel_globals__
+#define __kernel_globals__
+#include "area.h"
+
+
+extern area *nilreg_area, *tenured_area, *g2_area, *g1_area, *managed_static_area, *readonly_area, *static_cons_area;
+extern area *all_areas;
+extern int cache_block_size;
+
+
+
+
+
+
+
+#endif /* __kernel_globals__ */
Index: /branches/new-random/lisp-kernel/linuxppc/.cvsignore
===================================================================
--- /branches/new-random/lisp-kernel/linuxppc/.cvsignore	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxppc/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/lisp-kernel/linuxppc/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/linuxppc/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxppc/.gdbinit	(revision 13309)
@@ -0,0 +1,120 @@
+directory lisp-kernel
+
+define header32
+x/x $arg0-6
+end
+
+define header64
+x/x $arg0-12
+end
+
+define lisp_string32
+x/s ($arg0-2)
+end
+
+define lisp_string64
+x/s (($arg0)-4)
+end
+
+define pname32
+lisp_string32 (*($arg0-2))
+end
+
+# GDB's expression parser seems to have difficulty
+# with this unless the temporary is used.
+define pname64
+set $temp=*((long *)((long)($arg0-4)))
+lisp_string64 $temp
+end
+
+define ada 
+ p *all_areas->succ
+end
+
+define _TCR
+ p/x *(TCR *) $arg0
+end
+
+define tcr32
+ _TCR $r13
+end
+
+define tcr64
+ _TCR $r2
+end
+
+define regs32
+ p/x *(((struct pt_regs **)$arg0)[12])
+end
+
+define regs64
+ p/x * (((ExceptionInformation *)$arg0)->uc_mcontext.regs)
+end
+
+define xpGPR
+ p/x (((struct pt_regs **)$arg0)[12])->gpr[$arg1]
+end
+
+define xpPC
+ p/x ((ExceptionInformation *)$arg0)->uc_mcontext.regs->nip
+end
+
+define lisp_string
+ if $ppc64
+  lisp_string64 $arg0
+ else
+  lisp_string32 $arg0
+ end
+end
+
+define pname
+ if $ppc64
+  pname64 $arg0
+ else
+  pname32 $arg0
+ end
+end
+
+define tcr
+ if $ppc64
+  tcr64
+ else
+  tcr32
+ end
+end
+
+define regs
+ if $ppc64
+  regs64 $arg0
+ else
+  regs32 $arg0
+ end
+end
+
+define xpGPR
+ if $ppc64
+  xpGPR64 $arg0 $arg1
+ else
+  xpGPR32 $arg0 $arg1
+ end
+end
+
+define lisp
+ call print_lisp_object($arg0)
+end
+
+set $ppc64=0
+
+
+break Bug
+
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIG40 pass nostop noprint
+handle SIG41 pass nostop noprint
+handle SIG42 pass nostop noprint
+handle SIGPWR pass nostop noprint
+
+display/i $pc
Index: /branches/new-random/lisp-kernel/linuxppc/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/linuxppc/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxppc/Makefile	(revision 13309)
@@ -0,0 +1,107 @@
+#
+#   Copyright (C) 1994-2001 Digitool, Inc
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ../
+RM = /bin/rm
+# Versions of GNU as >= 2.9.1 all seem to work
+# AS = gas-2.9.1
+AS = as
+M4 = m4
+ASFLAGS = -mregnames -mppc32 -maltivec
+M4FLAGS = -DLINUX -DPPC
+CDEFINES = -DLINUX -DPPC -D_REENTRANT -D_GNU_SOURCE
+CDEBUG = -g
+COPT = -O2
+# Once in a while, -Wformat says something useful.  The odds are against that,
+# however.
+WFORMAT = -Wno-format
+
+# If the linker supports a "--hash-style=" option, use traditional
+# Sysv hash tables.  (If it doesn't support that option, assume
+# that traditional hash tables will be used by default.)
+ld_has_hash_style = $(shell $(LD) --help | grep "hash-style=")
+ifeq ($(ld_has_hash_style),)
+HASH_STYLE=
+else
+HASH_STYLE="-Wl,--hash-style=sysv"
+endif
+
+# The only version of GCC I have that supports both ppc32 and ppc64
+# compilation uses the -m32 option to target ppc32.  This may not be
+# definitive; there seem to be a bewildering array of similar options
+# in other GCC versions.  It's assumed here that if "-m32" is recognized,
+# it's required as well.
+
+PPC32 = $(shell ($(CC) --help -v 2>&1 | grep -q -e "-m32 ") && /bin/echo "-m32")
+
+# Likewise, some versions of GAS may need a "-a32" flag, to force the
+# output file to be 32-bit compatible.
+
+A32 = $(shell ($(AS) --help -v 2>&1 | grep -q -e "-a32") && /bin/echo "-a32")
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS) $(A32) $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) $(WFORMAT) $(PPC32) -o $@
+
+SPOBJ = pad.o ppc-spjump.o ppc-spentry.o ppc-subprims.o
+ASMOBJ = ppc-asmutils.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o ppc-gc.o bits.o  ppc-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o plbt.o ppc_print.o
+KERNELOBJ= $(COBJ) ppc-asmutils.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 ppc-constants.s ppc-macros.s errors.s ppc-uuo.s ppc-constants32.s
+
+CHEADERS = area.h bits.h ppc-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h ppc-constants32.h ppc-exceptions.h
+
+# Subprims linked into the kernel ?
+# Yes:
+
+KSPOBJ = $(SPOBJ)
+all:	../../ppccl
+
+
+# No:
+
+# KSPOBJ=
+# all:	../../ppccl ../../subprims.so
+
+OSLIBS = -ldl -lm -lpthread
+
+
+../../ppccl:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ)
+	$(CC) $(PPC32) $(CDEBUG)  -Wl,--export-dynamic $(HASH_STYLE) -o $@ -T ./elf32ppclinux.x $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../ppccl
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../ppccl
+	strip -g ../../ppccl
Index: /branches/new-random/lisp-kernel/linuxppc/elf32ppclinux.x
===================================================================
--- /branches/new-random/lisp-kernel/linuxppc/elf32ppclinux.x	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxppc/elf32ppclinux.x	(revision 13309)
@@ -0,0 +1,253 @@
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc",
+	      "elf32-powerpc")
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_start)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/powerpc-linux/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+VERSION {default { global : __trampoline_setup ;  } ;}
+SECTIONS
+{
+  PROVIDE (__executable_start = 0x00010000);
+  . = 0x00010000 + SIZEOF_HEADERS;
+  .pad : { pad.o(.text) }
+  .subprims ALIGN(0x1000)    :  
+  {
+   ppc-spjump.o(.text)
+   ppc-spentry.o(.text)   
+   ppc-subprims.o(.text)
+  }
+  /* Read-only sections, merged into text segment: */
+/*  . = 0x10000000; */
+  .interp     : { *(.interp) 	}
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .gnu.version   : { *(.gnu.version)	}
+  .gnu.version_d   : { *(.gnu.version_d)	}
+  .gnu.version_r   : { *(.gnu.version_r)	}
+  .rel.init      : { *(.rel.init)	}
+  .rela.init     : { *(.rela.init)	}
+  .rel.text      :
+    {
+      *(.rel.text)
+      *(.rel.text.*)
+      *(.rel.gnu.linkonce.t*)
+    }
+  .rela.text     :
+    {
+      *(.rela.text)
+      *(.rela.text.*)
+      *(.rela.gnu.linkonce.t*)
+    }
+  .rel.fini      : { *(.rel.fini)	}
+  .rela.fini     : { *(.rela.fini)	}
+  .rel.rodata    :
+    {
+      *(.rel.rodata)
+      *(.rel.rodata.*)
+      *(.rel.gnu.linkonce.r*)
+    }
+  .rela.rodata   :
+    {
+      *(.rela.rodata)
+      *(.rela.rodata.*)
+      *(.rela.gnu.linkonce.r*)
+    }
+  .rel.data      :
+    {
+      *(.rel.data)
+      *(.rel.data.*)
+      *(.rel.gnu.linkonce.d*)
+    }
+  .rela.data     :
+    {
+      *(.rela.data)
+      *(.rela.data.*)
+      *(.rela.gnu.linkonce.d*)
+    }
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.sdata     :
+    {
+      *(.rel.sdata)
+      *(.rel.sdata.*)
+      *(.rel.gnu.linkonce.s*)
+    }
+  .rela.sdata     :
+    {
+      *(.rela.sdata)
+      *(.rela.sdata.*)
+      *(.rela.gnu.linkonce.s*)
+    }
+  .rel.sbss      : { *(.rel.sbss)		}
+  .rela.sbss     : { *(.rela.sbss)	}
+  .rel.sdata2    : { *(.rel.sdata2)	}
+  .rela.sdata2   : { *(.rela.sdata2)	}
+  .rel.sbss2     : { *(.rel.sbss2)	}
+  .rela.sbss2    : { *(.rela.sbss2)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : 
+  { 
+    KEEP (*(.init))
+  } =0
+  .text      :
+  {
+    *(.text)
+    *(.text.*)
+    *(.stub)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    *(.gnu.linkonce.t*)
+  } =0
+  .fini      :
+  {
+    KEEP (*(.fini))
+  } =0
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata   : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r*) }
+  .rodata1   : { *(.rodata1) }
+  .sdata2   : { *(.sdata2) }
+  .sbss2   : { *(.sbss2) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN(0x10000) + (. & (0x10000 - 1));
+  /* Ensure the __preinit_array_start label is properly aligned.  We
+     could instead move the label definition inside the section, but
+     the linker would then create the section even if it turns out to
+     be empty, which isn't pretty.  */
+  . = ALIGN(32 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { *(.preinit_array) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { *(.init_array) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { *(.fini_array) }
+  PROVIDE (__fini_array_end = .);
+  .data    :
+  {
+    *(.data)
+    *(.data.*)
+    *(.gnu.linkonce.d*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1   : { *(.data1) }
+  .eh_frame : { *(.eh_frame) }
+  .gcc_except_table : { *(.gcc_except_table) }
+  .got1		: { *(.got1) }
+  .got2		: { *(.got2) }
+  .ctors   : 
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+   .dtors         :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .got		  : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : 
+  {
+    PROVIDE (_SDA_BASE_ = .);
+    *(.sdata) 
+    *(.sdata.*)
+    *(.gnu.linkonce.s.*)
+  }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .sbss      :
+  {
+    PROVIDE (__sbss_start = .);
+    PROVIDE (___sbss_start = .);
+    *(.dynsbss)
+    *(.sbss)
+    *(.sbss.*)
+    *(.scommon)
+    PROVIDE (__sbss_end = .);
+    PROVIDE (___sbss_end = .);
+  }
+  .plt      : { *(.plt)	}
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(.bss.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(32 / 8);
+  }
+  . = ALIGN(32 / 8);
+  _end = .;
+  PROVIDE (end = .);
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /DISCARD/	: { *(.fixup) }
+  /* These must appear regardless of  .  */
+}
Index: /branches/new-random/lisp-kernel/linuxppc64/.cvsignore
===================================================================
--- /branches/new-random/lisp-kernel/linuxppc64/.cvsignore	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxppc64/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/lisp-kernel/linuxppc64/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/linuxppc64/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxppc64/Makefile	(revision 13309)
@@ -0,0 +1,95 @@
+#
+#   Copyright (C) 1994-2001 Digitool, Inc
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ../
+RM = /bin/rm
+# Versions of GNU as >= 2.9.1 all seem to work
+# AS = gas-2.9.1
+AS = as
+M4 = m4
+ASFLAGS = -mregnames -mppc64 -a64 -maltivec
+M4FLAGS = -DLINUX -DPPC -DPPC64
+CDEFINES = -DLINUX -D_REENTRANT -DPPC -DPPC64 -D_GNU_SOURCE
+CDEBUG = -g
+COPT = -O2
+# word size issues are a little more relevant on a 64-bit platform
+# than elsewhere, but most gcc format warnings are still nonsense.
+WFORMAT = -Wno-format
+
+# If the linker supports a "--hash-style=" option, use traditional
+# Sysv hash tables.  (If it doesn't support that option, assume
+# that traditional hash tables will be used by default.)
+ld_has_hash_style = $(shell $(LD) --help | grep "hash-style=")
+ifeq ($(ld_has_hash_style),)
+HASH_STYLE=
+else
+HASH_STYLE="-Wl,--hash-style=sysv"
+endif
+
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) $(WFORMAT) -m64 -o $@
+
+SPOBJ = pad.o ppc-spjump.o ppc-spentry.o ppc-subprims.o
+ASMOBJ = ppc-asmutils.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o ppc-gc.o bits.o  ppc-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o plbt.o ppc_print.o
+KERNELOBJ= $(COBJ) ppc-asmutils.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 ppc-constants.s ppc-macros.s errors.s ppc-uuo.s ppc-constants64.s
+
+CHEADERS = area.h bits.h ppc-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h ppc-constants64.h ppc-exceptions.h
+
+# Subprims linked into the kernel ?
+# Yes:
+
+KSPOBJ = $(SPOBJ)
+all:	../../ppccl64
+
+
+# No:
+
+# KSPOBJ=
+# all:	../../ppccl64 ../../subprims.so
+
+OSLIBS = -ldl -lm -lpthread
+
+
+../../ppccl64:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ)
+	$(CC) -m64 $(CDEBUG)  -Wl,--export-dynamic $(HASH_STYLE)  -o $@ -T ./elf64ppc.x $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../ppccl64
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../ppccl64
+	strip -g ../../ppccl64
Index: /branches/new-random/lisp-kernel/linuxppc64/elf64ppc.x
===================================================================
--- /branches/new-random/lisp-kernel/linuxppc64/elf64ppc.x	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxppc64/elf64ppc.x	(revision 13309)
@@ -0,0 +1,229 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc",
+	      "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+ENTRY(_start)
+SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x00010000); . = 0x00010000 + SIZEOF_HEADERS;
+  .pad : { pad.o(.text) }
+  .subprims ALIGN(0x1000)    :  
+  {
+   ppc-spjump.o(.text)
+   ppc-spentry.o(.text)
+   ppc-subprims.o(.text)
+  }
+  .interp         : { *(.interp) }
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.dyn        :
+    {
+      *(.rel.init)
+      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+      *(.rel.fini)
+      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+      *(.rel.data.rel.ro*)
+      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+      *(.rel.ctors)
+      *(.rel.dtors)
+      *(.rel.got)
+      *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*)
+      *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*)
+      *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*)
+      *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*)
+      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+    }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.toc)
+      *(.rela.opd)
+      *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+      *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+      *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+      *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+    }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .rela.tocbss	  : { *(.rela.tocbss) }
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x60000000
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    KEEP (*(.text.*personality*))
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    *(.sfpr .glink)
+  } =0x60000000
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x60000000
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .sdata2         : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) }
+  .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000);
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  /* Ensure the __preinit_array_start label is properly aligned.  We
+     could instead move the label definition inside the section, but
+     the linker would then create the section even if it turns out to
+     be empty, which isn't pretty.  */
+  . = ALIGN(64 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { KEEP (*(.preinit_array)) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { KEEP (*(.init_array)) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { KEEP (*(.fini_array)) }
+  PROVIDE (__fini_array_end = .);
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin*.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin*.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) }
+  .dynamic        : { *(.dynamic) }
+/*  . = DATA_SEGMENT_RELRO_END (0, .); */
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    KEEP (*(.gnu.linkonce.d.*personality*))
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  .toc1		 ALIGN(8) : { *(.toc1) }
+  .opd		 ALIGN(8) : { KEEP (*(.opd)) }
+  .got		ALIGN(8) : { *(.got .toc) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata          :
+  {
+    *(.sdata .sdata.* .gnu.linkonce.s.*)
+  }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .tocbss	 ALIGN(8) : { *(.tocbss)}
+  .sbss           :
+  {
+    PROVIDE (__sbss_start = .);
+    PROVIDE (___sbss_start = .);
+    *(.dynsbss)
+    *(.sbss .sbss.* .gnu.linkonce.sb.*)
+    *(.scommon)
+    PROVIDE (__sbss_end = .);
+    PROVIDE (___sbss_end = .);
+  }
+  .plt            : { *(.plt) }
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(64 / 8);
+  }
+  . = ALIGN(64 / 8);
+  _end = .;
+  PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /DISCARD/ : { *(.note.GNU-stack) }
+}
Index: /branches/new-random/lisp-kernel/linuxx8632/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/linuxx8632/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxx8632/.gdbinit	(revision 13309)
@@ -0,0 +1,46 @@
+define pl
+  call print_lisp_object($arg0)
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x3001
+   set $car = *((LispObj *)($l+3))
+   set $l =  *((LispObj *)($l-1))
+   pl $car
+  end
+end
+
+
+define fn
+  pl $edi
+end
+
+define arg_y
+ pl $esi
+end
+
+define arg_z
+ pl $ebx
+end
+
+define offset
+ p (int)$pc-$edi
+end
+
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIG40 pass nostop noprint
+handle SIG41 pass nostop noprint
+handle SIG42 pass nostop noprint
+handle SIGPWR pass nostop noprint
+handle SIGQUIT pass nostop noprint
+
Index: /branches/new-random/lisp-kernel/linuxx8632/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/linuxx8632/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxx8632/Makefile	(revision 13309)
@@ -0,0 +1,85 @@
+#
+#   Copyright (C) 2008 Clozure Associates and contributors
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ../
+RM = /bin/rm
+AS = as
+M4 = m4
+ASFLAGS = --32
+M4FLAGS = -DLINUX -DX86 -DX8632 -DHAVE_TLS
+CDEFINES = -DLINUX -D_REENTRANT -DX86 -DX8632 -D_GNU_SOURCE -DHAVE_TLS -DUSE_FUTEX #-DGC_INTEGRITY_CHECKING -DDISABLE_EGC
+CDEBUG = -g
+COPT = -O2
+
+# If the linker supports a "--hash-style=" option, use traditional
+# SysV hash tables.  (If it doesn't support that option, assume
+# that traditional hash tables will be used by default.)
+ld_has_hash_style = $(shell $(LD) --help | grep "hash-style=")
+ifeq ($(ld_has_hash_style),)
+HASH_STYLE=
+else
+HASH_STYLE="-Wl,--hash-style=sysv"
+endif
+
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) -m32 -o $@
+
+SPOBJ = pad.o x86-spjump32.o x86-spentry32.o x86-subprims32.o
+ASMOBJ = x86-asmutils32.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils32.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants32.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants32.h x86-exceptions.h lisptypes.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	../../lx86cl
+
+
+OSLIBS = -ldl -lm -lpthread
+LINK_SCRIPT = # ./elf_x86_32.x
+USE_LINK_SCRIPT = # -T $(LINK_SCRIPT)
+
+../../lx86cl:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile  $(LINK_SCRIPT)
+	$(CC)  -m32 $(CDEBUG)  -Wl,--export-dynamic $(HASH_STYLE) -o $@ $(USE_LINK_SCRIPT) $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../lx86cl
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../lx86cl
+	strip -g ../../lx86cl
Index: /branches/new-random/lisp-kernel/linuxx8664/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/linuxx8664/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxx8664/.gdbinit	(revision 13309)
@@ -0,0 +1,83 @@
+define x86_lisp_string
+x/s $arg0-5
+end
+
+define gtra
+br *$r10
+cont
+end
+
+define x86pname
+set $temp=*((long *)((long)($arg0-6)))
+x86_lisp_string $temp
+end
+
+
+define pname
+ x86pname $arg0
+end
+
+define l
+ call print_lisp_object($arg0)
+end
+
+define lw
+ l $r13
+end
+
+define clobber_breakpoint
+  set *(short *)($pc-2)=0x9090
+end
+
+define arg_z
+ l $rsi
+end
+
+define arg_y
+ l $rdi
+end
+
+define arg_x
+ l $r8
+end
+
+define bx
+ l $rbx
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x200b
+   set $car = *((LispObj *)($l+5))
+   set $l =  *((LispObj *)($l-3))
+   l $car
+  end
+end
+
+define lbt
+ call plbt_sp($rbp)
+end
+
+define ada
+ p/x *(all_areas->succ)
+end
+
+define lregs
+ call debug_lisp_registers($arg0,0,0)
+end
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIG40 pass nostop noprint
+handle SIG41 pass nostop noprint
+handle SIG42 pass nostop noprint
+handle SIGPWR pass nostop noprint
+handle SIGQUIT pass nostop noprint
+
Index: /branches/new-random/lisp-kernel/linuxx8664/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/linuxx8664/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxx8664/Makefile	(revision 13309)
@@ -0,0 +1,85 @@
+#
+#   Copyright (C) 2005 Clozure Associates
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ../
+RM = /bin/rm
+AS = as
+M4 = m4
+ASFLAGS = --64
+M4FLAGS = -DLINUX -DX86 -DX8664 -DHAVE_TLS
+CDEFINES = -DLINUX -D_REENTRANT -DX86 -DX8664 -D_GNU_SOURCE -DHAVE_TLS -DUSE_FUTEX #-DDISABLE_EGC
+CDEBUG = -g
+COPT = -O2
+
+# If the linker supports a "--hash-style=" option, use traditional
+# SysV hash tables.  (If it doesn't support that option, assume
+# that traditional hash tables will be used by default.)
+ld_has_hash_style = $(shell $(LD) --help | grep "hash-style=")
+ifeq ($(ld_has_hash_style),)
+HASH_STYLE=
+else
+HASH_STYLE="-Wl,--hash-style=sysv"
+endif
+
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) -m64 -o $@
+
+SPOBJ = pad.o x86-spjump64.o x86-spentry64.o x86-subprims64.o
+ASMOBJ = x86-asmutils64.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils64.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants64.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants64.h x86-exceptions.h lisptypes.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	../../lx86cl64
+
+
+OSLIBS = -ldl -lm -lpthread
+LINK_MAP = ./elf_x86_64.x
+USE_LINK_MAP = # -T ./elf_x86_64.x
+
+../../lx86cl64:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile  $(LINK_MAP)
+	$(CC)  -m64 $(CDEBUG)  -Wl,--export-dynamic $(HASH_STYLE) -o $@ $(USE_LINK_MAP) $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../lx86cl64
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../lx86cl64
+	strip -g ../../lx86cl64
Index: /branches/new-random/lisp-kernel/linuxx8664/elf_x86_64.x
===================================================================
--- /branches/new-random/lisp-kernel/linuxx8664/elf_x86_64.x	(revision 13309)
+++ /branches/new-random/lisp-kernel/linuxx8664/elf_x86_64.x	(revision 13309)
@@ -0,0 +1,196 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SEARCH_DIR("/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/x86_64-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x400000); . = 0x400000 + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.dyn        :
+    {
+      *(.rel.init)
+      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+      *(.rel.fini)
+      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+      *(.rel.data.rel.ro*)
+      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+      *(.rel.ctors)
+      *(.rel.dtors)
+      *(.rel.got)
+      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+    }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+    }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x90909090
+  .plt            : { *(.plt) }
+  .subprims 0x410000:
+  {
+    x86-spjump64.o(.text)
+    x86-spentry64.o(.text)
+    x86-subprims64.o(.text)
+  }
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    KEEP (*(.text.*personality*))
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x90909090
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000);
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  /* Ensure the __preinit_array_start label is properly aligned.  We
+     could instead move the label definition inside the section, but
+     the linker would then create the section even if it turns out to
+     be empty, which isn't pretty.  */
+  . = ALIGN(64 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { KEEP (*(.preinit_array)) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { KEEP (*(.init_array)) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { KEEP (*(.fini_array)) }
+  PROVIDE (__fini_array_end = .);
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin*.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin*.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) }
+  . = DATA_SEGMENT_RELRO_END (24, .);
+  .got.plt        : { *(.got.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    KEEP (*(.gnu.linkonce.d.*personality*))
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(64 / 8);
+  }
+  . = ALIGN(64 / 8);
+  _end = .;
+  PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /DISCARD/ : { *(.note.GNU-stack) }
+}
+
Index: /branches/new-random/lisp-kernel/lisp-debug.c
===================================================================
--- /branches/new-random/lisp-kernel/lisp-debug.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/lisp-debug.c	(revision 13309)
@@ -0,0 +1,1256 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp-exceptions.h"
+#include "lisp_globals.h"
+#include "area.h"
+#include "Threads.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+
+#ifdef WINDOWS
+#include <fcntl.h>
+#else
+#include <sys/socket.h>
+#include <dlfcn.h>
+#endif
+#include <sys/stat.h>
+
+FILE *dbgout = NULL;
+
+typedef enum {
+  debug_continue,		/* stay in the repl */
+  debug_exit_success,		/* return 0 from lisp_Debugger */
+  debug_exit_fail,		/* return non-zero from lisp_Debugger */
+  debug_kill
+} debug_command_return;
+
+
+Boolean
+open_debug_output(int fd)
+{
+  FILE *f = fdopen(fd, "w");
+  
+  if (f) {
+    if (setvbuf(f, NULL, _IONBF, 0) == 0) {
+#ifdef WINDOWS
+      if (fileno(stdin) < 0) {
+        stdin->_file = 0;
+      }
+#endif
+      dbgout = f;
+      return true;
+    }
+    fclose(f);
+  }
+  return false;
+}
+
+
+typedef debug_command_return (*debug_command) (ExceptionInformation *,
+					       siginfo_t *,
+					       int);
+
+#define DEBUG_COMMAND_FLAG_REQUIRE_XP 1 /* function  */
+#define DEBUG_COMMAND_FLAG_AUX_REGNO  (2 | DEBUG_COMMAND_FLAG_REQUIRE_XP)
+#define DEBUG_COMMAND_FLAG_AUX_SPR (4 | DEBUG_COMMAND_FLAG_REQUIRE_XP)
+#define DEBUG_COMMAND_REG_FLAGS 7
+#define DEBUG_COMMAND_FLAG_EXCEPTION_ENTRY_ONLY 8
+#define DEBUG_COMMAND_FLAG_EXCEPTION_REASON_ARG 16
+
+typedef struct {
+  debug_command f;
+  char *help_text;
+  unsigned flags;
+  char *aux_prompt;
+  int c;
+} debug_command_entry;
+
+
+extern
+debug_command_entry debug_command_entries[];
+
+Boolean lisp_debugger_in_foreign_code = false;
+
+#ifndef WINDOWS
+Boolean
+stdin_is_dev_null()
+{
+  struct stat fd0stat, devnullstat;
+
+  if (fstat(fileno(stdin),&fd0stat)) {
+    return true;
+  }
+  if (stat("/dev/null",&devnullstat)) {
+    return true;
+  }
+  return ((fd0stat.st_ino == devnullstat.st_ino) &&
+          (fd0stat.st_dev == devnullstat.st_dev));
+}
+#endif
+
+#ifdef WINDOWS
+Boolean
+stdin_is_dev_null()
+{
+  HANDLE stdIn;
+  stdIn = GetStdHandle(STD_INPUT_HANDLE);
+  return (stdIn == NULL);
+}
+#endif
+
+
+
+
+char *
+foreign_name_and_offset(natural addr, int *delta)
+{
+#ifndef WINDOWS
+  Dl_info info;
+#endif
+  char *ret = NULL;
+
+  if (delta) {
+    *delta = 0;
+  }
+#ifndef WINDOWS
+  if (dladdr((void *)addr, &info)) {
+    ret = (char *)info.dli_sname;
+    if (delta) {
+      *delta = ((natural)addr - (natural)info.dli_saddr);
+    }
+  }
+#endif
+  return ret;
+}
+
+
+#if defined(LINUX) || defined(SOLARIS)
+#define fpurge __fpurge
+#endif
+
+#ifdef WINDOWS
+void
+fpurge (FILE* file)
+{
+}
+#endif
+
+int
+readc()
+{
+  unsigned tries = 1000;
+  int c;
+
+  while (tries) {
+    c = getchar();
+    switch(c) {
+    case '\n':
+      continue;
+    case '\r':
+      continue;
+    case EOF:
+      if (ferror(stdin)) {
+	if ((errno == EINTR) || (errno == EIO)) {
+	  clearerr(stdin);
+	  tries--;
+	  continue;
+	}
+      }
+      /* fall through */
+    default:
+      return c;
+    }
+  }
+  return EOF;
+}
+
+#ifdef X8664
+#ifdef LINUX
+char* Iregnames[] = {"r8 ","r9 ","r10","r11","r12","r13","r14","r15",
+		     "rdi","rsi","rbp", "rbx", "rdx", "rax", "rcx","rsp"};
+#endif
+#ifdef SOLARIS
+char* Iregnames[] = {"r15 ","r14 ","r13","r12","r11","r10","r9 ","r8 ",
+		     "rdi","rsi","rbp", "rbx", "rdx", "rcx", "rcx","rsp"};
+#endif
+#ifdef FREEBSD
+char* Iregnames[] = {"???", "rdi", "rsi", "rdx", "rcx", "r8 ", "r9 ", "rax",
+                     "rbx", "rbp", "r10", "r11", "r12", "r13", "r14", "r15",
+                     "???", "???", "???", "???", "???", "???", "???", "rsp"};
+#endif
+#ifdef DARWIN
+char* Iregnames[] = {"rax", "rbx", "rcx", "rdx", "rdi", "rsi",
+                     "rbp", "rsp", "r8 ", "r9 ", "r10", "r11", "r12", "r13",
+                     "r14", "r15", "rip", "rfl"};
+#endif
+#ifdef WINDOWS
+char* Iregnames[] = {"rax ","rcx ","rdx","rbx","rsp","rrbp","rsi","rdi",
+		     "r8","r9","r10", "r11", "r12", "r13", "r14","r15"};
+#endif
+#endif
+
+#ifdef X8632
+#ifdef DARWIN
+char *Iregnames[] = {"eax", "ebx", "ecx", "edx", "edi", "esi",
+		     "ebp", "???", "efl", "eip"};
+#endif
+#ifdef LINUX
+char *Iregnames[] = {"???", "???", "???", "???",
+                     "edi", "esi", "ebp", "esp",
+                     "ebx", "edx", "ecx", "eax",
+                     "???", "???", "eip", "???", "efl"};
+#endif
+#ifdef WINDOWS
+char *Iregnames[] = {"edi", "esi", "ebx", "edx", "ecx", "eax",
+                     "ebp", "eip", "???", "efl", "esp"};
+#endif
+#ifdef FREEBSD
+char *Iregnames[] = {"???", "???", "???", "???", "???"
+                     "edi", "esi", "ebp", "ebx", "edx", 
+		     "ecx", "eax", "???", "???", "eip",
+		     "???", "efl", "esp"};
+#endif
+#ifdef SOLARIS
+char *Iregnames[] = {"???", "???", "???", "???", "???",
+                     "edi", "esi", "ebp", "???", "ebx",
+                     "edx", "ecx", "eax", "???", "???",
+                     "eip", "???", "efl", "esp"};
+#endif
+#endif
+
+#ifdef X8632
+int bit_for_regnum(int r)
+{
+  switch (r) {
+  case REG_EAX: return 1<<0;
+  case REG_ECX: return 1<<1;
+  case REG_EDX: return 1<<2;
+  case REG_EBX: return 1<<3;
+  case REG_ESP: return 1<<4;
+  case REG_EBP: return 1<<5;
+  case REG_ESI: return 1<<6;
+  case REG_EDI: return 1<<7;
+  }
+}
+#endif
+
+void
+show_lisp_register(ExceptionInformation *xp, char *label, int r)
+{
+
+  extern char* print_lisp_object(LispObj);
+
+  LispObj val = xpGPR(xp, r);
+
+#ifdef PPC
+  fprintf(dbgout, "r%02d (%s) = %s\n", r, label, print_lisp_object(val));
+#endif
+#ifdef X8664
+  fprintf(dbgout, "%%%s (%s) = %s\n",Iregnames[r], label, print_lisp_object(val));
+#endif
+#ifdef X8632
+  {
+    TCR *tcr = get_tcr(false);
+    char *s;
+
+    if (r == REG_EDX && (xpGPR(xp, REG_EFL) & EFL_DF))
+      s = "marked as unboxed (DF set)";
+    else if (tcr && (tcr->node_regs_mask & bit_for_regnum(r)) == 0)
+      s = "marked as unboxed (node_regs_mask)";
+    else
+      s = print_lisp_object(val);
+
+    fprintf(dbgout, "%%%s (%s) = %s\n", Iregnames[r], label, s);
+  }
+#endif
+
+}
+
+
+void
+describe_memfault(ExceptionInformation *xp, siginfo_t *info)
+{
+#ifdef PPC
+  void *addr = (void *)xpDAR(xp);
+  natural dsisr = xpDSISR(xp);
+
+  fprintf(dbgout, "%s operation to %s address 0x%lx\n",
+	  dsisr & (1<<25) ? "Write" : "Read",
+	  dsisr & (1<<27) ? "protected" : "unmapped",
+	  addr);
+#endif
+}
+
+#ifdef PPC
+void
+describe_ppc_illegal(ExceptionInformation *xp)
+{
+  pc where = xpPC(xp);
+  opcode the_uuo = *where;
+  Boolean described = false;
+
+  if (IS_UUO(the_uuo)) {
+    unsigned 
+      minor = UUO_MINOR(the_uuo),
+      errnum = 0x3ff & (the_uuo >> 16);
+
+    switch(minor) {
+    case UUO_INTERR:
+      switch (errnum) {
+      case error_udf_call:
+        fprintf(dbgout, "ERROR: undefined function call: %s\n",
+                print_lisp_object(xpGPR(xp,fname)));
+        described = true;
+        break;
+        
+      default:
+        fprintf(dbgout, "ERROR: lisp error %d\n", errnum);
+        described = true;
+        break;
+      }
+      break;
+      
+    default:
+      break;
+    }
+  }
+  if (!described) {
+    fprintf(dbgout, "Illegal instruction (0x%08x) at 0x%lx\n",
+            the_uuo, where);
+  }
+}
+#endif
+
+#ifdef PPC
+void
+describe_ppc_trap(ExceptionInformation *xp)
+{
+  pc where = xpPC(xp);
+  opcode the_trap = *where, instr;
+  int err_arg2, ra, rs;
+  Boolean identified = false;
+
+  if ((the_trap & OP_MASK) == OP(major_opcode_TRI)) {
+    /* TWI/TDI.  If the RA field is "nargs", that means that the
+       instruction is either a number-of-args check or an
+       event-poll.  Otherwise, the trap is some sort of
+       typecheck. */
+
+    if (RA_field(the_trap) == nargs) {
+      switch (TO_field(the_trap)) {
+      case TO_NE:
+	if (xpGPR(xp, nargs) < D_field(the_trap)) {
+	  fprintf(dbgout, "Too few arguments (no opt/rest)\n");
+	} else {
+	  fprintf(dbgout, "Too many arguments (no opt/rest)\n");
+	}
+	identified = true;
+	break;
+	
+      case TO_GT:
+	fprintf(dbgout, "Event poll !\n");
+	identified = true;
+	break;
+	
+      case TO_HI:
+	fprintf(dbgout, "Too many arguments (with opt)\n");
+	identified = true;
+	break;
+	
+      case TO_LT:
+	fprintf(dbgout, "Too few arguments (with opt/rest/key)\n");
+	identified = true;
+	break;
+	
+      default:                /* some weird trap, not ours. */
+	identified = false;
+	break;
+      }
+    } else {
+      /* A type or boundp trap of some sort. */
+      switch (TO_field(the_trap)) {
+      case TO_EQ:
+	/* Boundp traps are of the form:
+	   treqi rX,unbound
+	   where some preceding instruction is of the form:
+	   lwz/ld rX,symbol.value(rY).
+	   The error message should try to say that rY is unbound. */
+	
+	if (D_field(the_trap) == unbound) {
+#ifdef PPC64
+	  instr = scan_for_instr(LD_instruction(RA_field(the_trap),
+                                                unmasked_register,
+                                                offsetof(lispsymbol,vcell)-fulltag_misc),
+				 D_RT_IMM_MASK,
+				 where);
+#else
+	  instr = scan_for_instr(LWZ_instruction(RA_field(the_trap),
+						 unmasked_register,
+						 offsetof(lispsymbol,vcell)-fulltag_misc),
+				 D_RT_IMM_MASK,
+				 where);
+#endif
+	  if (instr) {
+	    ra = RA_field(instr);
+	    if (lisp_reg_p(ra)) {
+	      fprintf(dbgout, "Unbound variable: %s\n",
+		      print_lisp_object(xpGPR(xp,ra)));
+	      identified = true;	
+	    }
+	  }
+	}
+	break;
+	
+      case TO_NE:
+	/* A type check.  If the type (the immediate field of the trap
+	   instruction) is a header type, an "lbz
+	   rX,misc_header_offset(rY)" should precede it, in which case
+	   we say that "rY is not of header type <type>."  If the type
+	   is not a header type, then rX should have been set by a
+	   preceding "clrlwi rX,rY,29/30".  In that case, scan
+	   backwards for an RLWINM instruction that set rX and report
+	   that rY isn't of the indicated type. */
+	err_arg2 = D_field(the_trap);
+	if (nodeheader_tag_p(err_arg2) ||
+	    immheader_tag_p(err_arg2)) {
+	  instr = scan_for_instr(LBZ_instruction(RA_field(the_trap),
+						 unmasked_register,
+						 misc_subtag_offset),
+				 D_RT_IMM_MASK,
+				 where);
+	  if (instr) {
+	    ra = RA_field(instr);
+	    if (lisp_reg_p(ra)) {
+	      fprintf(dbgout, "value 0x%lX is not of the expected header type 0x%02X\n", xpGPR(xp, ra), err_arg2);
+	      identified = true;
+	    }
+	  }
+	} else {		
+	  /* Not a header type, look for rlwinm whose RA field matches the_trap's */
+	  instr = scan_for_instr((OP(major_opcode_RLWINM) | (the_trap & RA_MASK)),
+				 (OP_MASK | RA_MASK),
+				 where);
+	  if (instr) {
+	    rs = RS_field(instr);
+	    if (lisp_reg_p(rs)) {
+	      fprintf(dbgout, "value 0x%lX is not of the expected type 0x%02X\n",
+		      xpGPR(xp, rs), err_arg2);
+	      identified = true;
+	    }
+	  }
+	}
+	break;
+      }
+    }
+  } else {
+    /* a "TW <to>,ra,rb" instruction."
+       twltu sp,rN is stack-overflow on SP.
+       twgeu rX,rY is subscript out-of-bounds, which was preceded
+       by an "lwz rM,misc_header_offset(rN)" instruction.
+       rM may or may not be the same as rY, but no other header
+       would have been loaded before the trap. */
+    switch (TO_field(the_trap)) {
+    case TO_LO:
+      if (RA_field(the_trap) == sp) {
+	fprintf(dbgout, "Stack overflow! Run away! Run away!\n");
+	identified = true;
+      }
+      break;
+      
+    case (TO_HI|TO_EQ):
+      instr = scan_for_instr(OP(major_opcode_LWZ) | (D_MASK & misc_header_offset),
+			     (OP_MASK | D_MASK),
+			     where);
+      if (instr) {
+	ra = RA_field(instr);
+	if (lisp_reg_p(ra)) {
+	  fprintf(dbgout, "Bad index %d for vector %lX length %d\n",
+		  unbox_fixnum(xpGPR(xp, RA_field(the_trap))),
+		  xpGPR(xp, ra),
+		  unbox_fixnum(xpGPR(xp, RB_field(the_trap))));
+	  identified = true;
+	}
+      }
+      break;
+    }
+  }
+
+  if (!identified) {
+    fprintf(dbgout, "Unknown trap: 0x%08x\n", the_trap);
+  }
+
+
+}
+#endif
+
+debug_command_return
+debug_lisp_registers(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  if (lisp_debugger_in_foreign_code == false) {
+#ifdef PPC
+    TCR *xpcontext = (TCR *)ptr_from_lispobj(xpGPR(xp, rcontext));
+
+    fprintf(dbgout, "rcontext = 0x%lX ", xpcontext);
+    if (!active_tcr_p(xpcontext)) {
+      fprintf(dbgout, "(INVALID)\n");
+    } else {
+      fprintf(dbgout, "\nnargs = %d\n", xpGPR(xp, nargs) >> fixnumshift);
+      show_lisp_register(xp, "fn", fn);
+      show_lisp_register(xp, "arg_z", arg_z);
+      show_lisp_register(xp, "arg_y", arg_y);
+      show_lisp_register(xp, "arg_x", arg_x);
+      show_lisp_register(xp, "temp0", temp0);
+      show_lisp_register(xp, "temp1/next_method_context", temp1);
+      show_lisp_register(xp, "temp2/nfn", temp2);
+      show_lisp_register(xp, "temp3/fname", temp3);
+      /*    show_lisp_register(xp, "new_fn", new_fn); */
+      show_lisp_register(xp, "save0", save0);
+      show_lisp_register(xp, "save1", save1);
+      show_lisp_register(xp, "save2", save2);
+      show_lisp_register(xp, "save3", save3);
+      show_lisp_register(xp, "save4", save4);
+      show_lisp_register(xp, "save5", save5);
+      show_lisp_register(xp, "save6", save6);
+      show_lisp_register(xp, "save7", save7);
+    }
+#endif
+#ifdef X8664
+
+    show_lisp_register(xp, "arg_z", Iarg_z);
+    show_lisp_register(xp, "arg_y", Iarg_y);
+    show_lisp_register(xp, "arg_x", Iarg_x);
+    fprintf(dbgout,"------\n");
+    show_lisp_register(xp, "fn", Ifn);
+    fprintf(dbgout,"------\n");
+    show_lisp_register(xp, "save0", Isave0);
+    show_lisp_register(xp, "save1", Isave1);
+    show_lisp_register(xp, "save2", Isave2);
+    show_lisp_register(xp, "save3", Isave3);
+    fprintf(dbgout,"------\n");
+    show_lisp_register(xp, "temp0", Itemp0);
+    show_lisp_register(xp, "temp1", Itemp1);
+    show_lisp_register(xp, "temp2", Itemp2);
+    fprintf(dbgout,"------\n");
+    if (tag_of(xpGPR(xp,Inargs)) == tag_fixnum) {
+      fprintf(dbgout,"%%rcx (nargs) = %ld (maybe)\n", unbox_fixnum(xpGPR(xp,Inargs)&0xffff));
+    }
+#endif
+
+#ifdef X8632
+  show_lisp_register(xp, "arg_z", Iarg_z);
+  show_lisp_register(xp, "arg_y", Iarg_y);
+  fprintf(dbgout,"------\n");
+  show_lisp_register(xp, "fn", Ifn);
+  fprintf(dbgout,"------\n");
+  show_lisp_register(xp, "temp0", Itemp0);
+  show_lisp_register(xp, "temp1", Itemp1);
+  fprintf(dbgout,"------\n");
+  if (tag_of(xpGPR(xp,Inargs)) == tag_fixnum) {
+    fprintf(dbgout,"%%edx (nargs) = %d (maybe)\n", unbox_fixnum(xpGPR(xp,Inargs)));
+  }
+#endif
+  }
+  
+  return debug_continue;
+}
+
+#ifdef PPC
+debug_command_return
+debug_advance_pc(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  adjust_exception_pc(xp,4);
+  return debug_continue;
+}
+#endif
+
+debug_command_return
+debug_identify_exception(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+#ifdef PPC
+  pc program_counter = xpPC(xp);
+  opcode instruction = 0;
+
+  switch (arg) {
+  case SIGILL:
+  case SIGTRAP:
+    instruction = *program_counter;
+    if (major_opcode_p(instruction, major_opcode_TRI) ||
+	X_opcode_p(instruction,major_opcode_X31,minor_opcode_TR)) {
+      describe_ppc_trap(xp);
+    } else {
+      describe_ppc_illegal(xp);
+    }
+    break;
+  case SIGSEGV:
+  case SIGBUS:
+    describe_memfault(xp, info);
+    break;
+  default:
+    break;
+  }
+#endif
+  return debug_continue;
+}
+
+char *
+debug_get_string_value(char *prompt)
+{
+  static char buf[128];
+  char *p, *res;
+
+  do {
+    fpurge(stdin);
+    fprintf(dbgout, "\n %s :",prompt);
+    buf[0] = 0;
+    res = fgets(buf, sizeof(buf), stdin);
+  } while (0);
+  p = strchr(res, '\n');
+  if (p) {
+    *p = 0;
+    return buf;
+  }
+  return NULL;
+}
+
+natural
+debug_get_natural_value(char *prompt)
+{
+  char s[32], *res;
+  int n;
+  natural val;
+
+  do {
+    fpurge(stdin);
+    fprintf(dbgout, "\n  %s :", prompt);
+    s[0]=0;
+    res = fgets(s, 24, stdin);
+    n = sscanf(s, "%lu", &val);
+  } while (n != 1);
+  return val;
+}
+
+unsigned
+debug_get_u5_value(char *prompt)
+{
+  char s[32], *res;
+  int n;
+  unsigned val;
+
+  do {
+    fpurge(stdin);
+    fprintf(dbgout, "\n  %s :", prompt);
+    res = fgets(s, 24, stdin);
+    n = sscanf(res, "%i", &val);
+  } while ((n != 1) || (val > 31));
+  return val;
+}
+
+debug_command_return
+debug_show_symbol(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  char *pname = debug_get_string_value("symbol name");
+  extern void *plsym(ExceptionInformation *,char*);
+  
+  if (pname != NULL) {
+    plsym(xp, pname);
+  }
+  return debug_continue;
+}
+
+debug_command_return
+debug_thread_info(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  TCR * tcr = get_tcr(false);
+  
+  if (tcr) {
+    area *vs_area = tcr->vs_area, *cs_area = tcr->cs_area;
+
+    fprintf(dbgout, "Current Thread Context Record (tcr) = 0x" LISP "\n", tcr);
+    fprintf(dbgout, "Control (C) stack area:  low = 0x" LISP ", high = 0x" LISP "\n",
+            (cs_area->low), (cs_area->high));
+    fprintf(dbgout, "Value (lisp) stack area: low = 0x" LISP ", high = 0x" LISP "\n",
+            (u64_t)(natural)(vs_area->low), (u64_t)(natural)vs_area->high);
+    fprintf(dbgout, "Exception stack pointer = 0x" LISP "\n",
+#ifdef PPC
+            (u64_t) (natural)(xpGPR(xp,1))
+#endif
+#ifdef X86
+            (u64_t) (natural)(xpGPR(xp,Isp))
+#endif
+            );
+  }
+  return debug_continue;
+}
+      
+
+debug_command_return
+debug_set_gpr(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  char buf[32];
+  natural val;
+
+  sprintf(buf, "value for GPR %d", arg);
+  val = debug_get_natural_value(buf);
+  xpGPR(xp,arg) = val;
+  return debug_continue;
+}
+
+debug_command_return
+debug_show_registers(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+
+
+#ifdef PPC
+#ifdef PPC64
+  int a, b;
+  for (a = 0, b = 16; a < 16; a++, b++) {
+    fprintf(dbgout,"r%02d = 0x%016lX    r%02d = 0x%016lX\n",
+	    a, xpGPR(xp, a),
+	    b, xpGPR(xp, b));
+  }
+  
+  fprintf(dbgout, "\n PC = 0x%016lX     LR = 0x%016lX\n",
+          xpPC(xp), xpLR(xp));
+  fprintf(dbgout, "CTR = 0x%016lX    CCR = 0x%08X\n",
+          xpCTR(xp), xpCCR(xp));
+  fprintf(dbgout, "XER = 0x%08X            MSR = 0x%016lX\n",
+          xpXER(xp), xpMSR(xp));
+  fprintf(dbgout,"DAR = 0x%016lX  DSISR = 0x%08X\n",
+	  xpDAR(xp), xpDSISR(xp));
+#else
+  int a, b, c, d;;
+  for (a = 0, b = 8, c = 16, d = 24; a < 8; a++, b++, c++, d++) {
+    fprintf(dbgout,"r%02d = 0x%08X  r%02d = 0x%08X  r%02d = 0x%08X  r%02d = 0x%08X\n",
+	    a, xpGPR(xp, a),
+	    b, xpGPR(xp, b),
+	    c, xpGPR(xp, c),
+	    d, xpGPR(xp, d));
+  }
+  fprintf(dbgout, "\n PC = 0x%08X   LR = 0x%08X  CTR = 0x%08X  CCR = 0x%08X\n",
+	  xpPC(xp), xpLR(xp), xpCTR(xp), xpCCR(xp));
+  fprintf(dbgout, "XER = 0x%08X  MSR = 0x%08X  DAR = 0x%08X  DSISR = 0x%08X\n",
+	  xpXER(xp), xpMSR(xp), xpDAR(xp), xpDSISR(xp));
+#endif
+#endif
+
+#ifdef X8664
+  fprintf(dbgout,"%%rax = 0x" ZLISP "      %%r8  = 0x" ZLISP "\n", xpGPR(xp,REG_RAX),xpGPR(xp,REG_R8));
+  fprintf(dbgout,"%%rcx = 0x" ZLISP "      %%r9  = 0x" ZLISP "\n", xpGPR(xp,REG_RCX),xpGPR(xp,REG_R9));
+  fprintf(dbgout,"%%rdx = 0x" ZLISP "      %%r10 = 0x" ZLISP "\n", xpGPR(xp,REG_RDX),xpGPR(xp,REG_R10));
+  fprintf(dbgout,"%%rbx = 0x" ZLISP "      %%r11 = 0x" ZLISP "\n", xpGPR(xp,REG_RBX),xpGPR(xp,REG_R11));
+  fprintf(dbgout,"%%rsp = 0x" ZLISP "      %%r12 = 0x" ZLISP "\n", xpGPR(xp,REG_RSP),xpGPR(xp,REG_R12));
+  fprintf(dbgout,"%%rbp = 0x" ZLISP "      %%r13 = 0x" ZLISP "\n", xpGPR(xp,REG_RBP),xpGPR(xp,REG_R13));
+  fprintf(dbgout,"%%rsi = 0x" ZLISP "      %%r14 = 0x" ZLISP "\n", xpGPR(xp,REG_RSI),xpGPR(xp,REG_R14));
+  fprintf(dbgout,"%%rdi = 0x" ZLISP "      %%r15 = 0x" ZLISP "\n", xpGPR(xp,REG_RDI),xpGPR(xp,REG_R15));
+  fprintf(dbgout,"%%rip = 0x" ZLISP "   %%rflags = 0x%08lx\n",
+	  xpGPR(xp, Iip), eflags_register(xp));
+#endif
+
+#ifdef X8632
+  unsigned short rcs,rds,res,rfs,rgs,rss;
+#ifdef DARWIN
+  rcs = xp->uc_mcontext->__ss.__cs;
+  rds = xp->uc_mcontext->__ss.__ds;
+  res = xp->uc_mcontext->__ss.__es;
+  rfs = xp->uc_mcontext->__ss.__fs;
+  rgs = xp->uc_mcontext->__ss.__gs;
+  rss = xp->uc_mcontext->__ss.__ss;
+#define DEBUG_SHOW_X86_SEGMENT_REGISTERS
+#endif
+#ifdef LINUX
+  rcs = xp->uc_mcontext.gregs[REG_CS];
+  rds = xp->uc_mcontext.gregs[REG_DS];
+  res = xp->uc_mcontext.gregs[REG_ES];
+  rfs = xp->uc_mcontext.gregs[REG_FS];
+  rgs = xp->uc_mcontext.gregs[REG_GS];
+  rss = xp->uc_mcontext.gregs[REG_SS];
+#define DEBUG_SHOW_X86_SEGMENT_REGISTERS
+#endif
+#ifdef FREEBSD
+  rcs = xp->uc_mcontext.mc_cs;
+  rds = xp->uc_mcontext.mc_ds;
+  res = xp->uc_mcontext.mc_es;
+  rfs = xp->uc_mcontext.mc_fs;
+  rgs = xp->uc_mcontext.mc_gs;
+  rss = xp->uc_mcontext.mc_ss;
+#define DEBUG_SHOW_X86_SEGMENT_REGISTERS
+#endif
+#ifdef SOLARIS
+  rcs = xp->uc_mcontext.gregs[CS];
+  rds = xp->uc_mcontext.gregs[DS];
+  res = xp->uc_mcontext.gregs[ES];
+  rfs = xp->uc_mcontext.gregs[FS];
+  rgs = xp->uc_mcontext.gregs[GS];
+  rss = xp->uc_mcontext.gregs[SS];
+#define DEBUG_SHOW_X86_SEGMENT_REGISTERS
+#endif
+#ifdef WINDOWS
+  rcs = xp->SegCs;
+  rds = xp->SegDs;
+  res = xp->SegEs;
+  rfs = xp->SegFs;
+  rgs = xp->SegGs;
+  rss = xp->SegSs;
+#define DEBUG_SHOW_X86_SEGMENT_REGISTERS
+#endif
+
+
+
+  fprintf(dbgout, "%%eax = 0x" ZLISP "\n", xpGPR(xp, REG_EAX));
+  fprintf(dbgout, "%%ecx = 0x" ZLISP "\n", xpGPR(xp, REG_ECX));
+  fprintf(dbgout, "%%edx = 0x" ZLISP "\n", xpGPR(xp, REG_EDX));
+  fprintf(dbgout, "%%ebx = 0x" ZLISP "\n", xpGPR(xp, REG_EBX));
+  fprintf(dbgout, "%%esp = 0x" ZLISP "\n", xpGPR(xp, REG_ESP));
+  fprintf(dbgout, "%%ebp = 0x" ZLISP "\n", xpGPR(xp, REG_EBP));
+  fprintf(dbgout, "%%esi = 0x" ZLISP "\n", xpGPR(xp, REG_ESI));
+  fprintf(dbgout, "%%edi = 0x" ZLISP "\n", xpGPR(xp, REG_EDI));
+  fprintf(dbgout, "%%eip = 0x" ZLISP "\n", xpGPR(xp, REG_EIP));
+  fprintf(dbgout, "%%eflags = 0x" ZLISP "\n", xpGPR(xp, REG_EFL));
+#ifdef DEBUG_SHOW_X86_SEGMENT_REGISTERS
+  fprintf(dbgout,"\n");
+  fprintf(dbgout, "%%cs = 0x%04x\n", rcs);
+  fprintf(dbgout, "%%ds = 0x%04x\n", rds);
+  fprintf(dbgout, "%%ss = 0x%04x\n", rss);
+  fprintf(dbgout, "%%es = 0x%04x\n", res);
+  fprintf(dbgout, "%%fs = 0x%04x\n", rfs);
+  fprintf(dbgout, "%%gs = 0x%04x\n", rgs);
+
+#endif
+
+#endif
+
+  return debug_continue;
+}
+
+debug_command_return
+debug_show_fpu(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  double *dp;
+  int *np, i;
+#ifdef PPC
+  dp = xpFPRvector(xp);
+  np = (int *) dp;
+  
+  for (i = 0; i < 32; i++, np+=2) {
+    fprintf(dbgout, "f%02d : 0x%08X%08X (%f)\n", i,  np[0], np[1], *dp++);
+  }
+  fprintf(dbgout, "FPSCR = %08X\n", xpFPSCR(xp));
+#endif
+#ifdef X8664
+#ifdef LINUX
+  struct _libc_xmmreg * xmmp = &(xp->uc_mcontext.fpregs->_xmm[0]);
+#endif
+#ifdef DARWIN
+  struct xmm {
+    char fpdata[16];
+  };
+  struct xmm *xmmp = (struct xmm *)(xpFPRvector(xp));
+#endif
+#ifdef WINDOWS
+  struct xmm {
+    char fpdata[16];
+  };
+  struct xmm *xmmp; /* XXX: actually get them */
+#endif
+#ifdef FREEBSD
+  struct xmmacc *xmmp = xpXMMregs(xp);
+#endif
+#ifdef SOLARIS
+  upad128_t *xmmp = xpXMMregs(xp);
+#endif
+  float *sp;
+
+
+  for (i = 0; i < 16; i++, xmmp++) {
+    sp = (float *) xmmp;
+    dp = (double *) xmmp;
+    np = (int *) xmmp;
+    fprintf(dbgout, "f%02d: 0x%08x (%e), 0x%08x%08x (%e)\n", i, *np, (double)(*sp), np[1], np[0], *dp);
+  }
+  fprintf(dbgout, "mxcsr = 0x%08x\n",
+#ifdef LINUX
+          xp->uc_mcontext.fpregs->mxcsr
+#endif
+#ifdef DARWIN
+          UC_MCONTEXT(xp)->__fs.__fpu_mxcsr
+#endif
+#ifdef FREEBSD
+          (((struct savefpu *)(&(xp)->uc_mcontext.mc_fpstate))->sv_env.en_mxcsr)
+#endif
+#ifdef SOLARIS
+	  xp->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xstatus
+#endif
+#ifdef WINDOWS
+          *(xpMXCSRptr(xp))
+#endif
+          );
+#endif  
+#ifdef X8632
+#ifdef DARWIN
+  struct xmm {
+    char fpdata[8];
+  };
+  struct xmm *xmmp = (struct xmm *)(xpFPRvector(xp));
+
+  for (i = 0; i < 8; i++, xmmp++) {
+    float *sp = (float *)xmmp;
+    dp = (double *)xmmp;
+    np = (int *)xmmp;
+    fprintf(dbgout, "f%1d: 0x%08x (%e), 0x%08x%08x (%e)\n", i, *np,
+	    (double)(*sp), np[1], np[0], *dp);
+  }
+  fprintf(dbgout, "mxcsr = 0x%08x\n", UC_MCONTEXT(xp)->__fs.__fpu_mxcsr);
+#endif
+#endif
+
+  return debug_continue;
+}
+
+debug_command_return
+debug_kill_process(ExceptionInformation *xp, siginfo_t *info, int arg) {
+  return debug_kill;
+}
+
+debug_command_return
+debug_win(ExceptionInformation *xp, siginfo_t *info, int arg) {
+  return debug_exit_success;
+}
+
+debug_command_return
+debug_lose(ExceptionInformation *xp, siginfo_t *info, int arg) {
+  return debug_exit_fail;
+}
+
+debug_command_return
+debug_help(ExceptionInformation *xp, siginfo_t *info, int arg) {
+  debug_command_entry *entry;
+
+  for (entry = debug_command_entries; entry->f; entry++) {
+    /* If we have an XP or don't need one, call the function */
+    if (xp || !(entry->flags & DEBUG_COMMAND_FLAG_REQUIRE_XP)) {
+      fprintf(dbgout, "(%c)  %s\n", entry->c, entry->help_text);
+    }
+  }
+  return debug_continue;
+}
+	      
+
+  
+
+debug_command_return
+debug_backtrace(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  extern LispObj current_stack_pointer();
+  extern void plbt_sp(LispObj);
+  extern void plbt(ExceptionInformation *);
+
+  if (xp) {
+    plbt(xp);
+  } else {
+    plbt_sp(current_stack_pointer());
+  }
+  return debug_continue;
+}
+
+debug_command_return
+debug_thread_reset(ExceptionInformation *xp, siginfo_t *info, int arg)
+{
+  reset_lisp_process(xp);
+  return debug_exit_success;
+}
+
+
+debug_command_entry debug_command_entries[] = 
+{
+  {debug_set_gpr,
+   "Set specified GPR to new value",
+   DEBUG_COMMAND_FLAG_AUX_REGNO,
+   "GPR to set (0-31) ?",
+   'G'},
+#ifdef PPC
+  {debug_advance_pc,
+   "Advance the program counter by one instruction (use with caution!)",
+   DEBUG_COMMAND_FLAG_REQUIRE_XP | DEBUG_COMMAND_FLAG_EXCEPTION_ENTRY_ONLY,
+   NULL,
+   'A'},
+  {debug_identify_exception,
+   "Describe the current exception in greater detail",
+   DEBUG_COMMAND_FLAG_REQUIRE_XP | DEBUG_COMMAND_FLAG_EXCEPTION_ENTRY_ONLY |
+   DEBUG_COMMAND_FLAG_EXCEPTION_REASON_ARG,
+   NULL,
+   'D'},
+#endif
+  {debug_show_registers, 
+   "Show raw GPR/SPR register values", 
+   DEBUG_COMMAND_FLAG_REQUIRE_XP,
+   NULL,
+   'R'},
+  {debug_lisp_registers,
+   "Show Lisp values of tagged registers",
+   DEBUG_COMMAND_FLAG_REQUIRE_XP,
+   NULL,
+   'L'},
+  {debug_show_fpu,
+   "Show FPU registers",
+   DEBUG_COMMAND_FLAG_REQUIRE_XP,
+   NULL,
+   'F'},
+  {debug_show_symbol,
+   "Find and describe symbol matching specified name",
+   0,
+   NULL,
+   'S'},
+  {debug_backtrace,
+   "Show backtrace",
+   0,
+   NULL,
+   'B'},
+  {debug_thread_info,
+   "Show info about current thread",
+   0,
+   NULL,
+   'T'},
+  {debug_win,
+   "Exit from this debugger, asserting that any exception was handled",
+   0,
+   NULL,
+   'X'},
+#ifdef DARWIN
+  {debug_lose,
+   "Propagate the exception to another handler (debugger or OS)",
+   DEBUG_COMMAND_FLAG_REQUIRE_XP | DEBUG_COMMAND_FLAG_EXCEPTION_ENTRY_ONLY,
+   NULL,
+   'P'},
+#endif
+#if 0
+  {debug_thread_reset,
+   "Reset current thread (as if in response to stack overflow)",
+   DEBUG_COMMAND_FLAG_REQUIRE_XP,
+   NULL,
+   'T'},
+#endif
+  {debug_kill_process,
+   "Kill Clozure CL process",
+   0,
+   NULL,
+   'K'},
+  {debug_help,
+   "Show this help",
+   0,
+   NULL,
+   '?'},
+  /* end-of-table */
+  {NULL,
+   NULL,
+   0,
+   NULL,
+   0}
+};
+
+debug_command_return
+apply_debug_command(ExceptionInformation *xp, int c, siginfo_t *info, int why) 
+{
+  if (c == EOF) {
+    return debug_kill;
+  } else {
+    debug_command_entry *entry;
+    debug_command f;
+    c = toupper(c);
+
+    for (entry = debug_command_entries; (f = entry->f) != NULL; entry++) {
+      if (toupper(entry->c) == c) {
+	/* If we have an XP or don't need one, call the function */
+	if ((xp || !(entry->flags & DEBUG_COMMAND_FLAG_REQUIRE_XP)) &&
+	    ((why > debug_entry_exception) || 
+	     !(entry->flags & DEBUG_COMMAND_FLAG_EXCEPTION_ENTRY_ONLY))) {
+	  int arg = 0;
+	  if ((entry->flags & DEBUG_COMMAND_REG_FLAGS)
+	      == DEBUG_COMMAND_FLAG_AUX_REGNO) {
+	    arg = debug_get_u5_value("register number");
+	  }
+	  if (entry->flags & DEBUG_COMMAND_FLAG_EXCEPTION_REASON_ARG) {
+	    arg = why;
+	  }
+	  return (f)(xp, info, arg);
+	}
+	break;
+      }
+    }
+    return debug_continue;
+  }
+}
+
+debug_identify_function(ExceptionInformation *xp, siginfo_t *info) 
+{
+#ifdef PPC
+  if (xp) {
+    if (active_tcr_p((TCR *)(ptr_from_lispobj(xpGPR(xp, rcontext))))) {
+      LispObj f = xpGPR(xp, fn), codev;
+      pc where = xpPC(xp);
+      
+      if (!(codev = register_codevector_contains_pc(f, where))) {
+        f = xpGPR(xp, nfn);
+        codev =  register_codevector_contains_pc(f, where);
+      }
+      if (codev) {
+        fprintf(dbgout, " While executing: %s\n", print_lisp_object(f));
+      }
+    } else {
+      int disp;
+      char *foreign_name;
+      natural where = (natural)xpPC(xp);
+
+      fprintf(dbgout, " In foreign code at address 0x" ZLISP "\n", where);
+      foreign_name = foreign_name_and_offset(where, &disp);
+      if (foreign_name) {
+        fprintf(dbgout, "  [%s + %d]\n", foreign_name, disp);
+      }
+    }
+  }
+#endif
+}
+
+#ifndef WINDOWS
+extern pid_t main_thread_pid;
+#endif
+
+
+OSStatus
+lisp_Debugger(ExceptionInformation *xp, 
+	      siginfo_t *info, 
+	      int why, 
+              Boolean in_foreign_code,
+	      char *message, 
+	      ...)
+{
+  va_list args;
+  debug_command_return state = debug_continue;
+
+
+  if (stdin_is_dev_null()) {
+    return -1;
+  }
+
+  va_start(args,message);
+  vfprintf(dbgout, message, args);
+  fprintf(dbgout, "\n");
+  va_end(args);
+
+  if (threads_initialized) {
+    suspend_other_threads(false);
+  }
+
+  lisp_debugger_in_foreign_code = in_foreign_code;
+  if (in_foreign_code) {    
+    char *foreign_name;
+    int disp;
+    fprintf(dbgout, "Exception occurred while executing foreign code\n");
+    foreign_name = foreign_name_and_offset((natural)xpPC(xp), &disp);
+    if (foreign_name) {
+      fprintf(dbgout, " at %s + %d\n", foreign_name, disp);
+    }
+  }
+
+  if (xp) {
+    if (why > debug_entry_exception) {
+      debug_identify_exception(xp, info, why);
+    }
+    debug_identify_function(xp, info);
+  }
+  if (lisp_global(BATCH_FLAG)) {
+#ifdef WINDOWS
+    fprintf(dbgout, "Current Process Id %d\n", (int)GetCurrentProcessId());
+#else
+    fprintf(dbgout, "Main thread pid %d\n", main_thread_pid);
+#endif
+    debug_thread_info(xp, info, 0);
+    if (xp) {
+      debug_show_registers(xp, info, 0);
+      debug_lisp_registers(xp, info, 0);
+      debug_show_fpu(xp, info, 0);
+    }
+    debug_backtrace(xp, info, 0);
+    abort();
+  }
+
+  fprintf(dbgout, "? for help\n");
+  while (state == debug_continue) {
+#ifdef WINDOWS
+    fprintf(dbgout, "[%d] Clozure CL kernel debugger: ", (int)GetCurrentProcessId());
+#else
+    fprintf(dbgout, "[%d] Clozure CL kernel debugger: ", main_thread_pid);
+#endif
+    fflush(dbgout);             /* dbgout should be unbuffered, so this shouldn't be necessary.  But it can't hurt ... */
+    state = apply_debug_command(xp, readc(), info, why);
+  }
+  switch (state) {
+  case debug_exit_success:
+    if (threads_initialized) {
+      resume_other_threads(false);
+    }
+    return 0;
+  case debug_exit_fail:
+    if (threads_initialized) {
+      resume_other_threads(false);
+    }
+    return -1;
+  case debug_kill:
+    terminate_lisp();
+  default:
+    return 0;
+  }
+}
+
+void
+Bug(ExceptionInformation *xp, const char *format, ...)
+{
+  va_list args;
+  char s[512];
+ 
+  va_start(args, format);
+  vsnprintf(s, sizeof(s),format, args);
+  va_end(args);
+  lisp_Debugger(xp, NULL, debug_entry_bug, false, s);
+
+}
+
+void
+FBug(ExceptionInformation *xp, const char *format, ...)
+{
+  va_list args;
+  char s[512];
+ 
+  va_start(args, format);
+  vsnprintf(s, sizeof(s),format, args);
+  va_end(args);
+  lisp_Debugger(xp, NULL, debug_entry_bug, true, s);
+
+}
+
+void
+lisp_bug(char *string)
+{
+  Bug(NULL, "Bug in Clozure CL system code:\n%s", string);
+}
+
Index: /branches/new-random/lisp-kernel/lisp-errors.h
===================================================================
--- /branches/new-random/lisp-kernel/lisp-errors.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/lisp-errors.h	(revision 13309)
@@ -0,0 +1,163 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __ERRORS_X
+#define __ERRORS_X 1
+
+
+#define error_reg_regnum 0
+#define error_udf 1
+#define error_udf_call 2
+#define error_throw_tag_missing 3
+#define error_alloc_failed 4
+#define error_stack_overflow 5
+#define error_excised_function_call 6
+#define error_too_many_values 7
+#define error_propagate_suspend 10
+#define error_interrupt 11
+#define error_suspend 12
+#define error_suspend_all 13
+#define error_resume 14
+#define error_resume_all 15 
+#define error_kill 16
+#define error_cant_call 17
+#define error_allocate_list 18
+
+#define error_type_error 128
+
+typedef enum {
+  error_object_not_array = error_type_error,
+  error_object_not_bignum,
+  error_object_not_fixnum,
+  error_object_not_character,
+  error_object_not_integer,
+  error_object_not_list,
+  error_object_not_number,
+  error_object_not_sequence,
+  error_object_not_simple_string,
+  error_object_not_simple_vector,
+  error_object_not_string,
+  error_object_not_symbol,
+  error_object_not_macptr,
+  error_object_not_real,
+  error_object_not_cons,
+  error_object_not_unsigned_byte,
+  error_object_not_radix,
+  error_object_not_float,
+  error_object_not_rational,
+  error_object_not_ratio,
+  error_object_not_short_float,
+  error_object_not_double_float,
+  error_object_not_complex,
+  error_object_not_vector,
+  error_object_not_simple_base_string,
+  error_object_not_function,
+  error_object_not_unsigned_byte_16,
+  error_object_not_unsigned_byte_8,
+  error_object_not_unsigned_byte_32,
+  error_object_not_signed_byte_32,
+  error_object_not_signed_byte_16,
+  error_object_not_signed_byte_8,	
+  error_object_not_base_character,
+  error_object_not_bit,
+  error_object_not_unsigned_byte_24,
+  error_object_not_u64,
+  error_object_not_s64,
+  error_object_not_unsigned_byte_56,
+  error_object_not_simple_array_double_float_2d,
+  error_object_not_simple_array_single_float_2d,
+  error_object_not_mod_char_code_limit,
+  error_object_not_array_2d,
+  error_object_not_array_3d,
+  error_object_not_array_t,
+  error_object_not_array_bit,
+  error_object_not_array_s8,
+  error_object_not_array_u8,
+  error_object_not_array_s16,
+  error_object_not_array_u16,
+  error_object_not_array_s32,
+  error_object_not_array_u32,
+  error_object_not_array_s64,
+  error_object_not_array_u64,
+  error_object_not_array_fixnum,
+  error_object_not_array_single_float,
+  error_object_not_array_double_float,
+  error_object_not_array_char,
+  error_object_not_array_t_2d,
+  error_object_not_array_bit_2d,
+  error_object_not_array_s8_2d,
+  error_object_not_array_u8_2d,
+  error_object_not_array_s16_2d,
+  error_object_not_array_u16_2d,
+  error_object_not_array_s32_2d,
+  error_object_not_array_u32_2d,
+  error_object_not_array_s64_2d,
+  error_object_not_array_u64_2d,
+  error_object_not_array_fixnum_2d,
+  error_object_not_array_single_float_2d,
+  error_object_not_array_double_float_2d,
+  error_object_not_array_char_2d,
+  error_object_not_simple_array_t_2d,
+  error_object_not_simple_array_bit_2d,
+  error_object_not_simple_array_s8_2d,
+  error_object_not_simple_array_u8_2d,
+  error_object_not_simple_array_s16_2d,
+  error_object_not_simple_array_u16_2d,
+  error_object_not_simple_array_s32_2d,
+  error_object_not_simple_array_u32_2d,
+  error_object_not_simple_array_s64_2d,
+  error_object_not_simple_array_u64_2d,
+  error_object_not_simple_array_fixnum_2d,
+  error_object_not_simple_array_char_2d,
+  error_object_not_array_t_3d,
+  error_object_not_array_bit_3d,
+  error_object_not_array_s8_3d,
+  error_object_not_array_u8_3d,
+  error_object_not_array_s16_3d,
+  error_object_not_array_u16_3d,
+  error_object_not_array_s32_3d,
+  error_object_not_array_u32_3d,
+  error_object_not_array_s64_3d,
+  error_object_not_array_u64_3d,
+  error_object_not_array_fixnum_3d,
+  error_object_not_array_single_float_3d,
+  error_object_not_array_double_float_3d,
+  error_object_not_array_char_3d,
+  error_object_not_simple_array_t_3d,
+  error_object_not_simple_array_bit_3d,
+  error_object_not_simple_array_s8_3d,
+  error_object_not_simple_array_u8_3d,
+  error_object_not_simple_array_s16_3d,
+  error_object_not_simple_array_u16_3d,
+  error_object_not_simple_array_s32_3d,
+  error_object_not_simple_array_u32_3d,
+  error_object_not_simple_array_s64_3d,
+  error_object_not_simple_array_u64_3d,
+  error_object_not_simple_array_fixnum_3d,
+  error_object_not_simple_array_single_float_3d,
+  error_object_not_simple_array_double_float_3d,
+  error_object_not_simple_array_char_3d
+} type_error;
+
+#define error_FPU_exception_double 1024
+#define error_FPU_exception_short 1025
+
+#define error_memory_full 2048
+
+
+
+#endif /* __ERRORS_X */
Index: /branches/new-random/lisp-kernel/lisp-exceptions.h
===================================================================
--- /branches/new-random/lisp-kernel/lisp-exceptions.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/lisp-exceptions.h	(revision 13309)
@@ -0,0 +1,158 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __lisp_exceptions_h__
+#define __lisp_exceptions_h__ 1
+
+
+#include <stdlib.h>
+#include "memprotect.h"
+#include "gc.h"
+
+#ifdef WINDOWS
+#include <windows.h>
+#endif
+
+typedef enum {
+  kDebugger,
+  kContinue,
+  kExit
+} ErrAction;
+
+
+#ifdef WINDOWS
+typedef EXCEPTION_RECORD siginfo_t;  /* Not even close to being the right thing to do */
+#endif
+
+
+void
+zero_page(BytePtr);
+
+void
+zero_heap_segment(BytePtr);
+
+extern protected_area_ptr AllProtectedAreas;
+
+protected_area_ptr find_protected_area(BytePtr);
+
+OSStatus
+lisp_Debugger(ExceptionInformation *, siginfo_t *, int, Boolean, char *, ...);
+
+OSStatus
+handle_protection_violation(ExceptionInformation *, siginfo_t *, TCR *, int);
+
+protected_area_ptr 
+new_protected_area(BytePtr, BytePtr, lisp_protection_kind, natural, Boolean);
+
+void
+unprotect_area_prefix(protected_area_ptr, size_t);
+
+void
+protect_area_prefix(protected_area_ptr, size_t);
+
+void
+protect_area(protected_area_ptr);
+
+
+Boolean
+resize_dynamic_heap(BytePtr, natural);
+
+OSStatus
+PMCL_exception_handler(int, ExceptionInformation *, TCR *, siginfo_t *, int);
+
+TCR*
+get_tcr(Boolean);
+
+ErrAction
+error_action( void );
+
+void
+install_pmcl_exception_handlers(void);
+
+void
+unprotect_all_areas(void);
+
+void
+exception_cleanup(void);
+
+void
+exception_init();
+
+
+#define debug_entry_exception 0
+#define debug_entry_bug -1
+#define debug_entry_dbg -2
+
+#ifdef WINDOWS
+#define ALLOW_EXCEPTIONS(context) // blank stare for now
+#else
+#define ALLOW_EXCEPTIONS(context) \
+  pthread_sigmask(SIG_SETMASK, &context->uc_sigmask, NULL);
+#endif
+
+void
+Fatal(StringPtr, StringPtr);
+
+
+Ptr
+allocate(natural);
+
+Ptr
+zalloc(natural);
+
+void
+deallocate(Ptr);
+
+
+
+void
+non_fatal_error( char * );
+
+void Bug(ExceptionInformation *, const char *format_string, ...);
+void FBug(ExceptionInformation *, const char *format_string, ...);
+signed_natural gc_from_xp(ExceptionInformation *, signed_natural);
+signed_natural purify_from_xp(ExceptionInformation *, signed_natural);
+signed_natural impurify_from_xp(ExceptionInformation *, signed_natural);
+
+
+
+void
+adjust_exception_pc(ExceptionInformation *, int);
+
+size_t
+symbol_name( unsigned, char *, size_t );
+
+
+size_t
+exception_fn_name( ExceptionInformation *, int, char *, size_t );
+
+
+
+#ifdef PPC
+#include "ppc-exceptions.h"
+#endif
+
+#ifdef X86
+#include "x86-exceptions.h"
+#endif
+
+void suspend_other_threads(Boolean);
+void resume_other_threads(Boolean);
+
+
+#endif /* __lisp_exceptions_h__ */
+
Index: /branches/new-random/lisp-kernel/lisp.h
===================================================================
--- /branches/new-random/lisp-kernel/lisp.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/lisp.h	(revision 13309)
@@ -0,0 +1,135 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __lisp__
+#define __lisp__
+
+
+
+#include "lisptypes.h"
+#ifndef LOWMEM_BIAS
+#define LOWMEM_BIAS 0
+#endif
+
+#ifdef PPC
+#include "ppc-constants.h"
+#endif
+#ifdef X86
+#include "x86-constants.h"
+#endif
+#include "macros.h"
+
+extern Boolean use_mach_exception_handling;
+
+extern int page_size, log2_page_size;
+
+static inline natural
+_align_to_power_of_2(natural n, unsigned power)
+{
+  natural align = (1<<power) -1;
+
+  return (n+align) & ~align;
+}
+
+#define align_to_power_of_2(n,p) _align_to_power_of_2(((natural)(n)),p)
+
+static inline natural
+_truncate_to_power_of_2(natural n, unsigned power)
+{
+  return n & ~((1<<power) -1);
+}
+
+#define truncate_to_power_of_2(n,p) _truncate_to_power_of_2((natural)(n),p)
+
+LispObj start_lisp(TCR*, LispObj);
+
+size_t
+ensure_stack_limit(size_t);
+
+char *
+print_lisp_object(LispObj);
+
+#include "kernel-globals.h"
+#endif
+
+#define PLATFORM_WORD_SIZE_32 0
+#define PLATFORM_WORD_SIZE_64 64
+#define PLATFORM_CPU_PPC (0<<3)
+#define PLATFORM_CPU_SPARC (1<<3)
+#define PLATFORM_CPU_X86 (2<<3)
+#define PLATFORM_OS_VXWORKS 0
+#define PLATFORM_OS_LINUX 1
+#define PLATFORM_OS_SOLARIS 2
+#define PLATFORM_OS_DARWIN 3
+#define PLATFORM_OS_FREEBSD 4
+#define PLATFORM_OS_WINDOWS 5
+
+#ifdef LINUX
+#define PLATFORM_OS PLATFORM_OS_LINUX
+#endif
+
+#ifdef DARWIN
+#define PLATFORM_OS PLATFORM_OS_DARWIN
+#endif
+
+#ifdef FREEBSD
+#define PLATFORM_OS PLATFORM_OS_FREEBSD
+#endif
+
+#ifdef SOLARIS
+#define PLATFORM_OS PLATFORM_OS_SOLARIS
+#endif
+
+#ifdef WINDOWS
+#define PLATFORM_OS PLATFORM_OS_WINDOWS
+#endif
+
+#ifdef PPC
+#define PLATFORM_CPU PLATFORM_CPU_PPC
+#endif
+
+#ifdef X86
+#define PLATFORM_CPU PLATFORM_CPU_X86
+#endif
+
+#if (WORD_SIZE == 32)
+#define PLATFORM_WORD_SIZE PLATFORM_WORD_SIZE_32
+#endif
+
+#if (WORD_SIZE == 64)
+#define PLATFORM_WORD_SIZE PLATFORM_WORD_SIZE_64
+#endif
+
+#define PLATFORM (PLATFORM_OS|PLATFORM_CPU|PLATFORM_WORD_SIZE)
+
+#ifdef WINDOWS
+Boolean check_for_embedded_image (wchar_t *);
+#else
+Boolean check_for_embedded_image (char *);
+#endif
+natural xStackSpace();
+void init_threads(void *, TCR *);
+
+#ifdef WINDOWS
+void wperror(char *);
+#endif
+
+void ensure_static_conses(ExceptionInformation *, TCR *,natural);
+
+#include <stdio.h>
+
+extern FILE *dbgout;
Index: /branches/new-random/lisp-kernel/lisp.s
===================================================================
--- /branches/new-random/lisp-kernel/lisp.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/lisp.s	(revision 13309)
@@ -0,0 +1,68 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL. */
+ 
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence. */
+ 
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+ 
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+	include(m4macros.m4)
+        ifdef([LOWMEM_BIAS],[
+[LOWMEM_BIAS] = LOWMEM_BIAS
+],[
+[LOWMEM_BIAS] = 0
+])
+        undefine([LOWMEM_BIAS])
+        /* DWARF2 exception fsm */
+        DW_CFA_advance_loc = 0x40   
+        DW_CFA_offset = 0x80
+        DW_CFA_restore = 0xc0
+        DW_CFA_nop = 0x00
+        DW_CFA_set_loc = 0x01
+        DW_CFA_advance_loc1 = 0x02
+        DW_CFA_advance_loc2 = 0x03
+        DW_CFA_advance_loc4 = 0x04
+        DW_CFA_offset_extended = 0x05
+        DW_CFA_restore_extended = 0x06
+        DW_CFA_undefined = 0x07
+        DW_CFA_same_value = 0x08
+        DW_CFA_register = 0x09
+        DW_CFA_remember_state = 0x0a
+        DW_CFA_restore_state = 0x0b
+        DW_CFA_def_cfa = 0x0c
+        DW_CFA_def_cfa_register = 0x0d
+        DW_CFA_def_cfa_offset = 0x0e
+        /* DWARF 3.  */
+        DW_CFA_def_cfa_expression = 0x0f
+        DW_CFA_expression = 0x10
+        DW_CFA_offset_extended_sf = 0x11
+        DW_CFA_def_cfa_sf = 0x12
+        DW_CFA_def_cfa_offset_sf = 0x13
+        DW_CFA_val_offset = 0x14
+        DW_CFA_val_offset_sf = 0x15
+        DW_CFA_val_expression = 0x16
+        /* SGI/MIPS specific.  */
+        DW_CFA_MIPS_advance_loc8 = 0x1d
+        /* GNU extensions.  */
+        DW_CFA_GNU_window_save = 0x2d
+        DW_CFA_GNU_args_size = 0x2e
+        DW_CFA_GNU_negative_offset_extended = 0x2f
+
+        ifdef([PPC],[
+         include(ppc-constants.s)
+         include(ppc-macros.s)
+	 include(ppc-uuo.s)
+        ])
+	ifdef([X86],[
+         include(x86-constants.s)
+         include(x86-macros.s)
+	 include(x86-uuo.s)
+	])
+
Index: /branches/new-random/lisp-kernel/lisp_globals.h
===================================================================
--- /branches/new-random/lisp-kernel/lisp_globals.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/lisp_globals.h	(revision 13309)
@@ -0,0 +1,146 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __lisp_globals__
+#define __lisp_globals__
+
+
+extern LispObj lisp_nil;
+
+#define GET_TCR (-1)		/* address of get_tcr() for callbacks */
+#define TCR_COUNT (-2)		/* next tcr's tcr_id */
+#define INTERRUPT_SIGNAL  (-3)  /* signal to use for PROCESS-INTERRUPT */
+#define KERNEL_IMPORTS (-4)	/* some things we need to have imported for us. */
+#define OBJC_2_PERSONALITY (-5) /* A good listener.  Doesn't say much */
+#define SAVETOC (-6)	        /* Saved TOC register, for some platforms */
+#define SAVER13 (-7)		/* Saved (global) r13, on some platforms */
+#define SUBPRIMS_BASE (-8)	/* where the dynamic subprims wound up */
+#define RET1VALN (-9)		/* magic multiple-values return address */
+#define TCR_KEY (-10)     	/* tsd key for per-thread tcr */
+#define TCR_AREA_LOCK (-11)       /* all_areas/tcr queue lock */
+#define EXCEPTION_LOCK (-12)	/* serialize exception handling */
+#define STATIC_CONSES (-13)
+#define DEFAULT_ALLOCATION_QUANTUM (-14)
+#define INTFLAG (-15)
+#define GC_INHIBIT_COUNT (-16)
+#define REFBITS (-17)
+#define OLDSPACE_DNODE_COUNT (-18) /* count of dynamic dnodes older than generation 0 */
+#define ALTIVEC_PRESENT (-19)   /* non-zero if AltiVec present. */
+#define FWDNUM (-20)            /* fixnum: GC "forwarder" call count. */
+#define GC_NUM (-21)            /* fixnum: GC call count. */
+#define GCABLE_POINTERS (-22)   /* linked-list of weak macptrs. */
+#define HEAP_START (-23)        /* start of lisp heap */
+#define HEAP_END (-24)          /* end of lisp heap */
+#define STATICALLY_LINKED (-25)        /* non-zero if -static */
+#define STACK_SIZE (-26)        /* from the command line */
+#define OBJC_2_BEGIN_CATCH (-27)  /* address of ObjC 2.0 objc_begin_catch() */
+#define KERNEL_PATH (-28)       /* real executable name */
+#define ALL_AREAS (-29)         /* doubly-linked list of stack & heap areas */
+#define LEXPR_RETURN (-30)      /* magic &lexpr cleanup code */
+#define LEXPR_RETURN1V (-31)    /* single-value &lexpr cleanup code */
+#define IN_GC (-32)             /* non-zero when lisp addresses may be invalid */
+#define FREE_STATIC_CONSES (-33)     /* length of freelist */
+#define OBJC_2_END_CACTCH (-34)          /* address of ObjC 2.0 objc_end_catch() */
+#define SHORT_FLOAT_ZERO (-35)  /* low half of 1.0d0 */
+#define DOUBLE_FLOAT_ONE (-36)  /* high half of 1.0d0 */
+#define STATIC_CONS_AREA (-37)	/* static_cons_area */
+#define LISP_EXIT_HOOK (-38)	/* install foreign exception handling */
+#define OLDEST_EPHEMERAL (-39)  /* doubleword address of oldest ephemeral object or 0 */
+#define TENURED_AREA (-40)      /* the tenured area */
+#define REF_BASE (-41)          /* start of oldest pointer-bearing area */
+#define ARGV (-42)              /* pointer to &argv[0] */
+#define HOST_PLATFORM (-43)	/* for platform-specific initialization */
+#define BATCH_FLAG (-44)	/* -b arg */
+#define UNWIND_RESUME (-45)	/* address of _Unwind_Resume from libobjc */
+#define WEAK_GC_METHOD (-46)	/* weak GC algorithm */
+#define IMAGE_NAME (-47)	/* --image-name arg */
+#define INITIAL_TCR (-48)	/* initial thread tcr */
+
+#define MIN_KERNEL_GLOBAL INITIAL_TCR
+
+/* These are only non-zero when an image is being saved or loaded */
+
+#if (WORD_SIZE==64)
+#define LISP_HEAP_THRESHOLD (-511)
+#define EGC_ENABLED (-510)
+#define G0_THRESHOLD (-509)
+#define G1_THRESHOLD (-508)
+#define G2_THRESHOLD (-507)
+#else
+#define LISP_HEAP_THRESHOLD (-1023)
+#define EGC_ENABLED (-1022)
+#define G0_THRESHOLD (-1021)
+#define G1_THRESHOLD (-1020)
+#define G2_THRESHOLD (-1019)
+#endif
+
+#ifdef PPC
+#ifdef PPC64
+#define lisp_global(g) (((LispObj *) (0x3000+(LOWMEM_BIAS)))[(g)])
+#define nrs_symbol(s) (((lispsymbol *) (0x3000+(LOWMEM_BIAS)))[(s)])
+#else
+#define lisp_global(g) (((LispObj *) (nil_value-fulltag_nil))[(g)])
+#define nrs_symbol(s) (((lispsymbol *) (nil_value+(8-fulltag_nil)+8))[(s)])
+#endif
+#endif
+
+#ifdef X8664
+#define lisp_global(g) (((LispObj *) (0x13000+(LOWMEM_BIAS)))[(g)])
+#define nrs_symbol(s) (((lispsymbol *) (0x13020+(LOWMEM_BIAS)))[(s)])
+#endif
+
+#ifdef X8632
+#define lisp_global(g) (((LispObj *) (0x13000+(LOWMEM_BIAS)))[(g)])
+#define nrs_symbol(s) (((lispsymbol *) (0x13008+(LOWMEM_BIAS)))[(s)])
+#endif
+
+#define nrs_T 				(nrs_symbol(0))		/* t */
+#define nrs_NILSYM			(nrs_symbol(1))		/* nil */
+#define nrs_ERRDISP			(nrs_symbol(2))		/* %err-disp */
+#define nrs_CMAIN			(nrs_symbol(3))		/* cmain */
+#define nrs_EVAL			(nrs_symbol(4))		/* eval */
+#define nrs_APPEVALFN			(nrs_symbol(5))		/* apply-evaluated-function */
+#define nrs_ERROR			(nrs_symbol(6))		/* error */
+#define nrs_DEFUN			(nrs_symbol(7))		/* %defun */
+#define nrs_DEFVAR			(nrs_symbol(8))		/* %defvar */
+#define nrs_DEFCONSTANT			(nrs_symbol(9))		/* %defconstant */
+#define nrs_MACRO			(nrs_symbol(10))	/* %macro */
+#define nrs_KERNELRESTART		(nrs_symbol(11))	/* %kernel-restart */
+#define nrs_PACKAGE			(nrs_symbol(12))	/* *package* */
+#define nrs_TOTAL_BYTES_FREED           (nrs_symbol(13))        /* *total-bytes-freed* */
+#define nrs_KALLOWOTHERKEYS		(nrs_symbol(14))	/* :allow-other-keys */
+#define nrs_TOPLCATCH			(nrs_symbol(15))	/* %toplevel-catch% */
+#define nrs_TOPLFUNC			(nrs_symbol(16))	/* %toplevel-function% */
+#define nrs_CALLBACKS			(nrs_symbol(17))	/* %pascal-functions% */
+#define nrs_ALLMETEREDFUNS		(nrs_symbol(18))	/* *all-metered-functions* */
+#define nrs_TOTAL_GC_MICROSECONDS       (nrs_symbol(19))        /* *total-gc-microseconds* */
+#define nrs_BUILTIN_FUNCTIONS           (nrs_symbol(20))        /* %builtin-functions% */
+#define nrs_UDF				(nrs_symbol(21))	/* %unbound-function% */
+#define nrs_INIT_MISC			(nrs_symbol(22))        /* %init-misc% */
+#define nrs_MACRO_CODE                  (nrs_symbol(23))        /* %macro-code% */
+#define nrs_CLOSURE_CODE		(nrs_symbol(24))        /* %closure-code% */
+#define nrs_NEW_GCABLE_PTR		(nrs_symbol(25))	/* %new-gcable-ptr */
+#define nrs_GC_EVENT_STATUS_BITS	(nrs_symbol(26))	/* *gc-event-status-bits* */
+#define nrs_POST_GC_HOOK		(nrs_symbol(27))	/* *post-gc-hook* */
+#define nrs_HANDLERS			(nrs_symbol(28))	/* %handlers% */
+#define nrs_ALL_PACKAGES		(nrs_symbol(29))	/* %all-packages% */
+#define nrs_KEYWORD_PACKAGE		(nrs_symbol(30))	/* *keyword-package* */
+#define nrs_FINALIZATION_ALIST		(nrs_symbol(31))	/* %finalization-alist% */
+#define nrs_FOREIGN_THREAD_CONTROL      (nrs_symbol(32))        /* %foreign-thread-control */
+#define num_nilreg_symbols 33
+#define nilreg_symbols_end ((BytePtr) &(nrs_symbol(num_nilreg_symbols)))
+#endif
Index: /branches/new-random/lisp-kernel/lispdcmd.c
===================================================================
--- /branches/new-random/lisp-kernel/lispdcmd.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/lispdcmd.c	(revision 13309)
@@ -0,0 +1,47 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+/*
+  MCL-PPC dcmd utilities.
+*/
+
+#include "lispdcmd.h"
+
+
+
+
+void
+display_buffer(char *buf)
+{
+  fprintf(dbgout, "%s\n", buf);
+}
+
+int
+Dprintf(const char *format, ...)
+{
+  char buf[512];
+  va_list args;
+  int res;
+
+  va_start(args, format);
+  res = vsnprintf(buf, sizeof(buf), format, args);
+  if (res >= 0) {
+    display_buffer(buf);
+  }
+  return res;
+}
+
Index: /branches/new-random/lisp-kernel/lispdcmd.h
===================================================================
--- /branches/new-random/lisp-kernel/lispdcmd.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/lispdcmd.h	(revision 13309)
@@ -0,0 +1,31 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "lisp.h"
+#include "area.h"
+#include "lisp-exceptions.h"
+#include "lisp_globals.h"
+
+/* More-or-less like c printf(); */
+int Dprintf(const char *format, ...);
+
+
+char *
+print_lisp_object(LispObj);
Index: /branches/new-random/lisp-kernel/lisptypes.h
===================================================================
--- /branches/new-random/lisp-kernel/lisptypes.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/lisptypes.h	(revision 13309)
@@ -0,0 +1,238 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __lisptypes__
+#define __lisptypes__
+
+#include <sys/types.h>
+#define WORD_SIZE 32
+#ifdef PPC64
+#undef WORD_SIZE
+#define WORD_SIZE 64
+#endif
+#ifdef X8664
+#undef WORD_SIZE
+#define WORD_SIZE 64
+#endif
+
+
+#ifdef WINDOWS
+#include <windows.h>
+typedef long long s64_t;
+typedef unsigned long long u64_t;
+typedef signed long s32_t;
+typedef unsigned long u32_t;
+typedef signed short s16_t;
+typedef unsigned short u16_t;
+typedef signed char s8_t;
+typedef unsigned char u8_t;
+#else
+
+#include <stdint.h>
+
+#ifdef SOLARIS
+/* Solaris doesn't laugh and play like the other children */
+typedef int64_t s64_t;
+typedef uint64_t u64_t;
+typedef int32_t s32_t;
+typedef uint32_t u32_t;
+typedef int16_t s16_t;
+typedef uint16_t u16_t;
+typedef int8_t s8_t;
+typedef uint8_t u8_t;
+#else
+typedef int64_t s64_t;
+typedef u_int64_t u64_t;
+typedef int32_t s32_t;
+typedef u_int32_t u32_t;
+typedef int16_t s16_t;
+typedef u_int16_t u16_t;
+typedef int8_t s8_t;
+typedef u_int8_t u8_t;
+#endif
+#endif
+
+#if WORD_SIZE == 64
+typedef u64_t LispObj;
+typedef u64_t natural;
+typedef s64_t signed_natural;
+typedef u64_t unsigned_of_pointer_size;
+#else
+typedef u32_t LispObj;
+typedef u32_t natural;
+typedef s32_t signed_natural;
+typedef u32_t unsigned_of_pointer_size;
+#endif
+
+
+#ifdef DARWIN
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+#include <AvailabilityMacros.h>
+
+#ifdef PPC
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#define __ss ss
+#define __es es
+#define __fs fs
+
+#define __srr0 srr0
+#define __srr1 srr1
+#define __r0 r0
+#define __r1 r1
+#define __r3 r3
+#define __r4 r4
+#define __r5 r5
+#define __r6 r6
+#define __r13 r13
+#define __cr cr
+#define __xer xer
+#define __lr lr
+#define __ctr ctr
+
+#define __dar dar
+#define __dsisr dsisr
+#define __exception exception
+
+#define __fpregs fpregs
+#define __fpscr fpscr
+#endif
+
+#if WORD_SIZE == 64
+#ifdef _STRUCT_UCONTEXT64
+typedef _STRUCT_UCONTEXT64 ExceptionInformation;
+typedef _STRUCT_MCONTEXT64 *MCONTEXT_T;
+#else /* _STRUCT_UCONTEXT64 */
+typedef struct ucontext64 ExceptionInformation;
+typedef struct mcontext64 *MCONTEXT_T;
+#endif /* _STRUCT_UCONTEXT64 */
+#define UC_MCONTEXT(UC) UC->uc_mcontext64
+#else /* WORD_SIZE */
+#ifdef _STRUCT_UCONTEXT
+typedef _STRUCT_UCONTEXT ExceptionInformation;
+typedef _STRUCT_MCONTEXT *MCONTEXT_T;
+#else
+typedef struct ucontext ExceptionInformation;
+typedef struct mcontext *MCONTEXT_T;
+#endif
+#define UC_MCONTEXT(UC) UC->uc_mcontext
+#endif /* WORD_SIZE */
+
+
+
+#endif /* PPC */
+
+#ifdef X8664
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+/* Broken <i386/ucontext.h> in Mac OS 10.4u SDK */
+struct mcontext64 {
+	x86_exception_state64_t	__es;
+	x86_thread_state64_t 	__ss;	
+	x86_float_state64_t	__fs;
+};
+
+typedef struct mcontext64 *MCONTEXT_T;
+typedef ucontext64_t ExceptionInformation;
+#define UC_MCONTEXT(UC) UC->uc_mcontext64
+#define __rax rax
+#define __fpu_mxcsr fpu_mxcsr
+#define __fpu_xmm0 fpu_xmm0
+#define __rsp rsp
+#define __trapno trapno
+#define __faultvaddr faultvaddr
+#define __err err
+#define __rip rip
+#define __rsi rsi
+#define __rdi rdi
+#define __rdx rdx
+#define __rcx rcx
+#define __r8 r8
+#define __rflags rflags
+#else /* post-10.4 */
+typedef mcontext_t MCONTEXT_T;
+typedef ucontext_t ExceptionInformation;
+#define UC_MCONTEXT(UC) UC->uc_mcontext
+#endif
+#endif
+
+#ifdef X8632
+/* Assume rational <i386/ucontext.h> */
+/* Sadly, we can't make that assumption, since Apple renamed things
+   for Leopard. Yow!  Are we standards-compliant yet ? */
+/* In the long term, we probably want to use the leopard-compliant
+   names (with leading __ prefixes).  In the shorter term, we want
+   kernels compiled on Leopard to run on Tiger (and not reference
+   foo$UNIX2003 and similar nonsense, and that means getting the old
+   names (without leading __ prefixes.)  Confused yet ? */
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#define __ss ss
+#define __ds ds
+#define __es es
+#define __cs cs
+#define __fs fs
+#define __gs gs
+#define __eax eax
+#define __esp esp
+#define __eip eip
+#define __eflags eflags
+#define __fpu_xmm0 fpu_xmm0
+#define __fpu_mxcsr fpu_mxcsr
+#define __fpu_stmm0 fpu_stmm0
+#define __trapno trapno
+#define __err err
+#define __faultvaddr faultvaddr
+#endif
+
+#define UC_MCONTEXT(UC) UC->uc_mcontext
+typedef mcontext_t MCONTEXT_T;
+typedef ucontext_t ExceptionInformation;
+#endif
+
+#endif /* #ifdef DARWIN */
+
+#ifdef LINUX
+typedef struct ucontext ExceptionInformation;
+#endif
+
+#ifdef FREEBSD
+typedef struct __ucontext ExceptionInformation;
+#endif
+
+#ifdef SOLARIS
+typedef struct ucontext ExceptionInformation;
+#endif
+
+#ifdef WINDOWS
+typedef CONTEXT ExceptionInformation;
+#endif
+
+typedef u32_t lisp_char_code;
+
+typedef int OSStatus, OSErr;
+#define noErr ((OSErr) 0)
+typedef int Boolean;
+typedef void *LogicalAddress;
+typedef char *Ptr, *BytePtr, *StringPtr;
+typedef unsigned int UInt32;
+
+
+
+#define true 1
+#define false 0
+
+#endif /*__lisptypes__ */
Index: /branches/new-random/lisp-kernel/m4macros.m4
===================================================================
--- /branches/new-random/lisp-kernel/m4macros.m4	(revision 13309)
+++ /branches/new-random/lisp-kernel/m4macros.m4	(revision 13309)
@@ -0,0 +1,354 @@
+changequote([,])
+changecom([/* ],[*/])
+
+
+
+/*   Copyright (C) 1994-2001 Digitool, Inc  */
+/*   This file is part of Clozure CL.    */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public  */
+/*   License , known as the LLGPL and distributed with Clozure CL as the  */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these  */
+/*   conflict, the preamble takes precedence.    */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."  */
+
+/*   The LLGPL is also available online at  */
+/*   http://opensource.franz.com/preamble.html  */
+
+
+
+/*  BSD debugging information (line numbers, etc) is a little different  */
+/*  from ELF/SVr4 debugging information.  There are probably lots more  */
+/*  differences, but this helps us to distinguish between what LinuxPPC  */
+/*  (ELF/SVr4) wants and what Darwin(BSD) wants.  */
+
+
+define([BSDstabs],[1])
+define([ELFstabs],[2])
+define([COFFstabs],[3])
+undefine([EABI])
+undefine([POWEROPENABI])
+undefine([rTOC])
+
+
+ifdef([DARWIN],[define([SYSstabs],[BSDstabs])
+		define([DarwinAssembler],[])
+                define([CNamesNeedUnderscores],[])
+	        define([LocalLabelPrefix],[L])
+	        define([StartTextLabel],[Ltext0])
+	        define([EndTextLabel],[Letext])
+                ifdef([PPC],[
+		define([POWEROPENABI],[])])
+                ifdef([X86],[
+                define([SYSCALL_SETS_CARRY_ON_ERROR],[])
+		define([SSE2_MATH_LIB],[])])
+])
+
+ifdef([LINUX],[define([SYSstabs],[ELFstabs])
+	       define([HaveWeakSymbols],[])
+	       define([LocalLabelPrefix],[.L])
+	       define([StartTextLabel],[.Ltext0])
+	       define([EndTextLabel],[.Letext])
+               ifdef([PPC64],[
+               define([POWEROPENABI],[])
+               define([rTOC],[r2])], [
+	       define([EABI],[])])])
+
+ifdef([FREEBSD],[define([SYSstabs],[ELFstabs])
+	       define([HaveWeakSymbols],[])
+	       define([LocalLabelPrefix],[.L])
+	       define([StartTextLabel],[.Ltext0])
+	       define([EndTextLabel],[.Letext])]
+                ifdef([X86],[
+                define([SYSCALL_SETS_CARRY_ON_ERROR],[])])
+)
+
+ifdef([SOLARIS],[define([SYSstabs],[ELFstabs])
+	       define([HaveWeakSymbols],[])
+	       define([LocalLabelPrefix],[.L])
+	       define([StartTextLabel],[.Ltext0])
+	       define([EndTextLabel],[.Letext])])
+
+ifdef([WINDOWS],[define([SYSstabs],[COFFstabs])
+               define([CNamesNeedUnderscores],[])
+               define([LocalLabelPrefix],[L])
+	       define([StartTextLabel],[Ltext0])
+	       define([EndTextLabel],[Letext])])
+
+
+/*  Names exported to (or imported from) C may need leading underscores.  */
+/*  Still.  After all these years.  Why ?  */
+
+define([C],[ifdef([CNamesNeedUnderscores],[[_]$1],[$1])])
+
+define([_linecounter_],0)
+
+define([_emit_BSD_source_line_stab],[
+ifdef([X86],[
+# __line__ "__file__" 1],[
+	.stabd 68,0,$1
+])])
+
+
+/*  We don't really do "weak importing" of symbols from a separate  */
+/*  subprims library anymore; if we ever do and the OS supports it,  */
+/*  here's how to say that we want it ...  */
+
+define([WEAK],[ifdef([HaveWeakSymbols],[
+	.weak $1
+],[
+	.globl $1
+])])
+
+define([_emit_ELF_source_line_stab],[
+  define([_linecounter_],incr(_linecounter_))
+	.stabn 68,0,$1,[.LM]_linecounter_[-]__func_name
+[.LM]_linecounter_:
+])
+
+define([_emit_COFF_source_line_stab],[
+        _emit_ELF_source_line_stab($1)
+])
+
+
+define([emit_source_line_stab],[
+	ifelse(eval(SYSstabs),
+             eval(BSDstabs),
+  	      [_emit_BSD_source_line_stab($1)],
+              eval(SYSstabs),
+              eval(ELFstabs),
+              [_emit_ELF_source_line_stab($1)],
+              [_emit_COFF_source_line_stab($1)])])
+
+
+
+
+
+
+/*  Assemble a reference to the high half of a 32-bit constant,  */
+/*  possibly adjusted for sign-extension of thw low half.  */
+
+
+define([HA],[ifdef([DARWIN],[ha16($1)],[$1@ha])])
+
+ 
+/*  Likewise for the low half, and for the high half without  */
+/*  concern for sign-extension of the low half.  */
+
+define([LO],[ifdef([DARWIN],[lo16($1)],[$1@l])])
+define([HI],[ifdef([DARWIN],[hi16($1)],[$1@hi])])
+
+/*  Note that m4 macros that could be expanded in the .text segment  */
+/*  need to advertise the current line number after they have finished  */
+/*  expanding.  That shouldn't be too onerous, if only because there  */
+/*  should not be too many of them.  */
+
+
+define([N_FUN],36)
+define([N_SO],100)
+
+/*    I wish that there was a less-dumb way of doing this.  */
+
+define([pwd0],esyscmd([/bin/pwd]))
+define([__pwd__],substr(pwd0,0,decr(len(pwd0)))[/])
+
+/*   _beginfile() -- gets line/file in synch, generates N_SO for file,  */
+/*   starts .text section  */
+
+
+define([_beginfile],[
+	.stabs "__pwd__",N_SO,0,0,StartTextLabel()
+	.stabs "__file__",N_SO,0,0,StartTextLabel()
+ifdef([PPC64],[
+ifdef([DARWIN],[
+        .machine ppc64
+])])
+	.text
+StartTextLabel():
+# __line__ "__file__"
+])
+
+define([_endfile],[
+	.stabs "",N_SO,0,0,EndTextLabel()
+EndTextLabel():
+# __line__
+])
+
+define([_startfn],[define([__func_name],$1)
+# __line__
+	ifelse(eval(SYSstabs),eval(ELFstabs),[
+	.type $1,@function
+])
+
+$1:
+ifdef([WINDOWS],[
+	.def	$1;	.scl	2;	.type	32;	.endef
+],[
+        .stabd 68,0,__line__
+])
+	.stabs "$1:F1",36,0,__line__,$1
+	.set func_start,$1
+# __line__ "__file__" 1 ])
+
+
+
+define([_exportfn],[
+	.globl $1
+	_startfn($1)
+ifdef([PPC64],[
+ifdef([LINUX],[
+        .global [.]$1
+[.]$1:
+])])
+# __line__
+])
+
+
+define([_endfn],[
+LocalLabelPrefix[]__func_name[999]:
+ifdef([WINDOWS],[
+],[
+	.stabs "",36,0,0,LocalLabelPrefix[]__func_name[999]-__func_name
+	.line __line__
+	ifelse(eval(SYSstabs),eval(ELFstabs),[
+        .size __func_name,LocalLabelPrefix[]__func_name[999]-__func_name
+])
+])
+	undefine([__func_name])
+])
+
+
+/* _struct(name,start_offset)  */
+/*   This just generates a bunch of assembler equates; m4  */
+/*   doesn't remember much of it ..  */
+
+define([_struct], [define([__struct_name],$1)
+ define([_struct_org_name], _$1_org) 
+ define([_struct_base_name], _$1_base)
+	.set _struct_org_name,$2
+	.set _struct_base_name,_struct_org_name
+ ifelse($3,[],[
+  undefine([_struct_fixed_size_name])
+  ],[
+  define([_struct_fixed_size_name], _$1_fixed_size)
+	.set _struct_fixed_size_name,$3
+  ])
+])
+
+define([_struct_pad],[
+	.set _struct_org_name,_struct_org_name + $1
+])
+ 
+define([_struct_label],[
+	.set __struct_name[.]$1, _struct_org_name
+])
+
+/*  _field(name,size)   */
+define([_field],[_struct_label($1) _struct_pad($2)])
+
+define([_halfword], [_field($1, 2)])
+define([_word], [_field($1, 4)])
+define([_dword],[_field($1, 8)])
+define([_node], [_field($1, node_size)])
+
+define([_ends],[ifdef([_struct_fixed_size_name],[
+	.set  __struct_name[.size],_struct_fixed_size_name
+	],[
+	.set  __struct_name[.size], _struct_org_name-_struct_base_name
+	])
+])
+
+
+/*   Lisp fixed-size objects always have a 1-word header  */
+/*   and are always accessed from a "fulltag_misc"-tagged pointer.  */
+/*   We also want to define STRUCT_NAME.element_count for each  */
+/*   such object.  */
+
+
+define([_structf],[
+	_struct($1,ifelse($2,[],-misc_bias,$2))
+        _node(header)
+])
+
+define([_endstructf],[
+	.set __struct_name.[element_count],((_struct_org_name-node_size)-_struct_base_name)/node_size
+	_ends
+])
+
+
+define([__],[emit_source_line_stab(__line__)
+	$@
+	])
+
+define([__local_label_counter__],0)
+define([__macro_label_counter__],0)
+
+define([new_local_labels],
+  [define([__local_label_counter__],incr(__local_label_counter__))])
+
+define([new_macro_labels],
+  [define([__macro_label_counter__],incr(__macro_label_counter__))])
+
+define([_local_label],[LocalLabelPrefix()[]$1])
+
+define([local_label],[_local_label($1[]__local_label_counter__)])
+
+define([macro_label],[_local_label($1[]__macro_label_counter__)])
+
+
+/* The Darwin assembler doesn't seem to support .ifdef/.ifndef, but  */
+/* does understand .if.    */
+/* Note that using M4's own ifdef is certainly possible, but it's  */
+/* hard to generate source line information when doing so.  */
+
+  
+define([__ifdef],[ifdef([$1],[.if 1],[.if 0])])
+define([__ifndef],[ifdef([$1],[.if 0],[.if 1])])
+define([__else],[.else])
+define([__endif],[.endif])
+define([__if],[.if $1])
+
+define([equate_if_defined],[ifdef($1,[
+[$1] = 1
+],[
+[$1] = 0
+])])
+
+equate_if_defined([DARWIN])
+equate_if_defined([LINUX])
+equate_if_defined([FREEBSD])
+equate_if_defined([SOLARIS])
+equate_if_defined([WIN_64])
+equate_if_defined([PPC64])
+equate_if_defined([X8664])
+equate_if_defined([WIN_32])
+equate_if_defined([WINDOWS])
+
+equate_if_defined([HAVE_TLS])
+/* DARWIN_GS_HACK is hopefully short-lived */
+equate_if_defined([DARWIN_GS_HACK])
+
+equate_if_defined([TCR_IN_GPR])
+
+/* Well, so much for that. Maybe this will go away soon ? */
+equate_if_defined([WIN32_ES_HACK])
+equate_if_defined([SYSCALL_SETS_CARRY_ON_ERROR])
+
+
+
+/* We use (more-or-less) a PowerOpen C frame, except on LinuxPPC32  */
+
+define([USE_POWEROPEN_C_FRAME],[])
+undefine([USE_EABI_C_FRAME])
+
+ifdef([LINUX],[
+ifdef([PPC64],[],[
+define([USE_EABI_C_FRAME],[])
+undefine([USE_POWEROPEN_C_FRAME])
+])])
+
+
+
+
Index: /branches/new-random/lisp-kernel/macros.h
===================================================================
--- /branches/new-random/lisp-kernel/macros.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/macros.h	(revision 13309)
@@ -0,0 +1,116 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+/* Totally different content than 'macros.s' */
+
+
+
+#ifndef __macros__
+#define __macros__
+
+#define ptr_to_lispobj(p) ((LispObj)(p))
+#define ptr_from_lispobj(o) ((LispObj*)(o))
+#define lisp_reg_p(reg)  ((reg) >= fn)
+
+#define fulltag_of(o)  ((o) & fulltagmask)
+#define tag_of(o) ((o) & tagmask)
+#define untag(o) ((o) & ~fulltagmask)
+#define node_aligned(o) ((o) & ~tagmask)
+#define indirect_node(o) (*(LispObj *)(node_aligned(o)))
+
+#define deref(o,n) ((((LispObj*) (untag((LispObj)o))))[(n)])
+#define header_of(o) deref(o,0)
+
+#define header_subtag(h) ((h) & subtagmask)
+#define header_element_count(h) ((h) >> num_subtag_bits)
+#define make_header(subtag,element_count) ((subtag)|((element_count)<<num_subtag_bits))
+
+#define unbox_fixnum(x) ((signed_natural)(((signed_natural)(x))>>fixnum_shift))
+#define box_fixnum(x) ((LispObj)((signed_natural)(x)<<fixnum_shift))
+
+#define car(x) (((cons *)ptr_from_lispobj(untag(x)))->car)
+#define cdr(x) (((cons *)ptr_from_lispobj(untag(x)))->cdr)
+
+/* "sym" is an untagged pointer to a symbol */
+#define BOUNDP(sym)  ((((lispsymbol *)(sym))->vcell) != undefined)
+
+/* Likewise. */
+#define FBOUNDP(sym) ((((lispsymbol *)(sym))->fcell) != nrs_UDF.vcell)
+
+#ifdef PPC
+#ifdef PPC64
+#define nodeheader_tag_p(tag) (((tag) & lowtag_mask) == lowtag_nodeheader)
+#define immheader_tag_p(tag) (((tag) & lowtag_mask) == lowtag_immheader)
+#else
+#define nodeheader_tag_p(tag) (tag == fulltag_nodeheader)
+#define immheader_tag_p(tag) (tag == fulltag_immheader)
+#endif
+#endif
+
+#ifdef X86
+#ifdef X8664
+#define NODEHEADER_MASK ((1<<(fulltag_nodeheader_0)) | \
+			 (1<<(fulltag_nodeheader_1)))
+#define nodeheader_tag_p(tag) ((1<<(tag)) &  NODEHEADER_MASK)
+
+#define IMMHEADER_MASK ((1<<fulltag_immheader_0) | \
+			(1UL<<fulltag_immheader_1) |			\
+			(1UL<<fulltag_immheader_2))
+
+#define immheader_tag_p(tag) ((1<<(tag)) & IMMHEADER_MASK)
+#else
+#define nodeheader_tag_p(tag) (tag == fulltag_nodeheader)
+#define immheader_tag_p(tag) (tag == fulltag_immheader)
+#endif
+#endif
+
+#ifdef VC
+#define inline
+#define __attribute__(x)
+#endif
+
+/* lfuns */
+#define lfun_bits(f) (deref(f,header_element_count(header_of(f))))
+#define named_function_p(f) (!(lfun_bits(f)&(1<<(29+fixnum_shift))))
+#define named_function_name(f) (deref(f,-1+header_element_count(header_of(f))))
+
+#define TCR_INTERRUPT_LEVEL(tcr) \
+  (((signed_natural *)((tcr)->tlb_pointer))[INTERRUPT_LEVEL_BINDING_INDEX])
+#endif
+
+#ifdef WINDOWS
+#define LSEEK(fd,offset,how) _lseeki64(fd,offset,how)
+#else
+#define LSEEK(fd,offset,how) lseek(fd,offset,how)
+#endif
+
+/* We can't easily and unconditionally use format strings like "0x%lx"
+   to print lisp objects: the "l" might not match the word size, and
+   neither would (necessarily) something like "0x%llx".  We can at 
+   least exploit the fact that on all current platforms, "ll" ("long long")
+   is the size of a 64-bit lisp object and "l" ("long") is the size of
+   a 32-bit lisp object. */
+
+#if (WORD_SIZE == 64)
+#define LISP "%llx"
+#define ZLISP "%016llx"
+#define DECIMAL "%lld"
+#else
+#define LISP "%lx"
+#define ZLISP "%08x"
+#define DECIMAL "%ld"
+#endif
Index: /branches/new-random/lisp-kernel/memory.c
===================================================================
--- /branches/new-random/lisp-kernel/memory.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/memory.c	(revision 13309)
@@ -0,0 +1,980 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp-exceptions.h"
+#include "lisp_globals.h"
+#include "Threads.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef LINUX
+#include <strings.h>
+#include <fpu_control.h>
+#include <linux/prctl.h>
+#endif
+
+#ifndef WINDOWS
+#include <sys/mman.h>
+#endif
+
+#define DEBUG_MEMORY 0
+
+void
+allocation_failure(Boolean pointerp, natural size)
+{
+  char buf[64];
+  sprintf(buf, "Can't allocate %s of size " DECIMAL " bytes.", pointerp ? "pointer" : "handle", size);
+  Fatal(":   Kernel memory allocation failure.  ", buf);
+}
+
+void
+fatal_oserr(StringPtr param, OSErr err)
+{
+  char buf[64];
+  sprintf(buf," - operating system error %d.", err);
+  Fatal(param, buf);
+}
+
+
+Ptr
+allocate(natural size)
+{
+  return (Ptr) malloc(size);
+}
+
+void
+deallocate(Ptr p)
+{
+  free((void *)p);
+}
+
+Ptr
+zalloc(natural size)
+{
+  Ptr p = allocate(size);
+  if (p != NULL) {
+    memset(p, 0, size);
+  }
+  return p;
+}
+
+#ifdef DARWIN
+#if WORD_SIZE == 64
+#define vm_region vm_region_64
+#endif
+
+/*
+  Check to see if the specified address is unmapped by trying to get
+  information about the mapped address at or beyond the target.  If
+  the difference between the target address and the next mapped address
+  is >= len, we can safely mmap len bytes at addr.
+*/
+Boolean
+address_unmapped_p(char *addr, natural len)
+{
+  vm_address_t vm_addr = (vm_address_t)addr;
+  vm_size_t vm_size;
+#if WORD_SIZE == 64
+  vm_region_basic_info_data_64_t vm_info;
+#else
+  vm_region_basic_info_data_t vm_info;
+#endif
+#if WORD_SIZE == 64
+  mach_msg_type_number_t vm_info_size = VM_REGION_BASIC_INFO_COUNT_64;
+#else
+  mach_msg_type_number_t vm_info_size = VM_REGION_BASIC_INFO_COUNT;
+#endif
+  mach_port_t vm_object_name = (mach_port_t) 0;
+  kern_return_t kret;
+
+  kret = vm_region(mach_task_self(),
+		   &vm_addr,
+		   &vm_size,
+#if WORD_SIZE == 64
+                   VM_REGION_BASIC_INFO_64,
+#else
+		   VM_REGION_BASIC_INFO,
+#endif
+		   (vm_region_info_t)&vm_info,
+		   &vm_info_size,
+		   &vm_object_name);
+  if (kret != KERN_SUCCESS) {
+    return false;
+  }
+
+  return vm_addr >= (vm_address_t)(addr+len);
+}
+#endif
+
+
+  /*
+    Through trial and error, we've found that IMAGE_BASE_ADDRESS is
+    likely to reside near the beginning of an unmapped block of memory
+    that's at least 1GB in size.  We'd like to load the heap image's
+    sections relative to IMAGE_BASE_ADDRESS; if we're able to do so,
+    that'd allow us to file-map those sections (and would enable us to
+    avoid having to relocate references in the data sections.)
+
+    In short, we'd like to reserve 1GB starting at IMAGE_BASE_ADDRESS
+    by creating an anonymous mapping with mmap().
+
+    If we try to insist that mmap() map a 1GB block at
+    IMAGE_BASE_ADDRESS exactly (by specifying the MAP_FIXED flag),
+    mmap() will gleefully clobber any mapped memory that's already
+    there.  (That region's empty at this writing, but some future
+    version of the OS might decide to put something there.)
+
+    If we don't specify MAP_FIXED, mmap() is free to treat the address
+    we give it as a hint; Linux seems to accept the hint if doing so
+    wouldn't cause a problem.  Naturally, that behavior's too useful
+    for Darwin (or perhaps too inconvenient for it): it'll often
+    return another address, even if the hint would have worked fine.
+
+    We call address_unmapped_p() to ask Mach whether using MAP_FIXED
+    would conflict with anything.  Until we discover a need to do 
+    otherwise, we'll assume that if Linux's mmap() fails to take the
+    hint, it's because of a legitimate conflict.
+
+    If Linux starts ignoring hints, we can parse /proc/<pid>/maps
+    to implement an address_unmapped_p() for Linux.
+  */
+
+LogicalAddress
+ReserveMemoryForHeap(LogicalAddress want, natural totalsize)
+{
+  LogicalAddress start;
+  Boolean fixed_map_ok = false;
+#ifdef DARWIN
+  fixed_map_ok = address_unmapped_p(want,totalsize);
+#endif
+#ifdef SOLARIS
+  fixed_map_ok = true;
+#endif
+  raise_limit();
+#ifdef WINDOWS
+  start = VirtualAlloc((void *)want,
+		       totalsize + heap_segment_size,
+		       MEM_RESERVE,
+		       PAGE_NOACCESS);
+  if (!start) {
+#if DEBUG_MEMORY    
+    fprintf(dbgout, "Can't get desired heap address at 0x" LISP "\n", want);
+#endif
+    start = VirtualAlloc(0,
+			 totalsize + heap_segment_size,
+			 MEM_RESERVE,
+			 PAGE_NOACCESS);
+    if (!start) {
+      return NULL;
+    }
+  }
+#else
+  start = mmap((void *)want,
+	       totalsize + heap_segment_size,
+	       PROT_NONE,
+	       MAP_PRIVATE | MAP_ANON | (fixed_map_ok ? MAP_FIXED : 0) | MAP_NORESERVE,
+	       -1,
+	       0);
+  if (start == MAP_FAILED) {
+    return NULL;
+  }
+
+  if (start != want) {
+    munmap(start, totalsize+heap_segment_size);
+    start = (void *)((((natural)start)+heap_segment_size-1) & ~(heap_segment_size-1));
+    if(mmap(start, totalsize, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, -1, 0) != start) {
+      return NULL;
+    }
+  }
+  mprotect(start, totalsize, PROT_NONE);
+#endif
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Reserving heap at 0x" LISP ", size 0x" LISP "\n", start, totalsize);
+#endif
+  return start;
+}
+
+int
+CommitMemory (LogicalAddress start, natural len) 
+{
+  LogicalAddress rc;
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Committing memory at 0x" LISP ", size 0x" LISP "\n", start, len);
+#endif
+#ifdef WINDOWS
+  if ((start < ((LogicalAddress)nil_value)) &&
+      (((LogicalAddress)nil_value) < (start+len))) {
+    /* nil area is in the executable on Windows; ensure range is
+       read-write */
+    DWORD as_if_i_care;
+    if (!VirtualProtect(start,len,PAGE_EXECUTE_READWRITE,&as_if_i_care)) {
+      return false;
+    }
+    return true;
+  }
+  rc = VirtualAlloc(start, len, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+  if (!rc) {
+    wperror("CommitMemory VirtualAlloc");
+    return false;
+  }
+  return true;
+#else
+  int i, err;
+  void *addr;
+
+  for (i = 0; i < 3; i++) {
+    addr = mmap(start, len, MEMPROTECT_RWX, MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
+    if (addr == start) {
+      return true;
+    } else {
+      mmap(addr, len, MEMPROTECT_NONE, MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
+    }
+  }
+  return false;
+#endif
+}
+
+void
+UnCommitMemory (LogicalAddress start, natural len) {
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Uncommitting memory at 0x" LISP ", size 0x" LISP "\n", start, len);
+#endif
+#ifdef WINDOWS
+  int rc = VirtualFree(start, len, MEM_DECOMMIT);
+  if (!rc) {
+    wperror("UnCommitMemory VirtualFree");
+    Fatal("mmap error", "");
+    return;
+  }
+#else
+  if (len) {
+    madvise(start, len, MADV_DONTNEED);
+    if (mmap(start, len, MEMPROTECT_NONE, MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0)
+	!= start) {
+      int err = errno;
+      Fatal("mmap error", "");
+      fprintf(dbgout, "errno = %d", err);
+    }
+  }
+#endif
+}
+
+
+LogicalAddress
+MapMemory(LogicalAddress addr, natural nbytes, int protection)
+{
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Mapping memory at 0x" LISP ", size 0x" LISP "\n", addr, nbytes);
+#endif
+#ifdef WINDOWS
+  return VirtualAlloc(addr, nbytes, MEM_RESERVE|MEM_COMMIT, MEMPROTECT_RWX);
+#else
+  {
+    int flags = MAP_PRIVATE|MAP_ANON;
+
+    if (addr > 0) flags |= MAP_FIXED;
+    return mmap(addr, nbytes, protection, flags, -1, 0);
+  }
+#endif
+}
+
+LogicalAddress
+MapMemoryForStack(natural nbytes)
+{
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Mapping stack of size 0x" LISP "\n", nbytes);
+#endif
+#ifdef WINDOWS
+  return VirtualAlloc(0, nbytes, MEM_RESERVE|MEM_COMMIT, MEMPROTECT_RWX);
+#else
+  return mmap(NULL, nbytes, MEMPROTECT_RWX, MAP_PRIVATE|MAP_ANON|MAP_GROWSDOWN, -1, 0);
+#endif
+}
+
+int
+UnMapMemory(LogicalAddress addr, natural nbytes)
+{
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Unmapping memory at 0x" LISP ", size 0x" LISP "\n", addr, nbytes);
+#endif
+#ifdef WINDOWS
+  /* Can't MEM_RELEASE here because we only want to free a chunk */
+  return VirtualFree(addr, nbytes, MEM_DECOMMIT);
+#else
+  return munmap(addr, nbytes);
+#endif
+}
+
+int
+ProtectMemory(LogicalAddress addr, natural nbytes)
+{
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Protecting memory at 0x" LISP ", size 0x" LISP "\n", addr, nbytes);
+#endif
+#ifdef WINDOWS
+  DWORD oldProtect;
+  BOOL status = VirtualProtect(addr, nbytes, MEMPROTECT_RX, &oldProtect);
+  
+  if(!status) {
+    wperror("ProtectMemory VirtualProtect");
+    Bug(NULL, "couldn't protect " DECIMAL " bytes at 0x" LISP ", errno = %d", nbytes, addr, status);
+  }
+  return status;
+#else
+  int status = mprotect(addr, nbytes, PROT_READ | PROT_EXEC);
+  
+  if (status) {
+    status = errno;
+    Bug(NULL, "couldn't protect " DECIMAL " bytes at " LISP ", errno = %d", nbytes, addr, status);
+  }
+  return status;
+#endif
+}
+
+int
+UnProtectMemory(LogicalAddress addr, natural nbytes)
+{
+#if DEBUG_MEMORY
+  fprintf(dbgout, "Unprotecting memory at 0x" LISP ", size 0x" LISP "\n", addr, nbytes);
+#endif
+#ifdef WINDOWS
+  DWORD oldProtect;
+  return VirtualProtect(addr, nbytes, MEMPROTECT_RWX, &oldProtect);
+#else
+  return mprotect(addr, nbytes, PROT_READ|PROT_WRITE|PROT_EXEC);
+#endif
+}
+
+int
+MapFile(LogicalAddress addr, natural pos, natural nbytes, int permissions, int fd) 
+{
+#ifdef WINDOWS
+#if 0
+  /* Lots of hair in here: mostly alignment issues, but also address space reservation */
+  HANDLE hFile, hFileMapping;
+  LPVOID rc;
+  DWORD desiredAccess;
+
+  if (permissions == MEMPROTECT_RWX) {
+    permissions |= PAGE_WRITECOPY;
+    desiredAccess = FILE_MAP_READ|FILE_MAP_WRITE|FILE_MAP_COPY|FILE_MAP_EXECUTE;
+  } else {
+    desiredAccess = FILE_MAP_READ|FILE_MAP_COPY|FILE_MAP_EXECUTE;
+  }
+
+  hFile = _get_osfhandle(fd);
+  hFileMapping = CreateFileMapping(hFile, NULL, permissions,
+				   (nbytes >> 32), (nbytes & 0xffffffff), NULL);
+  
+  if (!hFileMapping) {
+    wperror("CreateFileMapping");
+    return false;
+  }
+
+  rc = MapViewOfFileEx(hFileMapping,
+		       desiredAccess,
+		       (pos >> 32),
+		       (pos & 0xffffffff),
+		       nbytes,
+		       addr);
+#else
+  size_t count, total = 0;
+  size_t opos;
+
+  opos = LSEEK(fd, 0, SEEK_CUR);
+  CommitMemory(addr, nbytes);
+  LSEEK(fd, pos, SEEK_SET);
+
+  while (total < nbytes) {
+    count = read(fd, addr + total, nbytes - total);
+    total += count;
+    // fprintf(dbgout, "read " DECIMAL " bytes, for a total of " DECIMAL " out of " DECIMAL " so far\n", count, total, nbytes);
+    if (!(count > 0))
+      return false;
+  }
+
+  LSEEK(fd, opos, SEEK_SET);
+
+  return true;
+#endif
+#else
+  return mmap(addr, nbytes, permissions, MAP_PRIVATE|MAP_FIXED, fd, pos) != MAP_FAILED;
+#endif
+}
+
+void
+unprotect_area(protected_area_ptr p)
+{
+  BytePtr start = p->start;
+  natural nprot = p->nprot;
+  
+  if (nprot) {
+    UnProtectMemory(start, nprot);
+    p->nprot = 0;
+  }
+}
+
+protected_area_ptr
+new_protected_area(BytePtr start, BytePtr end, lisp_protection_kind reason, natural protsize, Boolean now)
+{
+  protected_area_ptr p = (protected_area_ptr) allocate(sizeof(protected_area));
+  
+  if (p == NULL) return NULL;
+  p->protsize = protsize;
+  p->nprot = 0;
+  p->start = start;
+  p->end = end;
+  p->why = reason;
+  p->next = AllProtectedAreas;
+
+  AllProtectedAreas = p;
+  if (now) {
+    protect_area(p);
+  }
+  
+  return p;
+}
+
+/*
+  Un-protect the first nbytes bytes in specified area.
+  Note that this may cause the area to be empty.
+*/
+void
+unprotect_area_prefix(protected_area_ptr area, size_t delta)
+{
+  unprotect_area(area);
+  area->start += delta;
+  if ((area->start + area->protsize) <= area->end) {
+    protect_area(area);
+  }
+}
+
+
+/*
+  Extend the protected area, causing the preceding nbytes bytes
+  to be included and protected.
+*/
+void
+protect_area_prefix(protected_area_ptr area, size_t delta)
+{
+  unprotect_area(area);
+  area->start -= delta;
+  protect_area(area);
+}
+
+protected_area_ptr
+AllProtectedAreas = NULL;
+
+
+/* 
+  This does a linear search.  Areas aren't created all that often;
+  if there get to be very many of them, some sort of tree search
+  might be justified.
+*/
+
+protected_area_ptr
+find_protected_area(BytePtr addr)
+{
+  protected_area* p;
+  
+  for(p = AllProtectedAreas; p; p=p->next) {
+    if ((p->start <= addr) && (p->end > addr)) {
+      return p;
+    }
+  }
+  return NULL;
+}
+
+
+void
+zero_memory_range(BytePtr start, BytePtr end)
+{
+#ifdef WINDOWS
+  ZeroMemory(start,end-start);
+#else
+  bzero(start,(size_t)(end-start));
+#endif
+}
+
+
+  
+
+/* 
+   Grow or shrink the dynamic area.  Or maybe not.
+   Whether or not the end of (mapped space in) the heap changes,
+   ensure that everything between the freeptr and the heap end
+   is mapped and read/write.  (It'll incidentally be zeroed.)
+*/
+Boolean
+resize_dynamic_heap(BytePtr newfree, 
+		    natural free_space_size)
+{
+  extern int page_size;
+  area *a = active_dynamic_area;
+  BytePtr newlimit, protptr, zptr;
+  int psize = page_size;
+  if (free_space_size) {
+    BytePtr lowptr = a->active;
+    newlimit = lowptr + align_to_power_of_2(newfree-lowptr+free_space_size,
+					    log2_heap_segment_size);
+    if (newlimit > a->high) {
+      return grow_dynamic_area(newlimit-a->high);
+    } else if ((lowptr + free_space_size) < a->high) {
+      shrink_dynamic_area(a->high-newlimit);
+      return true;
+    }
+  }
+}
+
+void
+protect_area(protected_area_ptr p)
+{
+  BytePtr start = p->start;
+  natural n = p->protsize;
+
+  if (n && ! p->nprot) {
+    ProtectMemory(start, n);
+    p->nprot = n;
+  }
+}
+
+
+void
+zero_page(BytePtr start)
+{
+  extern int page_size;
+#ifdef PPC
+  extern void zero_cache_lines(BytePtr, size_t, size_t);
+  zero_cache_lines(start, (page_size/cache_block_size), cache_block_size);
+#else
+  memset(start, 0, page_size);
+#endif
+}
+
+/* area management */
+
+
+area *
+new_area(BytePtr lowaddr, BytePtr highaddr, area_code code)
+{
+  area *a = (area *) (zalloc(sizeof(area)));
+  if (a) {
+    natural ndnodes = area_dnode(highaddr, lowaddr);
+    a->low = lowaddr;
+    a->high = highaddr;
+    a->active = (code == AREA_DYNAMIC) ? lowaddr : highaddr;
+    a->code = code;
+    a->ndnodes = ndnodes;
+    /* Caller must allocate markbits when allocating heap ! */
+    
+  }
+  return a;
+}
+
+static area *
+add_area_before(area *new_area, area *before)
+{
+  area *before_before = before->pred;
+
+  new_area->pred = before_before;
+  new_area->succ = before;
+  before_before->succ = new_area;
+  before->pred = new_area;
+  return new_area;
+}
+
+/*
+  The active dynamic area comes first.
+  Static areas follow dynamic areas.
+  Stack areas follow static areas.
+  Readonly areas come last.
+*/
+
+/*
+  If we already own the area_lock (or during iniitalization), it's safe
+  to add an area.
+*/
+
+
+void
+add_area_holding_area_lock(area *new_area)
+{
+  area *that = all_areas;
+  int
+    thiscode = (int)(new_area->code),
+    thatcode;
+
+  /* Cdr down the linked list */
+  do {
+    that = that->succ;
+    thatcode = (int)(that->code);
+  } while (thiscode < thatcode);
+  add_area_before(new_area, that);
+}
+
+/*
+  In general, we need to own the area lock before adding an area.
+*/
+void
+add_area(area *new_area, TCR *tcr)
+{
+  LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+  add_area_holding_area_lock(new_area);
+  LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+}  
+
+/*
+  Search areas "forward" from the header's successor, until
+  an area containing ADDR is found or an area with code < MINCODE
+  is encountered.
+  This walks the area list visiting heaps (dynamic, then static)
+  first, then stacks.
+
+*/
+static area *
+find_area_forward(BytePtr addr, area_code mincode)
+{
+  area *p, *header = all_areas;
+
+  for (p = header->succ; p != header; p = p->succ) {
+    area_code pcode = p->code;
+    if (pcode < mincode) {
+      return NULL;
+    }
+    if (pcode >= AREA_READONLY) {
+      if ((addr >= p->low) &&
+          (addr < p->active)) {
+        return p;
+      }
+    } else {
+      if ((addr >= p->active) &&
+          (addr < p->high)) {
+        return p;
+      }
+    }
+  }
+  return NULL;
+}
+
+static area *
+find_area_backward(BytePtr addr, area_code maxcode)
+{
+  area *p, *header = all_areas;
+
+  for (p = header->pred; p != header; p = p->pred) {
+    area_code pcode = p->code;
+
+    if (pcode > maxcode) {
+      return NULL;
+    }
+    if (pcode >= AREA_READONLY) {
+      if ((addr >= p->low) &&
+          (addr < p->active)) {
+        return p;
+      }
+    } else {
+      if ((addr >= p->active) &&
+          (addr < p->high)) {
+        return p;
+      }
+    }
+  }
+  return NULL;
+}
+
+area *
+area_containing(BytePtr addr)
+{
+  return find_area_forward(addr, AREA_VOID);
+}
+
+area *
+heap_area_containing(BytePtr addr)
+{
+  return find_area_forward(addr, AREA_READONLY);
+}
+
+area *
+stack_area_containing(BytePtr addr)
+{
+  return find_area_backward(addr, AREA_TSTACK);
+}
+
+/*
+  Make everything "younger" than the start of the target area
+  belong to that area; all younger areas will become empty, and
+  the dynamic area will have to lose some of its markbits (they
+  get zeroed and become part of the tenured area's refbits.)
+
+  The active dynamic area must have been "normalized" (e.g., its
+  active pointer must match the free pointer) before this is called.
+
+  If the target area is 'tenured_area' (the oldest ephemeral generation),
+  zero its refbits and update YOUNGEST_EPHEMERAL.
+
+*/
+
+void
+tenure_to_area(area *target)
+{
+  area *a = active_dynamic_area, *child;
+  BytePtr 
+    curfree = a->active,
+    target_low = target->low,
+    tenured_low = tenured_area->low;
+  natural 
+    dynamic_dnodes = area_dnode(curfree, a->low),
+    new_tenured_dnodes = area_dnode(curfree, tenured_area->low);
+  bitvector 
+    refbits = tenured_area->refbits,
+    markbits = a->markbits,
+    new_markbits;
+
+  target->high = target->active = curfree;
+  target->ndnodes = area_dnode(curfree, target_low);
+
+  for (child = target->younger; child != a; child = child->younger) {
+    child->high = child->low = child->active = curfree;
+    child->ndnodes = 0;
+  }
+
+  a->low = curfree;
+  a->ndnodes = area_dnode(a->high, curfree);
+
+  new_markbits = refbits + ((new_tenured_dnodes + (nbits_in_word-1)) >> bitmap_shift);
+  
+  if (target == tenured_area) {
+    zero_bits(refbits, new_tenured_dnodes);
+    lisp_global(OLDEST_EPHEMERAL) = ptr_to_lispobj(curfree);
+  } else {
+    /* Need more (zeroed) refbits & fewer markbits */
+    zero_bits(markbits, ((new_markbits-markbits)<<bitmap_shift));
+  }
+   
+  a->markbits = new_markbits;
+  lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(curfree, lisp_global(REF_BASE));
+}
+
+
+
+/*
+  Make everything younger than the oldest byte in 'from' belong to 
+  the youngest generation.  If 'from' is 'tenured_area', this means
+  that nothing's ephemeral any more (and OLDEST_EPHEMERAL can be set
+  to 0 to indicate this.)
+  
+  Some tenured_area refbits become dynamic area markbits in the process;
+  it's not necessary to zero them, since the GC will do that.
+*/
+
+void
+untenure_from_area(area *from)
+{
+  if (lisp_global(OLDEST_EPHEMERAL) != 0) {
+    area *a = active_dynamic_area, *child;
+    BytePtr curlow = from->low;
+    natural new_tenured_dnodes = area_dnode(curlow, tenured_area->low);
+    
+    for (child = from; child != a; child = child->younger) {
+      child->low = child->active = child->high = curlow;
+      child->ndnodes = 0;
+    }
+    
+    a->low = curlow;
+    a->ndnodes = area_dnode(a->high, curlow);
+    
+    a->markbits = (tenured_area->refbits) + ((new_tenured_dnodes+(nbits_in_word-1))>>bitmap_shift);
+    if (from == tenured_area) {
+      /* Everything's in the dynamic area */
+      lisp_global(OLDEST_EPHEMERAL) = 0;
+      lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(managed_static_area->active,managed_static_area->low);
+
+    }
+  }
+}
+
+
+Boolean
+egc_control(Boolean activate, BytePtr curfree)
+{
+  area *a = active_dynamic_area;
+  Boolean egc_is_active = (a->older != NULL);
+
+  if (activate != egc_is_active) {
+    if (curfree != NULL) {
+      a->active = curfree;
+    }
+    if (activate) {
+      a->older = g1_area;
+      tenure_to_area(tenured_area);
+      egc_is_active = true;
+    } else {
+      untenure_from_area(tenured_area);
+      a->older = NULL;
+      egc_is_active = false;
+    }
+  }
+  return egc_is_active;
+}
+
+/*
+  Lisp ff-calls this; it needs to set the active area's active pointer
+  correctly.
+*/
+
+Boolean
+lisp_egc_control(Boolean activate)
+{
+  area *a = active_dynamic_area;
+  return egc_control(activate, (BytePtr) a->active);
+}
+
+
+
+
+  
+/* Splice the protected_area_ptr out of the list and dispose of it. */
+void
+delete_protected_area(protected_area_ptr p)
+{
+  BytePtr start = p->start;
+  int nbytes = p->nprot;
+  protected_area_ptr *prev = &AllProtectedAreas, q;
+
+  if (nbytes) {
+    UnProtectMemory((LogicalAddress)start, nbytes);
+  }
+  
+  while ((q = *prev) != NULL) {
+    if (p == q) {
+      *prev = p->next;
+      break;
+    } else {
+      prev = &(q->next);
+    }
+  }
+
+  deallocate((Ptr)p);
+}
+
+
+
+
+/* 
+  Unlink the area from all_areas.
+  Unprotect and dispose of any hard/soft protected_areas.
+  If the area has a handle, dispose of that as well.
+  */
+
+void
+condemn_area_holding_area_lock(area *a)
+{
+  void free_stack(void *);
+  area *prev = a->pred, *next = a->succ;
+  Ptr h = a->h;
+  protected_area_ptr p;
+
+  prev->succ = next;
+  next->pred = prev;
+
+  p = a->softprot;
+  if (p) delete_protected_area(p);
+
+  p = a->hardprot;
+
+  if (p) delete_protected_area(p);
+
+  if (h) free_stack(h);
+  deallocate((Ptr)a);
+}
+
+
+
+void
+condemn_area(area *a, TCR *tcr)
+{
+  LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+  condemn_area_holding_area_lock(a);
+  LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+}
+
+
+
+
+/*
+  condemn an area and all the other areas that can be reached
+  via the area.older & area.younger links.
+  This is the function in the ppc::kernel-import-condemn-area slot,
+  called by free-stack-area
+  */
+void
+condemn_area_chain(area *a, TCR *tcr)
+{
+  area *older;
+
+  LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+
+  for (; a->younger; a = a->younger) ;
+  for (;a;) {
+    older = a->older;
+    condemn_area_holding_area_lock(a);
+    a = older;
+  }
+  UNLOCK(lisp_global(TCR_AREA_LOCK),tcr);
+}
+
+
+void
+protect_watched_areas()
+{
+  area *a = active_dynamic_area;
+  natural code = a->code;
+
+  while (code != AREA_VOID) {
+    if (code == AREA_WATCHED) {
+      natural size = a->high - a->low;
+      
+      ProtectMemory(a->low, size);
+    }
+    a = a->succ;
+    code = a->code;
+  }
+}
+
+void
+unprotect_watched_areas()
+{
+  area *a = active_dynamic_area;
+  natural code = a->code;
+
+  while (code != AREA_VOID) {
+    if (code == AREA_WATCHED) {
+      natural size = a->high - a->low;
+      
+      UnProtectMemory(a->low, size);
+    }
+    a = a->succ;
+    code = a->code;
+  }
+}
Index: /branches/new-random/lisp-kernel/memprotect.h
===================================================================
--- /branches/new-random/lisp-kernel/memprotect.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/memprotect.h	(revision 13309)
@@ -0,0 +1,132 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __memprotect_h__
+#define __memprotect_h__
+
+
+
+#include "lisptypes.h"
+#ifdef PPC
+#include "ppc-constants.h"
+#endif
+#include <signal.h>
+#ifndef WINDOWS
+#ifdef DARWIN
+#include <sys/ucontext.h>
+#else
+#include <ucontext.h>
+#endif
+#endif
+
+#ifdef WINDOWS
+#define MAP_FAILED ((void *)(-1))
+
+#define MEMPROTECT_NONE PAGE_NOACCESS
+#define MEMPROTECT_RO   PAGE_READONLY
+#define MEMPROTECT_RW   PAGE_READWRITE
+#define MEMPROTECT_RX   PAGE_EXECUTE_READ
+#define MEMPROTECT_RWX  PAGE_EXECUTE_READWRITE
+
+#else
+
+#define MEMPROTECT_NONE PROT_NONE
+#define MEMPROTECT_RO   PROT_READ
+#define MEMPROTECT_RW   (PROT_READ|PROT_WRITE)
+#define MEMPROTECT_RX   (PROT_READ|PROT_EXEC)
+#define MEMPROTECT_RWX  (PROT_READ|PROT_WRITE|PROT_EXEC)
+#ifndef MAP_GROWSDOWN
+#define MAP_GROWSDOWN (0)
+#endif
+
+
+#endif
+
+LogicalAddress
+ReserveMemoryForHeap(LogicalAddress want, natural totalsize);
+
+int
+CommitMemory (LogicalAddress start, natural len);
+
+void
+UnCommitMemory (LogicalAddress start, natural len);
+
+LogicalAddress
+MapMemory(LogicalAddress addr, natural nbytes, int protection);
+
+LogicalAddress
+MapMemoryForStack(natural nbytes);
+
+int
+UnMapMemory(LogicalAddress addr, natural nbytes);
+
+int
+ProtectMemory(LogicalAddress, natural);
+
+int
+UnProtectMemory(LogicalAddress, natural);
+
+int
+MapFile(LogicalAddress addr, natural pos, natural nbytes, int permissions, int fd);
+
+typedef enum {
+  kNotProtected,		/* At least not at the moment. */
+  kVSPsoftguard,
+  kSPsoftguard,
+  kTSPsoftguard,
+  kSPhardguard,			/* Touch one and die. */
+  kVSPhardguard,
+  kTSPhardguard,
+  kHEAPsoft,			/* Uninitialized page in the heap */
+  kHEAPhard,			/* The end-of-the-line in the heap */
+  /* Phony last entry. */
+  kNumProtectionKinds
+  } lisp_protection_kind;
+
+typedef
+struct protected_area {
+  struct protected_area *next;
+  BytePtr start;                /* first byte (page-aligned) that might be protected */
+  BytePtr end;                  /* last byte (page-aligned) that could be protected */
+  unsigned nprot;               /* Might be 0 */
+  unsigned protsize;            /* number of bytes to protect */
+  lisp_protection_kind why;
+} protected_area, *protected_area_ptr;
+
+
+/* Various functions that try to respond to a protection violation */
+typedef 
+  OSStatus (protection_handler)(ExceptionInformation *, protected_area_ptr, BytePtr);
+
+protection_handler 
+  do_spurious_wp_fault,
+  do_soft_stack_overflow,
+  do_hard_stack_overflow,
+  do_tenured_space_write,
+  do_heap_soft_probe,
+  do_heap_hard_probe;
+
+extern protection_handler
+  *protection_handlers[];
+
+
+void
+exception_cleanup(void);
+
+
+  
+#endif /* __memprotect_h__ */
Index: /branches/new-random/lisp-kernel/pad.s
===================================================================
--- /branches/new-random/lisp-kernel/pad.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/pad.s	(revision 13309)
@@ -0,0 +1,6 @@
+	.globl openmcl_low_address
+openmcl_low_address:
+        nop
+        
+
+
Index: /branches/new-random/lisp-kernel/plbt.c
===================================================================
--- /branches/new-random/lisp-kernel/plbt.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/plbt.c	(revision 13309)
@@ -0,0 +1,318 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lispdcmd.h"
+#ifdef LINUX
+#define __USE_GNU 1
+#include <dlfcn.h>
+#endif
+
+#ifdef DARWIN
+#if 0
+#undef undefined
+#include <stdint.h>
+#include <mach-o/dyld.h>
+#include <mach-o/nlist.h>
+
+typedef struct dl_info {
+  const char      *dli_fname;     /* Pathname of shared object */
+  void            *dli_fbase;     /* Base address of shared object */
+  const char      *dli_sname;     /* Name of nearest symbol */
+  void            *dli_saddr;     /* Address of nearest symbol */
+} Dl_info;
+
+int
+darwin_dladdr(void *p, Dl_info *info)
+{
+  unsigned long i;
+  unsigned long j;
+  uint32_t count = _dyld_image_count();
+  struct mach_header *mh = 0;
+  struct load_command *lc = 0;
+  unsigned long addr = 0;
+  unsigned long table_off = (unsigned long)0;
+  int found = 0;
+
+  if (!info)
+    return 0;
+  info->dli_fname = 0;
+  info->dli_fbase = 0;
+  info->dli_sname = 0;
+  info->dli_saddr = 0;
+  /* Some of this was swiped from code posted by Douglas Davidson
+   * <ddavidso AT apple DOT com> to darwin-development AT lists DOT
+   * apple DOT com and slightly modified
+   */
+  for (i = 0; i < count; i++) {
+    addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i);
+    mh = (struct mach_header *)_dyld_get_image_header(i);
+    if (mh) {
+      lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
+      for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) {
+	if (LC_SEGMENT == lc->cmd &&
+	    addr >= ((struct segment_command *)lc)->vmaddr &&
+	    addr <
+	    ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) {
+	  info->dli_fname = _dyld_get_image_name(i);
+	  info->dli_fbase = (void *)mh;
+	  found = 1;
+	  break;
+	}
+      }
+      if (found) {
+	    break;
+      }
+    }
+  }
+  if (!found) {
+    return 0;
+  }
+  lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
+  for (j = 0; 
+       j < mh->ncmds; 
+       j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) {
+    if (LC_SEGMENT == lc->cmd) {
+      if (!strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT"))
+	break;
+    }
+  }
+  table_off =
+    ((unsigned long)((struct segment_command *)lc)->vmaddr) -
+    ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i);
+  
+  lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
+  for (j = 0; 
+       j < mh->ncmds; 
+       j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) {
+    if (LC_SYMTAB == lc->cmd) {
+      struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off);
+      unsigned long numsyms = ((struct symtab_command *)lc)->nsyms;
+      struct nlist *nearest = NULL;
+      unsigned long diff = 0xffffffff;
+      unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off);
+      for (i = 0; i < numsyms; i++) {
+	/* fprintf(dbgout,"%s : 0x%08x, 0x%x\n",(char *)(strtable + symtable->n_un.n_strx) ,symtable->n_value, symtable->n_type); */
+	/* Ignore the following kinds of Symbols */
+	if ((!symtable->n_value)	/* Undefined */
+	    || (symtable->n_type & N_STAB)	/* Debug symbol */
+	    || ((symtable->n_type & N_TYPE) != N_SECT)	/* Absolute, indirect, ... */
+	    ) {
+	  symtable++;
+	  continue;
+	}
+	if ((addr >= symtable->n_value) && 
+	    (diff >= addr - (symtable->n_value ))) {
+	  diff = addr- (unsigned long)symtable->n_value;
+	  nearest = symtable;
+	}
+	symtable++;
+      }
+      if (nearest) {
+	info->dli_saddr = nearest->n_value + ((void *)p - addr);
+	info->dli_sname = (char *)(strtable + nearest->n_un.n_strx);
+      }
+    }
+  }
+  return 1;
+}
+
+#define dladdr darwin_dladdr
+#else
+#include <dlfcn.h>
+#endif
+#endif
+
+
+
+extern Boolean lisp_frame_p(lisp_frame *);
+
+void
+print_lisp_frame(lisp_frame *frame)
+{
+  LispObj fun = frame->savefn, pc = frame->savelr;
+  int delta = 0;
+  Dl_info info;
+  char *spname;
+
+  if ((fun == 0) || (fun == fulltag_misc)) {
+    spname = "unknown ?";
+#ifndef STATIC
+    if (dladdr((void *)ptr_from_lispobj(pc), &info)) {
+      spname = (char *)(info.dli_sname);
+#ifdef DARWIN
+      if (spname[-1] != '_') {
+        --spname;
+      }
+#endif
+    }
+#endif
+#ifdef PPC64
+    Dprintf("(#x%016lX) #x%016lX : (subprimitive %s)", frame, pc, spname);
+#else
+    Dprintf("(#x%08X) #x%08X : (subprimitive %s)", frame, pc, spname);
+#endif
+  } else {
+    if ((fulltag_of(fun) != fulltag_misc) ||
+        (header_subtag(header_of(fun)) != subtag_function)) {
+#ifdef PPC64
+      Dprintf("(#x%016lX) #x%016lX : (not a function!)", frame, pc);
+#else
+      Dprintf("(#x%08X) #x%08X : (not a function!)", frame, pc);
+#endif
+    } else {
+      LispObj code_vector = deref(fun, 1);
+      
+      if ((pc >= (code_vector+misc_data_offset)) &&
+          (pc < ((code_vector+misc_data_offset)+(header_element_count(header_of(code_vector))<<2)))) {
+        delta = (pc - (code_vector+misc_data_offset));
+      }
+#ifdef PPC64
+      Dprintf("(#x%016lX) #x%016lX : %s + %d", frame, pc, print_lisp_object(fun), delta);
+#else
+      Dprintf("(#x%08X) #x%08X : %s + %d", frame, pc, print_lisp_object(fun), delta);
+#endif
+    }
+  }
+}
+
+
+void
+print_foreign_frame(void *frame)
+{
+#ifdef LINUX
+  natural pc = (natural) (((eabi_c_frame *)frame)->savelr);
+#endif
+#ifdef DARWIN
+  natural pc = (natural) (((c_frame *)frame)->savelr);
+#endif
+  Dl_info foreign_info;
+
+#ifndef STATIC
+  if (dladdr((void *)pc, &foreign_info)) {
+    Dprintf(
+#ifdef PPC64
+"(#x%016lx) #x%016lX : %s + %d"
+#else
+"(#x%08x) #x%08X : %s + %d"
+#endif
+, frame, pc, foreign_info.dli_sname,
+	    pc-((long)foreign_info.dli_saddr));
+  } else {
+#endif
+    Dprintf(
+#ifdef PPC64
+"(#x%016X) #x%016X : foreign code (%s)"
+#else
+"(#x%08X) #x%08X : foreign code (%s)"
+#endif
+, frame, pc, "unknown");
+#ifndef STATIC
+  }
+#endif
+}
+
+
+/* Walk frames from "start" to "end". 
+   Say whatever can be said about foreign frames and lisp frames.
+*/
+
+void
+walk_stack_frames(lisp_frame *start, lisp_frame *end) 
+{
+  lisp_frame *next;
+  Dprintf("\n");
+  while (start < end) {
+
+    if (lisp_frame_p(start)) {
+      print_lisp_frame(start);
+    } else {
+#ifdef DARWIN
+      print_foreign_frame((c_frame *)start);
+#else
+      print_foreign_frame((eabi_c_frame *)start);
+#endif
+    }
+    
+    next = start->backlink;
+    if (next == 0) {
+      next = end;
+    }
+    if (next < start) {
+      fprintf(dbgout, "Bad frame! (%x < %x)\n", next, start);
+      break;
+    }
+    start = next;
+  }
+}
+
+char *
+interrupt_level_description(TCR *tcr)
+{
+  signed_natural level = (signed_natural) TCR_INTERRUPT_LEVEL(tcr);
+  if (level < 0) {
+    if (tcr->interrupt_pending) {
+      return "disabled(pending)";
+    } else {
+      return "disabled";
+    }
+  } else {
+    return "enabled";
+  }
+}
+
+void
+walk_other_areas()
+{
+  TCR *start = (TCR *)get_tcr(true), *tcr = start->next;
+  area *a;
+  char *ilevel = interrupt_level_description(tcr);
+
+  while (tcr != start) {
+    a = tcr->cs_area;
+    Dprintf("\n\n TCR = 0x%lx, cstack area #x%lx,  native thread ID = 0x%lx, interrupts %s", tcr, a,  tcr->native_thread_id, ilevel);
+    walk_stack_frames((lisp_frame *) (a->active), (lisp_frame *) (a->high));
+    tcr = tcr->next;
+  }
+}
+
+void
+plbt_sp(LispObj currentSP)
+{
+  area *cs_area;
+  
+{
+    TCR *tcr = (TCR *)get_tcr(true);
+    char *ilevel = interrupt_level_description(tcr);
+    cs_area = tcr->cs_area;
+    if ((((LispObj) ptr_to_lispobj(cs_area->low)) > currentSP) ||
+        (((LispObj) ptr_to_lispobj(cs_area->high)) < currentSP)) {
+      Dprintf("\nStack pointer [#x%lX] in unknown area.", currentSP);
+    } else {
+      fprintf(dbgout, "current thread: tcr = 0x%lx, native thread ID = 0x%lx, interrupts %s\n", tcr, tcr->native_thread_id, ilevel);
+      walk_stack_frames((lisp_frame *) ptr_from_lispobj(currentSP), (lisp_frame *) (cs_area->high));
+      walk_other_areas();
+    }
+  } 
+}
+
+  
+void
+plbt(ExceptionInformation *xp)
+{
+  plbt_sp(xpGPR(xp, sp));
+}
+    
Index: /branches/new-random/lisp-kernel/plprint.c
===================================================================
--- /branches/new-random/lisp-kernel/plprint.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/plprint.c	(revision 13309)
@@ -0,0 +1,30 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lispdcmd.h"
+
+
+void
+plprint(ExceptionInformation *xp, LispObj obj)
+{
+  if (lisp_nil == (LispObj) NULL) {
+    fprintf(dbgout,"can't find lisp NIL; lisp process not active process ?\n");
+  } else {
+    Dprintf("\n%s", print_lisp_object(obj));
+  }
+}
+
Index: /branches/new-random/lisp-kernel/plsym.c
===================================================================
--- /branches/new-random/lisp-kernel/plsym.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/plsym.c	(revision 13309)
@@ -0,0 +1,128 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lispdcmd.h"
+
+void
+describe_symbol(LispObj sym)
+{
+  lispsymbol *rawsym = (lispsymbol *)ptr_from_lispobj(untag(sym));
+  LispObj function = rawsym->fcell;
+#ifdef fulltag_symbol
+  sym += (fulltag_symbol-fulltag_misc);
+#endif
+  Dprintf("Symbol %s at #x%llX", print_lisp_object(sym), (u64_t) sym);
+  Dprintf("  value    : %s", print_lisp_object(rawsym->vcell));
+  if (function != nrs_UDF.vcell) {
+    Dprintf("  function : %s", print_lisp_object(function));
+  }
+}
+  
+int
+compare_lisp_string_to_c_string(lisp_char_code *lisp_string,
+                                char *c_string,
+                                natural n)
+{
+  natural i;
+  for (i = 0; i < n; i++) {
+    if (lisp_string[i] != (lisp_char_code)(c_string[i])) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+/*
+  Walk the heap until we find a symbol
+  whose pname matches "name".  Return the 
+  tagged symbol or NULL.
+*/
+
+LispObj
+find_symbol_in_range(LispObj *start, LispObj *end, char *name)
+{
+  LispObj header, tag;
+  int n = strlen(name);
+  char *s = name;
+  lisp_char_code *p;
+  while (start < end) {
+    header = *start;
+    tag = fulltag_of(header);
+    if (header_subtag(header) == subtag_symbol) {
+      LispObj 
+        pname = deref(ptr_to_lispobj(start), 1),
+        pname_header = header_of(pname);
+      if ((header_subtag(pname_header) == subtag_simple_base_string) &&
+          (header_element_count(pname_header) == n)) {
+        p = (lisp_char_code *) ptr_from_lispobj(pname + misc_data_offset);
+        if (compare_lisp_string_to_c_string(p, s, n) == 0) {
+          return (ptr_to_lispobj(start))+fulltag_misc;
+        }
+      }
+    }
+    if (nodeheader_tag_p(tag)) {
+      start += (~1 & (2 + header_element_count(header)));
+    } else if (immheader_tag_p(tag)) {
+      start = (LispObj *) skip_over_ivector((natural)start, header);
+    } else {
+      start += 2;
+    }
+  }
+  return (LispObj)NULL;
+}
+
+LispObj 
+find_symbol(char *name)
+{
+  area *a =  ((area *) (ptr_from_lispobj(lisp_global(ALL_AREAS))))->succ;
+  area_code code;
+  LispObj sym = 0;
+
+  while ((code = a->code) != AREA_VOID) {
+    if ((code == AREA_STATIC) ||
+        (code == AREA_DYNAMIC)) {
+      sym = find_symbol_in_range((LispObj *)(a->low), (LispObj *)(a->active), name);
+      if (sym) {
+        break;
+      }
+    }
+    a = a->succ;
+  }
+  return sym;
+}
+
+    
+void 
+plsym(ExceptionInformation *xp, char *pname) 
+{
+  natural address = 0;
+
+  address = find_symbol(pname);
+  if (address == 0) {
+    Dprintf("Can't find symbol.");
+    return;
+  }
+  
+  if ((fulltag_of(address) == fulltag_misc) &&
+      (header_subtag(header_of(address)) == subtag_symbol)){
+    describe_symbol(address);
+  } else {
+    fprintf(dbgout, "Not a symbol.\n");
+  }
+  return;
+}
+
Index: /branches/new-random/lisp-kernel/pmcl-kernel.c
===================================================================
--- /branches/new-random/lisp-kernel/pmcl-kernel.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/pmcl-kernel.c	(revision 13309)
@@ -0,0 +1,2482 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifdef DARWIN
+/*	dyld.h included here because something in "lisp.h" causes
+    a conflict (actually I think the problem is in "constants.h")
+*/
+#include <mach-o/dyld.h>
+
+#endif
+#include "lisp.h"
+#include "lisp_globals.h"
+#include "gc.h"
+#include "area.h"
+#include <stdlib.h>
+#include <string.h>
+#include "lisp-exceptions.h"
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef WINDOWS
+#include <sys/mman.h>
+#endif
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#ifndef WINDOWS
+#include <sys/utsname.h>
+#include <unistd.h>
+#endif
+
+#ifdef LINUX
+#include <mcheck.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <link.h>
+#include <elf.h>
+
+/* 
+   The version of <asm/cputable.h> provided by some distributions will
+   claim that <asm-ppc64/cputable.h> doesn't exist.  It may be present
+   in the Linux kernel source tree even if it's not copied to
+   /usr/include/asm-ppc64.  Hopefully, this will be straightened out
+   soon (and/or the PPC_FEATURE_HAS_ALTIVEC constant will be defined
+   in a less volatile place.)  Until that's straightened out, it may
+   be necessary to install a copy of the kernel header in the right
+   place and/or persuade <asm/cputable> to lighten up a bit.
+*/
+
+#ifdef PPC
+#ifndef PPC64
+#include <asm/cputable.h>
+#endif
+#ifndef PPC_FEATURE_HAS_ALTIVEC
+#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
+#endif
+#endif
+#endif
+
+Boolean use_mach_exception_handling = 
+#ifdef DARWIN
+  true
+#else
+  false
+#endif
+;
+
+#ifdef DARWIN
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <mach/mach_types.h>
+#include <mach/message.h>
+#include <mach/vm_region.h>
+#include <mach/port.h>
+#include <sys/sysctl.h>
+#include <dlfcn.h>
+#endif
+
+#if defined(FREEBSD) || defined(SOLARIS)
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <dlfcn.h>
+#include <elf.h> 
+#include <link.h>
+#endif
+
+#include <ctype.h>
+#ifndef WINDOWS
+#include <sys/select.h>
+#endif
+#include "Threads.h"
+
+#include <fenv.h>
+#include <sys/stat.h>
+
+#ifndef MAP_NORESERVE
+#define MAP_NORESERVE (0)
+#endif
+
+#ifdef WINDOWS
+#include <windows.h>
+#include <stdio.h>
+void
+wperror(char* message)
+{
+  char* buffer;
+  DWORD last_error = GetLastError();
+  
+  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
+		FORMAT_MESSAGE_FROM_SYSTEM|
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		last_error,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPTSTR)&buffer,
+		0, NULL);
+  fprintf(dbgout, "%s: 0x%x %s\n", message, (unsigned) last_error, buffer);
+  LocalFree(buffer);
+}
+#endif
+
+LispObj lisp_nil = (LispObj) 0;
+bitvector global_mark_ref_bits = NULL, dynamic_mark_ref_bits = NULL, relocatable_mark_ref_bits = NULL;
+
+
+/* These are all "persistent" : they're initialized when
+   subprims are first loaded and should never change. */
+extern LispObj ret1valn;
+extern LispObj nvalret;
+extern LispObj popj;
+
+LispObj text_start = 0;
+
+/* A pointer to some of the kernel's own data; also persistent. */
+
+extern LispObj import_ptrs_base;
+
+
+
+void
+xMakeDataExecutable(void *, unsigned long);
+
+void
+make_dynamic_heap_executable(LispObj *p, LispObj *q)
+{
+  void * cache_start = (void *) p;
+  natural ncacheflush = (natural) q - (natural) p;
+
+  xMakeDataExecutable(cache_start, ncacheflush);  
+}
+      
+size_t
+ensure_stack_limit(size_t stack_size)
+{
+#ifdef WINDOWS
+  extern void os_get_current_thread_stack_bounds(void **, natural*);
+  natural totalsize;
+  void *ignored;
+  
+  os_get_current_thread_stack_bounds(&ignored, &totalsize);
+
+  return (size_t)totalsize-(size_t)(CSTACK_HARDPROT+CSTACK_SOFTPROT);
+
+#else
+  struct rlimit limits;
+  rlim_t cur_stack_limit, max_stack_limit;
+ 
+  stack_size += (CSTACK_HARDPROT+CSTACK_SOFTPROT);
+  getrlimit(RLIMIT_STACK, &limits);
+  cur_stack_limit = limits.rlim_cur;
+  max_stack_limit = limits.rlim_max;
+  if (stack_size > max_stack_limit) {
+    stack_size = max_stack_limit;
+  }
+  if (cur_stack_limit < stack_size) {
+    limits.rlim_cur = stack_size;
+    errno = 0;
+    if (setrlimit(RLIMIT_STACK, &limits)) {
+      int e = errno;
+      fprintf(dbgout, "errno = %d\n", e);
+      Fatal(": Stack resource limit too small", "");
+    }
+  }
+#endif
+  return stack_size;
+}
+
+
+/* This should write-protect the bottom of the stack.
+   Doing so reliably involves ensuring that everything's unprotected on exit.
+*/
+
+BytePtr
+allocate_lisp_stack(natural useable,
+                    unsigned softsize,
+                    unsigned hardsize,
+                    lisp_protection_kind softkind,
+                    lisp_protection_kind hardkind,
+                    Ptr *h_p,
+                    BytePtr *base_p,
+                    protected_area_ptr *softp,
+                    protected_area_ptr *hardp)
+{
+  void *allocate_stack(natural);
+  void free_stack(void *);
+  natural size = useable+softsize+hardsize;
+  natural overhead;
+  BytePtr base, softlimit, hardlimit;
+  Ptr h = allocate_stack(size+4095);
+  protected_area_ptr hprotp = NULL, sprotp;
+
+  if (h == NULL) {
+    return NULL;
+  }
+  if (h_p) *h_p = h;
+  base = (BytePtr) align_to_power_of_2( h, log2_page_size);
+  hardlimit = (BytePtr) (base+hardsize);
+  softlimit = hardlimit+softsize;
+
+  overhead = (base - (BytePtr) h);
+  if (hardsize) {
+    hprotp = new_protected_area((BytePtr)base,hardlimit,hardkind, hardsize, true);
+    if (hprotp == NULL) {
+      if (base_p) *base_p = NULL;
+      if (h_p) *h_p = NULL;
+      deallocate(h);
+      return NULL;
+    }
+    if (hardp) *hardp = hprotp;
+  }
+  if (softsize) {
+    sprotp = new_protected_area(hardlimit,softlimit, softkind, softsize, true);
+    if (sprotp == NULL) {
+      if (base_p) *base_p = NULL;
+      if (h_p) *h_p = NULL;
+      if (hardp) *hardp = NULL;
+      if (hprotp) delete_protected_area(hprotp);
+      free_stack(h);
+      return NULL;
+    }
+    if (softp) *softp = sprotp;
+  }
+  if (base_p) *base_p = base;
+  return (BytePtr) ((natural)(base+size));
+}
+
+/*
+  This should only called by something that owns the area_lock, or
+  by the initial thread before other threads exist.
+*/
+area *
+allocate_lisp_stack_area(area_code stack_type,
+                         natural usable,
+                         unsigned softsize, 
+                         unsigned hardsize, 
+                         lisp_protection_kind softkind, 
+                         lisp_protection_kind hardkind)
+
+{
+  BytePtr base, bottom;
+  Ptr h;
+  area *a = NULL;
+  protected_area_ptr soft_area=NULL, hard_area=NULL;
+
+  bottom = allocate_lisp_stack(usable, 
+                               softsize, 
+                               hardsize, 
+                               softkind, 
+                               hardkind, 
+                               &h, 
+                               &base,
+                               &soft_area, 
+                               &hard_area);
+
+  if (bottom) {
+    a = new_area(base, bottom, stack_type);
+    a->hardlimit = base+hardsize;
+    a->softlimit = base+hardsize+softsize;
+    a->h = h;
+    a->softprot = soft_area;
+    a->hardprot = hard_area;
+    add_area_holding_area_lock(a);
+  }
+  return a;
+}
+
+/*
+  Also assumes ownership of the area_lock 
+*/
+area*
+register_cstack_holding_area_lock(BytePtr bottom, natural size)
+{
+  BytePtr lowlimit = (BytePtr) (((((natural)bottom)-size)+4095)&~4095);
+  area *a = new_area((BytePtr) bottom-size, bottom, AREA_CSTACK);
+  a->hardlimit = lowlimit+CSTACK_HARDPROT;
+  a->softlimit = a->hardlimit+CSTACK_SOFTPROT;
+#ifdef USE_SIGALTSTACK
+  setup_sigaltstack(a);
+#endif
+  add_area_holding_area_lock(a);
+  return a;
+}
+  
+
+area*
+allocate_vstack_holding_area_lock(natural usable)
+{
+  return allocate_lisp_stack_area(AREA_VSTACK, 
+				  usable > MIN_VSTACK_SIZE ?
+				  usable : MIN_VSTACK_SIZE,
+                                  VSTACK_SOFTPROT,
+                                  VSTACK_HARDPROT,
+                                  kVSPsoftguard,
+                                  kVSPhardguard);
+}
+
+area *
+allocate_tstack_holding_area_lock(natural usable)
+{
+  return allocate_lisp_stack_area(AREA_TSTACK, 
+                                  usable > MIN_TSTACK_SIZE ?
+				  usable : MIN_TSTACK_SIZE,
+                                  TSTACK_SOFTPROT,
+                                  TSTACK_HARDPROT,
+                                  kTSPsoftguard,
+                                  kTSPhardguard);
+}
+
+
+/* It's hard to believe that max & min don't exist already */
+unsigned unsigned_min(unsigned x, unsigned y)
+{
+  if (x <= y) {
+    return x;
+  } else {
+    return y;
+  }
+}
+
+unsigned unsigned_max(unsigned x, unsigned y)
+{
+  if (x >= y) {
+    return x;
+  } else {
+    return y;
+  }
+}
+
+#if WORD_SIZE == 64
+#ifdef DARWIN
+#define MAXIMUM_MAPPABLE_MEMORY (512L<<30L)
+#endif
+#ifdef FREEBSD
+#define MAXIMUM_MAPPABLE_MEMORY (512L<<30L)
+#endif
+#ifdef SOLARIS
+#define MAXIMUM_MAPPABLE_MEMORY (512L<<30L)
+#endif
+#ifdef LINUX
+#ifdef X8664
+#define MAXIMUM_MAPPABLE_MEMORY (512L<<30L)
+#endif
+#ifdef PPC
+#define MAXIMUM_MAPPABLE_MEMORY (512L<<30L)
+#endif
+#endif
+#ifdef WINDOWS
+/* Supposedly, the high-end version of Vista allow 128GB of pageable memory */
+#define MAXIMUM_MAPPABLE_MEMORY (512LL<<30LL)
+#endif
+#else
+#ifdef DARWIN
+#define MAXIMUM_MAPPABLE_MEMORY ((1U<<31)-2*heap_segment_size)
+#endif
+#ifdef LINUX
+#ifdef X86
+#define MAXIMUM_MAPPABLE_MEMORY (9U<<28)
+#else
+#define MAXIMUM_MAPPABLE_MEMORY (1U<<30)
+#endif
+#endif
+#ifdef WINDOWS
+#define MAXIMUM_MAPPABLE_MEMORY (1U<<30)
+#endif
+#ifdef FREEBSD
+#define MAXIMUM_MAPPABLE_MEMORY (1U<<30)
+#endif
+#ifdef SOLARIS
+#define MAXIMUM_MAPPABLE_MEMORY (1U<<30)
+#endif
+#endif
+
+natural
+reserved_area_size = MAXIMUM_MAPPABLE_MEMORY;
+
+area 
+  *nilreg_area=NULL,
+  *tenured_area=NULL, 
+  *g2_area=NULL, 
+  *g1_area=NULL,
+  *managed_static_area=NULL,
+  *static_cons_area=NULL,
+  *readonly_area=NULL;
+
+area *all_areas=NULL;
+int cache_block_size=32;
+
+
+#if WORD_SIZE == 64
+#define DEFAULT_LISP_HEAP_GC_THRESHOLD (32<<20)
+#define G2_AREA_THRESHOLD (8<<20)
+#define G1_AREA_THRESHOLD (4<<20)
+#define G0_AREA_THRESHOLD (2<<20)
+#else
+#define DEFAULT_LISP_HEAP_GC_THRESHOLD (16<<20)
+#define G2_AREA_THRESHOLD (4<<20)
+#define G1_AREA_THRESHOLD (2<<20)
+#define G0_AREA_THRESHOLD (1<<20)
+#endif
+
+#define MIN_DYNAMIC_SIZE (DEFAULT_LISP_HEAP_GC_THRESHOLD *2)
+
+#if (WORD_SIZE == 32)
+#define DEFAULT_INITIAL_STACK_SIZE (1<<20)
+#else
+#define DEFAULT_INITIAL_STACK_SIZE (2<<20)
+#endif
+
+natural
+lisp_heap_gc_threshold = DEFAULT_LISP_HEAP_GC_THRESHOLD;
+
+natural 
+initial_stack_size = DEFAULT_INITIAL_STACK_SIZE;
+
+natural
+thread_stack_size = 0;
+
+
+/*
+  'start' should be on a segment boundary; 'len' should be
+  an integral number of segments.  remap the entire range.
+*/
+
+void 
+uncommit_pages(void *start, size_t len)
+{
+  UnCommitMemory(start, len);
+}
+
+#define TOUCH_PAGES_ON_COMMIT 0
+
+Boolean
+touch_all_pages(void *start, size_t len)
+{
+#if TOUCH_PAGES_ON_COMMIT
+  extern Boolean touch_page(void *);
+  char *p = (char *)start;
+
+  while (len) {
+    if (!touch_page(p)) {
+      return false;
+    }
+    len -= page_size;
+    p += page_size;
+  }
+#endif
+  return true;
+}
+
+Boolean
+commit_pages(void *start, size_t len)
+{
+  if (len != 0) {
+    if (CommitMemory(start, len)) {
+      if (touch_all_pages(start, len)) {
+	return true;
+      }
+    }
+  }
+  return true;
+}
+
+area *
+find_readonly_area()
+{
+  area *a;
+
+  for (a = active_dynamic_area->succ; a != all_areas; a = a->succ) {
+    if (a->code == AREA_READONLY) {
+      return a;
+    }
+  }
+  return NULL;
+}
+
+area *
+extend_readonly_area(natural more)
+{
+  area *a;
+  unsigned mask;
+  BytePtr new_start, new_end;
+
+  if ((a = find_readonly_area()) != NULL) {
+    if ((a->active + more) > a->high) {
+      return NULL;
+    }
+    mask = ((natural)a->active) & (page_size-1);
+    if (mask) {
+      UnProtectMemory(a->active-mask, page_size);
+    }
+    new_start = (BytePtr)(align_to_power_of_2(a->active,log2_page_size));
+    new_end = (BytePtr)(align_to_power_of_2(a->active+more,log2_page_size));
+    if (!CommitMemory(new_start, new_end-new_start)) {
+      return NULL;
+    }
+    return a;
+  }
+  return NULL;
+}
+
+LispObj image_base=0;
+BytePtr pure_space_start, pure_space_active, pure_space_limit;
+BytePtr static_space_start, static_space_active, static_space_limit;
+
+void
+raise_limit()
+{
+#ifdef RLIMIT_AS
+  struct rlimit r;
+  if (getrlimit(RLIMIT_AS, &r) == 0) {
+    r.rlim_cur = r.rlim_max;
+    setrlimit(RLIMIT_AS, &r);
+    /* Could limit heaplimit to rlim_max here if smaller? */
+  }
+#endif
+} 
+
+
+area *
+create_reserved_area(natural totalsize)
+{
+  Ptr h;
+  natural base;
+  BytePtr 
+    end, 
+    lastbyte, 
+    start, 
+    want = (BytePtr)IMAGE_BASE_ADDRESS;
+  area *reserved;
+  Boolean fatal = false;
+
+  totalsize = align_to_power_of_2((void *)totalsize, log2_heap_segment_size);
+    
+  if (totalsize < (PURESPACE_RESERVE + MIN_DYNAMIC_SIZE)) {
+    totalsize = PURESPACE_RESERVE + MIN_DYNAMIC_SIZE;
+    fatal = true;
+  }
+
+  start = ReserveMemoryForHeap(want, totalsize);
+
+  if (start == NULL) {
+    if (fatal) {
+      perror("minimal initial mmap");
+      exit(1);
+    }
+    return NULL;
+  }
+
+  h = (Ptr) start;
+  base = (natural) start;
+  image_base = base;
+  lastbyte = (BytePtr) (start+totalsize);
+  static_space_start = static_space_active = (BytePtr)STATIC_BASE_ADDRESS;
+  static_space_limit = static_space_start + STATIC_RESERVE;
+  pure_space_start = pure_space_active = start;
+  pure_space_limit = start + PURESPACE_SIZE;
+  start += PURESPACE_RESERVE;
+
+  /*
+    Allocate mark bits here.  They need to be 1/64 the size of the
+     maximum useable area of the heap (+ 3 words for the EGC.)
+  */
+  end = lastbyte;
+  end = (BytePtr) ((natural)((((natural)end) - ((totalsize+63)>>6)) & ~4095));
+
+  global_mark_ref_bits = (bitvector)end;
+  end = (BytePtr) ((natural)((((natural)end) - ((totalsize+63) >> 6)) & ~4095));
+  global_reloctab = (LispObj *) end;
+  reserved = new_area(start, end, AREA_VOID);
+  /* The root of all evil is initially linked to itself. */
+  reserved->pred = reserved->succ = reserved;
+  all_areas = reserved;
+  return reserved;
+}
+
+void *
+allocate_from_reserved_area(natural size)
+{
+  area *reserved = reserved_area;
+  BytePtr low = reserved->low, high = reserved->high;
+  natural avail = high-low;
+  
+  size = align_to_power_of_2(size, log2_heap_segment_size);
+
+  if (size > avail) {
+    return NULL;
+  }
+  reserved->low += size;
+  reserved->active = reserved->low;
+  reserved->ndnodes -= (size>>dnode_shift);
+  return low;
+}
+
+
+
+BytePtr reloctab_limit = NULL, markbits_limit = NULL;
+BytePtr low_relocatable_address = NULL, high_relocatable_address = NULL,
+  low_markable_address = NULL, high_markable_address = NULL;
+
+void
+map_initial_reloctab(BytePtr low, BytePtr high)  
+{
+  natural ndnodes, reloctab_size, n;
+
+  low_relocatable_address = low; /* will never change */
+  high_relocatable_address = high;
+  ndnodes = area_dnode(high,low);
+  reloctab_size = (sizeof(LispObj)*(((ndnodes+((1<<bitmap_shift)-1))>>bitmap_shift)+1));
+  
+  reloctab_limit = (BytePtr)align_to_power_of_2(((natural)global_reloctab)+reloctab_size,log2_page_size);
+  CommitMemory(global_reloctab,reloctab_limit-(BytePtr)global_reloctab);
+}
+
+void
+map_initial_markbits(BytePtr low, BytePtr high)
+{
+  natural
+    prefix_dnodes = area_dnode(low, pure_space_limit),
+    ndnodes = area_dnode(high, low),
+    prefix_size = (prefix_dnodes+7)>>3,
+    markbits_size = (3*sizeof(LispObj))+((ndnodes+7)>>3),
+    n;
+  low_markable_address = low;
+  high_markable_address = high;
+  dynamic_mark_ref_bits = (bitvector)(((BytePtr)global_mark_ref_bits)+prefix_size);
+  relocatable_mark_ref_bits = dynamic_mark_ref_bits;
+  n = align_to_power_of_2(markbits_size,log2_page_size);
+  markbits_limit = ((BytePtr)dynamic_mark_ref_bits)+n;
+  CommitMemory(dynamic_mark_ref_bits,n);
+}
+    
+void
+lower_heap_start(BytePtr new_low, area *a)
+{
+  natural new_dnodes = area_dnode(low_markable_address,new_low);
+
+  if (new_dnodes) {
+    natural n = (new_dnodes+7)>>3;
+
+    BytePtr old_markbits = (BytePtr)dynamic_mark_ref_bits,
+      new_markbits = old_markbits-n;
+    CommitMemory(new_markbits,n);
+    dynamic_mark_ref_bits = (bitvector)new_markbits;
+    if (a->refbits) {
+      a->refbits= dynamic_mark_ref_bits;
+    }
+    a->static_dnodes += new_dnodes;
+    a->ndnodes += new_dnodes;
+    a->low = new_low;
+    low_markable_address = new_low;
+    lisp_global(HEAP_START) = (LispObj)new_low;
+    static_cons_area->ndnodes = area_dnode(static_cons_area->high,new_low);
+  }
+}
+
+void
+ensure_gc_structures_writable()
+{
+  natural 
+    ndnodes = area_dnode(lisp_global(HEAP_END),low_relocatable_address),
+    markbits_size = (3*sizeof(LispObj))+((ndnodes+7)>>3),
+    reloctab_size = (sizeof(LispObj)*(((ndnodes+((1<<bitmap_shift)-1))>>bitmap_shift)+1)),
+    n;
+  BytePtr 
+    new_reloctab_limit = (BytePtr)align_to_power_of_2(((natural)global_reloctab)+reloctab_size,log2_page_size),
+    new_markbits_limit = (BytePtr)align_to_power_of_2(((natural)relocatable_mark_ref_bits)+markbits_size,log2_page_size);
+
+  if (new_reloctab_limit > reloctab_limit) {
+    n = new_reloctab_limit - reloctab_limit;
+    CommitMemory(reloctab_limit, n);
+    UnProtectMemory(reloctab_limit, n);
+    reloctab_limit = new_reloctab_limit;
+  }
+  
+  if (new_markbits_limit > markbits_limit) {
+    n = new_markbits_limit-markbits_limit;
+    CommitMemory(markbits_limit, n);
+    UnProtectMemory(markbits_limit, n);
+    markbits_limit = new_markbits_limit;
+  }
+}
+
+
+area *
+allocate_dynamic_area(natural initsize)
+{
+  natural totalsize = align_to_power_of_2(initsize, log2_heap_segment_size);
+  BytePtr start, end;
+  area *a;
+
+  start = allocate_from_reserved_area(totalsize);
+  if (start == NULL) {
+    fprintf(dbgout, "reserved area too small to load heap image\n");
+    exit(1);
+  }
+  end = start + totalsize;
+  a = new_area(start, end, AREA_DYNAMIC);
+  a->active = start+initsize;
+  add_area_holding_area_lock(a);
+  CommitMemory(start, end-start);
+  a->h = start;
+  a->softprot = NULL;
+  a->hardprot = NULL;
+  map_initial_reloctab(a->low, a->high);
+  map_initial_markbits(a->low, a->high);
+  lisp_global(HEAP_START) = ptr_to_lispobj(a->low);
+  lisp_global(HEAP_END) = ptr_to_lispobj(a->high);
+  return a;
+ }
+
+
+Boolean
+grow_dynamic_area(natural delta)
+{
+  area *a = active_dynamic_area, *reserved = reserved_area;
+  natural avail = reserved->high - reserved->low;
+  
+  delta = align_to_power_of_2(delta, log2_heap_segment_size);
+  if (delta > avail) {
+    return false;
+  }
+
+  if (!commit_pages(a->high,delta)) {
+    return false;
+  }
+
+
+  if (!allocate_from_reserved_area(delta)) {
+    return false;
+  }
+
+
+  a->high += delta;
+  a->ndnodes = area_dnode(a->high, a->low);
+  lisp_global(HEAP_END) += delta;
+  ensure_gc_structures_writable();
+  return true;
+}
+
+/*
+  As above.  Pages that're returned to the reserved_area are
+  "condemned" (e.g, we try to convince the OS that they never
+  existed ...)
+*/
+Boolean
+shrink_dynamic_area(natural delta)
+{
+  area *a = active_dynamic_area, *reserved = reserved_area;
+  
+  delta = align_to_power_of_2(delta, log2_heap_segment_size);
+
+  a->high -= delta;
+  a->ndnodes = area_dnode(a->high, a->low);
+  a->hardlimit = a->high;
+  uncommit_pages(a->high, delta);
+  reserved->low -= delta;
+  reserved->ndnodes += (delta>>dnode_shift);
+  lisp_global(HEAP_END) -= delta;
+  return true;
+}
+
+
+
+#ifndef WINDOWS
+void
+user_signal_handler (int signum, siginfo_t *info, ExceptionInformation *context)
+{
+  if (signum == SIGINT) {
+    lisp_global(INTFLAG) = (((signum<<8) + 1) << fixnumshift);
+  }
+  else if (signum == SIGTERM) {
+    lisp_global(INTFLAG) = (((signum<<8) + 2) << fixnumshift);
+  }
+  else if (signum == SIGQUIT) {
+    lisp_global(INTFLAG) = (((signum<<8) + 2) << fixnumshift);
+  }
+#ifdef DARWIN
+  DarwinSigReturn(context);
+#endif
+}
+
+#endif
+
+void
+register_user_signal_handler()
+{
+#ifdef WINDOWS
+  extern BOOL CALLBACK ControlEventHandler(DWORD);
+
+  signal(SIGINT, SIG_IGN);
+
+  SetConsoleCtrlHandler(ControlEventHandler,TRUE);
+#else
+  install_signal_handler(SIGINT, (void *)user_signal_handler);
+  install_signal_handler(SIGTERM, (void *)user_signal_handler);
+#endif
+}
+
+
+
+BytePtr
+initial_stack_bottom()
+{
+#ifndef WINDOWS
+  extern char **environ;
+  char *p = *environ;
+  while (*p) {
+    p += (1+strlen(p));
+  }
+  return (BytePtr)((((natural) p) +4095) & ~4095);
+#endif
+#ifdef WINDOWS
+  return (BytePtr)((current_stack_pointer() + 4095) & ~ 4095);
+#endif
+}
+
+
+
+  
+Ptr fatal_spare_ptr = NULL;
+
+
+void
+Fatal(StringPtr param0, StringPtr param1)
+{
+
+  if (fatal_spare_ptr) {
+    deallocate(fatal_spare_ptr);
+    fatal_spare_ptr = NULL;
+  }
+  fprintf(dbgout, "Fatal error: %s\n%s\n", param0, param1);
+  _exit(-1);
+}
+
+OSErr application_load_err = noErr;
+
+area *
+set_nil(LispObj);
+
+
+/* Check for the existence of a file named by 'path'; return true
+   if it seems to exist, without checking size, permissions, or
+   anything else. */
+Boolean
+probe_file(char *path)
+{
+  struct stat st;
+
+  return (stat(path,&st) == 0);
+}
+
+
+#ifdef WINDOWS
+/* Chop the trailing ".exe" from the kernel image name */
+wchar_t *
+chop_exe_suffix(wchar_t *path)
+{
+  int len = wcslen(path);
+  wchar_t *copy = malloc((len+1)*sizeof(wchar_t)), *tail;
+
+  wcscpy(copy,path);
+  tail = wcsrchr(copy, '.');
+  if (tail) {
+    *tail = 0;
+  }
+  return copy;
+}
+#endif
+
+#ifdef WINDOWS
+wchar_t *
+path_by_appending_image(wchar_t *path)
+{
+  int len = wcslen(path) + wcslen(L".image") + 1;
+  wchar_t *copy = (wchar_t *) malloc(len*sizeof(wchar_t));
+
+  if (copy) {
+    wcscpy(copy, path);
+    wcscat(copy, L".image");
+  }
+  return copy;
+}
+#else
+char *
+path_by_appending_image(char *path)
+{
+  int len = strlen(path) + strlen(".image") + 1;
+  char *copy = (char *) malloc(len);
+
+  if (copy) {
+    strcpy(copy, path);
+    strcat(copy, ".image");
+  }
+  return copy;
+}
+#endif
+
+char *
+case_inverted_path(char *path)
+{
+  char *copy = strdup(path), *base = copy, *work = copy, c;
+  if (copy == NULL) {
+    return NULL;
+  }
+  while(*work) {
+    if (*work++ == '/') {
+      base = work;
+    }
+  }
+  work = base;
+  while ((c = *work) != '\0') {
+    if (islower(c)) {
+      *work++ = toupper(c);
+    } else {
+      *work++ = tolower(c);
+    }
+  }
+  return copy;
+}
+/* 
+   The underlying file system may be case-insensitive (e.g., HFS),
+   so we can't just case-invert the kernel's name.
+   Tack ".image" onto the end of the kernel's name.  Much better ...
+*/
+#ifdef WINDOWS
+wchar_t *
+default_image_name(wchar_t *orig)
+{
+  wchar_t *path = chop_exe_suffix(orig);
+  wchar_t *image_name = path_by_appending_image(path);
+  return image_name;
+}
+#else
+char *
+default_image_name(char *orig)
+{
+#ifdef WINDOWS
+  char *path = chop_exe_suffix(orig);
+#else
+  char *path = orig;
+#endif
+  char *image_name = path_by_appending_image(path);
+#if !defined(WINDOWS) && !defined(DARWIN)
+  if (!probe_file(image_name)) {
+    char *legacy = case_inverted_path(path);
+    if (probe_file(legacy)) {
+      image_name = legacy;
+    }
+  }
+#endif
+  return image_name;
+}
+#endif
+
+
+
+char *program_name = NULL;
+#ifdef WINDOWS
+wchar_t *real_executable_name = NULL;
+#else
+char *real_executable_name = NULL;
+#endif
+
+#ifndef WINDOWS
+
+char *
+ensure_real_path(char *path)
+{
+  char buf[PATH_MAX*2], *p, *q;
+  int n;
+
+  p = realpath(path, buf);
+  
+  if (p == NULL) {
+    return path;
+  }
+  n = strlen(p);
+  q = malloc(n+1);
+  strcpy(q,p);
+  return q;
+}
+
+char *
+determine_executable_name(char *argv0)
+{
+#ifdef DARWIN
+  uint32_t len = 1024;
+  char exepath[1024], *p = NULL;
+
+  if (_NSGetExecutablePath(exepath, (void *)&len) == 0) {
+    p = malloc(len+1);
+    memmove(p, exepath, len);
+    p[len]=0;
+    return ensure_real_path(p);
+  } 
+  return ensure_real_path(argv0);
+#endif
+#ifdef LINUX
+  char exepath[PATH_MAX], *p;
+  int n;
+
+  if ((n = readlink("/proc/self/exe", exepath, PATH_MAX)) > 0) {
+    p = malloc(n+1);
+    memmove(p,exepath,n);
+    p[n]=0;
+    return p;
+  }
+  return argv0;
+#endif
+#ifdef FREEBSD
+  return ensure_real_path(argv0);
+#endif
+#ifdef SOLARIS
+  char exepath[PATH_MAX], proc_path[PATH_MAX], *p;
+  int n;
+
+  snprintf(proc_path,PATH_MAX-1,"/proc/%d/path/a.out",getpid());
+
+  if ((n = readlink(proc_path, exepath, PATH_MAX)) > 0) {
+    p = malloc(n+1);
+    memmove(p,exepath,n);
+    p[n]=0;
+    return p;
+  }
+  return ensure_real_path(argv0);
+#endif
+  return ensure_real_path(argv0);
+}
+#endif
+
+#ifdef WINDOWS
+wchar_t *
+determine_executable_name()
+{
+  DWORD nsize = 512, result;
+  wchar_t *buf = malloc(nsize*sizeof(wchar_t));
+
+  do {
+    result = GetModuleFileNameW(NULL, buf, nsize);
+    if (result == nsize) {
+      nsize *= 2;
+      buf = realloc(buf,nsize*sizeof(wchar_t));
+    } else {
+      return buf;
+    }
+  } while (1);
+}
+
+
+wchar_t *
+ensure_real_path(wchar_t *path)
+{
+  int bufsize = 256, n;
+
+  do {
+    wchar_t buf[bufsize];
+
+    n = GetFullPathNameW(path,bufsize,buf,NULL);
+    if (n == 0) {
+      return path;
+    }
+
+    if (n < bufsize) {
+      int i;
+      wchar_t *q = calloc(n+1,sizeof(wchar_t));
+
+      for (i = 0; i < n; i++) {
+        q[i] = buf[i];
+      }
+      return q;
+    }
+    bufsize = n+1;
+  } while (1);
+}
+#endif
+
+void
+usage_exit(char *herald, int exit_status, char* other_args)
+{
+  if (herald && *herald) {
+    fprintf(dbgout, "%s\n", herald);
+  }
+  fprintf(dbgout, "usage: %s <options>\n", program_name);
+  fprintf(dbgout, "\t or %s <image-name>\n", program_name);
+  fprintf(dbgout, "\t where <options> are one or more of:\n");
+  if (other_args && *other_args) {
+    fputs(other_args, dbgout);
+  }
+  fprintf(dbgout, "\t-R, --heap-reserve <n>: reserve <n> (default: %lld)\n",
+	  (u64_t) reserved_area_size);
+  fprintf(dbgout, "\t\t bytes for heap expansion\n");
+  fprintf(dbgout, "\t-S, --stack-size <n>: set  size of initial thread's control stack to <n>\n");
+  fprintf(dbgout, "\t-Z, --thread-stack-size <n>: set default size of first (listener)  thread's stacks based on <n>\n");
+  fprintf(dbgout, "\t-b, --batch: exit when EOF on *STANDARD-INPUT*\n");
+  fprintf(dbgout, "\t--no-sigtrap : obscure option for running under GDB\n");
+  fprintf(dbgout, "\t-I, --image-name <image-name>\n");
+#ifndef WINDOWS
+  fprintf(dbgout, "\t and <image-name> defaults to %s\n", 
+	  default_image_name(program_name));
+#endif
+  fprintf(dbgout, "\n");
+  _exit(exit_status);
+}
+
+int no_sigtrap = 0;
+#ifdef WINDOWS
+wchar_t *image_name = NULL;
+#else
+char *image_name = NULL;
+#endif
+int batch_flag = 0;
+
+
+natural
+parse_numeric_option(char *arg, char *argname, natural default_val)
+{
+  char *tail;
+  natural val = 0;
+
+  val = strtoul(arg, &tail, 0);
+  switch(*tail) {
+  case '\0':
+    break;
+    
+  case 'M':
+  case 'm':
+    val = val << 20;
+    break;
+    
+  case 'K':
+  case 'k':
+    val = val << 10;
+    break;
+    
+  case 'G':
+  case 'g':
+    val = val << 30;
+    break;
+    
+  default:
+    fprintf(dbgout, "couldn't parse %s argument %s", argname, arg);
+    val = default_val;
+    break;
+  }
+  return val;
+}
+  
+
+
+/* 
+   The set of arguments recognized by the kernel is
+   likely to remain pretty small and pretty simple.
+   This removes everything it recognizes from argv;
+   remaining args will be processed by lisp code.
+*/
+
+void
+process_options(int argc, char *argv[], wchar_t *shadow[])
+{
+  int i, j, k, num_elide, flag, arg_error;
+  char *arg, *val;
+  wchar_t *warg, *wval;
+#ifdef DARWIN
+  extern int NXArgc;
+#endif
+
+  for (i = 1; i < argc;) {
+    arg = argv[i];
+    if (shadow) {
+      warg = shadow[i];
+    }
+    arg_error = 0;
+    if (*arg != '-') {
+      i++;
+    } else {
+      num_elide = 0;
+      val = NULL;
+      if ((flag = (strncmp(arg, "-I", 2) == 0)) ||
+	  (strcmp (arg, "--image-name") == 0)) {
+	if (flag && arg[2]) {
+	  val = arg+2;          
+          if (shadow) {
+            wval = warg+2;
+          }
+	  num_elide = 1;
+	} else {
+	  if ((i+1) < argc) {
+	    val = argv[i+1];
+            if (shadow) {
+              wval = shadow[i+1];
+            }
+	    num_elide = 2;
+	  } else {
+	    arg_error = 1;
+	  }
+	}
+	if (val) {
+#ifdef WINDOWS
+          image_name = wval;
+#else
+	  image_name = val;
+#endif
+	}
+      } else if ((flag = (strncmp(arg, "-R", 2) == 0)) ||
+		 (strcmp(arg, "--heap-reserve") == 0)) {
+	natural reserved_size = reserved_area_size;
+
+	if (flag && arg[2]) {
+	  val = arg+2;
+	  num_elide = 1;
+	} else {
+	  if ((i+1) < argc) {
+	    val = argv[i+1];
+	    num_elide = 2;
+	  } else {
+	    arg_error = 1;
+	  }
+	}
+
+	if (val) {
+	  reserved_size = parse_numeric_option(val, 
+					       "-R/--heap-reserve", 
+					       reserved_area_size);
+	}
+
+	if (reserved_size <= MAXIMUM_MAPPABLE_MEMORY) {
+	  reserved_area_size = reserved_size;
+	}
+
+      } else if ((flag = (strncmp(arg, "-S", 2) == 0)) ||
+		 (strcmp(arg, "--stack-size") == 0)) {
+	natural stack_size;
+
+	if (flag && arg[2]) {
+	  val = arg+2;
+	  num_elide = 1;
+	} else {
+	  if ((i+1) < argc) {
+	    val = argv[i+1];
+	    num_elide = 2;
+	  } else {
+	    arg_error = 1;
+	  }
+	}
+
+	if (val) {
+	  stack_size = parse_numeric_option(val, 
+					    "-S/--stack-size", 
+					    initial_stack_size);
+	  
+
+	  if (stack_size >= MIN_CSTACK_SIZE) {
+	    initial_stack_size = stack_size;
+	  }
+	}
+
+      } else if ((flag = (strncmp(arg, "-Z", 2) == 0)) ||
+		 (strcmp(arg, "--thread-stack-size") == 0)) {
+	natural stack_size;
+
+	if (flag && arg[2]) {
+	  val = arg+2;
+	  num_elide = 1;
+	} else {
+	  if ((i+1) < argc) {
+	    val = argv[i+1];
+	    num_elide = 2;
+	  } else {
+	    arg_error = 1;
+	  }
+	}
+
+	if (val) {
+	  stack_size = parse_numeric_option(val, 
+					    "-Z/--thread-stack-size", 
+					    thread_stack_size);
+	  
+
+	  if (stack_size >= MIN_CSTACK_SIZE) {
+	   thread_stack_size = stack_size;
+	  }
+          if (thread_stack_size >= (1LL<<((WORD_SIZE-fixnumshift)-1))) {
+            thread_stack_size = (1LL<<((WORD_SIZE-fixnumshift)-1))-1;
+          }
+          
+	}
+
+      } else if (strcmp(arg, "--no-sigtrap") == 0) {
+	no_sigtrap = 1;
+	num_elide = 1;
+      } else if ((strcmp(arg, "-b") == 0) ||
+		 (strcmp(arg, "--batch") == 0)) {
+	batch_flag = 1;
+	num_elide = 1;
+      } else if (strcmp(arg,"--") == 0) {
+        break;
+      } else {
+	i++;
+      }
+      if (arg_error) {
+	usage_exit("error in program arguments", 1, "");
+      }
+      if (num_elide) {
+	for (j = i+num_elide, k=i; j < argc; j++, k++) {
+	  argv[k] = argv[j];
+          if (shadow) {
+            shadow[k] = shadow[j];
+          }
+	}
+	argc -= num_elide;
+#ifdef DARWIN
+	NXArgc -= num_elide;
+#endif
+	argv[argc] = NULL;
+        if (shadow) {
+          shadow[argc] = NULL;
+        }
+      }
+    }
+  }
+}
+
+#ifdef WINDOWS
+void
+terminate_lisp()
+{
+  _exit(EXIT_FAILURE);
+}
+#else
+pid_t main_thread_pid = (pid_t)0;
+
+void
+terminate_lisp()
+{
+  kill(main_thread_pid, SIGKILL);
+  _exit(-1);
+}
+#endif
+
+#ifdef DARWIN
+#define min_os_version "8.0"    /* aka Tiger */
+#endif
+#ifdef LINUX
+#ifdef PPC
+#define min_os_version "2.2"
+#endif
+#ifdef X86
+#define min_os_version "2.6"
+#endif
+#endif
+#ifdef FREEBSD
+#define min_os_version "6.0"
+#endif
+#ifdef SOLARIS
+#define min_os_version "5.10"
+#endif
+
+#ifdef PPC
+#if defined(PPC64) || !defined(DARWIN)
+/* ld64 on Darwin doesn't offer anything close to reliable control
+   over the layout of a program in memory.  About all that we can
+   be assured of is that the canonical subprims jump table address
+   (currently 0x5000) is unmapped.  Map that page, and copy the
+   actual spjump table there. */
+
+
+void
+remap_spjump()
+{
+  extern opcode spjump_start, spjump_end;
+  pc new,
+    old = &spjump_start,
+    limit = &spjump_end,
+    work;
+  opcode instr;
+  void *target;
+  int disp;
+  
+  if (old != (pc)SPJUMP_TARGET_ADDRESS) {
+    new = mmap((pc) SPJUMP_TARGET_ADDRESS,
+               0x1000,
+               PROT_READ | PROT_WRITE | PROT_EXEC,
+               MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+               -1,
+               0);
+    if (new != (pc) SPJUMP_TARGET_ADDRESS) {
+      perror("remap spjump");
+      _exit(1);
+    }
+    
+    for (work = new; old < limit; work++, old++) {
+      instr = *old;
+      disp = instr & ((1<<26)-1);
+      target = (void*)old+disp;
+      disp = target-(void *)work;
+      *work = ((instr >> 26) << 26) | disp;
+    }
+    xMakeDataExecutable(new, (void*)work-(void*)new);
+    ProtectMemory(new, 0x1000);
+  }
+}
+#endif
+#endif
+
+#ifdef X86
+#ifdef WINDOWS
+
+/* By using linker tricks, we ensure there's memory between 0x11000
+   and 0x21000, so we just need to fix permissions and copy the spjump
+   table. */
+
+void
+remap_spjump()
+{
+  extern opcode spjump_start;
+  DWORD old_protect;
+
+  if ((void *)(&spjump_start) != (void *) SPJUMP_TARGET_ADDRESS) {
+    if (!VirtualProtect((pc) SPJUMP_TARGET_ADDRESS,
+                        0x1000,
+                        PAGE_EXECUTE_READWRITE,
+                        &old_protect)) {
+      wperror("VirtualProtect spjump");
+      _exit(1);
+    }
+    memmove((pc) SPJUMP_TARGET_ADDRESS, &spjump_start, 0x1000);
+  }
+}
+#else
+void
+remap_spjump()
+{
+  extern opcode spjump_start;
+  pc new = mmap((pc) SPJUMP_TARGET_ADDRESS,
+                0x1000,
+                PROT_READ | PROT_WRITE | PROT_EXEC,
+                MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+                -1,
+                0),
+    old = &spjump_start;
+  if (new == (pc)-1) {
+    perror("remap spjump");
+    _exit(1);
+  }
+  memmove(new, old, 0x1000);
+}
+#endif
+#endif
+
+
+void
+check_os_version(char *progname)
+{
+#ifdef WINDOWS
+  /* We should be able to run with any version of Windows that actually gets here executing the binary, so don't do anything for now. */
+#else
+  struct utsname uts;
+  long got, want;
+  char *got_end,*want_end;
+#ifdef X8632
+  extern Boolean rcontext_readonly;
+#endif
+
+  want = strtoul(min_os_version,&want_end,10);
+
+  uname(&uts);
+  got = strtoul(uts.release,&got_end,10);
+#ifdef X8632
+#ifdef FREEBSD
+  if (!strcmp(uts.machine,"amd64")) {
+    rcontext_readonly = true;
+  }
+#endif
+#endif
+  while (got == want) {
+    if (*want_end == '.') {
+      want = strtoul(want_end+1,&want_end,10);
+      got = 0;
+      if (*got_end == '.') {
+        got = strtoul(got_end+1,&got_end,10);
+      } else {
+        break;
+      }
+    } else {
+      break;
+    }
+  }
+
+  if (got < want) {
+    fprintf(dbgout, "\n%s requires %s version %s or later; the current version is %s.\n", progname, uts.sysname, min_os_version, uts.release);
+    exit(1);
+  }
+#endif
+}
+
+#ifdef X86
+/*
+  This should determine the cache block size.  It should also
+  probably complain if we don't have (at least) SSE2.
+*/
+extern int cpuid(natural, natural*, natural*, natural*);
+
+#define X86_FEATURE_CMOV    (1<<15)
+#define X86_FEATURE_CLFLUSH (1<<19)
+#define X86_FEATURE_MMX     (1<<23)
+#define X86_FEATURE_SSE     (1<<25)
+#define X86_FEATURE_SSE2    (1<<26)
+
+#define X86_REQUIRED_FEATURES (X86_FEATURE_CMOV|X86_FEATURE_MMX|X86_FEATURE_SSE|X86_FEATURE_SSE2)
+
+Boolean
+check_x86_cpu()
+{
+  natural eax, ebx, ecx, edx;
+
+  eax = cpuid(0, &ebx, &ecx, &edx);
+
+  if (eax >= 1) {
+    eax = cpuid(1, &ebx, &ecx, &edx);
+    cache_block_size = (ebx & 0xff00) >> 5;
+    if ((X86_REQUIRED_FEATURES & edx) == X86_REQUIRED_FEATURES) {
+      return true;
+    }
+    /* It's very unlikely that SSE2 would be present and other things
+       that we want wouldn't.  If they don't have MMX or CMOV either,
+       might as well tell them. */
+    if ((edx & X86_FEATURE_SSE2) == 0) {
+      fprintf(dbgout, "This CPU doesn't support the SSE2 instruction set\n");
+    }
+    if ((edx & X86_FEATURE_MMX) == 0) {
+      fprintf(dbgout, "This CPU doesn't support the MMX instruction set\n");
+    }
+    if ((edx & X86_FEATURE_CMOV) == 0) {
+      fprintf(dbgout, "This CPU doesn't support the CMOV instruction\n");
+    }
+    
+  }
+  return false;
+}
+#endif
+
+void
+lazarus()
+{
+  TCR *tcr = get_tcr(false);
+  if (tcr) {
+    /* Some threads may be dying; no threads should be created. */
+    LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+    tcr->vs_area->active = tcr->vs_area->high - node_size;
+    tcr->save_vsp = (LispObj *)(tcr->vs_area->active);
+    tcr->ts_area->active = tcr->ts_area->high;
+    tcr->save_tsp = (LispObj *)(tcr->ts_area->active);
+    tcr->catch_top = 0;
+    tcr->db_link = 0;
+    tcr->xframe = 0;
+    start_lisp(tcr, 0);
+  }
+}
+
+#ifdef LINUX
+#ifdef X8664
+#include <asm/prctl.h>
+#include <sys/prctl.h>
+
+void
+ensure_gs_available(char *progname)
+{
+  LispObj fs_addr = 0L, gs_addr = 0L, cur_thread = (LispObj)pthread_self();
+  char *gnu_get_libc_version(void);
+  
+  arch_prctl(ARCH_GET_GS, &gs_addr);
+  arch_prctl(ARCH_GET_FS, &fs_addr);
+  if ((gs_addr == cur_thread) && (fs_addr != cur_thread)) {
+    fprintf(dbgout, "The installed C library - version %s - seems to be using the %%gs register for thread storage.\n\"%s\" cannot run, since it expects to be\nable to use that register for its own purposes.\n", gnu_get_libc_version(),progname);
+    _exit(1);
+  }
+}
+#endif
+#endif
+
+Boolean 
+bogus_fp_exceptions = false;
+
+typedef
+float (*float_arg_returns_float)(float);
+
+float
+fcallf(float_arg_returns_float fun, float arg)
+{
+  return fun(arg);
+}
+
+void
+check_bogus_fp_exceptions()
+{
+#ifdef X8664
+  float asinf(float),result;
+    
+
+  natural save_mxcsr = get_mxcsr(), post_mxcsr;
+  set_mxcsr(0x1f80);
+
+  result = fcallf(asinf, 1.0);
+  post_mxcsr = get_mxcsr();
+  set_mxcsr(save_mxcsr);
+  if (post_mxcsr & (FE_ALL_EXCEPT & (~FE_INEXACT))) {
+    bogus_fp_exceptions = true;
+  }
+#endif
+}
+
+#ifdef WINDOWS
+char *
+utf_16_to_utf_8(wchar_t *utf_16)
+{
+  int utf8len = WideCharToMultiByte(CP_UTF8,
+                                    0,
+                                    utf_16,
+                                    -1,
+                                    NULL,
+                                    0,
+                                    NULL,
+                                    NULL);
+
+  char *utf_8 = malloc(utf8len);
+
+  WideCharToMultiByte(CP_UTF8,
+                      0,
+                      utf_16,
+                      -1,
+                      utf_8,
+                      utf8len,
+                      NULL,
+                      NULL);
+
+  return utf_8;
+}
+
+char **
+wide_argv_to_utf_8(wchar_t *wide_argv[], int argc)
+{
+  char** argv = calloc(argc+1,sizeof(char *));
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (wide_argv[i]) {
+      argv[i] = utf_16_to_utf_8(wide_argv[i]);
+    } else {
+      argv[i] = NULL;
+    }
+  }
+  return argv;
+}
+#endif
+
+
+  
+
+
+int
+main(int argc, char *argv[]
+#ifndef WINDOWS
+, char *envp[], void *aux
+#endif
+)
+{
+  extern int page_size;
+  natural default_g0_threshold = G0_AREA_THRESHOLD,
+    default_g1_threshold = G1_AREA_THRESHOLD,
+    default_g2_threshold = G2_AREA_THRESHOLD,
+    lisp_heap_threshold_from_image = 0;
+  Boolean egc_enabled =
+#ifdef DISABLE_EGC
+    false
+#else
+    true
+#endif
+    ;
+  Boolean lisp_heap_threshold_set_from_command_line = false;
+  wchar_t **utf_16_argv = NULL;
+
+#ifdef PPC
+  extern int altivec_present;
+#endif
+#ifdef WINDOWS
+  extern LispObj load_image(wchar_t *);
+#else
+  extern LispObj load_image(char *);
+#endif
+  area *a;
+  BytePtr stack_base, current_sp = (BytePtr) current_stack_pointer();
+  TCR *tcr;
+
+  dbgout = stderr;
+
+#ifdef WINDOWS
+  {
+    int wide_argc;
+    extern void init_winsock(void);
+    extern void init_windows_io(void);
+
+    _fmode = O_BINARY;
+    _setmode(1, O_BINARY);
+    _setmode(2, O_BINARY);
+    setvbuf(dbgout, NULL, _IONBF, 0);
+    init_winsock();
+    init_windows_io();
+    utf_16_argv = CommandLineToArgvW(GetCommandLineW(),&wide_argc);
+  }
+#endif
+
+  check_os_version(argv[0]);
+#ifdef WINDOWS
+  real_executable_name = determine_executable_name();
+#else
+  real_executable_name = determine_executable_name(argv[0]);
+#endif
+  page_size = getpagesize(); /* Implement with GetSystemInfo on Windows w/o MinGW */
+
+  check_bogus_fp_exceptions();
+#ifdef LINUX
+#ifdef X8664
+  ensure_gs_available(real_executable_name);
+#endif
+#endif
+#if (defined(DARWIN) && defined(PPC64)) || (defined(LINUX) && defined(PPC))|| defined(X8664) || (defined(X8632) && !defined(DARWIN))
+  remap_spjump();
+#endif
+
+#ifdef PPC
+#ifdef LINUX
+  {
+    ElfW(auxv_t) *av = aux;
+    int hwcap, done = false;
+    
+    if (av) {
+      do {
+	switch (av->a_type) {
+	case AT_DCACHEBSIZE:
+	  cache_block_size = av->a_un.a_val;
+	  break;
+
+	case AT_HWCAP:
+	  hwcap = av->a_un.a_val;
+	  altivec_present = ((hwcap & PPC_FEATURE_HAS_ALTIVEC) != 0);
+	  break;
+
+	case AT_NULL:
+	  done = true;
+	  break;
+	}
+	av++;
+      } while (!done);
+    }
+  }
+#endif
+#ifdef DARWIN
+  {
+    unsigned value = 0;
+    size_t len = sizeof(value);
+    int mib[2];
+    
+    mib[0] = CTL_HW;
+    mib[1] = HW_CACHELINE;
+    if (sysctl(mib,2,&value,&len, NULL, 0) != -1) {
+      if (len == sizeof(value)) {
+	cache_block_size = value;
+      }
+    }
+    mib[1] = HW_VECTORUNIT;
+    value = 0;
+    len = sizeof(value);
+    if (sysctl(mib,2,&value,&len, NULL, 0) != -1) {
+      if (len == sizeof(value)) {
+	altivec_present = value;
+      }
+    }
+  }
+#endif
+#endif
+
+#ifdef X86
+  if (!check_x86_cpu()) {
+    fprintf(dbgout, "CPU doesn't support required features\n");
+    exit(1);
+  }
+#endif
+
+#ifdef SOLARIS
+#ifdef X8632
+  {
+    extern void solaris_ldt_init(void);
+    solaris_ldt_init();
+  }
+#endif
+#endif
+
+#ifndef WINDOWS
+  main_thread_pid = getpid();
+#endif
+  tcr_area_lock = (void *)new_recursive_lock();
+
+  program_name = argv[0];
+  if ((argc == 2) && (*argv[1] != '-')) {
+#ifdef WINDOWS
+    image_name = utf_16_argv[1];
+#else
+    image_name = argv[1];
+#endif
+    argv[1] = NULL;
+#ifdef WINDOWS
+    utf_16_argv[1] = NULL;
+#endif
+  } else {
+    process_options(argc,argv,utf_16_argv);
+  }
+  if (lisp_heap_gc_threshold != DEFAULT_LISP_HEAP_GC_THRESHOLD) {
+    lisp_heap_threshold_set_from_command_line = true;
+  }
+
+  initial_stack_size = ensure_stack_limit(initial_stack_size);
+  if (image_name == NULL) {
+    if (check_for_embedded_image(real_executable_name)) {
+      image_name = real_executable_name;
+    } else {
+      image_name = default_image_name(real_executable_name);
+    }
+  }
+
+  while (1) {
+    if (create_reserved_area(reserved_area_size)) {
+      break;
+    }
+    reserved_area_size = reserved_area_size *.9;
+  }
+
+  gc_init();
+
+  set_nil(load_image(image_name));
+  lisp_heap_threshold_from_image = lisp_global(LISP_HEAP_THRESHOLD);
+  if (lisp_heap_threshold_from_image) {
+    if ((!lisp_heap_threshold_set_from_command_line) &&
+        (lisp_heap_threshold_from_image != lisp_heap_gc_threshold)) {
+      lisp_heap_gc_threshold = lisp_heap_threshold_from_image;
+      resize_dynamic_heap(active_dynamic_area->active,lisp_heap_gc_threshold);
+    }
+    /* If lisp_heap_threshold_from_image was set, other image params are
+       valid. */
+    default_g0_threshold = lisp_global(G0_THRESHOLD);
+    default_g1_threshold = lisp_global(G1_THRESHOLD);
+    default_g2_threshold = lisp_global(G2_THRESHOLD);
+    egc_enabled = lisp_global(EGC_ENABLED);
+  }
+
+  lisp_global(TCR_AREA_LOCK) = ptr_to_lispobj(tcr_area_lock);
+
+#ifdef X86
+  lisp_global(SUBPRIMS_BASE) = (LispObj)((1<<16)+(5<<10));
+#else
+  lisp_global(SUBPRIMS_BASE) = (LispObj)(5<<10);
+#endif
+  lisp_global(RET1VALN) = (LispObj)&ret1valn;
+  lisp_global(LEXPR_RETURN) = (LispObj)&nvalret;
+  lisp_global(LEXPR_RETURN1V) = (LispObj)&popj;
+  lisp_global(ALL_AREAS) = ptr_to_lispobj(all_areas);
+  lisp_global(DEFAULT_ALLOCATION_QUANTUM) = log2_heap_segment_size << fixnumshift;
+  lisp_global(STACK_SIZE) = thread_stack_size<<fixnumshift;
+
+
+  exception_init();
+
+  
+
+#ifdef WINDOWS
+  lisp_global(IMAGE_NAME) = ptr_to_lispobj(utf_16_to_utf_8(ensure_real_path(image_name)));
+  lisp_global(KERNEL_PATH) = ptr_to_lispobj(utf_16_to_utf_8(real_executable_name));
+  lisp_global(ARGV) = ptr_to_lispobj(wide_argv_to_utf_8(utf_16_argv, argc));
+#else
+  lisp_global(IMAGE_NAME) = ptr_to_lispobj(ensure_real_path(image_name));
+  lisp_global(KERNEL_PATH) = ptr_to_lispobj(real_executable_name);
+  lisp_global(ARGV) = ptr_to_lispobj(argv);
+#endif
+  lisp_global(KERNEL_IMPORTS) = (LispObj)import_ptrs_base;
+
+  lisp_global(GET_TCR) = (LispObj) get_tcr;
+  *(double *) &(lisp_global(DOUBLE_FLOAT_ONE)) = (double) 1.0;
+
+  lisp_global(HOST_PLATFORM) = (LispObj) PLATFORM << fixnumshift;
+
+  lisp_global(BATCH_FLAG) = (batch_flag << fixnumshift);
+
+  a = active_dynamic_area;
+
+  if (nilreg_area != NULL) {
+    BytePtr lowptr = (BytePtr) a->low;
+
+    /* Create these areas as AREA_STATIC, change them to AREA_DYNAMIC */
+    g1_area = new_area(lowptr, lowptr, AREA_STATIC);
+    g2_area = new_area(lowptr, lowptr, AREA_STATIC);
+    tenured_area = new_area(lowptr, lowptr, AREA_STATIC);
+    add_area_holding_area_lock(tenured_area);
+    add_area_holding_area_lock(g2_area);
+    add_area_holding_area_lock(g1_area);
+
+    g1_area->code = AREA_DYNAMIC;
+    g2_area->code = AREA_DYNAMIC;
+    tenured_area->code = AREA_DYNAMIC;
+
+/*    a->older = g1_area; */ /* Not yet: this is what "enabling the EGC" does. */
+    g1_area->younger = a;
+    g1_area->older = g2_area;
+    g2_area->younger = g1_area;
+    g2_area->older = tenured_area;
+    tenured_area->younger = g2_area;
+    tenured_area->refbits = dynamic_mark_ref_bits;
+    managed_static_area->refbits = global_mark_ref_bits;
+    a->markbits = dynamic_mark_ref_bits;
+    tenured_area->static_dnodes = a->static_dnodes;
+    a->static_dnodes = 0;
+    tenured_area->static_used = a->static_used;
+    a->static_used = 0;
+    lisp_global(TENURED_AREA) = ptr_to_lispobj(tenured_area);
+    lisp_global(STATIC_CONS_AREA) = ptr_to_lispobj(static_cons_area);
+    lisp_global(REFBITS) = ptr_to_lispobj(global_mark_ref_bits);
+    g2_area->threshold = default_g2_threshold;
+    g1_area->threshold = default_g1_threshold;
+    a->threshold = default_g0_threshold;
+  }
+
+  tcr = new_tcr(initial_stack_size, MIN_TSTACK_SIZE);
+  stack_base = initial_stack_bottom()-xStackSpace();
+  init_threads((void *)(stack_base), tcr);
+  thread_init_tcr(tcr, current_sp, current_sp-stack_base);
+
+  if (lisp_global(STATIC_CONSES) == 0) {
+    lisp_global(STATIC_CONSES) = lisp_nil;
+  }
+
+  lisp_global(EXCEPTION_LOCK) = ptr_to_lispobj(new_recursive_lock());
+  enable_fp_exceptions();
+  register_user_signal_handler();
+
+#ifdef PPC
+  lisp_global(ALTIVEC_PRESENT) = altivec_present << fixnumshift;
+#endif
+#if STATIC
+  lisp_global(STATICALLY_LINKED) = 1 << fixnumshift;
+#endif
+  tcr->prev = tcr->next = tcr;
+#ifndef WINDOWS
+  lisp_global(INTERRUPT_SIGNAL) = (LispObj) box_fixnum(SIGNAL_FOR_PROCESS_INTERRUPT);
+#endif
+  tcr->vs_area->active -= node_size;
+  *(--tcr->save_vsp) = nrs_TOPLFUNC.vcell;
+  nrs_TOPLFUNC.vcell = lisp_nil;
+#ifdef GC_INTEGRITY_CHECKING
+  (nrs_GC_EVENT_STATUS_BITS.vcell |= gc_integrity_check_bit);
+#endif
+  if (egc_enabled) {
+    egc_control(true, NULL);
+  } else {
+    lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(managed_static_area->active,managed_static_area->low);
+  }
+  atexit(lazarus);
+  start_lisp(TCR_TO_TSD(tcr), 0);
+  _exit(0);
+}
+
+area *
+set_nil(LispObj r)
+{
+
+  if (lisp_nil == (LispObj)NULL) {
+
+    lisp_nil = r;
+  }
+  return NULL;
+}
+
+
+void
+xMakeDataExecutable(void *start, unsigned long nbytes)
+{
+#ifndef X86
+  extern void flush_cache_lines();
+  natural ustart = (natural) start, base, end;
+  
+  base = (ustart) & ~(cache_block_size-1);
+  end = (ustart + nbytes + cache_block_size - 1) & ~(cache_block_size-1);
+  flush_cache_lines(base, (end-base)/cache_block_size, cache_block_size);
+#endif
+}
+
+natural
+xStackSpace()
+{
+  return initial_stack_size+CSTACK_HARDPROT+CSTACK_SOFTPROT;
+}
+
+#ifndef DARWIN
+#ifdef WINDOWS
+extern void *windows_open_shared_library(char *);
+
+void *
+xGetSharedLibrary(char *path, int mode)
+{
+  return windows_open_shared_library(path);
+}
+#else
+void *
+xGetSharedLibrary(char *path, int mode)
+{
+  return dlopen(path, mode);
+}
+#endif
+#else
+void *
+xGetSharedLibrary(char *path, int *resultType)
+{
+#if 0
+  NSObjectFileImageReturnCode code;
+  NSObjectFileImage	         moduleImage;
+  NSModule		         module;
+  const struct mach_header *     header;
+  const char *                   error;
+  void *                         result;
+  /* not thread safe */
+  /*
+  static struct {
+    const struct mach_header  *header;
+    NSModule	              *module;
+    const char                *error;
+  } results;	
+  */
+  result = NULL;
+  error = NULL;
+
+  /* first try to open this as a bundle */
+  code = NSCreateObjectFileImageFromFile(path,&moduleImage);
+  if (code != NSObjectFileImageSuccess &&
+      code != NSObjectFileImageInappropriateFile &&
+      code != NSObjectFileImageAccess)
+    {
+      /* compute error strings */
+      switch (code)
+	{
+	case NSObjectFileImageFailure:
+	  error = "NSObjectFileImageFailure";
+	  break;
+	case NSObjectFileImageArch:
+	  error = "NSObjectFileImageArch";
+	  break;
+	case NSObjectFileImageFormat:
+	  error = "NSObjectFileImageFormat";
+	  break;
+	case NSObjectFileImageAccess:
+	  /* can't find the file */
+	  error = "NSObjectFileImageAccess";
+	  break;
+	default:
+	  error = "unknown error";
+	}
+      *resultType = 0;
+      return (void *)error;
+    }
+  if (code == NSObjectFileImageInappropriateFile ||
+      code == NSObjectFileImageAccess ) {
+    /* the pathname might be a partial pathane (hence the access error)
+       or it might be something other than a bundle, if so perhaps
+       it is a .dylib so now try to open it as a .dylib */
+
+    /* protect against redundant loads, Gary Byers noticed possible
+       heap corruption if this isn't done */
+    header = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR |
+			NSADDIMAGE_OPTION_WITH_SEARCHING |
+			NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED);
+    if (!header)
+      header = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR |
+			  NSADDIMAGE_OPTION_WITH_SEARCHING);
+    result = (void *)header;
+    *resultType = 1;
+  }
+  else if (code == NSObjectFileImageSuccess) {
+    /* we have a sucessful module image
+       try to link it, don't bind symbols privately */
+
+    module = NSLinkModule(moduleImage, path,
+			  NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_BINDNOW);
+    NSDestroyObjectFileImage(moduleImage);	
+    result = (void *)module;
+    *resultType = 2;
+  }
+  if (!result)
+    {
+      /* compute error string */
+      NSLinkEditErrors ler;
+      int lerno;
+      const char* file;
+      NSLinkEditError(&ler,&lerno,&file,&error);
+      if (error) {
+	result = (void *)error;
+	*resultType = 0;
+      }
+    }
+  return result;
+#else
+  const char *                   error;
+  void *                         result;
+
+  result = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+  
+  if (result == NULL) {
+    error = dlerror();
+    *resultType = 0;
+    return (void *)error;
+  }
+  *resultType = 1;
+  return result;
+#endif
+}
+#endif
+
+
+
+int
+fd_setsize_bytes()
+{
+  return FD_SETSIZE/8;
+}
+
+void
+do_fd_set(int fd, fd_set *fdsetp)
+{
+  FD_SET(fd, fdsetp);
+}
+
+void
+do_fd_clr(int fd, fd_set *fdsetp)
+{
+  FD_CLR(fd, fdsetp);
+}
+
+int
+do_fd_is_set(int fd, fd_set *fdsetp)
+{
+  return FD_ISSET(fd,fdsetp);
+}
+
+
+void
+do_fd_zero(fd_set *fdsetp)
+{
+  FD_ZERO(fdsetp);
+}
+
+#include "image.h"
+
+
+
+Boolean
+check_for_embedded_image (
+#ifdef WINDOWS
+                          wchar_t *path
+#else
+                          char *path
+#endif
+                          )
+{
+#ifdef WINDOWS
+  int fd = wopen(path, O_RDONLY);
+#else  
+  int fd = open(path, O_RDONLY);
+#endif
+
+  Boolean image_is_embedded = false;
+
+  if (fd >= 0) {
+    openmcl_image_file_header h;
+
+    if (find_openmcl_image_file_header (fd, &h)) {
+      image_is_embedded = true;
+    }
+    close (fd);
+  }
+  return image_is_embedded;
+}
+
+LispObj
+load_image(
+#ifdef WINDOWS
+           wchar_t * path
+#else
+           char *path
+#endif
+)
+{
+#ifdef WINDOWS
+  int fd = wopen(path, O_RDONLY, 0666), err;
+#else
+  int fd = open(path, O_RDONLY, 0666), err;
+#endif
+  LispObj image_nil = 0;
+
+  if (fd > 0) {
+    openmcl_image_file_header ih;
+
+    errno = 0;
+    image_nil = load_openmcl_image(fd, &ih);
+    /* We -were- using a duplicate fd to map the file; that
+       seems to confuse Darwin (doesn't everything ?), so
+       we'll instead keep the original file open.
+    */
+    err = errno;
+    if (!image_nil) {
+      close(fd);
+    }
+#ifdef WINDOWS
+    /* We currently don't actually map the image, and leaving the file
+       open seems to make it difficult to write to reliably. */
+    if (image_nil) {
+      close(fd);
+    }
+#endif
+  } else {
+    err = errno;
+  }
+  if (image_nil == 0) {
+    if (err == 0) {
+      fprintf(dbgout, "Couldn't load lisp heap image from %s\n", path);
+    } else {
+      fprintf(dbgout, "Couldn't load lisp heap image from %s:\n%s\n", path, strerror(err));
+    }
+    exit(-1);
+  }
+  return image_nil;
+}
+
+int
+set_errno(int val)
+{
+  errno = val;
+  return -1;
+}
+
+/* A horrible hack to allow us to initialize a JVM instance from lisp.
+   On Darwin, creating a JVM instance clobbers the thread's existing
+   Mach exception infrastructure, so we save and restore it here.
+*/
+
+typedef int (*jvm_initfunc)(void*,void*,void*);
+
+int
+jvm_init(jvm_initfunc f,void*arg0,void*arg1,void*arg2)
+{
+  int result = -1;
+  TCR *tcr = get_tcr(1);
+#ifdef DARWIN
+  extern kern_return_t tcr_establish_lisp_exception_port(TCR *);
+#endif
+  
+  result = f(arg0,arg1,arg2);
+#ifdef DARWIN
+  tcr_establish_lisp_exception_port(tcr);
+#endif
+  return result;
+}
+  
+
+
+
+void *
+xFindSymbol(void* handle, char *name)
+{
+#if defined(LINUX) || defined(FREEBSD) || defined(SOLARIS)
+  return dlsym(handle, name);
+#endif
+#ifdef DARWIN
+#if 1
+  void *result;
+
+  if ((handle == NULL) || (handle == ((void *) -1))) {
+    handle = RTLD_DEFAULT;
+  }    
+  result = dlsym(handle, name);
+  if ((result == NULL) && (*name == '_')) {
+    result = dlsym(handle, name+1);
+  }
+  return result;
+#else
+  natural address = 0;
+
+  if ((handle == NULL) ||
+      (handle == (void *)-1) ||
+      (handle == (void *)-2)){
+    if (NSIsSymbolNameDefined(name)) { /* Keep dyld_lookup from crashing */
+      _dyld_lookup_and_bind(name, (void *) &address, (void*) NULL);
+    }
+    return (void *)address;
+  }
+  Bug(NULL, "How did this happen ?");
+#endif
+#endif
+#ifdef WINDOWS
+  extern void *windows_find_symbol(void *, char *);
+  return windows_find_symbol(handle, name);
+#endif
+}
+
+void *
+get_r_debug()
+{
+#if defined(LINUX) || defined(FREEBSD) || defined(SOLARIS)
+#if WORD_SIZE == 64
+  extern Elf64_Dyn _DYNAMIC[];
+  Elf64_Dyn *dp;
+#else
+  extern Elf32_Dyn _DYNAMIC[];
+  Elf32_Dyn *dp;
+#endif
+  int tag;
+
+  for (dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++) {
+    if (tag == DT_DEBUG) {
+      return (void *)(dp->d_un.d_ptr);
+    }
+  }
+#endif
+  return NULL;
+}
+
+
+#ifdef DARWIN
+void
+sample_paging_info(paging_info *stats)
+{
+  mach_msg_type_number_t count = TASK_EVENTS_INFO_COUNT;
+
+  task_info(mach_task_self(),
+            TASK_EVENTS_INFO,
+            (task_info_t)stats,
+            &count);
+}
+
+void
+report_paging_info_delta(FILE *out, paging_info *start, paging_info *stop)
+{
+  fprintf(out,";;; %d soft faults, %d faults, %d pageins\n\n",
+          stop->cow_faults-start->cow_faults,
+          stop->faults-start->faults,
+          stop->pageins-start->pageins);
+}
+
+#else
+#ifdef WINDOWS
+void
+sample_paging_info(paging_info *stats)
+{
+}
+
+void
+report_paging_info_delta(FILE *out, paging_info *start, paging_info *stop)
+{
+}
+#else
+void
+sample_paging_info(paging_info *stats)
+{
+  getrusage(RUSAGE_SELF, stats);
+}
+
+void
+report_paging_info_delta(FILE *out, paging_info *start, paging_info *stop)
+{
+  fprintf(out,";;; %ld soft faults, %ld faults, %ld pageins\n\n",
+          stop->ru_minflt-start->ru_minflt,
+          stop->ru_majflt-start->ru_majflt,
+          stop->ru_nswap-start->ru_nswap);
+}
+
+#endif
+#endif
+
+void
+allocate_static_conses(natural n)
+{
+  BytePtr old_low = static_cons_area->low,
+    new_low = old_low - (n<<dnode_shift);
+  cons *c;
+  natural i;
+  LispObj prev;
+
+  CommitMemory(new_low,old_low-new_low);
+
+  static_cons_area->low = new_low;
+  lower_heap_start(new_low, tenured_area);
+  /* what a mess this is ... */
+  if (active_dynamic_area->low == old_low) {
+    active_dynamic_area->low = new_low;
+  }
+  if (!active_dynamic_area->older) {
+    active_dynamic_area->markbits = tenured_area->refbits;
+  }
+  if (g1_area->low == old_low) {
+    g1_area->low = new_low;
+  }
+  if (g1_area->high == old_low) {
+    g1_area->high = new_low;
+  }
+  if (g2_area->low == old_low) {
+    g2_area->low = new_low;
+  }
+  if (g2_area->high == old_low) {
+    g2_area->high = new_low;
+  }
+  for (i=0, prev=lisp_global(STATIC_CONSES), c=(cons *)new_low;
+       i < n;
+       i++, c++) {
+    c->cdr = prev;
+    prev = ((LispObj)c)+fulltag_cons;
+  }
+  lisp_global(STATIC_CONSES)=prev;
+  lisp_global(FREE_STATIC_CONSES)+=(n<<fixnumshift);
+}
+void
+ensure_static_conses(ExceptionInformation *xp, TCR *tcr, natural nconses)
+{
+  area *a = active_dynamic_area;
+  natural nbytes = nconses>>dnode_shift, have;
+  BytePtr p = a->high-nbytes;
+
+  if (p < a->active) {
+    untenure_from_area(tenured_area);
+    gc_from_xp(xp, 0L);
+  }
+
+  have = unbox_fixnum(lisp_global(FREE_STATIC_CONSES));
+  if (have < nconses) {
+    if ((a->high-a->active)>nbytes) {
+      shrink_dynamic_area(nbytes);
+    }
+    allocate_static_conses(nconses);
+    tcr->bytes_allocated += nbytes;
+  }
+}
+      
Index: /branches/new-random/lisp-kernel/ppc-asmutils.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-asmutils.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-asmutils.s	(revision 13309)
@@ -0,0 +1,458 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL. */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence. */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+	
+
+	include(lisp.s)
+
+	_beginfile
+/*  Zero R4 cache lines, starting at address in R3.  Each line is assumed to be */
+/* R5 bytes wide. */
+_exportfn(C(zero_cache_lines))
+	__(cmpri(cr0,r4,0))
+	__(mtctr r4)
+	__(beqlr)
+1:
+	__(DCBZL(0,r3))
+	__(add r3,r3,r5)
+	__(bdnz 1b)
+	__(blr)
+_endfn
+
+/*  Flush R4 cache lines, starting at address in R3.  Each line is */
+/* assumed to be R5 bytes wide. */
+_exportfn(C(flush_cache_lines))
+	__(cmpri(cr0,r4,0))
+	__(mtctr r4)
+        __(mr r6,r3)
+	__(beqlr)
+1:
+	__(dcbst 0,r3)
+        __(add r3,r3,r5)
+        __(bdnz 1b)
+	__(sync)                /* wait until dcbst's get to memory */
+        __(mr r3,r6)
+        __(mtctr r4)
+2:      
+	__(icbi 0,r3)
+	__(add r3,r3,r5)
+	__(bdnz 2b)
+        __(sync)
+	__(isync)
+	__(blr)
+/* The strange reference to "exp" is supposed to force the kernel to */
+/* load libm, so lisp code can use it.   Under Darwin, the functionality */
+/* of libm is contained in libsystem, along with libc & everything else. */
+
+        __ifndef([DARWIN])
+        .data
+        __ifdef([PPC64])
+        .quad exp
+        __else
+        .long exp
+        __endif
+        .text        
+        __endif
+_endfn
+
+_exportfn(C(touch_page))
+        __(str(r3,0(r3)))
+        __(li r4,0)
+        __(str(r4,0(r3)))
+        __(li r3,1) /* can't assume that low 32 bits of r3 are non-zero */
+        .globl C(touch_page_end)
+C(touch_page_end):
+        __(blr)
+_endfn
+                                
+_exportfn(C(current_stack_pointer))
+	__(mr r3,sp)
+	__(blr)
+_endfn
+	
+_exportfn(C(count_leading_zeros))
+        __ifdef([PPC64])
+        __(cntlzd r3,r3)
+        __else
+	__(cntlzw r3,r3)
+        __endif
+	__(blr)
+_endfn
+
+_exportfn(C(noop))
+	__(blr)
+_endfn
+
+_exportfn(C(set_fpscr))
+	__(stru(sp,-32(sp)))
+	__(stw r3,12(sp))
+	__(lfd f0,8(sp))
+	__(mtfsf 0xff,f0)
+	__(la sp,32(sp))
+	__(blr)
+_endfn
+
+
+_exportfn(C(get_fpscr))
+	__(stru(sp,-32(sp)))
+        __(mffs f0)
+        __(stfd f0,8(sp))
+        __(lwz r3,12(sp))
+	__(la sp,32(sp))
+	__(blr)
+_endfn
+                
+
+/* The Linux kernel is constantly enabling and disabling the FPU and enabling */
+/* FPU exceptions.  We can't touch the FPU without turning off the FPSCR[FEX] */
+/* bit and we can't turn off the FPSCR[FEX] bit without touching the FPU. */
+/* Force a distinguished exception, and let the handler for that exception */
+/* zero the fpscr in its exception context. */
+
+_exportfn(C(zero_fpscr))
+	__(uuo_zero_fpscr())
+	__(blr)
+_endfn
+	
+	
+_exportfn(C(save_fp_context))
+	__(subi r4,r3,8)
+	__(stfdu f0,8(r4))
+	__(stfdu f1,8(r4))
+	__(stfdu f2,8(r4))
+	__(stfdu f3,8(r4))
+	__(stfdu f4,8(r4))
+	__(stfdu f5,8(r4))
+	__(stfdu f6,8(r4))
+	__(stfdu f7,8(r4))
+	__(stfdu f8,8(r4))
+	__(stfdu f9,8(r4))
+	__(stfdu f10,8(r4))
+	__(stfdu f11,8(r4))
+	__(stfdu f12,8(r4))
+	__(stfdu f13,8(r4))
+	__(stfdu f14,8(r4))
+	__(stfdu f15,8(r4))
+	__(stfdu f16,8(r4))
+	__(stfdu f17,8(r4))
+	__(stfdu f18,8(r4))
+	__(stfdu f19,8(r4))
+	__(stfdu f20,8(r4))
+	__(stfdu f21,8(r4))
+	__(stfdu f22,8(r4))
+	__(stfdu f23,8(r4))
+	__(stfdu f24,8(r4))
+	__(stfdu f25,8(r4))
+	__(stfdu f26,8(r4))
+	__(stfdu f27,8(r4))
+	__(stfdu f28,8(r4))
+	__(stfdu f29,8(r4))
+	__(stfdu f30,8(r4))
+	__(stfdu f31,8(r4))
+	__(mffs f0)
+	__(stfd f0,8(r4))
+	__(lfd f0,0(r3))
+	__(blr)
+_endfn
+
+_exportfn(C(restore_fp_context))
+	__(mr r4,r3)
+	__(lfdu f1,8(r4))
+	__(lfdu f2,8(r4))
+	__(lfdu f3,8(r4))
+	__(lfdu f4,8(r4))
+	__(lfdu f5,8(r4))
+	__(lfdu f6,8(r4))
+	__(lfdu f7,8(r4))
+	__(lfdu f8,8(r4))
+	__(lfdu f9,8(r4))
+	__(lfdu f10,8(r4))
+	__(lfdu f11,8(r4))
+	__(lfdu f12,8(r4))
+	__(lfdu f13,8(r4))
+	__(lfdu f14,8(r4))
+	__(lfdu f15,8(r4))
+	__(lfdu f16,8(r4))
+	__(lfdu f17,8(r4))
+	__(lfdu f18,8(r4))
+	__(lfdu f19,8(r4))
+	__(lfdu f20,8(r4))
+	__(lfdu f21,8(r4))
+	__(lfdu f22,8(r4))
+	__(lfdu f23,8(r4))
+	__(lfdu f24,8(r4))
+	__(lfdu f25,8(r4))
+	__(lfdu f26,8(r4))
+	__(lfdu f27,8(r4))
+	__(lfdu f28,8(r4))
+	__(lfdu f29,8(r4))
+	__(lfdu f30,8(r4))
+	__(lfdu f31,8(r4))
+	__(lfd f0,8(r4))
+	__(mtfsf 0xff,f0)
+	__(lfd f0,0(r3))
+	__(blr)
+_endfn
+
+
+
+/* Atomically store new value (r5) in *r3, if old value == expected. */
+/* Return actual old value. */
+
+_exportfn(C(store_conditional))
+        __(mr r6,r3)
+1:      __(lrarx(r3,0,r6))
+        __(cmpw r3,r4)
+        __(bne- 2f)
+        __(strcx(r5,0,r6))
+        __(bne- 1b)
+        __(isync)
+        __(blr)
+2:      __(li r0,RESERVATION_DISCHARGE)
+        __(strcx(r0,0,r0))
+        __(blr)
+_endfn
+
+/* Atomically store new_value(r4) in *r3 ;  return previous contents */
+/* of *r3. */
+
+_exportfn(C(atomic_swap))
+        __(sync)
+1:	__(lrarx(r5,0,r3))
+	__(strcx(r4,0,r3))
+	__(bne- 1b)
+	__(isync)
+	__(mr r3,r5)
+	__(blr)
+_endfn
+
+/* Logior the value in *r3 with the value in r4 (presumably a bitmask with exactly 1 */
+/* bit set.)  Return non-zero if any of the bits in that bitmask were already set. */
+        
+_exportfn(C(atomic_ior))
+        __(sync)
+1:	__(lrarx(r5,0,r3))
+        __(or r6,r4,r5)
+	__(strcx(r6,0,r3))
+	__(bne- 1b)
+	__(isync)
+	__(and r3,r4,r5)
+	__(blr)
+_endfn
+
+
+/* Logand the value in *r3 with the value in r4 (presumably a bitmask with exactly 1 */
+/* bit set.)  Return the value now in *r3 (for some value of "now" */
+
+_exportfn(C(atomic_and))
+        __(sync)
+1:	__(lrarx(r5,0,r3))
+        __(and r6,r4,r5)
+	__(strcx(r6,0,r3))
+	__(bne- 1b)
+	__(isync)
+	__(mr r3,r6)
+	__(blr)
+_endfn
+                
+	
+        __ifdef([DARWIN])
+_exportfn(C(enable_fp_exceptions))
+        __(.long 0)
+        __(blr)
+_endfn
+        
+_exportfn(C(disable_fp_exceptions))
+        __(.long 0)
+        __(blr)
+_endfn
+
+_exportfn(C(pseudo_sigreturn))
+	__(.long 0)
+	__(b C(pseudo_sigreturn))
+_endfn
+        __endif
+	
+/* Copy all 32 Altivec registers (+ VSCR & VRSAVE) to the buffer */
+/* in r3.  If the buffer's non-NULL, it's aligned and big enough, */
+/* and Altivec is present. */
+
+_exportfn(C(put_vector_registers))
+	__(cmpri(r3,0))
+	__(li r4,0)
+	__(beqlr)
+	__(stvx v0,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v1,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v2,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v3,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v4,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v5,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v6,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v7,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v8,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v9,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v10,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v11,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v12,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v13,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v14,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v15,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v16,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v17,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v18,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v19,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v20,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v21,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v22,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v23,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v24,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v25,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v26,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v27,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v28,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v29,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v30,r3,r4)
+	__(la r4,16(r4))
+	__(stvx v31,r3,r4)
+	__(la r4,16(r4))
+	__(mfvscr v0)
+	__(stvx v0,r3,r4)
+	__(mfspr r5,256)
+	__(stw r5,8(r4))
+	__(blr)
+_endfn
+
+_exportfn(C(get_vector_registers))
+	__(cmpri(r3,0))
+	__(li r4,32*16)
+	__(beqlr)
+	__(lvx v0,r3,r4)
+	__(mtvscr v0)
+	__(lwz r5,8(r4))
+	__(mtspr 256,r5)
+	__(la r4,-16(r4))
+	__(lvx v31,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v30,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v29,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v28,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v27,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v26,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v25,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v24,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v23,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v22,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v21,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v20,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v19,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v18,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v17,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v16,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v15,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v14,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v13,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v12,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v11,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v10,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v9,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v8,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v7,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v6,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v5,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v4,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v3,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v2,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v1,r3,r4)
+	__(la r4,-16(r4))
+	__(lvx v0,r3,r4)
+	__(blr)
+_endfn
+
+/* Some versions of Linux don't implement madvise().  That's */
+/* not catastrophic, but some versions of glibc will make a */
+/* big deal out of that at link time.  This is here to try */
+/* to fool those versions of glibc. */
+
+        __ifdef([LINUX])
+	.globl set_errno
+_exportfn(C(madvise))
+	__(li r0,205)	/* _NR_madvise; see /usr/include/asm/unistd.h */
+	__(sc)
+	__(bnslr)
+	__(b set_errno)
+_endfn
+        __endif
+
+	_endfile
Index: /branches/new-random/lisp-kernel/ppc-constants.h
===================================================================
--- /branches/new-random/lisp-kernel/ppc-constants.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-constants.h	(revision 13309)
@@ -0,0 +1,92 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __ppc_constants__
+#define __ppc_constants__ 1
+
+/*  Register usage: */
+#define rzero 0
+#define sp 1
+#define linux_sys_reg 2  /* volatile reg on Darwin ; thread ptr on Linux32, TOC on
+                                Linux64. */
+#define imm0 3
+#define imm1 4
+#define imm2 5
+#define imm3 6
+#define imm4 7
+#define imm5 8
+#define allocptr 9
+#define allocbase 10
+#define nargs 11
+#define tsp 12
+#define loc_pc 14		/*  code vector locative */
+#define vsp 15		
+#define fn 16
+#define temp3 17
+#define temp2 18
+#define temp1 19
+#define temp0 20	
+#define arg_x 21
+#define arg_y 22
+#define arg_z 23
+#define save7 24
+#define save6 25
+#define save5 26
+#define save4 27
+#define save3 28
+#define save2 29
+#define save1 30
+#define save0 31
+
+#define vfp save0	/*  frame pointer if needed (stack consing). */
+#define fname temp3
+#define nfn temp2
+#define next_method_context temp1
+#define closure_data temp0
+
+
+#define BA_MASK ((unsigned) ((-1<<26) | (1<<1)))
+#define BA_VAL  ((unsigned) ((18<<26) | (1<<1)))
+
+#define TCR_FLAG_BIT_FOREIGN fixnumshift
+#define TCR_FLAG_BIT_AWAITING_PRESET (fixnumshift+1)
+#define TCR_FLAG_BIT_ALT_SUSPEND (fixnumshift+2)
+#define TCR_FLAG_BIT_PROPAGATE_EXCEPTION (fixnumshift+3)
+#define TCR_FLAG_BIT_SUSPEND_ACK_PENDING (fixnumshift+4)
+#define TCR_FLAG_BIT_PENDING_EXCEPTION (fixnumshift+5)
+#define TCR_FLAG_BIT_FOREIGN_EXCEPTION (fixnumshift+6)
+#define TCR_FLAG_BIT_PENDING_SUSPEND (fixnumshift+7)
+
+#define TCR_STATE_FOREIGN (1)
+#define TCR_STATE_LISP    (0)
+#define TCR_STATE_EXCEPTION_WAIT (2)
+#define TCR_STATE_EXCEPTION_RETURN (4)
+
+#ifdef PPC64
+#include "ppc-constants64.h"
+#else
+#include "ppc-constants32.h"
+#endif
+
+#define dnode_size (node_size*2)
+#define dnode_shift (node_shift+1)
+
+#define INTERRUPT_LEVEL_BINDING_INDEX (1)
+
+#endif /* __ppc_constants__ */
+
+
Index: /branches/new-random/lisp-kernel/ppc-constants.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-constants.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-constants.s	(revision 13309)
@@ -0,0 +1,238 @@
+/* Copyright (C) 2004-2009 Clozure Associates */
+/* This file is part of Clozure CL. */
+ 
+/* Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/* License , known as the LLGPL and distributed with Clozure CL as the */
+/* file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/* which is distributed with Clozure CL as the file "LGPL".  Where these */
+/* conflict, the preamble takes precedence. */
+ 
+/* Clozure CL is referenced in the preamble as the "LIBRARY." */
+ 
+/* The LLGPL is also available online at */
+/* http://opensource.franz.com/preamble.html */
+
+
+/* Register usage: */
+
+
+define([rzero],[r0])	
+define([sp],[r1])
+
+define([imm0],[r3])
+define([imm1],[r4])
+define([imm2],[r5])
+define([imm3],[r6])
+define([imm4],[r7])
+define([imm5],[r8])
+define([allocptr],[r9])
+define([allocbase],[r10])
+define([nargs],[r11])
+define([tsp],[r12])      /* temp-consing stack. */
+
+define([loc_pc],[r14]) 	 /* code vector locative */
+define([vsp],[r15])
+define([fn],[r16])
+define([temp3],[r17])
+define([temp2],[r18])
+define([temp1],[r19])
+define([temp0],[r20])
+define([arg_x],[r21])
+define([arg_y],[r22])
+define([arg_z],[r23])
+define([save7],[r24])
+define([save6],[r25])
+define([save5],[r26])
+define([save4],[r27])
+define([save3],[r28])
+define([save2],[r29])
+define([save1],[r30])
+define([save0],[r31])
+
+define([fname],[temp3])
+define([nfn],[temp2])
+define([next_method_context],[temp1])
+define([first_nvr],[save7])
+define([second_nvr],[save6])        
+define([third_nvr],[save5])
+define([fourth_nvr],[save4])        
+define([fifth_nvr],[save3])
+define([sixth_nvr],[save2])        
+define([seventh_nvr],[save1])
+define([eighth_nvr],[save0])        
+define([nargregs],[3])
+	
+r0 = 0
+r1 = 1
+r2 = 2
+r3 = 3
+r4 = 4
+r5 = 5
+r6 = 6
+r7 = 7
+r8 = 8
+r9 = 9
+r10 = 10
+r11 = 11
+r12 = 12
+r13 = 13
+r14 = 14
+r15 = 15
+r16 = 16
+r17 = 17
+r18 = 18
+r19 = 19
+r20 = 20
+r21 = 21
+r22 = 22
+r23 = 23
+r24 = 24
+r25 = 25
+r26 = 26
+r27 = 27
+r28 = 28
+r29 = 29
+r30 = 30
+r31 = 31
+
+/* Lisp code keeps 0.0 in fp_zero */
+define([fp_zero],[f31])   /* a non-volatile reg as far as FFI is concerned. */
+define([fp_s32conv],[f30])   /* for s32->fp conversion */
+	
+/* registers, as used in destrucuring-bind/macro-bind */
+
+define([whole_reg],[temp1])
+define([arg_reg],[temp3])
+define([keyvect_reg],[temp2])
+define([mask_req_start],[24])
+define([mask_req_width],[8])
+define([mask_opt_start],[16])
+define([mask_opt_width],[8])
+define([mask_key_start],[8])
+define([mask_key_width],[8])
+define([mask_initopt],[7])
+define([mask_keyp],[6]) /*  note that keyp can be true even when 0 keys. */
+define([mask_aok],[5])
+define([mask_restp],[4])
+
+ifdef([DARWIN],[
+	define([STACK_ALIGN],16)
+	define([STACK_ALIGN_MASK],15)
+],[
+	define([STACK_ALIGN],8)
+	define([STACK_ALIGN_MASK],7)
+])
+
+/* Indices in %builtin-functions% */
+_builtin_plus = 0	/* +-2 */
+_builtin_minus = 1	/* --2 */
+_builtin_times = 2	/* *-2 */
+_builtin_div = 3	/* /-2 */
+_builtin_eq = 4		/* =-2 */
+_builtin_ne = 5		/* /-2 */
+_builtin_gt = 6		/* >-2 */
+_builtin_ge = 7		/* >=-2 */
+_builtin_lt = 8		/* <-2 */
+_builtin_le = 9		/* <=-2 */
+_builtin_eql = 10	/* eql */
+_builtin_length = 11	/* length */
+_builtin_seqtype = 12	/* sequence-type */
+_builtin_assq = 13	/* assq */
+_builtin_memq = 14	/* memq */
+_builtin_logbitp = 15	/* logbitp */
+_builtin_logior = 16	/* logior-2 */
+_builtin_logand = 17	/* logand-2 */
+_builtin_ash = 18	/* ash */
+_builtin_negate = 19	/* %negate */
+_builtin_logxor = 20	/* logxor-2 */
+_builtin_aref1 = 21	/* %aref1 */
+_builtin_aset1 = 22	/* %aset1 */
+
+	/* FPSCR status bits */
+fpscr_FX = 0
+fpscr_FEX = 1
+fpscr_VX = 2
+fpscr_OX = 3
+fpscr_UX = 4
+fpscr_ZX = 5
+fpscr_XX = 6
+	/* FPSCR control bits */
+fpscr_VE = 24
+fpscr_OE = 25
+fpscr_UE = 26
+fpscr_ZE = 27
+fpscr_XE = 28
+	
+
+/* This should be (a) an (UNSIGNED-BYTE 16) and (b) one less than */
+/* TSTACK_SOFTPROT (defined in "area.h") */
+		
+tstack_alloc_limit = 0xffff
+        
+define([TCR_STATE_FOREIGN],1)
+define([TCR_STATE_LISP],0)
+define([TCR_STATE_EXCEPTION_WAIT],2)
+define([TCR_STATE_EXCEPTION_RETURN],4)
+
+        
+
+        	
+ifdef([PPC64],[
+        include(ppc-constants64.s)
+],[
+        include(ppc-constants32.s)
+])
+
+num_lisp_globals = 48		 /* MUST UPDATE THIS !!! */
+	
+	_struct(lisp_globals,lisp_globals_limit-(num_lisp_globals*node_size))
+	 _node(initial_tcr)	        /* initial thread tcr */
+	 _node(image_name)	        /* --image-name argument */
+	 _node(BADfpscr_save_high)      /* high word of FP reg used to save FPSCR */
+	 _node(unwind_resume)           /* _Unwind_Resume */
+	 _node(batch_flag)	        /* -b */
+	 _node(host_platform)	        /* for runtime platform-specific stuff */
+	 _node(argv)			/* address of argv[0] */
+	 _node(ref_base)		        /* start of oldest pointer-bearing area */
+	 _node(tenured_area) 		/* the tenured_area */
+	 _node(oldest_ephemeral) 	/* dword address of oldest ephemeral object or 0 */
+	 _node(lisp_exit_hook)		/* install foreign exception_handling */
+	 _node(lisp_return_hook)	/* install lisp exception_handling */
+	 _node(double_float_one) 	/* high half of 1.0d0 */
+	 _node(short_float_zero) 	/* low half of 1.0d0 */
+	 _node(objc2_end_catch)         /* objc_end_catch() */
+	 _node(metering_info) 		/* address of lisp_metering global */
+	 _node(in_gc) 			/* non-zero when GC active */
+	 _node(lexpr_return1v) 		/* simpler when &lexpr called for single value. */
+	 _node(lexpr_return) 		/* magic &lexpr return code. */
+	 _node(all_areas) 		/* doubly-linked list of all memory areas */
+	 _node(kernel_path) 		/* real executable name */
+	 _node(objc2_begin_catch) 	/* objc_begin_catch */
+	 _node(stack_size) 		/* from command-line */
+	 _node(statically_linked)	/* non-zero if -static */
+	 _node(heap_end)                /* end of lisp heap */
+	 _node(heap_start)              /* start of lisp heap */
+	 _node(gcable_pointers)         /* linked-list of weak macptrs. */
+	 _node(gc_num)                  /* fixnum: GC call count. */
+	 _node(fwdnum)                  /* fixnum: GC "forwarder" call count. */
+	 _node(altivec_present)         /* non-zero when AltiVec available */
+	 _node(oldspace_dnode_count) 	/* dynamic dnodes older than g0 start */
+	 _node(refbits) 		/* EGC refbits */
+	 _node(gc_inhibit_count)
+	 _node(intflag) 		/* sigint pending */
+	 _node(BAD_block_tag_counter) 	/* counter for (immediate) block tag */
+	 _node(deleted_static_pairs) 		
+	 _node(exception_lock)
+	 _node(area_lock)
+	 _node(tcr_key) 		/* tsd key for per-thread tcr */
+	 _node(ret1val_addr) 		/* address of "dynamic" subprims magic values return addr */
+	 _node(subprims_base) 		/* address of dynamic subprims jump table */
+	 _node(saveR13)			/* probably don]t really need this */
+	 _node(saveTOC)                 /* where the 68K emulator stores the  emulated regs */
+	 _node(objc_2_personality)      /* exception "personality routine" address for ObjC 2.0 */ 
+	 _node(kernel_imports) 		/* some things we need imported for us */
+	 _node(interrupt_signal)	/* signal used by PROCESS-INTERRUPT */
+	 _node(tcr_count) 		/* tcr_id for next tcr */
+	 _node(get_tcr) 		/* address of get_tcr() */
+	_ends
+	
Index: /branches/new-random/lisp-kernel/ppc-constants32.h
===================================================================
--- /branches/new-random/lisp-kernel/ppc-constants32.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-constants32.h	(revision 13309)
@@ -0,0 +1,475 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __constants32__
+#define __constants32__ 1
+
+#define rcontext 13
+
+#define nbits_in_word 32
+#define log2_nbits_in_word 5
+#define nbits_in_byte 8
+#define ntagbits 3	/* But only 2 are significant to lisp */
+#define nlisptagbits 2
+#define nfixnumtagbits 2
+#define num_subtag_bits 8
+#define fixnumshift 2
+#define fixnum_shift 2
+#define fulltagmask 7
+#define tagmask	 3
+#define fixnummask 3
+#define subtagmask ((1<<num_subtag_bits)-1)
+#define ncharcodebits 24        /* Only the low 8 are used currently */
+#define charcode_shift (nbits_in_word-ncharcodebits)
+#define node_size 4
+#define node_shift 2
+
+/*  Tags. */
+/*  There are two-bit tags and three-bit tags. */
+/*  A FULLTAG is the value of the low three bits of a tagged object. */
+/*  A TAG is the value of the low two bits of a tagged object. */
+/*  A TYPECODE is either a TAG or the value of a "tag-misc" object's header-byte. */
+
+/*  There are 4 primary TAG values.  Any object which lisp can "see" can be classified  */
+/*  by its TAG.  (Some headers have FULLTAGS that are congruent modulo 4 with the */
+/*  TAGS of other objects, but lisp can't "see" headers.) */
+
+
+#define tag_fixnum 0	/*  All fixnums, whether odd or even */
+#define tag_list 1	/*  Conses and NIL */
+#define tag_misc 2	/*  Heap-consed objects other than lists: vectors, symbols, functions, floats ... */
+#define tag_imm	 3	/*  Immediate-objects: characters, UNBOUND, other markers. */
+
+/*  And there are 8 FULLTAG values.  Note that NIL has its own FULLTAG (congruent mod 4 to tag-list), */
+/*  that FULLTAG-MISC is > 4 (so that code-vector entry-points can be branched to, since the low */
+/*  two bits of the PC are ignored) and that both FULLTAG-MISC and FULLTAG-IMM have header fulltags */
+/*  that share the same TAG. */
+/*  Things that walk memory (and the stack) have to be careful to look at the FULLTAG of each */
+/*  object that they see. */
+
+#define fulltag_even_fixnum 0	/*  I suppose EVENP/ODDP might care; nothing else does. */
+#define fulltag_cons	 1	/*  a real (non_null) cons.  Shares TAG with fulltag_nil. */
+#define fulltag_nodeheader 2	/*  Header of heap_allocated object that contains lisp_object pointers */
+#define fulltag_imm	 3	/*  a "real" immediate object.  Shares TAG with fulltag_immheader. */
+#define fulltag_odd_fixnum 4	/*   */
+#define fulltag_nil	 5	/*  NIL and nothing but.  (Note that there's still a hidden NILSYM.) */
+#define fulltag_misc	 6	/*  Pointer "real" tag_misc object.  Shares TAG with fulltag_nodeheader. */
+#define fulltag_immheader 7	/*  Header of heap-allocated object that contains unboxed data. */
+
+
+
+/*  Order of CAR and CDR doesn't seem to matter much - there aren't */
+/*  too many tricks to be played with predecrement/preincrement addressing. */
+/*  Keep them in the confusing MCL 3.0 order, to avoid confusion. */
+
+typedef struct cons {
+  LispObj cdr;
+  LispObj car;
+} cons;
+
+
+#define misc_header_offset -fulltag_misc
+#define misc_subtag_offset misc_header_offset+3		/*  low byte of header */
+#define misc_data_offset misc_header_offset+4		/*  first word of data */
+#define misc_dfloat_offset misc_header_offset+8		/*  double-floats are doubleword-aligned */
+
+#define max_64_bit_constant_index ((0x7fff + misc_dfloat_offset)>>3)
+#define max_32_bit_constant_index ((0x7fff + misc_data_offset)>>2)
+#define max_16_bit_constant_index ((0x7fff + misc_data_offset)>>1)
+#define max_8_bit_constant_index (0x7fff + misc_data_offset)
+#define max_1_bit_constant_index ((0x7fff + misc_data_offset)<<5)
+
+/*  T is almost adjacent to NIL: since NIL is a misaligned CONS, it spans */
+/*  two doublewords.  The arithmetic difference between T and NIL is */
+/*  such that the least-significant bit and exactly one other bit is */
+/*  set in the result. */
+
+#define t_offset (8+(8-fulltag_nil)+fulltag_misc)
+#define t_value (lisp_nil+t_offset)
+
+/*  The order in which various header values are defined is significant in several ways: */
+/*  1) Numeric subtags precede non-numeric ones; there are further orderings among numeric subtags. */
+/*  2) All subtags which denote CL arrays are preceded by those that don't, */
+/*     with a further ordering which requires that (< header-arrayH header-vectorH ,@all-other-CL-vector-types) */
+/*  3) The element-size of ivectors is determined by the ordering of ivector subtags. */
+/*  4) All subtags are >= fulltag-immheader . */
+
+#define SUBTAG(tag,subtag) ((tag) | ((subtag) << ntagbits))
+#define IMM_SUBTAG(subtag) SUBTAG(fulltag_immheader,(subtag))
+#define NODE_SUBTAG(subtag) SUBTAG(fulltag_nodeheader,(subtag))
+
+	
+/* Numeric subtags. */
+
+#define subtag_bignum IMM_SUBTAG(0)
+#define min_numeric_subtag subtag_bignum
+
+#define subtag_ratio NODE_SUBTAG(1)
+#define max_rational_subtag subtag_ratio
+
+#define subtag_single_float IMM_SUBTAG(1)
+#define subtag_double_float IMM_SUBTAG(2)
+#define min_float_subtag subtag_single_float
+#define max_float_subtag subtag_double_float
+#define max_real_subtag subtag_double_float
+
+#define subtag_complex NODE_SUBTAG(3)
+#define max_numeric_subtag subtag_complex
+
+
+/*  CL array types.  There are more immediate types than node types; all CL array subtags must be > than */
+/*  all non-CL-array subtags.  So we start by defining the immediate subtags in decreasing order, starting */
+/*  with that subtag whose element size isn't an integral number of bits and ending with those whose */
+/*  element size - like all non-CL-array fulltag-immheader types - is 32 bits. */
+
+#define subtag_bit_vector IMM_SUBTAG(31)
+#define subtag_double_float_vector IMM_SUBTAG(30)
+#define subtag_s16_vector IMM_SUBTAG(29)
+#define subtag_u16_vector IMM_SUBTAG(28)
+#define min_16_bit_ivector_subtag subtag_u16_vector
+#define max_16_bit_ivector_subtag subtag_s16_vector
+
+#define subtag_s8_vector IMM_SUBTAG(26)
+#define subtag_u8_vector IMM_SUBTAG(25)
+#define min_8_bit_ivector_subtag subtag_u8_vector
+#define max_8_bit_ivector_subtag IMM_SUBTAG(27)
+
+#define subtag_simple_base_string IMM_SUBTAG(24)
+#define subtag_fixnum_vector IMM_SUBTAG(23)
+#define subtag_s32_vector IMM_SUBTAG(22)
+#define subtag_u32_vector IMM_SUBTAG(21)
+#define subtag_single_float_vector IMM_SUBTAG(20)
+#define max_32_bit_ivector_subtag IMM_SUBTAG(24)
+#define min_cl_ivector_subtag subtag_single_float_vector
+
+
+#define subtag_vectorH NODE_SUBTAG(20)
+#define subtag_arrayH NODE_SUBTAG(19)
+#define subtag_simple_vector NODE_SUBTAG(21)	/*  Only one such subtag) */
+#define min_vector_subtag subtag_vectorH
+#define min_array_subtag subtag_arrayH
+
+/*  So, we get the remaining subtags (n: (n > max-numeric-subtag) & (n < min-array-subtag)) */
+/*  for various immediate/node object types. */
+
+#define subtag_macptr IMM_SUBTAG(3)
+#define min_non_numeric_imm_subtag subtag_macptr
+
+#define subtag_dead_macptr IMM_SUBTAG(4)
+#define subtag_code_vector IMM_SUBTAG(5)
+#define subtag_creole IMM_SUBTAG(6)
+
+#define max_non_array_imm_subtag ((19<<ntagbits)|fulltag_immheader)
+
+#define subtag_catch_frame NODE_SUBTAG(4)
+#define subtag_function NODE_SUBTAG(5)
+#define subtag_basic_stream NODE_SUBTAG(6)
+#define subtag_symbol NODE_SUBTAG(7)
+#define subtag_lock NODE_SUBTAG(8)
+#define subtag_hash_vector NODE_SUBTAG(9)
+#define subtag_pool NODE_SUBTAG(10)
+#define subtag_weak NODE_SUBTAG(11)
+#define subtag_package NODE_SUBTAG(12)
+#define subtag_slot_vector NODE_SUBTAG(13)
+#define subtag_instance NODE_SUBTAG(14)
+#define subtag_struct NODE_SUBTAG(15)
+#define subtag_istruct NODE_SUBTAG(16)
+#define max_non_array_node_subtag ((19<<ntagbits)|fulltag_immheader)
+	
+/*  The objects themselves look something like this: */
+
+typedef struct lispsymbol {
+  LispObj header;
+  LispObj pname;
+  LispObj vcell;
+  LispObj fcell;
+  LispObj package_predicate;
+  LispObj flags;
+  LispObj plist;
+  LispObj binding_index;
+} lispsymbol;
+
+typedef struct ratio {
+  LispObj header;
+  LispObj numer;
+  LispObj denom;
+} ratio;
+
+typedef struct double_float {
+  LispObj header;
+  LispObj pad;
+  LispObj value_high;
+  LispObj value_low;
+} double_float;
+
+typedef struct single_float {
+  LispObj header;
+  LispObj value;
+} single_float;
+
+typedef struct macptr {
+  LispObj header;
+  LispObj address;
+  LispObj class;
+  LispObj type;
+} macptr;
+
+typedef struct xmacptr {
+  LispObj header;
+  LispObj address;
+  LispObj class;
+  LispObj type;
+  LispObj flags;
+  LispObj link;
+} xmacptr;
+  
+
+typedef struct eabi_c_frame {
+  struct eabi_c_frame *backlink;
+  unsigned savelr;
+  unsigned params[8];
+} eabi_c_frame;
+
+/* PowerOpen ABI C frame */
+
+typedef struct c_frame {
+  struct c_frame *backlink;
+  unsigned crsave;
+  unsigned savelr;
+  unsigned unused[2];
+  unsigned savetoc;		/* Used with CFM */
+  unsigned params[8];		/* Space for callee to save r3-r10 */
+} c_frame;
+
+typedef struct lisp_frame {
+  struct lisp_frame *backlink;
+  LispObj savefn;
+  LispObj savelr;
+  LispObj savevsp;
+} lisp_frame;
+
+typedef struct special_binding {
+  struct special_binding *link;
+  struct lispsymbol *sym;
+  LispObj value;
+} special_binding;
+
+/* The GC (at least) needs to know what a
+   package looks like, so that it can do GCTWA. */
+typedef struct package {
+  LispObj header;
+  LispObj itab;			/* itab and etab look like (vector (fixnum . fixnum) */
+  LispObj etab;
+  LispObj used;
+  LispObj used_by;
+  LispObj names;
+  LispObj shadowed;
+} package;
+
+/*
+  The GC also needs to know what a catch_frame looks like.
+*/
+
+typedef struct catch_frame {
+  LispObj header;
+  LispObj catch_tag;
+  LispObj link;
+  LispObj mvflag;
+  LispObj csp;
+  LispObj db_link;
+  LispObj regs[8];
+  LispObj xframe;
+  LispObj tsp_segment;
+} catch_frame;
+
+#define catch_frame_element_count ((sizeof(catch_frame)/sizeof(LispObj))-1)
+#define catch_frame_header make_header(subtag_catch_frame,catch_frame_element_count)
+
+#define unbound SUBTAG(fulltag_imm, 6)
+#define undefined unbound
+#define unbound_marker unbound
+#define subtag_character SUBTAG(fulltag_imm, 9)
+#define slot_unbound SUBTAG(fulltag_imm, 10)
+#define slot_unbound_marker slot_unbound
+#define no_thread_local_binding_marker SUBTAG(fulltag_imm,30)
+
+/* 
+  All exception frames in a thread are linked together 
+  */
+typedef struct xframe_list {
+  ExceptionInformation *curr;
+  struct xframe_list *prev;
+} xframe_list;
+
+#define fixnum_bitmask(n)  (1<<((n)+fixnumshift))
+
+/* 
+  The GC (at least) needs to know about hash-table-vectors and their flag bits.
+*/
+
+typedef struct hash_table_vector_header {
+  LispObj header;
+  LispObj link;                 /* If weak */
+  LispObj flags;                /* a fixnum; see below */
+  LispObj gc_count;             /* gc-count kernel global */
+  LispObj free_alist;           /* preallocated conses for finalization_alist */
+  LispObj finalization_alist;   /* key/value alist for finalization */
+  LispObj weak_deletions_count; /* incremented when GC deletes weak pair */
+  LispObj hash;                 /* backpointer to hash-table */
+  LispObj deleted_count;        /* number of deleted entries [not maintained if lock-free] */
+  LispObj count;                /* number of valid entries [not maintained if lock-free] */
+  LispObj cache_idx;            /* index of last cached pair */
+  LispObj cache_key;            /* value of last cached key */
+  LispObj cache_value;          /* last cached value */
+  LispObj size;                 /* number of entries in table */
+  LispObj size_reciprocal;      /* shifted reciprocal of size */
+} hash_table_vector_header;
+
+/*
+  Bits (masks)  in hash_table_vector.flags:
+*/
+
+/* GC should track keys when addresses change */ 
+#define nhash_track_keys_mask fixnum_bitmask(28) 
+
+/* GC should set when nhash_track_keys_bit & addresses change */
+#define nhash_key_moved_mask  fixnum_bitmask(27) 
+
+/* weak on key or value (need new "weak both" encoding.) */
+#define nhash_weak_mask       fixnum_bitmask(12)
+
+/* weak on value */
+#define nhash_weak_value_mask fixnum_bitmask(11)
+
+/* finalizable */
+#define nhash_finalizable_mask fixnum_bitmask(10)
+
+/* keys frozen, i.e. don't clobber keys, only values */
+#define nhash_keys_frozen_mask fixnum_bitmask(9)
+
+/* Lfun bits */
+
+#define lfbits_nonnullenv_mask fixnum_bitmask(0)
+#define lfbits_keys_mask fixnum_bitmask(1)
+#define lfbits_restv_mask fixnum_bitmask(7)
+#define lfbits_optinit_mask fixnum_bitmask(14)
+#define lfbits_rest_mask fixnum_bitmask(15)
+#define lfbits_aok_mask fixnum_bitmask(16)
+#define lfbits_lap_mask fixnum_bitmask(23)
+#define lfbits_trampoline_mask fixnum_bitmask(24)
+#define lfbits_evaluated_mask fixnum_bitmask(25)
+#define lfbits_cm_mask fixnum_bitmask(26)         /* combined_method */
+#define lfbits_nextmeth_mask fixnum_bitmask(26)   /* or call_next_method with method_mask */
+#define lfbits_gfn_mask fixnum_bitmask(27)        /* generic_function */
+#define lfbits_nextmeth_with_args_mask fixnum_bitmask(27)   /* or call_next_method_with_args with method_mask */
+#define lfbits_method_mask fixnum_bitmask(28)     /* method function */
+/* PPC only but want it defined for xcompile */
+#define lfbits_noname_mask fixnum_bitmask(29)
+
+
+/* Creole */
+
+#define doh_quantum 400
+#define doh_block_slots ((doh_quantum >> 2) - 3)
+
+typedef struct doh_block {
+  struct doh_block *link;
+  unsigned size;
+  unsigned free;
+  LispObj data[doh_block_slots];
+} doh_block, *doh_block_ptr;
+
+
+#define population_weak_list (0<<fixnum_shift)
+#define population_weak_alist (1<<fixnum_shift)
+#define population_termination_bit (16+fixnum_shift)
+#define population_type_mask ((1<<population_termination_bit)-1)
+
+#define gc_retain_pages_bit fixnum_bitmask(0)
+#define gc_integrity_check_bit fixnum_bitmask(2)
+#define egc_verbose_bit fixnum_bitmask(3)
+#define gc_verbose_bit fixnum_bitmask(4)
+#define gc_allow_stack_overflows_bit fixnum_bitmask(5)
+#define gc_postgc_pending fixnum_bitmask(26)
+
+#include "lisp-errors.h"
+
+
+
+
+#define nil_value (0x00003015+(LOWMEM_BIAS))
+
+#define TCR_BIAS (0)
+
+typedef struct tcr {
+  struct tcr *next;
+  struct tcr *prev;
+  union {
+    double d;
+    struct {unsigned h, l;} words;
+  } lisp_fpscr;			/* lisp thread's fpscr (in low word) */
+  special_binding *db_link;	/* special binding chain head */
+  LispObj catch_top;		/* top catch frame */
+  LispObj *save_vsp;		/* VSP when in foreign code */
+  LispObj *save_tsp;		/* TSP when in foreign code */
+  struct area *cs_area;		/* cstack area pointer */
+  struct area *vs_area;		/* vstack area pointer */
+  struct area *ts_area;		/* tstack area pointer */
+  LispObj cs_limit;		/* stack overflow limit */
+  unsigned long long bytes_allocated;
+  natural log2_allocation_quantum;  /* for per-thread consing */
+  int interrupt_pending;	/* deferred-interrupt pending */
+  xframe_list *xframe;		/* exception-frame linked list */
+  int *errno_loc;		/* per-thread (?) errno location */
+  LispObj ffi_exception;	/* fpscr bits from ff-call */
+  LispObj osid;			/* OS thread id */
+  int valence;			/* odd when in foreign code */
+  int foreign_exception_status;	/* non-zero -> call lisp_exit_hook */
+  void *native_thread_info;	/* platform-dependent */
+  void *native_thread_id;	/* mach_thread_t, pid_t, etc. */
+  void *last_allocptr;
+  void *save_allocptr;
+  void *save_allocbase;
+  void *reset_completion;
+  void *activate;
+  int suspend_count;
+  ExceptionInformation *suspend_context;
+  ExceptionInformation *pending_exception_context;
+  void *suspend;		/* suspension semaphore */
+  void *resume;			/* resumption semaphore */
+  natural flags;
+  ExceptionInformation *gc_context;
+  void *termination_semaphore;
+  int unwinding;
+  unsigned tlb_limit;
+  LispObj *tlb_pointer;
+  unsigned shutdown_count;
+  void *safe_ref_address;
+} TCR;
+
+/* 
+  These were previously global variables.  There are lots of implicit
+  assumptions about the size of a heap segment, so they might as well
+  be constants.
+*/
+
+#define heap_segment_size 0x00010000
+#define log2_heap_segment_size 16
+
+
+#endif
+
Index: /branches/new-random/lisp-kernel/ppc-constants32.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-constants32.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-constants32.s	(revision 13309)
@@ -0,0 +1,687 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL. */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence. */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+define([rcontext],[r13])
+        
+nbits_in_word = 32
+nbits_in_byte = 8
+ntagbits = 3	/* But only 2 are significant to lisp */
+nlisptagbits = 2
+nfixnumtagbits = 2
+num_subtag_bits = 8
+fixnumshift = 2
+fixnum_shift = 2
+fulltagmask = 7
+tagmask = 3
+fixnummask = 3
+ncharcodebits = 24              /* arguably, we're only using the low 8 */
+charcode_shift = nbits_in_word-ncharcodebits
+word_shift = 2
+node_size = 4
+dnode_size = 8
+dnode_align_bits = 3
+dnode_shift = dnode_align_bits
+bitmap_shift = 5
+
+
+fixnumone = (1<<fixnumshift)
+fixnum_one = fixnumone
+fixnum1 = fixnumone
+
+
+/* Tags. */
+/* There are two-bit tags and three-bit tags. */
+/* A FULLTAG is the value of the low three bits of a tagged object. */
+/* A TAG is the value of the low two bits of a tagged object. */
+/* A TYPECODE is either a TAG or the value of a "tag-misc" objects header-byte. */
+
+/* There are 4 primary TAG values.  Any object which lisp can "see" can be classified */
+/* by its TAG.  (Some headers have FULLTAGS that are congruent modulo 4 with the */
+/* TAGS of other objects, but lisp can't "see" headers.) */
+
+
+tag_fixnum = 0	/* All fixnums, whether odd or even */
+tag_list = 1	/* Conses and NIL */
+tag_misc = 2	/* Heap-consed objects other than lists: vectors, symbols, functions, floats ... */
+tag_imm = 3	/* Immediate-objects: characters, UNBOUND, other markers. */
+
+
+/*  And there are 8 FULLTAG values.  Note that NIL has its own FULLTAG (congruent mod 4 to tag-list), */
+/*  that FULLTAG-MISC is > 4 (so that code-vector entry-points can be branched to, since the low */
+/*  two bits of the PC are ignored) and that both FULLTAG-MISC and FULLTAG-IMM have header fulltags */
+/*  that share the same TAG. */
+/*  Things that walk memory (and the stack) have to be careful to look at the FULLTAG of each */
+/*  object that they see. */
+
+
+fulltag_even_fixnum = 0	/* I suppose EVENP/ODDP might care; nothing else does. */
+fulltag_cons = 1	/* a real (non_null) cons.  Shares TAG with fulltag_nil. */
+fulltag_nodeheader = 2	/* Header of heap_allocated object that contains lisp_object pointers */
+fulltag_imm = 3	/* a "real" immediate object.  Shares TAG with fulltag_immheader. */
+fulltag_odd_fixnum = 4	/* */
+fulltag_nil = 5	/* NIL and nothing but.  (Note that there]s still a hidden NILSYM.) */
+fulltag_misc = 6	/* Pointer "real" tag_misc object.  Shares TAG with fulltag_nodeheader. */
+fulltag_immheader = 7	/* Header of heap-allocated object that contains unboxed data. */
+
+nil_value = 0x00003015+LOWMEM_BIAS
+misc_bias = fulltag_misc
+cons_bias = tag_list        
+
+/* Functions are of (conceptually) unlimited size. */
+	_struct(_function,-misc_bias)
+	 _node(header)
+	 _node(codevector)
+	_ends
+
+	_struct(tsp_frame,0)
+	 _node(backlink)
+	 _node(type)
+	 _struct_label(fixed_overhead)
+	 _struct_label(data_offset)
+	_ends
+
+/* Order of CAR and CDR doesn]t seem to matter much - there aren]t */
+/* too many tricks to be played with predecrement/preincrement addressing. */
+/* Keep them in the confusing MCL 3.0 order, to avoid confusion. */
+	_struct(cons,-cons_bias)
+	 _node(cdr)
+	 _node(car)
+	_ends
+	
+misc_header_offset = -fulltag_misc
+misc_subtag_offset = misc_header_offset+3		/* low byte of header */
+misc_data_offset = misc_header_offset+4		/* first word of data */
+misc_dfloat_offset = misc_header_offset+8		/* double-floats are doubleword-aligned */
+
+max_64_bit_constant_index = ((0x7fff + misc_dfloat_offset)>>3)
+max_32_bit_constant_index = ((0x7fff + misc_data_offset)>>2)
+max_16_bit_constant_index = ((0x7fff + misc_data_offset)>>1)
+max_8_bit_constant_index = (0x7fff + misc_data_offset)
+max_1_bit_constant_index = ((0x7fff + misc_data_offset)<<5)
+
+/* T is almost adjacent to NIL: since NIL is a misaligned CONS, it spans */
+/* two doublewords.  The arithmetic difference between T and NIL is */
+/* such that the least-significant bit and exactly one other bit is */
+/* set in the result. */
+
+t_offset = (8+(8-fulltag_nil)+fulltag_misc)
+t_value = nil_value+t_offset
+
+/* The order in which various header values are defined is significant in several ways: */
+/* 1) Numeric subtags precede non-numeric ones; there are further orderings among numeric subtags. */
+/* 2) All subtags which denote CL arrays are preceded by those that don]t, */
+/*    with a further ordering which requires that (< header-arrayH header-vectorH ,@all-other-CL-vector-types) */
+/* 3) The element-size of ivectors is determined by the ordering of ivector subtags. */
+/* 4) All subtags are >= fulltag-immheader . */
+
+define([define_subtag],[
+subtag_$1 = $2|($3<<ntagbits)])
+	
+define([define_imm_subtag],[
+	define_subtag($1,fulltag_immheader,$2)])
+
+	
+define([define_node_subtag],[
+	define_subtag($1,fulltag_nodeheader,$2)])
+
+		
+/*Immediate subtags. */
+	define_subtag(character,fulltag_imm,9)
+	define_subtag(unbound,fulltag_imm,6)
+        define_subtag(illegal,fulltag_imm,10)
+	define_subtag(go_tag,fulltag_imm,12)
+	define_subtag(block_tag,fulltag_imm,24)
+	define_subtag(vsp_protect,fulltag_imm,7)
+        define_subtag(no_thread_local_binding,fulltag_imm,30)
+unbound_marker = subtag_unbound
+undefined = unbound_marker
+illegal_marker = subtag_illegal
+no_thread_local_binding_marker = subtag_no_thread_local_binding
+/*Numeric subtags. */
+
+	define_imm_subtag(bignum,0)
+min_numeric_subtag = subtag_bignum
+
+	define_node_subtag(ratio,1)
+max_rational_subtag = subtag_ratio
+
+	define_imm_subtag(single_float,1)
+	define_imm_subtag(double_float,2)
+min_float_subtag = subtag_single_float
+max_float_subtag = subtag_double_float
+max_real_subtag = subtag_double_float
+
+	define_node_subtag(complex,3)
+max_numeric_subtag = subtag_complex
+
+
+/* CL array types.  There are more immediate types than node types; all CL array subtags must be > than */
+/* all non-CL-array subtags.  So we start by defining the immediate subtags in decreasing order, starting */
+/* with that subtag whose element size isn]t an integral number of bits and ending with those whose */
+/* element size - like all non-CL-array fulltag-immheader types - is 32 bits. */
+
+	define_imm_subtag(bit_vector,31)
+	define_imm_subtag(double_float_vector,30)
+	define_imm_subtag(s16_vector,29)
+	define_imm_subtag(u16_vector,28)
+min_16_bit_ivector_subtag = subtag_u16_vector
+max_16_bit_ivector_subtag = subtag_s16_vector
+	define_imm_subtag(s8_vector,26)
+	define_imm_subtag(u8_vector,25)
+min_8_bit_ivector_subtag = subtag_u8_vector
+max_8_bit_ivector_subtag = fulltag_immheader|(27<<ntagbits)
+        define_imm_subtag(simple_base_string,24)
+        define_imm_subtag(fixnum_vector,23)
+	define_imm_subtag(s32_vector,22)
+	define_imm_subtag(u32_vector,21)
+	define_imm_subtag(single_float_vector,20)
+max_32_bit_ivector_subtag = fulltag_immheader|(24<<ntagbits)
+min_cl_ivector_subtag = subtag_single_float_vector
+
+
+	define_node_subtag(vectorH,20)
+	define_node_subtag(arrayH,19)
+	define_node_subtag(simple_vector,21)
+min_vector_subtag = subtag_vectorH
+min_array_subtag = subtag_arrayH
+
+/* So, we get the remaining subtags (n: (n > max-numeric-subtag) & (n < min-array-subtag)) */
+/* for various immediate/node object types. */
+
+	define_imm_subtag(macptr,3)
+min_non_numeric_imm_subtag = subtag_macptr
+
+	define_imm_subtag(dead_macptr,4)
+	define_imm_subtag(code_vector,5)
+	define_imm_subtag(creole,6)
+
+max_non_array_imm_subtag = (18<<ntagbits)|fulltag_immheader
+
+	define_node_subtag(catch_frame,4)
+	define_node_subtag(function,5)
+	define_node_subtag(basic_stream,6)
+	define_node_subtag(symbol,7)
+	define_node_subtag(lock,8)
+	define_node_subtag(hash_vector,9)
+	define_node_subtag(pool,10)
+	define_node_subtag(weak,11)
+	define_node_subtag(package,12)
+	define_node_subtag(slot_vector,13)
+	define_node_subtag(instance,14)
+	define_node_subtag(struct,15)
+	define_node_subtag(istruct,16)
+	define_node_subtag(value_cell,17)
+        define_node_subtag(xfunction,18)
+max_non_array_node_subtag = (18<<ntagbits)|fulltag_immheader
+	
+/* The objects themselves look something like this: */
+	_structf(ratio)
+	 _node(numer)
+	 _node(denom)
+	_endstructf
+
+	_structf(single_float)
+	 _word(value)
+	_endstructf
+
+	_structf(double_float)
+	 _word(pad)
+	 _dword(value)
+	_endstructf
+
+	_structf(symbol)
+	 _node(pname)
+	 _node(vcell)
+	 _node(fcell)
+	 _node(package_predicate)
+	 _node(flags)
+         _node(plist)
+         _node(binding_index)
+	_endstructf
+
+	_structf(catch_frame)
+	 _node(catch_tag)	/* #<unbound> -> unwind-protect, else catch */
+	 _node(link)		/* backpointer to previous catch frame */
+	 _node(mvflag)		/* 0 if single-valued catch, fixnum 1 otherwise */
+	 _node(csp)		/* pointer to lisp_frame on csp */
+	 _node(db_link)		/* head of special-binding chain */
+	 _field(regs,8*node_size)	/* save7-save0 */
+	 _node(xframe)		/* exception frame chain */
+	 _node(tsp_segment)	/* maybe someday; padding for now */
+	_endstructf
+
+	_structf(macptr)
+	 _node(address)
+         _node(domain)
+         _node(type)
+	_endstructf
+
+	_structf(vectorH)
+	 _node(logsize)
+	 _node(physsize)
+	 _node(data_vector)
+	 _node(displacement)
+	 _node(flags)
+	_endstructf
+
+        _structf(arrayH)
+         _node(rank)
+         _node(physsize)
+         _node(data_vector)
+         _node(displacement)
+         _node(flags)
+         _struct_label(dim0)
+        _endstructf
+        
+	
+        
+	_struct(c_frame,0)	/* PowerOpen ABI C stack frame */
+	 _node(backlink)
+	 _node(crsave)
+	 _node(savelr)
+	 _field(unused, 8)
+	 _node(savetoc)
+	 _struct_label(params)
+         _node(param0)
+         _node(param1)
+         _node(param2)
+         _node(param3)
+         _node(param4)
+         _node(param5)
+         _node(param6)
+         _node(param7)
+	 _struct_label(minsiz)
+	_ends
+
+
+	_struct(eabi_c_frame,0)
+	 _word(backlink) 
+	 _word(savelr)
+	 _word(param0)
+	 _word(param1)
+	 _word(param2)
+	 _word(param3)
+	 _word(param4)
+	 _word(param5)
+	 _word(param6)
+	 _word(param7)
+	 _struct_label(minsiz)
+	_ends
+
+	/* For entry to variable-argument-list functions */
+/*	  (e.g., via callback) */
+	_struct(varargs_eabi_c_frame,0)
+	 _word(backlink)
+	 _word(savelr)
+	 _struct_label(va_list)
+	 _word(flags)		/* gpr count byte, fpr count byte, padding */
+	 _word(overflow_arg_area)
+	 _word(reg_save_area)
+	 _field(padding,4)
+	 _struct_label(regsave)
+	 _field(gp_save,8*node_size)
+	 _field(fp_save,8*8)
+	 _word(old_backlink)
+	 _word(old_savelr)
+	 _struct_label(incoming_stack_args)
+	_ends
+        	
+	_struct(lisp_frame,0)
+	 _node(backlink) 
+	 _node(savefn)	
+	 _node(savelr)	
+	 _node(savevsp)	
+	_ends
+
+	_struct(vector,-fulltag_misc)
+	 _node(header)
+	 _struct_label(data)
+	_ends
+
+        _struct(binding,0)
+         _node(link)
+         _node(sym)
+         _node(val)
+        _ends
+
+
+
+symbol_extra = symbol.size-fulltag_misc
+	
+	_struct(nrs,nil_value-fulltag_nil)
+	 _struct_pad(fulltag_nil)
+	 _field(nilptr,16-fulltag_nil)
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(tsym)
+	 _struct_pad(symbol_extra)	/* t */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(nilsym)
+	 _struct_pad(symbol_extra)	/* nil */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(errdisp)
+	 _struct_pad(symbol_extra)	/* %err-disp */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(cmain)
+	 _struct_pad(symbol_extra)	/* cmain */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(eval)
+	 _struct_pad(symbol_extra)	/* eval */
+ 
+	 _struct_pad(fulltag_misc)
+	 _struct_label(appevalfn)
+	 _struct_pad(symbol_extra)	/* apply-evaluated-function */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(error)
+	 _struct_pad(symbol_extra)	/* error */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(defun)
+	 _struct_pad(symbol_extra)	/* %defun */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(defvar)
+	 _struct_pad(symbol_extra)	/* %defvar */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(defconstant)
+	 _struct_pad(symbol_extra)	/* %defconstant */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(macrosym)
+	 _struct_pad(symbol_extra)	/* %macro */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(kernelrestart)
+	 _struct_pad(symbol_extra)	/* %kernel-restart */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(package)
+	 _struct_pad(symbol_extra)	/* *package* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(total_bytes_freed)		/* *total-bytes-freed* */
+	 _struct_pad(symbol_extra)
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(kallowotherkeys)
+	 _struct_pad(symbol_extra)	/* allow-other-keys */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(toplcatch)
+	 _struct_pad(symbol_extra)	/* %toplevel-catch% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(toplfunc)
+	 _struct_pad(symbol_extra)	/* %toplevel-function% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(callbacks)
+	 _struct_pad(symbol_extra)	/* %pascal-functions% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(allmeteredfuns)
+	 _struct_pad(symbol_extra)	/* *all-metered-functions* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(total_gc_microseconds)		/* *total-gc-microseconds* */
+	 _struct_pad(symbol_extra)
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(builtin_functions)		/* %builtin-functions% */
+	 _struct_pad(symbol_extra)                
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(udf)
+	 _struct_pad(symbol_extra)	/* %unbound-function% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(init_misc)
+	 _struct_pad(symbol_extra)	/* %init-misc */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(macro_code)
+	 _struct_pad(symbol_extra)	/* %macro-code% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(closure_code)
+	 _struct_pad(symbol_extra)      /* %closure-code% */
+
+       	 _struct_pad(fulltag_misc)
+	 _struct_label(new_gcable_ptr) /* %new-gcable-ptr */
+	 _struct_pad(symbol_extra)
+	
+       	 _struct_pad(fulltag_misc)
+	 _struct_label(gc_event_status_bits)
+	 _struct_pad(symbol_extra)	/* *gc-event-status-bits* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(post_gc_hook)
+	 _struct_pad(symbol_extra)	/* *post-gc-hook* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(handlers)
+	 _struct_pad(symbol_extra)	/* %handlers% */
+
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(all_packages)
+	 _struct_pad(symbol_extra)	/* %all-packages% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(keyword_package)
+	 _struct_pad(symbol_extra)	/* *keyword-package* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(finalization_alist)
+	 _struct_pad(symbol_extra)	/* %finalization-alist% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(foreign_thread_control)
+	 _struct_pad(symbol_extra)	/* %foreign-thread-control */
+
+	_ends
+
+define([def_header],[
+$1 = ($2<<num_subtag_bits)|$3])
+
+	def_header(single_float_header,single_float.element_count,subtag_single_float)
+	def_header(double_float_header,double_float.element_count,subtag_double_float)
+	def_header(one_digit_bignum_header,1,subtag_bignum)
+	def_header(two_digit_bignum_header,2,subtag_bignum)
+	def_header(three_digit_bignum_header,3,subtag_bignum)
+	def_header(symbol_header,symbol.element_count,subtag_symbol)
+	def_header(value_cell_header,1,subtag_value_cell	)
+	def_header(macptr_header,macptr.element_count,subtag_macptr)
+	def_header(vectorH_header,vectorH.element_count,subtag_vectorH)
+
+	include(errors.s)
+
+/* Symbol bits that we care about */
+sym_vbit_bound = (0+fixnum_shift)
+sym_vbit_bound_mask = (1<<sym_vbit_bound)
+sym_vbit_const = (1+fixnum_shift)
+sym_vbit_const_mask = (1<<sym_vbit_const)
+
+	_struct(area,0)
+	 _node(pred) 
+	 _node(succ) 
+	 _node(low) 
+	 _node(high) 
+	 _node(active) 
+	 _node(softlimit) 
+	 _node(hardlimit) 
+	 _node(code) 
+	 _node(markbits) 
+	 _node(ndwords) 
+	 _node(older) 
+	 _node(younger) 
+	 _node(h) 
+	 _node(sofprot) 
+	 _node(hardprot) 
+	 _node(owner) 
+	 _node(refbits) 
+	 _node(nextref) 
+	_ends
+
+
+/* This is only referenced by c->lisp code that needs to save/restore C NVRs in a TSP frame. */
+	_struct(c_reg_save,0)
+	 _node(tsp_link)	/* backpointer */
+	 _node(tsp_mark)	/* frame type */
+	 _node(save_fpscr)	/* for Cs FPSCR */
+	 _field(save_gprs,19*4) /* r13-r31 */
+	 _dword(save_fp_zero)	/* for fp_zero */
+	 _dword(save_fps32conv)
+         _field(save_fprs,13*8)
+	_ends
+
+
+TCR_BIAS = 0
+/* TCR_BIAS = 0x7000 */
+        
+/*  Thread context record. */
+
+	_struct(tcr,-TCR_BIAS)
+	 _node(prev)		/* in doubly-linked list */
+	 _node(next)		/* in doubly-linked list */
+	 _node(lisp_fpscr)	/* lisp thread's fpscr (in low word) */
+	 _node(lisp_fpscr_low)
+	 _node(db_link)		/* special binding chain head */
+	 _node(catch_top)	/* top catch frame */
+	 _node(save_vsp)	/* VSP when in foreign code */
+	 _node(save_tsp)	/* TSP when in foreign code */
+	 _node(cs_area)		/* cstack area pointer */
+	 _node(vs_area)		/* vstack area pointer */
+	 _node(ts_area)		/* tstack area pointer */
+	 _node(cs_limit)	/* cstack overflow limit */
+	 _node(bytes_consed_high)
+	 _node(bytes_consed_low)
+	 _node(log2_allocation_quantum)
+	 _node(interrupt_pending)
+	 _node(xframe)		/* per-thread exception frame list */
+	 _node(errno_loc)	/* per-thread  errno location */
+	 _node(ffi_exception)	/* fpscr exception bits from ff-call */
+	 _node(osid)		/* OS thread id */
+         _node(valence)		/* odd when in foreign code */
+	 _node(foreign_exception_status)
+	 _node(native_thread_info)
+	 _node(native_thread_id)
+	 _node(last_allocptr)
+	 _node(save_allocptr)
+	 _node(save_allocbase)
+	 _node(reset_completion)
+	 _node(activate)
+         _node(suspend_count)
+         _node(suspend_context)
+	 _node(pending_exception_context)
+	 _node(suspend)		/* semaphore for suspension notify */
+	 _node(resume)		/* sempahore for resumption notify */
+	 _node(flags)      
+	 _node(gc_context)
+         _node(termination_semaphore)
+         _node(unwinding)
+         _node(tlb_limit)
+         _node(tlb_pointer)     /* Consider using tcr+N as tlb_pointer */
+	 _node(shutdown_count)
+         _node(safe_ref_address)
+	_ends
+
+TCR_FLAG_BIT_FOREIGN = fixnum_shift
+TCR_FLAG_BIT_AWAITING_PRESET = (fixnum_shift+1)
+TCR_FLAG_BIT_ALT_SUSPEND = (fixnumshift+2)
+TCR_FLAG_BIT_PROPAGATE_EXCEPTION = (fixnumshift+3)
+TCR_FLAG_BIT_SUSPEND_ACK_PENDING = (fixnumshift+4)
+TCR_FLAG_BIT_PENDING_EXCEPTION = (fixnumshift+5)
+TCR_FLAG_BIT_FOREIGN_EXCEPTION = (fixnumshift+6)
+TCR_FLAG_BIT_PENDING_SUSPEND = (fixnumshift+7)        
+	
+r0 = 0
+r1 = 1
+r2 = 2
+r3 = 3
+r4 = 4
+r5 = 5
+r6 = 6
+r7 = 7
+r8 = 8
+r9 = 9
+r10 = 10
+r11 = 11
+r12 = 12
+r13 = 13
+r14 = 14
+r15 = 15
+r16 = 16
+r17 = 17
+r18 = 18
+r19 = 19
+r20 = 20
+r21 = 21
+r22 = 22
+r23 = 23
+r24 = 24
+r25 = 25
+r26 = 26
+r27 = 27
+r28 = 28
+r29 = 29
+r30 = 30
+r31 = 31
+
+/* Lisp code keeps 0.0 in fp_zero */
+define([fp_zero],[f31])   /* a non-volatile reg as far as FFI is concerned. */
+define([fp_s32conv],[f30])   /* for s32->fp conversion */
+	
+/* registers, as used in destrucuring-bind/macro-bind */
+
+define([whole_reg],[temp1])
+define([arg_reg],[temp3])
+define([keyvect_reg],[temp2])
+define([mask_req_start],[24])
+define([mask_req_width],[8])
+define([mask_opt_start],[16])
+define([mask_opt_width],[8])
+define([mask_key_start],[8])
+define([mask_key_width],[8])
+define([mask_initopt],[7])
+define([mask_keyp],[6]) /*  note that keyp can be true even when 0 keys. */
+define([mask_aok],[5])
+define([mask_restp],[4])
+
+ifdef([DARWIN],[
+	define([STACK_ALIGN],16)
+	define([STACK_ALIGN_MASK],15)
+],[
+	define([STACK_ALIGN],8)
+	define([STACK_ALIGN_MASK],7)
+])
+
+define([TCR_STATE_FOREIGN],1)
+define([TCR_STATE_LISP],0)
+define([TCR_STATE_EXCEPTION_WAIT],2)
+define([TCR_STATE_EXCEPTION_RETURN],4)
+
+define([RESERVATION_DISCHARGE],0x2004)
+
+lisp_globals_limit = (0x3010+(LOWMEM_BIAS))
+        
+INTERRUPT_LEVEL_BINDING_INDEX = fixnumone
Index: /branches/new-random/lisp-kernel/ppc-constants64.h
===================================================================
--- /branches/new-random/lisp-kernel/ppc-constants64.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-constants64.h	(revision 13309)
@@ -0,0 +1,456 @@
+/*
+   Copyright (C) 2003-2009, Clozure Associates.
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __constants64__
+#define __constants64__ 1
+
+#define rcontext 2
+
+#define nbits_in_word 64L
+#define log2_nbits_in_word 6L
+#define nbits_in_byte 8L
+#define ntagbits 4L
+#define nlisptagbits 3L
+#define nfixnumtagbits 2L
+#define num_subtag_bits 8L
+#define fixnumshift 3L
+#define fixnum_shift 3L
+#define fulltagmask 15L
+#define tagmask	 7L
+#define fixnummask 3
+#define subtagmask ((1L<<num_subtag_bits)-1L)
+#define ncharcodebits 8L
+#define charcode_shift 8L
+#define node_size 8L
+#define node_shift 3L
+
+#define lowtagmask 3L
+#define lowtag_mask lowtagmask
+
+#define lowtag_primary 0L
+#define lowtag_imm 1L
+#define lowtag_immheader 2L
+#define lowtag_nodeheader 3L
+
+#define tag_fixnum 0L
+
+#define fulltag_even_fixnum 0L
+#define fulltag_imm_0 1L
+#define fulltag_immheader_0 2L
+#define fulltag_nodeheader_0 3L
+#define fulltag_cons 4L
+#define fulltag_imm_1 5L
+#define fulltag_immheader_1 6L
+#define fulltag_nodeheader_1 7L
+#define fulltag_odd_fixnum 8L
+#define fulltag_imm_2 9L
+#define fulltag_immheader_2 10L
+#define fulltag_nodeheader_2 11L
+#define fulltag_misc 12L
+#define fulltag_imm_3 13L
+#define fulltag_immheader_3 14L
+#define fulltag_nodeheader_3 15L
+
+#define SUBTAG(tag,subtag) ((tag) | ((subtag) << ntagbits))
+#define cl_array_subtag_mask 0x80L
+#define CL_ARRAY_SUBTAG(tag,subtag) (cl_array_subtag_mask | (SUBTAG(tag,subtag)))
+
+#define subtag_arrayH CL_ARRAY_SUBTAG(fulltag_nodeheader_1,0L)
+#define subtag_vectorH CL_ARRAY_SUBTAG(fulltag_nodeheader_2,0L)
+#define subtag_simple_vector CL_ARRAY_SUBTAG(fulltag_nodeheader_3,0L)
+#define min_vector_subtag subtag_vectorH	
+
+#define ivector_class_64_bit fulltag_immheader_3
+#define ivector_class_32_bit fulltag_immheader_2
+#define ivector_class_other_bit fulltag_immheader_1
+#define ivector_class_8_bit fulltag_immheader_0
+
+#define subtag_s64_vector CL_ARRAY_SUBTAG(ivector_class_64_bit,1)
+#define subtag_u64_vector CL_ARRAY_SUBTAG(ivector_class_64_bit,2)
+#define subtag_fixnum_vector CL_ARRAY_SUBTAG(ivector_class_64_bit,3)
+#define subtag_double_float_vector CL_ARRAY_SUBTAG(ivector_class_64_bit,4)
+#define subtag_s32_vector CL_ARRAY_SUBTAG(ivector_class_32_bit,1)
+#define subtag_u32_vector CL_ARRAY_SUBTAG(ivector_class_32_bit,2)
+#define subtag_single_float_vector CL_ARRAY_SUBTAG(ivector_class_32_bit,3)
+#define subtag_simple_base_string CL_ARRAY_SUBTAG(ivector_class_32_bit,5)
+#define subtag_s16_vector CL_ARRAY_SUBTAG(ivector_class_other_bit,1)
+#define subtag_u16_vector CL_ARRAY_SUBTAG(ivector_class_other_bit,2)
+#define subtag_bit_vector CL_ARRAY_SUBTAG(ivector_class_other_bit,7)
+#define subtag_s8_vector CL_ARRAY_SUBTAG(ivector_class_8_bit,1)
+#define subtag_u8_vector CL_ARRAY_SUBTAG(ivector_class_8_bit,2)
+
+/* There's some room for expansion in non-array ivector space. */
+#define subtag_macptr SUBTAG(ivector_class_64_bit,1)
+#define subtag_dead_macptr SUBTAG(ivector_class_64_bit,2)
+#define subtag_code_vector SUBTAG(ivector_class_32_bit,0)
+#define subtag_xcode_vector SUBTAG(ivector_class_32_bit,1)
+#define subtag_bignum SUBTAG(ivector_class_32_bit,2)
+#define subtag_double_float SUBTAG(ivector_class_32_bit,3)
+
+
+/*
+ Size doesn't matter for non-CL-array gvectors; I can't think of a good
+ reason to classify them in any particular way.  Let's put funcallable
+ things in the first slice by themselves, though it's not clear that
+ that helps FUNCALL much.
+*/
+#define gvector_funcallable fulltag_nodeheader_0
+	
+#define subtag_function SUBTAG(gvector_funcallable,0)
+#define subtag_symbol SUBTAG(gvector_funcallable,1)
+#define subtag_catch_frame SUBTAG(fulltag_nodeheader_1,0)
+#define subtag_basic_stream SUBTAG(fulltag_nodeheader_1,1)
+#define subtag_lock SUBTAG(fulltag_nodeheader_1,2)
+#define subtag_hash_vector SUBTAG(fulltag_nodeheader_1,3)
+#define subtag_pool SUBTAG(fulltag_nodeheader_1,4)
+#define subtag_weak SUBTAG(fulltag_nodeheader_1,5)
+#define subtag_package SUBTAG(fulltag_nodeheader_1,6)
+
+#define subtag_slot_vector SUBTAG(fulltag_nodeheader_2,0)
+#define subtag_instance SUBTAG(fulltag_nodeheader_2,1)
+#define subtag_struct SUBTAG(fulltag_nodeheader_2,2)
+#define subtag_istruct SUBTAG(fulltag_nodeheader_2,3)
+#define subtag_value_cell SUBTAG(fulltag_nodeheader_2,4)
+#define subtag_xfunction SUBTAG(fulltag_nodeheader_2,5)
+
+#define subtag_ratio SUBTAG(fulltag_nodeheader_3,0)
+#define subtag_complex SUBTAG(fulltag_nodeheader_3,1)
+
+
+
+#define nil_value (0x3000+fulltag_misc+sizeof(struct lispsymbol)+(LOWMEM_BIAS))
+#define t_value (0x3000+fulltag_misc+(LOWMEM_BIAS))	
+#define misc_bias fulltag_misc
+#define cons_bias fulltag_cons
+
+	
+#define misc_header_offset -fulltag_misc
+#define misc_subtag_offset misc_header_offset+7       /* low byte of header */
+#define misc_data_offset misc_header_offset+8		/* first word of data */
+#define misc_dfloat_offset misc_header_offset		/* double-floats are doubleword-aligned */
+
+#define subtag_single_float SUBTAG(fulltag_imm_0,0)
+
+#define subtag_go_tag SUBTAG(fulltag_imm_1,2) /* deprecated */
+#define subtag_block_tag SUBTAG(fulltag_imm_1,3) /* deprecated */
+
+#define subtag_character SUBTAG(fulltag_imm_1,0)
+
+#define subtag_unbound SUBTAG(fulltag_imm_3,0)
+#define unbound_marker subtag_unbound
+#define undefined unbound_marker
+#define unbound unbound_marker
+#define subtag_slot_unbound SUBTAG(fulltag_imm_3,1)
+#define slot_unbound_marker subtag_slot_unbound
+#define slot_unbound slot_unbound_marker
+#define subtag_illegal SUBTAG(fulltag_imm_3,2)
+#define illegal_marker subtag_illegal
+#define subtag_no_thread_local_binding SUBTAG(fulltag_imm_3,3)
+#define no_thread_local_binding_marker subtag_no_thread_local_binding        
+#define subtag_forward_marker SUBTAG(fulltag_imm_3,7)
+	
+#define max_64_bit_constant_index ((0x7fff + misc_dfloat_offset)>>3)
+#define max_32_bit_constant_index ((0x7fff + misc_data_offset)>>2)
+#define max_16_bit_constant_index ((0x7fff + misc_data_offset)>>1)
+#define max_8_bit_constant_index (0x7fff + misc_data_offset)
+#define max_1_bit_constant_index ((0x7fff + misc_data_offset)<<5)
+
+
+/* The objects themselves look something like this: */
+
+/*  Order of CAR and CDR doesn't seem to matter much - there aren't */
+/*  too many tricks to be played with predecrement/preincrement addressing. */
+/*  Keep them in the confusing MCL 3.0 order, to avoid confusion. */
+
+typedef struct cons {
+  LispObj cdr;
+  LispObj car;
+} cons;
+
+
+
+typedef struct lispsymbol {
+  LispObj header;
+  LispObj pname;
+  LispObj vcell;
+  LispObj fcell;
+  LispObj package_predicate;
+  LispObj flags;
+  LispObj plist;
+  LispObj binding_index;
+} lispsymbol;
+
+typedef struct ratio {
+  LispObj header;
+  LispObj numer;
+  LispObj denom;
+} ratio;
+
+typedef struct double_float {
+  LispObj header;
+  LispObj value;
+} double_float;
+
+
+typedef struct macptr {
+  LispObj header;
+  LispObj address;
+  LispObj class;
+  LispObj type;
+} macptr;
+
+typedef struct xmacptr {
+  LispObj header;
+  LispObj address;
+  LispObj class;
+  LispObj type;
+  LispObj flags;
+  LispObj link;
+} xmacptr;
+  
+
+typedef struct eabi_c_frame {
+  struct eabi_c_frame *backlink;
+  unsigned savelr;
+  LispObj params[8];
+} eabi_c_frame;
+
+/* PowerOpen ABI C frame */
+
+typedef struct c_frame {
+  struct c_frame *backlink;
+  natural crsave;
+  natural savelr;
+  natural unused[2];
+  natural savetoc;		/* Used with CFM (and on Linux.) */
+  natural params[8];		/* Space for callee to save r3-r10 */
+} c_frame;
+
+typedef struct lisp_frame {
+  struct lisp_frame *backlink;
+  LispObj savefn;
+  LispObj savelr;
+  LispObj savevsp;
+} lisp_frame;
+
+typedef struct special_binding {
+  struct special_binding *link;
+  struct lispsymbol *sym;
+  LispObj value;
+} special_binding;
+
+/* The GC (at least) needs to know what a
+   package looks like, so that it can do GCTWA. */
+typedef struct package {
+  LispObj header;
+  LispObj itab;			/* itab and etab look like (vector (fixnum . fixnum) */
+  LispObj etab;
+  LispObj used;
+  LispObj used_by;
+  LispObj names;
+  LispObj shadowed;
+} package;
+
+/*
+  The GC also needs to know what a catch_frame looks like.
+*/
+
+typedef struct catch_frame {
+  LispObj header;
+  LispObj catch_tag;
+  LispObj link;
+  LispObj mvflag;
+  LispObj csp;
+  LispObj db_link;
+  LispObj regs[8];
+  LispObj xframe;
+  LispObj tsp_segment;
+} catch_frame;
+
+#define catch_frame_element_count ((sizeof(catch_frame)/sizeof(LispObj))-1)
+#define catch_frame_header make_header(subtag_catch_frame,catch_frame_element_count)
+
+
+/* 
+  All exception frames in a thread are linked together 
+  */
+typedef struct xframe_list {
+  ExceptionInformation *curr;
+  struct xframe_list *prev;
+} xframe_list;
+
+#define fixnum_bitmask(n)  (1LL<<((n)+fixnumshift))
+
+/* 
+  The GC (at least) needs to know about hash-table-vectors and their flag bits.
+*/
+
+typedef struct hash_table_vector_header {
+  LispObj header;
+  LispObj link;                 /* If weak */
+  LispObj flags;                /* a fixnum; see below */
+  LispObj gc_count;             /* gc-count kernel global */
+  LispObj free_alist;           /* preallocated conses for finalization_alist */
+  LispObj finalization_alist;   /* key/value alist for finalization */
+  LispObj weak_deletions_count; /* incremented when GC deletes weak pair */
+  LispObj hash;                 /* backpointer to hash-table */
+  LispObj deleted_count;        /* number of deleted entries [not maintained if lock-free] */
+  LispObj count;                /* number of valid entries [not maintained if lock-free] */
+  LispObj cache_idx;            /* index of last cached pair */
+  LispObj cache_key;            /* value of last cached key */
+  LispObj cache_value;          /* last cached value */
+  LispObj size;                 /* number of entries in table */
+  LispObj size_reciprocal;      /* shifted reciprocal of size */
+} hash_table_vector_header;
+
+/*
+  Bits (masks)  in hash_table_vector.flags:
+*/
+
+/* GC should track keys when addresses change */ 
+#define nhash_track_keys_mask fixnum_bitmask(28) 
+
+/* GC should set when nhash_track_keys_bit & addresses change */
+#define nhash_key_moved_mask  fixnum_bitmask(27) 
+
+/* weak on key or value (need new "weak both" encoding.) */
+#define nhash_weak_mask       fixnum_bitmask(12)
+
+/* weak on value */
+#define nhash_weak_value_mask fixnum_bitmask(11)
+
+/* finalizable */
+#define nhash_finalizable_mask fixnum_bitmask(10)
+
+/* keys frozen, i.e. don't clobber keys, only values */
+#define nhash_keys_frozen_mask fixnum_bitmask(9)
+
+/* Lfun bits */
+
+#define lfbits_nonnullenv_mask fixnum_bitmask(0)
+#define lfbits_keys_mask fixnum_bitmask(1)
+#define lfbits_restv_mask fixnum_bitmask(7)
+#define lfbits_optinit_mask fixnum_bitmask(14)
+#define lfbits_rest_mask fixnum_bitmask(15)
+
+#define lfbits_aok_mask fixnum_bitmask(16)
+#define lfbits_lap_mask fixnum_bitmask(23)
+#define lfbits_trampoline_mask fixnum_bitmask(24)
+#define lfbits_evaluated_mask fixnum_bitmask(25)
+#define lfbits_cm_mask fixnum_bitmask(26)         /* combined_method */
+#define lfbits_nextmeth_mask fixnum_bitmask(26)   /* or call_next_method with method_mask */
+#define lfbits_gfn_mask fixnum_bitmask(27)        /* generic_function */
+#define lfbits_nextmeth_with_args_mask fixnum_bitmask(27)   /* or call_next_method_with_args with method_mask */
+#define lfbits_method_mask fixnum_bitmask(28)     /* method function */
+/* PPC only but want it defined for xcompile */
+#define lfbits_noname_mask fixnum_bitmask(29)
+
+
+/* Creole */
+
+#define doh_quantum 400
+#define doh_block_slots ((doh_quantum >> 2) - 3)
+
+typedef struct doh_block {
+  struct doh_block *link;
+  unsigned size;
+  unsigned free;
+  LispObj data[doh_block_slots];
+} doh_block, *doh_block_ptr;
+
+
+#define population_weak_list (0<<fixnum_shift)
+#define population_weak_alist (1<<fixnum_shift)
+#define population_termination_bit (16+fixnum_shift)
+#define population_type_mask ((1<<population_termination_bit)-1)
+
+#define gc_retain_pages_bit fixnum_bitmask(0)
+#define gc_integrity_check_bit fixnum_bitmask(2)
+#define egc_verbose_bit fixnum_bitmask(3)
+#define gc_verbose_bit fixnum_bitmask(4)
+#define gc_allow_stack_overflows_bit fixnum_bitmask(5)
+#define gc_postgc_pending fixnum_bitmask(26)
+
+#include "lisp-errors.h"
+
+
+
+#define TCR_BIAS (0x0)
+
+typedef struct tcr {
+  struct tcr* next;
+  struct tcr* prev;
+  struct {
+    float f;
+    u_int32_t tag;
+  } single_float_convert;
+  union {
+    double d;
+    struct {u_int32_t h, l;} words;
+  } lisp_fpscr;			/* lisp thread's fpscr (in low word) */
+  special_binding* db_link;	/* special binding chain head */
+  LispObj catch_top;		/* top catch frame */
+  LispObj* save_vsp;  /* VSP when in foreign code */
+  LispObj* save_tsp;  /* TSP when in foreign code */
+  struct area* cs_area; /* cstack area pointer */
+  struct area* vs_area; /* vstack area pointer */
+  struct area* ts_area; /* tstack area pointer */
+  LispObj cs_limit;		/* stack overflow limit */
+  natural bytes_allocated;
+  natural log2_allocation_quantum;      /* for per-tread consing */
+  signed_natural interrupt_pending;	/* pending interrupt flag */
+  xframe_list* xframe; /* exception-frame linked list */
+  int* errno_loc;		/* per-thread (?) errno location */
+  LispObj ffi_exception;	/* fpscr bits from ff-call */
+  LispObj osid;			/* OS thread id */
+  signed_natural valence;			/* odd when in foreign code */
+  signed_natural foreign_exception_status;	/* non-zero -> call lisp_exit_hook */
+  void* native_thread_info;	/* platform-dependent */
+  void* native_thread_id;	/* mach_thread_t, pid_t, etc. */
+  void* last_allocptr;
+  void* save_allocptr;
+  void* save_allocbase;
+  void* reset_completion;
+  void* activate;
+  signed_natural suspend_count;
+  ExceptionInformation* suspend_context;
+  ExceptionInformation* pending_exception_context;
+  void* suspend;		/* suspension semaphore */
+  void* resume;			/* resumption semaphore */
+  natural flags;
+  ExceptionInformation* gc_context;
+  void* termination_semaphore;
+  signed_natural unwinding;
+  natural tlb_limit;
+  LispObj* tlb_pointer;
+  natural shutdown_count;
+  void *safe_ref_address;
+} TCR;
+
+#define t_offset -(sizeof(lispsymbol))
+
+/* 
+  These were previously global variables.  There are lots of implicit
+  assumptions about the size of a heap segment, so they might as well
+  be constants.
+*/
+
+#define heap_segment_size 0x00020000L
+#define log2_heap_segment_size 17L
+
+#endif
+
Index: /branches/new-random/lisp-kernel/ppc-constants64.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-constants64.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-constants64.s	(revision 13309)
@@ -0,0 +1,596 @@
+/*   Copyright (C) 2003-2009, Clozure Associates. */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL. */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence. */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+define([rcontext],[r2])
+        
+nbits_in_word = 64
+nbits_in_byte = 8
+ntagbits = 4
+nlisptagbits = 3
+nfixnumtagbits = 3
+nlowtagbits = 2        
+num_subtag_bits = 8
+fixnumshift = 3
+fixnum_shift = 3
+fulltagmask = 15
+tagmask = 7
+fixnummask = 7
+ncharcodebits = 8
+charcode_shift = 8
+word_shift = 3
+node_size = 8
+dnode_size = 16
+dnode_align_bits = 4
+dnode_shift = dnode_align_bits        
+bitmap_shift = 6
+        
+fixnumone = (1<<fixnumshift)
+fixnum_one = fixnumone
+fixnum1 = fixnumone
+
+
+lowtagmask = ((1<<nlowtagbits)-1)
+lowtag_mask = lowtagmask
+
+lowtag_primary = 0
+lowtag_imm = 1
+lowtag_immheader = 2
+lowtag_nodeheader = 3
+
+tag_fixnum = 0
+
+fulltag_even_fixnum = 0
+fulltag_imm_0 = 1
+fulltag_immheader_0 = 2
+fulltag_nodeheader_0 = 3
+fulltag_cons = 4
+fulltag_imm_1 = 5
+fulltag_immheader_1 = 6
+fulltag_nodeheader_1 = 7
+fulltag_odd_fixnum = 8
+fulltag_imm_2 = 9
+fulltag_immheader_2 = 10
+fulltag_nodeheader_2 = 11
+fulltag_misc = 12
+fulltag_imm_3 = 13
+fulltag_immheader_3 = 14
+fulltag_nodeheader_3 = 15
+
+define([define_subtag],[
+subtag_$1 = ($2 | ($3 << ntagbits))
+])
+			
+cl_array_subtag_mask = 0x80
+define([define_cl_array_subtag],[
+define_subtag($1,(cl_array_subtag_mask|$2),$3)
+])
+
+define_cl_array_subtag(arrayH,fulltag_nodeheader_1,0)
+define_cl_array_subtag(vectorH,fulltag_nodeheader_2,0)
+define_cl_array_subtag(simple_vector,fulltag_nodeheader_3,0)
+min_vector_subtag = subtag_vectorH
+min_array_subtag = subtag_arrayH
+        
+	
+ivector_class_64_bit = fulltag_immheader_3
+ivector_class_32_bit = fulltag_immheader_2
+ivector_class_other_bit = fulltag_immheader_1
+ivector_class_8_bit = fulltag_immheader_0
+
+define_cl_array_subtag(s64_vector,ivector_class_64_bit,1)
+define_cl_array_subtag(u64_vector,ivector_class_64_bit,2)
+define_cl_array_subtag(fixnum_vector,ivector_class_64_bit,3)        
+define_cl_array_subtag(double_float_vector,ivector_class_64_bit,4)
+define_cl_array_subtag(s32_vector,ivector_class_32_bit,1)
+define_cl_array_subtag(u32_vector,ivector_class_32_bit,2)
+define_cl_array_subtag(single_float_vector,ivector_class_32_bit,3)
+define_cl_array_subtag(simple_base_string,ivector_class_32_bit,5)
+define_cl_array_subtag(s16_vector,ivector_class_other_bit,1)
+define_cl_array_subtag(u16_vector,ivector_class_other_bit,2)
+define_cl_array_subtag(bit_vector,ivector_class_other_bit,7)
+define_cl_array_subtag(s8_vector,ivector_class_8_bit,1)
+define_cl_array_subtag(u8_vector,ivector_class_8_bit,2)
+/* There's some room for expansion in non-array ivector space. */
+define_subtag(macptr,ivector_class_64_bit,1)
+define_subtag(dead_macptr,ivector_class_64_bit,2)
+define_subtag(code_vector,ivector_class_32_bit,0)
+define_subtag(xcode_vector,ivector_class_32_bit,1)
+define_subtag(bignum,ivector_class_32_bit,2)
+define_subtag(double_float,ivector_class_32_bit,3)
+
+
+
+        
+/* Size doesn't matter for non-CL-array gvectors; I can't think of a good */
+/* reason to classify them in any particular way.  Let's put funcallable */
+/* things in the first slice by themselves, though it's not clear that */
+/* that helps FUNCALL much. */
+        
+gvector_funcallable = fulltag_nodeheader_0
+	
+define_subtag(function,gvector_funcallable,0)
+define_subtag(symbol,gvector_funcallable,1)
+define_subtag(catch_frame,fulltag_nodeheader_1,0)
+define_subtag(basic_stream,fulltag_nodeheader_1,1)
+define_subtag(lock,fulltag_nodeheader_1,2)
+define_subtag(hash_vector,fulltag_nodeheader_1,3)
+define_subtag(pool,fulltag_nodeheader_1,4)
+define_subtag(weak,fulltag_nodeheader_1,5)
+define_subtag(package,fulltag_nodeheader_1,6)
+        
+define_subtag(slot_vector,fulltag_nodeheader_2,0)
+define_subtag(instance,fulltag_nodeheader_2,1)
+define_subtag(struct,fulltag_nodeheader_2,2)
+define_subtag(istruct,fulltag_nodeheader_2,3)
+define_subtag(value_cell,fulltag_nodeheader_2,4)
+define_subtag(xfunction,fulltag_nodeheader_2,5)
+	
+define_subtag(ratio,fulltag_nodeheader_3,0)
+define_subtag(complex,fulltag_nodeheader_3,1)
+			
+t_value = (0x3000+fulltag_misc)	
+misc_bias = fulltag_misc
+cons_bias = fulltag_cons
+define([t_offset],-symbol.size)
+	
+misc_header_offset = -fulltag_misc
+misc_data_offset = misc_header_offset+node_size /* first word of data */
+misc_subtag_offset = misc_data_offset-1       /* low byte of header */
+misc_dfloat_offset = misc_data_offset		/* double-floats are doubleword-aligned */
+
+define_subtag(single_float,fulltag_imm_0,0)
+
+define_subtag(go_tag,fulltag_imm_1,0)
+define_subtag(block_tag,fulltag_imm_1,1)
+
+define_subtag(character,fulltag_imm_1,0)
+                	
+define_subtag(unbound,fulltag_imm_3,0)
+unbound_marker = subtag_unbound
+undefined = unbound_marker
+define_subtag(slot_unbound,fulltag_imm_3,1)
+slot_unbound_marker = subtag_slot_unbound
+define_subtag(illegal,fulltag_imm_3,2)
+illegal_marker = subtag_illegal
+define_subtag(no_thread_local_binding,fulltag_imm_3,3)
+no_thread_local_binding_marker = subtag_no_thread_local_binding        
+
+	
+max_64_bit_constant_index = ((0x7fff + misc_dfloat_offset)>>3)
+max_32_bit_constant_index = ((0x7fff + misc_data_offset)>>2)
+max_16_bit_constant_index = ((0x7fff + misc_data_offset)>>1)
+max_8_bit_constant_index = (0x7fff + misc_data_offset)
+max_1_bit_constant_index = ((0x7fff + misc_data_offset)<<5)
+
+
+	
+/* The objects themselves look something like this: */
+	
+/* Order of CAR and CDR doesn]t seem to matter much - there aren't */
+/* too many tricks to be played with predecrement/preincrement addressing. */
+/* Keep them in the confusing MCL 3.0 order, to avoid confusion. */
+	_struct(cons,-cons_bias)
+	 _node(cdr)
+	 _node(car)
+	_ends
+	
+	_structf(ratio)
+	 _node(numer)
+	 _node(denom)
+	_endstructf
+	
+	_structf(double_float)
+	 _word(value)
+         _word(val_low)
+	_endstructf
+	
+	_structf(macptr)
+	 _node(address)
+         _node(domain)
+         _node(type)
+	_endstructf
+	
+/* Functions are of (conceptually) unlimited size. */
+	_struct(_function,-misc_bias)
+	 _node(header)
+	 _node(codevector)
+	_ends
+
+	_struct(tsp_frame,0)
+	 _node(backlink)
+	 _node(type)
+	 _struct_label(fixed_overhead)
+	 _struct_label(data_offset)
+	_ends
+
+
+
+	_structf(symbol)
+	 _node(pname)
+	 _node(vcell)
+	 _node(fcell)
+	 _node(package_predicate)
+	 _node(flags)
+         _node(plist)
+         _node(binding_index)
+	_endstructf
+
+	_structf(catch_frame)
+	 _node(catch_tag)	/* #<unbound> -> unwind-protect, else catch */
+	 _node(link)		/* backpointer to previous catch frame */
+	 _node(mvflag)		/* 0 if single-valued catch, fixnum 1 otherwise */
+	 _node(csp)		/* pointer to lisp_frame on csp */
+	 _node(db_link)		/* head of special-binding chain */
+	 _field(regs,8*node_size)	/* save7-save0 */
+	 _node(xframe)		/* exception frame chain */
+	 _node(tsp_segment)	/* maybe someday; padding for now */
+	_endstructf
+
+
+	_structf(vectorH)
+	 _node(logsize)
+	 _node(physsize)
+	 _node(data_vector)
+	 _node(displacement)
+	 _node(flags)
+	_endstructf	
+	
+        _structf(arrayH)
+         _node(rank)
+         _node(physsize)
+         _node(data_vector)
+         _node(displacement)
+         _node(flags)
+         _struct_label(dim0)
+        _endstructf
+        
+	_struct(c_frame,0)	/* PowerOpen ABI C stack frame */
+	 _node(backlink)
+	 _node(crsave)
+	 _node(savelr)
+	 _field(unused, 16)
+	 _node(savetoc)
+	 _struct_label(params)
+         _node(param0)
+         _node(param1)
+         _node(param2)
+         _node(param3)
+         _node(param4)
+         _node(param5)
+         _node(param6)
+         _node(param7)
+	 _struct_label(minsiz)
+	_ends
+
+
+	_struct(eabi_c_frame,0)
+	 _word(backlink) 
+	 _word(savelr)
+	 _word(param0)
+	 _word(param1)
+	 _word(param2)
+	 _word(param3)
+	 _word(param4)
+	 _word(param5)
+	 _word(param6)
+	 _word(param7)
+	 _struct_label(minsiz)
+	_ends
+
+        /* For entry to variable-argument-list functions */
+	/* (e.g., via callback) */
+	_struct(varargs_eabi_c_frame,0)
+	 _word(backlink)
+	 _word(savelr)
+	 _struct_label(va_list)
+	 _word(flags)		/* gpr count byte, fpr count byte, padding */
+	 _word(overflow_arg_area)
+	 _word(reg_save_area)
+	 _field(padding,4)
+	 _struct_label(regsave)
+	 _field(gp_save,8*4)
+	 _field(fp_save,8*8)
+	 _word(old_backlink)
+	 _word(old_savelr)
+	 _struct_label(incoming_stack_args)
+	_ends
+        	
+	_struct(lisp_frame,0)
+	 _node(backlink) 
+	 _node(savefn)	
+	 _node(savelr)	
+	 _node(savevsp)	
+	_ends
+
+	_struct(vector,-fulltag_misc)
+	 _node(header)
+	 _struct_label(data)
+	_ends
+
+        _struct(binding,0)
+         _node(link)
+         _node(sym)
+         _node(val)
+        _ends
+
+
+/* Nilreg-relative globals.  Talking the assembler into doing something reasonable here */
+/* is surprisingly hard. */
+
+symbol_extra = symbol.size-fulltag_misc
+
+	
+	_struct(nrs,(0x3000+(LOWMEM_BIAS)))
+	 _struct_pad(fulltag_misc)
+	 _struct_label(tsym)
+	 _struct_pad(symbol_extra)	/* t */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(nil)
+	 _struct_pad(symbol_extra)	/* nil */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(errdisp)
+	 _struct_pad(symbol_extra)	/* %err-disp */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(cmain)
+	 _struct_pad(symbol_extra)	/* cmain */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(eval)
+	 _struct_pad(symbol_extra)	/* eval */
+ 
+	 _struct_pad(fulltag_misc)
+	 _struct_label(appevalfn)
+	 _struct_pad(symbol_extra)	/* apply-evaluated-function */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(error)
+	 _struct_pad(symbol_extra)	/* error */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(defun)
+	 _struct_pad(symbol_extra)	/* %defun */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(defvar)
+	 _struct_pad(symbol_extra)	/* %defvar */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(defconstant)
+	 _struct_pad(symbol_extra)	/* %defconstant */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(macrosym)
+	 _struct_pad(symbol_extra)	/* %macro */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(kernelrestart)
+	 _struct_pad(symbol_extra)	/* %kernel-restart */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(package)
+	 _struct_pad(symbol_extra)	/* *package* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(total_bytes_freed)		/* *total-bytes-freed* */
+	 _struct_pad(symbol_extra)
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(kallowotherkeys)
+	 _struct_pad(symbol_extra)	/* allow-other-keys */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(toplcatch)
+	 _struct_pad(symbol_extra)	/* %toplevel-catch% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(toplfunc)
+	 _struct_pad(symbol_extra)	/* %toplevel-function% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(callbacks)
+	 _struct_pad(symbol_extra)	/* %pascal-functions% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(allmeteredfuns)
+	 _struct_pad(symbol_extra)	/* *all-metered-functions* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(total_gc_microseconds)		/* *total-gc-microseconds* */
+	 _struct_pad(symbol_extra)
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(builtin_functions)		/* %builtin-functions% */
+	 _struct_pad(symbol_extra)                
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(udf)
+	 _struct_pad(symbol_extra)	/* %unbound-function% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(init_misc)
+	 _struct_pad(symbol_extra)	/* %init-misc */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(macro_code)
+	 _struct_pad(symbol_extra)	/* %macro-code% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(closure_code)
+	 _struct_pad(symbol_extra)      /* %closure-code% */
+
+       	 _struct_pad(fulltag_misc)
+	 _struct_label(new_gcable_ptr) /* %new-gcable-ptr */
+	 _struct_pad(symbol_extra)
+	
+       	 _struct_pad(fulltag_misc)
+	 _struct_label(gc_event_status_bits)
+	 _struct_pad(symbol_extra)	/* *gc-event-status-bits* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(post_gc_hook)
+	 _struct_pad(symbol_extra)	/* *post-gc-hook* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(handlers)
+	 _struct_pad(symbol_extra)	/* %handlers% */
+
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(all_packages)
+	 _struct_pad(symbol_extra)	/* %all-packages% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(keyword_package)
+	 _struct_pad(symbol_extra)	/* *keyword-package* */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(finalization_alist)
+	 _struct_pad(symbol_extra)	/* %finalization-alist% */
+
+	 _struct_pad(fulltag_misc)
+	 _struct_label(foreign_thread_control)
+	 _struct_pad(symbol_extra)	/* %foreign-thread-control */
+
+	_ends
+
+define([def_header],[
+$1 = ($2<<num_subtag_bits)|$3])
+
+	def_header(double_float_header,2,subtag_double_float)
+	def_header(two_digit_bignum_header,2,subtag_bignum)
+	def_header(three_digit_bignum_header,3,subtag_bignum)
+	def_header(four_digit_bignum_header,4,subtag_bignum)
+	def_header(five_digit_bignum_header,5,subtag_bignum)        
+	def_header(symbol_header,symbol.element_count,subtag_symbol)
+	def_header(value_cell_header,1,subtag_value_cell	)
+	def_header(macptr_header,macptr.element_count,subtag_macptr)
+	def_header(vectorH_header,vectorH.element_count,subtag_vectorH)
+
+	include(errors.s)
+
+/* Symbol bits that we care about */
+sym_vbit_bound = (0+fixnum_shift)
+sym_vbit_bound_mask = (1<<sym_vbit_bound)
+sym_vbit_const = (1+fixnum_shift)
+sym_vbit_const_mask = (1<<sym_vbit_const)
+
+	_struct(area,0)
+	 _node(pred) 
+	 _node(succ) 
+	 _node(low) 
+	 _node(high) 
+	 _node(active) 
+	 _node(softlimit) 
+	 _node(hardlimit) 
+	 _node(code) 
+	 _node(markbits) 
+	 _node(ndwords) 
+	 _node(older) 
+	 _node(younger) 
+	 _node(h) 
+	 _node(sofprot) 
+	 _node(hardprot) 
+	 _node(owner) 
+	 _node(refbits) 
+	 _node(nextref) 
+	_ends
+
+
+/* This is only referenced by c->lisp code that needs to save/restore C NVRs in a TSP frame. */
+	_struct(c_reg_save,0)
+	 _node(tsp_link)	/* backpointer */
+	 _node(tsp_mark)	/* frame type */
+	 _node(save_fpscr)	/* for Cs FPSCR */
+	 _field(save_gprs,19*node_size) /* r13-r31 */
+	 _dword(save_fp_zero)	/* for fp_zero */
+	 _dword(save_fps32conv)
+         _field(save_fprs,13*8)
+	_ends
+
+
+TCR_BIAS = 0
+	
+/*  Thread context record. */
+
+	_struct(tcr,-TCR_BIAS)
+	 _node(prev)		/* in doubly-linked list */
+	 _node(next)		/* in doubly-linked list */
+         _node(single_float_convert) /* xxxf0 */
+	 _word(lisp_fpscr)	/* lisp thread's fpscr (in low word) */
+	 _word(lisp_fpscr_low)
+	 _node(db_link)		/* special binding chain head */
+	 _node(catch_top)	/* top catch frame */
+	 _node(save_vsp)	/* VSP when in foreign code */
+	 _node(save_tsp)	/* TSP when in foreign code */
+	 _node(cs_area)		/* cstack area pointer */
+	 _node(vs_area)		/* vstack area pointer */
+	 _node(ts_area)		/* tstack area pointer */
+	 _node(cs_limit)	/* cstack overflow limit */
+	 _word(bytes_consed_high)
+	 _word(bytes_consed_low)
+	 _node(log2_allocation_quantum)
+	 _node(interrupt_pending)
+	 _node(xframe)		/* per-thread exception frame list */
+	 _node(errno_loc)	/* per-thread  errno location */
+	 _node(ffi_exception)	/* fpscr exception bits from ff-call */
+	 _node(osid)		/* OS thread id */
+         _node(valence)		/* odd when in foreign code */
+	 _node(foreign_exception_status)
+	 _node(native_thread_info)
+	 _node(native_thread_id)
+	 _node(last_allocptr)
+	 _node(save_allocptr)
+	 _node(save_allocbase)
+	 _node(reset_completion)
+	 _node(activate)
+         _node(suspend_count)
+         _node(suspend_context)
+	 _node(pending_exception_context)
+	 _node(suspend)		/* semaphore for suspension notify */
+	 _node(resume)		/* sempahore for resumption notify */
+         _word(flags_pad)
+	 _word(flags)      
+	 _node(gc_context)
+         _node(termination_semaphore)
+         _node(unwinding)
+         _node(tlb_limit)
+         _node(tlb_pointer)     /* Consider using tcr+N as tlb_pointer */
+	 _node(shutdown_count)
+         _node(safe_ref_address)
+	_ends
+
+TCR_FLAG_BIT_FOREIGN = fixnum_shift
+TCR_FLAG_BIT_AWAITING_PRESET = (fixnum_shift+1)
+TCR_FLAG_BIT_ALT_SUSPEND = (fixnumshift+2)
+TCR_FLAG_BIT_PROPAGATE_EXCEPTION = (fixnumshift+3)
+TCR_FLAG_BIT_SUSPEND_ACK_PENDING = (fixnumshift+4)
+TCR_FLAG_BIT_PENDING_EXCEPTION = (fixnumshift+5)
+TCR_FLAG_BIT_FOREIGN_EXCEPTION = (fixnumshift+6)
+TCR_FLAG_BIT_PENDING_SUSPEND = (fixnumshift+7)        
+
+
+nil_value = (0x3000+symbol.size+fulltag_misc+(LOWMEM_BIAS))
+        	
+define([RESERVATION_DISCHARGE],(0x2008+(LOWMEM_BIAS)))
+
+lisp_globals_limit = (0x3000+(LOWMEM_BIAS))
+        
+INTERRUPT_LEVEL_BINDING_INDEX = fixnumone
+        
+                
Index: /branches/new-random/lisp-kernel/ppc-exceptions.c
===================================================================
--- /branches/new-random/lisp-kernel/ppc-exceptions.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-exceptions.c	(revision 13309)
@@ -0,0 +1,3232 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp-exceptions.h"
+#include "lisp_globals.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#ifdef LINUX
+#include <strings.h>
+#include <sys/mman.h>
+#include <fpu_control.h>
+#include <linux/prctl.h>
+#endif
+
+#ifdef DARWIN
+#include <sys/mman.h>
+#define _FPU_RESERVED 0xffffff00
+#ifndef SA_NODEFER
+#define SA_NODEFER 0
+#endif
+#include <sysexits.h>
+
+/* a distinguished UUO at a distinguished address */
+extern void pseudo_sigreturn(ExceptionInformation *);
+#endif
+
+
+#include "Threads.h"
+
+#define MSR_FE0_MASK (((unsigned)0x80000000)>>20)
+#define MSR_FE1_MASK (((unsigned)0x80000000)>>23)
+#define MSR_FE0_FE1_MASK (MSR_FE0_MASK|MSR_FE1_MASK)
+extern void enable_fp_exceptions(void);
+extern void disable_fp_exceptions(void);
+
+#ifdef LINUX
+/* Some relatively recent kernels support this interface.
+   If this prctl isn't supported, assume that we're always
+   running with excptions enabled and "precise". 
+*/
+#ifndef PR_SET_FPEXC
+#define PR_SET_FPEXC 12
+#endif
+#ifndef PR_FP_EXC_DISABLED
+#define PR_FP_EXC_DISABLED 0
+#endif
+#ifndef PR_FP_EXC_PRECISE
+#define PR_FP_EXC_PRECISE 3
+#endif
+
+void
+enable_fp_exceptions()
+{
+  prctl(PR_SET_FPEXC, PR_FP_EXC_PRECISE);
+}
+
+void
+disable_fp_exceptions()
+{
+  prctl(PR_SET_FPEXC, PR_FP_EXC_DISABLED);
+}
+
+#endif
+
+/*
+  Handle exceptions.
+
+*/
+
+extern LispObj lisp_nil;
+
+extern natural lisp_heap_gc_threshold;
+extern Boolean grow_dynamic_area(natural);
+
+
+
+
+
+
+int
+page_size = 4096;
+
+int
+log2_page_size = 12;
+
+
+
+
+
+/*
+  If the PC is pointing to an allocation trap, the previous instruction
+  must have decremented allocptr.  Return the non-zero amount by which
+  allocptr was decremented.
+*/
+signed_natural
+allocptr_displacement(ExceptionInformation *xp)
+{
+  pc program_counter = xpPC(xp);
+  opcode instr = *program_counter, prev_instr = *(program_counter-1);
+
+  if (instr == ALLOC_TRAP_INSTRUCTION) {
+    if (match_instr(prev_instr, 
+                    XO_MASK | RT_MASK | RB_MASK,
+                    XO(major_opcode_X31,minor_opcode_SUBF, 0, 0) |
+                    RT(allocptr) |
+                    RB(allocptr))) {
+      return ((signed_natural) xpGPR(xp, RA_field(prev_instr)));
+    }
+    if (match_instr(prev_instr,
+                    OP_MASK | RT_MASK | RA_MASK,
+                    OP(major_opcode_ADDI) | 
+                    RT(allocptr) |
+                    RA(allocptr))) {
+      return (signed_natural) -((short) prev_instr);
+    }
+    Bug(xp, "Can't determine allocation displacement");
+  }
+  return 0;
+}
+
+
+/*
+  A cons cell's been successfully allocated, but the allocptr's
+  still tagged (as fulltag_cons, of course.)  Emulate any instructions
+  that might follow the allocation (stores to the car or cdr, an
+  assignment to the "result" gpr) that take place while the allocptr's
+  tag is non-zero, advancing over each such instruction.  When we're
+  done, the cons cell will be allocated and initialized, the result
+  register will point to it, the allocptr will be untagged, and
+  the PC will point past the instruction that clears the allocptr's
+  tag.
+*/
+void
+finish_allocating_cons(ExceptionInformation *xp)
+{
+  pc program_counter = xpPC(xp);
+  opcode instr;
+  LispObj cur_allocptr = xpGPR(xp, allocptr);
+  cons *c = (cons *)ptr_from_lispobj(untag(cur_allocptr));
+  int target_reg;
+
+  while (1) {
+    instr = *program_counter++;
+
+    if (instr == UNTAG_ALLOCPTR_INSTRUCTION) {
+      xpGPR(xp, allocptr) = untag(cur_allocptr);
+      xpPC(xp) = program_counter;
+      return;
+    }
+    
+    switch (instr & STORE_CXR_ALLOCPTR_MASK) {
+    case STORE_CAR_ALLOCPTR_INSTRUCTION:
+      c->car = xpGPR(xp,RT_field(instr));
+      break;
+    case STORE_CDR_ALLOCPTR_INSTRUCTION:
+      c->cdr = xpGPR(xp,RT_field(instr));
+      break;
+    default:
+      /* Assume that this is an assignment: {rt/ra} <- allocptr.
+         There are several equivalent instruction forms
+         that might have that effect; just assign to target here.
+      */
+      if (major_opcode_p(instr,major_opcode_X31)) {
+	target_reg = RA_field(instr);
+      } else {
+	target_reg = RT_field(instr);
+      }
+      xpGPR(xp,target_reg) = cur_allocptr;
+      break;
+    }
+  }
+}
+
+/*
+  We were interrupted in the process of allocating a uvector; we
+  survived the allocation trap, and allocptr is tagged as fulltag_misc.
+  Emulate any instructions which store a header into the uvector,
+  assign the value of allocptr to some other register, and clear
+  allocptr's tag.  Don't expect/allow any other instructions in
+  this environment.
+*/
+void
+finish_allocating_uvector(ExceptionInformation *xp)
+{
+  pc program_counter = xpPC(xp);
+  opcode instr;
+  LispObj cur_allocptr = xpGPR(xp, allocptr);
+  int target_reg;
+
+  while (1) {
+    instr = *program_counter++;
+    if (instr == UNTAG_ALLOCPTR_INSTRUCTION) {
+      xpGPR(xp, allocptr) = untag(cur_allocptr);
+      xpPC(xp) = program_counter;
+      return;
+    }
+    if ((instr &  STORE_HEADER_ALLOCPTR_MASK) == 
+        STORE_HEADER_ALLOCPTR_INSTRUCTION) {
+      header_of(cur_allocptr) = xpGPR(xp, RT_field(instr));
+    } else {
+      /* assume that this is an assignment */
+
+      if (major_opcode_p(instr,major_opcode_X31)) {
+	target_reg = RA_field(instr);
+      } else {
+	target_reg = RT_field(instr);
+      }
+      xpGPR(xp,target_reg) = cur_allocptr;
+    }
+  }
+}
+
+
+Boolean
+allocate_object(ExceptionInformation *xp,
+                natural bytes_needed, 
+                signed_natural disp_from_allocptr,
+		TCR *tcr)
+{
+  area *a = active_dynamic_area;
+
+  /* Maybe do an EGC */
+  if (a->older && lisp_global(OLDEST_EPHEMERAL)) {
+    if (((a->active)-(a->low)) >= a->threshold) {
+      gc_from_xp(xp, 0L);
+    }
+  }
+
+  /* Life is pretty simple if we can simply grab a segment
+     without extending the heap.
+  */
+  if (new_heap_segment(xp, bytes_needed, false, tcr)) {
+    xpGPR(xp, allocptr) += disp_from_allocptr;
+#ifdef DEBUG
+    fprintf(dbgout, "New heap segment for #x%x, no GC: #x%x/#x%x, vsp = #x%x\n",
+            tcr,xpGPR(xp,allocbase),tcr->last_allocptr, xpGPR(xp,vsp));
+#endif
+    return true;
+  }
+  
+  /* It doesn't make sense to try a full GC if the object
+     we're trying to allocate is larger than everything
+     allocated so far.
+  */
+  if ((lisp_global(HEAP_END)-lisp_global(HEAP_START)) > bytes_needed) {
+    untenure_from_area(tenured_area); /* force a full GC */
+    gc_from_xp(xp, 0L);
+  }
+  
+  /* Try again, growing the heap if necessary */
+  if (new_heap_segment(xp, bytes_needed, true, tcr)) {
+    xpGPR(xp, allocptr) += disp_from_allocptr;
+#ifdef DEBUG
+    fprintf(dbgout, "New heap segment for #x%x after GC: #x%x/#x%x\n",
+            tcr,xpGPR(xp,allocbase),tcr->last_allocptr);
+#endif
+    return true;
+  }
+  
+  return false;
+}
+
+#ifndef XNOMEM
+#define XNOMEM 10
+#endif
+
+void
+update_bytes_allocated(TCR* tcr, void *cur_allocptr)
+{
+  BytePtr 
+    last = (BytePtr) tcr->last_allocptr, 
+    current = (BytePtr) cur_allocptr;
+  if (last && (cur_allocptr != ((void *)VOID_ALLOCPTR))) {
+    tcr->bytes_allocated += last-current;
+  }
+  tcr->last_allocptr = 0;
+}
+
+void
+lisp_allocation_failure(ExceptionInformation *xp, TCR *tcr, natural bytes_needed)
+{
+  /* Couldn't allocate the object.  If it's smaller than some arbitrary
+     size (say 128K bytes), signal a "chronically out-of-memory" condition;
+     else signal a "allocation request failed" condition.
+  */
+  xpGPR(xp,allocptr) = xpGPR(xp,allocbase) = VOID_ALLOCPTR;
+  handle_error(xp, bytes_needed < (128<<10) ? XNOMEM : error_alloc_failed, 0, 0,  xpPC(xp));
+}
+
+/*
+  Allocate a large list, where "large" means "large enough to
+  possibly trigger the EGC several times if this was done
+  by individually allocating each CONS."  The number of 
+  ocnses in question is in arg_z; on successful return,
+  the list will be in arg_z 
+*/
+
+Boolean
+allocate_list(ExceptionInformation *xp, TCR *tcr)
+{
+  natural 
+    nconses = (unbox_fixnum(xpGPR(xp,arg_z))),
+    bytes_needed = (nconses << dnode_shift);
+  LispObj
+    prev = lisp_nil,
+    current,
+    initial = xpGPR(xp,arg_y);
+
+  if (nconses == 0) {
+    /* Silly case */
+    xpGPR(xp,arg_z) = lisp_nil;
+    xpGPR(xp,allocptr) = lisp_nil;
+    return true;
+  }
+  update_bytes_allocated(tcr, (void *)(void *) tcr->save_allocptr);
+  if (allocate_object(xp,bytes_needed,(-bytes_needed)+fulltag_cons,tcr)) {
+    for (current = xpGPR(xp,allocptr);
+         nconses;
+         prev = current, current+= dnode_size, nconses--) {
+      deref(current,0) = prev;
+      deref(current,1) = initial;
+    }
+    xpGPR(xp,arg_z) = prev;
+    xpGPR(xp,arg_y) = xpGPR(xp,allocptr);
+    xpGPR(xp,allocptr)-=fulltag_cons;
+  } else {
+    lisp_allocation_failure(xp,tcr,bytes_needed);
+  }
+  return true;
+}
+
+OSStatus
+handle_alloc_trap(ExceptionInformation *xp, TCR *tcr)
+{
+  pc program_counter;
+  natural cur_allocptr, bytes_needed = 0;
+  opcode prev_instr;
+  signed_natural disp = 0;
+  unsigned allocptr_tag;
+
+  cur_allocptr = xpGPR(xp,allocptr);
+  program_counter = xpPC(xp);
+  prev_instr = *(program_counter-1);
+  allocptr_tag = fulltag_of(cur_allocptr);
+
+  switch (allocptr_tag) {
+  case fulltag_cons:
+    bytes_needed = sizeof(cons);
+    disp = -sizeof(cons) + fulltag_cons;
+    break;
+
+  case fulltag_even_fixnum:
+  case fulltag_odd_fixnum:
+    break;
+
+  case fulltag_misc:
+    if (match_instr(prev_instr, 
+                    XO_MASK | RT_MASK | RB_MASK,
+                    XO(major_opcode_X31,minor_opcode_SUBF, 0, 0) |
+                    RT(allocptr) |
+                    RB(allocptr))) {
+      disp = -((signed_natural) xpGPR(xp, RA_field(prev_instr)));
+    } else if (match_instr(prev_instr,
+                           OP_MASK | RT_MASK | RA_MASK,
+                           OP(major_opcode_ADDI) | 
+                           RT(allocptr) |
+                           RA(allocptr))) {
+      disp = (signed_natural) ((short) prev_instr);
+    }
+    if (disp) {
+      bytes_needed = (-disp) + fulltag_misc;
+      break;
+    }
+    /* else fall thru */
+  default:
+    return -1;
+  }
+
+  if (bytes_needed) {
+    update_bytes_allocated(tcr,((BytePtr)(cur_allocptr-disp)));
+    if (allocate_object(xp, bytes_needed, disp, tcr)) {
+#if 0
+      fprintf(dbgout, "alloc_trap in 0x%lx, new allocptr = 0x%lx\n",
+              tcr, xpGPR(xp, allocptr));
+#endif
+      adjust_exception_pc(xp,4);
+      return 0;
+    }
+    lisp_allocation_failure(xp,tcr,bytes_needed);
+    return -1;
+  }
+  return -1;
+}
+
+natural gc_deferred = 0, full_gc_deferred = 0;
+
+signed_natural
+flash_freeze(TCR *tcr, signed_natural param)
+{
+  return 0;
+}
+
+OSStatus
+handle_gc_trap(ExceptionInformation *xp, TCR *tcr)
+{
+  LispObj 
+    selector = xpGPR(xp,imm0), 
+    arg = xpGPR(xp,imm1);
+  area *a = active_dynamic_area;
+  Boolean egc_was_enabled = (a->older != NULL);
+  natural gc_previously_deferred = gc_deferred;
+
+
+  switch (selector) {
+  case GC_TRAP_FUNCTION_EGC_CONTROL:
+    egc_control(arg != 0, a->active);
+    xpGPR(xp,arg_z) = lisp_nil + (egc_was_enabled ? t_offset : 0);
+    break;
+
+  case GC_TRAP_FUNCTION_CONFIGURE_EGC:
+    a->threshold = unbox_fixnum(xpGPR(xp, arg_x));
+    g1_area->threshold = unbox_fixnum(xpGPR(xp, arg_y));
+    g2_area->threshold = unbox_fixnum(xpGPR(xp, arg_z));
+    xpGPR(xp,arg_z) = lisp_nil+t_offset;
+    break;
+
+  case GC_TRAP_FUNCTION_SET_LISP_HEAP_THRESHOLD:
+    if (((signed_natural) arg) > 0) {
+      lisp_heap_gc_threshold = 
+        align_to_power_of_2((arg-1) +
+                            (heap_segment_size - 1),
+                            log2_heap_segment_size);
+    }
+    /* fall through */
+  case GC_TRAP_FUNCTION_GET_LISP_HEAP_THRESHOLD:
+    xpGPR(xp, imm0) = lisp_heap_gc_threshold;
+    break;
+
+  case GC_TRAP_FUNCTION_USE_LISP_HEAP_THRESHOLD:
+    /*  Try to put the current threshold in effect.  This may
+        need to disable/reenable the EGC. */
+    untenure_from_area(tenured_area);
+    resize_dynamic_heap(a->active,lisp_heap_gc_threshold);
+    if (egc_was_enabled) {
+      if ((a->high - a->active) >= a->threshold) {
+        tenure_to_area(tenured_area);
+      }
+    }
+    xpGPR(xp, imm0) = lisp_heap_gc_threshold;
+    break;
+
+  case GC_TRAP_FUNCTION_ENSURE_STATIC_CONSES:
+    ensure_static_conses(xp,tcr,32768);
+    break;
+
+  case GC_TRAP_FUNCTION_FLASH_FREEZE:
+    untenure_from_area(tenured_area);
+    gc_like_from_xp(xp,flash_freeze,0);
+    a->active = (BytePtr) align_to_power_of_2(a->active, log2_page_size);
+    tenured_area->static_dnodes = area_dnode(a->active, a->low);
+    if (egc_was_enabled) {
+      tenure_to_area(tenured_area);
+    }
+    xpGPR(xp, imm0) = tenured_area->static_dnodes << dnode_shift;
+    break;
+
+  default:
+    update_bytes_allocated(tcr, (void *) ptr_from_lispobj(xpGPR(xp, allocptr)));
+
+    if (selector == GC_TRAP_FUNCTION_IMMEDIATE_GC) {
+      if (!full_gc_deferred) {
+        gc_from_xp(xp, 0L);
+        break;
+      }
+      /* Tried to do a full GC when gc was disabled.  That failed,
+         so try full GC now */
+      selector = GC_TRAP_FUNCTION_GC;
+    }
+    
+    if (egc_was_enabled) {
+      egc_control(false, (BytePtr) a->active);
+    }
+    gc_from_xp(xp, 0L);
+    if (gc_deferred > gc_previously_deferred) {
+      full_gc_deferred = 1;
+    } else {
+      full_gc_deferred = 0;
+    }
+    if (selector > GC_TRAP_FUNCTION_GC) {
+      if (selector & GC_TRAP_FUNCTION_IMPURIFY) {
+        impurify_from_xp(xp, 0L);
+        /*        nrs_GC_EVENT_STATUS_BITS.vcell |= gc_integrity_check_bit; */
+        lisp_global(OLDSPACE_DNODE_COUNT) = 0;
+        gc_from_xp(xp, 0L);
+      }
+      if (selector & GC_TRAP_FUNCTION_PURIFY) {
+        purify_from_xp(xp, 0L);
+        lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(managed_static_area->active, managed_static_area->low);
+        gc_from_xp(xp, 0L);
+      }
+      if (selector & GC_TRAP_FUNCTION_SAVE_APPLICATION) {
+        OSErr err;
+        extern OSErr save_application(unsigned, Boolean);
+        TCR *tcr = TCR_FROM_TSD(xpGPR(xp, rcontext));
+        area *vsarea = tcr->vs_area;
+	
+        nrs_TOPLFUNC.vcell = *((LispObj *)(vsarea->high)-1);
+        err = save_application(arg, egc_was_enabled);
+        if (err == noErr) {
+          _exit(0);
+        }
+        fatal_oserr(": save_application", err);
+      }
+      switch (selector) {
+
+
+      case GC_TRAP_FUNCTION_FREEZE:
+        a->active = (BytePtr) align_to_power_of_2(a->active, log2_page_size);
+        tenured_area->static_dnodes = area_dnode(a->active, a->low);
+        xpGPR(xp, imm0) = tenured_area->static_dnodes << dnode_shift;
+        break;
+      default:
+        break;
+      }
+    }
+    
+    if (egc_was_enabled) {
+      egc_control(true, NULL);
+    }
+    break;
+    
+  }
+
+  adjust_exception_pc(xp,4);
+  return 0;
+}
+
+
+
+void
+signal_stack_soft_overflow(ExceptionInformation *xp, unsigned reg)
+{
+  /* The cstack just overflowed.  Force the current thread's
+     control stack to do so until all stacks are well under their overflow
+     limits. 
+  */
+
+#if 0
+  lisp_global(CS_OVERFLOW_LIMIT) = CS_OVERFLOW_FORCE_LIMIT; /* force unsigned traps to fail */
+#endif
+  handle_error(xp, error_stack_overflow, reg, 0,  xpPC(xp));
+}
+
+/*
+  Lower (move toward 0) the "end" of the soft protected area associated
+  with a by a page, if we can.
+*/
+
+void
+adjust_soft_protection_limit(area *a)
+{
+  char *proposed_new_soft_limit = a->softlimit - 4096;
+  protected_area_ptr p = a->softprot;
+  
+  if (proposed_new_soft_limit >= (p->start+16384)) {
+    p->end = proposed_new_soft_limit;
+    p->protsize = p->end-p->start;
+    a->softlimit = proposed_new_soft_limit;
+  }
+  protect_area(p);
+}
+
+void
+restore_soft_stack_limit(unsigned stkreg)
+{
+  area *a;
+  TCR *tcr = get_tcr(true);
+
+  switch (stkreg) {
+  case sp:
+    a = tcr->cs_area;
+    if ((a->softlimit - 4096) > (a->hardlimit + 16384)) {
+      a->softlimit -= 4096;
+    }
+    tcr->cs_limit = (LispObj)ptr_to_lispobj(a->softlimit);
+    break;
+  case vsp:
+    a = tcr->vs_area;
+    adjust_soft_protection_limit(a);
+    break;
+  case tsp:
+    a = tcr->ts_area;
+    adjust_soft_protection_limit(a);
+  }
+}
+
+/* Maybe this'll work someday.  We may have to do something to
+   make the thread look like it's not handling an exception */
+void
+reset_lisp_process(ExceptionInformation *xp)
+{
+  TCR *tcr = TCR_FROM_TSD(xpGPR(xp,rcontext));
+  catch_frame *last_catch = (catch_frame *) ptr_from_lispobj(untag(tcr->catch_top));
+
+  tcr->save_allocptr = (void *) ptr_from_lispobj(xpGPR(xp, allocptr));
+  tcr->save_allocbase = (void *) ptr_from_lispobj(xpGPR(xp, allocbase));
+
+  tcr->save_vsp = (LispObj *) ptr_from_lispobj(((lisp_frame *)ptr_from_lispobj(last_catch->csp))->savevsp);
+  tcr->save_tsp = (LispObj *) ptr_from_lispobj((LispObj) ptr_to_lispobj(last_catch)) - (2*node_size); /* account for TSP header */
+
+  start_lisp(tcr, 1);
+}
+
+/*
+  This doesn't GC; it returns true if it made enough room, false
+  otherwise.
+  If "extend" is true, it can try to extend the dynamic area to
+  satisfy the request.
+*/
+
+Boolean
+new_heap_segment(ExceptionInformation *xp, natural need, Boolean extend, TCR *tcr)
+{
+  area *a;
+  natural newlimit, oldlimit;
+  natural log2_allocation_quantum = tcr->log2_allocation_quantum;
+
+  a  = active_dynamic_area;
+  oldlimit = (natural) a->active;
+  newlimit = (align_to_power_of_2(oldlimit, log2_allocation_quantum) +
+	      align_to_power_of_2(need, log2_allocation_quantum));
+  if (newlimit > (natural) (a->high)) {
+    if (extend) {
+      signed_natural inhibit = (signed_natural)(lisp_global(GC_INHIBIT_COUNT));
+      natural extend_by = inhibit ? 0 : lisp_heap_gc_threshold;
+      do {
+        if (resize_dynamic_heap(a->active, (newlimit-oldlimit)+extend_by)) {
+          break;
+        }
+        extend_by = align_to_power_of_2(extend_by>>1, log2_allocation_quantum);
+        if (extend_by < 4<<20) {
+          return false;
+        }
+      } while (1);
+    } else {
+      return false;
+    }
+  }
+  a->active = (BytePtr) newlimit;
+  tcr->last_allocptr = (void *)newlimit;
+  xpGPR(xp,allocptr) = (LispObj) newlimit;
+  xpGPR(xp,allocbase) = (LispObj) oldlimit;
+
+  return true;
+}
+
+ 
+void
+update_area_active (area **aptr, BytePtr value)
+{
+  area *a = *aptr;
+  for (; a; a = a->older) {
+    if ((a->low <= value) && (a->high >= value)) break;
+  };
+  if (a == NULL) Bug(NULL, "Can't find active area");
+  a->active = value;
+  *aptr = a;
+
+  for (a = a->younger; a; a = a->younger) {
+    a->active = a->high;
+  }
+}
+
+LispObj *
+tcr_frame_ptr(TCR *tcr)
+{
+  ExceptionInformation *xp;
+  LispObj *bp = NULL;
+
+  if (tcr->pending_exception_context)
+    xp = tcr->pending_exception_context;
+  else {
+    xp = tcr->suspend_context;
+  }
+  if (xp) {
+    bp = (LispObj *) xpGPR(xp, sp);
+  }
+  return bp;
+}
+
+void
+normalize_tcr(ExceptionInformation *xp, TCR *tcr, Boolean is_other_tcr)
+{
+  void *cur_allocptr = NULL;
+  LispObj freeptr = 0;
+
+  if (xp) {
+    if (is_other_tcr) {
+      pc_luser_xp(xp, tcr, NULL);
+      freeptr = xpGPR(xp, allocptr);
+      if (fulltag_of(freeptr) == 0){
+	cur_allocptr = (void *) ptr_from_lispobj(freeptr);
+      }
+    }
+    update_area_active((area **)&tcr->cs_area, (BytePtr) ptr_from_lispobj(xpGPR(xp, sp)));
+    update_area_active((area **)&tcr->vs_area, (BytePtr) ptr_from_lispobj(xpGPR(xp, vsp)));
+    update_area_active((area **)&tcr->ts_area, (BytePtr) ptr_from_lispobj(xpGPR(xp, tsp)));
+#ifdef DEBUG
+    fprintf(dbgout, "TCR 0x%x in lisp code, vsp = 0x%lx, tsp = 0x%lx\n",
+            tcr, xpGPR(xp, vsp), xpGPR(xp, tsp));
+    fprintf(dbgout, "TCR 0x%x, allocbase/allocptr were 0x%x/0x%x at #x%x\n",
+            tcr,
+            xpGPR(xp, allocbase),
+            xpGPR(xp, allocptr),
+            xpPC(xp));
+    fprintf(dbgout, "TCR 0x%x, exception context = 0x%x\n",
+            tcr,
+            tcr->pending_exception_context);
+#endif
+  } else {
+    /* In ff-call.  No need to update cs_area */
+    cur_allocptr = (void *) (tcr->save_allocptr);
+#ifdef DEBUG
+    fprintf(dbgout, "TCR 0x%x in foreign code, vsp = 0x%lx, tsp = 0x%lx\n",
+            tcr, tcr->save_vsp, tcr->save_tsp);
+    fprintf(dbgout, "TCR 0x%x, save_allocbase/save_allocptr were 0x%x/0x%x at #x%x\n",
+            tcr,
+            tcr->save_allocbase,
+            tcr->save_allocptr,
+            xpPC(xp));
+
+#endif
+    update_area_active((area **)&tcr->vs_area, (BytePtr) tcr->save_vsp);
+    update_area_active((area **)&tcr->ts_area, (BytePtr) tcr->save_tsp);
+  }
+
+
+  tcr->save_allocptr = tcr->save_allocbase = (void *)VOID_ALLOCPTR;
+  if (cur_allocptr) {
+    update_bytes_allocated(tcr, cur_allocptr);
+    if (freeptr) {
+      xpGPR(xp, allocptr) = VOID_ALLOCPTR;
+      xpGPR(xp, allocbase) = VOID_ALLOCPTR;
+    }
+  }
+}
+
+TCR *gc_tcr = NULL;
+
+/* Suspend and "normalize" other tcrs, then call a gc-like function
+   in that context.  Resume the other tcrs, then return what the
+   function returned */
+
+signed_natural
+gc_like_from_xp(ExceptionInformation *xp, 
+                signed_natural(*fun)(TCR *, signed_natural), 
+                signed_natural param)
+{
+  TCR *tcr = TCR_FROM_TSD(xpGPR(xp, rcontext)), *other_tcr;
+  int result;
+  signed_natural inhibit;
+
+  suspend_other_threads(true);
+  inhibit = (signed_natural)(lisp_global(GC_INHIBIT_COUNT));
+  if (inhibit != 0) {
+    if (inhibit > 0) {
+      lisp_global(GC_INHIBIT_COUNT) = (LispObj)(-inhibit);
+    }
+    resume_other_threads(true);
+    gc_deferred++;
+    return 0;
+  }
+  gc_deferred = 0;
+
+  gc_tcr = tcr;
+
+  xpGPR(xp, allocptr) = VOID_ALLOCPTR;
+  xpGPR(xp, allocbase) = VOID_ALLOCPTR;
+
+  normalize_tcr(xp, tcr, false);
+
+
+  for (other_tcr = tcr->next; other_tcr != tcr; other_tcr = other_tcr->next) {
+    if (other_tcr->pending_exception_context) {
+      other_tcr->gc_context = other_tcr->pending_exception_context;
+    } else if (other_tcr->valence == TCR_STATE_LISP) {
+      other_tcr->gc_context = other_tcr->suspend_context;
+    } else {
+      /* no pending exception, didn't suspend in lisp state:
+	 must have executed a synchronous ff-call. 
+      */
+      other_tcr->gc_context = NULL;
+    }
+    normalize_tcr(other_tcr->gc_context, other_tcr, true);
+  }
+    
+
+
+  result = fun(tcr, param);
+
+  other_tcr = tcr;
+  do {
+    other_tcr->gc_context = NULL;
+    other_tcr = other_tcr->next;
+  } while (other_tcr != tcr);
+
+  gc_tcr = NULL;
+
+  resume_other_threads(true);
+
+  return result;
+
+}
+
+
+
+/* Returns #bytes freed by invoking GC */
+
+signed_natural
+gc_from_tcr(TCR *tcr, signed_natural param)
+{
+  area *a;
+  BytePtr oldfree, newfree;
+  BytePtr oldend, newend;
+
+#ifdef DEBUG
+  fprintf(dbgout, "Start GC  in 0x%lx\n", tcr);
+#endif
+  a = active_dynamic_area;
+  oldend = a->high;
+  oldfree = a->active;
+  gc(tcr, param);
+  newfree = a->active;
+  newend = a->high;
+#if 0
+  fprintf(dbgout, "End GC  in 0x%lx\n", tcr);
+#endif
+  return ((oldfree-newfree)+(newend-oldend));
+}
+
+signed_natural
+gc_from_xp(ExceptionInformation *xp, signed_natural param)
+{
+  signed_natural status = gc_like_from_xp(xp, gc_from_tcr, param);
+
+  freeGCptrs();
+  return status;
+}
+
+signed_natural
+purify_from_xp(ExceptionInformation *xp, signed_natural param)
+{
+  return gc_like_from_xp(xp, purify, param);
+}
+
+signed_natural
+impurify_from_xp(ExceptionInformation *xp, signed_natural param)
+{
+  return gc_like_from_xp(xp, impurify, param);
+}
+
+
+
+
+
+
+protection_handler
+ * protection_handlers[] = {
+   do_spurious_wp_fault,
+   do_soft_stack_overflow,
+   do_soft_stack_overflow,
+   do_soft_stack_overflow,
+   do_hard_stack_overflow,    
+   do_hard_stack_overflow,
+   do_hard_stack_overflow
+   };
+
+
+Boolean
+is_write_fault(ExceptionInformation *xp, siginfo_t *info)
+{
+  /* use the siginfo if it's available.  Some versions of Linux
+     don't propagate the DSISR and TRAP fields correctly from
+     64- to 32-bit handlers.
+  */
+  if (info) {
+    /* 
+       To confuse matters still further, the value of SEGV_ACCERR
+       varies quite a bit among LinuxPPC variants (the value defined
+       in the header files varies, and the value actually set by
+       the kernel also varies.  So far, we're only looking at the
+       siginfo under Linux and Linux always seems to generate
+       SIGSEGV, so check for SIGSEGV and check the low 16 bits
+       of the si_code.
+    */
+    return ((info->si_signo == SIGSEGV) &&
+	    ((info->si_code & 0xff) == (SEGV_ACCERR & 0xff)));
+  }
+  return(((xpDSISR(xp) & (1 << 25)) != 0) &&
+	 (xpTRAP(xp) == 
+#ifdef LINUX
+0x0300
+#endif
+#ifdef DARWIN
+0x0300/0x100
+#endif
+)
+	 );
+#if 0 
+  /* Maybe worth keeping around; not sure if it's an exhaustive
+     list of PPC instructions that could cause a WP fault */
+  /* Some OSes lose track of the DSISR and DSR SPRs, or don't provide
+     valid values of those SPRs in the context they provide to
+     exception handlers.  Look at the opcode of the offending
+     instruction & recognize 32-bit store operations */
+  opcode instr = *(xpPC(xp));
+
+  if (xp->regs->trap != 0x300) {
+    return 0;
+  }
+  switch (instr >> 26) {
+  case 47:			/* STMW */
+  case 36:			/* STW */
+  case 37:			/* STWU */
+    return 1;
+  case 31:
+    switch ((instr >> 1) & 1023) {
+    case 151:			/* STWX */
+    case 183:			/* STWUX */
+      return 1;
+    default:
+      return 0;
+    }
+  default:
+    return 0;
+  }
+#endif
+}
+
+OSStatus
+handle_protection_violation(ExceptionInformation *xp, siginfo_t *info, TCR *tcr, int old_valence)
+{
+  BytePtr addr;
+  protected_area_ptr area;
+  protection_handler *handler;
+  extern Boolean touch_page(void *);
+  extern void touch_page_end(void);
+
+  if (info) {
+    addr = (BytePtr)(info->si_addr);
+  } else {
+    addr = (BytePtr) ((natural) (xpDAR(xp)));
+  }
+
+  if (addr && (addr == tcr->safe_ref_address)) {
+    adjust_exception_pc(xp,4);
+
+    xpGPR(xp,imm0) = 0;
+    return 0;
+  }
+
+  if (xpPC(xp) == (pc)touch_page) {
+    xpGPR(xp,imm0) = 0;
+    xpPC(xp) = (pc)touch_page_end;
+    return 0;
+  }
+
+
+  if (is_write_fault(xp,info)) {
+    area = find_protected_area(addr);
+    if (area != NULL) {
+      handler = protection_handlers[area->why];
+      return handler(xp, area, addr);
+    } else {
+      if ((addr >= readonly_area->low) &&
+	  (addr < readonly_area->active)) {
+        UnProtectMemory((LogicalAddress)(truncate_to_power_of_2(addr,log2_page_size)),
+                        page_size);
+	return 0;
+      }
+    }
+  }
+  if (old_valence == TCR_STATE_LISP) {
+    callback_for_trap(nrs_CMAIN.vcell, xp, (pc)xpPC(xp), SIGBUS, (natural)addr, is_write_fault(xp,info));
+  }
+  return -1;
+}
+
+
+
+
+
+OSStatus
+do_hard_stack_overflow(ExceptionInformation *xp, protected_area_ptr area, BytePtr addr)
+{
+#ifdef SUPPORT_PRAGMA_UNUSED
+#pragma unused(area,addr)
+#endif
+  reset_lisp_process(xp);
+  return -1;
+}
+
+extern area*
+allocate_vstack(natural useable);       /* This is in "pmcl-kernel.c" */
+
+extern area*
+allocate_tstack(natural useable);       /* This is in "pmcl-kernel.c" */
+
+#ifdef EXTEND_VSTACK
+Boolean
+catch_frame_p(lisp_frame *spPtr)
+{
+  catch_frame* catch = (catch_frame *) untag(lisp_global(CATCH_TOP));
+
+  for (; catch; catch = (catch_frame *) untag(catch->link)) {
+    if (spPtr == ((lisp_frame *) catch->csp)) {
+      return true;
+    }
+  }
+  return false;
+}
+#endif
+
+Boolean
+unwind_protect_cleanup_frame_p(lisp_frame *spPtr)
+{
+  if ((spPtr->savevsp == (LispObj)NULL) ||  /* The frame to where the unwind-protect will return */
+      (((spPtr->backlink)->savevsp) == (LispObj)NULL)) {  /* The frame that returns to the kernel  from the cleanup form */
+    return true;
+  } else {
+    return false;
+  }
+}
+
+Boolean
+lexpr_entry_frame_p(lisp_frame *spPtr)
+{
+  LispObj savelr = spPtr->savelr;
+  LispObj lexpr_return = (LispObj) lisp_global(LEXPR_RETURN);
+  LispObj lexpr_return1v = (LispObj) lisp_global(LEXPR_RETURN1V);
+  LispObj ret1valn = (LispObj) lisp_global(RET1VALN);
+
+  return
+    (savelr == lexpr_return1v) ||
+    (savelr == lexpr_return) ||
+    ((savelr == ret1valn) &&
+     (((spPtr->backlink)->savelr) == lexpr_return));
+}
+
+Boolean
+lisp_frame_p(lisp_frame *spPtr)
+{
+  LispObj savefn;
+  /* We can't just look at the size of the stack frame under the EABI
+     calling sequence, but that's the first thing to check. */
+  if (((lisp_frame *) spPtr->backlink) != (spPtr+1)) {
+    return false;
+  }
+  savefn = spPtr->savefn;
+  return (savefn == 0) || (fulltag_of(savefn) == fulltag_misc);
+  
+}
+
+
+int ffcall_overflow_count = 0;
+
+/* Find a frame that is neither a catch frame nor one of the
+   lexpr_entry frames We don't check for non-lisp frames here because
+   we'll always stop before we get there due to a dummy lisp frame
+   pushed by .SPcallback that masks out the foreign frames.  The one
+   exception is that there is a non-lisp frame without a valid VSP
+   while in the process of ppc-ff-call. We recognize that because its
+   savelr is NIL.  If the saved VSP itself is 0 or the savevsp in the
+   next frame is 0, then we're executing an unwind-protect cleanup
+   form, and the top stack frame belongs to its (no longer extant)
+   catch frame.  */
+
+#ifdef EXTEND_VSTACK
+lisp_frame *
+find_non_catch_frame_from_xp (ExceptionInformation *xp)
+{
+  lisp_frame *spPtr = (lisp_frame *) xpGPR(xp, sp);
+  if ((((natural) spPtr) + sizeof(lisp_frame)) != ((natural) (spPtr->backlink))) {
+    ffcall_overflow_count++;          /* This is mostly so I can breakpoint here */
+  }
+  for (; !lisp_frame_p(spPtr)  || /* In the process of ppc-ff-call */
+         unwind_protect_cleanup_frame_p(spPtr) ||
+         catch_frame_p(spPtr) ||
+         lexpr_entry_frame_p(spPtr) ; ) {
+     spPtr = spPtr->backlink;
+     };
+  return spPtr;
+}
+#endif
+
+#ifdef EXTEND_VSTACK
+Boolean
+db_link_chain_in_area_p (area *a)
+{
+  LispObj *db = (LispObj *) lisp_global(DB_LINK),
+          *high = (LispObj *) a->high,
+          *low = (LispObj *) a->low;
+  for (; db; db = (LispObj *) *db) {
+    if ((db >= low) && (db < high)) return true;
+  };
+  return false;
+}
+#endif
+
+
+
+
+/* Note: CURRENT_VS (CURRENT_TS) is always either the area containing
+  the current value of VSP (TSP) or an older area.  */
+
+OSStatus
+do_vsp_overflow (ExceptionInformation *xp, BytePtr addr)
+{
+  TCR* tcr = TCR_FROM_TSD(xpGPR(xp, rcontext));
+  area *a = tcr->vs_area;
+  protected_area_ptr vsp_soft = a->softprot;
+  unprotect_area(vsp_soft);
+  signal_stack_soft_overflow(xp,vsp);
+  return 0;
+}
+
+
+OSStatus
+do_tsp_overflow (ExceptionInformation *xp, BytePtr addr)
+{
+  TCR* tcr = TCR_FROM_TSD(xpGPR(xp, rcontext));
+  area *a = tcr->ts_area;
+  protected_area_ptr tsp_soft = a->softprot;
+  unprotect_area(tsp_soft);
+  signal_stack_soft_overflow(xp,tsp);
+  return 0;
+}
+
+OSStatus
+do_soft_stack_overflow(ExceptionInformation *xp, protected_area_ptr prot_area, BytePtr addr)
+{
+  /* Trying to write into a guard page on the vstack or tstack.
+     Allocate a new stack segment, emulate stwu and stwux for the TSP, and
+     signal an error_stack_overflow condition.
+      */
+  lisp_protection_kind which = prot_area->why;
+  Boolean on_TSP = (which == kTSPsoftguard);
+
+  if (on_TSP) {
+    return do_tsp_overflow(xp, addr);
+   } else {
+    return do_vsp_overflow(xp, addr);
+   }
+}
+
+OSStatus
+do_spurious_wp_fault(ExceptionInformation *xp, protected_area_ptr area, BytePtr addr)
+{
+#ifdef SUPPORT_PRAGMA_UNUSED
+#pragma unused(xp,area,addr)
+#endif
+  return -1;
+}
+
+
+/*
+  We have a couple of choices here.  We can simply unprotect the page
+  and let the store happen on return, or we can try to emulate writes
+  that we know will involve an intergenerational reference.  Both are
+  correct as far as EGC constraints go, but the latter approach is
+  probably more efficient.  (This only matters in the case where the
+  GC runs after this exception handler returns but before the write
+  actually happens.  If we didn't emulate node stores here, the EGC
+  would scan the newly-writen page, find nothing interesting, and
+  run to completion.  This thread will try the write again afer it
+  resumes, the page'll be re-protected, and we'll have taken this
+  fault twice.  The whole scenario shouldn't happen very often, but
+  (having already taken a fault and committed to an mprotect syscall)
+  we might as well emulate stores involving intergenerational references,
+  since they're pretty easy to identify.
+
+  Note that cases involving two or more threads writing to the same
+  page (before either of them can run this handler) is benign: one
+  invocation of the handler will just unprotect an unprotected page in
+  that case.
+
+  If there are GCs (or any other suspensions of the thread between
+  the time that the write fault was detected and the time that the
+  exception lock is obtained) none of this stuff happens.
+*/
+
+/*
+  Return true (and emulate the instruction) iff:
+  a) the fault was caused by an "stw rs,d(ra)" or "stwx rs,ra.rb"
+     instruction.
+  b) RS is a node register (>= fn)
+  c) RS is tagged as a cons or vector
+  d) RS is in some ephemeral generation.
+  This is slightly conservative, since RS may be no younger than the
+  EA being written to.
+*/
+Boolean
+is_ephemeral_node_store(ExceptionInformation *xp, BytePtr ea)
+{
+  if (((ptr_to_lispobj(ea)) & 3) == 0) {
+    opcode instr = *xpPC(xp);
+    
+    if (X_opcode_p(instr,major_opcode_X31,minor_opcode_STWX) ||
+        major_opcode_p(instr, major_opcode_STW)) {
+      LispObj 
+        rs = RS_field(instr), 
+        rsval = xpGPR(xp,rs),
+        tag = fulltag_of(rsval);
+      
+      if (rs >= fn) {
+        if ((tag == fulltag_misc) || (tag == fulltag_cons)) {
+          if (((BytePtr)ptr_from_lispobj(rsval) > tenured_area->high) &&
+              ((BytePtr)ptr_from_lispobj(rsval) < active_dynamic_area->high)) {
+            *(LispObj *)ea = rsval;
+            return true;
+          }
+        }
+      }
+    }
+  }
+  return false;
+}
+
+      
+
+
+
+
+
+OSStatus
+handle_sigfpe(ExceptionInformation *xp, TCR *tcr)
+{
+  (void) zero_fpscr(tcr);
+  enable_fp_exceptions();
+
+
+  tcr->lisp_fpscr.words.l =  xpFPSCR(xp) & ~_FPU_RESERVED;
+
+  /* 'handle_fpux_binop' scans back from the specified PC until it finds an FPU
+     operation; there's an FPU operation right at the PC, so tell it to start
+     looking one word beyond */
+  return handle_fpux_binop(xp, (pc)((natural)(xpPC(xp))+4));
+}
+
+    
+int
+altivec_present = 1;
+
+
+/* This only tries to implement the "optional" fsqrt and fsqrts
+   instructions, which were generally implemented on IBM hardware
+   but generally not available on Motorola/Freescale systems.
+*/		  
+OSStatus
+handle_unimplemented_instruction(ExceptionInformation *xp,
+                                 opcode instruction,
+                                 TCR *tcr)
+{
+  (void) zero_fpscr(tcr);
+  enable_fp_exceptions();
+  /* the rc bit (bit 0 in the instruction) is supposed to cause
+     some FPSCR bits to be copied to CR1.  Clozure CL doesn't generate
+     fsqrt. or fsqrts.
+  */
+  if (((major_opcode_p(instruction,major_opcode_FPU_DOUBLE)) || 
+       (major_opcode_p(instruction,major_opcode_FPU_SINGLE))) &&
+      ((instruction & ((1 << 6) -2)) == (22<<1))) {
+    double b, d, sqrt(double);
+
+    b = xpFPR(xp,RB_field(instruction));
+    d = sqrt(b);
+    xpFPSCR(xp) = ((xpFPSCR(xp) & ~_FPU_RESERVED) |
+                   (get_fpscr() & _FPU_RESERVED));
+    xpFPR(xp,RT_field(instruction)) = d;
+    adjust_exception_pc(xp,4);
+    return 0;
+  }
+
+  return -1;
+}
+
+OSStatus
+PMCL_exception_handler(int xnum, 
+                       ExceptionInformation *xp, 
+                       TCR *tcr, 
+                       siginfo_t *info,
+                       int old_valence)
+{
+  OSStatus status = -1;
+  pc program_counter;
+  opcode instruction = 0;
+
+
+  program_counter = xpPC(xp);
+  
+  if ((xnum == SIGILL) | (xnum == SIGTRAP)) {
+    instruction = *program_counter;
+  }
+
+  if (instruction == ALLOC_TRAP_INSTRUCTION) {
+    status = handle_alloc_trap(xp, tcr);
+  } else if ((xnum == SIGSEGV) ||
+	     (xnum == SIGBUS)) {
+    status = handle_protection_violation(xp, info, tcr, old_valence);
+  } else if (xnum == SIGFPE) {
+    status = handle_sigfpe(xp, tcr);
+  } else if ((xnum == SIGILL) || (xnum == SIGTRAP)) {
+    if (instruction == GC_TRAP_INSTRUCTION) {
+      status = handle_gc_trap(xp, tcr);
+    } else if (IS_UUO(instruction)) {
+      status = handle_uuo(xp, instruction, program_counter);
+    } else if (is_conditional_trap(instruction)) {
+      status = handle_trap(xp, instruction, program_counter, info);
+    } else {
+      status = handle_unimplemented_instruction(xp,instruction,tcr);
+    }
+  } else if (xnum == SIGNAL_FOR_PROCESS_INTERRUPT) {
+    tcr->interrupt_pending = 0;
+    callback_for_trap(nrs_CMAIN.vcell, xp, 0, TRI_instruction(TO_GT,nargs,0),0, 0);
+    status = 0;
+  }
+
+  return status;
+}
+
+void
+adjust_exception_pc(ExceptionInformation *xp, int delta)
+{
+  xpPC(xp) += (delta >> 2);
+}
+
+
+/* 
+  This wants to scan backwards until "where" points to an instruction
+   whose major opcode is either 63 (double-float) or 59 (single-float)
+*/
+
+OSStatus
+handle_fpux_binop(ExceptionInformation *xp, pc where)
+{
+  OSStatus err;
+  opcode *there = (opcode *) where, instr, errnum = 0;
+  int i = TRAP_LOOKUP_TRIES, delta = 0;
+  
+  while (i--) {
+    instr = *--there;
+    delta -= 4;
+    if (codevec_hdr_p(instr)) {
+      return -1;
+    }
+    if (major_opcode_p(instr, major_opcode_FPU_DOUBLE)) {
+      errnum = error_FPU_exception_double;
+      break;
+    }
+
+    if (major_opcode_p(instr, major_opcode_FPU_SINGLE)) {
+      errnum = error_FPU_exception_short;
+      break;
+    }
+  }
+  
+  err = handle_error(xp, errnum, rcontext, 0,  there);
+  /* Yeah, we said "non-continuable".  In case we ever change that ... */
+  
+  adjust_exception_pc(xp, delta);
+  xpFPSCR(xp)  &=  0x03fff;
+  
+  return err;
+
+}
+
+OSStatus
+handle_uuo(ExceptionInformation *xp, opcode the_uuo, pc where) 
+{
+#ifdef SUPPORT_PRAGMA_UNUSED
+#pragma unused(where)
+#endif
+  unsigned 
+    minor = UUO_MINOR(the_uuo),
+    rb = 0x1f & (the_uuo >> 11),
+    errnum = 0x3ff & (the_uuo >> 16);
+
+  OSStatus status = -1;
+
+  int bump = 4;
+
+  switch (minor) {
+
+  case UUO_ZERO_FPSCR:
+    status = 0;
+    xpFPSCR(xp) = 0;
+    break;
+
+
+  case UUO_INTERR:
+    {
+      TCR * target = (TCR *)xpGPR(xp,arg_z);
+      status = 0;
+      switch (errnum) {
+      case error_propagate_suspend:
+	break;
+      case error_interrupt:
+	xpGPR(xp,imm0) = (LispObj) raise_thread_interrupt(target);
+	break;
+      case error_suspend:
+	xpGPR(xp,imm0) = (LispObj) lisp_suspend_tcr(target);
+	break;
+      case error_suspend_all:
+	lisp_suspend_other_threads();
+	break;
+      case error_resume:
+	xpGPR(xp,imm0) = (LispObj) lisp_resume_tcr(target);
+	break;
+      case error_resume_all:
+	lisp_resume_other_threads();
+	break;
+      case error_kill:
+	xpGPR(xp,imm0) = (LispObj)kill_tcr(target);
+	break;
+      case error_allocate_list:
+        allocate_list(xp,get_tcr(true));
+        break;
+      default:
+	status = handle_error(xp, errnum, rb, 0,  where);
+	break;
+      }
+    }
+    break;
+
+  case UUO_INTCERR:
+    status = handle_error(xp, errnum, rb, 1,  where);
+    if (errnum == error_udf_call) {
+      /* If lisp's returned from a continuable undefined-function call,
+	 it's put a code vector in the xp's PC.  Don't advance the
+	 PC ... */
+      bump = 0;
+    }
+    break;
+
+  case UUO_FPUX_BINOP:
+    status = handle_fpux_binop(xp, where);
+    bump = 0;
+    break;
+
+  default:
+    status = -1;
+    bump = 0;
+  }
+  
+  if ((!status) && bump) {
+    adjust_exception_pc(xp, bump);
+  }
+  return status;
+}
+
+natural
+register_codevector_contains_pc (natural lisp_function, pc where)
+{
+  natural code_vector, size;
+
+  if ((fulltag_of(lisp_function) == fulltag_misc) &&
+      (header_subtag(header_of(lisp_function)) == subtag_function)) {
+    code_vector = deref(lisp_function, 1);
+    size = header_element_count(header_of(code_vector)) << 2;
+    if ((untag(code_vector) < (natural)where) && 
+	((natural)where < (code_vector + size)))
+      return(code_vector);
+  }
+
+  return(0);
+}
+
+/* Callback to lisp to handle a trap. Need to translate the
+   PC (where) into one of two forms of pairs:
+
+   1. If PC is in fn or nfn's code vector, use the register number
+      of fn or nfn and the index into that function's code vector.
+   2. Otherwise use 0 and the pc itself
+*/
+void
+callback_for_trap (LispObj callback_macptr, ExceptionInformation *xp, pc where,
+                   natural arg1, natural arg2, natural arg3)
+{
+  natural code_vector = register_codevector_contains_pc(xpGPR(xp, fn), where);
+  unsigned register_number = fn;
+  natural index = (natural)where;
+
+  if (code_vector == 0) {
+    register_number = nfn;
+    code_vector = register_codevector_contains_pc(xpGPR(xp, nfn), where);
+  }
+  if (code_vector == 0)
+    register_number = 0;
+  else
+    index = ((natural)where - (code_vector + misc_data_offset)) >> 2;
+  callback_to_lisp(callback_macptr, xp, register_number, index, arg1, arg2, arg3);
+}
+
+void
+callback_to_lisp (LispObj callback_macptr, ExceptionInformation *xp,
+                  natural arg1, natural arg2, natural arg3, natural arg4, natural arg5)
+{
+  natural  callback_ptr;
+  area *a;
+
+  TCR *tcr = TCR_FROM_TSD(xpGPR(xp, rcontext));
+
+  /* Put the active stack pointer where .SPcallback expects it */
+  a = tcr->cs_area;
+  a->active = (BytePtr) ptr_from_lispobj(xpGPR(xp, sp));
+
+  /* Copy globals from the exception frame to tcr */
+  tcr->save_allocptr = (void *)ptr_from_lispobj(xpGPR(xp, allocptr));
+  tcr->save_allocbase = (void *)ptr_from_lispobj(xpGPR(xp, allocbase));
+  tcr->save_vsp = (LispObj*) ptr_from_lispobj(xpGPR(xp, vsp));
+  tcr->save_tsp = (LispObj*) ptr_from_lispobj(xpGPR(xp, tsp));
+
+
+
+  /* Call back.
+     Lisp will handle trampolining through some code that
+     will push lr/fn & pc/nfn stack frames for backtrace.
+  */
+  callback_ptr = ((macptr *)ptr_from_lispobj(untag(callback_macptr)))->address;
+#ifdef DEBUG
+  fprintf(dbgout, "0x%x releasing exception lock for callback\n", tcr);
+#endif
+  UNLOCK(lisp_global(EXCEPTION_LOCK), tcr);
+  ((void (*)())callback_ptr) (xp, arg1, arg2, arg3, arg4, arg5);
+  LOCK(lisp_global(EXCEPTION_LOCK), tcr);
+#ifdef DEBUG
+  fprintf(dbgout, "0x%x acquired exception lock after callback\n", tcr);
+#endif
+
+
+
+  /* Copy GC registers back into exception frame */
+  xpGPR(xp, allocbase) = (LispObj) ptr_to_lispobj(tcr->save_allocbase);
+  xpGPR(xp, allocptr) = (LispObj) ptr_to_lispobj(tcr->save_allocptr);
+}
+
+area *
+allocate_no_stack (natural size)
+{
+#ifdef SUPPORT_PRAGMA_UNUSED
+#pragma unused(size)
+#endif
+
+  return (area *) NULL;
+}
+
+
+
+
+
+
+/* callback to (symbol-value cmain) if it is a macptr, 
+   otherwise report cause and function name to console.
+   Returns noErr if exception handled OK */
+OSStatus
+handle_trap(ExceptionInformation *xp, opcode the_trap, pc where, siginfo_t *info)
+{
+  LispObj   cmain = nrs_CMAIN.vcell;
+  TCR *tcr = TCR_FROM_TSD(xpGPR(xp, rcontext));
+
+  /* If we got here, "the_trap" is either a TRI or a TR instruction.
+     It's a TRI instruction iff its major opcode is major_opcode_TRI. */
+
+  /* If it's a "trllt" instruction where RA == sp, it's a failed 
+     control stack overflow check.  In that case:
+     
+     a) We're in "yellow zone" mode if the value of the
+     lisp_global(CS_OVERFLOW_LIMIT) is CS_OVERFLOW_FORCE_LIMIT.  If
+     we're not already in yellow zone mode, attempt to create a new
+     thread and continue execution on its stack. If that fails, call
+     signal_stack_soft_overflow to enter yellow zone mode and signal
+     the condition to lisp.
+     
+     b) If we're already in "yellow zone" mode, then:
+     
+     1) if the SP is past the current control-stack area's hard
+     overflow limit, signal a "hard" stack overflow error (e.g., throw
+     to toplevel as quickly as possible. If we aren't in "yellow zone"
+     mode, attempt to continue on another thread first.
+     
+     2) if SP is "well" (> 4K) below its soft overflow limit, set
+     lisp_global(CS_OVERFLOW_LIMIT) to its "real" value.  We're out of
+     "yellow zone mode" in this case.
+     
+     3) Otherwise, do nothing.  We'll continue to trap every time
+     something gets pushed on the control stack, so we should try to
+     detect and handle all of these cases fairly quickly.  Of course,
+     the trap overhead is going to slow things down quite a bit.
+     */
+
+  if (X_opcode_p(the_trap,major_opcode_X31,minor_opcode_TR) &&
+      (RA_field(the_trap) == sp) &&
+      (TO_field(the_trap) == TO_LO)) {
+    area 
+      *CS_area = tcr->cs_area,
+      *VS_area = tcr->vs_area;
+      
+    natural 
+      current_SP = xpGPR(xp,sp),
+      current_VSP = xpGPR(xp,vsp);
+
+    if (current_SP  < (natural) (CS_area->hardlimit)) {
+      /* If we're not in soft overflow mode yet, assume that the
+         user has set the soft overflow size very small and try to
+         continue on another thread before throwing to toplevel */
+      if ((tcr->cs_limit == CS_OVERFLOW_FORCE_LIMIT)) {
+        reset_lisp_process(xp);
+      }
+    } else {
+      if (tcr->cs_limit == CS_OVERFLOW_FORCE_LIMIT) {
+        /* If the control stack pointer is at least 4K away from its soft limit
+	   and the value stack pointer is at least 4K away from its soft limit,
+           stop trapping.  Else keep trapping. */
+        if ((current_SP > (natural) ((CS_area->softlimit)+4096)) &&
+	    (current_VSP > (natural) ((VS_area->softlimit)+4096))) {
+	  protected_area_ptr vs_soft = VS_area->softprot;
+	  if (vs_soft->nprot == 0) {
+	    protect_area(vs_soft);
+	  }
+          tcr->cs_limit = ptr_to_lispobj(CS_area->softlimit);
+        }
+      } else {
+	tcr->cs_limit = ptr_to_lispobj(CS_area->hardlimit);	  
+	signal_stack_soft_overflow(xp, sp);
+      }
+    }
+    
+    adjust_exception_pc(xp, 4);
+    return noErr;
+  } else {
+    if (the_trap == LISP_BREAK_INSTRUCTION) {
+      char *message =  (char *) ptr_from_lispobj(xpGPR(xp,3));
+      set_xpPC(xp, xpLR(xp));
+      if (message == NULL) {
+	message = "Lisp Breakpoint";
+      }
+      lisp_Debugger(xp, info, debug_entry_dbg, false, message);
+      return noErr;
+    }
+    if (the_trap == QUIET_LISP_BREAK_INSTRUCTION) {
+      adjust_exception_pc(xp,4);
+      lisp_Debugger(xp, info, debug_entry_dbg, false, "Lisp Breakpoint");
+      return noErr;
+    }
+    /*
+      twlle ra,rb is used to detect tlb overflow, where RA = current
+      limit and RB = index to use.
+    */
+    if ((X_opcode_p(the_trap, 31, minor_opcode_TR)) && 
+        (TO_field(the_trap) == (TO_LO|TO_EQ))) {
+      if (extend_tcr_tlb(tcr, xp, RA_field(the_trap), RB_field(the_trap))) {
+        return noErr;
+      }
+      return -1;
+    }
+
+    if ((fulltag_of(cmain) == fulltag_misc) &&
+        (header_subtag(header_of(cmain)) == subtag_macptr)) {
+      if (the_trap == TRI_instruction(TO_GT,nargs,0)) {
+        /* reset interrup_level, interrupt_pending */
+        TCR_INTERRUPT_LEVEL(tcr) = 0;
+        tcr->interrupt_pending = 0;
+      }
+#if 0
+      fprintf(dbgout, "About to do trap callback in 0x%x\n",tcr);
+#endif
+      callback_for_trap(cmain, xp,  where, (natural) the_trap,  0, 0);
+      adjust_exception_pc(xp, 4);
+      return(noErr);
+    }
+    return -1;
+  }
+}
+
+
+/* Look at up to TRAP_LOOKUP_TRIES instrs before trap instr for a pattern.
+   Stop if subtag_code_vector is encountered. */
+unsigned
+scan_for_instr( unsigned target, unsigned mask, pc where )
+{
+  int i = TRAP_LOOKUP_TRIES;
+
+  while( i-- ) {
+    unsigned instr = *(--where);
+    if ( codevec_hdr_p(instr) ) {
+      return 0;
+    } else if ( match_instr(instr, mask, target) ) {
+      return instr;
+    }
+  }
+  return 0;
+}
+
+
+void non_fatal_error( char *msg )
+{
+  fprintf( dbgout, "Non-fatal error: %s.\n", msg );
+  fflush( dbgout );
+}
+
+/* The main opcode.  */
+
+int 
+is_conditional_trap(opcode instr)
+{
+  unsigned to = TO_field(instr);
+  int is_tr = X_opcode_p(instr,major_opcode_X31,minor_opcode_TR);
+
+#ifndef MACOS
+  if ((instr == LISP_BREAK_INSTRUCTION) ||
+      (instr == QUIET_LISP_BREAK_INSTRUCTION)) {
+    return 1;
+  }
+#endif
+  if (is_tr || major_opcode_p(instr,major_opcode_TRI)) {
+    /* A "tw/td" or "twi/tdi" instruction.  To be unconditional, the
+       EQ bit must be set in the TO mask and either the register
+       operands (if "tw") are the same or either both of the signed or
+       both of the unsigned inequality bits must be set. */
+    if (! (to & TO_EQ)) {
+      return 1;			/* Won't trap on EQ: conditional */
+    }
+    if (is_tr && (RA_field(instr) == RB_field(instr))) {
+      return 0;			/* Will trap on EQ, same regs: unconditional */
+    }
+    if (((to & (TO_LO|TO_HI)) == (TO_LO|TO_HI)) || 
+	((to & (TO_LT|TO_GT)) == (TO_LT|TO_GT))) {
+      return 0;			/* Will trap on EQ and either (LT|GT) or (LO|HI) : unconditional */
+    }
+    return 1;			/* must be conditional */
+  }
+  return 0;			/* Not "tw/td" or "twi/tdi".  Let
+                                   debugger have it */
+}
+
+OSStatus
+handle_error(ExceptionInformation *xp, unsigned errnum, unsigned rb, unsigned continuable, pc where)
+{
+  LispObj   errdisp = nrs_ERRDISP.vcell;
+
+  if ((fulltag_of(errdisp) == fulltag_misc) &&
+      (header_subtag(header_of(errdisp)) == subtag_macptr)) {
+    /* errdisp is a macptr, we can call back to lisp */
+    callback_for_trap(errdisp, xp, where, errnum, rb, continuable);
+    return(0);
+    }
+
+  return(-1);
+}
+	       
+
+/* 
+   Current thread has all signals masked.  Before unmasking them,
+   make it appear that the current thread has been suspended.
+   (This is to handle the case where another thread is trying
+   to GC before this thread is able to sieze the exception lock.)
+*/
+int
+prepare_to_wait_for_exception_lock(TCR *tcr, ExceptionInformation *context)
+{
+  int old_valence = tcr->valence;
+
+  tcr->pending_exception_context = context;
+  tcr->valence = TCR_STATE_EXCEPTION_WAIT;
+
+  ALLOW_EXCEPTIONS(context);
+  return old_valence;
+}  
+
+void
+wait_for_exception_lock_in_handler(TCR *tcr, 
+				   ExceptionInformation *context,
+				   xframe_list *xf)
+{
+
+  LOCK(lisp_global(EXCEPTION_LOCK), tcr);
+#ifdef DEBUG
+  fprintf(dbgout, "0x%x has exception lock\n", tcr);
+#endif
+  xf->curr = context;
+  xf->prev = tcr->xframe;
+  tcr->xframe =  xf;
+  tcr->pending_exception_context = NULL;
+  tcr->valence = TCR_STATE_FOREIGN; 
+}
+
+void
+unlock_exception_lock_in_handler(TCR *tcr)
+{
+  tcr->pending_exception_context = tcr->xframe->curr;
+  tcr->xframe = tcr->xframe->prev;
+  tcr->valence = TCR_STATE_EXCEPTION_RETURN;
+#ifdef DEBUG
+  fprintf(dbgout, "0x%x releasing exception lock\n", tcr);
+#endif
+  UNLOCK(lisp_global(EXCEPTION_LOCK),tcr);
+}
+
+/* 
+   If an interrupt is pending on exception exit, try to ensure
+   that the thread sees it as soon as it's able to run.
+*/
+void
+raise_pending_interrupt(TCR *tcr)
+{
+  if (TCR_INTERRUPT_LEVEL(tcr) > 0) {
+    pthread_kill((pthread_t)ptr_from_lispobj(tcr->osid), SIGNAL_FOR_PROCESS_INTERRUPT);
+  }
+}
+
+void
+exit_signal_handler(TCR *tcr, int old_valence)
+{
+  sigset_t mask;
+  sigfillset(&mask);
+  
+  pthread_sigmask(SIG_SETMASK,&mask, NULL);
+  tcr->valence = old_valence;
+  tcr->pending_exception_context = NULL;
+}
+
+
+void
+signal_handler(int signum, siginfo_t *info, ExceptionInformation  *context, TCR *tcr, int old_valence)
+{
+  xframe_list xframe_link;
+
+  if (!use_mach_exception_handling) {
+    
+    tcr = (TCR *) get_interrupt_tcr(false);
+  
+    /* The signal handler's entered with all signals (notably the
+       thread_suspend signal) blocked.  Don't allow any other signals
+       (notably the thread_suspend signal) to preempt us until we've
+       set the TCR's xframe slot to include the current exception
+       context.
+    */
+    
+    old_valence = prepare_to_wait_for_exception_lock(tcr, context);
+  }
+
+  if (tcr->flags & (1<<TCR_FLAG_BIT_PENDING_SUSPEND)) {
+    CLR_TCR_FLAG(tcr, TCR_FLAG_BIT_PENDING_SUSPEND);
+    pthread_kill(pthread_self(), thread_suspend_signal);
+  }
+
+  
+  wait_for_exception_lock_in_handler(tcr, context, &xframe_link);
+  if ((noErr != PMCL_exception_handler(signum, context, tcr, info, old_valence))) {
+    char msg[512];
+    snprintf(msg, sizeof(msg), "Unhandled exception %d at 0x%lx, context->regs at #x%lx", signum, xpPC(context), (natural)xpGPRvector(context));
+    if (lisp_Debugger(context, info, signum, false, msg)) {
+      SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PROPAGATE_EXCEPTION);
+    }
+  }
+
+  unlock_exception_lock_in_handler(tcr);
+
+  /* This thread now looks like a thread that was suspended while
+     executing lisp code.  If some other thread gets the exception
+     lock and GCs, the context (this thread's suspend_context) will
+     be updated.  (That's only of concern if it happens before we
+     can return to the kernel/to the Mach exception handler).
+  */
+  if (!use_mach_exception_handling) {
+    exit_signal_handler(tcr, old_valence);
+    raise_pending_interrupt(tcr);
+  }
+}
+
+/*
+  If it looks like we're in the middle of an atomic operation, make
+  it seem as if that operation is either complete or hasn't started
+  yet.
+
+  The cases handled include:
+
+  a) storing into a newly-allocated lisp frame on the stack.
+  b) marking a newly-allocated TSP frame as containing "raw" data.
+  c) consing: the GC has its own ideas about how this should be
+     handled, but other callers would be best advised to back
+     up or move forward, according to whether we're in the middle
+     of allocating a cons cell or allocating a uvector.
+  d) a STMW to the vsp
+  e) EGC write-barrier subprims.
+*/
+
+extern opcode
+  egc_write_barrier_start,
+  egc_write_barrier_end, 
+  egc_store_node_conditional, 
+  egc_store_node_conditional_test,
+  egc_set_hash_key,
+  egc_gvset,
+  egc_rplaca,
+  egc_rplacd,
+  egc_set_hash_key_conditional,
+  egc_set_hash_key_conditional_test;
+
+
+extern opcode ffcall_return_window, ffcall_return_window_end;
+
+void
+pc_luser_xp(ExceptionInformation *xp, TCR *tcr, signed_natural *alloc_disp)
+{
+  pc program_counter = xpPC(xp);
+  opcode instr = *program_counter;
+  lisp_frame *frame = (lisp_frame *)ptr_from_lispobj(xpGPR(xp,sp));
+  LispObj cur_allocptr = xpGPR(xp, allocptr);
+  int allocptr_tag = fulltag_of(cur_allocptr);
+  
+
+
+  if ((program_counter < &egc_write_barrier_end) && 
+      (program_counter >= &egc_write_barrier_start)) {
+    LispObj *ea = 0, val = 0, root = 0;
+    bitvector refbits = (bitvector)(lisp_global(REFBITS));
+    Boolean need_store = true, need_check_memo = true, need_memoize_root = false;
+
+    if (program_counter >= &egc_set_hash_key_conditional) {
+      if ((program_counter < &egc_set_hash_key_conditional_test) ||
+	  ((program_counter == &egc_set_hash_key_conditional_test) &&
+	   (! (xpCCR(xp) & 0x20000000)))) {
+	return;
+      }
+      need_store = false;
+      root = xpGPR(xp,arg_x);
+      ea = (LispObj *) (root+xpGPR(xp,arg_y)+misc_data_offset);
+      need_memoize_root = true;
+    } else if (program_counter >= &egc_store_node_conditional) {
+      if ((program_counter < &egc_store_node_conditional_test) ||
+	  ((program_counter == &egc_store_node_conditional_test) &&
+	   (! (xpCCR(xp) & 0x20000000)))) {
+	/* The conditional store either hasn't been attempted yet, or
+	   has failed.  No need to adjust the PC, or do memoization. */
+	return;
+      }
+      ea = (LispObj*)(xpGPR(xp,arg_x) + xpGPR(xp,imm4));
+      xpGPR(xp,arg_z) = t_value;
+      need_store = false;
+    } else if (program_counter >= &egc_set_hash_key) {
+      root = xpGPR(xp,arg_x);
+      val = xpGPR(xp,arg_z);
+      ea = (LispObj *) (root+xpGPR(xp,arg_y)+misc_data_offset);
+      need_memoize_root = true;
+    } else if (program_counter >= &egc_gvset) {
+      ea = (LispObj *) (xpGPR(xp,arg_x)+xpGPR(xp,arg_y)+misc_data_offset);
+      val = xpGPR(xp,arg_z);
+    } else if (program_counter >= &egc_rplacd) {
+      ea = (LispObj *) untag(xpGPR(xp,arg_y));
+      val = xpGPR(xp,arg_z);
+    } else {                      /* egc_rplaca */
+      ea =  ((LispObj *) untag(xpGPR(xp,arg_y)))+1;
+      val = xpGPR(xp,arg_z);
+    }
+    if (need_store) {
+      *ea = val;
+    }
+    if (need_check_memo) {
+      natural  bitnumber = area_dnode(ea, lisp_global(REF_BASE));
+      if ((bitnumber < lisp_global(OLDSPACE_DNODE_COUNT)) &&
+          ((LispObj)ea < val)) {
+        atomic_set_bit(refbits, bitnumber);
+        if (need_memoize_root) {
+          bitnumber = area_dnode(root, lisp_global(REF_BASE));
+          atomic_set_bit(refbits, bitnumber);
+        }
+      }
+    }
+    set_xpPC(xp, xpLR(xp));
+    return;
+  }
+
+
+  if (instr == MARK_TSP_FRAME_INSTRUCTION) {
+    LispObj tsp_val = xpGPR(xp,tsp);
+    
+    ((LispObj *)ptr_from_lispobj(tsp_val))[1] = tsp_val;
+    adjust_exception_pc(xp, 4);
+    return;
+  }
+  
+  if (frame->backlink == (frame+1)) {
+    if (
+#ifdef PPC64
+        (major_opcode_p(instr, major_opcode_DS_STORE64)) &&
+        (DS_VARIANT_FIELD(instr) == DS_STORE64_VARIANT_STD) &&
+#else
+        (major_opcode_p(instr, major_opcode_STW)) && 
+#endif
+	(RA_field(instr) == sp) &&
+	/* There are a few places in the runtime that store into
+	   a previously-allocated frame atop the stack when
+	   throwing values around.  We only care about the case
+	   where the frame was newly allocated, in which case
+	   there must have been a CREATE_LISP_FRAME_INSTRUCTION
+	   a few instructions before the current program counter.
+	   (The whole point here is that a newly allocated frame
+	   might contain random values that we don't want the
+	   GC to see; a previously allocated frame should already
+	   be completely initialized.)
+	*/
+	((program_counter[-1] == CREATE_LISP_FRAME_INSTRUCTION) ||
+	 (program_counter[-2] == CREATE_LISP_FRAME_INSTRUCTION) ||
+	 (program_counter[-3] == CREATE_LISP_FRAME_INSTRUCTION)))  {
+#ifdef PPC64
+      int disp = DS_field(instr);
+#else      
+      int disp = D_field(instr);
+#endif
+
+
+      if (disp < (4*node_size)) {
+#if 0
+        fprintf(dbgout, "pc-luser: finish SP frame in 0x%x, disp = %d\n",tcr, disp);
+#endif
+	frame->savevsp = 0;
+	if (disp < (3*node_size)) {
+	  frame->savelr = 0;
+	  if (disp == node_size) {
+	    frame->savefn = 0;
+	  }
+	}
+      }
+      return;
+    }
+  }
+
+  if (allocptr_tag != tag_fixnum) {
+    signed_natural disp = allocptr_displacement(xp);
+
+    if (disp) {
+      /* Being architecturally "at" the alloc trap doesn't tell
+         us much (in particular, it doesn't tell us whether
+         or not the thread has committed to taking the trap
+         and is waiting for the exception lock (or waiting
+         for the Mach exception thread to tell it how bad
+         things are) or is about to execute a conditional
+         trap.
+         Regardless of which case applies, we want the
+         other thread to take (or finish taking) the
+         trap, and we don't want it to consider its
+         current allocptr to be valid.
+         The difference between this case (suspend other
+         thread for GC) and the previous case (suspend
+         current thread for interrupt) is solely a
+         matter of what happens after we leave this
+         function: some non-current thread will stay
+         suspended until the GC finishes, then take
+         (or start processing) the alloc trap.   The
+         current thread will go off and do PROCESS-INTERRUPT
+         or something, and may return from the interrupt
+         and need to finish the allocation that got interrupted.
+      */
+
+      if (alloc_disp) {
+        *alloc_disp = disp;
+        xpGPR(xp,allocptr) += disp;
+        /* Leave the PC at the alloc trap.  When the interrupt
+           handler returns, it'll decrement allocptr by disp
+           and the trap may or may not be taken.
+        */
+      } else {
+        update_bytes_allocated(tcr, (void *) ptr_from_lispobj(cur_allocptr + disp));
+        xpGPR(xp, allocbase) = VOID_ALLOCPTR;
+        xpGPR(xp, allocptr) = VOID_ALLOCPTR - disp;
+      }
+    } else {
+#ifdef DEBUG
+      fprintf(dbgout, "tcr 0x%x is past alloc trap, finishing alloc at 0x%x\n", tcr, xpGPR(xp,allocptr));
+#endif
+      /* If we're already past the alloc_trap, finish allocating
+         the object. */
+      if (allocptr_tag == fulltag_cons) {
+        finish_allocating_cons(xp);
+#ifdef DEBUG
+          fprintf(dbgout, "finish allocating cons in TCR = #x%x\n",
+                  tcr);
+#endif
+      } else {
+        if (allocptr_tag == fulltag_misc) {
+#ifdef DEBUG
+          fprintf(dbgout, "finish allocating uvector in TCR = #x%x\n",
+                  tcr);
+#endif
+          finish_allocating_uvector(xp);
+        } else {
+          Bug(xp, "what's being allocated here ?");
+        }
+      }
+      /* Whatever we finished allocating, reset allocptr/allocbase to
+         VOID_ALLOCPTR */
+      xpGPR(xp,allocptr) = xpGPR(xp,allocbase) = VOID_ALLOCPTR;
+    }
+    return;
+  }
+
+  if ((instr & INIT_CATCH_FRAME_MASK) == INIT_CATCH_FRAME_INSTRUCTION) {
+    LispObj *frame = ptr_from_lispobj(untag(xpGPR(xp, nargs)));
+    int idx = ((int)((short)(D_field(instr))+fulltag_misc))>>fixnumshift;
+#if 0
+        fprintf(dbgout, "pc-luser: CATCH frame in 0x%x, idx = %d\n",tcr, idx);
+#endif
+
+    for (;idx < sizeof(catch_frame)/sizeof(LispObj); idx++) {
+      deref(frame,idx) = 0;
+    }
+    ((LispObj *)(xpGPR(xp, tsp)))[1] = 0;
+    return;
+  }
+
+#ifndef PC64
+  if ((major_opcode_p(instr, 47)) && /* 47 = stmw */
+      (RA_field(instr) == vsp)) {
+    int r;
+    LispObj *vspptr = ptr_from_lispobj(xpGPR(xp,vsp));
+    
+    for (r = RS_field(instr); r <= 31; r++) {
+      *vspptr++ = xpGPR(xp,r);
+    }
+    adjust_exception_pc(xp, 4);
+  }
+#endif
+}
+
+void
+interrupt_handler (int signum, siginfo_t *info, ExceptionInformation *context)
+{
+  TCR *tcr = get_interrupt_tcr(false);
+  if (tcr) {
+    if (TCR_INTERRUPT_LEVEL(tcr) < 0) {
+      tcr->interrupt_pending = 1 << fixnumshift;
+    } else {
+      LispObj cmain = nrs_CMAIN.vcell;
+
+      if ((fulltag_of(cmain) == fulltag_misc) &&
+	  (header_subtag(header_of(cmain)) == subtag_macptr)) {
+	/* 
+	   This thread can (allegedly) take an interrupt now.
+	   It's tricky to do that if we're executing
+	   foreign code (especially Linuxthreads code, much
+	   of which isn't reentrant.)
+           If we're unwinding the stack, we also want to defer
+           the interrupt.
+	*/
+	if ((tcr->valence != TCR_STATE_LISP) ||
+            (tcr->unwinding != 0)) {
+	  TCR_INTERRUPT_LEVEL(tcr) = (1 << fixnumshift);
+	} else {
+	  xframe_list xframe_link;
+	  int old_valence;
+          signed_natural disp=0;
+	  
+	  pc_luser_xp(context, tcr, &disp);
+	  old_valence = prepare_to_wait_for_exception_lock(tcr, context);
+	  wait_for_exception_lock_in_handler(tcr, context, &xframe_link);
+#ifdef DEBUG
+          fprintf(dbgout, "[0x%x acquired exception lock for interrupt]\n",tcr);
+#endif
+	  PMCL_exception_handler(signum, context, tcr, info, old_valence);
+          if (disp) {
+            xpGPR(context,allocptr) -= disp;
+          }
+	  unlock_exception_lock_in_handler(tcr);
+#ifdef DEBUG
+          fprintf(dbgout, "[0x%x released exception lock for interrupt]\n",tcr);
+#endif
+	  exit_signal_handler(tcr, old_valence);
+	}
+      }
+    }
+  }
+#ifdef DARWIN
+    DarwinSigReturn(context);
+#endif
+}
+
+
+
+void
+install_signal_handler(int signo, void *handler)
+{
+  struct sigaction sa;
+  
+  sa.sa_sigaction = (void *)handler;
+  sigfillset(&sa.sa_mask);
+  sa.sa_flags = 
+    0 /* SA_RESTART */
+    | SA_SIGINFO
+#ifdef DARWIN
+#ifdef PPC64
+    | SA_64REGSET
+#endif
+#endif
+    ;
+
+  sigaction(signo, &sa, NULL);
+}
+
+void
+install_pmcl_exception_handlers()
+{
+#ifdef DARWIN
+  extern Boolean use_mach_exception_handling;
+#endif
+
+  Boolean install_signal_handlers_for_exceptions =
+#ifdef DARWIN
+    !use_mach_exception_handling
+#else
+    true
+#endif
+    ;
+  if (install_signal_handlers_for_exceptions) {
+    extern int no_sigtrap;
+    install_signal_handler(SIGILL, (void *)signal_handler);
+    if (no_sigtrap != 1) {
+      install_signal_handler(SIGTRAP, (void *)signal_handler);
+    }
+    install_signal_handler(SIGBUS,  (void *)signal_handler);
+    install_signal_handler(SIGSEGV, (void *)signal_handler);
+    install_signal_handler(SIGFPE, (void *)signal_handler);
+  }
+  
+  install_signal_handler(SIGNAL_FOR_PROCESS_INTERRUPT,
+			 (void *)interrupt_handler);
+  signal(SIGPIPE, SIG_IGN);
+}
+
+void
+thread_kill_handler(int signum, siginfo_t info, ExceptionInformation *xp)
+{
+  TCR *tcr = get_tcr(false);
+  area *a;
+  sigset_t mask;
+  
+  sigemptyset(&mask);
+
+  if (tcr) {
+    tcr->valence = TCR_STATE_FOREIGN;
+    a = tcr->vs_area;
+    if (a) {
+      a->active = a->high;
+    }
+    a = tcr->ts_area;
+    if (a) {
+      a->active = a->high;
+    }
+    a = tcr->cs_area;
+    if (a) {
+      a->active = a->high;
+    }
+  }
+  
+  pthread_sigmask(SIG_SETMASK,&mask,NULL);
+  pthread_exit(NULL);
+}
+
+void
+thread_signal_setup()
+{
+  thread_suspend_signal = SIG_SUSPEND_THREAD;
+  thread_kill_signal = SIG_KILL_THREAD;
+
+  install_signal_handler(thread_suspend_signal, (void *) suspend_resume_handler);
+  install_signal_handler(thread_kill_signal, (void *)thread_kill_handler);
+}
+
+
+
+void
+unprotect_all_areas()
+{
+  protected_area_ptr p;
+
+  for(p = AllProtectedAreas, AllProtectedAreas = NULL; p; p = p->next) {
+    unprotect_area(p);
+  }
+}
+
+/*
+  A binding subprim has just done "twlle limit_regno,idx_regno" and
+  the trap's been taken.  Extend the tcr's tlb so that the index will
+  be in bounds and the new limit will be on a page boundary, filling
+  in the new page(s) with 'no_thread_local_binding_marker'.  Update
+  the tcr fields and the registers in the xp and return true if this
+  all works, false otherwise.
+
+  Note that the tlb was allocated via malloc, so realloc can do some
+  of the hard work.
+*/
+Boolean
+extend_tcr_tlb(TCR *tcr, 
+               ExceptionInformation *xp, 
+               unsigned limit_regno,
+               unsigned idx_regno)
+{
+  unsigned
+    index = (unsigned) (xpGPR(xp,idx_regno)),
+    old_limit = tcr->tlb_limit,
+    new_limit = align_to_power_of_2(index+1,12),
+    new_bytes = new_limit-old_limit;
+  LispObj 
+    *old_tlb = tcr->tlb_pointer,
+    *new_tlb = realloc(old_tlb, new_limit),
+    *work;
+
+  if (new_tlb == NULL) {
+    return false;
+  }
+  
+  work = (LispObj *) ((BytePtr)new_tlb+old_limit);
+
+  while (new_bytes) {
+    *work++ = no_thread_local_binding_marker;
+    new_bytes -= sizeof(LispObj);
+  }
+  tcr->tlb_pointer = new_tlb;
+  tcr->tlb_limit = new_limit;
+  xpGPR(xp, limit_regno) = new_limit;
+  return true;
+}
+
+
+
+void
+exception_init()
+{
+  install_pmcl_exception_handlers();
+}
+
+
+
+
+
+#ifdef DARWIN
+
+
+#define TCR_FROM_EXCEPTION_PORT(p) ((TCR *)((natural)p))
+#define TCR_TO_EXCEPTION_PORT(tcr) ((mach_port_t)((natural)(tcr)))
+
+
+
+#define LISP_EXCEPTIONS_HANDLED_MASK \
+ (EXC_MASK_SOFTWARE | EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC)
+
+/* (logcount LISP_EXCEPTIONS_HANDLED_MASK) */
+#define NUM_LISP_EXCEPTIONS_HANDLED 4 
+
+typedef struct {
+  int foreign_exception_port_count;
+  exception_mask_t         masks[NUM_LISP_EXCEPTIONS_HANDLED];
+  mach_port_t              ports[NUM_LISP_EXCEPTIONS_HANDLED];
+  exception_behavior_t behaviors[NUM_LISP_EXCEPTIONS_HANDLED];
+  thread_state_flavor_t  flavors[NUM_LISP_EXCEPTIONS_HANDLED];
+} MACH_foreign_exception_state;
+
+
+
+
+/*
+  Mach's exception mechanism works a little better than its signal
+  mechanism (and, not incidentally, it gets along with GDB a lot
+  better.
+
+  Initially, we install an exception handler to handle each native
+  thread's exceptions.  This process involves creating a distinguished
+  thread which listens for kernel exception messages on a set of
+  0 or more thread exception ports.  As threads are created, they're
+  added to that port set; a thread's exception port is destroyed
+  (and therefore removed from the port set) when the thread exits.
+
+  A few exceptions can be handled directly in the handler thread;
+  others require that we resume the user thread (and that the
+  exception thread resumes listening for exceptions.)  The user
+  thread might eventually want to return to the original context
+  (possibly modified somewhat.)
+
+  As it turns out, the simplest way to force the faulting user
+  thread to handle its own exceptions is to do pretty much what
+  signal() does: the exception handlng thread sets up a sigcontext
+  on the user thread's stack and forces the user thread to resume
+  execution as if a signal handler had been called with that
+  context as an argument.  We can use a distinguished UUO at a
+  distinguished address to do something like sigreturn(); that'll
+  have the effect of resuming the user thread's execution in
+  the (pseudo-) signal context.
+
+  Since:
+    a) we have miles of code in C and in Lisp that knows how to
+    deal with Linux sigcontexts
+    b) Linux sigcontexts contain a little more useful information
+    (the DAR, DSISR, etc.) than their Darwin counterparts
+    c) we have to create a sigcontext ourselves when calling out
+    to the user thread: we aren't really generating a signal, just
+    leveraging existing signal-handling code.
+
+  we create a Linux sigcontext struct.
+
+  Simple ?  Hopefully from the outside it is ...
+
+  We want the process of passing a thread's own context to it to
+  appear to be atomic: in particular, we don't want the GC to suspend
+  a thread that's had an exception but has not yet had its user-level
+  exception handler called, and we don't want the thread's exception
+  context to be modified by a GC while the Mach handler thread is
+  copying it around.  On Linux (and on Jaguar), we avoid this issue
+  because (a) the kernel sets up the user-level signal handler and
+  (b) the signal handler blocks signals (including the signal used
+  by the GC to suspend threads) until tcr->xframe is set up.
+
+  The GC and the Mach server thread therefore contend for the lock
+  "mach_exception_lock".  The Mach server thread holds the lock
+  when copying exception information between the kernel and the
+  user thread; the GC holds this lock during most of its execution
+  (delaying exception processing until it can be done without
+  GC interference.)
+
+*/
+
+#ifdef PPC64
+#define	C_REDZONE_LEN		320
+#define	C_STK_ALIGN             32
+#else
+#define	C_REDZONE_LEN		224
+#define	C_STK_ALIGN		16
+#endif
+#define C_PARAMSAVE_LEN		64
+#define	C_LINKAGE_LEN		48
+
+#define TRUNC_DOWN(a,b,c)  (((((natural)a)-(b))/(c)) * (c))
+
+void
+fatal_mach_error(char *format, ...);
+
+#define MACH_CHECK_ERROR(context,x) if (x != KERN_SUCCESS) {fatal_mach_error("Mach error while %s : %d", context, x);}
+
+
+void
+restore_mach_thread_state(mach_port_t thread, ExceptionInformation *pseudosigcontext)
+{
+  kern_return_t kret;
+  MCONTEXT_T mc = UC_MCONTEXT(pseudosigcontext);
+
+  /* Set the thread's FP state from the pseudosigcontext */
+  kret = thread_set_state(thread,
+                          PPC_FLOAT_STATE,
+                          (thread_state_t)&(mc->__fs),
+                          PPC_FLOAT_STATE_COUNT);
+
+  MACH_CHECK_ERROR("setting thread FP state", kret);
+
+  /* The thread'll be as good as new ... */
+#ifdef PPC64
+  kret = thread_set_state(thread,
+                          PPC_THREAD_STATE64,
+                          (thread_state_t)&(mc->__ss),
+                          PPC_THREAD_STATE64_COUNT);
+#else
+  kret = thread_set_state(thread, 
+                          MACHINE_THREAD_STATE,
+                          (thread_state_t)&(mc->__ss),
+                          MACHINE_THREAD_STATE_COUNT);
+#endif
+  MACH_CHECK_ERROR("setting thread state", kret);
+}  
+
+/* This code runs in the exception handling thread, in response
+   to an attempt to execute the UU0 at "pseudo_sigreturn" (e.g.,
+   in response to a call to pseudo_sigreturn() from the specified
+   user thread.
+   Find that context (the user thread's R3 points to it), then
+   use that context to set the user thread's state.  When this
+   function's caller returns, the Mach kernel will resume the
+   user thread.
+*/
+
+kern_return_t
+do_pseudo_sigreturn(mach_port_t thread, TCR *tcr)
+{
+  ExceptionInformation *xp;
+
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "doing pseudo_sigreturn for 0x%x\n",tcr);
+#endif
+  xp = tcr->pending_exception_context;
+  if (xp) {
+    tcr->pending_exception_context = NULL;
+    tcr->valence = TCR_STATE_LISP;
+    restore_mach_thread_state(thread, xp);
+    raise_pending_interrupt(tcr);
+  } else {
+    Bug(NULL, "no xp here!\n");
+  }
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "did pseudo_sigreturn for 0x%x\n",tcr);
+#endif
+  return KERN_SUCCESS;
+}  
+
+ExceptionInformation *
+create_thread_context_frame(mach_port_t thread, 
+			    natural *new_stack_top)
+{
+#ifdef PPC64
+  ppc_thread_state64_t ts;
+#else
+  ppc_thread_state_t ts;
+#endif
+  mach_msg_type_number_t thread_state_count;
+  kern_return_t result;
+  ExceptionInformation *pseudosigcontext;
+  MCONTEXT_T mc;
+  natural stackp, backlink;
+
+#ifdef PPC64
+  thread_state_count = PPC_THREAD_STATE64_COUNT;
+  result = thread_get_state(thread,
+                            PPC_THREAD_STATE64,
+                            (thread_state_t)&ts,
+                            &thread_state_count);
+#else
+  thread_state_count = MACHINE_THREAD_STATE_COUNT;
+  result = thread_get_state(thread, 
+                            PPC_THREAD_STATE,	/* GPRs, some SPRs  */
+                            (thread_state_t)&ts,
+                            &thread_state_count);
+#endif
+  
+  if (result != KERN_SUCCESS) {
+    get_tcr(true);
+    Bug(NULL, "Exception thread can't obtain thread state, Mach result = %d", result);
+  }
+  stackp = ts.__r1;
+  backlink = stackp;
+  stackp = TRUNC_DOWN(stackp, C_REDZONE_LEN, C_STK_ALIGN);
+  stackp -= sizeof(*pseudosigcontext);
+  pseudosigcontext = (ExceptionInformation *) ptr_from_lispobj(stackp);
+
+  stackp = TRUNC_DOWN(stackp, sizeof(*mc), C_STK_ALIGN);
+  mc = (MCONTEXT_T) ptr_from_lispobj(stackp);
+  memmove(&(mc->__ss),&ts,sizeof(ts));
+
+  thread_state_count = PPC_FLOAT_STATE_COUNT;
+  thread_get_state(thread,
+		   PPC_FLOAT_STATE,
+		   (thread_state_t)&(mc->__fs),
+		   &thread_state_count);
+
+
+#ifdef PPC64
+  thread_state_count = PPC_EXCEPTION_STATE64_COUNT;
+#else
+  thread_state_count = PPC_EXCEPTION_STATE_COUNT;
+#endif
+  thread_get_state(thread,
+#ifdef PPC64
+                   PPC_EXCEPTION_STATE64,
+#else
+		   PPC_EXCEPTION_STATE,
+#endif
+		   (thread_state_t)&(mc->__es),
+		   &thread_state_count);
+
+
+  UC_MCONTEXT(pseudosigcontext) = mc;
+  stackp = TRUNC_DOWN(stackp, C_PARAMSAVE_LEN, C_STK_ALIGN);
+  stackp -= C_LINKAGE_LEN;
+  *(natural *)ptr_from_lispobj(stackp) = backlink;
+  if (new_stack_top) {
+    *new_stack_top = stackp;
+  }
+  return pseudosigcontext;
+}
+
+/*
+  This code sets up the user thread so that it executes a "pseudo-signal
+  handler" function when it resumes.  Create a linux sigcontext struct
+  on the thread's stack and pass it as an argument to the pseudo-signal
+  handler.
+
+  Things are set up so that the handler "returns to" pseudo_sigreturn(),
+  which will restore the thread's context.
+
+  If the handler invokes code that throws (or otherwise never sigreturn()'s
+  to the context), that's fine.
+
+  Actually, check that: throw (and variants) may need to be careful and
+  pop the tcr's xframe list until it's younger than any frame being
+  entered.
+*/
+
+int
+setup_signal_frame(mach_port_t thread,
+		   void *handler_address,
+		   int signum,
+                   int code,
+		   TCR *tcr)
+{
+#ifdef PPC64
+  ppc_thread_state64_t ts;
+#else
+  ppc_thread_state_t ts;
+#endif
+  ExceptionInformation *pseudosigcontext;
+  int old_valence = tcr->valence;
+  natural stackp;
+
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout,"Setting up exception handling for 0x%x\n", tcr);
+#endif
+  pseudosigcontext = create_thread_context_frame(thread, &stackp);
+  pseudosigcontext->uc_onstack = 0;
+  pseudosigcontext->uc_sigmask = (sigset_t) 0;
+  tcr->pending_exception_context = pseudosigcontext;
+  tcr->valence = TCR_STATE_EXCEPTION_WAIT;
+  
+
+  /* 
+     It seems like we've created a  sigcontext on the thread's
+     stack.  Set things up so that we call the handler (with appropriate
+     args) when the thread's resumed.
+  */
+
+  ts.__srr0 = (natural) handler_address;
+  ts.__srr1 = (int) xpMSR(pseudosigcontext) & ~MSR_FE0_FE1_MASK;
+  ts.__r1 = stackp;
+  ts.__r3 = signum;
+  ts.__r4 = (natural)pseudosigcontext;
+  ts.__r5 = (natural)tcr;
+  ts.__r6 = (natural)old_valence;
+  ts.__lr = (natural)pseudo_sigreturn;
+
+
+#ifdef PPC64
+  ts.__r13 = xpGPR(pseudosigcontext,13);
+  thread_set_state(thread,
+                   PPC_THREAD_STATE64,
+                   (thread_state_t)&ts,
+                   PPC_THREAD_STATE64_COUNT);
+#else
+  thread_set_state(thread, 
+		   MACHINE_THREAD_STATE,
+		   (thread_state_t)&ts,
+		   MACHINE_THREAD_STATE_COUNT);
+#endif
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout,"Set up exception context for 0x%x at 0x%x\n", tcr, tcr->pending_exception_context);
+#endif
+  return 0;
+}
+
+
+void
+pseudo_signal_handler(int signum, ExceptionInformation *context, TCR *tcr, int old_valence)
+{
+  signal_handler(signum, NULL, context, tcr, old_valence);
+} 
+
+
+int
+thread_set_fp_exceptions_enabled(mach_port_t thread, Boolean enabled)
+{
+#ifdef PPC64
+  ppc_thread_state64_t ts;
+#else
+  ppc_thread_state_t ts;
+#endif
+  mach_msg_type_number_t thread_state_count;
+
+#ifdef PPC64
+  thread_state_count = PPC_THREAD_STATE64_COUNT;
+#else
+  thread_state_count = PPC_THREAD_STATE_COUNT;
+#endif
+  thread_get_state(thread, 
+#ifdef PPC64
+		   PPC_THREAD_STATE64,	/* GPRs, some SPRs  */
+#else
+		   PPC_THREAD_STATE,	/* GPRs, some SPRs  */
+#endif
+		   (thread_state_t)&ts,
+		   &thread_state_count);
+  if (enabled) {
+    ts.__srr1 |= MSR_FE0_FE1_MASK;
+  } else {
+    ts.__srr1 &= ~MSR_FE0_FE1_MASK;
+  }
+  /* 
+     Hack-o-rama warning (isn't it about time for such a warning?):
+     pthread_kill() seems to want to lose the MSR's FE0/FE1 bits.
+     Our handler for lisp's use of pthread_kill() pushes a phony
+     lisp frame on the stack and force the context to resume at
+     the UUO in enable_fp_exceptions(); the "saveLR" field of that
+     lisp frame contains the -real- address that process_interrupt
+     should have returned to, and the fact that it's in a lisp
+     frame should convince the GC to notice that address if it
+     runs in the tiny time window between returning from our
+     interrupt handler and ... here.
+     If the top frame on the stack is a lisp frame, discard it
+     and set ts.srr0 to the saveLR field in that frame.  Otherwise,
+     just adjust ts.srr0 to skip over the UUO.
+  */
+  {
+    lisp_frame *tos = (lisp_frame *)ts.__r1,
+      *next_frame = tos->backlink;
+    
+    if (tos == (next_frame -1)) {
+      ts.__srr0 = tos->savelr;
+      ts.__r1 = (LispObj) next_frame;
+    } else {
+      ts.__srr0 += 4;
+    }
+  }
+  thread_set_state(thread, 
+#ifdef PPC64
+		   PPC_THREAD_STATE64,	/* GPRs, some SPRs  */
+#else
+		   PPC_THREAD_STATE,	/* GPRs, some SPRs  */
+#endif
+		   (thread_state_t)&ts,
+#ifdef PPC64
+                   PPC_THREAD_STATE64_COUNT
+#else
+		   PPC_THREAD_STATE_COUNT
+#endif
+                   );
+
+  return 0;
+}
+
+/*
+  This function runs in the exception handling thread.  It's
+  called (by this precise name) from the library function "exc_server()"
+  when the thread's exception ports are set up.  (exc_server() is called
+  via mach_msg_server(), which is a function that waits for and dispatches
+  on exception messages from the Mach kernel.)
+
+  This checks to see if the exception was caused by a pseudo_sigreturn()
+  UUO; if so, it arranges for the thread to have its state restored
+  from the specified context.
+
+  Otherwise, it tries to map the exception to a signal number and
+  arranges that the thread run a "pseudo signal handler" to handle
+  the exception.
+
+  Some exceptions could and should be handled here directly.
+*/
+
+kern_return_t
+catch_exception_raise(mach_port_t exception_port,
+		      mach_port_t thread,
+		      mach_port_t task, 
+		      exception_type_t exception,
+		      exception_data_t code_vector,
+		      mach_msg_type_number_t code_count)
+{
+  int signum = 0, code = *code_vector, code1;
+  TCR *tcr = TCR_FROM_EXCEPTION_PORT(exception_port);
+  kern_return_t kret;
+
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "obtaining Mach exception lock in exception thread\n");
+#endif
+
+  if (tcr->flags & (1<<TCR_FLAG_BIT_PENDING_EXCEPTION)) {
+    CLR_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_EXCEPTION);
+  } 
+  if ((exception == EXC_BAD_INSTRUCTION) &&
+      (code_vector[0] == EXC_PPC_UNIPL_INST) &&
+      (((code1 = code_vector[1]) == (int)pseudo_sigreturn) ||
+       (code1 == (int)enable_fp_exceptions) ||
+       (code1 == (int)disable_fp_exceptions))) {
+    if (code1 == (int)pseudo_sigreturn) {
+      kret = do_pseudo_sigreturn(thread, tcr);
+#if 0
+      fprintf(dbgout, "Exception return in 0x%x\n",tcr);
+#endif
+        
+    } else if (code1 == (int)enable_fp_exceptions) {
+      kret = thread_set_fp_exceptions_enabled(thread, true);
+    } else kret =  thread_set_fp_exceptions_enabled(thread, false);
+  } else if (tcr->flags & (1<<TCR_FLAG_BIT_PROPAGATE_EXCEPTION)) {
+    CLR_TCR_FLAG(tcr,TCR_FLAG_BIT_PROPAGATE_EXCEPTION);
+    kret = 17;
+  } else {
+    switch (exception) {
+    case EXC_BAD_ACCESS:
+      signum = SIGSEGV;
+      break;
+        
+    case EXC_BAD_INSTRUCTION:
+      signum = SIGILL;
+      break;
+      
+    case EXC_SOFTWARE:
+      if (code == EXC_PPC_TRAP) {
+        signum = SIGTRAP;
+      }
+      break;
+      
+    case EXC_ARITHMETIC:
+      signum = SIGFPE;
+      break;
+
+    default:
+      break;
+    }
+    if (signum) {
+      kret = setup_signal_frame(thread,
+                                (void *)pseudo_signal_handler,
+                                signum,
+                                code,
+                                tcr);
+#if 0
+      fprintf(dbgout, "Setup pseudosignal handling in 0x%x\n",tcr);
+#endif
+
+    } else {
+      kret = 17;
+    }
+  }
+
+  return kret;
+}
+
+
+
+typedef struct {
+  mach_msg_header_t Head;
+  /* start of the kernel processed data */
+  mach_msg_body_t msgh_body;
+  mach_msg_port_descriptor_t thread;
+  mach_msg_port_descriptor_t task;
+  /* end of the kernel processed data */
+  NDR_record_t NDR;
+  exception_type_t exception;
+  mach_msg_type_number_t codeCnt;
+  integer_t code[2];
+  mach_msg_trailer_t trailer;
+} exceptionRequest;
+
+
+boolean_t
+openmcl_exc_server(mach_msg_header_t *in, mach_msg_header_t *out)
+{
+  static NDR_record_t _NDR = {0};
+  kern_return_t handled;
+  mig_reply_error_t *reply = (mig_reply_error_t *) out;
+  exceptionRequest *req = (exceptionRequest *) in;
+
+  reply->NDR = _NDR;
+
+  out->msgh_bits = in->msgh_bits & MACH_MSGH_BITS_REMOTE_MASK;
+  out->msgh_remote_port = in->msgh_remote_port;
+  out->msgh_size = sizeof(mach_msg_header_t)+(3 * sizeof(unsigned));
+  out->msgh_local_port = MACH_PORT_NULL;
+  out->msgh_id = in->msgh_id+100;
+
+  /* Could handle other exception flavors in the range 2401-2403 */
+
+
+  if (in->msgh_id != 2401) {
+    reply->RetCode = MIG_BAD_ID;
+    return FALSE;
+  }
+  handled = catch_exception_raise(req->Head.msgh_local_port,
+                                  req->thread.name,
+                                  req->task.name,
+                                  req->exception,
+                                  req->code,
+                                  req->codeCnt);
+  reply->RetCode = handled;
+  return TRUE;
+}
+
+/*
+  The initial function for an exception-handling thread.
+*/
+
+void *
+exception_handler_proc(void *arg)
+{
+  extern boolean_t exc_server();
+  mach_port_t p = TCR_TO_EXCEPTION_PORT(arg);
+
+  mach_msg_server(openmcl_exc_server, 2048, p, 0);
+  /* Should never return. */
+  abort();
+}
+
+
+
+mach_port_t
+mach_exception_port_set()
+{
+  static mach_port_t __exception_port_set = MACH_PORT_NULL;
+  kern_return_t kret;  
+  if (__exception_port_set == MACH_PORT_NULL) {
+    kret = mach_port_allocate(mach_task_self(),
+			      MACH_PORT_RIGHT_PORT_SET,
+			      &__exception_port_set);
+    MACH_CHECK_ERROR("allocating thread exception_ports",kret);
+    create_system_thread(0,
+                         NULL,
+                         exception_handler_proc, 
+                         (void *)((natural)__exception_port_set));
+  }
+  return __exception_port_set;
+}
+
+/*
+  Setup a new thread to handle those exceptions specified by
+  the mask "which".  This involves creating a special Mach
+  message port, telling the Mach kernel to send exception
+  messages for the calling thread to that port, and setting
+  up a handler thread which listens for and responds to
+  those messages.
+
+*/
+
+/*
+  Establish the lisp thread's TCR as its exception port, and determine
+  whether any other ports have been established by foreign code for
+  exceptions that lisp cares about.
+
+  If this happens at all, it should happen on return from foreign
+  code and on entry to lisp code via a callback.
+
+  This is a lot of trouble (and overhead) to support Java, or other
+  embeddable systems that clobber their caller's thread exception ports.
+  
+*/
+kern_return_t
+tcr_establish_exception_port(TCR *tcr, mach_port_t thread)
+{
+  kern_return_t kret;
+  MACH_foreign_exception_state *fxs = (MACH_foreign_exception_state *)tcr->native_thread_info;
+  int i;
+  unsigned n = NUM_LISP_EXCEPTIONS_HANDLED;
+  mach_port_t lisp_port = TCR_TO_EXCEPTION_PORT(tcr), foreign_port;
+  exception_mask_t mask = 0;
+
+  kret = thread_swap_exception_ports(thread,
+				     LISP_EXCEPTIONS_HANDLED_MASK,
+				     lisp_port,
+				     EXCEPTION_DEFAULT,
+				     THREAD_STATE_NONE,
+				     fxs->masks,
+				     &n,
+				     fxs->ports,
+				     fxs->behaviors,
+				     fxs->flavors);
+  if (kret == KERN_SUCCESS) {
+    fxs->foreign_exception_port_count = n;
+    for (i = 0; i < n; i ++) {
+      foreign_port = fxs->ports[i];
+
+      if ((foreign_port != lisp_port) &&
+	  (foreign_port != MACH_PORT_NULL)) {
+	mask |= fxs->masks[i];
+      }
+    }
+    tcr->foreign_exception_status = (int) mask;
+  }
+  return kret;
+}
+
+kern_return_t
+tcr_establish_lisp_exception_port(TCR *tcr)
+{
+  return tcr_establish_exception_port(tcr, (mach_port_t)((natural)tcr->native_thread_id));
+}
+
+/*
+  Do this when calling out to or returning from foreign code, if
+  any conflicting foreign exception ports were established when we
+  last entered lisp code.
+*/
+kern_return_t
+restore_foreign_exception_ports(TCR *tcr)
+{
+  exception_mask_t m = (exception_mask_t) tcr->foreign_exception_status;
+  
+  if (m) {
+    MACH_foreign_exception_state *fxs  = 
+      (MACH_foreign_exception_state *) tcr->native_thread_info;
+    int i, n = fxs->foreign_exception_port_count;
+    exception_mask_t tm;
+
+    for (i = 0; i < n; i++) {
+      if ((tm = fxs->masks[i]) & m) {
+	thread_set_exception_ports((mach_port_t)((natural)tcr->native_thread_id),
+				   tm,
+				   fxs->ports[i],
+				   fxs->behaviors[i],
+				   fxs->flavors[i]);
+      }
+    }
+  }
+}
+				   
+
+/*
+  This assumes that a Mach port (to be used as the thread's exception port) whose
+  "name" matches the TCR's 32-bit address has already been allocated.
+*/
+
+kern_return_t
+setup_mach_exception_handling(TCR *tcr)
+{
+  mach_port_t 
+    thread_exception_port = TCR_TO_EXCEPTION_PORT(tcr),
+    task_self = mach_task_self();
+  kern_return_t kret;
+
+  kret = mach_port_insert_right(task_self,
+				thread_exception_port,
+				thread_exception_port,
+				MACH_MSG_TYPE_MAKE_SEND);
+  MACH_CHECK_ERROR("adding send right to exception_port",kret);
+
+  kret = tcr_establish_exception_port(tcr, (mach_port_t)((natural) tcr->native_thread_id));
+  if (kret == KERN_SUCCESS) {
+    mach_port_t exception_port_set = mach_exception_port_set();
+
+    kret = mach_port_move_member(task_self,
+				 thread_exception_port,
+				 exception_port_set);
+  }
+  return kret;
+}
+
+void
+darwin_exception_init(TCR *tcr)
+{
+  void tcr_monitor_exception_handling(TCR*, Boolean);
+  kern_return_t kret;
+  MACH_foreign_exception_state *fxs = 
+    calloc(1, sizeof(MACH_foreign_exception_state));
+  
+  tcr->native_thread_info = (void *) fxs;
+
+  if ((kret = setup_mach_exception_handling(tcr))
+      != KERN_SUCCESS) {
+    fprintf(dbgout, "Couldn't setup exception handler - error = %d\n", kret);
+    terminate_lisp();
+  }
+}
+
+/*
+  The tcr is the "name" of the corresponding thread's exception port.
+  Destroying the port should remove it from all port sets of which it's
+  a member (notably, the exception port set.)
+*/
+void
+darwin_exception_cleanup(TCR *tcr)
+{
+  void *fxs = tcr->native_thread_info;
+  extern Boolean use_mach_exception_handling;
+
+  if (fxs) {
+    tcr->native_thread_info = NULL;
+    free(fxs);
+  }
+  if (use_mach_exception_handling) {
+    mach_port_deallocate(mach_task_self(),TCR_TO_EXCEPTION_PORT(tcr));
+    mach_port_destroy(mach_task_self(),TCR_TO_EXCEPTION_PORT(tcr));
+  }
+}
+
+
+Boolean
+suspend_mach_thread(mach_port_t mach_thread)
+{
+  kern_return_t status;
+  Boolean aborted = false;
+  
+  do {
+    aborted = false;
+    status = thread_suspend(mach_thread);
+    if (status == KERN_SUCCESS) {
+      status = thread_abort_safely(mach_thread);
+      if (status == KERN_SUCCESS) {
+        aborted = true;
+      } else {
+        fprintf(dbgout, "abort failed on thread = 0x%x\n",mach_thread);
+        thread_resume(mach_thread);
+      }
+    } else {
+      return false;
+    }
+  } while (! aborted);
+  return true;
+}
+
+/*
+  Only do this if pthread_kill indicated that the pthread isn't
+  listening to signals anymore, as can happen as soon as pthread_exit()
+  is called on Darwin.  The thread could still call out to lisp as it
+  is exiting, so we need another way to suspend it in this case.
+*/
+Boolean
+mach_suspend_tcr(TCR *tcr)
+{
+  mach_port_t mach_thread = (mach_port_t)((natural)( tcr->native_thread_id));
+  ExceptionInformation *pseudosigcontext;
+  Boolean result = false;
+  
+  result = suspend_mach_thread(mach_thread);
+  if (result) {
+    pseudosigcontext = create_thread_context_frame(mach_thread, NULL);
+    pseudosigcontext->uc_onstack = 0;
+    pseudosigcontext->uc_sigmask = (sigset_t) 0;
+    tcr->suspend_context = pseudosigcontext;
+  }
+  return result;
+}
+
+void
+mach_resume_tcr(TCR *tcr)
+{
+  ExceptionInformation *xp;
+  mach_port_t mach_thread = (mach_port_t)((natural)(tcr->native_thread_id));
+  
+  xp = tcr->suspend_context;
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "resuming TCR 0x%x, pending_exception_context = 0x%x\n",
+          tcr, tcr->pending_exception_context);
+#endif
+  tcr->suspend_context = NULL;
+  restore_mach_thread_state(mach_thread, xp);
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "restored state in TCR 0x%x, pending_exception_context = 0x%x\n",
+          tcr, tcr->pending_exception_context);
+#endif
+  thread_resume(mach_thread);
+}
+
+void
+fatal_mach_error(char *format, ...)
+{
+  va_list args;
+  char s[512];
+ 
+
+  va_start(args, format);
+  vsnprintf(s, sizeof(s),format, args);
+  va_end(args);
+
+  Fatal("Mach error", s);
+}
+
+void
+pseudo_interrupt_handler(int signum, ExceptionInformation *context)
+{
+  interrupt_handler(signum, NULL, context);
+}
+
+int
+mach_raise_thread_interrupt(TCR *target)
+{
+  mach_port_t mach_thread = (mach_port_t)((natural)(target->native_thread_id));
+  kern_return_t kret;
+  Boolean result = false;
+  TCR *current = get_tcr(false);
+  thread_basic_info_data_t info; 
+  mach_msg_type_number_t info_count = THREAD_BASIC_INFO_COUNT;
+
+  LOCK(lisp_global(TCR_AREA_LOCK), current);
+
+  if (suspend_mach_thread(mach_thread)) {
+    if (thread_info(mach_thread,
+                    THREAD_BASIC_INFO,
+                    (thread_info_t)&info,
+                    &info_count) == KERN_SUCCESS) {
+      if (info.suspend_count == 1) {
+        if ((target->valence == TCR_STATE_LISP) &&
+            (!target->unwinding) &&
+            (TCR_INTERRUPT_LEVEL(target) >= 0)) {
+          kret = setup_signal_frame(mach_thread,
+                                    (void *)pseudo_interrupt_handler,
+                                    SIGNAL_FOR_PROCESS_INTERRUPT,
+                                    0,
+                                    target);
+          if (kret == KERN_SUCCESS) {
+            result = true;
+          }
+        }
+      }
+    }
+    if (! result) {
+      target->interrupt_pending = 1 << fixnumshift;
+    }
+    thread_resume(mach_thread);
+    
+  }
+  UNLOCK(lisp_global(TCR_AREA_LOCK), current);
+  return 0;
+}
+
+#endif
Index: /branches/new-random/lisp-kernel/ppc-exceptions.h
===================================================================
--- /branches/new-random/lisp-kernel/ppc-exceptions.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-exceptions.h	(revision 13309)
@@ -0,0 +1,440 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+#define UUO_MASK 0xfc00000f
+
+#define IS_UUO(i) (((i) & UUO_MASK) == 0xb)
+/* If an instruction is a UUO, the minor opcode is in bits 21:27 */
+#define UUO_MINOR(u) (((u) >> 4) & 0x7f)
+
+typedef u_int32_t opcode, *pc;
+
+OSStatus
+handle_uuo(ExceptionInformation *, opcode, pc);
+
+
+
+#ifdef LINUX
+/*
+  Different (recent) versions of glibc disagree about how
+  a ucontext is laid out (and about what an mcontext is.)
+  There's something like a pointer to a pt_regs structure
+  in the 12th word in both cases.  (Yes, this is an extremely
+  ugly hack; it would be better to conditionalize on the values
+  of GLIBC_VERSION/GLIBC_MINOR , but the discrepancy exists
+  in various flavors of glibc 2.3.)
+*/
+#ifdef PPC64
+#define XP_PTREGS(x) ((x)->uc_mcontext.regs)
+#define xpGPRvector(x) ((natural *)(XP_PTREGS(x)))
+#else
+#define XP_PTREGS(x) (((struct pt_regs **)(x))[12])
+#define xpGPRvector(x) (XP_PTREGS(x)->gpr)
+#endif
+#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
+#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
+#define xpPC(x) (*((pc*)(&(XP_PTREGS(x)->nip))))
+#define set_xpPC(x,new) (xpPC(x) = (pc)(new))
+#define xpLR(x) (*((pc*)(&(XP_PTREGS(x)->link))))
+#define xpCTR(x) (*(pc*)(&(XP_PTREGS(x)->ctr)))
+#define xpXER(x) (XP_PTREGS(x)->xer)
+#define xpCCR(x) (XP_PTREGS(x)->ccr)
+#define xpMSR(x) (XP_PTREGS(x)->msr)
+#define xpDSISR(x) (XP_PTREGS(x)->dsisr)
+#define xpDAR(x) (XP_PTREGS(x)->dar)
+#define xpTRAP(x) (XP_PTREGS(x)->trap)
+#define xpFPSCR(x) (XP_PTREGS(x)->gpr[PT_FPSCR])
+#define xpFPRvector(x) ((double *)(&(XP_PTREGS(x)->gpr[PT_FPR0])))
+#define xpFPR(x,fprno) (xpFPRvector(x)[fprno])
+
+/* 
+   Work around a Darwin G5 bug (present in OSX 10.2.7, 10.2.8, and later
+   versions.  See below for details.
+*/
+#define DarwinSigReturn(context)
+#define SIGRETURN(context)
+#endif
+
+#ifdef DARWIN
+#define xpGPRvector(x) (&(UC_MCONTEXT(x)->__ss.__r0))
+#define xpGPR(x,gprno) ((xpGPRvector(x))[gprno])
+#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (UInt32)(new)
+#define xpPC(x) (*((pc*) &(UC_MCONTEXT(x)->__ss.__srr0)))
+#define set_xpPC(x,new) (xpPC(x) = (pc)(new))
+#define xpLR(x) (*((pc*)(&(UC_MCONTEXT(x)->__ss.__lr))))
+#define xpCTR(x) (*(pc*)(&(UC_MCONTEXT(x)->__ss.__ctr)))
+#define xpXER(x) (UC_MCONTEXT(x)->__ss.__xer)
+#define xpCCR(x) (UC_MCONTEXT(x)->__ss.__cr)
+#define xpMSR(x) (UC_MCONTEXT(x)->__ss.__srr1)
+#define xpDSISR(x) (UC_MCONTEXT(x)->__es.__dsisr)
+#define xpDAR(x) (UC_MCONTEXT(x)->__es.__dar)
+#define xpTRAP(x) (UC_MCONTEXT(x)->__es.__exception)
+#define xpFPSCR(x) (UC_MCONTEXT(x)->__fs.__fpscr)
+#define xpFPRvector(x) (UC_MCONTEXT(x)->__fs.__fpregs)
+#define xpFPR(x,fprno) (xpFPRvector(x)[fprno])
+/* There's a bug in some versions of Darwin on G5 processors: FP context
+   isn't restored correctly on exit from a signal handler if the integer
+   context appears to be unmodified (the 64-bit context isn't set up
+   correctly by the kernel: only the first N bytes are copied out of
+   the kernel, where N = size of 32-bit context.
+
+   If the kernel pushed both a 32-bit and 64-bit context, the C
+   runtime "signal trampoline" code tries to determine if the 32-bit
+   GPRs and user-visible SPRs in the 32-bit context contain the same
+   values as their 64-bit counterparts on exit; if so, it tries to
+   call sigreturn with an extra argument that indicates that the
+   thread's state should be restored from the 64-bit context.
+   (Apparently that's more efficient; it'd be surprising if it'd be
+   more efficent when the cost of comparing values in the two contexts
+   is factored in ...).  On some OS releases, the 64-bit context can't
+   be reliably restored (FPRs get trashed.)
+
+   One way to work around this is to use a deprecated, 32-bit-context-only
+   version of the sigreturn syscall.  There seems to be reason to be
+   reason to believe that the old sigreturn syscall will disappear
+   on OS releases >10.3.
+
+   Another way to work around this is to make a "harmless" change to
+   an SPR or GPR value in the 32-bit context.  There are lots of
+   "reserved" bits in the XER that make good candidates: 1's written
+   to reserved XER bits can't be reliably read anyway, so this may
+   or may not actually change the value in the XER in a way that
+   can be reliably detected.
+
+   Note that both the old, deprecated version of sigreturn and the
+   new version take a first argument of type "struct ucontext *",
+   not "struct sigcontext *" as the man page and header files claim.
+   The new version takes a second argument, which is a small integer
+   which defines what "flavor" of context should be restored from.
+   The meaningful values that can be used here aren't defined in
+   a header file; the kernel (and the libc _sigtramp() function)
+   have (hopefully) matching, redundant hardwired definitions in
+   the source.
+*/
+#ifdef PPC64
+#define DarwinSigReturn(x)
+#else
+#define DarwinSigReturn(x) (UC_MCONTEXT(x)->__ss.__xer)^=0x80
+#endif
+#define SIGRETURN(context) DarwinSigReturn(context)
+#endif
+
+
+
+
+
+
+/* 
+  Unconditional traps (tw, twi instructions) are used by the
+  operating system.  We use conditional traps.
+  */
+
+int
+is_conditional_trap(opcode);
+
+#define kNameBufLen 256
+#define TRAP_LOOKUP_TRIES 5   /* # instrs to scan before trap instr */
+
+void
+callback_for_trap (LispObj, ExceptionInformation *, pc, natural, natural, natural);
+
+natural
+register_codevector_contains_pc (natural, pc);
+
+void
+callback_to_lisp (LispObj, ExceptionInformation *, natural, natural, natural, natural, natural);
+
+OSStatus
+handle_trap(ExceptionInformation *, opcode, pc, siginfo_t *);
+
+unsigned
+scan_for_instr( unsigned, unsigned, pc );
+
+
+
+#define UUO_INTERR (11)
+#define UUO_INTCERR (12)
+#define UUO_INTERR2 (13)
+#define UUO_INTCERR2 (14)
+
+#define UUO_FPUX_BINOP (22)
+#define UUO_ZERO_FPSCR (25)
+
+
+/* PPC instructions */
+#define match_instr(instr, mask, target)   (((instr) & (mask)) == (target))
+#define RS_field(instr)  (((instr) >> 21) & 0x1f)
+#define RT_field(instr)  (RS_field(instr))
+#define TO_field(instr)  (RT_field(instr))
+#define RA_field(instr)  (((instr) >> 16) & 0x1f)
+#define RB_field(instr)  (((instr) >> 11) & 0x1f)
+#define D_field(instr)   ((instr) & 0xffff)
+#define DS_field(instr)  ((instr) & 0xfffc)
+#define DS_VARIANT_FIELD(instr) ((instr) & 3)
+
+#define RT(val) ((val & 0x1f) << 21)
+#define RS(val) (RT(val))
+#define RA(val) ((val & 0x1f) << 16)
+#define RB(val) ((val & 0x1f) << 11)
+#define D(val) (val & 0xffff)
+
+#define RS_MASK RS(-1)
+#define RT_MASK RS_MASK
+#define TO_MASK RS_MASK
+#define RA_MASK RA(-1)
+#define RB_MASK RB(-1)
+#define D_MASK  D(-1)
+
+
+
+#define OP(x) (((x) & 0x3f) << 26)
+#define OP_MASK OP (0x3f)
+
+/* Main opcode + TO field of a D form instruction */
+#define OPTO(x,to) (OP(x) | (((to) & 0x1f) << 21))
+#define OPTO_MASK (OP_MASK | TO_MASK)
+#define OPTORA(x,to,ra) (OPTO(x,to) | RA(ra))
+#define OPTORA_MASK (OP_TO_MASK | RA_MASK)
+
+
+
+
+/* An X form instruction.  */
+#define X(op, xop) (OP (op) | (((xop) & 0x3ff) << 1))
+
+/* An X form instruction with the RC bit specified.  */
+#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
+
+/* The mask for an X form instruction.  */
+#define X_MASK XRC(0x3f, 0x3ff, 1)
+
+/* An XO form instruction */
+#define XO(op, xop, oe, rc) \
+  (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1) | ((((unsigned long)(oe)) & 1) << 10) | (((unsigned long)(rc)) & 1))
+#define XO_MASK XO (0x3f, 0x1ff, 1, 1)
+
+
+
+/* The bits in the TO field of a TW or TWI instruction */
+#define TO_LT (1<<4)		/* signed < */
+#define TO_GT (1<<3)		/* signed > */
+#define TO_EQ (1<<2)		/* = */
+#define TO_LO (1<<1)		/* unsigned < */
+#define TO_HI (1<<0)		/* unsigned > */
+#define TO_NE (TO_LT|TO_GT)
+
+/* True if major opcode of "instr" is "op" */
+#define major_opcode_p(instr, op) match_instr((instr),OP_MASK,OP(op))
+
+/* True if "instr" is an X form instruction with major opcode "major"
+   and minor opcode "minor" */
+#define X_opcode_p(instr,major,minor) match_instr((instr),X_MASK,X(major,minor))
+
+#define major_opcode_TDI 2
+#define major_opcode_TWI 3
+#ifdef PPC64
+#define major_opcode_TRI major_opcode_TDI
+#else
+#define major_opcode_TRI major_opcode_TWI
+#endif
+#define major_opcode_ADDI 14
+#define major_opcode_RLWINM 21
+#define major_opcode_X31 31		/* an "X" form instruction; see minor opcode */
+#define major_opcode_LWZ 32
+#define major_opcode_LBZ 34
+#define major_opcode_STW 36
+#define major_opcode_STWU 37
+#define major_opcode_LD_LDU_LWA 58
+#define major_opcode_FPU_SINGLE 59
+#define major_opcode_FPU_DOUBLE 63
+
+#define minor_opcode_TW 4
+#define minor_opcode_TD 68
+#ifdef PPC64
+#define minor_opcode_TR minor_opcode_TD
+#else
+#define minor_opcode_TR minor_opcode_TW
+#endif
+#define minor_opcode_SUBF 40
+#define minor_opcode_STWX 151
+#define minor_opcode_STWUX 183
+
+#define major_opcode_DS_LOAD64 58
+#define DS_LOAD64_VARIANT_LD 0
+
+#define major_opcode_DS_STORE64 62
+#define DS_STORE64_VARIANT_STD 0
+
+
+
+#define D_instruction(major,rt,ra,imm) (OP(major)|((rt)<<21)|((ra)<<16)|((imm)&D_MASK))
+#define DS_instruction(major,rt,ra,imm,minor) (OP(major)|((rt)<<21)|((ra)<<16)|(((imm)&D_MASK)&~3)|((minor)&3))
+#define TRI_instruction(rt,ra,imm)     D_instruction(major_opcode_TRI,rt,ra,imm)
+#define LBZ_instruction(rt,ra,imm)     D_instruction(major_opcode_LBZ,rt,ra,imm)
+#define LWZ_instruction(rt,ra,imm)     D_instruction(major_opcode_LWZ,rt,ra,imm)
+#define LD_instruction(rt,ra,imm)      DS_instruction(58,rt,ra,imm,0)
+
+#define D_RT_IMM_MASK                  (OP_MASK|RT_MASK|D_MASK)
+#define D_RA_IMM_MASK                  (OP_MASK|RA_MASK|D_MASK)
+
+#define X_instruction(major,minor,rt,ra,rb) (X(major,minor)|((rt)<<21)|((ra)<<16)|((rb)<<11))
+
+#define unmasked_register              0
+
+#define LISP_BREAK_INSTRUCTION 0x7f810808
+#define QUIET_LISP_BREAK_INSTRUCTION 0x7c800008
+
+#ifdef PPC64
+/* Have to use signed comparisons on PPC64; if we decrememt
+   allocptr and it "wraps around" address 0, that's an 
+   attempt to allocate a large object.  Note that this
+   means that valid heap addresses can't have the high
+   bit set. */
+/* tdlt allocptr,allocbase */
+#define ALLOC_TRAP_INSTRUCTION 0x7e095088
+#else
+/* On PPC32, we can use an unsigned comparison, as long
+   as  HEAP_IMAGE_BASE+PURESPACE_RESERVE is greater than
+   the maximum possible allocation (around 27 bits).
+   Decrementing allocptr may cause it to wrap around
+   #x80000000, but it should never wrap around 0. */
+/* twllt allocptr,allocbase */
+#define ALLOC_TRAP_INSTRUCTION 0x7c495008
+#endif
+
+#ifdef PPC64
+/* tdlgei allocptr,0 */
+#define GC_TRAP_INSTRUCTION 0x08a90000
+#else
+/* twlgei allocptr,0 */
+#define GC_TRAP_INSTRUCTION 0x0ca90000
+#endif
+
+#ifdef PPC64
+/* clrrdi allocptr,allocptr,4 */
+#define UNTAG_ALLOCPTR_INSTRUCTION 0x792906e4
+#else
+/* clrrwi allocptr,allocptr,3 */
+#define UNTAG_ALLOCPTR_INSTRUCTION 0x55290038
+#endif
+
+#ifdef PPC64
+/* std rX,misc_header_offset(allocptr) */
+#define STORE_HEADER_ALLOCPTR_INSTRUCTION 0xf809fff4
+#else
+/* stw rX,misc_header_offset(allocptr) */
+#define STORE_HEADER_ALLOCPTR_INSTRUCTION 0x9009fffa
+#endif
+#define STORE_HEADER_ALLOCPTR_MASK D_RA_IMM_MASK
+
+#ifdef PPC64
+/* std rX,cons.cXr(allocptr) */
+#define STORE_CAR_ALLOCPTR_INSTRUCTION 0xf8090004
+#define STORE_CDR_ALLOCPTR_INSTRUCTION 0xf809fffc
+#else
+/* stw rX,cons.cXr(allocptr) */
+#define STORE_CAR_ALLOCPTR_INSTRUCTION 0x90090003
+#define STORE_CDR_ALLOCPTR_INSTRUCTION 0x9009ffff
+#endif
+#define STORE_CXR_ALLOCPTR_MASK D_RA_IMM_MASK
+
+
+#ifdef PPC64
+/* stdu sp,-32(sp) */
+#define CREATE_LISP_FRAME_INSTRUCTION 0xf821ffe1
+#else
+/* stwu sp,-16(sp) */
+#define CREATE_LISP_FRAME_INSTRUCTION 0x9421fff0
+#endif
+
+#ifdef PPC64
+/* std tsp,tsp_frame.type(tsp) */
+#define MARK_TSP_FRAME_INSTRUCTION 0xf98c0008
+#else
+/* stw tsp,tsp_frame.type(tsp) */
+#define MARK_TSP_FRAME_INSTRUCTION 0x918c0004
+#endif
+
+#ifdef PPC64
+#define INIT_CATCH_FRAME_INSTRUCTION (0xf8000000 | RA(nargs))
+#define INIT_CATCH_FRAME_MASK (OP_MASK | RA_MASK)
+#else
+#define INIT_CATCH_FRAME_INSTRUCTION (0x90000000 | RA(nargs))
+#define INIT_CATCH_FRAME_MASK (OP_MASK | RA_MASK)
+#endif
+
+OSStatus
+handle_error(ExceptionInformation *, unsigned, unsigned, unsigned, pc);
+
+typedef char* vector_buf;
+
+void put_altivec_registers(vector_buf);
+void get_altivec_registers(vector_buf);
+
+
+int altivec_available;
+
+#ifdef DARWIN
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/machine/thread_state.h>
+#include <mach/machine/thread_status.h>
+
+#endif
+
+/* Yet another way to look at a branch instruction ... */
+typedef union {
+  struct {unsigned op:6, li:24, aa:1, lk:1;} b;
+  unsigned opcode;
+} branch_instruction;
+
+
+
+  /* Enable exceptions (at least, enable another thread's attempts to
+     suspend this one) by restoring the signal mask.
+  */
+
+
+
+#ifdef DARWIN
+#define SIGNAL_FOR_PROCESS_INTERRUPT SIGUSR1
+#endif
+#ifdef LINUX
+#define SIGNAL_FOR_PROCESS_INTERRUPT SIGPWR
+#endif
+
+
+#ifdef LINUX
+register void *current_r2 __asm__("r2");
+#endif
+
+Boolean
+extend_tcr_tlb(TCR *, ExceptionInformation *, unsigned, unsigned);
+
+void 
+pc_luser_xp(ExceptionInformation *, TCR *, signed_natural *);
+
+
+#ifdef PPC64
+#define codevec_hdr_p(value) ((value) == (('C'<<24)|('O'<<16)|('D'<<8)|'E'))
+#else
+/* top 6 bits will be zero, subtag will be subtag_code_vector */
+#define CV_HDR_MASK     (OP_MASK | subtagmask)
+#define CV_HDR_VALUE    subtag_code_vector
+#define codevec_hdr_p(value)	(((value) & CV_HDR_MASK) == CV_HDR_VALUE)
+#endif
+
+
Index: /branches/new-random/lisp-kernel/ppc-gc.c
===================================================================
--- /branches/new-random/lisp-kernel/ppc-gc.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-gc.c	(revision 13309)
@@ -0,0 +1,2370 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp_globals.h"
+#include "bits.h"
+#include "gc.h"
+#include "area.h"
+#include "Threads.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+/* Heap sanity checking. */
+
+void
+check_node(LispObj n)
+{
+  int tag = fulltag_of(n), header_tag;
+  area *a;
+  LispObj header;
+
+  switch (tag) {
+  case fulltag_even_fixnum:
+  case fulltag_odd_fixnum:
+
+
+#ifdef PPC64
+  case fulltag_imm_0:
+  case fulltag_imm_1:
+  case fulltag_imm_2:
+  case fulltag_imm_3:
+#else
+  case fulltag_imm:
+#endif
+
+
+    return;
+
+#ifndef PPC64
+  case fulltag_nil:
+    if (n != lisp_nil) {
+      Bug(NULL,"Object tagged as nil, not nil : 0x%08x", n);
+    }
+    return;
+#endif
+
+
+#ifdef PPC64
+  case fulltag_nodeheader_0: 
+  case fulltag_nodeheader_1: 
+  case fulltag_nodeheader_2: 
+  case fulltag_nodeheader_3: 
+  case fulltag_immheader_0: 
+  case fulltag_immheader_1: 
+  case fulltag_immheader_2: 
+  case fulltag_immheader_3: 
+#else
+  case fulltag_nodeheader:
+  case fulltag_immheader:
+#endif
+
+
+    Bug(NULL, "Header not expected : 0x%lx", n);
+    return;
+
+  case fulltag_misc:
+  case fulltag_cons:
+    a = heap_area_containing((BytePtr)ptr_from_lispobj(n));
+    
+    if (a == NULL) {
+      /* Can't do as much sanity checking as we'd like to
+         if object is a defunct stack-consed object.
+         If a dangling reference to the heap, that's
+         bad .. */
+      a = active_dynamic_area;
+      if ((n > (ptr_to_lispobj(a->active))) &&
+          (n < (ptr_to_lispobj(a->high)))) {
+        Bug(NULL, "Node points to heap free space: 0x%lx", n);
+      }
+      return;
+    }
+    break;
+  }
+  /* Node points to heap area, so check header/lack thereof. */
+  header = header_of(n);
+  header_tag = fulltag_of(header);
+  if (tag == fulltag_cons) {
+    if ((nodeheader_tag_p(header_tag)) ||
+        (immheader_tag_p(header_tag))) {
+      Bug(NULL, "Cons cell at 0x%lx has bogus header : 0x%lx", n, header);
+    }
+    return;
+  }
+
+  if ((!nodeheader_tag_p(header_tag)) &&
+      (!immheader_tag_p(header_tag))) {
+    Bug(NULL,"Vector at 0x%lx has bogus header : 0x%lx", n, header);
+  }
+  return;
+}
+
+
+
+
+void
+check_range(LispObj *start, LispObj *end, Boolean header_allowed)
+{
+  LispObj node, *current = start, *prev = NULL;
+  int tag;
+  natural elements;
+
+  while (current < end) {
+    prev = current;
+    node = *current++;
+    tag = fulltag_of(node);
+    if (immheader_tag_p(tag)) {
+      if (! header_allowed) {
+        Bug(NULL, "Header not expected at 0x%lx\n", prev);
+      }
+      current = (LispObj *)skip_over_ivector((natural)prev, node);
+    } else if (nodeheader_tag_p(tag)) {
+      if (! header_allowed) {
+        Bug(NULL, "Header not expected at 0x%lx\n", prev);
+      }
+      elements = header_element_count(node) | 1;
+      while (elements--) {
+        check_node(*current++);
+      }
+    } else {
+      check_node(node);
+      check_node(*current++);
+    }
+  }
+
+  if (current != end) {
+    Bug(NULL, "Overran end of memory range: start = 0x%08x, end = 0x%08x, prev = 0x%08x, current = 0x%08x",
+        start, end, prev, current);
+  }
+}
+
+void
+check_all_areas(TCR *tcr)
+{
+  area *a = active_dynamic_area;
+  area_code code = a->code;
+
+  while (code != AREA_VOID) {
+    switch (code) {
+    case AREA_DYNAMIC:
+    case AREA_STATIC:
+    case AREA_MANAGED_STATIC:
+      check_range((LispObj *)a->low, (LispObj *)a->active, true);
+      break;
+
+    case AREA_VSTACK:
+      {
+        LispObj* low = (LispObj *)a->active;
+        LispObj* high = (LispObj *)a->high;
+        
+        if (((natural)low) & node_size) {
+          check_node(*low++);
+        }
+        check_range(low, high, false);
+      }
+      break;
+
+    case AREA_TSTACK:
+      {
+        LispObj *current, *next,
+                *start = (LispObj *) a->active,
+                *end = start,
+                *limit = (LispObj *) a->high;
+                 
+        for (current = start;
+             end != limit;
+             current = next) {
+          next = ptr_from_lispobj(*current);
+          end = ((next >= start) && (next < limit)) ? next : limit;
+          if (current[1] == 0) {
+            check_range(current+2, end, true);
+          }
+        }
+      }
+      break;
+    }
+    a = a->succ;
+    code = (a->code);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+/* Sooner or later, this probably wants to be in assembler */
+/* Return false if n is definitely not an ephemeral node, true if
+   it might be */
+void
+mark_root(LispObj n)
+{
+  int tag_n = fulltag_of(n);
+  natural dnode, bits, *bitsp, mask;
+
+  if (!is_node_fulltag(tag_n)) {
+    return;
+  }
+
+  dnode = gc_area_dnode(n);
+  if (dnode >= GCndnodes_in_area) {
+    return;
+  }
+  set_bits_vars(GCmarkbits,dnode,bitsp,bits,mask);
+  if (bits & mask) {
+    return;
+  }
+  *bitsp = (bits | mask);
+
+  if (tag_n == fulltag_cons) {
+    cons *c = (cons *) ptr_from_lispobj(untag(n));
+    rmark(c->car);
+    rmark(c->cdr);
+    return;
+  }
+  {
+    LispObj *base = (LispObj *) ptr_from_lispobj(untag(n));
+    natural
+      header = *((natural *) base),
+      subtag = header_subtag(header),
+      element_count = header_element_count(header),
+      total_size_in_bytes,      /* including 4/8-byte header */
+      suffix_dnodes;
+    tag_n = fulltag_of(header);
+
+
+#ifdef PPC64
+    if ((nodeheader_tag_p(tag_n)) ||
+        (tag_n == ivector_class_64_bit)) {
+      total_size_in_bytes = 8 + (element_count<<3);
+    } else if (tag_n == ivector_class_8_bit) {
+      total_size_in_bytes = 8 + element_count;
+    } else if (tag_n == ivector_class_32_bit) {
+      total_size_in_bytes = 8 + (element_count<<2);
+    } else {
+      /* ivector_class_other_bit contains 16-bit arrays & bitvector */
+      if (subtag == subtag_bit_vector) {
+        total_size_in_bytes = 8 + ((element_count+7)>>3);
+      } else {
+        total_size_in_bytes = 8 + (element_count<<1);
+      }
+    }
+#else
+    if ((tag_n == fulltag_nodeheader) ||
+        (subtag <= max_32_bit_ivector_subtag)) {
+      total_size_in_bytes = 4 + (element_count<<2);
+    } else if (subtag <= max_8_bit_ivector_subtag) {
+      total_size_in_bytes = 4 + element_count;
+    } else if (subtag <= max_16_bit_ivector_subtag) {
+      total_size_in_bytes = 4 + (element_count<<1);
+    } else if (subtag == subtag_double_float_vector) {
+      total_size_in_bytes = 8 + (element_count<<3);
+    } else {
+      total_size_in_bytes = 4 + ((element_count+7)>>3);
+    }
+#endif
+
+
+
+    suffix_dnodes = ((total_size_in_bytes+(dnode_size-1))>>dnode_shift) -1;
+
+    if (suffix_dnodes) {
+      set_n_bits(GCmarkbits, dnode+1, suffix_dnodes);
+    }
+
+    if (nodeheader_tag_p(tag_n)) {
+      if (subtag == subtag_hash_vector) {
+        /* Don't invalidate the cache here.  It should get
+           invalidated on the lisp side, if/when we know
+           that rehashing is necessary. */
+        LispObj flags = ((hash_table_vector_header *) base)->flags;
+
+        if (flags & nhash_weak_mask) {
+          ((hash_table_vector_header *) base)->cache_key = undefined;
+          ((hash_table_vector_header *) base)->cache_value = lisp_nil;
+          mark_weak_htabv(n);
+	  return;
+	}
+      }
+
+      if (subtag == subtag_pool) {
+        deref(ptr_to_lispobj(base), 1) = lisp_nil;
+      }
+      
+      if (subtag == subtag_weak) {
+        natural weak_type = (natural) base[2];
+        if (weak_type >> population_termination_bit) {
+          element_count -= 2;
+        } else {
+          element_count -= 1;
+        }
+      }
+
+      base += (1+element_count);
+
+
+      while(element_count--) {
+        rmark(*--base);
+      }
+      if (subtag == subtag_weak) {
+        deref(ptr_to_lispobj(base),1) = GCweakvll;
+        GCweakvll = n;
+      }
+    }
+  }
+}
+
+
+/* 
+  This marks the node if it needs to; it returns true if the node
+  is either a hash table vector header or a cons/misc-tagged pointer
+  to ephemeral space.
+  Note that it  might be a pointer to ephemeral space even if it's
+  not pointing to the current generation.
+*/
+
+Boolean
+mark_ephemeral_root(LispObj n)
+{
+  int tag_n = fulltag_of(n);
+  natural eph_dnode;
+
+  if (nodeheader_tag_p(tag_n)) {
+    return (header_subtag(n) == subtag_hash_vector);
+  }
+ 
+  if ((tag_n == fulltag_cons) ||
+      (tag_n == fulltag_misc)) {
+    eph_dnode = area_dnode(n, GCephemeral_low);
+    if (eph_dnode < GCn_ephemeral_dnodes) {
+      mark_root(n);             /* May or may not mark it */
+      return true;              /* but return true 'cause it's an ephemeral node */
+    }
+  }
+  return false;                 /* Not a heap pointer or not ephemeral */
+}
+  
+
+#ifdef PPC64
+/* Any register (srr0, the lr or ctr) or stack location that
+   we're calling this on should have its low 2 bits clear; it'll
+   be tagged as a "primary" object, but the pc/lr/ctr should
+   never point to a tagged object or contain a fixnum.
+   
+   If the "pc" appears to be pointing into a heap-allocated
+   code vector that's not yet marked, back up until we find
+   the code-vector's prefix (the 32-bit word containing the
+   value 'CODE' whic precedes the code-vector's first instruction)
+   and mark the entire code-vector.
+*/
+void
+mark_pc_root(LispObj xpc)
+{
+  if ((xpc & 3) != 0) {
+    Bug(NULL, "Bad PC locative!");
+  } else {
+    natural dnode = gc_area_dnode(xpc);
+    if ((dnode < GCndnodes_in_area) &&
+        !ref_bit(GCmarkbits,dnode)) {
+      LispObj
+        *headerP,
+        header;
+      opcode *program_counter;
+
+      for(program_counter=(opcode *)ptr_from_lispobj(xpc & ~7);
+	  (LispObj)program_counter >= GCarealow;
+          program_counter-=2) {
+        if (*program_counter == PPC64_CODE_VECTOR_PREFIX) {
+          headerP = ((LispObj *)program_counter)-1;
+          header = *headerP;
+	  dnode = gc_area_dnode(headerP);
+          set_n_bits(GCmarkbits, dnode, (8+(header_element_count(header)<<2)+(dnode_size-1))>>dnode_shift);
+          return;
+        }
+      }
+      /*
+        Expected to have found a header by now, but didn't.
+        That's a bug.
+        */
+      Bug(NULL, "code_vector header not found!");
+    }
+  }
+}
+#else /* PPC64 */
+/*
+  Some objects (saved LRs on the control stack, the LR, PC, and CTR
+  in exception frames) may be tagged as fixnums but are really
+  locatives into code_vectors.
+
+  If "pc" is not tagged as a fixnum, mark it as a "normal" root.
+  If "pc" doesn't point at an unmarked doubleword in the area
+  being GCed, return.
+  Else back up until the code_vector's header is found and mark
+  all doublewords in the code_vector.
+*/
+void
+mark_pc_root(LispObj pc)
+{
+  if (tag_of(pc) != tag_fixnum) {
+    mark_root(pc);
+  } else {
+    natural dnode = gc_area_dnode(pc);
+    if ((dnode < GCndnodes_in_area) &&
+        !ref_bit(GCmarkbits,dnode)) {
+      LispObj
+        *headerP,
+        header;
+
+      for(headerP = (LispObj*)ptr_from_lispobj(untag(pc));
+          dnode < GCndnodes_in_area;
+          headerP-=2, --dnode) {
+        header = *headerP;
+
+        if ((header & code_header_mask) == subtag_code_vector) {
+          set_n_bits(GCmarkbits, dnode, (2+header_element_count(header))>>1);
+          return;
+        }
+      }
+      /*
+        Expected to have found a header by now, but didn't.
+        That's a bug.
+        */
+      Bug(NULL, "code_vector header not found!");
+    }
+  }
+}
+#endif /* PPC64 */
+
+
+
+#ifdef PPC64
+#define RMARK_PREV_ROOT fulltag_imm_3
+#define RMARK_PREV_CAR fulltag_misc
+#else
+#define RMARK_PREV_ROOT fulltag_imm
+#define RMARK_PREV_CAR fulltag_nil
+#endif
+
+
+
+
+
+/*
+  This wants to be in assembler even more than "mark_root" does.
+  For now, it does link-inversion: hard as that is to express in C,
+  reliable stack-overflow detection may be even harder ...
+*/
+void
+rmark(LispObj n)
+{
+  int tag_n = fulltag_of(n);
+  bitvector markbits = GCmarkbits;
+  natural dnode, bits, *bitsp, mask;
+
+  if (!is_node_fulltag(tag_n)) {
+    return;
+  }
+
+  dnode = gc_area_dnode(n);
+  if (dnode >= GCndnodes_in_area) {
+    return;
+  }
+  set_bits_vars(markbits,dnode,bitsp,bits,mask);
+  if (bits & mask) {
+    return;
+  }
+  *bitsp = (bits | mask);
+
+  if (current_stack_pointer() > GCstack_limit) {
+    if (tag_n == fulltag_cons) {
+      rmark(deref(n,1));
+      rmark(deref(n,0));
+    } else {
+      LispObj *base = (LispObj *) ptr_from_lispobj(untag(n));
+      natural
+        header = *((natural *) base),
+        subtag = header_subtag(header),
+        element_count = header_element_count(header),
+        total_size_in_bytes,
+        suffix_dnodes;
+      tag_n = fulltag_of(header);
+#ifdef PPC64
+      if ((nodeheader_tag_p(tag_n)) ||
+          (tag_n == ivector_class_64_bit)) {
+        total_size_in_bytes = 8 + (element_count<<3);
+      } else if (tag_n == ivector_class_8_bit) {
+        total_size_in_bytes = 8 + element_count;
+      } else if (tag_n == ivector_class_32_bit) {
+        total_size_in_bytes = 8 + (element_count<<2);
+      } else {
+        /* ivector_class_other_bit contains 16-bit arrays & bitvector */
+        if (subtag == subtag_bit_vector) {
+          total_size_in_bytes = 8 + ((element_count+7)>>3);
+        } else {
+          total_size_in_bytes = 8 + (element_count<<1);
+        }
+      }
+#else
+      if ((tag_n == fulltag_nodeheader) ||
+          (subtag <= max_32_bit_ivector_subtag)) {
+        total_size_in_bytes = 4 + (element_count<<2);
+      } else if (subtag <= max_8_bit_ivector_subtag) {
+        total_size_in_bytes = 4 + element_count;
+      } else if (subtag <= max_16_bit_ivector_subtag) {
+        total_size_in_bytes = 4 + (element_count<<1);
+      } else if (subtag == subtag_double_float_vector) {
+        total_size_in_bytes = 8 + (element_count<<3);
+      } else {
+        total_size_in_bytes = 4 + ((element_count+7)>>3);
+      }
+#endif
+
+
+      suffix_dnodes = ((total_size_in_bytes+(dnode_size-1))>>dnode_shift)-1;
+
+      if (suffix_dnodes) {
+        set_n_bits(GCmarkbits, dnode+1, suffix_dnodes);
+      }
+
+      if (!nodeheader_tag_p(tag_n)) return;
+
+      if (subtag == subtag_hash_vector) {
+        /* Splice onto weakvll, then return */
+        /* In general, there's no reason to invalidate the cached
+           key/value pair here.  However, if the hash table's weak,
+           we don't want to retain an otherwise unreferenced key
+           or value simply because they're referenced from the
+           cache.  Clear the cached entries iff the hash table's
+           weak in some sense.
+        */
+        LispObj flags = ((hash_table_vector_header *) base)->flags;
+
+        if ((flags & nhash_keys_frozen_mask) &&
+            (((hash_table_vector_header *) base)->deleted_count > 0)) {
+          /* We're responsible for clearing out any deleted keys, since
+             lisp side can't do it without breaking the state machine
+          */
+          LispObj *pairp = base + hash_table_vector_header_count;
+          natural
+            npairs = (element_count - (hash_table_vector_header_count - 1)) >> 1;
+
+          while (npairs--) {
+            if ((pairp[1] == unbound) && (pairp[0] != unbound)) {
+              pairp[0] = slot_unbound;
+            }
+            pairp +=2;
+          }
+          ((hash_table_vector_header *) base)->deleted_count = 0;
+        }
+
+
+        if (flags & nhash_weak_mask) {
+          ((hash_table_vector_header *) base)->cache_key = undefined;
+          ((hash_table_vector_header *) base)->cache_value = lisp_nil;
+	  mark_weak_htabv(n);
+	  return;
+	}
+      }
+
+      if (subtag == subtag_pool) {
+        deref(n, 1) = lisp_nil;
+      }
+
+      if (subtag == subtag_weak) {
+        natural weak_type = (natural) base[2];
+        if (weak_type >> population_termination_bit)
+          element_count -= 2;
+        else
+          element_count -= 1;
+      }
+      while (element_count) {
+        rmark(deref(n,element_count));
+        element_count--;
+      }
+
+      if (subtag == subtag_weak) {
+        deref(n, 1) = GCweakvll;
+        GCweakvll = n;
+      }
+
+    }
+  } else {
+    LispObj prev = undefined;
+    LispObj this = n, next;
+    /*
+      This is an FSM.  The basic states are:
+      (0) Just marked the cdr of a cons; mark the car next;
+      (1) Just marked the car of a cons; back up.
+      (2) Hit a gvector header.  Back up.
+      (3) Marked a gvector element; mark the preceding one.
+      (4) Backed all the way up to the object that got us here.
+      
+      This is all encoded in the fulltag of the "prev" pointer.
+    */
+
+    if (tag_n == fulltag_cons) goto MarkCons;
+    goto MarkVector;
+
+  ClimbCdr:
+    prev = deref(this,0);
+    deref(this,0) = next;
+
+  Climb:
+    next = this;
+    this = prev;
+    tag_n = fulltag_of(prev);
+    switch(tag_n) {
+    case fulltag_odd_fixnum:
+    case fulltag_even_fixnum:
+      goto ClimbVector;
+
+    case RMARK_PREV_ROOT:
+      return;
+
+    case fulltag_cons:
+      goto ClimbCdr;
+
+    case RMARK_PREV_CAR:
+      goto ClimbCar;
+
+      /* default: abort() */
+    }
+
+  DescendCons:
+    prev = this;
+    this = next;
+
+  MarkCons:
+    next = deref(this,1);
+    this += node_size;
+    tag_n = fulltag_of(next);
+    if (!is_node_fulltag(tag_n)) goto MarkCdr;
+    dnode = gc_area_dnode(next);
+    if (dnode >= GCndnodes_in_area) goto MarkCdr;
+    set_bits_vars(markbits,dnode,bitsp,bits,mask);
+    if (bits & mask) goto MarkCdr;
+    *bitsp = (bits | mask);
+    deref(this,1) = prev;
+    if (tag_n == fulltag_cons) goto DescendCons;
+    goto DescendVector;
+
+  ClimbCar:
+    prev = deref(this,1);
+    deref(this,1) = next;
+
+  MarkCdr:
+    next = deref(this, 0);
+    this -= node_size;
+    tag_n = fulltag_of(next);
+    if (!is_node_fulltag(tag_n)) goto Climb;
+    dnode = gc_area_dnode(next);
+    if (dnode >= GCndnodes_in_area) goto Climb;
+    set_bits_vars(markbits,dnode,bitsp,bits,mask);
+    if (bits & mask) goto Climb;
+    *bitsp = (bits | mask);
+    deref(this, 0) = prev;
+    if (tag_n == fulltag_cons) goto DescendCons;
+    /* goto DescendVector; */
+
+  DescendVector:
+    prev = this;
+    this = next;
+
+  MarkVector:
+    {
+      LispObj *base = (LispObj *) ptr_from_lispobj(untag(this));
+      natural
+        header = *((natural *) base),
+        subtag = header_subtag(header),
+        element_count = header_element_count(header),
+        total_size_in_bytes,
+        suffix_dnodes;
+
+      tag_n = fulltag_of(header);
+
+#ifdef PPC64
+      if ((nodeheader_tag_p(tag_n)) ||
+          (tag_n == ivector_class_64_bit)) {
+        total_size_in_bytes = 8 + (element_count<<3);
+      } else if (tag_n == ivector_class_8_bit) {
+        total_size_in_bytes = 8 + element_count;
+      } else if (tag_n == ivector_class_32_bit) {
+        total_size_in_bytes = 8 + (element_count<<2);
+      } else {
+        /* ivector_class_other_bit contains 16-bit arrays & bitvector */
+        if (subtag == subtag_bit_vector) {
+          total_size_in_bytes = 8 + ((element_count+7)>>3);
+        } else {
+          total_size_in_bytes = 8 + (element_count<<1);
+        }
+      }
+#else
+      if ((tag_n == fulltag_nodeheader) ||
+          (subtag <= max_32_bit_ivector_subtag)) {
+        total_size_in_bytes = 4 + (element_count<<2);
+      } else if (subtag <= max_8_bit_ivector_subtag) {
+        total_size_in_bytes = 4 + element_count;
+      } else if (subtag <= max_16_bit_ivector_subtag) {
+        total_size_in_bytes = 4 + (element_count<<1);
+      } else if (subtag == subtag_double_float_vector) {
+        total_size_in_bytes = 8 + (element_count<<3);
+      } else {
+        total_size_in_bytes = 4 + ((element_count+7)>>3);
+      }
+#endif
+
+
+      suffix_dnodes = ((total_size_in_bytes+(dnode_size-1))>>dnode_shift)-1;
+
+      if (suffix_dnodes) {
+        set_n_bits(GCmarkbits, dnode+1, suffix_dnodes);
+      }
+
+      if (!nodeheader_tag_p(tag_n)) goto Climb;
+
+      if (subtag == subtag_hash_vector) {
+        /* Splice onto weakvll, then climb */
+        LispObj flags = ((hash_table_vector_header *) base)->flags;
+
+        if (flags & nhash_weak_mask) {
+          ((hash_table_vector_header *) base)->cache_key = undefined;
+          ((hash_table_vector_header *) base)->cache_value = lisp_nil;
+	  dws_mark_weak_htabv(this);
+	  element_count = hash_table_vector_header_count;
+	}
+      }
+
+      if (subtag == subtag_pool) {
+        deref(this, 1) = lisp_nil;
+      }
+
+      if (subtag == subtag_weak) {
+        natural weak_type = (natural) base[2];
+        if (weak_type >> population_termination_bit)
+          element_count -= 2;
+        else
+          element_count -= 1;
+      }
+
+      this = untag(this) + ((element_count+1) << node_shift);
+      goto MarkVectorLoop;
+    }
+
+  ClimbVector:
+    prev = *((LispObj *) ptr_from_lispobj(this));
+    *((LispObj *) ptr_from_lispobj(this)) = next;
+
+  MarkVectorLoop:
+    this -= node_size;
+    next = *((LispObj *) ptr_from_lispobj(this));
+    tag_n = fulltag_of(next);
+    if (nodeheader_tag_p(tag_n)) goto MarkVectorDone;
+    if (!is_node_fulltag(tag_n)) goto MarkVectorLoop;
+    dnode = gc_area_dnode(next);
+    if (dnode >= GCndnodes_in_area) goto MarkVectorLoop;
+    set_bits_vars(markbits,dnode,bitsp,bits,mask);
+    if (bits & mask) goto MarkVectorLoop;
+    *bitsp = (bits | mask);
+    *(ptr_from_lispobj(this)) = prev;
+    if (tag_n == fulltag_cons) goto DescendCons;
+    goto DescendVector;
+
+  MarkVectorDone:
+    /* "next" is vector header; "this" is fixnum-aligned.
+       If  header subtag = subtag_weak_header, put it on weakvll */
+    this += fulltag_misc;
+
+    if (header_subtag(next) == subtag_weak) {
+      deref(this, 1) = GCweakvll;
+      GCweakvll = this;
+    }
+    goto Climb;
+  }
+}
+
+LispObj *
+skip_over_ivector(natural start, LispObj header)
+{
+  natural 
+    element_count = header_element_count(header),
+    subtag = header_subtag(header),
+    nbytes;
+
+#ifdef PPC64
+  switch (fulltag_of(header)) {
+  case ivector_class_64_bit:
+    nbytes = element_count << 3;
+    break;
+  case ivector_class_32_bit:
+    nbytes = element_count << 2;
+    break;
+  case ivector_class_8_bit:
+    nbytes = element_count;
+    break;
+  case ivector_class_other_bit:
+  default:
+    if (subtag == subtag_bit_vector) {
+      nbytes = (element_count+7)>>3;
+    } else {
+      nbytes = element_count << 1;
+    }
+  }
+  return ptr_from_lispobj(start+(~15 & (nbytes + 8 + 15)));
+#else
+  if (subtag <= max_32_bit_ivector_subtag) {
+    nbytes = element_count << 2;
+  } else if (subtag <= max_8_bit_ivector_subtag) {
+    nbytes = element_count;
+  } else if (subtag <= max_16_bit_ivector_subtag) {
+    nbytes = element_count << 1;
+  } else if (subtag == subtag_double_float_vector) {
+    nbytes = 4 + (element_count << 3);
+  } else {
+    nbytes = (element_count+7) >> 3;
+  }
+  return ptr_from_lispobj(start+(~7 & (nbytes + 4 + 7)));
+#endif
+
+
+
+}
+
+
+void
+check_refmap_consistency(LispObj *start, LispObj *end, bitvector refbits)
+{
+  LispObj x1, *base = start;
+  int tag;
+  natural ref_dnode, node_dnode;
+  Boolean intergen_ref;
+
+  while (start < end) {
+    x1 = *start;
+    tag = fulltag_of(x1);
+    if (immheader_tag_p(tag)) {
+      start = skip_over_ivector(ptr_to_lispobj(start), x1);
+    } else {
+      intergen_ref = false;
+      if ((tag == fulltag_misc) || (tag == fulltag_cons)) {        
+        node_dnode = gc_area_dnode(x1);
+        if (node_dnode < GCndnodes_in_area) {
+          intergen_ref = true;
+        }
+      }
+      if (intergen_ref == false) {        
+        x1 = start[1];
+        tag = fulltag_of(x1);
+        if ((tag == fulltag_misc) || (tag == fulltag_cons)) {
+          node_dnode = gc_area_dnode(x1);
+          if (node_dnode < GCndnodes_in_area) {
+            intergen_ref = true;
+          }
+        }
+      }
+      if (intergen_ref) {
+        ref_dnode = area_dnode(start, base);
+        if (!ref_bit(refbits, ref_dnode)) {
+          Bug(NULL, "Missing memoization in doublenode at 0x" LISP, start);
+          set_bit(refbits, ref_dnode);
+        }
+      }
+      start += 2;
+    }
+  }
+}
+
+
+
+void
+mark_memoized_area(area *a, natural num_memo_dnodes)
+{
+  bitvector refbits = a->refbits;
+  LispObj *p = (LispObj *) a->low, x1, x2;
+  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
+  Boolean keep_x1, keep_x2;
+
+  if (GCDebug) {
+    check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
+  }
+
+  /* The distinction between "inbits" and "outbits" is supposed to help us
+     detect cases where "uninteresting" setfs have been memoized.  Storing
+     NIL, fixnums, immediates (characters, etc.) or node pointers to static
+     or readonly areas is definitely uninteresting, but other cases are
+     more complicated (and some of these cases are hard to detect.)
+
+     Some headers are "interesting", to the forwarder if not to us. 
+
+     We -don't- give anything any weak treatment here.  Weak things have
+     to be seen by a full gc, for some value of 'full'.
+     */
+
+  /*
+    We need to ensure that there are no bits set at or beyond
+    "num_memo_dnodes" in the bitvector.  (This can happen as the EGC
+    tenures/untenures things.)  We find bits by grabbing a fullword at
+    a time and doing a cntlzw instruction; and don't want to have to
+    check for (< memo_dnode num_memo_dnodes) in the loop.
+    */
+
+  {
+    natural 
+      bits_in_last_word = (num_memo_dnodes & bitmap_shift_count_mask),
+      index_of_last_word = (num_memo_dnodes >> bitmap_shift);
+
+    if (bits_in_last_word != 0) {
+      natural mask = ~((1L<<(nbits_in_word-bits_in_last_word))-1L);
+      refbits[index_of_last_word] &= mask;
+    }
+  }
+        
+  set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
+  inbits = outbits = bits;
+  while (memo_dnode < num_memo_dnodes) {
+    if (bits == 0) {
+      int remain = nbits_in_word - bitidx;
+      memo_dnode += remain;
+      p += (remain+remain);
+      if (outbits != inbits) {
+        *bitsp = outbits;
+      }
+      bits = *++bitsp;
+      inbits = outbits = bits;
+      bitidx = 0;
+    } else {
+      nextbit = count_leading_zeros(bits);
+      if ((diff = (nextbit - bitidx)) != 0) {
+        memo_dnode += diff;
+        bitidx = nextbit;
+        p += (diff+diff);
+      }
+      x1 = *p++;
+      x2 = *p++;
+      bits &= ~(BIT0_MASK >> bitidx);
+      keep_x1 = mark_ephemeral_root(x1);
+      keep_x2 = mark_ephemeral_root(x2);
+      if ((keep_x1 == false) && 
+          (keep_x2 == false)) {
+        outbits &= ~(BIT0_MASK >> bitidx);
+      }
+      memo_dnode++;
+      bitidx++;
+    }
+  }
+  if (GCDebug) {
+    p = (LispObj *) a->low;
+    check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
+  }
+}
+
+
+
+void
+mark_simple_area_range(LispObj *start, LispObj *end)
+{
+  LispObj x1, *base;
+  int tag;
+
+  while (start < end) {
+    x1 = *start;
+    tag = fulltag_of(x1);
+    if (immheader_tag_p(tag)) {
+      start = (LispObj *)ptr_from_lispobj(skip_over_ivector(ptr_to_lispobj(start), x1));
+    } else if (!nodeheader_tag_p(tag)) {
+      ++start;
+      mark_root(x1);
+      mark_root(*start++);
+    } else {
+      int subtag = header_subtag(x1);
+      natural element_count = header_element_count(x1);
+      natural size = (element_count+1 + 1) & ~1;
+
+      if (subtag == subtag_hash_vector) {
+        LispObj flags = ((hash_table_vector_header *) start)->flags;
+
+        if (flags & nhash_weak_mask) {
+          ((hash_table_vector_header *) start)->cache_key = undefined;
+          ((hash_table_vector_header *) start)->cache_value = lisp_nil;
+	  mark_weak_htabv((LispObj)start);
+	  element_count = 0;
+	}
+      }
+      if (subtag == subtag_pool) {
+	start[1] = lisp_nil;
+      }
+
+      if (subtag == subtag_weak) {
+	natural weak_type = (natural) start[2];
+	if (weak_type >> population_termination_bit)
+	  element_count -= 2;
+	else
+	  element_count -= 1; 
+	start[1] = GCweakvll;
+	GCweakvll = (LispObj) (((natural) start) + fulltag_misc);    
+      }
+
+      base = start + element_count + 1;
+      while(element_count--) {
+	mark_root(*--base);
+      }   
+      start += size;
+    }
+  }
+}
+
+
+/* Mark a tstack area */
+void
+mark_tstack_area(area *a)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) (a->active),
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = (LispObj *) ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    if (current[1] == 0) {
+      mark_simple_area_range(current+2, end);
+    }
+  }
+}
+
+/*
+  It's really important that headers never wind up in tagged registers.
+  Those registers would (possibly) get pushed on the vstack and confuse
+  the hell out of this routine.
+
+  vstacks are just treated as a "simple area range", possibly with
+  an extra word at the top (where the area's active pointer points.)
+  */
+
+void
+mark_vstack_area(area *a)
+{
+  LispObj
+    *start = (LispObj *) a->active,
+    *end = (LispObj *) a->high;
+
+#if 0
+  fprintf(dbgout, "mark VSP range: 0x%lx:0x%lx\n", start, end);
+#endif
+  if (((natural)start) & (sizeof(natural))) {
+    /* Odd number of words.  Mark the first (can't be a header) */
+    mark_root(*start);
+    ++start;
+  }
+  mark_simple_area_range(start, end);
+}
+
+
+/*
+  Mark lisp frames on the control stack.
+  Ignore emulator frames (odd backpointer) and C frames (size != 4).
+*/
+
+void
+mark_cstack_area(area *a)
+{
+  BytePtr
+    current,
+    next,
+    limit = a->high,
+    low = a->low;
+
+  for (current = a->active; (current >= low) && (current < limit); current = next) {
+    next = *((BytePtr *)current);
+#if 0
+    if (next < current) {
+      Bug(NULL, "Child stack frame older than parent");
+    }
+#endif
+    if (next == NULL) break;
+    if (((next - current) == sizeof(lisp_frame)) &&
+	(((((lisp_frame *)current)->savefn) == 0) ||
+	 (fulltag_of(((lisp_frame *)current)->savefn) == fulltag_misc))) {
+      /* mark fn, then saved lr */
+      mark_root(((lisp_frame *)current)->savefn);
+      mark_pc_root(((lisp_frame *)current)->savelr);
+    } else {
+      /* Clear low 2 bits of "next", just in case */
+      next = (BytePtr) (((natural)next) & ~3);
+    }
+  }
+}
+
+
+
+/* Mark the lisp objects in an exception frame */
+void
+mark_xp(ExceptionInformation *xp)
+{
+  natural *regs = (natural *) xpGPRvector(xp);
+
+#ifdef PPC
+  int r;
+  /* registers >= fn should be tagged and marked as roots.
+     the PC, LR, loc_pc, and CTR should be treated as "pc_locatives".
+
+     In general, marking a locative is more expensive than marking
+     a node is, since it may be neccessary to back up and find the
+     containing object's header.  Since exception frames contain
+     many locatives, it'd be wise to mark them *after* marking the
+     stacks, nilreg-relative globals, etc.
+     */
+
+  for (r = fn; r < 32; r++) {
+    mark_root((regs[r]));
+  }
+
+
+
+  mark_pc_root((regs[loc_pc]));
+  mark_pc_root(ptr_to_lispobj(xpPC(xp)));
+  mark_pc_root(ptr_to_lispobj(xpLR(xp)));
+  mark_pc_root(ptr_to_lispobj(xpCTR(xp)));
+#endif /* PPC */
+
+}
+
+/* A "pagelet" contains 32 doublewords.  The relocation table contains
+   a word for each pagelet which defines the lowest address to which
+   dnodes on that pagelet will be relocated.
+
+   The relocation address of a given pagelet is the sum of the relocation
+   address for the preceding pagelet and the number of bytes occupied by
+   marked objects on the preceding pagelet.
+*/
+
+LispObj
+calculate_relocation()
+{
+  LispObj *relocptr = GCrelocptr;
+  LispObj current = GCareadynamiclow;
+  bitvector 
+    markbits = GCdynamic_markbits;
+  qnode *q = (qnode *) markbits;
+  natural npagelets = ((GCndynamic_dnodes_in_area+(nbits_in_word-1))>>bitmap_shift);
+  natural thesebits;
+  LispObj first = 0;
+
+  do {
+    *relocptr++ = current;
+    thesebits = *markbits++;
+    if (thesebits == ALL_ONES) {
+      current += nbits_in_word*dnode_size;
+      q += 4; /* sic */
+    } else {
+      if (!first) {
+        first = current;
+        while (thesebits & BIT0_MASK) {
+          first += dnode_size;
+          thesebits += thesebits;
+        }
+      }
+      current += one_bits(*q++);
+      current += one_bits(*q++);
+      current += one_bits(*q++);
+      current += one_bits(*q++);
+    }
+  } while(--npagelets);
+  *relocptr++ = current;
+  return first ? first : current;
+}
+
+#ifdef PPC64
+LispObj
+dnode_forwarding_address(natural dnode, int tag_n)
+{
+  natural pagelet, nbits;
+  unsigned int near_bits;
+  LispObj new;
+
+  if (GCDebug) {
+    if (! ref_bit(GCdynamic_markbits, dnode)) {
+      Bug(NULL, "unmarked object being forwarded!\n");
+    }
+  }
+
+  pagelet = dnode >> bitmap_shift;
+  nbits = dnode & bitmap_shift_count_mask;
+  near_bits = ((unsigned int *)GCdynamic_markbits)[dnode>>(dnode_shift+1)];
+
+  if (nbits < 32) {
+    new = GCrelocptr[pagelet] + tag_n;;
+    /* Increment "new" by the count of 1 bits which precede the dnode */
+    if (near_bits == 0xffffffff) {
+      return (new + (nbits << 4));
+    } else {
+      near_bits &= (0xffffffff00000000 >> nbits);
+      if (nbits > 15) {
+        new += one_bits(near_bits & 0xffff);
+      }
+      return (new + (one_bits(near_bits >> 16))); 
+    }
+  } else {
+    new = GCrelocptr[pagelet+1] + tag_n;
+    nbits = 64-nbits;
+
+    if (near_bits == 0xffffffff) {
+      return (new - (nbits << 4));
+    } else {
+      near_bits &= (1<<nbits)-1;
+      if (nbits > 15) {
+        new -= one_bits(near_bits >> 16);
+      }
+      return (new -  one_bits(near_bits & 0xffff));
+    }
+  }
+}
+#else
+LispObj
+dnode_forwarding_address(natural dnode, int tag_n)
+{
+  natural pagelet, nbits;
+  unsigned short near_bits;
+  LispObj new;
+
+  if (GCDebug) {
+    if (! ref_bit(GCdynamic_markbits, dnode)) {
+      Bug(NULL, "unmarked object being forwarded!\n");
+    }
+  }
+
+  pagelet = dnode >> 5;
+  nbits = dnode & 0x1f;
+  near_bits = ((unsigned short *)GCdynamic_markbits)[dnode>>4];
+
+  if (nbits < 16) {
+    new = GCrelocptr[pagelet] + tag_n;;
+    /* Increment "new" by the count of 1 bits which precede the dnode */
+    if (near_bits == 0xffff) {
+      return (new + (nbits << 3));
+    } else {
+      near_bits &= (0xffff0000 >> nbits);
+      if (nbits > 7) {
+        new += one_bits(near_bits & 0xff);
+      }
+      return (new + (one_bits(near_bits >> 8))); 
+    }
+  } else {
+    new = GCrelocptr[pagelet+1] + tag_n;
+    nbits = 32-nbits;
+
+    if (near_bits == 0xffff) {
+      return (new - (nbits << 3));
+    } else {
+      near_bits &= (1<<nbits)-1;
+      if (nbits > 7) {
+        new -= one_bits(near_bits >> 8);
+      }
+      return (new -  one_bits(near_bits & 0xff));
+    }
+  }
+}
+#endif
+
+
+LispObj
+locative_forwarding_address(LispObj obj)
+{
+  int tag_n = fulltag_of(obj);
+  natural dnode;
+
+
+#ifdef PPC
+  /* Locatives can be tagged as conses, "fulltag_misc"
+     objects, or as fixnums.  Immediates, headers, and nil
+     shouldn't be "forwarded".  Nil never will be, but it
+     doesn't hurt to check ... */
+#ifdef PPC64
+  if ((tag_n & lowtag_mask) != lowtag_primary) {
+    return obj;
+  }
+#else
+  if ((1<<tag_n) & ((1<<fulltag_immheader) |
+                    (1<<fulltag_nodeheader) |
+                    (1<<fulltag_imm) |
+                    (1<<fulltag_nil))) {
+    return obj;
+  }
+#endif
+#endif
+
+  dnode = gc_dynamic_area_dnode(obj);
+
+  if ((dnode >= GCndynamic_dnodes_in_area) ||
+      (obj < GCfirstunmarked)) {
+    return obj;
+  }
+
+  return dnode_forwarding_address(dnode, tag_n);
+}
+
+
+
+
+void
+forward_range(LispObj *range_start, LispObj *range_end)
+{
+  LispObj *p = range_start, node, new;
+  int tag_n;
+  natural nwords;
+  hash_table_vector_header *hashp;
+
+  while (p < range_end) {
+    node = *p;
+    tag_n = fulltag_of(node);
+    if (immheader_tag_p(tag_n)) {
+      p = (LispObj *) skip_over_ivector((natural) p, node);
+    } else if (nodeheader_tag_p(tag_n)) {
+      nwords = header_element_count(node);
+      nwords += (1 - (nwords&1));
+      if ((header_subtag(node) == subtag_hash_vector) &&
+          ((((hash_table_vector_header *)p)->flags) & nhash_track_keys_mask)) {
+        natural skip = (sizeof(hash_table_vector_header)/sizeof(LispObj))-1;
+        hashp = (hash_table_vector_header *) p;
+        p++;
+        nwords -= skip;
+        while(skip--) {
+          update_noderef(p);
+          p++;
+        }
+        /* "nwords" is odd at this point: there are (floor nwords 2)
+           key/value pairs to look at, and then an extra word for
+           alignment.  Process them two at a time, then bump "p"
+           past the alignment word. */
+        nwords >>= 1;
+        while(nwords--) {
+          if (update_noderef(p) && hashp) {
+            hashp->flags |= nhash_key_moved_mask;
+            hashp = NULL;
+          }
+          p++;
+          update_noderef(p);
+          p++;
+        }
+        *p++ = 0;
+      } else {
+        p++;
+        while(nwords--) {
+          update_noderef(p);
+          p++;
+        }
+      }
+    } else {
+      new = node_forwarding_address(node);
+      if (new != node) {
+        *p = new;
+      }
+      p++;
+      update_noderef(p);
+      p++;
+    }
+  }
+}
+
+
+
+
+/* Forward a tstack area */
+void
+forward_tstack_area(area *a)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) a->active,
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    if (current[1] == 0) {
+      forward_range(current+2, end);
+    }
+  }
+}
+
+/* Forward a vstack area */
+void
+forward_vstack_area(area *a)
+{
+  LispObj
+    *p = (LispObj *) a->active,
+    *q = (LispObj *) a->high;
+
+#ifdef DEBUG
+  fprintf(dbgout,"Forward range 0x%x/0x%x (owner 0x%x)\n",p,q,a->owner);
+#endif
+  if (((natural)p) & sizeof(natural)) {
+    update_noderef(p);
+    p++;
+  }
+  forward_range(p, q);
+}
+
+void
+forward_cstack_area(area *a)
+{
+  BytePtr
+    current,
+    next,
+    limit = a->high,
+    low = a->low;
+
+  for (current = a->active; (current >= low) && (current < limit); current = next) {
+    next = *((BytePtr *)current);
+    if (next == NULL) break;
+    if (((next - current) == sizeof(lisp_frame)) &&
+	(((((lisp_frame *)current)->savefn) == 0) ||
+	 (fulltag_of(((lisp_frame *)current)->savefn) == fulltag_misc))) {
+      update_noderef(&((lisp_frame *) current)->savefn);
+      update_locref(&((lisp_frame *) current)->savelr);
+    }
+  }
+}
+
+
+
+void
+forward_xp(ExceptionInformation *xp)
+{
+  natural *regs = (natural *) xpGPRvector(xp);
+
+  int r;
+
+  /* registers >= fn should be tagged and forwarded as roots.
+     the PC, LR, loc_pc, and CTR should be treated as "locatives".
+     */
+
+  for (r = fn; r < 32; r++) {
+    update_noderef((LispObj*) (&(regs[r])));
+  }
+
+  update_locref((LispObj*) (&(regs[loc_pc])));
+
+  update_locref((LispObj*) (&(xpPC(xp))));
+  update_locref((LispObj*) (&(xpLR(xp))));
+  update_locref((LispObj*) (&(xpCTR(xp))));
+
+}
+
+
+void
+forward_tcr_xframes(TCR *tcr)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+
+  xp = tcr->gc_context;
+  if (xp) {
+    forward_xp(xp);
+  }
+  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
+    if (xframes->curr == xp) {
+      Bug(NULL, "forward xframe twice ???");
+    }
+    forward_xp(xframes->curr);
+  }
+}
+
+
+
+/*
+  Compact the dynamic heap (from GCfirstunmarked through its end.)
+  Return the doublenode address of the new freeptr.
+  */
+
+LispObj
+compact_dynamic_heap()
+{
+  LispObj *src = ptr_from_lispobj(GCfirstunmarked), *dest = src, node, new;
+  natural 
+    elements, 
+    dnode = gc_area_dnode(GCfirstunmarked), 
+    node_dnodes = 0, 
+    imm_dnodes = 0, 
+    bitidx, 
+    *bitsp, 
+    bits, 
+    nextbit, 
+    diff;
+  int tag;
+  bitvector markbits = GCmarkbits;
+    /* keep track of whether or not we saw any
+       code_vector headers, and only flush cache if so. */
+  Boolean GCrelocated_code_vector = false;
+
+  if (dnode < GCndnodes_in_area) {
+    lisp_global(FWDNUM) += (1<<fixnum_shift);
+  
+    set_bitidx_vars(markbits,dnode,bitsp,bits,bitidx);
+    while (dnode < GCndnodes_in_area) {
+      if (bits == 0) {
+        int remain = nbits_in_word - bitidx;
+        dnode += remain;
+        src += (remain+remain);
+        bits = *++bitsp;
+        bitidx = 0;
+      } else {
+        /* Have a non-zero markbits word; all bits more significant
+           than "bitidx" are 0.  Count leading zeros in "bits"
+           (there'll be at least "bitidx" of them.)  If there are more
+           than "bitidx" leading zeros, bump "dnode", "bitidx", and
+           "src" by the difference. */
+        nextbit = count_leading_zeros(bits);
+        if ((diff = (nextbit - bitidx)) != 0) {
+          dnode += diff;
+          bitidx = nextbit;
+          src += (diff+diff);
+        }
+
+        if (GCDebug) {
+          if (dest != ptr_from_lispobj(locative_forwarding_address(ptr_to_lispobj(src)))) {
+            Bug(NULL, "Out of synch in heap compaction.  Forwarding from 0x%lx to 0x%lx,\n expected to go to 0x%lx\n", 
+                src, dest, locative_forwarding_address(ptr_to_lispobj(src)));
+          }
+        }
+
+        node = *src++;
+        tag = fulltag_of(node);
+        if (nodeheader_tag_p(tag)) {
+          elements = header_element_count(node);
+          node_dnodes = (elements+2)>>1;
+          dnode += node_dnodes;
+          if ((header_subtag(node) == subtag_hash_vector) &&
+              (((hash_table_vector_header *) (src-1))->flags & nhash_track_keys_mask)) {
+            hash_table_vector_header *hashp = (hash_table_vector_header *) dest;
+            int skip = (sizeof(hash_table_vector_header)/sizeof(LispObj))-1;
+          
+            *dest++ = node;
+            elements -= skip;
+            while(skip--) {
+              *dest++ = node_forwarding_address(*src++);
+            }
+            /* There should be an even number of (key/value) pairs in elements;
+               an extra alignment word follows. */
+            elements >>= 1;
+            while (elements--) {
+              if (hashp) {
+                node = *src++;
+                new = node_forwarding_address(node);
+                if (new != node) {
+                  hashp->flags |= nhash_key_moved_mask;
+                  hashp = NULL;
+                  *dest++ = new;
+                } else {
+                  *dest++ = node;
+                }
+              } else {
+                *dest++ = node_forwarding_address(*src++);
+              }
+              *dest++ = node_forwarding_address(*src++);
+            }
+            *dest++ = 0;
+            src++;
+          } else {
+            *dest++ = node;
+            *dest++ = node_forwarding_address(*src++);
+            while(--node_dnodes) {
+              *dest++ = node_forwarding_address(*src++);
+              *dest++ = node_forwarding_address(*src++);
+            }
+          }
+          set_bitidx_vars(markbits,dnode,bitsp,bits,bitidx);
+        } else if (immheader_tag_p(tag)) {
+          *dest++ = node;
+          *dest++ = *src++;
+          elements = header_element_count(node);
+          tag = header_subtag(node);
+
+#ifdef PPC
+#ifdef PPC64
+          switch(fulltag_of(tag)) {
+          case ivector_class_64_bit:
+            imm_dnodes = ((elements+1)+1)>>1;
+            break;
+          case ivector_class_32_bit:
+            if (tag == subtag_code_vector) {
+              GCrelocated_code_vector = true;
+            }
+            imm_dnodes = (((elements+2)+3)>>2);
+            break;
+          case ivector_class_8_bit:
+            imm_dnodes = (((elements+8)+15)>>4);
+            break;
+          case ivector_class_other_bit:
+            if (tag == subtag_bit_vector) {
+              imm_dnodes = (((elements+64)+127)>>7);
+            } else {
+              imm_dnodes = (((elements+4)+7)>>3);
+            }
+          }
+#else
+          if (tag <= max_32_bit_ivector_subtag) {
+            if (tag == subtag_code_vector) {
+              GCrelocated_code_vector = true;
+            }
+            imm_dnodes = (((elements+1)+1)>>1);
+          } else if (tag <= max_8_bit_ivector_subtag) {
+            imm_dnodes = (((elements+4)+7)>>3);
+          } else if (tag <= max_16_bit_ivector_subtag) {
+            imm_dnodes = (((elements+2)+3)>>2);
+          } else if (tag == subtag_bit_vector) {
+            imm_dnodes = (((elements+32)+63)>>6);
+          } else {
+            imm_dnodes = elements+1;
+          }
+#endif
+#endif
+
+          dnode += imm_dnodes;
+          while (--imm_dnodes) {
+            *dest++ = *src++;
+            *dest++ = *src++;
+          }
+          set_bitidx_vars(markbits,dnode,bitsp,bits,bitidx);
+        } else {
+          *dest++ = node_forwarding_address(node);
+          *dest++ = node_forwarding_address(*src++);
+          bits &= ~(BIT0_MASK >> bitidx);
+          dnode++;
+          bitidx++;
+        }
+      }
+  
+    }
+
+    {
+      natural nbytes = (natural)ptr_to_lispobj(dest) - (natural)GCfirstunmarked;
+      if ((nbytes != 0) && GCrelocated_code_vector) {
+        xMakeDataExecutable((LogicalAddress)ptr_from_lispobj(GCfirstunmarked), nbytes);
+      }
+    }
+  }
+  return ptr_to_lispobj(dest);
+}
+
+
+
+
+      
+    
+/*
+  Total the (physical) byte sizes of all ivectors in the indicated memory range
+*/
+
+natural
+unboxed_bytes_in_range(LispObj *start, LispObj *end)
+{
+    natural total=0, elements, tag, subtag, bytes;
+    LispObj header;
+
+    while (start < end) {
+      header = *start;
+      tag = fulltag_of(header);
+    
+      if ((nodeheader_tag_p(tag)) ||
+          (immheader_tag_p(tag))) {
+        elements = header_element_count(header);
+        if (nodeheader_tag_p(tag)) {
+          start += ((elements+2) & ~1);
+        } else {
+          subtag = header_subtag(header);
+
+#ifdef PPC64
+          switch(fulltag_of(header)) {
+          case ivector_class_64_bit:
+            bytes = 8 + (elements<<3);
+            break;
+          case ivector_class_32_bit:
+            bytes = 8 + (elements<<2);
+            break;
+          case ivector_class_8_bit:
+            bytes = 8 + elements;
+            break;
+          case ivector_class_other_bit:
+          default:
+            if (subtag == subtag_bit_vector) {
+              bytes = 8 + ((elements+7)>>3);
+            } else {
+              bytes = 8 + (elements<<1);
+            }
+          }
+#else
+          if (subtag <= max_32_bit_ivector_subtag) {
+            bytes = 4 + (elements<<2);
+          } else if (subtag <= max_8_bit_ivector_subtag) {
+            bytes = 4 + elements;
+          } else if (subtag <= max_16_bit_ivector_subtag) {
+            bytes = 4 + (elements<<1);
+          } else if (subtag == subtag_double_float_vector) {
+            bytes = 8 + (elements<<3);
+          } else {
+            bytes = 4 + ((elements+7)>>3);
+          }
+#endif
+
+
+          bytes = (bytes+dnode_size-1) & ~(dnode_size-1);
+          total += bytes;
+          start += (bytes >> node_shift);
+        }
+      } else {
+        start += 2;
+      }
+    }
+    return total;
+  }
+
+
+  /* 
+     This assumes that it's getting called with an ivector
+     argument and that there's room for the object in the
+     destination area.
+  */
+
+
+LispObj
+purify_displaced_object(LispObj obj, area *dest, natural disp)
+{
+  BytePtr 
+    free = dest->active,
+    *old = (BytePtr *) ptr_from_lispobj(untag(obj));
+  LispObj 
+    header = header_of(obj), 
+    new;
+  natural 
+    start = (natural)old,
+    physbytes;
+
+  physbytes = ((natural)(skip_over_ivector(start,header))) - start;
+  dest->active += physbytes;
+
+  new = ptr_to_lispobj(free)+disp;
+
+  memcpy(free, (BytePtr)old, physbytes);
+  /* Leave a trail of breadcrumbs.  Or maybe just one breadcrumb. */
+  /* Actually, it's best to always leave a trail, for two reasons.
+     a) We may be walking the same heap that we're leaving forwaring
+     pointers in, so we don't want garbage that we leave behind to
+     look like a header.
+     b) We'd like to be able to forward code-vector locatives, and
+     it's easiest to do so if we leave a {forward_marker, dnode_locative}
+     pair at every doubleword in the old vector.
+  */
+  while(physbytes) {
+    *old++ = (BytePtr) forward_marker;
+    *old++ = (BytePtr) free;
+    free += dnode_size;
+    physbytes -= dnode_size;
+  }
+  return new;
+}
+
+LispObj
+purify_object(LispObj obj, area *dest)
+{
+  return purify_displaced_object(obj, dest, fulltag_of(obj));
+}
+
+
+
+void
+copy_ivector_reference(LispObj *ref, BytePtr low, BytePtr high, area *dest)
+{
+  LispObj obj = *ref, header;
+  natural tag = fulltag_of(obj), header_tag;
+
+  if ((tag == fulltag_misc) &&
+      (((BytePtr)ptr_from_lispobj(obj)) > low) &&
+      (((BytePtr)ptr_from_lispobj(obj)) < high)) {
+    header = deref(obj, 0);
+    if (header == forward_marker) { /* already copied */
+      *ref = (untag(deref(obj,1)) + tag);
+    } else {
+      header_tag = fulltag_of(header);
+      if (immheader_tag_p(header_tag)) {
+        if (header_subtag(header) != subtag_macptr) {
+          *ref = purify_object(obj, dest);
+        }
+      }
+    }
+  }
+}
+
+void
+purify_locref(LispObj *locaddr, BytePtr low, BytePtr high, area *to)
+{
+#ifdef PPC
+  LispObj
+    loc = *locaddr,
+    *headerP;
+  opcode
+    *p,
+    insn;
+  natural
+    tag = fulltag_of(loc);
+
+  if (((BytePtr)ptr_from_lispobj(loc) > low) &&
+      ((BytePtr)ptr_from_lispobj(loc) < high)) {
+
+    headerP = (LispObj *)ptr_from_lispobj(untag(loc));
+    switch (tag) {
+    case fulltag_even_fixnum:
+    case fulltag_odd_fixnum:
+#ifdef PPC64
+    case fulltag_cons:
+    case fulltag_misc:
+#endif
+      if (*headerP == forward_marker) {
+	*locaddr = (headerP[1]+tag);
+      } else {
+	/* Grovel backwards until the header's found; copy
+	   the code vector to to space, then treat it as if it 
+	   hasn't already been copied. */
+	p = (opcode *)headerP;
+	do {
+	  p -= 2;
+	  tag += 8;
+	  insn = *p;
+#ifdef PPC64
+	} while (insn != PPC64_CODE_VECTOR_PREFIX);
+	headerP = ((LispObj*)p)-1;
+	*locaddr = purify_displaced_object(((LispObj)headerP), to, tag);
+#else
+      } while ((insn & code_header_mask) != subtag_code_vector);
+      *locaddr = purify_displaced_object(ptr_to_lispobj(p), to, tag);
+#endif
+    }
+    break;
+
+#ifndef PPC64
+  case fulltag_misc:
+    copy_ivector_reference(locaddr, low, high, to);
+    break;
+#endif
+  }
+}
+#endif
+}
+
+void
+purify_range(LispObj *start, LispObj *end, BytePtr low, BytePtr high, area *to)
+{
+  LispObj header;
+  unsigned tag;
+
+  while (start < end) {
+    header = *start;
+    if (header == forward_marker) {
+      start += 2;
+    } else {
+      tag = fulltag_of(header);
+      if (immheader_tag_p(tag)) {
+        start = (LispObj *)skip_over_ivector((natural)start, header);
+      } else {
+        if (!nodeheader_tag_p(tag)) {
+          copy_ivector_reference(start, low, high, to);
+        }
+        start++;
+        copy_ivector_reference(start, low, high, to);
+        start++;
+      }
+    }
+  }
+}
+        
+/* Purify references from tstack areas */
+void
+purify_tstack_area(area *a, BytePtr low, BytePtr high, area *to)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) (a->active),
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = (LispObj *) ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    if (current[1] == 0) {
+      purify_range(current+2, end, low, high, to);
+    }
+  }
+}
+
+/* Purify a vstack area */
+void
+purify_vstack_area(area *a, BytePtr low, BytePtr high, area *to)
+{
+  LispObj
+    *p = (LispObj *) a->active,
+    *q = (LispObj *) a->high;
+
+  if (((natural)p) & sizeof(natural)) {
+    copy_ivector_reference(p, low, high, to);
+    p++;
+  }
+  purify_range(p, q, low, high, to);
+}
+
+
+void
+purify_cstack_area(area *a, BytePtr low, BytePtr high, area *to)
+{
+  BytePtr
+    current,
+    next,
+    limit = a->high;
+
+  for (current = a->active; current != limit; current = next) {
+    next = *((BytePtr *)current);
+    if (next == NULL) break;
+    if (((next - current) == sizeof(lisp_frame)) && 
+	(((((lisp_frame *)current)->savefn) == 0) ||
+	 (fulltag_of(((lisp_frame *)current)->savefn) == fulltag_misc))) {
+      purify_locref(&((lisp_frame *) current)->savelr, low, high, to);
+    } else {
+      /* Clear low bits of "next", just in case */
+      next = (BytePtr) (((natural)next) & ~(sizeof(natural)-1));
+    }
+  }
+}
+
+void
+purify_xp(ExceptionInformation *xp, BytePtr low, BytePtr high, area *to)
+{
+  unsigned long *regs = (unsigned long *) xpGPRvector(xp);
+
+  int r;
+
+  /* registers >= fn should be treated as roots.
+     The PC, LR, loc_pc, and CTR should be treated as "locatives".
+   */
+
+  for (r = fn; r < 32; r++) {
+    copy_ivector_reference((LispObj*) (&(regs[r])), low, high, to);
+  };
+
+  purify_locref((LispObj*) (&(regs[loc_pc])), low, high, to);
+
+  purify_locref((LispObj*) (&(xpPC(xp))), low, high, to);
+  purify_locref((LispObj*) (&(xpLR(xp))), low, high, to);
+  purify_locref((LispObj*) (&(xpCTR(xp))), low, high, to);
+}
+
+void
+purify_tcr_tlb(TCR *tcr, BytePtr low, BytePtr high, area *to)
+{
+  natural n = tcr->tlb_limit;
+  LispObj *start = tcr->tlb_pointer, *end = (LispObj *) ((BytePtr)start+n);
+
+  purify_range(start, end, low, high, to);
+}
+
+void
+purify_tcr_xframes(TCR *tcr, BytePtr low, BytePtr high, area *to)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+  
+  xp = tcr->gc_context;
+  if (xp) {
+    purify_xp(xp, low, high, to);
+  }
+
+  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
+    purify_xp(xframes->curr, low, high, to);
+  }
+}
+
+void
+purify_gcable_ptrs(BytePtr low, BytePtr high, area *to)
+{
+  LispObj *prev = &(lisp_global(GCABLE_POINTERS)), next;
+
+  while ((*prev) != (LispObj)NULL) {
+    copy_ivector_reference(prev, low, high, to);
+    next = *prev;
+    prev = &(((xmacptr *)ptr_from_lispobj(untag(next)))->link);
+  }
+}
+
+
+void
+purify_areas(BytePtr low, BytePtr high, area *target)
+{
+  area *next_area;
+  area_code code;
+      
+  for (next_area = active_dynamic_area; (code = next_area->code) != AREA_VOID; next_area = next_area->succ) {
+    switch (code) {
+    case AREA_TSTACK:
+      purify_tstack_area(next_area, low, high, target);
+      break;
+      
+    case AREA_VSTACK:
+      purify_vstack_area(next_area, low, high, target);
+      break;
+      
+    case AREA_CSTACK:
+      purify_cstack_area(next_area, low, high, target);
+      break;
+      
+    case AREA_STATIC:
+    case AREA_DYNAMIC:
+      purify_range((LispObj *) next_area->low, (LispObj *) next_area->active, low, high, target);
+      break;
+      
+    default:
+      break;
+    }
+  }
+}
+
+/*
+  So far, this is mostly for save_application's benefit.
+  We -should- be able to return to lisp code after doing this,
+  however.
+
+*/
+
+
+signed_natural
+purify(TCR *tcr, signed_natural param)
+{
+  extern area *extend_readonly_area(unsigned);
+  area 
+    *a = active_dynamic_area,
+    *new_pure_area;
+
+  TCR  *other_tcr;
+  natural max_pure_size;
+  BytePtr new_pure_start;
+
+
+  max_pure_size = unboxed_bytes_in_range((LispObj *)(a->low + (static_dnodes_for_area(a) << dnode_shift)), 
+                                         (LispObj *) a->active);
+  new_pure_area = extend_readonly_area(max_pure_size);
+  if (new_pure_area) {
+    new_pure_start = new_pure_area->active;
+    lisp_global(IN_GC) = (1<<fixnumshift);
+
+    
+    purify_areas(a->low, a->active, new_pure_area);
+    
+    other_tcr = tcr;
+    do {
+      purify_tcr_xframes(other_tcr, a->low, a->active, new_pure_area);
+      purify_tcr_tlb(other_tcr, a->low, a->active, new_pure_area);
+      other_tcr = other_tcr->next;
+    } while (other_tcr != tcr);
+
+    purify_gcable_ptrs(a->low, a->active, new_pure_area);
+
+    {
+      natural puresize = (unsigned) (new_pure_area->active-new_pure_start);
+      if (puresize != 0) {
+        xMakeDataExecutable(new_pure_start, puresize);
+  
+      }
+    }
+    ProtectMemory(new_pure_area->low,
+		  align_to_power_of_2(new_pure_area->active-new_pure_area->low,
+				      log2_page_size));
+    lisp_global(IN_GC) = 0;
+    just_purified_p = true;
+    return 0;
+  }
+  return -1;
+}
+
+void
+impurify_locref(LispObj *p, LispObj low, LispObj high, int delta)
+{
+  LispObj q = *p;
+  
+  switch (fulltag_of(q)) {
+#ifdef PPC64
+  case fulltag_cons:
+#endif
+  case fulltag_misc:
+  case fulltag_even_fixnum:
+  case fulltag_odd_fixnum:
+    if ((q >= low) && (q < high)) {
+      *p = (q+delta);
+    }
+  }
+}
+
+  
+void
+impurify_noderef(LispObj *p, LispObj low, LispObj high, int delta)
+{
+  LispObj q = *p;
+  
+  if ((fulltag_of(q) == fulltag_misc) &&
+      (q >= low) && 
+      (q < high)) {
+    *p = (q+delta);
+  }
+}
+  
+
+#ifdef PPC
+void
+impurify_cstack_area(area *a, LispObj low, LispObj high, int delta)
+{
+  BytePtr
+    current,
+    next,
+    limit = a->high;
+
+  for (current = a->active; current != limit; current = next) {
+    next = *((BytePtr *)current);
+    if (next == NULL) break;
+    if (((next - current) == sizeof(lisp_frame)) && 
+	(((((lisp_frame *)current)->savefn) == 0) ||
+	 (fulltag_of(((lisp_frame *)current)->savefn) == fulltag_misc))) {
+      impurify_locref(&((lisp_frame *) current)->savelr, low, high, delta);
+    } else {
+      /* Clear low bits of "next", just in case */
+      next = (BytePtr) (((natural)next) & ~(sizeof(natural)-1));
+    }
+  }
+}
+#endif
+
+void
+impurify_xp(ExceptionInformation *xp, LispObj low, LispObj high, int delta)
+{
+  natural *regs = (natural *) xpGPRvector(xp);
+
+#ifdef PPC
+  int r;
+  /* registers >= fn should be treated as roots.
+     The PC, LR, loc_pc, and CTR should be treated as "locatives".
+   */
+
+  for (r = fn; r < 32; r++) {
+    impurify_noderef((LispObj*) (&(regs[r])), low, high, delta);
+  };
+
+  impurify_locref((LispObj*) (&(regs[loc_pc])), low, high, delta);
+
+  impurify_locref((LispObj*) (&(xpPC(xp))), low, high, delta);
+  impurify_locref((LispObj*) (&(xpLR(xp))), low, high, delta);
+  impurify_locref((LispObj*) (&(xpCTR(xp))), low, high, delta);
+#endif
+
+}
+
+
+void
+impurify_range(LispObj *start, LispObj *end, LispObj low, LispObj high, int delta)
+{
+  LispObj header;
+  unsigned tag;
+
+  while (start < end) {
+    header = *start;
+    tag = fulltag_of(header);
+    if (immheader_tag_p(tag)) {
+      start = (LispObj *)skip_over_ivector((natural)start, header);
+    } else {
+      if (!nodeheader_tag_p(tag)) {
+        impurify_noderef(start, low, high, delta);
+        }
+      start++;
+      impurify_noderef(start, low, high, delta);
+      start++;
+    }
+  }
+}
+
+
+
+
+void
+impurify_tcr_tlb(TCR *tcr,  LispObj low, LispObj high, int delta)
+{
+  unsigned n = tcr->tlb_limit;
+  LispObj *start = tcr->tlb_pointer, *end = (LispObj *) ((BytePtr)start+n);
+  
+  impurify_range(start, end, low, high, delta);
+}
+
+void
+impurify_tcr_xframes(TCR *tcr, LispObj low, LispObj high, int delta)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+  
+  xp = tcr->gc_context;
+  if (xp) {
+    impurify_xp(xp, low, high, delta);
+  }
+
+  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
+    impurify_xp(xframes->curr, low, high, delta);
+  }
+}
+
+void
+impurify_tstack_area(area *a, LispObj low, LispObj high, int delta)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) (a->active),
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = (LispObj *) ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    if (current[1] == 0) {
+      impurify_range(current+2, end, low, high, delta);
+    }
+  }
+}
+void
+impurify_vstack_area(area *a, LispObj low, LispObj high, int delta)
+{
+  LispObj
+    *p = (LispObj *) a->active,
+    *q = (LispObj *) a->high;
+
+  if (((natural)p) & sizeof(natural)) {
+    impurify_noderef(p, low, high, delta);
+    p++;
+  }
+  impurify_range(p, q, low, high, delta);
+}
+
+
+void
+impurify_areas(LispObj low, LispObj high, int delta)
+{
+  area *next_area;
+  area_code code;
+      
+  for (next_area = active_dynamic_area; (code = next_area->code) != AREA_VOID; next_area = next_area->succ) {
+    switch (code) {
+    case AREA_TSTACK:
+      impurify_tstack_area(next_area, low, high, delta);
+      break;
+      
+    case AREA_VSTACK:
+      impurify_vstack_area(next_area, low, high, delta);
+      break;
+      
+    case AREA_CSTACK:
+#ifdef PPC
+      impurify_cstack_area(next_area, low, high, delta);
+#endif
+      break;
+      
+    case AREA_STATIC:
+    case AREA_DYNAMIC:
+      impurify_range((LispObj *) next_area->low, (LispObj *) next_area->active, low, high, delta);
+      break;
+      
+    default:
+      break;
+    }
+  }
+}
+
+void
+impurify_gcable_ptrs(LispObj low, LispObj high, signed_natural delta)
+{
+  LispObj *prev = &(lisp_global(GCABLE_POINTERS)), next;
+
+  while ((*prev) != (LispObj)NULL) {
+    impurify_noderef(prev, low, high, delta);
+    next = *prev;
+    prev = &(((xmacptr *)ptr_from_lispobj(untag(next)))->link);
+  }
+}
+
+signed_natural
+impurify(TCR *tcr, signed_natural param)
+{
+  area *r = readonly_area;
+
+  if (r) {
+    area *a = active_dynamic_area;
+    BytePtr ro_base = r->low, ro_limit = r->active, oldfree = a->active,
+      oldhigh = a->high, newhigh; 
+    unsigned n = ro_limit - ro_base;
+    int delta = oldfree-ro_base;
+    TCR *other_tcr;
+
+    if (n) {
+      lisp_global(IN_GC) = 1;
+      newhigh = (BytePtr) (align_to_power_of_2(oldfree+n,
+                                               log2_heap_segment_size));
+      if (newhigh > oldhigh) {
+        grow_dynamic_area(newhigh-oldhigh);
+      }
+      a->active += n;
+      memmove(oldfree, ro_base, n);
+      munmap(ro_base, n);
+      a->ndnodes = area_dnode(a, a->active);
+      pure_space_active = r->active = r->low;
+      r->ndnodes = 0;
+
+      impurify_areas(ptr_to_lispobj(ro_base), ptr_to_lispobj(ro_limit), delta);
+
+      other_tcr = tcr;
+      do {
+        impurify_tcr_xframes(other_tcr, ptr_to_lispobj(ro_base), ptr_to_lispobj(ro_limit), delta);
+        impurify_tcr_tlb(other_tcr, ptr_to_lispobj(ro_base), ptr_to_lispobj(ro_limit), delta);
+        other_tcr = other_tcr->next;
+      } while (other_tcr != tcr);
+
+      impurify_gcable_ptrs(ptr_to_lispobj(ro_base), ptr_to_lispobj(ro_limit), delta);
+      lisp_global(IN_GC) = 0;
+    }
+    return 0;
+  }
+  return -1;
+}
+
Index: /branches/new-random/lisp-kernel/ppc-macros.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-macros.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-macros.s	(revision 13309)
@@ -0,0 +1,744 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL.  */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence.   */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+/* The assembler has to do the arithmetic here:	 the expression */
+/*   may not be evaluable by m4. */
+define([lwi],[ifdef([DARWIN],[
+	.if ((($2) & 0xffff8000) == 0xffff8000)
+	 li $1,($2)
+	.elseif ((($2) & 0xffff8000) == 0)
+	 li $1,$2
+	.else
+	 lis $1,(($2)>>16)
+	 .if (($2) & 0xffff) <> 0
+	  ori $1,$1,(($2) & 0xffff)
+	 .endif
+	.endif],[
+	.ifeq (($2) & 0xffff8000)-0xffff8000
+	 li $1,$2
+	.else
+	 .ifeq (($2) & 0xffff8000)
+	  li $1,$2
+	 .else
+	  lis $1,($2>>16)
+	  .ifne ($2 & 0xffff)
+	   ori $1,$1,$2 & 0xffff
+	  .endif
+	 .endif
+	.endif
+])])
+
+ifdef([PPC64],[
+        define([clrrri],[clrrdi $@])       
+        define([clrlri],[clrldi $@])
+        define([clrlri_],[clrldi. $@])
+        define([ldr],[ld $@])
+        define([ldrx],[ldx $@])
+        define([ldru],[ldu $@])
+        define([str],[std $@])
+        define([strx],[stdx $@])
+        define([stru],[stdu $@])
+        define([strux],[stdux $@])	
+        define([cmpr],[cmpd $@])
+        define([cmpri],[cmpdi $@])
+        define([cmplr],[cmpld $@])
+        define([cmplri],[cmpldi $@])
+        define([trlge],[tdlge $@])
+        define([trllt],[tdllt $@])
+        define([trlt],[tdlt $@])
+	define([trlle],[tdlle $@])
+        define([treqi],[tdeqi $@])
+        define([trnei],[tdnei $@])
+        define([trgti],[tdgti $@])
+        define([srari],[sradi $@])
+        define([srri],[srdi $@])
+        define([srr],[srd $@])
+        define([slri],[sldi $@])
+        define([lrarx],[ldarx $@])
+        define([strcx],[stdcx. $@])
+        define([load_highbit],[
+        __(lis $1,0x8000)
+        __(sldi $1,$1,32)
+        ])
+        define([extract_bit_shift_count],[
+        __(clrldi $1,$2,64-bitmap_shift)
+        ])
+        define([alloc_trap],[
+        __(tdlt allocptr,allocbase)
+        ])
+        define([mullr],[mulld $@])
+],[
+        define([clrrri],[clrrwi $@])
+        define([clrlri],[clrlwi $@])
+        define([clrlri_],[clrlwi. $@])
+        define([ldr],[lwz $@])
+        define([ldrx],[lwzx $@])
+        define([ldru],[lwzu $@])
+        define([str],[stw $@])
+        define([strx],[stwx $@])
+        define([stru],[stwu $@])
+        define([strux],[stwux $@])
+        define([cmpr],[cmpw $@])
+        define([cmpri],[cmpwi $@])
+        define([cmplr],[cmplw $@])
+        define([cmplri],[cmplwi $@])
+        define([trlge],[twlge $@])
+        define([trllt],[twllt $@])
+        define([trlt],[twlt $@])
+        define([trlle],[twlle $@])       
+        define([treqi],[tweqi $@])
+        define([trnei],[twnei $@])
+        define([trgti],[twgti $@])
+        define([srari],[srawi $@])
+        define([srri],[srwi $@])
+        define([srr],[srw $@])
+        define([slri],[slwi $@])
+        define([lrarx],[lwarx $@])
+        define([strcx],[stwcx. $@])
+        define([load_highbit],[
+        __(lis $1,0x8000)
+        ])
+        define([extract_bit_shift_count],[
+        __(clrlwi $1,$2,32-bitmap_shift)
+        ])
+        define([alloc_trap],[
+        __(twllt allocptr,allocbase)
+        ])
+        define([mullr],[mullw $@])
+])
+
+/* dnode_align(dest,src,delta) */
+        define([dnode_align],[
+        __(la $1,($3+(dnode_size-1))($2))
+        __(clrrri($1,$1,dnode_align_bits))
+])
+
+define([extract_fulltag],[
+	__(clrlri($1,$2,nbits_in_word-ntagbits))
+        ])
+
+define([extract_lisptag],[
+	__(clrlri($1,$2,nbits_in_word-nlisptagbits))
+        ])
+
+define([extract_lisptag_],[
+	__(clrlri_($1,$2,nbits_in_word-nlisptagbits))
+        ])
+
+define([extract_subtag],[
+	__(lbz $1,misc_subtag_offset($2))
+	])
+
+ifdef([PPC64],[
+define([extract_lowtag],[
+        __(clrldi $1,$2,nbits_in_word-nlowtagbits)
+])
+define([trap_unless_lowtag_equal],[
+        __(clrldi $3,$1,nbits_in_word-nlowtagbits)
+        __(tdnei $3,$2)
+])                
+        ])
+                               
+define([extract_lowbyte],[
+        __(clrlri($1,$2,nbits_in_word-num_subtag_bits))
+        ])
+
+define([extract_header],[
+	__(ldr($1,misc_header_offset($2)))
+	])
+
+
+ifdef([PPC64],[
+define([extract_typecode],[
+	new_macro_labels()
+	__(extract_fulltag($1,$2))
+	__(cmpdi cr0,$1,fulltag_misc)
+	__(extract_lisptag($1,$1))
+	__(bne cr0,macro_label(not_misc))
+	__(extract_subtag($1,$2))
+macro_label(not_misc):
+])],[	
+define([extract_typecode],[
+	new_macro_labels()
+	__(extract_lisptag($1,$2))
+	__(cmpwi cr0,$1,tag_misc)
+	__(bne cr0,macro_label(not_misc))
+	__(extract_subtag($1,$2))
+macro_label(not_misc):
+])])
+
+define([box_fixnum],[
+	__(slri($1,$2,fixnumshift))
+	])
+
+define([unbox_fixnum],[	
+	__(srari($1,$2,fixnumshift))
+	])
+
+define([loaddf],[
+	__(lfd $1,dfloat.value($2))])
+	
+define([storedf],[
+	__(stfd $1,dfloat.value($2))
+	])
+
+define([push],[
+	__(stru($1,-node_size($2)))
+	])
+	
+	/* Generally not a great idea. */
+define([pop],[
+	__(ldr($1,0($2)))
+	__(la $2,node_size($2))
+	])
+	
+define([vpush],[
+	__(push($1,vsp))
+	])
+	
+define([vpop],[
+	__(pop($1,vsp))
+	])
+	
+		
+define([unlink],[
+	__(ldr($1,0($1)))
+ ])
+
+	
+define([set_nargs],[
+	__(lwi(nargs,($1)<<fixnumshift))
+	])
+	
+define([bitclr],[
+	__(rlwinm $1,$2,0,0x1f&((31-($3))+1),0x1f&((31-($3))-1))
+	])
+	
+
+define([vref32],[
+	__(lwz $1,misc_data_offset+(($3)<<2)($2))
+	])
+        
+define([vref16],[/* dest,src,n*/
+	__(lhz $1,misc_data_offset+(($3)<<1)($2))
+	])
+	
+ifdef([PPC64],[
+        define([vref64],[
+        __(ld $1,misc_data_offset+(($3)<<3)($2))
+	])
+
+        define([vrefr],[
+        __(vref64($1,$2,$3))
+	])
+],[
+        define([vrefr],[
+        __(vref32($1,$2,$3))
+	])
+])
+        
+                	
+define([getvheader],[
+	__(ldr($1,vector.header($2)))
+	])
+	
+	/* Size is unboxed element count */
+define([header_size],[
+	__(srri($1,$2,num_subtag_bits))
+	])
+	
+	/* "Length" is fixnum element count */
+define([header_length],[
+ifdef([PPC64],[
+        __(rldicr $1,$2,nbits_in_word-(num_subtag_bits-nfixnumtagbits),63-nfixnumtagbits)
+        __(clrldi $1,$1,(num_subtag_bits-nfixnumtagbits))
+        ],[               
+	__(rlwinm $1,$2,nbits_in_word-(num_subtag_bits-nfixnumtagbits),(num_subtag_bits-nfixnumtagbits),31-nfixnumtagbits)
+        ])
+])        
+
+
+define([vector_size],[
+	__(getvheader(ifelse($3.[],$1,$3),$2))
+	__(header_size($1,ifelse($3.[],$1,$3)))
+	])
+	
+define([vector_length],[
+	__(getvheader($3,$2))
+	__(header_length($1,$3))
+	])
+
+	
+define([ref_global],[
+	__(ldr($1,lisp_globals.$2(0)))
+])
+
+define([set_global],[
+	__(str($1,lisp_globals.$2(0)))
+])
+
+define([ref_nrs_value],[
+	__(ldr($1,((nrs.$2)+(symbol.vcell))(0)))
+])
+	
+define([set_nrs_value],[
+	__(str($1,((nrs.$2)+(symbol.vcell))(0)))
+])
+
+define([extract_unsigned_byte_bits],[
+ifdef([PPC64],[
+        __(rldicr $1,$2,64-fixnumshift,63-$3)
+],[                
+        __(rlwinm $1,$2,0,32-fixnumshift,31-($3+fixnumshift))
+])        
+])
+
+define([extract_unsigned_byte_bits_],[
+ifdef([PPC64],[
+        __(rldicr. $1,$2,64-fixnumshift,63-$3)
+],[                
+        __(rlwinm. $1,$2,0,32-fixnumshift,31-($3+fixnumshift))
+])        
+])
+
+	/* vpop argregs - nargs is known to be non-zero */
+define([vpop_argregs_nz],[
+	new_macro_labels()
+	__(cmplri(cr1,nargs,node_size*2))
+	__(vpop(arg_z))
+	__(blt cr1,macro_label(l0))
+	__(vpop(arg_y))
+	__(bne cr1,macro_label(l0))
+	__(vpop(arg_x))
+macro_label(l0):])
+
+                
+	/* vpush argregs */
+define([vpush_argregs],[
+	new_macro_labels()
+	__(cmplri(cr0,nargs,0))
+	__(cmplri(cr1,nargs,node_size*2))
+	__(beq cr0,macro_label(done))
+	__(blt cr1,macro_label(z))
+	__(beq cr1,macro_label(yz))
+	__(vpush(arg_x))
+macro_label(yz):
+	__(vpush(arg_y))
+macro_label(z):
+	__(vpush(arg_z))
+macro_label(done):
+])
+
+define([create_lisp_frame],[
+	__(stru(sp,-lisp_frame.size(sp)))
+])
+
+                
+define([build_lisp_frame],[
+	create_lisp_frame()
+	__(str(ifelse($1,[],fn,$1),lisp_frame.savefn(sp)))
+	__(str(ifelse($2,[],loc_pc,$2),lisp_frame.savelr(sp)))
+	__(str(ifelse($3,[],vsp,$3),lisp_frame.savevsp(sp)))
+])
+
+        	
+define([discard_lisp_frame],[
+	__(la sp,lisp_frame.size(sp))
+	])
+	
+	
+define([_car],[
+	__(ldr($1,cons.car($2)))
+])
+	
+define([_cdr],[
+	__(ldr($1,cons.cdr($2)))
+	])
+	
+define([_rplaca],[
+	__(str($2,cons.car($1)))
+	])
+	
+define([_rplacd],[
+	__(str($2,cons.cdr($1)))
+	])
+
+define([vpush_saveregs],[
+	__(vpush(save7))
+	__(vpush(save6))
+	__(vpush(save5))
+	__(vpush(save4))
+	__(vpush(save3))
+	__(vpush(save2))
+	__(vpush(save1))
+	__(vpush(save0))
+	])
+	
+define([restore_saveregs],[
+	__(ldr(save0,node_size*0($1)))
+	__(ldr(save1,node_size*1($1)))
+	__(ldr(save2,node_size*2($1)))
+	__(ldr(save3,node_size*3($1)))
+	__(ldr(save4,node_size*4($1)))
+	__(ldr(save5,node_size*5($1)))
+	__(ldr(save6,node_size*6($1)))
+	__(ldr(save7,node_size*7($1)))
+])
+
+define([vpop_saveregs],[
+	__(restore_saveregs(vsp))
+	__(la vsp,node_size*8(vsp))
+])
+
+define([trap_unless_lisptag_equal],[
+	__(extract_lisptag($3,$1))
+	__(trnei($3,$2))
+])
+
+ifdef([PPC64],[
+define([trap_unless_list],[
+	new_macro_labels()
+	__(cmpdi ifelse($3,$3,cr0),$1,nil_value)
+	__(extract_fulltag($2,$1))
+	__(beq ifelse($3,$3,cr0),macro_label(is_list))
+	__(tdnei $2,fulltag_cons)
+macro_label(is_list):	
+
+])],[	
+define([trap_unless_list],[
+	__(trap_unless_lisptag_equal($1,tag_list,$2))
+])
+])
+
+define([trap_unless_fulltag_equal],[
+	__(extract_fulltag($3,$1))
+	__(trnei($3,$2))
+])
+	
+define([trap_unless_typecode_equal],[
+        __(extract_typecode($3,$1))
+        __(trnei($3,$2))
+])
+        
+/* "jump" to the code-vector of the function in nfn. */
+define([jump_nfn],[
+	__(ldr(temp0,_function.codevector(nfn)))
+	__(mtctr temp0)
+	__(bctr)
+])
+
+/* "call the code-vector of the function in nfn. */
+define([call_nfn],[
+	__(ldr(temp0,_function.codevector(nfn)))
+	__(mtctr temp0)
+	__(bctrl)
+])
+	
+
+/* "jump" to the function in fnames function cell. */
+define([jump_fname],[
+	__(ldr(nfn,symbol.fcell(fname)))
+	__(jump_nfn())
+])
+
+/* call the function in fnames function cell. */
+define([call_fname],[
+	__(ldr(nfn,symbol.fcell(fname)))
+	__(call_nfn())
+])
+
+define([do_funcall],[
+	new_macro_labels()
+	__(extract_fulltag(imm0,temp0))
+	__(cmpri(imm0,fulltag_misc))
+	__(mr nfn,temp0)
+	__(bne- macro_label(bad))
+	__(extract_subtag(imm0,temp0))
+	__(cmpri(imm0,subtag_function))
+	__(cmpri(cr1,imm0,subtag_symbol))
+        __(bne cr0,macro_label(_sym))
+        __(jump_nfn())
+macro_label(_sym):             
+	__(mr fname,temp0)
+	__(bne cr1,macro_label(bad))
+	__(jump_fname())
+macro_label(bad):
+	__(uuo_interr(error_cant_call,temp0))
+])	
+
+define([mkcatch],[
+	__(mflr loc_pc)
+	__(ldr(imm0,tcr.catch_top(rcontext)))
+	__(lwz imm1,0(loc_pc)) /* a forward branch to the catch/unwind cleanup */
+	__(rlwinm imm1,imm1,0,6,29)	/* extract LI */
+	__(add loc_pc,loc_pc,imm1)
+	__(build_lisp_frame(fn,loc_pc,vsp))
+	__(sub loc_pc,loc_pc,imm1)
+	__(la loc_pc,4(loc_pc))	/* skip over the forward branch */
+	__(mtlr loc_pc)
+	__(lwi(imm4,(catch_frame.element_count<<num_subtag_bits)|subtag_catch_frame))
+	__(ldr(imm3,tcr.xframe(rcontext)))
+	__(ldr(imm1,tcr.db_link(rcontext)))
+	__(TSP_Alloc_Fixed_Unboxed(catch_frame.size))
+	__(la nargs,tsp_frame.data_offset+fulltag_misc(tsp))
+        __(str(imm4,catch_frame.header(nargs)))
+	__(str(arg_z,catch_frame.catch_tag(nargs)))
+	__(str(imm0,catch_frame.link(nargs)))
+	__(str(imm2,catch_frame.mvflag(nargs)))
+	__(str(sp,catch_frame.csp(nargs)))
+	__(str(imm1,catch_frame.db_link(nargs)))
+        __(str(first_nvr,catch_frame.regs+0*node_size(nargs)))
+        __(str(second_nvr,catch_frame.regs+1*node_size(nargs)))
+        __(str(third_nvr,catch_frame.regs+2*node_size(nargs)))
+        __(str(fourth_nvr,catch_frame.regs+3*node_size(nargs)))
+        __(str(fifth_nvr,catch_frame.regs+4*node_size(nargs)))
+        __(str(sixth_nvr,catch_frame.regs+5*node_size(nargs)))
+        __(str(seventh_nvr,catch_frame.regs+6*node_size(nargs)))
+        __(str(eighth_nvr,catch_frame.regs+7*node_size(nargs)))
+	__(str(imm3,catch_frame.xframe(nargs)))
+	__(str(rzero,catch_frame.tsp_segment(nargs)))
+	__(Set_TSP_Frame_Boxed())
+	__(str(nargs,tcr.catch_top(rcontext)))
+        __(li nargs,0)
+
+])	
+
+define([restore_catch_nvrs],[
+        __(ldr(first_nvr,catch_frame.regs+(node_size*0)($1)))
+        __(ldr(second_nvr,catch_frame.regs+(node_size*1)($1)))
+        __(ldr(third_nvr,catch_frame.regs+(node_size*2)($1)))
+        __(ldr(fourth_nvr,catch_frame.regs+(node_size*3)($1)))
+        __(ldr(fifth_nvr,catch_frame.regs+(node_size*4)($1)))
+        __(ldr(sixth_nvr,catch_frame.regs+(node_size*5)($1)))
+        __(ldr(seventh_nvr,catch_frame.regs+(node_size*6)($1)))
+        __(ldr(eighth_nvr,catch_frame.regs+(node_size*7)($1)))
+])               
+
+define([DCBZL],[
+	__(.long (31<<26)+(1<<21)+($1<<16)+($2<<11)+(1014<<1))
+])
+	
+define([check_stack_alignment],[
+	new_macro_labels()
+	__(andi. $1,sp,STACK_ALIGN_MASK)
+	__(beq+ macro_label(stack_ok))
+	__(.long 0)
+macro_label(stack_ok):
+])
+
+define([stack_align],[((($1)+STACK_ALIGN_MASK)&~STACK_ALIGN_MASK)])
+
+define([clear_alloc_tag],[
+	__(clrrri(allocptr,allocptr,ntagbits))
+])
+
+/* If the GC interrupts the current thread (after the trap), it needs */
+/*   to ensure that the cons cell that's been "reserved" stays reserved */
+/*   (e.g. the tagged allocptr has to be treated as a node.)  If that */
+/*   reserved cons cell gets tenured, the car and cdr are of a generation */
+/*   that's at least as old (so memoization isn't an issue.) */
+
+/*   More generally, if the GC interrupts a thread when allocptr is */
+/*   tagged as a cons: */
+
+/*    a) if the trap hasn't been taken (yet), the GC should force the */
+/*       thread to resume in such a way that the trap will be taken ; */
+/*       the segment allocator should worry about allocating the object. */
+
+/*    b) If the trap has been taken, allocptr is treated as a node as */
+/*       described above.  Allocbase is made to point to the base of the */
+/*       cons cell, so that the thread's next allocation attempt will */
+/*       invoke the segment allocator. */
+	
+define([Cons],[
+	__(la allocptr,(-cons.size+fulltag_cons)(allocptr))
+        __(alloc_trap())
+	__(str($3,cons.cdr(allocptr)))
+	__(str($2,cons.car(allocptr)))
+	__(mr $1,allocptr)
+	__(clear_alloc_tag())
+])
+
+
+/* This is probably only used once or twice in the entire kernel, but */
+/* I wanted a place to describe the constraints on the mechanism. */
+
+/* Those constaints are (not surprisingly) similar to those which apply */
+/* to cons cells, except for the fact that the header (and any length */
+/* field that might describe large arrays) has to have been stored in */
+/* the object if the trap has succeeded on entry to the GC.  It follows */
+/* that storing the register containing the header must immediately */
+/* follow the allocation trap (and an auxiliary length register must */
+/* be stored immediately after the header.)  Successfully falling */
+/* through the trap must emulate any header initialization: it would */
+/* be a bad idea to have allocptr pointing to a zero header ... */
+
+
+
+/* Parameters: */
+
+/* $1 = dest reg */
+/* $2 = header.  (For now, assume that this always encodes length ; */
+/* that may change with "large vector" support.) */
+/* $3 = register containing size in bytes.  (We're going to subtract */
+/* fulltag_misc from this; do it in the macro body, rather than force the
+/* (1 ?) caller to do it. */
+
+
+define([Misc_Alloc],[
+	__(la $3,-fulltag_misc($3))
+	__(sub allocptr,allocptr,$3)
+        __(alloc_trap())
+	__(str($2,misc_header_offset(allocptr)))
+	__(mr $1,allocptr)
+	__(clear_alloc_tag())
+])
+
+/*  Parameters $1, $2 as above; $3 = physical size constant. */
+define([Misc_Alloc_Fixed],[
+	__(la allocptr,(-$3)+fulltag_misc(allocptr))
+        __(alloc_trap())
+	__(str($2,misc_header_offset(allocptr)))
+	__(mr $1,allocptr)
+	__(clear_alloc_tag())
+])
+
+
+/*  Zero $3 bytes worth of doublewords, starting at offset $2 relative */
+/* to the base register $1. */
+
+
+ifdef([DARWIN],[
+	.macro zero_doublewords
+	.if $2
+	stfd fp_zero,$1($0)
+	zero_doublewords $0,$1+8,$2-8
+	.endif
+	.endmacro
+])
+
+ifdef([LINUX],[
+	.macro zero_doublewords base,disp,nbytes
+	.if \nbytes
+	stfd fp_zero,\disp(\base)
+	zero_doublewords \base,\disp+8,\nbytes-8
+	.endif
+	.endm
+])	
+
+define([Set_TSP_Frame_Unboxed],[
+	__(str(tsp,tsp_frame.type(tsp)))
+])
+
+define([Set_TSP_Frame_Boxed],[
+	__(str(rzero,tsp_frame.type(tsp)))
+])
+		
+/* A newly allocated TSP frame is always "raw" (has non-zero type, indicating */
+/* that it doesn't contain tagged data. */
+
+define([TSP_Alloc_Fixed_Unboxed],[
+	__(stru(tsp,-($1+tsp_frame.data_offset)(tsp)))
+	__(Set_TSP_Frame_Unboxed())
+])
+
+define([TSP_Alloc_Fixed_Unboxed_Zeroed],[
+	__(TSP_Alloc_Fixed_Unboxed($1))
+	__(zero_doublewords tsp,tsp_frame.fixed_overhead,$1)
+])
+
+define([TSP_Alloc_Fixed_Boxed],[
+	__(TSP_Alloc_Fixed_Unboxed_Zeroed($1))
+	__(Set_TSP_Frame_Boxed())
+])
+
+
+        
+	
+
+/* This assumes that the backpointer points  to the first byte beyond */
+/* each frame.  If we allow segmented tstacks, that constraint might */
+/* complicate  their implementation. */
+/* We don't need to know the size of the frame (positive or negative, */
+/* with or without header).  $1 and $2 are temp registers, $3 is an */
+/* optional CR field. */
+
+
+/* Handle the general case, where the frame might be empty */
+define([Zero_TSP_Frame],[
+	__(new_macro_labels())
+	__(la $1,tsp_frame.size-8(tsp))
+	__(ldr($2,tsp_frame.backlink(tsp)))
+	__(la $2,-8($2))
+	__(b macro_label(zero_tsp_test))
+macro_label(zero_tsp_loop):
+	__(stfdu fp_zero,8($1))
+macro_label(zero_tsp_test):	
+	__(cmpr(ifelse($3,[],[cr0],$3),$1,$2))
+	__(bne ifelse($3,[],[cr0],$3),macro_label(zero_tsp_loop))
+])
+
+/* Save some branching when we know that the frame can't be empty.*/
+define([Zero_TSP_Frame_nz],[
+	new_macro_labels()
+	__(la $1,tsp_frame.size-8(tsp))
+	__(ldr($2,tsp_frame.backlink(tsp)))
+	__(la $2,-8($2))
+macro_label(zero_tsp_loop):
+	__(stfdu fp_zero,8($1))
+	__(cmpr(ifelse($3,[],[cr0],$3),$1,$2))
+	__(bne ifelse($3,[],[cr0],$3),macro_label(zero_tsp_loop))
+])
+	
+/* $1 = 8-byte-aligned size, positive.  $2 (optiional) set */
+/* to negated size. */
+define([TSP_Alloc_Var_Unboxed],[
+	__(neg ifelse($2,[],$1,$2),$1)
+	__(strux(tsp,tsp,ifelse($2,[],$1,$2)))
+	__(Set_TSP_Frame_Unboxed())
+])
+
+define([TSP_Alloc_Var_Boxed],[
+	__(TSP_Alloc_Var_Unboxed($1))
+	__(Zero_TSP_Frame($1,$2))
+	__(Set_TSP_Frame_Boxed())
+])		
+
+
+define([TSP_Alloc_Var_Boxed_nz],[
+	__(TSP_Alloc_Var_Unboxed($1))
+	__(Zero_TSP_Frame_nz($1,$2))
+	__(Set_TSP_Frame_Boxed())
+])		
+
+define([check_pending_interrupt],[
+	new_macro_labels()
+        __(ldr(nargs,tcr.tlb_pointer(rcontext)))
+	__(ldr(nargs,INTERRUPT_LEVEL_BINDING_INDEX(nargs)))
+	__(cmpri(ifelse($1,[],[cr0],$1),nargs,0))
+	__(blt ifelse($1,[],[cr0],$1),macro_label(done))
+	__(bgt ifelse($1,[],[cr0],$1),macro_label(trap))
+	__(ldr(nargs,tcr.interrupt_pending(rcontext)))
+macro_label(trap):
+	__(trgti(nargs,0))
+macro_label(done):
+])
+
+/* $1 = ndigits.  Assumes 4-byte digits */        
+define([aligned_bignum_size],[((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))])
+
+define([suspend_now],[
+	__(uuo_interr(error_propagate_suspend,rzero))
+])
Index: /branches/new-random/lisp-kernel/ppc-spentry.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-spentry.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-spentry.s	(revision 13309)
@@ -0,0 +1,7064 @@
+/* Copyright (C) 2009 Clozure Associates */
+/* Copyright (C) 1994-2001 Digitool, Inc */
+/* This file is part of Clozure CL.   */
+
+/* Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/* License , known as the LLGPL and distributed with Clozure CL as the */
+/* file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/* which is distributed with Clozure CL as the file "LGPL".  Where these */
+/* conflict, the preamble takes precedence.   */
+
+/* Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/* The LLGPL is also available online at */
+/* http://opensource.franz.com/preamble.html */
+
+
+	
+	include(lisp.s)
+	_beginfile
+        .align 2
+	
+local_label(start):	
+define([_spentry],[ifdef([__func_name],[_endfn],[])
+	_exportfn(_SP$1)
+	.line  __line__
+])
+
+             
+define([_endsubp],[
+	_endfn(_SP$1)
+# __line__
+])
+
+
+                	
+               
+define([jump_builtin],[
+	ref_nrs_value(fname,builtin_functions)
+	set_nargs($2)
+	vrefr(fname,fname,$1)
+	jump_fname()
+])
+	
+_spentry(jmpsym)
+	__(jump_fname())
+        
+_spentry(jmpnfn)
+	__(jump_nfn())
+        
+	/*  Call temp0 if it's either a symbol or function */
+_spentry(funcall)
+	__(do_funcall())
+	
+/* Subprims for catch, throw, unwind_protect.  */
+
+/* Push a catch frame on the temp stack (and some of it on the cstack, as well.)  */
+/* The PC in question is 4 bytes past the caller's return address. ALWAYS.  */
+/* The catch tag is in arg_z, the multiple-value flags is in imm2.  */
+/* Bash some of the imm registers and loc_pc.  */
+
+_spentry(mkcatch1v)
+	__(li imm2,0)
+	__(mkcatch())
+        __(blr)
+        
+_spentry(mkunwind)
+	__(lwi(arg_z,unbound_marker))
+	__(li imm2,fixnum_one)
+	__(mkcatch())
+	__(blr)
+        
+_spentry(mkcatchmv)
+	__(li imm2,fixnum_one)
+	__(mkcatch())
+        __(blr)
+        
+/* Caller has pushed tag and 0 or more values; nargs = nvalues.  */
+/* Otherwise, process unwind-protects and throw to indicated catch frame.  */
+	
+_spentry(throw)
+	__(ldr(imm1,tcr.catch_top(rcontext)))
+	__(li imm0,0) /* count intervening catch/unwind-protect frames.  */
+	__(cmpri(cr0,imm1,0))
+	__(ldrx(temp0,vsp,nargs))
+	__(beq- cr0,local_label(_throw_tag_not_found))
+local_label(_throw_loop):
+	__(ldr(temp1,catch_frame.catch_tag(imm1)))
+	__(cmpr(cr0,temp0,temp1))
+	__(mr imm2,imm1)
+	__(ldr(imm1,catch_frame.link(imm1)))
+	__(cmpri(cr1,imm1,0))
+	__(beq cr0,local_label(_throw_found))
+	__(addi imm0,imm0,fixnum_one)
+	__(beq- cr1,local_label(_throw_tag_not_found))
+	__(b local_label(_throw_loop))
+/* imm2: (tstack-consed) target catch frame, imm0: count of intervening  */
+/* frames. If target isn't a multiple-value receiver, discard extra values */
+/* (less hair, maybe.)  */
+local_label(_throw_found):
+	__(ldr(imm1,catch_frame.mvflag(imm2)))
+	__(cmpri(cr0,imm1,0))
+	__(cmpri(cr1,nargs,0))
+	__(li fn,0)
+	__(add imm1,vsp,nargs)
+	__(la imm1,-node_size(imm1))
+	__(bne cr0,local_label(_throw_all_values))
+	__(set_nargs(1))
+	__(beq cr1,local_label(_throw_default_1_val))
+	__(mr vsp,imm1)
+	__(b local_label(_throw_all_values))
+local_label(_throw_default_1_val):
+	__(li imm4,nil_value)
+	__(vpush(imm4))
+local_label(_throw_all_values):
+	__(bl _SPnthrowvalues)
+	__(ldr(imm3,tcr.catch_top(rcontext)))
+	__(ldr(imm1,tcr.db_link(rcontext)))
+	__(ldr(imm0,catch_frame.db_link(imm3)))
+	__(ldr(imm4,catch_frame.mvflag(imm3)))
+	__(cmpr(cr0,imm0,imm1))
+	__(cmpri(cr1,imm4,0))
+	__(la tsp,-((tsp_frame.fixed_overhead+fulltag_misc))(imm3))
+	__(beq cr0,local_label(_throw_dont_unbind))
+        __(bl _SPunbind_to)
+local_label(_throw_dont_unbind):
+	__(add imm0,vsp,nargs)
+	__(cmpri(cr0,nargs,0))
+	__(ldr(imm1,catch_frame.csp(imm3)))
+	__(ldr(imm1,lisp_frame.savevsp(imm1)))
+	__(bne cr1,local_label(_throw_multiple))
+        /* Catcher expects single value in arg_z  */
+	__(ldr(arg_z,-node_size(imm0)))
+	__(b local_label(_throw_pushed_values))
+local_label(_throw_multiple):
+	__(beq cr0,local_label(_throw_pushed_values))
+	__(mr imm2,nargs)
+local_label(_throw_mvloop):
+	__(subi imm2,imm2,fixnum_one)
+	__(cmpri(imm2,0))
+	__(ldru(temp0,-node_size(imm0)))
+	__(push(temp0,imm1))
+	__(bgt local_label(_throw_mvloop))
+local_label(_throw_pushed_values):
+	__(mr vsp,imm1)
+	__(ldr(imm1,catch_frame.xframe(imm3)))
+	__(str(imm1,tcr.xframe(rcontext)))
+	__(ldr(sp,catch_frame.csp(imm3)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(discard_lisp_frame())
+	__(mtlr loc_pc)
+        __(restore_catch_nvrs(imm3))
+	__(ldr(imm3,catch_frame.link(imm3)))
+	__(str(imm3,tcr.catch_top(rcontext)))
+	__(unlink(tsp))
+	__(blr)
+local_label(_throw_tag_not_found):
+	__(uuo_interr(error_throw_tag_missing,temp0))
+	__(strux(temp0,vsp,nargs))
+	__(b _SPthrow)
+
+
+/* This takes N multiple values atop the vstack.  */
+_spentry(nthrowvalues)
+        __(li imm1,1)
+	__(mr imm4,imm0)
+        __(str(imm1,tcr.unwinding(rcontext)))
+local_label(_nthrowv_nextframe):
+	__(subi imm4,imm4,fixnum_one)
+	__(cmpri(cr1,imm4,0))
+	__(ldr(temp0,tcr.catch_top(rcontext)))
+	__(ldr(imm1,tcr.db_link(rcontext)))
+	__(blt cr1,local_label(_nthrowv_done))
+	__(ldr(imm0,catch_frame.db_link(temp0)))
+	__(ldr(imm3,catch_frame.link(temp0)))
+	__(cmpr(cr0,imm0,imm1))
+	__(str(imm3,tcr.catch_top(rcontext)))
+	__(ldr(temp1,catch_frame.catch_tag(temp0)))
+	__(cmpri(cr7,temp1,unbound_marker))		/* unwind-protect ?  */
+	__(ldr(first_nvr,catch_frame.xframe(temp0)))
+	__(str(first_nvr,tcr.xframe(rcontext)))
+	__(ldr(sp,catch_frame.csp(temp0)))
+	__(beq cr0,local_label(_nthrowv_dont_unbind))
+	__(mflr loc_pc)
+        __(bl _SPunbind_to)
+	__(mtlr loc_pc)
+local_label(_nthrowv_dont_unbind):
+	__(beq cr7,local_label(_nthrowv_do_unwind))
+/* A catch frame.  If the last one, restore context from there.  */
+	__(bne cr1,local_label(_nthrowv_skip))
+	__(ldr(imm0,lisp_frame.savevsp(sp)))
+	__(str(rzero,lisp_frame.savevsp(sp)))	/* marker for stack overflow code  */
+	__(add imm1,vsp,nargs)
+	__(mr imm2,nargs)
+	__(b local_label(_nthrowv_push_test))
+local_label(_nthrowv_push_loop):
+	__(ldru(temp1,-node_size(imm1)))
+	__(push(temp1,imm0))
+local_label(_nthrowv_push_test):
+	__(cmpri(imm2,0))
+	__(subi imm2,imm2,fixnum_one)
+	__(bne local_label(_nthrowv_push_loop))
+	__(mr vsp,imm0)
+        __(restore_catch_nvrs(temp0))
+
+local_label(_nthrowv_skip):
+	__(la tsp,-(tsp_frame.fixed_overhead+fulltag_misc)(temp0))
+	__(unlink(tsp))
+	__(discard_lisp_frame())
+	__(b local_label(_nthrowv_nextframe))
+local_label(_nthrowv_do_unwind):
+        /* This is harder.  Call the cleanup code with the multiple */
+	/* values (and nargs, which is a fixnum.)  Remember the throw count  */
+        /* (also a fixnum) as well.  */
+        /* Save our caller's LR and FN in the csp frame created by the unwind-  */
+        /* protect.  (Clever, eh ?)  */
+	__(ldr(first_nvr,catch_frame.xframe(temp0)))
+	__(str(first_nvr,tcr.xframe(rcontext)))
+        __(restore_catch_nvrs(temp0))
+	__(la tsp,-(tsp_frame.fixed_overhead+fulltag_misc)(temp0))
+	__(unlink(tsp))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(nfn,lisp_frame.savefn(sp)))
+	__(mtctr loc_pc)	/* cleanup code address.  */
+	__(str(fn,lisp_frame.savefn(sp)))
+	__(mflr loc_pc)
+	__(mr fn,nfn)
+	__(str(loc_pc,lisp_frame.savelr(sp)))
+	__(dnode_align(imm0,nargs,tsp_frame.fixed_overhead+(2*node_size))) /* tsp overhead, nargs, throw count  */
+	__(TSP_Alloc_Var_Boxed_nz(imm0,imm1))
+	__(mr imm2,nargs)
+	__(add imm1,nargs,vsp)
+	__(la imm0,tsp_frame.data_offset(tsp))
+	__(str(nargs,0(imm0)))
+	__(b local_label(_nthrowv_tpushtest))
+local_label(_nthrowv_tpushloop):
+	__(ldru(temp0,-node_size(imm1)))
+	__(stru(temp0,node_size(imm0)))
+	__(subi imm2,imm2,fixnum_one)
+local_label(_nthrowv_tpushtest):
+	__(cmpri(imm2,0))
+	__(bne local_label(_nthrowv_tpushloop))
+	__(stru(imm4,node_size(imm0)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+        /* Interrupts should be disabled here (we're calling and returning */
+        /* from the cleanup form.  Clear the tcr.unwinding flag, so that */
+        /* interrupts can be taken if they're enabled in the cleanup form.  */
+        __(str(rzero,tcr.unwinding(rcontext)))        
+	__(bctrl)
+        __(li imm1,1)
+	__(la imm0,tsp_frame.data_offset(tsp))
+        __(str(imm1,tcr.unwinding(rcontext)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(discard_lisp_frame())
+	__(mtlr loc_pc)
+	__(ldr(nargs,0(imm0)))
+	__(mr imm2,nargs)
+	__(b local_label(_nthrowv_tpoptest))
+local_label(_nthrowv_tpoploop):
+	__(ldru(temp0,node_size(imm0)))
+	__(vpush(temp0))
+	__(subi imm2,imm2,fixnum_one)
+local_label(_nthrowv_tpoptest):
+	__(cmpri(imm2,0))
+	__(bne local_label(_nthrowv_tpoploop))
+	__(ldr(imm4,node_size(imm0)))
+	__(unlink(tsp))
+	__(b local_label(_nthrowv_nextframe))
+local_label(_nthrowv_done):
+        __(str(rzero,tcr.unwinding(rcontext)))
+        /* Poll for a deferred interrupt.  That clobbers nargs (which we've */
+        /* just expended a lot of effort to preserve), so expend a little *
+        /* more effort. */
+        __(mr imm4,nargs)
+        __(check_pending_interrupt())
+        __(mr nargs,imm4)
+        __(blr)
+
+/* This is a (slight) optimization.  When running an unwind-protect, */
+/* save the single value and the throw count in the tstack frame. */
+/* Note that this takes a single value in arg_z.  */
+_spentry(nthrow1value)
+        __(li imm1,1)
+	__(mr imm4,imm0)
+        __(str(imm1,tcr.unwinding(rcontext)))
+local_label(_nthrow1v_nextframe):
+	__(subi imm4,imm4,fixnum_one)
+	__(cmpri(cr1,imm4,0))
+	__(ldr(temp0,tcr.catch_top(rcontext)))
+	__(ldr(imm1,tcr.db_link(rcontext)))
+	__(set_nargs(1))
+	__(blt cr1,local_label(_nthrow1v_done))
+	__(ldr(imm3,catch_frame.link(temp0)))
+	__(ldr(imm0,catch_frame.db_link(temp0)))
+	__(cmpr(cr0,imm0,imm1))
+	__(str(imm3,tcr.catch_top(rcontext)))
+        __(ldr(imm3,catch_frame.xframe(temp0)))
+	__(ldr(temp1,catch_frame.catch_tag(temp0)))
+	__(cmpri(cr7,temp1,unbound_marker))		/* unwind-protect ?  */
+        __(str(imm3,tcr.xframe(rcontext)))
+	__(ldr(sp,catch_frame.csp(temp0)))
+	__(beq cr0,local_label(_nthrow1v_dont_unbind))
+	 __(mflr loc_pc)
+         __(bl _SPunbind_to)
+	 __(mtlr loc_pc)
+local_label(_nthrow1v_dont_unbind):
+	__(beq cr7,local_label(_nthrow1v_do_unwind))
+        /* A catch frame.  If the last one, restore context from there.  */
+	__(bne cr1,local_label(_nthrow1v_skip))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+        __(restore_catch_nvrs(temp0))
+local_label(_nthrow1v_skip):
+	__(la tsp,-(tsp_frame.fixed_overhead+fulltag_misc)(temp0))
+	__(unlink(tsp))
+	__(discard_lisp_frame())
+	__(b local_label(_nthrow1v_nextframe))
+local_label(_nthrow1v_do_unwind):
+        /* This is harder, but not as hard (not as much BLTing) as the  */
+        /* multiple-value case.  */
+        /* Save our caller's LR and FN in the csp frame created by the unwind-  */
+        /* protect.  (Clever, eh ?)  */
+
+        __(restore_catch_nvrs(temp0))
+	__(la tsp,-(tsp_frame.fixed_overhead+fulltag_misc)(temp0))
+	__(unlink(tsp))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(nfn,lisp_frame.savefn(sp)))
+	__(mtctr loc_pc)		/* cleanup code address.  */
+	__(str(fn,lisp_frame.savefn(sp)))
+	__(mflr loc_pc)
+	__(mr fn,nfn)
+	__(str(loc_pc,lisp_frame.savelr(sp)))
+	__(TSP_Alloc_Fixed_Boxed(2*node_size)) /* tsp overhead, value, throw count  */
+	__(str(arg_z,tsp_frame.data_offset(tsp)))
+	__(str(imm4,tsp_frame.data_offset+node_size(tsp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+        __(str(rzero,tcr.unwinding(rcontext)))
+	__(bctrl)
+        __(li imm1,1)
+	__(ldr(arg_z,tsp_frame.data_offset(tsp)))
+        __(str(imm1,tcr.unwinding(rcontext)))
+	__(ldr(imm4,tsp_frame.data_offset+node_size(tsp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(discard_lisp_frame())
+	__(mtlr loc_pc)
+	__(unlink(tsp))
+	__(b local_label(_nthrow1v_nextframe))
+local_label(_nthrow1v_done):
+        __(str(rzero,tcr.unwinding(rcontext)))
+        /* nargs has an undefined value here, so we can clobber it while */
+        /* polling for a deferred interrupt  */
+        __(check_pending_interrupt())
+        __(blr)
+
+/* This never affects the symbol's vcell  */
+/* Non-null symbol in arg_y, new value in arg_z          */
+_spentry(bind)
+        __(ldr(imm3,symbol.binding_index(arg_y)))
+        __(ldr(imm0,tcr.tlb_limit(rcontext)))
+        __(cmpri(imm3,0))
+        __(trlle(imm0,imm3))           /* tlb too small  */
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(ldrx(temp1,imm2,imm3))
+        __(beq 9f)
+        __(vpush(temp1))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(strx(arg_z,imm2,imm3))
+        __(str(vsp,tcr.db_link(rcontext)))
+        __(blr)
+9:
+        __(mr arg_z,arg_y)
+        __(lwi(arg_y,XSYMNOBIND))
+        __(set_nargs(2))
+        __(b _SPksignalerr)
+
+/* arg_z = symbol: bind it to its current value          */
+_spentry(bind_self)
+        __(ldr(imm3,symbol.binding_index(arg_z)))
+        __(ldr(imm0,tcr.tlb_limit(rcontext)))
+        __(cmpri(imm3,0))
+        __(trlle(imm0,imm3))           /* tlb too small  */
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(ldrx(temp1,imm2,imm3))
+        __(cmpri(cr1,temp1,no_thread_local_binding_marker))
+        __(beq 9f)
+        __(mr temp0,temp1)
+        __(bne cr1,1f)
+        __(ldr(temp0,symbol.vcell(arg_z)))
+1:              
+        __(vpush(temp1))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(strx(temp0,imm2,imm3))
+        __(str(vsp,tcr.db_link(rcontext)))
+        __(blr)
+9:      __(lwi(arg_y,XSYMNOBIND))
+        __(set_nargs(2))
+        __(b _SPksignalerr)
+
+/* Bind symbol in arg_z to NIL                 */
+_spentry(bind_nil)
+        __(ldr(imm3,symbol.binding_index(arg_z)))
+        __(ldr(imm0,tcr.tlb_limit(rcontext)))
+        __(cmpri(imm3,0))
+        __(beq- 9f)
+        __(trlle(imm0,imm3))           /* tlb too small  */
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(ldrx(temp1,imm2,imm3))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(li imm0,nil_value)
+        __(vpush(temp1))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(strx(imm0,imm2,imm3))
+        __(str(vsp,tcr.db_link(rcontext)))
+        __(blr)
+9:      __(lwi(arg_y,XSYMNOBIND))
+        __(set_nargs(2))
+        __(b _SPksignalerr)
+
+       
+/* Bind symbol in arg_z to its current value;  trap if symbol is unbound */
+_spentry(bind_self_boundp_check)
+        __(ldr(imm3,symbol.binding_index(arg_z)))
+        __(ldr(imm0,tcr.tlb_limit(rcontext)))
+        __(cmpri(imm3,0))
+        __(trlle(imm0,imm3))           /* tlb too small  */
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(ldrx(temp1,imm2,imm3))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(beq 9f)              /* no real tlb index  */
+        __(cmpri(temp1,no_thread_local_binding_marker))
+        __(mr temp0,temp1)
+        __(bne 1f)
+        __(ldr(temp0,symbol.vcell(arg_z)))
+1:      __(treqi(temp0,unbound_marker))       
+        __(vpush(temp1))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(strx(temp0,imm2,imm3))
+        __(str(vsp,tcr.db_link(rcontext)))
+        __(blr)
+9:      __(lwi(arg_y,XSYMNOBIND))
+        __(set_nargs(2))
+        __(b _SPksignalerr)
+
+
+/* The function pc_luser_xp() - which is used to ensure that suspended threads */
+/* are suspended in a GC-safe way - has to treat these subprims (which  */
+/* implement the EGC write-barrier) specially.  Specifically, a store that */
+/* might introduce an intergenerational reference (a young pointer stored  */
+/* in an old object) has to "memoize" that reference by setting a bit in  */
+/* the global "refbits" bitmap. */
+/* This has to happen atomically, and has to happen atomically wrt GC. */
+/* Note that updating a word in a bitmap is itself not atomic, unless we use */
+/* interlocked loads and stores. */
+
+
+/* For RPLACA and RPLACD, things are fairly simple: regardless of where we  */
+/* are in the function, we can do the store (even if it's already been done)  */
+/* and calculate whether or not we need to set the bit out-of-line.  (Actually */
+/* setting the bit needs to be done atomically, unless we're sure that other */
+/* threads are suspended.) */
+/* We can unconditionally set the suspended thread's PC to its LR. */
+	
+        .globl C(egc_write_barrier_start)
+_spentry(rplaca)
+C(egc_write_barrier_start):
+        __(cmplr(cr2,arg_z,arg_y))
+        __(_rplaca(arg_y,arg_z))
+        __(blelr cr2)
+        __(ref_global(imm2,ref_base))
+        __(sub imm0,arg_y,imm2)
+        __(load_highbit(imm3))
+        __(srri(imm0,imm0,dnode_shift))       
+        __(ref_global(imm1,oldspace_dnode_count))
+        __(extract_bit_shift_count(imm4,imm0))
+        __(cmplr(imm0,imm1))
+        __(srr(imm3,imm3,imm4))
+        __(srri(imm0,imm0,bitmap_shift))       
+        __(ref_global(imm2,refbits))
+        __(bgelr)
+        __(slri(imm0,imm0,word_shift))
+        __(ldrx(imm1,imm2,imm0))
+        __(and. imm1,imm1,imm3)
+        __(bnelr)
+1:      __(lrarx(imm1,imm2,imm0))
+        __(or imm1,imm1,imm3)
+        __(strcx(imm1,imm2,imm0))
+        __(bne- 1b)
+        __(isync)
+        __(blr)
+
+        .globl C(egc_rplacd)
+_spentry(rplacd)
+C(egc_rplacd):
+        __(cmplr(cr2,arg_z,arg_y))
+	__(_rplacd(arg_y,arg_z))
+        __(blelr cr2)
+        __(ref_global(imm2,ref_base))
+        __(sub imm0,arg_y,imm2)
+        __(load_highbit(imm3))
+        __(srri(imm0,imm0,dnode_shift))       
+        __(ref_global(imm1,oldspace_dnode_count))
+        __(extract_bit_shift_count(imm4,imm0))
+        __(cmplr(imm0,imm1))
+        __(srr(imm3,imm3,imm4))
+        __(srri(imm0,imm0,bitmap_shift))       
+        __(ref_global(imm2,refbits))
+        __(bgelr)
+        __(slri(imm0,imm0,word_shift))
+        __(ldrx(imm1,imm2,imm0))
+        __(and. imm1,imm1,imm3)
+        __(bnelr)        
+1:      __(lrarx(imm1,imm2,imm0))
+        __(or imm1,imm1,imm3)
+        __(strcx(imm1,imm2,imm0))
+        __(bne- 1b)
+        __(isync)
+        __(blr)
+
+/* Storing into a gvector can be handled the same way as storing into a CONS. */
+
+        .globl C(egc_gvset)
+_spentry(gvset)
+C(egc_gvset):
+        __(cmplr(cr2,arg_z,arg_x))
+        __(la imm0,misc_data_offset(arg_y))
+        __(strx(arg_z,arg_x,imm0))
+        __(blelr cr2)
+        __(add imm0,imm0,arg_x)
+        __(ref_global(imm2,ref_base))
+        __(load_highbit(imm3))
+        __(ref_global(imm1,oldspace_dnode_count))
+        __(sub imm0,imm0,imm2)
+        __(srri(imm0,imm0,dnode_shift))       
+        __(cmplr(imm0,imm1))
+        __(extract_bit_shift_count(imm4,imm0))
+        __(srri(imm0,imm0,bitmap_shift))       
+        __(srr(imm3,imm3,imm4))
+        __(ref_global(imm2,refbits))
+        __(bgelr)
+        __(slri(imm0,imm0,word_shift))
+        __(ldrx(imm1,imm2,imm0))
+        __(and. imm1,imm1,imm3)
+        __(bnelr)        
+1:      __(lrarx(imm1,imm2,imm0))
+        __(or imm1,imm1,imm3)
+        __(strcx(imm1,imm2,imm0))
+        __(bne- 1b)
+        __(isync)
+        __(blr)
+
+/* This is a special case of storing into a gvector: if we need to memoize  */
+/* the store, record the address of the hash-table vector in the refmap,  */
+/* as well. */
+        .globl C(egc_set_hash_key)        
+_spentry(set_hash_key)
+C(egc_set_hash_key):
+        __(cmplr(cr2,arg_z,arg_x))
+        __(la imm0,misc_data_offset(arg_y))
+        __(strx(arg_z,arg_x,imm0))
+        __(blelr cr2)
+        __(add imm0,imm0,arg_x)
+        __(ref_global(imm2,ref_base))
+        __(load_highbit(imm3))
+        __(ref_global(imm1,oldspace_dnode_count))
+        __(sub imm0,imm0,imm2)
+        __(srri(imm0,imm0,dnode_shift))       
+        __(cmplr(imm0,imm1))
+        __(extract_bit_shift_count(imm4,imm0))
+        __(srri(imm0,imm0,bitmap_shift))       
+        __(srr(imm3,imm3,imm4))
+        __(ref_global(imm2,refbits))
+        __(bgelr)
+        __(slri(imm0,imm0,word_shift))
+        __(ldrx(imm1,imm2,imm0))
+        __(and. imm1,imm1,imm3)
+        __(bne 2f)        
+1:      __(lrarx(imm1,imm2,imm0))
+        __(or imm1,imm1,imm3)
+        __(strcx(imm1,imm2,imm0))
+        __(bne- 1b)
+        __(isync)
+2:              
+        __(ref_global(imm1,ref_base))
+        __(sub imm0,arg_x,imm1)
+        __(srri(imm0,imm0,dnode_shift))
+        __(load_highbit(imm3))
+        __(extract_bit_shift_count(imm4,imm0))
+        __(srri(imm0,imm0,bitmap_shift))
+        __(srr(imm3,imm3,imm4))
+        __(slri(imm0,imm0,word_shift))
+        __(ldrx(imm1,imm2,imm0))
+        __(and. imm1,imm1,imm3)
+        __(bnelr)
+3:      __(lrarx(imm1,imm2,imm0))
+        __(or imm1,imm1,imm3)
+        __(strcx(imm1,imm2,imm0))
+        __(bne- 3b)
+        __(isync)
+        __(blr)
+        
+/*
+   Interrupt handling (in pc_luser_xp()) notes:	
+   If we are in this function and before the test which follows the
+   conditional (at egc_store_node_conditional), or at that test
+   and cr0[eq] is clear, pc_luser_xp() should just let this continue
+   (we either haven't done the store conditional yet, or got a
+   possibly transient failure.)  If we're at that test and the
+   cr0[EQ] bit is set, then the conditional store succeeded and
+   we have to atomically memoize the possible intergenerational
+   reference.  Note that the local labels 4 and 5 are in the
+   body of the next subprim (and at or beyond 'egc_write_barrier_end').
+
+   N.B:	it's not possible to really understand what's going on just
+   by the state of the cr0[eq] bit.  A transient failure in the
+   conditional stores that handle memoization might clear cr0[eq]
+   without having completed the memoization.
+*/
+
+        .globl C(egc_store_node_conditional)
+        .globl C(egc_write_barrier_end)
+_spentry(store_node_conditional)
+C(egc_store_node_conditional):
+        __(cmplr(cr2,arg_z,arg_x))
+        __(vpop(temp0))
+        __(unbox_fixnum(imm4,temp0))
+1:      __(lrarx(temp1,arg_x,imm4))
+        __(cmpr(cr1,temp1,arg_y))
+        __(bne cr1,5f)
+        __(strcx(arg_z,arg_x,imm4))
+	.globl C(egc_store_node_conditional_test)
+C(egc_store_node_conditional_test):	
+        __(bne 1b)
+        __(isync)
+        __(add imm0,imm4,arg_x)
+        __(ref_global(imm2,ref_base))
+        __(ref_global(imm1,oldspace_dnode_count))
+        __(sub imm0,imm0,imm2)
+        __(load_highbit(imm3))
+        __(srri(imm0,imm0,dnode_shift))       
+        __(cmplr(imm0,imm1))
+        __(extract_bit_shift_count(imm2,imm0))
+        __(srri(imm0,imm0,bitmap_shift))       
+        __(srr(imm3,imm3,imm2))
+        __(ref_global(imm2,refbits))
+        __(bge 4f)
+        __(slri(imm0,imm0,word_shift))
+2:      __(lrarx(imm1,imm2,imm0))
+        __(or imm1,imm1,imm3)
+        __(strcx( imm1,imm2,imm0))
+        __(bne- 2b)
+        __(isync)
+        __(b 4f)
+
+/* arg_z = new value, arg_y = expected old value, arg_x = hash-vector,
+   vsp[0] = (boxed) byte-offset 
+   Interrupt-related issues are as in store_node_conditional, but
+   we have to do more work to actually do the memoization.*/
+_spentry(set_hash_key_conditional)
+	.globl C(egc_set_hash_key_conditional)
+C(egc_set_hash_key_conditional):
+	__(cmplr(cr2,arg_z,arg_x))
+	__(vpop(imm4))
+	__(unbox_fixnum(imm4,imm4))
+1:	__(lrarx(temp1,arg_x,imm4))
+	__(cmpr(cr1,temp1,arg_y))
+	__(bne cr1,5f)
+	__(strcx(arg_z,arg_x,imm4))
+	.globl C(egc_set_hash_key_conditional_test)
+C(egc_set_hash_key_conditional_test):	
+	__(bne 1b)
+	__(isync)
+	__(add imm0,imm4,arg_x)
+	__(ref_global(imm2,ref_base))
+	__(ref_global(imm1,oldspace_dnode_count))
+	__(sub imm0,imm0,imm2)
+	__(load_highbit(imm3))
+	__(srri(imm0,imm0,dnode_shift))
+	__(cmplr(imm0,imm1))
+	__(extract_bit_shift_count(imm2,imm0))
+	__(srri(imm0,imm0,bitmap_shift))
+	__(srr(imm3,imm3,imm2))
+	__(ref_global(imm2,refbits))
+	__(bge 4f)
+	__(slri(imm0,imm0,word_shift))
+2:	__(lrarx(imm1,imm2,imm0))
+	__(or imm1,imm1,imm3)
+	__(strcx(imm1,imm2,imm0))
+	__(bne- 2b)
+	__(isync)
+	/* Memoize hash table header */		
+        __(ref_global(imm1,ref_base))
+        __(sub imm0,arg_x,imm1)
+        __(srri(imm0,imm0,dnode_shift))
+        __(load_highbit(imm3))
+        __(extract_bit_shift_count(imm4,imm0))
+        __(srri(imm0,imm0,bitmap_shift))
+        __(srr(imm3,imm3,imm4))
+        __(slri(imm0,imm0,word_shift))
+        __(ldrx(imm1,imm2,imm0))
+        __(and. imm1,imm1,imm3)
+        __(bne 4f)
+3:      __(lrarx(imm1,imm2,imm0))
+        __(or imm1,imm1,imm3)
+        __(strcx(imm1,imm2,imm0))
+        __(bne- 3b)
+        __(isync)
+C(egc_write_barrier_end):
+4:	__(li arg_z,t_value)
+	__(blr)
+5:      __(li imm0,RESERVATION_DISCHARGE)
+        __(strcx(rzero,0,imm0))
+	__(li arg_z,nil_value)
+	__(blr)
+	
+	
+	       
+_spentry(conslist)
+	__(li arg_z,nil_value)
+	__(cmpri(nargs,0))
+	__(b 2f)	
+1:
+	__(ldr(temp0,0(vsp)))
+	__(cmpri(nargs,fixnum_one))
+	__(la vsp,node_size(vsp))
+	__(Cons(arg_z,temp0,arg_z))
+	__(subi nargs,nargs,fixnum_one)
+2:
+	__(bne 1b)
+	__(blr)
+	
+/* do list*: last arg in arg_z, all others vpushed, nargs set to #args vpushed.  */
+/* Cons, one cons cell at at time.  Maybe optimize this later.  */
+_spentry(conslist_star)
+	__(cmpri(nargs,0))
+	__(b 2f)	
+1:
+	__(ldr(temp0,0(vsp)))
+	__(cmpri(nargs,fixnum_one))
+	__(la vsp,node_size(vsp))
+	__(Cons(arg_z,temp0,arg_z))
+	__(subi nargs,nargs,fixnum_one)
+2:
+	__(bne 1b)
+	__(blr)
+
+/* We always have to create a tsp frame (even if nargs is 0), so the compiler  */
+/* doesn't get confused.  */
+_spentry(stkconslist)
+	__(li arg_z,nil_value)
+	__(cmpri(cr1,nargs,0))
+	__(add imm1,nargs,nargs)
+	__(addi imm1,imm1,tsp_frame.fixed_overhead)
+	__(TSP_Alloc_Var_Boxed(imm1,imm2))
+	__(la imm1,tsp_frame.data_offset+fulltag_cons(tsp))
+	__(b 2f)
+1:	__(ldr(temp0,0(vsp)))
+	__(cmpri(cr1,nargs,fixnum_one))
+	__(la vsp,node_size(vsp))
+	__(_rplaca(imm1,temp0))
+	__(_rplacd(imm1,arg_z))
+	__(mr arg_z,imm1)
+	__(la imm1,cons.size(imm1))
+	__(la nargs,-fixnum_one(nargs))
+2:
+	__(bne cr1,1b)
+	__(blr)
+
+/* do list*: last arg in arg_z, all others vpushed,  */
+/* nargs set to #args vpushed.  */
+_spentry(stkconslist_star)
+	__(cmpri(cr1,nargs,0))
+	__(add imm1,nargs,nargs)
+	__(addi imm1,imm1,tsp_frame.fixed_overhead)
+	__(TSP_Alloc_Var_Boxed(imm1,imm2))
+	__(la imm1,tsp_frame.data_offset+fulltag_cons(tsp))
+	__(b 2f)
+1:	__(ldr(temp0,0(vsp)))
+	__(cmpri(cr1,nargs,fixnum_one))
+	__(la vsp,node_size(vsp))
+	__(_rplaca(imm1,temp0))
+	__(_rplacd(imm1,arg_z))
+	__(mr arg_z,imm1)
+	__(la imm1,cons.size(imm1))
+	__(la nargs,-fixnum_one(nargs))
+2:
+	__(bne cr1,1b)
+	__(blr)
+
+
+/* Make a stack-consed simple-vector out of the NARGS objects  */
+/* on top of the vstack; return it in arg_z.  */
+_spentry(mkstackv)
+	__(cmpri(cr1,nargs,0))
+	__(dnode_align(imm1,nargs,tsp_frame.fixed_overhead+node_size))
+	__(TSP_Alloc_Var_Boxed_nz(imm1,imm2))
+	__(slwi imm0,nargs,num_subtag_bits-fixnumshift)
+	__(ori imm0,imm0,subtag_simple_vector)
+	__(str(imm0,tsp_frame.data_offset(tsp)))
+	__(la arg_z,tsp_frame.data_offset+fulltag_misc(tsp))
+	__(beq- cr1,2f)
+	__(la imm0,misc_data_offset(arg_z))
+	__(add imm1,imm0,nargs)
+1:
+	__(la nargs,-node_size(nargs))
+	__(cmpri(cr1,nargs,0))
+	__(ldr(temp1,0(vsp)))
+	__(la vsp,node_size(vsp))
+	__(stru(temp1,-node_size(imm1)))
+	__(bne cr1,1b)
+2:
+	__(blr)
+
+	
+        
+
+_spentry(setqsym)
+	__(ldr(imm0,symbol.flags(arg_y)))
+	__(andi. imm0,imm0,sym_vbit_const_mask)
+	__(beq _SPspecset)
+	__(mr arg_z,arg_y)
+	__(lwi(arg_y,XCONST))
+	__(set_nargs(2))
+	__(b _SPksignalerr)
+
+
+	
+_spentry(progvsave)
+	/* Error if arg_z isn't a proper list.  That's unlikely, */
+	/* but it's better to check now than to crash later. */
+	
+	__(cmpri(arg_z,nil_value))
+	__(mr arg_x,arg_z)	/* fast  */
+	__(mr temp1,arg_z)	/* slow  */
+	__(beq 9f)		/* Null list is proper  */
+0:	
+	__(trap_unless_list(arg_x,imm0))
+	__(_cdr(temp2,arg_x))	/* (null (cdr fast)) ?  */
+	__(cmpri(cr3,temp2,nil_value))
+	__(trap_unless_list(temp2,imm0,cr0))
+	__(_cdr(arg_x,temp2))
+	__(beq cr3,9f)
+	__(_cdr(temp1,temp1))
+	__(cmpr(arg_x,temp1))
+	__(bne 0b)
+	__(lwi(arg_y,XIMPROPERLIST))
+	__(set_nargs(2))
+	__(b _SPksignalerr)
+9:	/* Whew 	 */
+	
+        /* Next, determine the length of arg_y.  We  */
+        /* know that it's a proper list.  */
+	__(li imm0,-node_size)
+	__(mr arg_x,arg_y)
+1:
+	__(cmpri(cr0,arg_x,nil_value))
+	__(la imm0,node_size(imm0))
+	__(_cdr(arg_x,arg_x))
+	__(bne 1b)
+	/* imm0 is now (boxed) triplet count.  */
+	/* Determine word count, add 1 (to align), and make room.  */
+	/* if count is 0, make an empty tsp frame and exit  */
+	__(cmpri(cr0,imm0,0))
+	__(add imm1,imm0,imm0)
+	__(add imm1,imm1,imm0)
+        __(dnode_align(imm1,imm1,node_size))
+	__(bne+ cr0,2f)
+	 __(TSP_Alloc_Fixed_Boxed(2*node_size))
+	 __(blr)
+2:
+	__(la imm1,tsp_frame.fixed_overhead(imm1))	/* tsp header  */
+	__(TSP_Alloc_Var_Boxed_nz(imm1,imm2))
+	__(str(imm0,tsp_frame.data_offset(tsp)))
+	__(ldr(imm2,tsp_frame.backlink(tsp)))
+	__(mr arg_x,arg_y)
+	__(ldr(imm1,tcr.db_link(rcontext)))
+        __(ldr(imm3,tcr.tlb_limit(rcontext)))
+3:
+        __(cmpri(cr1,arg_z,nil_value))
+	__(_car(temp0,arg_x))
+        __(ldr(imm0,symbol.binding_index(temp0)))
+	__(_cdr(arg_x,arg_x))
+        __(trlle(imm3,imm0))
+        __(ldr(imm4,tcr.tlb_pointer(rcontext))) /* Need to reload after trap  */
+        __(ldrx(temp3,imm4,imm0))
+	__(cmpri(cr0,arg_x,nil_value))
+        __(li temp2,unbound_marker)
+        __(beq cr1,4f)
+	__(_car(temp2,arg_z))
+	__(_cdr(arg_z,arg_z))
+4:      __(push(temp3,imm2))
+	__(push(imm0,imm2))
+	__(push(imm1,imm2))
+        __(strx(temp2,imm4,imm0))
+	__(mr imm1,imm2)
+	__(bne cr0,3b)
+	__(str(imm2,tcr.db_link(rcontext)))
+	__(blr)
+
+	
+/* Allocate a miscobj on the temp stack.  (Push a frame on the tsp and  */
+/* heap-cons the object if there's no room on the tstack.)  */
+_spentry(stack_misc_alloc)
+        __ifdef([PPC64])
+         __(extract_unsigned_byte_bits_(imm2,arg_y,56))
+         __(unbox_fixnum(imm0,arg_z))
+         __(clrldi imm2,imm0,64-nlowtagbits)
+         __(extract_fulltag(imm1,imm0))
+         __(bne cr0,9f)
+         __(cmpdi cr2,imm2,lowtag_nodeheader)
+         __(cmpdi cr4,imm1,ivector_class_8_bit)
+         __(cmpdi cr1,imm1,ivector_class_64_bit)
+         __(cmpdi cr3,imm1,ivector_class_32_bit)
+         __(cmpdi cr5,imm1,ivector_class_other_bit)
+         __(sldi imm1,arg_y,num_subtag_bits-fixnumshift)
+         __(mr imm2,arg_y)
+         __(beq cr2,3f)
+         __(cmpdi cr2,imm0,subtag_bit_vector)
+         __(beq cr1,3f)
+         __(beq cr3,1f)
+         __(beq cr4,2f)
+         __(beq cr2,0f)
+         /* 2 bytes per element  */
+         __(srdi imm2,imm2,2)
+         __(b 3f)
+0:       /* bit-vector case  */
+         __(addi imm2,imm2,7<<fixnumshift)
+         __(srdi imm2,imm2,3+fixnumshift)
+         __(b 3f)        
+         /* 4 bytes per element  */
+1:       __(srdi imm2,imm2,1)
+         __(b 3f)
+2:       /* 1 byte per element  */
+         __(srdi imm2,imm2,3)
+3:       /* 8 bytes per element  */
+         __(or imm0,imm1,imm0)   /* imm0 = header, imm2 = byte count  */
+         __(dnode_align(imm3,imm2,tsp_frame.fixed_overhead+node_size))
+	 __(cmpldi cr0,imm3,tstack_alloc_limit) /* more than limit ?  */
+	 __(bgt- cr0,4f)
+	 __(TSP_Alloc_Var_Boxed_nz(imm3,imm4))
+        /* Slap the header on the vector, then return.  */
+	 __(str(imm0,tsp_frame.data_offset(tsp)))
+	 __(la arg_z,tsp_frame.data_offset+fulltag_misc(tsp))
+	__(blr)
+        /* Too large to safely fit on tstack.  Heap-cons the vector, but make  */
+        /* sure that there's an empty tsp frame to keep the compiler happy.  */
+4:       __(TSP_Alloc_Fixed_Unboxed(0))
+	 __(b _SPmisc_alloc)
+        __else
+	 __(rlwinm. imm2,arg_y,32-fixnumshift,0,(8+fixnumshift)-1)
+	 __(unbox_fixnum(imm0,arg_z))
+	 __(extract_fulltag(imm1,imm0))
+	 __(bne- cr0,9f)
+	 __(cmpri(cr0,imm1,fulltag_nodeheader))
+	 __(mr imm3,imm0)
+	 __(cmplri(cr1,imm0,max_32_bit_ivector_subtag))
+	 __(rlwimi imm0,arg_y,num_subtag_bits-fixnum_shift,0,31-num_subtag_bits) /* imm0 now = header  */
+	 __(mr imm2,arg_y)
+	 __(beq cr0,1f)	/* do probe if node object  */
+        		/* (fixnum element count = byte count).  */
+	 __(cmplri(cr0,imm3,max_16_bit_ivector_subtag))
+	 __(bng cr1,1f) /* do probe if 32-bit imm object  */
+	 __(cmplri(cr1,imm3,max_8_bit_ivector_subtag))
+	 __(srwi imm2,imm2,1)
+	 __(bgt cr0,3f)
+	 __(bgt cr1,1f)
+	 __(srwi imm2,imm2,1)
+/* imm2 now = byte count.  Add 4 for header, 7 to align, then  */
+/*	clear low three bits.  */
+1:
+         __(dnode_align(imm3,imm2,tsp_frame.fixed_overhead+node_size))
+	 __(cmplri(cr0,imm3,tstack_alloc_limit)) /* more than limit ?  */
+	 __(bgt- cr0,0f)
+	 __(TSP_Alloc_Var_Boxed_nz(imm3,imm4))
+
+/* Slap the header on the vector, then return.  */
+	 __(str(imm0,tsp_frame.data_offset(tsp)))
+	 __(la arg_z,tsp_frame.data_offset+fulltag_misc(tsp))
+	 __(blr)
+9: 
+
+
+
+/* Too large to safely fit on tstack.  Heap-cons the vector, but make  */
+/* sure that there's an empty tsp frame to keep the compiler happy.  */
+0:
+	 __(TSP_Alloc_Fixed_Unboxed(0))
+	 __(b _SPmisc_alloc)
+3:
+	 __(cmplri(imm3,subtag_double_float_vector))
+	 __(slwi imm2,arg_y,1)
+	 __(beq 1b)
+	 __(addi imm2,arg_y,7<<fixnumshift)
+	 __(srwi imm2,imm2,fixnumshift+3)
+	 __(b 1b)
+        __endif
+        
+/* subtype (boxed, of course) is vpushed, followed by nargs bytes worth of  */
+/* initial-contents.  Note that this can be used to cons any type of initialized  */
+/* node-header'ed misc object (symbols, closures, ...) as well as vector-like  */
+/* objects.  */
+/* Note that we're guaranteed to win (or force GC, or run out of memory)  */
+/* because nargs < 32K.  */
+_spentry(gvector)
+        __(subi nargs,nargs,node_size)
+	__(ldrx(arg_z,vsp,nargs))
+	__(unbox_fixnum(imm0,arg_z))
+        __ifdef([PPC64])
+         __(sldi imm1,nargs,num_subtag_bits-fixnum_shift)
+         __(or imm0,imm0,imm1)
+        __else
+	 __(rlwimi imm0,nargs,num_subtag_bits-fixnum_shift,0,31-num_subtag_bits)
+        __endif
+        __(dnode_align(imm1,nargs,node_size))
+	__(Misc_Alloc(arg_z,imm0,imm1))
+	__(mr imm1,nargs)
+	__(la imm2,misc_data_offset(imm1))
+	__(b 2f)
+1:
+	__(strx(temp0,arg_z,imm2))
+2:
+	__(subi imm1,imm1,node_size)
+	__(cmpri(cr0,imm1,0))
+	__(subi imm2,imm2,node_size)
+	__(vpop(temp0))         /* Note the intentional fencepost: */
+				/* discard the subtype as well.  */
+	__(bge cr0,1b)
+	__(blr)
+	
+	
+/* funcall temp0, returning multiple values if it does.  */
+_spentry(mvpass)
+	__(cmpri(cr0,nargs,node_size*nargregs))
+	__(mflr loc_pc)
+	__(mr imm0,vsp)
+	__(ble+ cr0,1f)
+	 __(subi imm0,imm0,node_size*nargregs)
+	 __(add imm0,imm0,nargs)
+1:
+	__(build_lisp_frame(fn,loc_pc,imm0))
+	__(ref_global(loc_pc,ret1val_addr))
+	__(li fn,0)
+	__(mtlr loc_pc)
+	__(do_funcall())
+	
+/* ret1valn returns "1 multiple value" when a called function does not  */
+/* return multiple values.  Its presence on the stack (as a return address)  */
+/* identifies the stack frame to code which returns multiple values.  */
+
+_exportfn(C(ret1valn))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(discard_lisp_frame())
+	__(vpush(arg_z))
+	__(set_nargs(1))
+	__(blr)
+	
+_spentry(fitvals)
+	__(subf. imm0,nargs,imm0)
+	__(li imm1,nil_value)
+	__(bge 2f)
+	__(sub vsp,vsp,imm0)
+	__(blr)
+1:
+	__(subic. imm0,imm0,node_size)
+	__(vpush(imm1))
+	__(addi nargs,nargs,node_size)
+2:
+	__(bne 1b)
+	__(blr)
+
+
+_spentry(nthvalue)
+	__(add imm0,vsp,nargs)
+	__(ldr(imm1,0(imm0)))
+	__(cmplr(imm1,nargs))	/*  do unsigned compare:	 if (n < 0) => nil.  */
+	__(li arg_z,nil_value)
+	__(neg imm1,imm1)
+	__(subi imm1,imm1,node_size)
+	__(bge 1f)
+	__(ldrx(arg_z,imm0,imm1))
+1:	
+	__(la vsp,node_size(imm0))
+	__(blr)
+        
+
+/* Come here to return multiple values when  */
+/* the caller's context isn't saved in a lisp_frame.  */
+/* lr, fn valid; temp0 = entry vsp  */
+
+_spentry(values)
+	__(mflr loc_pc)
+local_label(return_values):  
+	__(ref_global(imm0,ret1val_addr))
+	__(li arg_z,nil_value)
+	/* max tsp frame is 4K. 8+8 is overhead for save_values_to_tsp below  */
+	/* and @do_unwind in nthrowvalues in "sp_catch.s".  */
+	__(cmpri(cr2,nargs,4096-(dnode_size+dnode_size)))
+	__(cmpr(cr1,imm0,loc_pc))
+	__(cmpri(cr0,nargs,fixnum_one))
+	__(bge cr2,2f)
+	__(beq+ cr1,3f)
+	__(mtlr loc_pc)
+	__(add imm0,nargs,vsp)
+	__(blt- cr0,1f)
+	__(ldr(arg_z,-node_size(imm0)))
+1:
+	__(mr vsp,temp0)
+	__(blr)
+
+2:
+	__(uuo_interr(error_too_many_values,nargs))
+	__(b 2b)
+
+/* Return multiple values to real caller.  */
+3:
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(add imm1,nargs,vsp)
+	__(ldr(imm0,lisp_frame.savevsp(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(cmpr(cr0,imm1,imm0)) /* a fairly common case  */
+	__(mtlr loc_pc)
+	__(cmpri(cr1,nargs,fixnum_one)) /* sadly, a very common case  */
+	__(discard_lisp_frame())
+	__(beqlr cr0) /* already in the right place  */
+	__(bne cr1,4f)
+	 __(ldr(arg_z,0(vsp)))
+	 __(mr vsp,imm0)
+	 __(vpush(arg_z))
+	 __(blr)
+4:
+	__(blt cr1,6f)
+	__(li imm2,fixnum_one)
+5:
+	__(cmpr(cr0,imm2,nargs))
+	__(addi imm2,imm2,fixnum_one)
+	__(ldru(arg_z,-node_size(imm1)))
+	__(push(arg_z,imm0))
+	__(bne cr0,5b)
+6:
+	__(mr vsp,imm0)
+	__(blr)
+
+	.globl C(nvalret)
+	
+/* Come here with saved context on top of stack.  */
+_spentry(nvalret)
+C(nvalret):	
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(temp0,lisp_frame.savevsp(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(discard_lisp_frame())
+        __(b local_label(return_values))
+        	
+/* Provide default (NIL) values for &optional arguments; imm0 is  */
+/* the (fixnum) upper limit on the total of required and &optional  */
+/* arguments.  nargs is preserved, all arguments wind up on the  */
+/* vstack.  */
+_spentry(default_optional_args)
+	__(cmplr( cr7,nargs,imm0))
+	__(li imm5,nil_value)
+	__(vpush_argregs())
+	__(mr imm1,nargs)
+	__(bgelr cr7)
+1:	
+	__(addi imm1,imm1,fixnum_one)
+	__(cmpr(cr0,imm1,imm0))
+	__(vpush(imm5))
+	__(bne cr0,1b)
+	__(blr)
+	
+/* Indicate whether &optional arguments were actually supplied.  nargs  */
+/* contains the actual arg count (minus the number of required args);  */
+/* imm0 contains the number of &optional args in the lambda list.  */
+/* Note that nargs may be > imm0 if &rest/&key is involved.  */
+_spentry(opt_supplied_p)
+	__(li imm1,0)
+1:
+	/* (vpush (< imm1 nargs))  */
+        __ifdef([PPC64])
+	 __(xor imm2,imm1,nargs)
+	 __(sradi imm2,imm2,63)
+	 __(or imm2,imm2,imm1)
+	 __(addi imm1,imm1,fixnumone)
+	 __(cmpr(cr0,imm1,imm0))
+	 __(subf imm2,nargs,imm2)
+	 __(srdi imm2,imm2,63)
+         __(mulli imm2,imm2,t_offset)
+	 __(addi imm2,imm2,nil_value)
+	 __(vpush(imm2))
+	 __(bne cr0,1b)
+	 __(blr)
+        __else
+	 __(xor imm2,imm1,nargs)
+	 __(srawi imm2,imm2,31)
+	 __(or imm2,imm2,imm1)
+	 __(addi imm1,imm1,fixnumone)
+	 __(cmpr(cr0,imm1,imm0))
+	 __(subf imm2,nargs,imm2)
+	 __(srwi imm2,imm2,31)
+	 __(insrwi imm2,imm2,1,27)
+	 __(addi imm2,imm2,nil_value)
+	 __(vpush(imm2))
+	 __(bne cr0,1b)
+	 __(blr)
+        __endif
+	
+
+
+/* If nargs is <= imm0, vpush a nil.  Otherwise, cons a list of length  */
+/* (- nargs imm0) and vpush it.  */
+/* Use this entry point to heap-cons a simple &rest arg.  */
+_spentry(heap_rest_arg)
+	__(li imm0,0)
+	__(vpush_argregs())
+ 	__(sub imm1,nargs,imm0)
+	__(cmpri(imm1,0))
+	__(li arg_z,nil_value)
+	__(b 2f)
+1:
+	__(ldr(temp0,0(vsp)))
+	__(cmpri(imm1,fixnum_one))
+	__(la vsp,node_size(vsp))
+	__(Cons(arg_z,temp0,arg_z))
+	__(subi imm1,imm1,fixnum_one)
+2:
+	__(bgt 1b)
+	__(vpush(arg_z))
+	__(blr)
+
+	
+/* And this entry point when the argument registers haven't yet been  */
+/* vpushed (as is typically the case when required/&rest but no  */
+/* &optional/&key.)  */
+_spentry(req_heap_rest_arg)
+	__(vpush_argregs())
+ 	__(sub imm1,nargs,imm0)
+	__(cmpri(imm1,0))
+	__(li arg_z,nil_value)
+	__(b 2f)
+1:
+	__(ldr(temp0,0(vsp)))
+	__(cmpri(imm1,fixnum_one))
+	__(la vsp,node_size(vsp))
+	__(Cons(arg_z,temp0,arg_z))
+	__(subi imm1,imm1,fixnum_one)
+2:
+	__(bgt 1b)
+	__(vpush(arg_z))
+	__(blr)
+
+
+_spentry(heap_cons_rest_arg)
+ 	__(sub imm1,nargs,imm0)
+	__(cmpri(imm1,0))
+	__(li arg_z,nil_value)
+	__(b 2f)
+1:
+	__(ldr(temp0,0(vsp)))
+	__(cmpri(imm1,fixnum_one))
+	__(la vsp,node_size(vsp))
+	__(Cons(arg_z,temp0,arg_z))
+	__(subi imm1,imm1,fixnum_one)
+2:
+	__(bgt 1b)
+	__(vpush(arg_z))
+	__(blr)
+
+	
+_spentry(simple_keywords)
+	__(li imm0,0)
+        __(vpush_argregs())
+        __(b _SPkeyword_bind)
+                
+_spentry(keyword_args)
+	__(vpush_argregs())
+        __(b _SPkeyword_bind)
+
+/* Treat the last (- nargs imm0) values on the vstack as keyword/value  */
+/* pairs.  There'll be imm3 keyword arguments.  Imm2 contains flags  */
+/* that indicate whether &allow-other-keys was specified and whether  */
+/* or not to leave the keyword/value pairs on the vstack for an &rest  */
+/* argument.  Temp3 contains a vector of keyword specifiers which we  */
+/* must (in general) match.  */
+/* If the number of arguments is greater than imm0, the difference must  */
+/* be even.  */
+/* Note that the caller hasn't yet saved its caller's context and that  */
+/* the temp registers used to pass next_method_context  */
+/* (temp1) may still have "live" values in them, as does nfn (temp2).  */
+
+define([keyword_flags],[imm2])
+define([keyword_vector],[temp3])
+define([keyword_count],[imm3])
+
+
+
+define([varptr],[save0])
+define([valptr],[save1])
+define([limit],[save2])
+
+_spentry(keyword_bind)
+        /* Before we can really do anything, we have to  */
+        /* save the caller's context.  To do so, we need to know  */
+        /* how many args have actually been pushed.  Ordinarily, that'd  */
+        /* be "nargs", but we may have pushed more args than we received  */
+	/* if we had to default any &optionals.  */
+	/* So, the number of args pushed so far is the larger of nargs  */
+	/* and the (canonical) total of required/&optional args received.  */
+	__(cmpr(cr0,nargs,imm0))
+	__(add arg_z,vsp,nargs)
+	__(bge+ cr0,1f)
+	__(add arg_z,vsp,imm0)
+1:
+	__(build_lisp_frame(fn,loc_pc,arg_z))
+	__(mr fn,nfn)
+	/* If there are key/value pairs to consider, we slide them down  */
+	/* the vstack to make room for the value/supplied-p pairs.  */
+	/* The first step in that operation involves pushing imm3 pairs  */
+	/* of NILs.  */
+	/* If there aren't any such pairs, the first step is the last  */
+	/* step.  */
+	__(cmpri(cr0,imm3,0))
+	__(li arg_z,0)
+	__(sub imm1,nargs,imm0)
+	__(mr imm4,vsp)	/* in case odd keywords error  */
+	__(cmpri(cr1,imm1,0))
+	__(b 3f)
+2:
+	__(addi arg_z,arg_z,fixnum_one)
+	__(cmplr(cr0,arg_z,imm3))
+	__(li imm5,nil_value)
+	__(vpush(imm5))
+	__(vpush(imm5))
+3:
+	__(bne cr0,2b)
+	__(andi. arg_z,imm1,fixnum_one)
+	__(blelr cr1)	/* no keyword/value pairs to consider.  */
+	__(bne cr0,odd_keywords)
+	/* We have key/value pairs.  Move them to the top of the vstack,  */
+	/* then set the value/supplied-p vars to NIL.  */
+	/* Have to use some save regs to do this.  */
+	__(vpush(limit))
+	__(vpush(valptr))
+	__(vpush(varptr))
+	/* recompute ptr to user args in case stack overflowed  */
+	__(add imm4,vsp,imm3)
+	__(add imm4,imm4,imm3)
+	__(addi imm4,imm4,3*node_size)
+	/* error if odd number of keyword/value args  */
+	__(mr varptr,imm4)
+	__(la limit,3*node_size(vsp))
+	__(mr valptr,limit)
+	__(mr arg_z,imm1)
+4:
+	__(li imm4,nil_value)
+	__(subi arg_z,arg_z,2<<fixnumshift)
+	__(cmplri(cr0,arg_z,0))
+	__(ldr(arg_x,node_size*0(varptr)))
+	__(ldr(arg_y,node_size*1(varptr)))
+	__(str(imm4,node_size*0(varptr)))
+	__(str(imm4,node_size*1(varptr)))
+	__(la varptr,node_size*2(varptr))
+	__(str(arg_x,node_size*0(valptr)))
+	__(str(arg_y,node_size*1(valptr)))
+	__(la valptr,node_size*2(valptr))
+	__(bne cr0,4b)
+
+
+        /* Now, iterate through each supplied keyword/value pair.  If  */
+        /* it's :allow-other-keys and the corresponding value is non-nil,  */
+        /* note that other keys will be allowed.  */
+        /* Find its position in the function's keywords vector.  If that's  */
+        /* nil, note that an unknown keyword was encountered.  */
+        /* Otherwise, if the keyword arg hasn't already had a value supplied,  */
+        /* supply it.  */
+        /* When done, complain if any unknown keywords were found and that  */
+        /* situation was unexpected.  */
+	__(mr imm4,valptr)
+5:
+        __(cmpri(cr0,keyword_flags,16<<fixnumshift)) /* seen :a-o-k yet ?  */
+	__(ldru(arg_z,-node_size(valptr)))
+	__(ldru(arg_y,-node_size(valptr)))
+	__(cmpri(cr1,arg_y,nil_value))
+	__(li arg_x,nrs.kallowotherkeys)
+        /* cr6_eq <- (eq current-keyword :allow-other-keys)  */
+	__(cmpr(cr6,arg_x,arg_z))
+	__(cmpr(cr7,valptr,limit))
+	__(bne cr6,6f)
+        __(bge cr0,6f) /* Already seen :allow-other-keys  */
+        __(ori keyword_flags,keyword_flags,16<<fixnumshift)
+	__(beq cr1,6f)
+	__(ori keyword_flags,keyword_flags,fixnum_one)
+6:
+	__(cmpri(cr1,imm3,0))
+	__(li imm1,misc_data_offset)
+	__(li imm0,0)
+	__(b 8f)
+7:
+	__(addi imm0,imm0,fixnum_one)
+	__(cmpr(cr1,imm0,imm3))
+	__(ldrx(arg_x,keyword_vector,imm1))
+	__(cmpr(cr0,arg_x,arg_z))
+	__(addi imm1,imm1,fixnum_one)
+	__(bne cr0,8f)
+	__(add imm0,imm0,imm0)
+	__(sub imm0,varptr,imm0)
+	__(ldr(arg_x,0(imm0)))
+	__(cmpri(cr0,arg_x,nil_value))
+	__(li arg_z,t_value)
+	__(bne cr0,9f)
+	__(str(arg_y,node_size(imm0)))
+	__(str(arg_z,0(imm0)))
+	__(b 9f)
+8:
+	__(bne cr1,7b)
+	/* Unknown keyword. If it was :allow-other-keys, cr6_eq will still */
+        /* be set.  */
+        __(beq cr6,9f)
+	__(ori keyword_flags,keyword_flags,2<<fixnumshift)
+9:
+	__(bne cr7,5b)
+	__(vpop(varptr))
+	__(vpop(valptr))
+	__(vpop(limit))
+	/* All keyword/value pairs have been processed.  */
+	/* If we saw an unknown keyword and didn't expect to, error.  */
+	/* Unless bit 2 is set in the fixnum in keyword_flags, discard the  */
+	/* keyword/value pairs from the vstack.  */
+	__(andi. imm0,keyword_flags,(fixnum_one)|(2<<fixnumshift))
+	__(cmpri(cr0,imm0,2<<fixnumshift))
+	__(beq- cr0,badkeys)
+	__(andi. imm2,keyword_flags,4<<fixnumshift)
+	__(bnelr cr0)
+	__(mr vsp,imm4)
+	__(blr)
+
+/* Signal an error.  We saved context on entry, so this thing doesn't  */
+/* have to.  */
+/* The "unknown keywords" error could be continuable (ignore them.)  */
+/* It might be hard to then cons an &rest arg.  */
+/* In the general case, it's hard to recover the set of args that were  */
+/* actually supplied to us ...  */
+/* For now, just cons a list out of the keyword/value pairs */
+/* that were actually provided, and signal an "invalid keywords" */
+/* error with that list as an operand.  */
+odd_keywords:
+	__(mr vsp,imm4)
+	__(mr nargs,imm1)
+	__(b 1f)
+badkeys:
+	__(sub nargs,imm4,vsp)
+1:
+	__(bl _SPconslist)
+	__(li arg_y,XBADKEYS)
+	__(set_nargs(2))
+	__(b _SPksignalerr)
+
+/*  A PowerOpen ff-call.  arg_z is either a fixnum (word-aligned entrypoint) */
+/*  or a macptr (whose address had better be word-aligned as well.)  A */
+/*  PowerOpen stack frame is on top of the stack; 4 additional words (to */
+/*  be used a a lisp frame) sit under the C frame. */
+
+/*  Since we probably can't deal with FP exceptions in foreign code, we */
+/*  disable them in the FPSCR, then check on return to see if any previously */
+/*  enabled FP exceptions occurred. */
+
+/*  As it turns out, we can share a lot of code with the eabi version of */
+/*  ff-call.  Some things that happen up to the point of call differ between */
+/*  the ABIs, but everything that happens after is the same. */
+
+        
+_spentry(poweropen_ffcall)
+LocalLabelPrefix[]ffcall:                
+	__(mflr loc_pc)
+	__(vpush_saveregs())		/* Now we can use save0-save7 to point to stacks  */
+	__(mr save0,rcontext)	/* or address globals.  */
+	__(extract_typecode(imm0,arg_z))
+	__(cmpri(cr7,imm0,subtag_macptr))
+	__(ldr(save1,0(sp)))	/* bottom of reserved lisp frame  */
+	__(la save2,-lisp_frame.size(save1))	/* top of lisp frame */
+        __(zero_doublewords save2,0,lisp_frame.size)
+	__(str(save1,lisp_frame.backlink(save2)))
+	__(str(save2,c_frame.backlink(sp)))
+	__(str(fn,lisp_frame.savefn(save2)))
+	__(str(loc_pc,lisp_frame.savelr(save2)))
+	__(str(vsp,lisp_frame.savevsp(save2)))
+        __(mr nargs,arg_z)
+       	__(bne cr7,1f)
+	__(ldr(nargs,macptr.address(arg_z)))
+1:
+	__(ldr(save3,tcr.cs_area(rcontext)))
+	__(str(save2,area.active(save3)))
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+	__(str(rzero,tcr.ffi_exception(rcontext)))
+	__(mffs f0)
+	__(stfd f0,tcr.lisp_fpscr(rcontext))	/* remember lisp's fpscr  */
+	__(mtfsf 0xff,fp_zero)	/* zero foreign fpscr  */
+	__(li r4,TCR_STATE_FOREIGN)
+	__(str(r4,tcr.valence(rcontext)))
+        __ifdef([rTOC])
+         __(ld rTOC,8(nargs))
+         __(ld nargs,0(nargs))
+        __else
+	 __(li rcontext,0)
+        __endif
+LocalLabelPrefix[]ffcall_setup: 
+	__(mtctr nargs)
+	__(ldr(r3,c_frame.param0(sp)))
+	__(ldr(r4,c_frame.param1(sp)))
+	__(ldr(r5,c_frame.param2(sp)))
+	__(ldr(r6,c_frame.param3(sp)))
+	__(ldr(r7,c_frame.param4(sp)))
+	__(ldr(r8,c_frame.param5(sp)))
+	__(ldr(r9,c_frame.param6(sp)))
+	__(ldr(r10,c_frame.param7(sp)))
+	/* Darwin is allegedly very picky about what register points */
+	/* to the function on entry.  */
+	__(mr r12,nargs)
+LocalLabelPrefix[]ffcall_setup_end: 
+LocalLabelPrefix[]ffcall_call:
+	__(bctrl)
+LocalLabelPrefix[]ffcall_call_end:
+	/* C should have preserved save0 (= rcontext) for us.  */
+	__(ldr(sp,0(sp)))
+	__(mr imm2,save0)
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(li rzero,0)
+	__(mr loc_pc,rzero)
+	__(li arg_x,nil_value)
+	__(li arg_y,nil_value)
+	__(li arg_z,nil_value)
+	__(li temp0,nil_value)
+	__(li temp1,nil_value)
+	__(li temp2,nil_value)
+	__(li temp3,nil_value)
+	__(li fn,nil_value)
+	__(mr rcontext,imm2)
+	__(li imm2,TCR_STATE_LISP)
+	__(ldr(tsp,tcr.save_tsp(rcontext)))
+        __(li save0,0)
+        __(li save1,0)
+        __(li save2,0)
+        __(li save3,0)
+        __(li save4,0)
+        __(li save5,0)
+        __(li save6,0)
+        __(li save7,0)
+        __(li allocptr,-dnode_size)
+        __(li allocbase,-dnode_size)
+	__(str(imm2,tcr.valence(rcontext)))	
+	__(vpop_saveregs())
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(mffs f0)
+	__(stfd f0,8(sp))
+	__(lwz imm3,12(sp))	/* imm3 = FPSCR after call  */
+        __(clrrwi imm2,imm3,8)
+	__(discard_lisp_frame())
+	__(str(imm2,tcr.ffi_exception(rcontext)))
+	__(lfd f0,tcr.lisp_fpscr(rcontext))
+	__(mtfsf 0xff,f0)
+	__(check_pending_interrupt([cr1]))
+        __(mtxer rzero)
+        __(mtctr rzero)
+        __ifdef([PPC64])
+         __ifdef([DARWIN])
+          __(li imm3,1<<TCR_FLAG_BIT_FOREIGN_EXCEPTION)
+          __(ld imm4,tcr.flags(rcontext))
+          __(and. imm3,imm3,imm4)
+          __(bne cr0,0f)
+         __endif
+        __endif
+	__(blr)
+        __ifdef([PPC64])
+         __ifdef([DARWIN])
+0:        /* Got here because TCR_FLAG_BIT_FOREIGN_EXCEPTION */
+          /* was set in tcr.flags.  Clear that bit. */
+          __(andc imm4,imm4,imm3)
+          __(std imm4,tcr.flags(rcontext))
+ 	  /* Unboxed foreign exception (likely an NSException) in %imm0. */
+	  /* Box it, then signal a lisp error. */
+          __(li imm1,macptr_header)
+          __(Misc_Alloc_Fixed(arg_z,imm1,macptr.size))
+          __(std imm0,macptr.address(arg_z))
+          __(li arg_y,XFOREIGNEXCEPTION)
+          __(set_nargs(2))
+          __(b _SPksignalerr)
+        /* Handle exceptions, for ObjC 2.0 */
+LocalLabelPrefix[]ffcallLandingPad:      
+          __(mr save1,r3)
+          __(cmpdi r4,1)
+          __(beq 1f)
+LocalLabelPrefix[]ffcallUnwindResume:
+          __(ref_global(r12,unwind_resume))
+          __(mtctr r12)
+          __(bctrl)
+LocalLabelPrefix[]ffcallUnwindResume_end:         
+1:        __(mr r3,save1)
+LocalLabelPrefix[]ffcallBeginCatch:
+          __(ref_global(r12,objc2_begin_catch))
+          __(mtctr r12)
+          __(bctrl)
+LocalLabelPrefix[]ffcallBeginCatch_end:          
+          __(ld save1,0(r3)) /* indirection is necessary because we don't provide type info in lsda */
+LocalLabelPrefix[]ffcallEndCatch:  
+          __(ref_global(r12,objc2_end_catch))
+          __(mtctr r12)
+          __(bctrl)              
+LocalLabelPrefix[]ffcallEndCatch_end:     
+          __(ref_global(r12,get_tcr))
+          __(mtctr r12)
+          __(li imm0,1)       
+	  __(bctrl)
+          __(ld imm2,tcr.flags(imm0))
+          __(ori imm2,imm2,1<<TCR_FLAG_BIT_FOREIGN_EXCEPTION)
+          __(std imm2,tcr.flags(imm0))
+          __(mr imm0,save1)
+	  __(b LocalLabelPrefix[]ffcall_call_end)
+LocalLabelPrefix[]ffcall_end:   
+
+        	.section __DATA,__gcc_except_tab
+	  .align 3
+LLSDA1:
+	  .byte	0xff	/* @LPStart format (omit) */
+	  .byte	0x0	/* @TType format (absolute) */
+	  .byte	0x4d	/* uleb128 0x4d; @TType base offset */
+	  .byte	0x3	/* call-site format (udata4) */
+	  .byte	0x41	/* uleb128 0x41; Call-site table length */
+	
+	  .long Lffcall_setup-Lffcall	/* region 0 start */
+	  .long Lffcall_setup_end-Lffcall_setup	/* length */
+	  .long	0x0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+        
+	  .long Lffcall_call-Lffcall	/* region 1 start */
+	  .long Lffcall_call_end-Lffcall_call	/* length */
+	  .long LffcallLandingPad-Lffcall	/* landing pad */
+	  .byte	0x1	/* uleb128 0x1; action */
+        
+	  .long LffcallUnwindResume-Lffcall	/* region 2 start */
+	  .long LffcallUnwindResume_end-LffcallUnwindResume	/* length */
+	  .long	0x0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+	
+	  .long LffcallBeginCatch-Lffcall	/* region 3 start */
+	  .long LffcallBeginCatch_end-LffcallBeginCatch	/* length */
+	  .long 0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+        
+	  .long LffcallEndCatch-Lffcall
+	  .long LffcallEndCatch_end-LffcallEndCatch	/* length */
+	  .long	0x0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+        
+	  .byte	0x1	/* Action record table */
+	  .byte	0x0
+	  .align 3
+	  .quad	0       /* _OBJC_EHTYPE_$_NSException */
+          .text
+         __endif
+        __endif
+
+/* Just like poweropen_ffcall, only we save all argument(result)
+   registers in a buffer passed in arg_y on entry before returning
+   to lisp.  (We have to do this in the ffcall glue here, because
+   r9 and r10 - at least - are overloaded as dedicated lisp registers */
+_spentry(poweropen_ffcall_return_registers)
+LocalLabelPrefix[]ffcall_return_registers:                
+	__(mflr loc_pc)
+	__(vpush_saveregs())		/* Now we can use save0-save7 to point to stacks  */
+        __(ldr(save7,macptr.address(arg_y)))
+	__(mr save0,rcontext)	/* or address globals.  */
+	__(extract_typecode(imm0,arg_z))
+	__(cmpri(cr7,imm0,subtag_macptr))
+	__(ldr(save1,0(sp)))	/* bottom of reserved lisp frame  */
+	__(la save2,-lisp_frame.size(save1))	/* top of lisp frame */
+        __(zero_doublewords save2,0,lisp_frame.size)
+	__(str(save1,lisp_frame.backlink(save2)))
+	__(str(save2,c_frame.backlink(sp)))
+	__(str(fn,lisp_frame.savefn(save2)))
+	__(str(loc_pc,lisp_frame.savelr(save2)))
+	__(str(vsp,lisp_frame.savevsp(save2)))
+        __(mr nargs,arg_z)
+       	__(bne cr7,1f)
+	__(ldr(nargs,macptr.address(arg_z)))
+1:
+	__(ldr(save3,tcr.cs_area(rcontext)))
+	__(str(save2,area.active(save3)))
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+	__(str(rzero,tcr.ffi_exception(rcontext)))
+	__(mffs f0)
+	__(stfd f0,tcr.lisp_fpscr(rcontext))	/* remember lisp's fpscr  */
+	__(mtfsf 0xff,fp_zero)	/* zero foreign fpscr  */
+	__(li r4,TCR_STATE_FOREIGN)
+	__(str(r4,tcr.valence(rcontext)))
+        __ifdef([rTOC])
+         __(ld rTOC,8(nargs))
+         __(ld nargs,0(nargs))
+        __else
+	 __(li rcontext,0)
+        __endif
+LocalLabelPrefix[]ffcall_return_registers_setup: 
+	__(mtctr nargs)
+	__(ldr(r3,c_frame.param0(sp)))
+	__(ldr(r4,c_frame.param1(sp)))
+	__(ldr(r5,c_frame.param2(sp)))
+	__(ldr(r6,c_frame.param3(sp)))
+	__(ldr(r7,c_frame.param4(sp)))
+	__(ldr(r8,c_frame.param5(sp)))
+	__(ldr(r9,c_frame.param6(sp)))
+	__(ldr(r10,c_frame.param7(sp)))
+	/* Darwin is allegedly very picky about what register points */
+	/* to the function on entry.  */
+	__(mr r12,nargs)
+LocalLabelPrefix[]ffcall_return_registers_setup_end: 
+LocalLabelPrefix[]ffcall_return_registers_call:
+	__(bctrl)
+LocalLabelPrefix[]ffcall_return_registers_call_end:
+        __(str(r3,0*node_size(save7)))        
+        __(str(r4,1*node_size(save7)))        
+        __(str(r5,2*node_size(save7)))        
+        __(str(r6,3*node_size(save7)))        
+        __(str(r7,4*node_size(save7)))        
+        __(str(r8,5*node_size(save7)))        
+        __(str(r9,6*node_size(save7)))        
+        __(str(r10,7*node_size(save7)))
+        __(stfd f1,((8*node_size)+(0*8))(save7))
+        __(stfd f2,((8*node_size)+(1*8))(save7))
+        __(stfd f3,((8*node_size)+(2*8))(save7))
+        __(stfd f4,((8*node_size)+(3*8))(save7))
+        __(stfd f5,((8*node_size)+(4*8))(save7))
+        __(stfd f6,((8*node_size)+(5*8))(save7))
+        __(stfd f7,((8*node_size)+(6*8))(save7))
+        __(stfd f8,((8*node_size)+(7*8))(save7))
+        __(stfd f9,((8*node_size)+(8*8))(save7))
+        __(stfd f10,((8*node_size)+(9*8))(save7))
+        __(stfd f11,((8*node_size)+(10*8))(save7))
+        __(stfd f12,((8*node_size)+(11*8))(save7))
+        __(stfd f13,((8*node_size)+(12*8))(save7))
+	/* C should have preserved save0 (= rcontext) for us.  */
+	__(ldr(sp,0(sp)))
+	__(mr imm2,save0)
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(li rzero,0)
+	__(mr loc_pc,rzero)
+	__(li arg_x,nil_value)
+	__(li arg_y,nil_value)
+	__(li arg_z,nil_value)
+	__(li temp0,nil_value)
+	__(li temp1,nil_value)
+	__(li temp2,nil_value)
+	__(li temp3,nil_value)
+	__(li fn,nil_value)
+	__(mr rcontext,imm2)
+	__(li imm2,TCR_STATE_LISP)
+	__(ldr(tsp,tcr.save_tsp(rcontext)))
+        __(li save0,0)
+        __(li save1,0)
+        __(li save2,0)
+        __(li save3,0)
+        __(li save4,0)
+        __(li save5,0)
+        __(li save6,0)
+        __(li save7,0)
+        __(li allocptr,-dnode_size)
+        __(li allocbase,-dnode_size)
+	__(str(imm2,tcr.valence(rcontext)))	
+	__(vpop_saveregs())
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(mffs f0)
+	__(stfd f0,8(sp))
+	__(lwz imm3,12(sp))	/* imm3 = FPSCR after call  */
+        __(clrrwi imm2,imm3,8)
+	__(discard_lisp_frame())
+	__(str(imm2,tcr.ffi_exception(rcontext)))
+	__(lfd f0,tcr.lisp_fpscr(rcontext))
+	__(mtfsf 0xff,f0)
+	__(check_pending_interrupt([cr1]))
+        __(mtxer rzero)
+        __(mtctr rzero)
+        __ifdef([DARWIN])
+         __ifdef([PPC64])
+          __(li imm3,1<<TCR_FLAG_BIT_FOREIGN_EXCEPTION)
+          __(ld imm4,tcr.flags(rcontext))
+          __(and. imm3,imm3,imm4)
+          __(bne 0f)
+         __endif
+        __endif
+	__(blr)
+
+        __ifdef([DARWIN])
+         __ifdef([PPC64])
+0:        /* Got here because TCR_FLAG_BIT_FOREIGN_EXCEPTION */
+          /* was set in tcr.flags.  Clear that bit. */
+          __(andc imm4,imm4,imm3)
+          __(std imm4,tcr.flags(rcontext))
+ 	  /* Unboxed foreign exception (likely an NSException) in %imm0. */
+	  /* Box it, then signal a lisp error. */
+          __(li imm1,macptr_header)
+          __(Misc_Alloc_Fixed(arg_z,imm1,macptr.size))
+          __(std imm0,macptr.address(arg_z))
+          __(li arg_y,XFOREIGNEXCEPTION)
+          __(set_nargs(2))
+          __(b _SPksignalerr)
+        /* Handle exceptions, for ObjC 2.0 */
+LocalLabelPrefix[]ffcall_return_registersLandingPad:      
+          __(mr save1,r3)
+          __(cmpdi r4,1)
+          __(beq 1f)
+LocalLabelPrefix[]ffcall_return_registersUnwindResume:
+          __(ref_global(r12,unwind_resume))
+          __(mtctr r12)
+          __(bctrl)
+LocalLabelPrefix[]ffcall_return_registersUnwindResume_end:         
+1:        __(mr r3,save1)
+LocalLabelPrefix[]ffcall_return_registersBeginCatch:
+          __(ref_global(r12,objc2_begin_catch))
+          __(mtctr r12)
+          __(bctrl)
+LocalLabelPrefix[]ffcall_return_registersBeginCatch_end:          
+          __(ld save1,0(r3)) /* indirection is necessary because we don't provide type info in lsda */
+LocalLabelPrefix[]ffcall_return_registersEndCatch:  
+          __(ref_global(r12,objc2_end_catch))
+          __(mtctr r12)
+          __(bctrl)              
+LocalLabelPrefix[]ffcall_return_registersEndCatch_end:     
+          __(ref_global(r12,get_tcr))
+          __(mtctr r12)
+          __(li imm0,1)       
+	  __(bctrl)
+          __(ld imm2,tcr.flags(imm0))
+          __(ori imm2,imm2,1<<TCR_FLAG_BIT_FOREIGN_EXCEPTION)
+          __(std imm2,tcr.flags(imm0))
+          __(mr imm0,save1)
+	  __(b LocalLabelPrefix[]ffcall_return_registers_call_end)
+LocalLabelPrefix[]ffcall_return_registers_end:
+	  .section __DATA,__gcc_except_tab
+	  .align 3
+LLSDA2:
+	  .byte	0xff	/* @LPStart format (omit) */
+  	  .byte	0x0	/* @TType format (absolute) */
+	  .byte	0x4d	/* uleb128 0x4d; @TType base offset */
+	  .byte	0x3	/* call-site format (udata4) */
+	  .byte	0x41	/* uleb128 0x41; Call-site table length */
+	
+	  .long Lffcall_return_registers_setup-Lffcall_return_registers	/* region 0 start */
+	  .long Lffcall_return_registers_setup_end-Lffcall_return_registers_setup	/* length */
+	  .long	0x0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+        
+	  .long Lffcall_return_registers_call-Lffcall_return_registers	/* region 1 start */
+	  .long Lffcall_return_registers_call_end-Lffcall_return_registers_call	/* length */
+	  .long Lffcall_return_registersLandingPad-Lffcall_return_registers	/* landing pad */
+	  .byte	0x1	/* uleb128 0x1; action */
+        
+	  .long Lffcall_return_registersUnwindResume-Lffcall_return_registers	/* region 2 start */
+	  .long Lffcall_return_registersUnwindResume_end-Lffcall_return_registersUnwindResume	/* length */
+	  .long	0x0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+	
+	  .long Lffcall_return_registersBeginCatch-Lffcall_return_registers	/* region 3 start */
+	  .long Lffcall_return_registersBeginCatch_end-Lffcall_return_registersBeginCatch	/* length */
+	  .long 0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+        
+	  .long Lffcall_return_registersEndCatch-Lffcall_return_registers
+	  .long Lffcall_return_registersEndCatch_end-Lffcall_return_registersEndCatch	/* length */
+	  .long	0x0	/* landing pad */
+	  .byte	0x0	/* uleb128 0x0; action */
+	  .byte	0x1	/* Action record table */
+	  .byte	0x0
+	  .align 3
+	  .quad	0       /* _OBJC_EHTYPE_$_NSException */
+          .text
+         __endif
+        __endif
+                      
+
+        	
+/* Signal an error synchronously, via %ERR-DISP.  */
+/* If %ERR-DISP isn't fbound, it'd be nice to print a message  */
+/* on the C runtime stderr.  */
+
+_spentry(ksignalerr)
+	__(li fname,nrs.errdisp)
+	__(jump_fname)
+        
+/* As in the heap-consed cases, only stack-cons the &rest arg  */
+_spentry(stack_rest_arg)
+	__(li imm0,0)
+	__(vpush_argregs())
+        __(b _SPstack_cons_rest_arg)
+
+	
+_spentry(req_stack_rest_arg)
+	__(vpush_argregs())
+        __(b _SPstack_cons_rest_arg)
+	
+_spentry(stack_cons_rest_arg)
+	__(sub imm1,nargs,imm0)
+	__(cmpri(cr0,imm1,0))
+	__(cmpri(cr1,imm1,(4096-dnode_size)/2))
+	__(li arg_z,nil_value)
+	__(ble cr0,2f)		/* always temp-push something.  */
+	__(bge cr1,3f)
+	__(add imm1,imm1,imm1)
+	__(dnode_align(imm2,imm1,tsp_frame.fixed_overhead))
+	__(TSP_Alloc_Var_Boxed(imm2,imm3))
+	__(la imm0,tsp_frame.data_offset+fulltag_cons(tsp))
+1:
+	__(cmpri(cr0,imm1,cons.size))	/* last time through ?  */
+	__(subi imm1,imm1,cons.size)
+	__(vpop(arg_x))
+	__(_rplacd(imm0,arg_z))
+	__(_rplaca(imm0,arg_x))
+	__(mr arg_z,imm0)
+	__(la imm0,cons.size(imm0))
+	__(bne cr0,1b)
+	__(vpush(arg_z))
+	__(blr)
+2:
+	__(TSP_Alloc_Fixed_Unboxed(0))
+	__(vpush(arg_z))
+	__(blr)
+3:
+	__(TSP_Alloc_Fixed_Unboxed(0))
+	__(b _SPheap_cons_rest_arg)
+
+/* This was trying to swap exception ports to work around Darwin JNI lossage.
+   It's tended to bitrot, and we have another way to do that now.
+*/        
+_spentry(poweropen_callbackX)
+        .long 0x7c800008        /* debug trap */
+	
+/* Prepend all but the first two (closure code, fn) and last two  */
+/* (function name, lfbits) elements of nfn to the "arglist".  */
+/* Doing things this way (the same way that 68K MCL does) lets  */
+/* functions which take "inherited arguments" work consistently  */
+/* even in cases where no closure object is created.  */
+_spentry(call_closure)        
+	__(cmpri(cr0,nargs,nargregs<<fixnumshift))
+	__(cmpri(cr1,nargs,fixnum_one))
+	__(vector_length(imm0,nfn,imm0))
+	__(subi imm0,imm0,4<<fixnumshift) /* imm0 = inherited arg count  */
+	__(li imm1,misc_data_offset+(2<<fixnumshift)) /* point to 1st arg  */
+	__(li imm4,nil_value)
+	__(ble+ cr0,local_label(no_insert))
+	/* Some arguments have already been vpushed.  Vpush imm0's worth  */
+	/* of NILs, copy those arguments that have already been vpushed from  */
+	/* the old TOS to the new, then insert all of the inerited args  */
+	/* and go to the function.  */
+	__(li imm2,0)
+local_label(push_nil_loop):
+	__(addi imm2,imm2,fixnum_one)
+	__(cmpr(cr2,imm2,imm0))
+	__(vpush(imm4))
+	__(bne cr2,local_label(push_nil_loop))
+
+	__(mr imm3,vsp)
+	__(add imm4,vsp,imm0)
+	__(subi imm2,nargs,nargregs<<fixnumshift)
+local_label(copy_already_loop):
+	__(cmpri(cr2,imm2,fixnum_one))
+	__(subi imm2,imm2,fixnum_one)
+	__(ldr(fname,0(imm4)))
+	__(addi imm4,imm4,fixnum_one)
+	__(str(fname,0(imm3)))
+	__(addi imm3,imm3,fixnum_one)
+	__(bne cr2,local_label(copy_already_loop))
+
+local_label(insert_loop):
+	__(cmpri(cr2,imm0,fixnum_one))
+	__(ldrx(fname,nfn,imm1))
+	__(addi imm1,imm1,fixnum_one)
+	__(addi nargs,nargs,fixnum_one)
+	__(subi imm0,imm0,fixnum_one)
+	__(push(fname,imm4))
+	__(bne cr2,local_label(insert_loop))
+	__(b local_label(go))
+local_label(no_insert):
+	/* nargregs or fewer args were already vpushed.  */
+	/* if exactly nargregs, vpush remaining inherited vars.  */
+	__(add imm2,imm1,imm0)
+	__(bne cr0,local_label(set_regs))
+local_label(vpush_remaining):
+	__(cmpri(cr2,imm0,fixnum_one))
+	__(ldrx(fname,nfn,imm1))
+	__(addi imm1,imm1,fixnum_one)
+	__(vpush(fname))
+	__(subi imm0,imm0,fixnum_one)
+	__(addi nargs,nargs,fixnum_one)
+	__(bne cr2,local_label(vpush_remaining))
+	__(b local_label(go))
+local_label(set_regs):
+	/* if nargs was > 1 (and we know that it was < 3), it must have  */
+	/* been 2.  Set arg_x, then vpush the remaining args.  */
+	__(ble cr1,local_label(set_y_z))
+local_label(set_arg_x):
+	__(subi imm0,imm0,fixnum_one)
+	__(cmpri(cr0,imm0,0))
+	__(subi imm2,imm2,fixnum_one)
+	__(ldrx(arg_x,nfn,imm2))
+	__(addi nargs,nargs,fixnum_one)
+	__(bne cr0,local_label(vpush_remaining))
+	__(b local_label(go))
+	/* Maybe set arg_y or arg_z, preceding args  */
+local_label(set_y_z):
+	__(bne cr1,local_label(set_arg_z))
+	/* Set arg_y, maybe arg_x, preceding args  */
+local_label(set_arg_y):
+	__(subi imm0,imm0,fixnum_one)
+	__(cmpri(cr0,imm0,0))
+	__(subi imm2,imm2,fixnum_one)
+	__(ldrx(arg_y,nfn,imm2))
+	__(addi nargs,nargs,fixnum_one)
+	__(bne cr0,local_label(set_arg_x))
+	__(b local_label(go))
+local_label(set_arg_z):
+	__(subi imm0,imm0,fixnum_one)
+	__(cmpri(cr0,imm0,0))
+	__(subi imm2,imm2,fixnum_one)
+	__(ldrx(arg_z,nfn,imm2))
+	__(addi nargs,nargs,fixnum_one)
+	__(bne cr0,local_label(set_arg_y))
+
+local_label(go):
+	__(vrefr(nfn,nfn,1))
+	__(ldr(loc_pc,_function.codevector(nfn)))
+	__(mtctr loc_pc)
+	__(bctr)
+        
+/* This  treats anything that's either */
+/* #+ppc32 (signed-byte 32), (unsigned-byte 32) */
+/* #+ppc64 (signed-byte 64), (unsigned-byte 64) */
+/* as if it denoted a "natural-sized" value.  */
+/* Argument in arg_z, result in imm0.  May use temp0.  */
+_spentry(getxlong)
+        __ifdef([PPC64])
+        __else
+        __(extract_typecode(imm0,arg_z))
+	__(cmpri(cr0,imm0,tag_fixnum))
+	__(cmpri(cr1,imm0,subtag_bignum))
+	__(unbox_fixnum(imm0,arg_z))
+	__(beqlr cr0)
+	__(mr temp0,arg_z)
+	__(bne- cr1,local_label(error))
+	__(getvheader(imm0,temp0))
+	__(cmpri(cr1,imm0,one_digit_bignum_header))
+	__(cmpri(cr7,imm0,two_digit_bignum_header))
+	__(beq cr1,local_label(big1))
+        __(beq cr7,local_label(big2))
+local_label(error):
+	__(uuo_interr(error_object_not_integer,arg_z)) /* not quite right but what 68K MCL said  */
+
+
+
+local_label(big2):
+	__(vrefr(imm0,temp0,1)) /* sign digit must be 0  */
+	__(cmpri(imm0,0))
+	__(bne local_label(error))
+local_label(big1):
+	__(vrefr(imm0,temp0,0))
+	__(blr)
+
+
+        __endif
+                
+/* Everything up to the last arg has been vpushed, nargs is set to  */
+/* the (boxed) count of things already pushed.  */
+/* On exit, arg_x, arg_y, arg_z, and nargs are set as per a normal  */
+/* function call (this may require vpopping a few things.)  */
+/* ppc2-invoke-fn assumes that temp1 is preserved here.  */
+_spentry(spreadargz)
+        __ifdef([PPC64])
+	 __(extract_fulltag(imm1,arg_z))
+	 __(cmpri(cr1,imm1,fulltag_cons))
+        __else
+	 __(extract_lisptag(imm1,arg_z))
+	 __(cmpri(cr1,imm1,tag_list))
+        __endif
+	__(cmpri(cr0,arg_z,nil_value))
+	__(li imm0,0)
+	__(mr arg_y,arg_z)		/*  save in case of error  */
+	__(beq cr0,2f)
+1:
+	__(bne- cr1,3f)
+	__(_car(arg_x,arg_z))
+	__(_cdr(arg_z,arg_z))
+	__(cmpri(cr0,arg_z,nil_value))
+        __ifdef([PPC64])
+	 __(extract_fulltag(imm1,arg_z))
+	 __(cmpri(cr1,imm1,fulltag_cons))
+        __else
+	 __(extract_lisptag(imm1,arg_z))
+	 __(cmpri(cr1,imm1,tag_list))
+        __endif
+	__(vpush(arg_x))
+	__(addi imm0,imm0,fixnum_one)
+	__(bne cr0,1b)
+2:
+	__(add. nargs,nargs,imm0)
+	__(cmpri(cr2,nargs,2<<fixnumshift))
+	__(beqlr- cr0)
+	__(vpop(arg_z))
+	__(bltlr cr2)
+	__(vpop(arg_y))
+	__(beqlr cr2)
+	__(vpop(arg_x))
+	__(blr)
+        /*  Discard whatever's been vpushed already, complain.  */
+3:	
+	__(add vsp,vsp,imm0)
+	__(mr arg_z,arg_y)		/* recover original arg_z  */
+	__(li arg_y,XNOSPREAD)
+	__(set_nargs(2))
+	__(b _SPksignalerr)
+        
+/* Tail-recursively funcall temp0.  */
+/* Pretty much the same as the tcallsym* cases above.  */
+_spentry(tfuncallgen)
+	__(cmpri(cr0,nargs,nargregs<<fixnumshift))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(mtlr loc_pc)
+	__(ble cr0,2f)
+	__(ldr(imm0,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	/* can use nfn (= temp2) as a temporary  */
+	__(subi imm1,nargs,nargregs<<fixnumshift)
+	__(add imm1,imm1,vsp)
+1:
+	__(ldru(temp2,-node_size(imm1)))
+	__(cmpr(cr0,imm1,vsp))
+	__(push(temp2,imm0))
+	__(bne cr0,1b)
+	__(mr vsp,imm0)
+	__(do_funcall())
+2:
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	__(do_funcall())
+
+
+/* Some args were vpushed.  Slide them down to the base of  */
+/* the current frame, then do funcall.  */
+_spentry(tfuncallslide)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(imm0,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	/* can use nfn (= temp2) as a temporary  */
+	__(subi imm1,nargs,nargregs<<fixnumshift)
+	__(add imm1,imm1,vsp)
+	__(mtlr loc_pc)
+1:
+	__(ldru(temp2,-node_size(imm1)))
+	__(cmpr(cr0,imm1,vsp))
+	__(push(temp2,imm0))
+	__(bne cr0,1b)
+	__(mr vsp,imm0)
+	__(do_funcall())
+
+/* No args were vpushed; recover saved context & do funcall  */
+_spentry(tfuncallvsp)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(mtlr loc_pc)
+	__(discard_lisp_frame())
+	__(do_funcall())
+        
+/* Tail-recursively call the (known symbol) in fname.  */
+/* In the general case, we don't know if any args were  */
+/* vpushed or not.  If so, we have to "slide" them down  */
+/* to the base of the frame.  If not, we can just restore  */
+/* vsp, lr, fn from the saved lisp frame on the control stack.  */
+_spentry(tcallsymgen)
+	__(cmpri(cr0,nargs,nargregs<<fixnumshift))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(mtlr loc_pc)
+	__(ble cr0,2f)
+
+	__(ldr(imm0,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	/* can use nfn (= temp2) as a temporary  */
+	__(subi imm1,nargs,nargregs<<fixnumshift)
+	__(add imm1,imm1,vsp)
+1:
+	__(ldru(temp2,-node_size(imm1)))
+	__(cmpr(cr0,imm1,vsp))
+	__(push(temp2,imm0))
+	__(bne cr0,1b)
+	__(mr vsp,imm0)
+	__(jump_fname)
+	
+2:		
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	__(jump_fname)
+	
+	
+/* Some args were vpushed.  Slide them down to the base of  */
+/* the current frame, then do funcall.  */
+_spentry(tcallsymslide)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(imm0,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	__(mtlr loc_pc)
+	/* can use nfn (= temp2) as a temporary  */
+	__(subi imm1,nargs,nargregs<<fixnumshift)
+	__(add imm1,imm1,vsp)
+1:
+	__(ldru(temp2,-node_size(imm1)))
+	__(cmpr(cr0,imm1,vsp))
+	__(push(temp2,imm0))
+	__(bne cr0,1b)
+	__(mr vsp,imm0)
+	__(jump_fname)
+
+/* No args were vpushed; recover saved context & call symbol  */
+_spentry(tcallsymvsp)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	__(mtlr loc_pc)
+	__(jump_fname)
+	
+/* Tail-recursively call the function in nfn.  */
+/* Pretty much the same as the tcallsym* cases above.  */
+_spentry(tcallnfngen)
+	__(cmpri(cr0,nargs,nargregs<<fixnumshift))
+	__(ble cr0,_SPtcallnfnvsp)
+        __(b _SPtcallnfnslide)
+
+/* Some args were vpushed.  Slide them down to the base of  */
+/* the current frame, then do funcall.  */
+_spentry(tcallnfnslide)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(imm0,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	__(mtlr loc_pc)
+	/* Since we have a known function, can use fname as a temporary.  */
+	__(subi imm1,nargs,nargregs<<fixnumshift)
+	__(add imm1,imm1,vsp)
+1:
+	__(ldru(fname,-node_size(imm1)))
+	__(cmpr(cr0,imm1,vsp))
+	__(push(fname,imm0))
+	__(bne cr0,1b)
+	__(mr vsp,imm0)
+       	__(jump_nfn())
+        
+_spentry(tcallnfnvsp)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	__(mtlr loc_pc)
+       	__(jump_nfn())
+	
+/* Reference index arg_z of a misc-tagged object (arg_y).  */
+/* Note that this conses in some cases.  Return a properly-tagged  */
+/* lisp object in arg_z.  Do type and bounds-checking.  */
+	
+_spentry(misc_ref)
+	__(trap_unless_fulltag_equal(arg_y,fulltag_misc,imm0))
+	__(trap_unless_lisptag_equal(arg_z,tag_fixnum,imm0))
+	__(vector_length(imm0,arg_y,imm1))
+	__(trlge(arg_z,imm0))
+	__(extract_lowbyte(imm1,imm1))	/* imm1 = subtag  */
+	
+local_label(misc_ref_common):   
+        __ifdef([PPC64])
+         __(slwi imm1,imm1,3)
+         __(li imm0,LO(local_label(misc_ref_jmp)))
+         __(addis imm0,imm0,HA(local_label(misc_ref_jmp)))
+         __(ldx imm0,imm0,imm1)
+         __(mtctr imm0)
+         __(bctr)
+
+local_label(misc_ref_jmp):              
+        /* 00-0f  */
+         .quad local_label(misc_ref_invalid) /* 00 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 01 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 02 immheader_0  */
+         .quad local_label(misc_ref_node) /* 03 function  */
+         .quad local_label(misc_ref_invalid) /* 04 cons  */
+         .quad local_label(misc_ref_invalid) /* 05 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 06 immheader_1  */
+         .quad local_label(misc_ref_node) /* 07 catch_frame  */
+         .quad local_label(misc_ref_invalid) /* 08 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 09 imm_2  */
+         .quad local_label(misc_ref_u32) /* 0a code_vector  */
+         .quad local_label(misc_ref_node) /* 0b slot_vector  */
+         .quad local_label(misc_ref_invalid) /* 0c misc  */
+         .quad local_label(misc_ref_invalid) /* 0d imm3  */
+         .quad local_label(misc_ref_invalid) /* 0e immheader_3  */
+         .quad local_label(misc_ref_node) /* 0f ratio  */
+        /* 10-1f  */
+         .quad local_label(misc_ref_invalid) /* 10 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 11 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 12 immheader_0  */
+         .quad local_label(misc_ref_node) /* 13 symbol_0  */
+         .quad local_label(misc_ref_invalid) /* 14 cons  */
+         .quad local_label(misc_ref_invalid) /* 15 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 16 immheader_1  */
+         .quad local_label(misc_ref_node) /* 17 lisp_tread  */
+         .quad local_label(misc_ref_invalid) /* 18 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 19 imm_2  */
+         .quad local_label(misc_ref_u32) /* 1a xcode_vector  */
+         .quad local_label(misc_ref_node) /* 1b instance  */
+         .quad local_label(misc_ref_invalid) /* 1c misc  */
+         .quad local_label(misc_ref_invalid) /* 1d imm3  */
+         .quad local_label(misc_ref_u64) /* 1e macptr  */
+         .quad local_label(misc_ref_node) /* 1f complex  */
+        /* 20-2f  */
+         .quad local_label(misc_ref_invalid) /* 20 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 21 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 22 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* 23 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 24 cons  */
+         .quad local_label(misc_ref_invalid) /* 25 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 26 immheader_1  */
+         .quad local_label(misc_ref_node) /* 27 lock  */
+         .quad local_label(misc_ref_invalid) /* 28 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 29 imm_2  */
+         .quad local_label(misc_ref_u32) /* 2a bignum  */
+         .quad local_label(misc_ref_node) /* 2b struct  */
+         .quad local_label(misc_ref_invalid) /* 2c misc  */
+         .quad local_label(misc_ref_invalid) /* 2d imm3  */
+         .quad local_label(misc_ref_u64) /* 2e dead_macptr  */
+         .quad local_label(misc_ref_invalid) /* 2f nodeheader_3  */
+        /* 30-3f  */
+         .quad local_label(misc_ref_invalid) /* 30 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 31 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 32 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* 33 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 34 cons  */
+         .quad local_label(misc_ref_invalid) /* 35 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 36 immheader_1  */
+         .quad local_label(misc_ref_node) /* 37 hash_vector  */
+         .quad local_label(misc_ref_invalid) /* 38 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 39 imm_2  */
+         .quad local_label(misc_ref_u32) /* 3a double_float  */
+         .quad local_label(misc_ref_node) /* 3b istruct  */
+         .quad local_label(misc_ref_invalid) /* 3c misc  */
+         .quad local_label(misc_ref_invalid) /* 3d imm3  */
+         .quad local_label(misc_ref_invalid) /* 3e immheader_3  */
+         .quad local_label(misc_ref_invalid) /* 3f nodeheader_3  */
+        /* 40-4f  */
+         .quad local_label(misc_ref_invalid) /* 40 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 41 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 42 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* 43 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 44 cons  */
+         .quad local_label(misc_ref_invalid) /* 45 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 46 immheader_1  */
+         .quad local_label(misc_ref_node) /* 47 pool  */
+         .quad local_label(misc_ref_invalid) /* 48 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 49 imm_2  */
+         .quad local_label(misc_ref_invalid) /* 4a immheader_2  */
+         .quad local_label(misc_ref_node) /* 4b value_cell_2  */
+         .quad local_label(misc_ref_invalid) /* 4c misc  */
+         .quad local_label(misc_ref_invalid) /* 4d imm3  */
+         .quad local_label(misc_ref_invalid) /* 4e immheader_3  */
+         .quad local_label(misc_ref_invalid) /* 4f nodeheader_3  */
+        /* 50-5f  */
+         .quad local_label(misc_ref_invalid) /* 50 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 51 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 52 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* 53 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 54 cons  */
+         .quad local_label(misc_ref_invalid) /* 55 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 56 immheader_1  */
+         .quad local_label(misc_ref_node) /* 57 weak  */
+         .quad local_label(misc_ref_invalid) /* 58 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 59 imm_2  */
+         .quad local_label(misc_ref_invalid) /* 5a immheader_2  */
+         .quad local_label(misc_ref_node) /* 5b xfunction  */
+         .quad local_label(misc_ref_invalid) /* 5c misc  */
+         .quad local_label(misc_ref_invalid) /* 5d imm3  */
+         .quad local_label(misc_ref_invalid) /* 5e immheader_3  */
+         .quad local_label(misc_ref_invalid) /* 5f nodeheader_3  */
+        /* 60-6f  */
+         .quad local_label(misc_ref_invalid) /* 60 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 61 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 62 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* 63 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 64 cons  */
+         .quad local_label(misc_ref_invalid) /* 65 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 66 immheader_1  */
+         .quad local_label(misc_ref_node) /* 67 package  */
+         .quad local_label(misc_ref_invalid) /* 68 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 69 imm_2  */
+         .quad local_label(misc_ref_invalid) /* 6a immheader_2  */
+         .quad local_label(misc_ref_invalid) /* 6b nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* 6c misc  */
+         .quad local_label(misc_ref_invalid) /* 6d imm3  */
+         .quad local_label(misc_ref_invalid) /* 6e immheader_3  */
+         .quad local_label(misc_ref_invalid) /* 6f nodeheader_3  */
+        /* 70-7f  */
+         .quad local_label(misc_ref_invalid) /* 70 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 71 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 72 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* 73 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 74 cons  */
+         .quad local_label(misc_ref_invalid) /* 75 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 76 immheader_1  */
+         .quad local_label(misc_ref_invalid) /* 77 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* 78 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 79 imm_2  */
+         .quad local_label(misc_ref_invalid) /* 7a immheader_2  */
+         .quad local_label(misc_ref_invalid) /* 7b nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* 7c misc  */
+         .quad local_label(misc_ref_invalid) /* 7d imm3  */
+         .quad local_label(misc_ref_invalid) /* 7e immheader_3  */
+         .quad local_label(misc_ref_invalid) /* 7f nodeheader_3  */
+        /* 80-8f  */
+         .quad local_label(misc_ref_invalid) /* 80 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 81 imm_0  */
+         .quad local_label(misc_ref_invalid) /* 82 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* 83 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 84 cons  */
+         .quad local_label(misc_ref_invalid) /* 85 imm_1  */
+         .quad local_label(misc_ref_invalid) /* 86 immheader_1  */
+         .quad local_label(misc_ref_node)    /* 87 arrayH  */ 
+         .quad local_label(misc_ref_invalid) /* 88 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 89 imm_2  */
+         .quad local_label(misc_ref_invalid) /* 8a immheader_2  */
+         .quad local_label(misc_ref_node)    /* 8b vectorH  */
+         .quad local_label(misc_ref_invalid) /* 8c misc  */
+         .quad local_label(misc_ref_invalid) /* 8d imm3  */
+         .quad local_label(misc_ref_invalid) /* 8e immheader_3  */
+         .quad local_label(misc_ref_node) /* 8f simple_vector  */
+        /* 90-9f  */
+         .quad local_label(misc_ref_invalid) /* 90 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 91 imm_0  */
+         .quad local_label(misc_ref_s8) /* 92 s8  */
+         .quad local_label(misc_ref_invalid) /* 93 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* 94 cons  */
+         .quad local_label(misc_ref_invalid) /* 95 imm_1  */
+         .quad local_label(misc_ref_s16) /* 96 immheader_1  */
+         .quad local_label(misc_ref_invalid) /* 97 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* 98 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* 99 imm_2  */
+         .quad local_label(misc_ref_s32) /* 9a s32  */
+         .quad local_label(misc_ref_invalid) /* 9b nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* 9c misc  */
+         .quad local_label(misc_ref_invalid) /* 9d imm3  */
+         .quad local_label(misc_ref_s64) /* 9e s64  */
+         .quad local_label(misc_ref_invalid) /* 9f nodeheader_3  */
+        /* a0-af  */
+         .quad local_label(misc_ref_invalid) /* a0 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* a1 imm_0  */
+         .quad local_label(misc_ref_u8) /* a2 u8  */
+         .quad local_label(misc_ref_invalid) /* a3 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* a4 cons  */
+         .quad local_label(misc_ref_invalid) /* a5 imm_1  */
+         .quad local_label(misc_ref_u16) /* a6 u16  */
+         .quad local_label(misc_ref_invalid) /* a7 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* a8 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* a9 imm_2  */
+         .quad local_label(misc_ref_u32) /* aa u32  */
+         .quad local_label(misc_ref_invalid) /* ab nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* ac misc  */
+         .quad local_label(misc_ref_invalid) /* ad imm3  */
+         .quad local_label(misc_ref_u64) /* ae u64  */
+         .quad local_label(misc_ref_invalid) /* af nodeheader_3  */
+        /* b0-bf  */
+         .quad local_label(misc_ref_invalid) /* b0 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* b1 imm_0  */
+         .quad local_label(misc_ref_invalid) /* b2 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* b3 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* b4 cons  */
+         .quad local_label(misc_ref_invalid) /* b5 imm_1  */
+         .quad local_label(misc_ref_invalid) /* b6 immheader_1  */
+         .quad local_label(misc_ref_invalid) /* b7 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* b8 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* b9 imm_2  */
+         .quad local_label(misc_ref_single_float_vector) /* ba sf vector  */
+         .quad local_label(misc_ref_invalid) /* bb nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* bc misc  */
+         .quad local_label(misc_ref_invalid) /* bd imm3  */
+         .quad local_label(misc_ref_fixnum_vector) /* be fixnum_vector  */
+         .quad local_label(misc_ref_invalid) /* bf nodeheader_3  */
+        /* c0-cf  */
+         .quad local_label(misc_ref_invalid) /* c0 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* c1 imm_0  */
+         .quad local_label(misc_ref_invalid) /* c2 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* c3 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* c4 cons  */
+         .quad local_label(misc_ref_invalid) /* c5 imm_1  */
+         .quad local_label(misc_ref_invalid) /* c6 immheader_1  */
+         .quad local_label(misc_ref_invalid) /* c7 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* c8 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* c9 imm_2  */
+         .quad local_label(misc_ref_invalid) /* ca immheader_2  */
+         .quad local_label(misc_ref_invalid) /* cb nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* cc misc  */
+         .quad local_label(misc_ref_invalid) /* cd imm3  */
+         .quad local_label(misc_ref_double_float_vector) /* ce double-float vector  */
+         .quad local_label(misc_ref_invalid) /* cf nodeheader_3  */
+        /* d0-df  */
+         .quad local_label(misc_ref_invalid) /* d0 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* d1 imm_0  */
+         .quad local_label(misc_ref_string) /* d2 string  */
+         .quad local_label(misc_ref_invalid) /* d3 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* d4 cons  */
+         .quad local_label(misc_ref_invalid) /* d5 imm_1  */
+         .quad local_label(misc_ref_invalid) /* d6 immheader_1  */
+         .quad local_label(misc_ref_invalid) /* d7 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* d8 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* d9 imm_2  */
+         .quad local_label(misc_ref_new_string) /* da new_string  */
+         .quad local_label(misc_ref_invalid) /* db nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* dc misc  */
+         .quad local_label(misc_ref_invalid) /* dd imm3  */
+         .quad local_label(misc_ref_invalid) /* de immheader_3  */
+         .quad local_label(misc_ref_invalid) /* df nodeheader_3  */
+        /* e0-ef  */
+         .quad local_label(misc_ref_invalid) /* e0 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* e1 imm_0  */
+         .quad local_label(misc_ref_invalid) /* e2 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* e3 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* e4 cons  */
+         .quad local_label(misc_ref_invalid) /* e5 imm_1  */
+         .quad local_label(misc_ref_invalid) /* e6 immheader_1  */
+         .quad local_label(misc_ref_invalid) /* e7 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* e8 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* e9 imm_2  */
+         .quad local_label(misc_ref_invalid) /* ea immheader_2  */
+         .quad local_label(misc_ref_invalid) /* eb nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* ec misc  */
+         .quad local_label(misc_ref_invalid) /* ed imm3  */
+         .quad local_label(misc_ref_invalid) /* ee immheader_3  */
+         .quad local_label(misc_ref_invalid) /* ef nodeheader_3  */
+        /* f0-ff  */
+         .quad local_label(misc_ref_invalid) /* f0 even_fixnum  */
+         .quad local_label(misc_ref_invalid) /* f1 imm_0  */
+         .quad local_label(misc_ref_invalid) /* f2 immheader_0  */
+         .quad local_label(misc_ref_invalid) /* f3 nodeheader_0  */
+         .quad local_label(misc_ref_invalid) /* f4 cons  */
+         .quad local_label(misc_ref_invalid) /* f5 imm_1  */
+         .quad local_label(misc_ref_bit_vector) /* f6 bit_vector  */
+         .quad local_label(misc_ref_invalid) /* f7 nodeheader_1  */
+         .quad local_label(misc_ref_invalid) /* f8 odd_fixnum  */
+         .quad local_label(misc_ref_invalid) /* f9 imm_2  */
+         .quad local_label(misc_ref_invalid) /* fa immheader_2  */
+         .quad local_label(misc_ref_invalid) /* fb nodeheader_2  */
+         .quad local_label(misc_ref_invalid) /* fc misc  */
+         .quad local_label(misc_ref_invalid) /* fd imm3  */
+         .quad local_label(misc_ref_invalid) /* fe immheader_3  */
+         .quad local_label(misc_ref_invalid) /* ff nodeheader_3  */
+	
+         /* A node vector  */
+local_label(misc_ref_node):        
+         __(la imm0,misc_data_offset(arg_z))
+         __(ldx arg_z,arg_y,imm0)
+         __(blr)
+local_label(misc_ref_double_float_vector):        
+         __(la imm0,misc_data_offset(arg_z))
+         __(ldx imm0,arg_y,imm0)
+         __(li imm1,double_float_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm1,double_float.size))
+         __(std imm0,double_float.value(arg_z))
+         __(blr)
+local_label(misc_ref_s64):      
+         __(la imm0,misc_data_offset(arg_z))
+         __(ldx imm0,arg_y,imm0)
+         __(b _SPmakes64)
+local_label(misc_ref_fixnum_vector):    
+         __(la imm0,misc_data_offset(arg_z))
+         __(ldx imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_u64):      
+         __(la imm0,misc_data_offset(arg_z))
+         __(ldx imm0,arg_y,imm0)
+         __(b _SPmakeu64)
+local_label(misc_ref_new_string):        
+         __(srdi imm0,arg_z,1)
+         __(la imm0,misc_data_offset(imm0))
+         __(lwzx imm0,arg_y,imm0)
+         __(slwi imm0,imm0,charcode_shift)
+         __(ori arg_z,imm0,subtag_character)
+         __(blr)
+local_label(misc_ref_s32):                     
+         __(srdi imm0,arg_z,1)
+         __(la imm0,misc_data_offset(imm0))
+         __(lwax imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_u32):                     
+         __(srdi imm0,arg_z,1)
+         __(la imm0,misc_data_offset(imm0))
+         __(lwzx imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_single_float_vector):             
+         __(srdi imm0,arg_z,1)
+         __(la imm0,misc_data_offset(imm0))
+         __(lwzx imm0,arg_y,imm0)
+         __(rldicr arg_z,imm0,32,31)
+         __(ori arg_z,arg_z,subtag_single_float)
+         __(blr)
+local_label(misc_ref_s16):      
+         __(srdi imm0,arg_z,2)
+         __(la imm0,misc_data_offset(imm0))
+         __(lhax imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_u16):
+         __(srdi imm0,arg_z,2)
+         __(la imm0,misc_data_offset(imm0))
+         __(lhzx imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_s8):       
+         __(srdi imm0,arg_z,3)
+         __(la imm0,misc_data_offset(imm0))
+         __(lbzx imm0,arg_y,imm0)
+         __(extsb imm0,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_u8):       
+         __(srdi imm0,arg_z,3)
+         __(la imm0,misc_data_offset(imm0))
+         __(lbzx imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_string):              
+         __(srdi imm0,arg_z,3)
+         __(la imm0,misc_data_offset(imm0))
+         __(lbzx imm0,arg_y,imm0)
+         __(sldi imm0,imm0,charcode_shift)
+         __(ori arg_z,imm0,subtag_character)
+         __(blr)
+local_label(misc_ref_bit_vector):               
+	 __(extrwi imm1,arg_z,5,32-(fixnumshift+5))	/* imm1 = bitnum  */
+         __(la imm1,1+fixnumshift(imm1))
+         __(srdi imm0,arg_z,5+fixnumshift)
+         __(sldi imm0,imm0,2)
+	 __(la imm0,misc_data_offset(imm0))
+	 __(lwzx imm0,arg_y,imm0)
+	 __(rlwnm arg_z,imm0,imm1,31-fixnumshift,31-fixnumshift)
+	 __(blr)
+local_label(misc_ref_invalid):      
+         __(li arg_x,XBADVEC)
+         __(set_nargs(3))
+         __(b _SPksignalerr)        
+        __else
+         __(slwi imm1,imm1,2)
+         __(li imm0,LO(local_label(misc_ref_jmp)))
+         __(addis imm0,imm0,HA(local_label(misc_ref_jmp)))
+         __(lwzx imm0,imm0,imm1)
+         __(mtctr imm0)
+         __(bctr)
+
+local_label(misc_ref_jmp):           
+        /* 00-0f  */
+         .long local_label(misc_ref_invalid) /* 00 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 01 cons  */
+         .long local_label(misc_ref_invalid) /* 02 nodeheader  */
+         .long local_label(misc_ref_invalid) /* 03 imm  */
+         .long local_label(misc_ref_invalid) /* 04 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 05 nil  */
+         .long local_label(misc_ref_invalid) /* 06 misc  */
+         .long local_label(misc_ref_u32) /* 07 bignum  */
+         .long local_label(misc_ref_invalid) /* 08 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 09 cons  */
+         .long local_label(misc_ref_node) /* 0a ratio  */
+         .long local_label(misc_ref_invalid) /* 0b imm  */
+         .long local_label(misc_ref_invalid) /* 0c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 0d nil  */
+         .long local_label(misc_ref_invalid) /* 0e misc  */
+         .long local_label(misc_ref_u32) /* 0f single_float  */
+        /* 10-1f  */
+         .long local_label(misc_ref_invalid) /* 10 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 11 cons  */
+         .long local_label(misc_ref_invalid) /* 12 nodeheader  */
+         .long local_label(misc_ref_invalid) /* 13 imm  */
+         .long local_label(misc_ref_invalid) /* 14 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 15 nil  */
+         .long local_label(misc_ref_invalid) /* 16 misc  */
+         .long local_label(misc_ref_u32) /* 17 double_float  */
+         .long local_label(misc_ref_invalid) /* 18 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 19 cons  */
+         .long local_label(misc_ref_node) /* 1a complex  */
+         .long local_label(misc_ref_invalid) /* 1b imm  */
+         .long local_label(misc_ref_invalid) /* 1c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 1d nil  */
+         .long local_label(misc_ref_invalid) /* 1e misc  */
+         .long local_label(misc_ref_u32) /* 1f macptr  */
+        /* 20-2f  */
+         .long local_label(misc_ref_invalid) /* 20 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 21 cons  */
+         .long local_label(misc_ref_node) /* 22 catch_frame  */
+         .long local_label(misc_ref_invalid) /* 23 imm  */
+         .long local_label(misc_ref_invalid) /* 24 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 25 nil  */
+         .long local_label(misc_ref_invalid) /* 26 misc  */
+         .long local_label(misc_ref_u32) /* 27 dead_macptr  */
+         .long local_label(misc_ref_invalid) /* 28 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 29 cons  */
+         .long local_label(misc_ref_node) /* 2a function  */
+         .long local_label(misc_ref_invalid) /* 2b imm  */
+         .long local_label(misc_ref_invalid) /* 2c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 2d nil  */
+         .long local_label(misc_ref_invalid) /* 2e misc  */
+         .long local_label(misc_ref_u32) /* 2f code_vector  */
+        /* 30-3f  */
+         .long local_label(misc_ref_invalid) /* 30 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 31 cons  */
+         .long local_label(misc_ref_node) /* 32 lisp_thread  */
+         .long local_label(misc_ref_invalid) /* 33 imm  */
+         .long local_label(misc_ref_invalid) /* 34 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 35 nil  */
+         .long local_label(misc_ref_invalid) /* 36 misc  */
+         .long local_label(misc_ref_u32) /* 37 creole  */
+         .long local_label(misc_ref_invalid) /* 38 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 39 cons  */
+         .long local_label(misc_ref_node) /* 3a symbol  */
+         .long local_label(misc_ref_invalid) /* 3b imm  */
+         .long local_label(misc_ref_invalid) /* 3c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 3d nil  */
+         .long local_label(misc_ref_invalid) /* 3e misc  */
+         .long local_label(misc_ref_u32) /* 3f xcode_vector  */
+        /* 40-4f  */
+         .long local_label(misc_ref_invalid) /* 40 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 41 cons  */
+         .long local_label(misc_ref_node) /* 42 lock  */
+         .long local_label(misc_ref_invalid) /* 43 imm  */
+         .long local_label(misc_ref_invalid) /* 44 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 45 nil  */
+         .long local_label(misc_ref_invalid) /* 46 misc  */
+         .long local_label(misc_ref_invalid) /* 47 immheader  */
+         .long local_label(misc_ref_invalid) /* 48 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 49 cons  */
+         .long local_label(misc_ref_node) /* 4a hash_vector  */
+         .long local_label(misc_ref_invalid) /* 4b imm  */
+         .long local_label(misc_ref_invalid) /* 4c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 4d nil  */
+         .long local_label(misc_ref_invalid) /* 4e misc  */
+         .long local_label(misc_ref_invalid) /* 4f immheader  */
+        /* 50-5f  */
+         .long local_label(misc_ref_invalid) /* 50 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 51 cons  */
+         .long local_label(misc_ref_node) /* 52 pool  */
+         .long local_label(misc_ref_invalid) /* 53 imm  */
+         .long local_label(misc_ref_invalid) /* 54 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 55 nil  */
+         .long local_label(misc_ref_invalid) /* 56 misc  */
+         .long local_label(misc_ref_invalid) /* 57 immheader  */
+         .long local_label(misc_ref_invalid) /* 58 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 59 cons  */
+         .long local_label(misc_ref_node) /* 5a weak  */
+         .long local_label(misc_ref_invalid) /* 5b imm  */
+         .long local_label(misc_ref_invalid) /* 5c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 5d nil  */
+         .long local_label(misc_ref_invalid) /* 5e misc  */
+         .long local_label(misc_ref_invalid) /* 5f immheader  */
+        /* 60-6f  */
+         .long local_label(misc_ref_invalid) /* 60 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 61 cons  */
+         .long local_label(misc_ref_node) /* 62 package  */
+         .long local_label(misc_ref_invalid) /* 63 imm  */
+         .long local_label(misc_ref_invalid) /* 64 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 65 nil  */
+         .long local_label(misc_ref_invalid) /* 66 misc  */
+         .long local_label(misc_ref_invalid) /* 67 immheader  */
+         .long local_label(misc_ref_invalid) /* 68 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 69 cons  */
+         .long local_label(misc_ref_node) /* 6a slot_vector  */
+         .long local_label(misc_ref_invalid) /* 6b imm  */
+         .long local_label(misc_ref_invalid) /* 6c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 6d nil  */
+         .long local_label(misc_ref_invalid) /* 6e misc  */
+         .long local_label(misc_ref_invalid) /* 6f immheader  */
+        /* 70-7f  */
+         .long local_label(misc_ref_invalid) /* 70 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 71 cons  */
+         .long local_label(misc_ref_node) /* 72 instance  */
+         .long local_label(misc_ref_invalid) /* 73 imm  */
+         .long local_label(misc_ref_invalid) /* 74 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 75 nil  */
+         .long local_label(misc_ref_invalid) /* 76 misc  */
+         .long local_label(misc_ref_invalid) /* 77 immheader  */
+         .long local_label(misc_ref_invalid) /* 78 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 79 cons  */
+         .long local_label(misc_ref_node) /* 7a struct  */
+         .long local_label(misc_ref_invalid) /* 7b imm  */
+         .long local_label(misc_ref_invalid) /* 7c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 7d nil  */
+         .long local_label(misc_ref_invalid) /* 7e misc  */
+         .long local_label(misc_ref_invalid) /* 7f immheader  */
+        /* 80-8f  */
+         .long local_label(misc_ref_invalid) /* 80 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 81 cons  */
+         .long local_label(misc_ref_node) /* 82 istruct  */
+         .long local_label(misc_ref_invalid) /* 83 imm  */
+         .long local_label(misc_ref_invalid) /* 84 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 85 nil  */
+         .long local_label(misc_ref_invalid) /* 86 misc  */
+         .long local_label(misc_ref_invalid) /* 87 immheader  */
+         .long local_label(misc_ref_invalid) /* 88 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 89 cons  */
+         .long local_label(misc_ref_node) /* 8a value_cell  */
+         .long local_label(misc_ref_invalid) /* 8b imm  */
+         .long local_label(misc_ref_invalid) /* 8c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 8d nil  */
+         .long local_label(misc_ref_invalid) /* 8e misc  */
+         .long local_label(misc_ref_invalid) /* 8f immheader  */
+        /* 90-9f  */
+         .long local_label(misc_ref_invalid) /* 90 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 91 cons  */
+         .long local_label(misc_ref_node) /* 92 xfunction  */
+         .long local_label(misc_ref_invalid) /* 93 imm  */
+         .long local_label(misc_ref_invalid) /* 94 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 95 nil  */
+         .long local_label(misc_ref_invalid) /* 96 misc  */
+         .long local_label(misc_ref_invalid) /* 97 immheader  */
+         .long local_label(misc_ref_invalid) /* 98 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* 99 cons  */
+         .long local_label(misc_ref_node) /* 9a arrayN  */
+         .long local_label(misc_ref_invalid) /* 9b imm  */
+         .long local_label(misc_ref_invalid) /* 9c odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* 9d nil  */
+         .long local_label(misc_ref_invalid) /* 9e misc  */
+         .long local_label(misc_ref_invalid) /* 9f immheader  */
+        /* a0-af  */
+         .long local_label(misc_ref_invalid) /* a0 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* a1 cons  */
+         .long local_label(misc_ref_node) /* a2 vectorH  */
+         .long local_label(misc_ref_invalid) /* a3 imm  */
+         .long local_label(misc_ref_invalid) /* a4 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* a5 nil  */
+         .long local_label(misc_ref_invalid) /* a6 misc  */
+         .long local_label(misc_ref_single_float_vector) /* a7 sf_vector  */
+         .long local_label(misc_ref_invalid) /* a8 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* a9 cons  */
+         .long local_label(misc_ref_node) /* aa simple_vector  */
+         .long local_label(misc_ref_invalid) /* ab imm  */
+         .long local_label(misc_ref_invalid) /* ac odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* ad nil  */
+         .long local_label(misc_ref_invalid) /* ae misc  */
+         .long local_label(misc_ref_u32) /* af u32  */
+        /* b0-bf  */
+         .long local_label(misc_ref_invalid) /* b0 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* b1 cons  */
+         .long local_label(misc_ref_invalid) /* b2 nodeheader  */
+         .long local_label(misc_ref_invalid) /* b3 imm  */
+         .long local_label(misc_ref_invalid) /* b4 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* b5 nil  */
+         .long local_label(misc_ref_invalid) /* b6 misc  */
+         .long local_label(misc_ref_s32) /* b7 s32  */
+         .long local_label(misc_ref_invalid) /* b8 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* b9 cons  */
+         .long local_label(misc_ref_invalid) /* ba nodeheader  */
+         .long local_label(misc_ref_invalid) /* bb imm  */
+         .long local_label(misc_ref_invalid) /* bc odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* bd nil  */
+         .long local_label(misc_ref_invalid) /* be misc  */
+         .long local_label(misc_ref_fixnum_vector) /* bf fixnum_vector  */
+        /* c0-cf  */
+         .long local_label(misc_ref_invalid) /* c0 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* c1 cons  */
+         .long local_label(misc_ref_invalid) /* c2 nodeheader  */
+         .long local_label(misc_ref_invalid) /* c3 imm  */
+         .long local_label(misc_ref_invalid) /* c4 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* c5 nil  */
+         .long local_label(misc_ref_invalid) /* c6 misc  */
+         .long local_label(misc_ref_new_string) /* c7 new_string  */
+         .long local_label(misc_ref_invalid) /* c8 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* c9 cons  */
+         .long local_label(misc_ref_invalid) /* ca nodeheader  */
+         .long local_label(misc_ref_invalid) /* cb imm  */
+         .long local_label(misc_ref_invalid) /* cc odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* cd nil  */
+         .long local_label(misc_ref_invalid) /* ce misc  */
+         .long local_label(misc_ref_u8) /* cf u8  */
+        /* d0-df  */
+         .long local_label(misc_ref_invalid) /* d0 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* d1 cons  */
+         .long local_label(misc_ref_invalid) /* d2 nodeheader  */
+         .long local_label(misc_ref_invalid) /* d3 imm  */
+         .long local_label(misc_ref_invalid) /* d4 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* d5 nil  */
+         .long local_label(misc_ref_invalid) /* d6 misc  */
+         .long local_label(misc_ref_s8)      /* d7 s8  */
+         .long local_label(misc_ref_invalid) /* d8 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* d9 cons  */
+         .long local_label(misc_ref_invalid) /* da nodeheader  */
+         .long local_label(misc_ref_invalid) /* db imm  */
+         .long local_label(misc_ref_invalid) /* dc odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* dd nil  */
+         .long local_label(misc_ref_invalid) /* de misc  */
+         .long local_label(misc_ref_old_string) /* df (old)subtag_simple_base_string  */
+        /* e0-ef  */
+         .long local_label(misc_ref_invalid) /* e0 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* e1 cons  */
+         .long local_label(misc_ref_invalid) /* e2 nodeheader  */
+         .long local_label(misc_ref_invalid) /* e3 imm  */
+         .long local_label(misc_ref_invalid) /* e4 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* e5 nil  */
+         .long local_label(misc_ref_invalid) /* e6 misc  */
+         .long local_label(misc_ref_u16) /* e7 u16  */
+         .long local_label(misc_ref_invalid) /* e8 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* e9 cons  */
+         .long local_label(misc_ref_invalid) /* ea nodeheader  */
+         .long local_label(misc_ref_invalid) /* eb imm  */
+         .long local_label(misc_ref_invalid) /* ec odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* ed nil  */
+         .long local_label(misc_ref_invalid) /* ee misc  */
+         .long local_label(misc_ref_s16) /* ef s16  */
+        /* f0-ff  */
+         .long local_label(misc_ref_invalid) /* f0 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* f1 cons  */
+         .long local_label(misc_ref_invalid) /* f2 nodeheader  */
+         .long local_label(misc_ref_invalid) /* f3 imm  */
+         .long local_label(misc_ref_invalid) /* f4 odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* f5 nil  */
+         .long local_label(misc_ref_invalid) /* f6 misc  */
+         .long local_label(misc_ref_double_float_vector) /* f7 df vector  */
+         .long local_label(misc_ref_invalid) /* f8 even_fixnum  */
+         .long local_label(misc_ref_invalid) /* f9 cons  */
+         .long local_label(misc_ref_invalid) /* fa nodeheader  */
+         .long local_label(misc_ref_invalid) /* fb imm  */
+         .long local_label(misc_ref_invalid) /* fc odd_fixnum  */
+         .long local_label(misc_ref_invalid) /* fd nil  */
+         .long local_label(misc_ref_invalid) /* fe misc  */
+         .long local_label(misc_ref_bit_vector) /* ff bit_vector  */
+                
+local_label(misc_ref_node):         
+	 /* A node vector.  */
+	 __(addi imm0,arg_z,misc_data_offset)
+	 __(ldrx(arg_z,arg_y,imm0))
+	 __(blr)
+local_label(misc_ref_single_float_vector):        
+	 __(addi imm0,arg_z,misc_data_offset)
+	 __(li imm1,single_float_header)
+	 __(ldrx(imm0,arg_y,imm0))
+	 __(Misc_Alloc_Fixed(arg_z,imm1,single_float.size))
+	 __(str(imm0,single_float.value(arg_z)))
+	 __(blr)
+local_label(misc_ref_new_string):        
+	 __(addi imm0,arg_z,misc_data_offset)
+	 __(ldrx(imm0,arg_y,imm0))
+         __(slwi arg_z,imm0,charcode_shift)
+         __(ori arg_z,arg_z,subtag_character)
+         __(blr)
+local_label(misc_ref_s32):        
+	 __(addi imm0,arg_z,misc_data_offset)
+	 __(ldrx(imm0,arg_y,imm0))
+         __(b _SPmakes32)
+local_label(misc_ref_fixnum_vector):    
+	 __(addi imm0,arg_z,misc_data_offset)
+	 __(ldrx(imm0,arg_y,imm0))
+         __(box_fixnum(arg_z,imm0))
+         __(blr)        
+local_label(misc_ref_u32):        
+	 __(addi imm0,arg_z,misc_data_offset)
+	 __(ldrx(imm0,arg_y,imm0))
+         __(b _SPmakeu32)
+local_label(misc_ref_double_float_vector):      
+         __(slwi imm0,arg_z,1)
+	 __(la imm0,misc_dfloat_offset(imm0))
+         __(lfdx f0,arg_y,imm0)
+	 __(li imm2,double_float_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,double_float.size))
+	 __(stfd f0,double_float.value(arg_z))
+	 __(blr)
+local_label(misc_ref_bit_vector):       
+	 __(extrwi imm1,arg_z,5,32-(fixnumshift+5))	/* imm1 = bitnum  */
+	 __(la imm1,1+fixnumshift(imm1))
+	 __(rlwinm imm0,arg_z,32-5,5,31-fixnumshift)
+	 __(la imm0,misc_data_offset(imm0))
+	 __(ldrx(imm0,arg_y,imm0))
+	 __(rlwnm arg_z,imm0,imm1,31-fixnumshift,31-fixnumshift)
+	 __(blr)
+local_label(misc_ref_s8):       
+         __(srwi imm0,arg_z,2)
+         __(la imm0,misc_data_offset(imm0))
+         __(lbzx imm0,arg_y,imm0)
+         __(extsb imm0,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_u8):       
+         __(srwi imm0,arg_z,2)
+         __(la imm0,misc_data_offset(imm0))
+         __(lbzx imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_old_string):           
+         __(srwi imm0,arg_z,2)
+         __(la imm0,misc_data_offset(imm0))
+         __(lbzx imm0,arg_y,imm0)
+	 __(slwi arg_z,imm0,charcode_shift)
+	 __(ori arg_z,arg_z,subtag_character)
+	 __(blr)
+local_label(misc_ref_u16):              
+         __(srwi imm0,arg_z,1)
+         __(la imm0,misc_data_offset(imm0))
+         __(lhzx imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_s16):              
+         __(srwi imm0,arg_z,1)
+         __(la imm0,misc_data_offset(imm0))
+         __(lhax imm0,arg_y,imm0)
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+local_label(misc_ref_invalid):
+         __(li arg_x,XBADVEC)
+         __(set_nargs(3))
+         __(b _SPksignalerr)        
+
+        __endif
+        
+/* like misc_ref, only the boxed subtag is in arg_x.  */
+
+_spentry(subtag_misc_ref)
+	__(trap_unless_fulltag_equal(arg_y,fulltag_misc,imm0))
+        __(trap_unless_lisptag_equal(arg_z,tag_fixnum,imm0))
+	__(vector_length(imm0,arg_y,imm1))
+	__(trlge(arg_z,imm0))
+	__(unbox_fixnum(imm1,arg_x))
+        __(b local_label(misc_ref_common))
+
+_spentry(builtin_aref1)
+	__(extract_typecode(imm0,arg_y))
+	__(cmpri(cr0,imm0,min_vector_subtag))
+	__(box_fixnum(arg_x,imm0))
+	__(bgt cr0,_SPsubtag_misc_ref)
+	__(jump_builtin(_builtin_aref1,2))
+        	
+	
+/* Make a cons cell on the vstack.  Always push 3 words, 'cause we're   */
+/* not sure how the vstack will be aligned.  */
+_spentry(stkconsyz)
+	__(li imm0,nil_value)
+	__(vpush(imm0))
+	__(vpush(imm0))
+	__(vpush(imm0))
+	__(andi. imm0,vsp,1<<word_shift) /* (oddp vsp ?)  */
+	__(beq cr0,1f)
+	__(str(arg_y,node_size*2(vsp))) /* car  */
+	__(str(arg_z,node_size(vsp))) /* cdr  */
+	__(la arg_z,fulltag_cons+node_size(vsp))
+	__(blr)
+1:
+	__(str(arg_y,node_size(vsp))) /* car, again  */
+	__(str(arg_z,0(vsp)))
+	__(la arg_z,fulltag_cons(vsp))
+	__(blr)
+
+/* Make a stack-consed value cell.  Much like the case of */
+/* stack-allocating a cons cell.  Imm0 points to the closed-over value */
+/* (already vpushed).  Replace that locative with the vcell.  */
+_spentry(stkvcell0)
+	__(sub imm1,imm0,vsp) /* imm1 = delta from vsp to value cell loc  */
+	__(li arg_z,nil_value)
+	__(vpush(arg_z))
+	__(vpush(arg_z))
+	__(vpush(arg_z))
+	__(addi imm1,imm1,node_size*3)
+	__(add imm0,vsp,imm1) /* in case stack overflowed  */
+	__(andi. imm1,vsp,1<<word_shift) /* (oddp vsp) ?  */
+	__(li imm1,value_cell_header)
+	__(ldr(arg_z,0(imm0)))
+	__(beq cr0,1f)
+	__(str(arg_z,node_size*2(vsp)))
+	__(str(imm1,node_size(vsp)))
+	__(la arg_z,fulltag_misc+node_size(vsp))
+	__(str(arg_z,0(imm0)))
+	__(blr)
+1:
+	__(str(arg_z,node_size(vsp)))
+	__(str(imm1,0(vsp)))
+	__(la arg_z,fulltag_misc(vsp))
+	__(str(arg_z,0(imm0)))
+	__(blr)
+
+        
+_spentry(stkvcellvsp)      
+	__(li arg_z,nil_value)
+	__(vpush(arg_z))
+	__(vpush(arg_z))
+	__(vpush(arg_z))
+	__(li imm1,node_size*3)
+	__(add imm0,vsp,imm1) /* in case stack overflowed  */
+	__(andi. imm1,vsp,1<<word_shift) /* (oddp vsp) ?  */
+	__(li imm1,value_cell_header)
+	__(ldr(arg_z,0(imm0)))
+	__(beq cr0,1f)
+	__(str(arg_z,node_size*2(vsp)))
+	__(str(imm1,node_size(vsp)))
+	__(la arg_z,fulltag_misc+node_size(vsp))
+	__(str(arg_z,0(imm0)))
+	__(blr)
+1:
+	__(str(arg_z,node_size(vsp)))
+	__(str(imm1,0(vsp)))
+	__(la arg_z,fulltag_misc(vsp))
+	__(str(arg_z,0(imm0)))
+	__(blr)
+
+/* Make a "raw" area on the temp stack, stack-cons a macptr to point to it,  */
+/* and return the macptr.  Size (in bytes, boxed) is in arg_z on entry; macptr */
+/* in arg_z on exit.  */
+_spentry(makestackblock)
+	__(unbox_fixnum(imm0,arg_z))
+        __(dnode_align(imm0,imm0,tsp_frame.fixed_overhead+macptr.size))
+	__(cmplri(cr0,imm0,tstack_alloc_limit))
+	__(bge cr0,1f)
+	__(TSP_Alloc_Var_Unboxed(imm0))
+	__(li imm0,macptr_header)
+	__(la imm1,tsp_frame.data_offset+macptr.size(tsp))
+	__(str(imm0,tsp_frame.data_offset(tsp)))
+	__(la arg_z,tsp_frame.data_offset+fulltag_misc(tsp))
+	__(str(imm1,macptr.address(arg_z)))
+        __ifdef([PPC64])
+         __(std rzero,macptr.domain(arg_z))
+         __(std rzero,macptr.type(arg_z))
+        __else
+	 __(stfd fp_zero,macptr.domain(arg_z))
+        __endif
+	__(blr)
+
+        /* Too big. Heap cons a gcable macptr  */
+1:
+	__(TSP_Alloc_Fixed_Unboxed(0))
+	__(set_nargs(1))
+	__(li fname,nrs.new_gcable_ptr)
+	__(jump_fname())
+
+/* As above, only set the block's contents to 0.  */
+_spentry(makestackblock0)
+	__(unbox_fixnum(imm0,arg_z))
+        __(dnode_align(imm0,imm0,tsp_frame.fixed_overhead+macptr.size))
+	__(cmplri(cr0,imm0,tstack_alloc_limit))
+	__(bge cr0,3f)
+	__(TSP_Alloc_Var_Unboxed(imm0))
+	__(Zero_TSP_Frame(imm0,imm1))
+	__(li imm0,macptr_header)
+	__(la imm1,tsp_frame.data_offset+macptr.size(tsp))
+	__(str(imm0,tsp_frame.data_offset(tsp)))
+	__(la arg_z,tsp_frame.data_offset+fulltag_misc(tsp))
+	__(str(imm1,macptr.address(arg_z))) /* makestackblock0 expects the address to be in imm1  */
+	__(stfd fp_zero,macptr.domain(arg_z))
+	__(blr)
+
+        /* Too big. Heap cons a gcable macptr  */
+3:
+	__(TSP_Alloc_Fixed_Unboxed(0)) /* "raw" block to make the compiler happy  */
+
+	__(mr arg_y,arg_z) /* save block size  */
+	__(li arg_z,t_value) /* clear-p arg to %new-gcable-ptr  */
+	__(set_nargs(2))
+	__(li fname,nrs.new_gcable_ptr)
+	__(jump_fname())
+
+/* Make a list of length arg_y (boxed), initial-element arg_z (boxed) on  */
+/* the tstack.  Return the list in arg_z.  */
+_spentry(makestacklist)
+	__(add imm0,arg_y,arg_y)
+	__(cmplri(cr1,imm0,((tstack_alloc_limit+1)-cons.size)))
+	__(addi imm0,imm0,tsp_frame.fixed_overhead)
+	__(bge cr1,3f)
+	__(TSP_Alloc_Var_Boxed(imm0,imm1))
+	__(mr imm1,arg_y)
+	__(cmpri(cr1,imm1,0))
+	__(mr arg_y,arg_z)
+	__(li arg_z,nil_value)
+	__(ldr(imm2,tsp_frame.backlink(tsp)))
+	__(la imm2,-tsp_frame.fixed_overhead+fulltag_cons(imm2))
+	__(b 2f)
+1:
+	__(subi imm1,imm1,fixnum1)
+	__(cmpri(cr1,imm1,0))
+	__(_rplacd(imm2,arg_z))
+	__(_rplaca(imm2,arg_y))
+	__(mr arg_z,imm2)
+	__(subi imm2,imm2,cons.size)
+2:
+	__(bne cr1,1b)
+	__(blr)
+
+3:
+	__(cmpri(cr1,arg_y,0))
+	__(TSP_Alloc_Fixed_Boxed(0))  /* make the compiler happy  */
+	__(mr imm1,arg_y) /* count  */
+	__(mr arg_y,arg_z) /* initial value  */
+	__(li arg_z,nil_value) /* result  */
+	__(b 5f)
+4:
+	__(subi imm1,imm1,fixnum1)
+	__(cmpri(cr1,imm1,0))
+	__(Cons(arg_z,arg_y,arg_z))
+5:
+	__(bne cr1,4b)
+	__(blr)
+
+/* subtype (boxed) vpushed before initial values. (Had better be a  */
+/* node header subtag.) Nargs set to count of things vpushed.  */
+
+_spentry(stkgvector)
+	__(la imm0,-fixnum_one(nargs))
+	__(cmpri(cr1,imm0,0))
+	__(add imm1,vsp,nargs)
+	__(ldru(temp0,-node_size(imm1)))
+	__(slri(imm2,imm0,num_subtag_bits-fixnumshift))
+        __ifdef([PPC64])
+         __(unbox_fixnum(imm3,temp0))
+         __(or imm2,imm3,imm2)
+        __else
+	 __(rlwimi imm2,temp0,32-fixnumshift,32-num_subtag_bits,31)
+        __endif
+        __(dnode_align(imm0,imm0,node_size+tsp_frame.fixed_overhead))
+	__(TSP_Alloc_Var_Boxed_nz(imm0,imm3))
+	__(str(imm2,tsp_frame.data_offset(tsp)))
+	__(la arg_z,tsp_frame.data_offset+fulltag_misc(tsp))
+	__(la imm3,misc_header_offset(arg_z))
+	__(li imm0,fixnum1)
+	__(b 2f)
+1:
+	__(addi imm0,imm0,fixnum1)
+	__(cmpr(cr1,imm0,nargs))
+	__(ldru(temp0,-node_size(imm1)))
+	__(stru(temp0,node_size(imm3)))
+2:
+	__(bne cr1,1b)
+	__(add vsp,vsp,nargs)
+	__(blr)
+
+/* Allocate a "fulltag_misc" object.  On entry, arg_y contains the element  */
+/* count (boxed) and  arg_z contains the subtag (boxed).  Both of these   */
+/* parameters must be "reasonable" (the  subtag must be valid, the element  */
+/* count must be of type (unsigned-byte 24)/(unsigned-byte 56).   */
+/* On exit, arg_z contains the (properly tagged) misc object; it'll have a  */
+/* proper header on it and its contents will be 0.   imm0 contains   */
+/* the object's header (fulltag = fulltag_immheader or fulltag_nodeheader.)  */
+/* This is intended for things like "make-array" and "%make-bignum" and the   */
+/* like.  Things that involve creating small objects of known size can usually  */
+/* do so inline with less hair.  */
+
+/* If this has to go out-of-line (to GC or whatever), it should do so via a   */
+/* trap (or should otherwise ensure that both the LR and CTR are preserved   */
+/* where the GC can find them.)  */
+
+
+_spentry(misc_alloc)
+        __ifdef([PPC64])
+         __(extract_unsigned_byte_bits_(imm2,arg_y,56))
+         __(unbox_fixnum(imm0,arg_z))
+         __(sldi imm2,arg_y,num_subtag_bits-fixnumshift)
+         __(clrldi imm1,imm0,64-nlowtagbits)
+         __(or imm0,imm2,imm0)
+         __(extract_fulltag(imm2,imm0))
+         __(cmpdi cr1,imm1,lowtag_nodeheader)
+         __(cmpdi cr2,imm2,ivector_class_64_bit)
+         __(bne- cr0,9f)
+         __(cmpdi cr3,imm2,ivector_class_32_bit)
+         __(cmpdi cr4,imm2,ivector_class_8_bit)
+         __(mr imm2,arg_y)
+         __(cmpdi cr5,imm1,subtag_bit_vector)
+         __(beq cr1,1f)
+         __(beq cr2,1f)
+         __(srdi imm2,imm2,1)
+         __(beq cr3,1f)
+         __(beq cr5,2f)
+         __(srdi imm2,imm2,1)
+         __(bne cr4,1f)
+         __(srdi imm2,imm2,1)
+/* imm2 now = byte count.  Add 8 for header, 15 to align, then clear */
+/* low four bits. */
+1:
+         __(dnode_align(imm2,imm2,node_size))
+
+	 __(Misc_Alloc(arg_z,imm0,imm2))
+	 __(blr)
+2:      /* bit-vector case  */
+         __(addi imm2,arg_y,7<<fixnumshift)
+         __(srdi imm2,imm2,3+fixnumshift)
+         __(b 1b)
+9:                      
+	 __(uuo_interr(error_object_not_unsigned_byte_56,arg_y))
+        __else
+	 __(extract_unsigned_byte_bits_(imm2,arg_y,24))
+	 __(unbox_fixnum(imm0,arg_z))
+	 __(extract_fulltag(imm1,imm0))
+	 __(bne- cr0,9f)
+	 __(cmpri(cr0,imm1,fulltag_nodeheader))
+	 __(mr imm3,imm0)
+	 __(cmplri(cr1,imm0,max_32_bit_ivector_subtag))
+	 __(rlwimi imm0,arg_y,num_subtag_bits-fixnum_shift,0,31-num_subtag_bits	)/* imm0 now = header  */
+	 __(mr imm2,arg_y)
+	 __(beq cr0,1f)	/* do probe if node object (fixnum element count = byte count).  */
+	 __(cmplri(cr0,imm3,max_16_bit_ivector_subtag))
+	 __(bng cr1,1f)	/* do probe if 32-bit imm object  */
+	 __(cmplri(cr1,imm3,max_8_bit_ivector_subtag))
+	 __(srwi imm2,imm2,1)
+	 __(bgt cr0,2f)
+	 __(bgt cr1,1f)
+	 __(srwi imm2,imm2,1)
+        /* imm2 now = byte count.  Add 4 for header, 7 to align, then clear */
+        /* low three bits.  */
+1:
+         __(dnode_align(imm2,imm2,node_size))
+
+	 __(Misc_Alloc(arg_z,imm0,imm2))
+	 __(blr)
+2:
+	 __(cmplri(imm3,subtag_double_float_vector))
+	 __(slwi imm2,arg_y,1)
+	 __(beq 1b)
+	 __(addi imm2,arg_y,7<<fixnumshift)
+	 __(srwi imm2,imm2,fixnumshift+3)
+	 __(b 1b)
+9:
+	 __(uuo_interr(error_object_not_unsigned_byte_24,arg_y))
+        __endif
+        
+/* almost exactly as above, but "swap exception handling info" */
+/* on exit and return  */
+/* Deprecated */        
+_spentry(poweropen_ffcallX)
+        .long 0x7c800008        /* debug trap */
+
+
+/* Destructuring-bind, macro-bind.  */
+   
+/* OK to use arg_x, arg_y for whatever (tagged) purpose;  */
+/* likewise immX regs.  */
+/* arg_z preserved, nothing else in particular defined on exit.  */
+/* nargs contains req count (0-255) in PPC bits mask_req_start/mask_req_width,  */
+/* opt count (0-255) in PPC bits mask_opt_start/mask_opt_width,  */
+/* key count (0-255) in PPC bits mask_key_start/mask_key_width,  */
+/* opt-supplied-p flag in PPC bit mask_initopt,  */
+/* keyp flag in PPC bit mask_keyp,  */
+/* &allow-other-keys flag in PPC bit mask_aok,  */
+/* &rest flag in PPC bit mask_restp.  */
+/* When mask_keyp bit is set, keyvect contains vector of keyword symbols,  */
+/* length key count.  */
+
+_spentry(macro_bind)
+        __ifdef([PPC64])
+ 	 __(mr whole_reg,arg_reg)
+	 __(extract_fulltag(imm0,arg_reg))
+         __(cmpri(cr1,arg_reg,nil_value))
+	 __(cmpri(cr0,imm0,fulltag_cons))
+         __(beq cr1,0f)
+	 __(bne- cr0,1f)
+0:             
+	 __(_cdr(arg_reg,arg_reg))
+	 __(b local_label(destbind1))
+        __else
+	 __(mr whole_reg,arg_reg)
+	 __(extract_lisptag(imm0,arg_reg))
+	 __(cmpri(cr0,imm0,tag_list))
+	 __(bne- cr0,1f)
+	 __(_cdr(arg_reg,arg_reg))
+	 __(b (local_label(destbind1)))
+        __endif
+1:
+	__(li arg_y,XCALLNOMATCH)
+	__(mr arg_z,whole_reg)
+	__(set_nargs(2))
+	__(b _SPksignalerr)
+
+
+_spentry(destructuring_bind)
+	__(mr whole_reg,arg_reg)
+        __(b local_label(destbind1))
+	
+_spentry(destructuring_bind_inner)
+	__(mr whole_reg,arg_z)
+local_label(destbind1): 
+	/* Extract required arg count.  */
+	/* A bug in gas: can't handle shift count of "32" (= 0  */
+	ifelse(eval(mask_req_width+mask_req_start),eval(32),[
+	__(clrlwi. imm0,nargs,mask_req_start)
+	],[
+	__(extrwi. imm0,nargs,mask_req_width,mask_req_start)
+	])
+	__(extrwi imm1,nargs,mask_opt_width,mask_opt_start)
+	__(rlwinm imm2,nargs,0,mask_initopt,mask_initopt)
+	__(rlwinm imm4,nargs,0,mask_keyp,mask_keyp)
+	__(cmpri(cr4,imm4,0))
+	__(rlwinm imm4,nargs,0,mask_restp,mask_restp)
+	__(cmpri(cr5,imm4,0))
+	__(cmpri(cr1,imm1,0))
+	__(cmpri(cr2,imm2,0))
+	/* Save entry vsp in case of error.  */
+	__(mr imm4,vsp)
+	__(beq cr0,2f)
+1:
+	__(cmpri(cr7,arg_reg,nil_value))
+        __ifdef([PPC64])
+         __(extract_fulltag(imm3,arg_reg))
+         __(cmpri(cr3,imm3,fulltag_cons))
+        __else       
+	 __(extract_lisptag(imm3,arg_reg))
+	 __(cmpri(cr3,imm3,tag_list))
+        __endif
+	__(subi imm0,imm0,1)
+	__(cmpri(cr0,imm0,0))
+	__(beq cr7,toofew)
+	__(bne cr3,badlist)
+	__(ldr(arg_x,cons.car(arg_reg)))
+	__(ldr(arg_reg,cons.cdr(arg_reg)))
+	__(vpush(arg_x))
+	__(bne cr0,1b)
+2:
+	__(beq cr1,rest_keys)
+	__(bne cr2,opt_supp)
+	/* 'simple' &optionals:	 no supplied-p, default to nil.  */
+simple_opt_loop:
+	__(cmpri(cr0,arg_reg,nil_value))
+        __ifdef([PPC64])
+         __(extract_fulltag(imm3,arg_reg))
+         __(cmpri(cr3,imm3,fulltag_cons))
+        __else
+	 __(extract_lisptag(imm3,arg_reg))
+	 __(cmpri(cr3,imm3,tag_list))
+        __endif
+	__(subi imm1,imm1,1)
+	__(cmpri(cr1,imm1,0))
+	__(li imm5,nil_value)
+	__(beq cr0,default_simple_opt)
+	__(bne cr3,badlist)
+	__(ldr(arg_x,cons.car(arg_reg)))
+	__(ldr(arg_reg,cons.cdr(arg_reg)))
+	__(vpush(arg_x))
+	__(bne cr1,simple_opt_loop)
+	__(b rest_keys)
+default_simple_opt_loop:
+	__(subi imm1,imm1,1)
+	__(cmpri(cr1,imm1,0))
+default_simple_opt:
+	__(vpush(imm5))
+	__(bne cr1,default_simple_opt_loop)
+	__(b rest_keys)
+	/* Provide supplied-p vars for the &optionals.  */
+opt_supp:
+	__(li arg_y,t_value)
+opt_supp_loop:
+	__(cmpri(cr0,arg_reg,nil_value))
+        __ifdef([PPC64])
+         __(extract_fulltag(imm3,arg_reg))
+         __(cmpri(cr3,imm3,fulltag_cons))
+        __else        
+	 __(extract_lisptag(imm3,arg_reg))
+	 __(cmpri(cr3,imm3,tag_list))
+        __endif
+	__(subi imm1,imm1,1)
+	__(cmpri(cr1,imm1,0))
+	__(beq cr0,default_hard_opt)
+	__(bne cr3,badlist)
+	__(ldr(arg_x,cons.car(arg_reg)))
+	__(ldr(arg_reg,cons.cdr(arg_reg)))
+	__(vpush(arg_x))
+	__(vpush(arg_y))
+	__(bne cr1,opt_supp_loop)
+	__(b rest_keys)
+default_hard_opt_loop:
+	__(subi imm1,imm1,1)
+	__(cmpri(cr1,imm1,0))
+default_hard_opt:
+	__(vpush(imm5))
+	__(vpush(imm5))
+	__(bne cr1,default_hard_opt_loop)
+rest_keys:
+	__(cmpri(cr0,arg_reg,nil_value))
+	__(bne cr5,have_rest)
+	__(bne cr4,have_keys)
+	__(bne cr0,toomany)
+	__(blr)
+have_rest:
+	__(vpush(arg_reg))
+	__(beqlr cr4)
+have_keys:
+	/* Ensure that arg_reg contains a proper,even-length list.  */
+	/* Insist that its length is <= 512 (as a cheap circularity check.)  */
+	__(li imm0,256)
+	__(mr arg_x,arg_reg)
+count_keys_loop:
+        __ifdef([PPC64])
+         __(extract_fulltag(imm3,arg_x))
+         __(cmpri(cr3,imm3,fulltag_cons))
+        __else
+	 __(extract_lisptag(imm3,arg_x))
+	 __(cmpri(cr3,imm3,tag_list))
+        __endif
+	__(cmpri(cr0,arg_x,nil_value))
+	__(subi imm0,imm0,1)
+	__(cmpri(cr4,imm0,0))
+	__(beq cr0,counted_keys)
+	__(bne cr3,badlist)
+	__(ldr(arg_x,cons.cdr(arg_x)))
+        __ifdef([PPC64])
+         __(extract_fulltag(imm3,arg_x))
+         __(cmpri(cr3,imm3,fulltag_cons))
+        __else
+	 __(extract_lisptag(imm3,arg_x))
+	 __(cmpri(cr3,imm3,tag_list))
+        __endif
+	__(blt cr4,toomany)
+	__(cmpri(cr0,arg_x,nil_value))
+	__(beq cr0,db_badkeys)
+	__(bne cr3,badlist)
+	__(ldr(arg_x,cons.cdr(arg_x)))
+	__(b count_keys_loop)
+counted_keys:
+	/* We've got a proper, even-length list of key/value pairs in */
+	/* arg_reg. For each keyword var in the lambda-list, push a pair */
+	/* of NILs on the vstack.  */
+	__(extrwi. imm0,nargs,mask_key_width,mask_key_start )
+	__(mr imm2,imm0) 	/* save number of keys  */
+	__(li imm5,nil_value)
+	__(b push_pair_test)
+push_pair_loop:
+	__(cmpri(cr0,imm0,1))
+	__(subi imm0,imm0,1)
+	__(vpush(imm5))
+	__(vpush(imm5))
+push_pair_test:
+	__(bne cr0,push_pair_loop)
+	__(slwi imm2,imm2,dnode_shift)  /* pairs -> bytes  */
+	__(add imm2,vsp,imm2)		/* imm2 points below pairs  */
+	__(li imm0,0)			/* count unknown keywords so far  */
+	__(extrwi imm1,nargs,1,mask_aok) /* unknown keywords allowed  */
+	__(extrwi nargs,nargs,mask_key_width,mask_key_start)
+	/* Now, for each keyword/value pair in the list  */
+	/*  a) if the keyword is found in the keyword vector, set the  */
+	/*     corresponding entry on the vstack to the value and the  */
+	/*     associated supplied-p var to T.  */
+	/*  b) Regardless of whether or not the keyword is found,  */
+        /*     if :ALLOW-OTHER-KEYS is provided with a non-nil value, */
+	/*     set the low bit of imm1 to indicate that unknown keywords  */
+	/*     are acceptable. (This bit is pre-set above to the value */
+        /*     the encoded value of &allow_other_keys.) */
+	/*  c) If the keyword is not found (and isn't :ALLOW-OTHER-KEYS), increment  */
+	/*     the count of unknown keywords in the high bits of imm1*/
+	/* At the end of the list, signal an error if any unknown keywords were seen  */
+	/* but not allowed.  Otherwise, return.  */
+
+match_keys_loop:
+	__(cmpri(cr0,arg_reg,nil_value))
+	__(li imm0,0)
+	__(li imm3,misc_data_offset)
+	__(beq cr0,matched_keys)
+	__(ldr(arg_x,cons.car(arg_reg)))
+	__(li arg_y,nrs.kallowotherkeys)
+	__(cmpr(cr3,arg_x,arg_y))	/* :ALLOW-OTHER-KEYS ?  */
+	__(ldr(arg_reg,cons.cdr(arg_reg)))
+	__(ldr(arg_y,cons.car(arg_reg)))
+	__(cmpr(cr4,imm0,nargs))
+	__(ldr(arg_reg,cons.cdr(arg_reg)))
+	__(b match_test)
+match_loop:
+	__(ldrx(temp0,keyvect_reg,imm3))
+	__(cmpr(cr0,arg_x,temp0))
+	__(addi imm0,imm0,1)
+	__(cmpr(cr4,imm0,nargs))
+	__(addi imm3,imm3,node_size)
+	__(bne cr0,match_test)
+	/* Got a hit.  Unless this keyword's been seen already, set it.  */
+	__(slwi imm0,imm0,dnode_shift)
+	__(subf imm0,imm0,imm2)
+	__(ldr(temp0,0(imm0)))
+	__(cmpri(cr0,temp0,nil_value))
+	__(li temp0,t_value)
+	__(bne cr0,match_keys_loop)	/* already saw this  */
+	__(str(arg_y,node_size*1(imm0)))
+	__(str(temp0,node_size*0(imm0)))
+        __(bne cr3,match_keys_loop)
+	__(b match_keys_check_aok)
+match_test:
+	__(bne cr4,match_loop)
+        __(beq cr3,match_keys_check_aok)
+        __(addi imm1,imm1,node_size)
+        __(b match_keys_loop)
+match_keys_check_aok:
+        __(andi. imm0,imm1,2)  /* check "seen-aok" bit in imm1 */
+        __(cmpri cr1,arg_y,nil_value) /* check value */
+        __(ori imm1,imm1,2)
+        __(bne cr0,match_keys_loop) /* duplicate aok */
+        __(beq cr1,match_keys_loop)
+        __(ori imm1,imm1,1)
+	__(b match_keys_loop)
+matched_keys:
+        __(clrrwi. imm0,imm1,2)
+        __(beqlr)
+        __(andi. imm1,imm1,1)
+        __(bnelr)
+	/* Some unrecognized keywords.  Complain generically about  */
+	/* invalid keywords.  */
+db_badkeys:
+	__(li arg_y,XBADKEYS)
+	__(b destructure_error)
+toomany:
+	__(li arg_y,XCALLTOOMANY)
+	__(b destructure_error)
+toofew:
+	__(li arg_y,XCALLTOOFEW)
+	__(b destructure_error)
+badlist:
+	__(li arg_y,XCALLNOMATCH)
+	/* b destructure_error  */
+destructure_error:
+	__(mr vsp,imm4)		/* undo everything done to the stack  */
+	__(mr arg_z,whole_reg)
+	__(set_nargs(2))
+	__(b _SPksignalerr)
+        
+/* vpush the values in the value set atop the vsp, incrementing nargs.  */
+/* Discard the tsp frame; leave values atop the vsp.  */
+
+_spentry(recover_values)
+
+/* First, walk the segments reversing the pointer to previous segment pointers  */
+/* Can tell the end because that previous segment pointer is the prev tsp pointer  */
+	__(ldr(imm0,tsp_frame.backlink(tsp))) /* previous tsp  */
+	__(mr imm1,tsp) /* current segment  */
+	__(mr imm2,tsp) /* last segment  */
+local_label(walkloop):
+	__(ldr(imm3,tsp_frame.fixed_overhead+node_size(imm1))) /* next segment  */
+	__(cmpr(cr0,imm0,imm3)) /* last segment?  */
+	__(str(imm2,tsp_frame.fixed_overhead+node_size(imm1))) /* reverse pointer  */
+	__(mr imm2,imm1) /* last segment <- current segment  */
+	__(mr imm1,imm3) /* current segment <- next segment  */
+	__(bne cr0,local_label(walkloop))
+
+        /* the final segment ptr is now in imm2  */
+        /* walk backwards, pushing values on VSP and incrementing NARGS  */
+local_label(pushloop):
+	__(ldr(imm0,tsp_frame.data_offset(imm2))) /* nargs in segment  */
+	__(cmpri(cr0,imm0,0))
+	__(cmpr(cr1,imm2,tsp))
+	__(la imm3,tsp_frame.data_offset+(2*node_size)(imm2))
+	__(add imm3,imm3,imm0)
+	__(add nargs,nargs,imm0)
+	__(b 2f)
+1:
+	__(ldru(arg_z,-node_size(imm3)))
+	__(cmpri(cr0,imm0,fixnum_one))
+	__(subi imm0,imm0,fixnum_one)
+	__(vpush(arg_z))
+2:
+	__(bne cr0,1b)
+	__(ldr(imm2,tsp_frame.data_offset+node_size(imm2))) /* previous segment  */
+	__(bne cr1,local_label(pushloop))
+	__(unlink(tsp))
+	__(blr)
+
+	
+/* Go out of line to do this.  Sheesh.  */
+
+_spentry(vpopargregs)
+	__(cmpri(cr0,nargs,0))
+	__(cmpri(cr1,nargs,2<<fixnumshift))
+	__(beqlr cr0)
+	__(beq cr1,local_label(yz))
+	__(blt cr1,local_label(z))
+	__(ldr(arg_z,node_size*0(vsp)))
+	__(ldr(arg_y,node_size*1(vsp)))
+	__(ldr(arg_x,node_size*2(vsp)))
+	__(la vsp,node_size*3(vsp))
+	__(blr)
+local_label(yz):
+	__(ldr(arg_z,node_size*0(vsp)))
+	__(ldr(arg_y,node_size*1(vsp)))
+	__(la vsp,node_size*2(vsp))
+	__(blr)
+local_label(z):
+	__(ldr(arg_z,node_size*0(vsp)))
+	__(la vsp,node_size*1(vsp))
+	__(blr)
+
+/* If arg_z is an integer, return in imm0 something whose sign  */
+/* is the same as arg_z's.  If not an integer, error.  */
+_spentry(integer_sign)
+	__(extract_typecode(imm0,arg_z))
+	__(cmpri(cr1,imm0,tag_fixnum))
+	__(cmpri(cr0,imm0,subtag_bignum))
+	__(mr imm0,arg_z)
+	__(beqlr+ cr1)
+	__(bne- cr0,1f)
+	__(getvheader(imm0,arg_z))
+        __ifdef([PPC64])
+         __(header_size(imm0,imm0))
+         __(sldi imm0,imm0,2)
+        __else
+         __(header_length(imm0,imm0)) /* boxed length = scaled size  */
+        __endif
+        __(addi imm0,imm0,misc_data_offset-4) /* bias, less 1 element  */
+	__(lwzx imm0,arg_z,imm0)
+	__(cmpwi cr0,imm0,0)
+	__(li imm0,1)
+	__(bgelr cr0)
+	__(li imm0,-1)
+	__(blr)
+1:
+	__(uuo_interr(error_object_not_integer,arg_z))
+
+/* like misc_set, only pass the (boxed) subtag in temp0  */
+_spentry(subtag_misc_set)
+	__(trap_unless_fulltag_equal(arg_x,fulltag_misc,imm0))
+	__(trap_unless_lisptag_equal(arg_y,tag_fixnum,imm0))
+	__(vector_length(imm0,arg_x,imm1))
+	__(trlge(arg_y,imm0))
+	__(unbox_fixnum(imm1,temp0))
+local_label(misc_set_common):
+        __ifdef([PPC64])
+         __(slwi imm1,imm1,3)
+         __(li imm0,LO(local_label(misc_set_jmp)))
+         __(addis imm0,imm0,HA(local_label(misc_set_jmp)))
+         __(ldx imm0,imm0,imm1)
+         __(mtctr imm0)
+         __(bctr)
+local_label(misc_set_jmp):              
+        /* 00-0f  */
+         .quad local_label(misc_set_invalid) /* 00 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 01 imm_0  */
+         .quad local_label(misc_set_invalid) /* 02 immheader_0  */
+         .quad _SPgvset /* 03 function  */
+         .quad local_label(misc_set_invalid) /* 04 cons  */
+         .quad local_label(misc_set_invalid) /* 05 imm_1  */
+         .quad local_label(misc_set_invalid) /* 06 immheader_1  */
+         .quad _SPgvset /* 07 catch_frame  */
+         .quad local_label(misc_set_invalid) /* 08 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 09 imm_2  */
+         .quad local_label(misc_set_u32) /* 0a code_vector  */
+         .quad _SPgvset /* 0b slot_vector  */
+         .quad local_label(misc_set_invalid) /* 0c misc  */
+         .quad local_label(misc_set_invalid) /* 0d imm3  */
+         .quad local_label(misc_set_invalid) /* 0e immheader_3  */
+         .quad _SPgvset /* 0f ratio  */
+        /* 10-1f  */
+         .quad local_label(misc_set_invalid) /* 10 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 11 imm_0  */
+         .quad local_label(misc_set_invalid) /* 12 immheader_0  */
+         .quad _SPgvset /* 13 symbol_0  */
+         .quad local_label(misc_set_invalid) /* 14 cons  */
+         .quad local_label(misc_set_invalid) /* 15 imm_1  */
+         .quad local_label(misc_set_invalid) /* 16 immheader_1  */
+         .quad _SPgvset /* 17 lisp_tread  */
+         .quad local_label(misc_set_invalid) /* 18 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 19 imm_2  */
+         .quad local_label(misc_set_u32) /* 1a xcode_vector  */
+         .quad _SPgvset /* 1b instance  */
+         .quad local_label(misc_set_invalid) /* 1c misc  */
+         .quad local_label(misc_set_invalid) /* 1d imm3  */
+         .quad local_label(misc_set_u64) /* 1e macptr  */
+         .quad _SPgvset /* 1f complex  */
+        /* 20-2f  */
+         .quad local_label(misc_set_invalid) /* 20 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 21 imm_0  */
+         .quad local_label(misc_set_invalid) /* 22 immheader_0  */
+         .quad local_label(misc_set_invalid) /* 23 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 24 cons  */
+         .quad local_label(misc_set_invalid) /* 25 imm_1  */
+         .quad local_label(misc_set_invalid) /* 26 immheader_1  */
+         .quad _SPgvset /* 27 lock  */
+         .quad local_label(misc_set_invalid) /* 28 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 29 imm_2  */
+         .quad local_label(misc_set_u32) /* 2a bignum  */
+         .quad _SPgvset /* 2b struct  */
+         .quad local_label(misc_set_invalid) /* 2c misc  */
+         .quad local_label(misc_set_invalid) /* 2d imm3  */
+         .quad local_label(misc_set_u64) /* 2e dead_macptr  */
+         .quad local_label(misc_set_invalid) /* 2f nodeheader_3  */
+        /* 30-3f  */
+         .quad local_label(misc_set_invalid) /* 30 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 31 imm_0  */
+         .quad local_label(misc_set_invalid) /* 32 immheader_0  */
+         .quad local_label(misc_set_invalid) /* 33 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 34 cons  */
+         .quad local_label(misc_set_invalid) /* 35 imm_1  */
+         .quad local_label(misc_set_invalid) /* 36 immheader_1  */
+         .quad _SPgvset /* 37 hash_vector  */
+         .quad local_label(misc_set_invalid) /* 38 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 39 imm_2  */
+         .quad local_label(misc_set_u32) /* 3a double_float  */
+         .quad _SPgvset /* 3b istruct  */
+         .quad local_label(misc_set_invalid) /* 3c misc  */
+         .quad local_label(misc_set_invalid) /* 3d imm3  */
+         .quad local_label(misc_set_invalid) /* 3e immheader_3  */
+         .quad local_label(misc_set_invalid) /* 3f nodeheader_3  */
+        /* 40-4f  */
+         .quad local_label(misc_set_invalid) /* 40 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 41 imm_0  */
+         .quad local_label(misc_set_invalid) /* 42 immheader_0  */
+         .quad local_label(misc_set_invalid) /* 43 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 44 cons  */
+         .quad local_label(misc_set_invalid) /* 45 imm_1  */
+         .quad local_label(misc_set_invalid) /* 46 immheader_1  */
+         .quad _SPgvset /* 47 pool  */
+         .quad local_label(misc_set_invalid) /* 48 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 49 imm_2  */
+         .quad local_label(misc_set_invalid) /* 4a immheader_2  */
+         .quad _SPgvset /* 4b value_cell_2  */
+         .quad local_label(misc_set_invalid) /* 4c misc  */
+         .quad local_label(misc_set_invalid) /* 4d imm3  */
+         .quad local_label(misc_set_invalid) /* 4e immheader_3  */
+         .quad local_label(misc_set_invalid) /* 4f nodeheader_3  */
+        /* 50-5f  */
+         .quad local_label(misc_set_invalid) /* 50 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 51 imm_0  */
+         .quad local_label(misc_set_invalid) /* 52 immheader_0  */
+         .quad local_label(misc_set_invalid) /* 53 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 54 cons  */
+         .quad local_label(misc_set_invalid) /* 55 imm_1  */
+         .quad local_label(misc_set_invalid) /* 56 immheader_1  */
+         .quad _SPgvset /* 57 weak  */
+         .quad local_label(misc_set_invalid) /* 58 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 59 imm_2  */
+         .quad local_label(misc_set_invalid) /* 5a immheader_2  */
+         .quad _SPgvset /* 5b xfunction  */
+         .quad local_label(misc_set_invalid) /* 5c misc  */
+         .quad local_label(misc_set_invalid) /* 5d imm3  */
+         .quad local_label(misc_set_invalid) /* 5e immheader_3  */
+         .quad local_label(misc_set_invalid) /* 5f nodeheader_3  */
+        /* 60-6f  */
+         .quad local_label(misc_set_invalid) /* 60 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 61 imm_0  */
+         .quad local_label(misc_set_invalid) /* 62 immheader_0  */
+         .quad local_label(misc_set_invalid) /* 63 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 64 cons  */
+         .quad local_label(misc_set_invalid) /* 65 imm_1  */
+         .quad local_label(misc_set_invalid) /* 66 immheader_1  */
+         .quad _SPgvset /* 67 package  */
+         .quad local_label(misc_set_invalid) /* 68 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 69 imm_2  */
+         .quad local_label(misc_set_invalid) /* 6a immheader_2  */
+         .quad local_label(misc_set_invalid) /* 6b nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* 6c misc  */
+         .quad local_label(misc_set_invalid) /* 6d imm3  */
+         .quad local_label(misc_set_invalid) /* 6e immheader_3  */
+         .quad local_label(misc_set_invalid) /* 6f nodeheader_3  */
+        /* 70-7f  */
+         .quad local_label(misc_set_invalid) /* 70 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 71 imm_0  */
+         .quad local_label(misc_set_invalid) /* 72 immheader_0  */
+         .quad local_label(misc_set_invalid) /* 73 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 74 cons  */
+         .quad local_label(misc_set_invalid) /* 75 imm_1  */
+         .quad local_label(misc_set_invalid) /* 76 immheader_1  */
+         .quad local_label(misc_set_invalid) /* 77 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* 78 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 79 imm_2  */
+         .quad local_label(misc_set_invalid) /* 7a immheader_2  */
+         .quad local_label(misc_set_invalid) /* 7b nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* 7c misc  */
+         .quad local_label(misc_set_invalid) /* 7d imm3  */
+         .quad local_label(misc_set_invalid) /* 7e immheader_3  */
+         .quad local_label(misc_set_invalid) /* 7f nodeheader_3  */
+        /* 80-8f  */
+         .quad local_label(misc_set_invalid) /* 80 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 81 imm_0  */
+         .quad local_label(misc_set_invalid) /* 82 immheader_0  */
+         .quad local_label(misc_set_invalid) /* 83 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 84 cons  */
+         .quad local_label(misc_set_invalid) /* 85 imm_1  */
+         .quad local_label(misc_set_invalid) /* 86 immheader_1  */
+         .quad _SPgvset /* 87 arrayH  */
+         .quad local_label(misc_set_invalid) /* 88 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 89 imm_2  */
+         .quad local_label(misc_set_invalid) /* 8a immheader_2  */
+         .quad _SPgvset /* 8b vectorH  */
+         .quad local_label(misc_set_invalid) /* 8c misc  */
+         .quad local_label(misc_set_invalid) /* 8d imm3  */
+         .quad local_label(misc_set_invalid) /* 8e immheader_3  */
+         .quad _SPgvset /* 8f simple_vector  */
+        /* 90-9f  */
+         .quad local_label(misc_set_invalid) /* 90 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* 91 imm_0  */
+         .quad local_label(misc_set_s8) /* 92 s8  */
+         .quad local_label(misc_set_invalid) /* 93 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* 94 cons  */
+         .quad local_label(misc_set_invalid) /* 95 imm_1  */
+         .quad local_label(misc_set_s16) /* 96 immheader_1  */
+         .quad local_label(misc_set_invalid) /* 97 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* 98 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* 99 imm_2  */
+         .quad local_label(misc_set_s32) /* 9a s32  */
+         .quad local_label(misc_set_invalid) /* 9b nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* 9c misc  */
+         .quad local_label(misc_set_invalid) /* 9d imm3  */
+         .quad local_label(misc_set_s64) /* 9e s64  */
+         .quad local_label(misc_set_invalid) /* 9f nodeheader_3  */
+        /* a0-af  */
+         .quad local_label(misc_set_invalid) /* a0 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* a1 imm_0  */
+         .quad local_label(misc_set_u8) /* a2 u8  */
+         .quad local_label(misc_set_invalid) /* a3 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* a4 cons  */
+         .quad local_label(misc_set_invalid) /* a5 imm_1  */
+         .quad local_label(misc_set_u16) /* a6 u16  */
+         .quad local_label(misc_set_invalid) /* a7 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* a8 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* a9 imm_2  */
+         .quad local_label(misc_set_u32) /* aa u32  */
+         .quad local_label(misc_set_invalid) /* ab nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* ac misc  */
+         .quad local_label(misc_set_invalid) /* ad imm3  */
+         .quad local_label(misc_set_u64) /* ae u64  */
+         .quad local_label(misc_set_invalid) /* af nodeheader_3  */
+        /* b0-bf  */
+         .quad local_label(misc_set_invalid) /* b0 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* b1 imm_0  */
+         .quad local_label(misc_set_invalid) /* b2 immheader_0  */
+         .quad local_label(misc_set_invalid) /* b3 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* b4 cons  */
+         .quad local_label(misc_set_invalid) /* b5 imm_1  */
+         .quad local_label(misc_set_invalid) /* b6 immheader_1  */
+         .quad local_label(misc_set_invalid) /* b7 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* b8 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* b9 imm_2  */
+         .quad local_label(misc_set_single_float_vector) /* ba sf vector  */
+         .quad local_label(misc_set_invalid) /* bb nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* bc misc  */
+         .quad local_label(misc_set_invalid) /* bd imm3  */
+         .quad local_label(misc_set_fixnum_vector) /* be fixnum_vector  */
+         .quad local_label(misc_set_invalid) /* bf nodeheader_3  */
+        /* c0-cf  */
+         .quad local_label(misc_set_invalid) /* c0 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* c1 imm_0  */
+         .quad local_label(misc_set_invalid) /* c2 immheader_0  */
+         .quad local_label(misc_set_invalid) /* c3 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* c4 cons  */
+         .quad local_label(misc_set_invalid) /* c5 imm_1  */
+         .quad local_label(misc_set_invalid) /* c6 immheader_1  */
+         .quad local_label(misc_set_invalid) /* c7 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* c8 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* c9 imm_2  */
+         .quad local_label(misc_set_invalid) /* ca immheader_2  */
+         .quad local_label(misc_set_invalid) /* cb nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* cc misc  */
+         .quad local_label(misc_set_invalid) /* cd imm3  */
+         .quad local_label(misc_set_double_float_vector) /* ce double-float vector  */
+         .quad local_label(misc_set_invalid) /* cf nodeheader_3  */
+        /* d0-df  */
+         .quad local_label(misc_set_invalid) /* d0 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* d1 imm_0  */
+         .quad local_label(misc_set_string) /* d2 string  */
+         .quad local_label(misc_set_invalid) /* d3 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* d4 cons  */
+         .quad local_label(misc_set_invalid) /* d5 imm_1  */
+         .quad local_label(misc_set_invalid) /* d6 immheader_1  */
+         .quad local_label(misc_set_invalid) /* d7 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* d8 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* d9 imm_2  */
+         .quad local_label(misc_set_new_string) /* da new_string  */
+         .quad local_label(misc_set_invalid) /* db nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* dc misc  */
+         .quad local_label(misc_set_invalid) /* dd imm3  */
+         .quad local_label(misc_set_invalid) /* de immheader_3  */
+         .quad local_label(misc_set_invalid) /* df nodeheader_3  */
+        /* e0-ef  */
+         .quad local_label(misc_set_invalid) /* e0 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* e1 imm_0  */
+         .quad local_label(misc_set_invalid) /* e2 immheader_0  */
+         .quad local_label(misc_set_invalid) /* e3 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* e4 cons  */
+         .quad local_label(misc_set_invalid) /* e5 imm_1  */
+         .quad local_label(misc_set_invalid) /* e6 immheader_1  */
+         .quad local_label(misc_set_invalid) /* e7 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* e8 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* e9 imm_2  */
+         .quad local_label(misc_set_invalid) /* ea immheader_2  */
+         .quad local_label(misc_set_invalid) /* eb nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* ec misc  */
+         .quad local_label(misc_set_invalid) /* ed imm3  */
+         .quad local_label(misc_set_invalid) /* ee immheader_3  */
+         .quad local_label(misc_set_invalid) /* ef nodeheader_3  */
+        /* f0-ff  */
+         .quad local_label(misc_set_invalid) /* f0 even_fixnum  */
+         .quad local_label(misc_set_invalid) /* f1 imm_0  */
+         .quad local_label(misc_set_invalid) /* f2 immheader_0  */
+         .quad local_label(misc_set_invalid) /* f3 nodeheader_0  */
+         .quad local_label(misc_set_invalid) /* f4 cons  */
+         .quad local_label(misc_set_invalid) /* f5 imm_1  */
+         .quad local_label(misc_set_bit_vector) /* f6 bit_vector  */
+         .quad local_label(misc_set_invalid) /* f7 nodeheader_1  */
+         .quad local_label(misc_set_invalid) /* f8 odd_fixnum  */
+         .quad local_label(misc_set_invalid) /* f9 imm_2  */
+         .quad local_label(misc_set_invalid) /* fa immheader_2  */
+         .quad local_label(misc_set_invalid) /* fb nodeheader_2  */
+         .quad local_label(misc_set_invalid) /* fc misc  */
+         .quad local_label(misc_set_invalid) /* fd imm3  */
+         .quad local_label(misc_set_invalid) /* fe immheader_3  */
+         .quad local_label(misc_set_invalid) /* ff nodeheader_3  */
+
+local_label(misc_set_bit_vector):               
+         __(lis imm3,0x8000)
+         __(extract_unsigned_byte_bits_(imm0,arg_z,1))
+	 __(extrwi imm1,arg_y,5,32-(fixnumshift+5))	/* imm1 = bitnum  */
+         __(srdi imm0,arg_y,5+fixnumshift)
+	 __(srw imm3,imm3,imm1)
+         __(bne local_label(misc_set_bad))
+         __(cmpdi cr0,arg_z,0)
+         __(sldi imm0,imm0,2)
+	 __(la imm0,misc_data_offset(imm0))
+	 __(lwzx imm2,arg_x,imm0)
+         __(beq 1f)
+         __(or imm2,imm3,imm2)
+         __(stwx imm2,arg_x,imm0)
+         __(blr)
+1:       __(andc imm2,imm2,imm3)
+         __(stwx imm2,arg_x,imm0)
+         __(blr)
+local_label(misc_set_s16):
+         __(extract_lisptag(imm2,arg_z))
+         __(sldi imm0,arg_z,64-(16+fixnumshift))
+         __(srdi imm1,arg_y,2)
+         __(cmpdi cr7,imm2,tag_fixnum)
+         __(sradi imm0,imm0,64-(16+fixnumshift))
+         __(cmpd imm0,arg_z)
+         __(la imm1,misc_data_offset(imm1))
+         __(unbox_fixnum(imm0,arg_z))
+         __(bne local_label(misc_set_bad))
+         __(bne cr7,local_label(misc_set_bad))
+         __(sthx imm0,arg_x,imm1)
+         __(blr)
+local_label(misc_set_u16):
+         __(extract_unsigned_byte_bits_(imm0,arg_z,16))
+         __(srdi imm1,arg_y,2)                
+         __(unbox_fixnum(imm0,arg_z))
+         __(la imm1,misc_data_offset(imm1))
+         __(bne local_label(misc_set_bad))
+         __(sthx imm0,arg_x,imm1)
+         __(blr)
+local_label(misc_set_single_float_vector):
+         __(extract_fulltag(imm3,arg_z))
+         __(srdi imm4,arg_y,1)
+         __(cmpdi cr3,imm3,subtag_single_float)
+         __(la imm4,misc_data_offset(imm4))
+         __(bne cr3,local_label(misc_set_bad))
+         __(srdi imm0,arg_z,32)
+         __(stwx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_s32):
+         __(extract_lisptag(imm2,arg_z))
+         __(srdi imm4,arg_y,1)
+         __(unbox_fixnum(imm0,arg_z))
+         __(cmpdi imm2,tag_fixnum)
+         __(sldi imm1,imm0,32)
+         __(sradi imm1,imm1,32)
+         __(la imm4,misc_data_offset(imm4))
+         __(bne local_label(misc_set_bad))
+         __(cmpd imm1,imm0)
+         __(bne local_label(misc_set_bad))
+         __(stwx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_u32):              
+         __(extract_unsigned_byte_bits_(imm0,arg_z,32))
+         __(srdi imm4,arg_y,1)
+	 __(la imm4,misc_data_offset(imm4))
+         __(unbox_fixnum(imm0,arg_z))
+         __(bne local_label(misc_set_bad))
+         __(stwx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_new_string):
+         __(extract_lowbyte(imm0,arg_z))
+         __(srdi imm4,arg_y,1)
+         __(cmpdi imm0,subtag_character)
+	 __(la imm4,misc_data_offset(imm4))
+         __(srwi imm0,arg_z,charcode_shift)
+         __(bne local_label(misc_set_bad))
+         __(stwx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_string):      
+         __(extract_lowbyte(imm0,arg_z))                
+         __(srdi imm4,arg_y,3)
+         __(cmpdi imm0,subtag_character)
+         __(la imm4,misc_data_offset(imm4))
+         __(bne cr0,local_label(misc_set_bad))
+         __(srwi imm0,arg_z,charcode_shift)
+         __(stbx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_s8):     
+         __(extract_lisptag(imm2,arg_z))
+         __(unbox_fixnum(imm0,arg_z))
+         __(cmpdi cr2,imm2,tag_fixnum)
+         __(srdi imm4,arg_y,3)
+         __(sldi imm1,imm0,56)
+         __(sradi imm1,imm1,56)
+         __(cmpd imm1,imm0)
+         __(bne cr2,local_label(misc_set_bad))
+         __(la imm4,misc_data_offset(imm4))
+         __(bne local_label(misc_set_bad))
+         __(stbx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_u8):     
+         __(extract_unsigned_byte_bits_(imm0,arg_z,8))
+         __(srdi imm4,arg_y,3)
+         __(unbox_fixnum(imm0,arg_z))
+         __(la imm4,misc_data_offset(imm4))
+         __(bne local_label(misc_set_bad))
+         __(stbx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_u64):
+         __(extract_lisptag(imm0,arg_z))
+         __(extract_fulltag(imm2,arg_z))
+         __(cmpdi cr0,arg_z,0)
+         __(cmpdi cr7,imm0,0)
+         __(cmpdi cr6,imm2,fulltag_misc)
+         __(la imm4,misc_data_offset(arg_y))
+         __(bne cr7,local_label(setu64_maybe_bignum))
+         __(unbox_fixnum(imm0,arg_z))
+         __(blt cr0,local_label(misc_set_bad))
+         __(stdx imm0,arg_x,imm4)
+         __(blr)
+local_label(setu64_maybe_bignum):
+         __(bne cr6,local_label(misc_set_bad))
+         __(getvheader(imm1,arg_z))
+         __(ld imm0,misc_data_offset(arg_z))
+         __(rotldi imm0,imm0,32)
+         __(cmpdi cr2,imm1,two_digit_bignum_header)
+         __(cmpdi cr3,imm1,three_digit_bignum_header)
+         __(cmpdi cr0,imm0,0)
+         __(beq cr2,1f)
+         __(bne cr3,local_label(misc_set_bad))
+         __(lwz imm3,misc_data_offset+8(arg_z))
+         __(cmpwi cr0,imm3,0)
+         __(bne cr0,local_label(misc_set_bad))
+         __(stdx imm0,arg_x,imm4)
+         __(blr)
+1:       __(blt cr0,local_label(misc_set_bad))
+         __(stdx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_double_float_vector):
+         __(extract_typecode(imm0,arg_z))
+         __(la imm4,misc_data_offset(arg_y))
+         __(cmpdi imm0,subtag_double_float)
+         __(bne local_label(misc_set_bad))
+         __(ld imm0,misc_dfloat_offset(arg_z))
+         __(stdx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_fixnum_vector):
+         __(extract_lisptag(imm2,arg_z))
+         __(unbox_fixnum(imm0,arg_z))
+         __(cmpdi cr2,imm2,tag_fixnum)
+         __(la imm4,misc_data_offset(arg_y))
+         __(bne cr2,local_label(misc_set_bad))
+         __(stdx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_s64):
+         __(extract_lisptag(imm2,arg_z))
+         __(extract_fulltag(imm3,arg_z))
+         __(unbox_fixnum(imm0,arg_z))
+         __(cmpdi cr2,imm2,tag_fixnum)
+         __(cmpdi cr6,imm3,fulltag_misc) 
+         __(la imm4,misc_data_offset(arg_y))
+         __(bne cr2,local_label(sets64_maybe_bignum))
+         __(stdx imm0,arg_x,imm4)
+         __(blr)
+local_label(sets64_maybe_bignum):       
+         __(bne cr6,local_label(misc_set_bad))
+         __(getvheader(imm1,arg_z))
+         __(ld imm0,misc_data_offset(arg_z))
+         __(cmpdi cr1,imm1,two_digit_bignum_header)
+         __(rotldi imm0,imm0,32)
+         __(bne cr1,local_label(misc_set_bad))
+         __(stdx imm0,arg_x,imm4)
+         __(blr)
+local_label(misc_set_bad):
+	 __(mr arg_y,arg_z)
+	 __(mr arg_z,arg_x)
+	 __(li arg_x,XNOTELT)
+	 __(set_nargs(3))
+	 __(b _SPksignalerr)
+local_label(misc_set_invalid):  
+         __(li temp0,XSETBADVEC)        
+         __(set_nargs(4))
+         __(vpush(temp0))
+         __(b _SPksignalerr)        
+        __else
+         __(slwi imm1,imm1,2)
+         __(li imm0,LO(local_label(misc_set_jmp)))
+         __(addis imm0,imm0,HA(local_label(misc_set_jmp)))
+         __(lwzx imm0,imm0,imm1)
+         __(mtctr imm0)
+         __(bctr)
+local_label(misc_set_jmp):             
+        /* 00-0f  */
+         .long local_label(misc_set_invalid) /* 00 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 01 cons  */
+         .long local_label(misc_set_invalid) /* 02 nodeheader  */
+         .long local_label(misc_set_invalid) /* 03 imm  */
+         .long local_label(misc_set_invalid) /* 04 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 05 nil  */
+         .long local_label(misc_set_invalid) /* 06 misc  */
+         .long local_label(misc_set_u32) /* 07 bignum  */
+         .long local_label(misc_set_invalid) /* 08 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 09 cons  */
+         .long _SPgvset /* 0a ratio  */
+         .long local_label(misc_set_invalid) /* 0b imm  */
+         .long local_label(misc_set_invalid) /* 0c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 0d nil  */
+         .long local_label(misc_set_invalid) /* 0e misc  */
+         .long local_label(misc_set_u32) /* 0f single_float  */
+        /* 10-1f  */
+         .long local_label(misc_set_invalid) /* 10 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 11 cons  */
+         .long local_label(misc_set_invalid) /* 12 nodeheader  */
+         .long local_label(misc_set_invalid) /* 13 imm  */
+         .long local_label(misc_set_invalid) /* 14 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 15 nil  */
+         .long local_label(misc_set_invalid) /* 16 misc  */
+         .long local_label(misc_set_u32) /* 17 double_float  */
+         .long local_label(misc_set_invalid) /* 18 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 19 cons  */
+         .long _SPgvset /* 1a complex  */
+         .long local_label(misc_set_invalid) /* 1b imm  */
+         .long local_label(misc_set_invalid) /* 1c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 1d nil  */
+         .long local_label(misc_set_invalid) /* 1e misc  */
+         .long local_label(misc_set_u32) /* 1f macptr  */
+        /* 20-2f  */
+         .long local_label(misc_set_invalid) /* 20 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 21 cons  */
+         .long _SPgvset /* 22 catch_frame  */
+         .long local_label(misc_set_invalid) /* 23 imm  */
+         .long local_label(misc_set_invalid) /* 24 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 25 nil  */
+         .long local_label(misc_set_invalid) /* 26 misc  */
+         .long local_label(misc_set_u32) /* 27 dead_macptr  */
+         .long local_label(misc_set_invalid) /* 28 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 29 cons  */
+         .long _SPgvset /* 2a function  */
+         .long local_label(misc_set_invalid) /* 2b imm  */
+         .long local_label(misc_set_invalid) /* 2c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 2d nil  */
+         .long local_label(misc_set_invalid) /* 2e misc  */
+         .long local_label(misc_set_u32) /* 2f code_vector  */
+        /* 30-3f  */
+         .long local_label(misc_set_invalid) /* 30 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 31 cons  */
+         .long _SPgvset /* 32 lisp_thread  */
+         .long local_label(misc_set_invalid) /* 33 imm  */
+         .long local_label(misc_set_invalid) /* 34 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 35 nil  */
+         .long local_label(misc_set_invalid) /* 36 misc  */
+         .long local_label(misc_set_u32) /* 37 creole  */
+         .long local_label(misc_set_invalid) /* 38 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 39 cons  */
+         .long _SPgvset /* 3a symbol  */
+         .long local_label(misc_set_invalid) /* 3b imm  */
+         .long local_label(misc_set_invalid) /* 3c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 3d nil  */
+         .long local_label(misc_set_invalid) /* 3e misc  */
+         .long local_label(misc_set_u32) /* 3f xcode_vector  */
+        /* 40-4f  */
+         .long local_label(misc_set_invalid) /* 40 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 41 cons  */
+         .long _SPgvset /* 42 lock  */
+         .long local_label(misc_set_invalid) /* 43 imm  */
+         .long local_label(misc_set_invalid) /* 44 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 45 nil  */
+         .long local_label(misc_set_invalid) /* 46 misc  */
+         .long local_label(misc_set_invalid) /* 47 immheader  */
+         .long local_label(misc_set_invalid) /* 48 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 49 cons  */
+         .long _SPgvset /* 4a hash_vector  */
+         .long local_label(misc_set_invalid) /* 4b imm  */
+         .long local_label(misc_set_invalid) /* 4c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 4d nil  */
+         .long local_label(misc_set_invalid) /* 4e misc  */
+         .long local_label(misc_set_invalid) /* 4f immheader  */
+        /* 50-5f  */
+         .long local_label(misc_set_invalid) /* 50 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 51 cons  */
+         .long _SPgvset /* 52 pool  */
+         .long local_label(misc_set_invalid) /* 53 imm  */
+         .long local_label(misc_set_invalid) /* 54 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 55 nil  */
+         .long local_label(misc_set_invalid) /* 56 misc  */
+         .long local_label(misc_set_invalid) /* 57 immheader  */
+         .long local_label(misc_set_invalid) /* 58 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 59 cons  */
+         .long _SPgvset /* 5a weak  */
+         .long local_label(misc_set_invalid) /* 5b imm  */
+         .long local_label(misc_set_invalid) /* 5c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 5d nil  */
+         .long local_label(misc_set_invalid) /* 5e misc  */
+         .long local_label(misc_set_invalid) /* 5f immheader  */
+        /* 60-6f  */
+         .long local_label(misc_set_invalid) /* 60 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 61 cons  */
+         .long _SPgvset /* 62 package  */
+         .long local_label(misc_set_invalid) /* 63 imm  */
+         .long local_label(misc_set_invalid) /* 64 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 65 nil  */
+         .long local_label(misc_set_invalid) /* 66 misc  */
+         .long local_label(misc_set_invalid) /* 67 immheader  */
+         .long local_label(misc_set_invalid) /* 68 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 69 cons  */
+         .long _SPgvset /* 6a slot_vector  */
+         .long local_label(misc_set_invalid) /* 6b imm  */
+         .long local_label(misc_set_invalid) /* 6c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 6d nil  */
+         .long local_label(misc_set_invalid) /* 6e misc  */
+         .long local_label(misc_set_invalid) /* 6f immheader  */
+        /* 70-7f  */
+         .long local_label(misc_set_invalid) /* 70 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 71 cons  */
+         .long _SPgvset /* 72 instance  */
+         .long local_label(misc_set_invalid) /* 73 imm  */
+         .long local_label(misc_set_invalid) /* 74 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 75 nil  */
+         .long local_label(misc_set_invalid) /* 76 misc  */
+         .long local_label(misc_set_invalid) /* 77 immheader  */
+         .long local_label(misc_set_invalid) /* 78 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 79 cons  */
+         .long _SPgvset /* 7a struct  */
+         .long local_label(misc_set_invalid) /* 7b imm  */
+         .long local_label(misc_set_invalid) /* 7c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 7d nil  */
+         .long local_label(misc_set_invalid) /* 7e misc  */
+         .long local_label(misc_set_invalid) /* 7f immheader  */
+        /* 80-8f  */
+         .long local_label(misc_set_invalid) /* 80 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 81 cons  */
+         .long _SPgvset /* 82 istruct  */
+         .long local_label(misc_set_invalid) /* 83 imm  */
+         .long local_label(misc_set_invalid) /* 84 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 85 nil  */
+         .long local_label(misc_set_invalid) /* 86 misc  */
+         .long local_label(misc_set_invalid) /* 87 immheader  */
+         .long local_label(misc_set_invalid) /* 88 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 89 cons  */
+         .long _SPgvset /* 8a value_cell  */
+         .long local_label(misc_set_invalid) /* 8b imm  */
+         .long local_label(misc_set_invalid) /* 8c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 8d nil  */
+         .long local_label(misc_set_invalid) /* 8e misc  */
+         .long local_label(misc_set_invalid) /* 8f immheader  */
+        /* 90-9f  */
+         .long local_label(misc_set_invalid) /* 90 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 91 cons  */
+         .long _SPgvset /* 92 xfunction  */
+         .long local_label(misc_set_invalid) /* 93 imm  */
+         .long local_label(misc_set_invalid) /* 94 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 95 nil  */
+         .long local_label(misc_set_invalid) /* 96 misc  */
+         .long local_label(misc_set_invalid) /* 97 immheader  */
+         .long local_label(misc_set_invalid) /* 98 even_fixnum  */
+         .long local_label(misc_set_invalid) /* 99 cons  */
+         .long _SPgvset /* 9a arrayH  */
+         .long local_label(misc_set_invalid) /* 9b imm  */
+         .long local_label(misc_set_invalid) /* 9c odd_fixnum  */
+         .long local_label(misc_set_invalid) /* 9d nil  */
+         .long local_label(misc_set_invalid) /* 9e misc  */
+         .long local_label(misc_set_invalid) /* 9f immheader  */
+        /* a0-af  */
+         .long local_label(misc_set_invalid) /* a0 even_fixnum  */
+         .long local_label(misc_set_invalid) /* a1 cons  */
+         .long _SPgvset /* a2 vectorH  */
+         .long local_label(misc_set_invalid) /* a3 imm  */
+         .long local_label(misc_set_invalid) /* a4 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* a5 nil  */
+         .long local_label(misc_set_invalid) /* a6 misc  */
+         .long local_label(misc_set_single_float_vector) /* a7 sf vector  */
+         .long local_label(misc_set_invalid) /* a8 even_fixnum  */
+         .long local_label(misc_set_invalid) /* a9 cons  */
+         .long _SPgvset /* aa vectorH  */
+         .long local_label(misc_set_invalid) /* ab imm  */
+         .long local_label(misc_set_invalid) /* ac odd_fixnum  */
+         .long local_label(misc_set_invalid) /* ad nil  */
+         .long local_label(misc_set_invalid) /* ae misc  */
+         .long local_label(misc_set_u32) /* af u32  */
+        /* b0-bf  */
+         .long local_label(misc_set_invalid) /* b0 even_fixnum  */
+         .long local_label(misc_set_invalid) /* b1 cons  */
+         .long local_label(misc_set_invalid) /* b2 node  */
+         .long local_label(misc_set_invalid) /* b3 imm  */
+         .long local_label(misc_set_invalid) /* b4 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* b5 nil  */
+         .long local_label(misc_set_invalid) /* b6 misc  */
+         .long local_label(misc_set_s32) /* b7 s32  */
+         .long local_label(misc_set_invalid) /* b8 even_fixnum  */
+         .long local_label(misc_set_invalid) /* b9 cons  */
+         .long local_label(misc_set_invalid) /* ba nodeheader  */
+         .long local_label(misc_set_invalid) /* bb imm  */
+         .long local_label(misc_set_invalid) /* bc odd_fixnum  */
+         .long local_label(misc_set_invalid) /* bd nil  */
+         .long local_label(misc_set_invalid) /* be misc  */
+         .long local_label(misc_set_fixnum_vector) /* bf fixnum_vector  */
+        /* c0-cf  */
+         .long local_label(misc_set_invalid) /* c0 even_fixnum  */
+         .long local_label(misc_set_invalid) /* c1 cons  */
+         .long local_label(misc_set_invalid) /* c2 nodeheader  */
+         .long local_label(misc_set_invalid) /* c3 imm  */
+         .long local_label(misc_set_invalid) /* c4 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* c5 nil  */
+         .long local_label(misc_set_invalid) /* c6 misc  */
+         .long local_label(misc_set_new_string) /* c7 new_string  */
+         .long local_label(misc_set_invalid) /* c8 even_fixnum  */
+         .long local_label(misc_set_invalid) /* c9 cons  */
+         .long local_label(misc_set_invalid) /* ca nodeheader  */
+         .long local_label(misc_set_invalid) /* cb imm  */
+         .long local_label(misc_set_invalid) /* cc odd_fixnum  */
+         .long local_label(misc_set_invalid) /* cd nil  */
+         .long local_label(misc_set_invalid) /* ce misc  */
+         .long local_label(misc_set_u8) /* cf u8  */
+        /* d0-df  */
+         .long local_label(misc_set_invalid) /* d0 even_fixnum  */
+         .long local_label(misc_set_invalid) /* d1 cons  */
+         .long local_label(misc_set_invalid) /* d2 nodeheader  */
+         .long local_label(misc_set_invalid) /* d3 imm  */
+         .long local_label(misc_set_invalid) /* d4 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* d5 nil  */
+         .long local_label(misc_set_invalid) /* d6 misc  */
+         .long local_label(misc_set_s8) /* d7 s8  */
+         .long local_label(misc_set_invalid) /* d8 even_fixnum  */
+         .long local_label(misc_set_invalid) /* d9 cons  */
+         .long local_label(misc_set_invalid) /* da nodeheader  */
+         .long local_label(misc_set_invalid) /* db imm  */
+         .long local_label(misc_set_invalid) /* dc odd_fixnum  */
+         .long local_label(misc_set_invalid) /* dd nil  */
+         .long local_label(misc_set_invalid) /* de misc  */
+         .long local_label(misc_set_old_string) /* df (old) simple_base_string  */
+        /* e0-ef  */
+         .long local_label(misc_set_invalid) /* e0 even_fixnum  */
+         .long local_label(misc_set_invalid) /* e1 cons  */
+         .long local_label(misc_set_invalid) /* e2 nodeheader  */
+         .long local_label(misc_set_invalid) /* e3 imm  */
+         .long local_label(misc_set_invalid) /* e4 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* e5 nil  */
+         .long local_label(misc_set_invalid) /* e6 misc  */
+         .long local_label(misc_set_u16) /* e7 u16  */
+         .long local_label(misc_set_invalid) /* e8 even_fixnum  */
+         .long local_label(misc_set_invalid) /* e9 cons  */
+         .long local_label(misc_set_invalid) /* ea nodeheader  */
+         .long local_label(misc_set_invalid) /* eb imm  */
+         .long local_label(misc_set_invalid) /* ec odd_fixnum  */
+         .long local_label(misc_set_invalid) /* ed nil  */
+         .long local_label(misc_set_invalid) /* ee misc  */
+         .long local_label(misc_set_s16) /* ef s16  */
+        /* f0-ff  */
+         .long local_label(misc_set_invalid) /* f0 even_fixnum  */
+         .long local_label(misc_set_invalid) /* f1 cons  */
+         .long local_label(misc_set_invalid) /* f2 nodeheader  */
+         .long local_label(misc_set_invalid) /* f3 imm  */
+         .long local_label(misc_set_invalid) /* f4 odd_fixnum  */
+         .long local_label(misc_set_invalid) /* f5 nil  */
+         .long local_label(misc_set_invalid) /* f6 misc  */
+         .long local_label(misc_set_double_float_vector) /* f7 df vector  */
+         .long local_label(misc_set_invalid) /* f8 even_fixnum  */
+         .long local_label(misc_set_invalid) /* f9 cons  */
+         .long local_label(misc_set_invalid) /* fa nodeheader  */
+         .long local_label(misc_set_invalid) /* fb imm  */
+         .long local_label(misc_set_invalid) /* fc odd_fixnum  */
+         .long local_label(misc_set_invalid) /* fd nil  */
+         .long local_label(misc_set_invalid) /* fe misc  */
+         .long local_label(misc_set_bit_vector) /* ff bit_vector  */
+
+local_label(misc_set_u32):        
+	/* Either a non-negative fixnum, a positiveone-digit bignum, */
+	/* or a two-digit bignum whose sign-digit is 0 is ok.  */
+	 __(extract_lisptag(imm2,arg_z))
+	 __(srawi. imm1,arg_z,fixnum_shift)
+         __(cmpwi cr5,imm2,tag_fixnum)         
+         __(la imm0,misc_data_offset(arg_y))
+         __(cmpwi cr7,imm2,tag_misc)
+	 __(bne cr5,local_label(set_not_fixnum_u32))
+	 __(blt- cr0,local_label(set_bad))
+local_label(set_set32):         
+	 __(stwx imm1,arg_x,imm0)
+	 __(blr)
+local_label(set_not_fixnum_u32):
+	 __(bne cr7,local_label(set_bad))
+	 __(extract_header(imm2,arg_z))
+	 __(cmpri(cr0,imm2,one_digit_bignum_header))
+	 __(cmpri(cr1,imm2,two_digit_bignum_header))
+	 __(vrefr(imm1,arg_z,0))
+	 __(cmpri(cr2,imm1,0))
+	 __(bne cr0,local_label(set_not_1_digit_u32))
+	 __(bge cr2,local_label(set_set32))
+	 __(b local_label(set_bad))
+local_label(set_not_1_digit_u32):
+	 __(bne- cr1,local_label(set_bad))
+	 __(vrefr(imm2,arg_z,1))
+	 __(cmpri(cr0,imm2,0))
+	 __(bne- cr1,local_label(set_bad))
+	 __(beq cr0,local_label(set_set32))
+local_label(set_bad):
+	/* arg_z does not match the array-element-type of arg_x.  */
+	 __(mr arg_y,arg_z)
+	 __(mr arg_z,arg_x)
+	 __(li arg_x,XNOTELT)
+	 __(set_nargs(3))
+	 __(b _SPksignalerr)
+local_label(misc_set_fixnum_vector):   
+         __(extract_lisptag(imm2,arg_z))
+         __(la imm0,misc_data_offset(arg_y))
+         __(cmpwi cr5,imm2,tag_fixnum)
+         __(unbox_fixnum(imm1,arg_z))
+         __(bne cr5,local_label(set_bad))
+         __(stwx imm1,arg_x,imm0)
+         __(blr)
+local_label(misc_set_new_string):   
+         __(clrlwi imm2,arg_z,ncharcodebits)
+         __(la imm0,misc_data_offset(arg_y))
+         __(cmpwi cr5,imm2,subtag_character)
+         __(srwi imm1,arg_z,charcode_shift)
+         __(bne cr5,local_label(set_bad))
+         __(stwx imm1,arg_x,imm0)
+         __(blr)
+local_label(misc_set_s32):
+         __(extract_lisptag(imm2,arg_z))
+         __(cmpwi cr5,imm2,tag_fixnum)
+         __(cmpwi cr7,imm2,tag_misc)
+         __(la imm0,misc_data_offset(arg_y))
+	 __(unbox_fixnum(imm1,arg_z))
+	 __(beq cr5,local_label(set_set32))
+	 __(bne cr7,local_label(set_bad))
+	 __(extract_header(imm2,arg_z))
+	 __(cmpri(cr0,imm2,one_digit_bignum_header))
+	 __(vrefr(imm1,arg_z,0))
+	 __(bne- cr0,local_label(set_bad))
+	 __(strx(imm1,arg_x,imm0))
+	 __(blr)
+local_label(misc_set_single_float_vector):
+         __(extract_lisptag(imm2,arg_z))
+         __(cmpwi cr7,imm2,tag_misc)
+         __(la imm0,misc_data_offset(arg_y))
+	 __(bne- cr7,local_label(set_bad))
+	 __(extract_header(imm2,arg_z))
+	 __(cmpri(cr0,imm2,single_float_header))
+	 __(bne- cr0,local_label(set_bad))
+	 __(ldr(imm1,single_float.value(arg_z)))
+	 __(strx(imm1,arg_x,imm0))
+	 __(blr)
+local_label(misc_set_u8):               
+	 __(extract_lisptag(imm2,arg_z))
+	 __(srwi imm0,arg_y,2)
+	 __(la imm0,misc_data_offset(imm0))
+	 __(extract_unsigned_byte_bits_(imm1,arg_z,8))
+	 __(unbox_fixnum(imm1,arg_z))
+	 __(bne- cr0,local_label(set_bad))
+	 __(stbx imm1,arg_x,imm0)
+	 __(blr)
+local_label(misc_set_old_string):
+	 __(srwi imm0,arg_y,2)
+	 __(extract_lowbyte(imm2,arg_z))
+	 __(cmpri(cr2,imm2,subtag_character))
+	 __(la imm0,misc_data_offset(imm0))
+	 __(srwi imm1,arg_z,charcode_shift)
+	 __(bne- cr2,local_label(set_bad))
+	 __(stbx imm1,arg_x,imm0)
+	 __(blr)
+local_label(misc_set_s8):
+	 __(extract_lisptag(imm2,arg_z))
+         __(srwi imm0,arg_y,2)
+	 __(unbox_fixnum(imm1,arg_z))
+         __(la imm0,misc_data_offset(imm0))
+         __(cmpwi cr5,imm2,tag_fixnum)
+	 __(extsb imm2,imm1)
+	 __(cmpw cr0,imm2,imm1)
+	 __(bne- cr5,local_label(set_bad))
+	 __(bne- cr0,local_label(set_bad))
+	 __(stbx imm1,arg_x,imm0)
+	 __(blr)
+local_label(misc_set_u16):         
+	 __(srwi imm0,arg_y,1)
+	 __(extract_unsigned_byte_bits_(imm1,arg_z,16))
+	 __(unbox_fixnum(imm1,arg_z))
+	 __(la imm0,misc_data_offset(imm0))
+	 __(bne- cr0,local_label(set_bad))
+	 __(sthx imm1,arg_x,imm0)
+	 __(blr)
+local_label(misc_set_s16):
+         __(extract_lisptag(imm2,arg_z))
+         __(srwi imm0,arg_y,1)
+	 __(unbox_fixnum(imm1,arg_z))
+         __(cmpwi cr5,imm2,tag_fixnum)
+         __(la imm0,misc_data_offset(imm0))
+	 __(extsh imm2,imm1)
+	 __(cmpw cr0,imm2,imm1)
+	 __(bne- cr5,local_label(set_bad))
+	 __(bne- cr0,local_label(set_bad))
+	 __(sthx imm1,arg_x,imm0)
+	 __(blr)
+local_label(misc_set_bit_vector):	
+	 __(cmplwi cr2,arg_z,fixnumone)   /* nothing not a (boxed) bit   */
+	 __(extrwi imm1,arg_y,5,32-(fixnumshift+5))	/* imm1 = bitnum  */
+	 __(extlwi imm2,arg_z,1,31-fixnumshift)
+	 __(srw imm2,imm2,imm1)
+	 __(lis imm3,0x8000)
+	 __(rlwinm imm0,arg_y,32-5,5,31-fixnumshift)
+	 __(la imm0,misc_data_offset(imm0))
+	 __(srw imm3,imm3,imm1)
+	 __(bgt- cr2,local_label(set_bad))
+	 __(lwzx imm1,arg_x,imm0)
+	 __(andc imm1,imm1,imm3)
+	 __(or imm1,imm1,imm2)
+	 __(stwx imm1,arg_x,imm0)
+	 __(blr)
+
+local_label(misc_set_double_float_vector):
+         __(extract_lisptag(imm2,arg_z))
+	 __(slwi imm0,arg_y,1)
+         __(cmpwi cr7,imm2,tag_misc)
+	 __(la imm0,misc_dfloat_offset(imm0))
+         __(bne- cr7,local_label(set_bad))
+	 __(extract_header(imm2,arg_z))
+	 __(cmpri(cr0,imm2,double_float_header))
+	 __(bne- cr0,local_label(set_bad))
+	 __(lwz imm1,double_float.value(arg_z))
+	 __(lwz imm2,double_float.value+4(arg_z))
+	 __(stwx imm1,arg_x,imm0)
+	 __(la imm0,4(imm0))
+	 __(stwx imm2,arg_x,imm0)
+	 __(blr)
+local_label(misc_set_invalid):  
+         __(li temp0,XSETBADVEC)        
+         __(set_nargs(4))
+         __(vpush(temp0))
+         __(b _SPksignalerr)                
+        __endif
+
+/* misc_set (vector index newval).  Pretty damned similar to  */
+/* misc_ref, as one might imagine.  */
+
+_spentry(misc_set)
+	__(trap_unless_fulltag_equal(arg_x,fulltag_misc,imm0))
+	__(trap_unless_lisptag_equal(arg_y,tag_fixnum,imm0))
+	__(vector_length(imm0,arg_x,imm1))
+	__(trlge(arg_y,imm0))
+	__(extract_lowbyte(imm1,imm1))
+        __(b local_label(misc_set_common))
+        
+/* "spread" the lexpr in arg_z.  */
+/* ppc2-invoke-fn assumes that temp1 is preserved here.  */
+_spentry(spread_lexprz)
+	__(ldr(imm0,0(arg_z)))
+	__(cmpri(cr3,imm0,3<<fixnumshift))
+	__(cmpri(cr4,imm0,2<<fixnumshift))
+	__(add imm1,arg_z,imm0)
+	__(cmpri(cr0,imm0,0))
+	__(add nargs,nargs,imm0)
+	__(cmpri(cr1,nargs,0))
+	__(cmpri(cr2,nargs,2<<fixnumshift))
+	__(la imm1,node_size(imm1))
+	__(bge cr3,9f)
+	__(beq cr4,2f)
+	__(bne cr0,1f)
+	/* lexpr count was 0; vpop the arg regs that  */
+	/* were vpushed by the caller  */
+	__(beqlr cr1)
+	__(vpop(arg_z))
+	__(bltlr cr2)
+	__(vpop(arg_y))
+	__(beqlr cr2)
+	__(vpop(arg_x))
+	__(blr)
+
+	/* vpush args from the lexpr until we have only  */
+	/* three left, then assign them to arg_x, arg_y,  */
+	/* and arg_z.  */
+8:
+	__(cmpri(cr3,imm0,4<<fixnumshift))
+	__(subi imm0,imm0,fixnumone)
+	__(ldru(arg_z,-node_size(imm1)))
+	__(vpush(arg_z))
+9:
+	__(bne cr3,8b)
+	__(ldr(arg_x,-node_size*1(imm1)))
+	__(ldr(arg_y,-node_size*2(imm1)))
+	__(ldr(arg_z,-node_size*3(imm1)))
+	__(blr)
+
+	/* lexpr count is two: set arg_y, arg_z from the  */
+	/* lexpr, maybe vpop arg_x  */
+2:	
+	__(ldr(arg_y,-node_size*1(imm1)))
+	__(ldr(arg_z,-node_size*2(imm1)))
+	__(beqlr cr2)		/* return if (new) nargs = 2  */
+	__(vpop(arg_x))
+	__(blr)
+
+	/* lexpr count is one: set arg_z from the lexpr,  */
+	/* maybe vpop arg_y, arg_x  */
+1:	
+	__(ldr(arg_z,-node_size(imm1)))
+	__(bltlr cr2)		/* return if (new) nargs < 2  */
+	__(vpop(arg_y))
+	__(beqlr cr2)		/* return if (new) nargs = 2  */
+	__(vpop(arg_x))
+	__(blr)
+        
+		
+_spentry(reset)
+	.globl _SPthrow
+	__(nop)
+	__(ref_nrs_value(temp0,toplcatch))
+	__(li temp1,XSTKOVER)
+	__(vpush(temp0))
+	__(vpush(temp1))
+	__(set_nargs(1))
+	__(b _SPthrow)
+
+	
+/* "slide" nargs worth of values up the vstack.  IMM0 contains  */
+/* the difference between the current VSP and the target.  */
+_spentry(mvslide)
+	__(cmpri(cr0,nargs,0))
+	__(mr imm3,nargs)
+	__(add imm2,vsp,nargs)
+	__(add imm2,imm2,imm0)
+	__(add imm0,vsp,nargs)
+	__(beq 2f)
+1:
+	__(cmpri(cr0,imm3,1<<fixnumshift))
+	__(subi imm3,imm3,1<<fixnumshift)
+	__(ldru(temp0,-node_size(imm0)))
+	__(stru(temp0,-node_size(imm2)))
+	__(bne cr0,1b)
+2:
+	__(mr vsp,imm2)
+	__(blr)
+
+/* Build a new TSP area to hold nargs worth of multiple-values.  */
+/* Pop the multiple values off of the vstack.  */
+/* The new TSP frame will look like this:  */
+/*  */
+/*+--------+-------+-------+---------+--------+--------+--------+======+----------+ */
+/*| ptr to | zero  | nargs | ptr to  | valn-1 | valn-2 | val-0  | ???? | prev TSP |  */
+/*|  prev  |       |       |  prev   |        |        |        | fill |          |  */
+/*| TSP    |       |       | segment |        |        |        |      |          | */
+/*+--------+-------+-------+---------+--------+--------+--------+------+----------+  */
+/*  */
+/* e.g., the first multiple value goes in the last cell in the frame, the  */
+/* count of values goes in the first word, and the word after the value count  */
+/* is 0 if the number of values is even (for alignment).  */
+/* Subsequent calls to .SPadd_values preserve this alignment.  */
+/* .SPrecover_values is therefore pretty simple.  */
+
+_spentry(save_values)
+	__(mr imm1,tsp)
+
+        /* common exit: nargs = values in this set, imm1 = ptr to tsp before  */
+        /* call to save_values  */
+local_label(save_values_to_tsp):
+	__(mr imm2,tsp)
+	__(dnode_align(imm0,nargs,tsp_frame.fixed_overhead+(2*node_size))) /* count, link  */
+	__(TSP_Alloc_Var_Boxed_nz(imm0,imm3))
+	__(str(imm1,tsp_frame.backlink(tsp))) /* keep one tsp "frame" as far as rest of lisp is concerned  */
+	__(str(nargs,tsp_frame.data_offset(tsp)))
+	__(str(imm2,tsp_frame.data_offset+node_size(tsp))) /* previous tsp  */
+	__(la imm3,tsp_frame.data_offset+node_size*2(tsp))
+	__(add imm3,imm3,nargs)
+	__(add imm0,vsp,nargs)
+	__(cmpr(cr0,imm0,vsp))
+	__(b 2f)
+1:
+	__(ldru(arg_z,-node_size(imm0)))
+	__(cmpr(cr0,imm0,vsp))
+	__(stru(arg_z,-node_size(imm3)))
+2:
+	__(bne cr0,1b)
+	__(add vsp,vsp,nargs) /*  discard values  */
+	__(blr)
+	
+
+/* Add the multiple values that are on top of the vstack to the set  */
+/* saved in the top tsp frame, popping them off of the vstack in the  */
+/* process.  It is an error (a bad one) if the TSP contains something  */
+/* other than a previously saved set of multiple-values.  */
+/* Since adding to the TSP may cause a new TSP segment to be allocated,  */
+/* each add_values call adds another linked element to the list of  */
+/* values. This makes recover_values harder.  */
+
+_spentry(add_values)
+	__(cmpri(cr0,nargs,0))
+	__(ldr(imm1,0(tsp)))
+	__(bne cr0,local_label(save_values_to_tsp))
+	__(blr)
+        
+/* On entry, R11->callback-index  */
+/* Restore lisp context, then funcall #'%pascal-functions% with  */
+/* two args: callback-index, args-ptr (a macptr pointing to the args on the stack)  */
+_spentry(poweropen_callback)
+        __ifdef([rTOC])
+         __(mr r11,rTOC)
+        __endif
+	/* Save C argument registers  */
+	__(str(r3,c_frame.param0(sp)))
+	__(str(r4,c_frame.param1(sp)))
+	__(str(r5,c_frame.param2(sp)))
+	__(str(r6,c_frame.param3(sp)))
+	__(str(r7,c_frame.param4(sp)))
+	__(str(r8,c_frame.param5(sp)))
+	__(str(r9,c_frame.param6(sp)))
+	__(str(r10,c_frame.param7(sp)))
+	__(mflr imm3)
+	__(str(imm3,c_frame.savelr(sp)))
+	__(mfcr imm0)
+	__(str(imm0,c_frame.crsave(sp)))
+
+	/* Save the non-volatile registers on the sp stack  */
+	/* This is a non-standard stack frame, but noone will ever see it,  */
+        /* so it doesn't matter. It will look like more of the stack frame pushed below.  */
+	__(stru(sp,-(stack_align(c_reg_save.size))(sp)))
+        __(str(r13,c_reg_save.save_gprs+(0*node_size)(sp)))
+        __(str(r14,c_reg_save.save_gprs+(1*node_size)(sp)))
+        __(str(r15,c_reg_save.save_gprs+(2*node_size)(sp)))
+        __(str(r16,c_reg_save.save_gprs+(3*node_size)(sp)))
+        __(str(r17,c_reg_save.save_gprs+(4*node_size)(sp)))
+        __(str(r18,c_reg_save.save_gprs+(5*node_size)(sp)))
+        __(str(r19,c_reg_save.save_gprs+(6*node_size)(sp)))
+        __(str(r20,c_reg_save.save_gprs+(7*node_size)(sp)))
+        __(str(r21,c_reg_save.save_gprs+(8*node_size)(sp)))
+        __(str(r22,c_reg_save.save_gprs+(9*node_size)(sp)))
+        __(str(r23,c_reg_save.save_gprs+(10*node_size)(sp)))
+        __(str(r24,c_reg_save.save_gprs+(11*node_size)(sp)))
+        __(str(r25,c_reg_save.save_gprs+(12*node_size)(sp)))
+        __(str(r26,c_reg_save.save_gprs+(13*node_size)(sp)))
+        __(str(r27,c_reg_save.save_gprs+(14*node_size)(sp)))
+        __(str(r28,c_reg_save.save_gprs+(15*node_size)(sp)))
+        __(str(r29,c_reg_save.save_gprs+(16*node_size)(sp)))
+        __(str(r30,c_reg_save.save_gprs+(17*node_size)(sp)))
+        __(str(r31,c_reg_save.save_gprs+(18*node_size)(sp)))
+        __(stfd f1,c_reg_save.save_fprs+(0*8)(sp))
+        __(stfd f2,c_reg_save.save_fprs+(1*8)(sp))
+        __(stfd f3,c_reg_save.save_fprs+(2*8)(sp))
+        __(stfd f4,c_reg_save.save_fprs+(3*8)(sp))
+        __(stfd f5,c_reg_save.save_fprs+(4*8)(sp))
+        __(stfd f6,c_reg_save.save_fprs+(5*8)(sp))
+        __(stfd f7,c_reg_save.save_fprs+(6*8)(sp))
+        __(stfd f8,c_reg_save.save_fprs+(7*8)(sp))
+        __(stfd f9,c_reg_save.save_fprs+(8*8)(sp))
+        __(stfd f10,c_reg_save.save_fprs+(9*8)(sp))
+        __(stfd f11,c_reg_save.save_fprs+(10*8)(sp))
+        __(stfd f12,c_reg_save.save_fprs+(11*8)(sp))
+        __(stfd f13,c_reg_save.save_fprs+(12*8)(sp))
+	__(check_stack_alignment(r0))
+	__(mffs f0)
+	__(stfd f0,c_reg_save.save_fp_zero(sp))
+	__(lwz r31,c_reg_save.save_fp_zero+4(sp))	/* recover FPSCR image  */
+	__(stw r31,c_reg_save.save_fpscr(sp))
+	__(lwi(r30,0x43300000))
+	__(lwi(r31,0x80000000))
+	__(stw r30,c_reg_save.save_fp_zero(sp))
+	__(stw r31,c_reg_save.save_fp_zero+4(sp))
+	__(stfd fp_s32conv,c_reg_save.save_fps32conv(sp))
+	__(lfd fp_s32conv,c_reg_save.save_fp_zero(sp))
+	__(stfd fp_zero,c_reg_save.save_fp_zero(sp))
+	__(lfs fp_zero,lisp_globals.short_float_zero(0))	/* ensure that fp_zero contains 0.0  */
+
+/* Restore rest of Lisp context.  */
+/* Could spread out the memory references here to gain a little speed  */
+
+	__(li loc_pc,0)
+	__(li fn,0)                     /* subprim, not a lisp function  */
+	__(li temp3,0)
+	__(li temp2,0)
+	__(li temp1,0)
+	__(li temp0,0)
+	__(li arg_x,0)
+	__(box_fixnum(arg_y,r11))	/* callback-index  */
+        __(la arg_z,c_reg_save.save_fprs(sp))
+        __(str(arg_z,stack_align(c_reg_save.size)+c_frame.unused(sp)))
+	__(la arg_z,stack_align(c_reg_save.size)+c_frame.param0(sp))	/* parameters (tagged as a fixnum)  */
+
+	/* Recover lisp thread context. Have to call C code to do so.  */
+	__(ref_global(r12,get_tcr))
+        __ifdef([rTOC])
+         __(ld rTOC,8(r12))
+         __(ld r12,0(r12))
+        __endif
+	__(mtctr r12)
+        __(li r3,1)
+	__(stru(sp,-(stack_align(c_frame.minsiz))(sp)))
+	__(bctrl)
+	__(la rcontext,TCR_BIAS(r3))
+	__(la sp,(stack_align(c_frame.minsiz))(sp))
+
+	__(ldr(vsp,tcr.save_vsp(rcontext)))
+	__(ldr(tsp,tcr.save_tsp(rcontext)))		
+	__(li rzero,0)
+	__(li imm0,TCR_STATE_LISP)
+	__(mtxer rzero) /* lisp wants the overflow bit being clear  */
+        __(mtctr rzero)
+	__(li save0,0)
+	__(li save1,0)
+	__(li save2,0)
+	__(li save3,0)
+	__(li save4,0)
+	__(li save5,0)
+	__(li save6,0)
+	__(li save7,0)
+	__(lfd f0,tcr.lisp_fpscr(rcontext))
+	__(mtfsf 0xff,f0)
+	__(li allocbase,0)
+	__(li allocptr,0)	
+	__(str(imm0,tcr.valence(rcontext)))
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+	
+        __(restore_saveregs(vsp))
+
+	/* load nargs and callback to the lisp  */
+	__(set_nargs(2))
+	__(ldr(imm2,tcr.cs_area(rcontext)))
+	__(ldr(imm4,area.active(imm2)))
+	__(stru(imm4,-lisp_frame.size(sp)))
+	__(str(imm3,lisp_frame.savelr(sp)))
+	__(li fname,nrs.callbacks)	/* %pascal-functions%  */
+	__(call_fname)
+	__(ldr(imm2,lisp_frame.backlink(sp)))
+	__(ldr(imm3,tcr.cs_area(rcontext)))
+	__(str(imm2,area.active(imm3)))
+	__(discard_lisp_frame())
+	/* save_vsp will be restored from ff_call's stack frame, but  */
+	/* I included it here for consistency.  */
+	/* save_tsp is set below after we exit Lisp context.  */
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	/* Exit lisp context  */
+	__(li imm1,TCR_STATE_FOREIGN)
+	__(str(imm1,tcr.valence(rcontext)))
+	/* Restore the non-volatile registers & fpscr  */
+	__(lfd fp_zero,c_reg_save.save_fp_zero(sp))
+	__(lwz r31,c_reg_save.save_fpscr(sp))
+	__(stw r31,c_reg_save.save_fp_zero+4(sp))
+	__(lfd f0,c_reg_save.save_fp_zero(sp))
+	__(mtfsf 0xff,f0)
+	__(ldr(r13,c_reg_save.save_gprs+(0*node_size)(sp)))
+	__(ldr(r14,c_reg_save.save_gprs+(1*node_size)(sp)))
+	__(ldr(r15,c_reg_save.save_gprs+(2*node_size)(sp)))
+	__(ldr(r16,c_reg_save.save_gprs+(3*node_size)(sp)))
+	__(ldr(r17,c_reg_save.save_gprs+(4*node_size)(sp)))
+	__(ldr(r18,c_reg_save.save_gprs+(5*node_size)(sp)))
+	__(ldr(r19,c_reg_save.save_gprs+(6*node_size)(sp)))
+	__(ldr(r20,c_reg_save.save_gprs+(7*node_size)(sp)))
+	__(ldr(r21,c_reg_save.save_gprs+(8*node_size)(sp)))
+	__(ldr(r22,c_reg_save.save_gprs+(9*node_size)(sp)))
+	__(ldr(r23,c_reg_save.save_gprs+(10*node_size)(sp)))
+	__(ldr(r24,c_reg_save.save_gprs+(11*node_size)(sp)))
+	__(ldr(r25,c_reg_save.save_gprs+(12*node_size)(sp)))
+	__(ldr(r26,c_reg_save.save_gprs+(13*node_size)(sp)))
+	__(ldr(r27,c_reg_save.save_gprs+(14*node_size)(sp)))
+	__(ldr(r28,c_reg_save.save_gprs+(15*node_size)(sp)))
+	__(ldr(r29,c_reg_save.save_gprs+(16*node_size)(sp)))
+	__(ldr(r30,c_reg_save.save_gprs+(17*node_size)(sp)))
+	__(ldr(r31,c_reg_save.save_gprs+(18*node_size)(sp)))
+        __(lfd f1,c_reg_save.save_fprs+(0*8)(sp))
+        __(lfd f2,c_reg_save.save_fprs+(1*8)(sp))
+        __(lfd f3,c_reg_save.save_fprs+(2*8)(sp))
+        __(lfd f4,c_reg_save.save_fprs+(3*8)(sp))
+        __(lfd f5,c_reg_save.save_fprs+(4*8)(sp))
+        __(lfd f6,c_reg_save.save_fprs+(5*8)(sp))
+        __(lfd f7,c_reg_save.save_fprs+(6*8)(sp))
+        __(lfd f8,c_reg_save.save_fprs+(7*8)(sp))
+        __(lfd f9,c_reg_save.save_fprs+(8*8)(sp))
+        __(lfd f10,c_reg_save.save_fprs+(9*8)(sp))
+        __(lfd f11,c_reg_save.save_fprs+(10*8)(sp))
+        __(lfd f12,c_reg_save.save_fprs+(11*8)(sp))
+        __(lfd f13,c_reg_save.save_fprs+(12*8)(sp))
+	__(lfd fp_s32conv,c_reg_save.save_fps32conv(sp))
+	__(ldr(sp,0(sp)))
+	__(ldr(r3,c_frame.param0(sp)))
+	__(ldr(r4,c_frame.param1(sp)))
+	__(ldr(r5,c_frame.param2(sp)))
+	__(ldr(r6,c_frame.param3(sp)))
+	__(ldr(r7,c_frame.param4(sp)))
+	__(ldr(r8,c_frame.param5(sp)))
+	__(ldr(r9,c_frame.param6(sp)))
+	__(ldr(r10,c_frame.param7(sp)))
+	__(ldr(r11,c_frame.savelr(sp)))
+	__(mtlr r11)
+	__(ldr(r11,c_frame.crsave(sp)))
+	__(mtcr r11)
+	__(blr)
+        
+/* Like misc_alloc (a LOT like it, since it does most of the work), but takes  */
+/* an initial-value arg in arg_z, element_count in arg_x, subtag in arg_y.  */
+/* Calls out to %init-misc, which does the rest of the work.  */
+
+_spentry(misc_alloc_init)
+	__(mflr loc_pc)
+	__(build_lisp_frame(fn,loc_pc,vsp))
+	__(li fn,0)
+	__(mr temp0,arg_z)		/* initval  */
+	__(mr arg_z,arg_y)		/* subtag  */
+	__(mr arg_y,arg_x)		/* element-count  */
+	__(bl _SPmisc_alloc)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp))) 
+	__(discard_lisp_frame())
+	__(li fname,nrs.init_misc)
+	__(set_nargs(2))
+	__(mr arg_y,temp0)
+	__(jump_fname())
+
+/* As in stack_misc_alloc above, only with a non-default initial-value.  */
+
+_spentry(stack_misc_alloc_init)
+	__(mflr loc_pc)
+	__(build_lisp_frame(fn,loc_pc,vsp))
+	__(li fn,0)
+	__(mr temp0,arg_z) /* initval  */
+	__(mr arg_z,arg_y) /* subtag  */
+	__(mr arg_y,arg_x) /* element-count  */
+	__(bl _SPstack_misc_alloc)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(discard_lisp_frame())
+	__(li fname,nrs.init_misc)
+	__(set_nargs(2))
+	__(mr arg_y,temp0)
+	__(jump_fname())
+
+	
+_spentry(callbuiltin)
+	__(ref_nrs_value(fname,builtin_functions))
+	__(la imm0,misc_data_offset(imm0))
+	__(ldrx(fname,fname,imm0))
+	__(jump_fname())
+
+/* the value of the nilreg-relative symbol %builtin-functions% should be  */
+/* a vector of symbols.  Call the symbol indexed by imm0 (boxed) and  */
+/* return a single value.  */
+
+_spentry(callbuiltin0)
+	__(set_nargs(0))
+	__(ref_nrs_value(fname,builtin_functions))
+	__(la imm0,misc_data_offset(imm0))
+	__(ldrx(fname,fname,imm0))
+	__(jump_fname())
+
+_spentry(callbuiltin1)
+	__(ref_nrs_value(fname,builtin_functions))
+	__(set_nargs(1))
+	__(la imm0,misc_data_offset(imm0))
+	__(ldrx(fname,fname,imm0))
+	__(jump_fname())
+
+_spentry(callbuiltin2)
+	__(set_nargs(2))
+	__(ref_nrs_value(fname,builtin_functions))
+	__(la imm0,misc_data_offset(imm0))
+	__(ldrx(fname,fname,imm0))
+	__(jump_fname())
+
+
+_spentry(callbuiltin3)
+	__(set_nargs(3))
+	__(ref_nrs_value(fname,builtin_functions))
+	__(la imm0,misc_data_offset(imm0))
+	__(ldrx(fname,fname,imm0))
+	__(jump_fname())
+	
+
+_spentry(popj)
+	.globl C(popj)
+C(popj):
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(discard_lisp_frame())
+	__(blr)
+
+_spentry(restorefullcontext)
+	__(mflr loc_pc)
+	__(mtctr loc_pc)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(discard_lisp_frame())
+	__(bctr)
+
+_spentry(savecontextvsp)
+	__(ldr(imm0,tcr.cs_limit(rcontext)))
+	__(build_lisp_frame(fn,loc_pc,vsp))
+	__(mr fn,nfn)
+	__(trllt(sp,imm0))
+	__(blr)
+
+_spentry(savecontext0)
+	__(add imm0,vsp,imm0)
+	__(build_lisp_frame(fn,loc_pc,imm0))
+	__(ldr(imm0,tcr.cs_limit(rcontext)))
+	__(mr fn,nfn)
+	__(trllt(sp,imm0))
+	__(blr)
+
+
+/* Like .SPrestorefullcontext, only the saved return address  */
+/* winds up in loc-pc instead of getting thrashed around ...  */
+_spentry(restorecontext)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(discard_lisp_frame())
+	__(blr)
+
+        
+/* Nargs is valid; all arg regs, lexpr-count pushed by caller.  */
+/* imm0 = vsp to restore.  */
+/* Return all values returned by caller to its caller, hiding  */
+/* the variable-length arglist.  */
+/* If we can detect that the caller's caller didn't expect  */
+/* multiple values, then things are even simpler.  */
+_spentry(lexpr_entry)
+	__(ref_global(imm1,ret1val_addr))
+	__(cmpr(cr0,imm1,loc_pc))
+	__(build_lisp_frame(fn,loc_pc,imm0))
+	__(bne cr0,1f)
+	__(ref_global(imm0,lexpr_return))
+	__(build_lisp_frame(rzero,imm0,vsp))
+	__(mr loc_pc,imm1)
+	__(ldr(imm0,tcr.cs_limit(rcontext)))
+	__(trllt(sp,imm0))
+	__(li fn,0)
+	__(blr)
+
+        /* The single-value case just needs to return to something that'll pop  */
+        /* the variable-length frame off of the vstack.  */
+1:
+	__(ref_global(loc_pc,lexpr_return1v))
+	__(ldr(imm0,tcr.cs_limit(rcontext)))
+	__(trllt(sp,imm0))
+	__(li fn,0)
+	__(blr)
+
+/* */
+/* Do a system call in Darwin.  The stack is set up much as it would be */
+/* for a PowerOpen ABI ff-call:	register parameters are in the stack */
+/* frame, and there are 4 extra words at the bottom of the frame that */
+/* we can carve a lisp frame out of. */
+/*  */
+/* System call return conventions are a little funky in Darwin: if "@sc" */
+/* is the address of the "sc" instruction, errors return to @sc+4 and */
+/* non-error cases return to @sc+8.  Error values are returned as */
+/* positive values in r3; this is true even if the system call returns */
+/* a doubleword (64-bit) result.  Since r3 would ordinarily contain */
+/* the high half of a doubleword result, this has to be special-cased. */
+/*  */
+/* The caller should set the c_frame.crsave field of the stack frame */
+/* to 0 if the result is to be interpreted as anything but a doubleword */
+/* and to non-zero otherwise.  (This only matters on an error return.) */
+
+        
+_spentry(poweropen_syscall)
+	__(mflr loc_pc)
+	__(vpush_saveregs())
+	__(ldr(imm1,0(sp)))
+	__(la imm2,-lisp_frame.size(imm1))
+        __(zero_doublewords imm2,0,lisp_frame.size)
+	__(str(imm1,lisp_frame.backlink(imm2)))
+	__(str(imm2,c_frame.backlink(sp)))
+	__(str(fn,lisp_frame.savefn(imm2)))
+	__(str(loc_pc,lisp_frame.savelr(imm2)))
+	__(str(vsp,lisp_frame.savevsp(imm2)))
+	__(ldr(imm3,tcr.cs_area(rcontext)))
+	__(str(imm2,area.active(imm3)))
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+	__(str(rzero,tcr.ffi_exception(rcontext)))
+	__(mr save0,rcontext)
+	__(li r3,TCR_STATE_FOREIGN)
+	__(str(r3,tcr.valence(rcontext)))
+	__(li rcontext,0)
+	__(ldr(r3,c_frame.param0(sp)))
+	__(ldr(r4,c_frame.param1(sp)))
+	__(ldr(r5,c_frame.param2(sp)))
+	__(ldr(r6,c_frame.param3(sp)))
+	__(ldr(r7,c_frame.param4(sp)))
+	__(ldr(r8,c_frame.param5(sp)))
+	__(ldr(r9,c_frame.param6(sp)))
+	__(ldr(r10,c_frame.param7(sp)))
+	__(unbox_fixnum(r0,arg_z))
+	__(sc)
+        __ifdef([LINUX])
+         __(bns+ 9f)
+        __else
+	 __(b 1f)
+	 __(b 9f)
+        __endif
+1:
+        __ifdef([PPC64])
+         __(neg r3,r3)
+        __else
+	 __(ldr(imm2,c_frame.crsave(sp)))
+	 __(cmpri(cr0,imm2,0))
+	 __(bne cr0,2f)
+	 /* 32-bit result  */
+	 __(neg r3,r3)
+	 __(b 9f)
+2:
+	 /* 64-bit result  */
+	 __(neg r4,r3)
+	 __(li r3,-1)
+        __endif
+9:
+	__(mr imm2,save0)	/* recover context  */
+	__(ldr(sp,c_frame.backlink(sp)))
+	__(li imm4,TCR_STATE_LISP)
+	__(li rzero,0)
+	__(li loc_pc,0)
+	__(li arg_x,nil_value)
+	__(li arg_y,nil_value)
+	__(li arg_z,nil_value)
+	__(li temp0,nil_value)
+	__(li temp1,nil_value)
+	__(li temp2,nil_value)
+	__(li temp3,nil_value)
+	__(li fn,nil_value)
+	__(mr rcontext,imm2)
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+	__(ldr(tsp,tcr.save_tsp(rcontext)))
+        __(li save0,0)
+        __(li save1,0)
+        __(li save2,0)
+        __(li save3,0)
+        __(li save4,0)
+        __(li save5,0)
+        __(li save6,0)
+        __(li save7,0)        
+	__(str(imm4,tcr.valence(rcontext)))
+	__(vpop_saveregs)
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(discard_lisp_frame)
+        __(mtxer rzero)
+	__(check_pending_interrupt([cr1]))
+	__(blr)
+        
+        
+_spentry(builtin_plus)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(addo. arg_z,arg_y,arg_z)
+	__(bnslr+)
+	__(mtxer rzero)
+	__(unbox_fixnum(imm1,arg_z))
+        __ifdef([PPC64])
+	 __(li imm0,two_digit_bignum_header)
+         __(rotldi imm1,imm1,32)
+	 __(xoris imm1,imm1,0xe000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(2)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __else
+	 __(li imm0,one_digit_bignum_header)
+	 __(xoris imm1,imm1,0xc000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(1)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __endif
+	__(blr)
+1:
+	__(jump_builtin(_builtin_plus,2))
+_spentry(builtin_minus)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(subo. arg_z,arg_y,arg_z)
+	__(bnslr+)
+	__(mtxer rzero)
+	__(unbox_fixnum(imm1,arg_z))
+        __ifdef([PPC64])
+	 __(li imm0,two_digit_bignum_header)
+         __(rotldi imm1,imm1,32)
+	 __(xoris imm1,imm1,0xe000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(2)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __else
+	 __(li imm0,one_digit_bignum_header)
+	 __(xoris imm1,imm1,0xc000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(1)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __endif
+	__(blr)
+1:
+	__(jump_builtin(_builtin_minus,2))
+_spentry(builtin_times)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(unbox_fixnum(imm2,arg_y))
+	__(bne cr0,1f)
+        __(bne cr1,1f)
+        __ifdef([PPC64])
+         __(mulldo. imm3,arg_z,imm2)
+         __(bso 2f)
+         __(mr arg_z,imm3)
+         __(blr)
+	 /* Args are fixnums; result can't be  */
+2:	 __(mtxer rzero)
+	 __(unbox_fixnum(imm3,arg_z))
+	 __(mulld imm1,imm3,imm2) /* imm1 = low  64 bits  */
+	 __(mulhd imm0,imm3,imm2) /* imm0 = high 64 bits  */
+	 __(b _SPmakes128)
+        __else
+	 __(mullwo. imm3,arg_z,imm2)
+	 __(bso 2f)		/*  SO set if result would overflow a fixnum  */
+	 __(mr arg_z,imm3)
+	 __(blr)
+	 /* Args are fixnums; result can't be  */
+2:	 __(mtxer rzero)
+	 __(unbox_fixnum(imm3,arg_z))
+	 __(mullw imm1,imm3,imm2) /* imm1 = low  32 bits  */
+	 __(mulhw imm0,imm3,imm2) /* imm0 = high 32 bits  */
+	 __(b _SPmakes64)
+        __endif
+
+1:	__(jump_builtin(_builtin_times,2))
+
+_spentry(builtin_div)
+	__(jump_builtin(_builtin_div,2))
+
+_spentry(builtin_eq)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(cmpr(cr2,arg_y,arg_z))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(li arg_z,nil_value)
+	__(bnelr cr2)
+	__(li arg_z,t_value)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_eq,2))
+
+_spentry(builtin_ne)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(cmpr(cr2,arg_y,arg_z))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(li arg_z,nil_value)
+	__(beqlr cr2)
+	__(li arg_z,t_value)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_ne,2))
+
+_spentry(builtin_gt)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(cmpr(cr2,arg_y,arg_z))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(li arg_z,nil_value)
+	__(bnglr cr2)
+	__(li arg_z,t_value)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_gt,2))
+
+_spentry(builtin_ge)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(cmpr(cr2,arg_y,arg_z))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(li arg_z,nil_value)
+	__(bltlr cr2)
+	__(li arg_z,t_value)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_ge,2))
+
+_spentry(builtin_lt)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(cmpr(cr2,arg_y,arg_z))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(li arg_z,nil_value)
+	__(bnllr cr2)
+	__(li arg_z,t_value)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_lt,2))
+
+_spentry(builtin_le)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(cmpr(cr2,arg_y,arg_z))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(li arg_z,nil_value)
+	__(bgtlr cr2)
+	__(li arg_z,t_value)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_le,2))
+
+
+_spentry(builtin_eql)
+        __(cmpr(cr1,arg_y,arg_z))
+        __(extract_fulltag(imm2,arg_y))
+        __(extract_fulltag(imm3,arg_z))
+        __(beq cr1,1f)
+        __(cmpri(cr1,imm2,fulltag_misc))
+        __(cmpri(cr0,imm3,fulltag_misc))
+        __(bne cr1,2f)
+        __(extract_subtag(imm0,arg_y))
+        __(bne cr0,2f)
+        __(extract_subtag(imm1,arg_z))
+        __(cmpr(cr0,imm0,imm1))
+        __(bne cr0,2f)
+	__(jump_builtin(_builtin_eql,2))
+1:	__(li arg_z,t_value)
+	__(blr)
+2:	__(li arg_z,nil_value)
+	__(blr)
+        
+_spentry(builtin_length)
+        __(cmpri(cr1,arg_z,nil_value))
+	__(extract_typecode(imm0,arg_z))
+	__(cmpri(cr0,imm0,min_vector_subtag))
+        __(beq cr1,1f)
+        __ifdef([PPC64])
+         __(cmpdi cr2,imm0,fulltag_cons)
+        __else
+	 __(cmpwi cr2,imm0,tag_list)
+        __endif
+	__(beq- cr0,2f)
+	__(blt- cr0,3f)
+	/* (simple-array * (*))  */
+	__(vector_length(arg_z,arg_z,imm0))
+	__(blr)
+1:      __(li arg_z,0)
+        __(blr)
+2:
+	__(ldr(arg_z,vectorH.logsize(arg_z)))
+	__(blr)        
+3:	__(bne cr2,8f)
+	__(li temp2,-1<<fixnum_shift)
+	__(mr temp0,arg_z)	/* fast pointer  */
+	__(mr temp1,arg_z)	/* slow pointer  */
+        __ifdef([PPC64])
+4:       __(extract_fulltag(imm0,temp0))
+         __(cmpdi cr7,temp0,nil_value)
+         __(cmpdi cr1,imm0,fulltag_cons)
+         __(addi temp2,temp2,fixnum_one)
+         __(beq cr7,9f)
+         __(andi. imm0,temp2,1<<fixnum_shift)
+         __(bne cr1,8f)
+         __(extract_fulltag(imm1,temp1))
+         __(_cdr(temp0,temp0))
+         __(cmpdi cr1,imm1,fulltag_cons)
+	 __(beq cr0,4b)
+	 __(bne cr1,8f)
+	 __(_cdr(temp1,temp1))
+	 __(cmpd cr0,temp0,temp1)
+	 __(bne cr0,4b)
+        __else
+4:	 __(extract_lisptag(imm0,temp0))
+	 __(cmpri(cr7,temp0,nil_value))
+	 __(cmpri(cr1,imm0,tag_list))
+	 __(addi temp2,temp2,fixnum_one)
+	 __(beq cr7,9f)
+	 __(andi. imm0,temp2,1<<fixnum_shift)
+	 __(bne cr1,8f)
+	 __(extract_lisptag(imm1,temp1))	
+	 __(_cdr(temp0,temp0))
+	 __(cmpri(cr1,imm1,tag_list))
+	 __(beq cr0,4b)
+	 __(bne cr1,8f)
+	 __(_cdr(temp1,temp1))
+	 __(cmpr(cr0,temp0,temp1))
+	 __(bne cr0,4b)
+        __endif
+8:	
+	__(jump_builtin(_builtin_length,1))
+9:	
+	__(mr arg_z,temp2)
+	__(blr)
+        
+_spentry(builtin_seqtype)
+        __ifdef([PPC64])
+         __(cmpdi cr2,arg_z,nil_value)
+         __(extract_typecode(imm0,arg_z))
+         __(beq cr2,1f)
+	 __(cmpri(cr0,imm0,fulltag_cons))
+        __else
+	 __(extract_typecode(imm0,arg_z))
+ 	 __(cmpri(cr0,imm0,tag_list))
+        __endif
+	__(cmpri(cr1,imm0,min_vector_subtag))
+	__(beq cr0,1f)
+	__(blt- cr1,2f)
+	__(li arg_z,nil_value)
+	__(blr)
+1:	__(li arg_z,t_value)
+	__(blr)
+2:
+	__(jump_builtin(_builtin_seqtype,1))
+        
+_spentry(builtin_assq)
+	__(cmpri(arg_z,nil_value))
+	__(beqlr)
+1:	__(trap_unless_list(arg_z,imm0))
+	__(_car(arg_x,arg_z))
+	__(_cdr(arg_z,arg_z))
+	__(cmpri(cr2,arg_x,nil_value))
+	__(cmpri(cr1,arg_z,nil_value))
+	__(beq cr2,2f)
+	__(trap_unless_list(arg_x,imm0))
+	__(_car(temp0,arg_x))
+	__(cmpr(temp0,arg_y))
+	__(bne cr0,2f)
+	__(mr arg_z,arg_x)
+	__(blr)
+2:	__(bne cr1,1b)
+	__(blr)
+
+_spentry(builtin_memq)
+	__(cmpri(cr1,arg_z,nil_value))
+	__(b 2f)
+1:	__(trap_unless_list(arg_z,imm0))
+	__(_car(arg_x,arg_z))
+	__(_cdr(temp0,arg_z))
+	__(cmpr(arg_x,arg_y))
+	__(cmpri(cr1,temp0,nil_value))
+	__(beqlr)
+	__(mr arg_z,temp0)
+2:	__(bne cr1,1b)
+	__(blr)
+
+        __ifdef([PPC64])
+logbitp_max_bit = 61
+        __else
+logbitp_max_bit = 30
+        __endif
+        
+_spentry(builtin_logbitp)
+	/* Call out unless both fixnums,0 <=  arg_y < logbitp_max_bit  */
+        __(cmplri(cr2,arg_y,logbitp_max_bit<<fixnum_shift))
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(unbox_fixnum(imm0,arg_y))
+	__(subfic imm0,imm0,logbitp_max_bit)
+        __ifdef([PPC64])
+         __(rldcl imm0,arg_z,imm0,63)
+         __(mulli imm0,imm0,t_offset)
+        __else
+  	 __(rlwnm imm0,arg_z,imm0,31,31)
+	 __(rlwimi imm0,imm0,4,27,27)
+        __endif
+	__(bnl cr2,1f)
+	__(bne cr0,1f)
+        __(bne cr1,1f)
+	__(addi arg_z,imm0,nil_value)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_logbitp,2))
+
+_spentry(builtin_logior)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(or arg_z,arg_y,arg_z)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_logior,2))
+
+_spentry(builtin_logand)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(and arg_z,arg_y,arg_z)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_logand,2))
+	
+_spentry(builtin_ash)
+        __ifdef([PPC64])
+	 __(cmpdi cr1,arg_z,0)
+         __(extract_lisptag(imm0,arg_y))
+         __(extract_lisptag(imm1,arg_z))
+         __(cmpdi cr0,imm0,tag_fixnum)
+         __(cmpdi cr3,imm1,tag_fixnum)
+	 __(cmpdi cr2,arg_z,-(63<<3))	/* !! 3 =  fixnumshift  */
+	 __(bne- cr0,9f)
+         __(bne- cr3,9f)
+	 __(bne cr1,0f)
+	 __(mr arg_z,arg_y)	/* (ash n 0) => n  */
+	 __(blr)
+0:		
+	 __(unbox_fixnum(imm1,arg_y))
+	 __(unbox_fixnum(imm0,arg_z))
+	 __(bgt cr1,2f)
+	 /* (ash n -count) => fixnum  */
+	 __(neg imm2,imm0)
+	 __(bgt cr2,1f)
+	 __(li imm2,63)
+1:	
+	 __(srad imm0,imm1,imm2)
+	 __(box_fixnum(arg_z,imm0))
+	 __(blr)
+	 /* Integer-length of arg_y/imm1 to imm2  */
+2:		
+	 __(cntlzd. imm2,imm1)
+	 __(bne 3f)		/* cr0[eq] set if negative  */
+	 __(not imm2,imm1)
+	 __(cntlzd imm2,imm2)
+3:
+	 __(subfic imm2,imm2,64)
+	 __(add imm2,imm2,imm0)	 /* imm2 <- integer-length(imm1) + count  */
+	 __(cmpdi cr1,imm2,63-fixnumshift)
+	 __(cmpdi cr2,imm0,64)
+	 __(sld imm2,imm1,imm0)
+	 __(bgt cr1,6f)
+	 __(box_fixnum(arg_z,imm2))
+	 __(blr)	
+6:
+	 __(bgt cr2,9f)
+	 __(bne cr2,7f)
+	 /* Shift left by 64 bits exactly  */
+	 __(mr imm0,imm1)
+	 __(li imm1,0)
+	 __(beq _SPmakes128)
+	 __(b _SPmakeu128)
+7:
+	 /* Shift left by fewer than 64 bits, result not a fixnum  */
+	 __(subfic imm0,imm0,64)
+	 __(beq 8f)
+	 __(srd imm0,imm1,imm0)
+	 __(mr imm1,imm2)
+	 __(b _SPmakeu128)
+8:	
+	 __(srad imm0,imm1,imm0)
+	 __(mr imm1,imm2)
+	 __(b _SPmakes128)
+        __else
+	 __(cmpri(cr1,arg_z,0))
+         __(extract_lisptag(imm0,arg_y))
+         __(extract_lisptag(imm1,arg_z))
+         __(cmpri(cr0,imm0,tag_fixnum))
+         __(cmpri(cr3,imm1,tag_fixnum))
+	 __(cmpri(cr2,arg_z,-(29<<2)))	/* !! 2 =  fixnumshift  */
+	 __(bne- cr0,9f)
+         __(bne- cr3,9f)
+	 __(bne cr1,0f)
+	 __(mr arg_z,arg_y)	/* (ash n 0) => n  */
+	 __(blr)
+0:		
+	 __(unbox_fixnum(imm1,arg_y))
+	 __(unbox_fixnum(imm0,arg_z))
+	 __(bgt cr1,2f)
+	 /* (ash n -count) => fixnum  */
+	 __(neg imm2,imm0)
+	 __(bgt cr2,1f)
+	 __(li imm2,31)
+1:	
+	 __(sraw imm0,imm1,imm2)
+	 __(box_fixnum(arg_z,imm0))
+	 __(blr)
+	 /* Integer-length of arg_y/imm1 to imm2  */
+2:		
+	 __(cntlzw. imm2,imm1)
+	 __(bne 3f)		/* cr0[eq] set if negative  */
+	 __(not imm2,imm1)
+	 __(cntlzw imm2,imm2)
+3:
+	 __(subfic imm2,imm2,32)
+	 __(add imm2,imm2,imm0)	 /* imm2 <- integer-length(imm1) + count  */
+	 __(cmpri(cr1,imm2,31-fixnumshift))
+	 __(cmpri(cr2,imm0,32))
+	 __(slw imm2,imm1,imm0)
+	 __(bgt cr1,6f)
+	 __(box_fixnum(arg_z,imm2))
+	 __(blr)	
+6:
+	 __(bgt cr2,9f)
+	 __(bne cr2,7f)
+	 /* Shift left by 32 bits exactly  */
+	 __(mr imm0,imm1)
+	 __(li imm1,0)
+	 __(beq _SPmakes64)
+	 __(b _SPmakeu64)
+7:
+	 /* Shift left by fewer than 32 bits, result not a fixnum  */
+	 __(subfic imm0,imm0,32)
+	 __(beq 8f)
+	 __(srw imm0,imm1,imm0)
+	 __(mr imm1,imm2)
+	 __(b _SPmakeu64)
+8:	
+	 __(sraw imm0,imm1,imm0)
+	 __(mr imm1,imm2)
+	 __(b _SPmakes64)
+        __endif
+9:		
+	__(jump_builtin(_builtin_ash,2))
+
+_spentry(builtin_negate)
+	__(extract_lisptag_(imm0,arg_z))
+	__(bne- cr0,1f)
+	__(nego. arg_z,arg_z)
+	__(bnslr+)
+	__(mtxer rzero)
+	__(unbox_fixnum(imm1,arg_z))
+        __ifdef([PPC64])
+	 __(li imm0,two_digit_bignum_header)
+         __(rotldi imm1,imm1,32)
+	 __(xoris imm1,imm1,0xe000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(2)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __else
+	 __(li imm0,one_digit_bignum_header)
+	 __(xoris imm1,imm1,0xc000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(1)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __endif
+	__(blr)
+1:
+	__(jump_builtin(_builtin_negate,1))
+
+_spentry(builtin_logxor)
+        __(extract_lisptag(imm0,arg_y))
+        __(extract_lisptag(imm1,arg_z))
+        __(cmpri(cr0,imm0,tag_fixnum))
+        __(cmpri(cr1,imm1,tag_fixnum))
+	__(bne- cr0,1f)
+        __(bne- cr1,1f)
+	__(xor arg_z,arg_y,arg_z)
+	__(blr)
+1:
+	__(jump_builtin(_builtin_logxor,2))
+
+
+
+        
+_spentry(builtin_aset1)
+	__(extract_typecode(imm0,arg_x))
+	__(cmpri(cr0,imm0,min_vector_subtag))
+	__(box_fixnum(temp0,imm0))
+	__(bgt cr0,1f)
+	__(jump_builtin(_builtin_aset1,3))
+1:
+	__(b _SPsubtag_misc_set)
+
+/* Enter the debugger  */
+_spentry(breakpoint)
+	__(li r3,0)
+	__(tw 28,sp,sp)	/* 28 = lt|gt|eq (assembler bug for the latter)  */
+	__(blr)		/* if handler didn't  */
+
+/* */
+/* We're entered with an eabi_c_frame on the C stack.  There's a */
+/* lisp_frame reserved underneath it; we'll link it in in a minute. */
+/* Load the outgoing GPR arguments from eabi_c_frame.param[0-7], */
+/* then shrink the eabi_c_frame. */
+/*  */
+	
+_spentry(eabi_ff_call)
+	__(mflr loc_pc)
+	__(str(sp,eabi_c_frame.savelr(sp)))
+	__(vpush_saveregs())		/* Now we can use save0-save7 to point to stacks  */
+	__(mr save0,rcontext)	/* or address globals.  */
+	__(extract_typecode(imm0,arg_z))
+	__(cmpri(imm0,subtag_macptr))
+	__(ldr(save1,0(sp)))	/* bottom of reserved lisp frame  */
+	__(la save2,-lisp_frame.size(save1))	/* top of lisp frame */
+        __(zero_doublewords save2,0,lisp_frame.size)
+	__(str(save1,lisp_frame.backlink(save2)))
+	__(str(save2,c_frame.backlink(sp)))
+	__(str(fn,lisp_frame.savefn(save2)))
+	__(str(loc_pc,lisp_frame.savelr(save2)))
+	__(str(vsp,lisp_frame.savevsp(save2)))
+	__(bne 1f)
+	__(ldr(arg_z,macptr.address(arg_z)))
+1:
+	__(ldr(save3,tcr.cs_area(rcontext)))
+	__(str(save2,area.active(save3)))
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+	__(mtctr arg_z)
+	__(str(rzero,tcr.ffi_exception(rcontext)))
+	__(mffs f0)
+	__(stfd f0,tcr.lisp_fpscr(rcontext))	/* remember lisp's fpscr  */
+	__(mtfsf 0xff,fp_zero)	/* zero foreign fpscr  */
+	__(li imm1,TCR_STATE_FOREIGN)
+	__(str(imm1,tcr.valence(rcontext)))
+	__(ldr(r2,tcr.native_thread_info(rcontext)))
+	__(ldr(r13,lisp_globals.saveR13(0)))
+	__(ldr(r3,eabi_c_frame.param0(sp)))
+	__(ldr(r4,eabi_c_frame.param1(sp)))
+	__(ldr(r5,eabi_c_frame.param2(sp)))
+	__(ldr(r6,eabi_c_frame.param3(sp)))
+	__(ldr(r7,eabi_c_frame.param4(sp)))
+	__(ldr(r8,eabi_c_frame.param5(sp)))
+	__(ldr(r9,eabi_c_frame.param6(sp)))
+	__(ldr(r10,eabi_c_frame.param7(sp)))
+	__(la save1,eabi_c_frame.minsiz-eabi_c_frame.param0(sp))
+	__(str(rzero,eabi_c_frame.savelr(save1)))
+	__(str(save2,eabi_c_frame.backlink(save1)))
+	__(mr sp,save1)
+	/* If we're calling a varargs C function, it'll want to */
+	/* know whether or not we've passed any args in FP regs. */
+	/* Better to say that we did (and force callee to save FP */
+	/* arg regs on entry) than to say that we didn't and get */
+	/* garbage results  */
+	__(crset 6)
+	__(bctrl)
+	/* C should have preserved save0 (= rcontext) for us.  */
+	__(ldr(sp,0(sp)))
+	__(mr imm2,save0)
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(li rzero,0)
+	__(mr loc_pc,rzero)
+	__(li arg_x,nil_value)
+	__(li arg_y,nil_value)
+	__(li arg_z,nil_value)
+	__(li temp0,nil_value)
+	__(li temp1,nil_value)
+	__(li temp2,nil_value)
+	__(li temp3,nil_value)
+	__(li fn,nil_value)
+	__(mr rcontext,imm2)
+	__(li imm2,TCR_STATE_LISP)
+	__(ldr(tsp,tcr.save_tsp(rcontext)))
+        __(li save0,0)
+        __(li save1,0)
+        __(li save2,0)
+        __(li save3,0)
+        __(li save4,0)
+        __(li save5,0)
+        __(li save6,0)
+        __(li save7,0)
+        __(li allocptr,-dnode_size)
+        __(li allocbase,-dnode_size)
+	__(str(imm2,tcr.valence(rcontext)))	
+	__(vpop_saveregs())
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(mffs f0)
+	__(stfd f0,8(sp))
+	__(lwz imm3,12(sp))	/* imm3 = FPSCR after call  */
+        __(clrrwi imm2,imm3,8)
+	__(discard_lisp_frame())
+	__(str(imm2,tcr.ffi_exception(rcontext)))
+	__(lfd f0,tcr.lisp_fpscr(rcontext))
+	__(mtfsf 0xff,f0)
+	__(check_pending_interrupt([cr1]))
+        __(mtxer rzero)
+        __(mtctr rzero)
+	__(blr)
+        
+/*  */
+/* This gets called with R11 holding the unboxed callback index. */
+/* */
+        
+_spentry(eabi_callback)
+	/* First, we extend the C frame so that it has room for */
+        /* incoming arg regs.  */
+	__(ldr(r0,eabi_c_frame.backlink(sp)))
+	__(stru(r0,eabi_c_frame.param0-varargs_eabi_c_frame.incoming_stack_args(sp)))
+	__(mflr r0)
+	__(str(r0,varargs_eabi_c_frame.savelr(sp)))
+	__(str(r3,varargs_eabi_c_frame.gp_save+(0*4)(sp)))
+	__(str(r4,varargs_eabi_c_frame.gp_save+(1*4)(sp)))
+	__(str(r5,varargs_eabi_c_frame.gp_save+(2*4)(sp)))
+	__(str(r6,varargs_eabi_c_frame.gp_save+(3*4)(sp)))
+	__(str(r7,varargs_eabi_c_frame.gp_save+(4*4)(sp)))
+	__(str(r8,varargs_eabi_c_frame.gp_save+(5*4)(sp)))
+	__(str(r9,varargs_eabi_c_frame.gp_save+(6*4)(sp)))
+	__(str(r10,varargs_eabi_c_frame.gp_save+(7*4)(sp)))
+	/* Could check the appropriate CR bit and skip saving FP regs here  */
+	__(stfd f1,varargs_eabi_c_frame.fp_save+(0*8)(sp))
+	__(stfd f2,varargs_eabi_c_frame.fp_save+(1*8)(sp))
+	__(stfd f3,varargs_eabi_c_frame.fp_save+(2*8)(sp))
+	__(stfd f4,varargs_eabi_c_frame.fp_save+(3*8)(sp))
+	__(stfd f5,varargs_eabi_c_frame.fp_save+(4*8)(sp))
+	__(stfd f6,varargs_eabi_c_frame.fp_save+(5*8)(sp))
+	__(stfd f7,varargs_eabi_c_frame.fp_save+(6*8)(sp))
+	__(stfd f8,varargs_eabi_c_frame.fp_save+(7*8)(sp))
+	__(la r0,varargs_eabi_c_frame.incoming_stack_args(sp))
+	__(str(r0,varargs_eabi_c_frame.overflow_arg_area(sp)))
+	__(la r0,varargs_eabi_c_frame.regsave(sp))
+	__(str(r0,varargs_eabi_c_frame.reg_save_area(sp)))
+	__(li r0,0)
+	__(str(r0,varargs_eabi_c_frame.flags(sp)))
+
+	/* Save the non-volatile registers on the sp stack  */
+	/* This is a non-standard stack frame, but noone will ever see it,  */
+        /* so it doesn't matter. It will look like more of the stack frame pushed below.  */
+	__(stru(sp,-(c_reg_save.size)(sp)))
+        __(str(r13,c_reg_save.save_gprs+(0*node_size)(sp)))
+        __(str(r14,c_reg_save.save_gprs+(1*node_size)(sp)))
+        __(str(r15,c_reg_save.save_gprs+(2*node_size)(sp)))
+        __(str(r16,c_reg_save.save_gprs+(3*node_size)(sp)))
+        __(str(r17,c_reg_save.save_gprs+(4*node_size)(sp)))
+        __(str(r18,c_reg_save.save_gprs+(5*node_size)(sp)))
+        __(str(r19,c_reg_save.save_gprs+(6*node_size)(sp)))
+        __(str(r20,c_reg_save.save_gprs+(7*node_size)(sp)))
+        __(str(r21,c_reg_save.save_gprs+(8*node_size)(sp)))
+        __(str(r22,c_reg_save.save_gprs+(9*node_size)(sp)))
+        __(str(r23,c_reg_save.save_gprs+(10*node_size)(sp)))
+        __(str(r24,c_reg_save.save_gprs+(11*node_size)(sp)))
+        __(str(r25,c_reg_save.save_gprs+(12*node_size)(sp)))
+        __(str(r26,c_reg_save.save_gprs+(13*node_size)(sp)))
+        __(str(r27,c_reg_save.save_gprs+(14*node_size)(sp)))
+        __(str(r28,c_reg_save.save_gprs+(15*node_size)(sp)))
+        __(str(r29,c_reg_save.save_gprs+(16*node_size)(sp)))
+        __(str(r30,c_reg_save.save_gprs+(17*node_size)(sp)))
+        __(str(r31,c_reg_save.save_gprs+(18*node_size)(sp)))
+	__(mffs f0)
+	__(stfd f0,c_reg_save.save_fp_zero(sp))
+	__(ldr(r31,c_reg_save.save_fp_zero+4(sp)))	/* recover FPSCR image  */
+	__(str(r31,c_reg_save.save_fpscr(sp)))
+	__(lwi(r30,0x43300000))
+	__(lwi(r31,0x80000000))
+	__(str(r30,c_reg_save.save_fp_zero(sp)))
+	__(str(r31,c_reg_save.save_fp_zero+4(sp)))
+	__(stfd fp_s32conv,c_reg_save.save_fps32conv(sp))
+	__(lfd fp_s32conv,c_reg_save.save_fp_zero(sp))
+	__(stfd fp_zero,c_reg_save.save_fp_zero(sp))
+	__(lfs fp_zero,lisp_globals.short_float_zero(0))	/* ensure that fp_zero contains 0.0  */
+
+	
+/* Restore rest of Lisp context.  */
+/* Could spread out the memory references here to gain a little speed  */
+	__(li loc_pc,0)
+	__(li fn,0)                     /* subprim, not a lisp function  */
+	__(li temp3,0)
+	__(li temp2,0)
+	__(li temp1,0)
+	__(li temp0,0)
+	__(li arg_x,0)
+	__(box_fixnum(arg_y,r11))	/* callback-index  */
+	__(la arg_z,c_reg_save.size+varargs_eabi_c_frame.gp_save(sp))	/* parameters (tagged as a fixnum)  */
+
+	/* Recover lisp thread context. Have to call C code to do so.  */
+	__(ref_global(r12,get_tcr))
+	__(mtctr r12)
+        __(li r3,1)
+	__(stru(sp,-(stack_align(eabi_c_frame.minsiz))(sp)))
+	__(bctrl)
+	__(la sp,(stack_align(eabi_c_frame.minsiz))(sp))
+	__(la rcontext,TCR_BIAS(r3))
+	__(li allocptr,0)
+	__(li allocbase,0)
+	__(ldr(vsp,tcr.save_vsp(rcontext)))
+	__(ldr(tsp,tcr.save_tsp(rcontext)))		
+	__(li rzero,0)
+	__(mtxer rzero) /* lisp wants the overflow bit clear  */
+	__(li imm0,TCR_STATE_LISP)
+	__(li save0,0)
+	__(li save1,0)
+	__(li save2,0)
+	__(li save3,0)
+	__(li save4,0)
+	__(li save5,0)
+	__(li save6,0)
+	__(li save7,0)
+        __(mtctr rzero)
+	__(str(imm0,tcr.valence(rcontext)))
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+	__(lfd f0,tcr.lisp_fpscr(rcontext))
+	__(mtfsf 0xff,f0)
+
+        __(restore_saveregs(vsp))        
+	/* load nargs and callback to the lisp  */
+	__(set_nargs(2))
+	__(ldr(imm2,tcr.cs_area(rcontext)))
+	__(ldr(imm4,area.active(imm2)))
+	__(stru(imm4,-lisp_frame.size(sp)))
+	__(str(imm3,lisp_frame.savelr(sp)))
+	__(str(vsp,lisp_frame.savevsp(sp)))	/* for stack overflow code  */
+	__(li fname,nrs.callbacks)	/* %pascal-functions%  */
+	__(call_fname)
+	__(ldr(imm2,lisp_frame.backlink(sp)))
+	__(ldr(imm3,tcr.cs_area(rcontext)))
+	__(str(imm2,area.active(imm3)))
+	__(discard_lisp_frame())
+	/* save_vsp will be restored from ff_call's stack frame, but  */
+	/* I included it here for consistency.  */
+	/* save_tsp is set below after we exit Lisp context.  */
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	/* Exit lisp context  */
+	/* This is not necessary yet, but will be once we can be interrupted  */
+	__(li imm1,TCR_STATE_FOREIGN)
+	__(str(imm1,tcr.valence(rcontext)))
+	/* Restore the non-volatile registers & fpscr  */
+	__(lfd fp_zero,c_reg_save.save_fp_zero(sp))
+	__(ldr(r31,c_reg_save.save_fpscr(sp)))
+	__(str(r31,c_reg_save.save_fp_zero+4(sp)))
+	__(lfd f0,c_reg_save.save_fp_zero(sp))
+	__(mtfsf 0xff,f0)
+	__(ldr(r13,c_reg_save.save_gprs+(0*node_size)(sp)))
+	__(ldr(r14,c_reg_save.save_gprs+(1*node_size)(sp)))
+	__(ldr(r15,c_reg_save.save_gprs+(2*node_size)(sp)))
+	__(ldr(r16,c_reg_save.save_gprs+(3*node_size)(sp)))
+	__(ldr(r17,c_reg_save.save_gprs+(4*node_size)(sp)))
+	__(ldr(r18,c_reg_save.save_gprs+(5*node_size)(sp)))
+	__(ldr(r19,c_reg_save.save_gprs+(6*node_size)(sp)))
+	__(ldr(r20,c_reg_save.save_gprs+(7*node_size)(sp)))
+	__(ldr(r21,c_reg_save.save_gprs+(8*node_size)(sp)))
+	__(ldr(r22,c_reg_save.save_gprs+(9*node_size)(sp)))
+	__(ldr(r23,c_reg_save.save_gprs+(10*node_size)(sp)))
+	__(ldr(r24,c_reg_save.save_gprs+(11*node_size)(sp)))
+	__(ldr(r25,c_reg_save.save_gprs+(12*node_size)(sp)))
+	__(ldr(r26,c_reg_save.save_gprs+(13*node_size)(sp)))
+	__(ldr(r27,c_reg_save.save_gprs+(14*node_size)(sp)))
+	__(ldr(r28,c_reg_save.save_gprs+(15*node_size)(sp)))
+	__(ldr(r29,c_reg_save.save_gprs+(16*node_size)(sp)))
+	__(ldr(r30,c_reg_save.save_gprs+(17*node_size)(sp)))
+	__(ldr(r31,c_reg_save.save_gprs+(18*node_size)(sp)))
+	__(lfd fp_s32conv,c_reg_save.save_fps32conv(sp))
+	__(ldr(sp,0(sp)))
+
+	__(ldr(r3,varargs_eabi_c_frame.gp_save+(0*4)(sp)))
+	__(ldr(r4,varargs_eabi_c_frame.gp_save+(1*4)(sp)))
+	__(lfd f1,varargs_eabi_c_frame.gp_save+(2*4)(sp))
+	__(ldr(r5,varargs_eabi_c_frame.savelr(sp)))
+	__(str(r5,varargs_eabi_c_frame.old_savelr(sp)))
+	__(mtlr r5)
+	__(ldr(r5,varargs_eabi_c_frame.backlink(sp)))
+	__(str(r5,varargs_eabi_c_frame.old_backlink(sp)))
+	__(la sp,varargs_eabi_c_frame.old_backlink(sp))
+	__(blr)
+	
+
+/*	Do a linux system call:	 the system call index is (boxed) */
+/*	in arg_z, and other arguments are in an eabi_c_frame on */
+/*	the C stack.  As is the case with an eabi_ff_call, there's */
+/*	a lisp frame reserved underneath the eabi_c_frame. */
+
+/*	This is a little simpler than eabi_ff_call, because we */
+/*	can assume that there are no synchronous callbacks to */
+/*	lisp (that might cause a GC.)  It's also simpler for the */
+/*	caller, since we return error status atomically. */
+
+/*	A system call can clobber any or all of r9-r12, so we need */
+/*	to save and restore allocptr, allocbase, and tsp. */
+	
+_spentry(eabi_syscall)
+/*	We're entered with an eabi_c_frame on the C stack.  There's a */
+/*	lisp_frame reserved underneath it; we'll link it in in a minute. */
+/*	Load the outgoing GPR arguments from eabi_c_frame.param[0-7], */
+/*	then shrink the eabi_c_frame. */
+
+	__(mflr loc_pc)
+        __(vpush_saveregs())
+	__(str(sp,eabi_c_frame.savelr(sp)))
+	__(li arg_x,nil_value)
+	__(mr temp0,rcontext)
+	__(ldr(temp1,c_frame.backlink(sp)))	/* bottom of reserved lisp frame  */
+	__(la temp2,-lisp_frame.size(temp1))	/* top of lisp frame  */
+        __(zero_doublewords temp2,0,lisp_frame.size)
+	__(str(temp1,lisp_frame.backlink(temp2)))
+	__(str(temp2,c_frame.backlink(sp)))
+	__(str(fn,lisp_frame.savefn(temp2)))
+	__(str(loc_pc,lisp_frame.savelr(temp2)))
+	__(str(vsp,lisp_frame.savevsp(temp2)))
+	__(ldr(temp3,tcr.cs_area(rcontext)))
+	__(str(temp2,area.active(temp3)))
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+	__(str(rzero,tcr.ffi_exception(rcontext)))
+	__(li imm1,TCR_STATE_FOREIGN)
+	__(str(imm1,tcr.valence(rcontext)))
+	__(ldr(r13,lisp_globals.saveR13(0)))
+	__(ldr(r3,eabi_c_frame.param0(sp)))
+	__(ldr(r4,eabi_c_frame.param1(sp)))
+	__(ldr(r5,eabi_c_frame.param2(sp)))
+	__(ldr(r6,eabi_c_frame.param3(sp)))
+	__(ldr(r7,eabi_c_frame.param4(sp)))
+	__(ldr(r8,eabi_c_frame.param5(sp)))
+	__(ldr(r9,eabi_c_frame.param6(sp)))
+	__(ldr(r10,eabi_c_frame.param7(sp)))
+	__(la temp1,eabi_c_frame.minsiz-eabi_c_frame.param0(sp))
+	__(str(rzero,eabi_c_frame.savelr(temp1)))
+	__(str(temp2,eabi_c_frame.backlink(temp1)))
+	__(mr sp,temp1)
+	__(unbox_fixnum(r0,arg_z))
+	__(sc)
+	__(nop)
+	/* C should have preserved temp0 (= rcontext) for us.  */
+	__(ldr(sp,0(sp)))
+	__(mr imm2,temp0)
+	__(ldr(vsp,lisp_frame.savevsp(sp)))
+	__(li rzero,0)
+	__(mr loc_pc,rzero)
+	__(mr fn,rzero)
+	__(li arg_x,nil_value)
+	__(li arg_y,nil_value)
+	__(li arg_z,nil_value)
+	__(li temp0,nil_value)
+	__(li temp1,nil_value)
+	__(li temp2,nil_value)
+	__(li temp3,nil_value)
+	__(li fn,nil_value)
+        
+	__(li imm3,TCR_STATE_LISP)
+	__(mr rcontext,imm2)
+        __(li save0,0)
+        __(li save1,0)
+        __(li save2,0)
+        __(li save3,0)
+        __(li save4,0)
+        __(li save5,0)
+        __(li save6,0)
+        __(li save7,0)        
+	__(str(imm3,tcr.valence(rcontext)))
+	__(vpop_saveregs)
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+	__(ldr(tsp,tcr.save_tsp(rcontext)))
+	__(ldr(loc_pc,lisp_frame.savelr(sp)))
+	__(mtlr loc_pc)
+	__(ldr(fn,lisp_frame.savefn(sp)))
+	__(discard_lisp_frame())
+	__(bns 1f)
+	__(neg r3,r3)
+1:      
+	__(check_pending_interrupt([cr1]))                
+	__(mtxer rzero)
+	__(blr)
+        
+/* arg_z should be of type (UNSIGNED-BYTE 64);  */
+/* On PPC32, return high 32 bits in imm0, low 32 bits in imm1 */
+/* On PPC64, return unboxed value in imm0  */
+
+_spentry(getu64)
+        __ifdef([PPC64])
+        __(extract_typecode(imm0,arg_z))
+        __(cmpdi cr0,imm0,tag_fixnum)
+        __(cmpdi cr2,arg_z,0)
+        __(cmpdi cr1,imm0,subtag_bignum)
+        __(bne cr0,1f)
+        __(unbox_fixnum(imm0,arg_z))
+        __(bgelr cr2)
+0:             
+	__(uuo_interr(error_object_not_u64,arg_z))
+        
+1:      __(bne cr1,0b)
+        __(getvheader(imm1,arg_z))
+        __(ld imm0,misc_data_offset(arg_z))
+        __(cmpdi cr2,imm1,two_digit_bignum_header)
+        __(rotldi imm0,imm0,32)
+        __(cmpdi cr1,imm1,three_digit_bignum_header)
+        __(cmpdi cr0,imm0,0)
+        __(beq cr2,2f)
+        __(lwz imm1,misc_data_offset+8(arg_z))
+        __(bne cr1,0b)
+        __(cmpwi imm1,0)
+        __(bne 0b)
+        __(blr)
+2:      __(blt 0b)
+        __(blr)        
+        __else
+	__(extract_typecode(imm0,arg_z))
+	__(cmpri(cr0,imm0,tag_fixnum))
+	__(cmpri(cr1,arg_z,0))
+	__(cmpri(cr2,imm0,subtag_bignum))
+	__(unbox_fixnum(imm1,arg_z))
+	__(bne cr0,8f)
+	__(bgelr cr1)
+9:
+	__(uuo_interr(error_object_not_u64,arg_z))
+8:
+	__(bne- cr2,9b)
+	__(getvheader(imm2,arg_z))
+	__(cmpri(cr2,imm2,two_digit_bignum_header))
+	__(vrefr(imm1,arg_z,0))
+	__(cmpri(cr1,imm1,0))
+	__(li imm0,0)
+	__(bge cr2,2f)
+	__(blt- cr1,9b)
+	__(blr)
+2:
+	__(cmpri(cr0,imm2,three_digit_bignum_header))
+	__(vrefr(imm0,arg_z,1))
+	__(cmpri(cr1,imm0,0))
+	__(bne cr2,3f)
+	__(blt- cr1,9b)
+	__(blr)
+3:
+	__(vrefr(imm2,arg_z,2))
+	__(cmpri(cr1,imm2,0))
+	__(bne- cr0,9b)
+	__(bne- cr1,9b)
+	__(blr)
+        __endif
+        
+/* arg_z should be of type (SIGNED-BYTE 64);  */
+/* PPC32:   return high 32 bits  in imm0, low 32 bits in imm1  */
+/* PPC64:   return unboxed value in imm0  */
+
+_spentry(gets64)
+        __ifdef([PPC64])
+	 __(extract_typecode(imm1,arg_z))
+         __(unbox_fixnum(imm0,arg_z))
+	 __(cmpri(cr0,imm1,tag_fixnum))
+	 __(cmpri(cr2,imm1,subtag_bignum))
+         __(beqlr cr0)
+         __(bne cr2,9f)
+         __(ld imm1,misc_header_offset(arg_z))
+         __(ld imm0,misc_data_offset(arg_z))
+         __(cmpdi imm1,two_digit_bignum_header)
+         __(rotldi imm0,imm0,32)
+         __(beqlr)
+        __else
+	 __(extract_typecode(imm0,arg_z))
+	 __(cmpri(cr0,imm0,tag_fixnum))
+	 __(cmpri(cr2,imm0,subtag_bignum))
+	 __(unbox_fixnum(imm1,arg_z))
+	 __(srawi imm0,imm1,31)
+	 __(beqlr cr0)
+	 __(bne cr2,9f)
+	 __(getvheader(imm2,arg_z))
+	 __(cmpri(cr2,imm2,two_digit_bignum_header))
+	 __(vrefr(imm1,arg_z,0))
+	 __(srawi imm0,imm1,31)
+	 __(bltlr cr2)
+	 __(vrefr(imm0,arg_z,1))
+	 __(beqlr cr2)
+        __endif
+9:
+	__(uuo_interr(error_object_not_s64,arg_z))
+
+
+/*  Construct a lisp integer out of the 64-bit unsigned value in */
+/*        ppc32:    imm0 (high 32 bits) and imm1 (low 32 bits) */
+/*        ppc64:    imm0 (64 bits) .  */
+_spentry(makeu64)
+        __ifdef([PPC64])
+	 __(clrrdi. imm1,imm0,63-nfixnumtagbits)
+	 __(cmpri(cr1,imm0,0))
+	 __(box_fixnum(arg_z,imm0))
+	 __(beqlr cr0) /* A fixnum  */
+         __(rotldi imm1,imm0,32)
+	 __(li imm2,two_digit_bignum_header)
+	 __(blt cr1,2f)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(2)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+	 __(blr)
+2:
+	 __(li imm2,three_digit_bignum_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(3)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+	 __(blr)
+        __else        
+ 	 __(cmpri(cr1,imm0,0))
+	 __(rlwinm. imm2,imm1,0,0,fixnum_shift)
+	 __(li imm2,three_digit_bignum_header)
+	 __(box_fixnum(arg_z,imm1))
+	 __(blt cr1,3f)
+	 __(bne cr1,2f)
+	 __(beqlr cr0) /* A fixnum  */
+	 __(blt cr0,2f)
+	 __(li imm2,one_digit_bignum_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(1)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+	 __(blr)
+2:
+	 __(li imm2,two_digit_bignum_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(2)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+	 __(str(imm0,misc_data_offset+4(arg_z)))
+	 __(blr)
+3:
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(3)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+	 __(str(imm0,misc_data_offset+4(arg_z)))
+	 __(blr)
+        __endif
+
+
+
+/*  Construct a lisp integer out of the 64-bit signed value in */
+/*        ppc32:    imm0 (high 32 bits) and imm1 (low 32 bits). */
+/*        ppc64:    imm0  */
+_spentry(makes64)
+        __ifdef([PPC64])
+	 __(addo imm1,imm0,imm0)
+         __(addo imm1,imm1,imm1)
+	 __(addo. arg_z,imm1,imm1)
+	 __(bnslr+)
+	 __(mtxer rzero)
+	 __(li imm1,two_digit_bignum_header)
+         __(rotldi imm0,imm0,32)
+	 __(Misc_Alloc_Fixed(arg_z,imm1,aligned_bignum_size(2)))
+	 __(str(imm0,misc_data_offset(arg_z)))
+         __(blr)
+        __else
+	 __(srawi imm2,imm1,31)
+	 __(cmpr(cr1,imm2,imm0))
+	 __(addo imm2,imm1,imm1)
+	 __(addo. arg_z,imm2,imm2)
+	 __(bne cr1,2f) /* High word is significant  */
+	 __(li imm2,one_digit_bignum_header)
+	 __(bnslr cr0) /* No overflow:	 fixnum  */
+	 __(mtxer rzero)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(1)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+	 __(blr)
+2:
+	 __(mtxer rzero)
+	 __(li imm2,two_digit_bignum_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(2)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+	 __(str(imm0,misc_data_offset+4(arg_z)))
+	 __(blr)
+        __endif
+
+/* imm0:imm1 constitute an unsigned integer, almost certainly a bignum. */
+/* Make a lisp integer out of those 128 bits ..  */
+_spentry(makeu128)
+        __ifdef([PPC64])
+         __(cmpdi imm0,0)
+         __(cmpdi cr1,imm1,0)
+         __(srdi imm3,imm0,32)
+         __(srawi imm4,imm0,31)
+         __(cmpdi cr3,imm3,0)
+         __(cmpdi cr4,imm4,0)
+         __(li imm2,five_digit_bignum_header)
+         __(blt cr1,0f)
+         __(beq 3f)
+0:              
+         __(bge 1f)
+         /* All 128 bits are significant, and the most significant */
+         /* bit is set.  Allocate a 5-digit bignum (with a zero */
+         /* sign digit  */
+         __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(5)))
+         __(rotldi imm0,imm0,32)
+         __(rotldi imm1,imm1,32)
+         __(std imm1,misc_data_offset(arg_z))
+         __(std imm0,misc_data_offset+8(arg_z))
+         __(blr)
+1:       /* If the high word of imm0 is a zero-extension of the low */
+         /* word, we only need 3 digits ; otherwise, we need 4.  */
+         __(li imm2,three_digit_bignum_header)
+         __(rotldi imm1,imm1,32)
+         __(bne cr3,2f) /* high word of imm0 is non-zero  */
+         __(bne cr4,2f) /* sign bit is on in low word of imm0  */
+         __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(3)))
+         __(std imm1,misc_data_offset(arg_z))
+         __(stw imm0,misc_data_offset+8(arg_z))
+         __(blr)
+2:       __(li imm2,four_digit_bignum_header)
+         __(rotldi imm0,imm0,32)
+         __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(4)))
+         __(std imm1,misc_data_offset(arg_z))
+         __(std imm0,misc_data_offset+8(arg_z))
+         __(blr)
+3:       __(mr imm0,imm1)
+         __(b _SPmakeu64)              
+        __else
+         __(twgei r0,r0)
+        __endif
+
+/* imm0:imm1 constitute a signed integer, almost certainly a bignum. */
+/* Make a lisp integer out of those 128 bits ..  */
+_spentry(makes128)
+        __ifdef([PPC64])
+         /* Is imm0 just a sign-extension of imm1 ?  */
+         __(sradi imm2,imm1,63)
+         /* Is the high word of imm0 just a sign-extension of the low word ?  */
+         __(extsw imm3,imm0)
+         __(cmpd imm2,imm0)
+         __(cmpd cr1,imm3,imm0)
+         __(beq 2f)
+         __(rotldi imm0,imm0,32)
+         __(rotldi imm1,imm1,32)
+         __(beq cr1,1f)
+         __(li imm2,four_digit_bignum_header)
+         __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(4)))
+         __(std imm1,misc_data_offset(arg_z))
+         __(std imm0,misc_data_offset+8(arg_z))
+         __(blr)
+1:       __(li imm2,three_digit_bignum_header)
+         __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(3)))
+         __(std imm1,misc_data_offset(arg_z))
+         __(stw imm3,misc_data_offset+8(arg_z))
+         __(blr)
+2:       __(mr imm0,imm1)
+         __(b _SPmakes64)        
+        __else
+         __(twgei r0,r0)
+        __endif        
+                        
+/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
+/* unbound_marker), arg_y = symbol, imm3 = symbol.binding-index  */
+_spentry(specref)
+        __(ldr(imm3,symbol.binding_index(arg_z)))
+        __(ldr(imm0,tcr.tlb_limit(rcontext)))
+        __(cmpr(imm3,imm0))
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(mr arg_y,arg_z)
+        __(bge 1f)
+        __(ldrx(arg_z,imm2,imm3))
+        __(cmpri(arg_z,no_thread_local_binding_marker))
+        __(bnelr)
+1:     	__(ldr(arg_z,symbol.vcell(arg_y)))
+        __(blr)
+
+
+_spentry(specrefcheck)
+        __(ldr(imm3,symbol.binding_index(arg_z)))
+        __(ldr(imm0,tcr.tlb_limit(rcontext)))
+        __(cmpr(imm3,imm0))
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(mr arg_y,arg_z)
+        __(bge 1f)
+        __(ldrx(arg_z,imm2,imm3))
+        __(cmpri(arg_z,no_thread_local_binding_marker))
+        __(bne 2f)
+1:     	__(ldr(arg_z,symbol.vcell(arg_y)))
+2:      __(treqi(arg_z,unbound_marker))
+        __(blr)
+	
+/* arg_y = special symbol, arg_z = new value.          */
+_spentry(specset)
+        __(ldr(imm3,symbol.binding_index(arg_y)))
+        __(ldr(imm0,tcr.tlb_limit(rcontext)))
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(cmpr(imm3,imm0))
+        __(bge 1f)
+        __(ldrx(temp1,imm2,imm3))
+        __(cmpri(temp1,no_thread_local_binding_marker))
+        __(beq 1f)
+        __(strx(arg_z,imm2,imm3))
+        __(blr)
+1:     	__(mr arg_x,arg_y)
+        __(li arg_y,symbol.vcell-misc_data_offset)
+        __(b _SPgvset)
+
+/* Restore current thread's interrupt level to arg_z, */
+/* noting whether the tcr's interrupt_pending flag was set.  */
+_spentry(restoreintlevel)
+	__(cmpri(cr1,arg_z,0))
+	__(ldr(imm0,tcr.interrupt_pending(rcontext)))
+	__(cmpri(cr0,imm0,0))
+	__(bne cr1,1f)
+	__(beq cr0,1f)
+	__(str(rzero,tcr.interrupt_pending(rcontext)))
+	__(li nargs,fixnum_one)
+	__(trgti(nargs,0))
+	__(blr)
+1:
+        __(ldr(nargs,tcr.tlb_pointer(rcontext)))
+	__(str(arg_z,INTERRUPT_LEVEL_BINDING_INDEX(nargs)))
+	__(blr)
+
+
+/* Construct a lisp integer out of the 32-bit signed value in imm0 */
+
+        
+_spentry(makes32)
+        __ifdef([PPC64])
+         __(box_fixnum(arg_z,imm0))
+        __else
+	 __(addo imm1,imm0,imm0)
+	 __(addo. arg_z,imm1,imm1)
+	 __(bnslr+)
+	 __(mtxer rzero)
+	 __(li imm1,one_digit_bignum_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm1,aligned_bignum_size(1)))
+	 __(str(imm0,misc_data_offset(arg_z)))
+        __endif
+	 __(blr)
+
+
+/* Construct a lisp integer out of the 32-bit unsigned value in imm0 */
+
+        
+_spentry(makeu32)
+        __ifdef([PPC64])
+         __(box_fixnum(arg_z,imm0))
+         __(blr)
+        __else
+	 __(clrrwi. imm1,imm0,31-nfixnumtagbits)
+	 __(cmpri(cr1,imm0,0))
+	 __(box_fixnum(arg_z,imm0))
+	 __(beqlr cr0) /* A fixnum  */
+	 __(blt cr1,2f)
+	 __(li imm2,one_digit_bignum_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(1)))
+	 __(str(imm0,misc_data_offset(arg_z)))
+	 __(blr)
+2:
+	 __(li imm2,two_digit_bignum_header)
+	 __(Misc_Alloc_Fixed(arg_z,imm2,aligned_bignum_size(2)))
+	 __(str(imm0,misc_data_offset(arg_z)))
+	 __(blr)
+        __endif
+
+/*  */
+/* arg_z should be of type (SIGNED-BYTE 32); return unboxed result in imm0 */
+/*  */
+_spentry(gets32)
+        __ifdef([PPC64])
+         __(sldi imm1,arg_z,32-fixnumshift)
+         __(extract_lisptag_(imm0,arg_z))
+         __(sradi imm1,imm1,32-fixnumshift)
+         __(box_fixnum(imm0,arg_z))
+         __(cmpd cr1,imm1,arg_z)
+         __(bne cr0,9f)
+         __(beqlr cr1)
+         __(b 9f)
+        __else
+	 __(extract_typecode(imm1,arg_z))
+	 __(cmpri(cr0,imm1,tag_fixnum))
+	 __(cmpri(cr2,imm1,subtag_bignum))
+	 __(unbox_fixnum(imm0,arg_z))
+	 __(beqlr+ cr0)
+	 __(bne cr2,9f)
+	 __(getvheader(imm1,arg_z))
+	 __(cmpri(cr1,imm1,one_digit_bignum_header))
+	 __(vrefr(imm0,arg_z,0))
+	 __(beqlr+ cr1)
+        __endif
+9:
+	__(uuo_interr(error_object_not_signed_byte_32,arg_z))
+
+/*  */
+/* arg_z should be of type (UNSIGNED-BYTE 32); return unboxed result in imm0 */
+/*  */
+
+_spentry(getu32)
+	__(extract_typecode(imm1,arg_z))
+	__(cmpri(cr0,imm1,tag_fixnum))
+	__(cmpri(cr1,arg_z,0))
+	__(cmpri(cr2,imm1,subtag_bignum))
+	__(unbox_fixnum(imm0,arg_z))
+	__(bne cr0,8f)
+	__(bgelr cr1)
+8:
+	__(bne- cr2,9f)
+	__(getvheader(imm2,arg_z))
+	__(cmpri(cr2,imm2,two_digit_bignum_header))
+	__(vrefr(imm0,arg_z,0))
+	__(cmpri(cr0,imm0,0))
+	__(bgt cr2,9f)
+	__(beq cr2,2f)
+	__(blt cr0,9f)
+	__(blr)
+2:
+	__(vrefr(imm1,arg_z,1))
+	__(cmpri(cr0,imm1,0))
+	__(beqlr+ cr0)
+
+9:
+	__(uuo_interr(error_object_not_unsigned_byte_32,arg_z))
+
+/* */
+/* arg_z has overflowed (by one bit) as the result of an addition or subtraction. */
+/* Make a bignum out of it. */
+
+_spentry(fix_overflow)
+	__(mtxer rzero)
+	__(unbox_fixnum(imm1,arg_z))
+        __ifdef([PPC64])
+	 __(li imm0,two_digit_bignum_header)
+         __(rotldi imm1,imm1,32)
+	 __(xoris imm1,imm1,0xe000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(2)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __else
+	 __(li imm0,one_digit_bignum_header)
+	 __(xoris imm1,imm1,0xc000)
+	 __(Misc_Alloc_Fixed(arg_z,imm0,aligned_bignum_size(1)))
+	 __(str(imm1,misc_data_offset(arg_z)))
+        __endif
+	__(blr)
+		
+
+
+/* */
+/* As per mvpass above, but in this case fname is known to be a */
+/* symbol. */
+
+_spentry(mvpasssym)
+	__(cmpri(cr0,nargs,node_size*nargregs))
+	__(mflr loc_pc)
+	__(mr imm0,vsp)
+	__(ble+ cr0,1f)
+	 __(subi imm0,imm0,node_size*nargregs)
+	 __(add imm0,imm0,nargs)
+1:            
+	__(build_lisp_frame(fn,loc_pc,imm0))
+	__(ref_global(loc_pc,ret1val_addr))
+	__(li fn,0)
+	__(mtlr loc_pc)
+	__(jump_fname())
+
+
+
+_spentry(unbind)
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))   
+        __(ldr(imm3,binding.sym(imm1)))
+        __(ldr(temp1,binding.val(imm1)))
+        __(ldr(imm1,binding.link(imm1)))
+        __(strx(temp1,imm2,imm3))
+        __(str(imm1,tcr.db_link(rcontext)))
+        __(blr)
+
+_spentry(unbind_n)
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))   
+1:      __(subi imm0,imm0,1)
+        __(ldr(imm3,binding.sym(imm1)))
+        __(ldr(temp1,binding.val(imm1)))
+        __(cmpri(imm0,0))
+        __(ldr(imm1,binding.link(imm1)))
+        __(strx(temp1,imm2,imm3))
+        __(bne 1b)
+        __(str(imm1,tcr.db_link(rcontext)))
+        __(blr)
+
+/* */
+/* Clobbers imm1,imm2,imm5,arg_x, arg_y */
+
+_spentry(unbind_to)
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+1:      __(ldr(imm5,binding.sym(imm1)))
+        __(ldr(arg_y,binding.val(imm1)))
+        __(ldr(imm1,binding.link(imm1)))
+        __(cmpr(imm0,imm1))
+        __(strx(arg_y,imm2,imm5))
+        __(bne 1b)
+        __(str(imm1,tcr.db_link(rcontext)))
+        __(blr)
+	
+
+
+/* */
+/* Restore the special bindings from the top of the tstack,  */
+/* leaving the tstack frame allocated.  */
+/* Note that there might be 0 saved bindings, in which case  */
+/* do nothing.  */
+/* Note also that this is -only- called from an unwind-protect  */
+/* cleanup form, and that .SPnthrowXXX is keeping one or more  */
+/* values in a frame on top of the tstack.  */
+/*  */
+                        
+_spentry(progvrestore)
+	__(ldr(imm0,tsp_frame.backlink(tsp)))	/* ignore .SPnthrowXXX values frame  */
+	__(ldr(imm0,tsp_frame.data_offset(imm0)))
+	__(cmpri(cr0,imm0,0))
+	__(unbox_fixnum(imm0,imm0))
+	__(bne+ cr0,_SPunbind_n)
+	__(blr)
+
+/* Bind CCL::*INTERRUPT-LEVEL* to 0.  If its value had been negative, check  */
+/* for pending interrupts after doing so.  "nargs" can be freely used for an */
+/* interrupt trap in this context.  */
+_spentry(bind_interrupt_level_0)
+        __(ldr(imm4,tcr.tlb_pointer(rcontext)))
+        __(ldr(temp0,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(cmpri(temp0,0))
+        __(li imm3,INTERRUPT_LEVEL_BINDING_INDEX)
+        __(vpush(temp0))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(str(rzero,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(str(vsp,tcr.db_link(rcontext)))
+        __(beqlr)
+        __(mr nargs,temp0)
+        __(bgt 1f)
+        __(ldr(nargs,tcr.interrupt_pending(rcontext)))
+1:      __(trgti(nargs,0))        
+        __(blr)
+
+/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect */
+/* of disabling interrupts.)  */
+_spentry(bind_interrupt_level_m1)
+        __(li imm2,-fixnumone)
+        __(li imm3,INTERRUPT_LEVEL_BINDING_INDEX)
+        __(ldr(imm4,tcr.tlb_pointer(rcontext)))
+        __(ldr(temp0,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(vpush(temp0))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(str(imm2,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(str(vsp,tcr.db_link(rcontext)))
+        __(blr)
+
+        
+/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
+/* do what _SPbind_interrupt_level_0 does  */
+_spentry(bind_interrupt_level)
+        __(cmpri(arg_z,0))
+        __(li imm3,INTERRUPT_LEVEL_BINDING_INDEX)
+        __(ldr(imm4,tcr.tlb_pointer(rcontext)))
+        __(ldr(temp0,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(beq _SPbind_interrupt_level_0)
+        __(vpush(temp0))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(str(arg_z,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(str(vsp,tcr.db_link(rcontext)))
+        __(blr)
+
+/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
+/* non-negative, check for pending interrupts.  This is often called in */
+/* a context where nargs is significant, so save and restore nargs around */
+/* any interrupt polling  */
+        
+_spentry(unbind_interrupt_level)
+        __(ldr(imm0,tcr.flags(rcontext)))
+        __(ldr(imm2,tcr.tlb_pointer(rcontext)))
+        __(andi. imm0,imm0,1<<TCR_FLAG_BIT_PENDING_SUSPEND)
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(ldr(temp1,INTERRUPT_LEVEL_BINDING_INDEX(imm2)))
+        __(bne 5f)
+0:      __(cmpri(cr1,temp1,0))
+        __(ldr(temp1,binding.val(imm1)))
+        __(ldr(imm1,binding.link(imm1)))
+        __(cmpri(cr0,temp1,0))
+        __(str(temp1,INTERRUPT_LEVEL_BINDING_INDEX(imm2)))
+        __(str(imm1,tcr.db_link(rcontext)))
+        __(bgelr cr1)
+        __(bltlr cr0)
+        __(mr imm2,nargs)
+        __(check_pending_interrupt([cr1]))
+        __(mr nargs,imm2)
+        __(blr)
+5:       /* Missed a suspend request; force suspend now if we're restoring
+          interrupt level to -1 or greater */
+        __(cmpri(temp1,-2<<fixnumshift))
+        __(bne 0b)
+        __(ldr(imm0,binding.val(imm1)))
+        __(cmpr(imm0,temp1))
+        __(beq 0b)
+        __(li imm0,1<<fixnumshift)
+        __(str(imm0,INTERRUPT_LEVEL_BINDING_INDEX(imm2)))
+        __(suspend_now())
+        __(b 0b)
+
+
+/* arg_x = array, arg_y = i, arg_z = j. Typecheck everything.
+   We don't know whether the array is alleged to be simple or
+   not, and don't know anythng about the element type.  */
+_spentry(aref2)
+        __(extract_typecode(imm2,arg_x))
+        __(trap_unless_lisptag_equal(arg_y,tag_fixnum,imm0))
+        __(cmpri(cr2,imm2,subtag_arrayH))
+        __(trap_unless_lisptag_equal(arg_z,tag_fixnum,imm0))
+        __(bne cr2,1f)
+        __(ldr(imm1,arrayH.rank(arg_x)))
+        __(cmpri(imm1,2<<fixnumshift))
+        __(bne 1f)
+        /* It's a 2-dimensional array.  Check bounds */
+        __(ldr(imm0,arrayH.dim0(arg_x)))
+        __(trlge(arg_y,imm0))
+        __(ldr(imm0,arrayH.dim0+node_size(arg_x)))
+        __(trlge(arg_z,imm0))
+        __(unbox_fixnum(imm0,imm0))
+        __(mullr(arg_y,arg_y,imm0))
+        __(add arg_z,arg_z,arg_y)
+        /* arg_z is now row-major-index; get data vector and
+           add in possible offset */
+        __(mr arg_y,arg_x)
+0:      __(ldr(imm0,arrayH.displacement(arg_y)))
+        __(ldr(arg_y,arrayH.data_vector(arg_y)))
+        __(extract_subtag(imm1,arg_y))
+        __(cmpri(imm1,subtag_vectorH))
+        __(add arg_z,arg_z,imm0)
+        __(bgt local_label(misc_ref_common))
+        __(b 0b)
+1:              
+        __(uuo_interr(error_object_not_array_2d,arg_x))
+
+/* temp0 = array, arg_x = i, arg_y = j, arg_z = k */
+_spentry(aref3)
+        __(extract_typecode(imm2,temp0))
+        __(trap_unless_lisptag_equal(arg_x,tag_fixnum,imm0))
+        __(cmpri(cr2,imm2,subtag_arrayH))
+        __(trap_unless_lisptag_equal(arg_y,tag_fixnum,imm0))
+        __(bne cr2,1f)
+        __(ldr(imm1,arrayH.rank(temp0)))
+        __(trap_unless_lisptag_equal(arg_z,tag_fixnum,imm0))
+        __(cmpri(imm1,3<<fixnumshift))
+        __(bne 1f)
+        /* It's a 3-dimensional array.  Check bounds */
+        __(ldr(imm2,arrayH.dim0+(node_size*2)(temp0)))
+        __(ldr(imm1,arrayH.dim0+node_size(temp0)))
+        __(ldr(imm0,arrayH.dim0(temp0)))
+        __(trlge(arg_z,imm2))
+        __(unbox_fixnum(imm2,imm2))
+        __(trlge(arg_y,imm1))
+        __(unbox_fixnum(imm1,imm1))
+        __(trlge(arg_x,imm0))
+        __(mullr(arg_y,arg_y,imm2))
+        __(mullr(imm1,imm2,imm1))
+        __(mullr(arg_x,imm1,arg_x))
+        __(add arg_z,arg_z,arg_y)
+        __(add arg_z,arg_z,arg_x)
+        __(mr arg_y,temp0)
+0:      __(ldr(arg_x,arrayH.displacement(arg_y)))
+        __(ldr(arg_y,arrayH.data_vector(arg_y)))
+        __(extract_subtag(imm1,arg_y))
+        __(cmpri(imm1,subtag_vectorH))
+        __(add arg_z,arg_x,arg_z)
+        __(bgt local_label(misc_ref_common))
+        __(b 0b)
+1:              
+        __(uuo_interr(error_object_not_array_3d,temp0))
+
+        
+        
+
+/* As for aref2 above, but temp = array, arg_x = i, arg_y = j, arg_z = newval */
+_spentry(aset2)
+        __(extract_typecode(imm2,temp0))
+        __(trap_unless_lisptag_equal(arg_x,tag_fixnum,imm0))
+        __(cmpri(cr2,imm2,subtag_arrayH))
+        __(trap_unless_lisptag_equal(arg_y,tag_fixnum,imm0))
+        __(bne cr2,1f)
+        __(ldr(imm1,arrayH.rank(temp0)))
+        __(cmpri(imm1,2<<fixnumshift))
+        __(bne 1f)
+        /* It's a 2-dimensional array.  Check bounds */
+        __(ldr(imm0,arrayH.dim0(temp0)))
+        __(trlge(arg_x,imm0))
+        __(ldr(imm0,arrayH.dim0+node_size(temp0)))
+        __(trlge(arg_y,imm0))
+        __(unbox_fixnum(imm0,imm0))
+        __(mullr(arg_x,arg_x,imm0))
+        __(add arg_y,arg_y,arg_x)
+        /* arg_y is now row-major-index; get data vector and
+           add in possible offset */
+        __(mr arg_x,temp0)
+0:      __(ldr(imm0,arrayH.displacement(arg_x)))
+        __(ldr(arg_x,arrayH.data_vector(arg_x)))
+        __(extract_subtag(imm1,arg_x))
+        __(cmpri(imm1,subtag_vectorH))
+        __(add arg_y,arg_y,imm0)
+        __(bgt local_label(misc_set_common))
+        __(b 0b)
+1:              
+        __(uuo_interr(error_object_not_array_2d,temp0))        
+                
+/* temp1 = array, temp0 = i, arg_x = j, arg_y = k, arg_z = new */        
+_spentry(aset3)
+        __(extract_typecode(imm2,temp1))
+        __(trap_unless_lisptag_equal(temp0,tag_fixnum,imm0))
+        __(cmpri(cr2,imm2,subtag_arrayH))
+        __(trap_unless_lisptag_equal(arg_x,tag_fixnum,imm0))
+        __(bne cr2,1f)
+        __(ldr(imm1,arrayH.rank(temp1)))
+        __(trap_unless_lisptag_equal(arg_y,tag_fixnum,imm0))
+        __(cmpri(imm1,3<<fixnumshift))
+        __(bne 1f)
+        /* It's a 3-dimensional array.  Check bounds */
+        __(ldr(imm2,arrayH.dim0+(node_size*2)(temp1)))
+        __(ldr(imm1,arrayH.dim0+node_size(temp1)))
+        __(ldr(imm0,arrayH.dim0(temp1)))
+        __(trlge(arg_y,imm2))
+        __(unbox_fixnum(imm2,imm2))
+        __(trlge(arg_x,imm1))
+        __(unbox_fixnum(imm1,imm1))
+        __(trlge(temp0,imm0))
+        __(mullr(arg_x,arg_x,imm2))
+        __(mullr(imm1,imm2,imm1))
+        __(mullr(temp0,imm1,temp0))
+        __(add arg_y,arg_y,arg_x)
+        __(add arg_y,arg_y,temp0)
+        __(mr arg_x,temp1)
+0:      __(ldr(temp0,arrayH.displacement(arg_x)))
+        __(ldr(arg_x,arrayH.data_vector(arg_x)))
+        __(extract_subtag(imm1,arg_x))
+        __(cmpri(imm1,subtag_vectorH))
+        __(add arg_y,arg_y,temp0)
+        __(bgt local_label(misc_set_common))
+        __(b 0b)
+1:              
+        __(uuo_interr(error_object_not_array_3d,temp1))
+
+
+        
+
+_spentry(nmkunwind)
+        __(li imm2,-fixnumone)
+        __(li imm3,INTERRUPT_LEVEL_BINDING_INDEX)
+        __(ldr(imm4,tcr.tlb_pointer(rcontext)))
+        __(ldr(arg_y,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(ldr(imm1,tcr.db_link(rcontext)))
+        __(vpush(arg_y))
+        __(vpush(imm3))
+        __(vpush(imm1))
+        __(str(imm2,INTERRUPT_LEVEL_BINDING_INDEX(imm4)))
+        __(str(vsp,tcr.db_link(rcontext)))
+	__(lwi(arg_z,unbound_marker))
+	__(li imm2,fixnum_one)
+	__(mkcatch())
+        __(mr arg_z,arg_y)
+        __(b _SPbind_interrupt_level)
+
+        .if 1
+        __ifdef([DARWIN])
+         __ifdef([PPC64])
+L_lisp_objc2_personality:       
+        __(ref_global(r12,objc_2_personality))
+        __(mtctr r12)
+        __(bctr)
+        .data
+        .globl _lisp_objc2_personality
+_lisp_objc2_personality: 
+        .quad L_lisp_objc2_personality
+	
+	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+	.set L$set$12,LECIE1-LSCIE1
+	.long L$set$12	/* Length of Common Information Entry */
+LSCIE1:
+	.long	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+	.ascii "zPLR\0"	/* CIE Augmentation */
+	.byte	0x1	/* uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x78	/* sleb128 -8; CIE Data Alignment Factor */
+	.byte	0x41	/* CIE RA Column */
+	.byte	0x7
+	.byte	0x9b
+	.long   _lisp_objc2_personality-.
+	.byte	0x10	/* LSDA Encoding (pcrel) */
+	.byte	0x10	/* FDE Encoding (pcrel) */
+	.byte	0xc
+	.byte	0x1
+	.byte	0x0
+	.align 3
+LECIE1:
+        .globl _SPffcall.eh
+_SPffcall.eh:
+        .set assembler_nonsense,LEFDEffcall-LSFDEffcall
+        .long assembler_nonsense
+LSFDEffcall:      
+        .long LSFDEffcall-EH_frame1 /* FDE CIE offset */
+        .quad Lffcall-. /* FDE Initial Location */
+        .quad Lffcall_end-Lffcall /* FDE address range */
+        .byte 8 /* uleb128 0x8; Augmentation size */
+        .quad LLSDA1-.           /* Language Specific Data Area */
+	.byte DW_CFA_def_cfa_offset 
+	.byte 0xc0,0x1 /* uleb128 0xc0.  A lie:  the frame is variable-length */
+	.byte DW_CFA_offset_extended_sf
+	.byte	0x41	
+	.byte	0x7e	/* sleb128 -2 */
+	.byte DW_CFA_advance_loc4
+	.long Lffcall_setup-Lffcall
+	.byte DW_CFA_advance_loc4
+	.long Lffcall_setup_end-Lffcall_setup
+	.byte DW_CFA_advance_loc4
+	.long Lffcall_call_end-Lffcall_call
+	.align 3
+LEFDEffcall:
+	
+        .globl _SPffcall_return_registers.eh
+_SPffcall_return_registers.eh:
+        .set Lfmh,LEFDEffcall_return_registers-LSFDEffcall_return_registers
+        .long Lfmh
+LSFDEffcall_return_registers:      
+        .long LSFDEffcall_return_registers-EH_frame1 /* FDE CIE offset */
+        .quad Lffcall_return_registers-. /* FDE Initial Location */
+        .quad Lffcall_return_registers_end-Lffcall_return_registers /* FDE address range */
+        .byte 8 /* uleb128 0x8; Augmentation size */
+        .quad LLSDA2-.           /* Language Specific Data Area */
+	.byte DW_CFA_def_cfa_offset 
+	.byte 0xc0,0x1 /* uleb128 0xc0.  A lie:  the frame is variable-length */
+	.byte DW_CFA_offset_extended_sf
+	.byte 0x41	
+	.byte 0x7e	/* sleb128 -2 */
+	.byte DW_CFA_advance_loc4
+	.long Lffcall_return_registers_setup-Lffcall_return_registers
+	.byte DW_CFA_advance_loc4
+	.long Lffcall_return_registers_setup_end-Lffcall_return_registers_setup
+	.byte DW_CFA_advance_loc4
+	.long Lffcall_return_registers_call_end-Lffcall_return_registers_call
+	.align 3
+LEFDEffcall_return_registers:
+        .text
+         __endif
+        __endif
+        .endif
+
+                                
+/*  EOF, basically  */
+        .globl _SPsp_end
+        b _SPsp_end
+	_endfile
Index: /branches/new-random/lisp-kernel/ppc-spjump.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-spjump.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-spjump.s	(revision 13309)
@@ -0,0 +1,191 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL.   */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence.   */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+        include(lisp.s)
+	_beginfile
+	
+define([_spjump],[
+        .align 2
+        .globl _SP$1
+_exportfn(j_SP$1)
+          __(b _SP$1)
+_endfn
+])
+         .org 0x5000-0x2000
+        /*	.align 12 */
+         .globl C(spjump_start)
+C(spjump_start):
+        _spjump(jmpsym)
+        _spjump(jmpnfn)
+        _spjump(funcall)
+        _spjump(mkcatch1v)
+        _spjump(mkunwind)
+        _spjump(mkcatchmv)
+        _spjump(throw)
+        _spjump(nthrowvalues)
+        _spjump(nthrow1value)
+        _spjump(bind)
+        _spjump(bind_self)
+        _spjump(bind_nil)
+        _spjump(bind_self_boundp_check)
+        _spjump(rplaca)
+        _spjump(rplacd)
+        _spjump(conslist)
+        _spjump(conslist_star)
+        _spjump(stkconslist)
+        _spjump(stkconslist_star)
+        _spjump(mkstackv)
+        _spjump(subtag_misc_ref)
+        _spjump(setqsym)
+        _spjump(progvsave)
+        _spjump(stack_misc_alloc)
+        _spjump(gvector)
+        _spjump(nvalret)
+        _spjump(mvpass)
+        _spjump(fitvals)
+        _spjump(nthvalue)
+        _spjump(values)
+        _spjump(default_optional_args)
+        _spjump(opt_supplied_p)
+        _spjump(heap_rest_arg)
+        _spjump(req_heap_rest_arg)
+        _spjump(heap_cons_rest_arg)
+        _spjump(simple_keywords)
+        _spjump(keyword_args)
+        _spjump(keyword_bind)
+        _spjump(poweropen_ffcall)
+        _spjump(aref2)
+        _spjump(ksignalerr)
+        _spjump(stack_rest_arg)
+        _spjump(req_stack_rest_arg)
+        _spjump(stack_cons_rest_arg)
+        _spjump(poweropen_callbackX)        
+        _spjump(call_closure)        
+        _spjump(getxlong)
+        _spjump(spreadargz)
+        _spjump(tfuncallgen)
+        _spjump(tfuncallslide)
+        _spjump(tfuncallvsp)
+        _spjump(tcallsymgen)
+        _spjump(tcallsymslide)
+        _spjump(tcallsymvsp)
+        _spjump(tcallnfngen)
+        _spjump(tcallnfnslide)
+        _spjump(tcallnfnvsp)
+        _spjump(misc_ref)
+        _spjump(misc_set)
+        _spjump(stkconsyz)
+        _spjump(stkvcell0)
+        _spjump(stkvcellvsp)      
+        _spjump(makestackblock)
+        _spjump(makestackblock0)
+        _spjump(makestacklist)
+        _spjump(stkgvector)
+        _spjump(misc_alloc)
+        _spjump(poweropen_ffcallX)
+        _spjump(gvset)
+        _spjump(macro_bind)
+        _spjump(destructuring_bind)
+        _spjump(destructuring_bind_inner)
+        _spjump(recover_values)
+        _spjump(vpopargregs)
+        _spjump(integer_sign)
+        _spjump(subtag_misc_set)
+        _spjump(spread_lexprz)
+        _spjump(store_node_conditional)
+        _spjump(reset)
+        _spjump(mvslide)
+        _spjump(save_values)
+        _spjump(add_values)
+        _spjump(poweropen_callback)
+        _spjump(misc_alloc_init)
+        _spjump(stack_misc_alloc_init)
+        _spjump(set_hash_key)
+        _spjump(aset2)
+        _spjump(callbuiltin)
+        _spjump(callbuiltin0)
+        _spjump(callbuiltin1)
+        _spjump(callbuiltin2)
+        _spjump(callbuiltin3)
+        _spjump(popj)
+        _spjump(restorefullcontext)
+        _spjump(savecontextvsp)
+        _spjump(savecontext0)
+        _spjump(restorecontext)
+        _spjump(lexpr_entry)
+        _spjump(poweropen_syscall)
+        _spjump(builtin_plus)
+        _spjump(builtin_minus)
+        _spjump(builtin_times)
+        _spjump(builtin_div)
+        _spjump(builtin_eq)
+        _spjump(builtin_ne)
+        _spjump(builtin_gt)
+        _spjump(builtin_ge)
+        _spjump(builtin_lt)
+        _spjump(builtin_le)
+        _spjump(builtin_eql)
+        _spjump(builtin_length)
+        _spjump(builtin_seqtype)
+        _spjump(builtin_assq)
+        _spjump(builtin_memq)
+        _spjump(builtin_logbitp)
+        _spjump(builtin_logior)
+        _spjump(builtin_logand)
+        _spjump(builtin_ash)
+        _spjump(builtin_negate)
+        _spjump(builtin_logxor)
+        _spjump(builtin_aref1)
+        _spjump(builtin_aset1)
+        _spjump(breakpoint)
+        _spjump(eabi_ff_call)
+        _spjump(eabi_callback)
+        _spjump(eabi_syscall)
+        _spjump(getu64)
+        _spjump(gets64)
+        _spjump(makeu64)
+        _spjump(makes64)
+        _spjump(specref)
+        _spjump(specset)
+        _spjump(specrefcheck)
+        _spjump(restoreintlevel)
+        _spjump(makes32)
+        _spjump(makeu32)
+        _spjump(gets32)
+        _spjump(getu32)
+        _spjump(fix_overflow)
+        _spjump(mvpasssym)
+        _spjump(aref3)
+        _spjump(aset3)
+        _spjump(poweropen_ffcall_return_registers)
+        _spjump(nmkunwind)
+        _spjump(set_hash_key_conditional)
+        _spjump(unbind_interrupt_level)
+        _spjump(unbind)
+        _spjump(unbind_n)
+        _spjump(unbind_to)
+        _spjump(bind_interrupt_level_m1)
+        _spjump(bind_interrupt_level)
+        _spjump(bind_interrupt_level_0)
+        _spjump(progvrestore)
+          .globl C(spjump_end)
+C(spjump_end):
+	__ifdef([DARWIN])
+	 __ifdef([PPC64])
+           .org 0x5000-0x1000
+	 __endif
+	__endif
+        _endfile
+        
Index: /branches/new-random/lisp-kernel/ppc-subprims.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-subprims.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-subprims.s	(revision 13309)
@@ -0,0 +1,241 @@
+/*   Copyright (C) 2009 Clozure Associates */
+/*   Copyright (C) 1994-2001 Digitool, Inc */
+/*   This file is part of Clozure CL.  */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence.   */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+
+	include(lisp.s)
+	_beginfile
+
+	.globl _SPmkcatch1v
+	.globl _SPnthrow1value
+
+
+/* This is called from a c-style context and calls a lisp function. */
+/* This does the moral equivalent of */
+/*   (loop  */
+/*	(let* ((fn (%function_on_top_of_lisp_stack))) */
+/*	  (if fn */
+/*           (catch %toplevel-catch% */
+/*	       (funcall fn)) */
+/*            (return nil)))) */
+
+_exportfn(toplevel_loop)
+	__(mflr imm0)
+        __ifdef([POWEROPENABI])
+	 __(str(imm0,c_frame.savelr(sp)))
+        __else
+	 __(str(imm0,eabi_c_frame.savelr(sp)))
+        __endif
+	__(b local_label(test))
+local_label(loop):
+	__(ref_nrs_value(arg_z,toplcatch))
+	__(bl _SPmkcatch1v)
+	__(b local_label(test))			/* cleanup address, not really a branch */
+
+	__(set_nargs(0))
+	__(bl _SPfuncall)
+	__(li arg_z,nil_value)
+	__(li imm0,fixnum_one)
+	__(bl _SPnthrow1value)
+local_label(test):
+	__(ldr(temp0,0(vsp)))
+	__(cmpri(cr0,temp0,nil_value))
+	__(bne cr0,local_label(loop))
+local_label(back_to_c):
+        __ifdef([POWEROPENABI])
+	 __(ldr(imm0,c_frame.savelr(sp)))
+        __else
+	 __(ldr(imm0,eabi_c_frame.savelr(sp)))
+        __endif
+	__(mtlr imm0)
+	__(blr)
+	_endfn
+
+
+/* This sucker gets called with R3 pointing to the current TCR. */
+/* r4 is 0 if we want to start the whole thing rolling, */
+/* non-zero if we want to reset the current process */
+/* by throwing to toplevel */
+
+	.globl _SPreset
+_exportfn(C(start_lisp))
+	__(mflr r0)
+        __ifdef([POWEROPENABI])
+	 __(str(r0,c_frame.savelr(sp)))
+         __ifdef([rTOC])
+          __(str(rTOC,c_frame.savetoc(sp)))
+         __endif
+	 __(stru(sp,-(stack_align(c_frame.minsiz+(32*node_size)))(sp)))
+         __(str(r13,c_frame.minsiz+(0*node_size)(sp)))
+         __(str(r14,c_frame.minsiz+(1*node_size)(sp)))
+         __(str(r15,c_frame.minsiz+(2*node_size)(sp)))
+         __(str(r16,c_frame.minsiz+(3*node_size)(sp)))
+         __(str(r17,c_frame.minsiz+(4*node_size)(sp)))
+         __(str(r18,c_frame.minsiz+(5*node_size)(sp)))
+         __(str(r19,c_frame.minsiz+(6*node_size)(sp)))
+         __(str(r20,c_frame.minsiz+(7*node_size)(sp)))
+         __(str(r21,c_frame.minsiz+(8*node_size)(sp)))
+         __(str(r22,c_frame.minsiz+(9*node_size)(sp)))
+         __(str(r23,c_frame.minsiz+(10*node_size)(sp)))
+         __(str(r24,c_frame.minsiz+(11*node_size)(sp)))
+         __(str(r25,c_frame.minsiz+(12*node_size)(sp)))
+         __(str(r26,c_frame.minsiz+(13*node_size)(sp)))
+         __(str(r27,c_frame.minsiz+(14*node_size)(sp)))
+         __(str(r28,c_frame.minsiz+(15*node_size)(sp)))
+         __(str(r29,c_frame.minsiz+(16*node_size)(sp)))
+         __(str(r30,c_frame.minsiz+(17*node_size)(sp)))
+         __(str(r31,c_frame.minsiz+(18*node_size)(sp)))
+	 __(stfd fp_s32conv,c_frame.minsiz+(22*node_size)(sp))
+        __else
+	 __(str(r0,eabi_c_frame.savelr(sp)))
+	 __(stru(sp,-(eabi_c_frame.minsiz+(32*node_size))(sp)))
+         __(str(r13,eabi_c_frame.minsiz+(0*node_size)(sp)))
+         __(str(r14,eabi_c_frame.minsiz+(1*node_size)(sp)))
+         __(str(r15,eabi_c_frame.minsiz+(2*node_size)(sp)))
+         __(str(r16,eabi_c_frame.minsiz+(3*node_size)(sp)))
+         __(str(r17,eabi_c_frame.minsiz+(4*node_size)(sp)))
+         __(str(r18,eabi_c_frame.minsiz+(5*node_size)(sp)))
+         __(str(r19,eabi_c_frame.minsiz+(6*node_size)(sp)))
+         __(str(r20,eabi_c_frame.minsiz+(7*node_size)(sp)))
+         __(str(r21,eabi_c_frame.minsiz+(8*node_size)(sp)))
+         __(str(r22,eabi_c_frame.minsiz+(9*node_size)(sp)))
+         __(str(r23,eabi_c_frame.minsiz+(10*node_size)(sp)))
+         __(str(r24,eabi_c_frame.minsiz+(11*node_size)(sp)))
+         __(str(r25,eabi_c_frame.minsiz+(12*node_size)(sp)))
+         __(str(r26,eabi_c_frame.minsiz+(13*node_size)(sp)))
+         __(str(r27,eabi_c_frame.minsiz+(14*node_size)(sp)))
+         __(str(r28,eabi_c_frame.minsiz+(15*node_size)(sp)))
+         __(str(r29,eabi_c_frame.minsiz+(16*node_size)(sp)))
+         __(str(r30,eabi_c_frame.minsiz+(17*node_size)(sp)))
+         __(str(r31,eabi_c_frame.minsiz+(18*node_size)(sp)))
+	 __(stfd fp_s32conv,eabi_c_frame.minsiz+(22*node_size)(sp))
+        __endif
+	__(mr rcontext,r3)
+	__(lwi(r30,0x43300000))
+	__(lwi(r31,0x80000000))
+        __ifdef([POWEROPENABI])
+	 __(stw r30,c_frame.minsiz+(20*node_size)(sp))
+	 __(stw r31,c_frame.minsiz+(20*node_size)+4(sp))
+	 __(lfd fp_s32conv,c_frame.minsiz+(20*node_size)(sp))
+	 __(stfd fp_zero,c_frame.minsiz+(20*node_size)(sp))
+        __else                
+ 	 __(stw r30,eabi_c_frame.minsiz+(20*node_size)(sp))
+	 __(stw r31,eabi_c_frame.minsiz+(20*node_size)+4(sp))
+	 __(lfd fp_s32conv,eabi_c_frame.minsiz+(20*node_size)(sp))
+	 __(stfd fp_zero,eabi_c_frame.minsiz+(20*node_size)(sp))
+        __endif
+	__(lfs fp_zero,lisp_globals.short_float_zero(0))
+	__(lfd f0,tcr.lisp_fpscr(rcontext))
+        __(mtfsf 0xff,f0)
+	__(li rzero,0)
+	__(mr save0,rzero)
+	__(mr save1,rzero)
+	__(mr save2,rzero)
+	__(mr save3,rzero)
+	__(mr save4,rzero)
+	__(mr save5,rzero)
+	__(mr save6,rzero)
+	__(mr save7,rzero)
+	__(mr arg_z,rzero)
+	__(mr arg_y,rzero)
+	__(mr arg_x,rzero)
+	__(mr temp0,rzero)
+	__(mr temp1,rzero)
+	__(mr temp2,rzero)
+	__(mr temp3,rzero)
+	__(li loc_pc,0)
+	__(li fn,0)
+	__(cmpri(cr0,r4,0))
+	__(mtxer rzero)  /* start lisp with the overflow bit clear */
+	__(ldr(vsp,tcr.save_vsp(rcontext)))
+	__(ldr(tsp,tcr.save_tsp(rcontext)))
+	__(ldr(allocptr,tcr.save_allocptr(rcontext)))
+	__(ldr(allocbase,tcr.save_allocbase(rcontext)))
+        __(li imm0,TCR_STATE_LISP)
+        __(str(imm0,tcr.valence(rcontext)))
+	__(bne cr0,1f)
+	__(bl toplevel_loop)
+	__(b 2f)
+1:
+	__(bl _SPreset)
+2:
+	__(str(allocptr,tcr.save_allocptr(rcontext)))
+	__(str(allocbase,tcr.save_allocbase(rcontext)))
+	__(str(tsp,tcr.save_tsp(rcontext)))
+	__(str(vsp,tcr.save_vsp(rcontext)))
+        __(li imm0,TCR_STATE_FOREIGN)
+        __(str(imm0,tcr.valence(rcontext)))
+        __ifdef([POWEROPENABI])
+         __(ldr(r13,c_frame.minsiz+(0*node_size)(sp)))
+         __(ldr(r14,c_frame.minsiz+(1*node_size)(sp)))
+         __(ldr(r15,c_frame.minsiz+(2*node_size)(sp)))
+         __(ldr(r16,c_frame.minsiz+(3*node_size)(sp)))
+         __(ldr(r17,c_frame.minsiz+(4*node_size)(sp)))
+         __(ldr(r18,c_frame.minsiz+(5*node_size)(sp)))
+         __(ldr(r19,c_frame.minsiz+(6*node_size)(sp)))
+         __(ldr(r20,c_frame.minsiz+(7*node_size)(sp)))
+         __(ldr(r21,c_frame.minsiz+(8*node_size)(sp)))
+         __(ldr(r22,c_frame.minsiz+(9*node_size)(sp)))
+         __(ldr(r23,c_frame.minsiz+(10*node_size)(sp)))
+         __(ldr(r24,c_frame.minsiz+(11*node_size)(sp)))
+         __(ldr(r25,c_frame.minsiz+(12*node_size)(sp)))
+         __(ldr(r26,c_frame.minsiz+(13*node_size)(sp)))
+         __(ldr(r27,c_frame.minsiz+(14*node_size)(sp)))
+         __(ldr(r28,c_frame.minsiz+(15*node_size)(sp)))
+         __(ldr(r29,c_frame.minsiz+(16*node_size)(sp)))
+         __(ldr(r30,c_frame.minsiz+(17*node_size)(sp)))
+         __(ldr(r31,c_frame.minsiz+(18*node_size)(sp)))
+        __else
+         __(ldr(r13,eabi_c_frame.minsiz+(0*node_size)(sp)))
+         __(ldr(r14,eabi_c_frame.minsiz+(1*node_size)(sp)))
+         __(ldr(r15,eabi_c_frame.minsiz+(2*node_size)(sp)))
+         __(ldr(r16,eabi_c_frame.minsiz+(3*node_size)(sp)))
+         __(ldr(r17,eabi_c_frame.minsiz+(4*node_size)(sp)))
+         __(ldr(r18,eabi_c_frame.minsiz+(5*node_size)(sp)))
+         __(ldr(r19,eabi_c_frame.minsiz+(6*node_size)(sp)))
+         __(ldr(r20,eabi_c_frame.minsiz+(7*node_size)(sp)))
+         __(ldr(r21,eabi_c_frame.minsiz+(8*node_size)(sp)))
+         __(ldr(r22,eabi_c_frame.minsiz+(9*node_size)(sp)))
+         __(ldr(r23,eabi_c_frame.minsiz+(10*node_size)(sp)))
+         __(ldr(r24,eabi_c_frame.minsiz+(11*node_size)(sp)))
+         __(ldr(r25,eabi_c_frame.minsiz+(12*node_size)(sp)))
+         __(ldr(r26,eabi_c_frame.minsiz+(13*node_size)(sp)))
+         __(ldr(r27,eabi_c_frame.minsiz+(14*node_size)(sp)))
+         __(ldr(r28,eabi_c_frame.minsiz+(15*node_size)(sp)))
+         __(ldr(r29,eabi_c_frame.minsiz+(16*node_size)(sp)))
+         __(ldr(r30,eabi_c_frame.minsiz+(17*node_size)(sp)))
+         __(ldr(r31,eabi_c_frame.minsiz+(18*node_size)(sp)))
+        __endif
+	__(li r3,nil_value)
+        __ifdef([POWEROPENABI])
+	 __(lfd fp_zero,c_frame.minsiz+(20*node_size)(sp))
+	 __(lfd fp_s32conv,c_frame.minsiz+(22*node_size)(sp))
+	 __(ldr(r0,((stack_align(c_frame.minsiz+(32*node_size)))+c_frame.savelr)(sp)))
+        __else
+	 __(lfd fp_zero,eabi_c_frame.minsiz+(20*4)(sp))
+	 __(lfd fp_s32conv,eabi_c_frame.minsiz+(22*4)(sp))
+	 __(ldr(r0,(eabi_c_frame.minsiz+(32*node_size)+eabi_c_frame.savelr)(sp)))
+        __endif
+	__(mtlr r0)
+	__(ldr(sp,0(sp)))
+         __ifdef([rTOC])
+          __(ld rTOC,c_frame.savetoc(sp))
+         __endif
+	__(blr)
+
+_exportfn(_SPsp_end)
+	nop
+	_endfile
+
Index: /branches/new-random/lisp-kernel/ppc-uuo.s
===================================================================
--- /branches/new-random/lisp-kernel/ppc-uuo.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc-uuo.s	(revision 13309)
@@ -0,0 +1,91 @@
+/* Copyright (C) 2009 Clozure Associates */
+/* Copyright (C) 1994-2001 Digitool, Inc */
+/* This file is part of Clozure CL. */
+
+/* Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/* License , known as the LLGPL and distributed with Clozure CL as the */
+/* file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/* which is distributed with Clozure CL as the file "LGPL".  Where these */
+/* conflict, the preamble takes precedence. */
+ 
+/* Clozure CL is referenced in the preamble as the "LIBRARY." */
+ 
+/* The LLGPL is also available online at */
+/* http://opensource.franz.com/preamble.html */
+
+
+
+
+/* A uuo looks like:  */
+/*  0      5 6                  15 16   20 21          27 28  31  */
+/* +--------+-----------------------------+--------------+------+  */
+/* |   0    |XXXXXXXXXXXXXXXXXXXX |  RB   |  <minor op>  |  11  |  */
+/* +--------+-----------------------------+--------------+------+  */
+/*  */
+/* e.g., the major opcode (bits 0-5) is 0, the low 4 bits (bits 28-31)  */
+/* have the value "11" decimal (that's tagged as an immediate as far  */
+/* as lisp is concerned, a 7-bit opcode in bits 21-27, and the format  */
+/* of bits 6-20 depend on the value of the minor opcode, though typically  */
+/* bits 16-20 are used to specify a register value between 0 and 31.  */
+/*  */
+/* There are a few cases where bits 6-15 are also used to denote registers  */
+/* (RT and RA, as in an X-form PPC instruction), some where bits 6-10 are  */
+/* to be interpreted as a constant (error number or type code), and some  */
+/* where bits 6-15 do so.  */
+/*  */
+/* Since C code is typically more interested in disassembling UUOs, the  */
+/* full list of UUOs is in "uuo.h".  This file contains macros for creating  */
+/* them.  */
+/*  */
+/* Of course, there -is- no such file as "uuo.h".  That's a stale comment.  */
+/* For all anyone knows, so is this one.  */
+
+UUO_TAG = 11
+UUU_MINOR_SHIFT = 4
+UUO_RB_SHIFT = 11
+UUO_RA_SHIFT = 16
+UUO_RT_SHIFT = 21
+
+define([rt_ra_uuo],[
+	.long (UUO_TAG|(($1)<<UUU_MINOR_SHIFT)|(($3)<<UUO_RA_SHIFT)|(($2)<<UUO_RT_SHIFT))])
+
+define([rt_ra_rb_uuo],[
+	.long (UUO_TAG|(($1)<<UUU_MINOR_SHIFT)|(($3)<<UUO_RA_SHIFT)|(($4)<<UUO_RB_SHIFT)|(($2)<<UUO_RT_SHIFT))])
+	
+define([errnum_rb_uuo],[
+	.long (UUO_TAG|(($1)<<UUU_MINOR_SHIFT)|(($2)<<UUO_RA_SHIFT)|(($3)<<UUO_RB_SHIFT))])
+	
+define([errnum_ra_rb_uuo],[ /* minorop,errnum,ra,rb */
+	.long (UUO_TAG|(($1)<<UUU_MINOR_SHIFT)|(($2)<<UUO_RA_SHIFT)|(($3)<<UUO_RB_SHIFT)|((\errnum)<<UUO_RT_SHIFT))])
+	
+	
+	
+/* Signal an internal error - type error or whatever - with error   */
+/* number (0-1023) and "register" argument.  */
+
+define([uuo_interr],[
+	errnum_rb_uuo(11,$1,$2)])
+	
+/* As above, but make the error continuable.  (A branch presumably  */
+/* follows the UUO opcode.)  */
+
+define([uuo_intcerr],[
+	errnum_rb_uuo(12,$1,$2)])
+
+
+/* Signal an error with a much smaller error number (0-31) and  */
+/* two "register" fields.  */
+
+define([uuo_interr2],[
+	errnum_ra_rb_uuo(13,$1,$2,$3)])
+	
+/* Continuably ....  */
+
+define([uuo_intcerr2],[
+	errnum_ra_rb_uuo(14,$1,$2,$3)])
+
+	
+
+/* A distinguished UUO: the handler should zero the FPSCR  */
+define([uuo_zero_fpscr],[
+	rt_ra_rb_uuo(25,0,0,0)])
Index: /branches/new-random/lisp-kernel/ppc_print.c
===================================================================
--- /branches/new-random/lisp-kernel/ppc_print.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/ppc_print.c	(revision 13309)
@@ -0,0 +1,490 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <setjmp.h>
+
+#include "lisp.h"
+#include "area.h"
+#include "lisp-exceptions.h"
+#include "lisp_globals.h"
+
+void
+sprint_lisp_object(LispObj, int);
+
+#define PBUFLEN 252
+
+char printbuf[PBUFLEN + 4];
+int bufpos = 0;
+
+jmp_buf escape;
+
+void
+add_char(char c)
+{
+  if (bufpos >= PBUFLEN) {
+    longjmp(escape, 1);
+  } else {
+    printbuf[bufpos++] = c;
+  }
+}
+
+void
+add_string(char *s, int len) 
+{
+  while(len--) {
+    add_char(*s++);
+  }
+}
+
+void
+add_lisp_base_string(LispObj str)
+{
+  lisp_char_code *src = (lisp_char_code *)  (ptr_from_lispobj(str + misc_data_offset));
+  natural i, n = header_element_count(header_of(str));
+
+  for (i=0; i < n; i++) {
+    add_char((char)(*src++));
+  }
+}
+
+void
+add_c_string(char *s)
+{
+  add_string(s, strlen(s));
+}
+
+char numbuf[64];
+
+void
+sprint_signed_decimal(signed_natural n)
+{
+  sprintf(numbuf, "%ld", n);
+  add_c_string(numbuf);
+}
+
+void
+sprint_unsigned_decimal(natural n)
+{
+  sprintf(numbuf, "%lu", n);
+  add_c_string(numbuf);
+}
+
+void
+sprint_unsigned_hex(natural n)
+{
+#ifdef PPC64
+  sprintf(numbuf, "#x%016lx", n);
+#else
+  sprintf(numbuf, "#x%08lx", n);
+#endif
+  add_c_string(numbuf);
+}
+
+void
+sprint_list(LispObj o, int depth)
+{
+  LispObj the_cdr;
+  
+  add_char('(');
+  while(1) {
+    if (o != lisp_nil) {
+      sprint_lisp_object(ptr_to_lispobj(car(o)), depth);
+      the_cdr = ptr_to_lispobj(cdr(o));
+      if (the_cdr != lisp_nil) {
+        add_char(' ');
+        if (fulltag_of(the_cdr) == fulltag_cons) {
+          o = the_cdr;
+          continue;
+        }
+        add_c_string(". ");
+        sprint_lisp_object(the_cdr, depth);
+        break;
+      }
+    }
+    break;
+  }
+  add_char(')');
+}
+
+/* 
+  Print a list of method specializers, using the class name instead of the class object.
+*/
+
+void
+sprint_specializers_list(LispObj o, int depth)
+{
+  LispObj the_cdr, the_car;
+  
+  add_char('(');
+  while(1) {
+    if (o != lisp_nil) {
+      the_car = car(o);
+      if (fulltag_of(the_car) == fulltag_misc) {
+        sprint_lisp_object(deref(deref(the_car,3), 4), depth);
+      } else {
+        sprint_lisp_object(the_car, depth);
+      }
+      the_cdr = cdr(o);
+      if (the_cdr != lisp_nil) {
+        add_char(' ');
+        if (fulltag_of(the_cdr) == fulltag_cons) {
+          o = the_cdr;
+          continue;
+        }
+        add_c_string(". ");
+        sprint_lisp_object(the_cdr, depth);
+        break;
+      }
+    }
+    break;
+  }
+  add_char(')');
+}
+
+char *
+vector_subtag_name(unsigned subtag)
+{
+  switch (subtag) {
+  case subtag_bit_vector:
+    return "BIT-VECTOR";
+    break;
+  case subtag_instance:
+    return "INSTANCE";
+    break;
+  case subtag_bignum:
+    return "BIGNUM";
+    break;
+  case subtag_u8_vector:
+    return "(UNSIGNED-BYTE 8)";
+    break;
+  case subtag_s8_vector:
+    return "(SIGNED-BYTE 8)";
+    break;
+  case subtag_u16_vector:
+    return "(UNSIGNED-BYTE 16)";
+    break;
+  case subtag_s16_vector:
+    return "(SIGNED-BYTE 16)";
+    break;
+  case subtag_u32_vector:
+    return "(UNSIGNED-BYTE 32)";
+    break;
+  case subtag_s32_vector:
+    return "(SIGNED-BYTE 32)";
+    break;
+#ifdef PPC64
+  case subtag_u64_vector:
+    return "(UNSIGNED-BYTE 64)";
+    break;
+  case subtag_s64_vector:
+    return "(SIGNED-BYTE 64)";
+    break;
+#endif
+  case subtag_package:
+    return "PACKAGE";
+    break;
+  case subtag_code_vector:
+    return "CODE-VECTOR";
+    break;
+  case subtag_slot_vector:
+    return "SLOT-VECTOR";
+    break;
+  default:
+    return "";
+    break;
+  }
+}
+
+
+void
+sprint_random_vector(LispObj o, unsigned subtag, natural elements)
+{
+  add_c_string("#<");
+  sprint_unsigned_decimal(elements);
+  add_c_string("-element vector subtag = ");
+  sprintf(numbuf, "%02X @", subtag);
+  add_c_string(numbuf);
+  sprint_unsigned_hex(o);
+  add_c_string(" (");
+  add_c_string(vector_subtag_name(subtag));
+  add_c_string(")>");
+}
+
+void
+sprint_symbol(LispObj o)
+{
+  lispsymbol *rawsym = (lispsymbol *) ptr_from_lispobj(untag(o));
+  LispObj 
+    pname = rawsym->pname,
+    package = rawsym->package_predicate;
+
+#ifdef PPC64
+  if (o == lisp_nil) {
+    add_c_string("()");
+    return;
+  }
+#endif
+  if (fulltag_of(package) == fulltag_cons) {
+    package = car(package);
+  }
+
+  if (package == nrs_KEYWORD_PACKAGE.vcell) {
+    add_char(':');
+  }
+  add_lisp_base_string(pname);
+}
+
+void
+sprint_function(LispObj o, int depth)
+{
+  LispObj lfbits, header, name = lisp_nil;
+  natural elements;
+
+  header = header_of(o);
+  elements = header_element_count(header);
+  lfbits = deref(o, elements);
+
+  if ((lfbits & lfbits_noname_mask) == 0) {
+    name = deref(o, elements-1);
+  }
+  
+  add_c_string("#<");
+  if (name == lisp_nil) {
+    add_c_string("Anonymous Function ");
+  } else {
+    if (lfbits & lfbits_method_mask) {
+      LispObj 
+	slot_vector = deref(name,3),
+        method_name = deref(slot_vector, 6),
+        method_qualifiers = deref(slot_vector, 2),
+        method_specializers = deref(slot_vector, 3);
+      add_c_string("Method-Function ");
+      sprint_lisp_object(method_name, depth);
+      add_char(' ');
+      if (method_qualifiers != lisp_nil) {
+        if (cdr(method_qualifiers) == lisp_nil) {
+          sprint_lisp_object(car(method_qualifiers), depth);
+        } else {
+          sprint_lisp_object(method_qualifiers, depth);
+        }
+        add_char(' ');
+      }
+      sprint_specializers_list(method_specializers, depth);
+      add_char(' ');
+    } else {
+      add_c_string("Function ");
+      sprint_lisp_object(name, depth);
+      add_char(' ');
+    }
+  }
+  sprint_unsigned_hex(o);
+  add_char('>');
+}
+
+void
+sprint_gvector(LispObj o, int depth)
+{
+  LispObj header = header_of(o);
+  unsigned 
+    elements = header_element_count(header),
+    subtag = header_subtag(header);
+    
+  switch(subtag) {
+  case subtag_function:
+    sprint_function(o, depth);
+    break;
+    
+  case subtag_symbol:
+    sprint_symbol(o);
+    break;
+    
+  case subtag_struct:
+  case subtag_istruct:
+    add_c_string("#<");
+    sprint_lisp_object(deref(o,1), depth);
+    add_c_string(" @");
+    sprint_unsigned_hex(o);
+    add_c_string(">");
+    break;
+   
+  case subtag_simple_vector:
+    {
+      int i;
+      add_c_string("#(");
+      for(i = 1; i <= elements; i++) {
+        if (i > 1) {
+          add_char(' ');
+        }
+        sprint_lisp_object(deref(o, i), depth);
+      }
+      add_char(')');
+      break;
+    }
+      
+  default:
+    sprint_random_vector(o, subtag, elements);
+    break;
+  }
+}
+
+void
+sprint_ivector(LispObj o)
+{
+  LispObj header = header_of(o);
+  unsigned 
+    elements = header_element_count(header),
+    subtag = header_subtag(header);
+    
+  switch(subtag) {
+  case subtag_simple_base_string:
+    add_char('"');
+    add_lisp_base_string(o);
+    add_char('"');
+    return;
+    
+  case subtag_bignum:
+    if (elements == 1) {
+      sprint_signed_decimal((signed_natural)(deref(o, 1)));
+      return;
+    }
+    if ((elements == 2) && (deref(o, 2) == 0)) {
+      sprint_unsigned_decimal(deref(o, 1));
+      return;
+    }
+    break;
+    
+  case subtag_double_float:
+    break;
+
+  case subtag_macptr:
+    add_c_string("#<MACPTR ");
+    sprint_unsigned_hex(deref(o,1));
+    add_c_string(">");
+    break;
+
+  default:
+    sprint_random_vector(o, subtag, elements);
+  }
+}
+
+void
+sprint_vector(LispObj o, int depth)
+{
+  LispObj header = header_of(o);
+  
+  if (immheader_tag_p(fulltag_of(header))) {
+    sprint_ivector(o);
+  } else {
+    sprint_gvector(o, depth);
+  }
+}
+
+void
+sprint_lisp_object(LispObj o, int depth) 
+{
+  if (--depth < 0) {
+    add_char('#');
+  } else {
+    switch (fulltag_of(o)) {
+    case fulltag_even_fixnum:
+    case fulltag_odd_fixnum:
+      sprint_signed_decimal(unbox_fixnum(o));
+      break;
+    
+#ifdef PPC64
+    case fulltag_immheader_0:
+    case fulltag_immheader_1:
+    case fulltag_immheader_2:
+    case fulltag_immheader_3:
+    case fulltag_nodeheader_0:
+    case fulltag_nodeheader_1:
+    case fulltag_nodeheader_2:
+    case fulltag_nodeheader_3:
+#else
+    case fulltag_immheader:
+    case fulltag_nodeheader:
+#endif      
+      add_c_string("#<header ? ");
+      sprint_unsigned_hex(o);
+      add_c_string(">");
+      break;
+
+#ifdef PPC64
+    case fulltag_imm_0:
+    case fulltag_imm_1:
+    case fulltag_imm_2:
+    case fulltag_imm_3:
+#else
+    case fulltag_imm:
+#endif
+      if (o == unbound) {
+        add_c_string("#<Unbound>");
+      } else {
+        if (header_subtag(o) == subtag_character) {
+          unsigned c = (o >> charcode_shift);
+          add_c_string("#\\");
+          if ((c >= ' ') && (c < 0x7f)) {
+            add_char(c);
+          } else {
+            sprintf(numbuf, "%o", c);
+            add_c_string(numbuf);
+          }
+#ifdef PPC64
+        } else if (header_subtag(o) == subtag_single_float) {
+          sprintf(numbuf, "%f", o>>32);
+          add_c_string(numbuf);
+#endif
+        } else {
+
+          add_c_string("#<imm ");
+          sprint_unsigned_hex(o);
+          add_c_string(">");
+        }
+      }
+      break;
+   
+#ifndef PPC64
+    case fulltag_nil:
+#endif
+    case fulltag_cons:
+      sprint_list(o, depth);
+      break;
+     
+    case fulltag_misc:
+      sprint_vector(o, depth);
+      break;
+    }
+  }
+}
+
+char *
+print_lisp_object(LispObj o)
+{
+  bufpos = 0;
+  if (setjmp(escape) == 0) {
+    sprint_lisp_object(o, 5);
+    printbuf[bufpos] = 0;
+  } else {
+    printbuf[PBUFLEN+0] = '.';
+    printbuf[PBUFLEN+1] = '.';
+    printbuf[PBUFLEN+2] = '.';
+    printbuf[PBUFLEN+3] = 0;
+  }
+  return printbuf;
+}
Index: /branches/new-random/lisp-kernel/solarisx64/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/solarisx64/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/solarisx64/.gdbinit	(revision 13309)
@@ -0,0 +1,82 @@
+define x86_lisp_string
+x/s $arg0-5
+end
+
+define gtra
+br *$r10
+cont
+end
+
+define x86pname
+set $temp=*((long *)((long)($arg0-6)))
+x86_lisp_string $temp
+end
+
+
+define pname
+ x86pname $arg0
+end
+
+define l
+ call print_lisp_object($arg0)
+end
+
+define lw
+ l $r13
+end
+
+define clobber_breakpoint
+  set *(short *)($pc-2)=0x9090
+end
+
+define arg_z
+ l $rsi
+end
+
+define arg_y
+ l $rdi
+end
+
+define arg_x
+ l $r8
+end
+
+define bx
+ l $rbx
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x200b
+   set $car = *((LispObj *)($l+5))
+   set $l =  *((LispObj *)($l-3))
+   l $car
+  end
+end
+
+define lbt
+ call plbt_sp($rbp)
+end
+
+define ada
+ p/x *(all_areas->succ)
+end
+
+define lregs
+ call debug_lisp_registers($arg0,0,0)
+end
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIGUSR1 pass nostop noprint
+handle SIGUSR2 pass nostop noprint
+handle SIGPWR pass nostop noprint
+handle SIGQUIT pass nostop noprint
+
Index: /branches/new-random/lisp-kernel/solarisx64/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/solarisx64/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/solarisx64/Makefile	(revision 13309)
@@ -0,0 +1,85 @@
+#
+#   Copyright (C) 2006 Clozure Associates and contributors
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ..
+RM = /bin/rm
+AS = /usr/sfw/bin/gas
+# As of this writing, /usr/sfw/bin/gm4 is both more recent (1.4.2 vs 1.4)
+# and more buggy than /opt/sfw/bin/gm4, which is available on the 
+# "Solaris companion" disk.  Do you get the impression that the people
+# who put this stuff together aren't paying much attention ?
+# Marching forward: as of the OpenSolais 0805 (snv_86) release, there
+# doesn't seem to be any way of obtaining a non-broken GNU m4 from Sun.
+# I just downloaded the source to 1.4.11 and installed it in /usr/local/bin;
+# I didn't try blastwave.org or sunfreeware.com; there might be working
+# packages there
+M4 = /usr/local/bin/m4
+CC = /usr/sfw/bin/gcc
+ASFLAGS = --64 --divide
+M4FLAGS = -DSOLARIS -DX86 -DX8664
+CDEFINES = -DSOLARIS -D_REENTRANT -DX86 -DX8664 -D__EXTENSIONS__ -DHAVE_TLS #-DDISABLE_EGC
+CDEBUG = -g
+COPT = #-O2
+
+
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) -m64 -o $@
+
+SPOBJ = pad.o x86-spjump64.o x86-spentry64.o x86-subprims64.o
+ASMOBJ = x86-asmutils64.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils64.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants64.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants64.h x86-exceptions.h lisptypes.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	../../sx86cl64
+
+
+OSLIBS = -ldl -lm -lpthread -lsocket -lnsl -lrt
+
+
+../../sx86cl64:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile
+	$(CC)  -m64 $(CDEBUG) -o $@  $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../sx86cl64
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../sx86cl64
+	strip -g ../../sx86cl64
Index: /branches/new-random/lisp-kernel/solarisx86/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/solarisx86/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/solarisx86/Makefile	(revision 13309)
@@ -0,0 +1,85 @@
+#
+#   Copyright (C) 2006 Clozure Associates and contributors
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ..
+RM = /bin/rm
+AS = /usr/sfw/bin/gas
+# As of this writing, /usr/sfw/bin/gm4 is both more recent (1.4.2 vs 1.4)
+# and more buggy than /opt/sfw/bin/gm4, which is available on the 
+# "Solaris companion" disk.  Do you get the impression that the people
+# who put this stuff together aren't paying much attention ?
+# Marching forward: as of the OpenSolais 0805 (snv_86) release, there
+# doesn't seem to be any way of obtaining a non-broken GNU m4 from Sun.
+# I just downloaded the source to 1.4.11 and installed it in /usr/local/bin;
+# I didn't try blastwave.org or sunfreeware.com; there might be working
+# packages there
+M4 = /usr/local/bin/m4
+CC = /usr/sfw/bin/gcc
+ASFLAGS = --32 --divide
+M4FLAGS = -DSOLARIS -DX86 -DX8632
+CDEFINES = -DSOLARIS -D_REENTRANT -DX86 -DX8632 -D__EXTENSIONS__ -DHAVE_TLS #-DDISABLE_EGC
+CDEBUG = -g
+COPT = -O2
+
+
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) -m32 -o $@
+
+SPOBJ = pad.o x86-spjump32.o x86-spentry32.o x86-subprims32.o
+ASMOBJ = x86-asmutils32.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o unix-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils32.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants32.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants32.h x86-exceptions.h lisptypes.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	../../sx86cl
+
+
+OSLIBS = -ldl -lm -lpthread -lsocket -lnsl -lrt
+
+
+../../sx86cl:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile
+	$(CC)  -m32 $(CDEBUG) -o $@  $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../sx86cl
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../sx86cl
+	strip -g ../../sx86cl
Index: /branches/new-random/lisp-kernel/static-linuxppc/.cvsignore
===================================================================
--- /branches/new-random/lisp-kernel/static-linuxppc/.cvsignore	(revision 13309)
+++ /branches/new-random/lisp-kernel/static-linuxppc/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+external-functions.h
+*~.*
Index: /branches/new-random/lisp-kernel/static-linuxppc/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/static-linuxppc/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/static-linuxppc/Makefile	(revision 13309)
@@ -0,0 +1,103 @@
+#
+#   Copyright (C) 1994-2001 Digitool, Inc
+#   This file is part of OpenMCL.  
+#
+#   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with OpenMCL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with OpenMCL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   OpenMCL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+OPENMCL_MAJOR_VERSION=0
+OPENMCL_MINOR_VERSION=14
+
+VPATH = ../
+RM = /bin/rm
+# Versions of GNU as >= 2.9.1 all seem to work
+# AS = gas-2.9.1
+AS = as
+M4 = m4
+ASFLAGS = -mregnames -mppc32
+M4FLAGS = -DLINUX -DPPC
+CDEFINES = -DLINUX -DPPC -D_REENTRANT -DSTATIC -D_GNU_SOURCE
+CDEBUG = -g
+COPT = -O2
+
+# The only version of GCC I have that supports both ppc32 and ppc64
+# compilation uses the -m32 option to target ppc32.  This may not be
+# definitive; there seem to be a bewildering array of similar options
+# in other GCC versions.  It's assumed here that if "-m32" is recognized,
+# it's required as well.
+
+PPC32 = $(shell ($(CC) --help -v 2>&1 | grep -q -e "-m32 ") && /bin/echo "-m32")
+
+# Likewise, some versions of GAS may need a "-a32" flag, to force the
+# output file to be 32-bit compatible.
+
+A32 = $(shell ($(AS) --help -v 2>&1 | grep -q -e "-a32") && /bin/echo "-a32")
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS) $(A32) $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) $(PPC32) -o $@
+
+SPOBJ = pad.o ppc-spjump.o ppc-spentry.o ppc-subprims.o
+ASMOBJ = ppc-asmutils.o imports.o
+
+COBJ  = pmcl-kernel.o ppc-gc.o bits.o  ppc-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o plbt.o ppc_print.o
+KERNELOBJ= $(COBJ) ppc-asmutils.o  imports.o
+STATICOBJ= staticlib.o
+
+SPINC =	lisp.s m4macros.m4 ppc-constants.s ppc-macros.s errors.s ppc-uuo.s ppc-constants32.s
+
+CHEADERS = area.h bits.h ppc-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h ppc-constants32.h ppc-exceptions.h
+
+# Subprims linked into the kernel ?
+# Yes:
+
+KSPOBJ = $(SPOBJ)
+all:	../../static-ppccl
+
+
+# No:
+
+# KSPOBJ=
+# all:	../../static-ppccl ../../subprims.so
+
+OSLIBS =  -lm -lpthread
+
+
+../../static-ppccl:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(STATICOBJ)
+	$(CC) $(PPC32) $(CDEBUG) -static  -o $@ -T ../linux//elf32ppclinux.x $(KSPOBJ) $(KERNELOBJ) $(STATICOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+staticlib.o: external-functions.h staticlib.c
+	$(CC) -c staticlib.c -fno-builtin $(CDEFINES) $(CDEBUG) $(COPT) $(PPC32) -o $@
+
+
+external-functions.h:
+	echo "Must generate external-functions.h from running lisp"
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../ppccl
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../ppccl
+	strip -g ../../ppccl
Index: /branches/new-random/lisp-kernel/static-linuxppc/staticlib.c
===================================================================
--- /branches/new-random/lisp-kernel/static-linuxppc/staticlib.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/static-linuxppc/staticlib.c	(revision 13309)
@@ -0,0 +1,53 @@
+typedef struct  {
+  char *name;
+  void *(*func)();
+} external_function;
+
+#define NULL ((void *)0)
+#include "external-functions.h"
+
+int
+string_compare(char *a, char *b)
+{
+  char ch;
+
+  while (ch = *a++) {
+    if (*b++ != ch) {
+      return 1;
+    }
+  }
+  return !!*b;
+}
+
+      
+void *
+dlsym(void *handle, char *name)
+{
+  external_function *p;
+  char *fname;
+
+  for (p = external_functions; fname = p->name; p++) {
+    if (!string_compare(name, fname)) {
+      return (void *)(p->func);
+    }
+  }
+  return NULL;
+}
+
+void *
+dlopen(char *path, int mode)
+{
+  return NULL;
+}
+
+void *
+dlerror()
+{
+  return (void *)"No shared library support\n";
+}
+
+void *
+dlclose()
+{
+  return NULL;
+}
Index: /branches/new-random/lisp-kernel/thread_manager.c
===================================================================
--- /branches/new-random/lisp-kernel/thread_manager.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/thread_manager.c	(revision 13309)
@@ -0,0 +1,2697 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+
+#include "Threads.h"
+
+
+typedef struct {
+  TCR *tcr;
+  natural vsize, tsize;
+  void *created;
+} thread_activation;
+
+#ifdef HAVE_TLS
+__thread char tcrbuf[sizeof(TCR)+16];
+__thread TCR *current_tcr;
+#endif
+
+/* This is set to true when running a 32-bit Lisp on 64-bit FreeBSD */
+Boolean rcontext_readonly = false;
+
+extern natural
+store_conditional(natural*, natural, natural);
+
+extern signed_natural
+atomic_swap(signed_natural*, signed_natural);
+
+#ifdef USE_FUTEX
+#define futex_wait(futex,val) syscall(SYS_futex,futex,FUTEX_WAIT,val)
+#define futex_wake(futex,n) syscall(SYS_futex,futex,FUTEX_WAKE,n)
+#define FUTEX_AVAIL (0)
+#define FUTEX_LOCKED (1)
+#define FUTEX_CONTENDED (2)
+#endif
+
+#ifdef WINDOWS
+extern pc spentry_start, spentry_end,subprims_start,subprims_end;
+extern pc restore_windows_context_start, restore_windows_context_end,
+  restore_windows_context_iret;
+
+
+extern void interrupt_handler(int, siginfo_t *, ExceptionInformation *);
+
+void CALLBACK 
+nullAPC(ULONG_PTR arg) 
+{
+}
+  
+BOOL (*pCancelIoEx)(HANDLE, OVERLAPPED*) = NULL;
+BOOL (*pCancelSynchronousIo)(HANDLE) = NULL;
+
+
+
+extern void *windows_find_symbol(void*, char*);
+
+int
+raise_thread_interrupt(TCR *target)
+{
+  /* GCC doesn't align CONTEXT corrcectly */
+  char _contextbuf[sizeof(CONTEXT)+__alignof(CONTEXT)];
+  CONTEXT  *pcontext;
+  HANDLE hthread = (HANDLE)(target->osid);
+  pc where;
+  area *cs = target->cs_area, *ts = target->cs_area;
+  DWORD rc;
+  BOOL io_pending;
+
+  pcontext = (CONTEXT *)((((natural)&_contextbuf)+15)&~15);
+  rc = SuspendThread(hthread);
+  if (rc == -1) {
+    return -1;
+  }
+  /* What if the suspend count is > 1 at this point ?  I don't think
+     that that matters, but I'm not sure */
+  pcontext->ContextFlags = CONTEXT_ALL;
+  rc = GetThreadContext(hthread, pcontext);
+  if (rc == 0) {
+    return ESRCH;
+  }
+
+  where = (pc)(xpPC(pcontext));
+  
+  if ((target->valence != TCR_STATE_LISP) ||
+      (TCR_INTERRUPT_LEVEL(target) < 0) ||
+      (target->unwinding != 0) ||
+      (!((where < (pc)lisp_global(HEAP_END)) &&
+         (where >= (pc)lisp_global(HEAP_START))) &&
+       !((where < spentry_end) && (where >= spentry_start)) &&
+       !((where < subprims_end) && (where >= subprims_start)) &&
+       !((where < (pc) 0x16000) &&
+         (where >= (pc) 0x15000)) &&
+       !((where < (pc) (ts->high)) &&
+         (where >= (pc) (ts->low))))) {
+
+    target->interrupt_pending = (1LL << (nbits_in_word - 1LL));
+
+#if 0
+    /* If the thread's in a blocking syscall, it'd be nice to
+       get it out of that state here. */
+    GetThreadIOPendingFlag(hthread,&io_pending);
+    if (io_pending) {
+      pending_io * pending = (pending_io *) (target->pending_io_info);
+      if (pending) {
+        if (pCancelIoEx) {
+          pCancelIoEx(pending->h, pending->o);
+        } else {
+          CancelIo(pending->h);
+        }
+      }
+    }
+#endif
+    if (pCancelSynchronousIo) {
+      pCancelSynchronousIo(hthread);
+    }
+    QueueUserAPC(nullAPC, hthread, 0);
+    ResumeThread(hthread);
+    return 0;
+  } else {
+    /* Thread is running lisp code with interupts enabled.  Set it
+       so that it calls out and then returns to the context,
+       handling any necessary pc-lusering. */
+    LispObj foreign_rsp = (((LispObj)(target->foreign_sp))-0x200)&~15;
+    CONTEXT *icontext = ((CONTEXT *) foreign_rsp) -1;
+    icontext = (CONTEXT *)(((LispObj)icontext)&~15);
+    
+    *icontext = *pcontext;
+
+#ifdef WIN_64    
+    xpGPR(pcontext,REG_RCX) = SIGNAL_FOR_PROCESS_INTERRUPT;
+    xpGPR(pcontext,REG_RDX) = 0;
+    xpGPR(pcontext,REG_R8) = (LispObj) icontext;
+    xpGPR(pcontext,REG_RSP) = (LispObj)(((LispObj *)icontext)-1);
+    *(((LispObj *)icontext)-1) = (LispObj)raise_thread_interrupt;
+#else
+    {
+      LispObj *p = (LispObj *)icontext;
+      p -= 4;
+      p[0] = SIGNAL_FOR_PROCESS_INTERRUPT;
+      p[1] = 0;
+      p[2] = (DWORD)icontext;
+      *(--p) = (LispObj)raise_thread_interrupt;;
+      xpGPR(pcontext,Isp) = (DWORD)p;
+#ifdef WIN32_ES_HACK
+      pcontext->SegEs = pcontext->SegDs;
+#endif
+    }
+#endif
+    pcontext->EFlags &= ~0x400;  /* clear direction flag */
+    xpPC(pcontext) = (LispObj)interrupt_handler;
+    SetThreadContext(hthread,pcontext);
+    ResumeThread(hthread);
+    return 0;
+  }
+}
+#else
+int
+raise_thread_interrupt(TCR *target)
+{
+  pthread_t thread = (pthread_t)target->osid;
+#ifdef DARWIN_not_yet
+  if (use_mach_exception_handling) {
+    return mach_raise_thread_interrupt(target);
+  }
+#endif
+  if (thread != (pthread_t) 0) {
+    return pthread_kill(thread, SIGNAL_FOR_PROCESS_INTERRUPT);
+  }
+  return ESRCH;
+}
+#endif
+
+signed_natural
+atomic_incf_by(signed_natural *ptr, signed_natural by)
+{
+  signed_natural old, new;
+  do {
+    old = *ptr;
+    new = old+by;
+  } while (store_conditional((natural *)ptr, (natural) old, (natural) new) !=
+           (natural) old);
+  return new;
+}
+
+signed_natural
+atomic_incf(signed_natural *ptr)
+{
+  return atomic_incf_by(ptr, 1);
+}
+
+signed_natural
+atomic_decf(signed_natural *ptr)
+{
+  signed_natural old, new;
+  do {
+    old = *ptr;
+    new = old == 0 ? old : old-1;
+  } while (store_conditional((natural *)ptr, (natural) old, (natural) new) !=
+           (natural) old);
+  return old-1;
+}
+
+
+#ifndef USE_FUTEX
+int spin_lock_tries = 1;
+
+void
+get_spin_lock(signed_natural *p, TCR *tcr)
+{
+  int i, n = spin_lock_tries;
+  
+  while (1) {
+    for (i = 0; i < n; i++) {
+      if (atomic_swap(p,(signed_natural)tcr) == 0) {
+        return;
+      }
+    }
+#ifndef WINDOWS
+    sched_yield();
+#endif
+  }
+}
+#endif
+
+#ifndef USE_FUTEX
+int
+lock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
+{
+
+  if (tcr == NULL) {
+    tcr = get_tcr(true);
+  }
+  if (m->owner == tcr) {
+    m->count++;
+    return 0;
+  }
+  while (1) {
+    LOCK_SPINLOCK(m->spinlock,tcr);
+    ++m->avail;
+    if (m->avail == 1) {
+      m->owner = tcr;
+      m->count = 1;
+      RELEASE_SPINLOCK(m->spinlock);
+      break;
+    }
+    RELEASE_SPINLOCK(m->spinlock);
+    SEM_WAIT_FOREVER(m->signal);
+  }
+  return 0;
+}
+
+#else /* USE_FUTEX */
+
+static void inline
+lock_futex(signed_natural *p)
+{
+  
+  while (1) {
+    if (store_conditional(p,FUTEX_AVAIL,FUTEX_LOCKED) == FUTEX_AVAIL) {
+      return;
+    }
+    while (1) {
+      if (atomic_swap(p,FUTEX_CONTENDED) == FUTEX_AVAIL) {
+        return;
+      }
+      futex_wait(p,FUTEX_CONTENDED);
+    }
+  }
+}
+
+static void inline
+unlock_futex(signed_natural *p)
+{
+  if (atomic_decf(p) != FUTEX_AVAIL) {
+    *p = FUTEX_AVAIL;
+    futex_wake(p,INT_MAX);
+  }
+}
+    
+int
+lock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
+{
+  if (tcr == NULL) {
+    tcr = get_tcr(true);
+  }
+  if (m->owner == tcr) {
+    m->count++;
+    return 0;
+  }
+  lock_futex(&m->avail);
+  m->owner = tcr;
+  m->count = 1;
+  return 0;
+}
+#endif /* USE_FUTEX */
+
+
+#ifndef USE_FUTEX  
+int
+unlock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
+{
+  int ret = EPERM, pending;
+
+  if (tcr == NULL) {
+    tcr = get_tcr(true);
+  }
+
+  if (m->owner == tcr) {
+    --m->count;
+    if (m->count == 0) {
+      LOCK_SPINLOCK(m->spinlock,tcr);
+      m->owner = NULL;
+      pending = m->avail-1 + m->waiting;     /* Don't count us */
+      m->avail = 0;
+      --pending;
+      if (pending > 0) {
+        m->waiting = pending;
+      } else {
+        m->waiting = 0;
+      }
+      RELEASE_SPINLOCK(m->spinlock);
+      if (pending >= 0) {
+	SEM_RAISE(m->signal);
+      }
+    }
+    ret = 0;
+  }
+  return ret;
+}
+#else /* USE_FUTEX */
+int
+unlock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
+{
+  int ret = EPERM;
+
+   if (tcr == NULL) {
+    tcr = get_tcr(true);
+  }
+
+  if (m->owner == tcr) {
+    --m->count;
+    if (m->count == 0) {
+      m->owner = NULL;
+      unlock_futex(&m->avail);
+    }
+    ret = 0;
+  }
+  return ret;
+}
+#endif /* USE_FUTEX */
+
+void
+destroy_recursive_lock(RECURSIVE_LOCK m)
+{
+#ifndef USE_FUTEX
+  destroy_semaphore((void **)&m->signal);
+#endif
+  postGCfree((void *)(m->malloced_ptr));
+}
+
+/*
+  If we're already the owner (or if the lock is free), lock it
+  and increment the lock count; otherwise, return EBUSY without
+  waiting.
+*/
+
+#ifndef USE_FUTEX
+int
+recursive_lock_trylock(RECURSIVE_LOCK m, TCR *tcr, int *was_free)
+{
+  TCR *owner = m->owner;
+
+  LOCK_SPINLOCK(m->spinlock,tcr);
+  if (owner == tcr) {
+    m->count++;
+    if (was_free) {
+      *was_free = 0;
+      RELEASE_SPINLOCK(m->spinlock);
+      return 0;
+    }
+  }
+  if (store_conditional((natural*)&(m->avail), 0, 1) == 0) {
+    m->owner = tcr;
+    m->count = 1;
+    if (was_free) {
+      *was_free = 1;
+    }
+    RELEASE_SPINLOCK(m->spinlock);
+    return 0;
+  }
+
+  RELEASE_SPINLOCK(m->spinlock);
+  return EBUSY;
+}
+#else
+int
+recursive_lock_trylock(RECURSIVE_LOCK m, TCR *tcr, int *was_free)
+{
+  TCR *owner = m->owner;
+
+  if (owner == tcr) {
+    m->count++;
+    if (was_free) {
+      *was_free = 0;
+      return 0;
+    }
+  }
+  if (store_conditional((natural*)&(m->avail), 0, 1) == 0) {
+    m->owner = tcr;
+    m->count = 1;
+    if (was_free) {
+      *was_free = 1;
+    }
+    return 0;
+  }
+
+  return EBUSY;
+}
+#endif
+
+void
+sem_wait_forever(SEMAPHORE s)
+{
+  int status;
+
+  do {
+#ifdef USE_MACH_SEMAPHORES
+    mach_timespec_t q = {1,0};
+    status = SEM_TIMEDWAIT(s,q);
+#endif
+#ifdef USE_POSIX_SEMAPHORES
+    struct timespec q;
+    gettimeofday((struct timeval *)&q, NULL);
+    q.tv_sec += 1;
+    status = SEM_TIMEDWAIT(s,&q);
+#endif
+#ifdef USE_WINDOWS_SEMAPHORES
+    status = (WaitForSingleObject(s,1000L) == WAIT_TIMEOUT) ? 1 : 0;
+#endif
+  } while (status != 0);
+}
+
+int
+wait_on_semaphore(void *s, int seconds, int millis)
+{
+#ifdef USE_POSIX_SEMAPHORES
+  int nanos = (millis % 1000) * 1000000;
+  int status;
+
+  struct timespec q;
+  gettimeofday((struct timeval *)&q, NULL);
+  q.tv_nsec *= 1000L;  /* microseconds -> nanoseconds */
+    
+  q.tv_nsec += nanos;
+  if (q.tv_nsec >= 1000000000L) {
+    q.tv_nsec -= 1000000000L;
+    seconds += 1;
+  }
+  q.tv_sec += seconds;
+  status = SEM_TIMEDWAIT(s, &q);
+  if (status < 0) {
+    return errno;
+  }
+  return status;
+#endif
+#ifdef USE_MACH_SEMAPHORES
+  int nanos = (millis % 1000) * 1000000;
+  mach_timespec_t q = {seconds, nanos};
+  int status = SEM_TIMEDWAIT(s, q);
+
+  
+  switch (status) {
+  case 0: return 0;
+  case KERN_OPERATION_TIMED_OUT: return ETIMEDOUT;
+  case KERN_ABORTED: return EINTR;
+  default: return EINVAL;
+  }
+#endif
+#ifdef USE_WINDOWS_SEMAPHORES
+  switch (WaitForSingleObjectEx(s, seconds*1000L+(DWORD)millis,true)) {
+  case WAIT_OBJECT_0:
+    return 0;
+  case WAIT_TIMEOUT:
+    return /* ETIMEDOUT */ WAIT_TIMEOUT;
+  case WAIT_IO_COMPLETION:
+    return EINTR;
+  default:
+    break;
+  }
+  return EINVAL;
+
+#endif
+}
+
+
+int
+semaphore_maybe_timedwait(void *s, struct timespec *t)
+{
+  if (t) {
+    return wait_on_semaphore(s, t->tv_sec, t->tv_nsec/1000000L);
+  }
+  SEM_WAIT_FOREVER(s);
+  return 0;
+}
+
+void
+signal_semaphore(SEMAPHORE s)
+{
+  SEM_RAISE(s);
+}
+
+  
+#ifdef WINDOWS
+LispObj
+current_thread_osid()
+{
+  TCR *tcr = get_tcr(false);
+  LispObj current = 0;
+
+  if (tcr) {
+    current = tcr->osid;
+  }
+  if (current == 0) {
+    DuplicateHandle(GetCurrentProcess(),
+                    GetCurrentThread(),
+                    GetCurrentProcess(),
+                    (LPHANDLE)(&current),
+                    0,
+                    FALSE,
+                    DUPLICATE_SAME_ACCESS);
+    if (tcr) {
+      tcr->osid = current;
+    }
+  }
+  return current;
+}
+#else
+LispObj
+current_thread_osid()
+{
+  return (LispObj)ptr_to_lispobj(pthread_self());
+}
+#endif
+
+
+int thread_suspend_signal = 0, thread_kill_signal = 0;
+
+
+
+void
+linux_exception_init(TCR *tcr)
+{
+}
+
+
+TCR *
+get_interrupt_tcr(Boolean create)
+{
+  return get_tcr(create);
+}
+  
+void
+suspend_resume_handler(int signo, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_interrupt_tcr(false);
+  
+  if (tcr == NULL) {
+    /* Got a suspend signal sent to the pthread. */
+    extern natural initial_stack_size;
+    void register_thread_tcr(TCR *);
+    
+    tcr = new_tcr(initial_stack_size, MIN_TSTACK_SIZE);
+    tcr->suspend_count = 1;
+    tcr->vs_area->active -= node_size;
+    *(--tcr->save_vsp) = lisp_nil;
+    register_thread_tcr(tcr);
+  }
+  if (TCR_INTERRUPT_LEVEL(tcr) <= (-2<<fixnumshift)) {
+    SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_SUSPEND);
+  } else {
+    tcr->suspend_context = context;
+    SEM_RAISE(tcr->suspend);
+    SEM_WAIT_FOREVER(tcr->resume);
+    tcr->suspend_context = NULL;
+  }
+#ifdef DARWIN_GS_HACK
+  if (gs_was_tcr) {
+    set_gs_address(tcr);
+  }
+#endif
+  SIGRETURN(context);
+}
+
+  
+
+/*
+  'base' should be set to the bottom (origin) of the stack, e.g., the
+  end from which it grows.
+*/
+  
+#ifdef WINDOWS
+void
+os_get_current_thread_stack_bounds(void **base, natural *size)
+{
+  natural natbase;
+  MEMORY_BASIC_INFORMATION info;
+  void *addr = (void *)current_stack_pointer();
+  
+  VirtualQuery(addr, &info, sizeof(info));
+  natbase = (natural)info.BaseAddress+info.RegionSize;
+  *size = natbase - (natural)(info.AllocationBase);
+  *base = (void *)natbase;
+}
+#else
+void
+os_get_current_thread_stack_bounds(void **base, natural *size)
+{
+  pthread_t p = pthread_self();
+#ifdef DARWIN
+  *base = pthread_get_stackaddr_np(p);
+  *size = pthread_get_stacksize_np(p);
+#endif
+#ifdef LINUX
+  pthread_attr_t attr;
+
+  pthread_getattr_np(p,&attr);
+  pthread_attr_getstack(&attr, base, size);
+  pthread_attr_destroy(&attr);
+  *(natural *)base += *size;
+#endif
+#ifdef FREEBSD
+  pthread_attr_t attr;
+  void * temp_base;
+  size_t temp_size;
+  
+
+  pthread_attr_init(&attr);  
+  pthread_attr_get_np(p, &attr);
+  pthread_attr_getstackaddr(&attr,&temp_base);
+  pthread_attr_getstacksize(&attr,&temp_size);
+  *base = (void *)((natural)temp_base + temp_size);
+  *size = temp_size;
+  pthread_attr_destroy(&attr);
+#endif
+#ifdef SOLARIS
+  stack_t st;
+  
+  thr_stksegment(&st);
+  *size = st.ss_size;
+  *base = st.ss_sp;
+  
+#endif
+}
+#endif
+
+void *
+new_semaphore(int count)
+{
+#ifdef USE_POSIX_SEMAPHORES
+  sem_t *s = malloc(sizeof(sem_t));
+  sem_init(s, 0, count);
+  return s;
+#endif
+#ifdef USE_MACH_SEMAPHORES
+  semaphore_t s = (semaphore_t)0;
+  semaphore_create(mach_task_self(),&s, SYNC_POLICY_FIFO, count);
+  return (void *)(natural)s;
+#endif
+#ifdef USE_WINDOWS_SEMAPHORES
+  return CreateSemaphore(NULL, count, 0x7fffL, NULL);
+#endif
+}
+
+RECURSIVE_LOCK
+new_recursive_lock()
+{
+  extern int cache_block_size;
+  void *p = calloc(1,sizeof(_recursive_lock)+cache_block_size-1);
+  RECURSIVE_LOCK m = NULL;
+#ifndef USE_FUTEX
+  void *signal = new_semaphore(0);
+#endif
+  if (p) {
+    m = (RECURSIVE_LOCK) ((((natural)p)+cache_block_size-1) & (~(cache_block_size-1)));
+    m->malloced_ptr = p;
+  }
+
+#ifdef USE_FUTEX
+  if (m) {
+    return m;
+  }
+#else
+  if (m && signal) {
+    m->signal = signal;
+    return m;
+  }
+  if (m) {
+    free(p);
+  }
+  if (signal) {
+    destroy_semaphore(&signal);
+  }
+#endif
+  return NULL;
+}
+
+void
+destroy_semaphore(void **s)
+{
+  if (*s) {
+#ifdef USE_POSIX_SEMAPHORES
+    sem_destroy((sem_t *)*s);
+    if (lisp_global(IN_GC)) {
+      postGCfree(*s);
+    } else {
+      free(*s);
+    }
+#endif
+#ifdef USE_MACH_SEMAPHORES
+    semaphore_destroy(mach_task_self(),((semaphore_t)(natural) *s));
+#endif
+#ifdef USE_WINDOWS_SEMAPHORES
+    CloseHandle(*s);
+#endif
+    *s=NULL;
+  }
+}
+
+#ifdef WINDOWS
+void
+tsd_set(LispObj key, void *datum)
+{
+  TlsSetValue((DWORD)key, datum);
+}
+
+void *
+tsd_get(LispObj key)
+{
+  return TlsGetValue((DWORD)key);
+}
+#else
+void
+tsd_set(LispObj key, void *datum)
+{
+  pthread_setspecific((pthread_key_t)key, datum);
+}
+
+void *
+tsd_get(LispObj key)
+{
+  return pthread_getspecific((pthread_key_t)key);
+}
+#endif
+
+void
+dequeue_tcr(TCR *tcr)
+{
+  TCR *next, *prev;
+
+  next = tcr->next;
+  prev = tcr->prev;
+
+  prev->next = next;
+  next->prev = prev;
+  tcr->prev = tcr->next = NULL;
+#ifdef X8664
+  tcr->linear = NULL;
+#endif
+}
+  
+void
+enqueue_tcr(TCR *new)
+{
+  TCR *head, *tail;
+  
+  LOCK(lisp_global(TCR_AREA_LOCK),new);
+  head = (TCR *)ptr_from_lispobj(lisp_global(INITIAL_TCR));
+  tail = head->prev;
+  tail->next = new;
+  head->prev = new;
+  new->prev = tail;
+  new->next = head;
+  UNLOCK(lisp_global(TCR_AREA_LOCK),new);
+}
+
+#ifdef WIN_32
+TCR *
+allocate_tcr()
+{
+  void *p = calloc(1,sizeof(TCR)+15);
+  TCR *tcr = (TCR *)((((natural)p)+15)&~15);
+
+  tcr->allocated = p;
+  return tcr;
+}
+#else
+TCR *
+allocate_tcr()
+{
+  TCR *tcr, *chain = NULL, *next;
+#ifdef DARWIN
+  extern Boolean use_mach_exception_handling;
+  kern_return_t kret;
+  mach_port_t 
+    thread_exception_port,
+    task_self = mach_task_self();
+#endif
+  for (;;) {
+    tcr = calloc(1, sizeof(TCR));
+#ifdef DARWIN
+#if WORD_SIZE == 64
+    if (((unsigned)((natural)tcr)) != ((natural)tcr)) {
+      tcr->next = chain;
+      chain = tcr;
+      continue;
+    }
+#endif
+    if (use_mach_exception_handling) {
+      thread_exception_port = (mach_port_t)((natural)tcr);
+      kret = mach_port_allocate_name(task_self,
+                                     MACH_PORT_RIGHT_RECEIVE,
+                                     thread_exception_port);
+    } else {
+      kret = KERN_SUCCESS;
+    }
+
+    if (kret != KERN_SUCCESS) {
+      tcr->next = chain;
+      chain = tcr;
+      continue;
+    }
+#endif
+    for (;chain;chain = next) {
+      next = chain->next;
+      free(chain);
+    }
+    return tcr;
+  }
+}
+#endif
+
+#ifdef X8664
+#ifdef LINUX
+#include <asm/prctl.h>
+#include <sys/prctl.h>
+#endif
+#ifdef FREEBSD
+#include <machine/sysarch.h>
+#endif
+
+void
+setup_tcr_extra_segment(TCR *tcr)
+{
+#ifdef FREEBSD
+  amd64_set_gsbase(tcr);
+#endif
+#ifdef LINUX
+  arch_prctl(ARCH_SET_GS, (natural)tcr);
+#endif
+#ifdef DARWIN
+  /* There's no way to do this yet.  See DARWIN_GS_HACK */
+  /* darwin_set_x8664_fs_reg(tcr); */
+#endif
+#ifdef SOLARIS
+  /* Chris Curtis found this and suggested the use of syscall here */
+  syscall(SYS_lwp_private,_LWP_SETPRIVATE, _LWP_GSBASE, tcr);
+#endif
+}
+
+#endif
+
+#ifdef X8632
+
+#ifdef DARWIN
+#include <architecture/i386/table.h>
+#include <architecture/i386/sel.h>
+#include <i386/user_ldt.h>
+
+void setup_tcr_extra_segment(TCR *tcr)
+{
+    uintptr_t addr = (uintptr_t)tcr;
+    unsigned int size = sizeof(*tcr);
+    ldt_entry_t desc;
+    sel_t sel;
+    int i;
+
+    desc.data.limit00 = (size - 1) & 0xffff;
+    desc.data.limit16 = ((size - 1) >> 16) & 0xf;
+    desc.data.base00 = addr & 0xffff;
+    desc.data.base16 = (addr >> 16) & 0xff;
+    desc.data.base24 = (addr >> 24) & 0xff;
+    desc.data.type = DESC_DATA_WRITE;
+    desc.data.dpl = USER_PRIV;
+    desc.data.present = 1;
+    desc.data.stksz = DESC_CODE_32B;
+    desc.data.granular = DESC_GRAN_BYTE;
+    
+    i = i386_set_ldt(LDT_AUTO_ALLOC, &desc, 1);
+
+    if (i < 0) {
+	perror("i386_set_ldt");
+    } else {
+	sel.index = i;
+	sel.rpl = USER_PRIV;
+	sel.ti = SEL_LDT;
+	tcr->ldt_selector = sel;
+    }
+}
+
+void free_tcr_extra_segment(TCR *tcr)
+{
+  /* load %fs with null segement selector */
+  __asm__ volatile ("mov %0,%%fs" : : "r"(0));
+  if (i386_set_ldt(tcr->ldt_selector.index, NULL, 1) < 0)
+    perror("i386_set_ldt");
+  tcr->ldt_selector = NULL_SEL;
+}
+#endif
+
+#ifdef LINUX
+
+#include <asm/ldt.h>
+#include <sys/syscall.h>
+
+/* see desc_struct in kernel/include/asm-i386/processor.h */
+typedef struct {
+  uint32_t a;
+  uint32_t b;
+} linux_desc_struct;
+
+
+#define desc_avail(d) (((d)->a) == 0)
+
+linux_desc_struct linux_ldt_entries[LDT_ENTRIES];
+
+/* We have to ask the Linux kernel for a copy of the ldt table
+   and manage it ourselves.  It's not clear that this is 
+   thread-safe in general, but we can at least ensure that
+   it's thread-safe wrt lisp threads. */
+
+pthread_mutex_t ldt_lock = PTHREAD_MUTEX_INITIALIZER;  /* simple, non-recursive mutex */
+
+int
+modify_ldt(int func, void *ptr, unsigned long bytecount)
+{
+  return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
+
+
+void
+setup_tcr_extra_segment(TCR *tcr)
+{
+  int i, n;
+  short sel;
+  struct user_desc u = {1, 0, 0, 1, MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 1};
+  linux_desc_struct *d = linux_ldt_entries;
+
+  pthread_mutex_lock(&ldt_lock);
+  n = modify_ldt(0,d,LDT_ENTRIES*LDT_ENTRY_SIZE)/LDT_ENTRY_SIZE;
+  for (i = 0; i < n; i++,d++) {
+    if (desc_avail(d)) {
+      break;
+    }
+  }
+  if (i == LDT_ENTRIES) {
+    pthread_mutex_unlock(&ldt_lock);
+    fprintf(dbgout, "All 8192 ldt entries in use ?\n");
+    _exit(1);
+  }
+  u.entry_number = i;
+  u.base_addr = (uint32_t)tcr;
+  u.limit = sizeof(TCR);
+  u.limit_in_pages = 0;
+  if (modify_ldt(1,&u,sizeof(struct user_desc)) != 0) {
+    pthread_mutex_unlock(&ldt_lock);
+    fprintf(dbgout,"Can't assign LDT entry\n");
+    _exit(1);
+  }
+  sel = (i << 3) | 7;
+  tcr->ldt_selector = sel;
+  pthread_mutex_unlock(&ldt_lock);
+}
+
+void
+free_tcr_extra_segment(TCR *tcr)
+{
+  struct user_desc u = {0, 0, 0, 0, MODIFY_LDT_CONTENTS_DATA, 0, 0, 0, 0};
+  short sel = tcr->ldt_selector;
+
+  pthread_mutex_lock(&ldt_lock);
+  /* load %fs with null segment selector */
+  __asm__ volatile ("mov %0,%%fs" : : "r"(0));
+  tcr->ldt_selector = 0;
+  u.entry_number = (sel>>3);
+  modify_ldt(1,&u,sizeof(struct user_desc));
+  pthread_mutex_unlock(&ldt_lock);
+  
+}
+
+#endif
+
+#ifdef WINDOWS
+bitvector ldt_entries_in_use = NULL;
+HANDLE ldt_lock;
+
+typedef struct {
+  DWORD offset;
+  DWORD size;
+  LDT_ENTRY entry;
+} win32_ldt_info;
+
+
+int WINAPI (*NtQueryInformationProcess)(HANDLE,DWORD,VOID*,DWORD,DWORD*);
+int WINAPI (*NtSetInformationProcess)(HANDLE,DWORD,VOID*,DWORD);
+
+void
+init_win32_ldt()
+{
+  HANDLE hNtdll;
+  int status = 0xc0000002;
+  win32_ldt_info info;
+  DWORD nret;
+  
+
+  ldt_entries_in_use=malloc(8192/8);
+  zero_bits(ldt_entries_in_use,8192);
+  ldt_lock = CreateMutex(NULL,0,NULL);
+
+  hNtdll = LoadLibrary("ntdll.dll");
+  NtQueryInformationProcess = (void*)GetProcAddress(hNtdll, "NtQueryInformationProcess");
+  NtSetInformationProcess = (void*)GetProcAddress(hNtdll, "NtSetInformationProcess");
+  if (NtQueryInformationProcess != NULL) {
+    info.offset = 0;
+    info.size = sizeof(LDT_ENTRY);
+    status = NtQueryInformationProcess(GetCurrentProcess(),10,&info,sizeof(info),&nret);
+  }
+
+  if (status) {
+    fprintf(dbgout, "This application can't run under this OS version\n");
+    _exit(1);
+  }
+}
+
+void
+setup_tcr_extra_segment(TCR *tcr)
+{
+  int i, status;
+  DWORD nret;
+  win32_ldt_info info;
+  LDT_ENTRY *entry = &(info.entry);
+  DWORD *words = (DWORD *)entry, tcraddr = (DWORD)tcr;
+
+
+  WaitForSingleObject(ldt_lock,INFINITE);
+
+  for (i = 0; i < 8192; i++) {
+    if (!ref_bit(ldt_entries_in_use,i)) {
+      info.offset = i << 3;
+      info.size = sizeof(LDT_ENTRY);
+      words[0] = 0;
+      words[1] = 0;
+      status = NtQueryInformationProcess(GetCurrentProcess(),10,&info,sizeof(info),&nret);
+      if (status == 0) {
+        if ((info.size == 0) ||
+            ((words[0] == 0) && (words[1] == 0))) {
+          break;
+        }
+      }
+    }
+  }
+  if (i == 8192) {
+    ReleaseMutex(ldt_lock);
+    fprintf(dbgout, "All 8192 ldt entries in use ?\n");
+    _exit(1);
+  }
+  set_bit(ldt_entries_in_use,i);
+  words[0] = 0;
+  words[1] = 0;
+  entry->LimitLow = sizeof(TCR);
+  entry->BaseLow = tcraddr & 0xffff;
+  entry->HighWord.Bits.BaseMid = (tcraddr >> 16) & 0xff;
+  entry->HighWord.Bits.BaseHi = (tcraddr >> 24);
+  entry->HighWord.Bits.Pres = 1;
+  entry->HighWord.Bits.Default_Big = 1;
+  entry->HighWord.Bits.Type = 16 | 2; /* read-write data */
+  entry->HighWord.Bits.Dpl = 3; /* for use by the great unwashed */
+  info.size = sizeof(LDT_ENTRY);
+  status = NtSetInformationProcess(GetCurrentProcess(),10,&info,sizeof(info));
+  if (status != 0) {
+    ReleaseMutex(ldt_lock);
+    FBug(NULL, "can't set LDT entry %d, status = 0x%x", i, status);
+  }
+#if 1
+  /* Sanity check */
+  info.offset = i << 3;
+  info.size = sizeof(LDT_ENTRY);
+  words[0] = 0;
+  words[0] = 0;
+  NtQueryInformationProcess(GetCurrentProcess(),10,&info,sizeof(info),&nret);
+  if (((entry->BaseLow)|((entry->HighWord.Bits.BaseMid)<<16)|((entry->HighWord.Bits.BaseHi)<<24)) != tcraddr) {
+    Bug(NULL, "you blew it: bad address in ldt entry\n");
+  }
+#endif
+  tcr->ldt_selector = (i << 3) | 7;
+  ReleaseMutex(ldt_lock);
+}
+
+void 
+free_tcr_extra_segment(TCR *tcr)
+{
+  win32_ldt_info info;
+  LDT_ENTRY *entry = &(info.entry);
+  DWORD *words = (DWORD *)entry;
+  int idx = tcr->ldt_selector >> 3;
+
+
+  info.offset = idx << 3;
+  info.size = sizeof(LDT_ENTRY);
+
+  words[0] = 0;
+  words[1] = 0;
+
+  WaitForSingleObject(ldt_lock,INFINITE);
+  NtSetInformationProcess(GetCurrentProcess(),10,&info,sizeof(info));
+  clr_bit(ldt_entries_in_use,idx);
+  ReleaseMutex(ldt_lock);
+
+  tcr->ldt_selector = 0;
+}
+
+#endif
+#ifdef FREEBSD
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+
+/* It'd be tempting to use i386_set_fsbase() here, but there doesn't
+   seem to be any way to free the GDT entry it creates.  Actually,
+   it's not clear that that really sets a GDT entry; let's see */
+
+#define FREEBSD_USE_SET_FSBASE 1
+void
+setup_tcr_extra_segment(TCR *tcr)
+{
+#if !FREEBSD_USE_SET_FSBASE
+  struct segment_descriptor sd;
+  uintptr_t addr = (uintptr_t)tcr;
+  unsigned int size = sizeof(*tcr);
+  int i;
+
+  sd.sd_lolimit = (size - 1) & 0xffff;
+  sd.sd_hilimit = ((size - 1) >> 16) & 0xf;
+  sd.sd_lobase = addr & ((1<<24)-1);
+  sd.sd_hibase = (addr>>24)&0xff;
+
+
+
+  sd.sd_type = 18;
+  sd.sd_dpl = SEL_UPL;
+  sd.sd_p = 1;
+  sd.sd_def32 = 1;
+  sd.sd_gran = 0;
+
+  i = i386_set_ldt(LDT_AUTO_ALLOC, (union descriptor *)&sd, 1);
+
+  if (i < 0) {
+    perror("i386_set_ldt");
+    exit(1);
+  } else {
+    tcr->ldt_selector = LSEL(i,SEL_UPL);
+  }
+#else
+  extern unsigned short get_fs_register(void);
+
+  if (i386_set_fsbase((void*)tcr)) {
+    perror("i386_set_fsbase");
+    exit(1);
+  }
+
+
+  /* Once we've called i386_set_fsbase, we can't write to %fs. */
+  tcr->ldt_selector = GSEL(GUFS_SEL, SEL_UPL);
+#endif
+}
+
+void 
+free_tcr_extra_segment(TCR *tcr)
+{
+#if FREEBSD_USE_SET_FSBASE
+  /* On a 32-bit kernel, this allocates a GDT entry.  It's not clear
+     what it would mean to deallocate that entry. */
+  /* If we're running on a 64-bit kernel, we can't write to %fs */
+#else
+  int idx = tcr->ldt_selector >> 3;
+  /* load %fs with null segment selector */
+  __asm__ volatile ("mov %0,%%fs" : : "r"(0));
+  if (i386_set_ldt(idx, NULL, 1) < 0)
+    perror("i386_set_ldt");
+#endif
+  tcr->ldt_selector = 0;
+}
+#endif
+
+#ifdef SOLARIS
+#include <sys/sysi86.h>
+
+bitvector ldt_entries_in_use = NULL;
+pthread_mutex_t ldt_lock = PTHREAD_MUTEX_INITIALIZER;  /* simple, non-recursive mutex */
+
+void
+solaris_ldt_init()
+{
+  int fd;
+  struct ssd s;
+
+  ldt_entries_in_use=malloc(8192/8);
+  zero_bits(ldt_entries_in_use,8192);
+  
+  fd = open("/proc/self/ldt", O_RDONLY);
+
+  while(read(fd,&s,sizeof(s)) == sizeof(s)) {
+    set_bit(ldt_entries_in_use,s.sel>>3);
+  }
+  close(fd);
+}
+    
+
+void
+setup_tcr_extra_segment(TCR *tcr)
+{
+  struct ssd s;
+  int i;
+
+  pthread_mutex_lock(&ldt_lock);
+
+  for (i = 0; i < 8192; i++) {
+    if (!ref_bit(ldt_entries_in_use,i)) {
+      s.sel = (i<<3)|7;
+      s.bo = (unsigned int)tcr;
+      s.ls = sizeof(TCR);
+      s.acc1 = 0xf2;
+      s.acc2 = 4;
+
+      if (sysi86(SI86DSCR, &s) >= 0) {
+        set_bit(ldt_entries_in_use,i);
+        tcr->ldt_selector = (i<<3)|7;
+        pthread_mutex_unlock(&ldt_lock);
+        return;
+      }
+      set_bit(ldt_entries_in_use,i);
+    }
+  }
+  pthread_mutex_unlock(&ldt_lock);
+  fprintf(dbgout, "All 8192 LDT descriptors in use\n");
+  _exit(1);
+
+
+  
+}
+
+void 
+free_tcr_extra_segment(TCR *tcr)
+{
+  struct ssd s;
+  int i;
+
+  pthread_mutex_lock(&ldt_lock);
+  __asm__ volatile ("mov %0,%%fs" : : "r"(0));
+  s.sel = tcr->ldt_selector;
+  i = s.sel>>3;
+  tcr->ldt_selector = 0;
+  s.bo = 0;
+  s.ls = 0;
+  s.acc1 = 0;
+  s.acc2 = 0;
+  sysi86(SI86DSCR, &s);
+  clr_bit(ldt_entries_in_use,i);
+  pthread_mutex_unlock(&ldt_lock);
+}
+
+#endif
+#endif
+
+/*
+  Caller must hold the area_lock.
+*/
+TCR *
+new_tcr(natural vstack_size, natural tstack_size)
+{
+  extern area
+    *allocate_vstack_holding_area_lock(natural),
+    *allocate_tstack_holding_area_lock(natural);
+  area *a;
+  int i;
+#ifndef WINDOWS
+  sigset_t sigmask;
+
+  sigemptyset(&sigmask);
+  pthread_sigmask(SIG_SETMASK,&sigmask, NULL);
+#endif
+
+#ifdef HAVE_TLS
+  TCR *tcr = (TCR *) ((((natural)&tcrbuf)+((natural)15)) & ~((natural)15));
+  current_tcr = tcr;
+#else /* no TLS */
+  TCR *tcr = allocate_tcr();
+#endif
+
+#ifdef X86
+  setup_tcr_extra_segment(tcr);
+  tcr->linear = tcr;
+#ifdef X8632
+  tcr->node_regs_mask = X8632_DEFAULT_NODE_REGS_MASK;
+#endif
+#endif
+
+#if (WORD_SIZE == 64)
+  tcr->single_float_convert.tag = subtag_single_float;
+#endif
+  tcr->suspend = new_semaphore(0);
+  tcr->resume = new_semaphore(0);
+  tcr->reset_completion = new_semaphore(0);
+  tcr->activate = new_semaphore(0);
+  LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+  a = allocate_vstack_holding_area_lock(vstack_size);
+  tcr->vs_area = a;
+  a->owner = tcr;
+  tcr->save_vsp = (LispObj *) a->active;  
+  a = allocate_tstack_holding_area_lock(tstack_size);
+  UNLOCK(lisp_global(TCR_AREA_LOCK),tcr);
+  tcr->ts_area = a;
+  a->owner = tcr;
+  tcr->save_tsp = (LispObj *) a->active;
+#ifdef X86
+  tcr->next_tsp = tcr->save_tsp;
+#endif
+
+  tcr->valence = TCR_STATE_FOREIGN;
+#ifdef PPC
+  tcr->lisp_fpscr.words.l = 0xd0;
+#endif
+#ifdef X86
+  tcr->lisp_mxcsr = (1 << MXCSR_DM_BIT) | 
+#if 1                           /* Mask underflow; too hard to 
+                                   deal with denorms if underflow is 
+                                   enabled */
+    (1 << MXCSR_UM_BIT) | 
+#endif
+    (1 << MXCSR_PM_BIT);
+#endif
+  tcr->save_allocbase = tcr->save_allocptr = (void *) VOID_ALLOCPTR;
+  tcr->tlb_limit = 2048<<fixnumshift;
+  tcr->tlb_pointer = (LispObj *)malloc(tcr->tlb_limit);
+  for (i = 0; i < 2048; i++) {
+    tcr->tlb_pointer[i] = (LispObj) no_thread_local_binding_marker;
+  }
+  TCR_INTERRUPT_LEVEL(tcr) = (LispObj) (-1<<fixnum_shift);
+#ifndef WINDOWS
+  tcr->shutdown_count = PTHREAD_DESTRUCTOR_ITERATIONS;
+#else
+  tcr->shutdown_count = 1;
+#endif
+  return tcr;
+}
+
+void
+shutdown_thread_tcr(void *arg)
+{
+  TCR *tcr = TCR_FROM_TSD(arg),*current=get_tcr(0);
+
+  area *vs, *ts, *cs;
+  
+  if (current == NULL) {
+    current = tcr;
+  }
+
+  if (--(tcr->shutdown_count) == 0) {
+    if (tcr->flags & (1<<TCR_FLAG_BIT_FOREIGN)) {
+      LispObj callback_macptr = nrs_FOREIGN_THREAD_CONTROL.vcell,
+	callback_ptr = ((macptr *)ptr_from_lispobj(untag(callback_macptr)))->address;
+    
+      tsd_set(lisp_global(TCR_KEY), TCR_TO_TSD(tcr));
+      ((void (*)())ptr_from_lispobj(callback_ptr))(1);
+      tsd_set(lisp_global(TCR_KEY), NULL);
+    }
+#ifdef DARWIN
+    darwin_exception_cleanup(tcr);
+#endif
+    LOCK(lisp_global(TCR_AREA_LOCK),current);
+    vs = tcr->vs_area;
+    tcr->vs_area = NULL;
+    ts = tcr->ts_area;
+    tcr->ts_area = NULL;
+    cs = tcr->cs_area;
+    tcr->cs_area = NULL;
+    if (vs) {
+      condemn_area_holding_area_lock(vs);
+    }
+    if (ts) {
+      condemn_area_holding_area_lock(ts);
+    }
+    if (cs) {
+      condemn_area_holding_area_lock(cs);
+    }
+    destroy_semaphore(&tcr->suspend);
+    destroy_semaphore(&tcr->resume);
+    destroy_semaphore(&tcr->reset_completion);
+    destroy_semaphore(&tcr->activate);
+    tcr->tlb_limit = 0;
+    free(tcr->tlb_pointer);
+    tcr->tlb_pointer = NULL;
+    tcr->osid = 0;
+    tcr->interrupt_pending = 0;
+    tcr->termination_semaphore = NULL;
+#ifdef HAVE_TLS
+    dequeue_tcr(tcr);
+#endif
+#ifdef X8632
+    free_tcr_extra_segment(tcr);
+#endif
+#ifdef WIN32
+    CloseHandle((HANDLE)tcr->io_datum);
+    tcr->io_datum = NULL;
+    free(tcr->native_thread_info);
+    tcr->native_thread_info = NULL;
+#endif
+    UNLOCK(lisp_global(TCR_AREA_LOCK),current);
+  } else {
+    tsd_set(lisp_global(TCR_KEY), TCR_TO_TSD(tcr));
+  }
+}
+
+void
+tcr_cleanup(void *arg)
+{
+  TCR *tcr = (TCR *)arg;
+  area *a;
+
+  a = tcr->vs_area;
+  if (a) {
+    a->active = a->high;
+  }
+  a = tcr->ts_area;
+  if (a) {
+    a->active = a->high;
+  }
+  a = tcr->cs_area;
+  if (a) {
+    a->active = a->high;
+  }
+  tcr->valence = TCR_STATE_FOREIGN;
+  tcr->shutdown_count = 1;
+  shutdown_thread_tcr(tcr);
+  tsd_set(lisp_global(TCR_KEY), NULL);
+}
+
+void *
+current_native_thread_id()
+{
+  return ((void *) (natural)
+#ifdef LINUX
+#ifdef __NR_gettid
+          syscall(__NR_gettid)
+#else
+          getpid()
+#endif
+#endif
+#ifdef DARWIN
+	  mach_thread_self()
+#endif
+#ifdef FREEBSD
+	  pthread_self()
+#endif
+#ifdef SOLARIS
+	  pthread_self()
+#endif
+#ifdef WINDOWS
+	  GetCurrentThreadId()
+#endif
+	  );
+}
+
+
+void
+thread_init_tcr(TCR *tcr, void *stack_base, natural stack_size)
+{
+  area *a, *register_cstack_holding_area_lock(BytePtr, natural);
+
+  tcr->osid = current_thread_osid();
+  tcr->native_thread_id = current_native_thread_id();
+  LOCK(lisp_global(TCR_AREA_LOCK),tcr);
+  a = register_cstack_holding_area_lock((BytePtr)stack_base, stack_size);
+  UNLOCK(lisp_global(TCR_AREA_LOCK),tcr);
+  tcr->cs_area = a;
+  a->owner = tcr;
+  if (!(tcr->flags & (1<<TCR_FLAG_BIT_FOREIGN))) {
+    tcr->cs_limit = (LispObj)ptr_to_lispobj(a->softlimit);
+  }
+#ifdef LINUX
+#ifdef PPC
+#ifndef PPC64
+  tcr->native_thread_info = current_r2;
+#endif
+#endif
+#endif
+  tcr->errno_loc = &errno;
+  tsd_set(lisp_global(TCR_KEY), TCR_TO_TSD(tcr));
+#ifdef DARWIN
+  extern Boolean use_mach_exception_handling;
+  if (use_mach_exception_handling) {
+    darwin_exception_init(tcr);
+  }
+#endif
+#ifdef LINUX
+  linux_exception_init(tcr);
+#endif
+#ifdef WINDOWS
+  tcr->io_datum = (VOID *)CreateEvent(NULL, true, false, NULL);
+  tcr->native_thread_info = malloc(sizeof(CONTEXT));
+#endif
+  tcr->log2_allocation_quantum = unbox_fixnum(lisp_global(DEFAULT_ALLOCATION_QUANTUM));
+}
+
+/*
+  Register the specified tcr as "belonging to" the current thread.
+  Under Darwin, setup Mach exception handling for the thread.
+  Install cleanup handlers for thread termination.
+*/
+void
+register_thread_tcr(TCR *tcr)
+{
+  void *stack_base = NULL;
+  natural stack_size = 0;
+
+  os_get_current_thread_stack_bounds(&stack_base, &stack_size);
+  thread_init_tcr(tcr, stack_base, stack_size);
+  enqueue_tcr(tcr);
+}
+
+
+  
+  
+#ifndef MAP_GROWSDOWN
+#define MAP_GROWSDOWN 0
+#endif
+
+Ptr
+create_stack(natural size)
+{
+  Ptr p;
+  size=align_to_power_of_2(size, log2_page_size);
+  p = (Ptr) MapMemoryForStack((size_t)size);
+  if (p != (Ptr)(-1)) {
+    *((size_t *)p) = size;
+    return p;
+  }
+  allocation_failure(true, size);
+
+}
+
+void *
+allocate_stack(natural size)
+{
+  return create_stack(size);
+}
+
+void
+free_stack(void *s)
+{
+  size_t size = *((size_t *)s);
+  UnMapMemory(s, size);
+}
+
+Boolean threads_initialized = false;
+
+#ifndef USE_FUTEX
+#ifdef WINDOWS
+void
+count_cpus()
+{
+  SYSTEM_INFO si;
+
+  GetSystemInfo(&si);
+  if (si.dwNumberOfProcessors > 1) {
+    spin_lock_tries = 1024;
+  }
+}
+#else
+void
+count_cpus()
+{
+#ifdef DARWIN
+  /* As of OSX 10.4, Darwin doesn't define _SC_NPROCESSORS_ONLN */
+#include <mach/host_info.h>
+
+  struct host_basic_info info;
+  mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
+  
+  if (KERN_SUCCESS == host_info(mach_host_self(), HOST_BASIC_INFO,(host_info_t)(&info),&count)) {
+    if (info.max_cpus > 1) {
+      spin_lock_tries = 1024;
+    }
+  }
+#else
+  int n = sysconf(_SC_NPROCESSORS_ONLN);
+  
+  if (n > 1) {
+    spin_lock_tries = 1024;
+  }
+#endif
+}
+#endif
+#endif
+
+void
+init_threads(void * stack_base, TCR *tcr)
+{
+  lisp_global(INITIAL_TCR) = (LispObj)ptr_to_lispobj(tcr);
+#ifdef WINDOWS
+  lisp_global(TCR_KEY) = TlsAlloc();
+  pCancelIoEx = windows_find_symbol(NULL, "CancelIoEx");
+  pCancelSynchronousIo = windows_find_symbol(NULL, "CancelSynchronousIo");
+#else
+  pthread_key_create((pthread_key_t *)&(lisp_global(TCR_KEY)), shutdown_thread_tcr);
+  thread_signal_setup();
+#endif
+
+#ifndef USE_FUTEX
+  count_cpus();
+#endif
+  threads_initialized = true;
+}
+
+
+#ifdef WINDOWS
+unsigned CALLBACK
+#else
+void *
+#endif
+lisp_thread_entry(void *param)
+{
+  thread_activation *activation = (thread_activation *)param;
+  TCR *tcr = new_tcr(activation->vsize, activation->tsize);
+  LispObj *start_vsp;
+#ifndef WINDOWS
+  sigset_t mask, old_mask;
+
+  sigemptyset(&mask);
+  pthread_sigmask(SIG_SETMASK, &mask, &old_mask);
+#endif
+
+  register_thread_tcr(tcr);
+
+#ifndef WINDOWS
+  pthread_cleanup_push(tcr_cleanup,(void *)tcr);
+#endif
+  tcr->vs_area->active -= node_size;
+  *(--tcr->save_vsp) = lisp_nil;
+  start_vsp = tcr->save_vsp;
+  enable_fp_exceptions();
+  SET_TCR_FLAG(tcr,TCR_FLAG_BIT_AWAITING_PRESET);
+  activation->tcr = tcr;
+  SEM_RAISE(activation->created);
+  do {
+    SEM_RAISE(tcr->reset_completion);
+    SEM_WAIT_FOREVER(tcr->activate);
+    /* Now go run some lisp code */
+    start_lisp(TCR_TO_TSD(tcr),0);
+    tcr->save_vsp = start_vsp;
+  } while (tcr->flags & (1<<TCR_FLAG_BIT_AWAITING_PRESET));
+#ifndef WINDOWS
+  pthread_cleanup_pop(true);
+#else
+  tcr_cleanup(tcr);
+#endif
+#ifdef WINDOWS
+  return 0;
+#else
+  return NULL;
+#endif
+}
+
+typedef 
+short (*suspendf)();
+
+
+void
+suspend_current_cooperative_thread()
+{
+  static suspendf cooperative_suspend = NULL;
+  void *xFindSymbol(void*,char*);
+
+  if (cooperative_suspend == NULL) {
+    cooperative_suspend = (suspendf)xFindSymbol(NULL, "SetThreadState");
+  }
+  if (cooperative_suspend) {
+    cooperative_suspend(1 /* kCurrentThreadID */,
+                        1 /* kStoppedThreadState */,
+                        0 /* kAnyThreadID */);
+  }
+}
+
+void *
+cooperative_thread_startup(void *arg)
+{
+
+  TCR *tcr = get_tcr(0);
+  LispObj *start_vsp;
+
+  if (!tcr) {
+    return NULL;
+  }
+#ifndef WINDOWS
+  pthread_cleanup_push(tcr_cleanup,(void *)tcr);
+#endif
+  SET_TCR_FLAG(tcr,TCR_FLAG_BIT_AWAITING_PRESET);
+  start_vsp = tcr->save_vsp;
+  do {
+    SEM_RAISE(tcr->reset_completion);
+    suspend_current_cooperative_thread();
+      
+    start_lisp(tcr, 0);
+    tcr->save_vsp = start_vsp;
+  } while (tcr->flags & (1<<TCR_FLAG_BIT_AWAITING_PRESET));
+#ifndef WINDOWS
+  pthread_cleanup_pop(true);
+#else
+  tcr_cleanup(tcr);
+#endif
+}
+
+void *
+xNewThread(natural control_stack_size,
+	   natural value_stack_size,
+	   natural temp_stack_size)
+
+{
+  thread_activation activation;
+
+
+  activation.tsize = temp_stack_size;
+  activation.vsize = value_stack_size;
+  activation.tcr = 0;
+  activation.created = new_semaphore(0);
+  if (create_system_thread(control_stack_size +(CSTACK_HARDPROT+CSTACK_SOFTPROT), 
+                           NULL, 
+                           lisp_thread_entry,
+                           (void *) &activation)) {
+    
+    SEM_WAIT_FOREVER(activation.created);	/* Wait until thread's entered its initial function */
+  }
+  destroy_semaphore(&activation.created);  
+  return TCR_TO_TSD(activation.tcr);
+}
+
+Boolean
+active_tcr_p(TCR *q)
+{
+  TCR *head = (TCR *)ptr_from_lispobj(lisp_global(INITIAL_TCR)), *p = head;
+  
+  do {
+    if (p == q) {
+      return true;
+    }
+    p = p->next;
+  } while (p != head);
+  return false;
+}
+
+#ifdef WINDOWS
+OSErr
+xDisposeThread(TCR *tcr)
+{
+  return 0;                     /* I don't think that this is ever called. */
+}
+#else
+OSErr
+xDisposeThread(TCR *tcr)
+{
+  if (tcr != (TCR *)ptr_from_lispobj(lisp_global(INITIAL_TCR))) {
+    if (active_tcr_p(tcr) && (tcr != get_tcr(false))) {
+      pthread_cancel((pthread_t)(tcr->osid));
+      return 0;
+    }
+  }
+  return -50;
+}
+#endif
+
+OSErr
+xYieldToThread(TCR *target)
+{
+  Bug(NULL, "xYieldToThread ?");
+  return 0;
+}
+  
+OSErr
+xThreadCurrentStackSpace(TCR *tcr, unsigned *resultP)
+{
+  Bug(NULL, "xThreadCurrentStackSpace ?");
+  return 0;
+}
+
+
+#ifdef WINDOWS
+LispObj
+create_system_thread(size_t stack_size,
+		     void* stackaddr,
+		     unsigned CALLBACK (*start_routine)(void *),
+		     void* param)
+{
+  HANDLE thread_handle;
+
+  stack_size = ((stack_size+(((1<<16)-1)))&~((1<<16)-1));
+
+  thread_handle = (HANDLE)_beginthreadex(NULL, 
+                                         0/*stack_size*/,
+                                         start_routine,
+                                         param,
+                                         0, 
+                                         NULL);
+
+  if (thread_handle == NULL) {
+    wperror("CreateThread");
+  }
+  return (LispObj) ptr_to_lispobj(thread_handle);
+}
+#else
+LispObj
+create_system_thread(size_t stack_size,
+		     void* stackaddr,
+		     void* (*start_routine)(void *),
+		     void* param)
+{
+  pthread_attr_t attr;
+  pthread_t returned_thread = (pthread_t) 0;
+  TCR *current = get_tcr(true);
+
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
+
+  if (stack_size == MINIMAL_THREAD_STACK_SIZE) {
+    stack_size = PTHREAD_STACK_MIN;
+  }
+
+  stack_size = ensure_stack_limit(stack_size);
+  if (stackaddr != NULL) {
+    /* Size must have been specified.  Sort of makes sense ... */
+#ifdef DARWIN
+    Fatal("no pthread_attr_setsetstack. "," Which end of stack does address refer to?");
+#else
+    pthread_attr_setstack(&attr, stackaddr, stack_size);
+#endif
+  } else if (stack_size != DEFAULT_THREAD_STACK_SIZE) {
+    pthread_attr_setstacksize(&attr,stack_size);
+  }
+
+  /* 
+     I think that's just about enough ... create the thread.
+     Well ... not quite enough.  In Leopard (at least), many
+     pthread routines grab an internal spinlock when validating
+     their arguments.  If we suspend a thread that owns this
+     spinlock, we deadlock.  We can't in general keep that
+     from happening: if arbitrary C code is suspended while
+     it owns the spinlock, we still deadlock.  It seems that
+     the best that we can do is to keep -this- code from
+     getting suspended (by grabbing TCR_AREA_LOCK)
+  */
+  LOCK(lisp_global(TCR_AREA_LOCK),current);
+  pthread_create(&returned_thread, &attr, start_routine, param);
+  UNLOCK(lisp_global(TCR_AREA_LOCK),current);
+  pthread_attr_destroy(&attr);
+  return (LispObj) ptr_to_lispobj(returned_thread);
+}
+#endif
+
+TCR *
+get_tcr(Boolean create)
+{
+#ifdef HAVE_TLS
+  TCR *current = current_tcr;
+#else
+  void *tsd = (void *)tsd_get(lisp_global(TCR_KEY));
+  TCR *current = (tsd == NULL) ? NULL : TCR_FROM_TSD(tsd);
+#endif
+
+  if ((current == NULL) && create) {
+    LispObj callback_macptr = nrs_FOREIGN_THREAD_CONTROL.vcell,
+      callback_ptr = ((macptr *)ptr_from_lispobj(untag(callback_macptr)))->address;
+    int i, nbindwords = 0;
+    extern natural initial_stack_size;
+    
+    /* Make one. */
+    current = new_tcr(initial_stack_size, MIN_TSTACK_SIZE);
+    SET_TCR_FLAG(current,TCR_FLAG_BIT_FOREIGN);
+    register_thread_tcr(current);
+#ifdef DEBUG_TCR_CREATION
+#ifndef WINDOWS
+    fprintf(dbgout, "\ncreating TCR for pthread 0x%x", pthread_self());
+#endif
+#endif
+    current->vs_area->active -= node_size;
+    *(--current->save_vsp) = lisp_nil;
+#ifdef PPC
+#define NSAVEREGS 8
+#endif
+#ifdef X8664
+#define NSAVEREGS 4
+#endif
+#ifdef X8632
+#define NSAVEREGS 0
+#endif
+    for (i = 0; i < NSAVEREGS; i++) {
+      *(--current->save_vsp) = 0;
+      current->vs_area->active -= node_size;
+    }
+    nbindwords = ((int (*)())ptr_from_lispobj(callback_ptr))(-1);
+    for (i = 0; i < nbindwords; i++) {
+      *(--current->save_vsp) = 0;
+      current->vs_area->active -= node_size;
+    }
+    current->shutdown_count = 1;
+    ((void (*)())ptr_from_lispobj(callback_ptr))(0);
+
+  }
+  
+  return current;
+}
+
+#ifdef WINDOWS
+void *
+pc_luser_restore_windows_context(CONTEXT *pcontext, TCR *tcr, pc where)
+{
+  /* Thread has started to return from an exception. */
+  if (where < restore_windows_context_iret) {
+    /* In the process of restoring registers; context still in
+       %rcx.  Just make our suspend_context be the context
+       we're trying to restore, so that we'll resume from
+       the suspend in the same context that we're trying to
+       restore */
+#ifdef WIN_64
+    *pcontext = * (CONTEXT *)(pcontext->Rcx);
+#else
+    *pcontext = * (CONTEXT *)(pcontext->Ecx);
+#endif
+  } else {
+    /* Most of the context has already been restored; fix %rcx
+       if need be, then restore ss:rsp, cs:rip, and flags. */
+#ifdef WIN_64
+    x64_iret_frame *iret_frame = (x64_iret_frame *) (pcontext->Rsp);
+
+    pcontext->Rip = iret_frame->Rip;
+    pcontext->SegCs = (WORD) iret_frame->Cs;
+    pcontext->EFlags = (DWORD) iret_frame->Rflags;
+    pcontext->Rsp = iret_frame->Rsp;
+    pcontext->SegSs = (WORD) iret_frame->Ss;
+#else
+    ia32_iret_frame *iret_frame = (ia32_iret_frame *) (pcontext->Esp);
+
+    pcontext->Eip = iret_frame->Eip;
+    pcontext->SegCs = (WORD) iret_frame->Cs;
+    pcontext->EFlags = (DWORD) iret_frame->EFlags;
+    pcontext->Esp += sizeof(ia32_iret_frame);
+#endif
+  }
+  tcr->pending_exception_context = NULL;
+}
+
+Boolean
+suspend_tcr(TCR *tcr)
+{
+  int suspend_count = atomic_incf(&(tcr->suspend_count));
+  DWORD rc;
+  if (suspend_count == 1) {
+    CONTEXT  *pcontext = (CONTEXT *)tcr->native_thread_info;
+    HANDLE hthread = (HANDLE)(tcr->osid);
+    pc where;
+    area *cs = tcr->cs_area;
+    LispObj foreign_rsp;
+
+    if (hthread == NULL) {
+      return false;
+    }
+    rc = SuspendThread(hthread);
+    if (rc == -1) {
+      /* If the thread's simply dead, we should handle that here */
+      return false;
+    }
+    pcontext->ContextFlags = CONTEXT_ALL;
+    rc = GetThreadContext(hthread, pcontext);
+    if (rc == 0) {
+      return false;
+    }
+    where = (pc)(xpPC(pcontext));
+
+    if (tcr->valence == TCR_STATE_LISP) {
+      if ((where >= restore_windows_context_start) &&
+          (where < restore_windows_context_end)) {
+        pc_luser_restore_windows_context(pcontext, tcr, where);
+      } else {
+        area *ts = tcr->ts_area;
+        /* If we're in the lisp heap, or in x86-spentry??.o, or in
+           x86-subprims??.o, or in the subprims jump table at #x15000,
+           or on the tstack ... we're just executing lisp code.  Otherwise,
+           we got an exception while executing lisp code, but haven't
+           entered the handler yet (still in Windows exception glue
+           or switching stacks or something.)  In the latter case, we
+           basically want to get to he handler and have it notice
+           the pending exception request, and suspend the thread at that
+           point. */
+        if (!((where < (pc)lisp_global(HEAP_END)) &&
+              (where >= (pc)lisp_global(HEAP_START))) &&
+            !((where < spentry_end) && (where >= spentry_start)) &&
+            !((where < subprims_end) && (where >= subprims_start)) &&
+            !((where < (pc) 0x16000) &&
+              (where >= (pc) 0x15000)) &&
+            !((where < (pc) (ts->high)) &&
+              (where >= (pc) (ts->low)))) {
+          /* The thread has lisp valence, but is not executing code
+             where we expect lisp code to be and is not exiting from
+             an exception handler.  That pretty much means that it's
+             on its way into an exception handler; we have to handshake
+             until it enters an exception-wait state. */
+          /* There are likely race conditions here */
+          SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_SUSPEND);
+          ResumeThread(hthread);
+          SEM_WAIT_FOREVER(tcr->suspend);
+          SuspendThread(hthread);
+          /* The thread is either waiting for its resume semaphore to
+             be signaled or is about to wait.  Signal it now, while
+             the thread's suspended. */
+          SEM_RAISE(tcr->resume);
+          pcontext->ContextFlags = CONTEXT_ALL;
+          GetThreadContext(hthread, pcontext);
+        }
+      }
+#if 0
+    } else {
+      if (tcr->valence == TCR_STATE_EXCEPTION_RETURN) {
+        if (!tcr->pending_exception_context) {
+          FBug(pcontext, "we're confused here.");
+        }
+        *pcontext = *tcr->pending_exception_context;
+        tcr->pending_exception_context = NULL;
+        tcr->valence = TCR_STATE_LISP;
+      }
+#endif
+    }
+    tcr->suspend_context = pcontext;
+    return true;
+  }
+  return false;
+}
+#else
+Boolean
+suspend_tcr(TCR *tcr)
+{
+  int suspend_count = atomic_incf(&(tcr->suspend_count));
+  pthread_t thread;
+  if (suspend_count == 1) {
+    thread = (pthread_t)(tcr->osid);
+    if ((thread != (pthread_t) 0) &&
+        (pthread_kill(thread, thread_suspend_signal) == 0)) {
+      SET_TCR_FLAG(tcr,TCR_FLAG_BIT_SUSPEND_ACK_PENDING);
+    } else {
+      /* A problem using pthread_kill.  On Darwin, this can happen
+	 if the thread has had its signal mask surgically removed
+	 by pthread_exit.  If the native (Mach) thread can be suspended,
+	 do that and return true; otherwise, flag the tcr as belonging
+	 to a dead thread by setting tcr->osid to 0.
+      */
+      tcr->osid = 0;
+      return false;
+    }
+    return true;
+  }
+  return false;
+}
+#endif
+
+#ifdef WINDOWS
+Boolean
+tcr_suspend_ack(TCR *tcr)
+{
+  return true;
+}
+#else
+Boolean
+tcr_suspend_ack(TCR *tcr)
+{
+  if (tcr->flags & (1<<TCR_FLAG_BIT_SUSPEND_ACK_PENDING)) {
+    SEM_WAIT_FOREVER(tcr->suspend);
+    tcr->flags &= ~(1<<TCR_FLAG_BIT_SUSPEND_ACK_PENDING);
+  }
+  return true;
+}
+#endif
+      
+
+Boolean
+kill_tcr(TCR *tcr)
+{
+  TCR *current = get_tcr(true);
+  Boolean result = false;
+
+  LOCK(lisp_global(TCR_AREA_LOCK),current);
+  {
+    LispObj osid = tcr->osid;
+    
+    if (osid) {
+      result = true;
+#ifdef WINDOWS
+      /* What we really want to de hear is (something like)
+         forcing the thread to run quit_handler().  For now,
+         mark the TCR as dead and kill thw Windows thread. */
+      tcr->osid = 0;
+      if (!TerminateThread((HANDLE)osid, 0)) {
+        result = false;
+      } else {
+        shutdown_thread_tcr(tcr);
+      }
+#else
+      if (pthread_kill((pthread_t)osid,thread_kill_signal)) {
+        result = false;
+      }
+#endif
+    }
+  }
+  UNLOCK(lisp_global(TCR_AREA_LOCK), current);
+  return result;
+}
+
+Boolean
+lisp_suspend_tcr(TCR *tcr)
+{
+  Boolean suspended;
+  TCR *current = get_tcr(true);
+  
+  LOCK(lisp_global(TCR_AREA_LOCK),current);
+  suspended = suspend_tcr(tcr);
+  if (suspended) {
+    while (!tcr_suspend_ack(tcr));
+  }
+  UNLOCK(lisp_global(TCR_AREA_LOCK),current);
+  return suspended;
+}
+	 
+#ifdef WINDOWS
+Boolean
+resume_tcr(TCR *tcr)
+{
+  int suspend_count = atomic_decf(&(tcr->suspend_count)), err;
+  DWORD rc;
+  if (suspend_count == 0) {
+    CONTEXT *context = tcr->suspend_context;
+    HANDLE hthread = (HANDLE)(tcr->osid);
+
+    if (context) {
+      context->ContextFlags = CONTEXT_ALL;
+      tcr->suspend_context = NULL;
+      SetThreadContext(hthread,context);
+      rc = ResumeThread(hthread);
+      if (rc == -1) {
+        wperror("ResumeThread");
+        return false;
+      }
+      return true;
+    }
+  }
+  return false;
+}   
+#else
+Boolean
+resume_tcr(TCR *tcr)
+{
+  int suspend_count = atomic_decf(&(tcr->suspend_count));
+  if (suspend_count == 0) {
+    void *s = (tcr->resume);
+    if (s != NULL) {
+      SEM_RAISE(s);
+      return true;
+    }
+  }
+  return false;
+}
+#endif
+
+    
+
+
+Boolean
+lisp_resume_tcr(TCR *tcr)
+{
+  Boolean resumed;
+  TCR *current = get_tcr(true);
+  
+  LOCK(lisp_global(TCR_AREA_LOCK),current);
+  resumed = resume_tcr(tcr);
+  UNLOCK(lisp_global(TCR_AREA_LOCK), current);
+  return resumed;
+}
+
+
+TCR *freed_tcrs = NULL;
+
+void
+enqueue_freed_tcr (TCR *tcr)
+{
+#ifndef HAVE_TLS
+  tcr->next = freed_tcrs;
+  freed_tcrs = tcr;
+#endif
+}
+
+/* It's not clear that we can safely condemn a dead tcr's areas, since
+   we may not be able to call free() if a suspended thread owns a 
+   malloc lock. At least make the areas appear to be empty. 
+*/
+   
+
+void
+normalize_dead_tcr_areas(TCR *tcr)
+{
+  area *a;
+
+  a = tcr->vs_area;
+  if (a) {
+    a->active = a->high;
+  }
+
+  a = tcr->ts_area;
+  if (a) {
+    a->active = a->high;
+  }
+
+  a = tcr->cs_area;
+  if (a) {
+    a->active = a->high;
+  }
+}
+    
+void
+free_freed_tcrs ()
+{
+  TCR *current, *next;
+
+  for (current = freed_tcrs; current; current = next) {
+    next = current->next;
+#ifndef HAVE_TLS
+#ifdef WIN32
+    free(current->allocated);
+#else
+    free(current);
+#endif
+#endif
+  }
+  freed_tcrs = NULL;
+}
+
+void
+suspend_other_threads(Boolean for_gc)
+{
+  TCR *current = get_tcr(true), *other, *next;
+  int dead_tcr_count = 0;
+  Boolean all_acked;
+
+  LOCK(lisp_global(TCR_AREA_LOCK), current);
+  for (other = current->next; other != current; other = other->next) {
+    if ((other->osid != 0)) {
+      suspend_tcr(other);
+      if (other->osid == 0) {
+	dead_tcr_count++;
+      }
+    } else {
+      dead_tcr_count++;
+    }
+  }
+
+  do {
+    all_acked = true;
+    for (other = current->next; other != current; other = other->next) {
+      if ((other->osid != 0)) {
+        if (!tcr_suspend_ack(other)) {
+          all_acked = false;
+        }
+      }
+    }
+  } while(! all_acked);
+
+      
+
+  /* All other threads are suspended; can safely delete dead tcrs now */
+  if (dead_tcr_count) {
+    for (other = current->next; other != current; other = next) {
+      next = other->next;
+      if ((other->osid == 0))  {
+        normalize_dead_tcr_areas(other);
+	dequeue_tcr(other);
+	enqueue_freed_tcr(other);
+      }
+    }
+  }
+}
+
+void
+lisp_suspend_other_threads()
+{
+  suspend_other_threads(false);
+}
+
+void
+resume_other_threads(Boolean for_gc)
+{
+  TCR *current = get_tcr(true), *other;
+  for (other = current->next; other != current; other = other->next) {
+    if ((other->osid != 0)) {
+      resume_tcr(other);
+    }
+  }
+  free_freed_tcrs();
+  UNLOCK(lisp_global(TCR_AREA_LOCK), current);
+}
+
+void
+lisp_resume_other_threads()
+{
+  resume_other_threads(false);
+}
+
+
+
+rwlock *
+rwlock_new()
+{
+  extern int cache_block_size;
+
+  void *p = calloc(1,sizeof(rwlock)+cache_block_size-1);
+  rwlock *rw = NULL;;
+  
+  if (p) {
+    rw = (rwlock *) ((((natural)p)+cache_block_size-1) & (~(cache_block_size-1)));
+    rw->malloced_ptr = p;
+#ifndef USE_FUTEX
+    rw->reader_signal = new_semaphore(0);
+    rw->writer_signal = new_semaphore(0);
+    if ((rw->reader_signal == NULL) || (rw->writer_signal == NULL)) {
+      if (rw->reader_signal) {
+        destroy_semaphore(&(rw->reader_signal));
+      } else {
+        destroy_semaphore(&(rw->writer_signal));
+      }
+      free(rw);
+      rw = NULL;
+    }
+#endif
+  }
+  return rw;
+}
+
+     
+/*
+  Try to get read access to a multiple-readers/single-writer lock.  If
+  we already have read access, return success (indicating that the
+  lock is held another time.  If we already have write access to the
+  lock ... that won't work; return EDEADLK.  Wait until no other
+  thread has or is waiting for write access, then indicate that we
+  hold read access once.
+*/
+#ifndef USE_FUTEX
+int
+rwlock_rlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
+{
+  int err = 0;
+  
+  LOCK_SPINLOCK(rw->spin, tcr);
+
+  if (rw->writer == tcr) {
+    RELEASE_SPINLOCK(rw->spin);
+    return EDEADLK;
+  }
+
+  while (rw->blocked_writers || (rw->state > 0)) {
+    rw->blocked_readers++;
+    RELEASE_SPINLOCK(rw->spin);
+    err = semaphore_maybe_timedwait(rw->reader_signal,waitfor);
+    LOCK_SPINLOCK(rw->spin,tcr);
+    rw->blocked_readers--;
+    if (err == EINTR) {
+      err = 0;
+    }
+    if (err) {
+      RELEASE_SPINLOCK(rw->spin);
+      return err;
+    }
+  }
+  rw->state--;
+  RELEASE_SPINLOCK(rw->spin);
+  return err;
+}
+#else
+int
+rwlock_rlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
+{
+  natural waitval;
+
+  lock_futex(&rw->spin);
+
+  if (rw->writer == tcr) {
+    unlock_futex(&rw->spin);
+    return EDEADLOCK;
+  }
+  while (1) {
+    if (rw->writer == NULL) {
+      --rw->state;
+      unlock_futex(&rw->spin);
+      return 0;
+    }
+    rw->blocked_readers++;
+    waitval = rw->reader_signal;
+    unlock_futex(&rw->spin);
+    futex_wait(&rw->reader_signal,waitval);
+    lock_futex(&rw->spin);
+    rw->blocked_readers--;
+  }
+  return 0;
+}
+#endif   
+
+
+/*
+  Try to obtain write access to the lock.
+  It is an error if we already have read access, but it's hard to
+  detect that.
+  If we already have write access, increment the count that indicates
+  that.
+  Otherwise, wait until the lock is not held for reading or writing,
+  then assert write access.
+*/
+
+#ifndef USE_FUTEX
+int
+rwlock_wlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
+{
+  int err = 0;
+
+  LOCK_SPINLOCK(rw->spin,tcr);
+  if (rw->writer == tcr) {
+    rw->state++;
+    RELEASE_SPINLOCK(rw->spin);
+    return 0;
+  }
+
+  while (rw->state != 0) {
+    rw->blocked_writers++;
+    RELEASE_SPINLOCK(rw->spin);
+    err = semaphore_maybe_timedwait(rw->writer_signal, waitfor);
+    LOCK_SPINLOCK(rw->spin,tcr);
+    rw->blocked_writers--;
+    if (err == EINTR) {
+      err = 0;
+    }
+    if (err) {
+      RELEASE_SPINLOCK(rw->spin);
+      return err;
+    }
+  }
+  rw->state = 1;
+  rw->writer = tcr;
+  RELEASE_SPINLOCK(rw->spin);
+  return err;
+}
+
+#else
+int
+rwlock_wlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
+{
+  int err = 0;
+  natural waitval;
+
+  lock_futex(&rw->spin);
+  if (rw->writer == tcr) {
+    rw->state++;
+    unlock_futex(&rw->spin);
+    return 0;
+  }
+
+  while (rw->state != 0) {
+    rw->blocked_writers++;
+    waitval = rw->writer_signal;
+    unlock_futex(&rw->spin);
+    futex_wait(&rw->writer_signal,waitval);
+    lock_futex(&rw->spin);
+    rw->blocked_writers--;
+  }
+  rw->state = 1;
+  rw->writer = tcr;
+  unlock_futex(&rw->spin);
+  return err;
+}
+#endif
+
+/*
+  Sort of the same as above, only return EBUSY if we'd have to wait.
+*/
+#ifndef USE_FUTEX
+int
+rwlock_try_wlock(rwlock *rw, TCR *tcr)
+{
+  int ret = EBUSY;
+
+  LOCK_SPINLOCK(rw->spin,tcr);
+  if (rw->writer == tcr) {
+    rw->state++;
+    ret = 0;
+  } else {
+    if (rw->state == 0) {
+      rw->writer = tcr;
+      rw->state = 1;
+      ret = 0;
+    }
+  }
+  RELEASE_SPINLOCK(rw->spin);
+  return ret;
+}
+#else
+int
+rwlock_try_wlock(rwlock *rw, TCR *tcr)
+{
+  int ret = EBUSY;
+
+  lock_futex(&rw->spin);
+  if (rw->writer == tcr) {
+    rw->state++;
+    ret = 0;
+  } else {
+    if (rw->state == 0) {
+      rw->writer = tcr;
+      rw->state = 1;
+      ret = 0;
+    }
+  }
+  unlock_futex(&rw->spin);
+  return ret;
+}
+#endif
+
+#ifndef USE_FUTEX
+int
+rwlock_try_rlock(rwlock *rw, TCR *tcr)
+{
+  int ret = EBUSY;
+
+  LOCK_SPINLOCK(rw->spin,tcr);
+  if (rw->state <= 0) {
+    --rw->state;
+    ret = 0;
+  }
+  RELEASE_SPINLOCK(rw->spin);
+  return ret;
+}
+#else
+int
+rwlock_try_rlock(rwlock *rw, TCR *tcr)
+{
+  int ret = EBUSY;
+
+  lock_futex(&rw->spin);
+  if (rw->state <= 0) {
+    --rw->state;
+    ret = 0;
+  }
+  unlock_futex(&rw->spin);
+  return ret;
+}
+#endif
+
+
+
+#ifndef USE_FUTEX
+int
+rwlock_unlock(rwlock *rw, TCR *tcr)
+{
+
+  int err = 0;
+  natural blocked_readers = 0;
+
+  LOCK_SPINLOCK(rw->spin,tcr);
+  if (rw->state > 0) {
+    if (rw->writer != tcr) {
+      err = EINVAL;
+    } else {
+      --rw->state;
+      if (rw->state == 0) {
+        rw->writer = NULL;
+      }
+    }
+  } else {
+    if (rw->state < 0) {
+      ++rw->state;
+    } else {
+      err = EINVAL;
+    }
+  }
+  if (err) {
+    RELEASE_SPINLOCK(rw->spin);
+    return err;
+  }
+  
+  if (rw->state == 0) {
+    if (rw->blocked_writers) {
+      SEM_RAISE(rw->writer_signal);
+    } else {
+      blocked_readers = rw->blocked_readers;
+      if (blocked_readers) {
+        SEM_BROADCAST(rw->reader_signal, blocked_readers);
+      }
+    }
+  }
+  RELEASE_SPINLOCK(rw->spin);
+  return 0;
+}
+#else
+int
+rwlock_unlock(rwlock *rw, TCR *tcr)
+{
+
+  int err = 0;
+
+  lock_futex(&rw->spin);
+  if (rw->state > 0) {
+    if (rw->writer != tcr) {
+      err = EINVAL;
+    } else {
+      --rw->state;
+      if (rw->state == 0) {
+        rw->writer = NULL;
+      }
+    }
+  } else {
+    if (rw->state < 0) {
+      ++rw->state;
+    } else {
+      err = EINVAL;
+    }
+  }
+  if (err) {
+    unlock_futex(&rw->spin);
+    return err;
+  }
+  
+  if (rw->state == 0) {
+    if (rw->blocked_writers) {
+      ++rw->writer_signal;
+      unlock_futex(&rw->spin);
+      futex_wake(&rw->writer_signal,1);
+      return 0;
+    }
+    if (rw->blocked_readers) {
+      ++rw->reader_signal;
+      unlock_futex(&rw->spin);
+      futex_wake(&rw->reader_signal, INT_MAX);
+      return 0;
+    }
+  }
+  unlock_futex(&rw->spin);
+  return 0;
+}
+#endif
+
+        
+void
+rwlock_destroy(rwlock *rw)
+{
+#ifndef USE_FUTEX
+  destroy_semaphore((void **)&rw->reader_signal);
+  destroy_semaphore((void **)&rw->writer_signal);
+#endif
+  postGCfree((void *)(rw->malloced_ptr));
+}
+
+
+
Index: /branches/new-random/lisp-kernel/unix-calls.c
===================================================================
--- /branches/new-random/lisp-kernel/unix-calls.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/unix-calls.c	(revision 13309)
@@ -0,0 +1,143 @@
+/*
+   Copyright (C) 2008-2009, Clozure Associates and contributors
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+/* Provide wrappers around some standard C library functions that
+   can't easily be called from CCL's FFI for some reason (or where
+   we want to override/extend the function's default behavior.)
+ 
+   Functions in this file should be referenced via the kernel
+   imports table.
+
+   Callers should generally expect standard C library error-handling
+   conventions (e.g., return -1 or NULL and set errno on error.)
+*/
+
+#define _LARGEFILE64_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <signal.h>
+
+ssize_t
+lisp_read(int fd, void *buf, size_t count)
+{
+  return read(fd,buf,count);
+}
+
+ssize_t
+lisp_write(int fd, void *buf, size_t count)
+{
+  return write(fd,buf,count);
+}
+
+int
+lisp_open(char *path, int flags, mode_t mode)
+{
+  return open(path,flags,mode);
+}
+
+int
+lisp_fchmod(int fd, mode_t mode)
+{
+  return fchmod(fd,mode);
+}
+
+int64_t
+lisp_lseek(int fd, int64_t offset, int whence)
+{
+#ifdef LINUX
+  return lseek64(fd,offset,whence);
+#else
+  return lseek(fd,offset,whence);
+#endif
+}
+
+int
+lisp_close(int fd)
+{
+  return close(fd);
+}
+
+int
+lisp_ftruncate(int fd, off_t length)
+{
+  return ftruncate(fd,length);
+}
+
+int
+lisp_stat(char *path, void *buf)
+{
+  return stat(path,buf);
+}
+
+int
+lisp_fstat(int fd, void *buf)
+{
+  return fstat(fd,buf);
+}
+
+
+int
+lisp_futex(int *uaddr, int op, int val, void *timeout, int *uaddr2, int val3)
+{
+#ifdef LINUX
+  return syscall(SYS_futex,uaddr,op,val,timeout,uaddr2,val3);
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}
+
+DIR *
+lisp_opendir(char *path)
+{
+  return opendir(path);
+}
+
+struct dirent *
+lisp_readdir(DIR *dir)
+{
+  return readdir(dir);
+}
+
+int
+lisp_closedir(DIR *dir)
+{
+  return closedir(dir);
+}
+
+int
+lisp_pipe(int pipefd[2])
+{
+  return pipe(pipefd);
+}
+
+int
+lisp_gettimeofday(struct timeval *tp, void *tzp)
+{
+  return gettimeofday(tp, tzp);
+}
+
+int
+lisp_sigexit(int signum)
+{
+  signal(signum, SIG_DFL);
+  return kill(getpid(), signum);
+}
Index: /branches/new-random/lisp-kernel/win32/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/win32/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/win32/.gdbinit	(revision 13309)
@@ -0,0 +1,51 @@
+directory lisp-kernel
+
+define pl
+  call print_lisp_object($arg0)
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x3001
+   set $car = *((LispObj *)($l+3))
+   set $l =  *((LispObj *)($l-1))
+   pl $car
+  end
+end
+
+
+define fn
+  pl $edi
+end
+
+define arg_y
+ pl $esi
+end
+
+define arg_z
+ pl $ebx
+end
+
+define offset
+ p (int)$pc-$edi
+end
+
+
+break Bug
+break FBug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIGUSR1 pass nostop noprint
+handle SIGUSR2 pass nostop noprint
+handle SIGEMT pass nostop noprint
+# Work around apparent Apple GDB bug
+handle SIGTTIN nopass nostop noprint
+# Work around Leopard bug du jour
+handle SIGSYS pass nostop noprint
+
Index: /branches/new-random/lisp-kernel/win32/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/win32/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/win32/Makefile	(revision 13309)
@@ -0,0 +1,109 @@
+#
+#   Copyright (C) 2008 Clozure Associates
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ../
+RM = /bin/rm
+CC = gcc
+AS = as
+M4 = m4
+LD = ld
+ASFLAGS = -g --32
+M4FLAGS = -DWIN_32 -DWINDOWS -DX86 -DX8632 -DWIN32_ES_HACK
+CDEFINES = -DWIN_32 -DWINDOWS -D_REENTRANT -DX86 -DX8632 -D_GNU_SOURCE  -D__MSVCRT__ -D__MSVCRT_VERSION__=0x700 -D_WIN32_WINNT=0x0502 -DWIN32_ES_HACK
+CDEBUG = -g
+COPT = -O2
+
+# If the linker supports a "--hash-style=" option, use traditional
+# SysV hash tables.  (If it doesn't support that option, assume
+# that traditional hash tables will be used by default.)
+ld_has_hash_style = $(shell $(LD) --help | grep "hash-style=")
+ifeq ($(ld_has_hash_style),)
+HASH_STYLE=
+else
+HASH_STYLE="-Wl,--hash-style=sysv"
+endif
+
+CRT2 = $(shell $(CC) -mno-cygwin -print-file-name=crt2.o)
+
+# There may be some confusion about whether or not C symbols have
+# leading underscores or not.  The assembler sources seem to
+# expect them to and mingw import libs seem to use them, but
+# it's not clear whether or not native win64 libraries use this
+# convention (and I'm not sure whether the Cygwin-hosted win64
+# toolchain behaves the same way as when hosted on Linux ...
+# The compiler default seems to be to use them; if we want to
+# suppress their use, uncomment the following:
+
+SUPPRESS_UNDERSCORES=#-fno-leading-underscore
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) ${SUPPRESS_UNDERSCORES} -mno-cygwin -o $@
+
+# order matters: x86-spjump32.o must be first.
+SPOBJ = x86-spjump32.o x86-spentry32.o x86-subprims32.o
+ASMOBJ = x86-asmutils32.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o windows-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils32.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants32.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants32.h x86-exceptions.h lisptypes.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	../../wx86cl.exe
+
+# Order matters: libs that provide definitions must follow libs that
+# reference them.  (It's legal to use -lfoo multiple times to try to
+# work around this.)
+LIBGCC = $(shell $(CC) -mno-cygwin -print-libgcc-file-name)
+OSLIBS =  -L/usr/lib/w32api -L/mingw/lib -L/usr/lib/mingw\
+	-lm -lpsapi -lws2_32 -lmingw32 $(LIBGCC) -lmoldname -lmingwex \
+	-lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32  $(GCCLIB) \
+	-lmoldname -lmingwex -lmsvcrt
+
+
+
+IMAGE_BASE =--image-base=0x10000
+
+../../wx86cl.exe: $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile
+	ld -o ../../wx86cl.exe  $(IMAGE_BASE) --enable-auto-import \
+	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(CRT2) $(OSLIBS) $(LIBGCC) $(LATELIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../wx86cl.exe
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../wx86cl.exe
+	strip -g ../../wx86cl.exe
Index: /branches/new-random/lisp-kernel/win32/pei-ia32.x
===================================================================
--- /branches/new-random/lisp-kernel/win32/pei-ia32.x	(revision 13309)
+++ /branches/new-random/lisp-kernel/win32/pei-ia32.x	(revision 13309)
@@ -0,0 +1,205 @@
+OUTPUT_FORMAT(pei-i386)
+SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
+SECTIONS
+{
+  . = SIZEOF_HEADERS;
+  . = ALIGN(__section_alignment__);
+  .spfoo  __image_base__ + __section_alignment__ :
+  {
+    __spfoo_start__ = . ;
+    . = __spfoo_start__ + 0x10000 ;
+    __spfoo_end__ = . ;
+  }
+  .text  BLOCK(__section_alignment__) :
+  {
+     *(.init)
+    *(.text)
+    *(SORT(.text$*))
+    *(.glue_7t)
+    *(.glue_7)
+     ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
+			LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0);
+     ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
+			LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0);
+     *(.fini)
+    /* ??? Why is .gcc_exc here?  */
+     *(.gcc_exc)
+    PROVIDE (etext = .);
+     *(.gcc_except_table)
+  }
+  /* The Cygwin32 library uses a section to avoid copying certain data
+     on fork.  This used to be named ".data".  The linker used
+     to include this between __data_start__ and __data_end__, but that
+     breaks building the cygwin32 dll.  Instead, we name the section
+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */
+  .data BLOCK(__section_alignment__) :
+  {
+    __data_start__ = . ;
+    *(.data)
+    *(.data2)
+    *(SORT(.data$*))
+    *(.jcr)
+    __data_end__ = . ;
+    *(.data_cygwin_nocopy)
+  }
+  .rdata BLOCK(__section_alignment__) :
+  {
+    *(.rdata)
+             *(SORT(.rdata$*))
+     *(.eh_frame)
+    ___RUNTIME_PSEUDO_RELOC_LIST__ = .;
+    __RUNTIME_PSEUDO_RELOC_LIST__ = .;
+    *(.rdata_runtime_pseudo_reloc)
+    ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
+    __RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
+  }
+  .pdata BLOCK(__section_alignment__) :
+  {
+    *(.pdata)
+  }
+  .bss BLOCK(__section_alignment__) :
+  {
+    __bss_start__ = . ;
+    *(.bss)
+    *(COMMON)
+    __bss_end__ = . ;
+  }
+  .edata BLOCK(__section_alignment__) :
+  {
+    *(.edata)
+  }
+  /DISCARD/ :
+  {
+    *(.debug$S)
+    *(.debug$T)
+    *(.debug$F)
+    *(.drectve)
+  }
+  .idata BLOCK(__section_alignment__) :
+  {
+    /* This cannot currently be handled with grouped sections.
+	See pe.em:sort_sections.  */
+    SORT(*)(.idata$2)
+    SORT(*)(.idata$3)
+    /* These zeroes mark the end of the import list.  */
+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
+    SORT(*)(.idata$4)
+    SORT(*)(.idata$5)
+    SORT(*)(.idata$6)
+    SORT(*)(.idata$7)
+  }
+  .CRT BLOCK(__section_alignment__) :
+  {
+    ___crt_xc_start__ = . ;
+    *(SORT(.CRT$XC*))  /* C initialization */
+    ___crt_xc_end__ = . ;
+    ___crt_xi_start__ = . ;
+    *(SORT(.CRT$XI*))  /* C++ initialization */
+    ___crt_xi_end__ = . ;
+    ___crt_xl_start__ = . ;
+    *(SORT(.CRT$XL*))  /* TLS callbacks */
+    /* ___crt_xl_end__ is defined in the TLS Directory support code */
+    ___crt_xp_start__ = . ;
+    *(SORT(.CRT$XP*))  /* Pre-termination */
+    ___crt_xp_end__ = . ;
+    ___crt_xt_start__ = . ;
+    *(SORT(.CRT$XT*))  /* Termination */
+    ___crt_xt_end__ = . ;
+  }
+  .tls BLOCK(__section_alignment__) :
+  {
+    ___tls_start__ = . ;
+    *(.tls)
+    *(.tls$)
+    *(SORT(.tls$*))
+    ___tls_end__ = . ;
+  }
+  .endjunk BLOCK(__section_alignment__) :
+  {
+    /* end is deprecated, don't use it */
+    PROVIDE (end = .);
+    PROVIDE ( _end = .);
+     __end__ = .;
+  }
+  .rsrc BLOCK(__section_alignment__) :
+  {
+    *(.rsrc)
+    *(SORT(.rsrc$*))
+  }
+  .reloc BLOCK(__section_alignment__) :
+  {
+    *(.reloc)
+  }
+  .stab BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.stab)
+  }
+  .stabstr BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.stabstr)
+  }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section.  Unlike other targets that fake this by putting the
+     section VMA at 0, the PE format will not allow it.  */
+  /* DWARF 1.1 and DWARF 2.  */
+  .debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_aranges)
+  }
+  .debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_pubnames)
+  }
+  /* DWARF 2.  */
+  .debug_info BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_info) *(.gnu.linkonce.wi.*)
+  }
+  .debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_abbrev)
+  }
+  .debug_line BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_line)
+  }
+  .debug_frame BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_frame)
+  }
+  .debug_str BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_str)
+  }
+  .debug_loc BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_loc)
+  }
+  .debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_macinfo)
+  }
+  /* SGI/MIPS DWARF 2 extensions.  */
+  .debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_weaknames)
+  }
+  .debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_funcnames)
+  }
+  .debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_typenames)
+  }
+  .debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_varnames)
+  }
+  /* DWARF 3.  */
+  .debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_ranges)
+  }
+}
Index: /branches/new-random/lisp-kernel/win64/.gdbinit
===================================================================
--- /branches/new-random/lisp-kernel/win64/.gdbinit	(revision 13309)
+++ /branches/new-random/lisp-kernel/win64/.gdbinit	(revision 13309)
@@ -0,0 +1,85 @@
+directory lisp-kernel
+
+define x86_lisp_string
+x/s $arg0-5
+end
+
+define gtra
+br *$r10
+cont
+end
+
+define x86pname
+set $temp=*((long *)((long)($arg0-6)))
+x86_lisp_string $temp
+end
+
+
+define pname
+ x86pname $arg0
+end
+
+define l
+ call print_lisp_object($arg0)
+end
+
+define lw
+ l $r13
+end
+
+define clobber_breakpoint
+  set *(short *)($pc-2)=0x9090
+end
+
+define arg_z
+ l $rsi
+end
+
+define arg_y
+ l $rdi
+end
+
+define arg_x
+ l $r8
+end
+
+define bx
+ l $rbx
+end
+
+define showlist
+  set $l=$arg0
+  while $l != 0x200b
+   set $car = *((LispObj *)($l+5))
+   set $l =  *((LispObj *)($l-3))
+   l $car
+  end
+end
+
+define lbt
+ call plbt_sp($rbp)
+end
+
+define ada
+ p/x *(all_areas->succ)
+end
+
+define lregs
+ call debug_lisp_registers($arg0,0,0)
+end
+
+break Bug
+
+display/i $pc
+
+handle SIGKILL pass nostop noprint
+handle SIGILL pass nostop noprint
+handle SIGSEGV pass nostop noprint
+handle SIGBUS pass nostop noprint
+handle SIGFPE pass nostop noprint
+handle SIG40 pass nostop noprint
+handle SIG41 pass nostop noprint
+handle SIG42 pass nostop noprint
+handle SIGPWR pass nostop noprint
+handle SIGQUIT pass nostop noprint
+
Index: /branches/new-random/lisp-kernel/win64/Makefile
===================================================================
--- /branches/new-random/lisp-kernel/win64/Makefile	(revision 13309)
+++ /branches/new-random/lisp-kernel/win64/Makefile	(revision 13309)
@@ -0,0 +1,98 @@
+#
+#   Copyright (C) 2007 Clozure Associates
+#   This file is part of Clozure CL.  
+#
+#   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with Clozure CL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with Clozure CL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   Clozure CL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+VPATH = ../
+RM = /bin/rm
+# gcc64, as64: until there's a real win64 gcc, assume that gcc and gas
+# are installed under these names
+CC = x86_64-w64-mingw32-gcc
+AS = x86_64-w64-mingw32-as
+M4 = m4
+LD = x86_64-w64-mingw32-ld
+ASFLAGS = -g --64
+M4FLAGS = -DWIN_64 -DWINDOWS -DX86 -DX8664 -DHAVE_TLS -DEMUTLS -DTCR_IN_GPR
+CDEFINES = -DWIN_64 -DWINDOWS -D_REENTRANT -DX86 -DX8664 -D_GNU_SOURCE -DHAVE_TLS -DEMUTLS -DTCR_IN_GPR
+CDEBUG = -g
+COPT = #-O2
+
+# If the linker supports a "--hash-style=" option, use traditional
+# SysV hash tables.  (If it doesn't support that option, assume
+# that traditional hash tables will be used by default.)
+ld_has_hash_style = $(shell $(LD) --help | grep "hash-style=")
+ifeq ($(ld_has_hash_style),)
+HASH_STYLE=
+else
+HASH_STYLE="-Wl,--hash-style=sysv"
+endif
+
+# There may be some confusion about whether or not C symbols have
+# leading underscores or not.  The assembler sources seem to
+# expect them to and mingw import libs seem to use them, but
+# it's not clear whether or not native win64 libraries use this
+# convention (and I'm not sure whether the Cygwin-hosted win64
+# toolchain behaves the same was as when hosted on Linux ...
+# The compiler default seems to be to use them; if we want to
+# suppress their use, uncomment the following:
+
+SUPPRESS_UNDERSCORES=#-fno-leading-underscore
+
+.s.o:
+	$(M4) $(M4FLAGS) -I../ $< | $(AS)  $(ASFLAGS) -o $@
+.c.o:
+	$(CC) -c $< $(CDEFINES) $(CDEBUG) $(COPT) ${SUPPRESS_UNDERSCORES} -m64 -o $@
+
+SPOBJ = pad.o x86-spjump64.o x86-spentry64.o x86-subprims64.o
+ASMOBJ = x86-asmutils64.o imports.o
+
+COBJ  = pmcl-kernel.o gc-common.o x86-gc.o bits.o  x86-exceptions.o \
+	image.o thread_manager.o lisp-debug.o memory.o windows-calls.o
+
+DEBUGOBJ = lispdcmd.o plprint.o plsym.o xlbt.o x86_print.o
+KERNELOBJ= $(COBJ) x86-asmutils64.o  imports.o
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants64.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants64.h x86-exceptions.h lisptypes.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	../../wx86cl64.exe
+
+
+OSLIBS = -lpsapi -lws2_32
+
+
+../../wx86cl64.exe:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile pei-x86-64.x
+	$(CC) -Wl,--image-base=0x10000 -Wl,-script=pei-x86-64.x -m64 $(CDEBUG)  -Wl,--export-dynamic $(HASH_STYLE) -o $@ $(USE_LINK_MAP) $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) -f $(KERNELOBJ) $(DEBUGOBJ) ../../wx86cl64.exe
+
+clean:	cclean
+	$(RM) -f $(SPOBJ)
+
+strip:	../../wx86cl64.exe
+	strip -g ../../wx86cl64.exe
Index: /branches/new-random/lisp-kernel/win64/Makefile.nmake
===================================================================
--- /branches/new-random/lisp-kernel/win64/Makefile.nmake	(revision 13309)
+++ /branches/new-random/lisp-kernel/win64/Makefile.nmake	(revision 13309)
@@ -0,0 +1,83 @@
+#
+#   Copyright (C) 2008 Clozure Associates
+#   This file is part of OpenMCL.  
+#
+#   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
+#   License , known as the LLGPL and distributed with OpenMCL as the
+#   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+#   which is distributed with OpenMCL as the file "LGPL".  Where these
+#   conflict, the preamble takes precedence.  
+#
+#   OpenMCL is referenced in the preamble as the "LIBRARY."
+#
+#   The LLGPL is also available online at
+#   http://opensource.franz.com/preamble.html
+
+
+# With nmake, VPATH is broken.  Invoke from the directory above:
+#
+# Z:\ccl-source\lisp-kernel> nmake /f win64/Makefile.nmake
+
+RM = del
+CC = cl
+M4 = m4
+MV = move
+LD = link
+ASFLAGS = -f win64 -g cv8 -p gas
+AS = yasm
+M4FLAGS = -DWIN64 -DWINDOWS -DX86 -DX8664 -DHAVE_TLS -DEMUTLS
+CDEFINES = /I.. /DWIN64 /DWINDOWS /D_REENTRANT /DX86 /DX8664 /D_GNU_SOURCE /DHAVE_TLS /DEMUTLS /DVC #-DDISABLE_EGC
+CDEBUG = /Zi
+COPT =
+LDFLAGS =
+
+.SUFFIXES : .exe .obj .c .asm .s
+
+.s.asm:
+	$(M4) $(M4FLAGS) -I. $< > $@.temp && mv $@.temp $@
+.asm.obj:
+	$(AS) $(ASFLAGS) -o $@ $<
+.c.obj:
+	$(CC) /c $< $(CDEFINES) $(CDEBUG) $(COPT)
+
+SPOBJ = pad.obj x86-spjump64.obj x86-spentry64.obj x86-subprims64.obj
+ASMOBJ = x86-asmutils64.obj imports.obj
+
+COBJ  = pmcl-kernel.obj gc-common.obj x86-gc.obj bits.obj  x86-exceptions.obj \
+	image.obj thread_manager.obj lisp-debug.obj memory.obj
+
+DEBUGOBJ = lispdcmd.obj plprint.obj plsym.obj xlbt.obj x86_print.obj
+KERNELOBJ= $(COBJ) x86-asmutils64.obj  imports.obj
+
+SPINC =	lisp.s m4macros.m4 x86-constants.s x86-macros.s errors.s x86-uuo.s \
+	x86-constants64.s
+
+CHEADERS = area.h bits.h x86-constants.h lisp-errors.h gc.h lisp.h \
+	lisp-exceptions.h lisp_globals.h macros.h memprotect.h image.h \
+	Threads.h x86-constants64.h x86-exceptions.h lisptypes.h
+
+
+KSPOBJ = $(SPOBJ)
+all:	..\wx86cl64
+
+OSLIBS = bufferoverflowu.lib
+
+..\wx86cl64:	$(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) Makefile 
+	$(LD) $(LDFLAGS) /out:$@ $(KSPOBJ) $(KERNELOBJ) $(DEBUGOBJ) $(OSLIBS)
+
+cobjs: $(COBJ)
+
+$(SPOBJ): $(SPINC)
+$(ASMOBJ): $(SPINC)
+$(COBJ): $(CHEADERS)
+$(DEBUGOBJ): $(CHEADERS) lispdcmd.h
+
+
+cclean:
+	$(RM) $(KERNELOBJ) $(DEBUGOBJ) ../../wx86cl64
+
+clean:	cclean
+	$(RM) $(SPOBJ)
+
+strip:	../../wx86cl64
+	strip -g ../../wx86cl64
Index: /branches/new-random/lisp-kernel/win64/pei-x86-64.x
===================================================================
--- /branches/new-random/lisp-kernel/win64/pei-x86-64.x	(revision 13309)
+++ /branches/new-random/lisp-kernel/win64/pei-x86-64.x	(revision 13309)
@@ -0,0 +1,205 @@
+OUTPUT_FORMAT(pei-x86-64)
+SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
+SECTIONS
+{
+  . = SIZEOF_HEADERS;
+  . = ALIGN(__section_alignment__);
+  .spfoo  __image_base__ + __section_alignment__ :
+  {
+    __spfoo_start__ = . ;
+    . = __spfoo_start__ + 0x10000 ;
+    __spfoo_end__ = . ;
+  }
+  .text  BLOCK(__section_alignment__) :
+  {
+     *(.init)
+    *(.text)
+    *(SORT(.text$*))
+    *(.glue_7t)
+    *(.glue_7)
+     ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
+			LONG (-1); LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0); LONG (0);
+     ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
+			LONG (-1); LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0); LONG (0);
+     *(.fini)
+    /* ??? Why is .gcc_exc here?  */
+     *(.gcc_exc)
+    PROVIDE (etext = .);
+     *(.gcc_except_table)
+  }
+  /* The Cygwin32 library uses a section to avoid copying certain data
+     on fork.  This used to be named ".data".  The linker used
+     to include this between __data_start__ and __data_end__, but that
+     breaks building the cygwin32 dll.  Instead, we name the section
+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */
+  .data BLOCK(__section_alignment__) :
+  {
+    __data_start__ = . ;
+    *(.data)
+    *(.data2)
+    *(SORT(.data$*))
+    *(.jcr)
+    __data_end__ = . ;
+    *(.data_cygwin_nocopy)
+  }
+  .rdata BLOCK(__section_alignment__) :
+  {
+    *(.rdata)
+             *(SORT(.rdata$*))
+     *(.eh_frame)
+    ___RUNTIME_PSEUDO_RELOC_LIST__ = .;
+    __RUNTIME_PSEUDO_RELOC_LIST__ = .;
+    *(.rdata_runtime_pseudo_reloc)
+    ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
+    __RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
+  }
+  .pdata BLOCK(__section_alignment__) :
+  {
+    *(.pdata)
+  }
+  .bss BLOCK(__section_alignment__) :
+  {
+    __bss_start__ = . ;
+    *(.bss)
+    *(COMMON)
+    __bss_end__ = . ;
+  }
+  .edata BLOCK(__section_alignment__) :
+  {
+    *(.edata)
+  }
+  /DISCARD/ :
+  {
+    *(.debug$S)
+    *(.debug$T)
+    *(.debug$F)
+    *(.drectve)
+  }
+  .idata BLOCK(__section_alignment__) :
+  {
+    /* This cannot currently be handled with grouped sections.
+	See pep.em:sort_sections.  */
+    SORT(*)(.idata$2)
+    SORT(*)(.idata$3)
+    /* These zeroes mark the end of the import list.  */
+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
+    SORT(*)(.idata$4)
+    SORT(*)(.idata$5)
+    SORT(*)(.idata$6)
+    SORT(*)(.idata$7)
+  }
+  .CRT BLOCK(__section_alignment__) :
+  {
+    ___crt_xc_start__ = . ;
+    *(SORT(.CRT$XC*))  /* C initialization */
+    ___crt_xc_end__ = . ;
+    ___crt_xi_start__ = . ;
+    *(SORT(.CRT$XI*))  /* C++ initialization */
+    ___crt_xi_end__ = . ;
+    ___crt_xl_start__ = . ;
+    *(SORT(.CRT$XL*))  /* TLS callbacks */
+    /* ___crt_xl_end__ is defined in the TLS Directory support code */
+    ___crt_xp_start__ = . ;
+    *(SORT(.CRT$XP*))  /* Pre-termination */
+    ___crt_xp_end__ = . ;
+    ___crt_xt_start__ = . ;
+    *(SORT(.CRT$XT*))  /* Termination */
+    ___crt_xt_end__ = . ;
+  }
+  .tls BLOCK(__section_alignment__) :
+  {
+    ___tls_start__ = . ;
+    *(.tls)
+    *(.tls$)
+    *(SORT(.tls$*))
+    ___tls_end__ = . ;
+  }
+  .endjunk BLOCK(__section_alignment__) :
+  {
+    /* end is deprecated, don't use it */
+    PROVIDE (end = .);
+    PROVIDE ( _end = .);
+     __end__ = .;
+  }
+  .rsrc BLOCK(__section_alignment__) :
+  {
+    *(.rsrc)
+    *(SORT(.rsrc$*))
+  }
+  .reloc BLOCK(__section_alignment__) :
+  {
+    *(.reloc)
+  }
+  .stab BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.stab)
+  }
+  .stabstr BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.stabstr)
+  }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section.  Unlike other targets that fake this by putting the
+     section VMA at 0, the PE format will not allow it.  */
+  /* DWARF 1.1 and DWARF 2.  */
+  .debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_aranges)
+  }
+  .debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_pubnames)
+  }
+  /* DWARF 2.  */
+  .debug_info BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_info) *(.gnu.linkonce.wi.*)
+  }
+  .debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_abbrev)
+  }
+  .debug_line BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_line)
+  }
+  .debug_frame BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_frame)
+  }
+  .debug_str BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_str)
+  }
+  .debug_loc BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_loc)
+  }
+  .debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_macinfo)
+  }
+  /* SGI/MIPS DWARF 2 extensions.  */
+  .debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_weaknames)
+  }
+  .debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_funcnames)
+  }
+  .debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_typenames)
+  }
+  .debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_varnames)
+  }
+  /* DWARF 3.  */
+  .debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
+  {
+    *(.debug_ranges)
+  }
+}
Index: /branches/new-random/lisp-kernel/win64/yasm-redefinition.patch
===================================================================
--- /branches/new-random/lisp-kernel/win64/yasm-redefinition.patch	(revision 13309)
+++ /branches/new-random/lisp-kernel/win64/yasm-redefinition.patch	(revision 13309)
@@ -0,0 +1,22 @@
+Index: libyasm/symrec.c
+===================================================================
+--- libyasm/symrec.c	(revision 2037)
++++ libyasm/symrec.c	(working copy)
+@@ -281,10 +281,15 @@
+ yasm_symtab_define_equ(yasm_symtab *symtab, const char *name, yasm_expr *e,
+                        unsigned long line)
+ {
+-    yasm_symrec *rec = symtab_define(symtab, name, SYM_EQU, 1, line);
++    yasm_symrec *rec = yasm_symtab_get(symtab, name);
++	if (rec) {
++		/* redefinition. Emit warning here. */
++	} else {
++		rec = symtab_define(symtab, name, SYM_EQU, 1, line);
++	}
+     if (yasm_error_occurred())
+         return rec;
+-    rec->value.expn = e;
++    rec->value.expn = yasm_expr_simplify(e, 1);
+     rec->status |= YASM_SYM_VALUED;
+     return rec;
+ }
Index: /branches/new-random/lisp-kernel/windows-calls.c
===================================================================
--- /branches/new-random/lisp-kernel/windows-calls.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/windows-calls.c	(revision 13309)
@@ -0,0 +1,1015 @@
+/*
+   Copyright (C) 2008-2009, Clozure Associates and contributors,
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "x86-exceptions.h"
+#include <io.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <windows.h>
+#include <psapi.h>
+#include <dirent.h>
+#include <signal.h>
+#undef __argv
+#include <stdio.h>
+#include <math.h>
+
+#ifndef WIN_32
+#define _dosmaperr mingw_dosmaperr
+#else
+void
+_dosmaperr(unsigned long oserrno)
+{
+  switch(oserrno) {
+  case  ERROR_INVALID_FUNCTION:
+    errno = EINVAL;
+    break;
+  case ERROR_FILE_NOT_FOUND:
+    errno = ENOENT;
+    break;
+  case ERROR_PATH_NOT_FOUND:
+    errno = ENOENT;
+    break;
+  case  ERROR_TOO_MANY_OPEN_FILES:
+    errno = EMFILE;
+    break;
+  case  ERROR_ACCESS_DENIED:
+    errno = EACCES;
+    break;
+  case  ERROR_ARENA_TRASHED:
+    errno = ENOMEM;
+    break;
+  case  ERROR_NOT_ENOUGH_MEMORY:
+    errno = ENOMEM;
+    break;
+  case  ERROR_INVALID_BLOCK:
+    errno = ENOMEM;
+    break;
+  case  ERROR_BAD_ENVIRONMENT:
+    errno = E2BIG;
+    break;
+  case  ERROR_BAD_FORMAT:
+    errno = ENOEXEC;
+    break;
+  case  ERROR_INVALID_ACCESS:
+    errno = EINVAL;
+    break;
+  case  ERROR_INVALID_DATA:
+    errno = EINVAL;
+    break;
+  case  ERROR_INVALID_DRIVE:
+    errno = ENOENT;
+    break;
+  case  ERROR_CURRENT_DIRECTORY:
+    errno = EACCES;
+    break;
+  case  ERROR_NOT_SAME_DEVICE:
+    errno = EXDEV;
+    break;
+  case  ERROR_NO_MORE_FILES:
+    errno = ENOENT;
+    break;
+  case  ERROR_LOCK_VIOLATION:
+    errno = EACCES;
+    break;
+  case  ERROR_BAD_NETPATH:
+    errno = ENOENT;
+    break;
+  case  ERROR_NETWORK_ACCESS_DENIED:
+    errno = EACCES;
+    break;
+  case  ERROR_BAD_NET_NAME:
+    errno = ENOENT;
+    break;
+  case  ERROR_FILE_EXISTS:
+    errno = EEXIST;
+    break;
+  case  ERROR_CANNOT_MAKE:
+    errno = EACCES;
+    break;
+  case  ERROR_FAIL_I24:
+    errno = EACCES;
+    break;
+  case  ERROR_INVALID_PARAMETER:
+    errno = EINVAL;
+    break;
+  case  ERROR_NO_PROC_SLOTS:
+    errno = EAGAIN;
+    break;
+  case  ERROR_DRIVE_LOCKED:
+    errno = EACCES;
+    break;
+  case  ERROR_BROKEN_PIPE:
+    errno = EPIPE;
+    break;
+  case  ERROR_DISK_FULL:
+    errno = ENOSPC;
+    break;
+  case  ERROR_INVALID_TARGET_HANDLE:
+    errno = EBADF;
+    break;
+  case  ERROR_INVALID_HANDLE:
+    errno = EINVAL;
+    break;
+  case  ERROR_WAIT_NO_CHILDREN:
+    errno = ECHILD;
+    break;
+  case  ERROR_CHILD_NOT_COMPLETE:
+    errno = ECHILD;
+    break;
+  case  ERROR_DIRECT_ACCESS_HANDLE:
+    errno = EBADF;
+    break;
+  case  ERROR_NEGATIVE_SEEK:
+    errno = EINVAL;
+    break;
+  case  ERROR_SEEK_ON_DEVICE:   
+    errno = EACCES;
+    break;
+  case  ERROR_DIR_NOT_EMPTY:
+    errno = ENOTEMPTY;
+    break;
+  case  ERROR_NOT_LOCKED:
+    errno = EACCES;
+    break;
+  case  ERROR_BAD_PATHNAME:
+    errno = ENOENT;
+    break;
+  case  ERROR_MAX_THRDS_REACHED:
+    errno = EAGAIN;
+    break;
+  case  ERROR_LOCK_FAILED:
+    errno = EACCES;
+    break;
+  case  ERROR_ALREADY_EXISTS:
+    errno = EEXIST;
+    break;
+  case  ERROR_FILENAME_EXCED_RANGE:
+    errno = ENOENT;
+    break;
+  case  ERROR_NESTING_NOT_ALLOWED:
+    errno = EAGAIN;
+    break;
+  case  ERROR_NOT_ENOUGH_QUOTA:
+    errno = ENOMEM;
+    break;
+  case ERROR_OPERATION_ABORTED:
+    errno = EINTR;
+    break;
+  default:
+    errno = EINVAL;
+    break;
+  }
+}
+    
+#endif
+
+#define MAX_FD 32
+
+HANDLE
+lisp_open(wchar_t *path, int flag, int mode)
+{
+  HANDLE hfile;
+  DWORD dwDesiredAccess = 0;
+  DWORD dwShareMode = 0;
+  DWORD dwCreationDistribution = 0;
+  DWORD dwFlagsAndAttributes = 0;
+  SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+
+  dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+
+  if ((flag & _O_WRONLY) == _O_WRONLY) {
+    dwDesiredAccess |= GENERIC_WRITE;
+  } else if ((flag & _O_RDWR) == _O_RDWR) {
+    dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ;
+  } else {
+    dwDesiredAccess |= GENERIC_READ;
+  }
+    
+
+  if ((flag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
+    dwCreationDistribution |= CREATE_NEW;
+  } else if ((flag &  O_TRUNC) == O_TRUNC) {
+    if ((flag &  O_CREAT) ==  O_CREAT) {
+      dwCreationDistribution |= CREATE_ALWAYS;
+    } else if ((flag & O_RDONLY) != O_RDONLY) {
+      dwCreationDistribution |= TRUNCATE_EXISTING;
+    }
+  } else if ((flag & _O_APPEND) == _O_APPEND) {
+    dwCreationDistribution |= OPEN_EXISTING;
+  } else if ((flag &  _O_CREAT) == _O_CREAT) {
+    dwCreationDistribution |= OPEN_ALWAYS;
+  } else {
+    dwCreationDistribution |= OPEN_EXISTING;
+  }
+  if ((flag &  _O_RANDOM) == _O_RANDOM) {
+    dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
+  }
+  if ((flag &  _O_SEQUENTIAL) == _O_SEQUENTIAL) {
+    dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+  }
+
+  if ((flag &  _O_TEMPORARY) == _O_TEMPORARY) {
+    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+  }
+
+  if ((flag &  _O_SHORT_LIVED) == _O_SHORT_LIVED) {
+    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+  }
+
+  if (flag & _O_NOINHERIT) {
+    sa.bInheritHandle = FALSE;
+  }
+
+#if 0
+  dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
+#endif
+    
+
+  hfile = CreateFileW(path,
+                      dwDesiredAccess,
+                      dwShareMode,
+                      &sa,
+                      dwCreationDistribution,
+                      dwFlagsAndAttributes,
+                      NULL);
+  if (hfile == ((HANDLE)-1)) {
+    _dosmaperr(GetLastError());
+    return (HANDLE)-1;
+  }
+  return hfile;
+}
+
+int
+wopen(wchar_t *path, int flag, int mode)
+{
+  HANDLE h = lisp_open(path, flag, mode);
+
+  if (h == (HANDLE)-1) {
+    return -1;                  /* errno already set */
+  }
+  return  _open_osfhandle((intptr_t)h,0);
+}
+
+int
+lisp_close(HANDLE hfile)
+{
+  int err;
+
+  if (closesocket((SOCKET)hfile) == 0) {
+    return 0;
+  }
+
+  err = WSAGetLastError();
+  if (err != WSAENOTSOCK) {
+    _dosmaperr(err);
+    return -1;
+  }
+  if (CloseHandle(hfile)) {
+    return 0;
+  }
+  _dosmaperr(GetLastError());
+  return -1;
+}
+
+extern TCR *get_tcr(int);
+
+ssize_t
+lisp_standard_read(HANDLE hfile, void *buf, unsigned int count)
+{
+  HANDLE hevent;
+  OVERLAPPED overlapped;
+  DWORD err, nread, wait_result;
+  pending_io pending;
+  TCR *tcr;
+  
+  
+  memset(&overlapped,0,sizeof(overlapped));
+
+  if (GetFileType(hfile) == FILE_TYPE_DISK) {
+    overlapped.Offset = SetFilePointer(hfile, 0, &(overlapped.OffsetHigh), FILE_CURRENT);
+  }
+
+  tcr = (TCR *)get_tcr(1);
+  pending.h = hfile;
+  pending.o = &overlapped;
+  tcr->pending_io_info = &pending;
+  hevent = (HANDLE)(tcr->io_datum);
+  overlapped.hEvent = hevent;
+  ResetEvent(hevent);
+  if (ReadFile(hfile, buf, count, &nread, &overlapped)) {
+    tcr->pending_io_info = NULL;
+    return nread;
+  }
+
+  err = GetLastError();
+  
+  if (err == ERROR_HANDLE_EOF) {
+    tcr->pending_io_info = NULL;
+    return 0;
+  }
+
+  if (err != ERROR_IO_PENDING) {
+    _dosmaperr(err);
+    tcr->pending_io_info = NULL;
+    return -1;
+  }
+  
+  err = 0;
+  
+  /* We block here */    
+  wait_result = WaitForSingleObjectEx(hevent, INFINITE, true);
+
+
+
+  tcr->pending_io_info = NULL;
+  if (wait_result == WAIT_OBJECT_0) {
+    err = overlapped.Internal;
+    if (err == ERROR_HANDLE_EOF) {
+      return 0;
+    }
+    if (err) {
+      _dosmaperr(err);
+      return -1;
+    }
+    return overlapped.InternalHigh;
+  }
+
+  if (wait_result == WAIT_IO_COMPLETION) {
+    CancelIo(hfile);
+    errno = EINTR;
+    return -1;
+  }
+  err = GetLastError();
+  
+
+  switch (err) {
+  case ERROR_HANDLE_EOF: 
+    return 0;
+  default:
+    _dosmaperr(err);
+    return -1;
+  }
+}
+
+ssize_t
+pipe_read(HANDLE hfile, void *buf, unsigned int count)
+{
+  DWORD navail, err;;
+
+  do {
+    navail = 0;
+    if (PeekNamedPipe(hfile, NULL, 0, NULL, &navail, NULL) == 0) {
+      err = GetLastError();
+      if (err = ERROR_HANDLE_EOF) {
+        return 0;
+      } else {
+        _dosmaperr(err);
+        return -1;
+      }
+    }
+    if (navail != 0) {
+      return lisp_standard_read(hfile, buf, count);
+    }
+    if (SleepEx(50, TRUE) == WAIT_IO_COMPLETION) {
+      errno = EINTR;
+      return -1;
+    }
+  } while (1);
+}
+
+ssize_t
+console_read(HANDLE hfile, void *buf, unsigned int count)
+{
+  DWORD err, eventcount, i, n;
+  INPUT_RECORD ir;
+
+  do {
+    err = WaitForSingleObjectEx(hfile, INFINITE, TRUE);
+    switch (err) {
+    case WAIT_OBJECT_0:
+      eventcount = 0;
+      GetNumberOfConsoleInputEvents(hfile, &eventcount);
+      for (i = 0; i < eventcount; i++) {
+        PeekConsoleInput(hfile, &ir, 1, &n);
+        if (ir.EventType == KEY_EVENT) {
+          return lisp_standard_read(hfile, buf, count);
+        } else {
+          ReadConsoleInput(hfile, &ir, 1, &n);
+        }
+      }
+      break;
+    case WAIT_IO_COMPLETION:
+      errno = EINTR;
+      return -1;
+      break;
+    case WAIT_FAILED:
+      _dosmaperr(GetLastError());
+      return -1;
+      break;
+    }
+  } while (1);
+}
+
+ssize_t
+lisp_read(HANDLE hfile, void *buf, unsigned int count) {
+  switch(GetFileType(hfile)) {
+  case FILE_TYPE_CHAR:
+    return console_read(hfile, buf, count);
+    break;
+
+  case FILE_TYPE_PIPE:          /* pipe or one of these newfangled socket things */
+    {
+      int socktype, optlen = sizeof(int);
+      if ((getsockopt((SOCKET)hfile, SOL_SOCKET, SO_TYPE, (char *)&socktype, &optlen) != 0) && (GetLastError() == WSAENOTSOCK)) {
+        return pipe_read(hfile, buf, count);
+      }
+    }
+    /* It's a socket, fall through */
+    
+  case FILE_TYPE_DISK:
+    return lisp_standard_read(hfile, buf, count);
+    break;
+
+  default:
+    errno = EBADF;
+    return -1;
+  }
+}
+
+
+
+ssize_t
+lisp_write(HANDLE hfile, void *buf, ssize_t count)
+{
+  HANDLE hevent;
+  OVERLAPPED overlapped;
+  DWORD err, nwritten, wait_result;
+  pending_io pending;
+  TCR *tcr = (TCR *)get_tcr(1);
+
+  hevent = (HANDLE)tcr->io_datum;
+  if (hfile == (HANDLE)1) {
+    hfile = GetStdHandle(STD_OUTPUT_HANDLE);
+  } else if (hfile == (HANDLE) 2) {
+    hfile = GetStdHandle(STD_ERROR_HANDLE);
+  }
+
+
+  memset(&overlapped,0,sizeof(overlapped));
+
+  if (GetFileType(hfile) == FILE_TYPE_DISK) {
+    overlapped.Offset = SetFilePointer(hfile, 0, &(overlapped.OffsetHigh), FILE_CURRENT);
+  }
+
+
+  pending.h = hfile;
+  pending.o = &overlapped;
+  tcr->pending_io_info = &pending;
+  overlapped.hEvent = hevent;
+  ResetEvent(hevent);
+  if (WriteFile(hfile, buf, count, &nwritten, &overlapped)) {
+    tcr->pending_io_info = NULL;
+    return nwritten;
+  }
+  
+  err = GetLastError();
+  if (err != ERROR_IO_PENDING) {
+    _dosmaperr(err);
+    tcr->pending_io_info = NULL;
+    return -1;
+  }
+  err = 0;
+  wait_result = WaitForSingleObjectEx(hevent, INFINITE, true);
+  tcr->pending_io_info = NULL;
+  if (wait_result == WAIT_OBJECT_0) {
+    err = overlapped.Internal;
+    if (err) {
+      _dosmaperr(err);
+      return -1;
+    }
+    return overlapped.InternalHigh;
+  }
+  if (wait_result == WAIT_IO_COMPLETION) {
+    CancelIo(hfile);
+    errno = EINTR;
+    return -1;
+  }
+  err = GetLastError();
+  _dosmaperr(err);
+  return -1;
+}
+
+int
+lisp_fchmod(HANDLE hfile, int mode)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+__int64
+lisp_lseek(HANDLE hfile, __int64 offset, int whence)
+{
+  DWORD high, low;
+
+  high = ((__int64)offset)>>32;
+  low = offset & 0xffffffff;
+  low = SetFilePointer(hfile, low, &high, whence);
+  if (low != INVALID_SET_FILE_POINTER) {
+    return ((((__int64)high)<<32)|low);
+  }
+  _dosmaperr(GetLastError());
+  return -1;
+}
+
+#define ALL_USERS(f) ((f) | ((f)>> 3) | ((f >> 6)))
+#define STAT_READONLY ALL_USERS(_S_IREAD)
+#define STAT_READWRITE ALL_USERS((_S_IREAD|_S_IWRITE))
+int
+lisp_stat(wchar_t *path, struct __stat64 *buf)
+{
+  return _wstat64(path,buf);
+}
+
+#define UNIX_EPOCH_IN_WINDOWS_EPOCH  116444736000000000LL
+
+__time64_t
+filetime_to_unix_time(FILETIME *ft)
+{
+  __time64_t then = *((__time64_t *) ft);
+
+  then -= UNIX_EPOCH_IN_WINDOWS_EPOCH;
+  return then/10000000;
+}
+
+int
+lisp_fstat(HANDLE hfile, struct __stat64 *buf)
+{
+  int filetype;
+
+  filetype = GetFileType(hfile) & ~FILE_TYPE_REMOTE;
+
+  if (filetype == FILE_TYPE_UNKNOWN) {
+    errno = EBADF;
+    return -1;
+  }
+
+  memset(buf, 0, sizeof(*buf));
+  buf->st_nlink = 1;
+  
+  switch(filetype) {
+  case FILE_TYPE_CHAR:
+  case FILE_TYPE_PIPE:
+    if (filetype == FILE_TYPE_CHAR) {
+      buf->st_mode = _S_IFCHR;
+    } else {
+      buf->st_mode = _S_IFIFO;
+    }
+    break;
+  case FILE_TYPE_DISK:
+    {
+      BY_HANDLE_FILE_INFORMATION info;
+
+      if (!GetFileInformationByHandle(hfile, &info)) {
+        _dosmaperr(GetLastError());
+        return -1;
+      }
+
+      if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+        buf->st_mode = STAT_READONLY;
+      } else {
+        buf->st_mode = STAT_READWRITE;
+      }
+      buf->st_mode |= _S_IFREG;
+      buf->st_size = ((((__int64)(info.nFileSizeHigh))<<32LL) |
+                      ((__int64)(info.nFileSizeLow)));
+      buf->st_mtime = filetime_to_unix_time(&info.ftLastWriteTime);
+      buf->st_atime = filetime_to_unix_time(&info.ftLastAccessTime);
+      buf->st_ctime = filetime_to_unix_time(&info.ftCreationTime);
+    }
+    break;
+  case FILE_TYPE_UNKNOWN:
+  default:
+    errno = EBADF;
+    return -1;
+  }
+  return 0;
+}
+
+int
+lisp_futex(int *uaddr, int op, int val, void *timeout, int *uaddr2, int val3)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+
+__int64
+lisp_ftruncate(HANDLE hfile, off_t new_size)
+{
+  __int64 oldpos;
+
+
+  oldpos = lisp_lseek(hfile, 0, SEEK_END);
+  if (oldpos == -1) {
+    return 0;
+  }
+  if (oldpos < new_size) {
+    char buf[4096];
+    __int64 n = new_size-oldpos;
+    DWORD nwritten, to_write;
+
+    memset(buf,0,sizeof(buf));
+    while(n) {
+      if (n > 4096LL) {
+        to_write = 4096;
+      } else {
+        to_write = n;
+      }
+      if (!WriteFile(hfile,buf,to_write,&nwritten,NULL)) {
+        _dosmaperr(GetLastError());
+        return -1;
+      }
+      n -= nwritten;
+    }
+    return 0;
+  }
+  lisp_lseek(hfile, new_size, SEEK_SET);
+  if (SetEndOfFile(hfile)) {
+    return 0;
+  }
+  _dosmaperr(GetLastError());
+  return -1;
+}
+
+
+_WDIR *
+lisp_opendir(wchar_t *path)
+{
+  return _wopendir(path);
+}
+
+struct _wdirent *
+lisp_readdir(_WDIR *dir)
+{
+  return _wreaddir(dir);
+}
+
+__int64
+lisp_closedir(_WDIR *dir)
+{
+  return _wclosedir(dir);
+}
+
+int
+lisp_pipe(int fd[2])
+{
+  HANDLE input, output;
+  SECURITY_ATTRIBUTES sa;
+
+  sa.nLength= sizeof(SECURITY_ATTRIBUTES);
+  sa.lpSecurityDescriptor = NULL;
+  sa.bInheritHandle = TRUE;
+
+  if (!CreatePipe(&input, &output, &sa, 0))
+    {
+      wperror("CreatePipe");
+      return -1;
+    }
+  fd[0] = (int) ((intptr_t)input);
+  fd[1] = (int) ((intptr_t)output);
+  return 0;
+}
+
+int
+lisp_gettimeofday(struct timeval *tp, void *tzp)
+{
+  __time64_t now;
+
+  gettimeofday(tp,tzp);       /* trust it to get time zone right, at least */
+  GetSystemTimeAsFileTime((FILETIME*)&now);
+  now -= UNIX_EPOCH_IN_WINDOWS_EPOCH;
+  now /= 10000;               /* convert time to milliseconds */
+  tp->tv_sec = now/1000LL;
+  tp->tv_usec = 1000 * (now%1000LL); /* convert milliseconds to microseconds */
+  return 0;
+}
+
+int
+lisp_sigexit(int signum)
+{
+  signal(signum, SIG_DFL);
+  return raise(signum);
+}
+
+#ifdef WIN_64
+
+/* Make sure that the lisp calls these functions, when they do something */
+/* This code is taken from the 32-bit mingw library and is in the
+   public domain */
+double
+acosh(double x)
+{
+  if (isnan (x)) 
+    return x;
+
+  if (x < 1.0)
+    {
+      errno = EDOM;
+      return nan("");
+    }
+
+  if (x > 0x1p32)
+    /*  Avoid overflow (and unnecessary calculation when
+        sqrt (x * x - 1) == x). GCC optimizes by replacing
+        the long double M_LN2 const with a fldln2 insn.  */ 
+    return log (x) + 6.9314718055994530941723E-1L;
+
+  /* Since  x >= 1, the arg to log will always be greater than
+     the fyl2xp1 limit (approx 0.29) so just use logl. */ 
+  return log (x + sqrt((x + 1.0) * (x - 1.0)));
+}
+
+float
+acoshf(float x)
+{
+  if (isnan (x)) 
+    return x;
+  if (x < 1.0f)
+    {
+      errno = EDOM;
+      return nan("");
+    }
+
+ if (x > 0x1p32f)
+    /*  Avoid overflow (and unnecessary calculation when
+        sqrt (x * x - 1) == x). GCC optimizes by replacing
+        the long double M_LN2 const with a fldln2 insn.  */ 
+    return log (x) + 6.9314718055994530941723E-1L;
+
+  /* Since  x >= 1, the arg to log will always be greater than
+     the fyl2xp1 limit (approx 0.29) so just use logl. */ 
+  return log (x + sqrt((x + 1.0) * (x - 1.0)));
+}
+
+double
+asinh(double x)
+{
+  double z;
+  if (!isfinite (x))
+    return x;
+  z = fabs (x);
+
+  /* Avoid setting FPU underflow exception flag in x * x. */
+#if 0
+  if ( z < 0x1p-32)
+    return x;
+#endif
+
+  /* Use log1p to avoid cancellation with small x. Put
+     x * x in denom, so overflow is harmless. 
+     asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0)
+              = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0))  */
+
+  z = log1p (z + z * z / (sqrt (z * z + 1.0) + 1.0));
+
+  return ( x >= 0.0 ? z : -z);
+}
+
+float
+asinhf(float x)
+{
+  float z;
+  if (!isfinite (x))
+    return x;
+  z = fabsf (x);
+
+  /* Avoid setting FPU underflow exception flag in x * x. */
+#if 0
+  if ( z < 0x1p-32)
+    return x;
+#endif
+
+
+  /* Use log1p to avoid cancellation with small x. Put
+     x * x in denom, so overflow is harmless. 
+     asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0)
+              = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0))  */
+
+  z = log1p (z + z * z / (sqrt (z * z + 1.0) + 1.0));
+
+  return ( x >= 0.0 ? z : -z);
+}
+
+double
+atanh(double x)
+{
+  double z;
+  if (isnan (x))
+    return x;
+  z = fabs (x);
+  if (z == 1.0)
+    {
+      errno  = ERANGE;
+      return (x > 0 ? INFINITY : -INFINITY);
+    }
+  if (z > 1.0)
+    {
+      errno = EDOM;
+      return nan("");
+    }
+  /* Rearrange formula to avoid precision loss for small x.
+
+  atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x))
+	   = 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0)
+           = 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) 
+           = 0.5 * log1p ((2.0 * x ) / (1.0 - x))  */
+  z = 0.5 * log1p ((z + z) / (1.0 - z));
+  return x >= 0 ? z : -z;
+}
+
+float
+atanhf(float x)
+{
+  float z;
+  if (isnan (x))
+    return x;
+  z = fabsf (x);
+  if (z == 1.0)
+    {
+      errno  = ERANGE;
+      return (x > 0 ? INFINITY : -INFINITY);
+    }
+  if ( z > 1.0)
+    {
+      errno = EDOM;
+      return nanf("");
+    }
+  /* Rearrange formula to avoid precision loss for small x.
+
+  atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x))
+	   = 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0)
+           = 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) 
+           = 0.5 * log1p ((2.0 * x ) / (1.0 - x))  */
+  z = 0.5 * log1p ((z + z) / (1.0 - z));
+  return x >= 0 ? z : -z;
+}
+
+#endif
+
+typedef struct {
+  char *name;
+  void *addr;
+} math_fn_entry;
+
+
+math_fn_entry math_fn_entries [] = {
+  {"acos",acos},
+  {"acosf",acosf},
+  {"acosh",acosh},
+  {"acoshf",acoshf},
+  {"asin",asin},
+  {"asinf",asinf},
+  {"asinh",asinh},
+  {"asinhf",asinhf},
+  {"atan",atan},
+  {"atan2",atan2},
+  {"atan2f",atan2f},
+  {"atanf",atanf},
+  {"atanh",atanh},
+  {"atanhf",atanhf},
+  {"cos",cos},
+  {"cosf",cosf},
+  {"cosh",cosh},
+  {"coshf",coshf},
+  {"exp",exp},
+  {"expf",expf},
+  {"log",log},
+  {"logf",logf},
+  {"pow",pow},
+  {"powf",powf},
+  {"sin",sin},
+  {"sinf",sinf},
+  {"sinh",sinh},
+  {"sinhf",sinhf},
+  {"tan",tan},
+  {"tanf",tanf},
+  {"tanh",tanh},
+  {"tanhf",tanhf},
+  {NULL, 0}};
+
+void *
+lookup_math_fn(char *name)
+{
+  math_fn_entry *p = math_fn_entries;
+  char *entry_name;
+  
+  while ((entry_name = p->name) != NULL) {
+    if (!strcmp(name, entry_name)) {
+      return p->addr;
+    }
+    p++;
+  }
+  return NULL;
+}
+
+HMODULE *modules = NULL;
+DWORD cbmodules = 0;
+HANDLE find_symbol_lock = 0;
+
+void *
+windows_find_symbol(void *handle, char *name)
+{
+  void *addr;
+
+  if ((handle == ((void *)-2L)) ||
+      (handle == ((void *)-1L))) {
+    handle = NULL;
+  }
+  if (handle != NULL) {
+    addr = GetProcAddress(handle, name);
+  } else {
+    DWORD cbneeded,  have, i;
+    WaitForSingleObject(find_symbol_lock,INFINITE);
+
+    if (cbmodules == 0) {
+      cbmodules = 16 * sizeof(HANDLE);
+      modules = malloc(cbmodules);
+    }
+    
+    while (1) {
+      EnumProcessModules(GetCurrentProcess(),modules,cbmodules,&cbneeded);
+      if (cbmodules >= cbneeded) {
+        break;
+      }
+      cbmodules = cbneeded;
+      modules = realloc(modules,cbmodules);
+    }
+    have = cbneeded/sizeof(HANDLE);
+
+    for (i = 0; i < have; i++) {
+      addr = GetProcAddress(modules[i],name);
+
+      if (addr) {
+        break;
+      }
+    }
+    ReleaseMutex(find_symbol_lock);
+    if (addr) {
+      return addr;
+    }
+    return lookup_math_fn(name);
+  }
+}
+
+/* Note that we're using 8-bit strings here */
+
+void *
+windows_open_shared_library(char *path)
+{
+  HMODULE module = (HMODULE)0;
+
+  /* Try to open an existing module in a way that increments its
+     reference count without running any initialization code in
+     the dll. */
+  if (!GetModuleHandleExA(0,path,&module)) {
+    /* If that failed ... */
+    module = LoadLibraryA(path);
+  }
+  return (void *)module;
+}
+
+
+void
+init_windows_io()
+{
+#ifdef WIN_32
+  extern void init_win32_ldt(void);
+  init_win32_ldt();
+#endif
+  find_symbol_lock = CreateMutex(NULL,false,NULL);
+}
+
+void
+init_winsock()
+{
+  WSADATA data;
+
+  WSAStartup((2<<8)|2,&data);
+}
+
Index: /branches/new-random/lisp-kernel/x86-asmutils32.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-asmutils32.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-asmutils32.s	(revision 13309)
@@ -0,0 +1,285 @@
+/*   Copyright (C) 2005-2009 Clozure Associates */
+/*   This file is part of Clozure CL.   */
+ 
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence.   */
+ 
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+ 
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+	
+
+	include(lisp.s)
+
+	_beginfile
+
+_exportfn(C(current_stack_pointer))
+	__(movl %esp,%eax)
+	__(ret)
+_endfn
+                        
+_exportfn(C(count_leading_zeros))
+	__(bsr 4(%esp),%eax)
+	__(xor $31,%eax)
+	__(ret)
+_endfn
+
+_exportfn(C(noop))
+	__(ret)
+_endfn
+
+_exportfn(C(set_mxcsr))
+        __(ldmxcsr 4(%esp))
+        __(ret)
+_endfn
+	
+_exportfn(C(get_mxcsr))
+        __(push $0)
+        __(stmxcsr (%esp))
+        __(pop %eax)
+        __(ret)
+_endfn
+
+_exportfn(C(save_fp_context))
+_endfn
+        
+_exportfn(C(restore_fp_context))
+_endfn                        
+
+/*  Atomically store new in *p, if *p == old. */
+/*  Return actual old value. */
+/* natural store_conditional(natural *p, natural old, natural new) */
+_exportfn(C(store_conditional))
+	__(movl 12(%esp),%edx)	/* new */
+	__(movl 8(%esp),%eax)	/* old */
+	__(movl 4(%esp),%ecx)	/* ptr */
+	__(lock)
+        __(cmpxchgl %edx,(%ecx))
+	__(cmovne %edx,%eax)
+	__(ret)
+_endfn
+
+/*	Atomically store val in *p; return previous *p */
+/*	of *%rdi. */
+/* signed_natural atomic_swap(signed_natural *p, signed_natural val) */
+_exportfn(C(atomic_swap))
+	__(movl 8(%esp),%eax)
+	__(movl 4(%esp),%edx)
+	__(lock)
+        __(xchg %eax,(%edx))
+	__(ret)
+_endfn
+
+/*      Logior the value in *p with mask (presumably a */
+/*	bitmask with exactly 1 bit set.)  Return non-zero if any of */
+/*	the bits in that bitmask were already set. */
+/* natural atomic_ior(natural *p, natural mask) */
+_exportfn(C(atomic_ior))
+	__(movl 4(%esp),%edx)	/* ptr */
+0:	__(movl (%edx),%eax)
+	__(movl %eax,%ecx)
+	__(orl 8(%esp),%ecx)
+	__(lock)
+        __(cmpxchg %ecx,(%edx))
+        __(jnz 0b)
+	__(andl 8(%esp),%eax)
+	__(ret)
+_endfn
+        
+        
+/* Logand the value in *p with mask (presumably a bitmask with exactly 1 */
+/* bit set.)  Return the value now in *p (for some value of "now"). */
+/* natural atomic_and(natural *p, natural mask) */
+_exportfn(C(atomic_and))
+	__(movl 4(%esp),%edx)
+0:	__(movl (%edx),%eax)
+	__(movl %eax,%ecx)
+	__(and 8(%esp),%ecx)
+	__(lock)
+        __(cmpxchg %ecx,(%edx))
+        __(jnz 0b)
+	__(movl %ecx,%eax)
+	__(ret)
+_endfn
+
+
+        __ifdef([DARWIN])
+_exportfn(C(pseudo_sigreturn))
+        __(hlt)
+        __(jmp C(pseudo_sigreturn))
+_endfn
+        __endif    
+
+/* int cpuid (int code, int *pebx, int *pecx, int *pedx)  */
+_exportfn(C(cpuid))
+	__(push %ebx)		/* %ebx is non-volatile */
+	__(push %esi)		/* ditto here */
+	__(movl 12(%esp),%eax)
+        __(xorl %ecx,%ecx)
+	__(cpuid)
+	__(movl 16(%esp),%esi)
+	__(movl %ebx,(%esi))
+	__(movl 20(%esp),%esi)
+	__(movl %ecx,(%esi))
+	__(movl 24(%esp),%esi)
+	__(movl %edx,(%esi))
+	__(pop %esi)
+	__(pop %ebx)
+	__(ret)
+_endfn
+
+/* switch_to_foreign_stack(new_sp, func, arg_0, arg_1, arg_2)  */
+/*   Not fully general, but should get us off of the signal stack */
+/* Beware: on Darwin, GDB can get very confused by this code, and
+   doesn't really get unconfused until the target function - the
+   handler - has built its stack frame
+   The lone caller of this function passes 3 arguments (besides
+   the new stack pointer and the handler address.)
+   On platforms where the C stack must be 16-byte aligned, pushing
+   a 4th word helps make the stack aligned before the return
+   address is (re-)pushed.
+   On Linux, there are severe constraints on what the top of stack
+   can look like when rt_sigreturn (the code at the return address)
+   runs, and there aren't any constraints on stack alignment, so
+   we don't push the extra word on the new stack.*/
+_exportfn(C(switch_to_foreign_stack))
+        __(addl $4,%esp)        /* discard return address, on wrong stack */
+        __(pop %edi)            /* new esp */
+        __(pop %esi)            /* handler */
+        __(pop %eax)            /* arg_0 */
+        __(pop %ebx)            /* arg_1 */
+        __(pop %ecx)            /* arg_2 */
+        __(mov %edi,%esp)
+        __(pop %edi)            /* Return address pushed by caller */
+        __ifndef([LINUX])
+        __(push $0)             /* For alignment. See comment above */
+        __endif
+        __(push %ecx)           /* arg_2 */
+        __(push %ebx)           /* arg_1 */
+        __(push %eax)           /* arg_0 */
+        __(push %edi)           /* return address */
+        __(jmp *%esi)           /* On some platforms, we don't really return */
+_endfn
+
+        __ifdef([FREEBSD])
+        .globl C(sigreturn)
+_exportfn(C(freebsd_sigreturn))
+        __(jmp C(sigreturn))
+_endfn
+        __endif
+
+        __ifdef([DARWIN])
+_exportfn(C(darwin_sigreturn))
+/* Need to set the sigreturn 'infostyle' argument, which is mostly
+   undocumented.  On x8632 Darwin, sigtramp() sets it to 0x1e, and
+   since we're trying to do what sigtramp() would do if we'd returned
+   to it ... */
+        __(movl $0x1e,8(%esp))
+	__(movl $0xb8,%eax)	/* SYS_sigreturn */
+	__(int $0x80)
+	__(ret)			/* shouldn't return */
+
+_endfn
+        __endif        
+		
+_exportfn(C(get_vector_registers))
+	__(ret)
+_endfn
+
+_exportfn(C(put_vector_registers))
+	__(ret)
+_endfn				
+
+        __ifdef([WIN_32])
+_exportfn(C(restore_windows_context))
+Xrestore_windows_context_start:
+        __(movl 4(%esp),%ecx)   /* context */
+        __(movl 12(%esp),%edx)  /* old valence */
+        __(movl 8(%esp),%eax)   /* tcr */
+        __(movw tcr.ldt_selector(%eax), %rcontext_reg)
+        __(movl %edx,rcontext(tcr.valence))
+        __(movl $0,rcontext(tcr.pending_exception_context))
+        __(frstor win32_context.FloatSave(%ecx))
+        /* Windows doesn't bother to align the context, so use
+          'movupd' here */
+        __(movupd win32_context.Xmm0(%ecx),%xmm0)
+        __(movupd win32_context.Xmm1(%ecx),%xmm1)
+        __(movupd win32_context.Xmm2(%ecx),%xmm2)
+        __(movupd win32_context.Xmm3(%ecx),%xmm3)
+        __(movupd win32_context.Xmm4(%ecx),%xmm4)
+        __(movupd win32_context.Xmm5(%ecx),%xmm5)
+        __(movupd win32_context.Xmm6(%ecx),%xmm6)
+        __(movupd win32_context.Xmm7(%ecx),%xmm7)
+        __(ldmxcsr win32_context.MXCSR(%ecx))
+        __(movl win32_context.Ebp(%ecx),%ebp)
+        __(movl win32_context.Edi(%ecx),%edi)
+        __(movl win32_context.Esi(%ecx),%esi)
+        __(movl win32_context.Edx(%ecx),%edx)
+        __(movl win32_context.Ebx(%ecx),%ebx)
+        __(movl win32_context.Eax(%ecx),%eax)
+        __(movl win32_context.Esp(%ecx),%esp)
+        __(pushl win32_context.EFlags(%ecx))
+        __(pushl %cs)
+        __(pushl win32_context.Eip(%ecx))        
+        /* This must be the last thing before the iret, e.g., if we're
+        interrupted before the iret, the context we're returning to here
+        is still in %ecx.  If we're interrupted -at- the iret, then
+        everything but that which the iret will restore has been restored. */
+        __(movl win32_context.Ecx(%ecx),%ecx)
+Xrestore_windows_context_iret:            
+        __(iret)
+Xrestore_windows_context_end:             
+        __(nop)
+_endfn
+	
+_exportfn(C(windows_switch_to_foreign_stack))
+        __(pop %eax)
+        __(pop %ebx)            /* new %esp */
+        __(pop %ecx)            /* handler */
+        __(pop %edx)            /* arg */
+        __(movl %ebx,%esp)
+        __(subl $0x10,%esp)
+        __(movl %edx,(%esp))
+        __(push %eax)
+        __(jmp *%ecx)
+_endfn        
+
+        .data
+        .globl C(restore_windows_context_start)
+        .globl C(restore_windows_context_end)
+        .globl C(restore_windows_context_iret)
+C(restore_windows_context_start):  .long Xrestore_windows_context_start
+C(restore_windows_context_end): .long Xrestore_windows_context_end
+C(restore_windows_context_iret): .long Xrestore_windows_context_iret
+        .text
+        
+        __ifdef([WIN32_ES_HACK])
+/* Something that we shouldn't return to */
+_exportfn(C(windows_halt))
+        __(hlt)
+_endfn         
+        __endif
+_exportfn(C(ensure_safe_for_string_operations))
+        __ifdef([WIN32_ES_HACK])
+        __(movw %es,%ax)
+        __(movw %ds,%dx)
+        __(cmpw %ax,%dx)
+        __(jne 9f)
+0:      __(movw %dx,%es)
+        __endif
+        __(cld)        
+	__(ret)
+        __ifdef([WIN32_ES_HACK])
+9:      __(hlt)
+        __(jmp 0b)
+        __endif
+_endfn                                       
+        __endif
+        _endfile
+
Index: /branches/new-random/lisp-kernel/x86-asmutils64.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-asmutils64.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-asmutils64.s	(revision 13309)
@@ -0,0 +1,308 @@
+/*   Copyright (C) 2005-2009 Clozure Associates */
+/*   This file is part of Clozure CL.   */
+ 
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence.   */
+ 
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+ 
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+	
+
+	include(lisp.s)
+
+	_beginfile
+
+/* Flush %carg1 cache lines, starting at address in %carg0.  Each line is */
+/*   assumed to be %carg2 bytes wide. */
+_exportfn(C(flush_cache_lines))
+	__(cmpq $0,%carg1)
+	__(jmp 2f)
+1:	__(clflush (%carg0))
+	__(addq %carg2,%carg0)
+	__(subq $1,%carg1)
+2:	__(jg 1b)	
+	__(repret)
+_endfn
+
+_exportfn(C(current_stack_pointer))
+	__(movq %rsp,%cret)
+	__(ret)
+_endfn
+
+_exportfn(C(touch_page))
+        __(movq %carg0,(%carg0))
+        __(movq $0,(%carg0))
+        __(movl $1,%cret_l)
+        .globl C(touch_page_end)
+C(touch_page_end):	
+        __(ret)
+                        
+_exportfn(C(count_leading_zeros))
+	__(bsrq %carg0,%cret)
+	__(xorq $63,%cret)
+	__(ret)
+_endfn
+
+_exportfn(C(noop))
+	__(retq)
+_endfn
+
+_exportfn(C(set_mxcsr))
+        __(pushq %carg0)
+        __(ldmxcsr (%rsp))
+        __(addq $8,%rsp)
+        __(ret)
+_endfn
+	
+_exportfn(C(get_mxcsr))
+        __(pushq $0)
+        __(stmxcsr (%rsp))
+        __(popq %cret)
+        __(ret)
+_endfn
+
+_exportfn(C(save_fp_context))
+_endfn
+        
+_exportfn(C(restore_fp_context))
+_endfn                        
+
+/*  Atomically store new value (%carg2) in *%carg0, if old value == %carg1. */
+/*  Return actual old value. */
+_exportfn(C(store_conditional))
+	__(mov %carg1,%cret)
+	__(lock) 
+        __(cmpxchgq %carg2,(%carg0))
+	__(cmovne %carg2,%cret)
+	__(ret)	
+_endfn
+
+/*	Atomically store new_value(%carg1) in *%carg0 ;  return previous contents */
+/*	of *%carg0. */
+
+_exportfn(C(atomic_swap))
+	__(lock) 
+        __(xchg %carg1,(%carg0))
+	__(mov %carg1,%cret)
+	__(ret)
+_endfn
+
+/*        Logior the value in *%carg0 with the value in %carg1 (presumably a */
+/*	bitmask with exactly 1 bit set.)  Return non-zero if any of */
+/*	the bits in that bitmask were already set. */
+_exportfn(C(atomic_ior))
+0:	__(movq (%carg0),%cret)
+	__(movq %cret,%carg2)
+	__(orq %carg1,%carg2)
+	__(lock)
+        __(cmpxchg %carg2,(%carg0))
+        __(jnz 0b)
+	__(andq %carg1,%cret)
+	__(ret)
+_endfn
+        
+        
+/* Logand the value in *carg0 with the value in carg1 (presumably a bitmask with exactly 1 */
+/* bit set.)  Return the value now in *carg0 (for some value of "now" */
+
+_exportfn(C(atomic_and))
+0:	__(movq (%carg0),%cret)
+	__(movq %cret,%carg2)
+	__(and %carg1,%carg2)
+	__(lock)
+        __(cmpxchg %carg2,(%carg0))
+        __(jnz 0b)
+	__(movq %carg2,%cret)
+	__(ret)
+_endfn
+
+
+        __ifdef([DARWIN])
+_exportfn(C(pseudo_sigreturn))
+        __(hlt)
+        __(jmp C(pseudo_sigreturn))
+_endfn
+        __endif                        
+
+/* int cpuid (natural code, natural *pebx, natural *pecx, natural *pedx)  */
+_exportfn(C(cpuid))
+	__(pushq %carg2)
+	__(pushq %carg3)
+	__(movq %carg1, %ctemp0)
+	__(pushq %rbx)		/* non-volatile reg, clobbered by CPUID */
+	__(movq %carg0, %rax)
+        __(xorq %rcx,%rcx)
+	__(cpuid)
+	__(movq %rbx,(%ctemp0))
+	__(popq %rbx)
+	__(popq %ctemp0)           /* recover pedx */
+	__(movq %rdx,(%ctemp0))
+	__(popq %ctemp0)		/* recover pecx */
+	__(movq %rcx,(%ctemp0))
+	__(ret)
+_endfn
+
+/* switch_to_foreign_stack(new_sp, func, arg_0, arg_1, arg_2, arg_3)  */
+/*   Not fully general, but should get us off of the signal stack */
+        __ifndef([WINDOWS])
+_exportfn(C(switch_to_foreign_stack))
+	__(movq %rdi,%rsp)
+	__(movq %rsi,%rax)
+	__(movq %rdx,%rdi)
+	__(movq %rcx,%rsi)
+	__(movq %r8,%rdx)
+	__(movq %r9,%rcx)
+	__(jmp *%rax)
+_endfn
+        __endif
+        
+_exportfn(C(freebsd_sigreturn))
+	__(movl $417,%eax)	/* SYS_sigreturn */
+	__(syscall)				
+	
+_exportfn(C(get_vector_registers))
+_endfn
+
+_exportfn(C(put_vector_registers))
+_endfn				
+        
+	__ifdef([DARWIN])
+_exportfn(C(darwin_sigreturn))
+        .globl C(sigreturn)
+/* Need to set the sigreturn 'infostyle' argument, which is mostly
+   undocumented.  On x8664 Darwin, sigtramp() sets it to 0x1e, and
+   since we're trying to do what sigtramp() would do if we'd returned
+   to it ... */
+        __(movl $0x1e,%esi)
+	__(movl $0x20000b8,%eax)
+	__(syscall)
+	__(ret)
+_endfn
+	__endif
+
+	
+        
+        __ifdef([DARWIN_GS_HACK])
+/* Check (in an ugly, non-portable way) to see if %gs is addressing
+   pthreads data.  If it was, return 0; otherwise, assume that it's
+   addressing a lisp tcr and set %gs to point to the tcr's tcr.osid,
+   then return 1. */
+	
+thread_signature = 0x54485244 /* 'THRD' */
+	
+_exportfn(C(ensure_gs_pthread))
+        __(cmpl $thread_signature,%gs:0)
+        __(movl $0,%eax)
+        __(je 9f)
+        __(movq %gs:tcr.osid,%rdi)
+        __(movl $0x3000003,%eax)
+        __(syscall)
+        __(movl $1,%eax)
+9:      __(repret)
+_endfn
+
+        /* Ensure that %gs addresses the linear address in %rdi */
+        /* This incidentally returns the segment selector .*/
+_exportfn(C(set_gs_address))
+        __(movl $0x3000003,%eax)
+        __(syscall)
+        __(ret)
+_endfn
+        __endif
+
+        __ifdef([WIN_64])
+/* %rcx = CONTEXT, %rdx = tcr, %r8 = old_valence.  This pretty
+   much has to be uninterruptible */        
+_exportfn(C(restore_windows_context))
+Xrestore_windows_context_start: 	
+        __(subq $0x38,%rsp)
+        __(xorl %eax,%eax)
+        __(movq %r8,tcr.valence(%rdx))
+        __(movq %rax,tcr.pending_exception_context(%rdx))
+        __(fxrstor win64_context.fpstate(%rcx))
+        __(movapd win64_context.Xmm0(%rcx),%xmm0)
+        __(movapd win64_context.Xmm1(%rcx),%xmm1)
+        __(movapd win64_context.Xmm2(%rcx),%xmm2)
+        __(movapd win64_context.Xmm3(%rcx),%xmm3)
+        __(movapd win64_context.Xmm4(%rcx),%xmm4)
+        __(movapd win64_context.Xmm5(%rcx),%xmm5)
+        __(movapd win64_context.Xmm6(%rcx),%xmm6)
+        __(movapd win64_context.Xmm7(%rcx),%xmm7)
+        __(movapd win64_context.Xmm8(%rcx),%xmm8)
+        __(movapd win64_context.Xmm9(%rcx),%xmm9)
+        __(movapd win64_context.Xmm10(%rcx),%xmm10)
+        __(movapd win64_context.Xmm11(%rcx),%xmm11)
+        __(movapd win64_context.Xmm12(%rcx),%xmm12)
+        __(movapd win64_context.Xmm13(%rcx),%xmm13)
+        __(movapd win64_context.Xmm14(%rcx),%xmm14)
+        __(movapd win64_context.Xmm15(%rcx),%xmm15)
+        __(ldmxcsr win64_context.MxCsr(%rcx))
+        __(movw win64_context.SegSs(%rcx),%ax)
+        __(movw %ax,0x20(%rsp))
+        __(movq win64_context.Rsp(%rcx),%rax)
+        __(movq %rax,0x18(%rsp))
+        __(movl win64_context.EFlags(%rcx),%eax)
+        __(movl %eax,0x10(%rsp))
+        __(movw win64_context.SegCs(%rcx),%ax)
+        __(movw %ax,8(%rsp))
+        __(movq win64_context.Rip(%rcx),%rax)
+        __(movq %rax,(%rsp))
+        __(movq win64_context.Rax(%rcx),%rax)
+        __(movq win64_context.Rbx(%rcx),%rbx)
+        __(movq win64_context.Rdx(%rcx),%rdx)
+        __(movq win64_context.Rdi(%rcx),%rdi)
+        __(movq win64_context.Rsi(%rcx),%rsi)
+        __(movq win64_context.Rbp(%rcx),%rbp)
+        __(movq win64_context.R8(%rcx),%r8)
+        __(movq win64_context.R9(%rcx),%r9)
+        __(movq win64_context.R10(%rcx),%r10)
+        __(movq win64_context.R11(%rcx),%r11)
+        __(movq win64_context.R12(%rcx),%r12)
+        __(movq win64_context.R13(%rcx),%r13)
+        __(movq win64_context.R14(%rcx),%r14)
+        __(movq win64_context.R15(%rcx),%r15)
+        /* This must be the last thing before the iret, e.g., if we're
+        interrupted before the iret, the context we're returning to here
+        is still in %rcx.  If we're interrupted -at- the iret, then
+        everything but that which the iret will restore has been restored. */
+        __(movq win64_context.Rcx(%rcx),%rcx)
+Xrestore_windows_context_iret:            
+        __(iretq)
+Xrestore_windows_context_end:             
+        __(nop)
+_endfn
+	
+_exportfn(C(windows_switch_to_foreign_stack))
+        __(pop %rax)
+        __(lea -0x20(%rcx),%rsp)
+        __(push %rax)
+        __(movq %r8,%rcx)
+        __(jmp *%rdx)
+_endfn        
+
+        .data
+        .globl C(restore_windows_context_start)
+        .globl C(restore_windows_context_end)
+        .globl C(restore_windows_context_iret)
+C(restore_windows_context_start):  .quad Xrestore_windows_context_start
+C(restore_windows_context_end): .quad Xrestore_windows_context_end
+C(restore_windows_context_iret): .quad Xrestore_windows_context_iret
+        .text
+
+/* Something that we shouldn't return to */
+_exportfn(C(windows_halt))
+        __(hlt)
+_endfn         
+_exportfn(C(ensure_safe_for_string_operations))
+        __(cld)
+        __(ret)
+_endfn                                       
+        __endif
+	_endfile
Index: /branches/new-random/lisp-kernel/x86-constants.h
===================================================================
--- /branches/new-random/lisp-kernel/x86-constants.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-constants.h	(revision 13309)
@@ -0,0 +1,63 @@
+/*
+   Copyright (C) 2005-2009 Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef __x86_constants__
+#define __x86_constants__ 1
+
+#define TCR_FLAG_BIT_FOREIGN fixnumshift
+#define TCR_FLAG_BIT_AWAITING_PRESET (fixnumshift+1)
+#define TCR_FLAG_BIT_ALT_SUSPEND (fixnumshift+2)
+#define TCR_FLAG_BIT_PROPAGATE_EXCEPTION (fixnumshift+3)
+#define TCR_FLAG_BIT_SUSPEND_ACK_PENDING (fixnumshift+4)
+#define TCR_FLAG_BIT_PENDING_EXCEPTION (fixnumshift+5)
+#define TCR_FLAG_BIT_FOREIGN_EXCEPTION (fixnumshift+6)
+#define TCR_FLAG_BIT_PENDING_SUSPEND (fixnumshift+7)
+#define TCR_STATE_FOREIGN (1)
+#define TCR_STATE_LISP    (0)
+#define TCR_STATE_EXCEPTION_WAIT (2)
+#define TCR_STATE_EXCEPTION_RETURN (4)
+
+#ifdef X8664
+#include "x86-constants64.h"
+#else
+#include "x86-constants32.h"
+#endif
+
+#define dnode_size (node_size*2)
+#define dnode_shift (node_shift+1)
+
+#define INTERRUPT_LEVEL_BINDING_INDEX (1)
+
+/* FP exception mask bits */
+#define MXCSR_IM_BIT (7)        /* invalid masked when set*/
+#define MXCSR_DM_BIT (8)        /* denormals masked when set*/
+#define MXCSR_ZM_BIT (9)        /* divide-by-zero masked when set */
+#define MXCSR_OM_BIT (10)       /* overflow masked when set */
+#define MXCSR_UM_BIT (11)       /* underflow masked when set */
+#define MXCSR_PM_BIT (12)       /* precision masked when set */
+
+/* Bits in the xFLAGS register */
+#define X86_CARRY_FLAG_BIT (0)
+#define X86_PARITY_FLAG_BIT (2)
+#define X86_AUX_CARRY_FLAG_BIT (4)
+#define X86_ZERO_FLAG_BIT (6)
+#define X86_SIGN_FLAG_BIT (7)
+#define X86_DIRECTION_FLAG_BIT (10)
+#define X86_OVERFLOW_FLAG_BIT (11)
+
+
+#endif /* __x86_constants__ */
+
Index: /branches/new-random/lisp-kernel/x86-constants.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-constants.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-constants.s	(revision 13309)
@@ -0,0 +1,139 @@
+/*   Copyright (C) 2005-2009 Clozure Associates  */
+/*   This file is part of Clozure CL.    */
+ 
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public  */
+/*   License , known as the LLGPL and distributed with Clozure CL as the  */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these  */
+/*   conflict, the preamble takes precedence.    */
+ 
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."  */
+ 
+/*   The LLGPL is also available online at  */
+/*   http://opensource.franz.com/preamble.html  */
+
+
+
+        
+/* Indices in %builtin-functions%  */
+	
+_builtin_plus = 0	/* +-2   */
+_builtin_minus = 1	/* --2   */
+_builtin_times = 2	/* *-2   */
+_builtin_div = 3	/* /-2   */
+_builtin_eq = 4		/* =-2   */
+_builtin_ne = 5		/* /-2   */
+_builtin_gt = 6		/* >-2   */
+_builtin_ge = 7		/* >=-2   */
+_builtin_lt = 8		/* <-2   */
+_builtin_le = 9		/* <=-2   */
+_builtin_eql = 10	/* eql   */
+_builtin_length = 11	/* length   */
+_builtin_seqtype = 12	/* sequence-type   */
+_builtin_assq = 13	/* assq   */
+_builtin_memq = 14	/* memq   */
+_builtin_logbitp = 15	/* logbitp   */
+_builtin_logior = 16	/* logior-2   */
+_builtin_logand = 17	/* logand-2   */
+_builtin_ash = 18	/* ash   */
+_builtin_negate = 19	/* %negate   */
+_builtin_logxor = 20	/* logxor-2   */
+_builtin_aref1 = 21	/* %aref1   */
+_builtin_aset1 = 22	/* %aset1   */
+	
+
+ifdef([X8664],[
+	include(x86-constants64.s)
+],[
+	include(x86-constants32.s)
+])						
+
+/* registers, as used in destructuring-bind/macro-bind   */
+ifdef([X8664],[
+define([whole_reg],[temp1])
+define([arg_reg],[temp0])
+define([keyvect_reg],[arg_x])
+],[
+define([arg_reg],[temp1])
+define([arg_reg_b],[temp1_b])
+define([keyvect_reg],[arg_y])
+])
+
+define([initopt_bit],[24])
+define([keyp_bit],[25]) /*  note that keyp can be true even when 0 keys.   */
+define([aok_bit],[26])
+define([restp_bit],[27])
+define([seen_aok_bit],[28])        
+        
+num_lisp_globals = 48		 /* MUST UPDATE THIS !!!   */
+	
+	_struct(lisp_globals,lisp_globals_limit-(num_lisp_globals*node_size))
+	 _node(initial_tcr)	        /* initial thread tcr */
+	 _node(image_name)	        /* --image-name argument */
+	 _node(BADfpscr_save_high)      /* high word of FP reg used to save FPSCR */
+	 _node(unwind_resume)           /* _Unwind_Resume */
+	 _node(batch_flag)	        /* -b */
+	 _node(host_platform)	        /* for runtime platform-specific stuff   */
+	 _node(argv)			/* address of argv[0]   */
+	 _node(ref_base)                /* start of oldest pointer-bearing area */
+	 _node(tenured_area) 		/* the tenured_area   */
+	 _node(oldest_ephemeral) 	/* dword address of oldest ephemeral object or 0   */
+	 _node(lisp_exit_hook)		/* install foreign exception_handling   */
+	 _node(lisp_return_hook)	/* install lisp exception_handling   */
+	 _node(double_float_one) 	/* high half of 1.0d0   */
+	 _node(short_float_zero) 	/* low half of 1.0d0   */
+	 _node(objc2_end_catch) 	/* objc_end_catch()  */
+	 _node(metering_info) 		/* address of lisp_metering global   */
+	 _node(in_gc) 			/* non-zero when GC active   */
+	 _node(lexpr_return1v) 		/* simpler when &lexpr called for single value.   */
+	 _node(lexpr_return) 		/* magic &lexpr return code.   */
+	 _node(all_areas) 		/* doubly-linked list of all memory areas   */
+	 _node(kernel_path)	 	/* real executable name */
+	 _node(objc2_begin_catch)	/* objc_begin_catch   */
+	 _node(stack_size) 		/* from the command line */
+	 _node(statically_linked)	/* non-zero if -static   */
+	 _node(heap_end)                /* end of lisp heap   */
+	 _node(heap_start)              /* start of lisp heap   */
+	 _node(gcable_pointers)         /* linked-list of weak macptrs.   */
+	 _node(gc_num)                  /* fixnum: GC call count.   */
+	 _node(fwdnum)                  /* fixnum: GC "forwarder" call count.   */
+	 _node(altivec_present)         /* non-zero when AltiVec available   */
+	 _node(oldspace_dnode_count) 	/* dynamic dnodes older than g0 start   */
+	 _node(refbits) 		/* EGC refbits   */
+	 _node(gc_inhibit_count)
+	 _node(intflag) 		/* sigint pending   */
+	 _node(default_allocation_quantum)	/* for per-thread allocation   */
+	 _node(deleted_static_pairs) 		
+	 _node(exception_lock)
+	 _node(area_lock)
+	 _node(tcr_key) 		/* tsd key for per-thread tcr   */
+	 _node(ret1val_addr) 		/* address of "dynamic" subprims magic values return addr   */
+	 _node(subprims_base) 		/* address of dynamic subprims jump table   */
+	 _node(saveR13)			/* probably don]t really need this   */
+	 _node(saveTOC)                 /* where the 68K emulator stores the  emulated regs   */
+	 _node(objc_2_personality)		/* exception "personality routine" address for ObjC 2.0 */
+	 _node(kernel_imports) 		/* some things we need imported for us   */
+	 _node(interrupt_signal)	/* signal used by PROCESS-INTERRUPT   */
+	 _node(tcr_count) 		/* tcr_id for next tcr   */
+	 _node(get_tcr) 		/* address of get_tcr()  */
+	_ends
+	
+	
+		
+define([TCR_STATE_FOREIGN],1)
+define([TCR_STATE_LISP],0)
+define([TCR_STATE_EXCEPTION_WAIT],2)
+define([TCR_STATE_EXCEPTION_RETURN],4)
+
+tstack_alloc_limit = 0xffff
+	
+mxcsr_ie_bit = 0                /* invalid */
+mxcsr_de_bit = 1                /* denorm */        
+mxcsr_ze_bit = 2
+mxcsr_oe_bit = 3
+mxcsr_ue_bit = 4
+mxcsr_pe_bit = 5
+num_mxcsr_exception_bits = 6
+        
+mxcsr_all_exceptions = ((1<<num_mxcsr_exception_bits)-1)
+        
Index: /branches/new-random/lisp-kernel/x86-constants32.h
===================================================================
--- /branches/new-random/lisp-kernel/x86-constants32.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-constants32.h	(revision 13309)
@@ -0,0 +1,499 @@
+/* offsets into uc_mcontext.ss */
+#ifdef DARWIN
+#define REG_EAX 0
+#define REG_EBX 1
+#define REG_ECX 2
+#define REG_EDX 3
+#define REG_EDI 4
+#define REG_ESI 5
+#define REG_EBP 6
+#define REG_ESP 7
+#define REG_EFL 9
+#define REG_EIP 10
+#endif
+
+#ifdef WINDOWS
+/* Offsets relative to _CONTEXT.Edi */
+#define REG_EDI 0
+#define REG_ESI 1
+#define REG_EBX 2
+#define REG_EDX 3
+#define REG_ECX 4
+#define REG_EAX 5
+#define REG_EBP 6
+#define REG_EIP 7
+#define REG_EFL 9
+#define REG_ESP 10
+#endif
+
+#ifdef FREEBSD
+#define REG_EDI 5
+#define REG_ESI 6
+#define REG_EBP 7
+#define REG_ISP 8
+#define REG_EBX 9
+#define REG_EDX 10
+#define REG_ECX 11
+#define REG_EAX 12
+#define REG_EIP 15
+#define REG_EFL 17
+#define REG_ESP 18
+#endif
+
+#ifdef SOLARIS
+#include <sys/regset.h>
+#include <limits.h>
+#define REG_EAX EAX
+#define REG_EBX EBX
+#define REG_ECX ECX
+#define REG_EDX EDX
+#define REG_ESI ESI
+#define REG_EDI EDI
+#define REG_EBP EBP
+#define REG_ESP UESP    /* Maybe ... ESP is often 0, but who knows why ? */
+#define REG_EFL EFL
+#define REG_EIP EIP
+#endif
+
+/* Indicies of GPRs in the mcontext component of a ucontext */
+#define Iimm0  REG_EAX
+#define Iarg_z REG_EBX
+#define Itemp0 REG_ECX
+#define Itemp1 REG_EDX
+#define Ifn    REG_EDI
+#define Iarg_y REG_ESI
+#define Iesp   REG_ESP
+#define Iebp   REG_EBP
+#define Ieip   REG_EIP
+#define Iflags REG_EFL
+
+#define Isp Iesp
+#define Iip Ieip
+#define Iallocptr Itemp0
+#define Ira0 Itemp0
+#define Inargs Itemp1
+#define Ixfn Itemp1
+#define Ifp Iebp
+
+/* MMX register offsets from where mm0 is found in uc_mcontext.fs */
+#define Imm0 0
+#define Imm1 1
+
+#define nbits_in_word 32
+#define log2_nbits_in_word 5
+#define nbits_in_byte 8
+#define ntagbits 3
+#define nlisptagbits 2
+#define nfixnumtagbits 2
+#define num_subtag_bits 8
+#define fixnumshift 2
+#define fixnum_shift 2
+#define fulltagmask 7
+#define tagmask  3
+#define fixnummask 3
+#define subtagmask ((1<<num_subtag_bits)-1)
+#define ncharcodebits 8
+#define charcode_shift 8
+#define node_size 4
+#define node_shift 2
+#define nargregs 2
+
+#define tag_fixnum 0
+#define tag_list 1
+#define tag_misc 2
+#define tag_imm 3
+
+#define fulltag_even_fixnum 0
+#define fulltag_cons 1
+#define fulltag_nodeheader 2
+#define fulltag_imm 3
+#define fulltag_odd_fixnum 4
+#define fulltag_tra 5
+#define fulltag_misc 6
+#define fulltag_immheader 7
+
+#define SUBTAG(tag,subtag) ((tag) | ((subtag) << ntagbits))
+#define IMM_SUBTAG(subtag) SUBTAG(fulltag_immheader,(subtag))
+#define NODE_SUBTAG(subtag) SUBTAG(fulltag_nodeheader,(subtag))
+
+#define subtag_bignum IMM_SUBTAG(0)
+#define min_numeric_subtag subtag_bignum
+#define subtag_ratio NODE_SUBTAG(1)
+#define max_rational_subtag subtag_ratio
+#define subtag_single_float IMM_SUBTAG(1)
+#define subtag_double_float IMM_SUBTAG(2)
+#define min_float_subtag subtag_single_float
+#define max_float_subtag subtag_double_float
+#define max_real_subtag subtag_double_float
+#define subtag_complex NODE_SUBTAG(3)
+#define max_numeric_subtag subtag_complex
+
+#define subtag_bit_vector IMM_SUBTAG(31)
+#define subtag_double_float_vector IMM_SUBTAG(30)
+#define subtag_s16_vector IMM_SUBTAG(29)
+#define subtag_u16_vector IMM_SUBTAG(28)
+#define min_16_bit_ivector_subtag subtag_u16_vector
+#define max_16_bit_ivector_subtag subtag_s16_vector
+
+/* subtag 27 unused*/
+#define subtag_s8_vector IMM_SUBTAG(26)
+#define subtag_u8_vector IMM_SUBTAG(25)
+#define min_8_bit_ivector_subtag subtag_u8_vector
+#define max_8_bit_ivector_subtag IMM_SUBTAG(27)
+
+#define subtag_simple_base_string IMM_SUBTAG(24)
+#define subtag_fixnum_vector IMM_SUBTAG(23)
+#define subtag_s32_vector IMM_SUBTAG(22)
+#define subtag_u32_vector IMM_SUBTAG(21)
+#define subtag_single_float_vector IMM_SUBTAG(20)
+#define max_32_bit_ivector_subtag IMM_SUBTAG(24)
+#define min_cl_ivector_subtag subtag_single_float_vector
+
+#define subtag_vectorH NODE_SUBTAG(20)
+#define subtag_arrayH NODE_SUBTAG(19)
+#define subtag_simple_vector NODE_SUBTAG(21)    /*  Only one such subtag */
+#define min_vector_subtag subtag_vectorH
+#define min_array_subtag subtag_arrayH
+
+#define subtag_macptr IMM_SUBTAG(3)
+#define min_non_numeric_imm_subtag subtag_macptr
+
+#define subtag_dead_macptr IMM_SUBTAG(4)
+#define subtag_code_vector IMM_SUBTAG(5)
+#define subtag_creole IMM_SUBTAG(6)
+
+#define max_non_array_imm_subtag ((19<<ntagbits)|fulltag_immheader)
+
+#define subtag_catch_frame NODE_SUBTAG(4)
+#define subtag_function NODE_SUBTAG(5)
+#define subtag_basic_stream NODE_SUBTAG(6)
+#define subtag_symbol NODE_SUBTAG(7)
+#define subtag_lock NODE_SUBTAG(8)
+#define subtag_hash_vector NODE_SUBTAG(9)
+#define subtag_pool NODE_SUBTAG(10)
+#define subtag_weak NODE_SUBTAG(11)
+#define subtag_package NODE_SUBTAG(12)
+#define subtag_slot_vector NODE_SUBTAG(13)
+#define subtag_instance NODE_SUBTAG(14)
+#define subtag_struct NODE_SUBTAG(15)
+#define subtag_istruct NODE_SUBTAG(16)
+#define max_non_array_node_subtag ((19<<ntagbits)|fulltag_immheader)
+
+#define subtag_unbound SUBTAG(fulltag_imm, 6)
+#define unbound_marker subtag_unbound
+#define undefined subtag_unbound
+#define unbound subtag_unbound
+#define subtag_character SUBTAG(fulltag_imm, 9)
+#define slot_unbound SUBTAG(fulltag_imm, 10)
+#define slot_unbound_marker slot_unbound
+#define subtag_illegal SUBTAG(fulltag_imm,11)
+#define illegal_marker subtag_illegal
+#define subtag_forward_marker SUBTAG(fulltag_imm,28)
+#define subtag_reserved_frame  SUBTAG(fulltag_imm,29)
+#define reserved_frame_marker subtag_reserved_frame
+#define subtag_no_thread_local_binding SUBTAG(fulltag_imm,30)
+#define no_thread_local_binding_marker subtag_no_thread_local_binding
+#define subtag_function_boundary_marker SUBTAG(fulltag_imm,31)
+#define function_boundary_marker subtag_function_boundary_marker
+
+typedef struct cons {
+    LispObj cdr;
+    LispObj car;
+} cons;
+
+typedef struct lispsymbol {
+    LispObj header;
+    LispObj pname;
+    LispObj vcell;
+    LispObj fcell;
+    LispObj package_predicate;
+    LispObj flags;
+    LispObj plist;
+    LispObj binding_index;
+} lispsymbol;
+
+typedef struct ratio {
+    LispObj header;
+    LispObj numer;
+    LispObj denom;
+} ratio;
+
+typedef struct double_float {
+    LispObj header;
+    LispObj pad;
+    LispObj value_low;
+    LispObj value_high;
+} double_float;
+
+typedef struct single_float {
+    LispObj header;
+    LispObj value;
+} single_float;
+
+typedef struct macptr {
+    LispObj header;
+    LispObj address;
+    LispObj class;
+    LispObj type;
+} macptr;
+
+typedef struct xmacptr {
+    LispObj header;
+    LispObj address;
+    LispObj class;
+    LispObj type;
+    LispObj flags;
+    LispObj link;
+} xmacptr;
+
+typedef struct special_binding {
+    struct special_binding *link;
+    struct lispsymbol *sym;
+    LispObj value;
+} special_binding;
+
+typedef struct lisp_frame {
+    struct lisp_frame *backlink;
+    LispObj tra;
+    LispObj xtra;		/* if tra is nvalretn */
+} lisp_frame;
+
+typedef struct exception_callback_frame {
+    struct lisp_frame *backlink;
+    LispObj tra;		/* ALWAYS 0 FOR AN XCF */
+    LispObj nominal_function;   /* the current function at the time of the exception */
+    LispObj relative_pc;        /* Boxed byte offset within actual function or absolute address */
+    LispObj containing_uvector;	/* the uvector that contains the relative PC or NIL */
+    LispObj xp;			/* exception context */
+    LispObj ra0;		/* value of ra0 from context */
+    LispObj foreign_sp;		/* foreign sp at the time that exception occurred */
+    LispObj prev_xframe;	/* so %apply-in-frame can unwind it */
+} xcf;
+
+/* The GC (at least) needs to know what a
+   package looks like, so that it can do GCTWA. */
+typedef struct package {
+    LispObj header;
+    LispObj itab; 		/* itab and etab look like (vector (fixnum . fixnum) */
+    LispObj etab;
+    LispObj used;
+    LispObj used_by;
+    LispObj names;
+    LispObj shadowed;
+} package;
+
+typedef struct catch_frame {
+    LispObj header;
+    LispObj catch_tag;
+    LispObj link;
+    LispObj mvflag;
+    LispObj esp;
+    LispObj ebp;
+    LispObj foreign_sp;
+    LispObj db_link;
+    LispObj xframe;
+    LispObj pc;
+} catch_frame;
+
+#define catch_frame_element_count ((sizeof(catch_frame)/sizeof(LispObj))-1)
+#define catch_frame_header make_header(subtag_catch_frame,catch_frame_element_count)
+
+/* 
+   All exception frames in a thread are linked together 
+ */
+typedef struct xframe_list {
+  ExceptionInformation *curr;
+  natural node_regs_mask;
+  struct xframe_list *prev;
+} xframe_list;
+
+#define fixnum_bitmask(n)  (1<<((n)+fixnumshift))
+
+/* 
+  The GC (at least) needs to know about hash-table-vectors and their flag bits.
+*/
+
+typedef struct hash_table_vector_header {
+  LispObj header;
+  LispObj link;                 /* If weak */
+  LispObj flags;                /* a fixnum; see below */
+  LispObj gc_count;             /* gc-count kernel global */
+  LispObj free_alist;           /* preallocated conses for finalization_alist */
+  LispObj finalization_alist;   /* key/value alist for finalization */
+  LispObj weak_deletions_count; /* incremented when GC deletes weak pair */
+  LispObj hash;                 /* backpointer to hash-table */
+  LispObj deleted_count;        /* number of deleted entries [not maintained if lock-free] */
+  LispObj count;                /* number of valid entries [not maintained if lock-free] */
+  LispObj cache_idx;            /* index of last cached pair */
+  LispObj cache_key;            /* value of last cached key */
+  LispObj cache_value;          /* last cached value */
+  LispObj size;                 /* number of entries in table */
+  LispObj size_reciprocal;      /* shifted reciprocal of size */
+} hash_table_vector_header;
+
+/*
+  Bits (masks) in hash_table_vector.flags:
+*/
+
+/* GC should track keys when addresses change */ 
+#define nhash_track_keys_mask fixnum_bitmask(28) 
+
+/* GC should set when nhash_track_keys_bit & addresses change */
+#define nhash_key_moved_mask  fixnum_bitmask(27) 
+
+/* weak on key or value (need new "weak both" encoding.) */
+#define nhash_weak_mask       fixnum_bitmask(12)
+
+/* weak on value */
+#define nhash_weak_value_mask fixnum_bitmask(11)
+
+/* finalizable */
+#define nhash_finalizable_mask fixnum_bitmask(10)
+
+/* keys frozen, i.e. don't clobber keys, only values */
+#define nhash_keys_frozen_mask fixnum_bitmask(9)
+
+/* Lfun bits */
+
+#define lfbits_nonnullenv_mask fixnum_bitmask(0)
+#define lfbits_keys_mask fixnum_bitmask(1)
+#define lfbits_restv_mask fixnum_bitmask(7)
+#define lfbits_optinit_mask fixnum_bitmask(14)
+#define lfbits_rest_mask fixnum_bitmask(15)
+#define lfbits_aok_mask fixnum_bitmask(16)
+#define lfbits_lap_mask fixnum_bitmask(23)
+#define lfbits_trampoline_mask fixnum_bitmask(24)
+#define lfbits_evaluated_mask fixnum_bitmask(25)
+#define lfbits_cm_mask fixnum_bitmask(26)         /* combined_method */
+#define lfbits_nextmeth_mask fixnum_bitmask(26)   /* or call_next_method with method_mask */
+#define lfbits_gfn_mask fixnum_bitmask(27)        /* generic_function */
+#define lfbits_nextmeth_with_args_mask fixnum_bitmask(27)   /* or call_next_method_with_args with method_mask */
+#define lfbits_method_mask fixnum_bitmask(28)     /* method function */
+/* PPC only but want it defined for xcompile */
+#define lfbits_noname_mask fixnum_bitmask(29)
+
+
+/* Creole */
+
+#define doh_quantum 400
+#define doh_block_slots ((doh_quantum >> 2) - 3)
+
+typedef struct doh_block {
+  struct doh_block *link;
+  unsigned size;
+  unsigned free;
+  LispObj data[doh_block_slots];
+} doh_block, *doh_block_ptr;
+
+#define population_weak_list (0<<fixnum_shift)
+#define population_weak_alist (1<<fixnum_shift)
+#define population_termination_bit (16+fixnum_shift)
+#define population_type_mask ((1<<population_termination_bit)-1)
+
+#define gc_retain_pages_bit fixnum_bitmask(0)
+#define gc_integrity_check_bit fixnum_bitmask(2)
+#define egc_verbose_bit fixnum_bitmask(3)
+#define gc_verbose_bit fixnum_bitmask(4)
+#define gc_allow_stack_overflows_bit fixnum_bitmask(5)
+#define gc_postgc_pending fixnum_bitmask(26)
+
+#include "lisp-errors.h"
+
+#ifdef DARWIN
+#include <architecture/i386/sel.h>
+#else
+typedef unsigned short sel_t;   /* for now */
+#endif
+
+#define TCR_BIAS 0
+
+/*
+ * bits correspond to reg encoding used in instructions
+ *   7   6   5   4   3   2   1   0
+ *  edi esi ebp esp ebx edx ecx eax
+ */
+
+#define X8632_DEFAULT_NODE_REGS_MASK 0xce
+
+typedef struct tcr {
+  struct tcr *next;
+  struct tcr *prev;
+  natural node_regs_mask; /* bit set means correspnding reg contains node */
+  struct tcr *linear;
+  /* this spill area must be 16-byte aligned */
+  LispObj save0;		/* spill area for node registers */
+  LispObj save1;
+  LispObj save2;
+  LispObj save3;
+  LispObj *save_fp;		/* EBP when in foreign code */
+  u32_t lisp_mxcsr;
+  u32_t foreign_mxcsr;
+  special_binding *db_link;     /* special binding chain head */
+  LispObj catch_top;            /* top catch frame */
+  LispObj *save_vsp;		  /* VSP when in foreign code */
+  LispObj *save_tsp;		  /* TSP when in foreign code */
+  LispObj *foreign_sp;
+  struct area *cs_area;		/* cstack area pointer */
+  struct area *vs_area;		/* vstack area pointer */
+  struct area *ts_area;		/* tstack area pointer */
+  LispObj cs_limit;			/* stack overflow limit */
+  natural bytes_allocated;
+  natural bytes_consed_high;
+  natural log2_allocation_quantum;      /* for per-thread consing */
+  signed_natural interrupt_pending;     /* pending interrupt flag */
+  xframe_list *xframe;	  /* exception-frame linked list */
+  int *errno_loc;               /* per-thread (?) errno location */
+  LispObj ffi_exception;        /* fpscr bits from ff-call */
+  LispObj osid;                 /* OS thread id */
+  signed_natural valence;	  /* odd when in foreign code */
+  signed_natural foreign_exception_status; /* non-zero -> call lisp_exit_hook */
+  void *native_thread_info;		     /* platform-dependent */
+  void *native_thread_id;	/* mach_thread_t, pid_t, etc. */
+  void *last_allocptr;
+  void *save_allocptr;
+  void *save_allocbase;
+  void *reset_completion;
+  void *activate;
+  signed_natural suspend_count;
+  ExceptionInformation *suspend_context;
+  ExceptionInformation *pending_exception_context;
+  void *suspend;                /* suspension semaphore */
+  void *resume;                 /* resumption semaphore */
+  natural flags;
+  ExceptionInformation *gc_context;
+  void *termination_semaphore;
+  signed_natural unwinding;
+  natural tlb_limit;
+  LispObj *tlb_pointer;
+  natural shutdown_count;
+  LispObj *next_tsp;
+  void *safe_ref_address;
+  sel_t ldt_selector;
+  natural scratch_mxcsr;
+  natural unboxed0;
+  natural unboxed1;
+  LispObj next_method_context; /* used in lieu of register */
+  natural save_eflags;
+  void *allocated;
+  void *pending_io_info;
+  void *io_datum;
+} TCR;
+
+#define nil_value ((0x13000 + (fulltag_cons))+(LOWMEM_BIAS))
+#define t_value ((0x13008 + (fulltag_misc))+(LOWMEM_BIAS))
+#define t_offset (t_value-nil_value)
+#define misc_header_offset -fulltag_misc
+#define misc_data_offset misc_header_offset + node_size
+
+typedef struct {
+  natural Eip;
+  natural Cs;                   /* in low 16 bits */
+  natural EFlags;
+} ia32_iret_frame;
+
+#define heap_segment_size 0x00010000
+#define log2_heap_segment_size 16
+
+#ifndef EFL_DF
+#define EFL_DF 1024
+#endif
Index: /branches/new-random/lisp-kernel/x86-constants32.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-constants32.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-constants32.s	(revision 13309)
@@ -0,0 +1,626 @@
+define([eax_l],[eax])
+define([ecx_l],[ecx])
+define([edx_l],[edx])
+define([ebx_l],[ebx])
+define([esi_l],[esi])
+define([edi_l],[edi])
+
+define([eax_b],[al])
+define([ecx_b],[cl])
+define([edx_b],[dl])
+define([ebx_b],[bl])
+
+define([imm0],[eax])
+	define([imm0_l],[eax])
+	define([imm0_w],[ax])
+	define([imm0_b],[al])
+	define([imm0_bh],[ah])
+	define([Rimm0],[0])
+
+define([temp0],[ecx])
+	define([temp0_l],[ecx])
+	define([temp0_w],[cx])
+	define([temp0_b],[cl])
+	define([temp0_bh],[ch])
+	define([Rtemp0],[1])
+
+define([temp1],[edx])
+	define([temp1_l],[edx])
+	define([temp1_w],[dx])
+	define([temp1_b],[dl])
+	define([temp1_bh],[dh])
+	define([Rtemp1],[2])
+
+define([arg_z],[ebx])
+	define([arg_z_l],[ebx])
+	define([arg_z_w],[bx])
+	define([arg_z_b],[bl])
+	define([arg_z_bh],[bh])
+	define([Rarg_z],[3])
+
+define([arg_y],[esi])
+	define([Rarg_y],[6])
+
+define([fn],[edi])
+	define([Rfn],[7])
+
+define([rcontext_reg],[fs])
+	
+        ifdef([WINDOWS],[
+undefine([rcontext_reg])        
+define([rcontext_reg],[es])
+        ])
+                
+define([rcontext],[%rcontext_reg:$1])
+
+define([fname],[temp0])
+define([allocptr],[temp0])
+
+define([nargs],[temp1])
+define([nargs_w],[temp1_w])
+
+define([ra0],[temp0])
+define([xfn],[temp1])
+
+define([allocptr],[temp0])
+define([stack_temp],[mm7])
+
+define([fp0],[xmm0])		
+define([fp1],[xmm1])		
+define([fp2],[xmm2])		
+define([fp3],[xmm3])		
+define([fp4],[xmm4])		
+define([fp5],[xmm5])		
+define([fp6],[xmm6])		
+define([fp7],[xmm7])		
+define([fpzero],[fp7])
+
+nbits_in_word = 32
+nbits_in_byte = 8
+ntagbits = 3
+nlisptagbits = 2
+nfixnumtagbits = 2
+num_subtag_bits = 8
+subtag_shift = num_subtag_bits
+fixnumshift = 2
+fixnum_shift = 2
+fulltagmask = 7
+tagmask = 3
+fixnummask = 3
+ncharcodebits = 8
+charcode_shift = 8
+word_shift = 2
+node_size = 4
+dnode_size = 8
+dnode_align_bits = 3
+dnode_shift = dnode_align_bits        
+bitmap_shift = 5
+
+fixnumone = (1<<fixnumshift)
+fixnum_one = fixnumone
+fixnum1 = fixnumone
+
+nargregs = 2
+
+tag_fixnum = 0
+tag_list = 1
+tag_misc = 2
+tag_imm = 3
+
+fulltag_even_fixnum = 0
+fulltag_cons = 1
+fulltag_nodeheader = 2
+fulltag_imm = 3
+fulltag_odd_fixnum = 4
+fulltag_tra = 5
+fulltag_misc = 6
+fulltag_immheader = 7
+
+define([define_subtag],[subtag_$1 = ($2 | ($3 << ntagbits))])
+define([define_imm_subtag],[define_subtag($1,fulltag_immheader,$2)])
+define([define_node_subtag],[define_subtag($1,fulltag_nodeheader,$2)])
+
+define_imm_subtag(bignum,0)
+min_numeric_subtag = subtag_bignum
+define_node_subtag(ratio,1)
+max_rational_subtag = subtag_ratio
+define_imm_subtag(single_float,1)
+define_imm_subtag(double_float,2)
+min_float_subtag = subtag_single_float
+max_float_subtag = subtag_double_float
+max_real_subtag = subtag_double_float
+define_node_subtag(complex,3)
+max_numeric_subtag = subtag_complex
+
+define_imm_subtag(bit_vector,31)
+define_imm_subtag(double_float_vector,30)
+define_imm_subtag(s16_vector,29)
+define_imm_subtag(u16_vector,28)
+min_16_bit_ivector_subtag = subtag_u16_vector
+max_16_bit_ivector_subtag = subtag_s16_vector
+define_imm_subtag(s8_vector,26)
+define_imm_subtag(u8_vector,25)
+min_8_bit_ivector_subtag = subtag_u8_vector
+max_8_bit_ivector_subtag = fulltag_immheader|(27<<ntagbits)
+define_imm_subtag(simple_base_string,24)
+define_imm_subtag(fixnum_vector,23)
+define_imm_subtag(s32_vector,22)
+define_imm_subtag(u32_vector,21)
+define_imm_subtag(single_float_vector,20)
+max_32_bit_ivector_subtag = fulltag_immheader|(24<<ntagbits)
+min_cl_ivector_subtag = subtag_single_float_vector
+
+define_node_subtag(arrayH,19)
+define_node_subtag(vectorH,20)
+define_node_subtag(simple_vector,21)
+min_vector_subtag = subtag_vectorH
+min_array_subtag = subtag_arrayH
+
+define_imm_subtag(macptr,3)
+min_non_numeric_imm_subtag = subtag_macptr
+define_imm_subtag(dead_macptr,4)
+define_imm_subtag(xcode_vector,7)
+
+define_subtag(unbound,fulltag_imm,6)
+unbound_marker = subtag_unbound
+undefined = unbound_marker
+define_subtag(character,fulltag_imm,9)
+define_subtag(slot_unbound,fulltag_imm,10)
+slot_unbound_marker = subtag_slot_unbound
+define_subtag(illegal,fulltag_imm,11)
+illegal = subtag_illegal
+define_subtag(reserved_frame,fulltag_imm,29)
+reserved_frame_marker = subtag_reserved_frame
+define_subtag(no_thread_local_binding,fulltag_imm,30)
+no_thread_local_binding_marker = subtag_no_thread_local_binding
+define_subtag(function_boundary_marker,fulltag_imm,31)
+function_boundary_marker = subtag_function_boundary_marker
+
+max_non_array_imm_subtag = (18<<ntagbits)|fulltag_immheader
+
+define_node_subtag(catch_frame,4)
+define_node_subtag(function,5)
+define_node_subtag(basic_stream,6)
+define_node_subtag(symbol,7)
+define_node_subtag(lock,8)
+define_node_subtag(hash_vector,9)
+define_node_subtag(pool,10)
+define_node_subtag(weak,11)
+define_node_subtag(package,12)
+define_node_subtag(slot_vector,13)
+define_node_subtag(instance,14)
+define_node_subtag(struct,15)
+define_node_subtag(istruct,16)
+define_node_subtag(value_cell,17)
+define_node_subtag(xfunction,18)
+
+max_non_array_node_subtag = (18<<ntagbits)|fulltag_immheader
+
+misc_header_offset = -fulltag_misc
+misc_subtag_offset = misc_header_offset
+misc_data_offset = misc_header_offset+node_size
+misc_dfloat_offset = misc_header_offset+8
+
+nil_value = ((0x13000 + fulltag_cons)+(LOWMEM_BIAS))
+t_value = ((0x13008 + fulltag_misc)+(LOWMEM_BIAS))
+t_offset = (t_value-nil_value)
+misc_bias = fulltag_misc
+cons_bias = fulltag_cons
+
+	_struct(cons,-cons_bias)
+         _node(cdr)
+         _node(car)
+        _ends
+
+        _structf(ratio)
+         _node(numer)
+         _node(denom)
+        _endstructf
+
+        _structf(single_float)
+         _word(value)
+        _endstructf
+
+        _structf(double_float)
+         _word(pad)
+         _dword(value)
+        _endstructf
+
+	_structf(macptr)
+         _node(address)
+         _node(domain)
+         _node(type)
+        _endstructf
+
+	_structf(catch_frame)
+	 _node(catch_tag)  /* #<unbound> -> unwind-protect, else catch */
+	 _node(link)	   /* backpointer to previous catch frame */
+	 _node(mvflag)     /* 0 if single-valued catch, fixnum 1 otherwise */
+	 _node(esp)	   /* saved lisp esp */
+	 _node(ebp)	   /* saved lisp ebp */
+	 _node(foreign_sp) /* necessary? */
+	 _node(db_link)	   /* head of special-binding chain */
+	 _node(xframe)	   /* exception frame chain */
+	 _node(pc)	   /* TRA of catch exit or cleanup form */
+	_endstructf
+
+	_struct(_function,-misc_bias)
+         _node(header)
+         _node(codevector)
+        _ends
+
+        _struct(tsp_frame,0)
+         _node(backlink)
+         _node(save_ebp)
+         _struct_label(fixed_overhead)
+         _struct_label(data_offset)
+        _ends
+
+	_struct(csp_frame,0)
+         _node(backlink)
+         _node(save_ebp)
+         _struct_label(fixed_overhead)
+         _struct_label(data_offset)
+        _ends
+
+        _structf(symbol)
+         _node(pname)
+         _node(vcell)
+         _node(fcell)
+         _node(package_predicate)
+         _node(flags)
+         _node(plist)
+         _node(binding_index)
+        _endstructf
+
+	_structf(vectorH)
+	 _node(logsize)
+	 _node(physsize)
+	 _node(data_vector)
+	 _node(displacement)
+	 _node(flags)
+	_endstructf	
+
+	_structf(arrayH)
+	 _node(rank)
+	 _node(physsize)
+	 _node(data_vector)
+	 _node(displacement)
+	 _node(flags)
+	 _struct_label(dim0)        
+	_endstructf	
+
+	_struct(lisp_frame,0)
+	 _node(backlink) 
+	 _node(savera0)	
+	_ends
+
+	_struct(vector,-fulltag_misc)
+	 _node(header)
+	 _struct_label(data)
+	_ends
+
+        _struct(binding,0)
+         _node(link)
+         _node(sym)
+         _node(val)
+        _ends
+
+symbol_extra = symbol.size-fulltag_misc
+
+	_struct(nrs,(0x13008+(LOWMEM_BIAS)))
+	 _struct_pad(fulltag_misc)
+	 _struct_label(tsym)
+	 _struct_pad(symbol_extra)	/* t */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(nilsym)
+         _struct_pad(symbol_extra)      /* nil */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(errdisp)
+         _struct_pad(symbol_extra)      /* %err-disp */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(cmain)
+         _struct_pad(symbol_extra)      /* cmain */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(eval)
+         _struct_pad(symbol_extra)      /* eval */
+ 
+         _struct_pad(fulltag_misc)
+         _struct_label(appevalfn)
+         _struct_pad(symbol_extra)      /* apply-evaluated-function */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(error)
+         _struct_pad(symbol_extra)      /* error */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(defun)
+         _struct_pad(symbol_extra)      /* %defun */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(defvar)
+         _struct_pad(symbol_extra)      /* %defvar */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(defconstant)
+         _struct_pad(symbol_extra)      /* %defconstant */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(macrosym)
+         _struct_pad(symbol_extra)      /* %macro */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(kernelrestart)
+         _struct_pad(symbol_extra)      /* %kernel-restart */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(package)
+         _struct_pad(symbol_extra)      /* *package* */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(total_bytes_freed)
+         _struct_pad(symbol_extra)	/* *total-bytes-freed* */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(kallowotherkeys)
+         _struct_pad(symbol_extra)      /* allow-other-keys */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(toplcatch)
+         _struct_pad(symbol_extra)      /* %toplevel-catch% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(toplfunc)
+         _struct_pad(symbol_extra)      /* %toplevel-function% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(callbacks)
+         _struct_pad(symbol_extra)      /* %pascal-functions% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(allmeteredfuns)
+         _struct_pad(symbol_extra)      /* *all-metered-functions* */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(total_gc_microseconds)
+         _struct_pad(symbol_extra)  	/* *total-gc-microseconds* */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(builtin_functions)
+         _struct_pad(symbol_extra)      /* %builtin-functions% */
+	
+         _struct_pad(fulltag_misc)
+         _struct_label(udf)
+         _struct_pad(symbol_extra)      /* %unbound-function% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(init_misc)
+         _struct_pad(symbol_extra)      /* %init-misc */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(macro_code)
+         _struct_pad(symbol_extra)      /* %macro-code% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(closure_code)
+         _struct_pad(symbol_extra)      /* %closure-code% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(new_gcable_ptr)
+         _struct_pad(symbol_extra)	/* %new-gcable-ptr */
+        
+         _struct_pad(fulltag_misc)
+         _struct_label(gc_event_status_bits)
+         _struct_pad(symbol_extra)      /* *gc-event-status-bits* */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(post_gc_hook)
+         _struct_pad(symbol_extra)      /* *post-gc-hook* */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(handlers)
+         _struct_pad(symbol_extra)      /* %handlers% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(all_packages)
+         _struct_pad(symbol_extra)      /* %all-packages% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(keyword_package)
+         _struct_pad(symbol_extra)      /* *keyword-package* */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(finalization_alist)
+         _struct_pad(symbol_extra)      /* %finalization-alist% */
+
+         _struct_pad(fulltag_misc)
+         _struct_label(foreign_thread_control)
+         _struct_pad(symbol_extra)      /* %foreign-thread-control */
+
+        _ends
+
+define([def_header],[$1 = ($2<<num_subtag_bits)|$3])
+
+def_header(single_float_header,single_float.element_count,subtag_single_float)
+def_header(double_float_header,double_float.element_count,subtag_double_float)
+def_header(one_digit_bignum_header,1,subtag_bignum)
+def_header(two_digit_bignum_header,2,subtag_bignum)
+def_header(three_digit_bignum_header,3,subtag_bignum)
+def_header(symbol_header,symbol.element_count,subtag_symbol)
+def_header(value_cell_header,1,subtag_value_cell)
+def_header(macptr_header,macptr.element_count,subtag_macptr)
+def_header(vectorH_header,vectorH.element_count,subtag_vectorH)
+
+	include(errors.s)
+
+/* Symbol bits that we care about */
+sym_vbit_bound = (0+fixnum_shift)
+sym_vbit_bound_mask = (1<<sym_vbit_bound)
+sym_vbit_const = (1+fixnum_shift)
+sym_vbit_const_mask = (1<<sym_vbit_const)
+
+        _struct(area,0)
+         _node(pred) 
+         _node(succ) 
+         _node(low) 
+         _node(high) 
+         _node(active) 
+         _node(softlimit) 
+         _node(hardlimit) 
+         _node(code) 
+         _node(markbits) 
+         _node(ndwords) 
+         _node(older) 
+         _node(younger) 
+         _node(h) 
+         _node(sofprot) 
+         _node(hardprot) 
+         _node(owner) 
+         _node(refbits) 
+         _node(nextref) 
+        _ends
+
+TCR_BIAS = 0
+                
+/*  Thread context record.  */
+
+        _struct(tcr,TCR_BIAS)
+         _node(next)            /* in doubly-linked list */
+         _node(prev)            /* in doubly-linked list */
+         _word(node_regs_mask)
+         _node(linear)          /* our linear (non-segment-based) address. */
+	 _node(save0)		/* spill area for node registers (16-byte aligned ) */
+	 _node(save1)
+	 _node(save2)
+	 _node(save3)
+         _node(save_ebp)        /* lisp EBP when in foreign code */
+         _word(lisp_mxcsr)
+         _word(foreign_mxcsr)   
+         _node(db_link)         /* special binding chain head */
+         _node(catch_top)       /* top catch frame */
+         _node(save_vsp)        /* VSP when in foreign code */
+         _node(save_tsp)        /* TSP when in foreign code */
+         _node(foreign_sp)      /* Saved foreign SP when in lisp code */
+         _node(cs_area)         /* cstack area pointer */
+         _node(vs_area)         /* vstack area pointer */
+         _node(ts_area)         /* tstack area pointer */
+         _node(cs_limit)        /* cstack overflow limit */
+         _word(bytes_allocated)
+         _word(bytes_consed_high)
+         _node(log2_allocation_quantum)
+         _node(interrupt_pending)
+         _node(xframe)          /* per-thread exception frame list */
+         _node(errno_loc)       /* per-thread  errno location */
+         _node(ffi_exception)   /* mxcsr exception bits from ff-call */
+         _node(osid)            /* OS thread id */
+         _node(valence)         /* odd when in foreign code */
+         _node(foreign_exception_status)
+         _node(native_thread_info)
+         _node(native_thread_id)
+         _node(last_allocptr)
+         _node(save_allocptr)
+         _node(save_allocbase)
+         _node(reset_completion)
+         _node(activate)
+         _node(suspend_count)
+         _node(suspend_context)
+         _node(pending_exception_context)
+         _node(suspend)         /* semaphore for suspension notify */
+         _node(resume)          /* sempahore for resumption notify */
+         _node(flags)      
+         _node(gc_context)
+         _node(termination_semaphore)
+         _node(unwinding)
+         _node(tlb_limit)
+         _node(tlb_pointer)     /* Consider using tcr+N as tlb_pointer */
+         _node(shutdown_count)
+         _node(next_tsp)
+         _node(safe_ref_address)
+	 _word(ldt_selector)
+	 _word(scratch_mxcsr)
+	 _word(unboxed0)
+	 _word(unboxed1)
+	 _node(next_method_context)
+	 _word(save_eflags)
+         _word(allocated)
+         _word(pending_io_info)
+         _word(io_datum)
+        _ends
+
+        _struct(win32_context,0)
+	 _field(ContextFlags, 4)
+	 _field(Dr0, 4)
+	 _field(Dr1, 4)
+	 _field(Dr2, 4)
+	 _field(Dr3, 4)
+	 _field(Dr6, 4)
+	 _field(Dr7, 4)
+	 _struct_label(FloatSave)
+	 _field(ControlWord, 4);
+	 _field(StatusWord, 4)
+	 _field(TagWord, 4)
+	 _field(ErrorOffset, 4)
+	 _field(ErrorSelector, 4)
+	 _field(DataOffset, 4)
+	 _field(DataSelector, 4)
+         _field(RegisterArea, 80)
+	 _field(Cr0NpxState, 4)
+        
+	 _field(SegGs, 4)
+	 _field(SegFs, 4)
+	 _field(SegEs, 4)
+	 _field(SegDs, 4)
+	 _field(Edi, 4)
+	 _field(Esi, 4)
+	 _field(Ebx, 4)
+	 _field(Edx, 4)
+	 _field(Ecx, 4)
+	 _field(Eax, 4)
+	 _field(Ebp, 4)
+	 _field(Eip, 4)
+	 _field(SegCs, 4)
+	 _field(EFlags, 4)
+	 _field(Esp, 4)
+	 _field(SegSs, 4)
+         _struct_label(ExtendedRegisters)
+         _struct_pad(24)
+         _field(MXCSR,4)
+         _struct_pad(132) /* (- 160 28) */
+         _field(Xmm0,16)
+         _field(Xmm1,16)
+         _field(Xmm2,16)
+         _field(Xmm3,16)
+         _field(Xmm4,16)
+         _field(Xmm5,16)
+         _field(Xmm6,16)
+         _field(Xmm7,16)
+         _struct_pad(224)
+         _ends
+        
+TCR_FLAG_BIT_FOREIGN = fixnum_shift
+TCR_FLAG_BIT_AWAITING_PRESET = (fixnum_shift+1)	
+TCR_FLAG_BIT_ALT_SUSPEND = (fixnumshift+2)
+TCR_FLAG_BIT_PROPAGATE_EXCEPTION = (fixnumshift+3)
+TCR_FLAG_BIT_SUSPEND_ACK_PENDING = (fixnumshift+4)
+TCR_FLAG_BIT_PENDING_EXCEPTION = (fixnumshift+5)
+TCR_FLAG_BIT_FOREIGN_EXCEPTION = (fixnumshift+6)
+TCR_FLAG_BIT_PENDING_SUSPEND = (fixnumshift+7)
+
+target_most_positive_fixnum = 536870911
+target_most_negative_fixnum = -536870912
+call_arguments_limit = 8192
+
+lisp_globals_limit = (0x13000+(LOWMEM_BIAS))
+        
+INTERRUPT_LEVEL_BINDING_INDEX = fixnumone
+
+
+ifdef([DARWIN],[
+c_stack_16_byte_aligned = 1
+],[
+c_stack_16_byte_aligned = 0
+])                
Index: /branches/new-random/lisp-kernel/x86-constants64.h
===================================================================
--- /branches/new-random/lisp-kernel/x86-constants64.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-constants64.h	(revision 13309)
@@ -0,0 +1,551 @@
+/*
+   Copyright (C) 2005-2009 Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifdef DARWIN
+#define REG_RAX 0
+#define REG_RBX 1
+#define REG_RCX 2
+#define REG_RDX 3
+#define REG_RDI 4
+#define REG_RSI 5
+#define REG_RBP 6
+#define REG_RSP 7
+#define REG_R8 8
+#define REG_R9 9
+#define REG_R10 10
+#define REG_R11 11
+#define REG_R12 12
+#define REG_R13 13
+#define REG_R14 14
+#define REG_R15 15
+#define REG_RIP 16
+#define REG_RFL 17
+#endif
+
+#ifdef FREEBSD
+#define REG_RDI 1
+#define REG_RSI 2
+#define REG_RDX 3
+#define REG_RCX 4
+#define REG_R8 5
+#define REG_R9 6
+#define REG_RAX 7
+#define REG_RBX 8
+#define REG_RBP 9
+#define REG_R10 10
+#define REG_R11 11
+#define REG_R12 12
+#define REG_R13 13
+#define REG_R14 14
+#define REG_R15 15
+#define REG_RIP 20
+#define REG_RFL 22
+#define REG_RSP 23
+#endif
+
+#ifdef WIN_64
+/* DWORD64 indices in &(CONTEXT->Rax) */
+#define REG_RAX     0
+#define REG_RCX     1
+#define REG_RDX     2
+#define REG_RBX     3
+#define REG_RSP     4
+#define REG_RBP     5
+#define REG_RSI     6
+#define REG_RDI     7
+#define REG_R8      8
+#define REG_R9      9
+#define REG_R10     10
+#define REG_R11     11
+#define REG_R12     12
+#define REG_R13     13
+#define REG_R14     14
+#define REG_R15     15
+#define REG_RIP     16
+#endif
+
+/* Define indices of the GPRs in the mcontext component of a ucontext */
+#define Itemp0      REG_RBX
+#define Iarg_y      REG_RDI
+#define Iarg_x      REG_R8
+#define Iarg_z      REG_RSI
+#define Isave3      REG_R11
+#define Isave2      REG_R12
+#define Isave1      REG_R14
+#define Isave0      REG_R15
+#define Itemp2        REG_R10
+#define Ifn         REG_R13
+#define Irbp        REG_RBP
+#define Iimm0       REG_RAX
+#define Iimm1       REG_RDX
+#define Iimm2       REG_RCX
+#define Itemp1      REG_R9
+#define Isp         REG_RSP
+#define Iip         REG_RIP
+#if defined(LINUX) || defined(WINDOWS)
+#define Iflags      REG_EFL
+#endif
+
+#if defined(SOLARIS) || defined(FREEBSD) || defined(DARWIN)
+#define Iflags      REG_RFL
+#endif
+
+
+#define Iallocptr Itemp0
+#define Ira0 Itemp2
+#define Inargs Iimm2
+#define Ixfn Itemp1
+#define Ifp Irbp
+
+
+#define nbits_in_word 64L
+#define log2_nbits_in_word 6L
+#define nbits_in_byte 8L
+#define ntagbits 4L
+#define nlisptagbits 3L
+#define nfixnumtagbits 2L
+#define num_subtag_bits 8L
+#define fixnumshift 3L
+#define fixnum_shift 3L
+#define fulltagmask 15L
+#define tagmask	 7L
+#define fixnummask 3
+#define subtagmask ((1L<<num_subtag_bits)-1L)
+#define ncharcodebits 8L
+#define charcode_shift 8L
+#define node_size 8L
+#define node_shift 3L
+#define nargregs 3L
+
+#define tag_fixnum 0L
+#define tag_imm_0 1L		/* subtag_single_float ONLY */
+#define tag_imm_1 2L		/* subtag_character, internal markers */
+#define tag_list 3L		/* subtag_cons or NIL */
+#define tag_tra 4L		/* tagged return_address */
+#define tag_misc 5L		/* random uvector */
+#define tag_symbol 6L	        /* non-null symbol */
+#define tag_function 7L	/* function entry point */
+
+#define fulltag_even_fixnum 0L
+#define fulltag_imm_0 1L
+#define fulltag_imm_1 2L
+#define fulltag_cons 3L
+#define fulltag_tra_0 4L
+#define fulltag_nodeheader_0 5L
+#define fulltag_nodeheader_1 6L
+#define fulltag_immheader_0 7L
+#define fulltag_odd_fixnum 8L
+#define fulltag_immheader_1 9L
+#define fulltag_immheader_2 10L
+#define fulltag_nil 11L
+#define fulltag_tra_1 12L
+#define fulltag_misc 13L
+#define fulltag_symbol 14L
+#define fulltag_function 15L
+
+#define SUBTAG(tag,subtag) ((tag) | ((subtag) << ntagbits))
+#define subtag_arrayH SUBTAG(fulltag_nodeheader_0,10L)
+#define subtag_vectorH SUBTAG(fulltag_nodeheader_1,10L)
+#define subtag_simple_vector SUBTAG(fulltag_nodeheader_1,11L)
+#define min_vector_subtag subtag_vectorH	
+
+#define ivector_class_64_bit fulltag_immheader_2
+#define ivector_class_32_bit fulltag_immheader_1
+#define ivector_class_other_bit fulltag_immheader_0
+
+
+#define subtag_fixnum_vector SUBTAG(ivector_class_64_bit,12L)
+#define subtag_s64_vector SUBTAG(ivector_class_64_bit,13L)
+#define subtag_u64_vector SUBTAG(ivector_class_64_bit,14L)
+#define subtag_double_float_vector SUBTAG(ivector_class_64_bit,15L)
+
+#define subtag_simple_base_string SUBTAG(ivector_class_32_bit,12L)
+#define subtag_s32_vector SUBTAG(ivector_class_32_bit,13L)
+#define subtag_u32_vector SUBTAG(ivector_class_32_bit,14L)
+#define subtag_single_float_vector SUBTAG(ivector_class_32_bit,15L)
+
+#define subtag_s16_vector SUBTAG(ivector_class_other_bit,10L)
+#define subtag_u16_vector SUBTAG(ivector_class_other_bit,11L)
+#define subtag_s8_vector SUBTAG(ivector_class_other_bit,13L)
+#define subtag_u8_vector SUBTAG(ivector_class_other_bit,14L)
+#define subtag_bit_vector SUBTAG(ivector_class_other_bit,15L)
+/* min_8_bit_ivector_subtag is the old 8-bit simple_base_string */
+#define min_8_bit_ivector_subtag SUBTAG(ivector_class_other_bit,12L)
+
+/* There's some room for expansion in non-array ivector space. */
+#define subtag_macptr SUBTAG(ivector_class_64_bit,1)
+#define subtag_dead_macptr SUBTAG(ivector_class_64_bit,2)
+#define subtag_bignum SUBTAG(ivector_class_32_bit,0)
+#define subtag_double_float SUBTAG(ivector_class_32_bit,1)
+#define subtag_xcode_vector SUBTAG(ivector_class_32_bit,2)
+
+/* Note the difference between (e.g) fulltag_function - which
+   defines what the low 4 bytes of a function pointer look like -
+   and subtag_function - which describes what the subtag byte
+   in a function header looks like.  (Likewise for fulltag_symbol
+   and subtag_symbol)
+*/		
+
+#define subtag_symbol SUBTAG(fulltag_nodeheader_0,1)
+#define subtag_catch_frame SUBTAG(fulltag_nodeheader_0,2)
+#define subtag_hash_vector SUBTAG(fulltag_nodeheader_0,3)
+#define subtag_pool SUBTAG(fulltag_nodeheader_0,4)
+#define subtag_weak SUBTAG(fulltag_nodeheader_0,5)
+#define subtag_package SUBTAG(fulltag_nodeheader_0,6)
+#define subtag_slot_vector SUBTAG(fulltag_nodeheader_0,7)
+#define subtag_basic_stream SUBTAG(fulltag_nodeheader_0,8)
+#define subtag_function SUBTAG(fulltag_nodeheader_0,9)
+
+#define subtag_ratio SUBTAG(fulltag_nodeheader_1,1)
+#define subtag_complex SUBTAG(fulltag_nodeheader_1,2)
+#define subtag_struct SUBTAG(fulltag_nodeheader_1,3)
+#define subtag_istruct SUBTAG(fulltag_nodeheader_1,4)
+#define subtag_value_cell SUBTAG(fulltag_nodeheader_1,5)
+#define subtag_xfunction SUBTAG(fulltag_nodeheader_1,6)
+#define subtag_lock SUBTAG(fulltag_nodeheader_1,7)
+#define subtag_instance SUBTAG(fulltag_nodeheader_1,8)
+
+
+
+#define nil_value ((0x13000+fulltag_nil)+(LOWMEM_BIAS))
+#define t_value ((0x13020+fulltag_symbol)+(LOWMEM_BIAS))
+#define misc_bias fulltag_misc
+#define cons_bias fulltag_cons
+
+	
+#define misc_header_offset -fulltag_misc
+#define misc_subtag_offset misc_header_offset       /* low byte of header */
+#define misc_data_offset misc_header_offset+node_size	/* first word of data */
+#define misc_dfloat_offset misc_header_offset		/* double-floats are doubleword-aligned */
+
+#define subtag_single_float SUBTAG(fulltag_imm_0,0)
+#define subtag_character SUBTAG(fulltag_imm_1,0)
+
+#define subtag_unbound SUBTAG(fulltag_imm_1,1)
+#define unbound_marker subtag_unbound
+#define undefined unbound_marker
+#define unbound unbound_marker
+#define subtag_slot_unbound SUBTAG(fulltag_imm_1,2)
+#define slot_unbound_marker subtag_slot_unbound
+#define slot_unbound slot_unbound_marker
+#define subtag_illegal SUBTAG(fulltag_imm_1,3)
+#define illegal_marker subtag_illegal
+#define subtag_no_thread_local_binding SUBTAG(fulltag_imm_1,4)
+#define no_thread_local_binding_marker subtag_no_thread_local_binding
+#define subtag_reserved_frame  SUBTAG(fulltag_imm_1,5)
+#define reserved_frame_marker subtag_reserved_frame
+#define subtag_forward_marker SUBTAG(fulltag_imm_1,6)
+
+#define function_boundary_marker SUBTAG(fulltag_imm_1,15)	
+
+/* The objects themselves look something like this: */
+
+/*  Order of CAR and CDR doesn't seem to matter much - there aren't */
+/*  too many tricks to be played with predecrement/preincrement addressing. */
+/*  Keep them in the confusing MCL 3.0 order, to avoid confusion. */
+
+typedef struct cons {
+  LispObj cdr;
+  LispObj car;
+} cons;
+
+
+
+typedef struct lispsymbol {
+  LispObj header;
+  LispObj pname;
+  LispObj vcell;
+  LispObj fcell;
+  LispObj package_predicate;
+  LispObj flags;
+  LispObj plist;
+  LispObj binding_index;
+} lispsymbol;
+
+typedef struct ratio {
+  LispObj header;
+  LispObj numer;
+  LispObj denom;
+} ratio;
+
+typedef struct double_float {
+  LispObj header;
+  LispObj value;
+} double_float;
+
+
+typedef struct macptr {
+  LispObj header;
+  LispObj address;
+  LispObj class;
+  LispObj type;
+} macptr;
+
+typedef struct xmacptr {
+  LispObj header;
+  LispObj address;
+  LispObj class;
+  LispObj type;
+  LispObj flags;
+  LispObj link;
+} xmacptr;
+  
+
+
+typedef struct special_binding {
+  struct special_binding *link;
+  struct lispsymbol *sym;
+  LispObj value;
+} special_binding;
+
+typedef struct lisp_frame {
+  struct lisp_frame *backlink;
+  LispObj tra;
+  LispObj xtra;			/* if tra is nvalretn */
+} lisp_frame;
+
+/* These are created on the lisp stack by the exception callback mechanism,
+   but nothing ever returns to them.  (At the very least, nothing -should-
+   try to return to them ...).
+*/
+typedef struct exception_callback_frame {
+  struct lisp_frame *backlink;
+  LispObj tra;                  /* ALWAYS 0 FOR AN XCF */
+  LispObj nominal_function;     /* the current function at the time of the exception */
+  LispObj relative_pc;          /* Boxed byte offset within actual
+                                   function or absolute address */
+  LispObj containing_uvector;   /* the uvector that contains the relative PC or NIL */
+  LispObj xp;                   /* exception context */
+  LispObj ra0;                  /* value of ra0 from context */
+  LispObj foreign_sp;           /* foreign sp at the time that exception occurred */
+  LispObj prev_xframe;          /* so %apply-in-frame can unwind it */
+} xcf;
+
+
+/* The GC (at least) needs to know what a
+   package looks like, so that it can do GCTWA. */
+typedef struct package {
+  LispObj header;
+  LispObj itab;			/* itab and etab look like (vector (fixnum . fixnum) */
+  LispObj etab;
+  LispObj used;
+  LispObj used_by;
+  LispObj names;
+  LispObj shadowed;
+} package;
+
+/*
+  The GC also needs to know what a catch_frame looks like.
+*/
+
+typedef struct catch_frame {
+  LispObj header;
+  LispObj catch_tag;
+  LispObj link;
+  LispObj mvflag;
+  LispObj csp;
+  LispObj db_link;
+  LispObj regs[4];
+  LispObj xframe;
+  LispObj tsp_segment;
+} catch_frame;
+
+#define catch_frame_element_count ((sizeof(catch_frame)/sizeof(LispObj))-1)
+#define catch_frame_header make_header(subtag_catch_frame,catch_frame_element_count)
+
+
+/* 
+  All exception frames in a thread are linked together 
+  */
+typedef struct xframe_list {
+  ExceptionInformation *curr;
+  struct xframe_list *prev;
+} xframe_list;
+
+#define fixnum_bitmask(n)  (1LL<<((n)+fixnumshift))
+
+/* 
+  The GC (at least) needs to know about hash-table-vectors and their flag bits.
+*/
+
+typedef struct hash_table_vector_header {
+  LispObj header;
+  LispObj link;                 /* If weak */
+  LispObj flags;                /* a fixnum; see below */
+  LispObj gc_count;             /* gc-count kernel global */
+  LispObj free_alist;           /* preallocated conses for finalization_alist */
+  LispObj finalization_alist;   /* key/value alist for finalization */
+  LispObj weak_deletions_count; /* incremented when GC deletes weak pair */
+  LispObj hash;                 /* backpointer to hash-table */
+  LispObj deleted_count;        /* number of deleted entries [not maintained if lock-free] */
+  LispObj count;                /* number of valid entries [not maintained if lock-free] */
+  LispObj cache_idx;            /* index of last cached pair */
+  LispObj cache_key;            /* value of last cached key */
+  LispObj cache_value;          /* last cached value */
+  LispObj size;                 /* number of entries in table */
+  LispObj size_reciprocal;      /* shifted reciprocal of size */
+} hash_table_vector_header;
+
+/*
+  Bits (masks)  in hash_table_vector.flags:
+*/
+
+/* GC should track keys when addresses change */ 
+#define nhash_track_keys_mask fixnum_bitmask(28) 
+
+/* GC should set when nhash_track_keys_bit & addresses change */
+#define nhash_key_moved_mask  fixnum_bitmask(27) 
+
+/* weak on key or value (need new "weak both" encoding.) */
+#define nhash_weak_mask       fixnum_bitmask(12)
+
+/* weak on value */
+#define nhash_weak_value_mask fixnum_bitmask(11)
+
+/* finalizable */
+#define nhash_finalizable_mask fixnum_bitmask(10)
+
+/* keys frozen, i.e. don't clobber keys, only values */
+#define nhash_keys_frozen_mask fixnum_bitmask(9)
+
+/* Lfun bits */
+
+#define lfbits_nonnullenv_mask fixnum_bitmask(0)
+#define lfbits_keys_mask fixnum_bitmask(1)
+#define lfbits_restv_mask fixnum_bitmask(7)
+#define lfbits_optinit_mask fixnum_bitmask(14)
+#define lfbits_rest_mask fixnum_bitmask(15)
+#define lfbits_aok_mask fixnum_bitmask(16)
+#define lfbits_lap_mask fixnum_bitmask(23)
+#define lfbits_trampoline_mask fixnum_bitmask(24)
+#define lfbits_evaluated_mask fixnum_bitmask(25)
+#define lfbits_cm_mask fixnum_bitmask(26)         /* combined_method */
+#define lfbits_nextmeth_mask fixnum_bitmask(26)   /* or call_next_method with method_mask */
+#define lfbits_gfn_mask fixnum_bitmask(27)        /* generic_function */
+#define lfbits_nextmeth_with_args_mask fixnum_bitmask(27)   /* or call_next_method_with_args with method_mask */
+#define lfbits_method_mask fixnum_bitmask(28)     /* method function */
+/* PPC only but want it defined for xcompile */
+#define lfbits_noname_mask fixnum_bitmask(29)
+
+/*
+  known values of an "extended" (gcable) macptr's flags word:
+*/
+
+
+/* Creole */
+
+#define doh_quantum 400
+#define doh_block_slots ((doh_quantum >> 2) - 3)
+
+typedef struct doh_block {
+  struct doh_block *link;
+  unsigned size;
+  unsigned free;
+  LispObj data[doh_block_slots];
+} doh_block, *doh_block_ptr;
+
+
+#define population_weak_list (0<<fixnum_shift)
+#define population_weak_alist (1<<fixnum_shift)
+#define population_termination_bit (16+fixnum_shift)
+#define population_type_mask ((1<<population_termination_bit)-1)
+
+#define gc_retain_pages_bit fixnum_bitmask(0)
+#define gc_integrity_check_bit fixnum_bitmask(2)
+#define egc_verbose_bit fixnum_bitmask(3)
+#define gc_verbose_bit fixnum_bitmask(4)
+#define gc_allow_stack_overflows_bit fixnum_bitmask(5)
+#define gc_postgc_pending fixnum_bitmask(26)
+
+#include "lisp-errors.h"
+
+
+
+#define TCR_BIAS (0x0)
+
+typedef struct tcr {
+  struct tcr* next;
+  struct tcr* prev;
+  struct {
+    u32_t tag;
+    float f;
+  } single_float_convert;
+  struct tcr* linear;
+  LispObj *save_fp;            /* RBP when in foreign code */
+  u32_t lisp_mxcsr;
+  u32_t foreign_mxcsr;
+  special_binding* db_link;	/* special binding chain head */
+  LispObj catch_top;		/* top catch frame */
+  LispObj* save_vsp;  /* VSP when in foreign code */
+  LispObj* save_tsp;  /* TSP when in foreign code */
+  LispObj* foreign_sp;
+  struct area* cs_area; /* cstack area pointer */
+  struct area* vs_area; /* vstack area pointer */
+  struct area* ts_area; /* tstack area pointer */
+  LispObj cs_limit;		/* stack overflow limit */
+  natural bytes_allocated;
+  natural log2_allocation_quantum;      /* for per-thread consing */
+  signed_natural interrupt_pending;	/* pending interrupt flag */
+  xframe_list* xframe; /* exception-frame linked list */
+  int* errno_loc;		/* per-thread (?) errno location */
+  LispObj ffi_exception;	/* fpscr bits from ff-call */
+  LispObj osid;			/* OS thread id */
+  signed_natural valence;			/* odd when in foreign code */
+  signed_natural foreign_exception_status;	/* non-zero -> call lisp_exit_hook */
+  void* native_thread_info;	/* platform-dependent */
+  void* native_thread_id;	/* mach_thread_t, pid_t, etc. */
+  void* last_allocptr;
+  void* save_allocptr;
+  void* save_allocbase;
+  void* reset_completion;
+  void* activate;
+  signed_natural suspend_count;
+  ExceptionInformation* suspend_context;
+  ExceptionInformation* pending_exception_context;
+  void* suspend;		/* suspension semaphore */
+  void* resume;			/* resumption semaphore */
+  natural flags;
+  ExceptionInformation* gc_context;
+  void* termination_semaphore;
+  signed_natural unwinding;
+  natural tlb_limit;
+  LispObj* tlb_pointer;
+  natural shutdown_count;
+  LispObj* next_tsp;
+  void *safe_ref_address;
+  void *pending_io_info;
+  void *io_datum;
+} TCR;
+
+#define t_offset (t_value-nil_value)
+
+typedef struct {
+  natural Rip;
+  natural Cs;                   /* in low 16 bits */
+  natural Rflags;               /* in low 32 bits */
+  natural Rsp;
+  natural Ss;                   /* in low 16 bits*/
+} x64_iret_frame;
+
+/* 
+  These were previously global variables.  There are lots of implicit
+  assumptions about the size of a heap segment, so they might as well
+  be constants.
+*/
+
+#define heap_segment_size 0x00020000L
+#define log2_heap_segment_size 17L
+
Index: /branches/new-random/lisp-kernel/x86-constants64.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-constants64.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-constants64.s	(revision 13309)
@@ -0,0 +1,1048 @@
+/*   Copyright (C) 2005-2009 Clozure Associates  */
+/*   This file is part of Clozure CL.    */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public  */
+/*   License , known as the LLGPL and distributed with Clozure CL as the  */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these  */
+/*   conflict, the preamble takes precedence.    */
+ 
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."  */
+ 
+/*   The LLGPL is also available online at  */
+/*   http://opensource.franz.com/preamble.html  */
+
+
+/* Register usage.  This is certainly a little short of  */
+/* immediate registers; we can maybe use the low bits  */
+/* of mmx or xmm registers to hold immediate values and  */
+/* do some unboxed arithmetic.   */
+
+
+/*
+
+	Register usage in C calling conventions differ between
+	Darwin/Linux/FreeBSD (which use the AMD-defined ABI) and
+	Windows64 (which uses something else).  The good news is that
+	Win64 did away with the cdecl/stdcall/fastcall madness, there
+	is only one ABI left.  Here's a rundown.
+
+	AMD64^Wx86-64 ABI:
+	 * Integer and pointer function arguments passed (from left to
+	right) in RDI, RSI, RDX, RCX, R8 and R9
+	 * FP arguments are passed in XMM0..XMM7
+	 * rest is passed on stack
+	 * return value in RAX
+	 * Callee must preserve RBP, RBX, R12..R15, MXCSR control bits
+	 * On function entry, x87 mode and DF clear is assumed
+	 * [RSP]..[RSP-128] must not be touched by signal handlers
+
+	Win64 ABI:
+	 * Integer and pointers passed in RCX, RDX, R8, R9
+	 * FP passed in XMM0..XMM3
+	 * rest is passed on stack
+	 * Return value in RAX or XMM0
+	 * Caller (!) responsible for creating and cleaning stack space for
+	spilling integer registers
+	 * Callee must preserve RBP, RBX, RSI, RDI, R12..R15, XMM6..XMM15
+
+	Both want their stack pointers to be 16 byte aligned on call,
+	equivalent to 8 byte offset after call due to pushed return address.
+	
+	http://msdn2.microsoft.com/en-us/library/zthk2dkh(VS.80).aspx
+	http://www.tortall.net/projects/yasm/manual/html/objfmt-win64-exception.html
+	http://www.x86-64.org/documentation/abi.pdf
+
+
+	Lisp register usage:
+
+	Clozure CL renames the physical registers, giving them names
+	based on their usage. An overview:
+
+	imm0..imm2
+	temp0..temp2
+	save0..save3
+	arg_x, arg_y, arg_z
+	fn
+
+	On top of that, further mappings are defined:
+
+	fname, next_method_context: 	temp0
+        nargs:				imm2
+        ra0:				temp2
+        xfn:				temp1
+        allocptr:			temp0
+        stack_temp:			mm7	
+	
+	x86-64 ABI mapping:
+	
+	imm0..imm2:		RAX, RDX, RCX
+	temp0..temp2:		RBX, R9, R10
+	save0..save3:		R15, R14, R12, R11
+	arg_x, arg_y, arg_z:	R8, RDI, RSI
+        fn:			R13
+        rcontext_reg:		GS
+
+	Win64 specifics:
+        rcontext_reg:		R11
+	
+*/
+	
+
+/* Redefining these standard register names - with the same _l, _w, _b suffixes  */
+/*  used in lispy symbolic names - allows us to play Stupid M4 Tricks in macros  */
+			
+define([rax_l],[eax])
+define([rax_w],[ax])
+define([rax_b],[al])
+define([rbx_l],[ebx])
+define([rbx_w],[bx])
+define([rbx_b],[bl])
+define([rcx_l],[ecx])
+define([rcx_w],[cx])
+define([rdx_l],[edx])
+define([rdx_w],[dx])					
+define([rdx_b],[dl])							
+define([rsi_l],[esi])
+define([rsi_w],[si])				
+define([rsi_b],[sil])
+define([rdi_l],[edo])
+define([rdi_w],[di])				
+define([rdi_b],[dil])
+define([r8_l],[r8d])
+define([r8_w],[r8w])					
+define([r8_b],[r8b])							
+define([r9_l],[r9d])
+define([r9_w],[r9w])					
+define([r9_b],[r9b])							
+define([r10_l],[r10d])
+define([r10_w],[r10w])					
+define([r10_b],[r10b])							
+define([r10_l],[r11d])
+define([r11_w],[r11w])					
+define([r11_b],[r11b])							
+define([r12_l],[r12d])
+define([r12_w],[r12w])					
+define([r12_b],[r12b])							
+define([r13_l],[r13d])
+define([r13_w],[r13w])					
+define([r13_b],[r13b])							
+define([r14_l],[r14d])
+define([r14_w],[r14w])					
+define([r14_b],[r14b])							
+define([r15_l],[r15d])
+define([r15_w],[r15w])					
+define([r15_b],[r15b])							
+
+/* Registers when using Lisp calling conventions */
+	
+define([imm0],[rax]) 
+	define([imm0_l],[eax])
+	define([imm0_w],[ax])
+	define([imm0_b],[al])
+	define([Rimm0],[0])
+	
+define([temp0],[rbx])
+	define([temp0_l],[ebx])
+	define([temp0_w],[bx])
+	define([temp0_b],[bl])
+	define([Rtemp0],[3])
+
+define([imm2],[rcx])
+	define([imm2_l],[ecx])
+	define([imm2_w],[cx])
+	define([imm2_b],[cl])
+	define([Rimm2],[1])
+	
+define([imm1],[rdx])
+	define([imm1_l],[edx])
+	define([imm1_w],[dx])
+	define([imm1_b],[dl])
+	define([Rimm1],[2])
+	
+define([arg_z],[rsi])
+	define([arg_z_l],[esi])
+	define([arg_z_w],[si])
+	define([arg_z_b],[sil])
+	define([Rarg_z],[6])
+
+define([arg_y],[rdi])
+	define([arg_y_l],[edi])
+	define([arg_y_w],[di])
+	define([arg_y_b],[dil])
+	define([Rarg_y],[7])
+
+define([arg_x],[r8])
+	define([arg_x_l],[r8d])
+	define([arg_x_w],[r8w])
+	define([arg_x_b],[r8b])
+	define([Rarg_x],[8])
+
+define([temp1],[r9])
+	define([temp1_l],[r9d])
+	define([temp1_w],[r9w])
+	define([temp1_b],[r9b])
+	define([Rtemp1],[9])
+
+define([temp2],[r10])
+	define([temp2_l],[r10d])
+	define([temp2_w],[r10w])
+	define([temp2_x_b],[r10b])
+	define([Rtemp2],[10])
+	
+define([save3],[r11])		
+	define([save3_l],[r11d])
+	define([save3_w],[r11w])
+	define([save3_b],[r11b])
+	define([Rsave3],[11])
+	
+define([save2],[r12])
+	define([save2_l],[r12d])
+	define([save2_w],[r12w])
+	define([save2_b],[r12b])
+	define([Rsave2],[12])
+	
+define([fn],[r13])		/* some addressing restrictions   */
+	define([fn_l],[r13d])
+	define([fn_w],[r13w])
+	define([fn_b],[r13b])
+	define([Rfn],[13])
+	
+define([save1],[r14])
+	define([save1_l],[r14d])
+	define([save1_w],[r14w])
+	define([save1_b],[r14b])
+	define([Rsave1],[14])
+		
+define([save0],[r15])
+	define([save0_l],[r15d])
+	define([save0_w],[r15w])
+	define([save0_b],[r15b])
+	define([Rsave0],[15])	
+
+
+ifdef([TCR_IN_GPR],[
+/* We keep the TCR pointer in r11 */
+	define([rcontext_reg], r11)
+	define([rcontext],[$1(%rcontext_reg)])
+],[
+/* The TCR can be accessed relative to %gs   */
+	define([rcontext_reg],[gs])
+	define([rcontext],[%rcontext_reg:$1])
+])
+define([fname],[temp0])
+define([next_method_context],[temp0])
+define([nargs_b],[imm2_b])	
+define([nargs_w],[imm2_w])
+define([nargs_q],[imm2])
+define([nargs],[imm2_l])
+define([ra0],[temp2])        
+						
+define([xfn],[temp1])
+
+define([allocptr],[temp0])		
+define([stack_temp],[mm7])
+
+		
+define([fp0],[xmm0])		
+define([fp1],[xmm1])		
+define([fp2],[xmm2])		
+define([fp3],[xmm3])		
+define([fp4],[xmm4])		
+define([fp5],[xmm5])		
+define([fp6],[xmm6])		
+define([fp7],[xmm7])		
+define([fp8],[xmm8])		
+define([fp9],[xmm9])		
+define([fp10],[xmm10])		
+define([fp11],[xmm11])		
+define([fp12],[xmm12])		
+define([fp13],[xmm13])		
+define([fp14],[xmm14])		
+define([fp15],[xmm15])		
+define([fpzero],[fp15])
+
+/* Registers when running with native C calling conventions */
+
+define([cret],[rax]) 
+	define([cret_l],[eax])
+	define([cret_w],[ax])
+	define([cret_b],[al])
+	define([Rcret],[0])
+	
+define([ctemp0],[r10])
+	define([ctemp0_l],[r10d])
+	define([ctemp0_w],[r10w])
+	define([ctemp0_b],[r10b])
+	define([Rctemp0],[10])
+	
+define([ctemp1],[r11])		
+	define([ctemp1_l],[r11d])
+	define([ctemp1_w],[r11w])
+	define([ctemp1_b],[r11b])
+	define([Rctemp1],[11])
+	
+define([csave0],[rbx])
+	define([csave0_l],[ebx])
+	define([csave0_w],[bx])
+	define([csave0_b],[bl])
+	define([Rcsave0],[3])
+
+define([csave1],[r12])
+	define([csave1_l],[r12d])
+	define([csave1_w],[r12w])
+	define([csave1_b],[r12b])
+	define([Rcsave1],[12])
+	
+define([csave2],[r13])
+	define([csave2_l],[r13d])
+	define([csave2_w],[r13w])
+	define([csave2_b],[r13b])
+	define([Rcsave2],[13])
+	
+define([csave3],[r14])
+	define([csave3_l],[r14d])
+	define([csave3_w],[r14w])
+	define([csave3_b],[r14b])
+	define([Rcsave3],[14])
+		
+define([csave4],[r15])
+	define([csave4_l],[r15d])
+	define([csave4_w],[r15w])
+	define([csave4_b],[r15b])
+	define([Rcsave4],[15])	
+
+ifdef([WINDOWS],[
+
+define([carg0],[rcx])
+	define([carg0_l],[ecx])
+	define([carg0_w],[cx])
+	define([carg0_b],[cl])
+	define([Rcarg0],[1])
+	
+define([carg1],[rdx])
+	define([carg1_l],[edx])
+	define([carg1_w],[dx])
+	define([carg1_b],[dl])
+	define([Rcarg1],[2])
+	
+define([carg2],[r8])
+	define([carg2_l],[r8d])
+	define([carg2_w],[r8w])
+	define([carg2_b],[r8b])
+	define([Rcarg2],[8])
+
+define([carg3],[r9])
+	define([carg3_l],[r9d])
+	define([carg3_w],[r9w])
+	define([carg3_b],[r9b])
+	define([Rcarg3],[9])
+
+define([csave5],[rsi])
+	define([csave5_l],[esi])
+	define([csave5_w],[si])
+	define([csave5_b],[sil])
+	define([csave5_z],[6])
+
+define([csave6],[rdi])
+	define([csave6_l],[edi])
+	define([csave6_w],[di])
+	define([csave6_b],[dil])
+	define([Rcsave6],[7])
+
+],[
+	
+define([carg0],[rdi])
+	define([carg0_l],[edi])
+	define([carg0_w],[di])
+	define([carg0_b],[dil])
+	define([Rcarg0],[7])
+
+define([carg1],[rsi])
+	define([carg1_l],[esi])
+	define([carg1_w],[si])
+	define([carg1_b],[sil])
+	define([carg1_z],[6])
+
+define([carg2],[rdx])
+	define([carg2_l],[edx])
+	define([carg2_w],[dx])
+	define([carg2_b],[dl])
+	define([Rcarg2],[2])
+	
+define([carg3],[rcx])
+	define([carg3_l],[ecx])
+	define([carg3_w],[cx])
+	define([carg3_b],[cl])
+	define([Rcarg3],[1])
+	
+define([carg4],[r8])
+	define([carg4_l],[r8d])
+	define([carg4_w],[r8w])
+	define([carg4_b],[r8b])
+	define([Rcarg4],[8])
+
+define([carg5],[r9])
+	define([carg5_l],[r9d])
+	define([carg5_w],[r9w])
+	define([carg5_b],[r9b])
+	define([Rcarg5],[9])	
+])
+	
+nbits_in_word = 64
+nbits_in_byte = 8
+ntagbits = 4
+nlisptagbits = 3
+nfixnumtagbits = 3
+nlowtagbits = 2        
+num_subtag_bits = 8
+subtag_shift = num_subtag_bits	
+fixnumshift = 3
+fixnum_shift = 3
+fulltagmask = 15
+tagmask = 7
+fixnummask = 7
+ncharcodebits = 8
+charcode_shift = 8
+word_shift = 3
+node_size = 8
+dnode_size = 16
+dnode_align_bits = 4
+dnode_shift = dnode_align_bits        
+bitmap_shift = 6
+        
+fixnumone = (1<<fixnumshift)
+fixnum_one = fixnumone
+fixnum1 = fixnumone
+
+nargregs = 3
+nsaveregs = 4	
+                
+
+tag_fixnum = 0
+tag_imm_0 = 1		/* subtag_single_float ONLY   */
+tag_imm_1 = 2		/* subtag_character, internal markers   */
+tag_list = 3		/* fulltag_cons or NIL   */
+tag_tra = 4		/* tagged return_address   */
+tag_misc = 5		/* random uvector   */
+tag_symbol = 6	        /* non-null symbol   */
+tag_function = 7	/* function entry point   */
+
+tag_single_float = tag_imm_0
+		
+fulltag_even_fixnum = 0
+fulltag_imm_0 = 1		/* subtag_single_float (ONLY)   */
+fulltag_imm_1 = 2		/* subtag_character (mostly)   */
+fulltag_cons = 3
+fulltag_tra_0 = 4		/* tagged return address   */
+fulltag_nodeheader_0 = 5
+fulltag_nodeheader_1 = 6
+fulltag_immheader_0 = 7	
+fulltag_odd_fixnum = 8
+fulltag_immheader_1 = 9
+fulltag_immheader_2 = 10
+fulltag_nil = 11
+fulltag_tra_1 = 12
+fulltag_misc = 13
+fulltag_symbol = 14
+fulltag_function = 15
+
+define([define_subtag],[
+subtag_$1 = ($2 | ($3 << ntagbits))
+])
+	
+
+define_subtag(arrayH,fulltag_nodeheader_0,10)
+define_subtag(vectorH,fulltag_nodeheader_1,10)
+define_subtag(simple_vector,fulltag_nodeheader_1,11)
+min_vector_subtag = subtag_vectorH
+min_array_subtag = subtag_arrayH
+        
+	
+ivector_class_64_bit = fulltag_immheader_2
+ivector_class_32_bit = fulltag_immheader_1
+ivector_class_other_bit = fulltag_immheader_0
+
+define_subtag(fixnum_vector,ivector_class_64_bit,12)
+define_subtag(s64_vector,ivector_class_64_bit,13)
+define_subtag(u64_vector,ivector_class_64_bit,14)
+define_subtag(double_float_vector,ivector_class_64_bit,15)
+
+define_subtag(simple_base_string,ivector_class_32_bit,12)
+define_subtag(s32_vector,ivector_class_32_bit,13)
+define_subtag(u32_vector,ivector_class_32_bit,14)
+define_subtag(single_float_vector,ivector_class_32_bit,15)
+	
+define_subtag(s16_vector,ivector_class_other_bit,10)
+define_subtag(u16_vector,ivector_class_other_bit,11)
+define_subtag(s8_vector,ivector_class_other_bit,13)
+define_subtag(u8_vector,ivector_class_other_bit,14)
+define_subtag(bit_vector,ivector_class_other_bit,15)
+
+
+/* There's some room for expansion in non-array ivector space.   */
+define_subtag(macptr,ivector_class_64_bit,1)
+define_subtag(dead_macptr,ivector_class_64_bit,2)
+define_subtag(bignum,ivector_class_32_bit,1)
+define_subtag(double_float,ivector_class_32_bit,2)
+define_subtag(xcode_vector,ivector_class_32_bit,3)
+
+        
+/* Note the difference between (e.g) fulltag_function - which  */
+/* defines what the low 4 bytes of a function pointer look like -  */
+/* and subtag_function - which describes what the subtag byte  */
+/* in a function header looks like.  (Likewise for fulltag_symbol  */
+/* and subtag_symbol)  */
+		
+
+define_subtag(symbol,fulltag_nodeheader_0,1)
+define_subtag(catch_frame,fulltag_nodeheader_0,2)
+define_subtag(hash_vector,fulltag_nodeheader_0,3)
+define_subtag(pool,fulltag_nodeheader_0,4)
+define_subtag(weak,fulltag_nodeheader_0,5)
+define_subtag(package,fulltag_nodeheader_0,6)
+define_subtag(slot_vector,fulltag_nodeheader_0,7)
+define_subtag(basic_stream,fulltag_nodeheader_0,8)
+define_subtag(function,fulltag_nodeheader_0,9)
+	
+define_subtag(ratio,fulltag_nodeheader_1,1)
+define_subtag(complex,fulltag_nodeheader_1,2)
+define_subtag(struct,fulltag_nodeheader_1,3)
+define_subtag(istruct,fulltag_nodeheader_1,4)
+define_subtag(value_cell,fulltag_nodeheader_1,5)
+define_subtag(xfunction,fulltag_nodeheader_1,6)
+define_subtag(lock,fulltag_nodeheader_1,7)
+define_subtag(instance,fulltag_nodeheader_1,8)
+	
+			
+nil_value = (0x13000+fulltag_nil)
+t_value = (0x13020+fulltag_symbol)
+misc_bias = fulltag_misc
+cons_bias = fulltag_cons
+define([t_offset],(t_value-nil_value))
+	
+misc_header_offset = -fulltag_misc
+misc_data_offset = misc_header_offset+node_size /* first word of data    */
+misc_subtag_offset = misc_header_offset       /* low byte of header   */
+misc_dfloat_offset = misc_data_offset		/* double-floats are doubleword-aligned   */
+function_header_offset = -fulltag_function
+function_data_offset = function_header_offset+node_size	
+
+define_subtag(single_float,fulltag_imm_0,0)
+
+
+define_subtag(character,fulltag_imm_1,0)
+                	
+define_subtag(unbound,fulltag_imm_1,1)
+unbound_marker = subtag_unbound
+undefined = unbound_marker
+define_subtag(slot_unbound,fulltag_imm_1,2)
+slot_unbound_marker = subtag_slot_unbound
+define_subtag(illegal,fulltag_imm_1,3)
+illegal_marker = subtag_illegal
+define_subtag(no_thread_local_binding,fulltag_imm_1,4)
+no_thread_local_binding_marker = subtag_no_thread_local_binding
+define_subtag(reserved_frame,fulltag_imm_1,5)
+reserved_frame_marker = subtag_reserved_frame
+define_subtag(function_boundary_marker,fulltag_imm_1,15)                        
+
+	
+
+
+	
+/* The objects themselves look something like this:   */
+	
+/* Order of CAR and CDR doesn]t seem to matter much - there aren't   */
+/* too many tricks to be played with predecrement/preincrement addressing.   */
+/* Keep them in the confusing MCL 3.0 order, to avoid confusion.   */
+	_struct(cons,-cons_bias)
+	 _node(cdr)
+	 _node(car)
+	_ends
+	
+	_structf(ratio)
+	 _node(numer)
+	 _node(denom)
+	_endstructf
+	
+	_structf(double_float)
+	 _word(value)
+         _word(val_low)
+	_endstructf
+	
+	_structf(macptr)
+	 _node(address)
+         _node(domain)
+         _node(type)
+	_endstructf
+	
+/* Functions are of (conceptually) unlimited size.  */
+	
+	_struct(_function,-misc_bias)
+	 _node(header)
+	 _node(codevector)
+	_ends
+
+	_struct(tsp_frame,0)
+	 _node(backlink)
+	 _node(save_rbp)
+	 _struct_label(fixed_overhead)
+	 _struct_label(data_offset)
+	_ends
+
+	_struct(csp_frame,0)
+	 _node(backlink)
+	 _node(save_rbp)
+	 _struct_label(fixed_overhead)
+	 _struct_label(data_offset)
+	_ends
+        
+
+
+	_structf(symbol,-fulltag_symbol)
+	 _node(pname)
+	 _node(vcell)
+	 _node(fcell)
+	 _node(package_predicate)
+	 _node(flags)
+         _node(plist)
+         _node(binding_index)
+	_endstructf
+
+	_structf(catch_frame)
+	 _node(catch_tag)	/* #<unbound> -> unwind-protect, else catch   */
+	 _node(link)		/* backpointer to previous catch frame   */
+	 _node(mvflag)		/* 0 if single-valued catch, fixnum 1 otherwise   */
+	 _node(rsp)		/* saved lisp sp   */
+	 _node(rbp)		/* saved lisp rbp   */
+	 _node(foreign_sp)      /* necessary ?    */
+	 _node(db_link)		/* head of special-binding chain   */
+	 _node(_save3)
+	 _node(_save2)
+	 _node(_save1)
+	 _node(_save0)
+	 _node(xframe)		/* exception frame chain   */
+	 _node(pc)		/* TRA of catch exit or cleanup form   */
+	_endstructf
+
+
+	_structf(vectorH)
+	 _node(logsize)
+	 _node(physsize)
+	 _node(data_vector)
+	 _node(displacement)
+	 _node(flags)
+	_endstructf	
+
+	_structf(arrayH)
+	 _node(rank)
+	 _node(physsize)
+	 _node(data_vector)
+	 _node(displacement)
+	 _node(flags)
+	 _struct_label(dim0)        
+	_endstructf	
+        	
+        
+	_struct(c_frame,0)	/* PowerOpen ABI C stack frame   */
+	 _node(backlink)
+	 _node(crsave)
+	 _node(savelr)
+	 _field(unused, 16)
+	 _node(savetoc)
+	 _struct_label(params)
+         _node(param0)
+         _node(param1)
+         _node(param2)
+         _node(param3)
+         _node(param4)
+         _node(param5)
+         _node(param6)
+         _node(param7)
+	 _struct_label(minsiz)
+	_ends
+
+
+	_struct(eabi_c_frame,0)
+	 _word(backlink) 
+	 _word(savelr)
+	 _word(param0)
+	 _word(param1)
+	 _word(param2)
+	 _word(param3)
+	 _word(param4)
+	 _word(param5)
+	 _word(param6)
+	 _word(param7)
+	 _struct_label(minsiz)
+	_ends
+
+	/* For entry to variable-argument-list functions   */
+	/* (e.g., via callback)   */
+	_struct(varargs_eabi_c_frame,0)
+	 _word(backlink)
+	 _word(savelr)
+	 _struct_label(va_list)
+	 _word(flags)		/* gpr count byte, fpr count byte, padding   */
+	 _word(overflow_arg_area)
+	 _word(reg_save_area)
+	 _field(padding,4)
+	 _struct_label(regsave)
+	 _field(gp_save,8*4)
+	 _field(fp_save,8*8)
+	 _word(old_backlink)
+	 _word(old_savelr)
+	 _struct_label(incoming_stack_args)
+	_ends
+        	
+	_struct(lisp_frame,0)
+	 _node(backlink) 
+	 _node(savera0)	
+	_ends
+
+	_struct(vector,-fulltag_misc)
+	 _node(header)
+	 _struct_label(data)
+	_ends
+
+        _struct(binding,0)
+         _node(link)
+         _node(sym)
+         _node(val)
+        _ends
+
+
+/* Nilreg-relative globals.  Talking the assembler into doing  */
+/* something reasonable here  */
+/* is surprisingly hard.   */
+
+symbol_extra = symbol.size-fulltag_symbol
+
+	
+	_struct(nrs,0x13020)
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(tsym)
+	 _struct_pad(symbol_extra)	/* t    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(nil)
+	 _struct_pad(symbol_extra)	/* nil    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(errdisp)
+	 _struct_pad(symbol_extra)	/* %err-disp    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(cmain)
+	 _struct_pad(symbol_extra)	/* cmain    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(eval)
+	 _struct_pad(symbol_extra)	/* eval    */
+ 
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(appevalfn)
+	 _struct_pad(symbol_extra)	/* apply-evaluated-function    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(error)
+	 _struct_pad(symbol_extra)	/* error    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(defun)
+	 _struct_pad(symbol_extra)	/* %defun    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(defvar)
+	 _struct_pad(symbol_extra)	/* %defvar    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(defconstant)
+	 _struct_pad(symbol_extra)	/* %defconstant    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(macrosym)
+	 _struct_pad(symbol_extra)	/* %macro    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(kernelrestart)
+	 _struct_pad(symbol_extra)	/* %kernel-restart    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(package)
+	 _struct_pad(symbol_extra)	/* *package*    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(total_bytes_freed)		/* *total-bytes-freed*   */
+	 _struct_pad(symbol_extra)
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(kallowotherkeys)
+	 _struct_pad(symbol_extra)	/* allow-other-keys    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(toplcatch)
+	 _struct_pad(symbol_extra)	/* %toplevel-catch%    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(toplfunc)
+	 _struct_pad(symbol_extra)	/* %toplevel-function%    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(callbacks)
+	 _struct_pad(symbol_extra)	/* %pascal-functions%    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(allmeteredfuns)
+	 _struct_pad(symbol_extra)	/* *all-metered-functions*    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(total_gc_microseconds)		/* *total-gc-microseconds*   */
+	 _struct_pad(symbol_extra)
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(builtin_functions)		/* %builtin-functions%   */
+	 _struct_pad(symbol_extra)                
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(udf)
+	 _struct_pad(symbol_extra)	/* %unbound-function%    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(init_misc)
+	 _struct_pad(symbol_extra)	/* %init-misc   */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(macro_code)
+	 _struct_pad(symbol_extra)	/* %macro-code%   */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(closure_code)
+	 _struct_pad(symbol_extra)      /* %closure-code%   */
+
+       	 _struct_pad(fulltag_symbol)
+	 _struct_label(new_gcable_ptr) /* %new-gcable-ptr   */
+	 _struct_pad(symbol_extra)
+	
+       	 _struct_pad(fulltag_symbol)
+	 _struct_label(gc_event_status_bits)
+	 _struct_pad(symbol_extra)	/* *gc-event-status-bits*    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(post_gc_hook)
+	 _struct_pad(symbol_extra)	/* *post-gc-hook*    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(handlers)
+	 _struct_pad(symbol_extra)	/* %handlers%    */
+
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(all_packages)
+	 _struct_pad(symbol_extra)	/* %all-packages%    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(keyword_package)
+	 _struct_pad(symbol_extra)	/* *keyword-package*    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(finalization_alist)
+	 _struct_pad(symbol_extra)	/* %finalization-alist%    */
+
+	 _struct_pad(fulltag_symbol)
+	 _struct_label(foreign_thread_control)
+	 _struct_pad(symbol_extra)	/* %foreign-thread-control    */
+
+	_ends
+
+define([def_header],[
+$1 = ($2<<num_subtag_bits)|$3])
+
+	def_header(double_float_header,2,subtag_double_float)
+	def_header(two_digit_bignum_header,2,subtag_bignum)
+	def_header(three_digit_bignum_header,3,subtag_bignum)
+	def_header(four_digit_bignum_header,4,subtag_bignum)
+	def_header(five_digit_bignum_header,5,subtag_bignum)        
+	def_header(symbol_header,symbol.element_count,subtag_symbol)
+	def_header(value_cell_header,1,subtag_value_cell	)
+	def_header(macptr_header,macptr.element_count,subtag_macptr)
+	def_header(vectorH_header,vectorH.element_count,subtag_vectorH)
+
+	include(errors.s)
+
+/* Symbol bits that we care about  */
+	
+sym_vbit_bound = (0+fixnum_shift)
+sym_vbit_bound_mask = (1<<sym_vbit_bound)
+sym_vbit_const = (1+fixnum_shift)
+sym_vbit_const_mask = (1<<sym_vbit_const)
+
+	_struct(area,0)
+	 _node(pred) 
+	 _node(succ) 
+	 _node(low) 
+	 _node(high) 
+	 _node(active) 
+	 _node(softlimit) 
+	 _node(hardlimit) 
+	 _node(code) 
+	 _node(markbits) 
+	 _node(ndwords) 
+	 _node(older) 
+	 _node(younger) 
+	 _node(h) 
+	 _node(sofprot) 
+	 _node(hardprot) 
+	 _node(owner) 
+	 _node(refbits) 
+	 _node(nextref) 
+	_ends
+
+
+
+TCR_BIAS = 0
+		
+/*  Thread context record.  */
+
+	_struct(tcr,TCR_BIAS)
+	 _node(prev)		/* in doubly-linked list   */
+	 _node(next)		/* in doubly-linked list   */
+         _node(single_float_convert)
+	 _node(linear)		/* our linear (non-segment-based) address.   */
+         _node(save_rbp)        /* lisp RBP when in foreign code    */
+	 _word(lisp_mxcsr)
+	 _word(foreign_mxcsr)	
+	 _node(db_link)		/* special binding chain head   */
+	 _node(catch_top)	/* top catch frame   */
+	 _node(save_vsp)	/* VSP when in foreign code   */
+	 _node(save_tsp)	/* TSP when in foreign code   */
+	 _node(foreign_sp)	/* Saved foreign SP when in lisp code   */
+	 _node(cs_area)		/* cstack area pointer   */
+	 _node(vs_area)		/* vstack area pointer   */
+	 _node(ts_area)		/* tstack area pointer   */
+	 _node(cs_limit)	/* cstack overflow limit   */
+	 _word(bytes_consed_low)
+	 _word(bytes_consed_high)
+	 _node(log2_allocation_quantum)
+	 _node(interrupt_pending)
+	 _node(xframe)		/* per-thread exception frame list   */
+	 _node(errno_loc)	/* per-thread  errno location   */
+	 _node(ffi_exception)	/* mxcsr exception bits from ff-call   */
+	 _node(osid)		/* OS thread id   */
+         _node(valence)		/* odd when in foreign code 	  */
+	 _node(foreign_exception_status)
+	 _node(native_thread_info)
+	 _node(native_thread_id)
+	 _node(last_allocptr)
+	 _node(save_allocptr)
+	 _node(save_allocbase)
+	 _node(reset_completion)
+	 _node(activate)
+         _node(suspend_count)
+         _node(suspend_context)
+	 _node(pending_exception_context)
+	 _node(suspend)		/* semaphore for suspension notify   */
+	 _node(resume)		/* sempahore for resumption notify   */
+	 _node(flags)      
+	 _node(gc_context)
+         _node(termination_semaphore)
+         _node(unwinding)
+         _node(tlb_limit)
+         _node(tlb_pointer)     /* Consider using tcr+N as tlb_pointer   */
+	 _node(shutdown_count)
+         _node(next_tsp)
+         _node(safe_ref_address)
+         _node(pending_io_info)
+         _node(io_datum)
+	_ends
+
+        _struct(win64_context,0)
+         _field(P1Home, 8)
+         _field(P2Home, 8)
+         _field(P3Home, 8)
+         _field(P4Home, 8)
+         _field(P5Home, 8)
+         _field(P6Home, 8)
+         _field(ContextFlags, 4)
+         _field(MxCsr, 4)
+         _field(SegCs, 2)
+         _field(SegDs, 2)
+         _field(SegEs, 2)
+         _field(SegFs, 2)
+         _field(SegGs, 2)
+         _field(SegSs, 2)
+         _field(EFlags, 4)
+         _field(Dr0, 8)
+         _field(Dr1, 8)
+         _field(Dr2, 8)
+         _field(Dr3, 8)
+         _field(Dr6, 8)
+         _field(Dr7, 8)
+         _field(Rax, 8)
+         _field(Rcx, 8)
+         _field(Rdx, 8)
+         _field(Rbx, 8)
+         _field(Rsp, 8)
+         _field(Rbp, 8)
+         _field(Rsi, 8)
+         _field(Rdi, 8)
+         _field(R8, 8)
+         _field(R9, 8)
+         _field(R10, 8)
+         _field(R11, 8)
+         _field(R12, 8)
+         _field(R13, 8)
+         _field(R14, 8)
+         _field(R15, 8)
+         _field(Rip, 8)
+         _struct_label(fpstate)
+         _field(Header, 32)
+         _field(Legacy, 128)
+         _field(Xmm0, 16)
+         _field(Xmm1, 16)        
+         _field(Xmm2, 16)        
+         _field(Xmm3, 16)        
+         _field(Xmm4, 16)        
+         _field(Xmm5, 16)        
+         _field(Xmm6, 16)        
+         _field(Xmm7, 16)        
+         _field(Xmm8, 16)        
+         _field(Xmm9, 16)        
+         _field(Xmm10, 16)        
+         _field(Xmm11, 16)        
+         _field(Xmm12, 16)        
+         _field(Xmm13, 16)        
+         _field(Xmm14, 16)        
+         _field(Xmm15, 16)
+         _field(__pad, 96)
+         _field(VectorRegister, 416)
+         _field(VectorControl, 8)
+         _field(DebugControl, 8)
+         _field(LastBranchToRip, 8)
+         _field(LastBranchFromRip, 8)
+         _field(LastExceptionToRip, 8)
+         _field(LastExceptionFromRip, 8)
+ _ends
+
+	
+TCR_FLAG_BIT_FOREIGN = fixnum_shift
+TCR_FLAG_BIT_AWAITING_PRESET = (fixnum_shift+1)	
+TCR_FLAG_BIT_ALT_SUSPEND = (fixnumshift+2)
+TCR_FLAG_BIT_PROPAGATE_EXCEPTION = (fixnumshift+3)
+TCR_FLAG_BIT_SUSPEND_ACK_PENDING = (fixnumshift+4)
+TCR_FLAG_BIT_PENDING_EXCEPTION = (fixnumshift+5)
+TCR_FLAG_BIT_FOREIGN_EXCEPTION = (fixnumshift+6)
+TCR_FLAG_BIT_PENDING_SUSPEND = (fixnumshift+7)        
+	
+target_most_positive_fixnum = 1152921504606846975
+target_most_negative_fixnum = -1152921504606846976
+
+
+lisp_globals_limit = 0x13000
+        
+INTERRUPT_LEVEL_BINDING_INDEX = fixnumone
+
+c_stack_16_byte_aligned = 1
+        	
+		        
+                
Index: /branches/new-random/lisp-kernel/x86-exceptions.c
===================================================================
--- /branches/new-random/lisp-kernel/x86-exceptions.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-exceptions.c	(revision 13309)
@@ -0,0 +1,3813 @@
+/*
+   Copyright (C) 2005-2009 Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp-exceptions.h"
+#include "lisp_globals.h"
+#include "Threads.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#ifdef LINUX
+#include <strings.h>
+#include <sys/mman.h>
+#include <fpu_control.h>
+#include <linux/prctl.h>
+#endif
+#ifdef DARWIN
+#include <sysexits.h>
+#endif
+#ifndef WINDOWS
+#include <sys/syslog.h>
+#endif
+#ifdef WINDOWS
+#include <windows.h>
+#ifdef WIN_64
+#include <winternl.h>
+#include <ntstatus.h>
+#endif
+#ifndef EXCEPTION_WRITE_FAULT
+#define EXCEPTION_WRITE_FAULT 1
+#endif
+#endif
+
+int
+page_size = 4096;
+
+int
+log2_page_size = 12;
+
+
+void
+update_bytes_allocated(TCR* tcr, void *cur_allocptr)
+{
+  BytePtr 
+    last = (BytePtr) tcr->last_allocptr, 
+    current = (BytePtr) cur_allocptr;
+  if (last && (tcr->save_allocbase != ((void *)VOID_ALLOCPTR))) {
+    tcr->bytes_allocated += last-current;
+  }
+  tcr->last_allocptr = 0;
+}
+
+
+
+//  This doesn't GC; it returns true if it made enough room, false
+//  otherwise.
+//  If "extend" is true, it can try to extend the dynamic area to
+//  satisfy the request.
+
+
+Boolean
+new_heap_segment(ExceptionInformation *xp, natural need, Boolean extend, TCR *tcr)
+{
+  area *a;
+  natural newlimit, oldlimit;
+  natural log2_allocation_quantum = tcr->log2_allocation_quantum;
+
+  a  = active_dynamic_area;
+  oldlimit = (natural) a->active;
+  newlimit = (align_to_power_of_2(oldlimit, log2_allocation_quantum) +
+	      align_to_power_of_2(need, log2_allocation_quantum));
+  if (newlimit > (natural) (a->high)) {
+    if (extend) {
+      signed_natural inhibit = (signed_natural)(lisp_global(GC_INHIBIT_COUNT));
+      natural extend_by = inhibit ? 0 : lisp_heap_gc_threshold;
+      do {
+        if (resize_dynamic_heap(a->active, (newlimit-oldlimit)+extend_by)) {
+          break;
+        }
+        extend_by = align_to_power_of_2(extend_by>>1,log2_allocation_quantum);
+        if (extend_by < 4<<20) {
+          return false;
+        }
+      } while (1);
+    } else {
+      return false;
+    }
+  }
+  a->active = (BytePtr) newlimit;
+  tcr->last_allocptr = (void *)newlimit;
+  tcr->save_allocptr = (void *)newlimit;
+  xpGPR(xp,Iallocptr) = (LispObj) newlimit;
+  tcr->save_allocbase = (void *) oldlimit;
+
+  return true;
+}
+
+Boolean
+allocate_object(ExceptionInformation *xp,
+                natural bytes_needed, 
+                signed_natural disp_from_allocptr,
+		TCR *tcr)
+{
+  area *a = active_dynamic_area;
+
+  /* Maybe do an EGC */
+  if (a->older && lisp_global(OLDEST_EPHEMERAL)) {
+    if (((a->active)-(a->low)) >= a->threshold) {
+      gc_from_xp(xp, 0L);
+    }
+  }
+
+  /* Life is pretty simple if we can simply grab a segment
+     without extending the heap.
+  */
+  if (new_heap_segment(xp, bytes_needed, false, tcr)) {
+    xpGPR(xp, Iallocptr) -= disp_from_allocptr;
+    tcr->save_allocptr = (void *) (xpGPR(xp, Iallocptr));
+    return true;
+  }
+  
+  /* It doesn't make sense to try a full GC if the object
+     we're trying to allocate is larger than everything
+     allocated so far.
+  */
+  if ((lisp_global(HEAP_END)-lisp_global(HEAP_START)) > bytes_needed) {
+    untenure_from_area(tenured_area); /* force a full GC */
+    gc_from_xp(xp, 0L);
+  }
+  
+  /* Try again, growing the heap if necessary */
+  if (new_heap_segment(xp, bytes_needed, true, tcr)) {
+    xpGPR(xp, Iallocptr) -= disp_from_allocptr;
+    tcr->save_allocptr = (void *) (xpGPR(xp, Iallocptr));
+    return true;
+  }
+  
+  return false;
+}
+
+natural gc_deferred = 0, full_gc_deferred = 0;
+
+signed_natural
+flash_freeze(TCR *tcr, signed_natural param)
+{
+  return 0;
+}
+
+
+Boolean
+handle_gc_trap(ExceptionInformation *xp, TCR *tcr)
+{
+  LispObj selector = xpGPR(xp,Iimm0);
+#ifdef X8664
+  LispObj arg = xpGPR(xp,Iimm1);
+#else
+  LispObj arg = xpMMXreg(xp,Imm0);
+#endif
+  area *a = active_dynamic_area;
+  Boolean egc_was_enabled = (a->older != NULL);
+  
+  natural gc_previously_deferred = gc_deferred;
+
+  switch (selector) {
+  case GC_TRAP_FUNCTION_EGC_CONTROL:
+    egc_control(arg != 0, a->active);
+    xpGPR(xp,Iarg_z) = lisp_nil + (egc_was_enabled ? t_offset : 0);
+    break;
+
+  case GC_TRAP_FUNCTION_CONFIGURE_EGC:
+#ifdef X8664
+    a->threshold = unbox_fixnum(xpGPR(xp, Iarg_x));
+#else
+    a->threshold = unbox_fixnum(xpGPR(xp, Itemp0));
+#endif
+    g1_area->threshold = unbox_fixnum(xpGPR(xp, Iarg_y));
+    g2_area->threshold = unbox_fixnum(xpGPR(xp, Iarg_z));
+    xpGPR(xp,Iarg_z) = lisp_nil+t_offset;
+    break;
+
+  case GC_TRAP_FUNCTION_SET_LISP_HEAP_THRESHOLD:
+    if (((signed_natural) arg) > 0) {
+      lisp_heap_gc_threshold = 
+        align_to_power_of_2((arg-1) +
+                            (heap_segment_size - 1),
+                            log2_heap_segment_size);
+    }
+    /* fall through */
+  case GC_TRAP_FUNCTION_GET_LISP_HEAP_THRESHOLD:
+    xpGPR(xp, Iimm0) = lisp_heap_gc_threshold;
+    break;
+
+  case GC_TRAP_FUNCTION_USE_LISP_HEAP_THRESHOLD:
+    /*  Try to put the current threshold in effect.  This may
+        need to disable/reenable the EGC. */
+    untenure_from_area(tenured_area);
+    resize_dynamic_heap(a->active,lisp_heap_gc_threshold);
+    if (egc_was_enabled) {
+      if ((a->high - a->active) >= a->threshold) {
+        tenure_to_area(tenured_area);
+      }
+    }
+    xpGPR(xp, Iimm0) = lisp_heap_gc_threshold;
+    break;
+
+  case GC_TRAP_FUNCTION_ENSURE_STATIC_CONSES:
+    ensure_static_conses(xp, tcr, 32768);
+    break;
+
+  case GC_TRAP_FUNCTION_FLASH_FREEZE: /* Like freeze below, but no GC */
+    untenure_from_area(tenured_area);
+    gc_like_from_xp(xp,flash_freeze,0);
+    a->active = (BytePtr) align_to_power_of_2(a->active, log2_page_size);
+    tenured_area->static_dnodes = area_dnode(a->active, a->low);
+    if (egc_was_enabled) {
+      tenure_to_area(tenured_area);
+    }
+    xpGPR(xp, Iimm0) = tenured_area->static_dnodes << dnode_shift;
+    break;
+
+  default:
+    update_bytes_allocated(tcr, (void *) tcr->save_allocptr);
+
+    if (selector == GC_TRAP_FUNCTION_IMMEDIATE_GC) {
+      if (!full_gc_deferred) {
+        gc_from_xp(xp, 0L);
+        break;
+      }
+      /* Tried to do a full GC when gc was disabled.  That failed,
+         so try full GC now */
+      selector = GC_TRAP_FUNCTION_GC;
+    }
+    
+    if (egc_was_enabled) {
+      egc_control(false, (BytePtr) a->active);
+    }
+    gc_from_xp(xp, 0L);
+    if (gc_deferred > gc_previously_deferred) {
+      full_gc_deferred = 1;
+    } else {
+      full_gc_deferred = 0;
+    }
+    if (selector > GC_TRAP_FUNCTION_GC) {
+      if (selector & GC_TRAP_FUNCTION_IMPURIFY) {
+        impurify_from_xp(xp, 0L);
+        /*        nrs_GC_EVENT_STATUS_BITS.vcell |= gc_integrity_check_bit; */
+        lisp_global(OLDSPACE_DNODE_COUNT) = 0;
+        gc_from_xp(xp, 0L);
+      }
+      if (selector & GC_TRAP_FUNCTION_PURIFY) {
+        purify_from_xp(xp, 1);
+        lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(managed_static_area->active, managed_static_area->low);
+        gc_from_xp(xp, 0L);
+      }
+      if (selector & GC_TRAP_FUNCTION_SAVE_APPLICATION) {
+        OSErr err;
+        extern OSErr save_application(unsigned, Boolean);
+        area *vsarea = tcr->vs_area;
+
+#ifdef WINDOWS	
+        arg = _open_osfhandle(arg,0);
+#endif
+        nrs_TOPLFUNC.vcell = *((LispObj *)(vsarea->high)-1);
+        err = save_application(arg, egc_was_enabled);
+        if (err == noErr) {
+          _exit(0);
+        }
+        fatal_oserr(": save_application", err);
+      }
+      switch (selector) {
+      case GC_TRAP_FUNCTION_FREEZE:
+        a->active = (BytePtr) align_to_power_of_2(a->active, log2_page_size);
+        tenured_area->static_dnodes = area_dnode(a->active, a->low);
+        xpGPR(xp, Iimm0) = tenured_area->static_dnodes << dnode_shift;
+        break;
+      default:
+        break;
+      }
+    }
+    if (egc_was_enabled) {
+      egc_control(true, NULL);
+    }
+    break;
+  }
+  return true;
+}
+
+  
+
+
+
+void
+push_on_lisp_stack(ExceptionInformation *xp, LispObj value)
+{
+  LispObj *vsp = (LispObj *)xpGPR(xp,Isp);
+  *--vsp = value;
+  xpGPR(xp,Isp) = (LispObj)vsp;
+}
+
+
+/* Hard to know if or whether this is necessary in general.  For now,
+   do it when we get a "wrong number of arguments" trap.
+*/
+void
+finish_function_entry(ExceptionInformation *xp)
+{
+  natural nargs = xpGPR(xp,Inargs)>>fixnumshift;
+  signed_natural disp = nargs - nargregs;
+  LispObj *vsp =  (LispObj *) xpGPR(xp,Isp), ra = *vsp++;
+   
+  xpGPR(xp,Isp) = (LispObj) vsp;
+
+  if (disp > 0) {               /* implies that nargs > nargregs */
+    vsp[disp] = xpGPR(xp,Ifp);
+    vsp[disp+1] = ra;
+    xpGPR(xp,Ifp) = (LispObj)(vsp+disp);
+#ifdef X8664
+    push_on_lisp_stack(xp,xpGPR(xp,Iarg_x));
+#endif
+    push_on_lisp_stack(xp,xpGPR(xp,Iarg_y));
+    push_on_lisp_stack(xp,xpGPR(xp,Iarg_z));
+  } else {
+    push_on_lisp_stack(xp,ra);
+    push_on_lisp_stack(xp,xpGPR(xp,Ifp));
+    xpGPR(xp,Ifp) = xpGPR(xp,Isp);
+#ifdef X8664
+    if (nargs == 3) {
+      push_on_lisp_stack(xp,xpGPR(xp,Iarg_x));
+    }
+#endif
+    if (nargs >= 2) {
+      push_on_lisp_stack(xp,xpGPR(xp,Iarg_y));
+    }
+    if (nargs >= 1) {
+      push_on_lisp_stack(xp,xpGPR(xp,Iarg_z));
+    }
+  }
+}
+
+Boolean
+object_contains_pc(LispObj container, LispObj addr)
+{
+  if (fulltag_of(container) >= fulltag_misc) {
+    natural elements = header_element_count(header_of(container));
+    if ((addr >= container) &&
+        (addr < ((LispObj)&(deref(container,1+elements))))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+LispObj
+create_exception_callback_frame(ExceptionInformation *xp, TCR *tcr)
+{
+  LispObj containing_uvector = 0, 
+    relative_pc, 
+    nominal_function = lisp_nil, 
+    f, tra, tra_f = 0, abs_pc;
+
+  f = xpGPR(xp,Ifn);
+  tra = *(LispObj*)(xpGPR(xp,Isp));
+
+#ifdef X8664
+  if (tag_of(tra) == tag_tra) {
+    if ((*((unsigned short *)tra) == RECOVER_FN_FROM_RIP_WORD0) &&
+        (*((unsigned char *)(tra+2)) == RECOVER_FN_FROM_RIP_BYTE2)) {
+      int sdisp = (*(int *) (tra+3));
+      tra_f = RECOVER_FN_FROM_RIP_LENGTH+tra+sdisp;
+    }
+    if (fulltag_of(tra_f) != fulltag_function) {
+      tra_f = 0;
+    }
+  } else {
+    tra = 0;
+  }
+#endif
+#ifdef X8632
+  if (fulltag_of(tra) == fulltag_tra) {
+    if (*(unsigned char *)tra == RECOVER_FN_OPCODE) {
+      tra_f = (LispObj)*(LispObj *)(tra + 1);
+    }
+    if (tra_f && header_subtag(header_of(tra_f)) != subtag_function) {
+      tra_f = 0;
+    }
+  } else {
+    tra = 0;
+  }
+#endif
+
+  abs_pc = (LispObj)xpPC(xp);
+
+#ifdef X8664
+  if (fulltag_of(f) == fulltag_function) 
+#else
+    if (fulltag_of(f) == fulltag_misc &&
+        header_subtag(header_of(f)) == subtag_function) 
+#endif
+      {
+        nominal_function = f;
+      } else {
+      if (tra_f) {
+        nominal_function = tra_f;
+      }
+    }
+  
+  f = xpGPR(xp,Ifn);
+  if (object_contains_pc(f, abs_pc)) {
+    containing_uvector = untag(f)+fulltag_misc;
+  } else {
+    f = xpGPR(xp,Ixfn);
+    if (object_contains_pc(f, abs_pc)) {
+      containing_uvector = untag(f)+fulltag_misc;
+    } else {
+      if (tra_f) {
+        f = tra_f;
+        if (object_contains_pc(f, abs_pc)) {
+          containing_uvector = untag(f)+fulltag_misc;
+          relative_pc = (abs_pc - f) << fixnumshift;
+        }
+      }
+    }
+  }
+  if (containing_uvector) {
+    relative_pc = (abs_pc - (LispObj)&(deref(containing_uvector,1))) << fixnumshift;
+  } else {
+    containing_uvector = lisp_nil;
+    relative_pc = abs_pc << fixnumshift;
+  }
+  push_on_lisp_stack(xp,(LispObj)(tcr->xframe->prev));
+  push_on_lisp_stack(xp,(LispObj)(tcr->foreign_sp));
+  push_on_lisp_stack(xp,tra);
+  push_on_lisp_stack(xp,(LispObj)xp);
+  push_on_lisp_stack(xp,containing_uvector); 
+  push_on_lisp_stack(xp,relative_pc);
+  push_on_lisp_stack(xp,nominal_function);
+  push_on_lisp_stack(xp,0);
+  push_on_lisp_stack(xp,xpGPR(xp,Ifp));
+  xpGPR(xp,Ifp) = xpGPR(xp,Isp);
+  return xpGPR(xp,Isp);
+}
+
+#ifndef XMEMFULL
+#define XMEMFULL (76)
+#endif
+
+void
+lisp_allocation_failure(ExceptionInformation *xp, TCR *tcr, natural bytes_needed )
+{
+  LispObj xcf = create_exception_callback_frame(xp, tcr),
+    cmain = nrs_CMAIN.vcell;
+  int skip;
+    
+  tcr->save_allocptr = tcr->save_allocbase = (void *)VOID_ALLOCPTR;
+  xpGPR(xp,Iallocptr) = VOID_ALLOCPTR;
+
+  skip = callback_to_lisp(tcr, cmain, xp, xcf, -1, XMEMFULL, 0, 0);
+  xpPC(xp) += skip;
+}
+
+/*
+  Allocate a large list, where "large" means "large enough to
+  possibly trigger the EGC several times if this was done
+  by individually allocating each CONS."  The number of 
+  ocnses in question is in arg_z; on successful return,
+  the list will be in arg_z 
+*/
+
+Boolean
+allocate_list(ExceptionInformation *xp, TCR *tcr)
+{
+  natural 
+    nconses = (unbox_fixnum(xpGPR(xp,Iarg_z))),
+    bytes_needed = (nconses << dnode_shift);
+  LispObj
+    prev = lisp_nil,
+    current,
+    initial = xpGPR(xp,Iarg_y);
+
+  if (nconses == 0) {
+    /* Silly case */
+    xpGPR(xp,Iarg_z) = lisp_nil;
+    xpGPR(xp,Iallocptr) = lisp_nil;
+    return true;
+  }
+  update_bytes_allocated(tcr, (void *)tcr->save_allocptr);
+  if (allocate_object(xp,bytes_needed,bytes_needed-fulltag_cons,tcr)) {
+    tcr->save_allocptr -= fulltag_cons;
+    for (current = xpGPR(xp,Iallocptr);
+         nconses;
+         prev = current, current+= dnode_size, nconses--) {
+      deref(current,0) = prev;
+      deref(current,1) = initial;
+    }
+    xpGPR(xp,Iarg_z) = prev;
+  } else {
+    lisp_allocation_failure(xp,tcr,bytes_needed);
+  }
+  return true;
+}
+
+Boolean
+handle_alloc_trap(ExceptionInformation *xp, TCR *tcr)
+{
+  natural cur_allocptr, bytes_needed;
+  unsigned allocptr_tag;
+  signed_natural disp;
+  
+  cur_allocptr = xpGPR(xp,Iallocptr);
+  allocptr_tag = fulltag_of(cur_allocptr);
+  if (allocptr_tag == fulltag_misc) {
+#ifdef X8664
+    disp = xpGPR(xp,Iimm1);
+#else
+    disp = xpGPR(xp,Iimm0);
+#endif
+  } else {
+    disp = dnode_size-fulltag_cons;
+  }
+  bytes_needed = disp+allocptr_tag;
+
+  update_bytes_allocated(tcr,((BytePtr)(cur_allocptr+disp)));
+  if (allocate_object(xp, bytes_needed, disp, tcr)) {
+    return true;
+  }
+  
+  lisp_allocation_failure(xp,tcr,bytes_needed);
+
+  return true;
+}
+
+  
+int
+callback_to_lisp (TCR * tcr, LispObj callback_macptr, ExceptionInformation *xp,
+                  natural arg1, natural arg2, natural arg3, natural arg4, natural arg5)
+{
+  natural  callback_ptr;
+  int delta;
+  unsigned old_mxcsr = get_mxcsr();
+#ifdef X8632
+  natural saved_node_regs_mask = tcr->node_regs_mask;
+  natural saved_unboxed0 = tcr->unboxed0;
+  natural saved_unboxed1 = tcr->unboxed1;
+  LispObj *vsp = (LispObj *)xpGPR(xp, Isp);
+#endif
+
+  set_mxcsr(0x1f80);
+
+  /* Put the active stack pointers where .SPcallback expects them */
+#ifdef X8632
+  tcr->node_regs_mask = X8632_DEFAULT_NODE_REGS_MASK;
+
+  *--vsp = tcr->save0;
+  *--vsp = tcr->save1;
+  *--vsp = tcr->save2;
+  *--vsp = tcr->save3;
+  *--vsp = tcr->next_method_context;
+  xpGPR(xp, Isp) = (LispObj)vsp;
+#endif
+  tcr->save_vsp = (LispObj *)xpGPR(xp, Isp);
+  tcr->save_fp = (LispObj *)xpGPR(xp, Ifp);
+
+  /* Call back.  The caller of this function may have modified stack/frame
+     pointers (and at least should have called prepare_for_callback()).
+  */
+  callback_ptr = ((macptr *)ptr_from_lispobj(untag(callback_macptr)))->address;
+  UNLOCK(lisp_global(EXCEPTION_LOCK), tcr);
+  delta = ((int (*)())callback_ptr) (xp, arg1, arg2, arg3, arg4, arg5);
+  LOCK(lisp_global(EXCEPTION_LOCK), tcr);
+
+#ifdef X8632
+  tcr->next_method_context = *vsp++;
+  tcr->save3 = *vsp++;
+  tcr->save2 = *vsp++;
+  tcr->save1 = *vsp++;
+  tcr->save0 = *vsp++;
+  xpGPR(xp, Isp) = (LispObj)vsp;
+
+  tcr->node_regs_mask = saved_node_regs_mask;
+  tcr->unboxed0 = saved_unboxed0;
+  tcr->unboxed1 = saved_unboxed1;
+#endif
+  set_mxcsr(old_mxcsr);
+  return delta;
+}
+
+void
+callback_for_interrupt(TCR *tcr, ExceptionInformation *xp)
+{
+  LispObj *save_vsp = (LispObj *)xpGPR(xp,Isp),
+    word_beyond_vsp = save_vsp[-1],
+    save_fp = xpGPR(xp,Ifp),
+    xcf = create_exception_callback_frame(xp, tcr);
+  int save_errno = errno;
+
+  callback_to_lisp(tcr, nrs_CMAIN.vcell,xp, xcf, 0, 0, 0, 0);
+  xpGPR(xp,Ifp) = save_fp;
+  xpGPR(xp,Isp) = (LispObj)save_vsp;
+  save_vsp[-1] = word_beyond_vsp;
+  errno = save_errno;
+}
+
+Boolean
+handle_error(TCR *tcr, ExceptionInformation *xp)
+{
+  pc program_counter = (pc)xpPC(xp);
+  unsigned char op0 = program_counter[0], op1 = program_counter[1];
+  LispObj rpc, errdisp = nrs_ERRDISP.vcell,
+    save_vsp = xpGPR(xp,Isp), xcf0,
+    save_fp = xpGPR(xp,Ifp);
+  int skip;
+
+  if ((fulltag_of(errdisp) == fulltag_misc) &&
+      (header_subtag(header_of(errdisp)) == subtag_macptr)) {
+
+    if ((op0 == 0xcd) && (op1 >= 0xc0) && (op1 <= 0xc2)) {
+      finish_function_entry(xp);
+    }
+    xcf0 = create_exception_callback_frame(xp, tcr);
+    skip = callback_to_lisp(tcr, errdisp, xp, xcf0, 0, 0, 0, 0);
+    if (skip == -1) {
+      xcf *xcf1 = (xcf *)xcf0;
+      LispObj container = xcf1->containing_uvector;
+      
+      rpc = xcf1->relative_pc >> fixnumshift;
+      if (container == lisp_nil) {
+        xpPC(xp) = rpc;
+      } else {
+        xpPC(xp) = (LispObj)(&(deref(container,
+#ifdef X8664
+                                     1
+#else
+                                     0
+#endif
+)))+rpc;
+      }
+        
+      skip = 0;
+    }
+    xpGPR(xp,Ifp) = save_fp;
+    xpGPR(xp,Isp) = save_vsp;
+    if ((op0 == 0xcd) && (op1 == 0xc7)) {
+      /* Continue after an undefined function call. The function
+         that had been undefined has already been called (in the
+         break loop), and a list of the values that it returned
+         in in the xp's %arg_z.  A function that returns those
+         values in in the xp's %fn; we just have to adjust the
+         stack (keeping the return address in the right place
+         and discarding any stack args/reserved stack frame),
+         then set nargs and the PC so that that function's
+         called when we resume.
+      */
+      LispObj *vsp =(LispObj *)save_vsp, ra = *vsp;
+      int nargs = xpGPR(xp, Inargs)>>fixnumshift;
+
+#ifdef X8664
+      if (nargs > 3) {
+        xpGPR(xp,Isp)=(LispObj) (vsp + (1 + 2 + (nargs - 3)));
+        push_on_lisp_stack(xp,ra);
+      }
+#else
+      if (nargs > 2) {
+        xpGPR(xp,Isp)=(LispObj) (vsp + (1 + 2 + (nargs - 2)));
+        push_on_lisp_stack(xp,ra);
+      }
+#endif
+      xpPC(xp) = xpGPR(xp,Ifn);
+      xpGPR(xp,Inargs) = 1<<fixnumshift;
+    } else {
+      xpPC(xp) += skip;
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
+protection_handler
+* protection_handlers[] = {
+  do_spurious_wp_fault,
+  do_soft_stack_overflow,
+  do_soft_stack_overflow,
+  do_soft_stack_overflow,
+  do_hard_stack_overflow,    
+  do_hard_stack_overflow,
+  do_hard_stack_overflow,
+};
+
+
+/* Maybe this'll work someday.  We may have to do something to
+   make the thread look like it's not handling an exception */
+void
+reset_lisp_process(ExceptionInformation *xp)
+{
+}
+
+Boolean
+do_hard_stack_overflow(ExceptionInformation *xp, protected_area_ptr area, BytePtr addr)
+{
+  reset_lisp_process(xp);
+  return false;
+}
+
+
+Boolean
+do_spurious_wp_fault(ExceptionInformation *xp, protected_area_ptr area, BytePtr addr)
+{
+
+  return false;
+}
+
+Boolean
+do_soft_stack_overflow(ExceptionInformation *xp, protected_area_ptr prot_area, BytePtr addr)
+{
+  /* Trying to write into a guard page on the vstack or tstack.
+     Allocate a new stack segment, emulate stwu and stwux for the TSP, and
+     signal an error_stack_overflow condition.
+      */
+  lisp_protection_kind which = prot_area->why;
+  Boolean on_TSP = (which == kTSPsoftguard);
+  LispObj save_fp = xpGPR(xp,Ifp);
+  LispObj save_vsp = xpGPR(xp,Isp), 
+    xcf,
+    cmain = nrs_CMAIN.vcell;
+  area *a;
+  protected_area_ptr soft;
+  TCR *tcr = get_tcr(false);
+  int skip;
+
+  if ((fulltag_of(cmain) == fulltag_misc) &&
+      (header_subtag(header_of(cmain)) == subtag_macptr)) {
+    if (on_TSP) {
+      a = tcr->ts_area;
+    } else {
+      a = tcr->vs_area;
+    }
+    soft = a->softprot;
+    unprotect_area(soft);
+    xcf = create_exception_callback_frame(xp, tcr);
+    skip = callback_to_lisp(tcr, cmain, xp, xcf, SIGSEGV, on_TSP, 0, 0);
+    xpGPR(xp,Ifp) = save_fp;
+    xpGPR(xp,Isp) = save_vsp;
+    xpPC(xp) += skip;
+    return true;
+  }
+  return false;
+}
+
+Boolean
+is_write_fault(ExceptionInformation *xp, siginfo_t *info)
+{
+#ifdef DARWIN
+  return (UC_MCONTEXT(xp)->__es.__err & 0x2) != 0;
+#endif
+#if defined(LINUX) || defined(SOLARIS)
+  return (xpGPR(xp,REG_ERR) & 0x2) != 0;
+#endif
+#ifdef FREEBSD
+  return (xp->uc_mcontext.mc_err & 0x2) != 0;
+#endif
+#ifdef WINDOWS
+  return (info->ExceptionFlags == EXCEPTION_WRITE_FAULT);
+#endif
+}
+
+Boolean
+handle_fault(TCR *tcr, ExceptionInformation *xp, siginfo_t *info, int old_valence)
+{
+#ifdef FREEBSD
+#ifdef X8664
+  BytePtr addr = (BytePtr) xp->uc_mcontext.mc_addr;
+#else
+  BytePtr addr = (BytePtr) info->si_addr;
+#endif
+#else
+#ifdef WINDOWS
+  BytePtr addr = (BytePtr) info->ExceptionInformation[1];
+#else
+  BytePtr addr = (BytePtr) info->si_addr;
+#endif
+#endif
+  Boolean valid = IS_PAGE_FAULT(info,xp);
+
+  if (valid) {
+    if (addr && (addr == tcr->safe_ref_address)) {
+      xpGPR(xp,Iimm0) = 0;
+      xpPC(xp) = xpGPR(xp,Ira0);
+      return true;
+    }
+    
+    {
+      protected_area *a = find_protected_area(addr);
+      protection_handler *handler;
+      
+      if (a) {
+        handler = protection_handlers[a->why];
+        return handler(xp, a, addr);
+      }
+    }
+
+    if ((addr >= readonly_area->low) &&
+	(addr < readonly_area->active)) {
+      UnProtectMemory((LogicalAddress)(truncate_to_power_of_2(addr,log2_page_size)),
+		      page_size);
+      return true;
+    }
+
+    {
+      area *a = area_containing(addr);
+
+      if (a && a->code == AREA_WATCHED && addr < a->high) {
+	/* caught a write to a watched object */
+	LispObj *p = (LispObj *)a->low;
+	LispObj node = *p;
+	unsigned tag_n = fulltag_of(node);
+	LispObj cmain = nrs_CMAIN.vcell;
+	LispObj obj;
+
+	if (immheader_tag_p(tag_n) || nodeheader_tag_p(tag_n))
+	  obj = (LispObj)p + fulltag_misc;
+	else
+	  obj = (LispObj)p + fulltag_cons;
+
+	if ((fulltag_of(cmain) == fulltag_misc) &&
+	    (header_subtag(header_of(cmain)) == subtag_macptr)) {
+	  LispObj save_vsp = xpGPR(xp, Isp);
+	  LispObj save_fp = xpGPR(xp, Ifp);
+	  LispObj xcf;
+	  natural offset = (LispObj)addr - obj;
+	  int skip;
+
+	  push_on_lisp_stack(xp, obj);
+	  xcf = create_exception_callback_frame(xp, tcr);
+
+	  /* The magic 2 means this was a write to a watchd object */
+	  skip = callback_to_lisp(tcr, cmain, xp, xcf, SIGSEGV, 2,
+				  (natural)addr, offset);
+	  xpPC(xp) += skip;
+	  xpGPR(xp, Ifp) = save_fp;
+	  xpGPR(xp, Isp) = save_vsp;
+	  return true;
+	}
+      }
+    }
+  }
+
+  if (old_valence == TCR_STATE_LISP) {
+    LispObj cmain = nrs_CMAIN.vcell,
+      xcf;
+    if ((fulltag_of(cmain) == fulltag_misc) &&
+      (header_subtag(header_of(cmain)) == subtag_macptr)) {
+      xcf = create_exception_callback_frame(xp, tcr);
+      callback_to_lisp(tcr, cmain, xp, xcf, SIGBUS, valid ? is_write_fault(xp,info) : (natural)-1, valid ? (natural)addr : 0, 0);
+    }
+  }
+  return false;
+}
+
+Boolean
+handle_floating_point_exception(TCR *tcr, ExceptionInformation *xp, siginfo_t *info)
+{
+  int code,skip;
+  LispObj  xcf, cmain = nrs_CMAIN.vcell,
+    save_vsp = xpGPR(xp,Isp),
+    save_fp = xpGPR(xp,Ifp);
+#ifdef WINDOWS
+  code = info->ExceptionCode;
+#else
+  code = info->si_code;
+#endif  
+
+  if ((fulltag_of(cmain) == fulltag_misc) &&
+      (header_subtag(header_of(cmain)) == subtag_macptr)) {
+    xcf = create_exception_callback_frame(xp, tcr);
+    skip = callback_to_lisp(tcr, cmain, xp, xcf, SIGFPE, code, 0, 0);
+    xpPC(xp) += skip;
+    xpGPR(xp,Ifp) = save_fp;
+    xpGPR(xp,Isp) = save_vsp;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
+Boolean
+extend_tcr_tlb(TCR *tcr, ExceptionInformation *xp)
+{
+  LispObj index, old_limit = tcr->tlb_limit, new_limit, new_bytes;
+  LispObj *old_tlb = tcr->tlb_pointer, *new_tlb, *work, *tos;
+
+  tos = (LispObj*)(xpGPR(xp,Isp));
+  index = *tos++;
+  (xpGPR(xp,Isp))=(LispObj)tos;
+  
+  new_limit = align_to_power_of_2(index+1,12);
+  new_bytes = new_limit-old_limit;
+  new_tlb = realloc(old_tlb, new_limit);
+
+  if (new_tlb == NULL) {
+    return false;
+  }
+  work = (LispObj *) ((BytePtr)new_tlb+old_limit);
+
+  while (new_bytes) {
+    *work++ = no_thread_local_binding_marker;
+    new_bytes -= sizeof(LispObj);
+  }
+  tcr->tlb_pointer = new_tlb;
+  tcr->tlb_limit = new_limit;
+  return true;
+}
+
+
+#if defined(FREEBSD) || defined(DARWIN)
+static
+char mxcsr_bit_to_fpe_code[] = {
+  FPE_FLTINV,                   /* ie */
+  0,                            /* de */
+  FPE_FLTDIV,                   /* ze */
+  FPE_FLTOVF,                   /* oe */
+  FPE_FLTUND,                   /* ue */
+  FPE_FLTRES                    /* pe */
+};
+
+void
+decode_vector_fp_exception(siginfo_t *info, uint32_t mxcsr)
+{
+  /* If the exception appears to be an XMM FP exception, try to
+     determine what it was by looking at bits in the mxcsr.
+  */
+  int xbit, maskbit;
+  
+  for (xbit = 0, maskbit = MXCSR_IM_BIT; xbit < 6; xbit++, maskbit++) {
+    if ((mxcsr & (1 << xbit)) &&
+        !(mxcsr & (1 << maskbit))) {
+      info->si_code = mxcsr_bit_to_fpe_code[xbit];
+      return;
+    }
+  }
+}
+
+#ifdef FREEBSD
+void
+freebsd_decode_vector_fp_exception(siginfo_t *info, ExceptionInformation *xp)
+{
+  if (info->si_code == 0) {
+#ifdef X8664
+    struct savefpu *fpu = (struct savefpu *) &(xp->uc_mcontext.mc_fpstate);
+#else
+    struct ccl_savexmm *fpu = (struct ccl_savexmm *) &(xp->uc_mcontext.mc_fpstate);
+#endif
+    uint32_t mxcsr = fpu->sv_env.en_mxcsr;
+
+    decode_vector_fp_exception(info, mxcsr);
+  }
+}
+#endif
+
+#ifdef DARWIN
+void
+darwin_decode_vector_fp_exception(siginfo_t *info, ExceptionInformation *xp)
+{
+  if (info->si_code == EXC_I386_SSEEXTERR) {
+    uint32_t mxcsr = UC_MCONTEXT(xp)->__fs.__fpu_mxcsr;
+
+    decode_vector_fp_exception(info, mxcsr);
+  }
+}
+
+#endif
+
+#endif
+
+void
+get_lisp_string(LispObj lisp_string, char *c_string, natural max)
+{
+  lisp_char_code *src = (lisp_char_code *)  (ptr_from_lispobj(lisp_string + misc_data_offset));
+  natural i, n = header_element_count(header_of(lisp_string));
+
+  if (n > max) {
+    n = max;
+  }
+
+  for (i = 0; i < n; i++) {
+    c_string[i] = 0xff & (src[i]);
+  }
+  c_string[n] = 0;
+}
+
+Boolean
+handle_exception(int signum, siginfo_t *info, ExceptionInformation  *context, TCR *tcr, int old_valence)
+{
+  pc program_counter = (pc)xpPC(context);
+
+  switch (signum) {
+  case SIGNUM_FOR_INTN_TRAP:
+    if (IS_MAYBE_INT_TRAP(info,context)) {
+      /* Something mapped to SIGSEGV/SIGBUS that has nothing to do with
+	 a memory fault.  On x86, an "int n" instruction that's
+         not otherwise implemented causes a "protecton fault".  Of
+         course that has nothing to do with accessing protected
+         memory; of course, most Unices act as if it did.*/
+      if ((program_counter != NULL) &&
+          (*program_counter == INTN_OPCODE)) {
+        program_counter++;
+        switch (*program_counter) {
+        case UUO_ALLOC_TRAP:
+          if (handle_alloc_trap(context, tcr)) {
+            xpPC(context) += 2;	/* we might have GCed. */
+            return true;
+          }
+          break;
+        case UUO_GC_TRAP:
+          if (handle_gc_trap(context, tcr)) {
+            xpPC(context) += 2;
+            return true;
+          }
+          break;
+	case UUO_WATCH_TRAP:
+	  /* add or remove watched object */
+	  if (handle_watch_trap(context, tcr)) {
+	    xpPC(context) += 2;
+	    return true;
+	  }
+	  break;
+        case UUO_DEBUG_TRAP:
+          xpPC(context) = (natural) (program_counter+1);
+          lisp_Debugger(context, info, debug_entry_dbg, false, "Lisp Breakpoint");
+          return true;
+            
+        case UUO_DEBUG_TRAP_WITH_STRING:
+          xpPC(context) = (natural) (program_counter+1);
+          {
+            char msg[512];
+
+            get_lisp_string(xpGPR(context,Iarg_z),msg, sizeof(msg)-1);
+            lisp_Debugger(context, info, debug_entry_dbg, false, msg);
+          }
+	  return true;
+          
+        default:
+          return handle_error(tcr, context);
+	}
+      } else {
+	return false;
+      }
+
+    } else {
+      return handle_fault(tcr, context, info, old_valence);
+    }
+    break;
+
+  case SIGNAL_FOR_PROCESS_INTERRUPT:
+    tcr->interrupt_pending = 0;
+    callback_for_interrupt(tcr, context);
+    return true;
+    break;
+
+
+  case SIGILL:
+    if ((program_counter[0] == XUUO_OPCODE_0) &&
+	(program_counter[1] == XUUO_OPCODE_1)) {
+      TCR *target = (TCR *)xpGPR(context, Iarg_z);
+
+      switch (program_counter[2]) {
+      case XUUO_TLB_TOO_SMALL:
+        if (extend_tcr_tlb(tcr,context)) {
+          xpPC(context)+=3;
+          return true;
+        }
+	break;
+	
+      case XUUO_INTERRUPT_NOW:
+	callback_for_interrupt(tcr,context);
+	xpPC(context)+=3;
+	return true;
+
+      case XUUO_SUSPEND_NOW:
+	xpPC(context)+=3;
+	return true;
+
+      case XUUO_INTERRUPT:
+        raise_thread_interrupt(target);
+	xpPC(context)+=3;
+	return true;
+
+      case XUUO_SUSPEND:
+        xpGPR(context,Iimm0) = (LispObj) lisp_suspend_tcr(target);
+	xpPC(context)+=3;
+	return true;
+
+      case XUUO_SUSPEND_ALL:
+        lisp_suspend_other_threads();
+	xpPC(context)+=3;
+	return true;
+
+
+      case XUUO_RESUME:
+        xpGPR(context,Iimm0) = (LispObj) lisp_resume_tcr(target);
+	xpPC(context)+=3;
+	return true;
+        
+      case XUUO_RESUME_ALL:
+        lisp_resume_other_threads();
+	xpPC(context)+=3;
+	return true;
+	
+      case XUUO_KILL:
+        xpGPR(context,Iimm0) = (LispObj)kill_tcr(target);
+        xpPC(context)+=3;
+        return true;
+
+      case XUUO_ALLOCATE_LIST:
+        allocate_list(context,tcr);
+        xpPC(context)+=3;
+        return true;
+
+      default:
+	return false;
+      }
+    } else {
+      return false;
+    }
+    break;
+    
+  case SIGFPE:
+#ifdef FREEBSD
+    /* As of 6.1, FreeBSD/AMD64 doesn't seem real comfortable
+       with this newfangled XMM business (and therefore info->si_code
+       is often 0 on an XMM FP exception.
+       Try to figure out what really happened by decoding mxcsr
+       bits.
+    */
+    freebsd_decode_vector_fp_exception(info,context);
+#endif
+#ifdef DARWIN
+    /* Same general problem with Darwin as of 8.7.2 */
+    darwin_decode_vector_fp_exception(info,context);
+#endif
+
+    return handle_floating_point_exception(tcr, context, info);
+
+#if SIGBUS != SIGNUM_FOR_INTN_TRAP
+  case SIGBUS:
+    return handle_fault(tcr, context, info, old_valence);
+#endif
+    
+#if SIGSEGV != SIGNUM_FOR_INTN_TRAP
+  case SIGSEGV:
+    return handle_fault(tcr, context, info, old_valence);
+#endif    
+    
+  default:
+    return false;
+  }
+}
+
+
+/* 
+   Current thread has all signals masked.  Before unmasking them,
+   make it appear that the current thread has been suspended.
+   (This is to handle the case where another thread is trying
+   to GC before this thread is able to seize the exception lock.)
+*/
+int
+prepare_to_wait_for_exception_lock(TCR *tcr, ExceptionInformation *context)
+{
+  int old_valence = tcr->valence;
+
+  tcr->pending_exception_context = context;
+  tcr->valence = TCR_STATE_EXCEPTION_WAIT;
+
+#ifdef WINDOWS
+  if (tcr->flags & (1<<TCR_FLAG_BIT_PENDING_SUSPEND)) {
+    CLR_TCR_FLAG(tcr, TCR_FLAG_BIT_PENDING_SUSPEND);
+    SEM_RAISE(tcr->suspend);
+    SEM_WAIT_FOREVER(tcr->resume);
+  }
+#else
+  ALLOW_EXCEPTIONS(context);
+#endif
+  return old_valence;
+}  
+
+void
+wait_for_exception_lock_in_handler(TCR *tcr, 
+				   ExceptionInformation *context,
+				   xframe_list *xf)
+{
+
+  LOCK(lisp_global(EXCEPTION_LOCK), tcr);
+#if 0
+  fprintf(dbgout, "0x" LISP " has exception lock\n", tcr);
+#endif
+  xf->curr = context;
+#ifdef X8632
+  xf->node_regs_mask = tcr->node_regs_mask;
+#endif
+  xf->prev = tcr->xframe;
+  tcr->xframe =  xf;
+  tcr->pending_exception_context = NULL;
+  tcr->valence = TCR_STATE_FOREIGN; 
+}
+
+void
+unlock_exception_lock_in_handler(TCR *tcr)
+{
+  tcr->pending_exception_context = tcr->xframe->curr;
+#ifdef X8632
+  tcr->node_regs_mask = tcr->xframe->node_regs_mask;
+#endif
+  tcr->xframe = tcr->xframe->prev;
+  tcr->valence = TCR_STATE_EXCEPTION_RETURN;
+  UNLOCK(lisp_global(EXCEPTION_LOCK),tcr);
+#if 0
+  fprintf(dbgout, "0x" LISP " released exception lock\n", tcr);
+#endif
+}
+
+/* 
+   If an interrupt is pending on exception exit, try to ensure
+   that the thread sees it as soon as it's able to run.
+*/
+#ifdef WINDOWS
+void
+raise_pending_interrupt(TCR *tcr)
+{
+}
+void
+exit_signal_handler(TCR *tcr, int old_valence)
+{
+}
+void
+signal_handler(int signum, siginfo_t *info, ExceptionInformation  *context, TCR *tcr, int old_valence)
+{
+}
+#else
+void
+raise_pending_interrupt(TCR *tcr)
+{
+  if ((TCR_INTERRUPT_LEVEL(tcr) >= 0) &&
+      (tcr->interrupt_pending)) {
+    pthread_kill((pthread_t)(tcr->osid), SIGNAL_FOR_PROCESS_INTERRUPT);
+  }
+}
+
+void
+exit_signal_handler(TCR *tcr, int old_valence)
+{
+  sigset_t mask;
+  sigfillset(&mask);
+#ifdef FREEBSD
+  sigdelset(&mask,SIGTRAP);
+#endif
+  
+  pthread_sigmask(SIG_SETMASK,&mask, NULL);
+  tcr->valence = old_valence;
+  tcr->pending_exception_context = NULL;
+}
+
+void
+signal_handler(int signum, siginfo_t *info, ExceptionInformation  *context
+#ifdef DARWIN
+               , TCR *tcr, int old_valence
+#endif
+)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  xframe_list xframe_link;
+#ifndef DARWIN
+  TCR *tcr = get_tcr(false);
+
+  int old_valence = prepare_to_wait_for_exception_lock(tcr, context);
+#endif
+  if (tcr->flags & (1<<TCR_FLAG_BIT_PENDING_SUSPEND)) {
+    CLR_TCR_FLAG(tcr, TCR_FLAG_BIT_PENDING_SUSPEND);
+    pthread_kill(pthread_self(), thread_suspend_signal);
+  }
+  wait_for_exception_lock_in_handler(tcr,context, &xframe_link);
+
+
+  if (! handle_exception(signum, info, context, tcr, old_valence)) {
+    char msg[512];
+    Boolean foreign = (old_valence != TCR_STATE_LISP);
+
+    snprintf(msg, sizeof(msg), "Unhandled exception %d at 0x" LISP ", context->regs at #x" LISP "", signum, xpPC(context), (natural)xpGPRvector(context));
+    
+    if (lisp_Debugger(context, info, signum,  foreign, msg)) {
+      SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PROPAGATE_EXCEPTION);
+    }
+  }
+  unlock_exception_lock_in_handler(tcr);
+#ifndef DARWIN_USE_PSEUDO_SIGRETURN
+  exit_signal_handler(tcr, old_valence);
+#endif
+  /* raise_pending_interrupt(tcr); */
+#ifdef DARWIN_GS_HACK
+  if (gs_was_tcr) {
+    set_gs_address(tcr);
+  }
+#endif
+#ifndef DARWIN_USE_PSEUDO_SIGRETURN
+  SIGRETURN(context);
+#endif
+}
+#endif
+
+
+
+
+#ifdef LINUX
+/* type of pointer to saved fp state */
+#ifdef X8664
+typedef fpregset_t FPREGS;
+#else
+typedef struct _fpstate *FPREGS;
+#endif
+LispObj *
+copy_fpregs(ExceptionInformation *xp, LispObj *current, FPREGS *destptr)
+{
+  FPREGS src = (FPREGS)(xp->uc_mcontext.fpregs), dest;
+  
+  if (src) {
+    dest = ((FPREGS)current)-1;
+    *dest = *src;
+    *destptr = dest;
+    current = (LispObj *) dest;
+  }
+  return current;
+}
+#endif
+
+#ifdef DARWIN
+LispObj *
+copy_darwin_mcontext(MCONTEXT_T context, 
+                     LispObj *current, 
+                     MCONTEXT_T *out)
+{
+  MCONTEXT_T dest = ((MCONTEXT_T)current)-1;
+  dest = (MCONTEXT_T) (((LispObj)dest) & ~15);
+
+  *dest = *context;
+  *out = dest;
+  return (LispObj *)dest;
+}
+#endif
+
+LispObj *
+copy_siginfo(siginfo_t *info, LispObj *current)
+{
+  siginfo_t *dest = ((siginfo_t *)current) - 1;
+#if !defined(LINUX) || !defined(X8632)
+  dest = (siginfo_t *) (((LispObj)dest)&~15);
+#endif
+  *dest = *info;
+  return (LispObj *)dest;
+}
+
+#ifdef LINUX
+typedef FPREGS copy_ucontext_last_arg_t;
+#else
+typedef void * copy_ucontext_last_arg_t;
+#endif
+
+#ifndef WINDOWS
+LispObj *
+copy_ucontext(ExceptionInformation *context, LispObj *current, copy_ucontext_last_arg_t fp)
+{
+  ExceptionInformation *dest = ((ExceptionInformation *)current)-1;
+#if !defined(LINUX) || !defined(X8632)
+  dest = (ExceptionInformation *) (((LispObj)dest) & ~15);
+#endif
+
+  *dest = *context;
+  /* Fix it up a little; where's the signal mask allocated, if indeed
+     it is "allocated" ? */
+#ifdef LINUX
+  dest->uc_mcontext.fpregs = (fpregset_t)fp;
+#endif
+  dest->uc_stack.ss_sp = 0;
+  dest->uc_stack.ss_size = 0;
+  dest->uc_stack.ss_flags = 0;
+  dest->uc_link = NULL;
+  return (LispObj *)dest;
+}
+#endif
+
+
+LispObj *
+tcr_frame_ptr(TCR *tcr)
+{
+  ExceptionInformation *xp;
+  LispObj *fp;
+
+  if (tcr->pending_exception_context)
+    xp = tcr->pending_exception_context;
+  else if (tcr->valence == TCR_STATE_LISP) {
+    xp = tcr->suspend_context;
+  } else {
+    xp = NULL;
+  }
+  if (xp) {
+    fp = (LispObj *)xpGPR(xp, Ifp);
+  } else {
+    fp = tcr->save_fp;
+  }
+  return fp;
+}
+
+
+LispObj *
+find_foreign_rsp(LispObj rsp, area *foreign_area, TCR *tcr)
+{
+
+  if (((BytePtr)rsp < foreign_area->low) ||
+      ((BytePtr)rsp > foreign_area->high)) {
+    rsp = (LispObj)(tcr->foreign_sp);
+  }
+  return (LispObj *) (((rsp-128) & ~15));
+}
+
+#ifdef X8632
+#ifdef LINUX
+/* This is here for debugging.  On entry to a signal handler that
+   receives info and context arguments, the stack should look exactly
+   like this.  The "pretcode field" of the structure is the address
+   of code that does an rt_sigreturn syscall, and rt_sigreturn expects
+   %esp at the time of that syscall to be pointing just past the
+   pretcode field.
+   handle_signal_on_foreign_stack() and helpers have to be very
+   careful to duplicate this "structure" exactly.
+   Note that on x8664 Linux, rt_sigreturn expects a ucontext to
+   be on top of the stack (with a siginfo_t underneath it.)
+   It sort of half-works to do sigreturn via setcontext() on 
+   x8632 Linux, but (a) it may not be available on some distributions
+   and (b) even a relatively modern version of it uses "fldenv" to
+   restore FP context, and "fldenv" isn't nearly good enough.
+*/
+
+struct rt_sigframe {
+	char *pretcode;
+	int sig;
+	siginfo_t  *pinfo;
+	void  *puc;
+	siginfo_t info;
+	struct ucontext uc;
+	struct _fpstate fpstate;
+	char retcode[8];
+};
+struct rt_sigframe *rtsf = 0;
+
+#endif
+#endif
+
+
+#ifndef WINDOWS
+/* x8632 Linux requires that the stack-allocated siginfo is nearer
+   the top of stack than the stack-allocated ucontext.  If other
+   platforms care, they expect the ucontext to be nearer the top
+   of stack.
+*/
+
+#if defined(LINUX) && defined(X8632)
+#define UCONTEXT_ON_TOP_OF_STACK 0
+#else
+#define UCONTEXT_ON_TOP_OF_STACK 1
+#endif
+void
+handle_signal_on_foreign_stack(TCR *tcr,
+                               void *handler, 
+                               int signum, 
+                               siginfo_t *info, 
+                               ExceptionInformation *context,
+                               LispObj return_address
+#ifdef DARWIN_GS_HACK
+                               , Boolean gs_was_tcr
+#endif
+                               )
+{
+#ifdef LINUX
+  FPREGS fpregs = NULL;
+#else
+  void *fpregs = NULL;
+#endif
+#ifdef DARWIN
+  MCONTEXT_T mcontextp = NULL;
+#endif
+  siginfo_t *info_copy = NULL;
+  ExceptionInformation *xp = NULL;
+  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
+
+#ifdef LINUX
+  foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
+#endif
+#ifdef DARWIN
+  foreign_rsp = copy_darwin_mcontext(UC_MCONTEXT(context), foreign_rsp, &mcontextp);
+#endif
+#if UCONTEXT_ON_TOP_OF_STACK
+  /* copy info first */
+  foreign_rsp = copy_siginfo(info, foreign_rsp);
+  info_copy = (siginfo_t *)foreign_rsp;
+  foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
+  xp = (ExceptionInformation *)foreign_rsp;
+#else
+  foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
+  xp = (ExceptionInformation *)foreign_rsp;
+  foreign_rsp = copy_siginfo(info, foreign_rsp);
+  info_copy = (siginfo_t *)foreign_rsp;
+#endif
+#ifdef DARWIN
+  UC_MCONTEXT(xp) = mcontextp;
+#endif
+  *--foreign_rsp = return_address;
+#ifdef DARWIN_GS_HACK
+  if (gs_was_tcr) {
+    set_gs_address(tcr);
+  }
+#endif
+  switch_to_foreign_stack(foreign_rsp,handler,signum,info_copy,xp);
+}
+#endif
+
+
+#ifndef WINDOWS
+#ifndef USE_SIGALTSTACK
+void
+arbstack_signal_handler(int signum, siginfo_t *info, ExceptionInformation *context)
+{
+  TCR *tcr = get_interrupt_tcr(false);
+#if 1
+  if (tcr->valence != TCR_STATE_LISP) {
+    FBug(context, "exception in foreign context");
+  }
+#endif
+  {
+    area *vs = tcr->vs_area;
+    BytePtr current_sp = (BytePtr) current_stack_pointer();
+
+
+    if ((current_sp >= vs->low) &&
+        (current_sp < vs->high)) {
+      handle_signal_on_foreign_stack(tcr,
+                                     signal_handler,
+                                     signum,
+                                     info,
+                                     context,
+                                     (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                     , false
+#endif
+
+                                     );
+    } else {
+      signal_handler(signum, info, context, tcr, 0);
+    }
+  }
+}
+
+#else
+void
+altstack_signal_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
+{
+  TCR* tcr = get_tcr(true);
+#if 1
+  if (tcr->valence != TCR_STATE_LISP) {
+    FBug(context, "exception in foreign context");
+  }
+#endif
+  handle_signal_on_foreign_stack(tcr,signal_handler,signum,info,context,(LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 , false
+#endif
+);
+}
+#endif
+#endif
+
+Boolean
+stack_pointer_on_vstack_p(LispObj stack_pointer, TCR *tcr)
+{
+  area *a = tcr->vs_area;
+ 
+  return (((BytePtr)stack_pointer <= a->high) &&
+          ((BytePtr)stack_pointer > a->low));
+}
+
+
+#ifdef WINDOWS
+extern DWORD restore_windows_context(ExceptionInformation *, TCR *, int);
+#endif
+
+void
+interrupt_handler (int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_interrupt_tcr(false);
+  int old_valence = tcr->valence;
+
+  if (tcr) {
+    if ((TCR_INTERRUPT_LEVEL(tcr) < 0) ||
+        (tcr->valence != TCR_STATE_LISP) ||
+        (tcr->unwinding != 0) ||
+        ! stack_pointer_on_vstack_p(xpGPR(context,Isp), tcr) ||
+        ! stack_pointer_on_vstack_p(xpGPR(context,Ifp), tcr)) {
+      tcr->interrupt_pending = (((natural) 1)<< (nbits_in_word - ((natural)1)));
+    } else {
+      LispObj cmain = nrs_CMAIN.vcell;
+
+      if ((fulltag_of(cmain) == fulltag_misc) &&
+	  (header_subtag(header_of(cmain)) == subtag_macptr)) {
+	/* 
+	   This thread can (allegedly) take an interrupt now. 
+        */
+
+        xframe_list xframe_link;
+        signed_natural alloc_displacement = 0;
+        LispObj 
+          *next_tsp = tcr->next_tsp,
+          *save_tsp = tcr->save_tsp,
+          *p,
+          q;
+        natural old_foreign_exception = tcr->flags & (1 << TCR_FLAG_BIT_FOREIGN_EXCEPTION);
+
+        tcr->flags &= ~(1 << TCR_FLAG_BIT_FOREIGN_EXCEPTION);
+            
+        if (next_tsp != save_tsp) {
+          tcr->next_tsp = save_tsp;
+        } else {
+          next_tsp = NULL;
+        }
+        /* have to do this before allowing interrupts */
+        pc_luser_xp(context, tcr, &alloc_displacement);
+        old_valence = prepare_to_wait_for_exception_lock(tcr, context);
+        wait_for_exception_lock_in_handler(tcr, context, &xframe_link);
+        handle_exception(signum, info, context, tcr, old_valence);
+        if (alloc_displacement) {
+          tcr->save_allocptr -= alloc_displacement;
+        }
+        if (next_tsp) {
+          tcr->next_tsp = next_tsp;
+          p = next_tsp;
+          while (p != save_tsp) {
+            *p++ = 0;
+          }
+          q = (LispObj)save_tsp;
+          *next_tsp = q;
+        }
+        tcr->flags |= old_foreign_exception;
+        unlock_exception_lock_in_handler(tcr);
+#ifndef WINDOWS
+        exit_signal_handler(tcr, old_valence);
+#endif
+      }
+    }
+  }
+#ifdef DARWIN_GS_HACK
+  if (gs_was_tcr) {
+    set_gs_address(tcr);
+  }
+#endif
+#ifdef WINDOWS
+  restore_windows_context(context,tcr,old_valence);
+#else
+  SIGRETURN(context);
+#endif
+}
+
+
+#ifndef WINDOWS
+#ifndef USE_SIGALTSTACK
+void
+arbstack_interrupt_handler (int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_interrupt_tcr(false);
+  area *vs = tcr->vs_area;
+  BytePtr current_sp = (BytePtr) current_stack_pointer();
+
+  if ((current_sp >= vs->low) &&
+      (current_sp < vs->high)) {
+    handle_signal_on_foreign_stack(tcr,
+                                   interrupt_handler,
+                                   signum,
+                                   info,
+                                   context,
+                                   (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                   ,gs_was_tcr
+#endif
+                                   );
+  } else {
+    /* If we're not on the value stack, we pretty much have to be on
+       the C stack.  Just run the handler. */
+#ifdef DARWIN_GS_HACK
+    if (gs_was_tcr) {
+      set_gs_address(tcr);
+    }
+#endif
+    interrupt_handler(signum, info, context);
+  }
+}
+
+#else /* altstack works */
+  
+void
+altstack_interrupt_handler (int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_interrupt_tcr(false);
+  handle_signal_on_foreign_stack(tcr,interrupt_handler,signum,info,context,(LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 ,gs_was_tcr
+#endif
+                                 );
+}
+
+#endif
+#endif
+
+#ifndef WINDOWS
+void
+install_signal_handler(int signo, void * handler)
+{
+  struct sigaction sa;
+  
+  sa.sa_sigaction = (void *)handler;
+  sigfillset(&sa.sa_mask);
+#ifdef FREEBSD
+  /* Strange FreeBSD behavior wrt synchronous signals */
+  sigdelset(&sa.sa_mask,SIGTRAP);  /* let GDB work */
+#endif
+  sa.sa_flags = 
+    0 /* SA_RESTART */
+#ifdef USE_SIGALTSTACK
+    | SA_ONSTACK
+#endif
+    | SA_SIGINFO;
+
+  sigaction(signo, &sa, NULL);
+}
+#endif
+
+#ifdef WINDOWS
+BOOL 
+CALLBACK ControlEventHandler(DWORD event)
+{
+  switch(event) {
+  case CTRL_C_EVENT:
+    lisp_global(INTFLAG) = (1 << fixnumshift);
+    return TRUE;
+    break;
+  default:
+    return FALSE;
+  }
+}
+
+static
+DWORD mxcsr_bit_to_fpe_code[] = {
+  EXCEPTION_FLT_INVALID_OPERATION, /* ie */
+  0,                            /* de */
+  EXCEPTION_FLT_DIVIDE_BY_ZERO, /* ze */
+  EXCEPTION_FLT_OVERFLOW,       /* oe */
+  EXCEPTION_FLT_UNDERFLOW,      /* ue */
+  EXCEPTION_FLT_INEXACT_RESULT  /* pe */
+};
+
+#ifndef STATUS_FLOAT_MULTIPLE_FAULTS
+#define STATUS_FLOAT_MULTIPLE_FAULTS 0xc00002b4
+#endif
+
+#ifndef STATUS_FLOAT_MULTIPLE_TRAPS
+#define  STATUS_FLOAT_MULTIPLE_TRAPS 0xc00002b5
+#endif
+
+int
+map_windows_exception_code_to_posix_signal(DWORD code, siginfo_t *info, ExceptionInformation *context)
+{
+  switch (code) {
+#ifdef WIN_32
+  case STATUS_FLOAT_MULTIPLE_FAULTS:
+  case STATUS_FLOAT_MULTIPLE_TRAPS:
+    {
+      int xbit, maskbit;
+      DWORD mxcsr = *(xpMXCSRptr(context));
+
+      for (xbit = 0, maskbit = MXCSR_IM_BIT; xbit < 6; xbit++, maskbit++) {
+        if ((mxcsr & (1 << xbit)) &&
+            !(mxcsr & (1 << maskbit))) {
+          info->ExceptionCode = mxcsr_bit_to_fpe_code[xbit];
+          break;
+        }
+      }
+    }
+    return SIGFPE;
+#endif
+      
+  case EXCEPTION_ACCESS_VIOLATION:
+    return SIGSEGV;
+  case EXCEPTION_FLT_DENORMAL_OPERAND:
+  case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+  case EXCEPTION_FLT_INEXACT_RESULT:
+  case EXCEPTION_FLT_INVALID_OPERATION:
+  case EXCEPTION_FLT_OVERFLOW:
+  case EXCEPTION_FLT_STACK_CHECK:
+  case EXCEPTION_FLT_UNDERFLOW:
+  case EXCEPTION_INT_DIVIDE_BY_ZERO:
+  case EXCEPTION_INT_OVERFLOW:
+    return SIGFPE;
+  case EXCEPTION_PRIV_INSTRUCTION:
+  case EXCEPTION_ILLEGAL_INSTRUCTION:
+    return SIGILL;
+  case EXCEPTION_IN_PAGE_ERROR:
+    return SIGBUS;
+  default:
+    return -1;
+  }
+}
+
+
+LONG
+windows_exception_handler(EXCEPTION_POINTERS *exception_pointers, TCR *tcr)
+{
+  DWORD code = exception_pointers->ExceptionRecord->ExceptionCode;
+  int old_valence, signal_number;
+  ExceptionInformation *context = exception_pointers->ContextRecord;
+  siginfo_t *info = exception_pointers->ExceptionRecord;
+  xframe_list xframes;
+
+  old_valence = prepare_to_wait_for_exception_lock(tcr, context);
+  wait_for_exception_lock_in_handler(tcr, context, &xframes);
+
+  signal_number = map_windows_exception_code_to_posix_signal(code, info, context);
+  
+  if (!handle_exception(signal_number, info, context, tcr, old_valence)) {
+    char msg[512];
+    Boolean foreign = (old_valence != TCR_STATE_LISP);
+
+    snprintf(msg, sizeof(msg), "Unhandled exception %d (windows code 0x%x) at 0x%Ix, context->regs at 0x%Ix", signal_number, code, xpPC(context), (natural)xpGPRvector(context));
+    
+    if (lisp_Debugger(context, info, signal_number,  foreign, msg)) {
+      SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PROPAGATE_EXCEPTION);
+    }
+  }
+  unlock_exception_lock_in_handler(tcr);
+  return restore_windows_context(context, tcr, old_valence);
+}
+
+void
+setup_exception_handler_call(CONTEXT *context,
+                             LispObj new_sp,
+                             void *handler,
+                             EXCEPTION_POINTERS *new_ep,
+                             TCR *tcr)
+{
+  extern void windows_halt(void);
+  LispObj *p = (LispObj *)new_sp;
+#ifdef WIN_64
+  p-=4;                         /* win64 abi argsave nonsense */
+  *(--p) = (LispObj)windows_halt;
+  context->Rsp = (DWORD64)p;
+  context->Rip = (DWORD64)handler;
+  context->Rcx = (DWORD64)new_ep;
+  context->Rdx = (DWORD64)tcr;
+#else
+  p-=4;                          /* args on stack, stack aligned */
+  p[0] = (LispObj)new_ep;
+  p[1] = (LispObj)tcr;
+  *(--p) = (LispObj)windows_halt;
+  context->Esp = (DWORD)p;
+  context->Eip = (DWORD)handler;
+#ifdef WIN32_ES_HACK
+  context->SegEs = context->SegDs;
+#endif
+#endif
+  context->EFlags &= ~0x400;  /* clear direction flag */
+}
+
+void
+prepare_to_handle_windows_exception_on_foreign_stack(TCR *tcr,
+                                                     CONTEXT *context,
+                                                     void *handler,
+                                                     EXCEPTION_POINTERS *original_ep)
+{
+  LispObj foreign_rsp = 
+    (LispObj) (tcr->foreign_sp - 128) & ~15;
+  CONTEXT *new_context;
+  siginfo_t *new_info;
+  EXCEPTION_POINTERS *new_ep;
+
+  new_context = ((CONTEXT *)(foreign_rsp&~15))-1;
+  *new_context = *context;
+  foreign_rsp = (LispObj)new_context;
+  new_info = ((siginfo_t *)(foreign_rsp&~15))-1;
+  *new_info = *original_ep->ExceptionRecord;
+  foreign_rsp = (LispObj)new_info;
+  new_ep = ((EXCEPTION_POINTERS *)(foreign_rsp&~15))-1;
+  foreign_rsp = (LispObj)new_ep & ~15;
+  new_ep->ContextRecord = new_context;
+  new_ep->ExceptionRecord = new_info;
+  setup_exception_handler_call(context,foreign_rsp,handler,new_ep, tcr);
+}
+
+LONG CALLBACK
+windows_arbstack_exception_handler(EXCEPTION_POINTERS *exception_pointers)
+{
+  extern void ensure_safe_for_string_operations(void);
+  DWORD code = exception_pointers->ExceptionRecord->ExceptionCode;
+
+
+  
+  if ((code & 0x80000000L) == 0) {
+    return EXCEPTION_CONTINUE_SEARCH;
+  } else {
+    TCR *tcr = get_interrupt_tcr(false);
+    area *cs = tcr->cs_area;
+    BytePtr current_sp = (BytePtr) current_stack_pointer();
+    CONTEXT *context = exception_pointers->ContextRecord;
+    
+    ensure_safe_for_string_operations();
+
+    if ((current_sp >= cs->low) &&
+        (current_sp < cs->high)) {
+      debug_show_registers(context, exception_pointers->ExceptionRecord, 0);
+      FBug(context, "Exception on foreign stack\n");
+      return EXCEPTION_CONTINUE_EXECUTION;
+    }
+
+    prepare_to_handle_windows_exception_on_foreign_stack(tcr,
+                                                         context,
+                                                         windows_exception_handler,
+                                                         exception_pointers);
+    return EXCEPTION_CONTINUE_EXECUTION;
+  }
+}
+
+
+void
+install_pmcl_exception_handlers()
+{
+  AddVectoredExceptionHandler(1,windows_arbstack_exception_handler);
+}
+#else
+void
+install_pmcl_exception_handlers()
+{
+#ifndef DARWIN  
+  void *handler = (void *)
+#ifdef USE_SIGALTSTACK
+    altstack_signal_handler
+#else
+    arbstack_signal_handler;
+#endif
+  ;
+  install_signal_handler(SIGILL, handler);
+  
+  install_signal_handler(SIGBUS, handler);
+  install_signal_handler(SIGSEGV,handler);
+  install_signal_handler(SIGFPE, handler);
+#endif
+  
+  install_signal_handler(SIGNAL_FOR_PROCESS_INTERRUPT,
+#ifdef USE_SIGALTSTACK
+			 altstack_interrupt_handler
+#else
+                         arbstack_interrupt_handler
+#endif
+);
+  signal(SIGPIPE, SIG_IGN);
+}
+#endif
+
+#ifndef WINDOWS
+#ifndef USE_SIGALTSTACK
+void
+arbstack_suspend_resume_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_interrupt_tcr(false);
+  if (tcr != NULL) {
+    area *vs = tcr->vs_area;
+    BytePtr current_sp = (BytePtr) current_stack_pointer();
+    
+    if ((current_sp >= vs->low) &&
+        (current_sp < vs->high)) {
+      return
+        handle_signal_on_foreign_stack(tcr,
+                                       suspend_resume_handler,
+                                       signum,
+                                       info,
+                                       context,
+                                       (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                       ,gs_was_tcr
+#endif
+                                       );
+    } else {
+      /* If we're not on the value stack, we pretty much have to be on
+         the C stack.  Just run the handler. */
+#ifdef DARWIN_GS_HACK
+      if (gs_was_tcr) {
+        set_gs_address(tcr);
+      }
+#endif
+    }
+  }
+  suspend_resume_handler(signum, info, context);
+}
+
+
+#else /* altstack works */
+void
+altstack_suspend_resume_handler(int signum, siginfo_t *info, ExceptionInformation  *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR* tcr = get_tcr(true);
+  handle_signal_on_foreign_stack(tcr,
+                                 suspend_resume_handler,
+                                 signum,
+                                 info,
+                                 context,
+                                 (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 ,gs_was_tcr
+#endif
+                                 );
+}
+#endif
+#endif
+
+
+/* This should only be called when the tcr_area_lock is held */
+void
+empty_tcr_stacks(TCR *tcr)
+{
+  if (tcr) {
+    area *a;
+
+    tcr->valence = TCR_STATE_FOREIGN;
+    a = tcr->vs_area;
+    if (a) {
+      a->active = a->high;
+    }
+    a = tcr->ts_area;
+    if (a) {
+      a->active = a->high;
+    }
+    a = tcr->cs_area;
+    if (a) {
+      a->active = a->high;
+    }
+  }
+}
+
+#ifdef WINDOWS
+void
+thread_kill_handler(int signum, siginfo_t *info, ExceptionInformation *xp)
+{
+}
+#else
+void
+thread_kill_handler(int signum, siginfo_t *info, ExceptionInformation *xp)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_tcr(false);
+  sigset_t mask;
+
+  sigemptyset(&mask);
+
+  empty_tcr_stacks(tcr);
+
+  pthread_sigmask(SIG_SETMASK,&mask,NULL);
+  pthread_exit(NULL);
+}
+#endif
+
+#ifndef WINDOWS
+#ifndef USE_SIGALTSTACK
+void
+arbstack_thread_kill_handler(int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR *tcr = get_interrupt_tcr(false);
+  area *vs = tcr->vs_area;
+  BytePtr current_sp = (BytePtr) current_stack_pointer();
+
+  if ((current_sp >= vs->low) &&
+      (current_sp < vs->high)) {
+    handle_signal_on_foreign_stack(tcr,
+                                   thread_kill_handler,
+                                   signum,
+                                   info,
+                                   context,
+                                   (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                   ,gs_was_tcr
+#endif
+                                   );
+  } else {
+    /* If we're not on the value stack, we pretty much have to be on
+       the C stack.  Just run the handler. */
+#ifdef DARWIN_GS_HACK
+    if (gs_was_tcr) {
+      set_gs_address(tcr);
+    }
+#endif
+    thread_kill_handler(signum, info, context);
+  }
+}
+
+
+#else
+void
+altstack_thread_kill_handler(int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR* tcr = get_tcr(true);
+  handle_signal_on_foreign_stack(tcr,
+                                 thread_kill_handler,
+                                 signum,
+                                 info,
+                                 context,
+                                 (LispObj)__builtin_return_address(0)
+#ifdef DARWIN_GS_HACK
+                                 ,gs_was_tcr
+#endif
+                                 );
+}
+#endif
+#endif
+
+#ifdef USE_SIGALTSTACK
+#define SUSPEND_RESUME_HANDLER altstack_suspend_resume_handler
+#define THREAD_KILL_HANDLER altstack_thread_kill_handler
+#else
+#define SUSPEND_RESUME_HANDLER arbstack_suspend_resume_handler
+#define THREAD_KILL_HANDLER arbstack_thread_kill_handler
+#endif
+
+#ifdef WINDOWS
+void
+thread_signal_setup()
+{
+}
+#else
+void
+thread_signal_setup()
+{
+  thread_suspend_signal = SIG_SUSPEND_THREAD;
+  thread_kill_signal = SIG_KILL_THREAD;
+
+  install_signal_handler(thread_suspend_signal, (void *)SUSPEND_RESUME_HANDLER);
+  install_signal_handler(thread_kill_signal, (void *)THREAD_KILL_HANDLER);
+}
+#endif
+
+void
+enable_fp_exceptions()
+{
+}
+
+void
+exception_init()
+{
+  install_pmcl_exception_handlers();
+}
+
+void
+adjust_exception_pc(ExceptionInformation *xp, int delta)
+{
+  xpPC(xp) += delta;
+}
+
+/*
+  Lower (move toward 0) the "end" of the soft protected area associated
+  with a by a page, if we can.
+*/
+
+void
+
+adjust_soft_protection_limit(area *a)
+{
+  char *proposed_new_soft_limit = a->softlimit - 4096;
+  protected_area_ptr p = a->softprot;
+  
+  if (proposed_new_soft_limit >= (p->start+16384)) {
+    p->end = proposed_new_soft_limit;
+    p->protsize = p->end-p->start;
+    a->softlimit = proposed_new_soft_limit;
+  }
+  protect_area(p);
+}
+
+void
+restore_soft_stack_limit(unsigned restore_tsp)
+{
+  TCR *tcr = get_tcr(false);
+  area *a;
+ 
+  if (restore_tsp) {
+    a = tcr->ts_area;
+  } else {
+    a = tcr->vs_area;
+  }
+  adjust_soft_protection_limit(a);
+}
+
+
+#ifdef USE_SIGALTSTACK
+void
+setup_sigaltstack(area *a)
+{
+  stack_t stack;
+  stack.ss_sp = a->low;
+  a->low += SIGSTKSZ*8;
+  stack.ss_size = SIGSTKSZ*8;
+  stack.ss_flags = 0;
+  mmap(stack.ss_sp,stack.ss_size, PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_ANON|MAP_PRIVATE,-1,0);
+  if (sigaltstack(&stack, NULL) != 0) {
+    perror("sigaltstack");
+    exit(-1);
+  }
+}
+#endif
+
+extern opcode egc_write_barrier_start, egc_write_barrier_end,
+  egc_set_hash_key_conditional, egc_set_hash_key_conditional_success_test,
+  egc_set_hash_key_conditional_retry,
+  egc_store_node_conditional_success_end, egc_store_node_conditional_retry,
+  egc_store_node_conditional_success_test,egc_store_node_conditional,
+  egc_set_hash_key, egc_gvset, egc_rplacd;
+
+/* We use (extremely) rigidly defined instruction sequences for consing,
+   mostly so that 'pc_luser_xp()' knows what to do if a thread is interrupted
+   while consing.
+
+   Note that we can usually identify which of these instructions is about
+   to be executed by a stopped thread without comparing all of the bytes
+   to those at the stopped program counter, but we generally need to
+   know the sizes of each of these instructions.
+*/
+
+#ifdef X8664
+opcode load_allocptr_reg_from_tcr_save_allocptr_instruction[] =
+#ifdef TCR_IN_GPR
+  {0x49,0x8b,0x9b,0xd8,0x00,0x00,0x00}
+#else
+  {0x65,0x48,0x8b,0x1c,0x25,0xd8,0x00,0x00,0x00}
+#endif
+;
+opcode compare_allocptr_reg_to_tcr_save_allocbase_instruction[] =
+#ifdef TCR_IN_GPR
+  {0x49,0x3b,0x9b,0xe0,0x00,0x00,0x00}
+#else
+  {0x65,0x48,0x3b,0x1c,0x25,0xe0,0x00,0x00,0x00}
+#endif
+
+;
+opcode branch_around_alloc_trap_instruction[] =
+  {0x77,0x02};
+opcode alloc_trap_instruction[] =
+  {0xcd,0xc5};
+opcode clear_tcr_save_allocptr_tag_instruction[] =
+#ifdef TCR_IN_GPR
+  {0x41,0x80,0xa3,0xd8,0x00,0x00,0x00,0xf0}
+#else
+  {0x65,0x80,0x24,0x25,0xd8,0x00,0x00,0x00,0xf0}
+#endif
+;
+opcode set_allocptr_header_instruction[] =
+  {0x48,0x89,0x43,0xf3};
+
+
+alloc_instruction_id
+recognize_alloc_instruction(pc program_counter)
+{
+  switch(program_counter[0]) {
+  case 0xcd: return ID_alloc_trap_instruction;
+  /* 0x7f is jg, which we used to use here instead of ja */
+  case 0x7f:
+  case 0x77: return ID_branch_around_alloc_trap_instruction;
+  case 0x48: return ID_set_allocptr_header_instruction;
+#ifdef TCR_IN_GPR
+  case 0x41: return ID_clear_tcr_save_allocptr_tag_instruction;
+  case 0x49:
+    switch(program_counter[1]) {
+    case 0x8b: return ID_load_allocptr_reg_from_tcr_save_allocptr_instruction;
+    case 0x3b: return ID_compare_allocptr_reg_to_tcr_save_allocbase_instruction;
+    }
+#else
+  case 0x65: 
+    switch(program_counter[1]) {
+    case 0x80: return ID_clear_tcr_save_allocptr_tag_instruction;
+    case 0x48:
+      switch(program_counter[2]) {
+      case 0x3b: return ID_compare_allocptr_reg_to_tcr_save_allocbase_instruction;
+      case 0x8b: return ID_load_allocptr_reg_from_tcr_save_allocptr_instruction;
+      }
+    }
+#endif
+  default: break;
+  }
+  return ID_unrecognized_alloc_instruction;
+}
+#endif
+#ifdef X8632
+/* The lisp assembler might use both a modrm byte and a sib byte to
+   encode a memory operand that contains a displacement but no
+   base or index.  Using the sib byte is necessary for 64-bit code,
+   since the sib-less form is used to indicate %rip-relative addressing
+   on x8664.  On x8632, it's not necessary, slightly suboptimal, and
+   doesn't match what we expect; until that's fixed, we may need to
+   account for this extra byte when adjusting the PC */
+#define LISP_ASSEMBLER_EXTRA_SIB_BYTE
+#ifdef WIN32_ES_HACK
+/* Win32 keeps the TCR in %es */
+#define TCR_SEG_PREFIX 0x26     /* %es: */
+#else
+/* Other platfroms use %fs */
+#define TCR_SEG_PREFIX 0x64     /* %fs: */
+#endif
+opcode load_allocptr_reg_from_tcr_save_allocptr_instruction[] =
+  {TCR_SEG_PREFIX,0x8b,0x0d,0x84,0x00,0x00,0x00};  /* may have extra SIB byte */
+opcode compare_allocptr_reg_to_tcr_save_allocbase_instruction[] =
+  {TCR_SEG_PREFIX,0x3b,0x0d,0x88,0x00,0x00,0x00};  /* may have extra SIB byte */
+opcode branch_around_alloc_trap_instruction[] =
+  {0x77,0x02};                  /* no SIB byte issue */
+opcode alloc_trap_instruction[] =
+  {0xcd,0xc5};                  /* no SIB byte issue */
+opcode clear_tcr_save_allocptr_tag_instruction[] =
+  {TCR_SEG_PREFIX,0x80,0x25,0x84,0x00,0x00,0x00,0xf8}; /* maybe SIB byte */
+opcode set_allocptr_header_instruction[] =
+  {0x0f,0x7e,0x41,0xfa};        /* no SIB byte issue */
+
+alloc_instruction_id
+recognize_alloc_instruction(pc program_counter)
+{
+  switch(program_counter[0]) {
+  case 0xcd: return ID_alloc_trap_instruction;
+  /* 0x7f is jg, which we used to use here instead of ja */
+  case 0x7f:
+  case 0x77: return ID_branch_around_alloc_trap_instruction;
+  case 0x0f: return ID_set_allocptr_header_instruction;
+  case TCR_SEG_PREFIX: 
+    switch(program_counter[1]) {
+    case 0x80: return ID_clear_tcr_save_allocptr_tag_instruction;
+    case 0x3b: return ID_compare_allocptr_reg_to_tcr_save_allocbase_instruction;
+    case 0x8b: return ID_load_allocptr_reg_from_tcr_save_allocptr_instruction;
+    }
+  }
+  return ID_unrecognized_alloc_instruction;
+}
+#endif      
+
+void
+pc_luser_xp(ExceptionInformation *xp, TCR *tcr, signed_natural *interrupt_displacement)
+{
+  pc program_counter = (pc)xpPC(xp);
+  int allocptr_tag = fulltag_of((LispObj)(tcr->save_allocptr));
+
+  if (allocptr_tag != 0) {
+    alloc_instruction_id state = recognize_alloc_instruction(program_counter);
+    signed_natural 
+      disp = (allocptr_tag == fulltag_cons) ?
+      sizeof(cons) - fulltag_cons :
+#ifdef X8664
+      xpGPR(xp,Iimm1)
+#else
+      xpGPR(xp,Iimm0)
+#endif
+      ;
+    LispObj new_vector;
+
+    if ((state == ID_unrecognized_alloc_instruction) ||
+        ((state == ID_set_allocptr_header_instruction) &&
+         (allocptr_tag != fulltag_misc))) {
+      Bug(xp, "Can't determine state of thread 0x" LISP ", interrupted during memory allocation", tcr);
+    }
+    switch(state) {
+    case ID_set_allocptr_header_instruction:
+      /* We were consing a vector and we won.  Set the header of the
+         new vector (in the allocptr register) to the header in %rax
+         (%mm0 on ia32) and skip over this instruction, then fall into
+         the next case. */
+      new_vector = xpGPR(xp,Iallocptr);
+      deref(new_vector,0) = 
+#ifdef X8664
+        xpGPR(xp,Iimm0)
+#else
+        xpMMXreg(xp,Imm0)
+#endif
+        ;
+      
+      xpPC(xp) += sizeof(set_allocptr_header_instruction);
+
+      /* Fall thru */
+    case ID_clear_tcr_save_allocptr_tag_instruction:
+      tcr->save_allocptr = (void *)(((LispObj)tcr->save_allocptr) & ~fulltagmask);
+#ifdef LISP_ASSEMBLER_EXTRA_SIB_BYTE
+      if (((pc)(xpPC(xp)))[2] == 0x24) {
+        xpPC(xp) += 1;
+      }
+#endif
+      xpPC(xp) += sizeof(clear_tcr_save_allocptr_tag_instruction);
+
+      break;
+    case ID_alloc_trap_instruction:
+      /* If we're looking at another thread, we're pretty much committed to
+         taking the trap.  We don't want the allocptr register to be pointing
+         into the heap, so make it point to (- VOID_ALLOCPTR disp), where 'disp'
+         was determined above. 
+      */
+      if (interrupt_displacement == NULL) {
+        xpGPR(xp,Iallocptr) = VOID_ALLOCPTR - disp;
+        tcr->save_allocptr = (void *)(VOID_ALLOCPTR - disp);
+      } else {
+        /* Back out, and tell the caller how to resume the allocation attempt */
+        *interrupt_displacement = disp;
+        xpGPR(xp,Iallocptr) = VOID_ALLOCPTR;
+        tcr->save_allocptr += disp;
+#ifdef LISP_ASSEMBLER_EXTRA_SIB_BYTE
+        /* This assumes that TCR_SEG_PREFIX can't appear 
+           anywhere but at the beginning of one of these
+           magic allocation-sequence instructions. */
+        xpPC(xp) -= (sizeof(branch_around_alloc_trap_instruction)+
+                     sizeof(compare_allocptr_reg_to_tcr_save_allocbase_instruction));
+        if (*((pc)(xpPC(xp))) == TCR_SEG_PREFIX) {
+          xpPC(xp) -= sizeof(load_allocptr_reg_from_tcr_save_allocptr_instruction);
+        } else {
+          xpPC(xp) -= (sizeof(load_allocptr_reg_from_tcr_save_allocptr_instruction) + 2);
+        }
+        
+#else
+        xpPC(xp) -= (sizeof(branch_around_alloc_trap_instruction)+
+                     sizeof(compare_allocptr_reg_to_tcr_save_allocbase_instruction) +
+                     sizeof(load_allocptr_reg_from_tcr_save_allocptr_instruction));
+#endif
+      }
+      break;
+    case ID_branch_around_alloc_trap_instruction:
+      /* If we'd take the branch - which is a "ja" - around the alloc trap,
+         we might as well finish the allocation.  Otherwise, back out of the
+         attempt. */
+      {
+        int flags = (int)eflags_register(xp);
+        
+        if ((!(flags & (1 << X86_ZERO_FLAG_BIT))) &&
+	    (!(flags & (1 << X86_CARRY_FLAG_BIT)))) {
+          /* The branch (ja) would have been taken.  Emulate taking it. */
+          xpPC(xp) += (sizeof(branch_around_alloc_trap_instruction)+
+                       sizeof(alloc_trap_instruction));
+          if (allocptr_tag == fulltag_misc) {
+            /* Slap the header on the new uvector */
+            new_vector = xpGPR(xp,Iallocptr);
+            deref(new_vector,0) = xpGPR(xp,Iimm0);
+            xpPC(xp) += sizeof(set_allocptr_header_instruction);
+          }
+          tcr->save_allocptr = (void *)(((LispObj)tcr->save_allocptr) & ~fulltagmask);
+#ifdef LISP_ASSEMBLER_EXTRA_SIB_BYTE
+          if (((pc)xpPC(xp))[2] == 0x24) {
+            xpPC(xp) += 1;
+          }
+#endif
+          xpPC(xp) += sizeof(clear_tcr_save_allocptr_tag_instruction);
+        } else {
+          /* Back up */
+          xpPC(xp) -= (sizeof(compare_allocptr_reg_to_tcr_save_allocbase_instruction) +
+                       sizeof(load_allocptr_reg_from_tcr_save_allocptr_instruction));
+#ifdef LISP_ASSEMBLER_EXTRA_SIB_BYTE
+          if (*((pc)(xpPC(xp))) != TCR_SEG_PREFIX) {
+            /* skipped two instructions with extra SIB byte */
+            xpPC(xp) -= 2;
+          }
+#endif
+          xpGPR(xp,Iallocptr) = VOID_ALLOCPTR;
+          if (interrupt_displacement) {
+            *interrupt_displacement = disp;
+            tcr->save_allocptr += disp;
+          } else {
+            tcr->save_allocptr = (void *)(VOID_ALLOCPTR-disp);
+          }
+        }
+      }
+      break;
+    case ID_compare_allocptr_reg_to_tcr_save_allocbase_instruction:
+      xpGPR(xp,Iallocptr) = VOID_ALLOCPTR;
+      xpPC(xp) -= sizeof(load_allocptr_reg_from_tcr_save_allocptr_instruction);
+#ifdef LISP_ASSEMBLER_EXTRA_SIB_BYTE
+      if (*((pc)xpPC(xp)) != TCR_SEG_PREFIX) {
+        xpPC(xp) -= 1;
+      }
+#endif
+      /* Fall through */
+    case ID_load_allocptr_reg_from_tcr_save_allocptr_instruction:
+      if (interrupt_displacement) {
+        tcr->save_allocptr += disp;
+        *interrupt_displacement = disp;
+      } else {
+        tcr->save_allocptr = (void *)(VOID_ALLOCPTR-disp);
+      }
+      break;
+    default: 
+      break;
+    }
+    return;
+  }
+  if ((program_counter >= &egc_write_barrier_start) &&
+      (program_counter < &egc_write_barrier_end)) {
+    LispObj *ea = 0, val, root = 0;
+    bitvector refbits = (bitvector)(lisp_global(REFBITS));
+    Boolean need_store = true, need_check_memo = true, need_memoize_root = false;
+
+    if (program_counter >= &egc_set_hash_key_conditional) {
+      if (program_counter <= &egc_set_hash_key_conditional_retry) {
+        return;
+      }
+      if ((program_counter < &egc_set_hash_key_conditional_success_test) ||
+          ((program_counter == &egc_set_hash_key_conditional_success_test) &&
+           !(eflags_register(xp) & (1 << X86_ZERO_FLAG_BIT)))) {
+        /* Back up the PC, try again */
+        xpPC(xp) = (LispObj) &egc_set_hash_key_conditional_retry;
+        return;
+      }
+      /* The conditional store succeeded.  Set the refbit, return to ra0 */
+      val = xpGPR(xp,Iarg_z);
+#ifdef X8664
+      root = xpGPR(xp,Iarg_x);
+      ea = (LispObj*)(root + (unbox_fixnum((signed_natural) xpGPR(xp,Itemp0))));
+#else
+      root = xpGPR(xp,Itemp1);
+      ea = (LispObj *)(root + misc_data_offset + xpGPR(xp,Itemp0));
+#endif
+      need_memoize_root = true;
+      need_store = false;
+      xpGPR(xp,Iarg_z) = t_value;
+    } else if (program_counter >= &egc_store_node_conditional) {
+      if (program_counter <= &egc_store_node_conditional_retry) {
+        return;
+      }
+      if ((program_counter < &egc_store_node_conditional_success_test) ||
+          ((program_counter == &egc_store_node_conditional_success_test) &&
+           !(eflags_register(xp) & (1 << X86_ZERO_FLAG_BIT)))) {
+        /* Back up the PC, try again */
+        xpPC(xp) = (LispObj) &egc_store_node_conditional_retry;
+        return;
+      }
+      if (program_counter >= &egc_store_node_conditional_success_end) {
+        return;
+      }
+
+      /* The conditional store succeeded.  Set the refbit, return to ra0 */
+      val = xpGPR(xp,Iarg_z);
+#ifdef X8664
+      ea = (LispObj*)(xpGPR(xp,Iarg_x) + (unbox_fixnum((signed_natural)
+                                                       xpGPR(xp,Itemp0))));
+#else
+      ea = (LispObj *)(misc_data_offset + xpGPR(xp,Itemp1) + xpGPR(xp,Itemp0));
+#endif
+      xpGPR(xp,Iarg_z) = t_value;
+      need_store = false;
+    } else if (program_counter >= &egc_set_hash_key) {
+#ifdef X8664
+      root = xpGPR(xp,Iarg_x);
+#else
+      root = xpGPR(xp,Itemp0);
+#endif
+      ea = (LispObj *) (root+xpGPR(xp,Iarg_y)+misc_data_offset);
+      val = xpGPR(xp,Iarg_z);
+      need_memoize_root = true;
+    } else if (program_counter >= &egc_gvset) {
+#ifdef X8664
+      ea = (LispObj *) (xpGPR(xp,Iarg_x)+xpGPR(xp,Iarg_y)+misc_data_offset);
+#else
+      ea = (LispObj *) (xpGPR(xp,Itemp0)+xpGPR(xp,Iarg_y)+misc_data_offset);
+#endif
+      val = xpGPR(xp,Iarg_z);
+    } else if (program_counter >= &egc_rplacd) {
+      ea = (LispObj *) untag(xpGPR(xp,Iarg_y));
+      val = xpGPR(xp,Iarg_z);
+    } else {                      /* egc_rplaca */
+      ea =  ((LispObj *) untag(xpGPR(xp,Iarg_y)))+1;
+      val = xpGPR(xp,Iarg_z);
+    }
+    if (need_store) {
+      *ea = val;
+    }
+    if (need_check_memo) {
+      natural  bitnumber = area_dnode(ea, lisp_global(REF_BASE));
+      if ((bitnumber < lisp_global(OLDSPACE_DNODE_COUNT)) &&
+          ((LispObj)ea < val)) {
+        atomic_set_bit(refbits, bitnumber);
+        if (need_memoize_root) {
+          bitnumber = area_dnode(root, lisp_global(REF_BASE));
+          atomic_set_bit(refbits, bitnumber);
+        }
+      }
+    }
+    {
+      /* These subprimitives are called via CALL/RET; need
+         to pop the return address off the stack and set
+         the PC there. */
+      LispObj *sp = (LispObj *)xpGPR(xp,Isp), ra = *sp++;
+      xpPC(xp) = ra;
+      xpGPR(xp,Isp)=(LispObj)sp;
+    }
+    return;
+  }
+}
+
+
+void
+normalize_tcr(ExceptionInformation *xp, TCR *tcr, Boolean is_other_tcr)
+{
+  void *cur_allocptr = (void *)(tcr->save_allocptr);
+  LispObj lisprsp;
+  area *a;
+
+  if (xp) {
+    if (is_other_tcr) {
+      pc_luser_xp(xp, tcr, NULL);
+    }
+    a = tcr->vs_area;
+    lisprsp = xpGPR(xp, Isp);
+    if (((BytePtr)lisprsp >= a->low) &&
+	((BytePtr)lisprsp < a->high)) {
+      a->active = (BytePtr)lisprsp;
+    } else {
+      a->active = (BytePtr) tcr->save_vsp;
+    }
+    a = tcr->ts_area;
+    a->active = (BytePtr) tcr->save_tsp;
+  } else {
+    /* In ff-call; get area active pointers from tcr */
+    tcr->vs_area->active = (BytePtr) tcr->save_vsp;
+    tcr->ts_area->active = (BytePtr) tcr->save_tsp;
+  }
+  if (cur_allocptr) {
+    update_bytes_allocated(tcr, cur_allocptr);
+  }
+  tcr->save_allocbase = (void *)VOID_ALLOCPTR;
+  if (fulltag_of((LispObj)(tcr->save_allocptr)) == 0) {
+    tcr->save_allocptr = (void *)VOID_ALLOCPTR;
+  }
+}
+
+
+/* Suspend and "normalize" other tcrs, then call a gc-like function
+   in that context.  Resume the other tcrs, then return what the
+   function returned */
+
+TCR *gc_tcr = NULL;
+
+
+signed_natural
+gc_like_from_xp(ExceptionInformation *xp, 
+                signed_natural(*fun)(TCR *, signed_natural), 
+                signed_natural param)
+{
+  TCR *tcr = get_tcr(false), *other_tcr;
+  int result;
+  signed_natural inhibit;
+
+  suspend_other_threads(true);
+  inhibit = (signed_natural)(lisp_global(GC_INHIBIT_COUNT));
+  if (inhibit != 0) {
+    if (inhibit > 0) {
+      lisp_global(GC_INHIBIT_COUNT) = (LispObj)(-inhibit);
+    }
+    resume_other_threads(true);
+    gc_deferred++;
+    return 0;
+  }
+  gc_deferred = 0;
+
+  gc_tcr = tcr;
+
+  /* This is generally necessary if the current thread invoked the GC
+     via an alloc trap, and harmless if the GC was invoked via a GC
+     trap.  (It's necessary in the first case because the "allocptr"
+     register - %rbx - may be pointing into the middle of something
+     below tcr->save_allocbase, and we wouldn't want the GC to see
+     that bogus pointer.) */
+  xpGPR(xp, Iallocptr) = VOID_ALLOCPTR; 
+
+  normalize_tcr(xp, tcr, false);
+
+
+  for (other_tcr = tcr->next; other_tcr != tcr; other_tcr = other_tcr->next) {
+    if (other_tcr->pending_exception_context) {
+      other_tcr->gc_context = other_tcr->pending_exception_context;
+    } else if (other_tcr->valence == TCR_STATE_LISP) {
+      other_tcr->gc_context = other_tcr->suspend_context;
+    } else {
+      /* no pending exception, didn't suspend in lisp state:
+	 must have executed a synchronous ff-call. 
+      */
+      other_tcr->gc_context = NULL;
+    }
+    normalize_tcr(other_tcr->gc_context, other_tcr, true);
+  }
+    
+
+
+  result = fun(tcr, param);
+
+  other_tcr = tcr;
+  do {
+    other_tcr->gc_context = NULL;
+    other_tcr = other_tcr->next;
+  } while (other_tcr != tcr);
+
+  gc_tcr = NULL;
+
+  resume_other_threads(true);
+
+  return result;
+
+}
+
+signed_natural
+purify_from_xp(ExceptionInformation *xp, signed_natural param)
+{
+  return gc_like_from_xp(xp, purify, param);
+}
+
+signed_natural
+impurify_from_xp(ExceptionInformation *xp, signed_natural param)
+{
+  return gc_like_from_xp(xp, impurify, param);
+}
+
+/* Returns #bytes freed by invoking GC */
+
+signed_natural
+gc_from_tcr(TCR *tcr, signed_natural param)
+{
+  area *a;
+  BytePtr oldfree, newfree;
+  BytePtr oldend, newend;
+
+#if 0
+  fprintf(dbgout, "Start GC  in 0x" LISP "\n", tcr);
+#endif
+  a = active_dynamic_area;
+  oldend = a->high;
+  oldfree = a->active;
+  gc(tcr, param);
+  newfree = a->active;
+  newend = a->high;
+#if 0
+  fprintf(dbgout, "End GC  in 0x" LISP "\n", tcr);
+#endif
+  return ((oldfree-newfree)+(newend-oldend));
+}
+
+signed_natural
+gc_from_xp(ExceptionInformation *xp, signed_natural param)
+{
+  signed_natural status = gc_like_from_xp(xp, gc_from_tcr, param);
+
+  freeGCptrs();
+  return status;
+}
+
+#ifdef DARWIN
+
+#define TCR_FROM_EXCEPTION_PORT(p) ((TCR *)((natural)p))
+#define TCR_TO_EXCEPTION_PORT(tcr) ((mach_port_t)((natural)(tcr)))
+
+extern void pseudo_sigreturn(void);
+
+
+
+#define LISP_EXCEPTIONS_HANDLED_MASK \
+ (EXC_MASK_SOFTWARE | EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC)
+
+/* (logcount LISP_EXCEPTIONS_HANDLED_MASK) */
+#define NUM_LISP_EXCEPTIONS_HANDLED 4 
+
+typedef struct {
+  int foreign_exception_port_count;
+  exception_mask_t         masks[NUM_LISP_EXCEPTIONS_HANDLED];
+  mach_port_t              ports[NUM_LISP_EXCEPTIONS_HANDLED];
+  exception_behavior_t behaviors[NUM_LISP_EXCEPTIONS_HANDLED];
+  thread_state_flavor_t  flavors[NUM_LISP_EXCEPTIONS_HANDLED];
+} MACH_foreign_exception_state;
+
+
+
+
+/*
+  Mach's exception mechanism works a little better than its signal
+  mechanism (and, not incidentally, it gets along with GDB a lot
+  better.
+
+  Initially, we install an exception handler to handle each native
+  thread's exceptions.  This process involves creating a distinguished
+  thread which listens for kernel exception messages on a set of
+  0 or more thread exception ports.  As threads are created, they're
+  added to that port set; a thread's exception port is destroyed
+  (and therefore removed from the port set) when the thread exits.
+
+  A few exceptions can be handled directly in the handler thread;
+  others require that we resume the user thread (and that the
+  exception thread resumes listening for exceptions.)  The user
+  thread might eventually want to return to the original context
+  (possibly modified somewhat.)
+
+  As it turns out, the simplest way to force the faulting user
+  thread to handle its own exceptions is to do pretty much what
+  signal() does: the exception handlng thread sets up a sigcontext
+  on the user thread's stack and forces the user thread to resume
+  execution as if a signal handler had been called with that
+  context as an argument.  We can use a distinguished UUO at a
+  distinguished address to do something like sigreturn(); that'll
+  have the effect of resuming the user thread's execution in
+  the (pseudo-) signal context.
+
+  Since:
+    a) we have miles of code in C and in Lisp that knows how to
+    deal with Linux sigcontexts
+    b) Linux sigcontexts contain a little more useful information
+    (the DAR, DSISR, etc.) than their Darwin counterparts
+    c) we have to create a sigcontext ourselves when calling out
+    to the user thread: we aren't really generating a signal, just
+    leveraging existing signal-handling code.
+
+  we create a Linux sigcontext struct.
+
+  Simple ?  Hopefully from the outside it is ...
+
+  We want the process of passing a thread's own context to it to
+  appear to be atomic: in particular, we don't want the GC to suspend
+  a thread that's had an exception but has not yet had its user-level
+  exception handler called, and we don't want the thread's exception
+  context to be modified by a GC while the Mach handler thread is
+  copying it around.  On Linux (and on Jaguar), we avoid this issue
+  because (a) the kernel sets up the user-level signal handler and
+  (b) the signal handler blocks signals (including the signal used
+  by the GC to suspend threads) until tcr->xframe is set up.
+
+  The GC and the Mach server thread therefore contend for the lock
+  "mach_exception_lock".  The Mach server thread holds the lock
+  when copying exception information between the kernel and the
+  user thread; the GC holds this lock during most of its execution
+  (delaying exception processing until it can be done without
+  GC interference.)
+
+*/
+
+#ifdef PPC64
+#define	C_REDZONE_LEN		320
+#define	C_STK_ALIGN             32
+#else
+#define	C_REDZONE_LEN		224
+#define	C_STK_ALIGN		16
+#endif
+#define C_PARAMSAVE_LEN		64
+#define	C_LINKAGE_LEN		48
+
+#define TRUNC_DOWN(a,b,c)  (((((natural)a)-(b))/(c)) * (c))
+
+void
+fatal_mach_error(char *format, ...);
+
+#define MACH_CHECK_ERROR(context,x) if (x != KERN_SUCCESS) {fatal_mach_error("Mach error while %s : %d", context, x);}
+
+
+void
+restore_mach_thread_state(mach_port_t thread, ExceptionInformation *pseudosigcontext)
+{
+  kern_return_t kret;
+#if WORD_SIZE == 64
+  MCONTEXT_T mc = UC_MCONTEXT(pseudosigcontext);
+#else
+  mcontext_t mc = UC_MCONTEXT(pseudosigcontext);
+#endif
+
+  /* Set the thread's FP state from the pseudosigcontext */
+#if WORD_SIZE == 64
+  kret = thread_set_state(thread,
+                          x86_FLOAT_STATE64,
+                          (thread_state_t)&(mc->__fs),
+                          x86_FLOAT_STATE64_COUNT);
+#else
+  kret = thread_set_state(thread,
+                          x86_FLOAT_STATE32,
+                          (thread_state_t)&(mc->__fs),
+                          x86_FLOAT_STATE32_COUNT);
+#endif
+  MACH_CHECK_ERROR("setting thread FP state", kret);
+
+  /* The thread'll be as good as new ... */
+#if WORD_SIZE == 64
+  kret = thread_set_state(thread,
+                          x86_THREAD_STATE64,
+                          (thread_state_t)&(mc->__ss),
+                          x86_THREAD_STATE64_COUNT);
+#else
+  kret = thread_set_state(thread, 
+                          x86_THREAD_STATE32,
+                          (thread_state_t)&(mc->__ss),
+                          x86_THREAD_STATE32_COUNT);
+#endif
+  MACH_CHECK_ERROR("setting thread state", kret);
+}  
+
+/* This code runs in the exception handling thread, in response
+   to an attempt to execute the UU0 at "pseudo_sigreturn" (e.g.,
+   in response to a call to pseudo_sigreturn() from the specified
+   user thread.
+   Find that context (the user thread's R3 points to it), then
+   use that context to set the user thread's state.  When this
+   function's caller returns, the Mach kernel will resume the
+   user thread.
+*/
+
+kern_return_t
+do_pseudo_sigreturn(mach_port_t thread, TCR *tcr)
+{
+  ExceptionInformation *xp;
+
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "doing pseudo_sigreturn for 0x%x\n",tcr);
+#endif
+  xp = tcr->pending_exception_context;
+  if (xp) {
+    tcr->pending_exception_context = NULL;
+    tcr->valence = TCR_STATE_LISP;
+    restore_mach_thread_state(thread, xp);
+    raise_pending_interrupt(tcr);
+  } else {
+    Bug(NULL, "no xp here!\n");
+  }
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "did pseudo_sigreturn for 0x%x\n",tcr);
+#endif
+  return KERN_SUCCESS;
+}  
+
+ExceptionInformation *
+create_thread_context_frame(mach_port_t thread, 
+			    natural *new_stack_top,
+                            siginfo_t **info_ptr,
+                            TCR *tcr,
+#ifdef X8664
+                            x86_thread_state64_t *ts
+#else
+                            x86_thread_state32_t *ts
+#endif
+                            )
+{
+  mach_msg_type_number_t thread_state_count;
+  ExceptionInformation *pseudosigcontext;
+#ifdef X8664
+  MCONTEXT_T mc;
+#else
+  mcontext_t mc;
+#endif
+  natural stackp;
+
+#ifdef X8664  
+  stackp = (LispObj) find_foreign_rsp(ts->__rsp,tcr->cs_area,tcr);
+  stackp = TRUNC_DOWN(stackp, C_REDZONE_LEN, C_STK_ALIGN);
+#else
+  stackp = (LispObj) find_foreign_rsp(ts->__esp, tcr->cs_area, tcr);
+#endif
+  stackp = TRUNC_DOWN(stackp, sizeof(siginfo_t), C_STK_ALIGN);
+  if (info_ptr) {
+    *info_ptr = (siginfo_t *)stackp;
+  }
+  stackp = TRUNC_DOWN(stackp,sizeof(*pseudosigcontext), C_STK_ALIGN);
+  pseudosigcontext = (ExceptionInformation *) ptr_from_lispobj(stackp);
+
+  stackp = TRUNC_DOWN(stackp, sizeof(*mc), C_STK_ALIGN);
+  mc = (MCONTEXT_T) ptr_from_lispobj(stackp);
+  
+  memmove(&(mc->__ss),ts,sizeof(*ts));
+
+#ifdef X8664
+  thread_state_count = x86_FLOAT_STATE64_COUNT;
+  thread_get_state(thread,
+		   x86_FLOAT_STATE64,
+		   (thread_state_t)&(mc->__fs),
+		   &thread_state_count);
+
+  thread_state_count = x86_EXCEPTION_STATE64_COUNT;
+  thread_get_state(thread,
+                   x86_EXCEPTION_STATE64,
+		   (thread_state_t)&(mc->__es),
+		   &thread_state_count);
+#else
+  thread_state_count = x86_FLOAT_STATE32_COUNT;
+  thread_get_state(thread,
+		   x86_FLOAT_STATE32,
+		   (thread_state_t)&(mc->__fs),
+		   &thread_state_count);
+
+  thread_state_count = x86_EXCEPTION_STATE32_COUNT;
+  thread_get_state(thread,
+                   x86_EXCEPTION_STATE32,
+		   (thread_state_t)&(mc->__es),
+		   &thread_state_count);
+#endif
+
+
+  UC_MCONTEXT(pseudosigcontext) = mc;
+  if (new_stack_top) {
+    *new_stack_top = stackp;
+  }
+  return pseudosigcontext;
+}
+
+/*
+  This code sets up the user thread so that it executes a "pseudo-signal
+  handler" function when it resumes.  Create a fake ucontext struct
+  on the thread's stack and pass it as an argument to the pseudo-signal
+  handler.
+
+  Things are set up so that the handler "returns to" pseudo_sigreturn(),
+  which will restore the thread's context.
+
+  If the handler invokes code that throws (or otherwise never sigreturn()'s
+  to the context), that's fine.
+
+  Actually, check that: throw (and variants) may need to be careful and
+  pop the tcr's xframe list until it's younger than any frame being
+  entered.
+*/
+
+int
+setup_signal_frame(mach_port_t thread,
+		   void *handler_address,
+		   int signum,
+                   int code,
+		   TCR *tcr,
+#ifdef X8664
+                   x86_thread_state64_t *ts
+#else
+                   x86_thread_state32_t *ts
+#endif
+                   )
+{
+#ifdef X8664
+  x86_thread_state64_t new_ts;
+#else
+  x86_thread_state32_t new_ts;
+#endif
+  ExceptionInformation *pseudosigcontext;
+  int  old_valence = tcr->valence;
+  natural stackp, *stackpp;
+  siginfo_t *info;
+
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout,"Setting up exception handling for 0x%x\n", tcr);
+#endif
+  pseudosigcontext = create_thread_context_frame(thread, &stackp, &info, tcr,  ts);
+  bzero(info, sizeof(*info));
+  info->si_code = code;
+  info->si_addr = (void *)(UC_MCONTEXT(pseudosigcontext)->__es.__faultvaddr);
+  info->si_signo = signum;
+  pseudosigcontext->uc_onstack = 0;
+  pseudosigcontext->uc_sigmask = (sigset_t) 0;
+  pseudosigcontext->uc_stack.ss_sp = 0;
+  pseudosigcontext->uc_stack.ss_size = 0;
+  pseudosigcontext->uc_stack.ss_flags = 0;
+  pseudosigcontext->uc_link = NULL;
+  pseudosigcontext->uc_mcsize = sizeof(*UC_MCONTEXT(pseudosigcontext));
+  tcr->pending_exception_context = pseudosigcontext;
+  tcr->valence = TCR_STATE_EXCEPTION_WAIT;
+  
+
+  /* 
+     It seems like we've created a  sigcontext on the thread's
+     stack.  Set things up so that we call the handler (with appropriate
+     args) when the thread's resumed.
+  */
+
+#ifdef X8664
+  new_ts.__rip = (natural) handler_address;
+  stackpp = (natural *)stackp;
+  *--stackpp = (natural)pseudo_sigreturn;
+  stackp = (natural)stackpp;
+  new_ts.__rdi = signum;
+  new_ts.__rsi = (natural)info;
+  new_ts.__rdx = (natural)pseudosigcontext;
+  new_ts.__rcx = (natural)tcr;
+  new_ts.__r8 = (natural)old_valence;
+  new_ts.__rsp = stackp;
+  new_ts.__rflags = ts->__rflags;
+#else
+#define USER_CS 0x17
+#define USER_DS 0x1f
+  bzero(&new_ts, sizeof(new_ts));
+  new_ts.__cs = ts->__cs;
+  new_ts.__ss = ts->__ss;
+  new_ts.__ds = ts->__ds;
+  new_ts.__es = ts->__es;
+  new_ts.__fs = ts->__fs;
+  new_ts.__gs = ts->__gs;
+
+  new_ts.__eip = (natural)handler_address;
+  stackpp = (natural *)stackp;
+  *--stackpp = 0;		/* alignment */
+  *--stackpp = 0;
+  *--stackpp = 0;
+  *--stackpp = (natural)old_valence;
+  *--stackpp = (natural)tcr;
+  *--stackpp = (natural)pseudosigcontext;
+  *--stackpp = (natural)info;
+  *--stackpp = (natural)signum;
+  *--stackpp = (natural)pseudo_sigreturn;
+  stackp = (natural)stackpp;
+  new_ts.__esp = stackp;
+  new_ts.__eflags = ts->__eflags;
+#endif
+
+#ifdef X8664
+  thread_set_state(thread,
+                   x86_THREAD_STATE64,
+                   (thread_state_t)&new_ts,
+                   x86_THREAD_STATE64_COUNT);
+#else
+  thread_set_state(thread, 
+		   x86_THREAD_STATE32,
+		   (thread_state_t)&new_ts,
+		   x86_THREAD_STATE32_COUNT);
+#endif
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout,"Set up exception context for 0x%x at 0x%x\n", tcr, tcr->pending_exception_context);
+#endif
+  return 0;
+}
+
+
+
+
+
+
+/*
+  This function runs in the exception handling thread.  It's
+  called (by this precise name) from the library function "exc_server()"
+  when the thread's exception ports are set up.  (exc_server() is called
+  via mach_msg_server(), which is a function that waits for and dispatches
+  on exception messages from the Mach kernel.)
+
+  This checks to see if the exception was caused by a pseudo_sigreturn()
+  UUO; if so, it arranges for the thread to have its state restored
+  from the specified context.
+
+  Otherwise, it tries to map the exception to a signal number and
+  arranges that the thread run a "pseudo signal handler" to handle
+  the exception.
+
+  Some exceptions could and should be handled here directly.
+*/
+
+/* We need the thread's state earlier on x86_64 than we did on PPC;
+   the PC won't fit in code_vector[1].  We shouldn't try to get it
+   lazily (via catch_exception_raise_state()); until we own the
+   exception lock, we shouldn't have it in userspace (since a GCing
+   thread wouldn't know that we had our hands on it.)
+*/
+
+#ifdef X8664
+#define ts_pc(t) t.__rip
+#else
+#define ts_pc(t) t.__eip
+#endif
+
+
+#define DARWIN_EXCEPTION_HANDLER signal_handler
+
+
+kern_return_t
+catch_exception_raise(mach_port_t exception_port,
+		      mach_port_t thread,
+		      mach_port_t task, 
+		      exception_type_t exception,
+		      exception_data_t code_vector,
+		      mach_msg_type_number_t code_count)
+{
+  int signum = 0, code = *code_vector;
+  TCR *tcr = TCR_FROM_EXCEPTION_PORT(exception_port);
+  kern_return_t kret, call_kret;
+#ifdef X8664
+  x86_thread_state64_t ts;
+#else
+  x86_thread_state32_t ts;
+#endif
+  mach_msg_type_number_t thread_state_count;
+
+
+
+
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "obtaining Mach exception lock in exception thread\n");
+#endif
+
+
+  if (1) {
+#ifdef X8664
+    do {
+      thread_state_count = x86_THREAD_STATE64_COUNT;
+      call_kret = thread_get_state(thread,
+                                   x86_THREAD_STATE64,
+                                   (thread_state_t)&ts,
+                                   &thread_state_count);
+    } while (call_kret == KERN_ABORTED);
+  MACH_CHECK_ERROR("getting thread state",call_kret);
+#else
+    thread_state_count = x86_THREAD_STATE32_COUNT;
+    call_kret = thread_get_state(thread,
+				 x86_THREAD_STATE32,
+				 (thread_state_t)&ts,
+				 &thread_state_count);
+    MACH_CHECK_ERROR("getting thread state",call_kret);
+#endif
+    if (tcr->flags & (1<<TCR_FLAG_BIT_PENDING_EXCEPTION)) {
+      CLR_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_EXCEPTION);
+    } 
+    if ((code == EXC_I386_GPFLT) &&
+        ((natural)(ts_pc(ts)) == (natural)pseudo_sigreturn)) {
+      kret = do_pseudo_sigreturn(thread, tcr);
+#if 0
+      fprintf(dbgout, "Exception return in 0x%x\n",tcr);
+#endif
+    } else if (tcr->flags & (1<<TCR_FLAG_BIT_PROPAGATE_EXCEPTION)) {
+      CLR_TCR_FLAG(tcr,TCR_FLAG_BIT_PROPAGATE_EXCEPTION);
+      kret = 17;
+    } else {
+      switch (exception) {
+      case EXC_BAD_ACCESS:
+        if (code == EXC_I386_GPFLT) {
+          signum = SIGSEGV;
+        } else {
+          signum = SIGBUS;
+        }
+        break;
+        
+      case EXC_BAD_INSTRUCTION:
+        if (code == EXC_I386_GPFLT) {
+          signum = SIGSEGV;
+        } else {
+          signum = SIGILL;
+        }
+        break;
+          
+      case EXC_SOFTWARE:
+        signum = SIGILL;
+        break;
+        
+      case EXC_ARITHMETIC:
+        signum = SIGFPE;
+        break;
+        
+      default:
+        break;
+      }
+      if (signum) {
+        kret = setup_signal_frame(thread,
+                                  (void *)DARWIN_EXCEPTION_HANDLER,
+                                  signum,
+                                  code,
+                                  tcr, 
+                                  &ts);
+#if 0
+        fprintf(dbgout, "Setup pseudosignal handling in 0x%x\n",tcr);
+#endif
+        
+      } else {
+        kret = 17;
+      }
+    }
+  }
+  return kret;
+}
+
+
+
+
+static mach_port_t mach_exception_thread = (mach_port_t)0;
+
+
+/*
+  The initial function for an exception-handling thread.
+*/
+
+void *
+exception_handler_proc(void *arg)
+{
+  extern boolean_t exc_server();
+  mach_port_t p = TCR_TO_EXCEPTION_PORT(arg);
+
+  mach_exception_thread = pthread_mach_thread_np(pthread_self());
+  mach_msg_server(exc_server, 256, p, 0);
+  /* Should never return. */
+  abort();
+}
+
+
+
+void
+mach_exception_thread_shutdown()
+{
+  kern_return_t kret;
+
+  fprintf(dbgout, "terminating Mach exception thread, 'cause exit can't\n");
+  kret = thread_terminate(mach_exception_thread);
+  if (kret != KERN_SUCCESS) {
+    fprintf(dbgout, "Couldn't terminate exception thread, kret = %d\n",kret);
+  }
+}
+
+
+mach_port_t
+mach_exception_port_set()
+{
+  static mach_port_t __exception_port_set = MACH_PORT_NULL;
+  kern_return_t kret;  
+  if (__exception_port_set == MACH_PORT_NULL) {
+
+    kret = mach_port_allocate(mach_task_self(),
+			      MACH_PORT_RIGHT_PORT_SET,
+			      &__exception_port_set);
+    MACH_CHECK_ERROR("allocating thread exception_ports",kret);
+    create_system_thread(0,
+                         NULL,
+                         exception_handler_proc, 
+                         (void *)((natural)__exception_port_set));
+  }
+  return __exception_port_set;
+}
+
+/*
+  Setup a new thread to handle those exceptions specified by
+  the mask "which".  This involves creating a special Mach
+  message port, telling the Mach kernel to send exception
+  messages for the calling thread to that port, and setting
+  up a handler thread which listens for and responds to
+  those messages.
+
+*/
+
+/*
+  Establish the lisp thread's TCR as its exception port, and determine
+  whether any other ports have been established by foreign code for
+  exceptions that lisp cares about.
+
+  If this happens at all, it should happen on return from foreign
+  code and on entry to lisp code via a callback.
+
+  This is a lot of trouble (and overhead) to support Java, or other
+  embeddable systems that clobber their caller's thread exception ports.
+  
+*/
+kern_return_t
+tcr_establish_exception_port(TCR *tcr, mach_port_t thread)
+{
+  kern_return_t kret;
+  MACH_foreign_exception_state *fxs = (MACH_foreign_exception_state *)tcr->native_thread_info;
+  int i;
+  unsigned n = NUM_LISP_EXCEPTIONS_HANDLED;
+  mach_port_t lisp_port = TCR_TO_EXCEPTION_PORT(tcr), foreign_port;
+  exception_mask_t mask = 0;
+
+  kret = thread_swap_exception_ports(thread,
+				     LISP_EXCEPTIONS_HANDLED_MASK,
+				     lisp_port,
+				     EXCEPTION_DEFAULT,
+				     THREAD_STATE_NONE,
+				     fxs->masks,
+				     &n,
+				     fxs->ports,
+				     fxs->behaviors,
+				     fxs->flavors);
+  if (kret == KERN_SUCCESS) {
+    fxs->foreign_exception_port_count = n;
+    for (i = 0; i < n; i ++) {
+      foreign_port = fxs->ports[i];
+
+      if ((foreign_port != lisp_port) &&
+	  (foreign_port != MACH_PORT_NULL)) {
+	mask |= fxs->masks[i];
+      }
+    }
+    tcr->foreign_exception_status = (int) mask;
+  }
+  return kret;
+}
+
+kern_return_t
+tcr_establish_lisp_exception_port(TCR *tcr)
+{
+  return tcr_establish_exception_port(tcr, (mach_port_t)((natural)tcr->native_thread_id));
+}
+
+/*
+  Do this when calling out to or returning from foreign code, if
+  any conflicting foreign exception ports were established when we
+  last entered lisp code.
+*/
+kern_return_t
+restore_foreign_exception_ports(TCR *tcr)
+{
+  exception_mask_t m = (exception_mask_t) tcr->foreign_exception_status;
+  
+  if (m) {
+    MACH_foreign_exception_state *fxs  = 
+      (MACH_foreign_exception_state *) tcr->native_thread_info;
+    int i, n = fxs->foreign_exception_port_count;
+    exception_mask_t tm;
+
+    for (i = 0; i < n; i++) {
+      if ((tm = fxs->masks[i]) & m) {
+	thread_set_exception_ports((mach_port_t)((natural)tcr->native_thread_id),
+				   tm,
+				   fxs->ports[i],
+				   fxs->behaviors[i],
+				   fxs->flavors[i]);
+      }
+    }
+  }
+}
+				   
+
+/*
+  This assumes that a Mach port (to be used as the thread's exception port) whose
+  "name" matches the TCR's 32-bit address has already been allocated.
+*/
+
+kern_return_t
+setup_mach_exception_handling(TCR *tcr)
+{
+  mach_port_t 
+    thread_exception_port = TCR_TO_EXCEPTION_PORT(tcr),
+    task_self = mach_task_self();
+  kern_return_t kret;
+
+  kret = mach_port_insert_right(task_self,
+				thread_exception_port,
+				thread_exception_port,
+				MACH_MSG_TYPE_MAKE_SEND);
+  MACH_CHECK_ERROR("adding send right to exception_port",kret);
+
+  kret = tcr_establish_exception_port(tcr, (mach_port_t)((natural) tcr->native_thread_id));
+  if (kret == KERN_SUCCESS) {
+    mach_port_t exception_port_set = mach_exception_port_set();
+
+    kret = mach_port_move_member(task_self,
+				 thread_exception_port,
+				 exception_port_set);
+  }
+  return kret;
+}
+
+void
+darwin_exception_init(TCR *tcr)
+{
+  void tcr_monitor_exception_handling(TCR*, Boolean);
+  kern_return_t kret;
+  MACH_foreign_exception_state *fxs = 
+    calloc(1, sizeof(MACH_foreign_exception_state));
+  
+  tcr->native_thread_info = (void *) fxs;
+
+  if ((kret = setup_mach_exception_handling(tcr))
+      != KERN_SUCCESS) {
+    fprintf(dbgout, "Couldn't setup exception handler - error = %d\n", kret);
+    terminate_lisp();
+  }
+}
+
+/*
+  The tcr is the "name" of the corresponding thread's exception port.
+  Destroying the port should remove it from all port sets of which it's
+  a member (notably, the exception port set.)
+*/
+void
+darwin_exception_cleanup(TCR *tcr)
+{
+  void *fxs = tcr->native_thread_info;
+  extern Boolean use_mach_exception_handling;
+
+  if (fxs) {
+    tcr->native_thread_info = NULL;
+    free(fxs);
+  }
+  if (use_mach_exception_handling) {
+    mach_port_deallocate(mach_task_self(),TCR_TO_EXCEPTION_PORT(tcr));
+    mach_port_destroy(mach_task_self(),TCR_TO_EXCEPTION_PORT(tcr));
+  }
+}
+
+
+Boolean
+suspend_mach_thread(mach_port_t mach_thread)
+{
+  kern_return_t status;
+  Boolean aborted = false;
+  
+  do {
+    aborted = false;
+    status = thread_suspend(mach_thread);
+    if (status == KERN_SUCCESS) {
+      status = thread_abort_safely(mach_thread);
+      if (status == KERN_SUCCESS) {
+        aborted = true;
+      } else {
+        fprintf(dbgout, "abort failed on thread = 0x%x\n",mach_thread);
+        thread_resume(mach_thread);
+      }
+    } else {
+      return false;
+    }
+  } while (! aborted);
+  return true;
+}
+
+/*
+  Only do this if pthread_kill indicated that the pthread isn't
+  listening to signals anymore, as can happen as soon as pthread_exit()
+  is called on Darwin.  The thread could still call out to lisp as it
+  is exiting, so we need another way to suspend it in this case.
+*/
+Boolean
+mach_suspend_tcr(TCR *tcr)
+{
+  mach_port_t mach_thread = (mach_port_t)((natural)( tcr->native_thread_id));
+  ExceptionInformation *pseudosigcontext;
+  Boolean result = false;
+  
+  result = suspend_mach_thread(mach_thread);
+  if (result) {
+    mach_msg_type_number_t thread_state_count;
+#ifdef X8664
+    x86_thread_state64_t ts;
+    thread_state_count = x86_THREAD_STATE64_COUNT;
+    thread_get_state(mach_thread,
+                     x86_THREAD_STATE64,
+                     (thread_state_t)&ts,
+                     &thread_state_count);
+#else
+    x86_thread_state32_t ts;
+    thread_state_count = x86_THREAD_STATE_COUNT;
+    thread_get_state(mach_thread,
+                     x86_THREAD_STATE,
+                     (thread_state_t)&ts,
+                     &thread_state_count);
+#endif
+
+    pseudosigcontext = create_thread_context_frame(mach_thread, NULL, NULL,tcr, &ts);
+    pseudosigcontext->uc_onstack = 0;
+    pseudosigcontext->uc_sigmask = (sigset_t) 0;
+    tcr->suspend_context = pseudosigcontext;
+  }
+  return result;
+}
+
+void
+mach_resume_tcr(TCR *tcr)
+{
+  ExceptionInformation *xp;
+  mach_port_t mach_thread = (mach_port_t)((natural)(tcr->native_thread_id));
+  
+  xp = tcr->suspend_context;
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "resuming TCR 0x%x, pending_exception_context = 0x%x\n",
+          tcr, tcr->pending_exception_context);
+#endif
+  tcr->suspend_context = NULL;
+  restore_mach_thread_state(mach_thread, xp);
+#ifdef DEBUG_MACH_EXCEPTIONS
+  fprintf(dbgout, "restored state in TCR 0x%x, pending_exception_context = 0x%x\n",
+          tcr, tcr->pending_exception_context);
+#endif
+  thread_resume(mach_thread);
+}
+
+void
+fatal_mach_error(char *format, ...)
+{
+  va_list args;
+  char s[512];
+ 
+
+  va_start(args, format);
+  vsnprintf(s, sizeof(s),format, args);
+  va_end(args);
+
+  Fatal("Mach error", s);
+}
+
+
+
+
+#endif
+
+/* watchpoint stuff */
+
+area *
+new_watched_area(natural size)
+{
+  void *p;
+
+  p = MapMemory(NULL, size, MEMPROTECT_RWX);
+  if ((signed_natural)p == -1) {
+    allocation_failure(true, size);
+  }
+  return new_area(p, p + size, AREA_WATCHED);
+}
+
+void
+delete_watched_area(area *a, TCR *tcr)
+{
+  natural nbytes = a->high - a->low;
+  char *base = a->low;
+
+  condemn_area_holding_area_lock(a);
+
+  if (nbytes) {
+    int err;
+
+/* can't use UnMapMemory() beacuse it only uses MEM_DECOMMIT */
+#ifdef WINDOWS
+    err = VirtualFree(base, nbytes, MEM_RELEASE);
+#else
+    err = munmap(base, nbytes);
+#endif
+    if (err != 0)
+      Fatal("munmap in delete_watched_area", "");
+  }
+}
+
+natural
+uvector_total_size_in_bytes(LispObj *u)
+{
+  LispObj header = header_of(u);
+  natural header_tag = fulltag_of(header);
+  natural subtag = header_subtag(header);
+  natural element_count = header_element_count(header);
+  natural nbytes = 0;
+
+#ifdef X8632
+  if ((nodeheader_tag_p(header_tag)) ||
+      (subtag <= max_32_bit_ivector_subtag)) {
+    nbytes = element_count << 2;
+  } else if (subtag <= max_8_bit_ivector_subtag) {
+    nbytes = element_count;
+  } else if (subtag <= max_16_bit_ivector_subtag) {
+    nbytes = element_count << 1;
+  } else if (subtag == subtag_double_float_vector) {
+    nbytes = element_count << 3;
+  } else {
+    nbytes = (element_count + 7) >> 3;
+  }
+  /* add 4 byte header and round up to multiple of 8 bytes */
+  return ~7 & (4 + nbytes + 7);
+#endif
+#ifdef X8664
+  if ((nodeheader_tag_p(header_tag)) || (header_tag == ivector_class_64_bit)) {
+    nbytes = element_count << 3;
+  } else if (header_tag == ivector_class_32_bit) {
+    nbytes = element_count << 2;
+  } else {
+    /* ivector_class_other_bit contains 8, 16-bit arrays & bit vector */
+    if (subtag == subtag_bit_vector) {
+      nbytes = (element_count + 7) >> 3;
+    } else if (subtag >= min_8_bit_ivector_subtag) {
+      nbytes = element_count;
+    } else {
+      nbytes = element_count << 1;
+    }
+  }
+  /* add 8 byte header and round up to multiple of 16 bytes */
+  return ~15 & (8 + nbytes + 15);
+#endif
+}
+
+extern void wp_update_references(TCR *, LispObj, LispObj);
+
+/*
+ * Other threads are suspended and pc-lusered.
+ *
+ * param contains a tagged pointer to a uvector or a cons cell
+ */
+signed_natural
+watch_object(TCR *tcr, signed_natural param)
+{
+  LispObj object = (LispObj)param;
+  unsigned tag = fulltag_of(object);
+  LispObj *noderef = (LispObj *)untag(object);
+  area *object_area = area_containing((BytePtr)noderef);
+  natural size;
+
+  if (tag == fulltag_cons)
+    size = 2 * node_size;
+  else
+    size = uvector_total_size_in_bytes(noderef);
+
+  if (object_area && object_area->code == AREA_DYNAMIC) {
+    area *a = new_watched_area(size);
+    LispObj old = object;
+    LispObj new = (LispObj)((natural)a->low + tag);
+
+    add_area_holding_area_lock(a);
+
+    /* move object to watched area */
+    memcpy(a->low, noderef, size);
+    ProtectMemory(a->low, size);
+    memset(noderef, 0, size);
+    wp_update_references(tcr, old, new);
+    check_all_areas(tcr);
+    return 1;
+  }
+  return 0;
+}
+
+/*
+ * We expect the watched object in arg_y, and the new uninitialized
+ * object (which is just zeroed) in arg_z.
+ */
+signed_natural
+unwatch_object(TCR *tcr, signed_natural param)
+{
+  ExceptionInformation *xp = tcr->xframe->curr;
+  LispObj old = xpGPR(xp, Iarg_y);
+  unsigned tag = fulltag_of(old);
+  LispObj new = xpGPR(xp, Iarg_z);
+  LispObj *oldnode = (LispObj *)untag(old);
+  LispObj *newnode = (LispObj *)untag(new);
+  area *a = area_containing((BytePtr)old);
+
+  if (a && a->code == AREA_WATCHED) {
+    natural size;
+
+    if (tag == fulltag_cons)
+      size = 2 * node_size;
+    else
+      size = uvector_total_size_in_bytes(oldnode);
+
+    memcpy(newnode, oldnode, size);
+    delete_watched_area(a, tcr);
+    wp_update_references(tcr, old, new);
+    /* because wp_update_references doesn't update refbits */
+    tenure_to_area(tenured_area);
+    /* Unwatching can (re-)introduce managed_static->dynamic references */
+    zero_bits(managed_static_area->refbits,managed_static_area->ndnodes);
+    update_managed_refs(managed_static_area, low_markable_address, area_dnode(active_dynamic_area->active, low_markable_address));
+    check_all_areas(tcr);
+    xpGPR(xp, Iarg_z) = new;
+  }
+  return 0;
+}
+
+Boolean
+handle_watch_trap(ExceptionInformation *xp, TCR *tcr)
+{
+  LispObj selector = xpGPR(xp,Iimm0);
+  LispObj object = xpGPR(xp, Iarg_z);
+  signed_natural result;
+  
+  switch (selector) {
+    case WATCH_TRAP_FUNCTION_WATCH:
+      result = gc_like_from_xp(xp, watch_object, object);
+      if (result == 0)
+	xpGPR(xp,Iarg_z) = lisp_nil;
+      break;
+    case WATCH_TRAP_FUNCTION_UNWATCH:
+      gc_like_from_xp(xp, unwatch_object, 0);
+      break;
+    default:
+      break;
+  }
+  return true;
+}
+
Index: /branches/new-random/lisp-kernel/x86-exceptions.h
===================================================================
--- /branches/new-random/lisp-kernel/x86-exceptions.h	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-exceptions.h	(revision 13309)
@@ -0,0 +1,269 @@
+/*
+   Copyright (C) 2005-2009 Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#ifndef X86_EXCEPTIONS_H
+#define X86_EXCEPTIONS_H 1
+
+typedef u8_t opcode, *pc;
+
+#ifdef LINUX
+#define xpGPRvector(x) ((natural *)(&((x)->uc_mcontext.gregs)))
+#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
+#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
+#define xpPC(x) (xpGPR(x,Iip))
+#define xpMMXreg(x,n)  *((natural *)(&((x)->uc_mcontext.fpregs->_st[n])))
+#define eflags_register(xp) xpGPR(xp,Iflags)
+#endif
+
+#ifdef DARWIN
+#define DARWIN_USE_PSEUDO_SIGRETURN 1
+#include <sys/syscall.h>
+#define DarwinSigReturn(context) do {\
+    darwin_sigreturn(context);\
+    Bug(context,"sigreturn returned");\
+  } while (0)
+
+#define xpGPRvector(x) ((natural *)(&(UC_MCONTEXT(x)->__ss)))
+#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
+#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
+#define xpPC(x) (xpGPR(x,Iip))
+#define eflags_register(xp) xpGPR(xp,Iflags)
+#define xpFPRvector(x) ((natural *)(&(UC_MCONTEXT(x)->__fs.__fpu_xmm0)))
+#define xpMMXvector(x) (&(UC_MCONTEXT(x)->__fs.__fpu_stmm0))
+/* Note that this yields only the lower half of the MMX reg on x8632 */
+#define xpMMXreg(x,n) *(natural *)&(xpMMXvector(x)[n])
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/machine/thread_state.h>
+#include <mach/machine/thread_status.h>
+
+pthread_mutex_t *mach_exception_lock;
+
+#endif
+
+#ifdef FREEBSD
+#ifdef X8664
+#include <machine/fpu.h>
+#else
+#include "freebsdx8632/fpu.h"
+#endif
+#define xpGPRvector(x) ((natural *)(&((x)->uc_mcontext)))
+#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
+#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
+#define eflags_register(xp) xpGPR(xp,Iflags)
+#define xpPC(x) xpGPR(x,Iip)
+#ifdef X8664
+#define xpMMXreg(x,n) *((natural *)(&(((struct savefpu *)(&(x)->uc_mcontext.mc_fpstate))->sv_fp[n])))
+#define xpXMMregs(x)(&(((struct savefpu *)(&(x)->uc_mcontext.mc_fpstate))->sv_xmm[0]))
+#else
+#define xpMMXreg(x,n) *((natural *)(&(((struct ccl_savexmm *)(&(x)->uc_mcontext.mc_fpstate))->sv_fp[n])))
+#define xpXMMregs(x)(&(((struct ccl_savexmm *)(&(x)->uc_mcontext.mc_fpstate))->sv_xmm[0]))
+#endif
+#endif
+
+#ifdef SOLARIS
+#define xpGPRvector(x) ((x)->uc_mcontext.gregs)
+#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
+#define set_xpGPR(x,gpr,new) xpGPR((x),(gpr)) = (natural)(new)
+#define xpPC(x) xpGPR(x,Iip)
+#define eflags_register(xp) xpGPR(xp,Iflags)
+#define xpXMMregs(x)(&((x)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[0]))
+#ifdef X8632
+#define xpMMXreg(x,n)*(natural *)(&(((struct fnsave_state *)(&(((x)->uc_mcontext.fpregs))))->f_st[n]))
+#endif
+#endif
+
+#ifdef WINDOWS
+#ifdef X8664
+#define xpGPRvector(x) ((DWORD64 *)(&(x)->Rax))
+#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
+#define xpPC(x) xpGPR(x,Iip)
+#define eflags_register(xp) xp->EFlags
+#define xpMXCSRptr(x) (DWORD *)(&(x->MxCsr))
+#else
+#define xpGPRvector(x) ((DWORD *)(&(x)->Edi))
+#define xpGPR(x,gprno) (xpGPRvector(x)[gprno])
+#define xpPC(x) xpGPR(x,Iip)
+#define eflags_register(xp) xp->EFlags
+#define xpFPRvector(x) ((natural *)(&(x->ExtendedRegisters[10*16])))
+#define xpMMXreg(x,n)  (*((u64_t *)(&(x->FloatSave.RegisterArea[10*(n)]))))
+#define xpMXCSRptr(x) (DWORD *)(&(x->ExtendedRegisters[24]))
+#endif
+#endif
+
+#ifdef DARWIN
+#define SIGNAL_FOR_PROCESS_INTERRUPT SIGUSR1
+#endif
+#ifdef LINUX
+#define SIGNAL_FOR_PROCESS_INTERRUPT SIGPWR
+#endif
+#ifdef FREEBSD
+#define SIGNAL_FOR_PROCESS_INTERRUPT SIGEMT
+#endif
+#ifdef SOLARIS
+#define SIGNAL_FOR_PROCESS_INTERRUPT SIGUSR1
+#endif
+#ifdef WINDOWS
+#define SIGNAL_FOR_PROCESS_INTERRUPT SIGINT
+#ifndef SIGBUS
+#define SIGBUS 10
+#endif
+#ifndef CONTEXT_ALL
+#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS)
+#endif
+#endif
+
+
+
+void switch_to_foreign_stack(void*, ...);
+
+#define INTN_OPCODE 0xcd
+
+#define UUO_GC_TRAP    0xc4
+#define UUO_ALLOC_TRAP 0xc5
+#define UUO_DEBUG_TRAP 0xca
+#define UUO_DEBUG_TRAP_WITH_STRING 0xcd
+#define UUO_WATCH_TRAP 0xce
+  #define WATCH_TRAP_FUNCTION_WATCH 0
+  #define WATCH_TRAP_FUNCTION_UNWATCH 1
+
+#define XUUO_OPCODE_0 0x0f
+#define XUUO_OPCODE_1 0x0b
+
+#define XUUO_TLB_TOO_SMALL 1
+#define XUUO_INTERRUPT_NOW 2
+#define XUUO_SUSPEND_NOW 3
+#define XUUO_INTERRUPT 4
+#define XUUO_SUSPEND 5
+#define XUUO_SUSPEND_ALL 6
+#define XUUO_RESUME 7
+#define XUUO_RESUME_ALL 8
+#define XUUO_KILL 9
+#define XUUO_ALLOCATE_LIST 10
+
+void
+pc_luser_xp(ExceptionInformation*, TCR*, signed_natural*);
+
+
+typedef enum {
+  ID_unrecognized_alloc_instruction,
+  ID_load_allocptr_reg_from_tcr_save_allocptr_instruction,
+  ID_compare_allocptr_reg_to_tcr_save_allocbase_instruction,
+  ID_branch_around_alloc_trap_instruction,
+  ID_alloc_trap_instruction,
+  ID_set_allocptr_header_instruction,
+  ID_clear_tcr_save_allocptr_tag_instruction
+} alloc_instruction_id;
+
+#ifdef LINUX
+#define SIGNUM_FOR_INTN_TRAP SIGSEGV
+#define IS_MAYBE_INT_TRAP(info,xp) ((xpGPR(xp,REG_TRAPNO)==0xd)&&((xpGPR(xp,REG_ERR)&7)==2))
+#define IS_PAGE_FAULT(info,xp) (xpGPR(xp,REG_TRAPNO)==0xe)
+#define SIGRETURN(context)
+#endif
+
+#ifdef FREEBSD
+extern void freebsd_sigreturn(ExceptionInformation *);
+#define SIGNUM_FOR_INTN_TRAP SIGBUS
+#define IS_MAYBE_INT_TRAP(info,xp) ((xp->uc_mcontext.mc_trapno == T_PROTFLT) && ((xp->uc_mcontext.mc_err & 7) == 2))
+#define IS_PAGE_FAULT(info,xp) (xp->uc_mcontext.mc_trapno == T_PAGEFLT)
+#define SIGRETURN(context) freebsd_sigreturn(context)
+#endif
+
+#ifdef DARWIN
+#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Not really, but our Mach handler fakes that */
+#define IS_MAYBE_INT_TRAP(info,xp) ((UC_MCONTEXT(xp)->__es.__trapno == 0xd) && (((UC_MCONTEXT(xp)->__es.__err)&7)==2))
+#define IS_PAGE_FAULT(info,xp) (UC_MCONTEXT(xp)->__es.__trapno == 0xe)
+/* The x86 version of sigreturn just needs the context argument; the
+   hidden, magic "flavor" argument that sigtramp uses is ignored. */
+#define SIGRETURN(context) DarwinSigReturn(context)
+#endif
+
+#ifdef SOLARIS
+#define SIGNUM_FOR_INTN_TRAP SIGSEGV
+#ifdef X8664
+#define IS_MAYBE_INT_TRAP(info,xp) ((xpGPR(xp,REG_TRAPNO)==0xd)&&((xpGPR(xp,REG_ERR)&7)==2))
+#define IS_PAGE_FAULT(info,xp) (xpGPR(xp,REG_TRAPNO)==0xe)
+#else
+#define IS_MAYBE_INT_TRAP(info,xp) ((xpGPR(xp,TRAPNO)==0xd)&&((xpGPR(xp,ERR)&7)==2))
+#define IS_PAGE_FAULT(info,xp) (xpGPR(xp,TRAPNO)==0xe)
+#endif
+#define SIGRETURN(context) setcontext(context)
+#endif
+
+#ifdef WINDOWS
+#define SIGNUM_FOR_INTN_TRAP SIGSEGV /* Also fake */
+#define IS_MAYBE_INT_TRAP(info,xp) \
+  ((info->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) &&       \
+   (info->ExceptionInformation[0]==0) &&                       \
+   (info->ExceptionInformation[1]==(ULONG_PTR)(-1L)))
+#define IS_PAGE_FAULT(info,xp) (1)
+#define SIGRETURN(context)      /* for now */
+#endif
+
+/* Please go away. */
+#ifdef DARWIN_GS_HACK
+extern Boolean ensure_gs_pthread(void);
+extern void set_gs_address(void *);
+#endif
+
+
+/* sigaltstack isn't thread-specific on The World's Most Advanced OS */
+#ifdef DARWIN
+#undef USE_SIGALTSTACK
+#else
+#ifdef WINDOWS
+#undef USE_SIGALTSTACK
+#else
+#define USE_SIGALTSTACK 1
+#endif
+#endif
+
+#ifdef USE_SIGALTSTACK
+void setup_sigaltstack(area *);
+#endif
+
+/* recognizing the function associated with a tagged return address */
+/* now involves recognizinig an "(lea (@ disp (% rip)) (% rn))" */
+/* instruction at the tra */
+
+#define RECOVER_FN_FROM_RIP_LENGTH 7 /* the instruction is 7 bytes long */
+#define RECOVER_FN_FROM_RIP_DISP_OFFSET 3 /* displacement word is 3 bytes in */
+#define RECOVER_FN_FROM_RIP_WORD0 0x8d4c /* 0x4c 0x8d, little-endian */
+#define RECOVER_FN_FROM_RIP_BYTE2 0x2d  /* third byte of opcode */
+
+extern natural get_mxcsr();
+extern void set_mxcsr(natural);
+
+#ifdef WINDOWS
+typedef struct {
+  HANDLE h;
+  OVERLAPPED *o;
+} pending_io;
+#endif
+
+#ifdef X8632
+/* The 32-bit immediate value in the instruction
+ * "(mov ($ 0x12345678) (% fn))" at a tagged return address
+ * refers to the associated function.
+ */
+#define RECOVER_FN_OPCODE 0xbf
+#define RECOVER_FN_LENGTH 5
+#endif
+
+#endif /* X86_EXCEPTIONS_H */
+
Index: /branches/new-random/lisp-kernel/x86-gc.c
===================================================================
--- /branches/new-random/lisp-kernel/x86-gc.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-gc.c	(revision 13309)
@@ -0,0 +1,3335 @@
+/*
+   Copyright (C) 2009 Clozure Associates
+   Copyright (C) 1994-2001 Digitool, Inc
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lisp.h"
+#include "lisp_globals.h"
+#include "bits.h"
+#include "gc.h"
+#include "area.h"
+#include "Threads.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#ifdef X8632
+inline natural
+imm_word_count(LispObj fn)
+{
+  natural w = ((unsigned short *)fn)[-1];
+
+  if (w & 0x8000) {
+    /* 
+     * The low 15 bits encode the number of contants.
+     * Compute and return the immediate word count.
+     */
+    LispObj header = header_of(fn);
+    natural element_count = header_element_count(header);
+
+    return element_count - (w & 0x7fff);
+  } else {
+    /* The immediate word count is encoded directly. */
+    return w;
+  }
+}
+#endif
+
+/* Heap sanity checking. */
+
+void
+check_node(LispObj n)
+{
+  int tag = fulltag_of(n), header_tag;
+  area *a;
+  LispObj header;
+
+  if (n == (n & 0xff)) {
+    return;
+  }
+
+  switch (tag) {
+  case fulltag_even_fixnum:
+  case fulltag_odd_fixnum:
+#ifdef X8632
+  case fulltag_imm:
+#endif
+#ifdef X8664
+  case fulltag_imm_0:
+  case fulltag_imm_1:
+#endif
+    return;
+
+#ifdef X8664
+  case fulltag_nil:
+    if (n != lisp_nil) {
+      Bug(NULL,"Object tagged as nil, not nil : " LISP, n);
+    }
+    return;
+#endif
+
+#ifdef X8632
+  case fulltag_nodeheader:
+  case fulltag_immheader:
+#endif
+#ifdef X8664
+  case fulltag_nodeheader_0: 
+  case fulltag_nodeheader_1: 
+  case fulltag_immheader_0: 
+  case fulltag_immheader_1: 
+  case fulltag_immheader_2: 
+#endif
+    Bug(NULL, "Header not expected : 0x" LISP, n);
+    return;
+
+#ifdef X8632
+  case fulltag_tra:
+#endif
+#ifdef X8664
+  case fulltag_tra_0:
+  case fulltag_tra_1:
+#endif
+    a = heap_area_containing((BytePtr)ptr_from_lispobj(n));
+    if (a == NULL) {
+      a = active_dynamic_area;
+      if ((n > (ptr_to_lispobj(a->active))) &&
+          (n < (ptr_to_lispobj(a->high)))) {
+        Bug(NULL, "TRA points to heap free space: 0x" LISP, n);
+      }
+      return;
+    }
+    /* tra points into the heap.  Check displacement, then
+       check the function it (should) identify.
+    */
+#ifdef X8632
+    {
+      LispObj fun = 0;
+
+      if (*(unsigned char *)n == RECOVER_FN_OPCODE)
+	fun = *(LispObj *)(n + 1);
+      if (fun == 0 ||
+	 (header_subtag(header_of(fun)) != subtag_function) ||
+	 (heap_area_containing((BytePtr)ptr_from_lispobj(fun)) != a)) {
+	Bug(NULL, "TRA at 0x" LISP " has bad function address 0x" LISP "\n", n, fun);
+      }
+      n = fun;
+    }
+#endif
+#ifdef X8664
+    {
+      int disp = 0;
+      LispObj m = n;
+
+      if ((*((unsigned short *)n) == RECOVER_FN_FROM_RIP_WORD0) &&
+          (*((unsigned char *)(n+2)) == RECOVER_FN_FROM_RIP_BYTE2)) {
+        disp = (*(int *) (n+3));
+        n = RECOVER_FN_FROM_RIP_LENGTH+m+disp;
+      }
+      if ((disp == 0) ||
+          (fulltag_of(n) != fulltag_function) ||
+          (heap_area_containing((BytePtr)ptr_from_lispobj(n)) != a)) {
+        Bug(NULL, "TRA at 0x" LISP " has bad displacement %d\n", n, disp);
+      }
+    }
+#endif
+    /* Otherwise, fall through and check the header on the function
+       that the tra references */
+
+  case fulltag_misc:
+  case fulltag_cons:
+#ifdef X8664
+  case fulltag_symbol:
+  case fulltag_function:
+#endif
+    a = heap_area_containing((BytePtr)ptr_from_lispobj(n));
+    
+    if (a == NULL) {
+      /* Can't do as much sanity checking as we'd like to
+         if object is a defunct stack-consed object.
+         If a dangling reference to the heap, that's
+         bad .. */
+      a = active_dynamic_area;
+      if ((n > (ptr_to_lispobj(a->active))) &&
+          (n < (ptr_to_lispobj(a->high)))) {
+        Bug(NULL, "Node points to heap free space: 0x" LISP, n);
+      }
+      return;
+    }
+    break;
+  }
+  /* Node points to heap area, so check header/lack thereof. */
+  header = header_of(n);
+  header_tag = fulltag_of(header);
+  if (tag == fulltag_cons) {
+    if ((nodeheader_tag_p(header_tag)) ||
+        (immheader_tag_p(header_tag))) {
+      Bug(NULL, "Cons cell at 0x" LISP " has bogus header : 0x" LISP, n, header);
+    }
+    return;
+  }
+
+  if ((!nodeheader_tag_p(header_tag)) &&
+      (!immheader_tag_p(header_tag))) {
+    Bug(NULL,"Vector at 0x" LISP " has bogus header : 0x" LISP, n, header);
+  }
+  return;
+}
+
+void
+check_all_mark_bits(LispObj *nodepointer) 
+{
+}
+
+
+
+
+
+void
+check_range(LispObj *start, LispObj *end, Boolean header_allowed)
+{
+  LispObj node, *current = start, *prev = NULL;
+  int tag;
+  natural elements;
+
+  while (current < end) {
+    prev = current;
+    node = *current++;
+    tag = fulltag_of(node);
+    if (immheader_tag_p(tag)) {
+      if (! header_allowed) {
+        Bug(NULL, "Header not expected at 0x" LISP "\n", prev);
+      }
+      current = (LispObj *)skip_over_ivector((natural)prev, node);
+    } else if (nodeheader_tag_p(tag)) {
+      if (! header_allowed) {
+        Bug(NULL, "Header not expected at 0x" LISP "\n", prev);
+      }
+      elements = header_element_count(node) | 1;
+      if (header_subtag(node) == subtag_function) {
+#ifdef X8632
+	int skip = *(unsigned short *)current;
+
+	/* XXX bootstrapping */
+	if (skip & 0x8000)
+	  skip = elements - (skip & 0x7fff);
+#else
+        int skip = *(int *)current;
+#endif
+        current += skip;
+        elements -= skip;
+      }
+      while (elements--) {
+        check_node(*current++);
+      }
+    } else {
+      check_node(node);
+      check_node(*current++);
+    }
+  }
+
+  if (current != end) {
+    Bug(NULL, "Overran end of memory range: start = 0x%08x, end = 0x%08x, prev = 0x%08x, current = 0x%08x",
+        start, end, prev, current);
+  }
+}
+
+#ifdef X8632
+void
+check_xp(ExceptionInformation *xp, natural node_regs_mask)
+{
+  natural *regs = (natural *) xpGPRvector(xp), dnode;
+
+  if (node_regs_mask & (1<<0)) check_node(regs[REG_EAX]);
+  if (node_regs_mask & (1<<1)) check_node(regs[REG_ECX]);
+  if (regs[REG_EFL] & EFL_DF) {
+    /* DF set means EDX should be treated as an imm reg */
+    ;
+  } else
+    if (node_regs_mask & (1<<2)) check_node(regs[REG_EDX]);
+
+  if (node_regs_mask & (1<<3)) check_node(regs[REG_EBX]);
+  if (node_regs_mask & (1<<4)) check_node(regs[REG_ESP]);
+  if (node_regs_mask & (1<<5)) check_node(regs[REG_EBP]);
+  if (node_regs_mask & (1<<6)) check_node(regs[REG_ESI]);
+  if (node_regs_mask & (1<<7)) check_node(regs[REG_EDI]);
+}
+#else
+void
+check_xp(ExceptionInformation *xp)
+{
+  natural *regs = (natural *) xpGPRvector(xp), dnode;
+
+  check_node(regs[Iarg_z]);
+  check_node(regs[Iarg_y]);
+  check_node(regs[Iarg_x]);
+  check_node(regs[Isave3]);
+  check_node(regs[Isave2]);
+  check_node(regs[Isave1]);
+  check_node(regs[Isave0]);
+  check_node(regs[Ifn]);
+  check_node(regs[Itemp0]);
+  check_node(regs[Itemp1]);
+  check_node(regs[Itemp2]);
+}
+#endif
+
+void
+check_tcrs(TCR *first)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+  
+  TCR *tcr = first;
+  LispObj *tlb_start,*tlb_end;
+
+  do {
+    xp = tcr->gc_context;
+    if (xp) {
+#ifdef X8632
+      check_xp(xp,tcr->node_regs_mask);
+#else
+      check_xp(xp);
+#endif
+    }
+#ifdef X8632
+    check_node(tcr->save0);
+    check_node(tcr->save1);
+    check_node(tcr->save2);
+    check_node(tcr->save3);
+    check_node(tcr->next_method_context);
+#endif
+    for (xframes = (xframe_list *) tcr->xframe; 
+         xframes; 
+         xframes = xframes->prev) {
+#ifndef X8632
+      check_xp(xframes->curr);
+#else
+      check_xp(xframes->curr, xframes->node_regs_mask);
+#endif
+    }
+    tlb_start = tcr->tlb_pointer;
+    if (tlb_start) {
+      tlb_end = tlb_start + ((tcr->tlb_limit)>>fixnumshift);
+      check_range(tlb_start,tlb_end,false);
+    }
+    tcr = tcr->next;
+  } while (tcr != first);
+}
+
+  
+void
+check_all_areas(TCR *tcr)
+{
+  area *a = active_dynamic_area;
+  area_code code = a->code;
+
+  while (code != AREA_VOID) {
+    switch (code) {
+    case AREA_DYNAMIC:
+    case AREA_WATCHED:
+    case AREA_STATIC:
+    case AREA_MANAGED_STATIC:
+      check_range((LispObj *)a->low, (LispObj *)a->active, true);
+      break;
+
+    case AREA_VSTACK:
+      {
+        LispObj* low = (LispObj *)a->active;
+        LispObj* high = (LispObj *)a->high;
+        
+        if (((natural)low) & node_size) {
+          check_node(*low++);
+        }
+        check_range(low, high, false);
+      }
+      break;
+
+    case AREA_TSTACK:
+      {
+        LispObj *current, *next,
+                *start = (LispObj *) a->active,
+                *end = start,
+                *limit = (LispObj *) a->high;
+                 
+        for (current = start;
+             end != limit;
+             current = next) {
+          next = ptr_from_lispobj(*current);
+          end = ((next >= start) && (next < limit)) ? next : limit;
+          check_range(current+2, end, true);
+        }
+      }
+      break;
+    }
+    a = a->succ;
+    code = (a->code);
+  }
+
+  check_tcrs(tcr);
+}
+
+
+
+
+
+
+
+
+/* Sooner or later, this probably wants to be in assembler */
+/* Return false if n is definitely not an ephemeral node, true if
+   it might be */
+void
+mark_root(LispObj n)
+{
+  int tag_n = fulltag_of(n);
+  natural dnode, bits, *bitsp, mask;
+
+  if (!is_node_fulltag(tag_n)) {
+    return;
+  }
+
+  dnode = gc_area_dnode(n);
+  if (dnode >= GCndnodes_in_area) {
+    return;
+  }
+
+#ifdef X8632
+  if (tag_n == fulltag_tra) {
+    if (*(unsigned char *)n == RECOVER_FN_OPCODE) {
+      n = *(LispObj *)(n + 1);
+      tag_n = fulltag_misc;
+      dnode = gc_area_dnode(n);
+    } else
+      return;
+  }
+#endif
+#ifdef X8664
+  if (tag_of(n) == tag_tra) {
+    if ((*((unsigned short *)n) == RECOVER_FN_FROM_RIP_WORD0) &&
+        (*((unsigned char *)(n+2)) == RECOVER_FN_FROM_RIP_BYTE2)) {
+      int sdisp = (*(int *) (n+3));
+      n = RECOVER_FN_FROM_RIP_LENGTH+n+sdisp;
+      tag_n = fulltag_function;
+      dnode = gc_area_dnode(n);
+    }
+    else {
+      return;
+    }
+  }
+#endif
+
+  set_bits_vars(GCmarkbits,dnode,bitsp,bits,mask);
+  if (bits & mask) {
+    return;
+  }
+  *bitsp = (bits | mask);
+
+  if (tag_n == fulltag_cons) {
+    cons *c = (cons *) ptr_from_lispobj(untag(n));
+
+    rmark(c->car);
+    rmark(c->cdr);
+    return;
+  }
+  {
+    LispObj *base = (LispObj *) ptr_from_lispobj(untag(n));
+    natural
+      header = *((natural *) base),
+      subtag = header_subtag(header),
+      element_count = header_element_count(header),
+      total_size_in_bytes,      /* including 4/8-byte header */
+      suffix_dnodes;
+    natural prefix_nodes = 0;
+
+    tag_n = fulltag_of(header);
+
+#ifdef X8664
+    if ((nodeheader_tag_p(tag_n)) ||
+        (tag_n == ivector_class_64_bit)) {
+      total_size_in_bytes = 8 + (element_count<<3);
+    } else if (tag_n == ivector_class_32_bit) {
+      total_size_in_bytes = 8 + (element_count<<2);
+    } else {
+      /* ivector_class_other_bit contains 8, 16-bit arrays & bitvector */
+      if (subtag == subtag_bit_vector) {
+        total_size_in_bytes = 8 + ((element_count+7)>>3);
+      } else if (subtag >= min_8_bit_ivector_subtag) {
+	total_size_in_bytes = 8 + element_count;
+      } else {
+        total_size_in_bytes = 8 + (element_count<<1);
+      }
+    }
+#endif
+#ifdef X8632
+    if ((tag_n == fulltag_nodeheader) ||
+        (subtag <= max_32_bit_ivector_subtag)) {
+      total_size_in_bytes = 4 + (element_count<<2);
+    } else if (subtag <= max_8_bit_ivector_subtag) {
+      total_size_in_bytes = 4 + element_count;
+    } else if (subtag <= max_16_bit_ivector_subtag) {
+      total_size_in_bytes = 4 + (element_count<<1);
+    } else if (subtag == subtag_double_float_vector) {
+      total_size_in_bytes = 8 + (element_count<<3);
+    } else {
+      total_size_in_bytes = 4 + ((element_count+7)>>3);
+    }
+#endif
+
+
+    suffix_dnodes = ((total_size_in_bytes+(dnode_size-1))>>dnode_shift) -1;
+
+    if (suffix_dnodes) {
+      set_n_bits(GCmarkbits, dnode+1, suffix_dnodes);
+    }
+
+    if (nodeheader_tag_p(tag_n)) {
+      if (subtag == subtag_hash_vector) {
+        /* Don't invalidate the cache here.  It should get
+           invalidated on the lisp side, if/when we know
+           that rehashing is necessary. */
+        LispObj flags = ((hash_table_vector_header *) base)->flags;
+
+        if ((flags & nhash_keys_frozen_mask) &&
+            (((hash_table_vector_header *) base)->deleted_count > 0)) {
+          /* We're responsible for clearing out any deleted keys, since
+             lisp side can't do it without breaking the state machine
+          */
+          LispObj *pairp = base + hash_table_vector_header_count;
+          natural
+            npairs = (element_count - (hash_table_vector_header_count - 1)) >> 1;
+
+          while (npairs--) {
+            if ((pairp[1] == unbound) && (pairp[0] != unbound)) {
+              pairp[0] = slot_unbound;
+            }
+            pairp +=2;
+          }
+          ((hash_table_vector_header *) base)->deleted_count = 0;
+        }
+
+        if (flags & nhash_weak_mask) {
+          ((hash_table_vector_header *) base)->cache_key = undefined;
+          ((hash_table_vector_header *) base)->cache_value = lisp_nil;
+          mark_weak_htabv(n);
+          return;
+        }
+      }
+
+      if (subtag == subtag_pool) {
+        deref(base, 1) = lisp_nil;
+      }
+      
+      if (subtag == subtag_weak) {
+        natural weak_type = (natural) base[2];
+        if (weak_type >> population_termination_bit) {
+          element_count -= 2;
+        } else {
+          element_count -= 1;
+        }
+      }
+
+      if (subtag == subtag_function) {
+#ifdef X8632
+	prefix_nodes = (natural) ((unsigned short) deref(base,1));
+
+	/* XXX bootstrapping */
+	if (prefix_nodes & 0x8000)
+	  prefix_nodes = element_count - (prefix_nodes & 0x7fff);
+#else
+	prefix_nodes = (natural) ((int) deref(base,1));
+#endif
+        if (prefix_nodes > element_count) {
+          Bug(NULL, "Function 0x" LISP " trashed",n);
+        }
+      }
+      base += (1+element_count);
+
+      element_count -= prefix_nodes;
+
+      while(element_count--) {
+        rmark(*--base);
+      }
+      if (subtag == subtag_weak) {
+        deref(ptr_to_lispobj(base),1) = GCweakvll;
+        GCweakvll = n;
+      }
+    }
+  }
+}
+
+
+/* 
+  This marks the node if it needs to; it returns true if the node
+  is either a hash table vector header or a cons/misc-tagged pointer
+  to ephemeral space.
+  Note that it  might be a pointer to ephemeral space even if it's
+  not pointing to the current generation.
+*/
+
+Boolean
+mark_ephemeral_root(LispObj n)
+{
+  int tag_n = fulltag_of(n);
+  natural eph_dnode;
+
+  if (nodeheader_tag_p(tag_n)) {
+    return (header_subtag(n) == subtag_hash_vector);
+  }
+ 
+  if (is_node_fulltag (tag_n)) {
+    eph_dnode = area_dnode(n, GCephemeral_low);
+    if (eph_dnode < GCn_ephemeral_dnodes) {
+      mark_root(n);             /* May or may not mark it */
+      return true;              /* but return true 'cause it's an ephemeral node */
+    }
+  }
+  return false;                 /* Not a heap pointer or not ephemeral */
+}
+  
+
+
+#ifdef X8664
+#define RMARK_PREV_ROOT fulltag_imm_1 /* fulltag of 'undefined' value */
+#define RMARK_PREV_CAR fulltag_nil /* fulltag_cons + node_size. Coincidence ? I think not. */
+#else
+#define RMARK_PREV_ROOT fulltag_imm /* fulltag of 'undefined' value */
+#define RMARK_PREV_CAR fulltag_odd_fixnum 
+#endif
+
+
+/*
+  This wants to be in assembler even more than "mark_root" does.
+  For now, it does link-inversion: hard as that is to express in C,
+  reliable stack-overflow detection may be even harder ...
+*/
+void
+rmark(LispObj n)
+{
+  int tag_n = fulltag_of(n);
+  bitvector markbits = GCmarkbits;
+  natural dnode, bits, *bitsp, mask;
+
+  if (!is_node_fulltag(tag_n)) {
+    return;
+  }
+
+  dnode = gc_area_dnode(n);
+  if (dnode >= GCndnodes_in_area) {
+    return;
+  }
+
+#ifdef X8632
+  if (tag_n == fulltag_tra) {
+    if (*(unsigned char *)n == RECOVER_FN_OPCODE) {
+      n = *(LispObj *)(n + 1);
+      tag_n = fulltag_misc;
+      dnode = gc_area_dnode(n);
+    } else {
+      return;
+    }
+  }
+#endif
+#ifdef X8664
+  if (tag_of(n) == tag_tra) {
+    if ((*((unsigned short *)n) == RECOVER_FN_FROM_RIP_WORD0) &&
+        (*((unsigned char *)(n+2)) == RECOVER_FN_FROM_RIP_BYTE2)) {
+      int sdisp = (*(int *) (n+3));
+      n = RECOVER_FN_FROM_RIP_LENGTH+n+sdisp;
+      tag_n = fulltag_function;
+      dnode = gc_area_dnode(n);
+    } else {
+      return;
+    }
+  }
+#endif
+
+  set_bits_vars(markbits,dnode,bitsp,bits,mask);
+  if (bits & mask) {
+    return;
+  }
+  *bitsp = (bits | mask);
+
+  if (current_stack_pointer() > GCstack_limit) {
+    if (tag_n == fulltag_cons) {
+      rmark(deref(n,1));
+      rmark(deref(n,0));
+    } else {
+      LispObj *base = (LispObj *) ptr_from_lispobj(untag(n));
+      natural
+        header = *((natural *) base),
+        subtag = header_subtag(header),
+        element_count = header_element_count(header),
+        total_size_in_bytes,
+        suffix_dnodes,
+	nmark;
+
+      tag_n = fulltag_of(header);
+
+#ifdef X8664
+      if ((nodeheader_tag_p(tag_n)) ||
+          (tag_n == ivector_class_64_bit)) {
+        total_size_in_bytes = 8 + (element_count<<3);
+      } else if (tag_n == ivector_class_32_bit) {
+        total_size_in_bytes = 8 + (element_count<<2);
+      } else {
+        /* ivector_class_other_bit contains 16-bit arrays & bitvector */
+        if (subtag == subtag_bit_vector) {
+          total_size_in_bytes = 8 + ((element_count+7)>>3);
+	} else if (subtag >= min_8_bit_ivector_subtag) {
+	  total_size_in_bytes = 8 + element_count;
+        } else {
+          total_size_in_bytes = 8 + (element_count<<1);
+        }
+      }
+#else
+      if ((tag_n == fulltag_nodeheader) ||
+	  (subtag <= max_32_bit_ivector_subtag)) {
+	total_size_in_bytes = 4 + (element_count<<2);
+      } else if (subtag <= max_8_bit_ivector_subtag) {
+	total_size_in_bytes = 4 + element_count;
+      } else if (subtag <= max_16_bit_ivector_subtag) {
+	total_size_in_bytes = 4 + (element_count<<1);
+      } else if (subtag == subtag_double_float_vector) {
+	total_size_in_bytes = 8 + (element_count<<3);
+      } else {
+	total_size_in_bytes = 4 + ((element_count+7)>>3);
+      }
+#endif
+
+      suffix_dnodes = ((total_size_in_bytes+(dnode_size-1))>>dnode_shift)-1;
+
+      if (suffix_dnodes) {
+        set_n_bits(GCmarkbits, dnode+1, suffix_dnodes);
+      }
+
+      if (!nodeheader_tag_p(tag_n)) return;
+
+      if (subtag == subtag_hash_vector) {
+        /* Splice onto weakvll, then return */
+        /* In general, there's no reason to invalidate the cached
+           key/value pair here.  However, if the hash table's weak,
+           we don't want to retain an otherwise unreferenced key
+           or value simply because they're referenced from the
+           cache.  Clear the cached entries iff the hash table's
+           weak in some sense.
+        */
+        LispObj flags = ((hash_table_vector_header *) base)->flags;
+
+        if (flags & nhash_weak_mask) {
+          ((hash_table_vector_header *) base)->cache_key = undefined;
+          ((hash_table_vector_header *) base)->cache_value = lisp_nil;
+          mark_weak_htabv(n);
+          return;
+        }
+      }
+
+      if (subtag == subtag_pool) {
+        deref(n, 1) = lisp_nil;
+      }
+
+      if (subtag == subtag_weak) {
+        natural weak_type = (natural) base[2];
+        if (weak_type >> population_termination_bit)
+          element_count -= 2;
+        else
+          element_count -= 1;
+      }
+
+      nmark = element_count;
+
+      if (subtag == subtag_function) {
+#ifdef X8664
+	int code_words = (int)base[1];
+#else
+	int code_words = (unsigned short)base[1];
+
+	/* XXX bootstrapping */
+	if (code_words & 0x8000)
+	  code_words = element_count - (code_words & 0x7fff);
+#endif
+        if (code_words >= nmark) {
+          Bug(NULL,"Bad function at 0x" LISP,n);
+        }
+	nmark -= code_words;
+      }
+
+      while (nmark--) {
+        rmark(deref(n,element_count));
+        element_count--;
+      }
+
+      if (subtag == subtag_weak) {
+        deref(n, 1) = GCweakvll;
+        GCweakvll = n;
+      }
+
+    }
+  } else {
+    /* This is all a bit more complicated than the PPC version:
+
+       - a symbol-vector can be referenced via either a FULLTAG-MISC
+       pointer or a FULLTAG-SYMBOL pointer.  When we've finished
+       marking the symbol-vector's elements, we need to know which tag
+       the object that pointed to the symbol-vector had originally.
+
+       - a function-vector can be referenced via either a FULLTAG-MISC
+       pointer or a FULLTAG-FUNCTION pointer.  That introduces pretty
+       much the same set of issues, but ...
+
+       - a function-vector can also be referenced via a TRA; the
+       offset from the TRA to the function header is arbitrary (though
+       we can probably put an upper bound on it, and it's certainly
+       not going to be more than 32 bits.)
+
+       - function-vectors contain a mixture of code and constants,
+       with a "boundary" word (that doesn't look like a valid
+       constant) in between them.  There are 56 unused bits in the
+       boundary word; the low 8 bits must be = to the constant
+       'function_boundary_marker'.  We can store the byte displacement
+       from the address of the object which references the function
+       (tagged fulltag_misc, fulltag_function, or tra) to the address
+       of the boundary marker when the function vector is first marked
+       and recover that offset when we've finished marking the
+       function vector.  (Note that the offset is signed; it's
+       probably simplest to keep it in the high 32 bits of the
+       boundary word.) 
+
+ So:
+
+       - while marking a CONS, the 'this' pointer as a 3-bit tag of
+       tag_list; the 4-bit fulltag indicates which cell is being
+       marked.
+
+       - while marking a gvector (other than a symbol-vector or
+       function-vector), the 'this' pointer is tagged tag_misc.
+       (Obviously, it alternates between fulltag_misc and
+       fulltag_nodeheader_0, arbitrarily.)  When we encounter the
+       gvector header when the 'this' pointer has been tagged as
+       fulltag_misc, we can restore 'this' to the header's address +
+       fulltag_misc and enter the 'climb' state.  (Note that this
+       value happens to be exactly what's in 'this' when the header's
+       encountered.)
+
+       - if we encounter a symbol-vector via the FULLTAG-MISC pointer
+       to the symbol (not very likely, but legal and possible), it's
+       treated exactly like the gvector case above.
+
+       - in the more likely case where a symbol-vector is referenced
+       via a FULLTAG-SYMBOL, we do the same loop as in the general
+       gvector case, backing up through the vector with 'this' tagged
+       as 'tag_symbol' (or fulltag_nodeheader_1); when we encounter
+       the symbol header, 'this' gets fulltag_symbol added to the
+       dnode-aligned address of the header, and we climb.
+
+       - if anything (fulltag_misc, fulltag_function, tra) references
+       an unmarked function function vector, we store the byte offfset
+       from the tagged reference to the address of the boundary word
+       in the high 32 bits of the boundary word, then we back up
+       through the function-vector's constants, with 'this' tagged
+       tag_function/ fulltag_immheader_0, until the (specially-tagged)
+       boundary word is encountered.  The displacement stored in the boundary
+       word is added to the aligned address of the  boundary word (restoring
+       the original 'this' pointer, and we climb.
+
+       Not that bad.
+    */
+       
+    LispObj prev = undefined, this = n, next, *base;
+    natural header, subtag, element_count, total_size_in_bytes, suffix_dnodes, *boundary;
+
+    if (tag_n == fulltag_cons) goto MarkCons;
+    goto MarkVector;
+
+  ClimbCdr:
+    prev = deref(this,0);
+    deref(this,0) = next;
+
+  Climb:
+    next = this;
+    this = prev;
+    tag_n = fulltag_of(prev);
+    switch(tag_n) {
+    case tag_misc:
+    case fulltag_misc:
+#ifdef X8664
+    case tag_symbol:
+    case fulltag_symbol:
+    case tag_function:
+    case fulltag_function:
+#endif
+      goto ClimbVector;
+
+    case RMARK_PREV_ROOT:
+      return;
+
+    case fulltag_cons:
+      goto ClimbCdr;
+
+    case RMARK_PREV_CAR:
+      goto ClimbCar;
+
+    default: abort();
+    }
+
+  DescendCons:
+    prev = this;
+    this = next;
+
+  MarkCons:
+    next = deref(this,1);
+#ifdef X8632
+    this += (RMARK_PREV_CAR-fulltag_cons);
+#else
+    this += node_size;
+#endif
+    tag_n = fulltag_of(next);
+    if (!is_node_fulltag(tag_n)) goto MarkCdr;
+    dnode = gc_area_dnode(next);
+    if (dnode >= GCndnodes_in_area) goto MarkCdr;
+    set_bits_vars(markbits,dnode,bitsp,bits,mask);
+    if (bits & mask) goto MarkCdr;
+    *bitsp = (bits | mask);
+    deref(this,1) = prev;
+    if (tag_n == fulltag_cons) goto DescendCons;
+    goto DescendVector;
+
+  ClimbCar:
+    prev = deref(this,1);
+    deref(this,1) = next;
+
+  MarkCdr:
+    next = deref(this, 0);
+#ifdef X8632
+    this -= (RMARK_PREV_CAR-fulltag_cons);
+#else
+    this -= node_size;
+#endif
+    tag_n = fulltag_of(next);
+    if (!is_node_fulltag(tag_n)) goto Climb;
+    dnode = gc_area_dnode(next);
+    if (dnode >= GCndnodes_in_area) goto Climb;
+    set_bits_vars(markbits,dnode,bitsp,bits,mask);
+    if (bits & mask) goto Climb;
+    *bitsp = (bits | mask);
+    deref(this, 0) = prev;
+    if (tag_n == fulltag_cons) goto DescendCons;
+    /* goto DescendVector; */
+
+  DescendVector:
+    prev = this;
+    this = next;
+
+  MarkVector:
+#ifdef X8664
+    if ((tag_n == fulltag_tra_0) ||
+        (tag_n == fulltag_tra_1)) {
+      int disp = (*(int *) (n+3)) + RECOVER_FN_FROM_RIP_LENGTH;
+
+      base = (LispObj *) (untag(n-disp));
+      header = *((natural *) base);
+      subtag = header_subtag(header);
+      boundary = base + (int)(base[1]);
+      (((int *)boundary)[1]) = (int)(this-((LispObj)boundary));
+      this = (LispObj)(base)+fulltag_function;
+      /* Need to set the initial markbit here */
+      dnode = gc_area_dnode(this);
+      set_bit(markbits,dnode);
+    } else {
+      base = (LispObj *) ptr_from_lispobj(untag(this));
+      header = *((natural *) base);
+      subtag = header_subtag(header);
+      if (subtag == subtag_function) {
+        boundary = base + (int)(base[1]);
+        (((int *)boundary)[1]) = (int)(this-((LispObj)boundary));
+      }
+    }
+    element_count = header_element_count(header);
+    tag_n = fulltag_of(header);
+
+    if ((nodeheader_tag_p(tag_n)) ||
+        (tag_n == ivector_class_64_bit)) {
+      total_size_in_bytes = 8 + (element_count<<3);
+    } else if (tag_n == ivector_class_32_bit) {
+      total_size_in_bytes = 8 + (element_count<<2);
+    } else {
+      /* ivector_class_other_bit contains 16-bit arrays & bitvector */
+      if (subtag == subtag_bit_vector) {
+        total_size_in_bytes = 8 + ((element_count+7)>>3);
+      } else if (subtag >= min_8_bit_ivector_subtag) {
+        total_size_in_bytes = 8 + element_count;
+      } else {
+        total_size_in_bytes = 8 + (element_count<<1);
+      }
+    }
+#else
+    if (tag_n == fulltag_tra) {
+      LispObj fn = *(LispObj *)(n + 1);
+
+      base = (LispObj *)untag(fn);
+      header = *(natural *)base;
+      subtag = header_subtag(header);
+      boundary = base + imm_word_count(fn);
+
+      /*
+       * On x8632, the upper 24 bits of the boundary word are zero.
+       * Functions on x8632 can be no more than 2^16 words (or 2^24
+       * bytes) long (including the self-reference table but excluding
+       * any constants).  Therefore, we can do the same basic thing
+       * that the x8664 port does: namely, we keep the byte
+       * displacement from the address of the object (tagged tra or
+       * fulltag_misc) that references the function to the address of
+       * the boundary marker in those 24 bits, recovering it when
+       * we've finished marking the function vector.
+       */
+      *((int *)boundary) &= 0xff;
+      *((int *)boundary) |= ((this-(LispObj)boundary) << 8);
+      this = (LispObj)(base)+fulltag_misc;
+      dnode = gc_area_dnode(this);
+      set_bit(markbits,dnode);
+    } else {
+      base = (LispObj *) ptr_from_lispobj(untag(this));
+      header = *((natural *) base);
+      subtag = header_subtag(header);
+      if (subtag == subtag_function) {
+        boundary = base + imm_word_count(this);
+
+	*((int *)boundary) &= 0xff;
+        *((int *)boundary) |= ((this-((LispObj)boundary)) << 8);
+      }
+    }
+    element_count = header_element_count(header);
+    tag_n = fulltag_of(header);
+
+    if ((tag_n == fulltag_nodeheader) ||
+	(subtag <= max_32_bit_ivector_subtag)) {
+      total_size_in_bytes = 4 + (element_count<<2);
+    } else if (subtag <= max_8_bit_ivector_subtag) {
+      total_size_in_bytes = 4 + element_count;
+    } else if (subtag <= max_16_bit_ivector_subtag) {
+      total_size_in_bytes = 4 + (element_count<<1);
+    } else if (subtag == subtag_double_float_vector) {
+      total_size_in_bytes = 8 + (element_count<<3);
+    } else {
+      total_size_in_bytes = 4 + ((element_count+7)>>3);
+    }
+#endif
+
+    suffix_dnodes = ((total_size_in_bytes+(dnode_size-1))>>dnode_shift)-1;
+    
+    if (suffix_dnodes) {
+      set_n_bits(GCmarkbits, dnode+1, suffix_dnodes);
+    }
+    
+    if (!nodeheader_tag_p(tag_n)) goto Climb;
+    
+    if (subtag == subtag_hash_vector) {
+      /* Splice onto weakvll, then climb */
+      LispObj flags = ((hash_table_vector_header *) base)->flags;
+      
+      if (flags & nhash_weak_mask) {
+        ((hash_table_vector_header *) base)->cache_key = undefined;
+        ((hash_table_vector_header *) base)->cache_value = lisp_nil;
+        dws_mark_weak_htabv(this);
+        element_count = hash_table_vector_header_count;
+      }
+    }
+
+    if (subtag == subtag_pool) {
+      deref(this, 1) = lisp_nil;
+    }
+
+    if (subtag == subtag_weak) {
+      natural weak_type = (natural) base[2];
+      if (weak_type >> population_termination_bit)
+        element_count -= 2;
+      else
+        element_count -= 1;
+    }
+
+    this = (LispObj)(base) + (tag_of(this))  + ((element_count+1) << node_shift);
+    goto MarkVectorLoop;
+
+  ClimbVector:
+    prev = indirect_node(this);
+    indirect_node(this) = next;
+
+  MarkVectorLoop:
+    this -= node_size;
+    next = indirect_node(this);
+#ifdef X8664
+    if ((tag_of(this) == tag_function) &&
+        (header_subtag(next) == function_boundary_marker)) goto MarkFunctionDone;
+#else
+    if ((tag_of(this) == tag_misc) &&
+        (header_subtag(next) == function_boundary_marker)) goto MarkFunctionDone;
+#endif
+
+    tag_n = fulltag_of(next);
+    if (nodeheader_tag_p(tag_n)) goto MarkVectorDone;
+    if (!is_node_fulltag(tag_n)) goto MarkVectorLoop;
+    dnode = gc_area_dnode(next);
+    if (dnode >= GCndnodes_in_area) goto MarkVectorLoop;
+    set_bits_vars(markbits,dnode,bitsp,bits,mask);
+    if (bits & mask) goto MarkVectorLoop;
+    *bitsp = (bits | mask);
+    indirect_node(this) = prev;
+    if (tag_n == fulltag_cons) goto DescendCons;
+    goto DescendVector;
+
+  MarkVectorDone:
+    /* "next" is vector header; "this" tagged tag_misc or tag_symbol.
+       If  header subtag = subtag_weak_header, put it on weakvll */
+    this += node_size;          /* make it fulltag_misc/fulltag_symbol */
+
+    if (header_subtag(next) == subtag_weak) {
+      deref(this, 1) = GCweakvll;
+      GCweakvll = this;
+    }
+    goto Climb;
+
+  MarkFunctionDone:
+    boundary = (LispObj *)(node_aligned(this));
+#ifdef X8664
+    this = ((LispObj)boundary) + (((int *)boundary)[1]);
+    (((int *)boundary)[1]) = 0;
+#else
+    this = ((LispObj)boundary) + ((*((int *)boundary)) >> 8);
+    ((int *)boundary)[0] &= 0xff;
+#endif
+    goto Climb;
+  }
+}
+
+LispObj *
+skip_over_ivector(natural start, LispObj header)
+{
+  natural 
+    element_count = header_element_count(header),
+    subtag = header_subtag(header),
+    nbytes;
+
+
+#ifdef X8664
+  switch (fulltag_of(header)) {
+  case ivector_class_64_bit:
+    nbytes = element_count << 3;
+    break;
+  case ivector_class_32_bit:
+    nbytes = element_count << 2;
+    break;
+  case ivector_class_other_bit:
+  default:
+    if (subtag == subtag_bit_vector) {
+      nbytes = (element_count+7)>>3;
+    } else if (subtag >= min_8_bit_ivector_subtag) {
+      nbytes = element_count;
+    } else {
+      nbytes = element_count << 1;
+    }
+  }
+  return ptr_from_lispobj(start+(~15 & (nbytes + 8 + 15)));
+#else
+  if (subtag <= max_32_bit_ivector_subtag) {
+    nbytes = element_count << 2;
+  } else if (subtag <= max_8_bit_ivector_subtag) {
+    nbytes = element_count;
+  } else if (subtag <= max_16_bit_ivector_subtag) {
+    nbytes = element_count << 1;
+  } else if (subtag == subtag_double_float_vector) {
+    nbytes = 4 + (element_count << 3);
+  } else {
+    nbytes = (element_count+7) >> 3;
+  }
+  return ptr_from_lispobj(start+(~7 & (nbytes + 4 + 7)));
+#endif
+}
+
+
+void
+check_refmap_consistency(LispObj *start, LispObj *end, bitvector refbits)
+{
+  LispObj x1, *base = start, *prev = start;
+  int tag;
+  natural ref_dnode, node_dnode;
+  Boolean intergen_ref;
+
+  while (start < end) {
+    x1 = *start;
+    prev = start;
+    tag = fulltag_of(x1);
+    if (immheader_tag_p(tag)) {
+      start = skip_over_ivector(ptr_to_lispobj(start), x1);
+    } else {
+      if (header_subtag(x1) == subtag_function) {
+#ifdef X8632
+	int skip = (unsigned short)deref(start,1);
+	/* XXX bootstrapping */
+	if (skip & 0x8000)
+	  skip = header_element_count(x1) - (skip & 0x7fff);
+#else
+        int skip = (int) deref(start,1);
+#endif
+        start += ((1+skip)&~1);
+        x1 = *start;
+        tag = fulltag_of(x1);
+      }
+      intergen_ref = false;
+      if (is_node_fulltag(tag)) {        
+        node_dnode = gc_area_dnode(x1);
+        if (node_dnode < GCndnodes_in_area) {
+          intergen_ref = true;
+        }
+      }
+      if (intergen_ref == false) {        
+        x1 = start[1];
+        tag = fulltag_of(x1);
+        if (is_node_fulltag(tag)) {        
+          node_dnode = gc_area_dnode(x1);
+          if (node_dnode < GCndnodes_in_area) {
+            intergen_ref = true;
+          }
+        }
+      }
+      if (intergen_ref) {
+        ref_dnode = area_dnode(start, base);
+        if (!ref_bit(refbits, ref_dnode)) {
+          Bug(NULL, "Missing memoization in doublenode at 0x" LISP, start);
+          set_bit(refbits, ref_dnode);
+        }
+      }
+      start += 2;
+    }
+  }
+  if (start > end) {
+    Bug(NULL, "Overran end of range!");
+  }
+}
+
+
+
+void
+mark_memoized_area(area *a, natural num_memo_dnodes)
+{
+  bitvector refbits = a->refbits;
+  LispObj *p = (LispObj *) a->low, x1, x2;
+  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
+  Boolean keep_x1, keep_x2;
+
+  if (GCDebug) {
+    check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
+  }
+
+  /* The distinction between "inbits" and "outbits" is supposed to help us
+     detect cases where "uninteresting" setfs have been memoized.  Storing
+     NIL, fixnums, immediates (characters, etc.) or node pointers to static
+     or readonly areas is definitely uninteresting, but other cases are
+     more complicated (and some of these cases are hard to detect.)
+
+     Some headers are "interesting", to the forwarder if not to us. 
+
+     We -don't- give anything any weak treatment here.  Weak things have
+     to be seen by a full gc, for some value of 'full'.
+     */
+
+  /*
+    We need to ensure that there are no bits set at or beyond
+    "num_memo_dnodes" in the bitvector.  (This can happen as the EGC
+    tenures/untenures things.)  We find bits by grabbing a fullword at
+    a time and doing a cntlzw instruction; and don't want to have to
+    check for (< memo_dnode num_memo_dnodes) in the loop.
+    */
+
+  {
+    natural 
+      bits_in_last_word = (num_memo_dnodes & bitmap_shift_count_mask),
+      index_of_last_word = (num_memo_dnodes >> bitmap_shift);
+
+    if (bits_in_last_word != 0) {
+      natural mask = ~((NATURAL1<<(nbits_in_word-bits_in_last_word))- NATURAL1);
+      refbits[index_of_last_word] &= mask;
+    }
+  }
+        
+  set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
+  inbits = outbits = bits;
+  while (memo_dnode < num_memo_dnodes) {
+    if (bits == 0) {
+      int remain = nbits_in_word - bitidx;
+      memo_dnode += remain;
+      p += (remain+remain);
+      if (outbits != inbits) {
+        *bitsp = outbits;
+      }
+      bits = *++bitsp;
+      inbits = outbits = bits;
+      bitidx = 0;
+    } else {
+      nextbit = count_leading_zeros(bits);
+      if ((diff = (nextbit - bitidx)) != 0) {
+        memo_dnode += diff;
+        bitidx = nextbit;
+        p += (diff+diff);
+      }
+      x1 = *p++;
+      x2 = *p++;
+      bits &= ~(BIT0_MASK >> bitidx);
+      keep_x1 = mark_ephemeral_root(x1);
+      keep_x2 = mark_ephemeral_root(x2);
+      if ((keep_x1 == false) && 
+          (keep_x2 == false)) {
+        outbits &= ~(BIT0_MASK >> bitidx);
+      }
+      memo_dnode++;
+      bitidx++;
+    }
+  }
+  if (GCDebug) {
+    p = (LispObj *) a->low;
+    check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
+  }
+}
+
+void
+mark_headerless_area_range(LispObj *start, LispObj *end)
+{
+  while (start < end) {
+    mark_root(*start++);
+  }
+}
+
+void
+mark_simple_area_range(LispObj *start, LispObj *end)
+{
+  LispObj x1, *base;
+  int tag;
+
+  while (start < end) {
+    x1 = *start;
+    tag = fulltag_of(x1);
+    if (immheader_tag_p(tag)) {
+      start = (LispObj *)ptr_from_lispobj(skip_over_ivector(ptr_to_lispobj(start), x1));
+    } else if (!nodeheader_tag_p(tag)) {
+      ++start;
+      mark_root(x1);
+      mark_root(*start++);
+    } else {
+      int subtag = header_subtag(x1);
+      natural element_count = header_element_count(x1);
+      natural size = (element_count+1 + 1) & ~1;
+
+      if (subtag == subtag_hash_vector) {
+        LispObj flags = ((hash_table_vector_header *) start)->flags;
+
+        if (flags & nhash_weak_mask) {
+          ((hash_table_vector_header *) start)->cache_key = undefined;
+          ((hash_table_vector_header *) start)->cache_value = lisp_nil;
+          mark_weak_htabv((LispObj)start);
+	  element_count = 0;
+	}
+      } 
+      if (subtag == subtag_pool) {
+	start[1] = lisp_nil;
+      }
+
+      if (subtag == subtag_weak) {
+	natural weak_type = (natural) start[2];
+	if (weak_type >> population_termination_bit)
+	  element_count -= 2;
+	else
+	  element_count -= 1; 
+	start[1] = GCweakvll;
+	GCweakvll = (LispObj) (((natural) start) + fulltag_misc);    
+      }
+
+      base = start + element_count + 1;
+      if (subtag == subtag_function) {
+#ifdef X8632
+	natural skip = (unsigned short)start[1];
+
+	/* XXX bootstrapping */
+	if (skip & 0x8000)
+	  skip = element_count - (skip & 0x7fff);
+
+	element_count -= skip;
+
+#else
+	element_count -= (int)start[1];
+#endif
+      }
+      while(element_count--) {
+	mark_root(*--base);
+      }
+      start += size;
+    }
+  }
+}
+
+
+/* Mark a tstack area */
+void
+mark_tstack_area(area *a)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) (a->active),
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = (LispObj *) ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    mark_simple_area_range(current+2, end);
+  }
+}
+
+/*
+  It's really important that headers never wind up in tagged registers.
+  Those registers would (possibly) get pushed on the vstack and confuse
+  the hell out of this routine.
+
+  vstacks are just treated as a "simple area range", possibly with
+  an extra word at the top (where the area's active pointer points.)
+  */
+
+void
+mark_vstack_area(area *a)
+{
+  LispObj
+    *start = (LispObj *) a->active,
+    *end = (LispObj *) a->high;
+
+#if 0
+  fprintf(dbgout, "mark VSP range: 0x" LISP ":0x" LISP "\n", start, end);
+#endif
+  mark_headerless_area_range(start, end);
+}
+
+/* No lisp objects on cstack on x86, at least x86-64 */
+void
+mark_cstack_area(area *a)
+{
+}
+
+
+/* Mark the lisp objects in an exception frame */
+#ifdef X8664
+void
+mark_xp(ExceptionInformation *xp)
+{
+  natural *regs = (natural *) xpGPRvector(xp), dnode;
+  LispObj rip;
+    
+  
+
+  mark_root(regs[Iarg_z]);
+  mark_root(regs[Iarg_y]);
+  mark_root(regs[Iarg_x]);
+  mark_root(regs[Isave3]);
+  mark_root(regs[Isave2]);
+  mark_root(regs[Isave1]);
+  mark_root(regs[Isave0]);
+  mark_root(regs[Ifn]);
+  mark_root(regs[Itemp0]);
+  mark_root(regs[Itemp1]);
+  mark_root(regs[Itemp2]);
+  /* If the RIP isn't pointing into a marked function,
+     we can -maybe- recover from that if it's tagged as
+     a TRA. */
+  rip = regs[Iip];
+  dnode = gc_area_dnode(rip);
+  if ((dnode < GCndnodes_in_area) &&
+      (! ref_bit(GCmarkbits,dnode))) {
+    if (tag_of(rip) == tag_tra) {
+      mark_root(rip);
+    } else if ((fulltag_of(rip) == fulltag_function) &&
+               (*((unsigned short *)rip) == RECOVER_FN_FROM_RIP_WORD0) &&
+               (*((unsigned char *)(rip+2)) == RECOVER_FN_FROM_RIP_BYTE2) &&
+               ((*(int *) (rip+3))) == -RECOVER_FN_FROM_RIP_LENGTH) {
+      mark_root(rip);
+    } else {
+      Bug(NULL, "Can't find function for rip 0x%16lx",rip);
+    }
+  }
+}
+#else
+void
+mark_xp(ExceptionInformation *xp, natural node_regs_mask)
+{
+  natural *regs = (natural *) xpGPRvector(xp), dnode;
+  LispObj eip;
+  int i;
+
+  if (node_regs_mask & (1<<0)) mark_root(regs[REG_EAX]);
+  if (node_regs_mask & (1<<1)) mark_root(regs[REG_ECX]);
+  if (regs[REG_EFL] & EFL_DF) {
+    /* DF set means EDX should be treated as an imm reg */
+    ;
+  } else
+    if (node_regs_mask & (1<<2)) mark_root(regs[REG_EDX]);
+
+  if (node_regs_mask & (1<<3)) mark_root(regs[REG_EBX]);
+  if (node_regs_mask & (1<<4)) mark_root(regs[REG_ESP]);
+  if (node_regs_mask & (1<<5)) mark_root(regs[REG_EBP]);
+  if (node_regs_mask & (1<<6)) mark_root(regs[REG_ESI]);
+  if (node_regs_mask & (1<<7)) mark_root(regs[REG_EDI]);
+
+  /* If the EIP isn't pointing into a marked function, we're probably
+     in trouble.  We can -maybe- recover from that if it's tagged as a
+     TRA. */
+  eip = regs[Ieip];
+  dnode = gc_area_dnode(eip);
+  if ((dnode < GCndnodes_in_area) &&
+      (! ref_bit(GCmarkbits,dnode))) {
+    if (fulltag_of(eip) == fulltag_tra) {
+      mark_root(eip);
+    } else if ((fulltag_of(eip) == fulltag_misc) &&
+               (header_subtag(header_of(eip)) == subtag_function) &&
+               (*(unsigned char *)eip == RECOVER_FN_OPCODE) &&
+	       (*(LispObj *)(eip + 1)) == eip) {
+      mark_root(eip);
+    } else {
+      Bug(NULL, "Can't find function for eip 0x%4x", eip);
+    }
+  }
+}
+#endif
+
+/* A "pagelet" contains 32 doublewords.  The relocation table contains
+   a word for each pagelet which defines the lowest address to which
+   dnodes on that pagelet will be relocated.
+
+   The relocation address of a given pagelet is the sum of the relocation
+   address for the preceding pagelet and the number of bytes occupied by
+   marked objects on the preceding pagelet.
+*/
+
+LispObj
+calculate_relocation()
+{
+  LispObj *relocptr = GCrelocptr;
+  LispObj current = GCareadynamiclow;
+  bitvector 
+    markbits = GCdynamic_markbits;
+  qnode *q = (qnode *) markbits;
+  natural npagelets = ((GCndynamic_dnodes_in_area+(nbits_in_word-1))>>bitmap_shift);
+  natural thesebits;
+  LispObj first = 0;
+
+  if (npagelets) {
+    do {
+      *relocptr++ = current;
+      thesebits = *markbits++;
+      if (thesebits == ALL_ONES) {
+        current += nbits_in_word*dnode_size;
+        q += 4; /* sic */
+      } else {
+        if (!first) {
+          first = current;
+          while (thesebits & BIT0_MASK) {
+            first += dnode_size;
+            thesebits += thesebits;
+          }
+        }
+        /* We're counting bits in qnodes in the wrong order here, but
+           that's OK.  I think ... */
+        current += one_bits(*q++);
+        current += one_bits(*q++);
+        current += one_bits(*q++);
+        current += one_bits(*q++);
+      }
+    } while(--npagelets);
+  }
+  *relocptr++ = current;
+  return first ? first : current;
+}
+
+
+#if 0
+LispObj
+dnode_forwarding_address(natural dnode, int tag_n)
+{
+  natural pagelet, nbits;
+  unsigned int near_bits;
+  LispObj new;
+
+  if (GCDebug) {
+    if (! ref_bit(GCdynamic_markbits, dnode)) {
+      Bug(NULL, "unmarked object being forwarded!\n");
+    }
+  }
+
+  pagelet = dnode >> bitmap_shift;
+  nbits = dnode & bitmap_shift_count_mask;
+  near_bits = ((unsigned int *)GCdynamic_markbits)[dnode>>(dnode_shift+1)];
+
+  if (nbits < 32) {
+    new = GCrelocptr[pagelet] + tag_n;;
+    /* Increment "new" by the count of 1 bits which precede the dnode */
+    if (near_bits == 0xffffffff) {
+      return (new + (nbits << 4));
+    } else {
+      near_bits &= (0xffffffff00000000 >> nbits);
+      if (nbits > 15) {
+        new += one_bits(near_bits & 0xffff);
+      }
+      return (new + (one_bits(near_bits >> 16))); 
+    }
+  } else {
+    new = GCrelocptr[pagelet+1] + tag_n;
+    nbits = 64-nbits;
+
+    if (near_bits == 0xffffffff) {
+      return (new - (nbits << 4));
+    } else {
+      near_bits &= (1<<nbits)-1;
+      if (nbits > 15) {
+        new -= one_bits(near_bits >> 16);
+      }
+      return (new -  one_bits(near_bits & 0xffff));
+    }
+  }
+}
+#else
+#ifdef X8664
+/* Quicker, dirtier */
+LispObj
+dnode_forwarding_address(natural dnode, int tag_n)
+{
+  natural pagelet, nbits, marked;
+  LispObj new;
+
+  if (GCDebug) {
+    if (! ref_bit(GCdynamic_markbits, dnode)) {
+      Bug(NULL, "unmarked object being forwarded!\n");
+    }
+  }
+
+  pagelet = dnode >> bitmap_shift;
+  nbits = dnode & bitmap_shift_count_mask;
+  new = GCrelocptr[pagelet] + tag_n;;
+  if (nbits) {
+    marked = (GCdynamic_markbits[dnode>>bitmap_shift]) >> (64-nbits);
+    while (marked) {
+      new += one_bits((qnode)marked);
+      marked >>=16;
+    }
+  }
+  return new;
+}
+#endif
+#ifdef X8632
+LispObj
+dnode_forwarding_address(natural dnode, int tag_n)
+{
+  natural pagelet, nbits;
+  unsigned short near_bits;
+  LispObj new;
+
+  if (GCDebug) {
+    if (! ref_bit(GCdynamic_markbits, dnode)) {
+      Bug(NULL, "unmarked object being forwarded!\n");
+    }
+  }
+
+  pagelet = dnode >> 5;
+  nbits = dnode & 0x1f;
+  /* On little-endian x86, we have to flip the low bit of dnode>>4 to
+     get the near_bits from the appropriate half-word. */
+  near_bits = ((unsigned short *)GCdynamic_markbits)[(dnode>>4)^1];
+
+  if (nbits < 16) {
+    new = GCrelocptr[pagelet] + tag_n;;
+    /* Increment "new" by the count of 1 bits which precede the dnode */
+    if (near_bits == 0xffff) {
+      return (new + (nbits << 3));
+    } else {
+      near_bits &= (0xffff0000 >> nbits);
+      if (nbits > 7) {
+        new += one_bits(near_bits & 0xff);
+      }
+      return (new + (one_bits(near_bits >> 8))); 
+    }
+  } else {
+    new = GCrelocptr[pagelet+1] + tag_n;
+    nbits = 32-nbits;
+
+    if (near_bits == 0xffff) {
+      return (new - (nbits << 3));
+    } else {
+      near_bits &= (1<<nbits)-1;
+      if (nbits > 7) {
+        new -= one_bits(near_bits >> 8);
+      }
+      return (new - one_bits(near_bits & 0xff));
+    }
+  }
+}
+#endif
+#endif
+
+LispObj
+locative_forwarding_address(LispObj obj)
+{
+  int tag_n = fulltag_of(obj);
+  natural dnode = gc_dynamic_area_dnode(obj);
+
+
+  if ((dnode >= GCndynamic_dnodes_in_area) ||
+      (obj < GCfirstunmarked)) {
+    return obj;
+  }
+
+  return dnode_forwarding_address(dnode, tag_n);
+}
+
+
+void
+forward_headerless_range(LispObj *range_start, LispObj *range_end)
+{
+  LispObj *p = range_start;
+
+  while (p < range_end) {
+    update_noderef(p);
+    p++;
+  }
+}
+
+void
+forward_range(LispObj *range_start, LispObj *range_end)
+{
+  LispObj *p = range_start, node, new;
+  int tag_n;
+  natural nwords;
+  hash_table_vector_header *hashp;
+
+  while (p < range_end) {
+    node = *p;
+    tag_n = fulltag_of(node);
+    if (immheader_tag_p(tag_n)) {
+      p = (LispObj *) skip_over_ivector((natural) p, node);
+    } else if (nodeheader_tag_p(tag_n)) {
+      nwords = header_element_count(node);
+      nwords += (1 - (nwords&1));
+      if ((header_subtag(node) == subtag_hash_vector) &&
+          ((((hash_table_vector_header *)p)->flags) & nhash_track_keys_mask)) {
+        natural skip = hash_table_vector_header_count-1;
+        hashp = (hash_table_vector_header *) p;
+        p++;
+        nwords -= skip;
+        while(skip--) {
+          update_noderef(p);
+          p++;
+        }
+        /* "nwords" is odd at this point: there are (floor nwords 2)
+           key/value pairs to look at, and then an extra word for
+           alignment.  Process them two at a time, then bump "p"
+           past the alignment word. */
+        nwords >>= 1;
+        while(nwords--) {
+          if (update_noderef(p) && hashp) {
+            hashp->flags |= nhash_key_moved_mask;
+            hashp = NULL;
+          }
+          p++;
+          update_noderef(p);
+          p++;
+        }
+        *p++ = 0;
+      } else {
+	if (header_subtag(node) == subtag_function) {
+#ifdef X8632
+	  int skip = (unsigned short)(p[1]);
+
+	  /* XXX bootstrapping */
+	  if (skip & 0x8000)
+	    skip = header_element_count(node) - (skip & 0x7fff);
+
+#else
+	  int skip = (int)(p[1]);
+#endif
+	  p += skip;
+	  nwords -= skip;
+	}
+        p++;
+        while(nwords--) {
+          update_noderef(p);
+          p++;
+        }
+      }
+    } else {
+      new = node_forwarding_address(node);
+      if (new != node) {
+        *p = new;
+      }
+      p++;
+      update_noderef(p);
+      p++;
+    }
+  }
+}
+
+
+
+
+
+
+/* Forward a tstack area */
+void
+forward_tstack_area(area *a)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) a->active,
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    forward_range(current+2, end);
+  }
+}
+
+/* Forward a vstack area */
+void
+forward_vstack_area(area *a)
+{
+  LispObj
+    *p = (LispObj *) a->active,
+    *q = (LispObj *) a->high;
+
+  forward_headerless_range(p, q);
+}
+
+/* Nothing of interest on x86 cstack */
+void
+forward_cstack_area(area *a)
+{
+}
+
+#ifdef X8664
+void
+forward_xp(ExceptionInformation *xp)
+{
+  natural *regs = (natural *) xpGPRvector(xp);
+
+  update_noderef(&(regs[Iarg_z]));
+  update_noderef(&(regs[Iarg_y]));
+  update_noderef(&(regs[Iarg_x]));
+  update_noderef(&(regs[Isave3]));
+  update_noderef(&(regs[Isave2]));
+  update_noderef(&(regs[Isave1]));
+  update_noderef(&(regs[Isave0]));
+  update_noderef(&(regs[Ifn]));
+  update_noderef(&(regs[Itemp0]));
+  update_noderef(&(regs[Itemp1]));
+  update_noderef(&(regs[Itemp2]));
+  update_locref(&(regs[Iip]));
+}
+#else
+void
+forward_xp(ExceptionInformation *xp, natural node_regs_mask)
+{
+  natural *regs = (natural *) xpGPRvector(xp);
+
+  if (node_regs_mask & (1<<0)) update_noderef(&regs[REG_EAX]);
+  if (node_regs_mask & (1<<1)) update_noderef(&regs[REG_ECX]);
+
+  if (regs[REG_EFL] & EFL_DF) {
+    /* then EDX is an imm reg */
+    ;
+  } else
+    if (node_regs_mask & (1<<2)) update_noderef(&regs[REG_EDX]);
+
+  if (node_regs_mask & (1<<3)) update_noderef(&regs[REG_EBX]);
+  if (node_regs_mask & (1<<4)) update_noderef(&regs[REG_ESP]);
+  if (node_regs_mask & (1<<5)) update_noderef(&regs[REG_EBP]);
+  if (node_regs_mask & (1<<6)) update_noderef(&regs[REG_ESI]);
+  if (node_regs_mask & (1<<7)) update_noderef(&regs[REG_EDI]);
+
+  update_locref(&(regs[Iip]));
+}
+#endif
+
+
+void
+forward_tcr_xframes(TCR *tcr)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+
+  xp = tcr->gc_context;
+  if (xp) {
+#ifdef X8664
+    forward_xp(xp);
+#else
+    forward_xp(xp, tcr->node_regs_mask);
+
+    update_noderef(&tcr->save0);
+    update_noderef(&tcr->save1);
+    update_noderef(&tcr->save2);
+    update_noderef(&tcr->save3);
+    update_noderef(&tcr->next_method_context);
+#endif
+  }
+  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
+#ifdef X8664
+    forward_xp(xframes->curr);
+#else
+    forward_xp(xframes->curr, xframes->node_regs_mask);
+#endif
+  }
+}
+
+
+#ifdef X8632
+void
+update_self_references(LispObj *node)
+{
+  LispObj fn = fulltag_misc + (LispObj)node;
+  unsigned char *p = (unsigned char *)node;
+  natural i = imm_word_count(fn);
+
+  if (i) {
+    natural offset = node[--i];
+
+    while (offset) {
+      *(LispObj *)(p + offset) = fn;
+      offset = node[--i];
+    }
+  }    
+}
+#endif
+
+/*
+  Compact the dynamic heap (from GCfirstunmarked through its end.)
+  Return the doublenode address of the new freeptr.
+  */
+
+LispObj
+compact_dynamic_heap()
+{
+  LispObj *src = ptr_from_lispobj(GCfirstunmarked), *dest = src, node, new, *current,  *prev = NULL;
+  natural 
+    elements, 
+    dnode = gc_area_dnode(GCfirstunmarked), 
+    node_dnodes = 0, 
+    imm_dnodes = 0, 
+    bitidx, 
+    *bitsp, 
+    bits, 
+    nextbit, 
+    diff;
+  int tag;
+  bitvector markbits = GCmarkbits;
+
+  if (dnode < GCndnodes_in_area) {
+    lisp_global(FWDNUM) += (1<<fixnum_shift);
+  
+    set_bitidx_vars(markbits,dnode,bitsp,bits,bitidx);
+    while (dnode < GCndnodes_in_area) {
+      if (bits == 0) {
+        int remain = nbits_in_word - bitidx;
+        dnode += remain;
+        src += (remain+remain);
+        bits = *++bitsp;
+        bitidx = 0;
+      } else {
+        /* Have a non-zero markbits word; all bits more significant
+           than "bitidx" are 0.  Count leading zeros in "bits"
+           (there'll be at least "bitidx" of them.)  If there are more
+           than "bitidx" leading zeros, bump "dnode", "bitidx", and
+           "src" by the difference. */
+        nextbit = count_leading_zeros(bits);
+        if ((diff = (nextbit - bitidx)) != 0) {
+          dnode += diff;
+          bitidx = nextbit;
+          src += (diff+diff);
+        }
+        prev = current;
+        current = src;
+        if (GCDebug) {
+          if (dest != ptr_from_lispobj(locative_forwarding_address(ptr_to_lispobj(src)))) {
+            Bug(NULL, "Out of synch in heap compaction.  Forwarding from 0x" LISP " to 0x" LISP ",\n expected to go to 0x" LISP "\n", 
+                src, dest, locative_forwarding_address(ptr_to_lispobj(src)));
+          }
+        }
+
+        node = *src++;
+        tag = fulltag_of(node);
+        if (nodeheader_tag_p(tag)) {
+          elements = header_element_count(node);
+          node_dnodes = (elements+2)>>1;
+          dnode += node_dnodes;
+	  if (header_subtag(node) == subtag_function) {
+#ifdef X8632
+	    LispObj *f = dest;
+	    int skip = imm_word_count(fulltag_misc + (LispObj)current);
+#else
+	    int skip = *((int *)src);
+#endif
+	    *dest++ = node;
+            if (skip) {
+              elements -= skip;
+              while(skip--) {
+                *dest++ = *src++;
+              }
+#ifdef X8632
+              update_self_references(f);
+#endif
+            }
+	    while(elements--) {
+	      *dest++ = node_forwarding_address(*src++);
+	    }
+	    if (((LispObj)src) & node_size) {
+	      src++;
+	      *dest++ = 0;
+	    }
+	  } else {
+	    if ((header_subtag(node) == subtag_hash_vector) &&
+		(((hash_table_vector_header *) (src-1))->flags & nhash_track_keys_mask)) {
+	      hash_table_vector_header *hashp = (hash_table_vector_header *) dest;
+	      int skip = (sizeof(hash_table_vector_header)/sizeof(LispObj))-1;
+	      
+	      *dest++ = node;
+	      elements -= skip;
+	      while(skip--) {
+		*dest++ = node_forwarding_address(*src++);
+	      }
+	      /* There should be an even number of (key/value) pairs in elements;
+		 an extra alignment word follows. */
+	      elements >>= 1;
+	      while (elements--) {
+		if (hashp) {
+		  node = *src++;
+		  new = node_forwarding_address(node);
+		  if (new != node) {
+		    hashp->flags |= nhash_key_moved_mask;
+		    hashp = NULL;
+		    *dest++ = new;
+		  } else {
+		    *dest++ = node;
+		  }
+		} else {
+		  *dest++ = node_forwarding_address(*src++);
+		}
+		*dest++ = node_forwarding_address(*src++);
+	      }
+	      *dest++ = 0;
+	      src++;
+	    } else {
+	      *dest++ = node;
+	      *dest++ = node_forwarding_address(*src++);
+	      while(--node_dnodes) {
+		*dest++ = node_forwarding_address(*src++);
+		*dest++ = node_forwarding_address(*src++);
+	      }
+	    }
+          }
+          set_bitidx_vars(markbits,dnode,bitsp,bits,bitidx);
+        } else if (immheader_tag_p(tag)) {
+          *dest++ = node;
+          *dest++ = *src++;
+          elements = header_element_count(node);
+          tag = header_subtag(node);
+
+#ifdef X8664
+          switch(fulltag_of(tag)) {
+          case ivector_class_64_bit:
+            imm_dnodes = ((elements+1)+1)>>1;
+            break;
+          case ivector_class_32_bit:
+            imm_dnodes = (((elements+2)+3)>>2);
+            break;
+          case ivector_class_other_bit:
+            if (tag == subtag_bit_vector) {
+              imm_dnodes = (((elements+64)+127)>>7);
+	    } else if (tag >= min_8_bit_ivector_subtag) {
+	      imm_dnodes = (((elements+8)+15)>>4);
+            } else {
+              imm_dnodes = (((elements+4)+7)>>3);
+            }
+          }
+#endif
+#ifdef X8632
+          if (tag <= max_32_bit_ivector_subtag) {
+            imm_dnodes = (((elements+1)+1)>>1);
+          } else if (tag <= max_8_bit_ivector_subtag) {
+            imm_dnodes = (((elements+4)+7)>>3);
+          } else if (tag <= max_16_bit_ivector_subtag) {
+            imm_dnodes = (((elements+2)+3)>>2);
+          } else if (tag == subtag_bit_vector) {
+            imm_dnodes = (((elements+32)+63)>>6);
+          } else {
+            imm_dnodes = elements+1;
+          }
+#endif
+
+          dnode += imm_dnodes;
+          while (--imm_dnodes) {
+            *dest++ = *src++;
+            *dest++ = *src++;
+          }
+          set_bitidx_vars(markbits,dnode,bitsp,bits,bitidx);
+        } else {
+          *dest++ = node_forwarding_address(node);
+          *dest++ = node_forwarding_address(*src++);
+          bits &= ~(BIT0_MASK >> bitidx);
+          dnode++;
+          bitidx++;
+        }
+      }
+    }
+  }
+  return ptr_to_lispobj(dest);
+}
+
+
+#define PURIFY_IVECTORS (1<<0)
+#define PURIFY_FUNCTIONS (1<<1)
+#define PURIFY_ALL (-1)
+#define PURIFY_NOTHING (0)      /* update forwarding pointers, don't copy */
+
+
+
+Boolean
+immutable_function_p(LispObj thing)
+{
+  LispObj header = header_of(thing), lfbits;
+  if (header_subtag(header) == subtag_function) {
+    lfbits = deref(thing,header_element_count(header));
+    if (((lfbits & (lfbits_cm_mask | lfbits_method_mask)) !=
+         lfbits_cm_mask) &&
+        ((lfbits & (lfbits_gfn_mask | lfbits_method_mask)) !=
+         lfbits_gfn_mask)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+    
+/*
+  Total the (physical) byte sizes of all ivectors in the indicated memory range
+*/
+
+natural
+unboxed_bytes_in_range(LispObj *start, LispObj *end, Boolean include_functions)
+{
+  natural total=0, elements, tag, subtag, bytes;
+  LispObj header;
+
+  while (start < end) {
+    header = *start;
+    tag = fulltag_of(header);
+    
+    if ((nodeheader_tag_p(tag)) ||
+        (immheader_tag_p(tag))) {
+      elements = header_element_count(header);
+      if (nodeheader_tag_p(tag)) {
+        if (include_functions && immutable_function_p((LispObj)start)) {
+          total += (((elements+2)&~1)<<node_shift);
+        }
+        start += ((elements+2) & ~1);
+      } else {
+        subtag = header_subtag(header);
+
+#ifdef X8664
+        switch(fulltag_of(header)) {
+        case ivector_class_64_bit:
+          bytes = 8 + (elements<<3);
+          break;
+        case ivector_class_32_bit:
+          bytes = 8 + (elements<<2);
+          break;
+        case ivector_class_other_bit:
+        default:
+          if (subtag == subtag_bit_vector) {
+            bytes = 8 + ((elements+7)>>3);
+	  } else if (subtag >= min_8_bit_ivector_subtag) {
+	    bytes = 8 + elements;
+          } else {
+            bytes = 8 + (elements<<1);
+          }
+        }
+#endif
+#ifdef X8632
+          if (subtag <= max_32_bit_ivector_subtag) {
+            bytes = 4 + (elements<<2);
+          } else if (subtag <= max_8_bit_ivector_subtag) {
+            bytes = 4 + elements;
+          } else if (subtag <= max_16_bit_ivector_subtag) {
+            bytes = 4 + (elements<<1);
+          } else if (subtag == subtag_double_float_vector) {
+            bytes = 8 + (elements<<3);
+          } else {
+            bytes = 4 + ((elements+7)>>3);
+          }
+#endif
+
+        bytes = (bytes+dnode_size-1) & ~(dnode_size-1);
+        total += bytes;
+        start += (bytes >> node_shift);
+      }
+    } else {
+      start += 2;
+    }
+  }
+  return total;
+}
+
+
+void
+ensure_writable_space(area *target, natural need)
+{
+  BytePtr
+    oldlimit = (BytePtr)align_to_power_of_2(target->active,log2_page_size),
+    newlimit = (BytePtr)align_to_power_of_2(target->active+need,log2_page_size);
+  if (newlimit > oldlimit) {
+    CommitMemory(oldlimit,newlimit-oldlimit);
+  }
+}
+
+LispObj
+purify_displaced_object(LispObj obj, area *dest, natural disp)
+{
+  BytePtr 
+    free = dest->active,
+    *old = (BytePtr *) ptr_from_lispobj(untag(obj));
+  LispObj 
+    header = header_of(obj), 
+    new;
+  natural 
+    start = (natural)old,
+    physbytes;
+  int
+    header_tag = fulltag_of(header);
+#ifdef X8632
+  Boolean
+    is_function = (header_subtag(header)==subtag_function);
+#endif
+
+  if (immheader_tag_p(header_tag)) {
+    physbytes = ((natural)(skip_over_ivector(start,header))) - start;
+  } else if (nodeheader_tag_p(header_tag)) {
+    physbytes = ((header_element_count(header)+2)&~1) << node_shift;
+  } else {
+    physbytes = dnode_size;
+  }
+  
+  ensure_writable_space(dest, physbytes);
+  dest->active += physbytes;
+
+  new = ptr_to_lispobj(free)+disp;
+
+  memcpy(free, (BytePtr)old, physbytes);
+
+#ifdef X8632
+  if (is_function) {
+    update_self_references((LispObj *)free);
+  }
+#endif
+
+
+  while(physbytes) {
+    *old++ = (BytePtr) forward_marker;
+    *old++ = (BytePtr) free;
+    free += dnode_size;
+    physbytes -= dnode_size;
+  }
+  return new;
+}
+
+LispObj
+purify_object(LispObj obj, area *dest)
+{
+  return purify_displaced_object(obj, dest, fulltag_of(obj));
+}
+
+Boolean
+purify_locref(LispObj *ref,  BytePtr low, BytePtr high, area *dest, int what)
+{
+  LispObj obj = *ref, header, new;
+  natural tag = fulltag_of(obj), header_tag;
+  Boolean changed = false;
+
+  if ((((BytePtr)ptr_from_lispobj(obj)) > low) &&
+      (((BytePtr)ptr_from_lispobj(obj)) < high)) {
+    header = deref(obj, 0);
+    if (header == forward_marker) { /* already copied */
+      *ref = (untag(deref(obj,1)) + tag);
+      changed = true;
+    } else {
+      header_tag = fulltag_of(header);
+      if ((what == PURIFY_ALL) ||
+          ((what & PURIFY_IVECTORS) &&
+           immheader_tag_p(header_tag) &&
+           header_subtag(header) != subtag_macptr) ||
+          ((what & PURIFY_FUNCTIONS) &&
+           immutable_function_p(obj))) {
+        new = purify_object(obj, dest);
+        *ref = new;
+        changed = (new != obj);
+      }
+    }
+  }
+  return changed;
+}
+
+Boolean
+copy_reference(LispObj *ref, BytePtr low, BytePtr high, area *dest, int what)
+{
+  LispObj obj = *ref;
+  natural tag = fulltag_of(obj);
+
+  if (
+#ifdef X8664
+      (tag == fulltag_tra_0) || (tag == fulltag_tra_1)
+#endif
+#ifdef X8632
+      tag == fulltag_tra
+#endif
+      ) {
+    what = PURIFY_NOTHING;
+  }
+  if (is_node_fulltag(tag)) {
+    return purify_locref(ref,low,high,dest,what);
+  }
+  return false;
+}
+
+
+
+void
+purify_gcable_ptrs(BytePtr low, BytePtr high, area *to, int what)
+{
+  LispObj *prev = &(lisp_global(GCABLE_POINTERS)), next;
+
+  while ((*prev) != (LispObj)NULL) {
+    copy_reference(prev, low, high, to, what);
+    next = *prev;
+    prev = &(((xmacptr *)ptr_from_lispobj(untag(next)))->link);
+  }
+}
+
+void 
+purify_headerless_range(LispObj *start, LispObj *end, BytePtr low, BytePtr high, area *to, int what)
+{
+  while (start < end) { 
+    copy_reference(start, low, high, to, what);
+    start++;
+  }
+}
+   
+void
+purify_range(LispObj *start, LispObj *end, BytePtr low, BytePtr high, area *to, int what)
+{
+  LispObj header;
+  unsigned tag;
+  natural nwords;
+  hash_table_vector_header *hashp;
+
+  while (start < end) {
+    header = *start;
+    if (header == forward_marker) {
+      start += 2;
+    } else {
+      tag = fulltag_of(header);
+      if (immheader_tag_p(tag)) {
+        start = (LispObj *)skip_over_ivector((natural)start, header);
+      } else if (nodeheader_tag_p(tag)) {
+        nwords = header_element_count(header);
+        nwords += (1 - (nwords&1));
+        if ((header_subtag(header) == subtag_hash_vector) &&
+          ((((hash_table_vector_header *)start)->flags) & 
+           nhash_track_keys_mask)) {
+          natural skip = (sizeof(hash_table_vector_header)/sizeof(LispObj))-1;
+
+          hashp = (hash_table_vector_header *) start;
+          start++;
+          nwords -= skip;
+          while(skip--) {
+            copy_reference(start, low, high, to, what);
+            start++;
+          }
+          /* "nwords" is odd at this point: there are (floor nwords 2)
+             key/value pairs to look at, and then an extra word for
+             alignment.  Process them two at a time, then bump "start"
+             past the alignment word. */
+          nwords >>= 1;
+          while(nwords--) {
+            if (copy_reference(start, low, high, to, what) && hashp) {
+              hashp->flags |= nhash_key_moved_mask;
+              hashp = NULL;
+            }
+            start++;
+            copy_reference(start, low, high, to, what);
+            start++;
+          }
+          *start++ = 0;
+        } else {
+          if (header_subtag(header) == subtag_function) {
+#ifdef X8632
+            int skip = (unsigned short)(start[1]);
+
+	    /* XXX bootstrapping */
+	    if (skip & 0x8000)
+	      skip = header_element_count(header) - (skip & 0x7fff);
+#else
+            int skip = (int)(start[1]);
+#endif
+            start += skip;
+            nwords -= skip;
+          }
+          start++;
+          while(nwords--) {
+            copy_reference(start, low, high, to, what);
+            start++;
+          }
+        }
+      } else {
+        /* Not a header, just a cons cell */
+        copy_reference(start, low, high, to, what);
+        start++;
+        copy_reference(start, low, high, to, what);
+        start++;
+      }
+    }
+  }
+}
+        
+/* Purify references from tstack areas */
+void
+purify_tstack_area(area *a, BytePtr low, BytePtr high, area *to, int what)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) (a->active),
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = (LispObj *) ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    purify_range(current+2, end, low, high, to, what);
+  }
+}
+
+/* Purify a vstack area */
+void
+purify_vstack_area(area *a, BytePtr low, BytePtr high, area *to, int what)
+{
+  LispObj
+    *p = (LispObj *) a->active,
+    *q = (LispObj *) a->high;
+  
+  purify_headerless_range(p, q, low, high, to, what);
+}
+
+
+void
+purify_xp(ExceptionInformation *xp, BytePtr low, BytePtr high, area *to, int what
+#ifdef X8632
+          ,natural node_regs_mask
+#endif
+)
+{
+  natural *regs = (natural *) xpGPRvector(xp);
+
+
+#ifdef X8664
+  copy_reference(&(regs[Iarg_z]), low, high, to, what);
+  copy_reference(&(regs[Iarg_y]), low, high, to, what);
+  copy_reference(&(regs[Iarg_x]), low, high, to, what);
+  copy_reference(&(regs[Isave3]), low, high, to, what);
+  copy_reference(&(regs[Isave2]), low, high, to, what);
+  copy_reference(&(regs[Isave1]), low, high, to, what);
+  copy_reference(&(regs[Isave0]), low, high, to, what);
+  copy_reference(&(regs[Ifn]), low, high, to, what);
+  copy_reference(&(regs[Itemp0]), low, high, to, what);
+  copy_reference(&(regs[Itemp1]), low, high, to, what);
+  copy_reference(&(regs[Itemp2]), low, high, to, what);
+
+  purify_locref(&(regs[Iip]), low, high, to, PURIFY_NOTHING);
+
+#else
+  if (node_regs_mask & (1<<0)) {
+    copy_reference(&(regs[REG_EAX]), low, high, to, what);
+  }
+  if (node_regs_mask & (1<<1)) {
+    copy_reference(&(regs[REG_ECX]), low, high, to, what);
+  }
+  if (! (regs[REG_EFL] & EFL_DF)) {
+    if (node_regs_mask & (1<<2)) {
+      copy_reference(&(regs[REG_EDX]), low, high, to, what);
+    }
+  }
+  if (node_regs_mask & (1<<3)) {
+    copy_reference(&(regs[REG_EBX]), low, high, to, what);
+  }
+  if (node_regs_mask & (1<<4)) {
+    copy_reference(&(regs[REG_ESP]), low, high, to, what);
+  }
+  if (node_regs_mask & (1<<5)) {
+    copy_reference(&(regs[REG_EBP]), low, high, to, what);
+  }
+  if (node_regs_mask & (1<<6)) {
+    copy_reference(&(regs[REG_ESI]), low, high, to, what);
+  }
+  if (node_regs_mask & (1<<7)) {
+    copy_reference(&(regs[REG_EDI]), low, high, to, what);
+  }
+  purify_locref(&regs[REG_EIP], low, high, to, what);
+#endif
+}
+
+void
+purify_tcr_tlb(TCR *tcr, BytePtr low, BytePtr high, area *to, int what)
+{
+  natural n = tcr->tlb_limit;
+  LispObj *start = tcr->tlb_pointer, *end = (LispObj *) ((BytePtr)start+n);
+
+  purify_range(start, end, low, high, to, what);
+}
+
+void
+purify_tcr_xframes(TCR *tcr, BytePtr low, BytePtr high, area *to, int what)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+  
+  xp = tcr->gc_context;
+  if (xp) {
+#ifdef X8632
+    purify_xp(xp, low, high, to, what, tcr->node_regs_mask);
+#else
+    purify_xp(xp, low, high, to, what);
+#endif
+  }
+#ifdef X8632
+  copy_reference(&tcr->save0, low, high, to, what);
+  copy_reference(&tcr->save1, low, high, to, what);
+  copy_reference(&tcr->save2, low, high, to, what);
+  copy_reference(&tcr->save3, low, high, to, what);
+  copy_reference(&tcr->next_method_context, low, high, to, what);
+#endif
+
+  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
+    purify_xp(xframes->curr, low, high, to, what
+#ifdef X8632
+              , xframes->node_regs_mask
+#endif
+              );
+  }
+}
+
+
+void
+purify_areas(BytePtr low, BytePtr high, area *target, int what)
+{
+  area *next_area;
+  area_code code;
+      
+  for (next_area = active_dynamic_area; (code = next_area->code) != AREA_VOID; next_area = next_area->succ) {
+    switch (code) {
+    case AREA_TSTACK:
+      purify_tstack_area(next_area, low, high, target, what);
+      break;
+      
+    case AREA_VSTACK:
+      purify_vstack_area(next_area, low, high, target, what);
+      break;
+      
+    case AREA_CSTACK:
+      break;
+      
+    case AREA_STATIC:
+    case AREA_DYNAMIC:
+    case AREA_MANAGED_STATIC:
+      purify_range((LispObj *) next_area->low, (LispObj *) next_area->active, low, high, target, what);
+      break;
+      
+    default:
+      break;
+    }
+  }
+}
+
+void
+update_managed_refs(area *a, BytePtr low_dynamic_address, natural ndynamic_dnodes)
+{
+  LispObj 
+    *start = (LispObj *)a->low,
+    *end = (LispObj *)a->active,
+    x1, 
+    *base = start, *prev = start;
+  int tag;
+  bitvector refbits = a->refbits;
+  natural ref_dnode, node_dnode;
+  Boolean intergen_ref;
+
+  while (start < end) {
+    x1 = *start;
+    prev = start;
+    tag = fulltag_of(x1);
+    if (immheader_tag_p(tag)) {
+      start = skip_over_ivector(ptr_to_lispobj(start), x1);
+    } else {
+      if (header_subtag(x1) == subtag_function) {
+#ifdef X8632
+	int skip = (unsigned short)deref(start,1);
+	/* XXX bootstrapping */
+	if (skip & 0x8000)
+	  skip = header_element_count(x1) - (skip & 0x7fff);
+#else
+        int skip = (int) deref(start,1);
+#endif
+        start += ((1+skip)&~1);
+        x1 = *start;
+        tag = fulltag_of(x1);
+      }
+      intergen_ref = false;
+      if (is_node_fulltag(tag)) {        
+        node_dnode = area_dnode(x1, low_dynamic_address);
+        if (node_dnode < ndynamic_dnodes) {
+          intergen_ref = true;
+        }
+      }
+      if (intergen_ref == false) {        
+        x1 = start[1];
+        tag = fulltag_of(x1);
+        if (is_node_fulltag(tag)) {        
+          node_dnode = area_dnode(x1, low_dynamic_address);
+          if (node_dnode < ndynamic_dnodes) {
+            intergen_ref = true;
+          }
+        }
+      }
+      if (intergen_ref) {
+        ref_dnode = area_dnode(start, base);
+        set_bit(refbits, ref_dnode);
+      }
+      start += 2;
+    }
+  }
+  if (start > end) {
+    Bug(NULL, "Overran end of range!");
+  }
+}
+
+/*
+  So far, this is mostly for save_application's benefit.
+  We -should- be able to return to lisp code after doing this,
+  however.
+
+*/
+
+
+signed_natural
+purify(TCR *tcr, signed_natural param)
+{
+  extern area *extend_readonly_area(natural);
+  area 
+    *a = active_dynamic_area,
+    *pure_area;
+
+  TCR  *other_tcr;
+  natural max_pure_size;
+  BytePtr new_pure_start,
+    low = (a->low + (static_dnodes_for_area(a) << dnode_shift)),
+    high = a->active;
+  Boolean purify_functions = (param != 0);
+  int flags = PURIFY_IVECTORS | (purify_functions ? PURIFY_FUNCTIONS : 0);
+
+  max_pure_size = unboxed_bytes_in_range((LispObj *) low, (LispObj *) high, purify_functions);
+  pure_area = extend_readonly_area(max_pure_size);
+  if (pure_area) {
+    new_pure_start = pure_area->active;
+    lisp_global(IN_GC) = (1<<fixnumshift);
+
+    /* 
+      Caller will typically GC again (and that should recover quite a bit of
+      the dynamic heap.)
+      */
+
+
+    
+    purify_areas(low, high, pure_area, flags);
+    
+    other_tcr = tcr;
+    do {
+      purify_tcr_xframes(other_tcr, low, high, pure_area, flags);
+      purify_tcr_tlb(other_tcr, low, high, pure_area, flags);
+      other_tcr = other_tcr->next;
+    } while (other_tcr != tcr);
+
+    purify_gcable_ptrs(low, high, pure_area, flags);
+    if (purify_functions) {
+      /* We're likely to copy a lot of symbols to the managed static
+         area.  Lots of symbols will have incidental references to
+         a relatively small number of things that happen to initialy
+         be in dynamic space: the UNDEFINED-FUNCTION object, packages,
+         etc.  Doing a shallow copy of those things to the managed-static
+         area will reduce the number of static->dynamic references. */
+      LispObj package_list;
+
+      copy_reference(&nrs_UDF.vcell,low,high,managed_static_area,PURIFY_ALL);
+      for (package_list = nrs_ALL_PACKAGES.vcell;
+           package_list != lisp_nil;
+           package_list = deref(package_list,0)) {
+        copy_reference(&(deref(package_list,1)),low,high,managed_static_area,PURIFY_ALL);
+      }
+
+        
+
+      /* Do a shallow copy of the constants of all purified functions
+         from the dynamic area to the managed static area */
+      purify_range((LispObj*)(pure_area->low),
+                   (LispObj*)(pure_area->active),
+                   low,
+                   high,
+                   managed_static_area,
+                   PURIFY_ALL);
+      /* Go back through all areas, resolving forwarding pointers
+         (but without copying anything.) */
+      purify_areas(low, high, NULL, PURIFY_NOTHING);
+      other_tcr = tcr;
+      do {
+        purify_tcr_xframes(other_tcr, low, high, NULL, PURIFY_NOTHING);
+        purify_tcr_tlb(other_tcr, low, high, NULL, PURIFY_NOTHING);
+        other_tcr = other_tcr->next;
+      } while (other_tcr != tcr);
+      
+      purify_gcable_ptrs(low, high, NULL, PURIFY_NOTHING);
+
+      /* Update refbits for managed static area */
+      {
+        natural 
+          managed_dnodes = area_dnode(managed_static_area->active,
+                                      managed_static_area->low),
+          refbytes = align_to_power_of_2((managed_dnodes+7)>>3,log2_page_size);
+        
+        managed_static_area->ndnodes = managed_dnodes;
+        CommitMemory(managed_static_area->refbits, refbytes); /* zeros them */
+        update_managed_refs(managed_static_area, low_markable_address, area_dnode(a->active,low_markable_address));
+      }
+    }
+    ProtectMemory(pure_area->low,
+		  align_to_power_of_2(pure_area->active-pure_area->low,
+				      log2_page_size));
+    lisp_global(IN_GC) = 0;
+    just_purified_p = true;
+    return 0;
+  }
+  return -1;
+}
+
+Boolean
+impurify_locref(LispObj *p, LispObj low, LispObj high, signed_natural delta)
+{
+  LispObj q = *p;
+
+  if ((q >= low) && 
+      (q < high)) {
+    *p = (q+delta);
+    return true;
+  }
+  return false;
+}
+  
+Boolean
+impurify_noderef(LispObj *p, LispObj low, LispObj high, signed_natural delta)
+{
+  LispObj q = *p;
+  
+  if (is_node_fulltag(fulltag_of(q)) &&
+      (q >= low) && 
+      (q < high)) {
+    *p = (q+delta);
+    return true;
+  }
+  return false;
+}
+  
+
+void
+impurify_gcable_ptrs(LispObj low, LispObj high, signed_natural delta)
+{
+  LispObj *prev = &(lisp_global(GCABLE_POINTERS)), next;
+
+  while ((*prev) != (LispObj)NULL) {
+    impurify_noderef(prev, low, high, delta);
+    next = *prev;
+    prev = &(((xmacptr *)ptr_from_lispobj(untag(next)))->link);
+  }
+}
+
+
+void
+impurify_xp(ExceptionInformation *xp, LispObj low, LispObj high, signed_natural delta
+#ifdef X8632
+            ,natural node_regs_mask
+#endif
+)
+{
+  natural *regs = (natural *) xpGPRvector(xp);
+
+
+#ifdef X8664
+  impurify_noderef(&(regs[Iarg_z]), low, high, delta);
+  impurify_noderef(&(regs[Iarg_y]), low, high, delta);
+  impurify_noderef(&(regs[Iarg_x]), low, high, delta);
+#ifndef TCR_IN_GPR
+  impurify_noderef(&(regs[Isave3]), low, high, delta);
+#endif
+  impurify_noderef(&(regs[Isave2]), low, high, delta);
+  impurify_noderef(&(regs[Isave1]), low, high, delta);
+  impurify_noderef(&(regs[Isave0]), low, high, delta);
+  impurify_noderef(&(regs[Ifn]), low, high, delta);
+  impurify_noderef(&(regs[Itemp0]), low, high, delta);
+  impurify_noderef(&(regs[Itemp1]), low, high, delta);
+
+  impurify_locref(&(regs[Iip]), low, high, delta);
+#else
+  if (node_regs_mask & (1<<0)) {
+    impurify_noderef(&(regs[REG_EAX]), low, high, delta);
+  }
+  if (node_regs_mask & (1<<1)) {
+    impurify_noderef(&(regs[REG_ECX]), low, high, delta);
+  }
+  if (! (regs[REG_EFL] & EFL_DF)) {
+    if (node_regs_mask & (1<<2)) {
+      impurify_noderef(&(regs[REG_EDX]), low, high, delta);
+    }
+  }
+  if (node_regs_mask & (1<<3)) {
+    impurify_noderef(&(regs[REG_EBX]), low, high, delta);
+  }
+  if (node_regs_mask & (1<<4)) {
+    impurify_noderef(&(regs[REG_ESP]), low, high, delta);
+  }
+  if (node_regs_mask & (1<<5)) {
+    impurify_noderef(&(regs[REG_EBP]), low, high, delta);
+  }
+  if (node_regs_mask & (1<<6)) {
+    impurify_noderef(&(regs[REG_ESI]), low, high, delta);
+  }
+  if (node_regs_mask & (1<<7)) {
+    impurify_noderef(&(regs[REG_EDI]), low, high, delta);
+  }
+  impurify_locref(&(regs[REG_EIP]), low, high, delta);
+
+#endif
+
+}
+
+void
+impurify_headerless_range(LispObj *start, LispObj *end, LispObj low, LispObj high, signed_natural delta)
+{
+  while (start < end) {
+    impurify_noderef(start, low, high, delta);
+    start++;
+  }
+}
+
+
+void
+impurify_range(LispObj *start, LispObj *end, LispObj low, LispObj high, signed_natural delta)
+{
+  LispObj header;
+  unsigned tag;
+  natural nwords;
+  hash_table_vector_header *hashp;
+
+  while (start < end) {
+    header = *start;
+    if (header == forward_marker) {
+      start += 2;
+    } else {
+      tag = fulltag_of(header);
+      if (immheader_tag_p(tag)) {
+        start = (LispObj *)skip_over_ivector((natural)start, header);
+      } else if (nodeheader_tag_p(tag)) {
+        nwords = header_element_count(header);
+        nwords += (1 - (nwords&1));
+        if ((header_subtag(header) == subtag_hash_vector) &&
+          ((((hash_table_vector_header *)start)->flags) & 
+           nhash_track_keys_mask)) {
+          natural skip = (sizeof(hash_table_vector_header)/sizeof(LispObj))-1;
+
+          hashp = (hash_table_vector_header *) start;
+          start++;
+          nwords -= skip;
+          while(skip--) {
+            impurify_noderef(start, low, high, delta);
+            start++;
+          }
+          /* "nwords" is odd at this point: there are (floor nwords 2)
+             key/value pairs to look at, and then an extra word for
+             alignment.  Process them two at a time, then bump "start"
+             past the alignment word. */
+          nwords >>= 1;
+          while(nwords--) {
+            if (impurify_noderef(start, low, high, delta) && hashp) {
+              hashp->flags |= nhash_key_moved_mask;
+              hashp = NULL;
+            }
+            start++;
+            impurify_noderef(start, low, high, delta);
+            start++;
+          }
+          *start++ = 0;
+        } else {
+          if (header_subtag(header) == subtag_function) {
+#ifdef X8632
+	    int skip = (unsigned short)start[1];
+#else
+            int skip = (int)(start[1]);
+#endif
+            start += skip;
+            nwords -= skip;
+          }
+          start++;
+          while(nwords--) {
+            impurify_noderef(start, low, high, delta);
+            start++;
+          }
+        }
+      } else {
+        /* Not a header, just a cons cell */
+        impurify_noderef(start, low, high, delta);
+        start++;
+        impurify_noderef(start, low, high, delta);
+        start++;
+      }
+    }
+  }
+}
+
+
+
+
+void
+impurify_tcr_tlb(TCR *tcr,  LispObj low, LispObj high, signed_natural delta)
+{
+  unsigned n = tcr->tlb_limit;
+  LispObj *start = tcr->tlb_pointer, *end = (LispObj *) ((BytePtr)start+n);
+  
+  impurify_range(start, end, low, high, delta);
+}
+
+void
+impurify_tcr_xframes(TCR *tcr, LispObj low, LispObj high, signed_natural delta)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+  
+  xp = tcr->gc_context;
+  if (xp) {
+#ifdef X8632
+    impurify_xp(xp, low, high, delta, tcr->node_regs_mask);
+#else
+    impurify_xp(xp, low, high, delta);
+#endif
+  }
+
+#ifdef X8632
+  impurify_noderef(&tcr->save0, low, high, delta);
+  impurify_noderef(&tcr->save1, low, high, delta);
+  impurify_noderef(&tcr->save2, low, high, delta);
+  impurify_noderef(&tcr->save3, low, high, delta);
+  impurify_noderef(&tcr->next_method_context, low, high, delta);
+#endif
+
+  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
+    impurify_xp(xframes->curr, low, high, delta
+#ifdef X8632
+                ,xframes->node_regs_mask
+#endif
+);
+  }
+}
+
+void
+impurify_tstack_area(area *a, LispObj low, LispObj high, signed_natural delta)
+{
+  LispObj
+    *current,
+    *next,
+    *start = (LispObj *) (a->active),
+    *end = start,
+    *limit = (LispObj *) (a->high);
+
+  for (current = start;
+       end != limit;
+       current = next) {
+    next = (LispObj *) ptr_from_lispobj(*current);
+    end = ((next >= start) && (next < limit)) ? next : limit;
+    impurify_range(current+2, end, low, high, delta);
+  }
+}
+void
+impurify_vstack_area(area *a, LispObj low, LispObj high, signed_natural delta)
+{
+  LispObj
+    *p = (LispObj *) a->active,
+    *q = (LispObj *) a->high;
+
+  impurify_headerless_range(p, q, low, high, delta);
+}
+
+
+void
+impurify_areas(LispObj low, LispObj high, signed_natural delta)
+{
+  area *next_area;
+  area_code code;
+      
+  for (next_area = active_dynamic_area; (code = next_area->code) != AREA_VOID; next_area = next_area->succ) {
+    switch (code) {
+    case AREA_TSTACK:
+      impurify_tstack_area(next_area, low, high, delta);
+      break;
+      
+    case AREA_VSTACK:
+      impurify_vstack_area(next_area, low, high, delta);
+      break;
+      
+    case AREA_CSTACK:
+      break;
+      
+    case AREA_STATIC:
+    case AREA_DYNAMIC:
+    case AREA_MANAGED_STATIC:
+      impurify_range((LispObj *) next_area->low, (LispObj *) next_area->active, low, high, delta);
+      break;
+      
+    default:
+      break;
+    }
+  }
+}
+
+void
+impurify_from_area(TCR *tcr, area *src)
+{
+  area *a = active_dynamic_area;
+  BytePtr base = src->low, limit = src->active, oldfree = a->active,
+    oldhigh = a->high, newhigh;
+  natural n = limit-base;
+  signed_natural delta = oldfree-base;
+  TCR *other_tcr;
+
+  newhigh = (BytePtr) (align_to_power_of_2(oldfree+n,
+                                           log2_heap_segment_size));
+  if (newhigh > oldhigh) {
+    grow_dynamic_area(newhigh-oldhigh);
+  }
+  a->active += n;
+  memmove(oldfree, base, n);
+  UnCommitMemory((void *)base, n);
+  a->ndnodes = area_dnode(a, a->active);
+  src->active = src->low;
+  if (src == readonly_area) {
+    pure_space_active = src->low;
+  }
+  src->ndnodes = 0;
+  
+  impurify_areas(ptr_to_lispobj(base), ptr_to_lispobj(limit), delta);
+  
+  other_tcr = tcr;
+  do {
+    impurify_tcr_xframes(other_tcr, ptr_to_lispobj(base), ptr_to_lispobj(limit), delta);
+    impurify_tcr_tlb(other_tcr, ptr_to_lispobj(base), ptr_to_lispobj(limit), delta);
+    other_tcr = other_tcr->next;
+  } while (other_tcr != tcr);
+  
+  impurify_gcable_ptrs(ptr_to_lispobj(base), ptr_to_lispobj(limit), delta);
+}
+
+signed_natural
+impurify(TCR *tcr, signed_natural param)
+{
+  lisp_global(IN_GC)=1;
+  impurify_from_area(tcr, readonly_area);
+  impurify_from_area(tcr, managed_static_area);
+  lisp_global(IN_GC)=0;
+  return 0;
+}
+
+/*
+ * This stuff is all adapted from the forward_xxx functions for use by
+ * the watchpoint code.  It's a lot of duplicated code, and it would
+ * be nice to generalize it somehow.
+ */
+
+static inline int
+wp_maybe_update(LispObj *p, LispObj old, LispObj new)
+{
+  if (*p == old) {
+    *p = new;
+    return true;
+  }
+  return false;
+}
+
+static void
+wp_update_headerless_range(LispObj *start, LispObj *end,
+			   LispObj old, LispObj new)
+{
+  LispObj *p = start;
+
+  while (p < end) {
+    wp_maybe_update(p, old, new);
+    p++;
+  }
+}
+
+static void
+wp_update_range(LispObj *start, LispObj *end, LispObj old, LispObj new)
+{
+  LispObj *p = start, node;
+  int tag_n;
+  natural nwords;
+
+  while (p < end) {
+    node = *p;
+    tag_n = fulltag_of(node);
+
+    if (immheader_tag_p(tag_n)) {
+      p = (LispObj *)skip_over_ivector(ptr_to_lispobj(p), node);
+    } else if (nodeheader_tag_p(tag_n)) {
+      nwords = header_element_count(node);
+      nwords += 1 - (nwords & 1);
+
+      if ((header_subtag(node) == subtag_hash_vector) &&
+          ((((hash_table_vector_header *)p)->flags) & nhash_track_keys_mask)) {
+        natural skip = hash_table_vector_header_count - 1;
+	hash_table_vector_header *hashp = (hash_table_vector_header *)p;
+
+        p++;
+        nwords -= skip;
+        while(skip--) {
+	  wp_maybe_update(p, old, new);
+          p++;
+        }
+        /* "nwords" is odd at this point: there are (floor nwords 2)
+           key/value pairs to look at, and then an extra word for
+           alignment.  Process them two at a time, then bump "p"
+           past the alignment word. */
+        nwords >>= 1;
+        while(nwords--) {
+          if (wp_maybe_update(p, old, new) && hashp) {
+            hashp->flags |= nhash_key_moved_mask;
+            hashp = NULL;
+          }
+          p++;
+	  wp_maybe_update(p, old, new);
+          p++;
+        }
+        *p++ = 0;
+      } else {
+	if (header_subtag(node) == subtag_function) {
+#ifdef X8632
+	  int skip = (unsigned short)(p[1]);
+
+	  /* XXX bootstrapping */
+	  if (skip & 0x8000)
+	    skip = header_element_count(node) - (skip & 0x7fff);
+
+#else
+	  int skip = (int)(p[1]);
+#endif
+	  p += skip;
+	  nwords -= skip;
+	}
+        p++;
+        while(nwords--) {
+	  wp_maybe_update(p, old, new);
+          p++;
+        }
+      }
+    } else {
+      /* a cons cell */
+      wp_maybe_update(p, old, new);
+      p++;
+      wp_maybe_update(p, old, new);
+      p++;
+    }
+  }
+}
+
+#ifdef X8664
+static void
+wp_update_xp(ExceptionInformation *xp, LispObj old, LispObj new)
+{
+  natural *regs = (natural *)xpGPRvector(xp);
+
+  wp_maybe_update(&regs[Iarg_z], old, new);
+  wp_maybe_update(&regs[Iarg_y], old, new);
+  wp_maybe_update(&regs[Iarg_x], old, new);
+  wp_maybe_update(&regs[Isave3], old, new);
+  wp_maybe_update(&regs[Isave2], old, new);
+  wp_maybe_update(&regs[Isave1], old, new);
+  wp_maybe_update(&regs[Isave0], old, new);
+  wp_maybe_update(&regs[Ifn], old, new);
+  wp_maybe_update(&regs[Itemp0], old, new);
+  wp_maybe_update(&regs[Itemp1], old, new);
+  wp_maybe_update(&regs[Itemp2], old, new);
+
+#if 0
+  /* 
+   * We don't allow watching functions, so this presumably doesn't
+   * matter.
+   */
+  update_locref(&(regs[Iip]));
+#endif
+}
+#else
+static void
+wp_update_xp(ExceptionInformation *xp, LispObj old, LispObj new, natural node_regs_mask)
+{
+  natural *regs = (natural *)xpGPRvector(xp);
+
+  if (node_regs_mask & (1<<0)) wp_maybe_update(&regs[REG_EAX], old, new);
+  if (node_regs_mask & (1<<1)) wp_maybe_update(&regs[REG_ECX], old, new);
+
+  if (regs[REG_EFL] & EFL_DF) {
+    /* then EDX is an imm reg */
+    ;
+  } else
+    if (node_regs_mask & (1<<2)) wp_maybe_update(&regs[REG_EDX], old, new);
+
+  if (node_regs_mask & (1<<3)) wp_maybe_update(&regs[REG_EBX], old, new);
+  if (node_regs_mask & (1<<4)) wp_maybe_update(&regs[REG_ESP], old, new);
+  if (node_regs_mask & (1<<5)) wp_maybe_update(&regs[REG_EBP], old, new);
+  if (node_regs_mask & (1<<6)) wp_maybe_update(&regs[REG_ESI], old, new);
+  if (node_regs_mask & (1<<7)) wp_maybe_update(&regs[REG_EDI], old, new);
+  /* we shouldn't watch functions, so no need to update PC */
+}
+#endif
+
+static void
+wp_update_tcr_xframes(TCR *tcr, LispObj old, LispObj new)
+{
+  xframe_list *xframes;
+  ExceptionInformation *xp;
+
+  xp = tcr->gc_context;
+  if (xp) {
+#ifdef X8664
+    wp_update_xp(xp, old, new);
+#else
+    wp_update_xp(xp, old, new, tcr->node_regs_mask);
+    wp_maybe_update(&tcr->save0, old, new);
+    wp_maybe_update(&tcr->save1, old, new);
+    wp_maybe_update(&tcr->save2, old, new);
+    wp_maybe_update(&tcr->save3, old, new);
+    wp_maybe_update(&tcr->next_method_context, old, new);
+#endif
+  }
+  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
+#ifdef X8664
+    wp_update_xp(xframes->curr, old, new);
+#else
+    wp_update_xp(xframes->curr, old, new, xframes->node_regs_mask);
+#endif
+  }
+}
+
+/*
+ * Scan all pointer-bearing areas, updating all references to
+ * "old" to "new".
+ */
+static void
+wp_update_all_areas(LispObj old, LispObj new)
+{
+  area *a = active_dynamic_area;
+  natural code = a->code;
+
+  while (code != AREA_VOID) {
+    switch (code) {
+      case AREA_DYNAMIC:
+      case AREA_STATIC:
+      case AREA_MANAGED_STATIC:
+      case AREA_WATCHED:
+	wp_update_range((LispObj *)a->low, (LispObj *)a->active, old, new);
+	break;
+      case AREA_VSTACK:
+      {
+	LispObj *low = (LispObj *)a->active;
+	LispObj *high = (LispObj *)a->high;
+	
+	wp_update_headerless_range(low, high, old, new);
+      }
+      break;
+      case AREA_TSTACK:
+      {
+	LispObj *current, *next;
+	LispObj *start = (LispObj *)a->active, *end = start;
+	LispObj *limit = (LispObj *)a->high;
+	
+	for (current = start; end != limit; current = next) {
+	  next = ptr_from_lispobj(*current);
+	  end = ((next >= start) && (next < limit)) ? next : limit;
+	  wp_update_range(current+2, end, old, new);
+	}
+      break;
+      }
+      default:
+	break;
+    }
+    a = a->succ;
+    code = a->code;
+  }
+}
+
+static void
+wp_update_tcr_tlb(TCR *tcr, LispObj old, LispObj new)
+{
+  natural n = tcr->tlb_limit;
+  LispObj *start = tcr->tlb_pointer;
+  LispObj *end = start + (n >> fixnumshift);
+
+  while (start < end) {
+    wp_maybe_update(start, old, new);
+    start++;
+  }
+}
+
+void
+wp_update_references(TCR *tcr, LispObj old, LispObj new)
+{
+  TCR *other_tcr = tcr;
+
+  do {
+    wp_update_tcr_xframes(other_tcr, old, new);
+    wp_update_tcr_tlb(other_tcr, old, new);
+    other_tcr = other_tcr->next;
+  } while (other_tcr != tcr);
+  unprotect_watched_areas();
+  wp_update_all_areas(old, new);
+  protect_watched_areas();
+}
Index: /branches/new-random/lisp-kernel/x86-macros.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-macros.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-macros.s	(revision 13309)
@@ -0,0 +1,765 @@
+/*   Copyright (C) 2005-2009 Clozure Associates  */
+/*   This file is part of Clozure CL.    */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public  */
+/*   License , known as the LLGPL and distributed with Clozure CL as the  */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these  */
+/*   conflict, the preamble takes precedence.    */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."  */
+
+/*   The LLGPL is also available online at  */
+/*   http://opensource.franz.com/preamble.html  */
+
+
+/* Try to make macros follow GAS/ATT conventions, where source precedes  */
+/* destination.  */
+
+define([lisp_global],[lisp_globals.$1])
+                        		
+define([ref_global],[
+	__(mov lisp_global($1),$2)
+])
+
+define([set_global],[
+	__(mov $1,lisp_global($2))
+])
+
+define([ref_nrs_value],[
+	__(mov nrs.$1+symbol.vcell,$2)
+])
+	
+define([set_nrs_value],[
+	__(mov $1,nrs.$2+symbol.vcell)
+])
+							
+define([unbox_fixnum],[
+	__(mov $1,$2)
+	__(sar [$]fixnumshift,$2)
+])
+
+define([box_fixnum],[
+        __(imul [$]fixnumone,$1,$2)
+])	
+
+
+/* box_fixnum, with no effect on flags */
+define([box_fixnum_no_flags],[
+        __(lea (,$1,fixnumone),$2)
+])
+
+
+/* Zero $3 bytes worth of dnodes, starting at offset $2 relative  */
+/* to the base register $1.  */
+
+
+ifdef([DarwinAssembler],[
+	.macro zero_dnodes
+	.if $2
+	ifdef([X8664],[
+	__(movapd %fpzero,$1($0))
+	],[
+	__(movsd %fpzero,$1($0))
+	])
+	__(zero_dnodes $0,$1+dnode_size,$2-dnode_size)
+	.endif
+	.endmacro
+],[
+	.macro zero_dnodes base,disp,nbytes
+	.ifgt \nbytes
+	ifdef([X8664],[
+        movapd %fpzero,\disp(\base)
+	],[
+	movsd %fpzero,\disp(\base)
+	])
+	zero_dnodes \base,"\disp+dnode_size","\nbytes-dnode_size"
+	.endif
+	.endm
+])	
+
+
+/* Allocate $1+dnode_size zeroed bytes on the tstack, using $2 as a temp  */
+/* reg.  */
+
+ifdef([X8632],[
+define([TSP_Alloc_Fixed],[
+	define([TSP_Alloc_Size],[((($1+node_size) & ~(dnode_size-1))+dnode_size)])
+	__(subl [$]TSP_Alloc_Size,rcontext(tcr.next_tsp))
+	__(movd rcontext(tcr.save_tsp),%stack_temp)
+	__(movl rcontext(tcr.next_tsp),$2)
+	zero_dnodes $2,0,TSP_Alloc_Size
+	__(movd %stack_temp,($2))
+	__(movl %ebp,tsp_frame.save_ebp($2))
+	__(movl $2,rcontext(tcr.save_tsp))
+	undefine([TSP_Alloc_Size])
+])],[
+define([TSP_Alloc_Fixed],[
+	define([TSP_Alloc_Size],[((($1+node_size) & ~(dnode_size-1))+dnode_size)])
+	__(subq [$]TSP_Alloc_Size,rcontext(tcr.next_tsp))
+        __(movq rcontext(tcr.save_tsp),%stack_temp)
+        __(movq rcontext(tcr.next_tsp),$2)
+	zero_dnodes $2,0,TSP_Alloc_Size
+	__(movq %stack_temp,($2))
+        __(movq %rbp,tsp_frame.save_rbp($2))
+        __(movq $2,rcontext(tcr.save_tsp))
+	undefine([TSP_Alloc_Size])
+])])
+
+/* $1 = size (dnode-aligned, including tsp overhead, $2 scratch.  */
+/* Modifies both $1 and $2; on exit, $2 = new_tsp+tsp_overhead, $1 = old tsp  */
+
+ifdef([X8632],[
+define([TSP_Alloc_Var],[
+        new_macro_labels()
+        __(subl $1,rcontext(tcr.next_tsp))
+        __(movd rcontext(tcr.save_tsp),%stack_temp)
+        __(movl rcontext(tcr.next_tsp),$2)
+        __(jmp macro_label(test))
+macro_label(loop):
+        __(movsd %fpzero,0($2))
+        __(addl $dnode_size,$2)
+macro_label(test):
+        __(subl $dnode_size,$1)
+        __(jge macro_label(loop))
+        __(movl rcontext(tcr.next_tsp),$2)
+        __(movd %stack_temp,$1)
+        __(movl $1,($2))
+	__(movl %ebp,tsp_frame.save_ebp($2))
+        __(movl $2,rcontext(tcr.save_tsp))
+        __(addl $dnode_size,$2)
+])],[
+define([TSP_Alloc_Var],[
+	new_macro_labels()
+        subq $1,rcontext(tcr.next_tsp)
+        __(movq rcontext(tcr.save_tsp),%stack_temp)
+        __(movq rcontext(tcr.next_tsp),$2)
+	__(jmp macro_label(test))
+macro_label(loop):
+	__(movapd %fpzero,0($2))
+	__(addq $dnode_size,$2)
+macro_label(test):	
+	__(subq $dnode_size,$1)
+	__(jge macro_label(loop))
+        __(movq rcontext(tcr.next_tsp),$2)
+	__(movd %stack_temp,$1)
+	__(movq $1,($2))
+        __(movq %rbp,tsp_frame.save_rbp($2))
+        __(movq $2,rcontext(tcr.save_tsp))
+	__(addq $dnode_size,$2)
+])])
+	
+	
+ifdef([X8632],[
+define([Allocate_Catch_Frame],[
+        TSP_Alloc_Fixed(catch_frame.size,$1)
+        __(movl [$](catch_frame.element_count<<subtag_shift)|subtag_catch_frame,dnode_size($1))
+        __(addl [$]dnode_size+fulltag_misc,$1)
+])],[
+define([Allocate_Catch_Frame],[
+	TSP_Alloc_Fixed(catch_frame.size,$1)
+	__(movq [$](catch_frame.element_count<<subtag_shift)|subtag_catch_frame,dnode_size($1))
+	__(addq [$]dnode_size+fulltag_misc,$1)
+])])
+
+/* %arg_z = tag,  %xfn = pc, $1 = mvflag 	  */
+
+ifdef([X8632],[
+define([Make_Catch],[
+	Allocate_Catch_Frame(%imm0)
+	__(movd rcontext(tcr.catch_top),%mm0)
+	__(movd rcontext(tcr.db_link),%mm1)
+	__(movl %arg_z,catch_frame.catch_tag(%imm0))
+	__(movd %mm0,catch_frame.link(%imm0))
+	__(movl [$]$1,catch_frame.mvflag(%imm0))
+	__(movd rcontext(tcr.xframe),%mm0)
+	__(movl %esp,catch_frame.esp(%imm0))
+	__(movl %ebp,catch_frame.ebp(%imm0))
+        __(movd rcontext(tcr.foreign_sp),%stack_temp)
+	__(movd %stack_temp,catch_frame.foreign_sp(%imm0))
+	__(movd %mm1,catch_frame.db_link(%imm0))
+	__(movd %mm0,catch_frame.xframe(%imm0))
+	__(movl %xfn,catch_frame.pc(%imm0))
+	__(movl %imm0,rcontext(tcr.catch_top))
+])],[
+define([Make_Catch],[
+	Allocate_Catch_Frame(%imm2)
+	__(movq rcontext(tcr.catch_top),%imm0)
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(movq %arg_z,catch_frame.catch_tag(%imm2))
+	__(movq %imm0,catch_frame.link(%imm2))
+	__(movq [$]$1,catch_frame.mvflag(%imm2))
+	__(movq rcontext(tcr.xframe),%imm0)
+	__(movq %rsp,catch_frame.rsp(%imm2))
+	__(movq %rbp,catch_frame.rbp(%imm2))
+        __(movq rcontext(tcr.foreign_sp),%stack_temp)
+	__(movq %imm1,catch_frame.db_link(%imm2))
+	__ifndef([WINDOWS])
+	__(movq %save3,catch_frame._save3(%imm2))
+	__endif
+	__(movq %save2,catch_frame._save2(%imm2))
+	__(movq %save1,catch_frame._save1(%imm2))
+	__(movq %save0,catch_frame._save0(%imm2))
+	__(movq %imm0,catch_frame.xframe(%imm2))
+	__(movq %stack_temp,catch_frame.foreign_sp(%imm2))
+	__(movq %xfn,catch_frame.pc(%imm2))
+	__(movq %imm2,rcontext(tcr.catch_top))
+])])	
+
+ifdef([X8632],[
+define([nMake_Catch],[
+	Allocate_Catch_Frame(%imm0)
+	__(movd rcontext(tcr.catch_top),%mm0)
+	__(movd rcontext(tcr.db_link),%mm1)
+	__(movl %arg_z,catch_frame.catch_tag(%imm0))
+	__(movd %mm0,catch_frame.link(%imm0))
+	__(movl %esp,catch_frame.esp(%imm0))
+	__(addl $node_size,catch_frame.esp(%imm0))
+	__(movl [$]$1,catch_frame.mvflag(%imm0))
+	__(movd rcontext(tcr.xframe),%mm0)
+	__(movl %ebp,catch_frame.ebp(%imm0))
+        __(movd rcontext(tcr.foreign_sp),%stack_temp)
+	__(movd %mm1,catch_frame.db_link(%imm0))
+	__(movd %mm0,catch_frame.xframe(%imm0))
+	__(movd %stack_temp,catch_frame.foreign_sp(%imm0))
+	__(movl %xfn,catch_frame.pc(%imm0))
+	__(movl %imm0,rcontext(tcr.catch_top))
+])],[	
+define([nMake_Catch],[
+	Allocate_Catch_Frame(%imm2)
+	__(movq rcontext(tcr.catch_top),%imm0)
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(movq %arg_z,catch_frame.catch_tag(%imm2))
+	__(movq %imm0,catch_frame.link(%imm2))
+        __(lea node_size(%rsp),%imm0)
+	__(movq [$]$1,catch_frame.mvflag(%imm2))
+	__(movq %imm0,catch_frame.rsp(%imm2))
+	__(movq rcontext(tcr.xframe),%imm0)
+	__(movq %rbp,catch_frame.rbp(%imm2))
+        __(movq rcontext(tcr.foreign_sp),%stack_temp)
+	__(movq %imm1,catch_frame.db_link(%imm2))
+	__ifndef([WINDOWS])
+	__(movq %save3,catch_frame._save3(%imm2))
+	__endif
+	__(movq %save2,catch_frame._save2(%imm2))
+	__(movq %save1,catch_frame._save1(%imm2))
+	__(movq %save0,catch_frame._save0(%imm2))
+	__(movq %imm0,catch_frame.xframe(%imm2))
+	__(movq %stack_temp,catch_frame.foreign_sp(%imm2))
+	__(movq %xfn,catch_frame.pc(%imm2))
+	__(movq %imm2,rcontext(tcr.catch_top))
+])])	
+        	
+	
+/* Consing can get interrupted (either by PROCESS-INTERRUPT or by GC  */
+/* activity in some other thread; if it's interrupted, the interrupting  */
+/* process needs to be able to determine what's going on well enough  */
+/* to be able to either back out of the attempt or finish the job.  */
+/* That requires that we use easily recogninized instruction sequences  */
+/* and follow certain conventions when consing (either in the kernel  */
+/* or in compiled code.)  (One of those conventions involves using  */
+/* %allocptr = %temp0 as a freepointer; when consing, %temp0 can't  */
+/* contain a live value.)  */
+/* Making a CONS cell is a little simpler than making a uvector.  */
+
+/* $1=new_car,$2=new_cdr,$3=dest   */
+
+ifdef([X8632],[
+define([Cons],[
+	new_macro_labels()
+/* The instructions where tcr.save_allocptr is tagged are difficult  */
+/* to interrupt; the interrupting code has to recognize and possibly  */
+/* emulate the instructions in between   */
+        __(subl $cons.size-fulltag_cons,rcontext(tcr.save_allocptr))
+        __(movl rcontext(tcr.save_allocptr),%allocptr)
+        __(rcmpl(%allocptr,rcontext(tcr.save_allocbase)))
+        __(ja macro_label(no_trap))
+        uuo_alloc()
+macro_label(no_trap):
+        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
+/* Easy to interrupt now that tcr.save_allocptr isn't tagged as a cons    */
+        __(movl $2,cons.cdr(%allocptr))
+        __(movl $1,cons.car(%allocptr))
+        ifelse($3,[],[],[
+         __(movl %allocptr,$3)
+        ])
+])],[
+
+define([Cons],[
+	new_macro_labels()
+/* The instructions where tcr.save_allocptr is tagged are difficult  */
+/* to interrupt; the interrupting code has to recognize and possibly  */
+/* emulate the instructions in between   */
+	__(subq $cons.size-fulltag_cons,rcontext(tcr.save_allocptr))
+	__(movq rcontext(tcr.save_allocptr),%allocptr)
+	__(rcmpq(%allocptr,rcontext(tcr.save_allocbase)))
+	__(ja macro_label(no_trap))
+	uuo_alloc()
+macro_label(no_trap):	
+	__(andb $~fulltagmask,rcontext(tcr.save_allocptr))
+/* Easy to interrupt now that tcr.save_allocptr isn't tagged as a cons    */
+	__(movq $2,cons.cdr(%allocptr))
+	__(movq $1,cons.car(%allocptr))
+	ifelse($3,[],[],[
+	 __(movq %allocptr,$3)
+	])
+])])
+
+ifdef([X8632],[
+/* Header in %mm0, size in bytes in %imm0.  We bash %imm0. */
+define([Misc_Alloc],[
+	__(sub [$]fulltag_misc,%imm0)
+	Misc_Alloc_Internal($1)
+])],[
+/* Header in %imm0, size in bytes in %imm1.  We bash %imm1. */
+define([Misc_Alloc],[
+	__(subq [$]fulltag_misc,%imm1)
+	Misc_Alloc_Internal($1)
+])])
+
+/* Here Be Monsters: we have to treat some/all of this instruction   */
+/* sequence atomically, as soon as tcr.save_allocptr becomes tagged.  */
+                
+ifdef([X8632],[
+define([Misc_Alloc_Internal],[                  
+        new_macro_labels()
+        __(subl %imm0,rcontext(tcr.save_allocptr))
+        __(movl rcontext(tcr.save_allocptr),%allocptr)
+        __(cmpl rcontext(tcr.save_allocbase),%allocptr)
+        __(ja macro_label(no_trap))
+        uuo_alloc()
+macro_label(no_trap):   
+        __(movd %mm0,misc_header_offset(%allocptr))
+        __(andb $~fulltagmask,rcontext(tcr.save_allocptr))
+/* Now that tcr.save_allocptr is untagged, it's easier to be interrupted   */
+        ifelse($1,[],[],[
+         __(mov %allocptr,$1)
+        ])
+])],[	
+define([Misc_Alloc_Internal],[			
+	new_macro_labels()
+	__(subq %imm1,rcontext(tcr.save_allocptr))
+	__(movq rcontext(tcr.save_allocptr),%allocptr)
+	__(rcmpq(%allocptr,rcontext(tcr.save_allocbase)))
+	__(ja macro_label(no_trap))
+	uuo_alloc()
+macro_label(no_trap):	
+	__(movq %imm0,misc_header_offset(%allocptr))
+	__(andb $~fulltagmask,rcontext(tcr.save_allocptr))
+/* Now that tcr.save_allocptr is untagged, it's easier to be interrupted   */
+	ifelse($1,[],[],[
+	 __(mov %allocptr,$1)
+	])
+])])
+
+ifdef([X8632],[
+define([Misc_Alloc_Fixed],[
+	__(mov [$]$2-fulltag_misc,%imm0)
+	Misc_Alloc_Internal($1)
+])],[
+define([Misc_Alloc_Fixed],[
+	__(movq [$]$2-fulltag_misc,%imm1)
+	Misc_Alloc_Internal($1)
+])])					
+
+define([vrefr],[
+	__(mov misc_data_offset+($3<<word_shift)($2),$1)
+])	
+
+define([jump_fn],[
+	__(jmp *%fn)
+])
+			
+define([jump_fname],[
+	__(mov symbol.fcell(%fname),%fn)
+	jump_fn()
+])	
+
+ifdef([X8632],[
+define([set_nargs],[
+	__(xorl %nargs,%nargs)
+	__(addl [$]$1<<fixnumshift,%nargs)
+])],[
+define([set_nargs],[
+        ifelse(eval($1>15),1,[
+        __(movl [$]$1<<fixnumshift,%nargs)
+        ],[
+        __(xorl %nargs,%nargs)
+        ifelse(eval($1),0,[],[
+        __(addl [$]$1<<fixnumshift,%nargs)
+        ])])])
+])
+
+/* $1 = ndigits.  Assumes 4-byte digits           */
+define([aligned_bignum_size],[((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))])
+	
+
+define([_car],[
+	__(mov cons.car($1),$2)
+])	
+
+define([_rplaca],[
+	__(mov $2,cons.car($1))
+])	
+		
+define([_cdr],[
+	__(mov cons.cdr($1),$2)
+])
+
+define([_rplacd],[
+	__(mov $2,cons.cdr($1))
+])	
+		
+	
+	
+ifdef([X8632],[
+define([tra],[
+        .p2align 3
+	.long 0
+	.byte 0
+$1:	
+])],[
+define([tra],[
+        .p2align 3
+	ifelse($2,[],[
+	.long 0
+	],[
+	.long $1-$2
+	])
+$1:	
+])])
+
+ifdef([X8632],[
+define([do_funcall],[
+        new_macro_labels()
+        extract_fulltag(%temp0,%imm0)
+        __(cmpb $fulltag_misc,%imm0_b)
+        __(jne macro_label(bad))
+        __(cmpb $subtag_function,misc_subtag_offset(%temp0))
+        __(jne macro_label(maybe_symbol))
+        __(mov %temp0,%fn)
+        __(jmp *%fn)
+macro_label(maybe_symbol):
+        __(cmpb $subtag_symbol,misc_subtag_offset(%temp0))
+        __(jne macro_label(bad))
+        /* %fname == %temp0 */
+        __(mov symbol.fcell(%fname),%fn)
+        __(jmp *%fn)
+macro_label(bad):
+        __(uuo_error_not_callable)
+])],[
+define([do_funcall],[
+	new_macro_labels()
+	__(movb %temp0_b,%imm0_b)
+	__(andb $fulltagmask,%imm0_b)
+	__(cmpb $fulltag_symbol,%imm0_b)
+	/* %fname == %temp0   */
+	__(cmovgq %temp0,%fn)
+	jl macro_label(bad)
+	__(cmoveq symbol.fcell(%fname),%fn)
+	__(jmp *%fn)
+macro_label(bad):		
+	__(uuo_error_not_callable)
+])])
+
+define([getvheader],[
+        __(mov misc_header_offset($1),$2)
+])
+
+/* "Size" is unboxed element-count.  $1 (header) and $2 (dest) should  */
+/*    both be immediate registers   */
+define([header_size],[
+        __(mov $1,$2)
+        __(shr $num_subtag_bits,$2)
+])
+
+/* $2 (length) is fixnum element-count.   */
+define([header_length],[
+        __(mov $~255,$2)
+        __(and $1,$2)
+        __(shr $num_subtag_bits-fixnumshift,$2)
+])
+
+/* $1 = vector, $2 = header, $3 = dest   */
+define([vector_size],[                                 
+        __(getvheader($1,$2))
+        __(header_size($2,$3))
+])
+
+/* $1 = vector, $2 = dest   */
+define([vector_length],[                                 
+        __(mov $~255,$2)
+        __(and misc_header_offset($1),$2)
+        __(shr $num_subtag_bits-fixnumshift,$2)
+])
+                
+/* GAS/ATT comparison arg order drives me nuts   */
+define([rcmpq],[
+	__(cmpq $2,$1)
+])
+
+define([rcmpl],[
+	__(cmpl $2,$1)
+])	
+
+define([rcmpw],[
+	__(cmpw $2,$1)
+])	
+
+define([rcmpb],[
+	__(cmpb $2,$1)
+])		
+
+
+define([condition_to_boolean],[
+        __(movl [$]t_value,$2_l)
+        __(lea (-t_offset)($2),$3)
+        __(cmov$1l $2_l,$3_l)
+])
+
+ifdef([X8632],[
+define([compare_reg_to_nil],[
+	__(cmp $nil_value,$1)
+])],[
+define([compare_reg_to_nil],[
+	__(cmpb $fulltag_nil,$1_b)
+])])
+
+ifdef([X8632],[
+define([extract_lisptag],[
+	__(movl $1,$2)
+	__(and [$]tagmask,$2)
+])],[
+define([extract_lisptag],[
+	__(movzbl $1_b,$2_l)
+	__(andb [$]tagmask,$2_b)
+])])
+
+								
+define([extract_fulltag],[
+	__(movzbl $1_b,$2_l)
+	__(andb [$]fulltagmask,$2_b)
+])
+
+define([extract_subtag],[
+	__(movb misc_subtag_offset($1),$2)
+])
+
+ifdef([X8632],[
+define([extract_typecode],[
+	new_macro_labels()
+	__(mov $1,$2)
+	__(andl $tagmask,$2)
+	__(cmpb $tag_misc,$2_b)
+	__(jne macro_label(done))
+	__(movb misc_subtag_offset($1),$2_b)
+macro_label(done):
+])],[
+define([extract_typecode],[
+	new_macro_labels()
+	__(movzbl $1_b,$2_l)
+	__(andb $tagmask,$2_b)
+	__(cmpb $tag_misc,$2_b)
+	__(jne macro_label(done))
+	__(movb misc_subtag_offset($1),$2_b)
+macro_label(done):
+])])
+
+/* dnode_align(src,delta,dest)  */
+
+define([dnode_align],[
+        __(lea ($2+(dnode_size-1))($1),$3)
+	__(andb $~(dnode_size-1),$3_b)
+])
+
+ifdef([X8632],[
+define([push_argregs],[
+	new_macro_labels()
+	/* xxx hack alert: when the compiler calls a keyword subprim */
+	/* (SPsimple_keywords, SPkeyword_args, SP_keyword_bind) */
+	/* it puts some flags in the upper half of %temp1, which
+	/* is %nargs.  We use the cmpw here to avoid seeing those flags. */
+	__(cmpw [$]1*node_size,%nargs_w)
+	__(jb macro_label(done))
+	__(je macro_label(z))
+	__(push %arg_y)
+macro_label(z):
+	__(push %arg_z)
+macro_label(done):
+])],[
+define([push_argregs],[
+	new_macro_labels()
+	__(testl %nargs,%nargs)
+	__(jz macro_label(done))
+	__(cmpl [$]2*node_size,%nargs)
+	__(je macro_label(yz))
+	__(jb macro_label(z))
+	__(push %arg_x)
+macro_label(yz):
+	__(push %arg_y)
+macro_label(z):
+	__(push %arg_z)
+macro_label(done):
+])])	
+
+
+/* $1 = ndigits.  Assumes 4-byte digits           */
+define([aligned_bignum_size],[((~(dnode_size-1)&(node_size+(dnode_size-1)+(4*$1))))])
+
+define([discard_temp_frame],[
+	__(mov rcontext(tcr.save_tsp),$1)
+	__(mov ($1),$1)
+	__(mov $1,rcontext(tcr.save_tsp))
+	__(mov $1,rcontext(tcr.next_tsp))
+])
+
+ifdef([X8632],[	
+define([check_pending_enabled_interrupt],[
+	__(btrl [$]31,rcontext(tcr.interrupt_pending))
+	__(jnc $1)
+	interrupt_now()
+])],[
+define([check_pending_enabled_interrupt],[
+	__(btrq [$]63,rcontext(tcr.interrupt_pending))
+	__(jnc $1)
+	interrupt_now()
+])])
+	
+/* $1 = scratch register, used to access tcr.tlb_pointer.  An interrupt  */
+/*   should be taken if interrupts are enabled and the most significant  */
+/*   bit of tcr.interrupt_pending is set.  If we take the interrupt, we  */
+/*   test and clear the pending bit.  */
+
+define([check_pending_interrupt],[
+	new_macro_labels()
+	__(mov rcontext(tcr.tlb_pointer),$1)
+	__(cmp [$]0,INTERRUPT_LEVEL_BINDING_INDEX($1))
+	__(js macro_label(done))
+	check_pending_enabled_interrupt(macro_label(done))
+macro_label(done):
+])
+
+/* This should only be called from a foreign context; it should be */
+/* assumed to bash all non-volatile C registers.  And of course it's */
+/* ugly, awful, non-portable, and slow.  %rdi should point to the */
+/* linear address that %gs should be made to address (tcr or pthread data) */
+        			
+ifdef([DARWIN_GS_HACK],[
+define([set_gs_base],[
+        ifelse($1,[],[
+        ],[
+        __(movq $1,%rdi)
+        ])
+        __(movl [$]0x3000003,%eax)
+        __(syscall)
+])
+
+/* %gs addresses the tcr.  Make it address pthread data before running */
+/* foreign code */        
+        
+define([set_foreign_gs_base],[
+        set_gs_base([rcontext(tcr.osid)])
+])
+
+/* %gs addresses the tcr.  Get the linear address of the tcr and */
+/* copy it to $1 */
+
+define([save_tcr_linear],[
+        __(movq rcontext(tcr.linear),$1)
+]) 
+	
+])
+
+/*  On AMD hardware (at least), a one-byte RET instruction should be */
+/*  prefixed with a REP prefix if it (a) is the target of a  */
+/*  branch or (b) immediately follows a conditional branch not taken. */
+define([repret],[
+        __(.byte 0xf3)
+        __(ret)
+])
+
+ifdef([X8632],[
+define([regnum],[ifelse($1, [%eax], [0],
+       $1, [%ecx], [1],
+       $1, [%edx], [2],
+       $1, [%ebx], [3],
+       $1, [%esp], [4],
+       $1, [%ebp], [5],
+       $1, [%esi], [6],
+       $1, [%edi], [7],
+	"unknown register")dnl
+])
+
+define([mark_as_node], [
+	__(xorl $1,$1)
+        __(orb [$](1<<regnum($1)), rcontext(tcr.node_regs_mask))
+])
+
+define([mark_as_imm],[
+        __(andb [$]~(1<<regnum($1)), rcontext(tcr.node_regs_mask))
+])
+])
+
+define([check_cstack_alignment],[
+        new_macro_labels()
+        __(testb [$]7,rcontext(tcr.foreign_sp))
+        __(je macro_label(done))
+        __(hlt)
+macro_label(done):
+])
+
+        __ifdef([WINDOWS])
+define([windows_cstack_probe],[
+        new_macro_labels()
+        __(cmp [$]0x1000,$1)
+        __(jb macro_label(done))
+        __(mov rcontext(tcr.foreign_sp),$2)
+        __(orl [$]0,-0x1000($2))
+        __(cmp [$]0x2000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x2000($2))
+        __(cmp [$]0x3000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x3000($2))
+        __(cmp [$]0x4000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x4000($2))
+        __(cmp [$]0x5000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x5000($2))
+        __(cmp [$]0x6000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x6000($2))
+        __(cmp [$]0x7000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x7000($2))
+        __(cmp [$]0x8000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x8000($2))
+        __(cmp [$]0x9000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0x9000($2))
+        __(cmp [$]0xa000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0xa000($2))
+        __(cmp [$]0xb000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0xb000($2))
+        __(cmp [$]0xc000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0xc000($2))
+        __(cmp [$]0xd000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0xd000($2))
+        __(cmp [$]0xe000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0xe000($2))
+        __(cmp [$]0xf000,$1)
+        __(jb macro_label(done))
+        __(orl [$]0,-0xf000($2))
+macro_label(done):      
+])
+
+
+        __endif                
+                        
Index: /branches/new-random/lisp-kernel/x86-spentry32.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-spentry32.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-spentry32.s	(revision 13309)
@@ -0,0 +1,4812 @@
+	include(lisp.s)
+	_beginfile
+
+	.align 2
+define([_spentry],[ifdef([__func_name],[_endfn],[])
+        .p2align 3
+        _exportfn(_SP$1)
+])
+
+define([_endsubp],[
+        _endfn(_SP$1)
+])
+
+define([jump_builtin],[
+	ref_nrs_value(builtin_functions,%fname)
+	set_nargs($2)
+	vrefr(%fname,%fname,$1)
+	jump_fname()
+])
+
+_spentry(bad_funcall)
+Xspentry_start:                 
+	.globl C(bad_funcall)
+__(tra(C(bad_funcall)))
+	__(uuo_error_not_callable)
+_endsubp(bad_funcall)
+
+/* %arg_z has overflowed by one bit.  Make a bignum with 1 (32-bit) digit. */
+_spentry(fix_overflow)
+C(fix_one_bit_overflow):
+        __(movl $one_digit_bignum_header,%imm0)
+	__(movd %imm0,%mm0)
+        __(Misc_Alloc_Fixed([],aligned_bignum_size(1)))
+        __(unbox_fixnum(%arg_z,%imm0))
+	__(xor $0xc0000000,%imm0)
+        __(mov %temp0,%arg_z)
+        __(movl %imm0,misc_data_offset(%arg_z))
+        __(ret)
+_endsubp(fix_overflow)
+
+/* %arg_y = vector, %arg_z = unscaled-idx */
+_spentry(misc_ref)
+	__(mov %arg_y,%imm0)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 0f)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+	__(movl misc_header_offset(%arg_y),%imm0)
+	__(xorb %imm0_b,%imm0_b)
+	__(shrl $num_subtag_bits-fixnumshift,%imm0)
+	__(cmpl %imm0,%arg_z)
+	__(jae 2f)
+	__(movb misc_subtag_offset(%arg_y),%imm0_b)
+	__(jmp C(misc_ref_common))
+
+0:	__(uuo_error_reg_not_tag(Rarg_y,tag_misc))
+1:	__(uuo_error_reg_not_fixnum(Rarg_z))
+2:	__(uuo_error_vector_bounds(Rarg_z,Rarg_y))
+_endsubp(misc_ref)
+
+/* %imm0_b = subtag, %arg_y = vector, %arg_z = index. */
+/* Bounds/type-checking done in caller. */
+_startfn(C(misc_ref_common))
+	__(movzbl %imm0_b,%imm0)
+	__(leal local_label(misc_ref_jmp)(,%imm0,4),%imm0)
+	__(jmp *(%imm0))
+	.p2align 2
+local_label(misc_ref_jmp):
+	/* 00-0f */
+        .long local_label(misc_ref_invalid) /* 00 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 01 cons  */
+        .long local_label(misc_ref_invalid) /* 02 nodeheader  */
+        .long local_label(misc_ref_invalid) /* 03 imm  */
+        .long local_label(misc_ref_invalid) /* 04 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 05 tra  */
+        .long local_label(misc_ref_invalid) /* 06 misc  */
+        .long local_label(misc_ref_u32) /* 07 bignum  */
+        .long local_label(misc_ref_invalid) /* 08 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 09 cons  */
+        .long local_label(misc_ref_node) /* 0a ratio  */
+        .long local_label(misc_ref_invalid) /* 0b imm  */
+        .long local_label(misc_ref_invalid) /* 0c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 0d tra  */
+        .long local_label(misc_ref_invalid) /* 0e misc  */
+        .long local_label(misc_ref_u32) /* 0f single_float  */
+        /* 10-1f  */
+        .long local_label(misc_ref_invalid) /* 10 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 11 cons  */
+        .long local_label(misc_ref_invalid) /* 12 nodeheader  */
+        .long local_label(misc_ref_invalid) /* 13 imm  */
+        .long local_label(misc_ref_invalid) /* 14 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 15 tra  */
+        .long local_label(misc_ref_invalid) /* 16 misc  */
+        .long local_label(misc_ref_u32) /* 17 double_float  */
+        .long local_label(misc_ref_invalid) /* 18 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 19 cons  */
+        .long local_label(misc_ref_node) /* 1a complex  */
+        .long local_label(misc_ref_invalid) /* 1b imm  */
+        .long local_label(misc_ref_invalid) /* 1c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 1d tra  */
+        .long local_label(misc_ref_invalid) /* 1e misc  */
+        .long local_label(misc_ref_u32) /* 1f macptr  */
+        /* 20-2f  */
+        .long local_label(misc_ref_invalid) /* 20 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 21 cons  */
+        .long local_label(misc_ref_node) /* 22 catch_frame  */
+        .long local_label(misc_ref_invalid) /* 23 imm  */
+        .long local_label(misc_ref_invalid) /* 24 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 25 tra  */
+        .long local_label(misc_ref_invalid) /* 26 misc  */
+        .long local_label(misc_ref_u32) /* 27 dead_macptr  */
+        .long local_label(misc_ref_invalid) /* 28 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 29 cons  */
+        .long local_label(misc_ref_function) /* 2a function  */
+        .long local_label(misc_ref_invalid) /* 2b imm  */
+        .long local_label(misc_ref_invalid) /* 2c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 2d tra  */
+        .long local_label(misc_ref_invalid) /* 2e misc  */
+        .long local_label(misc_ref_invalid) /* 2f immheader  */
+        /* 30-3f  */
+        .long local_label(misc_ref_invalid) /* 30 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 31 cons  */
+        .long local_label(misc_ref_node) /* 32 basic_stream  */
+        .long local_label(misc_ref_invalid) /* 33 imm  */
+        .long local_label(misc_ref_invalid) /* 34 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 35 tra  */
+        .long local_label(misc_ref_invalid) /* 36 misc  */
+        .long local_label(misc_ref_invalid) /* 37 immheader  */
+        .long local_label(misc_ref_invalid) /* 38 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 39 cons  */
+        .long local_label(misc_ref_node) /* 3a symbol  */
+        .long local_label(misc_ref_invalid) /* 3b imm  */
+        .long local_label(misc_ref_invalid) /* 3c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 3d tra  */
+        .long local_label(misc_ref_invalid) /* 3e misc  */
+        .long local_label(misc_ref_u32) /* 3f xcode_vector  */
+        /* 40-4f  */
+        .long local_label(misc_ref_invalid) /* 40 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 41 cons  */
+        .long local_label(misc_ref_node) /* 42 lock  */
+        .long local_label(misc_ref_invalid) /* 43 imm  */
+        .long local_label(misc_ref_invalid) /* 44 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 45 tra  */
+        .long local_label(misc_ref_invalid) /* 46 misc  */
+        .long local_label(misc_ref_invalid) /* 47 immheader  */
+        .long local_label(misc_ref_invalid) /* 48 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 49 cons  */
+        .long local_label(misc_ref_node) /* 4a hash_vector  */
+        .long local_label(misc_ref_invalid) /* 4b imm  */
+        .long local_label(misc_ref_invalid) /* 4c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 4d tra  */
+        .long local_label(misc_ref_invalid) /* 4e misc  */
+        .long local_label(misc_ref_invalid) /* 4f immheader  */
+        /* 50-5f  */
+        .long local_label(misc_ref_invalid) /* 50 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 51 cons  */
+        .long local_label(misc_ref_node) /* 52 pool  */
+        .long local_label(misc_ref_invalid) /* 53 imm  */
+        .long local_label(misc_ref_invalid) /* 54 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 55 tra  */
+        .long local_label(misc_ref_invalid) /* 56 misc  */
+        .long local_label(misc_ref_invalid) /* 57 immheader  */
+        .long local_label(misc_ref_invalid) /* 58 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 59 cons  */
+        .long local_label(misc_ref_node) /* 5a weak  */
+        .long local_label(misc_ref_invalid) /* 5b imm  */
+        .long local_label(misc_ref_invalid) /* 5c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 5d tra  */
+        .long local_label(misc_ref_invalid) /* 5e misc  */
+        .long local_label(misc_ref_invalid) /* 5f immheader  */
+        /* 60-6f  */
+        .long local_label(misc_ref_invalid) /* 60 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 61 cons  */
+        .long local_label(misc_ref_node) /* 62 package  */
+        .long local_label(misc_ref_invalid) /* 63 imm  */
+        .long local_label(misc_ref_invalid) /* 64 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 65 tra  */
+        .long local_label(misc_ref_invalid) /* 66 misc  */
+        .long local_label(misc_ref_invalid) /* 67 immheader  */
+        .long local_label(misc_ref_invalid) /* 68 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 69 cons  */
+        .long local_label(misc_ref_node) /* 6a slot_vector  */
+        .long local_label(misc_ref_invalid) /* 6b imm  */
+        .long local_label(misc_ref_invalid) /* 6c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 6d tra  */
+        .long local_label(misc_ref_invalid) /* 6e misc  */
+        .long local_label(misc_ref_invalid) /* 6f immheader  */
+        /* 70-7f  */
+        .long local_label(misc_ref_invalid) /* 70 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 71 cons  */
+        .long local_label(misc_ref_node) /* 72 instance  */
+        .long local_label(misc_ref_invalid) /* 73 imm  */
+        .long local_label(misc_ref_invalid) /* 74 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 75 tra  */
+        .long local_label(misc_ref_invalid) /* 76 misc  */
+        .long local_label(misc_ref_invalid) /* 77 immheader  */
+        .long local_label(misc_ref_invalid) /* 78 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 79 cons  */
+        .long local_label(misc_ref_node) /* 7a struct  */
+        .long local_label(misc_ref_invalid) /* 7b imm  */
+        .long local_label(misc_ref_invalid) /* 7c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 7d tra  */
+        .long local_label(misc_ref_invalid) /* 7e misc  */
+        .long local_label(misc_ref_invalid) /* 7f immheader  */
+        /* 80-8f  */
+        .long local_label(misc_ref_invalid) /* 80 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 81 cons  */
+        .long local_label(misc_ref_node) /* 82 istruct  */
+        .long local_label(misc_ref_invalid) /* 83 imm  */
+        .long local_label(misc_ref_invalid) /* 84 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 85 tra  */
+        .long local_label(misc_ref_invalid) /* 86 misc  */
+        .long local_label(misc_ref_invalid) /* 87 immheader  */
+        .long local_label(misc_ref_invalid) /* 88 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 89 cons  */
+        .long local_label(misc_ref_node) /* 8a value_cell  */
+        .long local_label(misc_ref_invalid) /* 8b imm  */
+        .long local_label(misc_ref_invalid) /* 8c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 8d tra  */
+        .long local_label(misc_ref_invalid) /* 8e misc  */
+        .long local_label(misc_ref_invalid) /* 8f immheader  */
+        /* 90-9f  */
+        .long local_label(misc_ref_invalid) /* 90 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 91 cons  */
+        .long local_label(misc_ref_node) /* 92 xfunction  */
+        .long local_label(misc_ref_invalid) /* 93 imm  */
+        .long local_label(misc_ref_invalid) /* 94 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 95 tra  */
+        .long local_label(misc_ref_invalid) /* 96 misc  */
+        .long local_label(misc_ref_invalid) /* 97 immheader  */
+        .long local_label(misc_ref_invalid) /* 98 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* 99 cons  */
+        .long local_label(misc_ref_node) /* 9a arrayH  */
+        .long local_label(misc_ref_invalid) /* 9b imm  */
+        .long local_label(misc_ref_invalid) /* 9c odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* 9d tra  */
+        .long local_label(misc_ref_invalid) /* 9e misc  */
+        .long local_label(misc_ref_invalid) /* 9f immheader  */
+        /* a0-af  */
+        .long local_label(misc_ref_invalid) /* a0 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* a1 cons  */
+        .long local_label(misc_ref_node) /* a2 vectorH  */
+        .long local_label(misc_ref_invalid) /* a3 imm  */
+        .long local_label(misc_ref_invalid) /* a4 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* a5 tra  */
+        .long local_label(misc_ref_invalid) /* a6 misc  */
+        .long local_label(misc_ref_single_float_vector) /* a7 sf_vector  */
+        .long local_label(misc_ref_invalid) /* a8 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* a9 cons  */
+        .long local_label(misc_ref_node) /* aa simple_vector  */
+        .long local_label(misc_ref_invalid) /* ab imm  */
+        .long local_label(misc_ref_invalid) /* ac odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* ad tra  */
+        .long local_label(misc_ref_invalid) /* ae misc  */
+        .long local_label(misc_ref_u32) /* af u32  */
+        /* b0-bf  */
+        .long local_label(misc_ref_invalid) /* b0 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* b1 cons  */
+        .long local_label(misc_ref_invalid) /* b2 nodeheader  */
+        .long local_label(misc_ref_invalid) /* b3 imm  */
+        .long local_label(misc_ref_invalid) /* b4 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* b5 tra  */
+        .long local_label(misc_ref_invalid) /* b6 misc  */
+        .long local_label(misc_ref_s32) /* b7 s32  */
+        .long local_label(misc_ref_invalid) /* b8 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* b9 cons  */
+        .long local_label(misc_ref_invalid) /* ba nodeheader  */
+        .long local_label(misc_ref_invalid) /* bb imm  */
+        .long local_label(misc_ref_invalid) /* bc odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* bd tra  */
+        .long local_label(misc_ref_invalid) /* be misc  */
+        .long local_label(misc_ref_fixnum_vector) /* bf fixnum_vector  */
+        /* c0-cf  */
+        .long local_label(misc_ref_invalid) /* c0 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* c1 cons  */
+        .long local_label(misc_ref_invalid) /* c2 nodeheader  */
+        .long local_label(misc_ref_invalid) /* c3 imm  */
+        .long local_label(misc_ref_invalid) /* c4 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* c5 tra  */
+        .long local_label(misc_ref_invalid) /* c6 misc  */
+        .long local_label(misc_ref_string) /* c7 simple_base_string  */
+        .long local_label(misc_ref_invalid) /* c8 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* c9 cons  */
+        .long local_label(misc_ref_invalid) /* ca nodeheader  */
+        .long local_label(misc_ref_invalid) /* cb imm  */
+        .long local_label(misc_ref_invalid) /* cc odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* cd tra  */
+        .long local_label(misc_ref_invalid) /* ce misc  */
+        .long local_label(misc_ref_u8) /* cf u8  */
+        /* d0-df  */
+        .long local_label(misc_ref_invalid) /* d0 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* d1 cons  */
+        .long local_label(misc_ref_invalid) /* d2 nodeheader  */
+        .long local_label(misc_ref_invalid) /* d3 imm  */
+        .long local_label(misc_ref_invalid) /* d4 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* d5 tra  */
+        .long local_label(misc_ref_invalid) /* d6 misc  */
+        .long local_label(misc_ref_s8)      /* d7 s8  */
+        .long local_label(misc_ref_invalid) /* d8 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* d9 cons  */
+        .long local_label(misc_ref_invalid) /* da nodeheader  */
+        .long local_label(misc_ref_invalid) /* db imm  */
+        .long local_label(misc_ref_invalid) /* dc odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* dd tra  */
+        .long local_label(misc_ref_invalid) /* de misc  */
+        .long local_label(misc_ref_invalid) /* df immheader  */
+        /* e0-ef  */
+        .long local_label(misc_ref_invalid) /* e0 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* e1 cons  */
+        .long local_label(misc_ref_invalid) /* e2 nodeheader  */
+        .long local_label(misc_ref_invalid) /* e3 imm  */
+        .long local_label(misc_ref_invalid) /* e4 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* e5 tra  */
+        .long local_label(misc_ref_invalid) /* e6 misc  */
+        .long local_label(misc_ref_u16) /* e7 u16  */
+        .long local_label(misc_ref_invalid) /* e8 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* e9 cons  */
+        .long local_label(misc_ref_invalid) /* ea nodeheader  */
+        .long local_label(misc_ref_invalid) /* eb imm  */
+        .long local_label(misc_ref_invalid) /* ec odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* ed tra  */
+        .long local_label(misc_ref_invalid) /* ee misc  */
+        .long local_label(misc_ref_s16) /* ef s16  */
+        /* f0-ff  */
+        .long local_label(misc_ref_invalid) /* f0 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* f1 cons  */
+        .long local_label(misc_ref_invalid) /* f2 nodeheader  */
+        .long local_label(misc_ref_invalid) /* f3 imm  */
+        .long local_label(misc_ref_invalid) /* f4 odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* f5 tra  */
+        .long local_label(misc_ref_invalid) /* f6 misc  */
+        .long local_label(misc_ref_double_float_vector) /* f7 df vector  */
+        .long local_label(misc_ref_invalid) /* f8 even_fixnum  */
+        .long local_label(misc_ref_invalid) /* f9 cons  */
+        .long local_label(misc_ref_invalid) /* fa nodeheader  */
+        .long local_label(misc_ref_invalid) /* fb imm  */
+        .long local_label(misc_ref_invalid) /* fc odd_fixnum  */
+        .long local_label(misc_ref_invalid) /* fd tra  */
+        .long local_label(misc_ref_invalid) /* fe misc  */
+        .long local_label(misc_ref_bit_vector) /* ff bit_vector  */
+
+/* Functions are funny.  The first N words are treated as */
+/* (UNSIGNED-BYTE 32), where N is the low 16 bits of the first word. */
+
+local_label(misc_ref_function):
+	__(movzwl misc_data_offset(%arg_y), %imm0)
+	/* XXX bootstrapping */
+	__(btr $15,%imm0)
+	__(jnc 0f)
+	__(movl $0xffffff00,%temp0)
+	__(andl misc_header_offset(%arg_y),%temp0)
+	__(shr $num_subtag_bits-fixnumshift,%temp0)
+	__(shl $fixnumshift,%imm0)
+	__(subl %imm0,%temp0)
+	__(movl %temp0,%imm0)
+	__(shr $fixnumshift,%imm0)
+0:	
+	__(shl $fixnumshift,%imm0)
+	__(rcmpl(%arg_z,%imm0))
+	__(jb local_label(misc_ref_u32))
+local_label(misc_ref_node):
+	__(movl misc_data_offset(%arg_y,%arg_z),%arg_z)
+	__(ret)
+local_label(misc_ref_u32):
+	__(movl misc_data_offset(%arg_y,%arg_z),%imm0)
+	__(jmp _SPmakeu32)
+local_label(misc_ref_s32):
+	__(movl misc_data_offset(%arg_y,%arg_z),%imm0)
+	__(jmp _SPmakes32)
+local_label(misc_ref_single_float_vector):
+	__(movss misc_data_offset(%arg_y,%arg_z),%fp1)
+	__(movl $single_float_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,single_float.size))
+	__(movss %fp1,single_float.value(%arg_z))
+	__(ret)
+local_label(misc_ref_double_float_vector):
+	__(movsd misc_dfloat_offset(%arg_y,%arg_z,2),%fp1)
+	__(movl $double_float_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,double_float.size))
+	__(movsd %fp1,double_float.value(%arg_z))
+	__(ret)
+local_label(misc_ref_fixnum_vector):
+	__(movl misc_data_offset(%arg_y,%arg_z),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_u8):
+	__(movl %arg_z,%imm0)
+	__(shr $2,%imm0)
+	__(movzbl misc_data_offset(%arg_y,%imm0),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_s8):
+	__(movl %arg_z,%imm0)
+	__(shr $2,%imm0)
+	__(movsbl misc_data_offset(%arg_y,%imm0),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_string):
+	__(movl %arg_z,%imm0)
+	__(movl misc_data_offset(%arg_y,%imm0),%imm0)
+	__(shll $charcode_shift,%imm0)
+	__(leal subtag_character(%imm0),%arg_z)
+	__(ret)
+local_label(misc_ref_u16):
+	__(movl %arg_z,%imm0)
+	__(shrl $1,%imm0)
+	__(movzwl misc_data_offset(%arg_y,%imm0),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_s16):
+	__(movl %arg_z,%imm0)
+	__(shrl $1,%imm0)
+	__(movswl misc_data_offset(%arg_y,%imm0),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_bit_vector):
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(btl %imm0,misc_data_offset(%arg_y))
+	__(setc %imm0_b)
+	__(movzbl %imm0_b,%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_invalid):
+	__(pop %temp1)	/* return addr */
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+	__(push $XBADVEC)
+	__(push %temp1)
+	__(set_nargs(3))
+	__(jmp _SPksignalerr)
+_endfn(C(misc_ref_common))
+
+/* Like misc_ref, only the boxed subtag is in temp0. */
+_spentry(subtag_misc_ref)
+	__(mov %arg_y,%imm0)
+	__(and $tagmask,%imm0)
+	__(cmp $tag_misc,%imm0)
+	__(jne 0f)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+	__(movl misc_header_offset(%arg_y),%imm0)
+	__(xorb %imm0_b,%imm0_b)
+	__(shrl $num_subtag_bits-fixnumshift,%imm0)
+	__(cmp %imm0,%arg_z)
+	__(jae 2f)
+	__(unbox_fixnum(%temp0,%imm0))
+	__(jmp C(misc_ref_common))
+0:	__(uuo_error_reg_not_tag(Rarg_y,tag_misc))
+1:	__(uuo_error_reg_not_fixnum(Rarg_z))
+2:	__(uuo_error_vector_bounds(Rarg_z,Rarg_y))
+_endsubp(subtag_misc_ref)
+
+/* Like misc_set, only the boxed subtag is in temp1. */
+_spentry(subtag_misc_set)
+	__(mov %temp0,%imm0)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 0f)
+	__(mov %arg_y,%imm0)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(movl misc_header_offset(%temp0),%imm0)
+	__(xorb %imm0_b,%imm0_b)
+	__(shrl $num_subtag_bits-fixnumshift,%imm0)
+	__(cmpl %imm0,%arg_y)
+	__(jae 2f)
+	__(unbox_fixnum(%temp1,%imm0))
+	__(jmp C(misc_set_common))
+0:	__(uuo_error_reg_not_tag(Rtemp0,tag_misc))
+1:	__(uuo_error_reg_not_fixnum(Rarg_y))
+2:	__(uuo_error_vector_bounds(Rarg_y,Rtemp0))
+_endsubp(subtag_misc_set)
+
+/* %temp0 = vector, %arg_y = unscaled-idx, %arg_z = val */
+_spentry(misc_set)
+	__(mov %temp0,%imm0)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 0f)
+	__(test $fixnummask,%arg_y)
+	__(jne 1f)
+	__(movl misc_header_offset(%temp0),%imm0)
+	__(xorb %imm0_b,%imm0_b)
+	__(shrl $num_subtag_bits-fixnumshift,%imm0)
+	__(cmpl %imm0,%arg_y)
+	__(jae 2f)
+	__(xorl %imm0,%imm0)
+	__(movb misc_subtag_offset(%temp0),%imm0_b)
+	__(jmp C(misc_set_common))
+0:	__(uuo_error_reg_not_tag(Rtemp0,tag_misc))
+1:	__(uuo_error_reg_not_fixnum(Rarg_y))
+2:	__(uuo_error_vector_bounds(Rarg_y,Rtemp0))
+_endsubp(misc_set)
+
+/* imm0_b = subtag, %temp0 = vector, %arg_y = index, %arg_z = value */
+_startfn(C(misc_set_common))
+	__(movzbl %imm0_b,%imm0)
+	__(leal local_label(misc_set_jmp)(,%imm0,4),%imm0)
+	__(jmp *(%imm0))
+	.p2align 2
+local_label(misc_set_jmp):
+	/* 00-0f */
+        .long local_label(misc_set_invalid) /* 00 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 01 cons  */
+        .long local_label(misc_set_invalid) /* 02 nodeheader  */
+        .long local_label(misc_set_invalid) /* 03 imm  */
+        .long local_label(misc_set_invalid) /* 04 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 05 tra  */
+        .long local_label(misc_set_invalid) /* 06 misc  */
+        .long local_label(misc_set_u32) /* 07 bignum  */
+        .long local_label(misc_set_invalid) /* 08 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 09 cons  */
+        .long _SPgvset /* 0a ratio  */
+        .long local_label(misc_set_invalid) /* 0b imm  */
+        .long local_label(misc_set_invalid) /* 0c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 0d tra  */
+        .long local_label(misc_set_invalid) /* 0e misc  */
+        .long local_label(misc_set_u32) /* 0f single_float  */
+        /* 10-1f  */
+        .long local_label(misc_set_invalid) /* 10 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 11 cons  */
+        .long local_label(misc_set_invalid) /* 12 nodeheader  */
+        .long local_label(misc_set_invalid) /* 13 imm  */
+        .long local_label(misc_set_invalid) /* 14 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 15 tra  */
+        .long local_label(misc_set_invalid) /* 16 misc  */
+        .long local_label(misc_set_u32) /* 17 double_float  */
+        .long local_label(misc_set_invalid) /* 18 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 19 cons  */
+        .long _SPgvset /* 1a complex  */
+        .long local_label(misc_set_invalid) /* 1b imm  */
+        .long local_label(misc_set_invalid) /* 1c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 1d tra  */
+        .long local_label(misc_set_invalid) /* 1e misc  */
+        .long local_label(misc_set_u32) /* 1f macptr  */
+        /* 20-2f  */
+        .long local_label(misc_set_invalid) /* 20 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 21 cons  */
+        .long _SPgvset /* 22 catch_frame  */
+        .long local_label(misc_set_invalid) /* 23 imm  */
+        .long local_label(misc_set_invalid) /* 24 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 25 tra  */
+        .long local_label(misc_set_invalid) /* 26 misc  */
+        .long local_label(misc_set_u32) /* 27 dead_macptr  */
+        .long local_label(misc_set_invalid) /* 28 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 29 cons  */
+        .long local_label(misc_set_function) /* 2a function  */
+        .long local_label(misc_set_invalid) /* 2b imm  */
+        .long local_label(misc_set_invalid) /* 2c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 2d tra  */
+        .long local_label(misc_set_invalid) /* 2e misc  */
+        .long local_label(misc_set_invalid) /* 2f immheader  */
+        /* 30-3f  */
+        .long local_label(misc_set_invalid) /* 30 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 31 cons  */
+        .long _SPgvset /* 32 basic_stream  */
+        .long local_label(misc_set_invalid) /* 33 imm  */
+        .long local_label(misc_set_invalid) /* 34 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 35 tra  */
+        .long local_label(misc_set_invalid) /* 36 misc  */
+        .long local_label(misc_set_invalid) /* 37 immheader  */
+        .long local_label(misc_set_invalid) /* 38 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 39 cons  */
+        .long _SPgvset /* 3a symbol  */
+        .long local_label(misc_set_invalid) /* 3b imm  */
+        .long local_label(misc_set_invalid) /* 3c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 3d tra  */
+        .long local_label(misc_set_invalid) /* 3e misc  */
+        .long local_label(misc_set_u32) /* 3f xcode_vector  */
+        /* 40-4f  */
+        .long local_label(misc_set_invalid) /* 40 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 41 cons  */
+        .long _SPgvset /* 42 lock  */
+        .long local_label(misc_set_invalid) /* 43 imm  */
+        .long local_label(misc_set_invalid) /* 44 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 45 tra  */
+        .long local_label(misc_set_invalid) /* 46 misc  */
+        .long local_label(misc_set_invalid) /* 47 immheader  */
+        .long local_label(misc_set_invalid) /* 48 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 49 cons  */
+        .long _SPgvset /* 4a hash_vector  */
+        .long local_label(misc_set_invalid) /* 4b imm  */
+        .long local_label(misc_set_invalid) /* 4c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 4d tra  */
+        .long local_label(misc_set_invalid) /* 4e misc  */
+        .long local_label(misc_set_invalid) /* 4f immheader  */
+        /* 50-5f  */
+        .long local_label(misc_set_invalid) /* 50 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 51 cons  */
+        .long _SPgvset /* 52 pool  */
+        .long local_label(misc_set_invalid) /* 53 imm  */
+        .long local_label(misc_set_invalid) /* 54 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 55 tra  */
+        .long local_label(misc_set_invalid) /* 56 misc  */
+        .long local_label(misc_set_invalid) /* 57 immheader  */
+        .long local_label(misc_set_invalid) /* 58 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 59 cons  */
+        .long _SPgvset /* 5a weak  */
+        .long local_label(misc_set_invalid) /* 5b imm  */
+        .long local_label(misc_set_invalid) /* 5c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 5d tra  */
+        .long local_label(misc_set_invalid) /* 5e misc  */
+        .long local_label(misc_set_invalid) /* 5f immheader  */
+        /* 60-6f  */
+        .long local_label(misc_set_invalid) /* 60 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 61 cons  */
+        .long _SPgvset /* 62 package  */
+        .long local_label(misc_set_invalid) /* 63 imm  */
+        .long local_label(misc_set_invalid) /* 64 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 65 tra  */
+        .long local_label(misc_set_invalid) /* 66 misc  */
+        .long local_label(misc_set_invalid) /* 67 immheader  */
+        .long local_label(misc_set_invalid) /* 68 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 69 cons  */
+        .long _SPgvset /* 6a slot_vector  */
+        .long local_label(misc_set_invalid) /* 6b imm  */
+        .long local_label(misc_set_invalid) /* 6c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 6d tra  */
+        .long local_label(misc_set_invalid) /* 6e misc  */
+        .long local_label(misc_set_invalid) /* 6f immheader  */
+        /* 70-7f  */
+        .long local_label(misc_set_invalid) /* 70 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 71 cons  */
+        .long _SPgvset /* 72 instance  */
+        .long local_label(misc_set_invalid) /* 73 imm  */
+        .long local_label(misc_set_invalid) /* 74 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 75 tra  */
+        .long local_label(misc_set_invalid) /* 76 misc  */
+        .long local_label(misc_set_invalid) /* 77 immheader  */
+        .long local_label(misc_set_invalid) /* 78 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 79 cons  */
+        .long _SPgvset /* 7a struct  */
+        .long local_label(misc_set_invalid) /* 7b imm  */
+        .long local_label(misc_set_invalid) /* 7c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 7d tra  */
+        .long local_label(misc_set_invalid) /* 7e misc  */
+        .long local_label(misc_set_invalid) /* 7f immheader  */
+        /* 80-8f  */
+        .long local_label(misc_set_invalid) /* 80 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 81 cons  */
+        .long _SPgvset /* 82 istruct  */
+        .long local_label(misc_set_invalid) /* 83 imm  */
+        .long local_label(misc_set_invalid) /* 84 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 85 tra  */
+        .long local_label(misc_set_invalid) /* 86 misc  */
+        .long local_label(misc_set_invalid) /* 87 immheader  */
+        .long local_label(misc_set_invalid) /* 88 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 89 cons  */
+        .long _SPgvset /* 8a value_cell  */
+        .long local_label(misc_set_invalid) /* 8b imm  */
+        .long local_label(misc_set_invalid) /* 8c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 8d tra  */
+        .long local_label(misc_set_invalid) /* 8e misc  */
+        .long local_label(misc_set_invalid) /* 8f immheader  */
+        /* 90-9f  */
+        .long local_label(misc_set_invalid) /* 90 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 91 cons  */
+        .long _SPgvset /* 92 xfunction  */
+        .long local_label(misc_set_invalid) /* 93 imm  */
+        .long local_label(misc_set_invalid) /* 94 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 95 tra  */
+        .long local_label(misc_set_invalid) /* 96 misc  */
+        .long local_label(misc_set_invalid) /* 97 immheader  */
+        .long local_label(misc_set_invalid) /* 98 even_fixnum  */
+        .long local_label(misc_set_invalid) /* 99 cons  */
+        .long _SPgvset /* 9a arrayH  */
+        .long local_label(misc_set_invalid) /* 9b imm  */
+        .long local_label(misc_set_invalid) /* 9c odd_fixnum  */
+        .long local_label(misc_set_invalid) /* 9d tra  */
+        .long local_label(misc_set_invalid) /* 9e misc  */
+        .long local_label(misc_set_invalid) /* 9f immheader  */
+        /* a0-af  */
+        .long local_label(misc_set_invalid) /* a0 even_fixnum  */
+        .long local_label(misc_set_invalid) /* a1 cons  */
+        .long _SPgvset /* a2 vectorH  */
+        .long local_label(misc_set_invalid) /* a3 imm  */
+        .long local_label(misc_set_invalid) /* a4 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* a5 tra  */
+        .long local_label(misc_set_invalid) /* a6 misc  */
+        .long local_label(misc_set_single_float_vector) /* a7 sf_vector  */
+        .long local_label(misc_set_invalid) /* a8 even_fixnum  */
+        .long local_label(misc_set_invalid) /* a9 cons  */
+        .long _SPgvset /* aa simple_vector  */
+        .long local_label(misc_set_invalid) /* ab imm  */
+        .long local_label(misc_set_invalid) /* ac odd_fixnum  */
+        .long local_label(misc_set_invalid) /* ad tra  */
+        .long local_label(misc_set_invalid) /* ae misc  */
+        .long local_label(misc_set_u32) /* af u32  */
+        /* b0-bf  */
+        .long local_label(misc_set_invalid) /* b0 even_fixnum  */
+        .long local_label(misc_set_invalid) /* b1 cons  */
+        .long local_label(misc_set_invalid) /* b2 nodeheader  */
+        .long local_label(misc_set_invalid) /* b3 imm  */
+        .long local_label(misc_set_invalid) /* b4 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* b5 tra  */
+        .long local_label(misc_set_invalid) /* b6 misc  */
+        .long local_label(misc_set_s32) /* b7 s32  */
+        .long local_label(misc_set_invalid) /* b8 even_fixnum  */
+        .long local_label(misc_set_invalid) /* b9 cons  */
+        .long local_label(misc_set_invalid) /* ba nodeheader  */
+        .long local_label(misc_set_invalid) /* bb imm  */
+        .long local_label(misc_set_invalid) /* bc odd_fixnum  */
+        .long local_label(misc_set_invalid) /* bd tra  */
+        .long local_label(misc_set_invalid) /* be misc  */
+        .long local_label(misc_set_fixnum_vector) /* bf fixnum_vector  */
+        /* c0-cf  */
+        .long local_label(misc_set_invalid) /* c0 even_fixnum  */
+        .long local_label(misc_set_invalid) /* c1 cons  */
+        .long local_label(misc_set_invalid) /* c2 nodeheader  */
+        .long local_label(misc_set_invalid) /* c3 imm  */
+        .long local_label(misc_set_invalid) /* c4 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* c5 tra  */
+        .long local_label(misc_set_invalid) /* c6 misc  */
+        .long local_label(misc_set_string) /* c7 simple_base_string  */
+        .long local_label(misc_set_invalid) /* c8 even_fixnum  */
+        .long local_label(misc_set_invalid) /* c9 cons  */
+        .long local_label(misc_set_invalid) /* ca nodeheader  */
+        .long local_label(misc_set_invalid) /* cb imm  */
+        .long local_label(misc_set_invalid) /* cc odd_fixnum  */
+        .long local_label(misc_set_invalid) /* cd tra  */
+        .long local_label(misc_set_invalid) /* ce misc  */
+        .long local_label(misc_set_u8) /* cf u8  */
+        /* d0-df  */
+        .long local_label(misc_set_invalid) /* d0 even_fixnum  */
+        .long local_label(misc_set_invalid) /* d1 cons  */
+        .long local_label(misc_set_invalid) /* d2 nodeheader  */
+        .long local_label(misc_set_invalid) /* d3 imm  */
+        .long local_label(misc_set_invalid) /* d4 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* d5 tra  */
+        .long local_label(misc_set_invalid) /* d6 misc  */
+        .long local_label(misc_set_s8)      /* d7 s8  */
+        .long local_label(misc_set_invalid) /* d8 even_fixnum  */
+        .long local_label(misc_set_invalid) /* d9 cons  */
+        .long local_label(misc_set_invalid) /* da nodeheader  */
+        .long local_label(misc_set_invalid) /* db imm  */
+        .long local_label(misc_set_invalid) /* dc odd_fixnum  */
+        .long local_label(misc_set_invalid) /* dd tra  */
+        .long local_label(misc_set_invalid) /* de misc  */
+        .long local_label(misc_set_invalid) /* df immheader  */
+        /* e0-ef  */
+        .long local_label(misc_set_invalid) /* e0 even_fixnum  */
+        .long local_label(misc_set_invalid) /* e1 cons  */
+        .long local_label(misc_set_invalid) /* e2 nodeheader  */
+        .long local_label(misc_set_invalid) /* e3 imm  */
+        .long local_label(misc_set_invalid) /* e4 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* e5 tra  */
+        .long local_label(misc_set_invalid) /* e6 misc  */
+        .long local_label(misc_set_u16) /* e7 u16  */
+        .long local_label(misc_set_invalid) /* e8 even_fixnum  */
+        .long local_label(misc_set_invalid) /* e9 cons  */
+        .long local_label(misc_set_invalid) /* ea nodeheader  */
+        .long local_label(misc_set_invalid) /* eb imm  */
+        .long local_label(misc_set_invalid) /* ec odd_fixnum  */
+        .long local_label(misc_set_invalid) /* ed tra  */
+        .long local_label(misc_set_invalid) /* ee misc  */
+        .long local_label(misc_set_s16) /* ef s16  */
+        /* f0-ff  */
+        .long local_label(misc_set_invalid) /* f0 even_fixnum  */
+        .long local_label(misc_set_invalid) /* f1 cons  */
+        .long local_label(misc_set_invalid) /* f2 nodeheader  */
+        .long local_label(misc_set_invalid) /* f3 imm  */
+        .long local_label(misc_set_invalid) /* f4 odd_fixnum  */
+        .long local_label(misc_set_invalid) /* f5 tra  */
+        .long local_label(misc_set_invalid) /* f6 misc  */
+        .long local_label(misc_set_double_float_vector) /* f7 df vector  */
+        .long local_label(misc_set_invalid) /* f8 even_fixnum  */
+        .long local_label(misc_set_invalid) /* f9 cons  */
+        .long local_label(misc_set_invalid) /* fa nodeheader  */
+        .long local_label(misc_set_invalid) /* fb imm  */
+        .long local_label(misc_set_invalid) /* fc odd_fixnum  */
+        .long local_label(misc_set_invalid) /* fd tra  */
+        .long local_label(misc_set_invalid) /* fe misc  */
+        .long local_label(misc_set_bit_vector) /* ff bit_vector  */
+
+local_label(misc_set_function):
+	/* Functions are funny: the first N words are treated as */
+	/* (UNSIGNED-BYTE 32), where N is the low 16 bits of the first word. */
+	__(movzwl misc_data_offset(%temp0),%imm0)
+	/* XXX bootstrapping */
+	__(btr $15,%imm0)
+	__(jnc 0f)
+	__(movl $0xffffff00,%temp1)
+	__(andl misc_header_offset(%temp0),%temp1)
+	__(shr $num_subtag_bits-fixnumshift,%temp1)
+	__(shl $fixnumshift,%imm0)
+	__(subl %imm0,%temp1)
+	__(movl %temp1,%imm0)
+	__(shr $fixnumshift,%imm0)
+0:
+	__(shl $fixnumshift,%imm0)
+	__(rcmpl(%arg_y,%imm0))
+	__(jae _SPgvset)
+local_label(misc_set_u32):
+	/* Either a non-negative fixnum, a positive one-digit bignum, or */
+	/* a two-digit bignum whose sign-digit is 0 is OK. */
+	__(movl $~(target_most_positive_fixnum <<fixnumshift),%imm0)
+	__(test %arg_z,%imm0)
+	__(movl %arg_z,%imm0)
+	__(jne 1f)
+	__(sarl $fixnumshift,%imm0)
+	__(jmp 9f)
+1:	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movl misc_header_offset(%arg_z),%imm0)
+	__(cmpl $two_digit_bignum_header,%imm0)
+	__(je 3f)
+	__(cmpl $one_digit_bignum_header,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(movl misc_data_offset(%arg_z),%imm0)
+	__(testl %imm0,%imm0)
+	__(js local_label(misc_set_bad))
+	__(jmp 9f)
+3:	__(movl misc_data_offset(%arg_z),%imm0)
+	__(cmpl $0,misc_data_offset+4(%arg_z))
+	__(jne local_label(misc_set_bad))
+9:	__(movl %imm0,misc_data_offset(%temp0,%arg_y))
+	__(ret)
+local_label(misc_set_s32):
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(testb $fixnummask,%arg_z_b)
+	__(je 9f)
+1:	__(movb %arg_z_b,%imm0_b)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movl misc_header_offset(%arg_z),%imm0)
+	__(cmpl $one_digit_bignum_header,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(movl misc_data_offset(%arg_z),%imm0)
+9:	__(movl %imm0,misc_data_offset(%temp0,%arg_y))
+	__(ret)
+local_label(misc_set_bad):
+	__(movl %arg_z,%arg_y)
+	__(movl %temp0,%arg_z)
+	__(pop %temp1)	/* return addr */
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+	__(push $XNOTELT)
+	__(push %temp1)
+	__(set_nargs(3))
+	__(jmp _SPksignalerr)
+local_label(misc_set_single_float_vector):
+	__(extract_lisptag(%arg_z,%imm0))
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_single_float,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movl single_float.value(%arg_z),%imm0)
+	__(movl %imm0,misc_data_offset(%temp0,%arg_y))
+	__(ret)
+local_label(misc_set_double_float_vector):
+	__(extract_lisptag(%arg_z,%imm0))
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_double_float,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movsd double_float.value(%arg_z),%fp0)
+	__(movsd %fp0,misc_dfloat_offset(%temp0,%arg_y,2))
+	__(ret)
+local_label(misc_set_fixnum_vector):
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(testb $fixnummask,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(movl %imm0,misc_data_offset(%temp0,%arg_y))
+	__(ret)
+local_label(misc_set_u8):
+	__(testl $~(0xff<<fixnumshift),%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(movl %arg_z,%arg_y)
+	__(shll $8-fixnumshift,%arg_z)
+	__(movb %arg_z_bh,misc_data_offset(%temp0,%imm0))
+	__(movl %arg_y,%arg_z)
+	__(ret)
+local_label(misc_set_s8):
+	__(movl %arg_z,%imm0)
+	__(shll $32-(8+fixnumshift),%imm0)
+	__(sarl $32-(8+fixnumshift),%imm0)
+	__(cmpl %arg_z,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(testb $fixnummask,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(movl %arg_z,%arg_z)
+	__(shll $8-fixnumshift,%arg_z)
+	__(movb %arg_z_bh,misc_data_offset(%temp0,%imm0))
+	__(movl %arg_y,%arg_z)
+	__(ret)
+local_label(misc_set_string):
+	__(cmpb $subtag_character,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(movl %arg_z,%imm0)
+	__(shrl $charcode_shift,%imm0)
+	__(movl %imm0,misc_data_offset(%temp0,%arg_y))
+	__(ret)
+local_label(misc_set_u16):
+	__(testl $~(0xffff<<fixnumshift),%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(movl %arg_y,%imm0)
+	__(shrl $1,%imm0)
+	__(mark_as_imm(%temp1))
+	__(unbox_fixnum(%arg_z,%temp1))
+	__(movw %temp1_w,misc_data_offset(%temp0,%imm0))
+	__(mark_as_node(%temp1))
+	__(ret)
+local_label(misc_set_s16):
+	__(movl %arg_z,%imm0)
+	__(shll $32-(16+fixnumshift),%imm0)
+	__(sarl $32-(16+fixnumshift),%imm0)
+	__(cmpl %arg_z,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(testb $fixnummask,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(movl %arg_y,%imm0)
+	__(shrl $1,%imm0)
+	__(mark_as_imm(%temp1))
+	__(unbox_fixnum(%arg_z,%temp1))
+	__(movw %temp1_w,misc_data_offset(%temp0,%imm0))
+	__(mark_as_node(%temp1))
+	__(ret)
+local_label(misc_set_bit_vector):
+	__(testl $~fixnumone,%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(testb %arg_z_b,%arg_z_b)
+	__(je local_label(misc_set_clr_bit))
+local_label(misc_set_set_bit):
+	__(btsl %imm0,misc_data_offset(%temp0))
+	__(ret)
+local_label(misc_set_clr_bit):
+	__(btrl %imm0,misc_data_offset(%temp0))
+	__(ret)
+local_label(misc_set_invalid):
+	__(pop %temp1)	/* return addr */
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+	__(push $XSETBADVEC)
+	__(push %temp0)
+	__(push %temp1)
+	__(set_nargs(4))
+	__(jmp _SPksignalerr)
+_endfn(C(misc_set_common))
+
+_spentry(Fret1valn)
+	.globl C(ret1valn)
+__(tra(C(ret1valn)))
+        __(mov (%esp),%ra0)
+        __(mov %arg_z,(%esp))
+	__(set_nargs(1))
+	__(jmp *%ra0)
+_endsubp(Fret1valn)
+
+_spentry(nvalret)
+	.globl C(nvalret)
+C(nvalret):
+	__(ref_global(ret1val_addr,%temp0))
+	__(cmpl lisp_frame.savera0(%ebp),%temp0)
+	__(je 1f)
+	__(test %nargs,%nargs)
+	__(movl $nil_value,%arg_z)
+	__(cmovnel -node_size(%esp,%nargs),%arg_z)
+	__(leave)
+	__(ret)
+
+/* actually need to return values; always need to copy. */
+1:	__(lea 2*node_size(%ebp),%imm0)
+	__(pushl (%imm0))
+	__(movl 0(%ebp),%ebp)
+	__(addl $node_size,%imm0)
+	__(lea node_size(%esp,%nargs),%temp0)
+	__(xorl %arg_y,%arg_y)
+	__(jmp 3f)
+2:	__(movl -node_size(%temp0),%arg_z)
+	__(subl $node_size,%temp0)
+	__(addl $node_size,%arg_y)
+	__(movl %arg_z,-node_size(%imm0))
+	__(subl $node_size,%imm0)
+3:	__(cmpl %arg_y,%nargs)
+	__(jne 2b)
+	__(pop %ra0)
+	__(movl %imm0,%esp)
+	__(jmp *%ra0)
+_endsubp(nvalret)
+
+_spentry(jmpsym)
+	__(jump_fname())
+_endsubp(jmpsym)
+
+_spentry(jmpnfn)
+	__(mov %temp0,%fn)
+	__(jmp *%fn)
+_endsubp(jmpnfn)
+
+_spentry(funcall)
+	__(do_funcall())
+_endsubp(funcall)
+
+/* Make a lisp integer (fixnum or one-digit bignum) from the value in %imm0 */
+_spentry(makes32)
+	__(imull $fixnumone,%imm0,%arg_z)	/* result is fixnum-tagged */
+	__(jno 0f)				/* but may have overflowed */
+	__(movd %imm0,%mm1)
+	__(movl $one_digit_bignum_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
+	__(movd %mm1,misc_data_offset(%arg_z))
+0:	__(repret)
+_endsubp(makes32)
+
+/* Make a lisp integer out of the unboxed 64-bit word in %mm0. */
+/* This is a little clumsy, but the alternative requires callers to */
+/* have already marked %edx as an imm reg (or else store it in memory
+/* somewhere), and I'm nervous about */
+/* splitting up the mark-as-imm/mark-as-node between two separate */
+/* pieces of code. */
+_spentry(makes64)
+        __(movq %mm0,%mm2)
+        __(pshufw $0x4e,%mm0,%mm1)      /* swap hi/lo halves */
+        __(psrad $31,%mm0)      /* propagate sign */
+        __(pcmpeqd %mm0,%mm1)	/* all ones if equal */
+        __(movd %mm1,%imm0)
+        __(cmpb $-1,%imm0_b)    /* upper half just sign extension? */
+        __(jne 1f)
+        __(movd %mm2,%imm0)
+	__(jmp _SPmakes32)
+1:      __(movl $two_digit_bignum_header,%imm0)
+        __(movd %imm0,%mm0)
+        __(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
+        __(movq %mm2,misc_data_offset(%arg_z))
+        __(ret)
+_endsubp(makes64)
+
+_spentry(syscall)
+	/* Save lisp registers */
+	__(push %ebp)
+	__(movl %esp,%ebp)
+	__(push %temp0)
+        __(push %temp1)
+        __(push %arg_y)
+        __(push %arg_z)
+        __(push %fn)
+	__(movl %esp,rcontext(tcr.save_vsp))
+	__(movl %ebp,rcontext(tcr.save_ebp))
+	__(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+	__(movl rcontext(tcr.foreign_sp),%esp)
+	/* preserve state of direction flag */
+	__(pushfl)
+	__(popl rcontext(tcr.save_eflags))
+	__(cld)
+	__(emms)
+	__(pop %ebp)		/* backlink */
+        __(lea 15(%esp),%edx)
+        __(andl $-16,%edx)
+        __(movl %edx,%esp)
+	__(unbox_fixnum(%arg_z,%eax))	/* syscall number */
+	__(movl $local_label(back_from_sysenter),%edx)
+	__(push %edx)
+	__(movl %esp,%ecx)
+	__(sysenter)
+local_label(back_from_sysenter):
+	__(jnc 0f)
+	__(neg %eax)
+0:	
+	__(movl %ebp,%esp)
+	__(movl %esp,rcontext(tcr.foreign_sp))
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+	__(pushl rcontext(tcr.save_eflags))
+	__(popfl)
+	__(movl rcontext(tcr.save_vsp),%esp)
+	__(movl rcontext(tcr.save_ebp),%ebp)
+	__(movl $TCR_STATE_LISP,rcontext(tcr.valence))
+        __(pop %fn)
+        __(pop %arg_z)
+        __(pop %arg_y)
+        __(pop %temp1)
+	__(check_pending_interrupt(%temp0))
+	__(pop %temp0)
+	__(leave)
+	__(ret)
+_endsubp(syscall)
+
+/* Make system call that returns a doubleword result in %edx:%eax and */
+/* copy the result into %mm0. */
+_spentry(syscall2)
+	/* Save lisp registers */
+	__(push %ebp)
+	__(movl %esp,%ebp)
+	__(push %temp0)
+        __(push %temp1)
+        __(push %arg_y)
+        __(push %arg_z)
+        __(push %fn)
+	__(movl %esp,rcontext(tcr.save_vsp))
+	__(movl %ebp,rcontext(tcr.save_ebp))
+	__(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+	__(movl rcontext(tcr.foreign_sp),%esp)
+	/* preserve state of direction flag */
+	__(pushfl)
+	__(popl rcontext(tcr.save_eflags))
+	__(cld)
+	__(emms)
+	__(pop %ebp)		/* backlink */
+        __(lea 15(%esp),%edx)
+        __(andl $-16,%edx)
+        __(movl %edx,%esp)
+	__(unbox_fixnum(%arg_z,%eax))	/* syscall number */
+	__(pushl $local_label(back_from_syscall))
+	__(int $0x80)
+local_label(back_from_syscall):
+	__(jnc 0f)
+	__(neg %eax)
+	__(movl $-1,%edx)
+0:
+	/* just use memory rather than screwing around with */
+	/* movd %eax,%mm0, movd %edx,%mm1, psllq $32,%mm1, por %mm1,%mm0 */
+	__(push %edx)
+	__(push %eax)
+	__(movq (%esp),%mm0)
+	__(movl %ebp,%esp)
+	__(movl %esp,rcontext(tcr.foreign_sp))
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+	__(pushl rcontext(tcr.save_eflags))
+	__(popf)
+	__(movl rcontext(tcr.save_vsp),%esp)
+	__(movl rcontext(tcr.save_ebp),%ebp)
+	__(movl $TCR_STATE_LISP,rcontext(tcr.valence))
+        __(pop %fn)
+        __(pop %arg_z)
+        __(pop %arg_y)
+        __(pop %temp1)
+	__(check_pending_interrupt(%temp0))
+	__(pop %temp0)
+	__(leave)
+	__(ret)
+_endsubp(syscall2)
+
+
+_spentry(mkcatch1v)
+	__(nMake_Catch(0))
+	__(ret)
+_endsubp(mkcatch1v)
+
+_spentry(mkunwind)
+	__(movl $undefined,%arg_z)
+	__(Make_Catch(fixnumone))
+	__(jmp *%ra0)
+_endsubp(mkunwind)
+
+/* this takes a return address in %ra0; it's "new" in that it does the */
+/*   double binding of *interrupt-level* out-of-line */
+_spentry(nmkunwind)
+	__(movl rcontext(tcr.tlb_pointer),%arg_z)
+        __(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_z),%arg_y)
+	__(push %arg_y)
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_z))
+	__(movl $undefined,%arg_z)
+	/* %arg_z = tag, %xfn (%temp1) = pc */
+	__(Make_Catch(fixnumone))
+	__(movl %arg_y,%arg_z)
+        __(jmp _SPbind_interrupt_level)
+_endsubp(nmkunwind)
+
+_spentry(mkcatchmv)
+	__(nMake_Catch(fixnumone))
+	__(ret)
+_endsubp(mkcatchmv)
+
+_spentry(throw)
+	__(movl rcontext(tcr.catch_top),%imm0)
+	__(movl (%esp,%nargs),%arg_y)	/* arg_y = tag   */
+	__(movd %nargs,%mm0)
+	__(xorl %temp1,%temp1)
+	__(jmp local_label(_throw_test))
+local_label(_throw_loop):
+	__(cmpl %arg_y,catch_frame.catch_tag(%imm0))
+	__(je local_label(_throw_found))
+	__(movl catch_frame.link(%imm0),%imm0)
+	__(addl $fixnum_one,%temp1)
+local_label(_throw_test):
+	__(test %imm0,%imm0)
+	__(jne local_label(_throw_loop))
+        __(push %ra0)
+	__(uuo_error_reg_not_tag(Rarg_y,subtag_catch_frame))
+        __(pop %ra0)
+	__(jmp _SPthrow)
+local_label(_throw_found):
+	__(testb $fulltagmask,catch_frame.mvflag(%imm0))
+	__(movl %temp1,%imm0)
+	__(movd %mm0,%nargs)
+	__(jne local_label(_throw_multiple))
+	__(movl $nil_value,%arg_z)
+	__(test %nargs,%nargs)
+	__(je local_label(_throw_one_value))
+	__(movl -node_size(%esp,%nargs),%arg_z)
+	__(add %nargs,%esp)
+local_label(_throw_one_value):
+	__(movl $local_label(_threw_one_value),%ra0)
+	__(jmp _SPnthrow1value)
+__(tra(local_label(_threw_one_value)))
+	__(movl rcontext(tcr.catch_top),%arg_y)
+	__(movl catch_frame.db_link(%arg_y),%imm0)
+	__(cmpl %imm0,rcontext(tcr.db_link))
+	__(jz local_label(_threw_one_value_dont_unbind))
+	__(push $local_label(_threw_one_value_dont_unbind))
+	__(jmp _SPunbind_to)	/* preserves registers */
+__(tra(local_label(_threw_one_value_dont_unbind)))
+	__(movl catch_frame.ebp(%arg_y),%ebp)
+	__(movl catch_frame.foreign_sp(%arg_y),%imm0)
+        __(movl %imm0,rcontext(tcr.foreign_sp))
+	__(movl catch_frame.xframe(%arg_y),%imm0)
+	__(movl %imm0,rcontext(tcr.xframe))
+	__(movl catch_frame.esp(%arg_y),%esp)
+	__(movl catch_frame.link(%arg_y),%imm0)
+	__(movl %imm0,rcontext(tcr.catch_top))
+	__(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
+	__(movl (%imm0),%imm0)
+        __(movl %imm0,rcontext(tcr.save_tsp))
+        __(movl %imm0,rcontext(tcr.next_tsp))
+	__(movl catch_frame.pc(%arg_y),%ra0)
+	__(jmp *%ra0)
+local_label(_throw_multiple):
+	__(movl $local_label(_threw_multiple),%ra0)
+	__(jmp _SPnthrowvalues)
+__(tra(local_label(_threw_multiple)))
+	__(movl rcontext(tcr.catch_top),%arg_y)
+	__(movl catch_frame.db_link(%arg_y),%imm0)
+	__(cmpl %imm0,rcontext(tcr.db_link))
+	__(je local_label(_threw_multiple_dont_unbind))
+	__(push $local_label(_threw_multiple_dont_unbind))
+	__(jmp _SPunbind_to)	/* preserves registers */
+__(tra(local_label(_threw_multiple_dont_unbind)))
+	/* Copy multiple values from the current %esp to the target %esp   */
+	__(lea (%esp,%nargs),%imm0)
+	__(movd %nargs,%mm0)	/* nargs is aka temp1 */
+	__(movl catch_frame.esp(%arg_y),%temp1)
+	__(jmp local_label(_threw_multiple_push_test))
+local_label(_threw_multiple_push_loop):
+	__(subl $node_size,%imm0)
+	__(subl $node_size,%temp1)
+	__(movl (%imm0),%arg_z)
+	__(movl %arg_z,(%temp1))
+local_label(_threw_multiple_push_test):
+	__(cmpl %imm0,%esp)
+	__(jne local_label(_threw_multiple_push_loop))
+	/* target %esp is now in %temp1   */
+	__(movl catch_frame.ebp(%arg_y),%ebp)
+	__(movl catch_frame.foreign_sp(%arg_y),%imm0)
+        __(movl %imm0,rcontext(tcr.foreign_sp))        
+	__(movl catch_frame.xframe(%arg_y),%imm0)
+	__(movl %imm0,rcontext(tcr.xframe))
+	__(movl %temp1,%esp)
+	__(movl catch_frame.link(%arg_y),%temp1)
+	__(movl %temp1,rcontext(tcr.catch_top))
+	__(movd %mm0,%nargs)
+	__(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%arg_y),%imm0)
+	__(movl catch_frame.pc(%arg_y),%ra0)
+	__(movl (%imm0),%imm0)
+        __(movl %imm0,rcontext(tcr.save_tsp))
+        __(movl %imm0,rcontext(tcr.next_tsp))
+	__(jmp *%ra0)
+_endsubp(throw)
+
+	/* This takes N multiple values atop the vstack.   */
+_spentry(nthrowvalues)
+	__(movb $1,rcontext(tcr.unwinding))
+	__(movl %ra0,rcontext(tcr.save0)) /* %ra0 (aka %temp0) to spill area */
+local_label(_nthrowv_nextframe):
+	__(subl $fixnumone,%imm0)
+	__(js local_label(_nthrowv_done))
+	__(movd %imm0,%mm1)
+	__(movl rcontext(tcr.catch_top),%temp0)
+	__(movl catch_frame.link(%temp0),%imm0)
+	__(movl %imm0,rcontext(tcr.catch_top))
+	__(movl catch_frame.db_link(%temp0),%imm0)
+	__(cmpl %imm0,rcontext(tcr.db_link))
+	__(jz local_label(_nthrowv_dont_unbind))
+	__(push %temp1)
+	__(push %temp0)
+	__(push $local_label(_nthrowv_back_from_unbind))
+	__(jmp _SPunbind_to)
+__(tra(local_label(_nthrowv_back_from_unbind)))
+	__(pop %temp0)
+	__(pop %temp1)
+local_label(_nthrowv_dont_unbind):
+	__(cmpb $unbound_marker,catch_frame.catch_tag(%temp0))
+	__(je local_label(_nthrowv_do_unwind))
+/* A catch frame.  If the last one, restore context from there.   */
+	__(movd %mm1,%imm0)
+	__(test %imm0,%imm0)	/* last catch frame ?   */
+	__(jne local_label(_nthrowv_skip))
+	__(movl catch_frame.xframe(%temp0),%arg_y)
+	__(movl %arg_y,rcontext(tcr.xframe))
+	__(lea (%esp,%nargs),%arg_y)
+	__(movl catch_frame.esp(%temp0),%arg_z)
+	__(movd %nargs,%mm2)
+	__(jmp local_label(_nthrowv_push_test))
+local_label(_nthrowv_push_loop):
+	__(subl $node_size,%arg_y)
+	__(subl $node_size,%arg_z)
+	__(movd (%arg_y),%mm0)
+	__(movd %mm0,(%arg_z))
+local_label(_nthrowv_push_test):
+	__(subl $node_size,%nargs)
+	__(jns local_label(_nthrowv_push_loop))
+	__(movd %mm2,%nargs)
+	__(movl catch_frame.xframe(%temp0),%arg_y)
+	__(movl %arg_y,rcontext(tcr.xframe))
+	__(movl %arg_z,%esp)
+	__(movl catch_frame.ebp(%temp0),%ebp)
+	__(movd catch_frame.foreign_sp(%temp0),%stack_temp)
+        __(movd %stack_temp,rcontext(tcr.foreign_sp))        
+local_label(_nthrowv_skip):	
+	__(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
+        __(movl %imm0,rcontext(tcr.save_tsp))
+        __(movl %imm0,rcontext(tcr.next_tsp))
+	__(movd %mm1,%imm0)
+	__(jmp local_label(_nthrowv_nextframe))
+local_label(_nthrowv_do_unwind):	
+/* This is harder.  Call the cleanup code with the multiple values and   */
+/* nargs, the throw count, and the caller's return address in a temp  */
+/* stack frame.   */
+	__(leal (%esp,%nargs),%arg_y)
+	__(push catch_frame.pc(%temp0))
+	__(movl catch_frame.ebp(%temp0),%ebp)
+        __(movd catch_frame.xframe(%temp0),%stack_temp)
+        __(movd %stack_temp,rcontext(tcr.xframe))
+	__(movl catch_frame.esp(%temp0),%arg_z)
+	__(movd catch_frame.foreign_sp(%temp0),%stack_temp)
+        __(movd %stack_temp,rcontext(tcr.foreign_sp))        
+	/* Discard the catch frame, so we can build a temp frame   */
+	__(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm0)
+        __(movl %imm0,rcontext(tcr.save_tsp))
+        __(movl %imm0,rcontext(tcr.next_tsp))
+	__(movd %temp1,%mm2) /* save %nargs */
+	/* tsp overhead, nargs, throw count, ra0   */
+	__(dnode_align(%nargs,(tsp_frame.fixed_overhead+(3*node_size)),%imm0))
+	__(movl %imm0,%temp1)
+	__(TSP_Alloc_Var(%temp1,%imm0))
+	__(movd %mm2,%temp1) /* aka %nargs */
+
+	__(movl %nargs,(%imm0))
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movl %ra0,node_size(%imm0))
+	__(movd %mm1,node_size*2(%imm0))
+	__(leal node_size*3(%imm0),%imm0)
+	__(jmp local_label(_nthrowv_tpushtest))
+local_label(_nthrowv_tpushloop):
+	__(movl -node_size(%arg_y),%temp0)
+	__(subl $node_size,%arg_y)
+	__(movl %temp0,(%imm0))
+	__(addl $node_size,%imm0)
+local_label(_nthrowv_tpushtest):
+	__(subl $node_size,%nargs)
+	__(jns local_label(_nthrowv_tpushloop))
+	__(pop %xfn)	/* aka %temp1/%nargs */
+	__(movl %arg_z,%esp)
+/* Ready to call cleanup code. set up tra, jmp to %xfn   */
+	__(push $local_label(_nthrowv_called_cleanup))
+	__(movb $0,rcontext(tcr.unwinding))
+	__(jmp *%xfn)
+__(tra(local_label(_nthrowv_called_cleanup)))
+
+	__(movb $1,rcontext(tcr.unwinding))
+	__(movl rcontext(tcr.save_tsp),%imm0)
+	__(movl tsp_frame.data_offset+(0*node_size)(%imm0),%nargs)
+	__(movl tsp_frame.data_offset+(1*node_size)(%imm0),%ra0)
+	__(movl %ra0,rcontext(tcr.save0))
+	__(movd tsp_frame.data_offset+(2*node_size)(%imm0),%mm1)
+	__(movd %nargs,%mm2)
+	__(addl $tsp_frame.fixed_overhead+(node_size*3),%imm0)
+	__(jmp local_label(_nthrowv_tpoptest))
+local_label(_nthrowv_tpoploop):	
+	__(push (%imm0))
+	__(addl $node_size,%imm0)
+local_label(_nthrowv_tpoptest):	
+	__(subl $node_size,%nargs)
+	__(jns local_label(_nthrowv_tpoploop))
+	__(movd %mm2,%nargs)
+	__(movl rcontext(tcr.save_tsp),%imm0)
+	__(movl (%imm0),%imm0)
+        __(movl %imm0,rcontext(tcr.save_tsp))
+        __(movl %imm0,rcontext(tcr.next_tsp))
+	__(movd %mm1,%imm0)
+	__(jmp local_label(_nthrowv_nextframe))
+local_label(_nthrowv_done):
+	__(movb $0,rcontext(tcr.unwinding))
+	__(check_pending_interrupt(%imm0))
+local_label(_nthrowv_return):
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(jmp *%ra0)	
+_endsubp(nthrowvalues)
+
+/* This is a (slight) optimization.  When running an unwind-protect,  */
+/* save the single value and the throw count in the tstack frame.  */
+/* Note that this takes a single value in arg_z.  */
+
+_spentry(nthrow1value)
+	__(movb $1,rcontext(tcr.unwinding))
+local_label(_nthrow1v_nextframe):
+	__(subl $fixnumone,%imm0)
+	__(js local_label(_nthrow1v_done))
+	__(movd %imm0,%mm0)
+	__(movl rcontext(tcr.catch_top),%temp1)
+	__(movl catch_frame.link(%temp1),%imm0)
+	__(movl %imm0,rcontext(tcr.catch_top))
+	__(movl catch_frame.db_link(%temp1),%imm0)
+	__(cmpl %imm0,rcontext(tcr.db_link))
+	__(jz local_label(_nthrow1v_dont_unbind))
+	__(push %temp1)
+	__(push %temp0)
+	__(push %arg_z)
+	__(push [$]local_label(_nthrow1v_back_from_unbind))
+	__(jmp _SPunbind_to)
+__(tra(local_label(_nthrow1v_back_from_unbind)))
+	__(pop %arg_z)
+	__(pop %temp0)
+	__(pop %temp1)
+local_label(_nthrow1v_dont_unbind):
+	__(cmpb $unbound_marker,catch_frame.catch_tag(%temp1))
+	__(je local_label(_nthrow1v_do_unwind))
+/* A catch frame.  If the last one, restore context from there. */
+	__(movd %mm0,%imm0)
+	__(test %imm0,%imm0)	/* last catch frame? */
+	__(jne local_label(_nthrow1v_skip))
+	__(movl catch_frame.xframe(%temp1),%arg_y)
+	__(movl %arg_y,rcontext(tcr.xframe))
+	__(movl catch_frame.esp(%temp1),%esp)
+	__(movl catch_frame.ebp(%temp1),%ebp)
+	__(movd catch_frame.foreign_sp(%temp1),%stack_temp)
+	__(movd %stack_temp,rcontext(tcr.foreign_sp))
+local_label(_nthrow1v_skip):
+	__(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
+	__(movl %imm0,rcontext(tcr.save_tsp))
+	__(movl %imm0,rcontext(tcr.next_tsp))
+	__(movd %mm0,%imm0)
+	__(jmp local_label(_nthrow1v_nextframe))
+local_label(_nthrow1v_do_unwind):
+/* This is harder, but not as hard (not as much BLTing) as the */
+/* multiple-value case. */
+	__(movl catch_frame.xframe(%temp1),%arg_y)
+	__(movl %arg_y,rcontext(tcr.xframe))
+	__(movl catch_frame.ebp(%temp1),%ebp)
+	__(movl catch_frame.esp(%temp1),%esp)
+	__(movd catch_frame.foreign_sp(%temp1),%stack_temp)
+	__(movd %stack_temp,rcontext(tcr.foreign_sp))
+	/* Discard the catch frame so we can build a temp frame. */
+	__(movl -(tsp_frame.fixed_overhead+fulltag_misc)(%temp1),%imm0)
+	__(movl %imm0,rcontext(tcr.save_tsp))
+	__(movl %imm0,rcontext(tcr.next_tsp))
+	__(movl catch_frame.pc(%temp1),%xfn) /* xfn is temp1 */
+	__(TSP_Alloc_Fixed((3*node_size),%imm0))
+	__(addl $tsp_frame.fixed_overhead,%imm0)
+	__(movl %ra0,(%imm0))
+	__(movd %mm0,node_size*1(%imm0))
+	__(movl %arg_z,node_size*2(%imm0))
+/* Ready to call cleanup code.  Set up tra, jmp to %xfn. */
+	__(push $local_label(_nthrow1v_called_cleanup))
+	__(movb $0,rcontext(tcr.unwinding))
+	__(jmp *%xfn)
+__(tra(local_label(_nthrow1v_called_cleanup)))
+	__(movb $1,rcontext(tcr.unwinding))
+	__(movl rcontext(tcr.save_tsp),%imm0)
+	__(movl tsp_frame.data_offset+(0*node_size)(%imm0),%ra0)
+	__(movd tsp_frame.data_offset+(1*node_size)(%imm0),%mm0)
+	__(movl tsp_frame.data_offset+(2*node_size)(%imm0),%arg_z)
+	__(movl (%imm0),%imm0)
+	__(movl %imm0,rcontext(tcr.save_tsp))
+	__(movl %imm0,rcontext(tcr.next_tsp))
+	__(movd %mm0,%imm0)
+	__(jmp local_label(_nthrow1v_nextframe))
+local_label(_nthrow1v_done):
+	__(movb $0,rcontext(tcr.unwinding))
+	__(check_pending_interrupt(%imm0))
+local_label(_nthrow1v_return):
+	__(jmp *%ra0)
+_endsubp(nthrow1value)
+
+/* This never affects the symbol's vcell   */
+/* Non-null symbol in arg_y, new value in arg_z           */
+
+_spentry(bind)
+	__(movl symbol.binding_index(%arg_y),%imm0)
+	__(cmpl rcontext(tcr.tlb_limit),%imm0)
+	__(jb 0f)
+	__(push %imm0)
+	__(tlb_too_small())
+0:	__(test %imm0,%imm0)
+	__(jz 9f)
+	__(movl rcontext(tcr.tlb_pointer),%temp1)
+	__(push (%temp1,%imm0))
+	__(push %imm0)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(movl %arg_z,(%temp1,%imm0))
+	__(jmp *%ra0)
+9:	
+	__(movl %arg_y,%arg_z)
+	__(movl $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(bind)
+
+/* arg_z = symbol: bind it to its current value  */
+
+_spentry(bind_self)
+	__(movl symbol.binding_index(%arg_z),%imm0)
+	__(cmpl rcontext(tcr.tlb_limit),%imm0)
+	__(jb 0f)
+	__(push %imm0)
+	__(tlb_too_small())
+0:	__(test %imm0,%imm0)
+	__(jz 9f)
+	__(movl rcontext(tcr.tlb_pointer),%temp1)
+	__(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
+	__(jz 2f)
+	__(push (%temp1,%imm0))
+	__(push %imm0)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(jmp *%ra0)
+2:	__(movl symbol.vcell(%arg_z),%arg_y)
+	__(push (%temp1,%imm0))
+	__(push %imm0)
+	__(push rcontext(tcr.db_link))
+	__(movl %arg_y,(%temp1,%imm0))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(jmp *%ra0)
+9:	__(movl $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(bind_self)
+
+_spentry(bind_nil)
+	__(movl symbol.binding_index(%arg_z),%imm0)
+	__(cmpl rcontext(tcr.tlb_limit),%imm0)
+	__(jb 0f)
+	__(push %imm0)
+	__(tlb_too_small())
+0:	__(test %imm0,%imm0)
+	__(jz 9f)
+	__(movl rcontext(tcr.tlb_pointer),%temp1)
+	__(push (%temp1,%imm0))
+	__(push %imm0)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(movl $nil_value,(%temp1,%imm0))
+	__(jmp *%ra0)
+9:	__(movl $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(bind_nil)
+
+_spentry(bind_self_boundp_check)
+	__(movl symbol.binding_index(%arg_z),%imm0)
+	__(cmpl rcontext(tcr.tlb_limit),%imm0)
+	__(jb 0f)
+	__(push %imm0)
+	__(tlb_too_small())
+0:	__(test %imm0,%imm0)
+	__(jz 9f)
+	__(movl rcontext(tcr.tlb_pointer),%temp1)
+	__(cmpb $no_thread_local_binding_marker,(%temp1,%imm0))
+	__(je 2f)
+	__(cmpb $unbound_marker,(%temp1,%imm0))
+	__(je 8f)
+	__(push (%temp1,%imm0))
+	__(push %imm0)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(jmp *%ra0)
+2:	__(movl symbol.vcell(%arg_z),%arg_y)
+	__(cmpl $unbound_marker,%arg_y)
+	__(jz 8f)
+	__(push (%temp1,%imm0))
+	__(push %imm0)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(movl %arg_y,(%temp1,%imm0))
+	__(jmp *%ra0)
+8:	__(push %ra0)
+        __(uuo_error_reg_unbound(Rarg_z))
+	
+9:	__(movl $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(bind_self_boundp_check)
+
+_spentry(conslist)
+	__(movl %nargs,%imm0)
+	__(movl %temp0,%temp1)	/* have to use temp0 for consing */
+	__(movl $nil_value,%arg_z)
+	__(test %imm0,%imm0)
+	__(jmp 2f)
+1:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%imm0)
+2:	__(jnz 1b)
+	__(jmp *%temp1)
+_endsubp(conslist)
+
+/* do list*: last arg in arg_z, all others pushed, nargs set to #args pushed.  */
+/* Cons, one cons cell at at time.  Maybe optimize this later.  */
+
+_spentry(conslist_star)
+	__(movl %nargs,%imm0)
+	__(test %imm0,%imm0)
+	__(movl %ra0,%temp1)
+	__(jmp 2f)
+1:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%imm0)
+2:	__(jnz 1b)
+	__(jmp *%temp1)
+_endsubp(conslist_star)
+
+/* We always have to create a tsp frame (even if nargs is 0), so the compiler */
+/* doesn't get confused. */
+_spentry(stkconslist)
+	__(movl $nil_value,%arg_z)
+C(stkconslist_common):               
+	__(movl %ra0,rcontext(tcr.save0))
+	__(movd %nargs,%mm0)
+	__(movl %nargs,%temp0)
+	__(addl %temp0,%temp0)
+	__(dnode_align(%temp0,tsp_frame.fixed_overhead,%temp0))
+	__(TSP_Alloc_Var(%temp0,%imm0))
+	__(addl $fulltag_cons,%imm0)
+	__(test %nargs,%nargs)
+	__(jmp 2f)
+1:	__(pop %arg_y)
+	__(_rplaca(%imm0,%arg_y))
+	__(_rplacd(%imm0,%arg_z))
+	__(movl %imm0,%arg_z)
+	__(add $cons.size,%imm0)
+	__(subl $node_size,%nargs)
+2:	__(jne 1b)
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movl $0,rcontext(tcr.save0))
+	__(jmp *%ra0)
+_endsubp(stkconslist)
+
+/* do list*: last arg in arg_z, all others vpushed,   */
+/*	nargs set to #args vpushed.  */
+
+_spentry(stkconslist_star)
+        __(jmp C(stkconslist_common))
+_endsubp(stkconslist_star)
+
+
+/* Make a stack-consed simple-vector out of the NARGS objects   */
+/*	on top of the vstack; return it in arg_z.  */
+
+_spentry(mkstackv)
+	__(dnode_align(%nargs,tsp_frame.fixed_overhead+node_size,%imm0))
+	__(TSP_Alloc_Var(%imm0,%arg_y))
+	__(movl %nargs,%imm0)
+	__(shll $(num_subtag_bits-fixnumshift),%imm0)
+	__(movb $subtag_simple_vector,%imm0_b)
+	__(movl %imm0,(%arg_y))
+	__(leal fulltag_misc(%arg_y),%arg_z)
+	__(test %nargs,%nargs)
+	__(leal misc_data_offset(%arg_z,%nargs),%imm0)
+	__(jmp 2f)
+1:	__(pop -node_size(%imm0))
+	__(subl $node_size,%nargs)
+	__(leal -node_size(%imm0),%imm0)
+2:	__(jne 1b)
+	__(jmp *%ra0)	
+_endsubp(mkstackv)
+
+        .globl C(egc_write_barrier_start)
+C(egc_write_barrier_start):
+/*  */
+/* The function pc_luser_xp() - which is used to ensure that suspended threads  */
+/* are suspended in a GC-safe way - has to treat these subprims (which implement  */
+/* the EGC write-barrier) specially.  Specifically, a store that might introduce  */
+/* an intergenerational reference (a young pointer stored in an old object) has  */
+/* to "memoize" that reference by setting a bit in the global "refbits" bitmap.  */
+/* This has to happen atomically, and has to happen atomically wrt GC.  */
+
+/* Note that updating a word in a bitmap is itself not atomic, unless we use  */
+/* interlocked loads and stores.  */
+
+/* For RPLACA and RPLACD, things are fairly simple: regardless of where we are  */
+/* in the function, we can do the store (even if it's already been done) and  */
+/* calculate whether or not we need to set the bit out-of-line.  (Actually  */
+/* setting the bit needs to be done atomically, unless we're sure that other  */
+/* threads are suspended.)  */
+/* We can unconditionally set the suspended thread's RIP to the return address.  */
+
+_spentry(rplaca)
+        .globl C(egc_rplaca)
+C(egc_rplaca):
+	__(rcmpl(%arg_z,%arg_y))
+	__(_rplaca(%arg_y,%arg_z))
+	__(ja 1f)
+0:	__(repret)
+1:	__(movl %arg_y,%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(cmpl lisp_global(oldspace_dnode_count),%imm0)
+	__(jae 0b)
+	__(ref_global(refbits,%temp0))
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp0))
+	__(ret)
+_endsubp(rplaca)
+
+_spentry(rplacd)
+        .globl C(egc_rplacd)
+C(egc_rplacd):
+	__(rcmpl(%arg_z,%arg_y))
+	__(_rplacd(%arg_y,%arg_z))
+	__(ja 1f)
+0:	__(repret)
+1:	__(movl %arg_y,%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(cmpl lisp_global(oldspace_dnode_count),%imm0)
+	__(jae 0b)
+	__(ref_global(refbits,%temp0))
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp0))
+	__(ret)
+_endsubp(rplacd)
+
+/* Storing into a gvector can be handled the same way as storing into a CONS. */
+/* args (src, unscaled-idx, val) in temp0, arg_y, arg_z */
+_spentry(gvset)
+        .globl C(egc_gvset)
+C(egc_gvset):
+	__(movl %arg_z,misc_data_offset(%temp0,%arg_y))
+	__(rcmpl(%arg_z,%temp0))
+	__(ja 1f)
+0:	__(repret)
+1:	__(lea misc_data_offset(%temp0,%arg_y),%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(cmpl lisp_global(oldspace_dnode_count),%imm0)
+	__(jae 0b)
+	__(ref_global(refbits,%temp1))
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp1))
+	__(ret)
+_endsubp(gvset)
+
+/* This is a special case of storing into a gvector: if we need to  */
+/* memoize the store, record the address of the hash-table vector  */
+/* in the refmap, as well.  */
+
+_spentry(set_hash_key)
+        .globl C(egc_set_hash_key)
+C(egc_set_hash_key):
+	__(movl %arg_z,misc_data_offset(%temp0,%arg_y))
+	__(rcmpl(%arg_z,%temp0))
+	__(ja 1f)
+0:	__(repret)
+1:	__(lea misc_data_offset(%temp0,%arg_y),%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(cmpl lisp_global(oldspace_dnode_count),%imm0)
+	__(jae 0b)
+	__(ref_global(refbits,%temp1))
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp1))
+	/* Now memoize the address of the hash vector */
+	__(movl %temp0,%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp1))
+	__(ret)
+_endsubp(set_hash_key)
+
+/* This is a little trickier: if this is interrupted, we need to know  */
+/* whether or not the STORE-CONDITIONAL (cmpxchgq) has won or not.    */
+/* If we're interrupted   before the PC has reached the "success_test" label, */
+/* repeat (luser the PC back to store_node_conditional_retry.)  If
+	we're at that */
+/* label with the Z flag set, we won and (may) need to memoize.  */
+
+/* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
+_spentry(store_node_conditional)
+        .globl C(egc_store_node_conditional)
+C(egc_store_node_conditional):
+	__(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
+	__(sarl $fixnumshift,%temp0)	/* will be fixnum-tagged */
+        .globl C(egc_store_node_conditional_retry)
+C(egc_store_node_conditional_retry):      
+0:	__(cmpl %arg_y,misc_data_offset(%temp1,%temp0))
+	__(movl misc_data_offset(%temp1,%temp0),%imm0)
+	__(jne 3f)
+	__(lock)
+	__(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
+	.globl C(egc_store_node_conditional_success_test)
+C(egc_store_node_conditional_success_test):
+	__(jne 0b)
+	__(leal misc_data_offset(%temp1,%temp0),%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(cmpl lisp_global(oldspace_dnode_count),%imm0)
+	__(jae 2f)
+	__(ref_global(refbits,%temp1))
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp1))
+        .globl C(egc_store_node_conditional_success_end)
+C(egc_store_node_conditional_success_end):
+2:	__(movl $t_value,%arg_z)
+	__(ret)
+3:	__(movl $nil_value,%arg_z)
+	__(ret)
+_endsubp(store_node_conditional)
+
+	/* %temp0 = offset, %temp1 = object, %arg_y = old, %arg_z = new */
+_spentry(set_hash_key_conditional)
+        .globl C(egc_set_hash_key_conditional)
+C(egc_set_hash_key_conditional):
+	__(subl $misc_data_offset*fixnumone,%temp0) /* undo pre-added offset */
+	__(sarl $fixnumshift,%temp0)	/* will be fixnum-tagged */
+        .globl C(egc_set_hash_key_conditional_retry)
+C(egc_set_hash_key_conditional_retry):          
+0:	__(cmpl %arg_y,misc_data_offset(%temp1,%temp0))
+	__(movl misc_data_offset(%temp1,%temp0),%imm0)
+	__(jne 3f)
+	__(lock)
+	__(cmpxchgl %arg_z,misc_data_offset(%temp1,%temp0))
+	.globl C(egc_set_hash_key_conditional_success_test)
+C(egc_set_hash_key_conditional_success_test):
+	__(jne 0b)
+	__(leal misc_data_offset(%temp1,%temp0),%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(cmpl lisp_global(oldspace_dnode_count),%imm0)
+	__(jae 2f)
+	__(ref_global(refbits,%temp0))
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp0))
+	/* Now memoize the address of the hash vector */
+	__(movl %temp1,%imm0)
+	__(subl lisp_global(ref_base),%imm0)
+	__(shrl $dnode_shift,%imm0)
+	__(xorb $31,%imm0_b)
+	__(lock)
+	__(btsl %imm0,(%temp0))
+        .globl C(egc_write_barrier_end)
+C(egc_write_barrier_end):
+2:	__(movl $t_value,%arg_z)
+	__(ret)
+3:	__(movl $nil_value,%arg_z)
+	__(ret)
+_endsubp(store_node_conditional)
+
+_spentry(setqsym)
+	__(bt $sym_vbit_const,symbol.flags(%arg_y))
+	__(jae _SPspecset)
+	__(mov %arg_y,%arg_z)
+	__(mov $XCONST,%arg_y)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+_endsubp(setqsym)
+
+_spentry(progvsave)
+	__(push %arg_y)
+	
+	/* Error if arg_z isn't a proper list.  That's unlikely,  */
+	/* but it's better to check now than to crash later.  */
+	
+	__(compare_reg_to_nil(%arg_z))
+	__(movl %arg_z,%temp0)	/* fast   */
+	__(movl %arg_z,%temp1)	/* slow   */
+	__(je 9f)		/* Null list is proper   */
+0:
+	__(extract_lisptag(%temp0,%imm0))
+	__(cmpb $tag_list,%imm0_b)
+	__(jne 8f)
+	__(compare_reg_to_nil(%temp0))
+	__(je 9f)
+	__(_cdr(%temp0,%arg_y))	/* (null (cdr fast)) ?   */
+	__(compare_reg_to_nil(%arg_y))
+	__(je 9f)
+	__(extract_lisptag(%arg_y,%imm0))
+	__(cmpb $tag_list,%imm0_b)
+	__(jne 8f)
+	__(_cdr(%arg_y,%temp0))
+	__(_cdr(%temp1,%temp1))
+	__(cmpl %temp1,%temp0)
+	__(jne 0b)
+
+8:	__(add $node_size,%esp)	/* discard pushed arg_y */
+	__(movl $XIMPROPERLIST,%arg_y)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+9:	/* Whew 	  */
+
+        /* Next, determine the length of arg_y.  We   */
+	/* know that it's a proper list.   */
+	__(pop %arg_y)
+	
+	__(movl $-fixnumone,%imm0)
+	__(movl %arg_y,%temp0)
+1:	__(compare_reg_to_nil(%temp0))
+	__(_cdr(%temp0,%temp0))
+	__(leal fixnumone(%imm0),%imm0)
+	__(jne 1b)
+	
+	/* imm0 is now (boxed) triplet count.  */
+	/* Determine word count, add 1 (to align), and make room.  */
+	/*  if count is 0, make an empty tsp frame and exit   */
+	__(testl %imm0,%imm0)
+	__(jne 2f)
+	__(TSP_Alloc_Fixed(2*node_size,%imm0))
+	__(ret)
+2:	__(movl %imm0,%temp1)
+	__(add %imm0,%imm0)
+	__(add %temp1,%imm0)
+	__(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
+	__(TSP_Alloc_Var(%imm0,%temp0))
+	__(movl %temp1,(%temp0))
+	__(movd rcontext(tcr.db_link),%mm0)
+3:	__(movl $unbound_marker,%temp0)
+	__(compare_reg_to_nil(%arg_z))
+	__(cmovnel cons.car(%arg_z),%temp0)
+	__(cmovnel cons.cdr(%arg_z),%arg_z)
+	__(_car(%arg_y,%temp1))
+	__(_cdr(%arg_y,%arg_y))
+	__(movl symbol.binding_index(%temp1),%temp1)
+	__(cmp rcontext(tcr.tlb_limit),%temp1)
+	__(jb 4f)
+	__(push %temp1)
+	__(tlb_too_small())
+4:	__(push %arg_z)
+	__(movl rcontext(tcr.tlb_pointer),%arg_z)
+	__(subl $binding.size,%imm0)
+	__(movl %temp1,binding.sym(%imm0))
+	__(push (%arg_z,%temp1))
+	__(pop binding.val(%imm0))
+	__(movl %temp0,(%arg_z,%temp1))
+	__(pop %arg_z)
+	__(movd %mm0,binding.link(%imm0))
+	__(movd %imm0,%mm0)
+	__(compare_reg_to_nil(%arg_y))
+	__(jne 3b)
+	__(movd %mm0,rcontext(tcr.db_link))
+	__(ret)
+_endsubp(progvsave)
+
+/* Allocate node objects on the temp stack, immediate objects on the foreign  */
+/* stack. (The caller has to know which stack to discard a frame from.)  */
+/* %arg_y = boxed element-count, %arg_z = boxed subtype  */
+
+_spentry(stack_misc_alloc)
+	__(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
+	__(jne local_label(stack_misc_alloc_not_u24))
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(mov %arg_y,%temp0)
+	__(shl $num_subtag_bits-fixnumshift,%temp0)
+	__(or %temp0,%imm0)	/* %imm0 now = header */
+	__(movd %imm0,%mm0)	/* cache header in %mm0 */
+	__(andb $fulltagmask,%imm0_b)
+	__(cmpb $fulltag_nodeheader,%imm0_b)
+	__(je local_label(stack_misc_alloc_node))
+	__(movd %mm0,%imm0)
+	__(cmpb $max_32_bit_ivector_subtag,%imm0_b)
+	__(jbe local_label(stack_misc_alloc_32))
+	__(cmpb $max_8_bit_ivector_subtag,%imm0_b)
+	__(jbe local_label(stack_misc_alloc_8))
+	__(cmpb $max_16_bit_ivector_subtag,%imm0_b)
+	__(jbe local_label(stack_misc_alloc_16))
+	__(cmpb $subtag_double_float_vector,%imm0_b)
+	__(jne local_label(stack_misc_alloc_1))
+	/* double-float vector case */
+	__(imul $2,%arg_y,%imm0)
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_1):
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(addl $7,%imm0)
+	__(shrl $3,%imm0)
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_8):
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_16):
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(shl $1,%imm0)
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_32):
+	__(mov %arg_y,%imm0)
+local_label(stack_misc_alloc_alloc_ivector):
+	/* byte count in %imm0 */
+	__(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
+	__(cmpl $tstack_alloc_limit,%imm0)
+	__(ja local_label(stack_misc_alloc_heap_alloc_ivector))
+        __ifdef([WINDOWS])
+         __(windows_cstack_probe(%imm0,%temp1))
+        __endif
+	__(movd rcontext(tcr.foreign_sp),%stack_temp)
+	__(movd %stack_temp,%temp1)
+	__(subl %imm0,rcontext(tcr.foreign_sp))
+	__(movl rcontext(tcr.foreign_sp),%temp0)
+0:	__(movsd %fpzero,-dnode_size(%temp1))
+	__(subl $dnode_size,%temp1)
+	__(cmpl %temp1,%temp0)
+	__(jnz 0b)
+	__(movd %stack_temp,(%temp0))
+	__(movl %ebp,csp_frame.save_ebp(%temp0))
+	__(movd %mm0,csp_frame.fixed_overhead(%temp0))
+	__(lea csp_frame.fixed_overhead+fulltag_misc(%temp0),%arg_z)
+	__(ret)
+local_label(stack_misc_alloc_heap_alloc_ivector):
+	__(movd rcontext(tcr.foreign_sp),%stack_temp)
+	__(subl $dnode_size,rcontext(tcr.foreign_sp))
+	__(movl rcontext(tcr.foreign_sp),%imm0)
+	__(movd %stack_temp,(%imm0))
+	__(jmp _SPmisc_alloc)
+local_label(stack_misc_alloc_node):
+	__(movl %arg_y,%imm0)
+	__(dnode_align(%imm0,tsp_frame.fixed_overhead+node_size,%imm0))
+	__(cmpl $tstack_alloc_limit,%imm0)
+	__(ja local_label(stack_misc_alloc_heap_alloc_gvector))
+	__(TSP_Alloc_Var(%imm0,%temp1))
+	__(movd %mm0,(%temp1))
+	__(leal fulltag_misc(%temp1),%arg_z)
+	__(ret)
+local_label(stack_misc_alloc_heap_alloc_gvector):
+	__(TSP_Alloc_Fixed(0,%imm0))
+	__(jmp _SPmisc_alloc)
+
+local_label(stack_misc_alloc_not_u24):
+	__(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_24))
+_endsubp(stack_misc_alloc)
+
+/* subtype (boxed, of course) is pushed, followed by nargs bytes worth of */
+/* initial-contents.  Note that this can be used to cons any type of */
+/* initialized node-header'ed misc object (symbols, closures, ...) */
+/* as well as vector-like objects. */
+_spentry(gvector)
+	__(subl $node_size,%nargs)	/* off by one in x862-%gvector */
+	__(movl (%esp,%nargs),%imm0)	/* boxed subtype */
+	__(sarl $fixnumshift,%imm0)
+	__(movl %nargs,%arg_z)
+	__(shll $num_subtag_bits-word_shift,%arg_z)
+	__(orl %arg_z,%imm0)
+	__(movd %imm0,%mm0)
+	__(dnode_align(%nargs,node_size,%imm0))
+	__(push %ra0)	/* aka %temp0, can't be live while consing */
+	__(Misc_Alloc(%arg_z))
+	__(pop %ra0)
+	__(movl %nargs,%imm0)
+	__(jmp 2f)
+1:	__(movl %arg_y,misc_data_offset(%arg_z,%imm0))
+2:	__(subl $node_size,%imm0)
+	__(pop %arg_y)	/* Note the intentional fencepost: */
+			/* discard the subtype as well. */
+	__(jge 1b)
+	__(jmp *%ra0)
+_endsubp(gvector)
+
+_spentry(mvpass)
+	__(hlt)
+_endsubp(mvpass)
+
+_spentry(nthvalue)
+	__(hlt)
+_endsubp(nthvalue)
+
+_spentry(values)
+	__(movl (%temp0),%arg_y)	/* return address */
+	__(ref_global(ret1val_addr,%imm0))
+	__(movl $nil_value,%arg_z)
+	__(cmpl %imm0,%arg_y)
+	__(je 0f)
+	__(test %nargs,%nargs)
+	__(cmovne -node_size(%esp,%nargs),%arg_z)
+	__(movl %temp0,%esp)
+	__(ret)
+0:	__(movl 4(%temp0),%arg_y)
+        __(addl $2*node_size,%temp0)
+	__(lea (%esp,%nargs),%imm0)
+	__(movd %nargs,%mm0)
+	__(jmp 2f)
+1:	__(subl $node_size,%imm0)
+	__(movl (%imm0),%temp1)
+	__(subl $node_size,%temp0)
+	__(movl %temp1,(%temp0))
+2:	__(cmp %imm0,%esp)
+	__(jne 1b)
+	__(movl %temp0,%esp)
+	__(movd %mm0,%nargs)
+	__(jmp *%arg_y)
+
+_endsubp(values)
+
+_spentry(default_optional_args)
+	__(hlt)
+_endsubp(default_optional_args)
+
+_spentry(opt_supplied_p)
+	__(hlt)
+_endsubp(opt_supplied_p)
+
+_spentry(lexpr_entry)
+	__(hlt)
+_endsubp(lexpr_entry)
+
+_spentry(heap_rest_arg)
+	__(push_argregs())
+	__(movl %temp0,%arg_y)
+	__(movl %nargs,%imm0)
+	__(testl %imm0,%imm0)
+	__(movl $nil_value,%arg_z)
+	__(jmp 2f)
+	.p2align 4
+1:	__(pop %temp1)
+	__(Cons(%temp1,%arg_z,%arg_z))
+	__(subl $node_size,%imm0)
+2:	__(jg 1b)
+	__(push %arg_z)
+	__(movl %arg_y,%temp0)
+	__(jmp *%ra0)
+
+_endsubp(heap_rest_arg)
+
+/* %imm0 contains the number of fixed args; make an &rest arg out of */
+/* the others. */
+_spentry(req_heap_rest_arg)
+	__(push_argregs())
+	__(movd %nargs,%mm0)
+	__(subl %imm0,%nargs)
+	__(movl %nargs,%imm0)
+	__(movl %temp0,%temp1)
+	__(movl $nil_value,%arg_z)
+	__(jmp 2f)
+	.p2align 4
+1:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%imm0)
+2:	__(jg 1b)
+	__(push %arg_z)
+	__(movl %temp1,%temp0)
+	__(movd %mm0,%nargs)
+	__(jmp *%ra0)
+_endsubp(req_heap_rest_arg)
+
+/* %imm0 bytes of stuff has already been pushed	  */
+/* make an &rest arg out of any others   */
+_spentry(heap_cons_rest_arg)
+	__(movd %nargs,%mm0)
+	__(subl %imm0,%nargs)
+	__(movl %nargs,%imm0)
+	__(movl $nil_value,%arg_z)
+	__(movl %ra0,%arg_y)	/* temp0 can't be live while consing */
+	__(jmp 2f)		/* (did I mention that already?) */
+	.p2align 4
+1:	__(pop %temp1)
+	__(Cons(%temp1,%arg_z,%arg_z))
+	__(subl $node_size,%imm0)
+2:	__(jg 1b)
+	__(push %arg_z)
+	__(movd %mm0,%nargs)
+	__(jmp *%arg_y)
+_endsubp(heap_cons_rest_arg)
+
+_spentry(simple_keywords)
+	__(xor %imm0,%imm0)
+	__(push_argregs())
+	__(jmp _SPkeyword_bind)
+_endsubp(simple_keywords)
+
+_spentry(keyword_args)
+	__(push_argregs())
+	__(jmp _SPkeyword_bind)
+_endsubp(keyword_args)
+
+/* There are %nargs words of arguments on the stack; %imm0 contains the */
+/* number of non-keyword args pushed.  It's possible that we never actually */
+/* got any keyword args, which would make things much simpler. */
+
+/* On entry, the upper half of %temp1 (aka %nargs) contains some bits */
+/* indicating whether &allow-other-keys and/or &rest was present in the */
+/* lambda list. */
+
+/* Once we get here, we can use the arg registers. */
+
+/* N.B.: %ra0 is %temp0, and must not be clobbered. */
+
+define([keyword_flags_aok_bit],[16])
+define([keyword_flags_unknown_keys_bit],[17])
+define([keyword_flags_rest_bit],[18])
+define([keyword_flags_seen_aok_bit],[19])
+
+_spentry(keyword_bind)
+	__(movl %temp1,rcontext(tcr.unboxed0))	/* save keyword flags */
+	__(movzwl %nargs_w,%nargs)
+	__(movl %nargs,%arg_z)
+	__(subl %imm0,%arg_z)
+	__(jbe local_label(no_keyword_values))
+	__(btl $word_shift,%arg_z)
+	__(jnc local_label(even))
+	__(movl $nil_value,%arg_y)
+	__(movl %arg_z,%nargs)
+	__(test %nargs,%nargs)
+	__(movl %ra0,rcontext(tcr.save0))	/* save temp0 while consing */
+	__(jmp 1f)
+0:	__(pop %arg_z)
+	__(Cons(%arg_z,%arg_y,%arg_y))
+	__(subl $node_size,%nargs)
+1:	__(jnz 0b)
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movapd %fpzero,rcontext(tcr.save0))
+	__(movl %arg_y,%arg_z)
+	__(movl $XBADKEYS,%arg_y)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+
+	/* Now that we're sure that we have an even number of */
+	/* keywords and values (in %arg_z), move the pairs over */
+	/* to the temp stack. */
+local_label(even):
+	__(lea tsp_frame.fixed_overhead(%arg_z),%arg_y)
+	__(TSP_Alloc_Var(%arg_y,%imm0))
+2:	__(subl $node_size,%arg_y)
+	__(pop (%arg_y))
+	__(cmpl %arg_y,%imm0)
+	__(jne 2b)
+
+	/* Get the keyword vector into %arg_y, and its length into %imm0. */
+	/* Push %imm0 pairs of NILs (representing value, supplied-p) */
+	/* for each declared keyword. */
+	__(movzwl misc_data_offset(%fn),%imm0)
+	/* XXX bootstrapping */
+	__(btr $15,%imm0)
+	__(jnc 0f)
+	__(vector_length(%fn,%arg_y))
+	__(box_fixnum(%imm0,%imm0))
+	__(subl %imm0,%arg_y)
+	__(movl %arg_y,%imm0)
+	__(shrl $fixnumshift,%imm0)
+0:
+	__(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
+	__(vector_length(%arg_y,%imm0))
+	__(jmp 4f)
+3:	__(push $nil_value)
+	__(push $nil_value)
+4:	__(subl $fixnumone,%imm0)
+	__(jge 3b)
+
+	/* We can now push %ra0 (aka %temp0) and %nargs (aka %temp1) */
+	/* in order to get a couple more registers to work with. */
+	__(push %ra0)
+	__(push %nargs)
+
+	/* At this point we have: */
+	/* number of supplied keywords and values in %arg_z */
+	/* keyword vector in %arg_y */
+	__(vector_length(%arg_y,%imm0))
+	__(push %imm0)		/* count of declared keywords */
+	__(push %arg_z)		/* count of supplied keys and values */
+
+	/* For each declared keyword, iterate over the supplied k/v pairs */
+	/* to see if it's supplied and what the value is. */
+	/* checking to see if any */
+	/* key-value pairs were unexpectedly supplied. */
+
+	__(movl rcontext(tcr.save_tsp),%temp0)
+	__(addl $2*node_size,%temp0) /* skip frame overhead */
+	/* %temp0: top of tstack (skipping frame overhead) */
+	__(lea 4*node_size(%esp,%imm0,2),%temp1)
+	/* %temp1: word above 0th value/supplied-p pair on vstack */
+	/* %arg_y: keyword vector */
+	__(xorl %imm0,%imm0)
+	/* %imm0: index */
+	/* %arg_z: temporary */
+
+	/* Iterate over supplied k/v pairs on tstack.  See if key is */
+	/* in the keyword vector.  Copy value and set supplied-p on */
+	/* vstack if found. */
+
+local_label(tstack_loop):
+	__(movl (%temp0,%imm0,2),%arg_z)	/* keyword */
+	__(push %imm0)
+	__(xorl %imm0,%imm0)
+	__(cmpl $nrs.kallowotherkeys,%arg_z)
+	__(jne local_label(next_keyvect_entry))
+	__(btsl $keyword_flags_seen_aok_bit,rcontext(tcr.unboxed0))
+	__(jc local_label(next_keyvect_entry))
+	__(push %imm0)
+	__(movl 4(%esp),%imm0)
+	__(cmpl $nil_value,node_size(%temp0,%imm0,2))
+	__(pop %imm0)
+	__(je local_label(next_keyvect_entry))
+	__(btsl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
+	__(jmp local_label(next_keyvect_entry))
+	/* loop through keyword vector */
+6:	__(cmpl misc_data_offset(%arg_y,%imm0),%arg_z)
+	__(jne 7f)
+	/* Got a match; have we already seen this keyword? */
+	__(negl %imm0)
+	__(cmpl $nil_value,-node_size*2(%temp1,%imm0,2))
+	__(jne 9f)	/* seen it, ignore this value */
+	__(movl (%esp),%arg_z)
+	__(lea (%temp0,%arg_z,2),%arg_z)
+	__(movl node_size(%arg_z),%arg_z) /* value for this key */
+	__(movl %arg_z,-node_size(%temp1,%imm0,2))
+	__(movl $t_value,-node_size*2(%temp1,%imm0,2))
+	__(jmp 9f)
+7:	__(addl $node_size,%imm0)
+local_label(next_keyvect_entry):
+	__(cmpl %imm0,8(%esp))
+	__(jne 6b)
+	/* Didn't match anything in the keyword vector.  Is the keyword */
+	/* :allow-other-keys? */
+	__(cmpl $nrs.kallowotherkeys,%arg_z)
+	__(je 9f)	/* :allow-other-keys is never "unknown" */
+8:	__(btsl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
+9:	__(pop %imm0)
+	__(addl $fixnumone,%imm0)
+	__(movl %imm0,%arg_z)
+	__(shll $1,%arg_z)	/* pairs of tstack words */
+	__(cmpl %arg_z,0(%esp))
+	__(jne local_label(tstack_loop))
+
+	__(pop %imm0)	/* count of supplied keys and values */
+	__(addl $node_size,%esp)
+	__(pop %nargs)
+	__(pop %ra0)
+
+	/* If the function takes an &rest arg, or if we got an unrecognized */
+	/* keyword and don't allow that, copy the incoming k/v pairs from */
+	/* the temp stack back to the value stack. */
+	__(btl $keyword_flags_rest_bit,rcontext(tcr.unboxed0))
+	__(jc 1f)
+	__(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
+	__(jnc 0f)
+	__(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
+	__(jnc 1f)
+	/* pop the tstack frame */
+0:	__(discard_temp_frame(%imm0))
+	__(jmp *%ra0)
+
+	/* Copy the k/v pairs from the tstack back to the value stack, */
+	/* either because the function takes an &rest arg or because */
+	/* we need to signal an "unknown keywords" error. */
+1:	__(movl rcontext(tcr.save_tsp),%arg_z)
+	__(mov (%arg_z),%arg_y)
+	__(jmp 3f)
+2:	__(push (%arg_z))
+	__(push node_size(%arg_z))
+3:	__(addl $dnode_size,%arg_z)
+	__(cmpl %arg_z,%arg_y)
+	__(jne 2b)
+	__(discard_temp_frame(%arg_z))
+	__(btl $keyword_flags_unknown_keys_bit,rcontext(tcr.unboxed0))
+	__(jnc 9f)
+	__(btl $keyword_flags_aok_bit,rcontext(tcr.unboxed0))
+	__(jc 9f)
+	/* Signal an "unknown keywords" error */
+	__(movl %imm0,%nargs)
+	__(movl $nil_value,%arg_z)
+	__(test %nargs,%nargs)
+	__(movl %ra0,rcontext(tcr.save0))
+	__(jmp 5f)
+4:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%nargs)
+5:	__(jnz 4b)
+	__(movl $XBADKEYS,%arg_y)
+	__(set_nargs(2))
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movl $0,rcontext(tcr.save0))
+	__(jmp _SPksignalerr)
+9:	__(jmp *%ra0)
+
+/* No keyword value were provided.  Access the keyword vector (which is the */
+/* 0th constant in %fn), determine its length N, and push N pairs of NILs. */
+/* N could be 0... */
+
+local_label(no_keyword_values):
+	__(movzwl misc_data_offset(%fn),%imm0)
+	/* XXX bootstrapping */
+	__(btr $15,%imm0)
+	__(jnc 9f)
+	__(vector_length(%fn,%arg_y))
+	__(box_fixnum(%imm0,%imm0))
+	__(subl %imm0,%arg_y)
+	__(movl %arg_y,%imm0)
+	__(shrl $fixnumshift,%imm0)
+9:
+	__(movl misc_data_offset(%fn,%imm0,node_size),%arg_y)
+	__(vector_length(%arg_y,%arg_z))
+	__(movl $nil_value,%imm0)
+	__(jmp 1f)
+0:	__(push %imm0)
+	__(push %imm0)
+1:	__(subl $fixnumone,%arg_z)
+	__(jge 0b)
+	__(jmp *%ra0)
+_endsubp(keyword_bind)
+
+/* Normally, we'd just set %fname (aka %temp0) and do */
+/* jump_fname().  Sometimes, though, %temp0 is being used */
+/* as %ra0, and I'm not sure that it's going to be safe to */
+/* clobber that.  (Note that nil-relative symbols aren't going */
+/* get moved around by the GC, so we can get away with putting */
+/* '%err-disp in %imm0.) */
+_spentry(ksignalerr)
+	__(mov $nrs.errdisp,%imm0)
+	__(mov symbol.fcell(%imm0),%fn)
+	__(jump_fn)
+_endsubp(ksignalerr)
+
+_spentry(stack_rest_arg)
+	__(xorl %imm0,%imm0)
+	__(push_argregs())
+	__(jmp _SPstack_cons_rest_arg)
+_endsubp(stack_rest_arg)
+
+_spentry(req_stack_rest_arg)
+	__(push_argregs())
+	__(jmp _SPstack_cons_rest_arg)
+_endsubp(req_stack_rest_arg)
+
+_spentry(stack_cons_rest_arg)
+	__(movd %nargs,%mm2)
+	__(movl %temp0,rcontext(tcr.save0))
+	__(subl %imm0,%temp1)
+	__(movl $nil_value,%arg_z)
+	__(jle 2f)	/* empty list; make an empty TSP frame */
+	__(addl %temp1,%temp1)
+	__(cmpl $(tstack_alloc_limit-dnode_size),%temp1)
+	__(ja 3f)	/* make empty frame, then heap-cons */
+	__(dnode_align(%temp1,tsp_frame.fixed_overhead,%imm0))
+	__(TSP_Alloc_Var(%imm0,%temp0))
+	__(addl $fulltag_cons,%temp0)
+1:	__(pop %arg_y)
+	__(_rplacd(%temp0,%arg_z))
+	__(_rplaca(%temp0,%arg_y))
+	__(movl %temp0,%arg_z)
+	__(addl $cons.size,%temp0)
+	__(subl $dnode_size,%temp1)
+	__(jne 1b)
+	__(push %arg_z)
+	__(movd %mm2,%nargs)
+	__(movl rcontext(tcr.save0),%temp0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(jmp *%temp0)
+/* Length 0, make empty frame */
+2:
+	__(TSP_Alloc_Fixed(0,%temp0))
+	__(push %arg_z)
+	__(movd %mm2,%nargs)
+	__(movl rcontext(tcr.save0),%temp0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(jmp *%temp0)
+/* Too big to stack-cons, but make an empty frame before heap-consing */
+	__(TSP_Alloc_Fixed(0,%temp0))
+	__(movd %mm2,%nargs)
+	__(movl rcontext(tcr.save0),%temp0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(jmp _SPheap_cons_rest_arg)
+_endsubp(stack_cons_rest_arg)
+
+_spentry(getxlong)
+	__(hlt)
+_endsubp(getxlong)
+
+/* Have to be a little careful here: the caller may or may not have pushed  */
+/* an empty frame, and we may or may not have needed one.  We can't easily  */
+/* tell whether or not a frame will be needed (if the caller didn't reserve  */
+/* a frame, whether or not we need one depends on the length of the list  */
+/* in arg_z.  So, if the caller didn't push a frame, we do so; once */
+/* everything's been spread, we discard the reserved frame (regardless of
+/* who pushed it) if all args fit in registers.   */
+
+/* xxx preserve temp1 somehow? cf. comment in x862-invoke-fn */
+_spentry(spreadargz)
+	__(test %nargs,%nargs)
+	__(jne 0f)
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+0:	__(movl %arg_z,rcontext(tcr.save0))	/* save in case of error */
+	__(movd %nargs,%mm0)	/* now we can use %temp1 */
+	__(xorl %nargs,%nargs)
+	__(cmpl $nil_value,%arg_z)
+	__(je 2f)
+1:	__(extract_fulltag(%arg_z,%imm0))
+	__(cmpb $fulltag_cons,%imm0_b)
+	__(jne 9f)
+	__(_car(%arg_z,%arg_y))
+	__(_cdr(%arg_z,%arg_z))
+	__(add $node_size,%nargs)
+	__(cmpl $call_arguments_limit<<fixnumshift,%nargs)
+	__(jge 8f)
+	__(push %arg_y)
+	__(cmpl $nil_value,%arg_z)
+	__(jne 1b)
+2:	__(movd %mm0,%imm0)
+	__(addl %imm0,%nargs)
+	__(jne 4f)
+3:	__(addl $2*node_size,%esp)
+	__(movl $0,rcontext(tcr.save0))
+	__(jmp *%ra0)
+4:	__(pop %arg_z)
+	__(cmp $1*node_size,%nargs)
+	__(je 3b)
+	__(pop %arg_y)
+	__(cmp $2*node_size,%nargs)
+	__(je 3b)
+	__(movl $0,rcontext(tcr.save0))
+	__(jmp *%ra0)
+/* Discard everything that's been pushed already, complain */
+8:	__(lea (%esp,%nargs),%esp)
+	__(movl rcontext(tcr.save0),%arg_z) /* recover original */
+	__(movl $0,rcontext(tcr.save0))
+	__(movl $XTMINPS,%arg_y)
+	__(set_nargs(2))
+	__(push %ra0)
+	__(jmp _SPksignalerr)
+9:	__(lea (%esp,%nargs),%esp)
+	__(movl rcontext(tcr.save0),%arg_z) /* recover original */
+	__(movl $0,rcontext(tcr.save0))
+	__(movl $XNOSPREAD,%arg_y)
+	__(set_nargs(2))
+	__(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(spreadargz)
+
+
+/* Caller built its own frame when it was entered.  If all outgoing args  */
+/* are in registers, we can discard that frame; otherwise, we copy outgoing  */
+/* relative to it and restore %rbp/%ra0   */
+_spentry(tfuncallgen)
+	__(cmpl $nargregs*node_size,%nargs)
+	__(jbe 9f)
+	__(lea -nargregs*node_size(%esp,%nargs),%imm0)
+	__(movl %temp0,rcontext(tcr.save0))
+	__(movd %nargs,%mm0)
+	__(xorl %temp1,%temp1)
+	/* We can use %ra0 as a temporary here, since the real return address */
+	/* is on the stack   */
+0:	__(movl -node_size(%imm0),%ra0)
+	__(movl %ra0,-node_size(%ebp,%temp1))
+	__(subl $node_size,%imm0)
+	__(subl $node_size,%temp1)
+	__(cmpl %imm0,%esp)
+	__(jne 0b)
+	__(lea (%ebp,%temp1),%esp)
+	__(movl 4(%ebp),%ra0)
+	__(movl (%ebp),%ebp)
+        __(pushl %ra0)
+	__(movd %mm0,%nargs)
+	__(movl rcontext(tcr.save0),%temp0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(do_funcall())
+        /* All args in regs; exactly the same as the tfuncallvsp case   */
+9:		
+	__(leave)
+	__(do_funcall())
+
+_endsubp(tfuncallgen)
+
+/* Some args were pushed; move them down in the frame   */
+_spentry(tfuncallslide)
+	__(lea -nargregs*node_size(%esp,%nargs),%imm0)
+	__(movd %nargs,%mm0)
+	__(xorl %temp1,%temp1)
+	__(movl %temp0,rcontext(tcr.save0))
+0:	__(movl -node_size(%imm0),%temp0)
+	__(movl %temp0,-node_size(%ebp,%temp1))
+	__(subl $node_size,%imm0)
+	__(subl $node_size,%temp1)
+	__(cmpl %imm0,%esp)
+	__(jne 0b)
+	__(lea (%ebp,%temp1),%esp)
+	__(push 4(%ebp))	/* return address */
+	__(movl (%ebp),%ebp)
+	__(movd %mm0,%nargs)
+	__(movl rcontext(tcr.save0),%temp0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(do_funcall())
+_endsubp(tfuncallslide)
+
+/* No args were pushed; recover saved context & do funcall 	  */
+_spentry(tfuncallvsp)
+	__(leave)
+	__(do_funcall())
+_endsubp(tfuncallvsp)
+
+_spentry(tcallsymgen)
+	__(cmpl $nargregs*node_size,%nargs)
+	__(jbe 9f)
+	__(lea -nargregs*node_size(%esp,%nargs),%imm0)
+	__(movd %nargs,%mm0)
+	__(movl %temp0,rcontext(tcr.save0))
+	__(xorl %temp1,%temp1)	/* aka nargs */
+0:	__(movl -node_size(%imm0),%temp0)
+	__(movl %temp0,-node_size(%ebp,%temp1))
+	__(subl $node_size,%imm0)
+	__(subl $node_size,%temp1)
+	__(cmpl %imm0,%esp)
+	__(jne 0b)
+	__(lea (%ebp,%temp1),%esp)
+	__(movl 4(%ebp),%temp0)
+	__(movl (%ebp),%ebp)
+	__(push %temp0)
+	__(movl rcontext(tcr.save0),%temp0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(movd %mm0,%nargs)
+	__(jump_fname())
+/* All args in regs; exactly the same as the tcallsymvsp case. */
+9:
+	__(leave)
+	__(jump_fname())
+_endsubp(tcallsymgen)
+
+_spentry(tcallsymslide)
+	__(movl %ebp,%imm0)
+	__(subl %nargs,%imm0)
+	__(addl $nargregs*node_size,%imm0)	/* new tos */
+	__(push %imm0)
+	__(push %arg_y)
+	__(push %arg_z)
+	__(push %nargs)
+	__(lea (4-nargregs)*node_size(%esp,%nargs),%arg_y) /* src ptr */
+	__(movl %ebp,%imm0) /* dst ptr */
+	__(subl $fixnumone*nargregs,%nargs)
+	__(jmp 1f)
+0:	__(subl $node_size,%arg_y)
+	__(movl (%arg_y),%arg_z)
+	__(subl $node_size,%imm0)
+	__(movl %arg_z,(%imm0))
+1:	__(subl $fixnumone,%nargs)
+	__(jge 0b)
+	__(pop %nargs)
+	__(pop %arg_z)
+	__(pop %arg_y)
+	__(pop %esp)
+	__(push node_size(%ebp))
+	__(movl 0(%ebp),%ebp)
+	__(jump_fname)
+_endsubp(tcallsymslide)
+
+_spentry(tcallsymvsp)
+	__(leave)
+	__(jump_fname())
+_endsubp(tcallsymvsp)
+
+_spentry(tcallnfngen)
+	__(cmpl $nargregs*node_size,%nargs)
+	__(jbe 9f)
+	__(lea -nargregs*node_size(%esp,%nargs),%imm0)
+	__(movd %nargs,%mm0)	/* stash nargs aka temp1 */
+	__(xorl %temp1,%temp1)
+	__(movl %temp0,rcontext(tcr.save0))
+	/* It's OK to use %ra0 (%temp0) as an temp here, since the */
+	/* real return address is on the stack. */
+0:	__(movl -node_size(%imm0),%ra0)
+	__(movl %ra0,-node_size(%ebp,%temp1))
+	__(subl $node_size,%imm0)
+	__(subl $node_size,%temp1)
+	__(cmpl %imm0,%esp)
+	__(jne 0b)
+	__(movl rcontext(tcr.save0),%fn)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(lea (%ebp,%temp1),%esp)
+	__(movl lisp_frame.savera0(%ebp),%ra0)
+	__(movl lisp_frame.backlink(%ebp),%ebp)
+	__(push %ra0)
+	__(movd %mm0,%nargs)
+	__(jmp *%fn)
+9:	/* All args in regs; exactly the same as the tcallnfnvsp case */
+	__(movl %temp0,%fn)
+	__(leave)
+	__(jmp *%fn)
+_endsubp(tcallnfngen)
+
+_spentry(tcallnfnslide)
+	__(lea -nargregs*node_size(%esp,%nargs),%imm0)
+	__(movd %nargs,%mm0)	/* save nargs aka temp1 */
+	__(xorl %temp1,%temp1)
+	__(movl %temp0,rcontext(tcr.save0))
+	/* We can use %ra0 as a temporary here, since the real return address */
+	/* is on the stack   */
+0:	__(movl -node_size(%imm0),%ra0)
+	__(movl %ra0,-node_size(%ebp,%temp1))
+	__(subl $node_size,%imm0)
+	__(subl $node_size,%temp1)
+	__(cmpl %imm0,%esp)
+	__(jne 0b)
+	__(movl rcontext(tcr.save0),%fn)
+	__(lea (%ebp,%temp1),%esp)
+	__(movl lisp_frame.savera0(%ebp),%ra0)
+	__(movl lisp_frame.backlink(%ebp),%ebp)
+        __(push %ra0)
+	__(movapd %fpzero,rcontext(tcr.save0))
+	__(movd %mm0,%nargs)
+	__(jmp *%fn)
+_endsubp(tcallnfnslide)
+
+_spentry(tcallnfnvsp)
+	__(mov %temp0,%fn)
+	__(leave)
+	__(jmp *%fn)
+_endsubp(tcallnfnvsp)
+
+/* Make a "raw" area on the foreign stack, stack-cons a macptr to point */
+/* to it, and return the macptr.  Size (in bytes, boxed) is in arg_z */
+/* on entry; macptr in arg_z on exit. */
+_spentry(makestackblock)
+        __(check_cstack_alignment())
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
+	__(cmpl $tstack_alloc_limit,%imm0)
+	__(jae 1f)
+        __ifdef([WINDOWS])
+         __(windows_cstack_probe(%imm0,%arg_z))
+        __endif
+	__(movd rcontext(tcr.foreign_sp),%mm0)
+	__(subl %imm0,rcontext(tcr.foreign_sp))
+	__(movl rcontext(tcr.foreign_sp),%arg_z)
+	__(movd %mm0,(%arg_z))
+	__(movl %ebp,csp_frame.save_ebp(%arg_z))
+	__(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
+	__(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
+	__(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
+	__(movl %imm0,macptr.address(%arg_z))
+	__(movss %fpzero,macptr.domain(%arg_z))
+	__(movss %fpzero,macptr.type(%arg_z))
+	__(ret)
+1:	__(movd rcontext(tcr.foreign_sp),%mm0)
+	__(subl $dnode_size,rcontext(tcr.foreign_sp))
+	__(movl rcontext(tcr.foreign_sp),%imm0)
+	__(movd %mm0,(%imm0))
+	__(movl %ebp,csp_frame.save_ebp(%imm0))
+	__(set_nargs(1))
+	__(movl $nrs.new_gcable_ptr,%fname)
+	__(jump_fname())
+_endsubp(makestackblock)
+
+_spentry(makestackblock0)
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
+	__(cmpl $tstack_alloc_limit,%imm0)
+	__(jae 9f)
+        __ifdef([WINDOWS])
+         __(windows_cstack_probe(%imm0,%temp0))
+        __endif
+        __(movl rcontext(tcr.foreign_sp),%temp0)
+        __(subl %imm0,rcontext(tcr.foreign_sp))
+        __(movl rcontext(tcr.foreign_sp),%arg_z)
+	__(movl %temp0,(%arg_z))
+	__(movl %ebp,csp_frame.save_ebp(%arg_z))
+	__(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
+	__(movl $macptr_header,tsp_frame.fixed_overhead(%arg_z))
+	__(addl $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
+	__(movl %imm0,macptr.address(%arg_z))
+	__(movss %fpzero,macptr.domain(%arg_z))
+	__(movss %fpzero,macptr.type(%arg_z))
+	__(jmp 2f)
+1:	__(movsd %fpzero,(%imm0))
+	__(addl $dnode_size,%imm0)
+2:	__(cmpl %imm0,%temp0)
+	__(jne 1b)
+	__(repret)
+9:	__(movd rcontext(tcr.foreign_sp),%mm0)
+        __(subl $dnode_size,rcontext(tcr.foreign_sp))
+        __(movl rcontext(tcr.foreign_sp),%imm0)
+	__(movd %mm0,(%imm0))
+	__(movl %ebp,csp_frame.save_ebp(%imm0))
+	__(set_nargs(1))
+	__(movl $nrs.new_gcable_ptr,%fname)
+	__(jump_fname())
+_endsubp(makestackblock0)
+
+_spentry(makestacklist)
+	__(test %arg_y,%arg_y)
+        __(js 9f)
+	__(movl %arg_y,%imm0)
+        __(testb $fixnummask,%imm0_b)
+        __(jne 9f)
+	__(addl %imm0,%imm0)
+	__(rcmpl(%imm0,$tstack_alloc_limit))
+	__(movl $nil_value,%temp1) 
+	__(jae 2f)
+	__(addl $tsp_frame.fixed_overhead,%imm0)
+	__(TSP_Alloc_Var(%imm0,%temp0))
+	__(addl $fulltag_cons,%temp0)
+	__(jmp 1f)
+0:	__(_rplaca(%temp0,%arg_z))
+	__(_rplacd(%temp0,%temp1))
+	__(movl %temp0,%temp1)
+	__(addl $cons.size,%temp0)
+1:	__(subl $fixnumone,%arg_y)
+	__(jge 0b)
+	__(movl %temp1,%arg_z)
+	__(ret)
+2:	__(TSP_Alloc_Fixed(0,%imm0))
+	__(jmp 4f)
+3:	__(Cons(%arg_z,%temp1,%temp1))
+4:	__(subl $fixnumone,%arg_y)				
+	__(jge 3b)
+	__(movl %temp1,%arg_z)
+	__(ret)
+9:      __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte))
+_endsubp(makestacklist)
+
+/* subtype (boxed) vpushed before initial values. (Had better be a */
+/* node header subtag.)  Nargs set to count of things vpushed. */
+_spentry(stkgvector)
+	__(movl -fixnumone(%esp,%nargs),%imm0)	/* boxed subtag */
+	__(shrl $fixnumshift,%imm0)
+	__(leal -fixnumone(%nargs),%arg_z)
+	__(movl %arg_z,%arg_y)
+	__(shll $num_subtag_bits-fixnumshift,%arg_z)
+	__(orl %arg_z,%imm0)	/* imm0 = header, %arg_y = unaligned size */
+	__(movd %imm0,%mm0)
+	__(dnode_align(%arg_y,(tsp_frame.fixed_overhead+node_size),%imm0))
+	__(TSP_Alloc_Var(%imm0,%arg_z))
+	__(movd %mm0,(%arg_z))
+	__(addl $fulltag_misc,%arg_z)
+	__(lea -node_size(%nargs),%imm0)
+	__(jmp 2f)
+1:	__(pop misc_data_offset(%arg_z,%imm0))
+2:	__(subl $node_size,%imm0)
+	__(jge 1b)
+	__(addl $node_size,%esp)
+	__(jmp *%ra0)
+_endsubp(stkgvector)
+
+/* Allocate a fulltag-misc object. */
+/* arg_y = boxed element count, arg_z = subtag (boxed, of course) */
+_spentry(misc_alloc)
+	__(testl $~(((1<<24)-1)<<fixnumshift),%arg_y)
+	__(jne local_label(misc_alloc_not_u24))
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(mov %arg_y,%temp0)
+	__(shl $num_subtag_bits-fixnumshift,%temp0)
+	__(or %temp0,%imm0)	/* %imm0 now = header */
+	__(movd %imm0,%mm0)	/* Misc_Alloc wants header in %mm0 */
+	__(andb $fulltagmask,%imm0_b)
+	__(cmpb $fulltag_nodeheader,%imm0_b)
+	__(je local_label(misc_alloc_32))
+	__(movd %mm0,%imm0)
+	__(cmpb $max_32_bit_ivector_subtag,%imm0_b)
+	__(jbe local_label(misc_alloc_32))
+	__(cmpb $max_8_bit_ivector_subtag,%imm0_b)
+	__(jbe local_label(misc_alloc_8))
+	__(cmpb $max_16_bit_ivector_subtag,%imm0_b)
+	__(jbe local_label(misc_alloc_16))
+	__(cmpb $subtag_double_float_vector,%imm0_b)
+	__(jne local_label(misc_alloc_1))
+	/* double-float vector case */
+	__(imul $2,%arg_y,%imm0)
+	__(jmp local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_1):
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(addl $7,%imm0)
+	__(shrl $3,%imm0)
+	__(jmp local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_8):
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(jmp local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_16):
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(shl $1,%imm0)
+	__(jmp local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_32):
+	__(movl %arg_y,%imm0)
+local_label(misc_alloc_alloc_vector):
+	__(dnode_align(%imm0,node_size,%imm0))
+	__(Misc_Alloc(%arg_z))
+	__(ret)
+local_label(misc_alloc_not_u24):
+	__(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_24))
+_endsubp(misc_alloc)
+
+/* N.B. arg count word in %imm0, not %nargs */
+/* no %whole_reg;  it's in rcontext(tcr.save0) */
+/* %arg_reg is %temp1, key vector in %arg_y */ 
+_startfn(C(destbind1))
+	__(movl %ra0,rcontext(tcr.save1))
+	/* Save entry %esp in case of error   */
+	__(movd %esp,%mm0)
+	/* Save arg count word */
+	__(movd %imm0,%mm1)
+	/* Extract required arg count.   */
+        __(testb %imm0_b,%imm0_b)
+	__(je local_label(opt))		/* skip if no required args   */
+	__(movzbl %imm0_b,%imm0)
+local_label(req_loop):	
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(toofew))
+	__(movb $fulltagmask,%imm0_bh)
+	__(andb %arg_reg_b,%imm0_bh)
+	__(cmpb $fulltag_cons,%imm0_bh)
+	__(jne local_label(badlist))
+	__(subb $1,%imm0_b)
+	__(pushl cons.car(%arg_reg))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(jne local_label(req_loop))
+	__(movd %mm1,%imm0)
+local_label(opt):
+        __(movb %imm0_bh,%imm0_b)
+	__(testb %imm0_b,%imm0_b)
+	__(je local_label(rest_keys))
+	__(btl $initopt_bit,%imm0)
+	__(jc local_label(opt_supp))
+	/* 'simple' &optionals:	 no supplied-p, default to nil.   */
+local_label(simple_opt_loop):
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(default_simple_opt))
+	__(movb $fulltagmask,%imm0_bh)
+	__(andb %arg_reg_b,%imm0_bh)
+	__(cmpb $fulltag_cons,%imm0_bh)
+	__(jne local_label(badlist))
+	__(subb $1,%imm0_b)
+	__(pushl cons.car(%arg_reg))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(jne local_label(simple_opt_loop))
+	__(jmp local_label(rest_keys))
+local_label(default_simple_opt):
+	__(subb $1,%imm0_b)
+	__(pushl $nil_value)
+	__(jne local_label(default_simple_opt))
+	__(jmp local_label(rest_keys))
+local_label(opt_supp):
+	__(movb $fulltagmask,%imm0_bh)
+	__(andb %arg_reg_b,%imm0_bh)
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(default_hard_opt))
+	__(cmpb $fulltag_cons,%imm0_bh)
+	__(jne local_label(badlist))
+	__(subb $1,%imm0_b)
+	__(pushl cons.car(%arg_reg))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(push $t_value)
+	__(jne local_label(opt_supp))
+	__(jmp local_label(rest_keys))
+local_label(default_hard_opt):
+	__(subb $1,%imm0_b)
+	__(push $nil_value)
+	__(push $nil_value)
+	__(jne local_label(default_hard_opt))
+local_label(rest_keys):	
+	__(btl $restp_bit,%imm0)
+	__(jc local_label(have_rest))
+	__(btl $keyp_bit,%imm0)
+	__(jc local_label(have_keys))
+	__(compare_reg_to_nil(%arg_reg))
+	__(jne local_label(toomany))
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(jmp *%ra0)
+local_label(have_rest):
+	__(pushl %arg_reg)
+	__(btl $keyp_bit,%imm0)
+	__(jc local_label(have_keys))
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(jmp *%ra0)
+	/* Ensure that arg_reg contains a proper,even-length list.  */
+	/* Insist that its length is <= 512 (as a cheap circularity check.)   */
+local_label(have_keys):
+	__(movb $255,%imm0_b)
+	__(push %arg_reg)
+	__(push %arg_z)
+	__(xorl %arg_z,%arg_z)
+local_label(count_keys_loop):
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(counted_keys))
+	__(subb $1,%imm0_b)
+	__(jb local_label(toomany))
+	__(movb $fulltagmask,%arg_z_bh)
+	__(andb %arg_reg_b,%arg_z_bh)
+ 	__(cmpb $fulltag_cons,%arg_z_bh)
+	__(jne local_label(badlist))
+	__(_cdr(%arg_reg,%arg_reg))
+        __(compare_reg_to_nil(%arg_reg))
+        __(je local_label(badlist))
+	__(movb $fulltagmask,%arg_z_bh)
+	__(andb %arg_reg_b,%arg_z_bh)
+	__(cmpb $fulltag_cons,%arg_z_bh)
+	__(jne local_label(badlist))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(jmp local_label(count_keys_loop))
+local_label(counted_keys):		
+	/* We've got a proper, even-length list of key/value pairs in  */
+	/* arg_reg. For each keyword var in the lambda-list, push a pair  */
+	/* of NILs on the vstack.   */
+	__(pop %arg_z)
+	__(pop %arg_reg)
+	__(movd %mm1,%imm0)
+	__(shrl $16,%imm0)
+	__(movzbl %imm0_b,%imm0)
+	__(movl %esp,rcontext(tcr.unboxed0))	/* 0th value/supplied-p pair */
+	__(jmp local_label(push_pair_test))
+local_label(push_pair_loop):
+	__(push $nil_value)
+	__(push $nil_value)
+local_label(push_pair_test):	
+	__(subb $1,%imm0_b)
+	__(jge local_label(push_pair_loop))
+	__(push %temp0)	/* keyword */
+	__(push %arg_z) /* value */
+	__(vector_length(%arg_y,%imm0))
+	__(push %arg_reg)
+	__(push %imm0)	/* keyword vector length */
+	__(movd %mm1,%imm0)
+	__(movl $0,rcontext(tcr.unboxed1)) /* count of unknown keywords seen */
+local_label(match_keys_loop):
+	__(movl 4(%esp),%arg_reg)
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(matched_keys))
+	__(_car(%arg_reg,%temp0))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(_car(%arg_reg,%arg_z))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(movl %arg_reg,4(%esp))
+	__(xorl %temp1,%temp1)
+	__(jmp local_label(match_test))
+local_label(match_loop):
+	__(cmpl misc_data_offset(%arg_y,%temp1),%temp0)
+	__(je local_label(matched))
+	__(addl $node_size,%temp1)
+local_label(match_test):
+	__(cmpl %temp1,(%esp))	/* compare index, keyword vector length */
+	__(jne local_label(match_loop))
+	/* No match.  Note unknown keyword, check for :allow-other-keys   */
+	__(addl $1,rcontext(tcr.unboxed1))
+	__(cmpl $nrs.kallowotherkeys,%temp0)
+	__(jne local_label(match_keys_loop))
+	__(subl $1,rcontext(tcr.unboxed1))
+	__(btsl $seen_aok_bit,%imm0)
+	__(jc local_label(match_keys_loop))
+	/* First time we've seen :allow-other-keys.  Maybe set aok_bit.   */
+	__(compare_reg_to_nil(%arg_z))
+	__(je local_label(match_keys_loop))
+	__(btsl $aok_bit,%imm0)
+	__(jmp local_label(match_keys_loop))
+	/* Got a match.  Worry about :allow-other-keys here, too.   */
+local_label(matched):
+	__(negl %temp1)
+	__(shll $1,%temp1)
+	__(addl rcontext(tcr.unboxed0),%temp1)
+	__(cmpl $nil_value,-node_size*2(%temp1))
+	__(jne local_label(match_keys_loop))
+	__(movl %arg_z,-node_size(%temp1))
+	__(movl $t_value,-node_size*2(%temp1))
+	__(cmpl $nrs.kallowotherkeys,%temp0)
+	__(jne local_label(match_keys_loop))
+	__(btsl $seen_aok_bit,%imm0)
+	__(jnc local_label(match_keys_loop))
+	__(compare_reg_to_nil(%arg_z))
+	__(je local_label(match_keys_loop))
+	__(btsl $aok_bit,%imm0)
+	__(jmp local_label(match_keys_loop))
+local_label(matched_keys):	
+	__(cmpl $0,rcontext(tcr.unboxed1))	/* any unknown keys seen? */
+	__(je local_label(keys_ok))
+	__(btl $aok_bit,%imm0)
+	__(jnc local_label(badkeys))
+local_label(keys_ok):
+	__(addl $(3*node_size),%esp)
+	__(pop %ra0)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(jmp *%ra0)
+	/* Some unrecognized keywords.  Complain generically about   */
+	/* invalid keywords.   */
+local_label(badkeys):
+	__(movl $XBADKEYS,%arg_y)
+	__(jmp local_label(destructure_error))
+local_label(toomany):
+	__(movl $XCALLTOOMANY,%arg_y)
+	__(jmp local_label(destructure_error))
+local_label(toofew):
+	__(movl $XCALLTOOFEW,%arg_y)
+	__(jmp local_label(destructure_error))
+local_label(badlist):
+	__(movl $XCALLNOMATCH,%arg_y)
+local_label(destructure_error):
+	__(movd %mm0,%esp)		/* undo everything done to the stack */
+	__(movl rcontext(tcr.save0),%arg_z)	/* %whole_reg */
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(set_nargs(2))
+	__(push %ra0)
+	__(jmp _SPksignalerr)
+_endfn(C(destbind1))
+
+_spentry(macro_bind)
+	__(movl %arg_reg,rcontext(tcr.save0))	/* %whole_reg */
+	__(extract_fulltag(%arg_reg,%imm0))
+	__(cmpb $fulltag_cons,%imm0_b)
+	__(jne 1f)
+	__(_cdr(%arg_reg,%arg_reg))
+	__(jmp C(destbind1))
+1:	__(movl $XCALLNOMATCH,%arg_y)
+	__(movl rcontext(tcr.save0),%arg_z)
+	__(movss %fpzero,rcontext(tcr.save0))
+	__(set_nargs(2))
+        __(push %ra0)        
+	__(jmp _SPksignalerr)
+
+_endsubp(macro_bind)
+
+_spentry(destructuring_bind)
+	__(movl %arg_reg,rcontext(tcr.save0))	/* %whole_reg */
+	__(jmp C(destbind1))
+_endsubp(destructuring_bind)
+
+_spentry(destructuring_bind_inner)
+	__(movl %arg_z,rcontext(tcr.save0))	/* %whole_reg */
+	__(jmp C(destbind1))
+_endsubp(destructuring_bind_inner)
+
+_spentry(vpopargregs)
+	__(hlt)
+_endsubp(vpopargregs)
+
+/* If arg_z is an integer, return in imm0 something whose sign  */
+/* is the same as arg_z's.  If not an integer, error.   */
+_spentry(integer_sign)
+	__(mov %arg_z,%imm0)
+	__(testb $tagmask,%arg_z_b)
+	__(je 8f)
+	__(extract_typecode(%arg_z,%imm0))
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne 9f)
+	__(getvheader(%arg_z,%imm0))
+	__(shr $num_subtag_bits,%imm0)
+	__(movl misc_data_offset-4(%arg_z,%imm0,4),%imm0)
+8:	__(repret)
+9:	__(uuo_error_reg_not_type(Rarg_z,error_object_not_integer))
+_endsubp(integer_sign)
+
+/* "slide" nargs worth of values up the stack.  imm0 contains */
+/* the difference between the current stack pointer and the target. */
+_spentry(mvslide)
+	__(movd %nargs,%mm0)
+	__(lea (%esp,%nargs),%arg_y)
+	__(lea (%arg_y,%imm0),%imm0)
+	__(test %nargs,%nargs)
+	__(je 2f)
+1:
+	__(subl $node_size,%arg_y)
+	__(movl (%arg_y),%arg_z)
+	__(subl $node_size,%imm0)
+	__(movl %arg_z,(%imm0))
+	__(subl $node_size,%nargs)
+	__(jne 1b)
+2:	__(movl %imm0,%esp)
+	__(movd %mm0,%nargs)
+	__(jmp *%ra0)
+_endsubp(mvslide)
+
+_spentry(save_values)
+	__(movd rcontext(tcr.save_tsp),%mm1)
+/* common exit: nargs = values in this set, mm1 = ptr to tsp before call to save_values   */
+local_label(save_values_to_tsp):
+	__(movl %ra0,rcontext(tcr.save0))
+	__(movl rcontext(tcr.save_tsp),%temp0)
+	__(dnode_align(%nargs,tsp_frame.fixed_overhead+(2*node_size),%imm0)) /* count, link   */
+	__(TSP_Alloc_Var(%imm0,%arg_z))
+	__(movl rcontext(tcr.save_tsp),%imm0)
+	__(movd %mm1,(%imm0))
+	__(movl %nargs,(%arg_z))
+	__(movl %temp0,node_size(%arg_z))
+	__(leal 2*node_size(%arg_z,%nargs),%arg_y)
+	__(leal (%esp,%nargs),%imm0)
+	__(cmpl %imm0,%esp)
+	__(jmp 2f)
+1:	__(subl $node_size,%imm0)
+	__(movl (%imm0),%arg_z)
+	__(subl $node_size,%arg_y)
+	__(cmpl %imm0,%esp)
+	__(movl %arg_z,(%arg_y))
+2:	__(jne 1b)
+	__(addl %nargs,%esp)
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movl $0,rcontext(tcr.save0))
+	__(jmp *%ra0)
+_endsubp(save_values)
+
+/* Add the multiple values that are on top of the vstack to the set  */
+/* saved in the top tsp frame, popping them off of the vstack in the  */
+/* process.  It is an error (a bad one) if the TSP contains something  */
+/* other than a previously saved set of multiple-values.  */
+/* Since adding to the TSP may cause a new TSP segment to be allocated,  */
+/* each add_values call adds another linked element to the list of  */
+/* values. This makes recover_values harder.   */
+_spentry(add_values)
+	/* do we need to preserve imm0? */
+	__(test %nargs,%nargs)
+	__(movl rcontext(tcr.save_tsp),%imm0)
+	__(movl (%imm0),%imm0)
+	__(movd %imm0,%mm1)	/* for the benefit of save_values_to_tsp */
+	__(jne local_label(save_values_to_tsp))
+	__(jmp *%ra0)
+_endsubp(add_values)
+
+/* push the values in the value set atop the sp, incrementing nargs.  */
+/* Discard the tsp frame; leave values atop the sp.   */
+_spentry(recover_values)
+	__(movl %ra0,rcontext(tcr.save0)) /* temp0 */
+	__(movd %nargs,%mm0)		  /* temp1 */
+	/* First, walk the segments reversing the pointer to previous  */
+	/* segment pointers Can tell the end because that previous  */
+	/* segment pointer is the prev tsp pointer   */
+	__(movl rcontext(tcr.save_tsp),%temp1)
+	__(movl %temp1,%temp0)	/* current segment   */
+	__(movl %temp1,%arg_y)	/* last segment   */
+	__(movl tsp_frame.backlink(%temp1),%arg_z)	/* previous tsp   */
+local_label(walkloop):
+	__(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
+	__(cmpl %imm0,%arg_z)	/* last segment ?   */
+	__(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
+	__(movl %temp0,%arg_y)	/* last segment <- current segment   */
+	__(movl %imm0,%temp0)	/* current segment <- next segment   */
+	__(jne local_label(walkloop))
+
+	__(movl %temp1,%arg_z)
+	__(movd %mm0,%nargs)
+	/* the final segment pointer is now in %arg_y  */
+	/* walk backwards, pushing values on the stack and incrementing %nargs   */
+local_label(pushloop):
+	__(movl tsp_frame.data_offset(%arg_y),%imm0)	/* nargs in segment   */
+	__(test %imm0,%imm0)
+	__(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
+	__(leal (%nargs,%imm0),%nargs)
+	__(jmp 2f)
+1:	__(push -node_size(%temp0))
+	__(subl $node_size,%temp0)
+	__(subl $fixnum_one,%imm0)
+2:	__(jne 1b)
+	__(cmpl %arg_y,%arg_z)
+	__(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
+	__(jne local_label(pushloop))
+	__(movl (%arg_z),%arg_z)
+        __(movl %arg_z,rcontext(tcr.save_tsp))
+        __(movl %arg_z,rcontext(tcr.next_tsp))
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movl $0,rcontext(tcr.save0))
+	__(jmp *%ra0)		
+_endsubp(recover_values)
+
+/* Exactly like recover_values, but it's necessary to reserve an outgoing  */
+/* frame if any values (which will be used as outgoing arguments) will  */
+/* wind up on the stack.  We can assume that %nargs contains 0 (and  */
+/* that no other arguments have been pushed) on entry.   */
+
+_spentry(recover_values_for_mvcall)
+	__(movl %ra0,rcontext(tcr.save0)) /* temp0 */
+	/* First, walk the segments reversing the pointer to previous  */
+	/* segment pointers Can tell the end because that previous  */
+	/* segment pointer is the prev tsp pointer   */
+	__(xorl %nargs,%nargs)
+	__(push %nargs)
+	__(movl rcontext(tcr.save_tsp),%temp1)
+	__(movl %temp1,%temp0)	/* current segment   */
+	__(movl %temp1,%arg_y)	/* last segment   */
+	__(movl tsp_frame.backlink(%temp1),%arg_z)	/* previous tsp   */
+local_label(walkloop_mvcall):
+	__(movl tsp_frame.data_offset(%temp0),%imm0)
+	__(addl %imm0,(%esp))
+	__(movl tsp_frame.fixed_overhead+node_size(%temp0),%imm0)
+	__(cmpl %imm0,%arg_z)	/* last segment ?   */
+	__(movl %arg_y,tsp_frame.fixed_overhead+node_size(%temp0))
+	__(movl %temp0,%arg_y)	/* last segment <- current segment   */
+	__(movl %imm0,%temp0)	/* current segment <- next segment   */
+	__(jne local_label(walkloop_mvcall))
+
+	__(movl %temp1,%arg_z)
+	__(pop %nargs)
+
+	__(cmpl $nargregs*node_size,%nargs)
+	__(jbe local_label(pushloop_mvcall))
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+
+	/* the final segment pointer is now in %arg_y  */
+	/* walk backwards, pushing values on the stack and incrementing %nargs*/
+local_label(pushloop_mvcall):
+	__(movl tsp_frame.data_offset(%arg_y),%imm0)	/* nargs in segment */
+	__(test %imm0,%imm0)
+	__(leal tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
+	__(jmp 2f)
+1:	__(push -node_size(%temp0))
+	__(subl $node_size,%temp0)
+	__(subl $fixnum_one,%imm0)
+2:	__(jne 1b)
+	__(cmpl %arg_y,%arg_z)
+	__(movl tsp_frame.data_offset+node_size(%arg_y),%arg_y)
+	__(jne local_label(pushloop_mvcall))
+	__(movl (%arg_z),%arg_z)
+        __(movl %arg_z,rcontext(tcr.save_tsp))
+        __(movl %arg_z,rcontext(tcr.next_tsp))
+	__(movl rcontext(tcr.save0),%ra0)
+	__(movl $0,rcontext(tcr.save0))
+	__(jmp *%ra0)		
+_endsubp(recover_values_for_mvcall)
+
+_spentry(reset)
+	__(hlt)
+_endsubp(reset)
+
+/* temp0 = element-count, arg_y = subtag, arg_z = initval */
+_spentry(misc_alloc_init)
+	__(push %ebp)
+	__(movl %esp,%ebp)
+	__(push %arg_z)
+	__(movl %arg_y,%arg_z)
+	__(movl %temp0,%arg_y)
+	__(push $local_label(misc_alloc_init_back))
+	__(jmp _SPmisc_alloc)
+__(tra(local_label(misc_alloc_init_back)))
+	__(pop %arg_y)
+	__(leave)
+	__(movl $nrs.init_misc,%fname)
+	__(set_nargs(2))
+	__(jump_fname())
+_endsubp(misc_alloc_init)
+
+/* %temp1 = element-count, %arg_y = subtag, %arg_z = initial-value */        
+_spentry(stack_misc_alloc_init)
+	__(push %ebp)
+        __(movl %esp,%ebp)
+        __(push %arg_z)
+        __(movl %arg_y,%arg_z)
+        __(movl %temp1,%arg_y)
+        __(pushl $local_label(stack_misc_alloc_init_back))
+        __(jmp _SPstack_misc_alloc)
+__(tra(local_label(stack_misc_alloc_init_back)))
+        __(popl %arg_y)
+	__(leave)
+	__(movl $nrs.init_misc,%fname)
+	__(set_nargs(2))
+	__(jump_fname())
+_endsubp(stack_misc_alloc_init)
+
+	.globl C(popj)
+_spentry(popj)
+C(popj):
+	__(leave)
+        __(ret)
+_endsubp(popj)
+
+/* arg_z should be of type (signed-byte 64) */
+/* return unboxed value in mm0 */
+_spentry(gets64)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+        __(unbox_fixnum(%arg_z,%imm0))
+        __(movd %imm0,%mm0)
+        __(jns 8f)
+        /* get sign into upper half of %mm0 */
+        __(pcmpeqd %mm1,%mm1)   /* all ones */
+        __(psllq $32,%mm1)
+        __(por %mm1,%mm0)
+        __(ret)
+1:      __(movb %arg_z_b,%imm0_b)
+        __(andb $tagmask,%imm0_b)
+        __(cmpb $tag_misc,%imm0_b)
+        __(jne 9f)
+        __(movl misc_header_offset(%arg_z),%imm0)
+        __(cmpb $subtag_bignum,%imm0_b)
+        __(jne 9f)
+        __(cmpl $two_digit_bignum_header,%imm0)
+        __(ja 9f)
+        __(movd misc_data_offset(%arg_z),%mm0)
+	__(jne 8f)
+	__(movq misc_data_offset(%arg_z),%mm0)
+8:      __(repret)
+9:      __(uuo_error_reg_not_type(Rarg_z,error_object_not_s64))
+_endsubp(gets64)
+
+/* arg_z should be of type (unsigned-byte 64) */
+/* return unboxed value in mm0 */
+_spentry(getu64)
+	__(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
+	__(testl %arg_z,%imm0)
+	__(movl %arg_z,%imm0)
+	__(jne 1f)
+	__(sarl $fixnumshift,%imm0)
+	__(movd %imm0,%mm0)
+	__(ret)
+1:	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 9f)
+	__(movl misc_header_offset(%arg_z),%imm0)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne 9f)
+	__(cmpl $three_digit_bignum_header,%imm0)
+	__(ja 9f)
+	__(je 3f)
+	__(cmpl $two_digit_bignum_header,%imm0)
+	__(je 2f)
+	/* must be a one digit bignum */
+	__(movl misc_data_offset(%arg_z),%imm0)
+	__(test %imm0,%imm0)
+	__(js 9f)
+	__(movd %imm0,%mm0)
+	__(ret)
+2: 	__(movl misc_data_offset+4(%arg_z),%imm0)
+	__(testl %imm0,%imm0)
+	__(js 9f)
+	__(movq misc_data_offset(%arg_z),%mm0)
+	__(ret)
+3:	__(movl misc_data_offset(%arg_z),%imm0)
+	__(cmpl $0,misc_data_offset+8(%arg_z))
+	__(jne 9f)
+	__(movq misc_data_offset(%arg_z),%mm0)
+	__(repret)
+9:	__(uuo_error_reg_not_type(Rarg_z,error_object_not_u64))
+_endsubp(getu64)
+
+/* Make unsigned integer from value in mm0 */
+_spentry(makeu64)
+	__(movq %mm0,%mm1)
+	__(psrlq $32,%mm0)
+	__(movd %mm0,%imm0)
+	__(test %imm0,%imm0)
+	__(js 3f)
+	__(jnz 2f)
+	__(movd %mm1,%imm0)
+	__(cmpl $target_most_positive_fixnum,%imm0)
+	__(ja 1f)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+1:	/* maybe make a 1 digit bignum */
+	__(test %imm0,%imm0)
+	__(js 2f)
+	__(movl $one_digit_bignum_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
+	__(movd %mm1,misc_data_offset(%arg_z))
+	__(ret)
+	/* make a 2 digit bignum */
+2:	__(movl $two_digit_bignum_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
+	__(movq %mm1,misc_data_offset(%arg_z))
+	__(ret)
+	/* make a 3 digit bignum */
+3:	__(movl $three_digit_bignum_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(3)))
+	__(movq %mm1,misc_data_offset(%arg_z))
+	__(ret)
+_endsubp(makeu64)
+
+/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly */
+/* unbound_marker), arg_y = symbol */
+_spentry(specref)
+	__(movl symbol.binding_index(%arg_z),%imm0)
+	__(cmp rcontext(tcr.tlb_limit),%imm0)
+	__(movl rcontext(tcr.tlb_pointer),%temp1)
+	__(movl %arg_z,%arg_y)
+	__(jae 7f)
+	__(movl (%temp1,%imm0),%arg_z)
+	__(cmpb $no_thread_local_binding_marker,%arg_z_b)
+	__(jne 8f)
+7:	__(movl symbol.vcell(%arg_y),%arg_z)
+8:	__(repret)		
+_endsubp(specref)
+
+/* arg_y = special symbol, arg_z = new value. */
+_spentry(specset)
+	__(movl symbol.binding_index(%arg_y),%imm0)
+	__(cmp rcontext(tcr.tlb_limit),%imm0)
+	__(movl rcontext(tcr.tlb_pointer),%temp1)
+	__(jae 1f)
+	__(movl (%temp1,%imm0),%temp0)
+	__(cmpb $no_thread_local_binding_marker,%temp0_b)
+	__(je 1f)
+	__(movl %arg_z,(%temp1,%imm0))
+	__(ret)
+1:	__(movl %arg_y,%temp0)
+	__(movl $1<<fixnumshift,%arg_y)
+	__(jmp _SPgvset)
+_endsubp(specset)
+
+_spentry(specrefcheck)
+	__(mov %arg_z,%arg_y)
+	__(movl symbol.binding_index(%arg_z),%imm0)
+	__(cmp rcontext(tcr.tlb_limit),%imm0)
+	__(jae 7f)
+	__(movl rcontext(tcr.tlb_pointer),%temp1)
+	__(movl (%temp1,%imm0),%arg_z)
+	__(cmpb $no_thread_local_binding_marker,%arg_z_b)
+	__(cmovel symbol.vcell(%arg_y),%arg_z)
+	__(cmpb $unbound_marker,%arg_z_b)
+	__(je 9f)
+8:	__(repret)
+7:	__(movl symbol.vcell(%arg_y),%arg_z)
+	__(cmpb $unbound_marker,symbol.vcell(%arg_y))
+	__(je 9f)
+	__(repret)
+9:	__(uuo_error_reg_unbound(Rarg_y))
+_endsubp(specrefcheck)
+
+_spentry(restoreintlevel)
+	__(hlt)
+_endsubp(restoreintlevel)
+
+/* Make a lisp integer from the unsigned value in imm0 */
+_spentry(makeu32)
+	__(cmpl $target_most_positive_fixnum,%imm0)
+	__(ja 0f)	/* need to make a bignum */
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+0:	__(movd %imm0,%mm1)
+	__(test %imm0,%imm0)
+	__(js 1f)
+	__(movl $one_digit_bignum_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(1)))
+	__(movd %mm1,misc_data_offset(%arg_z))
+	__(ret)
+1:	__(movl $two_digit_bignum_header,%imm0)
+	__(movd %imm0,%mm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
+	__(movd %mm1,misc_data_offset(%arg_z))
+	__(ret)
+_endsubp(makeu32)
+
+/* arg_z is of type (signed-byte 32) */
+/* return unboxed value in %imm0 */
+_spentry(gets32)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(ret)
+1:	__(movb %arg_z_b,%imm0_b)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 9f)
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne 9f)
+	__(movl misc_header_offset(%arg_z),%imm0)
+	__(cmpl $one_digit_bignum_header,%imm0)
+	__(jne 9f)
+	__(movl misc_data_offset(%arg_z),%imm0)
+	__(ret)
+9:	__(uuo_error_reg_not_type(Rarg_z,error_object_not_signed_byte_32))
+_endsubp(gets32)
+
+/* arg_z is of type (unsigned-byte 32) */
+/* return unboxed value in %imm0 */
+_spentry(getu32)
+	__(movl $~(target_most_positive_fixnum << fixnumshift),%imm0)
+	__(testl %arg_z,%imm0)
+	__(movl %arg_z,%imm0)
+	__(jne 1f)
+	__(sarl $fixnumshift,%imm0)
+	__(ret)
+1:	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 9f)
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne 9f)
+	__(movl misc_header_offset(%arg_z),%imm0)
+	__(cmpl $two_digit_bignum_header,%imm0)
+	__(je 2f)
+	__(cmpl $one_digit_bignum_header,%imm0)
+	__(jne 9f)
+	__(movl misc_data_offset(%arg_z),%imm0)
+	__(ret)
+2:	__(movl misc_data_offset(%arg_z),%imm0)
+	__(cmpl $0,misc_data_offset+4(%arg_z))
+	__(jne 9f)
+	__(ret)
+9:	__(uuo_error_reg_not_type(Rarg_z,error_object_not_unsigned_byte_32))
+_endsubp(getu32)
+
+_spentry(mvpasssym)
+	__(hlt)
+_endsubp(mvpasssym)
+
+/* don't smash arg_z */
+_spentry(unbind)
+	__(push %arg_z)
+	__(movl rcontext(tcr.db_link),%imm0)
+	__(movl rcontext(tcr.tlb_pointer),%arg_z)
+	__(movl binding.sym(%imm0),%temp0)
+	__(movl binding.val(%imm0),%arg_y)
+	__(movl binding.link(%imm0),%imm0)
+	__(movl %arg_y,(%arg_z,%temp0))
+	__(movl %imm0,rcontext(tcr.db_link))
+	__(pop %arg_z)
+	__(ret)
+_endsubp(unbind)
+
+_spentry(unbind_n)
+	__(push %temp1)		/* preserve temp1/nargs */
+	__(push %arg_z)
+	__(xorl %arg_z,%arg_z)
+	__(movl rcontext(tcr.db_link),%temp1)
+	__(movl rcontext(tcr.tlb_pointer),%arg_z)
+1:		
+	__(movl binding.sym(%temp1),%temp0)
+	__(movl binding.val(%temp1),%arg_y)
+	__(movl binding.link(%temp1),%temp1)
+	__(movl %arg_y,(%arg_z,%temp0))
+	__(decl %imm0)
+	__(jne 1b)
+	__(movl %temp1,rcontext(tcr.db_link))
+	__(pop %arg_z)
+	__(pop %temp1)
+	__(ret)	
+_endsubp(unbind_n)
+
+_spentry(unbind_to)
+	__(push %arg_y)
+	__(push %arg_z)
+	__(push %temp0)
+	__(push %temp1)
+	
+	__(movl rcontext(tcr.db_link),%temp0)
+	__(movl rcontext(tcr.tlb_pointer),%arg_z)
+1:
+	__(movl binding.sym(%temp0),%temp1)
+	__(movl binding.val(%temp0),%arg_y)
+	__(movl binding.link(%temp0),%temp0)
+	__(movl %arg_y,(%arg_z,%temp1))
+	__(cmpl %temp0,%imm0)
+	__(jne 1b)
+	__(movl %temp0,rcontext(tcr.db_link))
+
+	__(pop %temp1)
+	__(pop %temp0)
+	__(pop %arg_z)
+	__(pop %arg_y)
+	__(ret)
+_endsubp(unbind_to)
+
+_spentry(bind_interrupt_level_0)
+	__(movl rcontext(tcr.tlb_pointer),%arg_y)
+	__(cmpl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(movl $0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(js 1f)
+0:	__(jmp *%ra0)
+	/* Interrupt level was negative; interrupt may be pending */
+1:	__(check_pending_enabled_interrupt(2f))
+2:	__(jmp *%ra0)
+_endsubp(bind_interrupt_level_0)
+
+/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect  */
+/* of disabling interrupts.)   */
+_spentry(bind_interrupt_level_m1)
+	__(movl rcontext(tcr.tlb_pointer),%arg_y)
+	__(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(jmp *%ra0)
+_endsubp(bind_interrupt_level_m1)
+
+/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0, */
+/* do what _SPbind_interrupt_level_0 does. */
+_spentry(bind_interrupt_level)
+	__(test %arg_z,%arg_z)
+	__(jz _SPbind_interrupt_level_0)
+	__(movl rcontext(tcr.tlb_pointer),%arg_y)
+	__(push INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movl %esp,rcontext(tcr.db_link))
+	__(movl %arg_z,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(jmp *%ra0)
+_endsubp(bind_interrupt_level)
+
+/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to */
+/* non-negative, check for pending interrupts. */
+_spentry(unbind_interrupt_level)
+	__(btl $TCR_FLAG_BIT_PENDING_SUSPEND,rcontext(tcr.flags))
+	__(movl rcontext(tcr.tlb_pointer),%arg_y)
+	__(movl INTERRUPT_LEVEL_BINDING_INDEX(%arg_y),%imm0)
+	__(jc 5f)
+0:	__(test %imm0,%imm0)
+	__(movl rcontext(tcr.db_link),%imm0)
+	__(movl binding.val(%imm0),%temp0)
+	__(movl binding.link(%imm0),%imm0)
+	__(movl %temp0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+	__(movl %imm0,rcontext(tcr.db_link))
+	__(js 3f)
+2:	__(repret)
+3:	__(test %temp0,%temp0)
+	__(js 2b)
+	__(check_pending_enabled_interrupt(4f))
+4:	__(repret)
+5:       /* Missed a suspend request; force suspend now if we're restoring
+          interrupt level to -1 or greater */
+        __(cmpl $-2<<fixnumshift,%imm0)
+        __(jne 0b)
+	__(movl rcontext(tcr.db_link),%temp0)
+	__(movl binding.val(%temp0),%temp0)
+        __(cmpl %imm0,%temp0)
+        __(je 0b)
+        __(movl $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_y))
+        __(suspend_now())
+        __(jmp 0b)
+_endsubp(unbind_interrupt_level)
+
+_spentry(progvrestore)
+	__(movl rcontext(tcr.save_tsp),%imm0)
+	__(movl tsp_frame.backlink(%imm0),%imm0) /* ignore .SPnthrowXXX values frame   */
+	__(movl tsp_frame.data_offset(%imm0),%imm0)
+	__(shrl $fixnumshift,%imm0)
+	__(jne _SPunbind_n)
+	__(repret)
+_endsubp(progvrestore)
+
+/* %arg_z <- %arg_y + %arg_z.  Do the fixnum case - including overflow -  */
+/* inline.  Call out otherwise.   */
+_spentry(builtin_plus)
+	__(movl %arg_y,%imm0)
+	__(orl %arg_z,%imm0)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(addl %arg_y,%arg_z)
+	__(jo C(fix_one_bit_overflow))
+	__(repret)
+1:	__(jump_builtin(_builtin_plus,2))
+_endsubp(builtin_plus)
+
+/* %arg_z <- %arg_y - %arg_z.  Do the fixnum case - including overflow -  */
+/*  inline.  Call out otherwise.   */
+_spentry(builtin_minus)
+	__(movl %arg_y,%imm0)
+	__(orl %arg_z,%imm0)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(xchgl %arg_y,%arg_z)
+	__(subl %arg_y,%arg_z)
+	__(jo C(fix_one_bit_overflow))
+	__(repret)
+1:	__(jump_builtin(_builtin_minus,2))
+_endsubp(builtin_minus)
+
+/* %arg_z -< arg_y * arg_z. */
+/* Do the fixnum case---including overflow---inline.  Call out otherwise. */
+_spentry(builtin_times)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 2f)
+	__(unbox_fixnum(%arg_z,%imm0))
+	/* 32-bit fixnum result in %imm0.  Overflow set if it doesn't fit. */
+	__(imul %arg_y,%imm0)
+	__(jo 1f)
+	__(movl %imm0,%arg_z)
+	__(ret)
+1:	__(unbox_fixnum(%arg_z,%eax))
+	__(mark_as_imm(%edx))
+	__(unbox_fixnum(%arg_y,%edx))
+	__(imul %edx)
+        __(movd %eax,%mm0)
+        __(movd %edx,%mm1)
+        __(mark_as_node(%edx))
+        __(psllq $32,%mm1)
+        __(por %mm1,%mm0)
+        __(jmp _SPmakes64)
+2:	__(jump_builtin(_builtin_times,2))
+_endsubp(builtin_times)
+
+_spentry(builtin_div)
+	__(jump_builtin(_builtin_div,2))
+
+/* %arg_z <- (= %arg_y %arg_z).	  */
+_spentry(builtin_eq)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpl(%arg_z,%arg_y))
+	__(condition_to_boolean(e,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_eq,2))
+_endsubp(builtin_eq)
+
+/* %arg_z <- (/= %arg_y %arg_z).	  */
+_spentry(builtin_ne)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpl(%arg_z,%arg_y))
+	__(condition_to_boolean(ne,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_ne,2))
+_endsubp(builtin_ne)
+
+/* %arg_z <- (> %arg_y %arg_z).	  */
+_spentry(builtin_gt)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpl(%arg_y,%arg_z))
+	__(condition_to_boolean(g,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_gt,2))
+_endsubp(builtin_gt)
+
+/* %arg_z <- (>= %arg_y %arg_z).	  */
+_spentry(builtin_ge)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpl(%arg_y,%arg_z))
+	__(condition_to_boolean(ge,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_ge,2))
+_endsubp(builtin_ge)
+
+/* %arg_z <- (< %arg_y %arg_z).	  */
+_spentry(builtin_lt)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpl(%arg_y,%arg_z))
+	__(condition_to_boolean(l,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_lt,2))
+_endsubp(builtin_lt)
+
+/* %arg_z <- (<= %arg_y %arg_z).   */
+_spentry(builtin_le)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpl(%arg_y,%arg_z))
+	__(condition_to_boolean(le,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_le,2))
+_endsubp(builtin_le)
+
+_spentry(builtin_eql)
+	__(cmpl %arg_y,%arg_z)
+	__(je 1f)
+	/* Not EQ.  Could only possibly be EQL if both are tag-misc  */
+	/* and both have the same subtag. */
+	__(movl %arg_y,%imm0)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 2f)
+	__(movb %arg_z_b,%imm0_bh)
+	__(andb $tagmask,%imm0_bh)
+	__(cmpb %imm0_bh,%imm0_b)
+	__(jne 2f)
+	__(extract_subtag(%arg_y,%imm0_b))
+	__(extract_subtag(%arg_z,%imm0_bh))
+	__(cmpb %imm0_b,%imm0_bh)
+	__(jne 2f)
+	__(jump_builtin(_builtin_eql,2))
+1:	__(movl $t_value,%arg_z)
+	__(ret)
+2:	__(movl $nil_value,%arg_z)
+	__(ret)
+_endsubp(builtin_eql)
+
+_spentry(builtin_length)
+	__(extract_fulltag(%arg_z,%imm0))
+	__(cmpl $tag_list,%imm0)
+	__(jz 2f)
+	__(andl $tagmask,%imm0)
+	__(cmpl $tag_misc,%imm0)
+	__(jnz 8f)
+	__(extract_subtag(%arg_z,%imm0_b))
+	__(rcmpb(%imm0_b,$min_vector_subtag))
+	__(jb 8f)
+	__(je 1f)
+	/* (simple-array * (*)) */
+	__(movl %arg_z,%arg_y)
+	__(vector_length(%arg_y,%arg_z))
+	__(ret)
+1:	/* vector header */
+	__(movl vectorH.logsize(%arg_z),%arg_z)
+	__(ret)
+2:	/* list.  Maybe null, maybe dotted or circular. */
+	__(movl $-fixnumone,%arg_y)
+	__(movl %arg_z,%temp0)	/* fast pointer */
+	__(movl %arg_z,%temp1)  /* slow pointer */
+3:	__(movb %temp0_b,%al)
+	__(andb $fulltagmask,%al)
+	__(addl $fixnumone,%arg_y)
+	__(compare_reg_to_nil(%temp0))
+	__(je 9f)
+	__(cmpb $fulltag_cons,%al)
+	__(jne 8f)
+	__(movb %temp1_b,%ah)
+	__(andb $fulltagmask,%ah)
+	__(_cdr(%temp0,%temp0))
+	__(testl $fixnumone,%arg_y)
+	__(je 3b)
+	__(cmpb $fulltag_cons,%ah)
+	__(jne 8f)
+	__(_cdr(%temp1,%temp1))
+	__(cmpl %temp0,%temp1)
+	__(jne 3b)
+8:
+	__(jump_builtin(_builtin_length,1))
+9:
+	__(movl %arg_y,%arg_z)
+	__(ret)
+_endsubp(builtin_length)
+
+_spentry(builtin_seqtype)
+	__(extract_fulltag(%arg_z,%imm0))
+	__(cmpb $fulltag_cons,%imm0_b)
+	__(jz 1f)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 2f)
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(rcmpb(%imm0_b,$min_vector_subtag))
+	__(jb 2f)
+	__(movl $nil_value,%arg_z)
+	__(ret)
+1:	__(movl $t_value,%arg_z)
+	__(ret)
+2:
+	__(jump_builtin(_builtin_seqtype,1))
+_endsubp(builtin_seqtype)
+
+_spentry(builtin_assq)
+	__(cmpl $nil_value,%arg_z)
+	__(je 5f)
+1:	__(movl %arg_z,%imm0)
+	__(andb $fulltagmask,%imm0_b)
+	__(cmpb $fulltag_cons,%imm0_b)
+	__(jne 2f)
+	__(_car(%arg_z,%temp0))
+	__(_cdr(%arg_z,%arg_z))
+	__(cmpl $nil_value,%temp0)
+	__(je 4f)
+	__(movl %temp0,%imm0)
+	__(andb $fulltagmask,%imm0_b)
+	__(cmpb $fulltag_cons,%imm0_b)
+	__(jne 3f)
+	__(_car(%temp0,%temp1))
+	__(cmpl %temp1,%arg_y)
+	__(jne 4f)
+	__(movl %temp0,%arg_z)
+	__(ret)
+4:	__(cmpl $nil_value,%arg_z)
+5:	__(jnz 1b)
+	__(repret)
+2:	__(uuo_error_reg_not_list(Rarg_z))
+3:	__(uuo_error_reg_not_list(Rtemp0))
+_endsubp(builtin_assq)
+
+_spentry(builtin_memq)
+	__(cmpl $nil_value,%arg_z)
+	__(jmp 3f)
+1:	__(movb $fulltagmask,%imm0_b)
+	__(andb %arg_z_b,%imm0_b)
+	__(cmpb $fulltag_cons,%imm0_b)
+	__(jne 2f)
+	__(_car(%arg_z,%temp1))
+	__(_cdr(%arg_z,%temp0))
+	__(cmpl %temp1,%arg_y)
+	__(jz 4f)
+	__(cmpl $nil_value,%temp0)
+	__(movl %temp0,%arg_z)
+3:	__(jnz 1b)
+4:	__(repret)
+2:	__(uuo_error_reg_not_list(Rarg_z))
+_endsubp(builtin_memq)
+
+logbitp_max_bit = 30
+
+_spentry(builtin_logbitp)
+	/* Call out unless: both args fixnums, arg_y in [0, logbitp_max_bit) */
+	__(movl %arg_z,%imm0)
+	__(orl %arg_y,%imm0)
+	__(testb $fixnummask,%imm0_b)
+	__(jnz 1f)
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(js 1f)	/* bit number negative */
+	__(addb $fixnumshift,%imm0_b)
+	__(cmpl $logbitp_max_bit<<fixnumshift,%arg_y)
+	__(jb 2f)
+	__(movl $logbitp_max_bit-1+fixnumshift,%imm0)
+2:	__(bt %imm0,%arg_z)
+	__(condition_to_boolean(b,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_logbitp,2))
+_endsubp(builtin_logbitp)
+
+_spentry(builtin_logior)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(orl %arg_y,%arg_z)
+	__(ret)
+1:
+	__(jump_builtin(_builtin_logior,2))
+_endsubp(builtin_logior)
+
+_spentry(builtin_logand)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(andl %arg_y,%arg_z)
+	__(ret)
+1:
+	__(jump_builtin(_builtin_logand,2))
+_endsubp(builtin_logand)
+
+_spentry(builtin_negate)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+	__(negl %arg_z)
+	__(jo C(fix_one_bit_overflow))
+	__(repret)
+1:
+	__(jump_builtin(_builtin_negate,1))
+_endsubp(builtin_negate)
+
+_spentry(builtin_logxor)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(xorl %arg_y,%arg_z)
+	__(ret)
+1:
+	__(jump_builtin(_builtin_logxor,2))
+_endsubp(builtin_logxor)
+
+/* temp0 = vector, arg_y = index, arg_z = newval */
+_spentry(aset1)
+	__(extract_typecode(%temp0,%imm0))
+	__(box_fixnum(%imm0,%temp1))
+	__(cmpb $min_vector_subtag,%imm0_b)
+	__(ja _SPsubtag_misc_set)
+	/* push frame... */
+	__(pop %temp1)
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+	__(push %temp0)
+	__(push %temp1)
+	/* and fall through... */
+_endsubp(aset1)
+
+_spentry(builtin_aset1)
+	__(jump_builtin(_builtin_aset1,3))
+_endsubp(builtin_aset1)
+
+_spentry(builtin_ash)
+	__(movl %arg_y,%imm0)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 9f)
+	__(unbox_fixnum(%arg_z,%imm0))
+	/* Z flag set if zero ASH shift count */
+	__(jnz 1f)
+	__(movl %arg_y,%arg_z) /* shift by 0 */
+	__(ret)
+1:	__(jns 3f)
+	__(rcmpl(%imm0,$-31))
+	__(jg 2f)
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(sar $31,%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+2:	/* Right-shift by small fixnum */
+	__(negb %imm0_b)
+	__(movzbl %imm0_b,%ecx)
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(sar %cl,%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+3:	/* Left shift by fixnum.  We can't shift by more than 31 bits, */
+	/* though shifting by 32 is actually easy. */
+	__(rcmpl(%imm0,$32))
+	__(jg 9f)
+	__(jne 4f)
+	/* left-shift by 32 bits exactly */
+	__(unbox_fixnum(%arg_y,%imm0))
+        __(movd %imm0,%mm0)
+        __(psllq $32,%mm0)
+        __(jmp _SPmakes64)
+4:	/* left-shift by 1..31 bits. Safe to move shift count to %cl */
+	__(movd %imm0,%mm1)     /* shift count */
+        __(unbox_fixnum(%arg_y,%imm0))
+        __(movd %imm0,%mm0)
+        __(sarl $31,%imm0)      /* propagate sign */
+        __(movd %imm0,%mm2)
+        __(pshufw $0x4e,%mm2,%mm2) /* swap hi/lo halves */
+        __(por %mm2,%mm0)
+        __(psllq %mm1,%mm0)
+        __(jmp _SPmakes64)
+9:
+	__(jump_builtin(_builtin_ash,2))
+_endsubp(builtin_ash)
+
+_spentry(builtin_aref1)
+	__(extract_typecode(%arg_y,%imm0))
+	__(box_fixnum_no_flags(%imm0,%temp0))
+	__(cmpb $min_vector_subtag,%imm0_b)
+	__(ja _SPsubtag_misc_ref)
+	__(jump_builtin(_builtin_aref1,2))
+_endsubp(builtin_aref1)
+
+/* Maybe check the x87 tag word to see if st(0) is valid and pop it */
+/* if so.  This might allow us to avoid having to have a priori */
+/* knowledge of whether a foreign function returns a floating-point result. */
+/* backlink to saved %esp, below */
+/* arg n-1 */
+/* arg n-2 */
+/* ... */
+/* arg 0 */
+/* space for alignment */
+/* previous %esp */
+
+_spentry(ffcall)
+LocalLabelPrefix[]ffcall:
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(testb $fixnummask,%arg_z_b)
+	__(je 0f)
+	__(movl macptr.address(%arg_z),%imm0)
+0:
+	/* Save lisp registers. */
+	__(push %ebp)
+	__(mov %esp,%ebp)
+        __(push %temp0) 	 	 
+        __(push %temp1) 	 	 
+        __(push %arg_y) 	 	 
+        __(push %arg_z) 	 	 
+        __(push %fn)         
+        __ifdef([WIN32_ES_HACK])
+         __(movl rcontext(tcr.linear),%ebx)
+        __endif
+	__(movl %esp,rcontext(tcr.save_vsp))
+	__(movl %ebp,rcontext(tcr.save_ebp))
+	__(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+	__(movl rcontext(tcr.foreign_sp),%esp)
+	/* preserve state of direction flag */
+	__(pushfl)
+	__(popl rcontext(tcr.save_eflags))
+	__(cld)        
+	__(stmxcsr rcontext(tcr.lisp_mxcsr))
+	__(emms)
+	__(ldmxcsr rcontext(tcr.foreign_mxcsr))
+	__(movl (%esp),%ebp)
+LocalLabelPrefix[]ffcall_setup:
+        __(lea 15(%esp),%ecx)
+        __(andl $-16,%ecx)
+        __(movl %ecx,%esp)
+/*	__(addl $node_size,%esp) */
+        __ifdef([WIN32_ES_HACK])
+         __(push %ds)
+         __(pop %es)
+        __endif
+LocalLabelPrefix[]ffcall_call:
+	__(call *%eax)
+	__ifdef([WIN32_ES_HACK])
+         __(movw tcr.ldt_selector(%ebx),%rcontext_reg)
+        __endif
+LocalLabelPrefix[]ffcall_call_end:
+	__(movl %ebp,%esp)
+	__(movl %esp,rcontext(tcr.foreign_sp))
+        /* The high word of a 64-bit result would be in %edx right now.
+           There doesn't seem to be any other good place to put this,
+           though %edx is often undefined at this point. */
+        __(mov %edx,rcontext(tcr.unboxed1))
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+	__(cmpb $0,C(bogus_fp_exceptions))
+	__(je 0f)
+	__(movl %arg_z,rcontext(tcr.ffi_exception))
+	__(jmp 1f)
+0:
+	__ifdef([SSE2_MATH_LIB])
+	__(stmxcsr rcontext(tcr.ffi_exception))
+	__else
+	__(fnstsw rcontext(tcr.ffi_exception))
+	__(fnclex)
+	__endif
+1:	__(pushl rcontext(tcr.save_eflags))
+	__(popfl)
+	__(movl rcontext(tcr.save_vsp),%esp)
+	__(movl rcontext(tcr.save_ebp),%ebp)
+	__(movl $TCR_STATE_LISP,rcontext(tcr.valence))
+        __(pop %fn) 	 	 
+        __(pop %arg_z) 	 	 
+        __(pop %arg_y) 	 	 
+        __(pop %temp1) 
+       	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
+	__(check_pending_interrupt(%temp0))
+        __(pop %temp0)
+	__(leave)
+	__(ret)
+	/* need to deal with NSExceptions and Objc-2.0 execptions */
+_endsubp(ffcall)
+
+_spentry(ffcall_return_registers)
+	__(hlt)
+_endsubp(ffcall_return_registers)
+
+/* We need to reserve a frame here if (a) nothing else was already pushed
+/* and (b) we push something (e.g., more than 2 args in the lexpr) */
+_spentry(spread_lexprz)
+	new_local_labels()
+	__(movl (%arg_z),%imm0)	/* lexpr count */
+        __(leal node_size(%arg_z,%imm0),%arg_y)
+	__(movd %arg_y,%mm1)
+	__(test %nargs,%nargs) /* anything pushed by caller ? */
+        __(jne 0f)              /* yes, caller has already created frame. */
+        __(cmpl $(nargregs*node_size),%imm0) /* will we push anything ? */
+        __(jbe 0f)
+        __(push $reserved_frame_marker)
+        __(push $reserved_frame_marker)
+0:      __(addl %imm0,%nargs)
+        __(cmpl $(1*node_size),%imm0)
+        __(ja 2f)
+	__(je 1f)
+        /* lexpr count was 0; vpop the args that */
+        /* were pushed by the caller */
+        __(test %nargs,%nargs)
+        __(je local_label(all_args_popped))
+        __(pop %arg_z)
+local_label(maybe_pop_y):
+        __(cmpl $(1*node_size),%nargs)
+        __(je local_label(all_args_popped))
+        __(pop %arg_y)
+local_label(all_args_popped):   
+        /* If all args fit in registers but some were pushed */
+        /* by the caller, discard the reserved frame that the caller */
+        /* pushed.         */
+        __(cmpl %imm0,%nargs)
+        __(je local_label(go))
+        __(cmpl $(nargregs*node_size),%nargs)
+        __(ja local_label(go))
+        __(addl $(2*node_size),%esp)
+local_label(go):
+        __(jmp *%ra0)
+
+	/* lexpr count is two or more: vpush args from the lexpr until */
+	/* we have only two left, then assign them to arg_y and arg_z */
+2:	__(cmpl $(2*node_size),%imm0)
+	__(je local_label(push_loop_end))
+local_label(push_loop):
+	__(lea -1*node_size(%imm0),%imm0)
+	__(push -node_size(%arg_y))
+	__(lea -1*node_size(%arg_y),%arg_y)
+	__(cmpl $(2*node_size),%imm0)
+	__(jne 2b)
+local_label(push_loop_end):
+        __(movl -node_size*2(%arg_y),%arg_z)
+	__(movl -node_size*1(%arg_y),%arg_y)
+        __(jmp *%ra0)
+	/* lexpr count is one: set arg_z from the lexpr, */
+	/* maybe vpop arg_y  */
+1:      __(movl -node_size*1(%arg_y),%arg_z)
+        __(jmp local_label(maybe_pop_y))
+_endsubp(spread_lexprz)
+
+_spentry(callback)
+	__(push %ebp)
+	__(movl %esp,%ebp)
+	/* C scalar args are already on the stack. */
+	/* arg word 0 at 8(%ebp), word 1 at 12(%ebp), etc. */
+
+	/* %eax is passed to us via the callback trampoline.
+	   bits 0-22: callback index
+	   bit 23: flag, set if we need to discard hidden arg on return
+		   (ignored when upper 8 bits are non-zero)
+	   bits 24-31: arg words to discard on return (_stdcall for win32) */
+	
+        /* Reserve some space for results, relative to the
+           current %ebp.  We may need quite a bit of it. */
+        __(subl $20,%esp)
+        __(movl $0,-16(%ebp)) /* No FP result */
+	__(btl $23,%eax)      /* set CF if we need to discard hidden arg */
+	__(pushfl)	      /* and save for later */
+        __(movl %eax,%ecx)    /* extract args-discard count */
+        __(shrl $24,%ecx)
+        __(andl $0x007fffff,%eax) /* callback index */
+        __(movl %ecx,-20(%ebp))
+        /* If the C stack is 16-byte aligned by convention,
+           it should still be, and this'll be a NOP. */
+        __(andl $~15,%esp)
+	/* C NVRs */
+	__(push %edi)
+	__(push %esi)
+	__(push %ebx)
+	__(push %ebp)
+	__(box_fixnum(%eax,%esi))	/* put callback index in arg_y */
+        __(cmpb $0,C(rcontext_readonly))
+        __(jne 0f)
+	__(ref_global(get_tcr,%eax))
+	__(subl $12,%esp)		/* alignment */
+	__(push $1)			/* stack now 16-byte aligned */
+	__(call *%eax)
+	__(addl $16,%esp)		/* discard arg, alignment words */
+	/* linear TCR addr now in %eax */
+	__(movw tcr.ldt_selector(%eax), %rcontext_reg)
+0:      
+
+        /* ebp is 16-byte aligned, and we've pushed 4 words.  Make
+          sure that when we push old foreign_sp, %esp will be 16-byte
+          aligned again */
+        __(subl $8,%esp)
+        __(pushl rcontext(tcr.save_ebp))  /* mark cstack frame's "owner" */
+ 	__(push rcontext(tcr.foreign_sp))
+	__(movl %esp,rcontext(tcr.foreign_sp))
+	__(clr %arg_z)
+	/* arg_y contains callback index */
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+	__(movl rcontext(tcr.save_vsp),%esp)
+	__(movl %ebp,%arg_z)
+	__(movl rcontext(tcr.save_ebp),%ebp)
+	__(movl $TCR_STATE_LISP,rcontext(tcr.valence))
+	__(stmxcsr rcontext(tcr.foreign_mxcsr))
+	__(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
+	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
+	__(movl $nrs.callbacks,%fname)
+        __(check_cstack_alignment())
+	__(push $local_label(back_from_callback))
+	__(set_nargs(2))
+	__(jump_fname())
+__(tra(local_label(back_from_callback)))
+	__(movl %esp,rcontext(tcr.save_vsp))
+	__(movl %ebp,rcontext(tcr.save_ebp))
+	__(movl $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+	__(movl rcontext(tcr.foreign_sp),%esp)
+	__(stmxcsr rcontext(tcr.lisp_mxcsr))
+	__(emms)
+	__(pop rcontext(tcr.foreign_sp))
+        __(addl $12,%esp)       /* discard alignment padding */
+        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
+        __ifdef([WIN32_ES_HACK])
+         __(push %ds)
+         __(pop %es)
+        __endif
+	__(pop %ebp)
+	__(pop %ebx)
+	__(pop %esi)
+	__(pop %edi)
+        __(movl -12(%ebp),%ecx) /* magic value for ObjC bridge */
+        __(cmpb $1,-16(%ebp))
+        __(jae 1f)
+	__(movl -8(%ebp),%eax)
+        __(movl -4(%ebp),%edx)
+        __ifdef([WIN_32])
+	 __(cmpl $0,-20(%ebp))
+         __(jne local_label(winapi_return))
+	__endif
+        /* since we aligned the stack after pushing flags, we're not
+           really sure where %esp is relative to where flags were saved.
+           We do know where the saved flags are relative to %ebp, so use
+           that to establish %esp before the popfl.
+        */
+        __(lea -24(%ebp),%esp)
+	__(popfl)	/* flags from bt way back when */
+	__(jc local_label(discard_first_arg))
+	__(leave)
+	__(ret)
+1:      __(jne 2f)
+        /* single float return in x87 */
+        __(flds -8(%ebp))
+        __ifdef([WIN_32])
+	 __(cmpl $0,-20(%ebp))
+         __(jne local_label(winapi_return))
+        __endif
+        __(leave)
+	__(ret)
+2:      /* double-float return in x87 */
+        __(fldl -8(%ebp))
+        __ifdef([WIN_32])
+	 __(cmpl $0,-20(%ebp))
+         __(jne local_label(winapi_return))
+        __endif
+        __(leave)
+	__(ret)
+        __ifdef([WIN_32])
+local_label(winapi_return):
+	  __(movl -20(%ebp),%ecx)
+	  __(leave)
+         /* %ecx is non-zero and contains count of arg words to pop */
+          __(popl -4(%esp,%ecx,4))
+          __(leal -4(%esp,%ecx,4),%esp)
+          __(ret)
+        __endif
+local_label(discard_first_arg):
+	__(leave)
+	__(ret $4)
+_endsubp(callback)
+
+/* temp0 = array, arg_y = i, arg_z = j. Typecheck everything.
+   We don't know whether the array is alleged to be simple or
+   not, and don't know anythng about the element type.  */
+
+_spentry(aref2)
+        __(testl $fixnummask,%arg_y)
+        __(jne 0f)
+	__(testb $fixnummask,%arg_z_b)
+        __(jne 1f)
+	__(extract_typecode(%temp0,%imm0))
+        __(cmpb $subtag_arrayH,%imm0_b)
+        __(jne 2f)
+        __(cmpl $2<<fixnumshift,arrayH.rank(%temp0))
+        __(jne 2f)
+	__(cmpl arrayH.dim0(%temp0),%arg_y)
+        __(jae 3f)
+	__(movl arrayH.dim0+node_size(%temp0),%imm0)
+        __(cmpl %imm0,%arg_z)
+        __(jae 4f)
+	__(sarl $fixnumshift,%imm0)
+        __(imull %arg_y,%imm0)
+        __(addl %imm0,%arg_z)
+        __(movl %temp0,%arg_y)
+	__(xorl %temp1,%temp1)
+6:      __(addl arrayH.displacement(%arg_y),%arg_z)
+        __(movl arrayH.data_vector(%arg_y),%arg_y)
+        __(extract_subtag(%arg_y,%imm0_b))
+        __(cmpb $subtag_vectorH,%imm0_b)
+        __(ja C(misc_ref_common))
+        __(jmp 6b)
+0:	__(uuo_error_reg_not_fixnum(Rarg_y))
+1:	__(uuo_error_reg_not_fixnum(Rarg_z))
+2:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_2d))
+3:	__(uuo_error_array_bounds(Rarg_y,Rtemp0))
+4:	__(uuo_error_array_bounds(Rarg_z,Rtemp0))
+
+_endsubp(aref2)
+
+/* Like aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = k */
+_spentry(aref3)
+	__(testb $fixnummask,%temp0_b)
+	__(jne 0f)
+	__(testl $fixnummask,%arg_y)
+	__(jne 1f)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 2f)
+	__(extract_typecode(%temp1,%imm0))
+	__(cmpb $subtag_arrayH,%imm0_b)
+	__(jne 3f)
+	__(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
+	__(jne 3f)
+	__(cmpl arrayH.dim0(%temp1),%temp0)
+	__(jae 4f)
+	__(movl arrayH.dim0+node_size(%temp1),%imm0)
+	__(cmpl %imm0,%arg_y)
+	__(jae 5f)
+	__(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_z)
+	__(jae 6f)
+	/* index computation: k + dim2 * (j + dim1 * i) */
+	/* (plus minor fussing for fixnum scaling) */
+	__(sarl $fixnumshift,%imm0)
+	__(imull %imm0,%temp0)
+	__(addl %arg_y,%temp0)
+	__(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
+	__(sarl $fixnumshift,%imm0)
+	__(imull %imm0,%temp0)
+	__(addl %temp0,%arg_z)
+	__(movl %temp1,%arg_y)
+8:	__(addl arrayH.displacement(%arg_y),%arg_z)
+	__(movl arrayH.data_vector(%arg_y),%arg_y)
+	__(extract_subtag(%arg_y,%imm0_b))
+	__(cmpb $subtag_vectorH,%imm0_b)
+	__(ja C(misc_ref_common))
+	__(jmp 8b)
+0:	__(uuo_error_reg_not_fixnum(Rtemp0))
+1:	__(uuo_error_reg_not_fixnum(Rarg_y))
+2:	__(uuo_error_reg_not_fixnum(Rarg_z))
+3:	__(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
+4:	__(uuo_error_array_bounds(Rtemp0,Rtemp1))
+5:	__(uuo_error_array_bounds(Rarg_y,Rtemp1))
+6:	__(uuo_error_array_bounds(Rarg_z,Rtemp1))
+_endsubp(aref3)
+
+/* As with aref2, but temp1 = array, temp0 = i, arg_y = j, arg_z = new_value */
+_spentry(aset2)
+        __(testb $fixnummask,%temp0_b)
+        __(jne 0f)
+	__(testl $fixnummask,%arg_y)
+        __(jne 1f)
+	__(extract_typecode(%temp1,%imm0))
+        __(cmpb $subtag_arrayH,%imm0_b)
+        __(jne 2f)
+        __(cmpl $2<<fixnumshift,arrayH.rank(%temp1))
+        __(jne 2f)
+	__(cmpl arrayH.dim0(%temp1),%temp0)
+        __(jae 3f)
+	__(movl arrayH.dim0+node_size(%temp1),%imm0)
+        __(cmpl %imm0,%arg_y)
+        __(jae 4f)
+	__(sarl $fixnumshift,%imm0)
+        __(imull %temp0,%imm0)
+        __(addl %imm0,%arg_y)
+        __(movl %temp1,%temp0)
+	__(xorl %temp1,%temp1)
+6:      __(addl arrayH.displacement(%temp0),%arg_y)
+        __(movl arrayH.data_vector(%temp0),%temp0)
+        __(extract_subtag(%temp0,%imm0_b))
+        __(cmpb $subtag_vectorH,%imm0_b)
+        __(ja C(misc_set_common))
+        __(jmp 6b)
+0:	__(uuo_error_reg_not_fixnum(Rtemp0))
+1:	__(uuo_error_reg_not_fixnum(Rarg_y))
+2:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_2d))
+3:	__(uuo_error_array_bounds(Rtemp0,Rtemp1))
+4:	__(uuo_error_array_bounds(Rarg_y,Rtemp1))
+_endsubp(aset2)
+
+/* temp1 = array, (%esp) = i, temp0 = j, arg_y = k, arg_z = newval */
+_spentry(aset3)
+	__(testb $fixnummask,(%esp))
+	__(jne 0f)
+	__(testb $fixnummask,%temp0_b)
+	__(jne 1f)
+	__(testl $fixnummask,%arg_y)
+	__(jne 2f)
+	__(extract_typecode(%temp1,%imm0))
+	__(cmpb $subtag_arrayH,%imm0_b)
+	__(jne 3f)
+	__(cmpl $3<<fixnumshift,arrayH.rank(%temp1))
+	__(jne 3f)
+	__(movl arrayH.dim0(%temp1),%imm0)
+	__(cmpl %imm0,(%esp))	/* i on stack */
+	__(jae 4f)
+	__(movl arrayH.dim0+node_size(%temp1),%imm0)
+	__(cmpl %imm0,%temp0)
+	__(jae 5f)
+	__(cmpl arrayH.dim0+(node_size*2)(%temp1),%arg_y)
+	__(jae 6f)
+	/* index computation: k + dim2 * (j + dim1 * i) */
+	/* (plus minor fussing for fixnum scaling) */
+	__(sarl $fixnumshift,%imm0)
+	__(imull (%esp),%imm0)	/* i on stack */
+	__(addl %imm0,%temp0)
+	__(addl $node_size,%esp)
+	__(movl arrayH.dim0+(node_size*2)(%temp1),%imm0)
+	__(sarl $fixnumshift,%imm0)
+	__(imull %imm0,%temp0)
+	__(addl %temp0,%arg_y)
+	__(movl %temp1,%temp0)
+8:	__(addl arrayH.displacement(%temp0),%arg_y)
+	__(movl arrayH.data_vector(%temp0),%temp0)
+	__(extract_subtag(%temp0,%imm0_b))
+	__(cmpb $subtag_vectorH,%imm0_b)
+	__(ja C(misc_set_common))
+	__(jmp 8b)
+0:	__(pop %temp0)	/* supplied i */
+	__(uuo_error_reg_not_fixnum(Rtemp0))
+1:	__(uuo_error_reg_not_fixnum(Rtemp0))
+2:	__(uuo_error_reg_not_fixnum(Rarg_y))
+3:	__(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
+4:	__(pop %imm0)	/* supplied i is on stack */
+	__(uuo_error_array_bounds(Rimm0,Rtemp1))
+5:	__(uuo_error_array_bounds(Rtemp0,Rtemp1))
+6:	__(uuo_error_array_bounds(Rarg_y,Rtemp1))
+_endsubp(aset3)
+
+/* Prepend all but the first seven (6 words of code & other immediate data,
+/* plus inner fn) and last (lfbits) elements of %fn to the "arglist". */
+_spentry(call_closure)
+	new_local_labels()
+	__(vector_length(%fn,%imm0))
+	__(subl $8<<fixnumshift,%imm0)	/* imm0 = inherited arg count */
+	__(lea (%nargs,%imm0),%temp0)
+	__(cmpl $nargregs<<fixnumshift,%temp0)
+	__(jna local_label(regs_only))	/* either: 1 arg, 1 inherited, or */
+					/* no args, 2 inherited */
+	__(pop rcontext(tcr.save0))		/* save return address */
+	__(cmpl $nargregs<<fixnumshift,%nargs)
+	__(jna local_label(no_insert))
+
+/* Some arguments have already been pushed.  Push %imm0's worth */
+/* of NILs, copy those arguments that have already been vpushed from */
+/* the old TOS to the new, then insert all of the inherited args */
+/* and go to the function. */
+
+	__(mov %imm0,%temp0)
+local_label(push_nil_loop):
+	__(push $nil_value)
+	__(sub $fixnumone,%temp0)
+	__(jne local_label(push_nil_loop))
+
+/* Need to use arg regs as temporaries.  Stash them in the spill area. */
+	__(movl %arg_y,rcontext(tcr.save1))
+	__(movl %arg_z,rcontext(tcr.save2))
+
+	__(leal (%esp,%imm0),%temp0)	/* start of already-pushed args */
+	__(leal -nargregs<<fixnumshift(%nargs),%arg_y) /* args pushed */
+	__(movd %imm0,%mm0)	/* save inherited arg count */
+	__(xorl %imm0,%imm0)
+local_label(copy_already_loop):
+	__(movl (%temp0,%imm0),%arg_z)
+	__(movl %arg_z,(%esp,%imm0))
+	__(addl $fixnumone,%imm0)
+	__(cmpl %imm0,%arg_y)
+	__(jne local_label(copy_already_loop))
+
+	__(lea -node_size(%temp0,%imm0),%arg_y)	/* start of args on stack */
+	__(movl $7<<fixnumshift,%temp0)	/* skip code, new fn */
+	__(movd %mm0,%imm0)
+local_label(insert_loop):
+	__(movl misc_data_offset(%fn,%temp0),%arg_z)
+	__(addl $node_size,%temp0)
+	__(addl $fixnumone,%nargs)
+	__(movl %arg_z,(%arg_y))
+	__(subl $node_size,%arg_y)
+	__(subl $fixnumone,%imm0)
+	__(jne local_label(insert_loop))
+
+	/* Recover arg regs, saved earlier */
+	__(movl rcontext(tcr.save1),%arg_y)
+	__(movl rcontext(tcr.save2),%arg_z)
+	__(jmp local_label(go))
+	
+/* Here if no args were pushed by the caller. */
+/* cases: */
+/* no args, more than two inherited args */
+/* a single arg in arg_z, more than one inherited arg */
+/* two args in arg_y and arg_z, some number of inherited args */
+
+/* Therefore, we're always going to have to push something (the sum of */
+/* %nargs and %imm0 will always be greater than $nargregs), and */
+/* we will have to reserve space for a stack frame. */
+/* The 0 args, 2 inherited case and the 1 arg, 1 inherited case get */
+/* handled at local_label(regs_ony). */
+	
+local_label(no_insert):
+	/* Reserve space for a stack frame */
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+	__(lea 7<<fixnumshift(%imm0),%temp0)	/* last inherited arg */
+	__(rcmpl(%nargs,$fixnumone))
+	__(je local_label(set_arg_y))
+	__(jb local_label(set_y_z))
+	/* %nargs = $nargregs (i.e., 2), vpush remaining inherited vars. */
+
+local_label(vpush_remaining):
+	__(movl $7<<fixnumshift,%temp0)
+local_label(vpush_remaining_loop):
+	__(push misc_data_offset(%fn,%temp0))
+	__(add $node_size,%temp0)
+	__(add $fixnumone,%nargs)
+	__(sub $node_size,%imm0)
+	__(jnz local_label(vpush_remaining_loop))
+	__(jmp local_label(go))
+	
+local_label(set_arg_y):
+	/* one arg in arg_z.  set arg_y and vpush remaining inherited args */
+	__(subl $node_size,%temp0)
+	__(movl misc_data_offset(%fn,%temp0),%arg_y)
+	__(addl $fixnumone,%nargs)
+	__(subl $fixnumone,%imm0)
+	__(jmp local_label(vpush_remaining))
+local_label(set_y_z):
+	__(subl $node_size,%temp0)
+	__(movl misc_data_offset(%fn,%temp0),%arg_z)
+	__(addl $fixnumone,%nargs)
+	__(subl $fixnumone,%imm0)
+	__(jmp local_label(set_arg_y))
+
+local_label(go):
+	__(movl misc_data_offset+(6*node_size)(%fn),%fn)
+	__(push rcontext(tcr.save0))	/* restore return addr */
+	__(movapd %fpzero,rcontext(tcr.save0))	/* clear out spill area */
+	__(jmp *%fn)
+local_label(regs_only):
+	__(lea 7<<fixnumshift(%imm0),%temp0)
+	__(test %nargs,%nargs)
+	__(jne local_label(one_arg))
+	/* no args passed, two inherited args */
+	__(movl misc_data_offset-node_size(%fn,%temp0),%arg_z)
+	__(cmpl $node_size,%imm0)
+	__(je local_label(rgo))
+	__(movl misc_data_offset-(node_size*2)(%fn,%temp0),%arg_y)
+local_label(rgo):
+	__(addl %imm0,%nargs)
+	__(jmp *misc_data_offset+(6*node_size)(%fn))
+local_label(one_arg):
+	/* one arg was passed, so there's one inherited arg */
+	__(movl misc_data_offset-node_size(%fn,%temp0),%arg_y)
+	__(jmp local_label(rgo))
+_endsubp(call_closure)
+
+_spentry(poweropen_callbackX)
+	__(hlt)
+_endsubp(poweropen_callbackX)
+
+_spentry(poweropen_ffcallX)
+	__(hlt)
+_endsubp(poweropen_ffcallX)
+
+_spentry(eabi_ff_call)
+	__(hlt)
+_endsubp(eabi_ff_call)
+
+_spentry(eabi_callback)
+	__(hlt)
+_endsubp(eabi_callback)
+
+
+/* Unused, and often not used on PPC either  */
+_spentry(callbuiltin)
+	__(hlt)
+_endsubp(callbuiltin)
+
+_spentry(callbuiltin0)
+	__(hlt)
+_endsubp(callbuiltin0)
+
+_spentry(callbuiltin1)
+	__(hlt)
+_endsubp(callbuiltin1)
+
+_spentry(callbuiltin2)
+	__(hlt)
+_endsubp(callbuiltin2)
+
+_spentry(callbuiltin3)
+	__(hlt)
+_endsubp(callbuiltin3)
+
+_spentry(restorefullcontext)
+	__(hlt)
+_endsubp(restorefullcontext)
+
+_spentry(savecontextvsp)
+	__(hlt)
+_endsubp(savecontextvsp)
+
+_spentry(savecontext0)
+	__(hlt)
+_endsubp(savecontext0)
+
+_spentry(restorecontext)
+	__(hlt)
+_endsubp(restorecontext)
+
+_spentry(stkconsyz)
+	__(hlt)
+_endsubp(stkconsyz)
+
+_spentry(stkvcell0)
+	__(hlt)
+_endsubp(stkvcell0)
+
+_spentry(stkvcellvsp)
+	__(hlt)
+_endsubp(stkvcellvsp)
+
+_spentry(breakpoint)
+        __(hlt)
+_endsubp(breakpoint)
+
+_spentry(unused_6)
+        __(hlt)
+Xspentry_end:
+_endsubp(unused_6)
+        .data
+        .globl C(spentry_start)
+        .globl C(spentry_end)
+C(spentry_start):       .long Xspentry_start
+C(spentry_end):         .long Xspentry_end
+        
Index: /branches/new-random/lisp-kernel/x86-spentry64.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-spentry64.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-spentry64.s	(revision 13309)
@@ -0,0 +1,5184 @@
+/*   Copyright (C) 2005-2009 Clozure Associates and contributors  */
+/*   This file is part of Clozure CL.    */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public  */
+/*   License , known as the LLGPL and distributed with Clozure CL as the  */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these  */
+/*   conflict, the preamble takes precedence.    */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."  */
+
+/*   The LLGPL is also available online at  */
+/*   http://opensource.franz.com/preamble.html  */
+
+
+		
+	include(lisp.s)
+	_beginfile
+	
+        .align 2
+define([_spentry],[ifdef([__func_name],[_endfn],[])
+	.p2align 3
+	_exportfn(_SP$1)
+	.line  __line__
+])
+
+             
+define([_endsubp],[
+	_endfn(_SP$1)
+#  __line__ 
+])
+
+define([jump_builtin],[
+	ref_nrs_value(builtin_functions,%fname)
+	set_nargs($2)
+	vrefr(%fname,%fname,$1)
+	jump_fname()
+])
+
+        
+
+_spentry(bad_funcall)
+Xspentry_start:         
+	.globl C(bad_funcall)	
+__(tra(C(bad_funcall)))
+	__(uuo_error_not_callable)
+_endsubp(bad_funcall)
+	
+/* %arg_z has overflowed by one bit.  Make a bignum with 2 (32-bit) digits.  */
+	
+_spentry(fix_overflow)
+C(fix_one_bit_overflow):	
+	__(movq $two_digit_bignum_header,%imm0)
+	__(Misc_Alloc_Fixed([],aligned_bignum_size(2)))
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(movq $0xe000000000000000,%imm1)
+	__(mov %temp0,%arg_z)
+	__(xorq %imm1,%imm0)
+	__(movq %imm0,misc_data_offset(%arg_z))
+	__(ret)	
+_endsubp(fix_overflow)
+
+
+/* Make a lisp integer (fixnum or two-digit bignum) from the signed  */
+/* 64-bit value in %imm0.   */
+
+_spentry(makes64)
+	__(movq %imm0,%imm1)
+	__(shlq $fixnumshift,%imm1)
+	__(movq %imm1,%arg_z)
+	__(sarq $fixnumshift,%imm1)
+	__(cmpq %imm1,%imm0)
+	__(jz 0f)
+	__(movd %imm0,%mm0)
+	__(movq $two_digit_bignum_header,%imm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(2)))
+	__(movq %mm0,misc_data_offset(%arg_z))
+0:	__(repret)
+_endsubp(makes64)	
+
+        				
+
+/* %imm1:%imm0 constitute a signed integer, almost certainly a bignum.  */
+/* Make a lisp integer out of those 128 bits ..   */
+	
+_startfn(C(makes128))
+	
+        /*  We're likely to have to make a bignum out of the integer in %imm1 and  */
+        /*  %imm0. We'll need to use %imm0 and %imm1 to cons the bignum, and  */
+        /*  will need to do some arithmetic (determining significant bigits)  */
+        /*  on %imm0 and %imm1 in order to know how large that bignum needs to be.  */
+        /*  Cache %imm0 and %imm1 in %mm0 and %mm1.   */
+   
+	__(movd %imm0,%mm0)
+	__(movd %imm1,%mm1)
+	
+        /* If %imm1 is just a sign extension of %imm0, make a 64-bit signed integer.   */
+	
+	__(sarq $63,%imm0) 
+	__(cmpq %imm0,%imm1)
+	__(movd %mm0,%imm0)
+	__(je _SPmakes64)
+	
+        /* Otherwise, if the high 32 bits of %imm1 are a sign-extension of the  */
+        /* low 32 bits of %imm1, make a 3-digit bignum.  If the upper 32 bits  */
+        /* of %imm1 are significant, make a 4 digit bignum   */
+	
+	__(movq %imm1,%imm0)
+	__(shlq $32,%imm0)
+	__(sarq $32,%imm0)
+	__(cmpq %imm0,%imm1)
+	__(jz 3f)
+	__(mov $four_digit_bignum_header,%imm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(4)))
+	__(movq %mm0,misc_data_offset(%arg_z))
+	__(movq %mm1,misc_data_offset+8(%arg_z))
+	__(ret)
+3:	__(mov $three_digit_bignum_header,%imm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(3)))
+	__(movq %mm0,misc_data_offset(%arg_z))
+	__(movd %mm1,misc_data_offset+8(%arg_z))
+	__(ret)
+_endfn
+
+        
+/* %imm1:%imm0 constitute an unsigned integer, almost certainly a bignum.  */
+/* Make a lisp integer out of those 128 bits ..  */
+	
+_startfn(C(makeu128))
+	
+        /* We're likely to have to make a bignum out of the integer in %imm1 and  */
+        /* %imm0. We'll need to use %imm0 and %imm1 to cons the bignum, and  */
+        /* will need to do some arithmetic (determining significant bigits)  */
+        /* on %imm0 and %imm1 in order to know how large that bignum needs to be.  */
+        /* Cache %imm0 and %imm1 in %mm0 and %mm1.   */
+
+        /* If the high word is 0, make an unsigned-byte 64 ... 	  */
+	
+	__(testq %imm1,%imm1)
+	__(jz _SPmakeu64)
+	
+	__(movd %imm0,%mm0)
+	__(movd %imm1,%mm1)
+
+	__(js 5f)		/* Sign bit set in %imm1. Need 5 digits   */
+	__(bsrq %imm1,%imm0)
+	__(rcmpb(%imm0_b,$31))
+	__(jae 4f)		/* Some high bits in %imm1.  Need 4 digits   */
+	__(testl %imm1_l,%imm1_l)
+	__(movd %mm0,%imm0)
+	__(jz _SPmakeu64)
+	
+	/* Need 3 digits   */
+	
+	__(movq $three_digit_bignum_header,%imm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(3)))
+	__(movq %mm0,misc_data_offset(%arg_z))
+	__(movd %mm1,misc_data_offset+8(%arg_z))
+	__(ret)
+4:	__(movq $four_digit_bignum_header,%imm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(4)))
+	__(jmp 6f)
+5:	__(movq $five_digit_bignum_header,%imm0)
+	__(Misc_Alloc_Fixed(%arg_z,aligned_bignum_size(5)))
+6:	__(movq %mm0,misc_data_offset(%arg_z))
+	__(movq %mm0,misc_data_offset+8(%arg_z))
+	__(ret)
+_endfn
+
+_spentry(misc_ref)
+	__(movb $tagmask,%imm0_b)
+	__(andb %arg_y_b,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 0f)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+	__(movq misc_header_offset(%arg_y),%imm0)
+        __(xorb %imm0_b,%imm0_b)
+	__(shrq $num_subtag_bits-fixnumshift,%imm0)
+	__(cmpq %imm0,%arg_z)
+	__(jae 2f)
+	__(movb misc_subtag_offset(%arg_y),%imm1_b)
+        __(jmp C(misc_ref_common))
+        
+0:      __(uuo_error_reg_not_tag(Rarg_y,tag_misc))
+1:      __(uuo_error_reg_not_fixnum(Rarg_z))
+2:      __(uuo_error_vector_bounds(Rarg_z,Rarg_y))        
+_endsubp(misc_ref)
+	
+/* %imm1.b = subtag, %arg_y = uvector, %arg_z = index.  */
+/* Bounds/type-checking done in caller  */
+	
+_startfn(C(misc_ref_common))
+	__(movzbl %imm1_b,%imm1_l)
+        __(lea local_label(misc_ref_jmp)(%rip),%imm2)
+	__(jmp *(%imm2,%imm1,8))
+	.p2align 3
+local_label(misc_ref_jmp):	
+	/* 00-0f   */
+	.quad local_label(misc_ref_invalid) /* 00 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 01 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 02 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 03 cons   */
+	.quad local_label(misc_ref_invalid) /* 04 tra_0   */
+	.quad local_label(misc_ref_invalid) /* 05 nodeheader_0   */
+	.quad local_label(misc_ref_invalid) /* 06 nodeheader_1   */
+	.quad local_label(misc_ref_invalid) /* 07 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 08 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 09 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* 0a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 0b nil   */
+	.quad local_label(misc_ref_invalid) /* 0c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 0d misc   */
+	.quad local_label(misc_ref_invalid) /* 0e symbol   */
+	.quad local_label(misc_ref_invalid) /* 0f function   */
+	/* 10-1f   */
+	.quad local_label(misc_ref_invalid) /* 10 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 11 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 12 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 13 cons   */
+	.quad local_label(misc_ref_invalid) /* 14 tra_0   */
+	.quad local_label(misc_ref_node) /* 15 symbol_vector   */
+	.quad local_label(misc_ref_node) /* 16 ratio   */
+	.quad local_label(misc_ref_invalid) /* 17 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 18 odd_fixnum   */
+	.quad local_label(misc_ref_u32)	/* 19 bignum   */
+	.quad local_label(misc_ref_u64) /* 1a macptr   */
+	.quad local_label(misc_ref_invalid) /* 1b nil   */
+	.quad local_label(misc_ref_invalid) /* 1c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 1d misc   */
+	.quad local_label(misc_ref_invalid) /* 1e symbol   */
+	.quad local_label(misc_ref_invalid) /* 1f function   */
+	/* 20-2f   */
+	.quad local_label(misc_ref_invalid) /* 20 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 21 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 22 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 23 cons   */
+	.quad local_label(misc_ref_invalid) /* 24 tra_0   */
+	.quad local_label(misc_ref_node) /* 25 catch_frame   */
+	.quad local_label(misc_ref_node) /* 26 complex   */
+	.quad local_label(misc_ref_invalid) /* 27 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 28 odd_fixnum   */
+	.quad local_label(misc_ref_u32)	/* 29 double_float   */
+	.quad local_label(misc_ref_u64)  /* 2a dead_macptr   */
+	.quad local_label(misc_ref_invalid) /* 2b nil   */
+	.quad local_label(misc_ref_invalid) /* 2c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 2d misc   */
+	.quad local_label(misc_ref_invalid) /* 2e symbol   */
+	.quad local_label(misc_ref_invalid) /* 2f function   */
+	/* 30-3f   */
+	.quad local_label(misc_ref_invalid) /* 30 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 31 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 32 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 33 cons   */
+	.quad local_label(misc_ref_invalid) /* 34 tra_0   */
+	.quad local_label(misc_ref_node) /* 35 hash_vector   */
+	.quad local_label(misc_ref_node) /* 36 struct   */
+	.quad local_label(misc_ref_invalid) /* 37 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 38 odd_fixnum   */
+	.quad local_label(misc_ref_u32)	/* 39 xcode_vector   */
+	.quad local_label(misc_ref_invalid) /* 3a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 3b nil   */
+	.quad local_label(misc_ref_invalid) /* 3c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 3d misc   */
+	.quad local_label(misc_ref_invalid) /* 3e symbol   */
+	.quad local_label(misc_ref_invalid) /* 3f function   */
+	/* 40-4f   */
+	.quad local_label(misc_ref_invalid) /* 40 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 41 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 42 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 43 cons   */
+	.quad local_label(misc_ref_invalid) /* 44 tra_0   */
+	.quad local_label(misc_ref_node) /* 45 pool   */
+	.quad local_label(misc_ref_node) /* 46 istruct   */
+	.quad local_label(misc_ref_invalid) /* 47 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 48 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 49 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* 4a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 4b nil   */
+	.quad local_label(misc_ref_invalid) /* 4c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 4d misc   */
+	.quad local_label(misc_ref_invalid) /* 4e symbol   */
+	.quad local_label(misc_ref_invalid) /* 4f function   */
+	/* 50-5f   */
+	.quad local_label(misc_ref_invalid) /* 50 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 51 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 52 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 53 cons   */
+	.quad local_label(misc_ref_invalid) /* 54 tra_0   */
+	.quad local_label(misc_ref_node) /* 55 weak   */
+	.quad local_label(misc_ref_node) /* 56 value_cell   */
+	.quad local_label(misc_ref_invalid) /* 57 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 58 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 59 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* 5a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 5b nil   */
+	.quad local_label(misc_ref_invalid) /* 5c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 5d misc   */
+	.quad local_label(misc_ref_invalid) /* 5e symbol   */
+	.quad local_label(misc_ref_invalid) /* 5f function   */
+	/* 60-6f   */
+	.quad local_label(misc_ref_invalid) /* 60 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 61 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 62 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 63 cons   */
+	.quad local_label(misc_ref_invalid) /* 64 tra_0   */
+	.quad local_label(misc_ref_node) /* 65 package   */
+	.quad local_label(misc_ref_node) /* 66 xfunction   */
+	.quad local_label(misc_ref_invalid) /* 67 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 68 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 69 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* 6a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 6b nil   */
+	.quad local_label(misc_ref_invalid) /* 6c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 6d misc   */
+	.quad local_label(misc_ref_invalid) /* 6e symbol   */
+	.quad local_label(misc_ref_invalid) /* 6f function   */
+	/* 70-7f   */
+	.quad local_label(misc_ref_invalid) /* 70 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 71 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 72 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 73 cons   */
+	.quad local_label(misc_ref_invalid) /* 74 tra_0   */
+	.quad local_label(misc_ref_node) /* 75 slot_vector   */
+	.quad local_label(misc_ref_node) /* 76 lock   */
+	.quad local_label(misc_ref_invalid) /* 77 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 78 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 79 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* 7a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 7b nil   */
+	.quad local_label(misc_ref_invalid) /* 7c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 7d misc   */
+	.quad local_label(misc_ref_invalid) /* 7e symbol   */
+	.quad local_label(misc_ref_invalid) /* 7f function   */
+	/* 80-8f   */
+	.quad local_label(misc_ref_invalid) /* 80 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 81 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 82 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 83 cons   */
+	.quad local_label(misc_ref_invalid) /* 84 tra_0   */
+	.quad local_label(misc_ref_node) /* 85 lisp_thread   */
+	.quad local_label(misc_ref_node) /* 86 instance   */
+	.quad local_label(misc_ref_invalid) /* 87 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 88 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 89 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* 8a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 8b nil   */
+	.quad local_label(misc_ref_invalid) /* 8c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 8d misc   */
+	.quad local_label(misc_ref_invalid) /* 8e symbol   */
+	.quad local_label(misc_ref_invalid) /* 8f function   */
+	/* 90-9f   */
+	.quad local_label(misc_ref_invalid) /* 90 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 91 imm_1   */
+	.quad local_label(misc_ref_invalid) /* 92 imm_2   */
+	.quad local_label(misc_ref_invalid) /* 93 cons   */
+	.quad local_label(misc_ref_invalid) /* 94 tra_0   */
+	.quad local_label(misc_ref_function) /* 95 function_vector   */
+	.quad local_label(misc_ref_invalid) /* 96 nodeheader_1   */
+	.quad local_label(misc_ref_invalid) /* 97 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* 98 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* 99 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* 9a immheader_2   */
+	.quad local_label(misc_ref_invalid) /* 9b nil   */
+	.quad local_label(misc_ref_invalid) /* 9c tra_1   */
+	.quad local_label(misc_ref_invalid) /* 9d misc   */
+	.quad local_label(misc_ref_invalid) /* 9e symbol   */
+	.quad local_label(misc_ref_invalid) /* 9f function   */
+	/* a0-af   */
+	.quad local_label(misc_ref_invalid) /* a0 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* a1 imm_1   */
+	.quad local_label(misc_ref_invalid) /* a2 imm_2   */
+	.quad local_label(misc_ref_invalid) /* a3 cons   */
+	.quad local_label(misc_ref_invalid) /* a4 tra_0   */
+	.quad local_label(misc_ref_node) /* a5 arrayH   */
+	.quad local_label(misc_ref_node) /* a6 vectorH   */
+	.quad local_label(misc_ref_s16)	/* a7 s16   */
+	.quad local_label(misc_ref_invalid) /* a8 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* a9 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* aa immheader_2   */
+	.quad local_label(misc_ref_invalid) /* ab nil   */
+	.quad local_label(misc_ref_invalid) /* ac tra_1   */
+	.quad local_label(misc_ref_invalid) /* ad misc   */
+	.quad local_label(misc_ref_invalid) /* ae symbol   */
+	.quad local_label(misc_ref_invalid) /* af function   */
+	/* b0-bf   */
+	.quad local_label(misc_ref_invalid) /* b0 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* b1 imm_1   */
+	.quad local_label(misc_ref_invalid) /* b2 imm_2   */
+	.quad local_label(misc_ref_invalid) /* b3 cons   */
+	.quad local_label(misc_ref_invalid) /* b4 tra_0   */
+	.quad local_label(misc_ref_invalid) /* b5 nodeheader_0   */
+	.quad local_label(misc_ref_node) /* b6 simple_vector   */
+	.quad local_label(misc_ref_u16) /* b7 immheader_0   */
+	.quad local_label(misc_ref_invalid) /* b8 odd_fixnum   */
+	.quad local_label(misc_ref_invalid) /* b9 immheader_1   */
+	.quad local_label(misc_ref_invalid) /* ba immheader_2   */
+	.quad local_label(misc_ref_invalid) /* bb nil   */
+	.quad local_label(misc_ref_invalid) /* bc tra_1   */
+	.quad local_label(misc_ref_invalid) /* bd misc   */
+	.quad local_label(misc_ref_invalid) /* be symbol   */
+	.quad local_label(misc_ref_invalid) /* bf function   */
+	/* c0-cf   */
+	.quad local_label(misc_ref_invalid) /* c0 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* c1 imm_1   */
+	.quad local_label(misc_ref_invalid) /* c2 imm_2   */
+	.quad local_label(misc_ref_invalid) /* c3 cons   */
+	.quad local_label(misc_ref_invalid) /* c4 tra_0   */
+	.quad local_label(misc_ref_invalid) /* c5 nodeheader_0   */
+	.quad local_label(misc_ref_invalid) /* c6 nodeheader_1   */
+	.quad local_label(misc_ref_string) /* c7 simple_base_string   */
+	.quad local_label(misc_ref_invalid) /* c8 odd_fixnum   */
+	.quad local_label(misc_ref_new_string) /* c9 new_string_1   */
+	.quad local_label(misc_ref_fixnum_vector) /* ca fixnum_vector   */
+	.quad local_label(misc_ref_invalid) /* cb nil   */
+	.quad local_label(misc_ref_invalid) /* cc tra_1   */
+	.quad local_label(misc_ref_invalid) /* cd misc   */
+	.quad local_label(misc_ref_invalid) /* ce symbol   */
+	.quad local_label(misc_ref_invalid) /* cf function   */
+	/* d0-df   */
+	.quad local_label(misc_ref_invalid) /* d0 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* d1 imm_1   */
+	.quad local_label(misc_ref_invalid) /* d2 imm_2   */
+	.quad local_label(misc_ref_invalid) /* d3 cons   */
+	.quad local_label(misc_ref_invalid) /* d4 tra_0   */
+	.quad local_label(misc_ref_invalid) /* d5 nodeheader_0   */
+	.quad local_label(misc_ref_invalid) /* d6 nodeheader_1   */
+	.quad local_label(misc_ref_s8)	/* d7 s8   */
+	.quad local_label(misc_ref_invalid) /* d8 odd_fixnum   */
+	.quad local_label(misc_ref_s32)	/* d9 s32   */
+	.quad local_label(misc_ref_s64)	/* da s64   */
+	.quad local_label(misc_ref_invalid) /* db nil   */
+	.quad local_label(misc_ref_invalid) /* dc tra_1   */
+	.quad local_label(misc_ref_invalid) /* dd misc   */
+	.quad local_label(misc_ref_invalid) /* de symbol   */
+	.quad local_label(misc_ref_invalid) /* df function   */
+	/* e0-ef   */
+	.quad local_label(misc_ref_invalid) /* e0 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* e1 imm_1   */
+	.quad local_label(misc_ref_invalid) /* e2 imm_2   */
+	.quad local_label(misc_ref_invalid) /* e3 cons   */
+	.quad local_label(misc_ref_invalid) /* e4 tra_0   */
+	.quad local_label(misc_ref_invalid) /* e5 nodeheader_0   */
+	.quad local_label(misc_ref_invalid) /* e6 nodeheader_1   */
+	.quad local_label(misc_ref_u8)	/* e7 u8   */
+	.quad local_label(misc_ref_invalid) /* e8 odd_fixnum   */
+	.quad local_label(misc_ref_u32)	/* e9 u32   */
+	.quad local_label(misc_ref_u64) /* ea u64   */
+	.quad local_label(misc_ref_invalid) /* eb nil   */
+	.quad local_label(misc_ref_invalid) /* ec tra_1   */
+	.quad local_label(misc_ref_invalid) /* ed misc   */
+	.quad local_label(misc_ref_invalid) /* ee symbol   */
+	.quad local_label(misc_ref_invalid) /* ef function   */
+	/* f0-ff   */
+	.quad local_label(misc_ref_invalid) /* f0 even_fixnum   */
+	.quad local_label(misc_ref_invalid) /* f1 imm_1   */
+	.quad local_label(misc_ref_invalid) /* f2 imm_2   */
+	.quad local_label(misc_ref_invalid) /* f3 cons   */
+	.quad local_label(misc_ref_invalid) /* f4 tra_0   */
+	.quad local_label(misc_ref_invalid) /* f5 nodeheader_0   */
+	.quad local_label(misc_ref_invalid) /* f6 nodeheader_1   */
+	.quad local_label(misc_ref_bit_vector) /* f7 bitvector   */
+	.quad local_label(misc_ref_invalid) /* f8 odd_fixnum   */
+	.quad local_label(misc_ref_single_float_vector) /* f9 single_float   */
+	.quad local_label(misc_ref_double_float_vector) /* fa double_float   */
+	.quad local_label(misc_ref_invalid) /* fb nil   */
+	.quad local_label(misc_ref_invalid) /* fc tra_1   */
+	.quad local_label(misc_ref_invalid) /* fd misc   */
+	.quad local_label(misc_ref_invalid) /* fe symbol   */
+	.quad local_label(misc_ref_invalid) /* ff function   */
+	
+	
+	/* Node vector.  Functions are funny: the first  N words  */
+	/* are treated as (UNSIGNED-BYTE 64), where N is the low  */
+	/* 32 bits of the first word.  */
+	
+local_label(misc_ref_function):		
+	__(movl misc_data_offset(%arg_y),%imm0_l)
+	__(shl $fixnumshift,%imm0)
+	__(rcmpq(%arg_z,%imm0))
+	__(jb local_label(misc_ref_u64))
+local_label(misc_ref_node):
+	__(movq misc_data_offset(%arg_y,%arg_z),%arg_z)
+	__(ret)
+local_label(misc_ref_u64):
+	__(movq misc_data_offset(%arg_y,%arg_z),%imm0)
+	__(jmp _SPmakeu64)
+local_label(misc_ref_double_float_vector):
+	__(movsd misc_data_offset(%arg_y,%arg_z),%fp1)
+	__(movq $double_float_header,%imm0)
+	__(Misc_Alloc_Fixed(%arg_z,double_float.size))
+	__(movsd %fp1,double_float.value(%arg_z))
+	__(ret)
+local_label(misc_ref_fixnum_vector):	
+	__(movq misc_data_offset(%arg_y,%arg_z),%imm0)
+        __(box_fixnum(%imm0,%arg_z))
+        __(ret)
+local_label(misc_ref_s64):	
+	__(movq misc_data_offset(%arg_y,%arg_z),%imm0)
+	__(jmp _SPmakes64)
+local_label(misc_ref_u32):
+	__(movq %arg_z,%imm0)
+	__(shr $1,%imm0)
+	__(movl misc_data_offset(%arg_y,%imm0),%imm0_l)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_s32):
+	__(movq %arg_z,%imm0)
+	__(shr $1,%imm0)
+	__(movslq misc_data_offset(%arg_y,%imm0),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_single_float_vector):
+	__(movq %arg_z,%imm0)
+	__(shr $1,%imm0)
+	__(movsd misc_data_offset(%arg_y,%imm0),%fp1)
+	__(movd %fp1,%imm0_l)
+	__(shl $32,%imm0)
+	__(lea subtag_single_float(%imm0),%arg_z)
+	__(ret)
+local_label(misc_ref_u8):
+	__(movq %arg_z,%imm0)
+	__(shr $3,%imm0)
+	__(movzbl misc_data_offset(%arg_y,%imm0),%imm0_l)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_s8):	
+	__(movq %arg_z,%imm0)
+	__(shr $3,%imm0)
+	__(movsbq misc_data_offset(%arg_y,%imm0),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_string):
+	__(movq %arg_z,%imm0)
+	__(shr $3,%imm0)
+	__(movzbl misc_data_offset(%arg_y,%imm0),%imm0_l)
+	__(shlq $charcode_shift,%imm0)
+	__(leaq subtag_character(%imm0),%arg_z)
+	__(ret)
+local_label(misc_ref_new_string):
+	__(movq %arg_z,%imm0)
+	__(shr $1,%imm0)
+	__(movl misc_data_offset(%arg_y,%imm0),%imm0_l)
+	__(shlq $charcode_shift,%imm0)
+	__(leaq subtag_character(%imm0),%arg_z)
+	__(ret)        
+local_label(misc_ref_u16):	
+	__(movq %arg_z,%imm0)
+	__(shrq $2,%imm0)
+	__(movzwl misc_data_offset(%arg_y,%imm0),%imm0_l)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_s16):	
+	__(movq %arg_z,%imm0)
+	__(shrq $2,%imm0)
+	__(movswq misc_data_offset(%arg_y,%imm0),%imm0)
+	__(box_fixnum(%imm0,%arg_z))
+	__(ret)
+local_label(misc_ref_bit_vector):
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(btq %imm0,misc_data_offset(%arg_y))
+	__(setc %imm0_b)
+	__(movzbl %imm0_b,%imm0_l)
+	__(imull $fixnumone,%imm0_l,%arg_z_l)
+	__(ret)
+local_label(misc_ref_invalid):
+	__(movq $XBADVEC,%arg_x)
+	__(set_nargs(3))
+	__(jmp _SPksignalerr)
+_endfn(C(misc_ref_common))
+
+/* like misc_ref, only the boxed subtag is in arg_x.   */
+					
+_spentry(subtag_misc_ref)
+	__(movb $tagmask,%imm0_b)
+	__(andb %arg_y_b,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 0f)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+        __(movq misc_header_offset(%arg_y),%imm0)
+        __(xorb %imm0_b,%imm0_b)
+	__(shrq $num_subtag_bits-fixnumshift,%imm0)
+	__(cmpq %imm0,%arg_z)
+	__(jae 2f)
+	__(unbox_fixnum(%arg_x,%imm1))
+	__(jmp C(misc_ref_common))
+0:      __(uuo_error_reg_not_tag(Rarg_y,tag_misc))
+1:      __(uuo_error_reg_not_fixnum(Rarg_z))
+2:      __(uuo_error_vector_bounds(Rarg_z,Rarg_y))
+                        
+_endsubp(subtag_misc_ref)
+
+_spentry(subtag_misc_set)
+	__(movb $tagmask,%imm0_b)
+	__(andb %arg_x_b,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 0f)
+	__(testb $fixnummask,%arg_y_b)
+	__(jne 1f)
+	__(movq misc_header_offset(%arg_x),%imm0)
+        __(xorb %imm0_b,%imm0_b)
+	__(shrq $num_subtag_bits-fixnumshift,%imm0)
+	__(cmpq %imm0,%arg_y)
+	__(jae 2f)
+	__(unbox_fixnum(%temp0,%imm1))
+	__(jmp C(misc_set_common))
+0:      __(uuo_error_reg_not_tag(Rarg_x,tag_misc))
+1:      __(uuo_error_reg_not_fixnum(Rarg_y))
+2:      __(uuo_error_vector_bounds(Rarg_y,Rarg_x))                        
+_endsubp(subtag_misc_set)
+
+_spentry(misc_set)
+	__(movb $tagmask,%imm0_b)
+	__(andb %arg_x_b,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 0f)
+	__(testb $fixnummask,%arg_y_b)
+	__(jne 1f)
+	__(movq misc_header_offset(%arg_x),%imm0)
+        __(xorb %imm0_b,%imm0_b)
+	__(shrq $num_subtag_bits-fixnumshift,%imm0)
+	__(cmpq %imm0,%arg_y)
+	__(jae 2f)
+	__(movb misc_subtag_offset(%arg_x),%imm1_b)
+	__(jmp C(misc_set_common))
+	
+0:      __(uuo_error_reg_not_tag(Rarg_x,tag_misc))
+1:      __(uuo_error_reg_not_fixnum(Rarg_y))
+2:      __(uuo_error_vector_bounds(Rarg_y,Rarg_x))                        
+_endsubp(misc_set)
+		
+_startfn(C(misc_set_common))
+	__(movzbl %imm1_b,%imm1_l)
+        __(lea local_label(misc_set_jmp)(%rip),%imm2)
+	__(jmp *(%imm2,%imm1,8))
+	.p2align 3
+local_label(misc_set_jmp):		
+	/* 00-0f   */
+	.quad local_label(misc_set_invalid) /* 00 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 01 imm_1   */
+	.quad local_label(misc_set_invalid) /* 02 imm_2   */
+	.quad local_label(misc_set_invalid) /* 03 cons   */
+	.quad local_label(misc_set_invalid) /* 04 tra_0   */
+	.quad local_label(misc_set_invalid) /* 05 nodeheader_0   */
+	.quad local_label(misc_set_invalid) /* 06 nodeheader_1   */
+	.quad local_label(misc_set_invalid) /* 07 immheader_0   */
+	.quad local_label(misc_set_invalid) /* 08 odd_fixnum   */
+	.quad local_label(misc_set_invalid) /* 09 immheader_1   */
+	.quad local_label(misc_set_invalid) /* 0a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 0b nil   */
+	.quad local_label(misc_set_invalid) /* 0c tra_1   */
+	.quad local_label(misc_set_invalid) /* 0d misc   */
+	.quad local_label(misc_set_invalid) /* 0e symbol   */
+	.quad local_label(misc_set_invalid) /* 0f function   */
+	/* 10-1f   */
+	.quad local_label(misc_set_invalid)	/* 10 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 11 imm_1   */
+	.quad local_label(misc_set_invalid) /* 12 imm_2   */
+	.quad local_label(misc_set_invalid) /* 13 cons   */
+	.quad local_label(misc_set_invalid)	/* 14 tra_0   */
+	.quad _SPgvset /* 15 symbol_vector   */
+	.quad _SPgvset /* 16 ratio   */
+	.quad local_label(misc_set_invalid) /* 17 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 18 odd_fixnum   */
+	.quad local_label(misc_set_u32)	/* 19 bignum   */
+	.quad local_label(misc_set_u64) /* 1a macptr   */
+	.quad local_label(misc_set_invalid) /* 1b nil   */
+	.quad local_label(misc_set_invalid)	/* 1c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 1d misc   */
+	.quad local_label(misc_set_invalid)	/* 1e symbol   */
+	.quad local_label(misc_set_invalid)	/* 1f function   */
+	/* 20-2f   */
+	.quad local_label(misc_set_invalid)	/* 20 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 21 imm_1   */
+	.quad local_label(misc_set_invalid) /* 22 imm_2   */
+	.quad local_label(misc_set_invalid) /* 23 cons   */
+	.quad local_label(misc_set_invalid)	/* 24 tra_0   */
+	.quad _SPgvset /* 25 catch_frame   */
+	.quad _SPgvset /* 26 complex   */
+	.quad local_label(misc_set_invalid) /* 27 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 28 odd_fixnum   */
+	.quad local_label(misc_set_u32)	/* 29 double_float   */
+	.quad local_label(misc_set_u64)  /* 2a dead_macptr   */
+	.quad local_label(misc_set_invalid) /* 2b nil   */
+	.quad local_label(misc_set_invalid)	/* 2c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 2d misc   */
+	.quad local_label(misc_set_invalid)	/* 2e symbol   */
+	.quad local_label(misc_set_invalid)	/* 2f function   */
+	/* 30-3f   */
+	.quad local_label(misc_set_invalid)	/* 30 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 31 imm_1   */
+	.quad local_label(misc_set_invalid) /* 32 imm_2   */
+	.quad local_label(misc_set_invalid) /* 33 cons   */
+	.quad local_label(misc_set_invalid)	/* 34 tra_0   */
+	.quad _SPgvset /* 35 hash_vector   */
+	.quad _SPgvset /* 36 struct   */
+	.quad local_label(misc_set_invalid) /* 37 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 38 odd_fixnum   */
+	.quad local_label(misc_set_u32)	/* 39 xcode_vector   */
+	.quad local_label(misc_set_invalid)  /* 3a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 3b nil   */
+	.quad local_label(misc_set_invalid)	/* 3c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 3d misc   */
+	.quad local_label(misc_set_invalid)	/* 3e symbol   */
+	.quad local_label(misc_set_invalid)	/* 3f function   */
+	/* 40-4f   */
+	.quad local_label(misc_set_invalid)	/* 40 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 41 imm_1   */
+	.quad local_label(misc_set_invalid) /* 42 imm_2   */
+	.quad local_label(misc_set_invalid) /* 43 cons   */
+	.quad local_label(misc_set_invalid)	/* 44 tra_0   */
+	.quad _SPgvset /* 45 pool   */
+	.quad _SPgvset /* 46 istruct   */
+	.quad local_label(misc_set_invalid) /* 47 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 48 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* 49 immheader_1   */
+	.quad local_label(misc_set_invalid)  /* 4a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 4b nil   */
+	.quad local_label(misc_set_invalid)	/* 4c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 4d misc   */
+	.quad local_label(misc_set_invalid)	/* 4e symbol   */
+	.quad local_label(misc_set_invalid)	/* 4f function   */
+	/* 50-5f   */
+	.quad local_label(misc_set_invalid)	/* 50 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 51 imm_1   */
+	.quad local_label(misc_set_invalid) /* 52 imm_2   */
+	.quad local_label(misc_set_invalid) /* 53 cons   */
+	.quad local_label(misc_set_invalid)	/* 54 tra_0   */
+	.quad _SPgvset /* 55 weak   */
+	.quad _SPgvset /* 56 value_cell   */
+	.quad local_label(misc_set_invalid) /* 57 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 58 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* 59 immheader_1   */
+	.quad local_label(misc_set_invalid)  /* 5a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 5b nil   */
+	.quad local_label(misc_set_invalid)	/* 5c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 5d misc   */
+	.quad local_label(misc_set_invalid)	/* 5e symbol   */
+	.quad local_label(misc_set_invalid)	/* 5f function   */
+	/* 60-6f   */
+	.quad local_label(misc_set_invalid)	/* 60 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 61 imm_1   */
+	.quad local_label(misc_set_invalid) /* 62 imm_2   */
+	.quad local_label(misc_set_invalid) /* 63 cons   */
+	.quad local_label(misc_set_invalid)	/* 64 tra_0   */
+	.quad _SPgvset /* 65 package   */
+	.quad _SPgvset /* 66 xfunction   */
+	.quad local_label(misc_set_invalid) /* 67 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 68 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* 69 immheader_1   */
+	.quad local_label(misc_set_invalid)  /* 6a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 6b nil   */
+	.quad local_label(misc_set_invalid)	/* 6c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 6d misc   */
+	.quad local_label(misc_set_invalid)	/* 6e symbol   */
+	.quad local_label(misc_set_invalid)	/* 6f function   */
+	/* 70-7f   */
+	.quad local_label(misc_set_invalid)	/* 70 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 71 imm_1   */
+	.quad local_label(misc_set_invalid) /* 72 imm_2   */
+	.quad local_label(misc_set_invalid) /* 73 cons   */
+	.quad local_label(misc_set_invalid)	/* 74 tra_0   */
+	.quad _SPgvset /* 75 slot_vector   */
+	.quad _SPgvset /* 76 lock   */
+	.quad local_label(misc_set_invalid) /* 77 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 78 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* 79 immheader_1   */
+	.quad local_label(misc_set_invalid)  /* 7a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 7b nil   */
+	.quad local_label(misc_set_invalid)	/* 7c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 7d misc   */
+	.quad local_label(misc_set_invalid)	/* 7e symbol   */
+	.quad local_label(misc_set_invalid)	/* 7f function   */
+	/* 80-8f   */
+	.quad local_label(misc_set_invalid)	/* 80 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 81 imm_1   */
+	.quad local_label(misc_set_invalid) /* 82 imm_2   */
+	.quad local_label(misc_set_invalid) /* 83 cons   */
+	.quad local_label(misc_set_invalid)	/* 84 tra_0   */
+	.quad _SPgvset /* 85 lisp_thread   */
+	.quad _SPgvset /* 86 instance   */
+	.quad local_label(misc_set_invalid) /* 87 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 88 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* 89 immheader_1   */
+	.quad local_label(misc_set_invalid)  /* 8a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 8b nil   */
+	.quad local_label(misc_set_invalid)	/* 8c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 8d misc   */
+	.quad local_label(misc_set_invalid)	/* 8e symbol   */
+	.quad local_label(misc_set_invalid)	/* 8f function   */
+	/* 90-9f   */
+	.quad local_label(misc_set_invalid)	/* 90 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* 91 imm_1   */
+	.quad local_label(misc_set_invalid) /* 92 imm_2   */
+	.quad local_label(misc_set_invalid) /* 93 cons   */
+	.quad local_label(misc_set_invalid)	/* 94 tra_0   */
+	.quad local_label(misc_set_function) /* 95 function_vector   */
+	.quad local_label(misc_set_invalid) /* 96 nodeheader_1   */
+	.quad local_label(misc_set_invalid) /* 97 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* 98 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* 99 immheader_1   */
+	.quad local_label(misc_set_invalid)  /* 9a immheader_2   */
+	.quad local_label(misc_set_invalid) /* 9b nil   */
+	.quad local_label(misc_set_invalid)	/* 9c tra_1   */
+	.quad local_label(misc_set_invalid)	/* 9d misc   */
+	.quad local_label(misc_set_invalid)	/* 9e symbol   */
+	.quad local_label(misc_set_invalid)	/* 9f function   */
+	/* a0-af   */
+	.quad local_label(misc_set_invalid)	/* a0 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* a1 imm_1   */
+	.quad local_label(misc_set_invalid) /* a2 imm_2   */
+	.quad local_label(misc_set_invalid) /* a3 cons   */
+	.quad local_label(misc_set_invalid)	/* a4 tra_0   */
+	.quad _SPgvset /* a5 arrayH   */
+	.quad _SPgvset /* a6 vectorH   */
+	.quad local_label(misc_set_s16)	/* a7 s16   */
+	.quad local_label(misc_set_invalid)	/* a8 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* a9 immheader_1   */
+	.quad local_label(misc_set_invalid)  /* aa immheader_2   */
+	.quad local_label(misc_set_invalid) /* ab nil   */
+	.quad local_label(misc_set_invalid)	/* ac tra_1   */
+	.quad local_label(misc_set_invalid)	/* ad misc   */
+	.quad local_label(misc_set_invalid)	/* ae symbol   */
+	.quad local_label(misc_set_invalid)	/* af function   */
+	/* b0-bf   */
+	.quad local_label(misc_set_invalid)	/* b0 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* b1 imm_1   */
+	.quad local_label(misc_set_invalid) /* b2 imm_2   */
+	.quad local_label(misc_set_invalid) /* b3 cons   */
+	.quad local_label(misc_set_invalid)	/* b4 tra_0   */
+	.quad local_label(misc_set_invalid) /* b5 nodeheader_0   */
+	.quad _SPgvset /* b6 simple_vector   */
+	.quad local_label(misc_set_u16) /* b7 immheader_0   */
+	.quad local_label(misc_set_invalid)	/* b8 odd_fixnum   */
+	.quad local_label(misc_set_invalid)	/* b9 immheader_1   */
+	.quad local_label(misc_set_invalid) /* ba immheader_2   */
+	.quad local_label(misc_set_invalid) /* bb nil   */
+	.quad local_label(misc_set_invalid)	/* bc tra_1   */
+	.quad local_label(misc_set_invalid)	/* bd misc   */
+	.quad local_label(misc_set_invalid)	/* be symbol   */
+	.quad local_label(misc_set_invalid)	/* bf function   */
+	/* c0-cf   */
+	.quad local_label(misc_set_invalid)	/* c0 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* c1 imm_1   */
+	.quad local_label(misc_set_invalid) /* c2 imm_2   */
+	.quad local_label(misc_set_invalid) /* c3 cons   */
+	.quad local_label(misc_set_invalid)	/* c4 tra_0   */
+	.quad local_label(misc_set_invalid) /* c5 nodeheader_0   */
+	.quad local_label(misc_set_invalid) /* c6 nodeheader_1   */
+	.quad local_label(misc_set_string) /* c7 simple_base_string   */
+	.quad local_label(misc_set_invalid)	/* c8 odd_fixnum   */
+	.quad local_label(misc_set_new_string)	/* c9 new_strin   */
+	.quad local_label(misc_set_fixnum_vector)  /* ca fixnum_vector   */
+	.quad local_label(misc_set_invalid) /* cb nil   */
+	.quad local_label(misc_set_invalid)	/* cc tra_1   */
+	.quad local_label(misc_set_invalid)	/* cd misc   */
+	.quad local_label(misc_set_invalid)	/* ce symbol   */
+	.quad local_label(misc_set_invalid)	/* cf function   */
+	/* d0-df   */
+	.quad local_label(misc_set_invalid)	/* d0 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* d1 imm_1   */
+	.quad local_label(misc_set_invalid) /* d2 imm_2   */
+	.quad local_label(misc_set_invalid) /* d3 cons   */
+	.quad local_label(misc_set_invalid)	/* d4 tra_0   */
+	.quad local_label(misc_set_invalid) /* d5 nodeheader_0   */
+	.quad local_label(misc_set_invalid) /* d6 nodeheader_1   */
+	.quad local_label(misc_set_s8)	/* d7 s8   */
+	.quad local_label(misc_set_invalid)	/* d8 odd_fixnum   */
+	.quad local_label(misc_set_s32)	/* d9 s32   */
+	.quad local_label(misc_set_s64)	/* da s64   */
+	.quad local_label(misc_set_invalid) /* db nil   */
+	.quad local_label(misc_set_invalid)	/* dc tra_1   */
+	.quad local_label(misc_set_invalid)	/* dd misc   */
+	.quad local_label(misc_set_invalid)	/* de symbol   */
+	.quad local_label(misc_set_invalid)	/* df function   */
+	/* e0-ef   */
+	.quad local_label(misc_set_invalid)	/* e0 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* e1 imm_1   */
+	.quad local_label(misc_set_invalid) /* e2 imm_2   */
+	.quad local_label(misc_set_invalid) /* e3 cons   */
+	.quad local_label(misc_set_invalid)	/* e4 tra_0   */
+	.quad local_label(misc_set_invalid) /* e5 nodeheader_0   */
+	.quad local_label(misc_set_invalid) /* e6 nodeheader_1   */
+	.quad local_label(misc_set_u8)	/* e7 u8   */
+	.quad local_label(misc_set_invalid)	/* e8 odd_fixnum   */
+	.quad local_label(misc_set_u32)	/* e9 u32   */
+	.quad local_label(misc_set_u64) /* ea u64   */
+	.quad local_label(misc_set_invalid) /* eb nil   */
+	.quad local_label(misc_set_invalid)	/* ec tra_1   */
+	.quad local_label(misc_set_invalid)	/* ed misc   */
+	.quad local_label(misc_set_invalid)	/* ee symbol   */
+	.quad local_label(misc_set_invalid)	/* ef function   */
+	/* f0-ff   */
+	.quad local_label(misc_set_invalid)	/* f0 even_fixnum   */
+	.quad local_label(misc_set_invalid) /* f1 imm_1   */
+	.quad local_label(misc_set_invalid) /* f2 imm_2   */
+	.quad local_label(misc_set_invalid) /* f3 cons   */
+	.quad local_label(misc_set_invalid)	/* f4 tra_0   */
+	.quad local_label(misc_set_invalid) /* f5 nodeheader_0   */
+	.quad local_label(misc_set_invalid) /* f6 nodeheader_1   */
+	.quad local_label(misc_set_bit_vector) /* f7 bitvector   */
+	.quad local_label(misc_set_invalid)	/* f8 odd_fixnum   */
+	.quad local_label(misc_set_single_float_vector) /* f9 single_float   */
+	.quad local_label(misc_set_double_float_vector) /* fa double_float   */
+	.quad local_label(misc_set_invalid) /* fb nil   */
+	.quad local_label(misc_set_invalid)	/* fc tra_1   */
+	.quad local_label(misc_set_invalid)	/* fd misc   */
+	.quad local_label(misc_set_invalid)	/* fe symbol   */
+	.quad local_label(misc_set_invalid)	/* ff function   */
+
+local_label(misc_set_function):			
+	/* Functions are funny: the first  N words  */
+	/* are treated as (UNSIGNED-BYTE 64), where N is the low  */
+	/* 32 bits of the first word.   */
+	__(movl misc_data_offset(%arg_x),%imm0_l)
+	__(shl $fixnumshift,%imm0)
+	__(rcmpq(%arg_y,%imm0))
+	__(jae _SPgvset)
+local_label(misc_set_u64):
+	__(movq $~(target_most_positive_fixnum << fixnumshift),%imm0)
+	__(testq %arg_z,%imm0)
+	__(movq %arg_z,%imm0)
+	__(jne 1f)
+	__(sarq $fixnumshift,%imm0)
+	__(jmp 9f)
+1:	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movq misc_header_offset(%arg_z),%imm0)
+	__(cmpq $three_digit_bignum_header,%imm0)
+	__(je 3f)
+	__(cmpq $two_digit_bignum_header,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(movq misc_data_offset(%arg_z),%imm0)
+	__(testq %imm0,%imm0)
+	__(js local_label(misc_set_bad))
+	__(jmp 9f)
+3:	__(movq misc_data_offset(%arg_z),%imm0)
+	__(cmpl $0,misc_data_offset+8(%arg_z))
+	__(jne local_label(misc_set_bad))
+9:	__(movq %imm0,misc_data_offset(%arg_x,%arg_y))
+	__(ret)
+local_label(misc_set_fixnum_vector):
+	__(movq %arg_z,%imm0)
+	__(sarq $fixnumshift,%imm0)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(movq %imm0,misc_data_offset(%arg_x,%arg_y))
+	__(ret)	
+local_label(misc_set_s64):
+	__(movq %arg_z,%imm0)
+	__(sarq $fixnumshift,%imm0)
+	__(testb $fixnummask,%arg_z_b)
+	__(je 9f)
+1:	__(movb %arg_z_b,%imm0_b)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movq misc_header_offset(%arg_z),%imm0)
+	__(cmpq $two_digit_bignum_header,%imm0)
+	__(movq misc_data_offset(%arg_z),%imm0)
+	__(jne local_label(misc_set_bad))
+9:	__(movq %imm0,misc_data_offset(%arg_x,%arg_y))
+	__(ret)	
+local_label(misc_set_bad):
+	__(movq %arg_z,%arg_y)
+	__(movq %arg_x,%arg_z)
+	__(movq $XNOTELT,%arg_x)
+	__(set_nargs(3))
+	__(jmp _SPksignalerr)
+local_label(misc_set_double_float_vector):	
+	__(extract_lisptag(%arg_z,%imm0))
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_double_float,%imm0_b)
+	__(jne local_label(misc_set_bad))
+	__(movq double_float.value(%arg_z),%imm0)
+	__(movq %imm0,misc_dfloat_offset(%arg_x,%arg_y))
+	__(ret)
+local_label(misc_set_s32):	
+	__(movq %arg_z,%imm0)
+	__(movq %arg_y,%imm1)
+	__(shlq $64-(32+fixnumshift),%imm0)
+	__(shrq $1,%imm1)
+	__(sarq $64-(32+fixnumshift),%imm0)
+	__(cmpq %imm0,%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(testb $fixnummask,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(shr $fixnumshift,%imm0)
+	__(movl %imm0_l,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_single_float_vector):
+	__(cmpb $tag_single_float,%arg_z_b)
+	__(movq %arg_z,%imm0)
+	__(movq %arg_y,%imm1)
+	__(jne local_label(misc_set_bad))
+	__(shrq $1,%imm1)
+	__(shr $32,%imm0)
+	__(movl %imm0_l,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_u32):
+	__(movq %arg_y,%imm1)	
+	__(movq $~(0xffffffff<<fixnumshift),%imm0)
+	__(shrq $1,%imm1)
+	__(testq %imm0,%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(movl %imm0_l,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_bit_vector):	
+	__(testq $~fixnumone,%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(unbox_fixnum(%arg_y,%imm0))
+	__(testb %arg_z_b,%arg_z_b)
+	__(je local_label(misc_set_clr_bit))
+local_label(misc_set_set_bit):	
+	__(btsq %imm0,misc_data_offset(%arg_x))
+	__(ret)
+local_label(misc_set_clr_bit):	
+	__(btrq %imm0,misc_data_offset(%arg_x))
+	__(ret)
+local_label(misc_set_u8):	
+	__(testq $~(0xff<<fixnumshift),%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(movq %arg_y,%imm1)
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(shrq $3,%imm1)
+	__(movb %imm0_b,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_s8):
+	__(movq %arg_z,%imm0)
+	__(shlq $64-(8+fixnumshift),%imm0)	
+	__(sarq $64-(8+fixnumshift),%imm0)
+	__(cmpq %arg_z,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(testb $fixnummask,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(movq %arg_y,%imm1)
+	__(shrq $fixnumshift,%imm0)
+	__(shrq $3,%imm1)
+	__(movb %imm0_b,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_string):
+	__(cmpb $subtag_character,%arg_z_b)
+	__(movq %arg_z,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(movq %arg_y,%imm1)
+	__(shrq $charcode_shift,%imm0)
+	__(shrq $3,%imm1)
+	__(movb %imm0_b,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_new_string):
+	__(cmpb $subtag_character,%arg_z_b)
+	__(movq %arg_z,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(movq %arg_y,%imm1)
+	__(shrq $charcode_shift,%imm0)
+	__(shrq $1,%imm1)
+	__(movl %imm0_l,misc_data_offset(%arg_x,%imm1))
+	__(ret)        
+local_label(misc_set_s16):	
+	__(movq %arg_z,%imm0)
+	__(movq %arg_y,%imm1)
+	__(shlq $64-(16+fixnumshift),%imm0)	
+	__(shrq $2,%imm1)
+	__(sarq $64-(16+fixnumshift),%imm0)
+	__(cmpq %arg_z,%imm0)
+	__(jne local_label(misc_set_bad))
+	__(testb $fixnummask,%arg_z_b)
+	__(jne local_label(misc_set_bad))
+	__(shrq $fixnumshift,%imm0)
+	__(movw %imm0_w,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_u16):
+	__(movq %arg_y,%imm1)
+	__(testq $~(0xffff<<fixnumshift),%arg_z)
+	__(jne local_label(misc_set_bad))
+	__(shrq $2,%imm1)
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(movw %imm0_w,misc_data_offset(%arg_x,%imm1))
+	__(ret)
+local_label(misc_set_invalid):
+	__(push $XSETBADVEC)
+	__(set_nargs(4))
+	__(jmp _SPksignalerr)
+_endfn(C(misc_set_common))
+	
+/* ret1valn returns "1 multiple value" when a called function does not   */
+/* return multiple values.  Its presence on the stack (as a return address)   */
+/* identifies the stack frame to code which returns multiple values.   */
+
+_spentry(Fret1valn)
+	.globl C(ret1valn)
+__(tra(C(ret1valn)))
+        __(movq (%rsp),%ra0)
+        __(movq %arg_z,(%rsp))
+	__(set_nargs(1))
+	__(jmpq *%ra0)
+_endsubp(Fret1valn)
+	
+
+_spentry(nvalret)
+	.globl C(nvalret)			
+C(nvalret):	
+	__(ref_global(ret1val_addr,%temp1))
+	__(cmpq lisp_frame.savera0(%rbp),%temp1)
+	__(je 1f)
+	__(testl %nargs,%nargs)
+	__(movl $nil_value,%arg_z_l)
+	__(cmovneq -node_size(%rsp,%nargs_q),%arg_z)
+	__(leaveq)
+        __(ret)
+
+	
+/* actually need to return values ; always need to copy   */
+1:	__(leaq 2*node_size(%rbp),%imm1)
+	__(movq (%imm1),%ra0)
+	__(addq $node_size,%imm1)
+	__(movq 0(%rbp),%rbp)
+	__(leaq (%rsp,%nargs_q),%temp0)
+	__(xorl %imm0_l,%imm0_l)
+	__(jmp 3f)
+2:	__(movq -node_size(%temp0),%temp1)
+	__(subq $node_size,%temp0)
+	__(addl $node_size,%imm0_l)
+	__(movq %temp1,-node_size(%imm1))
+	__(subq $node_size,%imm1)
+3:	__(cmpl %imm0_l,%nargs)  ;
+	__(jne 2b)
+	__(movq %imm1,%rsp)
+	__(jmp *%ra0)	
+_endsubp(nvalret)
+	
+_spentry(jmpsym)
+	__(jump_fname())
+_endsubp(jmpsym)
+
+_spentry(jmpnfn)
+	__(movq %temp0,%fn)
+	__(jmp *%fn)
+_endsubp(jmpnfn)
+
+_spentry(funcall)
+	__(do_funcall())
+_endsubp(funcall)
+
+_spentry(mkcatch1v)
+	__(nMake_Catch(0))
+	__(ret)
+_endsubp(mkcatch1v)
+
+_spentry(mkunwind)
+	__(movq $undefined,%arg_z)
+	__(Make_Catch(fixnumone))
+	__(jmp *%ra0)
+_endsubp(mkunwind)
+        
+/* this takes a return address in %ra0; it's "new" in that it does the
+   double binding of *interrupt-level* out-of-line */
+_spentry(nmkunwind)
+	__(movq rcontext(tcr.tlb_pointer),%arg_x)
+        __(movq INTERRUPT_LEVEL_BINDING_INDEX(%arg_x),%arg_y)
+	__(push %arg_y)
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(movq $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_x))
+	__(movq $undefined,%arg_z)
+	__(Make_Catch(fixnumone))
+        __(movq %arg_y,%arg_z)
+        __(jmp _SPbind_interrupt_level)
+_endsubp(nmkunwind)
+
+_spentry(mkcatchmv)
+	__(nMake_Catch(fixnumone))
+	__(ret)
+_endsubp(mkcatchmv)
+        
+_spentry(throw)
+	__(movq rcontext(tcr.catch_top),%imm1)
+	__(xorl %imm0_l,%imm0_l)
+	__(movq (%rsp,%nargs_q),%temp0)	/* temp0 = tag   */
+	__(jmp local_label(_throw_test))
+local_label(_throw_loop):
+	__(cmpq %temp0,catch_frame.catch_tag(%imm1))
+	__(je local_label(_throw_found))
+	__(movq catch_frame.link(%imm1),%imm1)
+	__(addq $fixnum_one,%imm0)
+local_label(_throw_test):
+	__(testq %imm1,%imm1)
+	__(jne local_label(_throw_loop))
+        __(push %ra0)
+	__(uuo_error_reg_not_tag(Rtemp0,subtag_catch_frame))
+        __(pop %ra0)
+	__(jmp _SPthrow)
+local_label(_throw_found):	
+	__(testb $fulltagmask,catch_frame.mvflag(%imm1))
+	__(jne local_label(_throw_multiple))
+	__(testl %nargs,%nargs)
+	__(movl $nil_value,%arg_z_l)
+	__(je local_label(_throw_one_value))
+	__(movq -node_size(%rsp,%nargs_q),%arg_z)
+	__(add %nargs_q,%rsp)
+local_label(_throw_one_value):
+	__(lea local_label(_threw_one_value)(%rip),%ra0)
+	__(jmp _SPnthrow1value)
+__(tra(local_label(_threw_one_value)))
+	__(movq rcontext(tcr.catch_top),%temp0)
+	__(movq catch_frame.db_link(%temp0),%imm0)
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(cmpq %imm0,%imm1)
+	__(jz local_label(_threw_one_value_dont_unbind))
+	__(lea local_label(_threw_one_value_dont_unbind)(%rip),%ra0)
+        __(push %ra0)
+	__(jmp _SPunbind_to)
+__(tra(local_label(_threw_one_value_dont_unbind)))
+	__(movq catch_frame.rbp(%temp0),%rbp)
+	__(movq catch_frame.foreign_sp(%temp0),%imm0)
+	__(movq catch_frame.xframe(%temp0),%imm1)
+        __(movq %imm0,rcontext(tcr.foreign_sp))
+	__(movq %imm1,rcontext(tcr.xframe))
+	__(movq catch_frame.rsp(%temp0),%rsp)
+	__(movq catch_frame.link(%temp0),%imm1)
+	__(movq catch_frame._save0(%temp0),%save0)
+	__(movq catch_frame._save1(%temp0),%save1)
+	__(movq catch_frame._save2(%temp0),%save2)
+	__ifndef([TCR_IN_GPR])
+	__(movq catch_frame._save3(%temp0),%save3)
+	__endif
+	__(movq %imm1,rcontext(tcr.catch_top))
+	__(movq catch_frame.pc(%temp0),%ra0)
+	__(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm1)
+	__(movq (%imm1),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))
+        __(movq %imm1,rcontext(tcr.next_tsp))
+	__(jmp *%ra0)
+local_label(_throw_multiple):
+	__(lea local_label(_threw_multiple)(%rip),%ra0)
+	__(jmp _SPnthrowvalues)
+__(tra(local_label(_threw_multiple)))
+	__(movq rcontext(tcr.catch_top),%temp0)
+	__(movq catch_frame.db_link(%temp0),%imm0)
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(cmpq %imm0,%imm1)
+	__(je local_label(_threw_multiple_dont_unbind))
+	__(leaq local_label(_threw_multiple_dont_unbind)(%rip),%ra0)
+        __(push %ra0)
+	__(jmp _SPunbind_to)
+__(tra(local_label(_threw_multiple_dont_unbind)))
+	/* Copy multiple values from the current %rsp to the target %rsp   */
+	__(lea (%rsp,%nargs_q),%imm0)
+	__(movq catch_frame.rsp(%temp0),%imm1)
+	__(jmp local_label(_threw_multiple_push_test))
+local_label(_threw_multiple_push_loop):
+	__(subq $node_size,%imm0)
+	__(subq $node_size,%imm1)
+	__(movq (%imm0),%arg_z)
+	__(movq %arg_z,(%imm1))
+local_label(_threw_multiple_push_test):		
+	__(cmpq %imm0,%rsp)
+	__(jne local_label(_threw_multiple_push_loop))
+	/* target %rsp is now in %imm1   */
+	__(movq catch_frame.rbp(%temp0),%rbp)
+	__(movq catch_frame.foreign_sp(%temp0),%imm0)
+        __(movq %imm0,rcontext(tcr.foreign_sp))        
+	__(movq catch_frame.xframe(%temp0),%imm0)
+	__(movq %imm0,rcontext(tcr.xframe))
+	__(movq %imm1,%rsp)
+	__(movq catch_frame.link(%temp0),%imm1)		
+	__(movq catch_frame._save0(%temp0),%save0)
+	__(movq catch_frame._save1(%temp0),%save1)
+	__(movq catch_frame._save2(%temp0),%save2)
+	__ifndef([TCR_IN_GPR])
+	__(movq catch_frame._save3(%temp0),%save3)
+	__endif
+	__(movq %imm1,rcontext(tcr.catch_top))
+	__(movq catch_frame.pc(%temp0),%ra0)
+	__(lea -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm1)
+	__(movq (%imm1),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))
+        __(movq %imm1,rcontext(tcr.next_tsp))
+	__(jmp *%ra0)
+_endsubp(throw)
+
+/* This takes N multiple values atop the vstack.   */
+_spentry(nthrowvalues)
+	__(movb $1,rcontext(tcr.unwinding))
+local_label(_nthrowv_nextframe):
+	__(subq $fixnumone,%imm0)
+	__(js local_label(_nthrowv_done))
+	__(movd %imm0,%mm1)
+	__(movq rcontext(tcr.catch_top),%temp0)
+	__(movq catch_frame.link(%temp0),%imm1)
+	__(movq catch_frame.db_link(%temp0),%imm0)
+	__(movq %imm1,rcontext(tcr.catch_top))
+	__(cmpq %imm0,rcontext(tcr.db_link))
+	__(jz local_label(_nthrowv_dont_unbind))
+	__(push %ra0)
+	__(leaq local_label(_nthrowv_back_from_unbind)(%rip),%ra0)
+        __(push %ra0)
+	__(jmp _SPunbind_to)
+__(tra(local_label(_nthrowv_back_from_unbind)))
+
+	__(pop %ra0)
+local_label(_nthrowv_dont_unbind):
+	__(cmpb $unbound_marker,catch_frame.catch_tag(%temp0))
+	__(je local_label(_nthrowv_do_unwind))
+/* A catch frame.  If the last one, restore context from there.   */
+	__(movd %mm1,%imm0)
+	__(testq %imm0,%imm0)	/* last catch frame ?   */
+	__(jne local_label(_nthrowv_skip))
+	__(movq catch_frame.xframe(%temp0),%save0)
+	__(movq %save0,rcontext(tcr.xframe))
+	__(leaq (%rsp,%nargs_q),%save1)
+	__(movq catch_frame.rsp(%temp0),%save2)
+	__(movq %nargs_q,%save0)
+	__(jmp local_label(_nthrowv_push_test))
+local_label(_nthrowv_push_loop):
+	__(subq $node_size,%save1)
+	__(subq $node_size,%save2)
+	__(movq (%save1),%temp1)
+	__(movq %temp1,(%save2))
+local_label(_nthrowv_push_test):
+	__(subq $node_size,%save0)
+	__(jns local_label(_nthrowv_push_loop))
+	__(movq catch_frame.xframe(%temp0),%save0)
+	__(movq %save0,rcontext(tcr.xframe))
+	__(movq %save2,%rsp)
+	__(movq catch_frame.rbp(%temp0),%rbp)
+	__ifndef([TCR_IN_GPR])
+	__(movq catch_frame._save3(%temp0),%save3)
+	__endif
+	__(movq catch_frame._save2(%temp0),%save2)
+	__(movq catch_frame._save1(%temp0),%save1)
+	__(movq catch_frame._save0(%temp0),%save0)
+	__(movq catch_frame.foreign_sp(%temp0),%stack_temp)
+        __(movq %stack_temp,rcontext(tcr.foreign_sp))        
+local_label(_nthrowv_skip):	
+	__(movq -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))        
+        __(movq %imm1,rcontext(tcr.next_tsp))
+	__(movd %mm1,%imm0)
+	__(jmp local_label(_nthrowv_nextframe))
+local_label(_nthrowv_do_unwind):	
+/* This is harder.  Call the cleanup code with the multiple values and   */
+/* nargs, the throw count, and the caller's return address in a temp  */
+/* stack frame.   */
+	__(leaq (%rsp,%nargs_q),%save1)
+	__(push catch_frame._save0(%temp0))
+	__(push catch_frame._save1(%temp0))
+	__(push catch_frame._save2(%temp0))
+	__ifndef([TCR_IN_GPR])
+	__(push catch_frame._save3(%temp0))
+	__endif
+	__(push catch_frame.pc(%temp0))
+	__(movq catch_frame.rbp(%temp0),%rbp)
+        __(movq catch_frame.xframe(%temp0),%stack_temp)
+	__(movq catch_frame.rsp(%temp0),%arg_x)
+        __(movq %stack_temp,rcontext(tcr.xframe))
+	__(movq catch_frame.foreign_sp(%temp0),%stack_temp)
+        __(movq %stack_temp,rcontext(tcr.foreign_sp))        
+	/* Discard the catch frame, so we can build a temp frame   */
+	__(movq -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))
+        __(movq %imm1,rcontext(tcr.next_tsp))
+	/* tsp overhead, nargs, throw count, ra0   */
+	__(dnode_align(%nargs_q,(tsp_frame.fixed_overhead+(3*node_size)),%imm0))
+	__(TSP_Alloc_Var(%imm0,%imm1))
+
+	__(movq %nargs_q,(%imm1))
+	__(movq %ra0,node_size(%imm1))
+	__(movq %mm1,node_size*2(%imm1))
+	__(leaq node_size*3(%imm1),%imm1)
+	__(jmp local_label(_nthrowv_tpushtest))
+local_label(_nthrowv_tpushloop):
+	__(movq -node_size(%save1),%temp0)
+	__(subq $node_size,%save1)
+	__(movq %temp0,(%imm1))
+	__(addq $node_size,%imm1)
+local_label(_nthrowv_tpushtest):
+	__(subl $node_size,%nargs)
+	__(jns local_label(_nthrowv_tpushloop))
+	__(pop %xfn)
+	__ifndef([TCR_IN_GPR])
+	__(pop %save3)
+	__endif
+	__(pop %save2)
+	__(pop %save1)
+	__(pop %save0)
+	__(movq %arg_x,%rsp)
+/* Ready to call cleanup code. set up tra, jmp to %xfn   */
+	__(leaq local_label(_nthrowv_called_cleanup)(%rip),%ra0)
+        __(push %ra0)
+	__(movb $0,rcontext(tcr.unwinding))
+	__(jmp *%xfn)
+__(tra(local_label(_nthrowv_called_cleanup)))
+
+	__(movb $1,rcontext(tcr.unwinding))
+	__(movq rcontext(tcr.save_tsp),%imm1)
+	__(movq tsp_frame.data_offset+(0*node_size)(%imm1),%nargs_q)
+	__(movq tsp_frame.data_offset+(1*node_size)(%imm1),%ra0)
+	__(movq tsp_frame.data_offset+(2*node_size)(%imm1),%mm1)
+	__(movq %nargs_q,%imm0)
+	__(addq $tsp_frame.fixed_overhead+(node_size*3),%imm1)
+	__(jmp local_label(_nthrowv_tpoptest))
+local_label(_nthrowv_tpoploop):	
+	__(push (%imm1))
+	__(addq $node_size,%imm1)
+local_label(_nthrowv_tpoptest):	
+	__(subq $node_size,%imm0)
+	__(jns local_label(_nthrowv_tpoploop))
+	__(movq rcontext(tcr.save_tsp),%imm1)
+	__(movq (%imm1),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))
+        __(movq %imm1,rcontext(tcr.next_tsp))
+	__(movd %mm1,%imm0)
+	__(jmp local_label(_nthrowv_nextframe))
+local_label(_nthrowv_done):
+	__(movb $0,rcontext(tcr.unwinding))
+	__(check_pending_interrupt(%imm0))
+local_label(_nthrowv_return):	
+	__(jmp *%ra0)	
+_endsubp(nthrowvalues)
+
+/* This is a (slight) optimization.  When running an unwind-protect,  */
+/* save the single value and the throw count in the tstack frame.  */
+/* Note that this takes a single value in arg_z.  */
+	
+_spentry(nthrow1value)
+	__(movb $1,rcontext(tcr.unwinding))
+local_label(_nthrow1v_nextframe):
+	__(subq $fixnumone,%imm0)
+	__(js local_label(_nthrow1v_done))
+	__(movd %imm0,%mm1)
+	__(movq rcontext(tcr.catch_top),%temp0)
+	__(movq catch_frame.link(%temp0),%imm1)
+	__(movq catch_frame.db_link(%temp0),%imm0)
+	__(movq %imm1,rcontext(tcr.catch_top))
+	__(cmpq %imm0,rcontext(tcr.db_link))
+	__(jz local_label(_nthrow1v_dont_unbind))
+	__(push %ra0)
+	__(leaq local_label(_nthrow1v_back_from_unbind)(%rip),%ra0)
+        __(push %ra0)
+	__(jmp _SPunbind_to)
+__(tra(local_label(_nthrow1v_back_from_unbind)))
+
+	__(pop %ra0)
+local_label(_nthrow1v_dont_unbind):
+	__(cmpb $unbound_marker,catch_frame.catch_tag(%temp0))
+	__(je local_label(_nthrow1v_do_unwind))
+/* A catch frame.  If the last one, restore context from there.   */
+	__(movd %mm1,%imm0)
+	__(testq %imm0,%imm0)	/* last catch frame ?   */
+	__(jne local_label(_nthrow1v_skip))
+	__(movq catch_frame.xframe(%temp0),%save0)
+	__(movq %save0,rcontext(tcr.xframe))
+	__(leaq (%rsp,%nargs_q),%save1)
+	__(movq catch_frame.xframe(%temp0),%save0)
+	__(movq %save0,rcontext(tcr.xframe))
+	__(movq catch_frame.rsp(%temp0),%rsp)
+	__(movq catch_frame.rbp(%temp0),%rbp)
+	__ifndef([TCR_IN_GPR])
+	__(movq catch_frame._save3(%temp0),%save3)
+	__endif
+	__(movq catch_frame._save2(%temp0),%save2)
+	__(movq catch_frame._save1(%temp0),%save1)
+	__(movq catch_frame._save0(%temp0),%save0)
+	__(movq catch_frame.foreign_sp(%temp0),%stack_temp)
+        __(movq %stack_temp,rcontext(tcr.foreign_sp))        
+local_label(_nthrow1v_skip):	
+	__(movq -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))
+        __(movq %imm1,rcontext(tcr.next_tsp))        
+	__(movd %mm1,%imm0)
+	__(jmp local_label(_nthrow1v_nextframe))
+local_label(_nthrow1v_do_unwind):
+	
+/* This is harder, but not as hard (not as much BLTing) as the  */
+/* multiple-value case.  */
+	
+	__(movq catch_frame.xframe(%temp0),%save0)
+	__(movq %save0,rcontext(tcr.xframe))
+	__(movq catch_frame._save0(%temp0),%save0)
+	__(movq catch_frame._save1(%temp0),%save1)
+	__(movq catch_frame._save2(%temp0),%save2)
+	__ifndef([TCR_IN_GPR])
+	__(movq catch_frame._save3(%temp0),%save3)
+	__endif
+	__(movq catch_frame.pc(%temp0),%xfn)
+	__(movq catch_frame.rbp(%temp0),%rbp)
+	__(movq catch_frame.rsp(%temp0),%rsp)
+	__(movq catch_frame.foreign_sp(%temp0),%stack_temp)
+        __(movq %stack_temp,rcontext(tcr.foreign_sp))        
+	/* Discard the catch frame, so we can build a temp frame   */
+	__(movq -(tsp_frame.fixed_overhead+fulltag_misc)(%temp0),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))
+        __(movq %imm1,rcontext(tcr.next_tsp))        
+	__(TSP_Alloc_Fixed((3*node_size),%imm1))
+	__(addq $tsp_frame.fixed_overhead,%imm1)
+	__(movq %ra0,(%imm1))
+	__(movq %mm1,node_size*1(%imm1))
+	__(movq %arg_z,node_size*2(%imm1))
+/* Ready to call cleanup code. set up tra, jmp to %xfn   */
+	__(leaq local_label(_nthrow1v_called_cleanup)(%rip),%ra0)
+	__(movb $0,rcontext(tcr.unwinding))
+        __(push %ra0)
+	__(jmp *%xfn)
+__(tra(local_label(_nthrow1v_called_cleanup)))
+
+	__(movb $1,rcontext(tcr.unwinding))
+	__(movq rcontext(tcr.save_tsp),%imm1)
+	__(movq tsp_frame.data_offset+(0*node_size)(%imm1),%ra0)
+	__(movq tsp_frame.data_offset+(1*node_size)(%imm1),%mm1)
+	__(movq tsp_frame.data_offset+(2*node_size)(%imm1),%arg_z)
+
+	__(movq (%imm1),%imm1)
+        __(movq %imm1,rcontext(tcr.save_tsp))
+        __(movq %imm1,rcontext(tcr.next_tsp))        
+	__(movd %mm1,%imm0)
+	__(jmp local_label(_nthrow1v_nextframe))
+local_label(_nthrow1v_done):
+	__(movb $0,rcontext(tcr.unwinding))
+	__(check_pending_interrupt(%imm0))
+local_label(_nthrow1v_return):	
+	__(jmp *%ra0)	
+_endsubp(nthrow1value)
+
+/* This never affects the symbol's vcell   */
+/* Non-null symbol in arg_y, new value in arg_z           */
+	
+_spentry(bind)
+	__(movq symbol.binding_index(%arg_y),%temp0)
+	__(cmpq rcontext(tcr.tlb_limit),%temp0)
+	__(jb 0f)
+	__(push %temp0)
+	__(tlb_too_small())
+0:	__(testq %temp0,%temp0)
+	__(jz 9f)
+	__(movq rcontext(tcr.tlb_pointer),%temp1)
+	__(push (%temp1,%temp0))
+	__(push %temp0)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(movq %arg_z,(%temp1,%temp0))
+	__(jmp *%ra0)
+9:	
+	__(movq %arg_y,%arg_z)
+	__(movq $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)	
+_endsubp(bind)
+
+/* arg_z = symbol: bind it to its current value  */
+	
+_spentry(bind_self)
+	__(movq symbol.binding_index(%arg_z),%temp0)
+	__(cmpq rcontext(tcr.tlb_limit),%temp0)
+	__(jb 0f)
+	__(push %temp0)
+	__(tlb_too_small())
+0:	__(testq %temp0,%temp0)
+	__(jz 9f)
+	__(movq rcontext(tcr.tlb_pointer),%temp1)
+	__(cmpb $no_thread_local_binding_marker,(%temp0,%temp1))
+	__(jz 2f)
+	__(push (%temp1,%temp0))
+	__(push %temp0)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(jmp *%ra0)
+2:	__(movq symbol.vcell(%arg_z),%arg_y)
+	__(push (%temp1,%temp0))
+	__(push %temp0)
+	__(push rcontext(tcr.db_link))
+	__(movq %arg_y,(%temp1,%temp0))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(jmp *%ra0)
+9:	__(movq $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(bind_self)
+
+_spentry(bind_nil)
+	__(movq symbol.binding_index(%arg_z),%temp0)
+	__(cmpq rcontext(tcr.tlb_limit),%temp0)
+	__(jb 0f)
+	__(push %temp0)
+	__(tlb_too_small())
+0:	__(testq %temp0,%temp0)
+	__(jz 9f)
+	__(movq rcontext(tcr.tlb_pointer),%temp1)
+	__(push (%temp1,%temp0))
+	__(push %temp0)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(movq $nil_value,(%temp1,%temp0))
+	__(jmp *%ra0)
+9:	__(movq $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(bind_nil)
+
+_spentry(bind_self_boundp_check)
+	__(movq symbol.binding_index(%arg_z),%temp0)
+	__(cmpq rcontext(tcr.tlb_limit),%temp0)
+	__(jb 0f)
+	__(push %temp0)
+	__(tlb_too_small())
+0:	__(testq %temp0,%temp0)
+	__(jz 9f)
+	__(movq rcontext(tcr.tlb_pointer),%temp1)
+	__(cmpb $no_thread_local_binding_marker,(%temp1,%temp0))
+	__(je 2f)
+	__(cmpb $unbound_marker,(%temp1,%temp0))
+	__(je 8f)
+	__(push (%temp1,%temp0))
+	__(push %temp0)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(jmp *%ra0)
+2:	__(movq symbol.vcell(%arg_z),%arg_y)
+	__(cmpb $unbound_marker,%arg_y_b)
+	__(jz 8f)
+	__(push (%temp1,%temp0))
+	__(push %temp0)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(movq %arg_y,(%temp1,%temp0))
+	__(jmp *%ra0)
+8:	__(push %ra0)
+        __(uuo_error_reg_unbound(Rarg_z))
+	
+9:	__(movq $XSYMNOBIND,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(bind_self_boundp_check)
+
+_spentry(conslist)
+	__(movl $nil_value,%arg_z_l)
+	__(testl %nargs,%nargs)
+	__(jmp 2f)
+1:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%nargs)
+2:	__(jnz 1b)
+	__(jmp *%ra0)		
+_endsubp(conslist)
+
+/* do list*: last arg in arg_z, all others pushed, nargs set to #args pushed.  */
+/* Cons, one cons cell at at time.  Maybe optimize this later.  */
+	
+_spentry(conslist_star)
+	__(testl %nargs,%nargs)
+	__(jmp 2f)
+1:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%nargs)
+2:	__(jnz 1b)
+	__(jmp *%ra0)		
+_endsubp(conslist_star)
+
+/* We always have to create a tsp frame (even if nargs is 0), so the compiler   */
+/* doesn't get confused.   */
+_spentry(stkconslist)
+	__(movq %nargs_q,%imm1)
+	__(addq %imm1,%imm1)
+	__(movl $nil_value,%arg_z_l)
+	__(dnode_align(%imm1,tsp_frame.fixed_overhead,%imm1))
+	__(TSP_Alloc_Var(%imm1,%imm0))
+	__(addq $fulltag_cons,%imm0)
+	__(testl %nargs,%nargs)
+	__(jmp 2f)
+1:	__(pop %temp0)
+	__(_rplaca(%imm0,%temp0))
+	__(_rplacd(%imm0,%arg_z))
+	__(movq %imm0,%arg_z)
+	__(add $cons.size,%imm0)
+	__(subl $node_size,%nargs)
+2:	__(jne 1b)
+	__(jmp *%ra0)
+_endsubp(stkconslist)
+
+/* do list*: last arg in arg_z, all others vpushed,   */
+/*	nargs set to #args vpushed.  */
+	
+_spentry(stkconslist_star)
+	__(movq %nargs_q,%imm1)
+	__(addq %imm1,%imm1)
+	__(dnode_align(%imm1,tsp_frame.fixed_overhead,%imm1))
+	__(TSP_Alloc_Var(%imm1,%imm0))
+	__(addq $fulltag_cons,%imm0)
+	__(testl %nargs,%nargs)
+	__(jmp 2f)
+1:	__(pop %temp0)
+	__(_rplaca(%imm0,%temp0))
+	__(_rplacd(%imm0,%arg_z))
+	__(movq %imm0,%arg_z)
+	__(addq $cons.size,%imm0)
+	__(subl $node_size,%nargs)
+2:	__(jne 1b)
+	__(jmp *%ra0)
+_endsubp(stkconslist_star)
+
+/* Make a stack-consed simple-vector out of the NARGS objects   */
+/*	on top of the vstack; return it in arg_z.  */
+	
+_spentry(mkstackv)
+	__(dnode_align(%nargs_q,tsp_frame.fixed_overhead+node_size,%imm1))
+	__(TSP_Alloc_Var(%imm1,%temp0))
+	__(movl %nargs,%imm0_l)
+	__(shlq $(num_subtag_bits-fixnumshift),%imm0)
+	__(movb $subtag_simple_vector,%imm0_b)
+	__(movq %imm0,(%temp0))
+	__(leaq fulltag_misc(%temp0),%arg_z)
+	__(testl %nargs,%nargs)
+	__(leaq misc_data_offset(%arg_z,%nargs_q),%imm1)
+	__(jmp 2f)
+1:	__(pop -node_size(%imm1))
+	__(subl $node_size,%nargs)
+	__(leaq -node_size(%imm1),%imm1)
+2:	__(jne 1b)
+	__(jmp *%ra0)	
+_endsubp(mkstackv)
+
+	
+        .globl C(egc_write_barrier_start)
+C(egc_write_barrier_start):
+/*  */
+/* The function pc_luser_xp() - which is used to ensure that suspended threads  */
+/* are suspended in a GC-safe way - has to treat these subprims (which implement  */
+/* the EGC write-barrier) specially.  Specifically, a store that might introduce  */
+/* an intergenerational reference (a young pointer stored in an old object) has  */
+/* to "memoize" that reference by setting a bit in the global "refbits" bitmap.  */
+/* This has to happen atomically, and has to happen atomically wrt GC.  */
+
+/* Note that updating a word in a bitmap is itself not atomic, unless we use  */
+/* interlocked loads and stores.  */
+
+
+
+/* For RPLACA and RPLACD, things are fairly simple: regardless of where we are  */
+/* in the function, we can do the store (even if it's already been done) and  */
+/* calculate whether or not we need to set the bit out-of-line.  (Actually  */
+/* setting the bit needs to be done atomically, unless we're sure that other  */
+/* threads are suspended.)  */
+/* We can unconditionally set the suspended thread's RIP to the return address.  */
+
+	
+_spentry(rplaca)
+        .globl C(egc_rplaca)
+C(egc_rplaca):
+        __(rcmpq(%arg_z,%arg_y))
+	__(_rplaca(%arg_y,%arg_z))
+        __(ja 1f)
+0:      __(repret)
+1:      __(movq %arg_y,%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
+        __(jae 0b)
+        __(ref_global(refbits,%temp0))
+        __(xorb $63,%imm0_b)
+        __(lock)
+        __(btsq %imm0,(%temp0))
+        __(ret)
+_endsubp(rplaca)
+
+_spentry(rplacd)
+        .globl C(egc_rplacd)
+C(egc_rplacd):          
+        __(rcmpq(%arg_z,%arg_y))
+	__(_rplacd(%arg_y,%arg_z))
+        __(ja 1f)
+0:      __(repret)
+1:      __(movq %arg_y,%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
+        __(jae 0b)
+        __(ref_global(refbits,%temp0))
+        __(xorb $63,%imm0_b)
+        __(lock)
+        __(btsq %imm0,(%temp0))
+        __(ret)
+_endsubp(rplacd)
+
+/* Storing into a gvector can be handled the same way as storing into a CONS.  */
+
+
+_spentry(gvset)
+        .globl C(egc_gvset)
+C(egc_gvset):
+        __(rcmpq(%arg_z,%arg_x))
+	__(movq %arg_z,misc_data_offset(%arg_x,%arg_y))
+        __(ja 1f)
+0:      __(repret)
+1:      __(lea misc_data_offset(%arg_x,%arg_y),%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
+        __(jae 0b)
+        __(ref_global(refbits,%temp0))
+        __(xorb $63,%imm0_b)
+        __(lock) 
+        __(btsq %imm0,(%temp0))
+        __(ret)                
+_endsubp(gvset)
+
+/* This is a special case of storing into a gvector: if we need to  */
+/* memoize the store, record the address of the hash-table vector  */
+/* in the refmap, as well.  */
+        
+
+_spentry(set_hash_key)
+        .globl C(egc_set_hash_key)
+C(egc_set_hash_key):  
+        __(rcmpq(%arg_z,%arg_x))
+	__(movq %arg_z,misc_data_offset(%arg_x,%arg_y))
+        __(ja 1f)
+0:      __(repret)
+1:      __(lea misc_data_offset(%arg_x,%arg_y),%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
+        __(jae 0b)
+        __(ref_global(refbits,%temp0))
+        __(xorb $63,%imm0_b)
+        __(lock)
+        __(btsq %imm0,(%temp0))
+        /* Now memoize the address of the hash vector   */
+        __(movq %arg_x,%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(xorb $63,%imm0_b)
+        __(lock)
+        __(btsq %imm0,(%temp0))
+        __(ret)                
+_endsubp(set_hash_key)
+
+/* This is a little trickier: if this is interrupted, we need to know  */
+/* whether or not the STORE-CONDITIONAL (cmpxchgq) has won or not.    */
+/* If we're interrupted   before the PC has reached the "success_test" label,   */
+/* repeat (luser the PC back to store_node_conditional_retry.)  If we're at that  */
+/* label with the Z flag set, we won and (may) need to memoize.  */
+
+_spentry(store_node_conditional)
+        .globl C(egc_store_node_conditional)
+C(egc_store_node_conditional):
+	__(unbox_fixnum(%temp0,%imm1))
+        .globl C(egc_store_node_conditional_retry)
+C(egc_store_node_conditional_retry):      
+0:	__(movq (%arg_x,%imm1),%temp1)
+	__(cmpq %arg_y,%temp1)
+	__(movq %temp1,%imm0)
+	__(jne 3f)
+	__(lock)
+        __(cmpxchgq %arg_z,(%arg_x,%imm1))
+        .globl C(egc_store_node_conditional_success_test)
+C(egc_store_node_conditional_success_test):
+	__(jne 0b)
+        __(lea (%arg_x,%imm1),%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
+        __(ref_global(refbits,%temp1))
+        __(jae 2f)
+        __(xorb $63,%imm0_b)
+        __(lock)
+        __(btsq %imm0,(%temp1))
+	.globl C(egc_store_node_conditional_success_end)
+C(egc_store_node_conditional_success_end):
+2:      __(movl $t_value,%arg_z_l)
+	__(ret)
+3:	__(movl $nil_value,%arg_z_l)
+	__(ret)
+_endsubp(store_node_conditional)
+				
+	_spentry(set_hash_key_conditional)
+        .globl C(egc_set_hash_key_conditional)
+C(egc_set_hash_key_conditional):
+        .globl C(egc_set_hash_key_conditional_retry)
+C(egc_set_hash_key_conditional_retry):          
+	__(unbox_fixnum(%temp0,%imm1))
+0:	__(movq (%arg_x,%imm1),%temp1)
+	__(cmpq %arg_y,%temp1)
+	__(movq %temp1,%imm0)
+	__(jne 3f)
+	__(lock)
+        __(cmpxchgq %arg_z,(%arg_x,%imm1))
+        .globl C(egc_set_hash_key_conditional_success_test)
+C(egc_set_hash_key_conditional_success_test):
+	__(jne 0b)
+        __(lea (%arg_x,%imm1),%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
+        __(ref_global(refbits,%temp1))
+        __(jae 2f)
+        __(xorb $63,%imm0_b)
+        __(lock)
+        __(btsq %imm0,(%temp1))
+        /* Now memoize the address of the hash vector   */
+        __(movq %arg_x,%imm0)
+        __(subq lisp_global(ref_base),%imm0)
+        __(shrq $dnode_shift,%imm0)
+        __(xorb $63,%imm0_b)
+        __(lock)
+        __(btsq %imm0,(%temp1))
+        .globl C(egc_write_barrier_end)
+C(egc_write_barrier_end):
+2:      __(movl $t_value,%arg_z_l)
+	__(ret)
+3:	__(movl $nil_value,%arg_z_l)
+	__(ret)
+_endsubp(set_hash_key_conditional)
+
+	
+
+
+_spentry(setqsym)
+	__(btq $sym_vbit_const,symbol.flags(%arg_y))
+	__(jae _SPspecset)
+	__(movq %arg_y,%arg_z)
+	__(movq $XCONST,%arg_y)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+_endsubp(setqsym)
+
+_spentry(progvsave)
+	/* Error if arg_z isn't a proper list.  That's unlikely,  */
+	/* but it's better to check now than to crash later.  */
+	
+	__(compare_reg_to_nil(%arg_z))
+	__(movq %arg_z,%arg_x)	/* fast   */
+	__(movq %arg_z,%temp1)	/* slow   */
+	__(je 9f)		/* Null list is proper   */
+0:
+	__(extract_lisptag(%arg_x,%imm0))
+	__(cmpb $tag_list,%imm0_b)
+	__(jne 8f)
+	__(compare_reg_to_nil(%arg_x))
+	__(je 9f)
+	__(_cdr(%arg_x,%temp0))	/* (null (cdr fast)) ?   */
+	__(compare_reg_to_nil(%temp0))
+	__(je 9f)
+	__(extract_lisptag(%temp0,%imm0))
+	__(cmpb $tag_list,%imm0_b)
+	__(jne 8f)
+	__(_cdr(%temp0,%arg_x))
+	__(_cdr(%temp1,%temp1))
+	__(cmpq %temp1,%arg_x)
+	__(jne 0b)
+
+8:	__(movq $XIMPROPERLIST,%arg_y)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+9:	/* Whew 	  */
+
+        /* Next, determine the length of arg_y.  We   */
+	/* know that it's a proper list.   */
+	__(movq $-fixnumone,%imm0)
+	__(movq %arg_y,%arg_x)
+1:	__(compare_reg_to_nil(%arg_x))
+	__(_cdr(%arg_x,%arg_x))
+	__(leaq fixnumone(%imm0),%imm0)
+	__(jne 1b)
+	
+	/* imm0 is now (boxed) triplet count.  */
+	/* Determine word count, add 1 (to align), and make room.  */
+	/*  if count is 0, make an empty tsp frame and exit   */
+	__(testq %imm0,%imm0)
+	__(jne 2f)
+	__(TSP_Alloc_Fixed(2*node_size,%imm0))
+	__(ret)
+2:	__(movq %imm0,%imm1)
+	__(add %imm1,%imm1)
+	__(add %imm0,%imm1)
+	__(dnode_align(%imm1,tsp_frame.fixed_overhead+node_size,%imm1))
+	__(TSP_Alloc_Var(%imm1,%temp0))
+	__(movq %imm0,(%temp0))
+	__(movq rcontext(tcr.db_link),%temp1)
+3:	__(movl $unbound_marker,%temp0_l)
+	__(compare_reg_to_nil(%arg_z))
+	__(cmovneq cons.car(%arg_z),%temp0)
+	__(cmovneq cons.cdr(%arg_z),%arg_z)
+	__(_car(%arg_y,%arg_x))
+	__(_cdr(%arg_y,%arg_y))
+	__(movq symbol.binding_index(%arg_x),%arg_x)
+	__(cmp rcontext(tcr.tlb_limit),%arg_x)
+	__(jb 4f)
+	__(push %arg_x)
+	__(tlb_too_small())
+4:	__(movq rcontext(tcr.tlb_pointer),%imm0)
+	__(subq $binding.size,%imm1)
+	__(compare_reg_to_nil(%arg_y))
+	__(movq %arg_x,binding.sym(%imm1))
+	__(push (%imm0,%arg_x))
+	__(pop binding.val(%imm1))
+	__(movq %temp0,(%imm0,%arg_x))
+	__(movq %temp1,binding.link(%imm1))
+	__(movq %imm1,%temp1)
+	__(jne 3b)
+	__(movq %temp1,rcontext(tcr.db_link))
+	__(ret)
+_endsubp(progvsave)
+
+/* Allocate node objects on the temp stack, immediate objects on the foreign  */
+/* stack. (The caller has to know which stack to discard a frame from.)  */
+/* %arg_y = boxed element-count, %arg_z = boxed subtype  */
+	
+_spentry(stack_misc_alloc)
+	__(movq $~(((1<<56)-1)<<fixnumshift),%temp0)
+	__(testq %temp0,%arg_y)
+	__(jne local_label(stack_misc_alloc_not_u56))
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(movq %arg_y,%temp0)
+	__(shl $num_subtag_bits-fixnumshift,%temp0)
+	__(orq %temp0,%imm0)		/* %imm0 now = header   */
+	__(movb $fulltagmask,%imm1_b)
+	__(andb %imm0_b,%imm1_b)
+	__(cmpb $fulltag_nodeheader_0,%imm1_b)
+	__(je local_label(stack_misc_alloc_node))
+	__(cmpb $fulltag_nodeheader_1,%imm1_b)
+	__(je local_label(stack_misc_alloc_node))
+	__(cmpb $ivector_class_64_bit,%imm1_b)
+	__(jz local_label(stack_misc_alloc_64))
+	__(cmpb $ivector_class_32_bit,%imm1_b)
+	__(jz local_label(stack_misc_alloc_32))
+	__(unbox_fixnum(%arg_y,%imm1))
+	/* ivector_class_other_bit: 16, 8, or 1 ...   */
+	__(cmpb $subtag_bit_vector,%imm0_b)
+	__(jne local_label(stack_misc_alloc_8))
+	__(addq $7,%imm1)
+	__(shrq $3,%imm1)
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_8):	
+	__(cmpb $subtag_simple_base_string,%imm0_b)
+	__(jb local_label(stack_misc_alloc_16))
+	__(unbox_fixnum(%arg_y,%imm1))
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_16):	
+	__(unbox_fixnum(%arg_y,%imm1))
+	__(shlq %imm1)
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_32):
+	/* 32-bit ivector   */
+	__(unbox_fixnum(%arg_y,%imm1))
+	__(shlq $2,%imm1)
+	__(jmp local_label(stack_misc_alloc_alloc_ivector))
+local_label(stack_misc_alloc_64):
+	/* 64-bit ivector 	  */
+	__(movq %arg_y,%imm1)
+local_label(stack_misc_alloc_alloc_ivector):	
+	__(dnode_align(%imm1,tsp_frame.fixed_overhead+node_size,%imm1))
+	__(cmpq $tstack_alloc_limit,%imm1)
+	__(ja local_label(stack_misc_alloc_heap_alloc_ivector))
+        __ifdef([WINDOWS])
+         __(windows_cstack_probe(%imm1,%temp0))
+        __endif
+        __(movq rcontext(tcr.foreign_sp),%stack_temp) 
+	__(movd %stack_temp,%temp1)
+        __(subq %imm1,rcontext(tcr.foreign_sp))
+        __(movq rcontext(tcr.foreign_sp),%temp0)
+0:	__(movapd %fpzero,-dnode_size(%temp1))
+	__(subq $dnode_size,%temp1)
+	__(cmpq %temp1,%temp0)
+	__(jnz 0b)	
+	__(movq %stack_temp,(%temp0))
+        __(movq %rbp,csp_frame.save_rbp(%temp0))
+	__(movq %imm0,csp_frame.fixed_overhead(%temp0))
+	__(leaq csp_frame.fixed_overhead+fulltag_misc(%temp0),%arg_z)
+	__(ret)
+local_label(stack_misc_alloc_heap_alloc_ivector):
+        __(movq rcontext(tcr.foreign_sp),%imm1)
+        __(subq $dnode_size,rcontext(tcr.foreign_sp))
+        __(movq rcontext(tcr.foreign_sp),%imm0)
+	__(movq %imm1,(%imm0))
+	__(jmp _SPmisc_alloc)	
+local_label(stack_misc_alloc_node):
+	__(movq %arg_y,%imm1)
+	__(dnode_align(%imm1,tsp_frame.fixed_overhead+node_size,%imm1))
+	__(cmpq $tstack_alloc_limit,%imm1)
+	__(ja local_label(stack_misc_alloc_heap_alloc_gvector))
+	__(TSP_Alloc_Var(%imm1,%temp0))
+	__(movq %imm0,(%temp0))
+	__(leaq fulltag_misc(%temp0),%arg_z)
+	__(ret)
+local_label(stack_misc_alloc_heap_alloc_gvector):	
+	__(TSP_Alloc_Fixed(0,%imm0))
+	__(jmp _SPmisc_alloc)	
+		
+local_label(stack_misc_alloc_not_u56):				
+	__(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_56))	
+_endsubp(stack_misc_alloc)
+
+/* subtype (boxed, of course) is pushed, followed by nargs bytes worth of   */
+/* initial-contents.  Note that this can be used to cons any type of initialized   */
+/* node-header'ed misc object (symbols, closures, ...) as well as vector-like   */
+/* objects.   */
+_spentry(gvector)
+        __(subl $node_size,%nargs)
+	__(movq (%rsp,%nargs_q),%imm0)	/* boxed subtype   */
+	__(sarq $fixnumshift,%imm0)
+	__(movq %nargs_q,%imm1)
+	__(shlq $num_subtag_bits-word_shift,%imm1)
+	__(orq %imm1,%imm0)
+	__(dnode_align(%nargs_q,node_size,%imm1))
+	__(Misc_Alloc(%arg_z))
+	__(movq %nargs_q,%imm1)
+	__(jmp 2f)
+1:	__(movq %temp0,misc_data_offset(%arg_z,%imm1))
+2:	__(subq $node_size,%imm1)
+	__(pop %temp0)	/* Note the intentional fencepost:  */
+			/* discard the subtype as well.  */
+	__(jge 1b)
+	__(jmp *%ra0)
+_endsubp(gvector)
+
+_spentry(mvpass)
+	__(hlt)
+_endsubp(mvpass)
+
+
+
+_spentry(nthvalue)
+	__(hlt)
+_endsubp(nthvalue)
+
+_spentry(values)
+        __(movq (%temp0),%ra0)
+	__(ref_global(ret1val_addr,%imm1))
+	__(cmpq %imm1,%ra0)
+	__(movl $nil_value,%arg_z_l)
+	__(je 0f)
+	__(testl %nargs,%nargs)
+	__(cmovneq -node_size(%rsp,%nargs_q),%arg_z)
+	__(movq %temp0,%rsp)
+	__(ret)
+0:	__(movq 8(%temp0),%ra0)
+        __(addq $2*node_size,%temp0)
+	__(lea (%rsp,%nargs_q),%imm0)
+	__(jmp 2f)
+1:	__(subq $node_size,%imm0)
+	__(movq (%imm0),%temp1)
+	__(subq $node_size,%temp0)
+	__(movq %temp1,(%temp0))
+2:	__(cmpq %imm0,%rsp)
+	__(jne 1b)
+	__(movq %temp0,%rsp)
+	__(jmp *%ra0)	
+_endsubp(values)
+
+_spentry(default_optional_args)
+	__(hlt)
+_endsubp(default_optional_args)
+
+_spentry(opt_supplied_p)
+	__(hlt)
+_endsubp(opt_supplied_p)
+
+_spentry(lexpr_entry)
+	__(hlt)
+_endsubp(lexpr_entry)
+	
+_spentry(heap_rest_arg)
+	__(push_argregs())
+        __(movq %next_method_context,%arg_y)
+	__(movl %nargs,%imm1_l)
+	__(testl %imm1_l,%imm1_l)
+	__(movl $nil_value,%arg_z_l)
+	__(jmp 2f)
+	.p2align 4
+1:	__(pop %temp1)
+	__(Cons(%temp1,%arg_z,%arg_z))
+	__(subl $node_size,%imm1_l)
+2:	__(jg 1b)
+	__(push %arg_z)
+        __(movq %arg_y,%next_method_context)
+	__(jmp *%ra0)		
+_endsubp(heap_rest_arg)
+
+/* %imm0 contains the number of fixed args ; make an &rest arg out of the others   */
+_spentry(req_heap_rest_arg)
+	__(push_argregs())
+        __(movq %next_method_context,%arg_y)
+	__(movl %nargs,%imm1_l)
+	__(subl %imm0_l,%imm1_l)
+	__(movl $nil_value,%arg_z_l)
+	__(jmp 2f)
+	.p2align 4
+1:	__(pop %temp1)
+	__(Cons(%temp1,%arg_z,%arg_z))
+	__(subl $node_size,%imm1_l)
+2:	__(jg 1b)
+	__(push %arg_z)
+        __(movq %arg_y,%next_method_context)
+	__(jmp *%ra0)		
+_endsubp(req_heap_rest_arg)
+
+/* %imm0 bytes of stuff has already been pushed	  */
+/* make an &rest arg out of any others   */
+_spentry(heap_cons_rest_arg)
+	__(movl %nargs,%imm1_l)
+	__(subl %imm0_l,%imm1_l)
+        __(movq %next_method_context,%arg_y)
+	__(movl $nil_value,%arg_z_l)
+	__(jmp 2f)
+	.p2align 4
+1:	__(pop %temp1)
+	__(Cons(%temp1,%arg_z,%arg_z))
+	__(subl $node_size,%imm1_l)
+2:	__(jg 1b)
+	__(push %arg_z)
+        __(movq %arg_y,%next_method_context)
+	__(jmp *%ra0)		
+_endsubp(heap_cons_rest_arg)
+
+_spentry(simple_keywords)
+	__(xorl %imm0_l,%imm0_l)
+	__(push_argregs())
+	__(jmp _SPkeyword_bind)
+_endsubp(simple_keywords)
+
+_spentry(keyword_args)
+	__(push_argregs())
+	__(jmp _SPkeyword_bind)
+_endsubp(keyword_args)
+
+/* There are %nargs words of arguments on the stack; %imm0 contains the number  */
+/* of non-keyword args pushed.  It's possible that we never actually got  */
+/* any keyword args, which would make things much simpler.   */
+
+/* On entry, temp1 contains a fixnum with bits indicating whether   */
+/* &allow-other-keys and/or &rest was present in the lambda list.  */
+/* Once we get here, we can use the arg registers.  */
+
+define([keyword_flags_aok_bit],[fixnumshift])
+define([keyword_flags_unknown_keys_bit],[fixnumshift+1])
+define([keyword_flags_rest_bit],[fixnumshift+2])
+define([keyword_flags_seen_aok_bit],[fixnumshift+3])        
+	
+_spentry(keyword_bind)
+	__(movl %nargs,%imm1_l)
+	__(subq %imm0,%imm1)
+	__(jbe local_label(no_keyword_values))
+	__(btq $word_shift,%imm1)
+	__(jnc local_label(even))
+	__(movl $nil_value,%arg_z_l)
+	__(movq %imm1,%nargs_q)
+	__(testl %nargs,%nargs)
+	__(jmp 1f)
+0:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%nargs)
+1:	__(jnz 0b)
+	__(movl $XBADKEYS,%arg_y_l)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+	/* Now that we're sure that we have an even number of keywords and values  */
+	/* (in %imm1), copy all pairs to the temp stack   */
+local_label(even):
+	/* Get the keyword vector into arg_x, and its length into arg_y.  */
+	__(movl function_data_offset(%fn),%imm0_l)
+	__(movq function_data_offset(%fn,%imm0,node_size),%arg_x)
+	__(vector_length(%arg_x,%arg_y))
+        __(testq %arg_y,%arg_y)
+        __(jne 1f)
+        __(btq $keyword_flags_aok_bit,%temp1)
+        __(jnc 1f)
+
+        __(btq $keyword_flags_rest_bit,%temp1)
+        __(jc 0f)
+        __(addq %imm1,%rsp)
+0:      
+        __(jmp *%ra0)
+1:      
+       	__(lea tsp_frame.fixed_overhead(%imm1),%arg_z)
+	__(TSP_Alloc_Var(%arg_z,%imm0))
+2:	__(subq $node_size,%arg_z)
+	__(pop (%arg_z))
+	__(cmpq %arg_z,%imm0)
+	__(jne 2b)
+	/* Push arg_y pairs of NILs.   */
+	__(movq %arg_y,%imm0)
+	__(jmp 4f)
+3:	__(push $nil_value)
+	__(push $nil_value)
+4:	__(subq $fixnumone,%arg_y)
+	__(jge 3b)
+	/* Push the %saveN registers, so that we can use them in this loop   */
+	/* Also, borrow %arg_y for a bit */
+	__(push %arg_y)
+	__(push %save2)
+	__(push %save1)
+	__(push %save0)
+	__(leaq 4*node_size(%rsp,%imm0,2),%save0)
+	/* %save0 points to the 0th value/supplied-p pair   */
+	__(leaq (%arg_z,%imm1),%save1)
+	/* %save1 is the end of the provided keyword/value pairs (the old %tsp).   */
+	__(movq %imm0,%save2)
+	/* %save2 is the length of the keyword vector   */
+5:	__(movq (%arg_z),%arg_y)	/* %arg_y is current keyword   */
+	__(xorl %imm0_l,%imm0_l)
+        __(cmpq $nrs.kallowotherkeys,%arg_y)
+        __(jne local_label(next_keyvect_entry))
+        __(btsq $keyword_flags_seen_aok_bit,%temp1)
+        __(jc local_label(next_keyvect_entry))
+        __(cmpb $fulltag_nil,node_size(%arg_z))
+	__(je local_label(next_keyvect_entry))
+	__(btsq $keyword_flags_aok_bit,%temp1)
+	__(jmp local_label(next_keyvect_entry))
+6:	__(cmpq misc_data_offset(%arg_x,%imm0),%arg_y)
+	__(jne 7f)
+	/* Got a match; have we already seen this keyword ?   */
+	__(negq %imm0)
+	__(cmpb $fulltag_nil,-node_size*2(%save0,%imm0,2))
+	__(jne 9f)	/* already seen keyword, ignore this value   */
+	__(movq node_size(%arg_z),%arg_y)
+	__(movq %arg_y,-node_size(%save0,%imm0,2))
+	__(movl $t_value,-node_size*2(%save0,%imm0,2))
+	__(jmp 9f)
+7:	__(addq $node_size,%imm0)
+local_label(next_keyvect_entry):	
+	__(cmpq %imm0,%save2)
+	__(jne 6b)
+	/* Didn't match anything in the keyword vector. Is the keyword  */
+	/* :allow-other-keys ?   */
+	__(cmpq $nrs.kallowotherkeys,%arg_y)
+	__(je 9f)               /* :allow-other-keys is never "unknown" */
+8:	__(btsq $keyword_flags_unknown_keys_bit,%temp1)
+9:	__(addq $dnode_size,%arg_z)
+	__(cmpq %arg_z,%save1)
+	__(jne 5b)
+	__(pop %save0)
+	__(pop %save1)
+	__(pop %save2)
+	__(pop %arg_y)
+	/* If the function takes an &rest arg, or if we got an unrecognized  */
+	/* keyword and don't allow that, copy the incoming keyword/value  */
+	/* pairs from the temp stack back to the value stack   */
+	__(btq $keyword_flags_rest_bit,%temp1)
+	__(jc 1f)
+	__(btq $keyword_flags_unknown_keys_bit,%temp1)
+	__(jnc 0f)
+	__(btq $keyword_flags_aok_bit,%temp1)
+	__(jnc 1f)
+	/* pop the temp frame   */
+0:	__(discard_temp_frame(%imm1))
+	__(jmp *%ra0)
+	/* Copy the keyword/value pairs from the tsp back to sp, either because  */
+	/* the function takes an &rest arg or because we need to signal an  */
+	/* "unknown keywords" error   */
+1:	__(movq rcontext(tcr.save_tsp),%arg_z)
+	__(mov (%arg_z),%arg_y)
+	__(jmp 3f)
+2:	__(push (%arg_z))
+	__(push node_size(%arg_z))
+3:	__(addq $dnode_size,%arg_z)
+	__(cmpq %arg_z,%arg_y)
+	__(jne 2b)
+	__(discard_temp_frame(%imm0))
+	__(btq $keyword_flags_unknown_keys_bit,%temp1)
+	__(jnc 9f)
+	__(btq $keyword_flags_aok_bit,%temp1)
+	__(jc 9f)
+	/* Signal an "unknown keywords" error   */
+	__(movq %imm1,%nargs_q)
+	__(testl %nargs,%nargs)
+        __(movl $nil_value,%arg_z_l)
+	__(jmp 5f)
+4:	__(pop %arg_y)
+	__(Cons(%arg_y,%arg_z,%arg_z))
+	__(subl $node_size,%nargs)
+5:	__(jnz 4b)
+	__(movl $XBADKEYS,%arg_y_l)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+9:	__(jmp *%ra0)
+	
+/* No keyword values were provided.  Access the keyword vector (which is the 0th  */
+/*  constant in %fn), determine its length N, and push N	pairs of NILs.   */
+/* N could be 0 ...  */
+	
+local_label(no_keyword_values):		
+	__(movl function_data_offset(%fn),%imm0_l)
+	__(movq function_data_offset(%fn,%imm0,node_size),%arg_x)
+	__(movl $nil_value,%arg_z_l)
+	__(vector_length(%arg_x,%arg_y))
+	__(jmp 1f)
+0:	__(push %arg_z)
+	__(push %arg_z)
+1:	__(subq $fixnumone,%arg_y)
+	__(jge 0b)
+	__(jmp *%ra0)		
+_endsubp(keyword_bind)
+
+
+
+_spentry(ksignalerr)
+	__(movq $nrs.errdisp,%fname)
+	__(jump_fname)	
+_endsubp(ksignalerr)
+
+_spentry(stack_rest_arg)
+	__(xorl %imm0_l,%imm0_l)
+	__(push_argregs())
+	__(jmp _SPstack_cons_rest_arg)
+_endsubp(stack_rest_arg)
+
+_spentry(req_stack_rest_arg)
+	__(push_argregs())
+	__(jmp _SPstack_cons_rest_arg)
+_endsubp(req_stack_rest_arg)
+
+_spentry(stack_cons_rest_arg)
+	__(movl %nargs,%imm1_l)
+	__(subl %imm0_l,%imm1_l)
+	__(movl $nil_value,%arg_z_l)
+	__(jle 2f)	/* empty list ; make an empty TSP frame   */
+	__(addq %imm1,%imm1)
+	__(cmpq $(tstack_alloc_limit-dnode_size),%imm1)
+	__(ja 3f)	/* make empty frame, then heap-cons   */
+	__(dnode_align(%imm1,tsp_frame.fixed_overhead,%imm0))
+	__(TSP_Alloc_Var(%imm0,%temp1))
+	__(addq $fulltag_cons,%temp1)
+1:	__(pop %arg_x)
+	__(_rplacd(%temp1,%arg_z))
+	__(_rplaca(%temp1,%arg_x))
+	__(movq %temp1,%arg_z)
+	__(addq $cons.size,%temp1)
+	__(subq $dnode_size,%imm1)
+	__(jne 1b)
+	__(push %arg_z)
+	__(jmp *%ra0)
+	
+/* Length 0, make empty frame  */
+	
+2:
+	__(TSP_Alloc_Fixed(0,%temp1))
+	__(push %arg_z)
+	__(jmp *%ra0)
+	
+/* Too big to stack-cons, but make an empty frame before heap-consing  */
+	
+3:		
+	__(TSP_Alloc_Fixed(0,%temp1))
+	__(jmp _SPheap_cons_rest_arg)
+_endsubp(stack_cons_rest_arg)
+
+
+
+_spentry(getxlong)
+_endsubp(getxlong)
+
+/* Have to be a little careful here: the caller may or may not have pushed  */
+/*   an empty frame, and we may or may not have needed one.  We can't easily  */
+/*   tell whether or not a frame will be needed (if the caller didn't reserve  */
+/*   a frame, whether or not we need one depends on the length of the list  */
+/*   in arg_z.  So, if the caller didn't push a frame, we do so ; once everything's  */
+/*   been spread, we discard the reserved frame (regardless of who pushed it)  */
+/*   if all args fit in registers.   */
+_spentry(spreadargz)
+	__(testl %nargs,%nargs)
+	__(jne 0f)
+	__(push $reserved_frame_marker)
+	__(push $reserved_frame_marker)
+0:	__(movq %arg_z,%arg_y)	/* save in case of error   */
+	__(xorl %imm0_l,%imm0_l)
+	__(compare_reg_to_nil(%arg_z))
+	__(je 2f)
+1:	__(extract_fulltag(%arg_z,%imm1))
+	__(cmpb $fulltag_cons,%imm1_b)
+	__(jne 9f)
+	__(addw $node_size,%imm0_w)
+        __(_car(%arg_z,%arg_x))
+	__(_cdr(%arg_z,%arg_z))
+        __(js 8f)
+	__(compare_reg_to_nil(%arg_z))
+	__(push %arg_x)
+	__(jne 1b)
+2:	__(addw %imm0_w,%nargs_w)
+	__(jne 4f)
+3:	__(addq $2*node_size,%rsp)
+	__(jmp *%ra0)
+4:	__(cmpl $1*node_size,%nargs)
+	__(pop %arg_z)
+	__(je 3b)
+	__(cmpl $2*node_size,%nargs)
+	__(pop %arg_y)
+	__(je 3b)
+	__(cmpl $3*node_size,%nargs)
+	__(pop %arg_x)
+	__(je 3b)
+	__(jmp *%ra0)
+/* Discard everything that's been pushed already, complain   */
+
+8:     	__(lea (%rsp,%imm0),%rsp)
+	__(movq %arg_y,%arg_z)	/* recover original   */
+	__(movq $XTMINPS,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+/* Discard everything that's been pushed already, complain   */
+9:	__(lea (%rsp,%imm0),%rsp)
+	__(movq %arg_y,%arg_z)	/* recover original   */
+	__(movq $XNOSPREAD,%arg_y)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endsubp(spreadargz)
+
+/* Caller built it's own frame when it was entered.  If all outgoing args  */
+/* are in registers, we can discard that frame; otherwise, we copy outgoing  */
+/* relative to it and restore %rbp/%ra0   */
+_spentry(tfuncallgen)
+	__(cmpl $nargregs*node_size,%nargs)
+	__(jbe 9f)
+	__(lea -nargregs*node_size(%rsp,%nargs_q),%imm0)
+	__(xorl %imm1_l,%imm1_l)
+	/* We can use %ra0 as a temporary here, since the real return address  */
+	/* is on the stack   */
+0:	__(movq -node_size(%imm0),%ra0)
+	__(movq %ra0,-node_size(%rbp,%imm1))
+	__(subq $node_size,%imm0)
+	__(subq $node_size,%imm1)
+	__(cmpq %imm0,%rsp)
+	__(jne 0b)
+	__(lea (%rbp,%imm1),%rsp)
+	__(movq 8(%rbp),%ra0)
+	__(movq (%rbp),%rbp)
+        __(pushq %ra0)
+	__(do_funcall())
+        /* All args in regs; exactly the same as the tfuncallvsp case   */
+9:		
+	__(leave)
+	__(do_funcall())
+_endsubp(tfuncallgen)
+
+/* Some args were pushed; move them down in the frame   */
+_spentry(tfuncallslide)
+	__(lea -nargregs*node_size(%rsp,%nargs_q),%imm0)
+	__(xorl %imm1_l,%imm1_l)
+	/* We can use %ra0 as a temporary here, since the real return address  */
+	/* is on the stack   */
+0:	__(movq -node_size(%imm0),%ra0)
+	__(movq %ra0,-node_size(%rbp,%imm1))
+	__(subq $node_size,%imm0)
+	__(subq $node_size,%imm1)
+	__(cmpq %imm0,%rsp)
+	__(jne 0b)
+	__(lea (%rbp,%imm1),%rsp)
+	__(movq 8(%rbp),%ra0)
+	__(movq (%rbp),%rbp)
+        __(push %ra0)
+	__(do_funcall())	
+_endsubp(tfuncallslide)
+
+/* No args were pushed; recover saved context & do funcall 	  */
+_spentry(tfuncallvsp)
+	__(leave)
+	__(do_funcall())
+_endsubp(tfuncallvsp)
+
+_spentry(tcallsymgen)
+	__(cmpl $nargregs*node_size,%nargs)
+	__(jbe 9f)
+	__(lea -nargregs*node_size(%rsp,%nargs_q),%imm0)
+	__(xorl %imm1_l,%imm1_l)
+	/* We can use %ra0 as a temporary here, since the real return address  */
+	/* is on the stack   */
+0:	__(movq -node_size(%imm0),%ra0)
+	__(movq %ra0,-node_size(%rbp,%imm1))
+	__(subq $node_size,%imm0)
+	__(subq $node_size,%imm1)
+	__(cmpq %imm0,%rsp)
+	__(jne 0b)
+	__(lea (%rbp,%imm1),%rsp)
+	__(movq 8(%rbp),%ra0)
+	__(movq (%rbp),%rbp)
+        __(pushq %ra0)
+	__(jump_fname())
+/* All args in regs; exactly the same as the tcallsymvsp case   */
+9:		
+	__(leave)
+	__(jump_fname())
+_endsubp(tcallsymgen)
+
+_spentry(tcallsymslide)
+	__(lea -nargregs*node_size(%rsp,%nargs_q),%imm0)
+	__(xorl %imm1_l,%imm1_l)
+	/* We can use %ra0 as a temporary here, since the real return address  */
+	/* is on the stack   */
+0:	__(movq -node_size(%imm0),%ra0)
+	__(movq %ra0,-node_size(%rbp,%imm1))
+	__(subq $node_size,%imm0)
+	__(subq $node_size,%imm1)
+	__(cmpq %imm0,%rsp)
+	__(jne 0b)
+	__(lea (%rbp,%imm1),%rsp)
+	__(movq 8(%rbp),%ra0)
+	__(movq 0(%rbp),%rbp)
+        __(pushq %ra0)
+	__(jump_fname())
+_endsubp(tcallsymslide)
+
+_spentry(tcallsymvsp)
+	__(leave)
+	__(jump_fname())
+_endsubp(tcallsymvsp)
+
+_spentry(tcallnfngen)
+	__(cmpl $nargregs*node_size,%nargs)
+	__(jbe 9f)
+	__(lea -nargregs*node_size(%rsp,%nargs_q),%imm0)
+	__(xorl %imm1_l,%imm1_l)
+	/* We can use %ra0 as a temporary here, since the real return address  */
+	/* is on the stack   */
+0:	__(movq -node_size(%imm0),%ra0)
+	__(movq %ra0,-node_size(%rbp,%imm1))
+	__(subq $node_size,%imm0)
+	__(subq $node_size,%imm1)
+	__(cmpq %imm0,%rsp)
+	__(jne 0b)
+	__(movq %temp0,%fn)
+	__(lea (%rbp,%imm1),%rsp)
+	__(movq lisp_frame.savera0(%rbp),%ra0)
+	__(movq lisp_frame.backlink(%rbp),%rbp)
+        __(pushq %ra0)
+	__(jmp *%fn)
+/* All args in regs; exactly the same as the tcallnfnvsp case   */
+9:		
+	__(movq %temp0,%fn)
+	__(leave)
+	__(jmp *%fn)
+_endsubp(tcallnfngen)
+
+_spentry(tcallnfnslide)
+	__(lea -nargregs*node_size(%rsp,%nargs_q),%imm0)
+	__(xorl %imm1_l,%imm1_l)
+	/* We can use %ra0 as a temporary here, since the real return address  */
+	/* is on the stack   */
+0:	__(movq -node_size(%imm0),%ra0)
+	__(movq %ra0,-node_size(%rbp,%imm1))
+	__(subq $node_size,%imm0)
+	__(subq $node_size,%imm1)
+	__(cmpq %imm0,%rsp)
+	__(jne 0b)
+	__(movq %temp0,%fn)
+	__(lea (%rbp,%imm1),%rsp)
+	__(movq lisp_frame.savera0(%rbp),%ra0)
+	__(movq lisp_frame.backlink(%rbp),%rbp)
+        __(pushq %ra0)
+	__(jmp *%fn)
+_endsubp(tcallnfnslide)
+
+_spentry(tcallnfnvsp)
+	__(movq %temp0,%fn)
+	__(leave)
+	__(jmp *%fn)
+_endsubp(tcallnfnvsp)
+
+
+/* Make a "raw" area on the foreign stack, stack-cons a macptr to point to it,   */
+/*   and return the macptr.  Size (in bytes, boxed) is in arg_z on entry; macptr  */
+/*   in arg_z on exit.   */
+_spentry(makestackblock)
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
+	__(cmpq $tstack_alloc_limit,%imm0)
+	__(jae 1f)
+        __ifdef([WINDOWS])
+         __(windows_cstack_probe(%imm0,%arg_z))
+        __endif
+        __(movq rcontext(tcr.foreign_sp),%imm1)
+        __(subq %imm0,rcontext(tcr.foreign_sp))
+        __(movq rcontext(tcr.foreign_sp),%arg_z)
+	__(movq %imm1,(%arg_z))
+        __(movq %rbp,csp_frame.save_rbp(%arg_z))
+	__(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
+	__(movq $macptr_header,tsp_frame.fixed_overhead(%arg_z))
+	__(addq $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
+	__(movq %imm0,macptr.address(%arg_z))
+	__(movsd %fpzero,macptr.domain(%arg_z))
+	__(movsd %fpzero,macptr.type(%arg_z))
+	__(ret)
+1:	__(movq rcontext(tcr.foreign_sp),%imm1)
+        __(subq $dnode_size,rcontext(tcr.foreign_sp))
+        __(movq rcontext(tcr.foreign_sp),%imm0)
+	__(movq %imm1,(%imm0))
+        __(movq %rbp,csp_frame.save_rbp(%imm0))
+	__(set_nargs(1))
+	__(movq $nrs.new_gcable_ptr,%fname)
+	__(jump_fname())
+_endsubp(makestackblock)
+
+_spentry(makestackblock0)
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(dnode_align(%imm0,tsp_frame.fixed_overhead+macptr.size,%imm0))
+	__(cmpq $tstack_alloc_limit,%imm0)
+	__(jae 9f)
+        __ifdef([WINDOWS])
+         __(windows_cstack_probe(%imm0,%arg_z))
+        __endif        
+        __(movq rcontext(tcr.foreign_sp),%imm1)
+        __(subq %imm0,rcontext(tcr.foreign_sp))
+        __(movq rcontext(tcr.foreign_sp),%arg_z)
+	__(movq %imm1,(%arg_z))
+        __(movq %rbp,csp_frame.save_rbp(%arg_z))
+	__(lea macptr.size+tsp_frame.fixed_overhead(%arg_z),%imm0)
+	__(movq $macptr_header,tsp_frame.fixed_overhead(%arg_z))
+	__(addq $fulltag_misc+tsp_frame.fixed_overhead,%arg_z)
+	__(movq %imm0,macptr.address(%arg_z))
+	__(movsd %fpzero,macptr.domain(%arg_z))
+	__(movsd %fpzero,macptr.type(%arg_z))
+	__(jmp 2f)
+1:	__(movapd %fpzero,(%imm0))
+	__(addq $dnode_size,%imm0)
+2:	__(cmpq %imm0,%imm1)
+	__(jne 1b)		
+	__(repret)
+9:	__(movq rcontext(tcr.foreign_sp),%imm1)
+        __(subq $dnode_size,rcontext(tcr.foreign_sp))
+        __(movq rcontext(tcr.foreign_sp),%imm0)
+	__(movq %imm1,(%imm0))
+        __(movq %rbp,csp_frame.save_rbp(%imm0))
+	__(set_nargs(1))
+	__(movq $nrs.new_gcable_ptr,%fname)
+	__(jump_fname())
+_endsubp(makestackblock0)
+
+_spentry(makestacklist)
+        __(movq $((1<<63)|fixnummask),%imm0)
+        __(testq %imm0,%arg_y)
+        __(jne 9f)
+	__(movq %arg_y,%imm0)
+	__(addq %imm0,%imm0)
+	__(rcmpq(%imm0,$tstack_alloc_limit))
+	__(movl $nil_value,%temp1_l) 
+	__(jae 2f)
+	__(addq $tsp_frame.fixed_overhead,%imm0)
+	__(TSP_Alloc_Var(%imm0,%temp0))
+	__(addq $fulltag_cons,%temp0)
+	__(jmp 1f)
+0:	__(_rplaca(%temp0,%arg_z))
+	__(_rplacd(%temp0,%temp1))
+	__(movq %temp0,%temp1)
+	__(addq $cons.size,%temp0)
+1:	__(subq $fixnumone,%arg_y)
+	__(jge 0b)
+	__(movq %temp1,%arg_z)
+	__(ret)
+2:	__(TSP_Alloc_Fixed(0,%imm0))
+	__(jmp 4f)
+3:	__(Cons(%arg_z,%temp1,%temp1))
+4:	__(subq $fixnumone,%arg_y)				
+	__(jge 3b)
+	__(movq %temp1,%arg_z)
+	__(ret)
+9:      __(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte))
+_endsubp(makestacklist)
+
+/* subtype (boxed) vpushed before initial values. (Had better be a   */
+/* node header subtag.) Nargs set to count of things vpushed. 	  */
+_spentry(stkgvector)
+	__(lea -fixnum_one(%nargs_q),%imm0)
+	__(lea (%rsp,%imm0),%arg_x)
+	__(movq %imm0,%arg_y)
+	__(shlq $num_subtag_bits-fixnumshift,%imm0)
+	__(movq (%arg_x), %imm1)
+	__(shrq $fixnumshift,%imm1)
+	__(orq %imm1,%imm0)	/* imm0 = header, %arg_y = unaligned size   */
+	__(dnode_align(%arg_y,(tsp_frame.fixed_overhead+node_size),%imm1))
+	__(TSP_Alloc_Var(%imm1,%arg_z))
+	__(movq %imm0,(%arg_z))
+	__(addq $fulltag_misc,%arg_z)
+	__(lea -node_size(%nargs_q),%imm0)
+	__(jmp 2f)
+1:	__(pop misc_data_offset(%arg_z,%imm0))
+2:	__(subq $node_size,%imm0)
+	__(jge 1b)
+	__(addq $node_size,%rsp)
+	__(jmp *%ra0)	
+_endsubp(stkgvector)
+
+_spentry(misc_alloc)
+	__(movq $~(((1<<56)-1)<<fixnumshift),%imm0)
+	__(testq %imm0,%arg_y)
+	__(jne local_label(misc_alloc_not_u56))
+	__(unbox_fixnum(%arg_z,%imm0))
+	__(movq %arg_y,%temp0)
+	__(shl $num_subtag_bits-fixnumshift,%temp0)
+	__(orq %temp0,%imm0)		/* %imm0 now = header   */
+	__(movb $fulltagmask,%imm1_b)
+	__(andb %imm0_b,%imm1_b)
+	__(cmpb $fulltag_nodeheader_0,%imm1_b)
+	__(je local_label(misc_alloc_64))
+	__(cmpb $fulltag_nodeheader_1,%imm1_b)
+	__(je local_label(misc_alloc_64))
+	__(cmpb $ivector_class_64_bit,%imm1_b)
+	__(jz local_label(misc_alloc_64))
+	__(cmpb $ivector_class_32_bit,%imm1_b)
+	__(jz local_label(misc_alloc_32))
+	__(unbox_fixnum(%arg_y,%imm1))
+	/* ivector_class_other_bit: 16, 8, or 1 ...   */
+	__(cmpb $subtag_bit_vector,%imm0_b)
+	__(jne local_label(misc_alloc_8))
+	__(addq $7,%imm1)
+	__(shrq $3,%imm1)
+	__(jmp local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_8):	
+	__(cmpb $subtag_simple_base_string,%imm0_b)
+	__(jae local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_16):	
+	__(shlq %imm1)
+	__(jmp local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_32):
+	/* 32-bit ivector   */
+	__(unbox_fixnum(%arg_y,%imm1))
+	__(shlq $2,%imm1)
+	__(jmp local_label(misc_alloc_alloc_vector))
+local_label(misc_alloc_64):
+	/* 64-bit ivector or gvector 	  */
+	__(movq %arg_y,%imm1)
+local_label(misc_alloc_alloc_vector):	
+	__(dnode_align(%imm1,node_size,%imm1))
+	__(Misc_Alloc(%arg_z))
+	__(ret)
+local_label(misc_alloc_not_u56):
+	__(uuo_error_reg_not_type(Rarg_y,error_object_not_unsigned_byte_56))
+_endsubp(misc_alloc)
+
+
+_startfn(C(destbind1))
+	/* Save entry %rsp in case of error   */
+	__(movd %rsp,%mm0)
+	/* Extract required arg count.   */
+	__(movzbl %nargs_b,%imm0_l)
+        __(testl %imm0_l,%imm0_l)
+	__(je local_label(opt))		/* skip if no required args   */
+local_label(req_loop):	
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(toofew))
+	__(extract_lisptag(%arg_reg,%imm1))
+	__(cmpb $tag_list,%imm1_b)
+	__(jne local_label(badlist))
+	__(subb $1,%imm0_b)
+	__(pushq cons.car(%arg_reg))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(jne local_label(req_loop))
+local_label(opt):	
+	__(movw %nargs_w,%imm0_w)
+	__(shrw $8,%imm0_w)
+	__(je local_label(rest_keys))
+	__(btl $initopt_bit,%nargs)
+	__(jc local_label(opt_supp))
+	/* 'simple' &optionals:	 no supplied-p, default to nil.   */
+local_label(simple_opt_loop):
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(default_simple_opt))
+	__(extract_lisptag(%arg_reg,%imm1))
+	__(cmpb $tag_list,%imm1_b)
+	__(jne local_label(badlist))
+	__(subb $1,%imm0_b)
+	__(pushq cons.car(%arg_reg))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(jne local_label(simple_opt_loop))
+	__(jmp local_label(rest_keys))
+local_label(default_simple_opt):
+	__(subb $1,%imm0_b)
+	__(pushq $nil_value)
+	__(jne local_label(default_simple_opt))
+	__(jmp local_label(rest_keys))
+local_label(opt_supp):
+	__(extract_lisptag(%arg_reg,%imm1))
+	__(compare_reg_to_nil(%arg_z))
+	__(je local_label(default_hard_opt))
+	__(cmpb $tag_list,%imm1_b)
+	__(jne local_label(badlist))
+	__(subb $1,%imm0_b)
+	__(pushq cons.car(%arg_reg))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(push $t_value)
+	__(jne local_label(opt_supp))
+	__(jmp local_label(rest_keys))
+local_label(default_hard_opt):
+	__(subb $1,%imm0_b)
+	__(push $nil_value)
+	__(push $nil_value)
+	__(jne local_label(default_hard_opt))	
+local_label(rest_keys):	
+	__(btl $restp_bit,%nargs)
+	__(jc local_label(have_rest))
+	__(btl $keyp_bit,%nargs)
+	__(jc local_label(have_keys))
+	__(compare_reg_to_nil(%arg_reg))
+	__(jne local_label(toomany))
+	__(jmp *%ra0)
+local_label(have_rest):
+	__(pushq %arg_reg)
+	__(btl $keyp_bit,%nargs)
+	__(jc local_label(have_keys))
+	__(jmp *%ra0)		
+	/* Ensure that arg_reg contains a proper,even-length list.  */
+	/* Insist that its length is <= 512 (as a cheap circularity check.)   */
+local_label(have_keys):
+	__(movw $256,%imm0_w)
+	__(movq %arg_reg,%arg_y)
+local_label(count_keys_loop):	
+	__(compare_reg_to_nil(%arg_y))
+	__(je local_label(counted_keys))
+	__(subw $1,%imm0_w)
+	__(jl local_label(toomany))
+	__(extract_lisptag(%arg_y,%imm1))
+	__(cmpb $tag_list,%imm1_b)
+	__(jne local_label(badlist))
+	__(_cdr(%arg_y,%arg_y))
+	__(extract_fulltag(%arg_y,%imm1))
+	__(cmpb $fulltag_cons,%imm1_b)
+	__(jne local_label(badlist))
+	__(_cdr(%arg_y,%arg_y))
+	__(jmp local_label(count_keys_loop))
+local_label(counted_keys):		
+	/* We've got a proper, even-length list of key/value pairs in  */
+	/* arg_reg. For each keyword var in the lambda-list, push a pair  */
+	/* of NILs on the vstack.   */
+	
+	__(movl %nargs,%imm1_l)
+	__(shrl $16,%imm1_l)
+	__(movzbl %imm1_b,%imm0_l)
+	__(movq %rsp,%arg_y)
+	__(jmp local_label(push_pair_test))	
+local_label(push_pair_loop):
+	__(push $nil_value)
+	__(push $nil_value)
+local_label(push_pair_test):	
+	__(subb $1,%imm1_b)
+	__(jge local_label(push_pair_loop))
+	/* Push the %saveN registers, so that we can use them in this loop   */
+	/* Also, borrow %arg_z */
+	__(push %save0)
+	__(push %save1)
+	__(push %save2)
+	__(push %arg_z)
+	/* save0 points to the 0th value/supplied-p pair   */
+	__(movq %arg_y,%save0)
+	/* save1 is the length of the keyword vector   */
+	__(vector_length(%arg_x,%save1))
+	/* save2 is the current keyword   */
+	/* arg_z is the value of the current keyword   */
+	__(xorl %imm0_l,%imm0_l)	/* count unknown keywords seen   */
+local_label(match_keys_loop):
+	__(compare_reg_to_nil(%arg_reg))
+	__(je local_label(matched_keys))
+	__(_car(%arg_reg,%save2))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(_car(%arg_reg,%arg_z))
+	__(_cdr(%arg_reg,%arg_reg))
+	__(xorl %arg_y_l,%arg_y_l)
+	__(jmp local_label(match_test))
+local_label(match_loop):
+	__(cmpq misc_data_offset(%arg_x,%arg_y),%save2)
+	__(je local_label(matched))
+	__(addq $node_size,%arg_y)
+local_label(match_test):
+	__(cmpq %arg_y,%save1)
+	__(jne local_label(match_loop))
+	/* No match.  Note unknown keyword, check for :allow-other-keys   */
+	__(addl $1,%imm0_l)
+	__(cmpq $nrs.kallowotherkeys,%save2)
+	__(jne local_label(match_keys_loop))
+	__(subl $1,%imm0_l)
+	__(btsl $seen_aok_bit,%nargs)
+	__(jc local_label(match_keys_loop))
+	/* First time we've seen :allow-other-keys.  Maybe set aok_bit.   */
+	__(compare_reg_to_nil(%arg_z))
+	__(je local_label(match_keys_loop))
+	__(btsl $aok_bit,%nargs)
+	__(jmp local_label(match_keys_loop))
+	/* Got a match.  Worry about :allow-other-keys here, too.   */
+local_label(matched):
+	__(negq %arg_y)
+	__(cmpb $fulltag_nil,-node_size*2(%save0,%arg_y,2))
+	__(jne local_label(match_keys_loop))
+	__(movq %arg_z,-node_size(%save0,%arg_y,2))
+	__(movl $t_value,-node_size*2(%save0,%arg_y,2))
+	__(cmpq $nrs.kallowotherkeys,%save2)
+	__(jne local_label(match_keys_loop))
+	__(btsl $seen_aok_bit,%nargs)
+	__(jnc local_label(match_keys_loop))
+	__(compare_reg_to_nil(%arg_z))
+	__(je local_label(match_keys_loop))
+	__(btsl $aok_bit,%nargs)
+	__(jmp local_label(match_keys_loop))
+local_label(matched_keys):		
+	__(pop %arg_z)
+	__(pop %save2)
+	__(pop %save1)
+	__(pop %save0)
+	__(testl %imm0_l,%imm0_l)
+	__(je local_label(keys_ok)) 
+	__(btl $aok_bit,%nargs)
+	__(jnc local_label(badkeys))
+local_label(keys_ok):	
+	__(jmp *%ra0)
+	/* Some unrecognized keywords.  Complain generically about   */
+	/* invalid keywords.   */
+local_label(badkeys):
+	__(movq $XBADKEYS,%arg_y)
+	__(jmp local_label(destructure_error))
+local_label(toomany):
+	__(movq $XCALLTOOMANY,%arg_y)
+	__(jmp local_label(destructure_error))
+local_label(toofew):
+	__(movq $XCALLTOOFEW,%arg_y)
+	__(jmp local_label(destructure_error))
+local_label(badlist):
+	__(movq $XCALLNOMATCH,%arg_y)
+	/* jmp local_label(destructure_error)   */
+local_label(destructure_error):
+	__(movd %mm0,%rsp)		/* undo everything done to the stack   */
+	__(movq %whole_reg,%arg_z)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jmp _SPksignalerr)
+_endfn(C(destbind1))	
+
+_spentry(macro_bind)
+	__(movq %arg_reg,%whole_reg)
+	__(extract_lisptag(%arg_reg,%imm0))
+	__(cmpb $tag_list,%imm0_b)
+	__(jne 1f)
+	__(_cdr(%arg_reg,%arg_reg))
+	__(jmp C(destbind1))
+1:	__(movq $XCALLNOMATCH,%arg_y)
+	__(movq %whole_reg,%arg_z)
+	__(set_nargs(2))
+        __(push %ra0)        
+	__(jmp _SPksignalerr)
+_endsubp(macro_bind)
+
+_spentry(destructuring_bind)
+	__(movq %arg_reg,%whole_reg)
+	__(jmp C(destbind1))
+_endsubp(destructuring_bind)
+
+_spentry(destructuring_bind_inner)
+	__(movq %arg_z,%whole_reg)
+	__(jmp C(destbind1))
+_endsubp(destructuring_bind_inner)
+
+	
+
+
+_spentry(vpopargregs)
+_endsubp(vpopargregs)
+
+/* If arg_z is an integer, return in imm0 something whose sign  */
+/* is the same as arg_z's.  If not an integer, error.   */
+_spentry(integer_sign)
+	__(testb $tagmask,%arg_z_b)
+	__(movq %arg_z,%imm0)
+	__(je 8f)
+	__(extract_typecode(%arg_z,%imm0))
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne 9f)
+	__(getvheader(%arg_z,%imm0))
+	__(shr $num_subtag_bits,%imm0)
+	__(movslq misc_data_offset-4(%arg_z,%imm0,4),%imm0)
+8:	__(repret)
+9:	__(uuo_error_reg_not_type(Rarg_z,error_object_not_integer))
+_endsubp(integer_sign)
+
+/* "slide" nargs worth of values up the stack.  IMM0 contains   */
+/* the difference between the current RSP and the target.   */
+_spentry(mvslide)
+	__(movl %nargs,%imm1_l)
+	__(lea (%rsp,%nargs_q),%temp0)
+	__(testq %imm1,%imm1)
+	__(lea (%temp0,%imm0),%imm0)
+	__(je 2f)
+1:	
+	__(subq $node_size,%temp0)
+	__(movq (%temp0),%temp1)
+	__(subq $node_size,%imm0)
+	__(movq %temp1,(%imm0))
+	__(subq $node_size,%imm1)
+	__(jne 1b)
+2:	__(movq %imm0,%rsp)
+	__(jmp *%ra0)	
+_endsubp(mvslide)
+
+_spentry(save_values)
+	__(movq rcontext(tcr.save_tsp),%imm1)
+/* common exit: nargs = values in this set, imm1 = ptr to tsp before call to save_values   */
+local_label(save_values_to_tsp):
+	__(movq rcontext(tcr.save_tsp),%arg_x)
+	__(dnode_align(%nargs_q,tsp_frame.fixed_overhead+(2*node_size),%imm0)) /* count, link   */
+	__(TSP_Alloc_Var(%imm0,%arg_z))
+	__(movq rcontext(tcr.save_tsp),%imm0)
+	__(movq %imm1,(%imm0))
+	__(movq %nargs_q,(%arg_z))
+	__(movq %arg_x,node_size(%arg_z))
+	__(leaq 2*node_size(%arg_z,%nargs_q),%arg_y)
+	__(leaq (%rsp,%nargs_q),%imm0)
+	__(cmpq %imm0,%rsp)
+	__(jmp 2f)
+1:	__(subq $node_size,%imm0)
+	__(movq (%imm0),%arg_z)
+	__(subq $node_size,%arg_y)
+	__(cmpq %imm0,%rsp)
+	__(movq %arg_z,(%arg_y))
+2:	__(jne 1b)
+	__(add %nargs_q,%rsp)
+	__(jmp *%ra0)			
+_endsubp(save_values)
+
+/* Add the multiple values that are on top of the vstack to the set  */
+/* saved in the top tsp frame, popping them off of the vstack in the  */
+/* process.  It is an error (a bad one) if the TSP contains something  */
+/* other than a previously saved set of multiple-values.  */
+/* Since adding to the TSP may cause a new TSP segment to be allocated,  */
+/* each add_values call adds another linked element to the list of  */
+/* values. This makes recover_values harder.   */
+_spentry(add_values)
+	__(testl %nargs,%nargs)
+	__(movq rcontext(tcr.save_tsp),%imm1)
+	__(movq (%imm1),%imm1)
+	__(jne local_label(save_values_to_tsp))
+	__(jmp *%ra0)
+_endsubp(add_values)
+
+/* push the values in the value set atop the sp, incrementing nargs.  */
+/* Discard the tsp frame; leave values atop the sp.   */
+	
+_spentry(recover_values)
+	/* First, walk the segments reversing the pointer to previous  */
+	/* segment pointers Can tell the end because that previous  */
+	/* segment pointer is the prev tsp pointer   */
+	__(movq rcontext(tcr.save_tsp),%temp1)
+	__(movq %temp1,%arg_x)	/* current segment   */
+	__(movq %temp1,%arg_y)	/* last segment   */
+	__(movq tsp_frame.backlink(%temp1),%arg_z)	/* previous tsp   */
+local_label(walkloop):
+	__(movq tsp_frame.fixed_overhead+node_size(%arg_x),%temp0)
+	__(cmpq %temp0,%arg_z)	/* last segment ?   */
+	__(movq %arg_y,tsp_frame.fixed_overhead+node_size(%arg_x))
+	__(movq %arg_x,%arg_y)	/* last segment <- current segment   */
+	__(movq %temp0,%arg_x)	/* current segment <- next segment   */
+	__(jne local_label(walkloop))
+
+	/* the final segment pointer is now in %arg_y  */
+	/* walk backwards, pushing values on the stack and incrementing %nargs   */
+local_label(pushloop):
+	__(movq tsp_frame.data_offset(%arg_y),%imm0)	/* nargs in segment   */
+	__(testq %imm0,%imm0)
+	__(leaq tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
+	__(leaq (%nargs_q,%imm0),%nargs_q)
+	__(jmp 2f)
+1:	__(pushq -node_size(%temp0))
+	__(subq $node_size,%temp0)
+	__(subq $fixnum_one,%imm0)
+2:	__(jne 1b)
+	__(cmpq %arg_y,%temp1)
+	__(movq tsp_frame.data_offset+node_size(%arg_y),%arg_y)
+	__(jne local_label(pushloop))
+	__(movq (%temp1),%temp1)
+        __(movq %temp1,rcontext(tcr.save_tsp))
+        __(movq %temp1,rcontext(tcr.next_tsp))        
+	__(jmp *%ra0)		
+_endsubp(recover_values)
+
+/* Exactly like recover_values, but it's necessary to reserve an outgoing  */
+/* frame if any values (which will be used as outgoing arguments) will  */
+/* wind up on the stack.  We can assume that %nargs contains 0 (and  */
+/* that no other arguments have been pushed) on entry.   */
+                
+_spentry(recover_values_for_mvcall)
+	/* First, walk the segments reversing the pointer to previous  */
+	/* segment pointers Can tell the end because that previous  */
+	/* segment pointer is the prev tsp pointer   */
+        __(xorl %nargs,%nargs)
+	__(movq rcontext(tcr.save_tsp),%temp1)
+	__(movq %temp1,%arg_x)	/* current segment   */
+	__(movq %temp1,%arg_y)	/* last segment   */
+	__(movq tsp_frame.backlink(%temp1),%arg_z)	/* previous tsp   */
+local_label(walkloop_mvcall):
+	__(movq tsp_frame.fixed_overhead+node_size(%arg_x),%temp0)
+        __(addq tsp_frame.data_offset(%arg_x),%nargs_q)	
+	__(cmpq %temp0,%arg_z)	/* last segment ?   */
+	__(movq %arg_y,tsp_frame.fixed_overhead+node_size(%arg_x))
+	__(movq %arg_x,%arg_y)	/* last segment <- current segment   */
+	__(movq %temp0,%arg_x)	/* current segment <- next segment   */
+	__(jne local_label(walkloop_mvcall))
+
+        __(cmpl $nargregs*node_size,%nargs)
+        __(jbe local_label(pushloop_mvcall))
+        __(push $reserved_frame_marker)
+        __(push $reserved_frame_marker)
+
+	/* the final segment pointer is now in %arg_y  */
+	/* walk backwards, pushing values on the stack and incrementing %nargs   */
+local_label(pushloop_mvcall):
+	__(movq tsp_frame.data_offset(%arg_y),%imm0)	/* nargs in segment   */
+	__(testq %imm0,%imm0)
+	__(leaq tsp_frame.data_offset+(2*node_size)(%arg_y,%imm0),%temp0)
+	__(jmp 2f)
+1:	__(pushq -node_size(%temp0))
+	__(subq $node_size,%temp0)
+	__(subq $fixnum_one,%imm0)
+2:	__(jne 1b)
+	__(cmpq %arg_y,%temp1)
+	__(movq tsp_frame.data_offset+node_size(%arg_y),%arg_y)
+	__(jne local_label(pushloop_mvcall))
+	__(movq (%temp1),%temp1)
+        __(movq %temp1,rcontext(tcr.save_tsp))
+        __(movq %temp1,rcontext(tcr.next_tsp))        
+	__(jmp *%ra0)		
+_endsubp(recover_values_for_mvcall)
+        				
+_spentry(reset)
+	__(hlt)
+_endsubp(reset)
+
+
+
+_spentry(misc_alloc_init)
+	__(push %rbp)
+	__(movq %rsp,%rbp)
+	__(push %arg_z)
+	__(movq %arg_y,%arg_z)
+	__(movq %arg_x,%arg_y)
+	__(lea local_label(misc_alloc_init_back)(%rip),%ra0)
+        __(push %ra0)
+	__(jmp _SPmisc_alloc)
+__(tra(local_label(misc_alloc_init_back)))
+	__(pop %arg_y)
+	__(leave)
+	__(movq $nrs.init_misc,%fname)
+	__(set_nargs(2))
+	__(jump_fname())	
+_endsubp(misc_alloc_init)
+
+_spentry(stack_misc_alloc_init)
+	__(push %rbp)
+	__(movq %rsp,%rbp)
+	__(push %arg_z)
+	__(movq %arg_y,%arg_z)
+	__(movq %arg_x,%arg_y)
+	__(lea local_label(stack_misc_alloc_init_back)(%rip),%ra0)
+        __(push %ra0)
+	__(jmp _SPstack_misc_alloc)
+__(tra(local_label(stack_misc_alloc_init_back)))
+	__(pop %arg_y)
+	__(leave)
+	__(movq $nrs.init_misc,%fname)
+	__(set_nargs(2))
+	__(jump_fname())	
+_endsubp(stack_misc_alloc_init)
+
+
+
+	.globl C(popj)
+_spentry(popj)
+C(popj):
+	__(leave)
+        __(ret)
+_endsubp(popj)
+
+
+
+_spentry(getu64)
+	__(movq $~(target_most_positive_fixnum << fixnumshift),%imm0)
+	__(testq %arg_z,%imm0)
+	__(movq %arg_z,%imm0)
+	__(jne 1f)
+	__(sarq $fixnumshift,%imm0)
+	__(ret)
+1:	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 9f)
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne 9f)
+	__(movq misc_header_offset(%arg_z),%imm0)
+	__(cmpq $three_digit_bignum_header,%imm0)
+	__(je 3f)
+	__(cmpq $two_digit_bignum_header,%imm0)
+	__(jne 9f)
+	__(movq misc_data_offset(%arg_z),%imm0)
+	__(testq %imm0,%imm0)
+	__(js 9f)
+	__(repret)
+3:	__(movq misc_data_offset(%arg_z),%imm0)
+	__(cmpl $0,misc_data_offset+8(%arg_z))
+	__(jne 9f)
+	__(repret)
+9:	__(uuo_error_reg_not_type(Rarg_z,error_object_not_u64))
+_endsubp(getu64)
+
+_spentry(gets64)
+	__(movq %arg_z,%imm0)
+	__(sarq $fixnumshift,%imm0)
+	__(testb $fixnummask,%arg_z_b)
+	__(je 8f)
+1:	__(movb %arg_z_b,%imm0_b)
+	__(andb $tagmask,%imm0_b)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 9f)
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(cmpb $subtag_bignum,%imm0_b)
+	__(jne 9f)
+	__(movq misc_header_offset(%arg_z),%imm0)
+	__(cmpq $two_digit_bignum_header,%imm0)
+	__(movq misc_data_offset(%arg_z),%imm0)
+	__(jne 9f)
+8:	__(repret)
+9:	__(uuo_error_reg_not_type(Rarg_z,error_object_not_s64))
+_endsubp(gets64)
+
+_spentry(makeu64)
+	__(movq %imm0,%imm1)
+	__(shlq $fixnumshift+1,%imm1)
+	__(movq %imm1,%arg_z)	/* Tagged as a fixnum, 2x    */
+	__(shrq $fixnumshift+1,%imm1)
+	__(shrq %arg_z)
+	__(cmpq %imm0,%imm1)
+	__(je 9f)
+	__(testq %imm0,%imm0)
+	__(movd %imm0,%mm0)
+	__(js 3f)
+	/* Make a 2-digit bignum.   */
+	__(movl $two_digit_bignum_header,%imm0_l)
+	__(movl $aligned_bignum_size(2),%imm1_l)
+	__(Misc_Alloc(%arg_z))
+	__(movq %mm0,misc_data_offset(%arg_z))
+	__(ret)
+3:	__(movl $three_digit_bignum_header,%imm0_l)
+	__(movl $aligned_bignum_size(3),%imm1_l)
+	__(Misc_Alloc(%arg_z))
+	__(movq %mm0,misc_data_offset(%arg_z))
+9:	__(repret)
+_endsubp(makeu64)
+
+/* on entry: arg_z = symbol.  On exit, arg_z = value (possibly  */
+/* unbound_marker), arg_y = symbol   */
+_spentry(specref)
+	__(movq symbol.binding_index(%arg_z),%imm0)
+	__(cmp rcontext(tcr.tlb_limit),%imm0)
+	__(movq rcontext(tcr.tlb_pointer),%imm1)
+	__(movq %arg_z,%arg_y)
+	__(jae 7f)
+	__(movq (%imm1,%imm0),%arg_z)
+	__(cmpb $no_thread_local_binding_marker,%arg_z_b)
+	__(jne 8f)
+7:	__(movq symbol.vcell(%arg_y),%arg_z)
+8:	__(repret)		
+_endsubp(specref)
+
+/* arg_y = special symbol, arg_z = new value.           */
+_spentry(specset)
+	__(movq symbol.binding_index(%arg_y),%imm0)
+	__(cmp rcontext(tcr.tlb_limit),%imm0)
+	__(movq rcontext(tcr.tlb_pointer),%imm1)
+	__(jae 1f)
+	__(movq (%imm1,%imm0),%arg_x)
+	__(cmpb $no_thread_local_binding_marker,%arg_x_b)
+	__(je 1f)
+	__(movq %arg_z,(%imm1,%imm0))
+	__(ret)
+1:	__(lea fulltag_misc-fulltag_symbol(%arg_y),%arg_x)
+	__(movq $1<<fixnumshift,%arg_y)
+	__(jmp _SPgvset)
+_endsubp(specset)
+
+_spentry(specrefcheck)
+	__(movq symbol.binding_index(%arg_z),%imm0)
+	__(cmp rcontext(tcr.tlb_limit),%imm0)
+	__(movq rcontext(tcr.tlb_pointer),%imm1)
+	__(movq %arg_z,%arg_y)
+	__(jae 7f)
+	__(movq (%imm1,%imm0),%arg_z)
+	__(cmpb $no_thread_local_binding_marker,%arg_z_b)
+	__(cmoveq symbol.vcell(%arg_y),%arg_z)
+	__(cmpb $unbound_marker,%arg_z_b)
+	__(je 9f)
+8:      __(repret)
+7:      __(cmpb $unbound_marker,symbol.vcell(%arg_y))
+        __(movq symbol.vcell(%arg_y),%arg_z)
+        __(je 9f)
+        __(repret)
+9:      __(uuo_error_reg_unbound(Rarg_y))
+_endsubp(specrefcheck)
+
+_spentry(restoreintlevel)
+_endsubp(restoreintlevel)
+
+_spentry(makes32)
+	__(hlt)
+_endsubp(makes32)
+
+_spentry(makeu32)
+	__(hlt)
+_endsubp(makeu32)
+
+_spentry(gets32)
+	__(hlt)
+_endsubp(gets32)
+
+_spentry(getu32)
+	__(hlt)
+_endsubp(getu32)
+
+
+_spentry(mvpasssym)
+_endsubp(mvpasssym)
+
+
+_spentry(unbind)
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(movq rcontext(tcr.tlb_pointer),%arg_x)
+	__(movq binding.sym(%imm1),%temp1)
+	__(movq binding.val(%imm1),%arg_y)
+	__(movq binding.link(%imm1),%imm1)
+	__(movq %arg_y,(%arg_x,%temp1))
+	__(movq %imm1,rcontext(tcr.db_link))
+	__(ret)	
+_endsubp(unbind)
+
+_spentry(unbind_n)
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(movq rcontext(tcr.tlb_pointer),%arg_x)
+1:		
+	__(movq binding.sym(%imm1),%temp1)
+	__(movq binding.val(%imm1),%arg_y)
+	__(movq binding.link(%imm1),%imm1)
+	__(movq %arg_y,(%arg_x,%temp1))
+	__(subq $1,%imm0)
+	__(jne 1b)
+	__(movq %imm1,rcontext(tcr.db_link))
+	__(ret)	
+_endsubp(unbind_n)
+
+_spentry(unbind_to)
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(movq rcontext(tcr.tlb_pointer),%arg_x)
+1:		
+	__(movq binding.sym(%imm1),%temp1)
+	__(movq binding.val(%imm1),%arg_y)
+	__(movq binding.link(%imm1),%imm1)
+	__(movq %arg_y,(%arg_x,%temp1))
+	__(cmpq %imm1,%imm0)
+	__(jne 1b)
+	__(movq %imm1,rcontext(tcr.db_link))
+	__(ret)	
+_endsubp(unbind_to)
+
+
+/* Bind CCL::*INTERRUPT-LEVEL* to 0.  If its value had been negative, check   */
+/* for pending interrupts after doing so.   */
+	
+_spentry(bind_interrupt_level_0)
+	__(movq rcontext(tcr.tlb_pointer),%temp1)
+	__(cmpq $0,INTERRUPT_LEVEL_BINDING_INDEX(%temp1))
+	__(push INTERRUPT_LEVEL_BINDING_INDEX(%temp1))
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(movq $0,INTERRUPT_LEVEL_BINDING_INDEX(%temp1))
+	__(js 1f)
+0:	__(jmp *%ra0)
+	/* Interrupt level was negative; interrupt may be pending   */
+1:	__(check_pending_enabled_interrupt(2f))
+2:	__(jmp *%ra0)
+_endsubp(bind_interrupt_level_0)
+	
+
+/* Bind CCL::*INTERRUPT-LEVEL* to the fixnum -1.  (This has the effect  */
+/* of disabling interrupts.)   */
+
+_spentry(bind_interrupt_level_m1)
+	__(movq rcontext(tcr.tlb_pointer),%temp1)
+	__(push INTERRUPT_LEVEL_BINDING_INDEX(%temp1))
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(movq $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%temp1))
+	__(jmp *%ra0)
+_endsubp(bind_interrupt_level_m1)
+
+/* Bind CCL::*INTERRUPT-LEVEL* to the value in arg_z.  If that value's 0,  */
+/* do what _SPbind_interrupt_level_0 does   */
+_spentry(bind_interrupt_level)
+	__(testq %arg_z,%arg_z)
+	__(movq rcontext(tcr.tlb_pointer),%temp1)
+	__(jz _SPbind_interrupt_level_0)
+	__(push INTERRUPT_LEVEL_BINDING_INDEX(%temp1))
+	__(push $INTERRUPT_LEVEL_BINDING_INDEX)
+	__(push rcontext(tcr.db_link))
+	__(movq %rsp,rcontext(tcr.db_link))
+	__(movq %arg_z,INTERRUPT_LEVEL_BINDING_INDEX(%temp1))
+	__(jmp *%ra0)
+_endsubp(bind_interrupt_level)
+
+/* Unbind CCL::*INTERRUPT-LEVEL*.  If the value changes from negative to  */
+/* non-negative, check for pending interrupts.    */
+	
+_spentry(unbind_interrupt_level)
+        __(btq $TCR_FLAG_BIT_PENDING_SUSPEND,rcontext(tcr.flags))
+	__(movq rcontext(tcr.db_link),%imm1)
+	__(movq rcontext(tcr.tlb_pointer),%arg_x)
+	__(movq INTERRUPT_LEVEL_BINDING_INDEX(%arg_x),%imm0)
+        __(jc 5f)
+0:      __(testq %imm0,%imm0)
+	__(movq binding.val(%imm1),%temp0)
+	__(movq binding.link(%imm1),%imm1)
+	__(movq %temp0,INTERRUPT_LEVEL_BINDING_INDEX(%arg_x))
+ 	__(movq %imm1,rcontext(tcr.db_link))
+	__(js 3f)
+2:	__(repret)
+3:	__(testq %temp0,%temp0)
+	__(js 2b)
+	__(check_pending_enabled_interrupt(4f))
+4:	__(repret)
+5:       /* Missed a suspend request; force suspend now if we're restoring
+          interrupt level to -1 or greater */
+        __(cmpq $-2<<fixnumshift,%imm0)
+        __(jne 0b)
+	__(movq binding.val(%imm1),%temp0)
+        __(cmpq %imm0,%temp0)
+        __(je 0b)
+        __(movq $-1<<fixnumshift,INTERRUPT_LEVEL_BINDING_INDEX(%arg_x))
+        __(suspend_now())
+        __(jmp 0b)
+_endsubp(unbind_interrupt_level)
+
+	
+_spentry(progvrestore)
+	__(movq rcontext(tcr.save_tsp),%imm0)
+	__(movq tsp_frame.backlink(%imm0),%imm0) /* ignore .SPnthrowXXX values frame   */
+	__(movq tsp_frame.data_offset(%imm0),%imm0)
+	__(shrq $fixnumshift,%imm0)
+	__(jne _SPunbind_n)
+	__(repret)
+_endsubp(progvrestore)
+	
+
+/* %arg_z <- %arg_y + %arg_z.  Do the fixnum case - including overflow -  */
+/* inline.  Call out otherwise.   */
+_spentry(builtin_plus)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(addq %arg_y,%arg_z)
+	__(jo C(fix_one_bit_overflow))
+	__(repret)
+1:	__(jump_builtin(_builtin_plus,2))
+_endsubp(builtin_plus)
+	
+
+/* %arg_z <- %arg_z - %arg_y.  Do the fixnum case - including overflow -  */
+/*  inline.  Call out otherwise.   */
+_spentry(builtin_minus)			
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(xchgq %arg_y,%arg_z)
+	__(subq %arg_y,%arg_z)
+	__(jo C(fix_one_bit_overflow))
+	__(repret)
+1:	__(jump_builtin(_builtin_minus,2))
+_endsubp(builtin_minus)
+
+/* %arg_z <- %arg_z * %arg_y.  Do the fixnum case - including overflow -  */
+/* inline.  Call out otherwise.   */
+_spentry(builtin_times)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 2f)
+	__(unbox_fixnum(%arg_z,%imm0))
+	/* 128-bit fixnum result in %imm1:%imm0. Overflow set if %imm1  */
+	/* is significant   */
+	__(imul %arg_y)
+	__(jo 1f)
+	__(mov %imm0,%arg_z)
+	__(ret)
+1:	__(unbox_fixnum(%arg_z,%imm0))
+	__(unbox_fixnum(%arg_y,%imm1))
+	__(imul %imm1)
+	__(jmp C(makes128))
+2:	__(jump_builtin(_builtin_times,2))
+_endsubp(builtin_times)
+
+_spentry(builtin_div)
+	__(jump_builtin(_builtin_div,2))
+
+/* %arg_z <- (= %arg_y %arg_z).	  */
+_spentry(builtin_eq)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpq(%arg_z,%arg_y))
+	__(condition_to_boolean(e,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_eq,2))
+_endsubp(builtin_eq)
+	
+/* %arg_z <- (/= %arg_y %arg_z).	  */
+_spentry(builtin_ne)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpq(%arg_z,%arg_y))
+	__(condition_to_boolean(ne,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_ne,2))
+_endsubp(builtin_ne)
+	
+/* %arg_z <- (> %arg_y %arg_z).	  */
+_spentry(builtin_gt)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpq(%arg_y,%arg_z))
+	__(condition_to_boolean(g,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_gt,2))
+_endsubp(builtin_gt)
+
+/* %arg_z <- (>= %arg_y %arg_z).	  */
+_spentry(builtin_ge)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpq(%arg_y,%arg_z))
+	__(condition_to_boolean(ge,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_ge,2))
+_endsubp(builtin_ge)
+	
+/* %arg_z <- (< %arg_y %arg_z).	  */
+_spentry(builtin_lt)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpq(%arg_y,%arg_z))
+	__(condition_to_boolean(l,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_lt,2))
+_endsubp(builtin_lt)
+
+/* %arg_z <- (<= %arg_y %arg_z).   */
+_spentry(builtin_le)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(rcmpq(%arg_y,%arg_z))
+	__(condition_to_boolean(le,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_le,2))
+_endsubp(builtin_le)
+
+_spentry(builtin_eql)
+	__(cmpq %arg_y,%arg_z)
+	__(je 1f)
+	/* Not EQ.  Could only possibly be EQL if both are tag-misc  */
+	/* and both have the same subtag   */
+	__(extract_lisptag(%arg_y,%imm0))
+	__(extract_lisptag(%arg_z,%imm1))
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 2f)
+	__(cmpb %imm0_b,%imm1_b)
+	__(jne 2f)
+	__(extract_subtag(%arg_y,%imm0_b))
+	__(extract_subtag(%arg_z,%imm1_b))
+	__(cmpb %imm0_b,%imm1_b)
+	__(jne 2f)
+	__(jump_builtin(_builtin_eql,2))
+1:	__(movl $t_value,%arg_z_l)
+	__(ret)
+2:	__(movl $nil_value,%arg_z_l)
+	__(ret)	
+_endsubp(builtin_eql)
+
+_spentry(builtin_length)
+	__(extract_lisptag(%arg_z,%imm0))
+	__(cmpb $tag_list,%imm0_b)
+	__(jz 2f)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jnz 8f)
+	__(extract_subtag(%arg_z,%imm0_b))
+	__(rcmpb(%imm0_b,$min_vector_subtag))
+	__(jb 8f)
+	__(je 1f)
+	/* (simple-array * (*))   */
+	__(movq %arg_z,%arg_y)
+	__(vector_length(%arg_y,%arg_z))
+	__(ret)
+1:	/* vector header   */
+	__(movq vectorH.logsize(%arg_z),%arg_z)
+	__(ret)
+2:	/* list.  Maybe null, maybe dotted or circular.   */
+	__(movq $-fixnumone,%imm2)
+	__(movq %arg_z,%temp0)	/* fast pointer   */
+	__(movq %arg_z,%temp1)  /* slow pointer   */
+3:	__(extract_lisptag(%temp0,%imm0))	
+	__(compare_reg_to_nil(%temp0))
+	__(leaq fixnumone(%imm2),%imm2)
+	__(je 9f)
+	__(cmpb $tag_list,%imm0_b)
+	__(jne 8f)
+	__(extract_lisptag(%temp1,%imm1))
+	__(testb $fixnumone,%imm2_b)
+	__(_cdr(%temp0,%temp0))
+	__(je 3b)
+	__(cmpb $tag_list,%imm1_b)
+	__(jne 8f)
+	__(_cdr(%temp1,%temp1))
+	__(cmpq %temp0,%temp1)
+	__(jne 3b)
+8:	
+	__(jump_builtin(_builtin_length,1))
+9:	
+	__(movq %imm2,%arg_z)
+	__(ret)		
+_endsubp(builtin_length)
+
+	
+_spentry(builtin_seqtype)
+	__(extract_lisptag(%arg_z,%imm0))
+	__(cmpb $tag_list,%imm0_b)
+	__(jz 1f)
+	__(cmpb $tag_misc,%imm0_b)
+	__(jne 2f)
+	__(movb misc_subtag_offset(%arg_z),%imm0_b)
+	__(rcmpb(%imm0_b,$min_vector_subtag))
+	__(jb 2f)
+	__(movl $nil_value,%arg_z_l)
+	__(ret)
+1:	__(movl $t_value,%arg_z_l)
+	__(ret)
+2:	
+	__(jump_builtin(_builtin_seqtype,1))
+_endsubp(builtin_seqtype)
+
+_spentry(builtin_assq)
+	__(cmpb $fulltag_nil,%arg_z_b)
+	__(jz 5f)
+1:	__(movb $tagmask,%imm0_b)
+	__(andb %arg_z_b,%imm0_b)
+	__(cmpb $tag_list,%imm0_b)
+	__(jnz 2f)
+	__(_car(%arg_z,%arg_x))
+	__(_cdr(%arg_z,%arg_z))
+	__(cmpb $fulltag_nil,%arg_x_b)
+	__(jz 4f)
+	__(movb $tagmask,%imm0_b)
+	__(andb %arg_x_b,%imm0_b)
+	__(cmpb $tag_list,%imm0_b)
+	__(jnz 3f)
+	__(_car(%arg_x,%temp0))
+	__(cmpq %temp0,%arg_y)
+	__(jnz 4f)
+	__(movq %arg_x,%arg_z)
+	__(ret)
+4:	__(cmpb $fulltag_nil,%arg_z_b)
+5:	__(jnz 1b)
+	__(repret)
+2:      __(uuo_error_reg_not_list(Rarg_z))
+3:      __(uuo_error_reg_not_list(Rarg_x))        
+_endsubp(builtin_assq)	
+
+_spentry(builtin_memq)
+	__(cmpb $fulltag_nil,%arg_z_b)
+	__(jmp 3f)
+1:	__(movb $tagmask,%imm0_b)
+	__(andb %arg_z_b,%imm0_b)
+	__(cmpb $tag_list,%imm0_b)
+	__(jnz 2f)
+	__(_car(%arg_z,%arg_x))
+	__(_cdr(%arg_z,%temp0))
+	__(cmpq %arg_x,%arg_y)
+	__(jz 4f)
+	__(cmpb $fulltag_nil,%temp0_b)
+	__(movq %temp0,%arg_z)
+3:	__(jnz 1b)
+4:	__(repret)				
+2:      __(uuo_error_reg_not_list(Rarg_z))
+_endsubp(builtin_memq)
+
+        __ifdef([X8664])
+logbitp_max_bit = 61
+        __else
+logbitp_max_bit = 30
+        __endif
+	
+_spentry(builtin_logbitp)
+	__(movb %arg_z_b,%imm0_b)
+	__(orb %arg_y_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jnz 1f)
+	__(unbox_fixnum(%arg_y,%imm0))
+        __(movl $logbitp_max_bit-1+fixnumshift,%imm1_l)
+        __(js 1f)               /* bit number negative */
+	__(addb $fixnumshift,%imm0_b)
+	__(cmpq $logbitp_max_bit<<fixnumshift,%arg_y)
+	__(cmovael %imm1_l,%imm0_l)
+	__(bt %imm0,%arg_z)
+	__(condition_to_boolean(b,%imm0,%arg_z))
+	__(ret)
+1:	__(jump_builtin(_builtin_logbitp,2))
+_endsubp(builtin_logbitp)
+
+_spentry(builtin_logior)
+	__(movb %arg_y_b,%imm0_b)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(orq %arg_y,%arg_z)
+	__(ret)
+1:	
+	__(jump_builtin(_builtin_logior,2))
+		
+_endsubp(builtin_logior)
+
+_spentry(builtin_logand)
+	__(movb %arg_y_b,%imm0_b)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(andq %arg_y,%arg_z)
+	__(ret)
+1:		
+	__(jump_builtin(_builtin_logand,2))
+_endsubp(builtin_logand)
+
+_spentry(builtin_negate)
+	__(testb $fixnummask,%arg_z_b)
+	__(jne 1f)
+	__(negq %arg_z)
+	__(jo C(fix_one_bit_overflow))
+	__(repret)
+1:		
+	__(jump_builtin(_builtin_negate,1))	
+_endsubp(builtin_negate)
+
+_spentry(builtin_logxor)
+	__(movb %arg_y_b,%imm0_b)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 1f)
+	__(xorq %arg_y,%arg_z)
+	__(ret)
+1:		
+	__(jump_builtin(_builtin_logxor,2))
+_endsubp(builtin_logxor)
+
+
+_spentry(builtin_aset1)
+	__(extract_typecode(%arg_x,%imm0))
+	__(box_fixnum(%imm0,%temp0))
+	__(cmpb $min_vector_subtag,%imm0_b)
+	__(ja _SPsubtag_misc_set)
+	__(jump_builtin(_builtin_aset1,3))
+_endsubp(builtin_aset1)
+
+
+_spentry(builtin_ash)
+	__(movb %arg_y_b,%imm0_b)
+	__(orb %arg_z_b,%imm0_b)
+	__(testb $fixnummask,%imm0_b)
+	__(jne 9f)
+	__(unbox_fixnum(%arg_y,%imm1))
+	__(unbox_fixnum(%arg_z,%imm0))
+	/* Z flag set if zero ASH shift count   */
+	__(jnz 1f)
+	__(movq %arg_y,%arg_z)	/* shift by 0   */
+	__(ret)
+1:	__(jns 3f)
+	__(rcmpq(%imm0,$-63))
+	__(jg 2f)
+	__(sar $63,%imm1)
+	__(box_fixnum(%imm1,%arg_z))
+	__(ret)
+2:	/* Right-shift by small fixnum   */
+	__(negb %imm0_b)
+	__(movzbl %imm0_b,%ecx)
+	__(sar %cl,%imm1)
+	__(box_fixnum(%imm1,%arg_z))
+	__(ret)
+3:      /* Left shift by fixnum. We cant shift by more than 63 bits, though  */
+	/* shifting by 64 is actually easy.   */
+	__(rcmpq(%imm0,$64))
+	__(jg 9f)
+	__(jne 4f)
+	/* left-shift by 64-bits exactly   */
+	__(xorl %imm0_l,%imm0_l)
+	__(jmp C(makes128))
+4:	/* left-shift by 1..63 bits.  Safe to move shift count to %rcx/%cl   */
+	__(movzbl %imm0_b,%ecx)	 /* zero-extending mov   */
+	__(movq %imm1,%imm0)
+	__(sarq $63,%imm1)
+	__(js 5f)
+	__(shld %cl,%imm0,%imm1)
+	__(shl %cl,%imm0)
+	__(jmp C(makes128))
+5:	__(shld %cl,%imm0,%imm1)
+	__(shl %cl,%imm0)
+	__(jmp C(makes128))
+9:	
+	__(jump_builtin(_builtin_ash,2))
+_endsubp(builtin_ash)
+
+_spentry(builtin_aref1)
+	__(extract_typecode(%arg_y,%imm0))
+	__(cmpb $min_vector_subtag,%imm0_b)
+	__(box_fixnum_no_flags(%imm0,%arg_x))
+	__(ja _SPsubtag_misc_ref)
+	__(jump_builtin(_builtin_aref1,2))
+_endsubp(builtin_aref1)
+
+/* Arg_z is either a MACPTR containing the function address or a boxed fixnum.  */
+/*   %imm0.b (aka %al) contains the number (0-7) of args passed in FP regs.  */
+/*   On entry, the foreign stack contains a frame containing at least 8 words:  */
+
+/*   * -> aligned on 16-byte boundary  */
+/*  *backlink	<-	foreign %rsp		  */
+/*   unused  */
+/*   scalar arg 0		passed in %rdi  */
+/*   scalar arg 1         passed in %rsi  */
+/*   scalar arg 2		passed in %rdx  */
+/*   scalar arg 3		passed in %rcx  */
+/*   scalar arg 4		passed in %r8  */
+/*   scalar arg 5		passed in %r9  */
+/*  *address of first memory arg  */
+/*   ...  */
+/*   possible scratch space  */
+/*  *previous %rsp value  */
+
+/*   Any floating-point args will have been loaded into %xmm0-%xmm7 by the caller.  */
+/*   When this returns, the foreign %rsp will contain its previous value, and  */
+/*   the function result will be in %rax (and possibly %rdx) or %xmm0 (+ %xmm1).  */
+
+_spentry(ffcall)
+LocalLabelPrefix[]ffcall:                
+        /* Unbox %arg_z.  It's either a fixnum or macptr (or bignum) ;
+          if not a fixnum, get the first word */
+        __(unbox_fixnum(%arg_z,%imm1))
+	__(testb $fixnummask,%arg_z_b)
+        __(je 0f)
+        __(movq macptr.address(%arg_z),%imm1)
+0:              
+	/* Save lisp registers   */
+        __(push %rbp)
+	__(movq %rsp,%rbp)
+	__(push %temp0)
+	__(push %temp1)
+	__(push %temp2)
+	__(push %arg_x)
+	__(push %arg_y)
+	__(push %arg_z)
+	__(push %fn)
+	__ifndef([TCR_IN_GPR])
+	__(push %save3)  
+	__endif
+	__(push %save2)
+	__(push %save1)
+	__(push %save0)       /* 10 or 11 registers pushed after %rbp */
+	__(movq %rsp,rcontext(tcr.save_vsp))
+        __(movq %rbp,rcontext(tcr.save_rbp))
+	__(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+        __(movq rcontext(tcr.foreign_sp),%rsp)
+	__(stmxcsr rcontext(tcr.lisp_mxcsr))
+	__(emms)
+	__(ldmxcsr rcontext(tcr.foreign_mxcsr))
+	__(movq (%rsp),%rbp)
+        __ifdef([DARWIN_GS_HACK])
+         /* At this point, %imm1=%rdx is live (contains
+            the entrypoint) and %imm0.b=%al contains
+            info about xmm register arguments; the lisp registers are
+            all saved, and the foreign arguments are
+            on the foreign stack (about to be popped
+            off).  Save the linear TCR address in %save0/%r15
+            so that we can restore it later, and preserve
+            the entrypoint somewhere where C won't bash it.
+            Note that dereferencing the entrypoint from
+            foreign code has never been safe (unless it's
+            a fixnum */
+         __(save_tcr_linear(%csave0))
+         __(movq %imm1,%csave1)
+         __(movq %imm0,%csave2)
+         __(set_foreign_gs_base())
+         __(movq %csave1,%imm1)
+         __(movq %csave2,%imm0)
+        __endif
+	__ifdef([TCR_IN_GPR])
+	/* Preserve TCR pointer */
+	__(movq %rcontext_reg, %csave0)
+	__endif
+LocalLabelPrefix[]ffcall_setup: 
+	__(addq $2*node_size,%rsp)
+        __(movq %imm1,%r11)
+        __ifdef([WINDOWS])
+         /* Leave 0x20 bytes of register spill area on stack */
+         __(movq (%rsp),%carg0)
+         __(movq 8(%rsp),%carg1)
+         __(movq 16(%rsp),%carg2)
+         __(movq 24(%rsp),%carg3)
+        __else
+	 __(pop %carg0)
+	 __(pop %carg1)
+	 __(pop %carg2)
+	 __(pop %carg3)
+	 __(pop %carg4)
+	 __(pop %carg5)
+	__endif
+LocalLabelPrefix[]ffcall_setup_end: 
+LocalLabelPrefix[]ffcall_call:
+	__(call *%r11)
+LocalLabelPrefix[]ffcall_call_end:               
+	__ifdef([WINDOWS])
+	__(add $0x20,%rsp)
+	__endif
+	__(movq %rbp,%rsp)
+        __ifdef([DARWIN_GS_HACK])
+         /* %rax/%rdx contains the return value (maybe), %csave1 still
+            contains the linear tcr address.  Preserve %rax/%rdx here. */
+         __(movq %rax,%csave1)
+         __(movq %rdx,%csave2)
+         __(set_gs_base(%csave0))
+         __(movq %csave1,%rax)
+         __(movq %csave2,%rdx)
+        __endif
+	__ifdef([TCR_IN_GPR])
+	__(movq %csave0, %rcontext_reg)
+	__endif
+	__(movq %rsp,rcontext(tcr.foreign_sp))
+	__ifndef([TCR_IN_GPR])
+	__(clr %save3)
+	__endif
+	__(clr %save2)
+	__(clr %save1)
+	__(clr %save0)
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %arg_x)
+	__(clr %temp2)
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+        __(cmpb $0,C(bogus_fp_exceptions)(%rip))
+        __(je 0f)
+        __(movl %arg_x_l,rcontext(tcr.ffi_exception))
+        __(jmp 1f)
+0:      __(stmxcsr rcontext(tcr.ffi_exception))
+1:      __(movq rcontext(tcr.save_vsp),%rsp)
+        __(movq rcontext(tcr.save_rbp),%rbp)
+	__(movq $TCR_STATE_LISP,rcontext(tcr.valence))
+	__(pop %save0)
+	__(pop %save1)
+	__(pop %save2)
+	__ifndef([TCR_IN_GPR])
+	__(pop %save3)
+	__endif
+	__(pop %fn)
+	__(pop %arg_z)
+	__(pop %arg_y)
+	__(pop %arg_x)
+	__(pop %temp2)
+	__(pop %temp1)
+	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
+	__(check_pending_interrupt(%temp0))
+	__(pop %temp0)
+        __(leave)
+	__ifdef([DARWIN])
+	__(btrq $TCR_FLAG_BIT_FOREIGN_EXCEPTION,rcontext(tcr.flags))
+	__(jc 0f)
+	__endif
+	__(ret)
+	__ifdef([DARWIN])
+0:
+	/* Unboxed foreign exception (likely an NSException) in %imm0. */
+	/* Box it, then signal a lisp error. */
+	__(movq %imm0,%imm2)
+	__(movq $macptr_header,%rax)
+	__(Misc_Alloc_Fixed(%arg_z,macptr.size))
+	__(movq %imm2,macptr.address(%arg_z))
+	__(movq $XFOREIGNEXCEPTION,%arg_y)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+	__endif
+        __ifdef([DARWIN])        
+        /* Handle exceptions, for ObjC 2.0 */
+LocalLabelPrefix[]ffcallLandingPad:      
+        __(movq %rax,%save1)
+        __(cmpq $1,%rdx)
+        __(je 1f)
+        __(movq %rax,%rdi)
+LocalLabelPrefix[]ffcallUnwindResume:            
+       	__(call *lisp_global(unwind_resume))
+LocalLabelPrefix[]ffcallUnwindResume_end:         
+1:      __(movq %save1,%rdi)
+LocalLabelPrefix[]ffcallBeginCatch:              
+        __(call *lisp_global(objc2_begin_catch))
+LocalLabelPrefix[]ffcallBeginCatch_end:          
+        __(movq (%rax),%save1) /* indirection is necessary because we don't provide type info in lsda */
+LocalLabelPrefix[]ffcallEndCatch:                
+        __(call *lisp_global(objc2_end_catch))
+LocalLabelPrefix[]ffcallEndCatch_end:            
+	__(ref_global(get_tcr,%rax))
+	__(movq $1,%rdi)
+	__(call *%rax)
+	__(btsq $TCR_FLAG_BIT_FOREIGN_EXCEPTION,tcr.flags(%rax))
+	__(movq %save1,%rax)
+	__(jmp LocalLabelPrefix[]ffcall_call_end)
+LocalLabelPrefix[]ffcall_end:   
+        __endif
+_endsubp(ffcall)
+
+        __ifdef([DARWIN])
+	.section __DATA,__gcc_except_tab
+GCC_except_table0:
+	.align 3
+LLSDA1:
+	.byte	0xff	/* @LPStart format (omit) */
+	.byte	0x0	/* @TType format (absolute) */
+	.byte	0x4d	/* uleb128 0x4d; @TType base offset */
+	.byte	0x3	/* call-site format (udata4) */
+	.byte	0x41	/* uleb128 0x41; Call-site table length */
+	
+	.long Lffcall_setup-Lffcall	/* region 0 start */
+	.long Lffcall_setup_end-Lffcall_setup	/* length */
+	.long	0x0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+        
+	.long Lffcall_call-Lffcall	/* region 1 start */
+	.long Lffcall_call_end-Lffcall_call	/* length */
+	.long LffcallLandingPad-Lffcall	/* landing pad */
+	.byte	0x1	/* uleb128 0x1; action */
+        
+	.long LffcallUnwindResume-Lffcall	/* region 2 start */
+	.long LffcallUnwindResume_end-LffcallUnwindResume	/* length */
+	.long	0x0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+	
+	.long LffcallBeginCatch-Lffcall	/* region 3 start */
+	.long LffcallBeginCatch_end-LffcallBeginCatch	/* length */
+	.long 0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+        
+	.long LffcallEndCatch-Lffcall
+	.long LffcallEndCatch_end-LffcallEndCatch	/* length */
+	.long	0x0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+	.byte	0x1	/* Action record table */
+	.byte	0x0
+	.align 3
+	.quad	0       /* _OBJC_EHTYPE_$_NSException */
+        .text
+        __endif
+
+_spentry(ffcall_return_registers)
+LocalLabelPrefix[]ffcall_return_registers:                
+        /* Unbox %arg_z.  It's either a fixnum or macptr (or bignum) ;
+          if not a fixnum, get the first word */
+        __(unbox_fixnum(%arg_z,%imm1))
+	__(testb $fixnummask,%arg_z_b)
+        __(je 0f)
+        __(movq macptr.address(%arg_z),%imm1)
+0:              
+	/* Save lisp registers   */
+        __(push %rbp)
+        __(movq %rsp,%rbp)
+	__(push %temp0)
+	__(push %temp1)
+	__(push %temp2)
+	__(push %arg_x)
+	__(push %arg_y)
+	__(push %arg_z)
+	__ifndef([TCR_IN_GPR])
+	__(push %save3)
+	__endif
+	__(push %save2)
+	__(push %save1)
+	__(push %save0)
+        __(movq macptr.address(%arg_y),%csave0)  /* %rbx non-volatile */
+	__(push %fn)
+	__(movq %rsp,rcontext(tcr.save_vsp))
+        __(movq %rbp,rcontext(tcr.save_rbp))
+	__(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+        __(movq rcontext(tcr.foreign_sp),%rsp)
+	__(stmxcsr rcontext(tcr.lisp_mxcsr))
+	__(emms)
+	__(ldmxcsr rcontext(tcr.foreign_mxcsr))
+	__(movq (%rsp),%rbp)
+        __ifdef([DARWIN_GS_HACK])
+         /* At this point, %imm1=%rdx is live (contains
+            the entrypoint) and %imm0.b=%al contains
+            xmm argument info; the lisp registers are
+            all saved, and the foreign arguments are
+            on the foreign stack (about to be popped
+            off).  Save the linear TCR address in %csave1/%r12
+            so that we can restore it later, and preserve
+            the entrypoint somewhere where C won't bash it.
+            Note that dereferencing the entrypoint from
+            foreign code has never been safe (unless it's
+            a fixnum */
+         __(save_tcr_linear(%csave1))
+         __(movq %imm0,%csave2)
+         __(movq %imm1,%csave3)
+         __(set_foreign_gs_base())
+         __(movq %csave2,%imm0)
+         __(movq %csave3,%imm1)
+        __endif
+	__ifdef([TCR_IN_GPR])
+	/* Preserve TCR pointer */
+	__(movq %rcontext_reg, %csave1)
+	__endif
+        __(movq %imm1,%r11)
+LocalLabelPrefix[]ffcall_return_registers_setup: 
+	__(addq $2*node_size,%rsp)
+	__(pop %carg0)
+	__(pop %carg1)
+	__(pop %carg2)
+	__(pop %carg3)
+	__ifdef([WINDOWS])
+	__(sub $0x20, %rsp) /* Make room for arg register spill */
+	__else
+	__(pop %carg4)
+	__(pop %carg5)
+	__endif
+LocalLabelPrefix[]ffcall_return_registers_setup_end: 
+LocalLabelPrefix[]ffcall_return_registers_call:
+	__(call *%r11)
+LocalLabelPrefix[]ffcall_return_registers_call_end:
+	__ifdef([WINDOWS])
+	__(add $0x20, %rsp)
+	__endif
+        __(movq %rax,(%csave0))
+        __(movq %rdx,8(%csave0))
+        __(movsd %xmm0,16(%csave0))
+        __(movsd %xmm1,24(%csave0))
+	__(movq %rbp,%rsp)
+        __ifdef([DARWIN_GS_HACK])
+         /* %rax/%rdx contains the return value (maybe), %save0 still
+            contains the linear tcr address.  Preserve %rax/%rdx here. */
+         __(set_gs_base(%csave1))
+         __(movq (%csave0),%rax)
+         __(movq 8(%csave0),%rdx)
+         __(movsd 16(%csave0),%xmm0)
+         __(movsd 24(%csave0),%xmm1)
+        __endif
+	__ifdef([TCR_IN_GPR])
+	__(movq %csave1, %rcontext_reg)
+	__endif
+	__(movq %rsp,rcontext(tcr.foreign_sp))        
+	__ifndef([TCR_IN_GPR])
+	__(clr %save3)
+	__endif
+	__(clr %save2)
+	__(clr %save1)
+	__(clr %save0)
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %arg_x)
+	__(clr %temp2)
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+        __(cmpb $0,C(bogus_fp_exceptions)(%rip))
+        __(je 0f)
+        __(movl %arg_x_l,rcontext(tcr.ffi_exception))
+        __(jmp 1f)
+0:      __(stmxcsr rcontext(tcr.ffi_exception))
+1:      __(movq rcontext(tcr.save_vsp),%rsp)
+        __(movq rcontext(tcr.save_rbp),%rbp)
+	__(movq $TCR_STATE_LISP,rcontext(tcr.valence))
+	__(pop %fn)
+	__(pop %save0)
+	__(pop %save1)
+	__(pop %save2)
+	__ifndef([TCR_IN_GPR])
+	__(pop %save3)
+	__endif
+	__(pop %arg_z)
+	__(pop %arg_y)
+	__(pop %arg_x)
+	__(pop %temp2)
+	__(pop %temp1)
+	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
+	__(check_pending_interrupt(%temp0))
+	__(pop %temp0)
+        __(leave)
+	__ifdef([DARWIN])
+	__(btrq $TCR_FLAG_BIT_FOREIGN_EXCEPTION,rcontext(tcr.flags))
+	__(jc 0f)
+	__endif
+        __(ret)
+	__ifdef([DARWIN])
+0:
+	/* Unboxed foreign exception (likely an NSException) in %imm0. */
+	/* Box it, then signal a lisp error. */
+	__(movq %imm0,%imm2)
+	__(movq $macptr_header,%rax)
+	__(Misc_Alloc_Fixed(%arg_z,macptr.size))
+	__(movq %imm2,macptr.address(%arg_z))
+	__(movq $XFOREIGNEXCEPTION,%arg_y)
+	__(set_nargs(2))
+	__(jmp _SPksignalerr)
+	__endif
+        __ifdef([DARWIN])        
+        /* Handle exceptions, for ObjC 2.0 */
+LocalLabelPrefix[]ffcall_return_registersLandingPad:      
+        __(movq %rax,%save1)
+        __(cmpq $1,%rdx)
+        __(je 1f)
+        __(movq %rax,%rdi)
+LocalLabelPrefix[]ffcall_return_registersUnwindResume:            
+       	__(call *lisp_global(unwind_resume))
+LocalLabelPrefix[]ffcall_return_registersUnwindResume_end:         
+1:      __(movq %save1,%rdi)
+LocalLabelPrefix[]ffcall_return_registersBeginCatch:              
+        __(call *lisp_global(objc2_begin_catch))
+LocalLabelPrefix[]ffcall_return_registersBeginCatch_end:          
+        __(movq (%rax),%save1) /* indirection is necessary because we don't provide type info in lsda */
+LocalLabelPrefix[]ffcall_return_registersEndCatch:                
+        __(call *lisp_global(objc2_end_catch))
+LocalLabelPrefix[]ffcall_return_registersEndCatch_end:            
+	__(ref_global(get_tcr,%rax))
+	__(movq $1,%rdi)
+	__(call *%rax)
+	__(btsq $TCR_FLAG_BIT_FOREIGN_EXCEPTION,tcr.flags(%rax))
+	__(movq %save1,%rax)
+	__(jmp LocalLabelPrefix[]ffcall_return_registers_call_end)
+LocalLabelPrefix[]ffcall_return_registers_end:   
+        __endif
+_endsubp(ffcall_returning_registers)
+
+        __ifdef([DARWIN])
+	.section __DATA,__gcc_except_tab
+GCC_except_table1:
+	.align 3
+LLSDA2:
+	.byte	0xff	/* @LPStart format (omit) */
+	.byte	0x0	/* @TType format (absolute) */
+	.byte	0x4d	/* uleb128 0x4d; @TType base offset */
+	.byte	0x3	/* call-site format (udata4) */
+	.byte	0x41	/* uleb128 0x41; Call-site table length */
+	
+	.long Lffcall_return_registers_setup-Lffcall_return_registers	/* region 0 start */
+	.long Lffcall_return_registers_setup_end-Lffcall_return_registers_setup	/* length */
+	.long	0x0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+        
+	.long Lffcall_return_registers_call-Lffcall_return_registers	/* region 1 start */
+	.long Lffcall_return_registers_call_end-Lffcall_return_registers_call	/* length */
+	.long Lffcall_return_registersLandingPad-Lffcall_return_registers	/* landing pad */
+	.byte	0x1	/* uleb128 0x1; action */
+        
+	.long Lffcall_return_registersUnwindResume-Lffcall_return_registers	/* region 2 start */
+	.long Lffcall_return_registersUnwindResume_end-Lffcall_return_registersUnwindResume	/* length */
+	.long	0x0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+	
+	.long Lffcall_return_registersBeginCatch-Lffcall_return_registers	/* region 3 start */
+	.long Lffcall_return_registersBeginCatch_end-Lffcall_return_registersBeginCatch	/* length */
+	.long 0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+        
+	.long Lffcall_return_registersEndCatch-Lffcall_return_registers
+	.long Lffcall_return_registersEndCatch_end-Lffcall_return_registersEndCatch	/* length */
+	.long	0x0	/* landing pad */
+	.byte	0x0	/* uleb128 0x0; action */
+	.byte	0x1	/* Action record table */
+	.byte	0x0
+	.align 3
+	.quad	0       /* _OBJC_EHTYPE_$_NSException */
+        .text
+        __endif
+                
+_spentry(syscall)
+	/* Save lisp registers   */
+	__(push %rbp)
+	__(movq %rsp,%rbp)
+	__(push %temp0)
+	__(push %temp1)
+	__(push %temp2)
+	__(push %arg_x)
+	__(push %arg_y)
+	__(push %arg_z)
+        __ifndef([TCR_IN_GPR])
+	 __(push %save3)
+        __endif
+	__(push %save2)
+	__(push %save1)
+	__(push %save0)
+	__(push %fn)
+	__(movq %rsp,rcontext(tcr.save_vsp))
+        __(movq %rbp,rcontext(tcr.save_rbp))
+	__(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+        __(movq rcontext(tcr.foreign_sp),%rsp)
+	__(emms)
+	__(movq (%rsp),%rbp)
+	__(addq $2*node_size,%rsp)
+        __ifdef([TCR_IN_GPR])
+         __(movq %rcontext_reg,%csave0)
+        __endif
+        __ifdef([WINDOWS])
+         __(pop %carg0)
+         __(pop %carg1)
+         __(pop %carg2)
+         __(pop %carg3)
+         __(subq $0x20,%rsp)
+         __(orq $-1,%cret)
+         __(addq $0x20,%rsp)
+        __else
+	 __(unbox_fixnum(%arg_z,%rax))
+	 __(pop %rdi)
+	 __(pop %rsi)
+	 __(pop %rdx)
+	 __(pop %r10)		/*  syscalls take 4th param in %r10, not %rcx   */
+	 __(pop %r8)
+	 __(pop %r9)
+	 __(syscall)
+         __ifdef([SYSCALL_SETS_CARRY_ON_ERROR])
+          __(jnc 0f)
+          __(negq %rax)
+0:      
+         __endif
+        __endif
+        __ifdef([TCR_IN_GPR])
+         __(movq %csave0,%rcontext_reg)
+        __endif
+	__(movq %rbp,%rsp)
+	__(movq %rsp,rcontext(tcr.foreign_sp))
+        __ifndef([TCR_IN_GPR])
+	 __(clr %save3)
+        __endif
+	__(clr %save2)
+	__(clr %save1)
+	__(clr %save0)
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %arg_x)
+	__(clr %temp2)
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+	__(movq rcontext(tcr.save_vsp),%rsp)
+        __(movq rcontext(tcr.save_rbp),%rbp)
+	__(movq $TCR_STATE_LISP,rcontext(tcr.valence))
+	__(pop %fn)
+	__(pop %save0)
+	__(pop %save1)
+	__(pop %save2)
+        __ifndef([TCR_IN_GPR])
+	 __(pop %save3)
+        __endif
+	__(pop %arg_z)
+	__(pop %arg_y)
+	__(pop %arg_x)
+	__(pop %temp2)
+	__(pop %temp1)
+	__(check_pending_interrupt(%temp0))
+	__(pop %temp0)
+        __(leave)
+	__(ret)
+_endsubp(syscall)		
+
+/* We need to reserve a frame here if (a) nothing else was already pushed and (b) */
+/*   we push something (e.g., more than 3 args in the lexpr) 	  */
+_spentry(spread_lexprz)
+	new_local_labels()
+	__(movq (%arg_z),%imm0)
+	__(testl %nargs,%nargs) /* anything pushed by caller ? */
+        __(leaq node_size(%arg_z,%imm0),%imm1)
+        __(jne 0f)              /* yes, caller has already created frame. */
+        __(cmpw $(nargregs*node_size),%imm0_w) /* will we push anything ? */
+        __(jbe 0f)
+        __(push $reserved_frame_marker)
+        __(push $reserved_frame_marker)
+0:      __(addw %imm0_w,%nargs_w)
+        __(cmpw $(nargregs*node_size),%imm0_w)
+        __(jae 9f)
+        __(cmpw $(2*node_size),%imm0_w)
+        __(je 2f)
+        __(testw %imm0_w,%imm0_w)
+        __(jne 1f)
+        /* lexpr count was 0; vpop the args that */
+        /* were pushed by the caller */
+        __(testl %nargs,%nargs)
+        __(je local_label(all_args_popped))
+        __(pop %arg_z)
+local_label(maybe_pop_yx):              
+        __(cmpl $(1*node_size),%nargs)
+        __(je local_label(all_args_popped))
+        __(pop %arg_y)
+        __(cmpl $(2*node_size),%nargs)
+        __(je local_label(all_args_popped))
+local_label(pop_arg_x):         
+        __(pop %arg_x)
+local_label(all_args_popped):   
+        /* If all args fit in registers but some were pushed */
+        /* by the caller, discard the reserved frame that the caller */
+        /* pushed.         */
+        __(cmpw %imm0_w,%nargs_w)
+        __(je local_label(go))
+        __(cmpl $(nargregs*node_size),%nargs)
+        __(ja local_label(go))
+        __(addq $(2*node_size),%rsp)
+local_label(go):        
+        __(jmp *%ra0)        
+	/* vpush args from the lexpr until we have only */
+	/* three left, then assign them to arg_x, arg_y, */
+	/* and arg_z. */ 
+8:      __(cmpw $(4*node_size),%imm0_w)
+        __(lea -1*node_size(%imm0),%imm0)
+        __(push -node_size(%imm1))
+        __(lea -1*node_size(%imm1),%imm1)
+9:      __(jne 8b)
+        __(movq -node_size*1(%imm1),%arg_x)
+        __(movq -node_size*2(%imm1),%arg_y)
+        __(movq -node_size*3(%imm1),%arg_z)
+        __(jmp *%ra0)
+
+	/* lexpr count is two: set arg_y, arg_z from the */
+	/* lexpr, maybe vpop arg_x */
+2:      __(cmpl $(2*node_size),%nargs)
+        __(movq -node_size*1(%imm1),%arg_y)
+        __(movq -node_size*2(%imm1),%arg_z)
+        __(jne local_label(pop_arg_x))
+        __(jmp *%ra0)
+	/* lexpr count is one: set arg_z from the lexpr, */
+	/* maybe vpop arg_y, arg_x  */
+1:      __(movq -node_size*1(%imm1),%arg_z)
+        __(jmp local_label(maybe_pop_yx))
+_endsubp(spread_lexprz)
+	
+
+
+
+/* Callback index in %r11 */
+_spentry(callback)
+	__(push %rbp)
+	__(movq %rsp,%rbp)
+	/* C scalar args   */
+	__(push %carg0)	/* -8(%rbp)   */
+	__(push %carg1)
+	__(push %carg2)
+	__(push %carg3)
+	__ifndef([WINDOWS])
+	__(push %carg4)
+	__(push %carg5)
+	__endif
+	/* FP arg regs   */
+	__ifdef([WINDOWS])
+	__(subq $4*8,%rsp)
+	__(movq %xmm0,3*8(%rsp))	/* -40(%rbp) */
+	__(movq %xmm1,2*8(%rsp))
+	__(movq %xmm2,1*8(%rsp))
+	__(movq %xmm3,0*8(%rsp))
+	__else
+	__(subq $8*8,%rsp)
+	__(movq %xmm0,7*8(%rsp))	/* -56(%rbp) */
+	__(movq %xmm1,6*8(%rsp))
+	__(movq %xmm2,5*8(%rsp))
+	__(movq %xmm3,4*8(%rsp))
+	__(movq %xmm4,3*8(%rsp))
+	__(movq %xmm5,2*8(%rsp))
+	__(movq %xmm6,1*8(%rsp))
+	__(movq %xmm7,0*8(%rsp))
+	__endif
+	__ifndef([WINDOWS])
+	__endif
+	/* C NVRs   */
+	__(push %csave0)
+	__(push %csave1)
+	__(push %csave2)
+	__(push %csave3)
+	__(push %csave4)
+	__ifdef([WINDOWS])
+	__(push %csave5)
+	__(push %csave6)
+	__endif
+	__(push %rbp)
+	__(movq %r11,%csave0)
+        __ifdef([HAVE_TLS])
+	 /* TCR initialized for lisp ?   */
+	 __ifndef([TCR_IN_GPR]) /* FIXME */
+	 __(movq %fs:current_tcr@TPOFF+tcr.linear,%rax)
+	 __(testq %rax,%rax)
+	 __(jne 1f)
+	 __endif
+        __endif
+	__(ref_global(get_tcr,%rax))
+	__(movq $1,%carg0)
+	__ifdef([WINDOWS])
+	__(sub $0x20, %rsp)
+	__endif
+	__(call *%rax)
+	__ifdef([WINDOWS])
+	__(add $0x20, %rsp)
+        __endif
+        __ifdef([TCR_IN_GPR])
+	__(movq %rax, %rcontext_reg)
+	__endif	
+        __ifdef([DARWIN_GS_HACK])
+         /* linear TCR address in now in %rax; callback index was
+            saved in %r12 a moment ago. */
+         __(set_gs_base(%rax))
+        __endif
+1:	/* Align foreign stack for lisp   */
+        __(pushq rcontext(tcr.save_rbp)) /* mark cstack frame's "owner" */
+	__(pushq rcontext(tcr.foreign_sp))
+	/* init lisp registers   */
+	__(movq %csave0,%rax)
+	__(movq %rsp,rcontext(tcr.foreign_sp))
+	__ifndef([TCR_IN_GPR])
+	__(clr %save3)
+	__endif
+	__(clr %save2)
+	__(clr %save1)
+	__(clr %save0)
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %arg_x)
+	__(clr %temp2)
+	__(clr %temp1)
+	__(clr %temp0)
+	__(clr %fn)
+	__(pxor %fpzero,%fpzero)
+	__(movq rcontext(tcr.save_vsp),%rsp)
+	__(box_fixnum(%rax,%arg_y))
+	__(movq %rbp,%arg_z)
+        __(movq rcontext(tcr.save_rbp),%rbp)
+	__(movq $TCR_STATE_LISP,rcontext(tcr.valence))
+        __(movq (%rsp),%save0)
+        __(movq 8(%rsp),%save1)
+        __(movq 16(%rsp),%save2)
+        __ifndef([TCR_IN_GPR])
+         __(movq 24(%rsp),%save3)
+        __endif
+        __(stmxcsr rcontext(tcr.foreign_mxcsr))
+        __(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
+	__(ldmxcsr rcontext(tcr.lisp_mxcsr))
+	__(movq $nrs.callbacks,%fname)
+	__(lea local_label(back_from_callback)(%rip),%ra0)
+	__(set_nargs(2))
+        __(push %ra0)
+	__(jump_fname())
+__(tra(local_label(back_from_callback)))
+	__(movq %rsp,rcontext(tcr.save_vsp))
+        __(movq %rbp,rcontext(tcr.save_rbp))
+        __(movq rcontext(tcr.foreign_sp),%rsp)
+	__(stmxcsr rcontext(tcr.lisp_mxcsr))
+	__(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+	__(emms)
+	__(pop rcontext(tcr.foreign_sp))
+        __(addq $node_size,%rsp)
+        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
+        __ifdef([DARWIN_GS_HACK])
+         /* Lucky us; nothing is live here */
+         __(set_foreign_gs_base())
+        __endif
+	__(pop %rbp)
+	__ifdef([WINDOWS])
+	__(pop %csave6)
+	__(pop %csave5)
+	__endif
+	__(pop %csave4)
+	__(pop %csave3)
+	__(pop %csave2)
+	__(pop %csave1)
+	__(pop %csave0)
+	__(movq -8(%rbp),%rax)
+        __(movq -16(%rbp),%rdx)
+	__(movq -24(%rbp),%xmm0)
+        __(movq -32(%rbp),%xmm1)
+	__(leave)
+	__(ret)		
+_endsubp(callback)
+
+/* arg_x = array, arg_y = i, arg_z = j. Typecheck everything.
+   We don't know whether the array is alleged to be simple or
+   not, and don't know anythng about the element type.  */
+        	
+_spentry(aref2)
+        __(testb $fixnummask,%arg_y_b)
+        __(jne 0f)
+        
+        __(testb $fixnummask,%arg_z_b)
+        __(jne 1f)
+        __(extract_typecode(%arg_x,%imm0))
+        __(cmpb $subtag_arrayH,%imm0_b)
+        __(jne 2f)
+        __(cmpq $2<<fixnumshift,arrayH.rank(%arg_x))
+        __(jne 2f)
+        __(cmpq arrayH.dim0(%arg_x),%arg_y)
+        __(jae 3f)
+        __(movq arrayH.dim0+node_size(%arg_x),%imm0)
+        __(cmpq %imm0,%arg_z)
+        __(jae 4f)
+        __(unbox_fixnum(%imm0,%imm0))
+        __(mulq %arg_y)         /* imm0 <- imm0 * arg_y */
+        __(addq %imm0,%arg_z)
+        __(movq %arg_x,%arg_y)
+6:      __(addq arrayH.displacement(%arg_y),%arg_z)
+        __(movq arrayH.data_vector(%arg_y),%arg_y)
+        __(extract_subtag(%arg_y,%imm1_b))
+        __(cmpb $subtag_vectorH,%imm1_b)
+        __(ja C(misc_ref_common))
+        __(jmp 6b)
+0:      __(uuo_error_reg_not_fixnum(Rarg_y))
+1:      __(uuo_error_reg_not_fixnum(Rarg_z))
+2:      __(uuo_error_reg_not_type(Rarg_x,error_object_not_array_2d))
+3:      __(uuo_error_array_bounds(Rarg_y,Rarg_x))
+4:      __(uuo_error_array_bounds(Rarg_z,Rarg_x))
+        
+_endsubp(aref2)
+
+/* %temp0 = array, %arg_x = i,%arg_y = j, %arg_z = k */
+_spentry(aref3)
+        __(testb $fixnummask,%arg_x_b)
+        __(jne 0f)
+        __(testb $fixnummask,%arg_y_b)
+        __(jne 1f)
+        __(testb $fixnummask,%arg_z_b)
+        __(jne 2f)
+        __(extract_typecode(%temp0,%imm0))
+        __(cmpb $subtag_arrayH,%imm0_b)
+        __(jne 3f)
+        __(cmpq $3<<fixnumshift,arrayH.rank(%temp0))
+        __(jne 3f)
+        __(cmpq arrayH.dim0(%temp0),%arg_x)
+        __(jae 5f)
+        __(movq arrayH.dim0+node_size(%temp0),%imm0)
+        __(cmpq %imm0,%arg_y)
+        __(jae 6f)
+        __(unbox_fixnum(%imm0,%imm0))
+        __(movq arrayH.dim0+(node_size*2)(%temp0),%imm1)
+        __(cmpq %imm1,%arg_z)
+        __(jae 7f)
+        __(unbox_fixnum(%imm1,%imm1))
+        __(imulq %imm1,%arg_y)
+        __(mulq %imm1)
+        __(imulq %imm0,%arg_x)
+        __(addq %arg_x,%arg_z)
+        __(addq %arg_y,%arg_z)
+        __(movq %temp0,%arg_y)
+8:      __(addq arrayH.displacement(%arg_y),%arg_z)
+        __(movq arrayH.data_vector(%arg_y),%arg_y)
+        __(extract_subtag(%arg_y,%imm1_b))
+        __(cmpb $subtag_vectorH,%imm1_b)
+        __(ja C(misc_ref_common))
+        __(jmp 8b)
+0:      __(uuo_error_reg_not_fixnum(Rarg_x))
+1:      __(uuo_error_reg_not_fixnum(Rarg_y))	
+2:      __(uuo_error_reg_not_fixnum(Rarg_z))
+3:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_3d))
+5:      __(uuo_error_array_bounds(Rarg_x,Rtemp0))
+6:      __(uuo_error_array_bounds(Rarg_y,Rtemp0))
+7:      __(uuo_error_array_bounds(Rarg_z,Rtemp0))
+        
+_endsubp(aref3)
+        
+/* As with aref2, but temp0 = array, arg_x = i, arg_y = j, arg_z = new_value */
+_spentry(aset2)
+        __(testb $fixnummask,%arg_x_b)
+        __(jne 0f)
+        __(testb $fixnummask,%arg_y_b)
+        __(jne 1f)
+        __(extract_typecode(%temp0,%imm0))
+        __(cmpb $subtag_arrayH,%imm0_b)
+        __(jne 2f)
+        __(cmpq $2<<fixnumshift,arrayH.rank(%temp0))
+        __(jne 2f)
+        __(cmpq arrayH.dim0(%temp0),%arg_x)
+        __(jae 4f)
+        __(movq arrayH.dim0+node_size(%temp0),%imm0)
+        __(cmpq %imm0,%arg_y)
+        __(jae 5f)
+        __(unbox_fixnum(%imm0,%imm0))
+        __(mulq %arg_x)         /* imm0 <- imm0 * arg_x */
+        __(addq %imm0,%arg_y)
+        __(movq %temp0,%arg_x)
+6:      __(addq arrayH.displacement(%arg_x),%arg_y)
+        __(movq arrayH.data_vector(%arg_x),%arg_x)
+        __(extract_subtag(%arg_x,%imm1_b))
+        __(cmpb $subtag_vectorH,%imm1_b)
+        __(ja C(misc_set_common))
+        __(jmp 6b)
+0:      __(uuo_error_reg_not_fixnum(Rarg_x))
+1:      __(uuo_error_reg_not_fixnum(Rarg_y))
+2:      __(uuo_error_reg_not_type(Rtemp0,error_object_not_array_2d))
+4:      __(uuo_error_array_bounds(Rarg_x,Rtemp0))
+5:      __(uuo_error_array_bounds(Rarg_y,Rtemp0))
+_endsubp(aset2)
+
+/* %temp1 = array, %temp0 = i, %arg_x = j, %arg_y = k, %arg_y = newval. */
+
+_spentry(aset3)
+        __(testb $fixnummask,%temp0_b)
+        __(jne 0f)
+        __(testb $fixnummask,%arg_x_b)
+        __(jne 1f)
+        __(testb $fixnummask,%arg_y_b)
+        __(jne 2f)
+        __(extract_typecode(%temp1,%imm0))
+        __(cmpb $subtag_arrayH,%imm0_b)
+        __(jne 3f)
+        __(cmpq $3<<fixnumshift,arrayH.rank(%temp1))
+        __(jne 3f)
+        __(cmpq arrayH.dim0(%temp1),%temp0)
+        __(jae 5f)
+        __(movq arrayH.dim0+node_size(%temp1),%imm0)
+        __(cmpq %imm0,%arg_x)
+        __(jae 6f)
+        __(unbox_fixnum(%imm0,%imm0))
+        __(movq arrayH.dim0+(node_size*2)(%temp1),%imm1)
+        __(cmpq %imm1,%arg_y)
+        __(jae 7f)
+        __(unbox_fixnum(%imm1,%imm1))
+        __(imulq %imm1,%arg_x)
+        __(mulq %imm1)
+        __(imulq %imm0,%temp0)
+        __(addq %temp0,%arg_y)
+        __(addq %arg_x,%arg_y)
+        __(movq %temp1,%arg_x)
+8:      __(addq arrayH.displacement(%arg_x),%arg_y)
+        __(movq arrayH.data_vector(%arg_x),%arg_x)
+        __(extract_subtag(%arg_x,%imm1_b))
+        __(cmpb $subtag_vectorH,%imm1_b)
+        __(ja C(misc_set_common))
+        __(jmp 8b)
+	
+0:      __(uuo_error_reg_not_fixnum(Rtemp0))
+1:      __(uuo_error_reg_not_fixnum(Rarg_x))
+2:      __(uuo_error_reg_not_fixnum(Rarg_y))
+3:      __(uuo_error_reg_not_type(Rtemp1,error_object_not_array_3d))
+5:      __(uuo_error_array_bounds(Rtemp0,Rtemp1))
+6:      __(uuo_error_array_bounds(Rarg_x,Rtemp1))
+6:      __(uuo_error_array_bounds(Rarg_x,Rtemp1))
+7:      __(uuo_error_array_bounds(Rarg_y,Rtemp1))
+	
+_endsubp(aset3)
+
+        
+
+
+/* Prepend all but the first five (4 words of code, inner fn) and last   */
+/* (lfbits) elements of %fn to the "arglist".   */
+	
+_spentry(call_closure)
+        new_local_labels()
+        __(subq $fulltag_function-fulltag_misc,%fn)
+        __(vector_length(%fn,%imm0))
+	
+        __(subq $6<<fixnumshift,%imm0)  /* imm0 = inherited arg count   */
+        __(lea (%nargs_q,%imm0),%imm1)
+        __(cmpl $nargregs<<fixnumshift,%imm1_l)
+        __(jna local_label(regs_only))
+        __(pop %ra0)
+        __(cmpl $nargregs<<fixnumshift,%nargs)
+        __(jna local_label(no_insert))
+	
+/* Some arguments have already been pushed.  Push imm0's worth   */
+/* of NILs, copy those arguments that have already been vpushed from   */
+/* the old TOS to the new, then insert all of the inerited args   */
+/* and go to the function.  */
+	
+        __(movq %imm0,%imm1)
+local_label(push_nil_loop):     
+        __(push $nil_value)
+        __(sub $fixnumone,%imm1)
+        __(jne local_label(push_nil_loop))
+	
+/* Need to use arg regs as temporaries here.    */
+        __(movq %rsp,%temp1)
+        __(push %arg_z)
+        __(push %arg_y)
+        __(push %arg_x)
+        __(lea 3*node_size(%rsp,%imm0),%arg_x)
+        __(lea -nargregs<<fixnumshift(%nargs_q),%arg_y)
+local_label(copy_already_loop): 
+        __(movq (%arg_x),%arg_z)
+        __(addq $fixnumone,%arg_x)
+        __(movq %arg_z,(%temp1))
+        __(addq $fixnumone,%temp1)
+        __(subq $fixnumone,%arg_y)
+        __(jne local_label(copy_already_loop))
+	
+        __(movl $5<<fixnumshift,%imm1_l) /* skip code, new fn   */
+local_label(insert_loop):               
+        __(movq misc_data_offset(%fn,%imm1),%arg_z)
+        __(addq $node_size,%imm1)
+        __(addl $fixnum_one,%nargs)
+        __(subq $node_size,%arg_x)
+        __(movq %arg_z,(%arg_x))
+        __(subq $fixnum_one,%imm0)
+        __(jne local_label(insert_loop))
+
+        /* Recover the argument registers, pushed earlier   */
+        __(pop %arg_x)
+        __(pop %arg_y)
+        __(pop %arg_z)
+        __(jmp local_label(go))
+
+/* Here if nothing was pushed by the caller.  If we're  */
+/* going to push anything, we have to reserve a stack  */
+/* frame first. (We'll need to push something if the  */
+/* sum of %nargs and %imm0 is greater than nargregs)   */
+	
+local_label(no_insert):
+        __(lea (%nargs_q,%imm0),%imm1)
+        __(cmpq $nargregs<<fixnumshift,%imm1)
+        __(jna local_label(no_insert_no_frame))
+        /* Reserve space for a stack frame   */
+        __(push $reserved_frame_marker)
+        __(push $reserved_frame_marker)
+local_label(no_insert_no_frame):        
+	/* nargregs or fewer args were already vpushed.   */
+	/* if exactly nargregs, vpush remaining inherited vars.   */
+        __(cmpl $nargregs<<fixnumshift,%nargs)
+        __(movl $5<<fixnumshift,%imm1_l) /* skip code, new fn   */
+        __(leaq 5<<fixnumshift(%imm0),%temp1)
+        __(jnz local_label(set_regs))
+local_label(vpush_remaining):  
+        __(push misc_data_offset(%fn,%imm1))
+        __(addq $node_size,%imm1)
+        __(addl $fixnumone,%nargs)
+        __(subq $node_size,%imm0)
+        __(jnz local_label(vpush_remaining))
+        __(jmp local_label(go))
+local_label(set_regs):
+	/* if nargs was > 1 (and we know that it was < 3), it must have   */
+	/* been 2.  Set arg_x, then vpush the remaining args.   */
+        __(cmpl $fixnumone,%nargs)
+        __(jle local_label(set_y_z))
+local_label(set_arg_x): 
+        __(subq $node_size,%temp1)
+        __(movq misc_data_offset(%fn,%temp1),%arg_x)
+        __(addl $fixnumone,%nargs)
+        __(subq $fixnumone,%imm0)
+        __(jne local_label(vpush_remaining))
+        __(jmp local_label(go))
+	/* Maybe set arg_y or arg_z, preceding args   */
+local_label(set_y_z):
+        __(jne local_label(set_arg_z))
+	/* Set arg_y, maybe arg_x, preceding args   */
+local_label(set_arg_y): 
+        __(subq $node_size,%temp1)
+        __(movq misc_data_offset(%fn,%temp1),%arg_y)
+        __(addl $fixnumone,%nargs)
+        __(subq $fixnum_one,%imm0)
+        __(jnz local_label(set_arg_x))
+        __(jmp local_label(go))
+local_label(set_arg_z): 
+        __(subq $node_size,%temp1)
+        __(movq misc_data_offset(%fn,%temp1),%arg_z)
+        __(addl $fixnumone,%nargs)
+        __(subq $fixnum_one,%imm0)
+        __(jne local_label(set_arg_y))
+local_label(go):        
+        __(movq misc_data_offset+(4*node_size)(%fn),%fn)
+        __(push %ra0)
+        __(jmp *%fn)
+local_label(regs_only):
+        __(leaq 5<<fixnumshift(%imm0),%temp1)
+        __(testl %nargs,%nargs)
+        __(jne local_label(some_args))
+        __(cmpw $node_size,%imm0)
+        __(movq misc_data_offset-node_size(%fn,%temp1),%arg_z)
+        __(je local_label(rgo))
+        __(cmpw $2*node_size,%imm0)
+        __(movq misc_data_offset-(node_size*2)(%fn,%temp1),%arg_y)
+        __(je local_label(rgo))
+        __(movq misc_data_offset-(node_size*3)(%fn,%temp1),%arg_x)
+local_label(rgo):
+        __(addw %imm0_w,%nargs_w)
+        __(jmp *misc_data_offset+(4*node_size)(%fn))
+local_label(some_args):         
+        __(cmpl $2*node_size,%nargs)
+        __(jz local_label(rtwo))
+        /* One arg was passed, could be one or two inherited args */
+        __(cmpw $node_size,%imm0)
+        __(movq misc_data_offset-node_size(%fn,%temp1),%arg_y)
+        __(je local_label(rgo))
+        __(movq misc_data_offset-(node_size*2)(%fn,%temp1),%arg_x)
+        __(jmp local_label(rgo))
+local_label(rtwo):     
+        __(movq misc_data_offset-node_size(%fn,%temp1),%arg_x)
+        __(jmp local_label(rgo))
+_endsubp(call_closure)
+                                        
+        
+_spentry(poweropen_callbackX)
+_endsubp(poweropen_callbackX)
+	
+	
+_spentry(poweropen_ffcallX)
+_endsubp(poweropen_ffcallX)
+        	
+_spentry(poweropen_syscall)
+_endsubp(poweropen_syscall)
+
+_spentry(eabi_ff_call)
+_endsubp(eabi_ff_call)
+
+_spentry(eabi_callback)
+_endsubp(eabi_callback)
+
+
+/* Unused, and often not used on PPC either  */
+_spentry(callbuiltin)
+	__(hlt)
+_endsubp(callbuiltin)
+
+_spentry(callbuiltin0)
+	__(hlt)
+_endsubp(callbuiltin0)
+
+_spentry(callbuiltin1)
+	__(hlt)
+_endsubp(callbuiltin1)
+
+_spentry(callbuiltin2)
+	__(hlt)
+_endsubp(callbuiltin2)
+
+_spentry(callbuiltin3)
+	__(hlt)
+_endsubp(callbuiltin3)
+	
+_spentry(restorefullcontext)
+	__(hlt)
+_endsubp(restorefullcontext)
+
+_spentry(savecontextvsp)
+	__(hlt)
+_endsubp(savecontextvsp)
+
+_spentry(savecontext0)
+	__(hlt)
+_endsubp(savecontext0)
+
+_spentry(restorecontext)
+	__(hlt)
+_endsubp(restorecontext)
+
+_spentry(stkconsyz)
+	__(hlt)
+_endsubp(stkconsyz)
+
+_spentry(stkvcell0)
+	__(hlt)
+_endsubp(stkvcell0)
+
+_spentry(stkvcellvsp)
+	__(hlt)
+_endsubp(stkvcellvsp)
+
+_spentry(breakpoint)
+        __(hlt)
+_endsubp(breakpoint)
+
+
+        __ifdef([DARWIN])
+        .if 1
+	.globl  C(lisp_objc_personality)
+C(lisp_objc_personality):
+	jmp *lisp_global(objc_2_personality)
+	
+	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+	.set L$set$12,LECIE1-LSCIE1
+	.long L$set$12	/* Length of Common Information Entry */
+LSCIE1:
+	.long	0x0	/* CIE Identifier Tag */
+	.byte	0x1	/* CIE Version */
+	.ascii "zPLR\0"	/* CIE Augmentation */
+	.byte	0x1	/* uleb128 0x1; CIE Code Alignment Factor */
+	.byte	0x78	/* sleb128 -8; CIE Data Alignment Factor */
+	.byte	0x10	/* CIE RA Column */
+	.byte	0x7
+	.byte	0x9b
+	.long	_lisp_objc_personality+4@GOTPCREL
+	.byte	0x10	/* LSDA Encoding (pcrel) */
+	.byte	0x10	/* FDE Encoding (pcrel) */
+	.byte	0xc	/* DW_CFA_def_cfa */
+	.byte	0x7	/* uleb128 0x7 */
+	.byte	0x8	/* uleb128 0x8 */
+	.byte	0x90	/* DW_CFA_offset, column 0x10 */
+	.byte	0x1	/* uleb128 0x1 */
+	.align 3
+LECIE1:
+        .globl _SPffcall.eh
+_SPffcall.eh:
+        .long LEFDEffcall-LSFDEffcall
+LSFDEffcall:      
+        .long LSFDEffcall-EH_frame1 /* FDE CIE offset */
+        .quad Lffcall-. /* FDE Initial Location */
+        .quad Lffcall_end-Lffcall /* FDE address range */
+        .byte 8 /* uleb128 0x8; Augmentation size */
+        .quad LLSDA1-.           /* Language Specific Data Area */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long Lffcall_setup-Lffcall
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x10	/* uleb128 0x10 */
+	.byte	0x86	/* DW_CFA_offset, column 0x6 */
+	.byte	0x2	/* uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long Lffcall_setup_end-Lffcall_setup
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x6	/* uleb128 0x6 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long Lffcall_call_end-Lffcall_call
+	.byte	0x83	/* DW_CFA_offset, column 0x3 */
+	.byte	0x3	/* uleb128 0x3 */
+	.align 3
+LEFDEffcall:
+        .globl _SPffcall_return_registers.eh
+_SPffcall_return_registers.eh:
+        .long LEFDEffcall_return_registers-LSFDEffcall_return_registers
+LSFDEffcall_return_registers:      
+        .long LSFDEffcall_return_registers-EH_frame1 /* FDE CIE offset */
+        .quad Lffcall_return_registers-. /* FDE Initial Location */
+        .quad Lffcall_return_registers_end-Lffcall_return_registers /* FDE address range */
+        .byte 8 /* uleb128 0x8; Augmentation size */
+        .quad LLSDA2-.           /* Language Specific Data Area */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long Lffcall_return_registers_setup-Lffcall_return_registers
+	.byte	0xe	/* DW_CFA_def_cfa_offset */
+	.byte	0x10	/* uleb128 0x10 */
+	.byte	0x86	/* DW_CFA_offset, column 0x6 */
+	.byte	0x2	/* uleb128 0x2 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long Lffcall_return_registers_setup_end-Lffcall_return_registers_setup
+	.byte	0xd	/* DW_CFA_def_cfa_register */
+	.byte	0x6	/* uleb128 0x6 */
+	.byte	0x4	/* DW_CFA_advance_loc4 */
+	.long Lffcall_return_registers_call_end-Lffcall_return_registers_call
+	.byte	0x83	/* DW_CFA_offset, column 0x3 */
+	.byte	0x3	/* uleb128 0x3 */
+	.align 3
+LEFDEffcall_return_registers:
+        .text
+        .endif
+        __endif
+        
+_spentry(unused_5)
+        __(hlt)
+Xspentry_end:           
+_endsubp(unused_5)
+        
+        .data
+        .globl C(spentry_start)
+        .globl C(spentry_end)
+C(spentry_start):       .quad Xspentry_start
+C(spentry_end):         .quad Xspentry_end
Index: /branches/new-random/lisp-kernel/x86-spjump32.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-spjump32.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-spjump32.s	(revision 13309)
@@ -0,0 +1,193 @@
+/*   Copyright (C) 2005-2009 Clozure Associates */
+/*   This file is part of Clozure CL.    */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public  */
+/*   License , known as the LLGPL and distributed with Clozure CL as the  */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these  */
+/*   conflict, the preamble takes precedence.    */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."  */
+
+/*   The LLGPL is also available online at  */
+/*   http://opensource.franz.com/preamble.html  */
+
+	
+        include(lisp.s)
+define([_spjump],[
+        .p2align 2
+        .globl _SP$1
+_exportfn(j_SP$1)
+          __(.long _SP$1)
+_endfn
+])
+	_beginfile
+        __ifdef([DARWIN])
+        .space 0x3000,0
+        __endif
+        __ifdef([WIN_32])
+        .space 0x5000-0x1000,0
+        __endif
+         .globl C(spjump_start)
+C(spjump_start):
+
+        _spjump(jmpsym)
+        _spjump(jmpnfn)
+        _spjump(funcall)
+        _spjump(mkcatch1v)
+        _spjump(mkunwind)
+        _spjump(mkcatchmv)
+        _spjump(throw)
+        _spjump(nthrowvalues)
+        _spjump(nthrow1value)
+        _spjump(bind)
+        _spjump(bind_self)
+        _spjump(bind_nil)
+        _spjump(bind_self_boundp_check)
+        _spjump(rplaca)
+        _spjump(rplacd)
+        _spjump(conslist)
+        _spjump(conslist_star)
+        _spjump(stkconslist)
+        _spjump(stkconslist_star)
+        _spjump(mkstackv)
+        _spjump(subtag_misc_ref)
+        _spjump(setqsym)
+        _spjump(progvsave)
+        _spjump(stack_misc_alloc)
+        _spjump(gvector)
+        _spjump(nvalret)
+        _spjump(mvpass)
+        _spjump(recover_values_for_mvcall)
+        _spjump(nthvalue)
+        _spjump(values)
+        _spjump(default_optional_args)
+        _spjump(opt_supplied_p)
+        _spjump(heap_rest_arg)
+        _spjump(req_heap_rest_arg)
+        _spjump(heap_cons_rest_arg)
+        _spjump(simple_keywords)
+        _spjump(keyword_args)
+        _spjump(keyword_bind)
+        _spjump(ffcall)
+        _spjump(aref2)
+        _spjump(ksignalerr)
+        _spjump(stack_rest_arg)
+        _spjump(req_stack_rest_arg)
+        _spjump(stack_cons_rest_arg)
+        _spjump(poweropen_callbackX)        
+        _spjump(call_closure)        
+        _spjump(getxlong)
+        _spjump(spreadargz)
+        _spjump(tfuncallgen)
+        _spjump(tfuncallslide)
+        _spjump(tfuncallvsp)
+        _spjump(tcallsymgen)
+        _spjump(tcallsymslide)
+        _spjump(tcallsymvsp)
+        _spjump(tcallnfngen)
+        _spjump(tcallnfnslide)
+        _spjump(tcallnfnvsp)
+        _spjump(misc_ref)
+        _spjump(misc_set)
+        _spjump(stkconsyz)
+        _spjump(stkvcell0)
+        _spjump(stkvcellvsp)      
+        _spjump(makestackblock)
+        _spjump(makestackblock0)
+        _spjump(makestacklist)
+        _spjump(stkgvector)
+        _spjump(misc_alloc)
+        _spjump(poweropen_ffcallX)
+        _spjump(gvset)
+        _spjump(macro_bind)
+        _spjump(destructuring_bind)
+        _spjump(destructuring_bind_inner)
+        _spjump(recover_values)
+        _spjump(vpopargregs)
+        _spjump(integer_sign)
+        _spjump(subtag_misc_set)
+        _spjump(spread_lexprz)
+        _spjump(store_node_conditional)
+        _spjump(reset)
+        _spjump(mvslide)
+        _spjump(save_values)
+        _spjump(add_values)
+        _spjump(callback)
+        _spjump(misc_alloc_init)
+        _spjump(stack_misc_alloc_init)
+        _spjump(set_hash_key)
+        _spjump(aset2)
+        _spjump(callbuiltin)
+        _spjump(callbuiltin0)
+        _spjump(callbuiltin1)
+        _spjump(callbuiltin2)
+        _spjump(callbuiltin3)
+        _spjump(popj)
+        _spjump(restorefullcontext)
+        _spjump(savecontextvsp)
+        _spjump(savecontext0)
+        _spjump(restorecontext)
+        _spjump(lexpr_entry)
+        _spjump(syscall2)
+        _spjump(builtin_plus)
+        _spjump(builtin_minus)
+        _spjump(builtin_times)
+        _spjump(builtin_div)
+        _spjump(builtin_eq)
+        _spjump(builtin_ne)
+        _spjump(builtin_gt)
+        _spjump(builtin_ge)
+        _spjump(builtin_lt)
+        _spjump(builtin_le)
+        _spjump(builtin_eql)
+        _spjump(builtin_length)
+        _spjump(builtin_seqtype)
+        _spjump(builtin_assq)
+        _spjump(builtin_memq)
+        _spjump(builtin_logbitp)
+        _spjump(builtin_logior)
+        _spjump(builtin_logand)
+        _spjump(builtin_ash)
+        _spjump(builtin_negate)
+        _spjump(builtin_logxor)
+        _spjump(builtin_aref1)
+        _spjump(builtin_aset1)
+        _spjump(breakpoint)
+        _spjump(eabi_ff_call)
+        _spjump(eabi_callback)
+        _spjump(syscall)
+        _spjump(getu64)
+        _spjump(gets64)
+        _spjump(makeu64)
+        _spjump(makes64)
+        _spjump(specref)
+        _spjump(specset)
+        _spjump(specrefcheck)
+        _spjump(restoreintlevel)
+        _spjump(makes32)
+        _spjump(makeu32)
+        _spjump(gets32)
+        _spjump(getu32)
+        _spjump(fix_overflow)
+        _spjump(mvpasssym)
+        _spjump(aref3)
+        _spjump(aset3)
+        _spjump(ffcall_return_registers)
+        _spjump(aset1)
+        _spjump(set_hash_key_conditional)
+        _spjump(unbind_interrupt_level)
+        _spjump(unbind)
+        _spjump(unbind_n)
+        _spjump(unbind_to)
+        _spjump(bind_interrupt_level_m1)
+        _spjump(bind_interrupt_level)
+        _spjump(bind_interrupt_level_0)
+        _spjump(progvrestore)
+        _spjump(nmkunwind)
+         .globl C(spjump_end)
+C(spjump_end):
+	.org C(spjump_start)+0x1000
+	
+        _endfile
+		
Index: /branches/new-random/lisp-kernel/x86-spjump64.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-spjump64.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-spjump64.s	(revision 13309)
@@ -0,0 +1,190 @@
+/*   Copyright (C) 2005-2009 Clozure Associates */
+/*   This file is part of Clozure CL.    */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public  */
+/*   License , known as the LLGPL and distributed with Clozure CL as the  */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,  */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these  */
+/*   conflict, the preamble takes precedence.    */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."  */
+
+/*   The LLGPL is also available online at  */
+/*   http://opensource.franz.com/preamble.html  */
+
+	
+        include(lisp.s)
+define([_spjump],[
+        .p2align 3
+        .globl _SP$1
+_exportfn(j_SP$1)
+          __(.quad _SP$1)
+_endfn
+])
+	_beginfile
+        __ifdef([DARWIN])
+        .space 0x5000,0
+        __endif
+         .globl C(spjump_start)
+C(spjump_start):
+
+        _spjump(jmpsym)
+        _spjump(jmpnfn)
+        _spjump(funcall)
+        _spjump(mkcatch1v)
+        _spjump(mkunwind)
+        _spjump(mkcatchmv)
+        _spjump(throw)
+        _spjump(nthrowvalues)
+        _spjump(nthrow1value)
+        _spjump(bind)
+        _spjump(bind_self)
+        _spjump(bind_nil)
+        _spjump(bind_self_boundp_check)
+        _spjump(rplaca)
+        _spjump(rplacd)
+        _spjump(conslist)
+        _spjump(conslist_star)
+        _spjump(stkconslist)
+        _spjump(stkconslist_star)
+        _spjump(mkstackv)
+        _spjump(subtag_misc_ref)
+        _spjump(setqsym)
+        _spjump(progvsave)
+        _spjump(stack_misc_alloc)
+        _spjump(gvector)
+        _spjump(nvalret)
+        _spjump(mvpass)
+        _spjump(recover_values_for_mvcall)
+        _spjump(nthvalue)
+        _spjump(values)
+        _spjump(default_optional_args)
+        _spjump(opt_supplied_p)
+        _spjump(heap_rest_arg)
+        _spjump(req_heap_rest_arg)
+        _spjump(heap_cons_rest_arg)
+        _spjump(simple_keywords)
+        _spjump(keyword_args)
+        _spjump(keyword_bind)
+        _spjump(ffcall)
+        _spjump(aref2)
+        _spjump(ksignalerr)
+        _spjump(stack_rest_arg)
+        _spjump(req_stack_rest_arg)
+        _spjump(stack_cons_rest_arg)
+        _spjump(poweropen_callbackX)        
+        _spjump(call_closure)        
+        _spjump(getxlong)
+        _spjump(spreadargz)
+        _spjump(tfuncallgen)
+        _spjump(tfuncallslide)
+        _spjump(tfuncallvsp)
+        _spjump(tcallsymgen)
+        _spjump(tcallsymslide)
+        _spjump(tcallsymvsp)
+        _spjump(tcallnfngen)
+        _spjump(tcallnfnslide)
+        _spjump(tcallnfnvsp)
+        _spjump(misc_ref)
+        _spjump(misc_set)
+        _spjump(stkconsyz)
+        _spjump(stkvcell0)
+        _spjump(stkvcellvsp)      
+        _spjump(makestackblock)
+        _spjump(makestackblock0)
+        _spjump(makestacklist)
+        _spjump(stkgvector)
+        _spjump(misc_alloc)
+        _spjump(poweropen_ffcallX)
+        _spjump(gvset)
+        _spjump(macro_bind)
+        _spjump(destructuring_bind)
+        _spjump(destructuring_bind_inner)
+        _spjump(recover_values)
+        _spjump(vpopargregs)
+        _spjump(integer_sign)
+        _spjump(subtag_misc_set)
+        _spjump(spread_lexprz)
+        _spjump(store_node_conditional)
+        _spjump(reset)
+        _spjump(mvslide)
+        _spjump(save_values)
+        _spjump(add_values)
+        _spjump(callback)
+        _spjump(misc_alloc_init)
+        _spjump(stack_misc_alloc_init)
+        _spjump(set_hash_key)
+        _spjump(aset2)
+        _spjump(callbuiltin)
+        _spjump(callbuiltin0)
+        _spjump(callbuiltin1)
+        _spjump(callbuiltin2)
+        _spjump(callbuiltin3)
+        _spjump(popj)
+        _spjump(restorefullcontext)
+        _spjump(savecontextvsp)
+        _spjump(savecontext0)
+        _spjump(restorecontext)
+        _spjump(lexpr_entry)
+        _spjump(poweropen_syscall)
+        _spjump(builtin_plus)
+        _spjump(builtin_minus)
+        _spjump(builtin_times)
+        _spjump(builtin_div)
+        _spjump(builtin_eq)
+        _spjump(builtin_ne)
+        _spjump(builtin_gt)
+        _spjump(builtin_ge)
+        _spjump(builtin_lt)
+        _spjump(builtin_le)
+        _spjump(builtin_eql)
+        _spjump(builtin_length)
+        _spjump(builtin_seqtype)
+        _spjump(builtin_assq)
+        _spjump(builtin_memq)
+        _spjump(builtin_logbitp)
+        _spjump(builtin_logior)
+        _spjump(builtin_logand)
+        _spjump(builtin_ash)
+        _spjump(builtin_negate)
+        _spjump(builtin_logxor)
+        _spjump(builtin_aref1)
+        _spjump(builtin_aset1)
+        _spjump(breakpoint)
+        _spjump(eabi_ff_call)
+        _spjump(eabi_callback)
+        _spjump(syscall)
+        _spjump(getu64)
+        _spjump(gets64)
+        _spjump(makeu64)
+        _spjump(makes64)
+        _spjump(specref)
+        _spjump(specset)
+        _spjump(specrefcheck)
+        _spjump(restoreintlevel)
+        _spjump(makes32)
+        _spjump(makeu32)
+        _spjump(gets32)
+        _spjump(getu32)
+        _spjump(fix_overflow)
+        _spjump(mvpasssym)
+        _spjump(aref3)
+        _spjump(aset3)
+        _spjump(ffcall_return_registers)
+        _spjump(unused_5)
+        _spjump(set_hash_key_conditional)
+        _spjump(unbind_interrupt_level)
+        _spjump(unbind)
+        _spjump(unbind_n)
+        _spjump(unbind_to)
+        _spjump(bind_interrupt_level_m1)
+        _spjump(bind_interrupt_level)
+        _spjump(bind_interrupt_level_0)
+        _spjump(progvrestore)
+        _spjump(nmkunwind)
+         .globl C(spjump_end)
+C(spjump_end):
+	.org 0x1000
+	
+        _endfile
+		
Index: /branches/new-random/lisp-kernel/x86-subprims32.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-subprims32.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-subprims32.s	(revision 13309)
@@ -0,0 +1,126 @@
+        include(lisp.s)
+	_beginfile
+	
+	.globl _SPmkcatch1v
+	.globl _SPnthrow1value
+	
+/* This is called from a c-style context and calls a lisp function.*/
+/* This does the moral equivalent of*/
+/*   (loop */
+/*	(let* ((fn (%function_on_top_of_lisp_stack)))*/
+/*	  (if fn*/
+/*            (catch %toplevel-catch%*/
+/*	       (funcall fn))*/
+/*            (return nil))))*/
+
+
+_exportfn(toplevel_loop)
+Xsubprims_start:        	
+	__(push %ebp)
+	__(movl %esp,%ebp)
+	/* Switch to the lisp stack */
+	__(movl %esp,rcontext(tcr.foreign_sp))
+	__(movl rcontext(tcr.save_vsp),%esp)
+	__(push $0)
+	__(mov %esp,%ebp)
+	__(cmpl $0,C(GCDebug))
+	__(je 1f)
+        __(ref_global(initial_tcr,%imm0))
+        __(cmpl rcontext(tcr.linear),%imm0)
+        __(jne 1f)
+	__(clr %imm0)
+	__(uuo_error_gc_trap)
+1:
+	__(jmp local_label(test))
+local_label(loop):
+	__(ref_nrs_value(toplcatch,%arg_z))
+	__(movl [$]local_label(back_from_catch),%ra0)
+	__(movl [$]local_label(test),%xfn)
+        __(push %ra0)
+	__(jmp _SPmkcatch1v)
+__(tra(local_label(back_from_catch)))
+	__(movl %arg_y,%temp0)
+	__(pushl [$]local_label(back_from_funcall))
+	__(set_nargs(0))
+	__(jmp _SPfuncall)
+__(tra(local_label(back_from_funcall)))
+	__(movl $fixnumone,%imm0)
+	__(movl [$]local_label(test),%ra0)
+	__(jmp _SPnthrow1value)
+__(tra(local_label(test)))
+	__(movl 4(%ebp),%arg_y)
+	__(cmpl $nil_value,%arg_y)
+	__(jnz local_label(loop))
+local_label(back_to_c):
+	__(movl rcontext(tcr.foreign_sp),%esp)
+	__(movl %esp,%ebp)
+	__(leave)
+	__(ret)
+
+/* This is called from C code when a thread (including the initial thread) */
+/* starts execution.  (Historically, it also provided a primitive way of */
+/* "resettting" a thread in the event of catastrophic failure, but this */
+/* hasn't worked in a long time.) */
+/* For compatibility with PPC code, this is called with the first foreign */
+/* argument pointing to the thread's TCR and the second foreign argument */
+/*  being a Boolean which indicates whether the thread should try to */
+/* "reset" itself or start running lisp code. */
+/* The reset/panic code doesn't work. */
+
+_exportfn(C(start_lisp))
+	__(push %ebp)
+	__(movl %esp, %ebp)
+	__(push %edi)
+	__(push %esi)
+	__(push %ebx)
+	__(mov 8(%ebp), %ebx)	/* get tcr */
+        __(cmpb $0,C(rcontext_readonly))
+        __(jne 0f)
+        __(movw tcr.ldt_selector(%ebx), %rcontext_reg)
+0:              
+        __(movl 8(%ebp),%eax)
+        __(cmpl rcontext(tcr.linear),%eax)
+        __(je 1f)
+        __(hlt)
+1:              
+        .if c_stack_16_byte_aligned
+	__(sub $12, %esp) 	/* stack now 16-byte aligned */
+        .else
+        __(andl $~15,%esp)
+        .endif
+	__(clr %arg_z)
+	__(clr %arg_y)	
+	__(clr %temp0)
+	__(clr %temp1)
+	__(clr %fn)
+	__(pxor %fpzero, %fpzero)
+	__(stmxcsr rcontext(tcr.foreign_mxcsr))
+	__(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
+        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
+	__(movl $TCR_STATE_LISP, rcontext(tcr.valence))
+	__(call toplevel_loop)
+	__(movl $TCR_STATE_FOREIGN, rcontext(tcr.valence))
+	__(emms)
+        __(leal -3*node_size(%ebp),%esp)
+	__(pop %ebx)
+	__(pop %esi)
+	__(pop %edi)
+	__(ldmxcsr rcontext(tcr.foreign_mxcsr))
+        __ifdef([WIN32_ES_HACK])
+         __(push %ds)
+         __(pop %es)
+        __endif
+	__(movl $nil_value, %eax)
+	__(leave)
+	__(ret)
+Xsubprims_end:           
+_endfn
+
+        .data
+        .globl C(subprims_start)
+        .globl C(subprims_end)
+C(subprims_start):      .long Xsubprims_start
+C(subprims_end):        .long Xsubprims_end
+        .text
+
+
Index: /branches/new-random/lisp-kernel/x86-subprims64.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-subprims64.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-subprims64.s	(revision 13309)
@@ -0,0 +1,156 @@
+/*   Copyright (C) 2005-2009 Clozure Associates*/
+/*   This file is part of Clozure CL.  */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public*/
+/*   License , known as the LLGPL and distributed with Clozure CL as the*/
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,*/
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these*/
+/*   conflict, the preamble takes precedence.  */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY."*/
+
+/*   The LLGPL is also available online at*/
+/*   http://opensource.franz.com/preamble.html*/
+
+
+	include(lisp.s)
+	_beginfile
+
+	.globl _SPmkcatch1v
+	.globl _SPnthrow1value
+
+
+/* This is called from a c-style context and calls a lisp function.*/
+/* This does the moral equivalent of*/
+/*   (loop */
+/*	(let* ((fn (%function_on_top_of_lisp_stack)))*/
+/*	  (if fn*/
+/*            (catch %toplevel-catch%*/
+/*	       (funcall fn))*/
+/*            (return nil))))*/
+
+
+_exportfn(toplevel_loop)
+Xsubprims_start:        	
+	__(push %rbp)
+	__(movq %rsp,%rbp)
+	/* Switch to the lisp stack */
+        __(push $0)
+        __(push $0)
+	__(movq %rsp,rcontext(tcr.foreign_sp))
+	__(movq rcontext(tcr.save_vsp),%rsp)
+	__(push $0)
+	__(movq %rsp,%rbp)
+        
+        __(TSP_Alloc_Fixed(0,%temp0))
+        __(movsd %fpzero,tsp_frame.save_rbp(%temp0)) /* sentinel */
+	__(jmp local_label(test))
+local_label(loop):
+	__(ref_nrs_value(toplcatch,%arg_z))
+	__(leaq local_label(back_from_catch)(%rip),%ra0)
+	__(leaq local_label(test)(%rip),%xfn)
+        __(push %ra0)
+	__(jmp _SPmkcatch1v)
+__(tra(local_label(back_from_catch)))
+	__(movq %arg_x,%temp0)
+	__(leaq local_label(back_from_funcall)(%rip),%ra0)
+        __(push %ra0)
+	__(set_nargs(0))
+	__(jmp _SPfuncall)
+__(tra(local_label(back_from_funcall)))
+	__(movl $fixnumone,%imm0_l)
+	__(leaq local_label(test)(%rip),%ra0)
+	__(jmp _SPnthrow1value)	
+__(tra(local_label(test)))
+	__(movq 8(%rbp),%arg_x)
+	__(cmpq $nil_value,%arg_x)
+	__(jnz local_label(loop))
+local_label(back_to_c):
+        __(discard_temp_frame(%imm0))
+	__(movq rcontext(tcr.foreign_sp),%rsp)
+        __(addq $dnode_size,%rsp)
+	__(movq %rsp,%rbp)
+	__(leave)
+	__(ret)
+
+/* This is called from C code when a thread (including the initial thread) */
+/* starts execution.  (Historically, it also provided a primitive way of */
+/* "resettting" a thread in the event of catastrophic failure, but this */
+/* hasn't worked in a long time.) */
+/* For compatibility with PPC code, this is called with the first foreign */
+/* argument pointing to the thread's TCR and the second foreign argument */
+/*  being a Boolean which indicates whether the thread should try to */
+/* "reset" itself or start running lisp code.  Both of these arguments */
+/* are currently ignored (the TCR is maintained in a segment register and */
+/*  the reset/panic code doesn't work ...), except on Windows, where we use */
+/* the first arg to set up the TCR register */	
+   
+_exportfn(C(start_lisp))
+	__(push %rbp)
+	__(movq %rsp,%rbp)
+	__(push %csave0)
+	__(push %csave1)
+	__(push %csave2)
+	__(push %csave3)
+	__(push %csave4)
+	__ifdef([WINDOWS])
+	__(push %csave5)
+	__(push %csave6)
+        __endif
+        __ifdef([TCR_IN_GPR])
+	__(movq %carg0,%rcontext_reg)
+	__endif
+        __ifdef([DARWIN_GS_HACK])
+         __(set_gs_base())
+        __endif
+	__(sub $8,%rsp)	/* %rsp is now 16-byte aligned  */
+	/* Put harmless values in lisp node registers  */
+	__(clr %arg_z)
+	__(clr %arg_y)
+	__(clr %arg_x)
+	__(clr %temp0)
+	__(clr %temp1)
+	__(clr %temp2)
+	__(clr %fn)
+        /*	__(clr %ra0) */ /* %ra0 == %temp2, now zeroed above */
+	__(clr %save0)
+	__(clr %save1)
+	__(clr %save2)
+	__ifndef([TCR_IN_GPR]) /* no %save3, r11 is %rcontext_reg */
+	__(clr %save3)
+	__endif
+	__(pxor %fpzero,%fpzero)	/* fpzero = 0.0[d0] */
+        __(stmxcsr rcontext(tcr.foreign_mxcsr))
+        __(andb $~mxcsr_all_exceptions,rcontext(tcr.foreign_mxcsr))
+        __(ldmxcsr rcontext(tcr.lisp_mxcsr))
+	__(movq $TCR_STATE_LISP,rcontext(tcr.valence))
+	__(call toplevel_loop)
+	__(movq $TCR_STATE_FOREIGN,rcontext(tcr.valence))
+	__(emms)
+	__(addq $8,%rsp)	/* discard alignment word */
+	__ifdef([WINDOWS])
+	__(pop %csave6)
+	__(pop %csave5)
+	__endif
+	__(pop %csave4)
+	__(pop %csave3)
+	__(pop %csave2)
+	__(pop %csave1)
+	__(pop %csave0)
+        __(ldmxcsr rcontext(tcr.foreign_mxcsr))
+        __ifdef([DARWIN_GS_HACK])
+         __(set_foreign_gs_base)
+        __endif
+	__(movl $nil_value,%eax)
+	__(leave)
+	__(ret)
+Xsubprims_end:           
+_endfn
+
+        .data
+        .globl C(subprims_start)
+        .globl C(subprims_end)
+C(subprims_start):      .quad Xsubprims_start
+C(subprims_end):        .quad Xsubprims_end
+        .text
+                                
Index: /branches/new-random/lisp-kernel/x86-uuo.s
===================================================================
--- /branches/new-random/lisp-kernel/x86-uuo.s	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86-uuo.s	(revision 13309)
@@ -0,0 +1,104 @@
+/*   Copyright (C) 2005-2009 Clozure Associates */
+/*   This file is part of Clozure CL.   */
+
+/*   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public */
+/*   License , known as the LLGPL and distributed with Clozure CL as the */
+/*   file "LICENSE".  The LLGPL consists of a preamble and the LGPL, */
+/*   which is distributed with Clozure CL as the file "LGPL".  Where these */
+/*   conflict, the preamble takes precedence.   */
+
+/*   Clozure CL is referenced in the preamble as the "LIBRARY." */
+
+/*   The LLGPL is also available online at */
+/*   http://opensource.franz.com/preamble.html */
+
+
+define([uuo_error_too_few_args],[
+        int [$]0xc0
+])
+
+define([uuo_error_too_many_args],[
+        int [$]0xc1
+])
+
+define([uuo_error_wrong_number_of_args],[
+        int [$]0xc2
+])
+
+
+define([uuo_error_gc_trap],[
+        int [$]0xc4
+])                        
+
+
+define([uuo_error_debug_trap],[
+        int [$]0xca
+])                        
+        
+                                        
+/* If we're allocating a CONS, the tcr's save_allocptr slot will be */
+/* tagged as a cons.  Otherwise, it'll be tagged as fulltag_misc, */
+/* and we have to look at the immediate registers to determine what's */
+/* being allocated. */
+define([uuo_alloc],[
+	int [$]0xc5
+])
+				
+define([uuo_error_not_callable],[
+        int [$]0xc6
+])
+
+
+define([xuuo],[
+	ud2a
+	.byte $1
+])
+	
+define([tlb_too_small],[
+	xuuo(1)
+])
+
+define([interrupt_now],[
+	xuuo(2)
+])		
+
+define([suspend_now],[
+	xuuo(3)
+])		
+
+define([uuo_error_reg_not_fixnum],[
+	int [$]0xf0|$1
+])	
+	
+define([uuo_error_reg_not_list],[
+	int [$]0xe0|$1
+])
+
+define([uuo_error_reg_not_tag],[
+	int [$]0xd0|$1
+	.byte $2
+])			
+
+define([uuo_error_reg_not_type],[
+	int [$]0xb0|$1
+	.byte $2
+])
+
+define([uuo_error_reg_not_fixnum],[
+	int [$]0xf0|$1
+])	
+		
+define([uuo_error_reg_unbound],[
+	int [$]0x90|$1
+])	
+
+define([uuo_error_vector_bounds],[
+	int [$]0xc8
+	.byte ($1<<4)|($2)
+])	
+
+define([uuo_error_array_bounds],[
+	int [$]0xcb
+	.byte ($1<<4)|($2)
+])	
+
Index: /branches/new-random/lisp-kernel/x86_print.c
===================================================================
--- /branches/new-random/lisp-kernel/x86_print.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/x86_print.c	(revision 13309)
@@ -0,0 +1,608 @@
+/*
+   Copyright (C) 2005-2009, Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <setjmp.h>
+
+#include "lisp.h"
+#include "area.h"
+#include "lisp-exceptions.h"
+#include "lisp_globals.h"
+
+void
+sprint_lisp_object(LispObj, int);
+
+#define PBUFLEN 252
+
+char printbuf[PBUFLEN + 4];
+int bufpos = 0;
+
+jmp_buf escape;
+
+void
+add_char(char c)
+{
+  if (bufpos >= PBUFLEN) {
+    longjmp(escape, 1);
+  } else {
+    printbuf[bufpos++] = c;
+  }
+}
+
+void
+add_string(char *s, int len) 
+{
+  while(len--) {
+    add_char(*s++);
+  }
+}
+
+void
+add_lisp_base_string(LispObj str)
+{
+  lisp_char_code *src = (lisp_char_code *)  (ptr_from_lispobj(str + misc_data_offset));
+  natural i, n = header_element_count(header_of(str));
+
+  for (i=0; i < n; i++) {
+    add_char((char)(*src++));
+  }
+}
+
+void
+add_c_string(char *s)
+{
+  add_string(s, strlen(s));
+}
+
+char numbuf[64], *digits = "0123456789ABCDEF";
+
+
+void
+sprint_unsigned_decimal_aux(natural n, Boolean first)
+{
+  if (n == 0) {
+    if (first) {
+      add_char('0');
+    }
+  } else {
+    sprint_unsigned_decimal_aux(n/10, false);
+    add_char(digits[n%10]);
+  }
+}
+
+void
+sprint_unsigned_decimal(natural n)
+{
+  sprint_unsigned_decimal_aux(n, true);
+}
+
+void
+sprint_signed_decimal(signed_natural n)
+{
+  if (n < 0) {
+    add_char('-');
+    n = -n;
+  }
+  sprint_unsigned_decimal(n);
+}
+
+
+void
+sprint_unsigned_hex(natural n)
+{
+  int i, 
+    ndigits =
+#if WORD_SIZE == 64
+    16
+#else
+    8
+#endif
+    ;
+
+  add_c_string("#x");
+  for (i = 0; i < ndigits; i++) {
+    add_char(digits[(n>>(4*(ndigits-(i+1))))&15]);
+  }
+}
+
+void
+sprint_list(LispObj o, int depth)
+{
+  LispObj the_cdr;
+  
+  add_char('(');
+  while(1) {
+    if (o != lisp_nil) {
+      sprint_lisp_object(ptr_to_lispobj(car(o)), depth);
+      the_cdr = ptr_to_lispobj(cdr(o));
+      if (the_cdr != lisp_nil) {
+        add_char(' ');
+        if (fulltag_of(the_cdr) == fulltag_cons) {
+          o = the_cdr;
+          continue;
+        }
+        add_c_string(". ");
+        sprint_lisp_object(the_cdr, depth);
+        break;
+      }
+    }
+    break;
+  }
+  add_char(')');
+}
+
+/* 
+  Print a list of method specializers, using the class name instead of the class object.
+*/
+
+void
+sprint_specializers_list(LispObj o, int depth)
+{
+  LispObj the_cdr, the_car;
+  
+  add_char('(');
+  while(1) {
+    if (o != lisp_nil) {
+      the_car = car(o);
+      if (fulltag_of(the_car) == fulltag_misc) {
+        sprint_lisp_object(deref(deref(the_car,3), 4), depth);
+      } else {
+        sprint_lisp_object(the_car, depth);
+      }
+      the_cdr = cdr(o);
+      if (the_cdr != lisp_nil) {
+        add_char(' ');
+        if (fulltag_of(the_cdr) == fulltag_cons) {
+          o = the_cdr;
+          continue;
+        }
+        add_c_string(". ");
+        sprint_lisp_object(the_cdr, depth);
+        break;
+      }
+    }
+    break;
+  }
+  add_char(')');
+}
+
+char *
+vector_subtag_name(unsigned subtag)
+{
+  switch (subtag) {
+  case subtag_bit_vector:
+    return "BIT-VECTOR";
+    break;
+  case subtag_instance:
+    return "INSTANCE";
+    break;
+  case subtag_bignum:
+    return "BIGNUM";
+    break;
+  case subtag_u8_vector:
+    return "(UNSIGNED-BYTE 8)";
+    break;
+  case subtag_s8_vector:
+    return "(SIGNED-BYTE 8)";
+    break;
+  case subtag_u16_vector:
+    return "(UNSIGNED-BYTE 16)";
+    break;
+  case subtag_s16_vector:
+    return "(SIGNED-BYTE 16)";
+    break;
+  case subtag_u32_vector:
+    return "(UNSIGNED-BYTE 32)";
+    break;
+  case subtag_s32_vector:
+    return "(SIGNED-BYTE 32)";
+    break;
+#ifdef X8664
+  case subtag_u64_vector:
+    return "(UNSIGNED-BYTE 64)";
+    break;
+  case subtag_s64_vector:
+    return "(SIGNED-BYTE 64)";
+    break;
+#endif
+  case subtag_package:
+    return "PACKAGE";
+    break;
+  case subtag_slot_vector:
+    return "SLOT-VECTOR";
+    break;
+  default:
+    return "";
+    break;
+  }
+}
+
+
+void
+sprint_random_vector(LispObj o, unsigned subtag, natural elements)
+{
+  add_c_string("#<");
+  sprint_unsigned_decimal(elements);
+  add_c_string("-element vector subtag = #x");
+  add_char(digits[subtag>>4]);
+  add_char(digits[subtag&15]);
+  add_c_string(" @");
+  sprint_unsigned_hex(o);
+  add_c_string(" (");
+  add_c_string(vector_subtag_name(subtag));
+  add_c_string(")>");
+}
+
+void
+sprint_symbol(LispObj o)
+{
+  lispsymbol *rawsym = (lispsymbol *) ptr_from_lispobj(untag(o));
+  LispObj 
+    pname = rawsym->pname,
+    package = rawsym->package_predicate;
+
+  if (fulltag_of(package) == fulltag_cons) {
+    package = car(package);
+  }
+
+  if (package == nrs_KEYWORD_PACKAGE.vcell) {
+    add_char(':');
+  }
+  add_lisp_base_string(pname);
+}
+
+#ifdef X8632
+LispObj
+nth_immediate(LispObj o, unsigned n)
+{
+  u16_t imm_word_count = *(u16_t *)(o + misc_data_offset);
+  natural *constants = (natural *)((char *)o + misc_data_offset + (imm_word_count << 2));
+  LispObj result = (LispObj)(constants[n-1]);
+
+  return result;
+}
+#endif
+
+void
+sprint_function(LispObj o, int depth)
+{
+  LispObj lfbits, header, name = lisp_nil;
+  natural elements;
+
+  header = header_of(o);
+  elements = header_element_count(header);
+  lfbits = deref(o, elements);
+
+  if ((lfbits & lfbits_noname_mask) == 0) {
+    name = deref(o, elements-1);
+  }
+  
+  add_c_string("#<");
+  if (name == lisp_nil) {
+    add_c_string("Anonymous Function ");
+  } else {
+    if (lfbits & lfbits_method_mask) {
+      LispObj 
+	slot_vector = deref(name,3),
+        method_name = deref(slot_vector, 6),
+        method_qualifiers = deref(slot_vector, 2),
+        method_specializers = deref(slot_vector, 3);
+      add_c_string("Method-Function ");
+      sprint_lisp_object(method_name, depth);
+      add_char(' ');
+      if (method_qualifiers != lisp_nil) {
+        if (cdr(method_qualifiers) == lisp_nil) {
+          sprint_lisp_object(car(method_qualifiers), depth);
+        } else {
+          sprint_lisp_object(method_qualifiers, depth);
+        }
+        add_char(' ');
+      }
+      sprint_specializers_list(method_specializers, depth);
+      add_char(' ');
+    } else if (lfbits & lfbits_gfn_mask) {
+      LispObj gf_slots;
+      LispObj gf_name;
+
+      add_c_string("Generic Function ");
+
+#ifdef X8632
+      gf_slots = nth_immediate(o, 2);
+      gf_name = deref(gf_slots, 2);
+      sprint_lisp_object(gf_name, depth);
+      add_char(' ');
+#endif
+    } else {
+      add_c_string("Function ");
+      sprint_lisp_object(name, depth);
+      add_char(' ');
+    }
+  }
+  sprint_unsigned_hex(o);
+  add_char('>');
+}
+
+void
+sprint_tra(LispObj o, int depth)
+{
+#ifdef X8664
+  signed sdisp;
+  unsigned disp = 0;
+  LispObj f = 0;
+
+  if ((*((unsigned short *)o) == RECOVER_FN_FROM_RIP_WORD0) &&
+      (*((unsigned char *)(o+2)) == RECOVER_FN_FROM_RIP_BYTE2)) {
+    sdisp = (*(int *) (o+3));
+    f = RECOVER_FN_FROM_RIP_LENGTH+o+sdisp;
+    disp = o-f;
+  }
+
+  if (fulltag_of(f) == fulltag_function) {
+    add_c_string("tagged return address: ");
+    sprint_function(f, depth);
+    add_c_string(" + ");
+    sprint_unsigned_decimal(disp);
+  } else {
+    add_c_string("(tra ?) : ");
+    sprint_unsigned_hex(o);
+  }
+#else
+  LispObj f = 0;
+  unsigned disp = 0;
+
+  if (*(unsigned char *)o == RECOVER_FN_OPCODE) {
+    f = (LispObj)(*((natural *)(o + 1)));
+    disp = o - f;
+  }
+
+  if (f && header_subtag(header_of(f)) == subtag_function) {
+    add_c_string("tagged return address: ");
+    sprint_function(f, depth);
+    add_c_string(" + ");
+    sprint_unsigned_decimal(disp);
+  } else {
+    add_c_string("(tra ?) : ");
+    sprint_unsigned_hex(o);
+  }
+#endif
+}
+	       
+void
+sprint_gvector(LispObj o, int depth)
+{
+  LispObj header = header_of(o);
+  unsigned 
+    elements = header_element_count(header),
+    subtag = header_subtag(header);
+    
+  switch(subtag) {
+  case subtag_function:
+    sprint_function(o, depth);
+    break;
+    
+  case subtag_symbol:
+    sprint_symbol(o);
+    break;
+    
+  case subtag_struct:
+  case subtag_istruct:
+    add_c_string("#<");
+    sprint_lisp_object(deref(o,1), depth);
+    add_c_string(" @");
+    sprint_unsigned_hex(o);
+    add_c_string(">");
+    break;
+   
+  case subtag_simple_vector:
+    {
+      int i;
+      add_c_string("#(");
+      for(i = 1; i <= elements; i++) {
+        if (i > 1) {
+          add_char(' ');
+        }
+        sprint_lisp_object(deref(o, i), depth);
+      }
+      add_char(')');
+      break;
+    }
+
+  case subtag_instance:
+    {
+      LispObj class_or_hash = deref(o,1);
+      
+      if (tag_of(class_or_hash) == tag_fixnum) {
+	sprint_random_vector(o, subtag, elements);
+      } else {
+	add_c_string("#<CLASS ");
+	sprint_lisp_object(class_or_hash, depth);
+	add_c_string(" @");
+	sprint_unsigned_hex(o);
+	add_c_string(">");
+      }
+      break;
+    }
+
+	
+      
+  default:
+    sprint_random_vector(o, subtag, elements);
+    break;
+  }
+}
+
+void
+sprint_ivector(LispObj o)
+{
+  LispObj header = header_of(o);
+  unsigned 
+    elements = header_element_count(header),
+    subtag = header_subtag(header);
+    
+  switch(subtag) {
+  case subtag_simple_base_string:
+    add_char('"');
+    add_lisp_base_string(o);
+    add_char('"');
+    return;
+    
+  case subtag_bignum:
+    if (elements == 1) {
+      sprint_signed_decimal((signed_natural)(deref(o, 1)));
+      return;
+    }
+    if ((elements == 2) && (deref(o, 2) == 0)) {
+      sprint_unsigned_decimal(deref(o, 1));
+      return;
+    }
+    break;
+    
+  case subtag_double_float:
+    break;
+
+  case subtag_macptr:
+    add_c_string("#<MACPTR ");
+    sprint_unsigned_hex(deref(o,1));
+    add_c_string(">");
+    break;
+
+  default:
+    sprint_random_vector(o, subtag, elements);
+  }
+}
+
+void
+sprint_vector(LispObj o, int depth)
+{
+  LispObj header = header_of(o);
+  
+  if (immheader_tag_p(fulltag_of(header))) {
+    sprint_ivector(o);
+  } else {
+    sprint_gvector(o, depth);
+  }
+}
+
+void
+sprint_lisp_object(LispObj o, int depth) 
+{
+  if (--depth < 0) {
+    add_char('#');
+  } else {
+    switch (fulltag_of(o)) {
+    case fulltag_even_fixnum:
+    case fulltag_odd_fixnum:
+      sprint_signed_decimal(unbox_fixnum(o));
+      break;
+    
+#ifdef X8664
+    case fulltag_immheader_0:
+    case fulltag_immheader_1:
+    case fulltag_immheader_2:
+    case fulltag_nodeheader_0:
+    case fulltag_nodeheader_1:
+#else
+    case fulltag_immheader:
+    case fulltag_nodeheader:
+#endif      
+      add_c_string("#<header ? ");
+      sprint_unsigned_hex(o);
+      add_c_string(">");
+      break;
+
+#ifdef X8664
+    case fulltag_imm_0:
+    case fulltag_imm_1:
+#else
+    case fulltag_imm:
+#endif
+      if (o == unbound) {
+        add_c_string("#<Unbound>");
+      } else {
+        if (header_subtag(o) == subtag_character) {
+          unsigned c = (o >> charcode_shift);
+          add_c_string("#\\");
+          if ((c >= ' ') && (c < 0x7f)) {
+            add_char(c);
+          } else {
+            sprintf(numbuf, "%#o", c);
+            add_c_string(numbuf);
+          }
+#ifdef X8664
+        } else if (header_subtag(o) == subtag_single_float) {
+          LispObj xx = o;
+          float f = ((float *)&xx)[1];
+          sprintf(numbuf, "%f", f);
+          add_c_string(numbuf);
+#endif
+        } else {
+
+          add_c_string("#<imm ");
+          sprint_unsigned_hex(o);
+          add_c_string(">");
+        }
+      }
+      break;
+
+#ifdef X8664
+    case fulltag_nil:
+#endif
+    case fulltag_cons:
+      sprint_list(o, depth);
+      break;
+     
+    case fulltag_misc:
+      sprint_vector(o, depth);
+      break;
+
+#ifdef X8664
+    case fulltag_symbol:
+      sprint_symbol(o);
+      break;
+
+    case fulltag_function:
+      sprint_function(o, depth);
+      break;
+#endif
+
+#ifdef X8664
+    case fulltag_tra_0:
+    case fulltag_tra_1:
+#else
+    case fulltag_tra:
+#endif
+      sprint_tra(o,depth);
+      break;
+    }
+  }
+}
+
+char *
+print_lisp_object(LispObj o)
+{
+  bufpos = 0;
+  if (setjmp(escape) == 0) {
+    sprint_lisp_object(o, 5);
+    printbuf[bufpos] = 0;
+  } else {
+    printbuf[PBUFLEN+0] = '.';
+    printbuf[PBUFLEN+1] = '.';
+    printbuf[PBUFLEN+2] = '.';
+    printbuf[PBUFLEN+3] = 0;
+  }
+  return printbuf;
+}
Index: /branches/new-random/lisp-kernel/xlbt.c
===================================================================
--- /branches/new-random/lisp-kernel/xlbt.c	(revision 13309)
+++ /branches/new-random/lisp-kernel/xlbt.c	(revision 13309)
@@ -0,0 +1,171 @@
+/*
+   Copyright (C) 2005-2009 Clozure Associates
+   This file is part of Clozure CL.  
+
+   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+   License , known as the LLGPL and distributed with Clozure CL as the
+   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+   which is distributed with Clozure CL as the file "LGPL".  Where these
+   conflict, the preamble takes precedence.  
+
+   Clozure CL is referenced in the preamble as the "LIBRARY."
+
+   The LLGPL is also available online at
+   http://opensource.franz.com/preamble.html
+*/
+
+#include "lispdcmd.h"
+#include <stdio.h>
+
+
+
+void
+print_lisp_frame(lisp_frame *frame)
+{
+  LispObj pc = frame->tra, fun=0;
+  int delta = 0;
+
+  if (pc == lisp_global(RET1VALN)) {
+    pc = frame->xtra;
+  }
+#ifdef X8632
+  if (fulltag_of(pc) == fulltag_tra) {
+    if (*((unsigned char *)pc) == RECOVER_FN_OPCODE) {
+      natural n = *((natural *)(pc + 1));
+      fun = (LispObj)n;
+    }
+    if (fun && header_subtag(header_of(fun)) == subtag_function) {
+      delta = pc - fun;
+      Dprintf("(#x%08X) #x%08X : %s + %d", frame, pc, print_lisp_object(fun), delta);
+      return;
+    }
+  }
+  if (pc == 0) {
+    fun = ((xcf *)frame)->nominal_function;
+    Dprintf("(#x%08X) #x%08X : %s + ??", frame, pc, print_lisp_object(fun));
+    return;
+  }
+#else
+  if (tag_of(pc) == tag_tra) {
+    if ((*((unsigned short *)pc) == RECOVER_FN_FROM_RIP_WORD0) &&
+        (*((unsigned char *)(pc+2)) == RECOVER_FN_FROM_RIP_BYTE2)) {
+      int sdisp = (*(int *) (pc+3));
+      fun = RECOVER_FN_FROM_RIP_LENGTH+pc+sdisp;
+    }
+    if (fulltag_of(fun) == fulltag_function) {
+      delta = pc - fun;
+      Dprintf("(#x%016lX) #x%016lX : %s + %d", frame, pc, print_lisp_object(fun), delta);
+      return;
+    }
+  }
+  if (pc == 0) {
+    fun = ((xcf *)frame)->nominal_function;
+    Dprintf("(#x%016lX) #x%016lX : %s + ??", frame, pc, print_lisp_object(fun));
+    return;
+  }
+#endif
+}
+
+Boolean
+lisp_frame_p(lisp_frame *f)
+{
+  LispObj ra;
+
+  if (f) {
+    ra = f->tra;
+    if (ra == lisp_global(RET1VALN)) {
+      ra = f->xtra;
+    }
+
+#ifdef X8632
+    if (fulltag_of(ra) == fulltag_tra) {
+#else
+    if (tag_of(ra) == tag_tra) {
+#endif
+      return true;
+    } else if ((ra == lisp_global(LEXPR_RETURN)) ||
+	       (ra == lisp_global(LEXPR_RETURN1V))) {
+      return true;
+    } else if (ra == 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void
+walk_stack_frames(lisp_frame *start, lisp_frame *end) 
+{
+  lisp_frame *next;
+  Dprintf("\n");
+  while (start < end) {
+
+    if (lisp_frame_p(start)) {
+      print_lisp_frame(start);
+    } else {
+      if (start->backlink) {
+        fprintf(dbgout, "Bogus  frame %lx\n", start);
+      }
+      return;
+    }
+    
+    next = start->backlink;
+    if (next == 0) {
+      next = end;
+    }
+    if (next < start) {
+      fprintf(dbgout, "Bad frame! (%x < %x)\n", next, start);
+      break;
+    }
+    start = next;
+  }
+}
+
+char *
+interrupt_level_description(TCR *tcr)
+{
+  signed_natural level = (signed_natural) TCR_INTERRUPT_LEVEL(tcr);
+  if (level < 0) {
+    if (tcr->interrupt_pending) {
+      return "disabled(pending)";
+    } else {
+      return "disabled";
+    }
+  } else {
+    return "enabled";
+  }
+}
+
+void
+plbt_sp(LispObj current_fp)
+{
+  area *vs_area, *cs_area;
+  TCR *tcr = (TCR *)get_tcr(true);
+  char *ilevel = interrupt_level_description(tcr);
+
+  vs_area = tcr->vs_area;
+  cs_area = tcr->cs_area;
+  if ((((LispObj) ptr_to_lispobj(vs_area->low)) > current_fp) ||
+      (((LispObj) ptr_to_lispobj(vs_area->high)) < current_fp)) {
+    current_fp = (LispObj) (tcr->save_fp);
+  }
+  if ((((LispObj) ptr_to_lispobj(vs_area->low)) > current_fp) ||
+      (((LispObj) ptr_to_lispobj(vs_area->high)) < current_fp)) {
+    Dprintf("\nFrame pointer [#x" LISP "] in unknown area.", current_fp);
+  } else {
+    fprintf(dbgout, "current thread: tcr = 0x" LISP ", native thread ID = 0x" LISP ", interrupts %s\n", tcr, tcr->native_thread_id, ilevel);
+    walk_stack_frames((lisp_frame *) ptr_from_lispobj(current_fp), (lisp_frame *) (vs_area->high));
+    /*      walk_other_areas();*/
+  }
+}
+
+
+void
+plbt(ExceptionInformation *xp)
+{
+#ifdef X8632
+  plbt_sp(xpGPR(xp,Iebp));
+#else
+  plbt_sp(xpGPR(xp,Irbp));
+#endif
+}
Index: /branches/new-random/objc-bridge/bridge.lisp
===================================================================
--- /branches/new-random/objc-bridge/bridge.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/bridge.lisp	(revision 13309)
@@ -0,0 +1,1440 @@
+;;;; -*- Mode: Lisp; Package: CCL -*-
+;;;; bridge.lisp
+;;;;
+;;;; A Lisp bridge for Cocoa
+;;;;
+;;;; This provides:
+;;;;   (1) Convenient Lisp syntax for instantiating ObjC classes
+;;;;   (2) Convenient Lisp syntax for invoking ObjC methods
+;;;;
+;;;; Copyright (c) 2003 Randall D. Beer
+;;;; 
+;;;; This software is licensed under the terms of the Lisp Lesser GNU Public
+;;;; License, known as the LLGPL.  The LLGPL consists of a preamble and 
+;;;; the LGPL. Where these conflict, the preamble takes precedence.  The 
+;;;; LLGPL is available online at http://opensource.franz.com/preamble.html.
+;;;;
+;;;; Please send comments and bug reports to <beer@eecs.cwru.edu>
+
+;;; Temporary package and module stuff 
+
+(in-package "CCL")
+
+(require "OBJC-RUNTIME")
+(require "NAME-TRANSLATION")
+
+;;; Used in PRINT-OBJECT methods.
+
+(defun describe-macptr-allocation-and-address (p stream)
+  (format stream " ~@[~a ~](#x~x)"
+          (%macptr-allocation-string p)
+          (%ptr-to-int p)))
+
+(defstruct typed-foreign-struct-info
+  foreign-type
+  lisp-class-name
+  initializer
+  constructor
+  with-form-name
+  predicate-name)
+
+(defparameter *typed-foreign-struct-info* ())
+
+(defun note-typed-foreign-struct-info (foreign-type lisp-class-name initializer constructor with-form-name predicate-name)
+  (let* ((info (find foreign-type *typed-foreign-struct-info* :test #'equal :key #'typed-foreign-struct-info-foreign-type)))
+    (unless info
+      (setq info (make-typed-foreign-struct-info :foreign-type foreign-type))
+      (push info *typed-foreign-struct-info*))
+    (setf (typed-foreign-struct-info-lisp-class-name info) lisp-class-name
+          (typed-foreign-struct-info-initializer info) initializer
+          (typed-foreign-struct-info-constructor info) constructor
+          (typed-foreign-struct-info-with-form-name info) with-form-name
+          (typed-foreign-struct-info-predicate-name info) predicate-name)
+    info))
+  
+;;; This gets installed as the COMPILER-MACRO-FUNCTION on any dispatch
+;;; function associated with a method that passes structures by value.
+(defun hoist-struct-constructors (whole env)
+  (declare (ignorable env))
+  (destructuring-bind (operator receiver &rest args) whole
+    ;;See if any arguments are "obviously" known structure-creation forms.
+    (if (null (dolist (arg args)
+                (if (and (consp arg)
+                         (find (car arg) *typed-foreign-struct-info* :key #'typed-foreign-struct-info-constructor))
+                  (return t))))
+      whole
+      ;;; Simplest to hoist one call, then let compiler-macroexpand
+      ;;; call us again.
+      (let* ((with-name nil)
+             (info nil)
+             (temp (gensym)))
+        (collect ((new-args))
+          (new-args operator)
+          (new-args receiver)
+          (dolist (arg args)
+            (if (or info
+                    (atom arg)
+                    (not (setq info (find (car arg) *typed-foreign-struct-info* :key #'typed-foreign-struct-info-constructor))))
+              (new-args arg)
+              (progn
+                (setq with-name (typed-foreign-struct-info-with-form-name info))
+                (if (cdr arg)
+                  (new-args `(progn (,(typed-foreign-struct-info-initializer info)
+                                     ,temp
+                                     ,@(cdr arg))
+                              ,temp))
+                  (new-args temp)))))
+          `(,with-name (,temp)
+            (values ,(new-args))))))))
+          
+        
+      
+(defun define-typed-foreign-struct-accessor (type-name lisp-accessor-name foreign-accessor &optional (transform-output #'identity) (transform-input #'identity))
+  (let* ((arg (gensym))
+         (val (gensym)))
+    `(progn
+      (declaim (inline ,lisp-accessor-name))
+      (defun ,lisp-accessor-name (,arg)
+        (if (typep ,arg ',type-name)
+          ,(funcall transform-input `(pref ,arg ,foreign-accessor))
+          (report-bad-arg ,arg ',type-name)))
+      (declaim (inline (setf ,lisp-accessor-name)))
+      (defun (setf ,lisp-accessor-name) (,val ,arg)
+        (if (typep ,arg ',type-name)
+          (setf (pref ,arg ,foreign-accessor) ,(funcall transform-output val))
+          (report-bad-arg ,arg ',type-name))))))
+
+(defun define-typed-foreign-struct-accessors (type-name tuples)
+  (collect ((body))
+    (dolist (tuple tuples `(progn ,@(body)))
+      (body (apply #'define-typed-foreign-struct-accessor type-name (cdr tuple))))))
+
+(defun define-typed-foreign-struct-initializer (init-function-name  tuples)
+  (when init-function-name
+    (let* ((struct (gensym)))
+      (collect ((initforms)
+                (args))
+        (args struct)
+        (dolist (tuple tuples)
+          (destructuring-bind (arg-name lisp-accessor foreign-accessor &optional (transform #'identity)) tuple
+            (declare (ignore lisp-accessor))
+            (args arg-name)
+            (initforms `(setf (pref ,struct ,foreign-accessor) ,(funcall transform arg-name)))))
+        `(progn
+          (declaim (inline ,init-function-name))
+          (defun ,init-function-name ,(args)
+            (declare (ignorable ,struct))
+            ,@(initforms)
+            ,struct))))))
+
+(defun define-typed-foreign-struct-creation-function (creation-function-name init-function-name foreign-type accessors)
+  (when creation-function-name
+    (let* ((struct (gensym))
+           (arg-names (mapcar #'car accessors)))
+      `(defun ,creation-function-name ,arg-names
+        (let* ((,struct (make-gcable-record ,foreign-type)))
+          (,init-function-name ,struct ,@arg-names)
+          ,struct)))))
+
+(defun define-typed-foreign-struct-class-with-form (with-form-name foreign-type init-function-name)
+  (declare (ignorable init-function-name))
+  (when with-form-name
+  `(defmacro ,with-form-name ((instance &rest inits) &body body)
+    (multiple-value-bind (body decls) (parse-body body nil)
+      `(rlet ((,instance ,,foreign-type))
+        ,@decls
+        ,@(when inits
+                `((,',init-function-name ,instance ,@inits)))
+        ,@body)))))
+         
+
+(defmacro define-typed-foreign-struct-class (class-name (foreign-type predicate-name init-function-name creation-function-name with-form-name) &rest accessors)
+  (let* ((arg (gensym)))
+    `(progn
+      (%register-type-ordinal-class (parse-foreign-type ',foreign-type) ',class-name)
+      (def-foreign-type ,class-name  ,foreign-type)
+      (declaim (inline ,predicate-name))
+      (note-typed-foreign-struct-info ',foreign-type ',class-name ',init-function-name ',creation-function-name ',with-form-name ',predicate-name)
+      (defun ,predicate-name (,arg)
+        (and (typep ,arg 'macptr)
+             (<= (the fixnum (%macptr-domain ,arg)) 1)
+             (= (the fixnum (%macptr-type ,arg))
+                (foreign-type-ordinal (load-time-value (parse-foreign-type ',foreign-type))))))
+      (eval-when (:compile-toplevel :load-toplevel :execute)
+        (setf (type-predicate ',class-name) ',predicate-name))
+      ,(define-typed-foreign-struct-initializer init-function-name accessors)
+      ,(define-typed-foreign-struct-creation-function creation-function-name init-function-name foreign-type accessors)
+      ,(define-typed-foreign-struct-class-with-form with-form-name foreign-type init-function-name)
+      ,(define-typed-foreign-struct-accessors class-name accessors)
+      ',class-name)))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun wrap-cg-float (x)
+    `(float ,x +cgfloat-zero+)))
+
+
+#+darwin-target
+(progn
+;;; AEDesc (Apple Event Descriptor)
+
+(define-typed-foreign-struct-class ns::aedesc (:<AED>esc ns::aedesc-p ns::init-aedesc ns::make-aedesc ns::with-aedesc)
+  (descriptor-type ns::aedesc-descriptor-type :<AED>esc.descriptor<T>ype)
+  (data-handle ns::aedesc-data-handle :<AED>esc.data<H>andle))
+
+
+(defmethod print-object ((a ns::aedesc) stream)
+  (print-unreadable-object (a stream :type t :identity (%gcable-ptr-p a))
+    (unless (%null-ptr-p a)
+      (format stream "~s ~s"
+              (ns::aedesc-descriptor-type a)
+              (ns::aedesc-data-handle a)))
+    (describe-macptr-allocation-and-address a stream)))
+)
+
+;;; It's not clear how useful this would be; I think that it's
+;;; part of the ObjC 2.0 extensible iteration stuff ("foreach").
+#+apple-objc-2.0
+(define-typed-foreign-struct-class ns::ns-fast-enumeration-state (:<NSF>ast<E>numeration<S>tate ns::ns-fast-enumeration-state-p ns::init-ns-fast-enumeration-state ns::make-ns-fast-enumeration-state ns::with-ns-fast-enumeration-state))
+
+;;; NSAffineTransformStruct CGAffineTransform
+(define-typed-foreign-struct-class ns::ns-affine-transform-struct (:<NSA>ffine<T>ransform<S>truct ns::ns-affine-transform-struct-p ns::init-ns-affine-transform-struct ns::make-ns-affine-transform-struct ns::wint-ns-affine-transform-struct)
+    (m11 ns::ns-affine-transform-struct-m11 :<NSA>ffine<T>ransform<S>truct.m11 wrap-cg-float)
+    (m12 ns::ns-affine-transform-struct-m12 :<NSA>ffine<T>ransform<S>truct.m12 wrap-cg-float)
+    (m21 ns::ns-affine-transform-struct-m21 :<NSA>ffine<T>ransform<S>truct.m21 wrap-cg-float)
+    (m22 ns::ns-affine-transform-struct-m22 :<NSA>ffine<T>ransform<S>truct.m22 wrap-cg-float)
+    (tx ns::ns-affine-transform-struct-tx :<NSA>ffine<T>ransform<S>truct.t<X> wrap-cg-float)
+    (ty ns::ns-affine-transform-struct-ty :<NSA>ffine<T>ransform<S>truct.t<Y> wrap-cg-float))
+
+
+(defmethod print-object ((transform ns::ns-affine-transform-struct) stream)
+  (print-unreadable-object (transform stream :type t :identity t)
+    (format stream "~s ~s ~s ~s ~s ~s"
+            (ns::ns-affine-transform-struct-m11 transform)
+            (ns::ns-affine-transform-struct-m12 transform)
+            (ns::ns-affine-transform-struct-m21 transform)
+            (ns::ns-affine-transform-struct-m22 transform)
+            (ns::ns-affine-transform-struct-tx transform)
+            (ns::ns-affine-transform-struct-ty transform))
+    (describe-macptr-allocation-and-address transform stream)))
+
+
+
+
+
+;;; An <NSA>ffine<T>ransform<S>truct is identical to a
+;;; (:struct :<GGA>ffine<T>ransform), except for the names of its fields.
+
+(setf (foreign-type-ordinal (parse-foreign-type '(:struct :<GGA>ffine<T>ransform)))
+      (foreign-type-ordinal (parse-foreign-type :<NSA>ffine<T>ransform<S>truct)))
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun unwrap-boolean (form)
+    `(not (eql 0 ,form)))
+  (defun wrap-boolean (form)
+    `(if ,form 1 0)))
+
+#-cocotron-objc                         ;nyi
+(progn
+;;; NSDecimal
+(define-typed-foreign-struct-class ns::ns-decimal (:<NSD>ecimal ns::ns-decimal-p nil nil nil)
+  (nil ns::ns-decimal-exponent :<NSD>ecimal._exponent)
+  (nil ns::ns-decimal-length :<NSD>ecimal._length)
+  (nil ns::ns-decimal-is-negative :<NSD>ecimal._is<N>egative wrap-boolean unwrap-boolean)
+  (nil ns::ns-decimal-is-compact :<NSD>ecimal._is<C>ompact wrap-boolean unwrap-boolean))
+  
+
+(defun ns::init-ns-decimal (data exponent length is-negative is-compact mantissa)
+  (setf (pref data :<NSD>ecimal._exponent) exponent
+        (pref data :<NSD>ecimal._length) length
+        (pref data :<NSD>ecimal._is<N>egative) (if is-negative 1 0)
+        (pref data :<NSD>ecimal._is<C>ompact) (if is-compact 1 0))
+    (let* ((v (coerce mantissa '(vector (unsigned-byte 16) 8))))
+      (declare (type (simple-array (unsigned-byte 16) (8)) v))
+      (with-macptrs ((m (pref data :<NSD>ecimal._mantissa)))
+        (dotimes (i 8)
+          (setf (paref m (:* (:unsigned 16)) i) (aref v i))))))
+
+(defun ns::make-ns-decimal (exponent length is-negative is-compact mantissa)  
+  (let* ((data (make-gcable-record :<NSD>ecimal)))
+    (ns::init-ns-decimal data exponent length is-negative is-compact mantissa)
+    data))
+
+
+
+
+(defun ns::ns-decimal-mantissa (decimal)
+  (if (typep decimal 'ns::ns-decimal)
+    (let* ((dest (make-array 8 :element-type '(unsigned-byte 16))))
+      (with-macptrs ((m (pref decimal :<NSD>ecimal._mantissa)))
+        (dotimes (i 8 dest)
+        (setf (aref dest i) (paref m (:* (:unsigned 16)) i)))))
+    (report-bad-arg decimal 'ns::ns-decimal)))
+
+(defun (setf ns::ns-decimal-mantissa) (new decimal)
+  (if (typep decimal 'ns::ns-decimal)
+    (let* ((src (coerce new '(simple-array (unsigned-byte 16) (8)))))
+      (declare (type (simple-array (unsigned-byte 16) 8) src))
+      (with-macptrs ((m (pref decimal :<NSD>ecimal._mantissa)))
+        (dotimes (i 8 new)
+          (setf (paref m (:* (:unsigned 16)) i) (aref src i)))))
+    (report-bad-arg decimal 'ns::ns-decimal)))
+
+(defmethod print-object ((d ns::ns-decimal) stream)
+  (print-unreadable-object (d stream :type t :identity t)
+    (unless (%null-ptr-p d)
+      (format stream "exponent = ~d, length = ~s, is-negative = ~s, is-compact = ~s, mantissa = ~s" (ns::ns-decimal-exponent d) (ns::ns-decimal-length d) (ns::ns-decimal-is-negative d) (ns::ns-decimal-is-compact d) (ns::ns-decimal-mantissa d)))
+    (describe-macptr-allocation-and-address d stream)))
+
+)
+
+    
+;;; NSRect
+
+(define-typed-foreign-struct-class ns::ns-rect (:<NSR>ect ns::ns-rect-p ns::init-ns-rect ns::make-ns-rect ns::with-ns-rect)
+  (x ns::ns-rect-x :<NSR>ect.origin.x wrap-cg-float)
+  (y ns::ns-rect-y :<NSR>ect.origin.y wrap-cg-float)
+  (width ns::ns-rect-width :<NSR>ect.size.width wrap-cg-float)
+  (height ns::ns-rect-height :<NSR>ect.size.height wrap-cg-float))
+
+
+(defmethod print-object ((r ns::ns-rect) stream)
+  (print-unreadable-object (r stream :type t :identity t)
+    (unless (%null-ptr-p r)
+      (flet ((maybe-round (x)
+               (multiple-value-bind (q r) (round x)
+                 (if (zerop r) q x))))
+        (format stream "~s X ~s @ ~s,~s"
+                (maybe-round (ns::ns-rect-width r))
+                (maybe-round (ns::ns-rect-height r))
+                (maybe-round (ns::ns-rect-x r))
+                (maybe-round (ns::ns-rect-y r)))
+        (describe-macptr-allocation-and-address r stream)))))
+
+
+
+;;; NSSize
+(define-typed-foreign-struct-class ns::ns-size (:<NSS>ize ns::ns-size-p ns::init-ns-size ns::make-ns-size ns::with-ns-size)
+  (width ns::ns-size-width :<NSS>ize.width wrap-cg-float)
+  (height ns::ns-size-height :<NSS>ize.height wrap-cg-float))
+
+
+(defmethod print-object ((s ns::ns-size) stream)
+  (flet ((maybe-round (x)
+           (multiple-value-bind (q r) (round x)
+             (if (zerop r) q x))))
+    (unless (%null-ptr-p s)
+      (print-unreadable-object (s stream :type t :identity t)
+        (format stream "~s X ~s"
+                (maybe-round (ns::ns-size-width s))
+                (maybe-round (ns::ns-size-height s)))))
+    (describe-macptr-allocation-and-address s stream)))
+
+
+;;; NSPoint
+(define-typed-foreign-struct-class ns::ns-point (:<NSP>oint ns::ns-point-p ns::init-ns-point ns::make-ns-point ns::with-ns-point)
+  (x ns::ns-point-x :<NSP>oint.x wrap-cg-float)
+  (y ns::ns-point-y :<NSP>oint.y wrap-cg-float))
+
+(defmethod print-object ((p ns::ns-point) stream)
+  (flet ((maybe-round (x)
+           (multiple-value-bind (q r) (round x)
+             (if (zerop r) q x))))
+    (print-unreadable-object (p stream :type t :identity t)
+      (unless (%null-ptr-p p)
+        (format stream "~s,~s"
+                (maybe-round (ns::ns-point-x p))
+                (maybe-round (ns::ns-point-y p))))
+      (describe-macptr-allocation-and-address p stream))))
+
+
+;;; NSRange
+(define-typed-foreign-struct-class ns::ns-range (:<NSR>ange ns::ns-range-p ns::init-ns-range ns::make-ns-range ns::with-ns-range)
+  (location ns::ns-range-location :<NSR>ange.location)
+  (length ns::ns-range-length :<NSR>ange.length ))
+
+(defmethod print-object ((r ns::ns-range) stream)
+  (print-unreadable-object (r stream :type t :identity t)
+    (unless (%null-ptr-p r)
+      (format stream "~s/~s"
+              (ns::ns-range-location r)
+              (ns::ns-range-length r)))
+    (describe-macptr-allocation-and-address r stream)))
+
+
+;;; String might be stack allocated; make a copy before complaining
+;;; about it.
+(defun check-objc-message-name (string)
+  (dotimes (i (length string))
+    (let* ((ch (char string i)))
+      (unless (or (alpha-char-p ch)
+                  (digit-char-p ch 10)
+                  (eql ch #\:)
+                  (eql ch #\_))
+        (error "Illegal character ~s in ObjC message name ~s"
+               ch (copy-seq string)))))
+  (when (and (position #\: string)
+             (not (eql (char string (1- (length string))) #\:)))
+    (error "ObjC message name ~s contains colons, but last character is not a colon" (copy-seq string))))
+      
+
+(setf (pkg.intern-hook (find-package "NSFUN"))
+      'get-objc-message-info)
+
+(set-dispatch-macro-character #\# #\/ 
+                              (lambda (stream subchar numarg)
+                                (declare (ignorable subchar numarg))
+                                (let* ((token (make-array 16 :element-type 'character :fill-pointer 0 :adjustable t))
+                                       (attrtab (rdtab.ttab *readtable*)))
+                                  (when (peek-char t stream nil nil)
+                                    (loop
+                                      (multiple-value-bind (char attr)
+                                          (%next-char-and-attr stream attrtab)
+                                        (unless (eql attr $cht_cnst)
+                                          (when char (unread-char char stream))
+                                          (return))
+                                        (vector-push-extend char token))))
+                                  (unless *read-suppress*
+                                    (unless (> (length token) 0)
+                                      (signal-reader-error stream "Invalid token after #/."))
+                                    (check-objc-message-name token)
+                                    (intern token "NSFUN")))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                              Utilities                                 ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Return separate lists of the keys and values in a keyword/value list
+
+(defun keys-and-vals (klist)
+  (when (oddp (length klist))
+    (error "Invalid keyword/value list: ~S" klist))
+  (loop for l = klist then (cddr l)
+        until (null l)
+        collect (first l) into keys
+        collect (second l) into vals
+        finally (return (values keys vals))))
+
+
+;;; Return the typestring for an ObjC METHOD 
+
+(defun method-typestring (method)
+  (%get-cstring #+(or apple-objc-2.0 cocotron-objc)
+                (#_method_getTypeEncoding method)
+                #-(or apple-objc-2.0 cocotron-objc)
+                (pref method :objc_method.method_types)))
+
+
+;;; Parse the ObjC message from a SENDxxx macro
+
+(defun parse-message (args)
+  (let ((f (first args))
+	(nargs (length args)))
+    (cond ((or (= nargs 1) (= nargs 2))
+	   ;; (THING {VARGS})
+	   (if (constantp f)
+	       (%parse-message (cons (eval f) (rest args)))
+	     (values f (rest args) nil)))
+	  ;; (THING1 ARG1 ... THINGN ARGN)
+	  ((evenp nargs)
+	   (multiple-value-bind (ks vs) (keys-and-vals args)
+	     (if (every #'constantp ks)
+		 (%parse-message (mapcan #'list (mapcar #'eval ks) vs))
+	       (values f (rest args) nil))))
+	  ;; (THING1 ARG1 ... THINGN ARGN VARGS)
+	  (t (multiple-value-bind (ks vs) (keys-and-vals (butlast args))
+	       (if (every #'constantp ks)
+		   (%parse-message 
+		    (nconc (mapcan #'list (mapcar #'eval ks) vs) (last args)))
+		 (values f (rest args) nil)))))))
+
+
+;;; Parse the ObjC message from the evaluated args of a %SENDxxx function
+
+(defun %parse-message (args)
+  (let ((f (first args))
+	(l (first (last args))))
+    (cond ((stringp f)
+	   ;; (STRING-with-N-colons ARG1 ... ARGN {LIST}) 
+	   (let* ((n (count #\: (the simple-string f)))
+                  (message-info (need-objc-message-info f))
+		  (args (rest args))
+		  (nargs (length args)))
+	     (cond ((and (= nargs 1)
+                         (getf (objc-message-info-flags message-info)
+                               :accepts-varargs))
+		    (values f nil l))
+		   ((= nargs n) (values f args nil))
+		   ((= nargs (1+ n)) (values f (butlast args) l))
+		   (t (error "Improperly formatted argument list: ~S" args)))))
+	  ((keywordp f)
+	   ;; (KEY1 ARG1 ... KEYN ARGN {LIST}) or (KEY LIST)
+	   (let ((nargs (length args)))
+	     (cond ((and (= nargs 2) (consp l)
+                         (let* ((info (need-objc-message-info
+                                       (lisp-to-objc-message (list f)))))
+                           (getf (objc-message-info-flags info)
+                                 :accepts-varargs)))
+		    (values (lisp-to-objc-message (list f)) nil l))
+		   ((evenp nargs)
+		    (multiple-value-bind (ks vs) (keys-and-vals args)
+		      (values (lisp-to-objc-message ks) vs nil)))
+		   ((and (> nargs 1) (listp l))
+		    (multiple-value-bind (ks vs) (keys-and-vals (butlast args))
+		      (values (lisp-to-objc-message ks) vs l)))
+		 (t (error "Improperly formatted argument list: ~S" args)))))
+	  ((symbolp f)
+	   ;; (SYMBOL {LIST})
+	   (let ((nargs (length (rest args))))
+	     (cond ((= nargs 0) (values (lisp-to-objc-message (list f)) nil nil))
+		   ((= nargs 1) (values (lisp-to-objc-message (list f)) nil l))
+		   (t (error "Improperly formatted argument list: ~S" args)))))
+	   (t (error "Improperly formatted argument list: ~S" args)))))
+
+
+;;; Return the declared type of FORM in ENV
+
+(defun declared-type (form env)
+  (cond ((symbolp form)
+         (multiple-value-bind (ignore ignore decls) 
+                              (variable-information form env)
+           (declare (ignore ignore))
+           (or (cdr (assoc 'type decls)) t)))
+        ((and (consp form) (eq (first form) 'the))
+         (second form))
+        (t t)))
+
+
+;;; Return the current optimization setting of KEY in ENV
+
+(defun optimization-setting (key &optional env)
+  (cadr (assoc key (declaration-information 'optimize env))))
+
+
+;;; Return the ObjC class named CNAME
+
+(defun find-objc-class (cname)
+  (%objc-class-classptr 
+   (if (symbolp cname) 
+       (find-class cname)
+     (load-objc-class-descriptor cname))))
+
+
+;;; Return the class object of an ObjC object O, signalling an error
+;;; if O is not an ObjC object
+                      
+(defun objc-class-of (o)
+  (if (objc-object-p o)
+      (class-of o)
+    (progn
+      #+debug
+      (#_NSLog #@"class name = %s" :address (pref (pref o :objc_object.isa)
+                                                  :objc_class.name))
+      (error "~S is not an ObjC object" o))))
+
+
+;;; Returns the ObjC class corresponding to the declared type OTYPE if
+;;; possible, NIL otherwise 
+
+(defun get-objc-class-from-declaration (otype)
+  (cond ((symbolp otype) (lookup-objc-class (lisp-to-objc-classname otype)))
+        ((and (consp otype) (eq (first otype) '@metaclass))
+         (let* ((name (second otype))
+                (c
+                 (typecase name
+                   (string (lookup-objc-class name))
+                   (symbol (lookup-objc-class (lisp-to-objc-classname name)))
+                   (t (error "Improper metaclass typespec: ~S" otype)))))
+           (unless (null c) (objc-class-of c))))))
+
+
+;;; Returns the selector of MSG 
+
+(defun get-selector (msg)
+  (%get-selector (load-objc-selector msg)))
+
+
+;;; Get the instance method structure corresponding to SEL for CLASS 
+
+(defun get-method (class sel)
+  (let ((m (class-get-instance-method class sel)))
+    (if (%null-ptr-p m)
+      (error "Instances of ObjC class ~S cannot respond to the message ~S" 
+             (objc-class-name class)
+             (lisp-string-from-sel sel))
+      m)))
+
+
+;;; Get the class method structure corresponding to SEL for CLASS
+
+(defun get-class-method (class sel)
+  (let ((m (class-get-class-method class sel)))
+    (if (%null-ptr-p m)
+      (error "ObjC class ~S cannot respond to the message ~S" 
+             (objc-class-name class)
+             (lisp-string-from-sel sel))
+      m)))
+
+
+;;; For some reason, these types sometimes show up as :STRUCTs even though they
+;;; are not structure tags, but type names
+
+(defun fudge-objc-type (ftype)
+  (if (equal ftype '(:STRUCT :<NSD>ecimal))
+      :<NSD>ecimal
+    ftype))
+
+
+;;; Returns T if the result spec requires a STRET for its return, NIL otherwise
+;;; RSPEC may be either a number (in which case it is interpreted as a number
+;;; of words) or a foreign type spec acceptable to PARSE-FOREIGN-TYPE. STRETS
+;;; must be used when a structure larger than 4 bytes is returned
+
+(defun requires-stret-p (rspec)
+  (when (member rspec '(:DOUBLE-FLOAT :UNSIGNED-DOUBLEWORD :SIGNED-DOUBLEWORD) 
+		:test #'eq)
+    (return-from requires-stret-p nil))
+  (setq rspec (fudge-objc-type rspec))
+  (if (numberp rspec) 
+    (> rspec 1)
+    (> (ensure-foreign-type-bits (parse-foreign-type rspec)) target::nbits-in-word)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                      Stret Convenience Stuff                           ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Allocate any temporary storage necessary to hold strets required
+;;; AT TOPLEVEL in the value forms.  Special recognition is given to
+;;; SENDs involving strets and to stret pseudo-functions
+;;; NS-MAKE-POINT, NS-MAKE-RANGE, NS-MAKE-RECT and NS-MAKE-SIZE
+
+(defmacro slet (varforms &body body &environment env)
+  (multiple-value-bind (clean-body decls) (parse-body body env nil)
+    (loop with r and s
+          for (var val) in varforms
+          do (multiple-value-setq (r s) (sletify val t var))
+          collect r into rvarforms
+          unless (null s) collect s into stretforms
+          finally 
+          (return
+           `(rlet ,rvarforms
+              ,@decls
+              ,@stretforms
+              ,@clean-body)))))
+
+
+;;; Note that SLET* does not allow declarations 
+
+(defmacro slet* (varforms &body body &environment env)
+  (declare (ignorable env))
+  (if (= (length varforms) 1)
+      `(slet ,varforms ,@body)
+    `(slet ,(list (first varforms))
+       (slet* ,(rest varforms) ,@body))))
+
+
+;;; Collect the info necessary to transform a SLET into an RLET 
+
+(defun sletify (form &optional errorp (var (gensym)))
+  (if (listp form)
+    (case (first form)
+      (ns-make-point 
+       (assert (= (length form) 3))
+       `(,var :<NSP>oint :x ,(second form) :y ,(third form)))
+      (ns-make-rect 
+       (assert (= (length form) 5))
+       `(,var :<NSR>ect :origin.x ,(second form) :origin.y ,(third form)
+               :size.width ,(fourth form) :size.height ,(fifth form)))
+      (ns-make-range 
+       (assert (= (length form) 3))
+       `(,var :<NSR>ange :location ,(second form) :length ,(third form)))
+      (ns-make-size
+       (assert (= (length form) 3))
+       `(,var :<NSS>ize :width ,(second form) :height ,(third form)))
+      (send
+       (let* ((info (get-objc-message-info (parse-message (cddr form)))))
+         (if (null info)
+           (error "Can't determine message being sent in ~s" form))
+         (let* ((rtype (objc-method-info-result-type
+                        (car (objc-message-info-methods info)))))
+           (if (getf (objc-message-info-flags info) :returns-structure)
+             (values `(,var ,(if (typep rtype 'foreign-type)
+                                 (unparse-foreign-type rtype)
+                                 rtype))
+                     `(send/stret ,var ,@(rest form)))
+             (if errorp
+               (error "NonSTRET SEND in ~S" form)
+               form)))))
+      (send-super
+       (let* ((info (get-objc-message-info (parse-message (cddr form)))))
+         (if (null info)
+           (error "Can't determine message being sent in ~s" form))
+         (let* ((rtype (objc-method-info-result-type
+                        (car (objc-message-info-methods info)))))
+           (if (getf (objc-message-info-flags info) :returns-structure)
+             (values `(,var ,(if (typep rtype 'foreign-type)
+                                 (unparse-foreign-type rtype)
+                                 rtype))
+                     `(send-super/stret ,var ,@(rest form)))
+             (if errorp
+               (error "NonSTRET SEND-SUPER in ~S" form)
+               form)))))
+      (t (if errorp
+           (error "Unrecognized STRET call in ~S" form)
+           form)))
+    (if errorp
+      (error "Unrecognized STRET call in ~S" form)
+      form)))
+
+
+;;; Process the arguments to a message send as an implicit SLET, collecting
+;;; the info necessary to build the corresponding RLET
+
+(defun sletify-message-args (args)
+  (loop with svf and sif
+        for a in args
+        do (multiple-value-setq (svf sif) (sletify a))
+        unless (null sif) collect sif into sifs
+        unless (equal svf a)
+          do (setf a (first svf))
+          and collect svf into svfs
+        collect a into nargs
+        finally (return (values nargs svfs sifs))))
+  
+  
+;;; Convenience macros for some common Cocoa structures.  More
+;;; could be added
+
+(defmacro ns-max-range (r) 
+  (let ((rtemp (gensym)))
+    `(let ((,rtemp ,r))
+       (+ (pref ,rtemp :<NSR>ange.location) (pref ,rtemp :<NSR>ange.length)))))
+(defmacro ns-min-x (r) `(pref ,r :<NSR>ect.origin.x))
+(defmacro ns-min-y (r) `(pref ,r :<NSR>ect.origin.y))
+(defmacro ns-max-x (r)
+  (let ((rtemp (gensym)))
+    `(let ((,rtemp ,r))
+       (+ (pref ,r :<NSR>ect.origin.x) 
+          (pref ,r :<NSR>ect.size.width)))))
+(defmacro ns-max-y (r)
+  (let ((rtemp (gensym)))
+    `(let ((,rtemp ,r))
+       (+ (pref ,r :<NSR>ect.origin.y)
+          (pref ,r :<NSR>ect.size.height)))))
+(defmacro ns-mid-x (r)
+  (let ((rtemp (gensym)))
+    `(let ((,rtemp ,r))
+       (* 0.5 (+ (ns-min-x ,rtemp) (ns-max-x ,rtemp))))))
+(defmacro ns-mid-y (r)
+  (let ((rtemp (gensym)))
+    `(let ((,rtemp ,r))
+       (* 0.5 (+ (ns-min-y ,rtemp) (ns-max-y ,rtemp))))))
+(defmacro ns-height (r) `(pref ,r :<NSR>ect.size.height))
+(defmacro ns-width (r) `(pref ,r :<NSR>ect.size.width))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                             Type Stuff                                 ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+
+(defvar *objc-message-info* (make-hash-table :test #'equal :size 800))
+
+(defun result-type-requires-structure-return (result-type)
+  ;; Use objc-msg-send-stret for all methods that return
+  ;; record types.
+  (or (typep result-type 'foreign-record-type)
+      (and (not (typep result-type 'foreign-type))
+           (typep (parse-foreign-type result-type) 'foreign-record-type))))
+
+(defvar *objc-method-signatures* (make-hash-table :test #'equal))
+
+(defstruct objc-method-signature-info
+  type-signature
+  function
+  super-function)
+
+(defun objc-method-signature-info (sig)
+  (values
+   (or (gethash sig *objc-method-signatures*)
+       (setf (gethash sig *objc-method-signatures*)
+             (make-objc-method-signature-info
+              :type-signature sig
+              :function (compile-send-function-for-signature  sig)
+              :super-function (%compile-send-function-for-signature  sig t))))))
+
+(defmethod make-load-form ((siginfo objc-method-signature-info) &optional env)
+  (declare (ignore env))
+  `(objc-method-signature-info ',(objc-method-signature-info-type-signature siginfo)))
+
+(defun concise-foreign-type (ftype)
+  (if (typep ftype 'foreign-record-type)
+    (let* ((name (foreign-record-type-name ftype)))
+      (if name
+        `(,(foreign-record-type-kind ftype) ,name)
+        (unparse-foreign-type ftype)))
+    (if (objc-id-type-p ftype)
+      :id
+      (if (typep ftype 'foreign-pointer-type)
+        (let* ((to (foreign-pointer-type-to ftype)))
+          (if (null to)
+            '(:* :void)
+            `(:* ,(concise-foreign-type to))))
+        (if (typep ftype 'foreign-type)
+          (unparse-foreign-type ftype)
+          ftype)))))
+
+
+;;; Not a perfect mechanism.
+(defclass objc-dispatch-function (funcallable-standard-object)
+    ()
+  (:metaclass funcallable-standard-class))
+
+(defmethod print-object ((o objc-dispatch-function) stream)
+  (print-unreadable-object (o stream :type t :identity t)
+    (let* ((name (function-name o)))
+      (when name
+        (format stream "~s" name)))))
+
+
+
+
+(declaim (inline check-receiver))
+
+;;; Return a NULL pointer if RECEIVER is a null pointer.
+;;; Otherwise, insist that it's an ObjC object of some sort, and return NIL.
+(defun check-receiver (receiver)
+  (if (%null-ptr-p receiver)
+    (%null-ptr)
+    (let* ((domain (%macptr-domain receiver))
+           (valid (eql domain *objc-object-domain*)))
+      (declare (fixnum domain))
+      (when (zerop domain)
+        (if (recognize-objc-object receiver)
+          (progn (%set-macptr-domain receiver *objc-object-domain*)
+                 (setq valid t))))
+      (unless valid
+        (report-bad-arg receiver 'objc:objc-object)))))
+
+(defmethod shared-initialize :after ((gf objc-dispatch-function) slot-names &key message-info &allow-other-keys)
+  (declare (ignore slot-names))
+  (with-slots (name) gf
+    (if message-info
+      (let* ((ambiguous-methods (getf (objc-message-info-flags message-info) :ambiguous))
+             (selector (objc-message-info-selector message-info))
+             (first-method (car (objc-message-info-methods message-info))))
+        (lfun-bits gf (dpb (1+ (objc-message-info-req-args message-info))
+                           $lfbits-numreq
+                           (logior (ash
+                                    (if (getf (objc-message-info-flags message-info)
+                                              :accepts-varargs)
+                                      1
+                                      0)
+                                    $lfbits-rest-bit)
+                                   (logandc2 (lfun-bits gf) (ash 1 $lfbits-aok-bit)))))
+        (flet ((signature-function-for-method (m)
+                 (let* ((signature-info (objc-method-info-signature-info m)))
+                   (or (objc-method-signature-info-function signature-info)
+                       (setf (objc-method-signature-info-function signature-info)
+                             (compile-send-function-for-signature
+                              (objc-method-signature-info-type-signature signature-info)))))))
+          (if (null ambiguous-methods)
+            ;; Pick an arbitrary method, since all methods have the same
+            ;; signature.
+            (set-funcallable-instance-function
+             gf
+             (compile-named-function 
+              `(lambda (receiver &rest args)
+                (declare (dynamic-extent args))
+                (or (check-receiver receiver)
+                 (with-ns-exceptions-as-errors 
+                     (apply (objc-method-signature-info-function
+                             (load-time-value                                
+                              (objc-method-info-signature-info ,first-method)))
+                            receiver ,selector args))))
+              :name `(:objc-dispatch ,name)))
+            (let* ((protocol-pairs (mapcar #'(lambda (pm)
+                                               (cons (lookup-objc-protocol
+                                                      (objc-method-info-class-name pm))
+                                                     (objc-method-info-signature-info
+                                                      pm)))
+                                           (objc-message-info-protocol-methods message-info)))
+                   (method-pairs (mapcar #'(lambda (group)
+                                             (cons (mapcar #'(lambda (m)
+                                                               (get-objc-method-info-class m))
+                                                           group)
+                                                   (objc-method-info-signature-info (car group))))
+                                         (objc-message-info-ambiguous-methods message-info)))
+                   (default-function-info (if method-pairs
+                                            (prog1 (cdar (last method-pairs))
+                                              (setq method-pairs (nbutlast method-pairs)))
+                                            (prog1 (cdr (last protocol-pairs))
+                                              (setq protocol-pairs (nbutlast protocol-pairs))))))
+              (set-funcallable-instance-function
+               gf
+               (compile-named-function
+                `(lambda (receiver &rest args)
+                  (declare (dynamic-extent args))
+                  (or (check-receiver receiver)
+                   (let* ((function
+                           (objc-method-signature-info-function 
+                            (or (dolist (pair ',protocol-pairs)
+                                  (when (conforms-to-protocol receiver (car pair))
+                                    (return (cdr pair))))
+                                (block m
+                                  (dolist (pair ',method-pairs ,default-function-info)
+                                    (dolist (class (car pair))
+                                      (when (typep receiver class)
+                                        (return-from m (cdr pair))))))))))
+                     (with-ns-exceptions-as-errors
+                         (apply function receiver ,selector args)))))
+                :name `(:objc-dispatch ,name)))))))
+      (set-funcallable-instance-function
+       gf
+       #'(lambda (&rest args)
+           (error "Unknown ObjC message ~a called with arguments ~s"
+                  (symbol-name name) args))))))
+                                             
+
+(defun %call-next-objc-method (self class selector sig &rest args)
+  (declare (dynamic-extent args))
+  (rlet ((s :objc_super #+(or apple-objc cocotron-objc) :receiver #+gnu-objc :self self
+            #+(or apple-objc-2.0 cocotron-objc)  :super_class #-(or apple-objc-2.0 cocotron-objc) :class
+            #+(or apple-objc-2.0 cocotron-objc) (#_class_getSuperclass class)
+            #-(or apple-objc-2.0 cocotron-objc) (pref class :objc_class.super_class)))
+    (let* ((siginfo (objc-method-signature-info sig))
+           (function (or (objc-method-signature-info-super-function siginfo)
+                         (setf (objc-method-signature-info-super-function siginfo)
+                               (%compile-send-function-for-signature sig t)))))
+      (with-ns-exceptions-as-errors
+          (apply function s selector args)))))
+
+
+(defun %call-next-objc-class-method (self class selector sig &rest args)
+  (rlet ((s :objc_super #+(or apple-objc cocotron-objc) :receiver #+gnu-objc :self self
+            #+(or apple-objc-2.0 cocotron-objc) :super_class #-(or apple-objc-2.0 cocotron-objc) :class
+            #+(or apple-objc-2.0 cocotron-objc) (#_class_getSuperclass (pref class :objc_class.isa))
+            #-(or apple-objc-2.0 cocotron-objc) (pref (pref class #+apple-objc :objc_class.isa #+gnu-objc :objc_class.class_pointer) :objc_class.super_class)))
+    (let* ((siginfo (objc-method-signature-info sig))
+           (function (or (objc-method-signature-info-super-function siginfo)
+                         (setf (objc-method-signature-info-super-function siginfo)
+                               (%compile-send-function-for-signature sig t)))))
+      (with-ns-exceptions-as-errors
+          (apply function s selector args)))))
+
+(defun postprocess-objc-message-info (message-info)
+  (let* ((objc-name (objc-message-info-message-name message-info))
+         (lisp-name (or (objc-message-info-lisp-name message-info)
+                        (setf (objc-message-info-lisp-name message-info)
+                              (compute-objc-to-lisp-function-name  objc-name))))
+         (gf (or (fboundp lisp-name)
+                 (setf (fdefinition lisp-name)
+                       (make-instance 'objc-dispatch-function :name lisp-name)))))
+
+    (unless (objc-message-info-selector message-info)
+      (setf (objc-message-info-selector message-info)
+            (ensure-objc-selector (objc-message-info-message-name message-info))))
+    
+    (flet ((reduce-to-ffi-type (ftype)
+             (concise-foreign-type ftype)))
+      (flet ((ensure-method-signature (m)
+               (or (objc-method-info-signature m)
+                   (setf (objc-method-info-signature m)
+                         (let* ((sig 
+                                 (cons (reduce-to-ffi-type
+                                        (objc-method-info-result-type m))
+                                       (mapcar #'reduce-to-ffi-type
+                                               (objc-method-info-arglist m)))))
+                           (setf (objc-method-info-signature-info m)
+                                 (objc-method-signature-info sig))
+                           sig)))))
+        (let* ((methods (objc-message-info-methods message-info))
+               (signatures ())
+               (protocol-methods)
+               (signature-alist ()))
+          (labels ((signatures-equal (xs ys)
+                     (and xs
+                          ys
+                          (do* ((xs xs (cdr xs))
+                                (ys ys (cdr ys)))
+                               ((or (null xs) (null ys))
+                                (and (null xs) (null ys)))
+                            (unless (foreign-type-= (ensure-foreign-type (car xs))
+                                                    (ensure-foreign-type (car ys)))
+                              (return nil))))))
+            (dolist (m methods)
+              (let* ((signature (ensure-method-signature m)))
+                (pushnew signature signatures :test #'signatures-equal)
+                (if (getf (objc-method-info-flags m) :protocol)
+                  (push m protocol-methods)
+                  (let* ((pair (assoc signature signature-alist :test #'signatures-equal)))
+                    (if pair
+                      (push m (cdr pair))
+                      (push (cons signature (list m)) signature-alist)))))))
+          (setf (objc-message-info-ambiguous-methods message-info)
+                (mapcar #'cdr
+                        (sort signature-alist
+                              #'(lambda (x y)
+                                  (< (length (cdr x))
+                                     (length (cdr y)))))))
+          (setf (objc-message-info-flags message-info) nil)
+          (setf (objc-message-info-protocol-methods message-info)
+                protocol-methods)
+          (when (cdr signatures)
+            (setf (getf (objc-message-info-flags message-info) :ambiguous) t))
+          (let* ((first-method (car methods))
+                 (first-sig (objc-method-info-signature first-method))
+                 (first-sig-len (length first-sig)))
+            (setf (objc-message-info-req-args message-info)
+                  (1- first-sig-len))
+            ;; Whether some arg/result types vary or not, we want to insist
+            ;; on (a) either no methods take a variable number of arguments,
+            ;; or all do, and (b) either no method uses structure-return
+            ;; conventions, or all do. (It's not clear that these restrictions
+            ;; are entirely reasonable in the long run; in the short term,
+            ;; they'll help get things working.)
+            (flet ((method-returns-structure (m)
+                     (result-type-requires-structure-return
+                      (objc-method-info-result-type m)))
+                   (method-accepts-varargs (m)
+                     (eq (car (last (objc-method-info-arglist m)))
+                         *void-foreign-type*))
+                   (method-has-structure-arg (m)
+                     (dolist (arg (objc-method-info-arglist m))
+                       (when (typep (ensure-foreign-type arg) 'foreign-record-type)
+                         (return t)))))
+              (when (dolist (method methods)
+                      (when (method-has-structure-arg method)
+                        (return t)))
+                (setf (compiler-macro-function lisp-name)
+                      'hoist-struct-constructors))
+              (let* ((first-result-is-structure (method-returns-structure first-method))
+                     (first-accepts-varargs (method-accepts-varargs first-method)))
+                (if (dolist (m (cdr methods) t)
+                      (unless (eq (method-returns-structure m)
+                                  first-result-is-structure)
+                        (return nil)))
+                  (if first-result-is-structure
+                    (setf (getf (objc-message-info-flags message-info)
+                                :returns-structure) t)))
+                (if (dolist (m (cdr methods) t)
+                      (unless (eq (method-accepts-varargs m)
+                                  first-accepts-varargs)
+                        (return nil)))
+                  (if first-accepts-varargs
+                    (progn
+                      (setf (getf (objc-message-info-flags message-info)
+                                  :accepts-varargs) t)
+                      (decf (objc-message-info-req-args message-info)))))))))
+        (reinitialize-instance gf :message-info message-info)))))
+          
+;;; -may- need to invalidate cached info whenever new interface files
+;;; are made accessible.  Probably the right thing to do is to insist
+;;; that (known) message signatures be updated in that case.
+(defun get-objc-message-info (message-name &optional (use-database t))
+  (setq message-name (string message-name))
+  (or (gethash message-name *objc-message-info*)
+      (and use-database
+           (let* ((info (lookup-objc-message-info message-name)))
+             (when info
+               (setf (gethash message-name *objc-message-info*) info)
+               (postprocess-objc-message-info info)
+               info)))))
+
+(defun need-objc-message-info (message-name)
+  (or (get-objc-message-info message-name)
+      (error "Undeclared message: ~s" message-name)))
+
+;;; Should be called after using new interfaces that may define
+;;; new methods on existing messages.
+(defun update-objc-method-info ()
+  (maphash #'(lambda (message-name info)
+               (lookup-objc-message-info message-name info)
+               (postprocess-objc-message-info info))
+           *objc-message-info*))
+
+
+;;; Of the method declarations (OBJC-METHOD-INFO structures) associated
+;;; with the message-declaration (OBJC-MESSAGE-INFO structure) M,
+;;; return the one that seems to be applicable for the object O.
+;;; (If there's no ambiguity among the declared methods, any method
+;;; will do; this just tells runtime %SEND functions how to compose
+;;; an %FF-CALL).
+(defun %lookup-objc-method-info (m o)
+  (let* ((methods (objc-message-info-methods m))
+         (ambiguous (getf (objc-message-info-flags m) :ambiguous)))
+    (if (not ambiguous)
+      (car methods)
+      (or 
+       (dolist (method methods)
+         (let* ((mclass (get-objc-method-info-class method)))
+           (if (typep o mclass)
+             (return method))))
+       (error "Can't determine ObjC method type signature for message ~s, object ~s" (objc-message-info-message-name m) o)))))
+
+(defun resolve-existing-objc-method-info (message-info class-name class-p result-type args)
+  (let* ((method-info (dolist (m (objc-message-info-methods message-info))
+                        (when (and (eq (getf (objc-method-info-flags m) :class-p)
+                                       class-p)
+                                   (equal (objc-method-info-class-name m)
+                                          class-name))
+                          (return m)))))
+    (when method-info
+      (unless (and (foreign-type-= (ensure-foreign-type (objc-method-info-result-type method-info))
+                                   (parse-foreign-type result-type))
+                   (do* ((existing (objc-method-info-arglist method-info) (cdr existing))
+                         (proposed args (cdr proposed)))
+                        ((null existing) (null proposed))
+                     (unless (foreign-type-= (ensure-foreign-type (car existing))
+                                             (parse-foreign-type (car proposed)))
+                       (return nil))))
+        (cerror "Redefine existing method to have new type signature."
+                "The method ~c[~a ~a] is already declared to have type signature ~s; the new declaration ~s is incompatible." (if class-p #\+ #\-) class-name (objc-message-info-message-name message-info) (objc-method-info-signature method-info) (cons result-type args))
+        (setf (objc-method-info-arglist method-info) args
+              (objc-method-info-result-type method-info) result-type
+              (objc-method-info-signature method-info) nil
+              (objc-method-info-signature-info method-info) nil))
+      method-info)))
+
+(defvar *objc-verbose* nil)
+
+;;; Still not right; we have to worry about type conflicts with
+;;; shadowed methods, as well.
+(defun %declare-objc-method (message-name class-name class-p result-type args)
+  (let* ((info (get-objc-message-info message-name)))
+    (unless info
+      (when (or *objc-verbose* *compile-print*)
+	(format *error-output* "~&; Note: defining new ObjC message ~c[~a ~a]" (if class-p #\+ #\-) class-name message-name))
+      (setq info (make-objc-message-info :message-name message-name))
+      (setf (gethash message-name *objc-message-info*) info))
+    (let* ((was-ambiguous (getf (objc-message-info-flags info) :ambiguous))
+           (method-info (or (resolve-existing-objc-method-info info class-name class-p result-type args)
+                            (make-objc-method-info :message-info info
+                                                   :class-name class-name
+                                                   :result-type result-type
+                                                   :arglist args
+                                                   :flags (if class-p '(:class t))))))
+      (pushnew method-info (objc-message-info-methods info))
+      (postprocess-objc-message-info info)
+      (if (and (getf (objc-message-info-flags info) :ambiguous)
+               (not was-ambiguous))
+        (warn "previously declared methods on ~s all had the same type signature, but ~s introduces ambiguity" message-name method-info))
+           
+      (objc-method-info-signature method-info))))
+
+
+
+;;; TRANSLATE-FOREIGN-ARG-TYPE doesn't accept :VOID
+
+(defun translate-foreign-result-type (ftype)
+  (ensure-foreign-type-bits (parse-foreign-type ftype))
+  (if (eq ftype :void)
+    :void
+    (translate-foreign-arg-type ftype)))
+
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                        Invoking ObjC Methods                           ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;;; The SEND and SEND/STRET macros
+
+(defmacro send (o msg &rest args &environment env)
+  (make-optimized-send o msg args env))
+
+(defmacro send/stret (s o msg &rest args &environment env)
+  (make-optimized-send o msg args env s))
+
+
+
+
+;;; Optimize special cases of SEND and SEND/STRET
+
+(defun make-optimized-send (o msg args env  &optional s super sclassname)
+  (multiple-value-bind (msg args vargs) (parse-message (cons msg args))
+    (let* ((message-info (get-objc-message-info msg)))
+      (if (null message-info)
+        (error "Unknown message: ~S" msg))
+      ;; If a vararg exists, make sure that the message can accept it
+      (when (and vargs (not (getf (objc-message-info-flags message-info)
+                                  :accepts-varargs)))
+        (error "Message ~S cannot accept a variable number of arguments" msg))
+      (unless (= (length args) (objc-message-info-req-args message-info))
+        (error "Message ~S requires ~a ~d args, but ~d were provided."
+               msg
+               (if vargs "at least" "exactly")
+               (objc-message-info-req-args message-info)
+               (length args)))
+      (multiple-value-bind (args svarforms sinitforms) (sletify-message-args args)
+        (let* ((ambiguous (getf (objc-message-info-flags message-info) :ambiguous))
+               (methods (objc-message-info-methods message-info))
+               (method (if (not ambiguous) (car methods))))
+          (when ambiguous
+            (let* ((class (if sclassname 
+                            (find-objc-class sclassname)
+                            (get-objc-class-from-declaration (declared-type o env)))))
+              (if class
+                (dolist (m methods)
+                  (unless (getf (objc-method-info-flags m) :protocol)
+                    (let* ((mclass (or (get-objc-method-info-class m)
+                                       (error "Can't find ObjC class named ~s"
+                                              (objc-method-info-class-name m)))))
+                      (when (and class (subtypep class mclass))
+                        (return (setq method m)))))))))
+          (if method
+            (build-call-from-method-info method
+                                         args
+                                         vargs
+                                         o
+                                         msg
+                                         svarforms
+                                         sinitforms
+                                         s
+                                         super)
+            (build-ambiguous-send-form message-info
+                                       args
+                                       vargs
+                                       o
+                                       msg
+                                       svarforms
+                                       sinitforms
+                                       s
+                                       super)))))))
+
+    
+;;; WITH-NS-EXCEPTIONS-AS-ERRORS is only available in OpenMCL 0.14 and above
+
+#-openmcl-native-threads
+(defmacro with-ns-exceptions-as-errors (&body body)
+  `(progn ,@body))
+
+
+;;; Return a call to the method specified by SEL on object O, with the args
+;;; specified by ARGSPECS.  This decides whether a normal or stret call is 
+;;; needed and, if the latter, uses the memory S to hold the result. If SUPER
+;;; is nonNIL, then this builds a send to super.  Finally, this also 
+;;; coerces return #$YES/#$NO values to T/NIL. The entire call takes place 
+;;; inside an implicit SLET.
+
+(defun build-call (o sel msg argspecs svarforms sinitforms &optional s super)
+  `(with-ns-exceptions-as-errors
+     (rlet ,svarforms
+       ,@sinitforms
+       ,(let ((rspec (first (last argspecs))))
+          (if (requires-stret-p rspec)
+            (if (null s)
+              ;; STRET required but not provided
+              (error "The message ~S must be sent using SEND/STRET" msg)
+              ;; STRET required and provided, use stret send
+              (if (null super)
+                ;; Regular stret send
+                `(progn
+                   (objc-message-send-stret ,s ,o ,(cadr sel)
+                    ,@(append (butlast argspecs) (list :void)))
+                   ,s)
+                ;; Super stret send
+                `(progn
+                   (objc-message-send-super-stret ,s ,super ,(cadr sel)
+                    ,@(append (butlast argspecs) (list :void)))
+                   ,s)))
+            (if (null s)
+              ;; STRET not required and not provided, use send
+              (if (null super)
+                ;; Regular send
+                (if (eq rspec :<BOOL>)
+                  `(coerce-from-bool
+                    (objc-message-send ,o ,(cadr sel) ,@argspecs))
+                  `(objc-message-send ,o ,(cadr sel) ,@argspecs))
+                ;; Super send
+                (if (eq rspec :<BOOL>)
+                  `(coerce-from-bool
+                    (objc-message-send-super ,super ,(cadr sel) ,@argspecs))
+                  `(objc-message-send-super ,super ,(cadr sel) ,@argspecs)))
+              ;; STRET not required but provided
+              (error "The message ~S must be sent using SEND" msg)))))))
+
+(defun objc-id-type-p (foreign-type)
+  (and (typep foreign-type 'foreign-pointer-type)
+       (let* ((to (foreign-pointer-type-to foreign-type)))
+         (and (typep to 'foreign-record-type)
+              (eq :struct (foreign-record-type-kind to))
+              (not (null (progn (ensure-foreign-type-bits to) (foreign-record-type-fields to))))
+              (let* ((target (foreign-record-field-type (car (foreign-record-type-fields to)))))
+                (and (typep target 'foreign-pointer-type)
+                     (let* ((target-to (foreign-pointer-type-to target)))
+                       (and (typep target-to 'foreign-record-type)
+                            (eq :struct (foreign-record-type-kind target-to))
+                            (eq :objc_class (foreign-record-type-name target-to))))))))))
+
+(defun unique-objc-classes-in-method-info-list (method-info-list)
+  (if (cdr method-info-list)                     ; if more than 1 class
+    (flet ((subclass-of-some-other-class (c)
+             (let* ((c-class (get-objc-method-info-class c)))
+               (dolist (other method-info-list)
+                 (unless (eq other c)
+                   (when (subtypep c-class (get-objc-method-info-class other))
+                   (return t)))))))
+      (remove-if #'subclass-of-some-other-class method-info-list))
+    method-info-list))
+  
+(defun get-objc-method-info-class (method-info)
+  (or (objc-method-info-class-pointer method-info)
+      (setf (objc-method-info-class-pointer method-info)
+            (let* ((c (lookup-objc-class (objc-method-info-class-name method-info) nil)))
+              (when c
+                (let* ((meta-p (getf (objc-method-info-flags method-info) :class)))
+                  (if meta-p
+                    (with-macptrs ((m (pref c :objc_class.isa)))
+                      (canonicalize-registered-metaclass m))
+                    (canonicalize-registered-class c))))))))
+
+;;; Generate some sort of CASE or COND to handle an ambiguous message
+;;; send (where the signature of the FF-CALL depends on the type of the
+;;; receiver.)
+;;; AMBIGUOUS-METHODS is a list of lists of OBJC-METHOD-INFO structures,
+;;; where the methods in each sublist share the same type signature.  It's
+;;; sorted so that more unique method/signature combinations appear first
+;;; (and are easier to special-case via TYPECASE.)
+(defun build-send-case (ambiguous-methods
+                        args
+                        vargs
+                        receiver
+                        msg
+                        s
+                        super
+                        protocol-methods)
+  (flet ((method-class-name (m)
+           (let* ((mclass (get-objc-method-info-class m)))
+             (unless mclass
+               (error "Can't find class with ObjC name ~s"
+                      (objc-method-info-class-name m)))
+             (class-name mclass))))
+
+    (collect ((clauses))
+      (let* ((protocol (gensym))
+             (protocol-address (gensym)))
+        (dolist (method protocol-methods)
+          (let* ((protocol-name (objc-method-info-class-name method)))
+            (clauses `((let* ((,protocol (lookup-objc-protocol ,protocol-name))
+                              (,protocol-address (and ,protocol (objc-protocol-address ,protocol))))
+                         (and ,protocol-address
+                              (objc-message-send ,receiver
+                                                 "conformsToProtocol:"
+                                                 :address ,protocol-address
+                                                 :<BOOL>)))
+                       ,(build-internal-call-from-method-info
+                         method args vargs receiver msg s super))))))
+      (do* ((methods ambiguous-methods (cdr methods)))
+           ((null (cdr methods))
+            (when ambiguous-methods
+              (clauses `(t
+                         ,(build-internal-call-from-method-info
+                           (caar methods) args vargs receiver msg s super)))))
+        (clauses `(,(if (cdar methods)
+                        `(or ,@(mapcar #'(lambda (m)
+                                           `(typep ,receiver
+                                             ',(method-class-name m)))
+                                       (unique-objc-classes-in-method-info-list
+                                        (car methods))))
+                        `(typep ,receiver ',(method-class-name (caar methods))))
+                   ,(build-internal-call-from-method-info
+                     (caar methods) args vargs receiver msg s super))))
+      `(cond
+        ,@(clauses)))))
+
+(defun build-ambiguous-send-form (message-info args vargs o msg svarforms sinitforms s super)
+  (let* ((receiver (gensym))
+         (caseform (build-send-case
+                    (objc-message-info-ambiguous-methods message-info)
+                    args
+                    vargs
+                    receiver
+                    msg
+                    s
+                    super
+                    (objc-message-info-protocol-methods message-info))))
+    `(with-ns-exceptions-as-errors
+      (rlet ,svarforms
+        ,@sinitforms
+        (let* ((,receiver ,o))
+          ,caseform)))))
+
+
+;;; Generate the "internal" part of a method call; the "external" part
+;;; has established ObjC exception handling and handled structure-return
+;;  details
+(defun build-internal-call-from-method-info (method-info args vargs o msg s super)
+  (let* ((arglist ()))
+    (collect ((specs))
+      (do* ((args args (cdr args))
+            (argtypes (objc-method-info-arglist method-info) (cdr argtypes))
+            (reptypes (cdr (objc-method-info-signature method-info)) (cdr reptypes)))
+           ((null args) (setq arglist (append (specs) vargs)))
+        (let* ((reptype (if (objc-id-type-p (car argtypes)) :id (car reptypes)))
+               (arg (car args)))
+          (specs reptype)
+          (specs arg)))
+      ;;(break "~& arglist = ~s" arglist)
+      (if (result-type-requires-structure-return
+           (objc-method-info-result-type method-info))
+        (if (null s)
+          ;; STRET required but not provided
+          (error "The message ~S must be sent using SEND/STRET" msg)
+          (if (null super)
+            `(objc-message-send-stret ,s ,o ,msg ,@arglist ,(car (objc-method-info-signature method-info)))
+            `(objc-message-send-super-stret ,s ,super ,msg ,@arglist ,(car (objc-method-info-signature method-info)))))
+        (if s
+          ;; STRET provided but not required
+          (error "The message ~S must be sent using SEND" msg)
+          (let* ((result-spec (car (objc-method-info-signature method-info)))
+                 (form (if super
+                         `(objc-message-send-super ,super ,msg ,@arglist ,result-spec)
+                         `(objc-message-send ,o ,msg ,@arglist ,result-spec))))
+            form))))))
+  
+(defun build-call-from-method-info (method-info args vargs o  msg  svarforms sinitforms s super)
+  `(with-ns-exceptions-as-errors
+    (rlet ,svarforms
+      ,@sinitforms
+      ,(build-internal-call-from-method-info
+        method-info
+        args
+        vargs
+        o
+        msg
+        s
+        super))))
+
+ 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                       Instantiating ObjC Class                         ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; A MAKE-INSTANCE like interface to ObjC object creation
+
+(defun make-objc-instance (cname &rest initargs)
+  (declare (dynamic-extent initargs))
+  (multiple-value-bind (ks vs) (keys-and-vals initargs)
+    (declare (dynamic-extent ks vs))
+    (let* ((class (etypecase cname
+                    (string (canonicalize-registered-class 
+                             (find-objc-class cname)))
+                    (symbol (find-class cname))
+                    (class cname))))
+      (send-objc-init-message (#/alloc class) ks vs))))
+
+
+
+
+
+;;; Provide the BRIDGE module
+
+(provide "BRIDGE")
Index: /branches/new-random/objc-bridge/fake-cfbundle-path.lisp
===================================================================
--- /branches/new-random/objc-bridge/fake-cfbundle-path.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/fake-cfbundle-path.lisp	(revision 13309)
@@ -0,0 +1,83 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+
+(in-package "CCL")
+
+;;; Before loading any Cocoa code which depends on CFBundle/NSBundle
+;;; being able to find an application bundle, it -may- be neccessary
+;;; to point the environment variable "CFProcessPath" to some file
+;;; that's where the bundle's executable would be.
+;;; This should only be necessary if the current application isn't
+;;; already "inside a bundle".  If it is necessary, it has to happen
+;;; before the CoreFoundation library's initialized.
+
+(defun fake-cfbundle-path (bundle-root info-plist-proto-path bundle-prefix  bundle-suffix install-frameworks install-libraries #+windows-target icon-path)
+  (let* ((kernel-name (standard-kernel-name))
+         (translated-root (translate-logical-pathname bundle-root))
+	 (bundle-name (let* ((name (if (directory-pathname-p translated-root)
+				       (car (last (pathname-directory translated-root)))
+				       (file-namestring translated-root)))
+			     (len (length name)))
+			(if (and (> len 4)
+				 (string-equal name ".app" :start1 (- len 4)))
+                                  (subseq name 0 (- len 4))
+                                  name)))
+         (bundle-id (concatenate 'string bundle-prefix "." (or bundle-suffix bundle-name)))
+         (bundle-version (multiple-value-bind (os bits cpu)
+                             (ccl::host-platform)
+                           (declare (ignore os))
+                           (format nil "~d (~a~d)" *openmcl-svn-revision* cpu bits)))
+         (needles `(("OPENMCL-KERNEL" . ,kernel-name)
+		    ("OPENMCL-NAME" . ,bundle-name)
+                    ("OPENMCL-IDENTIFIER" . ,bundle-id)
+		    ("OPENMCL-VERSION" . ,bundle-version)))
+         (executable-dir (merge-pathnames
+                           (make-pathname :directory (format nil "Contents/~a/"
+                                                             #+windows-target
+                                                             "Windows"
+                                                             #+darwin-target
+                                                             "MacOS"
+                                                             #-(or windows-target darwin-target) "Unknown"))
+                           translated-root))
+         (executable-path (merge-pathnames executable-dir (make-pathname :name kernel-name :defaults nil))))
+    (unless (probe-file info-plist-proto-path)
+      (error "Can't find Info.plist prototype in ~s" info-plist-proto-path))
+    (with-open-file (in info-plist-proto-path 
+                        :direction :input
+                        :external-format :utf-8)
+      (with-open-file (out (merge-pathnames
+                            (make-pathname :directory "Contents/"
+                                           :name "Info"
+                                           :type "plist")
+                            translated-root)
+                           :direction :output
+                           :if-does-not-exist :create
+                           :if-exists :supersede
+                           :external-format :utf-8)
+        (do* ((line (read-line in nil nil) (read-line in nil nil)))
+             ((null line))
+	  (dolist (needle needles)
+	    (let* ((pos (search (car needle) line)))
+	      (when pos
+		(setq line
+		      (concatenate 'string
+				   (subseq line 0 pos)
+				   (cdr needle)
+				   (subseq line (+ pos (length (car needle)))))))))
+          (write-line line out))))
+    
+    (touch executable-path)
+    (dolist (lib install-libraries)
+      (copy-file lib executable-dir :preserve-attributes t :if-exists :supersede))
+    (when install-frameworks
+      (flet ((subdir (framework target)
+               (ensure-directory-pathname (make-pathname :name (car (last (pathname-directory framework))) :defaults target))))
+        (dolist (framework install-frameworks)
+          (recursive-copy-directory framework (subdir framework executable-dir) :if-exists :overwrite))))
+    #+windows-target
+    (copy-file icon-path (merge-pathnames
+                          (make-pathname :directory "Contents/Resources/"
+                                         :name bundle-name
+                                         :type "ico")
+                          translated-root)
+               :preserve-attributes t :if-exists :supersede)
+    (setenv "CFProcessPath" (native-translated-namestring executable-path))))
Index: /branches/new-random/objc-bridge/name-translation.lisp
===================================================================
--- /branches/new-random/objc-bridge/name-translation.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/name-translation.lisp	(revision 13309)
@@ -0,0 +1,422 @@
+;;;; -*- Mode: Lisp; Package: CCL -*-
+;;;; name-translation.lisp
+;;;;
+;;;; Handles the translation between ObjC and Lisp names
+;;;;
+;;;; Copyright (c) 2003 Randall D. Beer
+;;;; 
+;;;; This software is licensed under the terms of the Lisp Lesser GNU Public
+;;;; License , known as the LLGPL.  The LLGPL consists of a preamble and 
+;;;; the LGPL. Where these conflict, the preamble takes precedence.  The 
+;;;; LLGPL is available online at http://opensource.franz.com/preamble.html.
+;;;;
+;;;; Please send comments and bug reports to <beer@eecs.cwru.edu>
+
+;;; Temporary package stuff 
+
+(in-package "CCL")
+
+(require "SEQUENCE-UTILS")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                         Special ObjC Words                             ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Special character sequences that should be treated as words in ObjC
+;;; names even though they do not follow the normal naming conventions
+
+(defvar *special-objc-words* nil)
+
+
+;;; Add a special word to *SPECIAL-OBJC-WORDS*, keeping the words sorted
+;;; from longest to shortest
+
+(defmacro define-special-objc-word (str)
+  `(setf *special-objc-words* 
+         (sort (pushnew ,str *special-objc-words* :test #'equal)
+               #'>
+               :key #'length)))
+
+
+;;; Known special words used in Cocoa names
+
+(define-special-objc-word "AB")
+(define-special-objc-word "AE")
+(define-special-objc-word "ATS")
+(define-special-objc-word "BMP")
+(define-special-objc-word "CA")
+(define-special-objc-word "CF")
+(define-special-objc-word "CG")
+(define-special-objc-word "CMYK")
+(define-special-objc-word "MIME")
+(define-special-objc-word "DR")
+(define-special-objc-word "EPS")
+(define-special-objc-word "FTP")
+(define-special-objc-word "GMT")
+(define-special-objc-word "objC")
+(define-special-objc-word "OpenGL")
+(define-special-objc-word "HTML")
+(define-special-objc-word "HTTP")
+(define-special-objc-word "HTTPS")
+(define-special-objc-word "IB")
+(define-special-objc-word "ID")
+(define-special-objc-word "INT64")
+(define-special-objc-word "NS")
+(define-special-objc-word "MIME")
+(define-special-objc-word "PDF")
+(define-special-objc-word "PICT")
+(define-special-objc-word "PNG")
+(define-special-objc-word "QD")
+(define-special-objc-word "RGB")
+(define-special-objc-word "RTFD")
+(define-special-objc-word "RTF")
+(define-special-objc-word "TCP")
+(define-special-objc-word "TIFF")
+(define-special-objc-word "UI")
+(define-special-objc-word "UID")
+(define-special-objc-word "UTF8")
+(define-special-objc-word "URL")
+(define-special-objc-word "XOR")
+(define-special-objc-word "XML")
+(define-special-objc-word "1970")
+#+gnu-objc
+(define-special-objc-word "GS")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                              Utilities                                 ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Concatenate all of the simple strings STRS 
+
+(defun string-cat (&rest strs)
+  (apply #'concatenate 'simple-string strs))
+
+;;; Collapse all prefixes of L that correspond to known special ObjC words
+
+(defun collapse-prefix (l)
+  (unless (null l)
+    (multiple-value-bind (newpre skip) (check-prefix l)
+      (cons newpre (collapse-prefix (nthcdr skip l))))))
+
+(defun check-prefix (l)
+  (let ((pl (prefix-list l)))
+    (loop for w in *special-objc-words*
+          for p = (position-if #'(lambda (s) (string= s w)) pl)
+          when p do (return-from check-prefix (values (nth p pl) (1+ p))))
+    (values (first l) 1)))
+
+(defun prefix-list (l)
+  (loop for i from (1- (length l)) downto 0
+        collect (apply #'string-cat (butlast l i))))
+
+
+;;; Concatenate a list of strings with optional separator into a symbol 
+
+(defun symbol-concatenate (slist &optional (sep "") (package *package*))
+  (values 
+   (intern 
+    (reduce #'(lambda (s1 s2) (string-cat s1 sep s2))
+             (mapcar #'string-upcase slist))
+    package)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                             Implementation                             ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Convert an ObjC name to a corresponding Lisp name 
+;;; Example: "NSURLHandleClient" ==> ns-url-handle-client 
+;;;
+;;; 1) Break the string at each uppercase letter
+;;;    e.g., "NSWindow" ==> ("N" "S" "Window")
+;;; 2) Collapse known sequences of letters 
+;;;    e.g., ("N" "S" "Window") ==> ("NS" "Window")
+;;; 3) Uppercase and concatenate with hyphens into a symbol
+;;;    e.g., ("NS" "Window") ==> NS-WINDOW
+
+(defun compute-lisp-name (str &optional (package *package*))
+  (symbol-concatenate
+    (collapse-prefix 
+      (split-if #'(lambda (ch) (or (upper-case-p ch) (digit-char-p ch))) str))
+    "-"
+    package))
+
+
+;;; Convert a Lisp classname into a corresponding ObjC classname
+;;; Example: ns-url-handle-client ==> "NSURLHandleClient" 
+
+(defun compute-objc-classname (sym)
+  (apply #'string-cat
+         (loop for str in (split-if-char #\- (string sym) :elide)
+               for e = (member str *special-objc-words* 
+                               :test #'equal 
+                               :key #'string-upcase)
+               collect (if e (first e) (string-capitalize str)))))
+
+
+;;; Convert an ObjC method selector to a set of Lisp keywords
+;;; Example: "nextEventMatchingMask:untilDate:inMode:dequeue:" ==>
+;;;          (:next-event-matching-mask :until-date :in-mode :dequeue)
+
+(defun compute-objc-to-lisp-message (str)
+  (mapcar #'(lambda (s) (compute-lisp-name s (find-package "KEYWORD")))
+          (split-if-char #\: str :elide)))
+
+
+(defparameter *objc-colon-replacement-character* #\.)
+
+
+(defun compute-objc-to-lisp-function-name (str &optional (package "NSFUN"))
+  #-nil
+  (intern str package)
+  #+nil
+  (let* ((n (length str))
+         (i 0)
+         (trailing t))
+      (let* ((subs (if (not (position #\: str))
+                     (progn (setq trailing nil)
+                            (list str))
+                     (collect ((substrings))
+                       (do* ()
+                            ((= i n) (substrings))
+                         (let* ((pos (position #\: str :start i)))
+                           (unless pos
+                             (break "Huh?"))
+                           (substrings (subseq str i pos))
+                           (setq i (1+ pos)))))))
+             (split 
+              (mapcar #'(lambda (s)
+                    (collapse-prefix
+                     (split-if #'(lambda (ch)
+                                   (or (upper-case-p ch) (digit-char-p ch)))
+                               s)))
+                
+                subs))
+             (namelen (+ (if trailing (length split) 0)
+                           (let* ((c 0))
+                             (dolist (s split c)
+                               (if s (incf c (1- (length s))))))
+                           (let* ((c 0))
+                             (dolist (s split c)
+                               (dolist (sub s)
+                                 (incf c (length sub)))))))
+             (name (make-string namelen)))
+        (declare (dynamic-extent name))
+        (let* ((p 0))
+          (flet ((out-ch (ch)
+                   (setf (schar name p) ch)
+                   (incf p)))
+            (dolist (sub split)
+              (when sub
+                (do* ((string (pop sub) (pop sub)))
+                     ((null string))
+                  (dotimes (i (length string))
+                    (out-ch (char-upcase (schar string i))))
+                  (when sub
+                    (out-ch #\-))))
+              (when trailing (out-ch *objc-colon-replacement-character*)))))
+        (values
+         (or (find-symbol name package)
+             (intern (copy-seq name) package))))))
+
+        
+;;; Convert a Lisp list of keywords into an ObjC method selector string
+;;; Example: (:next-event-matching-mask :until-date :in-mode :dequeue) ==>
+;;;          "nextEventMatchingMask:untilDate:inMode:dequeue:"
+
+(defun compute-lisp-to-objc-message (klist)
+  (flet ((objcify (sym)
+           (apply 
+            #'string-cat
+            (loop for str in (split-if-char #\- (string sym) :elide)
+                  for first-word-flag = t then nil
+                  for e = (member str *special-objc-words* 
+                                  :test #'equal 
+                                  :key #'string-upcase)
+                  collect 
+                  (cond (e (first e))
+                        (first-word-flag (string-downcase str))
+                        (t (string-capitalize str)))))))
+    (if (and (= (length klist) 1) 
+             (neq (symbol-package (first klist)) (find-package :keyword)))
+      (objcify (first klist))
+      (apply #'string-cat
+             (mapcar #'(lambda (sym) (string-cat (objcify sym) ":")) klist)))))
+
+
+;;; Convert an ObjC initializer to a list of corresponding initargs,
+;;; stripping off any initial "init"
+;;; Example: "initWithCString:length:" ==> (:with-c-string :length)
+
+(defun compute-objc-to-lisp-init (init)
+  (cond 
+   ((= (length init) 0) nil)
+   ((and (> (length init) 3) (string= init "init" :start1 0 :end1 4))
+    (mapcar #'(lambda (s) (compute-lisp-name s (find-package "KEYWORD")))
+          (split-if-char #\: (subseq init 4 (length init)) :elide)))
+   (t (error "~S is not a valid initializer" init))))
+
+
+;;; Convert a list of initargs into an ObjC initilizer, adding an "init"
+;;; prefix if necessary
+;;; Example: (:with-c-string :length) ==> "initWithCString:length:"
+
+(defun compute-lisp-to-objc-init (initargs)
+  (if (null initargs) 
+    "init"
+    (let ((str (compute-lisp-to-objc-message initargs)))
+      (if (string/= (first (split-if-char #\- (string (first initargs)))) 
+                    "INIT")
+        (string-cat "init" (nstring-upcase str :start 0 :end 1))
+        str))))
+ 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                         Class Name Translation                         ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Hash tables for caching class name translations
+
+(defvar *lisp-classname-table* (make-hash-table :test #'equal))
+(defvar *objc-classname-table* (make-hash-table :test #'eq))
+
+  
+;;; Define a hard-wired ObjC class name translation (if the automatic
+;;; translation doesn't apply) 
+
+(defmacro define-classname-translation (str sym)
+  (let ((str-temp (gensym))
+        (sym-temp (gensym))
+        (old-str-temp (gensym))
+        (old-sym-temp (gensym)))
+    `(let* ((,str-temp ',str)
+            (,sym-temp ',sym)
+            (,old-sym-temp (gethash ,str-temp *lisp-classname-table*))
+            (,old-str-temp (gethash ,sym-temp *objc-classname-table*)))
+       (remhash ,old-str-temp *lisp-classname-table*)
+       (remhash ,old-sym-temp *objc-classname-table*)
+       (setf (gethash ,str-temp *lisp-classname-table*) ,sym-temp)
+       (setf (gethash ,sym-temp *objc-classname-table*) ,str-temp)
+       (values))))
+
+
+;;; Translate an ObjC class name to a Lisp class name
+
+(defun objc-to-lisp-classname (str &optional (package *package*))
+  (let ((sym 
+         (or (gethash str *lisp-classname-table*)
+             (compute-lisp-name str package))))
+    (setf (gethash sym *objc-classname-table*) str)
+    (setf (gethash str *lisp-classname-table*) sym)))
+
+
+;;; Translate a Lisp class name to an ObjC class name
+
+(defun lisp-to-objc-classname (sym)
+  (let ((str 
+         (or (gethash sym *objc-classname-table*)
+             (compute-objc-classname sym))))
+    (setf (gethash str *lisp-classname-table*) sym)
+    (setf (gethash sym *objc-classname-table*) str)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                      Message Keyword Translation                       ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Hash tables for caching initializer translations
+
+(defvar *lisp-message-table* (make-hash-table :test #'equal))
+(defvar *objc-message-table* (make-hash-table :test #'equal))
+
+
+;;; Define a hard-wired message-keyword translation (if the automatic
+;;; translation doesn't apply) 
+
+(defmacro define-message-translation (message msg-keywords)
+  (let ((message-temp (gensym))
+        (msg-keywords-temp (gensym))
+        (old-message-temp (gensym))
+        (old-msg-keywords-temp (gensym)))
+    `(let* ((,message-temp ',message)
+            (,msg-keywords-temp ',msg-keywords)
+            (,old-message-temp 
+             (gethash ,message-temp *lisp-message-table*))
+            (,old-msg-keywords-temp 
+             (gethash ,msg-keywords-temp *objc-message-table*)))
+       (remhash ,old-message-temp *lisp-message-table*)
+       (remhash ,old-msg-keywords-temp *objc-message-table*)
+       (setf (gethash ,message-temp *lisp-message-table*) ,msg-keywords-temp)
+       (setf (gethash ,msg-keywords-temp *objc-message-table*) ,message-temp)
+       (values))))
+
+
+;;; Translate an ObjC message to a list of Lisp message keywords
+
+(defun objc-to-lisp-message (message)
+  (let ((msg-keywords 
+         (or (gethash message *lisp-message-table*)
+             (compute-objc-to-lisp-message message))))
+    (setf (gethash msg-keywords *objc-message-table*) message)
+    (setf (gethash message *lisp-message-table*) msg-keywords)))
+
+
+;;; Translate a set of Lisp message keywords to an ObjC message 
+
+(defun lisp-to-objc-message (msg-keywords)
+  (let ((message 
+         (or (gethash msg-keywords *objc-message-table*)
+             (compute-lisp-to-objc-message msg-keywords))))
+    (setf (gethash message *lisp-message-table*) msg-keywords)
+    (setf (gethash msg-keywords *objc-message-table*) message)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                        Initializer Translation                         ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Hash tables for caching initializer translations
+
+(defvar *lisp-initializer-table* (make-hash-table :test #'equal))
+(defvar *objc-initializer-table* (make-hash-table :test #'equal))
+
+
+;;; Define a hard-wired init-keyword translation (if the automatic
+;;; translation doesn't apply) 
+
+(defmacro define-init-translation (initmsg initargs)
+  (let ((initmsg-temp (gensym))
+        (initargs-temp (gensym))
+        (old-initmsg-temp (gensym))
+        (old-initargs-temp (gensym)))
+    `(let* ((,initmsg-temp ',initmsg)
+            (,initargs-temp ',initargs)
+            (,old-initmsg-temp 
+             (gethash ,initmsg-temp *lisp-initializer-table*))
+            (,old-initargs-temp 
+             (gethash ,initargs-temp *objc-initializer-table*)))
+       (remhash ,old-initmsg-temp *lisp-initializer-table*)
+       (remhash ,old-initargs-temp *objc-initializer-table*)
+       (setf (gethash ,initmsg-temp *lisp-initializer-table*) ,initargs-temp)
+       (setf (gethash ,initargs-temp *objc-initializer-table*) ,initmsg-temp)
+       (values))))
+
+
+;;; Translate an ObjC initializer to a list of Lisp initargs
+
+(defun objc-to-lisp-init (initmsg)
+  (let ((initargs 
+         (or (gethash initmsg *lisp-initializer-table*)
+             (compute-objc-to-lisp-init initmsg))))
+    (setf (gethash initargs *objc-initializer-table*) initmsg)
+    (setf (gethash initmsg *lisp-initializer-table*) initargs)))
+
+
+;;; Translate a set of Lisp initargs to an ObjC initializer 
+
+(defun lisp-to-objc-init (initargs)
+  (let ((initmsg 
+         (or (gethash initargs *objc-initializer-table*)
+             (compute-lisp-to-objc-init initargs))))
+    (setf (gethash initmsg *lisp-initializer-table*) initargs)
+    (setf (gethash initargs *objc-initializer-table*) initmsg)))
Index: /branches/new-random/objc-bridge/objc-clos.lisp
===================================================================
--- /branches/new-random/objc-bridge/objc-clos.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/objc-clos.lisp	(revision 13309)
@@ -0,0 +1,963 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2003-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+;;;
+;;; TO DO
+;;;  - Both method creation and invocation should be faster and cons less
+;;;  - Resolve messages with repeated keywords
+;;;    (rename them to :range1:range2 or don't use &key in GFs and methods)
+;;;  - How to integrate SEND-SUPER with CALL-NEXT-METHOD?
+;;;  - Variable arity ObjC methods
+;;;  - Pass-by-ref structures need to keep track of IN, OUT, IN/OUT info
+;;;  - Need to canonicalize and retain every returned :ID
+;;;  - Support :BEFORE, :AFTER and :AROUND for ObjC methods
+;;;  - User-defined ObjC methods via DEFMETHOD (or DEFINE-OBJ-METHOD)
+;;;  - Need to fully handle init keywords and ObjC init messages
+
+;;; Package and module stuff
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  #+(or apple-objc cocotron-objc)
+  (use-interface-dir :cocoa)
+  #+gnu-objc
+  (use-interface-dir :gnustep))
+
+(require "SEQUENCE-UTILS")
+;;; We need OBJC-FOREIGN-ARG-TYPE from the bridge to process ivar types
+(require "BRIDGE")
+
+
+(defparameter *objc-import-private-ivars* t "When true, the CLASS-DIRECT-SLOTS of imported ObjC classes will contain slot definitions for instance variables whose name starts with an underscore.  Note that this may exacerbate compatibility problems.")
+
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                                 Testing                                ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Enable some debugging output.
+(defparameter *objc-clos-debug* nil)
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                     OBJC Foreign Object Domain                         ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconstant objc-type-flags (byte 3 20))
+(defconstant objc-type-index (byte 20 0))
+(defconstant objc-flag-instance 0)
+(defconstant objc-flag-class 1)
+(defconstant objc-flag-metaclass 2)
+
+(defvar *objc-class-class*)
+(defvar *objc-metaclass-class*)
+
+(defvar *objc-object-slot-vectors* (make-hash-table :test #'eql))
+(defvar *objc-canonical-instances* (make-hash-table :test #'eql :weak :value))
+
+(defun raw-macptr-for-instance (instance)
+  (let* ((p (%null-ptr)))
+    (%set-macptr-domain p 1)		; not an ObjC object, but EQL to one
+    (%setf-macptr p instance)
+    p))
+
+(defun register-canonical-objc-instance (instance raw-ptr)
+  ;(terminate-when-unreachable instance)
+  ;(retain-objc-instance instance)
+  (setf (gethash raw-ptr *objc-canonical-instances*) instance))
+
+(defun canonicalize-objc-instance (instance)
+  (or (gethash instance *objc-canonical-instances*)
+      (register-canonical-objc-instance
+       (setq instance (%inc-ptr instance 0))
+       (raw-macptr-for-instance instance))))
+
+
+(defun recognize-objc-object (p)
+  (labels ((recognize (p mapped)
+             (let* ((idx (objc-class-id p)))
+               (if idx
+                 (%set-macptr-type p (dpb objc-flag-class objc-type-flags idx))
+                 (if (setq idx (objc-metaclass-id p))
+                   (%set-macptr-type p (dpb objc-flag-metaclass objc-type-flags idx))
+                   (if (setq idx (%objc-instance-class-index p))
+                     (%set-macptr-type p idx)
+                     (unless mapped
+                       (if (maybe-map-objc-classes)
+                         (recognize p t)))))))))
+    (recognize p nil)))
+
+(defun release-canonical-nsobject (object)
+  object)
+
+  
+
+(defun %objc-domain-class-of (p)
+  (let* ((type (%macptr-type p))
+	 (flags (ldb objc-type-flags type))
+	 (index (ldb objc-type-index type)))
+    (declare (fixnum type flags index))
+    (ecase flags
+      (#.objc-flag-instance (id->objc-class index))
+      (#.objc-flag-class (objc-class-id->objc-metaclass index))
+      (#.objc-flag-metaclass *objc-metaclass-class*))))
+  
+(defun %objc-domain-classp (p)
+  (let* ((type (%macptr-type p))
+	 (flags (ldb objc-type-flags type)))
+    (declare (fixnum type flags))
+    (not (= flags objc-flag-instance))))
+
+(defun %objc-domain-instance-class-wrapper (p)
+  (let* ((type (%macptr-type p))
+	 (flags (ldb objc-type-flags type))
+	 (index (ldb objc-type-index type)))
+    (declare (fixnum type flags index))
+    (ecase flags
+      (#.objc-flag-instance (id->objc-class-wrapper index))
+      (#.objc-flag-class (id->objc-metaclass-wrapper (objc-class-id->objc-metaclass-id index)))
+      (#.objc-flag-metaclass (%class.own-wrapper *objc-metaclass-class*)))))
+
+(defun %objc-domain-class-own-wrapper (p)
+  (let* ((type (%macptr-type p))
+	 (flags (ldb objc-type-flags type))
+	 (index (ldb objc-type-index type)))
+    (declare (fixnum type flags index))
+    (ecase flags
+      (#.objc-flag-instance nil)
+      (#.objc-flag-class (id->objc-class-wrapper index))
+      (#.objc-flag-metaclass (id->objc-metaclass-wrapper index)))))
+
+(defun has-lisp-slot-vector (p)
+  (gethash p *objc-object-slot-vectors*))
+
+(defun %remove-lisp-slot-vector (p)
+  (remhash p *objc-object-slot-vectors*))
+
+(defun %objc-domain-slots-vector (p)
+       (let* ((type (%macptr-type p))
+             (flags (ldb objc-type-flags type))
+             (index (ldb objc-type-index type)))
+        (declare (fixnum type flags index))
+        (ecase flags
+          (#.objc-flag-instance (or (gethash p *objc-object-slot-vectors*)
+                                    ; try to allocate the slot vector on demand
+                                    (let* ((raw-ptr (raw-macptr-for-instance p))
+                                           (slot-vector (create-foreign-instance-slot-vector (class-of p))))
+                                      (when slot-vector
+                                        (setf (slot-vector.instance slot-vector) raw-ptr)
+                                        (setf (gethash raw-ptr *objc-object-slot-vectors*) slot-vector)
+					(register-canonical-objc-instance p raw-ptr)
+					(initialize-instance p))
+                                      slot-vector)
+                                    (error "~s has no slots." p)))
+          (#.objc-flag-class (id->objc-class-slots-vector index))
+          (#.objc-flag-metaclass (id->objc-metaclass-slots-vector index)))))
+
+(defun %objc-domain-class-ordinal (p)
+  (let* ((type (%macptr-type p))
+	 (flags (ldb objc-type-flags type))
+	 (index (ldb objc-type-index type)))
+    (declare (fixnum type flags index))
+    (ecase flags
+      (#.objc-flag-instance nil)
+      (#.objc-flag-class (objc-class-id->ordinal index))
+      (#.objc-flag-metaclass (objc-metaclass-id->ordinal index)))))
+
+(defun %set-objc-domain-class-ordinal (p new)
+  (let* ((type (%macptr-type p))
+	 (flags (ldb objc-type-flags type))
+	 (index (ldb objc-type-index type)))
+    (declare (fixnum type flags index))
+    (ecase flags
+      (#.objc-flag-instance nil)
+      (#.objc-flag-class (setf (objc-class-id->ordinal index) new))
+      (#.objc-flag-metaclass (setf (objc-metaclass-id->ordinal index) new)))))
+
+(defloadvar *objc-object-domain*
+    (register-foreign-object-domain :objc
+				:recognize #'recognize-objc-object
+				:class-of #'%objc-domain-class-of
+				:classp #'%objc-domain-classp
+				:instance-class-wrapper
+				#'%objc-domain-instance-class-wrapper
+				:class-own-wrapper
+				#'%objc-domain-class-own-wrapper
+				:slots-vector #'%objc-domain-slots-vector
+				:class-ordinal #'%objc-domain-class-ordinal
+				:set-class-ordinal
+				#'%set-objc-domain-class-ordinal))
+
+;;; P is known to be a (possibly null!) instance of some ObjC class.
+(defun %set-objc-instance-type (p)
+  (unless (%null-ptr-p p)
+    (let* ((parent (pref p :objc_object.isa))
+           (id (objc-class-id parent)))
+      (when id
+        (%set-macptr-domain p *objc-object-domain*)
+        (%set-macptr-type p id)))))
+
+;;; P is known to be of type :ID.  It may be null.
+(defun %set-objc-id-type (p)
+  (let* ((idx (objc-class-id p)))
+    (if idx
+      (progn
+        (%set-macptr-domain p *objc-object-domain*)
+        (%set-macptr-type p (dpb objc-flag-class objc-type-flags idx)))
+      (if (setq idx (objc-metaclass-id p))
+        (progn
+          (%set-macptr-domain p *objc-object-domain*)  
+          (%set-macptr-type p (dpb objc-flag-metaclass objc-type-flags idx)))
+        (%set-objc-instance-type p)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                  ObjC Objects, Classes and Metaclasses                 ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defclass objc:objc-object (foreign-standard-object)
+    ())
+
+;;; "Real" OBJC-CLASSes and OBJC-METACLASSEs are subtypes of this
+;;; abstract class.  We need to keep track of those classes that're
+;;; implemented in lisp separately (so that they can be restored after
+;;; SAVE-APPLICATION).
+
+(defclass objc:objc-class-object (foreign-class objc:objc-object)
+    ((foreign :initform nil :initarg :foreign)
+     (peer :initform nil :initarg :peer)))
+
+(defclass objc:objc-metaclass (objc:objc-class-object)
+    ())
+
+(setq *objc-metaclass-class* (find-class 'objc:objc-metaclass))
+
+(defclass objc:objc-class (objc:objc-class-object)
+    ())
+
+(setq *objc-class-class* (find-class 'objc:objc-class))
+
+(deftype @metaclass (&optional string)
+  (declare (ignore string))
+  'objc:objc-class)
+
+(defmethod objc-metaclass-p ((c class))
+  nil)
+
+(defmethod objc-metaclass-p ((c objc:objc-class-object))
+  (%objc-metaclass-p c))
+
+
+(defmethod print-object ((c objc:objc-class) stream)
+  (print-unreadable-object (c stream)
+    (format stream "~s ~:[~;[MetaClass] ~]~s (#x~x)" 
+	    'objc:objc-class 
+	    (objc-metaclass-p c) 
+	    (if (slot-boundp c 'name)
+              (class-name c)
+              "<unnamed>")
+	    (%ptr-to-int c))))
+
+(defmethod print-object ((c objc:objc-metaclass) stream)
+  (print-unreadable-object (c stream)
+    (format stream "~s ~s (#x~x)" 
+	    'objc:objc-metaclass 
+	    (if (slot-boundp c 'name)
+              (class-name c)
+              "<unnamed>") 
+	    (%ptr-to-int c))))
+
+(defmethod print-object ((o objc:objc-object) stream)
+  (if (objc-object-p o)
+    (print-unreadable-object (o stream :type t)
+      (format stream
+              (if (and (typep o 'ns::ns-string)
+                       (initialized-nsobject-p o))
+                "~s (#x~x)"
+                "~a (#x~x)")
+              (nsobject-description o) (%ptr-to-int o)))
+    (format stream "#<Bogus ObjC Object #x~X>" (%ptr-to-int o))))
+
+
+
+  
+
+
+(defun make-objc-class-object-slots-vector (class meta)
+  (let* ((n (1+ (length (extract-instance-effective-slotds meta))))
+	 (slots (allocate-typed-vector :slot-vector n (%slot-unbound-marker))))
+    (setf (slot-vector.instance slots) class)
+    slots))
+
+(defun make-objc-metaclass-slots-vector (metaclass)
+  (make-objc-class-object-slots-vector metaclass *objc-metaclass-class*))
+
+(defun make-objc-class-slots-vector (class)
+  (make-objc-class-object-slots-vector class *objc-class-class*))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                              Slot Protocol                             ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Accessing Lisp slots
+
+(defmethod slot-boundp-using-class ((class objc:objc-class-object)
+				    instance
+				    (slotd standard-effective-slot-definition))
+  (%std-slot-vector-boundp (%objc-domain-slots-vector instance) slotd))
+
+(defmethod slot-value-using-class ((class objc:objc-class-object)
+				   instance
+				   (slotd standard-effective-slot-definition))
+  (%std-slot-vector-value (%objc-domain-slots-vector instance) slotd))
+
+(defmethod (setf slot-value-using-class)
+    (new
+     (class objc:objc-class-object)
+     instance
+     (slotd standard-effective-slot-definition))
+  (%set-std-slot-vector-value (%objc-domain-slots-vector instance) slotd new))
+
+
+;;; Metaclasses for foreign slots
+
+(defclass foreign-direct-slot-definition (direct-slot-definition)
+  ((foreign-type  :initform :id :accessor foreign-slot-definition-foreign-type)
+   (bit-offset :initarg :bit-offset
+               :initform nil
+               :accessor foreign-direct-slot-definition-bit-offset
+               :documentation "A bit-offset, relative to the start of the
+               instance's slots.  The corresponding effective slot definition's
+                offset is strictly determined by this value")))
+
+(defmethod shared-initialize :after ((slotd foreign-direct-slot-definition)
+                                     slot-names
+                                     &key (foreign-type :id))
+  (declare (ignore slot-names))
+  (unless (typep foreign-type 'foreign-type)
+    (setq foreign-type (parse-foreign-type foreign-type)))
+  (setf (foreign-slot-definition-foreign-type slotd) foreign-type))
+
+
+(defclass foreign-effective-slot-definition (effective-slot-definition)
+  ((foreign-type :initarg :foreign-type :initform :id :accessor foreign-slot-definition-foreign-type)
+   (getter :type function :accessor foreign-slot-definition-getter)
+   (setter :type function :accessor foreign-slot-definition-setter)))
+
+
+;;; Use the foreign slot metaclasses if the slot has a :FOREIGN-TYPE attribute
+;;  
+
+(defmethod direct-slot-definition-class ((class objc:objc-class-object)
+					 &rest initargs)
+  (if (getf initargs :foreign-type)
+    (find-class 'foreign-direct-slot-definition)
+    (find-class 'standard-direct-slot-definition)))
+
+(defmethod effective-slot-definition-class ((class objc:objc-class-object)
+					    &rest initargs)
+  (if (getf initargs :foreign-type)
+    (find-class 'foreign-effective-slot-definition)
+    (find-class 'standard-effective-slot-definition)))
+
+
+(defun set-objc-foreign-direct-slot-offsets (dslotds bit-offset)
+  (dolist (d dslotds)
+    (let* ((ftype (foreign-slot-definition-foreign-type d))
+           (type-alignment (progn (ensure-foreign-type-bits ftype)
+                                  (foreign-type-alignment ftype))))
+      (setf (foreign-direct-slot-definition-bit-offset d)
+            (setq bit-offset
+                  (align-offset bit-offset type-alignment)))
+      (setq bit-offset (+ bit-offset (foreign-type-bits ftype))))))
+
+(defmethod (setf class-direct-slots) :before (dslotds (class objc::objc-class))
+  #-(or apple-objc-2.0 cocotron-objc)
+  (let* ((foreign-dslotds
+	  (loop for d in dslotds
+		when (typep d 'foreign-direct-slot-definition)
+		collect d))
+         (bit-offset (dolist (c (class-direct-superclasses class) 0)
+                       (when (typep c 'objc::objc-class)
+                         (return
+                           (ash (%objc-class-instance-size c)
+                                3))))))
+    (unless
+        (dolist (d foreign-dslotds t)
+          (if (not (foreign-direct-slot-definition-bit-offset d))
+            (return nil)))
+      (set-objc-foreign-direct-slot-offsets foreign-dslotds bit-offset)))
+  #+(or apple-objc-2.0 cocotron-objc)
+  ;; Add ivars for each foreign direct slot, then ask the runtime for
+  ;; the ivar's byte offset.  (Note that the ObjC 2.0 ivar initialization
+  ;; protocol doesn't seem to offer support for bitfield-valued ivars.)
+  (dolist (dslotd dslotds)
+    (when (typep dslotd 'foreign-direct-slot-definition)
+      (let* ((string (lisp-defined-slot-name-to-objc-slot-name (slot-definition-name dslotd)))
+             (type (foreign-slot-definition-foreign-type dslotd))
+             (encoding (progn
+                         (ensure-foreign-type-bits type)
+                         (encode-objc-type type)))
+             (size (ceiling (foreign-type-bits type) 8))
+             (align (round (log (ceiling (foreign-type-alignment type) 8) 2))))
+        (with-cstrs ((name string)
+                     (encoding encoding))
+          (when (eql #$NO (#_class_addIvar class name size align encoding))
+            (error "class_addIvar failed"))
+          (with-macptrs ((ivar (#_class_getInstanceVariable class name)))
+            (unless (%null-ptr-p ivar)
+              (let* ((offset (#_ivar_getOffset ivar)))
+                (setf (foreign-direct-slot-definition-bit-offset dslotd)
+                      (ash offset 3))))))))))
+
+
+#+(or apple-objc-2.0 cocotron-objc)
+(defun %revive-foreign-slots (class)
+  (dolist (dslotd (class-direct-slots class))
+    (when (typep dslotd 'foreign-direct-slot-definition)
+      (let* ((string (lisp-defined-slot-name-to-objc-slot-name (slot-definition-name dslotd)))
+             (type (foreign-slot-definition-foreign-type dslotd))
+             (encoding (progn
+                         (ensure-foreign-type-bits type)
+                         (encode-objc-type type)))
+             (size (ceiling (foreign-type-bits type) 8))
+             (align (round (log (ceiling (foreign-type-alignment type) 8) 2))))
+        (with-cstrs ((name string)
+                     (encoding encoding))
+          (#_class_addIvar class name size align encoding)
+          (with-macptrs ((ivar (#_class_getInstanceVariable class name)))
+              (unless (%null-ptr-p ivar)
+                (let* ((offset (#_ivar_getOffset ivar)))
+                  (unless (eql (foreign-direct-slot-definition-bit-offset dslotd)
+                               (ash offset 3))
+                    (dbg))))))))))
+
+(defun lisp-defined-slot-name-to-objc-slot-name (lisp-name)
+  (lisp-to-objc-message (list lisp-name)))
+
+;;; This is only going to be called on a class created by the user;
+;;; each foreign direct slotd's offset field should already have been
+;;; set to the slot's bit offset.
+#-(or apple-objc-2.0 cocotron-objc)
+(defun %make-objc-ivars (class)
+  (let* ((start-offset (superclass-instance-size class))
+	 (foreign-dslotds (loop for s in (class-direct-slots class)
+				when (typep s 'foreign-direct-slot-definition)
+				collect s)))
+    (if (null foreign-dslotds)
+      (values (%null-ptr) start-offset)
+      (let* ((n (length foreign-dslotds))
+	     (offset start-offset)
+	     (ivars (malloc (+ 4 (* n (%foreign-type-or-record-size
+				       :objc_ivar :bytes))))))
+      (setf (pref ivars :objc_ivar_list.ivar_count) n)
+      (do* ((l foreign-dslotds (cdr l))
+	    (dslotd (car l) (car l))
+	    (ivar (pref ivars :objc_ivar_list.ivar_list)
+		  (%inc-ptr ivar (%foreign-type-or-record-size
+				 :objc_ivar :bytes))))
+	   ((null l) (values ivars (ash (align-offset offset 32) 3)))
+	(let* ((string (lisp-defined-slot-name-to-objc-slot-name (slot-definition-name dslotd)))
+	       (type (foreign-slot-definition-foreign-type dslotd))
+	       (encoding (progn
+                           (ensure-foreign-type-bits type)
+                           (encode-objc-type type))))
+	  (setq offset (foreign-direct-slot-definition-bit-offset dslotd))
+	  (setf (pref ivar :objc_ivar.ivar_name) (make-cstring string)
+		(pref ivar :objc_ivar.ivar_type) (make-cstring encoding)
+		(pref ivar :objc_ivar.ivar_offset) (ash offset -3))
+          (incf offset (foreign-type-bits type))))))))
+  
+  
+
+(defun %objc-ivar-offset-in-class (name c)
+  ;; If C is a non-null ObjC class that contains an instance variable
+  ;; named NAME, return that instance variable's offset,  else return
+  ;; NIL.
+  #+(or apple-objc-2.0 cocotron-objc)
+  (with-cstrs ((name name))
+    (with-macptrs ((ivar (#_class_getInstanceVariable c name)))
+      (unless (%null-ptr-p ivar)
+        (#_ivar_getOffset ivar))))
+  #-(or apple-objc-2.0 cocotron-objc)
+  (when (objc-class-p c)
+    (with-macptrs ((ivars (pref c :objc_class.ivars)))
+      (unless (%null-ptr-p ivars)
+	(loop with n = (pref ivars :objc_ivar_list.ivar_count)
+	      for i from 1 to n
+	      for ivar = (pref ivars :objc_ivar_list.ivar_list) 
+	          then (%inc-ptr ivar (record-length :objc_ivar))
+	      when (string= name (%get-cstring (pref ivar :objc_ivar.ivar_name)))
+	        do (return-from %objc-ivar-offset-in-class (pref ivar :objc_ivar.ivar_offset)))))))
+
+(defun %objc-ivar-offset (name c)
+  (labels ((locate-objc-slot (name class)
+	     (unless (%null-ptr-p class)
+		 (or (%objc-ivar-offset-in-class name class)
+		     (with-macptrs ((super #+(or apple-objc-2.0 cocotron-objc)
+                                           (#_class_getSuperclass class)
+                                           #-(or apple-objc-2.0 cocotron-objc)
+                                           (pref class :objc_class.super_class)))
+		       (unless (or (%null-ptr-p super) (eql super class))
+			 (locate-objc-slot name super)))))))
+    (when (objc-class-p c)
+      (or (locate-objc-slot name c)
+	  (error "No ObjC instance variable named ~S in ~S" name c)))))
+
+;;; Maintain the class wrapper of an ObjC class or metaclass.
+
+(defmethod (setf class-own-wrapper) :after (wrapper (class objc::objc-metaclass))
+  (setf (id->objc-metaclass-wrapper (objc-metaclass-id class)) wrapper))
+
+(defmethod (setf class-own-wrapper) :after (wrapper (class objc::objc-class))
+  (setf (id->objc-class-wrapper (objc-class-id class)) wrapper))
+
+;;; Return the getter and setter functions for a foreign slot
+;;; NOTE: Should be changed to use FOREIGN-TYPE-TO-REPRESENTATION-TYPE
+
+(defun compute-foreign-slot-accessors (eslotd)
+  (let* ((ftype (foreign-slot-definition-foreign-type eslotd))
+         (ordinal (foreign-type-ordinal ftype)))
+    (etypecase ftype
+      (foreign-integer-type
+       (let* ((bits (foreign-integer-type-bits ftype))
+	      (align (foreign-integer-type-alignment ftype))
+	      (signed (foreign-integer-type-signed ftype)))
+         (if (= bits align)
+	   (case bits
+	     (1 (values #'%get-bit #'%set-bit))
+	     (8 (values (if signed #'%get-signed-byte #'%get-unsigned-byte)
+			#'%set-byte))
+	     (16 (values (if signed #'%get-signed-word #'%get-unsigned-word)
+			 #'%set-word))
+	     (32 (values (if signed #'%get-signed-long #'%get-unsigned-long)
+			 #'%set-long))
+	     (64 (if signed
+		   (values #'%%get-signed-longlong #'%%set-signed-longlong)
+		   (values #'%%get-unsigned-longlong #'%%set-unsigned-longlong)))
+             (t (values #'(lambda (ptr offset)
+                       (%get-bitfield ptr offset bits))
+                   #'(lambda (ptr offset new)
+                       (setf (%get-bitfield ptr offset bits) new)))))
+           (values #'(lambda (ptr offset)
+                       (%get-bitfield ptr offset bits))
+                   #'(lambda (ptr offset new)
+                       (setf (%get-bitfield ptr offset bits) new))))))
+      (foreign-double-float-type
+       (values #'%get-double-float #'%set-double-float))
+      (foreign-single-float-type
+       (values #'%get-single-float #'%set-single-float))
+      (foreign-pointer-type
+       (if (objc-id-type-p ftype)
+         (values #'%get-ptr #'%set-ptr)
+         (let* ((to (foreign-pointer-type-to ftype))
+                (to-ordinal (if to (foreign-type-ordinal to) 0)))
+           (values #'(lambda (ptr offset)
+                       (let* ((p (%null-ptr)))
+                         (%setf-macptr p (%get-ptr ptr offset))
+                         (unless (%null-ptr-p p)
+                           (%set-macptr-domain p 1)
+                           (%set-macptr-type p to-ordinal))
+                         p))
+                   #'%set-ptr))))
+      (foreign-mem-block-type
+       (let* ((nbytes (%foreign-type-or-record-size ftype :bytes)))
+	 (values #'(lambda (ptr offset)
+                     (let* ((p (%inc-ptr ptr offset)))
+                       (%set-macptr-type p ordinal)
+                       p))
+                 #'(lambda (pointer offset new)
+				(setf (%composite-pointer-ref
+				       nbytes
+				       pointer
+				       offset)
+				      new))))))))
+    
+
+
+;;; Shadow SLOT-CLASS's COMPUTE-EFFECTIVE-SLOT-DEFINITION with a
+;;; method for OBJC-CLASSes that sets up foreign slot info.
+
+(defmethod compute-effective-slot-definition :around ((class objc:objc-class-object)
+						      name
+						      direct-slots)
+  (let* ((first (first direct-slots)))
+    (if (not (typep first 'foreign-direct-slot-definition))
+      (call-next-method)
+      (let* ((initer (dolist (s direct-slots)
+		       (when (%slot-definition-initfunction s)
+			 (return s))))
+	     (documentor (dolist (s direct-slots)
+			   (when (%slot-definition-documentation s)
+			     (return s))))
+	     (initargs (let* ((initargs nil))
+			 (dolist (dslot direct-slots initargs)
+			   (dolist (dslot-arg (%slot-definition-initargs  dslot))
+			     (pushnew dslot-arg initargs :test #'eq)))))
+	     (eslotd
+	       (make-effective-slot-definition
+		class
+		:name name
+		:allocation :instance
+		:type (or (%slot-definition-type first) t)
+		:documentation (when documentor (nth-value
+				      1
+				      (%slot-definition-documentation
+				       documentor)))
+		:class (%slot-definition-class first)
+		:initargs initargs
+		:initfunction (if initer
+				(%slot-definition-initfunction initer))
+		:initform (if initer (%slot-definition-initform initer))
+		:foreign-type (foreign-slot-definition-foreign-type first))))
+      (multiple-value-bind (getter setter) (compute-foreign-slot-accessors eslotd)
+	(setf (foreign-slot-definition-getter eslotd) getter)
+	(setf (foreign-slot-definition-setter eslotd) setter))
+      eslotd))))
+
+(defun bit-offset-to-location (bit-offset foreign-type)
+  (ensure-foreign-type-bits foreign-type)
+  (let* ((bits (foreign-type-bits foreign-type)))
+    (if (or (= bits 1)
+            (and (not (typep foreign-type 'foreign-mem-block-type))
+                 (not (= bits (foreign-type-alignment foreign-type)))))
+      bit-offset
+      (ash bit-offset -3))))
+
+;;; Determine the location of each slot
+;;; An effective slot's location is
+;;; a) a function of the class's origin (superclass-instance-size)
+;;;    and the corresponding direct class's offset, if it's defined in the
+;;;    class (has a corresponding direct-slot-definition in the class)
+;;; b) Exactly the same as the superclass's version's location, because
+;;;    of single inheritance.
+
+(defun determine-foreign-slot-location (class slot-name)
+  (or
+   (dolist (d (class-direct-slots class))
+     (when (and (eq slot-name (slot-definition-name d))
+                (typep d 'foreign-direct-slot-definition))
+       (return (bit-offset-to-location
+                (foreign-direct-slot-definition-bit-offset d)
+                (foreign-slot-definition-foreign-type d )))))
+   (dolist (super (class-direct-superclasses class))
+     (when (typep super 'objc:objc-class) ; can be at most 1
+       (let* ((e (find slot-name (class-slots super) :key #'slot-definition-name)))
+	 (when e (return (slot-definition-location e))))))
+   (error "Can't find slot definition for ~s in ~s" slot-name class)))
+	  
+
+(defmethod compute-slots :around ((class objc:objc-class-object))
+  (flet ((foreign-slot-p (s) (typep s 'foreign-effective-slot-definition)))
+    (let* ((cpl (%class-precedence-list class))
+	   (slots (call-next-method))
+	   (instance-slots 
+	    (remove-if #'foreign-slot-p 
+		       (remove :class slots :key #'%slot-definition-allocation)))
+	   (class-slots (remove :instance slots :key #'%slot-definition-allocation))
+	   (foreign-slots (remove-if-not #'foreign-slot-p slots)))
+      (setq instance-slots
+	    (sort-effective-instance-slotds instance-slots class cpl))
+      (when *objc-clos-debug*
+	(format t "Instance slots: ~S~%Class Slots: ~S~%Foreign Slots: ~S~%"
+		instance-slots class-slots foreign-slots))
+      (loop for islot in instance-slots
+	    for loc = 1 then (1+ loc)
+	    do (setf (%slot-definition-location islot) loc))
+      (dolist (cslot class-slots)
+	(setf (%slot-definition-location cslot)
+	      (assoc (%slot-definition-name cslot)
+		     (%class-get (%slot-definition-class cslot) :class-slots)
+		     :test #'eq)))
+      (dolist (fslot foreign-slots)
+	(setf (%slot-definition-location fslot)
+	      (determine-foreign-slot-location
+	       class
+	       (%slot-definition-name fslot))))
+      (append instance-slots class-slots foreign-slots))))
+
+
+;;; Accessing foreign slots
+
+(defmethod slot-boundp-using-class ((class objc:objc-class-object)
+				    instance
+				    (slotd foreign-effective-slot-definition))
+  (declare (ignore class instance slotd))
+  ;; foreign slots are always bound
+  t)
+
+(defmethod slot-makunbound-using-class ((class objc:objc-class-object)
+					instance
+					(slotd foreign-effective-slot-definition))
+  (declare (ignore instance))
+  (error "Foreign slots cannot be unbound: ~S" (slot-definition-name slotd)))
+
+(defmethod slot-value-using-class ((class objc:objc-class-object)
+				   instance
+				   (slotd foreign-effective-slot-definition))
+  (funcall (foreign-slot-definition-getter slotd)
+	   instance
+	   (slot-definition-location slotd)))
+
+(defmethod (setf slot-value-using-class) (value
+					  (class objc:objc-class-object)
+					  instance
+					  (slotd foreign-effective-slot-definition))
+  (funcall (foreign-slot-definition-setter slotd)
+	   instance
+	   (slot-definition-location slotd)
+	   value))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;            Instance Allocation and Initialization Protocols            ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmethod make-instance ((class objc:objc-class-object) &rest initargs)
+  (let ((instance (apply #'allocate-instance class initargs)))
+    (if (%null-ptr-p instance)
+      instance
+      (apply #'initialize-instance instance initargs))))
+
+
+(defun remove-slot-initargs (class initargs)
+  (let* ((slot-initargs (class-slot-initargs class))) ; cache this, maybe
+    (collect ((new-initargs))
+    (loop for l = initargs then (cddr l)
+	  when (null l) do (return-from remove-slot-initargs (new-initargs))
+	  unless (member (first l)  slot-initargs :test #'eq)
+          do
+          (new-initargs (car l))
+          (new-initargs (cadr l))))))
+
+(defun create-foreign-instance-slot-vector (class)
+  (let* ((max 0))
+    (dolist (slotd (class-slots class)
+	     (unless (zerop max)
+	       (allocate-typed-vector :slot-vector (1+ max) (%slot-unbound-marker))))
+      (when (typep slotd 'standard-effective-slot-definition)
+	(let* ((loc (slot-definition-location slotd)))
+	  (if (> loc max)
+	    (setq max loc)))))))
+
+	       
+					 
+(defmethod allocate-instance ((class objc:objc-class) &rest initargs &key &allow-other-keys)
+  (unless (class-finalized-p class)
+    (finalize-inheritance class))
+  (let* ((instance
+	  (multiple-value-bind (ks vs) (keys-and-vals (remove-slot-initargs
+						       class
+						       initargs))
+	    (send-objc-init-message (allocate-objc-object class) ks vs))))
+    (unless (%null-ptr-p instance)
+      (or (gethash instance *objc-object-slot-vectors*)
+          (let* ((slot-vector (create-foreign-instance-slot-vector class)))
+            (when slot-vector
+              (let* ((raw-ptr (raw-macptr-for-instance instance)))
+                (setf (slot-vector.instance slot-vector) raw-ptr)
+                (setf (gethash raw-ptr *objc-object-slot-vectors*) slot-vector)
+                (register-canonical-objc-instance instance raw-ptr))))))
+    instance))
+
+
+
+
+(defmethod initialize-instance ((instance objc:objc-object) &rest initargs)
+  (apply #'shared-initialize instance t initargs))
+
+(defmethod reinitialize-instance ((instance objc:objc-object) &rest initargs)
+  (apply #'shared-initialize instance nil initargs))
+
+(defmethod initialize-instance :after ((class objc:objc-class) &rest initargs)
+  (declare (ignore initargs))
+  (unless (slot-value class 'foreign)
+    #-(or apple-objc-2.0 cocotron-objc)
+    (multiple-value-bind (ivars instance-size)
+	(%make-objc-ivars class)
+      (%add-objc-class class ivars instance-size))
+    #+(or apple-objc-2.0 cocotron-objc)
+    (%add-objc-class class)))
+
+(defmethod shared-initialize ((instance objc:objc-object) slot-names 
+			      &rest initargs)
+  (let ((class (class-of instance)))
+    ;; Initialize CLOS slots
+    (dolist (slotd (class-slots class))
+      (when (not (typep slotd 'foreign-effective-slot-definition)) ; For now
+	(let ((sname (slot-definition-name slotd))
+	      (slot-type (slot-definition-type slotd))
+	      (typepred (slot-value slotd 'type-predicate))
+	      (initfunction (slot-definition-initfunction slotd)))
+	  (multiple-value-bind (ignore newval foundp)
+			       (get-properties initargs
+					       (slot-definition-initargs slotd))
+	    (declare (ignore ignore))
+	    (if foundp
+		(if (or (null typepred)
+                        (funcall typepred newval))
+		    (setf (slot-value instance sname) newval)
+		  (report-bad-arg newval slot-type))
+	      (let* ((loc (slot-definition-location slotd))
+		     (curval (%standard-instance-instance-location-access
+			     instance loc)))
+		(when (and (or (eq slot-names t) 
+			       (member sname slot-names :test #'eq))
+			   (eq curval (%slot-unbound-marker))
+			   initfunction)
+		  (let ((newval (funcall initfunction)))
+		    (unless (or (null typepred)
+                                (funcall typepred newval))
+		      (report-bad-arg newval slot-type))
+		    (setf (%standard-instance-instance-location-access
+			   instance loc)
+			  newval)))))))))
+    instance))
+
+(defmethod shared-initialize :after ((spec foreign-effective-slot-definition)
+				     slot-names
+				     &key &allow-other-keys)
+  (declare (ignore slot-names))
+  (setf (slot-value spec 'type-predicate) #'true))
+
+;;; The CLASS-OF an existing OBJC:OBJC-CLASS is an OBJC:OBJC-METACLASS,
+;;; but not necessarily the one specified as a :metaclass option to
+;;; DEFCLASS or ENSURE-CLASS.  Allow an existing class to be reinitialized,
+;;; as long as the specified :metaclass and the class's own class have
+;;; the same metaclass and specified metaclass is a root class.
+
+(defmethod ensure-class-using-class ((class objc:objc-class)
+				     name
+				     &rest keys &key)
+  (multiple-value-bind (metaclass initargs)
+      (ensure-class-metaclass-and-initargs class keys)
+    (let* ((existing-metaclass (class-of class)))
+      (if (and (eq (class-of metaclass)
+		   (class-of existing-metaclass))
+	       ;; A root metaclass has the corresponding class as
+	       ;; its superclass, and that class has no superclass.
+	       (with-macptrs ((super #+(or apple-objc-2.0 cocotron-objc)
+                                     (#_class_getSuperclass metaclass)
+                                     #-(or apple-objc-2.0 cocotron-objc)
+                                     (pref metaclass :objc_class.super_class)))
+		 (and (not (%null-ptr-p super))
+		      (not (%objc-metaclass-p super))
+		      (%null-ptr-p
+                       #+(or apple-objc-2.0 cocotron-objc)
+                       (#_class_getSuperclass super)
+                       #-(or apple-objc-2.0 cocotron-objc)
+                       (pref super :objc_class.super_class)))))
+	;; Whew! it's ok to reinitialize the class.
+	(progn
+	  (apply #'reinitialize-instance class initargs)
+	  (setf (find-class name) class))
+	(error "Can't change metaclass of ~s to ~s." class metaclass)))))
+
+  
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;              Class Definition and Finalization Protocols               ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Create the ObjC class/metaclass pair and dress it up in its minimal CLOS garb
+;;; This currently requires that exactly one of DIRECT-SUPERCLASSES be a
+;;; already existing subclass of OBJC:OBJC-CLASS
+
+(defun compute-objc-variable-name (sym)
+  (let* ((pname (string sym))
+	 (first-alpha (position-if #'alpha-char-p pname)))
+    (string-downcase
+     (apply #'string-cat 
+	    (mapcar #'string-capitalize (split-if-char #\- pname :elide)))
+     :end (if first-alpha (1+ first-alpha) 1))))
+
+(defmethod allocate-instance ((metaclass objc:objc-metaclass) 
+			      &key name direct-superclasses
+			      &allow-other-keys)
+  (let ((superclass
+	 (loop for s in direct-superclasses
+	       when (typep s 'objc:objc-class)
+	         collect s into objc-supers
+	       finally 
+	       (if (= (length objc-supers) 1)
+		   (return (first objc-supers))
+		 (error "Exactly one OBJC:OBJC-CLASS must appear in ~S, found ~S" 
+			direct-superclasses
+			(length objc-supers))))))
+    (%allocate-objc-class name superclass)))
+
+(defmethod shared-initialize ((class objc:objc-class-object) slot-names &rest initargs)
+  (%shared-initialize class slot-names initargs))
+
+(defmethod validate-superclass ((c1 objc:objc-class) (c2 objc:objc-class))
+  t)
+
+(defmethod make-instances-obsolete ((class objc:objc-class))
+  class)
+
+;;; Reader/writer methods for instances of OBJC:OBJC-CLASS
+(defmethod reader-method-class ((class objc:objc-class)
+				(dslotd direct-slot-definition)
+				&rest initargs)
+  (declare (ignore initargs))
+  (find-class 'standard-reader-method))
+
+(defmethod writer-method-class ((class objc:objc-class)
+				(dslotd direct-slot-definition)
+				&rest initargs)
+  (declare (ignore initargs))
+  (find-class 'standard-writer-method))
+
+
+;;; By the time we see this, the slot name has been transformed to the form
+;;; "(load-time-value (ensure-slot-id <slot-name>))".
+;;; This only works if the setter is SETF inverse of the getter.
+(define-compiler-macro slot-id-value (&whole call instance slot-name &environment env)
+  (or
+   (let* ((type nil))
+     (if (and (symbolp instance)
+              (subtypep (setq type (cdr (assq 'type (nth-value 2 (variable-information instance env)))))
+                        'objc:objc-object
+                        env)
+              (consp slot-name)
+              (eq (car slot-name) 'load-time-value)
+              (consp (cdr slot-name))
+              (null (cddr slot-name))
+              (eq (caadr slot-name) 'ensure-slot-id)
+              (consp (cdadr slot-name))
+              (null (cddadr slot-name))
+              (setq slot-name (cadadr slot-name))
+              (quoted-form-p slot-name)
+              (setq slot-name (cadr slot-name)))
+       (let* ((class (find-class type nil env))
+              (eslotd (when class (find slot-name (class-slots class)
+                                        :key #'slot-definition-name))))
+         (when (typep eslotd 'foreign-effective-slot-definition)
+           (let* ((getter (foreign-slot-definition-getter eslotd))
+                  (name (if (typep getter 'compiled-function)
+                          (function-name getter))))
+             (when name
+               `(,name ,instance ,(slot-definition-location eslotd))))))))
+   call))
+
+
Index: /branches/new-random/objc-bridge/objc-package.lisp
===================================================================
--- /branches/new-random/objc-bridge/objc-package.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/objc-package.lisp	(revision 13309)
@@ -0,0 +1,60 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2007-2009 Clozure Associates and contributors.
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+;;;
+
+(in-package "CCL")
+
+;;; All class names and instance variable names are interned in the NS package
+;;; Force all symbols interned in the NS package to be external
+
+(defpackage "NS"
+  (:use)
+  (:export "+CGFLOAT-ZERO+" "CGFLOAT" "CG-FLOAT"))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (package-force-export "NS"))
+
+;;; ObjC function names (as produced by #/) are interned in NSF.
+(defpackage "NEXTSTEP-FUNCTIONS"
+  (:use)
+  (:nicknames "NSFUN"))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (package-force-export "NSFUN"))
+
+(defpackage "OBJC"
+  (:use)
+  (:export "OBJC-OBJECT" "OBJC-CLASS-OBJECT" "OBJC-CLASS" "OBJC-METACLASS"
+           "@CLASS" "@SELECTOR" "MAKE-OBJC-INSTANCE" "RETURNING-FOREIGN-STRUCT"
+           "DEFMETHOD" "SLET" "SEND" "SEND/STRET" "SEND-SUPER" "SEND-SUPER/STRET"
+           "DEFINE-OBJC-METHOD" "DEFINE-OBJC-CLASS-METHOD"
+           "OBJC-MESSAGE-SEND" "OBJC-MESSAGE-SEND-STRET"
+           "OBJC-MESSAGE-SEND-SUPER" "OBJC-MESSAGE-SEND-SUPER-STRET"
+           "LOAD-FRAMEWORK" "*OBJC-DESCRIPTION-MAX-LENGTH*"
+           ))
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (import '(objc:@class objc:@selector objc:make-objc-instance
+            objc:send objc:send/stret objc:send-super objc:send-super/stret
+            ns:+cgfloat-zero+ ns:cgfloat ns:cg-float
+            objc:define-objc-method objc:define-objc-class-method
+            objc:objc-message-send objc:objc-message-send-stret
+            objc:objc-message-send-super objc:objc-message-send-super-stret
+            objc:*objc-description-max-length*)
+          "CCL"))
+
+(provide "OBJC-PACKAGE")
Index: /branches/new-random/objc-bridge/objc-readtable.lisp
===================================================================
--- /branches/new-random/objc-bridge/objc-readtable.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/objc-readtable.lisp	(revision 13309)
@@ -0,0 +1,65 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2002-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defvar *objc-readtable* (copy-readtable nil))
+  (set-syntax-from-char #\] #\) *objc-readtable*))
+
+
+
+;;; We use the convention that [:super ....] denotes a send to the
+;;; defining object's superclass's method, and that a return value
+;;; specification of the form (:-> ... x) indicates a message send
+;;; that returns a structure (by reference) via the pointer x.
+
+(set-macro-character
+ #\[
+ (nfunction
+  |objc-[-reader|
+  (lambda (stream ignore)
+    (declare (ignore ignore))
+    (let* ((tail (read-delimited-list #\] stream))
+	   (structptr nil))
+      (unless *read-suppress*
+        (let* ((return (car (last tail))))
+          (when (and (consp return) (eq (car return) :->))
+            (rplaca (last tail) :void)
+            (setq structptr (car (last return)))))
+        (if (eq (car tail) :super)
+          (if structptr
+            `(objc-message-send-super-stret ,structptr (super) ,@(cdr tail))
+            `(objc-message-send-super (super) ,@(cdr tail)))
+          (if structptr
+            `(objc-message-send-stret ,structptr ,@tail)
+            `(objc-message-send ,@tail)))))))
+ nil
+ *objc-readtable*)
+
+(set-dispatch-macro-character
+ #\#
+ #\@
+ (nfunction
+  |objc-#@-reader|
+  (lambda (stream subchar numarg)
+    (declare (ignore subchar numarg))
+    (let* ((string (read stream)))
+      (unless *read-suppress*
+        (check-type string string)
+        `(@ ,string)))))
+ *objc-readtable*)
+
Index: /branches/new-random/objc-bridge/objc-runtime.lisp
===================================================================
--- /branches/new-random/objc-bridge/objc-runtime.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/objc-runtime.lisp	(revision 13309)
@@ -0,0 +1,3224 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2002-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+
+;;; Utilities for interacting with the Apple/GNU Objective-C runtime
+;;; systems.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  #+darwin-target (pushnew :apple-objc *features*)
+  #+(and darwin-target 64-bit-target) (pushnew :apple-objc-2.0 *features*)
+  #+win32-target (pushnew :cocotron-objc *features*)
+  #-(or darwin-target win32-target) (pushnew :gnu-objc *features*))
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (set-dispatch-macro-character
+   #\#
+   #\@
+   (nfunction
+    |objc-#@-reader|
+    (lambda (stream subchar numarg)
+      (declare (ignore subchar numarg))
+      (let* ((string (read stream)))
+	(unless *read-suppress*
+          (check-type string string)
+          `(@ ,string)))))))
+
+(eval-when (:compile-toplevel :execute)
+  #+apple-objc
+  (progn
+    (use-interface-dir :cocoa)
+    #+nomore
+    (use-interface-dir :carbon))        ; need :carbon for things in this file
+  #+cocotron-objc
+  (use-interface-dir :cocoa)
+  #+gnu-objc
+  (use-interface-dir :gnustep))
+
+
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "OBJC-PACKAGE")
+  (require "NAME-TRANSLATION")
+  (require "OBJC-CLOS"))
+
+;;; NSInteger and NSUInteger probably belong here.
+;;; CGFloat not so much.
+
+#-(or apple-objc-2.0 cocotron-objc)
+(progn
+  (def-foreign-type #>CGFloat :float)
+  (def-foreign-type #>NSUInteger :unsigned)
+  (def-foreign-type #>NSInteger :signed)
+  )
+
+(defconstant +cgfloat-zero+
+  #+(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) 0.0d0
+  #-(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) 0.0f0)
+
+(deftype cgfloat ()
+  #+(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) 'double-float
+  #-(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) 'single-float)
+
+(deftype cg-float () 'cgfloat)
+
+(deftype nsuinteger ()
+  #+(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) '(unsigned-byte 64)
+  #-(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) '(unsigned-byte 32))
+
+(deftype nsinteger ()
+  #+(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) '(signed-byte 64)
+  #-(and (or apple-objc-2.0 cocotron-objc) 64-bit-target) '(signed-byte 32))
+
+
+(defloadvar *NSApp* nil )
+
+;;; Apple ObjC 2.0 provides (#_objc_getProtocol name).  In other
+;;; runtimes, there doesn't seem to be any way to find a Protocol
+;;; object given its name.  We need to be able to ask at runtime
+;;; whether a given object conforms to a protocol in order to
+;;; know when a protocol method is ambiguous, at least when the
+;;; message contains ambiguous methods and some methods are protocol
+;;; methods
+(defvar *objc-protocols* (make-hash-table :test #'equal))
+
+
+(defstruct objc-protocol
+  name
+  address)
+
+
+(defun clear-objc-protocols ()
+  (maphash #'(lambda (name proto)
+	       (declare (ignore name))
+	       (setf (objc-protocol-address proto) nil))
+	   *objc-protocols*))
+
+(defun lookup-objc-protocol (name)
+  (values (gethash name *objc-protocols*)))
+
+(defun ensure-objc-classptr-resolved (classptr)
+  #-gnu-objc (declare (ignore classptr))
+  #+gnu-objc
+  (unless (logtest #$_CLS_RESOLV (pref classptr :objc_class.info))
+    (external-call "__objc_resolve_class_links" :void)))
+
+
+
+(defstruct private-objc-class-info
+  name
+  declared-ancestor)
+
+(defun compute-objc-direct-slots-from-info (info class)
+  (let* ((ns-package (find-package "NS")))
+    (mapcar #'(lambda (field)
+                (let* ((name (compute-lisp-name (unescape-foreign-name
+                                                 (foreign-record-field-name
+                                                  field))
+                                                ns-package))
+
+                       (type (foreign-record-field-type field))
+                       (offset (progn
+                                    (ensure-foreign-type-bits type)
+                                    (foreign-record-field-offset field))))
+                  (make-instance 'foreign-direct-slot-definition
+                                 :initfunction #'false
+                                 :initform nil
+                                 :name name
+                                 :foreign-type type
+                                 :class class
+                                 :bit-offset offset
+                                 :allocation :instance)))
+            (db-objc-class-info-ivars info))))
+
+
+(defun %ptr< (x y)
+  (< (the (unsigned-byte #+64-bit-target 64 #+32-bit-target 32)
+       (%ptr-to-int x))
+     (the (unsigned-byte #+64-bit-target 64 #+32-bit-target 32)
+       (%ptr-to-int Y))))
+
+(let* ((objc-class-map (make-hash-table :test #'eql :size 1024))
+       (objc-metaclass-map (make-hash-table :test #'eql :size 1024))
+       ;;; These are NOT lisp classes; we mostly want to keep track
+       ;;; of them so that we can pretend that instances of them
+       ;;; are instances of some known (declared) superclass.
+       (private-objc-classes (make-hash-table :test #'eql :size 2048))
+       (objc-class-lock (make-lock))
+       (next-objc-class-id 0)
+       (next-objc-metaclass-id 0)
+       (class-table-size 1024)
+       (c (make-array class-table-size))
+       (m (make-array class-table-size))
+       (cw (make-array class-table-size :initial-element nil))
+       (mw (make-array class-table-size :initial-element nil))
+       (csv (make-array class-table-size))
+       (msv (make-array class-table-size))
+       (class-id->metaclass-id (make-array class-table-size :initial-element nil))
+       (class-foreign-names (make-array class-table-size))
+       (metaclass-foreign-names (make-array class-table-size))
+       (class-id->ordinal (make-array class-table-size :initial-element nil))
+       (metaclass-id->ordinal (make-array class-table-size :initial-element nil))
+       )
+
+  (flet ((grow-vectors ()
+	   (let* ((old-size class-table-size)
+		  (new-size (* 2 old-size)))
+	     (declare (fixnum old-size new-size))
+	     (macrolet ((extend (v)
+                              `(setq ,v (%extend-vector old-size ,v new-size))))
+                   (extend c)
+                   (extend m)
+                   (extend cw)
+                   (extend mw)
+		   (fill cw nil :start old-size :end new-size)
+		   (fill mw nil :start old-size :end new-size)
+                   (extend csv)
+                   (extend msv)
+		   (extend class-id->metaclass-id)
+		   (fill class-id->metaclass-id nil :start old-size :end new-size)
+		   (extend class-foreign-names)
+		   (extend metaclass-foreign-names)
+		   (extend class-id->ordinal)
+		   (extend metaclass-id->ordinal)
+		   (fill class-id->ordinal nil :start old-size :end new-size)
+		   (fill metaclass-id->ordinal nil
+			 :start old-size :end new-size))
+	     (setq class-table-size new-size))))
+    (flet ((assign-next-class-id ()
+	     (let* ((id next-objc-class-id))
+	       (if (= (incf next-objc-class-id) class-table-size)
+		 (grow-vectors))
+	       id))
+	   (assign-next-metaclass-id ()
+	     (let* ((id next-objc-metaclass-id))
+	       (if (= (incf next-objc-metaclass-id) class-table-size)
+		 (grow-vectors))
+	       id)))
+      (defun id->objc-class (i)
+	(svref c i))
+      (defun (setf id->objc-class) (new i)
+	(setf (svref c i) new))
+      (defun id->objc-metaclass (i)
+	(svref m i))
+      (defun (setf id->objc-metaclass) (new i)
+	(setf (svref m i) new))
+      (defun id->objc-class-wrapper (i)
+	(svref cw i))
+      (defun (setf id->objc-class-wrapper) (new i)
+	(setf (svref cw i) new))
+      (defun id->objc-metaclass-wrapper (i)
+	(svref mw i))
+      (defun (setf id->objc-metaclass-wrapper) (new i)
+	(setf (svref mw i) new))
+      (defun id->objc-class-slots-vector (i)
+	(svref csv i))
+      (defun (setf id->objc-class-slots-vector) (new i)
+	(setf (svref csv i) new))
+      (defun id->objc-metaclass-slots-vector (i)
+	(svref msv i))
+      (defun (setf id->objc-metaclass-slots-vector) (new i)
+	(setf (svref msv i) new))
+      (defun objc-class-id-foreign-name (i)
+	(svref class-foreign-names i))
+      (defun (setf objc-class-id-foreign-name) (new i)
+	(setf (svref class-foreign-names i) new))
+      (defun objc-metaclass-id-foreign-name (i)
+	(svref metaclass-foreign-names i))
+      (defun (setf objc-metaclass-id-foreign-name) (new i)
+	(setf (svref metaclass-foreign-names i) new))
+      (defun %clear-objc-class-maps ()
+	(with-lock-grabbed (objc-class-lock)
+          (clrhash objc-class-map)
+          (clrhash objc-metaclass-map)
+          (clrhash private-objc-classes)))
+      (flet ((install-objc-metaclass (meta)
+	       (or (gethash meta objc-metaclass-map)
+		   (let* ((id (assign-next-metaclass-id))
+			  (meta (%inc-ptr meta 0)))
+		     (setf (gethash meta objc-metaclass-map) id)
+		     (setf (svref m id) meta
+			   (svref msv id)
+			   (make-objc-metaclass-slots-vector meta)
+			   (svref metaclass-id->ordinal id)
+			   (%next-class-ordinal))
+		     id))))
+	(defun register-objc-class (class)
+	  "ensure that the class is mapped to a small integer and associate a slots-vector with it."
+	  (with-lock-grabbed (objc-class-lock)
+	    (ensure-objc-classptr-resolved class)
+	    (or (gethash class objc-class-map)
+		(let* ((id (assign-next-class-id))
+		       (class (%inc-ptr class 0))
+		       (meta (pref class #+(or apple-objc cocotron-objc) :objc_class.isa #+gnu-objc :objc_class.class_pointer)))
+		  (setf (gethash class objc-class-map) id)
+		  (setf (svref c id) class
+			(svref csv id)
+			(make-objc-class-slots-vector class)
+			(svref class-id->metaclass-id id)
+			(install-objc-metaclass meta)
+			(svref class-id->ordinal id) (%next-class-ordinal))
+		  id)))))
+      (defun objc-class-id (class)
+        (gethash class objc-class-map))
+      (defun objc-metaclass-id (meta)
+        (gethash meta objc-metaclass-map))
+      (defun objc-class-id->objc-metaclass-id (class-id)
+	(svref class-id->metaclass-id class-id))
+      (defun objc-class-id->objc-metaclass (class-id)
+	(svref m (svref class-id->metaclass-id class-id)))
+      (defun objc-class-id->ordinal (i)
+	(svref class-id->ordinal i))
+      (defun (setf objc-class-id->ordinal) (new i)
+	(setf (svref class-id->ordinal i) new))
+      (defun objc-metaclass-id->ordinal (m)
+	(svref metaclass-id->ordinal m))
+      (defun (setf objc-metaclass-id->ordinal) (new m)
+	(setf (svref class-id->ordinal m) new))
+      (defun objc-class-map () objc-class-map)
+      (defun %objc-class-count () next-objc-class-id)
+      (defun objc-metaclass-map () objc-metaclass-map)
+      (defun %objc-metaclass-count () next-objc-metaclass-id)
+      (defun %register-private-objc-class (c name)
+        (setf (gethash c private-objc-classes) 
+              (make-private-objc-class-info :name name)))
+      (defun %get-private-objc-class (c)
+        (gethash c private-objc-classes))
+      (defun private-objc-classes ()
+        private-objc-classes))))
+
+(pushnew #'%clear-objc-class-maps *save-exit-functions* :test #'eq
+         :key #'function-name)
+
+(defun do-all-objc-classes (f)
+  (maphash #'(lambda (ptr id) (declare (ignore ptr)) (funcall f (id->objc-class id)))
+           (objc-class-map)))
+
+(defun canonicalize-registered-class (c)
+  (let* ((id (objc-class-id c)))
+    (if id
+      (id->objc-class id)
+      (error "Class ~S isn't recognized." c))))
+
+(defun canonicalize-registered-metaclass (m)
+  (let* ((id (objc-metaclass-id m)))
+    (if id
+      (id->objc-metaclass id)
+      (error "Class ~S isn't recognized." m))))
+
+(defun canonicalize-registered-class-or-metaclass (x)
+  (if (%objc-metaclass-p x)
+    (canonicalize-registered-metaclass x)
+    (canonicalize-registered-class x)))
+
+
+;;; Open shared libs.
+#+(or darwin-target cocotron-objc)
+(progn
+(defloadvar *cocoa-event-process* *initial-process*)
+
+
+(defun current-ns-thread ()
+  (with-cstrs ((class-name "NSThread")
+               (message-selector-name "currentThread"))
+    (let* ((nsthread-class (#_objc_lookUpClass class-name))
+           (message-selector (#_sel_getUid message-selector-name)))
+      (#_objc_msgSend nsthread-class message-selector)
+      nil)))
+  
+(defun create-void-nsthread ()
+  ;; Create an NSThread which does nothing but exit.
+  ;; This'll help to convince the AppKit that we're
+  ;; multitheaded.  (A lot of other things, including
+  ;; the ObjC runtime, seem to have already noticed.)
+  (with-cstrs ((thread-class-name "NSThread")
+               (pool-class-name "NSAutoreleasePool")
+               (thread-message-selector-name "detachNewThreadSelector:toTarget:withObject:")
+               (exit-selector-name "class")
+               (alloc-selector-name "alloc")
+               (init-selector-name "init")
+               (release-selector-name "release"))
+    (let* ((nsthread-class (#_objc_lookUpClass thread-class-name))
+           (pool-class (#_objc_lookUpClass pool-class-name))
+           (thread-message-selector (#_sel_getUid thread-message-selector-name))
+           (exit-selector (#_sel_getUid exit-selector-name))
+           (alloc-selector (#_sel_getUid alloc-selector-name))
+           (init-selector (#_sel_getUid init-selector-name))
+           (release-selector (#_sel_getUid release-selector-name))
+           (pool (#_objc_msgSend
+                  (#_objc_msgSend pool-class
+                                  alloc-selector)
+                  init-selector)))
+      (unwind-protect
+           (#_objc_msgSend nsthread-class thread-message-selector
+                           :address exit-selector
+                           :address nsthread-class
+                           :address (%null-ptr))
+        (#_objc_msgSend pool release-selector))
+      nil)))
+
+(defun run-in-cocoa-process-and-wait  (f)
+  (let* ((process *cocoa-event-process*)
+	 (success (cons nil nil))
+	 (done (make-semaphore)))
+    (process-interrupt process #'(lambda ()
+				   (unwind-protect
+					(progn
+					  (setf (car success) (funcall f)))
+				     (signal-semaphore done))))
+    (wait-on-semaphore done)
+    (car success)))
+
+
+(defun load-cocoa-framework ()
+  (run-in-cocoa-process-and-wait
+   #'(lambda ()
+       ;; We need to load and "initialize" the CoreFoundation library
+       ;; in the thread that's going to process events.  Looking up a
+       ;; symbol in the library should cause it to be initialized
+       #+apple-objc
+       (open-shared-library "/System/Library/Frameworks/Cocoa.framework/Cocoa")
+       #+cocotron-objc
+       (progn
+         (open-shared-library "Foundation.1.0.dll")
+         (open-shared-library "AppKit.1.0.dll")
+         ;; We may need to call #_NSInitializeProcess
+         ;; under Cocotron.  If so, we'd need to do
+         ;; so on standalone startup, too, and would
+         ;; have to have heap-allocated the string vector
+         ;; and its strings.
+         #+notyet
+         (with-string-vector (argv (list (kernel-path)))
+           (#_NSInitializeProcess 1 argv)))
+         
+       ;(#_GetCurrentEventQueue)
+       (current-ns-thread)
+       (create-void-nsthread))))
+
+(pushnew #'load-cocoa-framework *lisp-system-pointer-functions* :key #'function-name)
+
+#-cocotron
+(load-cocoa-framework)
+
+#+cocotron
+(let* ((path (getenv "PATH")))
+           (unwind-protect
+              (progn
+                (setenv "PATH"
+                        (format nil "~a;~a"
+                                (native-translated-namestring
+                                 (truename "ccl:cocotron;"))
+                                path))
+                (load-cocoa-framework))
+           (setenv "PATH" path)))
+
+
+(defun find-cfstring-sections ()
+  (warn "~s is obsolete" 'find-cfstring-sections))
+
+)
+
+#+gnu-objc
+(progn
+(defparameter *gnustep-system-root* "/usr/GNUstep/" "The root of all evil.")
+(defparameter *gnustep-libraries-pathname*
+  (merge-pathnames "System/Library/Libraries/" *gnustep-system-root*))
+
+(defloadvar *pending-loaded-classes* ())
+
+(defcallback register-class-callback (:address class :address category :void)
+  (let* ((id (map-objc-class class)))
+    (unless (%null-ptr-p category)
+      (let* ((cell (or (assoc id *pending-loaded-classes*)
+                       (let* ((c (list id)))
+                         (push c *pending-loaded-classes*)
+                         c))))
+        (push (%inc-ptr category 0) (cdr cell))))))
+
+;;; Shouldn't really be GNU-objc-specific.
+
+(defun get-c-format-string (c-format-ptr c-arg-ptr)
+  (do* ((n 128))
+       ()
+    (declare (fixnum n))
+    (%stack-block ((buf n))
+      (let* ((m (#_vsnprintf buf n c-format-ptr c-arg-ptr)))
+	(declare (fixnum m))
+	(cond ((< m 0) (return nil))
+	      ((< m n) (return (%get-cstring buf)))
+	      (t (setq n m)))))))
+
+
+
+(defun init-gnustep-framework ()
+  (or (getenv "GNUSTEP_SYSTEM_ROOT")
+      (setenv "GNUSTEP_SYSTEM_ROOT" *gnustep-system-root*))
+  (open-shared-library "libobjc.so.1")
+  (setf (%get-ptr (foreign-symbol-address "_objc_load_callback"))
+        register-class-callback)
+  (open-shared-library (namestring (merge-pathnames "libgnustep-base.so"
+                                                    *gnustep-libraries-pathname*)))
+  (open-shared-library (namestring (merge-pathnames "libgnustep-gui.so"
+                                                    *gnustep-libraries-pathname*))))
+
+(def-ccl-pointers gnustep-framework ()
+  (init-gnustep-framework))
+)
+
+(defun get-appkit-version ()
+  #+apple-objc
+  #&NSAppKitVersionNumber
+  #+cocotron-objc 1.0                   ; fix this
+  #+gnu-objc
+  (get-foundation-version))
+
+(defun get-foundation-version ()
+  #+apple-objc #&NSFoundationVersionNumber
+  #+cocotron-objc 1.0                   ; fix this
+  #+gnu-objc (%get-cstring (foreign-symbol-address "gnustep_base_version")))
+
+(defparameter *appkit-library-version-number* (get-appkit-version))
+(defparameter *foundation-library-version-number* (get-foundation-version))
+
+(defparameter *extension-framework-paths* ())
+
+;;; An instance of NSConstantString (which is a subclass of NSString)
+;;; consists of a pointer to the NSConstantString class (which the
+;;; global "_NSConstantStringClassReference" conveniently refers to), a
+;;; pointer to an array of 8-bit characters (doesn't have to be #\Nul
+;;; terminated, but doesn't hurt) and the length of that string (not
+;;; counting any #\Nul.)
+;;; The global reference to the "NSConstantString" class allows us to
+;;; make instances of NSConstantString, ala the @"foo" construct in
+;;; ObjC.  Sure it's ugly, but it seems to be exactly what the ObjC
+;;; compiler does.
+
+
+(defloadvar *NSConstantString-class*
+  (with-cstrs ((name "NSConstantString"))
+    #+(or apple-objc cocotron-objc) (#_objc_lookUpClass name)
+    #+gnu-objc (#_objc_lookup_class name)))
+
+
+;;; Catch frames are allocated on a stack, so it's OK to pass their
+;;; addresses around to foreign code.
+(defcallback throw-to-catch-frame (:signed-fullword value
+                                   :address frame
+                                   :void)
+  (throw (%get-object frame target::catch-frame.catch-tag) value))
+
+
+#+(and x8632-target (or apple-objc cocotron-objc))
+(defloadvar *setjmp-catch-rip-code*
+    (let* ((code-bytes '(#x83 #xec #x10 ; subl $16,%esp
+                         #x89 #x04 #x24 ; movl %eax,(%esp)
+                         #x89 #x7c #x24 #x04   ; movl %edi,4(%esp)
+                         #xff #xd3))    ; call *%ebx
+           (nbytes (length code-bytes))
+           (p (malloc nbytes)))
+      (dotimes (i nbytes p)
+        (setf (%get-unsigned-byte p i) (pop code-bytes)))))
+
+#+apple-objc
+(progn
+;;; NSException-handling stuff.
+;;; First, we have to jump through some hoops so that #_longjmp can
+;;; jump through some hoops (a jmp_buf) and wind up throwing to a
+;;; lisp catch tag.
+
+;;; These constants (offsets in the jmp_buf structure) come from
+;;; the _setjmp.h header file in the Darwin LibC source.
+
+#+ppc32-target
+(progn
+(defconstant JMP-lr #x54 "link register (return address) offset in jmp_buf")
+#|(defconstant JMP-ctr #x5c "count register jmp_buf offset")|#
+(defconstant JMP-sp 0 "stack pointer offset in jmp_buf")
+(defconstant JMP-r14 12 "offset of r14 (which we clobber) in jmp_buf")
+(defconstant JMP-r15 16 "offset of r14 (which we also clobber) in jmp_buf"))
+
+#+ppc64-target
+(progn
+(defconstant JMP-lr #xa8 "link register (return address) offset in jmp_buf")
+#|(defconstant JMP-ctr #x5c "count register jmp_buf offset")|#
+(defconstant JMP-sp 0 "stack pointer offset in jmp_buf")
+(defconstant JMP-r13 #x10 "offset of r13 (which we preserve) in jmp_buf")
+(defconstant JMP-r14 #x18 "offset of r14 (which we clobber) in jmp_buf")
+(defconstant JMP-r15 #x20 "offset of r15 (which we also clobber) in jmp_buf"))
+
+;;; These constants also come from Libc sources.  Hey, who needs
+;;; header files ?
+#+x8664-target
+(progn
+(defconstant JB-RBX 0)
+(defconstant JB-RBP 8)
+(defconstant JB-RSP 16)
+(defconstant JB-R12 24)
+(defconstant JB-R13 32)
+(defconstant JB-R14 40)
+(defconstant JB-R15 48)
+(defconstant JB-RIP 56)
+(defconstant JB-RFLAGS 64)
+(defconstant JB-MXCSR 72)
+(defconstant JB-FPCONTROL 76)
+(defconstant JB-MASK 80)
+)
+
+;;; I think that we know where these constants come from.
+#+x8632-target
+(progn
+  (defconstant JB-FPCW 0)
+  (defconstant JB-MASK 4)
+  (defconstant JB-MXCSR 8)
+  (defconstant JB-EBX 12)
+  (defconstant JB-ECX 16)
+  (defconstant JB-EDX 20)
+  (defconstant JB-EDI 24)
+  (defconstant JB-ESI 28)
+  (defconstant JB-EBP 32)
+  (defconstant JB-ESP 36)
+  (defconstant JB-SS 40)
+  (defconstant JB-EFLAGS 44)
+  (defconstant JB-EIP 48)
+  (defconstant JB-CS 52)
+  (defconstant JB-DS 56)
+  (defconstant JB-ES 60)
+  (defconstant JB-FS 64)
+  (defconstant JB-GS 68)
+
+
+  )
+
+ 
+
+;;; A malloc'ed pointer to three words of machine code.  The first
+;;; instruction copies the address of the trampoline callback from r14
+;;; to the count register.  The second instruction (rather obviously)
+;;; copies r15 to r4.  A C function passes its second argument in r4,
+;;; but since r4 isn't saved in a jmp_buf, we have to do this copy.
+;;; The second instruction just jumps to the address in the count
+;;; register, which is where we really wanted to go in the first
+;;; place.
+
+#+ppc-target
+(macrolet ((ppc-lap-word (instruction-form)
+             (uvref (uvref (compile nil
+                                    `(lambda (&lap 0)
+                                      (ppc-lap-function () ((?? 0))
+                                       ,instruction-form)))
+                           0) #+ppc64-target 1 #+ppc32-target 0)))
+  (defloadvar *setjmp-catch-lr-code*
+      (let* ((p (malloc 12)))
+        (setf (%get-unsigned-long p 0) (ppc-lap-word (mtctr 14))
+              (%get-unsigned-long p 4) (ppc-lap-word (mr 4 15))
+              (%get-unsigned-long p 8) (ppc-lap-word (bctr)))
+        ;;; Force this code out of the data cache and into memory, so
+        ;;; that it'll get loaded into the icache.
+        (ff-call (%kernel-import #.target::kernel-import-makedataexecutable) 
+                 :address p 
+                 :unsigned-fullword 12
+                 :void)
+        p)))
+
+;;; This isn't used; it isn't right, either.
+#+x8664-target
+(defloadvar *setjmp-catch-rip-code*
+    (let* ((code-bytes '(#x4c #x89 #xe6     ; movq %r12, %rsi
+                         #xff #xd3))        ; call *%rbx
+           (nbytes (length code-bytes))
+           (p (malloc nbytes)))
+      (dotimes (i nbytes p)
+        (setf (%get-unsigned-byte p i) (pop code-bytes)))))
+
+
+
+
+
+;;; Initialize a jmp_buf so that when it's #_longjmp-ed to, it'll
+;;; wind up calling THROW-TO-CATCH-FRAME with the specified catch
+;;; frame as its second argument.  The C frame used here is just
+;;; an empty C stack frame from which the callback will be called.
+
+#+ppc-target
+(defun %associate-jmp-buf-with-catch-frame (jmp-buf catch-frame c-frame)
+  (%set-object jmp-buf JMP-sp c-frame)
+  (%set-object jmp-buf JMP-r15 catch-frame)
+  #+ppc64-target
+  (%set-object jmp-buf JMP-r13 (%get-os-context))
+  (setf (%get-ptr jmp-buf JMP-lr) *setjmp-catch-lr-code*
+        (%get-ptr jmp-buf JMP-r14) throw-to-catch-frame)
+  t)
+
+#+x8664-target
+(defun %associate-jmp-buf-with-catch-frame (jmp-buf catch-frame c-frame)
+  (setf (%get-ptr jmp-buf JB-rbx) throw-to-catch-frame
+        (%get-ptr jmp-buf JB-rip) *setjmp-catch-rip-code*)
+  (setf (%get-unsigned-long jmp-buf JB-mxcsr) #x1f80
+        (%get-unsigned-long jmp-buf JB-fpcontrol) #x37f)
+  (%set-object jmp-buf JB-RSP c-frame)
+  (%set-object jmp-buf JB-RBP c-frame)
+  (%set-object jmp-buf JB-r12 catch-frame)
+  t)
+
+#+x8632-target
+;;; Ugh.  Apple stores segment register values in jmp_bufs.  You know,
+;;; since they're so volatile and everything.
+(defun %associate-jmp-buf-with-catch-frame (jmp-buf catch-frame c-frame)
+  (setf (%get-unsigned-word jmp-buf JB-FS) (%get-fs-register)
+        (%get-unsigned-word jmp-buf JB-GS) (%get-gs-register)
+        (%get-unsigned-word jmp-buf JB-CS) #x17
+        (%get-unsigned-word jmp-buf JB-DS) #x1f
+        (%get-unsigned-word jmp-buf JB-ES) #x1f
+        (%get-unsigned-word jmp-buf JB-SS) #x1f)
+  (%set-object jmp-buf JB-ESP c-frame)
+  (%set-object jmp-buf JB-EBP c-frame)
+  (setf (%get-unsigned-long jmp-buf JB-MXCSR) #x1f80
+        (%get-unsigned-long jmp-buf JB-FPCW) #x37f
+        (%get-unsigned-long jmp-buf JB-MASK) 0)
+  (setf (%get-ptr jmp-buf JB-EBX) throw-to-catch-frame
+        (%get-ptr jmp-buf JB-EIP) *setjmp-catch-rip-code*)
+  (%set-object jmp-buf JB-EDI catch-frame)
+  t)
+  
+
+        
+
+)
+
+#+win32-target
+(progn
+  (eval-when (:compile-toplevel :execute)
+    (progn
+      (defconstant jb-ebp 0)
+      (defconstant jb-ebx 4)
+      (defconstant jb-edi 8)
+      (defconstant jb-esi 12)
+      (defconstant jb-esp 16)
+      (defconstant jb-eip 20)
+      (defconstant jb-seh 24)
+      (defconstant jb-seh-info 28)))
+
+  (defx8632lapfunction set-jb-seh ((jb arg_z))
+    (macptr-ptr arg_z temp0)             ;fixnum-aligned
+    (movl (@ (% fs) 0) (% imm0))
+    (movl (% imm0) (@ jb-seh (% temp0)))
+    (cmpl ($ -1) (% imm0))
+    (je @store)
+    (movl (@ 12 (% imm0)) (% imm0))
+    @store
+    (movl (% imm0) (@ jb-seh-info (% temp0)))
+    (single-value-return))
+
+(defun %associate-jmp-buf-with-catch-frame (jmp-buf catch-frame c-frame)
+  (%set-object jmp-buf JB-ESP (1+ c-frame))
+  (%set-object jmp-buf JB-EBP (1+ c-frame))
+  (setf (%get-ptr jmp-buf JB-EBX) throw-to-catch-frame
+        (%get-ptr jmp-buf JB-EIP) *setjmp-catch-rip-code*)
+  (%set-object jmp-buf JB-EDI catch-frame)
+  (set-jb-seh jmp-buf)
+  t)  
+
+  
+  )
+
+;;; When starting up an image that's had ObjC classes in it, all of
+;;; those canonical classes (and metaclasses) will have had their type
+;;; changed (by SAVE-APPLICATION) to, CCL::DEAD-MACPTR and the addresses
+;;; of those classes may be bogus.  The hash tables (objc-class/metaclass-map)
+;;; should be empty.
+;;; For each class that -had- had an assigned ID, determine its ObjC
+;;; class name, and ask ObjC where (if anywhere) the class is now.
+;;; If we get a non-null answer, revive the class pointer and set its
+;;; address appropriately, then add an entry to the hash-table; this
+;;; means that classes that existed on both sides of SAVE-APPLICATION
+;;; will retain the same ID.
+
+(defun revive-objc-classes ()
+  ;; We need to do some things so that we can use (@class ...)
+  ;; and (@selector ...) early.
+  (invalidate-objc-class-descriptors)
+  (clear-objc-selectors)
+  (clear-objc-protocols)
+  (reset-objc-class-count)
+  ;; Ensure that any addon frameworks are loaded.
+  (dolist (path *extension-framework-paths*)
+    (%reload-objc-framework path))
+  ;; Make a first pass over the class and metaclass tables;
+  ;; resolving those foreign classes that existed in the old
+  ;; image and still exist in the new.
+  (let* ((class-map (objc-class-map))
+	 (metaclass-map (objc-metaclass-map))
+	 (nclasses (%objc-class-count)))
+    (dotimes (i nclasses)
+      (let* ((c (id->objc-class i))
+	     (meta-id (objc-class-id->objc-metaclass-id i))
+	     (m (id->objc-metaclass meta-id)))
+        (unless (typep c 'macptr)
+          (%revive-macptr c)
+          (%setf-macptr c (%null-ptr)))
+        (unless (typep m 'macptr)
+          (%revive-macptr m)
+          (%setf-macptr m (%null-ptr)))
+	(unless (gethash c class-map)
+	  (%set-pointer-to-objc-class-address (objc-class-id-foreign-name i) c)
+	  ;; If the class is valid and the metaclass is still
+	  ;; unmapped, set the metaclass pointer's address and map it.
+	  (unless (%null-ptr-p c)
+            (setf (gethash c class-map) i)
+	    (unless (gethash m metaclass-map)
+              (%setf-macptr m (pref c #+(or apple-objc cocotron-objc) :objc_class.isa
+				      #+gnu-objc :objc_class.class_pointer))
+              (setf (gethash m metaclass-map) meta-id))
+            (note-class-protocols c)))))
+    ;; Second pass: install class objects for user-defined classes,
+    ;; assuming the superclasses are already "revived".  If the
+    ;; superclass is itself user-defined, it'll appear first in the
+    ;; class table; that's an artifact of the current implementation.
+    (dotimes (i nclasses)
+      (let* ((c (id->objc-class i)))
+	(when (and (%null-ptr-p c)
+		   (not (slot-value c 'foreign)))
+	  (let* ((super (dolist (s (class-direct-superclasses c)
+				 (error "No ObjC superclass of ~s" c))
+			  (when (objc-class-p s) (return s))))
+		 (meta-id (objc-class-id->objc-metaclass-id i))
+		 (m (id->objc-metaclass meta-id)))
+            (let* ((class (make-objc-class-pair super (make-cstring (objc-class-id-foreign-name i))))
+                   (meta (pref class #+(or apple-objc cocotron-objc) :objc_class.isa
+                               #+gnu-objc :objc-class.class_pointer)))
+	    (unless (gethash m metaclass-map)
+	      (%revive-macptr m)
+	      (%setf-macptr m meta)
+	      (setf (gethash m metaclass-map) meta-id))
+	    (%setf-macptr c class))
+            #+(or apple-objc-2.0 cocotron-objc)
+            (%revive-foreign-slots c)
+            #+(or apple-objc-2.0 cocotron-objc)
+            (%add-objc-class c)
+            #-(or apple-objc-2.0 cocotron-objc)
+	    (multiple-value-bind (ivars instance-size)
+		(%make-objc-ivars c)
+	      (%add-objc-class c ivars instance-size))
+            (setf (gethash c class-map) i)))))
+    ;; Finally, iterate over all classes in the runtime world.
+    ;; Register any class that's not found in the class map
+    ;; as a "private" ObjC class.
+    ;; Iterate over all classes in the runtime.  Those that
+    ;; aren't already registered will get identified as
+    ;; "private" (undeclared) ObjC classes.
+    ;; Note that this means that if an application bundle
+    ;; was saved on (for instance) Panther and Tiger interfaces
+    ;; were used, and then the application is run on Tiger, any
+    ;; Tiger-specific classes will not be magically integrated
+    ;; into CLOS in the running application.
+    ;; A development envronment might want to provide such a
+    ;; mechanism; it would need access to Panther class
+    ;; declarations, and - in the general case - a standalone
+    ;; application doesn't necessarily have access to the
+    ;; interface database.
+    (map-objc-classes nil)
+    ))
+
+(pushnew #'revive-objc-classes *lisp-system-pointer-functions*
+	 :test #'eq
+	 :key #'function-name)
+    
+
+(defun %objc-class-instance-size (c)
+  #+(or apple-objc-2.0 cocotron-objc)
+  (#_class_getInstanceSize c)
+  #-(or apple-objc-2.0 cocotron-objc)
+  (pref c :objc_class.instance_size))
+
+(defun find-named-objc-superclass (class string)
+  (unless (or (null string) (%null-ptr-p class))
+    (with-macptrs ((name #+(or apple-objc-2.0 cocotron-objc) (#_class_getName class)
+                         #-(or apple-objc-2.0 cocotron-objc) (pref class :objc_class.name)))
+      (or
+       (dotimes (i (length string) class)
+         (let* ((b (%get-unsigned-byte name i)))
+           (unless (eq b (char-code (schar string i)))
+             (return))))
+       (find-named-objc-superclass #+(or apple-objc-2.0 cocotron-objc) (#_class_getSuperclass class)
+                                   #-(or apple-objc-2.0 cocotron-objc) (pref class :objc_class.super_class)
+                                   string)))))
+
+(defun install-foreign-objc-class (class &optional (use-db t))
+  (let* ((id (objc-class-id class)))
+    (unless id
+      (let* ((name (%get-cstring #+(or apple-objc-2.0 cocotron-objc) (#_class_getName class)
+                                 #-(or apple-objc-2.0 cocotron-objc) (pref class :objc_class.name)))
+             (decl (get-objc-class-decl name use-db)))
+        (if (null decl)
+          (or (%get-private-objc-class class)
+              (%register-private-objc-class class name))
+          (progn
+            (setq id (register-objc-class class)
+                  class (id->objc-class id))
+            ;; If not mapped, map the superclass (if there is one.)
+            (let* ((super (find-named-objc-superclass
+                           #+(or apple-objc-2.0 cocotron-objc)
+                           (#_class_getSuperclass class)
+                           #-(or apple-objc-2.0 cocotron-objc)
+                           (pref class :objc_class.super_class)
+                           (db-objc-class-info-superclass-name decl))))
+              (unless (null super)
+                (install-foreign-objc-class super))
+              (let* ((class-name 
+                      (objc-to-lisp-classname
+                       name
+                       "NS"))
+                     (meta-id
+                      (objc-class-id->objc-metaclass-id id)) 
+                     (meta (id->objc-metaclass meta-id)))
+                ;; Metaclass may already be initialized.  It'll have a
+                ;; class wrapper if so.
+                (unless (id->objc-metaclass-wrapper meta-id)
+                  (let* ((meta-foreign-name
+                          (%get-cstring
+                           #+(or apple-objc-2.0 cocotron-objc)
+                           (#_class_getName meta)
+                           #-(or apple-objc-2.0 cocotron-objc)
+                           (pref meta :objc_class.name)))
+                         (meta-name
+                          (intern
+                           (concatenate 'string
+                                        "+"
+                                        (string
+                                         (objc-to-lisp-classname
+                                          meta-foreign-name
+                                          "NS")))
+                           "NS"))
+                         (meta-super
+                          (if super (pref super #+(or apple-objc cocotron-objc) :objc_class.isa
+                                          #+gnu-objc :objc_class.class_pointer))))
+                    ;; It's important (here and when initializing the
+                    ;; class below) to use the "canonical"
+                    ;; (registered) version of the class, since some
+                    ;; things in CLOS assume EQness.  We probably
+                    ;; don't want to violate that assumption; it'll be
+                    ;; easier to revive a saved image if we don't have
+                    ;; a lot of EQL-but-not-EQ class pointers to deal
+                    ;; with.
+                    (initialize-instance
+                     meta
+                     :name meta-name
+                     :direct-superclasses
+                     (list
+                      (if (or (null meta-super)
+                              (not (%objc-metaclass-p meta-super)))
+                        (find-class 'objc:objc-class)
+                        (canonicalize-registered-metaclass meta-super)))
+                     :peer class
+                     :foreign t)
+                    (setf (objc-metaclass-id-foreign-name meta-id)
+                          meta-foreign-name)
+                    (setf (find-class meta-name) meta)
+                    (%defglobal meta-name meta)))
+                (setf (slot-value class 'direct-slots)
+                      (compute-objc-direct-slots-from-info decl class))
+                (initialize-instance
+                 class
+                 :name class-name
+                 :direct-superclasses
+                 (list
+                  (if (null super)
+                    (find-class 'objc:objc-object)
+                    (canonicalize-registered-class super)))
+                 :peer meta
+                 :foreign t)
+                (setf (objc-class-id-foreign-name id)
+                      name)
+                (setf (find-class class-name) class)
+                (%defglobal class-name class)
+                class))))))))
+				
+
+
+;;; Execute the body with the variable NSSTR bound to a
+;;; stack-allocated NSConstantString instance (made from
+;;; *NSConstantString-class*, CSTRING and LEN).
+(defmacro with-nsstr ((nsstr cstring len) &body body)
+  #+apple-objc
+  `(rlet ((,nsstr :<NSC>onstant<S>tring
+	   :isa *NSConstantString-class*
+	   :bytes ,cstring
+	   :num<B>ytes ,len))
+      ,@body)
+  #+cocotron-objc
+    `(rlet ((,nsstr :<NSC>onstant<S>tring
+	   :isa *NSConstantString-class*
+	   :_bytes ,cstring
+	   :_length ,len))
+      ,@body)
+  #+gnu-objc
+  `(rlet ((,nsstr :<NXC>onstant<S>tring
+	   :isa *NSConstantString-class*
+	   :c_string ,cstring
+	   :len ,len))
+    ,@body))
+
+;;; Make a persistent (heap-allocated) NSConstantString.
+
+(defun %make-constant-nsstring (string)
+  "Make a persistent (heap-allocated) NSConstantString from the
+argument lisp string."
+  #+apple-objc
+  (make-record :<NSC>onstant<S>tring
+	       :isa *NSConstantString-Class*
+	       :bytes (make-cstring string)
+	       :num<B>ytes (length string))
+  #+cocotron-objc
+    (make-record :<NSC>onstant<S>tring
+	       :isa *NSConstantString-Class*
+	       :_bytes (make-cstring string)
+	       :_length (length string))
+  #+gnu-objc
+  (make-record :<NXC>onstant<S>tring
+	       :isa *NSConstantString-Class*
+	       :c_string (make-cstring string)
+	       :len (length string))
+  )
+
+;;; Class declarations
+(defparameter *objc-class-declarations* (make-hash-table :test #'equal))
+
+(defun register-objc-class-decls ()
+  (do-interface-dirs (d)
+    (dolist (class-name (cdb-enumerate-keys (db-objc-classes d)))
+      (get-objc-class-decl class-name t))))
+
+
+(defun get-objc-class-decl (class-name &optional (use-db nil))
+  (or (gethash class-name *objc-class-declarations*)
+      (and use-db
+           (let* ((decl (%find-objc-class-info class-name)))
+             (when decl
+               (setf (gethash class-name *objc-class-declarations*) decl))))))
+
+(defun %ensure-class-declaration (name super-name)
+  (unless (get-objc-class-decl name)
+    (setf (gethash name *objc-class-declarations*)
+          (make-db-objc-class-info :class-name (string name)
+                                   :superclass-name (string super-name))))
+  name)
+
+;;; It's hard (and questionable) to allow ivars here.
+(defmacro declare-objc-class (name super-name)
+  `(%ensure-class-declaration ',name ',super-name))
+
+;;; Intern NSConstantString instances.
+(defvar *objc-constant-strings* (make-hash-table :test #'equal))
+
+(defstruct objc-constant-string
+  string
+  nsstringptr)
+
+(defun ns-constant-string (string)
+  (or (gethash string *objc-constant-strings*)
+      (setf (gethash string *objc-constant-strings*)
+	    (make-objc-constant-string :string string
+				       :nsstringptr (%make-constant-nsstring string)))))
+
+(def-ccl-pointers objc-strings ()
+  (maphash #'(lambda (string cached)
+	       (setf (objc-constant-string-nsstringptr cached)
+		     (%make-constant-nsstring string)))
+	   *objc-constant-strings*))
+
+(defmethod make-load-form ((s objc-constant-string) &optional env)
+  (declare (ignore env))
+  `(ns-constant-string ,(objc-constant-string-string s)))
+
+(defmacro @ (string)
+  `(objc-constant-string-nsstringptr ,(ns-constant-string string)))
+
+#+gnu-objc
+(progn
+  (defcallback lisp-objc-error-handler (:id receiver :int errcode (:* :char) format :address argptr :<BOOL>)
+    (let* ((message (get-c-format-string format argptr)))
+      (error "ObjC runtime error ~d, receiver ~s :~& ~a"
+	     errcode receiver message))
+    #$YES)
+
+  (def-ccl-pointers install-lisp-objc-error-handler ()
+    (#_objc_set_error_handler lisp-objc-error-handler)))
+
+
+
+
+
+
+;;; Registering named objc classes.
+
+
+(defun objc-class-name-string (name)
+  (etypecase name
+    (symbol (lisp-to-objc-classname name))
+    (string name)))
+
+;;; We'd presumably cache this result somewhere, so we'd only do the
+;;; lookup once per session (in general.)
+(defun lookup-objc-class (name &optional error-p)
+  (with-cstrs ((cstr (objc-class-name-string name)))
+    (let* ((p (#+(or apple-objc cocotron-objc) #_objc_lookUpClass
+               #+gnu-objc #_objc_lookup_class
+	       cstr)))
+      (if (%null-ptr-p p)
+	(if error-p
+	  (error "ObjC class ~a not found" name))
+	p))))
+
+(defun %set-pointer-to-objc-class-address (class-name-string ptr)
+  (with-cstrs ((cstr class-name-string))
+    (%setf-macptr ptr
+		  (#+(or apple-objc cocotron-objc) #_objc_lookUpClass
+		   #+gnu-objc #_objc_lookup_class
+		   cstr)))
+  nil)
+   
+		  
+
+(defvar *objc-class-descriptors* (make-hash-table :test #'equal))
+
+
+(defstruct objc-class-descriptor
+  name
+  classptr)
+
+(defun invalidate-objc-class-descriptors ()
+  (maphash #'(lambda (name descriptor)
+	       (declare (ignore name))
+	       (setf (objc-class-descriptor-classptr descriptor) nil))
+	   *objc-class-descriptors*))
+
+(defun %objc-class-classptr (class-descriptor &optional (error-p t))
+  (or (objc-class-descriptor-classptr class-descriptor)
+      (setf (objc-class-descriptor-classptr class-descriptor)
+	    (lookup-objc-class (objc-class-descriptor-name class-descriptor)
+			       error-p))))
+
+(defun load-objc-class-descriptor (name)
+  (let* ((descriptor (or (gethash name *objc-class-descriptors*)
+			 (setf (gethash name *objc-class-descriptors*)
+			       (make-objc-class-descriptor  :name name)))))
+    (%objc-class-classptr descriptor nil)
+    descriptor))
+
+(defmacro objc-class-descriptor (name)
+  `(load-objc-class-descriptor ,name))
+
+(defmethod make-load-form ((o objc-class-descriptor) &optional env)
+  (declare (ignore env))
+  `(load-objc-class-descriptor ,(objc-class-descriptor-name o)))
+
+(defmacro @class (name)
+  (let* ((name (objc-class-name-string name)))
+    `(the (@metaclass ,name) (%objc-class-classptr ,(objc-class-descriptor name)))))
+
+;;; This isn't quite the inverse operation of LOOKUP-OBJC-CLASS: it
+;;; returns a simple C string.  and can be applied to a class or any
+;;; instance (returning the class name.)
+(defun objc-class-name (object)
+  #+(or apple-objc cocotron-objc)
+  (with-macptrs (p)
+    (%setf-macptr p (#_object_getClassName object))
+    (unless (%null-ptr-p p)
+      (%get-cstring p)))
+  #+gnu-objc
+  (unless (%null-ptr-p object)
+    (with-macptrs ((parent (pref object :objc_object.class_pointer)))
+      (unless (%null-ptr-p parent)
+        (if (logtest (pref parent :objc_class.info) #$_CLS_CLASS)
+          (%get-cstring (pref parent :objc_class.name))
+          (%get-cstring (pref object :objc_class.name)))))))
+
+
+;;; Likewise, we want to cache the selectors ("SEL"s) which identify
+;;; method names.  They can vary from session to session, but within
+;;; a session, all methods with a given name (e.g, "init") will be
+;;; represented by the same SEL.
+(defun get-selector-for (method-name &optional error)
+  (with-cstrs ((cmethod-name method-name))
+    (let* ((p (#+(or apple-objc cocotron-objc) #_sel_getUid
+	       #+gnu-objc #_sel_get_uid
+	       cmethod-name)))
+      (if (%null-ptr-p p)
+	(if error
+	  (error "Can't find ObjC selector for ~a" method-name))
+	p))))
+
+(defvar *objc-selectors* (make-hash-table :test #'equal))
+
+(defstruct objc-selector
+  name
+  %sel)
+
+(defun %get-SELECTOR (selector &optional (error-p t))
+  (or (objc-selector-%sel selector)
+      (setf (objc-selector-%sel selector)
+	    (get-selector-for (objc-selector-name selector) error-p))))
+
+(defun clear-objc-selectors ()
+  (maphash #'(lambda (name sel)
+	       (declare (ignore name))
+	       (setf (objc-selector-%sel sel) nil))
+	   *objc-selectors*))
+
+;;; Find or create a SELECTOR; don't bother resolving it.
+(defun ensure-objc-selector (name)
+  (setq name (string name))
+  (or (gethash name *objc-selectors*)
+      (setf (gethash name *objc-selectors*)
+            (make-objc-selector :name name))))
+
+(defun load-objc-selector (name)
+  (let* ((selector (ensure-objc-selector name)))
+    (%get-SELECTOR selector nil)
+    selector))
+
+(defmacro @SELECTOR (name)
+  `(%get-selector ,(load-objc-selector name)))
+
+(defmethod make-load-form ((s objc-selector) &optional env)
+  (declare (ignore env))
+  `(load-objc-selector ,(objc-selector-name s)))
+
+
+;;; Convert a Lisp object X to a desired foreign type FTYPE 
+;;; The following conversions are currently done:
+;;;   - T/NIL => #$YES/#$NO
+;;;   - NIL => (%null-ptr)
+;;;   - Lisp numbers  => SINGLE-FLOAT when possible
+
+(defun coerce-to-bool (x)
+  (let ((x-temp (gensym)))
+    `(let ((,x-temp ,x))
+       (if (or (eq ,x-temp 0) (null ,x-temp))
+         #.#$NO
+         #.#$YES))))
+
+(declaim (inline %coerce-to-bool))
+(defun %coerce-to-bool (x)
+  (if (and x (not (eql x 0)))
+    #$YES
+    #$NO))
+
+(defun coerce-to-address (x)
+  (let ((x-temp (gensym)))
+    `(let ((,x-temp ,x))
+       (cond ((null ,x-temp) +null-ptr+)
+	     (t ,x-temp)))))
+
+;;; This is generally a bad idea; it forces us to
+;;; box intermediate pointer arguments in order
+;;; to typecase on them, and it's not clear to
+;;; me that it offers much in the way of additional
+;;; expressiveness.
+(declaim (inline %coerce-to-address))
+(defun %coerce-to-address (x)
+  (etypecase x
+    (macptr x)
+    (null (%null-ptr))))
+
+(defun coerce-to-foreign-type (x ftype)
+   (cond ((and (constantp x) (constantp ftype))
+          (case ftype
+            (:id (if (null x) `(%null-ptr) (coerce-to-address x)))
+            (:<BOOL> (coerce-to-bool (eval x)))
+            (t x)))
+         ((constantp ftype)
+          (case ftype
+            (:id `(%coerce-to-address ,x))
+            (:<BOOL> `(%coerce-to-bool ,x))
+            (t x)))
+         (t `(case ,(if (atom ftype) ftype)
+               (:id (%coerce-to-address ,x))
+               (:<BOOL> (%coerce-to-bool ,x))
+               (t ,x)))))
+
+(defun objc-arg-coerce (typespec arg)
+  (case typespec
+    (:<BOOL> `(%coerce-to-bool ,arg))
+    (:id `(%coerce-to-address ,arg))
+    (t arg)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;                       Boolean Return Hackery                           ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Convert a foreign object X to T or NIL 
+
+(defun coerce-from-bool (x)
+  (cond
+   ((eq x #$NO) nil)
+   ((eq x #$YES) t)
+   (t (error "Cannot coerce ~S to T or NIL" x))))
+
+(defun objc-result-coerce (type result)
+  (cond ((eq type :<BOOL>)
+         `(coerce-from-bool ,result))
+        (t result)))
+
+;;; Add a faster way to get the message from a SEL by taking advantage of the
+;;; fact that a selector is really just a canonicalized, interned C string
+;;; containing the message.  (This is an admitted modularity violation;
+;;; there's a more portable but slower way to do this if we ever need to.)
+
+
+(defun lisp-string-from-sel (sel)
+  (%get-cstring
+   #+apple-objc sel
+   #+cocotron-objc (#_sel_getName sel)
+   #+gnu-objc (#_sel_get_name sel)))
+
+;;; #_objc_msgSend takes two required arguments (the receiving object
+;;; and the method selector) and 0 or more additional arguments;
+;;; there'd have to be some macrology to handle common cases, since we
+;;; want the compiler to see all of the args in a foreign call.
+
+;;; I don't remmber what the second half of the above comment might
+;;; have been talking about.
+
+(defmacro objc-message-send (receiver selector-name &rest argspecs)
+  (when (evenp (length argspecs))
+    (setq argspecs (append argspecs '(:id))))
+  #+(or apple-objc cocotron-objc)
+  (funcall (ftd-ff-call-expand-function *target-ftd*)
+           `(%ff-call (%reference-external-entry-point (load-time-value (external "objc_msgSend"))))
+           `(:address ,receiver :<SEL> (@selector ,selector-name) ,@argspecs)
+           :arg-coerce 'objc-arg-coerce
+           :result-coerce 'objc-result-coerce)  
+  #+gnu-objc
+    (let* ((r (gensym))
+	 (s (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,r ,receiver)
+		    (,s (@selector ,selector-name))
+		    (,imp (external-call "objc_msg_lookup"
+					:id ,r
+					:<SEL> ,s
+					:<IMP>)))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+       `(%ff-call ,imp)
+       `(:address ,receiver :<SEL> (@selector ,selector-name) ,@argspecs)
+       :arg-coerce 'objc-arg-coerce
+       :result-coerce 'objc-result-coerce))))
+
+(defmacro objc-message-send-with-selector (receiver selector &rest argspecs)
+  (when (evenp (length argspecs))
+    (setq argspecs (append argspecs '(:id))))
+  #+(or apple-objc cocotron-objc)
+  (funcall (ftd-ff-call-expand-function *target-ftd*)
+           `(%ff-call (%reference-external-entry-point (load-time-value (external "objc_msgSend"))))
+           `(:address ,receiver :<SEL> (%get-selector ,selector) ,@argspecs)
+           :arg-coerce 'objc-arg-coerce
+           :result-coerce 'objc-result-coerce)  
+  #+gnu-objc
+    (let* ((r (gensym))
+	 (s (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,r ,receiver)
+		    (,s (%get-selector ,selector))
+		    (,imp (external-call "objc_msg_lookup"
+					:id ,r
+					:<SEL> ,s
+					:<IMP>)))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+       `(%ff-call ,imp)
+       `(:address ,receiver :<SEL> ,s ,@argspecs)
+       :arg-coerce 'objc-arg-coerce
+       :result-coerce 'objc-result-coerce))))
+
+;;; A method that returns a structure does so by platform-dependent
+;;; means.  One of those means (which is fairly common) is to pass a
+;;; pointer to an instance of a structure type as a first argument to
+;;; the method implementation function (thereby making SELF the second
+;;; argument, etc.), but whether or not it's actually done that way
+;;; depends on the platform and on the structure type.  The special
+;;; variable CCL::*TARGET-FTD* holds a structure (of type
+;;; CCL::FOREIGN-TYPE-DATA) which describes some static attributes of
+;;; the foreign type system on the target platform and contains some
+;;; functions which can determine dynamic ABI attributes.  One such
+;;; function can be used to determine whether or not the "invisible
+;;; first arg" convention is used to return structures of a given
+;;; foreign type; another function in *TARGET-FTD* can be used to
+;;; construct a foreign function call form that handles
+;;; structure-return and structure-types-as-arguments details.  In the
+;;; Apple ObjC runtime, #_objc_msgSend_stret must be used if the
+;;; invisible-first-argument convention is used to return a structure
+;;; and must NOT be used otherwise. (The Darwin ppc64 and all
+;;; supported x86-64 ABIs often use more complicated structure return
+;;; conventions than ppc32 Darwin or ppc Linux.)  We should use
+;;; OBJC-MESSAGE-SEND-STRET to send any message that returns a
+;;; structure or union, regardless of how that structure return is
+;;; actually implemented.
+
+(defmacro objc-message-send-stret (structptr receiver selector-name &rest argspecs)
+    #+(or apple-objc cocotron-objc)
+    (let* ((return-typespec (car (last argspecs)))
+           (entry-name (if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function *target-ftd*) return-typespec)
+                         "objc_msgSend_stret"
+                         "objc_msgSend")))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+               `(%ff-call (%reference-external-entry-point (load-time-value (external ,entry-name))))
+        `(,structptr :address ,receiver :<SEL> (@selector ,selector-name) ,@argspecs)
+               :arg-coerce 'objc-arg-coerce
+               :result-coerce 'objc-result-coerce))
+    #+gnu-objc
+    (let* ((r (gensym))
+	 (s (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,r ,receiver)
+		    (,s (@selector ,selector-name))
+		    (,imp (external-call "objc_msg_lookup"
+					 :id ,r
+					 :<SEL> ,s
+					 :<IMP>)))
+      ,      (funcall (ftd-ff-call-expand-function *target-ftd*)
+               `(%ff-call ,imp)
+              `(,structptr :address ,receiver :<SEL> ,s ,@argspecs)
+               :arg-coerce 'objc-arg-coerce
+               :result-coerce 'objc-result-coerce))))
+
+(defmacro objc-message-send-stret-with-selector (structptr receiver selector &rest argspecs)
+    #+(or apple-objc cocotron-objc)
+    (let* ((return-typespec (car (last argspecs)))
+           (entry-name (if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function *target-ftd*) return-typespec)
+                         "objc_msgSend_stret"
+                         "objc_msgSend")))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+               `(%ff-call (%reference-external-entry-point (load-time-value (external ,entry-name))))
+        `(,structptr :address ,receiver :<SEL> (%get-selector ,selector) ,@argspecs)
+               :arg-coerce 'objc-arg-coerce
+               :result-coerce 'objc-result-coerce))
+    #+gnu-objc
+    (let* ((r (gensym))
+	 (s (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,r ,receiver)
+		    (,s (%get-selector ,selector))
+		    (,imp (external-call "objc_msg_lookup"
+					 :id ,r
+					 :<SEL> ,s
+					 :<IMP>)))
+      ,      (funcall (ftd-ff-call-expand-function *target-ftd*)
+               `(%ff-call ,imp)
+              `(,structptr :address ,receiver :<SEL> ,s ,@argspecs)
+               :arg-coerce 'objc-arg-coerce
+               :result-coerce 'objc-result-coerce))))
+
+;;; #_objc_msgSendSuper is similar to #_objc_msgSend; its first argument
+;;; is a pointer to a structure of type objc_super {self,  the defining
+;;; class's superclass}.  It only makes sense to use this inside an
+;;; objc method.
+(defmacro objc-message-send-super (super selector-name &rest argspecs)
+  (when (evenp (length argspecs))
+    (setq argspecs (append argspecs '(:id))))
+  #+(or apple-objc cocotron-objc)
+  (funcall (ftd-ff-call-expand-function *target-ftd*)
+           `(%ff-call (%reference-external-entry-point (load-time-value (external "objc_msgSendSuper"))))
+           `(:address ,super :<SEL> (@selector ,selector-name) ,@argspecs)
+           :arg-coerce 'objc-arg-coerce
+           :result-coerce 'objc-result-coerce)
+  #+gnu-objc
+  (let* ((sup (gensym))
+	 (sel (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,sup ,super)
+		    (,sel (@selector ,selector-name))
+		    (,imp (external-call "objc_msg_lookup_super"
+					 :<S>uper_t ,sup
+					 :<SEL> ,sel
+					 :<IMP>)))
+  (funcall (ftd-ff-call-expand-function *target-ftd*)
+   `(%ff-call ,imp)
+   `(:id (pref ,sup :<S>uper.self)
+     :<SEL> ,sel
+     ,@argspecs)))))
+
+(defmacro objc-message-send-super-with-selector (super selector &rest argspecs)
+  (when (evenp (length argspecs))
+    (setq argspecs (append argspecs '(:id))))
+  #+(or apple-objc cocotron-objc)
+  (funcall (ftd-ff-call-expand-function *target-ftd*)
+           `(%ff-call (%reference-external-entry-point (load-time-value (external "objc_msgSendSuper"))))
+           `(:address ,super :<SEL> ,selector ,@argspecs)
+           :arg-coerce 'objc-arg-coerce
+           :result-coerce 'objc-result-coerce)
+  #+gnu-objc
+  (let* ((sup (gensym))
+	 (sel (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,sup ,super)
+		    (,sel ,selector)
+		    (,imp (external-call "objc_msg_lookup_super"
+					 :<S>uper_t ,sup
+					 :<SEL> ,sel
+					 :<IMP>)))
+  (funcall (ftd-ff-call-expand-function *target-ftd*)
+   `(%ff-call ,imp)
+   `(:id (pref ,sup :<S>uper.self)
+     :<SEL> ,sel
+     ,@argspecs)))))
+
+;;; Send to superclass method, returning a structure. See above.
+(defmacro objc-message-send-super-stret
+    (structptr super selector-name &rest argspecs)
+  #+(or apple-objc cocotron-objc)
+    (let* ((return-typespec (car (last argspecs)))
+           (entry-name (if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function *target-ftd*) return-typespec)
+                         "objc_msgSendSuper_stret"
+                         "objc_msgSendSuper")))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+               `(%ff-call (%reference-external-entry-point (load-time-value (external ,entry-name))))
+               `(,structptr :address ,super :<SEL> (@selector ,selector-name) ,@argspecs)
+               :arg-coerce 'objc-arg-coerce
+               :result-coerce 'objc-result-coerce))
+  #+gnu-objc
+  (let* ((sup (gensym))
+	 (sel (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,sup ,super)
+		    (,sel (@selector ,selector-name))
+		    (,imp (external-call "objc_msg_lookup_super"
+					 :<S>uper_t ,sup
+					 :<SEL> ,sel
+					 :<IMP>)))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+       `(%ff-call ,imp)
+       ,structptr
+       :id (pref ,sup :<S>uper.self)
+       :<SEL> ,sel
+       ,@argspecs))))
+
+(defmacro objc-message-send-super-stret-with-selector
+    (structptr super selector &rest argspecs)
+  #+(or apple-objc cocotron-objc)
+    (let* ((return-typespec (car (last argspecs)))
+           (entry-name (if (funcall (ftd-ff-call-struct-return-by-implicit-arg-function *target-ftd*) return-typespec)
+                         "objc_msgSendSuper_stret"
+                         "objc_msgSendSuper")))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+               `(%ff-call (%reference-external-entry-point (load-time-value (external ,entry-name))))
+               `(,structptr :address ,super :<SEL> ,selector ,@argspecs)
+               :arg-coerce 'objc-arg-coerce
+               :result-coerce 'objc-result-coerce))
+  #+gnu-objc
+  (let* ((sup (gensym))
+	 (sel (gensym))
+	 (imp (gensym)))
+    `(with-macptrs ((,sup ,super)
+		    (,sel ,selector)
+		    (,imp (external-call "objc_msg_lookup_super"
+					 :<S>uper_t ,sup
+					 :<SEL> ,sel
+					 :<IMP>)))
+      (funcall (ftd-ff-call-expand-function *target-ftd*)
+       `(%ff-call ,imp)
+       ,structptr
+       :id (pref ,sup :<S>uper.self)
+       :<SEL> ,sel
+       ,@argspecs))))
+
+(defun message-send-form-for-call (receiver selector args super-p struct-return-var)
+  (if struct-return-var
+    (if super-p
+      `(objc-message-send-super-stret-with-selector ,struct-return-var ,receiver ,selector ,@args)
+      `(objc-message-send-stret-with-selector ,struct-return-var ,receiver ,selector ,@args))
+    (if super-p
+      `(objc-message-send-super-with-selector ,receiver ,selector ,@args)
+      `(objc-message-send-with-selector ,receiver ,selector ,@args))))
+
+
+#+(and apple-objc x8664-target)
+(defun %process-varargs-list (gpr-pointer fpr-pointer stack-pointer ngprs nfprs nstackargs arglist)
+  (dolist (arg-temp arglist)
+    (typecase arg-temp
+      ((signed-byte 64)
+       (if (< ngprs 6)
+         (progn
+           (setf (paref gpr-pointer (:* (:signed 64)) ngprs) arg-temp)
+           (incf ngprs))
+         (progn
+           (setf (paref stack-pointer (:* (:signed 64)) nstackargs) arg-temp)
+           (incf nstackargs))))
+      ((unsigned-byte 64)
+       (if (< ngprs 6)
+         (progn
+           (setf (paref gpr-pointer (:* (:unsigned 64)) ngprs) arg-temp)
+           (incf ngprs))
+         (progn
+           (setf (paref stack-pointer (:* (:unsigned 64)) nstackargs) arg-temp)
+           (incf nstackargs))))
+      (macptr
+       (if (< ngprs 6)
+         (progn
+           (setf (paref gpr-pointer (:* :address) ngprs) arg-temp)
+           (incf ngprs))
+         (progn
+           (setf (paref stack-pointer (:* :address) nstackargs) arg-temp)
+           (incf nstackargs))))
+      (single-float
+       (if (< nfprs 8)
+         (progn
+           (setf (%get-single-float fpr-pointer (* nfprs 16))
+                 arg-temp)
+           (incf nfprs))
+         (progn
+           (setf (paref stack-pointer (:* :float) (* 2 nstackargs)) arg-temp)
+           (incf nstackargs))))
+      (double-float
+       (if (< nfprs 8)
+         (progn
+           (setf (%get-double-float fpr-pointer (* nfprs 16))
+                 arg-temp)
+           (incf nfprs))
+         (progn
+           (setf (paref stack-pointer (:* :double) nstackargs)
+                 arg-temp)
+           (incf nstackargs)))))))
+
+#+x8632-target
+(defun %process-varargs-list (ptr index arglist)
+  (dolist (arg-temp arglist)
+    (typecase arg-temp
+      ((signed-byte 32)
+       (setf (paref ptr (:* (:signed 32)) index) arg-temp)
+       (incf index))
+      ((unsigned-byte 32)
+       (setf (paref ptr (:* (:unsigned 32)) index) arg-temp)
+       (incf index))
+      (macptr
+       (setf (paref ptr (:* :address) index) arg-temp)
+       (incf index))
+      (single-float
+       (setf (%get-single-float ptr (* 4 index)) arg-temp)
+       (incf index))
+      (double-float
+       (setf (%get-double-float ptr (* 4 index)) arg-temp)
+       (incf index 2))
+      ((or (signed-byte 64)
+	   (unsigned-byte 64))
+       (setf (paref ptr (:* :unsigned) index) (ldb (byte 32 0) arg-temp))
+       (incf index)
+       (setf (paref ptr (:* :unsigned) index) (ldb (byte 32 32) arg-temp))
+       (incf index)))))
+
+#+(and apple-objc ppc32-target)
+(defun %process-varargs-list (gpr-pointer fpr-pointer ngprs nfprs arglist)
+  (dolist (arg-temp arglist)
+    (typecase arg-temp
+      ((signed-byte 32)
+       (setf (paref gpr-pointer (:* (:signed 32)) ngprs) arg-temp)
+       (incf ngprs))
+      ((unsigned-byte 32)
+       (setf (paref gpr-pointer (:* (:unsigned 32)) ngprs) arg-temp)
+       (incf ngprs))
+      (macptr
+       (setf (paref gpr-pointer (:* :address) ngprs) arg-temp)
+       (incf ngprs))
+      (single-float
+       (when (< nfprs 13)
+         (setf (paref fpr-pointer (:* :double-float) nfprs) (float arg-temp 0.0d0))
+         (incf nfprs))
+       (setf (paref gpr-pointer (:* :single-float) ngprs) arg-temp)
+       (incf ngprs))
+      (double-float
+       (when (< nfprs 13)
+         (setf (paref fpr-pointer (:* :double-float) nfprs) arg-temp)
+         (incf nfprs))
+       (multiple-value-bind (high low) (double-float-bits arg-temp)
+         (setf (paref gpr-pointer (:* :unsigned) ngprs) high)
+         (incf ngprs)
+         (setf (paref gpr-pointer (:* :unsigned) ngprs) low)
+         (incf nfprs)))
+      ((or (signed-byte 64)
+           (unsigned-byte 64))
+       (setf (paref gpr-pointer (:* :unsigned) ngprs) (ldb (byte 32 32) arg-temp))
+       (incf ngprs)
+       (setf (paref gpr-pointer (:* :unsigned) ngprs) (ldb (byte 32 0) arg-temp))
+       (incf ngprs)))))
+
+#+(and apple-objc ppc64-target)
+(defun %process-varargs-list (gpr-pointer fpr-pointer ngprs nfprs arglist)
+  (dolist (arg-temp arglist (min nfprs 13))
+    (typecase arg-temp
+      ((signed-byte 64)
+       (setf (paref gpr-pointer (:* (:signed 64)) ngprs) arg-temp)
+       (incf ngprs))
+      ((unsigned-byte 64)
+       (setf (paref gpr-pointer (:* (:unsigned 64)) ngprs) arg-temp)
+       (incf ngprs))
+      (macptr
+       (setf (paref gpr-pointer (:* :address) ngprs) arg-temp)
+       (incf ngprs))
+      (single-float
+       (when (< nfprs 13)
+         (setf (paref fpr-pointer (:* :double-float) nfprs) (float arg-temp 0.0d0))
+         (incf nfprs))
+       (setf (paref gpr-pointer (:* (:unsigned 64)) ngprs) (single-float-bits arg-temp))
+       (incf ngprs))
+      (double-float
+       (when (< nfprs 13)
+         (setf (paref fpr-pointer (:* :double-float) nfprs) arg-temp)
+         (incf nfprs))
+       (setf (paref gpr-pointer (:* :double-float) ngprs) arg-temp)
+       (incf ngprs)))))
+
+                          
+#+apple-objc
+(eval-when (:compile-toplevel :execute)
+  #+(and ppc-target (not apple-objc-2.0))
+  (def-foreign-type :<MARG>
+      (:struct nil
+               (:fp<P>arams (:array :double 13))
+               (:linkage (:array :uintptr_t 6))
+               (:reg<P>arams (:array :uintptr_t 8))
+               (:stack<P>arams (:array :uintptr_t) 0)))
+  )
+
+  
+#+(and apple-objc-2.0 x8664-target)
+(defun %compile-varargs-send-function-for-signature (sig)
+  (let* ((return-type-spec (foreign-type-to-representation-type (car sig)))
+         (op (case return-type-spec
+               (:address '%get-ptr)
+               (:unsigned-byte '%get-unsigned-byte)
+               (:signed-byte '%get-signed-byte)
+               (:unsigned-halfword '%get-unsigned-word)
+               (:signed-halfword '%get-signed-word)
+               (:unsigned-fullword '%get-unsigned-long)
+               (:signed-fullword '%get-signed-long)
+               (:unsigned-doubleword '%get-natural)
+               (:signed-doubleword '%get-signed-natural)
+               (:single-float '%get-single-float)
+               (:double-float '%get-double-float)))
+         (result-offset
+          (case op
+            ((:single-float :double-float) 0)
+            (t -8)))
+         (arg-type-specs (butlast (cdr sig)))
+         (args (objc-gen-message-arglist (length arg-type-specs)))
+         (receiver (gensym))
+         (selector (gensym))
+         (rest-arg (gensym))
+         (arg-temp (gensym))
+         (regparams (gensym))
+         (stackparams (gensym))
+         (fpparams (gensym))
+         (cframe (gensym))
+         (selptr (gensym))
+         (gpr-total (gensym))
+         (fpr-total (gensym))
+         (stack-total (gensym))
+         (n-static-gprs 2)              ;receiver, selptr
+         (n-static-fprs 0)
+         (n-static-stack-args 0))
+    (collect ((static-arg-forms))
+      (static-arg-forms `(setf (paref ,regparams (:* address) 0) ,receiver))
+      (static-arg-forms `(setf (paref ,regparams (:* address) 1) ,selptr))
+      (do* ((args args (cdr args))
+            (arg-type-specs arg-type-specs (cdr arg-type-specs)))
+           ((null args))
+        (let* ((arg (car args))
+               (spec (car arg-type-specs))
+               (static-arg-type (parse-foreign-type spec))
+               (gpr-base (if (< n-static-gprs 6) regparams stackparams))
+               (fpr-base (if (< n-static-fprs 8) fpparams stackparams))
+               (gpr-offset (if (< n-static-gprs 6) n-static-gprs n-static-stack-args))
+               (fpr-offset (if (< n-static-fprs 8)
+                             (* 8 n-static-fprs)
+                             (* 8 n-static-stack-args))))
+          (etypecase static-arg-type
+            (foreign-integer-type
+             (if (eq spec :<BOOL>)
+               (setq arg `(%coerce-to-bool ,arg)))
+             (static-arg-forms
+              `(setf (paref ,gpr-base (:* (
+                                           ,(if (foreign-integer-type-signed static-arg-type)
+                                                :signed
+                                                :unsigned)
+                                           ,(foreign-integer-type-bits static-arg-type))) ,gpr-offset)
+                ,arg))
+             (if (< n-static-gprs 6)
+               (incf n-static-gprs)
+               (incf n-static-stack-args)))
+            (foreign-single-float-type
+             (static-arg-forms
+              `(setf (%get-single-float ,fpr-base ,fpr-offset) ,arg))
+             (if (< n-static-fprs 8)
+               (incf n-static-fprs)
+               (incf n-static-stack-args)))
+            (foreign-double-float-type
+             (static-arg-forms
+              `(setf (%get-double-float ,fpr-base ,fpr-offset) ,arg))
+             (if (< n-static-fprs 8)
+               (incf n-static-fprs)
+               (incf n-static-stack-args)))
+            (foreign-pointer-type
+             (static-arg-forms
+              `(setf (paref ,gpr-base (:* address) ,gpr-offset) ,arg))
+             (if (< n-static-gprs 6)
+               (incf n-static-gprs)
+               (incf n-static-stack-args))))))
+      (compile
+       nil
+       `(lambda (,receiver ,selector ,@args &rest ,rest-arg)
+         (declare (dynamic-extent ,rest-arg))
+         (let* ((,selptr (%get-selector ,selector))
+                (,gpr-total ,n-static-gprs)
+                (,fpr-total ,n-static-fprs)
+                (,stack-total ,n-static-stack-args))
+           (dolist (,arg-temp ,rest-arg)
+             (if (or (typep ,arg-temp 'double-float)
+                     (typep ,arg-temp 'single-float))
+               (if (< ,fpr-total 8)
+                 (incf ,fpr-total)
+                 (incf ,stack-total))
+               (if (< ,gpr-total 6)
+                 (incf ,gpr-total)
+                 (incf ,stack-total))))
+           (%stack-block ((,fpparams (* 8 8)))
+             (with-macptrs (,regparams ,stackparams)
+               (with-variable-c-frame
+                   (+ 8 ,stack-total) ,cframe
+                   (%setf-macptr-to-object ,regparams (+ ,cframe 2))
+                   (%setf-macptr-to-object ,stackparams (+ ,cframe 8))
+                   (progn ,@(static-arg-forms))
+                   (%process-varargs-list ,regparams ,fpparams ,stackparams ,n-static-gprs ,n-static-fprs ,n-static-stack-args ,rest-arg)
+                   (%do-ff-call ,fpr-total ,cframe ,fpparams (%reference-external-entry-point (load-time-value (external "objc_msgSend"))))
+                   ,@(if op
+                         `((,op ,regparams ,result-offset))
+                         `(())))))))))))
+
+
+#+(and apple-objc ppc32-target)
+(defun %compile-varargs-send-function-for-signature (sig)
+  (let* ((return-type-spec (car sig))
+         (arg-type-specs (butlast (cdr sig)))
+         (args (objc-gen-message-arglist (length arg-type-specs)))
+         (receiver (gensym))
+         (selector (gensym))
+         (rest-arg (gensym))
+         (arg-temp (gensym))
+         (marg-ptr (gensym))
+         (regparams (gensym))
+         (selptr (gensym))
+         (gpr-total (gensym))
+         (n-static-gprs 2)              ;receiver, selptr
+         (n-static-fprs 0))
+    (collect ((static-arg-forms))
+      (static-arg-forms `(setf (paref ,regparams (:* address) 0) ,receiver))
+      (static-arg-forms `(setf (paref ,regparams (:* address) 1) ,selptr))
+      (do* ((args args (cdr args))
+            (arg-type-specs arg-type-specs (cdr arg-type-specs)))
+           ((null args))
+        (let* ((arg (car args))
+               (spec (car arg-type-specs))
+               (static-arg-type (parse-foreign-type spec))
+               (gpr-base regparams)
+               (fpr-base marg-ptr)
+               (gpr-offset (* n-static-gprs 4)))
+          (etypecase static-arg-type
+            (foreign-integer-type
+             (let* ((bits (foreign-type-bits static-arg-type))
+                    (signed (foreign-integer-type-signed static-arg-type)))
+               (if (> bits 32)
+                 (progn
+                   (static-arg-forms
+                    `(setf (,(if signed '%%get-signed-longlong '%%get-unsigned-long-long)
+                            ,gpr-base ,gpr-offset)
+                      ,arg))
+                   (incf n-static-gprs 2))
+                 (progn
+                   (if (eq spec :<BOOL>)
+                     (setq arg `(%coerce-to-bool ,arg)))
+                   (static-arg-forms
+                    `(setf (paref ,gpr-base (:* (
+                                                 ,(if (foreign-integer-type-signed static-arg-type)
+                                                      :signed
+                                                      :unsigned)
+                                           32)) ,gpr-offset)
+                ,arg))
+                   (incf n-static-gprs)))))
+            (foreign-single-float-type
+             (static-arg-forms
+              `(setf (paref ,gpr-base (:* :single-float) ,n-static-gprs) ,arg))
+             (when (< n-static-fprs 13)
+               (static-arg-forms
+                `(setf (paref ,fpr-base (:* :double-float) ,n-static-fprs)
+                  (float (paref ,gpr-base (:* :single-float) ,n-static-gprs) 0.0d0)))
+               (incf n-static-fprs))
+             (incf n-static-gprs))
+            (foreign-double-float-type
+             (static-arg-forms
+              `(setf (%get-double-float ,gpr-base ,gpr-offset) ,arg))
+             (when (< n-static-fprs 13)
+               (static-arg-forms
+                `(setf (paref ,fpr-base (:* :double-float) ,n-static-fprs)
+                  (%get-double-float ,gpr-base ,gpr-offset)))
+               (incf n-static-fprs))
+             (incf n-static-gprs 2))
+            (foreign-pointer-type
+             (static-arg-forms
+              `(setf (paref ,gpr-base (:* address) ,n-static-gprs) ,arg))
+               (incf n-static-gprs)))))
+      (compile
+       nil
+       `(lambda (,receiver ,selector ,@args &rest ,rest-arg)
+         (declare (dynamic-extent ,rest-arg))
+         (let* ((,selptr (%get-selector ,selector))
+                (,gpr-total ,n-static-gprs))
+           (dolist (,arg-temp ,rest-arg)
+             (if (or (typep ,arg-temp 'double-float)
+                     (and (typep ,arg-temp 'integer)
+                          (if (< ,arg-temp 0)
+                            (>= (integer-length ,arg-temp) 32)
+                            (> (integer-length ,arg-temp) 32))))
+               (incf ,gpr-total 2)
+               (incf ,gpr-total 1)))
+           (if (> ,gpr-total 8)
+             (setq ,gpr-total (- ,gpr-total 8))
+             (setq ,gpr-total 0))           
+           (%stack-block ((,marg-ptr (+ ,(%foreign-type-or-record-size
+                                          :<MARG> :bytes)
+                                        (* 4 ,gpr-total))))
+             
+             (with-macptrs ((,regparams (pref ,marg-ptr :<MARG>.reg<P>arams)))
+               (progn ,@(static-arg-forms))
+               (%process-varargs-list ,regparams ,marg-ptr ,n-static-gprs ,n-static-fprs  ,rest-arg)
+               (external-call "objc_msgSendv"
+                              :address ,receiver
+                              :address ,selptr
+                              :size_t (+ 32 (* 4 ,gpr-total))
+                              :address ,marg-ptr
+                              ,return-type-spec)))))))))
+
+#+(and (or apple-objc cocotron-objc) x8632-target)
+(defun %compile-varargs-send-function-for-signature (sig)
+  (let* ((return-type-spec (car sig))
+         (arg-type-specs (butlast (cdr sig)))
+         (args (objc-gen-message-arglist (length arg-type-specs)))
+         (receiver (gensym))
+         (selector (gensym))
+         (rest-arg (gensym))
+         (arg-temp (gensym))
+         (marg-ptr (gensym))
+	 (static-arg-words 2)		;receiver, selptr
+	 (marg-words (gensym))
+	 (marg-size (gensym))
+         (selptr (gensym)))
+    (collect ((static-arg-forms))
+      (static-arg-forms `(setf (paref ,marg-ptr (:* address) 0) ,receiver))
+      (static-arg-forms `(setf (paref ,marg-ptr (:* address) 1) ,selptr))
+      (do* ((args args (cdr args))
+            (arg-type-specs arg-type-specs (cdr arg-type-specs)))
+           ((null args))
+        (let* ((arg (car args))
+               (spec (car arg-type-specs))
+               (static-arg-type (parse-foreign-type spec)))
+          (etypecase static-arg-type
+            (foreign-integer-type
+             (let* ((bits (foreign-type-bits static-arg-type))
+                    (signed (foreign-integer-type-signed static-arg-type)))
+               (if (> bits 32)
+                 (progn
+                   (static-arg-forms
+                    `(setf (,(if signed '%%get-signed-longlong '%%get-unsigned-long-long)
+			     ,marg-ptr (* 4 ,static-arg-words))
+			   ,arg))
+                   (incf static-arg-words 2))
+                 (progn
+                   (if (eq spec :<BOOL>)
+                     (setq arg `(%coerce-to-bool ,arg)))
+                   (static-arg-forms
+                    `(setf (paref ,marg-ptr (:* 
+					     (,(if (foreign-integer-type-signed 
+						    static-arg-type)
+						   :signed
+						   :unsigned)
+					       32)) ,static-arg-words)
+			   ,arg))
+                   (incf static-arg-words)))))
+            (foreign-single-float-type
+             (static-arg-forms
+              `(setf (paref ,marg-ptr (:* :single-float) ,static-arg-words) ,arg))
+             (incf static-arg-words))
+            (foreign-double-float-type
+             (static-arg-forms
+              `(setf (%get-double-float ,marg-ptr (* 4 ,static-arg-words)) ,arg))
+             (incf static-arg-words 2))
+            (foreign-pointer-type
+             (static-arg-forms
+              `(setf (paref ,marg-ptr (:* address) ,static-arg-words) ,arg))
+	     (incf static-arg-words)))))
+      (compile
+       nil
+       `(lambda (,receiver ,selector ,@args &rest ,rest-arg)
+	  (declare (dynamic-extent ,rest-arg))
+	  (let* ((,selptr (%get-selector ,selector))
+		 (,marg-words ,static-arg-words)
+		 (,marg-size nil))
+	    (dolist (,arg-temp ,rest-arg)
+	      (if (or (typep ,arg-temp 'double-float)
+		      (and (typep ,arg-temp 'integer)
+			   (if (< ,arg-temp 0)
+			     (>= (integer-length ,arg-temp) 32)
+			     (> (integer-length ,arg-temp) 32))))
+		(incf ,marg-words 2)
+		(incf ,marg-words 1)))
+	    (setq ,marg-size (ash ,marg-words 2))
+	    (%stack-block ((,marg-ptr ,marg-size))
+	      (progn ,@(static-arg-forms))
+	      (%process-varargs-list ,marg-ptr ,static-arg-words ,rest-arg)
+	      (external-call #+apple-objc  "objc_msgSendv"
+                             #+cocotron-objc "objc_msg_sendv"
+			     :id ,receiver
+			     :<SEL> ,selptr
+			     :size_t ,marg-size
+			     :address ,marg-ptr
+			     ,return-type-spec))))))))
+
+#+(and apple-objc-2.0 ppc64-target)
+(defun %compile-varargs-send-function-for-signature (sig)
+  (let* ((return-type-spec (car sig))
+         (arg-type-specs (butlast (cdr sig)))
+         (args (objc-gen-message-arglist (length arg-type-specs)))
+         (receiver (gensym))
+         (selector (gensym))
+         (rest-arg (gensym))
+         (fp-arg-ptr (gensym))
+         (c-frame (gensym))
+         (gen-arg-ptr (gensym))
+         (selptr (gensym))
+         (gpr-total (gensym))
+         (n-static-gprs 2)              ;receiver, selptr
+         (n-static-fprs 0))
+    (collect ((static-arg-forms))
+      (static-arg-forms `(setf (paref ,gen-arg-ptr (:* address) 0) ,receiver))
+      (static-arg-forms `(setf (paref ,gen-arg-ptr (:* address) 1) ,selptr))
+      (do* ((args args (cdr args))
+            (arg-type-specs arg-type-specs (cdr arg-type-specs)))
+           ((null args))
+        (let* ((arg (car args))
+               (spec (car arg-type-specs))
+               (static-arg-type (parse-foreign-type spec))
+               (gpr-base gen-arg-ptr)
+               (fpr-base fp-arg-ptr)
+               (gpr-offset (* n-static-gprs 8)))
+          (etypecase static-arg-type
+            (foreign-integer-type
+             (if (eq spec :<BOOL>)
+               (setq arg `(%coerce-to-bool ,arg)))
+             (static-arg-forms
+              `(setf (paref ,gpr-base (:* (
+                                           ,(if (foreign-integer-type-signed static-arg-type)
+                                                :signed
+                                                :unsigned)
+                                           64)) ,gpr-offset)
+                ,arg))
+             (incf n-static-gprs))
+            (foreign-single-float-type
+             (static-arg-forms
+              `(setf (%get-single-float ,gpr-base ,(+ 4 gpr-offset)) ,arg))
+             (when (< n-static-fprs 13)
+               (static-arg-forms
+                `(setf (paref ,fpr-base (:* :double-float) ,n-static-fprs)
+                  (float (%get-single-float ,gpr-base ,(+ 4 (* 8 n-static-gprs))) 0.0d0)))
+               (incf n-static-fprs))
+             (incf n-static-gprs))
+            (foreign-double-float-type
+             (static-arg-forms
+              `(setf (%get-double-float ,gpr-base ,gpr-offset) ,arg))
+             (when (< n-static-fprs 13)
+               (static-arg-forms
+                `(setf (paref ,fpr-base (:* :double-float) ,n-static-fprs)
+                  (%get-double-float ,gpr-base ,gpr-offset)))
+               (incf n-static-fprs))
+             (incf n-static-gprs 1))
+            (foreign-pointer-type
+             (static-arg-forms
+              `(setf (paref ,gpr-base (:* address) ,n-static-gprs) ,arg))
+             (incf n-static-gprs)))))
+      
+      (compile
+        nil
+        `(lambda (,receiver ,selector ,@args &rest ,rest-arg)
+          (declare (dynamic-extent ,rest-arg))
+          (let* ((,selptr (%get-selector ,selector))
+                 (,gpr-total (+ ,n-static-gprs (length ,rest-arg))))
+            (%stack-block ((,fp-arg-ptr (* 8 13)))
+              (with-variable-c-frame ,gpr-total ,c-frame
+                (with-macptrs ((,gen-arg-ptr))
+                  (%setf-macptr-to-object ,gen-arg-ptr (+ ,c-frame (ash ppc64::c-frame.param0 (- ppc64::word-shift))))
+                  (progn ,@(static-arg-forms))
+                  (%load-fp-arg-regs (%process-varargs-list ,gen-arg-ptr ,fp-arg-ptr ,n-static-gprs ,n-static-fprs  ,rest-arg) ,fp-arg-ptr)
+                  
+                  (%do-ff-call nil (%reference-external-entry-point (load-time-value (external "objc_msgSend"))))
+                  ;; Using VALUES here is a hack: the multiple-value
+                  ;; returning machinery clobbers imm0.
+                  (values (%%ff-result ,(foreign-type-to-representation-type return-type-spec))))))))))))
+
+
+
+
+(defun %compile-send-function-for-signature (sig &optional super-p)
+  (let* ((return-type-spec (car sig))
+         (arg-type-specs (cdr sig)))
+    (if (eq (car (last arg-type-specs)) :void)
+      (%compile-varargs-send-function-for-signature sig)
+      (let* ((args (objc-gen-message-arglist (length arg-type-specs)))
+             (struct-return-var nil)
+             (receiver (gensym))
+             (selector (gensym)))
+        (collect ((call)
+                  (lets))
+          (let* ((result-type (parse-foreign-type return-type-spec)))
+            (when (typep result-type 'foreign-record-type)
+              (setq struct-return-var (gensym))
+              (lets `(,struct-return-var (make-gcable-record ,return-type-spec))))
+
+            (do ((args args (cdr args))
+                 (spec (pop arg-type-specs) (pop arg-type-specs)))
+                ((null args) (call return-type-spec))
+              (let* ((arg (car args)))
+                 (call spec)
+                 (case spec
+                   (:<BOOL> (call `(%coerce-to-bool ,arg)))
+                   (:id (call `(%coerce-to-address ,arg)))
+		   (:<CGF>loat (call `(float ,arg +cgfloat-zero+)))
+                   (t
+                    (call arg)))))
+            (let* ((call (call))
+                   (lets (lets))
+                   (body (message-send-form-for-call receiver selector call super-p struct-return-var)))
+              (if struct-return-var
+                (setq body `(progn ,body ,struct-return-var)))
+              (if lets
+                (setq body `(let* ,lets
+                             ,body)))
+              (compile nil
+                       `(lambda (,receiver ,selector ,@args)
+                         ,body)))))))))
+
+(defun compile-send-function-for-signature (sig)
+  (%compile-send-function-for-signature sig nil))
+                           
+                    
+
+
+;;; The first 8 words of non-fp arguments get passed in R3-R10
+#+ppc-target
+(defvar *objc-gpr-offsets*
+  #+32-bit-target
+  #(4 8 12 16 20 24 28 32)
+  #+64-bit-target
+  #(8 16 24 32 40 48 56 64)
+  )
+
+
+
+;;; The first 13 fp arguments get passed in F1-F13 (and also "consume"
+;;; a GPR or two.)  It's certainly possible for an FP arg and a non-
+;;; FP arg to share the same "offset", and parameter offsets aren't
+;;; strictly increasing.
+#+ppc-target
+(defvar *objc-fpr-offsets*
+  #+32-bit-target
+  #(36 44 52 60  68  76  84  92 100 108 116 124 132)
+  #+64-bit-target
+  #(68 76 84 92 100 108 116 124 132 140 148 156 164))
+
+;;; Just to make things even more confusing: once we've filled in the
+;;; first 8 words of the parameter area, args that aren't passed in
+;;; FP-regs get assigned offsets starting at 32.  That almost makes
+;;; sense (even though it conflicts with the last offset in
+;;; *objc-gpr-offsets* (assigned to R10), but we then have to add
+;;; this constant to the memory offset.
+(defconstant objc-forwarding-stack-offset 8)
+
+(defvar *objc-id-type* (parse-foreign-type :id))
+(defvar *objc-sel-type* (parse-foreign-type :<SEL>))
+(defvar *objc-char-type* (parse-foreign-type :char))
+
+
+(defun encode-objc-type (type &optional for-ivar recursive)
+  (if (or (eq type *objc-id-type*)
+	  (foreign-type-= type *objc-id-type*))
+    "@"
+    (if (or (eq type *objc-sel-type*)
+	    (foreign-type-= type *objc-sel-type*))
+      ":"
+      (if (eq (foreign-type-class type) 'root)
+	"v"
+	(typecase type
+	  (foreign-pointer-type
+	   (let* ((target (foreign-pointer-type-to type)))
+	     (if (or (eq target *objc-char-type*)
+		     (foreign-type-= target *objc-char-type*))
+	       "*"
+	       (format nil "^~a" (encode-objc-type target nil t)))))
+	  (foreign-double-float-type "d")
+	  (foreign-single-float-type "f")
+	  (foreign-integer-type
+	   (let* ((signed (foreign-integer-type-signed type))
+		  (bits (foreign-integer-type-bits type)))
+	     (if (eq (foreign-integer-type-alignment type) 1)
+	       (format nil "b~d" bits)
+	       (cond ((= bits 8)
+		      (if signed "c" "C"))
+		     ((= bits 16)
+		      (if signed "s" "S"))
+		     ((= bits 32)
+		      ;; Should be some way of noting "longness".
+		      (if signed "i" "I"))
+		     ((= bits 64)
+		      (if signed "q" "Q"))))))
+	  (foreign-record-type
+	   (ensure-foreign-type-bits type)
+	   (let* ((name (unescape-foreign-name
+			 (or (foreign-record-type-name type) "?")))
+		  (kind (foreign-record-type-kind type))
+		  (fields (foreign-record-type-fields type)))
+	     (with-output-to-string (s)
+				    (format s "~c~a=" (if (eq kind :struct) #\{ #\() name)
+				    (dolist (f fields (format s "~a" (if (eq kind :struct) #\} #\))))
+				      (when for-ivar
+					(format s "\"~a\""
+						(unescape-foreign-name
+						 (or (foreign-record-field-name f) ""))))
+                                      (unless recursive
+                                        (format s "~a" (encode-objc-type
+                                                        (foreign-record-field-type f) nil nil)))))))
+        (foreign-array-type
+	   (ensure-foreign-type-bits type)
+	   (let* ((dims (foreign-array-type-dimensions type))
+		  (element-type (foreign-array-type-element-type type)))
+	     (if dims (format nil "[~d~a]"
+			      (car dims)
+			      (encode-objc-type element-type nil t))
+	       (if (or (eq element-type *objc-char-type*)
+		       (foreign-type-= element-type *objc-char-type*))
+		 "*"
+		 (format nil "^~a" (encode-objc-type element-type nil t))))))
+	  (t (break "type = ~s" type)))))))
+
+#+ppc-target
+(defun encode-objc-method-arglist (arglist result-spec)
+  (let* ((gprs-used 0)
+	 (fprs-used 0)
+	 (arg-info
+	  (flet ((current-memory-arg-offset ()
+		   (+ 32 (* 4 (- gprs-used 8))
+		      objc-forwarding-stack-offset)))
+	    (flet ((current-gpr-arg-offset ()
+		     (if (< gprs-used 8)
+		       (svref *objc-gpr-offsets* gprs-used)
+		       (current-memory-arg-offset)))
+		   (current-fpr-arg-offset ()
+		     (if (< fprs-used 13)
+		       (svref *objc-fpr-offsets* fprs-used)
+		       (current-memory-arg-offset))))
+	      (let* ((result nil))
+		(dolist (argspec arglist (nreverse result))
+		  (let* ((arg (parse-foreign-type argspec))
+			 (offset 0)
+			 (size 0))
+		    (typecase arg
+		      (foreign-double-float-type
+		       (setq size 8 offset (current-fpr-arg-offset))
+		       (incf fprs-used)
+		       (incf gprs-used 2))
+		      (foreign-single-float-type
+		       (setq size target::node-size offset (current-fpr-arg-offset))
+		       (incf fprs-used)
+		       (incf gprs-used 1))
+		      (foreign-pointer-type
+		       (setq size target::node-size offset (current-gpr-arg-offset))
+		       (incf gprs-used))
+		      (foreign-integer-type
+		       (let* ((bits (foreign-type-bits arg)))
+			 (setq size (ceiling bits 8)
+			       offset (current-gpr-arg-offset))
+			 (incf gprs-used (ceiling bits target::nbits-in-word))))
+		      ((or foreign-record-type foreign-array-type)
+		       (let* ((bits (ensure-foreign-type-bits arg)))
+			 (setq size (ceiling bits 8)
+			       offset (current-gpr-arg-offset))
+			 (incf gprs-used (ceiling bits target::nbits-in-word))))
+		      (t (break "argspec = ~s, arg = ~s" argspec arg)))
+		    (push (list (encode-objc-type arg) offset size) result))))))))
+    (declare (fixnum gprs-used fprs-used))
+    (let* ((max-parm-end
+	    (- (apply #'max (mapcar #'(lambda (i) (+ (cadr i) (caddr i)))
+				    arg-info))
+	       objc-forwarding-stack-offset)))
+      (format nil "~a~d~:{~a~d~}"
+	      (encode-objc-type
+	       (parse-foreign-type result-spec))
+	      max-parm-end
+	      arg-info))))
+
+#+x86-target
+(defun encode-objc-method-arglist (arglist result-spec)
+  (let* ((offset 0)
+	 (arg-info
+          (let* ((result nil))
+		(dolist (argspec arglist (nreverse result))
+		  (let* ((arg (parse-foreign-type argspec))
+                         (delta target::node-size))
+		    (typecase arg
+		      (foreign-double-float-type)
+		      (foreign-single-float-type)
+		      ((or foreign-pointer-type foreign-array-type))
+		      (foreign-integer-type)
+		      (foreign-record-type
+		       (let* ((bits (ensure-foreign-type-bits arg)))
+			 (setq delta (ceiling bits target::node-size))))
+		      (t (break "argspec = ~s, arg = ~s" argspec arg)))
+		    (push (list (encode-objc-type arg) offset) result)
+                    (setq offset (* target::node-size (ceiling (+ offset delta) target::node-size))))))))
+    (let* ((max-parm-end offset))
+      (format nil "~a~d~:{~a~d~}"
+	      (encode-objc-type
+	       (parse-foreign-type result-spec))
+	      max-parm-end
+	      arg-info))))
+
+;;; In Apple Objc, a class's methods are stored in a (-1)-terminated
+;;; vector of method lists.  In GNU ObjC, method lists are linked
+;;; together.
+(defun %make-method-vector ()
+  #+apple-objc
+  (let* ((method-vector (malloc 16)))
+    (setf (%get-signed-long method-vector 0) 0
+	  (%get-signed-long method-vector 4) 0
+	  (%get-signed-long method-vector 8) 0
+	  (%get-signed-long method-vector 12) -1)
+    method-vector))
+
+
+;;; Make a meta-class object (with no instance variables or class
+;;; methods.)
+#-(or apple-objc-2.0 cocotron-objc)
+(defun %make-basic-meta-class (nameptr superptr rootptr)
+  #+apple-objc
+  (let* ((method-vector (%make-method-vector)))
+    (make-record :objc_class
+		 :isa (pref rootptr :objc_class.isa)
+		 :super_class (pref superptr :objc_class.isa)
+		 :name nameptr
+		 :version 0
+		 :info #$CLS_META
+		 :instance_size 0
+		 :ivars (%null-ptr)
+		 :method<L>ists method-vector
+		 :cache (%null-ptr)
+		 :protocols (%null-ptr)))
+  #+gnu-objc
+  (make-record :objc_class
+               :class_pointer (pref rootptr :objc_class.class_pointer)
+               :super_class (pref superptr :objc_class.class_pointer)
+               :name nameptr
+               :version 0
+               :info #$_CLS_META
+               :instance_size 0
+               :ivars (%null-ptr)
+               :methods (%null-ptr)
+               :dtable (%null-ptr)
+               :subclass_list (%null-ptr)
+               :sibling_class (%null-ptr)
+               :protocols (%null-ptr)
+               :gc_object_type (%null-ptr)))
+
+#-(or apple-objc-2.0 cocotron-objc)
+(defun %make-class-object (metaptr superptr nameptr ivars instance-size)
+  #+apple-objc
+  (let* ((method-vector (%make-method-vector)))
+    (make-record :objc_class
+		 :isa metaptr
+		 :super_class superptr
+		 :name nameptr
+		 :version 0
+		 :info #$CLS_CLASS
+		 :instance_size instance-size
+		 :ivars ivars
+		 :method<L>ists method-vector
+		 :cache (%null-ptr)
+		 :protocols (%null-ptr)))
+  #+gnu-objc
+  (make-record :objc_class
+		 :class_pointer metaptr
+		 :super_class superptr
+		 :name nameptr
+		 :version 0
+		 :info #$_CLS_CLASS
+		 :instance_size instance-size
+		 :ivars ivars
+		 :methods (%null-ptr)
+		 :dtable (%null-ptr)
+		 :protocols (%null-ptr)))
+
+(defun make-objc-class-pair (superptr nameptr)
+  #+(or apple-objc-2.0 cocotron-objc)
+  (#_objc_allocateClassPair superptr nameptr 0)
+  #-(or apple-objc-2.0 cocotron-objc)
+  (%make-class-object
+   (%make-basic-meta-class nameptr superptr (@class "NSObject"))
+   superptr
+   nameptr
+   (%null-ptr)
+   0))
+
+(defun superclass-instance-size (class)
+  (with-macptrs ((super #+(or apple-objc-2.0 cocotron-objc) (#_class_getSuperclass class)
+                        #-(or apple-objc-2.0 cocotron-objc) (pref class :objc_class.super_class)))
+    (if (%null-ptr-p super)
+      0
+      (%objc-class-instance-size super))))
+
+	
+
+
+#+gnu-objc
+(progn
+(defloadvar *gnu-objc-runtime-mutex*
+    (%get-ptr (foreign-symbol-address "__objc_runtime_mutex")))
+(defmacro with-gnu-objc-mutex-locked ((mutex) &body body)
+  (let* ((mname (gensym)))
+    `(let ((,mname ,mutex))
+      (unwind-protect
+	   (progn
+	     (external-call "objc_mutex_lock" :address ,mname :void)
+	     ,@body)
+	(external-call "objc_mutex_lock" :address ,mname :void)))))
+)
+
+(defun %objc-metaclass-p (class)
+  #+(or apple-objc-2.0 cocotron-objc) (not (eql #$NO (#_class_isMetaClass class)))
+  #-(or apple-objc-2.0 cocotron-objc)
+  (logtest (pref class :objc_class.info)
+	   #+apple-objc #$CLS_META
+	   #+gnu-objc #$_CLS_META))
+
+;; No way to tell in Objc-2.0.  Does anything care ?
+#-(or apple-objc-2.0 cocotron-objc)
+(defun %objc-class-posing-p (class)
+  (logtest (pref class :objc_class.info)
+	   #+apple-objc #$CLS_POSING
+	   #+gnu-objc #$_CLS_POSING))
+
+
+
+
+;;; Create (malloc) class and metaclass objects with the specified
+;;; name (string) and superclass name.  Initialize the metaclass
+;;; instance, but don't install the class in the ObjC runtime system
+;;; (yet): we don't know anything about its ivars and don't know
+;;; how big instances will be yet.
+;;; If an ObjC class with this name already exists, we're very
+;;; confused; check for that case and error out if it occurs.
+(defun %allocate-objc-class (name superptr)
+  (let* ((class-name (compute-objc-classname name)))
+    (if (lookup-objc-class class-name nil)
+      (error "An Objective C class with name ~s already exists." class-name))
+    (let* ((nameptr (make-cstring class-name))
+	   (id (register-objc-class
+                (make-objc-class-pair superptr nameptr)
+))
+	   (meta-id (objc-class-id->objc-metaclass-id id))
+	   (meta (id->objc-metaclass meta-id))
+	   (class (id->objc-class id))
+	   (meta-name (intern (format nil "+~a" name)
+			      (symbol-package name)))
+	   (meta-super (canonicalize-registered-metaclass
+                        #+(or apple-objc-2.0 cocotron-objc)
+                        (#_class_getSuperclass meta)
+                        #-(or apple-objc-2.0 cocotron-objc)
+			(pref meta :objc_class.super_class))))
+      (initialize-instance meta
+			 :name meta-name
+			 :direct-superclasses (list meta-super))
+      (setf (objc-class-id-foreign-name id) class-name
+	    (objc-metaclass-id-foreign-name meta-id) class-name
+	    (find-class meta-name) meta)
+      (%defglobal name class)
+      (%defglobal meta-name meta)
+    class)))
+
+;;; Set up the class's ivar_list and instance_size fields, then
+;;; add the class to the ObjC runtime.
+#-(or apple-objc-2.0 cocotron-objc)
+(defun %add-objc-class (class ivars instance-size)
+  (setf
+   (pref class :objc_class.ivars) ivars
+   (pref class :objc_class.instance_size) instance-size)
+  #+apple-objc
+  (#_objc_addClass class)
+  #+gnu-objc
+  ;; Why would anyone want to create a class without creating a Module ?
+  ;; Rather than ask that vexing question, let's create a Module with
+  ;; one class in it and use #___objc_exec_class to add the Module.
+  ;; (I mean "... to add the class", of course.
+  ;; It appears that we have to heap allocate the module, symtab, and
+  ;; module name: the GNU ObjC runtime wants to add the module to a list
+  ;; that it subsequently ignores.
+  (let* ((name (make-cstring "Phony Module"))
+	 (symtab (malloc (+ (record-length :objc_symtab) (record-length (:* :void)))))
+	 (m (make-record :objc_module
+			 :version 8 #|OBJC_VERSION|#
+			 :size (record-length :<M>odule)
+			 :name name
+			 :symtab symtab)))
+    (setf (%get-ptr symtab (record-length :objc_symtab)) (%null-ptr))
+    (setf (pref symtab :objc_symtab.sel_ref_cnt) 0
+	  (pref symtab :objc_symtab.refs) (%null-ptr)
+	  (pref symtab :objc_symtab.cls_def_cnt) 1
+	  (pref symtab :objc_symtab.cat_def_cnt) 0
+	  (%get-ptr (pref symtab :objc_symtab.defs)) class
+	  (pref class :objc_class.info) (logior #$_CLS_RESOLV (pref class :objc_class.info)))
+    (#___objc_exec_class m)))
+
+#+(or apple-objc-2.0 cocotron-objc)
+(defun %add-objc-class (class)
+  (#_objc_registerClassPair class))
+
+
+
+
+
+
+
+(let* ((objc-gen-message-args (make-array 10 :fill-pointer 0 :adjustable t)))
+  (defun %objc-gen-message-arg (n)
+    (let* ((len (length objc-gen-message-args)))
+      (do* ((i len (1+ i)))
+           ((> i n) (aref objc-gen-message-args n))
+        (vector-push-extend (intern (format nil "ARG~d" i)) objc-gen-message-args)))))
+
+(defun objc-gen-message-arglist (n)
+  (collect ((args))
+    (dotimes (i n (args)) (args (%objc-gen-message-arg i)))))
+
+
+
+;;; Call get-objc-message-info for all known init messages.  (A
+;;; message is an "init message" if it starts with the string "init",
+;;; and has at least one declared method that returns :ID and is not a
+;;; protocol method.
+(defun register-objc-init-messages ()
+  (do-interface-dirs (d)
+    (dolist (init (cdb-enumerate-keys (db-objc-methods d)
+                                      #'(lambda (string)
+                                          (string= string "init" :end1 (min (length string) 4)))))
+      (get-objc-message-info init))))
+
+    
+(defvar *objc-init-messages-for-init-keywords* (make-hash-table :test #'equal)
+  "Maps from lists of init keywords to dispatch-functions for init messages")
+
+
+
+(defun send-objc-init-message (instance init-keywords args)
+  (let* ((info (gethash init-keywords *objc-init-messages-for-init-keywords*)))
+    (unless info
+      (let* ((name (lisp-to-objc-init init-keywords))
+             (name-info (get-objc-message-info name nil)))
+        (unless name-info
+          (error "Unknown ObjC init message: ~s" name))
+        (setf (gethash init-keywords *objc-init-messages-for-init-keywords*)
+              (setq info name-info))))
+    (apply (objc-message-info-lisp-name info) instance args)))
+                   
+(defun objc-set->setf (method)
+  (let* ((info (get-objc-message-info method))
+         (name (objc-message-info-lisp-name info))
+         (str (symbol-name name))
+         (value-placeholder-index (position #\: str)))
+    (when (and (> (length str) 4) value-placeholder-index)
+      (let* ((truncated-name (nstring-downcase (subseq (remove #\: str
+                                                               :test #'char= :count 1)
+                                                       3)
+                                               :end 1))
+             (reader-name (if (> (length truncated-name)
+                                 (decf value-placeholder-index 3))
+                            (nstring-upcase truncated-name
+                                           :start value-placeholder-index
+                                           :end (1+ value-placeholder-index))
+                            truncated-name))
+             (reader (intern reader-name :nextstep-functions)))
+        (eval `(defun (setf ,reader) (value object &rest args)
+                 (apply #',name object value args)
+                 value))))))
+
+(defun register-objc-set-messages ()
+  (do-interface-dirs (d)
+    (dolist (init (cdb-enumerate-keys (db-objc-methods d)
+                                      #'(lambda (string)
+                                          (string= string "set"
+                                                   :end1 (min (length string) 3)))))
+      (objc-set->setf init))))
+
+  
+
+                  
+
+;;; Return the "canonical" version of P iff it's a known ObjC class
+(defun objc-class-p (p)
+  (if (typep p 'macptr)
+    (let* ((id (objc-class-id p)))
+      (if id (id->objc-class id)))))
+
+;;; Return the canonical version of P iff it's a known ObjC metaclass
+(defun objc-metaclass-p (p)
+  (if (typep p 'macptr)
+    (let* ((id (objc-metaclass-id p)))
+      (if id (id->objc-metaclass id)))))
+
+;;; If P is an ObjC instance, return a pointer to its class.
+;;; This assumes that all instances are allocated via something that's
+;;; ultimately malloc-based.
+(defun objc-instance-p (p)
+  (when (typep p 'macptr)
+    (let* ((idx (%objc-instance-class-index p)))
+      (if idx (id->objc-class  idx)))))
+
+
+
+
+(defun objc-private-class-id (classptr)
+  (let* ((info (%get-private-objc-class classptr)))
+    (when info
+      (or (private-objc-class-info-declared-ancestor info)
+          (with-macptrs ((super #+(or apple-objc-2.0 cocotron-objc) (#_class_getSuperclass classptr)
+                                #-(or apple-objc-2.0 cocotron-objc) (pref classptr :objc_class.super_class)))
+            (loop
+              (when (%null-ptr-p super)
+                (return))
+              (let* ((id (objc-class-id super)))
+                (if id
+                  (return (setf (private-objc-class-info-declared-ancestor info)
+                                id))
+                  (%setf-macptr super #+(or apple-objc-2.0 cocotron-objc) (#_class_getSuperclass super)
+                                #-(or apple-objc-2.0 cocotron-objc) (pref super :objc_class.super_class))))))))))
+
+(defun objc-class-or-private-class-id (classptr)
+  (or (objc-class-id classptr)
+      (objc-private-class-id classptr)))
+
+
+(defun %objc-instance-class-index (p)
+  (unless (%null-ptr-p p)
+    (if (with-macptrs (q)
+          (safe-get-ptr p q)
+          (not (%null-ptr-p q)))
+      (with-macptrs ((parent #+(or apple-objc cocotron-objc) (pref p :objc_object.isa)
+                             #+gnu-objc (pref p :objc_object.class_pointer)))
+        (or
+         (objc-class-id parent)
+         (objc-private-class-id parent))))))
+
+
+;;; If an instance, return (values :INSTANCE <class>)
+;;; If a class, return (values :CLASS <class>).
+;;; If a metaclass, return (values :METACLASS <metaclass>).
+;;; Else return (values NIL NIL).
+(defun objc-object-p (p)
+  (let* ((instance-p (objc-instance-p p)))
+    (if instance-p
+      (values :instance instance-p)
+      (let* ((class-p (objc-class-p p)))
+	(if class-p
+	  (values :class class-p)
+	  (let* ((metaclass-p (objc-metaclass-p p)))
+	    (if metaclass-p
+	      (values :metaclass metaclass-p)
+	      (values nil nil))))))))
+
+       
+
+
+
+;;; If the class contains an mlist that contains a method that
+;;; matches (is EQL to) the selector, remove the mlist and
+;;; set its IMP; return the containing mlist.
+;;; If the class doesn't contain any matching mlist, create
+;;; an mlist with one method slot, initialize the method, and
+;;; return the new mlist.  Doing it this way ensures
+;;; that the objc runtime will invalidate any cached references
+;;; to the old IMP, at least as far as objc method dispatch is
+;;; concerned.
+#-(or apple-objc-2.0 cocotron-objc)
+(defun %mlist-containing (classptr selector typestring imp)
+  #-apple-objc (declare (ignore classptr selector typestring imp))
+  #+apple-objc
+  (%stack-block ((iter 4))
+    (setf (%get-ptr iter) (%null-ptr))
+    (loop
+	(let* ((mlist (#_class_nextMethodList classptr iter)))
+	  (when (%null-ptr-p mlist)
+	    (let* ((mlist (make-record :objc_method_list
+				       :method_count 1))
+		   (method (pref mlist :objc_method_list.method_list)))
+	      (setf (pref method :objc_method.method_name) selector
+		    (pref method :objc_method.method_types)
+		    (make-cstring typestring)
+		    (pref method :objc_method.method_imp) imp)
+	      (return mlist)))
+	  (do* ((n (pref mlist :objc_method_list.method_count))
+		(i 0 (1+ i))
+		(method (pref mlist :objc_method_list.method_list)
+			(%incf-ptr method (record-length :objc_method))))
+	       ((= i n))
+	    (declare (fixnum i n))
+	    (when (eql selector (pref method :objc_method.method_name))
+	      (#_class_removeMethods classptr mlist)
+	      (setf (pref method :objc_method.method_imp) imp)
+	      (return-from %mlist-containing mlist)))))))
+	      
+
+(defun %add-objc-method (classptr selector typestring imp)
+  #+(or apple-objc-2.0 cocotron-objc)
+  (with-cstrs ((typestring typestring))
+    (or (not (eql #$NO (#_class_addMethod classptr selector imp typestring)))
+        (let* ((m (if (objc-metaclass-p classptr)
+                    (#_class_getClassMethod classptr selector)
+                    (#_class_getInstanceMethod classptr selector))))
+          (if (not (%null-ptr-p m))
+            (#_method_setImplementation m imp)
+            (error "Can't add ~s method to class ~s" selector typestring)))))
+  #-(or apple-objc-2.0 cocotron-objc)
+  (progn
+    #+apple-objc
+    (#_class_addMethods classptr
+                        (%mlist-containing classptr selector typestring imp))
+    #+gnu-objc
+  ;;; We have to do this ourselves, and have to do it with the runtime
+  ;;; mutex held.
+    (with-gnu-objc-mutex-locked (*gnu-objc-runtime-mutex*)
+      (let* ((ctypestring (make-cstring typestring))
+             (new-mlist nil))
+        (with-macptrs ((method (external-call "search_for_method_in_list"
+                                              :address (pref classptr :objc_class.methods)
+                                              :address selector
+                                              :address)))
+          (when (%null-ptr-p method)
+            (setq new-mlist (make-record :objc_method_list :method_count 1))
+            (%setf-macptr method (pref new-mlist :objc_method_list.method_list)))
+          (setf (pref method :objc_method.method_name) selector
+                (pref method :objc_method.method_types) ctypestring
+                (pref method :objc_method.method_imp) imp)
+          (if new-mlist
+            (external-call "GSObjCAddMethods"
+                           :address classptr
+                           :address new-mlist
+                           :void)
+            (external-call "__objc_update_dispatch_table_for_class"
+                           :address classptr
+                           :void)))))))
+
+(defvar *lisp-objc-methods* (make-hash-table :test #'eq))
+
+(defstruct lisp-objc-method
+  class-descriptor
+  sel
+  typestring
+  class-p				;t for class methods
+  imp					; callback ptr
+  )
+
+(defun %add-lisp-objc-method (m)
+  (let* ((class (%objc-class-classptr (lisp-objc-method-class-descriptor m)))
+	 (sel (%get-selector (lisp-objc-method-sel m)))
+	 (typestring (lisp-objc-method-typestring m))
+	 (imp (lisp-objc-method-imp m)))
+    (%add-objc-method
+     (if (lisp-objc-method-class-p m)
+       (pref class #+(or apple-objc cocotron-objc) :objc_class.isa #+gnu-objc :objc_class.class_pointer)
+       class)
+     sel
+     typestring
+     imp)))
+
+(def-ccl-pointers add-objc-methods ()
+  (maphash #'(lambda (impname m)
+	       (declare (ignore impname))
+	       (%add-lisp-objc-method m))
+	   *lisp-objc-methods*))
+
+(defun %define-lisp-objc-method (impname classname selname typestring imp
+					 &optional class-p)
+  (%add-lisp-objc-method
+   (setf (gethash impname *lisp-objc-methods*)
+	 (make-lisp-objc-method
+	  :class-descriptor (load-objc-class-descriptor classname)
+	  :sel (load-objc-selector selname)
+	  :typestring typestring
+	  :imp imp
+	  :class-p class-p)))
+  (if (string= selname "set" :end1 (min (length selname) 3))
+    (objc-set->setf selname))
+  impname)
+    
+
+
+
+
+;;; If any of the argspecs denote a value of type :<BOOL>, push an
+;;; appropriate SETQ on the front of the body.  (Order doesn't matter.)
+(defun coerce-foreign-boolean-args (argspecs body)
+  (do* ((argspecs argspecs (cddr argspecs))
+	(type (car argspecs) (car argspecs))
+	(var (cadr argspecs) (cadr argspecs)))
+       ((null argspecs) body)
+    (when (eq type :<BOOL>)
+      (push `(setq ,var (not (eql ,var 0))) body))))
+      
+(defun lisp-boolean->foreign-boolean (form)
+  (let* ((val (gensym)))
+    `((let* ((,val (progn ,@form)))
+	(if (and ,val (not (eql 0 ,val))) 1 0)))))
+
+;;; Return, as multiple values:
+;;;  the selector name, as a string
+;;;  the ObjC class name, as a string
+;;;  the foreign result type
+;;;  the foreign argument type/argument list
+;;;  the body
+;;;  a string which encodes the foreign result and argument types
+(defun parse-objc-method (selector-arg class-arg body)
+  (let* ((class-name (objc-class-name-string class-arg))
+	 (selector-form selector-arg)
+	 (selector nil)
+	 (argspecs nil)
+	 (resulttype nil)
+         (struct-return nil))
+    (flet ((bad-selector (why) (error "Can't parse method selector ~s : ~a"
+				   selector-arg why)))
+      (typecase selector-form
+	(string
+	 (let* ((specs (pop body)))
+	     (setq selector selector-form)
+	     (if (evenp (length specs))
+	       (setq argspecs specs resulttype :id)
+	       (setq resulttype (car (last specs))
+		     argspecs (butlast specs)))))
+	(cons				;sic
+	 (setq resulttype (pop selector-form))
+	 (unless (consp selector-form)
+	   (bad-selector "selector-form not a cons"))
+	 (ccl::collect ((components)
+			 (specs))
+	   ;; At this point, selector-form should be either a list of
+	   ;; a single symbol (a lispified version of the selector name
+	   ;; of a selector that takes no arguments) or a list of keyword/
+	   ;; variable pairs.  Each keyword is a lispified component of
+	   ;; the selector name; each "variable" is either a symbol
+	   ;; or a list of the form (<foreign-type> <symbol>), where
+	   ;; an atomic variable is shorthand for (:id <symbol>).
+	   (if (and (null (cdr selector-form))
+		    (car selector-form)
+		    (typep (car selector-form) 'symbol)
+		    (not (typep (car selector-form) 'keyword)))
+	     (components (car selector-form))
+	     (progn
+	       (unless (evenp (length selector-form))
+		 (bad-selector "Odd length"))
+	       (do* ((s selector-form (cddr s))
+		     (comp (car s) (car s))
+		     (var (cadr s) (cadr s)))
+		    ((null s))
+		 (unless (typep comp 'keyword) (bad-selector "not a keyword"))
+		 (components comp)
+		 (cond ((atom var)
+			(unless (and var (symbolp var))
+			  (bad-selector "not a non-null symbol"))
+			(specs :id)
+			(specs var))
+		       ((and (consp (cdr var))
+			     (null (cddr var))
+			     (cadr var)
+			     (symbolp (cadr var)))
+			(specs (car var))
+			(specs (cadr var)))
+		       (t (bad-selector "bad variable/type clause"))))))
+	   (setq argspecs (specs)
+		 selector (lisp-to-objc-message (components)))))
+	(t (bad-selector "general failure")))
+      ;; If the result type is of the form (:STRUCT <typespec> <name>),
+      ;; make <name> be the first argument.
+      (when (and (consp resulttype)
+		 (eq (car resulttype) :struct))
+	(destructuring-bind (typespec name) (cdr resulttype)
+          (let* ((rtype (%foreign-type-or-record typespec)))
+            (if (and (typep name 'symbol)
+                     (typep rtype 'foreign-record-type))
+              (setq struct-return name
+                    resulttype (unparse-foreign-type rtype))
+              (bad-selector "Bad struct return type")))))
+      (values selector
+	      class-name
+	      resulttype
+	      argspecs
+	      body
+	      (do* ((argtypes ())
+		    (argspecs argspecs (cddr argspecs)))
+		   ((null argspecs) (encode-objc-method-arglist
+				     `(:id :<sel> ,@(nreverse argtypes))
+				     resulttype))
+		(push (car argspecs) argtypes))
+              struct-return))))
+
+(defun objc-method-definition-form (class-p selector-arg class-arg body env)
+  (multiple-value-bind (selector-name
+			class-name
+			resulttype
+			argspecs
+			body
+			typestring
+                        struct-return)
+      (parse-objc-method selector-arg class-arg body)
+    (%declare-objc-method selector-name
+                          class-name
+                          class-p
+                          (concise-foreign-type resulttype)
+                          (collect ((argtypes))
+                            (do* ((argspecs argspecs (cddr argspecs)))
+                                 ((null argspecs) (mapcar #'concise-foreign-type (argtypes)))
+                              (argtypes (car argspecs)))))
+    (let* ((self (intern "SELF")))
+      (multiple-value-bind (body decls) (parse-body body env)
+        (unless class-p
+          (push `(%set-objc-instance-type ,self) body))
+	(setq body (coerce-foreign-boolean-args argspecs body))
+	(if (eq resulttype :<BOOL>)
+	  (setq body (lisp-boolean->foreign-boolean body)))
+	(let* ((impname (intern (format nil "~c[~a ~a]"
+					(if class-p #\+ #\-)
+					class-name
+					selector-name)))
+	       (_cmd (intern "_CMD"))
+	       (super (gensym "SUPER"))
+	       (params `(:id ,self :<sel> ,_cmd)))
+          (when struct-return
+            (push struct-return params))
+          (setq params (nconc params argspecs))
+	  `(progn
+	    (defcallback ,impname
+                (:without-interrupts nil
+                 #+(and openmcl-native-threads (or apple-objc cocotron-objc)) :error-return
+                 #+(and openmcl-native-threads (or apple-objc cocotron-objc))  (condition objc-callback-error-return) ,@params ,resulttype)
+              (declare (ignorable ,_cmd))
+              ,@decls
+              (rlet ((,super :objc_super
+                       #+(or apple-objc coctron-objc) :receiver #+gnu-objc :self ,self
+                       #+(or apple-objc-2.0 cocotron-objc) :super_class #-(or apple-objc-2.0 cocotron-objc) :class
+                       ,@(if class-p
+                             #+(or apple-objc-2.0 cocotron-objc)
+                             `((external-call "class_getSuperclass"
+                                :address (pref (@class ,class-name) :objc_class.isa) :address))
+                             #-(or apple-objc-2.0 cocotron-objc)
+                             `((pref
+                                (pref (@class ,class-name)
+                                 #+apple-objc :objc_class.isa
+                                 #+gnu-objc :objc_class.class_pointer)
+                                :objc_class.super_class))
+                             #+(or apple-objc-2.0 cocotron-objc)
+                             `((external-call "class_getSuperclass"
+                                :address (@class ,class-name) :address))
+                             #-(or apple-objc-2.0 cocotron-objc)
+                             `((pref (@class ,class-name) :objc_class.super_class)))))
+                (macrolet ((send-super (msg &rest args &environment env) 
+                             (make-optimized-send nil msg args env nil ',super ,class-name))
+                           (send-super/stret (s msg &rest args &environment env) 
+                             (make-optimized-send nil msg args env s ',super ,class-name)))
+                  ,@body)))
+	    (%define-lisp-objc-method
+	     ',impname
+	     ,class-name
+	     ,selector-name
+	     ,typestring
+	     ,impname
+	     ,class-p)))))))
+
+(defmacro define-objc-method ((selector-arg class-arg)
+			      &body body &environment env)
+  (objc-method-definition-form nil selector-arg class-arg body env))
+
+(defmacro define-objc-class-method ((selector-arg class-arg)
+				     &body body &environment env)
+  (objc-method-definition-form t selector-arg class-arg body env))
+
+
+(declaim (inline %objc-struct-return))
+
+(defun %objc-struct-return (return-temp size value)
+  (unless (eq return-temp value)
+    (#_memmove return-temp value size)))
+
+(defmacro objc:defmethod (name (self-arg &rest other-args) &body body &environment env)
+  (collect ((arglist)
+            (arg-names)
+            (arg-types)
+            (bool-args)
+            (type-assertions))
+    (let* ((result-type nil)
+           (struct-return-var nil)
+           (struct-return-size nil)
+           (selector nil)
+           (class-p nil)
+           (objc-class-name nil))
+      (if (atom name)
+        (setq selector (string name) result-type :id)
+        (setq selector (string (car name)) result-type (concise-foreign-type (or (cadr name) :id))))
+      (destructuring-bind (self-name lisp-class-name) self-arg
+        (arg-names self-name)
+        (arg-types :id)
+        ;; Hack-o-rama
+        (let* ((lisp-class-name (string lisp-class-name)))
+          (if (eq (schar lisp-class-name 0) #\+)
+            (setq class-p t lisp-class-name (subseq lisp-class-name 1)))
+          (setq objc-class-name (lisp-to-objc-classname lisp-class-name)))
+        (let* ((rtype (parse-foreign-type result-type)))
+          (when (typep rtype 'foreign-record-type)
+            (setq struct-return-var (gensym))
+            (setq struct-return-size (ceiling (foreign-type-bits rtype) 8))
+            (arglist struct-return-var)))
+        (arg-types :<SEL>)
+        (arg-names nil)                 ;newfangled
+        (dolist (arg other-args)
+          (if (atom arg)
+            (progn
+              (arg-types :id)
+              (arg-names arg))
+            (destructuring-bind (arg-name arg-type) arg
+              (let* ((concise-type (concise-foreign-type arg-type)))
+                (unless (eq concise-type :id)
+                  (let* ((ftype (parse-foreign-type concise-type)))
+                    (if (typep ftype 'foreign-pointer-type)
+                      (setq ftype (foreign-pointer-type-to ftype)))
+                    (if (and (typep ftype 'foreign-record-type)
+                             (foreign-record-type-name ftype))
+                      (type-assertions `(%set-macptr-type ,arg-name
+                                         (foreign-type-ordinal (load-time-value (%foreign-type-or-record ,(foreign-record-type-name ftype)))))))))
+                (arg-types concise-type)
+                (arg-names arg-name)))))
+        (let* ((arg-names (arg-names))
+               (arg-types (arg-types)))
+          (do* ((names arg-names)
+                (types arg-types))
+               ((null types) (arglist result-type))
+            (let* ((name (pop names))
+                   (type (pop types)))
+              (arglist type)
+              (arglist name)
+              (if (eq type :<BOOL>)
+                (bool-args `(setq ,name (not (eql ,name 0)))))))
+          (let* ((impname (intern (format nil "~c[~a ~a]"
+                                          (if class-p #\+ #\-)
+                                          objc-class-name
+                                          selector)))
+                 (typestring (encode-objc-method-arglist arg-types result-type))
+                 (signature (cons result-type (cddr arg-types))))
+            (multiple-value-bind (body decls) (parse-body body env)
+              
+              (setq body `((progn ,@(bool-args) ,@(type-assertions) ,@body)))
+              (if (eq result-type :<BOOL>)
+                (setq body `((%coerce-to-bool ,@body))))
+              (when struct-return-var
+                (setq body `((%objc-struct-return ,struct-return-var ,struct-return-size ,@body)))
+                (setq body `((flet ((struct-return-var-function ()
+                                      ,struct-return-var))
+                               (declaim (inline struct-return-var-function))
+                               ,@body)))
+                (setq body `((macrolet ((objc:returning-foreign-struct ((var) &body body)
+                                          `(let* ((,var (struct-return-var-function)))
+                                            ,@body)))
+                               ,@body))))
+              (setq body `((flet ((call-next-method (&rest args)
+                                  (declare (dynamic-extent args))
+                                  (apply (function ,(if class-p
+                                                        '%call-next-objc-class-method
+                                                        '%call-next-objc-method))
+                                         ,self-name
+                                         (@class ,objc-class-name)
+                                         (@selector ,selector)
+                                         ',signature
+                                         args)))
+                                 (declare (inline call-next-method))
+                                 ,@body)))
+              `(progn
+                (%declare-objc-method
+                 ',selector
+                 ',objc-class-name
+                 ,class-p
+                 ',result-type
+                 ',(cddr arg-types))
+                (defcallback ,impname ( :error-return (condition objc-callback-error-return) ,@(arglist))
+                  (declare (ignorable ,self-name)
+                           (unsettable ,self-name)
+                           ,@(unless class-p `((type ,lisp-class-name ,self-name))))
+                  ,@decls
+                  ,@body)
+                (%define-lisp-objc-method
+                 ',impname
+                 ,objc-class-name
+                 ,selector
+                 ,typestring
+                 ,impname
+                 ,class-p)))))))))
+
+      
+           
+  
+
+(defun class-get-instance-method (class sel)
+  #+(or apple-objc cocotron-objc) (#_class_getInstanceMethod class sel)
+  #+gnu-objc (#_class_get_instance_method class sel))
+
+(defun class-get-class-method (class sel)
+  #+(or apple-objc cocotron-objc) (#_class_getClassMethod class sel)
+  #+gnu-objc   (#_class_get_class_method class sel))
+
+(defun method-get-number-of-arguments (m)
+  #+(or apple-objc cocotron-objc) (#_method_getNumberOfArguments m)
+  #+gnu-objc (#_method_get_number_of_arguments m))
+
+#+(and apple-objc (not apple-objc-2.0) ppc-target)
+(progn
+(defloadvar *original-deallocate-hook*
+        #&_dealloc)
+
+(defcallback deallocate-nsobject (:address obj :int)
+  (unless (%null-ptr-p obj)
+    (remhash obj *objc-object-slot-vectors*))
+  (ff-call *original-deallocate-hook* :address obj :int))
+
+(defun install-lisp-deallocate-hook ()
+  (setf #&_dealloc deallocate-nsobject))
+
+#+later
+(def-ccl-pointers install-deallocate-hook ()
+  (install-lisp-deallocate-hook))
+
+(defun uninstall-lisp-deallocate-hook ()
+  (clrhash *objc-object-slot-vectors*)
+  (setf #&_dealloc *original-deallocate-hook*))
+
+(pushnew #'uninstall-lisp-deallocate-hook *save-exit-functions* :test #'eq
+         :key #'function-name)
+)
+
+  
+
+
+
+(defloadvar *nsstring-newline* #@"
+")
+
+
+;;; Execute BODY with an autorelease pool
+
+(defmacro with-autorelease-pool (&body body)
+  (let ((pool-temp (gensym)))
+    `(let ((,pool-temp (create-autorelease-pool)))
+      (unwind-protect
+	   (progn ,@body)
+	(release-autorelease-pool ,pool-temp)))))
+
+#+apple-objc-2.0
+;;; New!!! Improved!!! At best, half-right!!!
+(defmacro with-ns-exceptions-as-errors (&body body)
+  `(progn ,@body))
+
+;;; The NSHandler2 type was visible in Tiger headers, but it's not
+;;; in the Leopard headers.
+#+(and apple-objc (not apple-objc-2.0))
+(def-foreign-type #>NSHandler2_private
+  (:struct #>NSHandler2_private
+    (:_state :jmp_buf)
+    (:_exception :address)
+    (:_others :address)
+    (:_thread :address)
+    (:_reserved1 :address)))
+
+#-apple-objc-2.0
+(defmacro with-ns-exceptions-as-errors (&body body)
+  #+apple-objc
+  (let* ((nshandler (gensym))
+         (cframe (gensym)))
+    `(rletZ ((,nshandler #>NSHandler2_private))
+      (unwind-protect
+           (progn
+             (external-call "__NSAddHandler2" :address ,nshandler :void)
+             (catch ,nshandler
+               (with-c-frame ,cframe
+                 (%associate-jmp-buf-with-catch-frame
+                  ,nshandler
+                  (%fixnum-ref (%current-tcr) target::tcr.catch-top)
+                  ,cframe)
+                 (progn
+                   ,@body))))
+        (check-ns-exception ,nshandler))))
+  #+cocotron-objc
+  (let* ((xframe (gensym))
+         (cframe (gensym)))
+    `(rletZ ((,xframe #>NSExceptionFrame))
+      (unwind-protect
+           (progn
+             (external-call "__NSPushExceptionFrame" :address ,xframe :void)
+             (catch ,xframe
+               (with-c-frame ,cframe
+                 (%associate-jmp-buf-with-catch-frame
+                  ,xframe
+                  (%fixnum-ref (%current-tcr) target::tcr.catch-top)
+                  ,cframe)
+                 (progn
+                   ,@body))))
+        (check-ns-exception ,xframe))))
+  #+gnu-objc
+  `(progn ,@body)
+  )
+
+
+
+
+
+#+(and apple-objc (not apple-objc-2.0))
+(defun check-ns-exception (nshandler)
+  (with-macptrs ((exception (external-call "__NSExceptionObjectFromHandler2"
+                                           :address nshandler
+                                           :address)))
+    (if (%null-ptr-p exception)
+      (external-call "__NSRemoveHandler2" :address nshandler :void)
+      (error (ns-exception->lisp-condition (%inc-ptr exception 0))))))
+
+#+cocotron-objc
+(defun check-ns-exception (xframe)
+  (with-macptrs ((exception (pref xframe #>NSExceptionFrame.exception)))
+    (if (%null-ptr-p exception)
+      (external-call "__NSPopExceptionFrame" :address xframe :void)
+      (error (ns-exception->lisp-condition (%inc-ptr exception 0))))))
+
+
+
+
Index: /branches/new-random/objc-bridge/objc-support.lisp
===================================================================
--- /branches/new-random/objc-bridge/objc-support.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/objc-support.lisp	(revision 13309)
@@ -0,0 +1,577 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "BRIDGE"))
+
+(defun allocate-objc-object (class)
+  (#/alloc class))
+
+(defun conforms-to-protocol (thing protocol)
+  (#/conformsToProtocol: thing (objc-protocol-address protocol)))
+
+
+
+
+#+(or apple-objc cocotron-objc)
+(defun iterate-over-objc-classes (fn)
+  (let* ((n (#_objc_getClassList (%null-ptr) 0)))
+    (declare (fixnum n))
+    (%stack-block ((buffer (the fixnum (ash n target::word-shift))))
+      (#_objc_getClassList buffer n)
+      (do* ((i 0 (1+ i)))
+           ((= i n) (values))
+        (declare (fixnum i))
+        (funcall fn (paref buffer (:* :id) i))))))
+
+#+(or apple-objc cocotron-objc)
+(defun count-objc-classes ()
+  (#_objc_getClassList (%null-ptr) 0))  
+
+#+gnu-objc
+(defun iterate-over-objc-classes (fn)
+  (rletZ ((enum-state :address))
+    (loop
+      (let* ((class (#_objc_next_class enum-state)))
+        (if (%null-ptr-p class)
+          (return)
+          (funcall fn class))))))
+
+#+gnu-objc
+(defun count-objc-classes ()
+  (let* ((n 0))
+    (declare (fixnum n))
+    (rletZ ((enum-state :address))
+      (if (%null-ptr-p (#_objc_next_class enum-state))
+        (return n)
+        (incf n)))))
+
+(defun %note-protocol (p)
+  (with-macptrs ((cname (objc-message-send p "name" :address)))
+    (let* ((namelen (%cstrlen cname))
+           (name (make-string namelen)))
+      (declare (dynamic-extent name))
+      (%str-from-ptr cname namelen name)
+      (let* ((proto (or (gethash name *objc-protocols*)
+                        (progn
+                          (setq name (subseq name 0))
+                          (setf (gethash name *objc-protocols*)
+                                (make-objc-protocol :name name))))))
+        (unless (objc-protocol-address proto)
+          (setf (objc-protocol-address proto) (%inc-ptr p 0)))
+        proto))))
+
+(defun note-class-protocols (class)
+  #-(or apple-objc-2.0 cocotron-objc)
+  (do* ((protocols (pref class :objc_class.protocols)
+                   (pref protocols :objc_protocol_list.next)))
+       ((%null-ptr-p protocols))
+    (let* ((count (pref protocols :objc_protocol_list.count)))
+      (with-macptrs ((list (pref protocols :objc_protocol_list.list)))
+        (dotimes (i count)
+          (with-macptrs ((p (paref list (:* (:* (:struct :<P>rotocol))) i)))
+            (%note-protocol p))))))
+  #+(or apple-objc-2.0 cocotron-objc)
+  (rlet ((p-out-count :int 0))
+    (with-macptrs ((protocols (#_class_copyProtocolList class p-out-count)))
+      (let* ((n (pref p-out-count :int)))
+        (dotimes (i n)
+          (with-macptrs ((p (paref protocols (:* (:* (:struct :<P>rotocol))) i)))
+            (%note-protocol p))))
+      (unless (%null-ptr-p protocols) (#_free protocols)))))
+            
+
+(defun map-objc-classes (&optional (lookup-in-database-p t))
+  (iterate-over-objc-classes
+   #'(lambda (class)
+       (note-class-protocols class)
+       (install-foreign-objc-class class lookup-in-database-p))))
+
+(let* ((nclasses 0)
+       (lock (make-lock)))
+  (declare (fixnum nclasses))
+  (defun maybe-map-objc-classes (&optional use-db)
+    (with-lock-grabbed (lock)
+      (let* ((new (count-objc-classes)))
+        (declare (fixnum new))
+        (unless (= nclasses new)
+          (setq nclasses new)
+          (map-objc-classes use-db))
+        t)))
+  (defun reset-objc-class-count ()
+    (with-lock-grabbed (lock)
+      (setq nclasses 0))))
+
+(register-objc-class-decls)
+(maybe-map-objc-classes t)
+(register-objc-init-messages)
+(register-objc-set-messages)
+
+#+gnu-objc
+(defun iterate-over-class-methods (class method-function)
+  (do* ((mlist (pref class :objc_class.methods)
+	       (pref mlist :objc_method_list.method_next)))
+       ((%null-ptr-p mlist))
+    (do* ((n (pref mlist :objc_method_list.method_count))
+	  (i 0 (1+ i))
+	  (method (pref mlist :objc_method_list.method_list)
+		  (%incf-ptr method (record-length :objc_method))))
+	 ((= i n))
+      (declare (fixnum i n))
+      (funcall method-function method class))))
+
+#+gnu-objc
+(progn
+  ;; Er, um ... this needs lots-o-work.
+  (let* ((objc-class-count 0))
+    (defun reset-objc-class-count () (setq objc-class-count 0))
+    (defun note-all-library-methods (method-function)
+      (do* ((i objc-class-count (1+ i))
+	    (class (id->objc-class i) (id->objc-class i)))
+	   ((eq class 0))
+	(iterate-over-class-methods class method-function)
+	(iterate-over-class-methods (id->objc-metaclass i) method-function))))
+  (def-ccl-pointers revive-objc-classes ()
+    (reset-objc-class-count)))
+
+(defun retain-obcj-object (x)
+  (objc-message-send x "retain"))
+
+
+#+apple-objc-2.0
+(progn
+(defun setup-objc-exception-globals ()
+  (flet ((set-global (offset name)
+           (setf (%get-ptr (%int-to-ptr (+ (target-nil-value) (%kernel-global-offset offset))))
+                 (foreign-symbol-address name))))
+    (set-global 'objc-2-personality "___objc_personality_v0")
+    (set-global 'objc-2-begin-catch "objc_begin_catch")
+    (set-global 'objc-2-end-catch "objc_end_catch")
+    (set-global 'unwind-resume "__Unwind_Resume")))
+
+
+(def-ccl-pointers setup-objc-exception-handling ()
+  (setup-objc-exception-globals))
+
+(setup-objc-exception-globals)
+)
+
+
+(defvar *condition-id-map* (make-id-map) "Map lisp conditions to small integers")
+
+;;; Encapsulate an NSException in a lisp condition.
+(define-condition ns-exception (error)
+  ((ns-exception :initarg :ns-exception :accessor ns-exception))
+  (:report (lambda (c s)
+             (format s "Objective-C runtime exception: ~&~a"
+                     (nsobject-description (ns-exception c))))))
+
+
+
+(defclass ns-lisp-exception (ns::ns-exception)
+    ((condition :initarg :condition :initform nil :reader ns-lisp-exception-condition))
+  (:metaclass ns::+ns-object))
+
+(objc:defmethod #/init ((self ns-lisp-exception))
+  (#/initWithName:reason:userInfo: self #@"lisp exception" #@"lisp exception" +null-ptr+))
+
+
+(defun recognize-objc-exception (x)
+  (if (typep x 'ns:ns-exception)
+    (ns-exception->lisp-condition x)))
+
+(pushnew 'recognize-objc-exception *foreign-error-condition-recognizers*)
+
+(defun %make-nsstring (string)
+  (with-encoded-cstrs :utf-8 ((s string))
+    (#/initWithUTF8String: (#/alloc ns:ns-string) s)))
+
+(defmacro with-autoreleased-nsstring ((nsstring lisp-string) &body body)
+  `(let* ((,nsstring (%make-nsstring ,lisp-string)))
+     (#/autorelease ,nsstring)
+     ,@body))
+
+(defmacro with-autoreleased-nsstrings (speclist &body body)
+  (with-specs-aux 'with-autoreleased-nsstring speclist body))
+
+(defun retain-objc-instance (instance)
+  (#/retain instance))
+
+;;; May have to create/release autorelease pools before the bridge
+;;; is fully reinitialized, so use low-level OBJC-MESSAGE-SEND
+;;; and @class.
+(defun create-autorelease-pool ()
+  (objc-message-send
+   (objc-message-send (@class "NSAutoreleasePool") "alloc") "init"))
+
+(defun release-autorelease-pool (p)
+  (objc-message-send p "release" :void))
+
+
+#-ascii-only
+(progn
+#-windows-target
+(defun lisp-string-from-nsstring (nsstring)
+  ;; The NSData object created here is autoreleased.
+  (let* ((data (#/dataUsingEncoding:allowLossyConversion:
+                nsstring
+                #+little-endian-target #x9c000100
+                #+big-endian-target #x98000100
+                nil)))
+    (unless (%null-ptr-p data)
+      (let* ((nbytes (#/length data))
+             (string (make-string (ash nbytes -2))))
+        ;; BLT the 4-byte code-points from the NSData object
+        ;; to the string, return the string.
+        (%copy-ptr-to-ivector (#/bytes data) 0 string 0 nbytes)))))
+
+#+windows-target
+(defun lisp-string-from-nsstring (nsstring)
+  (let* ((n (#/length nsstring)))
+    (%stack-block ((buf (* (1+ n) (record-length :unichar))))
+      (#/getCharacters: nsstring buf)
+      (setf (%get-unsigned-word buf (+ n n)) 0)
+      (%get-native-utf-16-cstring buf))))
+        
+)
+
+#+ascii-only
+(defun lisp-string-from-nsstring (nsstring)
+  (with-macptrs (cstring)
+    (%setf-macptr cstring
+                  (#/cStringUsingEncoding: nsstring #$NSASCIIStringEncoding))
+    (unless (%null-ptr-p cstring)
+      (%get-cstring cstring))))
+
+
+(objc:defmethod #/reason ((self ns-lisp-exception))
+  (with-slots (condition) self
+    (if condition
+      (#/autorelease (%make-nsstring (format nil "~A" condition)))
+      (call-next-method))))
+
+(objc:defmethod #/description ((self ns-lisp-exception))
+  (#/stringWithFormat: ns:ns-string #@"Lisp exception: %@" (#/reason self)))
+
+
+                     
+(defun ns-exception->lisp-condition (nsexception)
+  (if (typep nsexception 'ns-lisp-exception)
+    (ns-lisp-exception-condition nsexception)
+    (make-condition 'ns-exception :ns-exception nsexception)))
+
+
+(defmethod ns-exception ((c condition))
+  "Map a lisp condition object to an NSException.  Note that instances
+of the NS-EXCEPTION condition class implement this by accessing an
+instance variable."
+  ;;; Create an NSLispException with a lispid that encapsulates
+  ;;; this condition.
+
+  ;; (dbg (format nil "~a" c))
+  ;;(#_NSLog #@"Lisp exception: %@" :id (%make-nsstring (format nil "~a" c)))
+  (make-instance 'ns-lisp-exception :condition c))
+
+
+
+#+(or apple-objc cocotron-objc)         ; not really
+(progn
+
+
+#+ppc-target
+(defun objc-callback-error-return (condition return-value-pointer return-address-pointer)
+  ;; On PPC, the "address" of an external entry point is always
+  ;; aligned on a 32-bit word boundary.  On PPC32, it can always
+  ;; be represented as a fixnum; on PPC64, it might be a pointer
+  ;; instead.
+  ;; Note that this clobbers the actual (foreign) return address,
+  ;; replacing it with the address of #__NSRaiseError.  Note also
+  ;; that storing the NSException object as the return value has
+  ;; the desired effect of causing #__NSRaiseError to be called
+  ;; with that NSException as its argument (because r3 is used both
+  ;; as the canonical return value register and used to pass the
+  ;; first argument on PPC.)
+  (process-debug-condition *current-process* condition (%get-frame-ptr))
+  (let* ((addr (%reference-external-entry-point (load-time-value (external "__NSRaiseError")))))
+    (if (typep addr 'fixnum)
+      (%set-object return-address-pointer 0 addr)
+      (setf (%get-ptr return-address-pointer 0) addr)))
+  (setf (%get-ptr return-value-pointer 0) (ns-exception condition))
+  nil)
+
+#+x8664-target
+(progn
+(defloadvar *x8664-objc-callback-error-return-trampoline*
+    (let* ((code-bytes '(#x48 #x89 #xc7      ; movq %rax %rdi
+                         #x66 #x48 #x0f #x7e #xc0 ; movd %xmm0,%rax
+                         #x52                ; pushq %rdx
+                         #xff #xe0))         ; jmp *rax
+           (nbytes (length code-bytes))
+           (ptr (%allocate-callback-pointer 16)))
+      (dotimes (i nbytes ptr)
+        (setf (%get-unsigned-byte ptr i) (pop code-bytes)))))
+
+(defun objc-callback-error-return (condition return-value-pointer return-address-pointer) 
+  ;; The callback glue reserves space for %rax at return-value-pointer-8,
+  ;; for %rdx at -16, for %xmm0 at -24.  Store NS-EXCEPTION in the
+  ;; %rax slot, the address of #_objc_exception_throw in the %rdx slot, the
+  ;; original return address in the %xmm0 slot, and force a return to
+  ;; the trampoline code above.
+  (process-debug-condition *current-process* condition (%get-frame-ptr))
+  (setf (%get-ptr return-value-pointer -8) (ns-exception condition)
+        (%get-ptr return-value-pointer -16) (%get-ptr return-address-pointer 0)
+        (%get-ptr return-address-pointer 0) *x8664-objc-callback-error-return-trampoline*)
+  ;; A foreign entry point is always an integer on x8664.
+  (let* ((addr (%reference-external-entry-point (load-time-value (external "_objc_exception_throw")))))
+    (if (< addr 0)                      ;unlikely
+      (setf (%%get-signed-longlong return-value-pointer -24) addr)
+      (setf (%%get-unsigned-longlong return-value-pointer -24) addr)))
+  nil)
+
+
+)
+
+#+x8632-target
+(progn
+
+(defloadvar *x8632-objc-callback-error-return-trampoline*
+    (let* ((code-bytes '(#x83 #xec #x10      ; subl $16,%esp
+                         #x89 #x04 #x24      ; movl %eax,(%esp)
+                         #x52                ; pushl %edx
+                         #xff #xe1))         ; jmp *ecx
+           (nbytes (length code-bytes))
+           (ptr (%allocate-callback-pointer 16)))
+      (dotimes (i nbytes ptr)
+        (setf (%get-unsigned-byte ptr i) (pop code-bytes)))))
+
+(defun objc-callback-error-return (condition return-value-pointer return-address-pointer)
+  (process-debug-condition *current-process* condition (%get-frame-ptr))
+  (let* ((addr (%reference-external-entry-point (load-time-value (external #+cocotron-objc "_NSRaiseException" #-cocotron-objc "__NSRaiseError")))))
+    (setf (%get-unsigned-long return-value-pointer -12 ) addr))
+  (setf (%get-ptr return-value-pointer -8) (ns-exception condition)
+        (%get-ptr return-value-pointer -4) (%get-ptr return-address-pointer)
+        (%get-ptr return-address-pointer) *x8632-objc-callback-error-return-trampoline*)
+  nil)
+)
+
+)
+
+
+
+(defun open-main-bundle ()
+  (#/mainBundle ns:ns-bundle))
+
+;;; Create a new immutable dictionary just like src, replacing the
+;;; value of each key in key-value-pairs with the corresponding value.
+(defun copy-dictionary (src &rest key-value-pairs)
+  (declare (dynamic-extent key-value-pairs))
+  ;(#_NSLog #@"src = %@" :id src)
+  (let* ((count (#/count src))
+	 (enum (#/keyEnumerator src))
+         (keys (#/arrayWithCapacity: ns:ns-mutable-array count))
+         (values (#/arrayWithCapacity: ns:ns-mutable-array count)))
+    (loop
+	(let* ((nextkey (#/nextObject enum)))
+	  (when (%null-ptr-p nextkey)
+	    (return))
+	  (do* ((kvps key-value-pairs (cddr kvps))
+		(newkey (car kvps) (car kvps))
+		(newval (cadr kvps) (cadr kvps)))
+	       ((null kvps)
+		;; Copy the key, value pair from the src dict
+                (#/addObject: keys nextkey)
+                (#/addObject: values (#/objectForKey: src nextkey)))
+	    (when (#/isEqualToString: nextkey newkey)
+              (#/addObject: keys nextkey)
+              (#/addObject: values newval)
+	      (return)))))
+    (make-instance 'ns:ns-dictionary
+                   :with-objects values
+                   :for-keys keys)))
+
+
+
+
+(defparameter *objc-description-max-length* 1024 "Limit on the length of NSObject description strings if non-NIL.")
+
+(defun %cf-instance-p (instance)
+  #-apple-objc (declare (ignore instance))
+  #+apple-objc
+  (> (objc-message-send instance "_cfTypeID" #>CFTypeID) 1))
+  
+
+(defun initialized-nsobject-p (nsobject)
+  (or (objc-class-p nsobject)
+      (objc-metaclass-p nsobject)
+      (has-lisp-slot-vector nsobject)
+      (let* ((cf-p (%cf-instance-p nsobject)) 
+             (isize (if cf-p (external-call "malloc_size" :address nsobject :size_t) (%objc-class-instance-size (#/class nsobject))))
+             (skip (if cf-p (+ (record-length :id) 4 #+64-bit-target 4) (record-length :id))))
+        (declare (fixnum isize skip))
+        (or (> skip isize)
+            (do* ((i skip (1+ i)))
+                 ((>= i isize))
+              (declare (fixnum i))
+              (unless (zerop (the (unsigned-byte 8) (%get-unsigned-byte nsobject i)))
+                (return t)))))))
+  
+(defun nsobject-description (nsobject)
+  "Returns a lisp string that describes nsobject.  Note that some
+NSObjects describe themselves in more detail than others."
+  (if (initialized-nsobject-p nsobject)
+    (with-autorelease-pool
+        (let* ((desc (#/description nsobject)))
+          (if (or (null *objc-description-max-length*)
+                  (< (#/length desc) *objc-description-max-length*))
+            (lisp-string-from-nsstring desc)
+            (ns:with-ns-range (r 0 *objc-description-max-length*)
+              (format nil "~a[...]"(lisp-string-from-nsstring (#/substringWithRange: desc r)))))))
+    "[uninitialized]"))
+
+
+
+
+
+;;; This can fail if the nsstring contains non-8-bit characters.
+(defun lisp-string-from-nsstring-substring (nsstring start length)
+  (%stack-block ((cstring (1+ length)))
+    (#/getCString:maxLength:range:remainingRange:
+       nsstring  cstring  length (ns:make-ns-range start length) +null-ptr+)
+    (%get-cstring cstring)))
+
+(def-standard-initial-binding *listener-autorelease-pool* nil)
+
+(setq *listener-autorelease-pool* (create-autorelease-pool))
+
+(define-toplevel-command :global rap () "Release and reestablish *LISTENER-AUTORELEASE-POOL*"
+  (when (eql *break-level* 0)
+    (without-interrupts
+     (when (boundp '*listener-autorelease-pool*)
+       (let* ((old *listener-autorelease-pool*))
+	 (if old (release-autorelease-pool old))
+	 (setq *listener-autorelease-pool* (create-autorelease-pool)))))))
+
+#+apple-objc
+(defun show-autorelease-pools ()
+  (objc-message-send (@class ns-autorelease-pool) "showPools" :void))
+
+#+gnu-objc
+(defun show-autorelease-pools ()
+  (do* ((current (objc-message-send (@class ns-autorelease-pool) "currentPool")
+		 (objc-message-send current "_parentAutoreleasePool"))
+	(i 0 (1+ i)))
+       ((%null-ptr-p current) (values))
+    (format t "~& ~d : ~a [~d]"
+	    i
+	    (nsobject-description current)
+	    (pref current :<NSA>utorelease<P>ool._released_count))))
+
+#+cocotron-objc
+(defun show-autorelease-pools ()
+  (%string-to-stderr  "No info about current thread's autorelease pools is available"))
+
+(define-toplevel-command :global sap () "Log information about current thread's autorelease-pool(s) to C's standard error stream"
+  (show-autorelease-pools))
+
+(define-toplevel-command :global kap () "Release (but don't reestablish) *LISTENER-AUTORELEASE-POOL*"
+  (when (eql *break-level* 0)
+    (without-interrupts
+     (when (boundp '*listener-autorelease-pool*)
+       (let* ((p *listener-autorelease-pool*))
+	 (setq *listener-autorelease-pool* nil)
+	 (release-autorelease-pool p))))))
+
+;;; Use the interfaces for an add-on ObjC framework.  We need to
+;;; tell the bridge to reconsider what it knows about the type
+;;; signatures of ObjC messages, since the new headers may define
+;;; a method whose type signature differs from the message's existing
+;;; methods.  (This probably doesn't happen too often, but it's
+;;; possible that some SENDs that have already been compiled would
+;;; need to be recompiled with that augmented method type info, e.g.,
+;;; because ambiguity was introduced.)
+
+(defun augment-objc-interfaces (dirname)
+  (use-interface-dir dirname)
+  (register-objc-class-decls)
+  (update-objc-method-info))
+
+;;; A list of "standard" locations which are known to contain
+;;; framework bundles.  We should look in ~/Library/Frameworks/" first,
+;;; if it exists.
+(defparameter *standard-framework-directories*
+  (list #p"/Library/Frameworks/"
+        #p"/System/Library/Frameworks/"))
+
+
+
+;;; This has to run during application (re-)initializtion, so it
+;;; uses lower-level bridge features.
+(defun %reload-objc-framework (path)
+  (when (probe-file path)
+    (let* ((namestring (native-translated-namestring path)))
+      (with-cstrs ((cnamestring namestring))
+        (with-nsstr (nsnamestring cnamestring (length namestring))
+          (with-autorelease-pool
+              (let* ((bundle (objc-message-send (@class "NSBundle")
+                                                "bundleWithPath:"
+                                                :id nsnamestring :id)))
+                (unless (%null-ptr-p bundle)
+                  (objc-message-send bundle "load" :<BOOL>)))))))))
+
+
+(defun load-objc-extension-framework (name)
+  (let* ((dirs *standard-framework-directories*)
+         (home-frameworks (make-pathname :defaults nil
+                                         :directory
+                                         (append (pathname-directory
+                                                  (user-homedir-pathname))
+                                                 '("Library" "Frameworks"))))
+         (fname (list (format nil "~a.framework" name))))
+    (when (probe-file home-frameworks)
+      (pushnew home-frameworks dirs :test #'equalp))
+    (dolist (d dirs)
+      (let* ((path (probe-file (make-pathname :defaults nil
+                                              :directory (append (pathname-directory d)
+                                                                 fname)))))
+        (when path
+          (let* ((namestring (native-translated-namestring path)))
+            (with-cstrs ((cnamestring namestring))
+              (with-nsstr (nsnamestring cnamestring (length namestring))
+                (with-autorelease-pool
+                    (let* ((bundle (#/bundleWithPath: ns:ns-bundle nsnamestring))
+                           (winning (unless (%null-ptr-p bundle)
+                                      t)))
+                      (when winning
+                        (let* ((libpath (#/executablePath bundle)))
+                          (unless (%null-ptr-p libpath)
+                            (open-shared-library (lisp-string-from-nsstring
+                                                  libpath))))
+                        (#/load bundle)
+                        (pushnew path *extension-framework-paths*
+                                 :test #'equalp)
+                        (map-objc-classes)
+                        ;; Update info about init messages.
+                        (register-objc-init-messages)
+                        (register-objc-set-messages))
+                      (return winning)))))))))))
+
+(defun objc:load-framework (framework-name interfaces-name)
+  (use-interface-dir interfaces-name)
+  (or (load-objc-extension-framework framework-name)
+      (error "Can't load ObjC framework ~s" framework-name))
+  (augment-objc-interfaces interfaces-name))
+
+                      
+(defmethod print-object ((p ns:protocol) stream)
+  (print-unreadable-object (p stream :type t)
+    (format stream "~a (#x~x)"
+            (%get-cstring (#/name p))
+            (%ptr-to-int p))))
+
+                                         
+(defmethod terminate ((instance objc:objc-object))
+  (objc-message-send instance "release"))
+
+
+(provide "OBJC-SUPPORT")
Index: /branches/new-random/objc-bridge/obsolete/CocoaBridgeDoc.txt
===================================================================
--- /branches/new-random/objc-bridge/obsolete/CocoaBridgeDoc.txt	(revision 13309)
+++ /branches/new-random/objc-bridge/obsolete/CocoaBridgeDoc.txt	(revision 13309)
@@ -0,0 +1,289 @@
+A Cocoa Bridge for OpenMCL
+
+Randall D. Beer
+beer@eecs.cwru.edu
+http://vorlon.cwru.edu/~beer
+
+
+INTRODUCTION
+
+The purpose of CocoaBridge is to make Cocoa as easy as possible to use
+from OpenMCL, in order to support GUI application and development
+environment activities.  It builds on the capabilities provided in the
+APPLE-OBJC example.  The eventual goal is complete integration of
+Cocoa into CLOS.  The current release provides Lisp-like syntax and
+naming conventions for ObjC object creation and message sending, with
+automatic type processing and compile-time checking of message
+sends. It also provides some convenience facilities for working with
+Cocoa.
+
+A small sample Cocoa program can be invoked by evaluating (REQUIRE
+'TINY) and then (CCL::TINY-SETUP). This program provides a simple example
+of using several of the bridge's capabilities
+
+
+BASICS
+
+The main things you need to know are:
+
+1) You create and initialize ObjC objects using
+MAKE-OBJC-INSTANCE. This should be replaced by MAKE-INSTANCE as CLOS
+integration improves
+
+Example: 
+[[NSNumber alloc] initWithFloat: 2.7] in ObjC becomes
+(MAKE-OBJC-INSTANCE 'NS-NUMBER :INIT-WITH-FLOAT 2.7) in Lisp
+
+Note that class names and init keywords are translated from ObjC to Lisp in
+pretty much the obvious way
+
+2) You send messages to ObjC objects using SEND
+
+Examples:
+[w alphaValue] becomes (SEND W 'ALPHA-VALUE)
+[w setAlphaValue: 0.5] becomes (SEND W :SET-ALPHA-VALUE 0.5)
+[v mouse: p inRect: r] becomes (SEND V :MOUSE P :IN-RECT R)
+
+Note that message keywords are translated to Lisp in pretty much the obvious
+way.  From within a method, you can also use SEND-SUPER.
+
+
+3) The @CLASS macro from APPLE-OBJC is currently used to refer to named ObjC
+classes, which can also be sent messages via SEND. This should be replaced by
+FIND-CLASS as CLOS integration improves.
+
+Example: 
+[NSColor whiteColor] becomes (SEND (@CLASS NS-COLOR) 'WHITE-COLOR)
+
+
+4) New ObjC classes and methods are currently defined using DEF-OBJC-CLASS and
+DEFINE-OBJC-METHOD from APPLE-OBJC.  This should be replaced by DEFCLASS and
+DEFMETHOD as CLOS integration improves.
+
+
+NAME TRANSLATION
+
+There are a standard set of naming conventions for Cocoa classes,
+ messages, etc.  As long as these are followed, the bridge is fairly
+ good at automaticallly translating between ObjC and Lisp names.
+
+Examples:
+"NSURLHandleClient" <==> NS-URL-HANDLE-CLIENT
+"NSOpenGLView" <==> NS-OPENGL-VIEW
+"nextEventMatchingMask:untilDate:inMode:dequeue:" <==>
+(:NEXT-EVENT-MATCHING-MASK :UNTIL-DATE :IN-MODE :DEQUEUE)
+
+To see how a given ObjC or Lisp name will be translated by the bridge, you can
+use the following functions:
+
+OBJC-TO-LISP-CLASSNAME string
+LISP-TO-OBJC-CLASSNAME symbol
+OBJC-TO-LISP-MESSAGE string
+LISP-TO-OBJC-MESSAGE keyword-list
+OBJC-TO-LISP-INIT string
+LISP-TO-OBJC-INIT keyword-list
+
+Of course, there will always be exceptions to any naming convention.
+Please let me know if you come across any name translation problems
+that seem to be bugs.  Otherwise, the bridge provides two ways of
+dealing with exceptions:
+
+1) You can pass a string as the class name of MAKE-OBJC-INSTANCE and
+as the message to SEND.  These strings will be directly interpreted as
+ObjC names, with no translation. This is useful for a one-time
+exception.
+
+Examples:
+(MAKE-OBJC-INSTANCE "WiErDclass")
+(SEND o "WiErDmEsSaGe:WithARG:" x y)
+
+2) You can define a special translation rule for your exception. This is useful
+for an exceptional name that you need to use throughout your code.
+
+Examples:
+(DEFINE-CLASSNAME-TRANSLATION "WiErDclass" WEIRD-CLASS)
+(DEFINE-MESSAGE-TRANSLATION "WiErDmEsSaGe:WithARG:" (:WEIRD-MESSAGE :WITH-ARG))
+(DEFINE-INIT-TRANSLATION "WiErDiNiT:WITHOPTION:" (:WEIRD-INIT :OPTION)
+
+The normal rule in ObjC names is that each word begins with a capital letter
+(except possibly the first).  Using this rule literally, "NSWindow" would be
+translated as N-S-WINDOW, which seems wrong.  "NS" is a special word in ObjC
+that should not be broken at each capital letter. Likewise "URL", "PDF",
+"OpenGL", etc. Most common special words used in Cocoa are already defined in
+the bridge, but you can define new ones as follows: (DEFINE-SPECIAL-OBJC-WORD
+"QuickDraw")
+
+Note that message keywords in a SEND such as (SEND V :MOUSE P :IN-RECT R) may
+look like Lisp keyword args, but they really aren't. All keywords must be
+present and the order is significant. Neither (:IN-RECT :MOUSE) nor (:MOUSE)
+translate to "mouse:inRect:"
+
+Note that an "init" prefix is optional in the initializer keywords, so
+(MAKE-OBJC-INSTANCE 'NS-NUMBER :INIT-WITH-FLOAT 2.7) can also be expressed as
+(MAKE-OBJC-INSTANCE 'NS-NUMBER :WITH-FLOAT 2.7)
+
+
+STRETS
+
+Some Cocoa methods return small structures (such as those used to represent
+points, rects, sizes and ranges). Although this is normally hidden by the ObjC
+compiler, such messages are sent in a special way, with the storage for the
+STructure RETurn (STRET) passed as an extra argument. This STRET and special
+SEND must normally be made explicit in Lisp.  Thus 
+
+NSRect r = [v1 bounds];
+[v2 setBounds r];
+
+in ObjC becomes
+
+(RLET ((R :<NSR>ect))
+  (SEND/STRET R V1 'BOUNDS)
+  (SEND V2 :SET-BOUNDS R))
+  
+In order to make STRETs easier to use, the bridge provides two conveniences:
+
+1) The SLET and SLET* macros may be used to define local variables that are
+initialized to STRETs using a normal SEND syntax. Thus, the following is 
+equivalent to the above RLET:
+
+(SLET ((R (SEND V 'BOUNDS)))
+ (SEND V2 :SET-BOUNDS R))
+ 
+2) The arguments to a SEND are evaluated inside an implicit SLET, so instead of
+the above, one could in fact just write:
+
+(SEND V1 :SET-BOUNDS (SEND V2 'BOUNDS))
+
+There are also several psuedo-functions provided for convenience by the ObjC
+compiler. The following are currently supported by the bridge: NS-MAKE-POINT,
+NS-MAKE-RANGE, NS-MAKE-RECT, and NS-MAKE-SIZE. These can be used within a SLET
+initform or within a message send:
+
+(SLET ((P (NS-MAKE-POINT 100.0 200.0)))
+  (SEND W :SET-FRAME-ORIGIN P))
+  
+or
+  
+(SEND W :SET-ORIGIN (NS-MAKE-POINT 100.0 200.0))
+
+However, since these aren't real functions, a call like the following won't
+work:
+
+(SETQ P (NS-MAKE-POINT 100.0 200.0))
+
+The following convenience macros are also provided: NS-MAX-RANGE, NS-MIN-X,
+NS-MIN-Y, NS-MAX-X, NS-MAX-Y, NS-MID-X, NS-MID-Y, NS-HEIGHT, and NS-WIDTH.
+
+Note that there is also a SEND-SUPER/STRET for use within methods.
+
+
+OPTIMIZATION
+
+The bridge works fairly hard to optimize message sends under two conditions. In
+both of these cases, a message send should be nearly as efficient as in ObjC:
+
+1) When both the message and the receiver's class are known at compile-time. In
+general, the only way the receiver's class is known is if you declare it, which
+you can do either via a DECLARE or THE form.  For example:
+
+(SEND (THE NS-WINDOW W) 'CENTER)
+
+Note that there is no way in ObjC to name the class of a class.  Thus
+the bridge provides a @METACLASS declaration. The type of an instance
+of "NSColor" is NS-COLOR.  The type of the *class* "NSColor" is
+(@METACLASS NS-COLOR):
+
+(LET ((C (@CLASS NS-COLOR)))
+  (DECLARE ((@METACLASS NS-COLOR) C))
+  (SEND C 'WHITE-COLOR))
+  
+2) When only the message is known at compile-time, but its type
+signature is unique. Of the over 6000 messages currently provided by
+Cocoa, only about 50 of them have nonunique type signatures.  An
+example of a message whose type signature is not unique is SET.  It
+returns VOID for NSColor, but ID for NSSet.  In order to optimize
+sends of messages with nonunique type signatures, the class of the
+receiver must be declared at compile-time.
+
+If the type signature is nonunique or the message is unknown at compile-time,
+then a slower runtime call must be used.
+
+The ability of the bridge to optimize most constant message sends even
+when the receiver's class is unknown crucially depends on a type
+signature table that the bridge maintains.  When the bridge is first
+loaded, it initializes this table by scanning all methods of all ObjC
+classes defined in the environment.  If new methods are later defined,
+this table must be updated. After a major change (such as loading a
+new framework with many classes), you should evaluate
+(UPDATE-TYPE-SIGNATURES) to rebuild the type signature table.
+
+Because SEND, SEND-SUPER, SEND/STRET and SEND-SUPER/STRET are macros,
+they cannot be FUNCALLed, APPLYed or passed as functional arguments.
+The functions %SEND and %SEND/STRET are provided for this
+purpose. There are also %SEND-SUPER and %SEND-SUPER/STRET functions
+for use within methods. However, these functions should be used only
+when necessary since they perform general (nonoptimized) message
+sends.
+
+
+VARIABLE ARITY MESSAGES
+
+There are a few messages in Cocoa that take variable numbers of arguments.  
+Perhaps the most common examples involve formatted strings:
+
+[NSClass stringWithFormat: "%f %f" x y]
+
+In the bridge, this would be written as follows:
+
+(SEND (@CLASS NS-STRING) 
+      :STRING-WITH-FORMAT #@"%f %f" 
+      (:DOUBLE-FLOAT X :DOUBLE-FLOAT Y))
+
+Note that the types of the variable arguments must be given, since the compiler
+has no way of knowing these types in general.
+
+Variable arity messages can also be sent with the %SEND function:
+
+(%SEND (@CLASS NS-STRING) 
+       :STRING-WITH-FORMAT #@"%f %f" 
+       (LIST :DOUBLE-FLOAT X :DOUBLE-FLOAT Y))
+
+Because the ObjC runtime system does not provide any information on
+which messages are variable arity, they must be explicitly defined.
+The standard variable arity messages in Cocoa are predefined.  If you
+need to define a new variable arity message, use
+(DEFINE-VARIABLE-ARITY-MESSAGE "myVariableArityMessage:")
+
+
+TYPE COERCION
+
+OpenMCL's FFI handles many common conversions between Lisp and foreign data,
+such as unboxing floating-point args and boxing floating-point results.  The
+bridge adds a few more automatic conversions:
+
+1) NIL is equivalent to (%NULL-PTR) for any message argument that requires a
+pointer
+
+2) T/NIL are equivalent to #$YES/#$NO for any boolean argument
+
+3) A #$YES/#$NO returned by any method that returns BOOL will be automatically
+converted to T/NIL
+
+To make this last conversion work, the bridge has to engage in a bit
+of hackery.  The bridge uses ObjC run-time type info.  Unfortunately,
+BOOL is typed as CHAR by ObjC.  Thus, a method that returns CHAR might
+actually return only BOOL, or it might return any CHAR.  The bridge
+currently assumes that any method that returns CHAR actually returns
+BOOL.  But it provides a facility for defining exceptions to this
+assumption: (DEFINE-RETURNS-BOOLEAN-EXCEPTION "charValue").
+Eventually, the best way to handle issues like this is probably to get
+our method type info directly from the header files rather than using
+ObjC's runtime type system.
+
+Note that no automatic conversion is currently performed between Lisp
+strings and NSStrings.  However, APPLE-OBJ provides a convenient
+syntax for creating constant NSStrings: (SEND W :SET-TITLE #@"My
+Window"), as well as facilities for converting between Lisp strings
+and NSStrings.  Note that #@"Hello" is a full ObjC object, so messages
+can be sent to it: (SEND #@"Hello" 'LENGTH)
+
Index: /branches/new-random/objc-bridge/obsolete/README
===================================================================
--- /branches/new-random/objc-bridge/obsolete/README	(revision 13309)
+++ /branches/new-random/objc-bridge/obsolete/README	(revision 13309)
@@ -0,0 +1,9 @@
+The Objective-C bridge has evolved quite a bit, and the CocoaBridgeDoc.txt
+file is now probably mostly misleading.
+
+The most current documentation for the bridge is in release-notes.txt in
+the top-level ccl directory.  At some point soon, updated documentation
+will be made available at:
+
+http://doc.clozure.com/doku.php/doc/openmcl/objc
+
Index: /branches/new-random/objc-bridge/process-objc-modules.lisp
===================================================================
--- /branches/new-random/objc-bridge/process-objc-modules.lisp	(revision 13309)
+++ /branches/new-random/objc-bridge/process-objc-modules.lisp	(revision 13309)
@@ -0,0 +1,217 @@
+;;;-*-Mode: LISP; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2003-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(#-(or apple-objc gnu-objc)
+   (eval-when (:compile-toplevel :load-toplevel :execute)
+     #+darwinppc-target (pushnew :apple-objc *features*)
+     #+linuxppc-target (pushnew :gnu-objc *features*)
+     #-(or darwinppc-target linuxppc-target)
+     (error "Not sure what ObjC runtime system to use.")))
+
+#+apple-objc
+(progn
+(defvar *objc-module-verbose* nil)
+
+
+(defun process-section-in-all-libraries (segname sectionname function)
+  "For every loaded shared library, find the section named SECTIONNAME
+in the segment named SEGNAME.  If this section exists, call FUNCTION with
+a pointer to the section data and the section's size in bytes as arguments."
+  (with-cstrs ((seg segname)
+	       (sect sectionname))
+    (rlet ((size :unsigned))
+      (with-macptrs (mach-header sectdata)
+	(dotimes (i (#_ _dyld_image_count))
+	  (%setf-macptr mach-header (#_ _dyld_get_image_header i))
+	  ;; Paranoia: this should never be null
+	  (unless (%null-ptr-p mach-header)
+            ;; The one instance of an MH_BUNDLE I've encountered
+            ;; hasn't had its section data relocated.  I'm not sure
+            ;; if that's generally true of MH_BUNDLEs; for the time
+            ;; being, ignore them and concentrate on MH_DYLIBs.
+            (when (eql (pref mach-header :mach_header.filetype) #$MH_DYLIB)
+              (%setf-macptr sectdata (#_getsectdatafromheader
+                                      mach-header
+                                      seg
+                                      sect
+                                      size))
+              ;; This pointer may be null, unless the shared object
+              ;; file denoted by "mach_header" contains a segment and
+              ;; section matching those we're looking for.
+              (unless (%null-ptr-p sectdata)
+                (funcall function sectdata (pref size :unsigned))))))))))
+
+(defun process-objc-modules (f)
+  (process-section-in-all-libraries #$SEG_OBJC #$SECT_OBJC_MODULES f))
+
+;;; A not-too-interesting test of the mechanism.
+(defun show-objc-module-sections ()
+  (process-objc-modules #'(lambda (sect size)
+			    (format t "~& module section @~s, size = ~d"
+				    sect size))))
+
+(defun process-module-classes (module classfn)
+  (when *objc-module-verbose*
+    (format t "~& processing classes in module ~s" module)
+    (force-output t))  
+  (with-macptrs ((symtab (pref module :objc_module.symtab)))
+    (with-macptrs ((defsptr (pref symtab :objc_symtab.defs))
+		   (classptr))
+      (dotimes (i (pref symtab :objc_symtab.cls_def_cnt))
+	(%setf-macptr classptr (%get-ptr defsptr (* i (record-length :address))))
+	(when *objc-module-verbose*
+	  (format t "~& processing class ~a, info = #x~8,'0x"
+		  (%get-cstring (pref classptr :objc_class.name))
+		  (pref classptr :objc_class.info))
+          (force-output t))
+	;; process the class
+	(funcall classfn classptr)
+	;; process the metaclass
+	(funcall classfn (pref classptr :objc_class.isa))))))
+
+(defun process-module-categories (module catfn)
+  (with-macptrs ((symtab (pref module :objc_module.symtab)))
+    (with-macptrs ((catptr
+		    (%inc-ptr (pref symtab :objc_symtab.defs)
+			      (* (pref symtab :objc_symtab.cls_def_cnt)
+				 (record-length :address)))))
+      (dotimes (i (pref symtab :objc_symtab.cat_def_cnt))
+	(when *objc-module-verbose*
+	  (format t "~& processing category ~s "
+		  (%get-cstring (pref (%get-ptr catptr)
+				      :objc_category.category_name))))
+	(funcall catfn (%get-ptr catptr))
+	(%incf-ptr catptr (record-length :address))))))
+
+
+;;; This is roughly equivalent to the inner loop in DO-OBJC-METHODS.
+(defun process-methods-in-method-list (mlist class  mfun)
+  (unless (%null-ptr-p mlist)
+    (with-macptrs ((method (pref mlist :objc_method_list.method_list)))
+      (dotimes (i (pref mlist :objc_method_list.method_count))
+	(funcall mfun method class)
+	(%incf-ptr method (record-length :objc_method))))))
+
+;;; Categories push method lists onto the "front" of the class.
+;;; The methods that belong to the class are in the last method list,
+;;; so we skip everything else here.
+(defun process-class-methods (class methodfun)
+  (%stack-block ((iter 4))
+    (setf (%get-ptr iter) (%null-ptr))
+    (with-macptrs ((next)
+		   (mlist ))
+      (loop
+	  (%setf-macptr next (#_class_nextMethodList class iter))
+	  (when (%null-ptr-p next)
+	    (process-methods-in-method-list mlist class  methodfun)
+	    (return))
+	(%setf-macptr mlist next)))))
+
+(defun process-category-methods (category methodfun)
+  (with-macptrs ((classname (pref category :objc_category.class_name))
+		 (class (#_objc_lookUpClass classname))
+		 (metaclass (pref class :objc_class.isa))
+		 (instance-methods
+		  (pref category :objc_category.instance_methods))
+		 (class-methods
+		  (pref category :objc_category.class_methods)))
+    (process-methods-in-method-list instance-methods class methodfun)
+    (process-methods-in-method-list class-methods metaclass methodfun)))
+
+(defun process-module-methods (sectptr size methodfun)
+  "Process all modules in the ObjC module section SECTPTR, whose size
+in bytes is SIZE.  For each class and each category in each module,
+call METHODFUN on each method defined in a class or category.  The
+METHODFUN will be called with a stack-allocated/mutable pointer to the
+method, and a stack-allocated/mutable pointer to the method receiver's
+class or metaclass object."
+  (when *objc-module-verbose*
+    (format t "~& processing classes in section ~s" sectptr)
+    (force-output t))
+  (with-macptrs ((module sectptr))
+    (let* ((nmodules (/ size (record-length :objc_module))))
+      (dotimes (i nmodules)
+	(process-module-classes
+	 module
+	 #'(lambda (class)
+	     (when *objc-module-verbose*
+	       (format t "~& == processing class #x~8,'0x ~a, (#x~8,'0x) info = #x~8,'0x"
+		       (%ptr-to-int class)
+		       (%get-cstring (pref class :objc_class.name))
+		       (%ptr-to-int (pref class :objc_class.name))
+		       (pref class :objc_class.info)))
+	     #+nope
+	     (unless (logtest #$CLS_META (pref class :objc_class.info))
+	       (map-objc-class class))
+	     (process-class-methods class methodfun)))
+	(process-module-categories	 
+	 module
+	 #'(lambda (category)
+	     (process-category-methods category methodfun)))
+	(%incf-ptr module (record-length :objc_module))))))
+	   
+(defun iterate-over-module-classes (sectptr size classfn)
+  (when *objc-module-verbose*
+    (format t "~& processing classes in section ~s" sectptr)
+    (force-output t))
+  (with-macptrs ((module sectptr))
+    (let* ((nmodules (/ size (record-length :objc_module))))
+      (dotimes (i nmodules)
+	(process-module-classes module classfn)
+	(%incf-ptr module (record-length :objc_module))))))
+
+	  
+(defun process-section-methods (sectptr size methodfun &optional
+					(section-check-fun #'true))
+  "If SECTION-CHECK-FUN returns true when called with the (stack-allocated,
+mutable) Objc modules section SECTPTR, process all methods defined
+in all classes/categories in all modules in the section."
+  (when (funcall section-check-fun sectptr)
+    (process-module-methods sectptr size methodfun)))
+
+(defloadvar *sections-already-scanned-for-methods* ())
+
+(defun check-if-section-already-scanned (sectptr)
+  (unless (member sectptr *sections-already-scanned-for-methods*
+		  :test #'eql)
+    (push (%inc-ptr sectptr 0)		;make a heap-allocated copy!
+	  *sections-already-scanned-for-methods*)
+    t))
+
+(defun note-all-library-methods (method-function)
+  "For all methods defined in all classes and categories defined in all
+ObjC module sections in all loaded shared libraries, call METHOD-FUNCTION
+with the method and defining class as arguments.  (Both of these arguments
+may have been stack-allocated by the caller, and may be destructively
+modified by the caller after the METHOD-FUNCTION returns.)
+  Sections that have already been scanned in the current lisp session are
+ignored."
+  (process-objc-modules
+   #'(lambda (sectptr size)
+       (process-section-methods
+	sectptr
+	size
+	method-function
+	#'check-if-section-already-scanned))))
+
+
+                        
+
+)
+(provide "PROCESS-OBJC-MODULES") 
+
Index: /branches/new-random/scripts/.cvsignore
===================================================================
--- /branches/new-random/scripts/.cvsignore	(revision 13309)
+++ /branches/new-random/scripts/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/scripts/ccl
===================================================================
--- /branches/new-random/scripts/ccl	(revision 13309)
+++ /branches/new-random/scripts/ccl	(revision 13309)
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# Change the definition of CCL_DEFAULT_DIRECTORY below to refer to
+# your OpenMCL installation directory.  
+# Any definition of CCL_DEFAULT_DIRECTORY already present in the environment 
+# takes precedence over definitions made below.
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+  CCL_DEFAULT_DIRECTORY=/usr/local/src/ccl
+fi
+
+export CCL_DEFAULT_DIRECTORY
+
+# This is shorter (& easier to type), making the invocation below
+# a little easier to read.
+
+DD=${CCL_DEFAULT_DIRECTORY}
+
+# If you don't want to guess the name of the OpenMCL kernel on
+# every invocation (or if you want to use a kernel with a
+# non-default name), you might want to uncomment and change
+# the following line:
+#OPENMCL_KERNEL=some_name
+
+# Set the CCL_DEFAULT_DIRECTORY  environment variable; 
+# the lisp will use this to setup translations for the CCL: logical host.
+
+if [ -z "$OPENMCL_KERNEL" ]; then
+  case `uname -s` in
+    Darwin) case `arch` in
+              ppc*) OPENMCL_KERNEL=dppccl ;;
+              i386) OPENMCL_KERNEL=dx86cl ;;
+            esac ;;
+    Linux) case `uname -m` in
+              ppc*) OPENMCL_KERNEL=ppccl ;;
+              *86*) OPENMCL_KERNEL=lx86cl ;;
+           esac ;;
+    CYGWIN*)
+       OPENMCL_KERNEL=wx86cl.exe
+       CCL_DEFAULT_DIRECTORY="C:/cygwin$CCL_DEFAULT_DIRECTORY"
+    ;;
+    SunOS) OPENMCL_KERNEL=sx86cl
+    ;;
+    FreeBSD) OPENMCL_KERNEL=fx86cl
+    ;;
+    *)
+    echo "Can't determine host OS.  Fix this."
+    exit 1
+    ;;
+  esac
+fi
+
+exec ${DD}/${OPENMCL_KERNEL} "$@"
+
Index: /branches/new-random/scripts/ccl64
===================================================================
--- /branches/new-random/scripts/ccl64	(revision 13309)
+++ /branches/new-random/scripts/ccl64	(revision 13309)
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# Change the definition of CCL_DEFAULT_DIRECTORY below to refer to
+# your OpenMCL installation directory.  
+# Any definition of CCL_DEFAULT_DIRECTORY already present in the environment 
+# takes precedence over definitions made below.
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+  CCL_DEFAULT_DIRECTORY=/usr/local/src/ccl
+fi
+
+# This is shorter (& easier to type), making the invocation below
+# a little easier to read.
+
+DD=${CCL_DEFAULT_DIRECTORY}
+
+# If you don't want to guess the name of the OpenMCL kernel on
+# every invocation (or if you want to use a kernel with a
+# non-default name), you might want to uncomment and change
+# the following line:
+#OPENMCL_KERNEL=some_name
+
+# Set the CCL_DEFAULT_DIRECTORY  environment variable; 
+# the lisp will use this to setup translations for the CCL: logical host.
+
+if [ -z "$OPENMCL_KERNEL" ]; then
+  case `uname -s` in
+    Darwin)
+    case `arch` in
+      ppc*)
+      OPENMCL_KERNEL=dppccl64
+      ;;
+      i386|x86_64)
+      OPENMCL_KERNEL=dx86cl64
+      ;;
+    esac
+    ;;
+    Linux)
+    case `uname -m` in
+      ppc64)
+      OPENMCL_KERNEL=ppccl64
+      ;;
+      x86_64)
+      OPENMCL_KERNEL=lx86cl64
+      ;;
+      *)
+      echo "Can't determine machine architecture.  Fix this."
+      exit 1
+      ;;
+    esac
+    ;;
+    FreeBSD)
+    case `uname -m` in
+      amd64)
+      OPENMCL_KERNEL=fx86cl64
+      ;;
+      *)
+      echo "unsupported architecture"
+      exit 1
+      ;;
+    esac
+    ;;
+    SunOS)
+    case `uname -m` in
+      i86pc)
+      OPENMCL_KERNEL=sx86cl64
+      ;;
+      *)
+      echo "unsupported architecture"
+      exit 1
+      ;;
+    esac
+    ;;
+    CYGWIN*)
+    OPENMCL_KERNEL=wx86cl64.exe
+    CCL_DEFAULT_DIRECTORY="C:/cygwin$CCL_DEFAULT_DIRECTORY"
+    ;;
+    *)
+    echo "Can't determine host OS.  Fix this."
+    exit 1
+    ;;
+  esac
+fi
+
+CCL_DEFAULT_DIRECTORY=${DD} exec ${DD}/${OPENMCL_KERNEL} "$@"
+
Index: /branches/new-random/scripts/http-to-ssh
===================================================================
--- /branches/new-random/scripts/http-to-ssh	(revision 13309)
+++ /branches/new-random/scripts/http-to-ssh	(revision 13309)
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# This script can be used to rewrite the schema in svn working copy URLs,
+# changing URLs that use 'http' as an access method to use 'svn+ssh' instead.
+# (The http: access method allows read-only access; 'svn+ssh' allows people
+# with appropriate permission to commit changes to the repository.)
+
+SCRIPTS=`dirname $0`
+CCLDIR=$SCRIPTS/..
+
+# This assumes that all directories under CCL are under svn control
+# That's a reasonable assumption after a fresh checkout; if it's
+# violated, svn will warn and we'll move on.
+
+for d in `ls $CCLDIR`
+do
+ if [ -d $CCLDIR/$d ]; then
+   $SCRIPTS/svn-switch $CCLDIR/$d
+ fi
+done
Index: /branches/new-random/scripts/makedmg
===================================================================
--- /branches/new-random/scripts/makedmg	(revision 13309)
+++ /branches/new-random/scripts/makedmg	(revision 13309)
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Creates a compresses disk image from the current directory
+# The resulting dmg file is placed in the parent directory
+#
+# This script first deletes any fasl files "*fsl"
+#
+# The volume name of the disk image is the final component
+# of the current directory name.
+# The file name is the same with ".dmg" appended.
+
+DIRNAME=${PWD##*/}
+
+find . -name "*fsl" -exec rm -f {} \;
+hdiutil create -fs HFS+ -srcfolder . -volname ${DIRNAME} ../${DIRNAME}x.dmg
+hdiutil convert ../${DIRNAME}x.dmg -format UDBZ -o ../${DIRNAME}.dmg
+rm ../${DIRNAME}x.dmg
Index: /branches/new-random/scripts/svn-switch
===================================================================
--- /branches/new-random/scripts/svn-switch	(revision 13309)
+++ /branches/new-random/scripts/svn-switch	(revision 13309)
@@ -0,0 +1,8 @@
+#!/bin/sh
+HTTP_URL=http://svn.clozure.com
+SSH_URL=svn+ssh://svn.clozure.com/usr/local
+
+(cd $1;
+    echo Relocating `pwd` ; 
+    svn switch --relocate $HTTP_URL $SSH_URL)
+
Index: /branches/new-random/tools/.cvsignore
===================================================================
--- /branches/new-random/tools/.cvsignore	(revision 13309)
+++ /branches/new-random/tools/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*fsl
+*~.*
Index: /branches/new-random/tools/README-OpenMCL.txt
===================================================================
--- /branches/new-random/tools/README-OpenMCL.txt	(revision 13309)
+++ /branches/new-random/tools/README-OpenMCL.txt	(revision 13309)
@@ -0,0 +1,46 @@
+This directory contains various third-party opensourced
+system-building tools.
+
+The code here is current as of February 1, 2005; you may want
+to check the originating project's homepages to see if more recent
+versions are available.
+
+"defsystem.lisp" is part of the clocc project on SourcForge:
+<http://sourceforge.net/projects/clocc>.  It's a "system definition
+facility" which provides functionality similar to that offered by
+the Unix "make" program.  It was originally written by Mark Kantrowitz
+and has been maintained and enhanced by many people; I believe that
+Marco Antoniotti is currently the principal developer.  This is
+version 3.4i of DEFSYSTEM (which is often called "MK-DEFSYSTEM").
+Note that, for historical reasons, DEFSYSTEM will try to redefine
+the CL:REQUIRE function.
+
+"asdf.lisp" is Another System Definition Facility and is available as
+part of the cclan project on SourceForge:
+<http://sourceforge.net/projects/cclan>.  It was written by and
+is maintained by Daniel Barlow.
+
+"asdf-install" is a library which can be used to download CL packages
+from the Internet and which uses ASDF to build and install them.  It's
+also part of the cclan project and was originally written (for SBCL)
+by Dan Barlow.  It's since been ported to several other CL
+implementations; Marco Baringer did the OpenMCL port.
+
+There's excellent documentation on asdf-install in the asdf-install/doc
+directory.  As that document mentions, asdf-install is designed to use
+the GnuPG package to validate cryptographic signatures associated with
+asdf-install-able packages, though it can apparently be configured to
+work in an environment in which GnuPG is not available.
+
+Downloading code from publicly-writable Internet sites - without the
+ability to verify that that code's really what it claims to be and
+from the author who claims to have provided it - is obviously a
+dangerous and unwise thing to do.  It's strongly recommended that
+people ensure that GnuPG is installed (and ensure that asdf-install is
+configured to use it) before using asdf-install to download packages.
+
+(GnuPG packages for OSX are available from <http://macgpg.sourceforge.net>.
+Most Linux distributions offer GnuPG through their packaging system;
+further information on GnuPG is available at <http:///www.gnupg.org>.
+
+
Index: /branches/new-random/tools/advice-profiler/overhead.lisp
===================================================================
--- /branches/new-random/tools/advice-profiler/overhead.lisp	(revision 13309)
+++ /branches/new-random/tools/advice-profiler/overhead.lisp	(revision 13309)
@@ -0,0 +1,62 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Profiling overhead calculation
+
+;;; This is in a separate file so that the profiler.lisp file can be
+;;; compiled and loaded beforehand, making the macrology available.
+
+(in-package "PROFILER")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun stub-function (x)
+    (declare (ignore x))
+    nil)
+  (proclaim '(notinline stub-function)))
+
+(defconstant +overhead-iterations+ 10000
+  "Number of iterations to make through the empty stub function to
+   determine profiling overhead.")
+
+(defvar *determining-overhead* nil
+  "Set while determining overhead in order to prevent recursion")
+
+(defun determine-overhead ()
+  (format *trace-output* "; Calculating profiling overhead...")
+  (force-output *trace-output*)
+  (reset)
+  (process-enable-profiling *current-process*)
+  (unprofile stub-function)
+  ;; Determine loop and function call overhead
+  (with-real/cpu/cons (bare-real bare-cpu bare-cons)
+      (dotimes (i +overhead-iterations+)
+        (stub-function nil))
+    (profile stub-function)
+    (with-real/cpu/cons (alloc-real alloc-cpu alloc-cons)
+        (stub-function nil)             ; call once in order to allocate call record structure
+      ;; Determine profiling overhead
+      (with-real/cpu/cons (profiled-real profiled-cpu profiled-cons)
+          (dotimes (i +overhead-iterations+)
+            (stub-function nil))
+        (unprofile stub-function)
+        (setf *real-overhead* (round (/ (- profiled-real bare-real) +overhead-iterations+))
+              *cpu-overhead* (round (/ (- profiled-cpu bare-cpu) +overhead-iterations+))
+              *cons-overhead* (round (/ (- profiled-cons bare-cons alloc-cons) +overhead-iterations+)))))
+    (reset)
+    (format *trace-output* "~&; per call overheads: cpu time ~A, real time ~A, cons ~A bytes~%"
+            (format-time *cpu-overhead*) (format-time *real-overhead*) *cons-overhead*)))
+
+(determine-overhead)
Index: /branches/new-random/tools/advice-profiler/package.lisp
===================================================================
--- /branches/new-random/tools/advice-profiler/package.lisp	(revision 13309)
+++ /branches/new-random/tools/advice-profiler/package.lisp	(revision 13309)
@@ -0,0 +1,28 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CL-USER")
+
+(defpackage "PROFILER"
+  (:nicknames "PROF")
+  (:use "COMMON-LISP" "CCL")
+  (:export "PROFILE" "UNPROFILE"
+           "UNPROFILE-ALL"
+           "PROFILE-PACKAGE" "UNPROFILE-PACKAGE"
+           "ENABLE-PROFILING" "DISABLE-PROFILING"
+           "PROCESS-ENABLE-PROFILING" "PROCESS-DISABLE-PROFILING"
+	   "RESET"
+	   "REPORT"))
Index: /branches/new-random/tools/advice-profiler/profiler.asd
===================================================================
--- /branches/new-random/tools/advice-profiler/profiler.asd	(revision 13309)
+++ /branches/new-random/tools/advice-profiler/profiler.asd	(revision 13309)
@@ -0,0 +1,29 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CL-USER")
+
+(defpackage "PROFILER-SYSTEM"
+  (:use "CL" "ASDF"))
+
+(in-package "PROFILER-SYSTEM")
+
+(defsystem :profiler
+  :name "Clozure CL deterministic multithread-profiler"
+  :author "Hans Huebner <hans@clozure.com>"
+  :components ((:file "package")
+               (:file "profiler" :depends-on ("package"))
+               (:file "overhead" :depends-on ("profiler"))))
Index: /branches/new-random/tools/advice-profiler/profiler.lisp
===================================================================
--- /branches/new-random/tools/advice-profiler/profiler.lisp	(revision 13309)
+++ /branches/new-random/tools/advice-profiler/profiler.lisp	(revision 13309)
@@ -0,0 +1,653 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Deterministic profiler for Clozure CL
+
+;;; Inspired by the public domain profiler written by Mark Kantrowitz
+
+;;; To get accurate profiling results, you need to make sure that your
+;;; processor runs at full speed.  Modern CPUs adjust their CPU clock
+;;; dynamically, which will have negative effects on accuracy of the
+;;; profiling result.
+
+;;; In virtual machines, the profiling results may also be inaccurate
+;;; due to virtualized timers.
+
+;;; Bottom line: Always try to profile on the bare metal, with all
+;;; power saving techniques switched off.  Repeat your profiling to get
+;;; a feel for the precision of the results.
+
+;;; The code has provisions for measuring CPU time in addition to real
+;;; time, but it seems that no operating system can deliver consistent
+;;; and accurate per-thread CPU time usage.
+
+;;; All clock values that are handled by this profiler are specified
+;;; in nanoseconds.  This means that it will use bignums on 32 bit
+;;; platforms.
+
+(in-package "PROFILER")
+
+(defvar *profiler-loaded* nil)
+ 
+(eval-when (:load-toplevel :execute)
+  (when (and (not *profiler-loaded*)
+             (> (length (all-processes)) 2))
+    (error "Profiler can't be loaded with active application threads.  Please load from ccl-init.lisp"))
+  (setf *profiler-loaded* t))
+
+;;; Process specific variables
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro defvar-process-specific (var init doc)
+    `(progn
+       (defvar ,var ,init ,doc)
+       (ccl::def-standard-initial-binding ,var ,init))))
+
+(defvar-process-specific *process-profile-results* nil
+  "Variable to hold profiling information, in a hash table.  If NIL,
+   profiling is disabled for this process.")
+
+(defvar-process-specific *total-cpu-time* 0
+  "Amount of CPU time used by profiled functions so far")
+(defvar-process-specific *total-real-time* 0
+  "Amount of real time used by profiled functions so far")
+(defvar-process-specific *total-cons* 0
+  "Amount of consing in profiled functions so far")
+(defvar-process-specific *total-calls* 0
+  "Number of calls to profiled functions so far")
+
+;;; Global variables
+
+;;; Profiler overhead is determined by the function DETERMINE-OVERHEAD
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defvar *real-overhead* 0 "Real time overhead")
+  (defvar *cpu-overhead* 0 "CPU time overhead")
+  (defvar *cons-overhead* 0 "Consing overhead (additional consing per call)"))
+
+(defvar *profiled-functions* nil
+  "List of function names that are currently being profiled.")
+
+(defvar *clock-errors* nil
+  "This flag indicates that the CPU and real time clock have shown to be inconsistent.  A warning
+   will be printed in the report if this is found to be true.")
+
+(defparameter *profile-new-processes* t
+  "This flag indicates that profiling should automatically be enabled for new processes that are
+   created.  If it nil, no call recording takes place for processes until after
+   PROCESS-ENABLE-PROFILING has been called for them.")
+
+(defvar *profiler-lock* (make-lock "Profiler lock")
+  "Lock to guard accesses to global profiler structures")
+
+(defmacro with-profiler-locked (() &body body)
+  `(with-lock-grabbed (*profiler-lock*)
+     ,@body))
+
+#+darwin
+(defun mach-timespec->nanoseconds (ts)
+  "Convert the given typespec structure into nanoseconds."
+  (+ (* 1000000000 (pref ts :mach_timespec.tv_sec))
+     (pref ts :mach_timespec.tv_nsec)))
+#+darwin
+(declaim (inline mach-timespec->nanoseconds))
+
+(defun timespec->nanoseconds (ts)
+  "Convert the given typespec structure into nanoseconds."
+  (+ (* 1000000000 (pref ts :timespec.tv_sec))
+     (pref ts :timespec.tv_nsec)))
+(declaim (inline timespec->nanoseconds))
+
+;;; Clock handling
+
+;;; For Darwin, we use the Mach clock service
+
+#+darwin
+(let ((clock-port (make-record :clock_serv_t)))
+  (#_host_get_clock_service (#_mach_host_self) #$REALTIME_CLOCK clock-port)
+  (defun get-real-time ()
+    (ccl:rlet ((ts :mach_timespec))
+      (unless (zerop (#_clock_get_time (%get-ptr clock-port) ts))
+        (error "error reading Mach clock: ~A~%" (ccl::%strerror (ccl::%get-errno))))
+      (mach-timespec->nanoseconds ts))))
+
+;;; For non-Darwin platforms, we use clock_gettime() with the
+;;; CLOCK_MONOTONIC clock.
+
+#-darwin
+(defun get-posix-clock (id)
+  (ccl:rlet ((ts :timespec))
+    (unless (zerop (#_clock_gettime id ts))
+      (error "error reading clock ~A: ~A~%" id (ccl::%strerror (ccl::%get-errno))))
+    (timespec->nanoseconds ts)))
+(declaim (inline get-posix-clock))
+
+#-darwin
+(defun get-real-time ()
+  (get-posix-clock #$CLOCK_MONOTONIC))
+
+;;; Per-thread CPU time measurement is only available on Linux
+
+(defun get-cpu-time ()
+  #+linux-target
+  (get-posix-clock #$CLOCK_THREAD_CPUTIME_ID)
+  #-linux-target
+  0)
+
+(defparameter *can-report-cpu* #+linux-target t #-linux-target nil)
+
+(defun get-cons ()
+  (ccl::total-bytes-allocated))
+
+(declaim (inline get-cpu-time get-real-time get-cons))
+
+;;; Helper macro to measure elapsed time
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro with-real/cpu/cons ((delta-real delta-cpu delta-cons &key adjusted) form &body post-process)
+    "Evaluate FORM, then run POST-PROCESS with DELTA-REAL, DELTA-CPU and
+   DELTA-CONS bound to the elapsed real time, elapsed CPU time and
+   amount of consing that happened in FORM.  If ADJUSTED is non-nil,
+   the values are adjusted by the overhead values."
+    (let ((start-real (gensym "START-REAL-"))
+          (start-cpu (gensym "START-CPU-"))
+          (start-cons (gensym "START-CONS-")))
+      `(let ((,start-real (get-real-time))
+             (,start-cpu (get-cpu-time))
+             (,start-cons (get-cons)))
+         (declare (type fixnum ,start-real ,start-cpu ,start-cons))
+         (multiple-value-prog1 ,form
+           (let ((,delta-real (- (get-real-time) ,start-real ,@(when adjusted (list '*real-overhead*))))
+                 (,delta-cpu (- (get-cpu-time) ,start-cpu ,@(when adjusted (list '*cpu-overhead*))))
+                 (,delta-cons (- (get-cons) ,start-cons ,@(when adjusted (list '*cons-overhead*)))))
+             (declare (type fixnum ,delta-real ,delta-cpu ,delta-cons))
+             ;; If there is clock imprecision, we can end up with
+             ;; negative delta values here.  For now, we just make
+             ;; sure that we never pass negative deltas back to the
+             ;; reporting code, but it may be preferable to take a
+             ;; note of such events and mark the report as being
+             ;; questionable.
+             (when (minusp ,delta-real) (setf ,delta-real 0))
+             (when (minusp ,delta-cpu) (setf ,delta-cpu 0))
+             (when (minusp ,delta-cons) (setf ,delta-cons 0))
+             (when (>= ,delta-real ,delta-cpu)
+               (setf *clock-errors* t))
+             ,@post-process))))))
+
+;;; Formatting
+
+(defun format-time (nanoseconds)
+  "Given a time in NANOSECONDS, return a human readable string with
+   the time scaled.  Times shorter than a second are reported with the
+   proper sub-second unit (ns, us, ms), times longer than a second are
+   reported in wall clock format (HH:MM:SSh)."
+  (cond
+    ((> 1000 nanoseconds)
+     (format nil "~Ans" (floor nanoseconds)))
+    ((> 1000000 nanoseconds)
+     (format nil "~,1Fus" (/ nanoseconds 1000)))
+    ((> 1000000000 nanoseconds)
+     (format nil "~,1Fms" (/ nanoseconds 1000000)))
+    ((> 100000000000 nanoseconds)
+     (format nil "~,1Fs " (/ nanoseconds 1000000000)))
+    (t
+     (let* ((seconds (floor nanoseconds 1000000000))
+            (minutes (floor seconds 60))
+            (hours (floor minutes 60)))
+       (format nil "~A:~2,'0D:~2,'0Dh"
+               hours
+               (- minutes (* 60 hours))
+               (- seconds (* 60 minutes)))))))
+               
+;; For each profiled function that is called within a process, a
+;; function-call-record structure is created that carries the counters
+;; and timing information.
+
+(defstruct (function-call-record
+             (:conc-name fcr-)
+             (:constructor make-function-call-record%))
+  (process *current-process* :type process)
+  (name nil :type symbol)
+  (inclusive-real-time 0 :type fixnum)
+  (exclusive-real-time 0 :type fixnum)
+  (inclusive-cpu-time 0 :type fixnum)
+  (exclusive-cpu-time 0 :type fixnum)
+  (inclusive-cons 0 :type fixnum)
+  (exclusive-cons 0 :type fixnum)
+  (calls 0 :type fixnum)
+  (nested-calls 0 :type fixnum))
+
+(defun make-function-call-record (name)
+  "Create a function-call-record structure for the function named NAME.  The
+   current process is written into the structure created for later
+   analysis."
+  (let ((fcr (make-function-call-record%)))
+    (setf (fcr-name fcr) name)
+    fcr))
+
+(defun sum-fcrs (fcrs)
+  (let ((sum (make-function-call-record (fcr-name (first fcrs)))))
+    (setf (fcr-inclusive-real-time sum) (reduce #'+ fcrs :key #'fcr-inclusive-real-time)
+          (fcr-exclusive-real-time sum) (reduce #'+ fcrs :key #'fcr-exclusive-real-time)
+          (fcr-inclusive-cpu-time sum) (reduce #'+ fcrs :key #'fcr-inclusive-cpu-time)
+          (fcr-exclusive-cpu-time sum) (reduce #'+ fcrs :key #'fcr-exclusive-cpu-time)
+          (fcr-inclusive-cons sum) (reduce #'+ fcrs :key #'fcr-inclusive-cons)
+          (fcr-exclusive-cons sum) (reduce #'+ fcrs :key #'fcr-exclusive-cons)
+          (fcr-calls sum) (reduce #'+ fcrs :key #'fcr-calls)
+          (fcr-nested-calls sum) (reduce #'+ fcrs :key #'fcr-nested-calls))
+    sum))
+
+(defmacro profile (&rest names)
+  "Profile the functions named by NAMES.  As in TRACE, the names are
+   not evaluated.  Strings and keywords are interpreted as package
+   designators and will cause all functions named by external symbols
+   in the package to be profiled.  If a function is already profiled,
+   then unprofile and reprofile (useful to notice function
+   redefinition).  If a name is undefined, give a warning and ignore
+   it."
+  `(progn
+     (let (new-names)
+       ,@(mapcar
+          (lambda (name)
+            (if (or (stringp name)
+                    (keywordp name))
+              `(setf new-names (append (profile-package ,name :external-only t) new-names))
+              `(with-profiler-locked ()
+                 (if (find ',name *profiled-functions*)
+                   (unprofile ,name)
+                   (push ',name new-names))
+                 (cond
+                   ((not (fboundp ',name))
+                    (warn "ignored argument ~A, which is not the name of a function" ',name))
+                   (t
+                    (ccl:advise ,name
+                                (progn
+                                  (when (and (null *process-profile-results*)
+                                             *profile-new-processes*)
+                                    (setf *process-profile-results* (make-hash-table)))
+                                  (if *process-profile-results*
+                                    (let ((prev-cpu-time *total-cpu-time*)
+                                          (prev-real-time *total-real-time*)
+                                          (prev-cons *total-cons*)
+                                          (prev-calls *total-calls*))
+                                      (declare (type fixnum prev-cpu-time prev-real-time prev-cons prev-calls))
+                                      (with-real/cpu/cons (delta-real delta-cpu delta-cons :adjusted t)
+                                          (:do-it)
+                                        (multiple-value-bind (fcr presentp)
+                                            (gethash ',name *process-profile-results*)
+                                          (unless presentp
+                                            (setf fcr (make-function-call-record ',name))
+                                            (setf (gethash ',name *process-profile-results*) fcr))
+                                          ;; Call counters
+                                          (incf *total-calls*)
+                                          (incf (fcr-calls fcr))
+                                          (incf (fcr-nested-calls fcr) (- *total-calls* prev-calls))
+                                          ;; Real time
+                                          (incf (fcr-inclusive-real-time fcr) delta-real)
+                                          (incf (fcr-exclusive-real-time fcr) (- delta-real
+                                                                                 (- *total-real-time* prev-real-time)))
+                                          (setf *total-real-time* (+ delta-real prev-real-time))
+                                          ;; CPU time
+                                          (incf (fcr-inclusive-cpu-time fcr) delta-cpu)
+                                          (incf (fcr-exclusive-cpu-time fcr) (- delta-cpu
+                                                                                (- *total-cpu-time* prev-cpu-time)))
+                                          (setf *total-cpu-time* (+ delta-cpu prev-cpu-time))
+                                          ;; consing
+                                          (incf (fcr-inclusive-cons fcr) delta-cons)
+                                          (incf (fcr-exclusive-cons fcr) (- delta-cons
+                                                                            (- *total-cons* prev-cons)))
+                                          (setf *total-cons* (+ delta-cons prev-cons)))))
+                                    (:do-it)))
+                                :when :around)
+                    (pushnew ',name *profiled-functions*))))))
+          names)
+       new-names)))
+
+(defun symbol-external-p (symbol)
+  "Return non-nil if the SYMBOL is external in its package (being
+exported)."
+  (eq :external (nth-value 1 (find-symbol (symbol-name symbol) (symbol-package symbol)))))
+
+(defun functions-in-package (package external-only)
+  "Return the list of symbols in PACKAGE that have a function bound to
+   them.  If EXTERNAL-ONLY is true, only returns those symbols that
+   are external."
+  (let ((package (if (packagep package)
+                   package
+                   (or (find-package package)
+                       (error "package ~S not found" package))))
+        symbols)
+    (do-symbols (symbol package)
+      (when (and (fboundp symbol)
+                 (not (macro-function symbol))
+                 (eq (symbol-package symbol) package)
+                 (or (not external-only)
+                     (symbol-external-p symbol)))
+        (pushnew symbol symbols)))
+    symbols))
+
+;;; Per-process profiling API
+
+(defmacro within-process ((process) &body body)
+  "Run BODY within PROCESS, using PROCESS-INTERRUPT."
+  (let ((sem (gensym "SEM-")))
+    `(let ((,sem (make-semaphore)))
+       (process-interrupt ,process
+                          (lambda ()
+                            (unwind-protect
+                                 (progn ,@body)
+                              (signal-semaphore, sem))))
+       (wait-on-semaphore ,sem))))
+
+(defun process-enable-profiling (&optional (process *current-process*))
+  "Enable profiling for the given process."
+  (within-process (process)
+    (unless *process-profile-results*
+      (setf *process-profile-results* (make-hash-table)))))
+
+(defun process-disable-profiling (&optional (process *current-process*))
+  "Disable profiling for the given process."
+  (within-process (process)
+    (setf *process-profile-results* nil)))
+
+(defun enable-profiling ()
+  "Enable profiling in all current and future processes."
+  (dolist (process (all-processes))
+    (process-enable-profiling process))
+  (setf *profile-new-processes* t))
+
+(defun disable-profiling ()
+  "Disable profiling in all current and future processes."
+  (dolist (process (all-processes))
+    (process-enable-profiling process))
+  (setf *profile-new-processes* nil))
+
+;;; Global profiling API
+
+(defmacro profile-package (&optional (package *package*) &key external-only)
+  "Profile all functions in the specified package."
+  `(profile ,@(functions-in-package package external-only)))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro unprofile (&rest names)
+    "Unprofile the functions named by NAMES.  If an argument is a
+     keyword or a string, it is considered to be a package name and
+     all (!) symbols in the package will be unprofiled."
+    `(with-profiler-locked ()
+       ,@(mapcar (lambda (name)
+                   (if (or (stringp name)
+                           (keywordp name))
+                       `(unprofile-package ,name)
+                       `(ccl:unadvise ,name)))
+                 names)
+       (setf *profiled-functions* (set-difference *profiled-functions* ',names)))))
+
+(defmacro unprofile-all ()
+  "Unprofile all functions that are currently profiled."
+  `(with-profiler-locked ()
+     ,@(mapcar (lambda (name) `(ccl:unadvise ,name)) *profiled-functions*)
+     (setf *profiled-functions* nil)))
+
+(defmacro unprofile-package (&optional (package *package*) &key external-only)
+  "Profile all functions in the specified PACKAGE, which may be either
+   a string, a keyword symbol or a package instance.  If EXTERNAL-ONLY
+   is t, only functions named by symbols which are external in PACKAGE
+   are unprofiled."
+  `(unprofile ,@(functions-in-package package external-only)))
+
+(defun reset ()
+  "Reset profiling information in all processes."
+  (setf *total-cpu-time* 0
+        *total-real-time* 0
+        *total-cons* 0
+        *total-calls* 0)
+  (dolist (process (all-processes))
+    (within-process (process)
+      (when *process-profile-results*
+        (clrhash *process-profile-results*)))))
+
+(defun collect-profiling-results (&key reset)
+  "Collect profiling results from all processes.  If RESET is true,
+   the profiling results are cleared when they have been read."
+  (let (results)
+    (dolist (process (all-processes))
+      (within-process (process)
+        (when *process-profile-results*
+          (with-profiler-locked ()
+            (maphash (lambda (key value)
+                       (declare (ignore key))
+                       (push value results))
+                     *process-profile-results*))
+          (when reset
+            (clrhash *process-profile-results*)))))
+    results))
+
+;; Reporting
+
+(defun write-results-xml (&key (stream *standard-output*))
+  "Write the profiling results to the given STREAM in an XML format,
+   one 'entry' element for each function call record that has been
+   collected."
+  (format stream "<profile-results>~%")
+  (dolist (fcr (collect-profiling-results))
+    (format stream "  <entry function='~S' ~
+                             process='~A' ~
+                             inclusive-real-time='~A' exclusive-real-time='~A' ~
+                             inclusive-cpu-time='~A' exclusive-cpu-time='~A' ~
+                             inclusive-cons='~A' exclusive-cons='~A' ~
+                             calls='~A' nested-calls='~A'/>~%"
+            (fcr-name fcr)
+            (process-name (fcr-process fcr))
+            (fcr-inclusive-real-time fcr) (fcr-exclusive-real-time fcr)
+            (fcr-inclusive-cpu-time fcr) (fcr-exclusive-cpu-time fcr)
+            (fcr-inclusive-cons fcr) (fcr-exclusive-cons fcr)
+            (fcr-calls fcr) (fcr-nested-calls fcr)))
+  (format stream "</profile-results>~%"))
+
+(defun write-results-csv (&key (stream *standard-output*))
+  "Write the profiling results to the given STREAM in a CSV format
+   which can be imported into excel for further analysis."
+  (format stream "package;function;process;inclusive-real-time;exclusive-real-time;inclusive-cpu-time;exclusive-cpu-time;~
+                  inclusive-cons;exclusive-cons;calls;nested-calls~%")
+  (dolist (fcr (collect-profiling-results))
+    (format stream "\"~S\";\"~A\";~A;~A;~A;~A;~A;~A;~A;~A~%"
+            (fcr-name fcr)
+            (process-name (fcr-process fcr))
+            (fcr-inclusive-real-time fcr) (fcr-exclusive-real-time fcr)
+            (fcr-inclusive-cpu-time fcr) (fcr-exclusive-cpu-time fcr)
+            (fcr-inclusive-cons fcr) (fcr-exclusive-cons fcr)
+            (fcr-calls fcr) (fcr-nested-calls fcr))))
+
+(defstruct (profile-results
+            (:conc-name pr-)
+            (:constructor make-profile-results
+                          (name process
+                                calls
+                                real-time cpu-time cons
+                                percent-real-time percent-cpu-time percent-cons)))
+  name
+  process
+  calls
+  real-time
+  cpu-time
+  cons
+  percent-real-time
+  percent-cpu-time
+  percent-cons)
+
+(defun group-on (list &key (test #'eql) (key #'identity) (include-key t))
+  (let ((hash (make-hash-table :test test))
+        keys)
+    (dolist (el list)
+      (let ((key (funcall key el)))
+        (unless (nth-value 1 (gethash key hash))
+          (push key keys))
+        (push el (gethash key hash))))    
+    (mapcar (lambda (key) (let ((keys (nreverse (gethash key hash))))
+                            (if include-key
+                                (cons key keys)
+                                keys)))
+            (nreverse keys))))
+
+(defun get-postprocessed (&key (by-process t) reset sort-by)
+  "Collect profiling results from all processes and compress them for
+   display, return a list of lists of PROFILE-RESULTS.  BY-PROCESS
+   determines whether the report will be per process or one report for
+   all processes combined."
+  (labels
+      ((percentage (value total)
+         (if (and (plusp value) (plusp total))
+           (/ value (/ total 100))
+           0))
+       (postprocess (records)
+         (let ((total-real-time 0)
+               (total-cpu-time 0)
+               (total-cons 0))
+           (dolist (record records)
+             (incf total-real-time (fcr-exclusive-real-time record))
+             (incf total-cpu-time (fcr-exclusive-cpu-time record))
+             (incf total-cons (fcr-exclusive-cons record)))
+           (sort (mapcar (lambda (fcr)
+                           (make-profile-results (let ((*package* (find-package :keyword)))
+                                                   (prin1-to-string (fcr-name fcr)))
+                                                 (fcr-process fcr)
+                                                 (fcr-calls fcr)
+                                                 (fcr-exclusive-real-time fcr)
+                                                 (fcr-exclusive-cpu-time fcr)
+                                                 (fcr-exclusive-cons fcr)
+                                                 (percentage (fcr-exclusive-real-time fcr) total-real-time)
+                                                 (percentage (fcr-exclusive-cpu-time fcr) total-cpu-time)
+                                                 (percentage (fcr-exclusive-cons fcr) total-cons)))
+                         records)
+                 #'<
+                 :key sort-by))))
+    (if by-process
+      (mapcar #'postprocess
+              (group-on (collect-profiling-results :reset reset)
+                        :key #'fcr-process
+                        :test #'eq
+                        :include-key nil))
+      (list (postprocess (mapcar #'sum-fcrs (group-on (collect-profiling-results :reset reset)
+                                                      :key #'fcr-name
+                                                      :test #'eq
+                                                      :include-key nil)))))))
+
+(defun sort-key-function (keyword)
+  (let ((valid-sort-keys (append '(:calls
+                                   :cons :percent-cons
+                                   :real-time :percent-real-time)
+                                 (when *can-report-cpu*
+                                   '(:cpu-time :percent-cpu-time)))))
+    (unless (member keyword valid-sort-keys)
+      (error "invalid sort key ~S, specify one of ~S"
+             keyword valid-sort-keys))
+    (fdefinition (find-symbol (format nil "PR-~A" keyword) :profiler))))
+
+(defun report (&key
+               (threshold 0.01)
+               (by-process t)
+               (stream *trace-output*)
+               (report-cpu *can-report-cpu*)
+               (sort-by (if *can-report-cpu* :cpu-time :real-time))
+               report-overhead)
+  (labels
+      ((do-report (records)
+         (let ((max-length 8)           ; Function header size
+               (max-cons-length 8)
+               (max-colon-pos 0)        ; Maximum offset of a colon in any name
+               (total-real-time 0)
+               (total-cpu-time 0)
+               (total-consed 0)
+               (total-calls 0)
+               (total-percent-real-time 0)
+               (total-percent-cpu-time 0)
+               (total-percent-cons 0))
+           (dolist (result records)
+             (when (or (zerop threshold)
+                       (> (pr-percent-real-time result) threshold))
+               (setq max-colon-pos
+                     (max max-colon-pos
+                          (position #\: (pr-name result))))
+               (setq max-length
+                     (max max-length
+                          (length (pr-name result))))
+               (setq max-cons-length
+                     (max max-cons-length
+                          (/ (pr-cons result) (pr-calls result))))))
+           (incf max-length 2)
+           (setf max-cons-length (max 4 (ceiling (log max-cons-length 10))))
+           (format stream
+                   "~
+             ~&   %      ~@[~* %      ~]                          ~@[~*          ~]~V@A~
+	     ~%  Real    ~@[~*CPU     ~] %             Real Time  ~@[~*CPU Time  ~]~V@A      Total  ~@[~*   Total  ~]     Total~
+	     ~%  Time    ~@[~*Time    ~]Cons    Calls      /Call  ~@[~*   /Call  ~]~V@A  Real Time  ~@[~*CPU Time  ~]      Cons  Name~
+             ~%~V,,,'-A"
+                   report-cpu report-cpu max-cons-length "Cons"
+                   report-cpu report-cpu max-cons-length "Per"  report-cpu
+                   report-cpu report-cpu max-cons-length "Call" report-cpu
+                   (+ max-length (if report-cpu 92 64) (max 0 (- max-cons-length 5))) "-")
+           (dolist (result records)
+             (when (or (zerop threshold)
+                       (> (pr-percent-real-time result) threshold))
+               (format stream
+                       "~%~6,2F  ~@[~6,2F  ~]~6,2F  ~7D   ~8@A  ~@[~8@A  ~]~VD   ~8@A  ~@[~8@A  ~]~10D  ~V@A"
+                       (pr-percent-real-time result)
+                       (and report-cpu (pr-percent-cpu-time result))
+                       (pr-percent-cons result)
+                       (pr-calls result)
+                       (format-time (/ (pr-real-time result) (pr-calls result)))
+                       (and report-cpu (format-time (/ (pr-cpu-time result) (pr-calls result))))
+                       max-cons-length
+                       (floor (/ (pr-cons result) (pr-calls result)))
+                       (format-time (pr-real-time result))
+                       (and report-cpu (format-time (pr-cpu-time result)))
+                       (pr-cons result)
+                       (+ (length (pr-name result))
+                          (- max-colon-pos (position #\: (pr-name result))))
+                       (pr-name result))
+               (incf total-real-time (pr-real-time result))
+               (incf total-cpu-time (pr-cpu-time result))
+               (incf total-consed (pr-cons result))
+               (incf total-calls (pr-calls result))
+               (incf total-percent-real-time (pr-percent-real-time result))
+               (incf total-percent-cpu-time (pr-percent-cpu-time result))
+               (incf total-percent-cons (pr-percent-cons result))))
+           (format stream
+                   "~%~V,,,'-A~
+	    ~%~6,2F  ~@[~6,2F  ~]~6,2F  ~7D  ~9@T ~VA~@[~*          ~]    ~8@A~@[  ~8@A~]  ~10D~%"
+                   (+ max-length (if report-cpu 92 64) (max 0 (- max-cons-length 5))) "-"
+                   total-percent-real-time
+                   (and report-cpu total-percent-cpu-time)
+                   total-percent-cons
+                   total-calls
+                   max-cons-length " "
+                   report-cpu
+                   (format-time total-real-time)
+                   (and report-cpu (format-time total-cpu-time))
+                   total-consed)
+           (when report-overhead
+             (format stream "Estimated monitoring overhead: real: ~A cons: ~A~%"
+                   (format-time (* *real-overhead* total-calls))
+                   (* *cons-overhead* total-calls)))
+           (terpri stream)
+           (values))))
+    (dolist (results (get-postprocessed :by-process by-process
+                                        :sort-by (sort-key-function sort-by)))
+      (if by-process
+          (format stream "Profile results for process ~A~%~%" (pr-process (car results)))
+          (format stream "Profile results combined for all profiledy processes~%~%"))
+      (do-report results))
+    (when (and *can-report-cpu* *clock-errors*)
+      (format stream "Warning: real time and CPU time clocks are inconsistent.~%"))))
Index: /branches/new-random/tools/asdf-install/.cvsignore
===================================================================
--- /branches/new-random/tools/asdf-install/.cvsignore	(revision 13309)
+++ /branches/new-random/tools/asdf-install/.cvsignore	(revision 13309)
@@ -0,0 +1,3 @@
+asdf-install
+test-passed
+*~.*
Index: /branches/new-random/tools/asdf-install/COPYRIGHT
===================================================================
--- /branches/new-random/tools/asdf-install/COPYRIGHT	(revision 13309)
+++ /branches/new-random/tools/asdf-install/COPYRIGHT	(revision 13309)
@@ -0,0 +1,47 @@
+The original ASDF-INSTALL code (the files Makefile, README,
+asdf-install.asd, defpackage.lisp, and installer.lisp) was written by
+Daniel Barlow <dan@telent.net> and is distributed with SBCL and
+therefore in the public domain.  The SBCL Common Lisp implementation
+can be obtained from Sourceforge: <http://sbcl.sf.net/>.
+
+The initial port of ASDF-INSTALL to other Lisps was done by Dr. Edmund
+Weitz <edi@agharta.de> and included the file port.lisp and some
+changes to the files mentioned above.  More code was provided by Marco
+Baringer <mb@bese.it> (OpenMCL port), James Anderson
+<james.anderson@setf.de> (MCL port, including the file digitool.lisp),
+Kiyoshi Mizumaru <maru@krc.sony.co.jp>, Robert P. Goldman
+<rpgoldman@sift.info>, and Raymond Toy <toy@rtp.ericsson.se>
+(bugfixes).  Marco Antoniotti <marcoxa@cs.nyu.edu> added support for
+MK:DEFSYSTEM which includes the files load-asdf-install.lisp,
+loader.lisp, and finally split-sequence.lisp which has its own
+copyright notice. ASDF-Install is currently maintained by Gary King
+<gwking@metabang.com> and is hosted on Common-Lisp.net.
+
+The complete code distributed with this archive (asdf-install.tar.gz)
+is copyrighted by the above-mentioned authors and governed by the
+following 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 AUTHORS 'AS IS' AND ANY EXPRESSED 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 AUTHORS 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.
+
Index: /branches/new-random/tools/asdf-install/Makefile
===================================================================
--- /branches/new-random/tools/asdf-install/Makefile	(revision 13309)
+++ /branches/new-random/tools/asdf-install/Makefile	(revision 13309)
@@ -0,0 +1,13 @@
+SYSTEM=asdf-install
+EXTRA_INSTALL_TARGETS=asdf-install-install
+
+include ../asdf-module.mk
+
+asdf-install-install: asdf-install
+	if test -f $(BUILD_ROOT)$(INSTALL_ROOT)/bin/sbcl-asdf-install ; then \
+	  mv $(BUILD_ROOT)$(INSTALL_ROOT)/bin/sbcl-asdf-install $(BUILD_ROOT)$(INSTALL_ROOT)/bin/sbcl-asdf-install.old ; \
+	fi
+# KLUDGE: mv rather than cp because keeping asdf-install in that
+# directory interferes with REQUIRE, and this is done before the tar 
+# in ../asdf-module.mk.  Better solutions welcome.
+	mv asdf-install $(BUILD_ROOT)$(INSTALL_ROOT)/bin/sbcl-asdf-install
Index: /branches/new-random/tools/asdf-install/README
===================================================================
--- /branches/new-random/tools/asdf-install/README	(revision 13309)
+++ /branches/new-random/tools/asdf-install/README	(revision 13309)
@@ -0,0 +1,121 @@
+Downloads and installs an ASDF or a MK:DEFSYSTEM system or anything
+else that looks convincingly like one. It updates the
+ASDF:*CENTRAL-REGISTRY* symlinks for all the toplevel .asd files it
+contains, and it also MK:ADD-REGISTRY-LOCATION for the appropriate
+directories for MK:DEFSYSTEM.
+
+Please read this file before use: in particular: this is an automatic
+tool that downloads and compiles stuff it finds on the 'net.  Please
+look at the SECURITY section and be sure you understand the
+implications
+
+
+= USAGE
+
+This can be used either from within a CL implementation:
+
+cl-prompt> (load "/path/to/load-asdf-install.lisp")
+cl-prompt> (asdf-install:install 'xlunit) ; for example
+
+With SBCL you can also use the standalone command `sbcl-asdf-install'
+from the shell:
+
+$ sbcl-asdf-install xlunit
+
+
+Each argument may be -
+
+ - The name of a cliki page.  asdf-install visits that page and finds
+   the download location from the `:(package)' tag - usually rendered
+   as "Download ASDF package from ..."
+
+ - A URL, which is downloaded directly
+
+ - A local tar.gz file, which is installed
+
+
+= SECURITY CONCERNS: READ THIS CAREFULLY
+
+When you invoke asdf-install, you are asking your CL implementation to
+download, compile, and install software from some random site on the
+web.  Given that it's indirected through a page on CLiki, any
+malicious third party doesn't even need to hack the distribution
+server to replace the package with something else: he can just edit
+the link.
+
+For this reason, we encourage package providers to crypto-sign their
+packages (see details at the URL in the PACKAGE CREATION section) and
+users to check the signatures.  asdf-install has three levels of
+automatic signature checking: "on", "off" and "unknown sites", which
+can be set using the configuration variables described in
+CUSTOMIZATION below.  The default is "unknown sites", which will
+expect a GPG signature on all downloads except those from
+presumed-good sites.  The current default presumed-good sites are
+CCLAN nodes, and two web sites run by SBCL maintainers: again, see
+below for customization details
+
+
+= CUSTOMIZATION
+
+If the file $HOME/.asdf-install exists, it is loaded.  This can be
+used to override the default values of exported special variables.
+Presently these are 
+
+*PROXY*         
+   defaults to $http_proxy environment variable
+*CCLAN-MIRROR*        
+   preferred/nearest CCLAN node.  See the list at 
+   http://ww.telent.net/cclan-choose-mirror
+*ASDF-INSTALL-DIRS*
+   Set from ASDF_INSTALL_DIR environment variable.  If you are running
+   SBCL, then *ASDF-INSTALL-DIRS* may be set form the environment variable
+   SBCL_HOME, which should already be correct for whatever SBCL is
+   running, if it's been installed correctly.  This is done for
+   backward compatibility with SBCL installations.
+*SBCL-HOME*
+   This is actually a symbol macro for *ASDF-INSTALL-DIRS*
+*VERIFY-GPG-SIGNATURES*
+   Verify GPG signatures for the downloaded packages?
+   NIL - no, T - yes, :UNKNOWN-LOCATIONS - only for URLs which aren't in CCLAN
+   and don't begin with one of the prefixes in *SAFE-URL-PREFIXES*
+*LOCATIONS*
+   Possible places in the filesystem to install packages into.  See default
+   value for format
+*SAFE-URL-PREFIXES* 
+   List of locations for which GPG signature checking /won't/ be done when
+   *verify-gpg-signatures* is :unknown-locations
+
+
+= PACKAGE CREATION
+
+If you want to create your own packages that can be installed using this
+loader, see the "Making your package downloadable..." section at
+<http://www.cliki.net/asdf-install> 
+
+
+= HACKERS NOTE
+
+Listen very carefully: I will say this only as often as it appears to
+be necessary to say it.  asdf-install is not a good example of how to
+write a URL parser, HTTP client, or anything else, really.
+Well-written extensible and robust URL parsers, HTTP clients, FTP
+clients, etc would definitely be nice things to have, but it would be
+nicer to have them in CCLAN where anyone can use them - after having
+downloaded them with asdf-install - than in SBCL contrib where they're
+restricted to SBCL users and can only be updated once a month via SBCL
+developers.  This is a bootstrap tool, and as such, will tend to
+resist changes that make it longer or dependent on more other
+packages, unless they also add to its usefulness for bootstrapping.
+
+
+= TODO
+
+a) gpg signature checking would be better if it actually checked against
+a list of "trusted to write Lisp" keys, instead of just "trusted to be
+who they say they are"
+
+e) nice to have: resume half-done downloads instead of starting from scratch
+every time.  but right now we're dealing in fairly small packages, this is not
+an immediate concern
+
+
Index: /branches/new-random/tools/asdf-install/RELNOTES
===================================================================
--- /branches/new-random/tools/asdf-install/RELNOTES	(revision 13309)
+++ /branches/new-random/tools/asdf-install/RELNOTES	(revision 13309)
@@ -0,0 +1,5 @@
+12 Sept 2006 gwking@metabang.com
+
+   * added :where parameter to install
+   * now uses more tempoary files
+   * changed selection of locations - 0 is always abort, can use symbols / strings
Index: /branches/new-random/tools/asdf-install/asdf-install.asd
===================================================================
--- /branches/new-random/tools/asdf-install/asdf-install.asd	(revision 13309)
+++ /branches/new-random/tools/asdf-install/asdf-install.asd	(revision 13309)
@@ -0,0 +1,52 @@
+;;; -*-  Lisp -*-
+
+;;; Portatble ASDF-Install is based on Dan Barlow's ASDF-Install 
+;; (see the file COPYRIGHT for details). It is currently maintained
+;; by Gary King <gwking@metabang.com>.
+
+(defpackage #:asdf-install-system 
+  (:use #:cl #:asdf))
+
+(in-package #:asdf-install-system)
+
+(defsystem asdf-install
+  #+:sbcl :depends-on
+  #+:sbcl (sb-bsd-sockets)
+  :version "0.6.10"
+  :author "Dan Barlow <dan@telent.net>, Edi Weitz <edi@agharta.de> and many others. See the file COPYRIGHT for more details."
+  :maintainer "Gary Warren King <gwking@metabang.com>"
+  :components ((:file "defpackage")
+               (:file "split-sequence" :depends-on ("defpackage"))
+               
+               (:file "port" :depends-on ("defpackage"))
+               #+:digitool
+               (:file "digitool" :depends-on ("port"))
+               
+	       (:file "conditions" :depends-on ("defpackage" "variables"))
+               (:file "variables" :depends-on ("port"))
+	       (:file "installer"
+                      :depends-on ("port" "split-sequence" 
+					  #+:digitool "digitool"
+					  "conditions" "variables"))
+               (:file "deprecated" :depends-on ("installer")))
+  :in-order-to ((test-op (load-op test-asdf-install)))
+  :perform (test-op :after (op c)
+		    (funcall
+		      (intern (symbol-name '#:run-tests) :lift)
+		      :config :generic)))
+	   
+(defmethod perform :after ((o load-op) (c (eql (find-system :asdf-install))))
+  (let ((show-version (find-symbol
+                       (symbol-name '#:show-version-information)
+		       '#:asdf-install)))
+    (when (and show-version (fboundp show-version)) 
+      (funcall show-version)))
+  (provide 'asdf-install))
+
+(defmethod operation-done-p 
+    ((o test-op) (c (eql (find-system :asdf-install))))
+  nil)
+
+#+(or)
+(defmethod perform ((o test-op) (c (eql (find-system :asdf-install))))
+  t)
Index: /branches/new-random/tools/asdf-install/changes.text
===================================================================
--- /branches/new-random/tools/asdf-install/changes.text	(revision 13309)
+++ /branches/new-random/tools/asdf-install/changes.text	(revision 13309)
@@ -0,0 +1,2 @@
+Gary King 2006-04-25: removed unused bits of split-sequence and split-sequence package
+Gary King 2006-04-25: pulled conditions into their own file
Index: /branches/new-random/tools/asdf-install/conditions.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/conditions.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/conditions.lisp	(revision 13309)
@@ -0,0 +1,82 @@
+(in-package #:asdf-install)
+
+(define-condition download-error (error)
+  ((url :initarg :url :reader download-url)
+   (response :initarg :response :reader download-response))
+  (:report (lambda (c s)
+	     (format s "Server responded ~A for GET ~A"
+		     (download-response c) (download-url c)))))
+
+(define-condition signature-error (error)
+  ((cause :initarg :cause :reader signature-error-cause))
+  (:report (lambda (c s)
+	     (format s "Cannot verify package signature:  ~A"
+		     (signature-error-cause c)))))
+
+(define-condition gpg-error (error)
+  ((message :initarg :message :reader gpg-error-message))
+  (:report (lambda (c s)
+	     (format s "GPG failed with error status:~%~S"
+		     (gpg-error-message c)))))
+
+(define-condition gpg-shell-error (gpg-error)
+  ()
+  (:report (lambda (c s)
+             (declare (ignore c))
+             (format s "Call to GPG failed. Perhaps GPG is not installed or not ~
+in the path."))))
+
+(define-condition no-signature (gpg-error) ())
+
+(define-condition key-not-found (gpg-error)
+  ((key-id :initarg :key-id :reader key-id))
+  (:report (lambda (c s)
+	     (let* ((*print-circle* nil)
+		    (key-id (key-id c))
+		    (key-id (if (and (consp key-id) 
+				     (> (length key-id) 1))
+				(car key-id) key-id)))
+	       (format s "~&No key found for key id 0x~A.~%" key-id)
+	       (format s "~&Try some command like ~%  gpg  --recv-keys 0x~A"
+		       (format nil "~a" key-id))))))
+
+(define-condition key-not-trusted (gpg-error)
+  ((key-id :initarg :key-id :reader key-id)
+   (key-user-name :initarg :key-user-name :reader key-user-name))
+  (:report (lambda (c s)
+	     (format s "GPG warns that the key id 0x~A (~A) is not fully trusted"
+		     (key-id c) (key-user-name c)))))
+
+(define-condition author-not-trusted (gpg-error)
+  ((key-id :initarg :key-id :reader key-id)
+   (key-user-name :initarg :key-user-name :reader key-user-name))
+  (:report (lambda (c s)
+	     (format s "~A (key id ~A) is not on your package supplier list"
+		     (key-user-name c) (key-id c)))))
+  
+(define-condition installation-abort (condition)
+  ()
+  (:report (lambda (c s)
+             (declare (ignore c))
+             (installer-msg s "Installation aborted."))))
+
+(defun report-valid-preferred-locations (stream &optional attempted-location)
+  (when attempted-location
+    (installer-msg stream "~s is not a valid value for *preferred-location*"
+		   attempted-location))
+  (installer-msg stream "*preferred-location* may either be nil, a number between 1 and ~d \(the length of *locations*\) or the name of one of the *locations* \(~{~s~^, ~}\). If using a name, then it can be a symbol tested with #'eq or a string tested with #'string-equal."
+		 (length *locations*)
+		 (mapcar #'third *locations*)))
+
+(define-condition invalid-preferred-location-error (error)
+  ((preferred-location :initarg :preferred-location))
+  (:report (lambda (c s)
+	     (report-valid-preferred-locations 
+	      s (slot-value c 'preferred-location)))))
+
+(define-condition invalid-preferred-location-number-error 
+    (invalid-preferred-location-error) ())
+
+(define-condition invalid-preferred-location-name-error 
+    (invalid-preferred-location-error) ())
+
Index: /branches/new-random/tools/asdf-install/dead-letter.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/dead-letter.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/dead-letter.lisp	(revision 13309)
@@ -0,0 +1,34 @@
+;;;; dead letter
+
+#+Old
+(defun load-system-definition (sysfile)
+  (declare (type pathname sysfile))
+  #+asdf
+  (when (or (string-equal "asd" (pathname-type sysfile))
+            (string-equal "asdf" (pathname-type sysfile)))
+    (installer-msg t "Loading system ~S via ASDF." (pathname-name sysfile))
+    ;; just load the system definition
+    (load sysfile)
+    #+Ignore
+    (asdf:operate 'asdf:load-op (pathname-name sysfile)))
+
+  #+mk-defsystem
+  (when (string-equal "system" (pathname-type sysfile))
+    (installer-msg t "Loading system ~S via MK:DEFSYSTEM." (pathname-name sysfile))
+    (mk:load-system (pathname-name sysfile))))
+
+#+Old
+;; from download-files-for-package
+(with-open-file 
+    #-(and allegro-version>= (not (version>= 8 0)))
+    (o file-name :direction :output
+       #+(or :clisp :digitool (and :lispworks :win32))
+       :element-type
+       #+(or :clisp :digitool (and :lispworks :win32))
+       '(unsigned-byte 8)
+       #+:sbcl #+:sbcl :external-format :latin1
+       :if-exists :supersede)
+    ;; for Allegro  versions  < 8.0,  the above  #+sbcl #+sbcl
+    ;; will cause an error [2006/01/09:rpg]
+    #+(and allegro-version>= (not (version>= 8 0)))
+    (o file-name :direction :output :if-exists :supersede))
Index: /branches/new-random/tools/asdf-install/defpackage.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/defpackage.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/defpackage.lisp	(revision 13309)
@@ -0,0 +1,59 @@
+(cl:in-package :cl-user)
+
+(defpackage #:asdf-install
+  (:use #:common-lisp)
+  
+  #+asdf
+  (:import-from #:asdf #:*defined-systems*)
+  (:export
+
+   ;; Customizable variables.
+   #:*shell-path*
+   #:*proxy*
+   #:*cclan-mirror*
+   #:asdf-install-dirs
+   #:private-asdf-install-dirs
+   #:*tar-extractors*
+
+   #:*shell-search-paths*
+   #:*verify-gpg-signatures*
+   #:*locations*
+   #:*safe-url-prefixes*
+   #:*preferred-location*
+   #:*temporary-directory*
+   
+   ;; External entry points.   
+   #:add-locations
+   #:add-registry-location
+   #:uninstall
+   #:install
+   #:asdf-install-version
+
+   #+(and asdf (or :win32 :mswindows))
+   #:sysdef-source-dir-search   
+   
+   ;; proxy authentication
+   #:*proxy-user*
+   #:*proxy-passwd*
+   
+   ;; conditions
+   #:download-error
+   #:signature-error
+   #:gpg-error
+   #:gpg-shell-error
+   #:key-not-found
+   #:key-not-trusted
+   #:author-not-trusted
+   #:installation-abort
+
+   ;; restarts
+   #:install-anyways
+   )
+  
+  #+(or :win32 :mswindows)
+  (:export
+   #:*cygwin-bin-directory*
+   #:*cygwin-bash-command*))
+
+(defpackage #:asdf-install-customize
+  (:use #:common-lisp #:asdf-install))
Index: /branches/new-random/tools/asdf-install/deprecated.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/deprecated.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/deprecated.lisp	(revision 13309)
@@ -0,0 +1,216 @@
+(in-package asdf-install)
+
+#+(and ignore sbcl) ; Deprecated.
+(define-symbol-macro *sbcl-home* *asdf-install-dirs*)
+
+#+(and ignore sbcl) ; Deprecated.
+(define-symbol-macro *dot-sbcl* *private-asdf-install-dirs*)
+
+#+(or)
+;; uncalled
+(defun read-until-eof (stream)
+  (with-output-to-string (o)
+    (copy-stream stream o)))
+
+
+#+(or)
+(defun verify-gpg-signature/string (string file-name)
+  (block verify
+    (loop
+      (restart-case
+        (let ((gpg-stream (make-stream-from-gpg-command string file-name))
+              tags)
+          (unwind-protect
+            (loop for l = (read-line gpg-stream nil nil)
+                  while l
+                  do (print l)
+                  when (> (mismatch l "[GNUPG:]") 6)
+                  do (destructuring-bind (_ tag &rest data)
+                                         (split-sequence-if (lambda (x)
+                                                              (find x '(#\Space #\Tab)))
+                                                            l)
+	               (declare (ignore _))
+                       (pushnew (cons (intern (string-upcase tag) :keyword)
+			              data) tags)))
+            (ignore-errors
+             (close gpg-stream)))
+          ;; test that command returned something 
+          (unless tags
+            (error 'gpg-shell-error))
+          ;; test for obvious key/sig problems
+          (let ((errsig (header-value :errsig tags)))
+            (and errsig (error 'key-not-found :key-id errsig)))
+          (let ((badsig (header-value :badsig tags)))
+            (and badsig (error 'key-not-found :key-id badsig)))
+          (let* ((good (header-value :goodsig tags))
+	         (id (first good))
+	         (name (format nil "~{~A~^ ~}" (rest good))))
+            ;; good signature, but perhaps not trusted
+            (restart-case
+              (let ((trusted? (or (header-pair :trust_ultimate tags)
+                                  (header-pair :trust_fully tags)))
+                    (in-list? (assoc id *trusted-uids* :test #'equal)))
+                (cond ((or trusted? in-list?)
+                       ;; ok
+                       )
+                      ((not trusted?)
+                       (error 'key-not-trusted :key-user-name name :key-id id))
+                      ((not in-list?)
+                       (error 'author-not-trusted
+                         :key-user-name name :key-id id))
+                      (t
+                       (error "Boolean logic gone bad. Run for the hills"))))
+              (add-key (&rest rest)
+                       :report "Add to package supplier list"
+                       (declare (ignore rest))
+                       (pushnew (list id name) *trusted-uids*))))
+          (return-from verify t))
+        #+Ignore
+        (install-anyways (&rest rest)
+	                       :report "Don't check GPG signature for this package"
+                               (declare (ignore rest))
+	                       (return-from verify t))
+        (retry-gpg-check (&rest args)
+                         :report "Retry GPG check \(e.g., after downloading the key\)"
+                         (declare (ignore args))
+                         nil)))))
+
+#+(or)
+(defun verify-gpg-signature/url (url file-name)
+  (block verify
+    (loop
+      (restart-case
+        (when (verify-gpg-signatures-p url)
+          (let ((sig-url (concatenate 'string url ".asc")))
+            (destructuring-bind (response headers stream)
+                                (url-connection sig-url)
+              (unwind-protect
+                (flet (#-:digitool
+                       (read-signature (data stream)
+                         (read-sequence data stream))
+                       #+:digitool
+                       (read-signature (data stream)
+                         (multiple-value-bind (reader arg)
+                                              (ccl:stream-reader stream)
+                           (let ((byte 0))
+                             (dotimes (i (length data))
+                               (unless (setf byte (funcall reader arg))
+                                 (error 'download-error :url sig-url
+                                        :response 200))
+                               (setf (char data i) (code-char byte)))))))
+                  (if (= response 200)
+                    (let ((data (make-string (parse-integer
+                                              (header-value :content-length headers)
+                                              :junk-allowed t))))
+                      (read-signature data stream)
+                      (verify-gpg-signature/string data file-name))
+                    (error 'download-error :url sig-url
+                           :response response)))
+                (close stream)
+                (return-from verify t)))))
+        (install-anyways (&rest rest)
+                         :report "Don't check GPG signature for this package"
+                         (declare (ignore rest))
+                         (return-from verify t))
+        (retry-gpg-check (&rest args)
+                         :report "Retry GPG check \(e.g., after fixing the network connection\)"
+                         (declare (ignore args))
+                         nil)))))
+
+
+#+(or :sbcl :cmu :scl)
+(defun make-stream-from-gpg-command (string file-name)
+  (#+:sbcl sb-ext:process-output
+   #+(or :cmu :scl) ext:process-output
+   (#+:sbcl sb-ext:run-program
+    #+(or :cmu :scl) ext:run-program
+    "gpg"
+    (list
+     "--status-fd" "1" "--verify" "-"
+     (namestring file-name))
+    :output :stream
+    :error nil
+    #+sbcl :search #+sbcl t
+    :input (make-string-input-stream string)
+    :wait t)))
+
+#+(and :lispworks (not :win32))
+(defun make-stream-from-gpg-command (string file-name)
+  ;; kludge - we can't separate the in and out streams
+  (let ((stream (sys:open-pipe (format nil "echo '~A' | gpg --status-fd 1 --verify - ~A"
+                                       string
+                                       (namestring file-name)))))
+    stream))
+
+
+#+(and :lispworks :win32)
+(defun make-stream-from-gpg-command (string file-name)
+  (sys:open-pipe (format nil "gpg --status-fd 1 --verify \"~A\" \"~A\""
+                         (make-temp-sig file-name string)
+                         (namestring file-name))))
+
+#+(and :clisp (not (or :win32 :cygwin)))
+(defun make-stream-from-gpg-command (string file-name)
+  (let ((stream
+         (ext:run-shell-command (format nil "echo '~A' | gpg --status-fd 1 --verify - ~A"
+                                        string
+                                        (namestring file-name))
+                                :output :stream
+                                :wait nil)))
+    stream))
+
+#+(and :clisp (or :win32 :cygwin))
+(defun make-stream-from-gpg-command (string file-name)
+  (ext:run-shell-command (format nil "gpg --status-fd 1 --verify \"~A\" \"~A\""
+                                 (make-temp-sig file-name string)
+                                 (namestring file-name))
+                         :output :stream
+                         :wait nil))
+
+#+:allegro
+(defun make-stream-from-gpg-command (string file-name)
+  (multiple-value-bind (in-stream out-stream)
+                       (excl:run-shell-command
+                        #-:mswindows
+                        (concatenate 'vector
+                                     #("gpg" "gpg" "--status-fd" "1" "--verify" "-")
+                                     (make-sequence 'vector 1
+                                                    :initial-element (namestring file-name)))
+                        #+:mswindows
+                        (format nil "gpg --status-fd 1 --verify - \"~A\"" (namestring file-name))
+                        :input :stream
+                        :output :stream
+                        :separate-streams t
+                        :wait nil)
+    (write-string string in-stream)
+    (finish-output in-stream)
+    (close in-stream)
+    out-stream))
+
+#+:openmcl
+(defun make-stream-from-gpg-command (string file-name)
+  (let ((proc (ccl:run-program "gpg" (list "--status-fd" "1" "--verify" "-" (namestring file-name))
+                               :input :stream
+                               :output :stream
+                               :wait nil)))
+    (write-string string (ccl:external-process-input-stream proc))
+    (close (ccl:external-process-input-stream proc))
+    (ccl:external-process-output-stream proc)))
+
+#+:digitool
+(defun make-stream-from-gpg-command (string file-name)
+  (make-instance 'popen-input-stream
+    :command (format nil "echo '~A' | gpg --status-fd 1 --verify - '~A'"
+                     string
+                     (system-namestring file-name))))
+
+#+(or)
+(defun make-temp-sig (file-name content)
+  (let ((name (format nil "~A.asc" (namestring (truename file-name)))))
+    (with-open-file (out name
+                         :direction :output
+                         :if-exists :supersede)
+      (write-string content out))
+    (pushnew name *temporary-files*)
+    name))
+
Index: /branches/new-random/tools/asdf-install/digitool.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/digitool.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/digitool.lisp	(revision 13309)
@@ -0,0 +1,230 @@
+;;; -*- package: asdf-install; -*-
+;;;
+;;; Digitool-specific bootstrapping
+;;;
+;;; 2004-01-18 james.anderson@setf.de additions for MCL
+;;; 2008-01-22 added exit-code checks to call-system
+
+(in-package #:asdf-install)
+
+#+:digitool
+(let ((getenv-fn 0)
+      (setenv-fn 0)
+      (unsetenv-fn 0)
+      (popen-fn 0)
+      (pclose-fn 0)
+      (fread-fn 0)
+      (feof-fn 0))
+  (ccl::with-cfstrs ((framework "System.framework"))
+    (let ((err 0)
+          (baseURL nil)
+          (bundleURL nil)
+          (bundle nil))
+      (ccl::rlet ((folder :fsref))
+        ;; Find the folder holding the bundle
+        (setf err (ccl::require-trap traps::_FSFindFolder
+                                     (ccl::require-trap-constant traps::$kOnAppropriateDisk)
+                                     (ccl::require-trap-constant traps::$kFrameworksFolderType)
+                                     t folder))
+        ;; if everything's cool, make a URL for it
+        (when (zerop err)
+          (setf baseURL (ccl::require-trap traps::_CFURLCreateFromFSRef (ccl::%null-ptr) folder)))
+        (if (ccl::%null-ptr-p baseURL)
+          (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr))))
+      ;; if everything's cool, make a URL for the bundle
+      (when (zerop err)
+        (setf bundleURL (ccl::require-trap traps::_CFURLCreateCopyAppendingPathComponent (ccl::%null-ptr) baseURL framework nil))
+        (if (ccl::%null-ptr-p bundleURL)
+          (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr))))
+      ;; if everything's cool, create it
+      (when (zerop err)
+        (setf bundle (ccl::require-trap traps::_CFBundleCreate (ccl::%null-ptr) bundleURL))
+        (if (ccl::%null-ptr-p bundle)
+          (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr))))
+      ;; if everything's cool, load it
+      (when (zerop err)
+        (if (not (ccl::require-trap traps::_CFBundleLoadExecutable bundle))
+          (setf err (ccl::require-trap-constant traps::$coreFoundationUnknownErr))))
+      ;; if there's an error, but we've got a pointer, free it and clear result
+      (when (and (not (zerop err)) (not (ccl::%null-ptr-p bundle)))
+        (ccl::require-trap traps::_CFRelease bundle)
+        (setf bundle nil))
+      ;; free the URLs if here non-null
+      (when (not (ccl::%null-ptr-p bundleURL))
+        (ccl::require-trap traps::_CFRelease bundleURL))
+      (when (not (ccl::%null-ptr-p baseURL))
+        (ccl::require-trap traps::_CFRelease baseURL))
+      (cond (bundle
+             ;; extract the necessary function id's
+             (flet ((get-addr (name)
+                      (ccl::with-cfstrs ((c-name name))
+                        (let* ((addr (ccl::require-trap traps::_CFBundleGetFunctionPointerForName bundle c-name)))
+                          (when (ccl::%null-ptr-p addr)
+                            (error "Couldn't resolve address of foreign function ~s" name))
+                          (ccl::rlet ((buf :long))
+                            (setf (ccl::%get-ptr buf) addr)
+                            (ash (ccl::%get-signed-long buf) -2))))))
+               (setf getenv-fn (get-addr "getenv"))
+               (setf setenv-fn (get-addr "setenv"))
+               (setf unsetenv-fn (get-addr "unsetenv"))
+               (setf popen-fn (get-addr "popen"))
+               (setf pclose-fn (get-addr "pclose"))
+               (setf fread-fn (get-addr "fread"))
+               (setf feof-fn (get-addr "feof")))
+             (ccl::require-trap traps::_CFRelease bundle)
+             (setf bundle nil))
+            (t
+             (error "can't resolve core framework entry points.")))))
+  
+  (defun ccl::getenv (variable-name)
+    (ccl::with-cstrs ((c-variable-name variable-name))
+      (let* ((env-ptr (ccl::%null-ptr)))
+        (declare (dynamic-extent env-ptr))
+        (ccl::%setf-macptr env-ptr (ccl::ppc-ff-call getenv-fn
+                                                     :address c-variable-name
+                                                     :address))
+        (unless (ccl::%null-ptr-p env-ptr)
+          (ccl::%get-cstring env-ptr)))))
+
+  (defun ccl::setenv (variable-name variable-value)
+    (ccl::with-cstrs ((c-variable-name variable-name)
+                      (c-variable-value variable-value))
+      (ccl::ppc-ff-call setenv-fn
+                        :address c-variable-name
+                        :address c-variable-value
+                        :signed-fullword 1
+                        :signed-fullword)))
+
+  (defun ccl::unsetenv (variable-name)
+    (ccl::with-cstrs ((c-variable-name variable-name))
+      (ccl::ppc-ff-call unsetenv-fn
+                        :address c-variable-name
+                        :void)))
+  
+  (labels ((fread (fp buffer length)
+             (ccl::ppc-ff-call fread-fn
+                               :address buffer
+                               :unsigned-fullword 1
+                               :unsigned-fullword length
+                               :address fp
+                               :signed-fullword))
+           (feof-p (fp)
+             (not (zerop (ccl::ppc-ff-call feof-fn
+                                           :address fp
+                                           :signed-fullword))))
+           (popen (command)
+             (ccl::with-cstrs  ((read "r")
+                                (cmd command))
+               (ccl::ppc-ff-call popen-fn
+                                 :address cmd
+                                 :address read
+                                 :address)))
+           (pclose (fp)
+             (ccl::ppc-ff-call pclose-fn
+                               :address fp
+                               :signed-fullword))
+           
+           (fread-decoded (fp io-buffer io-buffer-length string-buffer script)
+             (cond ((feof-p fp)
+                    (values nil string-buffer))
+                   (t
+                    (let ((io-count (fread fp io-buffer io-buffer-length)))
+                      (cond ((and io-count (plusp io-count))
+                             (if script
+                               (multiple-value-bind (chars fatp) (ccl::pointer-char-length io-buffer io-count script)
+                                 (cond ((not fatp)
+                                        (ccl::%copy-ptr-to-ivector io-buffer 0 string-buffer 0 io-count))
+                                       (t
+                                        (unless (>= (length string-buffer) chars)
+                                          (setf string-buffer (make-string chars :element-type 'base-character)))
+                                        (ccl::pointer-to-string-in-script io-buffer string-buffer io-count script)
+                                        (setf io-count chars))))
+                               (ccl::%copy-ptr-to-ivector io-buffer 0 string-buffer 0 io-count))
+                             (values io-count string-buffer))
+                            (t
+                             (values 0 string-buffer))))))))
+    
+    (defun ccl::call-system (command)
+      (let* ((script (ccl::default-script nil))
+             (table (ccl::get-char-byte-table script))
+             (result (make-array 128 :element-type 'character :adjustable t :fill-pointer 0))
+             (string-buffer (unless table (make-string 512 :element-type 'base-character)))
+             (io-count 0)
+             (fp (popen command))
+             (exit-code 0))
+        (unless (ccl::%null-ptr-p fp)
+          (unwind-protect
+            (ccl::%stack-block ((io-buffer 512))
+              (loop (multiple-value-setq (io-count string-buffer)
+                      (fread-decoded fp io-buffer 512 string-buffer (when table script)))
+                    (unless io-count (return))
+                    (let ((char #\null))
+                      (dotimes (i io-count)
+                        (case (setf char (schar string-buffer i))
+                          ((#\return #\linefeed) (setf char #\newline)))
+                        (vector-push-extend char result)))))
+            (setf exit-code (pclose fp))
+            (setf fp nil))
+          (if (zerop exit-code)
+            (values result 0)
+            (values nil exit-code result)))))
+    
+    ;; need a function to avoid both the reader macro and the compiler
+    (setf (symbol-function '%new-ptr) #'ccl::%new-ptr) 
+    
+    (defclass popen-input-stream (ccl::input-stream)
+      ((io-buffer :initform nil)
+       (fp :initform nil )
+       (string-buffer :initform nil)
+       (length :initform 0)
+       (index :initform 0)
+       (script :initarg :script :initform (ccl::default-script nil)))
+      (:default-initargs :direction :input))
+    
+    (defmethod initialize-instance :after ((instance popen-input-stream) &key command)
+      (with-slots (io-buffer string-buffer fp script) instance
+        (setf fp (popen command)
+              io-buffer (%new-ptr 512 nil)
+              string-buffer (make-string 512 :element-type 'base-character))
+        (when script (unless (ccl::get-char-byte-table script) (setf script nil)))))
+    
+    (defmethod ccl::stream-close ((stream popen-input-stream))
+      (declare (ignore abort))
+      (with-slots (io-buffer string-buffer fp ccl::direction) stream
+        (when (and fp (not (ccl::%null-ptr-p fp)))
+          (pclose fp)
+          (setf fp nil)
+          (setf ccl::direction :closed)
+          (ccl::disposeptr io-buffer)
+          (setf io-buffer nil))))
+    
+    (defmethod stream-element-type ((stream popen-input-stream))
+      'character)
+    
+    (defmethod ccl::stream-tyi ((stream popen-input-stream))
+      ;; despite the decoding provisions, unix input comes with linefeeds
+      ;; and i don't know what decoding one would need.
+      (with-slots (io-buffer fp string-buffer length index script) stream
+        (when fp
+          (when (>= index length)
+            (multiple-value-setq (length string-buffer)
+              (fread-decoded fp io-buffer 512 string-buffer script))
+            (unless (and length (plusp length))
+              (setf length -1)
+              (return-from ccl::stream-tyi nil))
+            (setf index 0))
+          (let ((char (schar string-buffer index)))
+            (incf index)
+            (case char
+              ((#\return #\linefeed) #\newline)
+              (t char))))))
+    
+    (defmethod ccl::stream-untyi ((stream popen-input-stream) char)
+      (with-slots (string-buffer length index) stream
+        (unless (and (plusp index) (eql char (schar (decf index) string-buffer)))
+          (error "invalid tyi character: ~s." char))
+        char))
+
+    (defmethod ccl::stream-eofp ((stream popen-input-stream))
+      (with-slots (length) stream
+        (minusp length)))))
Index: /branches/new-random/tools/asdf-install/doc/.cvsignore
===================================================================
--- /branches/new-random/tools/asdf-install/doc/.cvsignore	(revision 13309)
+++ /branches/new-random/tools/asdf-install/doc/.cvsignore	(revision 13309)
@@ -0,0 +1,1 @@
+*~.*
Index: /branches/new-random/tools/asdf-install/doc/index.html
===================================================================
--- /branches/new-random/tools/asdf-install/doc/index.html	(revision 13309)
+++ /branches/new-random/tools/asdf-install/doc/index.html	(revision 13309)
@@ -0,0 +1,1059 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html> 
+
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <title>A tutorial for ASDF-INSTALL</title>
+  <style type="text/css">
+  pre { padding:5px; background-color:#e0e0e0 }
+  a.none { text-decoration: none; color:black }
+  a.none:visited { text-decoration: none; color:black }
+  a.none:active { text-decoration: none; color:black }
+  a.none:hover { text-decoration: none; color:black }
+  a { text-decoration: none; }
+  a:visited { text-decoration: none; }
+  a:active { text-decoration: underline; }
+  a:hover { text-decoration: underline; }
+  </style>
+</head>
+
+<body bgcolor=white>
+
+<h2>A tutorial for ASDF-INSTALL</h2>
+
+<blockquote>
+<br>&nbsp;<br><h3>Abstract</h3>
+
+This tutorial is intended for people who are relatively new to Common
+Lisp. It describes an easy way to install third-party libraries into a
+Lisp implementation.
+
+</blockquote>
+
+<br>&nbsp;<br><h3><a class=none name="contents">Contents</a></h3>
+<ol>
+  <li><a href="#intro">Introduction</a>
+  <li><a href="#asdf">What is ASDF?</a>
+  <li><a href="#asdf-install">What is ASDF-INSTALL?</a>
+  <li><a href="#pre">Prerequisites</a>
+  <ol>
+    <li><a href="#install-asdf">Installing ASDF</a>
+    <li><a href="#load-asdf">Loading ASDF automatically</a>
+    <li><a href="#install-asdf-install">Installing ASDF-INSTALL</a>
+    <li><a href="#load-asdf-install">Loading ASDF-INSTALL automatically</a>
+  </ol>
+  <li><a href="#defsystem">Optional: Using MK:DEFSYSTEM instead of (or in addition to) ASDF</a>
+  <li><a href="#library">How to install a library</a>
+  <ol>
+    <li><a href="#name">Installing a library by name</a>
+    <li><a href="#url">Installing a library by URL</a>
+    <li><a href="#local">Installing from a local file</a>
+    <li><a href="#where">Where to store the library</a>
+    <li><a href="#security">The security check</a>
+  </ol>
+  <li><a href="#use">How to use an installed library</a>
+  <li><a href="#dependencies">How ASDF-INSTALL resolves dependencies</a>
+  <li><a href="#customize">Customizing ASDF-INSTALL</a>
+  <ol>
+    <li><a href="#*gnu-tar-program*">Special variable <code>*GNU-TAR-PROGRAM*</code></a>
+    <li><a href="#*proxy*">Special variable <code>*PROXY*</code></a>
+    <li><a href="#*proxy-user*">Special variable <code>*PROXY-USER*</code></a>
+    <li><a href="#*proxy-passwd*">Special variable <code>*PROXY-PASSWD*</code></a>
+    <li><a href="#*cclan-mirror*">Special variable <code>*CCLAN-MIRROR*</code></a>
+    <li><a href="#*verify-gpg-signatures*">Special variable <code>*VERIFY-GPG-SIGNATURES*</code></a>
+    <li><a href="#*safe-url-prefixes*">Special variable <code>*SAFE-URL-PREFIXES*</code></a>
+    <li><a href="#*locations*">Special variable <code>*LOCATIONS*</code></a>
+    <li><a href="#*preferred-location*">Special variable <code>*PREFERRED-LOCATION*</code></a>
+    <li><a href="#asdf-install-dir">Environment variable <code>ASDF_INSTALL_DIR</code></a>
+    <li><a href="#private-asdf-install-dir">Environment variable <code>PRIVATE_ASDF_INSTALL_DIR</code></a>
+  </ol>
+  <li><a href="#trusted-uids">The list of trusted code suppliers</a>
+  <li><a href="#uninstall">How to uninstall a library</a>
+  <li><a href="#changelog">Changelog</a>
+  <li><a href="#copyright">Copyright</a>
+  <li><a href="#license">License</a>
+</ol>
+
+<br>&nbsp;<br><h3><a class=none name="intro">Introduction</a></h3>
+
+If you're reading this you're probably already convinced that Common
+Lisp is a very fine programming language. However, while the <a
+href="http://www.lispworks.com/reference/HyperSpec/">ANSI standard</a>
+is huge and provides tons of functionality there are a couple of
+things (like, say, XML parsers, web servers, GUIs, regular
+expressions) that aren't included and must either be provided by your
+particular implementation or otherwise by a third-party library.
+<p>
+Hitherto these libraries had to be installed manually, an often
+complex process. However, many library authors are now packaging their
+systems using the new ASDF-INSTALL standard, allowing for automatic
+installation on any Lisp system that supports it.
+
+<br>&nbsp;<br><h3><a class=none name="asdf">What is ASDF?</a></h3>
+
+In order to understand what ASDF-INSTALL does we first have to
+understand what ASDF is and why we need it. <a
+href="http://www.cliki.net/asdf">ASDF</a> (&quot;Another System
+Definition Facility&quot;), written by <a
+href="http://ww.telent.net/">Daniel Barlow</a>, is a library to
+automate the compilation and loading of &quot;systems&quot;, i.e. Lisp
+programs which are usually composed of a couple of files which have to
+be compiled and loaded in a certain order. This is similar to the Unix
+<code>make</code> program. ASDF works with the majority of CL
+implementations in use today.
+<p>
+A similar system which precedes ASDF is <a
+href="http://www.cliki.net/mk-defsystem">MK:DEFSYSTEM</a>. You don't
+need it for ASDF-INSTALL but it won't hurt to have it available for
+libraries which aren't aware of ASDF. However, this document makes no
+effort to explain how MK:DEFSYSTEM is used. See Henrik Motakef's
+article &quot;<a href="http://www.henrik-motakef.de/defsystem.html">Fight The System</a>.&quot;
+<p>
+<font color=green><em>Update:</em></font> Marco Antoniotti has patched
+ASDF-INSTALL to make it work with MK:DEFSYSTEM as well. See the <a href="#defsystem">section about MK:DEFSYSTEM</a> below.
+
+<br>&nbsp;<br><h3><a class=none name="asdf-install">What is ASDF-INSTALL?</a></h3>
+
+<a href="http://www.cliki.net/asdf-install">ASDF-INSTALL</a>, also
+written by Dan Barlow, is layered atop ASDF and can automatically
+download Lisp libraries from the Internet and install them for you. It
+is also able to detect and <a href="#dependencies">resolve dependencies</a> on other
+libraries. (These libraries have to be prepared for ASDF-INSTALL by
+their author. See more <a href="#url">below</a>.)
+<p>
+ASDF-INSTALL was originally written for the <a
+href="http://sbcl.sf.net/">SBCL</a> Common Lisp implementation. It has
+been recently ported to <a
+href="http://www.cons.org/cmucl/">CMUCL</a>, <a
+href="http://www.franz.com/products/allegrocl/">Allegro Common
+Lisp</a>, <a href="http://www.lispworks.com/">Xanalys LispWorks</a>,
+and <a href="http://clisp.sourceforge.net/">CLISP</a> by <a
+href="http://weitz.de/">Edi Weitz</a>. <a
+href="http://www.cliki.net/Marco%20Baringer">Marco Baringer</a> added
+support for <a href="http://openmcl.clozure.com/">OpenMCL</a>, <a href="http://setf.de/">James Anderson</a> added support for <a
+href="http://www.digitool.com/">Macintosh Common Lisp</a> (MCL).
+<p>
+It'd be nice if users of other Lisps (like <a
+href="http://www.cormanlisp.com/">Corman Lisp</a>, <a
+href="http://ecls.sourceforge.net/">ECL</a>, or <a
+href="http://www.scieneer.com/scl/">Scieneer Common Lisp</a>) could <a
+href="mailto:edi@agharta.de">provide patches</a> to make ASDF-INSTALL
+available on more platforms.
+<p>
+The original ASDF-INSTALL is distributed with SBCL. The
+&quot;portable&quot; version is
+available from <a
+href="http://weitz.de/files/asdf-install.tar.gz">http://weitz.de/files/asdf-install.tar.gz</a> and also
+from <a
+href="http://www.cliki.net/cclan">CCLAN</a>.
+
+<br>&nbsp;<br><h3><a class=none name="pre">Prerequisites</a></h3>
+
+This tutorial is aimed at Unix-like systems which should include Linux and Mac&nbsp;OS&nbsp;X.
+If you're on MS&nbsp;Windows make sure to read the <font color=green><em>Windows notes</em></font> at the end of each section.
+<p>
+Apart from one of the <a href="#asdf-install">supported Lisps</a> you
+will need <a href="http://www.gnupg.org/">GnuPG</a> (which is probably pre-installed on
+most Linux distributions). Install it first if you don't have it already. You may also need to install <a href="http://www.gnu.org/software/tar/tar.html">the GNU version of <code>tar</code></a> if you're not on Linux.
+<p>
+(GnuPG is not strictly necessary - see <a
+href="#*verify-gpg-signatures*">below</a> - but it is recommended if
+you want to be reasonable sure that you're not installing arbitrary
+malicious code.)
+
+<p> <font><em>Update:</em></font> Beginning with version 0.14.1
+ASDF-INSTALL is already included with the OpenMCL distribution.  Also,
+AllegroCL 7.0 and higher include ASDF (but not ASDF-INSTALL.) See
+below for details.
+
+<p>
+<font><em>Note:</em></font> For MCL you must start
+your Lisp from a terminal.
+
+<p>
+<font color=green><em>Windows note:</em></font> If you want to use
+ASDF-INSTALL on Windows you must install <a
+href="http://www.cygwin.com/">Cygwin</a> first. You can also install
+GnuPG from the Cygwin setup program. If you want to use CLISP you
+currently <a
+href="http://article.gmane.org/gmane.lisp.clisp.general/7891">have to
+use</a> the Cygwin version (which can also be installed from the setup
+application). The good news is that if you use Cygwin you can pretty
+much pretend you're on Unix and <b>skip</b> all the <font
+color=green><em>Windows notes</em></font> below.
+<p>(Update: Alex Mizrahi posted <a href='http://www.google.com/groups?selm=2gacj0Fi7moU1%40uni-berlin.de&output=gplain'>some notes</a> about using the native Win32 version of CLISP to <a href='news://comp.lang.lisp'>comp.lang.lisp</a>. I asked him to send patches but he hasn't sent them yet.)
+
+<p>
+Whenever I use <code>~/</code> (the Unix shell notation for the user's
+home directory) in the following text what is actually meant is the
+value of <code>(<a
+href="http://www.lispworks.com/reference/HyperSpec/Body/f_user_h.htm">USER-HOMEDIR-PATHNAME</a>)</code>. While
+on Unix/Linux all implementations seem to agree what this value should
+be, on Windows this is not the case. Read the docs of your Lisp.
+
+<h4><a class=none name="install-asdf">Installing ASDF</a></h4>
+
+(<a href="#load-asdf">Skip</a> this section if you use SBCL or OpenMCL or AllegroCL 7.0 or higher.) <a
+href="http://weitz.de/files/asdf.lisp">Download</a> ASDF and put the
+file <code>asdf.lisp</code> in a place where you want it to
+stay. Change into this directory and, from your Lisp, issue the
+command
+
+<pre>
+(load (compile-file "asdf.lisp"))
+</pre>
+
+You should now have a new file the name of which depends on your
+implementation - probably something like <code>asdf.fasl</code>,
+<code>asdf.fas</code>, <code>asdf.fsl</code>, <code>asdf.ufsl</code>,
+<code>asdf.x86f</code>, or <code>asdf.so</code>.
+
+<p>
+<em>Note:</em> The download link above is provided for your
+convenience. The <em>real</em> home of ASDF can be found via <a
+href="http://www.cliki.net/asdf">http://www.cliki.net/asdf</a>. I
+cannot guarantee that the version available from my server will always
+be in sync with bleeding-edge ASDF but the program seems to be mature
+enough to warrant the usage of a version that may be slightly out-dated.
+
+<p>
+<em>Note:</em> LispWorks&nbsp;4.2 (and probably earlier versions) has a bug
+that prevents it from loading the compiled ASDF correctly. It is
+recommended that you upgrade to&nbsp;4.3 but if for some
+reason you must use an older version you can skip the compilation step
+above and later just load the <code>.lisp</code> file instead in which
+case you'll use interpreted code.
+
+<p>
+<em>Note:</em> CLISP&nbsp;2.32 cannot compile ASDF due to being not
+fully ANSI-compliant. You can download a compiled version (which
+should work with all operating systems supported by CLISP) from <a
+href="http://weitz.de/files/asdf.fas">http://weitz.de/files/asdf.fas</a>.
+Newer versions (like&nbsp;2.33.2) <em>can</em> compile ASDF, though.
+
+<h4><a class=none name="load-asdf">Loading ASDF automatically</a></h4>
+
+We want to make sure that ASDF is loaded whenever we start our
+Lisp. For this we'll use an <a class=none
+name="initialization-file"><em>initialization file</em></a>. Most
+Lisps will read and execute the contents of a certain file on
+startup. This file is usually located in your home directory and might
+be called <code>.clinit.cl</code> (for Allegro Common Lisp),
+<code>.cmucl-init</code> (for CMUCL), <code>.lispworks</code> (for
+Xanalys LispWorks), <code>.clisprc</code> (for CLISP), or
+<code>openmcl-init.lisp</code> (for OpenMCL). Consult your Lisp's
+documentation for details.
+<p>
+Open this file (create it if it doesn't exist) and add this line
+
+<pre>
+#-:asdf (load "/path/where/asdf/is/located/asdf")
+</pre>
+
+where of course you have replaced
+<code>/path/where/asdf/is/located/</code> with the correct path to
+ASDF - see <a href="#install-asdf">last section</a>. We wrote
+<code>(load&nbsp;&quot;.../asdf&quot;)</code> and not, say,
+<code>(load&nbsp;&quot;.../asdf.x86f&quot;)</code> because this way
+your Lisp will load the compiled file if it is available and otherwise
+<code>asdf.lisp</code> if for some reason you didn't compile the code.
+<p>
+Why the <code>#-:asdf</code>? After ASDF has been loaded it adds the
+symbol <code>:ASDF</code> to the <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/v_featur.htm">features
+list</a>. Our use of the <em>read-time conditional</em> <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/02_dhr.htm">Sharpsign
+Minus</a> thus makes sure that ASDF isn't loaded a second time if it's
+already there. (So you can safely save and use an image with ASDF
+pre-loaded without changing your init file.)
+<p>
+If you're using SBCL or OpenMCL or AllegroCL 7.0 or higher <em>don't</em> add the line from above but use
+
+<pre>
+(require :asdf)
+</pre>
+
+instead.
+
+<p>
+ASDF maintains a list of places where it will look for <a class=none name=definition><em>system
+definitions</em></a> when it is asked to load or compile a system. (System
+definitions are the files ending with <code>.asd</code>.) This list is
+stored in the <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/26_glo_s.htm#special_variable">special
+variable</a> <a class=none name="*central-registry*"><code>ASDF:*CENTRAL-REGISTRY*</code></a> and you can add new
+directories to it. Open your initialization file once again and add
+the following line <em>after</em> the line which loads ASDF:
+
+<pre>
+(pushnew "/path/to/your/registry/" asdf:*central-registry* :test #'equal)
+</pre>
+
+You can use a directory of your choice but you should make sure it
+exists. You can also add several of these lines with different
+directories so ASDF will look into each directory in turn until it has
+found a system definition. Use the directory
+<code>~/.asdf-install-dir/systems/</code> if you can't make a decision
+and make sure to create it. (Replace <code>~/</code> with an absolute
+path to your home directory because not all Lisps support the tilde
+notation.) We will call the directory you've chosen your <a class=none
+name=registry><em>registry</em></a> from now on.
+
+
+<p>
+
+<em>Note:</em> It is important that you add a <em>directory</em> here,
+not a file, so make sure the <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/26_glo_n.htm#namestring">namestring</a>
+ends with a slash!
+
+<p>
+
+<em>Note:</em> If you use ASDF alone the preferred way to deal with
+system definitions is to create symbolic links from the
+<code>.asd</code> files to your registry. However, you don't have to
+deal with this as ASDF-INSTALL will do that for you.
+
+<p>
+
+<em>Note:</em> The free &quot;Personal Edition&quot; of LispWorks doesn't read
+<code>~/.lispworks</code> on startup. You can circumvent this by
+putting something like
+
+<pre>
+alias lispworks="/usr/local/lib/LispWorksPersonal/lispworks-personal-4300 -init ~/.lispworks"
+</pre>
+
+into your <code>~/.bashrc</code> file.
+
+<p>
+<a class=none name="win-sym"><font color=green><em>Windows
+note:</em></font></a> On Windows we can't
+use a central registry because Windows doesn't have symbolic links. We
+will use another mechanism (see <a
+href="#load-asdf-install">below</a>) to find system definitions, so
+you don't have to put the <code>PUSHNEW</code> line into your
+initialization file.
+
+<h4><a class=none name="install-asdf-install">Installing ASDF-INSTALL</a></h4>
+
+(<a href="#load-asdf-install">Skip</a> this section if you use SBCL.)
+<a href="http://weitz.de/files/asdf-install.tar.gz">Download</a>
+ASDF-INSTALL and unpack the gzipped tar archive into a directory of
+your choice. Now create a symlink from the <code>.asd</code> file to your <a href="#registry">registry</a>:
+
+<pre>
+cd /path/to/your/registry/
+ln -s /path/where/you/unpacked/asdf-install/asdf-install.asd .
+</pre>
+
+<p>For OpenMCL you don't have to download ASDF-INSTALL because it's
+already there - it's in <code>/path/to/ccl/tools/asdf-install/</code>
+where <code>/path/to/ccl/</code> is the directory where you installed
+OpenMCL.  You have to provide the symlink, though.
+
+<p>
+Now start your Lisp and issue the following command:
+
+<pre>
+(asdf:operate 'asdf:compile-op :asdf-install)
+(asdf:operate 'asdf:load-op :asdf-install)
+</pre>
+
+This will ask ASDF to locate the ASDF-INSTALL library, compile it, and finally load it.
+
+<p>
+<font color=green><em>Windows note:</em></font> You can
+leave out the <code>ln</code> command. Now, <em>before</em> you
+compile and load ASDF-INSTALL you have to put this line into your
+initialization file:
+
+<pre>
+(pushnew "/path/where/you/unpacked/asdf-install/" asdf:*central-registry* :test #'equal)
+</pre>
+
+and then either restart your Lisp or evaluate this expression in your
+current session. Afterwards, proceed with the two
+<code>ASDF:OPERATE</code> forms.
+
+<h4><a class=none name="load-asdf-install">Loading ASDF-INSTALL automatically</a></h4>
+
+Open your <a href="#load-asdf">initilization file</a> again and add this line at the end:
+
+<pre>
+#-:asdf-install (asdf:operate 'asdf:load-op :asdf-install)
+</pre>
+
+This will instruct ASDF to load the (compiled) ASDF-INSTALL library
+whenever your Lisp starts up (unless ASDF-INSTALL is already available
+in your image).
+
+<p>
+If you're using SBCL <em>don't</em> add the line from above but use
+
+<pre>
+(require :asdf-install)
+</pre>
+
+instead.
+
+<p>
+You're now ready to use ASDF-INSTALL.
+
+<p>
+<font color=green><em>Windows note:</em></font> For Windows add the
+following line to end of the initialization file:
+
+<pre>
+(pushnew 'asdf-install:sysdef-source-dir-search
+         asdf:*system-definition-search-functions*)
+</pre>
+
+As we <a href="#win-sym">can't use</a> the <a
+href="#*central-registry*">central registry</a>, we're using a
+<a class=none name="custom-search">customized search function</a> instead. It'll scan all directories below
+each of the entries in <a
+href="#*locations*"><code>*LOCATIONS*</code></a> until it finds a
+suitable system definition. Note that this is a sub-optimal solution
+because this will not necessarily find the newest one if you've
+installed several versions of the same library. Make sure to <a
+href="#uninstall">uninstall</a> older versions.
+
+<br>&nbsp;<br><h3><a class=none name="defsystem">Optional: Using MK:DEFSYSTEM instead of (or in addition to) ASDF</a></h3>
+
+<a href="http://www.cliki.net/mk-defsystem">MK:DEFSYSTEM</a> was
+written by Mark Kantrovitz in the early days of Common Lisp. It
+precedes ASDF and also works with almost all CL implementations you'll
+come across. Thanks to the efforts of Marco Antoniotti, ASDF-INSTALL
+can now also be used with MK:DEFSYSTEM which means that even if the
+library you want to use doesn't have an ASDF system definition you
+might be able to install it via ASDF-INSTALL.
+<p>
+The recommended setup is to use <em>both</em> ASDF <em>and</em>
+MK:DEFSYSTEM because this will significantly increase the number of
+libraries you can install with ASDF-INSTALL.
+<p>
+To set up your Lisp environment for this you have to do the following (after reading the sections above):
+<ul>
+  <li>Get MK:DEFSYSTEM (version&nbsp;3.4i or higher) from <a href="http://clocc.sourceforge.net/">CLOCC</a>. (You can grab a nightly snapshot or browse the CVS. You only need the file <code>defsystem.lisp</code> from within the <code>src/defsystem-3.x</code> directory.)
+  <li>To install MK:DEFSYSTEM evaluate the form
+<pre>
+(load (compile-file "/path/to/defsystem.lisp"))
+</pre>
+  <li>To load MK:DEFSYSTEM automatically each time you start your Lisp put the forms
+<pre>
+#-:mk-defsystem (load "/path/to/defsystem")
+(mk:add-registry-location "/path/to/your/registry/")
+</pre>
+      into your initialization file.
+  <li>Finally, replace the line
+<pre>
+#-:asdf-install (asdf:operate 'asdf:load-op :asdf-install)
+</pre>
+from <a href="#load-asdf-install">above</a> with the line
+<pre>
+#-:asdf-install (load "/path/to/asdf-install/load-asdf-install")
+</pre>
+This last step will ensure that ASDF-INSTALL will always be loaded on startup even if you only use MK:DEFSYSTEM and don't have ASDF available.
+</ul>
+The following sections should work for you no matter whether you use ASDF, MK:DEFSYSTEM, or both.
+
+<br>&nbsp;<br><h3><a class=none name="library">How to install a library</a></h3>
+
+Here and in the following sections we assume that you have set up your
+environment as described in <a
+href="#pre"><em>Prerequisites</em></a>.
+
+<p>
+<em>Note:</em> Of course, the fact that a library can be installed with
+ASDF-INSTALL and that ASDF-INSTALL was ported to your Lisp
+implementation doesn't necessary mean that the library <em>itself</em>
+will work with your Lisp! Check the library's docs before you try to
+install it.
+
+<h4><a class=none name="name">Installing a library by name</a></h4>
+
+The webpage <a
+href="http://www.cliki.net/asdf-install">http://www.cliki.net/asdf-install</a>
+contains a list of libraries which can automatically be downloaded and
+installed via ASDF-INSTALL. Listed here are libraries which are
+explicitely prepared to work with ASDF-INSTALL and where the author
+decided to announce this via <a
+href="http://www.cliki.net/">CLiki</a>. This is the preferred way to
+install a library via ASDF-INSTALL.
+<p>
+You can click on the name of each library
+to get a description. Use the library's name from the list to install
+it. If, say, you want to install <a
+href="http://weitz.de/cl-ppcre/">CL-PPCRE</a> make sure you're
+connected to the Internet and use this command:
+
+<pre>
+(asdf-install:install :cl-ppcre)
+</pre>
+
+Then proceed with <a href="#where"><em>Where to store the library</em></a> below.
+<p>
+
+<em>Note:</em> If you install a library by name, ASDF-INSTALL will
+connect to the CLiki website and from there it'll be redirected to the
+actual download location provided by the library's author.
+
+<p>
+<em>Note:</em> The argument to the <code>ASDF-INSTALL:INSTALL</code>
+function is a <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/26_glo_s.htm#string_designator">string
+designator</a>, i.e. instead of <code>:CL-PPCRE</code> you can also
+use <code>&quot;cl-ppcre&quot;</code>. CLiki is case-insensitive and
+therefore case doesn't matter if you install a library by name.
+
+<h4><a class=none name="url">Installing a library by URL</a></h4>
+
+The list mentioned <a href="#name">above</a> is not necessary
+complete, i.e. there might as well exist libraries which aren't listed
+there but which can be installed via ASDF-INSTALL.
+
+<p>
+In order to be <em>ASDF-installable</em> a library has to contain a <a
+href="#definition">system definition</a> for ASDF. It also has to be
+packaged in a certain way: It is assumed to come as a gzipped tar
+archive (usually ending in <code>.tar.gz</code> or <code>.tgz</code>)
+which unpacks into one directory possibly containing
+sub-directories. The system definition has to have a name
+corresponding to the name of the library (so if your library is called
+&quot;foobar&quot; the system definition is supposed to be
+<code>foobar.asd</code>) and has to reside in the top-level
+directory.
+<p>
+If this is the case you can download and install the library directly by
+providing the download URL of the package like so:
+
+<pre>
+(asdf-install:install &quot;http://weitz.de/files/cl-ppcre.tar.gz&quot;)
+</pre>
+
+Now proceed with <a href="#where"><em>Where to store the library</em></a> below.
+
+<p>
+<em>Note:</em> Currently, ASDF-INSTALL only understands http. Other
+protocols like ftp or https aren't supported.
+
+<p>
+<em>Note:</em> It's obviously rather easy to make an existing library
+ASDF-installable if it isn't already. If you come across a library
+which you'd like to use but which isn't listed on <a
+href="http://www.cliki.net/asdf-install">http://www.cliki.net/asdf-install</a>,
+it might be worthwhile to kindly ask the library's author to change
+this.
+
+<h4><a class=none name="local">Installing from a local file</a></h4>
+
+The third way to install a library via ASDF-INSTALL is to use a local
+tar archive (in the format described <a href="#url">in the last
+section</a>). In this case you use the file's <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/26_glo_n.htm#namestring">namestring</a>
+
+<pre>
+(asdf-install:install &quot;/path/to/library/library.tar.gz&quot;)
+</pre>
+
+and afterwards carry on with the next section.
+
+<p>
+<em>Note:</em> For obvious reasons this namestring must not start with
+<code>&quot;http://&quot;</code> although your operating system might
+otherwise allow this.
+
+<h4><a class=none name="where">Where to store the library</a></h4>
+
+ASDF-INSTALL will now ask you where the library should be stored. (This can be <a href="#*locations*">customized</a>.) In
+the default configuration this'll look more or less like so:
+
+<pre>
+Install where?
+1) System-wide install:
+   System in /usr/local/asdf-install/site-systems/
+   Files in /usr/local/asdf-install/site/
+2) Personal installation:
+   System in /home/edi/.asdf-install-dir/systems/
+   Files in /home/edi/.asdf-install-dir/site/
+ -->
+</pre>
+
+Choose one of these options and enter the corresponding number, then
+press the <code>Return</code> key. (Note that on Unix-like systems you
+usually don't have write access in <code>/usr/local/</code> unless
+you're <code>root</code>.)
+
+<h4><a class=none name="security">The security check</a></h4>
+
+If you don't install from a local file, ASDF-INSTALL will now check the
+validity of the library. (This behaviour can be <a
+href="#*verify-gpg-signatures*">customized</a>.) Library authors are
+supposed to crypto-sign their libraries and provide a file with the
+(PGP) signature in the same place where the library can be downloaded,
+i.e. if the library is at
+<code>http://www.example.com/frob.tar.gz</code> then ASDF-INSTALL will
+try to download the signature from
+<code>http://www.example.com/frob.tar.gz.asc</code>.
+
+<p>
+ASDF-INSTALL will check
+<ul>
+ <li>if the signature exists,
+ <li>if there is a GPG trust relationship between the package signer
+    and you (i.e. that the package comes from someone whose
+    key you've signed, or someone else you have GPG trust with has signed), and
+ <li>if the signer is listed in
+    your <a href="#trusted-uids">personal list of valid suppliers of Lisp code</a>.
+</ul>
+
+If all these tests succeed, ASDF-INSTALL will compile and install the
+library and you can now <a href="#use">use it</a>. (This will also happen instantly if
+you have installed from a local file.)
+
+<p>
+If one of the checks fails, you'll most likely be confronted with one
+of these situations:
+ 
+<pre>
+Downloading 157777 bytes from http://weitz.de/files//cl-ppcre.tgz ...
+Error: Server responded 404 for GET http://weitz.de/files//cl-ppcre.tgz.asc
+  [condition type: DOWNLOAD-ERROR]
+
+Restart actions (select using :continue):
+ 0: Don't ckeck GPG signature for this package
+ 1: Return to Top Level (an &quot;abort&quot; restart).
+ 2: Abort entirely from this process.
+</pre>
+
+There was no signature corresponding to this package.
+
+<pre>
+Downloading 6365 bytes from http://files.b9.com//cl-base64-latest.tar.gz ...gpg: WARNING: using insecure memory!
+gpg: please see http://www.gnupg.org/faq.html for more information
+gpg: Signature made Thu 12 Jun 2003 04:06:04 PM CEST using DSA key ID C4A3823E
+gpg: Can't check signature: public key not found
+
+Error: No key found for key id 0x112ECDF2C4A3823E.  Try some command like
+  gpg  --recv-keys 0x112ECDF2C4A3823E
+  [condition type: KEY-NOT-FOUND]
+
+Restart actions (select using :continue):
+ 0: Don't ckeck GPG signature for this package
+ 1: Return to Top Level (an "abort" restart).
+ 2: Abort entirely from this process.
+</pre>
+
+The library was signed but the signer's public key wasn't found in
+your public keyring.
+
+<pre>
+Downloading 6365 bytes from http://files.b9.com//cl-base64-latest.tar.gz ...gpg: WARNING: using insecure memory!
+gpg: please see http://www.gnupg.org/faq.html for more information
+gpg: Signature made Thu 12 Jun 2003 04:06:04 PM CEST using DSA key ID C4A3823E
+gpg: Good signature from &quot;Kevin M. Rosenberg &lt;kmr@debian.org&gt;&quot;
+gpg:                 aka &quot;Kevin Rosenberg &lt;kevin@rosenberg.net&gt;&quot;
+gpg:                 aka &quot;Kevin M. Rosenberg &lt;kevin@b9.com&gt;&quot;
+gpg:                 aka &quot;Kevin Marcus Rosenberg, M.D. &lt;kevin@b9.com&gt;&quot;
+gpg: WARNING: This key is not certified with a trusted signature!
+gpg:          There is no indication that the signature belongs to the owner.
+Primary key fingerprint: D7A0 55B6 4768 3582 B10D  3F0C 112E CDF2 C4A3 823E
+
+Error: GPG warns that the key id 0x112ECDF2C4A3823E (Kevin M. Rosenberg &lt;kmr@debian.org&gt;) is not fully trusted
+  [condition type: KEY-NOT-TRUSTED]
+
+Restart actions (select using :continue):
+ 0: Don't ckeck GPG signature for this package
+ 1: Return to Top Level (an &quot;abort&quot; restart).
+ 2: Abort entirely from this process.
+</pre>
+
+The signer's key is in your public keyring but you have no GPG trust
+relationship with him.
+
+<pre>
+Downloading 157777 bytes from http://weitz.de/files//cl-ppcre.tgz ...gpg: WARNING: using insecure memory!
+gpg: please see http://www.gnupg.org/faq.html for more information
+gpg: Signature made Fri 24 Oct 2003 11:22:11 AM CEST using DSA key ID 057958C6
+gpg: Good signature from &quot;Dr. Edmund Weitz &lt;edi@weitz.de&gt;&quot;
+
+Error: Dr. Edmund Weitz &lt;edi@weitz.de&gt; (key id 595FF045057958C6) is not on your package supplier list
+  [condition type: AUTHOR-NOT-TRUSTED]
+
+Restart actions (select using :continue):
+ 0: Add to package supplier list
+ 1: Don't ckeck GPG signature for this package
+ 2: Return to Top Level (an &quot;abort&quot; restart).
+ 3: Abort entirely from this process.
+</pre>
+
+The signer's key is in your public keyring, you have a GPG trust
+relationship with him but the signer wasn't found in your <a
+href="#trusted-uids">list of valid suppliers of Lisp code</a>.
+<p>
+As you'll have noticed, in all these cases ASDF-INSTALL offers the <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/09_adb.htm">restart</a>
+not to check the GPG signature in this particular case. How you can
+select this restart depends on your Lisp implementation but if you
+select it ASDF-INSTALL will proceed compiling and installing the
+package without further checks for this library.
+<p>
+In the last case (condition type <code>AUTHOR-NOT-TRUSTED</code>) you
+are also offered <a class=none name=restart>another restart</a>. If you select this one the signer of
+the library will be added to your <a href="#trusted-uids">package
+supplier list</a> and you won't be asked again if you install another
+library signed by the same person.
+
+<p>
+<em>Note:</em> You might be asking yourself if all this security stuff
+is really necessary. Well, <a href="http://www.cliki.net/">CLiki</a>,
+the website where ASDF-INSTALL looks for the package URL if you
+install by name, can be edited by <em>anyone</em> so it would be
+fairly easy for a malicious hacker to redirect you to a library which
+once it's installed insults your boss by email or withdraws
+US$&nbsp;100,000 from your bank account. You better make sure this
+doesn't happen... See the <a href="#customize">section about
+customization</a> on how to (partly) disable security checks.
+
+<p>
+<em>Note:</em> If you're unsure about notions like <em>public
+keyring</em> or <em>GPG trust relationship</em>, please read 
+the <a href="http://www.gnupg.org/documentation/index.html">GnuPG documentation</a>. It is beyond the scope of this text to
+explain these terms.
+
+<br>&nbsp;<br><h3><a class=none name="use">How to use an installed library</a></h3>
+
+After you've successfully executed <code>ASDF-INSTALL:INSTALL</code>
+you can immediately use the library you've just installed while you're
+still in the same Lisp session. If you quit your Lisp image and start
+it anew you have to reload the library. (Of course you <em>don't</em>
+have to install it again!) This is done like so:
+
+<pre>
+(asdf:operate 'asdf:load-op :library-name)
+</pre>
+
+Here <a class=none name="library-name"><code>:LIBRARY-NAME</code></a> is either the name you've used if you
+installed <a href="#name">by name</a> or it is the name of the main
+<code>.asd</code> file if you've installed <a href="#url">by URL</a>
+or <a href="#local">from a local file</a>. If you're not sure about
+the name you have to use, you can list the contents of your <a
+href="#registry">registry</a> for all libraries which are available to
+you. So, if your registry looks like this
+
+<pre>
+edi@bird:~ > ls ~/.asdf-install-dir/systems/
+cl-ppcre.asd  cl-ppcre-test.asd  cl-who.asd  html-template.asd
+</pre>
+
+you can substitute <code>:LIBRARY-NAME</code> with one of
+<code>:CL-PPCRE</code>, <code>:CL-PPCRE-TEST</code>,
+<code>:CL-WHO</code>, or <code>:HTML-TEMPLATE</code>. (CL-PPCRE-TEST
+was most likely automatically installed when you installed <a
+href="http://weitz.de/cl-ppcre/">CL-PPCRE</a>.)
+
+<p>
+If you use SBCL you can, instead of calling <code>ASDF:OPERATE</code>,
+simply <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/f_provid.htm"><code>REQUIRE</code></a>
+the library:
+
+<pre>
+(require :library-name)
+</pre>
+
+<br>&nbsp;<br><h3><a class=none name="dependencies">How ASDF-INSTALL resolves dependencies</a></h3>
+
+Sometimes a library depends on one or more other libraries. This can
+be expressed within an ASDF <a href="#definition">system
+definition</a>. If there's a dependency and the necessary libraries
+aren't already installed then ASDF-INSTALL will try to download the
+missing libraries <a href="#name">by name</a> and install them before
+it proceeds to install the main library. This of course requires that
+the missing libraries are also listed on <a href="http://www.cliki.net/asdf-install">CLiki</a>.
+<p>
+You can for example from CMUCL issue the command
+
+<pre>
+(asdf-install:install :osicat)
+</pre>
+
+and watch how ASDF-INSTALL not only downloads and installs <a
+href="http://common-lisp.net/project/osicat/">Osicat</a> but also <a
+href="http://uffi.b9.com/">UFFI</a>.
+
+<br>&nbsp;<br><h3><a class=none name="customize">Customizing ASDF-INSTALL</a></h3>
+
+When ASDF-INSTALL is loaded it <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/f_load.htm"><code>LOAD</code></a>s
+the file <code>~/.asdf-install</code> if it's there. This file (which
+is obviously supposed to contain Lisp code) can be used to change the
+values of some <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/26_glo_s.htm#special_variable">special
+variables</a> which control ASDF-INSTALL's behaviour. Their names are
+<a
+href="http://www.lispworks.com/reference/HyperSpec/Body/26_glo_e.htm#exported">exported</a>
+from the <code>ASDF-INSTALL</code> <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/11_.htm">package</a>.
+
+<h4><a class=none name="*gnu-tar-program*">Special variable <code>*GNU-TAR-PROGRAM*</code></a></h4>
+
+The path to the GNU <code>tar</code> program as a string - the default is <code>&quot;tar&quot;</code>. Changing this variable has no effect if Cygwin is used.
+
+<h4><a class=none name="*proxy*">Special variable <code>*PROXY*</code></a></h4>
+
+This variable is <code>NIL</code> by default but will be set to the
+value of the environment variable <code>$http_proxy</code> (if it's
+set) prior to loading <code>~/.asdf-install</code>. Set this to a
+non-<code>NIL</code> value if you need to go through an http proxy.
+
+<h4><a class=none name="*proxy-user*">Special variable <code>*PROXY-USER*</code></a></h4>
+<h4><a class=none name="*proxy-passwd*">Special variable <code>*PROXY-PASSWD*</code></a></h4>
+
+Use these variables if your <a href="#*proxy*">proxy</a> requires authentication.
+
+<h4><a class=none name="*cclan-mirror*">Special variable <code>*CCLAN-MIRROR*</code></a></h4>
+
+This variable is set to
+<code>&quot;http://ftp.linux.org.uk/pub/lisp/cclan/&quot;</code>
+before <code>~/.asdf-install</code> is loaded.  A couple of
+ASDF-installable libraries are available via <a
+href="http://www.cliki.net/cclan">CCLAN</a> and with the help of this
+variable you can choose another CCLAN mirror from the list at <a
+href="http://ww.telent.net/cclan-choose-mirror">http://ww.telent.net/cclan-choose-mirror</a>.
+
+<h4><a class=none name="*verify-gpg-signatures*">Special variable <code>*VERIFY-GPG-SIGNATURES*</code></a></h4>
+
+This variable is set to <code>T</code> initially which means that
+there'll be a <a href="#security">security check</a> for each library
+which is not installed from a local file. You can set it to
+<code>NIL</code> which means no checks at all or to
+<code>:UNKNOWN-LOCATIONS</code> which means that only URLs which are
+not in <a href="#*safe-url-prefixes*"><code>*SAFE-URL-PREFIXES*</code></a> are
+checked. Every other value behaves like <code>T</code>.
+
+<p>
+<em>Note:</em> This customization option is currently not supported in
+the SBCL version of ASDF-INSTALL.
+
+<h4><a class=none name="*safe-url-prefixes*">Special variable <code>*SAFE-URL-PREFIXES*</code></a></h4>
+
+The value of this variable is <code>NIL</code> initially. It is
+supposed to be a list of strings which are &quot;safe&quot; URL
+prefixes, i.e. if a download URL begins with one of these strings
+there's no <a href="#security">security check</a>. The value of
+<code>*SAFE-URL-PREFIXES*</code> only matters if <a
+href="#*verify-gpg-signatures*"><code>*VERIFY-GPG-SIGNATURES*</code></a>
+is set to <code>:UNKNOWN-LOCATIONS</code>.
+
+<p>
+<em>Note:</em> This customization option is currently not supported in
+the SBCL version of ASDF-INSTALL.
+
+<h4><a class=none name="*locations*">Special variable <code>*LOCATIONS*</code></a></h4>
+
+The initial value of this variable (prior to loading
+<code>~/.asdf-install</code>) is
+
+<pre>
+((#p"/usr/local/asdf-install/site/"
+  #p"/usr/local/asdf-install/site-systems/"
+  "System-wide install")
+ (#p"/home/edi/.asdf-install-dir/site/"
+  #p"/home/edi/.asdf-install-dir/systems/"
+  "Personal installation"))
+</pre>
+
+where <code>/home/edi/</code> will obviously be replaced with your
+home directory. You'll notice that this corresponds to the <a
+href="#where">little menu</a> you see when ASDF-INSTALL starts to
+install a package. You can add elements to this list or replace it
+completely to get another menu. Each element is a list with three
+elements - a <a
+href="http://www.lispworks.com/reference/HyperSpec/Body/19_b.htm">pathname</a>
+denoting the directory where the (unpacked) libraries will be stored,
+a pathname denoting a directory where <a href="#definition">system
+definition</a> symlinks will be placed, and a string describing this
+particular choice.
+<p>
+If you make changes to this value it is important that you also update
+<a href="#*central-registry*"><code>ASDF:*CENTRAL-REGISTRY*</code></a>
+accordingly in your <a name="initialization-file">initialization
+file</a> or ASDF-INSTALL won't find your system definitions (unless
+you are on Windows). See the <a href="#example">example</a> below.
+
+<p>
+<em>Note:</em> On SBCL the initial value of this variable is different
+- try it out yourself.
+
+<h4><a class=none name="*preferred-location*">Special variable <code>*PREFERRED-LOCATION*</code></a></h4>
+
+This variable is initially <code>NIL</code>. If it is not
+<code>NIL</code> it should be a positive integer not greater than the
+length of <a href="#*locations*"><code>*LOCATIONS*</code></a>. By
+setting this value you circumvent the <a href="#where">question</a>
+about where to install a library and ASDF-INSTALL will unconditionally
+use the corresponding entry from <a
+href="#*locations*"><code>*LOCATIONS*</code></a>. Note that
+<code>1</code> (not <code>0</code>) means the first entry.
+
+<p>
+<em>Note:</em> This customization option is currently not supported in
+the SBCL version of ASDF-INSTALL.
+
+<h4><a class=none name="asdf-install-dir">Environment variable <code>ASDF_INSTALL_DIR</code></a></h4>
+
+The value of this <em>environment variable</em> determines the first element of the initial value of
+<a href="#*locations*"><code>*LOCATIONS*</code></a>, i.e. if it, say,
+contains the value <code>/usr/local/foo/</code>, then the first
+element of <code>*LOCATIONS*</code> is
+
+<pre>
+(#p&quot;/usr/local/foo/site/&quot;
+ #p&quot;/usr/local/foo/site-systems/&quot;
+ &quot;System-wide install&quot;)
+</pre>
+
+If this variable is not set, the directory
+<code>/usr/local/asdf-install/</code> is used. Note that this variable affects ASDF-INSTALL's behaviour <em>before</em> <code>~/.asdf-install</code> is loaded.
+
+<p>
+<em>Note:</em> On SBCL the value of <code>SBCL_HOME</code> is used
+instead.
+
+<h4><a class=none name="private-asdf-install-dir">Environment variable <code>PRIVATE_ASDF_INSTALL_DIR</code></a></h4>
+
+The value of this <em>environment variable</em> determines the second element of the initial value of
+<a href="#*locations*"><code>*LOCATIONS*</code></a>, i.e. if it, say,
+contains the value <code>frob/</code> and your username is <code>johndoe</code>, then the second
+element of <code>*LOCATIONS*</code> is
+
+<pre>
+(#p&quot;/home/johndoe/frob/site/&quot;
+ #p&quot;/home/johndoe/frob/systems/&quot;
+ &quot;Personal installation&quot;)
+</pre>
+
+If this variable is not set, the value
+<code>.asdf-install-dir</code> (note the dot) is used. Note that this variable affects ASDF-INSTALL's behaviour <em>before</em> <code>~/.asdf-install</code> is loaded.
+
+<p>
+<em>Note:</em> On SBCL the value <code>.sbcl</code> is used
+instead.
+
+<h4><a class=none name="example">An example <code>.asdf-install</code> file</a></h4>
+
+Here's a documented example for how the file
+<code>~/.asdf-install</code> could look like:
+
+<pre>
+<font color=orange>;; use a http proxy</font>
+(setq asdf-install:<a href="#*proxy*">*proxy*</a> &quot;http://proxy.foo.com/&quot;)
+
+<font color=orange>;; use a CCLAN mirror in France</font>
+(setq asdf-install:<a href="#*cclan-mirror*">*cclan-mirror*</a> &quot;http://thingamy.com/cclan/&quot;)
+
+<font color=orange>;; only partial security checks</font>
+(setq asdf-install:<a href="#*verify-gpg-signatures*">*verify-gpg-signatures*</a> :unknown-locations)
+
+<font color=orange>;; downloads from Kevin Rosenberg and from my own server don't have to be checked</font>
+(setq asdf-install:<a href="#*safe-url-prefixes*">*safe-url-prefixes*</a>
+        '(&quot;http://files.b9.com/&quot; &quot;http://weitz.de/files/&quot;))
+
+<font color=orange>;; add a repository for unstable libraries</font>
+(pushnew '(#p&quot;/usr/local/lisp/unstable/site/&quot;
+           #p&quot;/usr/local/lisp/unstable/systems/&quot;
+           &quot;Install as unstable&quot;)
+         asdf-install:<a href="#*locations*">*locations*</a>
+         :test #'equal)
+
+<font color=orange>;; make sure this is also known by ASDF</font>
+(pushnew &quot;/usr/local/lisp/unstable/systems/&quot;
+         asdf:<a href="#*central-registry*">*central-registry*</a>
+         :test #'equal)
+</pre>
+
+<br>&nbsp;<br><h3><a class=none name="trusted-uids">The list of trusted code suppliers</a></h3>
+
+ASDF-INSTALL maintains a list of library authors you trust. This list
+is stored in a file <code>trusted-uids.lisp</code> and usually resides in the directory <code>~/.asdf-install-dir/</code> but this can be customized by changing the environment variable <a href="#private-asdf-install-dir"><code>PRIVATE_ASDF_INSTALL_DIR</code></a>. You are not supposed to edit this file manually - new entries are added automatically whenever you choose the <a href="#restart">corresponding restart</a> during the security check.
+
+<br>&nbsp;<br><h3><a class=none name="uninstall">How to uninstall a library</a></h3>
+
+This is easy:
+
+<pre>
+(asdf-install:uninstall <a href="#library-name">:library-name</a>)
+</pre>
+
+ASDF-INSTALL will ask you to confirm this and then it'll remove the
+library's source directory as well as the symbolic link to the <a
+href="#definition">system definition</a> (if it exists).
+
+<p>
+<font color=green><em>Windows note:</em></font> Due to <a
+href="#custom-search">the way systems are found</a> on Windows
+ASDF-INSTALL will propose to delete an arbitrary version of your
+library if you've installed several of them. Make sure to read
+what it is about to remove before you confirm.
+
+<br>&nbsp;<br><h3><a class=none name="changelog">Changelog</a></h3>
+
+<table border=0>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2005-09-27</td><td>Small change for compatibility with future OpenMCL versions (thanks to Bryan O'Connor)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2005-07-14</td><td>Updated note about CLISP (thanks to Henri Lenzi)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2005-06-01</td><td>Added proxy authentication code (thanks to Sean Ross)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2005-02-16</td><td>More OpenMCL details (thanks to Jim Thompson)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-12-29</td><td>Added COPYRIGHT file to distribution</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-09-13</td><td>Added information about AllegroCL 7.0 and OpenMCL 0.14.1</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-09-08</td><td>Fixed typo in <code>GET-ENV-VAR</code> and added special variable <code>*GNU-TAR-PROGRAM*</code> (both thanks to Raymond Toy)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-05-20</td><td>Changed hyphens to underlines in names of environment variables (thanks to Robert P. Goldman)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-05-19</td><td>Mentioned Alex Mizrahi's notes, added version number for MK:DEFSYSTEM in docs and SPLIT-SEQUENCE dependency in ASDF system definition (thanks to Robert P. Goldman and Robert Lehr)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-04-28</td><td>Fixed <code>asdf-install.asd</code> so that it still works and you're not forced to use <code>load-asdf-install.lisp</code></td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-04-25</td><td>MK:DEFSYSTEM clarification</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-04-24</td><td>Patches by Marco Antoniotti for MK:DEFSYSTEM compatibility</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-03-27</td><td>Bugfixes by Kiyoshi Mizumaru</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-01-28</td><td>Improved MCL support (James Anderson)</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-01-21</td><td>Support for MCL by James Anderson</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-01-16</td><td>Minor edits, Cygwin CLISP support, download location for <code>asdf.fas</code></td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-01-15</td><td>Preliminary Windows support, described how to uninstall a library, added <code>*PREFERRED-LOCATION*</code>, removed <code>ln</code> bug in CLISP code</td></tr>
+<tr><td valign=top style='white-space:nowrap'>2004-01-13</td><td>&nbsp;</td><td>Mentioned OpenMCL support (Marco Baringer), added some SBCL exceptions, added clarification about Windows, minor edits, changes by Dan Barlow</td></tr>
+<tr><td colspan=2 valign=top style='white-space:nowrap'>2004-01-12</td><td>Initial version</td></tr>
+</table>
+
+<br>&nbsp;<br><h3><a class=none name="copyright">Copyright</a></h3>
+
+Copyright (c) 2004-2005 <a HREF="http://www.weitz.de/">Dr. Edmund Weitz</a>.  All rights reserved.
+
+<br>&nbsp;<br><h3><a class=none name="license">License</a></h3>
+
+Redistribution and use of this tutorial in its orginal form (HTML) or
+in 'derived' forms (PDF, Postscript, RTF and so forth) with or without
+modification, are permitted provided that the following condition is
+met:
+
+<ul>
+  <li>Redistributions must reproduce the above copyright notice, this
+      condition and the following disclaimer in the document itself
+      and/or other materials provided with the distribution.
+</ul>
+
+IMPORTANT: This document is provided by the author &quot;as is&quot; and any
+expressed or implied warranties, including, but not limited to, the
+implied warranties of merchantability and fitness for a particular
+purpose are disclaimed. In no event shall the author 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 documentation,
+even if advised of the possibility of such damage.
+
+<p>
+$Header$
+<p><a href="http://weitz.de/index.html">BACK TO MY HOMEPAGE</a>
+
+</body>
+</html>
Index: /branches/new-random/tools/asdf-install/installer.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/installer.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/installer.lisp	(revision 13309)
@@ -0,0 +1,575 @@
+(in-package #:asdf-install)
+
+(pushnew :asdf-install *features*)
+
+(defun installer-msg (stream format-control &rest format-arguments)
+  (apply #'format stream "~&;;; ASDF-INSTALL: ~@?~%"
+	 format-control format-arguments))
+
+(defun verify-gpg-signatures-p (url)
+  (labels ((prefixp (prefix string)
+	     (let ((m (mismatch prefix string)))
+	       (or (not m) (>= m (length prefix))))))
+    (case *verify-gpg-signatures*
+      ((nil) nil)
+      ((:unknown-locations)
+       (notany
+	(lambda (x) (prefixp x url))
+	*safe-url-prefixes*))
+      (t t))))
+	  
+(defun same-central-registry-entry-p (a b)
+  (flet ((ensure-string (x)
+           (typecase x
+             (string x)
+             (pathname (namestring (translate-logical-pathname x)))
+             (t nil))))
+    (and (setf a (ensure-string a))
+         (setf b (ensure-string b))
+         a b (string-equal a b))))
+
+(defun add-registry-location (location)
+  (let ((location-directory (pathname-sans-name+type location)))
+    #+asdf
+    (pushnew location-directory
+	     asdf:*central-registry*
+	     :test #'same-central-registry-entry-p)
+  
+    #+mk-defsystem
+    (mk:add-registry-location location-directory)))
+
+;;; Fixing the handling of *LOCATIONS*
+
+(defun add-locations (loc-name site system-site)
+  (declare (type string loc-name)
+           (type pathname site system-site))
+  #+asdf
+  (progn
+    (pushnew site asdf:*central-registry* :test #'equal)
+    (pushnew system-site asdf:*central-registry* :test #'equal))
+
+  #+mk-defsystem
+  (progn
+    (mk:add-registry-location site)
+    (mk:add-registry-location system-site))
+  (setf *locations*
+        (append *locations* (list (list site system-site loc-name)))))
+
+;;;---------------------------------------------------------------------------
+;;; URL handling.
+
+(defun url-host (url)
+  (assert (string-equal url "http://" :end1 7))
+  (let* ((port-start (position #\: url :start 7))
+	 (host-end (min (or (position #\/ url :start 7) (length url))
+			(or port-start (length url)))))
+    (subseq url 7 host-end)))
+
+(defun url-port (url)
+  (assert (string-equal url "http://" :end1 7))
+  (let ((port-start (position #\: url :start 7)))
+    (if port-start 
+	(parse-integer url :start (1+ port-start) :junk-allowed t) 80)))
+
+; This is from Juri Pakaste's <juri@iki.fi> base64.lisp
+(defparameter *encode-table*
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
+
+(defun base64-encode (string)
+  (let ((result (make-array
+                 (list (* 4 (truncate (/ (+ 2 (length string)) 3))))
+                 :element-type 'base-char)))
+    (do ((sidx 0 (+ sidx 3))
+         (didx 0 (+ didx 4))
+         (chars 2 2)
+         (value nil nil))
+        ((>= sidx (length string)) t)
+      (setf value (ash (logand #xFF (char-code (char string sidx))) 8))
+      (dotimes (n 2)
+        (when (< (+ sidx n 1) (length string))
+          (setf value
+                (logior value
+                        (logand #xFF (char-code (char string (+ sidx n 1))))))
+          (incf chars))
+        (when (= n 0)
+          (setf value (ash value 8))))
+      (setf (elt result (+ didx 3))
+            (elt *encode-table* (if (> chars 3) (logand value #x3F) 64)))
+      (setf value (ash value -6))
+      (setf (elt result (+ didx 2))
+            (elt *encode-table* (if (> chars 2) (logand value #x3F) 64)))
+      (setf value (ash value -6))
+      (setf (elt result (+ didx 1))
+            (elt *encode-table* (logand value #x3F)))
+      (setf value (ash value -6))
+      (setf (elt result didx)
+            (elt *encode-table* (logand value #x3F))))
+    result))
+
+(defun request-uri (url)
+  (assert (string-equal url "http://" :end1 7))
+  (if *proxy*
+      url
+      (let ((path-start (position #\/ url :start 7)))
+	(assert (and path-start) nil "url does not specify a file.")
+        (subseq url path-start))))
+
+(defun url-connection (url)
+  (let ((stream (make-stream-from-url (or *proxy* url)))
+        (host (url-host url)))
+    (format stream "GET ~A HTTP/1.0~C~CHost: ~A~C~CCookie: CCLAN-SITE=~A~C~C"
+            (request-uri url) #\Return #\Linefeed
+            host #\Return #\Linefeed
+            *cclan-mirror* #\Return #\Linefeed)
+    (when (and *proxy-passwd* *proxy-user*)
+      (format stream "Proxy-Authorization: Basic ~A~C~C"
+              (base64-encode (format nil "~A:~A" *proxy-user* *proxy-passwd*))
+              #\Return #\Linefeed))
+    (format stream "~C~C" #\Return #\Linefeed)
+    (force-output stream)
+    (list
+     (let* ((l (read-header-line stream))
+            (space (position #\Space l)))
+       (parse-integer l :start (1+ space) :junk-allowed t))
+     (loop for line = (read-header-line stream)
+           until (or (null line)
+                     (zerop (length line))
+                     (eql (elt line 0) (code-char 13)))
+           collect
+           (let ((colon (position #\: line)))
+             (cons (intern (string-upcase (subseq line 0 colon)) :keyword)
+                   (string-trim (list #\Space (code-char 13))
+                                (subseq line (1+ colon))))))
+     stream)))
+
+(defun download-link-for-package (package-name-or-url)
+  (if (= (mismatch package-name-or-url "http://") 7)
+    package-name-or-url
+    (format nil "http://www.cliki.net/~A?download"
+            package-name-or-url)))
+
+(defun download-link-for-signature (url)
+  (concatenate 'string url ".asc"))
+
+(defun download-files-for-package (package-name-or-url)
+  (multiple-value-bind (package-url package-file) 
+      (download-url-to-temporary-file
+       (download-link-for-package package-name-or-url))
+    (if (verify-gpg-signatures-p package-name-or-url)
+	(multiple-value-bind (signature-url signature-file) 
+	    (download-url-to-temporary-file
+	     (download-link-for-signature package-url))
+	  (declare (ignore signature-url))
+	  (values package-file signature-file))
+	(values package-file nil))))
+  
+(defun verify-gpg-signature (file-name signature-name)
+  (block verify
+    (loop
+      (restart-case
+	  (let ((tags (gpg-results file-name signature-name)))
+	    ;; test that command returned something 
+	    (unless tags
+	      (error 'gpg-shell-error))
+	    ;; test for obvious key/sig problems
+	    (let ((errsig (header-value :errsig tags)))
+	      (and errsig (error 'key-not-found :key-id errsig)))
+	    (let ((badsig (header-value :badsig tags)))
+	      (and badsig (error 'key-not-found :key-id badsig)))
+	    (let* ((good (header-value :goodsig tags))
+		   (id (first good))
+		   (name (format nil "~{~A~^ ~}" (rest good))))
+	      ;; good signature, but perhaps not trusted
+	      (restart-case
+		  (let ((trusted? (or (header-pair :trust_ultimate tags)
+				      (header-pair :trust_fully tags)))
+			(in-list? (assoc id *trusted-uids* :test #'equal)))
+		    (cond ((or trusted? in-list?)
+			   ;; ok
+			   )
+			  ((not trusted?)
+			   (error 'key-not-trusted 
+				  :key-user-name name :key-id id))
+			  ((not in-list?)
+			   (error 'author-not-trusted
+				  :key-user-name name :key-id id))))
+		(add-key (&rest rest)
+		  :report "Add to package supplier list"
+		  (declare (ignore rest))
+		  (pushnew (list id name) *trusted-uids*))))
+	    (return-from verify t))
+        (install-anyways
+	    (&rest rest)
+	  :report "Don't check GPG signature for this package"
+	  (declare (ignore rest))
+	  (return-from verify t))
+        (retry-gpg-check
+	    (&rest args)
+	  :report "Retry GPG check \(e.g., after downloading the key\)"
+	  (declare (ignore args))
+	  nil)))))
+
+(defun header-value (name headers)
+  "Searchers headers for name _without_ case sensitivity. Headers should be an alist mapping symbols to values; name a symbol. Returns the value if name is found or nil if it is not."
+  (cdr (header-pair name headers)))
+
+(defun header-pair (name headers)
+  "Searchers headers for name _without_ case sensitivity. Headers should be an alist mapping symbols to values; name a symbol. Returns the \(name value\) pair if name is found or nil if it is not."
+  (assoc name headers 
+         :test (lambda (a b) 
+                 (string-equal (symbol-name a) (symbol-name b)))))
+
+(defun validate-preferred-location ()
+  (typecase *preferred-location*
+    (null t)
+    ((integer 0) 
+     (assert (<= 1 *preferred-location* (length *locations*)) 
+	     (*preferred-location*)
+	     'invalid-preferred-location-number-error
+	     :preferred-location *preferred-location*))
+    ((or symbol string) 
+     (assert (find *preferred-location* *locations* 
+		   :test (if (typep *preferred-location* 'symbol)
+			     #'eq #'string-equal) :key #'third)
+	     (*preferred-location*)
+	     'invalid-preferred-location-name-error 
+	     :preferred-location *preferred-location*))
+    (t
+     (assert nil 
+	     (*preferred-location*)
+	     'invalid-preferred-location-error 
+	     :preferred-location *preferred-location*)))
+  *preferred-location*)
+
+(defun select-location ()
+  (loop with n-locations = (length *locations*)
+     for response = (progn
+		      (format t "Install where?~%")
+		      (loop for (source system name) in *locations*
+			 for i from 1
+			 do (format t "~A) ~A: ~%   System in ~A~%   Files in ~A ~%"
+				    i name system source))
+		      (format t "0) Abort installation.~% --> ")
+		      (force-output)
+		      (read))
+     when (and (numberp response)
+	       (<= 1 response n-locations))
+     return response
+     when (and (numberp response)
+	       (zerop response))
+     do (abort (make-condition 'installation-abort))))
+
+(defun install-location ()
+  (validate-preferred-location)
+  (let ((location-selection (or *preferred-location*
+				(select-location))))
+    (etypecase location-selection
+      (integer 
+       (elt *locations* (1- location-selection)))
+      ((or symbol string)
+       (find location-selection *locations* :key #'third
+	     :test (if (typep location-selection 'string) 
+		      #'string-equal #'eq))))))
+
+
+;;; install-package --
+
+(defun find-shell-command (command)
+  (loop for directory in *shell-search-paths* do
+       (let ((target (make-pathname :name command :type nil
+				    :directory directory)))
+	 (when (probe-file target)
+	   (return-from find-shell-command (namestring target)))))
+  (values nil))
+
+(defun tar-command ()
+  #-(or :win32 :mswindows)
+  (find-shell-command *gnu-tar-program*)
+  #+(or :win32 :mswindows)
+  *cygwin-bash-program*)
+
+(defun tar-arguments (source packagename)
+  #-(or :win32 :mswindows :scl)
+  (list "-C" (system-namestring (truename source))
+	"-xzvf" (system-namestring (truename packagename)))
+  #+(or :win32 :mswindows)
+  (list "-l"
+	"-c"
+	(format nil "\"tar -C \\\"`cygpath '~A'`\\\" -xzvf \\\"`cygpath '~A'`\\\"\""
+		(system-namestring (truename source))
+		(system-namestring (truename packagename))))
+  #+scl
+  (list "-C" (ext:unix-namestring (truename source))
+	"-xzvf" (ext:unix-namestring (truename packagename))))
+
+(defun extract-using-tar (to-dir tarball)
+  (let ((tar-command (tar-command)))
+    (if (and tar-command (probe-file tar-command))
+	(return-output-from-program tar-command
+				    (tar-arguments to-dir tarball))
+	(warn "Cannot find tar command ~S." tar-command))))
+
+(defun extract (to-dir tarball)
+  (or (some #'(lambda (extractor) (funcall extractor to-dir tarball))
+            *tar-extractors*)
+      (error "Unable to extract tarball ~A." tarball)))
+
+(defun install-package (source system packagename)
+  "Returns a list of system names (ASDF or MK:DEFSYSTEM) for installed systems."
+  (ensure-directories-exist source)
+  (ensure-directories-exist system)
+  (let* ((tar-output (extract source packagename))
+	 (tar (if (string= tar-output "x " :end1 2)
+		(subseq tar-output 2)
+		tar-output))
+	 (pos-slash (or (position #\/ tar)
+                        (position #\Return tar)
+                        (position #\Linefeed tar)))
+	 (*default-pathname-defaults*
+	  (merge-pathnames
+	   (make-pathname :directory
+			  `(:relative ,(subseq tar 0 pos-slash)))
+	   source)))
+    ;(princ tar)
+    (loop for sysfile in (append
+                          (directory
+		           (make-pathname :defaults *default-pathname-defaults*
+                                          :name :wild
+                                          :type "asd"))
+                          (directory
+		           (make-pathname :defaults *default-pathname-defaults*
+                                          :name :wild
+                                          :type "system")))
+       do (maybe-symlink-sysfile system sysfile)
+       do (installer-msg t "Found system definition: ~A" sysfile)
+       do (maybe-update-central-registry sysfile)
+       collect sysfile)))
+
+(defun maybe-update-central-registry (sysfile)
+  ;; make sure that the systems we install are accessible in case 
+  ;; asdf-install:*locations* and asdf:*central-registry* are out 
+  ;; of sync
+  (add-registry-location sysfile))
+
+(defun temp-file-name (p)
+  (declare (ignore p))
+  (let ((pathname nil))
+    (loop for i = 0 then (1+ i) do
+	 (setf pathname 
+	       (merge-pathnames
+		(make-pathname
+		 :name (format nil "asdf-install-~d" i)
+		 :type "asdf-install-tmp")
+		*temporary-directory*))
+	 (unless (probe-file pathname)
+	   (return-from temp-file-name pathname)))))
+
+
+;;; install
+;;; This is the external entry point.
+
+(defun install (packages &key (propagate nil) (where *preferred-location*))
+  (let* ((*preferred-location* where)
+	 (*temporary-files* nil)
+         (trusted-uid-file 
+          (merge-pathnames "trusted-uids.lisp" *private-asdf-install-dirs*))
+	 (*trusted-uids*
+          (when (probe-file trusted-uid-file)
+            (with-open-file (f trusted-uid-file) (read f))))
+         (old-uids (copy-list *trusted-uids*))
+         #+asdf
+         (*defined-systems* (if propagate 
+                              (make-hash-table :test 'equal)
+                              *defined-systems*))
+         (packages (if (atom packages) (list packages) packages))
+         (*propagate-installation* propagate)
+         (*systems-installed-this-time* nil))
+    (unwind-protect
+      (destructuring-bind (source system name) (install-location)
+        (declare (ignore name))
+        (labels 
+	    ((one-iter (packages)
+	       (let ((packages-to-install nil))
+		 (loop for p in (mapcar #'string packages) do
+		      (cond ((local-archive-p p)
+			     (setf packages-to-install
+				   (append packages-to-install 
+					   (install-package source system p))))
+			    (t
+			     (multiple-value-bind (package signature)
+				 (download-files-for-package p)
+			       (when (verify-gpg-signatures-p p)
+				 (verify-gpg-signature package signature))
+			       (installer-msg t "Installing ~A in ~A, ~A"
+					      p source system)
+			       (install-package source system package))
+			     (setf packages-to-install
+				   (append packages-to-install 
+					   (list p))))))
+		 (dolist (package packages-to-install)
+		   (setf package
+			 (etypecase package
+			   (symbol package)
+			   (string (intern package :asdf-install))
+			   (pathname (intern
+				      (namestring (pathname-name package))
+				      :asdf-install))))
+		   (handler-bind
+		       (
+			#+asdf
+			(asdf:missing-dependency
+			 (lambda (c) 
+			   (installer-msg
+			    t
+			    "Downloading package ~A, required by ~A~%"
+			    (asdf::missing-requires c)
+			    (asdf:component-name
+			     (asdf::missing-required-by c)))
+			   (one-iter 
+			    (list (asdf::coerce-name 
+				   (asdf::missing-requires c))))
+			   (invoke-restart 'retry)))
+			#+mk-defsystem
+			(make:missing-component
+			 (lambda (c) 
+			   (installer-msg 
+			    t
+			    "Downloading package ~A, required by ~A~%"
+			    (make:missing-component-name c)
+			    package)
+			   (one-iter (list (make:missing-component-name c)))
+			   (invoke-restart 'retry))))
+		     (loop (multiple-value-bind (ret restart-p)
+			       (with-simple-restart
+				   (retry "Retry installation")
+				 (push package *systems-installed-this-time*)
+				 (load-package package))
+			     (declare (ignore ret))
+			     (unless restart-p (return)))))))))
+	  (one-iter packages)))
+      ;;; cleanup
+      (unless (equal old-uids *trusted-uids*)
+        (let ((create-file-p nil))
+	  (unless (probe-file trusted-uid-file)
+	    (installer-msg t "Trusted UID file ~A does not exist"
+			   (namestring trusted-uid-file))
+	    (setf create-file-p
+		  (y-or-n-p "Do you want to create the file?")))
+          (when (or create-file-p (probe-file trusted-uid-file))
+	    (ensure-directories-exist trusted-uid-file)
+	    (with-open-file (out trusted-uid-file
+                                 :direction :output
+                                 :if-exists :supersede)
+	      (with-standard-io-syntax
+	        (prin1 *trusted-uids* out))))))
+      (dolist (l *temporary-files* t)
+	(when (probe-file l) (delete-file l))))
+    (nreverse *systems-installed-this-time*)))
+
+(defun local-archive-p (package)
+  #+(or :sbcl :allegro) (probe-file package)
+  #-(or :sbcl :allegro) (and (/= (mismatch package "http://") 7)
+			   (probe-file package)))
+
+(defun load-package (package)
+  #+asdf
+  (progn
+    (installer-msg t "Loading system ~S via ASDF." package)
+    (asdf:operate 'asdf:load-op package))
+  #+mk-defsystem
+  (progn
+    (installer-msg t "Loading system ~S via MK:DEFSYSTEM." package)
+    (mk:load-system package)))
+
+;;; uninstall --
+
+(defun uninstall (system &optional (prompt t))
+  #+asdf
+  (let* ((asd (asdf:system-definition-pathname system))
+	 (system (asdf:find-system system))
+	 (dir (pathname-sans-name+type
+	       (asdf::resolve-symlinks asd))))
+    (when (or (not prompt)
+	      (y-or-n-p
+	       "Delete system ~A~%asd file: ~A~%sources: ~A~%Are you sure?"
+	       system asd dir))
+      #-(or :win32 :mswindows)
+      (delete-file asd)
+      (let ((dir (#-scl system-namestring #+scl ext:unix-namestring (truename dir))))
+	(when dir
+	  (asdf:run-shell-command "rm -r '~A'" dir)))))
+
+  #+mk-defsystem
+  (multiple-value-bind (sysfile sysfile-exists-p)
+      (mk:system-definition-pathname system)
+    (when sysfile-exists-p
+      (let ((system (ignore-errors (mk:find-system system :error))))
+        (when system
+          (when (or (not prompt)
+	            (y-or-n-p
+	             "Delete system ~A.~%system file: ~A~%Are you sure?"
+	             system
+                     sysfile))
+            (mk:clean-system system)
+            (delete-file sysfile)
+            (dolist (f (mk:files-in-system system))
+              (delete-file f)))
+          ))
+      )))
+
+      
+;;; some day we will also do UPGRADE, but we need to sort out version
+;;; numbering a bit better first
+
+#+(and :asdf (or :win32 :mswindows))
+(defun sysdef-source-dir-search (system)
+  (let ((name (asdf::coerce-name system)))
+    (dolist (location *locations*)
+      (let* ((dir (first location))
+             (files (directory (merge-pathnames
+                                (make-pathname :name name
+                                               :type "asd"
+                                               :version :newest
+                                               :directory '(:relative :wild)
+                                               :host nil
+                                               :device nil)
+                                dir))))
+        (dolist (file files)
+          (when (probe-file file)
+            (return-from sysdef-source-dir-search file)))))))
+
+(defmethod asdf:find-component :around 
+    ((module (eql nil)) name &optional version)
+  (declare (ignore version))
+  (when (or (not *propagate-installation*) 
+            (member name *systems-installed-this-time* 
+                    :test (lambda (a b)
+                            (flet ((ensure-string (x)
+                                     (etypecase x
+                                       (symbol (symbol-name x))
+                                       (string x))))
+                              (string-equal (ensure-string a) (ensure-string b))))))
+    (call-next-method)))
+
+(defun show-version-information ()
+  (let ((version (asdf-install-version)))
+    (if version
+      (format *standard-output* "~&;;; ASDF-Install version ~A"
+              version)
+      (format *standard-output* "~&;;; ASDF-Install version unknown; unable to find ASDF system definition."))
+  (values)))
+
+(defun asdf-install-version ()
+  "Returns the ASDf-Install version information as a string or nil if it cannot be determined."
+  (let ((system (asdf:find-system 'asdf-install)))
+    (when system (asdf:component-version system))))
+
+;; load customizations if any
+(eval-when (:load-toplevel :execute)
+  (let* ((*package* (find-package :asdf-install-customize))
+         (file (probe-file (merge-pathnames
+			    (make-pathname :name ".asdf-install")
+			    (truename (user-homedir-pathname))))))
+    (when file (load file))))
+
+;;; end of file -- install.lisp --
Index: /branches/new-random/tools/asdf-install/lift-standard.config
===================================================================
--- /branches/new-random/tools/asdf-install/lift-standard.config	(revision 13309)
+++ /branches/new-random/tools/asdf-install/lift-standard.config	(revision 13309)
@@ -0,0 +1,38 @@
+;;; configuration for LIFT tests
+
+;; settings
+(:if-dribble-exists :supersede)
+(:dribble "asdf-install.dribble")
+(:print-length 10)
+(:print-level 5)
+(:print-test-case-names t)
+
+;; suites to run
+(test-asdf-install)
+
+;; report properties
+(:report-property :title "ASDF-Install | Test results")
+(:report-property :relative-to test-asdf-install)
+
+
+
+(:report-property :style-sheet "test-style.css")
+(:report-property :if-exists :supersede)
+(:report-property :format :html)
+(:report-property :name "test-results/test-report.html")
+(:report-property :unique-name t)
+(:build-report)
+
+(:report-property :unique-name t)
+(:report-property :format :describe)
+(:report-property :name "test-results/test-report.txt")
+(:build-report)
+
+
+(:report-property :format :save)
+(:report-property :name "test-results/test-report.sav")
+(:build-report)
+
+(:report-property :format :describe)
+(:report-property :full-pathname *standard-output*)
+(:build-report)
Index: /branches/new-random/tools/asdf-install/load-asdf-install.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/load-asdf-install.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/load-asdf-install.lisp	(revision 13309)
@@ -0,0 +1,90 @@
+;;; -*- Mode: Lisp -*-
+
+;;; load-asdf-install.lisp --
+;;; Generic loader for ASDF-INSTALL.
+
+(eval-when (:load-toplevel :execute)
+  (unless (find-package '#:asdf-install-loader)
+    (make-package '#:asdf-install-loader :use '(#:common-lisp))))
+
+(in-package :asdf-install-loader)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defparameter *asdf-install-directory*
+    (make-pathname :host (pathname-host *load-truename*)
+		   :device (pathname-device *load-truename*)
+		   :directory (pathname-directory *load-truename*)
+		   ;; :case :common ; Do we need this?
+		   )))
+
+
+(defun cl-user::load-asdf-install
+  (&key
+   (directory *asdf-install-directory*)
+   (compile-first-p nil)
+   (load-verbose *load-verbose*)
+   (print-herald t)
+   )
+  (when print-herald
+    (format *standard-output*
+	    "~&;;; ASDF-INSTALL: Loading ASDF-INSTALL package from directory~@
+               ;;;               \"~A\"~2%"
+	    (namestring (pathname directory))))
+  (let ((directory (pathname directory)))
+    (flet ((load-and-or-compile (file)
+	     (if compile-first-p
+		 (multiple-value-bind (output-truename warnings-p failure-p)
+		     (compile-file file)
+		   ;; (declare (ignore warnings-p))
+		   (when failure-p
+		     (format *standard-output*
+			     ";;; File ~S compiled~@
+                              ;;; Warnings ~S, Failure ~S.~%"
+			     output-truename
+			     warnings-p
+			     failure-p)
+		     (return-from cl-user::load-asdf-install nil)
+		     )
+		   (load output-truename :verbose load-verbose))
+		 (load file :verbose load-verbose)))
+	   )
+
+      (setf (logical-pathname-translations "ASDF-INSTALL-LIBRARY")
+	    `(("**;*.*.*"
+	       ,(make-pathname
+		 :host (pathname-host directory)
+		 :device (pathname-device directory)
+		 :directory (append (pathname-directory directory)
+				    (list :wild-inferiors))))
+	      ("**;*.*"
+	       ,(make-pathname
+		 :host (pathname-host directory)
+		 :device (pathname-device directory)
+		 :directory (append (pathname-directory directory)
+				    (list :wild-inferiors))))))
+
+      (load-and-or-compile "ASDF-INSTALL-LIBRARY:defpackage.lisp")
+      (load-and-or-compile "ASDF-INSTALL-LIBRARY:port.lisp")
+
+      (unless (find-package '#:split-sequence)
+        (load-and-or-compile "ASDF-INSTALL-LIBRARY:split-sequence.lisp"))
+
+      (load-and-or-compile "ASDF-INSTALL-LIBRARY:installer.lisp")
+
+      ;; (load-and-or-compile "ASDF-INSTALL-LIBRARY:loader.lisp")
+
+      ))
+  (pushnew :asdf-install *features*)
+  (provide 'asdf-install)
+
+  ;; To clean a minimum (and to make things difficult to debug)...
+  ;; (delete-package '#:asdf-install-loader)
+  )
+
+
+;;; Automatically load the library.
+
+(eval-when (:load-toplevel :execute)
+  (cl-user::load-asdf-install))
+
+;;; end of file -- load-asdf-install.lisp --
Index: /branches/new-random/tools/asdf-install/loader.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/loader.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/loader.lisp	(revision 13309)
@@ -0,0 +1,20 @@
+(in-package :cl-user)
+
+(eval-when (:load-toplevel)
+  (unless (find-package 'asdf)
+    (require 'asdf)))
+
+(eval-when (:load-toplevel)
+  (unless (find-package 'asdf)
+    (error "ASDF-Install requires ASDF to load"))    
+  (let ((asdf::*verbose-out* nil))
+    (require 'asdf-install)))
+
+#+sbcl
+(defun run ()
+  (handler-case
+      (apply #'asdf-install:install (cdr *posix-argv*))
+    (error (c)
+      (format *error-output* "Install failed due to error:~%  ~A~%" c)
+      (sb-ext:quit :unix-status 1))))
+
Index: /branches/new-random/tools/asdf-install/notes.text
===================================================================
--- /branches/new-random/tools/asdf-install/notes.text	(revision 13309)
+++ /branches/new-random/tools/asdf-install/notes.text	(revision 13309)
@@ -0,0 +1,103 @@
+fails: (asdf-install:install "http://common-lisp.net/project/cl-containers/asdf-binary-locations/asdf-binary-locations_latest.tar.gz")
+
+Need tests for new *temporary-directory*
+  how: ?
+
+why doesn't return-output-from-program use shell-command?
+
+remove asdf-doc directory (or symlink it or something)
+
+
+#### To-do - Ijara
+
+- Cleanup current ASDFI even more
+- build in untar
+- build in call to CVS, SVN, DARCS, (make modular, obviously)
+- supports parts of system-check
+- support uninstall
+- supoort logging
+- support aliasing
+- support experimentation
+- support
+
+#### To-do - ASDF-Install
+
+- better place for temporary files
+
+- clean up symlink files to use shell-command
+
+- digitool and shell-command
+
+- Use a condition instead
+  (error "ASDF-INSTALL: can't untar ~S." packagename)
+
+Which directory "systems" or "site-systems"
+
+#-:digitool
+(read-signature (data stream)
+                (read-sequence data stream))
+#+:digitool
+(read-signature (data stream)
+                (multiple-value-bind (reader arg)
+                                     (ccl:stream-reader stream)
+                  (let ((byte 0))
+                    (dotimes (i (length data))
+                      (unless (setf byte (funcall reader arg))
+                        (error 'download-error :url  (concatenate 'string url ".asc")
+                               :response 200))
+                      (setf (char data i) (code-char byte))))))
+
+#-(or :win32 :mswindows)
+(return-output-from-program *gnu-tar-program*
+                            (list "-C" (namestring (truename source))
+                                  "-xzvf" (namestring (truename packagename))))
+#+(or :win32 :mswindows)
+(return-output-from-program *cygwin-bash-program*
+                            (list "-l"
+                                  "-c"
+                                  (format nil "\"tar -C \\\"`cygpath '~A'`\\\" -xzvf \\\"`cygpath '~A'`\\\"\""
+                                          (namestring (truename source))
+                                          (namestring (truename packagename)))))
+
+#+(or :sbcl :alisp) (probe-file p)
+#-(or :sbcl :alisp) (and (/= (mismatch p "http://") 7)
+                         (probe-file p))
+
+
+- tests
+
+- new features
+-- force reinstallation of dependencies
+-- use places other than the CLiki for finding files 
+
+
+;;; ---------------------------------------------------------------------------
+
+;;; port
+
+;; pull in networking
+;; get-env-variable
+;; copy-stream
+;; make-stream-from-url
+;; make-stream-from-gpg-command
+;; make-temp-sig
+;; return-output-from-program
+;; unlink-file ==? delete-file
+;; symlink-files
+
+#+digitool
+;; system-namestring
+
+
+;;; split-sequence
+;;;; all we use is split-sequence-if
+
+package
+split-sequence
+split-sequence-if
+split-sequence-if-not
+partition
+partition-if
+partition-if-not
+
+
Index: /branches/new-random/tools/asdf-install/port.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/port.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/port.lisp	(revision 13309)
@@ -0,0 +1,498 @@
+(in-package #:asdf-install)
+
+(defvar *temporary-files*)
+
+(defparameter *shell-path* "/bin/sh"
+  "The path to a Bourne compatible command shell in physical pathname notation.")
+
+(eval-when (:load-toplevel :compile-toplevel :execute)
+  #+:allegro
+  (require :osi)
+  #+:allegro
+  (require :socket)
+  #+:digitool
+  (require :opentransport)
+  #+:ecl
+  (require :sockets)
+  #+:lispworks
+  (require "comm")
+  )
+
+(defun get-env-var (name)
+  #+:allegro (sys:getenv name)
+  #+:clisp (ext:getenv name)
+  #+:cmu (cdr (assoc (intern (substitute #\_ #\- name)
+                             :keyword)
+                     ext:*environment-list*))
+  #+:ecl (ext:getenv name)
+  #+:lispworks (lw:environment-variable name)
+  #+(or :mcl :openmcl) (ccl::getenv name)
+  #+:sbcl (sb-ext:posix-getenv name)
+  #+:scl (cdr (assoc name ext:*environment-list* :test #'string=))
+  )
+
+#-:digitool
+(defun system-namestring (pathname)
+  #+:openmcl
+  (ccl:native-translated-namestring pathname)
+  #-:openmcl
+  (namestring (truename pathname)))
+
+#+:digitool
+(defvar *start-up-volume*
+  (second (pathname-directory (truename "ccl:"))))
+
+#+:digitool
+(defun system-namestring (pathname)
+  ;; this tries to adjust the root directory to eliminate the spurious
+  ;; volume name for the boot file system; it also avoids use of
+  ;; TRUENAME as some applications are for not yet existent files
+  (let ((truename (probe-file pathname)))
+    (unless truename
+      (setf truename
+            (translate-logical-pathname
+             (merge-pathnames pathname *default-pathname-defaults*))))
+    (let ((directory (pathname-directory truename)))
+      (flet ((string-or-nil (value) (when (stringp value) value))
+             (absolute-p (directory) (eq (first directory) :absolute))
+             (root-volume-p (directory)
+               (equal *start-up-volume* (second directory))))
+        (format nil "~:[~;/~]~{~a/~}~@[~a~]~@[.~a~]"
+                (absolute-p directory)
+                (if (root-volume-p directory) (cddr directory) (cdr directory))
+                (string-or-nil (pathname-name truename))
+                (string-or-nil (pathname-type truename)))))))
+
+#+:digitool
+(progn
+  (defun |read-linefeed-eol-comment|
+         (stream char &optional (eol '(#\return #\linefeed)))
+    (loop (setf char (read-char stream nil nil))
+          (unless char (return))
+          (when (find char eol) (return)))
+    (values))
+  
+  (set-syntax-from-char #\linefeed #\space)
+  (set-macro-character #\; #'|read-linefeed-eol-comment| nil *readtable*))
+
+;; for non-SBCL we just steal this from SB-EXECUTABLE
+#-(or :digitool)
+(defvar *stream-buffer-size* 8192)
+#-(or :digitool)
+(defun copy-stream (from to)
+  "Copy into TO from FROM until end of the input stream, in blocks of
+*stream-buffer-size*.  The streams should have the same element type."
+  (unless (subtypep (stream-element-type to) (stream-element-type from))
+    (error "Incompatible streams ~A and ~A." from to))
+  (let ((buf (make-array *stream-buffer-size*
+			 :element-type (stream-element-type from))))
+    (loop
+      (let ((pos #-(or :clisp :cmu) (read-sequence buf from)
+                 #+:clisp (ext:read-byte-sequence buf from :no-hang nil)
+                 #+:cmu (sys:read-n-bytes from buf 0 *stream-buffer-size* nil)))
+        (when (zerop pos) (return))
+        (write-sequence buf to :end pos)))))
+
+#+:digitool
+(defun copy-stream (from to)
+  "Perform copy and map EOL mode."
+  (multiple-value-bind (reader reader-arg) (ccl::stream-reader from)
+    (multiple-value-bind (writer writer-arg) (ccl::stream-writer to)
+      (let ((datum nil))
+        (loop (unless (setf datum (funcall reader reader-arg))
+                (return))
+              (funcall writer writer-arg datum))))))
+
+(defun make-stream-from-url (url)
+  #+(or :sbcl :ecl)
+  (let ((s (make-instance 'sb-bsd-sockets:inet-socket
+             :type :stream
+             :protocol :tcp)))
+    (sb-bsd-sockets:socket-connect
+     s (car (sb-bsd-sockets:host-ent-addresses
+             (sb-bsd-sockets:get-host-by-name (url-host url))))
+     (url-port url))
+    (sb-bsd-sockets:socket-make-stream 
+     s
+     :input t 
+     :output t
+     :buffering :full
+     :external-format :iso-8859-1))
+  #+:cmu
+  (sys:make-fd-stream (ext:connect-to-inet-socket (url-host url) (url-port url))
+                      :input t :output t :buffering :full)
+  #+:scl
+  (sys:make-fd-stream (ext:connect-to-inet-socket (url-host url) (url-port url))
+                      :input t :output t :buffering :full
+		      :external-format :iso-8859-1)
+  #+:lispworks
+  (comm:open-tcp-stream (url-host url) (url-port url)
+                        #+(and :lispworks :win32) :element-type
+                        #+(and :lispworks :win32) '(unsigned-byte 8))
+  #+:allegro
+  (socket:make-socket :remote-host (url-host url)
+                      :remote-port (url-port url))
+  #+:clisp
+  (socket:socket-connect (url-port url) (url-host url)
+                         :external-format
+                         (ext:make-encoding :charset 'charset:iso-8859-1 :line-terminator :unix))
+  #+:openmcl
+  (ccl:make-socket :remote-host (url-host url)
+                   :remote-port (url-port url))
+  #+:digitool
+  (ccl::open-tcp-stream (url-host url) (url-port url)
+                        :element-type 'unsigned-byte))
+
+
+#+:sbcl
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (let ((proc (sb-ext:run-program
+                 program
+                 args
+                 :output out-stream
+                 :search t
+                 :wait t)))
+      (when (or (null proc)
+                (and (member (sb-ext:process-status proc) '(:exited :signaled))
+                     (not (zerop (sb-ext:process-exit-code proc)))))
+        (return-from return-output-from-program nil)))))
+
+#+(or :cmu :scl)
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (let ((proc (ext:run-program
+                 program
+                 args
+                 :output out-stream
+                 :wait t)))
+      (when (or (null proc)
+                (and (member (ext:process-status proc) '(:exited :signaled))
+                     (not (zerop (ext:process-exit-code proc)))))
+        (return-from return-output-from-program nil)))))
+
+#+:lispworks
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (unless (zerop (sys:call-system-showing-output
+                    (format nil #-:win32 "~A~{ '~A'~}"
+                            #+:win32 "~A~{ ~A~}"
+                            program args)
+                    :prefix ""
+                    :show-cmd nil
+                    :output-stream out-stream))
+      (return-from return-output-from-program nil))))
+
+#+(and :clisp (not :win32))
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (let ((stream
+           (ext:run-program program
+                            :arguments args
+                            :output :stream
+                            :wait nil)))
+      (loop for line = (read-line stream nil)
+            while line
+            do (write-line line out-stream)))))
+
+#+(and :clisp :win32)
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (let ((stream
+           (ext:run-shell-command
+            (format nil "~A~{ ~A~}" program args
+                    :output :stream
+                    :wait nil))))
+      (loop for line = (ignore-errors (read-line stream nil))
+            while line
+            do (write-line line out-stream)))))
+
+#+:allegro
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (let ((stream
+           (excl:run-shell-command
+            #-:mswindows
+            (concatenate 'vector
+                         (list program)
+                         (cons program args))
+            #+:mswindows
+            (format nil "~A~{ ~A~}" program args)
+            :output :stream
+            :wait nil)))
+      (loop for line = (read-line stream nil)
+            while line
+            do (write-line line out-stream)))))
+
+#+:ecl
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (let ((stream (ext:run-program program args :output :stream)))
+      (when stream
+	(loop for line = (ignore-errors (read-line stream nil))
+	      while line
+	      do (write-line line out-stream))))))
+
+#+:openmcl
+(defun return-output-from-program (program args)
+  (with-output-to-string (out-stream)
+    (let ((proc (ccl:run-program program args
+                                 :input nil
+                                 :output :stream
+                                 :wait nil)))
+      (loop for line = (read-line
+			(ccl:external-process-output-stream proc) nil nil nil)
+            while line
+            do (write-line line out-stream)))))
+
+#+:digitool
+(defun return-output-from-program (program args)
+  (ccl::call-system (format nil "~A~{ '~A'~} 2>&1" program args)))
+
+(defun unlink-file (pathname)
+  ;; 20070208 gwking@metabang.com - removed lisp-specific os-level calls
+  ;; in favor of a simple delete
+  (delete-file pathname))
+
+(defun symlink-files (old new)
+  (let* ((old (#-scl system-namestring #+scl ext:unix-namestring old))
+	 (new (#-scl system-namestring #+scl ext:unix-namestring new #+scl nil))
+	 ;; 20070811 - thanks to Juan Jose Garcia-Ripoll for pointing
+	 ;; that ~a would wreck havoc if the working directory had a space
+	 ;; in the pathname
+	 (command (format nil "ln -s ~s ~s" old new)))
+    (format t "~S~%" command)
+    (shell-command command)))
+
+(defun maybe-symlink-sysfile (system sysfile)
+  (declare (ignorable system sysfile))
+  #-(or :win32 :mswindows)
+  (let ((target (merge-pathnames
+                 (make-pathname :name (pathname-name sysfile)
+                                :type (pathname-type sysfile))
+                 system)))
+    (when (probe-file target)
+      (unlink-file target))
+    (symlink-files sysfile target)))
+
+;;; ---------------------------------------------------------------------------
+;;; read-header-line
+;;; ---------------------------------------------------------------------------
+
+#-:digitool
+(defun read-header-line (stream)
+  (read-line stream))
+
+#+:digitool
+(defun read-header-line (stream &aux (line (make-array 16
+                                                       :element-type 'character
+                                                       :adjustable t
+                                                       :fill-pointer 0))
+                                (byte nil))
+  (print (multiple-value-bind (reader arg)
+                              (ccl::stream-reader stream)
+           (loop (setf byte (funcall reader arg))
+                 (case byte
+                   ((nil)
+                    (return))
+                   ((#.(char-code #\Return)
+                     #.(char-code #\Linefeed))
+                    (case (setf byte (funcall reader arg))
+                      ((nil #.(char-code #\Return) #.(char-code #\Linefeed)))
+                      (t (ccl:stream-untyi stream byte)))
+                    (return))
+                   (t
+                    (vector-push-extend (code-char byte) line))))
+           (when (or byte (plusp (length line)))
+             line))))
+
+(defun open-file-arguments ()
+  (append 
+   #+(or sbcl ccl)
+   '(:external-format :latin1)
+   #+:scl
+   '(:external-format :iso-8859-1)
+   #+(or :clisp :digitool (and :lispworks :win32))
+   '(:element-type (unsigned-byte 8))))
+
+(defun download-url-to-file (url file-name)
+  "Resolves url and then downloads it to file-name; returns the url actually used."
+  (multiple-value-bind (response headers stream)
+      (loop
+       (destructuring-bind (response headers stream)
+	   (url-connection url)
+	 (unless (member response '(301 302))
+	   (return (values response headers stream)))
+	 (close stream)
+	 (setf url (header-value :location headers))))
+    (when (>= response 400)
+      (error 'download-error :url url :response response))
+    (let ((length (parse-integer (or (header-value :content-length headers) "")
+				 :junk-allowed t)))
+      (installer-msg t "Downloading ~A bytes from ~A to ~A ..."
+		     (or length "some unknown number of")
+		     url
+		     file-name)
+      (force-output)
+      #+:clisp (setf (stream-element-type stream)
+		     '(unsigned-byte 8))
+      (let ((ok? nil) (o nil))
+	(unwind-protect
+	     (progn
+	       (setf o (apply #'open file-name 
+			      :direction :output :if-exists :supersede
+			      (open-file-arguments)))
+	       #+(or :cmu :digitool)
+	       (copy-stream stream o)
+	       #-(or :cmu :digitool)
+	       (if length
+		   (let ((buf (make-array length
+					  :element-type
+					  (stream-element-type stream))))
+		     #-:clisp (read-sequence buf stream)
+		     #+:clisp (ext:read-byte-sequence buf stream :no-hang nil)
+		     (write-sequence buf o))
+		   (copy-stream stream o))
+	       (setf ok? t))
+	  (when o (close o :abort (null ok?))))))
+    (close stream))
+  (values url))
+
+(defun download-url-to-temporary-file (url)
+  "Attempts to download url to a new, temporary file. Returns the resolved url and the file name \(as multiple values\)."
+  (let ((tmp (temp-file-name url)))
+    (pushnew tmp *temporary-files*)
+    (values (download-url-to-file url tmp) tmp)))
+
+(defun gpg-results (package signature)
+  (let ((tags nil))
+    (with-input-from-string
+	(gpg-stream 
+	 (shell-command (format nil "gpg --status-fd 1 --verify ~s ~s"
+				(namestring signature) (namestring package))))
+      (loop for l = (read-line gpg-stream nil nil)
+	 while l
+	 do (print l)
+	 when (> (mismatch l "[GNUPG:]") 6)
+	 do (destructuring-bind (_ tag &rest data)
+		(split-sequence-if (lambda (x)
+				     (find x '(#\Space #\Tab)))
+				   l)
+	      (declare (ignore _))
+	      (pushnew (cons (intern (string-upcase tag) :keyword)
+			     data) tags)))
+      tags)))
+
+#+allegro
+(defun shell-command (command)
+  (multiple-value-bind (output error status)
+	               (excl.osi:command-output command :whole t)
+    (values output error status)))
+
+#+clisp
+(defun shell-command (command)
+  ;; BUG: CLisp doesn't allow output to user-specified stream
+  (values
+   nil
+   nil
+   (ext:run-shell-command  command :output :terminal :wait t)))
+
+#+(or :cmu :scl)
+(defun shell-command (command)
+  (let* ((process (ext:run-program
+                   *shell-path*
+                   (list "-c" command)
+                   :input nil :output :stream :error :stream))
+         (output (file-to-string-as-lines (ext::process-output process)))
+         (error (file-to-string-as-lines (ext::process-error process))))
+    (close (ext::process-output process))
+    (close (ext::process-error process))
+    (values
+     output
+     error
+     (ext::process-exit-code process))))
+
+#+ecl
+(defun shell-command (command)
+  ;; If we use run-program, we do not get exit codes
+  (values nil nil (ext:system command)))
+
+#+lispworks
+(defun shell-command (command)
+  ;; BUG: Lispworks combines output and error streams
+  (let ((output (make-string-output-stream)))
+    (unwind-protect
+      (let ((status
+             (system:call-system-showing-output
+              command
+              :prefix ""
+              :show-cmd nil
+              :output-stream output)))
+        (values (get-output-stream-string output) nil status))
+      (close output))))
+
+#+openmcl
+(defun shell-command (command)
+  (let* ((process (create-shell-process command t))
+         (output (file-to-string-as-lines 
+                  (ccl::external-process-output-stream process)))
+         (error (file-to-string-as-lines
+                 (ccl::external-process-error-stream process))))
+    (close (ccl::external-process-output-stream process))
+    (close (ccl::external-process-error-stream process))
+    (values output
+            error
+            (process-exit-code process))))
+
+#+openmcl
+(defun create-shell-process (command wait)
+  (ccl:run-program
+   *shell-path*
+   (list "-c" command)
+   :input nil :output :stream :error :stream
+   :wait wait))
+
+#+openmcl
+(defun process-exit-code (process)
+  (nth-value 1 (ccl:external-process-status process)))
+
+#+digitool
+(defun shell-command (command)
+  ;; BUG: I have no idea what this returns
+  (ccl::call-system command))
+
+#+sbcl
+(defun shell-command (command)
+  (let* ((process (sb-ext:run-program
+                   *shell-path*
+                   (list "-c" command)
+                   :input nil :output :stream :error :stream))
+         (output (file-to-string-as-lines (sb-impl::process-output process)))
+         (error (file-to-string-as-lines (sb-impl::process-error process))))
+    (close (sb-impl::process-output process))
+    (close (sb-impl::process-error process))
+    (values
+     output
+     error
+     (sb-impl::process-exit-code process))))
+
+(defgeneric file-to-string-as-lines (pathname)
+  (:documentation ""))
+
+(defmethod file-to-string-as-lines ((pathname pathname))
+  (with-open-file (stream pathname :direction :input)
+    (file-to-string-as-lines stream)))
+
+(defmethod file-to-string-as-lines ((stream stream))
+  (with-output-to-string (s)
+    (loop for line = (read-line stream nil :eof nil) 
+	 until (eq line :eof) do
+	 (princ line s)
+	 (terpri s))))
+
+;; copied from ASDF
+(defun pathname-sans-name+type (pathname)
+  "Returns a new pathname with same HOST, DEVICE, DIRECTORY as PATHNAME,
+and NIL NAME and TYPE components"
+  (make-pathname :name nil :type nil :defaults pathname))
+
Index: /branches/new-random/tools/asdf-install/split-sequence.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/split-sequence.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/split-sequence.lisp	(revision 13309)
@@ -0,0 +1,59 @@
+;;;; SPLIT-SEQUENCE
+;;;
+;;; This code was based on Arthur Lemmens' in
+;;; <URL:http://groups.google.com/groups?as_umsgid=39F36F1A.B8F19D20%40simplex.nl>;
+;;;
+
+(in-package #:asdf-install)
+
+(defun split-sequence-if (predicate seq &key (count nil) (remove-empty-subseqs nil) (from-end nil) (start 0) (end nil) (key nil key-supplied))
+  "Return a list of subsequences in seq delimited by items satisfying
+predicate.
+
+If :remove-empty-subseqs is NIL, empty subsequences will be included
+in the result; otherwise they will be discarded.  All other keywords
+work analogously to those for CL:SUBSTITUTE-IF.  In particular, the
+behaviour of :from-end is possibly different from other versions of
+this function; :from-end values of NIL and T are equivalent unless
+:count is supplied. The second return value is an index suitable as an
+argument to CL:SUBSEQ into the sequence indicating where processing
+stopped."
+  (let ((len (length seq))
+        (other-keys (when key-supplied 
+		      (list :key key))))
+    (unless end (setq end len))
+    (if from-end
+        (loop for right = end then left
+              for left = (max (or (apply #'position-if predicate seq 
+					 :end right
+					 :from-end t
+					 other-keys)
+				  -1)
+			      (1- start))
+              unless (and (= right (1+ left))
+                          remove-empty-subseqs) ; empty subseq we don't want
+              if (and count (>= nr-elts count))
+              ;; We can't take any more. Return now.
+              return (values (nreverse subseqs) right)
+              else 
+              collect (subseq seq (1+ left) right) into subseqs
+              and sum 1 into nr-elts
+              until (< left start)
+              finally (return (values (nreverse subseqs) (1+ left))))
+      (loop for left = start then (+ right 1)
+            for right = (min (or (apply #'position-if predicate seq 
+					:start left
+					other-keys)
+				 len)
+			     end)
+            unless (and (= right left) 
+                        remove-empty-subseqs) ; empty subseq we don't want
+            if (and count (>= nr-elts count))
+            ;; We can't take any more. Return now.
+            return (values subseqs left)
+            else
+            collect (subseq seq left right) into subseqs
+            and sum 1 into nr-elts
+            until (>= right end)
+            finally (return (values subseqs right))))))
+
Index: /branches/new-random/tools/asdf-install/variables.lisp
===================================================================
--- /branches/new-random/tools/asdf-install/variables.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf-install/variables.lisp	(revision 13309)
@@ -0,0 +1,117 @@
+(in-package #:asdf-install)
+
+(defun directorify (name)
+  ;; input name may or may not have a trailing #\/, but we know we
+  ;; want a directory
+  (let ((path (pathname name)))
+    (if (pathname-name path)
+	(merge-pathnames
+	 (make-pathname :directory `(:relative ,(pathname-name path))
+			:name "")
+	 path)
+	path)))
+
+#+:digitool
+(defparameter *home-volume-name*
+  (second (pathname-directory (truename (user-homedir-pathname))))
+  "Digitool MCL retains the OS 9 convention that ALL volumes have a
+name which includes the startup volume. OS X doesn't know about this.
+This figures in the home path and in the normalization for system
+namestrings.")
+
+(defvar *proxy* (get-env-var "http_proxy"))
+
+(defvar *proxy-user* nil)
+
+(defvar *proxy-passwd* nil)
+
+(defvar *trusted-uids* nil)
+
+(defvar *verify-gpg-signatures* t
+  "Can be t, nil, or :unknown-locations. If true, then the signature of all packages will be checked. If nil, then no signatures will be checked. If :unkown-locations, then only packages whose location is not a prefix of any `*safe-url-prefixes*` will be tested.")
+
+(defvar *safe-url-prefixes* nil)
+
+(defvar *preferred-location* nil)
+
+(defvar *cclan-mirror*
+  (or (get-env-var "CCLAN_MIRROR")
+      "http://ftp.linux.org.uk/pub/lisp/cclan/"))
+
+#+(or :win32 :mswindows)
+(defvar *cygwin-bin-directory*
+  (pathname "C:\\PROGRA~1\\Cygwin\\bin\\"))
+
+#+(or :win32 :mswindows)
+(defvar *cygwin-bash-program*
+  "C:\\PROGRA~1\\Cygwin\\bin\\bash.exe")
+
+;; bin first
+(defvar *shell-search-paths* '((:absolute "bin")
+                               (:absolute "usr" "bin")
+			       (:absolute "usr" "local" "bin"))
+  "A list of places to look for shell commands.")
+
+(defvar *gnu-tar-program*
+  #-(or :netbsd :freebsd :solaris) "tar"
+  #+(or :netbsd :freebsd :solaris) "gtar"
+  "Path to the GNU tar program")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defparameter *supported-defsystems*
+    (list :mk-defsystem
+          :asdf
+
+          ;; Add others.
+          ;; #+lispworks :common-defsystem
+	  ;; #+gbbopen :mini-module
+          ))          
+  (unless (some (lambda (defsys-tag)
+                  (member defsys-tag *features*))
+                *features*)
+    (error "ASDF-INSTALL requires one of the following \"defsystem\" utilities to work: ~A"
+           *supported-defsystems*)))
+
+(defvar *asdf-install-dirs*
+  (directorify (or #+sbcl (get-env-var "SBCL_HOME")
+                   (get-env-var "ASDF_INSTALL_DIR")
+                   (make-pathname :directory
+                                  `(:absolute
+                                    #+digitool ,*home-volume-name*
+                                    "usr" "local" "asdf-install")))))
+
+(defvar *private-asdf-install-dirs*
+  #+:sbcl
+  (merge-pathnames (make-pathname :directory '(:relative ".sbcl"))
+		   (truename (user-homedir-pathname)))
+  #-:sbcl
+  (cond ((get-env-var "PRIVATE_ASDF_INSTALL_DIR")
+          (directorify (get-env-var "PRIVATE_ASDF_INSTALL_DIR")))
+        (t
+          (merge-pathnames (make-pathname 
+			    :directory '(:relative ".asdf-install-dir"))
+                           (truename (user-homedir-pathname))))))
+
+(defparameter *locations*
+  `((,(merge-pathnames (make-pathname :directory '(:relative "site"))
+                       *asdf-install-dirs*)
+     ,(merge-pathnames (make-pathname :directory '(:relative "site-systems"))
+                       *asdf-install-dirs*)
+     "System-wide install")
+    (,(merge-pathnames (make-pathname :directory '(:relative "site"))
+                       *private-asdf-install-dirs*)
+     ,(merge-pathnames (make-pathname :directory '(:relative "systems"))
+                       *private-asdf-install-dirs*)
+     "Personal installation")))
+
+(defvar *tar-extractors*
+  '(extract-using-tar))
+
+(defvar *systems-installed-this-time* nil
+  "Used during installation propagation \(see *propagate-installation*\) to keep track off which systems have been installed during the current call to install.")
+
+(defvar *propagate-installation* nil
+  "If true, then every required system will be re-asdf-installed.")
+
+(defvar *temporary-directory* 
+  (pathname-sans-name+type (user-homedir-pathname)))
Index: /branches/new-random/tools/asdf.lisp
===================================================================
--- /branches/new-random/tools/asdf.lisp	(revision 13309)
+++ /branches/new-random/tools/asdf.lisp	(revision 13309)
@@ -0,0 +1,1994 @@
+;;; This is asdf: Another System Definition Facility. 
+;;; hash - $Format:%H$
+;;;
+;;; Local Variables:
+;;; mode: lisp
+;;; End:
+;;;
+;;; Feedback, bug reports, and patches are all welcome: please mail to
+;;; <asdf-devel@common-lisp.net>.  But note first that the canonical
+;;; source for asdf is presently on common-lisp.net at
+;;; <URL:http://common-lisp.net/project/asdf/>
+;;;
+;;; If you obtained this copy from anywhere else, and you experience
+;;; trouble using it, or find bugs, you may want to check at the
+;;; location above for a more recent version (and for documentation
+;;; and test files, if your copy came without them) before reporting
+;;; bugs.  There are usually two "supported" revisions - the git HEAD
+;;; is the latest development version, whereas the revision tagged
+;;; RELEASE may be slightly older but is considered `stable'
+
+;;; -- LICENSE START
+;;; (This is the MIT / X Consortium license as taken from 
+;;;  http://www.opensource.org/licenses/mit-license.html on or about
+;;;  Monday; July 13, 2009)
+;;;
+;;; Copyright (c) 2001-2009 Daniel Barlow and contributors
+;;;
+;;; 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.
+;;;
+;;; -- LICENSE END
+
+;;; the problem with writing a defsystem replacement is bootstrapping:
+;;; we can't use defsystem to compile it.  Hence, all in one file
+
+#+xcvb (module ())
+
+(defpackage #:asdf
+  (:documentation "Another System Definition Facility")
+  (:export #:defsystem #:oos #:operate #:find-system #:run-shell-command
+           #:system-definition-pathname #:find-component ; miscellaneous
+	   #:compile-system #:load-system #:test-system
+           #:compile-op #:load-op #:load-source-op
+           #:test-op
+           #:operation		 ; operations
+           #:feature		 ; sort-of operation
+           #:version		 ; metaphorically sort-of an operation
+
+           #:input-files #:output-files #:perform ; operation methods
+           #:operation-done-p #:explain
+
+           #:component #:source-file
+           #:c-source-file #:cl-source-file #:java-source-file
+           #:static-file
+           #:doc-file
+           #:html-file
+           #:text-file
+           #:source-file-type
+           #:module                     ; components
+           #:system
+           #:unix-dso
+
+           #:module-components          ; component accessors
+           #:component-pathname
+           #:component-relative-pathname
+           #:component-name
+           #:component-version
+           #:component-parent
+           #:component-property
+           #:component-system
+
+           #:component-depends-on
+
+           #:system-description
+           #:system-long-description
+           #:system-author
+           #:system-maintainer
+           #:system-license
+           #:system-licence
+           #:system-source-file
+           #:system-relative-pathname
+	   #:map-systems
+
+           #:operation-on-warnings
+           #:operation-on-failure
+
+					;#:*component-parent-pathname*
+           #:*system-definition-search-functions*
+           #:*central-registry*         ; variables
+           #:*compile-file-warnings-behaviour*
+           #:*compile-file-failure-behaviour*
+           #:*asdf-revision*
+	   #:*resolve-symlinks*
+
+           #:operation-error #:compile-failed #:compile-warned #:compile-error
+           #:error-component #:error-operation
+           #:system-definition-error
+           #:missing-component
+	   #:missing-component-of-version
+           #:missing-dependency
+           #:missing-dependency-of-version
+           #:circular-dependency        ; errors
+           #:duplicate-names
+
+	   #:try-recompiling
+           #:retry
+           #:accept                     ; restarts
+	   #:coerce-entry-to-directory
+	   #:remove-entry-from-registry
+
+           #:standard-asdf-method-combination
+           #:around                     ; protocol assistants
+	   
+	   #:*source-to-target-mappings*
+	   #:*default-toplevel-directory*
+	   #:*centralize-lisp-binaries*
+	   #:*include-per-user-information*
+	   #:*map-all-source-files*
+	   #:output-files-for-system-and-operation
+	   #:*enable-asdf-binary-locations*
+	   #:implementation-specific-directory-name)
+  (:use :cl))
+
+
+#+nil
+(error "The author of this file habitually uses #+nil to comment out ~
+        forms. But don't worry, it was unlikely to work in the New ~
+        Implementation of Lisp anyway")
+
+(in-package #:asdf)
+
+(defvar *asdf-revision* 
+  ;; the 1+ hair is to ensure that we don't do an inadvertant find and replace
+  (subseq "REVISION:1.366" (1+ (length "REVISION"))))
+  
+
+(defvar *resolve-symlinks* t
+  "Determine whether or not ASDF resolves symlinks when defining systems.
+
+Defaults to `t`.")
+
+(defvar *compile-file-warnings-behaviour* :warn)
+
+(defvar *compile-file-failure-behaviour* #+sbcl :error #-sbcl :warn)
+
+(defvar *verbose-out* nil)
+
+(defparameter +asdf-methods+
+  '(perform explain output-files operation-done-p))
+
+(define-method-combination standard-asdf-method-combination ()
+  ((around-asdf (around))
+   (around (:around))
+   (before (:before))
+   (primary () :required t)
+   (after (:after)))
+  (flet ((call-methods (methods)
+           (mapcar #'(lambda (method)
+                       `(call-method ,method))
+                   methods)))
+    (let* ((form (if (or before after (rest primary))
+                     `(multiple-value-prog1
+                          (progn ,@(call-methods before)
+                                 (call-method ,(first primary)
+                                              ,(rest primary)))
+                        ,@(call-methods (reverse after)))
+                     `(call-method ,(first primary))))
+           (standard-form (if around
+                              `(call-method ,(first around)
+                                            (,@(rest around)
+                                               (make-method ,form)))
+                              form)))
+      (if around-asdf
+          `(call-method ,(first around-asdf)
+                        (,@(rest around-asdf) (make-method ,standard-form)))
+          standard-form))))
+
+(setf (documentation 'standard-asdf-method-combination 
+		     'method-combination)
+      "This method combination is based on the standard method combination,
+but defines a new method-qualifier, `asdf:around`.  `asdf:around`
+methods will be run *around* any `:around` methods, so that the core
+protocol may employ around methods and those around methods will not
+be overridden by around methods added by a system developer.")
+
+(defgeneric perform (operation component)
+  (:method-combination standard-asdf-method-combination))
+(defgeneric operation-done-p (operation component)
+  (:method-combination standard-asdf-method-combination))
+(defgeneric explain (operation component)
+  (:method-combination standard-asdf-method-combination))
+(defgeneric output-files (operation component)
+  (:method-combination standard-asdf-method-combination))
+(defgeneric input-files (operation component)
+  (:method-combination standard-asdf-method-combination))
+
+(defgeneric system-source-file (system)
+  (:documentation "Return the source file in which system is defined."))
+
+(defgeneric component-system (component)
+  (:documentation "Find the top-level system containing COMPONENT"))
+
+(defgeneric component-pathname (component)
+  (:documentation "Extracts the pathname applicable for a particular component."))
+
+(defgeneric component-relative-pathname (component)
+  (:documentation "Extracts the relative pathname applicable for a particular component."))
+
+(defgeneric component-property (component property))
+
+(defgeneric (setf component-property) (new-value component property))
+
+(defgeneric version-satisfies (component version))
+
+(defgeneric find-component (module name &optional version)
+  (:documentation "Finds the component with name NAME present in the
+MODULE module; if MODULE is nil, then the component is assumed to be a
+system."))
+
+(defgeneric source-file-type (component system))
+
+(defgeneric operation-ancestor (operation)
+  (:documentation
+   "Recursively chase the operation's parent pointer until we get to
+the head of the tree"))
+
+(defgeneric component-visited-p (operation component))
+
+(defgeneric visit-component (operation component data))
+
+(defgeneric (setf visiting-component) (new-value operation component))
+
+(defgeneric component-visiting-p (operation component))
+
+(defgeneric component-depends-on (operation component)
+  (:documentation
+   "Returns a list of dependencies needed by the component to perform
+    the operation.  A dependency has one of the following forms:
+
+      (<operation> <component>*), where <operation> is a class
+        designator and each <component> is a component
+        designator, which means that the component depends on
+        <operation> having been performed on each <component>; or
+
+      (FEATURE <feature>), which means that the component depends
+        on <feature>'s presence in *FEATURES*.
+
+    Methods specialized on subclasses of existing component types
+    should usually append the results of CALL-NEXT-METHOD to the
+    list."))
+
+(defgeneric component-self-dependencies (operation component))
+
+(defgeneric traverse (operation component)
+  (:documentation 
+"Generate and return a plan for performing `operation` on `component`.
+
+The plan returned is a list of dotted-pairs. Each pair is the `cons`
+of ASDF operation object and a `component` object. The pairs will be 
+processed in order by `operate`."))
+
+(defgeneric output-files-using-mappings (source possible-paths path-mappings)
+  (:documentation 
+"Use the variable \\*source-to-target-mappings\\* to find
+an output path for the source. The algorithm transforms each
+entry in possible-paths as follows: If there is a mapping
+whose source starts with the path of possible-path, then
+replace possible-path with a pathname that starts with the
+target of the mapping and continues with the rest of
+possible-path. If no such mapping is found, then use the
+default mapping.
+
+If \\*centralize-lisp-binaries\\* is false, then the default
+mapping is to place the output in a subdirectory of the
+source. The subdirectory is named using the Lisp
+implementation \(see
+implementation-specific-directory-name\). If
+\\*centralize-lisp-binaries\\* is true, then the default
+mapping is to place the output in subdirectories of
+\\*default-toplevel-directory\\* where the subdirectory
+structure will mirror that of the source."))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; utility stuff
+
+(defmacro aif (test then &optional else)
+  `(let ((it ,test)) (if it ,then ,else)))
+
+(defun pathname-sans-name+type (pathname)
+  "Returns a new pathname with same HOST, DEVICE, DIRECTORY as PATHNAME,
+and NIL NAME and TYPE components"
+  (make-pathname :name nil :type nil :defaults pathname))
+
+(define-modify-macro appendf (&rest args)
+  append "Append onto list")
+
+(defun asdf-message (format-string &rest format-args)
+  (declare (dynamic-extent format-args))
+  (apply #'format *verbose-out* format-string format-args))
+
+(defun split-path-string (s &optional force-directory)
+  (check-type s string)
+  (let* ((components (split s nil "/"))
+         (last-comp (car (last components))))
+    (multiple-value-bind (relative components)
+        (if (equal (first components) "")
+          (values :absolute (cdr components))
+          (values :relative components))
+      (cond
+        ((equal last-comp "")
+         (values relative (butlast components) nil))
+        (force-directory
+         (values relative components nil))
+        (t
+         (values relative (butlast components) last-comp))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; classes, condiitons
+
+(define-condition system-definition-error (error) ()
+  ;; [this use of :report should be redundant, but unfortunately it's not.
+  ;; cmucl's lisp::output-instance prefers the kernel:slot-class-print-function
+  ;; over print-object; this is always conditions::%print-condition for
+  ;; condition objects, which in turn does inheritance of :report options at
+  ;; run-time.  fortunately, inheritance means we only need this kludge here in
+  ;; order to fix all conditions that build on it.  -- rgr, 28-Jul-02.]
+  #+cmu (:report print-object))
+
+(define-condition formatted-system-definition-error (system-definition-error)
+  ((format-control :initarg :format-control :reader format-control)
+   (format-arguments :initarg :format-arguments :reader format-arguments))
+  (:report (lambda (c s)
+             (apply #'format s (format-control c) (format-arguments c)))))
+
+(define-condition circular-dependency (system-definition-error)
+  ((components :initarg :components :reader circular-dependency-components)))
+
+(define-condition duplicate-names (system-definition-error)
+  ((name :initarg :name :reader duplicate-names-name)))
+
+(define-condition missing-component (system-definition-error)
+  ((requires :initform "(unnamed)" :reader missing-requires :initarg :requires)
+   (parent :initform nil :reader missing-parent :initarg :parent)))
+
+(define-condition missing-component-of-version (missing-component)
+  ((version :initform nil :reader missing-version :initarg :version)))
+
+(define-condition missing-dependency (missing-component)
+  ((required-by :initarg :required-by :reader missing-required-by)))
+
+(define-condition missing-dependency-of-version (missing-dependency
+						 missing-component-of-version)
+  ())
+
+(define-condition operation-error (error)
+  ((component :reader error-component :initarg :component)
+   (operation :reader error-operation :initarg :operation))
+  (:report (lambda (c s)
+             (format s "~@<erred while invoking ~A on ~A~@:>"
+                     (error-operation c) (error-component c)))))
+(define-condition compile-error (operation-error) ())
+(define-condition compile-failed (compile-error) ())
+(define-condition compile-warned (compile-error) ())
+
+(defclass component ()
+  ((name :accessor component-name :initarg :name :documentation
+         "Component name: designator for a string composed of portable pathname characters")
+   (version :accessor component-version :initarg :version)
+   (in-order-to :initform nil :initarg :in-order-to)
+   ;; XXX crap name
+   (do-first :initform nil :initarg :do-first)
+   ;; methods defined using the "inline" style inside a defsystem form:
+   ;; need to store them somewhere so we can delete them when the system
+   ;; is re-evaluated
+   (inline-methods :accessor component-inline-methods :initform nil)
+   (parent :initarg :parent :initform nil :reader component-parent)
+   ;; no direct accessor for pathname, we do this as a method to allow
+   ;; it to default in funky ways if not supplied
+   (relative-pathname :initarg :pathname)
+   (operation-times :initform (make-hash-table )
+                    :accessor component-operation-times)
+   ;; XXX we should provide some atomic interface for updating the
+   ;; component properties
+   (properties :accessor component-properties :initarg :properties
+               :initform nil)))
+
+;;;; methods: conditions
+
+(defmethod print-object ((c missing-dependency) s)
+  (format s "~@<~A, required by ~A~@:>"
+          (call-next-method c nil) (missing-required-by c)))
+
+(defun sysdef-error (format &rest arguments)
+  (error 'formatted-system-definition-error :format-control 
+	 format :format-arguments arguments))
+
+;;;; methods: components
+
+(defmethod print-object ((c missing-component) s)
+   (format s "~@<component ~S not found~
+             ~@[ in ~A~]~@:>"
+          (missing-requires c)
+          (when (missing-parent c)
+            (component-name (missing-parent c)))))
+
+(defmethod print-object ((c missing-component-of-version) s)
+  (format s "~@<component ~S does not match version ~A~
+              ~@[ in ~A~]~@:>"
+           (missing-requires c)
+           (missing-version c)
+	   (when (missing-parent c)
+	     (component-name (missing-parent c)))))
+
+(defmethod component-system ((component component))
+  (aif (component-parent component)
+       (component-system it)
+       component))
+
+(defmethod print-object ((c component) stream)
+  (print-unreadable-object (c stream :type t :identity t)
+    (ignore-errors
+      (prin1 (component-name c) stream))))
+
+(defclass module (component)
+  ((components :initform nil :accessor module-components :initarg :components)
+   ;; what to do if we can't satisfy a dependency of one of this module's
+   ;; components.  This allows a limited form of conditional processing
+   (if-component-dep-fails :initform :fail
+                           :accessor module-if-component-dep-fails
+                           :initarg :if-component-dep-fails)
+   (default-component-class :accessor module-default-component-class
+     :initform 'cl-source-file :initarg :default-component-class)))
+
+(defun component-parent-pathname (component)
+  (aif (component-parent component)
+       (component-pathname it)
+       *default-pathname-defaults*))
+
+(defmethod component-relative-pathname ((component module))
+  (or (slot-value component 'relative-pathname)
+      (multiple-value-bind (relative path)
+	  (split-path-string (component-name component) t)
+        (make-pathname
+         :directory `(,relative ,@path)
+         :host (pathname-host (component-parent-pathname component))))))
+
+(defmethod component-pathname ((component component))
+  (let ((*default-pathname-defaults* (component-parent-pathname component)))
+    (merge-pathnames (component-relative-pathname component))))
+
+(defmethod component-property ((c component) property)
+  (cdr (assoc property (slot-value c 'properties) :test #'equal)))
+
+(defmethod (setf component-property) (new-value (c component) property)
+  (let ((a (assoc property (slot-value c 'properties) :test #'equal)))
+    (if a
+        (setf (cdr a) new-value)
+        (setf (slot-value c 'properties)
+              (acons property new-value (slot-value c 'properties))))))
+
+(defclass system (module)
+  ((description :accessor system-description :initarg :description)
+   (long-description
+    :accessor system-long-description :initarg :long-description)
+   (author :accessor system-author :initarg :author)
+   (maintainer :accessor system-maintainer :initarg :maintainer)
+   (licence :accessor system-licence :initarg :licence
+            :accessor system-license :initarg :license)
+   (source-file :reader system-source-file :initarg :source-file
+		:writer %set-system-source-file)))
+
+;;; version-satisfies
+
+;;; with apologies to christophe rhodes ...
+(defun split (string &optional max (ws '(#\Space #\Tab)))
+  (flet ((is-ws (char) (find char ws)))
+    (nreverse
+     (let ((list nil) (start 0) (words 0) end)
+       (loop
+         (when (and max (>= words (1- max)))
+           (return (cons (subseq string start) list)))
+         (setf end (position-if #'is-ws string :start start))
+         (push (subseq string start end) list)
+         (incf words)
+         (unless end (return list))
+         (setf start (1+ end)))))))
+
+(defmethod version-satisfies ((c component) version)
+  (unless (and version (slot-boundp c 'version))
+    (return-from version-satisfies t))
+  (let ((x (mapcar #'parse-integer
+                   (split (component-version c) nil '(#\.))))
+        (y (mapcar #'parse-integer
+                   (split version nil '(#\.)))))
+    (labels ((bigger (x y)
+               (cond ((not y) t)
+                     ((not x) nil)
+                     ((> (car x) (car y)) t)
+                     ((= (car x) (car y))
+                      (bigger (cdr x) (cdr y))))))
+      (and (= (car x) (car y))
+           (or (not (cdr y)) (bigger (cdr x) (cdr y)))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; finding systems
+
+(defun make-defined-systems-table ()
+  (make-hash-table :test 'equal))
+
+(defvar *defined-systems* (make-defined-systems-table))
+
+(defun coerce-name (name)
+  (typecase name
+    (component (component-name name))
+    (symbol (string-downcase (symbol-name name)))
+    (string name)
+    (t (sysdef-error "~@<invalid component designator ~A~@:>" name))))
+
+(defun system-registered-p (name)
+  (gethash (coerce-name name) *defined-systems*))
+
+(defun map-systems (fn)
+  "Apply `fn` to each defined system.
+
+`fn` should be a function of one argument. It will be
+called with an object of type asdf:system."
+  (maphash (lambda (_ datum)
+	     (declare (ignore _))
+	     (destructuring-bind (_ . def) datum
+	       (declare (ignore _))
+	       (funcall fn def)))
+	   *defined-systems*))
+
+;;; for the sake of keeping things reasonably neat, we adopt a
+;;; convention that functions in this list are prefixed SYSDEF-
+
+(defvar *system-definition-search-functions*
+  '(sysdef-central-registry-search))
+
+(defun system-definition-pathname (system)
+  (let ((system-name (coerce-name system)))
+    (or
+     (some (lambda (x) (funcall x system-name))
+	   *system-definition-search-functions*)
+     (let ((system-pair (system-registered-p system-name)))
+       (and system-pair
+	    (system-source-file (cdr system-pair)))))))
+
+(defvar *central-registry*
+  `((directory-namestring *default-pathname-defaults*))
+"A list of 'system directory designators' ASDF uses to find systems.
+
+A 'system directory designator' is a pathname or a function 
+which evaluates to a pathname. For example:
+
+    (setf asdf:*central-registry*
+          (list '*default-pathname-defaults*
+                #p\"/home/me/cl/systems/\"
+                #p\"/usr/share/common-lisp/systems/\"))
+")
+
+(defun directory-pathname-p (pathname)
+  "Does `pathname` represent a directory?
+
+A directory-pathname is a pathname _without_ a filename. The three
+ways that the filename components can be missing are for it to be `nil`, 
+`:unspecific` or the empty string.
+
+Note that this does _not_ check to see that `pathname` points to an
+actually-existing directory."
+  (flet ((check-one (x)
+	   (not (null (member x '(nil :unspecific "")
+			      :test 'equal)))))
+    (and (check-one (pathname-name pathname))
+	 (check-one (pathname-type pathname)))))
+
+#+(or)
+;;test
+;;?? move into testsuite sometime soon
+(every (lambda (p)
+	  (directory-pathname-p p))
+	(list 
+	 (make-pathname :name "." :type nil :directory '(:absolute "tmp"))
+	 (make-pathname :name "." :type "" :directory '(:absolute "tmp"))
+	 (make-pathname :name nil :type "" :directory '(:absolute "tmp"))
+	 (make-pathname :name "" :directory '(:absolute "tmp"))
+	 (make-pathname :type :unspecific :directory '(:absolute "tmp"))
+	 (make-pathname :name :unspecific :directory '(:absolute "tmp"))
+	 (make-pathname :name :unspecific :directory '(:absolute "tmp"))
+	 (make-pathname :type "" :directory '(:absolute "tmp"))
+	 ))
+
+(defun ensure-directory-pathname (pathname)
+  (if (directory-pathname-p pathname)
+      pathname
+      (make-pathname :defaults pathname
+		     :directory (append
+				 (pathname-directory pathname)
+				 (list (file-namestring pathname)))
+		     :name nil :type nil :version nil)))
+
+(defun sysdef-central-registry-search (system)
+  (let ((name (coerce-name system))
+	(to-remove nil)
+	(to-replace nil))
+    (block nil
+      (unwind-protect
+	   (dolist (dir *central-registry*)
+	     (let ((defaults (eval dir)))
+	       (when defaults
+		 (cond ((directory-pathname-p defaults)
+			(let ((file (and defaults
+					 (make-pathname
+					  :defaults defaults :version :newest
+					  :name name :type "asd" :case :local)))
+                               #+(and (or win32 windows) (not :clisp))
+                               (shortcut (make-pathname
+                                          :defaults defaults :version :newest
+                                          :name name :type "asd.lnk" :case :local)))
+			  (if (and file (probe-file file))
+			      (return file))
+                          #+(and (or win32 windows) (not :clisp))
+                          (when (probe-file shortcut)
+                            (let ((target (parse-windows-shortcut shortcut)))
+                              (when target
+                                (return (pathname target)))))))
+		       (t
+			(restart-case 
+			    (let* ((*print-circle* nil)
+				   (message 
+				    (format nil 
+					    "~@<While searching for system `~a`: `~a` evaluated ~
+to `~a` which is not a directory.~@:>" 
+					    system dir defaults)))
+			      (error message))
+			  (remove-entry-from-registry ()
+			    :report "Remove entry from *central-registry* and continue"
+			    (push dir to-remove))
+			  (coerce-entry-to-directory ()
+			    :report (lambda (s)
+				      (format s "Coerce entry to ~a, replace ~a and continue."
+					      (ensure-directory-pathname defaults) dir))
+			    (push (cons dir (ensure-directory-pathname defaults)) to-replace))))))))
+	;; cleanup
+	(dolist (dir to-remove)
+	  (setf *central-registry* (remove dir *central-registry*)))
+	(dolist (pair to-replace)
+	  (let* ((current (car pair))
+		 (new (cdr pair))
+		 (position (position current *central-registry*)))
+	    (setf *central-registry*
+		  (append (subseq *central-registry* 0 position)
+			  (list new)
+			  (subseq *central-registry* (1+ position))))))))))
+
+(defun make-temporary-package ()
+  (flet ((try (counter)
+           (ignore-errors
+             (make-package (format nil "~a~D" 'asdf counter)
+                           :use '(:cl :asdf)))))
+    (do* ((counter 0 (+ counter 1))
+          (package (try counter) (try counter)))
+         (package package))))
+
+(defun find-system (name &optional (error-p t))
+  (let* ((name (coerce-name name))
+         (in-memory (system-registered-p name))
+         (on-disk (system-definition-pathname name)))
+    (when (and on-disk
+               (or (not in-memory)
+                   (< (car in-memory) (file-write-date on-disk))))
+      (let ((package (make-temporary-package)))
+        (unwind-protect
+             (let ((*package* package))
+	       (asdf-message
+                "~&~@<; ~@;loading system definition from ~A into ~A~@:>~%"
+                ;; FIXME: This wants to be (ENOUGH-NAMESTRING
+                ;; ON-DISK), but CMUCL barfs on that.
+                on-disk
+                *package*)
+               (load on-disk))
+          (delete-package package))))
+    (let ((in-memory (system-registered-p name)))
+      (if in-memory
+          (progn (if on-disk (setf (car in-memory) (file-write-date on-disk)))
+                 (cdr in-memory))
+          (if error-p (error 'missing-component :requires name))))))
+
+(defun register-system (name system)
+  (asdf-message "~&~@<; ~@;registering ~A as ~A~@:>~%" system name)
+  (setf (gethash (coerce-name name) *defined-systems*)
+        (cons (get-universal-time) system)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; finding components
+
+(defmethod find-component ((module module) name &optional version)
+  (if (slot-boundp module 'components)
+      (let ((m (find name (module-components module)
+                     :test #'equal :key #'component-name)))
+        (if (and m (version-satisfies m version)) m))))
+
+
+;;; a component with no parent is a system
+(defmethod find-component ((module (eql nil)) name &optional version)
+  (let ((m (find-system name nil)))
+    (if (and m (version-satisfies m version)) m)))
+
+;;; component subclasses
+
+(defclass source-file (component) ())
+
+(defclass cl-source-file (source-file) ())
+(defclass c-source-file (source-file) ())
+(defclass java-source-file (source-file) ())
+(defclass static-file (source-file) ())
+(defclass doc-file (static-file) ())
+(defclass html-file (doc-file) ())
+
+(defmethod source-file-type ((c cl-source-file) (s module)) "lisp")
+(defmethod source-file-type ((c c-source-file) (s module)) "c")
+(defmethod source-file-type ((c java-source-file) (s module)) "java")
+(defmethod source-file-type ((c html-file) (s module)) "html")
+(defmethod source-file-type ((c static-file) (s module)) nil)
+
+(defmethod component-relative-pathname ((component source-file))
+  (multiple-value-bind (relative path name)
+      (split-path-string (component-name component))
+    (let ((type (source-file-type component (component-system component)))
+          (relative-pathname (slot-value component 'relative-pathname))
+          (*default-pathname-defaults* (component-parent-pathname component)))
+      (if relative-pathname
+	(merge-pathnames
+         relative-pathname
+         (if type
+           (make-pathname :name name :type type)
+           name))
+        (make-pathname :directory `(,relative ,@path) :name name :type type)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; operations
+
+;;; one of these is instantiated whenever (operate ) is called
+
+(defclass operation ()
+  ((forced :initform nil :initarg :force :accessor operation-forced)
+   (original-initargs :initform nil :initarg :original-initargs
+                      :accessor operation-original-initargs)
+   (visited-nodes :initform nil :accessor operation-visited-nodes)
+   (visiting-nodes :initform nil :accessor operation-visiting-nodes)
+   (parent :initform nil :initarg :parent :accessor operation-parent)))
+
+(defmethod print-object ((o operation) stream)
+  (print-unreadable-object (o stream :type t :identity t)
+    (ignore-errors
+      (prin1 (operation-original-initargs o) stream))))
+
+(defmethod shared-initialize :after ((operation operation) slot-names
+                                     &key force
+                                     &allow-other-keys)
+  (declare (ignore slot-names force))
+  ;; empty method to disable initarg validity checking
+  )
+
+(defun node-for (o c)
+  (cons (class-name (class-of o)) c))
+
+(defmethod operation-ancestor ((operation operation))
+  (aif (operation-parent operation)
+       (operation-ancestor it)
+       operation))
+
+
+(defun make-sub-operation (c o dep-c dep-o)
+  (let* ((args (copy-list (operation-original-initargs o)))
+         (force-p (getf args :force)))
+    ;; note explicit comparison with T: any other non-NIL force value
+    ;; (e.g. :recursive) will pass through
+    (cond ((and (null (component-parent c))
+                (null (component-parent dep-c))
+                (not (eql c dep-c)))
+           (when (eql force-p t)
+             (setf (getf args :force) nil))
+           (apply #'make-instance dep-o
+                  :parent o
+                  :original-initargs args args))
+          ((subtypep (type-of o) dep-o)
+           o)
+          (t
+           (apply #'make-instance dep-o
+                  :parent o :original-initargs args args)))))
+
+
+(defmethod visit-component ((o operation) (c component) data)
+  (unless (component-visited-p o c)
+    (push (cons (node-for o c) data)
+          (operation-visited-nodes (operation-ancestor o)))))
+
+(defmethod component-visited-p ((o operation) (c component))
+  (assoc (node-for o c)
+         (operation-visited-nodes (operation-ancestor o))
+         :test 'equal))
+
+(defmethod (setf visiting-component) (new-value operation component)
+  ;; MCL complains about unused lexical variables
+  (declare (ignorable new-value operation component)))
+
+(defmethod (setf visiting-component) (new-value (o operation) (c component))
+  (let ((node (node-for o c))
+        (a (operation-ancestor o)))
+    (if new-value
+        (pushnew node (operation-visiting-nodes a) :test 'equal)
+        (setf (operation-visiting-nodes a)
+              (remove node  (operation-visiting-nodes a) :test 'equal)))))
+
+(defmethod component-visiting-p ((o operation) (c component))
+  (let ((node (node-for o c)))
+    (member node (operation-visiting-nodes (operation-ancestor o))
+            :test 'equal)))
+
+(defmethod component-depends-on ((op-spec symbol) (c component))
+  (component-depends-on (make-instance op-spec) c))
+
+(defmethod component-depends-on ((o operation) (c component))
+  (cdr (assoc (class-name (class-of o))
+              (slot-value c 'in-order-to))))
+
+(defmethod component-self-dependencies ((o operation) (c component))
+  (let ((all-deps (component-depends-on o c)))
+    (remove-if-not (lambda (x)
+                     (member (component-name c) (cdr x) :test #'string=))
+                   all-deps)))
+
+(defmethod input-files ((operation operation) (c component))
+  (let ((parent (component-parent c))
+        (self-deps (component-self-dependencies operation c)))
+    (if self-deps
+        (mapcan (lambda (dep)
+                  (destructuring-bind (op name) dep
+                    (output-files (make-instance op)
+                                  (find-component parent name))))
+                self-deps)
+        ;; no previous operations needed?  I guess we work with the
+        ;; original source file, then
+        (list (component-pathname c)))))
+
+(defmethod input-files ((operation operation) (c module)) nil)
+
+(defmethod operation-done-p ((o operation) (c component))
+  (flet ((fwd-or-return-t (file)
+           ;; if FILE-WRITE-DATE returns NIL, it's possible that the
+           ;; user or some other agent has deleted an input file.  If
+           ;; that's the case, well, that's not good, but as long as
+           ;; the operation is otherwise considered to be done we
+           ;; could continue and survive.
+           (let ((date (file-write-date file)))
+             (cond
+               (date)
+               (t
+                (warn "~@<Missing FILE-WRITE-DATE for ~S: treating ~
+                       operation ~S on component ~S as done.~@:>"
+                      file o c)
+                (return-from operation-done-p t))))))
+    (let ((out-files (output-files o c))
+          (in-files (input-files o c)))
+      (cond ((and (not in-files) (not out-files))
+             ;; arbitrary decision: an operation that uses nothing to
+             ;; produce nothing probably isn't doing much
+             t)
+            ((not out-files)
+             (let ((op-done
+                    (gethash (type-of o)
+                             (component-operation-times c))))
+               (and op-done
+                    (>= op-done
+                        (apply #'max
+                               (mapcar #'fwd-or-return-t in-files))))))
+            ((not in-files) nil)
+            (t
+             (and
+              (every #'probe-file out-files)
+              (> (apply #'min (mapcar #'file-write-date out-files))
+                 (apply #'max (mapcar #'fwd-or-return-t in-files)))))))))
+
+;;; So you look at this code and think "why isn't it a bunch of
+;;; methods".  And the answer is, because standard method combination
+;;; runs :before methods most->least-specific, which is back to front
+;;; for our purposes.  
+
+(defmethod traverse ((operation operation) (c component))
+  (let ((forced nil))
+    (labels ((%do-one-dep (required-op required-c required-v)
+               (let* ((dep-c (or (find-component
+                                  (component-parent c)
+                                  ;; XXX tacky.  really we should build the
+                                  ;; in-order-to slot with canonicalized
+                                  ;; names instead of coercing this late
+                                  (coerce-name required-c) required-v)
+				 (if required-v
+				     (error 'missing-dependency-of-version
+					    :required-by c
+					    :version required-v
+					    :requires required-c)
+				     (error 'missing-dependency
+					    :required-by c
+					    :requires required-c))))
+                      (op (make-sub-operation c operation dep-c required-op)))
+                 (traverse op dep-c)))
+	     (do-one-dep (required-op required-c required-v)
+               (loop
+		  (restart-case
+		      (return (%do-one-dep required-op required-c required-v))
+		    (retry ()
+		      :report (lambda (s)
+				(format s "~@<Retry loading component ~S.~@:>"
+					required-c))
+		      :test
+		      (lambda (c)
+#|
+			(print (list :c1 c (typep c 'missing-dependency)))
+			(when (typep c 'missing-dependency)
+			  (print (list :c2 (missing-requires c) required-c
+				       (equalp (missing-requires c)
+					       required-c))))
+|#
+			(and (typep c 'missing-dependency)
+			     (equalp (missing-requires c)
+				     required-c)))))))
+             (do-dep (op dep)
+               (cond ((eq op 'feature)
+                      (or (member (car dep) *features*)
+                          (error 'missing-dependency
+                                 :required-by c
+                                 :requires (car dep))))
+                     (t
+                      (dolist (d dep)
+                        (cond ((consp d)
+			       (cond ((string-equal
+				       (symbol-name (first d))
+				       "VERSION")
+				      (appendf
+				       forced
+				       (do-one-dep op (second d) (third d))))
+				     ((and (string-equal
+					    (symbol-name (first d))
+					    "FEATURE")
+					   (find (second d) *features*
+						 :test 'string-equal))
+				      (appendf
+				       forced
+				       (do-one-dep op (second d) (third d))))
+				     (t
+				      (error "Bad dependency ~a.  Dependencies must be (:version <version>), (:feature <feature>), or a name" d))))
+                              (t
+                               (appendf forced (do-one-dep op d nil)))))))))
+      (aif (component-visited-p operation c)
+           (return-from traverse
+             (if (cdr it) (list (cons 'pruned-op c)) nil)))
+      ;; dependencies
+      (if (component-visiting-p operation c)
+          (error 'circular-dependency :components (list c)))
+      (setf (visiting-component operation c) t)
+      (unwind-protect
+	   (progn
+	     (loop for (required-op . deps) in
+		  (component-depends-on operation c)
+		  do (do-dep required-op deps))
+	     ;; constituent bits
+	     (let ((module-ops
+		    (when (typep c 'module)
+		      (let ((at-least-one nil)
+			    (forced nil)
+			    (error nil))
+			(loop for kid in (module-components c)
+			   do (handler-case
+				  (appendf forced (traverse operation kid ))
+				(missing-dependency (condition)
+				  (if (eq (module-if-component-dep-fails c)
+					  :fail)
+				      (error condition))
+				  (setf error condition))
+				(:no-error (c)
+				  (declare (ignore c))
+				  (setf at-least-one t))))
+			(when (and (eq (module-if-component-dep-fails c)
+				       :try-next)
+				   (not at-least-one))
+			  (error error))
+			forced))))
+	       ;; now the thing itself
+	       (when (or forced module-ops
+			 (not (operation-done-p operation c))
+			 (let ((f (operation-forced
+				   (operation-ancestor operation))))
+			   (and f (or (not (consp f))
+				      (member (component-name
+					       (operation-ancestor operation))
+					      (mapcar #'coerce-name f)
+					      :test #'string=)))))
+		 (let ((do-first (cdr (assoc (class-name (class-of operation))
+					     (slot-value c 'do-first)))))
+		   (loop for (required-op . deps) in do-first
+		      do (do-dep required-op deps)))
+		 (setf forced (append (delete 'pruned-op forced :key #'car)
+				      (delete 'pruned-op module-ops :key #'car)
+				      (list (cons operation c)))))))
+	(setf (visiting-component operation c) nil))
+      (visit-component operation c (and forced t))
+      forced)))
+
+
+(defmethod perform ((operation operation) (c source-file))
+  (sysdef-error
+   "~@<required method PERFORM not implemented ~
+    for operation ~A, component ~A~@:>"
+   (class-of operation) (class-of c)))
+
+(defmethod perform ((operation operation) (c module))
+  nil)
+
+(defmethod explain ((operation operation) (component component))
+  (asdf-message "~&;;; ~A on ~A~%" operation component))
+
+;;; compile-op
+
+(defclass compile-op (operation)
+  ((proclamations :initarg :proclamations :accessor compile-op-proclamations :initform nil)
+   (on-warnings :initarg :on-warnings :accessor operation-on-warnings
+                :initform *compile-file-warnings-behaviour*)
+   (on-failure :initarg :on-failure :accessor operation-on-failure
+               :initform *compile-file-failure-behaviour*)))
+
+(defmethod perform :before ((operation compile-op) (c source-file))
+  (map nil #'ensure-directories-exist (output-files operation c)))
+
+(defmethod perform :after ((operation operation) (c component))
+  (setf (gethash (type-of operation) (component-operation-times c))
+        (get-universal-time)))
+
+;;; perform is required to check output-files to find out where to put
+;;; its answers, in case it has been overridden for site policy
+(defmethod perform ((operation compile-op) (c cl-source-file))
+  #-:broken-fasl-loader
+  (let ((source-file (component-pathname c))
+        (output-file (car (output-files operation c))))
+    (multiple-value-bind (output warnings-p failure-p)
+        (compile-file source-file :output-file output-file)
+      (when warnings-p
+        (case (operation-on-warnings operation)
+          (:warn (warn
+                  "~@<COMPILE-FILE warned while performing ~A on ~A.~@:>"
+                  operation c))
+          (:error (error 'compile-warned :component c :operation operation))
+          (:ignore nil)))
+      (when failure-p
+        (case (operation-on-failure operation)
+          (:warn (warn
+                  "~@<COMPILE-FILE failed while performing ~A on ~A.~@:>"
+                  operation c))
+          (:error (error 'compile-failed :component c :operation operation))
+          (:ignore nil)))
+      (unless output
+        (error 'compile-error :component c :operation operation)))))
+
+(defmethod output-files ((operation compile-op) (c cl-source-file))
+  #-:broken-fasl-loader (list (compile-file-pathname (component-pathname c)))
+  #+:broken-fasl-loader (list (component-pathname c)))
+
+(defmethod perform ((operation compile-op) (c static-file))
+  nil)
+
+(defmethod output-files ((operation compile-op) (c static-file))
+  nil)
+
+(defmethod input-files ((op compile-op) (c static-file))
+  nil)
+
+
+;;; load-op
+
+(defclass basic-load-op (operation) ())
+
+(defclass load-op (basic-load-op) ())
+
+(defmethod perform ((o load-op) (c cl-source-file))
+  (mapcar #'load (input-files o c)))
+
+(defmethod perform around ((o load-op) (c cl-source-file))
+  (let ((state :initial))
+    (loop until (or (eq state :success)
+		    (eq state :failure)) do
+	 (case state
+	   (:recompiled
+	    (setf state :failure)
+	    (call-next-method)
+	    (setf state :success))
+	   (:failed-load
+	    (setf state :recompiled)
+	    (perform (make-instance 'asdf:compile-op) c))
+	   (t
+	    (with-simple-restart
+		(try-recompiling "Recompile ~a and try loading it again"
+				  (component-name c))
+	      (setf state :failed-load)
+	      (call-next-method)
+	      (setf state :success)))))))
+
+(defmethod perform around ((o compile-op) (c cl-source-file))
+  (let ((state :initial))
+    (loop until (or (eq state :success)
+		    (eq state :failure)) do
+	 (case state
+	   (:recompiled
+	    (setf state :failure)
+	    (call-next-method)
+	    (setf state :success))
+	   (:failed-compile
+	    (setf state :recompiled)
+	    (perform (make-instance 'asdf:compile-op) c))
+	   (t
+	    (with-simple-restart
+		(try-recompiling "Try recompiling ~a"
+				  (component-name c))
+	      (setf state :failed-compile)
+	      (call-next-method)
+	      (setf state :success)))))))
+
+(defmethod perform ((operation load-op) (c static-file))
+  nil)
+
+(defmethod operation-done-p ((operation load-op) (c static-file))
+  t)
+
+(defmethod output-files ((o operation) (c component))
+  nil)
+
+(defmethod component-depends-on ((operation load-op) (c component))
+  (cons (list 'compile-op (component-name c))
+        (call-next-method)))
+
+;;; load-source-op
+
+(defclass load-source-op (basic-load-op) ())
+
+(defmethod perform ((o load-source-op) (c cl-source-file))
+  (let ((source (component-pathname c)))
+    (setf (component-property c 'last-loaded-as-source)
+          (and (load source)
+               (get-universal-time)))))
+
+(defmethod perform ((operation load-source-op) (c static-file))
+  nil)
+
+(defmethod output-files ((operation load-source-op) (c component))
+  nil)
+
+;;; FIXME: we simply copy load-op's dependencies.  this is Just Not Right.
+(defmethod component-depends-on ((o load-source-op) (c component))
+  (let ((what-would-load-op-do (cdr (assoc 'load-op
+                                           (slot-value c 'in-order-to)))))
+    (mapcar (lambda (dep)
+              (if (eq (car dep) 'load-op)
+                  (cons 'load-source-op (cdr dep))
+                  dep))
+            what-would-load-op-do)))
+
+(defmethod operation-done-p ((o load-source-op) (c source-file))
+  (if (or (not (component-property c 'last-loaded-as-source))
+          (> (file-write-date (component-pathname c))
+             (component-property c 'last-loaded-as-source)))
+      nil t))
+
+(defclass test-op (operation) ())
+
+(defmethod perform ((operation test-op) (c component))
+  nil)
+
+(defmethod operation-done-p ((operation test-op) (c system))
+  "Testing a system is _never_ done."
+  nil)
+
+(defmethod component-depends-on :around ((o test-op) (c system))
+  (cons `(load-op ,(component-name c)) (call-next-method)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; invoking operations
+
+(defun operate (operation-class system &rest args &key (verbose t) version force
+                &allow-other-keys)
+  (declare (ignore force))
+  (let* ((*package* *package*)
+         (*readtable* *readtable*)
+         (op (apply #'make-instance operation-class
+                    :original-initargs args
+                    args))
+         (*verbose-out* (if verbose *standard-output* (make-broadcast-stream)))
+         (system (if (typep system 'component) system (find-system system))))
+    (unless (version-satisfies system version)
+      (error 'missing-component-of-version :requires system :version version))
+    (let ((steps (traverse op system)))
+      (with-compilation-unit ()
+        (loop for (op . component) in steps do
+                 (loop
+                   (restart-case
+                       (progn (perform op component)
+                              (return))
+                     (retry ()
+                       :report
+                       (lambda (s)
+                         (format s "~@<Retry performing ~S on ~S.~@:>"
+                                 op component)))
+                     (accept ()
+                       :report
+                       (lambda (s)
+                         (format s "~@<Continue, treating ~S on ~S as ~
+                                   having been successful.~@:>"
+                                 op component))
+                       (setf (gethash (type-of op)
+                                      (component-operation-times component))
+                             (get-universal-time))
+                       (return)))))))
+    op))
+
+(defun oos (operation-class system &rest args &key force (verbose t) version
+	    &allow-other-keys)
+  (declare (ignore force verbose version))
+  (apply #'operate operation-class system args))
+
+(let ((operate-docstring
+  "Operate does three things:
+
+1. It creates an instance of `operation-class` using any keyword parameters
+as initargs.
+2. It finds the  asdf-system specified by `system` (possibly loading
+it from disk).
+3. It then calls `traverse` with the operation and system as arguments
+
+The traverse operation is wrapped in `with-compilation-unit` and error
+handling code. If a `version` argument is supplied, then operate also
+ensures that the system found satisfies it using the `version-satisfies`
+method.
+
+Note that dependencies may cause the operation to invoke other
+operations on the system or its components: the new operations will be
+created with the same initargs as the original one.
+"))
+  (setf (documentation 'oos 'function)
+	(format nil
+		"Short for _operate on system_ and an alias for the [operate][] function. ~&~&~a"
+		operate-docstring))
+  (setf (documentation 'operate 'function)
+	operate-docstring))
+
+(defun load-system (system &rest args &key force (verbose t) version)
+  "Shorthand for `(operate 'asdf:load-op system)`. See [operate][] for details."
+  (declare (ignore force verbose version))
+  (apply #'operate 'load-op system args))
+
+(defun compile-system (system &rest args &key force (verbose t) version)
+  "Shorthand for `(operate 'asdf:compile-op system)`. See [operate][] for details."
+  (declare (ignore force verbose version))
+  (apply #'operate 'compile-op system args))
+
+(defun test-system (system &rest args &key force (verbose t) version)
+  "Shorthand for `(operate 'asdf:test-op system)`. See [operate][] for details."
+  (declare (ignore force verbose version))
+  (apply #'operate 'test-op system args))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; syntax
+
+(defun remove-keyword (key arglist)
+  (labels ((aux (key arglist)
+             (cond ((null arglist) nil)
+                   ((eq key (car arglist)) (cddr arglist))
+                   (t (cons (car arglist) (cons (cadr arglist)
+                                                (remove-keyword
+                                                 key (cddr arglist))))))))
+    (aux key arglist)))
+
+(defun resolve-symlinks (path)
+  #-allegro (truename path)
+  #+allegro (excl:pathname-resolve-symbolic-links path)
+  )
+
+(defun determine-system-pathname (pathname pathname-supplied-p)
+  ;; called from the defsystem macro.
+  ;; the pathname of a system is either
+  ;; 1. the one supplied, 
+  ;; 2. derived from the *load-truename* (see below), or
+  ;; 3. taken from *default-pathname-defaults*
+  ;;
+  ;; if using *load-truename*, then we also deal with whether or not
+  ;; to resolve symbolic links. If not resolving symlinks, then we use
+  ;; *load-pathname* instead of *load-truename* since in some
+  ;; implementations, the latter has *already resolved it.
+  (or (and pathname-supplied-p pathname)
+      (when *load-truename*
+	(pathname-sans-name+type 
+	 (if *resolve-symlinks*
+	     (resolve-symlinks *load-truename*)
+	     *load-pathname*)))
+      *default-pathname-defaults*))
+
+(defmacro defsystem (name &body options)
+  (destructuring-bind (&key (pathname nil pathname-arg-p) (class 'system)
+                            &allow-other-keys)
+      options
+    (let ((component-options (remove-keyword :class options)))
+      `(progn
+         ;; system must be registered before we parse the body, otherwise
+         ;; we recur when trying to find an existing system of the same name
+         ;; to reuse options (e.g. pathname) from
+         (let ((s (system-registered-p ',name)))
+           (cond ((and s (eq (type-of (cdr s)) ',class))
+                  (setf (car s) (get-universal-time)))
+                 (s
+                  (change-class (cdr s) ',class))
+                 (t
+                  (register-system (quote ,name)
+                                   (make-instance ',class :name ',name))))
+           (%set-system-source-file *load-truename* 
+				    (cdr (system-registered-p ',name))))
+         (parse-component-form 
+	  nil (apply
+	       #'list
+	       :module (coerce-name ',name)
+	       :pathname
+	       ,(determine-system-pathname pathname pathname-arg-p)
+	       ',component-options))))))
+
+
+(defun class-for-type (parent type)
+  (let* ((extra-symbols (list (find-symbol (symbol-name type) *package*)
+                              (find-symbol (symbol-name type)
+                                           (load-time-value
+                                            (package-name :asdf)))))
+         (class (dolist (symbol (if (keywordp type)
+                                    extra-symbols
+                                    (cons type extra-symbols)))
+                  (when (and symbol
+                             (find-class symbol nil)
+                             (subtypep symbol 'component))
+                    (return (find-class symbol))))))
+    (or class
+        (and (eq type :file)
+             (or (module-default-component-class parent)
+                 (find-class 'cl-source-file)))
+        (sysdef-error "~@<don't recognize component type ~A~@:>" type))))
+
+(defun maybe-add-tree (tree op1 op2 c)
+  "Add the node C at /OP1/OP2 in TREE, unless it's there already.
+Returns the new tree (which probably shares structure with the old one)"
+  (let ((first-op-tree (assoc op1 tree)))
+    (if first-op-tree
+        (progn
+          (aif (assoc op2 (cdr first-op-tree))
+               (if (find c (cdr it))
+                   nil
+                   (setf (cdr it) (cons c (cdr it))))
+               (setf (cdr first-op-tree)
+                     (acons op2 (list c) (cdr first-op-tree))))
+          tree)
+        (acons op1 (list (list op2 c)) tree))))
+
+(defun union-of-dependencies (&rest deps)
+  (let ((new-tree nil))
+    (dolist (dep deps)
+      (dolist (op-tree dep)
+        (dolist (op  (cdr op-tree))
+          (dolist (c (cdr op))
+            (setf new-tree
+                  (maybe-add-tree new-tree (car op-tree) (car op) c))))))
+    new-tree))
+
+
+(defun remove-keys (key-names args)
+  (loop for ( name val ) on args by #'cddr
+        unless (member (symbol-name name) key-names
+                       :key #'symbol-name :test 'equal)
+        append (list name val)))
+
+(defvar *serial-depends-on*)
+
+(defun sysdef-error-component (msg type name value)
+  (sysdef-error (concatenate 'string msg
+                             "~&The value specified for ~(~A~) ~A is ~W")
+                type name value))
+
+(defun check-component-input (type name weakly-depends-on 
+			      depends-on components in-order-to)
+  "A partial test of the values of a component."
+  (unless (listp depends-on)
+    (sysdef-error-component ":depends-on must be a list."
+                            type name depends-on))
+  (unless (listp weakly-depends-on)
+    (sysdef-error-component ":weakly-depends-on must be a list."
+                            type name weakly-depends-on))
+  (unless (listp components)
+    (sysdef-error-component ":components must be NIL or a list of components."
+                            type name components))
+  (unless (and (listp in-order-to) (listp (car in-order-to)))
+    (sysdef-error-component ":in-order-to must be NIL or a list of components."
+                            type name in-order-to)))
+
+(defun %remove-component-inline-methods (component)
+  (loop for name in +asdf-methods+
+        do (map 'nil
+                ;; this is inefficient as most of the stored
+                ;; methods will not be for this particular gf n
+                ;; But this is hardly performance-critical
+                (lambda (m)
+                  (remove-method (symbol-function name) m))
+                (component-inline-methods component)))
+  ;; clear methods, then add the new ones
+  (setf (component-inline-methods component) nil))
+
+(defun %define-component-inline-methods (ret rest)
+  (loop for name in +asdf-methods+ do
+       (let ((keyword (intern (symbol-name name) :keyword)))
+	 (loop for data = rest then (cddr data)
+	      for key = (first data)
+	      for value = (second data)
+              while data
+	      when (eq key keyword) do
+	      (destructuring-bind (op qual (o c) &body body) value
+	      (pushnew
+		 (eval `(defmethod ,name ,qual ((,o ,op) (,c (eql ,ret)))
+				   ,@body))
+		 (component-inline-methods ret)))))))
+
+(defun %refresh-component-inline-methods (component rest)
+  (%remove-component-inline-methods component)
+  (%define-component-inline-methods component rest))
+  
+(defun parse-component-form (parent options)
+
+  (destructuring-bind
+        (type name &rest rest &key
+              ;; the following list of keywords is reproduced below in the
+              ;; remove-keys form.  important to keep them in sync
+              components pathname default-component-class
+              perform explain output-files operation-done-p
+              weakly-depends-on
+              depends-on serial in-order-to
+              ;; list ends
+              &allow-other-keys) options
+    (declare (ignorable perform explain output-files operation-done-p))
+    (check-component-input type name weakly-depends-on depends-on components in-order-to)
+
+    (when (and parent
+               (find-component parent name)
+               ;; ignore the same object when rereading the defsystem
+               (not
+                (typep (find-component parent name)
+                       (class-for-type parent type))))
+      (error 'duplicate-names :name name))
+
+    (let* ((other-args (remove-keys
+                        '(components pathname default-component-class
+                          perform explain output-files operation-done-p
+                          weakly-depends-on
+                          depends-on serial in-order-to)
+                        rest))
+           (ret
+            (or (find-component parent name)
+                (make-instance (class-for-type parent type)))))
+      (when weakly-depends-on
+        (setf depends-on (append depends-on (remove-if (complement #'find-system) weakly-depends-on))))
+      (when (boundp '*serial-depends-on*)
+        (setf depends-on
+              (concatenate 'list *serial-depends-on* depends-on)))
+      (apply #'reinitialize-instance ret
+             :name (coerce-name name)
+             :pathname pathname
+             :parent parent
+             other-args)
+      (when (typep ret 'module)
+        (setf (module-default-component-class ret)
+              (or default-component-class
+                  (and (typep parent 'module)
+                       (module-default-component-class parent))))
+        (let ((*serial-depends-on* nil))
+          (setf (module-components ret)
+                (loop for c-form in components
+                      for c = (parse-component-form ret c-form)
+                      collect c
+                      if serial
+                      do (push (component-name c) *serial-depends-on*))))
+
+        ;; check for duplicate names
+        (let ((name-hash (make-hash-table :test #'equal)))
+          (loop for c in (module-components ret)
+                do
+                (if (gethash (component-name c)
+                             name-hash)
+                    (error 'duplicate-names
+                           :name (component-name c))
+                    (setf (gethash (component-name c)
+                                   name-hash)
+                          t)))))
+
+      (setf (slot-value ret 'in-order-to)
+            (union-of-dependencies
+             in-order-to
+             `((compile-op (compile-op ,@depends-on))
+               (load-op (load-op ,@depends-on))))
+            (slot-value ret 'do-first) `((compile-op (load-op ,@depends-on))))
+
+      (%refresh-component-inline-methods ret rest)
+
+      ret)))
+
+;;; optional extras
+
+;;; run-shell-command functions for other lisp implementations will be
+;;; gratefully accepted, if they do the same thing.  If the docstring
+;;; is ambiguous, send a bug report
+
+(defun run-shell-command (control-string &rest args)
+  "Interpolate `args` into `control-string` as if by `format`, and
+synchronously execute the result using a Bourne-compatible shell, with
+output to `*verbose-out*`.  Returns the shell's exit code."
+  (let ((command (apply #'format nil control-string args)))
+    (asdf-message "; $ ~A~%" command)
+    #+sbcl
+    (sb-ext:process-exit-code
+     (apply #'sb-ext:run-program
+	    #+win32 "sh" #-win32 "/bin/sh"
+	    (list  "-c" command)
+	    :input nil :output *verbose-out*
+	    #+win32 '(:search t) #-win32 nil))
+
+    #+(or cmu scl)
+    (ext:process-exit-code
+     (ext:run-program
+      "/bin/sh"
+      (list  "-c" command)
+      :input nil :output *verbose-out*))
+
+    #+allegro
+    ;; will this fail if command has embedded quotes - it seems to work
+    (multiple-value-bind (stdout stderr exit-code)
+        (excl.osi:command-output 
+	 (format nil "~a -c \"~a\"" 
+		 #+mswindows "sh" #-mswindows "/bin/sh" command)
+	 :input nil :whole nil
+	 #+mswindows :show-window #+mswindows :hide)
+      (format *verbose-out* "~{~&; ~a~%~}~%" stderr)
+      (format *verbose-out* "~{~&; ~a~%~}~%" stdout)
+      exit-code)
+
+    #+lispworks
+    (system:call-system-showing-output
+     command
+     :shell-type "/bin/sh"
+     :output-stream *verbose-out*)
+
+    #+clisp                     ;XXX not exactly *verbose-out*, I know
+    (ext:run-shell-command  command :output :terminal :wait t)
+
+    #+openmcl
+    (nth-value 1
+               (ccl:external-process-status
+                (ccl:run-program "/bin/sh" (list "-c" command)
+                                 :input nil :output *verbose-out*
+                                 :wait t)))
+
+    #+ecl ;; courtesy of Juan Jose Garcia Ripoll
+    (si:system command)
+
+    #-(or openmcl clisp lispworks allegro scl cmu sbcl ecl)
+    (error "RUN-SHELL-PROGRAM not implemented for this Lisp")
+    ))
+
+(defmethod system-source-file ((system-name t))
+  (system-source-file (find-system system-name)))
+
+(defun system-source-directory (system-name)
+  (make-pathname :name nil
+                 :type nil
+                 :defaults (system-source-file system-name)))
+
+(defun system-relative-pathname (system pathname &key name type)
+  ;; you're not allowed to muck with the return value of pathname-X
+  (let ((directory (copy-list (pathname-directory pathname))))
+    (when (eq (car directory) :absolute)
+      (setf (car directory) :relative))
+    (merge-pathnames
+     (make-pathname :name (or name (pathname-name pathname))
+                    :type (or type (pathname-type pathname))
+                    :directory directory)
+     (system-source-directory system))))
+
+;;; ---------------------------------------------------------------------------
+;;; asdf-binary-locations
+;;;
+;;; this bit of code was stolen from Bjorn Lindberg and then it grew!
+;;; see http://www.cliki.net/asdf%20binary%20locations
+;;; and http://groups.google.com/group/comp.lang.lisp/msg/bd5ea9d2008ab9fd
+;;; ---------------------------------------------------------------------------
+;;; Portions of this code were once from SWANK / SLIME
+
+(defparameter *centralize-lisp-binaries*
+  nil "
+If true, compiled lisp files without an explicit mapping (see
+\\*source-to-target-mappings\\*) will be placed in subdirectories of
+\\*default-toplevel-directory\\*. If false, then compiled lisp files
+without an explicitly mapping will be placed in subdirectories of
+their sources.")
+
+(defparameter *enable-asdf-binary-locations* nil
+  "
+If true, then compiled lisp files will be placed into a directory 
+computed from the Lisp version, Operating System and computer archetecture.
+See [implementation-specific-directory-name][] for details.")
+
+
+(defparameter *default-toplevel-directory*
+  (merge-pathnames
+   (make-pathname :directory '(:relative ".fasls"))
+   (truename (user-homedir-pathname)))
+  "If \\*centralize-lisp-binaries\\* is true, then compiled lisp files without an explicit mapping \(see \\*source-to-target-mappings\\*\) will be placed in subdirectories of \\*default-toplevel-directory\\*.")
+
+(defparameter *include-per-user-information*
+  nil
+  "When \\*centralize-lisp-binaries\\* is true this variable controls whether or not to customize the output directory based on the current user. It can be nil, t or a string. If it is nil \(the default\), then no additional information will be added to the output directory. If it is t, then the user's name \(as taken from the return value of #'user-homedir-pathname\) will be included into the centralized path (just before the lisp-implementation directory). Finally, if \\*include-per-user-information\\* is a string, then this string will be included in the output-directory.")
+
+(defparameter *map-all-source-files*
+  nil
+  "If true, then all subclasses of source-file will have their output locations mapped by ASDF-Binary-Locations. If nil (the default), then only subclasses of cl-source-file will be mapped.")
+
+(defvar *source-to-target-mappings* 
+  #-sbcl
+  nil
+  #+sbcl
+  (list (list (princ-to-string (sb-ext:posix-getenv "SBCL_HOME")) nil))
+  "The \\*source-to-target-mappings\\* variable specifies mappings from source to target. If the target is nil, then it means to not map the source to anything. I.e., to leave it as is. This has the effect of turning off ASDF-Binary-Locations for the given source directory. Examples:
+
+    ;; compile everything in .../src and below into .../cmucl
+    '((\"/nfs/home/compbio/d95-bli/share/common-lisp/src/\" 
+       \"/nfs/home/compbio/d95-bli/lib/common-lisp/cmucl/\"))
+
+    ;; leave SBCL innards alone (SBCL specific)
+    (list (list (princ-to-string (sb-ext:posix-getenv \"SBCL_HOME\")) nil))
+")
+
+(defparameter *implementation-features*
+  '(:allegro :lispworks :sbcl :ccl :openmcl :cmu :clisp
+    :corman :cormanlisp :armedbear :gcl :ecl :scl))
+
+(defparameter *os-features*
+  '(:windows :mswindows :win32 :mingw32
+    :solaris :sunos
+    :macosx :darwin :apple
+    :freebsd :netbsd :openbsd :bsd
+    :linux :unix))
+
+(defparameter *architecture-features*
+  '(:amd64 (:x86-64 :x86_64 :x8664-target) :i686 :i586 :pentium3 
+    :i486 (:i386 :pc386 :iapx386) (:x86 :x8632-target) :pentium4
+    :hppa64 :hppa :ppc64 :ppc32 :powerpc :ppc :sparc64 :sparc))
+
+;; note to gwking: this is in slime, system-check, and system-check-server too
+(defun lisp-version-string ()
+  #+cmu       (substitute #\- #\/ 
+			  (substitute #\_ #\Space 
+				      (lisp-implementation-version)))
+  #+scl       (lisp-implementation-version)
+  #+sbcl      (lisp-implementation-version)
+  #+ecl       (reduce (lambda (x str) (substitute #\_ str x))
+		      '(#\Space #\: #\( #\)) 
+		      :initial-value (lisp-implementation-version))
+  #+gcl       (let ((s (lisp-implementation-version))) (subseq s 4))
+  #+openmcl   (format nil "~d.~d~@[-~d~]"
+                      ccl::*openmcl-major-version* 
+                      ccl::*openmcl-minor-version*
+                      #+ppc64-target 64 
+                      #-ppc64-target nil)
+  #+lispworks (format nil "~A~@[~A~]"
+                      (lisp-implementation-version)
+                      (when (member :lispworks-64bit *features*) "-64bit"))
+  #+allegro   (format nil
+                      "~A~A~A~A"
+                      excl::*common-lisp-version-number*
+					; ANSI vs MoDeRn
+		      ;; thanks to Robert Goldman and Charley Cox for
+		      ;; an improvement to my hack
+		      (if (eq excl:*current-case-mode* 
+			      :case-sensitive-lower) "M" "A")
+		      ;; Note if not using International ACL
+		      ;; see http://www.franz.com/support/documentation/8.1/doc/operators/excl/ics-target-case.htm
+		      (excl:ics-target-case
+			(:-ics "8")
+			(:+ics ""))
+                      (if (member :64bit *features*) "-64bit" ""))
+  #+clisp     (let ((s (lisp-implementation-version)))
+                (subseq s 0 (position #\space s)))
+  #+armedbear (lisp-implementation-version)
+  #+cormanlisp (lisp-implementation-version)
+  #+digitool   (subseq (lisp-implementation-version) 8))
+
+
+(defparameter *implementation-specific-directory-name* nil)
+
+(defun implementation-specific-directory-name ()
+  "Return a name that can be used as a directory name that is
+unique to a Lisp implementation, Lisp implementation version,
+operating system, and hardware architecture."
+  (and *enable-asdf-binary-locations*
+       (list 
+	(or *implementation-specific-directory-name*
+	    (setf *implementation-specific-directory-name*
+		  (labels 
+		      ((fp (thing)
+			 (etypecase thing
+			   (symbol
+			    (let ((feature (find thing *features*)))
+			      (when feature (return-from fp feature))))
+			   ;; allows features to be lists of which the first
+			   ;; member is the "main name", the rest being aliases
+			   (cons
+			    (dolist (subf thing)
+			      (let ((feature (find subf *features*)))
+				(when feature (return-from fp (first thing))))))))
+		       (first-of (features)
+			 (loop for f in features
+			    when (fp f) return it))
+		       (maybe-warn (value fstring &rest args)
+			 (cond (value)
+			       (t (apply #'warn fstring args)
+				  "unknown"))))
+		    (let ((lisp (maybe-warn (first-of *implementation-features*)
+					    "No implementation feature found in ~a." 
+					    *implementation-features*))
+			  (os   (maybe-warn (first-of *os-features*)
+					    "No os feature found in ~a." *os-features*))
+			  (arch (maybe-warn (first-of *architecture-features*)
+					    "No architecture feature found in ~a."
+					    *architecture-features*))
+			  (version (maybe-warn (lisp-version-string)
+					       "Don't know how to get Lisp ~
+                                          implementation version.")))
+		      (format nil "~(~@{~a~^-~}~)" lisp version os arch))))))))
+
+(defun pathname-prefix-p (prefix pathname)
+  (let ((prefix-ns (namestring prefix))
+        (pathname-ns (namestring pathname)))
+    (= (length prefix-ns)
+       (mismatch prefix-ns pathname-ns))))
+
+(defgeneric output-files-for-system-and-operation
+  (system operation component source possible-paths)
+  (:documentation "Returns the directory where the componets output files should be placed. This may depends on the system, the operation and the component. The ASDF default input and outputs are provided in the source and possible-paths parameters."))
+
+(defun source-to-target-resolved-mappings ()
+  "Answer `*source-to-target-mappings*` with additional entries made
+by resolving sources that are symlinks.
+
+As ASDF sometimes resolves symlinks to compute source paths, we must
+follow that.  For example, if SBCL is installed under a symlink, and
+SBCL_HOME is set through that symlink, the default rule above
+preventing SBCL contribs from being mapped elsewhere will not be
+applied by the plain `*source-to-target-mappings*`."
+  (loop for mapping in asdf:*source-to-target-mappings*
+	for (source target) = mapping
+	for true-source = (and source (resolve-symlinks source))
+	if (equal source true-source)
+	  collect mapping
+	else append (list mapping (list true-source target))))
+
+(defmethod output-files-for-system-and-operation
+           ((system system) operation component source possible-paths)
+  (declare (ignore operation component))
+  (output-files-using-mappings
+   source possible-paths (source-to-target-resolved-mappings)))
+
+(defmethod output-files-using-mappings (source possible-paths path-mappings)
+  (mapcar 
+   (lambda (path) 
+     (loop for (from to) in path-mappings 
+	when (pathname-prefix-p from source) 
+	do (return 
+	     (if to
+		 (merge-pathnames 
+		  (make-pathname :type (pathname-type path)) 
+		  (merge-pathnames (enough-namestring source from) 
+				   to))
+		 path))
+		  
+	finally
+	  (return 
+	    ;; Instead of just returning the path when we 
+	    ;; don't find a mapping, we stick stuff into 
+	    ;; the appropriate binary directory based on 
+	    ;; the implementation
+	    (if *centralize-lisp-binaries*
+		(merge-pathnames
+		 (make-pathname
+		  :type (pathname-type path)
+		  :directory `(:relative
+			       ,@(cond ((eq *include-per-user-information* t)
+					(cdr (pathname-directory
+					      (user-homedir-pathname))))
+				       ((not (null *include-per-user-information*))
+					(list *include-per-user-information*)))
+			       ,@(implementation-specific-directory-name)
+			       ,@(rest (pathname-directory path)))
+		  :defaults path)
+		 *default-toplevel-directory*)
+		(make-pathname 
+		 :type (pathname-type path)
+		 :directory (append
+			     (pathname-directory path)
+			     (implementation-specific-directory-name))
+		 :defaults path))))) 
+	  possible-paths))
+
+(defmethod output-files 
+    :around ((operation compile-op) (component source-file)) 
+  (if (or *map-all-source-files*
+	    (typecase component 
+	      (cl-source-file t)
+	      (t nil)))
+    (let ((source (component-pathname component )) 
+	  (paths (call-next-method))) 
+      (output-files-for-system-and-operation 
+       (component-system component) operation component source paths))
+    (call-next-method)))
+
+;;;; -----------------------------------------------------------------
+;;;; Windows shortcut support.  Based on:
+;;;;
+;;;; Jesse Hager: The Windows Shortcut File Format.
+;;;; http://www.wotsit.org/list.asp?fc=13
+;;;; -----------------------------------------------------------------
+
+(defparameter *link-initial-dword* 76)
+(defparameter *link-guid* #(1 20 2 0 0 0 0 0 192 0 0 0 0 0 0 70))
+
+(defun read-null-terminated-string (s)
+  (with-output-to-string (out)
+    (loop
+	for code = (read-byte s)
+	until (zerop code)
+	do (write-char (code-char code) out))))
+
+(defun read-little-endian (s &optional (bytes 4))
+  (let ((result 0))
+    (loop
+	for i from 0 below bytes
+	do
+	  (setf result (logior result (ash (read-byte s) (* 8 i)))))
+    result))
+
+(defun parse-windows-shortcut (pathname)
+  (with-open-file (s pathname :element-type '(unsigned-byte 8))
+    (handler-case
+	(when (and (= (read-little-endian s) *link-initial-dword*)
+		   (let ((header (make-array (length *link-guid*))))
+		     (read-sequence header s)
+		     (equalp header *link-guid*)))
+	  (let ((flags (read-little-endian s)))
+	    (file-position s 76)	;skip rest of header
+	    (when (logbitp 0 flags)
+	      ;; skip shell item id list
+	      (let ((length (read-little-endian s 2)))
+		(file-position s (+ length (file-position s)))))
+	    (cond
+	      ((logbitp 1 flags)
+		(parse-file-location-info s))
+	      (t
+		(when (logbitp 2 flags)
+		  ;; skip description string
+		  (let ((length (read-little-endian s 2)))
+		    (file-position s (+ length (file-position s)))))
+		(when (logbitp 3 flags)
+		  ;; finally, our pathname
+		  (let* ((length (read-little-endian s 2))
+			 (buffer (make-array length)))
+		    (read-sequence buffer s)
+		    (map 'string #'code-char buffer)))))))
+      (end-of-file ()
+	nil))))
+
+(defun parse-file-location-info (s)
+  (let ((start (file-position s))
+	(total-length (read-little-endian s))
+	(end-of-header (read-little-endian s))
+	(fli-flags (read-little-endian s))
+	(local-volume-offset (read-little-endian s))
+	(local-offset (read-little-endian s))
+	(network-volume-offset (read-little-endian s))
+	(remaining-offset (read-little-endian s)))
+    (declare (ignore total-length end-of-header local-volume-offset))
+    (unless (zerop fli-flags)
+      (cond
+	((logbitp 0 fli-flags)
+	  (file-position s (+ start local-offset)))
+	((logbitp 1 fli-flags)
+	  (file-position s (+ start
+			      network-volume-offset
+			      #x14))))
+      (concatenate 'string
+	(read-null-terminated-string s)
+	(progn
+	  (file-position s (+ start remaining-offset))
+	  (read-null-terminated-string s))))))
+
+
+(pushnew :asdf *features*)
+
+#+sbcl
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (when (sb-ext:posix-getenv "SBCL_BUILDING_CONTRIB")
+    (pushnew :sbcl-hooks-require *features*)))
+
+#+(and sbcl sbcl-hooks-require)
+(progn
+  (defun module-provide-asdf (name)
+    (handler-bind ((style-warning #'muffle-warning))
+      (let* ((*verbose-out* (make-broadcast-stream))
+             (system (asdf:find-system name nil)))
+        (when system
+          (asdf:operate 'asdf:load-op name)
+          t))))
+
+  (defun contrib-sysdef-search (system)
+    (let ((home (sb-ext:posix-getenv "SBCL_HOME")))
+      (when (and home (not (string= home "")))
+        (let* ((name (coerce-name system))
+               (home (truename home))
+               (contrib (merge-pathnames
+                         (make-pathname :directory `(:relative ,name)
+                                        :name name
+                                        :type "asd"
+                                        :case :local
+                                        :version :newest)
+                         home)))
+          (probe-file contrib)))))
+
+  (pushnew
+   '(let ((home (sb-ext:posix-getenv "SBCL_HOME")))
+      (when (and home (not (string= home "")))
+        (merge-pathnames "site-systems/" (truename home))))
+   *central-registry*)
+
+  (pushnew
+   '(merge-pathnames ".sbcl/systems/"
+     (user-homedir-pathname))
+   *central-registry*)
+
+  (pushnew 'module-provide-asdf sb-ext:*module-provider-functions*)
+  (pushnew 'contrib-sysdef-search *system-definition-search-functions*))
+
+(if *asdf-revision*
+    (asdf-message ";; ASDF, revision ~a" *asdf-revision*)
+    (asdf-message ";; ASDF, revision unknown; possibly a development version"))
+
+(provide 'asdf)
+
+
+#+(or)
+;;?? ignore -- so how will ABL get "installed"
+;; should be unnecessary with newer versions of ASDF
+;; load customizations
+(eval-when (:load-toplevel :execute)
+  (let* ((*package* (find-package :common-lisp)))
+    (load
+     (merge-pathnames
+      (make-pathname :name "asdf-binary-locations"
+		     :type "lisp"
+		     :directory '(:relative ".asdf"))
+      (truename (user-homedir-pathname)))
+     :if-does-not-exist nil)))
Index: /branches/new-random/tools/defsystem.lisp
===================================================================
--- /branches/new-random/tools/defsystem.lisp	(revision 13309)
+++ /branches/new-random/tools/defsystem.lisp	(revision 13309)
@@ -0,0 +1,4885 @@
+;;; -*- Mode: Lisp; Package: make -*-
+;;; -*- Mode: CLtL; Syntax: Common-Lisp -*-
+
+;;; DEFSYSTEM 3.4 Interim.
+
+;;; defsystem.lisp --
+
+;;; ****************************************************************
+;;; MAKE -- A Portable Defsystem Implementation ********************
+;;; ****************************************************************
+
+;;; This is a portable system definition facility for Common Lisp.
+;;; Though home-grown, the syntax was inspired by fond memories of the
+;;; defsystem facility on Symbolics 3600's. The exhaustive lists of
+;;; filename extensions for various lisps and the idea to have one
+;;; "operate-on-system" function instead of separate "compile-system"
+;;; and "load-system" functions were taken from Xerox Corp.'s PCL
+;;; system.
+
+;;; This system improves on both PCL and Symbolics defsystem utilities
+;;; by performing a topological sort of the graph of file-dependency
+;;; constraints. Thus, the components of the system need not be listed
+;;; in any special order, because the defsystem command reorganizes them
+;;; based on their constraints. It includes all the standard bells and
+;;; whistles, such as not recompiling a binary file that is up to date
+;;; (unless the user specifies that all files should be recompiled).
+
+;;; Originally written by Mark Kantrowitz, School of Computer Science,
+;;; Carnegie Mellon University, October 1989.
+
+;;; MK:DEFSYSTEM 3.3 Interim
+;;;
+;;; Copyright (c) 1989 - 1999 Mark Kantrowitz. All rights reserved.
+;;;               1999 - 2004 Mark Kantrowitz and Marco Antoniotti. All
+;;;                           rights reserved.
+
+;;; Use, copying, modification, merging, publishing, distribution
+;;; and/or sale of this software, source and/or binary files and
+;;; associated documentation files (the "Software") and of derivative
+;;; works based upon this Software are permitted, as long as the
+;;; following conditions are met:
+
+;;;    o this copyright notice is included intact and is prominently
+;;;      visible in the Software
+;;;    o if modifications have been made to the source code of the
+;;;      this package that have not been adopted for inclusion in the
+;;;      official version of the Software as maintained by the Copyright
+;;;      holders, then the modified package MUST CLEARLY identify that
+;;;      such package is a non-standard and non-official version of
+;;;      the Software.  Furthermore, it is strongly encouraged that any
+;;;      modifications made to the Software be sent via e-mail to the
+;;;      MK-DEFSYSTEM maintainers for consideration of inclusion in the
+;;;      official MK-DEFSYSTEM package.
+
+;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;;; EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+;;; IN NO EVENT SHALL M. KANTROWITZ AND M. ANTONIOTTI 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.
+
+;;; Except as contained in this notice, the names of M. Kantrowitz and
+;;; M. Antoniotti shall not be used in advertising or otherwise to promote
+;;; the sale, use or other dealings in this Software without prior written
+;;; authorization from M. Kantrowitz and M. Antoniotti.
+
+
+;;; Please send bug reports, comments and suggestions to <marcoxa@cons.org>.
+
+
+;;; ********************************
+;;; Change Log *********************
+;;; ********************************
+;;;
+;;; Note: Several of the fixes from 30-JAN-91 and 31-JAN-91 were done in
+;;; September and October 1990, but not documented until January 1991.
+;;;
+;;; akd  = Abdel Kader Diagne <diagne@dfki.uni-sb.de>
+;;; as   = Andreas Stolcke <stolcke@ICSI.Berkeley.EDU>
+;;; bha  = Brian Anderson <bha@atc.boeing.com>
+;;; brad = Brad Miller <miller@cs.rochester.edu>
+;;; bw   = Robert Wilhelm <wilhelm@rpal.rockwell.com>
+;;; djc  = Daniel J. Clancy <clancy@cs.utexas.edu>
+;;; fdmm = Fernando D. Mato Mira <matomira@di.epfl.ch>
+;;; gc   = Guillaume Cartier <cartier@math.uqam.ca>
+;;; gi   = Gabriel Inaebnit <inaebnit@research.abb.ch>
+;;; gpw  = George Williams <george@hsvaic.boeing.com>
+;;; hkt  = Rick Taube <hkt@cm-next-8.stanford.edu>
+;;; ik   = Ik Su Yoo <ik@ctt.bellcore.com>
+;;; jk   = John_Kolojejchick@MORK.CIMDS.RI.CMU.EDU
+;;; kt   = Kevin Thompson <kthompso@ptolemy.arc.nasa.gov>
+;;; kc   = Kaelin Colclasure <kaelin@bridge.com>
+;;; kmr  = Kevin M. Rosenberg <kevin@rosenberg.net>
+;;; lmh  = Liam M. Healy <Liam.Healy@nrl.navy.mil>
+;;; mc   = Matthew Cornell <cornell@unix1.cs.umass.edu>
+;;; oc   = Oliver Christ <oli@adler.ims.uni-stuttgart.de>
+;;; rs   = Ralph P. Sobek <ralph@vega.laas.fr>
+;;; rs2  = Richard Segal <segal@cs.washington.edu>
+;;; sb   = Sean Boisen <sboisen@bbn.com>
+;;; ss   = Steve Strassman <straz@cambridge.apple.com>
+;;; tar  = Thomas A. Russ <tar@isi.edu>
+;;; toni = Anton Beschta <toni%l4@ztivax.siemens.com>
+;;; yc   = Yang Chen <yangchen%iris.usc.edu@usc.edu>
+;;;
+;;; Thanks to Steve Strassmann <straz@media-lab.media.mit.edu> and
+;;; Sean Boisen <sboisen@BBN.COM> for detailed bug reports and
+;;; miscellaneous assistance. Thanks also to Gabriel Inaebnit
+;;; <inaebnit@research.abb.ch> for help with VAXLisp bugs.
+;;;
+;;; 05-NOV-90  hkt  Changed canonicalize-system-name to make system
+;;;                 names package independent. Interns them in the
+;;;                 keyword package. Thus either strings or symbols may
+;;;                 be used to name systems from the user's point of view.
+;;; 05-NOV-90  hkt  Added definition FIND-SYSTEM to allow OOS to
+;;;                 work on systems whose definition hasn't been loaded yet.
+;;; 05-NOV-90  hkt  Added definitions COMPILE-SYSTEM and LOAD-SYSTEM
+;;;                 as alternates to OOS for naive users.
+;;; 05-NOV-90  hkt  Shadowing-import of 'defsystem in Allegro CL 3.1 [NeXT]
+;;;                 into USER package instead of import.
+;;; 15-NOV-90  mk   Changed package name to "MAKE", eliminating "DEFSYSTEM"
+;;;                 to avoid conflicts with allegro, symbolics packages
+;;;                 named "DEFSYSTEM".
+;;; 30-JAN-91  mk   Modified append-directories to work with the
+;;;                 logical-pathnames system.
+;;; 30-JAN-91  mk   Append-directories now works with Sun CL4.0. Also, fixed
+;;;                 bug wrt Lucid 4.0's pathnames (which changed from lcl3.0
+;;;                 -- 4.0 uses a list for the directory slot, whereas
+;;;                 3.0 required a string). Possible fix to symbolics bug.
+;;; 30-JAN-91  mk   Defined NEW-REQUIRE to make redefinition of REQUIRE
+;;;                 cleaner. Replaced all calls to REQUIRE in this file with
+;;;                 calls to NEW-REQUIRE, which should avoid compiler warnings.
+;;; 30-JAN-91  mk   In VAXLisp, when we redefine lisp:require, the compiler
+;;;                 no longer automatically executes require forms when it
+;;;                 encounters them in a file. The user can always wrap an
+;;;                 (eval-when (compile load eval) ...) around the require
+;;;                 form. Alternately, see commented out code near the
+;;;                 redefinition of lisp:require which redefines it as a
+;;;                 macro instead.
+;;; 30-JAN-91  mk   Added parameter :version to operate-on-system. If it is
+;;;                 a number, that number is used as part of the binary
+;;;                 directory name as the place to store and load files.
+;;;                 If NIL (the default), uses regular binary directory.
+;;;                 If T, tries to find the most recent version of the
+;;;                 binary directory.
+;;; 30-JAN-91  mk   Added global variable *use-timeouts* (default: t), which
+;;;                 specifies whether timeouts should be used in
+;;;                 Y-OR-N-P-WAIT. This is provided for users whose lisps
+;;;                 don't handle read-char-no-hang properly, so that they
+;;;                 can set it to NIL to disable the timeouts. Usually the
+;;;                 reason for this is the lisp is run on top of UNIX,
+;;;                 which buffers input LINES (and provides input editing).
+;;;                 To get around this we could always turn CBREAK mode
+;;;                 on and off, but there's no way to do this in a portable
+;;;                 manner.
+;;; 30-JAN-91  mk   Fixed bug where in :test t mode it was actually providing
+;;;                 the system, instead of faking it.
+;;; 30-JAN-91  mk   Changed storage of system definitions to a hash table.
+;;;                 Changed canonicalize-system-name to coerce the system
+;;;                 names to uppercase strings. Since we're no longer using
+;;;                 get, there's no need to intern the names as symbols,
+;;;                 and strings don't have packages to cause problems.
+;;;                 Added UNDEFSYSTEM, DEFINED-SYSTEMS, and DESCRIBE-SYSTEM.
+;;;                 Added :delete-binaries command.
+;;; 31-JAN-91  mk   Franz Allegro CL has a defsystem in the USER package,
+;;;                 so we need to do a shadowing import to avoid name
+;;;                 conflicts.
+;;; 31-JAN-91  mk   Fixed bug in compile-and-load-operation where it was
+;;;                 only loading newly compiled files.
+;;; 31-JAN-91  mk   Added :load-time slot to components to record the
+;;;                 file-write-date of the binary/source file that was loaded.
+;;;                 Now knows "when" (which date version) the file was loaded.
+;;;                 Added keyword :minimal-load and global *minimal-load*
+;;;                 to enable defsystem to avoid reloading unmodified files.
+;;;                 Note that if B depends on A, but A is up to date and
+;;;                 loaded and the user specified :minimal-load T, then A
+;;;                 will not be loaded even if B needs to be compiled. So
+;;;                 if A is an initializations file, say, then the user should
+;;;                 not specify :minimal-load T.
+;;; 31-JAN-91  mk   Added :load-only slot to components. If this slot is
+;;;                 specified as non-NIL, skips over any attempts to compile
+;;;                 the files in the component. (Loading the file satisfies
+;;;                 the need to recompile.)
+;;; 31-JAN-91  mk   Eliminated use of set-alist-lookup and alist-lookup,
+;;;                 replacing it with hash tables. It was too much bother,
+;;;                 and rather brittle too.
+;;; 31-JAN-91  mk   Defined #@ macro character for use with AFS @sys
+;;;                 feature simulator. #@"directory" is then synonymous
+;;;                 with (afs-binary-directory "directory").
+;;; 31-JAN-91  mk   Added :private-file type of module. It is similar to
+;;;                 :file, but has an absolute pathname. This allows you
+;;;                 to specify a different version of a file in a system
+;;;                 (e.g., if you're working on the file in your home
+;;;                 directory) without completely rewriting the system
+;;;                 definition.
+;;; 31-JAN-91  mk   Operations on systems, such as :compile and :load,
+;;;                 now propagate to subsystems the system depends on
+;;;                 if *operations-propagate-to-subsystems* is T (the default)
+;;;                 and the systems were defined using either defsystem
+;;;                 or as a :system component of another system. Thus if
+;;;                 a system depends on another, it can now recompile the
+;;;                 other.
+;;; 01-FEB-91  mk   Added default definitions of PROVIDE/REQUIRE/*MODULES*
+;;;                 for lisps that have thrown away these definitions in
+;;;                 accordance with CLtL2.
+;;; 01-FEB-91  mk   Added :compile-only slot to components. Analogous to
+;;;                 :load-only. If :compile-only is T, will not load the
+;;;                 file on operation :compile. Either compiles or loads
+;;;                 the file, but not both. In other words, compiling the
+;;;                 file satisfies the demand to load it. This is useful
+;;;                 for PCL defmethod and defclass definitions, which wrap
+;;;                 an (eval-when (compile load eval) ...) around the body
+;;;                 of the definition -- we save time by not loading the
+;;;                 compiled code, since the eval-when forces it to be
+;;;                 loaded. Note that this may not be entirely safe, since
+;;;                 CLtL2 has added a :load keyword to compile-file, and
+;;;                 some lisps may maintain a separate environment for
+;;;                 the compiler. This feature is for the person who asked
+;;;                 that a :COMPILE-SATISFIES-LOAD keyword be added to
+;;;                 modules. It's named :COMPILE-ONLY instead to match
+;;;                 :LOAD-ONLY.
+;;; 11-FEB-91  mk   Now adds :mk-defsystem to features list, to allow
+;;;                 special cased loading of defsystem if not already
+;;;                 present.
+;;; 19-FEB-91  duff Added filename extension for hp9000/300's running Lucid.
+;;; 26-FEB-91  mk   Distinguish between toplevel systems (defined with
+;;;                 defsystem) and systems defined as a :system module
+;;;                 of a defsystem. The former can depend only on systems,
+;;;                 while the latter can depend on anything at the same
+;;;                 level.
+;;; 12-MAR-91  mk   Added :subsystem component type to be a system with
+;;;                 pathnames relative to its parent component.
+;;; 12-MAR-91  mk   Uncommented :device :absolute for CMU pathnames, so
+;;;                 that the leading slash is included.
+;;; 12-MAR-91  brad Patches for Allegro 4.0.1 on Sparc.
+;;; 12-MAR-91  mk   Changed definition of format-justified-string so that
+;;;                 it no longer depends on the ~<~> format directives,
+;;;                 because Allegro 4.0.1 has a bug which doesn't support
+;;;                 them. Anyway, the new definition is twice as fast
+;;;                 and conses half as much as FORMAT.
+;;; 12-MAR-91 toni  Remove nils from list in expand-component-components.
+;;; 12-MAR-91 bw    If the default-package and system have the same name,
+;;;                 and the package is not loaded, this could lead to
+;;;                 infinite loops, so we bomb out with an error.
+;;;                 Fixed bug in default packages.
+;;; 13-MAR-91 mk    Added global *providing-blocks-load-propagation* to
+;;;                 control whether system dependencies are loaded if they
+;;;                 have already been provided.
+;;; 13-MAR-91 brad  In-package is a macro in CLtL2 lisps, so we change
+;;;                 the package manually in operate-on-component.
+;;; 15-MAR-91 mk    Modified *central-registry* to be either a single
+;;;                 directory pathname, or a list of directory pathnames
+;;;                 to be checked in order.
+;;; 15-MAR-91 rs    Added afs-source-directory to handle versions when
+;;;                 compiling C code under lisp. Other minor changes to
+;;;                 translate-version and operate-on-system.
+;;; 21-MAR-91 gi    Fixed bug in defined-systems.
+;;; 22-MAR-91 mk    Replaced append-directories with new version that works
+;;;                 by actually appending the directories, after massaging
+;;;                 them into the proper format. This should work for all
+;;;                 CLtL2-compliant lisps.
+;;; 09-APR-91 djc   Missing package prefix for lp:pathname-host-type.
+;;;                 Modified component-full-pathname to work for logical
+;;;                 pathnames.
+;;; 09-APR-91 mk    Added *dont-redefine-require* to control whether
+;;;                 REQUIRE is redefined. Fixed minor bugs in redefinition
+;;;                 of require.
+;;; 12-APR-91 mk    (pathname-host nil) causes an error in MCL 2.0b1
+;;; 12-APR-91 mc    Ported to MCL2.0b1.
+;;; 16-APR-91 mk    Fixed bug in needs-loading where load-time and
+;;;                 file-write-date got swapped.
+;;; 16-APR-91 mk    If the component is load-only, defsystem shouldn't
+;;;                 tell you that there is no binary and ask you if you
+;;;                 want to load the source.
+;;; 17-APR-91 mc    Two additional operations for MCL.
+;;; 21-APR-91 mk    Added feature requested by ik. *files-missing-is-an-error*
+;;;                 new global variable which controls whether files (source
+;;;                 and binary) missing cause a continuable error or just a
+;;;                 warning.
+;;; 21-APR-91 mk    Modified load-file-operation to allow compilation of source
+;;;                 files during load if the binary files are old or
+;;;                 non-existent. This adds a :compile-during-load keyword to
+;;;                 oos, and load-system. Global *compile-during-load* sets
+;;;                 the default (currently :query).
+;;; 21-APR-91 mk    Modified find-system so that there is a preference for
+;;;                 loading system files from disk, even if the system is
+;;;                 already defined in the environment.
+;;; 25-APR-91 mk    Removed load-time slot from component defstruct and added
+;;;                 function COMPONENT-LOAD-TIME to store the load times in a
+;;;                 hash table. This is safer than the old definition because
+;;;                 it doesn't wipe out load times every time the system is
+;;;                 redefined.
+;;; 25-APR-91 mk    Completely rewrote load-file-operation. Fixed some bugs
+;;;                 in :compile-during-load and in the behavior of defsystem
+;;;                 when multiple users are compiling and loading a system
+;;;                 instead of just a single user.
+;;; 16-MAY-91 mk    Modified FIND-SYSTEM to do the right thing if the system
+;;;                 definition file cannot be found.
+;;; 16-MAY-91 mk    Added globals *source-pathname-default* and
+;;;                 *binary-pathname-default* to contain default values for
+;;;                 :source-pathname and :binary-pathname. For example, set
+;;;                 *source-pathname-default* to "" to avoid having to type
+;;;                 :source-pathname "" all the time.
+;;; 27-MAY-91 mk    Fixed bug in new-append-directories where directory
+;;;                 components of the form "foo4.0" would appear as "foo4",
+;;;                 since pathname-name truncates the type. Changed
+;;;                 pathname-name to file-namestring.
+;;;  3-JUN-91 gc    Small bug in new-append-directories; replace (when
+;;;                 abs-name) with (when (not (null-string abs-name)))
+;;;  4-JUN-91 mk    Additional small change to new-append-directories for
+;;;                 getting the device from the relative pname if the abs
+;;;                 pname is "". This is to fix a small behavior in CMU CL old
+;;;                 compiler. Also changed (when (not (null-string abs-name)))
+;;;                 to have an (and abs-name) in there.
+;;;  8-JAN-92 sb    Added filename extension for defsystem under Lucid Common
+;;;                 Lisp/SGO 3.0.1+.
+;;;  8-JAN-92 mk    Changed the definition of prompt-string to work around an
+;;;                 AKCL bug. Essentially, AKCL doesn't default the colinc to
+;;;                 1 if the colnum is provided, so we hard code it.
+;;;  8-JAN-92 rs    (pathname-directory (pathname "")) returns '(:relative) in
+;;;                 Lucid, instead of NIL. Changed new-append-directories and
+;;;                 test-new-append-directories to reflect this.
+;;;  8-JAN-92 mk    Fixed problem related to *load-source-if-no-binary*.
+;;;                 compile-and-load-source-if-no-binary wasn't checking for
+;;;                 the existence of the binary if this variable was true,
+;;;                 causing the file to not be compiled.
+;;;  8-JAN-92 mk    Fixed problem with null-string being called on a pathname
+;;;                 by returning NIL if the argument isn't a string.
+;;;  3-NOV-93 mk    In Allegro 4.2, pathname device is :unspecific by default.
+;;; 11-NOV-93 fdmm  Fixed package definition lock problem when redefining
+;;;                 REQUIRE on ACL.
+;;; 11-NOV-93 fdmm  Added machine and software types for SGI and IRIX. It is
+;;;                 important to distinguish the OS version and CPU type in
+;;;                 SGI+ACL, since ACL 4.1 on IRIX 4.x and ACL 4.2 on IRIX 5.x
+;;;                 have incompatible .fasl files.
+;;; 01-APR-94 fdmm  Fixed warning problem when redefining REQUIRE on LispWorks.
+;;; 01-NOV-94 fdmm  Replaced (software-type) call in ACL by code extracting
+;;;                 the interesting parts from (software-version) [deleted
+;;;                 machine name and id].
+;;; 03-NOV-94 fdmm  Added a hook (*compile-file-function*), that is funcalled
+;;;                 by compile-file-operation, so as to support other languages
+;;;                 running on top of Common Lisp.
+;;;                 The default is to compile  Common Lisp.
+;;; 03-NOV-94 fdmm  Added SCHEME-COMPILE-FILE, so that defsystem can now
+;;;                 compile Pseudoscheme files.
+;;; 04-NOV-94 fdmm  Added the exported generic function SET-LANGUAGE, to
+;;;                 have a clean, easy to extend  interface for telling
+;;;                 defsystem which language to assume for compilation.
+;;;                 Currently supported arguments: :common-lisp, :scheme.
+;;; 11-NOV-94 kc    Ported to Allegro CL for Windows 2.0 (ACLPC) and CLISP.
+;;; 18-NOV-94 fdmm  Changed the entry *filename-extensions* for LispWorks
+;;;                 to support any platform.
+;;;                 Added entries for :mcl and :clisp too.
+;;; 16-DEC-94 fdmm  Added and entry for CMU CL on SGI to *filename-extensions*.
+;;; 16-DEC-94 fdmm  Added OS version identification for CMU CL on SGI.
+;;; 16-DEC-94 fdmm  For CMU CL 17 : Bypassed make-pathnames call fix
+;;;                 in NEW-APPEND-DIRECTORIES.
+;;; 16-DEC-94 fdmm  Added HOME-SUBDIRECTORY to fix CMU's ignorance about `~'
+;;;                 when specifying registries.
+;;; 16-DEC-94 fdmm  For CMU CL 17 : Bypassed :device fix in make-pathnames call
+;;;                 in COMPONENT-FULL-PATHNAME. This fix was also reported
+;;;                 by kc on 12-NOV-94. CMU CL 17 now supports CLtL2 pathnames.
+;;; 16-DEC-94 fdmm  Removed a quote before the call to read in the readmacro
+;;;                 #@. This fixes a really annoying misfeature (couldn't do
+;;;                 #@(concatenate 'string "foo/" "bar"), for example).
+;;; 03-JAN-95 fdmm  Do not include :pcl in *features* if :clos is there.
+;;;  2-MAR-95 mk    Modified fdmm's *central-registry* change to use
+;;;                 user-homedir-pathname and to be a bit more generic in the
+;;;                 pathnames.
+;;;  2-MAR-95 mk    Modified fdmm's updates to *filename-extensions* to handle
+;;;                 any CMU CL binary extensions.
+;;;  2-MAR-95 mk    Make kc's port to ACLPC a little more generic.
+;;;  2-MAR-95 mk    djc reported a bug, in which GET-SYSTEM was not returning
+;;;                 a system despite the system's just having been loaded.
+;;;                 The system name specified in the :depends-on was a
+;;;                 lowercase string. I am assuming that the system name
+;;;                 in the defsystem form was a symbol (I haven't verified
+;;;                 that this was the case with djc, but it is the only
+;;;                 reasonable conclusion). So, CANONICALIZE-SYSTEM-NAME
+;;;                 was storing the system in the hash table as an
+;;;                 uppercase string, but attempting to retrieve it as a
+;;;                 lowercase string. This behavior actually isn't a bug,
+;;;                 but a user error. It was intended as a feature to
+;;;                 allow users to use strings for system names when
+;;;                 they wanted to distinguish between two different systems
+;;;                 named "foo.system" and "Foo.system". However, this
+;;;                 user error indicates that this was a bad design decision.
+;;;                 Accordingly, CANONICALIZE-SYSTEM-NAME now uppercases
+;;;                 even strings for retrieving systems, and the comparison
+;;;                 in *modules* is now case-insensitive. The result of
+;;;                 this change is if the user cannot have distinct
+;;;                 systems in "Foo.system" and "foo.system" named "Foo" and
+;;;                 "foo", because they will clobber each other. There is
+;;;                 still case-sensitivity on the filenames (i.e., if the
+;;;                 system file is named "Foo.system" and you use "foo" in
+;;;                 the :depends-on, it won't find it). We didn't take the
+;;;                 further step of requiring system filenames to be lowercase
+;;;                 because we actually find this kind of case-sensitivity
+;;;                 to be useful, when maintaining two different versions
+;;;                 of the same system.
+;;;  7-MAR-95 mk    Added simplistic handling of logical pathnames. Also
+;;;                 modified new-append-directories so that it'll try to
+;;;                 split up pathname directories that are strings into a
+;;;                 list of the directory components. Such directories aren't
+;;;                 ANSI CL, but some non-conforming implementations do it.
+;;;  7-MAR-95 mk    Added :proclamations to defsystem form, which can be used
+;;;                 to set the compiler optimization level before compilation.
+;;;                 For example,
+;;;                  :proclamations '(optimize (safety 3) (speed 3) (space 0))
+;;;  7-MAR-95 mk    Defsystem now tells the user when it reloads the system
+;;;                 definition.
+;;;  7-MAR-95 mk    Fixed problem pointed out by yc. If
+;;;                 *source-pathname-default* is "" and there is no explicit
+;;;                 :source-pathname specified for a file, the file could
+;;;                 wind up with an empty file name. In other words, this
+;;;                 global default shouldn't apply to :file components. Added
+;;;                 explicit test for null strings, and when present replaced
+;;;                 them with NIL (for binary as well as source, and also for
+;;;                 :private-file components).
+;;;  7-MAR-95 tar   Fixed defsystem to work on TI Explorers (TI CL).
+;;;  7-MAR-95 jk    Added machine-type-translation for Decstation 5000/200
+;;;                 under Allegro 3.1
+;;;  7-MAR-95 as    Fixed bug in AKCL-1-615 in which defsystem added a
+;;;                 subdirectory "RELATIVE" to all filenames.
+;;;  7-MAR-95 mk    Added new test to test-new-append-directories to catch the
+;;;                 error fixed by as. Essentially, this error occurs when the
+;;;                 absolute-pathname has no directory (i.e., it has a single
+;;;                 pathname component as in "foo" and not "foo/bar"). If
+;;;                 RELATIVE ever shows up in the Result, we now know to
+;;;                 add an extra conditionalization to prevent abs-keyword
+;;;                 from being set to :relative.
+;;;  7-MAR-95 ss    Miscellaneous fixes for MCL 2.0 final.
+;;;                 *compile-file-verbose* not in MCL, *version variables
+;;;                 need to occur before AFS-SOURCE-DIRECTORY definition,
+;;;                 and certain code needed to be in the CCL: package.
+;;;  8-MAR-95 mk    Y-OR-N-P-WAIT uses a busy-waiting. On Lisp systems where
+;;;                 the time functions cons, such as CMU CL, this can cause a
+;;;                 lot of ugly garbage collection messages. Modified the
+;;;                 waiting to include calls to SLEEP, which should reduce
+;;;                 some of the consing.
+;;;  8-MAR-95 mk    Replaced fdmm's SET-LANGUAGE enhancement with a more
+;;;                 general extension, along the lines suggested by akd.
+;;;                 Defsystem now allows components to specify a :language
+;;;                 slot, such as :language :lisp, :language :scheme. This
+;;;                 slot is inherited (with the default being :lisp), and is
+;;;                 used to obtain compilation and loading functions for
+;;;                 components, as well as source and binary extensions. The
+;;;                 compilation and loading functions can be overridden by
+;;;                 specifying a :compiler or :loader in the system
+;;;                 definition. Also added :documentation slot to the system
+;;;                 definition.
+;;;                    Where this comes in real handy is if one has a
+;;;                 compiler-compiler implemented in Lisp, and wants the
+;;;                 system to use the compiler-compiler to create a parser
+;;;                 from a grammar and then compile parser. To do this one
+;;;                 would create a module with components that looked
+;;;                 something like this:
+;;;		  ((:module cc :components ("compiler-compiler"))
+;;;		   (:module gr :compiler 'cc :loader #'ignore
+;;;			    :source-extension "gra"
+;;;			    :binary-extension "lisp"
+;;;			    :depends-on (cc)
+;;;			    :components ("sample-grammar"))
+;;;		   (:module parser :depends-on (gr)
+;;;			    :components ("sample-grammar")))
+;;;                 Defsystem would then compile and load the compiler, use
+;;;                 it (the function cc) to compile the grammar into a parser,
+;;;                 and then compile the parser. The only tricky part is
+;;;                 cc is defined by the system, and one can't include #'cc
+;;;                 in the system definition. However, one could include
+;;;                 a call to mk:define-language in the compiler-compiler file,
+;;;                 and define :cc as a language. This is the prefered method.
+;;;  8-MAR-95 mk    New definition of topological-sort suggested by rs2. This
+;;;                 version avoids the call to SORT, but in practice isn't
+;;;                 much faster. However, it avoids the need to maintain a
+;;;                 TIME slot in the topsort-node structure.
+;;;  8-MAR-95 mk    rs2 also pointed out that the calls to MAKE-PATHNAME and
+;;;                 NAMESTRING in COMPONENT-FULL-PATHNAME are a major reason
+;;;                 why defsystem is slow. Accordingly, I've changed
+;;;                 COMPONENT-FULL-PATHNAME to include a call to NAMESTRING
+;;;                 (and removed all other calls to NAMESTRING), and also made
+;;;                 a few changes to minimize the number of calls to
+;;;                 COMPONENT-FULL-PATHNAME, such as memoizing it. See To Do
+;;;                 below for other related comments.
+;;;  8-MAR-95 mk    Added special hack requested by Steve Strassman, which
+;;;                 allows one to specify absolute pathnames in the shorthand
+;;;                 for a list of components, and have defsystem recognize
+;;;                 which are absolute and which are relative.
+;;;                 I actually think this would be a good idea, but I haven't
+;;;                 tested it, so it is disabled by default. Search for
+;;;                 *enable-straz-absolute-string-hack* to enable it.
+;;;  8-MAR-95 kt    Fixed problem with EXPORT in AKCL 1.603, in which it wasn't
+;;;                 properly exporting the value of the global export
+;;;                 variables.
+;;;  8-MAR-95 mk    Added UNMUNGE-LUCID to fix nasty problem with COMPILE-FILE
+;;;                 in Lucid. Lucid apparently tries to merge the :output-file
+;;;                 with the source file when the :output-file is a relative
+;;;                 pathname. Wierd, and definitely non-standard.
+;;;  9-MAR-95 mk    Changed ALLEGRO-MAKE-SYSTEM-FASL to also include the files
+;;;                 in any systems the system depends on, as per a
+;;;                 request of oc.
+;;;  9-MAR-95 mk    Some version of CMU CL couldn't hack a call to
+;;;                 MAKE-PATHNAME with :host NIL. I'm not sure which version
+;;;                 it is, but the current version doesn't have this problem.
+;;;                 If given :host nil, it defaults the host to
+;;;                 COMMON-LISP::*UNIX-HOST*. So I haven't "fixed" this
+;;;                 problem.
+;;;  9-MAR-95 mk    Integrated top-level commands for Allegro designed by bha
+;;;                 into the code, with slight modifications.
+;;;  9-MAR-95 mk    Instead of having COMPUTE-SYSTEM-PATH check the current
+;;;                 directory in a hard-coded fashion, include the current
+;;;                 directory in the *central-registry*, as suggested by
+;;;                 bha and others.
+;;;  9-MAR-95 bha   Support for Logical Pathnames in Allegro.
+;;;  9-MAR-95 mk    Added modified version of bha's DEFSYSPATH idea.
+;;; 13-MAR-95 mk    Added a macro for the simple serial case, where a system
+;;;                 (or module) is simple a list of files, each of which
+;;;                 depends on the previous one. If the value of :components
+;;;                 is a list beginning with :serial, it expands each
+;;;                 component and makes it depend on the previous component.
+;;;                 For example, (:serial "foo" "bar" "baz") would create a
+;;;                 set of components where "baz" depended on "bar" and "bar"
+;;;                 on "foo".
+;;; 13-MAR-95 mk    *** Now version 3.0. This version is a interim bug-fix and
+;;;                 update, since I do not have the time right now to complete
+;;;                 the complete overhaul and redesign.
+;;;                 Major changes in 3.0 include CMU CL 17, CLISP, ACLPC, TI,
+;;;                 LispWorks and ACL(SGI) support, bug fixes for ACL 4.1/4.2.
+;;; 14-MAR-95 fdmm  Finally added the bit of code to discriminate cleanly
+;;;                 among different lisps without relying on (software-version)
+;;;                 idiosyncracies.
+;;;                 You can now customize COMPILER-TYPE-TRANSLATION so that
+;;;                 AFS-BINARY-DIRECTORY can return a different value for
+;;;                 different lisps on the same platform.
+;;;                 If you use only one compiler, do not care about supporting
+;;;                 code for multiple versions of it, and want less verbose
+;;;                 directory names, just set *MULTIPLE-LISP-SUPPORT* to nil.
+;;; 17-MAR-95 lmh   Added EVAL-WHEN for one of the MAKE-PACKAGE calls.
+;;;                 CMU CL's RUN-PROGRAM is in the extensions package.
+;;;                 ABSOLUTE-FILE-NAMESTRING-P was missing :test keyword
+;;;                 Rearranged conditionalization in DIRECTORY-TO-LIST to
+;;;                 suppress compiler warnings in CMU CL.
+;;; 17-MAR-95 mk    Added conditionalizations to avoid certain CMU CL compiler
+;;;                 warnings reported by lmh.
+;;; 19990610  ma    Added shadowing of 'HARDCOPY-SYSTEM' for LW Personal Ed.
+
+;;; 19991211  ma    NEW VERSION 4.0 started.
+;;; 19991211  ma    Merged in changes requested by T. Russ of
+;;;                 ISI. Please refer to the special "ISI" comments to
+;;;                 understand these changes
+;;; 20000228 ma     The symbols FIND-SYSTEM, LOAD-SYSTEM, DEFSYSTEM,
+;;;                 COMPILE-SYSTEM and HARDCOPY-SYSTEM are no longer
+;;;                 imported in the COMMON-LISP-USER package.
+;;;                 Cfr. the definitions of *EXPORTS* and
+;;;                 *SPECIAL-EXPORTS*.
+;;; 2000-07-21 rlt  Add COMPILER-OPTIONS to defstruct to allow user to
+;;;                 specify special compiler options for a particular
+;;;                 component.
+;;; 2002-01-08 kmr  Changed allegro symbols to lowercase to support
+;;;                 case-sensitive images
+
+;;;---------------------------------------------------------------------------
+;;; ISI Comments
+;;;
+;;; 19991211 Marco Antoniotti
+;;; These comments come from the "ISI Branch".  I believe I did
+;;; include the :load-always extension correctly.  The other commets
+;;; seem superseded by other changes made to the system in the
+;;; following years.  Some others are now useless with newer systems
+;;; (e.g. filename truncation for new Windows based CL
+;;; implementations.)
+
+;;;  1-OCT-92 tar   Fixed problem with TI Lisp machines and append-directory.
+;;;  1-OCT-92 tar   Made major modifications to compile-file-operation and
+;;;                 load-file-operation to reduce the number of probe-file
+;;;                 and write-date inquiries.  This makes the system run much
+;;;                 faster through slow network connections.
+;;; 13-OCT-92 tar   Added :load-always slot to components. If this slot is
+;;;                 specified as non-NIL, always loads the component.
+;;;                 This does not trigger dependent compilation.
+;;;                 (This can be useful when macro definitions needed
+;;;                 during compilation are changed by later files.  In
+;;;                 this case, not reloading up-to-date files can
+;;;                 cause different results.)
+;;; 28-OCT-93 tar   Allegro 4.2 causes an error on (pathname-device nil)
+;;; 14-SEP-94 tar   Disable importing of symbols into (CL-)USER package
+;;;                 to minimize conflicts with other defsystem utilities.
+;;; 10-NOV-94 tar   Added filename truncation code to support Franz Allegro
+;;;                 PC with it's 8 character filename limitation.
+;;; 15-MAY-98 tar   Changed host attribute for pathnames to support LispWorks
+;;;                 (Windows) pathnames which reference other Drives.  Also
+;;;                 updated file name convention.
+;;;  9-NOV-98 tar   Updated new-append-directories for Lucid 5.0
+;;;
+
+
+
+;;; ********************************
+;;; Ports **************************
+;;; ********************************
+;;;
+;;;    DEFSYSTEM has been tested (successfully) in the following lisps:
+;;;       CMU Common Lisp (M2.9 15-Aug-90, Compiler M1.8 15-Aug-90)
+;;;       CMU Common Lisp (14-Dec-90 beta, Python Compiler 0.0 PMAX/Mach)
+;;;       CMU Common Lisp 17f (Python 1.0)
+;;;       Franz Allegro Common Lisp 3.1.12 (ExCL 3/30/90)
+;;;       Franz Allegro Common Lisp 4.0/4.1/4.2
+;;;       Franz Allegro Common Lisp for Windows (2.0)
+;;;       Lucid Common Lisp (Version 2.1 6-DEC-87)
+;;;       Lucid Common Lisp (3.0 [SPARC,SUN3])
+;;;       Lucid Common Lisp (4.0 [SPARC,SUN3])
+;;;       VAXLisp (v2.2) [VAX/VMS]
+;;;       VAXLisp (v3.1)
+;;;       Harlequin LispWorks
+;;;       CLISP (CLISP3 [SPARC])
+;;;       Symbolics XL12000 (Genera 8.3)
+;;;       Scieneer Common Lisp (SCL) 1.1
+;;;       Macintosh Common Lisp
+;;;       ECL
+;;;
+;;;    DEFSYSTEM needs to be tested in the following lisps:
+;;;       OpenMCL
+;;;       Symbolics Common Lisp (8.0)
+;;;       KCL (June 3, 1987 or later)
+;;;       AKCL (1.86, June 30, 1987 or later)
+;;;       TI (Release 4.1 or later)
+;;;       Ibuki Common Lisp (01/01, October 15, 1987)
+;;;       Golden Common Lisp (3.1 IBM-PC)
+;;;       HP Common Lisp (same as Lucid?)
+;;;       Procyon Common Lisp
+
+
+;;; ********************************
+;;; To Do **************************
+;;; ********************************
+;;;
+;;; COMPONENT-FULL-PATHNAME is a major source of slowness in the system
+;;; because of all the calls to the expensive operations MAKE-PATHNAME
+;;; and NAMESTRING. To improve performance, DEFSYSTEM should be reworked
+;;; to avoid any need to call MAKE-PATHNAME and NAMESTRING, as the logical
+;;; pathnames package does. Unfortunately, I don't have the time to do this
+;;; right now. Instead, I installed a temporary improvement by memoizing
+;;; COMPONENT-FULL-PATHNAME to cache previous calls to the function on
+;;; a component by component and type by type basis. The cache is
+;;; cleared before each call to OOS, in case filename extensions change.
+;;; But DEFSYSTEM should really be reworked to avoid this problem and
+;;; ensure greater portability and to also handle logical pathnames.
+;;;
+;;; Also, PROBE-FILE and FILE-WRITE-DATE are other sources of slowness.
+;;; Perhaps by also memoizing FILE-WRITE-DATE and reimplementing PROBE-FILE
+;;; in terms of FILE-WRITE-DATE, can achieve a further speed-up. This was
+;;; suggested by Steven Feist (feist@ils.nwu.edu).
+;;;
+;;; True CLtL2 logical pathnames support -- can't do it, because CLtL2
+;;; doesn't have all the necessary primitives, and even in Allegro CL 4.2
+;;;   (namestring #l"foo:bar;baz.lisp")
+;;; does not work properly.
+;;;
+;;; Create separate stand-alone documentation for defsystem, and also
+;;; a test suite.
+;;;
+;;; Change SYSTEM to be a class instead of a struct, and make it a little
+;;; more generic, so that it permits alternate system definitions.
+;;; Replace OPERATE-ON-SYSTEM with MAP-SYSTEM (args: function, system-name,
+;;; &rest options)
+;;;
+;;; Add a patch directory mechanism. Perhaps have several directories
+;;; with code in them, and the first one with the specified file wins?
+;;; LOAD-PATCHES function.
+;;;
+;;; Need way to load old binaries even if source is newer.
+;;;
+;;; Allow defpackage forms/package definitions in the defsystem? If
+;;; a package not defined, look for and load a file named package.pkg?
+;;;
+;;; need to port for GNU CL (ala kcl)?
+;;;
+;;; Someone asked whether one can have :file components at top-level. I believe
+;;; this is the case, but should double-check that it is possible (and if
+;;; not, make it so).
+;;;
+;;; A common error/misconception seems to involve assuming that :system
+;;; components should include the name of the system file, and that
+;;; defsystem will automatically load the file containing the system
+;;; definition and propagate operations to it. Perhaps this would be a
+;;; nice feature to add.
+;;;
+;;; If a module is :load-only t, then it should not execute its :finally-do
+;;; and :initially-do clauses during compilation operations, unless the
+;;; module's files happen to be loaded during the operation.
+;;;
+;;; System Class. Customizable delimiters.
+;;;
+;;; Load a system (while not loading anything already loaded)
+;;; and inform the user of out of date fasls with the choice
+;;; to load the old fasl or recompile and then load the new
+;;; fasl?
+;;;
+;;; modify compile-file-operation to handle a query keyword....
+;;;
+;;; Perhaps systems should keep around the file-write-date of the system
+;;; definition file, to prevent excessive reloading of the system definition?
+;;;
+;;; load-file-operation needs to be completely reworked to simplify the
+;;; logic of when files get loaded or not.
+;;;
+;;; Need to revamp output: Nesting and indenting verbose output doesn't
+;;; seem cool, especially when output overflows the 80-column margins.
+;;;
+;;; Document various ways of writing a system. simple (short) form
+;;; (where :components is just a list of filenames) in addition to verbose.
+;;; Put documentation strings in code.
+;;;
+;;; :load-time for modules and systems -- maybe record the time the system
+;;; was loaded/compiled here and print it in describe-system?
+;;;
+;;; Make it easy to define new functions that operate on a system. For
+;;; example, a function that prints out a list of files that have changed,
+;;; hardcopy-system, edit-system, etc.
+;;;
+;;; If a user wants to have identical systems for different lisps, do we
+;;; force the user to use logical pathnames? Or maybe we should write a
+;;; generic-pathnames package that parses any pathname format into a
+;;; uniform underlying format (i.e., pull the relevant code out of
+;;; logical-pathnames.lisp and clean it up a bit).
+;;;
+;;;    Verify that Mac pathnames now work with append-directories.
+;;;
+;;; A common human error is to violate the modularization by making a file
+;;; in one module depend on a file in another module, instead of making
+;;; one module depend on the other. This is caught because the dependency
+;;; isn't found. However, is there any way to provide a more informative
+;;; error message? Probably not, especially if the system has multiple
+;;; files of the same name.
+;;;
+;;; For a module none of whose files needed to be compiled, have it print out
+;;; "no files need recompilation".
+;;;
+;;; Write a system date/time to a file? (version information) I.e., if the
+;;; filesystem supports file version numbers, write an auxiliary file to
+;;; the system definition file that specifies versions of the system and
+;;; the version numbers of the associated files.
+;;;
+;;; Add idea of a patch directory.
+;;;
+;;; In verbose printout, have it log a date/time at start and end of
+;;; compilation:
+;;;     Compiling system "test" on 31-Jan-91 21:46:47
+;;;     by Defsystem version v2.0 01-FEB-91.
+;;;
+;;; Define other :force options:
+;;;    :query    allows user to specify that a file not normally compiled
+;;;              should be. OR
+;;;    :confirm  allows user to specify that a file normally compiled
+;;;              shouldn't be. AND
+;;;
+;;; We currently assume that compilation-load dependencies and if-changed
+;;; dependencies are identical. However, in some cases this might not be
+;;; true. For example, if we change a macro we have to recompile functions
+;;; that depend on it (except in lisps that automatically do this, such
+;;; as the new CMU Common Lisp), but not if we change a function. Splitting
+;;; these apart (with appropriate defaulting) would be nice, but not worth
+;;; doing immediately since it may save only a couple of file recompilations,
+;;; while making defsystem much more complex than it already is.
+;;;
+;;; Current dependencies are limited to siblings. Maybe we should allow
+;;; nephews and uncles? So long as it is still a DAG, we can sort it.
+;;; Answer: No. The current setup enforces a structure on the modularity.
+;;; Otherwise, why should we have modules if we're going to ignore it?
+;;;
+;;; Currently a file is recompiled more or less if the source is newer
+;;; than the binary or if the file depends on a file that has changed
+;;; (i.e., was recompiled in this session of a system operation).
+;;; Neil Goldman <goldman@isi.edu> has pointed out that whether a file
+;;; needs recompilation is really independent of the current session of
+;;; a system operation, and depends only on the file-write-dates of the
+;;; source and binary files for a system. Thus a file should require
+;;; recompilation in the following circumstances:
+;;;   1. If a file's source is newer than its binary, or
+;;;   2. If a file's source is not newer than its binary, but the file
+;;;      depends directly or indirectly on a module (or file) that is newer.
+;;;      For a regular file use the file-write-date (FWD) of the source or
+;;;      binary, whichever is more recent. For a load-only file, use the only
+;;;      available FWD. For a module, use the most recent (max) FWD of any of
+;;;      its components.
+;;; The impact of this is that instead of using a boolean CHANGED variable
+;;; throughout the code, we need to allow CHANGED to be NIL/T/<FWD> or
+;;; maybe just the FWD timestamp, and to use the value of CHANGED in
+;;; needs-compilation decisions. (Use of NIL/T as values is an optimization.
+;;; The FWD timestamp which indicates the most recent time of any changes
+;;; should be sufficient.) This will affect not just the
+;;; compile-file-operation, but also the load-file-operation because of
+;;; compilation during load. Also, since FWDs will be used more prevalently,
+;;; we probably should couple this change with the inclusion of load-times
+;;; in the component defstruct. This is a tricky and involved change, and
+;;; requires more thought, since there are subtle cases where it might not
+;;; be correct. For now, the change will have to wait until the DEFSYSTEM
+;;; redesign.
+
+
+;;; ********************************************************************
+;;; How to Use this System *********************************************
+;;; ********************************************************************
+
+;;; To use this system,
+;;; 1. If you want to have a central registry of system definitions,
+;;;    modify the value of the variable *central-registry* below.
+;;; 2. Load this file (defsystem.lisp) in either source or compiled form,
+;;; 3. Load the file containing the "defsystem" definition of your system,
+;;; 4. Use the function "operate-on-system" to do things to your system.
+
+;;; For more information, see the documentation and examples in
+;;; lisp-utilities.ps.
+
+;;; ********************************
+;;; Usage Comments *****************
+;;; ********************************
+
+;;; If you use symbols in the system definition file, they get interned in
+;;; the COMMON-LISP-USER package, which can lead to name conflicts when
+;;; the system itself seeks to export the same symbol to the COMMON-LISP-USER
+;;; package. The workaround is to use strings instead of symbols for the
+;;; names of components in the system definition file. In the major overhaul,
+;;; perhaps the user should be precluded from using symbols for such
+;;; identifiers.
+;;;
+;;; If you include a tilde in the :source-pathname in Allegro, as in "~/lisp",
+;;; file name expansion is much slower than if you use the full pathname,
+;;; as in "/user/USERID/lisp".
+;;;
+
+
+;;; ****************************************************************
+;;; Lisp Code ******************************************************
+;;; ****************************************************************
+
+;;; ********************************
+;;; Massage CLtL2 onto *features* **
+;;; ********************************
+;;; Let's be smart about CLtL2 compatible Lisps:
+(eval-when (compile load eval)
+  #+(or (and allegro-version>= (version>= 4 0)) :mcl :openmcl :sbcl)
+  (pushnew :cltl2 *features*))
+
+;;; ********************************
+;;; Provide/Require/*modules* ******
+;;; ********************************
+
+;;; Since CLtL2 has dropped require and provide from the language, some
+;;; lisps may not have the functions PROVIDE and REQUIRE and the
+;;; global *MODULES*. So if lisp::provide and user::provide are not
+;;; defined, we define our own.
+
+;;; Hmmm. CMU CL old compiler gives bogus warnings here about functions
+;;; and variables not being declared or bound, apparently because it
+;;; sees that (or (fboundp 'lisp::require) (fboundp 'user::require)) returns
+;;; T, so it doesn't really bother when compiling the body of the unless.
+;;; The new compiler does this properly, so I'm not going to bother
+;;; working around this.
+
+;;; Some Lisp implementations return bogus warnings about assuming
+;;; *MODULE-FILES* and *LIBRARY* to be special, and CANONICALIZE-MODULE-NAME
+;;; and MODULE-FILES being undefined. Don't worry about them.
+
+;;; Now that ANSI CL includes PROVIDE and REQUIRE again, is this code
+;;; necessary?
+
+#-(or :CMU
+      :vms
+      :mcl
+      :openmcl
+      :lispworks
+      :clisp
+      :gcl
+      :sbcl
+      :cormanlisp
+      :scl
+      (and allegro-version>= (version>= 4 1)))
+(eval-when #-(or :lucid)
+           (:compile-toplevel :load-toplevel :execute)
+	   #+(or :lucid)
+           (compile load eval)
+
+  (unless (or (fboundp 'lisp::require)
+	      (fboundp 'user::require)
+
+	      #+(and :excl (and allegro-version>= (version>= 4 0)))
+	      (fboundp 'cltl1::require)
+
+	      #+:lispworks
+	      (fboundp 'system::require))
+
+    #-:lispworks
+    (in-package "LISP")
+    #+:lispworks
+    (in-package "SYSTEM")
+
+    (export '(*modules* provide require))
+
+    ;; Documentation strings taken almost literally from CLtL1.
+
+    (defvar *modules* ()
+      "List of names of the modules that have been loaded into Lisp so far.
+     It is used by PROVIDE and REQUIRE.")
+
+    ;; We provide two different ways to define modules. The default way
+    ;; is to put either a source or binary file with the same name
+    ;; as the module in the library directory. The other way is to define
+    ;; the list of files in the module with defmodule.
+
+    ;; The directory listed in *library* is implementation dependent,
+    ;; and is intended to be used by Lisp manufacturers as a place to
+    ;; store their implementation dependent packages.
+    ;; Lisp users should use systems and *central-registry* to store
+    ;; their packages -- it is intended that *central-registry* is
+    ;; set by the user, while *library* is set by the lisp.
+
+    (defvar *library* nil		; "/usr/local/lisp/Modules/"
+      "Directory within the file system containing files, where the name
+     of a file is the same as the name of the module it contains.")
+
+    (defvar *module-files* (make-hash-table :test #'equal)
+      "Hash table mapping from module names to list of files for the
+     module. REQUIRE loads these files in order.")
+
+    (defun canonicalize-module-name (name)
+      ;; if symbol, string-downcase the printrep to make nicer filenames.
+      (if (stringp name) name (string-downcase (string name))))
+
+    (defmacro defmodule (name &rest files)
+      "Defines a module NAME to load the specified FILES in order."
+      `(setf (gethash (canonicalize-module-name ,name) *module-files*)
+	     ',files))
+    (defun module-files (name)
+      (gethash name *module-files*))
+
+    (defun provide (name)
+      "Adds a new module name to the list of modules maintained in the
+     variable *modules*, thereby indicating that the module has been
+     loaded. Name may be a string or symbol -- strings are case-senstive,
+     while symbols are treated like lowercase strings. Returns T if
+     NAME was not already present, NIL otherwise."
+      (let ((module (canonicalize-module-name name)))
+	(unless (find module *modules* :test #'string=)
+	  ;; Module not present. Add it and return T to signify that it
+	  ;; was added.
+	  (push module *modules*)
+	  t)))
+
+    (defun require (name &optional pathname)
+      "Tests whether a module is already present. If the module is not
+     present, loads the appropriate file or set of files. The pathname
+     argument, if present, is a single pathname or list of pathnames
+     whose files are to be loaded in order, left to right. If the
+     pathname is nil, the system first checks if a module was defined
+     using defmodule and uses the pathnames so defined. If that fails,
+     it looks in the library directory for a file with name the same
+     as that of the module. Returns T if it loads the module."
+      (let ((module (canonicalize-module-name name)))
+	(unless (find module *modules* :test #'string=)
+	  ;; Module is not already present.
+	  (when (and pathname (not (listp pathname)))
+	    ;; If there's a pathname or pathnames, ensure that it's a list.
+	    (setf pathname (list pathname)))
+	  (unless pathname
+	    ;; If there's no pathname, try for a defmodule definition.
+	    (setf pathname (module-files module)))
+	  (unless pathname
+	    ;; If there's still no pathname, try the library directory.
+	    (when *library*
+	      (setf pathname (concatenate 'string *library* module))
+	      ;; Test if the file exists.
+	      ;; We assume that the lisp will default the file type
+	      ;; appropriately. If it doesn't, use #+".fasl" or some
+	      ;; such in the concatenate form above.
+	      (if (probe-file pathname)
+		  ;; If it exists, ensure we've got a list
+		  (setf pathname (list pathname))
+		  ;; If the library file doesn't exist, we don't want
+		  ;; a load error.
+		  (setf pathname nil))))
+	  ;; Now that we've got the list of pathnames, let's load them.
+	  (dolist (pname pathname t)
+	    (load pname :verbose nil))))))
+  ) ; eval-when
+
+;;; ********************************
+;;; Set up Package *****************
+;;; ********************************
+
+
+;;; Unfortunately, lots of lisps have their own defsystems, some more
+;;; primitive than others, all uncompatible, and all in the DEFSYSTEM
+;;; package. To avoid name conflicts, we've decided to name this the
+;;; MAKE package. A nice side-effect is that the short nickname
+;;; MK is my initials.
+
+#+(or clisp cormanlisp ecl (and gcl defpackage) sbcl)
+(defpackage "MAKE" (:use "COMMON-LISP") (:nicknames "MK"))
+
+#-(or :sbcl :cltl2 :lispworks :ecl :scl)
+(in-package "MAKE" :nicknames '("MK"))
+
+;;; For CLtL2 compatible lisps...
+#+(and :excl :allegro-v4.0 :cltl2)
+(defpackage "MAKE" (:nicknames "MK" "make" "mk") (:use :common-lisp)
+	    (:import-from cltl1 *modules* provide require))
+
+;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19970105
+;;; In Allegro 4.1, 'provide' and 'require' are not external in
+;;; 'CLTL1'.  However they are in 'COMMON-LISP'.  Hence the change.
+#+(and :excl :allegro-v4.1 :cltl2)
+(defpackage "MAKE" (:nicknames "MK" "make" "mk") (:use :common-lisp) )
+
+#+(and :excl :allegro-version>= (version>= 4 2))
+(defpackage "MAKE" (:nicknames "MK" "make" "mk") (:use :common-lisp))
+
+#+:lispworks
+(defpackage "MAKE" (:nicknames "MK") (:use "COMMON-LISP")
+	    (:import-from system *modules* provide require)
+	    (:export "DEFSYSTEM" "COMPILE-SYSTEM" "LOAD-SYSTEM"
+		     "DEFINE-LANGUAGE" "*MULTIPLE-LISP-SUPPORT*"))
+
+#+:mcl
+(defpackage "MAKE" (:nicknames "MK") (:use "COMMON-LISP")
+  (:import-from ccl *modules* provide require))
+
+;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19951012
+;;; The code below, is originally executed also for CMUCL. However I
+;;; believe this is wrong, since CMUCL comes with its own defpackage.
+;;; I added the extra :CMU in the 'or'.
+#+(and :cltl2 (not (or :cmu :clisp :sbcl
+		       (and :excl (or :allegro-v4.0 :allegro-v4.1))
+		       :mcl)))
+(eval-when (compile load eval)
+  (unless (find-package "MAKE")
+    (make-package "MAKE" :nicknames '("MK") :use '("COMMON-LISP"))))
+
+;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19951012
+;;; Here I add the proper defpackage for CMU
+#+:CMU
+(defpackage "MAKE" (:use "COMMON-LISP" "CONDITIONS")
+  (:nicknames "MK"))
+
+#+:sbcl
+(defpackage "MAKE" (:use "COMMON-LISP")
+  (:nicknames "MK"))
+
+#+:scl
+(defpackage :make (:use :common-lisp)
+  (:nicknames :mk))
+
+#+(or :cltl2 :lispworks :scl)
+(eval-when (compile load eval)
+  (in-package "MAKE"))
+
+#+ecl
+(in-package "MAKE")
+
+;;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu> 19970105
+;;; 'provide' is not esternal in 'CLTL1' in Allegro v 4.1
+#+(and :excl :allegro-v4.0 :cltl2)
+(cltl1:provide 'make)
+#+(and :excl :allegro-v4.0 :cltl2)
+(provide 'make)
+
+#+:openmcl
+(cl:provide 'make)
+
+#+(and :mcl (not :openmcl))
+(ccl:provide 'make)
+
+#+(and :cltl2 (not (or (and :excl (or :allegro-v4.0 :allegro-v4.1)) :mcl)))
+(provide 'make)
+
+#+:lispworks
+(provide 'make)
+
+#-(or :cltl2 :lispworks)
+(provide 'make)
+
+(pushnew :mk-defsystem *features*)
+
+;;; Some compatibility issues.  Mostly for CormanLisp.
+;;; 2002-02-20 Marco Antoniotti
+
+#+cormanlisp
+(defun compile-file-pathname (pathname-designator)
+ (merge-pathnames (make-pathname :type "fasl")
+		  (etypecase pathname-designator
+		    (pathname pathname-designator)
+		    (string (parse-namestring pathname-designator))
+		    ;; We need FILE-STREAM here as well.
+		    )))
+
+#+cormanlisp
+(defun file-namestring (pathname-designator)
+  (let ((p (etypecase pathname-designator
+	     (pathname pathname-designator)
+	     (string (parse-namestring pathname-designator))
+	     ;; We need FILE-STREAM here as well.
+	     )))
+    (namestring (make-pathname :directory ()
+			       :name (pathname-name p)
+			       :type (pathname-type p)
+			       :version (pathname-version p)))))
+
+;;; The external interface consists of *exports* and *other-exports*.
+
+;;; AKCL (at least 1.603) grabs all the (export) forms and puts them up top in
+;;; the compile form, so that you can't use a defvar with a default value and
+;;; then a succeeding export as well.
+
+(eval-when (compile load eval)
+   (defvar *special-exports* nil)
+   (defvar *exports* nil)
+   (defvar *other-exports* nil)
+
+   (export (setq *exports*
+		 '(operate-on-system
+		   oos
+		   afs-binary-directory afs-source-directory
+		   files-in-system)))
+   (export (setq *special-exports*
+		 '()))
+   (export (setq *other-exports*
+		 '(*central-registry*
+		   *bin-subdir*
+
+		   add-registry-location
+		   find-system
+		   defsystem compile-system load-system hardcopy-system
+
+                   system-definition-pathname
+
+                   missing-component
+                   missing-component-name
+                   missing-component-component
+                   missing-module
+                   missing-system
+
+                   register-foreign-system
+
+		   machine-type-translation
+		   software-type-translation
+		   compiler-type-translation
+		   ;; require
+		   define-language
+		   allegro-make-system-fasl
+		   files-which-need-compilation
+		   undefsystem
+		   defined-systems
+		   describe-system clean-system edit-system ;hardcopy-system
+		   system-source-size make-system-tag-table
+		   *defsystem-version*
+		   *compile-during-load*
+		   *minimal-load*
+		   *dont-redefine-require*
+		   *files-missing-is-an-error*
+		   *reload-systems-from-disk*
+		   *source-pathname-default*
+		   *binary-pathname-default*
+		   *multiple-lisp-support*
+		   ))))
+
+
+;;; We import these symbols into the USER package to make them
+;;; easier to use. Since some lisps have already defined defsystem
+;;; in the user package, we may have to shadowing-import it.
+#|
+#-(or :sbcl :cmu :ccl :allegro :excl :lispworks :symbolics)
+(eval-when (compile load eval)
+  (import *exports* #-(or :cltl2 :lispworks) "USER"
+	            #+(or :cltl2 :lispworks) "COMMON-LISP-USER")
+  (import *special-exports* #-(or :cltl2 :lispworks) "USER"
+	                    #+(or :cltl2 :lispworks) "COMMON-LISP-USER"))
+#+(or :sbcl :cmu :ccl :allegro :excl :lispworks :symbolics)
+(eval-when (compile load eval)
+  (import *exports* #-(or :cltl2 :lispworks) "USER"
+	            #+(or :cltl2 :lispworks) "COMMON-LISP-USER")
+  (shadowing-import *special-exports*
+		    #-(or :cltl2 :lispworks) "USER"
+		    #+(or :cltl2 :lispworks) "COMMON-LISP-USER"))
+|#
+
+#-(or :PCL :CLOS :scl)
+(when (find-package "PCL")
+  (pushnew :pcl *modules*)
+  (pushnew :pcl *features*))
+
+;;; ********************************
+;;; Defsystem Version **************
+;;; ********************************
+(defparameter *defsystem-version* "3.3 Interim, 2002-06-13"
+  "Current version number/date for Defsystem.")
+
+;;; ********************************
+;;; Customizable System Parameters *
+;;; ********************************
+
+(defvar *dont-redefine-require* nil
+  "If T, prevents the redefinition of REQUIRE. This is useful for
+   lisps that treat REQUIRE specially in the compiler.")
+
+(defvar *multiple-lisp-support* t
+  "If T, afs-binary-directory will try to return a name dependent
+   on the particular lisp compiler version being used.")
+
+;;; home-subdirectory --
+;;; HOME-SUBDIRECTORY is used only in *central-registry* below.
+;;; Note that CMU CL 17e does not understand the ~/ shorthand for home
+;;; directories.
+;;;
+;;; Note:
+;;; 20020220 Marco Antoniotti
+;;; The #-cormanlisp version is the original one, which is broken anyway, since
+;;; it is UNIX dependent.
+;;; I added the kludgy #+cormalisp (v 1.5) one, since it is missing
+;;; the ANSI USER-HOMEDIR-PATHNAME function.
+#-cormanlisp
+(defun home-subdirectory (directory)
+  (concatenate 'string
+	#+(or :sbcl :cmu :scl)
+	"home:"
+	#-(or :sbcl :cmu :scl)
+	(let ((homedir (user-homedir-pathname)))
+	  (or (and homedir (namestring homedir))
+	      "~/"))
+	directory))
+
+#+cormanlisp
+(defun home-subdirectory (directory)
+  (declare (type string directory))
+  (concatenate 'string "C:\\" directory))
+
+;;; The following function is available for users to add
+;;;   (setq mk:*central-registry* (defsys-env-search-path))
+;;; to Lisp init files in order to use the value of the DEFSYSPATH
+;;; instead of directly coding it in the file.
+#+:allegro
+(defun defsys-env-search-path ()
+  "This function grabs the value of the DEFSYSPATH environment variable
+   and breaks the search path into a list of paths."
+  (remove-duplicates (split-string (sys:getenv "DEFSYSPATH") :item #\:)
+		     :test #'string-equal))
+
+;;; Change this variable to set up the location of a central
+;;; repository for system definitions if you want one.
+;;; This is a defvar to allow users to change the value in their
+;;; lisp init files without worrying about it reverting if they
+;;; reload defsystem for some reason.
+
+;;; Note that if a form is included in the registry list, it will be evaluated
+;;; in COMPUTE-SYSTEM-PATH to return the appropriate directory to check.
+
+(defvar *central-registry*
+  `(;; Current directory
+    "./"
+    #+:LUCID     (working-directory)
+    #+ACLPC      (current-directory)
+    #+:allegro   (excl:current-directory)
+    #+:sbcl      (progn *default-pathname-defaults*)
+    #+(or :cmu :scl)       (ext:default-directory)
+    ;; *** Marco Antoniotti <marcoxa@icsi.berkeley.edu>
+    ;; Somehow it is better to qualify default-directory in CMU with
+    ;; the appropriate package (i.e. "EXTENSIONS".)
+    ;; Same for Allegro.
+    #+(and :lispworks (not :lispworks4))
+    ,(multiple-value-bind (major minor)
+			  #-:lispworks-personal-edition
+			  (system::lispworks-version)
+			  #+:lispworks-personal-edition
+			  (values system::*major-version-number*
+				  system::*minor-version-number*)
+       (if (or (> major 3)
+	       (and (= major 3) (> minor 2))
+	       (and (= major 3) (= minor 2)
+		    (equal (lisp-implementation-version) "3.2.1")))
+	   `(make-pathname :directory
+			   ,(find-symbol "*CURRENT-WORKING-DIRECTORY*"
+					 (find-package "SYSTEM")))
+           (find-symbol "*CURRENT-WORKING-DIRECTORY*"
+                        (find-package "LW"))))
+    #+:lispworks4
+    (hcl:get-working-directory)
+    ;; Home directory
+    #-sbcl
+    (mk::home-subdirectory "lisp/systems/")
+
+    ;; Global registry
+    "/usr/local/lisp/Registry/")
+  "Central directory of system definitions. May be either a single
+   directory pathname, or a list of directory pathnames to be checked
+   after the local directory.")
+
+
+(defun add-registry-location (pathname)
+  "Adds a path to the central registry."
+  (pushnew pathname *central-registry* :test #'equal))
+
+(defvar *bin-subdir* ".bin/"
+  "The subdirectory of an AFS directory where the binaries are really kept.")
+
+;;; These variables set up defaults for operate-on-system, and are used
+;;; for communication in lieu of parameter passing. Yes, this is bad,
+;;; but it keeps the interface small. Also, in the case of the -if-no-binary
+;;; variables, parameter passing would require multiple value returns
+;;; from some functions. Why make life complicated?
+(defvar *tell-user-when-done* nil
+  "If T, system will print ...DONE at the end of an operation")
+(defvar *oos-verbose* nil
+  "Operate on System Verbose Mode")
+(defvar *oos-test* nil
+  "Operate on System Test Mode")
+(defvar *load-source-if-no-binary* nil
+  "If T, system will try loading the source if the binary is missing")
+(defvar *bother-user-if-no-binary* t
+  "If T, the system will ask the user whether to load the source if
+   the binary is missing")
+(defvar *load-source-instead-of-binary* nil
+  "If T, the system will load the source file instead of the binary.")
+(defvar *compile-during-load* :query
+  "If T, the system will compile source files during load if the
+   binary file is missing. If :query, it will ask the user for
+   permission first.")
+(defvar *minimal-load* nil
+  "If T, the system tries to avoid reloading files that were already loaded
+   and up to date.")
+
+(defvar *files-missing-is-an-error* t
+  "If both the source and binary files are missing, signal a continuable
+   error instead of just a warning.")
+
+(defvar *operations-propagate-to-subsystems* t
+  "If T, operations like :COMPILE and :LOAD propagate to subsystems
+   of a system that are defined either using a component-type of :system
+   or by another defsystem form.")
+
+;;; Particular to CMULisp
+(defvar *compile-error-file-type* "err"
+  "File type of compilation error file in cmulisp")
+(defvar *cmu-errors-to-terminal* t
+  "Argument to :errors-to-terminal in compile-file in cmulisp")
+(defvar *cmu-errors-to-file* t
+  "If T, cmulisp will write an error file during compilation")
+
+;;; ********************************
+;;; Global Variables ***************
+;;; ********************************
+
+;;; Massage people's *features* into better shape.
+(eval-when (compile load eval)
+  (dolist (feature *features*)
+    (when (and (symbolp feature)   ; 3600
+               (equal (symbol-name feature) "CMU"))
+      (pushnew :CMU *features*)))
+
+  #+Lucid
+  (when (search "IBM RT PC" (machine-type))
+    (pushnew :ibm-rt-pc *features*))
+  )
+
+;;; *filename-extensions* is a cons of the source and binary extensions.
+(defvar *filename-extensions*
+  (car `(#+(and Symbolics Lispm)              ("lisp" . "bin")
+         #+(and dec common vax (not ultrix))  ("LSP"  . "FAS")
+         #+(and dec common vax ultrix)        ("lsp"  . "fas")
+ 	 #+ACLPC                              ("lsp"  . "fsl")
+ 	 #+CLISP                              ("lsp"  . "fas")
+         #+KCL                                ("lsp"  . "o")
+         #+ECL                                ("lsp"  . "so")
+         #+IBCL                               ("lsp"  . "o")
+         #+Xerox                              ("lisp" . "dfasl")
+	 ;; Lucid on Silicon Graphics
+	 #+(and Lucid MIPS)                   ("lisp" . "mbin")
+	 ;; the entry for (and lucid hp300) must precede
+	 ;; that of (and lucid mc68000) for hp9000/300's running lucid,
+	 ;; since *features* on hp9000/300's also include the :mc68000
+	 ;; feature.
+	 #+(and lucid hp300)                  ("lisp" . "6bin")
+         #+(and Lucid MC68000)                ("lisp" . "lbin")
+         #+(and Lucid Vax)                    ("lisp" . "vbin")
+         #+(and Lucid Prime)                  ("lisp" . "pbin")
+         #+(and Lucid SUNRise)                ("lisp" . "sbin")
+         #+(and Lucid SPARC)                  ("lisp" . "sbin")
+         #+(and Lucid :IBM-RT-PC)             ("lisp" . "bbin")
+	 ;; PA is Precision Architecture, HP's 9000/800 RISC cpu
+	 #+(and Lucid PA)		      ("lisp" . "hbin")
+         #+excl ("cl"   . ,(pathname-type (compile-file-pathname "foo.cl")))
+         #+(or :cmu :scl)  ("lisp" . ,(or (c:backend-fasl-file-type c:*backend*) "fasl"))
+;	 #+(and :CMU (not (or :sgi :sparc)))  ("lisp" . "fasl")
+;        #+(and :CMU :sgi)                    ("lisp" . "sgif")
+;        #+(and :CMU :sparc)                  ("lisp" . "sparcf")
+	 #+PRIME                              ("lisp" . "pbin")
+         #+HP                                 ("l"    . "b")
+         #+TI ("lisp" . #.(string (si::local-binary-file-type)))
+         #+:gclisp                            ("LSP"  . "F2S")
+         #+pyramid                            ("clisp" . "o")
+
+	 ;; Harlequin LispWorks
+	 #+:lispworks 	      ("lisp" . ,COMPILER:*FASL-EXTENSION-STRING*)
+;        #+(and :sun4 :lispworks)             ("lisp" . "wfasl")
+;        #+(and :mips :lispworks)             ("lisp" . "mfasl")
+         #+:mcl                               ("lisp" . ,(pathname-type (compile-file-pathname "foo.lisp")))
+         #+:coral                             ("lisp" . "fasl")
+
+         ;; Otherwise,
+         ("lisp" . ,(pathname-type (compile-file-pathname "foo.lisp")))))
+  "Filename extensions for Common Lisp. A cons of the form
+   (Source-Extension . Binary-Extension). If the system is
+   unknown (as in *features* not known), defaults to lisp and fasl.")
+
+(defvar *system-extension*
+  ;; MS-DOS systems can only handle three character extensions.
+  #-ACLPC "system"
+  #+ACLPC "sys"
+  "The filename extension to use with systems.")
+
+;;; The above variables and code should be extended to allow a list of
+;;; valid extensions for each lisp implementation, instead of a single
+;;; extension. When writing a file, the first extension should be used.
+;;; But when searching for a file, every extension in the list should
+;;; be used. For example, CMU Common Lisp recognizes "lisp" "l" "cl" and
+;;; "lsp" (*load-source-types*) as source code extensions, and
+;;; (c:backend-fasl-file-type c:*backend*)
+;;; (c:backend-byte-fasl-file-type c:*backend*)
+;;; and "fasl" as binary (object) file extensions (*load-object-types*).
+
+;;; Note that the above code is used below in the LANGUAGE defstruct.
+
+;;; There is no real support for this variable being nil, so don't change it.
+;;; Note that in any event, the toplevel system (defined with defsystem)
+;;; will have its dependencies delayed. Not having dependencies delayed
+;;; might be useful if we define several systems within one defsystem.
+(defvar *system-dependencies-delayed* t
+  "If T, system dependencies are expanded at run time")
+
+;;; Replace this with consp, dammit!
+(defun non-empty-listp (list)
+  (and list (listp list)))
+
+;;; ********************************
+;;; Component Operation Definition *
+;;; ********************************
+(eval-when (:compile-toplevel :load-toplevel :execute)
+(defvar *version-dir* nil
+  "The version subdir. bound in operate-on-system.")
+(defvar *version-replace* nil
+  "The version replace. bound in operate-on-system.")
+(defvar *version* nil
+  "Default version."))
+
+(defvar *component-operations* (make-hash-table :test #'equal)
+  "Hash table of (operation-name function) pairs.")
+(defun component-operation (name &optional operation)
+  (if operation
+      (setf (gethash name *component-operations*) operation)
+      (gethash name *component-operations*)))
+
+;;; ********************************
+;;; AFS @sys immitator *************
+;;; ********************************
+
+;;; mc 11-Apr-91: Bashes MCL's point reader, so commented out.
+#-:mcl
+(eval-when (compile load eval)
+  ;; Define #@"foo" as a shorthand for (afs-binary-directory "foo").
+  ;; For example,
+  ;;    <cl> #@"foo"
+  ;;    "foo/.bin/rt_mach/"
+  (set-dispatch-macro-character
+   #\# #\@
+   #'(lambda (stream char arg)
+       (declare (ignore char arg))
+       `(afs-binary-directory ,(read stream t nil t)))))
+
+(defvar *find-irix-version-script*
+    "\"1,4 d\\
+s/^[^M]*IRIX Execution Environment 1, *[a-zA-Z]* *\\([^ ]*\\)/\\1/p\\
+/./,$ d\\
+\"")
+
+(defun operating-system-version ()
+  #+(and :sgi :excl)
+  (let* ((full-version (software-version))
+	 (blank-pos (search " " full-version))
+	 (os (subseq full-version 0 blank-pos))
+	 (version-rest (subseq full-version
+			       (1+ blank-pos)))
+	 os-version)
+    (setq blank-pos (search " " version-rest))
+    (setq version-rest (subseq version-rest
+			       (1+ blank-pos)))
+    (setq blank-pos (search " " version-rest))
+    (setq os-version (subseq version-rest 0 blank-pos))
+    (setq version-rest (subseq version-rest
+			       (1+ blank-pos)))
+    (setq blank-pos (search " " version-rest))
+    (setq version-rest (subseq version-rest
+			       (1+ blank-pos)))
+    (concatenate 'string
+      os " " os-version))      ; " " version-rest
+  #+(and :sgi :cmu :sbcl)
+  (concatenate 'string
+    (software-type)
+    (software-version))
+  #+(and :lispworks :irix)
+  (let ((soft-type (software-type)))
+    (if (equalp soft-type "IRIX5")
+        (progn
+          (foreign:call-system
+	    (format nil "versions ~A | sed -e ~A > ~A"
+                         "eoe1"
+                         *find-irix-version-script*
+                         "irix-version")
+	    "/bin/csh")
+          (with-open-file (s "irix-version")
+                          (format nil "IRIX ~S"
+				  (read s))))
+      soft-type))
+  #-(or (and :excl :sgi) (and :cmu :sgi) (and :lispworks :irix))
+  (software-type))
+
+(defun compiler-version ()
+  #+:lispworks (concatenate 'string
+		"lispworks" " " (lisp-implementation-version))
+  #+excl      (concatenate 'string
+		"excl" " " excl::*common-lisp-version-number*)
+  #+sbcl      (concatenate 'string
+			   "sbcl" " " (lisp-implementation-version))
+  #+cmu       (concatenate 'string
+		"cmu" " " (lisp-implementation-version))
+  #+scl       (concatenate 'string
+		"scl" " " (lisp-implementation-version))
+
+  #+kcl       "kcl"
+  #+IBCL      "ibcl"
+  #+akcl      "akcl"
+  #+gcl       "gcl"
+  #+ecl       "ecl"
+  #+lucid     "lucid"
+  #+ACLPC     "aclpc"
+  #+CLISP     "clisp"
+  #+Xerox     "xerox"
+  #+symbolics "symbolics"
+  #+mcl       "mcl"
+  #+coral     "coral"
+  #+gclisp    "gclisp"
+  )
+
+(defun afs-binary-directory (root-directory)
+  ;; Function for obtaining the directory AFS's @sys feature would have
+  ;; chosen when we're not in AFS. This function is useful as the argument
+  ;; to :binary-pathname in defsystem. For example,
+  ;; :binary-pathname (afs-binary-directory "scanner/")
+  (let ((machine (machine-type-translation
+		  #-(and :sgi :allegro-version>= (version>= 4 2))
+		  (machine-type)
+		  #+(and :sgi :allegro-version>= (version>= 4 2))
+		  (machine-version)))
+	(software (software-type-translation
+		   #-(and :sgi (or :cmu :sbcl :scl
+				   (and :allegro-version>= (version>= 4 2))))
+		   (software-type)
+		   #+(and :sgi (or :cmu :sbcl :scl
+				   (and :allegro-version>= (version>= 4 2))))
+		   (operating-system-version)))
+	(lisp (compiler-type-translation (compiler-version))))
+    ;; pmax_mach rt_mach sun3_35 sun3_mach vax_mach
+    (setq root-directory (namestring root-directory))
+    (setq root-directory (ensure-trailing-slash root-directory))
+    (format nil "~A~@[~A~]~@[~A/~]"
+	    root-directory
+	    *bin-subdir*
+	    (if *multiple-lisp-support*
+		(afs-component machine software lisp)
+	      (afs-component machine software)))))
+
+(defun afs-source-directory (root-directory &optional version-flag)
+  ;; Function for obtaining the directory AFS's @sys feature would have
+  ;; chosen when we're not in AFS. This function is useful as the argument
+  ;; to :source-pathname in defsystem.
+  (setq root-directory (namestring root-directory))
+  (setq root-directory (ensure-trailing-slash root-directory))
+  (format nil "~A~@[~A/~]"
+          root-directory
+          (and version-flag (translate-version *version*))))
+
+(defun null-string (s)
+  (when (stringp s)
+    (string-equal s "")))
+
+(defun ensure-trailing-slash (dir)
+  (if (and dir
+	   (not (null-string dir))
+	   (not (char= (char dir
+			     (1- (length dir)))
+		       #\/))
+	   (not (char= (char dir
+			     (1- (length dir)))
+		       #\\))
+	   )
+      (concatenate 'string dir "/")
+      dir))
+
+(defun afs-component (machine software &optional lisp)
+  (format nil "~@[~A~]~@[_~A~]~@[_~A~]"
+	    machine
+	    (or software "mach")
+	    lisp))
+
+(defvar *machine-type-alist* (make-hash-table :test #'equal)
+  "Hash table for retrieving the machine-type")
+(defun machine-type-translation (name &optional operation)
+  (if operation
+      (setf (gethash (string-upcase name) *machine-type-alist*) operation)
+      (gethash (string-upcase name) *machine-type-alist*)))
+
+(machine-type-translation "IBM RT PC"                        "rt")
+(machine-type-translation "DEC 3100"                         "pmax")
+(machine-type-translation "DEC VAX-11"                       "vax")
+(machine-type-translation "DECstation"                       "pmax")
+(machine-type-translation "Sun3"                             "sun3")
+(machine-type-translation "Sun-4"                            "sun4")
+(machine-type-translation "MIPS Risc"                        "mips")
+(machine-type-translation "SGI"                              "sgi")
+(machine-type-translation "Silicon Graphics Iris 4D"         "sgi")
+(machine-type-translation "Silicon Graphics Iris 4D (R3000)" "sgi")
+(machine-type-translation "Silicon Graphics Iris 4D (R4000)" "sgi")
+(machine-type-translation "Silicon Graphics Iris 4D (R4400)" "sgi")
+(machine-type-translation "IP22"                             "sgi")
+;;; MIPS R4000 Processor Chip Revision: 3.0
+;;; MIPS R4400 Processor Chip Revision: 5.0
+;;; MIPS R4600 Processor Chip Revision: 1.0
+(machine-type-translation "IP20"                             "sgi")
+;;; MIPS R4000 Processor Chip Revision: 3.0
+(machine-type-translation "IP17"                             "sgi")
+;;; MIPS R4000 Processor Chip Revision: 2.2
+(machine-type-translation "IP12"                             "sgi")
+;;; MIPS R2000A/R3000 Processor Chip Revision: 3.0
+(machine-type-translation "IP7"                              "sgi")
+;;; MIPS R2000A/R3000 Processor Chip Revision: 3.0
+
+(machine-type-translation "x86"                              "x86")
+;;; ACL
+(machine-type-translation "IBM PC Compatible"                "x86")
+;;; LW
+(machine-type-translation "I686"                             "x86")
+;;; LW
+(machine-type-translation "PC/386"                           "x86")
+;;; CLisp Win32
+
+#+(and :lucid :sun :mc68000)
+(machine-type-translation "unknown"     "sun3")
+
+
+(defvar *software-type-alist* (make-hash-table :test #'equal)
+  "Hash table for retrieving the software-type")
+(defun software-type-translation (name &optional operation)
+  (if operation
+      (setf (gethash (string-upcase name) *software-type-alist*) operation)
+      (gethash (string-upcase name) *software-type-alist*)))
+
+(software-type-translation "BSD UNIX"      "mach") ; "unix"
+(software-type-translation "Ultrix"        "mach") ; "ultrix"
+(software-type-translation "SunOS"         "SunOS")
+(software-type-translation "MACH/4.3BSD"   "mach")
+(software-type-translation "IRIX System V" "irix") ; (software-type)
+(software-type-translation "IRIX5"         "irix5")
+;;(software-type-translation "IRIX liasg5 5.2 02282016 IP22 mips" "irix5") ; (software-version)
+
+(software-type-translation "IRIX 5.2" "irix5")
+(software-type-translation "IRIX 5.3" "irix5")
+(software-type-translation "IRIX5.2"  "irix5")
+(software-type-translation "IRIX5.3"  "irix5")
+
+(software-type-translation "Linux" "linux") ; Lispworks for Linux
+(software-type-translation "Linux 2.x, Redhat 6.x and 7.x" "linux") ; ACL
+(software-type-translation "Microsoft Windows 9x/Me and NT/2000/XP" "win32")
+(software-type-translation "Windows NT" "win32") ; LW for Windows
+(software-type-translation "ANSI C program" "ansi-c") ; CLISP
+(software-type-translation "C compiler" "ansi-c") ; CLISP for Win32
+
+(software-type-translation nil             "")
+
+#+:lucid
+(software-type-translation "Unix"
+			   #+:lcl4.0 "4.0"
+			   #+(and :lcl3.0 (not :lcl4.0)) "3.0")
+
+(defvar *compiler-type-alist* (make-hash-table :test #'equal)
+  "Hash table for retrieving the Common Lisp type")
+(defun compiler-type-translation (name &optional operation)
+  (if operation
+      (setf (gethash (string-upcase name) *compiler-type-alist*) operation)
+    (gethash (string-upcase name) *compiler-type-alist*)))
+
+(compiler-type-translation "lispworks 3.2.1"         "lispworks")
+(compiler-type-translation "lispworks 3.2.60 beta 6" "lispworks")
+(compiler-type-translation "lispworks 4.2.0"         "lispworks")
+
+#+allegro
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (unless (or (find :case-sensitive common-lisp:*features*)
+	      (find :case-insensitive common-lisp:*features*))
+    (if (or (eq excl:*current-case-mode* :case-sensitive-lower)
+	    (eq excl:*current-case-mode* :case-sensitive-upper))
+	(push :case-sensitive common-lisp:*features*)
+      (push :case-insensitive common-lisp:*features*))))
+
+
+#+(and allegro case-sensitive ics)
+(compiler-type-translation "excl 6.1" "excl-m")
+#+(and allegro case-sensitive (not ics))
+(compiler-type-translation "excl 6.1" "excl-m8")
+
+#+(and allegro case-insensitive ics)
+(compiler-type-translation "excl 6.1" "excl-a")
+#+(and allegro case-insensitive (not ics))
+(compiler-type-translation "excl 6.1" "excl-a8")
+
+(compiler-type-translation "excl 4.2" "excl")
+(compiler-type-translation "excl 4.1" "excl")
+(compiler-type-translation "cmu 17f" "cmu")
+(compiler-type-translation "cmu 17e" "cmu")
+(compiler-type-translation "cmu 17d" "cmu")
+
+;;; ********************************
+;;; System Names *******************
+;;; ********************************
+
+;;; If you use strings for system names, be sure to use the same case
+;;; as it appears on disk, if the filesystem is case sensitive.
+(defun canonicalize-system-name (name)
+  ;; Originally we were storing systems using GET. This meant that the
+  ;; name of a system had to be a symbol, so we interned the symbols
+  ;; in the keyword package to avoid package dependencies. Now that we're
+  ;; storing the systems in a hash table, we've switched to using strings.
+  ;; Since the hash table is case sensitive, we use uppercase strings.
+  ;; (Names of modules and files may be symbols or strings.)
+  #||(if (keywordp name)
+      name
+      (intern (string-upcase (string name)) "KEYWORD"))||#
+  (if (stringp name) (string-upcase name) (string-upcase (string name))))
+
+(defvar *defined-systems* (make-hash-table :test #'equal)
+  "Hash table containing the definitions of all known systems.")
+
+(defun get-system (name)
+  "Returns the definition of the system named NAME."
+  (gethash (canonicalize-system-name name) *defined-systems*))
+
+(defsetf get-system (name) (value)
+  `(setf (gethash (canonicalize-system-name ,name) *defined-systems*) ,value))
+
+(defun undefsystem (name)
+  "Removes the definition of the system named NAME."
+  (setf (get-system name) nil))
+
+(defun defined-systems ()
+  "Returns a list of defined systems."
+  (let ((result nil))
+    (maphash #'(lambda (key value)
+		 (declare (ignore key))
+		 (push value result))
+	     *defined-systems*)
+    result))
+
+;;; ********************************
+;;; Directory Pathname Hacking *****
+;;; ********************************
+
+;;; Unix example: An absolute directory starts with / while a
+;;; relative directory doesn't. A directory ends with /, while
+;;; a file's pathname doesn't. This is important 'cause
+;;; (pathname-directory "foo/bar") will return "foo" and not "foo/".
+
+;;; I haven't been able to test the fix to the problem with symbolics
+;;; hosts. Essentially, append-directories seems to have been tacking
+;;; the default host onto the front of the pathname (e.g., mk::source-pathname
+;;; gets a "B:" on front) and this overrides the :host specified in the
+;;; component. The value of :host should override that specified in
+;;; the :source-pathname and the default file server. If this doesn't
+;;; fix things, specifying the host in the root pathname "F:>root-dir>"
+;;; may be a good workaround.
+
+;;; Need to verify that merging of pathnames where modules are located
+;;; on different devices (in VMS-based VAXLisp) now works.
+
+;;; Merge-pathnames works for VMS systems. In VMS systems, the directory
+;;; part is enclosed in square brackets, e.g.,
+;;; 	"[root.child.child_child]" or "[root.][child.][child_child]"
+;;; To concatenate directories merge-pathnames works as follows:
+;;; 	(merge-pathnames "" "[root]")               ==> "[root]"
+;;; 	(merge-pathnames "[root.]" "[son]file.ext") ==> "[root.son]file.ext"
+;;; 	(merge-pathnames "[root.]file.ext" "[son]") ==> "[root.son]file.ext"
+;;; 	(merge-pathnames "[root]file.ext" "[son]")  ==> "[root]file.ext"
+;;; Thus the problem with the #-VMS code was that it was merging x y into
+;;; [[x]][y] instead of [x][y] or [x]y.
+
+;;; Miscellaneous notes:
+;;;   On GCLisp, the following are equivalent:
+;;;       "\\root\\subdir\\BAZ"
+;;;       "/root/subdir/BAZ"
+;;;   On VAXLisp, the following are equivalent:
+;;;       "[root.subdir]BAZ"
+;;;       "[root.][subdir]BAZ"
+;;; Use #+:vaxlisp for VAXLisp 3.0, #+(and vms dec common vax) for v2.2
+
+(defun new-append-directories (absolute-dir relative-dir)
+  ;; Version of append-directories for CLtL2-compliant lisps. In particular,
+  ;; they must conform to section 23.1.3 "Structured Directories". We are
+  ;; willing to fix minor aberations in this function, but not major ones.
+  ;; Tested in Allegro CL 4.0 (SPARC), Allegro CL 3.1.12 (DEC 3100),
+  ;; CMU CL old and new compilers, Lucid 3.0, Lucid 4.0.
+  (setf absolute-dir (or absolute-dir "")
+	relative-dir (or relative-dir ""))
+  (let* ((abs-dir (pathname absolute-dir))
+	 (rel-dir (pathname relative-dir))
+	 (host (pathname-host abs-dir))
+	 (device (if (null-string absolute-dir) ; fix for CMU CL old compiler
+		     (pathname-device rel-dir)
+		   (pathname-device abs-dir)))
+	 (abs-directory (directory-to-list (pathname-directory abs-dir)))
+	 (abs-keyword (when (keywordp (car abs-directory))
+			(pop abs-directory)))
+	 ;; Stig (July 2001):
+	 ;; Somehow CLISP dies on the next line, but NIL is ok.
+	 (abs-name (ignore-errors (file-namestring abs-dir))) ; was pathname-name
+	 (rel-directory (directory-to-list (pathname-directory rel-dir)))
+	 (rel-keyword (when (keywordp (car rel-directory))
+			(pop rel-directory)))
+         #-(or :MCL :sbcl :clisp) (rel-file (file-namestring rel-dir))
+	 ;; Stig (July 2001);
+	 ;; These values seems to help clisp as well
+	 #+(or :MCL :sbcl :clisp) (rel-name (pathname-name rel-dir))
+	 #+(or :MCL :sbcl :clisp) (rel-type (pathname-type rel-dir))
+	 (directory nil))
+
+    ;; TI Common Lisp pathnames can return garbage for file names because
+    ;; of bizarreness in the merging of defaults.  The following code makes
+    ;; sure that the name is a valid name by comparing it with the
+    ;; pathname-name.  It also strips TI specific extensions and handles
+    ;; the necessary case conversion.  TI maps upper back into lower case
+    ;; for unix files!
+    #+TI (if (search (pathname-name abs-dir) abs-name :test #'string-equal)
+	     (setf abs-name (string-right-trim "." (string-upcase abs-name)))
+	     (setf abs-name nil))
+    #+TI (if (search (pathname-name rel-dir) rel-file :test #'string-equal)
+	     (setf rel-file (string-right-trim "." (string-upcase rel-file)))
+	     (setf rel-file nil))
+    ;; Allegro v4.0/4.1 parses "/foo" into :directory '(:absolute :root)
+    ;; and filename "foo". The namestring of a pathname with
+    ;; directory '(:absolute :root "foo") ignores everything after the
+    ;; :root.
+    #+(and allegro-version>= (version>= 4 0))
+    (when (eq (car abs-directory) :root) (pop abs-directory))
+    #+(and allegro-version>= (version>= 4 0))
+    (when (eq (car rel-directory) :root) (pop rel-directory))
+
+    (when (and abs-name (not (null-string abs-name))) ; was abs-name
+      (cond ((and (null abs-directory) (null abs-keyword))
+	     #-(or :lucid :kcl :akcl TI) (setf abs-keyword :relative)
+	     (setf abs-directory (list abs-name)))
+	    (t
+	     (setf abs-directory (append abs-directory (list abs-name))))))
+    (when (and (null abs-directory)
+	       (or (null abs-keyword)
+		   ;; In Lucid, an abs-dir of nil gets a keyword of
+		   ;; :relative since (pathname-directory (pathname ""))
+		   ;; returns (:relative) instead of nil.
+		   #+:lucid (eq abs-keyword :relative))
+	       rel-keyword)
+      ;; The following feature switches seem necessary in CMUCL
+      ;; Marco Antoniotti 19990707
+      #+(or :sbcl :CMU)
+      (if (typep abs-dir 'logical-pathname)
+	  (setf abs-keyword :absolute)
+	  (setf abs-keyword rel-keyword))
+      #-(or :sbcl :CMU)
+      (setf abs-keyword rel-keyword))
+    (setf directory (append abs-directory rel-directory))
+    (when abs-keyword (setf directory (cons abs-keyword directory)))
+    (namestring
+     (make-pathname :host host
+		    :device device
+                    :directory
+                    directory
+		    :name
+		    #-(or :sbcl :MCL :clisp) rel-file
+		    #+(or :sbcl :MCL :clisp) rel-name
+
+		    #+(or :sbcl :MCL :clisp) :type
+		    #+(or :sbcl :MCL :clisp) rel-type
+		    ))))
+
+(defun directory-to-list (directory)
+  ;; The directory should be a list, but nonstandard implementations have
+  ;; been known to use a vector or even a string.
+  (cond ((listp directory)
+	 directory)
+	((stringp directory)
+	 (cond ((find #\; directory)
+		;; It's probably a logical pathname, so split at the
+		;; semicolons:
+		(split-string directory :item #\;))
+               #+MCL
+	       ((and (find #\: directory)
+		     (not (find #\/ directory)))
+		;; It's probably a MCL pathname, so split at the colons.
+		(split-string directory :item #\:))
+	       (t
+		;; It's probably a unix pathname, so split at the slash.
+		(split-string directory :item #\/))))
+	(t
+	 (coerce directory 'list))))
+
+
+(defparameter *append-dirs-tests*
+  '("~/foo/" "baz/bar.lisp"
+     "~/foo" "baz/bar.lisp"
+     "/foo/bar/" "baz/barf.lisp"
+     "/foo/bar/" "/baz/barf.lisp"
+     "foo/bar/" "baz/barf.lisp"
+     "foo/bar" "baz/barf.lisp"
+     "foo/bar" "/baz/barf.lisp"
+     "foo/bar/" "/baz/barf.lisp"
+     "/foo/bar/" nil
+     "foo/bar/" nil
+     "foo/bar" nil
+     "foo" nil
+     "foo" ""
+     nil "baz/barf.lisp"
+     nil "/baz/barf.lisp"
+     nil nil))
+
+(defun test-new-append-directories (&optional (test-dirs *append-dirs-tests*))
+  (do* ((dir-list test-dirs (cddr dir-list))
+	(abs-dir (car dir-list) (car dir-list))
+	(rel-dir (cadr dir-list) (cadr dir-list)))
+      ((null dir-list) (values))
+    (format t "~&ABS: ~S ~18TREL: ~S ~41TResult: ~S"
+	    abs-dir rel-dir (new-append-directories abs-dir rel-dir))))
+
+#||
+<cl> (test-new-append-directories)
+
+ABS: "~/foo/"     REL: "baz/bar.lisp"    Result: "/usr0/mkant/foo/baz/bar.lisp"
+ABS: "~/foo"      REL: "baz/bar.lisp"    Result: "/usr0/mkant/foo/baz/bar.lisp"
+ABS: "/foo/bar/"  REL: "baz/barf.lisp"   Result: "/foo/bar/baz/barf.lisp"
+ABS: "/foo/bar/"  REL: "/baz/barf.lisp"  Result: "/foo/bar/baz/barf.lisp"
+ABS: "foo/bar/"   REL: "baz/barf.lisp"   Result: "foo/bar/baz/barf.lisp"
+ABS: "foo/bar"    REL: "baz/barf.lisp"   Result: "foo/bar/baz/barf.lisp"
+ABS: "foo/bar"    REL: "/baz/barf.lisp"  Result: "foo/bar/baz/barf.lisp"
+ABS: "foo/bar/"   REL: "/baz/barf.lisp"  Result: "foo/bar/baz/barf.lisp"
+ABS: "/foo/bar/"  REL: NIL               Result: "/foo/bar/"
+ABS: "foo/bar/"   REL: NIL               Result: "foo/bar/"
+ABS: "foo/bar"    REL: NIL               Result: "foo/bar/"
+ABS: "foo"        REL: NIL               Result: "foo/"
+ABS: "foo"        REL: ""                Result: "foo/"
+ABS: NIL          REL: "baz/barf.lisp"   Result: "baz/barf.lisp"
+ABS: NIL          REL: "/baz/barf.lisp"  Result: "/baz/barf.lisp"
+ABS: NIL          REL: NIL               Result: ""
+
+||#
+
+
+(defun append-directories (absolute-directory relative-directory)
+  "There is no CL primitive for tacking a subdirectory onto a directory.
+   We need such a function because defsystem has both absolute and
+   relative pathnames in the modules. This is a somewhat ugly hack which
+   seems to work most of the time. We assume that ABSOLUTE-DIRECTORY
+   is a directory, with no filename stuck on the end. Relative-directory,
+   however, may have a filename stuck on the end."
+  (when (or absolute-directory relative-directory)
+    (cond
+     ;; KMR commented out because: when appending two logical pathnames,
+     ;; using this code translates the first logical pathname then appends
+     ;; the second logical pathname -- an error.
+     #|
+      ;; We need a reliable way to determine if a pathname is logical.
+      ;; Allegro 4.1 does not recognize the syntax of a logical pathname
+      ;;  as being logical unless its logical host is already defined.
+
+      #+(or (and allegro-version>= (version>= 4 1))
+	    :logical-pathnames-mk)
+      ((and absolute-directory
+	    (logical-pathname-p absolute-directory)
+	    relative-directory)
+       ;; For use with logical pathnames package.
+       (append-logical-directories-mk absolute-directory relative-directory))
+     |#
+      ((namestring-probably-logical absolute-directory)
+       ;; A simplistic stab at handling logical pathnames
+       (append-logical-pnames absolute-directory relative-directory))
+      (t
+       ;; In VMS, merge-pathnames actually does what we want!!!
+       #+:VMS
+       (namestring (merge-pathnames (or absolute-directory "")
+				    (or relative-directory "")))
+       #+:macl1.3.2
+       (namestring (make-pathname :directory absolute-directory
+				  :name relative-directory))
+       ;; Cross your fingers and pray.
+       #-(or :VMS :macl1.3.2)
+       (new-append-directories absolute-directory relative-directory)))))
+
+#+:logical-pathnames-mk
+(defun append-logical-directories-mk (absolute-dir relative-dir)
+  (lp:append-logical-directories absolute-dir relative-dir))
+
+
+;;; append-logical-pathnames-mk --
+;;; The following is probably still bogus and it does not solve the
+;;; problem of appending two logical pathnames.
+;;; Anyway, as per suggetsion by KMR, the function is not called
+;;; anymore.
+;;; Hopefully this will not cause problems for ACL.
+
+#+(and (and allegro-version>= (version>= 4 1))
+       (not :logical-pathnames-mk))
+(defun append-logical-directories-mk (absolute-dir relative-dir)
+  ;; We know absolute-dir and relative-dir are non nil.  Moreover
+  ;; absolute-dir is a logical pathname.
+  (setq absolute-dir (logical-pathname absolute-dir))
+  (etypecase relative-dir
+    (string (setq relative-dir (parse-namestring relative-dir)))
+    (pathname #| do nothing |#))
+
+  (translate-logical-pathname
+   (merge-pathnames relative-dir absolute-dir)))
+
+#| Old version 2002-03-02
+#+(and (and allegro-version>= (version>= 4 1))
+       (not :logical-pathnames-mk))
+(defun append-logical-directories-mk (absolute-dir relative-dir)
+  ;; We know absolute-dir and relative-dir are non nil.  Moreover
+  ;; absolute-dir is a logical pathname.
+  (setq absolute-dir (logical-pathname absolute-dir))
+  (etypecase relative-dir
+    (string (setq relative-dir (parse-namestring relative-dir)))
+    (pathname #| do nothing |#))
+
+  (translate-logical-pathname
+   (make-pathname
+    :host (or (pathname-host absolute-dir)
+	      (pathname-host relative-dir))
+    :directory (append (pathname-directory absolute-dir)
+		       (cdr (pathname-directory relative-dir)))
+    :name (or (pathname-name absolute-dir)
+	      (pathname-name relative-dir))
+    :type (or (pathname-type absolute-dir)
+	      (pathname-type relative-dir))
+    :version (or (pathname-version absolute-dir)
+		 (pathname-version relative-dir)))))
+
+;; Old version
+#+(and (and allegro-version>= (version>= 4 1))
+       (not :logical-pathnames-mk))
+(defun append-logical-directories-mk (absolute-dir relative-dir)
+  (when (or absolute-dir relative-dir)
+    (setq absolute-dir (logical-pathname (or absolute-dir ""))
+	  relative-dir (logical-pathname (or relative-dir "")))
+    (translate-logical-pathname
+     (make-pathname
+      :host (or (pathname-host absolute-dir)
+		(pathname-host relative-dir))
+      :directory (append (pathname-directory absolute-dir)
+			 (cdr (pathname-directory relative-dir)))
+      :name (or (pathname-name absolute-dir)
+		(pathname-name relative-dir))
+      :type (or (pathname-type absolute-dir)
+		(pathname-type relative-dir))
+      :version (or (pathname-version absolute-dir)
+		   (pathname-version relative-dir))))))
+|#
+
+;;; determines if string or pathname object is logical
+#+:logical-pathnames-mk
+(defun logical-pathname-p (thing)
+  (eq (lp:pathname-host-type thing) :logical))
+
+;;; From Kevin Layer for 4.1final.
+#+(and (and allegro-version>= (version>= 4 1))
+       (not :logical-pathnames-mk))
+(defun logical-pathname-p (thing)
+  (typep (parse-namestring thing) 'logical-pathname))
+
+(defun pathname-logical-p (thing)
+  (typecase thing
+    (logical-pathname t)
+    #+clisp ; CLisp has non conformant Logical Pathnames.
+    (pathname (pathname-logical-p (namestring thing)))
+    (string (and (= 1 (count #\: thing)) ; Shortcut.
+		 (ignore-errors (translate-logical-pathname thing))
+		 t))
+    (t nil)))
+
+;;; This affects only one thing.
+;;; 19990707 Marco Antoniotti
+;;; old version
+
+(defun namestring-probably-logical (namestring)
+  (and (stringp namestring)
+       ;; unix pathnames don't have embedded semicolons
+       (find #\; namestring)))
+#||
+;;; New version
+(defun namestring-probably-logical (namestring)
+  (and (stringp namestring)
+       (typep (parse-namestring namestring) 'logical-pathname)))
+
+
+;;; New new version
+;;; 20000321 Marco Antoniotti
+(defun namestring-probably-logical (namestring)
+  (pathname-logical-p namestring))
+||#
+
+(defun append-logical-pnames (absolute relative)
+  (declare (type (or null string pathname) absolute relative))
+  (let ((abs (if absolute
+		 #-clisp (namestring absolute)
+		 #+clisp absolute ;; Stig (July 2001): hack to avoid CLISP from translating the whole string
+		 ""))
+	(rel (if relative (namestring relative) ""))
+	)
+    ;; Make sure the absolute directory ends with a semicolon unless
+    ;; the pieces are null strings
+    (unless (or (null-string abs) (null-string rel)
+		(char= (char abs (1- (length abs)))
+		       #\;))
+      (setq abs (concatenate 'string abs ";")))
+    ;; Return the concatenate pathnames
+    (concatenate 'string abs rel)))
+
+#||
+;;; This was a try at appending a subdirectory onto a directory.
+;;; It failed. We're keeping this around to prevent future mistakes
+;;; of a similar sort.
+(defun merge-directories (absolute-directory relative-directory)
+  ;; replace concatenate with something more intelligent
+  ;; i.e., concatenation won't work with some directories.
+  ;; it should also behave well if the parent directory
+  ;; has a filename at the end, or if the relative-directory ain't relative
+  (when absolute-directory
+    (setq absolute-directory (pathname-directory absolute-directory)))
+  (concatenate 'string
+	       (or absolute-directory "")
+	       (or relative-directory "")))
+||#
+
+#||
+<cl> (defun d (d n) (namestring (make-pathname :directory d :name n)))
+
+D
+<cl> (d "~/foo/" "baz/bar.lisp")
+"/usr0/mkant/foo/baz/bar.lisp"
+
+<cl> (d "~/foo" "baz/bar.lisp")
+"/usr0/mkant/foo/baz/bar.lisp"
+
+<cl> (d "/foo/bar/" "baz/barf.lisp")
+"/foo/bar/baz/barf.lisp"
+
+<cl> (d "foo/bar/" "baz/barf.lisp")
+"foo/bar/baz/barf.lisp"
+
+<cl> (d "foo/bar" "baz/barf.lisp")
+"foo/bar/baz/barf.lisp"
+
+<cl> (d "foo/bar" "/baz/barf.lisp")
+"foo/bar//baz/barf.lisp"
+
+<cl> (d "foo/bar" nil)
+"foo/bar/"
+
+<cl> (d nil "baz/barf.lisp")
+"baz/barf.lisp"
+
+<cl> (d nil nil)
+""
+
+||#
+
+;;; The following is a change proposed by DTC for SCL.
+;;; Maybe it could be used all the time.
+
+#-scl
+(defun new-file-type (pathname type)
+  ;; why not (make-pathname :type type :defaults pathname)?
+  (make-pathname
+   :host (pathname-host pathname)
+   :device (pathname-device pathname)
+   :directory (pathname-directory pathname)
+   :name (pathname-name pathname)
+   :type type
+   :version (pathname-version pathname)))
+
+
+#+scl
+(defun new-file-type (pathname type)
+  ;; why not (make-pathname :type type :defaults pathname)?
+  (make-pathname
+   :host (pathname-host pathname :case :common)
+   :device (pathname-device pathname :case :common)
+   :directory (pathname-directory pathname :case :common)
+   :name (pathname-name pathname :case :common)
+   :type (string-upcase type)
+   :version (pathname-version pathname :case :common)))
+
+
+
+;;; ********************************
+;;; Component Defstruct ************
+;;; ********************************
+(defvar *source-pathname-default* nil
+  "Default value of :source-pathname keyword in DEFSYSTEM. Set this to
+   \"\" to avoid having to type :source-pathname \"\" all the time.")
+
+(defvar *binary-pathname-default* nil
+  "Default value of :binary-pathname keyword in DEFSYSTEM.")
+
+;;; Removed TIME slot, which has been made unnecessary by the new definition
+;;; of topological-sort.
+
+(defstruct (topological-sort-node (:conc-name topsort-))
+  (color :white :type (member :gray :black :white))
+  ;; time
+  )
+
+(defstruct (component (:include topological-sort-node)
+                      (:print-function print-component))
+  (type :file     ; to pacify the CMUCL compiler (:type is alway supplied)
+	:type (member :defsystem
+		      :system
+		      :subsystem
+		      :module
+		      :file
+		      :private-file
+		      ))
+  (name nil :type (or symbol string))
+  (indent 0 :type (mod 1024))		; Number of characters of indent in
+					; verbose output to the user.
+  host					; The pathname host (i.e., "/../a").
+  device				; The pathname device.
+  source-root-dir			; Relative or absolute (starts
+					; with "/"), directory or file
+					; (ends with "/").
+  (source-pathname *source-pathname-default*)
+  source-extension			; A string, e.g., "lisp"
+					; if NIL, inherit
+  (binary-pathname *binary-pathname-default*)
+  binary-root-dir
+  binary-extension			; A string, e.g., "fasl". If
+					; NIL, uses default for
+					; machine-type.
+  package				; Package for use-package.
+
+  ;; The following three slots are used to provide for alternate compilation
+  ;; and loading functions for the files contained within a component. If
+  ;; a component has a compiler or a loader specified, those functions are
+  ;; used. Otherwise the functions are derived from the language. If no
+  ;; language is specified, it defaults to Common Lisp (:lisp). Other current
+  ;; possible languages include :scheme (PseudoScheme) and :c, but the user
+  ;; can define additional language mappings. Compilation functions should
+  ;; accept a pathname argument and a :output-file keyword; loading functions
+  ;; just a pathname argument. The default functions are #'compile-file and
+  ;; #'load. Unlike fdmm's SET-LANGUAGE macro, this allows a defsystem to
+  ;; mix languages.
+  (language nil :type (or null symbol))
+  (compiler nil :type (or null symbol function))
+  (loader   nil :type (or null symbol function))
+  (compiler-options nil :type list)	; A list of compiler options to
+                                        ; use for compiling this
+                                        ; component.  These must be
+                                        ; keyword options supported by
+                                        ; the compiler.
+
+  (components () :type list)		; A list of components
+					; comprising this component's
+					; definition.
+  (depends-on () :type list)		; A list of the components
+					; this one depends on. may
+					; refer only to the components
+					; at the same level as this
+					; one.
+  proclamations				; Compiler options, such as
+					; '(optimize (safety 3)).
+  initially-do				; Form to evaluate before the
+					; operation.
+  finally-do				; Form to evaluate after the operation.
+  compile-form				; For foreign libraries.
+  load-form				; For foreign libraries.
+
+  ;; load-time				; The file-write-date of the
+					; binary/source file loaded.
+
+  ;; If load-only is T, will not compile the file on operation :compile.
+  ;; In other words, for files which are :load-only T, loading the file
+  ;; satisfies any demand to recompile.
+  load-only				; If T, will not compile this
+					; file on operation :compile.
+  ;; If compile-only is T, will not load the file on operation :compile.
+  ;; Either compiles or loads the file, but not both. In other words,
+  ;; compiling the file satisfies the demand to load it. This is useful
+  ;; for PCL defmethod and defclass definitions, which wrap a
+  ;; (eval-when (compile load eval) ...) around the body of the definition.
+  ;; This saves time in some lisps.
+  compile-only				; If T, will not load this
+					; file on operation :compile.
+  #|| ISI Extension ||#
+  load-always				; If T, will force loading
+					; even if file has not
+					; changed.
+  ;; PVE: add banner
+  (banner nil :type (or null string))
+
+  (documentation nil :type (or null string)) ; Optional documentation slot
+  )
+
+
+;;; To allow dependencies from "foreign systems" like ASDF or one of
+;;; the proprietary ones like ACL or LW.
+
+(defstruct (foreign-system (:include component (type :system)))
+  kind ; This is a keyword: (member :asdf :pcl :lispworks-common-defsystem ...)
+  object ; The actual foreign system object.
+  )
+
+
+(defun register-foreign-system (name &key representation kind)
+  (declare (type (or symbol string) name))
+  (let ((fs (make-foreign-system :name name
+                                 :kind kind
+                                 :object representation)))
+    (setf (get-system name) fs)))
+
+
+
+(define-condition missing-component (simple-condition)
+  ((name :reader missing-component-name
+         :initarg :name)
+   (component :reader missing-component-component
+              :initarg :component)
+   )
+  (:default-initargs :component nil)
+  (:report (lambda (mmc stream)
+	     (format stream "MK:DEFSYSTEM: missing component ~S for ~S."
+                     (missing-component-name mmc)
+                     (missing-component-component mmc))))
+  )
+
+(define-condition missing-module (missing-component)
+  ()
+  (:report (lambda (mmc stream)
+	     (format stream "MK:DEFSYSTEM: missing module ~S for ~S."
+                     (missing-component-name mmc)
+                     (missing-component-component mmc))))
+  )
+
+(define-condition missing-system (missing-module)
+  ()
+  (:report (lambda (msc stream)
+	     (format stream "MK:DEFSYSTEM: missing system ~S~@[ for S~]."
+                     (missing-component-name msc)
+                     (missing-component-component msc))))
+  )
+
+
+
+(defvar *file-load-time-table* (make-hash-table :test #'equal)
+  "Hash table of file-write-dates for the system definitions and
+   files in the system definitions.")
+(defun component-load-time (component)
+  (when component
+    (etypecase component
+      (string    (gethash component *file-load-time-table*))
+      (pathname (gethash (namestring component) *file-load-time-table*))
+      (component
+       (ecase (component-type component)
+	 (:defsystem
+	  (let* ((name (component-name component))
+		 (path (when name (compute-system-path name nil))))
+	    (declare (type (or string pathname null) path))
+	    (when path
+	      (gethash (namestring path) *file-load-time-table*))))
+	 ((:file :private-file)
+	  ;; Use only :source pathname to identify component's
+	  ;; load time.
+	  (let ((path (component-full-pathname component :source)))
+	    (when path
+	      (gethash path *file-load-time-table*)))))))))
+
+#-(or :cmu)
+(defsetf component-load-time (component) (value)
+  `(when ,component
+    (etypecase ,component
+      (string   (setf (gethash ,component *file-load-time-table*) ,value))
+      (pathname (setf (gethash (namestring (the pathname ,component))
+			       *file-load-time-table*)
+		      ,value))
+      (component
+       (ecase (component-type ,component)
+	 (:defsystem
+	  (let* ((name (component-name ,component))
+		 (path (when name (compute-system-path name nil))))
+	    (declare (type (or string pathname null) path))
+	    (when path
+	      (setf (gethash (namestring path) *file-load-time-table*)
+		    ,value))))
+	 ((:file :private-file)
+	  ;; Use only :source pathname to identify file.
+	  (let ((path (component-full-pathname ,component :source)))
+	    (when path
+	      (setf (gethash path *file-load-time-table*)
+		    ,value)))))))
+    ,value))
+
+#+(or :cmu)
+(defun (setf component-load-time) (value component)
+  (declare
+   (type (or null string pathname component) component)
+   (type (or unsigned-byte null) value))
+  (when component
+    (etypecase component
+      (string   (setf (gethash component *file-load-time-table*) value))
+      (pathname (setf (gethash (namestring (the pathname component))
+			       *file-load-time-table*)
+		      value))
+      (component
+       (ecase (component-type component)
+	 (:defsystem
+	     (let* ((name (component-name component))
+		    (path (when name (compute-system-path name nil))))
+	       (declare (type (or string pathname null) path))
+	       (when path
+		 (setf (gethash (namestring path) *file-load-time-table*)
+		       value))))
+	 ((:file :private-file)
+	  ;; Use only :source pathname to identify file.
+	  (let ((path (component-full-pathname component :source)))
+	    (when path
+	      (setf (gethash path *file-load-time-table*)
+		    value)))))))
+    value))
+
+
+;;; compute-system-path --
+
+(defun compute-system-path (module-name definition-pname)
+  (let* ((file-pathname
+	  (make-pathname :name (etypecase module-name
+				 (symbol (string-downcase
+					  (string module-name)))
+				 (string module-name))
+			 :type *system-extension*))
+         (lib-file-pathname
+	  (make-pathname :directory (list :relative module-name)
+                         :name (etypecase module-name
+				 (symbol (string-downcase
+					  (string module-name)))
+				 (string module-name))
+			 :type *system-extension*))
+         )
+    (or (when definition-pname		; given pathname for system def
+	  (probe-file definition-pname))
+	;; Then the central registry. Note that we also check the current
+	;; directory in the registry, but the above check is hard-coded.
+	(cond (*central-registry*
+	       (if (listp *central-registry*)
+		   (dolist (registry *central-registry*)
+		     (let ((file (or (probe-file
+				      (append-directories (if (consp registry)
+							      (eval registry)
+							      registry)
+						          file-pathname))
+                                     (probe-file
+				      (append-directories (if (consp registry)
+							      (eval registry)
+							      registry)
+						          lib-file-pathname))
+                                     ))
+                           )
+		       (when file (return file))))
+		   (or (probe-file (append-directories *central-registry*
+						       file-pathname))
+                       (probe-file (append-directories *central-registry*
+						       lib-file-pathname))
+                       ))
+               )
+	      (t
+	       ;; No central registry. Assume current working directory.
+	       ;; Maybe this should be an error?
+	       (or (probe-file file-pathname)
+                   (probe-file lib-file-pathname)))))
+    ))
+
+
+(defun system-definition-pathname (system-name)
+  (let ((system (ignore-errors (find-system system-name :error))))
+    (if system
+        (let ((system-def-pathname
+               (make-pathname :type "system"
+                              :defaults (pathname (component-full-pathname system :source))))
+              )
+          (values system-def-pathname
+                  (probe-file system-def-pathname)))
+        (values nil nil))))
+         
+         
+
+
+#|
+
+(defun compute-system-path (module-name definition-pname)
+  (let* ((filename (format nil "~A.~A"
+			   (if (symbolp module-name)
+			       (string-downcase (string module-name))
+			     module-name)
+			   *system-extension*)))
+    (or (when definition-pname		; given pathname for system def
+	  (probe-file definition-pname))
+	;; Then the central registry. Note that we also check the current
+	;; directory in the registry, but the above check is hard-coded.
+	(cond (*central-registry*
+	       (if (listp *central-registry*)
+		   (dolist (registry *central-registry*)
+		     (let ((file (probe-file
+				  (append-directories (if (consp registry)
+							  (eval registry)
+							registry)
+						      filename))))
+		       (when file (return file))))
+		 (probe-file (append-directories *central-registry*
+						 filename))))
+	      (t
+	       ;; No central registry. Assume current working directory.
+	       ;; Maybe this should be an error?
+	       (probe-file filename))))))
+|#
+
+
+(defvar *reload-systems-from-disk* t
+  "If T, always tries to reload newer system definitions from disk.
+   Otherwise first tries to find the system definition in the current
+   environment.")
+
+(defun find-system (system-name &optional (mode :ask) definition-pname)
+  "Returns the system named SYSTEM-NAME.
+If not already loaded, loads it, depending on the value of
+*RELOAD-SYSTEMS-FROM-DISK* and of the value of MODE. MODE can be :ASK,
+:ERROR, :LOAD-OR-NIL, or :LOAD. :ASK is the default.
+This allows OPERATE-ON-SYSTEM to work on non-loaded as well as
+loaded system definitions. DEFINITION-PNAME is the pathname for
+the system definition, if provided."
+  (ecase mode
+    (:ask
+     (or (get-system system-name)
+	 (when (y-or-n-p-wait
+		#\y 20
+		"System ~A not loaded. Shall I try loading it? "
+		system-name)
+	   (find-system system-name :load definition-pname))))
+    (:error
+     (or (get-system system-name)
+	 (error 'missing-system :name system-name)))
+    (:load-or-nil
+     (let ((system (get-system system-name)))
+       (or (unless *reload-systems-from-disk* system)
+	   ;; If SYSTEM-NAME is a symbol, it will lowercase the
+	   ;; symbol's string.
+	   ;; If SYSTEM-NAME is a string, it doesn't change the case of the
+	   ;; string. So if case matters in the filename, use strings, not
+	   ;; symbols, wherever the system is named.
+           (when (foreign-system-p system)
+             (warn "Foreign system ~S cannot be reloaded by MK:DEFSYSTEM." system)
+             (return-from find-system nil))
+	   (let ((path (compute-system-path system-name definition-pname)))
+	     (when (and path
+			(or (null system)
+			    (null (component-load-time path))
+			    (< (component-load-time path)
+			       (file-write-date path))))
+	       (tell-user-generic
+		(format nil "Loading system ~A from file ~A"
+			system-name
+			path))
+	       (load path)
+	       (setf system (get-system system-name))
+	       (when system
+		 (setf (component-load-time path)
+		       (file-write-date path))))
+	     system)
+	   system)))
+    (:load
+     (or (unless *reload-systems-from-disk* (get-system system-name))
+         (when (foreign-system-p (get-system system-name))
+           (warn "Foreign system ~S cannot be reloaded by MK:DEFSYSTEM." system-name)
+           (return-from find-system nil))
+	 (or (find-system system-name :load-or-nil definition-pname)
+	     (error "Can't find system named ~s." system-name))))))
+
+
+(defun print-component (component stream depth)
+  (declare (ignore depth))
+  (format stream "#<~:@(~A~): ~A>"
+          (component-type component)
+          (component-name component)))
+
+
+(defun describe-system (name &optional (stream *standard-output*))
+  "Prints a description of the system to the stream. If NAME is the
+   name of a system, gets it and prints a description of the system.
+   If NAME is a component, prints a description of the component."
+  (let ((system (if (typep name 'component) name (find-system name :load))))
+    (format stream "~&~A ~A: ~
+                    ~@[~&   Host: ~A~]~
+                    ~@[~&   Device: ~A~]~
+                    ~@[~&   Package: ~A~]~
+                    ~&   Source: ~@[~A~] ~@[~A~] ~@[~A~]~
+                    ~&   Binary: ~@[~A~] ~@[~A~] ~@[~A~]~
+                    ~@[~&   Depends On: ~A ~]~&   Components: ~{~15T~A~&~}"
+	    (component-type system)
+	    (component-name system)
+	    (component-host system)
+	    (component-device system)
+	    (component-package system)
+	    (component-root-dir system :source)
+	    (component-pathname system :source)
+	    (component-extension system :source)
+	    (component-root-dir system :binary)
+	    (component-pathname system :binary)
+	    (component-extension system :binary)
+	    (component-depends-on system)
+	    (component-components system))
+    #||(when recursive
+      (dolist (component (component-components system))
+	(describe-system component stream recursive)))||#
+    system))
+
+(defun canonicalize-component-name (component)
+  ;; Within the component, the name is a string.
+  (if (typep (component-name component) 'string)
+      ;; Unnecessary to change it, so just return it, same case
+      (component-name component)
+    ;; Otherwise, make it a downcase string -- important since file
+    ;; names are often constructed from component names, and unix
+    ;; prefers lowercase as a default.
+    (setf (component-name component)
+	  (string-downcase (string (component-name component))))))
+
+(defun component-pathname (component type)
+  (when component
+    (ecase type
+      (:source (component-source-pathname component))
+      (:binary (component-binary-pathname component))
+      (:error  (component-error-pathname component)))))
+(defun component-error-pathname (component)
+  (let ((binary (component-pathname component :binary)))
+    (new-file-type binary *compile-error-file-type*)))
+(defsetf component-pathname (component type) (value)
+  `(when ,component
+     (ecase ,type
+       (:source (setf (component-source-pathname ,component) ,value))
+       (:binary (setf (component-binary-pathname ,component) ,value)))))
+
+(defun component-root-dir (component type)
+  (when component
+    (ecase type
+      (:source (component-source-root-dir component))
+      ((:binary :error) (component-binary-root-dir component))
+      )))
+(defsetf component-root-dir (component type) (value)
+  `(when ,component
+     (ecase ,type
+       (:source (setf (component-source-root-dir ,component) ,value))
+       (:binary (setf (component-binary-root-dir ,component) ,value)))))
+
+(defvar *source-pathnames-table* (make-hash-table :test #'equal)
+  "Table which maps from components to full source pathnames.")
+(defvar *binary-pathnames-table* (make-hash-table :test #'equal)
+  "Table which maps from components to full binary pathnames.")
+(defparameter *reset-full-pathname-table* t
+  "If T, clears the full-pathname tables before each call to
+   OPERATE-ON-SYSTEM. Setting this to NIL may yield faster performance
+   after multiple calls to LOAD-SYSTEM and COMPILE-SYSTEM, but could
+   result in changes to system and language definitions to not take
+   effect, and so should be used with caution.")
+(defun clear-full-pathname-tables ()
+  (clrhash *source-pathnames-table*)
+  (clrhash *binary-pathnames-table*))
+
+(defun component-full-pathname (component type &optional (version *version*))
+  (when component
+    (case type
+      (:source
+       (let ((old (gethash component *source-pathnames-table*)))
+	 (or old
+	     (let ((new (component-full-pathname-i component type version)))
+	       (setf (gethash component *source-pathnames-table*) new)
+	       new))))
+      (:binary
+        (let ((old (gethash component *binary-pathnames-table*)))
+	 (or old
+	     (let ((new (component-full-pathname-i component type version)))
+	       (setf (gethash component *binary-pathnames-table*) new)
+	       new))))
+      (otherwise
+       (component-full-pathname-i component type version)))))
+
+(defun component-full-pathname-i (component type &optional (version *version*)
+					    &aux version-dir version-replace)
+  ;; If the pathname-type is :binary and the root pathname is null,
+  ;; distribute the binaries among the sources (= use :source pathname).
+  ;; This assumes that the component's :source pathname has been set
+  ;; before the :binary one.
+  (if version
+      (multiple-value-setq (version-dir version-replace)
+	(translate-version version))
+      (setq version-dir *version-dir* version-replace *version-replace*))
+  (let ((pathname
+	 (append-directories
+	  (if version-replace
+	      version-dir
+	      (append-directories (component-root-dir component type)
+				  version-dir))
+	  (component-pathname component type))))
+
+    ;; When a logical pathname is used, it must first be translated to
+    ;; a physical pathname. This isn't strictly correct. What should happen
+    ;; is we fill in the appropriate slots of the logical pathname, and
+    ;; then return the logical pathname for use by compile-file & friends.
+    ;; But calling translate-logical-pathname to return the actual pathname
+    ;; should do for now.
+
+    ;; (format t "pathname = ~A~%" pathname)
+    ;; (format t "type = ~S~%" (component-extension component type))
+
+    ;; 20000303 Marco Antoniotti
+    ;; Changed the following according to suggestion by Ray Toy.  I
+    ;; just collapsed the tests for "logical-pathname-ness" into a
+    ;; single test (heavy, but probably very portable) and added the
+    ;; :name argument to the MAKE-PATHNAME in the MERGE-PATHNAMES
+    ;; beacuse of possible null names (e.g. :defsystem components)
+    ;; causing problems with the subsequenct call to NAMESTRING.
+    (cond ((pathname-logical-p pathname) ; See definition of test above.
+	   (setf pathname
+		 (merge-pathnames pathname
+				  (make-pathname
+				   :name (component-name component)
+				   :type (component-extension component
+							      type))))
+	   ;;(format t "new path = ~A~%" pathname)
+	   (namestring (translate-logical-pathname pathname)))
+	  (t
+	   (namestring
+	    (make-pathname :host (when (component-host component)
+				   ;; MCL2.0b1 and ACLPC cause an error on
+				   ;; (pathname-host nil)
+				   (pathname-host (component-host component)
+						  #+scl :case #+scl :common
+						  ))
+			   :directory (pathname-directory pathname
+						  #+scl :case #+scl :common
+						  )
+			   ;; Use :directory instead of :defaults
+			   :name (pathname-name pathname
+						  #+scl :case #+scl :common
+						  )
+			   :type #-scl (component-extension component type)
+			         #+scl (string-upcase
+					(component-extension component type))
+			   :device
+			   #+sbcl
+			   :unspecific
+			   #-(or :sbcl)
+			   (let ((dev (component-device component)))
+			     (if dev
+                                 (pathname-device dev
+						  #+scl :case #+scl :common
+						  )
+                                 (pathname-device pathname
+						  #+scl :case #+scl :common
+						  )))
+			   ;; :version :newest
+			   ))))))
+
+;;; What about CMU17 :device :unspecific in the above?
+
+(defun translate-version (version)
+  ;; Value returns the version directory and whether it replaces
+  ;; the entire root (t) or is a subdirectory.
+  ;; Version may be nil to signify no subdirectory,
+  ;; a symbol, such as alpha, beta, omega, :alpha, mark, which
+  ;; specifies a subdirectory of the root, or
+  ;; a string, which replaces the root.
+  (cond ((null version)
+	 (values "" nil))
+	((symbolp version)
+	 (values (let ((sversion (string version)))
+		   (if (find-if #'lower-case-p sversion)
+		       sversion
+		       (string-downcase sversion)))
+		 nil))
+	((stringp version)
+	 (values version t))
+	(t (error "~&; Illegal version ~S" version))))
+
+(defun component-extension (component type &key local)
+  (ecase type
+    (:source (or (component-source-extension component)
+		 (unless local
+		   (default-source-extension component)))) ; system default
+    (:binary (or (component-binary-extension component)
+		 (unless local
+		   (default-binary-extension component)))) ; system default
+    (:error  *compile-error-file-type*)))
+(defsetf component-extension (component type) (value)
+  `(ecase ,type
+     (:source (setf (component-source-extension ,component) ,value))
+     (:binary (setf (component-binary-extension ,component) ,value))
+     (:error  (setf *compile-error-file-type* ,value))))
+
+;;; ********************************
+;;; System Definition **************
+;;; ********************************
+(defun create-component (type name definition-body &optional parent (indent 0))
+  (let ((component (apply #'make-component
+			  :type type
+			  :name name
+			  :indent indent definition-body)))
+    ;; Set up :load-only attribute
+    (unless (find :load-only definition-body)
+      ;; If the :load-only attribute wasn't specified,
+      ;; inherit it from the parent. If no parent, default it to nil.
+      (setf (component-load-only component)
+	    (when parent
+	      (component-load-only parent))))
+    ;; Set up :compile-only attribute
+    (unless (find :compile-only definition-body)
+      ;; If the :compile-only attribute wasn't specified,
+      ;; inherit it from the parent. If no parent, default it to nil.
+      (setf (component-compile-only component)
+	    (when parent
+	      (component-compile-only parent))))
+
+    ;; Set up :compiler-options attribute
+    (unless (find :compiler-options definition-body)
+      ;; If the :compiler-option attribute wasn't specified,
+      ;; inherit it from the parent.  If no parent, default it to NIL.
+      (setf (component-compiler-options component)
+	    (when parent
+	      (component-compiler-options parent))))
+
+    #|| ISI Extension ||#
+    ;; Set up :load-always attribute
+    (unless (find :load-always definition-body)
+      ;; If the :load-always attribute wasn't specified,
+      ;; inherit it from the parent. If no parent, default it to nil.
+      (setf (component-load-always component)
+	    (when parent
+	      (component-load-always parent))))
+
+    ;; Initializations/after makes
+    (canonicalize-component-name component)
+
+    ;; Inherit package from parent if not specified.
+    (setf (component-package component)
+	  (or (component-package component)
+	      (when parent (component-package parent))))
+
+    ;; Type specific setup:
+    (when (or (eq type :defsystem) (eq type :system) (eq type :subsystem))
+      (setf (get-system name) component))
+
+    ;; Set up the component's pathname
+    (create-component-pathnames component parent)
+
+    ;; If there are any components of the component, expand them too.
+    (expand-component-components component (+ indent 2))
+
+    ;; Make depends-on refer to structs instead of names.
+    (link-component-depends-on (component-components component))
+
+    ;; Design Decision: Topologically sort the dependency graph at
+    ;; time of definition instead of at time of use. Probably saves a
+    ;; little bit of time for the user.
+
+    ;; Topological Sort the components at this level.
+    (setf (component-components component)
+          (topological-sort (component-components component)))
+
+    ;; Return the component.
+    component))
+
+
+;;; defsystem --
+;;; The main macro.
+;;;
+;;; 2002-11-22 Marco Antoniotti
+;;; Added code to achieve a first cut "pathname less" operation,
+;;; following the ideas in ASDF.  If the DEFSYSTEM form is loaded from
+;;; a file, then the location of the file (intended as a directory) is
+;;; computed from *LOAD-PATHNAME* and stored as the :SOURCE-PATHNAME
+;;; of the system.
+
+(defmacro defsystem (name &rest definition-body)
+  (unless (find :source-pathname definition-body)
+    (setf definition-body
+	  (list* :source-pathname
+		 '(when *load-pathname*
+		        (make-pathname :name nil
+			               :type nil
+			               :defaults *load-pathname*))
+		 definition-body)))
+  `(create-component :defsystem ',name ',definition-body nil 0))
+
+(defun create-component-pathnames (component parent)
+  ;; Set up language-specific defaults
+  (setf (component-language component)
+	(or (component-language component) ; for local defaulting
+	    (when parent		; parent's default
+	      (component-language parent))))
+  (setf (component-compiler component)
+	(or (component-compiler component) ; for local defaulting
+	    (when parent		; parent's default
+	      (component-compiler parent))))
+  (setf (component-loader component)
+	(or (component-loader component) ; for local defaulting
+	    (when parent		; parent's default
+	      (component-loader parent))))
+
+  ;; Evaluate the root dir arg
+  (setf (component-root-dir component :source)
+	(eval (component-root-dir component :source)))
+  (setf (component-root-dir component :binary)
+	(eval (component-root-dir component :binary)))
+
+  ;; Evaluate the pathname arg
+  (setf (component-pathname component :source)
+	(eval (component-pathname component :source)))
+  (setf (component-pathname component :binary)
+	(eval (component-pathname component :binary)))
+
+  ;; Pass along the host and devices
+  (setf (component-host component)
+	(or (component-host component)
+	    (when parent (component-host parent))))
+  (setf (component-device component)
+	(or (component-device component)
+	    (when parent (component-device parent))))
+
+  ;; Set up extension defaults
+  (setf (component-extension component :source)
+	(or (component-extension component :source :local t) ; local default
+	    (when parent		; parent's default
+	      (component-extension parent :source))))
+  (setf (component-extension component :binary)
+	(or (component-extension component :binary  :local t) ; local default
+	    (when parent		; parent's default
+	      (component-extension parent :binary))))
+
+  ;; Set up pathname defaults -- expand with parent
+  ;; We must set up the source pathname before the binary pathname
+  ;; to allow distribution of binaries among the sources to work.
+  (generate-component-pathname component parent :source)
+  (generate-component-pathname component parent :binary))
+
+;; maybe file's inheriting of pathnames should be moved elsewhere?
+(defun generate-component-pathname (component parent pathname-type)
+  ;; Pieces together a pathname for the component based on its component-type.
+  ;; Assumes source defined first.
+  ;; Null binary pathnames inherit from source instead of the component's
+  ;; name. This allows binaries to be distributed among the source if
+  ;; binary pathnames are not specified. Or if the root directory is
+  ;; specified for binaries, but no module directories, it inherits
+  ;; parallel directory structure.
+  (case (component-type component)
+    ((:defsystem :system)		; Absolute Pathname
+     ;; Set the root-dir to be the absolute pathname
+     (setf (component-root-dir component pathname-type)
+	   (or (component-pathname component pathname-type)
+	       (when (eq pathname-type :binary)
+		 ;; When the binary root is nil, use source.
+		 (component-root-dir component :source))) )
+     ;; Set the relative pathname to be nil
+     (setf (component-pathname component pathname-type)
+	   nil));; should this be "" instead?
+    ;; If the name of the component-pathname is nil, it
+    ;; defaults to the name of the component. Use "" to
+    ;; avoid this defaulting.
+    (:private-file                      ; Absolute Pathname
+     ;; Root-dir is the directory part of the pathname
+     (setf (component-root-dir component pathname-type)
+	   ""
+	   #+ignore(or (when (component-pathname component pathname-type)
+			 (pathname-directory
+			  (component-pathname component pathname-type)))
+		       (when (eq pathname-type :binary)
+			 ;; When the binary root is nil, use source.
+			 (component-root-dir component :source)))
+	   )
+     ;; If *SOURCE-PATHNAME-DEFAULT* or *BINARY-PATHNAME-DEFAULT* is "",
+     ;; then COMPONENT-SOURCE-PATHNAME or COMPONENT-BINARY-PATHNAME could
+     ;; wind up being "", which is wrong for :file components. So replace
+     ;; them with NIL.
+     (when (null-string (component-pathname component pathname-type))
+       (setf (component-pathname component pathname-type) nil))
+     ;; The relative pathname is the name part
+     (setf (component-pathname component pathname-type)
+	   (or (when (and (eq pathname-type :binary)
+			  (null (component-pathname component :binary)))
+		 ;; When the binary-pathname is nil use source.
+		 (component-pathname component :source))
+	       (or (when (component-pathname component pathname-type)
+;		     (pathname-name )
+		     (component-pathname component pathname-type))
+		   (component-name component)))))
+    ((:module :subsystem)			; Pathname relative to parent.
+     ;; Inherit root-dir from parent
+     (setf (component-root-dir component pathname-type)
+	   (component-root-dir parent pathname-type))
+     ;; Tack the relative-dir onto the pathname
+     (setf (component-pathname component pathname-type)
+	   (or (when (and (eq pathname-type :binary)
+			  (null (component-pathname component :binary)))
+		 ;; When the binary-pathname is nil use source.
+		 (component-pathname component :source))
+	       (append-directories
+		(component-pathname parent pathname-type)
+		(or (component-pathname component pathname-type)
+		    (component-name component))))))
+    (:file				; Pathname relative to parent.
+     ;; Inherit root-dir from parent
+     (setf (component-root-dir component pathname-type)
+	   (component-root-dir parent pathname-type))
+     ;; If *SOURCE-PATHNAME-DEFAULT* or *BINARY-PATHNAME-DEFAULT* is "",
+     ;; then COMPONENT-SOURCE-PATHNAME or COMPONENT-BINARY-PATHNAME could
+     ;; wind up being "", which is wrong for :file components. So replace
+     ;; them with NIL.
+     (when (null-string (component-pathname component pathname-type))
+       (setf (component-pathname component pathname-type) nil))
+     ;; Tack the relative-dir onto the pathname
+     (setf (component-pathname component pathname-type)
+	   (or (append-directories
+		(component-pathname parent pathname-type)
+		(or (component-pathname component pathname-type)
+		    (component-name component)
+		    (when (eq pathname-type :binary)
+		      ;; When the binary-pathname is nil use source.
+		      (component-pathname component :source)))))))
+    ))
+
+#|| ;; old version
+(defun expand-component-components (component &optional (indent 0))
+  (let ((definitions (component-components component)))
+    (setf (component-components component)
+	  (remove-if #'null
+		     (mapcar #'(lambda (definition)
+				 (expand-component-definition definition
+							      component
+							      indent))
+			     definitions)))))
+||#
+;; new version
+(defun expand-component-components (component &optional (indent 0))
+  (let ((definitions (component-components component)))
+    (if (eq (car definitions) :serial)
+	(setf (component-components component)
+	      (expand-serial-component-chain (cdr definitions)
+					     component indent))
+	(setf (component-components component)
+	      (expand-component-definitions definitions component indent)))))
+
+(defun expand-component-definitions (definitions parent &optional (indent 0))
+  (let ((components nil))
+    (dolist (definition definitions)
+      (let ((new (expand-component-definition definition parent indent)))
+	(when new (push new components))))
+    (nreverse components)))
+
+(defun expand-serial-component-chain (definitions parent &optional (indent 0))
+  (let ((previous nil)
+	(components nil))
+    (dolist (definition definitions)
+      (let ((new (expand-component-definition definition parent indent)))
+	(when new
+	  ;; Make this component depend on the previous one. Since
+	  ;; we don't know the form of the definition, we have to
+	  ;; expand it first.
+	  (when previous (pushnew previous (component-depends-on new)))
+	  ;; The dependencies will be linked later, so we use the name
+	  ;; instead of the actual component.
+	  (setq previous (component-name new))
+	  ;; Save the new component.
+	  (push new components))))
+    ;; Return the list of expanded components, in appropriate order.
+    (nreverse components)))
+
+
+(defparameter *enable-straz-absolute-string-hack* nil
+  "Special hack requested by Steve Strassman, where the shorthand
+   that specifies a list of components as a list of strings also
+   recognizes absolute pathnames and treats them as files of type
+   :private-file instead of type :file. Defaults to NIL, because I
+   haven't tested this.")
+(defun absolute-file-namestring-p (string)
+  ;; If a FILE namestring starts with a slash, or is a logical pathname
+  ;; as implied by the existence of a colon in the filename, assume it
+  ;; represents an absolute pathname.
+  (or (find #\: string :test #'char=)
+      (and (not (null-string string))
+	   (char= (char string 0) #\/))))
+
+(defun expand-component-definition (definition parent &optional (indent 0))
+  ;; Should do some checking for malformed definitions here.
+  (cond ((null definition) nil)
+        ((stringp definition)
+         ;; Strings are assumed to be of type :file
+	 (if (and *enable-straz-absolute-string-hack*
+		  (absolute-file-namestring-p definition))
+	     ;; Special hack for Straz
+	     (create-component :private-file definition nil parent indent)
+	   ;; Normal behavior
+	   (create-component :file definition nil parent indent)))
+        ((and (listp definition)
+              (not (member (car definition)
+			   '(:defsystem :system :subsystem
+			     :module :file :private-file))))
+         ;; Lists whose first element is not a component type
+         ;; are assumed to be of type :file
+         (create-component :file
+			   (car definition)
+			   (cdr definition)
+			   parent
+			   indent))
+        ((listp definition)
+         ;; Otherwise, it is (we hope) a normal form definition
+         (create-component (car definition)   ; type
+                           (cadr definition)  ; name
+                           (cddr definition)  ; definition body
+                           parent             ; parent
+			   indent)            ; indent
+         )))
+
+(defun link-component-depends-on (components)
+  (dolist (component components)
+    (unless (and *system-dependencies-delayed*
+                 (eq (component-type component) :defsystem))
+      (setf (component-depends-on component)
+            (mapcar #'(lambda (dependency)
+			(let ((parent (find (string dependency) components
+					    :key #'component-name
+					    :test #'string-equal)))
+			  (cond (parent parent)
+				;; make it more intelligent about the following
+				(t (warn "Dependency ~S of component ~S not found."
+					 dependency component)))))
+
+                    (component-depends-on component))))))
+
+;;; ********************************
+;;; Topological Sort the Graph *****
+;;; ********************************
+
+;;; New version of topological sort suggested by rs2. Even though
+;;; this version avoids the call to sort, in practice it isn't faster. It
+;;; does, however, eliminate the need to have a TIME slot in the
+;;; topological-sort-node defstruct.
+(defun topological-sort (list &aux (sorted-list nil))
+  (labels ((dfs-visit (znode)
+	      (setf (topsort-color znode) :gray)
+	      (unless (and *system-dependencies-delayed*
+			   (eq (component-type znode) :system))
+		(dolist (child (component-depends-on znode))
+		  (cond ((eq (topsort-color child) :white)
+			 (dfs-visit child))
+			((eq (topsort-color child) :gray)
+			 (format t "~&Detected cycle containing ~A" child)))))
+	      (setf (topsort-color znode) :black)
+	      (push znode sorted-list)))
+    (dolist (znode list)
+      (setf (topsort-color znode) :white))
+    (dolist (znode list)
+      (when (eq (topsort-color znode) :white)
+        (dfs-visit znode)))
+    (nreverse sorted-list)))
+
+#||
+;;; Older version of topological sort.
+(defun topological-sort (list &aux (time 0))
+  ;; The algorithm works by calling depth-first-search to compute the
+  ;; blackening times for each vertex, and then sorts the vertices into
+  ;; reverse order by blackening time.
+  (labels ((dfs-visit (node)
+	      (setf (topsort-color node) 'gray)
+	      (unless (and *system-dependencies-delayed*
+			   (eq (component-type node) :defsystem))
+		(dolist (child (component-depends-on node))
+		  (cond ((eq (topsort-color child) 'white)
+			 (dfs-visit child))
+			((eq (topsort-color child) 'gray)
+			 (format t "~&Detected cycle containing ~A" child)))))
+		      (setf (topsort-color node) 'black)
+		      (setf (topsort-time node) time)
+		      (incf time)))
+    (dolist (node list)
+      (setf (topsort-color node) 'white))
+    (dolist (node list)
+      (when (eq (topsort-color node) 'white)
+        (dfs-visit node)))
+    (sort list #'< :key #'topsort-time)))
+||#
+
+;;; ********************************
+;;; Output to User *****************
+;;; ********************************
+;;; All output to the user is via the tell-user functions.
+
+(defun split-string (string &key (item #\space) (test #'char=))
+  ;; Splits the string into substrings at spaces.
+  (let ((len (length string))
+	(index 0) result)
+    (dotimes (i len
+		(progn (unless (= index len)
+			 (push (subseq string index) result))
+		       (reverse result)))
+      (when (funcall test (char string i) item)
+	(unless (= index i);; two spaces in a row
+	  (push (subseq string index i) result))
+	(setf index (1+ i))))))
+
+;; probably should remove the ",1" entirely. But AKCL 1.243 dies on it
+;; because of an AKCL bug.
+;; KGK suggests using an 8 instead, but 1 does nicely.
+(defun prompt-string (component)
+  (format nil "; ~:[~;TEST:~]~V,1@T "
+	  *oos-test*
+	  (component-indent component)))
+
+#||
+(defun format-justified-string (prompt contents)
+  (format t (concatenate 'string
+			 "~%"
+			 prompt
+			 "-~{~<~%" prompt " ~1,80:; ~A~>~^~}")
+	  (split-string contents))
+  (finish-output *standard-output*))
+||#
+
+(defun format-justified-string (prompt contents &optional (width 80)
+				       (stream *standard-output*))
+  (let ((prompt-length (+ 2 (length prompt))))
+    (cond ((< (+ prompt-length (length contents)) width)
+	   (format stream "~%~A- ~A" prompt contents))
+	  (t
+	   (format stream "~%~A-" prompt)
+	   (do* ((cursor prompt-length)
+		 (contents (split-string contents) (cdr contents))
+		 (content (car contents) (car contents))
+		 (content-length (1+ (length content)) (1+ (length content))))
+	       ((null contents))
+	     (cond ((< (+ cursor content-length) width)
+		    (incf cursor content-length)
+		    (format stream " ~A" content))
+		   (t
+		    (setf cursor (+ prompt-length content-length))
+		    (format stream "~%~A  ~A" prompt content)))))))
+  (finish-output stream))
+
+(defun tell-user (what component &optional type no-dots force)
+  (when (or *oos-verbose* force)
+    (format-justified-string (prompt-string component)
+     (format nil "~A ~(~A~) ~@[\"~A\"~] ~:[~;...~]"
+	     ;; To have better messages, wrap the following around the
+	     ;; case statement:
+	     ;;(if (find (component-type component)
+	     ;;    '(:defsystem :system :subsystem :module))
+	     ;;  "Checking"
+	     ;;  (case ...))
+	     ;; This gets around the problem of DEFSYSTEM reporting
+	     ;; that it's loading a module, when it eventually never
+	     ;; loads any of the files of the module.
+	     (case what
+	       ((compile :compile)
+		(if (component-load-only component)
+		    ;; If it is :load-only t, we're loading.
+		    "Loading"
+		    ;; Otherwise we're compiling.
+		    "Compiling"))
+	       ((load :load) "Loading")
+	       (otherwise what))
+	     (component-type component)
+	     (or (when type
+		   (component-full-pathname component type))
+		 (component-name component))
+	     (and *tell-user-when-done*
+		  (not no-dots))))))
+
+(defun tell-user-done (component &optional force no-dots)
+  ;; test is no longer really used, but we're leaving it in.
+  (when (and *tell-user-when-done*
+	     (or *oos-verbose* force))
+    (format t "~&~A~:[~;...~] Done."
+	    (prompt-string component) (not no-dots))
+    (finish-output *standard-output*)))
+
+(defmacro with-tell-user ((what component &optional type no-dots force) &body body)
+  `(progn
+     (tell-user ,what ,component ,type ,no-dots ,force)
+     ,@body
+     (tell-user-done ,component ,force ,no-dots)))
+
+(defun tell-user-no-files (component &optional force)
+  (when (or *oos-verbose* force)
+    (format-justified-string (prompt-string component)
+      (format nil "Source file ~A ~
+             ~:[and binary file ~A ~;~]not found, not loading."
+	      (component-full-pathname component :source)
+	      (or *load-source-if-no-binary* *load-source-instead-of-binary*)
+	      (component-full-pathname component :binary)))))
+
+(defun tell-user-require-system (name parent)
+  (when *oos-verbose*
+    (format t "~&; ~:[~;TEST:~] - System ~A requires ~S"
+	    *oos-test* (component-name parent) name)
+    (finish-output *standard-output*)))
+
+(defun tell-user-generic (string)
+  (when *oos-verbose*
+    (format t "~&; ~:[~;TEST:~] - ~A"
+	    *oos-test* string)
+    (finish-output *standard-output*)))
+
+;;; ********************************
+;;; Y-OR-N-P-WAIT ******************
+;;; ********************************
+;;; Y-OR-N-P-WAIT is like Y-OR-N-P, but will timeout after a specified
+;;; number of seconds. I should really replace this with a call to
+;;; the Y-OR-N-P-WAIT defined in the query.cl package and include that
+;;; instead.
+
+(defparameter *use-timeouts* t
+  "If T, timeouts in Y-OR-N-P-WAIT are enabled. Otherwise it behaves
+   like Y-OR-N-P. This is provided for users whose lisps don't handle
+   read-char-no-hang properly.")
+
+(defparameter *clear-input-before-query* t
+  "If T, y-or-n-p-wait will clear the input before printing the prompt
+   and asking the user for input.")
+
+;;; The higher *sleep-amount* is, the less consing, but the lower the
+;;; responsiveness.
+(defparameter *sleep-amount* #-CMU 0.1 #+CMU 1.0
+    "Amount of time to sleep between checking query-io. In multiprocessing
+     Lisps, this allows other processes to continue while we busy-wait. If
+     0, skips call to SLEEP.")
+
+(defun internal-real-time-in-seconds ()
+  (get-universal-time))
+
+(defun read-char-wait (&optional (timeout 20) input-stream
+                                 (eof-error-p t) eof-value
+                                 &aux peek)
+  (do ((start (internal-real-time-in-seconds)))
+      ((or (setq peek (listen input-stream))
+           (< (+ start timeout) (internal-real-time-in-seconds)))
+       (when peek
+         ;; was read-char-no-hang
+         (read-char input-stream eof-error-p eof-value)))
+    (unless (zerop *sleep-amount*)
+      (sleep *sleep-amount*))))
+
+;;; Lots of lisps, especially those that run on top of UNIX, do not get
+;;; their input one character at a time, but a whole line at a time because
+;;; of the buffering done by the UNIX system. This causes y-or-n-p-wait
+;;; to not always work as expected.
+;;;
+;;; I wish lisp did all its own buffering (turning off UNIX input line
+;;; buffering by putting the UNIX into CBREAK mode). Of course, this means
+;;; that we lose input editing, but why can't the lisp implement this?
+
+(defun y-or-n-p-wait (&optional (default #\y) (timeout 20)
+				format-string &rest args)
+  "Y-OR-N-P-WAIT prints the message, if any, and reads characters from
+   *QUERY-IO* until the user enters y, Y or space as an affirmative, or either
+   n or N as a negative answer, or the timeout occurs. It asks again if
+   you enter any other characters."
+  (when *clear-input-before-query* (clear-input *query-io*))
+  (when format-string
+    (fresh-line *query-io*)
+    (apply #'format *query-io* format-string args)
+    ;; FINISH-OUTPUT needed for CMU and other places which don't handle
+    ;; output streams nicely. This prevents it from continuing and
+    ;; reading the query until the prompt has been printed.
+    (finish-output *query-io*))
+  (loop
+   (let* ((read-char (if *use-timeouts*
+			 (read-char-wait timeout *query-io* nil nil)
+			 (read-char *query-io*)))
+	  (char (or read-char default)))
+     ;; We need to ignore #\newline because otherwise the bugs in
+     ;; clear-input will cause y-or-n-p-wait to print the "Type ..."
+     ;; message every time... *sigh*
+     ;; Anyway, we might want to use this to ignore whitespace once
+     ;; clear-input is fixed.
+     (unless (find char '(#\tab #\newline #\return))
+       (when (null read-char)
+	 (format *query-io* "~@[~A~]" default)
+	 (finish-output *query-io*))
+       (cond ((null char) (return t))
+	     ((find char '(#\y #\Y #\space) :test #'char=) (return t))
+	     ((find char '(#\n #\N) :test #'char=) (return nil))
+	     (t
+	      (when *clear-input-before-query* (clear-input *query-io*))
+	      (format *query-io* "~&Type \"y\" for yes or \"n\" for no. ")
+	      (when format-string
+		(fresh-line *query-io*)
+		(apply #'format *query-io* format-string args))
+	      (finish-output *query-io*)))))))
+
+#||
+(y-or-n-p-wait #\y 20 "What? ")
+(progn (format t "~&hi") (finish-output)
+       (y-or-n-p-wait #\y 10 "1? ")
+       (y-or-n-p-wait #\n 10 "2? "))
+||#
+;;; ********************************
+;;; Operate on System **************
+;;; ********************************
+;;; Operate-on-system
+;;; Operation is :compile, 'compile, :load or 'load
+;;; Force is :all or :new-source or :new-source-and-dependents or a list of
+;;; specific modules.
+;;;    :all (or T) forces a recompilation of every file in the system
+;;;    :new-source-and-dependents compiles only those files whose
+;;;          sources have changed or who depend on recompiled files.
+;;;    :new-source compiles only those files whose sources have changed
+;;;    A list of modules means that only those modules and their
+;;;    dependents are recompiled.
+;;; Test is T to print out what it would do without actually doing it.
+;;;      Note: it automatically sets verbose to T if test is T.
+;;; Verbose is T to print out what it is doing (compiling, loading of
+;;;      modules and files) as it does it.
+;;; Dribble should be the pathname of the dribble file if you want to
+;;; dribble the compilation.
+;;; Load-source-instead-of-binary is T to load .lisp instead of binary files.
+;;; Version may be nil to signify no subdirectory,
+;;; a symbol, such as alpha, beta, omega, :alpha, mark, which
+;;; specifies a subdirectory of the root, or
+;;; a string, which replaces the root.
+
+(defun operate-on-system (name operation
+			       &key
+			       force
+			       (version *version*)
+			       (test *oos-test*) (verbose *oos-verbose*)
+                               (load-source-instead-of-binary
+				*load-source-instead-of-binary*)
+                               (load-source-if-no-binary
+				*load-source-if-no-binary*)
+			       (bother-user-if-no-binary
+				*bother-user-if-no-binary*)
+			       (compile-during-load *compile-during-load*)
+			       dribble
+			       (minimal-load *minimal-load*)
+			       (override-compilation-unit t)
+			       )
+  (declare #-(or :cltl2 :ansi-cl) (ignore override-compilation-unit))
+  (unwind-protect
+      ;; Protect the undribble.
+      (#+(or :cltl2 :ansi-cl) with-compilation-unit
+	 #+(or :cltl2 :ansi-cl) (:override override-compilation-unit)
+	 #-(or :cltl2 :ansi-cl) progn
+	(when *reset-full-pathname-table* (clear-full-pathname-tables))
+	(when dribble (dribble dribble))
+	(when test (setq verbose t))
+	(when (null force)		; defaults
+	  (case operation
+	    ((load :load) (setq force :all))
+	    ((compile :compile) (setq force :new-source-and-dependents))
+	    (t (setq force :all))))
+	;; Some CL implementations have a variable called *compile-verbose*
+	;; or *compile-file-verbose*.
+	(multiple-value-bind (*version-dir* *version-replace*)
+	    (translate-version version)
+	  ;; CL implementations may uniformly default this to nil
+	  (let ((*load-verbose* #-common-lisp-controller t
+				#+common-lisp-controller nil) ; nil
+		#-(or MCL CMU CLISP ECL :sbcl lispworks scl)
+		(*compile-file-verbose* t) ; nil
+		#+common-lisp-controller
+		(*compile-print* nil)
+		#+(and common-lisp-controller cmu)
+		(ext:*compile-progress* nil)
+		#+(and common-lisp-controller cmu)
+		(ext:*require-verbose* nil)
+		#+(and common-lisp-controller cmu)
+		(ext:*gc-verbose* nil)
+
+		(*compile-verbose* #-common-lisp-controller t
+				   #+common-lisp-controller nil) ; nil
+		(*version* version)
+		(*oos-verbose* verbose)
+		(*oos-test* test)
+		(*load-source-if-no-binary* load-source-if-no-binary)
+		(*compile-during-load* compile-during-load)
+		(*bother-user-if-no-binary* bother-user-if-no-binary)
+		(*load-source-instead-of-binary* load-source-instead-of-binary)
+		(*minimal-load* minimal-load)
+		(system (if (and (component-p name)
+                                 (member (component-type name) '(:system :defsystem :subsystem)))
+                            name
+                            (find-system name :load))))
+	    #-(or CMU CLISP :sbcl :lispworks :cormanlisp scl)
+	    (declare (special *compile-verbose* #-MCL *compile-file-verbose*)
+		     #-openmcl (ignore *compile-verbose*
+				       #-MCL *compile-file-verbose*)
+		     #-openmcl (optimize (inhibit-warnings 3)))
+	    (unless (component-operation operation)
+	      (error "Operation ~A undefined." operation))
+	    (operate-on-component system operation force))))
+    (when dribble (dribble))))
+
+
+(defun compile-system (name &key force
+			    (version *version*)
+			    (test *oos-test*) (verbose *oos-verbose*)
+			    (load-source-instead-of-binary
+			     *load-source-instead-of-binary*)
+			    (load-source-if-no-binary
+			     *load-source-if-no-binary*)
+			    (bother-user-if-no-binary
+			     *bother-user-if-no-binary*)
+			    (compile-during-load *compile-during-load*)
+			    dribble
+			    (minimal-load *minimal-load*))
+  ;; For users who are confused by OOS.
+  (operate-on-system
+   name :compile
+   :force force
+   :version version
+   :test test
+   :verbose verbose
+   :load-source-instead-of-binary load-source-instead-of-binary
+   :load-source-if-no-binary load-source-if-no-binary
+   :bother-user-if-no-binary bother-user-if-no-binary
+   :compile-during-load compile-during-load
+   :dribble dribble
+   :minimal-load minimal-load))
+
+(defun load-system (name &key force
+			 (version *version*)
+			 (test *oos-test*) (verbose *oos-verbose*)
+			 (load-source-instead-of-binary
+			  *load-source-instead-of-binary*)
+			 (load-source-if-no-binary *load-source-if-no-binary*)
+			 (bother-user-if-no-binary *bother-user-if-no-binary*)
+			 (compile-during-load *compile-during-load*)
+			 dribble
+			 (minimal-load *minimal-load*))
+  ;; For users who are confused by OOS.
+  (operate-on-system
+   name :load
+   :force force
+   :version version
+   :test test
+   :verbose verbose
+   :load-source-instead-of-binary load-source-instead-of-binary
+   :load-source-if-no-binary load-source-if-no-binary
+   :bother-user-if-no-binary bother-user-if-no-binary
+   :compile-during-load compile-during-load
+   :dribble dribble
+   :minimal-load minimal-load))
+
+(defun clean-system (name &key (force :all)
+			 (version *version*)
+			 (test *oos-test*) (verbose *oos-verbose*)
+			 dribble)
+  "Deletes all the binaries in the system."
+  ;; For users who are confused by OOS.
+  (operate-on-system
+   name :delete-binaries
+   :force force
+   :version version
+   :test test
+   :verbose verbose
+   :dribble dribble))
+
+(defun edit-system
+    (name &key force
+	       (version *version*)
+	       (test *oos-test*)
+	       (verbose *oos-verbose*)
+	       dribble)
+
+  (operate-on-system
+   name :edit
+   :force force
+   :version version
+   :test test
+   :verbose verbose
+   :dribble dribble))
+
+(defun hardcopy-system
+    (name &key force
+	       (version *version*)
+	       (test *oos-test*)
+	       (verbose *oos-verbose*)
+	       dribble)
+
+  (operate-on-system
+   name :hardcopy
+   :force force
+   :version version
+   :test test
+   :verbose verbose
+   :dribble dribble))
+
+(defun operate-on-component (component operation force &aux changed)
+  ;; Returns T if something changed and had to be compiled.
+  (let ((type (component-type component))
+	(old-package (package-name *package*)))
+
+    (unwind-protect
+	;; Protect old-package.
+	(progn
+	  ;; Use the correct package.
+	  (when (component-package component)
+	    (tell-user-generic (format nil "Using package ~A"
+				       (component-package component)))
+	    (unless *oos-test*
+	      (unless (find-package (component-package component))
+		;; If the package name is the same as the name of the system,
+		;; and the package is not defined, this would lead to an
+		;; infinite loop, so bomb out with an error.
+		(when (string-equal (string (component-package component))
+				    (component-name component))
+		  (format t "~%Component ~A not loaded:~%"
+			  (component-name component))
+		  (error  "  Package ~A is not defined"
+			  (component-package component)))
+		;; If package not found, try using REQUIRE to load it.
+		(new-require (component-package component)))
+	      ;; This was USE-PACKAGE, but should be IN-PACKAGE.
+	      ;; Actually, CLtL2 lisps define in-package as a macro,
+	      ;; so we'll set the package manually.
+	      ;; (in-package (component-package component))
+	      (let ((package (find-package (component-package component))))
+		(when package
+		  (setf *package* package)))))
+	  #+mk-original
+	  (when (eq type :defsystem)	; maybe :system too?
+	    (operate-on-system-dependencies component operation force))
+	  (when (or (eq type :defsystem) (eq type :system))
+	    (operate-on-system-dependencies component operation force))
+
+	  ;; Do any compiler proclamations
+	  (when (component-proclamations component)
+	    (tell-user-generic (format nil "Doing proclamations for ~A"
+				       (component-name component)))
+	    (or *oos-test*
+		(proclaim (component-proclamations component))))
+
+	  ;; Do any initial actions
+	  (when (component-initially-do component)
+	    (tell-user-generic (format nil "Doing initializations for ~A"
+				       (component-name component)))
+	    (or *oos-test*
+		(eval (component-initially-do component))))
+
+	  ;; If operation is :compile and load-only is T, this would change
+	  ;; the operation to load. Only, this would mean that a module would
+	  ;; be considered to have changed if it was :load-only and had to be
+	  ;; loaded, and then dependents would be recompiled -- this doesn't
+	  ;; seem right. So instead, we propagate the :load-only attribute
+	  ;; to the components, and modify compile-file-operation so that
+	  ;; it won't compile the files (and modify tell-user to say "Loading"
+	  ;; instead of "Compiling" for load-only modules).
+	  #||
+	  (when (and (find operation '(:compile compile))
+		     (component-load-only component))
+	    (setf operation :load))
+	  ||#
+
+	  ;; Do operation and set changed flag if necessary.
+	  (setq changed
+		(case type
+		  ((:file :private-file)
+		   (funcall (component-operation operation) component force))
+		  ((:module :system :subsystem :defsystem)
+		   (operate-on-components component operation force changed))))
+
+	  ;; Do any final actions
+	  (when (component-finally-do component)
+	    (tell-user-generic (format nil "Doing finalizations for ~A"
+				       (component-name component)))
+	    (or *oos-test*
+		(eval (component-finally-do component))))
+
+	  ;; add the banner if needed
+	  #+(or cmu scl)
+	  (when (component-banner component)
+	    (unless (stringp (component-banner component))
+	      (error "The banner should be a string, it is: ~S"
+	             (component-banner component)))
+	    (setf (getf ext:*herald-items*
+			(intern (string-upcase  (component-name component))
+				(find-package :keyword)))
+		  (list
+		     (component-banner component)))))
+
+      ;; Reset the package. (Cleanup form of unwind-protect.)
+      ;;(in-package old-package)
+      (setf *package* (find-package old-package)))
+
+    ;; Provide the loaded system
+    (when (or (eq type :defsystem) (eq type :system) (eq type :subsystem))
+      (tell-user-generic (format nil "Providing system ~A~%"
+				 (component-name component)))
+      (or *oos-test*
+	  (provide (canonicalize-system-name (component-name component))))))
+
+  ;; Return non-NIL if something changed in this component and hence had
+  ;; to be recompiled. This is only used as a boolean.
+  changed)
+
+(defvar *force* nil)
+(defvar *providing-blocks-load-propagation* t
+  "If T, if a system dependency exists on *modules*, it is not loaded.")
+
+(defun operate-on-system-dependencies (component operation &optional force)
+  (when *system-dependencies-delayed*
+    (let ((*force* force))
+      (dolist (system (component-depends-on component))
+	;; For each system that this system depends on, if it is a
+	;; defined system (either via defsystem or component type :system),
+	;; and propagation is turned on, propagates the operation to the
+	;; subsystem. Otherwise runs require (my version) on that system
+	;; to load it (needed since we may be depending on a lisp
+	;; dependent package).
+	;; Explores the system tree in a DFS manner.
+	(cond ((and *operations-propagate-to-subsystems*
+		    (not (listp system))
+		    ;; The subsystem is a defined system.
+		    (find-system system :load-or-nil))
+	       ;; Call OOS on it. Since *system-dependencies-delayed* is
+	       ;; T, the :depends-on slot is filled with the names of
+	       ;; systems, not defstructs.
+	       ;; Aside from system, operation, force, for everything else
+	       ;; we rely on the globals.
+	       (unless (and *providing-blocks-load-propagation*
+			    ;; If *providing-blocks-load-propagation* is T,
+			    ;; the system dependency must not exist in the
+			    ;; *modules* for it to be loaded. Note that
+			    ;; the dependencies are implicitly systems.
+			    (find operation '(load :load))
+			    ;; (or (eq force :all) (eq force t))
+			    (find (canonicalize-system-name system)
+				  *modules* :test #'string-equal))
+                 
+		 (operate-on-system system operation :force force)))
+
+	      ((listp system)
+               ;; If the SYSTEM is a list then its contents are as follows.
+               ;;
+               ;;    (<name> <definition-pathname> <action> <version>)
+               ;;
+	       (tell-user-require-system
+		(cond ((and (null (first system)) (null (second system)))
+		       (third system))
+		      (t system))
+		component)
+	       (or *oos-test* (new-require (first system)
+                                           nil
+					   (eval (second system))
+					   (third system)
+					   (or (fourth system)
+					       *version*))))
+	      (t
+	       (tell-user-require-system system component)
+	       (or *oos-test* (new-require system))))))))
+
+;;; Modules can depend only on siblings. If a module should depend
+;;; on an uncle, then the parent module should depend on that uncle
+;;; instead. Likewise a module should depend on a sibling, not a niece
+;;; or nephew. Modules also cannot depend on cousins. Modules cannot
+;;; depend on parents, since that is circular.
+
+(defun module-depends-on-changed (module changed)
+  (dolist (dependent (component-depends-on module))
+    (when (member dependent changed)
+      (return t))))
+
+(defun operate-on-components (component operation force changed)
+  (with-tell-user (operation component)
+    (if (component-components component)
+	(dolist (module (component-components component))
+	  (when (operate-on-component module operation
+		  (cond ((and (module-depends-on-changed module changed)
+			      #||(some #'(lambda (dependent)
+					(member dependent changed))
+				    (component-depends-on module))||#
+			      (or (non-empty-listp force)
+				  (eq force :new-source-and-dependents)))
+			 ;; The component depends on a changed file
+			 ;; and force agrees.
+			 (if (eq force :new-source-and-dependents)
+			     :new-source-all
+			   :all))
+			((and (non-empty-listp force)
+			      (member (component-name module) force
+				      :test #'string-equal :key #'string))
+			 ;; Force is a list of modules
+			 ;; and the component is one of them.
+			 :all)
+			(t force)))
+	    (push module changed)))
+	(case operation
+	  ((compile :compile)
+	   (eval (component-compile-form component)))
+	  ((load :load)
+	   (eval (component-load-form component))))))
+  ;; This is only used as a boolean.
+  changed)
+
+;;; ********************************
+;;; New Require ********************
+;;; ********************************
+
+;;; This needs cleaning.  Obviously the code is a left over from the
+;;; time people did not know how to use packages in a proper way or
+;;; CLs were shaky in their implementation.
+
+;;; First of all we need this. (Commented out for the time being)
+;;; (shadow '(cl:require))
+
+
+(defvar *old-require* nil)
+
+;;; All calls to require in this file have been replaced with calls
+;;; to new-require to avoid compiler warnings and make this less of
+;;; a tangled mess.
+
+(defun new-require (module-name
+		    &optional
+		    pathname
+		    definition-pname
+		    default-action
+		    (version *version*))
+  ;; If the pathname is present, this behaves like the old require.
+  (unless (and module-name
+	       (find (string module-name)
+		     *modules* :test #'string=))
+    (handler-case
+        (cond (pathname
+	       (funcall *old-require* module-name pathname))
+	      ;; If the system is defined, load it.
+	      ((find-system module-name :load-or-nil definition-pname)
+	       (operate-on-system
+	        module-name :load
+	        :force *force*
+	        :version version
+	        :test *oos-test*
+	        :verbose *oos-verbose*
+	        :load-source-if-no-binary *load-source-if-no-binary*
+	        :bother-user-if-no-binary *bother-user-if-no-binary*
+	        :compile-during-load *compile-during-load*
+	        :load-source-instead-of-binary *load-source-instead-of-binary*
+	        :minimal-load *minimal-load*))
+	      ;; If there's a default action, do it. This could be a progn which
+	      ;; loads a file that does everything.
+	      ((and default-action
+		    (eval default-action)))
+	      ;; If no system definition file, try regular require.
+	      ;; had last arg  PATHNAME, but this wasn't really necessary.
+	      ((funcall *old-require* module-name))
+	      ;; If no default action, print a warning or error message.
+	      (t
+	       #||
+	       (format t "~&Warning: System ~A doesn't seem to be defined..."
+	               module-name)
+	       ||#
+	       (error 'missing-system :name module-name)))
+      (missing-module (mmc) (signal mmc)) ; Resignal.
+      (error (e)
+             (declare (ignore e))
+	     ;; Signal a (maybe wrong) MISSING-SYSTEM.
+	     (error 'missing-system :name module-name)))
+    ))
+
+
+;;; Note that in some lisps, when the compiler sees a REQUIRE form at
+;;; top level it immediately executes it. This is as if an
+;;; (eval-when (compile load eval) ...) were wrapped around the REQUIRE
+;;; form. I don't see any easy way to do this without making REQUIRE
+;;; a macro.
+;;;
+;;; For example, in VAXLisp, if a (require 'streams) form is at the top of
+;;; a file in the system, compiling the system doesn't wind up loading the
+;;; streams module. If the (require 'streams) form is included within an
+;;; (eval-when (compile load eval) ...) then everything is OK.
+;;;
+;;; So perhaps we should replace the redefinition of lisp:require
+;;; with the following macro definition:
+#||
+(unless *old-require*
+  (setf *old-require*
+	(symbol-function #-(or :lispworks
+			       :sbcl
+			       (and :excl :allegro-v4.0)) 'lisp:require
+			 #+:sbcl 'cl:require
+			 #+:lispworks 'system:::require
+			 #+(and :excl :allegro-v4.0) 'cltl1:require))
+
+  (let (#+(or :CCL :openmcl) (ccl:*warn-if-redefine-kernel* nil))
+    ;; Note that lots of lisps barf if we redefine a function from
+    ;; the LISP package. So what we do is define a macro with an
+    ;; unused name, and use (setf macro-function) to redefine
+    ;; lisp:require without compiler warnings. If the lisp doesn't
+    ;; do the right thing, try just replacing require-as-macro
+    ;; with lisp:require.
+    (defmacro require-as-macro (module-name
+				&optional pathname definition-pname
+				default-action (version '*version*))
+      `(eval-when (compile load eval)
+	 (new-require ,module-name ,pathname ,definition-pname
+		      ,default-action ,version)))
+    (setf (macro-function #-(and :excl :sbcl :allegro-v4.0) 'lisp:require
+			  #+:sbcl 'cl:require
+			  #+(and :excl :allegro-v4.0) 'cltl1:require)
+	  (macro-function 'require-as-macro))))
+||#
+;;; This will almost certainly fix the problem, but will cause problems
+;;; if anybody does a funcall on #'require.
+
+;;; Redefine old require to call the new require.
+(eval-when #-(or :lucid) (:load-toplevel :execute)
+	   #+(or :lucid) (load eval)
+(unless *old-require*
+  (setf *old-require*
+	(symbol-function
+	 #-(or (and :excl :allegro-v4.0) :mcl :openmcl :sbcl :lispworks) 'lisp:require
+	 #+(and :excl :allegro-v4.0) 'cltl1:require
+	 #+:sbcl 'cl:require
+	 #+:lispworks3.1 'common-lisp::require
+	 #+(and :lispworks (not :lispworks3.1)) 'system::require
+	 #+:openmcl 'cl:require
+	 #+(and :mcl (not :openmcl)) 'ccl:require
+	 ))
+
+  (unless *dont-redefine-require*
+    (let (#+(or :mcl :openmcl (and :CCL (not :lispworks)))
+	  (ccl:*warn-if-redefine-kernel* nil))
+      #-(or (and allegro-version>= (version>= 4 1)) :lispworks)
+      (setf (symbol-function
+	     #-(or (and :excl :allegro-v4.0) :mcl :openmcl :sbcl :lispworks) 'lisp:require
+	     #+(and :excl :allegro-v4.0) 'cltl1:require
+	     #+:lispworks3.1 'common-lisp::require
+	     #+:sbcl 'cl:require
+	     #+(and :lispworks (not :lispworks3.1)) 'system::require
+	     #+:openmcl 'cl:require
+	     #+(and :mcl (not :openmcl)) 'ccl:require
+	     )
+	    (symbol-function 'new-require))
+      #+:lispworks
+      (let ((warn-packs system::*packages-for-warn-on-redefinition*))
+	(declare (special system::*packages-for-warn-on-redefinition*))
+	(setq system::*packages-for-warn-on-redefinition* nil)
+	(setf (symbol-function
+	       #+:lispworks3.1 'common-lisp::require
+	       #-:lispworks3.1 'system::require
+	       )
+	      (symbol-function 'new-require))
+	(setq system::*packages-for-warn-on-redefinition* warn-packs))
+      #+(and allegro-version>= (version>= 4 1))
+      (excl:without-package-locks
+       (setf (symbol-function 'lisp:require)
+	 (symbol-function 'new-require))))))
+)
+
+;;; ********************************
+;;; Language-Dependent Characteristics
+;;; ********************************
+;;; This section is used for defining language-specific behavior of
+;;; defsystem. If the user changes a language definition, it should
+;;; take effect immediately -- they shouldn't have to reload the
+;;; system definition file for the changes to take effect.
+
+(defvar *language-table* (make-hash-table :test #'equal)
+  "Hash table that maps from languages to language structures.")
+(defun find-language (name)
+  (gethash name *language-table*))
+
+(defstruct (language (:print-function print-language))
+  name			; The name of the language (a keyword)
+  compiler		; The function used to compile files in the language
+  loader		; The function used to load files in the language
+  source-extension	; Filename extensions for source files
+  binary-extension	; Filename extensions for binary files
+)
+
+(defun print-language (language stream depth)
+  (declare (ignore depth))
+  (format stream "#<~:@(~A~): ~A ~A>"
+          (language-name language)
+          (language-source-extension language)
+	  (language-binary-extension language)))
+
+(defun compile-function (component)
+  (or (component-compiler component)
+      (let ((language (find-language (or (component-language component)
+					 :lisp))))
+	(when language (language-compiler language)))
+      #'compile-file))
+
+(defun load-function (component)
+  (or (component-loader component)
+      (let ((language (find-language (or (component-language component)
+					 :lisp))))
+	(when language (language-loader language)))
+      #'load))
+
+(defun default-source-extension (component)
+  (let ((language (find-language (or (component-language component)
+				     :lisp))))
+    (or (when language (language-source-extension language))
+	(car *filename-extensions*))))
+
+(defun default-binary-extension (component)
+  (let ((language (find-language (or (component-language component)
+				     :lisp))))
+    (or (when language (language-binary-extension language))
+	(cdr *filename-extensions*))))
+
+(defmacro define-language (name &key compiler loader
+				source-extension binary-extension)
+  (let ((language (gensym "LANGUAGE")))
+    `(let ((,language (make-language :name ,name
+				     :compiler ,compiler
+				     :loader ,loader
+				     :source-extension ,source-extension
+				     :binary-extension ,binary-extension)))
+       (setf (gethash ,name *language-table*) ,language)
+       ,name)))
+
+#||
+;;; Test System for verifying multi-language capabilities.
+(defsystem foo
+  :language :lisp
+  :components ((:module c :language :c :components ("foo" "bar"))
+	       (:module lisp :components ("baz" "barf"))))
+
+||#
+
+;;; *** Lisp Language Definition
+(define-language :lisp
+  :compiler #'compile-file
+  :loader #'load
+  :source-extension (car *filename-extensions*)
+  :binary-extension (cdr *filename-extensions*))
+
+;;; *** PseudoScheme Language Definition
+(defun scheme-compile-file (filename &rest args)
+  (let ((scheme-package (find-package '#:scheme)))
+    (apply (symbol-function (find-symbol (symbol-name 'compile-file)
+					 scheme-package))
+	   filename
+	   (funcall (symbol-function
+		     (find-symbol (symbol-name '#:interaction-environment)
+				  scheme-package)))
+	   args)))
+
+(define-language :scheme
+  :compiler #'scheme-compile-file
+  :loader #'load
+  :source-extension "scm"
+  :binary-extension "bin")
+
+;;; *** C Language Definition
+
+;;; This is very basic. Somebody else who needs it can add in support
+;;; for header files, libraries, different C compilers, etc. For example,
+;;; we might add a COMPILER-OPTIONS slot to the component defstruct.
+
+(defparameter *c-compiler* "gcc")
+#-(or symbolics (and :lispworks :harlequin-pc-lisp ))
+
+(defun run-unix-program (program arguments)
+  ;; arguments should be a list of strings, where each element is a
+  ;; command-line option to send to the program.
+  #+:lucid (run-program program :arguments arguments)
+  #+:allegro (excl:run-shell-command
+	      (format nil "~A~@[ ~{~A~^ ~}~]"
+		      program arguments))
+  #+(or :kcl :ecl) (system (format nil "~A~@[ ~{~A~^ ~}~]" program arguments))
+  #+(or :cmu :scl) (extensions:run-program program arguments)
+  #+:openmcl (ccl:run-program program arguments)
+  #+:sbcl (sb-ext:run-program program arguments)
+  #+:lispworks (foreign:call-system-showing-output
+		(format nil "~A~@[ ~{~A~^ ~}~]" program arguments))
+  #+clisp (#+lisp=cl ext:run-program #-lisp=cl lisp:run-program
+                     program :arguments arguments)
+  )
+
+#+(or symbolics (and :lispworks :harlequin-pc-lisp))
+(defun run-unix-program (program arguments)
+  (declare (ignore program arguments))
+  (error "MK::RUN-UNIX-PROGRAM: this does not seem to be a UN*X system.")
+  )
+
+#||
+(defun c-compile-file (filename &rest args &key output-file error-file)
+  ;; gcc -c foo.c -o foo.o
+  (declare (ignore args))
+  (run-unix-program *c-compiler*
+		    (format nil "-c ~A~@[ -o ~A~]"
+			    filename
+			    output-file)))
+||#
+
+#||
+(defun c-compile-file (filename &rest args &key output-file error-file)
+  ;; gcc -c foo.c -o foo.o
+  (declare (ignore args error-file))
+  (run-unix-program *c-compiler*
+		    `("-c" ,filename ,@(if output-file `("-o" ,output-file)))))
+||#
+
+
+;;; The following code was inserted to improve C compiler support (at
+;;; least under Linux/GCC).
+;;; Thanks to Espen S Johnsen.
+;;;
+;;; 20001118 Marco Antoniotti.
+
+(defun default-output-pathname (path1 path2 type)
+  (if (eq path1 t)
+      (translate-logical-pathname
+       (merge-pathnames (make-pathname :type type) (pathname path2)))
+      (translate-logical-pathname (pathname path1))))
+
+
+(defun run-compiler (program
+		     arguments
+		     output-file
+		     error-file
+		     error-output
+		     verbose)
+  #-(or cmu scl) (declare (ignore error-file error-output))
+
+  (flet ((make-useable-stream (&rest streams)
+	   (apply #'make-broadcast-stream (delete nil streams)))
+	 )
+    (let (#+(or cmu scl) (error-file error-file)
+	  #+(or cmu scl) (error-file-stream nil)
+	  (verbose-stream nil)
+	  (old-timestamp (file-write-date output-file))
+	  (fatal-error nil)
+	  (output-file-written nil)
+	  )
+      (unwind-protect
+	   (progn
+	     #+(or cmu scl)
+	     (setf error-file
+		   (when error-file
+		     (default-output-pathname error-file
+			                      output-file
+                     		              *compile-error-file-type*))
+
+		   error-file-stream
+		   (and error-file
+			(open error-file
+			      :direction :output
+			      :if-exists :supersede)))
+
+	     (setf verbose-stream
+		   (make-useable-stream
+		    #+cmu error-file-stream
+		    (and verbose *trace-output*)))
+
+	     (format verbose-stream "Running ~A~@[ ~{~A~^ ~}~]~%"
+		     program
+		     arguments)
+
+	     (setf fatal-error
+		   #-(or cmu scl)
+		   (and (run-unix-program program arguments) nil) ; Incomplete.
+		   #+(or cmu scl)
+		   (let* ((error-output
+			   (make-useable-stream error-file-stream
+						(if (eq error-output t)
+						    *error-output*
+						  error-output)))
+			  (process
+			   (ext:run-program program arguments
+					    :error error-output)))
+		     (not (zerop (ext:process-exit-code process)))))
+
+	     (setf output-file-written
+		   (and (probe-file output-file)
+			(not (eql old-timestamp
+				  (file-write-date output-file)))))
+
+
+	     (when output-file-written
+	       (format verbose-stream "~A written~%" output-file))
+	     (format verbose-stream "Running of ~A finished~%"
+		     program)
+	     (values (and output-file-written output-file)
+		     fatal-error
+		     fatal-error))
+
+	#+(or cmu scl)
+	(when error-file
+	  (close error-file-stream)
+	  (unless (or fatal-error (not output-file-written))
+	    (delete-file error-file)))
+
+	(values (and output-file-written output-file)
+		fatal-error
+		fatal-error)))))
+
+
+(defun c-compile-file (filename &rest args
+				&key
+				(output-file t)
+				(error-file t)
+				(error-output t)
+				(verbose *compile-verbose*)
+				debug
+				link
+				optimize
+				cflags
+				definitions
+				include-paths
+				library-paths
+				libraries
+				(error t))
+  (declare (ignore args))
+
+  (flet ((map-options (flag options &optional (func #'identity))
+	   (mapcar #'(lambda (option)
+		       (format nil "~A~A" flag (funcall func option)))
+		   options))
+	 )
+    (let* ((output-file (default-output-pathname output-file filename "o"))
+	   (arguments
+	    `(,@(when (not link) '("-c"))
+	      ,@(when debug '("-g"))
+	      ,@(when optimize (list (format nil "-O~D" optimize)))
+	      ,@cflags
+	      ,@(map-options
+		 "-D" definitions
+		 #'(lambda (definition)
+		     (if (atom definition)
+			 definition
+		       (apply #'format nil "~A=~A" definition))))
+	      ,@(map-options "-I" include-paths #'truename)
+	      ,(namestring (truename filename))
+	      "-o"
+	      ,(namestring (translate-logical-pathname output-file))
+	      ,@(map-options "-L" library-paths #'truename)
+	      ,@(map-options "-l" libraries))))
+
+      (multiple-value-bind (output-file warnings fatal-errors)
+	  (run-compiler *c-compiler*
+			arguments
+			output-file
+			error-file
+			error-output
+			verbose)
+	(if (and error (or (not output-file) fatal-errors))
+	    (error "Compilation failed")
+	    (values output-file warnings fatal-errors))))))
+
+
+(define-language :c
+  :compiler #'c-compile-file
+  :loader #+:lucid #'load-foreign-files
+          #+:allegro #'load
+          #+(or :cmu :scl) #'alien:load-foreign
+          #+:sbcl #'sb-alien:load-foreign
+	  #+(and :lispworks :unix (not :linux)) #'link-load:read-foreign-modules
+	  #+(and :lispworks (or (not :unix) :linux)) #'fli:register-module
+          #+(or :ecl :gcl :kcl) #'load ; should be enough.
+          #-(or :lucid
+		:allegro
+		:cmu
+		:sbcl
+		:scl
+		:lispworks
+		:ecl :gcl :kcl)
+	  (lambda (&rest args)
+	    (declare (ignore args))
+	    (cerror "Continue returning NIL."
+		    "Loader not defined for C foreign libraries in ~A ~A."
+		    (lisp-implementation-type)
+		    (lisp-implementation-version)))
+  :source-extension "c"
+  :binary-extension "o")
+
+#||
+;;; FDMM's changes, which we've replaced.
+(defvar *compile-file-function* #'cl-compile-file)
+
+#+(or :clos :pcl)
+(defmethod set-language ((lang (eql :common-lisp)))
+  (setq *compile-file-function* #'cl-compile-file))
+
+#+(or :clos :pcl)
+(defmethod set-language ((lang (eql :scheme)))
+  (setq *compile-file-function #'scheme-compile-file))
+||#
+
+;;; ********************************
+;;; Component Operations ***********
+;;; ********************************
+;;; Define :compile/compile and :load/load operations
+(eval-when (load eval)
+(component-operation :compile  'compile-and-load-operation)
+(component-operation 'compile  'compile-and-load-operation)
+(component-operation :load     'load-file-operation)
+(component-operation 'load     'load-file-operation)
+)
+
+(defun compile-and-load-operation (component force)
+  ;; FORCE was CHANGED. this caused defsystem during compilation to only
+  ;; load files that it immediately compiled.
+  (let ((changed (compile-file-operation component force)))
+    ;; Return T if the file had to be recompiled and reloaded.
+    (if (and changed (component-compile-only component))
+	;; For files which are :compile-only T, compiling the file
+	;; satisfies the need to load.
+	changed
+	;; If the file wasn't compiled, or :compile-only is nil,
+	;; check to see if it needs to be loaded.
+	(and (load-file-operation component force) ; FORCE was CHANGED ???
+	     changed))))
+
+(defun unmunge-lucid (namestring)
+  ;; Lucid's implementation of COMPILE-FILE is non-standard, in that
+  ;; when the :output-file is a relative pathname, it tries to munge
+  ;; it with the directory of the source file. For example,
+  ;; (compile-file "src/globals.lisp" :output-file "bin/globals.sbin")
+  ;; tries to stick the file in "./src/bin/globals.sbin" instead of
+  ;; "./bin/globals.sbin" like any normal lisp. This hack seems to fix the
+  ;; problem. I wouldn't have expected this problem to occur with any
+  ;; use of defsystem, but some defsystem users are depending on
+  ;; using relative pathnames (at least three folks reported the problem).
+  (cond ((null-string namestring) namestring)
+	((char= (char namestring 0) #\/)
+	 ;; It's an absolute namestring
+	 namestring)
+	(t
+	 ;; Ugly, but seems to fix the problem.
+	 (concatenate 'string "./" namestring))))
+
+(defun compile-file-operation (component force)
+  ;; Returns T if the file had to be compiled.
+  (let ((must-compile
+	 ;; For files which are :load-only T, loading the file
+	 ;; satisfies the demand to recompile.
+	 (and (null (component-load-only component)) ; not load-only
+	      (or (find force '(:all :new-source-all t) :test #'eq)
+		  (and (find force '(:new-source :new-source-and-dependents)
+			     :test #'eq)
+		       (needs-compilation component)))))
+	(source-pname (component-full-pathname component :source)))
+
+    (cond ((and must-compile (probe-file source-pname))
+	   (with-tell-user ("Compiling source" component :source)
+	     (let ((output-file
+		    #+:lucid
+		     (unmunge-lucid (component-full-pathname component
+							     :binary))
+		     #-:lucid
+		     (component-full-pathname component :binary)))
+
+	       ;; make certain the directory we need to write to
+	       ;; exists [pvaneynd@debian.org 20001114]
+	       ;; Added PATHNAME-HOST following suggestion by John
+	       ;; DeSoi [marcoxa@sourceforge.net 20020529]
+
+	       (ensure-directories-exist
+		(make-pathname
+		 :host (pathname-host output-file)
+		 :directory (pathname-directory output-file)))
+
+	       (or *oos-test*
+		   (apply (compile-function component)
+			  source-pname
+			  :output-file
+			  output-file
+			  #+(or :cmu :scl) :error-file
+			  #+(or :cmu :scl) (and *cmu-errors-to-file*
+						(component-full-pathname component
+									 :error))
+			  #+CMU
+			  :error-output
+			  #+CMU
+			  *cmu-errors-to-terminal*
+			  (component-compiler-options component)
+			  ))))
+	   must-compile)
+	  (must-compile
+	   (tell-user "Source file not found. Not compiling"
+		      component :source :no-dots :force)
+	   nil)
+	  (t nil))))
+
+(defun needs-compilation (component)
+  ;; If there is no binary, or it is older than the source
+  ;; file, then the component needs to be compiled.
+  ;; Otherwise we only need to recompile if it depends on a file that changed.
+  (let ((source-pname (component-full-pathname component :source))
+	(binary-pname (component-full-pathname component :binary)))
+    (and
+     ;; source must exist
+     (probe-file source-pname)
+     (or
+      ;; no binary
+      (null (probe-file binary-pname))
+      ;; old binary
+      (< (file-write-date binary-pname)
+	 (file-write-date source-pname))))))
+
+(defun needs-loading (component &optional (check-source t) (check-binary t))
+  ;; Compares the component's load-time against the file-write-date of
+  ;; the files on disk.
+  (let ((load-time (component-load-time component))
+	(source-pname (component-full-pathname component :source))
+	(binary-pname (component-full-pathname component :binary)))
+    (or
+     #|| ISI Extension ||#
+     (component-load-always component)
+
+     ;; File never loaded.
+     (null load-time)
+     ;; Binary is newer.
+     (when (and check-binary
+		(probe-file binary-pname))
+       (< load-time
+	  (file-write-date binary-pname)))
+     ;; Source is newer.
+     (when (and check-source
+		(probe-file source-pname))
+       (< load-time
+	  (file-write-date source-pname))))))
+
+;;; Need to completely rework this function...
+(defun load-file-operation (component force)
+  ;; Returns T if the file had to be loaded
+  (let* ((binary-pname (component-full-pathname component :binary))
+	 (source-pname (component-full-pathname component :source))
+	 (binary-exists (probe-file binary-pname))
+	 (source-exists (probe-file source-pname))
+	 (source-needs-loading (needs-loading component t nil))
+	 (binary-needs-loading (needs-loading component nil t))
+	 ;; needs-compilation has an implicit source-exists in it.
+	 (needs-compilation (if (component-load-only component)
+				source-needs-loading
+				(needs-compilation component)))
+	 (check-for-new-source
+	  ;; If force is :new-source*, we're checking for files
+	  ;; whose source is newer than the compiled versions.
+	  (find force '(:new-source :new-source-and-dependents :new-source-all)
+		:test #'eq))
+	 (load-binary (or (find force '(:all :new-source-all t) :test #'eq)
+			  binary-needs-loading))
+	 (load-source
+	  (or *load-source-instead-of-binary*
+	      (and load-binary (component-load-only component))
+	      (and check-for-new-source needs-compilation)))
+	 (compile-and-load
+	  (and needs-compilation (or load-binary check-for-new-source)
+	       (compile-and-load-source-if-no-binary component))))
+    ;; When we're trying to minimize the files loaded to only those
+    ;; that need be, restrict the values of load-source and load-binary
+    ;; so that we only load the component if the files are newer than
+    ;; the load-time.
+    (when *minimal-load*
+      (when load-source (setf load-source source-needs-loading))
+      (when load-binary (setf load-binary binary-needs-loading)))
+
+    (when (or load-source load-binary compile-and-load)
+      (cond (compile-and-load
+	     ;; If we're loading the binary and it is old or nonexistent,
+	     ;; and the user says yes, compile and load the source.
+	     (compile-file-operation component t)
+	     (with-tell-user ("Loading binary"   component :binary)
+	       (or *oos-test*
+		   (progn
+		     (funcall (load-function component) binary-pname)
+		     (setf (component-load-time component)
+			   (file-write-date binary-pname)))))
+	     t)
+	    ((and source-exists
+		  (or (and load-source	; implicit needs-comp...
+			   (or *load-source-instead-of-binary*
+			       (component-load-only component)
+			       (not *compile-during-load*)))
+		      (and load-binary (not binary-exists)
+			   (load-source-if-no-binary component))))
+	     ;; Load the source if the source exists and:
+	     ;;   o  we're loading binary and it doesn't exist
+	     ;;   o  we're forcing it
+	     ;;   o  we're loading new source and user wasn't asked to compile
+	     (with-tell-user ("Loading source" component :source)
+	       (or *oos-test*
+		   (progn
+		     (funcall (load-function component) source-pname)
+		     (setf (component-load-time component)
+			   (file-write-date source-pname)))))
+	     t)
+	    ((and binary-exists load-binary)
+	     (with-tell-user ("Loading binary"   component :binary)
+	       (or *oos-test*
+		   (progn
+		     (funcall (load-function component) binary-pname)
+		     (setf (component-load-time component)
+			   (file-write-date binary-pname)))))
+	     t)
+	    ((and (not binary-exists) (not source-exists))
+	     (tell-user-no-files component :force)
+	     (when *files-missing-is-an-error*
+	       (cerror "Continue, ignoring missing files."
+		       "~&Source file ~S ~:[and binary file ~S ~;~]do not exist."
+		       source-pname
+		       (or *load-source-if-no-binary*
+			   *load-source-instead-of-binary*)
+		       binary-pname))
+	     nil)
+	    (t
+	     nil)))))
+
+(eval-when (load eval)
+(component-operation :clean    'delete-binaries-operation)
+(component-operation 'clean    'delete-binaries-operation)
+(component-operation :delete-binaries     'delete-binaries-operation)
+(component-operation 'delete-binaries     'delete-binaries-operation)
+)
+(defun delete-binaries-operation (component force)
+  (when (or (eq force :all)
+	    (eq force t)
+	    (and (find force '(:new-source :new-source-and-dependents
+					   :new-source-all)
+		       :test #'eq)
+		 (needs-compilation component)))
+    (let ((binary-pname (component-full-pathname component :binary)))
+      (when (probe-file binary-pname)
+	(with-tell-user ("Deleting binary"   component :binary)
+			(or *oos-test*
+			    (delete-file binary-pname)))))))
+
+
+;; when the operation = :compile, we can assume the binary exists in test mode.
+;;	((and *oos-test*
+;;	      (eq operation :compile)
+;;	      (probe-file (component-full-pathname component :source)))
+;;	 (with-tell-user ("Loading binary"   component :binary)))
+
+(defun binary-exists (component)
+  (probe-file (component-full-pathname component :binary)))
+
+;;; or old-binary
+(defun compile-and-load-source-if-no-binary (component)
+  (when (not (or *load-source-instead-of-binary*
+		 (and *load-source-if-no-binary*
+		      (not (binary-exists component)))))
+    (cond ((component-load-only component)
+	   #||
+	   (let ((prompt (prompt-string component)))
+	     (format t "~A- File ~A is load-only, ~
+                        ~&~A  not compiling."
+		     prompt
+		     (component-full-pathname component :source)
+		     prompt))
+	   ||#
+	   nil)
+	  ((eq *compile-during-load* :query)
+	   (let* ((prompt (prompt-string component))
+		  (compile-source
+		   (y-or-n-p-wait
+		    #\y 30
+		    "~A- Binary file ~A is old or does not exist. ~
+                     ~&~A  Compile (and load) source file ~A instead? "
+		    prompt
+		    (component-full-pathname component :binary)
+		    prompt
+		    (component-full-pathname component :source))))
+	     (unless (y-or-n-p-wait
+		      #\y 30
+		      "~A- Should I bother you if this happens again? "
+		      prompt)
+	       (setq *compile-during-load*
+		     (y-or-n-p-wait
+		      #\y 30
+		      "~A- Should I compile and load or not? "
+		      prompt)))		; was compile-source, then t
+	     compile-source))
+	  (*compile-during-load*)
+	  (t nil))))
+
+(defun load-source-if-no-binary (component)
+  (and (not *load-source-instead-of-binary*)
+       (or (and *load-source-if-no-binary*
+		(not (binary-exists component)))
+	   (component-load-only component)
+	   (when *bother-user-if-no-binary*
+	     (let* ((prompt (prompt-string component))
+		    (load-source
+		     (y-or-n-p-wait #\y 30
+		      "~A- Binary file ~A does not exist. ~
+                       ~&~A  Load source file ~A instead? "
+		      prompt
+		      (component-full-pathname component :binary)
+		      prompt
+		      (component-full-pathname component :source))))
+	       (setq *bother-user-if-no-binary*
+		     (y-or-n-p-wait #\n 30
+		      "~A- Should I bother you if this happens again? "
+		      prompt ))
+	       (unless *bother-user-if-no-binary*
+		 (setq *load-source-if-no-binary* load-source))
+	       load-source)))))
+
+;;; ********************************
+;;; Allegro Toplevel Commands ******
+;;; ********************************
+;;; Creates toplevel command aliases for Allegro CL.
+#+:allegro
+(top-level:alias ("compile-system" 8)
+  (system &key force (minimal-load mk:*minimal-load*)
+	  test verbose version)
+  "Compile the specified system"
+
+  (mk:compile-system system :force force
+		     :minimal-load minimal-load
+		     :test test :verbose verbose
+		     :version version))
+
+#+:allegro
+(top-level:alias ("load-system" 5)
+  (system &key force (minimal-load mk:*minimal-load*)
+	  (compile-during-load mk:*compile-during-load*)
+	  test verbose version)
+  "Compile the specified system"
+
+  (mk:load-system system :force force
+		  :minimal-load minimal-load
+		  :compile-during-load compile-during-load
+		  :test test :verbose verbose
+		  :version version))
+
+#+:allegro
+(top-level:alias ("show-system" 5) (system)
+  "Show information about the specified system."
+
+  (mk:describe-system system))
+
+#+:allegro
+(top-level:alias ("describe-system" 9) (system)
+  "Show information about the specified system."
+
+  (mk:describe-system system))
+
+#+:allegro
+(top-level:alias ("system-source-size" 9) (system)
+  "Show size information about source files in the specified system."
+
+  (mk:system-source-size system))
+
+#+:allegro
+(top-level:alias ("clean-system" 6)
+  (system &key force test verbose version)
+  "Delete binaries in the specified system."
+
+  (mk:clean-system system :force force
+		   :test test :verbose verbose
+		   :version version))
+
+#+:allegro
+(top-level:alias ("edit-system" 7)
+  (system &key force test verbose version)
+  "Load system source files into Emacs."
+
+  (mk:edit-system system :force force
+		  :test test :verbose verbose
+		  :version version))
+
+#+:allegro
+(top-level:alias ("hardcopy-system" 9)
+  (system &key force test verbose version)
+  "Hardcopy files in the specified system."
+
+  (mk:hardcopy-system system :force force
+		      :test test :verbose verbose
+		      :version version))
+
+#+:allegro
+(top-level:alias ("make-system-tag-table" 13) (system)
+  "Make an Emacs TAGS file for source files in specified system."
+
+  (mk:make-system-tag-table system))
+
+
+;;; ********************************
+;;; Allegro Make System Fasl *******
+;;; ********************************
+#+:excl
+(defun allegro-make-system-fasl (system destination
+					&optional (include-dependents t))
+  (excl:shell
+   (format nil "rm -f ~A; cat~{ ~A~} > ~A"
+	   destination
+	   (if include-dependents
+	       (files-in-system-and-dependents system :all :binary)
+	       (files-in-system system :all :binary))
+	   destination)))
+
+(defun files-which-need-compilation (system)
+  (mapcar #'(lambda (comp) (component-full-pathname comp :source))
+	  (remove nil
+		  (file-components-in-component
+		   (find-system system :load) :new-source))))
+
+(defun files-in-system-and-dependents (name &optional (force :all)
+					    (type :source) version)
+  ;; Returns a list of the pathnames in system and dependents in load order.
+  (let ((system (find-system name :load)))
+    (multiple-value-bind (*version-dir* *version-replace*)
+	(translate-version version)
+      (let ((*version* version))
+	(let ((result (file-pathnames-in-component system type force)))
+	  (dolist (dependent (reverse (component-depends-on system)))
+	    (setq result
+		  (append (files-in-system-and-dependents dependent
+							  force type version)
+			  result)))
+	  result)))))
+
+(defun files-in-system (name &optional (force :all) (type :source) version)
+  ;; Returns a list of the pathnames in system in load order.
+  (let ((system (if (and (component-p name)
+                         (member (component-type name) '(:defsystem :system :subsystem)))
+                    name
+                    (find-system name :load))))
+    (multiple-value-bind (*version-dir* *version-replace*)
+	(translate-version version)
+      (let ((*version* version))
+	(file-pathnames-in-component system type force)))))
+
+(defun file-pathnames-in-component (component type &optional (force :all))
+  (mapcar #'(lambda (comp) (component-full-pathname comp type))
+	  (file-components-in-component component force)))
+
+(defun file-components-in-component (component &optional (force :all)
+					       &aux result changed)
+  (case (component-type component)
+    ((:file :private-file)
+     (when (setq changed
+		 (or (find force '(:all t) :test #'eq)
+		     (and (not (non-empty-listp force))
+			  (needs-compilation component))))
+       (setq result
+	     (list component))))
+    ((:module :system :subsystem :defsystem)
+     (dolist (module (component-components component))
+       (multiple-value-bind (r c)
+	   (file-components-in-component
+	    module
+	    (cond ((and (some #'(lambda (dependent)
+				  (member dependent changed))
+			      (component-depends-on module))
+			(or (non-empty-listp force)
+			    (eq force :new-source-and-dependents)))
+		   ;; The component depends on a changed file and force agrees.
+		   :all)
+		  ((and (non-empty-listp force)
+			(member (component-name module) force
+				:test #'string-equal :key #'string))
+		   ;; Force is a list of modules and the component is
+		   ;; one of them.
+		   :all)
+		  (t force)))
+	 (when c
+	   (push module changed)
+	   (setq result (append result r)))))))
+  (values result changed))
+
+(setf (symbol-function 'oos) (symbol-function 'operate-on-system))
+
+;;; ********************************
+;;; Additional Component Operations
+;;; ********************************
+
+;;; *** Edit Operation ***
+
+;;; Should this conditionalization be (or :mcl (and :CCL (not :lispworks)))?
+#|
+#+:ccl
+(defun edit-operation (component force)
+  "Always returns nil, i.e. component not changed."
+  (declare (ignore force))
+  ;;
+  (let* ((full-pathname (make::component-full-pathname component :source))
+         (already-editing\? #+:mcl (dolist (w (CCL:windows :class
+							   'fred-window))
+                                    (when (equal (CCL:window-filename w)
+                                                 full-pathname)
+                                      (return w)))
+                           #-:mcl nil))
+    (if already-editing\?
+      #+:mcl (CCL:window-select already-editing\?) #-:mcl nil
+      (ed full-pathname)))
+  nil)
+
+#+:allegro
+(defun edit-operation (component force)
+  "Edit a component - always returns nil, i.e. component not changed."
+  (declare (ignore force))
+  (let ((full-pathname (component-full-pathname component :source)))
+    (ed full-pathname))
+  nil)
+
+#+(or :ccl :allegro)
+(make::component-operation :edit 'edit-operation)
+#+(or :ccl :allegro)
+(make::component-operation 'edit 'edit-operation)
+|#
+
+;;; *** Hardcopy System ***
+(defparameter *print-command* "enscript -2Gr" ; "lpr"
+  "Command to use for printing files on UNIX systems.")
+#+:allegro
+(defun hardcopy-operation (component force)
+  "Hardcopy a component - always returns nil, i.e. component not changed."
+  (declare (ignore force))
+  (let ((full-pathname (component-full-pathname component :source)))
+    (excl:run-shell-command (format nil "~A ~A"
+				    *print-command* full-pathname)))
+  nil)
+
+#+:allegro
+(make::component-operation :hardcopy 'hardcopy-operation)
+#+:allegro
+(make::component-operation 'hardcopy 'hardcopy-operation)
+
+
+;;; *** System Source Size ***
+
+(defun system-source-size (system-name &optional (force :all))
+  "Prints a short report and returns the size in bytes of the source files in
+   <system-name>."
+  (let* ((file-list (files-in-system system-name force :source))
+         (total-size (file-list-size file-list)))
+    (format t "~&~a/~a (~:d file~:p) totals ~:d byte~:p (~:d kB)"
+            system-name force (length file-list)
+            total-size (round total-size 1024))
+    total-size))
+
+(defun file-list-size (file-list)
+  "Returns the size in bytes of the files in <file-list>."
+  ;;
+  (let ((total-size 0))
+    (dolist (file file-list)
+      (with-open-file (stream file)
+        (incf total-size (file-length stream))))
+    total-size))
+
+;;; *** System Tag Table ***
+
+#+:allegro
+(defun make-system-tag-table (system-name)
+  "Makes an Emacs tag table using the GNU etags program."
+  (let ((files-in-system (files-in-system system-name :all :source)))
+
+    (format t "~&Making tag table...")
+    (excl:run-shell-command (format nil "etags ~{~a ~}" files-in-system))
+    (format t "done.~%")))
+
+
+;;; end of file -- defsystem.lisp --
Index: /branches/new-random/xdump/.cvsignore
===================================================================
--- /branches/new-random/xdump/.cvsignore	(revision 13309)
+++ /branches/new-random/xdump/.cvsignore	(revision 13309)
@@ -0,0 +1,2 @@
+*.*fsl
+*~.*
Index: /branches/new-random/xdump/faslenv.lisp
===================================================================
--- /branches/new-random/xdump/faslenv.lisp	(revision 13309)
+++ /branches/new-random/xdump/faslenv.lisp	(revision 13309)
@@ -0,0 +1,150 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+
+(in-package "CCL")
+
+;; Compile-time environment for fasl dumper/loader.
+
+; loader state istruct
+(def-accessors (faslstate) %svref
+  ()
+  faslstate.faslfname
+  faslstate.faslevec
+  faslstate.faslecnt
+  faslstate.faslfd
+  faslstate.faslval
+  faslstate.faslstr
+  faslstate.oldfaslstr
+  faslstate.faslerr
+  faslstate.iobuffer
+  faslstate.bufcount
+  faslstate.faslversion
+  faslstate.faslepush
+  faslstate.faslgsymbols
+  faslstate.fasldispatch)
+
+
+(defconstant numfaslops 80 "Number of fasl file opcodes, roughly")
+(defconstant $fasl-epush-bit 7)
+(defconstant $fasl-file-id #xff00)
+(defconstant $fasl-file-id1 #xff01)
+(defconstant $fasl-vers #x5e)
+(defconstant $fasl-min-vers #x5e)
+(defconstant $faslend #xff)
+(defconstant $fasl-buf-len 2048)
+(defmacro deffaslop (n arglist &body body)
+  `(setf (svref *fasl-dispatch-table* ,n)
+         (nfunction ,n (lambda ,arglist ,@body))))
+
+
+(defconstant $fasl-noop 0)              ;<nada:zilch>.  
+(defconstant $fasl-s32-vector 1)        ;<count> Make a (SIMPLE-ARRAY (SIGNED-BYTE 32) <count>)
+(defconstant $fasl-code-vector 2)       ;<count> words of code
+(defconstant $fasl-clfun 3)             ;<size:count><codesize:count>code,size-codesize exprs
+(defconstant $fasl-lfuncall 4)          ;<lfun:expr> funcall the lfun.
+(defconstant $fasl-globals 5)           ;<expr> global symbols vector
+(defconstant $fasl-char 6)              ;<char:byte> Make a char
+(defconstant $fasl-fixnum 7)            ;<value:long> Make a (4-byte) fixnum
+(defconstant $fasl-dfloat 8)            ;<hi:long><lo:long> Make a DOUBLE-FLOAT
+(defconstant $fasl-bignum32 9)          ;<count> make a bignum with count digits
+(defconstant $fasl-word-fixnum 10)      ;<value:word> Make a fixnum
+(defconstant $fasl-double-float-vector 11) ;<count> make a (SIMPLE-ARRAY DOUBLE-FLOAT <count>)
+(defconstant $fasl-single-float-vector 12) ;<count> make a (SIMPLE-ARRAY SINGLE-FLOAT <count>)
+(defconstant $fasl-bit-vector 13)       ;<count> make a (SIMPLE-ARRAY BIT <count>)
+(defconstant $fasl-u8-vector 14)        ;<count> make a (SIMPLE-ARRAY (UNSIGNED-BYTE 8) <count>)
+(defconstant $fasl-cons 15)             ;<car:expr><cdr:expr> Make a cons
+(defconstant $fasl-s8-vector 16)        ;<count> make a (SIMPLE-ARRAY (SIGNED-BYTE 8) <count>)
+(defconstant $fasl-t-vector 17)         ;<count> make a (SIMPLE-ARRAY T <count>)
+(defconstant $fasl-nil 18)              ; Make nil
+(defconstant $fasl-timm 19)             ;<n:long>
+(defconstant $fasl-function 20)         ;<count> Make function
+(defconstant $fasl-vstr 21)             ;<vstring> Make a string
+(defconstant $fasl-vmksym 22)           ;<vstring> Make an uninterned symbol
+(defconstant $fasl-platform 23)         ;<n:byte> Ensure that file's loadable on platform n.
+(defconstant $fasl-vetab-alloc 24)      ;<count:count> Make a new expression table
+                                        ; with count slots.  Current etab gets lost.
+(defconstant $fasl-veref 25)            ;<index:count> Get the value from an etab slot.
+(defconstant $fasl-fixnum8 26)          ;<high:long><low:long> Make an 8-byte fixnum.
+(defconstant $fasl-symfn 27)            ;<sym:expr> 
+(defconstant $fasl-eval 28)             ;<expr> Eval <expr> and return value.
+(defconstant $fasl-u16-vector 29)       ;<count> Make a (SIMPLE-ARRAY (UNSIGNED-BYTE 16) <count>)
+(defconstant $fasl-s16-vector 30)       ;<count> Make a (SIMPLE-ARRAY (SIGNED-BYTE 16) <count>)
+(defconstant $fasl-vintern 31)          ;<vstring> Intern in current pkg.
+(defconstant $fasl-vpkg-intern 32)      ;<pkg:expr><vstring> Make a sym in pkg.
+(defconstant $fasl-vpkg 33)             ;<vstring> Returns the package of given name
+(defconstant $fasl-vgvec 34)            ;<subtype:byte><n:count><n exprs>
+(defconstant $fasl-defun 35)            ;<fn:expr><doc:expr>
+(defconstant $fasl-macro 37)            ;<fn:expr><doc:expr>
+(defconstant $fasl-defconstant 38)      ;<sym:expr><val:expr><doc:expr>
+(defconstant $fasl-defparameter 39)     ;<sym:expr><val:expr><doc:expr>
+(defconstant $fasl-defvar 40)           ;<sym:expr>
+(defconstant $fasl-defvar-init 41)      ;<sym:expr><val:expr><doc:expr>
+(defconstant $fasl-vivec 42)            ;<subtype:byte><n:count><n data bytes>
+(defconstant $fasl-prog1 43)            ;<expr><expr> - Second <expr> is for side-affects only
+(defconstant $fasl-vlist 44)            ;<n:count> <data: n+1 exprs> Make a list
+(defconstant $fasl-vlist* 45)           ;<n:count> <data:n+2 exprs> Make an sexpr
+(defconstant $fasl-sfloat 46)           ;<long> Make SINGLE-FLOAT from bits
+(defconstant $fasl-src 47)              ;<expr> - Set *loading-file-source-file * to <expr>.
+(defconstant $fasl-u32-vector 48)       ;<count> Make a (SIMPLE-ARRAY (UNSIGNED-BYTE 32) <count>)
+(defconstant $fasl-provide 49)          ;<string:expr>
+(defconstant $fasl-u64-vector 50)       ;<count> Make a (SIMPLE-ARRAY (UNSIGNED-BYTE 64) <count>)
+(defconstant $fasl-s64-vector 51)       ;<count> Make a (SIMPLE-ARRAY (SIGNED-BYTE 64) <count>)
+(defconstant $fasl-istruct 52)          ;<count> Make an ISTRUCT with <count> elements
+(defconstant $fasl-complex 53)          ;<real:expr><imag:expr>
+(defconstant $fasl-ratio 54)            ;<num:expr><den:expr>
+(defconstant $fasl-vector-header 55)    ;<count> Make a vector header
+(defconstant $fasl-array-header 56)     ;<count> Make an array header.
+(defconstant $fasl-s32 57)              ;<4bytes> Make a (SIGNED-BYTE 32)
+(defconstant $fasl-vintern-special 58)  ;<vstring> Intern in current pkg, ensure that it has a special binding index
+(defconstant $fasl-s64 59)              ;<8bytes> Make a (SIGNED-BYTE 64)
+(defconstant $fasl-vpkg-intern-special 60) ;<pkg:expr><vstring> Make a sym in pkg, ensure that it has a special binding index
+(defconstant $fasl-vmksym-special 61)   ;<vstring> Make an uninterned symbol, ensure special binding index
+(defconstant $fasl-nvmksym-special 62)  ;<nvstring> Make an uninterned symbol, ensure special binding index
+(defconstant $fasl-nvpkg-intern-special 63) ;<pkg:expr><nvstring> Make a sym in pkg, ensure that it has a special binding index
+(defconstant $fasl-nvintern-special 64)  ;<nvstring> Intern in current pkg, ensure that it has a special binding index
+(defconstant $fasl-nvpkg 65)            ;<vstring> Returns the package of given name
+(defconstant $fasl-nvpkg-intern 66)     ;<nvstring> Intern in current pkg.
+(defconstant $fasl-nvintern 67)         ;<pkg:expr><nvstring> Make a sym in pkg.
+(defconstant $fasl-nvmksym 68)          ;<nvstring> Make a string
+(defconstant $fasl-nvstr 69)            ;<nvstring> Make an uninterned symbol
+(defconstant $fasl-toplevel-location 70);<expr> - Set *loading-toplevel-location* to <expr>
+(defconstant $fasl-istruct-cell 71)     ;<expr> register istruct cell for expr
+
+
+;;; <string> means <size><size bytes> (this is no longer used)
+;;; <size> means either <n:byte> with n<#xFF, or <FF><n:word> with n<#xFFFF or
+;;;   <FFFF><n:long>
+;;; <count> is a variable-length encoding of an unsigned integer, written
+;;;  7 bits per octet, the least significant bits written first and the most
+;;;  significant octet having bit 7 set, so 127 would be written as #x00 and
+;;;  128 as #x00 #x81
+;;; <vstring> is a <count> (string length) followed by count octets of
+;;; 8-bit charcode data.
+;;; <nvstring> is a <count> (string length) followd by count <counts> of
+;;;  variable-length charcode data.  This encodes ASCII/STANDARD-CHAR as
+;;;  compactly as the <vstring> encoding, which should probably be deprecated.
+
+
+
+(defconstant $fasl-end #xFF)    ;Stop reading.
+
+(defconstant $fasl-epush-mask #x80)  ;Push value on etab if this bit is set in opcode.
+
+(defmacro fasl-epush-op (op) `(%ilogior2 ,$fasl-epush-mask ,op))
+
+(provide "FASLENV")
Index: /branches/new-random/xdump/hashenv.lisp
===================================================================
--- /branches/new-random/xdump/hashenv.lisp	(revision 13309)
+++ /branches/new-random/xdump/hashenv.lisp	(revision 13309)
@@ -0,0 +1,101 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+
+;;; It's wired in to the code that the length of this vector is 8 and
+;;; that its largest element is < 30
+(defconstant secondary-keys #(3 5 7 11 13 17 19 23))
+(defconstant secondary-keys-*-2 #(6 10 14 22 26 34 38 46))
+
+
+(defconstant $nhash.lock-free #x80000)
+
+; The hash.vector cell contains a vector with some longwords of overhead
+; followed by alternating keys and values.
+;; If you change anything here, also update the kernel def in XXX-constantsNN.h
+(def-accessors () %svref
+  nhash.vector.link                     ; GC link for weak vectors
+  nhash.vector.flags                    ; a fixnum of flags
+  nhash.vector.gc-count                 ; gc-count kernel global
+  nhash.vector.free-alist               ; empty alist entries for finalization
+  nhash.vector.finalization-alist       ; deleted out key/value pairs put here
+  nhash.vector.weak-deletions-count     ; incremented when the GC deletes an element
+  nhash.vector.hash                     ; back-pointer
+  nhash.vector.deleted-count            ; if lock-free, hint to GC to delete marked keys.
+                                        ; else number of deleted entries
+  nhash.vector.count                    ; number of valid entries [not maintained if lock-free]
+  nhash.vector.cache-idx                ; index of last cached key/value pair
+  nhash.vector.cache-key                ; cached key
+  nhash.vector.cache-value              ; cached value
+  nhash.vector.size                     ; number of entries in table
+  nhash.vector.size-reciprocal          ; shifted reciprocal of nhash.vector.size
+  )
+
+
+; number of longwords of overhead in nhash.vector.
+; Must be a multiple of 2 or INDEX parameters in LAP code will not be tagged as fixnums.
+(defconstant $nhash.vector_overhead 14)
+
+(defconstant $nhash_weak_bit 12)        ; weak hash table
+(defconstant $nhash_weak_value_bit 11)  ; weak on value vice key if this bit set
+(defconstant $nhash_finalizeable_bit 10)
+(defconstant $nhash_keys_frozen_bit 9)  ; GC must not change key slots when deleting
+(defconstant $nhash_weak_flags_mask
+  (bitset $nhash_keys_frozen_bit (bitset $nhash_weak_bit (bitset $nhash_weak_value_bit (bitset $nhash_finalizeable_bit 0)))))
+
+
+(defconstant $nhash_track_keys_bit 28)  ; request GC to track relocation of keys.
+(defconstant $nhash_key_moved_bit 27)   ; set by GC if a key moved.
+(defconstant $nhash_ephemeral_bit 26)   ; set if a hash code was computed using an address
+                                        ; in ephemeral space
+(defconstant $nhash_component_address_bit 25) ; a hash code was computed from a key's component
+
+
+
+(defconstant $nhash-growing-bit 16)
+(defconstant $nhash-rehashing-bit 17)
+
+)
+
+(declare-arch-specific-macro immediate-p-macro)
+
+(declare-arch-specific-macro hashed-by-identity)
+          
+	 
+;; state is #(hash-table index key-vector count)  
+(def-accessors %svref
+  nhti.hash-table
+  nhti.index
+  nhti.keys
+  nhti.values
+  nhti.nkeys)
+
+#+x8632-target
+(defconstant +nil-hash+ 201404780)
+
+#-x8632-target
+(defconstant +nil-hash+ (mixup-hash-code (%pname-hash "NIL" 3)))
+
+
+
+
+
+
+
Index: /branches/new-random/xdump/heap-image.lisp
===================================================================
--- /branches/new-random/xdump/heap-image.lisp	(revision 13309)
+++ /branches/new-random/xdump/heap-image.lisp	(revision 13309)
@@ -0,0 +1,161 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2002-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+(defconstant image-sig0 (dpb (char-code #\O)
+			     (byte 8 24)
+			     (dpb (char-code #\p)
+				  (byte 8 16)
+				  (dpb (char-code #\e)
+				       (byte 8 8)
+				       (char-code #\n)))))
+(defconstant image-sig1 (dpb (char-code #\M)
+			     (byte 8 24)
+			     (dpb (char-code #\C)
+				  (byte 8 16)
+				  (dpb (char-code #\L)
+				       (byte 8 8)
+				       (char-code #\I)))))
+(defconstant image-sig2 (dpb (char-code #\m)
+			     (byte 8 24)
+			     (dpb (char-code #\a)
+				  (byte 8 16)
+				  (dpb (char-code #\g)
+				       (byte 8 8)
+				       (char-code #\e)))))
+(defconstant image-sig3 (dpb (char-code #\F)
+			     (byte 8 24)
+			     (dpb (char-code #\i)
+				  (byte 8 16)
+				  (dpb (char-code #\l)
+				       (byte 8 8)
+				       (char-code #\e)))))
+
+#|
+(def-foreign-type
+    openmcl-image-section-header
+    (:struct nil
+	     (:code :unsigned-long)
+	     (:area (:* t))
+	     (:memory-size :unsigned-long)
+	     (:static-dnodes :unsigned-long)))
+|#
+
+(defparameter *image-section-size* ())
+
+
+
+(defparameter *image-header-size* nil)
+
+(defun target-setup-image-header-sizes ()
+  (setq *image-header-size* (* 4 16))
+  (setq *image-section-size* (* 4 (target-word-size-case
+                                   (32 4)
+                                   (64 8)))))
+
+(defun image-write-fullword (w f &optional force-big-endian)
+  (cond ((or force-big-endian *xload-target-big-endian*)
+         (write-byte (ldb (byte 8 24) w) f)
+         (write-byte (ldb (byte 8 16) w) f)
+         (write-byte (ldb (byte 8 8) w) f)
+         (write-byte (ldb (byte 8 0) w) f))
+        (t
+         (write-byte (ldb (byte 8 0) w) f)
+         (write-byte (ldb (byte 8 8) w) f)
+         (write-byte (ldb (byte 8 16) w) f)
+         (write-byte (ldb (byte 8 24) w) f))))
+
+(defun image-write-doubleword (dw f)
+  (cond (*xload-target-big-endian*
+         (image-write-fullword (ldb (byte 32 32) dw) f)
+         (image-write-fullword (ldb (byte 32 0) dw) f))
+        (t
+         (image-write-fullword (ldb (byte 32 0) dw) f)
+         (image-write-fullword (ldb (byte 32 32) dw) f))))
+
+(defun image-write-natural (n f)
+  (target-word-size-case
+   (32 (image-write-fullword n f))
+   (64 (image-write-doubleword n f))))
+
+(defun image-align-output-position (f)
+  (file-position f (logand (lognot 4095)
+			   (+ 4095 (file-position f)))))
+
+
+(defparameter *image-abi-version* 1036)
+
+(defun write-image-file (pathname image-base spaces &optional (abi-version *image-abi-version*))
+  (target-setup-image-header-sizes)
+  (with-open-file (f pathname
+		     :direction :output
+		     :if-does-not-exist :create
+		     :if-exists :supersede
+		     :element-type '(unsigned-byte 8))
+    (let* ((nsections (length spaces))
+	   (header-pos (- 4096 (+ *image-header-size*
+                                  (* nsections *image-section-size*)))))
+      (file-position f header-pos)
+      (image-write-fullword image-sig0 f)
+      (image-write-fullword image-sig1 f)
+      (image-write-fullword image-sig2 f)
+      (image-write-fullword image-sig3 f)
+      (image-write-fullword (get-universal-time) f)
+      (image-write-fullword (target-word-size-case
+                             (32 *xload-image-base-address*)
+                             (64 0)) f)
+      (image-write-fullword (target-word-size-case
+                             (32 image-base)
+                             (64 0)) f)
+      (image-write-fullword nsections f)
+      (image-write-fullword abi-version f)
+      (target-word-size-case
+       (32
+        (dotimes (i 2) (image-write-fullword 0 f))
+        
+        (image-write-fullword (backend-target-platform *target-backend*) f)
+        (dotimes (i 4) (image-write-fullword 0 f)))
+       (64
+        (image-write-fullword 0 f)
+        (image-write-fullword 0 f)
+        (image-write-fullword (backend-target-platform *target-backend*) f)
+        (image-write-doubleword *xload-image-base-address* f)
+        (image-write-doubleword image-base f)))
+      (dolist (sect spaces)
+	(image-write-natural (ash (xload-space-code sect)
+                                  *xload-target-fixnumshift*)
+                             f)
+	(image-write-natural 0 f)
+	(let* ((size (xload-space-lowptr sect)))
+	  (image-write-natural size f)
+	  (image-write-natural 0 f)))   ; static dnodes.
+      (dolist (sect spaces)
+	(image-align-output-position f)
+	(stream-write-ivector f
+			      (xload-space-data sect)
+			      0
+			      (xload-space-lowptr sect)))
+      ;; Write an openmcl_image_file_trailer.
+      (image-write-fullword image-sig0 f)
+      (image-write-fullword image-sig1 f)
+      (image-write-fullword image-sig2 f)
+      (let* ((pos (+ 4 (file-position f))))
+	(image-write-fullword (- header-pos pos) f))
+      nil)))
+
+      
+      
+    
Index: /branches/new-random/xdump/xfasload.lisp
===================================================================
--- /branches/new-random/xdump/xfasload.lisp	(revision 13309)
+++ /branches/new-random/xdump/xfasload.lisp	(revision 13309)
@@ -0,0 +1,1968 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 2009 Clozure Associates
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+(in-package "CCL")
+
+
+(eval-when (:compile-toplevel :execute)
+(require "FASLENV" "ccl:xdump;faslenv")
+
+
+
+(defmacro defxloadfaslop (n arglist &body body)
+  `(setf (svref *xload-fasl-dispatch-table* ,n)
+         (nfunction ,n (lambda ,arglist ,@body))))
+
+(defmacro xload-copy-faslop (n)
+  `(let* ((n ,n))
+     (setf (svref *xload-fasl-dispatch-table* n)
+           (svref *fasl-dispatch-table* n))))
+)
+
+
+;;; I'm not sure that there's a better way to do this.
+
+(defparameter *xload-show-cold-load-functions* nil "Set to T when debugging")
+(defparameter *xload-special-binding-indices* nil)
+(defparameter *xload-reserved-special-binding-index-symbols*
+  '(*interrupt-level*))
+
+(defparameter *xload-next-special-binding-index* (length *xload-reserved-special-binding-index-symbols*))
+
+(defparameter *xload-target-nil* nil)
+(defparameter *xload-target-fixnumshift* nil)
+(defparameter *xload-target-fulltag-cons* nil)
+(defparameter *xload-target-fulltag-misc* nil)
+(defparameter *xload-target-misc-data-offset* nil)
+(defparameter *xload-target-fulltagmask* nil)
+(defparameter *xload-target-fulltag-cons* nil)
+(defparameter *xload-target-cons-size* nil)
+(defparameter *xload-target-car-offset* nil)
+(defparameter *xload-target-cdr-offset* nil)
+(defparameter *xload-target-misc-header-offset* nil)
+(defparameter *xload-target-misc-subtag-offset* nil)
+(defparameter *xload-target-unbound-marker* nil)
+(defparameter *xload-target-subtag-char* nil)
+(defparameter *xload-target-charcode-shift* nil)
+(defparameter *xload-target-big-endian* t)
+(defparameter *xload-host-big-endian* t)
+(defparameter *xload-target-use-code-vectors* t
+  "When true, assume that the target represents functions as a node vector with an immediate vector (a CODE-VECTOR) in its 0th element.  When false, assume that the target mixes code and constants in a single object.")
+(defparameter *xload-target-fulltag-for-symbols* nil)
+(defparameter *xload-target-fulltag-for-functions* nil)
+(defparameter *xload-target-char-code-limit* nil)
+
+
+(defvar *xload-backends* nil)
+(defvar *xload-default-backend*)
+(defvar *xload-target-backend*)
+
+(defparameter *xload-image-base-address* nil)
+
+(defparameter *xload-purespace-reserve* nil)
+(defparameter *xload-static-space-address* (ash 1 12))
+(defparameter *xload-static-space-size* (ash 8 10))
+(defparameter *xload-readonly-space-address* nil)
+(defparameter *xload-readonly-space-size* (ash 1 18))
+(defparameter *xload-dynamic-space-address* nil)
+(defparameter *xload-dynamic-space-size* (ash 1 18))
+(defparameter *xload-managed-static-space-address* nil)
+(defparameter *xload-managed-static-space-size* 0)
+(defparameter *xload-static-cons-space-address* nil)
+(defparameter *xload-static-cons-space-size* 0)
+
+(defstruct backend-xload-info
+  name
+  macro-apply-code-function
+  closure-trampoline-code
+  udf-code
+  default-image-name
+  default-startup-file-name
+  subdirs
+  compiler-target-name
+  image-base-address
+  nil-relative-symbols
+  static-space-init-function
+  purespace-reserve
+  static-space-address
+)
+
+(defun setup-xload-target-parameters ()
+  (let* ((arch (backend-target-arch *target-backend*)))
+    (setq *xload-image-base-address*
+          (backend-xload-info-image-base-address
+           *xload-target-backend*))
+    (setq *xload-purespace-reserve*
+          (backend-xload-info-purespace-reserve
+           *xload-target-backend*))
+    (setq *xload-readonly-space-address* *xload-image-base-address*)
+    (setq *xload-dynamic-space-address*
+          (+ *xload-image-base-address*
+             *xload-purespace-reserve*))
+    (setq *xload-managed-static-space-address* *xload-dynamic-space-address*
+          *xload-static-cons-space-address* *xload-dynamic-space-address*)
+    (setq *xload-static-space-address*
+          (backend-xload-info-static-space-address
+           *xload-target-backend*))
+    (setq *xload-target-nil*
+          (arch::target-nil-value arch))
+    (setq *xload-target-unbound-marker*
+          (arch::target-unbound-marker-value arch))
+    (setq *xload-target-misc-header-offset*
+          (- (arch::target-misc-data-offset arch)
+             (arch::target-lisp-node-size arch)))
+    (setq *xload-target-misc-subtag-offset*
+          (arch::target-misc-subtag-offset arch))
+    (setq *xload-target-fixnumshift*
+          (arch::target-word-shift arch))
+    (setq *xload-target-fulltag-cons*
+          (arch::target-cons-tag arch))
+    (setq *xload-target-car-offset*
+          (arch::target-car-offset arch))
+    (setq *xload-target-cdr-offset*
+          (arch::target-cdr-offset arch))
+    (setq *xload-target-cons-size*
+          (* 2 (arch::target-lisp-node-size arch)))
+    (setq *xload-target-fulltagmask*
+          (arch::target-fulltagmask arch))
+    (setq *xload-target-misc-data-offset*
+          (arch::target-misc-data-offset arch))
+    (setq *xload-target-fulltag-misc*
+          (arch::target-fulltag-misc arch))
+    (setq *xload-target-subtag-char*
+          (arch::target-subtag-char arch))
+    (setq *xload-target-charcode-shift*
+          (arch::target-charcode-shift arch))
+    (setq *xload-target-big-endian*
+          (arch::target-big-endian arch))
+    (setq *xload-host-big-endian*
+          (arch::target-big-endian
+           (backend-target-arch *host-backend*)))
+    (setq *xload-target-use-code-vectors*
+          (not (null (assoc :code-vector (arch::target-uvector-subtags arch)))))
+    (setq *xload-target-fulltag-for-symbols*
+          (if (arch::target-symbol-tag-is-subtag arch)
+            (arch::target-fulltag-misc arch)
+            (arch::target-symbol-tag arch)))
+    (setq *xload-target-fulltag-for-functions*
+          (if (arch::target-function-tag-is-subtag arch)
+            (arch::target-fulltag-misc arch)
+            (arch::target-function-tag arch)))
+    (setq *xload-target-char-code-limit*
+          (arch::target-char-code-limit arch))))
+
+
+
+(defun xload-target-consp (addr)
+  (and (= *xload-target-fulltag-cons* (logand addr *xload-target-fulltagmask*))
+       (not (= addr *xload-target-nil*))))
+
+
+(defun xload-target-listp (addr)
+  (or (= addr *xload-target-nil*)
+      (xload-target-consp addr)))
+
+
+(defun find-xload-backend (target)
+  (find target *xload-backends* :key #'backend-xload-info-name))
+
+(defun add-xload-backend (b)
+  (let* ((already (find-xload-backend (backend-xload-info-name b))))
+    (when already
+      (setq *xload-backends* (remove already *xload-backends*)))
+    (push b *xload-backends*)))
+
+
+(defun make-xload-header (element-count subtag)
+  (logior (ash element-count target::num-subtag-bits) subtag))
+
+
+(defparameter *xload-record-source-file-p* t)
+
+(defun xload-symbol-header ()
+  (make-xload-header target::symbol.element-count (xload-target-subtype :symbol)))
+
+(defparameter *xload-fasl-dispatch-table* (make-array (length *fasl-dispatch-table*)
+                                                     :initial-element #'%bad-fasl))
+
+(defun xload-swap-16 (16-bit-value)
+  (dpb (ldb (byte 8 0) 16-bit-value)
+       (byte 8 8)
+       (ldb (byte 8 8) 16-bit-value)))
+
+(defun xload-swap-32 (32-bit-value)
+  (dpb (xload-swap-16 (ldb (byte 16 0) 32-bit-value))
+       (byte 16 16)
+       (xload-swap-16 (ldb (byte 16 16) 32-bit-value))))
+
+(defun xload-swap-64 (64-bit-value)
+  (dpb (xload-swap-32 (ldb (byte 32 0) 64-bit-value))
+       (byte 32 32)
+       (xload-swap-32 (ldb (byte 32 32) 64-bit-value))))
+       
+(defun u32-ref (u32v byte-offset)
+  (declare (type (simple-array (unsigned-byte 32) (*)) u32v)
+           (fixnum byte-offset))
+  (locally (declare (optimize (speed 3) (safety 0)))
+    (let* ((val (aref u32v (ash byte-offset -2))))
+      (if (eq *xload-target-big-endian* *xload-host-big-endian*)
+        val
+        (xload-swap-32 val)))))
+
+(defun (setf u32-ref) (new u32v byte-offset)
+  (declare (type (simple-array (unsigned-byte 32) (*)) u32v)
+           (fixnum byte-offset))
+  (locally (declare (optimize (speed 3) (safety 0)))
+    (setf (aref u32v (ash byte-offset -2))
+          (if (eq *xload-target-big-endian* *xload-host-big-endian*)
+            (logand new #xffffffff)
+            (xload-swap-32 new)))))
+
+(defun u16-ref (u16v byte-offset)
+  (declare (type (simple-array (unsigned-byte 16) (*)) u16v)
+           (fixnum byte-offset))
+  (locally (declare (optimize (speed 3) (safety 0)))
+    (let* ((val (aref u16v (ash byte-offset -1))))
+      (if (eq *xload-target-big-endian* *xload-host-big-endian*)
+        val
+        (xload-swap-16 val)))))
+
+(defun (setf u16-ref) (new u16v byte-offset)
+  (declare (type (simple-array (unsigned-byte 16) (*)) u16v)
+           (fixnum byte-offset))
+  (locally (declare (optimize (speed 3) (safety 0)))
+    (setf (aref u16v (ash byte-offset -1))
+          (if (eq *xload-target-big-endian* *xload-host-big-endian*)
+            new
+            (xload-swap-16 new)))
+    new))
+
+(defun u8-ref (u8v byte-offset)
+  (declare (type (simple-array (unsigned-byte 8) (*)) u8v)
+           (fixnum byte-offset))
+  (locally (declare (optimize (speed 3) (safety 0)))
+    (aref u8v byte-offset)))
+
+(defun (setf u8-ref) (new u8v byte-offset)
+  (declare (type (simple-array (unsigned-byte 8) (*)) u8v)
+           (fixnum byte-offset))
+  (locally (declare (optimize (speed 3) (safety 0)))
+    (setf (aref u8v byte-offset) new)))
+
+(defun natural-ref (u32v byte-offset)
+  (target-word-size-case
+   (32 (u32-ref u32v byte-offset))
+   (64 (let* ((first (u32-ref u32v byte-offset))
+              (second (u32-ref u32v (+ byte-offset 4))))
+         (if *xload-target-big-endian*
+           (dpb first (byte 32 32) second)
+           (dpb second (byte 32 32) first))))))
+
+(defun (setf natural-ref) (new u32v byte-offset)
+  (target-word-size-case
+   (32 (setf (u32-ref u32v byte-offset) new))
+   (64 (let* ((high (ldb (byte 32 32) new))
+              (low (ldb (byte 32 0) new)))
+         (if *xload-target-big-endian*
+           (setf (u32-ref u32v byte-offset) high
+                 (u32-ref u32v (+ byte-offset 4)) low)
+           (setf (u32-ref u32v byte-offset) low
+                 (u32-ref u32v (+ byte-offset 4)) high))
+         new))))
+
+
+(defun xload-aligned-uvector-size (nbytes)
+  (target-word-size-case
+   (32 (logand (lognot 7) (+ 4 7 nbytes )))
+   (64 (logand (lognot 15) (+ 15 8 nbytes)))))
+
+(defparameter *xload-spaces* nil)
+(defparameter *xload-image-file* nil)
+(defvar *xload-image-file-name*)
+(defvar *xload-startup-file*)
+
+
+(defstruct xload-space
+  (vaddr 0)
+  (size (ash 1 18))
+  (lowptr 0)
+  (data nil)
+  (code 0))
+
+(defmethod print-object ((s xload-space) stream)
+  (print-unreadable-object (s stream :type t)
+    (format stream "~a @#x~8,'0x len = ~d" (xload-space-code s) (xload-space-vaddr s) (xload-space-lowptr s))))
+
+;;; :constructor ... :constructor ... <gasp> ... must remember ... :constructor
+
+(defun init-xload-space (vaddr size code)
+  (let* ((nfullwords (ash (+ size 3) -2))
+         (space (make-xload-space :vaddr vaddr
+                                 :size size
+                                 :data (make-array nfullwords
+                                                   :element-type '(unsigned-byte 32)
+                                                   :initial-element 0)
+				 :code code)))
+    (push space *xload-spaces*)
+    space))
+
+;;; Nilreg-relative symbols.
+
+(defparameter %builtin-functions%
+  #(+-2 --2 *-2 /-2 =-2 /=-2 >-2 >=-2 <-2 <=-2 eql length sequence-type
+        assq memq logbitp logior-2 logand-2 ash 
+        %negate logxor-2 %aref1 %aset1
+        ;; add more
+        )
+  "Symbols naming fixed-arg, single-valued functions")
+        
+(defun xload-nrs ()
+  (mapcar
+   #'(lambda (s)
+       (or (assq s '((nil) (%pascal-functions%) (*all-metered-functions*)
+		      (*post-gc-hook*) (%handlers%) 
+		     (%finalization-alist%) (%closure-code%)))
+	   s))
+   (backend-xload-info-nil-relative-symbols *xload-target-backend*)))
+
+
+
+(defun  %xload-unbound-function% ()
+  (+ *xload-dynamic-space-address* *xload-target-fulltag-misc*))
+
+(defparameter *xload-dynamic-space* nil)
+(defparameter *xload-readonly-space* nil)
+(defparameter *xload-static-space* nil)
+(defparameter *xload-managed-static-space* nil)
+(defparameter *xload-static-cons-space* nil)
+(defparameter *xload-symbols* nil)
+(defparameter *xload-symbol-addresses* nil)
+(defparameter *xload-package-alist* nil)         ; maps real package to clone
+(defparameter *xload-aliased-package-addresses* nil)     ; cloned package to address
+(defparameter *xload-cold-load-functions* nil)
+(defparameter *xload-cold-load-documentation* nil)
+(defparameter *xload-loading-file-source-file* nil)
+(defparameter *xload-loading-toplevel-location* nil)
+(defparameter *xload-early-class-cells* nil)
+(defparameter *xload-early-istruct-cells* nil)
+
+(defparameter *xload-pure-code-p* t)     ; when T, subprims are copied to readonly space
+                                        ; and code vectors are allocated there, reference subprims
+                                        ; pc-relative.
+
+
+        
+(defun xload-lookup-symbol (sym)
+  (gethash (%symbol->symptr sym) *xload-symbols*))
+
+(defun xload-lookup-symbol-address (addr)
+  (gethash addr *xload-symbol-addresses*))
+
+(defun (setf xload-lookup-symbol) (addr sym)
+  (setf (gethash (%symbol->symptr sym) *xload-symbols*) addr))
+
+(defun (setf xload-lookup-symbol-address) (sym addr)
+  (setf (gethash addr *xload-symbol-addresses*) sym))
+
+(defun xload-lookup-address (address)
+  (dolist (space *xload-spaces* (error "Address #x~8,'0x not found in defined address spaces ." address))
+    (let* ((vaddr (xload-space-vaddr space)))
+      (if (and (<= vaddr address)
+               (< address (+ vaddr (the fixnum (xload-space-size space)))))
+        (return (values (xload-space-data space) (- address vaddr)))))))
+
+(defun xload-u32-at-address (address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (u32-ref v o)))
+
+(defun (setf xload-u32-at-address) (new address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (setf (u32-ref v o) new)))
+
+(defun xload-natural-at-address (address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (natural-ref v o)))
+
+(defun (setf xload-natural-at-address) (new address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (setf (natural-ref v o) new)))
+    
+(defun xload-u16-at-address (address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (u16-ref v o)))
+
+(defun (setf xload-u16-at-address) (new address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (setf (u16-ref v o) new)))
+
+(defun xload-u8-at-address (address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (u8-ref v o)))
+
+(defun (setf xload-u8-at-address) (new address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (setf (u8-ref v o) new)))
+
+(defun xload-integer (imm &optional (nwords 1))
+  (let* ((arch (backend-target-arch *target-backend*))
+         (most-negative (arch::target-most-negative-fixnum arch))
+         (most-positive (arch::target-most-positive-fixnum arch)))
+  (if (and (typep imm 'integer)
+           (<= most-negative imm most-positive))
+    (ash imm (arch::target-fixnum-shift arch))
+    (let* ((bignum (xload-make-ivector
+                    *xload-dynamic-space*
+                    :bignum
+                    nwords)))
+      (dotimes (i nwords bignum)
+        (setf (xload-%fullword-ref bignum i) (ldb (byte 32 0) imm)
+              imm (ash imm -32)))))))
+
+;;; "grow" the space: make a new data vector. Copy old data 
+;;;  to new data vector.  Update size and data fields.
+;;; Grow (arbitrarily) by 64K bytes, or as specified by caller.
+(defun xload-more-space (space &optional (delta (ash 1 16)))
+  (declare (fixnum delta))
+  (setq delta (logand (lognot 3) (the fixnum (+ delta 3))))
+  (let* ((old-size (xload-space-size space))
+         (old-data (xload-space-data space))
+         (old-nfullwords (ash old-size -2))
+         (delta-nfullwords (ash delta -2))
+         (new-size (+ old-size delta))
+         (new-nfullwords (+ old-nfullwords delta-nfullwords))
+         (new-data (make-array (the fixnum new-nfullwords)
+                               :element-type '(unsigned-byte 32)
+                               :initial-element 0)))
+    (declare (fixnum old-size old-nfullwords delta-nfullwords))
+    (declare (type (simple-array (unsigned-byte 32) (*)) old-data new-data))
+    (dotimes (i old-nfullwords)
+      (declare (optimize (speed 3) (safety 0)))
+      (setf (aref new-data i) (aref old-data i)))
+    (setf (xload-space-size space) new-size
+          (xload-space-data space) new-data)
+    new-size))
+                               
+
+(defun xload-alloc (space tag nbytes)
+  (declare (fixnum tag nbytes))
+  (when (logtest 7 nbytes) (error "~d not a multiple of 8 ." nbytes))
+  (let* ((free (xload-space-lowptr space)))
+    (if (> nbytes (the fixnum (- (the fixnum (xload-space-size space)) free)))
+      (xload-more-space space (the fixnum (+ nbytes (ash 1 16)))))
+    (setf (xload-space-lowptr space) (the fixnum (+ free nbytes)))
+    (let* ((offset (+ free tag)))
+      (declare (fixnum offset))
+      (values 
+       (the fixnum (+ (xload-space-vaddr space) offset))
+       (xload-space-data space)
+       offset))))
+
+;;; element-count doesn't include header
+(defun xload-alloc-fullwords (space tag nelements)
+  (xload-alloc space tag (xload-aligned-uvector-size (ash nelements 2))))
+
+(defun xload-alloc-halfwords (space tag nelements)
+  (xload-alloc space tag (xload-aligned-uvector-size (ash nelements 1))))
+
+(defun xload-alloc-bytes (space tag nelements)
+  (xload-alloc space tag (xload-aligned-uvector-size nelements)))
+
+(defun xload-alloc-doublewords (space tag nelements)
+  (xload-alloc space tag (xload-aligned-uvector-size (ash nelements 3))))
+
+
+
+
+(defun xload-make-cons (car cdr &optional (space *xload-dynamic-space*))
+  (multiple-value-bind (cell-addr data offset) (xload-alloc space  *xload-target-fulltag-cons* *xload-target-cons-size*)
+    (setf (natural-ref data (the fixnum (+ offset *xload-target-car-offset*))) car)
+    (setf (natural-ref data (the fixnum (+ offset *xload-target-cdr-offset*))) cdr)
+    cell-addr))
+
+;;; This initializes the gvector's contents to 0.  Might want to
+;;; consider initializing it to NIL for the benefit of package and
+;;; hashtable code.
+(defun xload-make-gvector (subtag len)
+  (unless (typep subtag 'fixnum)
+    (setq subtag (type-keyword-code subtag)))
+  (locally
+      (declare (fixnum subtag len))
+      (multiple-value-bind (cell-addr data offset)
+          (target-word-size-case
+           (32 (xload-alloc-fullwords *xload-dynamic-space* *xload-target-fulltag-misc* len))
+           (64 (xload-alloc-doublewords *xload-dynamic-space* *xload-target-fulltag-misc* len)))
+        (declare (fixnum offset))
+        (setf (natural-ref data (+ offset *xload-target-misc-header-offset*)) (make-xload-header len subtag))
+        cell-addr)))
+
+(defun xload-make-word-ivector (subtag len space)
+  (declare (fixnum subtag len))
+    (multiple-value-bind (cell-addr data offset) (xload-alloc-fullwords space  *xload-target-fulltag-misc* len)
+      (declare (fixnum offset))
+      (setf (natural-ref data (+ offset *xload-target-misc-header-offset*)) (make-xload-header len subtag))
+      cell-addr))
+
+(defun xload-package->addr (p)
+  (or (cdr (assq (or (cdr (assq p *xload-package-alist*)) 
+                     (error "Package ~s not cloned ." p))
+                 *xload-aliased-package-addresses*))
+      (error "Cloned package ~s: no assigned address . " p)))
+
+(defun xload-addr->package (a)
+  (or (car (rassoc (or (car (rassoc a *xload-aliased-package-addresses* :test #'eq))
+                       (error "Address ~d: no cloned package ." a))
+                   *xload-package-alist*))
+      (error "Package at address ~d not cloned ." a)))
+
+(defun xload-make-symbol (pname-address &optional
+					(package-address *xload-target-nil*)
+					(space *xload-dynamic-space*))
+  (let* ((sym
+          (target-word-size-case
+           (32 (xload-alloc-fullwords space *xload-target-fulltag-for-symbols* target::symbol.element-count))
+           (64 (xload-alloc-doublewords space *xload-target-fulltag-for-symbols* target::symbol.element-count))))
+         (sv (logior *xload-target-fulltag-misc*
+                     (logandc2 sym *xload-target-fulltagmask*))))
+    (setf (xload-%svref sv -1)  (xload-symbol-header))
+    (setf (xload-%svref sv target::symbol.flags-cell) 0)
+    ;; On PPC64, NIL's pname must be NIL.
+    (setf (xload-%svref sv target::symbol.pname-cell)
+          (if (and (target-arch-case (:ppc64 t) (otherwise nil))
+                   (= sym *xload-target-nil*))
+            *xload-target-nil*
+            pname-address))
+    (setf (xload-%svref sv target::symbol.vcell-cell) *xload-target-unbound-marker*)
+    (setf (xload-%svref sv target::symbol.package-predicate-cell) package-address)
+    (setf (xload-%svref sv target::symbol.fcell-cell) (%xload-unbound-function%))
+    (setf (xload-%svref sv target::symbol.plist-cell) *xload-target-nil*)
+    ;;(break "Made symbol at #x~x (#x~x)" cell-addr offset)
+    sym))
+
+;;; No importing or shadowing can (easily) happen during the cold
+;;; load; a symbol is present in no package other than its home
+;;; package.
+;;; This -just- finds or adds the symbol in the "clone" package's itab/etab.
+;;; Somebody else has to copy the symbol to the image ...
+(defun xload-intern (symbol)
+  (let* ((pname (symbol-name symbol))
+         (namelen (length pname))
+         (package (symbol-package symbol))
+         (clone (cdr (assq package *xload-package-alist*))))
+    (unless (nth-value 1 (%find-package-symbol pname clone namelen))    ; already there
+      (without-interrupts
+       (let* ((htab (if (%get-htab-symbol pname namelen (pkg.etab package)) 
+                      (pkg.etab clone) 
+                      (pkg.itab clone))))
+         (%htab-add-symbol symbol htab (nth-value 2 (%get-htab-symbol pname namelen htab))))))
+    t))
+     
+
+(defun xload-dnode-align (nbytes)
+  (target-word-size-case
+   (32 (logand (lognot 7) (+ nbytes 7 4)))
+   (64 (logand (lognot 15) (+ nbytes 15 8)))))
+
+(defun xload-subtag-bytes (subtag element-count)
+  (funcall (arch::target-array-data-size-function
+            (backend-target-arch *target-backend*))
+           subtag element-count))
+
+    
+(defun xload-make-dfloat (space high low)
+  (let* ((double-float-tag (arch::target-double-float-tag
+                            (backend-target-arch *target-backend*))))
+    (target-word-size-case
+     (32
+      (multiple-value-bind (dfloat-addr v o) (xload-alloc-fullwords space *xload-target-fulltag-misc* 3)
+        (declare (fixnum o))
+        (setf (u32-ref v (the fixnum (+ o *xload-target-misc-header-offset*))) 
+              (make-xload-header 3 double-float-tag))
+        (setf (u32-ref v (the fixnum (+ o *xload-target-misc-data-offset* 4)))
+              (if *xload-target-big-endian* high low))
+        (setf (u32-ref v (the fixnum (+ o *xload-target-misc-data-offset* 8)))
+              (if *xload-target-big-endian* low high))
+        dfloat-addr))
+     (64
+      (multiple-value-bind (dfloat-addr v o) (xload-alloc-fullwords space *xload-target-fulltag-misc* 2)
+        (declare (fixnum o))
+        (setf (natural-ref v (the fixnum (+ o *xload-target-misc-header-offset*))) 
+              (make-xload-header 2 double-float-tag))
+        (setf (u32-ref v (the fixnum (+ o *xload-target-misc-data-offset*)))
+              (if *xload-target-big-endian* high low))
+        (setf (u32-ref v (the fixnum (+ o *xload-target-misc-data-offset* 4)))
+              (if *xload-target-big-endian* low high))
+        dfloat-addr)))))
+
+(defun xload-make-sfloat (space bits)
+  (let* ((single-float-tag (arch::target-single-float-tag
+                            (backend-target-arch *target-backend*))))
+    (target-word-size-case
+     (32
+      (multiple-value-bind (sfloat-addr v o) (xload-alloc-fullwords space *xload-target-fulltag-misc* 1)
+        (declare (fixnum o))
+        (setf (u32-ref v (the fixnum (+ o *xload-target-misc-header-offset*))) 
+              (make-xload-header 1 single-float-tag))
+        (setf (u32-ref v (the fixnum (+ o *xload-target-misc-data-offset*))) bits)
+        sfloat-addr))
+     (64
+      (logior (ash bits 32) single-float-tag)))))
+        
+(defun xload-make-ivector (space subtag nelements)
+  (unless (typep subtag 'fixnum)
+    (setq subtag (type-keyword-code subtag)))
+  (locally
+      (declare (fixnum subtag nelements))
+    (multiple-value-bind (addr v o) (xload-alloc space *xload-target-fulltag-misc* (xload-dnode-align (xload-subtag-bytes subtag nelements)))
+      (declare (fixnum o))
+      (setf (natural-ref v (the fixnum (- o *xload-target-fulltag-misc*))) (make-xload-header nelements subtag))
+      (values addr v o))))
+
+(defun xload-%svref (addr i)
+  (declare (fixnum i))
+  (if (= (the fixnum (logand addr *xload-target-fulltagmask*)) *xload-target-fulltag-misc*)
+    (target-word-size-case
+     (32
+      (multiple-value-bind (v offset) (xload-lookup-address addr)
+        (declare (fixnum offset))
+        (u32-ref v (the fixnum (+ offset (the fixnum (+ *xload-target-misc-data-offset* (the fixnum (ash i 2)))))))))
+     (64
+      (multiple-value-bind (v offset) (xload-lookup-address addr)
+        (declare (fixnum offset))
+        (natural-ref v (the fixnum (+ offset (the fixnum (+ *xload-target-misc-data-offset* (the fixnum (ash i 3))))))))))
+    (error "Not a vector: #x~x" addr)))   
+
+(defun (setf xload-%svref) (new addr i)
+  (declare (fixnum i))
+  (if (= (the fixnum (logand addr *xload-target-fulltagmask*)) *xload-target-fulltag-misc*)
+    (target-word-size-case
+     (32
+      (multiple-value-bind (v offset) (xload-lookup-address addr)
+        (declare (fixnum offset))
+        (setf (u32-ref v (the fixnum (+ offset (the fixnum (+ *xload-target-misc-data-offset* (the fixnum (ash i 2))))))) new)))
+     (64
+      (multiple-value-bind (v offset) (xload-lookup-address addr)
+        (declare (fixnum offset))
+        (setf (natural-ref v (the fixnum (+ offset (the fixnum (+ *xload-target-misc-data-offset* (the fixnum (ash i 3))))))) new))))
+    (error "Not a vector: #x~x" addr)))
+
+
+(defun xload-%fullword-ref (addr i)
+  (declare (fixnum i))
+  (if (= (the fixnum (logand addr *xload-target-fulltagmask*))
+           *xload-target-fulltag-misc*)
+      (multiple-value-bind (v offset) (xload-lookup-address addr)
+        (declare (fixnum offset))
+        (u32-ref v (the fixnum (+ offset (the fixnum (+ *xload-target-misc-data-offset* (the fixnum (ash i 2))))))))
+      (error "Not a vector: #x~x" addr)))
+
+(defun (setf xload-%fullword-ref) (new addr i)
+  (declare (fixnum i))
+  (if (= (the fixnum (logand addr *xload-target-fulltagmask*))
+         *xload-target-fulltag-misc*)
+    (multiple-value-bind (v offset) (xload-lookup-address addr)
+      (declare (fixnum offset))
+      (setf (u32-ref v (the fixnum (+ offset (the fixnum (+ *xload-target-misc-data-offset* (the fixnum (ash i 2))))))) new))
+    (error "Not a vector: #x~x" addr)))
+
+(defun xload-car (addr)
+  (if (xload-target-listp addr)
+    (multiple-value-bind (v offset) (xload-lookup-address addr)
+      (declare (fixnum offset))
+      (natural-ref v (the fixnum (+ offset *xload-target-car-offset*))))
+    (error "Not a list: #x~x" addr)))
+
+(defun (setf xload-car) (new addr)
+  (if (xload-target-consp addr)
+    (multiple-value-bind (v offset) (xload-lookup-address addr)
+      (declare (fixnum offset))
+      (setf (natural-ref v (the fixnum (+ offset *xload-target-car-offset*))) new))
+    (error "Not a cons: #x~x" addr)))
+
+(defun xload-cdr (addr)
+  (if (xload-target-listp addr)
+    (multiple-value-bind (v offset) (xload-lookup-address addr)
+      (declare (fixnum offset))
+      (natural-ref v (the fixnum (+ offset *xload-target-cdr-offset*))))
+    (error "Not a list: #x~x" addr)))
+
+(defun (setf xload-cdr) (new addr)
+  (if (xload-target-consp addr)
+    (multiple-value-bind (v offset) (xload-lookup-address addr)
+      (declare (fixnum offset))
+      (setf (natural-ref v (the fixnum (+ offset *xload-target-cdr-offset*))) new))
+    (error "Not a cons: #x~x" addr)))
+
+(defun xload-caar (addr)
+  (xload-car (xload-car addr)))
+
+(defun xload-cadr (addr)
+  (xload-car (xload-cdr addr)))
+
+(defun xload-cdar (addr)
+  (xload-cdr (xload-car addr)))
+
+(defun xload-cddr (addr)
+  (xload-cdr (xload-cdr addr)))
+
+(defun xload-symbol-value (addr)
+  (unless (= *xload-target-fulltag-for-symbols*
+             (logand addr *xload-target-fulltagmask*))
+    (error "~& Not a symbol address: #x~x" addr))
+  (setq addr (logior *xload-target-fulltag-misc*
+                     (logandc2 addr *xload-target-fulltagmask*)))
+  (if (= (xload-%svref addr -1) (xload-symbol-header))
+    (xload-%svref addr target::symbol.vcell-cell)
+    (error "Not a symbol: #x~x" addr)))
+  
+
+(defun (setf xload-symbol-value) (new addr)
+  (unless (= *xload-target-fulltag-for-symbols*
+             (logand addr *xload-target-fulltagmask*))
+    (error "~& Not a symbol address: #x~x" addr))
+  (setq addr (logior *xload-target-fulltag-misc*
+                     (logandc2 addr *xload-target-fulltagmask*)))
+  (if (= (xload-%svref addr -1) (xload-symbol-header))
+    (setf (xload-%svref addr target::symbol.vcell-cell) new)
+    (error "Not a symbol: #x~x" addr)))
+
+(defun xload-set (sym val)
+  (check-type sym symbol)
+  (check-type val integer)
+  (let* ((symaddr (xload-lookup-symbol sym)))
+    (unless symaddr (error "Symbol address not found: ~s ." sym))
+    (setf (xload-symbol-value symaddr) val)))
+
+(defun xload-fset (addr def)
+  (unless (= *xload-target-fulltag-for-symbols*
+             (logand addr *xload-target-fulltagmask*))
+    (error "~& Not a symbol address: #x~x" addr))
+  (setq addr (logior *xload-target-fulltag-misc*
+                     (logandc2 addr *xload-target-fulltagmask*)))
+  (if (= (xload-%svref addr -1) (xload-symbol-header))
+    (setf (xload-%svref addr target::symbol.fcell-cell) def)
+    (error "Not a symbol: #x~x" addr)))
+
+(defun (setf xload-symbol-plist) (new addr)
+  (unless (= *xload-target-fulltag-for-symbols*
+             (logand addr *xload-target-fulltagmask*))
+    (error "~& Not a symbol address: #x~x" addr))
+  (setq addr (logior *xload-target-fulltag-misc*
+                     (logandc2 addr *xload-target-fulltagmask*)))
+  (let* ((plist (xload-%svref addr target::symbol.plist-cell)))
+    (if (xload-target-consp plist)
+      (let* ((str (xload-get-string (xload-%svref addr target::symbol.pname-cell))))
+        (warn "Symbol at #x~x (~a): plist already set." addr str))
+      (setf (xload-%svref addr target::symbol.plist-cell)
+            (xload-make-cons *xload-target-nil* new)))
+    new))
+
+;;; Emulate REGISTER-ISTRUCT-CELL, kinda.  Maintain
+;;; *xload-early-istruct-istruct-cells* in the image.
+(defun xload-register-istruct-cell (xsym)
+  (do* ((alist *xload-early-istruct-cells* (xload-cdr alist)))
+       ((= alist *xload-target-nil*)
+        (let* ((pair (xload-make-cons xsym *xload-target-nil*)))
+          (setq *xload-early-istruct-cells*
+                (xload-make-cons pair *xload-early-istruct-cells*))
+          pair))
+    (let* ((pair (xload-car alist)))
+      (when (= (xload-car pair) xsym)
+        (return pair)))))
+
+  
+;;; This handles constants set to themselves.  Unless
+;;; PRESERVE-CONSTANTNESS is true, the symbol's $sym_vbit_const bit is
+;;; cleared.  (This is done because the kernel tries to call EQUALP if
+;;; constants are "redefined", and EQUALP may not be defined early
+;;; enough.)
+(defun xload-copy-symbol (symbol &key
+				 (preserve-constantness (keywordp symbol))
+				 (space *xload-dynamic-space*))
+  (or (xload-lookup-symbol symbol)
+      (let* ((pname (symbol-name symbol))
+             (home-package (symbol-package symbol))
+             (addr (xload-make-symbol (xload-save-string pname (length pname))
+                                      (if home-package 
+                                        (xload-package->addr home-package)
+                                        *xload-target-nil*)
+                                      space))
+             (svaddr (logior *xload-target-fulltag-misc*
+                             (logandc2 addr *xload-target-fulltagmask*))))
+        (xload-intern symbol)
+        (let* ((bits (logandc2 (%symbol-bits symbol)
+                               (ash 1 $sym_vbit_typeppred))))
+          (setf (xload-%svref svaddr target::symbol.flags-cell)
+                (ash (if preserve-constantness
+                       bits
+                       (logand (lognot (ash 1 $sym_vbit_const)) bits))
+                     *xload-target-fixnumshift*)))
+        (if (and (constantp symbol)
+                 (eq (symbol-value symbol) symbol))
+          (setf (xload-symbol-value addr) addr))
+        (setf (xload-lookup-symbol-address addr) symbol)
+        (setf (xload-lookup-symbol symbol) addr))))
+
+
+;;; Write a list to dynamic space.  No detection of circularity or
+;;; structure sharing.  The cdr of the final cons can be nil (treated
+;;; as *xload-target-nil*.  All cars must be addresses.
+
+(defun xload-save-list (l)
+  (if (atom l)
+    (or l *xload-target-nil*)
+    (xload-make-cons (car l) (xload-save-list (cdr l)))))
+
+(defun xload-save-string (str &optional (n (length str)))
+  (declare (fixnum n))
+  (let* ((subtag (type-keyword-code :simple-string)))
+    (multiple-value-bind (addr v offset) (xload-make-ivector *xload-readonly-space* subtag n)
+      (case *xload-target-char-code-limit*
+        (256 (do* ((p (+ offset *xload-target-misc-data-offset*)
+                      (1+ p))
+                   (i 0 (1+ i)))
+                  ((= i n) str)
+               (declare (fixnum i p))
+               (setf (u8-ref v p) (char-code (schar str i)))))
+        (t
+         (do* ((p (+ offset *xload-target-misc-data-offset*)
+                      (+ p 4))
+                   (i 0 (1+ i)))
+                  ((= i n) str)
+               (declare (fixnum i p))
+               (setf (u32-ref v p) (char-code (schar str i))))))
+        addr)))
+
+;;; Read a string from fasl file, save it to readonly-space.
+(defun %xload-fasl-vreadstr (s)
+  (multiple-value-bind (str n new-p) (%fasl-vreadstr s)
+    (declare (fixnum n))
+    (values (xload-save-string str n) str n new-p)))
+
+;;; Read a string from fasl file, save it to readonly-space.
+;;; (assumes variable-length encoding.)
+(defun %xload-fasl-nvreadstr (s)
+  (multiple-value-bind (str n new-p) (%fasl-nvreadstr s)
+    (declare (fixnum n))
+    (values (xload-save-string str n) str n new-p)))
+
+(defun xload-clone-packages (packages)
+  (let* ((alist (mapcar #'(lambda (p)
+                            (cons p
+                                  (gvector :package
+                                            (cons (make-array (the fixnum (length (car (uvref p 0))))
+                                                              :initial-element 0)
+                                                  (cons 0 (cddr (pkg.itab p))))
+                                            (cons (make-array
+                                                   (the fixnum
+                                                     (length
+                                                      (car
+                                                       (pkg.etab p))))
+                                                   :initial-element 0)
+                                                  (cons 0 (cddr (pkg.etab p))))
+                                            nil                         ; used
+                                            nil                         ; used-by
+                                            (copy-list (pkg.names p))     ; names
+                                            nil ;shadowed
+                                            nil ;lock
+                                            nil ;intern-hook
+                                            )))
+                        packages)))
+    (flet ((lookup-clone (p) (let* ((clone (cdr (assq p alist))))
+                               (when clone (list clone)))))
+      (dolist (pair alist alist)
+        (let* ((orig (car pair))
+               (dup (cdr pair)))
+          (setf (pkg.used dup) (mapcan #'lookup-clone (pkg.used orig))
+                (pkg.used-by dup) (mapcan #'lookup-clone (pkg.used-by orig))))))))
+
+;;; Dump each cloned package into dynamic-space; return an alist
+(defun xload-assign-aliased-package-addresses (alist)
+  (let* ((addr-alist (mapcar #'(lambda (pair)
+                                 (let* ((p (cdr pair))
+                                        (v (xload-make-gvector :package (uvsize p))))
+                                   (setf (xload-%svref v pkg.names)
+                                         (xload-save-list (mapcar #'(lambda (n) (xload-save-string n))
+                                                                 (pkg.names p))))
+                                   (cons p v)))
+                             alist)))
+    (flet ((clone->addr (clone)
+             (or (cdr (assq clone addr-alist)) (error "cloned package ~S not found ." clone))))
+      (dolist (pair addr-alist addr-alist)
+        (let* ((p (car pair))
+               (v (cdr pair)))
+          (setf (xload-%svref v pkg.used)
+                (xload-save-list (mapcar #'clone->addr (pkg.used p)))
+                (xload-%svref v pkg.used-by)
+                (xload-save-list (mapcar #'clone->addr (pkg.used-by p)))
+                (xload-%svref v pkg.shadowed) 
+                (xload-save-list (mapcar #'xload-copy-symbol (pkg.shadowed p)))
+                (xload-%svref v pkg.intern-hook)
+                *xload-target-nil*
+                ))))))
+
+
+
+(defun xload-fasload (pathnames)
+  (dolist (path pathnames)
+    (multiple-value-bind (*load-pathname* *load-truename* source-file) (find-load-file (merge-pathnames path))
+      (unless *load-truename*
+        (return (signal-file-error $err-no-file path)))
+      (setq path *load-truename*)
+      (let* ((*readtable* *readtable*)
+             (*package* *ccl-package*)   ; maybe just *package*
+             (*loading-files* (cons path *loading-files*))
+             (*xload-loading-file-source-file* nil)
+             (*xload-loading-toplevel-location* nil)
+             (*loading-file-source-file* (namestring source-file)))
+        (when *load-verbose*
+	  (format t "~&;Loading ~S..." *load-pathname*)
+	  (force-output))
+        (multiple-value-bind (winp err) (%fasload (native-translated-namestring path) *xload-fasl-dispatch-table*)
+          (if (not winp) (%err-disp err)))))))
+  
+
+
+
+(defun xload-save-htab (htab)
+  (let* ((htvec (car htab))
+         (len (length htvec))
+         (xvec (xload-make-gvector :simple-vector len))
+         (deleted-marker *xload-target-unbound-marker*))
+    (dotimes (i len)
+      (let* ((s (%svref htvec i)))
+        (setf (xload-%svref xvec i)
+              (if s
+                (if (symbolp s)
+                  (or (xload-lookup-symbol s) deleted-marker)
+                  0)
+                (if (= (logand *xload-target-nil* *xload-target-fulltagmask*)
+                       *xload-target-fulltag-for-symbols*)
+                  *xload-target-nil*
+                  (+ *xload-target-nil*
+                     (let* ((arch (backend-target-arch *target-backend*)))
+                       (+ (arch::target-t-offset arch)
+                          (ash 8 (arch::target-word-shift arch))))))))))
+    (xload-make-cons  
+     xvec 
+     (xload-make-cons
+      (xload-integer (cadr htab))
+      (xload-integer (cddr htab))))))
+
+(defun xload-finalize-packages ()
+  (dolist (pair *xload-aliased-package-addresses*)
+    (let* ((p (car pair))
+           (q (cdr pair)))
+      (setf (xload-%svref q pkg.etab) (xload-save-htab (pkg.etab p)))
+      (setf (xload-%svref q pkg.itab) (xload-save-htab (pkg.itab p))))))
+
+(defun xload-get-string (address)
+  (multiple-value-bind (v o) (xload-lookup-address address)
+    (let* ((header (natural-ref v (+ o *xload-target-misc-header-offset*)))
+           (len (ash header (- target::num-subtag-bits)))
+           (str (make-string len))
+           (p (+ o *xload-target-misc-data-offset*)))
+      (case *xload-target-char-code-limit*
+        (256
+         (dotimes (i len str)
+           (setf (schar str i) (code-char (u8-ref v (+ p i))))))
+        (t
+         (dotimes (i len str)
+           (setf (schar str i) (code-char (u32-ref v (+ p (* i 4)))))))))))
+
+               
+(defun xload-save-code-vector (code)
+  (let* ((read-only-p *xload-pure-code-p*)
+         (vlen (uvsize code))
+         (prefix (arch::target-code-vector-prefix (backend-target-arch
+                                                   *target-backend*)))
+         (n (+ (length prefix) vlen)))
+    (declare (fixnum n))
+    (let* ((vector (xload-make-ivector 
+                    (if read-only-p
+                      *xload-readonly-space*
+                      *xload-dynamic-space*)
+                    :code-vector
+                    n))
+           (j -1))
+      (declare (fixnum j))
+      (dotimes (i n)
+        (setf (xload-%fullword-ref vector i)
+              (if prefix
+                (pop prefix)
+                (uvref code (incf j)))))
+      vector)))
+                          
+;;; For debugging
+(defun xload-show-list (l)
+  (labels ((show-list (l)
+             (unless (= l *xload-target-nil*)
+               (format t "#x~x" (xload-car l))
+               (setq l (xload-cdr l))
+               (unless (= l *xload-target-nil*)
+                 (format t " ")
+                 (show-list l)))))
+    (format t "~&(")
+    (show-list l)
+    (format t ")")))
+
+(defun xload-initial-packages ()
+  (mapcar #'find-package '("CL" "CCL"  "KEYWORD" "TARGET" "OS")))
+
+
+(defun xfasload (output-file &rest pathnames)
+  (let* ((*xload-symbols* (make-hash-table :test #'eq))
+         (*xload-symbol-addresses* (make-hash-table :test #'eql))
+         (*xload-spaces* nil)
+         (*xload-early-class-cells* nil)
+         (*xload-early-istruct-cells* *xload-target-nil*)
+         (*xload-readonly-space* (init-xload-space *xload-readonly-space-address* *xload-readonly-space-size* area-readonly))
+         (*xload-dynamic-space* (init-xload-space *xload-dynamic-space-address* *xload-dynamic-space-size* area-dynamic))
+	 (*xload-static-space* (init-xload-space *xload-static-space-address* *xload-static-space-size* area-static))
+         (*xload-managed-static-space* (init-xload-space *xload-managed-static-space-address* *xload-managed-static-space-size* area-managed-static))
+         (*xload-static-cons-space* (init-xload-space *xload-static-cons-space-address* *xload-static-cons-space-size* area-static-cons))
+						 
+         (*xload-package-alist* (xload-clone-packages (xload-initial-packages)))
+         (*xload-cold-load-functions* nil)
+         (*xload-cold-load-documentation* nil)
+         (*xload-loading-file-source-file* nil)
+         (*xload-loading-toplevel-location* nil)
+         (*xload-aliased-package-addresses* nil)
+         (*xload-special-binding-indices*
+          (make-hash-table :test #'eql))
+         (*xload-next-special-binding-index*
+          (length *xload-reserved-special-binding-index-symbols*)))
+    (funcall (backend-xload-info-static-space-init-function
+              *xload-target-backend*))
+    ;; Create %unbound-function% and the package objects in dynamic space,
+    ;; then fill in the nilreg-relative symbols in static space.
+    ;; Then start consing ..
+    (if *xload-target-use-code-vectors*
+      ;; The undefined-function object is a 1-element simple-vector (not
+      ;; a function vector).  The code-vector in its 0th element should
+      ;; report the appropriate error.
+      (let* ((udf-object (xload-make-gvector :simple-vector 1)))
+        (setf (xload-%svref udf-object 0) (xload-save-code-vector
+                                           (backend-xload-info-udf-code
+                                            *xload-target-backend*))))
+      (let* ((udf-object (xload-make-gvector :simple-vector 1)))
+        (setf (xload-%svref udf-object 0) (backend-xload-info-udf-code
+                                           *xload-target-backend*))))
+      
+    (setq *xload-aliased-package-addresses* (xload-assign-aliased-package-addresses *xload-package-alist*))
+    (dolist (pair (xload-nrs))
+      (let* ((val-p (consp pair))
+	     (val (if val-p (or (cdr pair) *xload-target-nil*)))
+	     (sym (if val-p (car pair) pair)))
+	(xload-copy-symbol sym
+			   :preserve-constantness t
+			   :space *xload-static-space*)
+	(when val-p (xload-set sym val))))
+                                        ; This could be a little less ... procedural.
+    (xload-set '*package* (xload-package->addr *ccl-package*))
+    (xload-set '*keyword-package* (xload-package->addr *keyword-package*))
+    (xload-set '%all-packages% (xload-save-list (mapcar #'cdr *xload-aliased-package-addresses*)))
+    (xload-set '%unbound-function% (%xload-unbound-function%))
+    (xload-set '*gc-event-status-bits* (xload-integer 0 #|(ash 1 $gc-integrity-check-bit)|#))
+    (xload-set '%toplevel-catch% (xload-copy-symbol :toplevel))
+    (if *xload-target-use-code-vectors*
+      (xload-set '%closure-code% (xload-save-code-vector
+                                  (backend-xload-info-closure-trampoline-code
+                                   *xload-target-backend*)))
+      (xload-set '%closure-code% *xload-target-nil*))
+    (let* ((macro-apply-code (funcall
+                              (backend-xload-info-macro-apply-code-function
+                               *xload-target-backend*))))
+
+      (xload-set '%macro-code%
+                 (if *xload-target-use-code-vectors*
+                   (xload-save-code-vector macro-apply-code)
+                   macro-apply-code)))
+    (let* ((len (length %builtin-functions%))
+           (v (xload-make-gvector :simple-vector len)))
+      (dotimes (i len)
+        (setf (xload-%svref v i) (xload-copy-symbol (svref %builtin-functions% i))))
+      (xload-set '%builtin-functions% v))
+    (xload-copy-symbol '*xload-startup-file*)
+    (xload-fasload pathnames)
+    (xload-set '*xload-startup-file*
+               (xload-save-string *xload-startup-file*))
+    (let* ((toplevel (xload-symbol-value (xload-lookup-symbol '%toplevel-function%))))      
+      (when (or (= toplevel *xload-target-unbound-marker*)
+                (= toplevel *xload-target-nil*))
+	(warn "~S not set in loading ~S ." '%toplevel-function pathnames)))
+    (setf (xload-symbol-value (xload-copy-symbol '*xload-cold-load-functions*))
+          (xload-save-list (setq *xload-cold-load-functions*
+                                 (nreverse *xload-cold-load-functions*))))
+    (setf (xload-symbol-value (xload-copy-symbol '*early-class-cells*))
+          (xload-save-list (mapcar #'xload-save-list *xload-early-class-cells*)))
+    (setf (xload-symbol-value (xload-copy-symbol '*istruct-cells*))
+          *xload-early-istruct-cells*)
+    (let* ((svnrev (local-svn-revision))
+           (tree (svn-tree)))
+      (setf (xload-symbol-value (xload-copy-symbol '*openmcl-svn-revision*))
+            (typecase svnrev
+              (fixnum (ash svnrev *xload-target-fixnumshift*))
+              (string (xload-save-string (if tree (format nil "~a-~a" svnrev tree) svnrev)))
+              (t *xload-target-nil*))))
+    (let* ((experimental-features *build-time-optional-features*))
+      (setf (xload-symbol-value (xload-copy-symbol '*optional-features*))
+            (xload-save-list (mapcar #'xload-copy-symbol experimental-features))))
+                              
+    (when *xload-show-cold-load-functions*
+      (format t "~&cold-load-functions list:")
+      (xload-show-list (xload-symbol-value (xload-copy-symbol '*xload-cold-load-functions*))))
+    (setf (xload-symbol-value (xload-copy-symbol '*xload-cold-load-documentation*))
+          (xload-save-list (setq *xload-cold-load-documentation*
+                                 (nreverse *xload-cold-load-documentation*))))
+    (dolist (s *xload-reserved-special-binding-index-symbols*)
+      (xload-ensure-binding-index (xload-copy-symbol s)))
+    (xload-finalize-packages)
+    #+debug
+    (maphash #'(lambda (addr idx)
+                 (format t "~&~d: ~s" idx
+                         (xload-lookup-symbol-address addr)))
+             *xload-special-binding-indices*)
+    (xload-dump-image output-file *xload-image-base-address*)))
+
+(defun xload-dump-image (output-file heap-start)
+  (declare (ftype (function (t t list)) write-image-file))
+  (write-image-file output-file
+		    heap-start
+		    (list *xload-static-space*
+			  *xload-readonly-space*
+			  *xload-dynamic-space*
+                          *xload-managed-static-space*
+                          *xload-static-cons-space*)))
+		    
+
+
+
+
+
+
+;;; The xloader
+
+(xload-copy-faslop $fasl-noop)
+(xload-copy-faslop $fasl-vetab-alloc)
+(xload-copy-faslop $fasl-veref)
+
+;;; Should error if epush bit set, else push on
+;;; *xload-cold-load-functions* or something.
+(defxloadfaslop $fasl-lfuncall (s)
+  (let* ((fun (%fasl-expr-preserve-epush s)))
+    (when (faslstate.faslepush s)
+      (error "Can't call function for value : ~s" fun))
+    (when *xload-show-cold-load-functions*
+      (format t "~& cold-load function: #x~x" fun))
+    (push fun *xload-cold-load-functions*)))
+
+(xload-copy-faslop $fasl-globals)        ; what the hell did this ever do ?
+
+;;; fasl-char: maybe epush, return target representation of BASE-CHARACTER
+(defxloadfaslop $fasl-char (s)
+  (let* ((code (%fasl-read-count s))
+         (target-char (logior *xload-target-subtag-char*
+                              (ash code *xload-target-charcode-shift*))))
+    (%epushval s target-char)))
+
+
+
+(defxloadfaslop $fasl-dfloat (s)
+  (%epushval s (xload-make-dfloat *xload-readonly-space* (%fasl-read-long s) (%fasl-read-long s))))
+
+(defxloadfaslop $fasl-sfloat (s)
+  (%epushval s (xload-make-sfloat *xload-readonly-space* (%fasl-read-long s))))
+
+(defun xload-read-utf-8-string (s v o nchars nextra)
+  (declare (fixnum nchars nextra))
+  (if (eql 0 nextra)
+    (dotimes (i nchars)
+      (setf (u32-ref v (+ o (* i 4) *xload-target-misc-data-offset*))
+            (%fasl-read-byte s)) )
+    (flet ((trailer-byte ()
+             (when (> nextra 0)
+               (decf nextra)
+               (let* ((b (%fasl-read-byte s)))
+                 (declare ((unsigned-byte 8) b))
+                 (and (>= b #x80)
+                      (< b #xc0)
+                      (logand b #x3f))))))
+      (declare (inline trailer-byte))
+      (dotimes (i nchars)
+        (let* ((b0 (%fasl-read-byte s)))
+          (declare ((unsigned-byte 8) b0))
+          (setf (u32-ref v (+ o (* i 4) *xload-target-misc-data-offset*))
+                (or
+                 (cond ((< b0 #x80) b0)
+                       ((and (>= b0 #xc2)
+                             (< b0 #xe0))
+                        (let* ((b1 (trailer-byte)))
+                          (and b1 (logior (ash (logand b0 #x1f) 6) b1))))
+                       ((and (>= b0 #xe0)
+                             (< b0 #xf0))
+                        (let* ((b1 (trailer-byte))
+                               (b2 (trailer-byte)))
+                          (and b1 b2 (logior (ash (logand b0 #x0f) 12)
+                                             (logior (ash b1 6)
+                                                     b2)))))
+                       ((and (>= b0 #xf0)
+                             (< b0 #xf5))
+                        (let* ((b1 (trailer-byte))
+                               (b2 (trailer-byte))
+                               (b3 (trailer-byte)))
+                          (and b1
+                               b2
+                               b3
+                               (logior (ash (logand b0 #x7) 18)
+                                       (logior (ash b1 12)
+                                               (logior (ash b2 6)
+                                                       b3)))))))
+                 (char-code #\Replacement_Character))))))))
+
+
+(defxloadfaslop $fasl-vstr (s)
+  (let* ((nchars (%fasl-read-count s))
+         (nextra (%fasl-read-count s)))
+    (multiple-value-bind (str v o) (xload-make-ivector *xload-readonly-space* :simple-string nchars)
+      (%epushval s str)
+      (xload-read-utf-8-string s v o nchars nextra)
+      str)))
+
+(defxloadfaslop $fasl-nvstr (s)
+  (let* ((n (%fasl-read-count s)))
+    (multiple-value-bind (str v o) (xload-make-ivector *xload-readonly-space* :simple-string n)
+      (%epushval s str)
+      (case *xload-target-char-code-limit*
+        (256
+         (dotimes (i n)
+           (setf (u8-ref v (+ o i *xload-target-misc-data-offset*))
+                 (%fasl-read-byte s))))
+        (t
+         (dotimes (i n)
+           (setf (u32-ref v (+ o (* i 4) *xload-target-misc-data-offset*))
+                 (%fasl-read-byte s)))))
+      str)))
+
+;;; Allegedly deprecated.
+(defxloadfaslop $fasl-fixnum (s)
+  (%epushval s (xload-integer
+                ;; This nonsense converts unsigned %fasl-read-long
+                ;; result to signed
+                (rlet ((long :long))
+                  (setf (%get-long long) (%fasl-read-long s))
+                  (%get-long long)))))
+
+(defxloadfaslop $fasl-word-fixnum (s)
+  (%epushval s (xload-integer (%word-to-int (%fasl-read-word s)))))
+
+(defxloadfaslop $fasl-s32 (s)
+  (%epushval s (xload-integer (%fasl-read-signed-long s))))
+
+(defxloadfaslop $fasl-s64 (s)
+  (%epushval s (xload-integer (logior (ash (%fasl-read-signed-long s) 32)
+                                      (%fasl-read-long s))
+                              2)))
+
+(defun xload-set-binding-address (symbol-address idx)
+  (unless (= *xload-target-fulltag-for-symbols*
+             (logand symbol-address *xload-target-fulltagmask*))
+    (error "~& Not a symbol address: #x~x" symbol-address))
+  (setq symbol-address
+        (logior *xload-target-fulltag-misc*
+                (logandc2 symbol-address *xload-target-fulltagmask*)))
+  (setf (xload-%svref symbol-address target::symbol.binding-index-cell)
+        (ash idx *xload-target-fixnumshift*))
+  (setf (gethash symbol-address *xload-special-binding-indices*) idx))
+
+(defun xload-ensure-binding-index (symbol-address)
+  (or (gethash symbol-address *xload-special-binding-indices*)
+      (let* ((sym (xload-lookup-symbol-address symbol-address))
+             (pos (position sym *xload-reserved-special-binding-index-symbols*)))
+        (xload-set-binding-address
+         symbol-address
+         (if pos
+           (1+ pos)
+           (incf *xload-next-special-binding-index*))))))
+
+(defun %xload-fasl-vmake-symbol (s &optional idx)
+  (let* ((sym (xload-make-symbol (%xload-fasl-vreadstr s))))
+    (when idx
+      (xload-ensure-binding-index sym))
+    (%epushval s sym)))
+
+(defun %xload-fasl-nvmake-symbol (s &optional idx)
+  (let* ((sym (xload-make-symbol (%xload-fasl-nvreadstr s))))
+    (when idx
+      (xload-ensure-binding-index sym))
+    (%epushval s sym)))
+
+
+
+(defxloadfaslop $fasl-vmksym (s)
+  (%xload-fasl-vmake-symbol s))
+
+(defxloadfaslop $fasl-nvmksym (s)
+  (%xload-fasl-nvmake-symbol s))
+
+(defxloadfaslop $fasl-vmksym-special (s)
+  (%xload-fasl-vmake-symbol s t))
+
+(defxloadfaslop $fasl-nvmksym-special (s)
+  (%xload-fasl-nvmake-symbol s t))
+
+(defun %xload-fasl-vintern (s package &optional idx)
+  (multiple-value-bind (str len new-p) (%fasl-vreadstr s)
+    (without-interrupts
+     (multiple-value-bind (cursym access internal external) (%find-symbol str len package)
+       (unless access
+         (unless new-p (setq str (%fasl-copystr str len)))
+         (setq cursym (%add-symbol str package internal external)))
+       ;; cursym now exists in the load-time world; make sure that it exists
+       ;; (and is properly "interned" in the world we're making as well)
+       (let* ((symaddr (xload-copy-symbol cursym)))
+         (when idx
+           (xload-ensure-binding-index symaddr))
+         (%epushval s symaddr))))))
+
+(defun %xload-fasl-nvintern (s package &optional idx)
+  (multiple-value-bind (str len new-p) (%fasl-nvreadstr s)
+    (without-interrupts
+     (multiple-value-bind (cursym access internal external) (%find-symbol str len package)
+       (unless access
+         (unless new-p (setq str (%fasl-copystr str len)))
+         (setq cursym (%add-symbol str package internal external)))
+       ;; cursym now exists in the load-time world; make sure that it exists
+       ;; (and is properly "interned" in the world we're making as well)
+       (let* ((symaddr (xload-copy-symbol cursym)))
+         (when idx
+           (xload-ensure-binding-index symaddr))
+         (%epushval s symaddr))))))
+
+
+(defxloadfaslop $fasl-vintern (s)
+  (%xload-fasl-vintern s *package*))
+
+(defxloadfaslop $fasl-nvintern (s)
+  (%xload-fasl-nvintern s *package*))
+
+(defxloadfaslop $fasl-vintern-special (s)
+  (%xload-fasl-vintern s *package* t))
+
+(defxloadfaslop $fasl-nvintern-special (s)
+  (%xload-fasl-nvintern s *package* t))
+
+(defxloadfaslop $fasl-vpkg-intern (s)
+  (let* ((addr (%fasl-expr-preserve-epush  s))
+         (pkg (xload-addr->package addr)))
+    (%xload-fasl-vintern s pkg)))
+
+(defxloadfaslop $fasl-nvpkg-intern (s)
+  (let* ((addr (%fasl-expr-preserve-epush  s))
+         (pkg (xload-addr->package addr)))
+    (%xload-fasl-nvintern s pkg)))
+
+(defxloadfaslop $fasl-vpkg-intern-special (s)
+  (let* ((addr (%fasl-expr-preserve-epush  s))
+         (pkg (xload-addr->package addr)))
+    (%xload-fasl-vintern s pkg t)))
+
+(defxloadfaslop $fasl-nvpkg-intern-special (s)
+  (let* ((addr (%fasl-expr-preserve-epush  s))
+         (pkg (xload-addr->package addr)))
+    (%xload-fasl-nvintern s pkg t)))
+
+(defun %xload-fasl-vpackage (s)
+  (multiple-value-bind (str len new-p) (%fasl-vreadstr s)
+    (let* ((p (%find-pkg str len)))
+      (%epushval s (xload-package->addr 
+                    (or p (%kernel-restart $XNOPKG (if new-p str (%fasl-copystr str len)))))))))
+
+(defun %xload-fasl-nvpackage (s)
+  (multiple-value-bind (str len new-p) (%fasl-nvreadstr s)
+    (let* ((p (%find-pkg str len)))
+      (%epushval s (xload-package->addr 
+                    (or p (%kernel-restart $XNOPKG (if new-p str (%fasl-copystr str len)))))))))
+
+
+(defxloadfaslop $fasl-vpkg (s)
+  (%xload-fasl-vpackage s))
+
+(defxloadfaslop $fasl-nvpkg (s)
+  (%xload-fasl-nvpackage s))
+
+(defxloadfaslop $fasl-cons (s)
+  (let* ((cons (%epushval s (xload-make-cons *xload-target-nil* *xload-target-nil*))))
+    (setf (xload-car cons) (%fasl-expr s)
+          (xload-cdr cons) (%fasl-expr s))
+    (setf (faslstate.faslval s) cons)))
+    
+
+(defun %xload-fasl-vlistX (s dotp)
+  (let* ((len (%fasl-read-count s)))
+    (declare (fixnum len))
+    (let* ((val (%epushval s (xload-make-cons *xload-target-nil* *xload-target-nil*)))
+           (tail val))
+      (setf (xload-car val) (%fasl-expr s))
+      (dotimes (i len)
+        (setf (xload-cdr tail) (setq tail (xload-make-cons  (%fasl-expr s) *xload-target-nil*))))
+      (if dotp
+        (setf (xload-cdr tail) (%fasl-expr s)))
+      (setf (faslstate.faslval s) val))))
+
+(defxloadfaslop $fasl-vlist (s)
+  (%xload-fasl-vlistX s nil))
+
+(defxloadfaslop $fasl-vlist* (s)
+  (%xload-fasl-vlistX s t))
+
+(defxloadfaslop $fasl-nil (s)
+  (%epushval s *xload-target-nil*))
+
+(defxloadfaslop $fasl-timm (s)
+  (let* ((val (%fasl-read-long s)))
+    #+paranoid (unless (= (logand $typemask val) $t_imm) 
+                 (error "Bug: expected immediate-tagged object, got ~s ." val))
+    (%epushval s val)))
+
+
+(defxloadfaslop $fasl-platform (s)
+  (%cant-epush s)
+  (let* ((platform (%fasl-expr s))
+	 (backend-name (backend-xload-info-compiler-target-name
+				 *xload-target-backend*))
+	 (backend (find-backend backend-name)))
+    (declare (fixnum platform))
+    (unless (= platform (ash (backend-target-platform backend)
+                             *xload-target-fixnumshift*))
+      (error "Not a ~A fasl file : ~s" backend-name (faslstate.faslfname s)))))
+
+
+(defxloadfaslop $fasl-symfn (s)
+  (let* ((symaddr (%fasl-expr-preserve-epush s))
+         (fnobj (xload-%svref symaddr target::symbol.fcell-cell)))
+    (if (and (= *xload-target-fulltag-misc*
+                (logand fnobj *xload-target-fulltagmask*))
+             (= (type-keyword-code :function) (xload-u8-at-address (+ fnobj *xload-target-misc-subtag-offset*))))
+      (%epushval s fnobj)
+      (error "symbol at #x~x is unfbound . " symaddr))))
+
+(defxloadfaslop $fasl-eval (s)
+  (let* ((expr (%fasl-expr-preserve-epush s)))
+    (cond ((and (xload-target-consp expr)
+                (eq (xload-lookup-symbol-address (xload-car expr))
+                    'find-class-cell)
+                (xload-target-consp (xload-car (xload-cdr expr)))
+                (eq (xload-lookup-symbol-address (xload-car (xload-car (xload-cdr expr))))
+                    'quote))
+           (let* ((class-name (xload-cadr (xload-cadr expr)))
+                  (cell (cdr (assoc class-name *xload-early-class-cells*))))
+             (unless cell
+               (setq cell (xload-make-gvector :istruct 5))
+               (setf (xload-%svref cell 0) (xload-register-istruct-cell
+                                            (xload-copy-symbol 'class-cell)))
+               (setf (xload-%svref cell 1) class-name)
+               (setf (xload-%svref cell 2) *xload-target-nil*)
+               (setf (xload-%svref cell 3) (xload-copy-symbol '%make-instance))
+               (setf (xload-%svref cell 4) *xload-target-nil*)
+               (push (cons class-name cell) *xload-early-class-cells*))
+             (%epushval s cell)))
+          ((and (xload-target-consp expr)
+                (eq (xload-lookup-symbol-address (xload-car expr))
+                    'register-istruct-cell)
+                (xload-target-consp (xload-cadr expr))
+                (eq (xload-lookup-symbol-address (xload-cdar expr))
+                    'quote))
+           (%epushval s (xload-register-istruct-cell (xload-cadr (xload-cadr expr)))))
+          (t
+           (error "Can't evaluate expression ~s in cold load ." expr)
+           (%epushval s (eval expr))))))         ; could maybe evaluate symbols, constants ...
+
+
+(defun xload-target-subtype (name)
+  (or
+   (cdr (assoc name (arch::target-uvector-subtags (backend-target-arch *target-backend*))))
+   (error "Unknown uvector type name ~s" name)))
+
+(defxloadfaslop $fasl-vivec (s)
+  (let* ((subtag (%fasl-read-byte s))
+         (element-count (%fasl-read-count s)))
+    (declare (fixnum subtag))
+    (multiple-value-bind (vector v o)
+                         (xload-make-ivector 
+                          *xload-readonly-space*
+                          subtag 
+                          element-count)
+      (%epushval s vector)
+      (%fasl-read-n-bytes s v (+ o  *xload-target-misc-data-offset*) (xload-subtag-bytes subtag element-count))
+      vector)))
+
+(defun xfasl-read-ivector (s subtag)
+  (let* ((element-count (%fasl-read-count s)))
+    (multiple-value-bind (vector v o)
+                         (xload-make-ivector 
+                          *xload-readonly-space*
+                          subtag 
+                          element-count)
+      (%epushval s vector)
+      (%fasl-read-n-bytes s
+                          v
+                          (+ o *xload-target-misc-data-offset*)
+                          (xload-subtag-bytes subtag element-count))
+      vector)))
+
+(defxloadfaslop $fasl-u8-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :unsigned-8-bit-vector)))
+
+(defxloadfaslop $fasl-s8-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :signed-8-bit-vector)))
+
+(defxloadfaslop $fasl-u16-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :unsigned-16-bit-vector)))
+
+(defxloadfaslop $fasl-s16-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :signed-16-bit-vector)))
+
+(defxloadfaslop $fasl-u32-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :unsigned-32-bit-vector)))
+
+(defxloadfaslop $fasl-s32-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :signed-32-bit-vector)))
+
+
+;;; We really can't compile 64-bit vectors on a 32-bit host.
+#+64-bit-target
+(defxloadfaslop $fasl-u64-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :unsigned-64-bit-vector)))
+
+#+64-bit-target
+(defxloadfaslop $fasl-u64-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :unsigned-64-bit-vector)))
+
+(defxloadfaslop $fasl-bit-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :bit-vector)))
+
+(defxloadfaslop $fasl-bignum32 (s)
+  (xfasl-read-ivector s (xload-target-subtype :bignum)))
+
+(defxloadfaslop $fasl-single-float-vector (s)
+  (xfasl-read-ivector s (xload-target-subtype :single-float-vector)))
+
+(defxloadfaslop $fasl-double-float-vector (s)
+  (target-word-size-case
+   (64 (xfasl-read-ivector s (xload-target-subtype :double-float-vector)))
+   (32
+    (let* ((element-count (%fasl-read-count s)))
+      (multiple-value-bind (vector v o)
+          (xload-make-ivector 
+           *xload-readonly-space*
+           (xload-target-subtype :double-float-vector)
+           element-count)
+        (%epushval s vector)
+        (%fasl-read-n-bytes s v (+ o (arch::target-misc-dfloat-offset (backend-target-arch *target-backend*))) (xload-subtag-bytes (xload-target-subtype :double-float-vector)  element-count))
+        vector)))))
+
+(defxloadfaslop $fasl-code-vector (s)
+  (let* ((element-count (%fasl-read-count s))
+         (subtag (xload-target-subtype :code-vector)))
+    (multiple-value-bind (vector v o)
+                         (xload-make-ivector 
+                          (if (not *xload-pure-code-p*)
+                            *xload-dynamic-space* 
+                            *xload-readonly-space*)
+                          subtag 
+                          element-count)
+      (%epushval s vector)
+      (%fasl-read-n-bytes s v (+ o
+                                 *xload-target-misc-data-offset*)
+                          (xload-subtag-bytes subtag element-count))
+      vector)))
+
+(defun xfasl-read-gvector (s subtype)
+  (declare (fixnum subtype))
+  (let* ((n (%fasl-read-count s))
+         (vector (xload-make-gvector subtype n)))
+    (%epushval s vector)
+    (dotimes (i n (setf (faslstate.faslval s) vector))
+      (setf (xload-%svref vector i) (%fasl-expr s)))))
+  
+(defxloadfaslop $fasl-vgvec (s)
+  (let* ((subtype (%fasl-read-byte s)))
+    (xfasl-read-gvector s subtype)))
+
+(defxloadfaslop $fasl-vector-header (s)
+  (xfasl-read-gvector s (xload-target-subtype :vector-header)))
+
+(defxloadfaslop $fasl-array-header (s)
+  (xfasl-read-gvector s (xload-target-subtype :array-header)))
+
+(defxloadfaslop $fasl-ratio (s)
+  (let* ((r (xload-make-gvector (xload-target-subtype :ratio)
+                                target::ratio.element-count)))
+    (%epushval s r)
+    (setf (xload-%svref r target::ratio.numer-cell) (%fasl-expr s)
+          (xload-%svref r target::ratio.denom-cell) (%fasl-expr s))
+    (setf (faslstate.faslval s) r)))
+
+(defxloadfaslop $fasl-complex (s)
+  (let* ((c (xload-make-gvector (xload-target-subtype :complex)
+                                target::complex.element-count)))
+    (%epushval s c)
+    (setf (xload-%svref c target::complex.realpart-cell) (%fasl-expr s)
+          (xload-%svref c target::complex.imagpart-cell) (%fasl-expr s))
+    (setf (faslstate.faslval s) c)))
+
+
+
+(defxloadfaslop $fasl-t-vector (s)
+  (xfasl-read-gvector s (xload-target-subtype :simple-vector)))
+
+(defxloadfaslop $fasl-function (s)
+  (xfasl-read-gvector s (xload-target-subtype :function)))
+
+(defxloadfaslop $fasl-istruct (s)
+  (xfasl-read-gvector s (xload-target-subtype :istruct)))
+
+(defun xload-lfun-name (lf)
+  (let* ((lfv (logior *xload-target-fulltag-misc*
+                      (logandc2 lf *xload-target-fulltagmask*)))
+         (header (xload-%svref lfv -1)))
+    (unless (= (type-keyword-code :function)
+               (logand header (1- (ash 1 target::num-subtag-bits))))
+      (error "Not a function address: ~x" lf))
+    (let* ((n (ash header (- target::num-subtag-bits))))
+      (if (> n 2)
+        (let* ((bits (ash (xload-%svref lfv (1- n))
+                          (- *xload-target-fixnumshift*))))
+          (unless (logbitp $lfbits-noname-bit bits)
+            (xload-%svref lfv (- n 2))))
+        (error "Teeny, tiny, little function : ~s" lf)))))
+
+
+(defun xload-record-source-file (symaddr indicator)
+  (when *xload-record-source-file-p*
+    (when (or (eq indicator 'function)
+              (eq indicator 'variable))
+      (let* ((keyaddr (xload-copy-symbol 'bootstrapping-source-files))
+             (pathaddr (or *xload-loading-toplevel-location*
+                           *xload-loading-file-source-file*
+                           (if *loading-file-source-file*
+                             (setq *xload-loading-file-source-file* (xload-save-string *loading-file-source-file*))))))
+        (when pathaddr
+          (let* ((keyval (if (eq indicator 'function)
+                           (xload-make-cons  pathaddr *xload-target-nil*)
+                           (xload-make-cons
+                            (xload-make-cons 
+                             (xload-make-cons  (xload-copy-symbol indicator) pathaddr)
+                             *xload-target-nil*)
+                            *xload-target-nil*))))
+            (setf (xload-symbol-plist symaddr) (xload-make-cons keyaddr keyval))))))))
+
+(defun xload-set-documentation (symaddr indicator doc)
+  ;; Should maybe check further that it's a string
+  ;; and it would hurt for whatever processes *xload-cold-load-documentation*
+  ;; to do some checking there as well.
+  (when (= (the fixnum (logand doc *xload-target-fulltagmask*))
+           *xload-target-fulltag-misc*)
+    (push (xload-save-list
+           (list symaddr
+                 (xload-copy-symbol indicator)
+                 doc))
+          *xload-cold-load-documentation*)))
+
+
+
+(defxloadfaslop $fasl-defun (s)
+  (%cant-epush s)
+  (let* ((fun (%fasl-expr s))
+         (doc (%fasl-expr s)))
+    (let* ((sym (xload-lfun-name fun)))
+      (unless (= doc *xload-target-nil*)
+        (xload-set-documentation sym 'function doc))
+      (xload-record-source-file sym 'function)
+      (xload-fset sym fun))))
+
+(defxloadfaslop $fasl-macro (s)
+  (%cant-epush s)
+  (let* ((fun (%fasl-expr s))
+         (doc (%fasl-expr s)))
+    (let* ((sym (xload-lfun-name fun))
+           (vector (xload-make-gvector :simple-vector 2)))
+      (setf (xload-%svref vector 0) (xload-symbol-value (xload-lookup-symbol '%macro-code%))
+            (xload-%svref vector 1) fun)
+      (unless (= doc *xload-target-nil*)
+        (xload-set-documentation sym 'function doc))
+      (xload-record-source-file sym 'function)
+      (xload-fset sym vector))))
+
+(defxloadfaslop $fasl-defconstant (s)
+  (%cant-epush s)
+  (let* ((sym (%fasl-expr s))
+         (val (%fasl-expr s))
+         (doc (%fasl-expr s)))
+    (unless (= doc *xload-target-nil*)
+      (xload-set-documentation sym 'variable doc))
+    (xload-record-source-file sym 'variable)
+    (setf (xload-symbol-value sym) val)
+    (let* ((sv (logior *xload-target-fulltag-misc*
+                       (logandc2 sym *xload-target-fulltagmask*))))
+      (setf (xload-%svref sv target::symbol.flags-cell)
+            (ash 
+             (logior (ash 1 $sym_vbit_special) 
+                     (ash 1 $sym_vbit_const) 
+                     (ash (xload-%svref sv target::symbol.flags-cell)
+                        (- *xload-target-fixnumshift*)))
+             *xload-target-fixnumshift*)))))
+
+(defxloadfaslop $fasl-defparameter (s)
+  (%cant-epush s)
+  (let* ((sym (%fasl-expr s))
+         (val (%fasl-expr s))
+         (doc (%fasl-expr s)))
+    (unless (= doc *xload-target-nil*)
+      (xload-set-documentation sym 'variable doc))
+    (xload-record-source-file sym 'variable)
+    (setf (xload-symbol-value sym) val)
+    (let* ((sv (logior *xload-target-fulltag-misc*
+                       (logandc2 sym *xload-target-fulltagmask*))))
+      (setf (xload-%svref sv target::symbol.flags-cell)
+            (ash 
+             (logior (ash 1 $sym_vbit_special) 
+                     (ash (xload-%svref sv target::symbol.flags-cell)
+                          (- *xload-target-fixnumshift*)))
+             *xload-target-fixnumshift*)))))
+
+(defxloadfaslop $fasl-defvar (s)
+  (%cant-epush s)
+  (let* ((sym (%fasl-expr s)))
+    (xload-record-source-file sym 'variable)
+    (let* ((sv (logior *xload-target-fulltag-misc*
+                       (logandc2 sym *xload-target-fulltagmask*))))
+      (setf (xload-%svref sv target::symbol.flags-cell)
+            (ash 
+             (logior (ash 1 $sym_vbit_special) 
+                     (ash (xload-%svref sv target::symbol.flags-cell)
+                          (- *xload-target-fixnumshift*)))
+             *xload-target-fixnumshift*)))))
+
+(defxloadfaslop $fasl-defvar-init (s)
+  (%cant-epush s)
+  (let* ((sym (%fasl-expr s))
+         (val (%fasl-expr s))
+         (doc (%fasl-expr s)))
+    (unless (= doc *xload-target-nil*)
+      (xload-set-documentation sym 'variable doc))
+    (when (= *xload-target-unbound-marker*
+             (xload-symbol-value sym))
+      (setf (xload-symbol-value sym) val))
+    (xload-record-source-file sym 'variable)
+    (let* ((sv (logior *xload-target-fulltag-misc*
+                       (logandc2 sym *xload-target-fulltagmask*))))
+      (setf (xload-%svref sv target::symbol.flags-cell)
+            (ash 
+             (logior (ash 1 $sym_vbit_special) 
+                     (ash (xload-%svref sv target::symbol.flags-cell)
+                          (- *xload-target-fixnumshift*)))
+             *xload-target-fixnumshift*)))))
+
+
+(xload-copy-faslop $fasl-prog1)
+
+(defxloadfaslop $fasl-src (s)
+  (%cant-epush s)
+  (let* ((path (%fasl-expr s)))
+    (setq *xload-loading-file-source-file* path)))
+
+(defxloadfaslop $fasl-toplevel-location (s)
+  (%cant-epush s)
+  (let* ((location (%fasl-expr s)))
+    (setq *xload-loading-toplevel-location* location)))
+
+;;; Use the offsets in the self-reference table to replace the :self
+;;; in (movl ($ :self) (% fn)) wih the function's actual address.
+;;; (x8632 only)
+(defun xload-fixup-self-references (addr)
+  (let* ((imm-word-count (xload-u16-at-address
+			  (+ addr *xload-target-misc-data-offset*))))
+    (do* ((i (- imm-word-count 2) (1- i))
+	  (offset (xload-%fullword-ref addr i) (xload-%fullword-ref addr i)))
+	 ((zerop offset))
+      (setf (xload-u8-at-address (+ *xload-target-misc-header-offset*
+				    addr
+				    offset
+				    0))
+				 (ldb (byte 8 0) addr)
+	    (xload-u8-at-address (+ *xload-target-misc-header-offset*
+				    addr
+				    offset
+				    1))
+				 (ldb (byte 8 8) addr)
+	    (xload-u8-at-address (+ *xload-target-misc-header-offset*
+				    addr
+				    offset
+				    2))
+				 (ldb (byte 8 16) addr)
+	    (xload-u8-at-address (+ *xload-target-misc-header-offset*
+				    addr
+				    offset
+				    3))
+				 (ldb (byte 8 24) addr)))))
+      
+(defxloadfaslop $fasl-clfun (s)
+  (let* ((size-in-elements (%fasl-read-count s))
+         (size-of-code (%fasl-read-count s)))
+    (declare (fixnum size-in-elements size-of-code))
+    (multiple-value-bind (vector v o)
+        (target-word-size-case
+         (32 (xload-alloc-fullwords *xload-dynamic-space* *xload-target-fulltag-misc* size-in-elements))
+         (64 (xload-alloc-doublewords *xload-dynamic-space* *xload-target-fulltag-misc* size-in-elements)))
+      (declare (fixnum o))
+      (setf (natural-ref v (+ o *xload-target-misc-header-offset*))
+            (make-xload-header size-in-elements (xload-target-subtype :function)))
+      (let* ((function (logior *xload-target-fulltag-for-functions*
+                               (logandc2 vector *xload-target-fulltagmask*))))
+        (%epushval s function)
+        (%fasl-read-n-bytes s v (+ o *xload-target-misc-data-offset*)
+                            (ash size-of-code *xload-target-fixnumshift*))
+	(target-arch-case
+	 (:x8632 (xload-fixup-self-references vector)))
+        (do* ((numconst (- size-in-elements size-of-code))
+              (i 0 (1+ i))
+              (constidx size-of-code (1+ constidx)))
+             ((= i numconst)
+              (setf (faslstate.faslval s) function))
+          (declare (fixnum i numconst constidx))
+          (setf (xload-%svref vector constidx) (%fasl-expr s)))))))
+
+(defxloadfaslop $fasl-istruct-cell (s)
+  (%epushval s (xload-register-istruct-cell (%fasl-expr-preserve-epush s))))
+
+
+
+(defparameter *xcompile-features* nil)
+
+
+
+(defun target-Xcompile-directory (target dir &optional force)
+  (let* ((backend (find-backend target))
+	 (any (not (null force)))
+         (outpath (merge-pathnames dir (backend-target-fasl-pathname backend)))
+         (*nx-speed* (max 1 *nx-speed*))
+         (*nx-safety* (min 1 *nx-safety*)))
+    (in-development-mode
+     (dolist (src (sort (directory (merge-pathnames dir "*.lisp"))
+			#'string< :key #'namestring)
+	      any)
+       (let* ((fasl (merge-pathnames outpath  src)))
+	 (when (or force
+		   (not (probe-file fasl))
+		   (> (file-write-date src)
+		      (file-write-date fasl)))
+	   (setq any t)
+	   (compile-file src :target target
+			 :features *xcompile-features*
+			 :output-file  fasl 
+			 :verbose t)))))))
+
+(defun target-xcompile-level-0 (target &optional force)
+  (let* ((backend (or (find-xload-backend target)
+		      (error "Unknown xload backend: ~s" target)))
+         ;; Saving doc-strings doesn't work in level-0 (yet.)
+         (*save-doc-strings* t)
+         (*fasl-save-doc-strings* t)
+	 (a (target-xcompile-directory target "ccl:level-0;" force))
+	 (b
+          (dolist (d (backend-xload-info-subdirs backend))
+            (target-xcompile-directory target d force))))
+    (or a b)))
+
+(defun cross-compile-level-0 (target &optional (recompile t))
+  (with-cross-compilation-target (target)
+    (target-xcompile-level-0 target recompile)))
+    
+(defun target-Xload-level-0 (target &optional (recompile t))
+  (let* ((*xload-target-backend* (or (find-xload-backend target)
+				     *xload-default-backend*))
+	 (*xload-startup-file* (backend-xload-info-default-startup-file-name
+				*xload-target-backend*)))
+    (in-development-mode
+     (when recompile
+       (target-Xcompile-level-0 target (eq recompile :force)))
+     (let* ((*xload-image-base-address* *xload-image-base-address*)
+            (*xload-readonly-space-address* *xload-readonly-space-address*)
+            (*xload-dynamic-space-address* *xload-dynamic-space-address*)
+            (*xload-target-nil* *xload-target-nil*)
+            (*xload-target-unbound-marker* *xload-target-unbound-marker*)
+            (*xload-target-misc-header-offset* *xload-target-misc-header-offset*)
+            (*xload-target-misc-subtag-offset* *xload-target-misc-subtag-offset*)
+            (*xload-target-fixnumshift* *xload-target-fixnumshift*)
+            (*xload-target-fulltag-cons* *xload-target-fulltag-cons*)
+            (*xload-target-car-offset* *xload-target-car-offset*)
+            (*xload-target-cdr-offset* *xload-target-cdr-offset*)
+            (*xload-target-cons-size* *xload-target-cons-size*)
+            (*xload-target-fulltagmask* *xload-target-fulltagmask*)
+            (*xload-target-misc-data-offset* *xload-target-misc-data-offset*)
+            (*xload-target-fulltag-misc* *xload-target-fulltag-misc*)
+            (*xload-target-subtag-char* *xload-target-subtag-char*)
+            (*xload-target-charcode-shift* *xload-target-charcode-shift*)
+            (*xload-target-big-endian* *xload-target-big-endian*)
+            (*xload-host-big-endian* *xload-host-big-endian*)
+            (*xload-target-use-code-vectors* *xload-target-use-code-vectors*)
+            (*xload-target-fulltag-for-symbols* *xload-target-fulltag-for-symbols*)
+            (*xload-target-fulltag-for-functions* *xload-target-fulltag-for-functions*)
+            (*xload-target-char-code-limit* *xload-target-char-code-limit*)
+            (*xload-purespace-reserve* *xload-purespace-reserve*)
+            (*xload-static-space-address* *xload-static-space-address*))
+       (setup-xload-target-parameters)
+       (let* ((*load-verbose* t)
+              (compiler-backend (find-backend
+                                 (backend-xload-info-compiler-target-name
+                                  *xload-target-backend*)))
+              (wild-fasls (concatenate 'simple-string
+                                       "*."
+                                       (pathname-type
+                                        (backend-target-fasl-pathname
+                                         compiler-backend))))
+              (wild-root (merge-pathnames "ccl:level-0;" wild-fasls))
+              (wild-subdirs
+               (mapcar #'(lambda (d)
+                           (merge-pathnames d wild-fasls))
+                       (backend-xload-info-subdirs *xload-target-backend*)))
+              (*xload-image-file-name* (backend-xload-info-default-image-name *xload-target-backend*)))
+         (apply #'xfasload *xload-image-file-name*
+                (append
+                 (apply #'append
+                        (mapcar #'(lambda (d)
+                                    (sort (directory d) #'string< :key #'namestring))
+                                wild-subdirs))
+                 (sort (directory wild-root) #'string< :key #'namestring)))
+         (format t "~&;Wrote bootstrapping image: ~s" (truename *xload-image-file-name*)))))))
+
+(defun Xcompile-directory (dir &optional force)
+  (target-xcompile-directory (backend-name *host-backend*) dir  force))
+
+(defun Xcompile-level-0 (&optional force)
+  (target-xcompile-level-0 (backend-name *host-backend*) force))
+
+(defun xload-level-0 (&optional (recompile t))
+  (target-xload-level-0 (backend-name *host-backend*) recompile))
+
+(defun cross-xload-level-0 (target &optional (recompile t))
+  (with-cross-compilation-target (target)
+    (let* ((*target-backend* (find-backend target)))
+      (target-xload-level-0 target recompile))))
+
+
+(provide "XFASLOAD")
Index: /branches/new-random/xdump/xppcfasload.lisp
===================================================================
--- /branches/new-random/xdump/xppcfasload.lisp	(revision 13309)
+++ /branches/new-random/xdump/xppcfasload.lisp	(revision 13309)
@@ -0,0 +1,156 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Portions copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "FASLENV" "ccl:xdump;faslenv")
+  (require "PPC-LAP"))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "XFASLOAD" "ccl:xdump;xfasload"))
+
+
+(defun xload-ppc-lap-word (instruction-form)
+  (uvref (uvref (compile nil
+                         `(lambda (&lap 0)
+                           (ppc-lap-function () ((?? 0))
+                            ,instruction-form)))
+                  0)
+         (target-arch-case
+          (:ppc32 0)
+          (:ppc64 1))))
+
+(defparameter *ppc-macro-apply-code*
+  (let* ((code '((mflr loc-pc)
+                 (bla .SPheap-rest-arg)
+                 (mtlr loc-pc)
+                 (vpop arg_z)
+                 (mr arg_y fname)
+                 (li arg_x '#.$xnotfun)
+                 (set-nargs 3)
+                 (ba .SPksignalerr))))
+    (make-array (length code)
+                :element-type '(unsigned-byte 32)
+                :initial-contents
+                (mapcar #'xload-ppc-lap-word code))))
+
+
+(defun ppc-fixup-macro-apply-code ()
+  (let* ((codev *ppc-macro-apply-code*))
+    (setf (uvref codev 5)
+          (logior (logand #xffff00000 (uvref *ppc-macro-apply-code* 5))
+                  (target-arch-case
+                   (:ppc32 (ash $xnotfun ppc32::fixnumshift))
+                   (:ppc64 (ash $xnotfun ppc64::fixnumshift)))))
+    codev))
+
+
+(defparameter *ppc-closure-trampoline-code*
+  (let* ((code '((ba .SPcall-closure))))
+    (make-array (length code)
+                :element-type '(unsigned-byte 32)
+                :initial-contents
+                (mapcar #'xload-ppc-lap-word code))))
+
+
+;;; For now, do this with a UUO so that the kernel can catch it.
+(defparameter *ppc-udf-code*
+  (let* ((code '((uuo_interr #.arch::error-udf-call 0))))
+    (make-array (length code)
+                :element-type '(unsigned-byte 32)
+                :initial-contents
+                (mapcar #'xload-ppc-lap-word code))))
+
+
+(defun ppc32-initialize-static-space ()
+  (xload-make-word-ivector ppc32::subtag-u32-vector 1027 *xload-static-space*)
+  ;; Make NIL.  Note that NIL is sort of a misaligned cons (it
+  ;; straddles two doublewords.)
+  (xload-make-cons *xload-target-nil* 0 *xload-static-space*)
+  (xload-make-cons 0 *xload-target-nil* *xload-static-space*))
+
+(defun ppc64-initialize-static-space ()
+  (xload-make-ivector *xload-static-space*
+                      (xload-target-subtype :unsigned-64-bit-vector) 
+                      (1- (/ 4096 8))))
+
+(defparameter *ppc32-xload-backend*
+  (make-backend-xload-info
+   :name #+darwinppc-target :darwinppc32 #+linuxppc-target :linuxppc32
+   :macro-apply-code-function 'ppc-fixup-macro-apply-code
+   :closure-trampoline-code *ppc-closure-trampoline-code*
+   :udf-code *ppc-udf-code*
+   :default-image-name
+   #+linuxppc-target "ccl:ccl;ppc-boot"
+   #+darwinppc-target "ccl:ccl;ppc-boot.image"
+   :default-startup-file-name
+   #+linuxppc-target "level-1.pfsl"
+   #+darwinppc-target "level-1.dfsl"
+   :subdirs '("ccl:level-0;PPC;PPC32;" "ccl:level-0;PPC;")
+   :compiler-target-name
+   #+linuxppc-target :linuxppc32
+   #+darwinppc-target :darwinppc32
+   :image-base-address
+   #+darwinppc-target #x04000000
+   #+linuxppc-target #x31000000
+   :nil-relative-symbols ppc::*ppc-nil-relative-symbols*
+   :static-space-init-function 'ppc32-initialize-static-space
+   :purespace-reserve (ash 128 20)
+   :static-space-address (ash 2 12)
+))
+
+(add-xload-backend *ppc32-xload-backend*)
+
+(defparameter *ppc64-xload-backend*
+  (make-backend-xload-info
+   :name #+darwinppc-target :darwinppc64 #+linuxppc-target :linuxppc64
+   :macro-apply-code-function 'ppc-fixup-macro-apply-code
+   :closure-trampoline-code *ppc-closure-trampoline-code*
+   :udf-code *ppc-udf-code*
+   :default-image-name
+   #+linuxppc-target "ccl:ccl;ppc-boot64"
+   #+darwinppc-target "ccl:ccl;ppc-boot64.image"
+   :default-startup-file-name
+   #+linuxppc-target "level-1.p64fsl"
+   #+darwinppc-target "level-1.d64fsl"
+   :subdirs '("ccl:level-0;PPC;PPC64;" "ccl:level-0;PPC;")
+   :compiler-target-name
+   #+linuxppc-target :linuxppc64
+   #+darwinppc-target :darwinppc64
+   :image-base-address #+linuxppc-target #x50000000000 #+darwinppc-target #x300000000000
+   :nil-relative-symbols ppc::*ppc-nil-relative-symbols*
+   :static-space-init-function 'ppc64-initialize-static-space
+   :purespace-reserve (ash 128 30)
+   :static-space-address (ash 2 12)
+   ))
+
+(add-xload-backend *ppc64-xload-backend*)
+
+#+ppc32-target
+(progn
+(setq *xload-default-backend* *ppc32-xload-backend*)
+)
+
+#+ppc64-target
+(progn
+
+  (setq *xload-default-backend* *ppc64-xload-backend*))
+
+
+
+
Index: /branches/new-random/xdump/xx8632-fasload.lisp
===================================================================
--- /branches/new-random/xdump/xx8632-fasload.lisp	(revision 13309)
+++ /branches/new-random/xdump/xx8632-fasload.lisp	(revision 13309)
@@ -0,0 +1,149 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+
+;;; Copyright 2009 Clozure Associates
+;;; This file is part of Clozure CL.  
+;;;
+;;; Clozure CL is licensed under the terms of the Lisp Lesser GNU
+;;; Public License , known as the LLGPL and distributed with Clozure
+;;; CL as the file "LICENSE".  The LLGPL consists of a preamble and
+;;; the LGPL, which is distributed with Clozure CL as the file "LGPL".
+;;; Where these conflict, the preamble takes precedence.
+;;;
+;;; Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;; The LLGPL is also available online at
+;;; http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "FASLENV" "ccl:xdump;faslenv")
+  (require "X86-LAP"))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "XFASLOAD" "ccl:xdump;xfasload"))
+
+(defparameter *x8632-macro-apply-code*
+  #xc9cd0000)	    ;uuo-error-call-macro-or-special-operator
+
+(defun x8632-fixup-macro-apply-code ()
+  *x8632-macro-apply-code*)
+
+;;; For now, do this with a UUO so that the kernel can catch it.
+(defparameter *x8632-udf-code*
+  #xc7cd0000)			;uuo-error-udf-call
+
+(defun x8632-initialize-static-space ()
+  (xload-make-ivector *xload-static-space*
+                      (xload-target-subtype :unsigned-32-bit-vector)
+                      (1- (/ 4096 4)))
+  (xload-make-cons *xload-target-nil* *xload-target-nil* *xload-static-space*))
+
+(defparameter *x8632-darwin-xload-backend*
+  (make-backend-xload-info
+   :name  :darwinx8632
+   :macro-apply-code-function 'x8632-fixup-macro-apply-code
+   :closure-trampoline-code nil
+   :udf-code *x8632-udf-code*
+   :default-image-name "ccl:ccl;x86-boot32.image"
+   :default-startup-file-name "level-1.dx32fsl"
+   :subdirs '("ccl:level-0;X86;X8632;" "ccl:level-0;X86;")
+   :compiler-target-name :darwinx8632
+   :image-base-address #x04000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8632-initialize-static-space
+   :purespace-reserve (ash 128 20)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8632-darwin-xload-backend*)
+
+(defparameter *x8632-linux-xload-backend*
+  (make-backend-xload-info
+   :name  :linuxx8632
+   :macro-apply-code-function 'x8632-fixup-macro-apply-code
+   :closure-trampoline-code nil
+   :udf-code *x8632-udf-code*
+   :default-image-name "ccl:ccl;x86-boot32"
+   :default-startup-file-name "level-1.lx32fsl"
+   :subdirs '("ccl:level-0;X86;X8632;" "ccl:level-0;X86;")
+   :compiler-target-name :linuxx8632
+   :image-base-address #x10000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8632-initialize-static-space
+   :purespace-reserve (ash 128 20)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8632-linux-xload-backend*)
+
+(defparameter *x8632-windows-xload-backend*
+  (make-backend-xload-info
+   :name  :win32
+   :macro-apply-code-function 'x8632-fixup-macro-apply-code
+   :closure-trampoline-code nil
+   :udf-code *x8632-udf-code*
+   :default-image-name "ccl:ccl;wx86-boot32.image"
+   :default-startup-file-name "level-1.wx32fsl"
+   :subdirs '("ccl:level-0;X86;X8632;" "ccl:level-0;X86;")
+   :compiler-target-name :win32
+   :image-base-address #x04000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8632-initialize-static-space
+   :purespace-reserve (ash 128 20)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8632-windows-xload-backend*)
+
+(defparameter *x8632-solaris-xload-backend*
+  (make-backend-xload-info
+   :name  :solarisx8632
+   :macro-apply-code-function 'x8632-fixup-macro-apply-code
+   :closure-trampoline-code nil
+   :udf-code *x8632-udf-code*
+   :default-image-name "ccl:ccl;sx86-boot32"
+   :default-startup-file-name "level-1.sx32fsl"
+   :subdirs '("ccl:level-0;X86;X8632;" "ccl:level-0;X86;")
+   :compiler-target-name :solarisx8632
+   :image-base-address #x10000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8632-initialize-static-space
+   :purespace-reserve (ash 128 20)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8632-solaris-xload-backend*)
+
+(defparameter *x8632-freebsd-xload-backend*
+  (make-backend-xload-info
+   :name  :freebsdx8632
+   :macro-apply-code-function 'x8632-fixup-macro-apply-code
+   :closure-trampoline-code nil
+   :udf-code *x8632-udf-code*
+   :default-image-name "ccl:ccl;fx86-boot32"
+   :default-startup-file-name "level-1.fx32fsl"
+   :subdirs '("ccl:level-0;X86;X8632;" "ccl:level-0;X86;")
+   :compiler-target-name :freebsdx8632
+   :image-base-address #x30000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8632-initialize-static-space
+   :purespace-reserve (ash 128 20)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8632-freebsd-xload-backend*)
+
+#+x8632-target
+(progn
+  #+darwin-target
+  (setq *xload-default-backend* *x8632-darwin-xload-backend*)
+  #+linux-target
+  (setq *xload-default-backend* *x8632-linux-xload-backend*)
+  #+windows-target
+  (setq *xload-default-backend* *x8632-windows-xload-backend*)
+  #+solaris-target
+  (setq *xload-default-backend* *x8632-solaris-xload-backend*)
+  #+freebsd-target
+  (setq *xload-default-backend* *x8632-freebsd-xload-backend*)
+  )
Index: /branches/new-random/xdump/xx8664-fasload.lisp
===================================================================
--- /branches/new-random/xdump/xx8664-fasload.lisp	(revision 13309)
+++ /branches/new-random/xdump/xx8664-fasload.lisp	(revision 13309)
@@ -0,0 +1,171 @@
+;;;-*- Mode: Lisp; Package: CCL -*-
+;;;
+;;;   Copyright (C) 1994-2001 Digitool, Inc
+;;;   Portions copyright (C) 2001-2009 Clozure Associates
+;;;   This file is part of Clozure CL.  
+;;;
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CCL")
+
+(eval-when (:compile-toplevel :execute)
+  (require "FASLENV" "ccl:xdump;faslenv")
+  (require "X86-LAP"))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require "XFASLOAD" "ccl:xdump;xfasload"))
+
+(defun xload-x8664-lap-code (instructions)
+  (let* ((f (%define-x86-lap-function nil instructions)))
+    (if (= (typecode f) target::subtag-xfunction)
+      (uvref f 0)
+      f)))
+
+(defparameter *x8664-macro-apply-code*
+  #xc9cd0000000000)
+
+
+(defun x8664-fixup-macro-apply-code ()
+  *x8664-macro-apply-code*)
+
+
+(defparameter *x8664-closure-trampoline-code*
+  (xload-x8664-lap-code '((jmp-subprim  .SPcall-closure))))
+
+
+
+;;; For now, do this with a UUO so that the kernel can catch it.
+(defparameter *x8664-udf-code*
+  #xc7cd0000000000)
+
+
+(defun x8664-initialize-static-space ()
+  (xload-make-ivector *xload-static-space*
+                      (xload-target-subtype :unsigned-64-bit-vector) 
+                      (1- (/ 4096 8)))
+  (xload-make-cons *xload-target-nil* 0 *xload-static-space*)
+  (xload-make-cons 0 *xload-target-nil* *xload-static-space*))
+                      
+
+(defparameter *x8664-linux-xload-backend*
+  (make-backend-xload-info
+   :name  :linuxx8664
+   :macro-apply-code-function 'x8664-fixup-macro-apply-code
+   :closure-trampoline-code *x8664-closure-trampoline-code*
+   :udf-code *x8664-udf-code*
+   :default-image-name "ccl:ccl;x86-boot64"
+   :default-startup-file-name "level-1.lx64fsl"
+   :subdirs '("ccl:level-0;X86;X8664;" "ccl:level-0;X86;")
+   :compiler-target-name :linuxx8664
+   :image-base-address #x300000000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8664-initialize-static-space
+   :purespace-reserve (ash 128 30)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+
+(add-xload-backend *x8664-linux-xload-backend*)
+
+
+(defparameter *x8664-freebsd-xload-backend*
+  (make-backend-xload-info
+   :name  :freebsdx8664
+   :macro-apply-code-function 'x8664-fixup-macro-apply-code
+   :closure-trampoline-code *x8664-closure-trampoline-code*
+   :udf-code *x8664-udf-code*
+   :default-image-name "ccl:ccl;fx86-boot64"
+   :default-startup-file-name "level-1.fx64fsl"
+   :subdirs '("ccl:level-0;X86;X8664;" "ccl:level-0;X86;")
+   :compiler-target-name :freebsdx8664
+   :image-base-address #x300000000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8664-initialize-static-space
+   :purespace-reserve (ash 128 30)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8664-freebsd-xload-backend*)
+
+(defparameter *x8664-darwin-xload-backend*
+  (make-backend-xload-info
+   :name  :darwinx8664
+   :macro-apply-code-function 'x8664-fixup-macro-apply-code
+   :closure-trampoline-code *x8664-closure-trampoline-code*
+   :udf-code *x8664-udf-code*
+   :default-image-name "ccl:ccl;x86-boot64.image"
+   :default-startup-file-name "level-1.dx64fsl"
+   :subdirs '("ccl:level-0;X86;X8664;" "ccl:level-0;X86;")
+   :compiler-target-name :darwinx8664
+   :image-base-address #x300000000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8664-initialize-static-space
+   :purespace-reserve (ash 128 30)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8664-darwin-xload-backend*)
+
+(defparameter *x8664-solaris-xload-backend*
+  (make-backend-xload-info
+   :name  :solarisx8664
+   :macro-apply-code-function 'x8664-fixup-macro-apply-code
+   :closure-trampoline-code *x8664-closure-trampoline-code*
+   :udf-code *x8664-udf-code*
+   :default-image-name "ccl:ccl;sx86-boot64"
+   :default-startup-file-name "level-1.sx64fsl"
+   :subdirs '("ccl:level-0;X86;X8664;" "ccl:level-0;X86;")
+   :compiler-target-name :solarisx8664
+   :image-base-address #x300000000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8664-initialize-static-space
+   :purespace-reserve (ash 128 30)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8664-solaris-xload-backend*)
+
+(defparameter *x8664-windows-xload-backend*
+  (make-backend-xload-info
+   :name  :win64
+   :macro-apply-code-function 'x8664-fixup-macro-apply-code
+   :closure-trampoline-code *x8664-closure-trampoline-code*
+   :udf-code *x8664-udf-code*
+   :default-image-name "ccl:ccl;wx86-boot64.image"
+   :default-startup-file-name "level-1.wx64fsl"
+   :subdirs '("ccl:level-0;X86;X8664;" "ccl:level-0;X86;")
+   :compiler-target-name :win64
+   :image-base-address #x100000000
+   :nil-relative-symbols x86::*x86-nil-relative-symbols*
+   :static-space-init-function 'x8664-initialize-static-space
+   :purespace-reserve (ash 128 30)
+   :static-space-address (+ (ash 1 16) (ash 2 12))
+))
+
+(add-xload-backend *x8664-windows-xload-backend*)
+
+#+x8664-target
+(progn
+  #+linux-target
+  (setq *xload-default-backend* *x8664-linux-xload-backend*)
+  #+freebsd-target
+  (setq *xload-default-backend* *x8664-freebsd-xload-backend*)
+  #+darwin-target
+  (setq *xload-default-backend* *x8664-darwin-xload-backend*)
+  #+solaris-target
+  (setq *xload-default-backend* *x8664-solaris-xload-backend*)
+  #+windows-target
+  (setq *xload-default-backend* *x8664-windows-xload-backend*))
+
+
+
+
